From cd26f1bd6bf3c73cc5afe848677b430ab342a909 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 11 Aug 2014 15:29:23 +0800 Subject: greybus: Initial commit diff --git a/drivers/staging/greybus/.gitignore b/drivers/staging/greybus/.gitignore new file mode 100644 index 0000000..4d40434 --- /dev/null +++ b/drivers/staging/greybus/.gitignore @@ -0,0 +1,23 @@ +# Object files +*.o +*.ko +*.obj +*.elf + +# Libraries +*.lib +*.a + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex diff --git a/drivers/staging/greybus/LICENSE b/drivers/staging/greybus/LICENSE new file mode 100644 index 0000000..d7f1051 --- /dev/null +++ b/drivers/staging/greybus/LICENSE @@ -0,0 +1,339 @@ +GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {description} + Copyright (C) {year} {fullname} + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + {signature of Ty Coon}, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/drivers/staging/greybus/README.md b/drivers/staging/greybus/README.md new file mode 100644 index 0000000..57e8490 --- /dev/null +++ b/drivers/staging/greybus/README.md @@ -0,0 +1,4 @@ +greybus +======= + +greybus kernel code -- cgit v0.10.2 From c8a797a98cb63afd620d3ae448e8ee3e45f47088 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 11 Aug 2014 15:30:45 +0800 Subject: greybus: Import most recent greybus code to new repo. diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile new file mode 100644 index 0000000..432ad4c --- /dev/null +++ b/drivers/staging/greybus/Makefile @@ -0,0 +1,22 @@ +greybus-y := core.o + +obj-m += greybus.o +obj-m += i2c-gb.o + +KERNELVER ?= $(shell uname -r) +KERNELDIR ?= /lib/modules/$(KERNELVER)/build +PWD := $(shell pwd) + +all: module + +module: + $(MAKE) -C $(KERNELDIR) M=$(PWD) + +clean: + rm -f *.o *~ core .depend .*.cmd *.ko *.mod.c + rm -f Module.markers Module.symvers modules.order + rm -rf .tmp_versions Modules.symvers + +coccicheck: + $(MAKE) -C $(KERNELDIR) M=$(PWD) coccicheck + diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c new file mode 100644 index 0000000..87148cd --- /dev/null +++ b/drivers/staging/greybus/core.c @@ -0,0 +1,153 @@ +/* + * Greybus "Core" + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include + +#include "greybus.h" + +/* Allow greybus to be disabled at boot if needed */ +static bool nogreybus; +#ifdef MODULE +module_param(nogreybus, bool, 0444); +#else +core_param(nogreybus, bool, 0444); +#endif +int greybus_disabled(void) +{ + return nogreybus; +} +EXPORT_SYMBOL_GPL(greybus_disabled); + +static int greybus_match_one_id(struct greybus_device *gdev, + const struct greybus_device_id *id) +{ + struct greybus_descriptor *des = &gdev->descriptor; + + if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_VENDOR) && + (des->wVendor != id->wVendor)) + return 0; + + if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_PRODUCT) && + (des->wProduct != id->wProduct)) + return 0; + + if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_SERIAL) && + (des->lSerialNumber != id->lSerialNumber)) + return 0; + + return 1; +} + +static const struct greybus_device_id *greybus_match_id( + struct greybus_device *gdev, + const struct greybus_device_id *id) +{ + if (id == NULL) + return NULL; + + for (; id->wVendor || id->wProduct || id->lSerialNumber || + id->driver_info ; id++) { + if (greybus_match_one_id(gdev, id)) + return id; + } + + return NULL; +} + +static int greybus_device_match(struct device *dev, struct device_driver *drv) +{ + struct greybus_driver *driver = to_greybus_driver(dev->driver); + struct greybus_device *gdev = to_greybus_device(dev); + const struct greybus_device_id *id; + + id = greybus_match_id(gdev, driver->id_table); + if (id) + return 1; + /* FIXME - Dyanmic ids? */ + return 0; +} + +static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + /* struct greybus_device *gdev = to_greybus_device(dev); */ + + /* FIXME - add some uevents here... */ + return 0; +} + +struct bus_type greybus_bus_type = { + .name = "greybus", + .match = greybus_device_match, + .uevent = greybus_uevent, +}; + +static int greybus_probe(struct device *dev) +{ + struct greybus_driver *driver = to_greybus_driver(dev->driver); + struct greybus_device *gdev = to_greybus_device(dev); + const struct greybus_device_id *id; + int retval; + + /* match id */ + id = greybus_match_id(gdev, driver->id_table); + if (!id) + return -ENODEV; + + retval = driver->probe(gdev, id); + if (retval) + return retval; + + return 0; +} + +static int greybus_remove(struct device *dev) +{ + struct greybus_driver *driver = to_greybus_driver(dev->driver); + struct greybus_device *gdev = to_greybus_device(dev); + + driver->disconnect(gdev); + return 0; +} + +int greybus_register_driver(struct greybus_driver *driver, struct module *owner, + const char *mod_name) +{ + int retval; + + if (greybus_disabled()) + return -ENODEV; + + driver->driver.name = driver->name; + driver->driver.probe = greybus_probe; + driver->driver.remove = greybus_remove; + driver->driver.owner = owner; + driver->driver.mod_name = mod_name; + + retval = driver_register(&driver->driver); + if (retval) + return retval; + + pr_info("registered new driver %s\n", driver->name); + return 0; +} +EXPORT_SYMBOL_GPL(greybus_register_driver); + +void greybus_deregister(struct greybus_driver *driver) +{ + driver_unregister(&driver->driver); +} +EXPORT_SYMBOL_GPL(greybus_deregister); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Greg Kroah-Hartman "); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h new file mode 100644 index 0000000..8158e45 --- /dev/null +++ b/drivers/staging/greybus/greybus.h @@ -0,0 +1,97 @@ +/* + * Greybus driver and device API + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ + +#ifndef __LINUX_GREYBUS_H +#define __LINUX_GREYBUS_H + +#ifdef __KERNEL__ + +#include +#include +#include +#include "greybus_id.h" + + +#define GREYBUS_DEVICE_ID_MATCH_DEVICE \ + (GREYBUS_DEVICE_ID_MATCH_VENDOR | GREYBUS_DEVICE_ID_MATCH_PRODUCT) + +#define GREYBUS_DEVICE(vendor, product) \ + .match_flags = GREYBUS_DEVICE_ID_MATCH_DEVICE, \ + .wVendor = (vendor), \ + .wProduct = (product), + +#define GREYBUS_DEVICE_SERIAL(serial) \ + .match_flags = GREYBUS_DEVICE_ID_MATCH_SERIAL, \ + .lSerial = (serial), + + +struct greybus_descriptor { + __u16 wVendor; + __u16 wProduct; + __u64 lSerialNumber; +}; + +struct greybus_device { + struct device dev; + struct greybus_descriptor descriptor; +}; +#define to_greybus_device(d) container_of(d, struct greybus_device, dev) + +struct greybus_driver { + const char *name; + + int (*probe) (struct greybus_device *gdev, + const struct greybus_device_id *id); + void (*disconnect) (struct greybus_device *gdev); + + int (*suspend) (struct greybus_device *gdev, pm_message_t message); + int (*resume) (struct greybus_device *gdev); + + const struct greybus_device_id *id_table; + + struct device_driver driver; +}; +#define to_greybus_driver(d) container_of(d, struct greybus_driver, driver) + +static inline void greybus_set_drvdata(struct greybus_device *gdev, void *data) +{ + dev_set_drvdata(&gdev->dev, data); +} + +static inline void *greybus_get_drvdata(struct greybus_device *gdev) +{ + return dev_get_drvdata(&gdev->dev); +} + +/* Don't call these directly, use the module_greybus_driver() macro instead */ +int greybus_register_driver(struct greybus_driver *driver, + struct module *module, const char *mod_name); +void greybus_deregister(struct greybus_driver *driver); + +/* define to get proper THIS_MODULE and KBUILD_MODNAME values */ +#define greybus_register(driver) \ + greybus_register_driver(driver, THIS_MODULE, KBUILD_MODNAME) + +/** + * module_greybus_driver() - Helper macro for registering a Greybus driver + * @__greybus_driver: greybus_driver structure + * + * Helper macro for Greybus drivers to set up proper module init / exit + * functions. Replaces module_init() and module_exit() and keeps people from + * printing pointless things to the kernel log when their driver is loaded. + */ +#define module_greybus_driver(__greybus_driver) \ + module_driver(__greybus_driver, greybus_register, greybus_deregister) + +extern struct bus_type greybus_bus_type; + +int greybus_disabled(void); + + +#endif /* __KERNEL__ */ +#endif /* __LINUX_GREYBUS_H */ diff --git a/drivers/staging/greybus/greybus_id.h b/drivers/staging/greybus/greybus_id.h new file mode 100644 index 0000000..4afbfe2 --- /dev/null +++ b/drivers/staging/greybus/greybus_id.h @@ -0,0 +1,27 @@ +/* FIXME + * move this to include/linux/mod_devicetable.h when merging + */ + +#ifndef __LINUX_GREYBUS_ID_H +#define __LINUX_GREYBUS_ID_H + +#include +#include + + +struct greybus_device_id { + __u16 match_flags; + __u16 wVendor; + __u16 wProduct; + __u64 lSerialNumber; + + kernel_ulong_t driver_info + __attribute__((aligned(sizeof(kernel_ulong_t)))); +}; + +/* Used to match the greybus_device_id */ +#define GREYBUS_DEVICE_ID_MATCH_VENDOR BIT(0) +#define GREYBUS_DEVICE_ID_MATCH_PRODUCT BIT(1) +#define GREYBUS_DEVICE_ID_MATCH_SERIAL BIT(2) + +#endif /* __LINUX_GREYBUS_H */ diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c new file mode 100644 index 0000000..a481e06 --- /dev/null +++ b/drivers/staging/greybus/i2c-gb.c @@ -0,0 +1,122 @@ +/* + * I2C bridge driver for the Greybus "generic" I2C module. + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include "greybus.h" + +struct i2c_gb_data { + struct i2c_adapter *adapter; + struct greybus_device *gdev; +}; + +static const struct greybus_device_id id_table[] = { + { GREYBUS_DEVICE(0x42, 0x42) }, /* make shit up */ + { }, /* terminating NULL entry */ +}; + +/* We BETTER be able to do SMBUS protocl calls, otherwise we are bit-banging the + * slowest thing possible over the fastest bus possible, crazy... + * FIXME - research this, for now just assume we can + */ + + +static s32 i2c_gb_access(struct i2c_adapter *adap, u16 addr, + unsigned short flags, char read_write, u8 command, + int size, union i2c_smbus_data *data) +{ + struct i2c_gb_data *i2c_gb_data; + struct greybus_device *gdev; + + i2c_gb_data = i2c_get_adapdata(adap); + gdev = i2c_gb_data->gdev; + + // FIXME - do the actual work of sending a i2c message here... + switch (size) { + case I2C_SMBUS_QUICK: + case I2C_SMBUS_BYTE: + case I2C_SMBUS_BYTE_DATA: + case I2C_SMBUS_WORD_DATA: + case I2C_SMBUS_PROC_CALL: + case I2C_SMBUS_BLOCK_DATA: + case I2C_SMBUS_I2C_BLOCK_BROKEN: + case I2C_SMBUS_BLOCK_PROC_CALL: + case I2C_SMBUS_I2C_BLOCK_DATA: + default: + dev_err(&gdev->dev, "Unsupported transaction %d\n", size); + return -EOPNOTSUPP; + } + + return 0; +} + +static u32 i2c_gb_func(struct i2c_adapter *adapter) +{ + // FIXME - someone figure out what we really can support, for now just guess... + return 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 | + I2C_FUNC_SMBUS_PEC | + I2C_FUNC_SMBUS_READ_I2C_BLOCK; +} + +static const struct i2c_algorithm smbus_algorithm = { + .smbus_xfer = i2c_gb_access, + .functionality = i2c_gb_func, +}; + +static int i2c_gb_probe(struct greybus_device *gdev, const struct greybus_device_id *id) +{ + struct i2c_gb_data *i2c_gb_data; + struct i2c_adapter *adapter; + + i2c_gb_data = kzalloc(sizeof(*i2c_gb_data), GFP_KERNEL); + if (!i2c_gb_data) + return -ENOMEM; + adapter = kzalloc(sizeof(*adapter), GFP_KERNEL); + if (!adapter) { + kfree(i2c_gb_data); + return -ENOMEM; + } + + i2c_set_adapdata(adapter, i2c_gb_data); + adapter->owner = THIS_MODULE; + adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; + adapter->algo = &smbus_algorithm; + + i2c_gb_data->gdev = gdev; + i2c_gb_data->adapter = adapter; + + greybus_set_drvdata(gdev, i2c_gb_data); + return 0; +} + +static void i2c_gb_disconnect(struct greybus_device *gdev) +{ + struct i2c_gb_data *i2c_gb_data; + + i2c_gb_data = greybus_get_drvdata(gdev); + i2c_del_adapter(i2c_gb_data->adapter); + kfree(i2c_gb_data->adapter); + kfree(i2c_gb_data); +} + +static struct greybus_driver i2c_gb_driver = { + .probe = i2c_gb_probe, + .disconnect = i2c_gb_disconnect, + .id_table = id_table, +}; + +module_greybus_driver(i2c_gb_driver); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Greg Kroah-Hartman "); -- cgit v0.10.2 From 06823c3eb9c4069f899b0c71d35fd17af945627c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 11 Aug 2014 15:32:12 +0800 Subject: greybus: README and .gitignore updates diff --git a/drivers/staging/greybus/.gitignore b/drivers/staging/greybus/.gitignore index 4d40434..a07ab9d 100644 --- a/drivers/staging/greybus/.gitignore +++ b/drivers/staging/greybus/.gitignore @@ -1,23 +1,9 @@ -# Object files -*.o +*.cmd *.ko -*.obj -*.elf - -# Libraries -*.lib -*.a - -# Shared objects (inc. Windows DLLs) -*.dll -*.so -*.so.* -*.dylib - -# Executables -*.exe -*.out -*.app -*.i*86 -*.x86_64 -*.hex +*.mod.c +modules.order +Module.symvers +*.o +*.swp +.tmp_versions +tags diff --git a/drivers/staging/greybus/README b/drivers/staging/greybus/README new file mode 100644 index 0000000..50953b1 --- /dev/null +++ b/drivers/staging/greybus/README @@ -0,0 +1 @@ +Greybus kernel code diff --git a/drivers/staging/greybus/README.md b/drivers/staging/greybus/README.md deleted file mode 100644 index 57e8490..0000000 --- a/drivers/staging/greybus/README.md +++ /dev/null @@ -1,4 +0,0 @@ -greybus -======= - -greybus kernel code -- cgit v0.10.2 From 4c009fada183bbca4dfa40e187268d3ee1040119 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 11 Aug 2014 15:44:51 +0800 Subject: greybus: update README with info on how to build and contact me. diff --git a/drivers/staging/greybus/README b/drivers/staging/greybus/README index 50953b1..b0745d3 100644 --- a/drivers/staging/greybus/README +++ b/drivers/staging/greybus/README @@ -1 +1,10 @@ Greybus kernel code + +To build against the running kernel (odds are you don't want this): + make + +To build against a specific kernel source tree (odds are you want this): + KERNELDIR=/home/some/random/place make + +Any questions / concerns about this code base, please email: + Greg Kroah-Hartman -- cgit v0.10.2 From 53419e07cc94c89307c7b1e698e84f7f9340f37d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 11 Aug 2014 17:01:15 +0800 Subject: greybus: i2c-gb: actually add the i2c adapter properly... diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index a481e06..7fcbcef 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -79,6 +79,7 @@ static int i2c_gb_probe(struct greybus_device *gdev, const struct greybus_device { struct i2c_gb_data *i2c_gb_data; struct i2c_adapter *adapter; + int retval; i2c_gb_data = kzalloc(sizeof(*i2c_gb_data), GFP_KERNEL); if (!i2c_gb_data) @@ -93,12 +94,24 @@ static int i2c_gb_probe(struct greybus_device *gdev, const struct greybus_device adapter->owner = THIS_MODULE; adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; adapter->algo = &smbus_algorithm; + adapter->dev.parent = &gdev->dev; + adapter->retries = 3; /* we have to pick something... */ + snprintf(adapter->name, sizeof(adapter->name), "Greybus i2c adapter"); + retval = i2c_add_adapter(adapter); + if (retval) { + dev_err(&gdev->dev, "Can not add SMBus adapter\n"); + goto error; + } i2c_gb_data->gdev = gdev; i2c_gb_data->adapter = adapter; greybus_set_drvdata(gdev, i2c_gb_data); return 0; +error: + kfree(adapter); + kfree(i2c_gb_data); + return retval; } static void i2c_gb_disconnect(struct greybus_device *gdev) -- cgit v0.10.2 From 776f136c75f2c2346a8fca698ef81d15245f5a00 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 11 Aug 2014 17:27:07 +0800 Subject: greybus: greybus.h: tiny coding style cleanups diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 8158e45..28b3148 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -45,12 +45,12 @@ struct greybus_device { struct greybus_driver { const char *name; - int (*probe) (struct greybus_device *gdev, - const struct greybus_device_id *id); - void (*disconnect) (struct greybus_device *gdev); + int (*probe)(struct greybus_device *gdev, + const struct greybus_device_id *id); + void (*disconnect)(struct greybus_device *gdev); - int (*suspend) (struct greybus_device *gdev, pm_message_t message); - int (*resume) (struct greybus_device *gdev); + int (*suspend)(struct greybus_device *gdev, pm_message_t message); + int (*resume)(struct greybus_device *gdev); const struct greybus_device_id *id_table; @@ -60,12 +60,12 @@ struct greybus_driver { static inline void greybus_set_drvdata(struct greybus_device *gdev, void *data) { - dev_set_drvdata(&gdev->dev, data); + dev_set_drvdata(&gdev->dev, data); } static inline void *greybus_get_drvdata(struct greybus_device *gdev) { - return dev_get_drvdata(&gdev->dev); + return dev_get_drvdata(&gdev->dev); } /* Don't call these directly, use the module_greybus_driver() macro instead */ -- cgit v0.10.2 From 83ddaaab01c2ababbcaa507a3ecaa80499cf000f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 11 Aug 2014 17:27:22 +0800 Subject: greybus: Greybus SD/MMC host driver Need to add specifics, but this should be enough to hook up to the mmc framework. diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 432ad4c..753436d 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -2,6 +2,7 @@ greybus-y := core.o obj-m += greybus.o obj-m += i2c-gb.o +obj-m += sdio-gb.o KERNELVER ?= $(shell uname -r) KERNELDIR ?= /lib/modules/$(KERNELVER)/build diff --git a/drivers/staging/greybus/sdio-gb.c b/drivers/staging/greybus/sdio-gb.c new file mode 100644 index 0000000..f92ab1b --- /dev/null +++ b/drivers/staging/greybus/sdio-gb.c @@ -0,0 +1,88 @@ +/* + * SD/MMC Greybus driver. + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include "greybus.h" + +struct sd_gb_host { + struct mmc_host *mmc; + struct mmc_request *mrq; + // FIXME - some lock? +}; + +static const struct greybus_device_id id_table[] = { + { GREYBUS_DEVICE(0x43, 0x43) }, /* make shit up */ + { }, /* terminating NULL entry */ +}; + +static void gb_sd_request(struct mmc_host *mmc, struct mmc_request *mrq) +{ + // FIXME - do something here... +} + +static void gb_sd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) +{ + // FIXME - do something here... +} + +static int gb_sd_get_ro(struct mmc_host *mmc) +{ + // FIXME - do something here... + return 0; +} + +static const struct mmc_host_ops gb_sd_ops = { + .request = gb_sd_request, + .set_ios = gb_sd_set_ios, + .get_ro = gb_sd_get_ro, +}; + +static int sd_gb_probe(struct greybus_device *gdev, const struct greybus_device_id *id) +{ + struct mmc_host *mmc; + struct sd_gb_host *host; + + mmc = mmc_alloc_host(sizeof(struct sd_gb_host), &gdev->dev); + if (!mmc) + return -ENOMEM; + + host = mmc_priv(mmc); + host->mmc = mmc; + + mmc->ops = &gb_sd_ops; + // FIXME - set up size limits we can handle. + + greybus_set_drvdata(gdev, host); + return 0; +} + +static void sd_gb_disconnect(struct greybus_device *gdev) +{ + struct mmc_host *mmc; + struct sd_gb_host *host; + + host = greybus_get_drvdata(gdev); + mmc = host->mmc; + + mmc_remove_host(mmc); + mmc_free_host(mmc); +} + +static struct greybus_driver sd_gb_driver = { + .probe = sd_gb_probe, + .disconnect = sd_gb_disconnect, + .id_table = id_table, +}; + +module_greybus_driver(sd_gb_driver); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Greybus SD/MMC Host driver"); +MODULE_AUTHOR("Greg Kroah-Hartman "); -- cgit v0.10.2 From d5d1903dcd158e220275a64f9f4df6cd06addb82 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 11 Aug 2014 19:03:20 +0800 Subject: greybus: add framework for 'struct gbuf' This is the equlivant of sk_buf or urbs for Greybus. diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 753436d..cc9c3a7 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -1,4 +1,4 @@ -greybus-y := core.o +greybus-y := core.o gbuf.o obj-m += greybus.o obj-m += i2c-gb.o diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c new file mode 100644 index 0000000..de31da8 --- /dev/null +++ b/drivers/staging/greybus/gbuf.c @@ -0,0 +1,42 @@ +/* + * Greybus gbuf handling + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include + +#include "greybus.h" + + +struct gbuf *greybus_alloc_gbuf(struct greybus_device *gdev, + struct cport *cport, + gfp_t mem_flags) +{ + return NULL; +} + +void greybus_free_gbuf(struct gbuf *gbuf) +{ +} + +int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t mem_flags) +{ + return -ENOMEM; +} + +int greybus_kill_gbuf(struct gbuf *gbuf) +{ + return -ENOMEM; +} + + + diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 28b3148..51b9f5b 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -29,19 +29,68 @@ .match_flags = GREYBUS_DEVICE_ID_MATCH_SERIAL, \ .lSerial = (serial), - struct greybus_descriptor { __u16 wVendor; __u16 wProduct; __u64 lSerialNumber; }; + +struct gbuf; + +struct cport { + u16 number; + // FIXME, what else? +}; + +typedef void (*gbuf_complete_t)(struct gbuf *gbuf); + +struct gbuf { + struct kref kref; + void *hcpriv; + + struct list_head anchor_list; + struct gbuf_anchor *anchor; // FIXME do we need? + + struct greybus_device *gdev; + struct cport *cport; + int status; + void *transfer_buffer; + u32 transfer_flags; /* flags for the transfer buffer */ + u32 transfer_buffer_length; + u32 actual_length; + + struct scatterlist *sg; // FIXME do we need? + int num_sgs; + + void *context; + gbuf_complete_t complete; +}; + +/* + * gbuf->transfer_flags + */ +#define GBUF_FREE_BUFFER BIT(0) /* Free the transfer buffer with the gbuf */ + + struct greybus_device { struct device dev; struct greybus_descriptor descriptor; + int num_cport; + struct cport cport[0]; }; #define to_greybus_device(d) container_of(d, struct greybus_device, dev) + +struct gbuf *greybus_alloc_gbuf(struct greybus_device *gdev, + struct cport *cport, + gfp_t mem_flags); +void greybus_free_gbuf(struct gbuf *gbuf); + +int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t mem_flags); +int greybus_kill_gbuf(struct gbuf *gbuf); + + struct greybus_driver { const char *name; -- cgit v0.10.2 From c16854c3bf562a1f7d1dea92309f35fe97e26889 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 12 Aug 2014 12:00:16 +0800 Subject: greybus: gpio driver diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index cc9c3a7..12705b0 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -3,6 +3,7 @@ greybus-y := core.o gbuf.o obj-m += greybus.o obj-m += i2c-gb.o obj-m += sdio-gb.o +obj-m += gpio-gb.o KERNELVER ?= $(shell uname -r) KERNELDIR ?= /lib/modules/$(KERNELVER)/build diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c new file mode 100644 index 0000000..98b599b --- /dev/null +++ b/drivers/staging/greybus/gpio-gb.c @@ -0,0 +1,108 @@ +/* + * GPIO Greybus driver. + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include "greybus.h" + +struct gb_gpio { + struct gpio_chip chip; + struct greybus_device *gdev; + // FIXME - some lock? +}; + +static const struct greybus_device_id id_table[] = { + { GREYBUS_DEVICE(0x44, 0x44) }, /* make shit up */ + { }, /* terminating NULL entry */ +}; + +static int direction_input(struct gpio_chip *gpio, unsigned nr) +{ + struct gp_gpio *gp_gpio = container_of(gpio, struct gp_gpio, chip); + + // FIXME - do something there + return 0; +} + +static int direction_output(struct gpio_chip *gpio, unsigned nr, int val) +{ + // FIXME - do something there + return 0; +} + +static int gpio_get(struct gpio_chip *gpio, unsigned nr) +{ + // FIXME - do something there + return 0; +} + +static int gpio_set(struct gpio_chip *gpio, unsigned nr, int val) +{ + // FIXME - do something there + return 0; +} + +static int gpio_gb_probe(struct greybus_device *gdev, const struct greybus_device_id *id) +{ + struct gp_gpio *gp_gpio; + struct gpio_chip *gpio; + struct device *dev = &gdev->dev; + + gp_gpio = devm_kzalloc(dev, sizeof(*gp_gpio), GFP_KERNEL); + if (!gp_gpio) + return -ENOMEM; + gp_gpio->gdev = gdev; + + gpio = &gp_gpio->gpio; + + gpio->label = "greybus_gpio"; + gpio->owner = THIS_MODULE; + gpio->direction_input = direction_input; + gpio->direction_output = direction_output; + gpio->get = gpio_get; + gpio->set = gpio_set; + gpio->dbg_show = NULL; + gpio->base = 0; // FIXME!!! + gpio->ngpio = 42; // FIXME!!! + gpio->can_sleep = false; // FIXME!!! + + greybus_set_drvdata(gdev, gp_gpio); + + retval = gpio_chip_add(gpio); + if (retval) { + dev_err(dev, "Failed to register GPIO\n"); + return retval; + } + + return 0; +} + +static void gpio_gb_disconnect(struct greybus_device *gdev) +{ + struct mmc_host *mmc; + struct sd_gb_host *host; + + host = greybus_get_drvdata(gdev); + mmc = host->mmc; + + mmc_remove_host(mmc); + mmc_free_host(mmc); +} + +static struct greybus_driver gpio_gb_driver = { + .probe = gpio_gb_probe, + .disconnect = gpio_gb_disconnect, + .id_table = id_table, +}; + +module_greybus_driver(gpio_gb_driver); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Greybus GPIO driver"); +MODULE_AUTHOR("Greg Kroah-Hartman "); -- cgit v0.10.2 From e9023d227ab854c9ea3019c226b2c15cb3f3c2ea Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 12 Aug 2014 14:41:49 +0800 Subject: greybus: gpio-gb.c: it now builds properly diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index 98b599b..0cbabb5 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -10,11 +10,13 @@ #include #include #include +#include #include "greybus.h" struct gb_gpio { struct gpio_chip chip; struct greybus_device *gdev; + struct gpio_chip *gpio; // FIXME - some lock? }; @@ -25,7 +27,7 @@ static const struct greybus_device_id id_table[] = { static int direction_input(struct gpio_chip *gpio, unsigned nr) { - struct gp_gpio *gp_gpio = container_of(gpio, struct gp_gpio, chip); +// struct gb_gpio *gb_gpio = container_of(gpio, struct gb_gpio, chip); // FIXME - do something there return 0; @@ -43,24 +45,25 @@ static int gpio_get(struct gpio_chip *gpio, unsigned nr) return 0; } -static int gpio_set(struct gpio_chip *gpio, unsigned nr, int val) +static void gpio_set(struct gpio_chip *gpio, unsigned nr, int val) { // FIXME - do something there - return 0; + return; } static int gpio_gb_probe(struct greybus_device *gdev, const struct greybus_device_id *id) { - struct gp_gpio *gp_gpio; + struct gb_gpio *gb_gpio; struct gpio_chip *gpio; struct device *dev = &gdev->dev; + int retval; - gp_gpio = devm_kzalloc(dev, sizeof(*gp_gpio), GFP_KERNEL); - if (!gp_gpio) + gb_gpio = devm_kzalloc(dev, sizeof(*gb_gpio), GFP_KERNEL); + if (!gb_gpio) return -ENOMEM; - gp_gpio->gdev = gdev; + gb_gpio->gdev = gdev; - gpio = &gp_gpio->gpio; + gpio = &gb_gpio->chip; gpio->label = "greybus_gpio"; gpio->owner = THIS_MODULE; @@ -73,9 +76,9 @@ static int gpio_gb_probe(struct greybus_device *gdev, const struct greybus_devic gpio->ngpio = 42; // FIXME!!! gpio->can_sleep = false; // FIXME!!! - greybus_set_drvdata(gdev, gp_gpio); + greybus_set_drvdata(gdev, gb_gpio); - retval = gpio_chip_add(gpio); + retval = gpiochip_add(gpio); if (retval) { dev_err(dev, "Failed to register GPIO\n"); return retval; @@ -86,14 +89,11 @@ static int gpio_gb_probe(struct greybus_device *gdev, const struct greybus_devic static void gpio_gb_disconnect(struct greybus_device *gdev) { - struct mmc_host *mmc; - struct sd_gb_host *host; + struct gb_gpio *gb_gpio; - host = greybus_get_drvdata(gdev); - mmc = host->mmc; + gb_gpio = greybus_get_drvdata(gdev); - mmc_remove_host(mmc); - mmc_free_host(mmc); + gpiochip_remove(&gb_gpio->chip); } static struct greybus_driver gpio_gb_driver = { -- cgit v0.10.2 From 79c822be7b85c8bfc682c011d06a02fe960773ad Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 15 Aug 2014 16:01:23 +0800 Subject: greybus: uart framework added, doesn't build diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 12705b0..b84ff76 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -4,6 +4,7 @@ obj-m += greybus.o obj-m += i2c-gb.o obj-m += sdio-gb.o obj-m += gpio-gb.o +obj-m += uart-gb.o KERNELVER ?= $(shell uname -r) KERNELDIR ?= /lib/modules/$(KERNELVER)/build diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c new file mode 100644 index 0000000..9527307 --- /dev/null +++ b/drivers/staging/greybus/uart-gb.c @@ -0,0 +1,118 @@ +/* + * I2C bridge driver for the Greybus "generic" I2C module. + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "greybus.h" + +#define GB_TTY_MAJOR 180 /* FIXME use a real number!!! */ + +struct gb_tty { + struct tty_port port; + struct greybus_device *gdev; + int cport; + unsigned int minor; + unsigned char clocal; + // FIXME locking!!! +}; + +static const struct greybus_device_id id_table[] = { + { GREYBUS_DEVICE(0x45, 0x45) }, /* make shit up */ + { }, /* terminating NULL entry */ +}; + + +static const struct tty_operations gb_ops = { + .install = gb_tty_install, + .open = gb_tty_open, + .close = gb_tty_close, + .cleanup = gb_tty_cleanup, + .hangup = gb_tty_hangup, + .write = gb_tty_write, + .write_room = gb_tty_write_room, + .ioctl = gb_tty_ioctl, + .throttle = gb_tty_throttle, + .unthrottle = gb_tty_unthrottle, + .chars_in_buffer = gb_tty_chars_in_buffer, + .break_ctl = gb_tty_break_ctl, + .set_termios = gb_tty_set_termios, + .tiocmget = gb_tty_tiocmget, + .tiocmset = gb_tty_tiocmset, +}; + +static struct tty_driver *gb_tty_driver; +static struct gb_tty *gb_tty_table[255]; + +static int tty_gb_probe(struct greybus_device *gdev, const struct greybus_device_id *id) +{ + int retval; + + //greybus_set_drvdata(gdev, i2c_gb_data); + return 0; +} + +static void tty_gb_disconnect(struct greybus_device *gdev) +{ +} + +static struct greybus_driver tty_gb_driver = { + .probe = tty_gb_probe, + .disconnect = tty_gb_disconnect, + .id_table = id_table, +}; + + +static int __init gb_tty_init(void) +{ + int retval; + + gb_tty_driver = alloc_tty_driver(255); + if (!gb_tty_driver) + return -ENOMEM; + + gb_tty_driver->driver_name = "gb"; + gb_tty_driver->name = "ttyGB"; + gb_tty_driver->major = GB_TTY_MAJOR; + gb_tty_driver->minor_start = 0; + gb_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; + gb_tty_driver->subtype = SERIAL_TYPE_NORMAL; + gb_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; + gb_tty_driver->init_termios = tty_std_termios; + gb_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + tty_set_operations(gb_tty_driver, &gb_ops); + + retval = tty_register_driver(gb_tty_driver); + if (retval) { + put_tty_driver(gb_tty_driver); + return retval; + } + + retval = greybus_register(&tty_gb_driver); + if (retval) { + tty_unregister_driver(gb_tty_driver); + put_tty_driver(gb_tty_driver); + } + return retval; +} + +static void __exit gb_tty_exit(void) +{ + greybus_deregister(&tty_gb_driver); + tty_unregister_driver(gb_tty_driver); + put_tty_driver(gb_tty_driver); +} + +module_init(gb_tty_init); +module_exit(gb_tty_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Greg Kroah-Hartman "); -- cgit v0.10.2 From ff45c265f849ce42e8d1eb48e49e8176019ec5af Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 15 Aug 2014 18:33:33 +0800 Subject: greybus: uart-gb: more work on tty functions diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 9527307..3eaada9 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "greybus.h" #define GB_TTY_MAJOR 180 /* FIXME use a real number!!! */ @@ -31,6 +32,89 @@ static const struct greybus_device_id id_table[] = { { }, /* terminating NULL entry */ }; +static struct tty_driver *gb_tty_driver; +static DEFINE_IDR(tty_minors); +static DEFINE_MUTEX(table_lock); + +static struct gb_tty *get_gb_by_minor(unsigned minor) +{ + struct gb_tty *gb_tty; + + mutex_lock(&table_lock); + gb_tty = idr_find(&tty_minors, minor); + mutex_unlock(&table_lock); + return gb_tty; +} + +static int alloc_minor(struct gb_tty *gb_tty) +{ + int minor; + + mutex_lock(&table_lock); + minor = idr_alloc(&tty_minors, gb_tty, 0, 0, GFP_KERNEL); + if (minor < 0) + goto error; + gb_tty->minor = minor; +error: + mutex_unlock(&table_lock); + return minor; +} + +static void release_minor(struct gb_tty *gb_tty) +{ + mutex_lock(&table_lock); + idr_remove(&tty_minors, gb_tty->minor); + mutex_unlock(&table_lock); +} + +static int gb_tty_install(struct tty_driver *driver, struct tty_struct *tty) +{ + struct gb_tty *gb_tty; + int retval; + + gb_tty = get_gb_by_minor(tty->index); + if (!gb_tty) + return -ENODEV; + + retval = tty_standard_install(driver, tty); + if (retval) + goto error; + + tty->driver_data = gb_tty; + return 0; +error: + tty_port_put(&gb_tty->port); + return retval; +} + +static int gb_tty_open(struct tty_struct *tty, struct file *file) +{ + struct gb_tty *gb_tty = tty->driver_data; + + return tty_port_open(&gb_tty->port, tty, file); +} + +static void gb_tty_close(struct tty_struct *tty, struct file *file) +{ + struct gb_tty *gb_tty = tty->driver_data; + + tty_port_close(&gb_tty->port, tty, file); +} + +static void gb_tty_cleanup(struct tty_struct *tty) +{ + struct gb_tty *gb_tty = tty->driver_data; + + tty_port_put(&gb_tty->port); +} + +static void gb_tty_hangup(struct tty_struct *tty) +{ + struct gb_tty *gb_tty = tty->driver_data; + + tty_port_hangup(&gb_tty->port); +} + static const struct tty_operations gb_ops = { .install = gb_tty_install, @@ -50,8 +134,6 @@ static const struct tty_operations gb_ops = { .tiocmset = gb_tty_tiocmset, }; -static struct tty_driver *gb_tty_driver; -static struct gb_tty *gb_tty_table[255]; static int tty_gb_probe(struct greybus_device *gdev, const struct greybus_device_id *id) { -- cgit v0.10.2 From a18e15175708d39abbe9746ddc3479466b7800c3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 15 Aug 2014 18:54:11 +0800 Subject: greybus: more uart work diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 3eaada9..792536c 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -16,7 +16,8 @@ #include #include "greybus.h" -#define GB_TTY_MAJOR 180 /* FIXME use a real number!!! */ +#define GB_TTY_MAJOR 180 /* FIXME use a real number!!! */ +#define GB_NUM_MINORS 255 /* 255 is enough for anyone... */ struct gb_tty { struct tty_port port; @@ -24,6 +25,10 @@ struct gb_tty { int cport; unsigned int minor; unsigned char clocal; + unsigned int throttled:1; + unsigned int throttle_req:1; + spinlock_t read_lock; + spinlock_t write_lock; // FIXME locking!!! }; @@ -115,6 +120,57 @@ static void gb_tty_hangup(struct tty_struct *tty) tty_port_hangup(&gb_tty->port); } +static int gb_tty_write(struct tty_struct *tty, const unsigned char *buf, + int count) +{ + struct gb_tty *gb_tty = tty->driver_data; + + // FIXME - actually implement... + + return 0; +} + +static int gb_tty_write_room(struct tty_struct *tty) +{ + struct gb_tty *gb_tty = tty->driver_data; + + // FIXME - how much do we want to say we have room for? + return 0; +} + +static int gb_tty_chars_in_buffer(struct tty_struct *tty) +{ + struct gb_tty *gb_tty = tty->driver_data; + + // FIXME - how many left to send? + return 0; +} + +static void gb_tty_throttle(struct tty_struct *tty) +{ + struct gb_tty *gb_tty = tty->driver_data; + + spin_lock_irq(&gb_tty->read_lock); + gb_tty->throttle_req = 1; + spin_unlock_irq(&gb_tty->read_lock); +} + +static void gb_tty_unthrottle(struct tty_struct *tty) +{ + struct gb_tty *gb_tty = tty->driver_data; + unsigned int was_throttled; + + spin_lock_irq(&gb_tty->read_lock); + was_throttled = gb_tty->throttled; + gb_tty->throttle_req = 0; + gb_tty->throttled = 0; + spin_unlock_irq(&gb_tty->read_lock); + + if (was_throttled) { + // FIXME - send more data + } +} + static const struct tty_operations gb_ops = { .install = gb_tty_install, @@ -137,14 +193,58 @@ static const struct tty_operations gb_ops = { static int tty_gb_probe(struct greybus_device *gdev, const struct greybus_device_id *id) { + struct gb_tty *gb_tty; + struct device *tty_dev; int retval; + int minor; + + gb_tty = devm_kzalloc(&gdev->dev, sizeof(*gb_tty), GFP_KERNEL); + if (!gb_tty) + return -ENOMEM; + + minor = alloc_minor(gb_tty); + if (minor == GB_NUM_MINORS) { + dev_err(&gdev->dev, "no more free minor numbers\n"); + return -ENODEV; + } + + gb_tty->minor = minor; + gb_tty->gdev = gdev; + spin_lock_init(&gb_tty->write_lock); + spin_lock_init(&gb_tty->read_lock); + + /* FIXME - allocate gb buffers */ + + greybus_set_drvdata(gdev, gb_tty); + + tty_dev = tty_port_register_device(&gb_tty->port, gb_tty_driver, minor, + &gdev->dev); + if (IS_ERR(tty_dev)) { + retval = PTR_ERR(tty_dev); + goto error; + } - //greybus_set_drvdata(gdev, i2c_gb_data); return 0; +error: + release_minor(gb_tty); + return retval; } static void tty_gb_disconnect(struct greybus_device *gdev) { + struct gb_tty *gb_tty = greybus_get_drvdata(gdev); + struct tty_struct *tty; + + tty = tty_port_tty_get(&gb_tty->port); + if (tty) { + tty_vhangup(tty); + tty_kref_put(tty); + } + /* FIXME - stop all traffic */ + + tty_unregister_device(gb_tty_driver, gb_tty->minor); + + tty_port_put(&gb_tty->port); } static struct greybus_driver tty_gb_driver = { @@ -158,7 +258,7 @@ static int __init gb_tty_init(void) { int retval; - gb_tty_driver = alloc_tty_driver(255); + gb_tty_driver = alloc_tty_driver(GB_NUM_MINORS); if (!gb_tty_driver) return -ENOMEM; -- cgit v0.10.2 From e68453ed28c550c448709473ab89cebafa0ee34e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 15 Aug 2014 19:44:32 +0800 Subject: greybus: uart-gb: now builds, more framework added diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 792536c..13a23cd 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -1,18 +1,27 @@ /* - * I2C bridge driver for the Greybus "generic" I2C module. + * UART driver for the Greybus "generic" UART module. * * Copyright 2014 Google Inc. * * Released under the GPLv2 only. + * + * Heavily based on drivers/usb/class/cdc-acm.c and + * drivers/usb/serial/usb-serial.c. */ #include +#include #include +#include +#include #include +#include +#include #include #include #include #include +#include #include #include "greybus.h" @@ -27,9 +36,14 @@ struct gb_tty { unsigned char clocal; unsigned int throttled:1; unsigned int throttle_req:1; + bool disconnected; + int writesize; // FIXME - set this somehow. spinlock_t read_lock; spinlock_t write_lock; - // FIXME locking!!! + struct async_icount iocount; + struct async_icount oldcount; + wait_queue_head_t wioctl; + struct mutex mutex; }; static const struct greybus_device_id id_table[] = { @@ -47,6 +61,16 @@ static struct gb_tty *get_gb_by_minor(unsigned minor) mutex_lock(&table_lock); gb_tty = idr_find(&tty_minors, minor); + if (gb_tty) { + mutex_lock(&gb_tty->mutex); + if (gb_tty->disconnected) { + mutex_unlock(&gb_tty->mutex); + gb_tty = NULL; + } else { + tty_port_get(&gb_tty->port); + mutex_unlock(&gb_tty->mutex); + } + } mutex_unlock(&table_lock); return gb_tty; } @@ -123,7 +147,7 @@ static void gb_tty_hangup(struct tty_struct *tty) static int gb_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) { - struct gb_tty *gb_tty = tty->driver_data; +// struct gb_tty *gb_tty = tty->driver_data; // FIXME - actually implement... @@ -132,7 +156,7 @@ static int gb_tty_write(struct tty_struct *tty, const unsigned char *buf, static int gb_tty_write_room(struct tty_struct *tty) { - struct gb_tty *gb_tty = tty->driver_data; +// struct gb_tty *gb_tty = tty->driver_data; // FIXME - how much do we want to say we have room for? return 0; @@ -140,12 +164,43 @@ static int gb_tty_write_room(struct tty_struct *tty) static int gb_tty_chars_in_buffer(struct tty_struct *tty) { - struct gb_tty *gb_tty = tty->driver_data; +// struct gb_tty *gb_tty = tty->driver_data; // FIXME - how many left to send? return 0; } +static int gb_tty_break_ctl(struct tty_struct *tty, int state) +{ +// struct gb_tty *gb_tty = tty->driver_data; + + // FIXME - send a break, if asked to... + return 0; +} + +static void gb_tty_set_termios(struct tty_struct *tty, struct ktermios *old) +{ + // FIXME - is this it??? + tty_termios_copy_hw(&tty->termios, old); +} + +static int gb_tty_tiocmget(struct tty_struct *tty) +{ +// struct gb_tty *gb_tty = tty->driver_data; + + // FIXME - get some tiocms! + return 0; +} + +static int gb_tty_tiocmset(struct tty_struct *tty, unsigned int set, + unsigned int clear) +{ +// struct gb_tty *gb_tty = tty->driver_data; + + // FIXME - set some tiocms! + return 0; +} + static void gb_tty_throttle(struct tty_struct *tty) { struct gb_tty *gb_tty = tty->driver_data; @@ -171,6 +226,148 @@ static void gb_tty_unthrottle(struct tty_struct *tty) } } +static int get_serial_info(struct gb_tty *gb_tty, + struct serial_struct __user *info) +{ + struct serial_struct tmp; + + if (!info) + return -EINVAL; + + memset(&tmp, 0, sizeof(tmp)); + tmp.flags = ASYNC_LOW_LATENCY; + tmp.xmit_fifo_size = gb_tty->writesize; + tmp.baud_base = 0; // FIXME + tmp.close_delay = gb_tty->port.close_delay / 10; + tmp.closing_wait = gb_tty->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ? + ASYNC_CLOSING_WAIT_NONE : gb_tty->port.closing_wait / 10; + + if (copy_to_user(info, &tmp, sizeof(tmp))) + return -EFAULT; + else + return 0; +} + +static int set_serial_info(struct gb_tty *gb_tty, + struct serial_struct __user *newinfo) +{ + struct serial_struct new_serial; + unsigned int closing_wait; + unsigned int close_delay; + int retval; + + if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) + return -EFAULT; + + close_delay = new_serial.close_delay * 10; + closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ? + ASYNC_CLOSING_WAIT_NONE : new_serial.closing_wait * 10; + + mutex_lock(&gb_tty->port.mutex); + if (!capable(CAP_SYS_ADMIN)) { + if ((close_delay != gb_tty->port.close_delay) || + (closing_wait != gb_tty->port.closing_wait)) + retval = -EPERM; + else + retval = -EOPNOTSUPP; + } else { + gb_tty->port.close_delay = close_delay; + gb_tty->port.closing_wait = closing_wait; + } + mutex_unlock(&gb_tty->port.mutex); + return retval; +} + +static int wait_serial_change(struct gb_tty *gb_tty, unsigned long arg) +{ + int retval = 0; + DECLARE_WAITQUEUE(wait, current); + struct async_icount old; + struct async_icount new; + + if (arg & (TIOCM_DSR | TIOCM_RI | TIOCM_CD)) + return -EINVAL; + + do { + spin_lock_irq(&gb_tty->read_lock); + old = gb_tty->oldcount; + new = gb_tty->iocount; + gb_tty->oldcount = new; + spin_lock_irq(&gb_tty->read_lock); + + if ((arg & TIOCM_DSR) && (old.dsr != new.dsr)) + break; + if ((arg & TIOCM_CD) && (old.dcd != new.dcd)) + break; + if ((arg & TIOCM_RI) && (old.rng != new.rng)) + break; + + add_wait_queue(&gb_tty->wioctl, &wait); + set_current_state(TASK_INTERRUPTIBLE); + schedule(); + remove_wait_queue(&gb_tty->wioctl, &wait); + if (gb_tty->disconnected) { + if (arg & TIOCM_CD) + break; + else + retval = -ENODEV; + } else { + if (signal_pending(current)) + retval = -ERESTARTSYS; + } + } while (!retval); + + return retval; +} + +static int get_serial_usage(struct gb_tty *gb_tty, + struct serial_icounter_struct __user *count) +{ + struct serial_icounter_struct icount; + int retval = 0; + + memset(&icount, 0, sizeof(icount)); + icount.dsr = gb_tty->iocount.dsr; + icount.rng = gb_tty->iocount.rng; + icount.dcd = gb_tty->iocount.dcd; + icount.frame = gb_tty->iocount.frame; + icount.overrun = gb_tty->iocount.overrun; + icount.parity = gb_tty->iocount.parity; + icount.brk = gb_tty->iocount.brk; + + if (copy_to_user(count, &icount, sizeof(icount)) > 0) + retval = -EFAULT; + + return retval; +} + +static int gb_tty_ioctl(struct tty_struct *tty, unsigned int cmd, + unsigned long arg) +{ + struct gb_tty *gb_tty = tty->driver_data; + int retval = -ENOIOCTLCMD; + + switch (cmd) { + case TIOCGSERIAL: + retval = get_serial_info(gb_tty, + (struct serial_struct __user *)arg); + break; + case TIOCSSERIAL: + retval = set_serial_info(gb_tty, + (struct serial_struct __user *)arg); + break; + case TIOCMIWAIT: + retval = wait_serial_change(gb_tty, arg); + break; + case TIOCGICOUNT: + retval = get_serial_usage(gb_tty, + (struct serial_icounter_struct __user *)arg); + break; + } + + return retval; +} + static const struct tty_operations gb_ops = { .install = gb_tty_install, @@ -212,6 +409,8 @@ static int tty_gb_probe(struct greybus_device *gdev, const struct greybus_device gb_tty->gdev = gdev; spin_lock_init(&gb_tty->write_lock); spin_lock_init(&gb_tty->read_lock); + init_waitqueue_head(&gb_tty->wioctl); + mutex_init(&gb_tty->mutex); /* FIXME - allocate gb buffers */ @@ -235,6 +434,16 @@ static void tty_gb_disconnect(struct greybus_device *gdev) struct gb_tty *gb_tty = greybus_get_drvdata(gdev); struct tty_struct *tty; + if (!gb_tty) + return; + + mutex_lock(&gb_tty->mutex); + gb_tty->disconnected = true; + + wake_up_all(&gb_tty->wioctl); + greybus_set_drvdata(gdev, NULL); + mutex_unlock(&gb_tty->mutex); + tty = tty_port_tty_get(&gb_tty->port); if (tty) { tty_vhangup(tty); @@ -244,6 +453,8 @@ static void tty_gb_disconnect(struct greybus_device *gdev) tty_unregister_device(gb_tty_driver, gb_tty->minor); + /* FIXME - free transmit / recieve buffers */ + tty_port_put(&gb_tty->port); } -- cgit v0.10.2 From ff5f0b38228fbf10ff58a530a8a462b3b90cc7ef Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 18 Aug 2014 18:25:11 -0500 Subject: greybus: uart-gb: improve minor device number error checking When alloc_minor() finds an available minor device number it does not constrain the highest number desired. Instead, it relies on its caller, tty_gb_probe() to see if the returned number indicates all minor numbers have been exhausted. There are a couple problems with this--or rather with this code. First, if an allocation is attempted *after* GB_NUM_MINORS is returned, a new number greater than (but not equal to) GB_NUM_MINORS will be allocated, and that won't produce any error condition. Second, alloc_minor() can return an error code (like -ENOMEM). And its caller is only checking for GB_NUM_MINORS. If an error code is returned, tty_gb_probe() simply uses it. Change alloc_minor() so it requests minor device numbers in the range 0..(GB_NUM_MINORS-1), and use an error return to detect when the minor device numbers have been exhausted. If alloc_minor() returns -ENOSPC (from idr_alloc()), translate that to -ENODEV. The only other error we might see is -ENOMEM, and if we get that, return it. Finally, zero gb_tty->minor when it's released. (If this is actually important a reserved value like GB_NUM_MINORS should be used instead to signify a gb_tty with no minor assigned.) Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 13a23cd..0e2507c 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -80,19 +80,20 @@ static int alloc_minor(struct gb_tty *gb_tty) int minor; mutex_lock(&table_lock); - minor = idr_alloc(&tty_minors, gb_tty, 0, 0, GFP_KERNEL); - if (minor < 0) - goto error; - gb_tty->minor = minor; -error: + minor = idr_alloc(&tty_minors, gb_tty, 0, GB_NUM_MINORS, GFP_KERNEL); mutex_unlock(&table_lock); + if (minor >= 0) + gb_tty->minor = minor; return minor; } static void release_minor(struct gb_tty *gb_tty) { + int minor = gb_tty->minor; + + gb_tty->minor = 0; /* Maybe should use an invalid value instead */ mutex_lock(&table_lock); - idr_remove(&tty_minors, gb_tty->minor); + idr_remove(&tty_minors, minor); mutex_unlock(&table_lock); } @@ -400,9 +401,12 @@ static int tty_gb_probe(struct greybus_device *gdev, const struct greybus_device return -ENOMEM; minor = alloc_minor(gb_tty); - if (minor == GB_NUM_MINORS) { - dev_err(&gdev->dev, "no more free minor numbers\n"); - return -ENODEV; + if (minor < 0) { + if (minor == -ENOSPC) { + dev_err(&gdev->dev, "no more free minor numbers\n"); + return -ENODEV; + } + return minor; } gb_tty->minor = minor; -- cgit v0.10.2 From caaa8a838dd098fc72f393b871c3f882bfac9e77 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 18 Aug 2014 18:25:12 -0500 Subject: greybus: uart-gb: a few minor bug fixes Here are a few small bug fixes in uart-gb.c: - In wait_serial_change(): - Return -EINVAL if *none* of the relevant flags are set in the "arg" parameter. - Balance the spin_lock_irq() with an unlock call (not another lock). - Rearrange a nested if structure (not a bug fix). - In tty_gb_probe(): - Reset the greybus_device driver data in case of error. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 0e2507c..4a54e9e 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -286,7 +286,7 @@ static int wait_serial_change(struct gb_tty *gb_tty, unsigned long arg) struct async_icount old; struct async_icount new; - if (arg & (TIOCM_DSR | TIOCM_RI | TIOCM_CD)) + if (!(arg & (TIOCM_DSR | TIOCM_RI | TIOCM_CD))) return -EINVAL; do { @@ -294,7 +294,7 @@ static int wait_serial_change(struct gb_tty *gb_tty, unsigned long arg) old = gb_tty->oldcount; new = gb_tty->iocount; gb_tty->oldcount = new; - spin_lock_irq(&gb_tty->read_lock); + spin_unlock_irq(&gb_tty->read_lock); if ((arg & TIOCM_DSR) && (old.dsr != new.dsr)) break; @@ -310,11 +310,9 @@ static int wait_serial_change(struct gb_tty *gb_tty, unsigned long arg) if (gb_tty->disconnected) { if (arg & TIOCM_CD) break; - else - retval = -ENODEV; - } else { - if (signal_pending(current)) - retval = -ERESTARTSYS; + retval = -ENODEV; + } else if (signal_pending(current)) { + retval = -ERESTARTSYS; } } while (!retval); @@ -429,6 +427,7 @@ static int tty_gb_probe(struct greybus_device *gdev, const struct greybus_device return 0; error: + greybus_set_drvdata(gdev, NULL); release_minor(gb_tty); return retval; } -- cgit v0.10.2 From 199d68d4a8cb3d2318d62a29f74d1838e1069232 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 30 Aug 2014 16:20:22 -0700 Subject: greybus: start moving the function types into the greybus core diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index b84ff76..2e3212b 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -1,7 +1,6 @@ -greybus-y := core.o gbuf.o +greybus-y := core.o gbuf.o i2c-gb.o obj-m += greybus.o -obj-m += i2c-gb.o obj-m += sdio-gb.o obj-m += gpio-gb.o obj-m += uart-gb.o diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 87148cd..ccc4e35 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -149,5 +149,29 @@ void greybus_deregister(struct greybus_driver *driver) } EXPORT_SYMBOL_GPL(greybus_deregister); + +static int new_device(struct greybus_device *gdev, + const struct greybus_device_id *id) +{ + int retval; + + /* Allocate all of the different "sub device types" for this device */ + retval = gb_i2c_probe(gdev, id); + return 0; +} + + +int __init gb_init(void) +{ + return 0; +} + +void __exit gb_exit(void) +{ +} + +module_init(gb_init); +module_exit(gb_exit); + MODULE_LICENSE("GPL"); MODULE_AUTHOR("Greg Kroah-Hartman "); diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index 0cbabb5..990a74d 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -13,7 +13,7 @@ #include #include "greybus.h" -struct gb_gpio { +struct gb_gpio_device { struct gpio_chip chip; struct greybus_device *gdev; struct gpio_chip *gpio; @@ -27,7 +27,7 @@ static const struct greybus_device_id id_table[] = { static int direction_input(struct gpio_chip *gpio, unsigned nr) { -// struct gb_gpio *gb_gpio = container_of(gpio, struct gb_gpio, chip); + //struct gb_gpio_device *gb_gpio_dev = container_of(gpio, struct gb_gpio_device, chip); // FIXME - do something there return 0; @@ -53,7 +53,7 @@ static void gpio_set(struct gpio_chip *gpio, unsigned nr, int val) static int gpio_gb_probe(struct greybus_device *gdev, const struct greybus_device_id *id) { - struct gb_gpio *gb_gpio; + struct gb_gpio_device *gb_gpio; struct gpio_chip *gpio; struct device *dev = &gdev->dev; int retval; @@ -89,11 +89,11 @@ static int gpio_gb_probe(struct greybus_device *gdev, const struct greybus_devic static void gpio_gb_disconnect(struct greybus_device *gdev) { - struct gb_gpio *gb_gpio; + struct gb_gpio_device *gb_gpio_dev; - gb_gpio = greybus_get_drvdata(gdev); + gb_gpio_dev = greybus_get_drvdata(gdev); - gpiochip_remove(&gb_gpio->chip); + gpiochip_remove(&gb_gpio_dev->chip); } static struct greybus_driver gpio_gb_driver = { diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 51b9f5b..3137668 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -72,15 +72,44 @@ struct gbuf { */ #define GBUF_FREE_BUFFER BIT(0) /* Free the transfer buffer with the gbuf */ +/* For SP1 hardware, we are going to "hardcode" each device to have all logical + * blocks in order to be able to address them as one unified "unit". Then + * higher up layers will then be able to talk to them as one logical block and + * properly know how they are hooked together (i.e. which i2c port is on the + * same module as the gpio pins, etc.) + * + * So, put the "private" data structures here in greybus.h and link to them off + * of the "main" greybus_device structure. + */ + +struct gb_i2c_device; +struct gb_gpio_device; +struct gb_sdio_host; +struct gb_tty; +struct gb_usb_device; struct greybus_device { struct device dev; struct greybus_descriptor descriptor; int num_cport; struct cport cport[0]; + + struct gb_i2c_device *gb_i2c_dev; + struct gb_gpio_device *gb_gpio_dev; + struct gb_sdio_host *gb_sdio_host; + struct gb_tty *gb_tty; + struct gb_usb_device *gb_usb_dev; }; #define to_greybus_device(d) container_of(d, struct greybus_device, dev) +/* + * Because we are allocating a data structure per "type" in the greybus device, + * we have static functions for this, not "dynamic" drivers like we really + * should in the end. + */ +int gb_i2c_probe(struct greybus_device *gdev, const struct greybus_device_id *id); +void gb_i2c_disconnect(struct greybus_device *gdev); + struct gbuf *greybus_alloc_gbuf(struct greybus_device *gdev, struct cport *cport, diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index 7fcbcef..929243e 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -12,7 +12,7 @@ #include #include "greybus.h" -struct i2c_gb_data { +struct gb_i2c_device { struct i2c_adapter *adapter; struct greybus_device *gdev; }; @@ -32,11 +32,11 @@ static s32 i2c_gb_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data) { - struct i2c_gb_data *i2c_gb_data; + struct gb_i2c_device *i2c_gb_dev; struct greybus_device *gdev; - i2c_gb_data = i2c_get_adapdata(adap); - gdev = i2c_gb_data->gdev; + i2c_gb_dev = i2c_get_adapdata(adap); + gdev = i2c_gb_dev->gdev; // FIXME - do the actual work of sending a i2c message here... switch (size) { @@ -75,22 +75,23 @@ static const struct i2c_algorithm smbus_algorithm = { .functionality = i2c_gb_func, }; -static int i2c_gb_probe(struct greybus_device *gdev, const struct greybus_device_id *id) +int gb_i2c_probe(struct greybus_device *gdev, + const struct greybus_device_id *id) { - struct i2c_gb_data *i2c_gb_data; + struct gb_i2c_device *i2c_gb_dev; struct i2c_adapter *adapter; int retval; - i2c_gb_data = kzalloc(sizeof(*i2c_gb_data), GFP_KERNEL); - if (!i2c_gb_data) + i2c_gb_dev = kzalloc(sizeof(*i2c_gb_dev), GFP_KERNEL); + if (!i2c_gb_dev) return -ENOMEM; adapter = kzalloc(sizeof(*adapter), GFP_KERNEL); if (!adapter) { - kfree(i2c_gb_data); + kfree(i2c_gb_dev); return -ENOMEM; } - i2c_set_adapdata(adapter, i2c_gb_data); + i2c_set_adapdata(adapter, i2c_gb_dev); adapter->owner = THIS_MODULE; adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; adapter->algo = &smbus_algorithm; @@ -103,33 +104,35 @@ static int i2c_gb_probe(struct greybus_device *gdev, const struct greybus_device goto error; } - i2c_gb_data->gdev = gdev; - i2c_gb_data->adapter = adapter; + i2c_gb_dev->gdev = gdev; + i2c_gb_dev->adapter = adapter; - greybus_set_drvdata(gdev, i2c_gb_data); + greybus_set_drvdata(gdev, i2c_gb_dev); return 0; error: kfree(adapter); - kfree(i2c_gb_data); + kfree(i2c_gb_dev); return retval; } -static void i2c_gb_disconnect(struct greybus_device *gdev) +void gb_i2c_disconnect(struct greybus_device *gdev) { - struct i2c_gb_data *i2c_gb_data; + struct gb_i2c_device *i2c_gb_dev; - i2c_gb_data = greybus_get_drvdata(gdev); - i2c_del_adapter(i2c_gb_data->adapter); - kfree(i2c_gb_data->adapter); - kfree(i2c_gb_data); + i2c_gb_dev = greybus_get_drvdata(gdev); + i2c_del_adapter(i2c_gb_dev->adapter); + kfree(i2c_gb_dev->adapter); + kfree(i2c_gb_dev); } +#if 0 static struct greybus_driver i2c_gb_driver = { - .probe = i2c_gb_probe, - .disconnect = i2c_gb_disconnect, + .probe = gb_i2c_probe, + .disconnect = gb_i2c_disconnect, .id_table = id_table, }; module_greybus_driver(i2c_gb_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Greg Kroah-Hartman "); +#endif diff --git a/drivers/staging/greybus/sdio-gb.c b/drivers/staging/greybus/sdio-gb.c index f92ab1b..8521b06 100644 --- a/drivers/staging/greybus/sdio-gb.c +++ b/drivers/staging/greybus/sdio-gb.c @@ -12,7 +12,7 @@ #include #include "greybus.h" -struct sd_gb_host { +struct gb_sdio_host { struct mmc_host *mmc; struct mmc_request *mrq; // FIXME - some lock? @@ -48,9 +48,9 @@ static const struct mmc_host_ops gb_sd_ops = { static int sd_gb_probe(struct greybus_device *gdev, const struct greybus_device_id *id) { struct mmc_host *mmc; - struct sd_gb_host *host; + struct gb_sdio_host *host; - mmc = mmc_alloc_host(sizeof(struct sd_gb_host), &gdev->dev); + mmc = mmc_alloc_host(sizeof(struct gb_sdio_host), &gdev->dev); if (!mmc) return -ENOMEM; @@ -67,7 +67,7 @@ static int sd_gb_probe(struct greybus_device *gdev, const struct greybus_device_ static void sd_gb_disconnect(struct greybus_device *gdev) { struct mmc_host *mmc; - struct sd_gb_host *host; + struct gb_sdio_host *host; host = greybus_get_drvdata(gdev); mmc = host->mmc; diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 4a54e9e..839ea2d 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -344,27 +344,22 @@ static int gb_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct gb_tty *gb_tty = tty->driver_data; - int retval = -ENOIOCTLCMD; switch (cmd) { case TIOCGSERIAL: - retval = get_serial_info(gb_tty, - (struct serial_struct __user *)arg); - break; + return get_serial_info(gb_tty, + (struct serial_struct __user *)arg); case TIOCSSERIAL: - retval = set_serial_info(gb_tty, - (struct serial_struct __user *)arg); - break; + return set_serial_info(gb_tty, + (struct serial_struct __user *)arg); case TIOCMIWAIT: - retval = wait_serial_change(gb_tty, arg); - break; + return wait_serial_change(gb_tty, arg); case TIOCGICOUNT: - retval = get_serial_usage(gb_tty, - (struct serial_icounter_struct __user *)arg); - break; + return get_serial_usage(gb_tty, + (struct serial_icounter_struct __user *)arg); } - return retval; + return -ENOIOCTLCMD; } -- cgit v0.10.2 From 503c1cdbfb5c7570bf64d7b04847861dfd6328fa Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 30 Aug 2014 16:21:03 -0700 Subject: greybus: static module_init/exit functions diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index ccc4e35..f8332b4 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -161,12 +161,12 @@ static int new_device(struct greybus_device *gdev, } -int __init gb_init(void) +static int __init gb_init(void) { return 0; } -void __exit gb_exit(void) +static void __exit gb_exit(void) { } -- cgit v0.10.2 From db6e1fd264ac6716ad9778e9b6cd6bae5a527f5e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 30 Aug 2014 16:47:26 -0700 Subject: greybus: hook up sdio, gpio, and tty into the greybus core. diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 2e3212b..74d4124 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -1,9 +1,6 @@ -greybus-y := core.o gbuf.o i2c-gb.o +greybus-y := core.o gbuf.o i2c-gb.o gpio-gb.o sdio-gb.o uart-gb.o obj-m += greybus.o -obj-m += sdio-gb.o -obj-m += gpio-gb.o -obj-m += uart-gb.o KERNELVER ?= $(shell uname -r) KERNELDIR ?= /lib/modules/$(KERNELVER)/build diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index f8332b4..b1a5b88 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -157,17 +157,58 @@ static int new_device(struct greybus_device *gdev, /* Allocate all of the different "sub device types" for this device */ retval = gb_i2c_probe(gdev, id); + if (retval) + goto error_i2c; + + retval = gb_gpio_probe(gdev, id); + if (retval) + goto error_gpio; + + retval = gb_sdio_probe(gdev, id); + if (retval) + goto error_sdio; + + retval = gb_tty_probe(gdev, id); + if (retval) + goto error_tty; return 0; + +error_tty: + gb_sdio_disconnect(gdev); + +error_sdio: + gb_gpio_disconnect(gdev); + +error_gpio: + gb_i2c_disconnect(gdev); + +error_i2c: + return retval; } +static void remove_device(struct greybus_device *gdev) +{ + /* tear down all of the "sub device types" for this device */ + gb_i2c_disconnect(gdev); + gb_gpio_disconnect(gdev); + gb_sdio_disconnect(gdev); + gb_tty_disconnect(gdev); +} static int __init gb_init(void) { + int retval; + + retval = gb_tty_init(); + if (retval) + return retval; + return 0; } static void __exit gb_exit(void) { + gb_tty_exit(); } module_init(gb_init); diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index 990a74d..30b15ed 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -51,7 +51,8 @@ static void gpio_set(struct gpio_chip *gpio, unsigned nr, int val) return; } -static int gpio_gb_probe(struct greybus_device *gdev, const struct greybus_device_id *id) +int gb_gpio_probe(struct greybus_device *gdev, + const struct greybus_device_id *id) { struct gb_gpio_device *gb_gpio; struct gpio_chip *gpio; @@ -87,7 +88,7 @@ static int gpio_gb_probe(struct greybus_device *gdev, const struct greybus_devic return 0; } -static void gpio_gb_disconnect(struct greybus_device *gdev) +void gb_gpio_disconnect(struct greybus_device *gdev) { struct gb_gpio_device *gb_gpio_dev; @@ -96,9 +97,10 @@ static void gpio_gb_disconnect(struct greybus_device *gdev) gpiochip_remove(&gb_gpio_dev->chip); } +#if 0 static struct greybus_driver gpio_gb_driver = { - .probe = gpio_gb_probe, - .disconnect = gpio_gb_disconnect, + .probe = gb_gpio_probe, + .disconnect = gb_gpio_disconnect, .id_table = id_table, }; @@ -106,3 +108,4 @@ module_greybus_driver(gpio_gb_driver); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Greybus GPIO driver"); MODULE_AUTHOR("Greg Kroah-Hartman "); +#endif diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 3137668..2440342a 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -109,7 +109,15 @@ struct greybus_device { */ int gb_i2c_probe(struct greybus_device *gdev, const struct greybus_device_id *id); void gb_i2c_disconnect(struct greybus_device *gdev); - +int gb_gpio_probe(struct greybus_device *gdev, const struct greybus_device_id *id); +void gb_gpio_disconnect(struct greybus_device *gdev); +int gb_sdio_probe(struct greybus_device *gdev, const struct greybus_device_id *id); +void gb_sdio_disconnect(struct greybus_device *gdev); +int gb_tty_probe(struct greybus_device *gdev, const struct greybus_device_id *id); +void gb_tty_disconnect(struct greybus_device *gdev); + +int gb_tty_init(void); +void gb_tty_exit(void); struct gbuf *greybus_alloc_gbuf(struct greybus_device *gdev, struct cport *cport, diff --git a/drivers/staging/greybus/sdio-gb.c b/drivers/staging/greybus/sdio-gb.c index 8521b06..9f7b44d 100644 --- a/drivers/staging/greybus/sdio-gb.c +++ b/drivers/staging/greybus/sdio-gb.c @@ -45,7 +45,8 @@ static const struct mmc_host_ops gb_sd_ops = { .get_ro = gb_sd_get_ro, }; -static int sd_gb_probe(struct greybus_device *gdev, const struct greybus_device_id *id) +int gb_sdio_probe(struct greybus_device *gdev, + const struct greybus_device_id *id) { struct mmc_host *mmc; struct gb_sdio_host *host; @@ -64,7 +65,7 @@ static int sd_gb_probe(struct greybus_device *gdev, const struct greybus_device_ return 0; } -static void sd_gb_disconnect(struct greybus_device *gdev) +void gb_sdio_disconnect(struct greybus_device *gdev) { struct mmc_host *mmc; struct gb_sdio_host *host; @@ -76,9 +77,10 @@ static void sd_gb_disconnect(struct greybus_device *gdev) mmc_free_host(mmc); } +#if 0 static struct greybus_driver sd_gb_driver = { - .probe = sd_gb_probe, - .disconnect = sd_gb_disconnect, + .probe = gb_sdio_probe, + .disconnect = gb_sdio_disconnect, .id_table = id_table, }; @@ -86,3 +88,4 @@ module_greybus_driver(sd_gb_driver); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Greybus SD/MMC Host driver"); MODULE_AUTHOR("Greg Kroah-Hartman "); +#endif diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 839ea2d..cdb4a82 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -382,7 +382,8 @@ static const struct tty_operations gb_ops = { }; -static int tty_gb_probe(struct greybus_device *gdev, const struct greybus_device_id *id) +int gb_tty_probe(struct greybus_device *gdev, + const struct greybus_device_id *id) { struct gb_tty *gb_tty; struct device *tty_dev; @@ -427,7 +428,7 @@ error: return retval; } -static void tty_gb_disconnect(struct greybus_device *gdev) +void gb_tty_disconnect(struct greybus_device *gdev) { struct gb_tty *gb_tty = greybus_get_drvdata(gdev); struct tty_struct *tty; @@ -457,13 +458,13 @@ static void tty_gb_disconnect(struct greybus_device *gdev) } static struct greybus_driver tty_gb_driver = { - .probe = tty_gb_probe, - .disconnect = tty_gb_disconnect, + .probe = gb_tty_probe, + .disconnect = gb_tty_disconnect, .id_table = id_table, }; -static int __init gb_tty_init(void) +int __init gb_tty_init(void) { int retval; @@ -496,14 +497,16 @@ static int __init gb_tty_init(void) return retval; } -static void __exit gb_tty_exit(void) +void __exit gb_tty_exit(void) { greybus_deregister(&tty_gb_driver); tty_unregister_driver(gb_tty_driver); put_tty_driver(gb_tty_driver); } +#if 0 module_init(gb_tty_init); module_exit(gb_tty_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Greg Kroah-Hartman "); +#endif -- cgit v0.10.2 From e7e0782c41681856740fbdd63972fba6ec08f943 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 30 Aug 2014 16:49:05 -0700 Subject: greybus: i2c: tie to the proper place on the greybus_device diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index 929243e..8b99e8a 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -107,7 +107,7 @@ int gb_i2c_probe(struct greybus_device *gdev, i2c_gb_dev->gdev = gdev; i2c_gb_dev->adapter = adapter; - greybus_set_drvdata(gdev, i2c_gb_dev); + gdev->gb_i2c_dev = i2c_gb_dev; return 0; error: kfree(adapter); @@ -119,7 +119,7 @@ void gb_i2c_disconnect(struct greybus_device *gdev) { struct gb_i2c_device *i2c_gb_dev; - i2c_gb_dev = greybus_get_drvdata(gdev); + i2c_gb_dev = gdev->gb_i2c_dev; i2c_del_adapter(i2c_gb_dev->adapter); kfree(i2c_gb_dev->adapter); kfree(i2c_gb_dev); -- cgit v0.10.2 From 3d9efaaea3bd49ddd6d06b079812f4af8103d824 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 30 Aug 2014 16:49:59 -0700 Subject: greybus: i2c: use same naming convention everywhere diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index 8b99e8a..bb107f8 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -32,11 +32,11 @@ static s32 i2c_gb_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data) { - struct gb_i2c_device *i2c_gb_dev; + struct gb_i2c_device *gb_i2c_dev; struct greybus_device *gdev; - i2c_gb_dev = i2c_get_adapdata(adap); - gdev = i2c_gb_dev->gdev; + gb_i2c_dev = i2c_get_adapdata(adap); + gdev = gb_i2c_dev->gdev; // FIXME - do the actual work of sending a i2c message here... switch (size) { @@ -78,20 +78,20 @@ static const struct i2c_algorithm smbus_algorithm = { int gb_i2c_probe(struct greybus_device *gdev, const struct greybus_device_id *id) { - struct gb_i2c_device *i2c_gb_dev; + struct gb_i2c_device *gb_i2c_dev; struct i2c_adapter *adapter; int retval; - i2c_gb_dev = kzalloc(sizeof(*i2c_gb_dev), GFP_KERNEL); - if (!i2c_gb_dev) + gb_i2c_dev = kzalloc(sizeof(*gb_i2c_dev), GFP_KERNEL); + if (!gb_i2c_dev) return -ENOMEM; adapter = kzalloc(sizeof(*adapter), GFP_KERNEL); if (!adapter) { - kfree(i2c_gb_dev); + kfree(gb_i2c_dev); return -ENOMEM; } - i2c_set_adapdata(adapter, i2c_gb_dev); + i2c_set_adapdata(adapter, gb_i2c_dev); adapter->owner = THIS_MODULE; adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; adapter->algo = &smbus_algorithm; @@ -104,25 +104,25 @@ int gb_i2c_probe(struct greybus_device *gdev, goto error; } - i2c_gb_dev->gdev = gdev; - i2c_gb_dev->adapter = adapter; + gb_i2c_dev->gdev = gdev; + gb_i2c_dev->adapter = adapter; - gdev->gb_i2c_dev = i2c_gb_dev; + gdev->gb_i2c_dev = gb_i2c_dev; return 0; error: kfree(adapter); - kfree(i2c_gb_dev); + kfree(gb_i2c_dev); return retval; } void gb_i2c_disconnect(struct greybus_device *gdev) { - struct gb_i2c_device *i2c_gb_dev; + struct gb_i2c_device *gb_i2c_dev; - i2c_gb_dev = gdev->gb_i2c_dev; - i2c_del_adapter(i2c_gb_dev->adapter); - kfree(i2c_gb_dev->adapter); - kfree(i2c_gb_dev); + gb_i2c_dev = gdev->gb_i2c_dev; + i2c_del_adapter(gb_i2c_dev->adapter); + kfree(gb_i2c_dev->adapter); + kfree(gb_i2c_dev); } #if 0 -- cgit v0.10.2 From 426f29d6be1272dc3e7678144d2ef2a89a1fdd1d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 30 Aug 2014 16:51:21 -0700 Subject: greybus: gpio: tie into gb core properly diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index 30b15ed..7b8b85f 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -77,7 +77,7 @@ int gb_gpio_probe(struct greybus_device *gdev, gpio->ngpio = 42; // FIXME!!! gpio->can_sleep = false; // FIXME!!! - greybus_set_drvdata(gdev, gb_gpio); + gdev->gb_gpio_dev= gb_gpio; retval = gpiochip_add(gpio); if (retval) { @@ -92,7 +92,7 @@ void gb_gpio_disconnect(struct greybus_device *gdev) { struct gb_gpio_device *gb_gpio_dev; - gb_gpio_dev = greybus_get_drvdata(gdev); + gb_gpio_dev = gdev->gb_gpio_dev; gpiochip_remove(&gb_gpio_dev->chip); } -- cgit v0.10.2 From 56f10573be491212dd46ec44789f7a3ffc6e3352 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 30 Aug 2014 16:52:18 -0700 Subject: greybus: sdio: tie into gb core properly diff --git a/drivers/staging/greybus/sdio-gb.c b/drivers/staging/greybus/sdio-gb.c index 9f7b44d..81eb33d 100644 --- a/drivers/staging/greybus/sdio-gb.c +++ b/drivers/staging/greybus/sdio-gb.c @@ -61,7 +61,7 @@ int gb_sdio_probe(struct greybus_device *gdev, mmc->ops = &gb_sd_ops; // FIXME - set up size limits we can handle. - greybus_set_drvdata(gdev, host); + gdev->gb_sdio_host = host; return 0; } @@ -70,7 +70,7 @@ void gb_sdio_disconnect(struct greybus_device *gdev) struct mmc_host *mmc; struct gb_sdio_host *host; - host = greybus_get_drvdata(gdev); + host = gdev->gb_sdio_host; mmc = host->mmc; mmc_remove_host(mmc); -- cgit v0.10.2 From eca17c52038f974d406768a6f0ab171b9e81a7c8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 30 Aug 2014 16:54:05 -0700 Subject: greybus: uart: tie into gb core properly diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index cdb4a82..377ad38 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -412,7 +412,7 @@ int gb_tty_probe(struct greybus_device *gdev, /* FIXME - allocate gb buffers */ - greybus_set_drvdata(gdev, gb_tty); + gdev->gb_tty = gb_tty; tty_dev = tty_port_register_device(&gb_tty->port, gb_tty_driver, minor, &gdev->dev); @@ -423,14 +423,14 @@ int gb_tty_probe(struct greybus_device *gdev, return 0; error: - greybus_set_drvdata(gdev, NULL); + gdev->gb_tty = NULL; release_minor(gb_tty); return retval; } void gb_tty_disconnect(struct greybus_device *gdev) { - struct gb_tty *gb_tty = greybus_get_drvdata(gdev); + struct gb_tty *gb_tty = gdev->gb_tty; struct tty_struct *tty; if (!gb_tty) @@ -440,7 +440,7 @@ void gb_tty_disconnect(struct greybus_device *gdev) gb_tty->disconnected = true; wake_up_all(&gb_tty->wioctl); - greybus_set_drvdata(gdev, NULL); + gdev->gb_tty = NULL; mutex_unlock(&gb_tty->mutex); tty = tty_port_tty_get(&gb_tty->port); -- cgit v0.10.2 From ba4468d4641d959350d69d9ccaab41ffb92355cc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 30 Aug 2014 17:06:54 -0700 Subject: greybus: initial framework for ES1 usb AP driver diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 74d4124..29ba1da 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -1,6 +1,7 @@ greybus-y := core.o gbuf.o i2c-gb.o gpio-gb.o sdio-gb.o uart-gb.o obj-m += greybus.o +obj-m += es1-ap-usb.o KERNELVER ?= $(shell uname -r) KERNELDIR ?= /lib/modules/$(KERNELVER)/build diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c new file mode 100644 index 0000000..05c7248 --- /dev/null +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -0,0 +1,45 @@ +/* + * Greybus "AP" USB driver + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ +#include +#include +#include +#include +#include + + +static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x0000, 0x0000) }, // FIXME + { }, +}; +MODULE_DEVICE_TABLE(usb, id_table); + + +static int ap_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + + return 0; +} + +static void ap_disconnect(struct usb_interface *interface) +{ + + +} + +static struct usb_driver es1_ap_driver = { + .name = "es1_ap_driver", + .probe = ap_probe, + .disconnect = ap_disconnect, + .id_table = id_table, +}; + +module_usb_driver(es1_ap_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Greg Kroah-Hartman "); -- cgit v0.10.2 From e5f167f1df8c0975ab90489724e7f542cd72dc45 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 30 Aug 2014 17:11:41 -0700 Subject: greybus: can't use devm anymore, we aren't tieing into the driver model lifecycle :( diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index 7b8b85f..43fd0d3 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -59,7 +59,7 @@ int gb_gpio_probe(struct greybus_device *gdev, struct device *dev = &gdev->dev; int retval; - gb_gpio = devm_kzalloc(dev, sizeof(*gb_gpio), GFP_KERNEL); + gb_gpio = kzalloc(dev, sizeof(*gb_gpio), GFP_KERNEL); if (!gb_gpio) return -ENOMEM; gb_gpio->gdev = gdev; @@ -95,6 +95,7 @@ void gb_gpio_disconnect(struct greybus_device *gdev) gb_gpio_dev = gdev->gb_gpio_dev; gpiochip_remove(&gb_gpio_dev->chip); + kfree(gb_gpio_dev); } #if 0 diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 377ad38..298b9ff 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -390,7 +390,7 @@ int gb_tty_probe(struct greybus_device *gdev, int retval; int minor; - gb_tty = devm_kzalloc(&gdev->dev, sizeof(*gb_tty), GFP_KERNEL); + gb_tty = kzalloc(&gdev->dev, sizeof(*gb_tty), GFP_KERNEL); if (!gb_tty) return -ENOMEM; @@ -455,6 +455,8 @@ void gb_tty_disconnect(struct greybus_device *gdev) /* FIXME - free transmit / recieve buffers */ tty_port_put(&gb_tty->port); + + kfree(gb_tty); } static struct greybus_driver tty_gb_driver = { -- cgit v0.10.2 From 8bf23e84d7cc2d63cfe433ded084e1052fc6d487 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 30 Aug 2014 17:18:04 -0700 Subject: greybus: actually get the devm() change to build... diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index 43fd0d3..2047794 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -59,7 +59,7 @@ int gb_gpio_probe(struct greybus_device *gdev, struct device *dev = &gdev->dev; int retval; - gb_gpio = kzalloc(dev, sizeof(*gb_gpio), GFP_KERNEL); + gb_gpio = kzalloc(sizeof(*gb_gpio), GFP_KERNEL); if (!gb_gpio) return -ENOMEM; gb_gpio->gdev = gdev; diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 298b9ff..f667b5c 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -390,7 +390,7 @@ int gb_tty_probe(struct greybus_device *gdev, int retval; int minor; - gb_tty = kzalloc(&gdev->dev, sizeof(*gb_tty), GFP_KERNEL); + gb_tty = kzalloc(sizeof(*gb_tty), GFP_KERNEL); if (!gb_tty) return -ENOMEM; -- cgit v0.10.2 From f1eec30ac83cf95d0607a1c736cf42b44846bad8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 30 Aug 2014 17:18:14 -0700 Subject: greybus: first framework for the es1 ap controller diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 05c7248..991a538 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -18,17 +18,40 @@ static const struct usb_device_id id_table[] = { }; MODULE_DEVICE_TABLE(usb, id_table); +/* + * Hack, we "know" we will only have one of these at any one time, so only + * create one static structure pointer. + */ +struct es1_ap_dev { + struct usb_interface *usb_intf; + +} *es1_ap_dev; + static int ap_probe(struct usb_interface *interface, const struct usb_device_id *id) { + if (es1_ap_dev) { + dev_err(&interface->dev, "Already have a es1_ap_dev???\n"); + return -ENODEV; + } + es1_ap_dev = kzalloc(sizeof(*es1_ap_dev), GFP_KERNEL); + if (!es1_ap_dev) + return -ENOMEM; + es1_ap_dev->usb_intf = interface; + usb_set_intfdata(interface, es1_ap_dev); return 0; } static void ap_disconnect(struct usb_interface *interface) { + es1_ap_dev = usb_get_intfdata(interface); + + /* Tear down everything! */ + kfree(es1_ap_dev); + es1_ap_dev = NULL; } -- cgit v0.10.2 From 6f83ab76b8e6ed3d9b8187ffd97bfd68c8a9a045 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 30 Aug 2014 17:30:04 -0700 Subject: greybus: es1-ap-usb: more init framework added. diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 991a538..bebef6d 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -18,19 +18,31 @@ static const struct usb_device_id id_table[] = { }; MODULE_DEVICE_TABLE(usb, id_table); +struct es1_ap_dev { + struct usb_device *usb_dev; + struct usb_interface *usb_intf; + + __u8 ap_in_endpoint; + __u8 ap_out_endpoint; + u8 *ap_buffer; + +}; + /* * Hack, we "know" we will only have one of these at any one time, so only * create one static structure pointer. */ -struct es1_ap_dev { - struct usb_interface *usb_intf; - -} *es1_ap_dev; +static struct es1_ap_dev *es1_ap_dev; static int ap_probe(struct usb_interface *interface, const struct usb_device_id *id) { + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + size_t buffer_size; + int i; + if (es1_ap_dev) { dev_err(&interface->dev, "Already have a es1_ap_dev???\n"); return -ENODEV; @@ -39,7 +51,30 @@ static int ap_probe(struct usb_interface *interface, if (!es1_ap_dev) return -ENOMEM; + // FIXME + // figure out endpoint for talking to the AP. + iface_desc = interface->cur_altsetting; + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i].desc; + + if (usb_endpoint_is_bulk_in(endpoint)) { + buffer_size = usb_endpoint_maxp(endpoint); + // FIXME - Save buffer_size? + es1_ap_dev->ap_in_endpoint = endpoint->bEndpointAddress; + } + if (usb_endpoint_is_bulk_out(endpoint)) { + // FIXME - anything else about this we need? + es1_ap_dev->ap_out_endpoint = endpoint->bEndpointAddress; + } + // FIXME - properly exit once found the AP endpoint + // FIXME - set up cport endpoints + } + + // FIXME - allocate buffer + // FIXME = start up talking, then create the gb "devices" based on what the AP tells us. + es1_ap_dev->usb_intf = interface; + es1_ap_dev->usb_dev = usb_get_dev(interface_to_usbdev(interface)); usb_set_intfdata(interface, es1_ap_dev); return 0; } @@ -50,6 +85,8 @@ static void ap_disconnect(struct usb_interface *interface) /* Tear down everything! */ + usb_put_dev(es1_ap_dev->usb_dev); + kfree(es1_ap_dev->ap_buffer); kfree(es1_ap_dev); es1_ap_dev = NULL; -- cgit v0.10.2 From 27fb83109a3901767cbabafeba617d74f70fcbdc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 31 Aug 2014 13:54:59 -0700 Subject: greybus: register the bus with the driver core and add framework for debugfs files. diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 29ba1da..3badfef 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -1,4 +1,4 @@ -greybus-y := core.o gbuf.o i2c-gb.o gpio-gb.o sdio-gb.o uart-gb.o +greybus-y := core.o gbuf.o debugfs.o i2c-gb.o gpio-gb.o sdio-gb.o uart-gb.o obj-m += greybus.o obj-m += es1-ap-usb.o diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index b1a5b88..143882a 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -86,7 +86,7 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) return 0; } -struct bus_type greybus_bus_type = { +static struct bus_type greybus_bus_type = { .name = "greybus", .match = greybus_device_match, .uevent = greybus_uevent, @@ -199,16 +199,36 @@ static int __init gb_init(void) { int retval; - retval = gb_tty_init(); + retval = greybus_debugfs_init(); if (retval) return retval; + retval = bus_register(&greybus_bus_type); + if (retval) + goto error_bus; + + // FIXME - more gb core init goes here + + retval = gb_tty_init(); + if (retval) + goto error_tty; + return 0; + +error_tty: + bus_unregister(&greybus_bus_type); + +error_bus: + greybus_debugfs_cleanup(); + + return retval; } static void __exit gb_exit(void) { gb_tty_exit(); + bus_unregister(&greybus_bus_type); + greybus_debugfs_cleanup(); } module_init(gb_init); diff --git a/drivers/staging/greybus/debugfs.c b/drivers/staging/greybus/debugfs.c new file mode 100644 index 0000000..097b32d --- /dev/null +++ b/drivers/staging/greybus/debugfs.c @@ -0,0 +1,34 @@ +/* + * Greybus debugfs code + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include + +#include "greybus.h" + +static struct dentry *gb_debug_root; + +int greybus_debugfs_init(void) +{ + gb_debug_root = debugfs_create_dir("greybus", NULL); + if (!gb_debug_root) + return -ENOENT; + + return 0; +} + +void greybus_debugfs_cleanup(void) +{ + debugfs_remove_recursive(gb_debug_root); +} diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 2440342a..7ce8c6e 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -174,10 +174,10 @@ void greybus_deregister(struct greybus_driver *driver); #define module_greybus_driver(__greybus_driver) \ module_driver(__greybus_driver, greybus_register, greybus_deregister) -extern struct bus_type greybus_bus_type; - int greybus_disabled(void); +int greybus_debugfs_init(void); +void greybus_debugfs_cleanup(void); #endif /* __KERNEL__ */ #endif /* __LINUX_GREYBUS_H */ -- cgit v0.10.2 From de536e3094760880569e23166854c99b7c66135c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 31 Aug 2014 16:17:04 -0700 Subject: greybus: ap message loop added. diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 3badfef..9815e8a 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -1,4 +1,11 @@ -greybus-y := core.o gbuf.o debugfs.o i2c-gb.o gpio-gb.o sdio-gb.o uart-gb.o +greybus-y := core.o \ + gbuf.o \ + debugfs.o \ + ap.o \ + i2c-gb.o \ + gpio-gb.o \ + sdio-gb.o \ + uart-gb.o obj-m += greybus.o obj-m += es1-ap-usb.o diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c new file mode 100644 index 0000000..5189e8e --- /dev/null +++ b/drivers/staging/greybus/ap.c @@ -0,0 +1,125 @@ +/* + * Greybus "AP" message loop handling + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include "greybus.h" + +struct ap_msg { + u8 *data; + int size; + struct list_head list; +}; + +static LIST_HEAD(ap_msg_list); +static spinlock_t ap_msg_list_lock; +static struct task_struct *ap_thread; +static wait_queue_head_t ap_wait; + +static struct ap_msg *get_ap_msg(void) +{ + struct ap_msg *ap_msg; + unsigned long flags; + + spin_lock_irqsave(&ap_msg_list_lock, flags); + + ap_msg = list_first_entry_or_null(&ap_msg_list, struct ap_msg, list); + if (ap_msg != NULL) + list_del(&ap_msg->list); + spin_unlock_irqrestore(&ap_msg_list_lock, flags); + + return ap_msg; +} + +static int ap_process_loop(void *data) +{ + struct ap_msg *ap_msg; + + while (!kthread_should_stop()) { + wait_event_interruptible(ap_wait, kthread_should_stop()); + + if (kthread_should_stop()) + break; + + /* Get some data off of the ap list and process it */ + ap_msg = get_ap_msg(); + if (!ap_msg) + continue; + + // FIXME - process the message + + /* clean the message up */ + kfree(ap_msg->data); + kfree(ap_msg); + } + return 0; +} + +int gb_new_ap_msg(u8 *data, int size) +{ + struct ap_msg *ap_msg; + unsigned long flags; + + /* + * Totally naive copy the message into a new structure that we slowly + * create and add it to the list. Let's get this working, the odds of + * this being any "slow path" for AP messages is really low at this + * point in time, but you never know, so this comment is here to point + * out that maybe we should use a slab allocator, or even just not copy + * the data, but use it directly and force the urbs to be "new" each + * time. + */ + + /* Note - this can, and will, be called in interrupt context. */ + ap_msg = kmalloc(sizeof(*ap_msg), GFP_ATOMIC); + if (!ap_msg) + return -ENOMEM; + ap_msg->data = kmalloc(size, GFP_ATOMIC); + if (!ap_msg->data) { + kfree(ap_msg); + return -ENOMEM; + } + memcpy(ap_msg->data, data, size); + ap_msg->size = size; + + spin_lock_irqsave(&ap_msg_list_lock, flags); + list_add(&ap_msg->list, &ap_msg_list); + spin_unlock_irqrestore(&ap_msg_list_lock, flags); + + /* kick our thread to handle the message */ + wake_up_interruptible(&ap_wait); + + return 0; +} + +int gb_thread_init(void) +{ + init_waitqueue_head(&ap_wait); + spin_lock_init(&ap_msg_list_lock); + + ap_thread = kthread_run(ap_process_loop, NULL, "greybus_ap"); + if (IS_ERR(ap_thread)) + return PTR_ERR(ap_thread); + + return 0; +} + +void gb_thread_destroy(void) +{ + kthread_stop(ap_thread); +} + + diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 143882a..887aa60 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include "greybus.h" @@ -199,7 +200,7 @@ static int __init gb_init(void) { int retval; - retval = greybus_debugfs_init(); + retval = gb_debugfs_init(); if (retval) return retval; @@ -207,6 +208,10 @@ static int __init gb_init(void) if (retval) goto error_bus; + retval = gb_thread_init(); + if (retval) + goto error_thread; + // FIXME - more gb core init goes here retval = gb_tty_init(); @@ -216,10 +221,13 @@ static int __init gb_init(void) return 0; error_tty: + gb_thread_destroy(); + +error_thread: bus_unregister(&greybus_bus_type); error_bus: - greybus_debugfs_cleanup(); + gb_debugfs_cleanup(); return retval; } @@ -228,7 +236,7 @@ static void __exit gb_exit(void) { gb_tty_exit(); bus_unregister(&greybus_bus_type); - greybus_debugfs_cleanup(); + gb_debugfs_cleanup(); } module_init(gb_init); diff --git a/drivers/staging/greybus/debugfs.c b/drivers/staging/greybus/debugfs.c index 097b32d..4e313f1 100644 --- a/drivers/staging/greybus/debugfs.c +++ b/drivers/staging/greybus/debugfs.c @@ -19,7 +19,7 @@ static struct dentry *gb_debug_root; -int greybus_debugfs_init(void) +int gb_debugfs_init(void) { gb_debug_root = debugfs_create_dir("greybus", NULL); if (!gb_debug_root) @@ -28,7 +28,7 @@ int greybus_debugfs_init(void) return 0; } -void greybus_debugfs_cleanup(void) +void gb_debugfs_cleanup(void) { debugfs_remove_recursive(gb_debug_root); } diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index bebef6d..abf9dfe 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -10,7 +10,7 @@ #include #include #include - +#include "greybus.h" static const struct usb_device_id id_table[] = { { USB_DEVICE(0x0000, 0x0000) }, // FIXME @@ -34,6 +34,68 @@ struct es1_ap_dev { */ static struct es1_ap_dev *es1_ap_dev; +static void ap_in_callback(struct urb *urb) +{ + struct device *dev = &urb->dev->dev; + int status = urb->status; + int retval; + + switch (status) { + case 0: + break; + case -EOVERFLOW: + dev_err(dev, "%s: overflow actual length is %d\n", + __func__, urb->actual_length); + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + case -EILSEQ: + /* device is gone, stop sending */ + return; + default: + dev_err(dev, "%s: unknown status %d\n", __func__, status); + goto exit; + } + + /* We have a message, create a new message structure, add it to the + * list, and wake up our thread that will process the messages. + */ + gb_new_ap_msg(urb->transfer_buffer, urb->actual_length); + +exit: + /* resubmit the urb to get more messages */ + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) + dev_err(dev, "Can not submit urb for AP data: %d\n", retval); +} + +static void ap_out_callback(struct urb *urb) +{ + struct device *dev = &urb->dev->dev; + int status = urb->status; + + switch (status) { + case 0: + break; + case -EOVERFLOW: + dev_err(dev, "%s: overflow actual length is %d\n", + __func__, urb->actual_length); + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + case -EILSEQ: + /* device is gone, stop sending */ + return; + default: + dev_err(dev, "%s: unknown status %d\n", __func__, status); + goto exit; + } + + // FIXME - queue up next AP message to send??? +exit: + return; +} + static int ap_probe(struct usb_interface *interface, const struct usb_device_id *id) diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 7ce8c6e..9b0b41b 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -176,8 +176,16 @@ void greybus_deregister(struct greybus_driver *driver); int greybus_disabled(void); -int greybus_debugfs_init(void); -void greybus_debugfs_cleanup(void); + +/* Internal functions to gb module, move to internal .h file eventually. */ + +int gb_new_ap_msg(u8 *data, int length); +int gb_thread_init(void); +void gb_thread_destroy(void); +int gb_debugfs_init(void); +void gb_debugfs_cleanup(void); + + #endif /* __KERNEL__ */ #endif /* __LINUX_GREYBUS_H */ -- cgit v0.10.2 From be1e2e9cd12de6611939d37b468c2ef1939225b2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 31 Aug 2014 16:21:33 -0700 Subject: greybus: structures added diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 5189e8e..39b83c5 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -18,6 +18,21 @@ #include #include "greybus.h" +/* + * AP <-> SVC message structure format: + * + * + * + */ +struct svc_msg { + u8 function; + u8 type; + u8 version_major; + u8 version_minor; + u16 payload_length; +}; + + struct ap_msg { u8 *data; int size; -- cgit v0.10.2 From 2ecd536de70997a1975fa5547185f0c4e70db203 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 31 Aug 2014 17:25:22 -0700 Subject: greybus: more structure definitions added diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 39b83c5..3741428 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -24,14 +24,135 @@ * * */ -struct svc_msg { +enum svc_function_type { + SVC_FUNCTION_HANDSHAKE = 0x00, + SVC_FUNCTION_UNIPRO_NETWORK_MANAGEMENT = 0x01, + SVC_FUNCTION_HOTPLUG = 0x02, + SVC_FUNCTION_DDB = 0x03, + SVC_FUNCTION_POWER = 0x04, + SVC_FUNCTION_EPM = 0x05, + SVC_FUNCTION_SUSPEND = 0x06, +}; + +struct svc_msg_header { u8 function; - u8 type; + u8 type; /* enum svc_function_type */ u8 version_major; u8 version_minor; u16 payload_length; }; +enum svc_function_handshake_type { + SVC_HANDSHAKE_SVC_HELLO = 0x00, + SVC_HANDSHAKE_AP_HELLO = 0x01, + SVC_HANDSHAKE_MODULE_HELLO = 0x02, +}; + +struct svc_function_handshake { + u8 handshake_type; /* enum svc_function_handshake_type */ +}; + +struct svc_function_unipro_set_route { + u8 source_device_id; + u8 source_cport_id; + u8 destination_device_id; + u8 destination_cport_id; +}; + +struct svc_function_unipro_link_up { + u8 device_id; +}; + +enum svc_function_management_event { + SVC_MANAGEMENT_SET_ROUTE = 0x00, + SVC_MANAGEMENT_LINK_UP = 0x01, +}; + +struct svc_function_unipro_management { + u8 management_packet_type; /* enum svc_function_management_event */ + union { + struct svc_function_unipro_set_route set_route; + struct svc_function_unipro_link_up link_up; + }; +}; + +enum svc_function_hotplug_event { + SVC_HOTPLUG_EVENT = 0x00, + SVC_HOTUNPLUG_EVENT = 0x01, +}; + +struct svc_function_hotplug { + u8 hotplug_event; /* enum svc_function_hotplug_event */ + u8 device_id; +}; + +enum svc_function_ddb_type { + SVC_DDB_GET = 0x00, + SVC_DDB_RESPONSE = 0x01, +}; + +struct svc_function_ddb_get { + u8 device_id; + u8 message_id; +}; + +struct svc_function_ddb_response { + u8 device_id; + u8 message_id; + u16 descriptor_length; + u8 ddb[0]; +}; + +struct svc_function_ddb { + u8 ddb_type; /* enum svc_function_ddb_type */ + union { + struct svc_function_ddb_get ddb_get; + struct svc_function_ddb_response ddb_response; + }; +}; + +enum svc_function_power_type { + SVC_POWER_BATTERY_STATUS = 0x00, + SVC_POWER_BATTERY_STATUS_REQUEST = 0x01, +}; + +enum svc_function_battery_status { + SVC_BATTERY_UNKNOWN = 0x00, + SVC_BATTERY_CHARGING = 0x01, + SVC_BATTERY_DISCHARGING = 0x02, + SVC_BATTERY_NOT_CHARGING = 0x03, + SVC_BATTERY_FULL = 0x04, +}; + +struct svc_function_power_battery_status { + u16 charge_full; + u16 charge_now; + u8 status; /* enum svc_function_battery_status */ +}; + +struct svc_function_power_battery_status_request { + +}; + +struct svc_function_power { + u8 power_type; /* enum svc_function_power_type */ + union { + struct svc_function_power_battery_status status; + struct svc_function_power_battery_status_request request; + }; +}; + +struct svc_msg { + struct svc_msg_header header; + union { + struct svc_function_handshake handshake; + struct svc_function_unipro_management management; + struct svc_function_hotplug hotplug; + struct svc_function_ddb ddb; + u8 data[0]; + }; +}; + struct ap_msg { u8 *data; -- cgit v0.10.2 From b9b2a46265a16702dd77a55f7b7434d27823e702 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 31 Aug 2014 17:43:38 -0700 Subject: greybus: split svc msg out into separate header file diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 3741428..2d63b5c 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -16,143 +16,9 @@ #include #include #include +#include "svc_msg.h" #include "greybus.h" -/* - * AP <-> SVC message structure format: - * - * - * - */ -enum svc_function_type { - SVC_FUNCTION_HANDSHAKE = 0x00, - SVC_FUNCTION_UNIPRO_NETWORK_MANAGEMENT = 0x01, - SVC_FUNCTION_HOTPLUG = 0x02, - SVC_FUNCTION_DDB = 0x03, - SVC_FUNCTION_POWER = 0x04, - SVC_FUNCTION_EPM = 0x05, - SVC_FUNCTION_SUSPEND = 0x06, -}; - -struct svc_msg_header { - u8 function; - u8 type; /* enum svc_function_type */ - u8 version_major; - u8 version_minor; - u16 payload_length; -}; - -enum svc_function_handshake_type { - SVC_HANDSHAKE_SVC_HELLO = 0x00, - SVC_HANDSHAKE_AP_HELLO = 0x01, - SVC_HANDSHAKE_MODULE_HELLO = 0x02, -}; - -struct svc_function_handshake { - u8 handshake_type; /* enum svc_function_handshake_type */ -}; - -struct svc_function_unipro_set_route { - u8 source_device_id; - u8 source_cport_id; - u8 destination_device_id; - u8 destination_cport_id; -}; - -struct svc_function_unipro_link_up { - u8 device_id; -}; - -enum svc_function_management_event { - SVC_MANAGEMENT_SET_ROUTE = 0x00, - SVC_MANAGEMENT_LINK_UP = 0x01, -}; - -struct svc_function_unipro_management { - u8 management_packet_type; /* enum svc_function_management_event */ - union { - struct svc_function_unipro_set_route set_route; - struct svc_function_unipro_link_up link_up; - }; -}; - -enum svc_function_hotplug_event { - SVC_HOTPLUG_EVENT = 0x00, - SVC_HOTUNPLUG_EVENT = 0x01, -}; - -struct svc_function_hotplug { - u8 hotplug_event; /* enum svc_function_hotplug_event */ - u8 device_id; -}; - -enum svc_function_ddb_type { - SVC_DDB_GET = 0x00, - SVC_DDB_RESPONSE = 0x01, -}; - -struct svc_function_ddb_get { - u8 device_id; - u8 message_id; -}; - -struct svc_function_ddb_response { - u8 device_id; - u8 message_id; - u16 descriptor_length; - u8 ddb[0]; -}; - -struct svc_function_ddb { - u8 ddb_type; /* enum svc_function_ddb_type */ - union { - struct svc_function_ddb_get ddb_get; - struct svc_function_ddb_response ddb_response; - }; -}; - -enum svc_function_power_type { - SVC_POWER_BATTERY_STATUS = 0x00, - SVC_POWER_BATTERY_STATUS_REQUEST = 0x01, -}; - -enum svc_function_battery_status { - SVC_BATTERY_UNKNOWN = 0x00, - SVC_BATTERY_CHARGING = 0x01, - SVC_BATTERY_DISCHARGING = 0x02, - SVC_BATTERY_NOT_CHARGING = 0x03, - SVC_BATTERY_FULL = 0x04, -}; - -struct svc_function_power_battery_status { - u16 charge_full; - u16 charge_now; - u8 status; /* enum svc_function_battery_status */ -}; - -struct svc_function_power_battery_status_request { - -}; - -struct svc_function_power { - u8 power_type; /* enum svc_function_power_type */ - union { - struct svc_function_power_battery_status status; - struct svc_function_power_battery_status_request request; - }; -}; - -struct svc_msg { - struct svc_msg_header header; - union { - struct svc_function_handshake handshake; - struct svc_function_unipro_management management; - struct svc_function_hotplug hotplug; - struct svc_function_ddb ddb; - u8 data[0]; - }; -}; - struct ap_msg { u8 *data; diff --git a/drivers/staging/greybus/svc_msg.h b/drivers/staging/greybus/svc_msg.h new file mode 100644 index 0000000..3f97a5e --- /dev/null +++ b/drivers/staging/greybus/svc_msg.h @@ -0,0 +1,162 @@ +/* + * Greybus AP <-> SVC message structure format. + * + * Defined in the "Greybus Application Protocol" document. + * See that document for any details on these values and structures. + * + * Copyright 2014 Google Inc. + */ +enum svc_function_type { + SVC_FUNCTION_HANDSHAKE = 0x00, + SVC_FUNCTION_UNIPRO_NETWORK_MANAGEMENT = 0x01, + SVC_FUNCTION_HOTPLUG = 0x02, + SVC_FUNCTION_DDB = 0x03, + SVC_FUNCTION_POWER = 0x04, + SVC_FUNCTION_EPM = 0x05, + SVC_FUNCTION_SUSPEND = 0x06, +}; + +struct svc_msg_header { + u8 function; + u8 type; /* enum svc_function_type */ + u8 version_major; + u8 version_minor; + u16 payload_length; +}; + +enum svc_function_handshake_type { + SVC_HANDSHAKE_SVC_HELLO = 0x00, + SVC_HANDSHAKE_AP_HELLO = 0x01, + SVC_HANDSHAKE_MODULE_HELLO = 0x02, +}; + +struct svc_function_handshake { + u8 handshake_type; /* enum svc_function_handshake_type */ +}; + +struct svc_function_unipro_set_route { + u8 source_device_id; + u8 source_cport_id; + u8 destination_device_id; + u8 destination_cport_id; +}; + +struct svc_function_unipro_link_up { + u8 device_id; +}; + +enum svc_function_management_event { + SVC_MANAGEMENT_SET_ROUTE = 0x00, + SVC_MANAGEMENT_LINK_UP = 0x01, +}; + +struct svc_function_unipro_management { + u8 management_packet_type; /* enum svc_function_management_event */ + union { + struct svc_function_unipro_set_route set_route; + struct svc_function_unipro_link_up link_up; + }; +}; + +enum svc_function_hotplug_event { + SVC_HOTPLUG_EVENT = 0x00, + SVC_HOTUNPLUG_EVENT = 0x01, +}; + +struct svc_function_hotplug { + u8 hotplug_event; /* enum svc_function_hotplug_event */ + u8 device_id; +}; + +enum svc_function_ddb_type { + SVC_DDB_GET = 0x00, + SVC_DDB_RESPONSE = 0x01, +}; + +struct svc_function_ddb_get { + u8 device_id; + u8 message_id; +}; + +struct svc_function_ddb_response { + u8 device_id; + u8 message_id; + u16 descriptor_length; + u8 ddb[0]; +}; + +struct svc_function_ddb { + u8 ddb_type; /* enum svc_function_ddb_type */ + union { + struct svc_function_ddb_get ddb_get; + struct svc_function_ddb_response ddb_response; + }; +}; + +enum svc_function_power_type { + SVC_POWER_BATTERY_STATUS = 0x00, + SVC_POWER_BATTERY_STATUS_REQUEST = 0x01, +}; + +enum svc_function_battery_status { + SVC_BATTERY_UNKNOWN = 0x00, + SVC_BATTERY_CHARGING = 0x01, + SVC_BATTERY_DISCHARGING = 0x02, + SVC_BATTERY_NOT_CHARGING = 0x03, + SVC_BATTERY_FULL = 0x04, +}; + +struct svc_function_power_battery_status { + u16 charge_full; + u16 charge_now; + u8 status; /* enum svc_function_battery_status */ +}; + +struct svc_function_power_battery_status_request { + u8 epm_command_type; /* enum svc_function_epm_command_type */ + u8 device_id; +}; + +struct svc_function_power { + u8 power_type; /* enum svc_function_power_type */ + union { + struct svc_function_power_battery_status status; + struct svc_function_power_battery_status_request request; + }; +}; + +enum svc_function_epm_command_type { + SVC_EPM_ENABLE = 0x00, + SVC_EPM_DISABLE = 0x01, +}; + +struct svc_function_epm { + u8 epm_command_type; /* enum svc_function_epm_command_type */ + u8 device_id; +}; + +enum svc_function_suspend_command_type { + SVC_SUSPEND_FIXME_1 = 0x00, // FIXME + SVC_SUSPEND_FIXME_2 = 0x01, +}; + +struct svc_function_suspend { + u8 suspend_command_type; /* enum function_suspend_command_type */ + u8 device_id; +}; + +struct svc_msg { + struct svc_msg_header header; + union { + struct svc_function_handshake handshake; + struct svc_function_unipro_management management; + struct svc_function_hotplug hotplug; + struct svc_function_ddb ddb; + struct svc_function_power power; + struct svc_function_epm epm; + struct svc_function_suspend suspend; + }; +}; + + + -- cgit v0.10.2 From 80ebe8a63134f4418765d6ae9ddcba7427094da8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 31 Aug 2014 18:08:52 -0700 Subject: greybus: greybus_desc.h created diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 2d63b5c..e2b6063 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -17,9 +17,9 @@ #include #include #include "svc_msg.h" +#include "greybus_desc.h" #include "greybus.h" - struct ap_msg { u8 *data; int size; diff --git a/drivers/staging/greybus/greybus_desc.h b/drivers/staging/greybus/greybus_desc.h new file mode 100644 index 0000000..6a3674d --- /dev/null +++ b/drivers/staging/greybus/greybus_desc.h @@ -0,0 +1,95 @@ +/* + * Greybus device descriptor definition + * + * Defined in the "Greybus Application Protocol" document. + * See that document for any details on these values and structures. + * + * Copyright 2014 Google Inc. + */ + +#ifndef __GREYBUS_DESC_H +#define __GREYBUS_DESC_H + +struct greybus_decriptor_block_header { + __le16 size; + u8 version_major; + u8 version_minor; +}; + +enum greybus_descriptor_type { + GREYBUS_TYPE_INVALID = 0x0000, + GREYBUS_TYPE_DEVICE_ID = 0x0001, + GREYBUS_TYPE_SERIAL_NUMBER = 0x0002, + GREYBUS_TYPE_DEVICE_STRING = 0x0003, + GREYBUS_TYPE_CPORT = 0x0004, + GREYBUS_TYPE_FUNCTION = 0x0005, +}; + +struct greybus_descriptor_header { + __le16 size; + __le16 type; /* enum greybus_descriptor_type */ +}; + + +struct greybus_descriptor_deviceid { + __le16 vendor; + __le16 product; + __le16 version; + u8 vendor_stringid; + u8 product_stringid; +}; + +struct greybus_descriptor_serial_number { + __le64 serial_number; +}; + +struct greybus_descriptor_string { + u8 id; + __le16 length; + u8 string[0]; +}; + +struct greybus_descriptor_cport { + __le16 number; + u8 speed; // FIXME + u8 reserved; +}; + +enum greybus_function_class { + GREYBUS_FUNCTION_CONTROL = 0x00, + GREYBUS_FUNCTION_USB = 0x01, + GREYBUS_FUNCTION_GPIO = 0x02, + GREYBUS_FUNCTION_SPI = 0x03, + GREYBUS_FUNCTION_UART = 0x04, + GREYBUS_FUNCTION_PWM = 0x05, + GREYBUS_FUNCTION_I2S = 0x06, + GREYBUS_FUNCTION_I2C = 0x07, + GREYBUS_FUNCTION_SDIO = 0x08, + GREYBUS_FUNCTION_HID = 0x09, + GREYBUS_FUNCTION_DISPLAY = 0x0a, + GREYBUS_FUNCTION_CAMERA = 0x0b, + GREYBUS_FUNCTION_SENSOR = 0x0c, + GREYBUS_FUNCTION_VENDOR = 0xff, +}; + +struct greybus_descriptor_function { + __le16 number; + __le16 cport; + u8 function_class; /* enum greybus_function_class */ + u8 function_subclass; + u8 function_protocol; + u8 reserved; +}; + +struct greybus_msg_descriptor { + struct greybus_descriptor_header header; + union { + struct greybus_descriptor_deviceid device_id; + struct greybus_descriptor_serial_number serial_number; + struct greybus_descriptor_string string; + struct greybus_descriptor_cport cport; + struct greybus_descriptor_function function; + }; +}; + +#endif /* __GREYBUS_DESC_H */ diff --git a/drivers/staging/greybus/svc_msg.h b/drivers/staging/greybus/svc_msg.h index 3f97a5e..f97b22c 100644 --- a/drivers/staging/greybus/svc_msg.h +++ b/drivers/staging/greybus/svc_msg.h @@ -6,6 +6,10 @@ * * Copyright 2014 Google Inc. */ + +#ifndef __SVC_MSG_H +#define __SVC_MSG_H + enum svc_function_type { SVC_FUNCTION_HANDSHAKE = 0x00, SVC_FUNCTION_UNIPRO_NETWORK_MANAGEMENT = 0x01, @@ -21,7 +25,7 @@ struct svc_msg_header { u8 type; /* enum svc_function_type */ u8 version_major; u8 version_minor; - u16 payload_length; + __le16 payload_length; }; enum svc_function_handshake_type { @@ -81,7 +85,7 @@ struct svc_function_ddb_get { struct svc_function_ddb_response { u8 device_id; u8 message_id; - u16 descriptor_length; + __le16 descriptor_length; u8 ddb[0]; }; @@ -107,8 +111,8 @@ enum svc_function_battery_status { }; struct svc_function_power_battery_status { - u16 charge_full; - u16 charge_now; + __le16 charge_full; + __le16 charge_now; u8 status; /* enum svc_function_battery_status */ }; @@ -158,5 +162,4 @@ struct svc_msg { }; }; - - +#endif /* __SVC_MSG_H */ -- cgit v0.10.2 From 3772f1610f4f61023019c5639e4e74fd03806f68 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 1 Sep 2014 09:51:33 -0700 Subject: greybus: header file s/u8/__u8/g diff --git a/drivers/staging/greybus/greybus_desc.h b/drivers/staging/greybus/greybus_desc.h index 6a3674d..30995e5 100644 --- a/drivers/staging/greybus/greybus_desc.h +++ b/drivers/staging/greybus/greybus_desc.h @@ -12,8 +12,8 @@ struct greybus_decriptor_block_header { __le16 size; - u8 version_major; - u8 version_minor; + __u8 version_major; + __u8 version_minor; }; enum greybus_descriptor_type { @@ -35,8 +35,8 @@ struct greybus_descriptor_deviceid { __le16 vendor; __le16 product; __le16 version; - u8 vendor_stringid; - u8 product_stringid; + __u8 vendor_stringid; + __u8 product_stringid; }; struct greybus_descriptor_serial_number { @@ -44,15 +44,15 @@ struct greybus_descriptor_serial_number { }; struct greybus_descriptor_string { - u8 id; + __u8 id; __le16 length; - u8 string[0]; + __u8 string[0]; }; struct greybus_descriptor_cport { __le16 number; - u8 speed; // FIXME - u8 reserved; + __u8 speed; // FIXME + __u8 reserved; }; enum greybus_function_class { @@ -75,10 +75,10 @@ enum greybus_function_class { struct greybus_descriptor_function { __le16 number; __le16 cport; - u8 function_class; /* enum greybus_function_class */ - u8 function_subclass; - u8 function_protocol; - u8 reserved; + __u8 function_class; /* enum greybus_function_class */ + __u8 function_subclass; + __u8 function_protocol; + __u8 reserved; }; struct greybus_msg_descriptor { diff --git a/drivers/staging/greybus/svc_msg.h b/drivers/staging/greybus/svc_msg.h index f97b22c..3b4fd0d 100644 --- a/drivers/staging/greybus/svc_msg.h +++ b/drivers/staging/greybus/svc_msg.h @@ -21,10 +21,10 @@ enum svc_function_type { }; struct svc_msg_header { - u8 function; - u8 type; /* enum svc_function_type */ - u8 version_major; - u8 version_minor; + __u8 function; + __u8 type; /* enum svc_function_type */ + __u8 version_major; + __u8 version_minor; __le16 payload_length; }; @@ -35,18 +35,18 @@ enum svc_function_handshake_type { }; struct svc_function_handshake { - u8 handshake_type; /* enum svc_function_handshake_type */ + __u8 handshake_type; /* enum svc_function_handshake_type */ }; struct svc_function_unipro_set_route { - u8 source_device_id; - u8 source_cport_id; - u8 destination_device_id; - u8 destination_cport_id; + __u8 source_device_id; + __u8 source_cport_id; + __u8 destination_device_id; + __u8 destination_cport_id; }; struct svc_function_unipro_link_up { - u8 device_id; + __u8 device_id; }; enum svc_function_management_event { @@ -55,7 +55,7 @@ enum svc_function_management_event { }; struct svc_function_unipro_management { - u8 management_packet_type; /* enum svc_function_management_event */ + __u8 management_packet_type; /* enum svc_function_management_event */ union { struct svc_function_unipro_set_route set_route; struct svc_function_unipro_link_up link_up; @@ -68,8 +68,8 @@ enum svc_function_hotplug_event { }; struct svc_function_hotplug { - u8 hotplug_event; /* enum svc_function_hotplug_event */ - u8 device_id; + __u8 hotplug_event; /* enum svc_function_hotplug_event */ + __u8 device_id; }; enum svc_function_ddb_type { @@ -78,19 +78,19 @@ enum svc_function_ddb_type { }; struct svc_function_ddb_get { - u8 device_id; - u8 message_id; + __u8 device_id; + __u8 message_id; }; struct svc_function_ddb_response { - u8 device_id; - u8 message_id; + __u8 device_id; + __u8 message_id; __le16 descriptor_length; - u8 ddb[0]; + __u8 ddb[0]; }; struct svc_function_ddb { - u8 ddb_type; /* enum svc_function_ddb_type */ + __u8 ddb_type; /* enum svc_function_ddb_type */ union { struct svc_function_ddb_get ddb_get; struct svc_function_ddb_response ddb_response; @@ -113,16 +113,16 @@ enum svc_function_battery_status { struct svc_function_power_battery_status { __le16 charge_full; __le16 charge_now; - u8 status; /* enum svc_function_battery_status */ + __u8 status; /* enum svc_function_battery_status */ }; struct svc_function_power_battery_status_request { - u8 epm_command_type; /* enum svc_function_epm_command_type */ - u8 device_id; + __u8 epm_command_type; /* enum svc_function_epm_command_type */ + __u8 device_id; }; struct svc_function_power { - u8 power_type; /* enum svc_function_power_type */ + __u8 power_type; /* enum svc_function_power_type */ union { struct svc_function_power_battery_status status; struct svc_function_power_battery_status_request request; @@ -135,8 +135,8 @@ enum svc_function_epm_command_type { }; struct svc_function_epm { - u8 epm_command_type; /* enum svc_function_epm_command_type */ - u8 device_id; + __u8 epm_command_type; /* enum svc_function_epm_command_type */ + __u8 device_id; }; enum svc_function_suspend_command_type { @@ -145,8 +145,8 @@ enum svc_function_suspend_command_type { }; struct svc_function_suspend { - u8 suspend_command_type; /* enum function_suspend_command_type */ - u8 device_id; + __u8 suspend_command_type; /* enum function_suspend_command_type */ + __u8 device_id; }; struct svc_msg { -- cgit v0.10.2 From 712d65915a3ad5bffaa8cd97e6dd951e1d10eabd Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 1 Sep 2014 09:51:51 -0700 Subject: greybus: greybus.h: tiny movement around diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 9b0b41b..f878453 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -102,23 +102,6 @@ struct greybus_device { }; #define to_greybus_device(d) container_of(d, struct greybus_device, dev) -/* - * Because we are allocating a data structure per "type" in the greybus device, - * we have static functions for this, not "dynamic" drivers like we really - * should in the end. - */ -int gb_i2c_probe(struct greybus_device *gdev, const struct greybus_device_id *id); -void gb_i2c_disconnect(struct greybus_device *gdev); -int gb_gpio_probe(struct greybus_device *gdev, const struct greybus_device_id *id); -void gb_gpio_disconnect(struct greybus_device *gdev); -int gb_sdio_probe(struct greybus_device *gdev, const struct greybus_device_id *id); -void gb_sdio_disconnect(struct greybus_device *gdev); -int gb_tty_probe(struct greybus_device *gdev, const struct greybus_device_id *id); -void gb_tty_disconnect(struct greybus_device *gdev); - -int gb_tty_init(void); -void gb_tty_exit(void); - struct gbuf *greybus_alloc_gbuf(struct greybus_device *gdev, struct cport *cport, gfp_t mem_flags); @@ -185,6 +168,23 @@ void gb_thread_destroy(void); int gb_debugfs_init(void); void gb_debugfs_cleanup(void); +/* + * Because we are allocating a data structure per "type" in the greybus device, + * we have static functions for this, not "dynamic" drivers like we really + * should in the end. + */ +int gb_i2c_probe(struct greybus_device *gdev, const struct greybus_device_id *id); +void gb_i2c_disconnect(struct greybus_device *gdev); +int gb_gpio_probe(struct greybus_device *gdev, const struct greybus_device_id *id); +void gb_gpio_disconnect(struct greybus_device *gdev); +int gb_sdio_probe(struct greybus_device *gdev, const struct greybus_device_id *id); +void gb_sdio_disconnect(struct greybus_device *gdev); +int gb_tty_probe(struct greybus_device *gdev, const struct greybus_device_id *id); +void gb_tty_disconnect(struct greybus_device *gdev); + +int gb_tty_init(void); +void gb_tty_exit(void); + #endif /* __KERNEL__ */ -- cgit v0.10.2 From d58778002b303bd1915b7e38084feb9df1ea3361 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 1 Sep 2014 10:59:08 -0700 Subject: greybus: more changes due to name changes in the greybus document diff --git a/drivers/staging/greybus/greybus_desc.h b/drivers/staging/greybus/greybus_desc.h index 30995e5..ae962d5 100644 --- a/drivers/staging/greybus/greybus_desc.h +++ b/drivers/staging/greybus/greybus_desc.h @@ -18,11 +18,11 @@ struct greybus_decriptor_block_header { enum greybus_descriptor_type { GREYBUS_TYPE_INVALID = 0x0000, - GREYBUS_TYPE_DEVICE_ID = 0x0001, - GREYBUS_TYPE_SERIAL_NUMBER = 0x0002, - GREYBUS_TYPE_DEVICE_STRING = 0x0003, - GREYBUS_TYPE_CPORT = 0x0004, - GREYBUS_TYPE_FUNCTION = 0x0005, + GREYBUS_TYPE_FUNCTION = 0x0001, + GREYBUS_TYPE_MODULE_ID = 0x0002, + GREYBUS_TYPE_SERIAL_NUMBER = 0x0003, + GREYBUS_TYPE_DEVICE_STRING = 0x0004, + GREYBUS_TYPE_CPORT = 0x0005, }; struct greybus_descriptor_header { @@ -30,31 +30,6 @@ struct greybus_descriptor_header { __le16 type; /* enum greybus_descriptor_type */ }; - -struct greybus_descriptor_deviceid { - __le16 vendor; - __le16 product; - __le16 version; - __u8 vendor_stringid; - __u8 product_stringid; -}; - -struct greybus_descriptor_serial_number { - __le64 serial_number; -}; - -struct greybus_descriptor_string { - __u8 id; - __le16 length; - __u8 string[0]; -}; - -struct greybus_descriptor_cport { - __le16 number; - __u8 speed; // FIXME - __u8 reserved; -}; - enum greybus_function_class { GREYBUS_FUNCTION_CONTROL = 0x00, GREYBUS_FUNCTION_USB = 0x01, @@ -81,14 +56,39 @@ struct greybus_descriptor_function { __u8 reserved; }; +struct greybus_descriptor_module_id { + __le16 vendor; + __le16 product; + __le16 version; + __u8 vendor_stringid; + __u8 product_stringid; +}; + +struct greybus_descriptor_serial_number { + __le64 serial_number; +}; + +struct greybus_descriptor_string { + __le16 length; + __u8 id; + __u8 string[0]; +}; + +struct greybus_descriptor_cport { + __le16 number; + __le16 size; + __u8 speed; // FIXME + __u8 reserved; +}; + struct greybus_msg_descriptor { struct greybus_descriptor_header header; union { - struct greybus_descriptor_deviceid device_id; + struct greybus_descriptor_function function; + struct greybus_descriptor_module_id module_id; struct greybus_descriptor_serial_number serial_number; struct greybus_descriptor_string string; struct greybus_descriptor_cport cport; - struct greybus_descriptor_function function; }; }; diff --git a/drivers/staging/greybus/svc_msg.h b/drivers/staging/greybus/svc_msg.h index 3b4fd0d..d992f3c 100644 --- a/drivers/staging/greybus/svc_msg.h +++ b/drivers/staging/greybus/svc_msg.h @@ -39,14 +39,14 @@ struct svc_function_handshake { }; struct svc_function_unipro_set_route { - __u8 source_device_id; + __u8 source_module_id; __u8 source_cport_id; - __u8 destination_device_id; + __u8 destination_module_id; __u8 destination_cport_id; }; struct svc_function_unipro_link_up { - __u8 device_id; + __u8 module_id; }; enum svc_function_management_event { @@ -69,7 +69,7 @@ enum svc_function_hotplug_event { struct svc_function_hotplug { __u8 hotplug_event; /* enum svc_function_hotplug_event */ - __u8 device_id; + __u8 module_id; }; enum svc_function_ddb_type { @@ -78,12 +78,12 @@ enum svc_function_ddb_type { }; struct svc_function_ddb_get { - __u8 device_id; + __u8 module_id; __u8 message_id; }; struct svc_function_ddb_response { - __u8 device_id; + __u8 module_id; __u8 message_id; __le16 descriptor_length; __u8 ddb[0]; @@ -117,12 +117,11 @@ struct svc_function_power_battery_status { }; struct svc_function_power_battery_status_request { - __u8 epm_command_type; /* enum svc_function_epm_command_type */ - __u8 device_id; }; struct svc_function_power { __u8 power_type; /* enum svc_function_power_type */ + __u8 module_id; union { struct svc_function_power_battery_status status; struct svc_function_power_battery_status_request request; @@ -136,7 +135,7 @@ enum svc_function_epm_command_type { struct svc_function_epm { __u8 epm_command_type; /* enum svc_function_epm_command_type */ - __u8 device_id; + __u8 module_id; }; enum svc_function_suspend_command_type { @@ -146,7 +145,7 @@ enum svc_function_suspend_command_type { struct svc_function_suspend { __u8 suspend_command_type; /* enum function_suspend_command_type */ - __u8 device_id; + __u8 module_id; }; struct svc_msg { -- cgit v0.10.2 From 6584c8af7045d12249ebbe34b1e370d972abb0ff Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 1 Sep 2014 13:31:31 -0700 Subject: greybus: s/greybus_device_id/greybus_module_id/g diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 887aa60..e41689f 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -31,7 +31,7 @@ int greybus_disabled(void) EXPORT_SYMBOL_GPL(greybus_disabled); static int greybus_match_one_id(struct greybus_device *gdev, - const struct greybus_device_id *id) + const struct greybus_module_id *id) { struct greybus_descriptor *des = &gdev->descriptor; @@ -50,9 +50,9 @@ static int greybus_match_one_id(struct greybus_device *gdev, return 1; } -static const struct greybus_device_id *greybus_match_id( +static const struct greybus_module_id *greybus_match_id( struct greybus_device *gdev, - const struct greybus_device_id *id) + const struct greybus_module_id *id) { if (id == NULL) return NULL; @@ -70,7 +70,7 @@ static int greybus_device_match(struct device *dev, struct device_driver *drv) { struct greybus_driver *driver = to_greybus_driver(dev->driver); struct greybus_device *gdev = to_greybus_device(dev); - const struct greybus_device_id *id; + const struct greybus_module_id *id; id = greybus_match_id(gdev, driver->id_table); if (id) @@ -97,7 +97,7 @@ static int greybus_probe(struct device *dev) { struct greybus_driver *driver = to_greybus_driver(dev->driver); struct greybus_device *gdev = to_greybus_device(dev); - const struct greybus_device_id *id; + const struct greybus_module_id *id; int retval; /* match id */ @@ -152,7 +152,7 @@ EXPORT_SYMBOL_GPL(greybus_deregister); static int new_device(struct greybus_device *gdev, - const struct greybus_device_id *id) + const struct greybus_module_id *id) { int retval; diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index 2047794..c4cb6a2 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -20,7 +20,7 @@ struct gb_gpio_device { // FIXME - some lock? }; -static const struct greybus_device_id id_table[] = { +static const struct greybus_module_id id_table[] = { { GREYBUS_DEVICE(0x44, 0x44) }, /* make shit up */ { }, /* terminating NULL entry */ }; @@ -52,7 +52,7 @@ static void gpio_set(struct gpio_chip *gpio, unsigned nr, int val) } int gb_gpio_probe(struct greybus_device *gdev, - const struct greybus_device_id *id) + const struct greybus_module_id *id) { struct gb_gpio_device *gb_gpio; struct gpio_chip *gpio; diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index f878453..45720ce 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -115,13 +115,13 @@ struct greybus_driver { const char *name; int (*probe)(struct greybus_device *gdev, - const struct greybus_device_id *id); + const struct greybus_module_id *id); void (*disconnect)(struct greybus_device *gdev); int (*suspend)(struct greybus_device *gdev, pm_message_t message); int (*resume)(struct greybus_device *gdev); - const struct greybus_device_id *id_table; + const struct greybus_module_id *id_table; struct device_driver driver; }; @@ -173,13 +173,13 @@ void gb_debugfs_cleanup(void); * we have static functions for this, not "dynamic" drivers like we really * should in the end. */ -int gb_i2c_probe(struct greybus_device *gdev, const struct greybus_device_id *id); +int gb_i2c_probe(struct greybus_device *gdev, const struct greybus_module_id *id); void gb_i2c_disconnect(struct greybus_device *gdev); -int gb_gpio_probe(struct greybus_device *gdev, const struct greybus_device_id *id); +int gb_gpio_probe(struct greybus_device *gdev, const struct greybus_module_id *id); void gb_gpio_disconnect(struct greybus_device *gdev); -int gb_sdio_probe(struct greybus_device *gdev, const struct greybus_device_id *id); +int gb_sdio_probe(struct greybus_device *gdev, const struct greybus_module_id *id); void gb_sdio_disconnect(struct greybus_device *gdev); -int gb_tty_probe(struct greybus_device *gdev, const struct greybus_device_id *id); +int gb_tty_probe(struct greybus_device *gdev, const struct greybus_module_id *id); void gb_tty_disconnect(struct greybus_device *gdev); int gb_tty_init(void); diff --git a/drivers/staging/greybus/greybus_id.h b/drivers/staging/greybus/greybus_id.h index 4afbfe2..b6fe26a 100644 --- a/drivers/staging/greybus/greybus_id.h +++ b/drivers/staging/greybus/greybus_id.h @@ -9,7 +9,7 @@ #include -struct greybus_device_id { +struct greybus_module_id { __u16 match_flags; __u16 wVendor; __u16 wProduct; diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index bb107f8..3c1d947 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -17,7 +17,7 @@ struct gb_i2c_device { struct greybus_device *gdev; }; -static const struct greybus_device_id id_table[] = { +static const struct greybus_module_id id_table[] = { { GREYBUS_DEVICE(0x42, 0x42) }, /* make shit up */ { }, /* terminating NULL entry */ }; @@ -76,7 +76,7 @@ static const struct i2c_algorithm smbus_algorithm = { }; int gb_i2c_probe(struct greybus_device *gdev, - const struct greybus_device_id *id) + const struct greybus_module_id *id) { struct gb_i2c_device *gb_i2c_dev; struct i2c_adapter *adapter; diff --git a/drivers/staging/greybus/sdio-gb.c b/drivers/staging/greybus/sdio-gb.c index 81eb33d..665767d 100644 --- a/drivers/staging/greybus/sdio-gb.c +++ b/drivers/staging/greybus/sdio-gb.c @@ -18,7 +18,7 @@ struct gb_sdio_host { // FIXME - some lock? }; -static const struct greybus_device_id id_table[] = { +static const struct greybus_module_id id_table[] = { { GREYBUS_DEVICE(0x43, 0x43) }, /* make shit up */ { }, /* terminating NULL entry */ }; @@ -46,7 +46,7 @@ static const struct mmc_host_ops gb_sd_ops = { }; int gb_sdio_probe(struct greybus_device *gdev, - const struct greybus_device_id *id) + const struct greybus_module_id *id) { struct mmc_host *mmc; struct gb_sdio_host *host; diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index f667b5c..d104d9c 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -46,7 +46,7 @@ struct gb_tty { struct mutex mutex; }; -static const struct greybus_device_id id_table[] = { +static const struct greybus_module_id id_table[] = { { GREYBUS_DEVICE(0x45, 0x45) }, /* make shit up */ { }, /* terminating NULL entry */ }; @@ -383,7 +383,7 @@ static const struct tty_operations gb_ops = { int gb_tty_probe(struct greybus_device *gdev, - const struct greybus_device_id *id) + const struct greybus_module_id *id) { struct gb_tty *gb_tty; struct device *tty_dev; -- cgit v0.10.2 From 6dca7b97c7e0d4ef71c0dad9a3ab939fb6a27033 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 1 Sep 2014 13:42:43 -0700 Subject: greybus: get field names right for descriptors diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index e41689f..c73b3ac 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -33,18 +33,22 @@ EXPORT_SYMBOL_GPL(greybus_disabled); static int greybus_match_one_id(struct greybus_device *gdev, const struct greybus_module_id *id) { - struct greybus_descriptor *des = &gdev->descriptor; + struct greybus_descriptor_module_id *module_id; + struct greybus_descriptor_serial_number *serial_num; + + module_id = &gdev->module_id; + serial_num = &gdev->serial_number; if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_VENDOR) && - (des->wVendor != id->wVendor)) + (id->vendor != le16_to_cpu(module_id->vendor))) return 0; if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_PRODUCT) && - (des->wProduct != id->wProduct)) + (id->product != le16_to_cpu(module_id->product))) return 0; if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_SERIAL) && - (des->lSerialNumber != id->lSerialNumber)) + (id->serial_number != le64_to_cpu(serial_num->serial_number))) return 0; return 1; @@ -57,7 +61,7 @@ static const struct greybus_module_id *greybus_match_id( if (id == NULL) return NULL; - for (; id->wVendor || id->wProduct || id->lSerialNumber || + for (; id->vendor || id->product || id->serial_number || id->driver_info ; id++) { if (greybus_match_one_id(gdev, id)) return id; @@ -151,7 +155,7 @@ void greybus_deregister(struct greybus_driver *driver) EXPORT_SYMBOL_GPL(greybus_deregister); -static int new_device(struct greybus_device *gdev, +int new_device(struct greybus_device *gdev, const struct greybus_module_id *id) { int retval; @@ -187,7 +191,7 @@ error_i2c: return retval; } -static void remove_device(struct greybus_device *gdev) +void remove_device(struct greybus_device *gdev) { /* tear down all of the "sub device types" for this device */ gb_i2c_disconnect(gdev); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 45720ce..b511c63 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -11,29 +11,26 @@ #ifdef __KERNEL__ +#include #include #include #include #include "greybus_id.h" +#include "greybus_desc.h" #define GREYBUS_DEVICE_ID_MATCH_DEVICE \ (GREYBUS_DEVICE_ID_MATCH_VENDOR | GREYBUS_DEVICE_ID_MATCH_PRODUCT) -#define GREYBUS_DEVICE(vendor, product) \ +#define GREYBUS_DEVICE(v, p) \ .match_flags = GREYBUS_DEVICE_ID_MATCH_DEVICE, \ - .wVendor = (vendor), \ - .wProduct = (product), + .vendor = (v), \ + .product = (p), -#define GREYBUS_DEVICE_SERIAL(serial) \ +#define GREYBUS_DEVICE_SERIAL(s) \ .match_flags = GREYBUS_DEVICE_ID_MATCH_SERIAL, \ - .lSerial = (serial), + .serial_number = (s), -struct greybus_descriptor { - __u16 wVendor; - __u16 wProduct; - __u64 lSerialNumber; -}; struct gbuf; @@ -90,7 +87,9 @@ struct gb_usb_device; struct greybus_device { struct device dev; - struct greybus_descriptor descriptor; + struct greybus_descriptor_function function; + struct greybus_descriptor_module_id module_id; + struct greybus_descriptor_serial_number serial_number; int num_cport; struct cport cport[0]; diff --git a/drivers/staging/greybus/greybus_desc.h b/drivers/staging/greybus/greybus_desc.h index ae962d5..48e2ec92 100644 --- a/drivers/staging/greybus/greybus_desc.h +++ b/drivers/staging/greybus/greybus_desc.h @@ -81,7 +81,7 @@ struct greybus_descriptor_cport { __u8 reserved; }; -struct greybus_msg_descriptor { +struct greybus_descriptor { struct greybus_descriptor_header header; union { struct greybus_descriptor_function function; diff --git a/drivers/staging/greybus/greybus_id.h b/drivers/staging/greybus/greybus_id.h index b6fe26a..83c4d05 100644 --- a/drivers/staging/greybus/greybus_id.h +++ b/drivers/staging/greybus/greybus_id.h @@ -11,9 +11,9 @@ struct greybus_module_id { __u16 match_flags; - __u16 wVendor; - __u16 wProduct; - __u64 lSerialNumber; + __u16 vendor; + __u16 product; + __u64 serial_number; kernel_ulong_t driver_info __attribute__((aligned(sizeof(kernel_ulong_t)))); -- cgit v0.10.2 From ec909874c7e0cfe81b8fd1c2a93c97f8a1086afc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 1 Sep 2014 14:39:14 -0700 Subject: greybus: turn off warnings for es1-ap-usb.c to make it easier to build for now... diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index abf9dfe..e7042d5 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -34,7 +34,7 @@ struct es1_ap_dev { */ static struct es1_ap_dev *es1_ap_dev; -static void ap_in_callback(struct urb *urb) +void ap_in_callback(struct urb *urb) { struct device *dev = &urb->dev->dev; int status = urb->status; @@ -69,7 +69,7 @@ exit: dev_err(dev, "Can not submit urb for AP data: %d\n", retval); } -static void ap_out_callback(struct urb *urb) +void ap_out_callback(struct urb *urb) { struct device *dev = &urb->dev->dev; int status = urb->status; -- cgit v0.10.2 From d94a44a54e9b2df3716e919763763e7095526e4b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 1 Sep 2014 14:39:34 -0700 Subject: greybus: export gb_new_ap_msg so that the es1 module can use it diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index e2b6063..5b06b19 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -106,6 +106,8 @@ int gb_new_ap_msg(u8 *data, int size) return 0; } +EXPORT_SYMBOL_GPL(gb_new_ap_msg); + int gb_thread_init(void) { -- cgit v0.10.2 From a239f67c5d3b443597e8dde92bd2d80dc59418a1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 1 Sep 2014 14:39:49 -0700 Subject: greybus: start parsing descriptor structures diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index c73b3ac..f4b562c 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -155,8 +156,8 @@ void greybus_deregister(struct greybus_driver *driver) EXPORT_SYMBOL_GPL(greybus_deregister); -int new_device(struct greybus_device *gdev, - const struct greybus_module_id *id) +static int gb_init_subdevs(struct greybus_device *gdev, + const struct greybus_module_id *id) { int retval; @@ -191,6 +192,118 @@ error_i2c: return retval; } +static const struct greybus_module_id fake_gb_id = + { GREYBUS_DEVICE(0x42, 0x42) }; + +/** + * greybus_new_device: + * + * Pass in a buffer that _should_ be a set of greybus descriptor fields and spit + * out a greybus device structure. + */ +struct greybus_device *greybus_new_device(int module_number, u8 *data, int size) +{ + struct greybus_device *gdev; + struct greybus_descriptor_block_header *block; + struct greybus_descriptor *desc; + int retval; + int overall_size; + int header_size; + int desc_size; + u8 version_major; + u8 version_minor; + + /* we have to have at _least_ the block header */ + if (size <= sizeof(struct greybus_descriptor_block_header)) + return NULL; + + gdev = kzalloc(sizeof(*gdev), GFP_KERNEL); + if (!gdev) + return NULL; + + gdev->module_number = module_number; + + block = (struct greybus_descriptor_block_header *)data; + overall_size = le16_to_cpu(block->size); + if (overall_size != size) { + pr_err("size != block header size, %d != %d\n", size, + overall_size); + goto error; + } + + version_major = block->version_major; + version_minor = block->version_minor; + + // FIXME - check version major/minor here! + + size -= sizeof(struct greybus_descriptor_block_header); + data += sizeof(struct greybus_descriptor_block_header); + while (size > 0) { + desc = (struct greybus_descriptor *)data; + desc_size = le16_to_cpu(desc->header.size); + + switch (desc->header.type) { + case GREYBUS_TYPE_FUNCTION: + header_size = + sizeof(struct greybus_descriptor_function); + if (desc_size != header_size) { + pr_err("invalid function header size %d\n", + desc_size); + goto error; + } + memcpy(&gdev->function, &desc->function, header_size); + size -= header_size; + data += header_size; + break; + + case GREYBUS_TYPE_MODULE_ID: + header_size = + sizeof(struct greybus_descriptor_module_id); + if (desc_size != header_size) { + pr_err("invalid module header size %d\n", + desc_size); + goto error; + } + memcpy(&gdev->module_id, &desc->module_id, header_size); + size -= header_size; + data += header_size; + break; + + case GREYBUS_TYPE_SERIAL_NUMBER: + header_size = + sizeof(struct greybus_descriptor_serial_number); + if (desc_size != header_size) { + pr_err("invalid serial number header size %d\n", + desc_size); + goto error; + } + memcpy(&gdev->serial_number, &desc->serial_number, + header_size); + size -= header_size; + data += header_size; + break; + + case GREYBUS_TYPE_DEVICE_STRING: + case GREYBUS_TYPE_CPORT: + case GREYBUS_TYPE_INVALID: + default: + pr_err("invalid descriptor type %d\n", desc->header.type); + goto error; + } +#if 0 + struct greybus_descriptor_string string; + struct greybus_descriptor_cport cport; +#endif + } + retval = gb_init_subdevs(gdev, &fake_gb_id); + if (retval) + goto error; + return gdev; +error: + kfree(gdev); + return NULL; +} + void remove_device(struct greybus_device *gdev) { /* tear down all of the "sub device types" for this device */ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index b511c63..93d7dae 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -37,6 +37,7 @@ struct gbuf; struct cport { u16 number; + u16 size; // FIXME, what else? }; @@ -87,11 +88,12 @@ struct gb_usb_device; struct greybus_device { struct device dev; + u16 module_number; struct greybus_descriptor_function function; struct greybus_descriptor_module_id module_id; struct greybus_descriptor_serial_number serial_number; int num_cport; - struct cport cport[0]; + struct cport *cport[10]; // FIXME - no more than 10 cports per device... struct gb_i2c_device *gb_i2c_dev; struct gb_gpio_device *gb_gpio_dev; diff --git a/drivers/staging/greybus/greybus_desc.h b/drivers/staging/greybus/greybus_desc.h index 48e2ec92..e7355a3 100644 --- a/drivers/staging/greybus/greybus_desc.h +++ b/drivers/staging/greybus/greybus_desc.h @@ -10,7 +10,7 @@ #ifndef __GREYBUS_DESC_H #define __GREYBUS_DESC_H -struct greybus_decriptor_block_header { +struct greybus_descriptor_block_header { __le16 size; __u8 version_major; __u8 version_minor; -- cgit v0.10.2 From 526c5c8d2393da2b74655f12687c30538c469825 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 1 Sep 2014 16:03:31 -0700 Subject: greybus: start parsing descriptor fields diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index f4b562c..9e9ffa0 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -195,6 +195,76 @@ error_i2c: static const struct greybus_module_id fake_gb_id = { GREYBUS_DEVICE(0x42, 0x42) }; +static int create_function(struct greybus_device *gdev, + struct greybus_descriptor *desc, int desc_size) +{ + int header_size = sizeof(struct greybus_descriptor_function); + + if (desc_size != header_size) { + pr_err("invalid function header size %d\n", desc_size); + return -EINVAL; + } + memcpy(&gdev->function, &desc->function, header_size); + return 0; +} + +static int create_module_id(struct greybus_device *gdev, + struct greybus_descriptor *desc, int desc_size) +{ + int header_size = sizeof(struct greybus_descriptor_module_id); + + if (desc_size != header_size) { + pr_err("invalid module header size %d\n", desc_size); + return -EINVAL; + } + memcpy(&gdev->module_id, &desc->module_id, header_size); + return 0; +} + +static int create_serial_number(struct greybus_device *gdev, + struct greybus_descriptor *desc, int desc_size) +{ + int header_size = sizeof(struct greybus_descriptor_serial_number); + + if (desc_size != header_size) { + pr_err("invalid serial number header size %d\n", desc_size); + return -EINVAL; + } + memcpy(&gdev->serial_number, &desc->serial_number, header_size); + return 0; +} + +static int create_string(struct greybus_device *gdev, + struct greybus_descriptor *desc, int desc_size) +{ + int string_size; + struct gdev_string *string; + int header_size = sizeof(struct greybus_descriptor_string); + + if ((gdev->num_strings + 1) >= MAX_STRINGS_PER_MODULE) { + pr_err("too many strings for this module!\n"); + return -EINVAL; + } + + if (desc_size < header_size) { + pr_err("invalid string header size %d\n", desc_size); + return -EINVAL; + } + + string_size = le16_to_cpu(desc->string.length); + string = kzalloc(sizeof(*string) + string_size + 1, GFP_KERNEL); + if (!string) + return -ENOMEM; + + string->length = string_size; + string->id = desc->string.id; + memcpy(&string->string, &desc->string.string, string_size); + gdev->string[gdev->num_strings] = string; + gdev->num_strings++; + + return 0; +} + /** * greybus_new_device: * @@ -210,6 +280,7 @@ struct greybus_device *greybus_new_device(int module_number, u8 *data, int size) int overall_size; int header_size; int desc_size; + int i; u8 version_major; u8 version_minor; @@ -244,62 +315,64 @@ struct greybus_device *greybus_new_device(int module_number, u8 *data, int size) switch (desc->header.type) { case GREYBUS_TYPE_FUNCTION: - header_size = - sizeof(struct greybus_descriptor_function); - if (desc_size != header_size) { - pr_err("invalid function header size %d\n", - desc_size); - goto error; - } - memcpy(&gdev->function, &desc->function, header_size); - size -= header_size; - data += header_size; + retval = create_function(gdev, desc, desc_size); break; case GREYBUS_TYPE_MODULE_ID: - header_size = - sizeof(struct greybus_descriptor_module_id); - if (desc_size != header_size) { - pr_err("invalid module header size %d\n", - desc_size); - goto error; - } - memcpy(&gdev->module_id, &desc->module_id, header_size); - size -= header_size; - data += header_size; + retval = create_module_id(gdev, desc, desc_size); break; case GREYBUS_TYPE_SERIAL_NUMBER: - header_size = - sizeof(struct greybus_descriptor_serial_number); + retval = create_serial_number(gdev, desc, desc_size); + break; + + case GREYBUS_TYPE_STRING: + retval = create_string(gdev, desc, desc_size); + break; + + case GREYBUS_TYPE_CPORT: { + struct gdev_cport *cport; + + header_size = sizeof(struct greybus_descriptor_cport); if (desc_size != header_size) { pr_err("invalid serial number header size %d\n", desc_size); goto error; } - memcpy(&gdev->serial_number, &desc->serial_number, - header_size); - size -= header_size; - data += header_size; + cport = kzalloc(sizeof(*cport), GFP_KERNEL); + if (!cport) + goto error; + cport->number = le16_to_cpu(desc->cport.number); + cport->size = le16_to_cpu(desc->cport.size); + cport->speed = desc->cport.speed; + gdev->cport[gdev->num_cports] = cport; + gdev->num_cports++; + // FIXME - check for too many cports... + + size -= desc_size; + data += desc_size; break; - - case GREYBUS_TYPE_DEVICE_STRING: - case GREYBUS_TYPE_CPORT: + } case GREYBUS_TYPE_INVALID: default: pr_err("invalid descriptor type %d\n", desc->header.type); goto error; } -#if 0 - struct greybus_descriptor_string string; - struct greybus_descriptor_cport cport; -#endif + if (retval) + goto error; + size -= desc_size; + data += desc_size; } + retval = gb_init_subdevs(gdev, &fake_gb_id); if (retval) goto error; return gdev; error: + for (i = 0; i < gdev->num_strings; ++i) + kfree(gdev->string[i]); + for (i = 0; i < gdev->num_cports; ++i) + kfree(gdev->cport[i]); kfree(gdev); return NULL; } diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index de31da8..9f37fc6 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -18,7 +18,7 @@ struct gbuf *greybus_alloc_gbuf(struct greybus_device *gdev, - struct cport *cport, + struct gdev_cport *cport, gfp_t mem_flags) { return NULL; diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 93d7dae..6d82806 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -35,10 +35,17 @@ struct gbuf; -struct cport { +struct gdev_cport { u16 number; u16 size; // FIXME, what else? + u8 speed; // valid??? +}; + +struct gdev_string { + u16 length; + u8 id; + u8 string[0]; }; typedef void (*gbuf_complete_t)(struct gbuf *gbuf); @@ -51,7 +58,7 @@ struct gbuf { struct gbuf_anchor *anchor; // FIXME do we need? struct greybus_device *gdev; - struct cport *cport; + struct gdev_cport *cport; int status; void *transfer_buffer; u32 transfer_flags; /* flags for the transfer buffer */ @@ -86,14 +93,20 @@ struct gb_sdio_host; struct gb_tty; struct gb_usb_device; +/* Increase these values if needed */ +#define MAX_CPORTS_PER_MODULE 10 +#define MAX_STRINGS_PER_MODULE 10 + struct greybus_device { struct device dev; u16 module_number; struct greybus_descriptor_function function; struct greybus_descriptor_module_id module_id; struct greybus_descriptor_serial_number serial_number; - int num_cport; - struct cport *cport[10]; // FIXME - no more than 10 cports per device... + int num_cports; + int num_strings; + struct gdev_cport *cport[MAX_CPORTS_PER_MODULE]; + struct gdev_string *string[MAX_STRINGS_PER_MODULE]; struct gb_i2c_device *gb_i2c_dev; struct gb_gpio_device *gb_gpio_dev; @@ -104,7 +117,7 @@ struct greybus_device { #define to_greybus_device(d) container_of(d, struct greybus_device, dev) struct gbuf *greybus_alloc_gbuf(struct greybus_device *gdev, - struct cport *cport, + struct gdev_cport *cport, gfp_t mem_flags); void greybus_free_gbuf(struct gbuf *gbuf); diff --git a/drivers/staging/greybus/greybus_desc.h b/drivers/staging/greybus/greybus_desc.h index e7355a3..37cc99a 100644 --- a/drivers/staging/greybus/greybus_desc.h +++ b/drivers/staging/greybus/greybus_desc.h @@ -21,7 +21,7 @@ enum greybus_descriptor_type { GREYBUS_TYPE_FUNCTION = 0x0001, GREYBUS_TYPE_MODULE_ID = 0x0002, GREYBUS_TYPE_SERIAL_NUMBER = 0x0003, - GREYBUS_TYPE_DEVICE_STRING = 0x0004, + GREYBUS_TYPE_STRING = 0x0004, GREYBUS_TYPE_CPORT = 0x0005, }; -- cgit v0.10.2 From b94295e0502dbe7f0c0d2b572c8b7334b05c279c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 1 Sep 2014 18:34:28 -0700 Subject: greybus: sysfs attributes for functions and more driver core integration. diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 9e9ffa0..c05495b 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -156,6 +156,78 @@ void greybus_deregister(struct greybus_driver *driver) EXPORT_SYMBOL_GPL(greybus_deregister); +static void greybus_module_release(struct device *dev) +{ + struct greybus_device *gdev = to_greybus_device(dev); + int i; + + for (i = 0; i < gdev->num_strings; ++i) + kfree(gdev->string[i]); + for (i = 0; i < gdev->num_cports; ++i) + kfree(gdev->cport[i]); + kfree(gdev); +} + + + +static struct device_type greybus_module_type = { + .name = "greybus_module", + .release = greybus_module_release, +}; + +/* Function fields */ +#define greybus_function_attr(field) \ +static ssize_t function_##field##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct greybus_device *gdev = to_greybus_device(dev); \ + return sprintf(buf, "%d\n", gdev->function.field); \ +} \ +static DEVICE_ATTR_RO(function_##field) + +greybus_function_attr(number); +greybus_function_attr(cport); +greybus_function_attr(class); +greybus_function_attr(subclass); +greybus_function_attr(protocol); + +static struct attribute *function_attrs[] = { + &dev_attr_function_number.attr, + &dev_attr_function_cport.attr, + &dev_attr_function_class.attr, + &dev_attr_function_subclass.attr, + &dev_attr_function_protocol.attr, + NULL, +}; + +static umode_t function_attrs_are_visible(struct kobject *kobj, + struct attribute *a, int n) +{ + struct greybus_device *gdev = to_greybus_device(kobj_to_dev(kobj)); + + // FIXME - make this a dynamic structure to "know" if it really is here + // or not easier? + if (gdev->function.number || + gdev->function.cport || + gdev->function.class || + gdev->function.subclass || + gdev->function.protocol) + return a->mode; + return 0; +} + +static struct attribute_group function_addr_grp = { + .attrs = function_attrs, + .is_visible = function_attrs_are_visible, +}; + +static const struct attribute_group *greybus_module_groups[] = { + &function_addr_grp, + NULL, +}; + + static int gb_init_subdevs(struct greybus_device *gdev, const struct greybus_module_id *id) { @@ -201,7 +273,8 @@ static int create_function(struct greybus_device *gdev, int header_size = sizeof(struct greybus_descriptor_function); if (desc_size != header_size) { - pr_err("invalid function header size %d\n", desc_size); + dev_err(gdev->dev.parent, "invalid function header size %d\n", + desc_size); return -EINVAL; } memcpy(&gdev->function, &desc->function, header_size); @@ -214,7 +287,8 @@ static int create_module_id(struct greybus_device *gdev, int header_size = sizeof(struct greybus_descriptor_module_id); if (desc_size != header_size) { - pr_err("invalid module header size %d\n", desc_size); + dev_err(gdev->dev.parent, "invalid module header size %d\n", + desc_size); return -EINVAL; } memcpy(&gdev->module_id, &desc->module_id, header_size); @@ -227,7 +301,8 @@ static int create_serial_number(struct greybus_device *gdev, int header_size = sizeof(struct greybus_descriptor_serial_number); if (desc_size != header_size) { - pr_err("invalid serial number header size %d\n", desc_size); + dev_err(gdev->dev.parent, "invalid serial number header size %d\n", + desc_size); return -EINVAL; } memcpy(&gdev->serial_number, &desc->serial_number, header_size); @@ -242,12 +317,14 @@ static int create_string(struct greybus_device *gdev, int header_size = sizeof(struct greybus_descriptor_string); if ((gdev->num_strings + 1) >= MAX_STRINGS_PER_MODULE) { - pr_err("too many strings for this module!\n"); + dev_err(gdev->dev.parent, + "too many strings for this module!\n"); return -EINVAL; } if (desc_size < header_size) { - pr_err("invalid string header size %d\n", desc_size); + dev_err(gdev->dev.parent, "invalid string header size %d\n", + desc_size); return -EINVAL; } @@ -259,28 +336,59 @@ static int create_string(struct greybus_device *gdev, string->length = string_size; string->id = desc->string.id; memcpy(&string->string, &desc->string.string, string_size); + gdev->string[gdev->num_strings] = string; gdev->num_strings++; return 0; } +static int create_cport(struct greybus_device *gdev, + struct greybus_descriptor *desc, int desc_size) +{ + struct gdev_cport *cport; + int header_size = sizeof(struct greybus_descriptor_cport); + + if ((gdev->num_cports + 1) >= MAX_CPORTS_PER_MODULE) { + dev_err(gdev->dev.parent, "too many cports for this module!\n"); + return -EINVAL; + } + + if (desc_size != header_size) { + dev_err(gdev->dev.parent, + "invalid serial number header size %d\n", desc_size); + return -EINVAL; + } + + cport = kzalloc(sizeof(*cport), GFP_KERNEL); + if (!cport) + return -ENOMEM; + + cport->number = le16_to_cpu(desc->cport.number); + cport->size = le16_to_cpu(desc->cport.size); + cport->speed = desc->cport.speed; + + gdev->cport[gdev->num_cports] = cport; + gdev->num_cports++; + + return 0; +} + /** * greybus_new_device: * * Pass in a buffer that _should_ be a set of greybus descriptor fields and spit * out a greybus device structure. */ -struct greybus_device *greybus_new_device(int module_number, u8 *data, int size) +struct greybus_device *greybus_new_device(struct device *parent, + int module_number, u8 *data, int size) { struct greybus_device *gdev; struct greybus_descriptor_block_header *block; struct greybus_descriptor *desc; int retval; int overall_size; - int header_size; int desc_size; - int i; u8 version_major; u8 version_minor; @@ -293,12 +401,20 @@ struct greybus_device *greybus_new_device(int module_number, u8 *data, int size) return NULL; gdev->module_number = module_number; + gdev->dev.parent = parent; + gdev->dev.driver = NULL; + gdev->dev.bus = &greybus_bus_type; + gdev->dev.type = &greybus_module_type; + gdev->dev.groups = greybus_module_groups; + gdev->dev.dma_mask = parent->dma_mask; + device_initialize(&gdev->dev); + dev_set_name(&gdev->dev, "%d", module_number); block = (struct greybus_descriptor_block_header *)data; overall_size = le16_to_cpu(block->size); if (overall_size != size) { - pr_err("size != block header size, %d != %d\n", size, - overall_size); + dev_err(parent, "size != block header size, %d != %d\n", size, + overall_size); goto error; } @@ -330,32 +446,14 @@ struct greybus_device *greybus_new_device(int module_number, u8 *data, int size) retval = create_string(gdev, desc, desc_size); break; - case GREYBUS_TYPE_CPORT: { - struct gdev_cport *cport; - - header_size = sizeof(struct greybus_descriptor_cport); - if (desc_size != header_size) { - pr_err("invalid serial number header size %d\n", - desc_size); - goto error; - } - cport = kzalloc(sizeof(*cport), GFP_KERNEL); - if (!cport) - goto error; - cport->number = le16_to_cpu(desc->cport.number); - cport->size = le16_to_cpu(desc->cport.size); - cport->speed = desc->cport.speed; - gdev->cport[gdev->num_cports] = cport; - gdev->num_cports++; - // FIXME - check for too many cports... - - size -= desc_size; - data += desc_size; + case GREYBUS_TYPE_CPORT: + retval = create_cport(gdev, desc, desc_size); break; - } + case GREYBUS_TYPE_INVALID: default: - pr_err("invalid descriptor type %d\n", desc->header.type); + dev_err(parent, "invalid descriptor type %d\n", + desc->header.type); goto error; } if (retval) @@ -367,23 +465,25 @@ struct greybus_device *greybus_new_device(int module_number, u8 *data, int size) retval = gb_init_subdevs(gdev, &fake_gb_id); if (retval) goto error; + + // FIXME device_add(&gdev->dev); + + return gdev; error: - for (i = 0; i < gdev->num_strings; ++i) - kfree(gdev->string[i]); - for (i = 0; i < gdev->num_cports; ++i) - kfree(gdev->cport[i]); - kfree(gdev); + greybus_module_release(&gdev->dev); return NULL; } -void remove_device(struct greybus_device *gdev) +void greybus_remove_device(struct greybus_device *gdev) { /* tear down all of the "sub device types" for this device */ gb_i2c_disconnect(gdev); gb_gpio_disconnect(gdev); gb_sdio_disconnect(gdev); gb_tty_disconnect(gdev); + + // FIXME - device_remove(&gdev->dev); } static int __init gb_init(void) diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 6d82806..1a0dc4c 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -173,6 +173,10 @@ void greybus_deregister(struct greybus_driver *driver); int greybus_disabled(void); +struct greybus_device *greybus_new_device(struct device *parent, + int module_number, u8 *data, + int size); +void greybus_remove_device(struct greybus_device *gdev); /* Internal functions to gb module, move to internal .h file eventually. */ diff --git a/drivers/staging/greybus/greybus_desc.h b/drivers/staging/greybus/greybus_desc.h index 37cc99a..0fd7230 100644 --- a/drivers/staging/greybus/greybus_desc.h +++ b/drivers/staging/greybus/greybus_desc.h @@ -50,9 +50,9 @@ enum greybus_function_class { struct greybus_descriptor_function { __le16 number; __le16 cport; - __u8 function_class; /* enum greybus_function_class */ - __u8 function_subclass; - __u8 function_protocol; + __u8 class; /* enum greybus_function_class */ + __u8 subclass; + __u8 protocol; __u8 reserved; }; -- cgit v0.10.2 From 291f3b9e61eb4d4f3cc43f93b8862fbe74c588ae Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 1 Sep 2014 18:41:39 -0700 Subject: greybus: serial number attribute added diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index c05495b..68fb2a5 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -169,7 +169,6 @@ static void greybus_module_release(struct device *dev) } - static struct device_type greybus_module_type = { .name = "greybus_module", .release = greybus_module_release, @@ -222,8 +221,40 @@ static struct attribute_group function_addr_grp = { .is_visible = function_attrs_are_visible, }; +#if 0 +struct greybus_descriptor_module_id { + __le16 vendor; + __le16 product; + __le16 version; + __u8 vendor_stringid; + __u8 product_stringid; +}; +#endif + +/* Serial Number */ +static ssize_t serial_number_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct greybus_device *gdev = to_greybus_device(dev); + return sprintf(buf, "%llX\n", + (unsigned long long)gdev->serial_number.serial_number); +} +static DEVICE_ATTR_RO(serial_number); + +static struct attribute *serial_number_attrs[] = { + &dev_attr_serial_number.attr, + NULL, +}; + +static struct attribute_group serial_number_grp = { + .attrs = serial_number_attrs, + .is_visible = function_attrs_are_visible, +}; + + static const struct attribute_group *greybus_module_groups[] = { &function_addr_grp, + &serial_number_grp, NULL, }; -- cgit v0.10.2 From 21ee4116fdf251b26a0fa6921f771f714f3bcd65 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 1 Sep 2014 18:57:42 -0700 Subject: greybus: module id attributes diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 68fb2a5..37ece6d 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -216,20 +216,81 @@ static umode_t function_attrs_are_visible(struct kobject *kobj, return 0; } -static struct attribute_group function_addr_grp = { +static struct attribute_group function_attr_grp = { .attrs = function_attrs, .is_visible = function_attrs_are_visible, }; -#if 0 -struct greybus_descriptor_module_id { - __le16 vendor; - __le16 product; - __le16 version; - __u8 vendor_stringid; - __u8 product_stringid; +/* Module fields */ +#define greybus_module_attr(field) \ +static ssize_t module_##field##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct greybus_device *gdev = to_greybus_device(dev); \ + return sprintf(buf, "%x\n", gdev->module_id.field); \ +} \ +static DEVICE_ATTR_RO(module_##field) + +greybus_module_attr(vendor); +greybus_module_attr(product); +greybus_module_attr(version); + +static ssize_t module_vendor_string_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct greybus_device *gdev = to_greybus_device(dev); + return sprintf(buf, "%s", + greybus_string(gdev->module_id.vendor_stringid)); +} +static DEVICE_ATTR_RO(module_vendor_string); + +static ssize_t module_product_string_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct greybus_device *gdev = to_greybus_device(dev); + return sprintf(buf, "%s", + greybus_string(gdev->module_id.product_stringid)); +} +static DEVICE_ATTR_RO(module_product_string); + +static struct attribute *module_attrs[] = { + &dev_attr_module_vendor.attr, + &dev_attr_module_product.attr, + &dev_attr_module_version.attr, + &dev_attr_module_vendor_string.attr, + &dev_attr_module_product_string.attr, + NULL, }; -#endif + +static umode_t module_attrs_are_visible(struct kobject *kobj, + struct attribute *a, int n) +{ + struct greybus_device *gdev = to_greybus_device(kobj_to_dev(kobj)); + + if ((a == &dev_attr_module_vendor_string.attr) && + (gdev->module_id.vendor_stringid)) + return a->mode; + if ((a == &dev_attr_module_product_string.attr) && + (gdev->module_id.product_stringid)) + return a->mode; + + // FIXME - make this a dynamic structure to "know" if it really is here + // or not easier? + if (gdev->module_id.vendor || + gdev->module_id.product || + gdev->module_id.version) + return a->mode; + return 0; +} + +static struct attribute_group module_attr_grp = { + .attrs = module_attrs, + .is_visible = module_attrs_are_visible, +}; + /* Serial Number */ static ssize_t serial_number_show(struct device *dev, @@ -246,15 +307,16 @@ static struct attribute *serial_number_attrs[] = { NULL, }; -static struct attribute_group serial_number_grp = { +static struct attribute_group serial_number_attr_grp = { .attrs = serial_number_attrs, .is_visible = function_attrs_are_visible, }; static const struct attribute_group *greybus_module_groups[] = { - &function_addr_grp, - &serial_number_grp, + &function_attr_grp, + &module_attr_grp, + &serial_number_attr_grp, NULL, }; diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 1a0dc4c..1955fea 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -178,6 +178,8 @@ struct greybus_device *greybus_new_device(struct device *parent, int size); void greybus_remove_device(struct greybus_device *gdev); +const u8 *greybus_string(int id); + /* Internal functions to gb module, move to internal .h file eventually. */ int gb_new_ap_msg(u8 *data, int length); -- cgit v0.10.2 From e24e7257b12d409d1ef0a24307b9525093845f1e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 1 Sep 2014 19:01:14 -0700 Subject: greybus: greybus_string() diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 37ece6d..235a9c4 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -169,6 +169,22 @@ static void greybus_module_release(struct device *dev) } +const u8 *greybus_string(struct greybus_device *gdev, int id) +{ + int i; + struct gdev_string *string; + + if (!gdev) + return NULL; + + for (i = 0; i < gdev->num_strings; ++i) { + string = gdev->string[i]; + if (string->id == id) + return &string->string[0]; + } + return NULL; +} + static struct device_type greybus_module_type = { .name = "greybus_module", .release = greybus_module_release, @@ -242,7 +258,7 @@ static ssize_t module_vendor_string_show(struct device *dev, { struct greybus_device *gdev = to_greybus_device(dev); return sprintf(buf, "%s", - greybus_string(gdev->module_id.vendor_stringid)); + greybus_string(gdev, gdev->module_id.vendor_stringid)); } static DEVICE_ATTR_RO(module_vendor_string); @@ -252,7 +268,7 @@ static ssize_t module_product_string_show(struct device *dev, { struct greybus_device *gdev = to_greybus_device(dev); return sprintf(buf, "%s", - greybus_string(gdev->module_id.product_stringid)); + greybus_string(gdev, gdev->module_id.product_stringid)); } static DEVICE_ATTR_RO(module_product_string); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 1955fea..50bbf18 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -178,7 +178,7 @@ struct greybus_device *greybus_new_device(struct device *parent, int size); void greybus_remove_device(struct greybus_device *gdev); -const u8 *greybus_string(int id); +const u8 *greybus_string(struct greybus_device *gdev, int id); /* Internal functions to gb module, move to internal .h file eventually. */ -- cgit v0.10.2 From 06340efb7cc38fb7184cae6d3705383f468cefbe Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 1 Sep 2014 19:05:54 -0700 Subject: greybus: split sysfs functions out to separate file. diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 9815e8a..c1e4e12 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -1,5 +1,6 @@ greybus-y := core.o \ gbuf.o \ + sysfs.o \ debugfs.o \ ap.o \ i2c-gb.o \ diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 235a9c4..bbe9ef9 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -190,153 +190,6 @@ static struct device_type greybus_module_type = { .release = greybus_module_release, }; -/* Function fields */ -#define greybus_function_attr(field) \ -static ssize_t function_##field##_show(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct greybus_device *gdev = to_greybus_device(dev); \ - return sprintf(buf, "%d\n", gdev->function.field); \ -} \ -static DEVICE_ATTR_RO(function_##field) - -greybus_function_attr(number); -greybus_function_attr(cport); -greybus_function_attr(class); -greybus_function_attr(subclass); -greybus_function_attr(protocol); - -static struct attribute *function_attrs[] = { - &dev_attr_function_number.attr, - &dev_attr_function_cport.attr, - &dev_attr_function_class.attr, - &dev_attr_function_subclass.attr, - &dev_attr_function_protocol.attr, - NULL, -}; - -static umode_t function_attrs_are_visible(struct kobject *kobj, - struct attribute *a, int n) -{ - struct greybus_device *gdev = to_greybus_device(kobj_to_dev(kobj)); - - // FIXME - make this a dynamic structure to "know" if it really is here - // or not easier? - if (gdev->function.number || - gdev->function.cport || - gdev->function.class || - gdev->function.subclass || - gdev->function.protocol) - return a->mode; - return 0; -} - -static struct attribute_group function_attr_grp = { - .attrs = function_attrs, - .is_visible = function_attrs_are_visible, -}; - -/* Module fields */ -#define greybus_module_attr(field) \ -static ssize_t module_##field##_show(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct greybus_device *gdev = to_greybus_device(dev); \ - return sprintf(buf, "%x\n", gdev->module_id.field); \ -} \ -static DEVICE_ATTR_RO(module_##field) - -greybus_module_attr(vendor); -greybus_module_attr(product); -greybus_module_attr(version); - -static ssize_t module_vendor_string_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct greybus_device *gdev = to_greybus_device(dev); - return sprintf(buf, "%s", - greybus_string(gdev, gdev->module_id.vendor_stringid)); -} -static DEVICE_ATTR_RO(module_vendor_string); - -static ssize_t module_product_string_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct greybus_device *gdev = to_greybus_device(dev); - return sprintf(buf, "%s", - greybus_string(gdev, gdev->module_id.product_stringid)); -} -static DEVICE_ATTR_RO(module_product_string); - -static struct attribute *module_attrs[] = { - &dev_attr_module_vendor.attr, - &dev_attr_module_product.attr, - &dev_attr_module_version.attr, - &dev_attr_module_vendor_string.attr, - &dev_attr_module_product_string.attr, - NULL, -}; - -static umode_t module_attrs_are_visible(struct kobject *kobj, - struct attribute *a, int n) -{ - struct greybus_device *gdev = to_greybus_device(kobj_to_dev(kobj)); - - if ((a == &dev_attr_module_vendor_string.attr) && - (gdev->module_id.vendor_stringid)) - return a->mode; - if ((a == &dev_attr_module_product_string.attr) && - (gdev->module_id.product_stringid)) - return a->mode; - - // FIXME - make this a dynamic structure to "know" if it really is here - // or not easier? - if (gdev->module_id.vendor || - gdev->module_id.product || - gdev->module_id.version) - return a->mode; - return 0; -} - -static struct attribute_group module_attr_grp = { - .attrs = module_attrs, - .is_visible = module_attrs_are_visible, -}; - - -/* Serial Number */ -static ssize_t serial_number_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct greybus_device *gdev = to_greybus_device(dev); - return sprintf(buf, "%llX\n", - (unsigned long long)gdev->serial_number.serial_number); -} -static DEVICE_ATTR_RO(serial_number); - -static struct attribute *serial_number_attrs[] = { - &dev_attr_serial_number.attr, - NULL, -}; - -static struct attribute_group serial_number_attr_grp = { - .attrs = serial_number_attrs, - .is_visible = function_attrs_are_visible, -}; - - -static const struct attribute_group *greybus_module_groups[] = { - &function_attr_grp, - &module_attr_grp, - &serial_number_attr_grp, - NULL, -}; - - static int gb_init_subdevs(struct greybus_device *gdev, const struct greybus_module_id *id) { diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 50bbf18..d9cfc3b 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -188,6 +188,8 @@ void gb_thread_destroy(void); int gb_debugfs_init(void); void gb_debugfs_cleanup(void); +extern const struct attribute_group *greybus_module_groups[]; + /* * Because we are allocating a data structure per "type" in the greybus device, * we have static functions for this, not "dynamic" drivers like we really diff --git a/drivers/staging/greybus/sysfs.c b/drivers/staging/greybus/sysfs.c new file mode 100644 index 0000000..16e6ca4 --- /dev/null +++ b/drivers/staging/greybus/sysfs.c @@ -0,0 +1,166 @@ +/* + * Greybus sysfs file functions + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include + +#include "greybus.h" + +/* Function fields */ +#define greybus_function_attr(field) \ +static ssize_t function_##field##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct greybus_device *gdev = to_greybus_device(dev); \ + return sprintf(buf, "%d\n", gdev->function.field); \ +} \ +static DEVICE_ATTR_RO(function_##field) + +greybus_function_attr(number); +greybus_function_attr(cport); +greybus_function_attr(class); +greybus_function_attr(subclass); +greybus_function_attr(protocol); + +static struct attribute *function_attrs[] = { + &dev_attr_function_number.attr, + &dev_attr_function_cport.attr, + &dev_attr_function_class.attr, + &dev_attr_function_subclass.attr, + &dev_attr_function_protocol.attr, + NULL, +}; + +static umode_t function_attrs_are_visible(struct kobject *kobj, + struct attribute *a, int n) +{ + struct greybus_device *gdev = to_greybus_device(kobj_to_dev(kobj)); + + // FIXME - make this a dynamic structure to "know" if it really is here + // or not easier? + if (gdev->function.number || + gdev->function.cport || + gdev->function.class || + gdev->function.subclass || + gdev->function.protocol) + return a->mode; + return 0; +} + +static struct attribute_group function_attr_grp = { + .attrs = function_attrs, + .is_visible = function_attrs_are_visible, +}; + +/* Module fields */ +#define greybus_module_attr(field) \ +static ssize_t module_##field##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct greybus_device *gdev = to_greybus_device(dev); \ + return sprintf(buf, "%x\n", gdev->module_id.field); \ +} \ +static DEVICE_ATTR_RO(module_##field) + +greybus_module_attr(vendor); +greybus_module_attr(product); +greybus_module_attr(version); + +static ssize_t module_vendor_string_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct greybus_device *gdev = to_greybus_device(dev); + return sprintf(buf, "%s", + greybus_string(gdev, gdev->module_id.vendor_stringid)); +} +static DEVICE_ATTR_RO(module_vendor_string); + +static ssize_t module_product_string_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct greybus_device *gdev = to_greybus_device(dev); + return sprintf(buf, "%s", + greybus_string(gdev, gdev->module_id.product_stringid)); +} +static DEVICE_ATTR_RO(module_product_string); + +static struct attribute *module_attrs[] = { + &dev_attr_module_vendor.attr, + &dev_attr_module_product.attr, + &dev_attr_module_version.attr, + &dev_attr_module_vendor_string.attr, + &dev_attr_module_product_string.attr, + NULL, +}; + +static umode_t module_attrs_are_visible(struct kobject *kobj, + struct attribute *a, int n) +{ + struct greybus_device *gdev = to_greybus_device(kobj_to_dev(kobj)); + + if ((a == &dev_attr_module_vendor_string.attr) && + (gdev->module_id.vendor_stringid)) + return a->mode; + if ((a == &dev_attr_module_product_string.attr) && + (gdev->module_id.product_stringid)) + return a->mode; + + // FIXME - make this a dynamic structure to "know" if it really is here + // or not easier? + if (gdev->module_id.vendor || + gdev->module_id.product || + gdev->module_id.version) + return a->mode; + return 0; +} + +static struct attribute_group module_attr_grp = { + .attrs = module_attrs, + .is_visible = module_attrs_are_visible, +}; + + +/* Serial Number */ +static ssize_t serial_number_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct greybus_device *gdev = to_greybus_device(dev); + return sprintf(buf, "%llX\n", + (unsigned long long)gdev->serial_number.serial_number); +} +static DEVICE_ATTR_RO(serial_number); + +static struct attribute *serial_number_attrs[] = { + &dev_attr_serial_number.attr, + NULL, +}; + +static struct attribute_group serial_number_attr_grp = { + .attrs = serial_number_attrs, + .is_visible = function_attrs_are_visible, +}; + + +const struct attribute_group *greybus_module_groups[] = { + &function_attr_grp, + &module_attr_grp, + &serial_number_attr_grp, + NULL, +}; + -- cgit v0.10.2 From 3be03d42cd02402a5aa41d8a55ae3597ef302667 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 1 Sep 2014 19:10:06 -0700 Subject: greybus: minor checkpatch cleanups diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index bbe9ef9..da62baf 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -226,8 +226,9 @@ error_i2c: return retval; } -static const struct greybus_module_id fake_gb_id = - { GREYBUS_DEVICE(0x42, 0x42) }; +static const struct greybus_module_id fake_gb_id = { + GREYBUS_DEVICE(0x42, 0x42) +}; static int create_function(struct greybus_device *gdev, struct greybus_descriptor *desc, int desc_size) diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index c4cb6a2..3428220 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -48,7 +48,6 @@ static int gpio_get(struct gpio_chip *gpio, unsigned nr) static void gpio_set(struct gpio_chip *gpio, unsigned nr, int val) { // FIXME - do something there - return; } int gb_gpio_probe(struct greybus_device *gdev, @@ -77,7 +76,7 @@ int gb_gpio_probe(struct greybus_device *gdev, gpio->ngpio = 42; // FIXME!!! gpio->can_sleep = false; // FIXME!!! - gdev->gb_gpio_dev= gb_gpio; + gdev->gb_gpio_dev = gb_gpio; retval = gpiochip_add(gpio); if (retval) { diff --git a/drivers/staging/greybus/sysfs.c b/drivers/staging/greybus/sysfs.c index 16e6ca4..2393a6a 100644 --- a/drivers/staging/greybus/sysfs.c +++ b/drivers/staging/greybus/sysfs.c @@ -85,6 +85,7 @@ static ssize_t module_vendor_string_show(struct device *dev, char *buf) { struct greybus_device *gdev = to_greybus_device(dev); + return sprintf(buf, "%s", greybus_string(gdev, gdev->module_id.vendor_stringid)); } @@ -95,6 +96,7 @@ static ssize_t module_product_string_show(struct device *dev, char *buf) { struct greybus_device *gdev = to_greybus_device(dev); + return sprintf(buf, "%s", greybus_string(gdev, gdev->module_id.product_stringid)); } @@ -141,6 +143,7 @@ static ssize_t serial_number_show(struct device *dev, struct device_attribute *attr, char *buf) { struct greybus_device *gdev = to_greybus_device(dev); + return sprintf(buf, "%llX\n", (unsigned long long)gdev->serial_number.serial_number); } diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index d104d9c..896d501 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -245,8 +245,7 @@ static int get_serial_info(struct gb_tty *gb_tty, if (copy_to_user(info, &tmp, sizeof(tmp))) return -EFAULT; - else - return 0; + return 0; } static int set_serial_info(struct gb_tty *gb_tty, -- cgit v0.10.2 From 48123e0e1eb917c577fb48ef25f41823a7b080f9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 2 Sep 2014 10:51:56 -0700 Subject: greybus: add proper packing to all greybus message types diff --git a/drivers/staging/greybus/greybus_desc.h b/drivers/staging/greybus/greybus_desc.h index 0fd7230..592b651 100644 --- a/drivers/staging/greybus/greybus_desc.h +++ b/drivers/staging/greybus/greybus_desc.h @@ -10,6 +10,8 @@ #ifndef __GREYBUS_DESC_H #define __GREYBUS_DESC_H +#pragma pack(push, 1) + struct greybus_descriptor_block_header { __le16 size; __u8 version_major; @@ -92,4 +94,6 @@ struct greybus_descriptor { }; }; +#pragma pack(pop) + #endif /* __GREYBUS_DESC_H */ diff --git a/drivers/staging/greybus/svc_msg.h b/drivers/staging/greybus/svc_msg.h index d992f3c..bbc7ef0 100644 --- a/drivers/staging/greybus/svc_msg.h +++ b/drivers/staging/greybus/svc_msg.h @@ -10,6 +10,8 @@ #ifndef __SVC_MSG_H #define __SVC_MSG_H +#pragma pack(push, 1) + enum svc_function_type { SVC_FUNCTION_HANDSHAKE = 0x00, SVC_FUNCTION_UNIPRO_NETWORK_MANAGEMENT = 0x01, @@ -161,4 +163,6 @@ struct svc_msg { }; }; +#pragma pack(pop) + #endif /* __SVC_MSG_H */ -- cgit v0.10.2 From f8089c0c6e6572b4c1f3483d93e0ec4edff20f53 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Fri, 5 Sep 2014 23:56:09 -0400 Subject: greybus: uart-gb.c: replace alloc_tty_driver with tty_alloc_driver alloc_tty_driver() is deprecated. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 896d501..0139365 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -469,8 +469,8 @@ int __init gb_tty_init(void) { int retval; - gb_tty_driver = alloc_tty_driver(GB_NUM_MINORS); - if (!gb_tty_driver) + gb_tty_driver = tty_alloc_driver(GB_NUM_MINORS, 0); + if (IS_ERR(gb_tty_driver)) return -ENOMEM; gb_tty_driver->driver_name = "gb"; -- cgit v0.10.2 From 7fabc884f9be6ad0828c955bfd28d067bbf6a999 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Fri, 5 Sep 2014 23:56:10 -0400 Subject: greybus: uart-gb.c: dynamically allocate device numbers diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 0139365..f351046 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -23,10 +23,13 @@ #include #include #include +#include +#include #include "greybus.h" #define GB_TTY_MAJOR 180 /* FIXME use a real number!!! */ #define GB_NUM_MINORS 255 /* 255 is enough for anyone... */ +#define GB_NAME "ttyGB" struct gb_tty { struct tty_port port; @@ -467,16 +470,24 @@ static struct greybus_driver tty_gb_driver = { int __init gb_tty_init(void) { - int retval; + int retval = 0; + dev_t dev; + + retval = alloc_chrdev_region(&dev, 0, GB_NUM_MINORS, GB_NAME); + if (retval) + return retval; gb_tty_driver = tty_alloc_driver(GB_NUM_MINORS, 0); - if (IS_ERR(gb_tty_driver)) - return -ENOMEM; + if (IS_ERR(gb_tty_driver)) { + retval = -ENOMEM; + goto fail_unregister_dev; + } + gb_tty_driver->owner = THIS_MODULE; gb_tty_driver->driver_name = "gb"; - gb_tty_driver->name = "ttyGB"; - gb_tty_driver->major = GB_TTY_MAJOR; - gb_tty_driver->minor_start = 0; + gb_tty_driver->name = GB_NAME; + gb_tty_driver->major = MAJOR(dev); + gb_tty_driver->minor_start = MINOR(dev); gb_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; gb_tty_driver->subtype = SERIAL_TYPE_NORMAL; gb_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; @@ -485,24 +496,32 @@ int __init gb_tty_init(void) tty_set_operations(gb_tty_driver, &gb_ops); retval = tty_register_driver(gb_tty_driver); - if (retval) { - put_tty_driver(gb_tty_driver); - return retval; - } + if (retval) + goto fail_put_gb_tty; retval = greybus_register(&tty_gb_driver); - if (retval) { - tty_unregister_driver(gb_tty_driver); - put_tty_driver(gb_tty_driver); - } + if (retval) + goto fail_unregister_gb_tty; + + return 0; + + fail_unregister_gb_tty: + tty_unregister_driver(gb_tty_driver); + fail_put_gb_tty: + put_tty_driver(gb_tty_driver); + fail_unregister_dev: + unregister_chrdev_region(dev, GB_NUM_MINORS); return retval; } void __exit gb_tty_exit(void) { + int major = MAJOR(gb_tty_driver->major); + int minor = gb_tty_driver->minor_start; greybus_deregister(&tty_gb_driver); tty_unregister_driver(gb_tty_driver); put_tty_driver(gb_tty_driver); + unregister_chrdev_region(MKDEV(major, minor), GB_NUM_MINORS); } #if 0 -- cgit v0.10.2 From f0e49eb05997d9a835a9537e8c466f1ce01a93cb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 6 Sep 2014 11:42:25 -0700 Subject: greybus: uart-gb: remove unneeded THIS_MODULE setting diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index f351046..852dd0c5 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -483,7 +483,6 @@ int __init gb_tty_init(void) goto fail_unregister_dev; } - gb_tty_driver->owner = THIS_MODULE; gb_tty_driver->driver_name = "gb"; gb_tty_driver->name = GB_NAME; gb_tty_driver->major = MAJOR(dev); -- cgit v0.10.2 From d6e0e1c552fe83f6694acebf3a34e4b66a143e05 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 6 Sep 2014 13:13:13 -0700 Subject: greybus: add es1_ap_desc.c to describe the ES1 USB device descriptors diff --git a/drivers/staging/greybus/es1_ap_desc.c b/drivers/staging/greybus/es1_ap_desc.c new file mode 100644 index 0000000..eec7349 --- /dev/null +++ b/drivers/staging/greybus/es1_ap_desc.c @@ -0,0 +1,63 @@ + +static const u8 es1_dev_descriptor[] = { + 0x12, /* __u8 bLength */ + 0x01, /* __u8 bDescriptorType; Device */ + 0x00, 0x02 /* __le16 bcdUSB v2.0 */ + 0x00, /* __u8 bDeviceClass */ + 0x00, /* __u8 bDeviceClass */ + 0x00, /* __u8 bDeviceSubClass; */ + 0x00, /* __u8 bDeviceProtocol; */ + 0x40, /* __u8 bMaxPacketSize0; 2^64 = 512 Bytes */ + + 0xff, 0xff, /* __le16 idVendor; 0xffff made up for now */ + 0x01, 0x00, /* __le16 idProduct; 0x0001 made up for now */ + 0x01, 0x00, /* __le16 bcdDevice; ES1 */ + + 0x03, /* __u8 iManufacturer; */ + 0x02, /* __u8 iProduct; */ + 0x01, /* __u8 iSerialNumber; */ + 0x01 /* __u8 bNumConfigurations; */ +}; + +static const u8 es1_config_descriptor[] = { + /* one configuration */ + 0x09, /* __u8 bLength; */ + 0x02, /* __u8 bDescriptorType; Configuration */ + 0x19, 0x00, /* __le16 wTotalLength; */ + 0x01, /* __u8 bNumInterfaces; (1) */ + 0x01, /* __u8 bConfigurationValue; */ + 0x00, /* __u8 iConfiguration; */ + 0xc0, /* __u8 bmAttributes; + Bit 7: must be set, + 6: Self-powered, + 5: Remote wakeup, + 4..0: resvd */ + 0x00, /* __u8 MaxPower; */ + + /* one interface */ + 0x09, /* __u8 if_bLength; */ + 0x04, /* __u8 if_bDescriptorType; Interface */ + 0x00, /* __u8 if_bInterfaceNumber; */ + 0x00, /* __u8 if_bAlternateSetting; */ + 0x02, /* __u8 if_bNumEndpoints; */ + 0xff, /* __u8 if_bInterfaceClass; Vendor-specific */ + 0xff, /* __u8 if_bInterfaceSubClass; Vendor-specific */ + 0xff, /* __u8 if_bInterfaceProtocol; Vendor-specific */ + 0x00, /* __u8 if_iInterface; */ + + /* two endpoints */ + 0x07, /* __u8 ep_bLength; */ + 0x05, /* __u8 ep_bDescriptorType; Endpoint */ + 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ + 0x02, /* __u8 ep_bmAttributes; Bulk */ + 0x40, 0x00, /* __le16 ep_wMaxPacketSize; 64??? */ + 0x00 /* __u8 ep_bInterval; */ + + 0x07, /* __u8 ep_bLength; */ + 0x05, /* __u8 ep_bDescriptorType; Endpoint */ + 0x02, /* __u8 ep_bEndpointAddress; Out Endpoint 2 */ + 0x02, /* __u8 ep_bmAttributes; Bulk */ + 0x40, 0x00, /* __le16 ep_wMaxPacketSize; 64??? */ + 0x00 /* __u8 ep_bInterval; */ + +}; -- cgit v0.10.2 From a39879fc089c9db1be9d2aee2daf2991424f9a04 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 6 Sep 2014 16:57:36 -0700 Subject: greybus: host controller additions Also some gbuf functions starting to get fleshed out. diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index da62baf..517b260 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -449,6 +449,22 @@ void greybus_remove_device(struct greybus_device *gdev) // FIXME - device_remove(&gdev->dev); } +struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver, + struct device *parent) +{ + struct greybus_host_device *hd; + + hd = kzalloc(sizeof(*hd) + driver->hd_priv_size, GFP_KERNEL); + if (!hd) + return NULL; + + kref_init(&hd->kref); + + return hd; +} +EXPORT_SYMBOL_GPL(greybus_create_hd); + + static int __init gb_init(void) { int retval; diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index e7042d5..a08e4dd 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -13,7 +13,7 @@ #include "greybus.h" static const struct usb_device_id id_table[] = { - { USB_DEVICE(0x0000, 0x0000) }, // FIXME + { USB_DEVICE(0xffff, 0x0001) }, // FIXME { }, }; MODULE_DEVICE_TABLE(usb, id_table); @@ -21,18 +21,73 @@ MODULE_DEVICE_TABLE(usb, id_table); struct es1_ap_dev { struct usb_device *usb_dev; struct usb_interface *usb_intf; + struct greybus_host_device *hd; - __u8 ap_in_endpoint; - __u8 ap_out_endpoint; + __u8 ap_comm_endpoint; /* endpoint to talk to the AP */ + __u8 ap_in_endpoint; /* bulk in for CPort data */ + __u8 ap_out_endpoint; /* bulk out for CPort data */ u8 *ap_buffer; }; +static inline struct es1_ap_dev *hd_to_es1(struct greybus_host_device *hd) +{ + return (struct es1_ap_dev *)(hd->hd_priv); +} + /* - * Hack, we "know" we will only have one of these at any one time, so only - * create one static structure pointer. + * Allocate the actual buffer for this gbuf and device and cport + * + * We are responsible for setting the following fields in a struct gbuf: + * void *hcpriv; + * void *transfer_buffer; + * u32 transfer_buffer_length; */ -static struct es1_ap_dev *es1_ap_dev; +static int alloc_gbuf(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask) +{ + struct es1_ap_dev *es1 = hd_to_es1(gbuf->gdev->hd); + u8 *buffer; + + /* For ES2 we need to figure out what cport is going to what endpoint, + * but for ES1, it's so dirt simple, we don't have a choice... + * + * Also, do a "slow" allocation now, if we need speed, use a cache + */ + buffer = kmalloc(size + 1, gfp_mask); + if (!buffer) + return -ENOMEM; + + /* + * we will encode the cport number in the first byte of the buffer, so + * set the second byte to be the "transfer buffer" + */ + buffer[0] = gbuf->cport->number; + gbuf->transfer_buffer = &buffer[1]; + gbuf->transfer_buffer_length = size; + + gbuf->hdpriv = es1; /* really, we could do something else here... */ + + return 0; +} + +/* Free the memory we allocated with a gbuf */ +static void free_gbuf(struct gbuf *gbuf) +{ + u8 *transfer_buffer; + u8 *buffer; + + transfer_buffer = gbuf->transfer_buffer; + buffer = &transfer_buffer[-1]; /* yes, we mean -1 */ + kfree(buffer); +} + + +static struct greybus_host_driver es1_driver = { + .hd_priv_size = sizeof(struct es1_ap_dev), + .alloc_gbuf = alloc_gbuf, + .free_gbuf = free_gbuf, +}; + void ap_in_callback(struct urb *urb) { @@ -100,19 +155,26 @@ exit: static int ap_probe(struct usb_interface *interface, const struct usb_device_id *id) { + struct es1_ap_dev *es1; + struct greybus_host_device *hd; + struct usb_device *udev; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; - size_t buffer_size; int i; - if (es1_ap_dev) { - dev_err(&interface->dev, "Already have a es1_ap_dev???\n"); - return -ENODEV; - } - es1_ap_dev = kzalloc(sizeof(*es1_ap_dev), GFP_KERNEL); - if (!es1_ap_dev) + udev = usb_get_dev(interface_to_usbdev(interface)); + + hd = greybus_create_hd(&es1_driver, &udev->dev); + if (!hd) return -ENOMEM; + es1 = hd_to_es1(hd); + es1->hd = hd; + + /* Control endpoint is the pipe to talk to this AP, so save it off */ + endpoint = &udev->ep0.desc; + es1->ap_comm_endpoint = endpoint->bEndpointAddress; + // FIXME // figure out endpoint for talking to the AP. iface_desc = interface->cur_altsetting; @@ -120,13 +182,10 @@ static int ap_probe(struct usb_interface *interface, endpoint = &iface_desc->endpoint[i].desc; if (usb_endpoint_is_bulk_in(endpoint)) { - buffer_size = usb_endpoint_maxp(endpoint); - // FIXME - Save buffer_size? - es1_ap_dev->ap_in_endpoint = endpoint->bEndpointAddress; + es1->ap_in_endpoint = endpoint->bEndpointAddress; } if (usb_endpoint_is_bulk_out(endpoint)) { - // FIXME - anything else about this we need? - es1_ap_dev->ap_out_endpoint = endpoint->bEndpointAddress; + es1->ap_out_endpoint = endpoint->bEndpointAddress; } // FIXME - properly exit once found the AP endpoint // FIXME - set up cport endpoints @@ -135,23 +194,25 @@ static int ap_probe(struct usb_interface *interface, // FIXME - allocate buffer // FIXME = start up talking, then create the gb "devices" based on what the AP tells us. - es1_ap_dev->usb_intf = interface; - es1_ap_dev->usb_dev = usb_get_dev(interface_to_usbdev(interface)); - usb_set_intfdata(interface, es1_ap_dev); + es1->usb_intf = interface; + es1->usb_dev = udev; + usb_set_intfdata(interface, es1); return 0; } static void ap_disconnect(struct usb_interface *interface) { - es1_ap_dev = usb_get_intfdata(interface); + struct es1_ap_dev *es1; + + es1 = usb_get_intfdata(interface); /* Tear down everything! */ - usb_put_dev(es1_ap_dev->usb_dev); - kfree(es1_ap_dev->ap_buffer); - kfree(es1_ap_dev); - es1_ap_dev = NULL; + usb_put_dev(es1->usb_dev); + kfree(es1->ap_buffer); + // FIXME + //greybus_destroy_hd(es1->hd); } static struct usb_driver es1_ap_driver = { diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 9f37fc6..1444b3f 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -12,21 +12,93 @@ #include #include #include +#include #include +#include #include "greybus.h" +/** + * greybus_alloc_gbuf - allocate a greybus buffer + * + * @gdev: greybus device that wants to allocate this + * @cport: cport to send the data to + * @complete: callback when the gbuf is finished with + * @size: size of the buffer + * @gfp_mask: allocation mask + * @context: context added to the gbuf by the driver + * + * TODO: someday it will be nice to handle DMA, but for now, due to the + * architecture we are stuck with, the greybus core has to allocate the buffer + * that the driver can then fill up with the data to be sent out. Curse + * hardware designers for this issue... + */ struct gbuf *greybus_alloc_gbuf(struct greybus_device *gdev, struct gdev_cport *cport, - gfp_t mem_flags) + gbuf_complete_t complete, + unsigned int size, + gfp_t gfp_mask, + void *context) { - return NULL; + struct gbuf *gbuf; + int retval; + + /* + * change this to a slab allocation if it's too slow, but for now, let's + * be dumb and simple. + */ + gbuf = kzalloc(sizeof(*gbuf), gfp_mask); + if (!gbuf) + return NULL; + + kref_init(&gbuf->kref); + gbuf->gdev = gdev; + gbuf->cport = cport; + gbuf->complete = complete; + gbuf->context = context; + + /* Host controller specific allocation for the actual buffer */ + retval = gbuf->gdev->hd->driver->alloc_gbuf(gbuf, size, gfp_mask); + if (retval) { + kfree(gbuf); + return NULL; + } + + return gbuf; +} +EXPORT_SYMBOL_GPL(greybus_alloc_gbuf); + +static DEFINE_MUTEX(gbuf_mutex); + +static void free_gbuf(struct kref *kref) +{ + struct gbuf *gbuf = container_of(kref, struct gbuf, kref); + + /* let the host controller free what it wants to */ + gbuf->gdev->hd->driver->free_gbuf(gbuf); + + kfree(gbuf); } void greybus_free_gbuf(struct gbuf *gbuf) { + /* drop the reference count and get out of here */ + kref_put_mutex(&gbuf->kref, free_gbuf, &gbuf_mutex); + } +EXPORT_SYMBOL_GPL(greybus_free_gbuf); + +struct gbuf *greybus_get_gbuf(struct gbuf *gbuf) +{ + mutex_lock(&gbuf_mutex); + kref_get(&gbuf->kref); + mutex_unlock(&gbuf_mutex); + return gbuf; +} +EXPORT_SYMBOL_GPL(greybus_get_gbuf); + + int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t mem_flags) { diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index d9cfc3b..95225f2 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -52,10 +52,7 @@ typedef void (*gbuf_complete_t)(struct gbuf *gbuf); struct gbuf { struct kref kref; - void *hcpriv; - - struct list_head anchor_list; - struct gbuf_anchor *anchor; // FIXME do we need? + void *hdpriv; struct greybus_device *gdev; struct gdev_cport *cport; @@ -65,8 +62,10 @@ struct gbuf { u32 transfer_buffer_length; u32 actual_length; +#if 0 struct scatterlist *sg; // FIXME do we need? int num_sgs; +#endif void *context; gbuf_complete_t complete; @@ -92,6 +91,31 @@ struct gb_gpio_device; struct gb_sdio_host; struct gb_tty; struct gb_usb_device; +struct greybus_host_device; + +/* Greybus "Host driver" structure, needed by a host controller driver to be + * able to handle both SVC control as well as "real" greybus messages + */ +struct greybus_host_driver { + size_t hd_priv_size; + + int (*start)(struct greybus_host_device *hd); + int (*alloc_gbuf)(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask); + void (*free_gbuf)(struct gbuf *gbuf); +}; + +struct greybus_host_device { + struct kref kref; + const struct greybus_host_driver *driver; + unsigned long hd_priv_size; + + /* Private data for the host driver */ + unsigned long hd_priv[0] __attribute__ ((aligned(sizeof(s64)))); +}; + +struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *host_driver, + struct device *parent); + /* Increase these values if needed */ #define MAX_CPORTS_PER_MODULE 10 @@ -108,6 +132,8 @@ struct greybus_device { struct gdev_cport *cport[MAX_CPORTS_PER_MODULE]; struct gdev_string *string[MAX_STRINGS_PER_MODULE]; + struct greybus_host_device *hd; + struct gb_i2c_device *gb_i2c_dev; struct gb_gpio_device *gb_gpio_dev; struct gb_sdio_host *gb_sdio_host; @@ -118,8 +144,13 @@ struct greybus_device { struct gbuf *greybus_alloc_gbuf(struct greybus_device *gdev, struct gdev_cport *cport, - gfp_t mem_flags); + gbuf_complete_t complete, + unsigned int size, + gfp_t gfp_mask, + void *context); void greybus_free_gbuf(struct gbuf *gbuf); +struct gbuf *greybus_get_gbuf(struct gbuf *gbuf); +#define greybus_put_gbuf greybus_free_gbuf int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t mem_flags); int greybus_kill_gbuf(struct gbuf *gbuf); -- cgit v0.10.2 From 68f1fc4d2c9c908b1a6f00847743545082353e99 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 7 Sep 2014 13:12:11 -0700 Subject: greybus: more hd work diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 5b06b19..2fb2cc1 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -22,7 +22,8 @@ struct ap_msg { u8 *data; - int size; + size_t size; + struct greybus_host_device *hd; struct list_head list; }; @@ -31,6 +32,21 @@ static spinlock_t ap_msg_list_lock; static struct task_struct *ap_thread; static wait_queue_head_t ap_wait; + +static struct svc_msg *convert_ap_message(struct ap_msg *ap_msg) +{ + struct svc_msg *svc_msg; + + // FIXME - validate message, right now we are trusting the size and data + // from the AP, what could go wrong? :) + // for now, just cast the pointer and run away... + + svc_msg = (struct svc_msg *)ap_msg->data; + return svc_msg; +} + + + static struct ap_msg *get_ap_msg(void) { struct ap_msg *ap_msg; @@ -49,6 +65,7 @@ static struct ap_msg *get_ap_msg(void) static int ap_process_loop(void *data) { struct ap_msg *ap_msg; + struct svc_msg *svc_msg; while (!kthread_should_stop()) { wait_event_interruptible(ap_wait, kthread_should_stop()); @@ -61,7 +78,12 @@ static int ap_process_loop(void *data) if (!ap_msg) continue; - // FIXME - process the message + /* Turn the "raw" data into a real message */ + svc_msg = convert_ap_message(ap_msg); + if (svc_msg) { + /* Pass the message to the host controller */ + ap_msg->hd->driver->ap_msg(svc_msg, ap_msg->hd); + } /* clean the message up */ kfree(ap_msg->data); @@ -70,7 +92,7 @@ static int ap_process_loop(void *data) return 0; } -int gb_new_ap_msg(u8 *data, int size) +int gb_new_ap_msg(u8 *data, int size, struct greybus_host_device *hd) { struct ap_msg *ap_msg; unsigned long flags; @@ -96,6 +118,7 @@ int gb_new_ap_msg(u8 *data, int size) } memcpy(ap_msg->data, data, size); ap_msg->size = size; + ap_msg->hd = hd; spin_lock_irqsave(&ap_msg_list_lock, flags); list_add(&ap_msg->list, &ap_msg_list); diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 517b260..5c633a39 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include "greybus.h" @@ -449,6 +448,17 @@ void greybus_remove_device(struct greybus_device *gdev) // FIXME - device_remove(&gdev->dev); } +static DEFINE_MUTEX(hd_mutex); + +static void free_hd(struct kref *kref) +{ + struct greybus_host_device *hd; + + hd = container_of(kref, struct greybus_host_device, kref); + + kfree(hd); +} + struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver, struct device *parent) { @@ -464,6 +474,12 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver } EXPORT_SYMBOL_GPL(greybus_create_hd); +void greybus_remove_hd(struct greybus_host_device *hd) +{ + kref_put_mutex(&hd->kref, free_hd, &hd_mutex); +} +EXPORT_SYMBOL_GPL(greybus_remove_hd); + static int __init gb_init(void) { diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index a08e4dd..8589273 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -82,15 +82,30 @@ static void free_gbuf(struct gbuf *gbuf) } +/* Main message loop for ap messages */ +/* Odds are, most of this logic can move to core.c someday, but as we only have + * one host controller driver for now, let's leave it here */ +static void ap_msg(struct svc_msg *svc_msg, struct greybus_host_device *hd) +{ + struct es1_ap_dev *es1 = hd_to_es1(hd); + + /* Look at the message to figure out what to do with it */ + + +} + + static struct greybus_host_driver es1_driver = { .hd_priv_size = sizeof(struct es1_ap_dev), .alloc_gbuf = alloc_gbuf, .free_gbuf = free_gbuf, + .ap_msg = ap_msg, }; void ap_in_callback(struct urb *urb) { + struct es1_ap_dev *es1 = urb->context; struct device *dev = &urb->dev->dev; int status = urb->status; int retval; @@ -115,7 +130,7 @@ void ap_in_callback(struct urb *urb) /* We have a message, create a new message structure, add it to the * list, and wake up our thread that will process the messages. */ - gb_new_ap_msg(urb->transfer_buffer, urb->actual_length); + gb_new_ap_msg(urb->transfer_buffer, urb->actual_length, es1->hd); exit: /* resubmit the urb to get more messages */ @@ -211,8 +226,7 @@ static void ap_disconnect(struct usb_interface *interface) usb_put_dev(es1->usb_dev); kfree(es1->ap_buffer); - // FIXME - //greybus_destroy_hd(es1->hd); + greybus_remove_hd(es1->hd); } static struct usb_driver es1_ap_driver = { diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 95225f2..2f67df5 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -92,6 +92,7 @@ struct gb_sdio_host; struct gb_tty; struct gb_usb_device; struct greybus_host_device; +struct svc_msg; /* Greybus "Host driver" structure, needed by a host controller driver to be * able to handle both SVC control as well as "real" greybus messages @@ -102,6 +103,7 @@ struct greybus_host_driver { int (*start)(struct greybus_host_device *hd); int (*alloc_gbuf)(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask); void (*free_gbuf)(struct gbuf *gbuf); + void (*ap_msg)(struct svc_msg *svc_msg, struct greybus_host_device *hd); }; struct greybus_host_device { @@ -115,6 +117,7 @@ struct greybus_host_device { struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *host_driver, struct device *parent); +void greybus_remove_hd(struct greybus_host_device *hd); /* Increase these values if needed */ @@ -213,7 +216,7 @@ const u8 *greybus_string(struct greybus_device *gdev, int id); /* Internal functions to gb module, move to internal .h file eventually. */ -int gb_new_ap_msg(u8 *data, int length); +int gb_new_ap_msg(u8 *data, int length, struct greybus_host_device *hd); int gb_thread_init(void); void gb_thread_destroy(void); int gb_debugfs_init(void); -- cgit v0.10.2 From 43cc32a2ab9ba004fa2fec1893ca5bd3e13f64d2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 7 Sep 2014 13:51:12 -0700 Subject: greybus: first cut at parsing svc messages sent to the AP diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 2fb2cc1..a70404d 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -42,6 +42,12 @@ static struct svc_msg *convert_ap_message(struct ap_msg *ap_msg) // for now, just cast the pointer and run away... svc_msg = (struct svc_msg *)ap_msg->data; + + // FIXME - put in correct version numbers + if ((svc_msg->header.version_major != 0x00) && + (svc_msg->header.version_minor != 0x00)) + return NULL; + return svc_msg; } diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 8589273..12a5d0c 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -11,6 +11,7 @@ #include #include #include "greybus.h" +#include "svc_msg.h" static const struct usb_device_id id_table[] = { { USB_DEVICE(0xffff, 0x0001) }, // FIXME @@ -81,6 +82,124 @@ static void free_gbuf(struct gbuf *gbuf) kfree(buffer); } +static struct svc_msg *svc_msg_alloc(enum svc_function_type type) +{ + struct svc_msg *svc_msg; + + svc_msg = kzalloc((sizeof *svc_msg), GFP_KERNEL); + if (!svc_msg) + return NULL; + + // FIXME - verify we are only sending message types we should be + svc_msg->header.type = type; + return svc_msg; +} + +static void svc_msg_free(struct svc_msg *svc_msg) +{ + kfree(svc_msg); +} + +static int svc_msg_send(struct svc_msg *svc_msg) +{ + // FIXME - Do something with this message! + + + svc_msg_free(svc_msg); + return 0; +} + + +static void svc_handshake(struct svc_function_handshake *handshake, + struct es1_ap_dev *es1) +{ + struct svc_msg *svc_msg; + + /* A new SVC communication channel, let's verify it was for us */ + if (handshake->handshake_type != SVC_HANDSHAKE_SVC_HELLO) { + /* we don't know what to do with this, log it and return */ + dev_dbg(&es1->usb_intf->dev, + "received invalid handshake type %d\n", + handshake->handshake_type); + return; + } + + /* Send back a AP_HELLO message */ + svc_msg = svc_msg_alloc(SVC_FUNCTION_HANDSHAKE); + if (!svc_msg) + return; + + svc_msg->handshake.handshake_type = SVC_HANDSHAKE_AP_HELLO; + svc_msg_send(svc_msg); +} + +static void svc_management(struct svc_function_unipro_management *management, + struct es1_ap_dev *es1) +{ + /* What? An AP should not get this message */ + dev_err(&es1->usb_intf->dev, "Got an svc management message???\n"); +} + +static void svc_hotplug(struct svc_function_hotplug *hotplug, + struct es1_ap_dev *es1) +{ + u8 module_id = hotplug->module_id; + + switch (hotplug->hotplug_event) { + case SVC_HOTPLUG_EVENT: + dev_dbg(&es1->usb_intf->dev, "module id %d added\n", + module_id); + // FIXME - add the module to the system + break; + + case SVC_HOTUNPLUG_EVENT: + dev_dbg(&es1->usb_intf->dev, "module id %d removed\n", + module_id); + // FIXME - remove the module from the system + break; + + default: + dev_err(&es1->usb_intf->dev, "received invalid hotplug message type %d\n", + hotplug->hotplug_event); + break; + } +} + +static void svc_ddb(struct svc_function_ddb *ddb, struct es1_ap_dev *es1) +{ + /* What? An AP should not get this message */ + dev_err(&es1->usb_intf->dev, "Got an svc DDB message???\n"); +} + +static void svc_power(struct svc_function_power *power, struct es1_ap_dev *es1) +{ + u8 module_id = power->module_id; + + if (power->power_type != SVC_POWER_BATTERY_STATUS) { + dev_err(&es1->usb_intf->dev, "received invalid power type %d\n", + power->power_type); + return; + } + + dev_dbg(&es1->usb_intf->dev, "power status for module id %d is %d\n", + module_id, power->status.status); + + // FIXME - do something with the power information, like update our + // battery information... +} + +static void svc_epm(struct svc_function_epm *epm, struct es1_ap_dev *es1) +{ + /* What? An AP should not get this message */ + dev_err(&es1->usb_intf->dev, "Got an EPM message???\n"); +} + +static void svc_suspend(struct svc_function_suspend *suspend, + struct es1_ap_dev *es1) +{ + /* What? An AP should not get this message */ + dev_err(&es1->usb_intf->dev, "Got an suspend message???\n"); +} /* Main message loop for ap messages */ /* Odds are, most of this logic can move to core.c someday, but as we only have @@ -90,8 +209,32 @@ static void ap_msg(struct svc_msg *svc_msg, struct greybus_host_device *hd) struct es1_ap_dev *es1 = hd_to_es1(hd); /* Look at the message to figure out what to do with it */ - - + switch (svc_msg->header.type) { + case SVC_FUNCTION_HANDSHAKE: + svc_handshake(&svc_msg->handshake, es1); + break; + case SVC_FUNCTION_UNIPRO_NETWORK_MANAGEMENT: + svc_management(&svc_msg->management, es1); + break; + case SVC_FUNCTION_HOTPLUG: + svc_hotplug(&svc_msg->hotplug, es1); + break; + case SVC_FUNCTION_DDB: + svc_ddb(&svc_msg->ddb, es1); + break; + case SVC_FUNCTION_POWER: + svc_power(&svc_msg->power, es1); + break; + case SVC_FUNCTION_EPM: + svc_epm(&svc_msg->epm, es1); + break; + case SVC_FUNCTION_SUSPEND: + svc_suspend(&svc_msg->suspend, es1); + break; + default: + dev_err(&es1->usb_intf->dev, "received invalid SVC message type %d\n", + svc_msg->header.type); + } } -- cgit v0.10.2 From 33ea3a3f56d26f10e07ffe16fcaccaad904056d3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 7 Sep 2014 15:39:34 -0700 Subject: greybus: add battery module diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index c1e4e12..114089a 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -6,7 +6,8 @@ greybus-y := core.o \ i2c-gb.o \ gpio-gb.o \ sdio-gb.o \ - uart-gb.o + uart-gb.o \ + battery-gb.o obj-m += greybus.o obj-m += es1-ap-usb.o diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c new file mode 100644 index 0000000..123b2af --- /dev/null +++ b/drivers/staging/greybus/battery-gb.c @@ -0,0 +1,153 @@ +/* + * Battery driver for a Greybus module. + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include "greybus.h" + +struct gb_battery { + struct power_supply bat; + struct greybus_device *gdev; +}; +#define to_gb_battery(x) container_of(x, struct gb_battery, bat) + +static const struct greybus_module_id id_table[] = { + { GREYBUS_DEVICE(0x42, 0x42) }, /* make shit up */ + { }, /* terminating NULL entry */ +}; + +static int get_status(struct gb_battery *gb) +{ + // FIXME!!! + return 0; +} + +static int get_capacity(struct gb_battery *gb) +{ + // FIXME!!! + return 0; +} + +static int get_temp(struct gb_battery *gb) +{ + // FIXME!!! + return 0; +} + +static int get_voltage(struct gb_battery *gb) +{ + // FIXME!!! + return 0; +} + + + +static int get_property(struct power_supply *b, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct gb_battery *gb = to_gb_battery(b); + + switch (psp) { + case POWER_SUPPLY_PROP_TECHNOLOGY: + // FIXME - guess! + val->intval = POWER_SUPPLY_TECHNOLOGY_NiMH; + break; + + case POWER_SUPPLY_PROP_STATUS: + val->intval = get_status(gb); + break; + + case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: + val->intval = 4700000; // FIXME - guess??? + break; + + case POWER_SUPPLY_PROP_CAPACITY: + val->intval = get_capacity(gb); + break; + + case POWER_SUPPLY_PROP_TEMP: + val->intval = get_temp(gb); + break; + + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + val->intval = get_voltage(gb); + break; + + default: + return -EINVAL; + } + + return 0; +} + + +// FIXME - verify this list, odds are some can be removed and others added. +static enum power_supply_property battery_props[] = { + POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, + POWER_SUPPLY_PROP_CAPACITY, + POWER_SUPPLY_PROP_TEMP, + POWER_SUPPLY_PROP_VOLTAGE_NOW, +}; + +int gb_battery_probe(struct greybus_device *gdev, + const struct greybus_module_id *id) +{ + struct gb_battery *gb; + struct power_supply *b; + int retval; + + gb = kzalloc(sizeof(*gb), GFP_KERNEL); + if (!gb) + return -ENOMEM; + + b = &gb->bat; + // FIXME - get a better (i.e. unique) name + // FIXME - anything else needs to be set? + b->name = "gb_battery"; + b->type = POWER_SUPPLY_TYPE_BATTERY, + b->properties = battery_props, + b->num_properties = ARRAY_SIZE(battery_props), + b->get_property = get_property, + + retval = power_supply_register(&gdev->dev, b); + if (retval) { + kfree(gb); + return retval; + } + gdev->gb_battery = gb; + + return 0; +} + +void gb_battery_disconnect(struct greybus_device *gdev) +{ + struct gb_battery *gb; + + gb = gdev->gb_battery; + + power_supply_unregister(&gb->bat); + + kfree(gb); +} + +#if 0 +static struct greybus_driver battery_gb_driver = { + .probe = gb_battery_probe, + .disconnect = gb_battery_disconnect, + .id_table = id_table, +}; + +module_greybus_driver(battery_gb_driver); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Greg Kroah-Hartman "); +#endif diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 5c633a39..76938cd 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -210,8 +210,15 @@ static int gb_init_subdevs(struct greybus_device *gdev, retval = gb_tty_probe(gdev, id); if (retval) goto error_tty; + + retval = gb_battery_probe(gdev, id); + if (retval) + goto error_battery; return 0; +error_battery: + gb_tty_disconnect(gdev); + error_tty: gb_sdio_disconnect(gdev); @@ -444,6 +451,7 @@ void greybus_remove_device(struct greybus_device *gdev) gb_gpio_disconnect(gdev); gb_sdio_disconnect(gdev); gb_tty_disconnect(gdev); + gb_battery_disconnect(gdev); // FIXME - device_remove(&gdev->dev); } diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 2f67df5..2b96917 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -91,6 +91,7 @@ struct gb_gpio_device; struct gb_sdio_host; struct gb_tty; struct gb_usb_device; +struct gb_battery; struct greybus_host_device; struct svc_msg; @@ -142,6 +143,7 @@ struct greybus_device { struct gb_sdio_host *gb_sdio_host; struct gb_tty *gb_tty; struct gb_usb_device *gb_usb_dev; + struct gb_battery *gb_battery; }; #define to_greybus_device(d) container_of(d, struct greybus_device, dev) @@ -237,6 +239,8 @@ int gb_sdio_probe(struct greybus_device *gdev, const struct greybus_module_id *i void gb_sdio_disconnect(struct greybus_device *gdev); int gb_tty_probe(struct greybus_device *gdev, const struct greybus_module_id *id); void gb_tty_disconnect(struct greybus_device *gdev); +int gb_battery_probe(struct greybus_device *gdev, const struct greybus_module_id *id); +void gb_battery_disconnect(struct greybus_device *gdev); int gb_tty_init(void); void gb_tty_exit(void); -- cgit v0.10.2 From d47aa761612c9bc2174718889cdab185cb20b723 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 7 Sep 2014 15:54:24 -0700 Subject: greybus: battery FIXME added diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index 123b2af..242b34f 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -14,6 +14,10 @@ struct gb_battery { struct power_supply bat; + // FIXME + // we will want to keep the battery stats in here as we will be getting + // updates from the SVC "on the fly" so we don't have to always go ask + // the battery for some information. Hopefully... struct greybus_device *gdev; }; #define to_gb_battery(x) container_of(x, struct gb_battery, bat) @@ -47,8 +51,6 @@ static int get_voltage(struct gb_battery *gb) return 0; } - - static int get_property(struct power_supply *b, enum power_supply_property psp, union power_supply_propval *val) -- cgit v0.10.2 From fe3270425f5555bf382178f27327752f3f2c9c4a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 7 Sep 2014 15:57:07 -0700 Subject: greybus: minor whitespace cleanups to make checkpatch.pl happy diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index 242b34f..7d12433 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -90,7 +90,6 @@ static int get_property(struct power_supply *b, return 0; } - // FIXME - verify this list, odds are some can be removed and others added. static enum power_supply_property battery_props[] = { POWER_SUPPLY_PROP_TECHNOLOGY, @@ -102,7 +101,7 @@ static enum power_supply_property battery_props[] = { }; int gb_battery_probe(struct greybus_device *gdev, - const struct greybus_module_id *id) + const struct greybus_module_id *id) { struct gb_battery *gb; struct power_supply *b; diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 1444b3f..1bf9226 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -18,7 +18,6 @@ #include "greybus.h" - /** * greybus_alloc_gbuf - allocate a greybus buffer * @@ -85,7 +84,6 @@ void greybus_free_gbuf(struct gbuf *gbuf) { /* drop the reference count and get out of here */ kref_put_mutex(&gbuf->kref, free_gbuf, &gbuf_mutex); - } EXPORT_SYMBOL_GPL(greybus_free_gbuf); @@ -98,8 +96,6 @@ struct gbuf *greybus_get_gbuf(struct gbuf *gbuf) } EXPORT_SYMBOL_GPL(greybus_get_gbuf); - - int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t mem_flags) { return -ENOMEM; @@ -109,6 +105,3 @@ int greybus_kill_gbuf(struct gbuf *gbuf) { return -ENOMEM; } - - - -- cgit v0.10.2 From 8b9951480b996eac4699860042bf3d6a0ef4d064 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 8 Sep 2014 19:34:30 -0700 Subject: greybus: es1_ap_desc.c: updated ES1 USB device descriptor Interrupt IN endpoint added. diff --git a/drivers/staging/greybus/es1_ap_desc.c b/drivers/staging/greybus/es1_ap_desc.c index eec7349..8c558a4 100644 --- a/drivers/staging/greybus/es1_ap_desc.c +++ b/drivers/staging/greybus/es1_ap_desc.c @@ -1,3 +1,4 @@ +/* ES1 AP Bridge Chip USB descriptor definitions */ static const u8 es1_dev_descriptor[] = { 0x12, /* __u8 bLength */ @@ -45,19 +46,25 @@ static const u8 es1_config_descriptor[] = { 0xff, /* __u8 if_bInterfaceProtocol; Vendor-specific */ 0x00, /* __u8 if_iInterface; */ - /* two endpoints */ + /* three endpoints */ 0x07, /* __u8 ep_bLength; */ 0x05, /* __u8 ep_bDescriptorType; Endpoint */ 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ + 0x03, /* __u8 ep_bmAttributes; Bulk */ + 0x00, 0x04, /* __le16 ep_wMaxPacketSize; 1024 */ + 0x00 /* __u8 ep_bInterval; */ + + 0x07, /* __u8 ep_bLength; */ + 0x05, /* __u8 ep_bDescriptorType; Endpoint */ + 0x82, /* __u8 ep_bEndpointAddress; IN Endpoint 2 */ 0x02, /* __u8 ep_bmAttributes; Bulk */ - 0x40, 0x00, /* __le16 ep_wMaxPacketSize; 64??? */ + 0x00, 0x04, /* __le16 ep_wMaxPacketSize; 1024 */ 0x00 /* __u8 ep_bInterval; */ 0x07, /* __u8 ep_bLength; */ 0x05, /* __u8 ep_bDescriptorType; Endpoint */ 0x02, /* __u8 ep_bEndpointAddress; Out Endpoint 2 */ 0x02, /* __u8 ep_bmAttributes; Bulk */ - 0x40, 0x00, /* __le16 ep_wMaxPacketSize; 64??? */ + 0x00, 0x04, /* __le16 ep_wMaxPacketSize; 1024 */ 0x00 /* __u8 ep_bInterval; */ - }; -- cgit v0.10.2 From 47f6ef12fe6dfc4107597af4a44b045324c53c02 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 8 Sep 2014 20:09:08 -0700 Subject: greybus: es1: finialized USB device structure Set up device properly and start up the SVC interrupt in endpoint for processing data diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 12a5d0c..da35234 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -24,11 +24,12 @@ struct es1_ap_dev { struct usb_interface *usb_intf; struct greybus_host_device *hd; - __u8 ap_comm_endpoint; /* endpoint to talk to the AP */ - __u8 ap_in_endpoint; /* bulk in for CPort data */ - __u8 ap_out_endpoint; /* bulk out for CPort data */ - u8 *ap_buffer; - + __u8 control_endpoint; /* endpoint to send data to SVC */ + __u8 svc_endpoint; /* endpoint for SVC data */ + __u8 cport_in_endpoint; /* bulk in for CPort data */ + __u8 cport_out_endpoint; /* bulk out for CPort data */ + u8 *svc_buffer; /* buffer for SVC messages coming in */ + struct urb *svc_urb; /* urb for SVC messages coming in */ }; static inline struct es1_ap_dev *hd_to_es1(struct greybus_host_device *hd) @@ -245,8 +246,8 @@ static struct greybus_host_driver es1_driver = { .ap_msg = ap_msg, }; - -void ap_in_callback(struct urb *urb) +/* Callback for when we get a SVC message */ +static void svc_callback(struct urb *urb) { struct es1_ap_dev *es1 = urb->context; struct device *dev = &urb->dev->dev; @@ -282,7 +283,7 @@ exit: dev_err(dev, "Can not submit urb for AP data: %d\n", retval); } -void ap_out_callback(struct urb *urb) +void cport_in_callback(struct urb *urb) { struct device *dev = &urb->dev->dev; int status = urb->status; @@ -304,12 +305,45 @@ void ap_out_callback(struct urb *urb) goto exit; } - // FIXME - queue up next AP message to send??? + // FIXME - handle the CPort in data exit: return; } +void cport_out_callback(struct urb *urb) +{ + struct device *dev = &urb->dev->dev; + int status = urb->status; + + switch (status) { + case 0: + break; + case -EOVERFLOW: + dev_err(dev, "%s: overflow actual length is %d\n", + __func__, urb->actual_length); + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + case -EILSEQ: + /* device is gone, stop sending */ + return; + default: + dev_err(dev, "%s: unknown status %d\n", __func__, status); + goto exit; + } + // FIXME - handle the CPort out data callback +exit: + return; +} + +/* + * The ES1 USB Bridge device contains 4 endpoints + * 1 Control - usual USB stuff + AP -> SVC messages + * 1 Interrupt IN - SVC -> AP messages + * 1 Bulk IN - CPort data in + * 1 Bulk OUT - CPorta data out + */ static int ap_probe(struct usb_interface *interface, const struct usb_device_id *id) { @@ -318,7 +352,13 @@ static int ap_probe(struct usb_interface *interface, struct usb_device *udev; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; + bool int_in_found = false; + bool bulk_in_found = false; + bool bulk_out_found = false; + int retval = -ENOMEM; int i; + int buffer_size = 0; + u8 svc_interval = 0; udev = usb_get_dev(interface_to_usbdev(interface)); @@ -328,34 +368,69 @@ static int ap_probe(struct usb_interface *interface, es1 = hd_to_es1(hd); es1->hd = hd; + es1->usb_intf = interface; + es1->usb_dev = udev; + usb_set_intfdata(interface, es1); /* Control endpoint is the pipe to talk to this AP, so save it off */ endpoint = &udev->ep0.desc; - es1->ap_comm_endpoint = endpoint->bEndpointAddress; + es1->control_endpoint = endpoint->bEndpointAddress; - // FIXME - // figure out endpoint for talking to the AP. + /* find all 3 of our endpoints */ iface_desc = interface->cur_altsetting; for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; - if (usb_endpoint_is_bulk_in(endpoint)) { - es1->ap_in_endpoint = endpoint->bEndpointAddress; + if (usb_endpoint_is_int_in(endpoint)) { + es1->svc_endpoint = endpoint->bEndpointAddress; + buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); + svc_interval = endpoint->bInterval; + int_in_found = true; + } else if (usb_endpoint_is_bulk_in(endpoint)) { + es1->cport_in_endpoint = endpoint->bEndpointAddress; + bulk_in_found = true; + } else if (usb_endpoint_is_bulk_out(endpoint)) { + es1->cport_out_endpoint = endpoint->bEndpointAddress; + bulk_out_found = true; + } else { + dev_err(&udev->dev, + "Unknown endpoint type found, address %x\n", + endpoint->bEndpointAddress); } - if (usb_endpoint_is_bulk_out(endpoint)) { - es1->ap_out_endpoint = endpoint->bEndpointAddress; - } - // FIXME - properly exit once found the AP endpoint - // FIXME - set up cport endpoints + } + if ((int_in_found == false) || + (bulk_in_found == false) || + (bulk_out_found == false)) { + dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n"); + goto error; } - // FIXME - allocate buffer - // FIXME = start up talking, then create the gb "devices" based on what the AP tells us. + /* Create our buffer and URB to get SVC messages, and start it up */ + es1->svc_buffer = kmalloc(buffer_size, GFP_KERNEL); + if (!es1->svc_buffer) + goto error; + + es1->svc_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!es1->svc_urb) + goto error_urb; + + usb_fill_int_urb(es1->svc_urb, udev, + usb_rcvintpipe(udev, es1->svc_endpoint), + es1->svc_buffer, buffer_size, svc_callback, + es1, svc_interval); + retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); + if (retval) + goto error_submit_urb; - es1->usb_intf = interface; - es1->usb_dev = udev; - usb_set_intfdata(interface, es1); return 0; + +error_submit_urb: + usb_free_urb(es1->svc_urb); +error_urb: + kfree(es1->svc_buffer); +error: + greybus_remove_hd(es1->hd); + return retval; } static void ap_disconnect(struct usb_interface *interface) @@ -365,11 +440,11 @@ static void ap_disconnect(struct usb_interface *interface) es1 = usb_get_intfdata(interface); /* Tear down everything! */ - + usb_kill_urb(es1->svc_urb); usb_put_dev(es1->usb_dev); - kfree(es1->ap_buffer); - + kfree(es1->svc_buffer); greybus_remove_hd(es1->hd); + usb_set_intfdata(interface, NULL); } static struct usb_driver es1_ap_driver = { -- cgit v0.10.2 From d9d077fdbc474150b9494fc45855a9cec781e778 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 8 Sep 2014 20:11:18 -0700 Subject: greybus: es1: forgot to free our urb on disconnect diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index da35234..767981a 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -441,6 +441,7 @@ static void ap_disconnect(struct usb_interface *interface) /* Tear down everything! */ usb_kill_urb(es1->svc_urb); + usb_free_urb(es1->svc_urb); usb_put_dev(es1->usb_dev); kfree(es1->svc_buffer); greybus_remove_hd(es1->hd); -- cgit v0.10.2 From 05ad189c23ad278c5586936bbb08147ac6f479be Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 9 Sep 2014 13:55:03 -0500 Subject: greybus: switch to the term "manifest" We agreed to rename a few things to improve clarity. This patch implements one of those changes. The blob of data that describes what's relevant to Greybus within an Ara module will now be called the "module manifest." In addition, in the context of Greybus we'll also be calling what's in an Ara module a "module" or "Greybus module." So this patch renames some structures and updates some comments. It also renames "greybus_desc.h" to be "greybus_manifest.h", and renames greybus_new_device() to be greybus_new_module(). Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index a70404d..aee47f5 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -17,7 +17,7 @@ #include #include #include "svc_msg.h" -#include "greybus_desc.h" +#include "greybus_manifest.h" #include "greybus.h" struct ap_msg { diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 76938cd..107e1fb 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -344,16 +344,16 @@ static int create_cport(struct greybus_device *gdev, } /** - * greybus_new_device: + * greybus_new_module: * - * Pass in a buffer that _should_ be a set of greybus descriptor fields and spit - * out a greybus device structure. + * Pass in a buffer that _should_ contain a Greybus module manifest + * and spit out a greybus device structure. */ -struct greybus_device *greybus_new_device(struct device *parent, +struct greybus_device *greybus_new_module(struct device *parent, int module_number, u8 *data, int size) { struct greybus_device *gdev; - struct greybus_descriptor_block_header *block; + struct greybus_manifest_header *header; struct greybus_descriptor *desc; int retval; int overall_size; @@ -361,8 +361,8 @@ struct greybus_device *greybus_new_device(struct device *parent, u8 version_major; u8 version_minor; - /* we have to have at _least_ the block header */ - if (size <= sizeof(struct greybus_descriptor_block_header)) + /* we have to have at _least_ the manifest header */ + if (size <= sizeof(struct greybus_manifest_header)) return NULL; gdev = kzalloc(sizeof(*gdev), GFP_KERNEL); @@ -379,21 +379,21 @@ struct greybus_device *greybus_new_device(struct device *parent, device_initialize(&gdev->dev); dev_set_name(&gdev->dev, "%d", module_number); - block = (struct greybus_descriptor_block_header *)data; - overall_size = le16_to_cpu(block->size); + header = (struct greybus_manifest_header *)data; + overall_size = le16_to_cpu(header->size); if (overall_size != size) { - dev_err(parent, "size != block header size, %d != %d\n", size, - overall_size); + dev_err(parent, "size != manifest header size, %d != %d\n", + size, overall_size); goto error; } - version_major = block->version_major; - version_minor = block->version_minor; + version_major = header->version_major; + version_minor = header->version_minor; // FIXME - check version major/minor here! - size -= sizeof(struct greybus_descriptor_block_header); - data += sizeof(struct greybus_descriptor_block_header); + size -= sizeof(struct greybus_manifest_header); + data += sizeof(struct greybus_manifest_header); while (size > 0) { desc = (struct greybus_descriptor *)data; desc_size = le16_to_cpu(desc->header.size); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 2b96917..a8d13b5 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -16,7 +16,7 @@ #include #include #include "greybus_id.h" -#include "greybus_desc.h" +#include "greybus_manifest.h" #define GREYBUS_DEVICE_ID_MATCH_DEVICE \ @@ -209,7 +209,7 @@ void greybus_deregister(struct greybus_driver *driver); int greybus_disabled(void); -struct greybus_device *greybus_new_device(struct device *parent, +struct greybus_device *greybus_new_module(struct device *parent, int module_number, u8 *data, int size); void greybus_remove_device(struct greybus_device *gdev); diff --git a/drivers/staging/greybus/greybus_desc.h b/drivers/staging/greybus/greybus_desc.h deleted file mode 100644 index 592b651..0000000 --- a/drivers/staging/greybus/greybus_desc.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Greybus device descriptor definition - * - * Defined in the "Greybus Application Protocol" document. - * See that document for any details on these values and structures. - * - * Copyright 2014 Google Inc. - */ - -#ifndef __GREYBUS_DESC_H -#define __GREYBUS_DESC_H - -#pragma pack(push, 1) - -struct greybus_descriptor_block_header { - __le16 size; - __u8 version_major; - __u8 version_minor; -}; - -enum greybus_descriptor_type { - GREYBUS_TYPE_INVALID = 0x0000, - GREYBUS_TYPE_FUNCTION = 0x0001, - GREYBUS_TYPE_MODULE_ID = 0x0002, - GREYBUS_TYPE_SERIAL_NUMBER = 0x0003, - GREYBUS_TYPE_STRING = 0x0004, - GREYBUS_TYPE_CPORT = 0x0005, -}; - -struct greybus_descriptor_header { - __le16 size; - __le16 type; /* enum greybus_descriptor_type */ -}; - -enum greybus_function_class { - GREYBUS_FUNCTION_CONTROL = 0x00, - GREYBUS_FUNCTION_USB = 0x01, - GREYBUS_FUNCTION_GPIO = 0x02, - GREYBUS_FUNCTION_SPI = 0x03, - GREYBUS_FUNCTION_UART = 0x04, - GREYBUS_FUNCTION_PWM = 0x05, - GREYBUS_FUNCTION_I2S = 0x06, - GREYBUS_FUNCTION_I2C = 0x07, - GREYBUS_FUNCTION_SDIO = 0x08, - GREYBUS_FUNCTION_HID = 0x09, - GREYBUS_FUNCTION_DISPLAY = 0x0a, - GREYBUS_FUNCTION_CAMERA = 0x0b, - GREYBUS_FUNCTION_SENSOR = 0x0c, - GREYBUS_FUNCTION_VENDOR = 0xff, -}; - -struct greybus_descriptor_function { - __le16 number; - __le16 cport; - __u8 class; /* enum greybus_function_class */ - __u8 subclass; - __u8 protocol; - __u8 reserved; -}; - -struct greybus_descriptor_module_id { - __le16 vendor; - __le16 product; - __le16 version; - __u8 vendor_stringid; - __u8 product_stringid; -}; - -struct greybus_descriptor_serial_number { - __le64 serial_number; -}; - -struct greybus_descriptor_string { - __le16 length; - __u8 id; - __u8 string[0]; -}; - -struct greybus_descriptor_cport { - __le16 number; - __le16 size; - __u8 speed; // FIXME - __u8 reserved; -}; - -struct greybus_descriptor { - struct greybus_descriptor_header header; - union { - struct greybus_descriptor_function function; - struct greybus_descriptor_module_id module_id; - struct greybus_descriptor_serial_number serial_number; - struct greybus_descriptor_string string; - struct greybus_descriptor_cport cport; - }; -}; - -#pragma pack(pop) - -#endif /* __GREYBUS_DESC_H */ diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h new file mode 100644 index 0000000..293451e --- /dev/null +++ b/drivers/staging/greybus/greybus_manifest.h @@ -0,0 +1,99 @@ +/* + * Greybus device descriptor definition + * + * Defined in the "Greybus Application Protocol" document. + * See that document for any details on these values and structures. + * + * Copyright 2014 Google Inc. + */ + +#ifndef __GREYBUS_DESC_H +#define __GREYBUS_DESC_H + +#pragma pack(push, 1) + +struct greybus_manifest_header { + __le16 size; + __u8 version_major; + __u8 version_minor; +}; + +enum greybus_descriptor_type { + GREYBUS_TYPE_INVALID = 0x0000, + GREYBUS_TYPE_FUNCTION = 0x0001, + GREYBUS_TYPE_MODULE_ID = 0x0002, + GREYBUS_TYPE_SERIAL_NUMBER = 0x0003, + GREYBUS_TYPE_STRING = 0x0004, + GREYBUS_TYPE_CPORT = 0x0005, +}; + +struct greybus_descriptor_header { + __le16 size; + __le16 type; /* enum greybus_descriptor_type */ +}; + +enum greybus_function_class { + GREYBUS_FUNCTION_CONTROL = 0x00, + GREYBUS_FUNCTION_USB = 0x01, + GREYBUS_FUNCTION_GPIO = 0x02, + GREYBUS_FUNCTION_SPI = 0x03, + GREYBUS_FUNCTION_UART = 0x04, + GREYBUS_FUNCTION_PWM = 0x05, + GREYBUS_FUNCTION_I2S = 0x06, + GREYBUS_FUNCTION_I2C = 0x07, + GREYBUS_FUNCTION_SDIO = 0x08, + GREYBUS_FUNCTION_HID = 0x09, + GREYBUS_FUNCTION_DISPLAY = 0x0a, + GREYBUS_FUNCTION_CAMERA = 0x0b, + GREYBUS_FUNCTION_SENSOR = 0x0c, + GREYBUS_FUNCTION_VENDOR = 0xff, +}; + +struct greybus_descriptor_function { + __le16 number; + __le16 cport; + __u8 class; /* enum greybus_function_class */ + __u8 subclass; + __u8 protocol; + __u8 reserved; +}; + +struct greybus_descriptor_module_id { + __le16 vendor; + __le16 product; + __le16 version; + __u8 vendor_stringid; + __u8 product_stringid; +}; + +struct greybus_descriptor_serial_number { + __le64 serial_number; +}; + +struct greybus_descriptor_string { + __le16 length; + __u8 id; + __u8 string[0]; +}; + +struct greybus_descriptor_cport { + __le16 number; + __le16 size; + __u8 speed; // FIXME + __u8 reserved; +}; + +struct greybus_descriptor { + struct greybus_descriptor_header header; + union { + struct greybus_descriptor_function function; + struct greybus_descriptor_module_id module_id; + struct greybus_descriptor_serial_number serial_number; + struct greybus_descriptor_string string; + struct greybus_descriptor_cport cport; + }; +}; + +#pragma pack(pop) + +#endif /* __GREYBUS_DESC_H */ -- cgit v0.10.2 From badad68e3adc3d0b7cbfe66902cb21c97833e242 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 9 Sep 2014 13:55:04 -0500 Subject: greybus: define struct greybus_manifest Define a structure that describes the entire greybus manifest. Adjust greybus_new_module() to use that, making it explicit that it's not just a header that's being provided to that function. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 107e1fb..95655e2 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -353,7 +353,7 @@ struct greybus_device *greybus_new_module(struct device *parent, int module_number, u8 *data, int size) { struct greybus_device *gdev; - struct greybus_manifest_header *header; + struct greybus_manifest *manifest; struct greybus_descriptor *desc; int retval; int overall_size; @@ -362,7 +362,7 @@ struct greybus_device *greybus_new_module(struct device *parent, u8 version_minor; /* we have to have at _least_ the manifest header */ - if (size <= sizeof(struct greybus_manifest_header)) + if (size <= sizeof(manifest->header)) return NULL; gdev = kzalloc(sizeof(*gdev), GFP_KERNEL); @@ -379,21 +379,21 @@ struct greybus_device *greybus_new_module(struct device *parent, device_initialize(&gdev->dev); dev_set_name(&gdev->dev, "%d", module_number); - header = (struct greybus_manifest_header *)data; - overall_size = le16_to_cpu(header->size); + manifest = (struct greybus_manifest *)data; + overall_size = le16_to_cpu(manifest->header.size); if (overall_size != size) { dev_err(parent, "size != manifest header size, %d != %d\n", size, overall_size); goto error; } - version_major = header->version_major; - version_minor = header->version_minor; + version_major = manifest->header.version_major; + version_minor = manifest->header.version_minor; // FIXME - check version major/minor here! - size -= sizeof(struct greybus_manifest_header); - data += sizeof(struct greybus_manifest_header); + size -= sizeof(manifest->header); + data += sizeof(manifest->header); while (size > 0) { desc = (struct greybus_descriptor *)data; desc_size = le16_to_cpu(desc->header.size); diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 293451e..8b4acd3 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -94,6 +94,11 @@ struct greybus_descriptor { }; }; +struct greybus_manifest { + struct greybus_manifest_header header; + struct greybus_descriptor descriptors[0]; +}; + #pragma pack(pop) #endif /* __GREYBUS_DESC_H */ -- cgit v0.10.2 From a5808add9a6cae290af60bb3b4efd2c9d3208588 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 9 Sep 2014 13:55:06 -0500 Subject: greybus: call put_device() on error As soon as we've called device_initialize() we're required to call put_device() in order to drop our reference to the device structure. This was missed in the error path in greybus_new_module(). Fix that. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 95655e2..3bb8f9c 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -440,6 +440,7 @@ struct greybus_device *greybus_new_module(struct device *parent, return gdev; error: + put_device(&gdev->dev); greybus_module_release(&gdev->dev); return NULL; } -- cgit v0.10.2 From a22e15a1fc8d46139c6ca4b17b81c14783d3f5a2 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 9 Sep 2014 13:55:07 -0500 Subject: greybus: interpret descriptor type properly The type field in a manifest descriptor header is in little endian format. Make sure we interpret it that way. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 3bb8f9c..61a4bc6 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -398,7 +398,7 @@ struct greybus_device *greybus_new_module(struct device *parent, desc = (struct greybus_descriptor *)data; desc_size = le16_to_cpu(desc->header.size); - switch (desc->header.type) { + switch (le16_to_cpu(desc->header.type)) { case GREYBUS_TYPE_FUNCTION: retval = create_function(gdev, desc, desc_size); break; -- cgit v0.10.2 From 57fc0a110405ba305b525bede8cdf2e1b00b69a0 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 9 Sep 2014 13:55:08 -0500 Subject: greybus: validate descriptor sizes When interpreting a manifest descriptor header, don't assume there is enough space in the buffer to hold a descriptor header. Also, verify the remaining buffer is at least as big as the reported descriptor size. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 61a4bc6..4b7034d 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -395,8 +395,17 @@ struct greybus_device *greybus_new_module(struct device *parent, size -= sizeof(manifest->header); data += sizeof(manifest->header); while (size > 0) { + if (size < sizeof(desc->header)) { + dev_err(parent, "remaining size %d too small\n", size); + goto error; + } desc = (struct greybus_descriptor *)data; desc_size = le16_to_cpu(desc->header.size); + if (size < desc_size) { + dev_err(parent, "descriptor size %d too big\n", + desc_size); + goto error; + } switch (le16_to_cpu(desc->header.type)) { case GREYBUS_TYPE_FUNCTION: -- cgit v0.10.2 From e82bef42fdacd3434bd58738545a98c791fd64d1 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 9 Sep 2014 13:55:09 -0500 Subject: greybus: fix manifest parsing size bug The type-specific "create" routines that get called while parsing the descriptor entries in the module manifest assume the size they are provided is the size of their data portion only--not including the descriptor header. Compute this value in greybus_new_module(), and pass it to those functions rather than the full descriptor size. Move a few declarations to the innermost block that uses them. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 4b7034d..f239b96 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -354,10 +354,8 @@ struct greybus_device *greybus_new_module(struct device *parent, { struct greybus_device *gdev; struct greybus_manifest *manifest; - struct greybus_descriptor *desc; int retval; int overall_size; - int desc_size; u8 version_major; u8 version_minor; @@ -395,6 +393,10 @@ struct greybus_device *greybus_new_module(struct device *parent, size -= sizeof(manifest->header); data += sizeof(manifest->header); while (size > 0) { + struct greybus_descriptor *desc; + u16 desc_size; + size_t data_size; + if (size < sizeof(desc->header)) { dev_err(parent, "remaining size %d too small\n", size); goto error; @@ -406,26 +408,27 @@ struct greybus_device *greybus_new_module(struct device *parent, desc_size); goto error; } + data_size = (size_t)desc_size - sizeof(desc->header); switch (le16_to_cpu(desc->header.type)) { case GREYBUS_TYPE_FUNCTION: - retval = create_function(gdev, desc, desc_size); + retval = create_function(gdev, desc, data_size); break; case GREYBUS_TYPE_MODULE_ID: - retval = create_module_id(gdev, desc, desc_size); + retval = create_module_id(gdev, desc, data_size); break; case GREYBUS_TYPE_SERIAL_NUMBER: - retval = create_serial_number(gdev, desc, desc_size); + retval = create_serial_number(gdev, desc, data_size); break; case GREYBUS_TYPE_STRING: - retval = create_string(gdev, desc, desc_size); + retval = create_string(gdev, desc, data_size); break; case GREYBUS_TYPE_CPORT: - retval = create_cport(gdev, desc, desc_size); + retval = create_cport(gdev, desc, data_size); break; case GREYBUS_TYPE_INVALID: -- cgit v0.10.2 From 3d5453261b6e03b670c408c4139bbcc9076896a8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 9 Sep 2014 17:16:54 -0700 Subject: greybus: pass appropriate type to create function Based on a patch from Alex Elder . Alex's original description: Every descriptor in a manifest is interpreted by greybus_new_module(). We call a function to do initialization based on descriptor's type. Since we know the type of the descriptor at that point, we can pass to the called function the actual sub-type it needs (i.e., the union member associated with the type). This allows those functions to be slightly simplified, and more focused. Also change some size variables to have size_t type, and simplify a few spots further by using sizeof(object) in place of sizeof(type). diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index f239b96..647bc5b 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -237,53 +237,50 @@ static const struct greybus_module_id fake_gb_id = { }; static int create_function(struct greybus_device *gdev, - struct greybus_descriptor *desc, int desc_size) + struct greybus_descriptor_function *function, + size_t desc_size) { - int header_size = sizeof(struct greybus_descriptor_function); - - if (desc_size != header_size) { - dev_err(gdev->dev.parent, "invalid function header size %d\n", + if (desc_size != sizeof(*function)) { + dev_err(gdev->dev.parent, "invalid function header size %zu\n", desc_size); return -EINVAL; } - memcpy(&gdev->function, &desc->function, header_size); + memcpy(&gdev->function, function, desc_size); return 0; } static int create_module_id(struct greybus_device *gdev, - struct greybus_descriptor *desc, int desc_size) + struct greybus_descriptor_module_id *module_id, + size_t desc_size) { - int header_size = sizeof(struct greybus_descriptor_module_id); - - if (desc_size != header_size) { - dev_err(gdev->dev.parent, "invalid module header size %d\n", + if (desc_size != sizeof(*module_id)) { + dev_err(gdev->dev.parent, "invalid module header size %zu\n", desc_size); return -EINVAL; } - memcpy(&gdev->module_id, &desc->module_id, header_size); + memcpy(&gdev->module_id, module_id, desc_size); return 0; } static int create_serial_number(struct greybus_device *gdev, - struct greybus_descriptor *desc, int desc_size) + struct greybus_descriptor_serial_number *serial_num, + size_t desc_size) { - int header_size = sizeof(struct greybus_descriptor_serial_number); - - if (desc_size != header_size) { - dev_err(gdev->dev.parent, "invalid serial number header size %d\n", + if (desc_size != sizeof(*serial_num)) { + dev_err(gdev->dev.parent, "invalid serial number header size %zu\n", desc_size); return -EINVAL; } - memcpy(&gdev->serial_number, &desc->serial_number, header_size); + memcpy(&gdev->serial_number, serial_num, desc_size); return 0; } static int create_string(struct greybus_device *gdev, - struct greybus_descriptor *desc, int desc_size) + struct greybus_descriptor_string *string, + size_t desc_size) { int string_size; - struct gdev_string *string; - int header_size = sizeof(struct greybus_descriptor_string); + struct gdev_string *gdev_string; if ((gdev->num_strings + 1) >= MAX_STRINGS_PER_MODULE) { dev_err(gdev->dev.parent, @@ -291,53 +288,53 @@ static int create_string(struct greybus_device *gdev, return -EINVAL; } - if (desc_size < header_size) { - dev_err(gdev->dev.parent, "invalid string header size %d\n", + if (desc_size < sizeof(*string)) { + dev_err(gdev->dev.parent, "invalid string header size %zu\n", desc_size); return -EINVAL; } - string_size = le16_to_cpu(desc->string.length); - string = kzalloc(sizeof(*string) + string_size + 1, GFP_KERNEL); - if (!string) + string_size = le16_to_cpu(string->length); + gdev_string = kzalloc(sizeof(*gdev_string) + string_size + 1, GFP_KERNEL); + if (!gdev_string) return -ENOMEM; - string->length = string_size; - string->id = desc->string.id; - memcpy(&string->string, &desc->string.string, string_size); + gdev_string->length = string_size; + gdev_string->id = string->id; + memcpy(&gdev_string->string, &string->string, string_size); - gdev->string[gdev->num_strings] = string; + gdev->string[gdev->num_strings] = gdev_string; gdev->num_strings++; return 0; } static int create_cport(struct greybus_device *gdev, - struct greybus_descriptor *desc, int desc_size) + struct greybus_descriptor_cport *cport, + size_t desc_size) { - struct gdev_cport *cport; - int header_size = sizeof(struct greybus_descriptor_cport); + struct gdev_cport *gdev_cport; if ((gdev->num_cports + 1) >= MAX_CPORTS_PER_MODULE) { dev_err(gdev->dev.parent, "too many cports for this module!\n"); return -EINVAL; } - if (desc_size != header_size) { + if (desc_size != sizeof(*cport)) { dev_err(gdev->dev.parent, - "invalid serial number header size %d\n", desc_size); + "invalid serial number header size %zu\n", desc_size); return -EINVAL; } - cport = kzalloc(sizeof(*cport), GFP_KERNEL); - if (!cport) + gdev_cport = kzalloc(sizeof(*gdev_cport), GFP_KERNEL); + if (!gdev_cport) return -ENOMEM; - cport->number = le16_to_cpu(desc->cport.number); - cport->size = le16_to_cpu(desc->cport.size); - cport->speed = desc->cport.speed; + gdev_cport->number = le16_to_cpu(cport->number); + gdev_cport->size = le16_to_cpu(cport->size); + gdev_cport->speed = cport->speed; - gdev->cport[gdev->num_cports] = cport; + gdev->cport[gdev->num_cports] = gdev_cport; gdev->num_cports++; return 0; @@ -412,23 +409,27 @@ struct greybus_device *greybus_new_module(struct device *parent, switch (le16_to_cpu(desc->header.type)) { case GREYBUS_TYPE_FUNCTION: - retval = create_function(gdev, desc, data_size); + retval = create_function(gdev, &desc->function, + data_size); break; case GREYBUS_TYPE_MODULE_ID: - retval = create_module_id(gdev, desc, data_size); + retval = create_module_id(gdev, &desc->module_id, + data_size); break; case GREYBUS_TYPE_SERIAL_NUMBER: - retval = create_serial_number(gdev, desc, data_size); + retval = create_serial_number(gdev, + &desc->serial_number, + data_size); break; case GREYBUS_TYPE_STRING: - retval = create_string(gdev, desc, data_size); + retval = create_string(gdev, &desc->string, data_size); break; case GREYBUS_TYPE_CPORT: - retval = create_cport(gdev, desc, data_size); + retval = create_cport(gdev, &desc->cport, data_size); break; case GREYBUS_TYPE_INVALID: -- cgit v0.10.2 From a6294fe8493cf0c98480f42d3057da2f98cc4ec1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 10 Sep 2014 17:12:20 -0700 Subject: greybus: fix endian issue in sysfs.c diff --git a/drivers/staging/greybus/sysfs.c b/drivers/staging/greybus/sysfs.c index 2393a6a..a24a9ed 100644 --- a/drivers/staging/greybus/sysfs.c +++ b/drivers/staging/greybus/sysfs.c @@ -145,7 +145,7 @@ static ssize_t serial_number_show(struct device *dev, struct greybus_device *gdev = to_greybus_device(dev); return sprintf(buf, "%llX\n", - (unsigned long long)gdev->serial_number.serial_number); + (unsigned long long)le64_to_cpu(gdev->serial_number.serial_number)); } static DEVICE_ATTR_RO(serial_number); -- cgit v0.10.2 From f91121b48fda4bba7eb298c51e9a871ec9c538d7 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 11 Sep 2014 08:22:06 -0700 Subject: greybus: Fix build errors on older kernels. Thanks to Marti for pointing out the code didn't build properly on 3.10. Added kernel_ver.h to handle any api mis-matches between the code and older kernel versions. diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index 3428220..bcf65087 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include "greybus.h" struct gb_gpio_device { @@ -90,10 +90,11 @@ int gb_gpio_probe(struct greybus_device *gdev, void gb_gpio_disconnect(struct greybus_device *gdev) { struct gb_gpio_device *gb_gpio_dev; + int retval; gb_gpio_dev = gdev->gb_gpio_dev; - gpiochip_remove(&gb_gpio_dev->chip); + retval = gpiochip_remove(&gb_gpio_dev->chip); kfree(gb_gpio_dev); } diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h new file mode 100644 index 0000000..40cc2e8 --- /dev/null +++ b/drivers/staging/greybus/kernel_ver.h @@ -0,0 +1,22 @@ +/* + * Greybus kernel "version" glue logic. + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + * + * Backports of newer kernel apis to allow the code to build properly on older + * kernel versions. Remove this file when merging to upstream, it should not be + * needed at all + */ + +#ifndef __GREYBUS_KERNEL_VER_H +#define __GREYBUS_KERNEL_VER_H + +#ifndef DEVICE_ATTR_RO +#define DEVICE_ATTR_RO(_name) \ + struct device_attribute dev_attr_##_name = __ATTR_RO(_name) +#endif + + +#endif /* __GREYBUS_KERNEL_VER_H */ diff --git a/drivers/staging/greybus/sysfs.c b/drivers/staging/greybus/sysfs.c index 2393a6a..c02ca55 100644 --- a/drivers/staging/greybus/sysfs.c +++ b/drivers/staging/greybus/sysfs.c @@ -18,6 +18,8 @@ #include "greybus.h" +#include "kernel_ver.h" + /* Function fields */ #define greybus_function_attr(field) \ static ssize_t function_##field##_show(struct device *dev, \ -- cgit v0.10.2 From 8c53e073f723cec46270cbc98dd690dd209f4fa2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 12 Sep 2014 20:47:11 -0700 Subject: greybus: AP: move a bunch of svc message handling logic into ap.c Add a send_svc_msg() callback to the host driver. hook up ES1 driver to send control USB messages as it's SVC transport. diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index aee47f5..53ad66c 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -32,6 +32,127 @@ static spinlock_t ap_msg_list_lock; static struct task_struct *ap_thread; static wait_queue_head_t ap_wait; +static struct svc_msg *svc_msg_alloc(enum svc_function_type type) +{ + struct svc_msg *svc_msg; + + svc_msg = kzalloc((sizeof *svc_msg), GFP_KERNEL); + if (!svc_msg) + return NULL; + + // FIXME - verify we are only sending message types we should be + svc_msg->header.type = type; + return svc_msg; +} + +static void svc_msg_free(struct svc_msg *svc_msg) +{ + kfree(svc_msg); +} + +static int svc_msg_send(struct svc_msg *svc_msg, struct greybus_host_device *hd) +{ + int retval; + + // FIXME - Do we need to do more than just pass it to the hd and then + // free it? + retval = hd->driver->send_svc_msg(svc_msg, hd); + + svc_msg_free(svc_msg); + return retval; +} + + +static void svc_handshake(struct svc_function_handshake *handshake, + struct greybus_host_device *hd) +{ + struct svc_msg *svc_msg; + + /* A new SVC communication channel, let's verify it was for us */ + if (handshake->handshake_type != SVC_HANDSHAKE_SVC_HELLO) { + /* we don't know what to do with this, log it and return */ + dev_dbg(&hd->dev, "received invalid handshake type %d\n", + handshake->handshake_type); + return; + } + + /* Send back a AP_HELLO message */ + svc_msg = svc_msg_alloc(SVC_FUNCTION_HANDSHAKE); + if (!svc_msg) + return; + + svc_msg->handshake.handshake_type = SVC_HANDSHAKE_AP_HELLO; + svc_msg_send(svc_msg, hd); +} + +static void svc_management(struct svc_function_unipro_management *management, + struct greybus_host_device *hd) +{ + /* What? An AP should not get this message */ + dev_err(&hd->dev, "Got an svc management message???\n"); +} + +static void svc_hotplug(struct svc_function_hotplug *hotplug, + struct greybus_host_device *hd) +{ + u8 module_id = hotplug->module_id; + + switch (hotplug->hotplug_event) { + case SVC_HOTPLUG_EVENT: + dev_dbg(&hd->dev, "module id %d added\n", module_id); + // FIXME - add the module to the system + break; + + case SVC_HOTUNPLUG_EVENT: + dev_dbg(&hd->dev, "module id %d removed\n", module_id); + // FIXME - remove the module from the system + break; + + default: + dev_err(&hd->dev, "received invalid hotplug message type %d\n", + hotplug->hotplug_event); + break; + } +} + +static void svc_ddb(struct svc_function_ddb *ddb, + struct greybus_host_device *hd) +{ + /* What? An AP should not get this message */ + dev_err(&hd->dev, "Got an svc DDB message???\n"); +} + +static void svc_power(struct svc_function_power *power, + struct greybus_host_device *hd) +{ + u8 module_id = power->module_id; + + if (power->power_type != SVC_POWER_BATTERY_STATUS) { + dev_err(&hd->dev, "received invalid power type %d\n", + power->power_type); + return; + } + + dev_dbg(&hd->dev, "power status for module id %d is %d\n", + module_id, power->status.status); + + // FIXME - do something with the power information, like update our + // battery information... +} + +static void svc_epm(struct svc_function_epm *epm, + struct greybus_host_device *hd) +{ + /* What? An AP should not get this message */ + dev_err(&hd->dev, "Got an EPM message???\n"); +} + +static void svc_suspend(struct svc_function_suspend *suspend, + struct greybus_host_device *hd) +{ + /* What? An AP should not get this message */ + dev_err(&hd->dev, "Got an suspend message???\n"); +} static struct svc_msg *convert_ap_message(struct ap_msg *ap_msg) { @@ -43,16 +164,62 @@ static struct svc_msg *convert_ap_message(struct ap_msg *ap_msg) svc_msg = (struct svc_msg *)ap_msg->data; - // FIXME - put in correct version numbers - if ((svc_msg->header.version_major != 0x00) && - (svc_msg->header.version_minor != 0x00)) + /* Verify the version is something we can handle with this code */ + if ((svc_msg->header.version_major != GREYBUS_VERSION_MAJOR) && + (svc_msg->header.version_minor != GREYBUS_VERSION_MINOR)) return NULL; return svc_msg; } +static void process_ap_message(struct ap_msg *ap_msg) +{ + struct svc_msg *svc_msg; + struct greybus_host_device *hd; + + /* Turn the "raw" data into a real message */ + svc_msg = convert_ap_message(ap_msg); + if (!svc_msg) { + // FIXME log an error??? + return; + } + + hd = ap_msg->hd; + + /* Pass the message to the host controller */ +// ap_msg->hd->driver->ap_msg(svc_msg, ap_msg->hd); + + /* Look at the message to figure out what to do with it */ + switch (svc_msg->header.type) { + case SVC_FUNCTION_HANDSHAKE: + svc_handshake(&svc_msg->handshake, hd); + break; + case SVC_FUNCTION_UNIPRO_NETWORK_MANAGEMENT: + svc_management(&svc_msg->management, hd); + break; + case SVC_FUNCTION_HOTPLUG: + svc_hotplug(&svc_msg->hotplug, hd); + break; + case SVC_FUNCTION_DDB: + svc_ddb(&svc_msg->ddb, hd); + break; + case SVC_FUNCTION_POWER: + svc_power(&svc_msg->power, hd); + break; + case SVC_FUNCTION_EPM: + svc_epm(&svc_msg->epm, hd); + break; + case SVC_FUNCTION_SUSPEND: + svc_suspend(&svc_msg->suspend, hd); + break; + default: + dev_err(&hd->dev, "received invalid SVC message type %d\n", + svc_msg->header.type); + } +} + static struct ap_msg *get_ap_msg(void) { struct ap_msg *ap_msg; @@ -71,7 +238,6 @@ static struct ap_msg *get_ap_msg(void) static int ap_process_loop(void *data) { struct ap_msg *ap_msg; - struct svc_msg *svc_msg; while (!kthread_should_stop()) { wait_event_interruptible(ap_wait, kthread_should_stop()); @@ -84,12 +250,7 @@ static int ap_process_loop(void *data) if (!ap_msg) continue; - /* Turn the "raw" data into a real message */ - svc_msg = convert_ap_message(ap_msg); - if (svc_msg) { - /* Pass the message to the host controller */ - ap_msg->hd->driver->ap_msg(svc_msg, ap_msg->hd); - } + process_ap_message(ap_msg); /* clean the message up */ kfree(ap_msg->data); diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 767981a..f32023e 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -83,167 +83,33 @@ static void free_gbuf(struct gbuf *gbuf) kfree(buffer); } -static struct svc_msg *svc_msg_alloc(enum svc_function_type type) +#define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ +static int send_svc_msg(struct svc_msg *svc_msg, struct greybus_host_device *hd) { - struct svc_msg *svc_msg; - - svc_msg = kzalloc((sizeof *svc_msg), GFP_KERNEL); - if (!svc_msg) - return NULL; - - // FIXME - verify we are only sending message types we should be - svc_msg->header.type = type; - return svc_msg; -} - -static void svc_msg_free(struct svc_msg *svc_msg) -{ - kfree(svc_msg); -} - -static int svc_msg_send(struct svc_msg *svc_msg) -{ - // FIXME - Do something with this message! + struct es1_ap_dev *es1 = hd_to_es1(hd); + int retval; + /* SVC messages go down our control pipe */ + retval = usb_control_msg(es1->usb_dev, + usb_sndctrlpipe(es1->usb_dev, + es1->control_endpoint), + 0x01, /* vendor request AP message */ + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER, + 0x00, 0x00, + (char *)svc_msg, + sizeof(*svc_msg), + ES1_TIMEOUT); + if (retval != sizeof(*svc_msg)) + return retval; - svc_msg_free(svc_msg); return 0; } - -static void svc_handshake(struct svc_function_handshake *handshake, - struct es1_ap_dev *es1) -{ - struct svc_msg *svc_msg; - - /* A new SVC communication channel, let's verify it was for us */ - if (handshake->handshake_type != SVC_HANDSHAKE_SVC_HELLO) { - /* we don't know what to do with this, log it and return */ - dev_dbg(&es1->usb_intf->dev, - "received invalid handshake type %d\n", - handshake->handshake_type); - return; - } - - /* Send back a AP_HELLO message */ - svc_msg = svc_msg_alloc(SVC_FUNCTION_HANDSHAKE); - if (!svc_msg) - return; - - svc_msg->handshake.handshake_type = SVC_HANDSHAKE_AP_HELLO; - svc_msg_send(svc_msg); -} - -static void svc_management(struct svc_function_unipro_management *management, - struct es1_ap_dev *es1) -{ - /* What? An AP should not get this message */ - dev_err(&es1->usb_intf->dev, "Got an svc management message???\n"); -} - -static void svc_hotplug(struct svc_function_hotplug *hotplug, - struct es1_ap_dev *es1) -{ - u8 module_id = hotplug->module_id; - - switch (hotplug->hotplug_event) { - case SVC_HOTPLUG_EVENT: - dev_dbg(&es1->usb_intf->dev, "module id %d added\n", - module_id); - // FIXME - add the module to the system - break; - - case SVC_HOTUNPLUG_EVENT: - dev_dbg(&es1->usb_intf->dev, "module id %d removed\n", - module_id); - // FIXME - remove the module from the system - break; - - default: - dev_err(&es1->usb_intf->dev, "received invalid hotplug message type %d\n", - hotplug->hotplug_event); - break; - } -} - -static void svc_ddb(struct svc_function_ddb *ddb, struct es1_ap_dev *es1) -{ - /* What? An AP should not get this message */ - dev_err(&es1->usb_intf->dev, "Got an svc DDB message???\n"); -} - -static void svc_power(struct svc_function_power *power, struct es1_ap_dev *es1) -{ - u8 module_id = power->module_id; - - if (power->power_type != SVC_POWER_BATTERY_STATUS) { - dev_err(&es1->usb_intf->dev, "received invalid power type %d\n", - power->power_type); - return; - } - - dev_dbg(&es1->usb_intf->dev, "power status for module id %d is %d\n", - module_id, power->status.status); - - // FIXME - do something with the power information, like update our - // battery information... -} - -static void svc_epm(struct svc_function_epm *epm, struct es1_ap_dev *es1) -{ - /* What? An AP should not get this message */ - dev_err(&es1->usb_intf->dev, "Got an EPM message???\n"); -} - -static void svc_suspend(struct svc_function_suspend *suspend, - struct es1_ap_dev *es1) -{ - /* What? An AP should not get this message */ - dev_err(&es1->usb_intf->dev, "Got an suspend message???\n"); -} - -/* Main message loop for ap messages */ -/* Odds are, most of this logic can move to core.c someday, but as we only have - * one host controller driver for now, let's leave it here */ -static void ap_msg(struct svc_msg *svc_msg, struct greybus_host_device *hd) -{ - struct es1_ap_dev *es1 = hd_to_es1(hd); - - /* Look at the message to figure out what to do with it */ - switch (svc_msg->header.type) { - case SVC_FUNCTION_HANDSHAKE: - svc_handshake(&svc_msg->handshake, es1); - break; - case SVC_FUNCTION_UNIPRO_NETWORK_MANAGEMENT: - svc_management(&svc_msg->management, es1); - break; - case SVC_FUNCTION_HOTPLUG: - svc_hotplug(&svc_msg->hotplug, es1); - break; - case SVC_FUNCTION_DDB: - svc_ddb(&svc_msg->ddb, es1); - break; - case SVC_FUNCTION_POWER: - svc_power(&svc_msg->power, es1); - break; - case SVC_FUNCTION_EPM: - svc_epm(&svc_msg->epm, es1); - break; - case SVC_FUNCTION_SUSPEND: - svc_suspend(&svc_msg->suspend, es1); - break; - default: - dev_err(&es1->usb_intf->dev, "received invalid SVC message type %d\n", - svc_msg->header.type); - } -} - - static struct greybus_host_driver es1_driver = { .hd_priv_size = sizeof(struct es1_ap_dev), .alloc_gbuf = alloc_gbuf, .free_gbuf = free_gbuf, - .ap_msg = ap_msg, + .send_svc_msg = send_svc_msg, }; /* Callback for when we get a SVC message */ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index a8d13b5..2d7972f 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -19,6 +19,10 @@ #include "greybus_manifest.h" +/* Matches up with the Greybus Protocol specification document */ +#define GREYBUS_VERSION_MAJOR 0x01 +#define GREYBUS_VERSION_MINOR 0x00 + #define GREYBUS_DEVICE_ID_MATCH_DEVICE \ (GREYBUS_DEVICE_ID_MATCH_VENDOR | GREYBUS_DEVICE_ID_MATCH_PRODUCT) @@ -104,11 +108,12 @@ struct greybus_host_driver { int (*start)(struct greybus_host_device *hd); int (*alloc_gbuf)(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask); void (*free_gbuf)(struct gbuf *gbuf); - void (*ap_msg)(struct svc_msg *svc_msg, struct greybus_host_device *hd); + int (*send_svc_msg)(struct svc_msg *svc_msg, struct greybus_host_device *hd); }; struct greybus_host_device { - struct kref kref; + struct device dev; + struct kref kref; const struct greybus_host_driver *driver; unsigned long hd_priv_size; -- cgit v0.10.2 From 112997324db001eed32ec67909d5c8eed74a554d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 12 Sep 2014 21:17:37 -0700 Subject: greybus: es1: add the start of cport urb handling. diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index f32023e..c37deb1 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -19,6 +19,19 @@ static const struct usb_device_id id_table[] = { }; MODULE_DEVICE_TABLE(usb, id_table); +/* + * Number of CPort IN urbs in flight at any point in time. + * Adjust if we are having stalls in the USB buffer due to not enough urbs in + * flight. + */ +#define NUM_CPORT_IN_URB 4 + +/* Number of CPort OUT urbs in flight at any point in time. + * Adjust if we get messages saying we are out of urbs in the system log. + */ +#define NUM_CPORT_OUT_URB 8 + + struct es1_ap_dev { struct usb_device *usb_dev; struct usb_interface *usb_intf; @@ -30,6 +43,10 @@ struct es1_ap_dev { __u8 cport_out_endpoint; /* bulk out for CPort data */ u8 *svc_buffer; /* buffer for SVC messages coming in */ struct urb *svc_urb; /* urb for SVC messages coming in */ + struct urb *cport_in_urb[NUM_CPORT_IN_URB]; /* CPort IN urbs */ + u8 *cport_in_buffer[NUM_CPORT_IN_URB]; /* CPort IN buffers */ + struct urb *cport_out_urb[NUM_CPORT_OUT_URB]; /* CPort OUT urbs */ + u8 cport_out_urb_busy[NUM_CPORT_OUT_URB]; /* CPort OUT urb busy marker */ }; static inline struct es1_ap_dev *hd_to_es1(struct greybus_host_device *hd) @@ -37,6 +54,8 @@ static inline struct es1_ap_dev *hd_to_es1(struct greybus_host_device *hd) return (struct es1_ap_dev *)(hd->hd_priv); } +static void cport_out_callback(struct urb *urb); + /* * Allocate the actual buffer for this gbuf and device and cport * @@ -67,7 +86,8 @@ static int alloc_gbuf(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask) gbuf->transfer_buffer = &buffer[1]; gbuf->transfer_buffer_length = size; - gbuf->hdpriv = es1; /* really, we could do something else here... */ + /* When we send the gbuf, we need this pointer to be here */ + gbuf->hdpriv = es1; return 0; } @@ -105,11 +125,44 @@ static int send_svc_msg(struct svc_msg *svc_msg, struct greybus_host_device *hd) return 0; } +static struct urb *next_free_urb(struct es1_ap_dev *es1) +{ + // FIXME + return NULL; +} + +static int send_gbuf(struct gbuf *gbuf, struct greybus_host_device *hd, + gfp_t gfp_mask) +{ + struct es1_ap_dev *es1 = hd_to_es1(hd); + struct usb_device *udev = es1->usb_dev; + int retval; + u8 *transfer_buffer; + u8 *buffer; + struct urb *urb; + + transfer_buffer = gbuf->transfer_buffer; + buffer = &transfer_buffer[-1]; /* yes, we mean -1 */ + + /* Find a free urb */ + urb = next_free_urb(es1); + if (!urb) + return -ENOMEM; + + usb_fill_bulk_urb(urb, udev, + usb_sndbulkpipe(udev, es1->cport_out_endpoint), + buffer, gbuf->transfer_buffer_length + 1, + cport_out_callback, gbuf); + retval = usb_submit_urb(urb, gfp_mask); + return retval; +} + static struct greybus_host_driver es1_driver = { .hd_priv_size = sizeof(struct es1_ap_dev), .alloc_gbuf = alloc_gbuf, .free_gbuf = free_gbuf, .send_svc_msg = send_svc_msg, + .send_gbuf = send_gbuf, }; /* Callback for when we get a SVC message */ @@ -149,7 +202,7 @@ exit: dev_err(dev, "Can not submit urb for AP data: %d\n", retval); } -void cport_in_callback(struct urb *urb) +static void cport_in_callback(struct urb *urb) { struct device *dev = &urb->dev->dev; int status = urb->status; @@ -176,7 +229,7 @@ exit: return; } -void cport_out_callback(struct urb *urb) +static void cport_out_callback(struct urb *urb) { struct device *dev = &urb->dev->dev; int status = urb->status; @@ -278,7 +331,7 @@ static int ap_probe(struct usb_interface *interface, es1->svc_urb = usb_alloc_urb(0, GFP_KERNEL); if (!es1->svc_urb) - goto error_urb; + goto error_int_urb; usb_fill_int_urb(es1->svc_urb, udev, usb_rcvintpipe(udev, es1->svc_endpoint), @@ -288,11 +341,56 @@ static int ap_probe(struct usb_interface *interface, if (retval) goto error_submit_urb; + /* Allocate buffers for our cport in messages and start them up */ + for (i = 0; i < NUM_CPORT_IN_URB; ++i) { + struct urb *urb; + u8 *buffer; + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) + goto error_bulk_in_urb; + buffer = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!buffer) + goto error_bulk_in_urb; + + usb_fill_bulk_urb(urb, udev, + usb_rcvbulkpipe(udev, es1->cport_in_endpoint), + buffer, PAGE_SIZE, cport_in_callback, es1); + es1->cport_in_urb[i] = urb; + es1->cport_in_buffer[i] = buffer; + retval = usb_submit_urb(urb, GFP_KERNEL); + if (retval) + goto error_bulk_in_urb; + } + + /* Allocate urbs for our CPort OUT messages */ + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + struct urb *urb; + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) + goto error_bulk_out_urb; + + es1->cport_out_urb[i] = urb; + es1->cport_out_urb_busy[i] = false; /* just to be anal */ + } + return 0; +error_bulk_out_urb: + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) + usb_free_urb(es1->cport_out_urb[i]); + +error_bulk_in_urb: + for (i = 0; i < NUM_CPORT_IN_URB; ++i) { + usb_kill_urb(es1->cport_in_urb[i]); + usb_free_urb(es1->cport_in_urb[i]); + kfree(es1->cport_in_buffer[i]); + } + error_submit_urb: usb_free_urb(es1->svc_urb); -error_urb: +error_int_urb: kfree(es1->svc_buffer); error: greybus_remove_hd(es1->hd); @@ -302,10 +400,24 @@ error: static void ap_disconnect(struct usb_interface *interface) { struct es1_ap_dev *es1; + int i; es1 = usb_get_intfdata(interface); + if (!es1) + return; /* Tear down everything! */ + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + usb_kill_urb(es1->cport_out_urb[i]); + usb_free_urb(es1->cport_out_urb[i]); + } + + for (i = 0; i < NUM_CPORT_IN_URB; ++i) { + usb_kill_urb(es1->cport_in_urb[i]); + usb_free_urb(es1->cport_in_urb[i]); + kfree(es1->cport_in_buffer[i]); + } + usb_kill_urb(es1->svc_urb); usb_free_urb(es1->svc_urb); usb_put_dev(es1->usb_dev); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 2d7972f..573274b 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -109,6 +109,8 @@ struct greybus_host_driver { int (*alloc_gbuf)(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask); void (*free_gbuf)(struct gbuf *gbuf); int (*send_svc_msg)(struct svc_msg *svc_msg, struct greybus_host_device *hd); + int (*send_gbuf)(struct gbuf *gbuf, struct greybus_host_device *hd, + gfp_t gfp_mask); }; struct greybus_host_device { -- cgit v0.10.2 From 0dad95dc372057e628f8aced70fa0b8493896b1a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 13 Sep 2014 09:54:35 -0700 Subject: greybus: es1: allocate cport out urbs properly diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index c37deb1..cf2987e 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -46,7 +46,8 @@ struct es1_ap_dev { struct urb *cport_in_urb[NUM_CPORT_IN_URB]; /* CPort IN urbs */ u8 *cport_in_buffer[NUM_CPORT_IN_URB]; /* CPort IN buffers */ struct urb *cport_out_urb[NUM_CPORT_OUT_URB]; /* CPort OUT urbs */ - u8 cport_out_urb_busy[NUM_CPORT_OUT_URB]; /* CPort OUT urb busy marker */ + bool cport_out_urb_busy[NUM_CPORT_OUT_URB]; /* CPort OUT urb busy marker */ + spinlock_t cport_out_urb_lock; /* locks list of cport out urbs */ }; static inline struct es1_ap_dev *hd_to_es1(struct greybus_host_device *hd) @@ -125,10 +126,37 @@ static int send_svc_msg(struct svc_msg *svc_msg, struct greybus_host_device *hd) return 0; } -static struct urb *next_free_urb(struct es1_ap_dev *es1) +static struct urb *next_free_urb(struct es1_ap_dev *es1, gfp_t gfp_mask) { - // FIXME - return NULL; + struct urb *urb = NULL; + unsigned long flags; + int i; + + spin_lock_irqsave(&es1->cport_out_urb_lock, flags); + + /* Look in our pool of allocated urbs first, as that's the "fastest" */ + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + if (es1->cport_out_urb_busy[i] == false) { + es1->cport_out_urb_busy[i] = true; + urb = es1->cport_out_urb[i]; + break; + } + } + spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); + if (urb) + return urb; + + /* + * Crap, pool is empty, complain to the syslog and go allocate one + * dynamically as we have to succeed. + */ + dev_err(&es1->usb_dev->dev, + "No free CPort OUT urbs, having to dynamically allocate one!\n"); + urb = usb_alloc_urb(0, gfp_mask); + if (!urb) + return NULL; + + return urb; } static int send_gbuf(struct gbuf *gbuf, struct greybus_host_device *hd, @@ -145,7 +173,7 @@ static int send_gbuf(struct gbuf *gbuf, struct greybus_host_device *hd, buffer = &transfer_buffer[-1]; /* yes, we mean -1 */ /* Find a free urb */ - urb = next_free_urb(es1); + urb = next_free_urb(es1, gfp_mask); if (!urb) return -ENOMEM; @@ -289,6 +317,7 @@ static int ap_probe(struct usb_interface *interface, es1->hd = hd; es1->usb_intf = interface; es1->usb_dev = udev; + spin_lock_init(&es1->cport_out_urb_lock); usb_set_intfdata(interface, es1); /* Control endpoint is the pipe to talk to this AP, so save it off */ -- cgit v0.10.2 From 9c8d3afdb58cf96a0e784e2e0a62923fe8855e4d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 13 Sep 2014 11:09:35 -0700 Subject: greybus: es1: handle cport data in and out diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 53ad66c..e606a45 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -298,6 +298,12 @@ int gb_new_ap_msg(u8 *data, int size, struct greybus_host_device *hd) } EXPORT_SYMBOL_GPL(gb_new_ap_msg); +void greybus_cport_in_data(struct greybus_host_device *hd, int cport, u8 *data, + size_t length) +{ + // FIXME - implement... +} +EXPORT_SYMBOL_GPL(greybus_cport_in_data); int gb_thread_init(void) { diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index cf2987e..6635194 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -233,7 +233,11 @@ exit: static void cport_in_callback(struct urb *urb) { struct device *dev = &urb->dev->dev; + struct es1_ap_dev *es1 = urb->context; int status = urb->status; + int retval; + u8 cport; + u8 *data; switch (status) { case 0: @@ -252,15 +256,40 @@ static void cport_in_callback(struct urb *urb) goto exit; } - // FIXME - handle the CPort in data + /* The size has to be more then just an "empty" transfer */ + if (urb->actual_length <= 2) { + dev_err(dev, "%s: \"short\" cport in transfer of %d bytes?\n", + __func__, urb->actual_length); + goto exit; + } + + /* + * The CPort number is the first byte of the data stream, the rest of + * the stream is "real" data + */ + data = urb->transfer_buffer; + cport = data[0]; + data = &data[1]; + + /* Pass this data to the greybus core */ + greybus_cport_in_data(es1->hd, cport, data, urb->actual_length - 1); + exit: - return; + /* put our urb back in the request pool */ + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) + dev_err(dev, "%s: error %d in submitting urb.\n", + __func__, retval); } static void cport_out_callback(struct urb *urb) { struct device *dev = &urb->dev->dev; + struct gbuf *gbuf = urb->context; + struct es1_ap_dev *es1 = gbuf->hdpriv; + unsigned long flags; int status = urb->status; + int i; switch (status) { case 0: @@ -273,15 +302,34 @@ static void cport_out_callback(struct urb *urb) case -ESHUTDOWN: case -EILSEQ: /* device is gone, stop sending */ - return; + goto exit; default: dev_err(dev, "%s: unknown status %d\n", __func__, status); goto exit; } - // FIXME - handle the CPort out data callback + // FIXME - do we care about errors going back up? + + /* Tell the core the gbuf is properly sent */ + greybus_gbuf_finished(gbuf); + exit: - return; + /* + * See if this was an urb in our pool, if so mark it "free", otherwise we + * need to free it ourselves. + */ + spin_lock_irqsave(&es1->cport_out_urb_lock, flags); + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + if (urb == es1->cport_out_urb[i]) { + es1->cport_out_urb_busy[i] = false; + urb = NULL; + break; + } + } + spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); + if (urb) + usb_free_urb(urb); + } /* diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 1bf9226..e12a625 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -98,10 +98,19 @@ EXPORT_SYMBOL_GPL(greybus_get_gbuf); int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t mem_flags) { + // FIXME - implement return -ENOMEM; } int greybus_kill_gbuf(struct gbuf *gbuf) { + // FIXME - implement return -ENOMEM; } + +/* Can be called in interrupt context, do the work and get out of here */ +void greybus_gbuf_finished(struct gbuf *gbuf) +{ + // FIXME - implement +} +EXPORT_SYMBOL_GPL(greybus_gbuf_finished); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 573274b..1badfa8 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -126,6 +126,9 @@ struct greybus_host_device { struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *host_driver, struct device *parent); void greybus_remove_hd(struct greybus_host_device *hd); +void greybus_cport_in_data(struct greybus_host_device *hd, int cport, u8 *data, + size_t length); +void greybus_gbuf_finished(struct gbuf *gbuf); /* Increase these values if needed */ -- cgit v0.10.2 From 88929c593d38c0855baddc5192acb08f244b59e2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 13 Sep 2014 11:35:02 -0700 Subject: greybus: ap: convert to workqueue from thread diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index e606a45..e9aa701 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -24,13 +24,10 @@ struct ap_msg { u8 *data; size_t size; struct greybus_host_device *hd; - struct list_head list; + struct work_struct event; }; -static LIST_HEAD(ap_msg_list); -static spinlock_t ap_msg_list_lock; -static struct task_struct *ap_thread; -static wait_queue_head_t ap_wait; +static struct workqueue_struct *ap_workqueue; static struct svc_msg *svc_msg_alloc(enum svc_function_type type) { @@ -220,49 +217,22 @@ static void process_ap_message(struct ap_msg *ap_msg) } -static struct ap_msg *get_ap_msg(void) +static void ap_process_event(struct work_struct *work) { struct ap_msg *ap_msg; - unsigned long flags; - spin_lock_irqsave(&ap_msg_list_lock, flags); + ap_msg = container_of(work, struct ap_msg, event); - ap_msg = list_first_entry_or_null(&ap_msg_list, struct ap_msg, list); - if (ap_msg != NULL) - list_del(&ap_msg->list); - spin_unlock_irqrestore(&ap_msg_list_lock, flags); + process_ap_message(ap_msg); - return ap_msg; -} - -static int ap_process_loop(void *data) -{ - struct ap_msg *ap_msg; - - while (!kthread_should_stop()) { - wait_event_interruptible(ap_wait, kthread_should_stop()); - - if (kthread_should_stop()) - break; - - /* Get some data off of the ap list and process it */ - ap_msg = get_ap_msg(); - if (!ap_msg) - continue; - - process_ap_message(ap_msg); - - /* clean the message up */ - kfree(ap_msg->data); - kfree(ap_msg); - } - return 0; + /* clean the message up */ + kfree(ap_msg->data); + kfree(ap_msg); } int gb_new_ap_msg(u8 *data, int size, struct greybus_host_device *hd) { struct ap_msg *ap_msg; - unsigned long flags; /* * Totally naive copy the message into a new structure that we slowly @@ -287,12 +257,8 @@ int gb_new_ap_msg(u8 *data, int size, struct greybus_host_device *hd) ap_msg->size = size; ap_msg->hd = hd; - spin_lock_irqsave(&ap_msg_list_lock, flags); - list_add(&ap_msg->list, &ap_msg_list); - spin_unlock_irqrestore(&ap_msg_list_lock, flags); - - /* kick our thread to handle the message */ - wake_up_interruptible(&ap_wait); + INIT_WORK(&ap_msg->event, ap_process_event); + queue_work(ap_workqueue, &ap_msg->event); return 0; } @@ -307,19 +273,16 @@ EXPORT_SYMBOL_GPL(greybus_cport_in_data); int gb_thread_init(void) { - init_waitqueue_head(&ap_wait); - spin_lock_init(&ap_msg_list_lock); - - ap_thread = kthread_run(ap_process_loop, NULL, "greybus_ap"); - if (IS_ERR(ap_thread)) - return PTR_ERR(ap_thread); + ap_workqueue = alloc_workqueue("greybus_ap", 0, 1); + if (!ap_workqueue) + return -ENOMEM; return 0; } void gb_thread_destroy(void) { - kthread_stop(ap_thread); + destroy_workqueue(ap_workqueue); } -- cgit v0.10.2 From b57b06241b0177a36a1c951b25fdead3bc1d87ba Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 13 Sep 2014 12:18:09 -0700 Subject: greybus: ap: cleanup of process ap message loop diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index e9aa701..f920666 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -169,10 +169,14 @@ static struct svc_msg *convert_ap_message(struct ap_msg *ap_msg) return svc_msg; } -static void process_ap_message(struct ap_msg *ap_msg) +static void ap_process_event(struct work_struct *work) { struct svc_msg *svc_msg; struct greybus_host_device *hd; + struct ap_msg *ap_msg; + + ap_msg = container_of(work, struct ap_msg, event); + hd = ap_msg->hd; /* Turn the "raw" data into a real message */ svc_msg = convert_ap_message(ap_msg); @@ -181,11 +185,6 @@ static void process_ap_message(struct ap_msg *ap_msg) return; } - hd = ap_msg->hd; - - /* Pass the message to the host controller */ -// ap_msg->hd->driver->ap_msg(svc_msg, ap_msg->hd); - /* Look at the message to figure out what to do with it */ switch (svc_msg->header.type) { case SVC_FUNCTION_HANDSHAKE: @@ -214,17 +213,6 @@ static void process_ap_message(struct ap_msg *ap_msg) svc_msg->header.type); } - -} - -static void ap_process_event(struct work_struct *work) -{ - struct ap_msg *ap_msg; - - ap_msg = container_of(work, struct ap_msg, event); - - process_ap_message(ap_msg); - /* clean the message up */ kfree(ap_msg->data); kfree(ap_msg); -- cgit v0.10.2 From ac7171ea266d6978bc9eeb4db5e60847237cd1a5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 13 Sep 2014 12:39:23 -0700 Subject: greybus: Makefile: add 'check' option to run sparse with endian checks enabled diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 114089a..0550e21 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -21,6 +21,9 @@ all: module module: $(MAKE) -C $(KERNELDIR) M=$(PWD) +check: + $(MAKE) -C $(KERNELDIR) M=$(PWD) C=2 CF="-D__CHECK_ENDIAN__" + clean: rm -f *.o *~ core .depend .*.cmd *.ko *.mod.c rm -f Module.markers Module.symvers modules.order -- cgit v0.10.2 From 082570b0eebdd108c6b50b6c1299cf6d02a6ad82 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 13 Sep 2014 16:15:07 -0700 Subject: greybus: es1 endpoint descriptor: minor fixes to get the config right diff --git a/drivers/staging/greybus/es1_ap_desc.c b/drivers/staging/greybus/es1_ap_desc.c index 8c558a4..1502089 100644 --- a/drivers/staging/greybus/es1_ap_desc.c +++ b/drivers/staging/greybus/es1_ap_desc.c @@ -40,7 +40,7 @@ static const u8 es1_config_descriptor[] = { 0x04, /* __u8 if_bDescriptorType; Interface */ 0x00, /* __u8 if_bInterfaceNumber; */ 0x00, /* __u8 if_bAlternateSetting; */ - 0x02, /* __u8 if_bNumEndpoints; */ + 0x03, /* __u8 if_bNumEndpoints; */ 0xff, /* __u8 if_bInterfaceClass; Vendor-specific */ 0xff, /* __u8 if_bInterfaceSubClass; Vendor-specific */ 0xff, /* __u8 if_bInterfaceProtocol; Vendor-specific */ @@ -50,21 +50,21 @@ static const u8 es1_config_descriptor[] = { 0x07, /* __u8 ep_bLength; */ 0x05, /* __u8 ep_bDescriptorType; Endpoint */ 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ - 0x03, /* __u8 ep_bmAttributes; Bulk */ + 0x03, /* __u8 ep_bmAttributes; Interrupt */ 0x00, 0x04, /* __le16 ep_wMaxPacketSize; 1024 */ - 0x00 /* __u8 ep_bInterval; */ + 0x40, /* __u8 ep_bInterval; 64ms */ 0x07, /* __u8 ep_bLength; */ 0x05, /* __u8 ep_bDescriptorType; Endpoint */ 0x82, /* __u8 ep_bEndpointAddress; IN Endpoint 2 */ 0x02, /* __u8 ep_bmAttributes; Bulk */ 0x00, 0x04, /* __le16 ep_wMaxPacketSize; 1024 */ - 0x00 /* __u8 ep_bInterval; */ + 0x40 /* __u8 ep_bInterval; */ 0x07, /* __u8 ep_bLength; */ 0x05, /* __u8 ep_bDescriptorType; Endpoint */ 0x02, /* __u8 ep_bEndpointAddress; Out Endpoint 2 */ 0x02, /* __u8 ep_bmAttributes; Bulk */ 0x00, 0x04, /* __le16 ep_wMaxPacketSize; 1024 */ - 0x00 /* __u8 ep_bInterval; */ + 0x40 /* __u8 ep_bInterval; */ }; -- cgit v0.10.2 From 168db1cd2977f29c1181482aec69c22c20da7d72 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 13 Sep 2014 16:15:52 -0700 Subject: greybus: tty driver fixes to get init working properly diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 647bc5b..1d9efd4 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -508,22 +508,30 @@ static int __init gb_init(void) int retval; retval = gb_debugfs_init(); - if (retval) + if (retval) { + pr_err("debugfs failed\n"); return retval; + } retval = bus_register(&greybus_bus_type); - if (retval) + if (retval) { + pr_err("bus_register failed\n"); goto error_bus; + } retval = gb_thread_init(); - if (retval) + if (retval) { + pr_err("gb_thread_init failed\n"); goto error_thread; + } // FIXME - more gb core init goes here retval = gb_tty_init(); - if (retval) + if (retval) { + pr_err("gb_tty_init failed\n"); goto error_tty; + } return 0; diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 852dd0c5..5c01b0a 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -8,6 +8,7 @@ * Heavily based on drivers/usb/class/cdc-acm.c and * drivers/usb/serial/usb-serial.c. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include #include @@ -27,7 +28,7 @@ #include #include "greybus.h" -#define GB_TTY_MAJOR 180 /* FIXME use a real number!!! */ +#define GB_TTY_MAJOR 230 /* FIXME use a real number!!! */ #define GB_NUM_MINORS 255 /* 255 is enough for anyone... */ #define GB_NAME "ttyGB" @@ -473,20 +474,27 @@ int __init gb_tty_init(void) int retval = 0; dev_t dev; +#if 0 + retval = alloc_chrdev_region(&dev, 0, GB_NUM_MINORS, GB_NAME); - if (retval) + if (retval) { + pr_err("Can not allocate minors\n"); return retval; + } +#endif + gb_tty_driver = tty_alloc_driver(GB_NUM_MINORS, 0); if (IS_ERR(gb_tty_driver)) { + pr_err("Can not allocate tty driver\n"); retval = -ENOMEM; goto fail_unregister_dev; } gb_tty_driver->driver_name = "gb"; gb_tty_driver->name = GB_NAME; - gb_tty_driver->major = MAJOR(dev); - gb_tty_driver->minor_start = MINOR(dev); + gb_tty_driver->major = 0; + gb_tty_driver->minor_start = 0; gb_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; gb_tty_driver->subtype = SERIAL_TYPE_NORMAL; gb_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; @@ -495,12 +503,18 @@ int __init gb_tty_init(void) tty_set_operations(gb_tty_driver, &gb_ops); retval = tty_register_driver(gb_tty_driver); - if (retval) + if (retval) { + pr_err("Can not register tty driver: %d\n", retval); goto fail_put_gb_tty; + } +#if 0 retval = greybus_register(&tty_gb_driver); - if (retval) + if (retval) { + pr_err("Can not register greybus driver.\n"); goto fail_unregister_gb_tty; + } +#endif return 0; @@ -509,7 +523,7 @@ int __init gb_tty_init(void) fail_put_gb_tty: put_tty_driver(gb_tty_driver); fail_unregister_dev: - unregister_chrdev_region(dev, GB_NUM_MINORS); +// unregister_chrdev_region(dev, GB_NUM_MINORS); return retval; } @@ -517,7 +531,7 @@ void __exit gb_tty_exit(void) { int major = MAJOR(gb_tty_driver->major); int minor = gb_tty_driver->minor_start; - greybus_deregister(&tty_gb_driver); +// greybus_deregister(&tty_gb_driver); tty_unregister_driver(gb_tty_driver); put_tty_driver(gb_tty_driver); unregister_chrdev_region(MKDEV(major, minor), GB_NUM_MINORS); -- cgit v0.10.2 From 543b8ed2fee047ae8f598a0c8b763aff59139044 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 13 Sep 2014 17:02:47 -0700 Subject: greybus: uart-gb: let the core dynamically allocate the major number Don't register the tty_gb_driver, the gb core is not ready for the for ES1 devices. diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 5c01b0a..39a6e01 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -28,7 +28,6 @@ #include #include "greybus.h" -#define GB_TTY_MAJOR 230 /* FIXME use a real number!!! */ #define GB_NUM_MINORS 255 /* 255 is enough for anyone... */ #define GB_NAME "ttyGB" @@ -462,27 +461,17 @@ void gb_tty_disconnect(struct greybus_device *gdev) kfree(gb_tty); } +#if 0 static struct greybus_driver tty_gb_driver = { .probe = gb_tty_probe, .disconnect = gb_tty_disconnect, .id_table = id_table, }; - +#endif int __init gb_tty_init(void) { int retval = 0; - dev_t dev; - -#if 0 - - retval = alloc_chrdev_region(&dev, 0, GB_NUM_MINORS, GB_NAME); - if (retval) { - pr_err("Can not allocate minors\n"); - return retval; - } -#endif - gb_tty_driver = tty_alloc_driver(GB_NUM_MINORS, 0); if (IS_ERR(gb_tty_driver)) { @@ -518,12 +507,11 @@ int __init gb_tty_init(void) return 0; - fail_unregister_gb_tty: +/* fail_unregister_gb_tty: */ tty_unregister_driver(gb_tty_driver); - fail_put_gb_tty: +fail_put_gb_tty: put_tty_driver(gb_tty_driver); - fail_unregister_dev: -// unregister_chrdev_region(dev, GB_NUM_MINORS); +fail_unregister_dev: return retval; } @@ -531,7 +519,10 @@ void __exit gb_tty_exit(void) { int major = MAJOR(gb_tty_driver->major); int minor = gb_tty_driver->minor_start; -// greybus_deregister(&tty_gb_driver); + +#if 0 + greybus_deregister(&tty_gb_driver); +#endif tty_unregister_driver(gb_tty_driver); put_tty_driver(gb_tty_driver); unregister_chrdev_region(MKDEV(major, minor), GB_NUM_MINORS); -- cgit v0.10.2 From a1dc62b0c8efe79f27d048d03daac4764cb7c46c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 13 Sep 2014 17:28:19 -0700 Subject: greybus: core: verify major/minor number of greybus protocol diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 1d9efd4..bad40ba 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -385,7 +385,15 @@ struct greybus_device *greybus_new_module(struct device *parent, version_major = manifest->header.version_major; version_minor = manifest->header.version_minor; - // FIXME - check version major/minor here! + /* Validate major/minor number */ + if ((version_major != GREYBUS_VERSION_MAJOR) || + (version_minor != GREYBUS_VERSION_MINOR)) { + dev_err(parent, + "Invalid greybus versions, expected %d.%d, got %d.%d\n", + GREYBUS_VERSION_MAJOR, GREYBUS_VERSION_MINOR, + version_major, version_minor); + goto error; + } size -= sizeof(manifest->header); data += sizeof(manifest->header); -- cgit v0.10.2 From 7f9e05e15b4e0a252a26122ac3762a9caa80a65d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 13 Sep 2014 17:28:33 -0700 Subject: greybus: es1: functionally complete Have only tested USB device add/remove, the urbs seem to all be queued up, no data has been tested to flow through yet. Odds are the hc interface will have to change, but this is a good first start to build on. diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 6635194..e6cfd6c 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -14,7 +14,8 @@ #include "svc_msg.h" static const struct usb_device_id id_table[] = { - { USB_DEVICE(0xffff, 0x0001) }, // FIXME + /* Made up numbers for the SVC USB Bridge in ES1 */ + { USB_DEVICE(0xffff, 0x0001) }, { }, }; MODULE_DEVICE_TABLE(usb, id_table); @@ -31,23 +32,42 @@ MODULE_DEVICE_TABLE(usb, id_table); */ #define NUM_CPORT_OUT_URB 8 - +/** + * es1_ap_dev - ES1 USB Bridge to AP structure + * @usb_dev: pointer to the USB device we are. + * @usb_intf: pointer to the USB interface we are bound to. + * @hd: pointer to our greybus_host_device structure + * @control_endpoint: endpoint to send data to SVC + * @svc_endpoint: endpoint for SVC data in + * @cport_in_endpoint: bulk in endpoint for CPort data + * @cport-out_endpoint: bulk out endpoint for CPort data + * @svc_buffer: buffer for SVC messages coming in on @svc_endpoint + * @svc_urb: urb for SVC messages coming in on @svc_endpoint + * @cport_in_urb: array of urbs for the CPort in messages + * @cport_in_buffer: array of buffers for the @cport_in_urb urbs + * @cport_out_urb: array of urbs for the CPort out messages + * @cport_out_urb_busy: array of flags to see if the @cport_out_urb is busy or + * not. + * @cport_out_urb_lock: locks the @cport_out_urb_busy "list" + */ struct es1_ap_dev { struct usb_device *usb_dev; struct usb_interface *usb_intf; struct greybus_host_device *hd; - __u8 control_endpoint; /* endpoint to send data to SVC */ - __u8 svc_endpoint; /* endpoint for SVC data */ - __u8 cport_in_endpoint; /* bulk in for CPort data */ - __u8 cport_out_endpoint; /* bulk out for CPort data */ - u8 *svc_buffer; /* buffer for SVC messages coming in */ - struct urb *svc_urb; /* urb for SVC messages coming in */ - struct urb *cport_in_urb[NUM_CPORT_IN_URB]; /* CPort IN urbs */ - u8 *cport_in_buffer[NUM_CPORT_IN_URB]; /* CPort IN buffers */ - struct urb *cport_out_urb[NUM_CPORT_OUT_URB]; /* CPort OUT urbs */ - bool cport_out_urb_busy[NUM_CPORT_OUT_URB]; /* CPort OUT urb busy marker */ - spinlock_t cport_out_urb_lock; /* locks list of cport out urbs */ + __u8 control_endpoint; + __u8 svc_endpoint; + __u8 cport_in_endpoint; + __u8 cport_out_endpoint; + + u8 *svc_buffer; + struct urb *svc_urb; + + struct urb *cport_in_urb[NUM_CPORT_IN_URB]; + u8 *cport_in_buffer[NUM_CPORT_IN_URB]; + struct urb *cport_out_urb[NUM_CPORT_OUT_URB]; + bool cport_out_urb_busy[NUM_CPORT_OUT_URB]; + spinlock_t cport_out_urb_lock; }; static inline struct es1_ap_dev *hd_to_es1(struct greybus_host_device *hd) @@ -291,6 +311,7 @@ static void cport_out_callback(struct urb *urb) int status = urb->status; int i; + /* do we care about errors going back up? */ switch (status) { case 0: break; @@ -308,15 +329,13 @@ static void cport_out_callback(struct urb *urb) goto exit; } - // FIXME - do we care about errors going back up? - /* Tell the core the gbuf is properly sent */ greybus_gbuf_finished(gbuf); exit: /* - * See if this was an urb in our pool, if so mark it "free", otherwise we - * need to free it ourselves. + * See if this was an urb in our pool, if so mark it "free", otherwise + * we need to free it ourselves. */ spin_lock_irqsave(&es1->cport_out_urb_lock, flags); for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { @@ -327,9 +346,9 @@ exit: } } spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); - if (urb) - usb_free_urb(urb); + /* If urb is not NULL, then we need to free this urb */ + usb_free_urb(urb); } /* -- cgit v0.10.2 From ee6fb799021290e226e0559eb8048b86747cb045 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 13 Sep 2014 17:31:27 -0700 Subject: greybus: devices: endpoint description of device diff --git a/drivers/staging/greybus/devices b/drivers/staging/greybus/devices new file mode 100644 index 0000000..486bba8 --- /dev/null +++ b/drivers/staging/greybus/devices @@ -0,0 +1,11 @@ +T: Bus=01 Lev=03 Prnt=07 Port=02 Cnt=03 Dev#= 12 Spd=12 MxCh= 0 +D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 +P: Vendor=ffff ProdID=0001 Rev= 1.00 +S: Manufacturer=Greybus +S: Product=SVC Bridge +S: SerialNumber=12239 +C:* #Ifs= 1 Cfg#= 1 Atr=c0 MxPwr=100mA +I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=es1_ap_driver +E: Ad=81(I) Atr=03(Int.) MxPS= 64 Ivl=64ms +E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms +E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms -- cgit v0.10.2 From 80e04f09942e3641a5745e22b270e91f65c9107c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 13 Sep 2014 18:20:54 -0700 Subject: greybus: gbuf recieve path work, not done, dinner time... diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index f920666..0fc3ff7 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -252,13 +252,6 @@ int gb_new_ap_msg(u8 *data, int size, struct greybus_host_device *hd) } EXPORT_SYMBOL_GPL(gb_new_ap_msg); -void greybus_cport_in_data(struct greybus_host_device *hd, int cport, u8 *data, - size_t length) -{ - // FIXME - implement... -} -EXPORT_SYMBOL_GPL(greybus_cport_in_data); - int gb_thread_init(void) { ap_workqueue = alloc_workqueue("greybus_ap", 0, 1); diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index e12a625..b06d779 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -18,6 +18,31 @@ #include "greybus.h" +static struct gbuf *__alloc_gbuf(struct greybus_device *gdev, + struct gdev_cport *cport, + gbuf_complete_t complete, + gfp_t gfp_mask, + void *context) +{ + struct gbuf *gbuf; + + /* + * change this to a slab allocation if it's too slow, but for now, let's + * be dumb and simple. + */ + gbuf = kzalloc(sizeof(*gbuf), gfp_mask); + if (!gbuf) + return NULL; + + kref_init(&gbuf->kref); + gbuf->gdev = gdev; + gbuf->cport = cport; + gbuf->complete = complete; + gbuf->context = context; + + return gbuf; +} + /** * greybus_alloc_gbuf - allocate a greybus buffer * @@ -43,20 +68,10 @@ struct gbuf *greybus_alloc_gbuf(struct greybus_device *gdev, struct gbuf *gbuf; int retval; - /* - * change this to a slab allocation if it's too slow, but for now, let's - * be dumb and simple. - */ - gbuf = kzalloc(sizeof(*gbuf), gfp_mask); + gbuf = __alloc_gbuf(gdev, cport, complete, gfp_mask, context); if (!gbuf) return NULL; - kref_init(&gbuf->kref); - gbuf->gdev = gdev; - gbuf->cport = cport; - gbuf->complete = complete; - gbuf->context = context; - /* Host controller specific allocation for the actual buffer */ retval = gbuf->gdev->hd->driver->alloc_gbuf(gbuf, size, gfp_mask); if (retval) { @@ -114,3 +129,71 @@ void greybus_gbuf_finished(struct gbuf *gbuf) // FIXME - implement } EXPORT_SYMBOL_GPL(greybus_gbuf_finished); + +#define MAX_CPORTS 1024 +struct gb_cport_handler { + gbuf_complete_t handler; + struct gdev_cport cport; + struct greybus_device *gdev; + void *context; +}; + +static struct gb_cport_handler cport_handler[MAX_CPORTS]; +// FIXME - use a lock for this list of handlers, but really, for now we don't +// need it, we don't have a dynamic system... + +int gb_register_cport_complete(struct greybus_device *gdev, + gbuf_complete_t handler, int cport, + void *context) +{ + if (cport_handler[cport].handler) + return -EINVAL; + cport_handler[cport].context = context; + cport_handler[cport].gdev = gdev; + cport_handler[cport].cport.number = cport; + cport_handler[cport].handler = handler; + return 0; +} + +void gb_deregister_cport_handler(int cport) +{ + cport_handler[cport].handler = NULL; +} + +void greybus_cport_in_data(struct greybus_host_device *hd, int cport, u8 *data, + size_t length) +{ + struct gb_cport_handler *ch; + struct gbuf *gbuf; + + /* first check to see if we have a cport handler for this cport */ + ch = &cport_handler[cport]; + if (!ch->handler) { + /* Ugh, drop the data on the floor, after logging it... */ + dev_err(&hd->dev, + "Received data for cport %d, but no handler!\n", + cport); + return; + } + + gbuf = __alloc_gbuf(ch->gdev, &ch->cport, ch->handler, GFP_ATOMIC, + ch->context); + if (!gbuf) { + /* Again, something bad went wrong, log it... */ + pr_err("can't allocate gbuf???\n"); + return; + } + /* Set the data pointers */ + + // FIXME - implement... +} +EXPORT_SYMBOL_GPL(greybus_cport_in_data); + +int greybus_gbuf_init(void) +{ + return 0; +} + +void greybus_gbuf_exit(void) +{ +} diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 1badfa8..55cb48f 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -42,8 +42,8 @@ struct gbuf; struct gdev_cport { u16 number; u16 size; - // FIXME, what else? u8 speed; // valid??? + // FIXME, what else? }; struct gdev_string { @@ -234,6 +234,11 @@ void gb_thread_destroy(void); int gb_debugfs_init(void); void gb_debugfs_cleanup(void); +int gb_register_cport_complete(struct greybus_device *gdev, + gbuf_complete_t handler, int cport, + void *context); +void gb_deregister_cport_complete(int cport); + extern const struct attribute_group *greybus_module_groups[]; /* -- cgit v0.10.2 From 45f3678bcff37889b8fe81a7b1ea21b09a25803d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 14 Sep 2014 11:40:35 -0700 Subject: greybus: gbuf: cport in buffer stream logic diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 0fc3ff7..4c10650 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include "svc_msg.h" #include "greybus_manifest.h" @@ -252,7 +252,7 @@ int gb_new_ap_msg(u8 *data, int size, struct greybus_host_device *hd) } EXPORT_SYMBOL_GPL(gb_new_ap_msg); -int gb_thread_init(void) +int gb_ap_init(void) { ap_workqueue = alloc_workqueue("greybus_ap", 0, 1); if (!ap_workqueue) @@ -261,7 +261,7 @@ int gb_thread_init(void) return 0; } -void gb_thread_destroy(void) +void gb_ap_exit(void) { destroy_workqueue(ap_workqueue); } diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index bad40ba..f987086 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -527,13 +527,17 @@ static int __init gb_init(void) goto error_bus; } - retval = gb_thread_init(); + retval = gb_ap_init(); if (retval) { - pr_err("gb_thread_init failed\n"); - goto error_thread; + pr_err("gb_ap_init failed\n"); + goto error_ap; } - // FIXME - more gb core init goes here + retval = gb_gbuf_init(); + if (retval) { + pr_err("gb_gbuf_init failed\n"); + goto error_gbuf; + } retval = gb_tty_init(); if (retval) { @@ -544,9 +548,12 @@ static int __init gb_init(void) return 0; error_tty: - gb_thread_destroy(); + gb_gbuf_exit(); + +error_gbuf: + gb_ap_exit(); -error_thread: +error_ap: bus_unregister(&greybus_bus_type); error_bus: @@ -558,6 +565,8 @@ error_bus: static void __exit gb_exit(void) { gb_tty_exit(); + gb_gbuf_exit(); + gb_ap_exit(); bus_unregister(&greybus_bus_type); gb_debugfs_cleanup(); } diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index b06d779..3affdbf 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "greybus.h" @@ -155,16 +156,42 @@ int gb_register_cport_complete(struct greybus_device *gdev, return 0; } -void gb_deregister_cport_handler(int cport) +void gb_deregister_cport_complete(int cport) { cport_handler[cport].handler = NULL; } +struct cport_msg { + struct gbuf *gbuf; + struct work_struct event; +}; + +static struct workqueue_struct *cport_workqueue; + +static void cport_process_event(struct work_struct *work) +{ + struct cport_msg *cm; + struct gbuf *gbuf; + + cm = container_of(work, struct cport_msg, event); + + gbuf = cm->gbuf; + + /* call the gbuf handler */ + gbuf->complete(gbuf); + + /* free all the memory */ + kfree(gbuf->transfer_buffer); + kfree(gbuf); + kfree(cm); +} + void greybus_cport_in_data(struct greybus_host_device *hd, int cport, u8 *data, size_t length) { struct gb_cport_handler *ch; struct gbuf *gbuf; + struct cport_msg *cm; /* first check to see if we have a cport handler for this cport */ ch = &cport_handler[cport]; @@ -183,17 +210,42 @@ void greybus_cport_in_data(struct greybus_host_device *hd, int cport, u8 *data, pr_err("can't allocate gbuf???\n"); return; } - /* Set the data pointers */ + gbuf->hdpriv = hd; + + /* + * FIXME: + * Very dumb copy data method for now, if this is slow (odds are it will + * be, we should move to a model where the hd "owns" all buffers, but we + * want something up and working first for now. + */ + gbuf->transfer_buffer = kmalloc(length, GFP_ATOMIC); + if (!gbuf->transfer_buffer) { + kfree(gbuf); + return; + } + memcpy(gbuf->transfer_buffer, data, length); + gbuf->transfer_buffer_length = length; - // FIXME - implement... + /* Again with the slow allocate... */ + cm = kmalloc(sizeof(*cm), GFP_ATOMIC); + + /* Queue up the cport message to be handled in user context */ + cm->gbuf = gbuf; + INIT_WORK(&cm->event, cport_process_event); + queue_work(cport_workqueue, &cm->event); } EXPORT_SYMBOL_GPL(greybus_cport_in_data); -int greybus_gbuf_init(void) +int gb_gbuf_init(void) { + cport_workqueue = alloc_workqueue("greybus_gbuf", 0, 1); + if (!cport_workqueue) + return -ENOMEM; + return 0; } -void greybus_gbuf_exit(void) +void gb_gbuf_exit(void) { + destroy_workqueue(cport_workqueue); } diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 55cb48f..ecda30dd 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -229,10 +229,12 @@ const u8 *greybus_string(struct greybus_device *gdev, int id); /* Internal functions to gb module, move to internal .h file eventually. */ int gb_new_ap_msg(u8 *data, int length, struct greybus_host_device *hd); -int gb_thread_init(void); -void gb_thread_destroy(void); +int gb_ap_init(void); +void gb_ap_exit(void); int gb_debugfs_init(void); void gb_debugfs_cleanup(void); +int gb_gbuf_init(void); +void gb_gbuf_exit(void); int gb_register_cport_complete(struct greybus_device *gdev, gbuf_complete_t handler, int cport, -- cgit v0.10.2 From 13c8d9cd8a5381a68eb39bfebf2004835ffc0251 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 14 Sep 2014 12:27:19 -0700 Subject: greybus: add test_sink driver diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 0550e21..2e048a01 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -11,6 +11,7 @@ greybus-y := core.o \ obj-m += greybus.o obj-m += es1-ap-usb.o +obj-m += test_sink.o KERNELVER ?= $(shell uname -r) KERNELDIR ?= /lib/modules/$(KERNELVER)/build diff --git a/drivers/staging/greybus/test_sink.c b/drivers/staging/greybus/test_sink.c new file mode 100644 index 0000000..932c169 --- /dev/null +++ b/drivers/staging/greybus/test_sink.c @@ -0,0 +1,38 @@ +/* + * Test "sink" Greybus driver. + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include "greybus.h" + +struct test_device { + struct greybus_device *gdev; +}; + +int gb_register_cport_complete(struct greybus_device *gdev, + gbuf_complete_t handler, int cport, + void *context); +void gb_deregister_cport_complete(int cport); + + + +static int test_init(void) +{ + return 0; +} + +static void test_exit(void) +{ +} + +module_init(test_init); +module_exit(test_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Greg Kroah-Hartman "); -- cgit v0.10.2 From 772149b6df4648333c033d6b68e7a0b860dc22da Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 14 Sep 2014 12:27:28 -0700 Subject: greybus: fix hd init sequence of setting up parent and driver pointers properly diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 4c10650..4293073 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -68,7 +68,7 @@ static void svc_handshake(struct svc_function_handshake *handshake, /* A new SVC communication channel, let's verify it was for us */ if (handshake->handshake_type != SVC_HANDSHAKE_SVC_HELLO) { /* we don't know what to do with this, log it and return */ - dev_dbg(&hd->dev, "received invalid handshake type %d\n", + dev_dbg(hd->parent, "received invalid handshake type %d\n", handshake->handshake_type); return; } @@ -86,7 +86,7 @@ static void svc_management(struct svc_function_unipro_management *management, struct greybus_host_device *hd) { /* What? An AP should not get this message */ - dev_err(&hd->dev, "Got an svc management message???\n"); + dev_err(hd->parent, "Got an svc management message???\n"); } static void svc_hotplug(struct svc_function_hotplug *hotplug, @@ -96,17 +96,18 @@ static void svc_hotplug(struct svc_function_hotplug *hotplug, switch (hotplug->hotplug_event) { case SVC_HOTPLUG_EVENT: - dev_dbg(&hd->dev, "module id %d added\n", module_id); + dev_dbg(hd->parent, "module id %d added\n", module_id); // FIXME - add the module to the system break; case SVC_HOTUNPLUG_EVENT: - dev_dbg(&hd->dev, "module id %d removed\n", module_id); + dev_dbg(hd->parent, "module id %d removed\n", module_id); // FIXME - remove the module from the system break; default: - dev_err(&hd->dev, "received invalid hotplug message type %d\n", + dev_err(hd->parent, + "received invalid hotplug message type %d\n", hotplug->hotplug_event); break; } @@ -116,7 +117,7 @@ static void svc_ddb(struct svc_function_ddb *ddb, struct greybus_host_device *hd) { /* What? An AP should not get this message */ - dev_err(&hd->dev, "Got an svc DDB message???\n"); + dev_err(hd->parent, "Got an svc DDB message???\n"); } static void svc_power(struct svc_function_power *power, @@ -125,12 +126,12 @@ static void svc_power(struct svc_function_power *power, u8 module_id = power->module_id; if (power->power_type != SVC_POWER_BATTERY_STATUS) { - dev_err(&hd->dev, "received invalid power type %d\n", + dev_err(hd->parent, "received invalid power type %d\n", power->power_type); return; } - dev_dbg(&hd->dev, "power status for module id %d is %d\n", + dev_dbg(hd->parent, "power status for module id %d is %d\n", module_id, power->status.status); // FIXME - do something with the power information, like update our @@ -141,14 +142,14 @@ static void svc_epm(struct svc_function_epm *epm, struct greybus_host_device *hd) { /* What? An AP should not get this message */ - dev_err(&hd->dev, "Got an EPM message???\n"); + dev_err(hd->parent, "Got an EPM message???\n"); } static void svc_suspend(struct svc_function_suspend *suspend, struct greybus_host_device *hd) { /* What? An AP should not get this message */ - dev_err(&hd->dev, "Got an suspend message???\n"); + dev_err(hd->parent, "Got an suspend message???\n"); } static struct svc_msg *convert_ap_message(struct ap_msg *ap_msg) @@ -209,7 +210,7 @@ static void ap_process_event(struct work_struct *work) svc_suspend(&svc_msg->suspend, hd); break; default: - dev_err(&hd->dev, "received invalid SVC message type %d\n", + dev_err(hd->parent, "received invalid SVC message type %d\n", svc_msg->header.type); } diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index f987086..a13cf9f 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -499,6 +499,8 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver return NULL; kref_init(&hd->kref); + hd->parent = parent; + hd->driver = driver; return hd; } diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 3affdbf..2bdf485 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -197,7 +197,7 @@ void greybus_cport_in_data(struct greybus_host_device *hd, int cport, u8 *data, ch = &cport_handler[cport]; if (!ch->handler) { /* Ugh, drop the data on the floor, after logging it... */ - dev_err(&hd->dev, + dev_err(hd->parent, "Received data for cport %d, but no handler!\n", cport); return; diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index ecda30dd..2838e44 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -105,7 +105,6 @@ struct svc_msg; struct greybus_host_driver { size_t hd_priv_size; - int (*start)(struct greybus_host_device *hd); int (*alloc_gbuf)(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask); void (*free_gbuf)(struct gbuf *gbuf); int (*send_svc_msg)(struct svc_msg *svc_msg, struct greybus_host_device *hd); @@ -114,10 +113,9 @@ struct greybus_host_driver { }; struct greybus_host_device { - struct device dev; struct kref kref; + struct device *parent; const struct greybus_host_driver *driver; - unsigned long hd_priv_size; /* Private data for the host driver */ unsigned long hd_priv[0] __attribute__ ((aligned(sizeof(s64)))); -- cgit v0.10.2 From 710ecb0605350391e14a2d470397afb798b1fbf7 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Thu, 18 Sep 2014 15:25:41 -0400 Subject: greybus: update svc_msg_header fields and users to match spec The Greybus spec has been updated to clarify some of the original intent of the SVC message definition. The svc_msg_header was: struct svc_msg_header { __u8 function; __u8 message_type; ... } and is now struct svc_msg_header { __u8 function_id; __u8 message_type; ... } to match the spec. The function_id carries enum svc_function_id values and message_type is now clarified to be a session layer level field that is simply "data" or "error". Change all references of function type to function id. For now, don't parse the message_type field but add the two allowable svc_msg_type enums. Signed-off-by: Matt Porter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 4293073..c2c5aa6 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -29,7 +29,7 @@ struct ap_msg { static struct workqueue_struct *ap_workqueue; -static struct svc_msg *svc_msg_alloc(enum svc_function_type type) +static struct svc_msg *svc_msg_alloc(enum svc_function_id id) { struct svc_msg *svc_msg; @@ -37,8 +37,8 @@ static struct svc_msg *svc_msg_alloc(enum svc_function_type type) if (!svc_msg) return NULL; - // FIXME - verify we are only sending message types we should be - svc_msg->header.type = type; + // FIXME - verify we are only sending function IDs we should be + svc_msg->header.function_id = id; return svc_msg; } @@ -187,7 +187,7 @@ static void ap_process_event(struct work_struct *work) } /* Look at the message to figure out what to do with it */ - switch (svc_msg->header.type) { + switch (svc_msg->header.function_id) { case SVC_FUNCTION_HANDSHAKE: svc_handshake(&svc_msg->handshake, hd); break; @@ -210,8 +210,8 @@ static void ap_process_event(struct work_struct *work) svc_suspend(&svc_msg->suspend, hd); break; default: - dev_err(hd->parent, "received invalid SVC message type %d\n", - svc_msg->header.type); + dev_err(hd->parent, "received invalid SVC function ID %d\n", + svc_msg->header.function_id); } /* clean the message up */ diff --git a/drivers/staging/greybus/svc_msg.h b/drivers/staging/greybus/svc_msg.h index bbc7ef0..3f1a934 100644 --- a/drivers/staging/greybus/svc_msg.h +++ b/drivers/staging/greybus/svc_msg.h @@ -12,7 +12,7 @@ #pragma pack(push, 1) -enum svc_function_type { +enum svc_function_id { SVC_FUNCTION_HANDSHAKE = 0x00, SVC_FUNCTION_UNIPRO_NETWORK_MANAGEMENT = 0x01, SVC_FUNCTION_HOTPLUG = 0x02, @@ -22,9 +22,14 @@ enum svc_function_type { SVC_FUNCTION_SUSPEND = 0x06, }; +enum svc_msg_type { + SVC_MSG_DATA = 0x00, + SVC_MSG_ERROR = 0xff, +}; + struct svc_msg_header { - __u8 function; - __u8 type; /* enum svc_function_type */ + __u8 function_id; /* enum svc_function_id */ + __u8 message_type; __u8 version_major; __u8 version_minor; __le16 payload_length; -- cgit v0.10.2 From e94e17143ea61f08488e55a8b8dfa025ab5fee44 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Thu, 18 Sep 2014 15:25:42 -0400 Subject: greybus: move versioning from svc message header to handshake function The Greybus spec has been updated to improve the efficiency of the version major/minor information that had been previously carried in every SVC message header. The version major/minor is now provided as part of the handshake function. Update the SVC msg header and handshake function payload definitions and move the version major/minor validation into the SVC handshake handling routine. Signed-off-by: Matt Porter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index c2c5aa6..2a60de0 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -65,7 +65,15 @@ static void svc_handshake(struct svc_function_handshake *handshake, { struct svc_msg *svc_msg; - /* A new SVC communication channel, let's verify it was for us */ + /* A new SVC communication channel, let's verify a supported version */ + if ((handshake->version_major != GREYBUS_VERSION_MAJOR) && + (handshake->version_minor != GREYBUS_VERSION_MINOR)) { + dev_dbg(hd->parent, "received invalid greybus version %d:%d\n", + handshake->version_major, handshake->version_minor); + return; + } + + /* Validate that the handshake came from the SVC */ if (handshake->handshake_type != SVC_HANDSHAKE_SVC_HELLO) { /* we don't know what to do with this, log it and return */ dev_dbg(hd->parent, "received invalid handshake type %d\n", @@ -162,11 +170,6 @@ static struct svc_msg *convert_ap_message(struct ap_msg *ap_msg) svc_msg = (struct svc_msg *)ap_msg->data; - /* Verify the version is something we can handle with this code */ - if ((svc_msg->header.version_major != GREYBUS_VERSION_MAJOR) && - (svc_msg->header.version_minor != GREYBUS_VERSION_MINOR)) - return NULL; - return svc_msg; } diff --git a/drivers/staging/greybus/svc_msg.h b/drivers/staging/greybus/svc_msg.h index 3f1a934..e84e01c 100644 --- a/drivers/staging/greybus/svc_msg.h +++ b/drivers/staging/greybus/svc_msg.h @@ -30,8 +30,6 @@ enum svc_msg_type { struct svc_msg_header { __u8 function_id; /* enum svc_function_id */ __u8 message_type; - __u8 version_major; - __u8 version_minor; __le16 payload_length; }; @@ -42,6 +40,8 @@ enum svc_function_handshake_type { }; struct svc_function_handshake { + __u8 version_major; + __u8 version_minor; __u8 handshake_type; /* enum svc_function_handshake_type */ }; -- cgit v0.10.2 From 52adb56340b6f83d62d65e96b0f925ec8797b802 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Thu, 18 Sep 2014 15:25:43 -0400 Subject: greybus: update GREYBUS_VERSION_[MAJOR|MINOR] to match spec The Greybus spec was updated to have major=0 and minor=1 so update this in the code. Signed-off-by: Matt Porter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 2838e44..c9f516a 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -20,8 +20,8 @@ /* Matches up with the Greybus Protocol specification document */ -#define GREYBUS_VERSION_MAJOR 0x01 -#define GREYBUS_VERSION_MINOR 0x00 +#define GREYBUS_VERSION_MAJOR 0x00 +#define GREYBUS_VERSION_MINOR 0x01 #define GREYBUS_DEVICE_ID_MATCH_DEVICE \ (GREYBUS_DEVICE_ID_MATCH_VENDOR | GREYBUS_DEVICE_ID_MATCH_PRODUCT) -- cgit v0.10.2 From 29f000f434afbdf136714aabaaab8f8f27025a36 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 19 Sep 2014 18:37:44 -0700 Subject: greybus: es1: set buffer sizes for messages based on email discussions The gbuf sizes are 4k (i.e. PAGE_SIZE) and svc interrupt urb is 2k diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index e6cfd6c..c385a0b 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -13,6 +13,11 @@ #include "greybus.h" #include "svc_msg.h" +/* Memory sizes for the buffers sent to/from the ES1 controller */ +#define ES1_SVC_MSG_SIZE 2048 +#define ES1_GBUF_MSG_SIZE PAGE_SIZE + + static const struct usb_device_id id_table[] = { /* Made up numbers for the SVC USB Bridge in ES1 */ { USB_DEVICE(0xffff, 0x0001) }, @@ -90,6 +95,11 @@ static int alloc_gbuf(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask) struct es1_ap_dev *es1 = hd_to_es1(gbuf->gdev->hd); u8 *buffer; + if (size > ES1_GBUF_MSG_SIZE) { + pr_err("guf was asked to be bigger than %d!\n", + ES1_GBUF_MSG_SIZE); + } + /* For ES2 we need to figure out what cport is going to what endpoint, * but for ES1, it's so dirt simple, we don't have a choice... * @@ -371,7 +381,6 @@ static int ap_probe(struct usb_interface *interface, bool bulk_out_found = false; int retval = -ENOMEM; int i; - int buffer_size = 0; u8 svc_interval = 0; udev = usb_get_dev(interface_to_usbdev(interface)); @@ -398,7 +407,6 @@ static int ap_probe(struct usb_interface *interface, if (usb_endpoint_is_int_in(endpoint)) { es1->svc_endpoint = endpoint->bEndpointAddress; - buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); svc_interval = endpoint->bInterval; int_in_found = true; } else if (usb_endpoint_is_bulk_in(endpoint)) { @@ -421,7 +429,7 @@ static int ap_probe(struct usb_interface *interface, } /* Create our buffer and URB to get SVC messages, and start it up */ - es1->svc_buffer = kmalloc(buffer_size, GFP_KERNEL); + es1->svc_buffer = kmalloc(ES1_SVC_MSG_SIZE, GFP_KERNEL); if (!es1->svc_buffer) goto error; @@ -431,7 +439,7 @@ static int ap_probe(struct usb_interface *interface, usb_fill_int_urb(es1->svc_urb, udev, usb_rcvintpipe(udev, es1->svc_endpoint), - es1->svc_buffer, buffer_size, svc_callback, + es1->svc_buffer, ES1_SVC_MSG_SIZE, svc_callback, es1, svc_interval); retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); if (retval) @@ -445,7 +453,7 @@ static int ap_probe(struct usb_interface *interface, urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) goto error_bulk_in_urb; - buffer = kmalloc(PAGE_SIZE, GFP_KERNEL); + buffer = kmalloc(ES1_GBUF_MSG_SIZE, GFP_KERNEL); if (!buffer) goto error_bulk_in_urb; -- cgit v0.10.2 From f036e05600bd3901ee5d24d52cbfde93b71a5751 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 19 Sep 2014 19:13:33 -0700 Subject: greybus: gbuf: implement submission logic diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index c385a0b..961d6b1 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -96,7 +96,7 @@ static int alloc_gbuf(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask) u8 *buffer; if (size > ES1_GBUF_MSG_SIZE) { - pr_err("guf was asked to be bigger than %d!\n", + pr_err("guf was asked to be bigger than %ld!\n", ES1_GBUF_MSG_SIZE); } @@ -189,8 +189,8 @@ static struct urb *next_free_urb(struct es1_ap_dev *es1, gfp_t gfp_mask) return urb; } -static int send_gbuf(struct gbuf *gbuf, struct greybus_host_device *hd, - gfp_t gfp_mask) +static int submit_gbuf(struct gbuf *gbuf, struct greybus_host_device *hd, + gfp_t gfp_mask) { struct es1_ap_dev *es1 = hd_to_es1(hd); struct usb_device *udev = es1->usb_dev; @@ -216,11 +216,11 @@ static int send_gbuf(struct gbuf *gbuf, struct greybus_host_device *hd, } static struct greybus_host_driver es1_driver = { - .hd_priv_size = sizeof(struct es1_ap_dev), - .alloc_gbuf = alloc_gbuf, - .free_gbuf = free_gbuf, - .send_svc_msg = send_svc_msg, - .send_gbuf = send_gbuf, + .hd_priv_size = sizeof(struct es1_ap_dev), + .alloc_gbuf = alloc_gbuf, + .free_gbuf = free_gbuf, + .send_svc_msg = send_svc_msg, + .submit_gbuf = submit_gbuf, }; /* Callback for when we get a SVC message */ diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 2bdf485..6cc752c 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -112,10 +112,9 @@ struct gbuf *greybus_get_gbuf(struct gbuf *gbuf) } EXPORT_SYMBOL_GPL(greybus_get_gbuf); -int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t mem_flags) +int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) { - // FIXME - implement - return -ENOMEM; + return gbuf->gdev->hd->driver->submit_gbuf(gbuf, gbuf->gdev->hd, gfp_mask); } int greybus_kill_gbuf(struct gbuf *gbuf) @@ -124,13 +123,6 @@ int greybus_kill_gbuf(struct gbuf *gbuf) return -ENOMEM; } -/* Can be called in interrupt context, do the work and get out of here */ -void greybus_gbuf_finished(struct gbuf *gbuf) -{ - // FIXME - implement -} -EXPORT_SYMBOL_GPL(greybus_gbuf_finished); - #define MAX_CPORTS 1024 struct gb_cport_handler { gbuf_complete_t handler; @@ -236,6 +228,21 @@ void greybus_cport_in_data(struct greybus_host_device *hd, int cport, u8 *data, } EXPORT_SYMBOL_GPL(greybus_cport_in_data); +/* Can be called in interrupt context, do the work and get out of here */ +void greybus_gbuf_finished(struct gbuf *gbuf) +{ + struct cport_msg *cm; + + /* Again with the slow allocate... */ + cm = kmalloc(sizeof(*cm), GFP_ATOMIC); + cm->gbuf = gbuf; + INIT_WORK(&cm->event, cport_process_event); + queue_work(cport_workqueue, &cm->event); + + // FIXME - implement +} +EXPORT_SYMBOL_GPL(greybus_gbuf_finished); + int gb_gbuf_init(void) { cport_workqueue = alloc_workqueue("greybus_gbuf", 0, 1); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index c9f516a..17a01bd 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -107,9 +107,10 @@ struct greybus_host_driver { int (*alloc_gbuf)(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask); void (*free_gbuf)(struct gbuf *gbuf); - int (*send_svc_msg)(struct svc_msg *svc_msg, struct greybus_host_device *hd); - int (*send_gbuf)(struct gbuf *gbuf, struct greybus_host_device *hd, - gfp_t gfp_mask); + int (*send_svc_msg)(struct svc_msg *svc_msg, + struct greybus_host_device *hd); + int (*submit_gbuf)(struct gbuf *gbuf, struct greybus_host_device *hd, + gfp_t gfp_mask); }; struct greybus_host_device { -- cgit v0.10.2 From 3e7736e5c17801e15c0355d905988c03bbc0ba22 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 21 Sep 2014 17:34:28 -0700 Subject: greybus: gbuf: clean up logic of who owns what "part" of the gbuf Started documenting the gbuf and how a greybus driver and a host controller driver needs to interact with it, and the rest of the greybus system. It's crude documentation, but better than nothing for now... diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 961d6b1..1a47da6 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -90,7 +90,7 @@ static void cport_out_callback(struct urb *urb); * void *transfer_buffer; * u32 transfer_buffer_length; */ -static int alloc_gbuf(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask) +static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask) { struct es1_ap_dev *es1 = hd_to_es1(gbuf->gdev->hd); u8 *buffer; @@ -116,6 +116,7 @@ static int alloc_gbuf(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask) buffer[0] = gbuf->cport->number; gbuf->transfer_buffer = &buffer[1]; gbuf->transfer_buffer_length = size; + gbuf->actual_length = size; /* When we send the gbuf, we need this pointer to be here */ gbuf->hdpriv = es1; @@ -124,14 +125,17 @@ static int alloc_gbuf(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask) } /* Free the memory we allocated with a gbuf */ -static void free_gbuf(struct gbuf *gbuf) +static void free_gbuf_data(struct gbuf *gbuf) { u8 *transfer_buffer; u8 *buffer; transfer_buffer = gbuf->transfer_buffer; - buffer = &transfer_buffer[-1]; /* yes, we mean -1 */ - kfree(buffer); + /* Can be called with a NULL transfer_buffer on some error paths */ + if (transfer_buffer) { + buffer = &transfer_buffer[-1]; /* yes, we mean -1 */ + kfree(buffer); + } } #define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ @@ -216,11 +220,11 @@ static int submit_gbuf(struct gbuf *gbuf, struct greybus_host_device *hd, } static struct greybus_host_driver es1_driver = { - .hd_priv_size = sizeof(struct es1_ap_dev), - .alloc_gbuf = alloc_gbuf, - .free_gbuf = free_gbuf, - .send_svc_msg = send_svc_msg, - .submit_gbuf = submit_gbuf, + .hd_priv_size = sizeof(struct es1_ap_dev), + .alloc_gbuf_data = alloc_gbuf_data, + .free_gbuf_data = free_gbuf_data, + .send_svc_msg = send_svc_msg, + .submit_gbuf = submit_gbuf, }; /* Callback for when we get a SVC message */ diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 6cc752c..40174b8 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -19,6 +19,9 @@ #include "greybus.h" + +static struct kmem_cache *gbuf_head_cache; + static struct gbuf *__alloc_gbuf(struct greybus_device *gdev, struct gdev_cport *cport, gbuf_complete_t complete, @@ -27,11 +30,7 @@ static struct gbuf *__alloc_gbuf(struct greybus_device *gdev, { struct gbuf *gbuf; - /* - * change this to a slab allocation if it's too slow, but for now, let's - * be dumb and simple. - */ - gbuf = kzalloc(sizeof(*gbuf), gfp_mask); + gbuf = kmem_cache_zalloc(gbuf_head_cache, gfp_mask); if (!gbuf) return NULL; @@ -73,10 +72,12 @@ struct gbuf *greybus_alloc_gbuf(struct greybus_device *gdev, if (!gbuf) return NULL; + gbuf->direction = GBUF_DIRECTION_OUT; + /* Host controller specific allocation for the actual buffer */ - retval = gbuf->gdev->hd->driver->alloc_gbuf(gbuf, size, gfp_mask); + retval = gbuf->gdev->hd->driver->alloc_gbuf_data(gbuf, size, gfp_mask); if (retval) { - kfree(gbuf); + greybus_free_gbuf(gbuf); return NULL; } @@ -90,10 +91,15 @@ static void free_gbuf(struct kref *kref) { struct gbuf *gbuf = container_of(kref, struct gbuf, kref); - /* let the host controller free what it wants to */ - gbuf->gdev->hd->driver->free_gbuf(gbuf); + /* If the direction is "out" then the host controller frees the data */ + if (gbuf->direction == GBUF_DIRECTION_OUT) { + gbuf->gdev->hd->driver->free_gbuf_data(gbuf); + } else { + /* we "own" this in data, so free it ourselves */ + kfree(gbuf->transfer_buffer); + } - kfree(gbuf); + kmem_cache_free(gbuf_head_cache, gbuf); } void greybus_free_gbuf(struct gbuf *gbuf) @@ -123,6 +129,43 @@ int greybus_kill_gbuf(struct gbuf *gbuf) return -ENOMEM; } +struct cport_msg { + struct gbuf *gbuf; + struct work_struct event; +}; + +static struct workqueue_struct *cport_workqueue; + +static void cport_process_event(struct work_struct *work) +{ + struct cport_msg *cm; + struct gbuf *gbuf; + + cm = container_of(work, struct cport_msg, event); + + gbuf = cm->gbuf; + + /* call the gbuf handler */ + gbuf->complete(gbuf); + + /* free all the memory */ + greybus_free_gbuf(gbuf); + kfree(cm); +} + +static void cport_create_event(struct gbuf *gbuf) +{ + struct cport_msg *cm; + + /* Slow alloc, does it matter??? */ + cm = kmalloc(sizeof(*cm), GFP_ATOMIC); + + /* Queue up the cport message to be handled in user context */ + cm->gbuf = gbuf; + INIT_WORK(&cm->event, cport_process_event); + queue_work(cport_workqueue, &cm->event); +} + #define MAX_CPORTS 1024 struct gb_cport_handler { gbuf_complete_t handler; @@ -153,37 +196,11 @@ void gb_deregister_cport_complete(int cport) cport_handler[cport].handler = NULL; } -struct cport_msg { - struct gbuf *gbuf; - struct work_struct event; -}; - -static struct workqueue_struct *cport_workqueue; - -static void cport_process_event(struct work_struct *work) -{ - struct cport_msg *cm; - struct gbuf *gbuf; - - cm = container_of(work, struct cport_msg, event); - - gbuf = cm->gbuf; - - /* call the gbuf handler */ - gbuf->complete(gbuf); - - /* free all the memory */ - kfree(gbuf->transfer_buffer); - kfree(gbuf); - kfree(cm); -} - void greybus_cport_in_data(struct greybus_host_device *hd, int cport, u8 *data, size_t length) { struct gb_cport_handler *ch; struct gbuf *gbuf; - struct cport_msg *cm; /* first check to see if we have a cport handler for this cport */ ch = &cport_handler[cport]; @@ -203,6 +220,7 @@ void greybus_cport_in_data(struct greybus_host_device *hd, int cport, u8 *data, return; } gbuf->hdpriv = hd; + gbuf->direction = GBUF_DIRECTION_IN; /* * FIXME: @@ -217,29 +235,16 @@ void greybus_cport_in_data(struct greybus_host_device *hd, int cport, u8 *data, } memcpy(gbuf->transfer_buffer, data, length); gbuf->transfer_buffer_length = length; + gbuf->actual_length = length; - /* Again with the slow allocate... */ - cm = kmalloc(sizeof(*cm), GFP_ATOMIC); - - /* Queue up the cport message to be handled in user context */ - cm->gbuf = gbuf; - INIT_WORK(&cm->event, cport_process_event); - queue_work(cport_workqueue, &cm->event); + cport_create_event(gbuf); } EXPORT_SYMBOL_GPL(greybus_cport_in_data); /* Can be called in interrupt context, do the work and get out of here */ void greybus_gbuf_finished(struct gbuf *gbuf) { - struct cport_msg *cm; - - /* Again with the slow allocate... */ - cm = kmalloc(sizeof(*cm), GFP_ATOMIC); - cm->gbuf = gbuf; - INIT_WORK(&cm->event, cport_process_event); - queue_work(cport_workqueue, &cm->event); - - // FIXME - implement + cport_create_event(gbuf); } EXPORT_SYMBOL_GPL(greybus_gbuf_finished); @@ -249,10 +254,13 @@ int gb_gbuf_init(void) if (!cport_workqueue) return -ENOMEM; + gbuf_head_cache = kmem_cache_create("gbuf_head_cache", + sizeof(struct gbuf), 0, 0, NULL); return 0; } void gb_gbuf_exit(void) { destroy_workqueue(cport_workqueue); + kmem_cache_destroy(gbuf_head_cache); } diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 17a01bd..9802cce 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -36,6 +36,68 @@ .serial_number = (s), +/* + gbuf + + This is the "main" data structure to send / receive Greybus messages + + There are two different "views" of a gbuf structure: + - a greybus driver + - a greybus host controller + + A Greybus driver needs to worry about the following: + - creating a gbuf + - putting data into a gbuf + - sending a gbuf to a device + - receiving a gbuf from a device + + Creating a gbuf: + A greybus driver calls greybus_alloc_gbuf() + Putting data into a gbuf: + copy data into gbuf->transfer_buffer + Send a gbuf: + A greybus driver calls greybus_submit_gbuf() + The completion function in a gbuf will be called if the gbuf is successful + or not. That completion function runs in user context. After the + completion function is called, the gbuf must not be touched again as the + greybus core "owns" it. But, if a greybus driver wants to "hold on" to a + gbuf after the completion function has been called, a reference must be + grabbed on the gbuf with a call to greybus_get_gbuf(). When finished with + the gbuf, call greybus_free_gbuf() and when the last reference count is + dropped, it will be removed from the system. + Receive a gbuf: + A greybus driver calls gb_register_cport_complete() with a pointer to the + callback function to be called for when a gbuf is received from a specific + cport and device. That callback will be made in user context with a gbuf + when it is received. To stop receiving messages, call + gb_deregister_cport_complete() for a specific cport. + + + Greybus Host controller drivers need to provide + - a way to allocate the transfer buffer for a gbuf + - a way to free the transfer buffer for a gbuf when it is "finished" + - a way to submit gbuf for transmissions + - notify the core the gbuf is complete + - receive gbuf from the wire and submit them to the core + - a way to send and receive svc messages + Allocate a transfer buffer + the host controller function alloc_gbuf_data is called + Free a transfer buffer + the host controller function free_gbuf_data is called + Submit a gbuf to the hardware + the host controller function submit_gbuf is called + Notify the gbuf is complete + the host controller driver must call greybus_gbuf_finished() + Submit a SVC message to the hardware + the host controller function send_svc_msg is called + Receive gbuf messages + the host controller driver must call greybus_cport_in_data() with the data + Reveive SVC messages from the hardware + The host controller driver must call gb_new_ap_msg + + +*/ + struct gbuf; @@ -66,10 +128,9 @@ struct gbuf { u32 transfer_buffer_length; u32 actual_length; -#if 0 - struct scatterlist *sg; // FIXME do we need? - int num_sgs; -#endif +#define GBUF_DIRECTION_OUT 0 +#define GBUF_DIRECTION_IN 1 + unsigned int direction : 1; /* 0 is out, 1 is in */ void *context; gbuf_complete_t complete; @@ -105,8 +166,8 @@ struct svc_msg; struct greybus_host_driver { size_t hd_priv_size; - int (*alloc_gbuf)(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask); - void (*free_gbuf)(struct gbuf *gbuf); + int (*alloc_gbuf_data)(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask); + void (*free_gbuf_data)(struct gbuf *gbuf); int (*send_svc_msg)(struct svc_msg *svc_msg, struct greybus_host_device *hd); int (*submit_gbuf)(struct gbuf *gbuf, struct greybus_host_device *hd, -- cgit v0.10.2 From 798ea88abec88852e6dae2afb265560f9ec56432 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 21 Sep 2014 18:16:41 -0700 Subject: greybus: svc_msg.h: add data for hotplug message diff --git a/drivers/staging/greybus/svc_msg.h b/drivers/staging/greybus/svc_msg.h index e84e01c..c290547 100644 --- a/drivers/staging/greybus/svc_msg.h +++ b/drivers/staging/greybus/svc_msg.h @@ -77,6 +77,7 @@ enum svc_function_hotplug_event { struct svc_function_hotplug { __u8 hotplug_event; /* enum svc_function_hotplug_event */ __u8 module_id; + __u8 data[0]; }; enum svc_function_ddb_type { -- cgit v0.10.2 From 85e0066c597c5fd9bc278eac79065251aa507c65 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 21 Sep 2014 18:17:12 -0700 Subject: greybus: greybus.h: add function prototype for add/remove a module diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 9802cce..f804b19 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -288,6 +288,9 @@ const u8 *greybus_string(struct greybus_device *gdev, int id); /* Internal functions to gb module, move to internal .h file eventually. */ +void gb_add_module(struct greybus_host_device *hd, u8 module_id, u8 *data); +void gb_remove_module(struct greybus_host_device *hd, u8 module_id); + int gb_new_ap_msg(u8 *data, int length, struct greybus_host_device *hd); int gb_ap_init(void); void gb_ap_exit(void); -- cgit v0.10.2 From 6779997d78bf4c98857c397ed3d1dfede8949835 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 21 Sep 2014 18:17:36 -0700 Subject: greybus: core.c: create empty functions to keep linking working for hotplug/remove diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index a13cf9f..9a232a0 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -346,6 +346,11 @@ static int create_cport(struct greybus_device *gdev, * Pass in a buffer that _should_ contain a Greybus module manifest * and spit out a greybus device structure. */ +void gb_add_module(struct greybus_host_device *hd, u8 module_id, u8 *data) +{ + // FIXME - should be the new module call... +} + struct greybus_device *greybus_new_module(struct device *parent, int module_number, u8 *data, int size) { @@ -466,6 +471,11 @@ error: return NULL; } +void gb_remove_module(struct greybus_host_device *hd, u8 module_id) +{ + // FIXME should be the remove_device call... +} + void greybus_remove_device(struct greybus_device *gdev) { /* tear down all of the "sub device types" for this device */ -- cgit v0.10.2 From 00c52e4d3e37f3cd56c2159c7827f6d08e198262 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 21 Sep 2014 18:19:54 -0700 Subject: greybus: ap: start validating the message better We check the type of the message now. Start to check the size of the payload to match the size of the message type. Still more work to do needed here. Also "hooked up" the hotplug message, but doesn't call anything as the core doesn't implement that yet... diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 2a60de0..267d8b5 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -61,10 +61,17 @@ static int svc_msg_send(struct svc_msg *svc_msg, struct greybus_host_device *hd) static void svc_handshake(struct svc_function_handshake *handshake, - struct greybus_host_device *hd) + int payload_length, struct greybus_host_device *hd) { struct svc_msg *svc_msg; + if (payload_length != sizeof(struct svc_function_handshake)) { + dev_err(hd->parent, + "Illegal size of svc handshake message %d\n", + payload_length); + return; + } + /* A new SVC communication channel, let's verify a supported version */ if ((handshake->version_major != GREYBUS_VERSION_MAJOR) && (handshake->version_minor != GREYBUS_VERSION_MINOR)) { @@ -91,8 +98,15 @@ static void svc_handshake(struct svc_function_handshake *handshake, } static void svc_management(struct svc_function_unipro_management *management, - struct greybus_host_device *hd) + int payload_length, struct greybus_host_device *hd) { + if (payload_length != sizeof(struct svc_function_unipro_management)) { + dev_err(hd->parent, + "Illegal size of svc management message %d\n", + payload_length); + return; + } + /* What? An AP should not get this message */ dev_err(hd->parent, "Got an svc management message???\n"); } @@ -104,13 +118,15 @@ static void svc_hotplug(struct svc_function_hotplug *hotplug, switch (hotplug->hotplug_event) { case SVC_HOTPLUG_EVENT: + /* Add a new module to the system */ dev_dbg(hd->parent, "module id %d added\n", module_id); - // FIXME - add the module to the system + gb_add_module(hd, module_id, hotplug->data); break; case SVC_HOTUNPLUG_EVENT: + /* Remove a module from the system */ dev_dbg(hd->parent, "module id %d removed\n", module_id); - // FIXME - remove the module from the system + gb_remove_module(hd, module_id); break; default: @@ -160,15 +176,27 @@ static void svc_suspend(struct svc_function_suspend *suspend, dev_err(hd->parent, "Got an suspend message???\n"); } -static struct svc_msg *convert_ap_message(struct ap_msg *ap_msg) +static struct svc_msg *convert_ap_message(struct ap_msg *ap_msg, + struct greybus_host_device *hd) { struct svc_msg *svc_msg; - - // FIXME - validate message, right now we are trusting the size and data - // from the AP, what could go wrong? :) - // for now, just cast the pointer and run away... + struct svc_msg_header *header; svc_msg = (struct svc_msg *)ap_msg->data; + header = &svc_msg->header; + + /* Validate the message type */ + if (header->message_type != SVC_MSG_DATA) { + dev_err(hd->parent, "message type %d received?\n", + header->message_type); + return NULL; + } + + /* + * The validation of the size of the message buffer happens in each + * svc_* function, due to the different types of messages, keeping the + * logic for each message only in one place. + */ return svc_msg; } @@ -178,24 +206,25 @@ static void ap_process_event(struct work_struct *work) struct svc_msg *svc_msg; struct greybus_host_device *hd; struct ap_msg *ap_msg; + int payload_length; ap_msg = container_of(work, struct ap_msg, event); hd = ap_msg->hd; /* Turn the "raw" data into a real message */ - svc_msg = convert_ap_message(ap_msg); - if (!svc_msg) { - // FIXME log an error??? + svc_msg = convert_ap_message(ap_msg, hd); + if (!svc_msg) return; - } + + payload_length = le16_to_cpu(svc_msg->header.payload_length); /* Look at the message to figure out what to do with it */ switch (svc_msg->header.function_id) { case SVC_FUNCTION_HANDSHAKE: - svc_handshake(&svc_msg->handshake, hd); + svc_handshake(&svc_msg->handshake, payload_length, hd); break; case SVC_FUNCTION_UNIPRO_NETWORK_MANAGEMENT: - svc_management(&svc_msg->management, hd); + svc_management(&svc_msg->management, payload_length, hd); break; case SVC_FUNCTION_HOTPLUG: svc_hotplug(&svc_msg->hotplug, hd); -- cgit v0.10.2 From d0cfd109c7eb5df548dd98bfa7f2dba370c68e1c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 21 Sep 2014 19:10:39 -0700 Subject: greybus: ap: validate the rest of the svc message buffer sizes diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 267d8b5..21f2e33 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -112,49 +112,86 @@ static void svc_management(struct svc_function_unipro_management *management, } static void svc_hotplug(struct svc_function_hotplug *hotplug, - struct greybus_host_device *hd) + int payload_length, struct greybus_host_device *hd) { u8 module_id = hotplug->module_id; switch (hotplug->hotplug_event) { case SVC_HOTPLUG_EVENT: /* Add a new module to the system */ + if (payload_length < 0x03) { + /* Hotplug message is at lest 3 bytes big */ + dev_err(hd->parent, + "Illegal size of svc hotplug message %d\n", + payload_length); + return; + } dev_dbg(hd->parent, "module id %d added\n", module_id); - gb_add_module(hd, module_id, hotplug->data); + gb_add_module(hd, module_id, hotplug->data, + payload_length - 0x02); break; case SVC_HOTUNPLUG_EVENT: /* Remove a module from the system */ + if (payload_length != 0x02) { + /* Hotunplug message is only 2 bytes big */ + dev_err(hd->parent, + "Illegal size of svc hotunplug message %d\n", + payload_length); + return; + } dev_dbg(hd->parent, "module id %d removed\n", module_id); gb_remove_module(hd, module_id); break; default: dev_err(hd->parent, - "received invalid hotplug message type %d\n", + "Received invalid hotplug message type %d\n", hotplug->hotplug_event); break; } } static void svc_ddb(struct svc_function_ddb *ddb, - struct greybus_host_device *hd) + int payload_length, struct greybus_host_device *hd) { + /* + * Need to properly validate payload_length once we start + * to handle ddb messages, but for now, we don't, so no need to check + * anything. + */ + /* What? An AP should not get this message */ dev_err(hd->parent, "Got an svc DDB message???\n"); } static void svc_power(struct svc_function_power *power, - struct greybus_host_device *hd) + int payload_length, struct greybus_host_device *hd) { u8 module_id = power->module_id; + /* + * The AP is only allowed to get a Battery Status message, not a Battery + * Status Request + */ if (power->power_type != SVC_POWER_BATTERY_STATUS) { - dev_err(hd->parent, "received invalid power type %d\n", + dev_err(hd->parent, "Received invalid power type %d\n", power->power_type); return; } + /* + * As struct struct svc_function_power_battery_status_request is 0 bytes + * big, we can just check the union of the whole structure to validate + * the size of this message. + */ + if (payload_length != sizeof(struct svc_function_power)) { + dev_err(hd->parent, + "Illegal size of svc power message %d\n", + payload_length); + return; + } + dev_dbg(hd->parent, "power status for module id %d is %d\n", module_id, power->status.status); @@ -163,14 +200,14 @@ static void svc_power(struct svc_function_power *power, } static void svc_epm(struct svc_function_epm *epm, - struct greybus_host_device *hd) + int payload_length, struct greybus_host_device *hd) { /* What? An AP should not get this message */ dev_err(hd->parent, "Got an EPM message???\n"); } static void svc_suspend(struct svc_function_suspend *suspend, - struct greybus_host_device *hd) + int payload_length, struct greybus_host_device *hd) { /* What? An AP should not get this message */ dev_err(hd->parent, "Got an suspend message???\n"); @@ -227,19 +264,19 @@ static void ap_process_event(struct work_struct *work) svc_management(&svc_msg->management, payload_length, hd); break; case SVC_FUNCTION_HOTPLUG: - svc_hotplug(&svc_msg->hotplug, hd); + svc_hotplug(&svc_msg->hotplug, payload_length, hd); break; case SVC_FUNCTION_DDB: - svc_ddb(&svc_msg->ddb, hd); + svc_ddb(&svc_msg->ddb, payload_length, hd); break; case SVC_FUNCTION_POWER: - svc_power(&svc_msg->power, hd); + svc_power(&svc_msg->power, payload_length, hd); break; case SVC_FUNCTION_EPM: - svc_epm(&svc_msg->epm, hd); + svc_epm(&svc_msg->epm, payload_length, hd); break; case SVC_FUNCTION_SUSPEND: - svc_suspend(&svc_msg->suspend, hd); + svc_suspend(&svc_msg->suspend, payload_length, hd); break; default: dev_err(hd->parent, "received invalid SVC function ID %d\n", diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 9a232a0..b4e3093 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -346,7 +346,8 @@ static int create_cport(struct greybus_device *gdev, * Pass in a buffer that _should_ contain a Greybus module manifest * and spit out a greybus device structure. */ -void gb_add_module(struct greybus_host_device *hd, u8 module_id, u8 *data) +void gb_add_module(struct greybus_host_device *hd, u8 module_id, + u8 *data, int size) { // FIXME - should be the new module call... } diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index f804b19..855cb0e 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -288,7 +288,8 @@ const u8 *greybus_string(struct greybus_device *gdev, int id); /* Internal functions to gb module, move to internal .h file eventually. */ -void gb_add_module(struct greybus_host_device *hd, u8 module_id, u8 *data); +void gb_add_module(struct greybus_host_device *hd, u8 module_id, + u8 *data, int size); void gb_remove_module(struct greybus_host_device *hd, u8 module_id); int gb_new_ap_msg(u8 *data, int length, struct greybus_host_device *hd); -- cgit v0.10.2 From 4a833fdb7fc73039b06c1d879d896ebab0df7bd9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 21 Sep 2014 19:17:55 -0700 Subject: greybus: core: hook up the hotplug message We should now try to parse the manifest and create a device based on the manifest. Not hooked up to the driver core yet, so removing it isn't going to do anything except cause problems... diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index b4e3093..e4a78b4 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -341,20 +341,14 @@ static int create_cport(struct greybus_device *gdev, } /** - * greybus_new_module: + * gb_add_module * * Pass in a buffer that _should_ contain a Greybus module manifest - * and spit out a greybus device structure. + * and register a greybus device structure with the kernel core. */ void gb_add_module(struct greybus_host_device *hd, u8 module_id, u8 *data, int size) { - // FIXME - should be the new module call... -} - -struct greybus_device *greybus_new_module(struct device *parent, - int module_number, u8 *data, int size) -{ struct greybus_device *gdev; struct greybus_manifest *manifest; int retval; @@ -364,26 +358,26 @@ struct greybus_device *greybus_new_module(struct device *parent, /* we have to have at _least_ the manifest header */ if (size <= sizeof(manifest->header)) - return NULL; + return; gdev = kzalloc(sizeof(*gdev), GFP_KERNEL); if (!gdev) - return NULL; + return; - gdev->module_number = module_number; - gdev->dev.parent = parent; + gdev->module_number = module_id; + gdev->dev.parent = hd->parent; gdev->dev.driver = NULL; gdev->dev.bus = &greybus_bus_type; gdev->dev.type = &greybus_module_type; gdev->dev.groups = greybus_module_groups; - gdev->dev.dma_mask = parent->dma_mask; + gdev->dev.dma_mask = hd->parent->dma_mask; device_initialize(&gdev->dev); - dev_set_name(&gdev->dev, "%d", module_number); + dev_set_name(&gdev->dev, "%d", module_id); manifest = (struct greybus_manifest *)data; overall_size = le16_to_cpu(manifest->header.size); if (overall_size != size) { - dev_err(parent, "size != manifest header size, %d != %d\n", + dev_err(hd->parent, "size != manifest header size, %d != %d\n", size, overall_size); goto error; } @@ -394,7 +388,7 @@ struct greybus_device *greybus_new_module(struct device *parent, /* Validate major/minor number */ if ((version_major != GREYBUS_VERSION_MAJOR) || (version_minor != GREYBUS_VERSION_MINOR)) { - dev_err(parent, + dev_err(hd->parent, "Invalid greybus versions, expected %d.%d, got %d.%d\n", GREYBUS_VERSION_MAJOR, GREYBUS_VERSION_MINOR, version_major, version_minor); @@ -409,13 +403,14 @@ struct greybus_device *greybus_new_module(struct device *parent, size_t data_size; if (size < sizeof(desc->header)) { - dev_err(parent, "remaining size %d too small\n", size); + dev_err(hd->parent, "remaining size %d too small\n", + size); goto error; } desc = (struct greybus_descriptor *)data; desc_size = le16_to_cpu(desc->header.size); if (size < desc_size) { - dev_err(parent, "descriptor size %d too big\n", + dev_err(hd->parent, "descriptor size %d too big\n", desc_size); goto error; } @@ -448,7 +443,7 @@ struct greybus_device *greybus_new_module(struct device *parent, case GREYBUS_TYPE_INVALID: default: - dev_err(parent, "invalid descriptor type %d\n", + dev_err(hd->parent, "invalid descriptor type %d\n", desc->header.type); goto error; } @@ -464,12 +459,11 @@ struct greybus_device *greybus_new_module(struct device *parent, // FIXME device_add(&gdev->dev); - - return gdev; + //return gdev; + return; error: put_device(&gdev->dev); greybus_module_release(&gdev->dev); - return NULL; } void gb_remove_module(struct greybus_host_device *hd, u8 module_id) diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 855cb0e..1f996b9 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -279,9 +279,6 @@ void greybus_deregister(struct greybus_driver *driver); int greybus_disabled(void); -struct greybus_device *greybus_new_module(struct device *parent, - int module_number, u8 *data, - int size); void greybus_remove_device(struct greybus_device *gdev); const u8 *greybus_string(struct greybus_device *gdev, int id); -- cgit v0.10.2 From 648cb6cb75a1ef09200a24b280a2932caef88597 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 22 Sep 2014 15:51:48 -0400 Subject: greybus: es1-ap-usb: fix svc control pipe flags The control message flags currently indicate USB_DIR_IN, which doesn't allow the data phase carrying the SVC message to be send to the device. Change this to USB_DIR_OUT so our SVC message buffer reaches the device. Also, the recipient is USB_RECIP_OTHER but almost all real devices that handle vendor setup requests seem to set this as USB_RECIP_INTERFACE. As a result, functionfs-based gadgets don't handle vendor setup requests with a recipient of OTHER. Change this to USB_RECIP_INTERFACE to work with the functionfs-based emulator and this should be no issue for the firmware to implement to match. Signed-off-by: Matt Porter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 1a47da6..47c4524 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -149,7 +149,7 @@ static int send_svc_msg(struct svc_msg *svc_msg, struct greybus_host_device *hd) usb_sndctrlpipe(es1->usb_dev, es1->control_endpoint), 0x01, /* vendor request AP message */ - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0x00, 0x00, (char *)svc_msg, sizeof(*svc_msg), -- cgit v0.10.2 From be5064c75bb9e513698142584f4bb64de73e9f18 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 22 Sep 2014 15:51:49 -0400 Subject: greybus: initialize all fields in an SVC handshake message Currently only the handshake_type is being initialized when responding to an SVC handshake request. Update this to explicitly set all header/payload fields appropriately. Signed-off-by: Matt Porter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 21f2e33..78e9e4a 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -93,6 +93,12 @@ static void svc_handshake(struct svc_function_handshake *handshake, if (!svc_msg) return; + svc_msg->header.function_id = SVC_FUNCTION_HANDSHAKE; + svc_msg->header.message_type = SVC_MSG_DATA; + svc_msg->header.payload_length = + cpu_to_le16(sizeof(struct svc_function_handshake)); + svc_msg->handshake.version_major = GREYBUS_VERSION_MAJOR; + svc_msg->handshake.version_minor = GREYBUS_VERSION_MINOR; svc_msg->handshake.handshake_type = SVC_HANDSHAKE_AP_HELLO; svc_msg_send(svc_msg, hd); } -- cgit v0.10.2 From 69f93abf1181082c7a3dfa24b2ba4a2933ce2c1c Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 22 Sep 2014 18:53:02 -0500 Subject: greybus: simple fixes A few silly little fixes. - Clear out some unnecessary #includes in "debugfs.c" - Drop some unneeded parentheses in hd_to_es1() - Use &hd->hd_priv in hd_to_es1() to emphasize we are working with an embedded array, not a pointer - Fix a comment in the header for ap_probe() - Drop a duplicate #include in "gpio-gb.c" - Fix a use-before-set problem in set_serial_info() Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/debugfs.c b/drivers/staging/greybus/debugfs.c index 4e313f1..ef292f4 100644 --- a/drivers/staging/greybus/debugfs.c +++ b/drivers/staging/greybus/debugfs.c @@ -8,11 +8,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include -#include -#include -#include -#include #include #include "greybus.h" diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 47c4524..eadbfc8 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -77,7 +77,7 @@ struct es1_ap_dev { static inline struct es1_ap_dev *hd_to_es1(struct greybus_host_device *hd) { - return (struct es1_ap_dev *)(hd->hd_priv); + return (struct es1_ap_dev *)&hd->hd_priv; } static void cport_out_callback(struct urb *urb); @@ -370,7 +370,7 @@ exit: * 1 Control - usual USB stuff + AP -> SVC messages * 1 Interrupt IN - SVC -> AP messages * 1 Bulk IN - CPort data in - * 1 Bulk OUT - CPorta data out + * 1 Bulk OUT - CPort data out */ static int ap_probe(struct usb_interface *interface, const struct usb_device_id *id) diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index bcf65087..485480d 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -10,7 +10,6 @@ #include #include #include -#include #include "greybus.h" struct gb_gpio_device { diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 39a6e01..75ddd18 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -257,7 +257,7 @@ static int set_serial_info(struct gb_tty *gb_tty, struct serial_struct new_serial; unsigned int closing_wait; unsigned int close_delay; - int retval; + int retval = 0; if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) return -EFAULT; -- cgit v0.10.2 From 778c69c9e2fbb7462e5ebffe42845c9cdf75b1e2 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 22 Sep 2014 19:19:03 -0500 Subject: greybus: rename struct greybus_device The greybus_device structure represents an Ara phone module. It does *not* (necessarily) represent a UniPro device, nor any device (like an i2c adapter) that might reside on an Ara module. As such, rename struct greybus_device to be struct greybus_module. Rename all symbols having that type to be "gmod" rather than "gdev". Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index 7d12433..5f1bf00 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -18,7 +18,7 @@ struct gb_battery { // we will want to keep the battery stats in here as we will be getting // updates from the SVC "on the fly" so we don't have to always go ask // the battery for some information. Hopefully... - struct greybus_device *gdev; + struct greybus_module *gmod; }; #define to_gb_battery(x) container_of(x, struct gb_battery, bat) @@ -100,7 +100,7 @@ static enum power_supply_property battery_props[] = { POWER_SUPPLY_PROP_VOLTAGE_NOW, }; -int gb_battery_probe(struct greybus_device *gdev, +int gb_battery_probe(struct greybus_module *gmod, const struct greybus_module_id *id) { struct gb_battery *gb; @@ -120,21 +120,21 @@ int gb_battery_probe(struct greybus_device *gdev, b->num_properties = ARRAY_SIZE(battery_props), b->get_property = get_property, - retval = power_supply_register(&gdev->dev, b); + retval = power_supply_register(&gmod->dev, b); if (retval) { kfree(gb); return retval; } - gdev->gb_battery = gb; + gmod->gb_battery = gb; return 0; } -void gb_battery_disconnect(struct greybus_device *gdev) +void gb_battery_disconnect(struct greybus_module *gmod) { struct gb_battery *gb; - gb = gdev->gb_battery; + gb = gmod->gb_battery; power_supply_unregister(&gb->bat); diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index e4a78b4..296ff61 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -30,14 +30,14 @@ int greybus_disabled(void) } EXPORT_SYMBOL_GPL(greybus_disabled); -static int greybus_match_one_id(struct greybus_device *gdev, +static int greybus_match_one_id(struct greybus_module *gmod, const struct greybus_module_id *id) { struct greybus_descriptor_module_id *module_id; struct greybus_descriptor_serial_number *serial_num; - module_id = &gdev->module_id; - serial_num = &gdev->serial_number; + module_id = &gmod->module_id; + serial_num = &gmod->serial_number; if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_VENDOR) && (id->vendor != le16_to_cpu(module_id->vendor))) @@ -55,7 +55,7 @@ static int greybus_match_one_id(struct greybus_device *gdev, } static const struct greybus_module_id *greybus_match_id( - struct greybus_device *gdev, + struct greybus_module *gmod, const struct greybus_module_id *id) { if (id == NULL) @@ -63,20 +63,20 @@ static const struct greybus_module_id *greybus_match_id( for (; id->vendor || id->product || id->serial_number || id->driver_info ; id++) { - if (greybus_match_one_id(gdev, id)) + if (greybus_match_one_id(gmod, id)) return id; } return NULL; } -static int greybus_device_match(struct device *dev, struct device_driver *drv) +static int greybus_module_match(struct device *dev, struct device_driver *drv) { struct greybus_driver *driver = to_greybus_driver(dev->driver); - struct greybus_device *gdev = to_greybus_device(dev); + struct greybus_module *gmod = to_greybus_module(dev); const struct greybus_module_id *id; - id = greybus_match_id(gdev, driver->id_table); + id = greybus_match_id(gmod, driver->id_table); if (id) return 1; /* FIXME - Dyanmic ids? */ @@ -85,7 +85,7 @@ static int greybus_device_match(struct device *dev, struct device_driver *drv) static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) { - /* struct greybus_device *gdev = to_greybus_device(dev); */ + /* struct greybus_module *gmod = to_greybus_module(dev); */ /* FIXME - add some uevents here... */ return 0; @@ -93,23 +93,23 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) static struct bus_type greybus_bus_type = { .name = "greybus", - .match = greybus_device_match, + .match = greybus_module_match, .uevent = greybus_uevent, }; static int greybus_probe(struct device *dev) { struct greybus_driver *driver = to_greybus_driver(dev->driver); - struct greybus_device *gdev = to_greybus_device(dev); + struct greybus_module *gmod = to_greybus_module(dev); const struct greybus_module_id *id; int retval; /* match id */ - id = greybus_match_id(gdev, driver->id_table); + id = greybus_match_id(gmod, driver->id_table); if (!id) return -ENODEV; - retval = driver->probe(gdev, id); + retval = driver->probe(gmod, id); if (retval) return retval; @@ -119,9 +119,9 @@ static int greybus_probe(struct device *dev) static int greybus_remove(struct device *dev) { struct greybus_driver *driver = to_greybus_driver(dev->driver); - struct greybus_device *gdev = to_greybus_device(dev); + struct greybus_module *gmod = to_greybus_module(dev); - driver->disconnect(gdev); + driver->disconnect(gmod); return 0; } @@ -157,27 +157,27 @@ EXPORT_SYMBOL_GPL(greybus_deregister); static void greybus_module_release(struct device *dev) { - struct greybus_device *gdev = to_greybus_device(dev); + struct greybus_module *gmod = to_greybus_module(dev); int i; - for (i = 0; i < gdev->num_strings; ++i) - kfree(gdev->string[i]); - for (i = 0; i < gdev->num_cports; ++i) - kfree(gdev->cport[i]); - kfree(gdev); + for (i = 0; i < gmod->num_strings; ++i) + kfree(gmod->string[i]); + for (i = 0; i < gmod->num_cports; ++i) + kfree(gmod->cport[i]); + kfree(gmod); } -const u8 *greybus_string(struct greybus_device *gdev, int id) +const u8 *greybus_string(struct greybus_module *gmod, int id) { int i; - struct gdev_string *string; + struct gmod_string *string; - if (!gdev) + if (!gmod) return NULL; - for (i = 0; i < gdev->num_strings; ++i) { - string = gdev->string[i]; + for (i = 0; i < gmod->num_strings; ++i) { + string = gmod->string[i]; if (string->id == id) return &string->string[0]; } @@ -189,44 +189,44 @@ static struct device_type greybus_module_type = { .release = greybus_module_release, }; -static int gb_init_subdevs(struct greybus_device *gdev, +static int gb_init_subdevs(struct greybus_module *gmod, const struct greybus_module_id *id) { int retval; /* Allocate all of the different "sub device types" for this device */ - retval = gb_i2c_probe(gdev, id); + retval = gb_i2c_probe(gmod, id); if (retval) goto error_i2c; - retval = gb_gpio_probe(gdev, id); + retval = gb_gpio_probe(gmod, id); if (retval) goto error_gpio; - retval = gb_sdio_probe(gdev, id); + retval = gb_sdio_probe(gmod, id); if (retval) goto error_sdio; - retval = gb_tty_probe(gdev, id); + retval = gb_tty_probe(gmod, id); if (retval) goto error_tty; - retval = gb_battery_probe(gdev, id); + retval = gb_battery_probe(gmod, id); if (retval) goto error_battery; return 0; error_battery: - gb_tty_disconnect(gdev); + gb_tty_disconnect(gmod); error_tty: - gb_sdio_disconnect(gdev); + gb_sdio_disconnect(gmod); error_sdio: - gb_gpio_disconnect(gdev); + gb_gpio_disconnect(gmod); error_gpio: - gb_i2c_disconnect(gdev); + gb_i2c_disconnect(gmod); error_i2c: return retval; @@ -236,106 +236,106 @@ static const struct greybus_module_id fake_gb_id = { GREYBUS_DEVICE(0x42, 0x42) }; -static int create_function(struct greybus_device *gdev, +static int create_function(struct greybus_module *gmod, struct greybus_descriptor_function *function, size_t desc_size) { if (desc_size != sizeof(*function)) { - dev_err(gdev->dev.parent, "invalid function header size %zu\n", + dev_err(gmod->dev.parent, "invalid function header size %zu\n", desc_size); return -EINVAL; } - memcpy(&gdev->function, function, desc_size); + memcpy(&gmod->function, function, desc_size); return 0; } -static int create_module_id(struct greybus_device *gdev, +static int create_module_id(struct greybus_module *gmod, struct greybus_descriptor_module_id *module_id, size_t desc_size) { if (desc_size != sizeof(*module_id)) { - dev_err(gdev->dev.parent, "invalid module header size %zu\n", + dev_err(gmod->dev.parent, "invalid module header size %zu\n", desc_size); return -EINVAL; } - memcpy(&gdev->module_id, module_id, desc_size); + memcpy(&gmod->module_id, module_id, desc_size); return 0; } -static int create_serial_number(struct greybus_device *gdev, +static int create_serial_number(struct greybus_module *gmod, struct greybus_descriptor_serial_number *serial_num, size_t desc_size) { if (desc_size != sizeof(*serial_num)) { - dev_err(gdev->dev.parent, "invalid serial number header size %zu\n", + dev_err(gmod->dev.parent, "invalid serial number header size %zu\n", desc_size); return -EINVAL; } - memcpy(&gdev->serial_number, serial_num, desc_size); + memcpy(&gmod->serial_number, serial_num, desc_size); return 0; } -static int create_string(struct greybus_device *gdev, +static int create_string(struct greybus_module *gmod, struct greybus_descriptor_string *string, size_t desc_size) { int string_size; - struct gdev_string *gdev_string; + struct gmod_string *gmod_string; - if ((gdev->num_strings + 1) >= MAX_STRINGS_PER_MODULE) { - dev_err(gdev->dev.parent, + if ((gmod->num_strings + 1) >= MAX_STRINGS_PER_MODULE) { + dev_err(gmod->dev.parent, "too many strings for this module!\n"); return -EINVAL; } if (desc_size < sizeof(*string)) { - dev_err(gdev->dev.parent, "invalid string header size %zu\n", + dev_err(gmod->dev.parent, "invalid string header size %zu\n", desc_size); return -EINVAL; } string_size = le16_to_cpu(string->length); - gdev_string = kzalloc(sizeof(*gdev_string) + string_size + 1, GFP_KERNEL); - if (!gdev_string) + gmod_string = kzalloc(sizeof(*gmod_string) + string_size + 1, GFP_KERNEL); + if (!gmod_string) return -ENOMEM; - gdev_string->length = string_size; - gdev_string->id = string->id; - memcpy(&gdev_string->string, &string->string, string_size); + gmod_string->length = string_size; + gmod_string->id = string->id; + memcpy(&gmod_string->string, &string->string, string_size); - gdev->string[gdev->num_strings] = gdev_string; - gdev->num_strings++; + gmod->string[gmod->num_strings] = gmod_string; + gmod->num_strings++; return 0; } -static int create_cport(struct greybus_device *gdev, +static int create_cport(struct greybus_module *gmod, struct greybus_descriptor_cport *cport, size_t desc_size) { - struct gdev_cport *gdev_cport; + struct gmod_cport *gmod_cport; - if ((gdev->num_cports + 1) >= MAX_CPORTS_PER_MODULE) { - dev_err(gdev->dev.parent, "too many cports for this module!\n"); + if ((gmod->num_cports + 1) >= MAX_CPORTS_PER_MODULE) { + dev_err(gmod->dev.parent, "too many cports for this module!\n"); return -EINVAL; } if (desc_size != sizeof(*cport)) { - dev_err(gdev->dev.parent, + dev_err(gmod->dev.parent, "invalid serial number header size %zu\n", desc_size); return -EINVAL; } - gdev_cport = kzalloc(sizeof(*gdev_cport), GFP_KERNEL); - if (!gdev_cport) + gmod_cport = kzalloc(sizeof(*gmod_cport), GFP_KERNEL); + if (!gmod_cport) return -ENOMEM; - gdev_cport->number = le16_to_cpu(cport->number); - gdev_cport->size = le16_to_cpu(cport->size); - gdev_cport->speed = cport->speed; + gmod_cport->number = le16_to_cpu(cport->number); + gmod_cport->size = le16_to_cpu(cport->size); + gmod_cport->speed = cport->speed; - gdev->cport[gdev->num_cports] = gdev_cport; - gdev->num_cports++; + gmod->cport[gmod->num_cports] = gmod_cport; + gmod->num_cports++; return 0; } @@ -349,7 +349,7 @@ static int create_cport(struct greybus_device *gdev, void gb_add_module(struct greybus_host_device *hd, u8 module_id, u8 *data, int size) { - struct greybus_device *gdev; + struct greybus_module *gmod; struct greybus_manifest *manifest; int retval; int overall_size; @@ -360,19 +360,19 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, if (size <= sizeof(manifest->header)) return; - gdev = kzalloc(sizeof(*gdev), GFP_KERNEL); - if (!gdev) + gmod = kzalloc(sizeof(*gmod), GFP_KERNEL); + if (!gmod) return; - gdev->module_number = module_id; - gdev->dev.parent = hd->parent; - gdev->dev.driver = NULL; - gdev->dev.bus = &greybus_bus_type; - gdev->dev.type = &greybus_module_type; - gdev->dev.groups = greybus_module_groups; - gdev->dev.dma_mask = hd->parent->dma_mask; - device_initialize(&gdev->dev); - dev_set_name(&gdev->dev, "%d", module_id); + gmod->module_number = module_id; + gmod->dev.parent = hd->parent; + gmod->dev.driver = NULL; + gmod->dev.bus = &greybus_bus_type; + gmod->dev.type = &greybus_module_type; + gmod->dev.groups = greybus_module_groups; + gmod->dev.dma_mask = hd->parent->dma_mask; + device_initialize(&gmod->dev); + dev_set_name(&gmod->dev, "%d", module_id); manifest = (struct greybus_manifest *)data; overall_size = le16_to_cpu(manifest->header.size); @@ -418,27 +418,27 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, switch (le16_to_cpu(desc->header.type)) { case GREYBUS_TYPE_FUNCTION: - retval = create_function(gdev, &desc->function, + retval = create_function(gmod, &desc->function, data_size); break; case GREYBUS_TYPE_MODULE_ID: - retval = create_module_id(gdev, &desc->module_id, + retval = create_module_id(gmod, &desc->module_id, data_size); break; case GREYBUS_TYPE_SERIAL_NUMBER: - retval = create_serial_number(gdev, + retval = create_serial_number(gmod, &desc->serial_number, data_size); break; case GREYBUS_TYPE_STRING: - retval = create_string(gdev, &desc->string, data_size); + retval = create_string(gmod, &desc->string, data_size); break; case GREYBUS_TYPE_CPORT: - retval = create_cport(gdev, &desc->cport, data_size); + retval = create_cport(gmod, &desc->cport, data_size); break; case GREYBUS_TYPE_INVALID: @@ -453,17 +453,17 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, data += desc_size; } - retval = gb_init_subdevs(gdev, &fake_gb_id); + retval = gb_init_subdevs(gmod, &fake_gb_id); if (retval) goto error; - // FIXME device_add(&gdev->dev); + // FIXME device_add(&gmod->dev); - //return gdev; + //return gmod; return; error: - put_device(&gdev->dev); - greybus_module_release(&gdev->dev); + put_device(&gmod->dev); + greybus_module_release(&gmod->dev); } void gb_remove_module(struct greybus_host_device *hd, u8 module_id) @@ -471,16 +471,16 @@ void gb_remove_module(struct greybus_host_device *hd, u8 module_id) // FIXME should be the remove_device call... } -void greybus_remove_device(struct greybus_device *gdev) +void greybus_remove_device(struct greybus_module *gmod) { /* tear down all of the "sub device types" for this device */ - gb_i2c_disconnect(gdev); - gb_gpio_disconnect(gdev); - gb_sdio_disconnect(gdev); - gb_tty_disconnect(gdev); - gb_battery_disconnect(gdev); + gb_i2c_disconnect(gmod); + gb_gpio_disconnect(gmod); + gb_sdio_disconnect(gmod); + gb_tty_disconnect(gmod); + gb_battery_disconnect(gmod); - // FIXME - device_remove(&gdev->dev); + // FIXME - device_remove(&gmod->dev); } static DEFINE_MUTEX(hd_mutex); diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index eadbfc8..dfe96cb 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -92,7 +92,7 @@ static void cport_out_callback(struct urb *urb); */ static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask) { - struct es1_ap_dev *es1 = hd_to_es1(gbuf->gdev->hd); + struct es1_ap_dev *es1 = hd_to_es1(gbuf->gmod->hd); u8 *buffer; if (size > ES1_GBUF_MSG_SIZE) { diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 40174b8..5655721 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -22,8 +22,8 @@ static struct kmem_cache *gbuf_head_cache; -static struct gbuf *__alloc_gbuf(struct greybus_device *gdev, - struct gdev_cport *cport, +static struct gbuf *__alloc_gbuf(struct greybus_module *gmod, + struct gmod_cport *cport, gbuf_complete_t complete, gfp_t gfp_mask, void *context) @@ -35,7 +35,7 @@ static struct gbuf *__alloc_gbuf(struct greybus_device *gdev, return NULL; kref_init(&gbuf->kref); - gbuf->gdev = gdev; + gbuf->gmod = gmod; gbuf->cport = cport; gbuf->complete = complete; gbuf->context = context; @@ -46,7 +46,7 @@ static struct gbuf *__alloc_gbuf(struct greybus_device *gdev, /** * greybus_alloc_gbuf - allocate a greybus buffer * - * @gdev: greybus device that wants to allocate this + * @gmod: greybus device that wants to allocate this * @cport: cport to send the data to * @complete: callback when the gbuf is finished with * @size: size of the buffer @@ -58,8 +58,8 @@ static struct gbuf *__alloc_gbuf(struct greybus_device *gdev, * that the driver can then fill up with the data to be sent out. Curse * hardware designers for this issue... */ -struct gbuf *greybus_alloc_gbuf(struct greybus_device *gdev, - struct gdev_cport *cport, +struct gbuf *greybus_alloc_gbuf(struct greybus_module *gmod, + struct gmod_cport *cport, gbuf_complete_t complete, unsigned int size, gfp_t gfp_mask, @@ -68,14 +68,14 @@ struct gbuf *greybus_alloc_gbuf(struct greybus_device *gdev, struct gbuf *gbuf; int retval; - gbuf = __alloc_gbuf(gdev, cport, complete, gfp_mask, context); + gbuf = __alloc_gbuf(gmod, cport, complete, gfp_mask, context); if (!gbuf) return NULL; gbuf->direction = GBUF_DIRECTION_OUT; /* Host controller specific allocation for the actual buffer */ - retval = gbuf->gdev->hd->driver->alloc_gbuf_data(gbuf, size, gfp_mask); + retval = gbuf->gmod->hd->driver->alloc_gbuf_data(gbuf, size, gfp_mask); if (retval) { greybus_free_gbuf(gbuf); return NULL; @@ -93,7 +93,7 @@ static void free_gbuf(struct kref *kref) /* If the direction is "out" then the host controller frees the data */ if (gbuf->direction == GBUF_DIRECTION_OUT) { - gbuf->gdev->hd->driver->free_gbuf_data(gbuf); + gbuf->gmod->hd->driver->free_gbuf_data(gbuf); } else { /* we "own" this in data, so free it ourselves */ kfree(gbuf->transfer_buffer); @@ -120,7 +120,7 @@ EXPORT_SYMBOL_GPL(greybus_get_gbuf); int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) { - return gbuf->gdev->hd->driver->submit_gbuf(gbuf, gbuf->gdev->hd, gfp_mask); + return gbuf->gmod->hd->driver->submit_gbuf(gbuf, gbuf->gmod->hd, gfp_mask); } int greybus_kill_gbuf(struct gbuf *gbuf) @@ -169,8 +169,8 @@ static void cport_create_event(struct gbuf *gbuf) #define MAX_CPORTS 1024 struct gb_cport_handler { gbuf_complete_t handler; - struct gdev_cport cport; - struct greybus_device *gdev; + struct gmod_cport cport; + struct greybus_module *gmod; void *context; }; @@ -178,14 +178,14 @@ static struct gb_cport_handler cport_handler[MAX_CPORTS]; // FIXME - use a lock for this list of handlers, but really, for now we don't // need it, we don't have a dynamic system... -int gb_register_cport_complete(struct greybus_device *gdev, +int gb_register_cport_complete(struct greybus_module *gmod, gbuf_complete_t handler, int cport, void *context) { if (cport_handler[cport].handler) return -EINVAL; cport_handler[cport].context = context; - cport_handler[cport].gdev = gdev; + cport_handler[cport].gmod = gmod; cport_handler[cport].cport.number = cport; cport_handler[cport].handler = handler; return 0; @@ -212,7 +212,7 @@ void greybus_cport_in_data(struct greybus_host_device *hd, int cport, u8 *data, return; } - gbuf = __alloc_gbuf(ch->gdev, &ch->cport, ch->handler, GFP_ATOMIC, + gbuf = __alloc_gbuf(ch->gmod, &ch->cport, ch->handler, GFP_ATOMIC, ch->context); if (!gbuf) { /* Again, something bad went wrong, log it... */ diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index 485480d..4b71866 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -14,7 +14,7 @@ struct gb_gpio_device { struct gpio_chip chip; - struct greybus_device *gdev; + struct greybus_module *gmod; struct gpio_chip *gpio; // FIXME - some lock? }; @@ -49,18 +49,18 @@ static void gpio_set(struct gpio_chip *gpio, unsigned nr, int val) // FIXME - do something there } -int gb_gpio_probe(struct greybus_device *gdev, +int gb_gpio_probe(struct greybus_module *gmod, const struct greybus_module_id *id) { struct gb_gpio_device *gb_gpio; struct gpio_chip *gpio; - struct device *dev = &gdev->dev; + struct device *dev = &gmod->dev; int retval; gb_gpio = kzalloc(sizeof(*gb_gpio), GFP_KERNEL); if (!gb_gpio) return -ENOMEM; - gb_gpio->gdev = gdev; + gb_gpio->gmod = gmod; gpio = &gb_gpio->chip; @@ -75,7 +75,7 @@ int gb_gpio_probe(struct greybus_device *gdev, gpio->ngpio = 42; // FIXME!!! gpio->can_sleep = false; // FIXME!!! - gdev->gb_gpio_dev = gb_gpio; + gmod->gb_gpio_dev = gb_gpio; retval = gpiochip_add(gpio); if (retval) { @@ -86,12 +86,12 @@ int gb_gpio_probe(struct greybus_device *gdev, return 0; } -void gb_gpio_disconnect(struct greybus_device *gdev) +void gb_gpio_disconnect(struct greybus_module *gmod) { struct gb_gpio_device *gb_gpio_dev; int retval; - gb_gpio_dev = gdev->gb_gpio_dev; + gb_gpio_dev = gmod->gb_gpio_dev; retval = gpiochip_remove(&gb_gpio_dev->chip); kfree(gb_gpio_dev); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 1f996b9..59f9b98 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -101,14 +101,14 @@ struct gbuf; -struct gdev_cport { +struct gmod_cport { u16 number; u16 size; u8 speed; // valid??? // FIXME, what else? }; -struct gdev_string { +struct gmod_string { u16 length; u8 id; u8 string[0]; @@ -120,8 +120,8 @@ struct gbuf { struct kref kref; void *hdpriv; - struct greybus_device *gdev; - struct gdev_cport *cport; + struct greybus_module *gmod; + struct gmod_cport *cport; int status; void *transfer_buffer; u32 transfer_flags; /* flags for the transfer buffer */ @@ -148,7 +148,7 @@ struct gbuf { * same module as the gpio pins, etc.) * * So, put the "private" data structures here in greybus.h and link to them off - * of the "main" greybus_device structure. + * of the "main" greybus_module structure. */ struct gb_i2c_device; @@ -195,7 +195,7 @@ void greybus_gbuf_finished(struct gbuf *gbuf); #define MAX_CPORTS_PER_MODULE 10 #define MAX_STRINGS_PER_MODULE 10 -struct greybus_device { +struct greybus_module { struct device dev; u16 module_number; struct greybus_descriptor_function function; @@ -203,8 +203,8 @@ struct greybus_device { struct greybus_descriptor_serial_number serial_number; int num_cports; int num_strings; - struct gdev_cport *cport[MAX_CPORTS_PER_MODULE]; - struct gdev_string *string[MAX_STRINGS_PER_MODULE]; + struct gmod_cport *cport[MAX_CPORTS_PER_MODULE]; + struct gmod_string *string[MAX_STRINGS_PER_MODULE]; struct greybus_host_device *hd; @@ -215,10 +215,10 @@ struct greybus_device { struct gb_usb_device *gb_usb_dev; struct gb_battery *gb_battery; }; -#define to_greybus_device(d) container_of(d, struct greybus_device, dev) +#define to_greybus_module(d) container_of(d, struct greybus_module, dev) -struct gbuf *greybus_alloc_gbuf(struct greybus_device *gdev, - struct gdev_cport *cport, +struct gbuf *greybus_alloc_gbuf(struct greybus_module *gmod, + struct gmod_cport *cport, gbuf_complete_t complete, unsigned int size, gfp_t gfp_mask, @@ -234,12 +234,12 @@ int greybus_kill_gbuf(struct gbuf *gbuf); struct greybus_driver { const char *name; - int (*probe)(struct greybus_device *gdev, + int (*probe)(struct greybus_module *gmod, const struct greybus_module_id *id); - void (*disconnect)(struct greybus_device *gdev); + void (*disconnect)(struct greybus_module *gmod); - int (*suspend)(struct greybus_device *gdev, pm_message_t message); - int (*resume)(struct greybus_device *gdev); + int (*suspend)(struct greybus_module *gmod, pm_message_t message); + int (*resume)(struct greybus_module *gmod); const struct greybus_module_id *id_table; @@ -247,14 +247,14 @@ struct greybus_driver { }; #define to_greybus_driver(d) container_of(d, struct greybus_driver, driver) -static inline void greybus_set_drvdata(struct greybus_device *gdev, void *data) +static inline void greybus_set_drvdata(struct greybus_module *gmod, void *data) { - dev_set_drvdata(&gdev->dev, data); + dev_set_drvdata(&gmod->dev, data); } -static inline void *greybus_get_drvdata(struct greybus_device *gdev) +static inline void *greybus_get_drvdata(struct greybus_module *gmod) { - return dev_get_drvdata(&gdev->dev); + return dev_get_drvdata(&gmod->dev); } /* Don't call these directly, use the module_greybus_driver() macro instead */ @@ -279,9 +279,9 @@ void greybus_deregister(struct greybus_driver *driver); int greybus_disabled(void); -void greybus_remove_device(struct greybus_device *gdev); +void greybus_remove_device(struct greybus_module *gmod); -const u8 *greybus_string(struct greybus_device *gdev, int id); +const u8 *greybus_string(struct greybus_module *gmod, int id); /* Internal functions to gb module, move to internal .h file eventually. */ @@ -297,7 +297,7 @@ void gb_debugfs_cleanup(void); int gb_gbuf_init(void); void gb_gbuf_exit(void); -int gb_register_cport_complete(struct greybus_device *gdev, +int gb_register_cport_complete(struct greybus_module *gmod, gbuf_complete_t handler, int cport, void *context); void gb_deregister_cport_complete(int cport); @@ -309,16 +309,16 @@ extern const struct attribute_group *greybus_module_groups[]; * we have static functions for this, not "dynamic" drivers like we really * should in the end. */ -int gb_i2c_probe(struct greybus_device *gdev, const struct greybus_module_id *id); -void gb_i2c_disconnect(struct greybus_device *gdev); -int gb_gpio_probe(struct greybus_device *gdev, const struct greybus_module_id *id); -void gb_gpio_disconnect(struct greybus_device *gdev); -int gb_sdio_probe(struct greybus_device *gdev, const struct greybus_module_id *id); -void gb_sdio_disconnect(struct greybus_device *gdev); -int gb_tty_probe(struct greybus_device *gdev, const struct greybus_module_id *id); -void gb_tty_disconnect(struct greybus_device *gdev); -int gb_battery_probe(struct greybus_device *gdev, const struct greybus_module_id *id); -void gb_battery_disconnect(struct greybus_device *gdev); +int gb_i2c_probe(struct greybus_module *gmod, const struct greybus_module_id *id); +void gb_i2c_disconnect(struct greybus_module *gmod); +int gb_gpio_probe(struct greybus_module *gmod, const struct greybus_module_id *id); +void gb_gpio_disconnect(struct greybus_module *gmod); +int gb_sdio_probe(struct greybus_module *gmod, const struct greybus_module_id *id); +void gb_sdio_disconnect(struct greybus_module *gmod); +int gb_tty_probe(struct greybus_module *gmod, const struct greybus_module_id *id); +void gb_tty_disconnect(struct greybus_module *gmod); +int gb_battery_probe(struct greybus_module *gmod, const struct greybus_module_id *id); +void gb_battery_disconnect(struct greybus_module *gmod); int gb_tty_init(void); void gb_tty_exit(void); diff --git a/drivers/staging/greybus/greybus_id.h b/drivers/staging/greybus/greybus_id.h index 83c4d05..8b3bce6 100644 --- a/drivers/staging/greybus/greybus_id.h +++ b/drivers/staging/greybus/greybus_id.h @@ -19,7 +19,7 @@ struct greybus_module_id { __attribute__((aligned(sizeof(kernel_ulong_t)))); }; -/* Used to match the greybus_device_id */ +/* Used to match the greybus_module_id */ #define GREYBUS_DEVICE_ID_MATCH_VENDOR BIT(0) #define GREYBUS_DEVICE_ID_MATCH_PRODUCT BIT(1) #define GREYBUS_DEVICE_ID_MATCH_SERIAL BIT(2) diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index 3c1d947..bd03f19 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -14,7 +14,7 @@ struct gb_i2c_device { struct i2c_adapter *adapter; - struct greybus_device *gdev; + struct greybus_module *gmod; }; static const struct greybus_module_id id_table[] = { @@ -33,10 +33,10 @@ static s32 i2c_gb_access(struct i2c_adapter *adap, u16 addr, int size, union i2c_smbus_data *data) { struct gb_i2c_device *gb_i2c_dev; - struct greybus_device *gdev; + struct greybus_module *gmod; gb_i2c_dev = i2c_get_adapdata(adap); - gdev = gb_i2c_dev->gdev; + gmod = gb_i2c_dev->gmod; // FIXME - do the actual work of sending a i2c message here... switch (size) { @@ -50,7 +50,7 @@ static s32 i2c_gb_access(struct i2c_adapter *adap, u16 addr, case I2C_SMBUS_BLOCK_PROC_CALL: case I2C_SMBUS_I2C_BLOCK_DATA: default: - dev_err(&gdev->dev, "Unsupported transaction %d\n", size); + dev_err(&gmod->dev, "Unsupported transaction %d\n", size); return -EOPNOTSUPP; } @@ -75,7 +75,7 @@ static const struct i2c_algorithm smbus_algorithm = { .functionality = i2c_gb_func, }; -int gb_i2c_probe(struct greybus_device *gdev, +int gb_i2c_probe(struct greybus_module *gmod, const struct greybus_module_id *id) { struct gb_i2c_device *gb_i2c_dev; @@ -95,19 +95,19 @@ int gb_i2c_probe(struct greybus_device *gdev, adapter->owner = THIS_MODULE; adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; adapter->algo = &smbus_algorithm; - adapter->dev.parent = &gdev->dev; + adapter->dev.parent = &gmod->dev; adapter->retries = 3; /* we have to pick something... */ snprintf(adapter->name, sizeof(adapter->name), "Greybus i2c adapter"); retval = i2c_add_adapter(adapter); if (retval) { - dev_err(&gdev->dev, "Can not add SMBus adapter\n"); + dev_err(&gmod->dev, "Can not add SMBus adapter\n"); goto error; } - gb_i2c_dev->gdev = gdev; + gb_i2c_dev->gmod = gmod; gb_i2c_dev->adapter = adapter; - gdev->gb_i2c_dev = gb_i2c_dev; + gmod->gb_i2c_dev = gb_i2c_dev; return 0; error: kfree(adapter); @@ -115,11 +115,11 @@ error: return retval; } -void gb_i2c_disconnect(struct greybus_device *gdev) +void gb_i2c_disconnect(struct greybus_module *gmod) { struct gb_i2c_device *gb_i2c_dev; - gb_i2c_dev = gdev->gb_i2c_dev; + gb_i2c_dev = gmod->gb_i2c_dev; i2c_del_adapter(gb_i2c_dev->adapter); kfree(gb_i2c_dev->adapter); kfree(gb_i2c_dev); diff --git a/drivers/staging/greybus/sdio-gb.c b/drivers/staging/greybus/sdio-gb.c index 665767d..3cf258a 100644 --- a/drivers/staging/greybus/sdio-gb.c +++ b/drivers/staging/greybus/sdio-gb.c @@ -45,13 +45,13 @@ static const struct mmc_host_ops gb_sd_ops = { .get_ro = gb_sd_get_ro, }; -int gb_sdio_probe(struct greybus_device *gdev, +int gb_sdio_probe(struct greybus_module *gmod, const struct greybus_module_id *id) { struct mmc_host *mmc; struct gb_sdio_host *host; - mmc = mmc_alloc_host(sizeof(struct gb_sdio_host), &gdev->dev); + mmc = mmc_alloc_host(sizeof(struct gb_sdio_host), &gmod->dev); if (!mmc) return -ENOMEM; @@ -61,16 +61,16 @@ int gb_sdio_probe(struct greybus_device *gdev, mmc->ops = &gb_sd_ops; // FIXME - set up size limits we can handle. - gdev->gb_sdio_host = host; + gmod->gb_sdio_host = host; return 0; } -void gb_sdio_disconnect(struct greybus_device *gdev) +void gb_sdio_disconnect(struct greybus_module *gmod) { struct mmc_host *mmc; struct gb_sdio_host *host; - host = gdev->gb_sdio_host; + host = gmod->gb_sdio_host; mmc = host->mmc; mmc_remove_host(mmc); diff --git a/drivers/staging/greybus/sysfs.c b/drivers/staging/greybus/sysfs.c index 074fcfe..b503d2c 100644 --- a/drivers/staging/greybus/sysfs.c +++ b/drivers/staging/greybus/sysfs.c @@ -26,8 +26,8 @@ static ssize_t function_##field##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ - struct greybus_device *gdev = to_greybus_device(dev); \ - return sprintf(buf, "%d\n", gdev->function.field); \ + struct greybus_module *gmod = to_greybus_module(dev); \ + return sprintf(buf, "%d\n", gmod->function.field); \ } \ static DEVICE_ATTR_RO(function_##field) @@ -49,15 +49,15 @@ static struct attribute *function_attrs[] = { static umode_t function_attrs_are_visible(struct kobject *kobj, struct attribute *a, int n) { - struct greybus_device *gdev = to_greybus_device(kobj_to_dev(kobj)); + struct greybus_module *gmod = to_greybus_module(kobj_to_dev(kobj)); // FIXME - make this a dynamic structure to "know" if it really is here // or not easier? - if (gdev->function.number || - gdev->function.cport || - gdev->function.class || - gdev->function.subclass || - gdev->function.protocol) + if (gmod->function.number || + gmod->function.cport || + gmod->function.class || + gmod->function.subclass || + gmod->function.protocol) return a->mode; return 0; } @@ -73,8 +73,8 @@ static ssize_t module_##field##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ - struct greybus_device *gdev = to_greybus_device(dev); \ - return sprintf(buf, "%x\n", gdev->module_id.field); \ + struct greybus_module *gmod = to_greybus_module(dev); \ + return sprintf(buf, "%x\n", gmod->module_id.field); \ } \ static DEVICE_ATTR_RO(module_##field) @@ -86,10 +86,10 @@ static ssize_t module_vendor_string_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct greybus_device *gdev = to_greybus_device(dev); + struct greybus_module *gmod = to_greybus_module(dev); return sprintf(buf, "%s", - greybus_string(gdev, gdev->module_id.vendor_stringid)); + greybus_string(gmod, gmod->module_id.vendor_stringid)); } static DEVICE_ATTR_RO(module_vendor_string); @@ -97,10 +97,10 @@ static ssize_t module_product_string_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct greybus_device *gdev = to_greybus_device(dev); + struct greybus_module *gmod = to_greybus_module(dev); return sprintf(buf, "%s", - greybus_string(gdev, gdev->module_id.product_stringid)); + greybus_string(gmod, gmod->module_id.product_stringid)); } static DEVICE_ATTR_RO(module_product_string); @@ -116,20 +116,20 @@ static struct attribute *module_attrs[] = { static umode_t module_attrs_are_visible(struct kobject *kobj, struct attribute *a, int n) { - struct greybus_device *gdev = to_greybus_device(kobj_to_dev(kobj)); + struct greybus_module *gmod = to_greybus_module(kobj_to_dev(kobj)); if ((a == &dev_attr_module_vendor_string.attr) && - (gdev->module_id.vendor_stringid)) + (gmod->module_id.vendor_stringid)) return a->mode; if ((a == &dev_attr_module_product_string.attr) && - (gdev->module_id.product_stringid)) + (gmod->module_id.product_stringid)) return a->mode; // FIXME - make this a dynamic structure to "know" if it really is here // or not easier? - if (gdev->module_id.vendor || - gdev->module_id.product || - gdev->module_id.version) + if (gmod->module_id.vendor || + gmod->module_id.product || + gmod->module_id.version) return a->mode; return 0; } @@ -144,10 +144,10 @@ static struct attribute_group module_attr_grp = { static ssize_t serial_number_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct greybus_device *gdev = to_greybus_device(dev); + struct greybus_module *gmod = to_greybus_module(dev); return sprintf(buf, "%llX\n", - (unsigned long long)le64_to_cpu(gdev->serial_number.serial_number)); + (unsigned long long)le64_to_cpu(gmod->serial_number.serial_number)); } static DEVICE_ATTR_RO(serial_number); diff --git a/drivers/staging/greybus/test_sink.c b/drivers/staging/greybus/test_sink.c index 932c169..9dbf6ee 100644 --- a/drivers/staging/greybus/test_sink.c +++ b/drivers/staging/greybus/test_sink.c @@ -12,10 +12,10 @@ #include "greybus.h" struct test_device { - struct greybus_device *gdev; + struct greybus_module *gmod; }; -int gb_register_cport_complete(struct greybus_device *gdev, +int gb_register_cport_complete(struct greybus_module *gmod, gbuf_complete_t handler, int cport, void *context); void gb_deregister_cport_complete(int cport); diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 75ddd18..2021f27 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -33,7 +33,7 @@ struct gb_tty { struct tty_port port; - struct greybus_device *gdev; + struct greybus_module *gmod; int cport; unsigned int minor; unsigned char clocal; @@ -384,7 +384,7 @@ static const struct tty_operations gb_ops = { }; -int gb_tty_probe(struct greybus_device *gdev, +int gb_tty_probe(struct greybus_module *gmod, const struct greybus_module_id *id) { struct gb_tty *gb_tty; @@ -399,14 +399,14 @@ int gb_tty_probe(struct greybus_device *gdev, minor = alloc_minor(gb_tty); if (minor < 0) { if (minor == -ENOSPC) { - dev_err(&gdev->dev, "no more free minor numbers\n"); + dev_err(&gmod->dev, "no more free minor numbers\n"); return -ENODEV; } return minor; } gb_tty->minor = minor; - gb_tty->gdev = gdev; + gb_tty->gmod = gmod; spin_lock_init(&gb_tty->write_lock); spin_lock_init(&gb_tty->read_lock); init_waitqueue_head(&gb_tty->wioctl); @@ -414,10 +414,10 @@ int gb_tty_probe(struct greybus_device *gdev, /* FIXME - allocate gb buffers */ - gdev->gb_tty = gb_tty; + gmod->gb_tty = gb_tty; tty_dev = tty_port_register_device(&gb_tty->port, gb_tty_driver, minor, - &gdev->dev); + &gmod->dev); if (IS_ERR(tty_dev)) { retval = PTR_ERR(tty_dev); goto error; @@ -425,14 +425,14 @@ int gb_tty_probe(struct greybus_device *gdev, return 0; error: - gdev->gb_tty = NULL; + gmod->gb_tty = NULL; release_minor(gb_tty); return retval; } -void gb_tty_disconnect(struct greybus_device *gdev) +void gb_tty_disconnect(struct greybus_module *gmod) { - struct gb_tty *gb_tty = gdev->gb_tty; + struct gb_tty *gb_tty = gmod->gb_tty; struct tty_struct *tty; if (!gb_tty) @@ -442,7 +442,7 @@ void gb_tty_disconnect(struct greybus_device *gdev) gb_tty->disconnected = true; wake_up_all(&gb_tty->wioctl); - gdev->gb_tty = NULL; + gmod->gb_tty = NULL; mutex_unlock(&gb_tty->mutex); tty = tty_port_tty_get(&gb_tty->port); -- cgit v0.10.2 From 380f6bddc900b9baba8163e5c5f60eabe712f7d0 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 23 Sep 2014 12:46:32 -0500 Subject: greybus: quick fix for sysfs serial number Let the serial number attribute have its own is_visible function. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/sysfs.c b/drivers/staging/greybus/sysfs.c index b503d2c..792a238 100644 --- a/drivers/staging/greybus/sysfs.c +++ b/drivers/staging/greybus/sysfs.c @@ -156,9 +156,15 @@ static struct attribute *serial_number_attrs[] = { NULL, }; +static umode_t serial_number_is_visible(struct kobject *kobj, + struct attribute *a, int n) +{ + return a->mode; +} + static struct attribute_group serial_number_attr_grp = { .attrs = serial_number_attrs, - .is_visible = function_attrs_are_visible, + .is_visible = serial_number_is_visible, }; -- cgit v0.10.2 From 217b870e99ce68b868db08f4257c6f463abddd0c Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 23 Sep 2014 12:46:33 -0500 Subject: greybus: get rid of a weird idiom It strikes me as strange to add one to a value while checking to see if it exceeds a maximum. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 296ff61..33d7a33 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -282,7 +282,7 @@ static int create_string(struct greybus_module *gmod, int string_size; struct gmod_string *gmod_string; - if ((gmod->num_strings + 1) >= MAX_STRINGS_PER_MODULE) { + if (gmod->num_strings == MAX_STRINGS_PER_MODULE) { dev_err(gmod->dev.parent, "too many strings for this module!\n"); return -EINVAL; @@ -315,7 +315,7 @@ static int create_cport(struct greybus_module *gmod, { struct gmod_cport *gmod_cport; - if ((gmod->num_cports + 1) >= MAX_CPORTS_PER_MODULE) { + if (gmod->num_cports == MAX_CPORTS_PER_MODULE) { dev_err(gmod->dev.parent, "too many cports for this module!\n"); return -EINVAL; } -- cgit v0.10.2 From 2e353685bf0e523505695f8339316b0536474ea4 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 23 Sep 2014 12:46:36 -0500 Subject: greybus: embed workqueue structure in struct gbuf A Greybus buffer containing outbound data is submitted to to the underlying driver to be sent over a CPort. Sending that data could be deferred, so the submit operation completes asynchronously. When the send is done, a callback occurs, and the buffer is "completed", and the buffer's completion routine is called. The buffer is then freed. If data arrives on the CPort, greybus_cport_in_data() is called to allocate a Greybus buffer and copy the received data into it. Once that's done the buffer is completed, again allowing the buffer's completion routine to finish any final tasks before freeing the buffer. We use a workqueue to schedule calling the buffer's completion function. This patch does two things related to the work queue: - Renames the work queue "gbuf_workqueue" so its name more directly describes its purpose - Moves the work_struct needed for scheduling completions into the struct greybuf. Previously a separate type was used, and dynamically allocated *at interrupt time* to hold this work_struct. We can now do away with that. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 5655721..b51bd2a 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -19,9 +19,13 @@ #include "greybus.h" +static void cport_process_event(struct work_struct *work); static struct kmem_cache *gbuf_head_cache; +/* Workqueue to handle Greybus buffer completions. */ +static struct workqueue_struct *gbuf_workqueue; + static struct gbuf *__alloc_gbuf(struct greybus_module *gmod, struct gmod_cport *cport, gbuf_complete_t complete, @@ -37,6 +41,7 @@ static struct gbuf *__alloc_gbuf(struct greybus_module *gmod, kref_init(&gbuf->kref); gbuf->gmod = gmod; gbuf->cport = cport; + INIT_WORK(&gbuf->event, cport_process_event); gbuf->complete = complete; gbuf->context = context; @@ -129,41 +134,13 @@ int greybus_kill_gbuf(struct gbuf *gbuf) return -ENOMEM; } -struct cport_msg { - struct gbuf *gbuf; - struct work_struct event; -}; - -static struct workqueue_struct *cport_workqueue; - static void cport_process_event(struct work_struct *work) { - struct cport_msg *cm; - struct gbuf *gbuf; - - cm = container_of(work, struct cport_msg, event); - - gbuf = cm->gbuf; - - /* call the gbuf handler */ - gbuf->complete(gbuf); - - /* free all the memory */ - greybus_free_gbuf(gbuf); - kfree(cm); -} - -static void cport_create_event(struct gbuf *gbuf) -{ - struct cport_msg *cm; - - /* Slow alloc, does it matter??? */ - cm = kmalloc(sizeof(*cm), GFP_ATOMIC); + struct gbuf *gbuf = container_of(work, struct gbuf, event); - /* Queue up the cport message to be handled in user context */ - cm->gbuf = gbuf; - INIT_WORK(&cm->event, cport_process_event); - queue_work(cport_workqueue, &cm->event); + /* Call the completion handler, then drop our reference */ + gbuf->complete(gbuf); + greybus_put_gbuf(gbuf); } #define MAX_CPORTS 1024 @@ -237,21 +214,21 @@ void greybus_cport_in_data(struct greybus_host_device *hd, int cport, u8 *data, gbuf->transfer_buffer_length = length; gbuf->actual_length = length; - cport_create_event(gbuf); + queue_work(gbuf_workqueue, &gbuf->event); } EXPORT_SYMBOL_GPL(greybus_cport_in_data); /* Can be called in interrupt context, do the work and get out of here */ void greybus_gbuf_finished(struct gbuf *gbuf) { - cport_create_event(gbuf); + queue_work(gbuf_workqueue, &gbuf->event); } EXPORT_SYMBOL_GPL(greybus_gbuf_finished); int gb_gbuf_init(void) { - cport_workqueue = alloc_workqueue("greybus_gbuf", 0, 1); - if (!cport_workqueue) + gbuf_workqueue = alloc_workqueue("greybus_gbuf", 0, 1); + if (!gbuf_workqueue) return -ENOMEM; gbuf_head_cache = kmem_cache_create("gbuf_head_cache", @@ -261,6 +238,6 @@ int gb_gbuf_init(void) void gb_gbuf_exit(void) { - destroy_workqueue(cport_workqueue); + destroy_workqueue(gbuf_workqueue); kmem_cache_destroy(gbuf_head_cache); } diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 59f9b98..692a5b9 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -133,6 +133,7 @@ struct gbuf { unsigned int direction : 1; /* 0 is out, 1 is in */ void *context; + struct work_struct event; gbuf_complete_t complete; }; -- cgit v0.10.2 From dce745af21884c9e27665a333d3b4fc9fcf643e7 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 23 Sep 2014 20:58:58 -0700 Subject: greybus: fix up coding style issue I caused with the last patch... diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index b51bd2a..46896e8 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -139,8 +139,8 @@ static void cport_process_event(struct work_struct *work) struct gbuf *gbuf = container_of(work, struct gbuf, event); /* Call the completion handler, then drop our reference */ - gbuf->complete(gbuf); - greybus_put_gbuf(gbuf); + gbuf->complete(gbuf); + greybus_put_gbuf(gbuf); } #define MAX_CPORTS 1024 -- cgit v0.10.2 From 6d63ff7a2d40b8865eb00857cdb910944c17f0b2 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Fri, 26 Sep 2014 20:49:48 -0500 Subject: greybus: update descriptor module_id->module to match spec Greybus spec was updated to change the name of the Module ID descriptor to simply Module descriptor. Change everything accordingly. Signed-off-by: Matt Porter Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 33d7a33..37bc780 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -33,18 +33,18 @@ EXPORT_SYMBOL_GPL(greybus_disabled); static int greybus_match_one_id(struct greybus_module *gmod, const struct greybus_module_id *id) { - struct greybus_descriptor_module_id *module_id; + struct greybus_descriptor_module *module; struct greybus_descriptor_serial_number *serial_num; - module_id = &gmod->module_id; + module = &gmod->module; serial_num = &gmod->serial_number; if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_VENDOR) && - (id->vendor != le16_to_cpu(module_id->vendor))) + (id->vendor != le16_to_cpu(module->vendor))) return 0; if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_PRODUCT) && - (id->product != le16_to_cpu(module_id->product))) + (id->product != le16_to_cpu(module->product))) return 0; if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_SERIAL) && @@ -249,16 +249,16 @@ static int create_function(struct greybus_module *gmod, return 0; } -static int create_module_id(struct greybus_module *gmod, - struct greybus_descriptor_module_id *module_id, +static int create_module(struct greybus_module *gmod, + struct greybus_descriptor_module *module, size_t desc_size) { - if (desc_size != sizeof(*module_id)) { + if (desc_size != sizeof(*module)) { dev_err(gmod->dev.parent, "invalid module header size %zu\n", desc_size); return -EINVAL; } - memcpy(&gmod->module_id, module_id, desc_size); + memcpy(&gmod->module, module, desc_size); return 0; } @@ -422,8 +422,8 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, data_size); break; - case GREYBUS_TYPE_MODULE_ID: - retval = create_module_id(gmod, &desc->module_id, + case GREYBUS_TYPE_MODULE: + retval = create_module(gmod, &desc->module, data_size); break; diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 692a5b9..0a0b0a5 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -200,7 +200,7 @@ struct greybus_module { struct device dev; u16 module_number; struct greybus_descriptor_function function; - struct greybus_descriptor_module_id module_id; + struct greybus_descriptor_module module; struct greybus_descriptor_serial_number serial_number; int num_cports; int num_strings; diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 8b4acd3..037d7a4 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -21,7 +21,7 @@ struct greybus_manifest_header { enum greybus_descriptor_type { GREYBUS_TYPE_INVALID = 0x0000, GREYBUS_TYPE_FUNCTION = 0x0001, - GREYBUS_TYPE_MODULE_ID = 0x0002, + GREYBUS_TYPE_MODULE = 0x0002, GREYBUS_TYPE_SERIAL_NUMBER = 0x0003, GREYBUS_TYPE_STRING = 0x0004, GREYBUS_TYPE_CPORT = 0x0005, @@ -58,7 +58,7 @@ struct greybus_descriptor_function { __u8 reserved; }; -struct greybus_descriptor_module_id { +struct greybus_descriptor_module { __le16 vendor; __le16 product; __le16 version; @@ -87,7 +87,7 @@ struct greybus_descriptor { struct greybus_descriptor_header header; union { struct greybus_descriptor_function function; - struct greybus_descriptor_module_id module_id; + struct greybus_descriptor_module module; struct greybus_descriptor_serial_number serial_number; struct greybus_descriptor_string string; struct greybus_descriptor_cport cport; diff --git a/drivers/staging/greybus/sysfs.c b/drivers/staging/greybus/sysfs.c index 792a238..8cedd4b 100644 --- a/drivers/staging/greybus/sysfs.c +++ b/drivers/staging/greybus/sysfs.c @@ -74,7 +74,7 @@ static ssize_t module_##field##_show(struct device *dev, \ char *buf) \ { \ struct greybus_module *gmod = to_greybus_module(dev); \ - return sprintf(buf, "%x\n", gmod->module_id.field); \ + return sprintf(buf, "%x\n", gmod->module.field); \ } \ static DEVICE_ATTR_RO(module_##field) @@ -89,7 +89,7 @@ static ssize_t module_vendor_string_show(struct device *dev, struct greybus_module *gmod = to_greybus_module(dev); return sprintf(buf, "%s", - greybus_string(gmod, gmod->module_id.vendor_stringid)); + greybus_string(gmod, gmod->module.vendor_stringid)); } static DEVICE_ATTR_RO(module_vendor_string); @@ -100,7 +100,7 @@ static ssize_t module_product_string_show(struct device *dev, struct greybus_module *gmod = to_greybus_module(dev); return sprintf(buf, "%s", - greybus_string(gmod, gmod->module_id.product_stringid)); + greybus_string(gmod, gmod->module.product_stringid)); } static DEVICE_ATTR_RO(module_product_string); @@ -119,17 +119,17 @@ static umode_t module_attrs_are_visible(struct kobject *kobj, struct greybus_module *gmod = to_greybus_module(kobj_to_dev(kobj)); if ((a == &dev_attr_module_vendor_string.attr) && - (gmod->module_id.vendor_stringid)) + (gmod->module.vendor_stringid)) return a->mode; if ((a == &dev_attr_module_product_string.attr) && - (gmod->module_id.product_stringid)) + (gmod->module.product_stringid)) return a->mode; // FIXME - make this a dynamic structure to "know" if it really is here // or not easier? - if (gmod->module_id.vendor || - gmod->module_id.product || - gmod->module_id.version) + if (gmod->module.vendor || + gmod->module.product || + gmod->module.version) return a->mode; return 0; } -- cgit v0.10.2 From 4fc645494f7a363f0aa8a997b38ac73a63306e61 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Fri, 26 Sep 2014 20:49:49 -0500 Subject: greybus: remove serial number descriptor to match spec Greybus spec was updated to remove the serial number descriptor and move the serial number field to the, now mandatory, module descriptor. Change everything accordingly. Signed-off-by: Matt Porter Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 37bc780..fc54ac9 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -34,10 +34,8 @@ static int greybus_match_one_id(struct greybus_module *gmod, const struct greybus_module_id *id) { struct greybus_descriptor_module *module; - struct greybus_descriptor_serial_number *serial_num; module = &gmod->module; - serial_num = &gmod->serial_number; if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_VENDOR) && (id->vendor != le16_to_cpu(module->vendor))) @@ -48,7 +46,7 @@ static int greybus_match_one_id(struct greybus_module *gmod, return 0; if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_SERIAL) && - (id->serial_number != le64_to_cpu(serial_num->serial_number))) + (id->serial_number != le64_to_cpu(module->serial_number))) return 0; return 1; @@ -262,19 +260,6 @@ static int create_module(struct greybus_module *gmod, return 0; } -static int create_serial_number(struct greybus_module *gmod, - struct greybus_descriptor_serial_number *serial_num, - size_t desc_size) -{ - if (desc_size != sizeof(*serial_num)) { - dev_err(gmod->dev.parent, "invalid serial number header size %zu\n", - desc_size); - return -EINVAL; - } - memcpy(&gmod->serial_number, serial_num, desc_size); - return 0; -} - static int create_string(struct greybus_module *gmod, struct greybus_descriptor_string *string, size_t desc_size) @@ -427,12 +412,6 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, data_size); break; - case GREYBUS_TYPE_SERIAL_NUMBER: - retval = create_serial_number(gmod, - &desc->serial_number, - data_size); - break; - case GREYBUS_TYPE_STRING: retval = create_string(gmod, &desc->string, data_size); break; diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 0a0b0a5..87e6218 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -201,7 +201,6 @@ struct greybus_module { u16 module_number; struct greybus_descriptor_function function; struct greybus_descriptor_module module; - struct greybus_descriptor_serial_number serial_number; int num_cports; int num_strings; struct gmod_cport *cport[MAX_CPORTS_PER_MODULE]; diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 037d7a4..6dda11c 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -22,7 +22,6 @@ enum greybus_descriptor_type { GREYBUS_TYPE_INVALID = 0x0000, GREYBUS_TYPE_FUNCTION = 0x0001, GREYBUS_TYPE_MODULE = 0x0002, - GREYBUS_TYPE_SERIAL_NUMBER = 0x0003, GREYBUS_TYPE_STRING = 0x0004, GREYBUS_TYPE_CPORT = 0x0005, }; @@ -62,14 +61,11 @@ struct greybus_descriptor_module { __le16 vendor; __le16 product; __le16 version; + __le64 serial_number; __u8 vendor_stringid; __u8 product_stringid; }; -struct greybus_descriptor_serial_number { - __le64 serial_number; -}; - struct greybus_descriptor_string { __le16 length; __u8 id; @@ -88,7 +84,6 @@ struct greybus_descriptor { union { struct greybus_descriptor_function function; struct greybus_descriptor_module module; - struct greybus_descriptor_serial_number serial_number; struct greybus_descriptor_string string; struct greybus_descriptor_cport cport; }; diff --git a/drivers/staging/greybus/sysfs.c b/drivers/staging/greybus/sysfs.c index 8cedd4b..55dc7b7 100644 --- a/drivers/staging/greybus/sysfs.c +++ b/drivers/staging/greybus/sysfs.c @@ -82,6 +82,17 @@ greybus_module_attr(vendor); greybus_module_attr(product); greybus_module_attr(version); +static ssize_t module_serial_number_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct greybus_module *gmod = to_greybus_module(dev); + + return sprintf(buf, "%llX\n", + (unsigned long long)le64_to_cpu(gmod->module.serial_number)); +} +static DEVICE_ATTR_RO(module_serial_number); + static ssize_t module_vendor_string_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -108,6 +119,7 @@ static struct attribute *module_attrs[] = { &dev_attr_module_vendor.attr, &dev_attr_module_product.attr, &dev_attr_module_version.attr, + &dev_attr_module_serial_number.attr, &dev_attr_module_vendor_string.attr, &dev_attr_module_product_string.attr, NULL, @@ -129,7 +141,8 @@ static umode_t module_attrs_are_visible(struct kobject *kobj, // or not easier? if (gmod->module.vendor || gmod->module.product || - gmod->module.version) + gmod->module.version || + gmod->module.serial_number) return a->mode; return 0; } @@ -140,38 +153,11 @@ static struct attribute_group module_attr_grp = { }; -/* Serial Number */ -static ssize_t serial_number_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct greybus_module *gmod = to_greybus_module(dev); - - return sprintf(buf, "%llX\n", - (unsigned long long)le64_to_cpu(gmod->serial_number.serial_number)); -} -static DEVICE_ATTR_RO(serial_number); - -static struct attribute *serial_number_attrs[] = { - &dev_attr_serial_number.attr, - NULL, -}; - -static umode_t serial_number_is_visible(struct kobject *kobj, - struct attribute *a, int n) -{ - return a->mode; -} - -static struct attribute_group serial_number_attr_grp = { - .attrs = serial_number_attrs, - .is_visible = serial_number_is_visible, -}; const struct attribute_group *greybus_module_groups[] = { &function_attr_grp, &module_attr_grp, - &serial_number_attr_grp, NULL, }; -- cgit v0.10.2 From 097724c2fb203d1bfa0853ddf73c3a5df030ab05 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Fri, 26 Sep 2014 20:49:50 -0500 Subject: greybus: remove unused function descriptor fields and change class->function_type Greybus spec was updated to remove a number of unused function descriptor fields. In addition, the class field was change to function_type to avoid confusion with the concept of high-level class drivers. Signed-off-by: Matt Porter Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 6dda11c..2830d55 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -31,7 +31,7 @@ struct greybus_descriptor_header { __le16 type; /* enum greybus_descriptor_type */ }; -enum greybus_function_class { +enum greybus_function_type { GREYBUS_FUNCTION_CONTROL = 0x00, GREYBUS_FUNCTION_USB = 0x01, GREYBUS_FUNCTION_GPIO = 0x02, @@ -49,12 +49,8 @@ enum greybus_function_class { }; struct greybus_descriptor_function { - __le16 number; __le16 cport; - __u8 class; /* enum greybus_function_class */ - __u8 subclass; - __u8 protocol; - __u8 reserved; + __u8 function_type; /* enum greybus_function_type */ }; struct greybus_descriptor_module { diff --git a/drivers/staging/greybus/sysfs.c b/drivers/staging/greybus/sysfs.c index 55dc7b7..1f17388 100644 --- a/drivers/staging/greybus/sysfs.c +++ b/drivers/staging/greybus/sysfs.c @@ -31,18 +31,12 @@ static ssize_t function_##field##_show(struct device *dev, \ } \ static DEVICE_ATTR_RO(function_##field) -greybus_function_attr(number); greybus_function_attr(cport); -greybus_function_attr(class); -greybus_function_attr(subclass); -greybus_function_attr(protocol); +greybus_function_attr(function_type); static struct attribute *function_attrs[] = { - &dev_attr_function_number.attr, &dev_attr_function_cport.attr, - &dev_attr_function_class.attr, - &dev_attr_function_subclass.attr, - &dev_attr_function_protocol.attr, + &dev_attr_function_function_type.attr, NULL, }; @@ -53,11 +47,8 @@ static umode_t function_attrs_are_visible(struct kobject *kobj, // FIXME - make this a dynamic structure to "know" if it really is here // or not easier? - if (gmod->function.number || - gmod->function.cport || - gmod->function.class || - gmod->function.subclass || - gmod->function.protocol) + if (gmod->function.cport || + gmod->function.function_type) return a->mode; return 0; } -- cgit v0.10.2 From cbd0fd7b9b6fd5c6d9f13f021a17a072e9d33147 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Fri, 26 Sep 2014 20:49:51 -0500 Subject: greybus: update string descriptor length field to __u8 type to match spec Greybus spec was updated to make the length field a single byte. Update the type and remove endian handling of that field in the core. Signed-off-by: Matt Porter Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index fc54ac9..05217c6 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -279,7 +279,7 @@ static int create_string(struct greybus_module *gmod, return -EINVAL; } - string_size = le16_to_cpu(string->length); + string_size = string->length; gmod_string = kzalloc(sizeof(*gmod_string) + string_size + 1, GFP_KERNEL); if (!gmod_string) return -ENOMEM; diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 2830d55..8ffeb17 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -63,7 +63,7 @@ struct greybus_descriptor_module { }; struct greybus_descriptor_string { - __le16 length; + __u8 length; __u8 id; __u8 string[0]; }; -- cgit v0.10.2 From c41a36677365e6c5ad9e01ef50776052dfb6c0c5 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Fri, 26 Sep 2014 20:49:52 -0500 Subject: greybus: update descriptor type enums to match renumbering in spec Greybus spec updated the descriptor type values and added an additional class descriptor type. Change the enum accordingly. Signed-off-by: Matt Porter Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 8ffeb17..f1f3237 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -20,8 +20,9 @@ struct greybus_manifest_header { enum greybus_descriptor_type { GREYBUS_TYPE_INVALID = 0x0000, - GREYBUS_TYPE_FUNCTION = 0x0001, - GREYBUS_TYPE_MODULE = 0x0002, + GREYBUS_TYPE_MODULE = 0x0001, + GREYBUS_TYPE_FUNCTION = 0x0002, + GREYBUS_TYPE_CLASS = 0x0003, GREYBUS_TYPE_STRING = 0x0004, GREYBUS_TYPE_CPORT = 0x0005, }; -- cgit v0.10.2 From 877b1ee82e4eb5d0fa56ff5eef310c75556c8762 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 24 Sep 2014 05:16:13 -0500 Subject: greybus: encapsulate URB status checking Define a new common function check_urb_status() that looks at the status in a completed URB (containing incoming data) and issues warnings in a consistent way. It returns -EAGAIN to signal an unrecognized status was seen, so the caller can ignore it and re-post the URB to receive the next incoming data. This consolidates three blocks of code into one. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index dfe96cb..7ce3a77 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -227,17 +227,16 @@ static struct greybus_host_driver es1_driver = { .submit_gbuf = submit_gbuf, }; -/* Callback for when we get a SVC message */ -static void svc_callback(struct urb *urb) +/* Common function to report consistent warnings based on URB status */ +static int check_urb_status(struct urb *urb) { - struct es1_ap_dev *es1 = urb->context; struct device *dev = &urb->dev->dev; int status = urb->status; - int retval; switch (status) { case 0: - break; + return 0; + case -EOVERFLOW: dev_err(dev, "%s: overflow actual length is %d\n", __func__, urb->actual_length); @@ -246,11 +245,25 @@ static void svc_callback(struct urb *urb) case -ESHUTDOWN: case -EILSEQ: /* device is gone, stop sending */ - return; - default: - dev_err(dev, "%s: unknown status %d\n", __func__, status); - goto exit; + return status; } + dev_err(dev, "%s: unknown status %d\n", __func__, status); + + return -EAGAIN; +} + +/* Callback for when we get a SVC message */ +static void svc_in_callback(struct urb *urb) +{ + struct es1_ap_dev *es1 = urb->context; + struct device *dev = &urb->dev->dev; + int status = check_urb_status(urb); + int retval; + + if (status == -EAGAIN) + goto exit; + if (status) + return; /* We have a message, create a new message structure, add it to the * list, and wake up our thread that will process the messages. @@ -268,27 +281,15 @@ static void cport_in_callback(struct urb *urb) { struct device *dev = &urb->dev->dev; struct es1_ap_dev *es1 = urb->context; - int status = urb->status; + int status = check_urb_status(urb); int retval; u8 cport; u8 *data; - switch (status) { - case 0: - break; - case -EOVERFLOW: - dev_err(dev, "%s: overflow actual length is %d\n", - __func__, urb->actual_length); - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - case -EILSEQ: - /* device is gone, stop sending */ - return; - default: - dev_err(dev, "%s: unknown status %d\n", __func__, status); + if (status == -EAGAIN) goto exit; - } + if (status) + return; /* The size has to be more then just an "empty" transfer */ if (urb->actual_length <= 2) { @@ -318,35 +319,15 @@ exit: static void cport_out_callback(struct urb *urb) { - struct device *dev = &urb->dev->dev; struct gbuf *gbuf = urb->context; struct es1_ap_dev *es1 = gbuf->hdpriv; unsigned long flags; - int status = urb->status; int i; - /* do we care about errors going back up? */ - switch (status) { - case 0: - break; - case -EOVERFLOW: - dev_err(dev, "%s: overflow actual length is %d\n", - __func__, urb->actual_length); - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - case -EILSEQ: - /* device is gone, stop sending */ - goto exit; - default: - dev_err(dev, "%s: unknown status %d\n", __func__, status); - goto exit; - } - - /* Tell the core the gbuf is properly sent */ - greybus_gbuf_finished(gbuf); + /* If no error, tell the core the gbuf is properly sent */ + if (!check_urb_status(urb)) + greybus_gbuf_finished(gbuf); -exit: /* * See if this was an urb in our pool, if so mark it "free", otherwise * we need to free it ourselves. @@ -443,7 +424,7 @@ static int ap_probe(struct usb_interface *interface, usb_fill_int_urb(es1->svc_urb, udev, usb_rcvintpipe(udev, es1->svc_endpoint), - es1->svc_buffer, ES1_SVC_MSG_SIZE, svc_callback, + es1->svc_buffer, ES1_SVC_MSG_SIZE, svc_in_callback, es1, svc_interval); retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); if (retval) -- cgit v0.10.2 From 0db32a6d5e58d85cfa4ffe5cebbde60917f61bba Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 24 Sep 2014 05:16:14 -0500 Subject: greybus: some more renames This patch renames of symbols, for better clarity and consistency. cport -> cport_id (when it represents a cport *number*) send_svc_msg -> submit_svc (like submit_gbuf) greybus_cport_in_data -> greybus_cport_in gb_new_ap_msg -> greybus_svc_in (like greybus_cport_in) cport->number -> cport->id (like cport_id) Making the svc and cport message stuff more similar is done with an eye toward having SVC messages and messages exchanged with other modules use some more common communication mechanisms. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 78e9e4a..e3684299 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -53,7 +53,7 @@ static int svc_msg_send(struct svc_msg *svc_msg, struct greybus_host_device *hd) // FIXME - Do we need to do more than just pass it to the hd and then // free it? - retval = hd->driver->send_svc_msg(svc_msg, hd); + retval = hd->driver->submit_svc(svc_msg, hd); svc_msg_free(svc_msg); return retval; @@ -294,7 +294,7 @@ static void ap_process_event(struct work_struct *work) kfree(ap_msg); } -int gb_new_ap_msg(u8 *data, int size, struct greybus_host_device *hd) +int greybus_svc_in(u8 *data, int size, struct greybus_host_device *hd) { struct ap_msg *ap_msg; @@ -326,7 +326,7 @@ int gb_new_ap_msg(u8 *data, int size, struct greybus_host_device *hd) return 0; } -EXPORT_SYMBOL_GPL(gb_new_ap_msg); +EXPORT_SYMBOL_GPL(greybus_svc_in); int gb_ap_init(void) { diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 05217c6..a240a92 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -315,7 +315,7 @@ static int create_cport(struct greybus_module *gmod, if (!gmod_cport) return -ENOMEM; - gmod_cport->number = le16_to_cpu(cport->number); + gmod_cport->id = le16_to_cpu(cport->id); gmod_cport->size = le16_to_cpu(cport->size); gmod_cport->speed = cport->speed; diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 7ce3a77..b6ab124 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -113,7 +113,7 @@ static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask) * we will encode the cport number in the first byte of the buffer, so * set the second byte to be the "transfer buffer" */ - buffer[0] = gbuf->cport->number; + buffer[0] = gbuf->cport->id; gbuf->transfer_buffer = &buffer[1]; gbuf->transfer_buffer_length = size; gbuf->actual_length = size; @@ -139,7 +139,7 @@ static void free_gbuf_data(struct gbuf *gbuf) } #define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ -static int send_svc_msg(struct svc_msg *svc_msg, struct greybus_host_device *hd) +static int submit_svc(struct svc_msg *svc_msg, struct greybus_host_device *hd) { struct es1_ap_dev *es1 = hd_to_es1(hd); int retval; @@ -223,7 +223,7 @@ static struct greybus_host_driver es1_driver = { .hd_priv_size = sizeof(struct es1_ap_dev), .alloc_gbuf_data = alloc_gbuf_data, .free_gbuf_data = free_gbuf_data, - .send_svc_msg = send_svc_msg, + .submit_svc = submit_svc, .submit_gbuf = submit_gbuf, }; @@ -268,7 +268,7 @@ static void svc_in_callback(struct urb *urb) /* We have a message, create a new message structure, add it to the * list, and wake up our thread that will process the messages. */ - gb_new_ap_msg(urb->transfer_buffer, urb->actual_length, es1->hd); + greybus_svc_in(urb->transfer_buffer, urb->actual_length, es1->hd); exit: /* resubmit the urb to get more messages */ @@ -307,7 +307,7 @@ static void cport_in_callback(struct urb *urb) data = &data[1]; /* Pass this data to the greybus core */ - greybus_cport_in_data(es1->hd, cport, data, urb->actual_length - 1); + greybus_cport_in(es1->hd, cport, data, urb->actual_length - 1); exit: /* put our urb back in the request pool */ diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 46896e8..94c2d6a 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -156,36 +156,36 @@ static struct gb_cport_handler cport_handler[MAX_CPORTS]; // need it, we don't have a dynamic system... int gb_register_cport_complete(struct greybus_module *gmod, - gbuf_complete_t handler, int cport, + gbuf_complete_t handler, int cport_id, void *context) { - if (cport_handler[cport].handler) + if (cport_handler[cport_id].handler) return -EINVAL; - cport_handler[cport].context = context; - cport_handler[cport].gmod = gmod; - cport_handler[cport].cport.number = cport; - cport_handler[cport].handler = handler; + cport_handler[cport_id].context = context; + cport_handler[cport_id].gmod = gmod; + cport_handler[cport_id].cport.id = cport_id; + cport_handler[cport_id].handler = handler; return 0; } -void gb_deregister_cport_complete(int cport) +void gb_deregister_cport_complete(int cport_id) { - cport_handler[cport].handler = NULL; + cport_handler[cport_id].handler = NULL; } -void greybus_cport_in_data(struct greybus_host_device *hd, int cport, u8 *data, +void greybus_cport_in(struct greybus_host_device *hd, int cport_id, u8 *data, size_t length) { struct gb_cport_handler *ch; struct gbuf *gbuf; /* first check to see if we have a cport handler for this cport */ - ch = &cport_handler[cport]; + ch = &cport_handler[cport_id]; if (!ch->handler) { /* Ugh, drop the data on the floor, after logging it... */ dev_err(hd->parent, "Received data for cport %d, but no handler!\n", - cport); + cport_id); return; } @@ -216,7 +216,7 @@ void greybus_cport_in_data(struct greybus_host_device *hd, int cport, u8 *data, queue_work(gbuf_workqueue, &gbuf->event); } -EXPORT_SYMBOL_GPL(greybus_cport_in_data); +EXPORT_SYMBOL_GPL(greybus_cport_in); /* Can be called in interrupt context, do the work and get out of here */ void greybus_gbuf_finished(struct gbuf *gbuf) diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 87e6218..7948220 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -91,9 +91,9 @@ Submit a SVC message to the hardware the host controller function send_svc_msg is called Receive gbuf messages - the host controller driver must call greybus_cport_in_data() with the data + the host controller driver must call greybus_cport_in() with the data Reveive SVC messages from the hardware - The host controller driver must call gb_new_ap_msg + The host controller driver must call greybus_svc_in */ @@ -102,7 +102,7 @@ struct gbuf; struct gmod_cport { - u16 number; + u16 id; u16 size; u8 speed; // valid??? // FIXME, what else? @@ -169,7 +169,7 @@ struct greybus_host_driver { int (*alloc_gbuf_data)(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask); void (*free_gbuf_data)(struct gbuf *gbuf); - int (*send_svc_msg)(struct svc_msg *svc_msg, + int (*submit_svc)(struct svc_msg *svc_msg, struct greybus_host_device *hd); int (*submit_gbuf)(struct gbuf *gbuf, struct greybus_host_device *hd, gfp_t gfp_mask); @@ -187,7 +187,7 @@ struct greybus_host_device { struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *host_driver, struct device *parent); void greybus_remove_hd(struct greybus_host_device *hd); -void greybus_cport_in_data(struct greybus_host_device *hd, int cport, u8 *data, +void greybus_cport_in(struct greybus_host_device *hd, int cport_id, u8 *data, size_t length); void greybus_gbuf_finished(struct gbuf *gbuf); @@ -289,7 +289,7 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, u8 *data, int size); void gb_remove_module(struct greybus_host_device *hd, u8 module_id); -int gb_new_ap_msg(u8 *data, int length, struct greybus_host_device *hd); +int greybus_svc_in(u8 *data, int length, struct greybus_host_device *hd); int gb_ap_init(void); void gb_ap_exit(void); int gb_debugfs_init(void); @@ -298,9 +298,9 @@ int gb_gbuf_init(void); void gb_gbuf_exit(void); int gb_register_cport_complete(struct greybus_module *gmod, - gbuf_complete_t handler, int cport, + gbuf_complete_t handler, int cport_id, void *context); -void gb_deregister_cport_complete(int cport); +void gb_deregister_cport_complete(int cport_id); extern const struct attribute_group *greybus_module_groups[]; diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index f1f3237..6f019fa 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -70,7 +70,7 @@ struct greybus_descriptor_string { }; struct greybus_descriptor_cport { - __le16 number; + __le16 id; __le16 size; __u8 speed; // FIXME __u8 reserved; diff --git a/drivers/staging/greybus/test_sink.c b/drivers/staging/greybus/test_sink.c index 9dbf6ee..8b254e3 100644 --- a/drivers/staging/greybus/test_sink.c +++ b/drivers/staging/greybus/test_sink.c @@ -16,9 +16,9 @@ struct test_device { }; int gb_register_cport_complete(struct greybus_module *gmod, - gbuf_complete_t handler, int cport, + gbuf_complete_t handler, int cport_id, void *context); -void gb_deregister_cport_complete(int cport); +void gb_deregister_cport_complete(int cport_id); diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 2021f27..7735a04 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -34,7 +34,7 @@ struct gb_tty { struct tty_port port; struct greybus_module *gmod; - int cport; + int cport_id; unsigned int minor; unsigned char clocal; unsigned int throttled:1; -- cgit v0.10.2 From 908a85d7dd09f5acc28de147a2e3dc84aa2d0b6b Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 24 Sep 2014 05:16:16 -0500 Subject: greybus: update a few header file comments Add a GPLv2 tag and reword some comments at the top of "greybus_desc.h" and "svc_msg.h". Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 6f019fa..844a7f1 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -1,10 +1,12 @@ /* - * Greybus device descriptor definition + * Greybus module manifest definition * - * Defined in the "Greybus Application Protocol" document. - * See that document for any details on these values and structures. + * See "Greybus Application Protocol" document (version 0.draft) for + * details on these values and structures. * * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. */ #ifndef __GREYBUS_DESC_H diff --git a/drivers/staging/greybus/svc_msg.h b/drivers/staging/greybus/svc_msg.h index c290547..8b936ed 100644 --- a/drivers/staging/greybus/svc_msg.h +++ b/drivers/staging/greybus/svc_msg.h @@ -1,10 +1,12 @@ /* * Greybus AP <-> SVC message structure format. * - * Defined in the "Greybus Application Protocol" document. - * See that document for any details on these values and structures. + * See "Greybus Application Protocol" document (version 0.draft) for + * details on these values and structures. * * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. */ #ifndef __SVC_MSG_H -- cgit v0.10.2 From cb705e0dd0bc0614660aaf9adb0984c538532acf Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 24 Sep 2014 05:16:17 -0500 Subject: greybus: fix document version number Two spots use the old "0.draft" version number for the Greybus protocol specification. We've updated that to be 0.1. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 844a7f1..8865beec 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -1,7 +1,7 @@ /* * Greybus module manifest definition * - * See "Greybus Application Protocol" document (version 0.draft) for + * See "Greybus Application Protocol" document (version 0.1) for * details on these values and structures. * * Copyright 2014 Google Inc. diff --git a/drivers/staging/greybus/svc_msg.h b/drivers/staging/greybus/svc_msg.h index 8b936ed..4b69604 100644 --- a/drivers/staging/greybus/svc_msg.h +++ b/drivers/staging/greybus/svc_msg.h @@ -1,7 +1,7 @@ /* * Greybus AP <-> SVC message structure format. * - * See "Greybus Application Protocol" document (version 0.draft) for + * See "Greybus Application Protocol" document (version 0.1) for * details on these values and structures. * * Copyright 2014 Google Inc. -- cgit v0.10.2 From 1dd7f58f8e24e03a3a5eea85a547a1ba91d82e81 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 26 Sep 2014 20:55:32 -0500 Subject: greybus: fix the guard in "greybus_manifest.h" The tag in the #ifndef guard surrounding the content of "greybus_manifest.h" needs to be updated to reflect the actual name of the file. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 8865beec..75dea81 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -9,8 +9,8 @@ * Released under the GPLv2 only. */ -#ifndef __GREYBUS_DESC_H -#define __GREYBUS_DESC_H +#ifndef __GREYBUS_MANIFEST_H +#define __GREYBUS_MANIFEST_H #pragma pack(push, 1) @@ -95,4 +95,4 @@ struct greybus_manifest { #pragma pack(pop) -#endif /* __GREYBUS_DESC_H */ +#endif /* __GREYBUS_MANIFEST_H */ -- cgit v0.10.2 From 72b0ffc019137b4877145ef7143cd69a6194b9c6 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 26 Sep 2014 20:55:33 -0500 Subject: greybus: descriptor type is 1 byte The spec was changed to require only one byte to represent the type of a module descriptor. Update our data type and the values used to reflect that. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 75dea81..0867054 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -21,17 +21,17 @@ struct greybus_manifest_header { }; enum greybus_descriptor_type { - GREYBUS_TYPE_INVALID = 0x0000, - GREYBUS_TYPE_MODULE = 0x0001, - GREYBUS_TYPE_FUNCTION = 0x0002, - GREYBUS_TYPE_CLASS = 0x0003, - GREYBUS_TYPE_STRING = 0x0004, - GREYBUS_TYPE_CPORT = 0x0005, + GREYBUS_TYPE_INVALID = 0x00, + GREYBUS_TYPE_MODULE = 0x01, + GREYBUS_TYPE_FUNCTION = 0x02, + GREYBUS_TYPE_CLASS = 0x03, + GREYBUS_TYPE_STRING = 0x04, + GREYBUS_TYPE_CPORT = 0x05, }; struct greybus_descriptor_header { __le16 size; - __le16 type; /* enum greybus_descriptor_type */ + __u8 type; /* enum greybus_descriptor_type */ }; enum greybus_function_type { -- cgit v0.10.2 From 01e8280150a2ef330f082a996479b96d75164353 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 26 Sep 2014 20:55:34 -0500 Subject: greybus: fix version check When we read a module manifest we are required to verify that its version is compatible with the version the present code is able to parse. All that's required is a check of the major version number. If the manifest's major version is greater than the software, the software can't assume it can parse it. All new code must be able to parse all old versions of the format. And any difference in minor version is supposed to have no effect on parsability. Update the version check to enforce this policy, and reword the error message to do a better job of explaining the situation. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index a240a92..3cc54ed 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -338,8 +338,6 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, struct greybus_manifest *manifest; int retval; int overall_size; - u8 version_major; - u8 version_minor; /* we have to have at _least_ the manifest header */ if (size <= sizeof(manifest->header)) @@ -367,16 +365,13 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, goto error; } - version_major = manifest->header.version_major; - version_minor = manifest->header.version_minor; - /* Validate major/minor number */ - if ((version_major != GREYBUS_VERSION_MAJOR) || - (version_minor != GREYBUS_VERSION_MINOR)) { + if (manifest->header.version_major > GREYBUS_VERSION_MAJOR) { dev_err(hd->parent, - "Invalid greybus versions, expected %d.%d, got %d.%d\n", - GREYBUS_VERSION_MAJOR, GREYBUS_VERSION_MINOR, - version_major, version_minor); + "Manifest version too new (%hhu.%hhu > %hhu.%hhu)\n", + manifest->header.version_major, + manifest->header.version_minor, + GREYBUS_VERSION_MAJOR, GREYBUS_VERSION_MINOR); goto error; } -- cgit v0.10.2 From 51c75fd060a71dfdf4f836759a2b9300ae8af138 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 26 Sep 2014 20:55:35 -0500 Subject: greybus: reorder greybus_svc_in() arguments The two functions greybus_svc_in() and greybus_cport_in() do very similar things, but their arguments are in a different order. Move the greybus_host_device structure argument for greybus_svc_in() to be first so the functions' prototypes are better aligned. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index e3684299..f4470b5 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -294,7 +294,7 @@ static void ap_process_event(struct work_struct *work) kfree(ap_msg); } -int greybus_svc_in(u8 *data, int size, struct greybus_host_device *hd) +int greybus_svc_in(struct greybus_host_device *hd, u8 *data, int size) { struct ap_msg *ap_msg; diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index b6ab124..291da40 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -268,7 +268,7 @@ static void svc_in_callback(struct urb *urb) /* We have a message, create a new message structure, add it to the * list, and wake up our thread that will process the messages. */ - greybus_svc_in(urb->transfer_buffer, urb->actual_length, es1->hd); + greybus_svc_in(es1->hd, urb->transfer_buffer, urb->actual_length); exit: /* resubmit the urb to get more messages */ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 7948220..1328dc9 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -289,7 +289,7 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, u8 *data, int size); void gb_remove_module(struct greybus_host_device *hd, u8 module_id); -int greybus_svc_in(u8 *data, int length, struct greybus_host_device *hd); +int greybus_svc_in(struct greybus_host_device *hd, u8 *data, int length); int gb_ap_init(void); void gb_ap_exit(void); int gb_debugfs_init(void); -- cgit v0.10.2 From f0f70916fba72ca70235ca40db43030ec8f467ad Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Tue, 30 Sep 2014 16:01:40 -0400 Subject: greybus: es1-ap-usb: adjust SVC buffer size to handle worst case The worst case message from the SVC->AP is a hotplug "plugged" event. It includes the module manifest which may be up to 64KB in size. Adjust our buffer allocation to allow for this. Signed-off-by: Matt Porter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 291da40..8df1643 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -9,12 +9,13 @@ #include #include #include +#include #include #include "greybus.h" #include "svc_msg.h" /* Memory sizes for the buffers sent to/from the ES1 controller */ -#define ES1_SVC_MSG_SIZE 2048 +#define ES1_SVC_MSG_SIZE (sizeof(struct svc_msg) + SZ_64K) #define ES1_GBUF_MSG_SIZE PAGE_SIZE -- cgit v0.10.2 From 1cfc667d75d3a38989365da387f52a1c303c435d Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 30 Sep 2014 19:25:21 -0500 Subject: greybus: kill struct gmod_cport A UniPro (short header) segment has a 5-bit field to represent a CPort Id. In addition, the 7-bit L3 short header holds a UniPro device id. There can be no more than 128 devices in a UniPro network, but these two fields can be combined in ways to allow for over 2000 CPorts within a single device. As a result, a device id is represented with one byte, and a CPort Id within a device is always representable with a two byte value. This patch changes integral values that reresent CPort Ids so they use type u16 consistently. Separately, the contents of the gmod_cport structure were mostly fabricated, with the cport_id field being the only one that's meaningful. This patch gets rid of that structure, putting a simple u16 to represent the CPort Id everywhere it had been used before. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 3cc54ed..f8ba49c 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -160,8 +160,6 @@ static void greybus_module_release(struct device *dev) for (i = 0; i < gmod->num_strings; ++i) kfree(gmod->string[i]); - for (i = 0; i < gmod->num_cports; ++i) - kfree(gmod->cport[i]); kfree(gmod); } @@ -298,8 +296,6 @@ static int create_cport(struct greybus_module *gmod, struct greybus_descriptor_cport *cport, size_t desc_size) { - struct gmod_cport *gmod_cport; - if (gmod->num_cports == MAX_CPORTS_PER_MODULE) { dev_err(gmod->dev.parent, "too many cports for this module!\n"); return -EINVAL; @@ -311,15 +307,7 @@ static int create_cport(struct greybus_module *gmod, return -EINVAL; } - gmod_cport = kzalloc(sizeof(*gmod_cport), GFP_KERNEL); - if (!gmod_cport) - return -ENOMEM; - - gmod_cport->id = le16_to_cpu(cport->id); - gmod_cport->size = le16_to_cpu(cport->size); - gmod_cport->speed = cport->speed; - - gmod->cport[gmod->num_cports] = gmod_cport; + gmod->cport_ids[gmod->num_cports] = le16_to_cpu(cport->id); gmod->num_cports++; return 0; diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 8df1643..410acd3 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -11,8 +11,10 @@ #include #include #include + #include "greybus.h" #include "svc_msg.h" +#include "kernel_ver.h" /* Memory sizes for the buffers sent to/from the ES1 controller */ #define ES1_SVC_MSG_SIZE (sizeof(struct svc_msg) + SZ_64K) @@ -114,7 +116,8 @@ static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask) * we will encode the cport number in the first byte of the buffer, so * set the second byte to be the "transfer buffer" */ - buffer[0] = gbuf->cport->id; + BUG_ON(gbuf->cport_id > (u16)U8_MAX); + buffer[0] = gbuf->cport_id; gbuf->transfer_buffer = &buffer[1]; gbuf->transfer_buffer_length = size; gbuf->actual_length = size; diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 94c2d6a..7b4a72a 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -27,7 +27,7 @@ static struct kmem_cache *gbuf_head_cache; static struct workqueue_struct *gbuf_workqueue; static struct gbuf *__alloc_gbuf(struct greybus_module *gmod, - struct gmod_cport *cport, + u16 cport_id, gbuf_complete_t complete, gfp_t gfp_mask, void *context) @@ -40,7 +40,7 @@ static struct gbuf *__alloc_gbuf(struct greybus_module *gmod, kref_init(&gbuf->kref); gbuf->gmod = gmod; - gbuf->cport = cport; + gbuf->cport_id = cport_id; INIT_WORK(&gbuf->event, cport_process_event); gbuf->complete = complete; gbuf->context = context; @@ -64,7 +64,7 @@ static struct gbuf *__alloc_gbuf(struct greybus_module *gmod, * hardware designers for this issue... */ struct gbuf *greybus_alloc_gbuf(struct greybus_module *gmod, - struct gmod_cport *cport, + u16 cport_id, gbuf_complete_t complete, unsigned int size, gfp_t gfp_mask, @@ -73,7 +73,7 @@ struct gbuf *greybus_alloc_gbuf(struct greybus_module *gmod, struct gbuf *gbuf; int retval; - gbuf = __alloc_gbuf(gmod, cport, complete, gfp_mask, context); + gbuf = __alloc_gbuf(gmod, cport_id, complete, gfp_mask, context); if (!gbuf) return NULL; @@ -146,7 +146,7 @@ static void cport_process_event(struct work_struct *work) #define MAX_CPORTS 1024 struct gb_cport_handler { gbuf_complete_t handler; - struct gmod_cport cport; + u16 cport_id; struct greybus_module *gmod; void *context; }; @@ -156,25 +156,25 @@ static struct gb_cport_handler cport_handler[MAX_CPORTS]; // need it, we don't have a dynamic system... int gb_register_cport_complete(struct greybus_module *gmod, - gbuf_complete_t handler, int cport_id, + gbuf_complete_t handler, u16 cport_id, void *context) { if (cport_handler[cport_id].handler) return -EINVAL; cport_handler[cport_id].context = context; cport_handler[cport_id].gmod = gmod; - cport_handler[cport_id].cport.id = cport_id; + cport_handler[cport_id].cport_id = cport_id; cport_handler[cport_id].handler = handler; return 0; } -void gb_deregister_cport_complete(int cport_id) +void gb_deregister_cport_complete(u16 cport_id) { cport_handler[cport_id].handler = NULL; } -void greybus_cport_in(struct greybus_host_device *hd, int cport_id, u8 *data, - size_t length) +void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, + u8 *data, size_t length) { struct gb_cport_handler *ch; struct gbuf *gbuf; @@ -189,7 +189,7 @@ void greybus_cport_in(struct greybus_host_device *hd, int cport_id, u8 *data, return; } - gbuf = __alloc_gbuf(ch->gmod, &ch->cport, ch->handler, GFP_ATOMIC, + gbuf = __alloc_gbuf(ch->gmod, ch->cport_id, ch->handler, GFP_ATOMIC, ch->context); if (!gbuf) { /* Again, something bad went wrong, log it... */ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 1328dc9..4ca11f2 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -101,13 +101,6 @@ struct gbuf; -struct gmod_cport { - u16 id; - u16 size; - u8 speed; // valid??? - // FIXME, what else? -}; - struct gmod_string { u16 length; u8 id; @@ -121,7 +114,7 @@ struct gbuf { void *hdpriv; struct greybus_module *gmod; - struct gmod_cport *cport; + u16 cport_id; int status; void *transfer_buffer; u32 transfer_flags; /* flags for the transfer buffer */ @@ -187,8 +180,8 @@ struct greybus_host_device { struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *host_driver, struct device *parent); void greybus_remove_hd(struct greybus_host_device *hd); -void greybus_cport_in(struct greybus_host_device *hd, int cport_id, u8 *data, - size_t length); +void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, + u8 *data, size_t length); void greybus_gbuf_finished(struct gbuf *gbuf); @@ -203,7 +196,7 @@ struct greybus_module { struct greybus_descriptor_module module; int num_cports; int num_strings; - struct gmod_cport *cport[MAX_CPORTS_PER_MODULE]; + u16 cport_ids[MAX_CPORTS_PER_MODULE]; struct gmod_string *string[MAX_STRINGS_PER_MODULE]; struct greybus_host_device *hd; @@ -218,7 +211,7 @@ struct greybus_module { #define to_greybus_module(d) container_of(d, struct greybus_module, dev) struct gbuf *greybus_alloc_gbuf(struct greybus_module *gmod, - struct gmod_cport *cport, + u16 cport_id, gbuf_complete_t complete, unsigned int size, gfp_t gfp_mask, @@ -298,9 +291,9 @@ int gb_gbuf_init(void); void gb_gbuf_exit(void); int gb_register_cport_complete(struct greybus_module *gmod, - gbuf_complete_t handler, int cport_id, + gbuf_complete_t handler, u16 cport_id, void *context); -void gb_deregister_cport_complete(int cport_id); +void gb_deregister_cport_complete(u16 cport_id); extern const struct attribute_group *greybus_module_groups[]; diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index 40cc2e8..4aa5b83 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -18,5 +18,8 @@ struct device_attribute dev_attr_##_name = __ATTR_RO(_name) #endif +#ifndef U8_MAX +#define U8_MAX ((u8)~0U) +#endif /* ! U8_MAX */ #endif /* __GREYBUS_KERNEL_VER_H */ diff --git a/drivers/staging/greybus/svc_msg.h b/drivers/staging/greybus/svc_msg.h index 4b69604..986368d 100644 --- a/drivers/staging/greybus/svc_msg.h +++ b/drivers/staging/greybus/svc_msg.h @@ -49,9 +49,9 @@ struct svc_function_handshake { struct svc_function_unipro_set_route { __u8 source_module_id; - __u8 source_cport_id; + __u8 source_cport_id; /* bottom 8 bits */ __u8 destination_module_id; - __u8 destination_cport_id; + __u8 destination_cport_id; /* bottom 8 bits */ }; struct svc_function_unipro_link_up { diff --git a/drivers/staging/greybus/test_sink.c b/drivers/staging/greybus/test_sink.c index 8b254e3..811a237 100644 --- a/drivers/staging/greybus/test_sink.c +++ b/drivers/staging/greybus/test_sink.c @@ -16,9 +16,9 @@ struct test_device { }; int gb_register_cport_complete(struct greybus_module *gmod, - gbuf_complete_t handler, int cport_id, + gbuf_complete_t handler, u16 cport_id, void *context); -void gb_deregister_cport_complete(int cport_id); +void gb_deregister_cport_complete(u16 cport_id); diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 7735a04..7f9d498 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -34,7 +34,7 @@ struct gb_tty { struct tty_port port; struct greybus_module *gmod; - int cport_id; + u16 cport_id; unsigned int minor; unsigned char clocal; unsigned int throttled:1; -- cgit v0.10.2 From a6cdb3492e845dd1c784d35e0cfec0c6ac66aaef Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 30 Sep 2014 18:21:36 -0700 Subject: greybus: es1: no BUG_ON() code, report an error and recover. diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 410acd3..f23c674 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -116,7 +116,13 @@ static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask) * we will encode the cport number in the first byte of the buffer, so * set the second byte to be the "transfer buffer" */ - BUG_ON(gbuf->cport_id > (u16)U8_MAX); + if (gbuf->cport_id > (u16)U8_MAX) { + pr_err("gbuf->cport_id is '%d' and is out of range!\n", + gbuf->cport_id); + kfree(buffer); + return -EINVAL; + } + buffer[0] = gbuf->cport_id; gbuf->transfer_buffer = &buffer[1]; gbuf->transfer_buffer_length = size; -- cgit v0.10.2 From 9c852d2b8feee2d559032363980b6372182cbe34 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 30 Sep 2014 19:25:22 -0500 Subject: greybus: clarify device vs module The Project ARA MDK states that a single module can have more than one interface block (up to 2 at the moment). An interface block consists of two bidirectional UniPro lanes (along with power and detect lines), and effectively represents a UniPro Device (with an id in the range 0-127). The service messages currently use "module_id" everywhere, even though in a lot of cases we really need to be talking about device ids. The easiest case of this to see is the "set route" request directed at a switch; a switch has no notion of modules, just UniPro devices. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc_msg.h b/drivers/staging/greybus/svc_msg.h index 986368d..1f8b4f1 100644 --- a/drivers/staging/greybus/svc_msg.h +++ b/drivers/staging/greybus/svc_msg.h @@ -48,14 +48,14 @@ struct svc_function_handshake { }; struct svc_function_unipro_set_route { - __u8 source_module_id; + __u8 source_device_id; __u8 source_cport_id; /* bottom 8 bits */ - __u8 destination_module_id; + __u8 destination_device_id; __u8 destination_cport_id; /* bottom 8 bits */ }; struct svc_function_unipro_link_up { - __u8 module_id; + __u8 device_id; }; enum svc_function_management_event { @@ -76,6 +76,11 @@ enum svc_function_hotplug_event { SVC_HOTUNPLUG_EVENT = 0x01, }; +/* XXX + * Does a hotplug come from module insertion, or from detection + * of each interface block (UniPro device) in a module? Assume + * the former for now. + */ struct svc_function_hotplug { __u8 hotplug_event; /* enum svc_function_hotplug_event */ __u8 module_id; @@ -87,6 +92,12 @@ enum svc_function_ddb_type { SVC_DDB_RESPONSE = 0x01, }; +/* XXX + * Will only the first interface block in a module be responsible + * for this? If a module has two interface blocks, will both supply + * the same information, or will it be partitioned? For now assume + * it's a per-module thing. + */ struct svc_function_ddb_get { __u8 module_id; __u8 message_id; @@ -129,6 +140,11 @@ struct svc_function_power_battery_status { struct svc_function_power_battery_status_request { }; +/* XXX + * Each interface block carries power, so it's possible these things + * are associated with each UniPro device and not just the module. + * For now it's safe to assume it's per-module. + */ struct svc_function_power { __u8 power_type; /* enum svc_function_power_type */ __u8 module_id; @@ -143,6 +159,7 @@ enum svc_function_epm_command_type { SVC_EPM_DISABLE = 0x01, }; +/* EPM's are associated with the module */ struct svc_function_epm { __u8 epm_command_type; /* enum svc_function_epm_command_type */ __u8 module_id; @@ -153,9 +170,10 @@ enum svc_function_suspend_command_type { SVC_SUSPEND_FIXME_2 = 0x01, }; +/* We'll want independent control for multi-interface block modules */ struct svc_function_suspend { __u8 suspend_command_type; /* enum function_suspend_command_type */ - __u8 module_id; + __u8 device_id; }; struct svc_msg { -- cgit v0.10.2 From 7a57479b1d6727a3635833d75396650a1914fa7e Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Wed, 1 Oct 2014 15:09:00 -0400 Subject: greybus: remove additional unused fields from the cport descriptor The Greybus spec was updated to remove some unused fields from the CPort descriptor definition. Remove them from the structure so we don't fail manifest parsing. Signed-off-by: Matt Porter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 0867054..4d801d7 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -73,9 +73,6 @@ struct greybus_descriptor_string { struct greybus_descriptor_cport { __le16 id; - __le16 size; - __u8 speed; // FIXME - __u8 reserved; }; struct greybus_descriptor { -- cgit v0.10.2 From 513c54cb0566dc8aa74b4e3c603a35ee9f8e07ae Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Wed, 1 Oct 2014 15:09:01 -0400 Subject: greybus: fix error message on parse of cport descriptor size Fix a simple cut and paste error that was reporting a serial number header size error rather than a cport descriptor size error. Signed-off-by: Matt Porter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index f8ba49c..c065beb 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -303,7 +303,7 @@ static int create_cport(struct greybus_module *gmod, if (desc_size != sizeof(*cport)) { dev_err(gmod->dev.parent, - "invalid serial number header size %zu\n", desc_size); + "invalid cport descriptor size %zu\n", desc_size); return -EINVAL; } -- cgit v0.10.2 From ecf7d579713155e7d2e2aa76227c68c4f64c5146 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 1 Oct 2014 21:54:10 -0500 Subject: greybus: descriptor type updates Some more updates to the definition of a manifest descriptor. - We get rid of function descriptors. The type of function is easily specified with the CPort it uses. - Add a new interface descriptor type. - Clean up the CPort descriptor structure, eliminating fields that serve no purpose and adding the function id field The sysfs stuff will be updated a little later to add entries for the Greybus interfaces associated with modules. Rearrange the order of a few things in "greybus_manifest.h". Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index c065beb..e93ee40 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -232,19 +232,6 @@ static const struct greybus_module_id fake_gb_id = { GREYBUS_DEVICE(0x42, 0x42) }; -static int create_function(struct greybus_module *gmod, - struct greybus_descriptor_function *function, - size_t desc_size) -{ - if (desc_size != sizeof(*function)) { - dev_err(gmod->dev.parent, "invalid function header size %zu\n", - desc_size); - return -EINVAL; - } - memcpy(&gmod->function, function, desc_size); - return 0; -} - static int create_module(struct greybus_module *gmod, struct greybus_descriptor_module *module, size_t desc_size) @@ -385,9 +372,7 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, data_size = (size_t)desc_size - sizeof(desc->header); switch (le16_to_cpu(desc->header.type)) { - case GREYBUS_TYPE_FUNCTION: - retval = create_function(gmod, &desc->function, - data_size); + case GREYBUS_TYPE_DEVICE: break; case GREYBUS_TYPE_MODULE: diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 4ca11f2..c8bd8eb 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -192,7 +192,6 @@ void greybus_gbuf_finished(struct gbuf *gbuf); struct greybus_module { struct device dev; u16 module_number; - struct greybus_descriptor_function function; struct greybus_descriptor_module module; int num_cports; int num_strings; @@ -210,12 +209,9 @@ struct greybus_module { }; #define to_greybus_module(d) container_of(d, struct greybus_module, dev) -struct gbuf *greybus_alloc_gbuf(struct greybus_module *gmod, - u16 cport_id, - gbuf_complete_t complete, - unsigned int size, - gfp_t gfp_mask, - void *context); +struct gbuf *greybus_alloc_gbuf(struct greybus_module *gmod, u16 cport_id, + gbuf_complete_t complete, unsigned int size, + gfp_t gfp_mask, void *context); void greybus_free_gbuf(struct gbuf *gbuf); struct gbuf *greybus_get_gbuf(struct gbuf *gbuf); #define greybus_put_gbuf greybus_free_gbuf diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 4d801d7..6118999 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -14,26 +14,15 @@ #pragma pack(push, 1) -struct greybus_manifest_header { - __le16 size; - __u8 version_major; - __u8 version_minor; -}; - enum greybus_descriptor_type { GREYBUS_TYPE_INVALID = 0x00, GREYBUS_TYPE_MODULE = 0x01, - GREYBUS_TYPE_FUNCTION = 0x02, + GREYBUS_TYPE_DEVICE = 0x02, GREYBUS_TYPE_CLASS = 0x03, GREYBUS_TYPE_STRING = 0x04, GREYBUS_TYPE_CPORT = 0x05, }; -struct greybus_descriptor_header { - __le16 size; - __u8 type; /* enum greybus_descriptor_type */ -}; - enum greybus_function_type { GREYBUS_FUNCTION_CONTROL = 0x00, GREYBUS_FUNCTION_USB = 0x01, @@ -51,11 +40,10 @@ enum greybus_function_type { GREYBUS_FUNCTION_VENDOR = 0xff, }; -struct greybus_descriptor_function { - __le16 cport; - __u8 function_type; /* enum greybus_function_type */ -}; - +/* + * A module descriptor describes information about a module as a + * whole, *not* the functions within it. + */ struct greybus_descriptor_module { __le16 vendor; __le16 product; @@ -65,26 +53,61 @@ struct greybus_descriptor_module { __u8 product_stringid; }; +/* + * A UniPro device normally supports a range of 32 CPorts (0..31). + * It is possible to support more than this by having a UniPro + * switch treat one device as if it were more than one. E.g., + * allocate 3 device ids (rather than the normal--1) to physical + * device 5, and configure the switch to route all packets destined + * for "encoded" device ids 5, 6, and 7 to physical device 5. + * Device 5 uses the encoded device id in incoming UniPro packets to + * determine which bank of 32 CPorts should receive the UniPro + * segment. + * + * The "scale" field in this structure is used to define the number + * of encoded device ids should be allocated for this physical + * device. Scale is normally 1, to represent 32 available CPorts. + * A scale value 2 represents up to 64 CPorts; scale value 3 + * represents up to 96 CPorts, and so on. + */ +struct greybus_descriptor_interface { + __u8 id; /* module-relative id (0..) */ + __u8 scale; /* indicates range of of CPorts supported */ + /* UniPro gear, number of in/out lanes */ +}; + +struct greybus_descriptor_cport { + __le16 id; + __u8 function_type; /* enum greybus_function_type */ +}; + struct greybus_descriptor_string { __u8 length; __u8 id; __u8 string[0]; }; -struct greybus_descriptor_cport { - __le16 id; +struct greybus_descriptor_header { + __le16 size; + __u8 type; /* enum greybus_descriptor_type */ }; struct greybus_descriptor { struct greybus_descriptor_header header; union { - struct greybus_descriptor_function function; struct greybus_descriptor_module module; struct greybus_descriptor_string string; + struct greybus_descriptor_interface interface; struct greybus_descriptor_cport cport; }; }; +struct greybus_manifest_header { + __le16 size; + __u8 version_major; + __u8 version_minor; +}; + struct greybus_manifest { struct greybus_manifest_header header; struct greybus_descriptor descriptors[0]; diff --git a/drivers/staging/greybus/sysfs.c b/drivers/staging/greybus/sysfs.c index 1f17388..a2dce7a 100644 --- a/drivers/staging/greybus/sysfs.c +++ b/drivers/staging/greybus/sysfs.c @@ -20,44 +20,6 @@ #include "kernel_ver.h" -/* Function fields */ -#define greybus_function_attr(field) \ -static ssize_t function_##field##_show(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct greybus_module *gmod = to_greybus_module(dev); \ - return sprintf(buf, "%d\n", gmod->function.field); \ -} \ -static DEVICE_ATTR_RO(function_##field) - -greybus_function_attr(cport); -greybus_function_attr(function_type); - -static struct attribute *function_attrs[] = { - &dev_attr_function_cport.attr, - &dev_attr_function_function_type.attr, - NULL, -}; - -static umode_t function_attrs_are_visible(struct kobject *kobj, - struct attribute *a, int n) -{ - struct greybus_module *gmod = to_greybus_module(kobj_to_dev(kobj)); - - // FIXME - make this a dynamic structure to "know" if it really is here - // or not easier? - if (gmod->function.cport || - gmod->function.function_type) - return a->mode; - return 0; -} - -static struct attribute_group function_attr_grp = { - .attrs = function_attrs, - .is_visible = function_attrs_are_visible, -}; - /* Module fields */ #define greybus_module_attr(field) \ static ssize_t module_##field##_show(struct device *dev, \ @@ -147,7 +109,6 @@ static struct attribute_group module_attr_grp = { const struct attribute_group *greybus_module_groups[] = { - &function_attr_grp, &module_attr_grp, NULL, }; -- cgit v0.10.2 From e1e9dbddfe71de1efba5bc77b3f2b374e2ba0104 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 1 Oct 2014 21:54:11 -0500 Subject: greybus: isolate greybus module code Define new source files "module.h" and "module.c" to separate the definitions of the Greybus module abstraction from other code. Rename "greybus_module" to be "gb_module", for brevity. Do the same for a few other symbols with "greybus_module" in their names. A few (like greybus_module_id) are more visible outside this kernel module so we'll keep their names more descriptive. Add a definition for U8_MAX in "kernel_ver.h" (it appeared in 3.14). Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 2e048a01..9b5d8e9 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -3,6 +3,7 @@ greybus-y := core.o \ sysfs.o \ debugfs.o \ ap.o \ + module.o \ i2c-gb.o \ gpio-gb.o \ sdio-gb.o \ diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index 5f1bf00..1ef2f17 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -18,7 +18,7 @@ struct gb_battery { // we will want to keep the battery stats in here as we will be getting // updates from the SVC "on the fly" so we don't have to always go ask // the battery for some information. Hopefully... - struct greybus_module *gmod; + struct gb_module *gmod; }; #define to_gb_battery(x) container_of(x, struct gb_battery, bat) @@ -100,7 +100,7 @@ static enum power_supply_property battery_props[] = { POWER_SUPPLY_PROP_VOLTAGE_NOW, }; -int gb_battery_probe(struct greybus_module *gmod, +int gb_battery_probe(struct gb_module *gmod, const struct greybus_module_id *id) { struct gb_battery *gb; @@ -130,7 +130,7 @@ int gb_battery_probe(struct greybus_module *gmod, return 0; } -void gb_battery_disconnect(struct greybus_module *gmod) +void gb_battery_disconnect(struct gb_module *gmod) { struct gb_battery *gb; diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index e93ee40..934bdeb 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -30,51 +30,13 @@ int greybus_disabled(void) } EXPORT_SYMBOL_GPL(greybus_disabled); -static int greybus_match_one_id(struct greybus_module *gmod, - const struct greybus_module_id *id) -{ - struct greybus_descriptor_module *module; - - module = &gmod->module; - - if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_VENDOR) && - (id->vendor != le16_to_cpu(module->vendor))) - return 0; - - if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_PRODUCT) && - (id->product != le16_to_cpu(module->product))) - return 0; - - if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_SERIAL) && - (id->serial_number != le64_to_cpu(module->serial_number))) - return 0; - - return 1; -} - -static const struct greybus_module_id *greybus_match_id( - struct greybus_module *gmod, - const struct greybus_module_id *id) -{ - if (id == NULL) - return NULL; - - for (; id->vendor || id->product || id->serial_number || - id->driver_info ; id++) { - if (greybus_match_one_id(gmod, id)) - return id; - } - - return NULL; -} - static int greybus_module_match(struct device *dev, struct device_driver *drv) { struct greybus_driver *driver = to_greybus_driver(dev->driver); - struct greybus_module *gmod = to_greybus_module(dev); + struct gb_module *gmod = to_gb_module(dev); const struct greybus_module_id *id; - id = greybus_match_id(gmod, driver->id_table); + id = gb_module_match_id(gmod, driver->id_table); if (id) return 1; /* FIXME - Dyanmic ids? */ @@ -83,7 +45,7 @@ static int greybus_module_match(struct device *dev, struct device_driver *drv) static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) { - /* struct greybus_module *gmod = to_greybus_module(dev); */ + /* struct gb_module *gmod = to_gb_module(dev); */ /* FIXME - add some uevents here... */ return 0; @@ -98,12 +60,12 @@ static struct bus_type greybus_bus_type = { static int greybus_probe(struct device *dev) { struct greybus_driver *driver = to_greybus_driver(dev->driver); - struct greybus_module *gmod = to_greybus_module(dev); + struct gb_module *gmod = to_gb_module(dev); const struct greybus_module_id *id; int retval; /* match id */ - id = greybus_match_id(gmod, driver->id_table); + id = gb_module_match_id(gmod, driver->id_table); if (!id) return -ENODEV; @@ -117,7 +79,7 @@ static int greybus_probe(struct device *dev) static int greybus_remove(struct device *dev) { struct greybus_driver *driver = to_greybus_driver(dev->driver); - struct greybus_module *gmod = to_greybus_module(dev); + struct gb_module *gmod = to_gb_module(dev); driver->disconnect(gmod); return 0; @@ -155,7 +117,7 @@ EXPORT_SYMBOL_GPL(greybus_deregister); static void greybus_module_release(struct device *dev) { - struct greybus_module *gmod = to_greybus_module(dev); + struct gb_module *gmod = to_gb_module(dev); int i; for (i = 0; i < gmod->num_strings; ++i) @@ -164,7 +126,7 @@ static void greybus_module_release(struct device *dev) } -const u8 *greybus_string(struct greybus_module *gmod, int id) +const u8 *greybus_string(struct gb_module *gmod, int id) { int i; struct gmod_string *string; @@ -185,7 +147,7 @@ static struct device_type greybus_module_type = { .release = greybus_module_release, }; -static int gb_init_subdevs(struct greybus_module *gmod, +static int gb_init_subdevs(struct gb_module *gmod, const struct greybus_module_id *id) { int retval; @@ -228,11 +190,11 @@ error_i2c: return retval; } -static const struct greybus_module_id fake_gb_id = { +static const struct greybus_module_id fake_greybus_module_id = { GREYBUS_DEVICE(0x42, 0x42) }; -static int create_module(struct greybus_module *gmod, +static int create_module(struct gb_module *gmod, struct greybus_descriptor_module *module, size_t desc_size) { @@ -245,7 +207,7 @@ static int create_module(struct greybus_module *gmod, return 0; } -static int create_string(struct greybus_module *gmod, +static int create_string(struct gb_module *gmod, struct greybus_descriptor_string *string, size_t desc_size) { @@ -279,7 +241,7 @@ static int create_string(struct greybus_module *gmod, return 0; } -static int create_cport(struct greybus_module *gmod, +static int create_cport(struct gb_module *gmod, struct greybus_descriptor_cport *cport, size_t desc_size) { @@ -309,7 +271,7 @@ static int create_cport(struct greybus_module *gmod, void gb_add_module(struct greybus_host_device *hd, u8 module_id, u8 *data, int size) { - struct greybus_module *gmod; + struct gb_module *gmod; struct greybus_manifest *manifest; int retval; int overall_size; @@ -318,11 +280,10 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, if (size <= sizeof(manifest->header)) return; - gmod = kzalloc(sizeof(*gmod), GFP_KERNEL); + gmod = gb_module_create(hd, module_id); if (!gmod) return; - gmod->module_number = module_id; gmod->dev.parent = hd->parent; gmod->dev.driver = NULL; gmod->dev.bus = &greybus_bus_type; @@ -400,7 +361,7 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, data += desc_size; } - retval = gb_init_subdevs(gmod, &fake_gb_id); + retval = gb_init_subdevs(gmod, &fake_greybus_module_id); if (retval) goto error; @@ -418,7 +379,7 @@ void gb_remove_module(struct greybus_host_device *hd, u8 module_id) // FIXME should be the remove_device call... } -void greybus_remove_device(struct greybus_module *gmod) +void greybus_remove_device(struct gb_module *gmod) { /* tear down all of the "sub device types" for this device */ gb_i2c_disconnect(gmod); @@ -453,6 +414,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver kref_init(&hd->kref); hd->parent = parent; hd->driver = driver; + INIT_LIST_HEAD(&hd->modules); return hd; } diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 7b4a72a..fada121 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -26,7 +26,7 @@ static struct kmem_cache *gbuf_head_cache; /* Workqueue to handle Greybus buffer completions. */ static struct workqueue_struct *gbuf_workqueue; -static struct gbuf *__alloc_gbuf(struct greybus_module *gmod, +static struct gbuf *__alloc_gbuf(struct gb_module *gmod, u16 cport_id, gbuf_complete_t complete, gfp_t gfp_mask, @@ -63,7 +63,7 @@ static struct gbuf *__alloc_gbuf(struct greybus_module *gmod, * that the driver can then fill up with the data to be sent out. Curse * hardware designers for this issue... */ -struct gbuf *greybus_alloc_gbuf(struct greybus_module *gmod, +struct gbuf *greybus_alloc_gbuf(struct gb_module *gmod, u16 cport_id, gbuf_complete_t complete, unsigned int size, @@ -80,7 +80,7 @@ struct gbuf *greybus_alloc_gbuf(struct greybus_module *gmod, gbuf->direction = GBUF_DIRECTION_OUT; /* Host controller specific allocation for the actual buffer */ - retval = gbuf->gmod->hd->driver->alloc_gbuf_data(gbuf, size, gfp_mask); + retval = gmod->hd->driver->alloc_gbuf_data(gbuf, size, gfp_mask); if (retval) { greybus_free_gbuf(gbuf); return NULL; @@ -147,7 +147,7 @@ static void cport_process_event(struct work_struct *work) struct gb_cport_handler { gbuf_complete_t handler; u16 cport_id; - struct greybus_module *gmod; + struct gb_module *gmod; void *context; }; @@ -155,8 +155,9 @@ static struct gb_cport_handler cport_handler[MAX_CPORTS]; // FIXME - use a lock for this list of handlers, but really, for now we don't // need it, we don't have a dynamic system... -int gb_register_cport_complete(struct greybus_module *gmod, - gbuf_complete_t handler, u16 cport_id, +int gb_register_cport_complete(struct gb_module *gmod, + gbuf_complete_t handler, + u16 cport_id, void *context) { if (cport_handler[cport_id].handler) diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index 4b71866..2369175 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -14,7 +14,7 @@ struct gb_gpio_device { struct gpio_chip chip; - struct greybus_module *gmod; + struct gb_module *gmod; struct gpio_chip *gpio; // FIXME - some lock? }; @@ -49,7 +49,7 @@ static void gpio_set(struct gpio_chip *gpio, unsigned nr, int val) // FIXME - do something there } -int gb_gpio_probe(struct greybus_module *gmod, +int gb_gpio_probe(struct gb_module *gmod, const struct greybus_module_id *id) { struct gb_gpio_device *gb_gpio; @@ -86,7 +86,7 @@ int gb_gpio_probe(struct greybus_module *gmod, return 0; } -void gb_gpio_disconnect(struct greybus_module *gmod) +void gb_gpio_disconnect(struct gb_module *gmod) { struct gb_gpio_device *gb_gpio_dev; int retval; diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index c8bd8eb..a4fad87 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -11,12 +11,16 @@ #ifdef __KERNEL__ +#include #include #include +#include #include #include + #include "greybus_id.h" #include "greybus_manifest.h" +#include "module.h" /* Matches up with the Greybus Protocol specification document */ @@ -113,7 +117,7 @@ struct gbuf { struct kref kref; void *hdpriv; - struct greybus_module *gmod; + struct gb_module *gmod; u16 cport_id; int status; void *transfer_buffer; @@ -142,7 +146,7 @@ struct gbuf { * same module as the gpio pins, etc.) * * So, put the "private" data structures here in greybus.h and link to them off - * of the "main" greybus_module structure. + * of the "main" gb_module structure. */ struct gb_i2c_device; @@ -173,6 +177,8 @@ struct greybus_host_device { struct device *parent; const struct greybus_host_driver *driver; + struct list_head modules; + /* Private data for the host driver */ unsigned long hd_priv[0] __attribute__ ((aligned(sizeof(s64)))); }; @@ -184,32 +190,7 @@ void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, u8 *data, size_t length); void greybus_gbuf_finished(struct gbuf *gbuf); - -/* Increase these values if needed */ -#define MAX_CPORTS_PER_MODULE 10 -#define MAX_STRINGS_PER_MODULE 10 - -struct greybus_module { - struct device dev; - u16 module_number; - struct greybus_descriptor_module module; - int num_cports; - int num_strings; - u16 cport_ids[MAX_CPORTS_PER_MODULE]; - struct gmod_string *string[MAX_STRINGS_PER_MODULE]; - - struct greybus_host_device *hd; - - struct gb_i2c_device *gb_i2c_dev; - struct gb_gpio_device *gb_gpio_dev; - struct gb_sdio_host *gb_sdio_host; - struct gb_tty *gb_tty; - struct gb_usb_device *gb_usb_dev; - struct gb_battery *gb_battery; -}; -#define to_greybus_module(d) container_of(d, struct greybus_module, dev) - -struct gbuf *greybus_alloc_gbuf(struct greybus_module *gmod, u16 cport_id, +struct gbuf *greybus_alloc_gbuf(struct gb_module *gmod, u16 cport_id, gbuf_complete_t complete, unsigned int size, gfp_t gfp_mask, void *context); void greybus_free_gbuf(struct gbuf *gbuf); @@ -223,12 +204,12 @@ int greybus_kill_gbuf(struct gbuf *gbuf); struct greybus_driver { const char *name; - int (*probe)(struct greybus_module *gmod, + int (*probe)(struct gb_module *gmod, const struct greybus_module_id *id); - void (*disconnect)(struct greybus_module *gmod); + void (*disconnect)(struct gb_module *gmod); - int (*suspend)(struct greybus_module *gmod, pm_message_t message); - int (*resume)(struct greybus_module *gmod); + int (*suspend)(struct gb_module *gmod, pm_message_t message); + int (*resume)(struct gb_module *gmod); const struct greybus_module_id *id_table; @@ -236,16 +217,6 @@ struct greybus_driver { }; #define to_greybus_driver(d) container_of(d, struct greybus_driver, driver) -static inline void greybus_set_drvdata(struct greybus_module *gmod, void *data) -{ - dev_set_drvdata(&gmod->dev, data); -} - -static inline void *greybus_get_drvdata(struct greybus_module *gmod) -{ - return dev_get_drvdata(&gmod->dev); -} - /* Don't call these directly, use the module_greybus_driver() macro instead */ int greybus_register_driver(struct greybus_driver *driver, struct module *module, const char *mod_name); @@ -268,9 +239,9 @@ void greybus_deregister(struct greybus_driver *driver); int greybus_disabled(void); -void greybus_remove_device(struct greybus_module *gmod); +void greybus_remove_device(struct gb_module *gmod); -const u8 *greybus_string(struct greybus_module *gmod, int id); +const u8 *greybus_string(struct gb_module *gmod, int id); /* Internal functions to gb module, move to internal .h file eventually. */ @@ -286,7 +257,7 @@ void gb_debugfs_cleanup(void); int gb_gbuf_init(void); void gb_gbuf_exit(void); -int gb_register_cport_complete(struct greybus_module *gmod, +int gb_register_cport_complete(struct gb_module *gmod, gbuf_complete_t handler, u16 cport_id, void *context); void gb_deregister_cport_complete(u16 cport_id); @@ -298,16 +269,17 @@ extern const struct attribute_group *greybus_module_groups[]; * we have static functions for this, not "dynamic" drivers like we really * should in the end. */ -int gb_i2c_probe(struct greybus_module *gmod, const struct greybus_module_id *id); -void gb_i2c_disconnect(struct greybus_module *gmod); -int gb_gpio_probe(struct greybus_module *gmod, const struct greybus_module_id *id); -void gb_gpio_disconnect(struct greybus_module *gmod); -int gb_sdio_probe(struct greybus_module *gmod, const struct greybus_module_id *id); -void gb_sdio_disconnect(struct greybus_module *gmod); -int gb_tty_probe(struct greybus_module *gmod, const struct greybus_module_id *id); -void gb_tty_disconnect(struct greybus_module *gmod); -int gb_battery_probe(struct greybus_module *gmod, const struct greybus_module_id *id); -void gb_battery_disconnect(struct greybus_module *gmod); +int gb_i2c_probe(struct gb_module *gmod, const struct greybus_module_id *id); +void gb_i2c_disconnect(struct gb_module *gmod); +int gb_gpio_probe(struct gb_module *gmod, const struct greybus_module_id *id); +void gb_gpio_disconnect(struct gb_module *gmod); +int gb_sdio_probe(struct gb_module *gmod, const struct greybus_module_id *id); +void gb_sdio_disconnect(struct gb_module *gmod); +int gb_tty_probe(struct gb_module *gmod, const struct greybus_module_id *id); +void gb_tty_disconnect(struct gb_module *gmod); +int gb_battery_probe(struct gb_module *gmod, + const struct greybus_module_id *id); +void gb_battery_disconnect(struct gb_module *gmod); int gb_tty_init(void); void gb_tty_exit(void); diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index bd03f19..c01f41b 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -10,11 +10,12 @@ #include #include #include + #include "greybus.h" struct gb_i2c_device { struct i2c_adapter *adapter; - struct greybus_module *gmod; + struct gb_module *gmod; }; static const struct greybus_module_id id_table[] = { @@ -33,7 +34,7 @@ static s32 i2c_gb_access(struct i2c_adapter *adap, u16 addr, int size, union i2c_smbus_data *data) { struct gb_i2c_device *gb_i2c_dev; - struct greybus_module *gmod; + struct gb_module *gmod; gb_i2c_dev = i2c_get_adapdata(adap); gmod = gb_i2c_dev->gmod; @@ -75,7 +76,7 @@ static const struct i2c_algorithm smbus_algorithm = { .functionality = i2c_gb_func, }; -int gb_i2c_probe(struct greybus_module *gmod, +int gb_i2c_probe(struct gb_module *gmod, const struct greybus_module_id *id) { struct gb_i2c_device *gb_i2c_dev; @@ -115,7 +116,7 @@ error: return retval; } -void gb_i2c_disconnect(struct greybus_module *gmod) +void gb_i2c_disconnect(struct gb_module *gmod) { struct gb_i2c_device *gb_i2c_dev; diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c new file mode 100644 index 0000000..31017c2 --- /dev/null +++ b/drivers/staging/greybus/module.c @@ -0,0 +1,93 @@ +/* + * Greybus modules + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ + +#include "greybus.h" + +/* XXX This could be per-host device */ +static DEFINE_SPINLOCK(gb_modules_lock); + +static int gb_module_match_one_id(struct gb_module *gmod, + const struct greybus_module_id *id) +{ + struct greybus_descriptor_module *module; + + module = &gmod->module; + + if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_VENDOR) && + (id->vendor != le16_to_cpu(module->vendor))) + return 0; + + if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_PRODUCT) && + (id->product != le16_to_cpu(module->product))) + return 0; + + if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_SERIAL) && + (id->serial_number != le64_to_cpu(module->serial_number))) + return 0; + + return 1; +} + +const struct greybus_module_id *gb_module_match_id(struct gb_module *gmod, + const struct greybus_module_id *id) +{ + if (id == NULL) + return NULL; + + for (; id->vendor || id->product || id->serial_number || + id->driver_info; id++) { + if (gb_module_match_one_id(gmod, id)) + return id; + } + + return NULL; +} + +/* + * A Greybus module represents a user-replacable component on an Ara + * phone. + * + * Create a gb_module structure to represent a discovered module. + * The position within the Endo is encoded in the "module_id" argument. + * Returns a pointer to the new module or a null pointer if a + * failure occurs due to memory exhaustion. + */ +struct gb_module *gb_module_create(struct greybus_host_device *hd, u8 module_id) +{ + struct gb_module *module; + + module = kzalloc(sizeof(*module), GFP_KERNEL); + if (!module) + return NULL; + + module->hd = hd; /* XXX refcount? */ + module->module_id = module_id; + + spin_lock_irq(&gb_modules_lock); + list_add_tail(&module->links, &hd->modules); + spin_unlock_irq(&gb_modules_lock); + + return module; +} + +/* + * Tear down a previously set up module. + */ +void gb_module_destroy(struct gb_module *module) +{ + if (WARN_ON(!module)) + return; + + spin_lock_irq(&gb_modules_lock); + list_del(&module->links); + spin_unlock_irq(&gb_modules_lock); + + /* kref_put(module->hd); */ + + kfree(module); +} diff --git a/drivers/staging/greybus/module.h b/drivers/staging/greybus/module.h new file mode 100644 index 0000000..0d0f19f --- /dev/null +++ b/drivers/staging/greybus/module.h @@ -0,0 +1,57 @@ +/* + * Greybus modules + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ + +#ifndef __MODULE_H +#define __MODULE_H + +/* Increase these values if needed */ +#define MAX_CPORTS_PER_MODULE 10 +#define MAX_STRINGS_PER_MODULE 10 + +struct gb_module { + struct device dev; + + struct list_head links; /* greybus_host_device->modules */ + u8 module_id; /* Physical location within the Endo */ + + struct greybus_descriptor_module module; + int num_cports; + int num_strings; + u16 cport_ids[MAX_CPORTS_PER_MODULE]; + struct gmod_string *string[MAX_STRINGS_PER_MODULE]; + + struct greybus_host_device *hd; + + struct gb_i2c_device *gb_i2c_dev; + struct gb_gpio_device *gb_gpio_dev; + struct gb_sdio_host *gb_sdio_host; + struct gb_tty *gb_tty; + struct gb_usb_device *gb_usb_dev; + struct gb_battery *gb_battery; +}; +#define to_gb_module(d) container_of(d, struct gb_module, dev) + +static inline void +gb_module_set_drvdata(struct gb_module *gmod, void *data) +{ + dev_set_drvdata(&gmod->dev, data); +} + +static inline void *gb_module_get_drvdata(struct gb_module *gmod) +{ + return dev_get_drvdata(&gmod->dev); +} + +const struct greybus_module_id *gb_module_match_id(struct gb_module *gmod, + const struct greybus_module_id *id); + +struct gb_module *gb_module_create(struct greybus_host_device *hd, + u8 module_id); +void gb_module_destroy(struct gb_module *module); + +#endif /* __MODULE_H */ diff --git a/drivers/staging/greybus/sdio-gb.c b/drivers/staging/greybus/sdio-gb.c index 3cf258a..f7e80ab 100644 --- a/drivers/staging/greybus/sdio-gb.c +++ b/drivers/staging/greybus/sdio-gb.c @@ -7,9 +7,9 @@ */ #include -#include #include #include + #include "greybus.h" struct gb_sdio_host { @@ -45,7 +45,7 @@ static const struct mmc_host_ops gb_sd_ops = { .get_ro = gb_sd_get_ro, }; -int gb_sdio_probe(struct greybus_module *gmod, +int gb_sdio_probe(struct gb_module *gmod, const struct greybus_module_id *id) { struct mmc_host *mmc; @@ -65,7 +65,7 @@ int gb_sdio_probe(struct greybus_module *gmod, return 0; } -void gb_sdio_disconnect(struct greybus_module *gmod) +void gb_sdio_disconnect(struct gb_module *gmod) { struct mmc_host *mmc; struct gb_sdio_host *host; diff --git a/drivers/staging/greybus/sysfs.c b/drivers/staging/greybus/sysfs.c index a2dce7a..804c0a0 100644 --- a/drivers/staging/greybus/sysfs.c +++ b/drivers/staging/greybus/sysfs.c @@ -17,29 +17,28 @@ #include #include "greybus.h" - #include "kernel_ver.h" /* Module fields */ -#define greybus_module_attr(field) \ +#define gb_module_attr(field) \ static ssize_t module_##field##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ - struct greybus_module *gmod = to_greybus_module(dev); \ + struct gb_module *gmod = to_gb_module(dev); \ return sprintf(buf, "%x\n", gmod->module.field); \ } \ static DEVICE_ATTR_RO(module_##field) -greybus_module_attr(vendor); -greybus_module_attr(product); -greybus_module_attr(version); +gb_module_attr(vendor); +gb_module_attr(product); +gb_module_attr(version); static ssize_t module_serial_number_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct greybus_module *gmod = to_greybus_module(dev); + struct gb_module *gmod = to_gb_module(dev); return sprintf(buf, "%llX\n", (unsigned long long)le64_to_cpu(gmod->module.serial_number)); @@ -50,7 +49,7 @@ static ssize_t module_vendor_string_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct greybus_module *gmod = to_greybus_module(dev); + struct gb_module *gmod = to_gb_module(dev); return sprintf(buf, "%s", greybus_string(gmod, gmod->module.vendor_stringid)); @@ -61,7 +60,7 @@ static ssize_t module_product_string_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct greybus_module *gmod = to_greybus_module(dev); + struct gb_module *gmod = to_gb_module(dev); return sprintf(buf, "%s", greybus_string(gmod, gmod->module.product_stringid)); @@ -81,7 +80,7 @@ static struct attribute *module_attrs[] = { static umode_t module_attrs_are_visible(struct kobject *kobj, struct attribute *a, int n) { - struct greybus_module *gmod = to_greybus_module(kobj_to_dev(kobj)); + struct gb_module *gmod = to_gb_module(kobj_to_dev(kobj)); if ((a == &dev_attr_module_vendor_string.attr) && (gmod->module.vendor_stringid)) diff --git a/drivers/staging/greybus/test_sink.c b/drivers/staging/greybus/test_sink.c index 811a237..1b47769 100644 --- a/drivers/staging/greybus/test_sink.c +++ b/drivers/staging/greybus/test_sink.c @@ -12,10 +12,10 @@ #include "greybus.h" struct test_device { - struct greybus_module *gmod; + struct gb_module *gmod; }; -int gb_register_cport_complete(struct greybus_module *gmod, +int gb_register_cport_complete(struct gb_module *gmod, gbuf_complete_t handler, u16 cport_id, void *context); void gb_deregister_cport_complete(u16 cport_id); diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 7f9d498..301868c 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -26,14 +26,16 @@ #include #include #include + #include "greybus.h" +#include "module.h" #define GB_NUM_MINORS 255 /* 255 is enough for anyone... */ #define GB_NAME "ttyGB" struct gb_tty { struct tty_port port; - struct greybus_module *gmod; + struct gb_module *gmod; u16 cport_id; unsigned int minor; unsigned char clocal; @@ -384,7 +386,7 @@ static const struct tty_operations gb_ops = { }; -int gb_tty_probe(struct greybus_module *gmod, +int gb_tty_probe(struct gb_module *gmod, const struct greybus_module_id *id) { struct gb_tty *gb_tty; @@ -430,7 +432,7 @@ error: return retval; } -void gb_tty_disconnect(struct greybus_module *gmod) +void gb_tty_disconnect(struct gb_module *gmod) { struct gb_tty *gb_tty = gmod->gb_tty; struct tty_struct *tty; -- cgit v0.10.2 From 8c12cde3c2b98ec2d298b2536bcb0cb1d7591b85 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 1 Oct 2014 21:54:12 -0500 Subject: greybus: define greybus interface abstraction Define new source files "interface.h" and "interface.c" to contain the definitions of the Greybus interface abstraction. A Greybus interface represents a UniPro device present in a UniPro module. For Project Ara, each interface block on a module implements a UniPro interface. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 9b5d8e9..21f6358 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -4,6 +4,7 @@ greybus-y := core.o \ debugfs.o \ ap.o \ module.o \ + interface.o \ i2c-gb.o \ gpio-gb.o \ sdio-gb.o \ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index a4fad87..c82c630 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -21,6 +21,7 @@ #include "greybus_id.h" #include "greybus_manifest.h" #include "module.h" +#include "interface.h" /* Matches up with the Greybus Protocol specification document */ diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c new file mode 100644 index 0000000..a6e6e0e --- /dev/null +++ b/drivers/staging/greybus/interface.c @@ -0,0 +1,58 @@ +/* + * Greybus interfaces + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ + +#include "greybus.h" + +/* XXX This could be per-host device or per-module */ +static DEFINE_SPINLOCK(gb_interfaces_lock); + +/* + * A Greybus interface represents a UniPro device present on a + * module. For Project Ara, each active Interface Block on a module + * implements a UniPro device, and therefore a Greybus interface. A + * Greybus module has at least one interface, but can have two (or + * even more). + * + * Create a gb_interface structure to represent a discovered + * interface. Returns a pointer to the new interface or a null + * pointer if a failure occurs due to memory exhaustion. + */ +struct gb_interface * +gb_interface_create(struct gb_module *gmod, u8 interface_id) +{ + struct gb_interface *interface; + + interface = kzalloc(sizeof(*interface), GFP_KERNEL); + if (!interface) + return NULL; + + interface->gmod = gmod; /* XXX refcount? */ + interface->interface_id = interface_id; + + spin_lock_irq(&gb_interfaces_lock); + list_add_tail(&interface->links, &gmod->interfaces); + spin_unlock_irq(&gb_interfaces_lock); + + return interface; +} + +/* + * Tear down a previously set up interface. + */ +void gb_interface_destroy(struct gb_interface *interface) +{ + if (WARN_ON(!interface)) + return; + + spin_lock_irq(&gb_interfaces_lock); + list_del(&interface->links); + spin_unlock_irq(&gb_interfaces_lock); + + /* kref_put(gmod); */ + kfree(interface); +} diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h new file mode 100644 index 0000000..63ae762 --- /dev/null +++ b/drivers/staging/greybus/interface.h @@ -0,0 +1,24 @@ +/* + * Greybus interfaces + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ + +#ifndef __INTERFACE_H +#define __INTERFACE_H + +#include + +struct gb_interface { + struct gb_module *gmod; + u8 interface_id; + + struct list_head links; /* module->interfaces */ +}; + +struct gb_interface *gb_interface_create(struct gb_module *gmod, u8 module_id); +void gb_interface_destroy(struct gb_interface *interface); + +#endif /* __INTERFACE_H */ diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index 31017c2..e777912 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -67,6 +67,7 @@ struct gb_module *gb_module_create(struct greybus_host_device *hd, u8 module_id) module->hd = hd; /* XXX refcount? */ module->module_id = module_id; + INIT_LIST_HEAD(&module->interfaces); spin_lock_irq(&gb_modules_lock); list_add_tail(&module->links, &hd->modules); diff --git a/drivers/staging/greybus/module.h b/drivers/staging/greybus/module.h index 0d0f19f..921c001 100644 --- a/drivers/staging/greybus/module.h +++ b/drivers/staging/greybus/module.h @@ -16,6 +16,7 @@ struct gb_module { struct device dev; + struct list_head interfaces; struct list_head links; /* greybus_host_device->modules */ u8 module_id; /* Physical location within the Endo */ -- cgit v0.10.2 From ef0d2ba20142b5db051e2673d1373e128c990743 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 1 Oct 2014 21:54:13 -0500 Subject: greybus: define greybus function abstraction Define new source files "function.h" and "function.c" to contain the definitions of the Greybus function abstraction. A Greybus function represents an active entity connected to a CPort implemented by a Greybus interface. A Greybus function has a type, which defines the protocol to be used to interact with the function. A Greybus interface normally has at least two functions, but potentially many more. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 21f6358..0efb695 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -5,6 +5,7 @@ greybus-y := core.o \ ap.o \ module.o \ interface.o \ + function.o \ i2c-gb.o \ gpio-gb.o \ sdio-gb.o \ diff --git a/drivers/staging/greybus/function.c b/drivers/staging/greybus/function.c new file mode 100644 index 0000000..b06265c --- /dev/null +++ b/drivers/staging/greybus/function.c @@ -0,0 +1,58 @@ +/* + * Greybus functions + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ + +#include "greybus.h" + +/* XXX This could be per-host device or per-module or per-interface */ +static DEFINE_SPINLOCK(gb_functions_lock); + +/* + * A Greybus function generically defines an entity associated with + * a CPort within a module. Each function has a type (e.g. i2c, + * GPIO, etc.) that defines how it behaves and how the AP interacts + * with it. + * + * Create a gb_function structure to represent a discovered + * function. Returns a pointer to the new function or a null + * pointer if a failure occurs due to memory exhaustion. + */ +struct gb_function *gb_function_create(struct gb_interface *interface, + u16 cport_id, enum greybus_function_type type) +{ + struct gb_function *function; + + function = kzalloc(sizeof(*function), GFP_KERNEL); + if (!function) + return NULL; + + function->interface = interface; /* XXX refcount? */ + function->cport_id = cport_id; + function->type = type; + + spin_lock_irq(&gb_functions_lock); + list_add_tail(&function->links, &interface->functions); + spin_unlock_irq(&gb_functions_lock); + + return function; +} + +/* + * Tear down a previously set up function. + */ +void gb_function_destroy(struct gb_function *function) +{ + if (WARN_ON(!function)) + return; + + spin_lock_irq(&gb_functions_lock); + list_del(&function->links); + spin_unlock_irq(&gb_functions_lock); + + /* kref_put(gmod); */ + kfree(function); +} diff --git a/drivers/staging/greybus/function.h b/drivers/staging/greybus/function.h new file mode 100644 index 0000000..379ffcd --- /dev/null +++ b/drivers/staging/greybus/function.h @@ -0,0 +1,25 @@ +/* + * Greybus functions + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ + +#ifndef __FUNCTION_H +#define __FUNCTION_H + +struct gb_function { + struct gb_interface *interface; + u16 cport_id; + enum greybus_function_type type; + + struct list_head links; /* interface->functions */ +}; + +struct gb_function *gb_function_create(struct gb_interface *interface, + u16 cport_id, + enum greybus_function_type function_type); +void gb_function_destroy(struct gb_function *function); + +#endif /* __FUNCTION_H */ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index c82c630..4eb70af 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -22,6 +22,7 @@ #include "greybus_manifest.h" #include "module.h" #include "interface.h" +#include "function.h" /* Matches up with the Greybus Protocol specification document */ diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index a6e6e0e..dc7d009 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -33,6 +33,7 @@ gb_interface_create(struct gb_module *gmod, u8 interface_id) interface->gmod = gmod; /* XXX refcount? */ interface->interface_id = interface_id; + INIT_LIST_HEAD(&interface->functions); spin_lock_irq(&gb_interfaces_lock); list_add_tail(&interface->links, &gmod->interfaces); diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 63ae762..7c3feb7 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -14,6 +14,7 @@ struct gb_interface { struct gb_module *gmod; u8 interface_id; + struct list_head functions; struct list_head links; /* module->interfaces */ }; -- cgit v0.10.2 From c68adb2f2c999886f8e18e98ad4e69aec14c9f32 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 1 Oct 2014 21:54:14 -0500 Subject: greybus: introduce a connection abstraction Within a UniPro network a pair of CPorts can be linked to form a UniPro Connection. This patch creates a new abstraction to represent an AP CPort that is connected with a CPort used by a function within a Greybus module. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 0efb695..ed39a5c 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -6,6 +6,7 @@ greybus-y := core.o \ module.o \ interface.o \ function.o \ + connection.o \ i2c-gb.o \ gpio-gb.o \ sdio-gb.o \ diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c new file mode 100644 index 0000000..113c985 --- /dev/null +++ b/drivers/staging/greybus/connection.c @@ -0,0 +1,48 @@ +/* + * Greybus connections + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ + +#include "greybus.h" + +/* + * Set up a Greybus connection, representing the bidirectional link + * between a CPort on a (local) Greybus host device and a CPort on + * another Greybus module. + * + * Returns a pointer to the new connection if successful, or a null + * pointer otherwise. + */ +struct gb_connection *gb_connection_create(struct greybus_host_device *hd, + u16 cport_id, struct gb_function *function) +{ + struct gb_connection *connection; + + connection = kzalloc(sizeof(*connection), GFP_KERNEL); + if (!connection) + return NULL; + + connection->hd = hd; /* XXX refcount? */ + connection->cport_id = cport_id; + connection->function = function; /* XXX refcount? */ + + return connection; +} + +/* + * Tear down a previously set up connection. + */ +void gb_connection_destroy(struct gb_connection *connection) +{ + if (WARN_ON(!connection)) + return; + + /* XXX Need to wait for any outstanding requests to complete */ + + /* kref_put(function); */ + /* kref_put(hd); */ + kfree(connection); +} diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h new file mode 100644 index 0000000..79b3b07 --- /dev/null +++ b/drivers/staging/greybus/connection.h @@ -0,0 +1,29 @@ +/* + * Greybus connections + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ + +#ifndef __CONNECTION_H +#define __CONNECTION_H + +#include + +#include "greybus.h" +#include "function.h" + +struct gb_connection { + struct gb_function *function; + struct greybus_host_device *hd; + u16 cport_id; /* Host side */ + + struct list_head host_links; +}; + +bool gb_connection_setup(struct greybus_host_device *hd, u16 cport_id, + struct gb_function *function); +void gb_connection_teardown(struct gb_connection *connection); + +#endif /* __CONNECTION_H */ diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 934bdeb..eb8f8e5 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -147,12 +147,22 @@ static struct device_type greybus_module_type = { .release = greybus_module_release, }; +/* XXX + * This needs to be driven by the list of functions that the + * manifest says are present. + */ static int gb_init_subdevs(struct gb_module *gmod, const struct greybus_module_id *id) { int retval; /* Allocate all of the different "sub device types" for this device */ + + /* XXX + * Decide what exactly we should get supplied for the i2c + * probe, and then work that back to what should be present + * in the manifest. + */ retval = gb_i2c_probe(gmod, id); if (retval) goto error_i2c; diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 4eb70af..732cc5e 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -23,6 +23,7 @@ #include "module.h" #include "interface.h" #include "function.h" +#include "connection.h" /* Matches up with the Greybus Protocol specification document */ @@ -180,6 +181,7 @@ struct greybus_host_device { const struct greybus_host_driver *driver; struct list_head modules; + struct list_head connections; /* Private data for the host driver */ unsigned long hd_priv[0] __attribute__ ((aligned(sizeof(s64)))); -- cgit v0.10.2 From e88afa5811c741facff3fa695d340133ac8a1be1 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 1 Oct 2014 21:54:15 -0500 Subject: greybus: introduce an operation abstraction This patch defines a new "operation" abstraction. An operation is a request from by one end of a connection to the function (or AP) on the other, coupled with a matching response returned to the requestor. The request indicates some action to be performed by the target of the request (such as "read some data"). Once the action has completed the target sends back an operation response message. Additional data can be supplied by the sender with its request, and/or by the target with its resposne message. Each request message has a unique id, generated by the sender. The sender recognizes the matching response by the presence of this id value. Each end of a connection is responsible for creating unique ids for the requests it sends. An operation also has a type, whose interpretation is dependent on the function type on the end of the connection opposite the sender. It is up to the creator of an operation to fill in the data (if any) to be sent with the request. Note that not all requests are initiated by the AP. Incoming data on a module function can result in a request message being sent from that function to the AP to notify of the data's arrival. Once the AP has processed this, it sends a response to the sender. Every operation response contains a status byte. If it's value is 0, the operation was successful. Any other value indicates an error. Add a defintion of U16_MAX to "kernel_ver.h". Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index ed39a5c..d6c4cc3 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -7,6 +7,7 @@ greybus-y := core.o \ interface.o \ function.o \ connection.o \ + operation.o \ i2c-gb.o \ gpio-gb.o \ sdio-gb.o \ diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 113c985..fa5ab5d 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -6,6 +6,9 @@ * Released under the GPLv2 only. */ +#include + +#include "kernel_ver.h" #include "greybus.h" /* @@ -13,6 +16,9 @@ * between a CPort on a (local) Greybus host device and a CPort on * another Greybus module. * + * A connection also maintains the state of operations sent over the + * connection. + * * Returns a pointer to the new connection if successful, or a null * pointer otherwise. */ @@ -28,6 +34,8 @@ struct gb_connection *gb_connection_create(struct greybus_host_device *hd, connection->hd = hd; /* XXX refcount? */ connection->cport_id = cport_id; connection->function = function; /* XXX refcount? */ + INIT_LIST_HEAD(&connection->operations); + atomic_set(&connection->op_cycle, 0); return connection; } @@ -41,8 +49,14 @@ void gb_connection_destroy(struct gb_connection *connection) return; /* XXX Need to wait for any outstanding requests to complete */ + WARN_ON(!list_empty(&connection->operations)); /* kref_put(function); */ /* kref_put(hd); */ kfree(connection); } + +u16 gb_connection_op_id(struct gb_connection *connection) +{ + return (u16)(atomic_inc_return(&connection->op_cycle) % U16_MAX); +} diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 79b3b07..c653c95 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -20,10 +20,15 @@ struct gb_connection { u16 cport_id; /* Host side */ struct list_head host_links; + + struct list_head operations; + atomic_t op_cycle; }; bool gb_connection_setup(struct greybus_host_device *hd, u16 cport_id, struct gb_function *function); void gb_connection_teardown(struct gb_connection *connection); +u16 gb_connection_op_id(struct gb_connection *connection); + #endif /* __CONNECTION_H */ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 732cc5e..9a66fd1 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -24,6 +24,7 @@ #include "interface.h" #include "function.h" #include "connection.h" +#include "operation.h" /* Matches up with the Greybus Protocol specification document */ diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index 4aa5b83..c9ea7a9 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -22,4 +22,8 @@ #define U8_MAX ((u8)~0U) #endif /* ! U8_MAX */ +#ifndef U16_MAX +#define U16_MAX ((u16)(~0U)) +#endif /* !U16_MAX */ + #endif /* __GREYBUS_KERNEL_VER_H */ diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c new file mode 100644 index 0000000..5cb23aa --- /dev/null +++ b/drivers/staging/greybus/operation.c @@ -0,0 +1,171 @@ +/* + * Greybus operations + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include + +#include "greybus.h" + +/* + * All operation messages (both requests and responses) begin with + * a common header that encodes the size of the data (header + * included). This header also contains a unique identifier, which + * is used to keep track of in-flight operations. Finally, the + * header contains a operation type field, whose interpretation is + * dependent on what type of device lies on the other end of the + * connection. Response messages are distinguished from request + * messages by setting the high bit (0x80) in the operation type + * value. + * + * The wire format for all numeric fields in the header is little + * endian. Any operation-specific data begins immediately after the + * header, and is 64-bit aligned. + */ +struct gb_operation_msg_hdr { + __le16 size; /* Size in bytes of header + payload */ + __le16 id; /* Operation unique id */ + __u8 type; /* E.g GB_I2C_TYPE_* or GB_GPIO_TYPE_* */ + /* 3 bytes pad, must be zero (ignore when read) */ +} __aligned(sizeof(u64)); + +/* XXX Could be per-host device, per-module, or even per-connection */ +static DEFINE_SPINLOCK(gb_operations_lock); + +/* + * An operations's response message has arrived. If no callback was + * supplied it was submitted for asynchronous completion, so we notify + * any waiters. Otherwise we assume calling the completion is enough + * and nobody else will be waiting. + */ +void gb_operation_complete(struct gb_operation *operation) +{ + if (operation->callback) + operation->callback(operation); + else + complete_all(&operation->completion); +} + +/* + * Wait for a submitted operatnoi to complete */ +int gb_operation_wait(struct gb_operation *operation) +{ + int ret; + + ret = wait_for_completion_interruptible(&operation->completion); + /* If interrupted, cancel the in-flight buffer */ + if (ret < 0) + ret = greybus_kill_gbuf(operation->gbuf); + return ret; + +} + +/* + * Submit an outbound operation. The caller has filled in any + * payload so the request message is ready to go. If non-null, + * the callback function supplied will be called when the response + * message has arrived indicating the operation is complete. A null + * callback function is used for a synchronous request; return from + * this function won't occur until the operation is complete (or an + * interrupt occurs). + */ +int gb_operation_submit(struct gb_operation *operation, + gb_operation_callback callback) +{ + int ret; + + /* XXX + * gfp is probably GFP_ATOMIC but really I think + * the gfp mask should go away. + */ + operation->callback = callback; + ret = greybus_submit_gbuf(operation->gbuf, GFP_KERNEL); + if (ret) + return ret; + if (!callback) + ret = gb_operation_wait(operation); + + return ret; +} + +/* + * Called when a greybus request message has actually been sent. + */ +static void gbuf_out_callback(struct gbuf *gbuf) +{ + /* Record it's been submitted; need response now */ +} + +/* + * Create a Greybus operation having a buffer big enough for an + * outgoing payload of the given size to be sent over the given + * connection. + * + * Returns a pointer to the new operation or a null pointer if a + * failure occurs due to memory exhaustion. + */ +struct gb_operation *gb_operation_create(struct gb_connection *connection, + size_t size) +{ + struct gb_operation *operation; + struct gb_operation_msg_hdr *header; + struct gbuf *gbuf; + + /* XXX Use a slab cache */ + operation = kzalloc(sizeof(*operation), GFP_KERNEL); + if (!operation) + return NULL; + + /* Our buffer holds a header in addition to the requested payload */ + size += sizeof(*header); + gbuf = greybus_alloc_gbuf(connection->function->interface->gmod, + connection->cport_id, + gbuf_out_callback, size, + GFP_KERNEL, operation); + if (gbuf) { + kfree(operation); + return NULL; + } + + operation->connection = connection; /* XXX refcount? */ + + /* Fill in the header structure and payload pointer */ + operation->gbuf = gbuf; + header = (struct gb_operation_msg_hdr *)&gbuf->transfer_buffer; + header->id = 0; + header->size = size; + operation->payload = (char *)header + sizeof(*header); + + operation->callback = NULL; /* set at submit time */ + init_completion(&operation->completion); + + spin_lock_irq(&gb_operations_lock); + list_add_tail(&operation->links, &connection->operations); + spin_unlock_irq(&gb_operations_lock); + + return operation; +} + +/* + * Destroy a previously created operation. + */ +void gb_operation_destroy(struct gb_operation *operation) +{ + if (WARN_ON(!operation)) + return; + + /* XXX Make sure it's not in flight */ + spin_lock_irq(&gb_operations_lock); + list_del(&operation->links); + spin_unlock_irq(&gb_operations_lock); + + greybus_free_gbuf(operation->gbuf); + + kfree(operation); +} diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h new file mode 100644 index 0000000..96a7a0f --- /dev/null +++ b/drivers/staging/greybus/operation.h @@ -0,0 +1,69 @@ +/* + * Greybus operations + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ + +#ifndef __OPERATION_H +#define __OPERATION_H + +#include + +enum gb_operation_status { + GB_OP_SUCCESS = 0, + GB_OP_INVALID = 1, + GB_OP_NO_MEMORY = 2, + GB_OP_INTERRUPTED = 3, +}; + +/* + * A Greybus operation is a remote procedure call performed over a + * connection between the AP and a function on Greybus module. + * Every operation consists of a request message sent to the other + * end of the connection coupled with a reply returned to the + * sender. + * + * The state for managing active requests on a connection is held in + * the connection structure. + * + * YADA YADA + * + * submitting each request and providing its matching response to + * the caller when it arrives. Operations normally complete + * asynchronously, and when an operation's response arrives its + * callback function is executed. The callback pointer is supplied + * at the time the operation is submitted; a null callback pointer + * causes synchronous operation--the caller is blocked until + * the response arrives. In addition, it is possible to await + * the completion of a submitted asynchronous operation. + * + * A Greybus device operation includes a Greybus buffer to hold the + * data sent to the device. The only field within a Greybus + * operation that should be used by a caller is the payload pointer, + * which should be used to populate the request data. This pointer + * is guaranteed to be 64-bit aligned. + * XXX and callback? + */ +struct gb_operation; +typedef void (*gb_operation_callback)(struct gb_operation *); +struct gb_operation { + struct gb_connection *connection; + struct gbuf *gbuf; + void *payload; /* sender data */ + gb_operation_callback callback; /* If asynchronous */ + struct completion completion; /* Used if no callback */ + u8 result; + + struct list_head links; /* connection->operations */ +}; + +struct gb_operation *gb_operation_create(struct gb_connection *connection, + size_t size); +void gb_operation_destroy(struct gb_operation *operation); + +int gb_operation_wait(struct gb_operation *operation); +void gb_operation_complete(struct gb_operation *operation); + +#endif /* !__OPERATION_H */ -- cgit v0.10.2 From b09c94a1b71c82385ffa5f3c913d7d6e14eaea3d Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 1 Oct 2014 21:54:16 -0500 Subject: greybus: start improving manifest parsing Currently the module manifest parsing code is sort of representative only and is not really very useful. This patch begins doing "real" parsing of the module manifest. It scans the module manifest to identify the descriptors it holds. It then verifies there's only one module descriptor found, and initializes new some fields in the gb_module structure based on what it contains (converting what's found to native byte order). Note that if anything unexpected is found or other errors occur when parsing the manifest, the parse fails. Because we now save this converted information when it's parsed we no longer have a greybus_descriptor_module struct within a struct gb_module. And because we've already converted these values, we can do a little less work displaying values in sysfs. (We also now show vendor, product, and version values in the right byte order.) This eliminates the need for greybus_string(), so get rid of it. It also slightly simplifies the greybus module matching code. Move some existing parsing code into a new file, "manifest.c". Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index d6c4cc3..a303f81 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -3,6 +3,7 @@ greybus-y := core.o \ sysfs.o \ debugfs.o \ ap.o \ + manifest.o \ module.o \ interface.o \ function.o \ diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index eb8f8e5..8e4493c 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -126,22 +126,6 @@ static void greybus_module_release(struct device *dev) } -const u8 *greybus_string(struct gb_module *gmod, int id) -{ - int i; - struct gmod_string *string; - - if (!gmod) - return NULL; - - for (i = 0; i < gmod->num_strings; ++i) { - string = gmod->string[i]; - if (string->id == id) - return &string->string[0]; - } - return NULL; -} - static struct device_type greybus_module_type = { .name = "greybus_module", .release = greybus_module_release, @@ -204,19 +188,6 @@ static const struct greybus_module_id fake_greybus_module_id = { GREYBUS_DEVICE(0x42, 0x42) }; -static int create_module(struct gb_module *gmod, - struct greybus_descriptor_module *module, - size_t desc_size) -{ - if (desc_size != sizeof(*module)) { - dev_err(gmod->dev.parent, "invalid module header size %zu\n", - desc_size); - return -EINVAL; - } - memcpy(&gmod->module, module, desc_size); - return 0; -} - static int create_string(struct gb_module *gmod, struct greybus_descriptor_string *string, size_t desc_size) @@ -284,15 +255,16 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, struct gb_module *gmod; struct greybus_manifest *manifest; int retval; - int overall_size; - - /* we have to have at _least_ the manifest header */ - if (size <= sizeof(manifest->header)) - return; - gmod = gb_module_create(hd, module_id); - if (!gmod) + /* + * Parse the manifest and build up our data structures + * representing what's in it. + */ + gmod = gb_manifest_parse(data, size); + if (!gmod) { + dev_err(hd->parent, "manifest error\n"); return; + } gmod->dev.parent = hd->parent; gmod->dev.driver = NULL; @@ -303,24 +275,6 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, device_initialize(&gmod->dev); dev_set_name(&gmod->dev, "%d", module_id); - manifest = (struct greybus_manifest *)data; - overall_size = le16_to_cpu(manifest->header.size); - if (overall_size != size) { - dev_err(hd->parent, "size != manifest header size, %d != %d\n", - size, overall_size); - goto error; - } - - /* Validate major/minor number */ - if (manifest->header.version_major > GREYBUS_VERSION_MAJOR) { - dev_err(hd->parent, - "Manifest version too new (%hhu.%hhu > %hhu.%hhu)\n", - manifest->header.version_major, - manifest->header.version_minor, - GREYBUS_VERSION_MAJOR, GREYBUS_VERSION_MINOR); - goto error; - } - size -= sizeof(manifest->header); data += sizeof(manifest->header); while (size > 0) { @@ -347,8 +301,6 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, break; case GREYBUS_TYPE_MODULE: - retval = create_module(gmod, &desc->module, - data_size); break; case GREYBUS_TYPE_STRING: diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 9a66fd1..fabd74e4 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -20,6 +20,7 @@ #include "greybus_id.h" #include "greybus_manifest.h" +#include "manifest.h" #include "module.h" #include "interface.h" #include "function.h" @@ -246,8 +247,6 @@ int greybus_disabled(void); void greybus_remove_device(struct gb_module *gmod); -const u8 *greybus_string(struct gb_module *gmod, int id); - /* Internal functions to gb module, move to internal .h file eventually. */ void gb_add_module(struct greybus_host_device *hd, u8 module_id, diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c new file mode 100644 index 0000000..cdb7c24 --- /dev/null +++ b/drivers/staging/greybus/manifest.c @@ -0,0 +1,313 @@ +/* + * Greybus module manifest parsing + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include + +#include "greybus.h" + +/* + * We scan the manifest once to identify where all the descriptors + * are. The result is a list of these manifest_desc structures. We + * then pick through them for what we're looking for (starting with + * the module descriptor). As each is processed we remove it from + * the list. When we're done the list should (probably) be empty. + */ +struct manifest_desc { + struct list_head links; + + size_t size; + void *data; + enum greybus_descriptor_type type; +}; + +static LIST_HEAD(manifest_descs); + +static void release_manifest_descriptor(struct manifest_desc *descriptor) +{ + list_del(&descriptor->links); + kfree(descriptor); +} + +static void release_manifest_descriptors(void) +{ + struct manifest_desc *descriptor; + struct manifest_desc *next; + + list_for_each_entry_safe(descriptor, next, &manifest_descs, links) + release_manifest_descriptor(descriptor); +} + +/* + * Validate the given descriptor. Its reported size must fit within + * the number of bytes reamining, and it must have a recognized + * type. Check that the reported size is at least as big as what + * we expect to see. (It could be bigger, perhaps for a new version + * of the format.) + * + * Returns the number of bytes consumed by the descriptor, or a + * negative errno. + */ +static int identify_descriptor(struct greybus_descriptor *desc, size_t size) +{ + struct greybus_descriptor_header *desc_header = &desc->header; + struct manifest_desc *descriptor; + int desc_size; + size_t expected_size; + + if (size < sizeof(*desc_header)) { + pr_err("manifest too small\n"); + return -EINVAL; /* Must at least have header */ + } + + desc_size = (int)le16_to_cpu(desc_header->size); + if ((size_t)desc_size > size) { + pr_err("descriptor too big\n"); + return -EINVAL; + } + + switch (desc_header->type) { + case GREYBUS_TYPE_MODULE: + if (desc_size < sizeof(struct greybus_descriptor_module)) { + pr_err("module descriptor too small (%u)\n", + desc_size); + return -EINVAL; + } + break; + case GREYBUS_TYPE_DEVICE: + break; + case GREYBUS_TYPE_CLASS: + pr_err("class descriptor found (ignoring)\n"); + break; + case GREYBUS_TYPE_STRING: + expected_size = sizeof(struct greybus_descriptor_header); + expected_size += sizeof(struct greybus_descriptor_string); + expected_size += (size_t)desc->string.length; + if (desc_size < expected_size) { + pr_err("string descriptor too small (%u)\n", + desc_size); + return -EINVAL; + } + break; + case GREYBUS_TYPE_CPORT: + if (desc_size < sizeof(struct greybus_descriptor_cport)) { + pr_err("cport descriptor too small (%u)\n", + desc_size); + return -EINVAL; + } + break; + case GREYBUS_TYPE_INVALID: + default: + pr_err("invalid descriptor type (%hhu)\n", desc_header->type); + return -EINVAL; + } + + descriptor = kzalloc(sizeof(*descriptor), GFP_KERNEL); + if (!descriptor) + return -ENOMEM; + + descriptor->size = desc_size; + descriptor->data = desc; + descriptor->type = desc_header->type; + list_add_tail(&descriptor->links, &manifest_descs); + + return desc_size; +} + +/* + * Find the string descriptor having the given id, validate it, and + * allocate a duplicate copy of it. The duplicate has an extra byte + * which guarantees the returned string is NUL-terminated. + * + * String index 0 is valid (it represents "no string"), and for + * that a null pointer is returned. + * + * Otherwise returns a pointer to a newly-allocated copy of the + * descriptor string, or an error-coded pointer on failure. + */ +static char *gb_string_get(u8 string_id) +{ + struct greybus_descriptor_string *desc_string; + struct manifest_desc *descriptor; + bool found = false; + char *string; + + /* A zero string id means no string (but no error) */ + if (!string_id) + return NULL; + + list_for_each_entry(descriptor, &manifest_descs, links) { + struct greybus_descriptor *desc; + + if (descriptor->type != GREYBUS_TYPE_STRING) + continue; + + desc = descriptor->data; + desc_string = &desc->string; + if (desc_string->id == string_id) { + found = true; + break; + } + } + if (!found) + return ERR_PTR(-ENOENT); + + /* Allocate an extra byte so we can guarantee it's NUL-terminated */ + string = kmemdup(&desc_string->string, (size_t)desc_string->length + 1, + GFP_KERNEL); + if (!string) + return ERR_PTR(-ENOMEM); + string[desc_string->length] = '\0'; + + /* Ok we've used this string, so we're done with it */ + release_manifest_descriptor(descriptor); + + return string; +} + +struct gb_module *gb_manifest_parse_module(struct manifest_desc *module_desc) +{ + struct greybus_descriptor *desc = module_desc->data; + struct greybus_descriptor_module *desc_module = &desc->module; + struct gb_module *gmod; + + gmod = kzalloc(sizeof(*gmod), GFP_KERNEL); + if (!gmod) + return NULL; + + /* Handle the strings first--they can fail */ + gmod->vendor_string = gb_string_get(desc_module->vendor_stringid); + if (IS_ERR(gmod->vendor_string)) { + kfree(gmod); + return NULL; + } + gmod->product_string = gb_string_get(desc_module->product_stringid); + if (IS_ERR(gmod->product_string)) { + kfree(gmod->vendor_string); + kfree(gmod); + return NULL; + } + + gmod->vendor = le16_to_cpu(desc_module->vendor); + gmod->product = le16_to_cpu(desc_module->product); + gmod->version = le16_to_cpu(desc_module->version); + gmod->serial_number = le64_to_cpu(desc_module->serial_number); + + /* Release the module descriptor, now that we're done with it */ + release_manifest_descriptor(module_desc); + + return gmod; +} + +/* + * Parse a buffer containing a module manifest. + * + * If we find anything wrong with the content/format of the buffer + * we reject it. + * + * The first requirement is that the manifest's version is + * one we can parse. + * + * We make an initial pass through the buffer and identify all of + * the descriptors it contains, keeping track for each its type + * and the location size of its data in the buffer. + * + * Next we scan the descriptors, looking for a module descriptor; + * there must be exactly one of those. When found, we record the + * information it contains, and then remove that descriptor (and any + * string descriptors it refers to) from further consideration. + * + * After that we look for the module's interfaces--there must be at + * least one of those. + * + * Return a pointer to an initialized gb_module structure + * representing the content of the module manifest, or a null + * pointer if an error occurs. + */ +struct gb_module *gb_manifest_parse(void *data, size_t size) +{ + struct greybus_manifest *manifest; + struct greybus_manifest_header *header; + struct greybus_descriptor *desc; + struct manifest_desc *descriptor; + struct manifest_desc *module_desc = NULL; + struct gb_module *gmod; + u16 manifest_size; + u32 found = 0; + + /* we have to have at _least_ the manifest header */ + if (size <= sizeof(manifest->header)) { + pr_err("short manifest (%zu)\n", size); + return NULL; + } + + /* Make sure the size is right */ + manifest = data; + header = &manifest->header; + manifest_size = le16_to_cpu(header->size); + if (manifest_size != size) { + pr_err("manifest size mismatch %zu != %hu\n", + size, manifest_size); + return NULL; + } + + /* Validate major/minor number */ + if (header->version_major > GREYBUS_VERSION_MAJOR) { + pr_err("manifest version too new (%hhu.%hhu > %hhu.%hhu)\n", + header->version_major, header->version_minor, + GREYBUS_VERSION_MAJOR, GREYBUS_VERSION_MINOR); + return NULL; + } + + /* OK, find all the descriptors */ + desc = (struct greybus_descriptor *)(header + 1); + size -= sizeof(*header); + while (size) { + int desc_size; + + desc_size = identify_descriptor(desc, size); + if (desc_size <= 0) { + if (!desc_size) + pr_err("zero-sized manifest descriptor\n"); + goto out_err; + } + desc = (struct greybus_descriptor *)((char *)desc + desc_size); + size -= desc_size; + } + + /* There must be a single module descriptor */ + list_for_each_entry(descriptor, &manifest_descs, links) { + if (descriptor->type == GREYBUS_TYPE_MODULE) + if (!found++) + module_desc = descriptor; + } + if (found != 1) { + pr_err("manifest must have 1 module descriptor (%u found)\n", + found); + goto out_err; + } + + /* Parse the module manifest, starting with the module descriptor */ + gmod = gb_manifest_parse_module(module_desc); + + /* + * We really should have no remaining descriptors, but we + * don't know what newer format manifests might leave. + */ + if (!list_empty(&manifest_descs)) { + pr_info("excess descriptors in module manifest\n"); + release_manifest_descriptors(); + } + + return gmod; +out_err: + release_manifest_descriptors(); + + return NULL; +} diff --git a/drivers/staging/greybus/manifest.h b/drivers/staging/greybus/manifest.h new file mode 100644 index 0000000..29cbf92 --- /dev/null +++ b/drivers/staging/greybus/manifest.h @@ -0,0 +1,14 @@ +/* + * Greybus module manifest parsing + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ + +#ifndef __MANIFEST_H +#define __MANIFEST_H + +struct gb_module *gb_manifest_parse(void *data, size_t size); + +#endif /* __MANIFEST_H */ diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index e777912..6618d21 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -14,20 +14,16 @@ static DEFINE_SPINLOCK(gb_modules_lock); static int gb_module_match_one_id(struct gb_module *gmod, const struct greybus_module_id *id) { - struct greybus_descriptor_module *module; - - module = &gmod->module; - if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_VENDOR) && - (id->vendor != le16_to_cpu(module->vendor))) + (id->vendor != gmod->vendor)) return 0; if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_PRODUCT) && - (id->product != le16_to_cpu(module->product))) + (id->product != gmod->product)) return 0; if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_SERIAL) && - (id->serial_number != le64_to_cpu(module->serial_number))) + (id->serial_number != gmod->serial_number)) return 0; return 1; @@ -84,6 +80,9 @@ void gb_module_destroy(struct gb_module *module) if (WARN_ON(!module)) return; + kfree(module->product_string); + kfree(module->vendor_string); + spin_lock_irq(&gb_modules_lock); list_del(&module->links); spin_unlock_irq(&gb_modules_lock); diff --git a/drivers/staging/greybus/module.h b/drivers/staging/greybus/module.h index 921c001..326176a 100644 --- a/drivers/staging/greybus/module.h +++ b/drivers/staging/greybus/module.h @@ -20,7 +20,14 @@ struct gb_module { struct list_head links; /* greybus_host_device->modules */ u8 module_id; /* Physical location within the Endo */ - struct greybus_descriptor_module module; + /* Information taken from the manifest module descriptor */ + u16 vendor; + u16 product; + u16 version; + u64 serial_number; + char *vendor_string; + char *product_string; + int num_cports; int num_strings; u16 cport_ids[MAX_CPORTS_PER_MODULE]; diff --git a/drivers/staging/greybus/sysfs.c b/drivers/staging/greybus/sysfs.c index 804c0a0..f969d90 100644 --- a/drivers/staging/greybus/sysfs.c +++ b/drivers/staging/greybus/sysfs.c @@ -26,7 +26,7 @@ static ssize_t module_##field##_show(struct device *dev, \ char *buf) \ { \ struct gb_module *gmod = to_gb_module(dev); \ - return sprintf(buf, "%x\n", gmod->module.field); \ + return sprintf(buf, "%x\n", gmod->field); \ } \ static DEVICE_ATTR_RO(module_##field) @@ -40,8 +40,7 @@ static ssize_t module_serial_number_show(struct device *dev, { struct gb_module *gmod = to_gb_module(dev); - return sprintf(buf, "%llX\n", - (unsigned long long)le64_to_cpu(gmod->module.serial_number)); + return sprintf(buf, "%llX\n", (unsigned long long)gmod->serial_number); } static DEVICE_ATTR_RO(module_serial_number); @@ -51,8 +50,7 @@ static ssize_t module_vendor_string_show(struct device *dev, { struct gb_module *gmod = to_gb_module(dev); - return sprintf(buf, "%s", - greybus_string(gmod, gmod->module.vendor_stringid)); + return sprintf(buf, "%s", gmod->vendor_string); } static DEVICE_ATTR_RO(module_vendor_string); @@ -62,8 +60,7 @@ static ssize_t module_product_string_show(struct device *dev, { struct gb_module *gmod = to_gb_module(dev); - return sprintf(buf, "%s", - greybus_string(gmod, gmod->module.product_stringid)); + return sprintf(buf, "%s", gmod->product_string); } static DEVICE_ATTR_RO(module_product_string); @@ -81,21 +78,17 @@ static umode_t module_attrs_are_visible(struct kobject *kobj, struct attribute *a, int n) { struct gb_module *gmod = to_gb_module(kobj_to_dev(kobj)); + umode_t mode = a->mode; + + if (a == &dev_attr_module_vendor_string.attr && gmod->vendor_string) + return mode; + if (a == &dev_attr_module_product_string.attr && gmod->product_string) + return mode; + if (gmod->vendor || gmod->product || gmod->version) + return mode; + if (gmod->serial_number) + return mode; - if ((a == &dev_attr_module_vendor_string.attr) && - (gmod->module.vendor_stringid)) - return a->mode; - if ((a == &dev_attr_module_product_string.attr) && - (gmod->module.product_stringid)) - return a->mode; - - // FIXME - make this a dynamic structure to "know" if it really is here - // or not easier? - if (gmod->module.vendor || - gmod->module.product || - gmod->module.version || - gmod->module.serial_number) - return a->mode; return 0; } @@ -104,9 +97,6 @@ static struct attribute_group module_attr_grp = { .is_visible = module_attrs_are_visible, }; - - - const struct attribute_group *greybus_module_groups[] = { &module_attr_grp, NULL, -- cgit v0.10.2 From d88bfb5b7df54f81869b28a25511e8ab957c4ced Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 1 Oct 2014 21:54:17 -0500 Subject: greybus: manifest interface descriptor parsing Add support for parsing one or more interface descriptors in a module manifest. There must be at least one, but we impose no limit on the number of interfaces associated with a module. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index cdb7c24..2c3cf74 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -171,6 +171,45 @@ static char *gb_string_get(u8 string_id) return string; } +/* + * Find interface descriptors in the manifest and set up their data + * structures. Returns the number of interfaces set up for the + * given module. + */ +static u32 gb_manifest_parse_interfaces(struct gb_module *gmod) +{ + u32 count = 0; + + while (true) { + struct manifest_desc *descriptor; + struct greybus_descriptor_interface *desc_interface; + struct gb_interface *interface; + bool found = false; + + /* Find an interface descriptor */ + list_for_each_entry(descriptor, &manifest_descs, links) { + if (descriptor->type == GREYBUS_TYPE_DEVICE) { + found = true; + break; + } + } + if (!found) + break; + + /* Found one. Set up its interface structure*/ + desc_interface = descriptor->data; + interface = gb_interface_create(gmod, desc_interface->id); + if (!interface) + return 0; /* Error */ + count++; + + /* Done with this interface descriptor */ + release_manifest_descriptor(descriptor); + } + + return count; +} + struct gb_module *gb_manifest_parse_module(struct manifest_desc *module_desc) { struct greybus_descriptor *desc = module_desc->data; @@ -202,6 +241,13 @@ struct gb_module *gb_manifest_parse_module(struct manifest_desc *module_desc) /* Release the module descriptor, now that we're done with it */ release_manifest_descriptor(module_desc); + /* A module must have at least one interface descriptor */ + if (!gb_manifest_parse_interfaces(gmod)) { + pr_err("manifest interface descriptors not valid\n"); + gb_module_destroy(gmod); + return NULL; + } + return gmod; } -- cgit v0.10.2 From c095bbcfcb1728aea3e9730ea6997373e3744582 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 1 Oct 2014 21:54:18 -0500 Subject: greybus: manifest cport descriptor parsing Add support for parsing one or more cports descriptors in a module manifest. There must be at least one for each interface, but we impose no limit on the number of interfaces associated with a module. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 2c3cf74..bae260f 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -172,6 +172,49 @@ static char *gb_string_get(u8 string_id) } /* + * Find cport descriptors in the manifest and set up data structures + * for the functions that use them. Returns the number of interfaces + * set up for the given module, or 0 if there is an error. + */ +u32 gb_manifest_parse_cports(struct gb_interface *interface) +{ + u32 count = 0; + + while (true) { + struct manifest_desc *descriptor; + struct greybus_descriptor_cport *desc_cport; + enum greybus_function_type function_type; + u16 cport_id; + bool found; + + /* Find a cport descriptor */ + found = false; + list_for_each_entry(descriptor, &manifest_descs, links) { + if (descriptor->type == GREYBUS_TYPE_CPORT) { + found = true; + break; + } + } + if (!found) + break; + + /* Found one. Set up its function structure */ + desc_cport = descriptor->data; + function_type = + (enum greybus_function_type)desc_cport->function_type; + cport_id = le16_to_cpu(desc_cport->id); + if (!gb_function_create(interface, cport_id, function_type)) + return 0; /* Error */ + + count++; + /* Release the cport descriptor */ + release_manifest_descriptor(descriptor); + } + + return count; +} + +/* * Find interface descriptors in the manifest and set up their data * structures. Returns the number of interfaces set up for the * given module. @@ -201,6 +244,11 @@ static u32 gb_manifest_parse_interfaces(struct gb_module *gmod) interface = gb_interface_create(gmod, desc_interface->id); if (!interface) return 0; /* Error */ + + /* Now go set up this interface's functions and cports */ + if (!gb_manifest_parse_cports(interface)) + return 0; /* Error parsing cports */ + count++; /* Done with this interface descriptor */ -- cgit v0.10.2 From 459164b1f4d8075e6eaf0fd8eaa54e84c9e3fb3a Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 1 Oct 2014 21:54:19 -0500 Subject: greybus: kill off old manifest code Now that the new manifest code is in place, delete the old stuff from "core.c". Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 8e4493c..d9bbc67 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -188,60 +188,6 @@ static const struct greybus_module_id fake_greybus_module_id = { GREYBUS_DEVICE(0x42, 0x42) }; -static int create_string(struct gb_module *gmod, - struct greybus_descriptor_string *string, - size_t desc_size) -{ - int string_size; - struct gmod_string *gmod_string; - - if (gmod->num_strings == MAX_STRINGS_PER_MODULE) { - dev_err(gmod->dev.parent, - "too many strings for this module!\n"); - return -EINVAL; - } - - if (desc_size < sizeof(*string)) { - dev_err(gmod->dev.parent, "invalid string header size %zu\n", - desc_size); - return -EINVAL; - } - - string_size = string->length; - gmod_string = kzalloc(sizeof(*gmod_string) + string_size + 1, GFP_KERNEL); - if (!gmod_string) - return -ENOMEM; - - gmod_string->length = string_size; - gmod_string->id = string->id; - memcpy(&gmod_string->string, &string->string, string_size); - - gmod->string[gmod->num_strings] = gmod_string; - gmod->num_strings++; - - return 0; -} - -static int create_cport(struct gb_module *gmod, - struct greybus_descriptor_cport *cport, - size_t desc_size) -{ - if (gmod->num_cports == MAX_CPORTS_PER_MODULE) { - dev_err(gmod->dev.parent, "too many cports for this module!\n"); - return -EINVAL; - } - - if (desc_size != sizeof(*cport)) { - dev_err(gmod->dev.parent, - "invalid cport descriptor size %zu\n", desc_size); - return -EINVAL; - } - - gmod->cport_ids[gmod->num_cports] = le16_to_cpu(cport->id); - gmod->num_cports++; - - return 0; -} /** * gb_add_module @@ -253,7 +199,6 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, u8 *data, int size) { struct gb_module *gmod; - struct greybus_manifest *manifest; int retval; /* @@ -266,6 +211,15 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, return; } + /* + * XXX + * We've successfully parsed the manifest. Now we need to + * allocate CPort Id's for connecting to the CPorts found on + * other modules. For each of these, establish a connection + * between the local and remote CPorts (including + * configuring the switch to allow them to communicate). + */ + gmod->dev.parent = hd->parent; gmod->dev.driver = NULL; gmod->dev.bus = &greybus_bus_type; @@ -275,54 +229,6 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, device_initialize(&gmod->dev); dev_set_name(&gmod->dev, "%d", module_id); - size -= sizeof(manifest->header); - data += sizeof(manifest->header); - while (size > 0) { - struct greybus_descriptor *desc; - u16 desc_size; - size_t data_size; - - if (size < sizeof(desc->header)) { - dev_err(hd->parent, "remaining size %d too small\n", - size); - goto error; - } - desc = (struct greybus_descriptor *)data; - desc_size = le16_to_cpu(desc->header.size); - if (size < desc_size) { - dev_err(hd->parent, "descriptor size %d too big\n", - desc_size); - goto error; - } - data_size = (size_t)desc_size - sizeof(desc->header); - - switch (le16_to_cpu(desc->header.type)) { - case GREYBUS_TYPE_DEVICE: - break; - - case GREYBUS_TYPE_MODULE: - break; - - case GREYBUS_TYPE_STRING: - retval = create_string(gmod, &desc->string, data_size); - break; - - case GREYBUS_TYPE_CPORT: - retval = create_cport(gmod, &desc->cport, data_size); - break; - - case GREYBUS_TYPE_INVALID: - default: - dev_err(hd->parent, "invalid descriptor type %d\n", - desc->header.type); - goto error; - } - if (retval) - goto error; - size -= desc_size; - data += desc_size; - } - retval = gb_init_subdevs(gmod, &fake_greybus_module_id); if (retval) goto error; -- cgit v0.10.2 From b05890db5e75aa0627f3f5d2241cc90fc399a697 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 2 Oct 2014 12:30:01 -0500 Subject: greybus: fix connection header declarations Changes to the create/destroy connection functions were not properly reflected in the header file. Fix that. There's also no need to include anything other than "greybus.h". Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index c653c95..6094fb4 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -12,7 +12,6 @@ #include #include "greybus.h" -#include "function.h" struct gb_connection { struct gb_function *function; @@ -25,9 +24,9 @@ struct gb_connection { atomic_t op_cycle; }; -bool gb_connection_setup(struct greybus_host_device *hd, u16 cport_id, - struct gb_function *function); -void gb_connection_teardown(struct gb_connection *connection); +struct gb_connection *gb_connection_create(struct greybus_host_device *hd, + u16 cport_id, struct gb_function *function); +void gb_connection_destroy(struct gb_connection *connection); u16 gb_connection_op_id(struct gb_connection *connection); -- cgit v0.10.2 From 63cc932b02bc5e697b5ba8f04a5d846b61f38879 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 2 Oct 2014 12:30:02 -0500 Subject: greybus: October 1 updates Update the definitions in "greybus_manifest.h" to reflect the changes to the Greybus specification made on October 1. They are: - renaming "device" to be "interface" - renumbering greybus descriptor type - eliminating the notion of a "function" - defining a CPort's protocol in the CPort descriptor - having a "class" take on the types previously used for "function" - renaming "serial number" to be "unique id" (for now) - relying on an interface's maximum cport id to determine how much device+cport address space the interface consumes - adding a simple class descriptor - renaming gb_interface->interface_id to be gb_interface->id This also reorders some things to match ordering in the document, and adds some commentary for the various structures. Since greybus_function_type is gone, we eliminate the "type" field from a function structure. (Functions are going away, next.) Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/function.c b/drivers/staging/greybus/function.c index b06265c..bfc9ac7 100644 --- a/drivers/staging/greybus/function.c +++ b/drivers/staging/greybus/function.c @@ -22,7 +22,7 @@ static DEFINE_SPINLOCK(gb_functions_lock); * pointer if a failure occurs due to memory exhaustion. */ struct gb_function *gb_function_create(struct gb_interface *interface, - u16 cport_id, enum greybus_function_type type) + u16 cport_id) { struct gb_function *function; @@ -32,7 +32,6 @@ struct gb_function *gb_function_create(struct gb_interface *interface, function->interface = interface; /* XXX refcount? */ function->cport_id = cport_id; - function->type = type; spin_lock_irq(&gb_functions_lock); list_add_tail(&function->links, &interface->functions); diff --git a/drivers/staging/greybus/function.h b/drivers/staging/greybus/function.h index 379ffcd..e1b30c5 100644 --- a/drivers/staging/greybus/function.h +++ b/drivers/staging/greybus/function.h @@ -12,14 +12,12 @@ struct gb_function { struct gb_interface *interface; u16 cport_id; - enum greybus_function_type type; struct list_head links; /* interface->functions */ }; struct gb_function *gb_function_create(struct gb_interface *interface, - u16 cport_id, - enum greybus_function_type function_type); + u16 cport_id); void gb_function_destroy(struct gb_function *function); #endif /* __FUNCTION_H */ diff --git a/drivers/staging/greybus/greybus_id.h b/drivers/staging/greybus/greybus_id.h index 8b3bce6..f8e7b38 100644 --- a/drivers/staging/greybus/greybus_id.h +++ b/drivers/staging/greybus/greybus_id.h @@ -13,7 +13,7 @@ struct greybus_module_id { __u16 match_flags; __u16 vendor; __u16 product; - __u64 serial_number; + __u64 unique_id; kernel_ulong_t driver_info __attribute__((aligned(sizeof(kernel_ulong_t)))); diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 6118999..35e1c5d 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -17,13 +17,24 @@ enum greybus_descriptor_type { GREYBUS_TYPE_INVALID = 0x00, GREYBUS_TYPE_MODULE = 0x01, - GREYBUS_TYPE_DEVICE = 0x02, - GREYBUS_TYPE_CLASS = 0x03, - GREYBUS_TYPE_STRING = 0x04, - GREYBUS_TYPE_CPORT = 0x05, + GREYBUS_TYPE_STRING = 0x02, + GREYBUS_TYPE_INTERFACE = 0x03, + GREYBUS_TYPE_CPORT = 0x04, + GREYBUS_TYPE_CLASS = 0x05, }; -enum greybus_function_type { +enum greybus_protocol { + GREYBUS_PROTOCOL_CONTROL = 0x00, + GREYBUS_PROTOCOL_AP = 0x01, + GREYBUS_PROTOCOL_GPIO = 0x02, + GREYBUS_PROTOCOL_I2C = 0x03, + GREYBUS_PROTOCOL_UART = 0x04, + GREYBUS_PROTOCOL_HID = 0x05, + /* ... */ + GREYBUS_PROTOCOL_VENDOR = 0xff, +}; + +enum greybus_class_type { GREYBUS_FUNCTION_CONTROL = 0x00, GREYBUS_FUNCTION_USB = 0x01, GREYBUS_FUNCTION_GPIO = 0x02, @@ -48,57 +59,71 @@ struct greybus_descriptor_module { __le16 vendor; __le16 product; __le16 version; - __le64 serial_number; __u8 vendor_stringid; __u8 product_stringid; + __le64 unique_id; +}; + +/* + * The string in a string descriptor is not NUL-terminated. The + * size of the descriptor will be rounded up to a multiple of 4 + * bytes, by padding the string with 0x00 bytes if necessary. + */ +struct greybus_descriptor_string { + __u8 length; + __u8 id; + __u8 string[0]; }; /* - * A UniPro device normally supports a range of 32 CPorts (0..31). - * It is possible to support more than this by having a UniPro - * switch treat one device as if it were more than one. E.g., - * allocate 3 device ids (rather than the normal--1) to physical - * device 5, and configure the switch to route all packets destined - * for "encoded" device ids 5, 6, and 7 to physical device 5. - * Device 5 uses the encoded device id in incoming UniPro packets to - * determine which bank of 32 CPorts should receive the UniPro - * segment. + * An interface descriptor simply defines a module-unique id for + * each interface present on a module. Its sole purpose is to allow + * CPort descriptors to specify which interface they are associated + * with. Normally there's only one interface, with id 0. The + * second one must have id 1, and so on consecutively. * - * The "scale" field in this structure is used to define the number - * of encoded device ids should be allocated for this physical - * device. Scale is normally 1, to represent 32 available CPorts. - * A scale value 2 represents up to 64 CPorts; scale value 3 - * represents up to 96 CPorts, and so on. + * The largest CPort id associated with an interface (defined by a + * CPort descriptor in the manifest) is used to determine how to + * encode the device id and module number in UniPro packets + * that use the interface. */ struct greybus_descriptor_interface { __u8 id; /* module-relative id (0..) */ - __u8 scale; /* indicates range of of CPorts supported */ - /* UniPro gear, number of in/out lanes */ }; +/* + * A CPort descriptor indicates the id of the interface within the + * module it's associated with, along with the CPort id used to + * address the CPort. The protocol defines the format of messages + * exchanged using the CPort. + */ struct greybus_descriptor_cport { + __u8 interface; __le16 id; - __u8 function_type; /* enum greybus_function_type */ + __u8 protocol; /* enum greybus_protocol */ }; -struct greybus_descriptor_string { - __u8 length; - __u8 id; - __u8 string[0]; +/* + * A class descriptor defines functionality supplied by a module. + * Beyond that, not much else is defined yet... + */ +struct greybus_descriptor_class { + __u8 class; /* enum greybus_class_type */ }; struct greybus_descriptor_header { __le16 size; - __u8 type; /* enum greybus_descriptor_type */ + __u8 type; /* enum greybus_descriptor_type */ }; struct greybus_descriptor { - struct greybus_descriptor_header header; + struct greybus_descriptor_header header; union { struct greybus_descriptor_module module; struct greybus_descriptor_string string; struct greybus_descriptor_interface interface; struct greybus_descriptor_cport cport; + struct greybus_descriptor_class class; }; }; diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index dc7d009..a2c2f05 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -32,7 +32,7 @@ gb_interface_create(struct gb_module *gmod, u8 interface_id) return NULL; interface->gmod = gmod; /* XXX refcount? */ - interface->interface_id = interface_id; + interface->id = interface_id; INIT_LIST_HEAD(&interface->functions); spin_lock_irq(&gb_interfaces_lock); diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 7c3feb7..7a4b3704 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -13,7 +13,7 @@ struct gb_interface { struct gb_module *gmod; - u8 interface_id; + u8 id; struct list_head functions; struct list_head links; /* module->interfaces */ diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index bae260f..4066547 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -80,11 +80,6 @@ static int identify_descriptor(struct greybus_descriptor *desc, size_t size) return -EINVAL; } break; - case GREYBUS_TYPE_DEVICE: - break; - case GREYBUS_TYPE_CLASS: - pr_err("class descriptor found (ignoring)\n"); - break; case GREYBUS_TYPE_STRING: expected_size = sizeof(struct greybus_descriptor_header); expected_size += sizeof(struct greybus_descriptor_string); @@ -95,6 +90,8 @@ static int identify_descriptor(struct greybus_descriptor *desc, size_t size) return -EINVAL; } break; + case GREYBUS_TYPE_INTERFACE: + break; case GREYBUS_TYPE_CPORT: if (desc_size < sizeof(struct greybus_descriptor_cport)) { pr_err("cport descriptor too small (%u)\n", @@ -102,6 +99,9 @@ static int identify_descriptor(struct greybus_descriptor *desc, size_t size) return -EINVAL; } break; + case GREYBUS_TYPE_CLASS: + pr_warn("class descriptor found (ignoring)\n"); + break; case GREYBUS_TYPE_INVALID: default: pr_err("invalid descriptor type (%hhu)\n", desc_header->type); @@ -183,7 +183,7 @@ u32 gb_manifest_parse_cports(struct gb_interface *interface) while (true) { struct manifest_desc *descriptor; struct greybus_descriptor_cport *desc_cport; - enum greybus_function_type function_type; + enum greybus_protocol protocol; u16 cport_id; bool found; @@ -191,19 +191,20 @@ u32 gb_manifest_parse_cports(struct gb_interface *interface) found = false; list_for_each_entry(descriptor, &manifest_descs, links) { if (descriptor->type == GREYBUS_TYPE_CPORT) { - found = true; - break; + desc_cport = descriptor->data; + if (desc_cport->interface == interface->id) { + found = true; + break; + } } } if (!found) break; /* Found one. Set up its function structure */ - desc_cport = descriptor->data; - function_type = - (enum greybus_function_type)desc_cport->function_type; + protocol = (enum greybus_protocol)desc_cport->protocol; cport_id = le16_to_cpu(desc_cport->id); - if (!gb_function_create(interface, cport_id, function_type)) + if (!gb_function_create(interface, cport_id)) return 0; /* Error */ count++; @@ -231,7 +232,7 @@ static u32 gb_manifest_parse_interfaces(struct gb_module *gmod) /* Find an interface descriptor */ list_for_each_entry(descriptor, &manifest_descs, links) { - if (descriptor->type == GREYBUS_TYPE_DEVICE) { + if (descriptor->type == GREYBUS_TYPE_INTERFACE) { found = true; break; } @@ -284,7 +285,7 @@ struct gb_module *gb_manifest_parse_module(struct manifest_desc *module_desc) gmod->vendor = le16_to_cpu(desc_module->vendor); gmod->product = le16_to_cpu(desc_module->product); gmod->version = le16_to_cpu(desc_module->version); - gmod->serial_number = le64_to_cpu(desc_module->serial_number); + gmod->unique_id = le64_to_cpu(desc_module->unique_id); /* Release the module descriptor, now that we're done with it */ release_manifest_descriptor(module_desc); diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index 6618d21..1970e7b 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -23,7 +23,7 @@ static int gb_module_match_one_id(struct gb_module *gmod, return 0; if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_SERIAL) && - (id->serial_number != gmod->serial_number)) + (id->unique_id != gmod->unique_id)) return 0; return 1; @@ -35,7 +35,7 @@ const struct greybus_module_id *gb_module_match_id(struct gb_module *gmod, if (id == NULL) return NULL; - for (; id->vendor || id->product || id->serial_number || + for (; id->vendor || id->product || id->unique_id || id->driver_info; id++) { if (gb_module_match_one_id(gmod, id)) return id; diff --git a/drivers/staging/greybus/module.h b/drivers/staging/greybus/module.h index 326176a..7b01950 100644 --- a/drivers/staging/greybus/module.h +++ b/drivers/staging/greybus/module.h @@ -24,9 +24,9 @@ struct gb_module { u16 vendor; u16 product; u16 version; - u64 serial_number; char *vendor_string; char *product_string; + u64 unique_id; int num_cports; int num_strings; diff --git a/drivers/staging/greybus/sysfs.c b/drivers/staging/greybus/sysfs.c index f969d90..2777b8c 100644 --- a/drivers/staging/greybus/sysfs.c +++ b/drivers/staging/greybus/sysfs.c @@ -40,7 +40,7 @@ static ssize_t module_serial_number_show(struct device *dev, { struct gb_module *gmod = to_gb_module(dev); - return sprintf(buf, "%llX\n", (unsigned long long)gmod->serial_number); + return sprintf(buf, "%llX\n", (unsigned long long)gmod->unique_id); } static DEVICE_ATTR_RO(module_serial_number); @@ -86,7 +86,7 @@ static umode_t module_attrs_are_visible(struct kobject *kobj, return mode; if (gmod->vendor || gmod->product || gmod->version) return mode; - if (gmod->serial_number) + if (gmod->unique_id) return mode; return 0; -- cgit v0.10.2 From 1bb3c724e85b3d13f6b2e455fb60c6e664f8f28d Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 2 Oct 2014 12:30:03 -0500 Subject: greybus: create host device cport id map A Greybus host device has a pool of CPort Ids it can use. When we establish a connection with a CPort on another module we will need to allocate one from those that are available. This patch adds a bitmap to the greybus host device structure that allows cport ids to be allocated and freed as needed. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index d9bbc67..9669a34 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -30,6 +30,8 @@ int greybus_disabled(void) } EXPORT_SYMBOL_GPL(greybus_disabled); +static spinlock_t cport_id_map_lock; + static int greybus_module_match(struct device *dev, struct device_driver *drv) { struct greybus_driver *driver = to_greybus_driver(dev->driver); @@ -261,6 +263,69 @@ void greybus_remove_device(struct gb_module *gmod) static DEFINE_MUTEX(hd_mutex); +/* + * Allocate an available CPort Id for use on the given host device. + * Returns the CPort Id, or CPORT_ID_BAD of none remain. + * + * The lowest-available id is returned, so the first call is + * guaranteed to allocate CPort Id 0. + */ +u16 greybus_hd_cport_id_alloc(struct greybus_host_device *hd) +{ + unsigned long cport_id; + + /* If none left, return BAD */ + if (hd->cport_id_count == HOST_DEV_CPORT_ID_MAX) + return CPORT_ID_BAD; + + spin_lock_irq(&cport_id_map_lock); + cport_id = find_next_zero_bit(hd->cport_id_map, hd->cport_id_count, + hd->cport_id_next_free); + if (cport_id < hd->cport_id_count) { + hd->cport_id_next_free = cport_id + 1; /* Success */ + hd->cport_id_count++; + } else { + /* Lost a race for the last one */ + if (hd->cport_id_count != HOST_DEV_CPORT_ID_MAX) { + pr_err("bad cport_id_count in alloc"); + hd->cport_id_count = HOST_DEV_CPORT_ID_MAX; + } + cport_id = CPORT_ID_BAD; + } + spin_unlock_irq(&cport_id_map_lock); + + return cport_id; +} + +/* + * Free a previously-allocated CPort Id on the given host device. + */ +void greybus_hd_cport_id_free(struct greybus_host_device *hd, u16 cport_id) +{ + if (cport_id >= HOST_DEV_CPORT_ID_MAX) { + pr_err("bad cport_id %hu\n", cport_id); + return; + } + if (!hd->cport_id_count) { + pr_err("too many cport_id frees\n"); + return; + } + + spin_lock_irq(&cport_id_map_lock); + if (test_and_clear_bit(cport_id, hd->cport_id_map)) { + if (hd->cport_id_count) { + hd->cport_id_count--; + if (cport_id < hd->cport_id_next_free) + hd->cport_id_next_free = cport_id; + } else { + pr_err("bad cport_id_count in free"); + } + } else { + pr_err("duplicate cport_id %hu free\n", cport_id); + } + spin_unlock_irq(&cport_id_map_lock); +} + static void free_hd(struct kref *kref) { struct greybus_host_device *hd; @@ -284,6 +349,13 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver hd->driver = driver; INIT_LIST_HEAD(&hd->modules); + /* Pre-allocate CPort 0 for control stuff. XXX */ + if (greybus_hd_cport_id_alloc(hd) != 0) { + pr_err("couldn't allocate cport 0\n"); + kfree(hd); + return NULL; + } + return hd; } EXPORT_SYMBOL_GPL(greybus_create_hd); @@ -299,6 +371,9 @@ static int __init gb_init(void) { int retval; + BUILD_BUG_ON(HOST_DEV_CPORT_ID_MAX >= (long)CPORT_ID_BAD); + spin_lock_init(&cport_id_map_lock); + retval = gb_debugfs_init(); if (retval) { pr_err("debugfs failed\n"); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index fabd74e4..077daf0a 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -18,6 +18,7 @@ #include #include +#include "kernel_ver.h" #include "greybus_id.h" #include "greybus_manifest.h" #include "manifest.h" @@ -44,6 +45,15 @@ .match_flags = GREYBUS_DEVICE_ID_MATCH_SERIAL, \ .serial_number = (s), +/* XXX I couldn't get my Kconfig file to be noticed for out-of-tree build */ +#ifndef CONFIG_HOST_DEV_CPORT_ID_MAX +#define CONFIG_HOST_DEV_CPORT_ID_MAX 128 +#endif /* !CONFIG_HOST_DEV_CPORT_ID_MAX */ + +/* Maximum number of CPorts usable by a host device */ +/* XXX This should really be determined by the AP module manifest */ +#define HOST_DEV_CPORT_ID_MAX CONFIG_HOST_DEV_CPORT_ID_MAX +#define CPORT_ID_BAD U16_MAX /* UniPro max id is 4095 */ /* gbuf @@ -185,10 +195,18 @@ struct greybus_host_device { struct list_head modules; struct list_head connections; + spinlock_t cport_id_map_lock; + DECLARE_BITMAP(cport_id_map, HOST_DEV_CPORT_ID_MAX); + u16 cport_id_count; /* How many have been allocated */ + u16 cport_id_next_free; /* Where to start checking anyway */ + /* Private data for the host driver */ unsigned long hd_priv[0] __attribute__ ((aligned(sizeof(s64)))); }; +u16 greybus_hd_cport_id_alloc(struct greybus_host_device *hd); +void greybus_hd_cport_id_free(struct greybus_host_device *hd, u16 cport_id); + struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *host_driver, struct device *parent); void greybus_remove_hd(struct greybus_host_device *hd); -- cgit v0.10.2 From 9e8a6860f5d113b42334b27f12217ee9fb9970f9 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 2 Oct 2014 12:30:04 -0500 Subject: greybus: allocate connection host cport id Allocate a cport id from the host device whenever creating a connection. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index fa5ab5d..b16ac4c 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -23,7 +23,7 @@ * pointer otherwise. */ struct gb_connection *gb_connection_create(struct greybus_host_device *hd, - u16 cport_id, struct gb_function *function) + struct gb_function *function) { struct gb_connection *connection; @@ -31,8 +31,13 @@ struct gb_connection *gb_connection_create(struct greybus_host_device *hd, if (!connection) return NULL; + connection->cport_id = greybus_hd_cport_id_alloc(hd); + if (connection->cport_id == CPORT_ID_BAD) { + kfree(connection); + return NULL; + } + connection->hd = hd; /* XXX refcount? */ - connection->cport_id = cport_id; connection->function = function; /* XXX refcount? */ INIT_LIST_HEAD(&connection->operations); atomic_set(&connection->op_cycle, 0); @@ -51,6 +56,7 @@ void gb_connection_destroy(struct gb_connection *connection) /* XXX Need to wait for any outstanding requests to complete */ WARN_ON(!list_empty(&connection->operations)); + greybus_hd_cport_id_free(connection->hd, connection->cport_id); /* kref_put(function); */ /* kref_put(hd); */ kfree(connection); diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 6094fb4..f06ff92 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -25,7 +25,7 @@ struct gb_connection { }; struct gb_connection *gb_connection_create(struct greybus_host_device *hd, - u16 cport_id, struct gb_function *function); + struct gb_function *function); void gb_connection_destroy(struct gb_connection *connection); u16 gb_connection_op_id(struct gb_connection *connection); -- cgit v0.10.2 From cd345074bb7cb2c2bdd6bc3b042c38a74128ed6c Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 2 Oct 2014 12:30:05 -0500 Subject: greybus: get rid of functions now... We decided yesterday that we would no longer support the notion of a "function." Instead, a connection will simply exist between the AP and an interface on a module (and a CPort Id on each end). What was previously considered the "function type" will now be handled as the "protocol" associated with the connection. Update gb_connection_create() to take just the interface and a cport id associated with that interface. Right now every module points back to a host device, so for now we'll establish the connection back to that. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index a303f81..42a3944 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -6,7 +6,6 @@ greybus-y := core.o \ manifest.o \ module.o \ interface.o \ - function.o \ connection.o \ operation.o \ i2c-gb.o \ diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index b16ac4c..f3f774d 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -22,23 +22,25 @@ * Returns a pointer to the new connection if successful, or a null * pointer otherwise. */ -struct gb_connection *gb_connection_create(struct greybus_host_device *hd, - struct gb_function *function) +struct gb_connection *gb_connection_create(struct gb_interface *interface, + u16 cport_id) { struct gb_connection *connection; + struct greybus_host_device *hd; connection = kzalloc(sizeof(*connection), GFP_KERNEL); if (!connection) return NULL; - connection->cport_id = greybus_hd_cport_id_alloc(hd); - if (connection->cport_id == CPORT_ID_BAD) { + hd = interface->gmod->hd; + connection->hd_cport_id = greybus_hd_cport_id_alloc(hd); + if (connection->hd_cport_id == CPORT_ID_BAD) { kfree(connection); return NULL; } - connection->hd = hd; /* XXX refcount? */ - connection->function = function; /* XXX refcount? */ + connection->interface = interface; /* XXX refcount? */ + connection->interface_cport_id = cport_id; INIT_LIST_HEAD(&connection->operations); atomic_set(&connection->op_cycle, 0); @@ -56,9 +58,9 @@ void gb_connection_destroy(struct gb_connection *connection) /* XXX Need to wait for any outstanding requests to complete */ WARN_ON(!list_empty(&connection->operations)); - greybus_hd_cport_id_free(connection->hd, connection->cport_id); - /* kref_put(function); */ - /* kref_put(hd); */ + greybus_hd_cport_id_free(connection->hd, connection->hd_cport_id); + /* kref_put(connection->interface); */ + /* kref_put(connection->hd); */ kfree(connection); } diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index f06ff92..530d645 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -14,18 +14,21 @@ #include "greybus.h" struct gb_connection { - struct gb_function *function; struct greybus_host_device *hd; - u16 cport_id; /* Host side */ + struct gb_interface *interface; + u16 hd_cport_id; + u16 interface_cport_id; - struct list_head host_links; + struct list_head hd_links; + struct list_head interface_links; + /* protocol */ struct list_head operations; atomic_t op_cycle; }; -struct gb_connection *gb_connection_create(struct greybus_host_device *hd, - struct gb_function *function); +struct gb_connection *gb_connection_create(struct gb_interface *interface, + u16 cport_id); void gb_connection_destroy(struct gb_connection *connection); u16 gb_connection_op_id(struct gb_connection *connection); diff --git a/drivers/staging/greybus/function.c b/drivers/staging/greybus/function.c deleted file mode 100644 index bfc9ac7..0000000 --- a/drivers/staging/greybus/function.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Greybus functions - * - * Copyright 2014 Google Inc. - * - * Released under the GPLv2 only. - */ - -#include "greybus.h" - -/* XXX This could be per-host device or per-module or per-interface */ -static DEFINE_SPINLOCK(gb_functions_lock); - -/* - * A Greybus function generically defines an entity associated with - * a CPort within a module. Each function has a type (e.g. i2c, - * GPIO, etc.) that defines how it behaves and how the AP interacts - * with it. - * - * Create a gb_function structure to represent a discovered - * function. Returns a pointer to the new function or a null - * pointer if a failure occurs due to memory exhaustion. - */ -struct gb_function *gb_function_create(struct gb_interface *interface, - u16 cport_id) -{ - struct gb_function *function; - - function = kzalloc(sizeof(*function), GFP_KERNEL); - if (!function) - return NULL; - - function->interface = interface; /* XXX refcount? */ - function->cport_id = cport_id; - - spin_lock_irq(&gb_functions_lock); - list_add_tail(&function->links, &interface->functions); - spin_unlock_irq(&gb_functions_lock); - - return function; -} - -/* - * Tear down a previously set up function. - */ -void gb_function_destroy(struct gb_function *function) -{ - if (WARN_ON(!function)) - return; - - spin_lock_irq(&gb_functions_lock); - list_del(&function->links); - spin_unlock_irq(&gb_functions_lock); - - /* kref_put(gmod); */ - kfree(function); -} diff --git a/drivers/staging/greybus/function.h b/drivers/staging/greybus/function.h deleted file mode 100644 index e1b30c5..0000000 --- a/drivers/staging/greybus/function.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Greybus functions - * - * Copyright 2014 Google Inc. - * - * Released under the GPLv2 only. - */ - -#ifndef __FUNCTION_H -#define __FUNCTION_H - -struct gb_function { - struct gb_interface *interface; - u16 cport_id; - - struct list_head links; /* interface->functions */ -}; - -struct gb_function *gb_function_create(struct gb_interface *interface, - u16 cport_id); -void gb_function_destroy(struct gb_function *function); - -#endif /* __FUNCTION_H */ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 077daf0a..0813201 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -24,7 +24,6 @@ #include "manifest.h" #include "module.h" #include "interface.h" -#include "function.h" #include "connection.h" #include "operation.h" diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 4066547..6411c26 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -204,7 +204,7 @@ u32 gb_manifest_parse_cports(struct gb_interface *interface) /* Found one. Set up its function structure */ protocol = (enum greybus_protocol)desc_cport->protocol; cport_id = le16_to_cpu(desc_cport->id); - if (!gb_function_create(interface, cport_id)) + if (!gb_connection_create(interface, cport_id)) return 0; /* Error */ count++; diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 5cb23aa..b930d24 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -124,8 +124,8 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, /* Our buffer holds a header in addition to the requested payload */ size += sizeof(*header); - gbuf = greybus_alloc_gbuf(connection->function->interface->gmod, - connection->cport_id, + gbuf = greybus_alloc_gbuf(connection->interface->gmod, + connection->hd_cport_id, gbuf_out_callback, size, GFP_KERNEL, operation); if (gbuf) { -- cgit v0.10.2 From ad1c449eb905ac1bf819afe9b799c11a6cf304a6 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 2 Oct 2014 12:30:06 -0500 Subject: greybus: record connection protocol Record the protocol association with a connection when it gets created. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index f3f774d..d63048c 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -23,7 +23,7 @@ * pointer otherwise. */ struct gb_connection *gb_connection_create(struct gb_interface *interface, - u16 cport_id) + u16 cport_id, enum greybus_protocol protocol) { struct gb_connection *connection; struct greybus_host_device *hd; @@ -41,6 +41,8 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, connection->hd = hd; /* XXX refcount? */ connection->interface = interface; /* XXX refcount? */ connection->interface_cport_id = cport_id; + connection->protocol = protocol; + INIT_LIST_HEAD(&connection->operations); atomic_set(&connection->op_cycle, 0); diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 530d645..15bdc81 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -21,14 +21,14 @@ struct gb_connection { struct list_head hd_links; struct list_head interface_links; - /* protocol */ + enum greybus_protocol protocol; struct list_head operations; atomic_t op_cycle; }; struct gb_connection *gb_connection_create(struct gb_interface *interface, - u16 cport_id); + u16 cport_id, enum greybus_protocol protocol); void gb_connection_destroy(struct gb_connection *connection); u16 gb_connection_op_id(struct gb_connection *connection); diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 6411c26..a694c88 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -204,7 +204,7 @@ u32 gb_manifest_parse_cports(struct gb_interface *interface) /* Found one. Set up its function structure */ protocol = (enum greybus_protocol)desc_cport->protocol; cport_id = le16_to_cpu(desc_cport->id); - if (!gb_connection_create(interface, cport_id)) + if (!gb_connection_create(interface, cport_id, protocol)) return 0; /* Error */ count++; -- cgit v0.10.2 From 322543a335c9dc9393a7472ce0b53a428ab3decd Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 2 Oct 2014 21:25:21 -0700 Subject: greybus: operation: fix endian issue in the operation message header size field. diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index b930d24..fe2f1a7 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -139,7 +139,7 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, operation->gbuf = gbuf; header = (struct gb_operation_msg_hdr *)&gbuf->transfer_buffer; header->id = 0; - header->size = size; + header->size = cpu_to_le16(size); operation->payload = (char *)header + sizeof(*header); operation->callback = NULL; /* set at submit time */ -- cgit v0.10.2 From 2f30d9ffeee15fb655f1f5e288e69e46a3059b39 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 2 Oct 2014 21:26:26 -0700 Subject: greybus: manifest: some minor sparse warning fixups. diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index a694c88..ad7922a 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -176,7 +176,7 @@ static char *gb_string_get(u8 string_id) * for the functions that use them. Returns the number of interfaces * set up for the given module, or 0 if there is an error. */ -u32 gb_manifest_parse_cports(struct gb_interface *interface) +static u32 gb_manifest_parse_cports(struct gb_interface *interface) { u32 count = 0; @@ -259,7 +259,7 @@ static u32 gb_manifest_parse_interfaces(struct gb_module *gmod) return count; } -struct gb_module *gb_manifest_parse_module(struct manifest_desc *module_desc) +static struct gb_module *gb_manifest_parse_module(struct manifest_desc *module_desc) { struct greybus_descriptor *desc = module_desc->data; struct greybus_descriptor_module *desc_module = &desc->module; -- cgit v0.10.2 From 32dff13d21120cfbf6196347f7bc74e9236fce1e Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Fri, 3 Oct 2014 13:38:24 -0400 Subject: greybus: fix gb_add_module() by enabling the device_add() Without the gb_module device being added, we have no parent device for any of the greybus subdevs to be added. Do the device_add() before creating subdevs as we need it then to register any children in the various greybus protocol drivers. Signed-off-by: Matt Porter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 9669a34..8237f5f 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -231,14 +231,20 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, device_initialize(&gmod->dev); dev_set_name(&gmod->dev, "%d", module_id); - retval = gb_init_subdevs(gmod, &fake_greybus_module_id); + retval = device_add(&gmod->dev); if (retval) goto error; - // FIXME device_add(&gmod->dev); + retval = gb_init_subdevs(gmod, &fake_greybus_module_id); + if (retval) + goto error_subdevs; //return gmod; return; + +error_subdevs: + device_del(&gmod->dev); + error: put_device(&gmod->dev); greybus_module_release(&gmod->dev); -- cgit v0.10.2 From d7f9be4867e060712b6d9aaa1a8c98d15976c71d Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Fri, 3 Oct 2014 14:32:35 -0400 Subject: greybus: implement core module removal path Implement gb_remove_module() by finding the gb_module to be removed via the supplied module_id. Add support for removing the actual device into greybus_remove_device() after all the subdevs are disconnected. Signed-off-by: Matt Porter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 8237f5f..8811f35 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -252,7 +252,19 @@ error: void gb_remove_module(struct greybus_host_device *hd, u8 module_id) { - // FIXME should be the remove_device call... + struct gb_module *gmod; + bool found = false; + + list_for_each_entry(gmod, &hd->modules, links) + if (gmod->module_id == module_id) { + found = true; + break; + } + + if (found) + greybus_remove_device(gmod); + else + dev_err(hd->parent, "module id %d remove error\n", module_id); } void greybus_remove_device(struct gb_module *gmod) @@ -264,7 +276,8 @@ void greybus_remove_device(struct gb_module *gmod) gb_tty_disconnect(gmod); gb_battery_disconnect(gmod); - // FIXME - device_remove(&gmod->dev); + device_del(&gmod->dev); + put_device(&gmod->dev); } static DEFINE_MUTEX(hd_mutex); -- cgit v0.10.2 From 748e1230cb921369738104415ed9352e81ccc413 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 3 Oct 2014 14:14:22 -0500 Subject: greybus: fix some hasty bugs Fix some omissions found in the code. - initialize and use the host device connections list - rename the interface connections list (was "functions") - use the interface connections list - define a spinlock protecting the connections lists - declare gb_operation_submit() in "operation.h" And the cport id map lock is per-host device, it's shared across all host devices. There's no need for one in struct greybus_host_device. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index d63048c..806eb8c 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -11,6 +11,8 @@ #include "kernel_ver.h" #include "greybus.h" +static DEFINE_SPINLOCK(gb_connections_lock); + /* * Set up a Greybus connection, representing the bidirectional link * between a CPort on a (local) Greybus host device and a CPort on @@ -43,6 +45,11 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, connection->interface_cport_id = cport_id; connection->protocol = protocol; + spin_lock_irq(&gb_connections_lock); + list_add_tail(&connection->hd_links, &hd->connections); + list_add_tail(&connection->interface_links, &interface->connections); + spin_unlock_irq(&gb_connections_lock); + INIT_LIST_HEAD(&connection->operations); atomic_set(&connection->op_cycle, 0); @@ -60,6 +67,11 @@ void gb_connection_destroy(struct gb_connection *connection) /* XXX Need to wait for any outstanding requests to complete */ WARN_ON(!list_empty(&connection->operations)); + spin_lock_irq(&gb_connections_lock); + list_del(&connection->hd_links); + list_del(&connection->interface_links); + spin_unlock_irq(&gb_connections_lock); + greybus_hd_cport_id_free(connection->hd, connection->hd_cport_id); /* kref_put(connection->interface); */ /* kref_put(connection->hd); */ diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 8811f35..16100e7 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -298,9 +298,9 @@ u16 greybus_hd_cport_id_alloc(struct greybus_host_device *hd) return CPORT_ID_BAD; spin_lock_irq(&cport_id_map_lock); - cport_id = find_next_zero_bit(hd->cport_id_map, hd->cport_id_count, + cport_id = find_next_zero_bit(hd->cport_id_map, HOST_DEV_CPORT_ID_MAX, hd->cport_id_next_free); - if (cport_id < hd->cport_id_count) { + if (cport_id < HOST_DEV_CPORT_ID_MAX) { hd->cport_id_next_free = cport_id + 1; /* Success */ hd->cport_id_count++; } else { @@ -367,6 +367,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver hd->parent = parent; hd->driver = driver; INIT_LIST_HEAD(&hd->modules); + INIT_LIST_HEAD(&hd->connections); /* Pre-allocate CPort 0 for control stuff. XXX */ if (greybus_hd_cport_id_alloc(hd) != 0) { diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 0813201..460ace5 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -194,7 +194,6 @@ struct greybus_host_device { struct list_head modules; struct list_head connections; - spinlock_t cport_id_map_lock; DECLARE_BITMAP(cport_id_map, HOST_DEV_CPORT_ID_MAX); u16 cport_id_count; /* How many have been allocated */ u16 cport_id_next_free; /* Where to start checking anyway */ diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index a2c2f05..b9dd930 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -33,7 +33,7 @@ gb_interface_create(struct gb_module *gmod, u8 interface_id) interface->gmod = gmod; /* XXX refcount? */ interface->id = interface_id; - INIT_LIST_HEAD(&interface->functions); + INIT_LIST_HEAD(&interface->connections); spin_lock_irq(&gb_interfaces_lock); list_add_tail(&interface->links, &gmod->interfaces); diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 7a4b3704..9c9ffe7 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -14,7 +14,7 @@ struct gb_interface { struct gb_module *gmod; u8 id; - struct list_head functions; + struct list_head connections; struct list_head links; /* module->interfaces */ }; -- cgit v0.10.2 From 063e6ec221b6a68d28642e6653ae7cef2fdb11fd Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 3 Oct 2014 14:14:23 -0500 Subject: greybus: fix greybus_class_type symbol names These were inadvertently not fixed when the type name was changed. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 35e1c5d..d31eb68 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -35,20 +35,20 @@ enum greybus_protocol { }; enum greybus_class_type { - GREYBUS_FUNCTION_CONTROL = 0x00, - GREYBUS_FUNCTION_USB = 0x01, - GREYBUS_FUNCTION_GPIO = 0x02, - GREYBUS_FUNCTION_SPI = 0x03, - GREYBUS_FUNCTION_UART = 0x04, - GREYBUS_FUNCTION_PWM = 0x05, - GREYBUS_FUNCTION_I2S = 0x06, - GREYBUS_FUNCTION_I2C = 0x07, - GREYBUS_FUNCTION_SDIO = 0x08, - GREYBUS_FUNCTION_HID = 0x09, - GREYBUS_FUNCTION_DISPLAY = 0x0a, - GREYBUS_FUNCTION_CAMERA = 0x0b, - GREYBUS_FUNCTION_SENSOR = 0x0c, - GREYBUS_FUNCTION_VENDOR = 0xff, + GREYBUS_CLASS_CONTROL = 0x00, + GREYBUS_CLASS_USB = 0x01, + GREYBUS_CLASS_GPIO = 0x02, + GREYBUS_CLASS_SPI = 0x03, + GREYBUS_CLASS_UART = 0x04, + GREYBUS_CLASS_PWM = 0x05, + GREYBUS_CLASS_I2S = 0x06, + GREYBUS_CLASS_I2C = 0x07, + GREYBUS_CLASS_SDIO = 0x08, + GREYBUS_CLASS_HID = 0x09, + GREYBUS_CLASS_DISPLAY = 0x0a, + GREYBUS_CLASS_CAMERA = 0x0b, + GREYBUS_CLASS_SENSOR = 0x0c, + GREYBUS_CLASS_VENDOR = 0xff, }; /* -- cgit v0.10.2 From 177404bd20fdabd77d04ad818d56ab34150fff4c Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 3 Oct 2014 14:14:24 -0500 Subject: greybus: use ida for cport id allocation The ida mechanism for allocating ids may be overkill but it works. Don't preallocate the id 0 for control. That should be done when initializing connections based on the manifest anyway. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 806eb8c..c50472d 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -14,6 +14,39 @@ static DEFINE_SPINLOCK(gb_connections_lock); /* + * Allocate an available CPort Id for use for the host side of the + * given connection. The lowest-available id is returned, so the + * first call is guaranteed to allocate CPort Id 0. + * + * Assigns the connection's hd_cport_id and returns true if successful. + * Returns false otherwise. + */ +static bool hd_connection_hd_cport_id_alloc(struct gb_connection *connection) +{ + struct ida *ida = &connection->hd->cport_id_map; + int id; + + id = ida_simple_get(ida, 0, HOST_DEV_CPORT_ID_MAX, GFP_KERNEL); + if (id < 0) + return false; + + connection->hd_cport_id = (u16)id; + + return true; +} + +/* + * Free a previously-allocated CPort Id on the given host device. + */ +static void hd_connection_hd_cport_id_free(struct gb_connection *connection) +{ + struct ida *ida = &connection->hd->cport_id_map; + + ida_simple_remove(ida, connection->hd_cport_id); + connection->hd_cport_id = CPORT_ID_BAD; +} + +/* * Set up a Greybus connection, representing the bidirectional link * between a CPort on a (local) Greybus host device and a CPort on * another Greybus module. @@ -35,8 +68,9 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, return NULL; hd = interface->gmod->hd; - connection->hd_cport_id = greybus_hd_cport_id_alloc(hd); - if (connection->hd_cport_id == CPORT_ID_BAD) { + connection->hd = hd; /* XXX refcount? */ + if (!hd_connection_hd_cport_id_alloc(connection)) { + /* kref_put(connection->hd); */ kfree(connection); return NULL; } @@ -72,7 +106,7 @@ void gb_connection_destroy(struct gb_connection *connection) list_del(&connection->interface_links); spin_unlock_irq(&gb_connections_lock); - greybus_hd_cport_id_free(connection->hd, connection->hd_cport_id); + hd_connection_hd_cport_id_free(connection); /* kref_put(connection->interface); */ /* kref_put(connection->hd); */ kfree(connection); diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 16100e7..40c8996 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -282,69 +282,6 @@ void greybus_remove_device(struct gb_module *gmod) static DEFINE_MUTEX(hd_mutex); -/* - * Allocate an available CPort Id for use on the given host device. - * Returns the CPort Id, or CPORT_ID_BAD of none remain. - * - * The lowest-available id is returned, so the first call is - * guaranteed to allocate CPort Id 0. - */ -u16 greybus_hd_cport_id_alloc(struct greybus_host_device *hd) -{ - unsigned long cport_id; - - /* If none left, return BAD */ - if (hd->cport_id_count == HOST_DEV_CPORT_ID_MAX) - return CPORT_ID_BAD; - - spin_lock_irq(&cport_id_map_lock); - cport_id = find_next_zero_bit(hd->cport_id_map, HOST_DEV_CPORT_ID_MAX, - hd->cport_id_next_free); - if (cport_id < HOST_DEV_CPORT_ID_MAX) { - hd->cport_id_next_free = cport_id + 1; /* Success */ - hd->cport_id_count++; - } else { - /* Lost a race for the last one */ - if (hd->cport_id_count != HOST_DEV_CPORT_ID_MAX) { - pr_err("bad cport_id_count in alloc"); - hd->cport_id_count = HOST_DEV_CPORT_ID_MAX; - } - cport_id = CPORT_ID_BAD; - } - spin_unlock_irq(&cport_id_map_lock); - - return cport_id; -} - -/* - * Free a previously-allocated CPort Id on the given host device. - */ -void greybus_hd_cport_id_free(struct greybus_host_device *hd, u16 cport_id) -{ - if (cport_id >= HOST_DEV_CPORT_ID_MAX) { - pr_err("bad cport_id %hu\n", cport_id); - return; - } - if (!hd->cport_id_count) { - pr_err("too many cport_id frees\n"); - return; - } - - spin_lock_irq(&cport_id_map_lock); - if (test_and_clear_bit(cport_id, hd->cport_id_map)) { - if (hd->cport_id_count) { - hd->cport_id_count--; - if (cport_id < hd->cport_id_next_free) - hd->cport_id_next_free = cport_id; - } else { - pr_err("bad cport_id_count in free"); - } - } else { - pr_err("duplicate cport_id %hu free\n", cport_id); - } - spin_unlock_irq(&cport_id_map_lock); -} - static void free_hd(struct kref *kref) { struct greybus_host_device *hd; @@ -368,13 +305,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver hd->driver = driver; INIT_LIST_HEAD(&hd->modules); INIT_LIST_HEAD(&hd->connections); - - /* Pre-allocate CPort 0 for control stuff. XXX */ - if (greybus_hd_cport_id_alloc(hd) != 0) { - pr_err("couldn't allocate cport 0\n"); - kfree(hd); - return NULL; - } + ida_init(&hd->cport_id_map); return hd; } diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 460ace5..4404d93 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -17,6 +17,7 @@ #include #include #include +#include #include "kernel_ver.h" #include "greybus_id.h" @@ -194,7 +195,7 @@ struct greybus_host_device { struct list_head modules; struct list_head connections; - DECLARE_BITMAP(cport_id_map, HOST_DEV_CPORT_ID_MAX); + struct ida cport_id_map; u16 cport_id_count; /* How many have been allocated */ u16 cport_id_next_free; /* Where to start checking anyway */ @@ -202,9 +203,6 @@ struct greybus_host_device { unsigned long hd_priv[0] __attribute__ ((aligned(sizeof(s64)))); }; -u16 greybus_hd_cport_id_alloc(struct greybus_host_device *hd); -void greybus_hd_cport_id_free(struct greybus_host_device *hd, u16 cport_id); - struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *host_driver, struct device *parent); void greybus_remove_hd(struct greybus_host_device *hd); -- cgit v0.10.2 From 937d0da83ffde769f24b5124d66f793045c5da10 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 3 Oct 2014 14:14:25 -0500 Subject: greybus: fix module setup The code that was setting up a module was not properly initializing the module data structure. Fixing this required a little rework. Now gb_add_module() (which the host device pointer and module id) allocates and initializes the structure, and passes it to gb_manifest_parse() for populating it further. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 40c8996..41fb7ca 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -203,14 +203,19 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, struct gb_module *gmod; int retval; + gmod = gb_module_create(hd, module_id); + if (!gmod) { + dev_err(hd->parent, "failed to create module\n"); + return; + } + /* * Parse the manifest and build up our data structures * representing what's in it. */ - gmod = gb_manifest_parse(data, size); - if (!gmod) { + if (!gb_manifest_parse(gmod, data, size)) { dev_err(hd->parent, "manifest error\n"); - return; + goto error; } /* @@ -246,6 +251,8 @@ error_subdevs: device_del(&gmod->dev); error: + gb_module_destroy(gmod); + put_device(&gmod->dev); greybus_module_release(&gmod->dev); } diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index ad7922a..03282fd 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -259,27 +259,20 @@ static u32 gb_manifest_parse_interfaces(struct gb_module *gmod) return count; } -static struct gb_module *gb_manifest_parse_module(struct manifest_desc *module_desc) +static bool gb_manifest_parse_module(struct gb_module *gmod, + struct manifest_desc *module_desc) { struct greybus_descriptor *desc = module_desc->data; struct greybus_descriptor_module *desc_module = &desc->module; - struct gb_module *gmod; - - gmod = kzalloc(sizeof(*gmod), GFP_KERNEL); - if (!gmod) - return NULL; /* Handle the strings first--they can fail */ gmod->vendor_string = gb_string_get(desc_module->vendor_stringid); - if (IS_ERR(gmod->vendor_string)) { - kfree(gmod); - return NULL; - } + if (IS_ERR(gmod->vendor_string)) + return false; + gmod->product_string = gb_string_get(desc_module->product_stringid); if (IS_ERR(gmod->product_string)) { - kfree(gmod->vendor_string); - kfree(gmod); - return NULL; + goto out_err; } gmod->vendor = le16_to_cpu(desc_module->vendor); @@ -293,11 +286,17 @@ static struct gb_module *gb_manifest_parse_module(struct manifest_desc *module_d /* A module must have at least one interface descriptor */ if (!gb_manifest_parse_interfaces(gmod)) { pr_err("manifest interface descriptors not valid\n"); - gb_module_destroy(gmod); - return NULL; + goto out_err; } - return gmod; + return true; +out_err: + kfree(gmod->product_string); + gmod->product_string = NULL; + kfree(gmod->vendor_string); + gmod->vendor_string = NULL; + + return false; } /* @@ -321,25 +320,23 @@ static struct gb_module *gb_manifest_parse_module(struct manifest_desc *module_d * After that we look for the module's interfaces--there must be at * least one of those. * - * Return a pointer to an initialized gb_module structure - * representing the content of the module manifest, or a null - * pointer if an error occurs. + * Returns true if parsing was successful, false otherwise. */ -struct gb_module *gb_manifest_parse(void *data, size_t size) +bool gb_manifest_parse(struct gb_module *gmod, void *data, size_t size) { struct greybus_manifest *manifest; struct greybus_manifest_header *header; struct greybus_descriptor *desc; struct manifest_desc *descriptor; - struct manifest_desc *module_desc = NULL; - struct gb_module *gmod; + struct manifest_desc *module_desc = false; u16 manifest_size; u32 found = 0; + bool result = false; /* we have to have at _least_ the manifest header */ if (size <= sizeof(manifest->header)) { pr_err("short manifest (%zu)\n", size); - return NULL; + return false; } /* Make sure the size is right */ @@ -349,7 +346,7 @@ struct gb_module *gb_manifest_parse(void *data, size_t size) if (manifest_size != size) { pr_err("manifest size mismatch %zu != %hu\n", size, manifest_size); - return NULL; + return false; } /* Validate major/minor number */ @@ -357,7 +354,7 @@ struct gb_module *gb_manifest_parse(void *data, size_t size) pr_err("manifest version too new (%hhu.%hhu > %hhu.%hhu)\n", header->version_major, header->version_minor, GREYBUS_VERSION_MAJOR, GREYBUS_VERSION_MINOR); - return NULL; + return false; } /* OK, find all the descriptors */ @@ -370,7 +367,7 @@ struct gb_module *gb_manifest_parse(void *data, size_t size) if (desc_size <= 0) { if (!desc_size) pr_err("zero-sized manifest descriptor\n"); - goto out_err; + goto out; } desc = (struct greybus_descriptor *)((char *)desc + desc_size); size -= desc_size; @@ -385,24 +382,20 @@ struct gb_module *gb_manifest_parse(void *data, size_t size) if (found != 1) { pr_err("manifest must have 1 module descriptor (%u found)\n", found); - goto out_err; + goto out; } /* Parse the module manifest, starting with the module descriptor */ - gmod = gb_manifest_parse_module(module_desc); + result = gb_manifest_parse_module(gmod, module_desc); /* * We really should have no remaining descriptors, but we * don't know what newer format manifests might leave. */ - if (!list_empty(&manifest_descs)) { + if (!list_empty(&manifest_descs)) pr_info("excess descriptors in module manifest\n"); - release_manifest_descriptors(); - } - - return gmod; -out_err: +out: release_manifest_descriptors(); - return NULL; + return false; } diff --git a/drivers/staging/greybus/manifest.h b/drivers/staging/greybus/manifest.h index 29cbf92..a1fe2c12 100644 --- a/drivers/staging/greybus/manifest.h +++ b/drivers/staging/greybus/manifest.h @@ -9,6 +9,7 @@ #ifndef __MANIFEST_H #define __MANIFEST_H -struct gb_module *gb_manifest_parse(void *data, size_t size); +struct gb_module; +bool gb_manifest_parse(struct gb_module *gmod, void *data, size_t size); #endif /* __MANIFEST_H */ -- cgit v0.10.2 From 652433f3fe97e3609acd9afcb9b50ec62f7a8d05 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 3 Oct 2014 15:05:19 -0500 Subject: greybus: gbuf: have caller set actual_length A Greybus buffer has both a transfer_buffer_size field, which is the size in bytes of the transfer buffer, and an actual_length field, which is the number of bytes in that buffer that are actually consumed. The user of the buffer--and not the buffer allocation method--should be setting the actual_length field. Stop setting the actual length on the es1-ap-usb alloc_gbuf_data method. And *do* set it in gb_operation_create(), where we can presume the operation being allocated will consume all the bytes requested. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index f23c674..3601499 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -126,7 +126,6 @@ static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask) buffer[0] = gbuf->cport_id; gbuf->transfer_buffer = &buffer[1]; gbuf->transfer_buffer_length = size; - gbuf->actual_length = size; /* When we send the gbuf, we need this pointer to be here */ gbuf->hdpriv = es1; diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index fe2f1a7..75f6e50 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -132,6 +132,7 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, kfree(operation); return NULL; } + gbuf->actual_length = size; /* Record what we'll use */ operation->connection = connection; /* XXX refcount? */ -- cgit v0.10.2 From b0b657555c8f9bb64189a0ff8824de1ad992f889 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 3 Oct 2014 15:05:20 -0500 Subject: greybus: specify type when creating an operation The type of an operation belongs in the operation header, which shouldn't be touched by users of the interface. So specify it at operation creation time. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 75f6e50..03f6660 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -111,7 +111,7 @@ static void gbuf_out_callback(struct gbuf *gbuf) * failure occurs due to memory exhaustion. */ struct gb_operation *gb_operation_create(struct gb_connection *connection, - size_t size) + size_t size, u8 type) { struct gb_operation *operation; struct gb_operation_msg_hdr *header; @@ -139,8 +139,9 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, /* Fill in the header structure and payload pointer */ operation->gbuf = gbuf; header = (struct gb_operation_msg_hdr *)&gbuf->transfer_buffer; - header->id = 0; header->size = cpu_to_le16(size); + header->id = 0; /* Filled in when submitted */ + header->type = type; operation->payload = (char *)header + sizeof(*header); operation->callback = NULL; /* set at submit time */ diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 96a7a0f..0dff703 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -60,7 +60,7 @@ struct gb_operation { }; struct gb_operation *gb_operation_create(struct gb_connection *connection, - size_t size); + size_t size, u8 type); void gb_operation_destroy(struct gb_operation *operation); int gb_operation_wait(struct gb_operation *operation); -- cgit v0.10.2 From 8a30672a526adcf797bcd3e40d4ef90d8b794f3f Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 3 Oct 2014 15:05:21 -0500 Subject: greybus: add a connection->private field This will be used for driver-specific data for whatever drives the other end of the connection. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 15bdc81..f2588a7 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -25,6 +25,8 @@ struct gb_connection { struct list_head operations; atomic_t op_cycle; + + void *private; }; struct gb_connection *gb_connection_create(struct gb_interface *interface, -- cgit v0.10.2 From eeeed42250f851a9c3368448b63c5aeaae65962a Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 3 Oct 2014 15:05:22 -0500 Subject: greybus: define gb_connection_err() Define a function that prints error information about a Greybus connection in a standard format. This adopts the convention that [M:I:C] represents the "path" the connection represents--specifying the module id, the interface number on that module, and the connection id on that interface. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index c50472d..80ebe1d 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -116,3 +116,21 @@ u16 gb_connection_op_id(struct gb_connection *connection) { return (u16)(atomic_inc_return(&connection->op_cycle) % U16_MAX); } + +void gb_connection_err(struct gb_connection *connection, const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + pr_err("greybus: [%hhu:%hhu:%hu]: %pV\n", + connection->interface->gmod->module_id, + connection->interface->id, + connection->interface_cport_id, &vaf); + + va_end(args); +} diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index f2588a7..61e9435 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -35,4 +35,7 @@ void gb_connection_destroy(struct gb_connection *connection); u16 gb_connection_op_id(struct gb_connection *connection); +__printf(2, 3) +void gb_connection_err(struct gb_connection *connection, const char *fmt, ...); + #endif /* __CONNECTION_H */ -- cgit v0.10.2 From 2fb5c518fcbc6c33f36039c23a9fe38a64ad4040 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 4 Oct 2014 18:43:41 -0700 Subject: greybus: manifest.c: minor sparse cleanup diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 03282fd..f0468d7 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -328,7 +328,7 @@ bool gb_manifest_parse(struct gb_module *gmod, void *data, size_t size) struct greybus_manifest_header *header; struct greybus_descriptor *desc; struct manifest_desc *descriptor; - struct manifest_desc *module_desc = false; + struct manifest_desc *module_desc = NULL; u16 manifest_size; u32 found = 0; bool result = false; -- cgit v0.10.2 From f6aec2516a1afcab2cdd1897098afe8b4bb435f2 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 6 Oct 2014 06:53:06 -0500 Subject: greybus: fix two misnamed functions I guess I got a little hd crazy. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 80ebe1d..5308612 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -21,7 +21,7 @@ static DEFINE_SPINLOCK(gb_connections_lock); * Assigns the connection's hd_cport_id and returns true if successful. * Returns false otherwise. */ -static bool hd_connection_hd_cport_id_alloc(struct gb_connection *connection) +static bool gb_connection_hd_cport_id_alloc(struct gb_connection *connection) { struct ida *ida = &connection->hd->cport_id_map; int id; @@ -38,7 +38,7 @@ static bool hd_connection_hd_cport_id_alloc(struct gb_connection *connection) /* * Free a previously-allocated CPort Id on the given host device. */ -static void hd_connection_hd_cport_id_free(struct gb_connection *connection) +static void gb_connection_hd_cport_id_free(struct gb_connection *connection) { struct ida *ida = &connection->hd->cport_id_map; @@ -69,7 +69,7 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, hd = interface->gmod->hd; connection->hd = hd; /* XXX refcount? */ - if (!hd_connection_hd_cport_id_alloc(connection)) { + if (!gb_connection_hd_cport_id_alloc(connection)) { /* kref_put(connection->hd); */ kfree(connection); return NULL; @@ -106,7 +106,7 @@ void gb_connection_destroy(struct gb_connection *connection) list_del(&connection->interface_links); spin_unlock_irq(&gb_connections_lock); - hd_connection_hd_cport_id_free(connection); + gb_connection_hd_cport_id_free(connection); /* kref_put(connection->interface); */ /* kref_put(connection->hd); */ kfree(connection); -- cgit v0.10.2 From 369fb8324969a94c2f243ea56641993ee2061e60 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 6 Oct 2014 06:53:07 -0500 Subject: greybus: bury some dead code One data structure and a few fields in another one are no longer used, and were not removed when they should have been. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 4404d93..f4ca18a 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -120,12 +120,6 @@ struct gbuf; -struct gmod_string { - u16 length; - u8 id; - u8 string[0]; -}; - typedef void (*gbuf_complete_t)(struct gbuf *gbuf); struct gbuf { @@ -194,10 +188,7 @@ struct greybus_host_device { struct list_head modules; struct list_head connections; - struct ida cport_id_map; - u16 cport_id_count; /* How many have been allocated */ - u16 cport_id_next_free; /* Where to start checking anyway */ /* Private data for the host driver */ unsigned long hd_priv[0] __attribute__ ((aligned(sizeof(s64)))); -- cgit v0.10.2 From ee9ebe4d0b78e64f0c3741085d230ea18c15f4e4 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 6 Oct 2014 06:53:08 -0500 Subject: greybus: add bg_hd_connection_find() Add a function that looks up a connection given the host device pointer an the host cport id. This will be used to determine which connection an incoming message is associated with. Replace the list tracking host device connections with a red-black tree so lookup can scale and be done quickly. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 5308612..449ae34 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -13,6 +13,56 @@ static DEFINE_SPINLOCK(gb_connections_lock); +static void _gb_hd_connection_insert(struct greybus_host_device *hd, + struct gb_connection *connection) +{ + struct rb_root *root = &hd->connections; + struct rb_node *node = &connection->hd_node; + struct rb_node **link = &root->rb_node; + struct rb_node *above = NULL; + u16 cport_id = connection->hd_cport_id; + + while (*link) { + struct gb_connection *connection; + + above = *link; + connection = rb_entry(above, struct gb_connection, hd_node); + if (connection->hd_cport_id > cport_id) + link = &above->rb_left; + else if (connection->hd_cport_id < cport_id) + link = &above->rb_right; + } + rb_link_node(node, above, link); + rb_insert_color(node, root); +} + +static void _gb_hd_connection_remove(struct gb_connection *connection) +{ + rb_erase(&connection->hd_node, &connection->hd->connections); +} + +struct gb_connection *gb_hd_connection_find(struct greybus_host_device *hd, + u16 cport_id) +{ + struct gb_connection *connection = NULL; + struct rb_node *node; + + spin_lock_irq(&gb_connections_lock); + node = hd->connections.rb_node; + while (node) { + connection = rb_entry(node, struct gb_connection, hd_node); + if (connection->hd_cport_id > cport_id) + node = node->rb_left; + else if (connection->hd_cport_id < cport_id) + node = node->rb_right; + else + break; + } + spin_unlock_irq(&gb_connections_lock); + + return connection; +} + /* * Allocate an available CPort Id for use for the host side of the * given connection. The lowest-available id is returned, so the @@ -80,7 +130,7 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, connection->protocol = protocol; spin_lock_irq(&gb_connections_lock); - list_add_tail(&connection->hd_links, &hd->connections); + _gb_hd_connection_insert(hd, connection); list_add_tail(&connection->interface_links, &interface->connections); spin_unlock_irq(&gb_connections_lock); @@ -102,8 +152,8 @@ void gb_connection_destroy(struct gb_connection *connection) WARN_ON(!list_empty(&connection->operations)); spin_lock_irq(&gb_connections_lock); - list_del(&connection->hd_links); list_del(&connection->interface_links); + _gb_hd_connection_remove(connection); spin_unlock_irq(&gb_connections_lock); gb_connection_hd_cport_id_free(connection); diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 61e9435..89d58e5 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -19,7 +19,7 @@ struct gb_connection { u16 hd_cport_id; u16 interface_cport_id; - struct list_head hd_links; + struct rb_node hd_node; struct list_head interface_links; enum greybus_protocol protocol; @@ -33,6 +33,9 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, u16 cport_id, enum greybus_protocol protocol); void gb_connection_destroy(struct gb_connection *connection); +struct gb_connection *gb_hd_connection_find(struct greybus_host_device *hd, + u16 cport_id); + u16 gb_connection_op_id(struct gb_connection *connection); __printf(2, 3) diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 41fb7ca..51d7e59 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -311,7 +311,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver hd->parent = parent; hd->driver = driver; INIT_LIST_HEAD(&hd->modules); - INIT_LIST_HEAD(&hd->connections); + hd->connections = RB_ROOT; ida_init(&hd->cport_id_map); return hd; diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index f4ca18a..ae7d322 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -187,7 +187,7 @@ struct greybus_host_device { const struct greybus_host_driver *driver; struct list_head modules; - struct list_head connections; + struct rb_root connections; struct ida cport_id_map; /* Private data for the host driver */ -- cgit v0.10.2 From 00d2e7588c79a2b9681f243d06ad02a254ab4ff9 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 6 Oct 2014 06:53:09 -0500 Subject: greybus: look up connection for recevied messages Look up the connection that an incoming message is associated with. This is the start of making message handling oriented toward the the connection rather than the cport. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index fada121..17c1af8 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -179,6 +179,14 @@ void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, { struct gb_cport_handler *ch; struct gbuf *gbuf; + struct gb_connection *connection; + + connection = gb_hd_connection_find(hd, cport_id); + if (!connection) { + dev_err(hd->parent, + "nonexistent connection (%zu bytes dropped)\n", length); + return; + } /* first check to see if we have a cport handler for this cport */ ch = &cport_handler[cport_id]; -- cgit v0.10.2 From 6eb3f4bdec331c951906792479a0f7ea49fe9a5c Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 6 Oct 2014 06:53:10 -0500 Subject: greybus: allocate gbufs using the connection Switch to using the connection rather than the host device as the locus for doing Greybus buffer allocation. A connection encapsulates both the host device (whose driver is what's required for allocation) and the *destination* cport id. Record the connection a gbuf is associated with rather than the host module and (unspecified) cport id. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 3601499..502b353 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -95,7 +95,7 @@ static void cport_out_callback(struct urb *urb); */ static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask) { - struct es1_ap_dev *es1 = hd_to_es1(gbuf->gmod->hd); + struct es1_ap_dev *es1 = hd_to_es1(gbuf->connection->hd); u8 *buffer; if (size > ES1_GBUF_MSG_SIZE) { @@ -116,14 +116,14 @@ static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask) * we will encode the cport number in the first byte of the buffer, so * set the second byte to be the "transfer buffer" */ - if (gbuf->cport_id > (u16)U8_MAX) { - pr_err("gbuf->cport_id is '%d' and is out of range!\n", - gbuf->cport_id); + if (gbuf->connection->interface_cport_id > (u16)U8_MAX) { + pr_err("gbuf->interface_cport_id (%hd) is out of range!\n", + gbuf->connection->interface_cport_id); kfree(buffer); return -EINVAL; } - buffer[0] = gbuf->cport_id; + buffer[0] = gbuf->connection->interface_cport_id; gbuf->transfer_buffer = &buffer[1]; gbuf->transfer_buffer_length = size; diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 17c1af8..2afd889 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -26,8 +26,7 @@ static struct kmem_cache *gbuf_head_cache; /* Workqueue to handle Greybus buffer completions. */ static struct workqueue_struct *gbuf_workqueue; -static struct gbuf *__alloc_gbuf(struct gb_module *gmod, - u16 cport_id, +static struct gbuf *__alloc_gbuf(struct gb_connection *connection, gbuf_complete_t complete, gfp_t gfp_mask, void *context) @@ -39,8 +38,7 @@ static struct gbuf *__alloc_gbuf(struct gb_module *gmod, return NULL; kref_init(&gbuf->kref); - gbuf->gmod = gmod; - gbuf->cport_id = cport_id; + gbuf->connection = connection; INIT_WORK(&gbuf->event, cport_process_event); gbuf->complete = complete; gbuf->context = context; @@ -63,8 +61,7 @@ static struct gbuf *__alloc_gbuf(struct gb_module *gmod, * that the driver can then fill up with the data to be sent out. Curse * hardware designers for this issue... */ -struct gbuf *greybus_alloc_gbuf(struct gb_module *gmod, - u16 cport_id, +struct gbuf *greybus_alloc_gbuf(struct gb_connection *connection, gbuf_complete_t complete, unsigned int size, gfp_t gfp_mask, @@ -73,14 +70,14 @@ struct gbuf *greybus_alloc_gbuf(struct gb_module *gmod, struct gbuf *gbuf; int retval; - gbuf = __alloc_gbuf(gmod, cport_id, complete, gfp_mask, context); + gbuf = __alloc_gbuf(connection, complete, gfp_mask, context); if (!gbuf) return NULL; gbuf->direction = GBUF_DIRECTION_OUT; /* Host controller specific allocation for the actual buffer */ - retval = gmod->hd->driver->alloc_gbuf_data(gbuf, size, gfp_mask); + retval = connection->hd->driver->alloc_gbuf_data(gbuf, size, gfp_mask); if (retval) { greybus_free_gbuf(gbuf); return NULL; @@ -98,7 +95,7 @@ static void free_gbuf(struct kref *kref) /* If the direction is "out" then the host controller frees the data */ if (gbuf->direction == GBUF_DIRECTION_OUT) { - gbuf->gmod->hd->driver->free_gbuf_data(gbuf); + gbuf->connection->hd->driver->free_gbuf_data(gbuf); } else { /* we "own" this in data, so free it ourselves */ kfree(gbuf->transfer_buffer); @@ -125,7 +122,9 @@ EXPORT_SYMBOL_GPL(greybus_get_gbuf); int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) { - return gbuf->gmod->hd->driver->submit_gbuf(gbuf, gbuf->gmod->hd, gfp_mask); + struct greybus_host_device *hd = gbuf->connection->hd; + + return hd->driver->submit_gbuf(gbuf, hd, gfp_mask); } int greybus_kill_gbuf(struct gbuf *gbuf) @@ -198,8 +197,7 @@ void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, return; } - gbuf = __alloc_gbuf(ch->gmod, ch->cport_id, ch->handler, GFP_ATOMIC, - ch->context); + gbuf = __alloc_gbuf(connection, ch->handler, GFP_ATOMIC, ch->context); if (!gbuf) { /* Again, something bad went wrong, log it... */ pr_err("can't allocate gbuf???\n"); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index ae7d322..e46d27e 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -126,8 +126,7 @@ struct gbuf { struct kref kref; void *hdpriv; - struct gb_module *gmod; - u16 cport_id; + struct gb_connection *connection; int status; void *transfer_buffer; u32 transfer_flags; /* flags for the transfer buffer */ @@ -201,7 +200,7 @@ void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, u8 *data, size_t length); void greybus_gbuf_finished(struct gbuf *gbuf); -struct gbuf *greybus_alloc_gbuf(struct gb_module *gmod, u16 cport_id, +struct gbuf *greybus_alloc_gbuf(struct gb_connection *connection, gbuf_complete_t complete, unsigned int size, gfp_t gfp_mask, void *context); void greybus_free_gbuf(struct gbuf *gbuf); diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 03f6660..cca3918 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -124,9 +124,7 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, /* Our buffer holds a header in addition to the requested payload */ size += sizeof(*header); - gbuf = greybus_alloc_gbuf(connection->interface->gmod, - connection->hd_cport_id, - gbuf_out_callback, size, + gbuf = greybus_alloc_gbuf(connection, gbuf_out_callback, size, GFP_KERNEL, operation); if (gbuf) { kfree(operation); -- cgit v0.10.2 From 9a6f6314d17ce2b66a6293b86f79afda6e9a563b Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 6 Oct 2014 06:53:11 -0500 Subject: greybus: use alloc_gbuf_data() for both directions Change the "direction" flag field of a gbuf to be a Boolean called "outbound". Add a Boolean outbound flag to alloc_gbuf_data(), and use it for allocating the data buffer for gbufs for data being transferred in either direction. Update free_gbuf_data() accordingly--letting the host device driver's gbuf data free function handle all of them. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 502b353..ef0ac7f 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -93,9 +93,11 @@ static void cport_out_callback(struct urb *urb); * void *transfer_buffer; * u32 transfer_buffer_length; */ -static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask) +static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, + gfp_t gfp_mask) { struct es1_ap_dev *es1 = hd_to_es1(gbuf->connection->hd); + u32 cport_reserve = gbuf->outbound ? 1 : 0; u8 *buffer; if (size > ES1_GBUF_MSG_SIZE) { @@ -107,8 +109,12 @@ static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask) * but for ES1, it's so dirt simple, we don't have a choice... * * Also, do a "slow" allocation now, if we need speed, use a cache + * + * For ES1 outbound buffers need to insert their target + * CPort Id before the data; set aside an extra byte for + * that purpose in that case. */ - buffer = kmalloc(size + 1, gfp_mask); + buffer = kmalloc(cport_reserve + size, gfp_mask); if (!buffer) return -ENOMEM; @@ -123,8 +129,10 @@ static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask) return -EINVAL; } - buffer[0] = gbuf->connection->interface_cport_id; - gbuf->transfer_buffer = &buffer[1]; + /* Insert the cport id for outbound buffers */ + if (gbuf->outbound) + *buffer++ = gbuf->connection->interface_cport_id; + gbuf->transfer_buffer = buffer; gbuf->transfer_buffer_length = size; /* When we send the gbuf, we need this pointer to be here */ @@ -136,15 +144,15 @@ static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask) /* Free the memory we allocated with a gbuf */ static void free_gbuf_data(struct gbuf *gbuf) { - u8 *transfer_buffer; - u8 *buffer; + u8 *transfer_buffer = gbuf->transfer_buffer; - transfer_buffer = gbuf->transfer_buffer; /* Can be called with a NULL transfer_buffer on some error paths */ - if (transfer_buffer) { - buffer = &transfer_buffer[-1]; /* yes, we mean -1 */ - kfree(buffer); - } + if (!transfer_buffer) + return; + + if (gbuf->outbound) + transfer_buffer--; /* Back up to cport id */ + kfree(transfer_buffer); } #define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 2afd889..62d0cb6 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -27,6 +27,7 @@ static struct kmem_cache *gbuf_head_cache; static struct workqueue_struct *gbuf_workqueue; static struct gbuf *__alloc_gbuf(struct gb_connection *connection, + bool outbound, gbuf_complete_t complete, gfp_t gfp_mask, void *context) @@ -40,6 +41,7 @@ static struct gbuf *__alloc_gbuf(struct gb_connection *connection, kref_init(&gbuf->kref); gbuf->connection = connection; INIT_WORK(&gbuf->event, cport_process_event); + gbuf->outbound = outbound; gbuf->complete = complete; gbuf->context = context; @@ -64,18 +66,17 @@ static struct gbuf *__alloc_gbuf(struct gb_connection *connection, struct gbuf *greybus_alloc_gbuf(struct gb_connection *connection, gbuf_complete_t complete, unsigned int size, + bool outbound, gfp_t gfp_mask, void *context) { struct gbuf *gbuf; int retval; - gbuf = __alloc_gbuf(connection, complete, gfp_mask, context); + gbuf = __alloc_gbuf(connection, outbound, complete, gfp_mask, context); if (!gbuf) return NULL; - gbuf->direction = GBUF_DIRECTION_OUT; - /* Host controller specific allocation for the actual buffer */ retval = connection->hd->driver->alloc_gbuf_data(gbuf, size, gfp_mask); if (retval) { @@ -93,13 +94,7 @@ static void free_gbuf(struct kref *kref) { struct gbuf *gbuf = container_of(kref, struct gbuf, kref); - /* If the direction is "out" then the host controller frees the data */ - if (gbuf->direction == GBUF_DIRECTION_OUT) { - gbuf->connection->hd->driver->free_gbuf_data(gbuf); - } else { - /* we "own" this in data, so free it ourselves */ - kfree(gbuf->transfer_buffer); - } + gbuf->connection->hd->driver->free_gbuf_data(gbuf); kmem_cache_free(gbuf_head_cache, gbuf); } @@ -197,14 +192,14 @@ void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, return; } - gbuf = __alloc_gbuf(connection, ch->handler, GFP_ATOMIC, ch->context); + gbuf = greybus_alloc_gbuf(connection, ch->handler, length, false, + GFP_ATOMIC, ch->context); + if (!gbuf) { /* Again, something bad went wrong, log it... */ pr_err("can't allocate gbuf???\n"); return; } - gbuf->hdpriv = hd; - gbuf->direction = GBUF_DIRECTION_IN; /* * FIXME: @@ -212,13 +207,7 @@ void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, * be, we should move to a model where the hd "owns" all buffers, but we * want something up and working first for now. */ - gbuf->transfer_buffer = kmalloc(length, GFP_ATOMIC); - if (!gbuf->transfer_buffer) { - kfree(gbuf); - return; - } memcpy(gbuf->transfer_buffer, data, length); - gbuf->transfer_buffer_length = length; gbuf->actual_length = length; queue_work(gbuf_workqueue, &gbuf->event); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index e46d27e..12a6cbf 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -133,9 +133,7 @@ struct gbuf { u32 transfer_buffer_length; u32 actual_length; -#define GBUF_DIRECTION_OUT 0 -#define GBUF_DIRECTION_IN 1 - unsigned int direction : 1; /* 0 is out, 1 is in */ + bool outbound; /* AP-relative data direction */ void *context; struct work_struct event; @@ -172,7 +170,8 @@ struct svc_msg; struct greybus_host_driver { size_t hd_priv_size; - int (*alloc_gbuf_data)(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask); + int (*alloc_gbuf_data)(struct gbuf *gbuf, unsigned int size, + gfp_t gfp_mask); void (*free_gbuf_data)(struct gbuf *gbuf); int (*submit_svc)(struct svc_msg *svc_msg, struct greybus_host_device *hd); @@ -202,7 +201,7 @@ void greybus_gbuf_finished(struct gbuf *gbuf); struct gbuf *greybus_alloc_gbuf(struct gb_connection *connection, gbuf_complete_t complete, unsigned int size, - gfp_t gfp_mask, void *context); + bool outbound, gfp_t gfp_mask, void *context); void greybus_free_gbuf(struct gbuf *gbuf); struct gbuf *greybus_get_gbuf(struct gbuf *gbuf); #define greybus_put_gbuf greybus_free_gbuf diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index cca3918..b5351b2 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -125,7 +125,7 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, /* Our buffer holds a header in addition to the requested payload */ size += sizeof(*header); gbuf = greybus_alloc_gbuf(connection, gbuf_out_callback, size, - GFP_KERNEL, operation); + true, GFP_KERNEL, operation); if (gbuf) { kfree(operation); return NULL; -- cgit v0.10.2 From fdb594f1366327f10cbc8167a9923a5e88a381fa Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 6 Oct 2014 06:53:12 -0500 Subject: greybus: kill __alloc_gbuf() GEt rid of __alloc_gbuf(), now that it's used in only one place. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 62d0cb6..2ef6ead 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -26,28 +26,6 @@ static struct kmem_cache *gbuf_head_cache; /* Workqueue to handle Greybus buffer completions. */ static struct workqueue_struct *gbuf_workqueue; -static struct gbuf *__alloc_gbuf(struct gb_connection *connection, - bool outbound, - gbuf_complete_t complete, - gfp_t gfp_mask, - void *context) -{ - struct gbuf *gbuf; - - gbuf = kmem_cache_zalloc(gbuf_head_cache, gfp_mask); - if (!gbuf) - return NULL; - - kref_init(&gbuf->kref); - gbuf->connection = connection; - INIT_WORK(&gbuf->event, cport_process_event); - gbuf->outbound = outbound; - gbuf->complete = complete; - gbuf->context = context; - - return gbuf; -} - /** * greybus_alloc_gbuf - allocate a greybus buffer * @@ -73,14 +51,21 @@ struct gbuf *greybus_alloc_gbuf(struct gb_connection *connection, struct gbuf *gbuf; int retval; - gbuf = __alloc_gbuf(connection, outbound, complete, gfp_mask, context); + gbuf = kmem_cache_zalloc(gbuf_head_cache, gfp_mask); if (!gbuf) return NULL; + kref_init(&gbuf->kref); + gbuf->connection = connection; + INIT_WORK(&gbuf->event, cport_process_event); + gbuf->outbound = outbound; + gbuf->complete = complete; + gbuf->context = context; + /* Host controller specific allocation for the actual buffer */ retval = connection->hd->driver->alloc_gbuf_data(gbuf, size, gfp_mask); if (retval) { - greybus_free_gbuf(gbuf); + kmem_cache_free(gbuf_head_cache, gbuf); return NULL; } -- cgit v0.10.2 From e8caf9a31b90d7c596cfcd5810dbf6910f3cbcc6 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 6 Oct 2014 06:53:13 -0500 Subject: greybus: get rid of gbuf->hdpriv Last time I tried to kill off gbuf->context my efforts were shot down. Now that I've got the connection infrastructure in place, maybe I'll have more luck getting rid of gbuf->hdpriv. The only place it's used is to stash the es1_ap_dev structure pointer in the buffer. But that information is now available through the buffer's connection, so we don't need to use the hdpriv field any more. So get rid of it, and use hd_to_es1(gbuf->connection->hd) to get at what we need. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index ef0ac7f..97dd9b6 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -96,7 +96,6 @@ static void cport_out_callback(struct urb *urb); static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask) { - struct es1_ap_dev *es1 = hd_to_es1(gbuf->connection->hd); u32 cport_reserve = gbuf->outbound ? 1 : 0; u8 *buffer; @@ -135,9 +134,6 @@ static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, gbuf->transfer_buffer = buffer; gbuf->transfer_buffer_length = size; - /* When we send the gbuf, we need this pointer to be here */ - gbuf->hdpriv = es1; - return 0; } @@ -337,7 +333,7 @@ exit: static void cport_out_callback(struct urb *urb) { struct gbuf *gbuf = urb->context; - struct es1_ap_dev *es1 = gbuf->hdpriv; + struct es1_ap_dev *es1 = hd_to_es1(gbuf->connection->hd); unsigned long flags; int i; diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 12a6cbf..851f5ae 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -124,7 +124,6 @@ typedef void (*gbuf_complete_t)(struct gbuf *gbuf); struct gbuf { struct kref kref; - void *hdpriv; struct gb_connection *connection; int status; -- cgit v0.10.2 From 7a13e2f68831cba76cb699103b27219649ca6e57 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 6 Oct 2014 09:58:44 -0400 Subject: greybus: fix manifest parsing problem with descriptor payload The internal struct manifest_desc needs the data payload, rather than the entire descriptor with header to be populated into the data field. Also fix two places where the parser was trying to extract the entire descriptor with header for the data payload field. Signed-off-by: Matt Porter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index f0468d7..43ece74 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -113,7 +113,7 @@ static int identify_descriptor(struct greybus_descriptor *desc, size_t size) return -ENOMEM; descriptor->size = desc_size; - descriptor->data = desc; + descriptor->data = (u8 *)desc + sizeof(*desc_header); descriptor->type = desc_header->type; list_add_tail(&descriptor->links, &manifest_descs); @@ -143,13 +143,11 @@ static char *gb_string_get(u8 string_id) return NULL; list_for_each_entry(descriptor, &manifest_descs, links) { - struct greybus_descriptor *desc; if (descriptor->type != GREYBUS_TYPE_STRING) continue; - desc = descriptor->data; - desc_string = &desc->string; + desc_string = descriptor->data; if (desc_string->id == string_id) { found = true; break; @@ -262,8 +260,7 @@ static u32 gb_manifest_parse_interfaces(struct gb_module *gmod) static bool gb_manifest_parse_module(struct gb_module *gmod, struct manifest_desc *module_desc) { - struct greybus_descriptor *desc = module_desc->data; - struct greybus_descriptor_module *desc_module = &desc->module; + struct greybus_descriptor_module *desc_module = module_desc->data; /* Handle the strings first--they can fail */ gmod->vendor_string = gb_string_get(desc_module->vendor_stringid); -- cgit v0.10.2 From e86905b6cd73ce62af88b3526dbc10c14d47016d Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Mon, 6 Oct 2014 13:26:02 -0400 Subject: greybus: gb_hd_connection_find(): fix "not found" case Without this, null-testing the return value of this function is broken. Signed-off-by: Marti Bolivar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 449ae34..07a593d 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -56,8 +56,10 @@ struct gb_connection *gb_hd_connection_find(struct greybus_host_device *hd, else if (connection->hd_cport_id < cport_id) node = node->rb_right; else - break; + goto found; } + connection = NULL; + found: spin_unlock_irq(&gb_connections_lock); return connection; -- cgit v0.10.2 From ff8aed527455feea7d36bb45dd529b7931150087 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 6 Oct 2014 13:46:36 -0400 Subject: greybus: fix gb_manifest_parse() successful return path Even if we successfully parse a manifest we are returning failure. Instead, we now proudly proclaim success. Signed-off-by: Matt Porter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 43ece74..09fcde9 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -364,6 +364,7 @@ bool gb_manifest_parse(struct gb_module *gmod, void *data, size_t size) if (desc_size <= 0) { if (!desc_size) pr_err("zero-sized manifest descriptor\n"); + result = false; goto out; } desc = (struct greybus_descriptor *)((char *)desc + desc_size); @@ -379,6 +380,7 @@ bool gb_manifest_parse(struct gb_module *gmod, void *data, size_t size) if (found != 1) { pr_err("manifest must have 1 module descriptor (%u found)\n", found); + result = false; goto out; } @@ -394,5 +396,5 @@ bool gb_manifest_parse(struct gb_module *gmod, void *data, size_t size) out: release_manifest_descriptors(); - return false; + return result; } -- cgit v0.10.2 From 25b7b6d04bdfc76631cc02012f33f10bc27dd27e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 6 Oct 2014 20:29:40 -0700 Subject: greybus: connection: properly lock idr We had a lock, but we never used it, so move it to be per-hd, like the idr structure is. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 07a593d..1a2bec2 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -78,7 +78,9 @@ static bool gb_connection_hd_cport_id_alloc(struct gb_connection *connection) struct ida *ida = &connection->hd->cport_id_map; int id; + spin_lock(&connection->hd->cport_id_map_lock); id = ida_simple_get(ida, 0, HOST_DEV_CPORT_ID_MAX, GFP_KERNEL); + spin_unlock(&connection->hd->cport_id_map_lock); if (id < 0) return false; @@ -94,7 +96,9 @@ static void gb_connection_hd_cport_id_free(struct gb_connection *connection) { struct ida *ida = &connection->hd->cport_id_map; + spin_lock(&connection->hd->cport_id_map_lock); ida_simple_remove(ida, connection->hd_cport_id); + spin_unlock(&connection->hd->cport_id_map_lock); connection->hd_cport_id = CPORT_ID_BAD; } @@ -126,7 +130,7 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, kfree(connection); return NULL; } - connection->hd = hd; /* XXX refcount? */ + connection->interface = interface; /* XXX refcount? */ connection->interface_cport_id = cport_id; connection->protocol = protocol; diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 51d7e59..6c4107e 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -30,8 +30,6 @@ int greybus_disabled(void) } EXPORT_SYMBOL_GPL(greybus_disabled); -static spinlock_t cport_id_map_lock; - static int greybus_module_match(struct device *dev, struct device_driver *drv) { struct greybus_driver *driver = to_greybus_driver(dev->driver); @@ -313,6 +311,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver INIT_LIST_HEAD(&hd->modules); hd->connections = RB_ROOT; ida_init(&hd->cport_id_map); + spin_lock_init(&hd->cport_id_map_lock); return hd; } @@ -330,7 +329,6 @@ static int __init gb_init(void) int retval; BUILD_BUG_ON(HOST_DEV_CPORT_ID_MAX >= (long)CPORT_ID_BAD); - spin_lock_init(&cport_id_map_lock); retval = gb_debugfs_init(); if (retval) { diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 851f5ae..20c1a03 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -186,6 +186,7 @@ struct greybus_host_device { struct list_head modules; struct rb_root connections; struct ida cport_id_map; + spinlock_t cport_id_map_lock; /* Private data for the host driver */ unsigned long hd_priv[0] __attribute__ ((aligned(sizeof(s64)))); -- cgit v0.10.2 From 8faa8da9a621821dfc5945cff415c4d3f904f3ce Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 6 Oct 2014 20:34:48 -0700 Subject: greybus: greybus.h: remove transfer_flags We didn't use them, so drop it. Also some other checkpatch cleanups while I was in there. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 20c1a03..39ccdc4 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -34,7 +34,7 @@ #define GREYBUS_VERSION_MINOR 0x01 #define GREYBUS_DEVICE_ID_MATCH_DEVICE \ - (GREYBUS_DEVICE_ID_MATCH_VENDOR | GREYBUS_DEVICE_ID_MATCH_PRODUCT) + (GREYBUS_DEVICE_ID_MATCH_VENDOR | GREYBUS_DEVICE_ID_MATCH_PRODUCT) #define GREYBUS_DEVICE(v, p) \ .match_flags = GREYBUS_DEVICE_ID_MATCH_DEVICE, \ @@ -128,7 +128,6 @@ struct gbuf { struct gb_connection *connection; int status; void *transfer_buffer; - u32 transfer_flags; /* flags for the transfer buffer */ u32 transfer_buffer_length; u32 actual_length; @@ -139,10 +138,6 @@ struct gbuf { gbuf_complete_t complete; }; -/* - * gbuf->transfer_flags - */ -#define GBUF_FREE_BUFFER BIT(0) /* Free the transfer buffer with the gbuf */ /* For SP1 hardware, we are going to "hardcode" each device to have all logical * blocks in order to be able to address them as one unified "unit". Then @@ -189,10 +184,10 @@ struct greybus_host_device { spinlock_t cport_id_map_lock; /* Private data for the host driver */ - unsigned long hd_priv[0] __attribute__ ((aligned(sizeof(s64)))); + unsigned long hd_priv[0] __aligned(sizeof(s64)); }; -struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *host_driver, +struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *hd, struct device *parent); void greybus_remove_hd(struct greybus_host_device *hd); void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, -- cgit v0.10.2 From c4f37c62fafef55972dfbce31d253df9b4d85bd0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 6 Oct 2014 20:37:08 -0700 Subject: greybus: greybus_id.h: checkpatch cleanup diff --git a/drivers/staging/greybus/greybus_id.h b/drivers/staging/greybus/greybus_id.h index f8e7b38..c6cd2e8 100644 --- a/drivers/staging/greybus/greybus_id.h +++ b/drivers/staging/greybus/greybus_id.h @@ -15,8 +15,7 @@ struct greybus_module_id { __u16 product; __u64 unique_id; - kernel_ulong_t driver_info - __attribute__((aligned(sizeof(kernel_ulong_t)))); + kernel_ulong_t driver_info __aligned(sizeof(kernel_ulong_t)); }; /* Used to match the greybus_module_id */ -- cgit v0.10.2 From 62e120f599c203da7ffa455581405ff26786d83c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 6 Oct 2014 20:37:18 -0700 Subject: greybus: svc_msg.h: add bsd license to file so that firmware can use it. diff --git a/drivers/staging/greybus/svc_msg.h b/drivers/staging/greybus/svc_msg.h index 1f8b4f1..57d0a91 100644 --- a/drivers/staging/greybus/svc_msg.h +++ b/drivers/staging/greybus/svc_msg.h @@ -6,7 +6,7 @@ * * Copyright 2014 Google Inc. * - * Released under the GPLv2 only. + * Released under the GPLv2 and BSD license. */ #ifndef __SVC_MSG_H -- cgit v0.10.2 From 9b60aa02bae723db131ae8f4e460c09a3b528a3f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 6 Oct 2014 20:37:53 -0700 Subject: greybus: greybus_manifest.h: add BSD license so that firmware can share it. diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index d31eb68..4fd27d3 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -6,7 +6,7 @@ * * Copyright 2014 Google Inc. * - * Released under the GPLv2 only. + * Released under the GPLv2 and BSD licenses. */ #ifndef __GREYBUS_MANIFEST_H -- cgit v0.10.2 From 8218605d20fff015bb3f76060ad7fe87d4362fc0 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Fri, 10 Oct 2014 14:42:33 -0700 Subject: greybus: Changes required for integrating into the Android build In order to easily integrate into the Android build, include an Android.mk. Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Android.mk b/drivers/staging/greybus/Android.mk new file mode 100644 index 0000000..773129b --- /dev/null +++ b/drivers/staging/greybus/Android.mk @@ -0,0 +1,29 @@ +.PHONY: build-greybus + +$(PRODUCT_OUT)/ramdisk.img: build-greybus + +include $(CLEAR_VARS) +GREYBUS_SRC_PATH := $(ANDROID_BUILD_TOP)/external/greybus/ +LOCAL_PATH := $(GREYBUS_SRC_PATH) +LOCAL_SRC_FILES := greybus.ko +LOCAL_MODULE := $(LOCAL_SRC_FILES) +LOCAL_MODULE_CLASS := EXECUTABLES +LOCAL_MODULE_PATH := $(PRODUCT_OUT)/root/lib/modules +$(LOCAL_PATH)/$(LOCAL_SRC_FILES): build-greybus +include $(BUILD_PREBUILT) + +KDIRARG := KERNELDIR="${ANDROID_PRODUCT_OUT}/obj/kernel" +ifneq ($(ANDROID_64),) + ARCHARG := ARCH=arm64 + FLAGARG := EXTRA_CFLAGS+=-fno-pic +else + ARCHARG := ARCH=arm +endif +ARGS := $(KDIRARG) $(ARCHARG) $(FLAGARG) + +build-greybus: android_kernel + make clean -C $(GREYBUS_SRC_PATH) + cd $(GREYBUS_SRC_PATH) &&\ + $(MAKE) -j$(MAKE_JOBS) CROSS_COMPILE=$(KERNEL_TOOLS_PREFIX) $(ARGS) + mkdir -p $(PRODUCT_OUT)/root/lib/modules + cp $(GREYBUS_SRC_PATH)/greybus.ko $(PRODUCT_OUT)/root/lib/modules -- cgit v0.10.2 From 8fd39e3dcb881501726ed0161855ed7a61f642ef Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 13 Oct 2014 03:00:53 -0400 Subject: greybus: es1-ap-usb: handle -EPROTO in check_urb_status() On a disconnect we can also have a status of -EPROTO. This results in a flood of error messages due to the -EAGAIN handling of unsupported status results. Fix this by also returning status when we have -EPROTO. Signed-off-by: Matt Porter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 97dd9b6..1a67d9e 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -257,6 +257,7 @@ static int check_urb_status(struct urb *urb) case -ENOENT: case -ESHUTDOWN: case -EILSEQ: + case -EPROTO: /* device is gone, stop sending */ return status; } -- cgit v0.10.2 From 051fb04712593a1bebdf638cd9f9935db2ce48aa Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 16 Oct 2014 06:35:24 -0500 Subject: greybus: don't assume subdevs are valid Most of the disconnect routines for the "subdevs" of a module blindly assume that initialization of the subdev was successful. Fix this by checking for null pointers. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index 1ef2f17..eaced9a 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -135,6 +135,8 @@ void gb_battery_disconnect(struct gb_module *gmod) struct gb_battery *gb; gb = gmod->gb_battery; + if (!gb) + return; power_supply_unregister(&gb->bat); diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index 2369175..da20028 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -92,6 +92,8 @@ void gb_gpio_disconnect(struct gb_module *gmod) int retval; gb_gpio_dev = gmod->gb_gpio_dev; + if (!gb_gpio_dev) + return; retval = gpiochip_remove(&gb_gpio_dev->chip); kfree(gb_gpio_dev); diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index c01f41b..0da1958 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -121,6 +121,8 @@ void gb_i2c_disconnect(struct gb_module *gmod) struct gb_i2c_device *gb_i2c_dev; gb_i2c_dev = gmod->gb_i2c_dev; + if (!gb_i2c_dev) + return; i2c_del_adapter(gb_i2c_dev->adapter); kfree(gb_i2c_dev->adapter); kfree(gb_i2c_dev); diff --git a/drivers/staging/greybus/sdio-gb.c b/drivers/staging/greybus/sdio-gb.c index f7e80ab..239fcf7 100644 --- a/drivers/staging/greybus/sdio-gb.c +++ b/drivers/staging/greybus/sdio-gb.c @@ -71,8 +71,10 @@ void gb_sdio_disconnect(struct gb_module *gmod) struct gb_sdio_host *host; host = gmod->gb_sdio_host; - mmc = host->mmc; + if (!host) + return; + mmc = host->mmc; mmc_remove_host(mmc); mmc_free_host(mmc); } -- cgit v0.10.2 From ad8cd0d643f0c3f86755a0169bb7c9597005fa8e Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 16 Oct 2014 06:35:25 -0500 Subject: greybus: unlock gbuf mutex on free To drop a reference on a gbuf, greybus_free_gbuf() is called. That uses kref_put_mutex() to drop the refernce under protection of gbuf_mutex. However the release routine, free_gbuf(), never releases the mutex as it should. Fix that. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 2ef6ead..a33dbb4 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -82,6 +82,7 @@ static void free_gbuf(struct kref *kref) gbuf->connection->hd->driver->free_gbuf_data(gbuf); kmem_cache_free(gbuf_head_cache, gbuf); + mutex_unlock(&gbuf_mutex); } void greybus_free_gbuf(struct gbuf *gbuf) -- cgit v0.10.2 From a06df4b08cee2cd201b3cbb7ee8312ea68cc2047 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 16 Oct 2014 06:35:26 -0500 Subject: greybus: unlock hd mutex on free When free_hd() is called, hd_mutex is held. It is the responsibility of free_hd() to drop that mutex. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 6c4107e..6762871 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -294,6 +294,7 @@ static void free_hd(struct kref *kref) hd = container_of(kref, struct greybus_host_device, kref); kfree(hd); + mutex_unlock(&hd_mutex); } struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver, -- cgit v0.10.2 From 170229d19586955e30604b2de37557e09a70b66c Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 16 Oct 2014 06:35:27 -0500 Subject: greybus: don't restrict input buffer size Don't assume that input buffers have any particular content. The only thing the gbuf layer needs to be concerned with is the presence of the cport_id byte at the beginning of a transfer. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 1a67d9e..e55ad03 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -305,10 +305,9 @@ static void cport_in_callback(struct urb *urb) if (status) return; - /* The size has to be more then just an "empty" transfer */ - if (urb->actual_length <= 2) { - dev_err(dev, "%s: \"short\" cport in transfer of %d bytes?\n", - __func__, urb->actual_length); + /* The size has to be at least one, for the cport id */ + if (!urb->actual_length) { + dev_err(dev, "%s: no cport id in input buffer?\n", __func__); goto exit; } @@ -338,10 +337,6 @@ static void cport_out_callback(struct urb *urb) unsigned long flags; int i; - /* If no error, tell the core the gbuf is properly sent */ - if (!check_urb_status(urb)) - greybus_gbuf_finished(gbuf); - /* * See if this was an urb in our pool, if so mark it "free", otherwise * we need to free it ourselves. -- cgit v0.10.2 From a7901d5ef7ff6bb6b7fdc500d9383450b23ba059 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 16 Oct 2014 06:35:28 -0500 Subject: greybus: zero all data buffers Don't assume the buffer data area will all be overwritten. Zero all buffer space, to avoid sending crap over the wire. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index e55ad03..2405670 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -113,7 +113,7 @@ static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, * CPort Id before the data; set aside an extra byte for * that purpose in that case. */ - buffer = kmalloc(cport_reserve + size, gfp_mask); + buffer = kzalloc(cport_reserve + size, gfp_mask); if (!buffer) return -ENOMEM; -- cgit v0.10.2 From 61418b9fd9a4e38b5ba41f7c1703083a989dda09 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 16 Oct 2014 06:35:29 -0500 Subject: greybus: drop hd arg from submit_gbuf method Every gbuf is associated with a connection when it is created. And a connection contains a pointer to the host device that will carry messages. So there's no need for the submit_gbuf() method to have the host device pointer passed to it, the function can get it from the gbuf's connection. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 2405670..5acf5a7 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -206,9 +206,9 @@ static struct urb *next_free_urb(struct es1_ap_dev *es1, gfp_t gfp_mask) return urb; } -static int submit_gbuf(struct gbuf *gbuf, struct greybus_host_device *hd, - gfp_t gfp_mask) +static int submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) { + struct greybus_host_device *hd = gbuf->connection->hd; struct es1_ap_dev *es1 = hd_to_es1(hd); struct usb_device *udev = es1->usb_dev; int retval; diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index a33dbb4..6580deb 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -105,7 +105,7 @@ int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) { struct greybus_host_device *hd = gbuf->connection->hd; - return hd->driver->submit_gbuf(gbuf, hd, gfp_mask); + return hd->driver->submit_gbuf(gbuf, gfp_mask); } int greybus_kill_gbuf(struct gbuf *gbuf) diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 39ccdc4..033c7ab 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -169,8 +169,7 @@ struct greybus_host_driver { void (*free_gbuf_data)(struct gbuf *gbuf); int (*submit_svc)(struct svc_msg *svc_msg, struct greybus_host_device *hd); - int (*submit_gbuf)(struct gbuf *gbuf, struct greybus_host_device *hd, - gfp_t gfp_mask); + int (*submit_gbuf)(struct gbuf *gbuf, gfp_t gfp_mask); }; struct greybus_host_device { -- cgit v0.10.2 From 17d265f6a69aef5920cf3d6669735239cb792184 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 16 Oct 2014 06:35:30 -0500 Subject: greybus: stop init_subdevs stuff Upcoming patches are going to set up devices based on what is discovered in the module manifest. Get rid of the hard-coded initialization done by gb_init_subdevs(), along with other related code. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 6762871..720ab47 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -131,59 +131,6 @@ static struct device_type greybus_module_type = { .release = greybus_module_release, }; -/* XXX - * This needs to be driven by the list of functions that the - * manifest says are present. - */ -static int gb_init_subdevs(struct gb_module *gmod, - const struct greybus_module_id *id) -{ - int retval; - - /* Allocate all of the different "sub device types" for this device */ - - /* XXX - * Decide what exactly we should get supplied for the i2c - * probe, and then work that back to what should be present - * in the manifest. - */ - retval = gb_i2c_probe(gmod, id); - if (retval) - goto error_i2c; - - retval = gb_gpio_probe(gmod, id); - if (retval) - goto error_gpio; - - retval = gb_sdio_probe(gmod, id); - if (retval) - goto error_sdio; - - retval = gb_tty_probe(gmod, id); - if (retval) - goto error_tty; - - retval = gb_battery_probe(gmod, id); - if (retval) - goto error_battery; - return 0; - -error_battery: - gb_tty_disconnect(gmod); - -error_tty: - gb_sdio_disconnect(gmod); - -error_sdio: - gb_gpio_disconnect(gmod); - -error_gpio: - gb_i2c_disconnect(gmod); - -error_i2c: - return retval; -} - static const struct greybus_module_id fake_greybus_module_id = { GREYBUS_DEVICE(0x42, 0x42) }; @@ -235,19 +182,8 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, dev_set_name(&gmod->dev, "%d", module_id); retval = device_add(&gmod->dev); - if (retval) - goto error; - - retval = gb_init_subdevs(gmod, &fake_greybus_module_id); - if (retval) - goto error_subdevs; - - //return gmod; - return; - -error_subdevs: - device_del(&gmod->dev); - + if (!retval) + return; /* Success */ error: gb_module_destroy(gmod); @@ -274,13 +210,6 @@ void gb_remove_module(struct greybus_host_device *hd, u8 module_id) void greybus_remove_device(struct gb_module *gmod) { - /* tear down all of the "sub device types" for this device */ - gb_i2c_disconnect(gmod); - gb_gpio_disconnect(gmod); - gb_sdio_disconnect(gmod); - gb_tty_disconnect(gmod); - gb_battery_disconnect(gmod); - device_del(&gmod->dev); put_device(&gmod->dev); } diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 033c7ab..1970106 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -265,23 +265,6 @@ void gb_deregister_cport_complete(u16 cport_id); extern const struct attribute_group *greybus_module_groups[]; -/* - * Because we are allocating a data structure per "type" in the greybus device, - * we have static functions for this, not "dynamic" drivers like we really - * should in the end. - */ -int gb_i2c_probe(struct gb_module *gmod, const struct greybus_module_id *id); -void gb_i2c_disconnect(struct gb_module *gmod); -int gb_gpio_probe(struct gb_module *gmod, const struct greybus_module_id *id); -void gb_gpio_disconnect(struct gb_module *gmod); -int gb_sdio_probe(struct gb_module *gmod, const struct greybus_module_id *id); -void gb_sdio_disconnect(struct gb_module *gmod); -int gb_tty_probe(struct gb_module *gmod, const struct greybus_module_id *id); -void gb_tty_disconnect(struct gb_module *gmod); -int gb_battery_probe(struct gb_module *gmod, - const struct greybus_module_id *id); -void gb_battery_disconnect(struct gb_module *gmod); - int gb_tty_init(void); void gb_tty_exit(void); -- cgit v0.10.2 From 22b320f400f38afac70fff0472c4df1cf1bfeee5 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 16 Oct 2014 06:35:31 -0500 Subject: greybus: add response buffer to an operation We need to track both request messages and response messages in operations. So add another gbuf (and payload pointer) field to the operation structure, and rename them to indicate which one is which. Allow the creator specify the size of the response buffer; just leave it a null pointer if the size is 0. Define a new helper function gb_operation_gbuf_create() to encapsulate creating either a request or a response buffer. Any buffer associated with a connection will (eventually) have been created as part of an operation. So stash the operation pointer in the gbuf as the context pointer. Whether a buffer is for the request or the response can be determined by pointer comparison. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index b5351b2..43ad244 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -14,6 +14,12 @@ #include "greybus.h" /* + * The top bit of the type in an operation message header indicates + * whether the message is a request (bit clear) or response (bit set) + */ +#define GB_OPERATION_TYPE_RESPONSE 0x80 + +/* * All operation messages (both requests and responses) begin with * a common header that encodes the size of the data (header * included). This header also contains a unique identifier, which @@ -61,7 +67,7 @@ int gb_operation_wait(struct gb_operation *operation) ret = wait_for_completion_interruptible(&operation->completion); /* If interrupted, cancel the in-flight buffer */ if (ret < 0) - ret = greybus_kill_gbuf(operation->gbuf); + ret = greybus_kill_gbuf(operation->request); return ret; } @@ -80,12 +86,14 @@ int gb_operation_submit(struct gb_operation *operation, { int ret; - /* XXX - * gfp is probably GFP_ATOMIC but really I think - * the gfp mask should go away. + /* + * XXX + * I think the order of operations is going to be + * significant, and if so, we may need a mutex to surround + * setting the operation id and submitting the gbuf. */ operation->callback = callback; - ret = greybus_submit_gbuf(operation->gbuf, GFP_KERNEL); + ret = greybus_submit_gbuf(operation->request, GFP_KERNEL); if (ret) return ret; if (!callback) @@ -95,52 +103,100 @@ int gb_operation_submit(struct gb_operation *operation, } /* - * Called when a greybus request message has actually been sent. + * Called when an operation buffer completes. */ -static void gbuf_out_callback(struct gbuf *gbuf) +static void gb_operation_gbuf_complete(struct gbuf *gbuf) { - /* Record it's been submitted; need response now */ + /* TODO */ } /* - * Create a Greybus operation having a buffer big enough for an - * outgoing payload of the given size to be sent over the given - * connection. + * Allocate a buffer to be used for an operation request or response + * message. Both types of message contain a header, which is filled + * in here. W + */ +struct gbuf *gb_operation_gbuf_create(struct gb_operation *operation, + u8 type, size_t size, bool outbound) +{ + struct gb_connection *connection = operation->connection; + struct gb_operation_msg_hdr *header; + struct gbuf *gbuf; + gfp_t gfp_flags = outbound ? GFP_KERNEL : GFP_ATOMIC; + + /* Operation buffers hold a header in addition to their payload */ + size += sizeof(*header); + gbuf = greybus_alloc_gbuf(connection, gb_operation_gbuf_complete, + size, outbound, gfp_flags, operation); + if (!gbuf) + return NULL; + + /* Fill in the header structure */ + header = (struct gb_operation_msg_hdr *)gbuf->transfer_buffer; + header->size = cpu_to_le16(size); + header->id = 0; /* Filled in when submitted */ + header->type = type; + + return gbuf; +} + +/* + * Create a Greybus operation to be sent over the given connection. + * The request buffer will big enough for a payload of the given + * size. Outgoing requests must specify the size of the response + * buffer size, which must be sufficient to hold all expected + * response data. + * + * Incoming requests will supply a response size of 0, and in that + * case no response buffer is allocated. (A response always + * includes a status byte, so 0 is not a valid size.) Whatever + * handles the operation request is responsible for allocating the + * response buffer. * - * Returns a pointer to the new operation or a null pointer if a - * failure occurs due to memory exhaustion. + * Returns a pointer to the new operation or a null pointer if an + * error occurs. */ struct gb_operation *gb_operation_create(struct gb_connection *connection, - size_t size, u8 type) + u8 type, size_t request_size, + size_t response_size) { struct gb_operation *operation; - struct gb_operation_msg_hdr *header; - struct gbuf *gbuf; + gfp_t gfp_flags = response_size ? GFP_KERNEL : GFP_ATOMIC; + + if (!request_size) { + gb_connection_err(connection, "zero-sized request"); + return NULL; + } /* XXX Use a slab cache */ - operation = kzalloc(sizeof(*operation), GFP_KERNEL); + operation = kzalloc(sizeof(*operation), gfp_flags); if (!operation) return NULL; + operation->connection = connection; /* XXX refcount? */ - /* Our buffer holds a header in addition to the requested payload */ - size += sizeof(*header); - gbuf = greybus_alloc_gbuf(connection, gbuf_out_callback, size, - true, GFP_KERNEL, operation); - if (gbuf) { + operation->request = gb_operation_gbuf_create(operation, type, + request_size, true); + if (!operation->request) { kfree(operation); return NULL; } - gbuf->actual_length = size; /* Record what we'll use */ - - operation->connection = connection; /* XXX refcount? */ - - /* Fill in the header structure and payload pointer */ - operation->gbuf = gbuf; - header = (struct gb_operation_msg_hdr *)&gbuf->transfer_buffer; - header->size = cpu_to_le16(size); - header->id = 0; /* Filled in when submitted */ - header->type = type; - operation->payload = (char *)header + sizeof(*header); + operation->request_payload = operation->request->transfer_buffer + + sizeof(struct gb_operation_msg_hdr); + /* We always use the full request buffer */ + operation->request->actual_length = request_size; + + if (response_size) { + type |= GB_OPERATION_TYPE_RESPONSE; + operation->response = gb_operation_gbuf_create(operation, + type, response_size, false); + if (!operation->response) { + greybus_free_gbuf(operation->request); + kfree(operation); + return NULL; + } + operation->response_payload = + operation->response->transfer_buffer + + sizeof(struct gb_operation_msg_hdr); + } operation->callback = NULL; /* set at submit time */ init_completion(&operation->completion); @@ -165,7 +221,8 @@ void gb_operation_destroy(struct gb_operation *operation) list_del(&operation->links); spin_unlock_irq(&gb_operations_lock); - greybus_free_gbuf(operation->gbuf); + greybus_free_gbuf(operation->response); + greybus_free_gbuf(operation->request); kfree(operation); } diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 0dff703..8279a00 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -50,17 +50,23 @@ struct gb_operation; typedef void (*gb_operation_callback)(struct gb_operation *); struct gb_operation { struct gb_connection *connection; - struct gbuf *gbuf; - void *payload; /* sender data */ + struct gbuf *request; + struct gbuf *response; + gb_operation_callback callback; /* If asynchronous */ struct completion completion; /* Used if no callback */ u8 result; struct list_head links; /* connection->operations */ + + /* These are what's used by caller */ + void *request_payload; + void *response_payload; }; struct gb_operation *gb_operation_create(struct gb_connection *connection, - size_t size, u8 type); + u8 type, size_t request_size, + size_t response_size); void gb_operation_destroy(struct gb_operation *operation); int gb_operation_wait(struct gb_operation *operation); -- cgit v0.10.2 From 84d148b10e26d55b41726c7b5a6d227f10b39b0a Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 16 Oct 2014 06:35:32 -0500 Subject: greybus: add gb_operation_find() Add a red-black tree indexed by operation id to a connection to allow pending operations (whose requests are in-flight) to be found when their matching response is recieved. Assign the id at the time an operation is inserted, and update the operation's message header(s) to include it. Rename gb_connection_op_id() to be more consistent with the naming conventions being used elsewhere. (Noting now that this may switch to a simple list implementation based on Greg's assertion that lists are faster than red-black trees for up to a few hundred entries.) Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 1a2bec2..740f491 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -141,6 +141,7 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, spin_unlock_irq(&gb_connections_lock); INIT_LIST_HEAD(&connection->operations); + connection->pending = RB_ROOT; atomic_set(&connection->op_cycle, 0); return connection; @@ -168,7 +169,7 @@ void gb_connection_destroy(struct gb_connection *connection) kfree(connection); } -u16 gb_connection_op_id(struct gb_connection *connection) +u16 gb_connection_operation_id(struct gb_connection *connection) { return (u16)(atomic_inc_return(&connection->op_cycle) % U16_MAX); } diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 89d58e5..5862ce0 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -24,6 +24,7 @@ struct gb_connection { enum greybus_protocol protocol; struct list_head operations; + struct rb_root pending; /* awaiting reponse */ atomic_t op_cycle; void *private; @@ -36,7 +37,7 @@ void gb_connection_destroy(struct gb_connection *connection); struct gb_connection *gb_hd_connection_find(struct greybus_host_device *hd, u16 cport_id); -u16 gb_connection_op_id(struct gb_connection *connection); +u16 gb_connection_operation_id(struct gb_connection *connection); __printf(2, 3) void gb_connection_err(struct gb_connection *connection, const char *fmt, ...); diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 43ad244..b56a2b9 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -44,6 +44,75 @@ struct gb_operation_msg_hdr { /* XXX Could be per-host device, per-module, or even per-connection */ static DEFINE_SPINLOCK(gb_operations_lock); +static void gb_operation_insert(struct gb_operation *operation) +{ + struct gb_connection *connection = operation->connection; + struct rb_root *root = &connection->pending; + struct rb_node *node = &operation->node; + struct rb_node **link = &root->rb_node; + struct rb_node *above = NULL; + struct gb_operation_msg_hdr *header; + __le16 wire_id; + + /* + * Assign the operation's id, and store it in the header of + * both request and response message headers. + */ + operation->id = gb_connection_operation_id(connection); + wire_id = cpu_to_le16(operation->id); + header = operation->request->transfer_buffer; + header->id = wire_id; + + /* OK, insert the operation into its connection's tree */ + spin_lock_irq(&gb_operations_lock); + + while (*link) { + struct gb_operation *other; + + above = *link; + other = rb_entry(above, struct gb_operation, node); + header = other->request->transfer_buffer; + if (other->id > operation->id) + link = &above->rb_left; + else if (other->id < operation->id) + link = &above->rb_right; + } + rb_link_node(node, above, link); + rb_insert_color(node, root); + + spin_unlock_irq(&gb_operations_lock); +} + +static void gb_operation_remove(struct gb_operation *operation) +{ + spin_lock_irq(&gb_operations_lock); + rb_erase(&operation->node, &operation->connection->pending); + spin_unlock_irq(&gb_operations_lock); +} + +static struct gb_operation * +gb_operation_find(struct gb_connection *connection, u16 id) +{ + struct gb_operation *operation; + struct rb_node *node; + bool found = false; + + spin_lock_irq(&gb_operations_lock); + node = connection->pending.rb_node; + while (node && !found) { + operation = rb_entry(node, struct gb_operation, node); + if (operation->id > id) + node = node->rb_left; + else if (operation->id < id) + node = node->rb_right; + else + found = true; + } + spin_unlock_irq(&gb_operations_lock); + + return found ? operation : NULL; +} + /* * An operations's response message has arrived. If no callback was * supplied it was submitted for asynchronous completion, so we notify @@ -93,6 +162,7 @@ int gb_operation_submit(struct gb_operation *operation, * setting the operation id and submitting the gbuf. */ operation->callback = callback; + gb_operation_insert(operation); ret = greybus_submit_gbuf(operation->request, GFP_KERNEL); if (ret) return ret; @@ -107,7 +177,21 @@ int gb_operation_submit(struct gb_operation *operation, */ static void gb_operation_gbuf_complete(struct gbuf *gbuf) { - /* TODO */ + struct gb_operation *operation; + struct gb_operation_msg_hdr *header; + u16 id; + + /* + * This isn't right, but it keeps things balanced until we + * can set up operation response handling. + */ + header = gbuf->transfer_buffer; + id = le16_to_cpu(header->id); + operation = gb_operation_find(gbuf->connection, id); + if (operation) + gb_operation_remove(operation); + else + gb_connection_err(gbuf->connection, "operation not found"); } /* diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 8279a00..5d863ed 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -52,12 +52,14 @@ struct gb_operation { struct gb_connection *connection; struct gbuf *request; struct gbuf *response; + u16 id; + u8 result; gb_operation_callback callback; /* If asynchronous */ struct completion completion; /* Used if no callback */ - u8 result; struct list_head links; /* connection->operations */ + struct rb_node node; /* connection->pending */ /* These are what's used by caller */ void *request_payload; -- cgit v0.10.2 From d90c25b0a279b006becc36c166f27e99578409cd Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 16 Oct 2014 06:35:33 -0500 Subject: greybus: let operation layer examine incoming data Give the operation layer a chance to examine incoming data so that it can handle it appropriately. Treat the data as an operation message header. If it's a response, look up the operation it's associated with. If it's not, create a new operation. Copy the incoming data into the request or response buffer. The next patch adds a work queue to pick up handling the request or response from there. Get rid of gb_operation_submit(). Instead, we have two functions, one for sending an operation's request message, the other for sending an operation's response message. Not fully functional yet, still just filling things in... Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 6580deb..97b45e9 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -167,6 +167,7 @@ void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, "nonexistent connection (%zu bytes dropped)\n", length); return; } + gb_connection_operation_recv(connection, data, length); /* first check to see if we have a cport handler for this cport */ ch = &cport_handler[cport_id]; diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index b56a2b9..092ceb6 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -20,6 +20,11 @@ #define GB_OPERATION_TYPE_RESPONSE 0x80 /* + * XXX This needs to be coordinated with host driver parameters + */ +#define GB_OPERATION_MESSAGE_SIZE_MAX 4096 + +/* * All operation messages (both requests and responses) begin with * a common header that encodes the size of the data (header * included). This header also contains a unique identifier, which @@ -93,7 +98,7 @@ static void gb_operation_remove(struct gb_operation *operation) static struct gb_operation * gb_operation_find(struct gb_connection *connection, u16 id) { - struct gb_operation *operation; + struct gb_operation *operation = NULL; struct rb_node *node; bool found = false; @@ -121,10 +126,12 @@ gb_operation_find(struct gb_connection *connection, u16 id) */ void gb_operation_complete(struct gb_operation *operation) { + /* XXX Should probably report bad status if no callback */ if (operation->callback) operation->callback(operation); else complete_all(&operation->completion); + gb_operation_destroy(operation); } /* @@ -142,41 +149,11 @@ int gb_operation_wait(struct gb_operation *operation) } /* - * Submit an outbound operation. The caller has filled in any - * payload so the request message is ready to go. If non-null, - * the callback function supplied will be called when the response - * message has arrived indicating the operation is complete. A null - * callback function is used for a synchronous request; return from - * this function won't occur until the operation is complete (or an - * interrupt occurs). - */ -int gb_operation_submit(struct gb_operation *operation, - gb_operation_callback callback) -{ - int ret; - - /* - * XXX - * I think the order of operations is going to be - * significant, and if so, we may need a mutex to surround - * setting the operation id and submitting the gbuf. - */ - operation->callback = callback; - gb_operation_insert(operation); - ret = greybus_submit_gbuf(operation->request, GFP_KERNEL); - if (ret) - return ret; - if (!callback) - ret = gb_operation_wait(operation); - - return ret; -} - -/* * Called when an operation buffer completes. */ static void gb_operation_gbuf_complete(struct gbuf *gbuf) { + /* Don't do anything */ struct gb_operation *operation; struct gb_operation_msg_hdr *header; u16 id; @@ -310,3 +287,94 @@ void gb_operation_destroy(struct gb_operation *operation) kfree(operation); } + +/* + * Send an operation request message. The caller has filled in + * any payload so the request message is ready to go. If non-null, + * the callback function supplied will be called when the response + * message has arrived indicating the operation is complete. A null + * callback function is used for a synchronous request; return from + * this function won't occur until the operation is complete (or an + * interrupt occurs). + */ +int gb_operation_request_send(struct gb_operation *operation, + gb_operation_callback callback) +{ + int ret; + + /* + * XXX + * I think the order of operations is going to be + * significant, and if so, we may need a mutex to surround + * setting the operation id and submitting the gbuf. + */ + operation->callback = callback; + gb_operation_insert(operation); + ret = greybus_submit_gbuf(operation->request, GFP_KERNEL); + if (ret) + return ret; + if (!callback) + ret = gb_operation_wait(operation); + + return ret; +} + +/* + * Send a response for an incoming operation request. + */ +int gb_operation_response_send(struct gb_operation *operation) +{ + /* XXX + * Caller needs to have set operation->response->actual_length + */ + gb_operation_remove(operation); + gb_operation_destroy(operation); + + return 0; +} + +void gb_connection_operation_recv(struct gb_connection *connection, + void *data, size_t size) +{ + struct gb_operation_msg_hdr *header; + struct gb_operation *operation; + struct gbuf *gbuf; + u16 msg_size; + + if (size > GB_OPERATION_MESSAGE_SIZE_MAX) { + gb_connection_err(connection, "message too big"); + return; + } + + header = data; + msg_size = le16_to_cpu(header->size); + if (header->type & GB_OPERATION_TYPE_RESPONSE) { + u16 id = le16_to_cpu(header->id); + + operation = gb_operation_find(connection, id); + if (!operation) { + gb_connection_err(connection, "operation not found"); + return; + } + gb_operation_remove(operation); + gbuf = operation->response; + if (size > gbuf->transfer_buffer_length) { + gb_connection_err(connection, "recv buffer too small"); + return; + } + } else { + WARN_ON(msg_size != size); + operation = gb_operation_create(connection, header->type, + msg_size, 0); + if (!operation) { + gb_connection_err(connection, "can't create operation"); + return; + } + gbuf = operation->request; + } + + memcpy(gbuf->transfer_buffer, data, msg_size); + gbuf->actual_length = msg_size; + + /* XXX And now we let a work queue handle the rest */ +} diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 5d863ed..2ed708a 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -66,11 +66,18 @@ struct gb_operation { void *response_payload; }; +void gb_connection_operation_recv(struct gb_connection *connection, + void *data, size_t size); + struct gb_operation *gb_operation_create(struct gb_connection *connection, u8 type, size_t request_size, size_t response_size); void gb_operation_destroy(struct gb_operation *operation); +int gb_operation_request_send(struct gb_operation *operation, + gb_operation_callback callback); +int gb_operation_response_send(struct gb_operation *operation); + int gb_operation_wait(struct gb_operation *operation); void gb_operation_complete(struct gb_operation *operation); -- cgit v0.10.2 From 2eb585f8df3f2121751ff8cf9b2cd8040575bff2 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 16 Oct 2014 06:35:34 -0500 Subject: greybus: move receive handling to operation layer Create a work queue to do the bulk of processing of received operation request or response messages. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 720ab47..b5f666a 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -284,6 +284,12 @@ static int __init gb_init(void) goto error_gbuf; } + retval = gb_operation_init(); + if (retval) { + pr_err("gb_operation_init failed\n"); + goto error_operation; + } + retval = gb_tty_init(); if (retval) { pr_err("gb_tty_init failed\n"); @@ -293,6 +299,9 @@ static int __init gb_init(void) return 0; error_tty: + gb_operation_exit(); + +error_operation: gb_gbuf_exit(); error_gbuf: @@ -310,6 +319,7 @@ error_bus: static void __exit gb_exit(void) { gb_tty_exit(); + gb_operation_exit(); gb_gbuf_exit(); gb_ap_exit(); bus_unregister(&greybus_bus_type); diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 092ceb6..7753bf7 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -24,6 +24,9 @@ */ #define GB_OPERATION_MESSAGE_SIZE_MAX 4096 +/* Workqueue to handle Greybus operation completions. */ +static struct workqueue_struct *gb_operation_recv_workqueue; + /* * All operation messages (both requests and responses) begin with * a common header that encodes the size of the data (header @@ -126,16 +129,13 @@ gb_operation_find(struct gb_connection *connection, u16 id) */ void gb_operation_complete(struct gb_operation *operation) { - /* XXX Should probably report bad status if no callback */ if (operation->callback) operation->callback(operation); else complete_all(&operation->completion); - gb_operation_destroy(operation); } -/* - * Wait for a submitted operatnoi to complete */ +/* Wait for a submitted operation to complete */ int gb_operation_wait(struct gb_operation *operation) { int ret; @@ -148,46 +148,100 @@ int gb_operation_wait(struct gb_operation *operation) } + +typedef void (*gb_operation_recv_handler)(struct gb_operation *operation); +static gb_operation_recv_handler gb_operation_recv_handlers[] = { + [GREYBUS_PROTOCOL_CONTROL] = NULL, + [GREYBUS_PROTOCOL_AP] = NULL, + [GREYBUS_PROTOCOL_GPIO] = NULL, + [GREYBUS_PROTOCOL_I2C] = NULL, + [GREYBUS_PROTOCOL_UART] = NULL, + [GREYBUS_PROTOCOL_HID] = NULL, + [GREYBUS_PROTOCOL_VENDOR] = NULL, +}; + +static void gb_operation_request_handle(struct gb_operation *operation) +{ + u8 protocol = operation->connection->protocol; + + /* Subtract one from array size to stay within u8 range */ + if (protocol <= (u8)(ARRAY_SIZE(gb_operation_recv_handlers) - 1)) { + gb_operation_recv_handler handler; + + handler = gb_operation_recv_handlers[protocol]; + if (handler) { + handler(operation); /* Handle the request */ + return; + } + } + + gb_connection_err(operation->connection, "unrecognized protocol %u\n", + (unsigned int)protocol); + operation->result = GB_OP_PROTOCOL_BAD; + gb_operation_complete(operation); +} + /* - * Called when an operation buffer completes. + * Either this operation contains an incoming request, or its + * response has arrived. An incoming request will have a null + * response buffer pointer (it is the responsibility of the request + * handler to allocate and fill in the response buffer). */ -static void gb_operation_gbuf_complete(struct gbuf *gbuf) +static void gb_operation_recv_work(struct work_struct *recv_work) { - /* Don't do anything */ struct gb_operation *operation; - struct gb_operation_msg_hdr *header; - u16 id; + bool incoming_request; - /* - * This isn't right, but it keeps things balanced until we - * can set up operation response handling. - */ - header = gbuf->transfer_buffer; - id = le16_to_cpu(header->id); - operation = gb_operation_find(gbuf->connection, id); - if (operation) - gb_operation_remove(operation); + operation = container_of(recv_work, struct gb_operation, recv_work); + incoming_request = operation->response == NULL; + if (incoming_request) + gb_operation_request_handle(operation); + gb_operation_complete(operation); + + /* We're finished with the buffer we read into */ + if (incoming_request) + greybus_gbuf_finished(operation->request); else - gb_connection_err(gbuf->connection, "operation not found"); + greybus_gbuf_finished(operation->response); +} + +/* + * Buffer completion function. We get notified whenever any buffer + * completes. For outbound messages, this tells us that the message + * has been sent. For inbound messages, it means the data has + * landed in the buffer and is ready to be processed. + * + * Either way, we don't do anything. We don't really care when an + * outbound message has been sent, and for incoming messages we + * we'll be done with everything we need to do before we mark it + * finished. + * + * XXX We may want to record that a buffer is (or is no longer) in flight. + */ +static void gb_operation_gbuf_complete(struct gbuf *gbuf) +{ + return; } /* * Allocate a buffer to be used for an operation request or response - * message. Both types of message contain a header, which is filled - * in here. W + * message. For outgoing messages, both types of message contain a + * common header, which is filled in here. Incoming requests or + * responses also contain the same header, but there's no need to + * initialize it here (it'll be overwritten by the incoming + * message). */ struct gbuf *gb_operation_gbuf_create(struct gb_operation *operation, - u8 type, size_t size, bool outbound) + u8 type, size_t size, bool data_out) { struct gb_connection *connection = operation->connection; struct gb_operation_msg_hdr *header; struct gbuf *gbuf; - gfp_t gfp_flags = outbound ? GFP_KERNEL : GFP_ATOMIC; + gfp_t gfp_flags = data_out ? GFP_KERNEL : GFP_ATOMIC; - /* Operation buffers hold a header in addition to their payload */ size += sizeof(*header); gbuf = greybus_alloc_gbuf(connection, gb_operation_gbuf_complete, - size, outbound, gfp_flags, operation); + size, data_out, gfp_flags, operation); if (!gbuf) return NULL; @@ -222,11 +276,7 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, { struct gb_operation *operation; gfp_t gfp_flags = response_size ? GFP_KERNEL : GFP_ATOMIC; - - if (!request_size) { - gb_connection_err(connection, "zero-sized request"); - return NULL; - } + bool outgoing = response_size != 0; /* XXX Use a slab cache */ operation = kzalloc(sizeof(*operation), gfp_flags); @@ -235,7 +285,8 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, operation->connection = connection; /* XXX refcount? */ operation->request = gb_operation_gbuf_create(operation, type, - request_size, true); + request_size, + outgoing); if (!operation->request) { kfree(operation); return NULL; @@ -245,10 +296,11 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, /* We always use the full request buffer */ operation->request->actual_length = request_size; - if (response_size) { + if (outgoing) { type |= GB_OPERATION_TYPE_RESPONSE; operation->response = gb_operation_gbuf_create(operation, - type, response_size, false); + type, response_size, + false); if (!operation->response) { greybus_free_gbuf(operation->request); kfree(operation); @@ -259,6 +311,7 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, sizeof(struct gb_operation_msg_hdr); } + INIT_WORK(&operation->recv_work, gb_operation_recv_work); operation->callback = NULL; /* set at submit time */ init_completion(&operation->completion); @@ -333,6 +386,11 @@ int gb_operation_response_send(struct gb_operation *operation) return 0; } +/* + * Handle data arriving on a connection. This is called in + * interrupt context, so just copy the incoming data into a buffer + * and do remaining handling via a work queue. + */ void gb_connection_operation_recv(struct gb_connection *connection, void *data, size_t size) { @@ -354,7 +412,7 @@ void gb_connection_operation_recv(struct gb_connection *connection, operation = gb_operation_find(connection, id); if (!operation) { gb_connection_err(connection, "operation not found"); - return; + return; } gb_operation_remove(operation); gbuf = operation->response; @@ -376,5 +434,20 @@ void gb_connection_operation_recv(struct gb_connection *connection, memcpy(gbuf->transfer_buffer, data, msg_size); gbuf->actual_length = msg_size; - /* XXX And now we let a work queue handle the rest */ + /* The rest will be handled in work queue context */ + queue_work(gb_operation_recv_workqueue, &operation->recv_work); +} + +int gb_operation_init(void) +{ + gb_operation_recv_workqueue = alloc_workqueue("greybus_recv", 0, 1); + if (!gb_operation_recv_workqueue) + return -ENOMEM; + + return 0; +} + +void gb_operation_exit(void) +{ + destroy_workqueue(gb_operation_recv_workqueue); } diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 2ed708a..d5ec582 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -16,6 +16,7 @@ enum gb_operation_status { GB_OP_INVALID = 1, GB_OP_NO_MEMORY = 2, GB_OP_INTERRUPTED = 3, + GB_OP_PROTOCOL_BAD = 4, }; /* @@ -55,6 +56,7 @@ struct gb_operation { u16 id; u8 result; + struct work_struct recv_work; gb_operation_callback callback; /* If asynchronous */ struct completion completion; /* Used if no callback */ @@ -81,4 +83,7 @@ int gb_operation_response_send(struct gb_operation *operation); int gb_operation_wait(struct gb_operation *operation); void gb_operation_complete(struct gb_operation *operation); +int gb_operation_init(void); +void gb_operation_exit(void); + #endif /* !__OPERATION_H */ -- cgit v0.10.2 From 574341c67213afdc9dcb5aefb4f6fa84644438bb Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 16 Oct 2014 06:35:35 -0500 Subject: greybus: add device initialization Set up the infrastructure for initializing connections based on their protocol. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 740f491..0143a4f 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -191,3 +191,27 @@ void gb_connection_err(struct gb_connection *connection, const char *fmt, ...) va_end(args); } + +/* + * XXX Protocols should have a set of function pointers: + * ->init (called here, to initialize the device) + * ->input_handler + * ->exit (reverse of init) + */ +int gb_connection_init(struct gb_connection *connection) +{ + switch (connection->protocol) { + case GREYBUS_PROTOCOL_I2C: + case GREYBUS_PROTOCOL_CONTROL: + case GREYBUS_PROTOCOL_AP: + case GREYBUS_PROTOCOL_GPIO: + case GREYBUS_PROTOCOL_UART: + case GREYBUS_PROTOCOL_HID: + case GREYBUS_PROTOCOL_VENDOR: + default: + gb_connection_err(connection, "unimplemented protocol %u", + (u32)connection->protocol); + break; + } + return -ENXIO; +} diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 5862ce0..bb22c52 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -34,6 +34,8 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, u16 cport_id, enum greybus_protocol protocol); void gb_connection_destroy(struct gb_connection *connection); +int gb_connection_init(struct gb_connection *connection); + struct gb_connection *gb_hd_connection_find(struct greybus_host_device *hd, u16 cport_id); diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index b5f666a..38f867d 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -182,8 +182,11 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, dev_set_name(&gmod->dev, "%d", module_id); retval = device_add(&gmod->dev); - if (!retval) - return; /* Success */ + if (retval) + goto error; + + gb_module_interfaces_init(gmod); + return; error: gb_module_destroy(gmod); @@ -253,7 +256,6 @@ void greybus_remove_hd(struct greybus_host_device *hd) } EXPORT_SYMBOL_GPL(greybus_remove_hd); - static int __init gb_init(void) { int retval; diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 1970106..d92ba51 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -265,6 +265,8 @@ void gb_deregister_cport_complete(u16 cport_id); extern const struct attribute_group *greybus_module_groups[]; +int gb_i2c_device_init(struct gb_connection *connection); + int gb_tty_init(void); void gb_tty_exit(void); diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index b9dd930..0c2fdd3 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -57,3 +57,18 @@ void gb_interface_destroy(struct gb_interface *interface) /* kref_put(gmod); */ kfree(interface); } + +int gb_interface_connections_init(struct gb_interface *interface) +{ + struct gb_connection *connection; + int ret = 0; + + list_for_each_entry(connection, &interface->connections, + interface_links) { + ret = gb_connection_init(connection); + if (ret) + break; + } + + return ret; +} diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 9c9ffe7..1019a98 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -22,4 +22,6 @@ struct gb_interface { struct gb_interface *gb_interface_create(struct gb_module *gmod, u8 module_id); void gb_interface_destroy(struct gb_interface *interface); +int gb_interface_connections_init(struct gb_interface *interface); + #endif /* __INTERFACE_H */ diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index 1970e7b..699cd00 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -55,39 +55,52 @@ const struct greybus_module_id *gb_module_match_id(struct gb_module *gmod, */ struct gb_module *gb_module_create(struct greybus_host_device *hd, u8 module_id) { - struct gb_module *module; + struct gb_module *gmod; - module = kzalloc(sizeof(*module), GFP_KERNEL); - if (!module) + gmod = kzalloc(sizeof(*gmod), GFP_KERNEL); + if (!gmod) return NULL; - module->hd = hd; /* XXX refcount? */ - module->module_id = module_id; - INIT_LIST_HEAD(&module->interfaces); + gmod->hd = hd; /* XXX refcount? */ + gmod->module_id = module_id; + INIT_LIST_HEAD(&gmod->interfaces); spin_lock_irq(&gb_modules_lock); - list_add_tail(&module->links, &hd->modules); + list_add_tail(&gmod->links, &hd->modules); spin_unlock_irq(&gb_modules_lock); - return module; + return gmod; } /* * Tear down a previously set up module. */ -void gb_module_destroy(struct gb_module *module) +void gb_module_destroy(struct gb_module *gmod) { - if (WARN_ON(!module)) + if (WARN_ON(!gmod)) return; - kfree(module->product_string); - kfree(module->vendor_string); + kfree(gmod->product_string); + kfree(gmod->vendor_string); spin_lock_irq(&gb_modules_lock); - list_del(&module->links); + list_del(&gmod->links); spin_unlock_irq(&gb_modules_lock); /* kref_put(module->hd); */ - kfree(module); + kfree(gmod); +} + +void gb_module_interfaces_init(struct gb_module *gmod) +{ + struct gb_interface *interface; + int ret = 0; + + list_for_each_entry(interface, &gmod->interfaces, links) { + ret = gb_interface_connections_init(interface); + if (ret) + dev_err(gmod->hd->parent, + "module interface init error %d\n", ret); + } } diff --git a/drivers/staging/greybus/module.h b/drivers/staging/greybus/module.h index 7b01950..114f157 100644 --- a/drivers/staging/greybus/module.h +++ b/drivers/staging/greybus/module.h @@ -62,4 +62,6 @@ struct gb_module *gb_module_create(struct greybus_host_device *hd, u8 module_id); void gb_module_destroy(struct gb_module *module); +void gb_module_interfaces_init(struct gb_module *gmod); + #endif /* __MODULE_H */ -- cgit v0.10.2 From c149f8ffb2cbd1fa77f2c964bc547577835af647 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 16 Oct 2014 06:35:36 -0500 Subject: greybus: kill off gbuf work queue At this point all incoming messages are handled by the operation code, so this obviates the need for the gbuf workqueue. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 97b45e9..12c8c23 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -15,17 +15,11 @@ #include #include #include -#include #include "greybus.h" -static void cport_process_event(struct work_struct *work); - static struct kmem_cache *gbuf_head_cache; -/* Workqueue to handle Greybus buffer completions. */ -static struct workqueue_struct *gbuf_workqueue; - /** * greybus_alloc_gbuf - allocate a greybus buffer * @@ -57,7 +51,6 @@ struct gbuf *greybus_alloc_gbuf(struct gb_connection *connection, kref_init(&gbuf->kref); gbuf->connection = connection; - INIT_WORK(&gbuf->event, cport_process_event); gbuf->outbound = outbound; gbuf->complete = complete; gbuf->context = context; @@ -114,15 +107,6 @@ int greybus_kill_gbuf(struct gbuf *gbuf) return -ENOMEM; } -static void cport_process_event(struct work_struct *work) -{ - struct gbuf *gbuf = container_of(work, struct gbuf, event); - - /* Call the completion handler, then drop our reference */ - gbuf->complete(gbuf); - greybus_put_gbuf(gbuf); -} - #define MAX_CPORTS 1024 struct gb_cport_handler { gbuf_complete_t handler; @@ -196,24 +180,18 @@ void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, */ memcpy(gbuf->transfer_buffer, data, length); gbuf->actual_length = length; - - queue_work(gbuf_workqueue, &gbuf->event); } EXPORT_SYMBOL_GPL(greybus_cport_in); /* Can be called in interrupt context, do the work and get out of here */ void greybus_gbuf_finished(struct gbuf *gbuf) { - queue_work(gbuf_workqueue, &gbuf->event); + gbuf->complete(gbuf); } EXPORT_SYMBOL_GPL(greybus_gbuf_finished); int gb_gbuf_init(void) { - gbuf_workqueue = alloc_workqueue("greybus_gbuf", 0, 1); - if (!gbuf_workqueue) - return -ENOMEM; - gbuf_head_cache = kmem_cache_create("gbuf_head_cache", sizeof(struct gbuf), 0, 0, NULL); return 0; @@ -221,6 +199,5 @@ int gb_gbuf_init(void) void gb_gbuf_exit(void) { - destroy_workqueue(gbuf_workqueue); kmem_cache_destroy(gbuf_head_cache); } diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index d92ba51..854122b 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -134,7 +134,6 @@ struct gbuf { bool outbound; /* AP-relative data direction */ void *context; - struct work_struct event; gbuf_complete_t complete; }; -- cgit v0.10.2 From 98d35ba22e6328491559892e796f276de7ba3d00 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 16 Oct 2014 06:35:37 -0500 Subject: greybus: kill old cport handlers The original CPort message handlers are not needed. All incoming data is passed to handlers based on the protocol used over the connection over which the data was transferred. So get rid of the old CPort handler code. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 12c8c23..348ee7c2 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -141,8 +141,6 @@ void gb_deregister_cport_complete(u16 cport_id) void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, u8 *data, size_t length) { - struct gb_cport_handler *ch; - struct gbuf *gbuf; struct gb_connection *connection; connection = gb_hd_connection_find(hd, cport_id); @@ -152,34 +150,6 @@ void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, return; } gb_connection_operation_recv(connection, data, length); - - /* first check to see if we have a cport handler for this cport */ - ch = &cport_handler[cport_id]; - if (!ch->handler) { - /* Ugh, drop the data on the floor, after logging it... */ - dev_err(hd->parent, - "Received data for cport %d, but no handler!\n", - cport_id); - return; - } - - gbuf = greybus_alloc_gbuf(connection, ch->handler, length, false, - GFP_ATOMIC, ch->context); - - if (!gbuf) { - /* Again, something bad went wrong, log it... */ - pr_err("can't allocate gbuf???\n"); - return; - } - - /* - * FIXME: - * Very dumb copy data method for now, if this is slow (odds are it will - * be, we should move to a model where the hd "owns" all buffers, but we - * want something up and working first for now. - */ - memcpy(gbuf->transfer_buffer, data, length); - gbuf->actual_length = length; } EXPORT_SYMBOL_GPL(greybus_cport_in); -- cgit v0.10.2 From ed8800dc376edd7aa10815fb9df83a66c7557031 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 16 Oct 2014 06:35:38 -0500 Subject: greybus: add i2c driver This patch adds the i2c driver, based on the use of Greybus operations over Greybus connections. It basically replaces almost all of what was previously found in "i2c-gb.c". When gb_connection_device_init(connection) is called, any connection that talks the GREYBUS_PROTOCOL_I2C is passed to gb_i2c_device_init() to be initialized. Initialization involves verifying the code is able to support the version of the protocol. For I2C, we then query the functionality mask, and set the retry count and timeout to default values. After that, we set up the i2c device and associate it with the connection. The i2c_algorithm methods are then implemented by translating them into Greybus operations. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 0143a4f..fc692f0 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -202,6 +202,7 @@ int gb_connection_init(struct gb_connection *connection) { switch (connection->protocol) { case GREYBUS_PROTOCOL_I2C: + return gb_i2c_device_init(connection); case GREYBUS_PROTOCOL_CONTROL: case GREYBUS_PROTOCOL_AP: case GREYBUS_PROTOCOL_GPIO: diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index 0da1958..c4e47ef 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -14,127 +14,516 @@ #include "greybus.h" struct gb_i2c_device { - struct i2c_adapter *adapter; - struct gb_module *gmod; + struct gb_connection *connection; + u8 version_major; + u8 version_minor; + + u32 functionality; + u16 timeout_msec; + u8 retries; + + struct i2c_adapter *adapter; +}; + +/* Version of the Greybus i2c protocol we support */ +#define GB_I2C_VERSION_MAJOR 0x00 +#define GB_I2C_VERSION_MINOR 0x01 + +/* Greybus i2c request types */ +#define GB_I2C_TYPE_INVALID 0x00 +#define GB_I2C_TYPE_PROTOCOL_VERSION 0x01 +#define GB_I2C_TYPE_FUNCTIONALITY 0x02 +#define GB_I2C_TYPE_TIMEOUT 0x03 +#define GB_I2C_TYPE_RETRIES 0x04 +#define GB_I2C_TYPE_TRANSFER 0x05 +#define GB_I2C_TYPE_RESPONSE 0x80 /* OR'd with rest */ + +#define GB_I2C_RETRIES_DEFAULT 3 +#define GB_I2C_TIMEOUT_DEFAULT 1000 /* milliseconds */ + +/* version request has no payload */ +struct gb_i2c_proto_version_response { + __u8 status; + __u8 major; + __u8 minor; +}; + +/* functionality request has no payload */ +struct gb_i2c_functionality_response { + __u8 status; + __le32 functionality; }; -static const struct greybus_module_id id_table[] = { - { GREYBUS_DEVICE(0x42, 0x42) }, /* make shit up */ - { }, /* terminating NULL entry */ +struct gb_i2c_timeout_request { + __le16 msec; +}; +struct gb_i2c_timeout_response { + __u8 status; +}; + +struct gb_i2c_retries_request { + __u8 retries; +}; +struct gb_i2c_retries_response { + __u8 status; +}; + +/* + * Outgoing data immediately follows the op count and ops array. + * The data for each write (master -> slave) op in the array is sent + * in order, with no (e.g. pad) bytes separating them. + * + * Short reads cause the entire transfer request to fail So response + * payload consists only of bytes read, and the number of bytes is + * exactly what was specified in the corresponding op. Like + * outgoing data, the incoming data is in order and contiguous. + */ +struct gb_i2c_transfer_op { + __le16 addr; + __le16 flags; + __le16 size; }; -/* We BETTER be able to do SMBUS protocl calls, otherwise we are bit-banging the - * slowest thing possible over the fastest bus possible, crazy... - * FIXME - research this, for now just assume we can +struct gb_i2c_transfer_request { + __le16 op_count; + struct gb_i2c_transfer_op ops[0]; /* op_count of these */ +}; +struct gb_i2c_transfer_response { + __u8 status; + __u8 data[0]; /* inbound data */ +}; + +/* + * This request only uses the connection field, and if successful, + * fills in the major and minor protocol version of the target. + */ +static int gb_i2c_proto_version_operation(struct gb_i2c_device *gb_i2c_dev) +{ + struct gb_connection *connection = gb_i2c_dev->connection; + struct gb_operation *operation; + struct gb_i2c_proto_version_response *response; + int ret; + + /* A protocol version request has no payload */ + operation = gb_operation_create(connection, + GB_I2C_TYPE_PROTOCOL_VERSION, + 0, sizeof(*response)); + if (!operation) + return -ENOMEM; + + /* Synchronous operation--no callback */ + ret = gb_operation_request_send(operation, NULL); + if (ret) { + pr_err("version operation failed (%d)\n", ret); + goto out; + } + + response = operation->response_payload; + if (response->status) { + gb_connection_err(connection, "version response %hhu", + response->status); + ret = -EIO; + } else { + if (response->major > GB_I2C_VERSION_MAJOR) { + pr_err("unsupported major version (%hhu > %hhu)\n", + response->major, GB_I2C_VERSION_MAJOR); + ret = -ENOTSUPP; + goto out; + } + gb_i2c_dev->version_major = response->major; + gb_i2c_dev->version_minor = response->minor; + } +out: + + gb_operation_destroy(operation); + + return ret; +} + +/* + * Map Greybus i2c functionality bits into Linux ones */ +static u32 gb_i2c_functionality_map(u32 gb_i2c_functionality) +{ + return gb_i2c_functionality; /* All bits the same for now */ +} + +static int gb_i2c_functionality_operation(struct gb_i2c_device *gb_i2c_dev) +{ + struct gb_connection *connection = gb_i2c_dev->connection; + struct gb_operation *operation; + struct gb_i2c_functionality_response *response; + u32 functionality; + int ret; + + /* A functionality request has no payload */ + operation = gb_operation_create(connection, + GB_I2C_TYPE_FUNCTIONALITY, + 0, sizeof(*response)); + if (!operation) + return -ENOMEM; + + /* Synchronous operation--no callback */ + ret = gb_operation_request_send(operation, NULL); + if (ret) { + pr_err("functionality operation failed (%d)\n", ret); + goto out; + } + + response = operation->response_payload; + if (response->status) { + gb_connection_err(connection, "functionality response %hhu", + response->status); + ret = -EIO; + } else { + functionality = le32_to_cpu(response->functionality); + gb_i2c_dev->functionality = + gb_i2c_functionality_map(functionality); + } +out: + gb_operation_destroy(operation); + return ret; +} -static s32 i2c_gb_access(struct i2c_adapter *adap, u16 addr, - unsigned short flags, char read_write, u8 command, - int size, union i2c_smbus_data *data) +static int gb_i2c_timeout_operation(struct gb_i2c_device *gb_i2c_dev, u16 msec) +{ + struct gb_connection *connection = gb_i2c_dev->connection; + struct gb_operation *operation; + struct gb_i2c_timeout_request *request; + struct gb_i2c_timeout_response *response; + int ret; + + operation = gb_operation_create(connection, GB_I2C_TYPE_TIMEOUT, + sizeof(*request), sizeof(*response)); + if (!operation) + return -ENOMEM; + request = operation->request_payload; + request->msec = cpu_to_le16(msec); + + /* Synchronous operation--no callback */ + ret = gb_operation_request_send(operation, NULL); + if (ret) { + pr_err("timeout operation failed (%d)\n", ret); + goto out; + } + + response = operation->response_payload; + if (response->status) { + gb_connection_err(connection, "timeout response %hhu", + response->status); + ret = -EIO; + } else { + gb_i2c_dev->timeout_msec = msec; + } +out: + gb_operation_destroy(operation); + + return ret; +} + +static int gb_i2c_retries_operation(struct gb_i2c_device *gb_i2c_dev, + u8 retries) +{ + struct gb_connection *connection = gb_i2c_dev->connection; + struct gb_operation *operation; + struct gb_i2c_retries_request *request; + struct gb_i2c_retries_response *response; + int ret; + + operation = gb_operation_create(connection, GB_I2C_TYPE_RETRIES, + sizeof(*request), sizeof(*response)); + if (!operation) + return -ENOMEM; + request = operation->request_payload; + request->retries = retries; + + /* Synchronous operation--no callback */ + ret = gb_operation_request_send(operation, NULL); + if (ret) { + pr_err("retries operation failed (%d)\n", ret); + goto out; + } + + response = operation->response_payload; + if (response->status) { + gb_connection_err(connection, "retries response %hhu", + response->status); + ret = -EIO; + } else { + gb_i2c_dev->retries = retries; + } +out: + gb_operation_destroy(operation); + + return ret; +} + + +/* + * Map Linux i2c_msg flags into Greybus i2c transfer op flags. + */ +static u16 gb_i2c_transfer_op_flags_map(u16 flags) +{ + return flags; /* All flags the same for now */ +} + +static void +gb_i2c_fill_transfer_op(struct gb_i2c_transfer_op *op, struct i2c_msg *msg) +{ + u16 flags = gb_i2c_transfer_op_flags_map(msg->flags); + + op->addr = cpu_to_le16(msg->addr); + op->flags = cpu_to_le16(flags); + op->size = cpu_to_le16(msg->len); +} + +static struct gb_operation * +gb_i2c_transfer_request(struct gb_connection *connection, + struct i2c_msg *msgs, u32 msg_count) +{ + struct gb_i2c_transfer_request *request; + struct gb_operation *operation; + struct gb_i2c_transfer_op *op; + struct i2c_msg *msg; + u32 data_out_size = 0; + u32 data_in_size = 1; /* Response begins with a status byte */ + size_t request_size; + void *data; + u16 op_count; + u32 i; + + if (msg_count > (u32)U16_MAX) { + gb_connection_err(connection, "msg_count (%u) too big", + msg_count); + return NULL; + } + op_count = (u16)msg_count; + + /* + * In addition to space for all message descriptors we need + * to have enough to hold all outbound message data. + */ + msg = msgs; + for (i = 0; i < msg_count; i++, msg++) + if (msg->flags & I2C_M_RD) + data_in_size += (u32)msg->len; + else + data_out_size += (u32)msg->len; + + request_size = sizeof(struct gb_i2c_transfer_request); + request_size += msg_count * sizeof(struct gb_i2c_transfer_op); + request_size += data_out_size; + + /* Response consists only of incoming data */ + operation = gb_operation_create(connection, GB_I2C_TYPE_TRANSFER, + request_size, data_in_size); + if (!operation) + return NULL; + + request = operation->request_payload; + request->op_count = cpu_to_le16(op_count); + /* Fill in the ops array */ + op = &request->ops[0]; + msg = msgs; + for (i = 0; i < msg_count; i++) + gb_i2c_fill_transfer_op(op++, msg++); + + if (!data_out_size) + return operation; + + /* Copy over the outgoing data; it starts after the last op */ + data = op; + msg = msgs; + for (i = 0; i < msg_count; i++) { + if (!(msg->flags & I2C_M_RD)) { + memcpy(data, msg->buf, msg->len); + data += msg->len; + } + msg++; + } + + return operation; +} + +static void gb_i2c_transfer_response(struct i2c_msg *msgs, u32 msg_count, + void *data) +{ + struct i2c_msg *msg = msgs; + u32 i; + + for (i = 0; i < msg_count; i++) { + if (msg->flags & I2C_M_RD) { + memcpy(msg->buf, data, msg->len); + data += msg->len; + } + msg++; + } +} + +static int gb_i2c_transfer_operation(struct gb_i2c_device *gb_i2c_dev, + struct i2c_msg *msgs, u32 msg_count) +{ + struct gb_connection *connection = gb_i2c_dev->connection; + struct gb_i2c_transfer_response *response; + struct gb_operation *operation; + int ret; + + operation = gb_i2c_transfer_request(connection, msgs, msg_count); + if (!operation) + return -ENOMEM; + + /* Synchronous operation--no callback */ + ret = gb_operation_request_send(operation, NULL); + if (ret) { + pr_err("transfer operation failed (%d)\n", ret); + goto out; + } + + response = operation->response_payload; + if (response->status) { + gb_connection_err(connection, "transfer response %hhu", + response->status); + ret = -EIO; + } else { + gb_i2c_transfer_response(msgs, msg_count, response->data); + ret = msg_count; + } +out: + gb_operation_destroy(operation); + + return ret; +} + +static int gb_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, + int msg_count) +{ + struct gb_i2c_device *gb_i2c_dev; + + gb_i2c_dev = i2c_get_adapdata(adap); + + return gb_i2c_transfer_operation(gb_i2c_dev, msgs, msg_count); +} + +#if 0 +/* Later */ +static int gb_i2c_smbus_xfer(struct i2c_adapter *adap, + u16 addr, unsigned short flags, char read_write, + u8 command, int size, union i2c_smbus_data *data) { struct gb_i2c_device *gb_i2c_dev; - struct gb_module *gmod; gb_i2c_dev = i2c_get_adapdata(adap); - gmod = gb_i2c_dev->gmod; - - // FIXME - do the actual work of sending a i2c message here... - switch (size) { - case I2C_SMBUS_QUICK: - case I2C_SMBUS_BYTE: - case I2C_SMBUS_BYTE_DATA: - case I2C_SMBUS_WORD_DATA: - case I2C_SMBUS_PROC_CALL: - case I2C_SMBUS_BLOCK_DATA: - case I2C_SMBUS_I2C_BLOCK_BROKEN: - case I2C_SMBUS_BLOCK_PROC_CALL: - case I2C_SMBUS_I2C_BLOCK_DATA: - default: - dev_err(&gmod->dev, "Unsupported transaction %d\n", size); - return -EOPNOTSUPP; - } return 0; } +#endif -static u32 i2c_gb_func(struct i2c_adapter *adapter) +static u32 gb_i2c_functionality(struct i2c_adapter *adap) { - // FIXME - someone figure out what we really can support, for now just guess... - return 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 | - I2C_FUNC_SMBUS_PEC | - I2C_FUNC_SMBUS_READ_I2C_BLOCK; + struct gb_i2c_device *gb_i2c_dev = i2c_get_adapdata(adap); + + return gb_i2c_dev->functionality; } -static const struct i2c_algorithm smbus_algorithm = { - .smbus_xfer = i2c_gb_access, - .functionality = i2c_gb_func, +static const struct i2c_algorithm gb_i2c_algorithm = { + .master_xfer = gb_i2c_master_xfer, + /* .smbus_xfer = gb_i2c_smbus_xfer, */ + .functionality = gb_i2c_functionality, }; -int gb_i2c_probe(struct gb_module *gmod, - const struct greybus_module_id *id) +/* + * Do initial setup of the i2c device. This includes verifying we + * can support it (based on the protocol version it advertises). + * If that's OK, we get and cached its functionality bits, and + * set up the retry count and timeout. + * + * Note: gb_i2c_dev->connection is assumed to have been valid. + */ +static int gb_i2c_device_setup(struct gb_i2c_device *gb_i2c_dev) +{ + int ret; + + /* First thing we need to do is check the version */ + ret = gb_i2c_proto_version_operation(gb_i2c_dev); + if (ret) + return ret; + + /* Assume the functionality never changes, just get it once */ + ret = gb_i2c_functionality_operation(gb_i2c_dev); + if (ret) + return ret; + + /* Set up our default retry count and timeout */ + ret = gb_i2c_retries_operation(gb_i2c_dev, GB_I2C_RETRIES_DEFAULT); + if (ret) + return ret; + + return gb_i2c_timeout_operation(gb_i2c_dev, GB_I2C_TIMEOUT_DEFAULT); +} + +int gb_i2c_device_init(struct gb_connection *connection) { struct gb_i2c_device *gb_i2c_dev; - struct i2c_adapter *adapter; - int retval; + struct i2c_adapter *adapter = NULL; + int ret; gb_i2c_dev = kzalloc(sizeof(*gb_i2c_dev), GFP_KERNEL); if (!gb_i2c_dev) return -ENOMEM; + + gb_i2c_dev->connection = connection; /* refcount? */ + + ret = gb_i2c_device_setup(gb_i2c_dev); + if (ret) + goto out_err; + + /* Looks good; allocate and set up our i2c adapter */ adapter = kzalloc(sizeof(*adapter), GFP_KERNEL); if (!adapter) { - kfree(gb_i2c_dev); - return -ENOMEM; + ret = -ENOMEM; + goto out_err; } - i2c_set_adapdata(adapter, gb_i2c_dev); adapter->owner = THIS_MODULE; adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - adapter->algo = &smbus_algorithm; - adapter->dev.parent = &gmod->dev; - adapter->retries = 3; /* we have to pick something... */ + adapter->algo = &gb_i2c_algorithm; + /* adapter->algo_data = what? */ + adapter->timeout = gb_i2c_dev->timeout_msec * HZ / 1000; + adapter->retries = gb_i2c_dev->retries; + + /* XXX I think this parent device is wrong, but it uses existing code */ + adapter->dev.parent = &connection->interface->gmod->dev; snprintf(adapter->name, sizeof(adapter->name), "Greybus i2c adapter"); - retval = i2c_add_adapter(adapter); - if (retval) { - dev_err(&gmod->dev, "Can not add SMBus adapter\n"); - goto error; - } + i2c_set_adapdata(adapter, gb_i2c_dev); + + ret = i2c_add_adapter(adapter); + if (ret) + goto out_err; - gb_i2c_dev->gmod = gmod; gb_i2c_dev->adapter = adapter; + connection->private = gb_i2c_dev; - gmod->gb_i2c_dev = gb_i2c_dev; return 0; -error: +out_err: kfree(adapter); + /* kref_put(gb_i2c_dev->connection) */ kfree(gb_i2c_dev); - return retval; + + return ret; } -void gb_i2c_disconnect(struct gb_module *gmod) +void gb_i2c_device_exit(struct gb_connection *connection) { - struct gb_i2c_device *gb_i2c_dev; + struct gb_i2c_device *gb_i2c_dev = connection->private; - gb_i2c_dev = gmod->gb_i2c_dev; - if (!gb_i2c_dev) - return; i2c_del_adapter(gb_i2c_dev->adapter); kfree(gb_i2c_dev->adapter); + /* kref_put(gb_i2c_dev->connection) */ kfree(gb_i2c_dev); } #if 0 -static struct greybus_driver i2c_gb_driver = { - .probe = gb_i2c_probe, - .disconnect = gb_i2c_disconnect, - .id_table = id_table, -}; - module_greybus_driver(i2c_gb_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Greg Kroah-Hartman "); diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 7753bf7..a49d929 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -148,13 +148,21 @@ int gb_operation_wait(struct gb_operation *operation) } +/* + * This handler is used if no operation response messages are ever + * expected for a given protocol. + */ +static void gb_operation_recv_none(struct gb_operation *operation) +{ + /* Nothing to do! */ +} typedef void (*gb_operation_recv_handler)(struct gb_operation *operation); static gb_operation_recv_handler gb_operation_recv_handlers[] = { [GREYBUS_PROTOCOL_CONTROL] = NULL, [GREYBUS_PROTOCOL_AP] = NULL, [GREYBUS_PROTOCOL_GPIO] = NULL, - [GREYBUS_PROTOCOL_I2C] = NULL, + [GREYBUS_PROTOCOL_I2C] = gb_operation_recv_none, [GREYBUS_PROTOCOL_UART] = NULL, [GREYBUS_PROTOCOL_HID] = NULL, [GREYBUS_PROTOCOL_VENDOR] = NULL, -- cgit v0.10.2 From bb2e1c9626c9bfe0b3558830a70681eaf1f71e2d Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 16 Oct 2014 06:35:39 -0500 Subject: greybus: initial operations-based GPIO driver First cut. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index fc692f0..a51b478 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -206,6 +206,7 @@ int gb_connection_init(struct gb_connection *connection) case GREYBUS_PROTOCOL_CONTROL: case GREYBUS_PROTOCOL_AP: case GREYBUS_PROTOCOL_GPIO: + return gb_gpio_controller_init(connection); case GREYBUS_PROTOCOL_UART: case GREYBUS_PROTOCOL_HID: case GREYBUS_PROTOCOL_VENDOR: diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index da20028..7f03676 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -12,101 +12,804 @@ #include #include "greybus.h" -struct gb_gpio_device { - struct gpio_chip chip; - struct gb_module *gmod; - struct gpio_chip *gpio; - // FIXME - some lock? +struct gb_gpio_line { + /* The following has to be an array of line_max entries */ + /* --> make them just a flags field */ + u8 active: 1, + direction: 1, /* 0 = output, 1 = input */ + value: 1; /* 0 = low, 1 = high */ + u16 debounce_usec; +}; + +struct gb_gpio_controller { + struct gb_connection *connection; + u8 version_major; + u8 version_minor; + u8 line_max; /* max line number */ + struct gb_gpio_line *lines; + + struct gpio_chip chip; + struct gpio_chip *gpio; +}; +#define gpio_chip_to_gb_gpio_controller(chip) \ + container_of(chip, struct gb_gpio_controller, chip) + +/* Version of the Greybus GPIO protocol we support */ +#define GB_GPIO_VERSION_MAJOR 0x00 +#define GB_GPIO_VERSION_MINOR 0x01 + +/* Greybus GPIO request types */ +#define GB_GPIO_TYPE_INVALID 0x00 +#define GB_GPIO_TYPE_PROTOCOL_VERSION 0x01 +#define GB_GPIO_TYPE_LINE_COUNT 0x02 +#define GB_GPIO_TYPE_ACTIVATE 0x03 +#define GB_GPIO_TYPE_DEACTIVATE 0x04 +#define GB_GPIO_TYPE_GET_DIRECTION 0x05 +#define GB_GPIO_TYPE_DIRECTION_IN 0x06 +#define GB_GPIO_TYPE_DIRECTION_OUT 0x07 +#define GB_GPIO_TYPE_GET_VALUE 0x08 +#define GB_GPIO_TYPE_SET_VALUE 0x09 +#define GB_GPIO_TYPE_SET_DEBOUNCE 0x0a +#define GB_GPIO_TYPE_RESPONSE 0x80 /* OR'd with rest */ + +#define GB_GPIO_DEBOUNCE_USEC_DEFAULT 0 /* microseconds */ + +/* version request has no payload */ +struct gb_gpio_proto_version_response { + __u8 status; + __u8 major; + __u8 minor; +}; + +/* line count request has no payload */ +struct gb_gpio_line_count_response { + __u8 status; + __u8 count; +}; + +struct gb_gpio_activate_request { + __u8 which; +}; +struct gb_gpio_activate_response { + __u8 status; +}; + +struct gb_gpio_deactivate_request { + __u8 which; +}; +struct gb_gpio_deactivate_response { + __u8 status; +}; + +struct gb_gpio_get_direction_request { + __u8 which; +}; +struct gb_gpio_get_direction_response { + __u8 status; + __u8 direction; +}; + +struct gb_gpio_direction_in_request { + __u8 which; +}; +struct gb_gpio_direction_in_response { + __u8 status; +}; + +struct gb_gpio_direction_out_request { + __u8 which; + __u8 value; +}; +struct gb_gpio_direction_out_response { + __u8 status; +}; + +struct gb_gpio_get_value_request { + __u8 status; + __u8 which; +}; +struct gb_gpio_get_value_response { + __u8 status; + __u8 value; +}; + +struct gb_gpio_set_value_request { + __u8 which; + __u8 value; +}; +struct gb_gpio_set_value_response { + __u8 status; }; -static const struct greybus_module_id id_table[] = { - { GREYBUS_DEVICE(0x44, 0x44) }, /* make shit up */ - { }, /* terminating NULL entry */ +struct gb_gpio_set_debounce_request { + __u8 which; + __le16 usec; +}; +struct gb_gpio_set_debounce_response { + __u8 status; }; -static int direction_input(struct gpio_chip *gpio, unsigned nr) + +/* + * This request only uses the connection field, and if successful, + * fills in the major and minor protocol version of the target. + */ +static int gb_gpio_proto_version_operation(struct gb_gpio_controller *gb_gpio_controller) +{ + struct gb_connection *connection = gb_gpio_controller->connection; + struct gb_operation *operation; + struct gb_gpio_proto_version_response *response; + int ret; + + /* protocol version request has no payload */ + operation = gb_operation_create(connection, + GB_GPIO_TYPE_PROTOCOL_VERSION, + 0, sizeof(*response)); + if (!operation) + return -ENOMEM; + + /* Synchronous operation--no callback */ + ret = gb_operation_request_send(operation, NULL); + if (ret) { + pr_err("version operation failed (%d)\n", ret); + goto out; + } + + response = operation->response_payload; + if (response->status) { + gb_connection_err(connection, "version response %hhu", + response->status); + ret = -EIO; + } else { + if (response->major > GB_GPIO_VERSION_MAJOR) { + pr_err("unsupported major version (%hhu > %hhu)\n", + response->major, GB_GPIO_VERSION_MAJOR); + ret = -ENOTSUPP; + goto out; + } + gb_gpio_controller->version_major = response->major; + gb_gpio_controller->version_minor = response->minor; +printk("%s: version_major = %u version_minor = %u\n", __func__, + gb_gpio_controller->version_major, gb_gpio_controller->version_minor); + } +out: + gb_operation_destroy(operation); + + return ret; +} + +static int gb_gpio_line_count_operation(struct gb_gpio_controller *gb_gpio_controller) { - //struct gb_gpio_device *gb_gpio_dev = container_of(gpio, struct gb_gpio_device, chip); + struct gb_connection *connection = gb_gpio_controller->connection; + struct gb_operation *operation; + struct gb_gpio_line_count_response *response; + int ret; + + /* line count request has no payload */ + operation = gb_operation_create(connection, + GB_GPIO_TYPE_LINE_COUNT, + 0, sizeof(*response)); + if (!operation) + return -ENOMEM; + + /* Synchronous operation--no callback */ + ret = gb_operation_request_send(operation, NULL); + if (ret) { + pr_err("line count operation failed (%d)\n", ret); + goto out; + } + + response = operation->response_payload; + if (response->status) { + gb_connection_err(connection, "line count response %hhu", + response->status); + ret = -EIO; + } else { + gb_gpio_controller->line_max = response->count; +printk("%s: count = %u\n", __func__, + gb_gpio_controller->line_max + 1); + } +out: + gb_operation_destroy(operation); + + return ret; +} + +static int gb_gpio_activate_operation(struct gb_gpio_controller *gb_gpio_controller, + u8 which) +{ + struct gb_connection *connection = gb_gpio_controller->connection; + struct gb_operation *operation; + struct gb_gpio_activate_request *request; + struct gb_gpio_activate_response *response; + int ret; + + if (which > gb_gpio_controller->line_max) + return -EINVAL; + + /* activate response has no payload */ + operation = gb_operation_create(connection, + GB_GPIO_TYPE_ACTIVATE, + sizeof(*request), sizeof(*response)); + if (!operation) + return -ENOMEM; + request = operation->request_payload; + request->which = which; + + /* Synchronous operation--no callback */ + ret = gb_operation_request_send(operation, NULL); + if (ret) { + pr_err("activate operation failed (%d)\n", ret); + goto out; + } + + response = operation->response_payload; + if (response->status) { + gb_connection_err(connection, "activate response %hhu", + response->status); + ret = -EIO; + } else { + gb_gpio_controller->lines[which].active = true; +printk("%s: %u is now active\n", __func__, which); + } +out: + gb_operation_destroy(operation); + + return ret; +} + +static int gb_gpio_deactivate_operation(struct gb_gpio_controller *gb_gpio_controller, + u8 which) +{ + struct gb_connection *connection = gb_gpio_controller->connection; + struct gb_operation *operation; + struct gb_gpio_deactivate_request *request; + struct gb_gpio_deactivate_response *response; + int ret; + + if (which > gb_gpio_controller->line_max) + return -EINVAL; + + /* deactivate response has no payload */ + operation = gb_operation_create(connection, + GB_GPIO_TYPE_DEACTIVATE, + sizeof(*request), sizeof(*response)); + if (!operation) + return -ENOMEM; + request = operation->request_payload; + request->which = which; + + /* Synchronous operation--no callback */ + ret = gb_operation_request_send(operation, NULL); + if (ret) { + pr_err("deactivate operation failed (%d)\n", ret); + goto out; + } + + response = operation->response_payload; + if (response->status) { + gb_connection_err(connection, "deactivate response %hhu", + response->status); + ret = -EIO; + } else { + gb_gpio_controller->lines[which].active = false; +printk("%s: %u is now inactive\n", __func__, which); + } +out: + gb_operation_destroy(operation); + + return ret; +} + +static int gb_gpio_get_direction_operation(struct gb_gpio_controller *gb_gpio_controller, + u8 which) +{ + struct gb_connection *connection = gb_gpio_controller->connection; + struct gb_operation *operation; + struct gb_gpio_get_direction_request *request; + struct gb_gpio_get_direction_response *response; + int ret; + + if (which > gb_gpio_controller->line_max) + return -EINVAL; + + operation = gb_operation_create(connection, + GB_GPIO_TYPE_GET_DIRECTION, + sizeof(*request), sizeof(*response)); + if (!operation) + return -ENOMEM; + request = operation->request_payload; + request->which = which; + + /* Synchronous operation--no callback */ + ret = gb_operation_request_send(operation, NULL); + if (ret) { + pr_err("get direction operation failed (%d)\n", ret); + goto out; + } + + response = operation->response_payload; + if (response->status) { + gb_connection_err(connection, "get direction response %hhu", + response->status); + ret = -EIO; + } else { + u8 direction = response->direction; + + if (direction && direction != 1) + pr_warn("gpio %u direction was %u (should be 0 or 1)\n", + which, direction); + gb_gpio_controller->lines[which].direction = direction ? 1 : 0; +printk("%s: direction of %u is %s\n", __func__, which, + direction ? "in" : "out"); + } +out: + gb_operation_destroy(operation); + + return ret; +} + +static int gb_gpio_direction_in_operation(struct gb_gpio_controller *gb_gpio_controller, + u8 which) +{ + struct gb_connection *connection = gb_gpio_controller->connection; + struct gb_operation *operation; + struct gb_gpio_direction_in_request *request; + struct gb_gpio_direction_in_response *response; + int ret; + + if (which > gb_gpio_controller->line_max) + return -EINVAL; + + /* direction_in response has no payload */ + operation = gb_operation_create(connection, + GB_GPIO_TYPE_DIRECTION_IN, + sizeof(*request), sizeof(*response)); + if (!operation) + return -ENOMEM; + request = operation->request_payload; + request->which = which; + + /* Synchronous operation--no callback */ + ret = gb_operation_request_send(operation, NULL); + if (ret) { + pr_err("direction in operation failed (%d)\n", ret); + goto out; + } - // FIXME - do something there + response = operation->response_payload; + if (response->status) { + gb_connection_err(connection, "direction in response %hhu", + response->status); + ret = -EIO; + } else { + gb_gpio_controller->lines[which].direction = 1; +printk("%s: direction of %u is now in\n", __func__, which); + } +out: + gb_operation_destroy(operation); + + return ret; +} + +static int gb_gpio_direction_out_operation(struct gb_gpio_controller *gb_gpio_controller, + u8 which, bool value_high) +{ + struct gb_connection *connection = gb_gpio_controller->connection; + struct gb_operation *operation; + struct gb_gpio_direction_out_request *request; + struct gb_gpio_direction_out_response *response; + int ret; + + if (which > gb_gpio_controller->line_max) + return -EINVAL; + + /* direction_out response has no payload */ + operation = gb_operation_create(connection, + GB_GPIO_TYPE_DIRECTION_OUT, + sizeof(*request), sizeof(*response)); + if (!operation) + return -ENOMEM; + request = operation->request_payload; + request->which = which; + request->value = value_high ? 1 : 0; + + /* Synchronous operation--no callback */ + ret = gb_operation_request_send(operation, NULL); + if (ret) { + pr_err("direction out operation failed (%d)\n", ret); + goto out; + } + + response = operation->response_payload; + if (response->status) { + gb_connection_err(connection, "direction out response %hhu", + response->status); + ret = -EIO; + } else { + gb_gpio_controller->lines[which].direction = 0; +printk("%s: direction of %u is now out, value %s\n", __func__, + which, value_high ? "high" : "low"); + } +out: + gb_operation_destroy(operation); + + return ret; +} + +static int gb_gpio_get_value_operation(struct gb_gpio_controller *gb_gpio_controller, + u8 which) +{ + struct gb_connection *connection = gb_gpio_controller->connection; + struct gb_operation *operation; + struct gb_gpio_get_value_request *request; + struct gb_gpio_get_value_response *response; + int ret; + + if (which > gb_gpio_controller->line_max) + return -EINVAL; + + operation = gb_operation_create(connection, + GB_GPIO_TYPE_GET_VALUE, + sizeof(*request), sizeof(*response)); + if (!operation) + return -ENOMEM; + request = operation->request_payload; + request->which = which; + + /* Synchronous operation--no callback */ + ret = gb_operation_request_send(operation, NULL); + if (ret) { + pr_err("get value operation failed (%d)\n", ret); + goto out; + } + + response = operation->response_payload; + if (response->status) { + gb_connection_err(connection, "get value response %hhu", + response->status); + ret = -EIO; + } else { + u8 value = response->value; + + if (value && value != 1) + pr_warn("gpio %u value was %u (should be 0 or 1)\n", + which, value); + gb_gpio_controller->lines[which].value = value ? 1 : 0; + /* XXX should this set direction to out? */ +printk("%s: value of %u is %s\n", __func__, + which, gb_gpio_controller->lines[which].value ? "high" : "low"); + } +out: + gb_operation_destroy(operation); + + return ret; +} + +static int gb_gpio_set_value_operation(struct gb_gpio_controller *gb_gpio_controller, + u8 which, bool value_high) +{ + struct gb_connection *connection = gb_gpio_controller->connection; + struct gb_operation *operation; + struct gb_gpio_set_value_request *request; + struct gb_gpio_set_value_response *response; + int ret; + + if (which > gb_gpio_controller->line_max) + return -EINVAL; + + /* set_value response has no payload */ + operation = gb_operation_create(connection, + GB_GPIO_TYPE_SET_VALUE, + sizeof(*request), sizeof(*response)); + if (!operation) + return -ENOMEM; + request = operation->request_payload; + request->which = which; + request->value = value_high ? 1 : 0; + + /* Synchronous operation--no callback */ + ret = gb_operation_request_send(operation, NULL); + if (ret) { + pr_err("set value operation failed (%d)\n", ret); + goto out; + } + + response = operation->response_payload; + if (response->status) { + gb_connection_err(connection, "set value response %hhu", + response->status); + ret = -EIO; + } else { + /* XXX should this set direction to out? */ + gb_gpio_controller->lines[which].value = request->value; +printk("%s: out value of %u is now %s\n", __func__, + which, gb_gpio_controller->lines[which].value ? "high" : "low"); + } +out: + gb_operation_destroy(operation); + + return ret; +} + +static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *gb_gpio_controller, + u8 which, u16 debounce_usec) +{ + struct gb_connection *connection = gb_gpio_controller->connection; + struct gb_operation *operation; + struct gb_gpio_set_debounce_request *request; + struct gb_gpio_set_debounce_response *response; + int ret; + + if (which > gb_gpio_controller->line_max) + return -EINVAL; + + /* set_debounce response has no payload */ + operation = gb_operation_create(connection, + GB_GPIO_TYPE_SET_DEBOUNCE, + sizeof(*request), sizeof(*response)); + if (!operation) + return -ENOMEM; + request = operation->request_payload; + request->which = which; + request->usec = le16_to_cpu(debounce_usec); + + /* Synchronous operation--no callback */ + ret = gb_operation_request_send(operation, NULL); + if (ret) { + pr_err("set debounce operation failed (%d)\n", ret); + goto out; + } + + response = operation->response_payload; + if (response->status) { + gb_connection_err(connection, "set debounce response %hhu", + response->status); + ret = -EIO; + } else { + gb_gpio_controller->lines[which].debounce_usec = request->usec; +printk("%s: debounce of %u is now %hu usec\n", __func__, + which, gb_gpio_controller->lines[which].debounce_usec); + } +out: + gb_operation_destroy(operation); + + return ret; +} + +static int gb_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); + u8 which; + int ret; + + if (offset < chip->base || offset >= chip->base + chip->ngpio) + return -EINVAL; + which = (u8)(offset - chip->base); + ret = gb_gpio_activate_operation(gb_gpio_controller, which); + if (ret) + ; /* return ret; */ return 0; } -static int direction_output(struct gpio_chip *gpio, unsigned nr, int val) +static void gb_gpio_free(struct gpio_chip *chip, unsigned offset) +{ + struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); + u8 which; + int ret; + + if (offset < chip->base || offset >= chip->base + chip->ngpio) { + pr_err("bad offset %u supplied (must be %u..%u)\n", + offset, chip->base, chip->base + chip->ngpio - 1); + return; + } + which = (u8)(offset - chip->base); + ret = gb_gpio_deactivate_operation(gb_gpio_controller, which); + if (ret) + ; /* return ret; */ +} + +static int gb_gpio_get_direction(struct gpio_chip *chip, unsigned offset) +{ + struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); + u8 which; + int ret; + + if (offset < chip->base || offset >= chip->base + chip->ngpio) + return -EINVAL; + which = (u8)(offset - chip->base); + ret = gb_gpio_get_direction_operation(gb_gpio_controller, which); + if (ret) + ; /* return ret; */ + return gb_gpio_controller->lines[which].direction ? 1 : 0; +} + +static int gb_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { - // FIXME - do something there + struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); + u8 which; + int ret; + + if (offset < chip->base || offset >= chip->base + chip->ngpio) + return -EINVAL; + which = (u8)(offset - chip->base); + ret = gb_gpio_direction_in_operation(gb_gpio_controller, which); + if (ret) + ; /* return ret; */ return 0; } -static int gpio_get(struct gpio_chip *gpio, unsigned nr) +static int gb_gpio_direction_output(struct gpio_chip *chip, unsigned offset, + int value) { - // FIXME - do something there + struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); + u8 which; + int ret; + + if (offset < chip->base || offset >= chip->base + chip->ngpio) + return -EINVAL; + which = (u8)(offset - chip->base); + ret = gb_gpio_direction_out_operation(gb_gpio_controller, which, !!value); + if (ret) + ; /* return ret; */ return 0; } -static void gpio_set(struct gpio_chip *gpio, unsigned nr, int val) +static int gb_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); + u8 which; + int ret; + + if (offset < chip->base || offset >= chip->base + chip->ngpio) + return -EINVAL; + which = (u8)(offset - chip->base); + ret = gb_gpio_get_value_operation(gb_gpio_controller, which); + if (ret) + return ret; + return (int)gb_gpio_controller->lines[which].value; +} + +static void gb_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - // FIXME - do something there + struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); + u8 which; + int ret; + + if (offset < chip->base || offset >= chip->base + chip->ngpio) { + pr_err("bad offset %u supplied (must be %u..%u)\n", + offset, chip->base, chip->base + chip->ngpio - 1); + return; + } + which = (u8)(offset - chip->base); + ret = gb_gpio_set_value_operation(gb_gpio_controller, which, !!value); + if (ret) + ; /* return ret; */ } -int gb_gpio_probe(struct gb_module *gmod, - const struct greybus_module_id *id) +static int gb_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, + unsigned debounce) { - struct gb_gpio_device *gb_gpio; + struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); + u16 usec; + u8 which; + int ret; + + if (offset < chip->base || offset >= chip->base + chip->ngpio) + return -EINVAL; + which = (u8)(offset - chip->base); + if (debounce > (unsigned int)U16_MAX) + return -EINVAL; + usec = (u8)debounce; + ret = gb_gpio_set_debounce_operation(gb_gpio_controller, which, usec); + if (ret) + ; /* return ret; */ + + return 0; /* XXX */ +} + +static int gb_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +{ + u8 which; + + if (offset < chip->base || offset >= chip->base + chip->ngpio) + return -EINVAL; + which = (u8)(offset - chip->base); + + return 0; /* XXX */ +} + +static void gb_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) +{ + return; /* XXX */ +} + +int gb_gpio_controller_setup(struct gb_gpio_controller *gb_gpio_controller) +{ + u32 line_count; + size_t size; + int ret; + + /* First thing we need to do is check the version */ + ret = gb_gpio_proto_version_operation(gb_gpio_controller); + if (ret) + ; /* return ret; */ + + /* Now find out how many lines there are */ + ret = gb_gpio_line_count_operation(gb_gpio_controller); + if (ret) + ; /* return ret; */ + line_count = (u32)gb_gpio_controller->line_max + 1; + size = line_count * sizeof(*gb_gpio_controller->lines); + gb_gpio_controller->lines = kzalloc(size, GFP_KERNEL); + if (!gb_gpio_controller->lines) + return -ENOMEM; + + return ret; +} + +int gb_gpio_controller_init(struct gb_connection *connection) +{ + struct gb_gpio_controller *gb_gpio_controller; struct gpio_chip *gpio; - struct device *dev = &gmod->dev; - int retval; + int ret; - gb_gpio = kzalloc(sizeof(*gb_gpio), GFP_KERNEL); - if (!gb_gpio) + gb_gpio_controller = kzalloc(sizeof(*gb_gpio_controller), GFP_KERNEL); + if (!gb_gpio_controller) return -ENOMEM; - gb_gpio->gmod = gmod; + gb_gpio_controller->connection = connection; + + ret = gb_gpio_controller_setup(gb_gpio_controller); + if (ret) + goto out_err; - gpio = &gb_gpio->chip; + gpio = &gb_gpio_controller->chip; gpio->label = "greybus_gpio"; - gpio->owner = THIS_MODULE; - gpio->direction_input = direction_input; - gpio->direction_output = direction_output; - gpio->get = gpio_get; - gpio->set = gpio_set; - gpio->dbg_show = NULL; - gpio->base = 0; // FIXME!!! - gpio->ngpio = 42; // FIXME!!! - gpio->can_sleep = false; // FIXME!!! + gpio->owner = THIS_MODULE; /* XXX Module get? */ + + gpio->request = gb_gpio_request; + gpio->free = gb_gpio_free; + gpio->get_direction = gb_gpio_get_direction; + gpio->direction_input = gb_gpio_direction_input; + gpio->direction_output = gb_gpio_direction_output; + gpio->get = gb_gpio_get; + gpio->set = gb_gpio_set; + gpio->set_debounce = gb_gpio_set_debounce; + gpio->to_irq = gb_gpio_to_irq; + gpio->dbg_show = gb_gpio_dbg_show; - gmod->gb_gpio_dev = gb_gpio; + gpio->base = -1; /* Allocate base dynamically */ + gpio->ngpio = gb_gpio_controller->line_max + 1; + gpio->can_sleep = true; /* XXX */ - retval = gpiochip_add(gpio); - if (retval) { - dev_err(dev, "Failed to register GPIO\n"); - return retval; + ret = gpiochip_add(gpio); + if (ret) { + pr_err("Failed to register GPIO\n"); + return ret; } + connection->private = gb_gpio_controller; return 0; +out_err: + kfree(gb_gpio_controller); + return ret; } -void gb_gpio_disconnect(struct gb_module *gmod) +void gb_gpio_controller_exit(struct gb_connection *connection) { - struct gb_gpio_device *gb_gpio_dev; - int retval; + struct gb_gpio_controller *gb_gpio_controller = connection->private; + int ret; - gb_gpio_dev = gmod->gb_gpio_dev; - if (!gb_gpio_dev) + if (!gb_gpio_controller) return; - retval = gpiochip_remove(&gb_gpio_dev->chip); - kfree(gb_gpio_dev); + ret = gpiochip_remove(&gb_gpio_controller->chip); + /* kref_put(gb_gpio_controller->connection) */ + kfree(gb_gpio_controller); } #if 0 -static struct greybus_driver gpio_gb_driver = { - .probe = gb_gpio_probe, - .disconnect = gb_gpio_disconnect, - .id_table = id_table, -}; - -module_greybus_driver(gpio_gb_driver); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Greybus GPIO driver"); MODULE_AUTHOR("Greg Kroah-Hartman "); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 854122b..d4f5d94 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -265,6 +265,7 @@ void gb_deregister_cport_complete(u16 cport_id); extern const struct attribute_group *greybus_module_groups[]; int gb_i2c_device_init(struct gb_connection *connection); +int gb_gpio_controller_init(struct gb_connection *connection); int gb_tty_init(void); void gb_tty_exit(void); -- cgit v0.10.2 From d75286852bb3bd575bd8707f80ca0b362a7ae5a6 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 17 Oct 2014 05:09:21 -0500 Subject: greybus: add write retry support for i2c It is expected that i2c writes may fail, and in that case the driver simply retries some number of times before actually treating it as a failure. Define a GB_OP_RETRY status, which is interpreted by the i2c driver as an indication a retry is in order. We just translate that into an EAGAIN error passed back to the i2c core. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index c4e47ef..e1a0ed9 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -382,9 +382,13 @@ static int gb_i2c_transfer_operation(struct gb_i2c_device *gb_i2c_dev, response = operation->response_payload; if (response->status) { - gb_connection_err(connection, "transfer response %hhu", - response->status); - ret = -EIO; + if (response->status == GB_OP_RETRY) { + ret = -EAGAIN; + } else { + gb_connection_err(connection, "transfer response %hhu", + response->status); + ret = -EIO; + } } else { gb_i2c_transfer_response(msgs, msg_count, response->data); ret = msg_count; diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index d5ec582..59aad3a 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -16,7 +16,8 @@ enum gb_operation_status { GB_OP_INVALID = 1, GB_OP_NO_MEMORY = 2, GB_OP_INTERRUPTED = 3, - GB_OP_PROTOCOL_BAD = 4, + GB_OP_RETRY = 4, + GB_OP_PROTOCOL_BAD = 5, }; /* -- cgit v0.10.2 From bedfdf30565ef533b578d90a9dae5483347c8ea1 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 17 Oct 2014 05:18:22 -0500 Subject: greybus: update gbuf status for completion handlers Currently, if a USB urb completes with an error, that error status is not transferred back to the gbuf that it's associated with. For inbound data there's not a lot we can do about an error, but for outbound data, this means there is no notification to the submitter that something went wrong. For outbound data copy the urb status directly back to the gbuf as its status. Follow USB's lead and set the status to -EINPROGRESS while a gbuf is "in flight." Assign a gbuf an initial status value of -EBADR to help identify use of never-set status values. When an inbound urb fails (SVC or CPort), currently the urb is just leaked, more or less (i.e., we lose an urb posted to receive incoming data). Change that so such an error is reported, but then re-submitted. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 5acf5a7..21fe4fd 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -274,10 +274,11 @@ static void svc_in_callback(struct urb *urb) int status = check_urb_status(urb); int retval; - if (status == -EAGAIN) + if (status) { + if (status != -EAGAIN) + dev_err(dev, "urb svc in error %d (dropped)\n", status); goto exit; - if (status) - return; + } /* We have a message, create a new message structure, add it to the * list, and wake up our thread that will process the messages. @@ -300,10 +301,12 @@ static void cport_in_callback(struct urb *urb) u8 cport; u8 *data; - if (status == -EAGAIN) + if (status) { + if (status != -EAGAIN) + dev_err(dev, "urb cport in error %d (dropped)\n", + status); goto exit; - if (status) - return; + } /* The size has to be at least one, for the cport id */ if (!urb->actual_length) { @@ -337,6 +340,9 @@ static void cport_out_callback(struct urb *urb) unsigned long flags; int i; + /* Record whether the transfer was successful */ + gbuf->status = check_urb_status(urb); + /* * See if this was an urb in our pool, if so mark it "free", otherwise * we need to free it ourselves. diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 348ee7c2..9b435af 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -54,6 +54,7 @@ struct gbuf *greybus_alloc_gbuf(struct gb_connection *connection, gbuf->outbound = outbound; gbuf->complete = complete; gbuf->context = context; + gbuf->status = -EBADR; /* Initial value--means "never set" */ /* Host controller specific allocation for the actual buffer */ retval = connection->hd->driver->alloc_gbuf_data(gbuf, size, gfp_mask); @@ -98,6 +99,8 @@ int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) { struct greybus_host_device *hd = gbuf->connection->hd; + gbuf->status = -EINPROGRESS; + return hd->driver->submit_gbuf(gbuf, gfp_mask); } diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index a49d929..4d19eec 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -424,6 +424,7 @@ void gb_connection_operation_recv(struct gb_connection *connection, } gb_operation_remove(operation); gbuf = operation->response; + gbuf->status = GB_OP_SUCCESS; /* If we got here we're good */ if (size > gbuf->transfer_buffer_length) { gb_connection_err(connection, "recv buffer too small"); return; -- cgit v0.10.2 From f012a520e1a8bb5d05de3307334a8de4dd95afdf Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 17 Oct 2014 21:03:49 -0500 Subject: greybus: report gbuf errors If a gbuf completion indicates an error has occurred, report it. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 4d19eec..4cbe33e 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -224,10 +224,29 @@ static void gb_operation_recv_work(struct work_struct *recv_work) * we'll be done with everything we need to do before we mark it * finished. * - * XXX We may want to record that a buffer is (or is no longer) in flight. + * XXX We may want to record that a request is (or is no longer) in flight. */ static void gb_operation_gbuf_complete(struct gbuf *gbuf) { + if (gbuf->status) { + struct gb_operation *operation = gbuf->context; + struct gb_operation_msg_hdr *header; + int id; + int type; + + if (gbuf == operation->request) + header = operation->request_payload; + else if (gbuf == operation->response) + header = operation->response_payload; + else + header = NULL; + id = header ? (int)header->id : -1; + type = header ? (int)header->type : -1; + + gb_connection_err(operation->connection, + "operation %d type %d gbuf error %d", + id, type, gbuf->status); + } return; } -- cgit v0.10.2 From 6ce3e03f717820eb8edd92c9ac659e2a050727db Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 20 Oct 2014 13:27:42 +0800 Subject: greybus: greybus_manifest.h: fix up class protocol numbers to match the spec. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 4fd27d3..2f1249a 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -36,18 +36,20 @@ enum greybus_protocol { enum greybus_class_type { GREYBUS_CLASS_CONTROL = 0x00, - GREYBUS_CLASS_USB = 0x01, + GREYBUS_CLASS_AP = 0x01, GREYBUS_CLASS_GPIO = 0x02, - GREYBUS_CLASS_SPI = 0x03, + GREYBUS_CLASS_I2C = 0x03, GREYBUS_CLASS_UART = 0x04, - GREYBUS_CLASS_PWM = 0x05, - GREYBUS_CLASS_I2S = 0x06, - GREYBUS_CLASS_I2C = 0x07, - GREYBUS_CLASS_SDIO = 0x08, - GREYBUS_CLASS_HID = 0x09, - GREYBUS_CLASS_DISPLAY = 0x0a, - GREYBUS_CLASS_CAMERA = 0x0b, - GREYBUS_CLASS_SENSOR = 0x0c, + GREYBUS_CLASS_HID = 0x05, + GREYBUS_CLASS_USB = 0x06, + GREYBUS_CLASS_SDIO = 0x07, + GREYBUS_CLASS_BATTERY = 0x08, + GREYBUS_CLASS_PWM = 0x09, + GREYBUS_CLASS_I2S = 0x0a, + GREYBUS_CLASS_SPI = 0x0b, + GREYBUS_CLASS_DISPLAY = 0x0c, + GREYBUS_CLASS_CAMERA = 0x0d, + GREYBUS_CLASS_SENSOR = 0x0e, GREYBUS_CLASS_VENDOR = 0xff, }; -- cgit v0.10.2 From 213aefe206d288eee4a2d480d9c6b2889b441682 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 20 Oct 2014 13:40:02 +0800 Subject: greybus: gpio-gb: allow it to build properly for all current kernel versions. GPIO remove changed the api for 3.17 to try to make up for some previously foolish design decisions. Handle that in kernel_ver.h to make the code simple. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index 7f03676..53464e3 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -799,12 +799,11 @@ out_err: void gb_gpio_controller_exit(struct gb_connection *connection) { struct gb_gpio_controller *gb_gpio_controller = connection->private; - int ret; if (!gb_gpio_controller) return; - ret = gpiochip_remove(&gb_gpio_controller->chip); + gb_gpiochip_remove(&gb_gpio_controller->chip); /* kref_put(gb_gpio_controller->connection) */ kfree(gb_gpio_controller); } diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index c9ea7a9..e0fea18 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -26,4 +26,26 @@ #define U16_MAX ((u16)(~0U)) #endif /* !U16_MAX */ +/* + * The GPIO api sucks rocks in places, like removal, so work around their + * explicit requirements of catching the return value for kernels older than + * 3.17, which they explicitly changed in the 3.17 kernel. Consistency is + * overrated. + */ +#include +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) +static inline void gb_gpiochip_remove(struct gpio_chip *chip) +{ + gpiochip_remove(chip); +} +#else +static inline void gb_gpiochip_remove(struct gpio_chip *chip) +{ + int ret; + ret = gpiochip_remove(chip); +} +#endif + #endif /* __GREYBUS_KERNEL_VER_H */ -- cgit v0.10.2 From 43789c319ee80140fd1d07b85e1a619a8e01e466 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 20 Oct 2014 15:09:49 +0800 Subject: greybus: battery-gb: provide accessors for a few more functions Put the hard coded values in a function to make it easier to see what needs to be done here. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index eaced9a..685cff5 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -27,12 +27,24 @@ static const struct greybus_module_id id_table[] = { { }, /* terminating NULL entry */ }; +static int get_tech(struct gb_battery *gb) +{ + // FIXME - guess! + return POWER_SUPPLY_TECHNOLOGY_NiMH; +} + static int get_status(struct gb_battery *gb) { // FIXME!!! return 0; } +static int get_max_voltage(struct gb_battery *gb) +{ + // FIXME!!! + return 4700000; +} + static int get_capacity(struct gb_battery *gb) { // FIXME!!! @@ -59,8 +71,7 @@ static int get_property(struct power_supply *b, switch (psp) { case POWER_SUPPLY_PROP_TECHNOLOGY: - // FIXME - guess! - val->intval = POWER_SUPPLY_TECHNOLOGY_NiMH; + val->intval = get_tech(gb); break; case POWER_SUPPLY_PROP_STATUS: @@ -68,7 +79,7 @@ static int get_property(struct power_supply *b, break; case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: - val->intval = 4700000; // FIXME - guess??? + val->intval = get_max_voltage(gb); break; case POWER_SUPPLY_PROP_CAPACITY: -- cgit v0.10.2 From 47ee0d135e7b1e9feebbe20342bacb99e4ae2ff6 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 20 Oct 2014 01:51:18 -0400 Subject: greybus: gpio-gb: remove unused status field from struct gb_gpio_get_value_request probably a cut and paste error got this unused status field. remove it. Signed-off-by: Matt Porter Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index 53464e3..f3fb0b6 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -105,7 +105,6 @@ struct gb_gpio_direction_out_response { }; struct gb_gpio_get_value_request { - __u8 status; __u8 which; }; struct gb_gpio_get_value_response { -- cgit v0.10.2 From 2bb7eae8be12e8510fdb00aca6886b91ce72cb25 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 20 Oct 2014 15:24:57 +0800 Subject: greybus: battery: some hooking up to the greybus core Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index 685cff5..3288101 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -18,7 +18,10 @@ struct gb_battery { // we will want to keep the battery stats in here as we will be getting // updates from the SVC "on the fly" so we don't have to always go ask // the battery for some information. Hopefully... - struct gb_module *gmod; + struct gb_connection *connection; + u8 version_major; + u8 version_minor; + }; #define to_gb_battery(x) container_of(x, struct gb_battery, bat) @@ -111,8 +114,7 @@ static enum power_supply_property battery_props[] = { POWER_SUPPLY_PROP_VOLTAGE_NOW, }; -int gb_battery_probe(struct gb_module *gmod, - const struct greybus_module_id *id) +int gb_battery_device_init(struct gb_connection *connection) { struct gb_battery *gb; struct power_supply *b; @@ -122,6 +124,8 @@ int gb_battery_probe(struct gb_module *gmod, if (!gb) return -ENOMEM; + gb->connection = connection; // FIXME refcount! + b = &gb->bat; // FIXME - get a better (i.e. unique) name // FIXME - anything else needs to be set? @@ -131,12 +135,11 @@ int gb_battery_probe(struct gb_module *gmod, b->num_properties = ARRAY_SIZE(battery_props), b->get_property = get_property, - retval = power_supply_register(&gmod->dev, b); + retval = power_supply_register(&connection->interface->gmod->dev, b); if (retval) { kfree(gb); return retval; } - gmod->gb_battery = gb; return 0; } diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index a51b478..c9d524b 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -203,10 +203,12 @@ int gb_connection_init(struct gb_connection *connection) switch (connection->protocol) { case GREYBUS_PROTOCOL_I2C: return gb_i2c_device_init(connection); - case GREYBUS_PROTOCOL_CONTROL: - case GREYBUS_PROTOCOL_AP: case GREYBUS_PROTOCOL_GPIO: return gb_gpio_controller_init(connection); + case GREYBUS_PROTOCOL_BATTERY: + return gb_battery_device_init(connection); + case GREYBUS_PROTOCOL_CONTROL: + case GREYBUS_PROTOCOL_AP: case GREYBUS_PROTOCOL_UART: case GREYBUS_PROTOCOL_HID: case GREYBUS_PROTOCOL_VENDOR: diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index d4f5d94..c09572c 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -265,6 +265,7 @@ void gb_deregister_cport_complete(u16 cport_id); extern const struct attribute_group *greybus_module_groups[]; int gb_i2c_device_init(struct gb_connection *connection); +int gb_battery_device_init(struct gb_connection *connection); int gb_gpio_controller_init(struct gb_connection *connection); int gb_tty_init(void); diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 2f1249a..62023f8 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -30,6 +30,7 @@ enum greybus_protocol { GREYBUS_PROTOCOL_I2C = 0x03, GREYBUS_PROTOCOL_UART = 0x04, GREYBUS_PROTOCOL_HID = 0x05, + GREYBUS_PROTOCOL_BATTERY = 0x08, /* ... */ GREYBUS_PROTOCOL_VENDOR = 0xff, }; diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 4cbe33e..4639212 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -165,6 +165,7 @@ static gb_operation_recv_handler gb_operation_recv_handlers[] = { [GREYBUS_PROTOCOL_I2C] = gb_operation_recv_none, [GREYBUS_PROTOCOL_UART] = NULL, [GREYBUS_PROTOCOL_HID] = NULL, + [GREYBUS_PROTOCOL_BATTERY] = gb_operation_recv_none, [GREYBUS_PROTOCOL_VENDOR] = NULL, }; -- cgit v0.10.2 From 42d4a22d6b8e66f1e4d08a643429dbe5321eb458 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 20 Oct 2014 16:02:56 +0800 Subject: greybus: add LED protocol numbers diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index c9d524b..7a86c7c 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -211,6 +211,7 @@ int gb_connection_init(struct gb_connection *connection) case GREYBUS_PROTOCOL_AP: case GREYBUS_PROTOCOL_UART: case GREYBUS_PROTOCOL_HID: + case GREYBUS_PROTOCOL_LED: case GREYBUS_PROTOCOL_VENDOR: default: gb_connection_err(connection, "unimplemented protocol %u", diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 62023f8..c18ee11 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -31,6 +31,7 @@ enum greybus_protocol { GREYBUS_PROTOCOL_UART = 0x04, GREYBUS_PROTOCOL_HID = 0x05, GREYBUS_PROTOCOL_BATTERY = 0x08, + GREYBUS_PROTOCOL_LED = 0x0e, /* ... */ GREYBUS_PROTOCOL_VENDOR = 0xff, }; diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 4639212..1176c97 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -166,6 +166,7 @@ static gb_operation_recv_handler gb_operation_recv_handlers[] = { [GREYBUS_PROTOCOL_UART] = NULL, [GREYBUS_PROTOCOL_HID] = NULL, [GREYBUS_PROTOCOL_BATTERY] = gb_operation_recv_none, + [GREYBUS_PROTOCOL_LED] = NULL, [GREYBUS_PROTOCOL_VENDOR] = NULL, }; -- cgit v0.10.2 From ff6e0b9c2f05e9f3a06e84af5af2fa8a2c8098f8 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 20 Oct 2014 06:39:45 -0400 Subject: greybus: gpio-gb: fix offset error checking and usage Offset (or hwgpio num) is the offset within a gpiochip, not the unique gpio namespace number. Adjust the error checking and use of offset in our operation calls to fix this. Signed-off-by: Matt Porter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index f3fb0b6..32bf45f 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -579,13 +579,12 @@ out: static int gb_gpio_request(struct gpio_chip *chip, unsigned offset) { struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); - u8 which; int ret; - if (offset < chip->base || offset >= chip->base + chip->ngpio) + if (offset < 0 || offset >= chip->ngpio) return -EINVAL; - which = (u8)(offset - chip->base); - ret = gb_gpio_activate_operation(gb_gpio_controller, which); + printk("passed check\n"); + ret = gb_gpio_activate_operation(gb_gpio_controller, (u8)offset); if (ret) ; /* return ret; */ return 0; @@ -594,16 +593,14 @@ static int gb_gpio_request(struct gpio_chip *chip, unsigned offset) static void gb_gpio_free(struct gpio_chip *chip, unsigned offset) { struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); - u8 which; int ret; - if (offset < chip->base || offset >= chip->base + chip->ngpio) { - pr_err("bad offset %u supplied (must be %u..%u)\n", - offset, chip->base, chip->base + chip->ngpio - 1); + if (offset < 0 || offset >= chip->ngpio) { + pr_err("bad offset %u supplied (must be 0..%u)\n", + offset, chip->ngpio - 1); return; } - which = (u8)(offset - chip->base); - ret = gb_gpio_deactivate_operation(gb_gpio_controller, which); + ret = gb_gpio_deactivate_operation(gb_gpio_controller, (u8)offset); if (ret) ; /* return ret; */ } @@ -614,9 +611,9 @@ static int gb_gpio_get_direction(struct gpio_chip *chip, unsigned offset) u8 which; int ret; - if (offset < chip->base || offset >= chip->base + chip->ngpio) + if (offset < 0 || offset >= chip->ngpio) return -EINVAL; - which = (u8)(offset - chip->base); + which = (u8)offset; ret = gb_gpio_get_direction_operation(gb_gpio_controller, which); if (ret) ; /* return ret; */ @@ -626,13 +623,11 @@ static int gb_gpio_get_direction(struct gpio_chip *chip, unsigned offset) static int gb_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); - u8 which; int ret; - if (offset < chip->base || offset >= chip->base + chip->ngpio) + if (offset < 0 || offset >= chip->ngpio) return -EINVAL; - which = (u8)(offset - chip->base); - ret = gb_gpio_direction_in_operation(gb_gpio_controller, which); + ret = gb_gpio_direction_in_operation(gb_gpio_controller, (u8)offset); if (ret) ; /* return ret; */ return 0; @@ -642,13 +637,11 @@ static int gb_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value) { struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); - u8 which; int ret; - if (offset < chip->base || offset >= chip->base + chip->ngpio) + if (offset < 0 || offset >= chip->ngpio) return -EINVAL; - which = (u8)(offset - chip->base); - ret = gb_gpio_direction_out_operation(gb_gpio_controller, which, !!value); + ret = gb_gpio_direction_out_operation(gb_gpio_controller, (u8)offset, !!value); if (ret) ; /* return ret; */ return 0; @@ -660,9 +653,9 @@ static int gb_gpio_get(struct gpio_chip *chip, unsigned offset) u8 which; int ret; - if (offset < chip->base || offset >= chip->base + chip->ngpio) + if (offset < 0 || offset >= chip->ngpio) return -EINVAL; - which = (u8)(offset - chip->base); + which = (u8)offset; ret = gb_gpio_get_value_operation(gb_gpio_controller, which); if (ret) return ret; @@ -672,16 +665,14 @@ static int gb_gpio_get(struct gpio_chip *chip, unsigned offset) static void gb_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); - u8 which; int ret; - if (offset < chip->base || offset >= chip->base + chip->ngpio) { - pr_err("bad offset %u supplied (must be %u..%u)\n", - offset, chip->base, chip->base + chip->ngpio - 1); + if (offset < 0 || offset >= chip->ngpio) { + pr_err("bad offset %u supplied (must be 0..%u)\n", + offset, chip->ngpio - 1); return; } - which = (u8)(offset - chip->base); - ret = gb_gpio_set_value_operation(gb_gpio_controller, which, !!value); + ret = gb_gpio_set_value_operation(gb_gpio_controller, (u8)offset, !!value); if (ret) ; /* return ret; */ } @@ -691,16 +682,14 @@ static int gb_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, { struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); u16 usec; - u8 which; int ret; - if (offset < chip->base || offset >= chip->base + chip->ngpio) + if (offset < 0 || offset >= chip->ngpio) return -EINVAL; - which = (u8)(offset - chip->base); if (debounce > (unsigned int)U16_MAX) return -EINVAL; usec = (u8)debounce; - ret = gb_gpio_set_debounce_operation(gb_gpio_controller, which, usec); + ret = gb_gpio_set_debounce_operation(gb_gpio_controller, (u8)offset, usec); if (ret) ; /* return ret; */ @@ -709,11 +698,8 @@ static int gb_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, static int gb_gpio_to_irq(struct gpio_chip *chip, unsigned offset) { - u8 which; - - if (offset < chip->base || offset >= chip->base + chip->ngpio) + if (offset < 0 || offset >= chip->ngpio) return -EINVAL; - which = (u8)(offset - chip->base); return 0; /* XXX */ } -- cgit v0.10.2 From 8597e6b2b9df0a1c777e3183c105d78a470d0c66 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 20 Oct 2014 16:45:50 +0530 Subject: greybus: Fix parameters of core_param() core_param() takes four parameters instead of three and so results in this compilation error: greybus/core.c:25:33: error: macro "core_param" requires 4 arguments, but only 3 given core_param(nogreybus, bool, 0444); ^ Fix this by adding proper arguments to it. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 38f867d..0a37b95 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -22,7 +22,7 @@ static bool nogreybus; #ifdef MODULE module_param(nogreybus, bool, 0444); #else -core_param(nogreybus, bool, 0444); +core_param(nogreybus, nogreybus, bool, 0444); #endif int greybus_disabled(void) { -- cgit v0.10.2 From 6813e35a0ea48749b4d0f1eb1c4df35f4fa2a4c1 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 20 Oct 2014 16:46:18 +0530 Subject: greybus: .gitignore: minor updates Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/.gitignore b/drivers/staging/greybus/.gitignore index a07ab9d..f7dc3ba 100644 --- a/drivers/staging/greybus/.gitignore +++ b/drivers/staging/greybus/.gitignore @@ -7,3 +7,6 @@ Module.symvers *.swp .tmp_versions tags +cscope.* +ncscope.* +*.patch -- cgit v0.10.2 From 599dc6aa8ed91addf38814de22bdb5bb813a95aa Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 20 Oct 2014 10:27:55 -0500 Subject: greybus: properly drop device reference Drop the USB device reference taken at the top of ap_probe() in the event greybus_create_hd() fails. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 21fe4fd..21db78f 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -386,8 +386,10 @@ static int ap_probe(struct usb_interface *interface, udev = usb_get_dev(interface_to_usbdev(interface)); hd = greybus_create_hd(&es1_driver, &udev->dev); - if (!hd) + if (!hd) { + usb_put_dev(udev); return -ENOMEM; + } es1 = hd_to_es1(hd); es1->hd = hd; -- cgit v0.10.2 From 5b3db0ddaaf7e844dd0efbaa11a1cec4700aff34 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 20 Oct 2014 10:27:56 -0500 Subject: greybus: create a slab cache for operations Everything we do on greybus will involve an operation, so create a slab cache for that frequently-allocated data structure. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 1176c97..da455f0 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -24,6 +24,8 @@ */ #define GB_OPERATION_MESSAGE_SIZE_MAX 4096 +static struct kmem_cache *gb_operation_cache; + /* Workqueue to handle Greybus operation completions. */ static struct workqueue_struct *gb_operation_recv_workqueue; @@ -307,8 +309,7 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, gfp_t gfp_flags = response_size ? GFP_KERNEL : GFP_ATOMIC; bool outgoing = response_size != 0; - /* XXX Use a slab cache */ - operation = kzalloc(sizeof(*operation), gfp_flags); + operation = kmem_cache_zalloc(gb_operation_cache, gfp_flags); if (!operation) return NULL; operation->connection = connection; /* XXX refcount? */ @@ -316,10 +317,8 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, operation->request = gb_operation_gbuf_create(operation, type, request_size, outgoing); - if (!operation->request) { - kfree(operation); - return NULL; - } + if (!operation->request) + goto err_cache; operation->request_payload = operation->request->transfer_buffer + sizeof(struct gb_operation_msg_hdr); /* We always use the full request buffer */ @@ -330,11 +329,8 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, operation->response = gb_operation_gbuf_create(operation, type, response_size, false); - if (!operation->response) { - greybus_free_gbuf(operation->request); - kfree(operation); - return NULL; - } + if (!operation->response) + goto err_request; operation->response_payload = operation->response->transfer_buffer + sizeof(struct gb_operation_msg_hdr); @@ -349,6 +345,13 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, spin_unlock_irq(&gb_operations_lock); return operation; + +err_request: + greybus_free_gbuf(operation->request); +err_cache: + kmem_cache_free(gb_operation_cache, operation); + + return NULL; } /* @@ -367,7 +370,7 @@ void gb_operation_destroy(struct gb_operation *operation) greybus_free_gbuf(operation->response); greybus_free_gbuf(operation->request); - kfree(operation); + kmem_cache_free(gb_operation_cache, operation); } /* @@ -470,14 +473,25 @@ void gb_connection_operation_recv(struct gb_connection *connection, int gb_operation_init(void) { + gb_operation_cache = kmem_cache_create("gb_operation_cache", + sizeof(struct gb_operation), 0, 0, NULL); + if (!gb_operation_cache) + return -ENOMEM; + gb_operation_recv_workqueue = alloc_workqueue("greybus_recv", 0, 1); - if (!gb_operation_recv_workqueue) + if (!gb_operation_recv_workqueue) { + kmem_cache_destroy(gb_operation_cache); + gb_operation_cache = NULL; return -ENOMEM; + } return 0; } void gb_operation_exit(void) { + kmem_cache_destroy(gb_operation_cache); + gb_operation_cache = NULL; destroy_workqueue(gb_operation_recv_workqueue); + gb_operation_recv_workqueue = NULL; } -- cgit v0.10.2 From 09c521dc0a98141ae3c1b431c967d90d46c372e8 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 20 Oct 2014 10:27:57 -0500 Subject: greybus: drop gb_* device fields from gb_module A struct gb_module has a bunch of fields from the earlier skeleton code, where a module was assumed to possibly have one of every type of device available on the GP Bridge. The manifest parsing code changed it so these things will be related to connection endpoints, so these gb_module fields are no longer needed. A few of these (battery and sdio) haven't been implemented the "new way" yet, so just leave a bit of the code that was there commented out for now. Also, gb_tty seems to be partially implemented and I don't want to remove that without knowing where it's headed, so that one stays. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index 3288101..09c3290 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -146,6 +146,7 @@ int gb_battery_device_init(struct gb_connection *connection) void gb_battery_disconnect(struct gb_module *gmod) { +#if 0 struct gb_battery *gb; gb = gmod->gb_battery; @@ -155,6 +156,7 @@ void gb_battery_disconnect(struct gb_module *gmod) power_supply_unregister(&gb->bat); kfree(gb); +#endif } #if 0 diff --git a/drivers/staging/greybus/module.h b/drivers/staging/greybus/module.h index 114f157..e32135f 100644 --- a/drivers/staging/greybus/module.h +++ b/drivers/staging/greybus/module.h @@ -35,12 +35,7 @@ struct gb_module { struct greybus_host_device *hd; - struct gb_i2c_device *gb_i2c_dev; - struct gb_gpio_device *gb_gpio_dev; - struct gb_sdio_host *gb_sdio_host; struct gb_tty *gb_tty; - struct gb_usb_device *gb_usb_dev; - struct gb_battery *gb_battery; }; #define to_gb_module(d) container_of(d, struct gb_module, dev) diff --git a/drivers/staging/greybus/sdio-gb.c b/drivers/staging/greybus/sdio-gb.c index 239fcf7..19c7c4a 100644 --- a/drivers/staging/greybus/sdio-gb.c +++ b/drivers/staging/greybus/sdio-gb.c @@ -61,12 +61,13 @@ int gb_sdio_probe(struct gb_module *gmod, mmc->ops = &gb_sd_ops; // FIXME - set up size limits we can handle. - gmod->gb_sdio_host = host; + // gmod->gb_sdio_host = host; return 0; } void gb_sdio_disconnect(struct gb_module *gmod) { +#if 0 struct mmc_host *mmc; struct gb_sdio_host *host; @@ -77,6 +78,7 @@ void gb_sdio_disconnect(struct gb_module *gmod) mmc = host->mmc; mmc_remove_host(mmc); mmc_free_host(mmc); +#endif } #if 0 -- cgit v0.10.2 From 6ff5e00a176878c218c2b27e4437e6af8f46a28c Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 20 Oct 2014 10:27:58 -0500 Subject: greybus: remove cports and strings from gb_module We no longer keep copies of strings found in the manifuest in a module's strings array, so we can get rid of the strings array. Similarly, the new manifest parsing code sets up connections for each cport id advertised for a module, so the cport array is no longer needed either. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 0a37b95..b59dee1 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -118,10 +118,7 @@ EXPORT_SYMBOL_GPL(greybus_deregister); static void greybus_module_release(struct device *dev) { struct gb_module *gmod = to_gb_module(dev); - int i; - for (i = 0; i < gmod->num_strings; ++i) - kfree(gmod->string[i]); kfree(gmod); } diff --git a/drivers/staging/greybus/module.h b/drivers/staging/greybus/module.h index e32135f..2c6707d 100644 --- a/drivers/staging/greybus/module.h +++ b/drivers/staging/greybus/module.h @@ -28,11 +28,6 @@ struct gb_module { char *product_string; u64 unique_id; - int num_cports; - int num_strings; - u16 cport_ids[MAX_CPORTS_PER_MODULE]; - struct gmod_string *string[MAX_STRINGS_PER_MODULE]; - struct greybus_host_device *hd; struct gb_tty *gb_tty; -- cgit v0.10.2 From 6892537f61b1eac275ad50e093708e5e3c8664bd Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 20 Oct 2014 10:27:59 -0500 Subject: greybus: move ap_disconnect() The next patch has ap_probe() reference ap_disconnect(). To prepare for that, move ap_disconnect() up in the file. This is done as a separate commit to make it easier to see this move involves no other change to that function. This and the next commit can be squashed if desired. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 21db78f..4473c9a 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -266,6 +266,35 @@ static int check_urb_status(struct urb *urb) return -EAGAIN; } +static void ap_disconnect(struct usb_interface *interface) +{ + struct es1_ap_dev *es1; + int i; + + es1 = usb_get_intfdata(interface); + if (!es1) + return; + + /* Tear down everything! */ + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + usb_kill_urb(es1->cport_out_urb[i]); + usb_free_urb(es1->cport_out_urb[i]); + } + + for (i = 0; i < NUM_CPORT_IN_URB; ++i) { + usb_kill_urb(es1->cport_in_urb[i]); + usb_free_urb(es1->cport_in_urb[i]); + kfree(es1->cport_in_buffer[i]); + } + + usb_kill_urb(es1->svc_urb); + usb_free_urb(es1->svc_urb); + usb_put_dev(es1->usb_dev); + kfree(es1->svc_buffer); + greybus_remove_hd(es1->hd); + usb_set_intfdata(interface, NULL); +} + /* Callback for when we get a SVC message */ static void svc_in_callback(struct urb *urb) { @@ -503,35 +532,6 @@ error: return retval; } -static void ap_disconnect(struct usb_interface *interface) -{ - struct es1_ap_dev *es1; - int i; - - es1 = usb_get_intfdata(interface); - if (!es1) - return; - - /* Tear down everything! */ - for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - usb_kill_urb(es1->cport_out_urb[i]); - usb_free_urb(es1->cport_out_urb[i]); - } - - for (i = 0; i < NUM_CPORT_IN_URB; ++i) { - usb_kill_urb(es1->cport_in_urb[i]); - usb_free_urb(es1->cport_in_urb[i]); - kfree(es1->cport_in_buffer[i]); - } - - usb_kill_urb(es1->svc_urb); - usb_free_urb(es1->svc_urb); - usb_put_dev(es1->usb_dev); - kfree(es1->svc_buffer); - greybus_remove_hd(es1->hd); - usb_set_intfdata(interface, NULL); -} - static struct usb_driver es1_ap_driver = { .name = "es1_ap_driver", .probe = ap_probe, -- cgit v0.10.2 From 1ec1d6dd357766cb6d1816ad61cc0f7ca3dbc960 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 20 Oct 2014 10:28:00 -0500 Subject: greybus: leverage ap_disconnect() in ap_probe() With a few minor changes, ap_disconnect() can correctly handle cleaning up even a partially initialized USB interface. Make those changes, and then use ap_disconnect() to simplify cleanup for all the error paths in ap_probe(). Reset all fields as they're cleaned up to facilitate debugging. Signed-off-by: Alex Elder diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 4473c9a..12eb9b2 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -277,22 +277,37 @@ static void ap_disconnect(struct usb_interface *interface) /* Tear down everything! */ for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - usb_kill_urb(es1->cport_out_urb[i]); - usb_free_urb(es1->cport_out_urb[i]); + struct urb *urb = es1->cport_out_urb[i]; + + if (!urb) + break; + usb_kill_urb(urb); + usb_free_urb(urb); + es1->cport_out_urb[i] = NULL; + es1->cport_out_urb_busy[i] = false; /* just to be anal */ } for (i = 0; i < NUM_CPORT_IN_URB; ++i) { - usb_kill_urb(es1->cport_in_urb[i]); - usb_free_urb(es1->cport_in_urb[i]); + struct urb *urb = es1->cport_in_urb[i]; + + if (!urb) + break; + usb_kill_urb(urb); + usb_free_urb(urb); kfree(es1->cport_in_buffer[i]); + es1->cport_in_buffer[i] = NULL; } usb_kill_urb(es1->svc_urb); usb_free_urb(es1->svc_urb); - usb_put_dev(es1->usb_dev); + es1->svc_urb = NULL; kfree(es1->svc_buffer); - greybus_remove_hd(es1->hd); + es1->svc_buffer = NULL; + usb_set_intfdata(interface, NULL); + greybus_remove_hd(es1->hd); + + usb_put_dev(es1->usb_dev); } /* Callback for when we get a SVC message */ @@ -466,7 +481,7 @@ static int ap_probe(struct usb_interface *interface, es1->svc_urb = usb_alloc_urb(0, GFP_KERNEL); if (!es1->svc_urb) - goto error_int_urb; + goto error; usb_fill_int_urb(es1->svc_urb, udev, usb_rcvintpipe(udev, es1->svc_endpoint), @@ -474,7 +489,7 @@ static int ap_probe(struct usb_interface *interface, es1, svc_interval); retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); if (retval) - goto error_submit_urb; + goto error; /* Allocate buffers for our cport in messages and start them up */ for (i = 0; i < NUM_CPORT_IN_URB; ++i) { @@ -483,10 +498,10 @@ static int ap_probe(struct usb_interface *interface, urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) - goto error_bulk_in_urb; + goto error; buffer = kmalloc(ES1_GBUF_MSG_SIZE, GFP_KERNEL); if (!buffer) - goto error_bulk_in_urb; + goto error; usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, es1->cport_in_endpoint), @@ -495,7 +510,7 @@ static int ap_probe(struct usb_interface *interface, es1->cport_in_buffer[i] = buffer; retval = usb_submit_urb(urb, GFP_KERNEL); if (retval) - goto error_bulk_in_urb; + goto error; } /* Allocate urbs for our CPort OUT messages */ @@ -504,31 +519,16 @@ static int ap_probe(struct usb_interface *interface, urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) - goto error_bulk_out_urb; + goto error; es1->cport_out_urb[i] = urb; es1->cport_out_urb_busy[i] = false; /* just to be anal */ } return 0; - -error_bulk_out_urb: - for (i = 0; i < NUM_CPORT_OUT_URB; ++i) - usb_free_urb(es1->cport_out_urb[i]); - -error_bulk_in_urb: - for (i = 0; i < NUM_CPORT_IN_URB; ++i) { - usb_kill_urb(es1->cport_in_urb[i]); - usb_free_urb(es1->cport_in_urb[i]); - kfree(es1->cport_in_buffer[i]); - } - -error_submit_urb: - usb_free_urb(es1->svc_urb); -error_int_urb: - kfree(es1->svc_buffer); error: - greybus_remove_hd(es1->hd); + ap_disconnect(interface); + return retval; } -- cgit v0.10.2 From c0855bfdd65dd5c100d5c63daab5897a117d8b49 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 21 Oct 2014 14:31:24 +0800 Subject: greybus: battery-gb: Add battery communication with the module This adds support to talk to the battery to get the various requests made to it, based on the battery protocol defined in the Greybus Specification. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index 09c3290..eca1d09 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -25,45 +25,245 @@ struct gb_battery { }; #define to_gb_battery(x) container_of(x, struct gb_battery, bat) +/* Version of the Greybus battery protocol we support */ +#define GB_BATTERY_VERSION_MAJOR 0x00 +#define GB_BATTERY_VERSION_MINOR 0x01 + +/* Greybus battery request types */ +#define GB_BATTERY_TYPE_INVALID 0x00 +#define GB_BATTERY_TYPE_PROTOCOL_VERSION 0x01 +#define GB_BATTERY_TYPE_TECHNOLOGY 0x02 +#define GB_BATTERY_TYPE_STATUS 0x03 +#define GB_BATTERY_TYPE_MAX_VOLTAGE 0x04 +#define GB_BATTERY_TYPE_CAPACITY 0x05 +#define GB_BATTERY_TYPE_TEMPERATURE 0x06 +#define GB_BATTERY_TYPE_VOLTAGE 0x07 + +struct gb_battery_proto_version_response { + __u8 status; + __u8 major; + __u8 minor; +}; + +/* Should match up with battery types in linux/power_supply.h */ +#define GB_BATTERY_TECH_UNKNOWN 0x0000 +#define GB_BATTERY_TECH_NiMH 0x0001 +#define GB_BATTERY_TECH_LION 0x0002 +#define GB_BATTERY_TECH_LIPO 0x0003 +#define GB_BATTERY_TECH_LiFe 0x0004 +#define GB_BATTERY_TECH_NiCd 0x0005 +#define GB_BATTERY_TECH_LiMn 0x0006 + +struct gb_battery_technology_request { + __u8 status; + __le32 technology; +}; + +/* Should match up with battery status in linux/power_supply.h */ +#define GB_BATTERY_STATUS_UNKNOWN 0x0000 +#define GB_BATTERY_STATUS_CHARGING 0x0001 +#define GB_BATTERY_STATUS_DISCHARGING 0x0002 +#define GB_BATTERY_STATUS_NOT_CHARGING 0x0003 +#define GB_BATTERY_STATUS_FULL 0x0004 + +struct gb_battery_status_request { + __u8 status; + __le16 battery_status; +}; + +struct gb_battery_max_voltage_request { + __u8 status; + __le32 max_voltage; +}; + +struct gb_battery_capacity_request { + __u8 status; + __le32 capacity; +}; + +struct gb_battery_temperature_request { + __u8 status; + __le32 temperature; +}; + +struct gb_battery_voltage_request { + __u8 status; + __le32 voltage; +}; + + static const struct greybus_module_id id_table[] = { { GREYBUS_DEVICE(0x42, 0x42) }, /* make shit up */ { }, /* terminating NULL entry */ }; +static int battery_operation(struct gb_battery *gb, int type, + void *response, int response_size) +{ + struct gb_connection *connection = gb->connection; + struct gb_operation *operation; + struct gb_battery_technology_request *fake_request; + u8 *local_response; + int ret; + + local_response = kmalloc(response_size, GFP_KERNEL); + if (!local_response) + return -ENOMEM; + + operation = gb_operation_create(connection, type, 0, response_size); + if (!operation) { + kfree(local_response); + return -ENOMEM; + } + + /* Synchronous operation--no callback */ + ret = gb_operation_request_send(operation, NULL); + if (ret) { + pr_err("version operation failed (%d)\n", ret); + goto out; + } + + /* + * We only want to look at the status, and all requests have the same + * layout for where the status is, so cast this to a random request so + * we can see the status easier. + */ + fake_request = (struct gb_battery_technology_request *)local_response; + if (fake_request->status) { + gb_connection_err(connection, "version response %hhu", + fake_request->status); + ret = -EIO; + } else { + /* Good request, so copy to the caller's buffer */ + memcpy(response, local_response, response_size); + } +out: + gb_operation_destroy(operation); + + return ret; +} + +/* + * This request only uses the connection field, and if successful, + * fills in the major and minor protocol version of the target. + */ +static int get_version(struct gb_battery *gb) +{ + struct gb_battery_proto_version_response version_request; + int retval; + + retval = battery_operation(gb, GB_BATTERY_TYPE_PROTOCOL_VERSION, + &version_request, sizeof(version_request)); + if (retval) + return retval; + + if (version_request.major > GB_BATTERY_VERSION_MAJOR) { + pr_err("unsupported major version (%hhu > %hhu)\n", + version_request.major, GB_BATTERY_VERSION_MAJOR); + return -ENOTSUPP; + } + + gb->version_major = version_request.major; + gb->version_minor = version_request.minor; + return 0; +} + static int get_tech(struct gb_battery *gb) { - // FIXME - guess! - return POWER_SUPPLY_TECHNOLOGY_NiMH; + struct gb_battery_technology_request tech_request; + u32 technology; + int retval; + + retval = battery_operation(gb, GB_BATTERY_TYPE_TECHNOLOGY, + &tech_request, sizeof(tech_request)); + if (retval) + return retval; + + /* + * We have a one-to-one mapping of tech types to power_supply + * status, so just return that value. + */ + technology = le32_to_cpu(tech_request.technology); + return technology; } static int get_status(struct gb_battery *gb) { - // FIXME!!! - return 0; + struct gb_battery_status_request status_request; + u16 battery_status; + int retval; + + retval = battery_operation(gb, GB_BATTERY_TYPE_STATUS, + &status_request, sizeof(status_request)); + if (retval) + return retval; + + /* + * We have a one-to-one mapping of battery status to power_supply + * status, so just return that value. + */ + battery_status = le16_to_cpu(status_request.battery_status); + return battery_status; } static int get_max_voltage(struct gb_battery *gb) { - // FIXME!!! - return 4700000; + struct gb_battery_max_voltage_request volt_request; + u32 max_voltage; + int retval; + + retval = battery_operation(gb, GB_BATTERY_TYPE_MAX_VOLTAGE, + &volt_request, sizeof(volt_request)); + if (retval) + return retval; + + max_voltage = le32_to_cpu(volt_request.max_voltage); + return max_voltage; } static int get_capacity(struct gb_battery *gb) { - // FIXME!!! - return 0; + struct gb_battery_capacity_request capacity_request; + u32 capacity; + int retval; + + retval = battery_operation(gb, GB_BATTERY_TYPE_CAPACITY, + &capacity_request, sizeof(capacity_request)); + if (retval) + return retval; + + capacity = le32_to_cpu(capacity_request.capacity); + return capacity; } static int get_temp(struct gb_battery *gb) { - // FIXME!!! - return 0; + struct gb_battery_temperature_request temp_request; + u32 temperature; + int retval; + + retval = battery_operation(gb, GB_BATTERY_TYPE_TEMPERATURE, + &temp_request, sizeof(temp_request)); + if (retval) + return retval; + + temperature = le32_to_cpu(temp_request.temperature); + return temperature; } static int get_voltage(struct gb_battery *gb) { - // FIXME!!! - return 0; + struct gb_battery_voltage_request voltage_request; + u32 voltage; + int retval; + + retval = battery_operation(gb, GB_BATTERY_TYPE_VOLTAGE, + &voltage_request, sizeof(voltage_request)); + if (retval) + return retval; + + voltage = le32_to_cpu(voltage_request.voltage); + return voltage; } static int get_property(struct power_supply *b, @@ -126,6 +326,13 @@ int gb_battery_device_init(struct gb_connection *connection) gb->connection = connection; // FIXME refcount! + /* Check the version */ + retval = get_version(gb); + if (retval) { + kfree(gb); + return retval; + } + b = &gb->bat; // FIXME - get a better (i.e. unique) name // FIXME - anything else needs to be set? -- cgit v0.10.2 From 03130a77d52bd738cdcee17627aa5e3d19fdbeeb Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 20 Oct 2014 23:01:02 -0500 Subject: greybus: fix op_cycle logic The function that computes the operation id for a connection is wrongly using MOD rather than AND. Fix that. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 7a86c7c..09fe25d 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -171,7 +171,7 @@ void gb_connection_destroy(struct gb_connection *connection) u16 gb_connection_operation_id(struct gb_connection *connection) { - return (u16)(atomic_inc_return(&connection->op_cycle) % U16_MAX); + return (u16)(atomic_inc_return(&connection->op_cycle) & (int)U16_MAX); } void gb_connection_err(struct gb_connection *connection, const char *fmt, ...) -- cgit v0.10.2 From fb305c335ca3c7f175c18654d952880ec91df9ef Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 20 Oct 2014 23:01:03 -0500 Subject: greybus: stash power supply pointer in connection The battery code was not stashing a copy of its private data pointer. It'll be needed in the next patch. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index 09c3290..5d0db61 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -125,6 +125,7 @@ int gb_battery_device_init(struct gb_connection *connection) return -ENOMEM; gb->connection = connection; // FIXME refcount! + connection->private = gb; b = &gb->bat; // FIXME - get a better (i.e. unique) name -- cgit v0.10.2 From 697e55d35dcb441cc5bd800efae0f98ec8d63fd9 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 20 Oct 2014 23:01:04 -0500 Subject: greybus: improve module cleanup code When a module gets destroyed all of its state and the state of its interfaces and connections (etc.) need to be torn down. This is not now being done properly. Add this teardown code. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index 5d0db61..a3b2bee 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -145,6 +145,14 @@ int gb_battery_device_init(struct gb_connection *connection) return 0; } +void gb_battery_device_exit(struct gb_connection *connection) +{ + struct gb_battery *gb = connection->private; + + power_supply_unregister(&gb->bat); + kfree(gb); +} + void gb_battery_disconnect(struct gb_module *gmod) { #if 0 diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 09fe25d..e2340d8 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -220,3 +220,27 @@ int gb_connection_init(struct gb_connection *connection) } return -ENXIO; } + +void gb_connection_exit(struct gb_connection *connection) +{ + switch (connection->protocol) { + case GREYBUS_PROTOCOL_I2C: + gb_i2c_device_exit(connection); + break; + case GREYBUS_PROTOCOL_GPIO: + gb_gpio_controller_exit(connection); + break; + case GREYBUS_PROTOCOL_BATTERY: + gb_battery_device_exit(connection); + break; + case GREYBUS_PROTOCOL_CONTROL: + case GREYBUS_PROTOCOL_AP: + case GREYBUS_PROTOCOL_UART: + case GREYBUS_PROTOCOL_HID: + case GREYBUS_PROTOCOL_VENDOR: + default: + gb_connection_err(connection, "unimplemented protocol %u", + (u32)connection->protocol); + break; + } +} diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index bb22c52..685c1ff 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -35,6 +35,7 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, void gb_connection_destroy(struct gb_connection *connection); int gb_connection_init(struct gb_connection *connection); +void gb_connection_exit(struct gb_connection *connection); struct gb_connection *gb_hd_connection_find(struct greybus_host_device *hd, u16 cport_id); diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index b59dee1..bc27ad6 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -119,10 +119,9 @@ static void greybus_module_release(struct device *dev) { struct gb_module *gmod = to_gb_module(dev); - kfree(gmod); + gb_module_destroy(gmod); } - static struct device_type greybus_module_type = { .name = "greybus_module", .release = greybus_module_release, @@ -157,7 +156,7 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, */ if (!gb_manifest_parse(gmod, data, size)) { dev_err(hd->parent, "manifest error\n"); - goto error; + goto err_module; } /* @@ -180,14 +179,14 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, retval = device_add(&gmod->dev); if (retval) - goto error; + goto err_device; gb_module_interfaces_init(gmod); - return; -error: - gb_module_destroy(gmod); + return; +err_device: put_device(&gmod->dev); +err_module: greybus_module_release(&gmod->dev); } diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index c09572c..bbd90b4 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -265,8 +265,13 @@ void gb_deregister_cport_complete(u16 cport_id); extern const struct attribute_group *greybus_module_groups[]; int gb_i2c_device_init(struct gb_connection *connection); +void gb_i2c_device_exit(struct gb_connection *connection); + int gb_battery_device_init(struct gb_connection *connection); +void gb_battery_device_exit(struct gb_connection *connection); + int gb_gpio_controller_init(struct gb_connection *connection); +void gb_gpio_controller_exit(struct gb_connection *connection); int gb_tty_init(void); void gb_tty_exit(void); diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 0c2fdd3..645f05b 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -54,6 +54,8 @@ void gb_interface_destroy(struct gb_interface *interface) list_del(&interface->links); spin_unlock_irq(&gb_interfaces_lock); + gb_interface_connections_exit(interface); + /* kref_put(gmod); */ kfree(interface); } @@ -72,3 +74,15 @@ int gb_interface_connections_init(struct gb_interface *interface) return ret; } + +void gb_interface_connections_exit(struct gb_interface *interface) +{ + struct gb_connection *connection; + struct gb_connection *next; + + list_for_each_entry_safe(connection, next, &interface->connections, + interface_links) { + gb_connection_exit(connection); + gb_connection_destroy(connection); + } +} diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 1019a98..f0c9e1d 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -23,5 +23,6 @@ struct gb_interface *gb_interface_create(struct gb_module *gmod, u8 module_id); void gb_interface_destroy(struct gb_interface *interface); int gb_interface_connections_init(struct gb_interface *interface); +void gb_interface_connections_exit(struct gb_interface *interface); #endif /* __INTERFACE_H */ diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index 699cd00..2883947 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -44,6 +44,15 @@ const struct greybus_module_id *gb_module_match_id(struct gb_module *gmod, return NULL; } +static void gb_module_interfaces_exit(struct gb_module *gmod) +{ + struct gb_interface *interface; + struct gb_interface *next; + + list_for_each_entry_safe(interface, next, &gmod->interfaces, links) + gb_interface_destroy(interface); +} + /* * A Greybus module represents a user-replacable component on an Ara * phone. @@ -62,7 +71,7 @@ struct gb_module *gb_module_create(struct greybus_host_device *hd, u8 module_id) return NULL; gmod->hd = hd; /* XXX refcount? */ - gmod->module_id = module_id; + gmod->module_id = module_id; /* XXX check for dups */ INIT_LIST_HEAD(&gmod->interfaces); spin_lock_irq(&gb_modules_lock); @@ -80,15 +89,21 @@ void gb_module_destroy(struct gb_module *gmod) if (WARN_ON(!gmod)) return; - kfree(gmod->product_string); - kfree(gmod->vendor_string); - spin_lock_irq(&gb_modules_lock); list_del(&gmod->links); spin_unlock_irq(&gb_modules_lock); + gb_module_interfaces_exit(gmod); + /* XXX Do something with gmod->gb_tty */ + + put_device(&gmod->dev); + /* kfree(gmod->dev->name); */ + + kfree(gmod->product_string); + kfree(gmod->vendor_string); /* kref_put(module->hd); */ + kfree(gmod); } -- cgit v0.10.2 From 98f4ab2df9b51356b48210188b4fbff41789acbb Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Tue, 21 Oct 2014 01:52:27 -0400 Subject: greybus: ap: add support for the AP Device ID unipro management function message The AP needs to know its assigned Device ID in order to establish Greybus connections between CPorts. We could have pulled the Device ID from the controller hardware in a driver specific manner, but instead we define one generic message from the SVC to let the AP know this information. Add this additional unipro management message and handle it by setting the supplied Device ID in the struct greybus_host_device. The greybus core will use this to populate the source Device ID when establishing a connection between the AP and another module's CPort. Signed-off-by: Matt Porter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index f4470b5..5b63356 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -113,8 +113,13 @@ static void svc_management(struct svc_function_unipro_management *management, return; } - /* What? An AP should not get this message */ - dev_err(hd->parent, "Got an svc management message???\n"); + switch (management->management_packet_type) { + case SVC_MANAGEMENT_AP_DEVICE_ID: + hd->device_id = management->ap_device_id.device_id; + break; + default: + dev_err(hd->parent, "Unhandled UniPro management message\n"); + } } static void svc_hotplug(struct svc_function_hotplug *hotplug, diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index bbd90b4..a4e1f4b 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -180,6 +180,7 @@ struct greybus_host_device { struct rb_root connections; struct ida cport_id_map; spinlock_t cport_id_map_lock; + u8 device_id; /* Private data for the host driver */ unsigned long hd_priv[0] __aligned(sizeof(s64)); diff --git a/drivers/staging/greybus/svc_msg.h b/drivers/staging/greybus/svc_msg.h index 57d0a91..4aa7e17 100644 --- a/drivers/staging/greybus/svc_msg.h +++ b/drivers/staging/greybus/svc_msg.h @@ -58,9 +58,14 @@ struct svc_function_unipro_link_up { __u8 device_id; }; +struct svc_function_ap_device_id { + __u8 device_id; +}; + enum svc_function_management_event { SVC_MANAGEMENT_SET_ROUTE = 0x00, SVC_MANAGEMENT_LINK_UP = 0x01, + SVC_MANAGEMENT_AP_DEVICE_ID = 0x02, }; struct svc_function_unipro_management { @@ -68,6 +73,7 @@ struct svc_function_unipro_management { union { struct svc_function_unipro_set_route set_route; struct svc_function_unipro_link_up link_up; + struct svc_function_ap_device_id ap_device_id; }; }; -- cgit v0.10.2 From c9346e19b25f9abc7630200d7d180a20224a956c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 21 Oct 2014 15:51:53 +0800 Subject: greybus: battery-gb.c: fix memory leak found by Viresh Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index 03c16f7..fd2b86e 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -139,6 +139,7 @@ static int battery_operation(struct gb_battery *gb, int type, } out: gb_operation_destroy(operation); + kfree(local_response); return ret; } -- cgit v0.10.2 From 0369a459982f58688235000fc8990b70e7553e6e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 21 Oct 2014 16:25:13 +0800 Subject: greybus: battery-gb: Allow kernel values to get out of sync with greybus spec We can't know that the greybus values and the kernel values for a number of battery enumerated types will remain in sync. And as theses are sent by an external device from the kernel, we have to explicitly check these values. Reported-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index fd2b86e..592b68d 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -181,10 +181,35 @@ static int get_tech(struct gb_battery *gb) return retval; /* - * We have a one-to-one mapping of tech types to power_supply - * status, so just return that value. + * Map greybus values to power_supply values. Hopefully these are + * "identical" which should allow gcc to optomize the code away to + * nothing. */ technology = le32_to_cpu(tech_request.technology); + switch (technology) { + case GB_BATTERY_TECH_NiMH: + technology = POWER_SUPPLY_TECHNOLOGY_NiMH; + break; + case GB_BATTERY_TECH_LION: + technology = POWER_SUPPLY_TECHNOLOGY_LION; + break; + case GB_BATTERY_TECH_LIPO: + technology = POWER_SUPPLY_TECHNOLOGY_LIPO; + break; + case GB_BATTERY_TECH_LiFe: + technology = POWER_SUPPLY_TECHNOLOGY_LiFe; + break; + case GB_BATTERY_TECH_NiCd: + technology = POWER_SUPPLY_TECHNOLOGY_NiCd; + break; + case GB_BATTERY_TECH_LiMn: + technology = POWER_SUPPLY_TECHNOLOGY_LiMn; + break; + case GB_BATTERY_TECH_UNKNOWN: + default: + technology = POWER_SUPPLY_TECHNOLOGY_UNKNOWN; + break; + } return technology; } @@ -200,10 +225,29 @@ static int get_status(struct gb_battery *gb) return retval; /* - * We have a one-to-one mapping of battery status to power_supply - * status, so just return that value. + * Map greybus values to power_supply values. Hopefully these are + * "identical" which should allow gcc to optomize the code away to + * nothing. */ battery_status = le16_to_cpu(status_request.battery_status); + switch (battery_status) { + case GB_BATTERY_STATUS_CHARGING: + battery_status = POWER_SUPPLY_STATUS_CHARGING; + break; + case GB_BATTERY_STATUS_DISCHARGING: + battery_status = POWER_SUPPLY_STATUS_DISCHARGING; + break; + case GB_BATTERY_STATUS_NOT_CHARGING: + battery_status = POWER_SUPPLY_STATUS_NOT_CHARGING; + break; + case GB_BATTERY_STATUS_FULL: + battery_status = POWER_SUPPLY_STATUS_FULL; + break; + case GB_BATTERY_STATUS_UNKNOWN: + default: + battery_status = POWER_SUPPLY_STATUS_UNKNOWN; + break; + } return battery_status; } -- cgit v0.10.2 From 6271b5bac99c2d06543adbdbecb9157d77765831 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Tue, 21 Oct 2014 22:43:29 -0400 Subject: greybus: module: add gb_module_find() Add support for getting a struct gb_module from a Module ID. Signed-off-by: Matt Porter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index 2883947..50139f4 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -107,6 +107,17 @@ void gb_module_destroy(struct gb_module *gmod) kfree(gmod); } +struct gb_module *gb_module_find(struct greybus_host_device *hd, u8 module_id) +{ + struct gb_module *module; + + list_for_each_entry(module, &hd->modules, links) + if (module->module_id == module_id) + return module; + + return NULL; +} + void gb_module_interfaces_init(struct gb_module *gmod) { struct gb_interface *interface; diff --git a/drivers/staging/greybus/module.h b/drivers/staging/greybus/module.h index 2c6707d..82def46 100644 --- a/drivers/staging/greybus/module.h +++ b/drivers/staging/greybus/module.h @@ -52,6 +52,9 @@ struct gb_module *gb_module_create(struct greybus_host_device *hd, u8 module_id); void gb_module_destroy(struct gb_module *module); +struct gb_module *gb_module_find(struct greybus_host_device *hd, + u8 module_id); + void gb_module_interfaces_init(struct gb_module *gmod); #endif /* __MODULE_H */ -- cgit v0.10.2 From 1a4c013a44add7f174e0507f0240f3b3cc810301 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Tue, 21 Oct 2014 22:43:30 -0400 Subject: greybus: interface: add gb_interface_find() Add support for getting a struct gb_interface from an Interface ID. Signed-off-by: Matt Porter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 645f05b..0415db5 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -60,6 +60,18 @@ void gb_interface_destroy(struct gb_interface *interface) kfree(interface); } +struct gb_interface *gb_interface_find(struct gb_module *module, + u8 interface_id) +{ + struct gb_interface *interface; + + list_for_each_entry(interface, &module->interfaces, links) + if (interface->id == interface_id) + return interface; + + return NULL; +} + int gb_interface_connections_init(struct gb_interface *interface) { struct gb_connection *connection; diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index f0c9e1d..907b634 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -14,6 +14,7 @@ struct gb_interface { struct gb_module *gmod; u8 id; + u8 device_id; struct list_head connections; struct list_head links; /* module->interfaces */ @@ -22,6 +23,8 @@ struct gb_interface { struct gb_interface *gb_interface_create(struct gb_module *gmod, u8 module_id); void gb_interface_destroy(struct gb_interface *interface); +struct gb_interface *gb_interface_find(struct gb_module *gmod, u8 interface_id); + int gb_interface_connections_init(struct gb_interface *interface); void gb_interface_connections_exit(struct gb_interface *interface); -- cgit v0.10.2 From 6232b073d44646e3051a8871feb2deaabe9d624c Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Tue, 21 Oct 2014 22:43:31 -0400 Subject: greybus: ap: process the UniPro link up message The link up message is the event that tells the AP what device ID has been assigned to a particular interface on a module during enumeration. The link up is sent *only* after the hotplug event for a particular module has been sent to the AP. The link up payload must carry the Module ID and Interface ID to uniquely identify the struct gb_interface to which the Device ID has been assigned. After processing of the link up message, the interface's device_id field will contain the assigned Device ID so that the AP has the information necessary to issue network route commands. Signed-off-by: Matt Porter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 5b63356..c8f30f6 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -106,6 +106,9 @@ static void svc_handshake(struct svc_function_handshake *handshake, static void svc_management(struct svc_function_unipro_management *management, int payload_length, struct greybus_host_device *hd) { + struct gb_module *module; + struct gb_interface *interface; + if (payload_length != sizeof(struct svc_function_unipro_management)) { dev_err(hd->parent, "Illegal size of svc management message %d\n", @@ -114,6 +117,22 @@ static void svc_management(struct svc_function_unipro_management *management, } switch (management->management_packet_type) { + case SVC_MANAGEMENT_LINK_UP: + module = gb_module_find(hd, management->link_up.module_id); + if (!module) { + dev_err(hd->parent, "Module ID %d not found\n", + management->link_up.module_id); + return; + } + interface = gb_interface_find(module, + management->link_up.interface_id); + if (!interface) { + dev_err(hd->parent, "Interface ID %d not found\n", + management->link_up.interface_id); + return; + } + interface->device_id = management->link_up.device_id; + break; case SVC_MANAGEMENT_AP_DEVICE_ID: hd->device_id = management->ap_device_id.device_id; break; diff --git a/drivers/staging/greybus/svc_msg.h b/drivers/staging/greybus/svc_msg.h index 4aa7e17..47597e6 100644 --- a/drivers/staging/greybus/svc_msg.h +++ b/drivers/staging/greybus/svc_msg.h @@ -55,6 +55,8 @@ struct svc_function_unipro_set_route { }; struct svc_function_unipro_link_up { + __u8 module_id; + __u8 interface_id; __u8 device_id; }; -- cgit v0.10.2 From e390b193d6abef0ed3316e3738cbadba8e9c7e17 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Wed, 22 Oct 2014 02:06:08 -0400 Subject: greybus: svc: remove unneeded fields from the unipro set route message payload CPort connections are being handled in the application layer connection protocol and the layer 3 switch doesn't care about them. Also, the switch doesn't care about a source device id when setting up the route table. Reduce the message to just the necessary destination device ID. As the SVC is aware of which switch port it found the module/interface and assigned the device ID, we can simply tell the SVC to set a route to the device ID it has reported to the AP as being active. Signed-off-by: Matt Porter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc_msg.h b/drivers/staging/greybus/svc_msg.h index 47597e6..661cbae 100644 --- a/drivers/staging/greybus/svc_msg.h +++ b/drivers/staging/greybus/svc_msg.h @@ -48,10 +48,7 @@ struct svc_function_handshake { }; struct svc_function_unipro_set_route { - __u8 source_device_id; - __u8 source_cport_id; /* bottom 8 bits */ - __u8 destination_device_id; - __u8 destination_cport_id; /* bottom 8 bits */ + __u8 device_id; }; struct svc_function_unipro_link_up { -- cgit v0.10.2 From 060b93ddbb5dedd10bddb61664815752db56a9f3 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Wed, 22 Oct 2014 02:06:09 -0400 Subject: greybus: ap: add svc_set_route_send() command and use it on a link up event When the AP receives a link up event, request that the SVC set a route to the interface's device id (this device id has been previously reported to the AP). In the future, we may not always immediately set a route upon receiving a link up event but this is sufficient for the known use cases at this time. Signed-off-by: Matt Porter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index c8f30f6..46553b1 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -103,6 +103,23 @@ static void svc_handshake(struct svc_function_handshake *handshake, svc_msg_send(svc_msg, hd); } +static void svc_set_route_send(struct gb_interface *interface, + struct greybus_host_device *hd) +{ + struct svc_msg *svc_msg; + + svc_msg = svc_msg_alloc(SVC_FUNCTION_UNIPRO_NETWORK_MANAGEMENT); + if (!svc_msg) + return; + + svc_msg->header.function_id = SVC_FUNCTION_UNIPRO_NETWORK_MANAGEMENT; + svc_msg->header.message_type = SVC_MSG_DATA; + svc_msg->header.payload_length = + cpu_to_le16(sizeof(struct svc_function_unipro_set_route)); + svc_msg->management.set_route.device_id = interface->device_id; + svc_msg_send(svc_msg, hd); +} + static void svc_management(struct svc_function_unipro_management *management, int payload_length, struct greybus_host_device *hd) { @@ -132,6 +149,7 @@ static void svc_management(struct svc_function_unipro_management *management, return; } interface->device_id = management->link_up.device_id; + svc_set_route_send(interface, hd); break; case SVC_MANAGEMENT_AP_DEVICE_ID: hd->device_id = management->ap_device_id.device_id; -- cgit v0.10.2 From 63e4a8ee8fdd9d86e7d2f16a99d82ee03fa0a785 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 22 Oct 2014 16:38:07 +0800 Subject: greybus: module: fix double free of module Also properly clean up all modules when you remove a host driver Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index bc27ad6..480e12b 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -190,6 +190,13 @@ err_module: greybus_module_release(&gmod->dev); } +static void gb_delete_module(struct gb_module *gmod) +{ + /* FIXME - tear down interfaces first */ + + device_del(&gmod->dev); +} + void gb_remove_module(struct greybus_host_device *hd, u8 module_id) { struct gb_module *gmod; @@ -202,15 +209,18 @@ void gb_remove_module(struct greybus_host_device *hd, u8 module_id) } if (found) - greybus_remove_device(gmod); + gb_delete_module(gmod); else dev_err(hd->parent, "module id %d remove error\n", module_id); } -void greybus_remove_device(struct gb_module *gmod) +static void gb_remove_modules(struct greybus_host_device *hd) { - device_del(&gmod->dev); - put_device(&gmod->dev); + struct gb_module *gmod, *temp; + + list_for_each_entry_safe(gmod, temp, &hd->modules, links) { + gb_delete_module(gmod); + } } static DEFINE_MUTEX(hd_mutex); @@ -248,6 +258,7 @@ EXPORT_SYMBOL_GPL(greybus_create_hd); void greybus_remove_hd(struct greybus_host_device *hd) { + gb_remove_modules(hd); kref_put_mutex(&hd->kref, free_hd, &hd_mutex); } EXPORT_SYMBOL_GPL(greybus_remove_hd); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index a4e1f4b..4baa372 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -242,8 +242,6 @@ void greybus_deregister(struct greybus_driver *driver); int greybus_disabled(void); -void greybus_remove_device(struct gb_module *gmod); - /* Internal functions to gb module, move to internal .h file eventually. */ void gb_add_module(struct greybus_host_device *hd, u8 module_id, -- cgit v0.10.2 From e816e3741956746d7a0e1992e4a4e96e8af5ab30 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 22 Oct 2014 02:04:28 -0500 Subject: greybus: time out operation requests Arrange for operation requests that takke too long to time out. At the moment, nothing happens when that occurs (other than a silly message getting printed). When the connection and operation and interface and module code are cleaned up properly, this event should most likely cause the affected module to get torn down. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index e2340d8..368f056 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -102,6 +102,15 @@ static void gb_connection_hd_cport_id_free(struct gb_connection *connection) connection->hd_cport_id = CPORT_ID_BAD; } +static void connection_timeout(struct work_struct *work) +{ + struct gb_connection *connection; + + connection = + container_of(work, struct gb_connection, timeout_work.work); + printk("timeout!\n"); +} + /* * Set up a Greybus connection, representing the bidirectional link * between a CPort on a (local) Greybus host device and a CPort on @@ -143,6 +152,7 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, INIT_LIST_HEAD(&connection->operations); connection->pending = RB_ROOT; atomic_set(&connection->op_cycle, 0); + INIT_DELAYED_WORK(&connection->timeout_work, connection_timeout); return connection; } diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 685c1ff..b5901a1 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -26,6 +26,7 @@ struct gb_connection { struct list_head operations; struct rb_root pending; /* awaiting reponse */ atomic_t op_cycle; + struct delayed_work timeout_work; void *private; }; diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index da455f0..e70e8a3 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -19,6 +19,8 @@ */ #define GB_OPERATION_TYPE_RESPONSE 0x80 +#define CONNECTION_TIMEOUT_DEFAULT 1000 /* milliseconds */ + /* * XXX This needs to be coordinated with host driver parameters */ @@ -62,6 +64,8 @@ static void gb_operation_insert(struct gb_operation *operation) struct rb_node **link = &root->rb_node; struct rb_node *above = NULL; struct gb_operation_msg_hdr *header; + unsigned long timeout; + bool start_timer; __le16 wire_id; /* @@ -76,6 +80,16 @@ static void gb_operation_insert(struct gb_operation *operation) /* OK, insert the operation into its connection's tree */ spin_lock_irq(&gb_operations_lock); + /* + * We impose a time limit for requests to complete. If + * there are no requests pending there is no need for a + * timer. So if this will be the only one in flight we'll + * need to start the timer. Otherwise we just update the + * existing one to give this request a full timeout period + * to complete. + */ + start_timer = RB_EMPTY_ROOT(root); + while (*link) { struct gb_operation *other; @@ -89,15 +103,31 @@ static void gb_operation_insert(struct gb_operation *operation) } rb_link_node(node, above, link); rb_insert_color(node, root); - spin_unlock_irq(&gb_operations_lock); + + timeout = msecs_to_jiffies(CONNECTION_TIMEOUT_DEFAULT); + if (start_timer) + schedule_delayed_work(&connection->timeout_work, timeout); + else + mod_delayed_work(system_wq, &connection->timeout_work, timeout); } static void gb_operation_remove(struct gb_operation *operation) { + struct gb_connection *connection = operation->connection; + bool last_pending; + spin_lock_irq(&gb_operations_lock); - rb_erase(&operation->node, &operation->connection->pending); + rb_erase(&operation->node, &connection->pending); + last_pending = RB_EMPTY_ROOT(&connection->pending); spin_unlock_irq(&gb_operations_lock); + + /* + * If there are no more pending requests, we can stop the + * timeout timer. + */ + if (last_pending) + cancel_delayed_work(&connection->timeout_work); } static struct gb_operation * -- cgit v0.10.2 From e1158df0634ab771297fc7510dd78bcbe83e8c87 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 22 Oct 2014 02:04:29 -0500 Subject: greybus: define operation_cancel() Define a new function operation_cancel() that cancels an outstanding operation. Use it to clear out any operations that might be pending at the time a connection is torn down. Note: This code isn't really functional yet, partially because greybus_kill_gbuf() is not implemented. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 368f056..9bcda99 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -162,12 +162,19 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, */ void gb_connection_destroy(struct gb_connection *connection) { + struct gb_operation *operation; + struct gb_operation *next; + if (WARN_ON(!connection)) return; /* XXX Need to wait for any outstanding requests to complete */ WARN_ON(!list_empty(&connection->operations)); + list_for_each_entry_safe(operation, next, &connection->operations, + links) { + gb_operation_cancel(operation); + } spin_lock_irq(&gb_connections_lock); list_del(&connection->interface_links); _gb_hd_connection_remove(connection); diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index e70e8a3..afb42d5 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -501,6 +501,24 @@ void gb_connection_operation_recv(struct gb_connection *connection, queue_work(gb_operation_recv_workqueue, &operation->recv_work); } +/* + * Cancel an operation. + */ +void gb_operation_cancel(struct gb_operation *operation) +{ + int ret; + + operation->canceled = true; + ret = greybus_kill_gbuf(operation->request); + if (ret) + pr_warn("error %d killing request gbuf\n", ret); + if (operation->response) { + ret = greybus_kill_gbuf(operation->response); + if (ret) + pr_warn("error %d killing response gbuf\n", ret); + } +} + int gb_operation_init(void) { gb_operation_cache = kmem_cache_create("gb_operation_cache", diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 59aad3a..1a8e6b9 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -55,6 +55,7 @@ struct gb_operation { struct gbuf *request; struct gbuf *response; u16 id; + bool canceled; u8 result; struct work_struct recv_work; @@ -81,6 +82,7 @@ int gb_operation_request_send(struct gb_operation *operation, gb_operation_callback callback); int gb_operation_response_send(struct gb_operation *operation); +void gb_operation_cancel(struct gb_operation *operation); int gb_operation_wait(struct gb_operation *operation); void gb_operation_complete(struct gb_operation *operation); -- cgit v0.10.2 From 36561f23a80b7c44320f34a3b6e6833616e50200 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 22 Oct 2014 02:04:30 -0500 Subject: greybus: define connection state Define the state of a connection. A connection will not be enabled until it has been successfully set up. Once it starts getting torn down its state will move to "being destroyed". Don't send any operation request messages unless the connection is enabled. And drop any incoming messages if if the connection is not enabled. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 9bcda99..b1e933f 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -143,6 +143,7 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, connection->interface = interface; /* XXX refcount? */ connection->interface_cport_id = cport_id; connection->protocol = protocol; + connection->state = GB_CONNECTION_STATE_DISABLED; spin_lock_irq(&gb_connections_lock); _gb_hd_connection_insert(hd, connection); @@ -217,13 +218,20 @@ void gb_connection_err(struct gb_connection *connection, const char *fmt, ...) */ int gb_connection_init(struct gb_connection *connection) { + int ret; + + /* Need to enable the connection to initialize it */ + connection->state = GB_CONNECTION_STATE_ENABLED; switch (connection->protocol) { case GREYBUS_PROTOCOL_I2C: - return gb_i2c_device_init(connection); + ret = gb_i2c_device_init(connection); + break; case GREYBUS_PROTOCOL_GPIO: - return gb_gpio_controller_init(connection); + ret = gb_gpio_controller_init(connection); + break; case GREYBUS_PROTOCOL_BATTERY: - return gb_battery_device_init(connection); + ret = gb_battery_device_init(connection); + break; case GREYBUS_PROTOCOL_CONTROL: case GREYBUS_PROTOCOL_AP: case GREYBUS_PROTOCOL_UART: @@ -233,13 +241,20 @@ int gb_connection_init(struct gb_connection *connection) default: gb_connection_err(connection, "unimplemented protocol %u", (u32)connection->protocol); + ret = -ENXIO; break; } - return -ENXIO; + + if (ret) + connection->state = GB_CONNECTION_STATE_ERROR; + + return ret; } void gb_connection_exit(struct gb_connection *connection) { + connection->state = GB_CONNECTION_STATE_DESTROYING; + switch (connection->protocol) { case GREYBUS_PROTOCOL_I2C: gb_i2c_device_exit(connection); diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index b5901a1..a16e52a 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -13,6 +13,14 @@ #include "greybus.h" +enum gb_connection_state { + GB_CONNECTION_STATE_INVALID = 0, + GB_CONNECTION_STATE_DISABLED = 1, + GB_CONNECTION_STATE_ENABLED = 2, + GB_CONNECTION_STATE_ERROR = 3, + GB_CONNECTION_STATE_DESTROYING = 4, +}; + struct gb_connection { struct greybus_host_device *hd; struct gb_interface *interface; @@ -22,6 +30,7 @@ struct gb_connection { struct rb_node hd_node; struct list_head interface_links; enum greybus_protocol protocol; + enum gb_connection_state state; struct list_head operations; struct rb_root pending; /* awaiting reponse */ diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index afb42d5..5d23d19 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -417,6 +417,9 @@ int gb_operation_request_send(struct gb_operation *operation, { int ret; + if (operation->connection->state != GB_CONNECTION_STATE_ENABLED) + return -ENOTCONN; + /* * XXX * I think the order of operations is going to be @@ -461,6 +464,9 @@ void gb_connection_operation_recv(struct gb_connection *connection, struct gbuf *gbuf; u16 msg_size; + if (connection->state != GB_CONNECTION_STATE_ENABLED) + return; + if (size > GB_OPERATION_MESSAGE_SIZE_MAX) { gb_connection_err(connection, "message too big"); return; -- cgit v0.10.2 From 525f1467bc22ad7d0866444b3a57c21ba64a0dd2 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 22 Oct 2014 02:04:31 -0500 Subject: greybus: make svc_set_route_send() public Give svc_set_route_send() non-private scope so it can be used by a function outside "ap.c" in the next patch. Change its type so it can tell its caller if an error occurs. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 46553b1..7ea329c 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -100,24 +100,26 @@ static void svc_handshake(struct svc_function_handshake *handshake, svc_msg->handshake.version_major = GREYBUS_VERSION_MAJOR; svc_msg->handshake.version_minor = GREYBUS_VERSION_MINOR; svc_msg->handshake.handshake_type = SVC_HANDSHAKE_AP_HELLO; - svc_msg_send(svc_msg, hd); + + (void)svc_msg_send(svc_msg, hd); } -static void svc_set_route_send(struct gb_interface *interface, +int svc_set_route_send(struct gb_interface *interface, struct greybus_host_device *hd) { struct svc_msg *svc_msg; svc_msg = svc_msg_alloc(SVC_FUNCTION_UNIPRO_NETWORK_MANAGEMENT); if (!svc_msg) - return; + return -ENOMEM; svc_msg->header.function_id = SVC_FUNCTION_UNIPRO_NETWORK_MANAGEMENT; svc_msg->header.message_type = SVC_MSG_DATA; svc_msg->header.payload_length = cpu_to_le16(sizeof(struct svc_function_unipro_set_route)); svc_msg->management.set_route.device_id = interface->device_id; - svc_msg_send(svc_msg, hd); + + return svc_msg_send(svc_msg, hd); } static void svc_management(struct svc_function_unipro_management *management, @@ -149,7 +151,7 @@ static void svc_management(struct svc_function_unipro_management *management, return; } interface->device_id = management->link_up.device_id; - svc_set_route_send(interface, hd); + (void)svc_set_route_send(interface, hd); break; case SVC_MANAGEMENT_AP_DEVICE_ID: hd->device_id = management->ap_device_id.device_id; diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 4baa372..617d55c 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -275,7 +275,8 @@ void gb_gpio_controller_exit(struct gb_connection *connection); int gb_tty_init(void); void gb_tty_exit(void); - +int svc_set_route_send(struct gb_interface *interface, + struct greybus_host_device *hd); #endif /* __KERNEL__ */ #endif /* __LINUX_GREYBUS_H */ -- cgit v0.10.2 From c41b4f121240df46e5d901ad8aa9b9051b6c58e1 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 22 Oct 2014 02:04:32 -0500 Subject: greybus: only initialize interfaces when up Rather than bringing up all interfaces described in the manifest, wait until we get a link up message, and at that time go initialize the link. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 7ea329c..1a9112a 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -126,7 +126,7 @@ static void svc_management(struct svc_function_unipro_management *management, int payload_length, struct greybus_host_device *hd) { struct gb_module *module; - struct gb_interface *interface; + int ret; if (payload_length != sizeof(struct svc_function_unipro_management)) { dev_err(hd->parent, @@ -143,15 +143,14 @@ static void svc_management(struct svc_function_unipro_management *management, management->link_up.module_id); return; } - interface = gb_interface_find(module, - management->link_up.interface_id); - if (!interface) { - dev_err(hd->parent, "Interface ID %d not found\n", + ret = gb_module_interface_init(module, + management->link_up.interface_id, + management->link_up.device_id); + if (ret) + dev_err(hd->parent, "error %d initializing" + "module %hhu interface %hhu\n", + ret, management->link_up.module_id, management->link_up.interface_id); - return; - } - interface->device_id = management->link_up.device_id; - (void)svc_set_route_send(interface, hd); break; case SVC_MANAGEMENT_AP_DEVICE_ID: hd->device_id = management->ap_device_id.device_id; diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 480e12b..9f4ae1c 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -181,8 +181,6 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, if (retval) goto err_device; - gb_module_interfaces_init(gmod); - return; err_device: put_device(&gmod->dev); diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index 50139f4..bcb0ff0 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -118,15 +118,25 @@ struct gb_module *gb_module_find(struct greybus_host_device *hd, u8 module_id) return NULL; } -void gb_module_interfaces_init(struct gb_module *gmod) +int +gb_module_interface_init(struct gb_module *gmod, u8 interface_id, u8 device_id) { struct gb_interface *interface; - int ret = 0; + int ret; - list_for_each_entry(interface, &gmod->interfaces, links) { - ret = gb_interface_connections_init(interface); - if (ret) - dev_err(gmod->hd->parent, - "module interface init error %d\n", ret); + interface = gb_interface_find(gmod, interface_id); + if (!interface) { + dev_err(gmod->hd->parent, "module %hhu not found\n", + interface_id); + return -ENOENT; } + ret = gb_interface_connections_init(interface); + if (ret) { + dev_err(gmod->hd->parent, "module interface init error %d\n", + ret); + return ret; + } + interface->device_id = device_id; + + return svc_set_route_send(interface, gmod->hd); } diff --git a/drivers/staging/greybus/module.h b/drivers/staging/greybus/module.h index 82def46..74ac4fd 100644 --- a/drivers/staging/greybus/module.h +++ b/drivers/staging/greybus/module.h @@ -55,6 +55,7 @@ void gb_module_destroy(struct gb_module *module); struct gb_module *gb_module_find(struct greybus_host_device *hd, u8 module_id); -void gb_module_interfaces_init(struct gb_module *gmod); +int gb_module_interface_init(struct gb_module *gmod, u8 module_id, + u8 device_id); #endif /* __MODULE_H */ -- cgit v0.10.2 From 8a9bf8a99669e365bdc89d27bbc29bf0216472f6 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Wed, 22 Oct 2014 03:22:48 -0400 Subject: greybus: svc: remove the DDB function message support We removed the DDB function messages from the spec as they are not needed. Now remove it from the code. Signed-off-by: Matt Porter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 1a9112a..8156df0 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -201,19 +201,6 @@ static void svc_hotplug(struct svc_function_hotplug *hotplug, } } -static void svc_ddb(struct svc_function_ddb *ddb, - int payload_length, struct greybus_host_device *hd) -{ - /* - * Need to properly validate payload_length once we start - * to handle ddb messages, but for now, we don't, so no need to check - * anything. - */ - - /* What? An AP should not get this message */ - dev_err(hd->parent, "Got an svc DDB message???\n"); -} - static void svc_power(struct svc_function_power *power, int payload_length, struct greybus_host_device *hd) { @@ -315,9 +302,6 @@ static void ap_process_event(struct work_struct *work) case SVC_FUNCTION_HOTPLUG: svc_hotplug(&svc_msg->hotplug, payload_length, hd); break; - case SVC_FUNCTION_DDB: - svc_ddb(&svc_msg->ddb, payload_length, hd); - break; case SVC_FUNCTION_POWER: svc_power(&svc_msg->power, payload_length, hd); break; diff --git a/drivers/staging/greybus/svc_msg.h b/drivers/staging/greybus/svc_msg.h index 661cbae..d76b621 100644 --- a/drivers/staging/greybus/svc_msg.h +++ b/drivers/staging/greybus/svc_msg.h @@ -18,10 +18,9 @@ enum svc_function_id { SVC_FUNCTION_HANDSHAKE = 0x00, SVC_FUNCTION_UNIPRO_NETWORK_MANAGEMENT = 0x01, SVC_FUNCTION_HOTPLUG = 0x02, - SVC_FUNCTION_DDB = 0x03, - SVC_FUNCTION_POWER = 0x04, - SVC_FUNCTION_EPM = 0x05, - SVC_FUNCTION_SUSPEND = 0x06, + SVC_FUNCTION_POWER = 0x03, + SVC_FUNCTION_EPM = 0x04, + SVC_FUNCTION_SUSPEND = 0x05, }; enum svc_msg_type { @@ -92,37 +91,6 @@ struct svc_function_hotplug { __u8 data[0]; }; -enum svc_function_ddb_type { - SVC_DDB_GET = 0x00, - SVC_DDB_RESPONSE = 0x01, -}; - -/* XXX - * Will only the first interface block in a module be responsible - * for this? If a module has two interface blocks, will both supply - * the same information, or will it be partitioned? For now assume - * it's a per-module thing. - */ -struct svc_function_ddb_get { - __u8 module_id; - __u8 message_id; -}; - -struct svc_function_ddb_response { - __u8 module_id; - __u8 message_id; - __le16 descriptor_length; - __u8 ddb[0]; -}; - -struct svc_function_ddb { - __u8 ddb_type; /* enum svc_function_ddb_type */ - union { - struct svc_function_ddb_get ddb_get; - struct svc_function_ddb_response ddb_response; - }; -}; - enum svc_function_power_type { SVC_POWER_BATTERY_STATUS = 0x00, SVC_POWER_BATTERY_STATUS_REQUEST = 0x01, @@ -187,7 +155,6 @@ struct svc_msg { struct svc_function_handshake handshake; struct svc_function_unipro_management management; struct svc_function_hotplug hotplug; - struct svc_function_ddb ddb; struct svc_function_power power; struct svc_function_epm epm; struct svc_function_suspend suspend; -- cgit v0.10.2 From 65e50f95f18066442093d4c49528804a9bc8956f Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 22 Oct 2014 05:36:17 -0500 Subject: greybus: set route before sending packets The route for a connection needs to be set *before* we initialize the connection. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index bcb0ff0..b1ec090 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -130,13 +130,21 @@ gb_module_interface_init(struct gb_module *gmod, u8 interface_id, u8 device_id) interface_id); return -ENOENT; } + + ret = svc_set_route_send(interface, gmod->hd); + if (ret) { + dev_err(gmod->hd->parent, "failed to set route (%d)\n", ret); + return ret; + } + ret = gb_interface_connections_init(interface); if (ret) { dev_err(gmod->hd->parent, "module interface init error %d\n", ret); + /* XXX clear route */ return ret; } interface->device_id = device_id; - return svc_set_route_send(interface, gmod->hd); + return 0; } -- cgit v0.10.2 From 2d5e4fa9dc2e629b1ace5fa715f1d6bb2a71d61f Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 22 Oct 2014 05:36:18 -0500 Subject: greybus: update AP id service message Rename and renumber the values for the AP ID service message and related symbols to match the recently-updated spec. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 8156df0..24a15e9 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -136,6 +136,9 @@ static void svc_management(struct svc_function_unipro_management *management, } switch (management->management_packet_type) { + case SVC_MANAGEMENT_AP_ID: + hd->device_id = management->ap_id.device_id; + break; case SVC_MANAGEMENT_LINK_UP: module = gb_module_find(hd, management->link_up.module_id); if (!module) { @@ -152,9 +155,6 @@ static void svc_management(struct svc_function_unipro_management *management, ret, management->link_up.module_id, management->link_up.interface_id); break; - case SVC_MANAGEMENT_AP_DEVICE_ID: - hd->device_id = management->ap_device_id.device_id; - break; default: dev_err(hd->parent, "Unhandled UniPro management message\n"); } diff --git a/drivers/staging/greybus/svc_msg.h b/drivers/staging/greybus/svc_msg.h index d76b621..5b54512 100644 --- a/drivers/staging/greybus/svc_msg.h +++ b/drivers/staging/greybus/svc_msg.h @@ -56,22 +56,23 @@ struct svc_function_unipro_link_up { __u8 device_id; }; -struct svc_function_ap_device_id { +struct svc_function_ap_id { + __u8 module_id; __u8 device_id; }; enum svc_function_management_event { - SVC_MANAGEMENT_SET_ROUTE = 0x00, + SVC_MANAGEMENT_AP_ID = 0x00, SVC_MANAGEMENT_LINK_UP = 0x01, - SVC_MANAGEMENT_AP_DEVICE_ID = 0x02, + SVC_MANAGEMENT_SET_ROUTE = 0x02, }; struct svc_function_unipro_management { __u8 management_packet_type; /* enum svc_function_management_event */ union { - struct svc_function_unipro_set_route set_route; + struct svc_function_ap_id ap_id; struct svc_function_unipro_link_up link_up; - struct svc_function_ap_device_id ap_device_id; + struct svc_function_unipro_set_route set_route; }; }; -- cgit v0.10.2 From f0f61b90427b776b884821cde483528580f6d630 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 24 Oct 2014 17:34:46 +0800 Subject: greybus: hook up greybus to the driver model This patch hooks up modules, interfaces, and connections to the driver model. Now we have a correct hierarchy, and drivers can be correctly bound to the proper portions in the future. Devices are correctly reference counted and torn down in the proper order on removal of a module. Some basic sysfs attributes have been created for interfaces and connections. Module attributes are not working properly, but that will be fixed in future changes. This has been tested on Alex's machine, with multiple hotplug and unplug operations of a module working correctly. Signed-off-by: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index b1e933f..2d71679 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -111,6 +111,44 @@ static void connection_timeout(struct work_struct *work) printk("timeout!\n"); } +static ssize_t state_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct gb_connection *connection = to_gb_connection(dev); + + return sprintf(buf, "%d", connection->state); +} +static DEVICE_ATTR_RO(state); + +static ssize_t protocol_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct gb_connection *connection = to_gb_connection(dev); + + return sprintf(buf, "%d", connection->protocol); +} +static DEVICE_ATTR_RO(protocol); + +static struct attribute *connection_attrs[] = { + &dev_attr_state.attr, + &dev_attr_protocol.attr, + NULL, +}; + +ATTRIBUTE_GROUPS(connection); + +static void gb_connection_release(struct device *dev) +{ + struct gb_connection *connection = to_gb_connection(dev); + + kfree(connection); +} + +static struct device_type greybus_connection_type = { + .name = "greybus_connection", + .release = gb_connection_release, +}; + /* * Set up a Greybus connection, representing the bidirectional link * between a CPort on a (local) Greybus host device and a CPort on @@ -127,6 +165,7 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, { struct gb_connection *connection; struct greybus_host_device *hd; + int retval; connection = kzalloc(sizeof(*connection), GFP_KERNEL); if (!connection) @@ -145,6 +184,21 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, connection->protocol = protocol; connection->state = GB_CONNECTION_STATE_DISABLED; + connection->dev.parent = &interface->dev; + connection->dev.driver = NULL; + connection->dev.bus = &greybus_bus_type; + connection->dev.type = &greybus_connection_type; + connection->dev.groups = connection_groups; + device_initialize(&connection->dev); + dev_set_name(&connection->dev, "%s:%d", + dev_name(&interface->dev), cport_id); + + retval = device_add(&connection->dev); + if (retval) { + kfree(connection); + return NULL; + } + spin_lock_irq(&gb_connections_lock); _gb_hd_connection_insert(hd, connection); list_add_tail(&connection->interface_links, &interface->connections); @@ -182,9 +236,8 @@ void gb_connection_destroy(struct gb_connection *connection) spin_unlock_irq(&gb_connections_lock); gb_connection_hd_cport_id_free(connection); - /* kref_put(connection->interface); */ - /* kref_put(connection->hd); */ - kfree(connection); + + device_del(&connection->dev); } u16 gb_connection_operation_id(struct gb_connection *connection) diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index a16e52a..19dd91d 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -24,6 +24,7 @@ enum gb_connection_state { struct gb_connection { struct greybus_host_device *hd; struct gb_interface *interface; + struct device dev; u16 hd_cport_id; u16 interface_cport_id; @@ -39,6 +40,7 @@ struct gb_connection { void *private; }; +#define to_gb_connection(d) container_of(d, struct gb_connection, dev) struct gb_connection *gb_connection_create(struct gb_interface *interface, u16 cport_id, enum greybus_protocol protocol); diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 9f4ae1c..853bfd6 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -48,10 +48,14 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) /* struct gb_module *gmod = to_gb_module(dev); */ /* FIXME - add some uevents here... */ + + /* FIXME - be sure to check the type to know how to handle modules and + * interfaces differently */ + return 0; } -static struct bus_type greybus_bus_type = { +struct bus_type greybus_bus_type = { .name = "greybus", .match = greybus_module_match, .uevent = greybus_uevent, @@ -115,18 +119,6 @@ void greybus_deregister(struct greybus_driver *driver) EXPORT_SYMBOL_GPL(greybus_deregister); -static void greybus_module_release(struct device *dev) -{ - struct gb_module *gmod = to_gb_module(dev); - - gb_module_destroy(gmod); -} - -static struct device_type greybus_module_type = { - .name = "greybus_module", - .release = greybus_module_release, -}; - static const struct greybus_module_id fake_greybus_module_id = { GREYBUS_DEVICE(0x42, 0x42) }; @@ -142,7 +134,6 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, u8 *data, int size) { struct gb_module *gmod; - int retval; gmod = gb_module_create(hd, module_id); if (!gmod) { @@ -168,31 +159,10 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, * configuring the switch to allow them to communicate). */ - gmod->dev.parent = hd->parent; - gmod->dev.driver = NULL; - gmod->dev.bus = &greybus_bus_type; - gmod->dev.type = &greybus_module_type; - gmod->dev.groups = greybus_module_groups; - gmod->dev.dma_mask = hd->parent->dma_mask; - device_initialize(&gmod->dev); - dev_set_name(&gmod->dev, "%d", module_id); - - retval = device_add(&gmod->dev); - if (retval) - goto err_device; - return; -err_device: - put_device(&gmod->dev); -err_module: - greybus_module_release(&gmod->dev); -} - -static void gb_delete_module(struct gb_module *gmod) -{ - /* FIXME - tear down interfaces first */ - device_del(&gmod->dev); +err_module: + gb_module_destroy(gmod); } void gb_remove_module(struct greybus_host_device *hd, u8 module_id) @@ -207,7 +177,7 @@ void gb_remove_module(struct greybus_host_device *hd, u8 module_id) } if (found) - gb_delete_module(gmod); + gb_module_destroy(gmod); else dev_err(hd->parent, "module id %d remove error\n", module_id); } @@ -217,7 +187,7 @@ static void gb_remove_modules(struct greybus_host_device *hd) struct gb_module *gmod, *temp; list_for_each_entry_safe(gmod, temp, &hd->modules, links) { - gb_delete_module(gmod); + gb_module_destroy(gmod); } } @@ -256,6 +226,8 @@ EXPORT_SYMBOL_GPL(greybus_create_hd); void greybus_remove_hd(struct greybus_host_device *hd) { + /* Tear down all modules that happen to be associated with this host + * controller */ gb_remove_modules(hd); kref_put_mutex(&hd->kref, free_hd, &hd_mutex); } diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 617d55c..f287f3b 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -261,6 +261,7 @@ int gb_register_cport_complete(struct gb_module *gmod, void *context); void gb_deregister_cport_complete(u16 cport_id); +extern struct bus_type greybus_bus_type; extern const struct attribute_group *greybus_module_groups[]; int gb_i2c_device_init(struct gb_connection *connection); diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 0415db5..a7375a2 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -8,6 +8,35 @@ #include "greybus.h" +static ssize_t device_id_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct gb_interface *interface = to_gb_interface(dev); + + return sprintf(buf, "%d", interface->device_id); +} +static DEVICE_ATTR_RO(device_id); + +static struct attribute *interface_attrs[] = { + &dev_attr_device_id.attr, + NULL, +}; + +ATTRIBUTE_GROUPS(interface); + +static void gb_interface_release(struct device *dev) +{ + struct gb_interface *interface = to_gb_interface(dev); + + kfree(interface); +} + +static struct device_type greybus_interface_type = { + .name = "greybus_interface", + .release = gb_interface_release, +}; + + /* XXX This could be per-host device or per-module */ static DEFINE_SPINLOCK(gb_interfaces_lock); @@ -26,6 +55,7 @@ struct gb_interface * gb_interface_create(struct gb_module *gmod, u8 interface_id) { struct gb_interface *interface; + int retval; interface = kzalloc(sizeof(*interface), GFP_KERNEL); if (!interface) @@ -33,8 +63,25 @@ gb_interface_create(struct gb_module *gmod, u8 interface_id) interface->gmod = gmod; /* XXX refcount? */ interface->id = interface_id; + interface->device_id = 0xff; /* Invalid device id to start with */ INIT_LIST_HEAD(&interface->connections); + /* Build up the interface device structures and register it with the + * driver core */ + interface->dev.parent = &gmod->dev; + interface->dev.driver = NULL; + interface->dev.bus = &greybus_bus_type; + interface->dev.type = &greybus_interface_type; + interface->dev.groups = interface_groups; + device_initialize(&interface->dev); + dev_set_name(&interface->dev, "%d:%d", gmod->module_id, interface_id); + + retval = device_add(&interface->dev); + if (retval) { + kfree(interface); + return NULL; + } + spin_lock_irq(&gb_interfaces_lock); list_add_tail(&interface->links, &gmod->interfaces); spin_unlock_irq(&gb_interfaces_lock); @@ -45,19 +92,21 @@ gb_interface_create(struct gb_module *gmod, u8 interface_id) /* * Tear down a previously set up interface. */ -void gb_interface_destroy(struct gb_interface *interface) +void gb_interface_destroy(struct gb_module *gmod) { - if (WARN_ON(!interface)) + struct gb_interface *interface; + struct gb_interface *temp; + + if (WARN_ON(!gmod)) return; spin_lock_irq(&gb_interfaces_lock); - list_del(&interface->links); + list_for_each_entry_safe(interface, temp, &gmod->interfaces, links) { + list_del(&interface->links); + gb_interface_connections_exit(interface); + device_del(&interface->dev); + } spin_unlock_irq(&gb_interfaces_lock); - - gb_interface_connections_exit(interface); - - /* kref_put(gmod); */ - kfree(interface); } struct gb_interface *gb_interface_find(struct gb_module *module, @@ -65,9 +114,13 @@ struct gb_interface *gb_interface_find(struct gb_module *module, { struct gb_interface *interface; + spin_lock_irq(&gb_interfaces_lock); list_for_each_entry(interface, &module->interfaces, links) - if (interface->id == interface_id) + if (interface->id == interface_id) { + spin_unlock_irq(&gb_interfaces_lock); return interface; + } + spin_unlock_irq(&gb_interfaces_lock); return NULL; } diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 907b634..50b0317 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -12,6 +12,7 @@ #include struct gb_interface { + struct device dev; struct gb_module *gmod; u8 id; u8 device_id; @@ -19,9 +20,10 @@ struct gb_interface { struct list_head links; /* module->interfaces */ }; +#define to_gb_interface(d) container_of(d, struct gb_interface, dev) struct gb_interface *gb_interface_create(struct gb_module *gmod, u8 module_id); -void gb_interface_destroy(struct gb_interface *interface); +void gb_interface_destroy(struct gb_module *gmod); struct gb_interface *gb_interface_find(struct gb_module *gmod, u8 interface_id); diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index b1ec090..f9415c0 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -44,15 +44,18 @@ const struct greybus_module_id *gb_module_match_id(struct gb_module *gmod, return NULL; } -static void gb_module_interfaces_exit(struct gb_module *gmod) +static void greybus_module_release(struct device *dev) { - struct gb_interface *interface; - struct gb_interface *next; + struct gb_module *gmod = to_gb_module(dev); - list_for_each_entry_safe(interface, next, &gmod->interfaces, links) - gb_interface_destroy(interface); + kfree(gmod); } +static struct device_type greybus_module_type = { + .name = "greybus_module", + .release = greybus_module_release, +}; + /* * A Greybus module represents a user-replacable component on an Ara * phone. @@ -65,6 +68,7 @@ static void gb_module_interfaces_exit(struct gb_module *gmod) struct gb_module *gb_module_create(struct greybus_host_device *hd, u8 module_id) { struct gb_module *gmod; + int retval; gmod = kzalloc(sizeof(*gmod), GFP_KERNEL); if (!gmod) @@ -78,6 +82,21 @@ struct gb_module *gb_module_create(struct greybus_host_device *hd, u8 module_id) list_add_tail(&gmod->links, &hd->modules); spin_unlock_irq(&gb_modules_lock); + gmod->dev.parent = hd->parent; + gmod->dev.driver = NULL; + gmod->dev.bus = &greybus_bus_type; + gmod->dev.type = &greybus_module_type; + gmod->dev.groups = greybus_module_groups; + gmod->dev.dma_mask = hd->parent->dma_mask; + device_initialize(&gmod->dev); + dev_set_name(&gmod->dev, "%d", module_id); + + retval = device_add(&gmod->dev); + if (retval) { + put_device(&gmod->dev); + return NULL; + } + return gmod; } @@ -93,18 +112,15 @@ void gb_module_destroy(struct gb_module *gmod) list_del(&gmod->links); spin_unlock_irq(&gb_modules_lock); - gb_module_interfaces_exit(gmod); /* XXX Do something with gmod->gb_tty */ - put_device(&gmod->dev); - /* kfree(gmod->dev->name); */ + gb_interface_destroy(gmod); kfree(gmod->product_string); kfree(gmod->vendor_string); /* kref_put(module->hd); */ - - kfree(gmod); + device_del(&gmod->dev); } struct gb_module *gb_module_find(struct greybus_host_device *hd, u8 module_id) -- cgit v0.10.2 From c4a432d3db8b9fa0145048ac4a84bac54c7a9d73 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 24 Oct 2014 05:02:02 -0500 Subject: greybus: fix repeated input errors I screwed up the error handling in a patch the other day. If we get an error on an input URB we should not re-submit it. Signed-off-by: Alex Elder diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 12eb9b2..bd416b4 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -319,9 +319,10 @@ static void svc_in_callback(struct urb *urb) int retval; if (status) { - if (status != -EAGAIN) - dev_err(dev, "urb svc in error %d (dropped)\n", status); - goto exit; + if (status == -EAGAIN) + goto exit; + dev_err(dev, "urb svc in error %d (dropped)\n", status); + return; } /* We have a message, create a new message structure, add it to the @@ -346,10 +347,10 @@ static void cport_in_callback(struct urb *urb) u8 *data; if (status) { - if (status != -EAGAIN) - dev_err(dev, "urb cport in error %d (dropped)\n", - status); - goto exit; + if (status == -EAGAIN) + goto exit; + dev_err(dev, "urb cport in error %d (dropped)\n", status); + return; } /* The size has to be at least one, for the cport id */ -- cgit v0.10.2 From 44dd970be94a468c60e0745536f29115dd40d368 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 24 Oct 2014 17:54:02 +0800 Subject: greybus: module: enable all sysfs attributes We were thinking that module attributes were known at the time the device was created in the system, so we could query them to know if the sysfs file was present or not. Unfortunatly that's not the case, we create the device before we parse the values, so just always show the sysfs attributes. If there is no such attribute, the sysfs file will be empty (i.e. for the string attributes.) Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/sysfs.c b/drivers/staging/greybus/sysfs.c index 2777b8c..42d54eb 100644 --- a/drivers/staging/greybus/sysfs.c +++ b/drivers/staging/greybus/sysfs.c @@ -74,27 +74,8 @@ static struct attribute *module_attrs[] = { NULL, }; -static umode_t module_attrs_are_visible(struct kobject *kobj, - struct attribute *a, int n) -{ - struct gb_module *gmod = to_gb_module(kobj_to_dev(kobj)); - umode_t mode = a->mode; - - if (a == &dev_attr_module_vendor_string.attr && gmod->vendor_string) - return mode; - if (a == &dev_attr_module_product_string.attr && gmod->product_string) - return mode; - if (gmod->vendor || gmod->product || gmod->version) - return mode; - if (gmod->unique_id) - return mode; - - return 0; -} - static struct attribute_group module_attr_grp = { .attrs = module_attrs, - .is_visible = module_attrs_are_visible, }; const struct attribute_group *greybus_module_groups[] = { -- cgit v0.10.2 From 3e6d5f3a6103b20c70f4d75b90d2c798045cc7ef Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 24 Oct 2014 18:33:59 +0800 Subject: greybus: i2c: point to the proper parent device Use the connection, not the host controller, as the parent device of the i2c device. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index e1a0ed9..9ecfd79 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -496,8 +496,7 @@ int gb_i2c_device_init(struct gb_connection *connection) adapter->timeout = gb_i2c_dev->timeout_msec * HZ / 1000; adapter->retries = gb_i2c_dev->retries; - /* XXX I think this parent device is wrong, but it uses existing code */ - adapter->dev.parent = &connection->interface->gmod->dev; + adapter->dev.parent = &connection->dev; snprintf(adapter->name, sizeof(adapter->name), "Greybus i2c adapter"); i2c_set_adapdata(adapter, gb_i2c_dev); -- cgit v0.10.2 From 066799c18ff476642858fb0e4050c5c600c47e4c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 24 Oct 2014 18:46:15 +0800 Subject: greybus: module: don't create duplicate module ids If we somehow get a hotplug event for a module id that we already have created[1], don't try to create it again, or sysfs will complain loudly. Instead, abort the creation properly. [1] If, for example, you happened to run a script on a greybus emulator twice in a row... Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index f9415c0..54e8f9e 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -70,6 +70,13 @@ struct gb_module *gb_module_create(struct greybus_host_device *hd, u8 module_id) struct gb_module *gmod; int retval; + gmod = gb_module_find(hd, module_id); + if (gmod) { + dev_err(hd->parent, "Duplicate module id %d will not be created\n", + module_id); + return NULL; + } + gmod = kzalloc(sizeof(*gmod), GFP_KERNEL); if (!gmod) return NULL; -- cgit v0.10.2 From f9624ded90d0f4f6077b243d8526da671ba58d25 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 27 Oct 2014 12:30:15 +0800 Subject: greybus: operation: fix some sparse warnings One of which was "real". Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 5d23d19..c94e509 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -274,8 +274,14 @@ static void gb_operation_gbuf_complete(struct gbuf *gbuf) header = operation->response_payload; else header = NULL; - id = header ? (int)header->id : -1; - type = header ? (int)header->type : -1; + + if (header) { + id = le16_to_cpu(header->id); + type = header->type; + } else { + id = -1; + type = -1; + } gb_connection_err(operation->connection, "operation %d type %d gbuf error %d", @@ -292,8 +298,9 @@ static void gb_operation_gbuf_complete(struct gbuf *gbuf) * initialize it here (it'll be overwritten by the incoming * message). */ -struct gbuf *gb_operation_gbuf_create(struct gb_operation *operation, - u8 type, size_t size, bool data_out) +static struct gbuf *gb_operation_gbuf_create(struct gb_operation *operation, + u8 type, size_t size, + bool data_out) { struct gb_connection *connection = operation->connection; struct gb_operation_msg_hdr *header; -- cgit v0.10.2 From d4c8247b56a3c3f9c8c879189338d2fa13a281a0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 27 Oct 2014 12:33:47 +0800 Subject: greybus: gpio-gb: fix some endian sparse warnings that were real. Not like we are ever going to use a BE cpu, but it's good to be "correct"... Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index 32bf45f..069ee69 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -551,7 +551,7 @@ static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *gb_gpio_con return -ENOMEM; request = operation->request_payload; request->which = which; - request->usec = le16_to_cpu(debounce_usec); + request->usec = cpu_to_le16(debounce_usec); /* Synchronous operation--no callback */ ret = gb_operation_request_send(operation, NULL); @@ -566,9 +566,9 @@ static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *gb_gpio_con response->status); ret = -EIO; } else { - gb_gpio_controller->lines[which].debounce_usec = request->usec; -printk("%s: debounce of %u is now %hu usec\n", __func__, - which, gb_gpio_controller->lines[which].debounce_usec); + gb_gpio_controller->lines[which].debounce_usec = le16_to_cpu(request->usec); + printk("%s: debounce of %u is now %hu usec\n", __func__, which, + gb_gpio_controller->lines[which].debounce_usec); } out: gb_operation_destroy(operation); @@ -709,7 +709,7 @@ static void gb_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) return; /* XXX */ } -int gb_gpio_controller_setup(struct gb_gpio_controller *gb_gpio_controller) +static int gb_gpio_controller_setup(struct gb_gpio_controller *gb_gpio_controller) { u32 line_count; size_t size; -- cgit v0.10.2 From d81448849a6a919bdc6366b44a7664f817c94d84 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 27 Oct 2014 13:31:01 +0800 Subject: greybus: gbuf: implement gbuf_kill_gbuf() Hook up gbuf_kill_gbuf() by implementing yet-another-host-controller callback and a gbuf-specific pointer to hold the tracking data the hcd needs in order to be able to abort a transfer. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index bd416b4..a207294 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -224,6 +224,8 @@ static int submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) if (!urb) return -ENOMEM; + gbuf->hcd_data = urb; + usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, es1->cport_out_endpoint), buffer, gbuf->transfer_buffer_length + 1, @@ -232,12 +234,24 @@ static int submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) return retval; } +static int abort_gbuf(struct gbuf *gbuf) +{ + struct urb *urb = gbuf->hcd_data; + + if (!urb) + return -EINVAL; + + usb_kill_urb(urb); + return 0; +} + static struct greybus_host_driver es1_driver = { .hd_priv_size = sizeof(struct es1_ap_dev), .alloc_gbuf_data = alloc_gbuf_data, .free_gbuf_data = free_gbuf_data, .submit_svc = submit_svc, .submit_gbuf = submit_gbuf, + .abort_gbuf = abort_gbuf, }; /* Common function to report consistent warnings based on URB status */ @@ -387,6 +401,7 @@ static void cport_out_callback(struct urb *urb) /* Record whether the transfer was successful */ gbuf->status = check_urb_status(urb); + gbuf->hcd_data = NULL; /* * See if this was an urb in our pool, if so mark it "free", otherwise diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 9b435af..726a1f4 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -106,8 +106,12 @@ int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) int greybus_kill_gbuf(struct gbuf *gbuf) { - // FIXME - implement - return -ENOMEM; + struct greybus_host_device *hd = gbuf->connection->hd; + + if (gbuf->status != -EINPROGRESS) + return -EINVAL; + + return hd->driver->abort_gbuf(gbuf); } #define MAX_CPORTS 1024 diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index f287f3b..8b6ea05 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -134,6 +134,7 @@ struct gbuf { bool outbound; /* AP-relative data direction */ void *context; + void *hcd_data; /* for the HCD to track the gbuf */ gbuf_complete_t complete; }; @@ -169,6 +170,7 @@ struct greybus_host_driver { int (*submit_svc)(struct svc_msg *svc_msg, struct greybus_host_device *hd); int (*submit_gbuf)(struct gbuf *gbuf, gfp_t gfp_mask); + int (*abort_gbuf)(struct gbuf *gbuf); }; struct greybus_host_device { -- cgit v0.10.2 From 724b619dfbe1238eb8b9bd4916eeaf40b5640b28 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 27 Oct 2014 13:32:27 +0800 Subject: greybus: core: check for valid hcd callbacks When registering a host controller, verify that all of the needed callbacks are present, so we don't have to do the testing on any "hot" paths when we want to send real data. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder alloc_gbuf_data) || + (!driver->free_gbuf_data) || + (!driver->submit_svc) || + (!driver->submit_gbuf) || + (!driver->abort_gbuf)) { + pr_err("Must implement all greybus_host_driver callbacks!\n"); + return NULL; + } + hd = kzalloc(sizeof(*hd) + driver->hd_priv_size, GFP_KERNEL); if (!hd) return NULL; -- cgit v0.10.2 From 4afbba0703b2b2a2a9355e5d29a7a8ddcff92953 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 27 Oct 2014 14:01:06 +0800 Subject: greybus: core: make greybus_kill_gbuf not return a value We can't do anything if killing a gbuf fails, so just make this function "always" be successful. At the same time, make the host controller function also be called "kill_gbuf" to keep the terminology in sync. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 1436b3d..61fd690 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -216,7 +216,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver (!driver->free_gbuf_data) || (!driver->submit_svc) || (!driver->submit_gbuf) || - (!driver->abort_gbuf)) { + (!driver->kill_gbuf)) { pr_err("Must implement all greybus_host_driver callbacks!\n"); return NULL; } diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index a207294..b8784b1 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -234,15 +234,14 @@ static int submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) return retval; } -static int abort_gbuf(struct gbuf *gbuf) +static void kill_gbuf(struct gbuf *gbuf) { struct urb *urb = gbuf->hcd_data; if (!urb) - return -EINVAL; + return; usb_kill_urb(urb); - return 0; } static struct greybus_host_driver es1_driver = { @@ -251,7 +250,7 @@ static struct greybus_host_driver es1_driver = { .free_gbuf_data = free_gbuf_data, .submit_svc = submit_svc, .submit_gbuf = submit_gbuf, - .abort_gbuf = abort_gbuf, + .kill_gbuf = kill_gbuf, }; /* Common function to report consistent warnings based on URB status */ diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 726a1f4..4f591aa 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -104,14 +104,14 @@ int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) return hd->driver->submit_gbuf(gbuf, gfp_mask); } -int greybus_kill_gbuf(struct gbuf *gbuf) +void greybus_kill_gbuf(struct gbuf *gbuf) { struct greybus_host_device *hd = gbuf->connection->hd; if (gbuf->status != -EINPROGRESS) - return -EINVAL; + return; - return hd->driver->abort_gbuf(gbuf); + hd->driver->kill_gbuf(gbuf); } #define MAX_CPORTS 1024 diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 8b6ea05..1e3f31d 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -170,7 +170,7 @@ struct greybus_host_driver { int (*submit_svc)(struct svc_msg *svc_msg, struct greybus_host_device *hd); int (*submit_gbuf)(struct gbuf *gbuf, gfp_t gfp_mask); - int (*abort_gbuf)(struct gbuf *gbuf); + void (*kill_gbuf)(struct gbuf *gbuf); }; struct greybus_host_device { @@ -203,7 +203,7 @@ struct gbuf *greybus_get_gbuf(struct gbuf *gbuf); #define greybus_put_gbuf greybus_free_gbuf int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t mem_flags); -int greybus_kill_gbuf(struct gbuf *gbuf); +void greybus_kill_gbuf(struct gbuf *gbuf); struct greybus_driver { diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index c94e509..9b889b1 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -175,7 +175,7 @@ int gb_operation_wait(struct gb_operation *operation) ret = wait_for_completion_interruptible(&operation->completion); /* If interrupted, cancel the in-flight buffer */ if (ret < 0) - ret = greybus_kill_gbuf(operation->request); + greybus_kill_gbuf(operation->request); return ret; } @@ -519,17 +519,10 @@ void gb_connection_operation_recv(struct gb_connection *connection, */ void gb_operation_cancel(struct gb_operation *operation) { - int ret; - operation->canceled = true; - ret = greybus_kill_gbuf(operation->request); - if (ret) - pr_warn("error %d killing request gbuf\n", ret); - if (operation->response) { - ret = greybus_kill_gbuf(operation->response); - if (ret) - pr_warn("error %d killing response gbuf\n", ret); - } + greybus_kill_gbuf(operation->request); + if (operation->response) + greybus_kill_gbuf(operation->response); } int gb_operation_init(void) -- cgit v0.10.2 From 708971e43c29d103c22409cf66b6213033518da3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 27 Oct 2014 15:40:09 +0800 Subject: greybus: operation: make the timeout a per-operation thing, not per-connection An operation is what can timeout, not a connection itself. So notify the operation timedout, and the connection can then do with it as it sees fit, if necessary. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 2d71679..bbae163 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -102,15 +102,6 @@ static void gb_connection_hd_cport_id_free(struct gb_connection *connection) connection->hd_cport_id = CPORT_ID_BAD; } -static void connection_timeout(struct work_struct *work) -{ - struct gb_connection *connection; - - connection = - container_of(work, struct gb_connection, timeout_work.work); - printk("timeout!\n"); -} - static ssize_t state_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -207,7 +198,6 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, INIT_LIST_HEAD(&connection->operations); connection->pending = RB_ROOT; atomic_set(&connection->op_cycle, 0); - INIT_DELAYED_WORK(&connection->timeout_work, connection_timeout); return connection; } diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 19dd91d..17fde8f 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -36,7 +36,6 @@ struct gb_connection { struct list_head operations; struct rb_root pending; /* awaiting reponse */ atomic_t op_cycle; - struct delayed_work timeout_work; void *private; }; diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 9b889b1..736c2c1 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -19,7 +19,7 @@ */ #define GB_OPERATION_TYPE_RESPONSE 0x80 -#define CONNECTION_TIMEOUT_DEFAULT 1000 /* milliseconds */ +#define OPERATION_TIMEOUT_DEFAULT 1000 /* milliseconds */ /* * XXX This needs to be coordinated with host driver parameters @@ -105,29 +105,25 @@ static void gb_operation_insert(struct gb_operation *operation) rb_insert_color(node, root); spin_unlock_irq(&gb_operations_lock); - timeout = msecs_to_jiffies(CONNECTION_TIMEOUT_DEFAULT); + timeout = msecs_to_jiffies(OPERATION_TIMEOUT_DEFAULT); if (start_timer) - schedule_delayed_work(&connection->timeout_work, timeout); + schedule_delayed_work(&operation->timeout_work, timeout); else - mod_delayed_work(system_wq, &connection->timeout_work, timeout); + mod_delayed_work(system_wq, &operation->timeout_work, timeout); } static void gb_operation_remove(struct gb_operation *operation) { struct gb_connection *connection = operation->connection; - bool last_pending; + /* Shut down our timeout timer */ + cancel_delayed_work(&operation->timeout_work); + + /* Take us off of the list of pending operations */ spin_lock_irq(&gb_operations_lock); rb_erase(&operation->node, &connection->pending); - last_pending = RB_EMPTY_ROOT(&connection->pending); spin_unlock_irq(&gb_operations_lock); - /* - * If there are no more pending requests, we can stop the - * timeout timer. - */ - if (last_pending) - cancel_delayed_work(&connection->timeout_work); } static struct gb_operation * @@ -159,7 +155,7 @@ gb_operation_find(struct gb_connection *connection, u16 id) * any waiters. Otherwise we assume calling the completion is enough * and nobody else will be waiting. */ -void gb_operation_complete(struct gb_operation *operation) +static void gb_operation_complete(struct gb_operation *operation) { if (operation->callback) operation->callback(operation); @@ -248,6 +244,24 @@ static void gb_operation_recv_work(struct work_struct *recv_work) } /* + * Timeout call for the operation. + * + * If this fires, something went wrong, so mark the result as timed out, and + * run the completion handler, which (hopefully) should clean up the operation + * properly. + */ +static void operation_timeout(struct work_struct *work) +{ + struct gb_operation *operation; + + operation = container_of(work, struct gb_operation, timeout_work.work); + printk("timeout!\n"); + + operation->result = GB_OP_TIMEOUT; + gb_operation_complete(operation); +} + +/* * Buffer completion function. We get notified whenever any buffer * completes. For outbound messages, this tells us that the message * has been sent. For inbound messages, it means the data has @@ -376,6 +390,7 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, INIT_WORK(&operation->recv_work, gb_operation_recv_work); operation->callback = NULL; /* set at submit time */ init_completion(&operation->completion); + INIT_DELAYED_WORK(&operation->timeout_work, operation_timeout); spin_lock_irq(&gb_operations_lock); list_add_tail(&operation->links, &connection->operations); diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 1a8e6b9..965ad9c 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -18,6 +18,7 @@ enum gb_operation_status { GB_OP_INTERRUPTED = 3, GB_OP_RETRY = 4, GB_OP_PROTOCOL_BAD = 5, + GB_OP_TIMEOUT = 0xff, }; /* @@ -61,6 +62,7 @@ struct gb_operation { struct work_struct recv_work; gb_operation_callback callback; /* If asynchronous */ struct completion completion; /* Used if no callback */ + struct delayed_work timeout_work; struct list_head links; /* connection->operations */ struct rb_node node; /* connection->pending */ @@ -84,7 +86,6 @@ int gb_operation_response_send(struct gb_operation *operation); void gb_operation_cancel(struct gb_operation *operation); int gb_operation_wait(struct gb_operation *operation); -void gb_operation_complete(struct gb_operation *operation); int gb_operation_init(void); void gb_operation_exit(void); -- cgit v0.10.2 From 81d631cae83e32e3dcab0d20d9c387592e1fa230 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 27 Oct 2014 03:48:31 -0500 Subject: greybus: gpio: kill gpio_controller->gpio This field is never used (and not needed) so get rid of it. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index 069ee69..8781f81 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -29,7 +29,6 @@ struct gb_gpio_controller { struct gb_gpio_line *lines; struct gpio_chip chip; - struct gpio_chip *gpio; }; #define gpio_chip_to_gb_gpio_controller(chip) \ container_of(chip, struct gb_gpio_controller, chip) -- cgit v0.10.2 From 81f4e22732f0a29826168899d7e62839812d34dd Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 27 Oct 2014 03:48:32 -0500 Subject: greybus: embed the i2c adapter struct We don't need to dynamically allocate the i2c adapter structure, we can just embed it right in struct gb_i2c_device. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index 9ecfd79..e208011 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -22,7 +22,7 @@ struct gb_i2c_device { u16 timeout_msec; u8 retries; - struct i2c_adapter *adapter; + struct i2c_adapter adapter; }; /* Version of the Greybus i2c protocol we support */ @@ -469,7 +469,7 @@ static int gb_i2c_device_setup(struct gb_i2c_device *gb_i2c_dev) int gb_i2c_device_init(struct gb_connection *connection) { struct gb_i2c_device *gb_i2c_dev; - struct i2c_adapter *adapter = NULL; + struct i2c_adapter *adapter; int ret; gb_i2c_dev = kzalloc(sizeof(*gb_i2c_dev), GFP_KERNEL); @@ -482,13 +482,8 @@ int gb_i2c_device_init(struct gb_connection *connection) if (ret) goto out_err; - /* Looks good; allocate and set up our i2c adapter */ - adapter = kzalloc(sizeof(*adapter), GFP_KERNEL); - if (!adapter) { - ret = -ENOMEM; - goto out_err; - } - + /* Looks good; up our i2c adapter */ + adapter = &gb_i2c_dev->adapter; adapter->owner = THIS_MODULE; adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; adapter->algo = &gb_i2c_algorithm; @@ -504,12 +499,10 @@ int gb_i2c_device_init(struct gb_connection *connection) if (ret) goto out_err; - gb_i2c_dev->adapter = adapter; connection->private = gb_i2c_dev; return 0; out_err: - kfree(adapter); /* kref_put(gb_i2c_dev->connection) */ kfree(gb_i2c_dev); @@ -520,8 +513,7 @@ void gb_i2c_device_exit(struct gb_connection *connection) { struct gb_i2c_device *gb_i2c_dev = connection->private; - i2c_del_adapter(gb_i2c_dev->adapter); - kfree(gb_i2c_dev->adapter); + i2c_del_adapter(&gb_i2c_dev->adapter); /* kref_put(gb_i2c_dev->connection) */ kfree(gb_i2c_dev); } -- cgit v0.10.2 From aed0bc6e6856d467061e8de2f3adc713c3561628 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 27 Oct 2014 17:32:34 +0800 Subject: greybus: uart-gb: convert over to the connection interface Move the uart code over to use the "new" connection interface, instead of the "old" module interface. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 2d71679..2d3421f 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -285,9 +285,11 @@ int gb_connection_init(struct gb_connection *connection) case GREYBUS_PROTOCOL_BATTERY: ret = gb_battery_device_init(connection); break; + case GREYBUS_PROTOCOL_UART: + ret = gb_uart_device_init(connection); + break; case GREYBUS_PROTOCOL_CONTROL: case GREYBUS_PROTOCOL_AP: - case GREYBUS_PROTOCOL_UART: case GREYBUS_PROTOCOL_HID: case GREYBUS_PROTOCOL_LED: case GREYBUS_PROTOCOL_VENDOR: @@ -318,9 +320,11 @@ void gb_connection_exit(struct gb_connection *connection) case GREYBUS_PROTOCOL_BATTERY: gb_battery_device_exit(connection); break; + case GREYBUS_PROTOCOL_UART: + gb_uart_device_exit(connection); + break; case GREYBUS_PROTOCOL_CONTROL: case GREYBUS_PROTOCOL_AP: - case GREYBUS_PROTOCOL_UART: case GREYBUS_PROTOCOL_HID: case GREYBUS_PROTOCOL_VENDOR: default: diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 1e3f31d..c700b0d 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -275,6 +275,9 @@ void gb_battery_device_exit(struct gb_connection *connection); int gb_gpio_controller_init(struct gb_connection *connection); void gb_gpio_controller_exit(struct gb_connection *connection); +int gb_uart_device_init(struct gb_connection *connection); +void gb_uart_device_exit(struct gb_connection *connection); + int gb_tty_init(void); void gb_tty_exit(void); diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 301868c..d15a49b 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -35,7 +35,7 @@ struct gb_tty { struct tty_port port; - struct gb_module *gmod; + struct gb_connection *connection; u16 cport_id; unsigned int minor; unsigned char clocal; @@ -386,8 +386,7 @@ static const struct tty_operations gb_ops = { }; -int gb_tty_probe(struct gb_module *gmod, - const struct greybus_module_id *id) +int gb_uart_device_init(struct gb_connection *connection) { struct gb_tty *gb_tty; struct device *tty_dev; @@ -401,14 +400,14 @@ int gb_tty_probe(struct gb_module *gmod, minor = alloc_minor(gb_tty); if (minor < 0) { if (minor == -ENOSPC) { - dev_err(&gmod->dev, "no more free minor numbers\n"); + dev_err(&connection->dev, "no more free minor numbers\n"); return -ENODEV; } return minor; } gb_tty->minor = minor; - gb_tty->gmod = gmod; + gb_tty->connection = connection; spin_lock_init(&gb_tty->write_lock); spin_lock_init(&gb_tty->read_lock); init_waitqueue_head(&gb_tty->wioctl); @@ -416,10 +415,10 @@ int gb_tty_probe(struct gb_module *gmod, /* FIXME - allocate gb buffers */ - gmod->gb_tty = gb_tty; + connection->private = gb_tty; tty_dev = tty_port_register_device(&gb_tty->port, gb_tty_driver, minor, - &gmod->dev); + &connection->dev); if (IS_ERR(tty_dev)) { retval = PTR_ERR(tty_dev); goto error; @@ -427,14 +426,14 @@ int gb_tty_probe(struct gb_module *gmod, return 0; error: - gmod->gb_tty = NULL; + connection->private = NULL; release_minor(gb_tty); return retval; } -void gb_tty_disconnect(struct gb_module *gmod) +void gb_uart_device_exit(struct gb_connection *connection) { - struct gb_tty *gb_tty = gmod->gb_tty; + struct gb_tty *gb_tty = connection->private; struct tty_struct *tty; if (!gb_tty) @@ -444,7 +443,7 @@ void gb_tty_disconnect(struct gb_module *gmod) gb_tty->disconnected = true; wake_up_all(&gb_tty->wioctl); - gmod->gb_tty = NULL; + connection->private = NULL; mutex_unlock(&gb_tty->mutex); tty = tty_port_tty_get(&gb_tty->port); @@ -463,14 +462,6 @@ void gb_tty_disconnect(struct gb_module *gmod) kfree(gb_tty); } -#if 0 -static struct greybus_driver tty_gb_driver = { - .probe = gb_tty_probe, - .disconnect = gb_tty_disconnect, - .id_table = id_table, -}; -#endif - int __init gb_tty_init(void) { int retval = 0; -- cgit v0.10.2 From 4d98098942bda347cd9b5ce1b8f253e631ddf2a8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 27 Oct 2014 17:42:45 +0800 Subject: greybus: uart-gb: remove global init functions The uart-gb code needs to init the tty core before it can add devices. Previously we hard-coded this in the greybus core, move this to be "dynamic" and self-contained within the uart-gb.c file. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 61fd690..7c0cb62 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -282,17 +282,8 @@ static int __init gb_init(void) goto error_operation; } - retval = gb_tty_init(); - if (retval) { - pr_err("gb_tty_init failed\n"); - goto error_tty; - } - return 0; -error_tty: - gb_operation_exit(); - error_operation: gb_gbuf_exit(); @@ -310,7 +301,6 @@ error_bus: static void __exit gb_exit(void) { - gb_tty_exit(); gb_operation_exit(); gb_gbuf_exit(); gb_ap_exit(); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index c700b0d..deb34f1 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -278,9 +278,6 @@ void gb_gpio_controller_exit(struct gb_connection *connection); int gb_uart_device_init(struct gb_connection *connection); void gb_uart_device_exit(struct gb_connection *connection); -int gb_tty_init(void); -void gb_tty_exit(void); - int svc_set_route_send(struct gb_interface *interface, struct greybus_host_device *hd); diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index d15a49b..7c9229da 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -59,6 +59,10 @@ static const struct greybus_module_id id_table[] = { static struct tty_driver *gb_tty_driver; static DEFINE_IDR(tty_minors); static DEFINE_MUTEX(table_lock); +static atomic_t reference_count = ATOMIC_INIT(0); + +static int gb_tty_init(void); +static void gb_tty_exit(void); static struct gb_tty *get_gb_by_minor(unsigned minor) { @@ -393,6 +397,15 @@ int gb_uart_device_init(struct gb_connection *connection) int retval; int minor; + /* First time here, initialize the tty structures */ + if (atomic_inc_return(&reference_count) == 1) { + retval = gb_tty_init(); + if (retval) { + atomic_dec(&reference_count); + return retval; + } + } + gb_tty = kzalloc(sizeof(*gb_tty), GFP_KERNEL); if (!gb_tty) return -ENOMEM; @@ -460,9 +473,13 @@ void gb_uart_device_exit(struct gb_connection *connection) tty_port_put(&gb_tty->port); kfree(gb_tty); + + /* If last device is gone, tear down the tty structures */ + if (atomic_dec_return(&reference_count) == 0) + gb_tty_exit(); } -int __init gb_tty_init(void) +static int gb_tty_init(void) { int retval = 0; @@ -490,40 +507,20 @@ int __init gb_tty_init(void) goto fail_put_gb_tty; } -#if 0 - retval = greybus_register(&tty_gb_driver); - if (retval) { - pr_err("Can not register greybus driver.\n"); - goto fail_unregister_gb_tty; - } -#endif - return 0; -/* fail_unregister_gb_tty: */ - tty_unregister_driver(gb_tty_driver); fail_put_gb_tty: put_tty_driver(gb_tty_driver); fail_unregister_dev: return retval; } -void __exit gb_tty_exit(void) +static void gb_tty_exit(void) { int major = MAJOR(gb_tty_driver->major); int minor = gb_tty_driver->minor_start; -#if 0 - greybus_deregister(&tty_gb_driver); -#endif tty_unregister_driver(gb_tty_driver); put_tty_driver(gb_tty_driver); unregister_chrdev_region(MKDEV(major, minor), GB_NUM_MINORS); } - -#if 0 -module_init(gb_tty_init); -module_exit(gb_tty_exit); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Greg Kroah-Hartman "); -#endif -- cgit v0.10.2 From 6507cced6bf00c53108034a4954b9b8b73e6a216 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 27 Oct 2014 17:58:54 +0800 Subject: greybus: FIXME/XXX removals: We have proper reference counting now Now that we have proper reference counting for modules, interfaces, and connections, no need to worry about grabbing a pointer to your "parent" structure, all is good. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index 592b68d..185fa2c 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -369,7 +369,7 @@ int gb_battery_device_init(struct gb_connection *connection) if (!gb) return -ENOMEM; - gb->connection = connection; // FIXME refcount! + gb->connection = connection; connection->private = gb; /* Check the version */ diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 2d3421f..722bee4 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -179,7 +179,7 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, return NULL; } - connection->interface = interface; /* XXX refcount? */ + connection->interface = interface; connection->interface_cport_id = cport_id; connection->protocol = protocol; connection->state = GB_CONNECTION_STATE_DISABLED; diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index a7375a2..163cdc4 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -61,7 +61,7 @@ gb_interface_create(struct gb_module *gmod, u8 interface_id) if (!interface) return NULL; - interface->gmod = gmod; /* XXX refcount? */ + interface->gmod = gmod; interface->id = interface_id; interface->device_id = 0xff; /* Invalid device id to start with */ INIT_LIST_HEAD(&interface->connections); diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 9b889b1..df3a502 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -349,7 +349,7 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, operation = kmem_cache_zalloc(gb_operation_cache, gfp_flags); if (!operation) return NULL; - operation->connection = connection; /* XXX refcount? */ + operation->connection = connection; operation->request = gb_operation_gbuf_create(operation, type, request_size, -- cgit v0.10.2 From eec5883f5179367821ab5102be897231dc64fa62 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 27 Oct 2014 18:00:13 +0800 Subject: greybus: module: remove unneeded XXX comment about module id values We do properly check for duplicate module ids, as fixed in 008d85d90ae1ab31f1f7b80f245f6ee2eb5aed49 "module: don't create duplicate module ids", so remove the XXX marker. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index 54e8f9e..f65aea6 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -82,7 +82,7 @@ struct gb_module *gb_module_create(struct greybus_host_device *hd, u8 module_id) return NULL; gmod->hd = hd; /* XXX refcount? */ - gmod->module_id = module_id; /* XXX check for dups */ + gmod->module_id = module_id; INIT_LIST_HEAD(&gmod->interfaces); spin_lock_irq(&gb_modules_lock); -- cgit v0.10.2 From f348964c266c6b2db80af8b7a75a6f9ef566f1c3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Oct 2014 09:27:50 +0800 Subject: greybus: kernel_ver.h: add ATTRIBUTE_GROUPS() macro for older kernels This was added in 3.11, and we need it for 3.10 Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index e0fea18..e4cda5c 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -48,4 +48,19 @@ static inline void gb_gpiochip_remove(struct gpio_chip *chip) } #endif +/* + * ATTRIBUTE_GROUPS showed up in 3.11-rc2, but we need to build on 3.10, so add + * it here. + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0) +#define ATTRIBUTE_GROUPS(name) \ +static const struct attribute_group name##_group = { \ + .attrs = name##_attrs, \ +}; \ +static const struct attribute_group *name##_groups[] = { \ + &name##_group, \ + NULL, \ +} +#endif + #endif /* __GREYBUS_KERNEL_VER_H */ -- cgit v0.10.2 From 3689f9744a029ee9b7b38fb177249d2812ffa676 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 27 Oct 2014 06:04:30 -0500 Subject: greybus: begin abstracting connection operations This is part 1 of abstracting the connection operations into a set of methods. This will avoid some big switch statements, but more importantly this will be needed for supporting multiple versions of each protocol. For now only two methods are defined. The init method is used to set up the device (or whatever the CPort represents) and the exit method tears it down. There may need to be additional operations added in the future, and once versioning is used we might stash the version number in this structure as well. The next patch adds dynamic registratration of these protocol handlers, and will do away with the switch statement now found in gb_connection_init(). Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index 185fa2c..74698c1 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -359,7 +359,7 @@ static enum power_supply_property battery_props[] = { POWER_SUPPLY_PROP_VOLTAGE_NOW, }; -int gb_battery_device_init(struct gb_connection *connection) +static int gb_battery_connection_init(struct gb_connection *connection) { struct gb_battery *gb; struct power_supply *b; @@ -397,7 +397,7 @@ int gb_battery_device_init(struct gb_connection *connection) return 0; } -void gb_battery_device_exit(struct gb_connection *connection) +static void gb_battery_connection_exit(struct gb_connection *connection) { struct gb_battery *gb = connection->private; @@ -405,6 +405,11 @@ void gb_battery_device_exit(struct gb_connection *connection) kfree(gb); } +struct gb_connection_handler gb_battery_connection_handler = { + .connection_init = gb_battery_connection_init, + .connection_exit = gb_battery_connection_exit, +}; + void gb_battery_disconnect(struct gb_module *gmod) { #if 0 diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 722bee4..1a849ce 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -277,16 +277,16 @@ int gb_connection_init(struct gb_connection *connection) connection->state = GB_CONNECTION_STATE_ENABLED; switch (connection->protocol) { case GREYBUS_PROTOCOL_I2C: - ret = gb_i2c_device_init(connection); + connection->handler = &gb_i2c_connection_handler; break; case GREYBUS_PROTOCOL_GPIO: - ret = gb_gpio_controller_init(connection); + connection->handler = &gb_gpio_connection_handler; break; case GREYBUS_PROTOCOL_BATTERY: - ret = gb_battery_device_init(connection); + connection->handler = &gb_battery_connection_handler; break; case GREYBUS_PROTOCOL_UART: - ret = gb_uart_device_init(connection); + connection->handler = &gb_uart_connection_handler; break; case GREYBUS_PROTOCOL_CONTROL: case GREYBUS_PROTOCOL_AP: @@ -308,28 +308,10 @@ int gb_connection_init(struct gb_connection *connection) void gb_connection_exit(struct gb_connection *connection) { - connection->state = GB_CONNECTION_STATE_DESTROYING; - - switch (connection->protocol) { - case GREYBUS_PROTOCOL_I2C: - gb_i2c_device_exit(connection); - break; - case GREYBUS_PROTOCOL_GPIO: - gb_gpio_controller_exit(connection); - break; - case GREYBUS_PROTOCOL_BATTERY: - gb_battery_device_exit(connection); - break; - case GREYBUS_PROTOCOL_UART: - gb_uart_device_exit(connection); - break; - case GREYBUS_PROTOCOL_CONTROL: - case GREYBUS_PROTOCOL_AP: - case GREYBUS_PROTOCOL_HID: - case GREYBUS_PROTOCOL_VENDOR: - default: - gb_connection_err(connection, "unimplemented protocol %u", - (u32)connection->protocol); - break; + if (!connection->handler) { + gb_connection_err(connection, "uninitialized connection"); + return; } + connection->state = GB_CONNECTION_STATE_DESTROYING; + connection->handler->connection_exit(connection); } diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 19dd91d..4492d2f 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -21,6 +21,15 @@ enum gb_connection_state { GB_CONNECTION_STATE_DESTROYING = 4, }; +struct gb_connection; +typedef int (*gb_connection_init_t)(struct gb_connection *); +typedef void (*gb_connection_exit_t)(struct gb_connection *); + +struct gb_connection_handler { + gb_connection_init_t connection_init; + gb_connection_exit_t connection_exit; +}; + struct gb_connection { struct greybus_host_device *hd; struct gb_interface *interface; @@ -38,6 +47,8 @@ struct gb_connection { atomic_t op_cycle; struct delayed_work timeout_work; + struct gb_connection_handler *handler; + void *private; }; #define to_gb_connection(d) container_of(d, struct gb_connection, dev) diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index 8781f81..6ba1f63 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -732,7 +732,7 @@ static int gb_gpio_controller_setup(struct gb_gpio_controller *gb_gpio_controlle return ret; } -int gb_gpio_controller_init(struct gb_connection *connection) +static int gb_gpio_connection_init(struct gb_connection *connection) { struct gb_gpio_controller *gb_gpio_controller; struct gpio_chip *gpio; @@ -780,7 +780,7 @@ out_err: return ret; } -void gb_gpio_controller_exit(struct gb_connection *connection) +static void gb_gpio_connection_exit(struct gb_connection *connection) { struct gb_gpio_controller *gb_gpio_controller = connection->private; @@ -792,6 +792,11 @@ void gb_gpio_controller_exit(struct gb_connection *connection) kfree(gb_gpio_controller); } +struct gb_connection_handler gb_gpio_connection_handler = { + .connection_init = gb_gpio_connection_init, + .connection_exit = gb_gpio_connection_exit, +}; + #if 0 MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Greybus GPIO driver"); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index deb34f1..f907e0f 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -266,14 +266,10 @@ void gb_deregister_cport_complete(u16 cport_id); extern struct bus_type greybus_bus_type; extern const struct attribute_group *greybus_module_groups[]; -int gb_i2c_device_init(struct gb_connection *connection); -void gb_i2c_device_exit(struct gb_connection *connection); - -int gb_battery_device_init(struct gb_connection *connection); -void gb_battery_device_exit(struct gb_connection *connection); - -int gb_gpio_controller_init(struct gb_connection *connection); -void gb_gpio_controller_exit(struct gb_connection *connection); +extern struct gb_connection_handler gb_i2c_connection_handler; +extern struct gb_connection_handler gb_gpio_connection_handler; +extern struct gb_connection_handler gb_battery_connection_handler; +extern struct gb_connection_handler gb_uart_connection_handler; int gb_uart_device_init(struct gb_connection *connection); void gb_uart_device_exit(struct gb_connection *connection); diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index e208011..5d3e2f2 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -466,7 +466,7 @@ static int gb_i2c_device_setup(struct gb_i2c_device *gb_i2c_dev) return gb_i2c_timeout_operation(gb_i2c_dev, GB_I2C_TIMEOUT_DEFAULT); } -int gb_i2c_device_init(struct gb_connection *connection) +static int gb_i2c_connection_init(struct gb_connection *connection) { struct gb_i2c_device *gb_i2c_dev; struct i2c_adapter *adapter; @@ -509,7 +509,7 @@ out_err: return ret; } -void gb_i2c_device_exit(struct gb_connection *connection) +static void gb_i2c_connection_exit(struct gb_connection *connection) { struct gb_i2c_device *gb_i2c_dev = connection->private; @@ -518,6 +518,11 @@ void gb_i2c_device_exit(struct gb_connection *connection) kfree(gb_i2c_dev); } +struct gb_connection_handler gb_i2c_connection_handler = { + .connection_init = gb_i2c_connection_init, + .connection_exit = gb_i2c_connection_exit, +}; + #if 0 module_greybus_driver(i2c_gb_driver); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 7c9229da..370a78f 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -390,7 +390,7 @@ static const struct tty_operations gb_ops = { }; -int gb_uart_device_init(struct gb_connection *connection) +int gb_uart_connection_init(struct gb_connection *connection) { struct gb_tty *gb_tty; struct device *tty_dev; @@ -444,7 +444,7 @@ error: return retval; } -void gb_uart_device_exit(struct gb_connection *connection) +void gb_uart_connection_exit(struct gb_connection *connection) { struct gb_tty *gb_tty = connection->private; struct tty_struct *tty; @@ -524,3 +524,8 @@ static void gb_tty_exit(void) put_tty_driver(gb_tty_driver); unregister_chrdev_region(MKDEV(major, minor), GB_NUM_MINORS); } + +struct gb_connection_handler gb_uart_connection_handler = { + .connection_init = gb_uart_connection_init, + .connection_exit = gb_uart_connection_exit, +}; -- cgit v0.10.2 From 059b093616313683a3d6259646d21f64d2756838 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Oct 2014 09:49:33 +0800 Subject: greybus: uart-gb: mark some functions static Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 370a78f..f88a301 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -390,7 +390,7 @@ static const struct tty_operations gb_ops = { }; -int gb_uart_connection_init(struct gb_connection *connection) +static int gb_uart_connection_init(struct gb_connection *connection) { struct gb_tty *gb_tty; struct device *tty_dev; @@ -444,7 +444,7 @@ error: return retval; } -void gb_uart_connection_exit(struct gb_connection *connection) +static void gb_uart_connection_exit(struct gb_connection *connection) { struct gb_tty *gb_tty = connection->private; struct tty_struct *tty; -- cgit v0.10.2 From 5e8e8ff6d0bf804e1f85154f21bcca699e2f8aa9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Oct 2014 09:50:56 +0800 Subject: greybus: battery-gb: remove some #if 0 code We aren't going to have individual modules for the gb protocols, so just remove this useless code, it was throwing up warnings in sparse. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index 74698c1..b7d8e2c 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -409,30 +409,3 @@ struct gb_connection_handler gb_battery_connection_handler = { .connection_init = gb_battery_connection_init, .connection_exit = gb_battery_connection_exit, }; - -void gb_battery_disconnect(struct gb_module *gmod) -{ -#if 0 - struct gb_battery *gb; - - gb = gmod->gb_battery; - if (!gb) - return; - - power_supply_unregister(&gb->bat); - - kfree(gb); -#endif -} - -#if 0 -static struct greybus_driver battery_gb_driver = { - .probe = gb_battery_probe, - .disconnect = gb_battery_disconnect, - .id_table = id_table, -}; - -module_greybus_driver(battery_gb_driver); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Greg Kroah-Hartman "); -#endif -- cgit v0.10.2 From a2f4763f4829c5efb9e38b9d25385d464e0e277a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Oct 2014 10:17:09 +0800 Subject: greybus: sdio-gb: convert to the connection interface. No one is using sdio yet, but convert to the connection interface to remove the last user of the "old" module interface. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index f907e0f..3a8d8f1 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -151,7 +151,6 @@ struct gbuf { struct gb_i2c_device; struct gb_gpio_device; -struct gb_sdio_host; struct gb_tty; struct gb_usb_device; struct gb_battery; @@ -270,6 +269,7 @@ extern struct gb_connection_handler gb_i2c_connection_handler; extern struct gb_connection_handler gb_gpio_connection_handler; extern struct gb_connection_handler gb_battery_connection_handler; extern struct gb_connection_handler gb_uart_connection_handler; +extern struct gb_connection_handler gb_sdio_connection_handler; int gb_uart_device_init(struct gb_connection *connection); void gb_uart_device_exit(struct gb_connection *connection); diff --git a/drivers/staging/greybus/sdio-gb.c b/drivers/staging/greybus/sdio-gb.c index 19c7c4a..e9c3117 100644 --- a/drivers/staging/greybus/sdio-gb.c +++ b/drivers/staging/greybus/sdio-gb.c @@ -13,6 +13,7 @@ #include "greybus.h" struct gb_sdio_host { + struct gb_connection *connection; struct mmc_host *mmc; struct mmc_request *mrq; // FIXME - some lock? @@ -45,13 +46,12 @@ static const struct mmc_host_ops gb_sd_ops = { .get_ro = gb_sd_get_ro, }; -int gb_sdio_probe(struct gb_module *gmod, - const struct greybus_module_id *id) +static int gb_sdio_connection_init(struct gb_connection *connection) { struct mmc_host *mmc; struct gb_sdio_host *host; - mmc = mmc_alloc_host(sizeof(struct gb_sdio_host), &gmod->dev); + mmc = mmc_alloc_host(sizeof(struct gb_sdio_host), &connection->dev); if (!mmc) return -ENOMEM; @@ -60,36 +60,29 @@ int gb_sdio_probe(struct gb_module *gmod, mmc->ops = &gb_sd_ops; // FIXME - set up size limits we can handle. + // FIXME - register the host controller. - // gmod->gb_sdio_host = host; + host->connection = connection; + connection->private = host; return 0; } -void gb_sdio_disconnect(struct gb_module *gmod) +static void gb_sdio_connection_exit(struct gb_connection *connection) { -#if 0 struct mmc_host *mmc; struct gb_sdio_host *host; - host = gmod->gb_sdio_host; + host = connection->private; if (!host) return; mmc = host->mmc; mmc_remove_host(mmc); mmc_free_host(mmc); -#endif + connection->private = NULL; } -#if 0 -static struct greybus_driver sd_gb_driver = { - .probe = gb_sdio_probe, - .disconnect = gb_sdio_disconnect, - .id_table = id_table, +struct gb_connection_handler gb_sdio_connection_handler = { + .connection_init = gb_sdio_connection_init, + .connection_exit = gb_sdio_connection_exit, }; - -module_greybus_driver(sd_gb_driver); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Greybus SD/MMC Host driver"); -MODULE_AUTHOR("Greg Kroah-Hartman "); -#endif -- cgit v0.10.2 From c7a90cb5990313b61cfe5cba859ce34d537075b6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Oct 2014 17:09:35 +0800 Subject: greybus: #if 0 cleanups Remove some #if 0 chunks for the old-style greybus driver macros Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index 6ba1f63..df7dbae 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -796,9 +796,3 @@ struct gb_connection_handler gb_gpio_connection_handler = { .connection_init = gb_gpio_connection_init, .connection_exit = gb_gpio_connection_exit, }; - -#if 0 -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Greybus GPIO driver"); -MODULE_AUTHOR("Greg Kroah-Hartman "); -#endif diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index 5d3e2f2..b26464a 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -522,9 +522,3 @@ struct gb_connection_handler gb_i2c_connection_handler = { .connection_init = gb_i2c_connection_init, .connection_exit = gb_i2c_connection_exit, }; - -#if 0 -module_greybus_driver(i2c_gb_driver); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Greg Kroah-Hartman "); -#endif -- cgit v0.10.2 From cea54c12f7badb18f2adbf718b8451f5d14a654d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Oct 2014 17:49:59 +0800 Subject: greybus: Remove id_table usages We aren't using an id_table for "drivers" at this moment, as the whole driver model interaction is under heavy rework. So remove these for now to keep things easier to understand for future patches. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index b7d8e2c..28c0d0b 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -92,11 +92,6 @@ struct gb_battery_voltage_request { }; -static const struct greybus_module_id id_table[] = { - { GREYBUS_DEVICE(0x42, 0x42) }, /* make shit up */ - { }, /* terminating NULL entry */ -}; - static int battery_operation(struct gb_battery *gb, int type, void *response, int response_size) { diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 7c0cb62..252d131 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -119,11 +119,6 @@ void greybus_deregister(struct greybus_driver *driver) EXPORT_SYMBOL_GPL(greybus_deregister); -static const struct greybus_module_id fake_greybus_module_id = { - GREYBUS_DEVICE(0x42, 0x42) -}; - - /** * gb_add_module * diff --git a/drivers/staging/greybus/sdio-gb.c b/drivers/staging/greybus/sdio-gb.c index e9c3117..30caba8 100644 --- a/drivers/staging/greybus/sdio-gb.c +++ b/drivers/staging/greybus/sdio-gb.c @@ -19,11 +19,6 @@ struct gb_sdio_host { // FIXME - some lock? }; -static const struct greybus_module_id id_table[] = { - { GREYBUS_DEVICE(0x43, 0x43) }, /* make shit up */ - { }, /* terminating NULL entry */ -}; - static void gb_sd_request(struct mmc_host *mmc, struct mmc_request *mrq) { // FIXME - do something here... diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index f88a301..b52d9e1 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -51,11 +51,6 @@ struct gb_tty { struct mutex mutex; }; -static const struct greybus_module_id id_table[] = { - { GREYBUS_DEVICE(0x45, 0x45) }, /* make shit up */ - { }, /* terminating NULL entry */ -}; - static struct tty_driver *gb_tty_driver; static DEFINE_IDR(tty_minors); static DEFINE_MUTEX(table_lock); -- cgit v0.10.2 From f9ab34c2bf1ed120802ae64ae3f0c4ba6b46c6b3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Oct 2014 18:20:24 +0800 Subject: greybus: es1-ap-usb: document the lack of callback for the outgoing bulk urbs We don't need a callback for bulk out urbs to do anything except put the urb back in the pool. Document why we do this and what is involved. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index b8784b1..2fccece 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -418,6 +418,31 @@ static void cport_out_callback(struct urb *urb) /* If urb is not NULL, then we need to free this urb */ usb_free_urb(urb); + + /* + * Yes, you are right, we aren't telling anyone that the urb finished. + * "That's crazy! How does this all even work?" you might be saying. + * The "magic" is the idea that greybus works on the "operation" level, + * not the "send a buffer" level. All operations are "round-trip" with + * a response from the device that the operation finished, or it will + * time out. Because of that, we don't care that this urb finished, or + * failed, or did anything else, as higher levels of the protocol stack + * will handle completions and timeouts and the rest. + * + * This protocol is "needed" due to some hardware restrictions on the + * current generation of Unipro controllers. Think about it for a + * minute, this is a USB driver, talking to a Unipro bridge, impediance + * mismatch is huge, yet the Unipro controller are even more + * underpowered than this little USB controller. We rely on the round + * trip to keep stalls in the Unipro controllers from happening so that + * we can keep data flowing properly, no matter how slow it might be. + * + * Once again, a wonderful bus protocol cut down in its prime by a naive + * controller chip. We dream of the day we have a "real" HCD for + * Unipro. Until then, we suck it up and make the hardware work, as + * that's the job of the firmware and kernel. + * + */ } /* -- cgit v0.10.2 From 53cbb00933a5181cf57ae799a6fc8cbecba973a4 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Tue, 28 Oct 2014 10:08:12 -0400 Subject: greybus: module: set device_id when initializing an interface gb_module_interface_init() looks for the interface corresponding to the supplied interface_id, but fails to configure the device_id that goes with it. This results in a set route command being set with an uninitialized and bogus value. Fix it. Signed-off-by: Matt Porter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index f65aea6..4c6e084 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -153,6 +153,7 @@ gb_module_interface_init(struct gb_module *gmod, u8 interface_id, u8 device_id) interface_id); return -ENOENT; } + interface->device_id = device_id; ret = svc_set_route_send(interface, gmod->hd); if (ret) { -- cgit v0.10.2 From 755a21a9bfeef4bd8145d0896a1b6f668f6d99f3 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Tue, 28 Oct 2014 10:08:13 -0400 Subject: greybus: connection: call connection_init hook after setting the handler In gb_connection_init() we set the connection_handler for each supported protocol, but we never call the connection_init hook after doing so. This results in a failure being returned so fix it by calling the connection_init hook to get a good return and the associated driver initialized. Signed-off-by: Matt Porter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index f76855c..69ea3a7 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -290,6 +290,8 @@ int gb_connection_init(struct gb_connection *connection) break; } + ret = connection->handler->connection_init(connection); + if (ret) connection->state = GB_CONNECTION_STATE_ERROR; -- cgit v0.10.2 From b29699602df46a8dffe01bedf2a601c4e2699a96 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 28 Oct 2014 19:35:58 -0500 Subject: greybus: drop the cport id on error In gb_connection_create(), if an error occurs adding a connection's device, the cport id assigned to the AP end of the connection is not getting freed. Fix that. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 69ea3a7..3fee647 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -186,6 +186,8 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, retval = device_add(&connection->dev); if (retval) { + gb_connection_hd_cport_id_free(connection); + /* kref_put(connection->hd); */ kfree(connection); return NULL; } -- cgit v0.10.2 From 7fba0079ad9a5b1b851947ad3c5b90093b2fc415 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 28 Oct 2014 19:35:59 -0500 Subject: greybus: use protocol_id for numeric values Switch to using "protocol_id" to refer to a byte-sized numeric protocol number. A "protocol" will represent a protocol structure (created in the next patch). Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 3fee647..6d5085d 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -111,18 +111,18 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR_RO(state); -static ssize_t protocol_show(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t +protocol_id_show(struct device *dev, struct device_attribute *attr, char *buf) { struct gb_connection *connection = to_gb_connection(dev); - return sprintf(buf, "%d", connection->protocol); + return sprintf(buf, "%d", connection->protocol_id); } -static DEVICE_ATTR_RO(protocol); +static DEVICE_ATTR_RO(protocol_id); static struct attribute *connection_attrs[] = { &dev_attr_state.attr, - &dev_attr_protocol.attr, + &dev_attr_protocol_id.attr, NULL, }; @@ -152,7 +152,7 @@ static struct device_type greybus_connection_type = { * pointer otherwise. */ struct gb_connection *gb_connection_create(struct gb_interface *interface, - u16 cport_id, enum greybus_protocol protocol) + u16 cport_id, u8 protocol_id) { struct gb_connection *connection; struct greybus_host_device *hd; @@ -172,7 +172,7 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, connection->interface = interface; connection->interface_cport_id = cport_id; - connection->protocol = protocol; + connection->protocol_id = protocol_id; connection->state = GB_CONNECTION_STATE_DISABLED; connection->dev.parent = &interface->dev; @@ -267,7 +267,7 @@ int gb_connection_init(struct gb_connection *connection) /* Need to enable the connection to initialize it */ connection->state = GB_CONNECTION_STATE_ENABLED; - switch (connection->protocol) { + switch (connection->protocol_id) { case GREYBUS_PROTOCOL_I2C: connection->handler = &gb_i2c_connection_handler; break; @@ -286,8 +286,8 @@ int gb_connection_init(struct gb_connection *connection) case GREYBUS_PROTOCOL_LED: case GREYBUS_PROTOCOL_VENDOR: default: - gb_connection_err(connection, "unimplemented protocol %u", - (u32)connection->protocol); + gb_connection_err(connection, "unimplemented protocol %hhu", + connection->protocol_id); ret = -ENXIO; break; } diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 88a9398..830abe7 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -39,7 +39,8 @@ struct gb_connection { struct rb_node hd_node; struct list_head interface_links; - enum greybus_protocol protocol; + u8 protocol_id; + enum gb_connection_state state; struct list_head operations; @@ -53,7 +54,7 @@ struct gb_connection { #define to_gb_connection(d) container_of(d, struct gb_connection, dev) struct gb_connection *gb_connection_create(struct gb_interface *interface, - u16 cport_id, enum greybus_protocol protocol); + u16 cport_id, u8 protocol_id); void gb_connection_destroy(struct gb_connection *connection); int gb_connection_init(struct gb_connection *connection); diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index c18ee11..c6988ce 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -98,13 +98,13 @@ struct greybus_descriptor_interface { /* * A CPort descriptor indicates the id of the interface within the * module it's associated with, along with the CPort id used to - * address the CPort. The protocol defines the format of messages + * address the CPort. The protocol id defines the format of messages * exchanged using the CPort. */ struct greybus_descriptor_cport { __u8 interface; __le16 id; - __u8 protocol; /* enum greybus_protocol */ + __u8 protocol_id; /* enum greybus_protocol */ }; /* diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 09fcde9..2e22f54 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -181,7 +181,7 @@ static u32 gb_manifest_parse_cports(struct gb_interface *interface) while (true) { struct manifest_desc *descriptor; struct greybus_descriptor_cport *desc_cport; - enum greybus_protocol protocol; + u8 protocol_id; u16 cport_id; bool found; @@ -200,9 +200,9 @@ static u32 gb_manifest_parse_cports(struct gb_interface *interface) break; /* Found one. Set up its function structure */ - protocol = (enum greybus_protocol)desc_cport->protocol; + protocol_id = desc_cport->protocol_id; cport_id = le16_to_cpu(desc_cport->id); - if (!gb_connection_create(interface, cport_id, protocol)) + if (!gb_connection_create(interface, cport_id, protocol_id)) return 0; /* Error */ count++; diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index dc35425..0388242 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -200,21 +200,21 @@ static gb_operation_recv_handler gb_operation_recv_handlers[] = { static void gb_operation_request_handle(struct gb_operation *operation) { - u8 protocol = operation->connection->protocol; + u8 protocol_id = operation->connection->protocol_id; /* Subtract one from array size to stay within u8 range */ - if (protocol <= (u8)(ARRAY_SIZE(gb_operation_recv_handlers) - 1)) { + if (protocol_id <= (u8)(ARRAY_SIZE(gb_operation_recv_handlers) - 1)) { gb_operation_recv_handler handler; - handler = gb_operation_recv_handlers[protocol]; + handler = gb_operation_recv_handlers[protocol_id]; if (handler) { handler(operation); /* Handle the request */ return; } } - gb_connection_err(operation->connection, "unrecognized protocol %u\n", - (unsigned int)protocol); + gb_connection_err(operation->connection, + "unrecognized protocol id %hhu\n", protocol_id); operation->result = GB_OP_PROTOCOL_BAD; gb_operation_complete(operation); } -- cgit v0.10.2 From 4ccb6b7abb8ee4ff6fc28468ffe893caa730ea13 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 28 Oct 2014 19:36:00 -0500 Subject: greybus: introduce protocol abstraction Define a protocol structure that will allow protocols to be registered dynamically. For now we just introduce a bookkeeping data structure. Upcoming patches will move protocol-related methods into the protocol structure, and will start registering protocol handlers dynamically. A list of connections using a given protocol is maintained so we can tell when a protocol is no longer in use. This may not be necessary (we could use a kref instead) but it may turn out to be a good way to clean things up. The interface is gb_protocol_get() and gb_protocol_put() for a connection, allowing the protocol to be looked up and the connection structure to be inserted into its list. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 42a3944..39874de 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -7,6 +7,7 @@ greybus-y := core.o \ module.o \ interface.o \ connection.o \ + protocol.o \ operation.o \ i2c-gb.o \ gpio-gb.o \ diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 6d5085d..dac47b3 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -116,7 +116,7 @@ protocol_id_show(struct device *dev, struct device_attribute *attr, char *buf) { struct gb_connection *connection = to_gb_connection(dev); - return sprintf(buf, "%d", connection->protocol_id); + return sprintf(buf, "%d", connection->protocol->id); } static DEVICE_ATTR_RO(protocol_id); @@ -162,17 +162,23 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, if (!connection) return NULL; + INIT_LIST_HEAD(&connection->protocol_links); + if (!gb_protocol_get(connection, protocol_id)) { + kfree(connection); + return NULL; + } + hd = interface->gmod->hd; connection->hd = hd; /* XXX refcount? */ if (!gb_connection_hd_cport_id_alloc(connection)) { /* kref_put(connection->hd); */ + gb_protocol_put(connection); kfree(connection); return NULL; } connection->interface = interface; connection->interface_cport_id = cport_id; - connection->protocol_id = protocol_id; connection->state = GB_CONNECTION_STATE_DISABLED; connection->dev.parent = &interface->dev; @@ -188,6 +194,7 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, if (retval) { gb_connection_hd_cport_id_free(connection); /* kref_put(connection->hd); */ + gb_protocol_put(connection); kfree(connection); return NULL; } @@ -228,6 +235,8 @@ void gb_connection_destroy(struct gb_connection *connection) spin_unlock_irq(&gb_connections_lock); gb_connection_hd_cport_id_free(connection); + /* kref_put(connection->hd); */ + gb_protocol_put(connection); device_del(&connection->dev); } @@ -267,7 +276,7 @@ int gb_connection_init(struct gb_connection *connection) /* Need to enable the connection to initialize it */ connection->state = GB_CONNECTION_STATE_ENABLED; - switch (connection->protocol_id) { + switch (connection->protocol->id) { case GREYBUS_PROTOCOL_I2C: connection->handler = &gb_i2c_connection_handler; break; @@ -287,7 +296,7 @@ int gb_connection_init(struct gb_connection *connection) case GREYBUS_PROTOCOL_VENDOR: default: gb_connection_err(connection, "unimplemented protocol %hhu", - connection->protocol_id); + connection->protocol->id); ret = -ENXIO; break; } diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 830abe7..8056993 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -39,7 +39,9 @@ struct gb_connection { struct rb_node hd_node; struct list_head interface_links; - u8 protocol_id; + + struct gb_protocol *protocol; + struct list_head protocol_links; enum gb_connection_state state; diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 3a8d8f1..f6c90e0 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -26,6 +26,7 @@ #include "module.h" #include "interface.h" #include "connection.h" +#include "protocol.h" #include "operation.h" diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 0388242..cc278bc 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -200,7 +200,7 @@ static gb_operation_recv_handler gb_operation_recv_handlers[] = { static void gb_operation_request_handle(struct gb_operation *operation) { - u8 protocol_id = operation->connection->protocol_id; + u8 protocol_id = operation->connection->protocol->id; /* Subtract one from array size to stay within u8 range */ if (protocol_id <= (u8)(ARRAY_SIZE(gb_operation_recv_handlers) - 1)) { diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c new file mode 100644 index 0000000..52944ec --- /dev/null +++ b/drivers/staging/greybus/protocol.c @@ -0,0 +1,122 @@ +/* + * Greybus protocol handling + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ + +#include "greybus.h" + +/* Global list of registered protocols */ +static DEFINE_SPINLOCK(gb_protocols_lock); +static LIST_HEAD(gb_protocols); + +/* Caller must hold gb_protocols_lock */ +struct gb_protocol *_gb_protocol_find(u8 id) +{ + struct gb_protocol *protocol; + + list_for_each_entry(protocol, &gb_protocols, links) + if (protocol->id == id) + return protocol; + return NULL; +} + +/* This is basically for debug */ +static struct gb_protocol *gb_protocol_find(u8 id) +{ + struct gb_protocol *protocol; + + spin_lock_irq(&gb_protocols_lock); + protocol = _gb_protocol_find(id); + spin_unlock_irq(&gb_protocols_lock); + + return protocol; +} + +/* Returns true if protocol was succesfully registered, false otherwise */ +bool gb_protocol_register(u8 id) +{ + struct gb_protocol *protocol; + struct gb_protocol *existing; + + /* Initialize it speculatively */ + protocol = kzalloc(sizeof(*protocol), GFP_KERNEL); + if (!protocol) + return false; + protocol->id = id; + INIT_LIST_HEAD(&protocol->connections); + + spin_lock_irq(&gb_protocols_lock); + existing = _gb_protocol_find(id); + if (!existing) + list_add(&protocol->links, &gb_protocols); + spin_unlock_irq(&gb_protocols_lock); + + if (existing) { + kfree(protocol); + protocol = NULL; + } + + return protocol != NULL; +} + +/* Returns true if successful, false otherwise */ +bool gb_protocol_deregister(struct gb_protocol *protocol) +{ + spin_lock_irq(&gb_protocols_lock); + if (list_empty(&protocol->connections)) + list_del(&protocol->links); + else + protocol = NULL; /* Protocol is still in use */ + spin_unlock_irq(&gb_protocols_lock); + kfree(protocol); + + return protocol != NULL; +} + +/* Returns true if successful, false otherwise */ +bool gb_protocol_get(struct gb_connection *connection, u8 id) +{ + struct gb_protocol *protocol; + + /* Sanity */ + if (!list_empty(&connection->protocol_links) || + !connection->protocol->id) { + gb_connection_err(connection, + "connection already has protocol"); + return false; + } + + spin_lock_irq(&gb_protocols_lock); + protocol = _gb_protocol_find(id); + if (protocol) + list_add(&connection->protocol_links, &protocol->connections); + spin_unlock_irq(&gb_protocols_lock); + connection->protocol = protocol; + + return protocol != NULL; +} + +void gb_protocol_put(struct gb_connection *connection) +{ + struct gb_protocol *protocol = connection->protocol; + + /* Sanity checks */ + if (list_empty(&connection->protocol_links)) { + gb_connection_err(connection, + "connection protocol not recorded"); + return; + } + if (!protocol || gb_protocol_find(protocol->id) != protocol) { + gb_connection_err(connection, + "connection has undefined protocol"); + return; + } + + spin_lock_irq(&gb_protocols_lock); + list_del(&connection->protocol_links); + connection->protocol = NULL; + spin_unlock_irq(&gb_protocols_lock); +} diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h new file mode 100644 index 0000000..d244e9d --- /dev/null +++ b/drivers/staging/greybus/protocol.h @@ -0,0 +1,26 @@ +/* + * Greybus protocol handling + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ + +#ifndef __PROTOCOL_H +#define __PROTOCOL_H + +#include "greybus.h" + +struct gb_protocol { + u8 id; + struct list_head connections; /* protocol users */ + struct list_head links; /* global list */ +}; + +bool gb_protocol_register(u8 id); +bool gb_protocol_deregister(struct gb_protocol *protocol); + +bool gb_protocol_get(struct gb_connection *connection, u8 id); +void gb_protocol_put(struct gb_connection *connection); + +#endif /* __PROTOCOL_H */ -- cgit v0.10.2 From 4b640bb1357a3eed16a04b23167dc3de4294dcd9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 29 Oct 2014 09:57:08 +0800 Subject: greybus: connection: fix up error patch logic in gb_connection_create() Once you have called device_initialize() you have to call put_device() on the structure to clean it up on an error path, otherwise you will leak memory. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index dac47b3..c4b6505 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -169,9 +169,8 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, } hd = interface->gmod->hd; - connection->hd = hd; /* XXX refcount? */ + connection->hd = hd; if (!gb_connection_hd_cport_id_alloc(connection)) { - /* kref_put(connection->hd); */ gb_protocol_put(connection); kfree(connection); return NULL; @@ -193,9 +192,8 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, retval = device_add(&connection->dev); if (retval) { gb_connection_hd_cport_id_free(connection); - /* kref_put(connection->hd); */ gb_protocol_put(connection); - kfree(connection); + put_device(&connection->dev); return NULL; } -- cgit v0.10.2 From 2dcf6871dd19a8129929203776c57cddbb07bcc3 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Thu, 30 Oct 2014 15:28:18 -0700 Subject: greybus: build: Add -fno-pic for 32bit arm as well In order for 32bit arm devices using the android toolchain to load the greybus module, I need to add -fno-pic in the build arguments as well. Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Android.mk b/drivers/staging/greybus/Android.mk index 773129b..924099b 100644 --- a/drivers/staging/greybus/Android.mk +++ b/drivers/staging/greybus/Android.mk @@ -18,6 +18,7 @@ ifneq ($(ANDROID_64),) FLAGARG := EXTRA_CFLAGS+=-fno-pic else ARCHARG := ARCH=arm + FLAGARG := EXTRA_CFLAGS+=-fno-pic endif ARGS := $(KDIRARG) $(ARCHARG) $(FLAGARG) -- cgit v0.10.2 From 96fd8c2bfdda4b6a2223f235ebdd35e4d391d075 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 5 Nov 2014 16:03:08 -0600 Subject: greybus: fix a bug in gb_operation_gbuf_complete() The gbuf completion routine was using the request payload pointers (which point at the area *past* the message header) rather than the header. This didn't matter much for now, it was only used in the error path. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index cc278bc..9cb9c9d 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -283,9 +283,9 @@ static void gb_operation_gbuf_complete(struct gbuf *gbuf) int type; if (gbuf == operation->request) - header = operation->request_payload; + header = operation->request->transfer_buffer; else if (gbuf == operation->response) - header = operation->response_payload; + header = operation->response->transfer_buffer; else header = NULL; -- cgit v0.10.2 From 00ace9739042a867bbbaaceefb6ad88571358ea5 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 5 Nov 2014 16:03:09 -0600 Subject: greybus: drop a redundant assignment Get rid of a duplicate assignment of an interface's device id. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index 4c6e084..3a64a2b 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -168,7 +168,6 @@ gb_module_interface_init(struct gb_module *gmod, u8 interface_id, u8 device_id) /* XXX clear route */ return ret; } - interface->device_id = device_id; return 0; } -- cgit v0.10.2 From 0570afcf24930e4c4078a637d93c61fa448fbd10 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 5 Nov 2014 16:03:10 -0600 Subject: greybus: make _gb_protocol_find() static This function should have private scope. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index 52944ec..e0bcd4b 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -13,7 +13,7 @@ static DEFINE_SPINLOCK(gb_protocols_lock); static LIST_HEAD(gb_protocols); /* Caller must hold gb_protocols_lock */ -struct gb_protocol *_gb_protocol_find(u8 id) +static struct gb_protocol *_gb_protocol_find(u8 id) { struct gb_protocol *protocol; -- cgit v0.10.2 From 545a697512a0b9c08ae4f152b7dd146f02dcbb92 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 5 Nov 2014 16:03:11 -0600 Subject: greybus: control printing message There's a message that gets printed in gb_manifest_parse() if excess descriptors are found in the manifest. This should only be printed if the parse was successful. If it was not successful it's not really very helpful. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 2e22f54..5634639 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -391,7 +391,7 @@ bool gb_manifest_parse(struct gb_module *gmod, void *data, size_t size) * We really should have no remaining descriptors, but we * don't know what newer format manifests might leave. */ - if (!list_empty(&manifest_descs)) + if (result && !list_empty(&manifest_descs)) pr_info("excess descriptors in module manifest\n"); out: release_manifest_descriptors(); -- cgit v0.10.2 From 6b09938a48d4fd86596c75b19aea3286da2e4d9f Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 5 Nov 2014 16:03:12 -0600 Subject: greybus: improve some error messages Add a few error messages to help explain the reason for failures. Add a missing space in a message in svc_management(). Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 24a15e9..a8cd7e7 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -150,7 +150,7 @@ static void svc_management(struct svc_function_unipro_management *management, management->link_up.interface_id, management->link_up.device_id); if (ret) - dev_err(hd->parent, "error %d initializing" + dev_err(hd->parent, "error %d initializing " "module %hhu interface %hhu\n", ret, management->link_up.module_id, management->link_up.interface_id); diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index c4b6505..1a8f53e 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -164,6 +164,7 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, INIT_LIST_HEAD(&connection->protocol_links); if (!gb_protocol_get(connection, protocol_id)) { + pr_err("protocol 0x%02hhx not found\n", protocol_id); kfree(connection); return NULL; } @@ -191,6 +192,8 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, retval = device_add(&connection->dev); if (retval) { + pr_err("failed to add connection device for cport 0x%04hx\n", + cport_id); gb_connection_hd_cport_id_free(connection); gb_protocol_put(connection); put_device(&connection->dev); diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 163cdc4..eb63f63 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -78,6 +78,8 @@ gb_interface_create(struct gb_module *gmod, u8 interface_id) retval = device_add(&interface->dev); if (retval) { + pr_err("failed to add interface device for id 0x%02hhx\n", + interface_id); kfree(interface); return NULL; } diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index 3a64a2b..9cf98cd 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -100,6 +100,8 @@ struct gb_module *gb_module_create(struct greybus_host_device *hd, u8 module_id) retval = device_add(&gmod->dev); if (retval) { + pr_err("failed to add module device for id 0x%02hhx\n", + module_id); put_device(&gmod->dev); return NULL; } -- cgit v0.10.2 From 6ae7fa4520c9a3e316996320ad6d6439f08bb63c Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 5 Nov 2014 16:12:50 -0600 Subject: greybus: identify protocol by id *and* version Right now we only look up a protocol based on its protocol id. Add support for maintaining a major and minor version as well, and use them when looking up a protocol. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 1a8f53e..703c286 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -157,13 +157,16 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, struct gb_connection *connection; struct greybus_host_device *hd; int retval; + u8 major = 0; + u8 minor = 1; connection = kzalloc(sizeof(*connection), GFP_KERNEL); if (!connection) return NULL; INIT_LIST_HEAD(&connection->protocol_links); - if (!gb_protocol_get(connection, protocol_id)) { + /* XXX Will have to establish connections to get version */ + if (!gb_protocol_get(connection, protocol_id, major, minor)) { pr_err("protocol 0x%02hhx not found\n", protocol_id); kfree(connection); return NULL; diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index e0bcd4b..704b180 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -13,30 +13,31 @@ static DEFINE_SPINLOCK(gb_protocols_lock); static LIST_HEAD(gb_protocols); /* Caller must hold gb_protocols_lock */ -static struct gb_protocol *_gb_protocol_find(u8 id) +static struct gb_protocol *_gb_protocol_find(u8 id, u8 major, u8 minor) { struct gb_protocol *protocol; list_for_each_entry(protocol, &gb_protocols, links) - if (protocol->id == id) + if (protocol->id == id && protocol->major == major + && protocol->minor == minor) return protocol; return NULL; } /* This is basically for debug */ -static struct gb_protocol *gb_protocol_find(u8 id) +static struct gb_protocol *gb_protocol_find(u8 id, u8 major, u8 minor) { struct gb_protocol *protocol; spin_lock_irq(&gb_protocols_lock); - protocol = _gb_protocol_find(id); + protocol = _gb_protocol_find(id, major, minor); spin_unlock_irq(&gb_protocols_lock); return protocol; } /* Returns true if protocol was succesfully registered, false otherwise */ -bool gb_protocol_register(u8 id) +bool gb_protocol_register(u8 id, u8 major, u8 minor) { struct gb_protocol *protocol; struct gb_protocol *existing; @@ -46,10 +47,12 @@ bool gb_protocol_register(u8 id) if (!protocol) return false; protocol->id = id; + protocol->major = major; + protocol->minor = minor; INIT_LIST_HEAD(&protocol->connections); spin_lock_irq(&gb_protocols_lock); - existing = _gb_protocol_find(id); + existing = _gb_protocol_find(id, major, minor); if (!existing) list_add(&protocol->links, &gb_protocols); spin_unlock_irq(&gb_protocols_lock); @@ -77,7 +80,8 @@ bool gb_protocol_deregister(struct gb_protocol *protocol) } /* Returns true if successful, false otherwise */ -bool gb_protocol_get(struct gb_connection *connection, u8 id) +bool +gb_protocol_get(struct gb_connection *connection, u8 id, u8 major, u8 minor) { struct gb_protocol *protocol; @@ -90,7 +94,7 @@ bool gb_protocol_get(struct gb_connection *connection, u8 id) } spin_lock_irq(&gb_protocols_lock); - protocol = _gb_protocol_find(id); + protocol = _gb_protocol_find(id, major, minor); if (protocol) list_add(&connection->protocol_links, &protocol->connections); spin_unlock_irq(&gb_protocols_lock); @@ -102,6 +106,8 @@ bool gb_protocol_get(struct gb_connection *connection, u8 id) void gb_protocol_put(struct gb_connection *connection) { struct gb_protocol *protocol = connection->protocol; + u8 major = protocol->major; + u8 minor = protocol->minor; /* Sanity checks */ if (list_empty(&connection->protocol_links)) { @@ -109,9 +115,12 @@ void gb_protocol_put(struct gb_connection *connection) "connection protocol not recorded"); return; } - if (!protocol || gb_protocol_find(protocol->id) != protocol) { - gb_connection_err(connection, - "connection has undefined protocol"); + if (!protocol) { + gb_connection_err(connection, "connection has no protocol"); + return; + } + if (gb_protocol_find(protocol->id, major, minor) != protocol) { + gb_connection_err(connection, "connection protocol not found"); return; } diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index d244e9d..d53f67d 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -11,16 +11,25 @@ #include "greybus.h" +/* + * Protocols having the same id but different major and/or minor + * version numbers are treated as distinct protocols. If it makes + * sense someday we could group protocols having the same id. + */ struct gb_protocol { - u8 id; - struct list_head connections; /* protocol users */ - struct list_head links; /* global list */ + u8 id; + u8 major; + u8 minor; + + struct list_head connections; /* protocol users */ + struct list_head links; /* global list */ }; -bool gb_protocol_register(u8 id); +bool gb_protocol_register(u8 id, u8 major, u8 minor); bool gb_protocol_deregister(struct gb_protocol *protocol); -bool gb_protocol_get(struct gb_connection *connection, u8 id); +bool gb_protocol_get(struct gb_connection *connection, u8 id, + u8 major, u8 minor); void gb_protocol_put(struct gb_connection *connection); #endif /* __PROTOCOL_H */ -- cgit v0.10.2 From 0e44765743c06664773475cd07684a70a29a6816 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 5 Nov 2014 16:12:51 -0600 Subject: greybus: count rather than list protocol users We don't really need a list of protocol users, we can just keep track of how many there are. Get rid of the list and use a count instead. Also, have gb_protocol_get() return the protocol rather than assigning a passed-in connection pointer's protocol. Make a comparable change to the gb_protocol_put() interface. Get rid of gb_protocol_find() (the version that locks), because it is no longer needed. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 703c286..e3000f7e 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -164,9 +164,9 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, if (!connection) return NULL; - INIT_LIST_HEAD(&connection->protocol_links); /* XXX Will have to establish connections to get version */ - if (!gb_protocol_get(connection, protocol_id, major, minor)) { + connection->protocol = gb_protocol_get(protocol_id, major, minor); + if (!connection->protocol) { pr_err("protocol 0x%02hhx not found\n", protocol_id); kfree(connection); return NULL; @@ -175,7 +175,7 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, hd = interface->gmod->hd; connection->hd = hd; if (!gb_connection_hd_cport_id_alloc(connection)) { - gb_protocol_put(connection); + gb_protocol_put(connection->protocol); kfree(connection); return NULL; } @@ -198,7 +198,7 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, pr_err("failed to add connection device for cport 0x%04hx\n", cport_id); gb_connection_hd_cport_id_free(connection); - gb_protocol_put(connection); + gb_protocol_put(connection->protocol); put_device(&connection->dev); return NULL; } @@ -239,8 +239,7 @@ void gb_connection_destroy(struct gb_connection *connection) spin_unlock_irq(&gb_connections_lock); gb_connection_hd_cport_id_free(connection); - /* kref_put(connection->hd); */ - gb_protocol_put(connection); + gb_protocol_put(connection->protocol); device_del(&connection->dev); } diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 8056993..ea54334 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -41,7 +41,6 @@ struct gb_connection { struct list_head interface_links; struct gb_protocol *protocol; - struct list_head protocol_links; enum gb_connection_state state; diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index 704b180..347d52c 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -24,18 +24,6 @@ static struct gb_protocol *_gb_protocol_find(u8 id, u8 major, u8 minor) return NULL; } -/* This is basically for debug */ -static struct gb_protocol *gb_protocol_find(u8 id, u8 major, u8 minor) -{ - struct gb_protocol *protocol; - - spin_lock_irq(&gb_protocols_lock); - protocol = _gb_protocol_find(id, major, minor); - spin_unlock_irq(&gb_protocols_lock); - - return protocol; -} - /* Returns true if protocol was succesfully registered, false otherwise */ bool gb_protocol_register(u8 id, u8 major, u8 minor) { @@ -49,7 +37,6 @@ bool gb_protocol_register(u8 id, u8 major, u8 minor) protocol->id = id; protocol->major = major; protocol->minor = minor; - INIT_LIST_HEAD(&protocol->connections); spin_lock_irq(&gb_protocols_lock); existing = _gb_protocol_find(id, major, minor); @@ -68,64 +55,64 @@ bool gb_protocol_register(u8 id, u8 major, u8 minor) /* Returns true if successful, false otherwise */ bool gb_protocol_deregister(struct gb_protocol *protocol) { + u8 protocol_count; + spin_lock_irq(&gb_protocols_lock); - if (list_empty(&protocol->connections)) - list_del(&protocol->links); - else - protocol = NULL; /* Protocol is still in use */ + protocol = _gb_protocol_find(protocol->id, protocol->major, + protocol->minor); + if (protocol) { + protocol_count = protocol->count; + if (!protocol_count) + list_del(&protocol->links); + } spin_unlock_irq(&gb_protocols_lock); kfree(protocol); - return protocol != NULL; + return protocol && !protocol_count; } -/* Returns true if successful, false otherwise */ -bool -gb_protocol_get(struct gb_connection *connection, u8 id, u8 major, u8 minor) +/* Returns the requested protocol if available, or a null pointer */ +struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor) { struct gb_protocol *protocol; - - /* Sanity */ - if (!list_empty(&connection->protocol_links) || - !connection->protocol->id) { - gb_connection_err(connection, - "connection already has protocol"); - return false; - } + u8 protocol_count; spin_lock_irq(&gb_protocols_lock); protocol = _gb_protocol_find(id, major, minor); - if (protocol) - list_add(&connection->protocol_links, &protocol->connections); + if (protocol) { + protocol_count = protocol->count; + if (protocol_count != U8_MAX) + protocol->count++; + } spin_unlock_irq(&gb_protocols_lock); - connection->protocol = protocol; - return protocol != NULL; + if (protocol) + WARN_ON(protocol_count == U8_MAX); + else + pr_err("protocol id %hhu version %hhu.%hhu not found\n", + id, major, minor); + + return protocol; } -void gb_protocol_put(struct gb_connection *connection) +void gb_protocol_put(struct gb_protocol *protocol) { - struct gb_protocol *protocol = connection->protocol; u8 major = protocol->major; u8 minor = protocol->minor; - - /* Sanity checks */ - if (list_empty(&connection->protocol_links)) { - gb_connection_err(connection, - "connection protocol not recorded"); - return; - } - if (!protocol) { - gb_connection_err(connection, "connection has no protocol"); - return; - } - if (gb_protocol_find(protocol->id, major, minor) != protocol) { - gb_connection_err(connection, "connection protocol not found"); - return; - } + u8 protocol_count; spin_lock_irq(&gb_protocols_lock); - list_del(&connection->protocol_links); - connection->protocol = NULL; + protocol = _gb_protocol_find(protocol->id, protocol->major, + protocol->minor); + if (protocol) { + protocol_count = protocol->count; + if (protocol_count) + protocol->count--; + } spin_unlock_irq(&gb_protocols_lock); + if (protocol) + WARN_ON(!protocol_count); + else + pr_err("protocol id %hhu version %hhu.%hhu not found\n", + protocol->id, major, minor); } diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index d53f67d..aa7b554 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -20,16 +20,15 @@ struct gb_protocol { u8 id; u8 major; u8 minor; + u8 count; - struct list_head connections; /* protocol users */ struct list_head links; /* global list */ }; bool gb_protocol_register(u8 id, u8 major, u8 minor); bool gb_protocol_deregister(struct gb_protocol *protocol); -bool gb_protocol_get(struct gb_connection *connection, u8 id, - u8 major, u8 minor); -void gb_protocol_put(struct gb_connection *connection); +struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor); +void gb_protocol_put(struct gb_protocol *protocol); #endif /* __PROTOCOL_H */ -- cgit v0.10.2 From dbb8894e0c3cf1661d83466faa277a8d436a1cba Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 5 Nov 2014 16:12:52 -0600 Subject: greybus: order the protocols list Add protocols to the global list in sorted order, based on their protocol id, and then their major and minor version number. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index 347d52c..6fec32e 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -17,10 +17,24 @@ static struct gb_protocol *_gb_protocol_find(u8 id, u8 major, u8 minor) { struct gb_protocol *protocol; - list_for_each_entry(protocol, &gb_protocols, links) - if (protocol->id == id && protocol->major == major - && protocol->minor == minor) - return protocol; + list_for_each_entry(protocol, &gb_protocols, links) { + if (protocol->id < id) + continue; + if (protocol->id > id) + break; + + if (protocol->major > major) + continue; + if (protocol->major < major) + break; + + if (protocol->minor > minor) + continue; + if (protocol->minor < minor) + break; + + return protocol; + } return NULL; } @@ -38,24 +52,52 @@ bool gb_protocol_register(u8 id, u8 major, u8 minor) protocol->major = major; protocol->minor = minor; + /* + * The protocols list is sorted first by protocol id (low to + * high), then by major version (high to low), and finally + * by minor version (high to low). Searching only by + * protocol id will produce the newest implemented version + * of the protocol. + */ spin_lock_irq(&gb_protocols_lock); - existing = _gb_protocol_find(id, major, minor); - if (!existing) - list_add(&protocol->links, &gb_protocols); - spin_unlock_irq(&gb_protocols_lock); - if (existing) { + list_for_each_entry(existing, &gb_protocols, links) { + if (existing->id < id) + continue; + if (existing->id > id) + break; + + if (existing->major > major) + continue; + if (existing->major < major) + break; + + if (existing->minor > minor) + continue; + if (existing->minor < minor) + break; + + /* A matching protocol has already been registered */ + spin_unlock_irq(&gb_protocols_lock); kfree(protocol); - protocol = NULL; + + return false; } - return protocol != NULL; + /* + * We need to insert the protocol here, before the existing one + * (or before the head if we searched the whole list) + */ + list_add_tail(&protocol->links, &existing->links); + spin_unlock_irq(&gb_protocols_lock); + + return true; } /* Returns true if successful, false otherwise */ bool gb_protocol_deregister(struct gb_protocol *protocol) { - u8 protocol_count; + u8 protocol_count = 0; spin_lock_irq(&gb_protocols_lock); protocol = _gb_protocol_find(protocol->id, protocol->major, -- cgit v0.10.2 From 19d03decd3415a7a0ec6c378720058f29f9568cc Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 5 Nov 2014 16:12:53 -0600 Subject: greybus: register preallocated protocols Set up protocol structures as static objects in each protocol source file. Pass the address of that in--rather than the protocol id and version information--to the protocol registration routine. Call a central routine to register all our pre-defined protocols. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index 28c0d0b..457daf70 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -404,3 +404,19 @@ struct gb_connection_handler gb_battery_connection_handler = { .connection_init = gb_battery_connection_init, .connection_exit = gb_battery_connection_exit, }; + +static struct gb_protocol battery_protocol = { + .id = GREYBUS_PROTOCOL_BATTERY, + .major = 0, + .minor = 1, +}; + +bool gb_battery_protocol_init(void) +{ + return gb_protocol_register(&battery_protocol); +} + +void gb_battery_protocol_exit(void) +{ + gb_protocol_deregister(&battery_protocol); +} diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 252d131..1d05c35 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -277,17 +277,23 @@ static int __init gb_init(void) goto error_operation; } - return 0; + if (!gb_protocol_init()) { + /* This only fails for duplicate protocol registration */ + retval = -EEXIST; + pr_err("gb_protocol_init failed\n"); + goto error_protocol; + } + return 0; /* Success */ + +error_protocol: + gb_operation_exit(); error_operation: gb_gbuf_exit(); - error_gbuf: gb_ap_exit(); - error_ap: bus_unregister(&greybus_bus_type); - error_bus: gb_debugfs_cleanup(); diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index df7dbae..242b91a 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -796,3 +796,19 @@ struct gb_connection_handler gb_gpio_connection_handler = { .connection_init = gb_gpio_connection_init, .connection_exit = gb_gpio_connection_exit, }; + +static struct gb_protocol gpio_protocol = { + .id = GREYBUS_PROTOCOL_GPIO, + .major = 0, + .minor = 1, +}; + +bool gb_gpio_protocol_init(void) +{ + return gb_protocol_register(&gpio_protocol); +} + +void gb_gpio_protocol_exit(void) +{ + gb_protocol_deregister(&gpio_protocol); +} diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index c6988ce..844ab8a 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -30,6 +30,7 @@ enum greybus_protocol { GREYBUS_PROTOCOL_I2C = 0x03, GREYBUS_PROTOCOL_UART = 0x04, GREYBUS_PROTOCOL_HID = 0x05, + GREYBUS_PROTOCOL_SDIO = 0x06, GREYBUS_PROTOCOL_BATTERY = 0x08, GREYBUS_PROTOCOL_LED = 0x0e, /* ... */ diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index b26464a..c8fae17 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -522,3 +522,19 @@ struct gb_connection_handler gb_i2c_connection_handler = { .connection_init = gb_i2c_connection_init, .connection_exit = gb_i2c_connection_exit, }; + +static struct gb_protocol i2c_protocol = { + .id = GREYBUS_PROTOCOL_I2C, + .major = 0, + .minor = 1, +}; + +bool gb_i2c_protocol_init(void) +{ + return gb_protocol_register(&i2c_protocol); +} + +void gb_i2c_protocol_exit(void) +{ + gb_protocol_deregister(&i2c_protocol); +} diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index 6fec32e..93e0af3 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -39,18 +39,12 @@ static struct gb_protocol *_gb_protocol_find(u8 id, u8 major, u8 minor) } /* Returns true if protocol was succesfully registered, false otherwise */ -bool gb_protocol_register(u8 id, u8 major, u8 minor) +bool gb_protocol_register(struct gb_protocol *protocol) { - struct gb_protocol *protocol; struct gb_protocol *existing; - - /* Initialize it speculatively */ - protocol = kzalloc(sizeof(*protocol), GFP_KERNEL); - if (!protocol) - return false; - protocol->id = id; - protocol->major = major; - protocol->minor = minor; + u8 id = protocol->id; + u8 major = protocol->major; + u8 minor = protocol->minor; /* * The protocols list is sorted first by protocol id (low to @@ -79,7 +73,6 @@ bool gb_protocol_register(u8 id, u8 major, u8 minor) /* A matching protocol has already been registered */ spin_unlock_irq(&gb_protocols_lock); - kfree(protocol); return false; } @@ -94,7 +87,17 @@ bool gb_protocol_register(u8 id, u8 major, u8 minor) return true; } -/* Returns true if successful, false otherwise */ +/* + * De-register a previously registered protocol. + * + * XXX Currently this fails (and reports an error to the caller) if + * XXX the protocol is currently in use. We may want to forcefully + * XXX kill off a protocol and all its active users at some point. + * XXX But I think that's better handled by quescing modules that + * XXX have users and having those users drop their reference. + * + * Returns true if successful, false otherwise. + */ bool gb_protocol_deregister(struct gb_protocol *protocol) { u8 protocol_count = 0; @@ -108,7 +111,6 @@ bool gb_protocol_deregister(struct gb_protocol *protocol) list_del(&protocol->links); } spin_unlock_irq(&gb_protocols_lock); - kfree(protocol); return protocol && !protocol_count; } @@ -158,3 +160,39 @@ void gb_protocol_put(struct gb_protocol *protocol) pr_err("protocol id %hhu version %hhu.%hhu not found\n", protocol->id, major, minor); } + +bool gb_protocol_init(void) +{ + bool ret = true; + + if (!gb_battery_protocol_init()) { + pr_err("error initializing battery protocol\n"); + ret = false; + } + if (!gb_gpio_protocol_init()) { + pr_err("error initializing gpio protocol\n"); + ret = false; + } + if (!gb_i2c_protocol_init()) { + pr_err("error initializing i2c protocol\n"); + ret = false; + } + if (!gb_uart_protocol_init()) { + pr_err("error initializing uart protocol\n"); + ret = false; + } + if (!gb_sdio_protocol_init()) { + pr_err("error initializing sdio protocol\n"); + ret = false; + } + return ret; +} + +void gb_protocol_exit(void) +{ + gb_sdio_protocol_exit(); + gb_uart_protocol_exit(); + gb_i2c_protocol_exit(); + gb_gpio_protocol_exit(); + gb_battery_protocol_exit(); +} diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index aa7b554..c2adfdc 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -25,10 +25,33 @@ struct gb_protocol { struct list_head links; /* global list */ }; -bool gb_protocol_register(u8 id, u8 major, u8 minor); +bool gb_protocol_register(struct gb_protocol *protocol); bool gb_protocol_deregister(struct gb_protocol *protocol); struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor); void gb_protocol_put(struct gb_protocol *protocol); +/* + * These are defined in their respective protocol source files. + * Declared here for now. They could be added via modules, or maybe + * just use initcalls (which level?). + */ +extern bool gb_battery_protocol_init(void); +extern void gb_battery_protocol_exit(void); + +extern bool gb_gpio_protocol_init(void); +extern void gb_gpio_protocol_exit(void); + +extern bool gb_i2c_protocol_init(void); +extern void gb_i2c_protocol_exit(void); + +extern bool gb_uart_protocol_init(void); +extern void gb_uart_protocol_exit(void); + +extern bool gb_sdio_protocol_init(void); +extern void gb_sdio_protocol_exit(void); + +bool gb_protocol_init(void); +void gb_protocol_exit(void); + #endif /* __PROTOCOL_H */ diff --git a/drivers/staging/greybus/sdio-gb.c b/drivers/staging/greybus/sdio-gb.c index 30caba8..8fbfbca 100644 --- a/drivers/staging/greybus/sdio-gb.c +++ b/drivers/staging/greybus/sdio-gb.c @@ -81,3 +81,19 @@ struct gb_connection_handler gb_sdio_connection_handler = { .connection_init = gb_sdio_connection_init, .connection_exit = gb_sdio_connection_exit, }; + +static struct gb_protocol sdio_protocol = { + .id = GREYBUS_PROTOCOL_SDIO, + .major = 0, + .minor = 1, +}; + +bool gb_sdio_protocol_init(void) +{ + return gb_protocol_register(&sdio_protocol); +} + +void gb_sdio_protocol_exit(void) +{ + gb_protocol_deregister(&sdio_protocol); +} diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index b52d9e1..5596644 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -524,3 +524,19 @@ struct gb_connection_handler gb_uart_connection_handler = { .connection_init = gb_uart_connection_init, .connection_exit = gb_uart_connection_exit, }; + +static struct gb_protocol uart_protocol = { + .id = GREYBUS_PROTOCOL_UART, + .major = 0, + .minor = 1, +}; + +bool gb_uart_protocol_init(void) +{ + return gb_protocol_register(&uart_protocol); +} + +void gb_uart_protocol_exit(void) +{ + gb_protocol_deregister(&uart_protocol); +} -- cgit v0.10.2 From 5d9fd7e1ba801ff83bb657ad364581947400898c Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 5 Nov 2014 16:12:54 -0600 Subject: greybus: move methods into protocol Get rid of the connection handler structure, and instead put the methods that were there into the protocol structure. Eliminate the big switch statement in connection_init() and just call the connection's protocol's init function there directly. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index 457daf70..a401567 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -400,15 +400,12 @@ static void gb_battery_connection_exit(struct gb_connection *connection) kfree(gb); } -struct gb_connection_handler gb_battery_connection_handler = { - .connection_init = gb_battery_connection_init, - .connection_exit = gb_battery_connection_exit, -}; - static struct gb_protocol battery_protocol = { .id = GREYBUS_PROTOCOL_BATTERY, .major = 0, .minor = 1, + .connection_init = gb_battery_connection_init, + .connection_exit = gb_battery_connection_exit, }; bool gb_battery_protocol_init(void) diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index e3000f7e..586457f 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -267,45 +267,18 @@ void gb_connection_err(struct gb_connection *connection, const char *fmt, ...) va_end(args); } -/* - * XXX Protocols should have a set of function pointers: - * ->init (called here, to initialize the device) - * ->input_handler - * ->exit (reverse of init) - */ int gb_connection_init(struct gb_connection *connection) { int ret; - /* Need to enable the connection to initialize it */ - connection->state = GB_CONNECTION_STATE_ENABLED; - switch (connection->protocol->id) { - case GREYBUS_PROTOCOL_I2C: - connection->handler = &gb_i2c_connection_handler; - break; - case GREYBUS_PROTOCOL_GPIO: - connection->handler = &gb_gpio_connection_handler; - break; - case GREYBUS_PROTOCOL_BATTERY: - connection->handler = &gb_battery_connection_handler; - break; - case GREYBUS_PROTOCOL_UART: - connection->handler = &gb_uart_connection_handler; - break; - case GREYBUS_PROTOCOL_CONTROL: - case GREYBUS_PROTOCOL_AP: - case GREYBUS_PROTOCOL_HID: - case GREYBUS_PROTOCOL_LED: - case GREYBUS_PROTOCOL_VENDOR: - default: - gb_connection_err(connection, "unimplemented protocol %hhu", - connection->protocol->id); - ret = -ENXIO; - break; + if (!connection->protocol) { + gb_connection_err(connection, "uninitialized connection"); + return -EIO; } - ret = connection->handler->connection_init(connection); - + /* Need to enable the connection to initialize it */ + connection->state = GB_CONNECTION_STATE_ENABLED; + ret = connection->protocol->connection_init(connection); if (ret) connection->state = GB_CONNECTION_STATE_ERROR; @@ -314,10 +287,10 @@ int gb_connection_init(struct gb_connection *connection) void gb_connection_exit(struct gb_connection *connection) { - if (!connection->handler) { + if (!connection->protocol) { gb_connection_err(connection, "uninitialized connection"); return; } connection->state = GB_CONNECTION_STATE_DESTROYING; - connection->handler->connection_exit(connection); + connection->protocol->connection_exit(connection); } diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index ea54334..893c02a 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -21,15 +21,6 @@ enum gb_connection_state { GB_CONNECTION_STATE_DESTROYING = 4, }; -struct gb_connection; -typedef int (*gb_connection_init_t)(struct gb_connection *); -typedef void (*gb_connection_exit_t)(struct gb_connection *); - -struct gb_connection_handler { - gb_connection_init_t connection_init; - gb_connection_exit_t connection_exit; -}; - struct gb_connection { struct greybus_host_device *hd; struct gb_interface *interface; @@ -48,8 +39,6 @@ struct gb_connection { struct rb_root pending; /* awaiting reponse */ atomic_t op_cycle; - struct gb_connection_handler *handler; - void *private; }; #define to_gb_connection(d) container_of(d, struct gb_connection, dev) diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index 242b91a..a4ee356 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -792,15 +792,12 @@ static void gb_gpio_connection_exit(struct gb_connection *connection) kfree(gb_gpio_controller); } -struct gb_connection_handler gb_gpio_connection_handler = { - .connection_init = gb_gpio_connection_init, - .connection_exit = gb_gpio_connection_exit, -}; - static struct gb_protocol gpio_protocol = { .id = GREYBUS_PROTOCOL_GPIO, .major = 0, .minor = 1, + .connection_init = gb_gpio_connection_init, + .connection_exit = gb_gpio_connection_exit, }; bool gb_gpio_protocol_init(void) diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index c8fae17..60db15e 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -518,15 +518,12 @@ static void gb_i2c_connection_exit(struct gb_connection *connection) kfree(gb_i2c_dev); } -struct gb_connection_handler gb_i2c_connection_handler = { - .connection_init = gb_i2c_connection_init, - .connection_exit = gb_i2c_connection_exit, -}; - static struct gb_protocol i2c_protocol = { .id = GREYBUS_PROTOCOL_I2C, .major = 0, .minor = 1, + .connection_init = gb_i2c_connection_init, + .connection_exit = gb_i2c_connection_exit, }; bool gb_i2c_protocol_init(void) diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index c2adfdc..32178f1 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -11,6 +11,9 @@ #include "greybus.h" +typedef int (*gb_connection_init_t)(struct gb_connection *); +typedef void (*gb_connection_exit_t)(struct gb_connection *); + /* * Protocols having the same id but different major and/or minor * version numbers are treated as distinct protocols. If it makes @@ -23,6 +26,9 @@ struct gb_protocol { u8 count; struct list_head links; /* global list */ + + gb_connection_init_t connection_init; + gb_connection_exit_t connection_exit; }; bool gb_protocol_register(struct gb_protocol *protocol); diff --git a/drivers/staging/greybus/sdio-gb.c b/drivers/staging/greybus/sdio-gb.c index 8fbfbca..9e5fb8f 100644 --- a/drivers/staging/greybus/sdio-gb.c +++ b/drivers/staging/greybus/sdio-gb.c @@ -77,15 +77,12 @@ static void gb_sdio_connection_exit(struct gb_connection *connection) connection->private = NULL; } -struct gb_connection_handler gb_sdio_connection_handler = { - .connection_init = gb_sdio_connection_init, - .connection_exit = gb_sdio_connection_exit, -}; - static struct gb_protocol sdio_protocol = { .id = GREYBUS_PROTOCOL_SDIO, .major = 0, .minor = 1, + .connection_init = gb_sdio_connection_init, + .connection_exit = gb_sdio_connection_exit, }; bool gb_sdio_protocol_init(void) diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 5596644..56db891 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -520,15 +520,12 @@ static void gb_tty_exit(void) unregister_chrdev_region(MKDEV(major, minor), GB_NUM_MINORS); } -struct gb_connection_handler gb_uart_connection_handler = { - .connection_init = gb_uart_connection_init, - .connection_exit = gb_uart_connection_exit, -}; - static struct gb_protocol uart_protocol = { .id = GREYBUS_PROTOCOL_UART, .major = 0, .minor = 1, + .connection_init = gb_uart_connection_init, + .connection_exit = gb_uart_connection_exit, }; bool gb_uart_protocol_init(void) -- cgit v0.10.2 From f8fb05e2b89eddaadce319fb55a532731393e630 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 5 Nov 2014 16:12:55 -0600 Subject: greybus: add an incoming request receive method Define a new protocol method intended to handle the receipt of an incoming operation request. Most protocols have no expected incoming requests and can leave this null. If a request arrives for a protocol with no request receive handler an error is reported and the request fails. Get rid of the previous fixed array of receive handlers, it's no longer needed. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index a401567..4bd7aed 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -406,6 +406,7 @@ static struct gb_protocol battery_protocol = { .minor = 1, .connection_init = gb_battery_connection_init, .connection_exit = gb_battery_connection_exit, + .request_recv = NULL, /* no incoming requests */ }; bool gb_battery_protocol_init(void) diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index a4ee356..40833fa 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -798,6 +798,7 @@ static struct gb_protocol gpio_protocol = { .minor = 1, .connection_init = gb_gpio_connection_init, .connection_exit = gb_gpio_connection_exit, + .request_recv = NULL, /* no incoming requests */ }; bool gb_gpio_protocol_init(void) diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index 60db15e..c179078 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -524,6 +524,7 @@ static struct gb_protocol i2c_protocol = { .minor = 1, .connection_init = gb_i2c_connection_init, .connection_exit = gb_i2c_connection_exit, + .request_recv = NULL, /* no incoming requests */ }; bool gb_i2c_protocol_init(void) diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 9cb9c9d..24707f6 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -176,46 +176,25 @@ int gb_operation_wait(struct gb_operation *operation) } -/* - * This handler is used if no operation response messages are ever - * expected for a given protocol. - */ -static void gb_operation_recv_none(struct gb_operation *operation) -{ - /* Nothing to do! */ -} - -typedef void (*gb_operation_recv_handler)(struct gb_operation *operation); -static gb_operation_recv_handler gb_operation_recv_handlers[] = { - [GREYBUS_PROTOCOL_CONTROL] = NULL, - [GREYBUS_PROTOCOL_AP] = NULL, - [GREYBUS_PROTOCOL_GPIO] = NULL, - [GREYBUS_PROTOCOL_I2C] = gb_operation_recv_none, - [GREYBUS_PROTOCOL_UART] = NULL, - [GREYBUS_PROTOCOL_HID] = NULL, - [GREYBUS_PROTOCOL_BATTERY] = gb_operation_recv_none, - [GREYBUS_PROTOCOL_LED] = NULL, - [GREYBUS_PROTOCOL_VENDOR] = NULL, -}; - static void gb_operation_request_handle(struct gb_operation *operation) { - u8 protocol_id = operation->connection->protocol->id; - - /* Subtract one from array size to stay within u8 range */ - if (protocol_id <= (u8)(ARRAY_SIZE(gb_operation_recv_handlers) - 1)) { - gb_operation_recv_handler handler; + struct gb_protocol *protocol = operation->connection->protocol; + struct gb_operation_msg_hdr *header; - handler = gb_operation_recv_handlers[protocol_id]; - if (handler) { - handler(operation); /* Handle the request */ - return; - } + /* + * If the protocol has no incoming request handler, report + * an error and mark the request bad. + */ + if (protocol->request_recv) { + protocol->request_recv(operation); + goto out; } + header = operation->request->transfer_buffer; gb_connection_err(operation->connection, - "unrecognized protocol id %hhu\n", protocol_id); + "unexpected incoming request type 0x%02hhx\n", header->type); operation->result = GB_OP_PROTOCOL_BAD; +out: gb_operation_complete(operation); } diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index 32178f1..a236401 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -11,8 +11,11 @@ #include "greybus.h" +struct gb_operation; + typedef int (*gb_connection_init_t)(struct gb_connection *); typedef void (*gb_connection_exit_t)(struct gb_connection *); +typedef void (*gb_request_recv_t)(struct gb_operation *); /* * Protocols having the same id but different major and/or minor @@ -29,6 +32,7 @@ struct gb_protocol { gb_connection_init_t connection_init; gb_connection_exit_t connection_exit; + gb_request_recv_t request_recv; }; bool gb_protocol_register(struct gb_protocol *protocol); diff --git a/drivers/staging/greybus/sdio-gb.c b/drivers/staging/greybus/sdio-gb.c index 9e5fb8f..4775ed0 100644 --- a/drivers/staging/greybus/sdio-gb.c +++ b/drivers/staging/greybus/sdio-gb.c @@ -83,6 +83,7 @@ static struct gb_protocol sdio_protocol = { .minor = 1, .connection_init = gb_sdio_connection_init, .connection_exit = gb_sdio_connection_exit, + .request_recv = NULL, /* no incoming requests */ }; bool gb_sdio_protocol_init(void) diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 56db891..9638d0e 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -526,6 +526,7 @@ static struct gb_protocol uart_protocol = { .minor = 1, .connection_init = gb_uart_connection_init, .connection_exit = gb_uart_connection_exit, + .request_recv = NULL, /* no incoming requests */ }; bool gb_uart_protocol_init(void) -- cgit v0.10.2 From 8d59897978aa0dfb3562f130e568e898e6952e72 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 6 Nov 2014 07:00:59 -0600 Subject: greybus: kill test_sink.c This file is an artifact of some early testing, but it is otherwise unused. So get rid of it. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 39874de..bb90895 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -17,7 +17,6 @@ greybus-y := core.o \ obj-m += greybus.o obj-m += es1-ap-usb.o -obj-m += test_sink.o KERNELVER ?= $(shell uname -r) KERNELDIR ?= /lib/modules/$(KERNELVER)/build diff --git a/drivers/staging/greybus/test_sink.c b/drivers/staging/greybus/test_sink.c deleted file mode 100644 index 1b47769..0000000 --- a/drivers/staging/greybus/test_sink.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Test "sink" Greybus driver. - * - * Copyright 2014 Google Inc. - * - * Released under the GPLv2 only. - */ - -#include -#include -#include -#include "greybus.h" - -struct test_device { - struct gb_module *gmod; -}; - -int gb_register_cport_complete(struct gb_module *gmod, - gbuf_complete_t handler, u16 cport_id, - void *context); -void gb_deregister_cport_complete(u16 cport_id); - - - -static int test_init(void) -{ - return 0; -} - -static void test_exit(void) -{ -} - -module_init(test_init); -module_exit(test_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Greg Kroah-Hartman "); -- cgit v0.10.2 From 7a0eed065ded836bbb6b71da965cef0d6a0aeecf Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 6 Nov 2014 07:01:00 -0600 Subject: greybus: kill old cport handler code Handling of incoming requests has been moved into the Greybus connection and protocol layers. As a result, the original cport oriented handler code is no longer used. So get rid of it. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 4f591aa..17141b6 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -114,37 +114,6 @@ void greybus_kill_gbuf(struct gbuf *gbuf) hd->driver->kill_gbuf(gbuf); } -#define MAX_CPORTS 1024 -struct gb_cport_handler { - gbuf_complete_t handler; - u16 cport_id; - struct gb_module *gmod; - void *context; -}; - -static struct gb_cport_handler cport_handler[MAX_CPORTS]; -// FIXME - use a lock for this list of handlers, but really, for now we don't -// need it, we don't have a dynamic system... - -int gb_register_cport_complete(struct gb_module *gmod, - gbuf_complete_t handler, - u16 cport_id, - void *context) -{ - if (cport_handler[cport_id].handler) - return -EINVAL; - cport_handler[cport_id].context = context; - cport_handler[cport_id].gmod = gmod; - cport_handler[cport_id].cport_id = cport_id; - cport_handler[cport_id].handler = handler; - return 0; -} - -void gb_deregister_cport_complete(u16 cport_id) -{ - cport_handler[cport_id].handler = NULL; -} - void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, u8 *data, size_t length) { diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index f6c90e0..834cbaa 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -258,11 +258,6 @@ void gb_debugfs_cleanup(void); int gb_gbuf_init(void); void gb_gbuf_exit(void); -int gb_register_cport_complete(struct gb_module *gmod, - gbuf_complete_t handler, u16 cport_id, - void *context); -void gb_deregister_cport_complete(u16 cport_id); - extern struct bus_type greybus_bus_type; extern const struct attribute_group *greybus_module_groups[]; -- cgit v0.10.2 From c69a50f2ce2eaec8ee9f50081a88589d1231ef3b Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 6 Nov 2014 07:01:01 -0600 Subject: greybus: get rid of gbuf->actual_length Right now, the actual_length field of a gbuf is only ever assigned, never used. We now fill gbufs only with operation messages, and they encode within them the amount of space "actually used" in a buffer in a request-specific way. As a result, there's no need for the gbuf->actual_length field, so we can remove it. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 834cbaa..175bd00 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -130,7 +130,6 @@ struct gbuf { int status; void *transfer_buffer; u32 transfer_buffer_length; - u32 actual_length; bool outbound; /* AP-relative data direction */ diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 24707f6..720cc76 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -351,8 +351,6 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, goto err_cache; operation->request_payload = operation->request->transfer_buffer + sizeof(struct gb_operation_msg_hdr); - /* We always use the full request buffer */ - operation->request->actual_length = request_size; if (outgoing) { type |= GB_OPERATION_TYPE_RESPONSE; @@ -443,9 +441,6 @@ int gb_operation_request_send(struct gb_operation *operation, */ int gb_operation_response_send(struct gb_operation *operation) { - /* XXX - * Caller needs to have set operation->response->actual_length - */ gb_operation_remove(operation); gb_operation_destroy(operation); @@ -502,7 +497,6 @@ void gb_connection_operation_recv(struct gb_connection *connection, } memcpy(gbuf->transfer_buffer, data, msg_size); - gbuf->actual_length = msg_size; /* The rest will be handled in work queue context */ queue_work(gb_operation_recv_workqueue, &operation->recv_work); -- cgit v0.10.2 From ef45fa33a4c9b37440ef2e3af55843066c6149ce Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 6 Nov 2014 07:01:02 -0600 Subject: greybus: record gbuf->operation Currently a gbuf records a pointer to the connection it's associated with. We now know only use gbufs in operation messages, so we can point a gbuf at its operation instead. This still gives access to the connection where needed, but it also will provide all the context we'll ever need for a gbuf, and this allows us (in the next patch) to remove the gbuf->context field as well. So switch to recording in a gbuf the operation rather than the connection it is associated with. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 2fccece..645edbd 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -96,6 +96,7 @@ static void cport_out_callback(struct urb *urb); static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask) { + struct gb_connection *connection = gbuf->operation->connection; u32 cport_reserve = gbuf->outbound ? 1 : 0; u8 *buffer; @@ -121,16 +122,16 @@ static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, * we will encode the cport number in the first byte of the buffer, so * set the second byte to be the "transfer buffer" */ - if (gbuf->connection->interface_cport_id > (u16)U8_MAX) { + if (connection->interface_cport_id > (u16)U8_MAX) { pr_err("gbuf->interface_cport_id (%hd) is out of range!\n", - gbuf->connection->interface_cport_id); + connection->interface_cport_id); kfree(buffer); return -EINVAL; } /* Insert the cport id for outbound buffers */ if (gbuf->outbound) - *buffer++ = gbuf->connection->interface_cport_id; + *buffer++ = connection->interface_cport_id; gbuf->transfer_buffer = buffer; gbuf->transfer_buffer_length = size; @@ -208,7 +209,7 @@ static struct urb *next_free_urb(struct es1_ap_dev *es1, gfp_t gfp_mask) static int submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) { - struct greybus_host_device *hd = gbuf->connection->hd; + struct greybus_host_device *hd = gbuf->operation->connection->hd; struct es1_ap_dev *es1 = hd_to_es1(hd); struct usb_device *udev = es1->usb_dev; int retval; @@ -394,7 +395,7 @@ exit: static void cport_out_callback(struct urb *urb) { struct gbuf *gbuf = urb->context; - struct es1_ap_dev *es1 = hd_to_es1(gbuf->connection->hd); + struct es1_ap_dev *es1 = hd_to_es1(gbuf->operation->connection->hd); unsigned long flags; int i; diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 17141b6..817e262 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -35,13 +35,14 @@ static struct kmem_cache *gbuf_head_cache; * that the driver can then fill up with the data to be sent out. Curse * hardware designers for this issue... */ -struct gbuf *greybus_alloc_gbuf(struct gb_connection *connection, +struct gbuf *greybus_alloc_gbuf(struct gb_operation *operation, gbuf_complete_t complete, unsigned int size, bool outbound, gfp_t gfp_mask, void *context) { + struct greybus_host_device *hd = operation->connection->hd; struct gbuf *gbuf; int retval; @@ -50,14 +51,14 @@ struct gbuf *greybus_alloc_gbuf(struct gb_connection *connection, return NULL; kref_init(&gbuf->kref); - gbuf->connection = connection; + gbuf->operation = operation; gbuf->outbound = outbound; gbuf->complete = complete; gbuf->context = context; gbuf->status = -EBADR; /* Initial value--means "never set" */ /* Host controller specific allocation for the actual buffer */ - retval = connection->hd->driver->alloc_gbuf_data(gbuf, size, gfp_mask); + retval = hd->driver->alloc_gbuf_data(gbuf, size, gfp_mask); if (retval) { kmem_cache_free(gbuf_head_cache, gbuf); return NULL; @@ -72,8 +73,9 @@ static DEFINE_MUTEX(gbuf_mutex); static void free_gbuf(struct kref *kref) { struct gbuf *gbuf = container_of(kref, struct gbuf, kref); + struct greybus_host_device *hd = gbuf->operation->connection->hd; - gbuf->connection->hd->driver->free_gbuf_data(gbuf); + hd->driver->free_gbuf_data(gbuf); kmem_cache_free(gbuf_head_cache, gbuf); mutex_unlock(&gbuf_mutex); @@ -97,7 +99,7 @@ EXPORT_SYMBOL_GPL(greybus_get_gbuf); int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) { - struct greybus_host_device *hd = gbuf->connection->hd; + struct greybus_host_device *hd = gbuf->operation->connection->hd; gbuf->status = -EINPROGRESS; @@ -106,7 +108,7 @@ int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) void greybus_kill_gbuf(struct gbuf *gbuf) { - struct greybus_host_device *hd = gbuf->connection->hd; + struct greybus_host_device *hd = gbuf->operation->connection->hd; if (gbuf->status != -EINPROGRESS) return; diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 175bd00..34e8584 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -126,7 +126,7 @@ typedef void (*gbuf_complete_t)(struct gbuf *gbuf); struct gbuf { struct kref kref; - struct gb_connection *connection; + struct gb_operation *operation; int status; void *transfer_buffer; u32 transfer_buffer_length; @@ -194,7 +194,7 @@ void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, u8 *data, size_t length); void greybus_gbuf_finished(struct gbuf *gbuf); -struct gbuf *greybus_alloc_gbuf(struct gb_connection *connection, +struct gbuf *greybus_alloc_gbuf(struct gb_operation *operation, gbuf_complete_t complete, unsigned int size, bool outbound, gfp_t gfp_mask, void *context); void greybus_free_gbuf(struct gbuf *gbuf); diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 720cc76..20ad452 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -295,13 +295,12 @@ static struct gbuf *gb_operation_gbuf_create(struct gb_operation *operation, u8 type, size_t size, bool data_out) { - struct gb_connection *connection = operation->connection; struct gb_operation_msg_hdr *header; struct gbuf *gbuf; gfp_t gfp_flags = data_out ? GFP_KERNEL : GFP_ATOMIC; size += sizeof(*header); - gbuf = greybus_alloc_gbuf(connection, gb_operation_gbuf_complete, + gbuf = greybus_alloc_gbuf(operation, gb_operation_gbuf_complete, size, data_out, gfp_flags, operation); if (!gbuf) return NULL; -- cgit v0.10.2 From a77b06809b9214e23e603248d7609d6efa55f833 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 6 Nov 2014 07:01:03 -0600 Subject: greybus: remove gbuf->context A gbuf now records a pointer to its operation. The only thing ever stored in a gbuf context pointer is the gbuf's operation. Therefore there's no longer any need to maintain the context pointer, so get rid of it. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 817e262..af077ff 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -28,7 +28,6 @@ static struct kmem_cache *gbuf_head_cache; * @complete: callback when the gbuf is finished with * @size: size of the buffer * @gfp_mask: allocation mask - * @context: context added to the gbuf by the driver * * TODO: someday it will be nice to handle DMA, but for now, due to the * architecture we are stuck with, the greybus core has to allocate the buffer @@ -39,8 +38,7 @@ struct gbuf *greybus_alloc_gbuf(struct gb_operation *operation, gbuf_complete_t complete, unsigned int size, bool outbound, - gfp_t gfp_mask, - void *context) + gfp_t gfp_mask) { struct greybus_host_device *hd = operation->connection->hd; struct gbuf *gbuf; @@ -54,7 +52,6 @@ struct gbuf *greybus_alloc_gbuf(struct gb_operation *operation, gbuf->operation = operation; gbuf->outbound = outbound; gbuf->complete = complete; - gbuf->context = context; gbuf->status = -EBADR; /* Initial value--means "never set" */ /* Host controller specific allocation for the actual buffer */ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 34e8584..a4af64f 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -133,7 +133,6 @@ struct gbuf { bool outbound; /* AP-relative data direction */ - void *context; void *hcd_data; /* for the HCD to track the gbuf */ gbuf_complete_t complete; }; @@ -196,7 +195,7 @@ void greybus_gbuf_finished(struct gbuf *gbuf); struct gbuf *greybus_alloc_gbuf(struct gb_operation *operation, gbuf_complete_t complete, unsigned int size, - bool outbound, gfp_t gfp_mask, void *context); + bool outbound, gfp_t gfp_mask); void greybus_free_gbuf(struct gbuf *gbuf); struct gbuf *greybus_get_gbuf(struct gbuf *gbuf); #define greybus_put_gbuf greybus_free_gbuf diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 20ad452..575e586 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -256,7 +256,7 @@ static void operation_timeout(struct work_struct *work) static void gb_operation_gbuf_complete(struct gbuf *gbuf) { if (gbuf->status) { - struct gb_operation *operation = gbuf->context; + struct gb_operation *operation = gbuf->operation; struct gb_operation_msg_hdr *header; int id; int type; @@ -301,7 +301,7 @@ static struct gbuf *gb_operation_gbuf_create(struct gb_operation *operation, size += sizeof(*header); gbuf = greybus_alloc_gbuf(operation, gb_operation_gbuf_complete, - size, data_out, gfp_flags, operation); + size, data_out, gfp_flags); if (!gbuf) return NULL; -- cgit v0.10.2 From eecf6deb578a250fc3336286a0759281569966ec Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 6 Nov 2014 07:01:04 -0600 Subject: greybus: get rid of greybus_gbuf_finished() All greybus_gbuf_finished() does is call the gbuf's complete method. Currently, greybus_gbuf_finished() is only ever called in one place, and that place can call the complete method directly instead. That allows us to eliminate greybus_gbuf_finished(). Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index af077ff..1e5562e 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -128,13 +128,6 @@ void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, } EXPORT_SYMBOL_GPL(greybus_cport_in); -/* Can be called in interrupt context, do the work and get out of here */ -void greybus_gbuf_finished(struct gbuf *gbuf) -{ - gbuf->complete(gbuf); -} -EXPORT_SYMBOL_GPL(greybus_gbuf_finished); - int gb_gbuf_init(void) { gbuf_head_cache = kmem_cache_create("gbuf_head_cache", diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index a4af64f..6f2369e 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -191,7 +191,6 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *hd, void greybus_remove_hd(struct greybus_host_device *hd); void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, u8 *data, size_t length); -void greybus_gbuf_finished(struct gbuf *gbuf); struct gbuf *greybus_alloc_gbuf(struct gb_operation *operation, gbuf_complete_t complete, unsigned int size, diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 575e586..6bb7568 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -207,6 +207,7 @@ out: static void gb_operation_recv_work(struct work_struct *recv_work) { struct gb_operation *operation; + struct gbuf *gbuf; bool incoming_request; operation = container_of(recv_work, struct gb_operation, recv_work); @@ -217,9 +218,10 @@ static void gb_operation_recv_work(struct work_struct *recv_work) /* We're finished with the buffer we read into */ if (incoming_request) - greybus_gbuf_finished(operation->request); + gbuf = operation->request; else - greybus_gbuf_finished(operation->response); + gbuf = operation->response; + gbuf->complete(gbuf); } /* -- cgit v0.10.2 From 3a0e3c3efde8655958dc10673f374a8cc983cca2 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 6 Nov 2014 07:01:05 -0600 Subject: greybus: move gb_operation_gbuf_complete() Simple move of a block of code, done as a separate commit to make it easier to see that's all that's going on. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 6bb7568..16ee7ce 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -199,6 +199,49 @@ out: } /* + * Buffer completion function. We get notified whenever any buffer + * completes. For outbound messages, this tells us that the message + * has been sent. For inbound messages, it means the data has + * landed in the buffer and is ready to be processed. + * + * Either way, we don't do anything. We don't really care when an + * outbound message has been sent, and for incoming messages we + * we'll be done with everything we need to do before we mark it + * finished. + * + * XXX We may want to record that a request is (or is no longer) in flight. + */ +static void gb_operation_gbuf_complete(struct gbuf *gbuf) +{ + if (gbuf->status) { + struct gb_operation *operation = gbuf->operation; + struct gb_operation_msg_hdr *header; + int id; + int type; + + if (gbuf == operation->request) + header = operation->request->transfer_buffer; + else if (gbuf == operation->response) + header = operation->response->transfer_buffer; + else + header = NULL; + + if (header) { + id = le16_to_cpu(header->id); + type = header->type; + } else { + id = -1; + type = -1; + } + + gb_connection_err(operation->connection, + "operation %d type %d gbuf error %d", + id, type, gbuf->status); + } + return; +} + +/* * Either this operation contains an incoming request, or its * response has arrived. An incoming request will have a null * response buffer pointer (it is the responsibility of the request @@ -243,49 +286,6 @@ static void operation_timeout(struct work_struct *work) } /* - * Buffer completion function. We get notified whenever any buffer - * completes. For outbound messages, this tells us that the message - * has been sent. For inbound messages, it means the data has - * landed in the buffer and is ready to be processed. - * - * Either way, we don't do anything. We don't really care when an - * outbound message has been sent, and for incoming messages we - * we'll be done with everything we need to do before we mark it - * finished. - * - * XXX We may want to record that a request is (or is no longer) in flight. - */ -static void gb_operation_gbuf_complete(struct gbuf *gbuf) -{ - if (gbuf->status) { - struct gb_operation *operation = gbuf->operation; - struct gb_operation_msg_hdr *header; - int id; - int type; - - if (gbuf == operation->request) - header = operation->request->transfer_buffer; - else if (gbuf == operation->response) - header = operation->response->transfer_buffer; - else - header = NULL; - - if (header) { - id = le16_to_cpu(header->id); - type = header->type; - } else { - id = -1; - type = -1; - } - - gb_connection_err(operation->connection, - "operation %d type %d gbuf error %d", - id, type, gbuf->status); - } - return; -} - -/* * Allocate a buffer to be used for an operation request or response * message. For outgoing messages, both types of message contain a * common header, which is filled in here. Incoming requests or -- cgit v0.10.2 From 5d2207e7047ebd110307f5f60c440f7119f999b8 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 6 Nov 2014 07:01:06 -0600 Subject: greybus: kill gbuf->complete The gbuf complete method is a callback that allows the creator of a gbuf to know when all processing on a gbuf is done. We now only ever allocate gbufs for use in Greybus operations, and in that case we only ever supply gb_operation_gbuf_complete() as the completion callback. Furthermore, the only place gbuf->complete() is called is in gb_operation_recv_work(). Knowing this, we can just call gb_operation_gbuf_complete() directly from gb_operation_recv_work(), and get rid of the gbuf->complete() method entirely. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 1e5562e..8b5a438 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -35,7 +35,6 @@ static struct kmem_cache *gbuf_head_cache; * hardware designers for this issue... */ struct gbuf *greybus_alloc_gbuf(struct gb_operation *operation, - gbuf_complete_t complete, unsigned int size, bool outbound, gfp_t gfp_mask) @@ -51,7 +50,6 @@ struct gbuf *greybus_alloc_gbuf(struct gb_operation *operation, kref_init(&gbuf->kref); gbuf->operation = operation; gbuf->outbound = outbound; - gbuf->complete = complete; gbuf->status = -EBADR; /* Initial value--means "never set" */ /* Host controller specific allocation for the actual buffer */ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 6f2369e..296a6a2 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -118,11 +118,6 @@ */ - -struct gbuf; - -typedef void (*gbuf_complete_t)(struct gbuf *gbuf); - struct gbuf { struct kref kref; @@ -134,7 +129,6 @@ struct gbuf { bool outbound; /* AP-relative data direction */ void *hcd_data; /* for the HCD to track the gbuf */ - gbuf_complete_t complete; }; @@ -193,8 +187,8 @@ void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, u8 *data, size_t length); struct gbuf *greybus_alloc_gbuf(struct gb_operation *operation, - gbuf_complete_t complete, unsigned int size, - bool outbound, gfp_t gfp_mask); + unsigned int size, bool outbound, + gfp_t gfp_mask); void greybus_free_gbuf(struct gbuf *gbuf); struct gbuf *greybus_get_gbuf(struct gbuf *gbuf); #define greybus_put_gbuf greybus_free_gbuf diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 16ee7ce..302ab00 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -264,7 +264,7 @@ static void gb_operation_recv_work(struct work_struct *recv_work) gbuf = operation->request; else gbuf = operation->response; - gbuf->complete(gbuf); + gb_operation_gbuf_complete(gbuf); } /* @@ -302,8 +302,7 @@ static struct gbuf *gb_operation_gbuf_create(struct gb_operation *operation, gfp_t gfp_flags = data_out ? GFP_KERNEL : GFP_ATOMIC; size += sizeof(*header); - gbuf = greybus_alloc_gbuf(operation, gb_operation_gbuf_complete, - size, data_out, gfp_flags); + gbuf = greybus_alloc_gbuf(operation, size, data_out, gfp_flags); if (!gbuf) return NULL; -- cgit v0.10.2 From 34c6507ca8e675ca0afa11ca0076d108027b0b2f Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Thu, 13 Nov 2014 09:14:13 -0500 Subject: greybus: add pwm protocol driver Add a PWM driver that implements the Greybus PWM protocol. Signed-off-by: Matt Porter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index bb90895..7ec70fe 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -11,6 +11,7 @@ greybus-y := core.o \ operation.o \ i2c-gb.o \ gpio-gb.o \ + pwm-gb.o \ sdio-gb.o \ uart-gb.o \ battery-gb.o diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 844ab8a..a0af9a2 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -32,6 +32,7 @@ enum greybus_protocol { GREYBUS_PROTOCOL_HID = 0x05, GREYBUS_PROTOCOL_SDIO = 0x06, GREYBUS_PROTOCOL_BATTERY = 0x08, + GREYBUS_PROTOCOL_PWM = 0x09, GREYBUS_PROTOCOL_LED = 0x0e, /* ... */ GREYBUS_PROTOCOL_VENDOR = 0xff, diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index 93e0af3..8df2b4e 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -177,6 +177,10 @@ bool gb_protocol_init(void) pr_err("error initializing i2c protocol\n"); ret = false; } + if (!gb_pwm_protocol_init()) { + pr_err("error initializing pwm protocol\n"); + ret = false; + } if (!gb_uart_protocol_init()) { pr_err("error initializing uart protocol\n"); ret = false; diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index a236401..f57f0db 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -55,6 +55,9 @@ extern void gb_gpio_protocol_exit(void); extern bool gb_i2c_protocol_init(void); extern void gb_i2c_protocol_exit(void); +extern bool gb_pwm_protocol_init(void); +extern void gb_pwm_protocol_exit(void); + extern bool gb_uart_protocol_init(void); extern void gb_uart_protocol_exit(void); diff --git a/drivers/staging/greybus/pwm-gb.c b/drivers/staging/greybus/pwm-gb.c new file mode 100644 index 0000000..44a4f64 --- /dev/null +++ b/drivers/staging/greybus/pwm-gb.c @@ -0,0 +1,531 @@ +/* + * PWM Greybus driver. + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include "greybus.h" + +struct gb_pwm_chip { + struct gb_connection *connection; + u8 version_major; + u8 version_minor; + u8 pwm_max; /* max pwm number */ + + struct pwm_chip chip; + struct pwm_chip *pwm; +}; +#define pwm_chip_to_gb_pwm_chip(chip) \ + container_of(chip, struct gb_pwm_chip, chip) + +/* Version of the Greybus PWM protocol we support */ +#define GB_PWM_VERSION_MAJOR 0x00 +#define GB_PWM_VERSION_MINOR 0x01 + +/* Greybus PWM request types */ +#define GB_PWM_TYPE_INVALID 0x00 +#define GB_PWM_TYPE_PROTOCOL_VERSION 0x01 +#define GB_PWM_TYPE_PWM_COUNT 0x02 +#define GB_PWM_TYPE_ACTIVATE 0x03 +#define GB_PWM_TYPE_DEACTIVATE 0x04 +#define GB_PWM_TYPE_CONFIG 0x05 +#define GB_PWM_TYPE_POLARITY 0x06 +#define GB_PWM_TYPE_ENABLE 0x07 +#define GB_PWM_TYPE_DISABLE 0x08 +#define GB_PWM_TYPE_RESPONSE 0x80 /* OR'd with rest */ + +struct gb_pwm_simple_response { + __u8 status; +}; + +/* version request has no payload */ +struct gb_pwm_proto_version_response { + __u8 status; + __u8 major; + __u8 minor; +}; + +/* pwm count request has no payload */ +struct gb_pwm_count_response { + __u8 status; + __u8 count; +}; + +struct gb_pwm_activate_request { + __u8 which; +}; + +struct gb_pwm_deactivate_request { + __u8 which; +}; + +struct gb_pwm_config_request { + __u8 which; + __u32 duty; + __u32 period; +}; + +struct gb_pwm_polarity_request { + __u8 which; + __u8 polarity; +}; + +struct gb_pwm_enable_request { + __u8 which; +}; + +struct gb_pwm_disable_request { + __u8 which; +}; + +/* + * This request only uses the connection field, and if successful, + * fills in the major and minor protocol version of the target. + */ +static int gb_pwm_proto_version_operation(struct gb_pwm_chip *pwmc) +{ + struct gb_connection *connection = pwmc->connection; + struct gb_operation *operation; + struct gb_pwm_proto_version_response *response; + int ret; + + /* protocol version request has no payload */ + operation = gb_operation_create(connection, + GB_PWM_TYPE_PROTOCOL_VERSION, + 0, sizeof(*response)); + if (!operation) + return -ENOMEM; + + /* Synchronous operation--no callback */ + ret = gb_operation_request_send(operation, NULL); + if (ret) { + pr_err("version operation failed (%d)\n", ret); + goto out; + } + + response = operation->response_payload; + if (response->status) { + gb_connection_err(connection, "version response %hhu", + response->status); + ret = -EIO; + } else { + if (response->major > GB_PWM_VERSION_MAJOR) { + pr_err("unsupported major version (%hhu > %hhu)\n", + response->major, GB_PWM_VERSION_MAJOR); + ret = -ENOTSUPP; + goto out; + } + pwmc->version_major = response->major; + pwmc->version_minor = response->minor; + } +out: + gb_operation_destroy(operation); + + return ret; +} + +static int gb_pwm_count_operation(struct gb_pwm_chip *pwmc) +{ + struct gb_connection *connection = pwmc->connection; + struct gb_operation *operation; + struct gb_pwm_count_response *response; + int ret; + + /* pwm count request has no payload */ + operation = gb_operation_create(connection, GB_PWM_TYPE_PWM_COUNT, + 0, sizeof(*response)); + if (!operation) + return -ENOMEM; + + /* Synchronous operation--no callback */ + ret = gb_operation_request_send(operation, NULL); + if (ret) { + pr_err("line count operation failed (%d)\n", ret); + goto out; + } + + response = operation->response_payload; + if (response->status) { + gb_connection_err(connection, "pwm count response %hhu", + response->status); + ret = -EIO; + } else + pwmc->pwm_max = response->count; +out: + gb_operation_destroy(operation); + + return ret; +} + +static int gb_pwm_activate_operation(struct gb_pwm_chip *pwmc, + u8 which) +{ + struct gb_connection *connection = pwmc->connection; + struct gb_operation *operation; + struct gb_pwm_activate_request *request; + struct gb_pwm_simple_response *response; + int ret; + + if (which > pwmc->pwm_max) + return -EINVAL; + + /* activate response has no payload */ + operation = gb_operation_create(connection, GB_PWM_TYPE_ACTIVATE, + sizeof(*request), sizeof(*response)); + if (!operation) + return -ENOMEM; + request = operation->request_payload; + request->which = which; + + /* Synchronous operation--no callback */ + ret = gb_operation_request_send(operation, NULL); + if (ret) { + pr_err("activate operation failed (%d)\n", ret); + goto out; + } + + response = operation->response_payload; + if (response->status) { + gb_connection_err(connection, "activate response %hhu", + response->status); + ret = -EIO; + } +out: + gb_operation_destroy(operation); + + return ret; +} + +static int gb_pwm_deactivate_operation(struct gb_pwm_chip *pwmc, + u8 which) +{ + struct gb_connection *connection = pwmc->connection; + struct gb_operation *operation; + struct gb_pwm_deactivate_request *request; + struct gb_pwm_simple_response *response; + int ret; + + if (which > pwmc->pwm_max) + return -EINVAL; + + /* deactivate response has no payload */ + operation = gb_operation_create(connection, GB_PWM_TYPE_DEACTIVATE, + sizeof(*request), sizeof(*response)); + if (!operation) + return -ENOMEM; + request = operation->request_payload; + request->which = which; + + /* Synchronous operation--no callback */ + ret = gb_operation_request_send(operation, NULL); + if (ret) { + pr_err("deactivate operation failed (%d)\n", ret); + goto out; + } + + response = operation->response_payload; + if (response->status) { + gb_connection_err(connection, "deactivate response %hhu", + response->status); + ret = -EIO; + } +out: + gb_operation_destroy(operation); + + return ret; +} + +static int gb_pwm_config_operation(struct gb_pwm_chip *pwmc, + u8 which, u32 duty, u32 period) +{ + struct gb_connection *connection = pwmc->connection; + struct gb_operation *operation; + struct gb_pwm_config_request *request; + struct gb_pwm_simple_response *response; + int ret; + + if (which > pwmc->pwm_max) + return -EINVAL; + + operation = gb_operation_create(connection, GB_PWM_TYPE_CONFIG, + sizeof(*request), sizeof(*response)); + if (!operation) + return -ENOMEM; + request = operation->request_payload; + request->which = which; + request->duty = duty; + request->period = period; + + /* Synchronous operation--no callback */ + ret = gb_operation_request_send(operation, NULL); + if (ret) { + pr_err("config operation failed (%d)\n", ret); + goto out; + } + + response = operation->response_payload; + if (response->status) { + gb_connection_err(connection, "config response %hhu", + response->status); + ret = -EIO; + } +out: + gb_operation_destroy(operation); + + return ret; +} + + +static int gb_pwm_set_polarity_operation(struct gb_pwm_chip *pwmc, + u8 which, u8 polarity) +{ + struct gb_connection *connection = pwmc->connection; + struct gb_operation *operation; + struct gb_pwm_polarity_request *request; + struct gb_pwm_simple_response *response; + int ret; + + if (which > pwmc->pwm_max) + return -EINVAL; + + operation = gb_operation_create(connection, GB_PWM_TYPE_POLARITY, + sizeof(*request), sizeof(*response)); + if (!operation) + return -ENOMEM; + request = operation->request_payload; + request->which = which; + request->polarity = polarity; + + /* Synchronous operation--no callback */ + ret = gb_operation_request_send(operation, NULL); + if (ret) { + pr_err("set polarity operation failed (%d)\n", ret); + goto out; + } + + response = operation->response_payload; + if (response->status) { + gb_connection_err(connection, "set polarity response %hhu", + response->status); + ret = -EIO; + } +out: + gb_operation_destroy(operation); + + return ret; +} + +static int gb_pwm_enable_operation(struct gb_pwm_chip *pwmc, + u8 which) +{ + struct gb_connection *connection = pwmc->connection; + struct gb_operation *operation; + struct gb_pwm_enable_request *request; + struct gb_pwm_simple_response *response; + int ret; + + if (which > pwmc->pwm_max) + return -EINVAL; + + /* enable response has no payload */ + operation = gb_operation_create(connection, GB_PWM_TYPE_ENABLE, + sizeof(*request), sizeof(*response)); + if (!operation) + return -ENOMEM; + request = operation->request_payload; + request->which = which; + + /* Synchronous operation--no callback */ + ret = gb_operation_request_send(operation, NULL); + if (ret) { + pr_err("enable operation failed (%d)\n", ret); + goto out; + } + + response = operation->response_payload; + if (response->status) { + gb_connection_err(connection, "enable response %hhu", + response->status); + ret = -EIO; + } +out: + gb_operation_destroy(operation); + + return ret; +} + +static int gb_pwm_disable_operation(struct gb_pwm_chip *pwmc, + u8 which) +{ + struct gb_connection *connection = pwmc->connection; + struct gb_operation *operation; + struct gb_pwm_disable_request *request; + struct gb_pwm_simple_response *response; + int ret; + + if (which > pwmc->pwm_max) + return -EINVAL; + + /* disable response has no payload */ + operation = gb_operation_create(connection, GB_PWM_TYPE_DISABLE, + sizeof(*request), sizeof(*response)); + if (!operation) + return -ENOMEM; + request = operation->request_payload; + request->which = which; + + /* Synchronous operation--no callback */ + ret = gb_operation_request_send(operation, NULL); + if (ret) { + pr_err("disable operation failed (%d)\n", ret); + goto out; + } + + response = operation->response_payload; + if (response->status) { + gb_connection_err(connection, "disable response %hhu", + response->status); + ret = -EIO; + } +out: + gb_operation_destroy(operation); + + return ret; +} + +static int gb_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); + + return gb_pwm_activate_operation(pwmc, pwm->hwpwm); +}; + +static void gb_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); + + if (test_bit(PWMF_ENABLED, &pwm->flags)) + dev_warn(chip->dev, "freeing PWM device without disabling\n"); + + gb_pwm_deactivate_operation(pwmc, pwm->hwpwm); +} + +static int gb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, + int duty_ns, int period_ns) +{ + struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); + + return gb_pwm_config_operation(pwmc, pwm->hwpwm, duty_ns, period_ns); +}; + +static int gb_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm, + enum pwm_polarity polarity) +{ + struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); + + return gb_pwm_set_polarity_operation(pwmc, pwm->hwpwm, polarity); +}; + +static int gb_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); + + return gb_pwm_enable_operation(pwmc, pwm->hwpwm); +}; + +static void gb_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); + + gb_pwm_disable_operation(pwmc, pwm->hwpwm); +}; + +static const struct pwm_ops gb_pwm_ops = { + .request = gb_pwm_request, + .free = gb_pwm_free, + .config = gb_pwm_config, + .set_polarity = gb_pwm_set_polarity, + .enable = gb_pwm_enable, + .disable = gb_pwm_disable, + .owner = THIS_MODULE, +}; + +static int gb_pwm_connection_init(struct gb_connection *connection) +{ + struct gb_pwm_chip *pwmc; + struct pwm_chip *pwm; + int ret; + + pwmc = kzalloc(sizeof(*pwmc), GFP_KERNEL); + if (!pwmc) + return -ENOMEM; + pwmc->connection = connection; + + /* Check for compatible protocol version */ + ret = gb_pwm_proto_version_operation(pwmc); + if (ret) + goto out_err; + + /* Query number of pwms present */ + ret = gb_pwm_count_operation(pwmc); + if (ret) + goto out_err; + + pwm = &pwmc->chip; + + pwm->dev = &connection->dev; + pwm->ops = &gb_pwm_ops; + pwm->base = -1; /* Allocate base dynamically */ + pwm->npwm = pwmc->pwm_max + 1; + pwm->can_sleep = true; /* FIXME */ + + ret = pwmchip_add(pwm); + if (ret) { + pr_err("Failed to register PWM\n"); + return ret; + } + connection->private = pwmc; + + return 0; +out_err: + kfree(pwmc); + return ret; +} + +static void gb_pwm_connection_exit(struct gb_connection *connection) +{ + struct gb_pwm_chip *pwmc = connection->private; + + if (!pwmc) + return; + + pwmchip_remove(&pwmc->chip); + /* kref_put(pwmc->connection) */ + kfree(pwmc); +} + +static struct gb_protocol pwm_protocol = { + .id = GREYBUS_PROTOCOL_PWM, + .major = 0, + .minor = 1, + .connection_init = gb_pwm_connection_init, + .connection_exit = gb_pwm_connection_exit, + .request_recv = NULL, /* no incoming requests */ +}; + +bool gb_pwm_protocol_init(void) +{ + return gb_protocol_register(&pwm_protocol); +} + +void gb_pwm_protocol_exit(void) +{ + gb_protocol_deregister(&pwm_protocol); +} -- cgit v0.10.2 From 3e9cb4a11831e8c0bf91cd880845b6b35051a484 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 12 Nov 2014 15:17:50 -0600 Subject: greybus: don't assume PAGE_SIZE for URB size The buffers allocated for CPort URBS are ES1_GBUF_MSG_SIZE bytes. But usb_fill_bulk_urb() passes PAGE_SIZE as its size. They happen to be the same, but the code is wrong, so fix it. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 645edbd..f82f665 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -546,7 +546,8 @@ static int ap_probe(struct usb_interface *interface, usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, es1->cport_in_endpoint), - buffer, PAGE_SIZE, cport_in_callback, es1); + buffer, ES1_GBUF_MSG_SIZE, cport_in_callback, + es1); es1->cport_in_urb[i] = urb; es1->cport_in_buffer[i] = buffer; retval = usb_submit_urb(urb, GFP_KERNEL); -- cgit v0.10.2 From 10520528fee29f29ec3d4d3f651294247b07c0a9 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 12 Nov 2014 15:17:51 -0600 Subject: greybus: fix request timeout bug This commit changed the timeout behavior for operations: 6a8732e operation: make the timeout a per-operation thing... It unfortunately left in place some code that was only appropriate for per-connection timeouts. In particular, the timer for an operation is currently getting started only if no existing operations are in flight. Fix that oversight, and schedule an operation's timer unconditionally. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 302ab00..beac353 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -65,31 +65,16 @@ static void gb_operation_insert(struct gb_operation *operation) struct rb_node *above = NULL; struct gb_operation_msg_hdr *header; unsigned long timeout; - bool start_timer; - __le16 wire_id; - /* - * Assign the operation's id, and store it in the header of - * both request and response message headers. + /* Assign the operation's id, and store it in the header of + * the request message header. */ operation->id = gb_connection_operation_id(connection); - wire_id = cpu_to_le16(operation->id); header = operation->request->transfer_buffer; - header->id = wire_id; + header->id = cpu_to_le16(operation->id); - /* OK, insert the operation into its connection's tree */ + /* OK, insert the operation into its connection's pending tree */ spin_lock_irq(&gb_operations_lock); - - /* - * We impose a time limit for requests to complete. If - * there are no requests pending there is no need for a - * timer. So if this will be the only one in flight we'll - * need to start the timer. Otherwise we just update the - * existing one to give this request a full timeout period - * to complete. - */ - start_timer = RB_EMPTY_ROOT(root); - while (*link) { struct gb_operation *other; @@ -105,11 +90,9 @@ static void gb_operation_insert(struct gb_operation *operation) rb_insert_color(node, root); spin_unlock_irq(&gb_operations_lock); + /* We impose a time limit for requests to complete. */ timeout = msecs_to_jiffies(OPERATION_TIMEOUT_DEFAULT); - if (start_timer) - schedule_delayed_work(&operation->timeout_work, timeout); - else - mod_delayed_work(system_wq, &operation->timeout_work, timeout); + schedule_delayed_work(&operation->timeout_work, timeout); } static void gb_operation_remove(struct gb_operation *operation) -- cgit v0.10.2 From 8350e7a01110cbee813256a8ebcda99bf11b8ec3 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 12 Nov 2014 15:17:52 -0600 Subject: greybus: move timeout out of gb_operation_insert() Currently, gb_operation_insert() arranges to time out a request if it takes too long. Move this out of that function and into gb_operation_request_send(), so we know it's getting set up after the request has actually be sent. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index beac353..5f3e52d 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -64,7 +64,6 @@ static void gb_operation_insert(struct gb_operation *operation) struct rb_node **link = &root->rb_node; struct rb_node *above = NULL; struct gb_operation_msg_hdr *header; - unsigned long timeout; /* Assign the operation's id, and store it in the header of * the request message header. @@ -89,10 +88,6 @@ static void gb_operation_insert(struct gb_operation *operation) rb_link_node(node, above, link); rb_insert_color(node, root); spin_unlock_irq(&gb_operations_lock); - - /* We impose a time limit for requests to complete. */ - timeout = msecs_to_jiffies(OPERATION_TIMEOUT_DEFAULT); - schedule_delayed_work(&operation->timeout_work, timeout); } static void gb_operation_remove(struct gb_operation *operation) @@ -397,6 +392,7 @@ void gb_operation_destroy(struct gb_operation *operation) int gb_operation_request_send(struct gb_operation *operation, gb_operation_callback callback) { + unsigned long timeout; int ret; if (operation->connection->state != GB_CONNECTION_STATE_ENABLED) @@ -413,6 +409,10 @@ int gb_operation_request_send(struct gb_operation *operation, ret = greybus_submit_gbuf(operation->request, GFP_KERNEL); if (ret) return ret; + + /* We impose a time limit for requests to complete. */ + timeout = msecs_to_jiffies(OPERATION_TIMEOUT_DEFAULT); + schedule_delayed_work(&operation->timeout_work, timeout); if (!callback) ret = gb_operation_wait(operation); -- cgit v0.10.2 From b8616da875ea2f36bdeaff49f1373ea1e37406f4 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 12 Nov 2014 15:17:53 -0600 Subject: greybus: simplify pending operations tracking Greg raised the alarm when I first put in the red-black tree for tracking pending operations. The reality as that we're not likely to have that many operations in flight at any one time, so the complexity of the red-black tree is most likely unwarranted. I already This pulls out the red-black tree and uses a simple list instead. A connection maintains two lists of operations. An operation starts on its connection's operations list. It is moved to the pending list when its request message is sent. And it is moved back to the operations list when the response message arrives. It is removed from whatever list it's in when the operation is destroyed. We reuse the single operation->links field for both lists. Only outgoing requests are ever "pending." Incoming requests are transient--we receive them, process them, send the response, and then we're done. Change a few function names so it's clear we're working with the pending list. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 586457f..377ac7d 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -209,7 +209,7 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, spin_unlock_irq(&gb_connections_lock); INIT_LIST_HEAD(&connection->operations); - connection->pending = RB_ROOT; + INIT_LIST_HEAD(&connection->pending); atomic_set(&connection->op_cycle, 0); return connection; diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 893c02a..861e066 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -36,7 +36,7 @@ struct gb_connection { enum gb_connection_state state; struct list_head operations; - struct rb_root pending; /* awaiting reponse */ + struct list_head pending; /* awaiting reponse */ atomic_t op_cycle; void *private; diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 5f3e52d..cc49210 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -56,13 +56,9 @@ struct gb_operation_msg_hdr { /* XXX Could be per-host device, per-module, or even per-connection */ static DEFINE_SPINLOCK(gb_operations_lock); -static void gb_operation_insert(struct gb_operation *operation) +static void gb_pending_operation_insert(struct gb_operation *operation) { struct gb_connection *connection = operation->connection; - struct rb_root *root = &connection->pending; - struct rb_node *node = &operation->node; - struct rb_node **link = &root->rb_node; - struct rb_node *above = NULL; struct gb_operation_msg_hdr *header; /* Assign the operation's id, and store it in the header of @@ -72,25 +68,13 @@ static void gb_operation_insert(struct gb_operation *operation) header = operation->request->transfer_buffer; header->id = cpu_to_le16(operation->id); - /* OK, insert the operation into its connection's pending tree */ + /* Insert the operation into its connection's pending list */ spin_lock_irq(&gb_operations_lock); - while (*link) { - struct gb_operation *other; - - above = *link; - other = rb_entry(above, struct gb_operation, node); - header = other->request->transfer_buffer; - if (other->id > operation->id) - link = &above->rb_left; - else if (other->id < operation->id) - link = &above->rb_right; - } - rb_link_node(node, above, link); - rb_insert_color(node, root); + list_move_tail(&operation->links, &connection->pending); spin_unlock_irq(&gb_operations_lock); } -static void gb_operation_remove(struct gb_operation *operation) +static void gb_pending_operation_remove(struct gb_operation *operation) { struct gb_connection *connection = operation->connection; @@ -99,29 +83,22 @@ static void gb_operation_remove(struct gb_operation *operation) /* Take us off of the list of pending operations */ spin_lock_irq(&gb_operations_lock); - rb_erase(&operation->node, &connection->pending); + list_move_tail(&operation->links, &connection->operations); spin_unlock_irq(&gb_operations_lock); - } static struct gb_operation * -gb_operation_find(struct gb_connection *connection, u16 id) +gb_pending_operation_find(struct gb_connection *connection, u16 id) { - struct gb_operation *operation = NULL; - struct rb_node *node; + struct gb_operation *operation; bool found = false; spin_lock_irq(&gb_operations_lock); - node = connection->pending.rb_node; - while (node && !found) { - operation = rb_entry(node, struct gb_operation, node); - if (operation->id > id) - node = node->rb_left; - else if (operation->id < id) - node = node->rb_right; - else + list_for_each_entry(operation, &connection->pending, links) + if (operation->id == id) { found = true; - } + break; + } spin_unlock_irq(&gb_operations_lock); return found ? operation : NULL; @@ -405,7 +382,7 @@ int gb_operation_request_send(struct gb_operation *operation, * setting the operation id and submitting the gbuf. */ operation->callback = callback; - gb_operation_insert(operation); + gb_pending_operation_insert(operation); ret = greybus_submit_gbuf(operation->request, GFP_KERNEL); if (ret) return ret; @@ -424,7 +401,6 @@ int gb_operation_request_send(struct gb_operation *operation, */ int gb_operation_response_send(struct gb_operation *operation) { - gb_operation_remove(operation); gb_operation_destroy(operation); return 0; @@ -456,12 +432,12 @@ void gb_connection_operation_recv(struct gb_connection *connection, if (header->type & GB_OPERATION_TYPE_RESPONSE) { u16 id = le16_to_cpu(header->id); - operation = gb_operation_find(connection, id); + operation = gb_pending_operation_find(connection, id); if (!operation) { gb_connection_err(connection, "operation not found"); return; } - gb_operation_remove(operation); + gb_pending_operation_remove(operation); gbuf = operation->response; gbuf->status = GB_OP_SUCCESS; /* If we got here we're good */ if (size > gbuf->transfer_buffer_length) { diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 965ad9c..4913f72 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -64,8 +64,7 @@ struct gb_operation { struct completion completion; /* Used if no callback */ struct delayed_work timeout_work; - struct list_head links; /* connection->operations */ - struct rb_node node; /* connection->pending */ + struct list_head links; /* connection->{operations,pending} */ /* These are what's used by caller */ void *request_payload; -- cgit v0.10.2 From 360a8779d96c7c592ee79d035afe9bdf05695204 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 12 Nov 2014 15:17:54 -0600 Subject: greybus: op_cycle doesn't need to be atomic We can update a connection's operation id counter under spinlock, and thereby avoid the need to maintain it in an atomic variable. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 377ac7d..bb26157 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -210,7 +210,6 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, INIT_LIST_HEAD(&connection->operations); INIT_LIST_HEAD(&connection->pending); - atomic_set(&connection->op_cycle, 0); return connection; } @@ -244,11 +243,6 @@ void gb_connection_destroy(struct gb_connection *connection) device_del(&connection->dev); } -u16 gb_connection_operation_id(struct gb_connection *connection) -{ - return (u16)(atomic_inc_return(&connection->op_cycle) & (int)U16_MAX); -} - void gb_connection_err(struct gb_connection *connection, const char *fmt, ...) { struct va_format vaf; diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 861e066..3aa8695 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -35,9 +35,9 @@ struct gb_connection { enum gb_connection_state state; + u16 op_cycle; struct list_head operations; struct list_head pending; /* awaiting reponse */ - atomic_t op_cycle; void *private; }; @@ -53,8 +53,6 @@ void gb_connection_exit(struct gb_connection *connection); struct gb_connection *gb_hd_connection_find(struct greybus_host_device *hd, u16 cport_id); -u16 gb_connection_operation_id(struct gb_connection *connection); - __printf(2, 3) void gb_connection_err(struct gb_connection *connection, const char *fmt, ...); diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index cc49210..72e5ef9 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -61,17 +61,18 @@ static void gb_pending_operation_insert(struct gb_operation *operation) struct gb_connection *connection = operation->connection; struct gb_operation_msg_hdr *header; - /* Assign the operation's id, and store it in the header of - * the request message header. + /* + * Assign the operation's id and move it into its + * connection's pending list. */ - operation->id = gb_connection_operation_id(connection); - header = operation->request->transfer_buffer; - header->id = cpu_to_le16(operation->id); - - /* Insert the operation into its connection's pending list */ spin_lock_irq(&gb_operations_lock); + operation->id = ++connection->op_cycle; list_move_tail(&operation->links, &connection->pending); spin_unlock_irq(&gb_operations_lock); + + /* Store the operation id in the request header */ + header = operation->request->transfer_buffer; + header->id = cpu_to_le16(operation->id); } static void gb_pending_operation_remove(struct gb_operation *operation) -- cgit v0.10.2 From c3cf278533c6e5f3df385afce8eb11889e58cfe3 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 12 Nov 2014 15:17:55 -0600 Subject: greybus: pass operation type on request receive When an incoming request is received, the operation type is encoded in the header and is not available in the payload. Add the operation type as a parameter to the request_recv method so the request handler knows what to do. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 72e5ef9..f455452 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -137,16 +137,17 @@ static void gb_operation_request_handle(struct gb_operation *operation) struct gb_protocol *protocol = operation->connection->protocol; struct gb_operation_msg_hdr *header; + header = operation->request->transfer_buffer; + /* * If the protocol has no incoming request handler, report * an error and mark the request bad. */ if (protocol->request_recv) { - protocol->request_recv(operation); + protocol->request_recv(header->type, operation); goto out; } - header = operation->request->transfer_buffer; gb_connection_err(operation->connection, "unexpected incoming request type 0x%02hhx\n", header->type); operation->result = GB_OP_PROTOCOL_BAD; diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index f57f0db..1aeb340 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -15,7 +15,7 @@ struct gb_operation; typedef int (*gb_connection_init_t)(struct gb_connection *); typedef void (*gb_connection_exit_t)(struct gb_connection *); -typedef void (*gb_request_recv_t)(struct gb_operation *); +typedef void (*gb_request_recv_t)(u8, struct gb_operation *); /* * Protocols having the same id but different major and/or minor -- cgit v0.10.2 From 437caa8a0c2570b4d33c873b14f348ce39b657da Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Wed, 12 Nov 2014 15:59:32 -0500 Subject: greybus: remove unused gb_connection_handler externs Remove some leftover cruft from recent refactoring of connection handlers. Signed-off-by: Matt Porter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 296a6a2..d64c181 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -252,12 +252,6 @@ void gb_gbuf_exit(void); extern struct bus_type greybus_bus_type; extern const struct attribute_group *greybus_module_groups[]; -extern struct gb_connection_handler gb_i2c_connection_handler; -extern struct gb_connection_handler gb_gpio_connection_handler; -extern struct gb_connection_handler gb_battery_connection_handler; -extern struct gb_connection_handler gb_uart_connection_handler; -extern struct gb_connection_handler gb_sdio_connection_handler; - int gb_uart_device_init(struct gb_connection *connection); void gb_uart_device_exit(struct gb_connection *connection); -- cgit v0.10.2 From e2f345ab40762ffa4456ad08956c2a74bc3a0649 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 13 Nov 2014 18:14:29 +0530 Subject: greybus: gitignore: few more additions Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/.gitignore b/drivers/staging/greybus/.gitignore index f7dc3ba..8395773 100644 --- a/drivers/staging/greybus/.gitignore +++ b/drivers/staging/greybus/.gitignore @@ -1,9 +1,11 @@ +.* *.cmd *.ko *.mod.c modules.order Module.symvers *.o +*.o.* *.swp .tmp_versions tags -- cgit v0.10.2 From 43d9431f6bc9dd7cf0f3b9e8a3cd94bb61745da8 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 13 Nov 2014 18:14:30 +0530 Subject: greybus: manifest: no need to initialize 'result' Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 5634639..ebc2494 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -328,7 +328,7 @@ bool gb_manifest_parse(struct gb_module *gmod, void *data, size_t size) struct manifest_desc *module_desc = NULL; u16 manifest_size; u32 found = 0; - bool result = false; + bool result; /* we have to have at _least_ the manifest header */ if (size <= sizeof(manifest->header)) { -- cgit v0.10.2 From 4ed16a81c179d8e72bd127067e344959d1d6b1be Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 13 Nov 2014 18:14:31 +0530 Subject: greybus: manifest: initialize variable during definition Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index ebc2494..964f85ed 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -183,10 +183,9 @@ static u32 gb_manifest_parse_cports(struct gb_interface *interface) struct greybus_descriptor_cport *desc_cport; u8 protocol_id; u16 cport_id; - bool found; + bool found = false; /* Find a cport descriptor */ - found = false; list_for_each_entry(descriptor, &manifest_descs, links) { if (descriptor->type == GREYBUS_TYPE_CPORT) { desc_cport = descriptor->data; -- cgit v0.10.2 From 50fc08f8c023d1e698207342e003f1b6d4bca1f5 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 13 Nov 2014 18:14:32 +0530 Subject: greybus: manifest: don't free unallocated resources Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 964f85ed..777abf4 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -268,7 +268,7 @@ static bool gb_manifest_parse_module(struct gb_module *gmod, gmod->product_string = gb_string_get(desc_module->product_stringid); if (IS_ERR(gmod->product_string)) { - goto out_err; + goto out_free_vendor_string; } gmod->vendor = le16_to_cpu(desc_module->vendor); @@ -289,6 +289,7 @@ static bool gb_manifest_parse_module(struct gb_module *gmod, out_err: kfree(gmod->product_string); gmod->product_string = NULL; +out_free_vendor_string: kfree(gmod->vendor_string); gmod->vendor_string = NULL; -- cgit v0.10.2 From 35a52cafbc214844f5940fe756bc2af01d987626 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 13 Nov 2014 18:14:33 +0530 Subject: greybus: Fix missing gb_protocol_exit() on gb_exit() Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 1d05c35..7428206 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -302,6 +302,7 @@ error_bus: static void __exit gb_exit(void) { + gb_protocol_exit(); gb_operation_exit(); gb_gbuf_exit(); gb_ap_exit(); -- cgit v0.10.2 From 669f5faf84998227b2604d310a7f33ac90189b8c Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 13 Nov 2014 18:14:34 +0530 Subject: greybus: don't set ->dev.driver to NULL when it is already NULL Parent objects of 'dev' are allocated with kzalloc() and so all of their fields are initialized with 0. Hence no need of marking them NULL again. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index bb26157..5373f44 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -185,7 +185,6 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, connection->state = GB_CONNECTION_STATE_DISABLED; connection->dev.parent = &interface->dev; - connection->dev.driver = NULL; connection->dev.bus = &greybus_bus_type; connection->dev.type = &greybus_connection_type; connection->dev.groups = connection_groups; diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index eb63f63..f7f9bfd 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -69,7 +69,6 @@ gb_interface_create(struct gb_module *gmod, u8 interface_id) /* Build up the interface device structures and register it with the * driver core */ interface->dev.parent = &gmod->dev; - interface->dev.driver = NULL; interface->dev.bus = &greybus_bus_type; interface->dev.type = &greybus_interface_type; interface->dev.groups = interface_groups; diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index 9cf98cd..f5d7dc8 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -90,7 +90,6 @@ struct gb_module *gb_module_create(struct greybus_host_device *hd, u8 module_id) spin_unlock_irq(&gb_modules_lock); gmod->dev.parent = hd->parent; - gmod->dev.driver = NULL; gmod->dev.bus = &greybus_bus_type; gmod->dev.type = &greybus_module_type; gmod->dev.groups = greybus_module_groups; -- cgit v0.10.2 From 37d8afc42b30e8883a30eb2dadb1ff4f94caa33b Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 13 Nov 2014 18:14:35 +0530 Subject: greybus: debug: mark debug messages with pr_debug() instead of printk Also fix indentation. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index 40833fa..473df4d4 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -167,8 +167,10 @@ static int gb_gpio_proto_version_operation(struct gb_gpio_controller *gb_gpio_co } gb_gpio_controller->version_major = response->major; gb_gpio_controller->version_minor = response->minor; -printk("%s: version_major = %u version_minor = %u\n", __func__, - gb_gpio_controller->version_major, gb_gpio_controller->version_minor); + + pr_debug("%s: version_major = %u version_minor = %u\n", __func__, + gb_gpio_controller->version_major, + gb_gpio_controller->version_minor); } out: gb_operation_destroy(operation); @@ -204,8 +206,9 @@ static int gb_gpio_line_count_operation(struct gb_gpio_controller *gb_gpio_contr ret = -EIO; } else { gb_gpio_controller->line_max = response->count; -printk("%s: count = %u\n", __func__, - gb_gpio_controller->line_max + 1); + + pr_debug("%s: count = %u\n", __func__, + gb_gpio_controller->line_max + 1); } out: gb_operation_destroy(operation); @@ -248,7 +251,8 @@ static int gb_gpio_activate_operation(struct gb_gpio_controller *gb_gpio_control ret = -EIO; } else { gb_gpio_controller->lines[which].active = true; -printk("%s: %u is now active\n", __func__, which); + + pr_debug("%s: %u is now active\n", __func__, which); } out: gb_operation_destroy(operation); @@ -291,7 +295,7 @@ static int gb_gpio_deactivate_operation(struct gb_gpio_controller *gb_gpio_contr ret = -EIO; } else { gb_gpio_controller->lines[which].active = false; -printk("%s: %u is now inactive\n", __func__, which); + pr_debug("%s: %u is now inactive\n", __func__, which); } out: gb_operation_destroy(operation); @@ -338,8 +342,8 @@ static int gb_gpio_get_direction_operation(struct gb_gpio_controller *gb_gpio_co pr_warn("gpio %u direction was %u (should be 0 or 1)\n", which, direction); gb_gpio_controller->lines[which].direction = direction ? 1 : 0; -printk("%s: direction of %u is %s\n", __func__, which, - direction ? "in" : "out"); + pr_debug("%s: direction of %u is %s\n", __func__, which, + direction ? "in" : "out"); } out: gb_operation_destroy(operation); @@ -382,7 +386,7 @@ static int gb_gpio_direction_in_operation(struct gb_gpio_controller *gb_gpio_con ret = -EIO; } else { gb_gpio_controller->lines[which].direction = 1; -printk("%s: direction of %u is now in\n", __func__, which); + pr_debug("%s: direction of %u is now in\n", __func__, which); } out: gb_operation_destroy(operation); @@ -426,8 +430,8 @@ static int gb_gpio_direction_out_operation(struct gb_gpio_controller *gb_gpio_co ret = -EIO; } else { gb_gpio_controller->lines[which].direction = 0; -printk("%s: direction of %u is now out, value %s\n", __func__, - which, value_high ? "high" : "low"); + pr_debug("%s: direction of %u is now out, value %s\n", __func__, + which, value_high ? "high" : "low"); } out: gb_operation_destroy(operation); @@ -475,8 +479,9 @@ static int gb_gpio_get_value_operation(struct gb_gpio_controller *gb_gpio_contro which, value); gb_gpio_controller->lines[which].value = value ? 1 : 0; /* XXX should this set direction to out? */ -printk("%s: value of %u is %s\n", __func__, - which, gb_gpio_controller->lines[which].value ? "high" : "low"); + pr_debug("%s: value of %u is %s\n", __func__, which, + gb_gpio_controller->lines[which].value ? "high" : + "low"); } out: gb_operation_destroy(operation); @@ -521,8 +526,9 @@ static int gb_gpio_set_value_operation(struct gb_gpio_controller *gb_gpio_contro } else { /* XXX should this set direction to out? */ gb_gpio_controller->lines[which].value = request->value; -printk("%s: out value of %u is now %s\n", __func__, - which, gb_gpio_controller->lines[which].value ? "high" : "low"); + pr_debug("%s: out value of %u is now %s\n", __func__, which, + gb_gpio_controller->lines[which].value ? "high" : + "low"); } out: gb_operation_destroy(operation); @@ -566,8 +572,8 @@ static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *gb_gpio_con ret = -EIO; } else { gb_gpio_controller->lines[which].debounce_usec = le16_to_cpu(request->usec); - printk("%s: debounce of %u is now %hu usec\n", __func__, which, - gb_gpio_controller->lines[which].debounce_usec); + pr_debug("%s: debounce of %u is now %hu usec\n", __func__, which, + gb_gpio_controller->lines[which].debounce_usec); } out: gb_operation_destroy(operation); @@ -582,7 +588,7 @@ static int gb_gpio_request(struct gpio_chip *chip, unsigned offset) if (offset < 0 || offset >= chip->ngpio) return -EINVAL; - printk("passed check\n"); + pr_debug("%s: passed check\n", __func__); ret = gb_gpio_activate_operation(gb_gpio_controller, (u8)offset); if (ret) ; /* return ret; */ diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index f455452..7fcd8e4 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -236,7 +236,7 @@ static void operation_timeout(struct work_struct *work) struct gb_operation *operation; operation = container_of(work, struct gb_operation, timeout_work.work); - printk("timeout!\n"); + pr_debug("%s: timeout!\n", __func__); operation->result = GB_OP_TIMEOUT; gb_operation_complete(operation); -- cgit v0.10.2 From 132d03ea8989949ed40d52ea6bd4c5aaa083381b Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 13 Nov 2014 18:14:36 +0530 Subject: greybus: sysfs: generalize gb_module_attr() to capture more cases Most of the attribute routines are created with gb_module_attr() and few are left out because they weren't printing 32 bit hexadecimal values. Extend gb_module_attr() to cover more cases. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/sysfs.c b/drivers/staging/greybus/sysfs.c index 42d54eb..44b0c70 100644 --- a/drivers/staging/greybus/sysfs.c +++ b/drivers/staging/greybus/sysfs.c @@ -20,55 +20,28 @@ #include "kernel_ver.h" /* Module fields */ -#define gb_module_attr(field) \ +#define gb_module_attr(field, type) \ static ssize_t module_##field##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ struct gb_module *gmod = to_gb_module(dev); \ - return sprintf(buf, "%x\n", gmod->field); \ + return sprintf(buf, "%"#type"\n", gmod->field); \ } \ static DEVICE_ATTR_RO(module_##field) -gb_module_attr(vendor); -gb_module_attr(product); -gb_module_attr(version); - -static ssize_t module_serial_number_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct gb_module *gmod = to_gb_module(dev); - - return sprintf(buf, "%llX\n", (unsigned long long)gmod->unique_id); -} -static DEVICE_ATTR_RO(module_serial_number); - -static ssize_t module_vendor_string_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct gb_module *gmod = to_gb_module(dev); - - return sprintf(buf, "%s", gmod->vendor_string); -} -static DEVICE_ATTR_RO(module_vendor_string); - -static ssize_t module_product_string_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct gb_module *gmod = to_gb_module(dev); - - return sprintf(buf, "%s", gmod->product_string); -} -static DEVICE_ATTR_RO(module_product_string); +gb_module_attr(vendor, x); +gb_module_attr(product, x); +gb_module_attr(version, x); +gb_module_attr(unique_id, llX); +gb_module_attr(vendor_string, s); +gb_module_attr(product_string, s); static struct attribute *module_attrs[] = { &dev_attr_module_vendor.attr, &dev_attr_module_product.attr, &dev_attr_module_version.attr, - &dev_attr_module_serial_number.attr, + &dev_attr_module_unique_id.attr, &dev_attr_module_vendor_string.attr, &dev_attr_module_product_string.attr, NULL, -- cgit v0.10.2 From 0a68a16b914472aa3c9dbac81df501b9c8dffb86 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 13 Nov 2014 18:14:37 +0530 Subject: greybus: module: free resources properly on failures Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index f5d7dc8..8cbe65b 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -85,10 +85,6 @@ struct gb_module *gb_module_create(struct greybus_host_device *hd, u8 module_id) gmod->module_id = module_id; INIT_LIST_HEAD(&gmod->interfaces); - spin_lock_irq(&gb_modules_lock); - list_add_tail(&gmod->links, &hd->modules); - spin_unlock_irq(&gb_modules_lock); - gmod->dev.parent = hd->parent; gmod->dev.bus = &greybus_bus_type; gmod->dev.type = &greybus_module_type; @@ -102,9 +98,14 @@ struct gb_module *gb_module_create(struct greybus_host_device *hd, u8 module_id) pr_err("failed to add module device for id 0x%02hhx\n", module_id); put_device(&gmod->dev); + kfree(gmod); return NULL; } + spin_lock_irq(&gb_modules_lock); + list_add_tail(&gmod->links, &hd->modules); + spin_unlock_irq(&gb_modules_lock); + return gmod; } -- cgit v0.10.2 From b97c46ecaf27c815469f5f7e6a325f0cb53869fe Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 13 Nov 2014 18:14:38 +0530 Subject: greybus: interface: free resources properly on failures Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index f7f9bfd..537ef80 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -79,6 +79,7 @@ gb_interface_create(struct gb_module *gmod, u8 interface_id) if (retval) { pr_err("failed to add interface device for id 0x%02hhx\n", interface_id); + put_device(&interface->dev); kfree(interface); return NULL; } -- cgit v0.10.2 From a68bd742c068924950d17e2c5122fb9e710360ed Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 13 Nov 2014 18:14:39 +0530 Subject: greybus: connection: free resources properly on failures Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 5373f44..32f1ec5 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -199,6 +199,7 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, gb_connection_hd_cport_id_free(connection); gb_protocol_put(connection->protocol); put_device(&connection->dev); + kfree(connection); return NULL; } -- cgit v0.10.2 From 85f3aeeda6047a42cd16782692864da697e53c85 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 13 Nov 2014 18:14:40 +0530 Subject: greybus: manifest: remove extra loop for finding module descriptor Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 777abf4..6b2c5ee 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -54,7 +54,8 @@ static void release_manifest_descriptors(void) * Returns the number of bytes consumed by the descriptor, or a * negative errno. */ -static int identify_descriptor(struct greybus_descriptor *desc, size_t size) +static int identify_descriptor(struct greybus_descriptor *desc, size_t size, + bool *is_module) { struct greybus_descriptor_header *desc_header = &desc->header; struct manifest_desc *descriptor; @@ -79,6 +80,7 @@ static int identify_descriptor(struct greybus_descriptor *desc, size_t size) desc_size); return -EINVAL; } + *is_module = true; break; case GREYBUS_TYPE_STRING: expected_size = sizeof(struct greybus_descriptor_header); @@ -309,7 +311,7 @@ out_free_vendor_string: * the descriptors it contains, keeping track for each its type * and the location size of its data in the buffer. * - * Next we scan the descriptors, looking for a module descriptor; + * We also identify the module descriptor during this iteration, * there must be exactly one of those. When found, we record the * information it contains, and then remove that descriptor (and any * string descriptors it refers to) from further consideration. @@ -359,8 +361,9 @@ bool gb_manifest_parse(struct gb_module *gmod, void *data, size_t size) size -= sizeof(*header); while (size) { int desc_size; + bool is_module = false; - desc_size = identify_descriptor(desc, size); + desc_size = identify_descriptor(desc, size, &is_module); if (desc_size <= 0) { if (!desc_size) pr_err("zero-sized manifest descriptor\n"); @@ -369,19 +372,17 @@ bool gb_manifest_parse(struct gb_module *gmod, void *data, size_t size) } desc = (struct greybus_descriptor *)((char *)desc + desc_size); size -= desc_size; - } - /* There must be a single module descriptor */ - list_for_each_entry(descriptor, &manifest_descs, links) { - if (descriptor->type == GREYBUS_TYPE_MODULE) - if (!found++) + if (is_module) { + if (++found > 1) { + pr_err("manifest must have 1 module descriptor (%u found)\n", + found); + result = false; + goto out; + } else { module_desc = descriptor; - } - if (found != 1) { - pr_err("manifest must have 1 module descriptor (%u found)\n", - found); - result = false; - goto out; + } + } } /* Parse the module manifest, starting with the module descriptor */ -- cgit v0.10.2 From 219871e25270bcb8082a98264c48b78725a74335 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 14 Nov 2014 09:47:39 +0530 Subject: greybus: manifest: improve print message Suggested-by: Alex Elder Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 6b2c5ee..d1357a2 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -375,8 +375,7 @@ bool gb_manifest_parse(struct gb_module *gmod, void *data, size_t size) if (is_module) { if (++found > 1) { - pr_err("manifest must have 1 module descriptor (%u found)\n", - found); + pr_err("multiple module descriptors found in manifest\n"); result = false; goto out; } else { -- cgit v0.10.2 From 3dc05f187185cb5795054b1a7f490fe695c779fe Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 14 Nov 2014 17:24:58 +0530 Subject: greybus: core: remove unnecessary braces Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 7428206..0f4a18b 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -181,9 +181,8 @@ static void gb_remove_modules(struct greybus_host_device *hd) { struct gb_module *gmod, *temp; - list_for_each_entry_safe(gmod, temp, &hd->modules, links) { + list_for_each_entry_safe(gmod, temp, &hd->modules, links) gb_module_destroy(gmod); - } } static DEFINE_MUTEX(hd_mutex); -- cgit v0.10.2 From 95bd99def54d972b2d528a91acb0152da0cdaeec Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 14 Nov 2014 17:24:59 +0530 Subject: greybus: core: use 'drv' instead of dev->driver Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 0f4a18b..4604649 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -32,7 +32,7 @@ EXPORT_SYMBOL_GPL(greybus_disabled); static int greybus_module_match(struct device *dev, struct device_driver *drv) { - struct greybus_driver *driver = to_greybus_driver(dev->driver); + struct greybus_driver *driver = to_greybus_driver(drv); struct gb_module *gmod = to_gb_module(dev); const struct greybus_module_id *id; -- cgit v0.10.2 From 837b3b7c04c1df9dbf5e8dc4b15aaa28e7b6439b Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 14 Nov 2014 17:25:00 +0530 Subject: greybus: operation: free resources in the reverse order of allocation Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 7fcd8e4..603697e 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -493,8 +493,8 @@ int gb_operation_init(void) void gb_operation_exit(void) { - kmem_cache_destroy(gb_operation_cache); - gb_operation_cache = NULL; destroy_workqueue(gb_operation_recv_workqueue); gb_operation_recv_workqueue = NULL; + kmem_cache_destroy(gb_operation_cache); + gb_operation_cache = NULL; } -- cgit v0.10.2 From f66832dae0ad61732d07c40a3c81adbc935fa1b3 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 14 Nov 2014 17:25:01 +0530 Subject: greybus: nullify dangling pointers Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index a8cd7e7..9d743f2 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -367,6 +367,7 @@ int gb_ap_init(void) void gb_ap_exit(void) { destroy_workqueue(ap_workqueue); + ap_workqueue = NULL; } diff --git a/drivers/staging/greybus/debugfs.c b/drivers/staging/greybus/debugfs.c index ef292f4..4755a36 100644 --- a/drivers/staging/greybus/debugfs.c +++ b/drivers/staging/greybus/debugfs.c @@ -26,4 +26,5 @@ int gb_debugfs_init(void) void gb_debugfs_cleanup(void) { debugfs_remove_recursive(gb_debug_root); + gb_debug_root = NULL; } diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 8b5a438..d5cfb38 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -136,4 +136,5 @@ int gb_gbuf_init(void) void gb_gbuf_exit(void) { kmem_cache_destroy(gbuf_head_cache); + gbuf_head_cache = NULL; } -- cgit v0.10.2 From 38d61ddf95734c3fe69c31b867cc26932db63235 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 14 Nov 2014 17:25:02 +0530 Subject: greybus: connection: try cancelling operations only if list isn't empty Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 32f1ec5..4515bcd 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -226,11 +226,10 @@ void gb_connection_destroy(struct gb_connection *connection) return; /* XXX Need to wait for any outstanding requests to complete */ - WARN_ON(!list_empty(&connection->operations)); - - list_for_each_entry_safe(operation, next, &connection->operations, - links) { - gb_operation_cancel(operation); + if (WARN_ON(!list_empty(&connection->operations))) { + list_for_each_entry_safe(operation, next, + &connection->operations, links) + gb_operation_cancel(operation); } spin_lock_irq(&gb_connections_lock); list_del(&connection->interface_links); -- cgit v0.10.2 From 1dd90df403692f718564638543e73b6d1f734f70 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 14 Nov 2014 17:25:03 +0530 Subject: greybus: manifest: make sure manifest_descs list is empty before parsing manifest Just an extra check to make sure the list isn't corrupted. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index d1357a2..4b85c53 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -332,6 +332,10 @@ bool gb_manifest_parse(struct gb_module *gmod, void *data, size_t size) u32 found = 0; bool result; + /* Manifest descriptor list should be empty here */ + if (WARN_ON(!list_empty(&manifest_descs))) + return false; + /* we have to have at _least_ the manifest header */ if (size <= sizeof(manifest->header)) { pr_err("short manifest (%zu)\n", size); -- cgit v0.10.2 From ab34291da5537f8b1e037873591d6a5d54e00749 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 14 Nov 2014 17:25:04 +0530 Subject: greybus: connection: fix duplicating naming in _gb_hd_connection_insert() Though this doesn't cause any logical issues as far as the behavior of the routine is concerned as the local variable would be considered inside the 'while' loop. But its better not to use the same name for variables at different levels. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 4515bcd..f460df4 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -23,13 +23,13 @@ static void _gb_hd_connection_insert(struct greybus_host_device *hd, u16 cport_id = connection->hd_cport_id; while (*link) { - struct gb_connection *connection; + struct gb_connection *_connection; above = *link; - connection = rb_entry(above, struct gb_connection, hd_node); - if (connection->hd_cport_id > cport_id) + _connection = rb_entry(above, struct gb_connection, hd_node); + if (_connection->hd_cport_id > cport_id) link = &above->rb_left; - else if (connection->hd_cport_id < cport_id) + else if (_connection->hd_cport_id < cport_id) link = &above->rb_right; } rb_link_node(node, above, link); -- cgit v0.10.2 From 577f5f974c874228573451b9a521df7962f8b7de Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 14 Nov 2014 17:25:05 +0530 Subject: greybus: core: re-use gb_module_find() in gb_remove_module() Also fix print message. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 4604649..851a302 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -162,19 +162,12 @@ err_module: void gb_remove_module(struct greybus_host_device *hd, u8 module_id) { - struct gb_module *gmod; - bool found = false; - - list_for_each_entry(gmod, &hd->modules, links) - if (gmod->module_id == module_id) { - found = true; - break; - } + struct gb_module *gmod = gb_module_find(hd, module_id); - if (found) + if (gmod) gb_module_destroy(gmod); else - dev_err(hd->parent, "module id %d remove error\n", module_id); + dev_err(hd->parent, "module id %d not found\n", module_id); } static void gb_remove_modules(struct greybus_host_device *hd) -- cgit v0.10.2 From 9ca4d62f15bc8e1977ed2c6c2dfc84449b6ab35f Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 14 Nov 2014 17:25:06 +0530 Subject: greybus: module: move gb_module_find() to a more logical location Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index 8cbe65b..22b35e4 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -44,6 +44,17 @@ const struct greybus_module_id *gb_module_match_id(struct gb_module *gmod, return NULL; } +struct gb_module *gb_module_find(struct greybus_host_device *hd, u8 module_id) +{ + struct gb_module *module; + + list_for_each_entry(module, &hd->modules, links) + if (module->module_id == module_id) + return module; + + return NULL; +} + static void greybus_module_release(struct device *dev) { struct gb_module *gmod = to_gb_module(dev); @@ -132,17 +143,6 @@ void gb_module_destroy(struct gb_module *gmod) device_del(&gmod->dev); } -struct gb_module *gb_module_find(struct greybus_host_device *hd, u8 module_id) -{ - struct gb_module *module; - - list_for_each_entry(module, &hd->modules, links) - if (module->module_id == module_id) - return module; - - return NULL; -} - int gb_module_interface_init(struct gb_module *gmod, u8 interface_id, u8 device_id) { -- cgit v0.10.2 From 676daaf45869e810dcbe97cf6996f7c8e2fb7d32 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 14 Nov 2014 17:25:07 +0530 Subject: greybus: module: move module specific code to module.c Some of module specific routines were present in core.c instead of module.c. Move them to the right place. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 851a302..be190e7 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -119,65 +119,6 @@ void greybus_deregister(struct greybus_driver *driver) EXPORT_SYMBOL_GPL(greybus_deregister); -/** - * gb_add_module - * - * Pass in a buffer that _should_ contain a Greybus module manifest - * and register a greybus device structure with the kernel core. - */ -void gb_add_module(struct greybus_host_device *hd, u8 module_id, - u8 *data, int size) -{ - struct gb_module *gmod; - - gmod = gb_module_create(hd, module_id); - if (!gmod) { - dev_err(hd->parent, "failed to create module\n"); - return; - } - - /* - * Parse the manifest and build up our data structures - * representing what's in it. - */ - if (!gb_manifest_parse(gmod, data, size)) { - dev_err(hd->parent, "manifest error\n"); - goto err_module; - } - - /* - * XXX - * We've successfully parsed the manifest. Now we need to - * allocate CPort Id's for connecting to the CPorts found on - * other modules. For each of these, establish a connection - * between the local and remote CPorts (including - * configuring the switch to allow them to communicate). - */ - - return; - -err_module: - gb_module_destroy(gmod); -} - -void gb_remove_module(struct greybus_host_device *hd, u8 module_id) -{ - struct gb_module *gmod = gb_module_find(hd, module_id); - - if (gmod) - gb_module_destroy(gmod); - else - dev_err(hd->parent, "module id %d not found\n", module_id); -} - -static void gb_remove_modules(struct greybus_host_device *hd) -{ - struct gb_module *gmod, *temp; - - list_for_each_entry_safe(gmod, temp, &hd->modules, links) - gb_module_destroy(gmod); -} - static DEFINE_MUTEX(hd_mutex); static void free_hd(struct kref *kref) diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index d64c181..284be84 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -240,6 +240,7 @@ int greybus_disabled(void); void gb_add_module(struct greybus_host_device *hd, u8 module_id, u8 *data, int size); void gb_remove_module(struct greybus_host_device *hd, u8 module_id); +void gb_remove_modules(struct greybus_host_device *hd); int greybus_svc_in(struct greybus_host_device *hd, u8 *data, int length); int gb_ap_init(void); diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index 22b35e4..9583b5a 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -143,6 +143,65 @@ void gb_module_destroy(struct gb_module *gmod) device_del(&gmod->dev); } +/** + * gb_add_module + * + * Pass in a buffer that _should_ contain a Greybus module manifest + * and register a greybus device structure with the kernel core. + */ +void gb_add_module(struct greybus_host_device *hd, u8 module_id, + u8 *data, int size) +{ + struct gb_module *gmod; + + gmod = gb_module_create(hd, module_id); + if (!gmod) { + dev_err(hd->parent, "failed to create module\n"); + return; + } + + /* + * Parse the manifest and build up our data structures + * representing what's in it. + */ + if (!gb_manifest_parse(gmod, data, size)) { + dev_err(hd->parent, "manifest error\n"); + goto err_module; + } + + /* + * XXX + * We've successfully parsed the manifest. Now we need to + * allocate CPort Id's for connecting to the CPorts found on + * other modules. For each of these, establish a connection + * between the local and remote CPorts (including + * configuring the switch to allow them to communicate). + */ + + return; + +err_module: + gb_module_destroy(gmod); +} + +void gb_remove_module(struct greybus_host_device *hd, u8 module_id) +{ + struct gb_module *gmod = gb_module_find(hd, module_id); + + if (gmod) + gb_module_destroy(gmod); + else + dev_err(hd->parent, "module id %d not found\n", module_id); +} + +void gb_remove_modules(struct greybus_host_device *hd) +{ + struct gb_module *gmod, *temp; + + list_for_each_entry_safe(gmod, temp, &hd->modules, links) + gb_module_destroy(gmod); +} + int gb_module_interface_init(struct gb_module *gmod, u8 interface_id, u8 device_id) { -- cgit v0.10.2 From 2206ea9cf8c56a0b98db3498ae5b6642a995a0a8 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 14 Nov 2014 17:25:08 +0530 Subject: greybus: interface: move gb_module_interface_init() to interface.c That's where it belong to. Also rename it in a similar way to: gb_interface_create() and gb_interface_destroy(). Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 9d743f2..990e5c0 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -146,7 +146,7 @@ static void svc_management(struct svc_function_unipro_management *management, management->link_up.module_id); return; } - ret = gb_module_interface_init(module, + ret = gb_interface_init(module, management->link_up.interface_id, management->link_up.device_id); if (ret) diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 537ef80..04c864f 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -111,6 +111,36 @@ void gb_interface_destroy(struct gb_module *gmod) spin_unlock_irq(&gb_interfaces_lock); } +int gb_interface_init(struct gb_module *gmod, u8 interface_id, u8 device_id) +{ + struct gb_interface *interface; + int ret; + + interface = gb_interface_find(gmod, interface_id); + if (!interface) { + dev_err(gmod->hd->parent, "module %hhu not found\n", + interface_id); + return -ENOENT; + } + interface->device_id = device_id; + + ret = svc_set_route_send(interface, gmod->hd); + if (ret) { + dev_err(gmod->hd->parent, "failed to set route (%d)\n", ret); + return ret; + } + + ret = gb_interface_connections_init(interface); + if (ret) { + dev_err(gmod->hd->parent, "module interface init error %d\n", + ret); + /* XXX clear route */ + return ret; + } + + return 0; +} + struct gb_interface *gb_interface_find(struct gb_module *module, u8 interface_id) { diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 50b0317..bfd1781 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -24,6 +24,7 @@ struct gb_interface { struct gb_interface *gb_interface_create(struct gb_module *gmod, u8 module_id); void gb_interface_destroy(struct gb_module *gmod); +int gb_interface_init(struct gb_module *gmod, u8 module_id, u8 device_id); struct gb_interface *gb_interface_find(struct gb_module *gmod, u8 interface_id); diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index 9583b5a..51bd5c6 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -201,34 +201,3 @@ void gb_remove_modules(struct greybus_host_device *hd) list_for_each_entry_safe(gmod, temp, &hd->modules, links) gb_module_destroy(gmod); } - -int -gb_module_interface_init(struct gb_module *gmod, u8 interface_id, u8 device_id) -{ - struct gb_interface *interface; - int ret; - - interface = gb_interface_find(gmod, interface_id); - if (!interface) { - dev_err(gmod->hd->parent, "module %hhu not found\n", - interface_id); - return -ENOENT; - } - interface->device_id = device_id; - - ret = svc_set_route_send(interface, gmod->hd); - if (ret) { - dev_err(gmod->hd->parent, "failed to set route (%d)\n", ret); - return ret; - } - - ret = gb_interface_connections_init(interface); - if (ret) { - dev_err(gmod->hd->parent, "module interface init error %d\n", - ret); - /* XXX clear route */ - return ret; - } - - return 0; -} diff --git a/drivers/staging/greybus/module.h b/drivers/staging/greybus/module.h index 74ac4fd..9e5358b 100644 --- a/drivers/staging/greybus/module.h +++ b/drivers/staging/greybus/module.h @@ -55,7 +55,4 @@ void gb_module_destroy(struct gb_module *module); struct gb_module *gb_module_find(struct greybus_host_device *hd, u8 module_id); -int gb_module_interface_init(struct gb_module *gmod, u8 module_id, - u8 device_id); - #endif /* __MODULE_H */ -- cgit v0.10.2 From b7be8d2eb354ba896034276a4ef68013f2720ba5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Nov 2014 14:37:32 -0800 Subject: greybus: Revert "manifest: improve print message" This reverts commit b8ba855506906de71df5b12b50cdbbf7259a930c. needed to revert an older change. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 4b85c53..7b0621d 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -379,7 +379,8 @@ bool gb_manifest_parse(struct gb_module *gmod, void *data, size_t size) if (is_module) { if (++found > 1) { - pr_err("multiple module descriptors found in manifest\n"); + pr_err("manifest must have 1 module descriptor (%u found)\n", + found); result = false; goto out; } else { -- cgit v0.10.2 From 86bf33afa3c1d52f01f9e12c2e26b730acb6bbd6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Nov 2014 14:37:56 -0800 Subject: greybus: Revert "manifest: remove extra loop for finding module descriptor" This reverts commit 4d1529e6687d53878b71cdcd646e28e10d62c2e8. Alex reports that this causes problems. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 7b0621d..9014611 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -54,8 +54,7 @@ static void release_manifest_descriptors(void) * Returns the number of bytes consumed by the descriptor, or a * negative errno. */ -static int identify_descriptor(struct greybus_descriptor *desc, size_t size, - bool *is_module) +static int identify_descriptor(struct greybus_descriptor *desc, size_t size) { struct greybus_descriptor_header *desc_header = &desc->header; struct manifest_desc *descriptor; @@ -80,7 +79,6 @@ static int identify_descriptor(struct greybus_descriptor *desc, size_t size, desc_size); return -EINVAL; } - *is_module = true; break; case GREYBUS_TYPE_STRING: expected_size = sizeof(struct greybus_descriptor_header); @@ -311,7 +309,7 @@ out_free_vendor_string: * the descriptors it contains, keeping track for each its type * and the location size of its data in the buffer. * - * We also identify the module descriptor during this iteration, + * Next we scan the descriptors, looking for a module descriptor; * there must be exactly one of those. When found, we record the * information it contains, and then remove that descriptor (and any * string descriptors it refers to) from further consideration. @@ -365,9 +363,8 @@ bool gb_manifest_parse(struct gb_module *gmod, void *data, size_t size) size -= sizeof(*header); while (size) { int desc_size; - bool is_module = false; - desc_size = identify_descriptor(desc, size, &is_module); + desc_size = identify_descriptor(desc, size); if (desc_size <= 0) { if (!desc_size) pr_err("zero-sized manifest descriptor\n"); @@ -376,17 +373,19 @@ bool gb_manifest_parse(struct gb_module *gmod, void *data, size_t size) } desc = (struct greybus_descriptor *)((char *)desc + desc_size); size -= desc_size; + } - if (is_module) { - if (++found > 1) { - pr_err("manifest must have 1 module descriptor (%u found)\n", - found); - result = false; - goto out; - } else { + /* There must be a single module descriptor */ + list_for_each_entry(descriptor, &manifest_descs, links) { + if (descriptor->type == GREYBUS_TYPE_MODULE) + if (!found++) module_desc = descriptor; - } - } + } + if (found != 1) { + pr_err("manifest must have 1 module descriptor (%u found)\n", + found); + result = false; + goto out; } /* Parse the module manifest, starting with the module descriptor */ -- cgit v0.10.2 From 0ac5a838811c5921783cd8da410b23ee673b7e55 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 15 Nov 2014 12:12:16 -0800 Subject: greybus: skeleton for future uevents. Implement a skeleton for the uevent framework, to be filled in later when we figure out what type of module "matching" we want to do for things (connections, interfaces, modules, etc.) Based on a patch from Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index f460df4..5927f2d 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -135,7 +135,7 @@ static void gb_connection_release(struct device *dev) kfree(connection); } -static struct device_type greybus_connection_type = { +struct device_type greybus_connection_type = { .name = "greybus_connection", .release = gb_connection_release, }; diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index be190e7..9567324 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -45,13 +45,42 @@ static int greybus_module_match(struct device *dev, struct device_driver *drv) static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) { - /* struct gb_module *gmod = to_gb_module(dev); */ + struct gb_module *gmod = NULL; + struct gb_interface *interface = NULL; + struct gb_connection *connection = NULL; + + if (is_gb_module(dev)) { + gmod = to_gb_module(dev); + } else if (is_gb_interface(dev)) { + interface = to_gb_interface(dev); + gmod = interface->gmod; + } else if (is_gb_connection(dev)) { + connection = to_gb_connection(dev); + interface = connection->interface; + gmod = interface->gmod; + } else { + dev_WARN(dev, "uevent for unknown greybus device \"type\"!\n"); + return -EINVAL; + } - /* FIXME - add some uevents here... */ + if (connection) { + // FIXME + // add a uevent that can "load" a connection type + return 0; + } - /* FIXME - be sure to check the type to know how to handle modules and - * interfaces differently */ + if (interface) { + // FIXME + // add a uevent that can "load" a interface type + // This is what we need to bind a driver to so use the info + // in gmod here as well + return 0; + } + // FIXME + // "just" a module, be vague here, nothing binds to a module except + // the greybus core, so there's not much, if anything, we need to + // advertise. return 0; } diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 284be84..eb5eb60 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -259,5 +259,24 @@ void gb_uart_device_exit(struct gb_connection *connection); int svc_set_route_send(struct gb_interface *interface, struct greybus_host_device *hd); +extern struct device_type greybus_module_type; +extern struct device_type greybus_interface_type; +extern struct device_type greybus_connection_type; + +static inline int is_gb_module(const struct device *dev) +{ + return dev->type == &greybus_module_type; +} + +static inline int is_gb_interface(const struct device *dev) +{ + return dev->type == &greybus_interface_type; +} + +static inline int is_gb_connection(const struct device *dev) +{ + return dev->type == &greybus_connection_type; +} + #endif /* __KERNEL__ */ #endif /* __LINUX_GREYBUS_H */ diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 04c864f..38c104f 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -31,7 +31,7 @@ static void gb_interface_release(struct device *dev) kfree(interface); } -static struct device_type greybus_interface_type = { +struct device_type greybus_interface_type = { .name = "greybus_interface", .release = gb_interface_release, }; diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index 51bd5c6..f432bea 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -62,7 +62,7 @@ static void greybus_module_release(struct device *dev) kfree(gmod); } -static struct device_type greybus_module_type = { +struct device_type greybus_module_type = { .name = "greybus_module", .release = greybus_module_release, }; -- cgit v0.10.2 From b4be40435284fab95de39a16690e3580ff32fb06 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 15 Nov 2014 18:30:00 -0800 Subject: greybus: Greybus UART connection driver Flush out the Greybus UART driver to actually implement greybus requests. The number of Greybus Protocol operations has been reduced down to a managable number, and, if you look closely, you will notice it follows the CDC ACM USB specification, which can drive UART devices quite well, no need for complex UART state changes, leave all of that logic up to the firmware, if it wants/needs it. The Greybus Protocol spec has been updated to match the driver. TODO: There are 2 requests from the device to the host that need to be implemented. As this isn't fully hooked up in the Greybus core, that is not implemented here yet either. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 9638d0e..533c3c2 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -33,6 +33,83 @@ #define GB_NUM_MINORS 255 /* 255 is enough for anyone... */ #define GB_NAME "ttyGB" +/* Version of the Greybus PWM protocol we support */ +#define GB_UART_VERSION_MAJOR 0x00 +#define GB_UART_VERSION_MINOR 0x01 + +/* Greybus UART request types */ +#define GB_UART_REQ_INVALID 0x00 +#define GB_UART_REQ_PROTOCOL_VERSION 0x01 +#define GB_UART_REQ_SEND_DATA 0x02 +#define GB_UART_REQ_RECEIVE_DATA 0x03 /* Unsolicited data */ +#define GB_UART_REQ_SET_LINE_CODING 0x04 +#define GB_UART_REQ_SET_CONTROL_LINE_STATE 0x05 +#define GB_UART_REQ_SET_BREAK 0x06 +#define GB_UART_REQ_SERIAL_STATE 0x07 /* Unsolicited data */ +#define GB_UART_TYPE_RESPONSE 0x80 /* OR'd with rest */ + +struct gb_uart_proto_version_response { + __u8 status; + __u8 major; + __u8 minor; +}; + +struct gb_uart_send_data_request { + __le16 size; + __u8 data[0]; +}; + +struct gb_serial_line_coding { + __le32 rate; + __u8 format; +#define GB_SERIAL_1_STOP_BITS 0 +#define GB_SERIAL_1_5_STOP_BITS 1 +#define GB_SERIAL_2_STOP_BITS 2 + + __u8 parity; +#define GB_SERIAL_NO_PARITY 0 +#define GB_SERIAL_ODD_PARITY 1 +#define GB_SERIAL_EVEN_PARITY 2 +#define GB_SERIAL_MARK_PARITY 3 +#define GB_SERIAL_SPACE_PARITY 4 + + __u8 data; +} __attribute__ ((packed)); + +struct gb_uart_set_line_coding_request { + struct gb_serial_line_coding line_coding; +}; + +/* output control lines */ +#define GB_UART_CTRL_DTR 0x01 +#define GB_UART_CTRL_RTS 0x02 + +struct gb_uart_set_control_line_state_request { + __le16 control; +}; + +struct gb_uart_set_break_request { + __u8 state; +}; + +/* input control lines and line errors */ +#define GB_UART_CTRL_DCD 0x01 +#define GB_UART_CTRL_DSR 0x02 +#define GB_UART_CTRL_BRK 0x04 +#define GB_UART_CTRL_RI 0x08 + +#define GB_UART_CTRL_FRAMING 0x10 +#define GB_UART_CTRL_PARITY 0x20 +#define GB_UART_CTRL_OVERRUN 0x40 + +struct gb_uart_serial_state_request { + __u16 control; +}; + +struct gb_uart_simple_response { + __u8 status; +}; + struct gb_tty { struct tty_port port; struct gb_connection *connection; @@ -49,15 +126,247 @@ struct gb_tty { struct async_icount oldcount; wait_queue_head_t wioctl; struct mutex mutex; + u8 version_major; + u8 version_minor; + unsigned int ctrlin; /* input control lines */ + unsigned int ctrlout; /* output control lines */ + struct gb_serial_line_coding line_coding; }; + static struct tty_driver *gb_tty_driver; static DEFINE_IDR(tty_minors); static DEFINE_MUTEX(table_lock); static atomic_t reference_count = ATOMIC_INIT(0); -static int gb_tty_init(void); -static void gb_tty_exit(void); + +static int request_operation(struct gb_connection *connection, int type, + void *response, int response_size) +{ + struct gb_operation *operation; + struct gb_uart_simple_response *fake_request; + u8 *local_response; + int ret; + + local_response = kmalloc(response_size, GFP_KERNEL); + if (!local_response) + return -ENOMEM; + + operation = gb_operation_create(connection, type, 0, response_size); + if (!operation) { + kfree(local_response); + return -ENOMEM; + } + + /* Synchronous operation--no callback */ + ret = gb_operation_request_send(operation, NULL); + if (ret) { + pr_err("version operation failed (%d)\n", ret); + goto out; + } + + /* + * We only want to look at the status, and all requests have the same + * layout for where the status is, so cast this to a random request so + * we can see the status easier. + */ + fake_request = (struct gb_uart_simple_response *)local_response; + if (fake_request->status) { + gb_connection_err(connection, "response %hhu", + fake_request->status); + ret = -EIO; + } else { + /* Good request, so copy to the caller's buffer */ + memcpy(response, local_response, response_size); + } +out: + gb_operation_destroy(operation); + kfree(local_response); + + return ret; +} + +/* + * This request only uses the connection field, and if successful, + * fills in the major and minor protocol version of the target. + */ +static int get_version(struct gb_tty *tty) +{ + struct gb_uart_proto_version_response version_request; + int retval; + + retval = request_operation(tty->connection, + GB_UART_REQ_PROTOCOL_VERSION, + &version_request, sizeof(version_request)); + if (retval) + return retval; + + if (version_request.major > GB_UART_VERSION_MAJOR) { + pr_err("unsupported major version (%hhu > %hhu)\n", + version_request.major, GB_UART_VERSION_MAJOR); + return -ENOTSUPP; + } + + tty->version_major = version_request.major; + tty->version_minor = version_request.minor; + return 0; +} + +static int send_data(struct gb_tty *tty, u16 size, const u8 *data) +{ + struct gb_connection *connection = tty->connection; + struct gb_operation *operation; + struct gb_uart_send_data_request *request; + struct gb_uart_simple_response *response; + int retval; + + if (!data || !size) + return 0; + + operation = gb_operation_create(connection, GB_UART_REQ_SEND_DATA, + sizeof(*request) + size, + sizeof(*response)); + if (!operation) + return -ENOMEM; + request = operation->request_payload; + request->size = cpu_to_le16(size); + memcpy(&request->data[0], data, size); + + /* Synchronous operation--no callback */ + retval = gb_operation_request_send(operation, NULL); + if (retval) { + dev_err(&connection->dev, + "send data operation failed (%d)\n", retval); + goto out; + } + + response = operation->response_payload; + if (response->status) { + gb_connection_err(connection, "send data response %hhu", + response->status); + retval = -EIO; + } +out: + gb_operation_destroy(operation); + + return retval; +} + +static int send_line_coding(struct gb_tty *tty, + struct gb_serial_line_coding *line_coding) +{ + struct gb_connection *connection = tty->connection; + struct gb_operation *operation; + struct gb_uart_set_line_coding_request *request; + struct gb_uart_simple_response *response; + int retval; + + operation = gb_operation_create(connection, GB_UART_REQ_SET_LINE_CODING, + sizeof(*request), + sizeof(*response)); + if (!operation) + return -ENOMEM; + request = operation->request_payload; + memcpy(&request->line_coding, line_coding, sizeof(*line_coding)); + + /* Synchronous operation--no callback */ + retval = gb_operation_request_send(operation, NULL); + if (retval) { + dev_err(&connection->dev, + "send line coding operation failed (%d)\n", retval); + goto out; + } + + response = operation->response_payload; + if (response->status) { + gb_connection_err(connection, "send line coding response %hhu", + response->status); + retval = -EIO; + } +out: + gb_operation_destroy(operation); + + return retval; +} + +static int send_control(struct gb_tty *tty, u16 control) +{ + struct gb_connection *connection = tty->connection; + struct gb_operation *operation; + struct gb_uart_set_control_line_state_request *request; + struct gb_uart_simple_response *response; + int retval; + + operation = gb_operation_create(connection, + GB_UART_REQ_SET_CONTROL_LINE_STATE, + sizeof(*request), + sizeof(*response)); + if (!operation) + return -ENOMEM; + request = operation->request_payload; + request->control = cpu_to_le16(control); + + /* Synchronous operation--no callback */ + retval = gb_operation_request_send(operation, NULL); + if (retval) { + dev_err(&connection->dev, + "send control operation failed (%d)\n", retval); + goto out; + } + + response = operation->response_payload; + if (response->status) { + gb_connection_err(connection, "send control response %hhu", + response->status); + retval = -EIO; + } +out: + gb_operation_destroy(operation); + + return retval; +} + +static int send_break(struct gb_tty *tty, u8 state) +{ + struct gb_connection *connection = tty->connection; + struct gb_operation *operation; + struct gb_uart_set_break_request *request; + struct gb_uart_simple_response *response; + int retval; + + if ((state != 0) && (state != 1)) { + dev_err(&connection->dev, "invalid break state of %d\n", state); + return -EINVAL; + } + + operation = gb_operation_create(connection, GB_UART_REQ_SET_BREAK, + sizeof(*request), + sizeof(*response)); + if (!operation) + return -ENOMEM; + request = operation->request_payload; + request->state = state; + + /* Synchronous operation--no callback */ + retval = gb_operation_request_send(operation, NULL); + if (retval) { + dev_err(&connection->dev, + "send break operation failed (%d)\n", retval); + goto out; + } + + response = operation->response_payload; + if (response->status) { + gb_connection_err(connection, "send break response %hhu", + response->status); + retval = -EIO; + } +out: + gb_operation_destroy(operation); + + return retval; +} + static struct gb_tty *get_gb_by_minor(unsigned minor) { @@ -152,11 +461,9 @@ static void gb_tty_hangup(struct tty_struct *tty) static int gb_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) { -// struct gb_tty *gb_tty = tty->driver_data; - - // FIXME - actually implement... + struct gb_tty *gb_tty = tty->driver_data; - return 0; + return send_data(gb_tty, count, buf); } static int gb_tty_write_room(struct tty_struct *tty) @@ -177,33 +484,91 @@ static int gb_tty_chars_in_buffer(struct tty_struct *tty) static int gb_tty_break_ctl(struct tty_struct *tty, int state) { -// struct gb_tty *gb_tty = tty->driver_data; + struct gb_tty *gb_tty = tty->driver_data; - // FIXME - send a break, if asked to... - return 0; + return send_break(gb_tty, state ? 1 : 0); } -static void gb_tty_set_termios(struct tty_struct *tty, struct ktermios *old) +static void gb_tty_set_termios(struct tty_struct *tty, + struct ktermios *termios_old) { - // FIXME - is this it??? - tty_termios_copy_hw(&tty->termios, old); + struct gb_tty *gb_tty = tty->driver_data; + struct ktermios *termios = &tty->termios; + struct gb_serial_line_coding newline; + int newctrl = gb_tty->ctrlout; + + newline.rate = cpu_to_le32(tty_get_baud_rate(tty)); + newline.format = termios->c_cflag & CSTOPB ? 2 : 0; + newline.parity = 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.data = 5; + break; + case CS6: + newline.data = 6; + break; + case CS7: + newline.data = 7; + break; + case CS8: + default: + newline.data = 8; + break; + } + + /* FIXME: needs to clear unsupported bits in the termios */ + gb_tty->clocal = ((termios->c_cflag & CLOCAL) != 0); + + if (C_BAUD(tty) == B0) { + newline.rate = gb_tty->line_coding.rate; + newctrl &= GB_UART_CTRL_DTR; + } else if (termios_old && (termios_old->c_cflag & CBAUD) == B0) { + newctrl |= GB_UART_CTRL_DTR; + } + + if (newctrl != gb_tty->ctrlout) { + gb_tty->ctrlout = newctrl; + send_control(gb_tty, newctrl); + } + + if (memcpy(&gb_tty->line_coding, &newline, sizeof(newline))) { + memcpy(&gb_tty->line_coding, &newline, sizeof(newline)); + send_line_coding(gb_tty, &gb_tty->line_coding); + } } static int gb_tty_tiocmget(struct tty_struct *tty) { -// struct gb_tty *gb_tty = tty->driver_data; + struct gb_tty *gb_tty = tty->driver_data; - // FIXME - get some tiocms! - return 0; + return (gb_tty->ctrlout & GB_UART_CTRL_DTR ? TIOCM_DTR : 0) | + (gb_tty->ctrlout & GB_UART_CTRL_RTS ? TIOCM_RTS : 0) | + (gb_tty->ctrlin & GB_UART_CTRL_DSR ? TIOCM_DSR : 0) | + (gb_tty->ctrlin & GB_UART_CTRL_RI ? TIOCM_RI : 0) | + (gb_tty->ctrlin & GB_UART_CTRL_DCD ? TIOCM_CD : 0) | + TIOCM_CTS; } static int gb_tty_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { -// struct gb_tty *gb_tty = tty->driver_data; + struct gb_tty *gb_tty = tty->driver_data; + unsigned int newctrl = gb_tty->ctrlout; - // FIXME - set some tiocms! - return 0; + set = (set & TIOCM_DTR ? GB_UART_CTRL_DTR : 0) | + (set & TIOCM_RTS ? GB_UART_CTRL_RTS : 0); + clear = (clear & TIOCM_DTR ? GB_UART_CTRL_DTR : 0) | + (clear & TIOCM_RTS ? GB_UART_CTRL_RTS : 0); + + newctrl = (newctrl & ~clear) | set; + if (gb_tty->ctrlout == newctrl) + return 0; + + gb_tty->ctrlout = newctrl; + return send_control(gb_tty, newctrl); } static void gb_tty_throttle(struct tty_struct *tty) @@ -385,6 +750,9 @@ static const struct tty_operations gb_ops = { }; +static int gb_tty_init(void); +static void gb_tty_exit(void); + static int gb_uart_connection_init(struct gb_connection *connection) { struct gb_tty *gb_tty; @@ -404,27 +772,40 @@ static int gb_uart_connection_init(struct gb_connection *connection) gb_tty = kzalloc(sizeof(*gb_tty), GFP_KERNEL); if (!gb_tty) return -ENOMEM; + gb_tty->connection = connection; + + /* Check for compatible protocol version */ + retval = get_version(gb_tty); + if (retval) + goto error_version; minor = alloc_minor(gb_tty); if (minor < 0) { if (minor == -ENOSPC) { - dev_err(&connection->dev, "no more free minor numbers\n"); + dev_err(&connection->dev, + "no more free minor numbers\n"); return -ENODEV; } return minor; } gb_tty->minor = minor; - gb_tty->connection = connection; spin_lock_init(&gb_tty->write_lock); spin_lock_init(&gb_tty->read_lock); init_waitqueue_head(&gb_tty->wioctl); mutex_init(&gb_tty->mutex); - /* FIXME - allocate gb buffers */ - connection->private = gb_tty; + send_control(gb_tty, gb_tty->ctrlout); + + /* initialize the uart to be 9600n81 */ + gb_tty->line_coding.rate = cpu_to_le32(9600); + gb_tty->line_coding.format = GB_SERIAL_1_STOP_BITS; + gb_tty->line_coding.parity = GB_SERIAL_NO_PARITY; + gb_tty->line_coding.data = 8; + send_line_coding(gb_tty, &gb_tty->line_coding); + tty_dev = tty_port_register_device(&gb_tty->port, gb_tty_driver, minor, &connection->dev); if (IS_ERR(tty_dev)) { @@ -434,8 +815,10 @@ static int gb_uart_connection_init(struct gb_connection *connection) return 0; error: - connection->private = NULL; release_minor(gb_tty); +error_version: + connection->private = NULL; + kfree(gb_tty); return retval; } @@ -526,7 +909,7 @@ static struct gb_protocol uart_protocol = { .minor = 1, .connection_init = gb_uart_connection_init, .connection_exit = gb_uart_connection_exit, - .request_recv = NULL, /* no incoming requests */ + .request_recv = NULL, /* FIXME we have 2 types of requests!!! */ }; bool gb_uart_protocol_init(void) -- cgit v0.10.2 From 19363a2ca1aa7dc48214e4556fa5bfecaf570f3f Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 17 Nov 2014 08:08:36 -0600 Subject: greybus: move operation timeout teardown Move the cancel_delayed_work() call so it's done separate from the removing the operation from the pending list. This should have been part of this commit: d3809f7 greybus: move timeout out of gb_operation_insert() Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 603697e..344f58f 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -79,9 +79,6 @@ static void gb_pending_operation_remove(struct gb_operation *operation) { struct gb_connection *connection = operation->connection; - /* Shut down our timeout timer */ - cancel_delayed_work(&operation->timeout_work); - /* Take us off of the list of pending operations */ spin_lock_irq(&gb_operations_lock); list_move_tail(&operation->links, &connection->operations); @@ -439,6 +436,7 @@ void gb_connection_operation_recv(struct gb_connection *connection, gb_connection_err(connection, "operation not found"); return; } + cancel_delayed_work(&operation->timeout_work); gb_pending_operation_remove(operation); gbuf = operation->response; gbuf->status = GB_OP_SUCCESS; /* If we got here we're good */ -- cgit v0.10.2 From ea590d5cbded81a4a7863260c2918ecebf9d1182 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 17 Nov 2014 08:08:37 -0600 Subject: greybus: delete some lines in "greybus.h" This gets rid of a block of unnecessary forward declarations in "greybus.h". Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index eb5eb60..41be579 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -142,11 +142,6 @@ struct gbuf { * of the "main" gb_module structure. */ -struct gb_i2c_device; -struct gb_gpio_device; -struct gb_tty; -struct gb_usb_device; -struct gb_battery; struct greybus_host_device; struct svc_msg; -- cgit v0.10.2 From b37716f67298191aabd9f0ef5ccdf2edd3d1a50c Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 17 Nov 2014 08:08:38 -0600 Subject: greybus: kill gb_operation_gbuf_complete() It's possible this function was destined to do something important, but at this point it's pretty pointless. Get rid of it. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 344f58f..f1c7dcf 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -153,49 +153,6 @@ out: } /* - * Buffer completion function. We get notified whenever any buffer - * completes. For outbound messages, this tells us that the message - * has been sent. For inbound messages, it means the data has - * landed in the buffer and is ready to be processed. - * - * Either way, we don't do anything. We don't really care when an - * outbound message has been sent, and for incoming messages we - * we'll be done with everything we need to do before we mark it - * finished. - * - * XXX We may want to record that a request is (or is no longer) in flight. - */ -static void gb_operation_gbuf_complete(struct gbuf *gbuf) -{ - if (gbuf->status) { - struct gb_operation *operation = gbuf->operation; - struct gb_operation_msg_hdr *header; - int id; - int type; - - if (gbuf == operation->request) - header = operation->request->transfer_buffer; - else if (gbuf == operation->response) - header = operation->response->transfer_buffer; - else - header = NULL; - - if (header) { - id = le16_to_cpu(header->id); - type = header->type; - } else { - id = -1; - type = -1; - } - - gb_connection_err(operation->connection, - "operation %d type %d gbuf error %d", - id, type, gbuf->status); - } - return; -} - -/* * Either this operation contains an incoming request, or its * response has arrived. An incoming request will have a null * response buffer pointer (it is the responsibility of the request @@ -204,7 +161,6 @@ static void gb_operation_gbuf_complete(struct gbuf *gbuf) static void gb_operation_recv_work(struct work_struct *recv_work) { struct gb_operation *operation; - struct gbuf *gbuf; bool incoming_request; operation = container_of(recv_work, struct gb_operation, recv_work); @@ -212,13 +168,6 @@ static void gb_operation_recv_work(struct work_struct *recv_work) if (incoming_request) gb_operation_request_handle(operation); gb_operation_complete(operation); - - /* We're finished with the buffer we read into */ - if (incoming_request) - gbuf = operation->request; - else - gbuf = operation->response; - gb_operation_gbuf_complete(gbuf); } /* -- cgit v0.10.2 From 78496db0128bd50281e1318602f64ed9509d4b6a Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 17 Nov 2014 08:08:39 -0600 Subject: greybus: clean up gb_connection_operation_recv() This patch does some cleanup of gb_connection_operation_recv(). - Improve the header comments - Verify message is big enough for header before interpreting beginning of the message as a header - Verify at buffer creation time rather than receive time that no operation buffer is bigger than the maximum allowed. We can then compare the incoming data size against the buffer. - When a response message arrives, record its status in the operation result, not in the buffer status. - Record a buffer overflow as an operation error. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index f1c7dcf..bc68a5f 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -204,6 +204,9 @@ static struct gbuf *gb_operation_gbuf_create(struct gb_operation *operation, struct gbuf *gbuf; gfp_t gfp_flags = data_out ? GFP_KERNEL : GFP_ATOMIC; + if (size > GB_OPERATION_MESSAGE_SIZE_MAX) + return NULL; /* Message too big */ + size += sizeof(*header); gbuf = greybus_alloc_gbuf(operation, size, data_out, gfp_flags); if (!gbuf) @@ -355,9 +358,18 @@ int gb_operation_response_send(struct gb_operation *operation) } /* - * Handle data arriving on a connection. This is called in - * interrupt context, so just copy the incoming data into a buffer - * and do remaining handling via a work queue. + * Handle data arriving on a connection. As soon as we return, the + * incoming data buffer will be reused, so we need to copy the data + * into one of our own operation message buffers. + * + * If the incoming data is an operation response message, look up + * the operation and copy the incoming data into its response + * buffer. Otherwise allocate a new operation and copy the incoming + * data into its request buffer. + * + * This is called in interrupt context, so just copy the incoming + * data into the buffer and do remaining handling via a work queue. + * */ void gb_connection_operation_recv(struct gb_connection *connection, void *data, size_t size) @@ -370,8 +382,8 @@ void gb_connection_operation_recv(struct gb_connection *connection, if (connection->state != GB_CONNECTION_STATE_ENABLED) return; - if (size > GB_OPERATION_MESSAGE_SIZE_MAX) { - gb_connection_err(connection, "message too big"); + if (size < sizeof(*header)) { + gb_connection_err(connection, "message too small"); return; } @@ -388,11 +400,12 @@ void gb_connection_operation_recv(struct gb_connection *connection, cancel_delayed_work(&operation->timeout_work); gb_pending_operation_remove(operation); gbuf = operation->response; - gbuf->status = GB_OP_SUCCESS; /* If we got here we're good */ if (size > gbuf->transfer_buffer_length) { + operation->result = GB_OP_OVERFLOW; gb_connection_err(connection, "recv buffer too small"); return; } + operation->result = GB_OP_SUCCESS; } else { WARN_ON(msg_size != size); operation = gb_operation_create(connection, header->type, diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 4913f72..f30b162 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -18,6 +18,7 @@ enum gb_operation_status { GB_OP_INTERRUPTED = 3, GB_OP_RETRY = 4, GB_OP_PROTOCOL_BAD = 5, + GB_OP_OVERFLOW = 6, GB_OP_TIMEOUT = 0xff, }; -- cgit v0.10.2 From c7d0f258fb4d9ccb0e26bde0036abeda02575ad6 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 17 Nov 2014 08:08:40 -0600 Subject: greybus: reference count operations Add a reference counter to the operations structure. We'll need this when operations are actually allowed to complete asynchronously. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index bc68a5f..2b33d33 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -274,6 +274,7 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, operation->callback = NULL; /* set at submit time */ init_completion(&operation->completion); INIT_DELAYED_WORK(&operation->timeout_work, operation_timeout); + kref_init(&operation->kref); spin_lock_irq(&gb_operations_lock); list_add_tail(&operation->links, &connection->operations); @@ -292,10 +293,11 @@ err_cache: /* * Destroy a previously created operation. */ -void gb_operation_destroy(struct gb_operation *operation) +static void _gb_operation_destroy(struct kref *kref) { - if (WARN_ON(!operation)) - return; + struct gb_operation *operation; + + operation = container_of(kref, struct gb_operation, kref); /* XXX Make sure it's not in flight */ spin_lock_irq(&gb_operations_lock); @@ -308,6 +310,12 @@ void gb_operation_destroy(struct gb_operation *operation) kmem_cache_free(gb_operation_cache, operation); } +void gb_operation_put(struct gb_operation *operation) +{ + if (!WARN_ON(!operation)) + kref_put(&operation->kref, _gb_operation_destroy); +} + /* * Send an operation request message. The caller has filled in * any payload so the request message is ready to go. If non-null, diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index f30b162..dc15c2f 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -65,6 +65,7 @@ struct gb_operation { struct completion completion; /* Used if no callback */ struct delayed_work timeout_work; + struct kref kref; struct list_head links; /* connection->{operations,pending} */ /* These are what's used by caller */ @@ -78,7 +79,12 @@ void gb_connection_operation_recv(struct gb_connection *connection, struct gb_operation *gb_operation_create(struct gb_connection *connection, u8 type, size_t request_size, size_t response_size); -void gb_operation_destroy(struct gb_operation *operation); +struct gb_operation *gb_operation_get(struct gb_operation *operation); +void gb_operation_put(struct gb_operation *operation); +static inline void gb_operation_destroy(struct gb_operation *operation) +{ + gb_operation_put(operation); +} int gb_operation_request_send(struct gb_operation *operation, gb_operation_callback callback); -- cgit v0.10.2 From 63921d88724168da6d7868aa5eae8def6888a253 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 17 Nov 2014 08:08:41 -0600 Subject: greybus: record a gbuf's destination CPort id Rather than indicating whether a gbuf is intended for outbound data, record its destination CPort id. That's what's really needed by the ES1 host driver. Use CPORT_ID_BAD when the buffer is intended for inbound data. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index f82f665..df0af13 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -97,7 +97,7 @@ static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask) { struct gb_connection *connection = gbuf->operation->connection; - u32 cport_reserve = gbuf->outbound ? 1 : 0; + u32 cport_reserve = gbuf->dest_cport_id == CPORT_ID_BAD ? 0 : 1; u8 *buffer; if (size > ES1_GBUF_MSG_SIZE) { @@ -130,7 +130,7 @@ static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, } /* Insert the cport id for outbound buffers */ - if (gbuf->outbound) + if (cport_reserve) *buffer++ = connection->interface_cport_id; gbuf->transfer_buffer = buffer; gbuf->transfer_buffer_length = size; @@ -147,7 +147,8 @@ static void free_gbuf_data(struct gbuf *gbuf) if (!transfer_buffer) return; - if (gbuf->outbound) + /* Account for the cport id in outbound buffers */ + if (gbuf->dest_cport_id != CPORT_ID_BAD) transfer_buffer--; /* Back up to cport id */ kfree(transfer_buffer); } diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index d5cfb38..1b6a31d 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -35,8 +35,8 @@ static struct kmem_cache *gbuf_head_cache; * hardware designers for this issue... */ struct gbuf *greybus_alloc_gbuf(struct gb_operation *operation, + u16 dest_cport_id, unsigned int size, - bool outbound, gfp_t gfp_mask) { struct greybus_host_device *hd = operation->connection->hd; @@ -49,7 +49,7 @@ struct gbuf *greybus_alloc_gbuf(struct gb_operation *operation, kref_init(&gbuf->kref); gbuf->operation = operation; - gbuf->outbound = outbound; + gbuf->dest_cport_id = dest_cport_id; gbuf->status = -EBADR; /* Initial value--means "never set" */ /* Host controller specific allocation for the actual buffer */ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 41be579..b817c76 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -122,12 +122,12 @@ struct gbuf { struct kref kref; struct gb_operation *operation; + u16 dest_cport_id; /* Destination CPort id */ int status; + void *transfer_buffer; u32 transfer_buffer_length; - bool outbound; /* AP-relative data direction */ - void *hcd_data; /* for the HCD to track the gbuf */ }; @@ -182,7 +182,7 @@ void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, u8 *data, size_t length); struct gbuf *greybus_alloc_gbuf(struct gb_operation *operation, - unsigned int size, bool outbound, + u16 dest_cport_id, unsigned int size, gfp_t gfp_mask); void greybus_free_gbuf(struct gbuf *gbuf); struct gbuf *greybus_get_gbuf(struct gbuf *gbuf); diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 2b33d33..24e0a52 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -203,12 +203,17 @@ static struct gbuf *gb_operation_gbuf_create(struct gb_operation *operation, struct gb_operation_msg_hdr *header; struct gbuf *gbuf; gfp_t gfp_flags = data_out ? GFP_KERNEL : GFP_ATOMIC; + u16 dest_cport_id; if (size > GB_OPERATION_MESSAGE_SIZE_MAX) return NULL; /* Message too big */ + if (data_out) + dest_cport_id = operation->connection->interface_cport_id; + else + dest_cport_id = CPORT_ID_BAD; size += sizeof(*header); - gbuf = greybus_alloc_gbuf(operation, size, data_out, gfp_flags); + gbuf = greybus_alloc_gbuf(operation, dest_cport_id, size, gfp_flags); if (!gbuf) return NULL; -- cgit v0.10.2 From 6af29086bfbe201723a82b732ba5b12ecb2dfc53 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 17 Nov 2014 08:08:42 -0600 Subject: greybus: use gbuf's destination cport id If the buffer allocated in the ES1 alloc_gbuf_data() routine is for outbound data, we are getting the destination CPort id from the connection. Switch to using the copy of the destination cport id we now have in the gbuf instead. Check for a valid CPort id there only if we're inserting it into the buffer. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index df0af13..7698463 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -96,7 +96,6 @@ static void cport_out_callback(struct urb *urb); static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask) { - struct gb_connection *connection = gbuf->operation->connection; u32 cport_reserve = gbuf->dest_cport_id == CPORT_ID_BAD ? 0 : 1; u8 *buffer; @@ -118,20 +117,16 @@ static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, if (!buffer) return -ENOMEM; - /* - * we will encode the cport number in the first byte of the buffer, so - * set the second byte to be the "transfer buffer" - */ - if (connection->interface_cport_id > (u16)U8_MAX) { - pr_err("gbuf->interface_cport_id (%hd) is out of range!\n", - connection->interface_cport_id); - kfree(buffer); - return -EINVAL; - } - /* Insert the cport id for outbound buffers */ - if (cport_reserve) - *buffer++ = connection->interface_cport_id; + if (cport_reserve) { + if (gbuf->dest_cport_id > (u16)U8_MAX) { + pr_err("gbuf->dest_cport_id (%hd) is out of range!\n", + gbuf->dest_cport_id); + kfree(buffer); + return -EINVAL; + } + *buffer++ = gbuf->dest_cport_id; + } gbuf->transfer_buffer = buffer; gbuf->transfer_buffer_length = size; -- cgit v0.10.2 From ba99346828089d3833a5c31106b60b3a8cddb91d Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 17 Nov 2014 08:08:43 -0600 Subject: greybus: record the host device in a gbuf The only thing we now use the gbuf->operation pointer for is to get access to its connection's host device. Record the host device pointer directly in the gbuf, rather than keeping a pointer to the operation. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 7698463..e24012a 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -205,7 +205,7 @@ static struct urb *next_free_urb(struct es1_ap_dev *es1, gfp_t gfp_mask) static int submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) { - struct greybus_host_device *hd = gbuf->operation->connection->hd; + struct greybus_host_device *hd = gbuf->hd; struct es1_ap_dev *es1 = hd_to_es1(hd); struct usb_device *udev = es1->usb_dev; int retval; @@ -391,7 +391,7 @@ exit: static void cport_out_callback(struct urb *urb) { struct gbuf *gbuf = urb->context; - struct es1_ap_dev *es1 = hd_to_es1(gbuf->operation->connection->hd); + struct es1_ap_dev *es1 = hd_to_es1(gbuf->hd); unsigned long flags; int i; diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 1b6a31d..6f8873a 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -34,12 +34,11 @@ static struct kmem_cache *gbuf_head_cache; * that the driver can then fill up with the data to be sent out. Curse * hardware designers for this issue... */ -struct gbuf *greybus_alloc_gbuf(struct gb_operation *operation, +struct gbuf *greybus_alloc_gbuf(struct greybus_host_device *hd, u16 dest_cport_id, unsigned int size, gfp_t gfp_mask) { - struct greybus_host_device *hd = operation->connection->hd; struct gbuf *gbuf; int retval; @@ -48,7 +47,7 @@ struct gbuf *greybus_alloc_gbuf(struct gb_operation *operation, return NULL; kref_init(&gbuf->kref); - gbuf->operation = operation; + gbuf->hd = hd; gbuf->dest_cport_id = dest_cport_id; gbuf->status = -EBADR; /* Initial value--means "never set" */ @@ -68,9 +67,8 @@ static DEFINE_MUTEX(gbuf_mutex); static void free_gbuf(struct kref *kref) { struct gbuf *gbuf = container_of(kref, struct gbuf, kref); - struct greybus_host_device *hd = gbuf->operation->connection->hd; - hd->driver->free_gbuf_data(gbuf); + gbuf->hd->driver->free_gbuf_data(gbuf); kmem_cache_free(gbuf_head_cache, gbuf); mutex_unlock(&gbuf_mutex); @@ -94,21 +92,17 @@ EXPORT_SYMBOL_GPL(greybus_get_gbuf); int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) { - struct greybus_host_device *hd = gbuf->operation->connection->hd; - gbuf->status = -EINPROGRESS; - return hd->driver->submit_gbuf(gbuf, gfp_mask); + return gbuf->hd->driver->submit_gbuf(gbuf, gfp_mask); } void greybus_kill_gbuf(struct gbuf *gbuf) { - struct greybus_host_device *hd = gbuf->operation->connection->hd; - if (gbuf->status != -EINPROGRESS) return; - hd->driver->kill_gbuf(gbuf); + gbuf->hd->driver->kill_gbuf(gbuf); } void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index b817c76..c86eb25 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -121,7 +121,7 @@ struct gbuf { struct kref kref; - struct gb_operation *operation; + struct greybus_host_device *hd; u16 dest_cport_id; /* Destination CPort id */ int status; @@ -181,7 +181,7 @@ void greybus_remove_hd(struct greybus_host_device *hd); void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, u8 *data, size_t length); -struct gbuf *greybus_alloc_gbuf(struct gb_operation *operation, +struct gbuf *greybus_alloc_gbuf(struct greybus_host_device *hd, u16 dest_cport_id, unsigned int size, gfp_t gfp_mask); void greybus_free_gbuf(struct gbuf *gbuf); diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 24e0a52..c0161a2 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -200,6 +200,7 @@ static struct gbuf *gb_operation_gbuf_create(struct gb_operation *operation, u8 type, size_t size, bool data_out) { + struct gb_connection *connection = operation->connection; struct gb_operation_msg_hdr *header; struct gbuf *gbuf; gfp_t gfp_flags = data_out ? GFP_KERNEL : GFP_ATOMIC; @@ -209,11 +210,12 @@ static struct gbuf *gb_operation_gbuf_create(struct gb_operation *operation, return NULL; /* Message too big */ if (data_out) - dest_cport_id = operation->connection->interface_cport_id; + dest_cport_id = connection->interface_cport_id; else dest_cport_id = CPORT_ID_BAD; size += sizeof(*header); - gbuf = greybus_alloc_gbuf(operation, dest_cport_id, size, gfp_flags); + gbuf = greybus_alloc_gbuf(connection->hd, dest_cport_id, + size, gfp_flags); if (!gbuf) return NULL; -- cgit v0.10.2 From 2c43ce49672eacd1df87df92c2ddfdb02e276be0 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 17 Nov 2014 08:08:44 -0600 Subject: greybus: use a simple list of hd connections First of all, there's a bug in _gb_hd_connection_insert, which Viresh found. But pointing out that problem just called attention to the fact that I have planning to to remove the affected block of code. The set of connections associated with a host device is currently maintained in a red-black tree. The number of connections we're likely to have is on the order of a hundred, and at least for now isn't even going to approach that. When this code first went in, Greg asserted that using a list is speedier than a red-black tree for smallish numbers of elements (maybe up to a few hundred?). So this patch just removes the host device's red-black tree of connections, using a simple list instead. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 5927f2d..ecd7931 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -13,51 +13,15 @@ static DEFINE_SPINLOCK(gb_connections_lock); -static void _gb_hd_connection_insert(struct greybus_host_device *hd, - struct gb_connection *connection) -{ - struct rb_root *root = &hd->connections; - struct rb_node *node = &connection->hd_node; - struct rb_node **link = &root->rb_node; - struct rb_node *above = NULL; - u16 cport_id = connection->hd_cport_id; - - while (*link) { - struct gb_connection *_connection; - - above = *link; - _connection = rb_entry(above, struct gb_connection, hd_node); - if (_connection->hd_cport_id > cport_id) - link = &above->rb_left; - else if (_connection->hd_cport_id < cport_id) - link = &above->rb_right; - } - rb_link_node(node, above, link); - rb_insert_color(node, root); -} - -static void _gb_hd_connection_remove(struct gb_connection *connection) -{ - rb_erase(&connection->hd_node, &connection->hd->connections); -} - struct gb_connection *gb_hd_connection_find(struct greybus_host_device *hd, u16 cport_id) { struct gb_connection *connection = NULL; - struct rb_node *node; spin_lock_irq(&gb_connections_lock); - node = hd->connections.rb_node; - while (node) { - connection = rb_entry(node, struct gb_connection, hd_node); - if (connection->hd_cport_id > cport_id) - node = node->rb_left; - else if (connection->hd_cport_id < cport_id) - node = node->rb_right; - else + list_for_each_entry(connection, &hd->connections, hd_links) + if (connection->hd_cport_id == cport_id) goto found; - } connection = NULL; found: spin_unlock_irq(&gb_connections_lock); @@ -204,7 +168,7 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, } spin_lock_irq(&gb_connections_lock); - _gb_hd_connection_insert(hd, connection); + list_add_tail(&connection->hd_links, &hd->connections); list_add_tail(&connection->interface_links, &interface->connections); spin_unlock_irq(&gb_connections_lock); @@ -233,7 +197,7 @@ void gb_connection_destroy(struct gb_connection *connection) } spin_lock_irq(&gb_connections_lock); list_del(&connection->interface_links); - _gb_hd_connection_remove(connection); + list_del(&connection->hd_links); spin_unlock_irq(&gb_connections_lock); gb_connection_hd_cport_id_free(connection); diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 3aa8695..5e96967 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -28,7 +28,7 @@ struct gb_connection { u16 hd_cport_id; u16 interface_cport_id; - struct rb_node hd_node; + struct list_head hd_links; struct list_head interface_links; struct gb_protocol *protocol; diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 9567324..96bd974 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -186,7 +186,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver hd->parent = parent; hd->driver = driver; INIT_LIST_HEAD(&hd->modules); - hd->connections = RB_ROOT; + INIT_LIST_HEAD(&hd->connections); ida_init(&hd->cport_id_map); spin_lock_init(&hd->cport_id_map_lock); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index c86eb25..bb39528 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -166,7 +166,7 @@ struct greybus_host_device { const struct greybus_host_driver *driver; struct list_head modules; - struct rb_root connections; + struct list_head connections; struct ida cport_id_map; spinlock_t cport_id_map_lock; u8 device_id; -- cgit v0.10.2 From 1e776f31838f1037319fe54ea7e676a8871c6603 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 17 Nov 2014 08:08:45 -0600 Subject: greybus: get rid of cport_id_map_lock The only time we get a cport id is when setting up a new connection. We already have a (coarser-grained) spin lock that's used to protect the connection lists, and we can use that same lock for protecting the hd's connection id map. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index ecd7931..cb6e2e1 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -42,9 +42,9 @@ static bool gb_connection_hd_cport_id_alloc(struct gb_connection *connection) struct ida *ida = &connection->hd->cport_id_map; int id; - spin_lock(&connection->hd->cport_id_map_lock); + spin_lock_irq(&gb_connections_lock); id = ida_simple_get(ida, 0, HOST_DEV_CPORT_ID_MAX, GFP_KERNEL); - spin_unlock(&connection->hd->cport_id_map_lock); + spin_unlock_irq(&gb_connections_lock); if (id < 0) return false; @@ -60,9 +60,9 @@ static void gb_connection_hd_cport_id_free(struct gb_connection *connection) { struct ida *ida = &connection->hd->cport_id_map; - spin_lock(&connection->hd->cport_id_map_lock); + spin_lock_irq(&gb_connections_lock); ida_simple_remove(ida, connection->hd_cport_id); - spin_unlock(&connection->hd->cport_id_map_lock); + spin_unlock_irq(&gb_connections_lock); connection->hd_cport_id = CPORT_ID_BAD; } diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 96bd974..26e4b44 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -188,7 +188,6 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver INIT_LIST_HEAD(&hd->modules); INIT_LIST_HEAD(&hd->connections); ida_init(&hd->cport_id_map); - spin_lock_init(&hd->cport_id_map_lock); return hd; } diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index bb39528..90469bb 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -168,7 +168,6 @@ struct greybus_host_device { struct list_head modules; struct list_head connections; struct ida cport_id_map; - spinlock_t cport_id_map_lock; u8 device_id; /* Private data for the host driver */ -- cgit v0.10.2 From ed7538e5a36ee7b369cb0ab0616394cb2f892a9f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 17 Nov 2014 15:15:34 -0800 Subject: greybus: uart: handle NULL size requests in request_operation() Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 533c3c2..a4f745a 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -177,7 +177,8 @@ static int request_operation(struct gb_connection *connection, int type, ret = -EIO; } else { /* Good request, so copy to the caller's buffer */ - memcpy(response, local_response, response_size); + if (response_size && response) + memcpy(response, local_response, response_size); } out: gb_operation_destroy(operation); -- cgit v0.10.2 From 68190676b78a4736081e13d67d3d5bc2a519df5c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 17 Nov 2014 15:19:14 -0800 Subject: greybus: greybus_manifest.h: update with full list of protocols The protocol values had gotten out of sync with the Greybus Protocol specification document, so bring them back into sync by changing a few values, and adding the missing values. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index a0af9a2..e2ec558 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -30,10 +30,17 @@ enum greybus_protocol { GREYBUS_PROTOCOL_I2C = 0x03, GREYBUS_PROTOCOL_UART = 0x04, GREYBUS_PROTOCOL_HID = 0x05, - GREYBUS_PROTOCOL_SDIO = 0x06, + GREYBUS_PROTOCOL_USB = 0x06, + GREYBUS_PROTOCOL_SDIO = 0x07, GREYBUS_PROTOCOL_BATTERY = 0x08, GREYBUS_PROTOCOL_PWM = 0x09, - GREYBUS_PROTOCOL_LED = 0x0e, + GREYBUS_PROTOCOL_I2S = 0x0a, + GREYBUS_PROTOCOL_SPI = 0x0b, + GREYBUS_PROTOCOL_DISPLAY = 0x0c, + GREYBUS_PROTOCOL_CAMERA = 0x0d, + GREYBUS_PROTOCOL_SENSOR = 0x0e, + GREYBUS_PROTOCOL_LED = 0x0f, + GREYBUS_PROTOCOL_VIBRATOR = 0x10, /* ... */ GREYBUS_PROTOCOL_VENDOR = 0xff, }; -- cgit v0.10.2 From ac4029fb60abd00f63cfb4c626f1653a918dcc66 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 17 Nov 2014 16:03:34 -0800 Subject: greybus: vibrator-gb: add vibrator driver This driver implements the Greybus vibrator protocol, as defined in the Greybus protocol specification. It interacts to userspace with a single sysfs file, "timeout", and a separate "class" called "vibrator". That interface can/should be changed in the future depending on what Android wants for its HAL, but for now should be good enough to test with. There are some changes needed to kernel_ver.h to support some sysfs/driver core changes that happened after the 3.10 kernel was released to try to make the code simpler. Even with those changes, there are #ifdefs in the code to do different things depending on the kernel version to implement the same userspace api. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 7ec70fe..198539c 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -14,7 +14,8 @@ greybus-y := core.o \ pwm-gb.o \ sdio-gb.o \ uart-gb.o \ - battery-gb.o + battery-gb.o \ + vibrator-gb.o obj-m += greybus.o obj-m += es1-ap-usb.o diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index e4cda5c..ca0da11 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -18,6 +18,18 @@ struct device_attribute dev_attr_##_name = __ATTR_RO(_name) #endif +#ifndef DEVICE_ATTR_WO +#define DEVICE_ATTR_WO(_name) \ + struct device_attribute dev_attr_##_name = __ATTR_WO(_name) +#endif + +#ifndef __ATTR_WO +#define __ATTR_WO(_name) { \ + .attr = { .name = __stringify(_name), .mode = S_IWUSR }, \ + .store = _name##_store, \ +} +#endif + #ifndef U8_MAX #define U8_MAX ((u8)~0U) #endif /* ! U8_MAX */ diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index 8df2b4e..346120f 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -189,11 +189,16 @@ bool gb_protocol_init(void) pr_err("error initializing sdio protocol\n"); ret = false; } + if (!gb_vibrator_protocol_init()) { + pr_err("error initializing vibrator protocol\n"); + ret = false; + } return ret; } void gb_protocol_exit(void) { + gb_vibrator_protocol_exit(); gb_sdio_protocol_exit(); gb_uart_protocol_exit(); gb_i2c_protocol_exit(); diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index 1aeb340..69a4007 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -64,6 +64,9 @@ extern void gb_uart_protocol_exit(void); extern bool gb_sdio_protocol_init(void); extern void gb_sdio_protocol_exit(void); +extern bool gb_vibrator_protocol_init(void); +extern void gb_vibrator_protocol_exit(void); + bool gb_protocol_init(void); void gb_protocol_exit(void); diff --git a/drivers/staging/greybus/vibrator-gb.c b/drivers/staging/greybus/vibrator-gb.c new file mode 100644 index 0000000..2fcb2a4 --- /dev/null +++ b/drivers/staging/greybus/vibrator-gb.c @@ -0,0 +1,298 @@ +/* + * I2C bridge driver for the Greybus "generic" I2C module. + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include +#include "greybus.h" + +struct gb_vibrator_device { + struct gb_connection *connection; + struct device *dev; + u8 version_major; + u8 version_minor; +}; + +/* Version of the Greybus i2c protocol we support */ +#define GB_VIBRATOR_VERSION_MAJOR 0x00 +#define GB_VIBRATOR_VERSION_MINOR 0x01 + +/* Greybus Vibrator request types */ +#define GB_VIBRATOR_TYPE_INVALID 0x00 +#define GB_VIBRATOR_TYPE_PROTOCOL_VERSION 0x01 +#define GB_VIBRATOR_TYPE_ON 0x02 +#define GB_VIBRATOR_TYPE_OFF 0x03 +#define GB_VIBRATOR_TYPE_RESPONSE 0x80 /* OR'd with rest */ + +struct gb_vibrator_proto_version_response { + __u8 status; + __u8 major; + __u8 minor; +}; + +struct gb_vibrator_on_request { + __le16 timeout_ms; +}; + +struct gb_vibrator_simple_response { + __u8 status; +}; + +static int request_operation(struct gb_connection *connection, int type, + void *response, int response_size) +{ + struct gb_operation *operation; + struct gb_vibrator_simple_response *fake_request; + u8 *local_response; + int ret; + + local_response = kmalloc(response_size, GFP_KERNEL); + if (!local_response) + return -ENOMEM; + + operation = gb_operation_create(connection, type, 0, response_size); + if (!operation) { + kfree(local_response); + return -ENOMEM; + } + + /* Synchronous operation--no callback */ + ret = gb_operation_request_send(operation, NULL); + if (ret) { + pr_err("version operation failed (%d)\n", ret); + goto out; + } + + /* + * We only want to look at the status, and all requests have the same + * layout for where the status is, so cast this to a random request so + * we can see the status easier. + */ + fake_request = (struct gb_vibrator_simple_response *)local_response; + if (fake_request->status) { + gb_connection_err(connection, "response %hhu", + fake_request->status); + ret = -EIO; + } else { + /* Good request, so copy to the caller's buffer */ + if (response_size && response) + memcpy(response, local_response, response_size); + } +out: + gb_operation_destroy(operation); + kfree(local_response); + + return ret; +} + +/* + * This request only uses the connection field, and if successful, + * fills in the major and minor protocol version of the target. + */ +static int get_version(struct gb_vibrator_device *vib) +{ + struct gb_connection *connection = vib->connection; + struct gb_vibrator_proto_version_response version_request; + int retval; + + retval = request_operation(connection, + GB_VIBRATOR_TYPE_PROTOCOL_VERSION, + &version_request, sizeof(version_request)); + if (retval) + return retval; + + if (version_request.major > GB_VIBRATOR_VERSION_MAJOR) { + dev_err(&connection->dev, + "unsupported major version (%hhu > %hhu)\n", + version_request.major, GB_VIBRATOR_VERSION_MAJOR); + return -ENOTSUPP; + } + + vib->version_major = version_request.major; + vib->version_minor = version_request.minor; + return 0; +} + +static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms) +{ + struct gb_connection *connection = vib->connection; + struct gb_operation *operation; + struct gb_vibrator_on_request *request; + struct gb_vibrator_simple_response *response; + int retval; + + operation = gb_operation_create(connection, GB_VIBRATOR_TYPE_ON, + sizeof(*request), sizeof(*response)); + if (!operation) + return -ENOMEM; + request = operation->request_payload; + request->timeout_ms = cpu_to_le16(timeout_ms); + + /* Synchronous operation--no callback */ + retval = gb_operation_request_send(operation, NULL); + if (retval) { + dev_err(&connection->dev, + "send data operation failed (%d)\n", retval); + goto out; + } + + response = operation->response_payload; + if (response->status) { + gb_connection_err(connection, "send data response %hhu", + response->status); + retval = -EIO; + } +out: + gb_operation_destroy(operation); + + return retval; + + return 0; +} + +static int turn_off(struct gb_vibrator_device *vib) +{ + struct gb_connection *connection = vib->connection; + int retval; + + retval = request_operation(connection, GB_VIBRATOR_TYPE_OFF, NULL, 0); + if (retval) + return retval; + + return 0; +} + +static ssize_t timeout_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct gb_vibrator_device *vib = dev_get_drvdata(dev); + unsigned long val; + int retval; + + retval = kstrtoul(buf, 10, &val); + if (retval < 0) { + dev_err(dev, "could not parse timeout value %d\n", retval); + return retval; + } + + if (val < 0) + return -EINVAL; + if (val) + retval = turn_on(vib, (u16)val); + else + retval = turn_off(vib); + if (retval) + return retval; + + return count; +} +static DEVICE_ATTR_WO(timeout); + +static struct attribute *vibrator_attrs[] = { + &dev_attr_timeout.attr, + NULL, +}; +ATTRIBUTE_GROUPS(vibrator); + +static struct class vibrator_class = { + .name = "vibrator", + .owner = THIS_MODULE, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) + .dev_groups = vibrator_groups, +#endif +}; + +static int minor; + +static int gb_vibrator_connection_init(struct gb_connection *connection) +{ + struct gb_vibrator_device *vib; + struct device *dev; + int retval; + + vib = kzalloc(sizeof(*vib), GFP_KERNEL); + if (!vib) + return -ENOMEM; + + vib->connection = connection; + + retval = get_version(vib); + if (retval) + goto error; + + /* + * FIXME: for now we create a device in sysfs for the vibrator, but odds + * are there is a "real" device somewhere in the kernel for this, but I + * can't find it at the moment... + */ + dev = device_create(&vibrator_class, NULL, MKDEV(0, 0), vib, + "vibrator%d", minor); + if (IS_ERR(dev)) { + retval = -EINVAL; + goto error; + } + minor++; + vib->dev = dev; + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(3,11,0) + /* + * Newer kernels handle this in a race-free manner, for us, we need + * to "open code this :( + */ + retval = sysfs_create_group(&dev->kobj, vibrator_groups[0]); + if (retval) { + device_unregister(dev); + goto error; + } +#endif + + return 0; + +error: + kfree(vib); + return retval; +} + +static void gb_vibrator_connection_exit(struct gb_connection *connection) +{ + struct gb_vibrator_device *vib = connection->private; + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(3,11,0) + sysfs_remove_group(&vib->dev->kobj, vibrator_groups[0]); +#endif + device_unregister(vib->dev); + kfree(vib); +} + +static struct gb_protocol vibrator_protocol = { + .id = GREYBUS_PROTOCOL_VIBRATOR, + .major = 0, + .minor = 1, + .connection_init = gb_vibrator_connection_init, + .connection_exit = gb_vibrator_connection_exit, + .request_recv = NULL, /* no incoming requests */ +}; + +bool gb_vibrator_protocol_init(void) +{ + int retval; + + retval = class_register(&vibrator_class); + if (retval) + return retval; + + return gb_protocol_register(&vibrator_protocol); +} + +void gb_vibrator_protocol_exit(void) +{ + gb_protocol_deregister(&vibrator_protocol); + class_unregister(&vibrator_class); +} -- cgit v0.10.2 From 4efe6065ce0e68fc6216114d061a14b9828c0e00 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 17 Nov 2014 16:55:54 -0800 Subject: greybus: vibrator-gb: fixes based on Marti's review comments. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index ca0da11..a39ceaf 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -13,6 +13,13 @@ #ifndef __GREYBUS_KERNEL_VER_H #define __GREYBUS_KERNEL_VER_H +#ifndef __ATTR_WO +#define __ATTR_WO(_name) { \ + .attr = { .name = __stringify(_name), .mode = S_IWUSR }, \ + .store = _name##_store, \ +} +#endif + #ifndef DEVICE_ATTR_RO #define DEVICE_ATTR_RO(_name) \ struct device_attribute dev_attr_##_name = __ATTR_RO(_name) @@ -23,13 +30,6 @@ struct device_attribute dev_attr_##_name = __ATTR_WO(_name) #endif -#ifndef __ATTR_WO -#define __ATTR_WO(_name) { \ - .attr = { .name = __stringify(_name), .mode = S_IWUSR }, \ - .store = _name##_store, \ -} -#endif - #ifndef U8_MAX #define U8_MAX ((u8)~0U) #endif /* ! U8_MAX */ diff --git a/drivers/staging/greybus/vibrator-gb.c b/drivers/staging/greybus/vibrator-gb.c index 2fcb2a4..22356af 100644 --- a/drivers/staging/greybus/vibrator-gb.c +++ b/drivers/staging/greybus/vibrator-gb.c @@ -1,5 +1,5 @@ /* - * I2C bridge driver for the Greybus "generic" I2C module. + * Greybus Vibrator protocol driver. * * Copyright 2014 Google Inc. * @@ -153,20 +153,13 @@ out: gb_operation_destroy(operation); return retval; - - return 0; } static int turn_off(struct gb_vibrator_device *vib) { struct gb_connection *connection = vib->connection; - int retval; - retval = request_operation(connection, GB_VIBRATOR_TYPE_OFF, NULL, 0); - if (retval) - return retval; - - return 0; + return request_operation(connection, GB_VIBRATOR_TYPE_OFF, NULL, 0); } static ssize_t timeout_store(struct device *dev, struct device_attribute *attr, @@ -232,7 +225,7 @@ static int gb_vibrator_connection_init(struct gb_connection *connection) * are there is a "real" device somewhere in the kernel for this, but I * can't find it at the moment... */ - dev = device_create(&vibrator_class, NULL, MKDEV(0, 0), vib, + dev = device_create(&vibrator_class, &connection->dev, MKDEV(0, 0), vib, "vibrator%d", minor); if (IS_ERR(dev)) { retval = -EINVAL; @@ -243,7 +236,8 @@ static int gb_vibrator_connection_init(struct gb_connection *connection) #if LINUX_VERSION_CODE <= KERNEL_VERSION(3,11,0) /* - * Newer kernels handle this in a race-free manner, for us, we need + * Newer kernels handle this in a race-free manner, by the dev_groups + * field in the struct class up above. But for older kernels, we need * to "open code this :( */ retval = sysfs_create_group(&dev->kobj, vibrator_groups[0]); -- cgit v0.10.2 From 396671b139ff5d1271d6a1d9d465f244dfa6188d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 17 Nov 2014 17:12:50 -0800 Subject: greybus: vibrator-gb: proper allocate minor numbers Change the driver to allocate minors in a proper manner, using the idr interface. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/vibrator-gb.c b/drivers/staging/greybus/vibrator-gb.c index 22356af..e423751 100644 --- a/drivers/staging/greybus/vibrator-gb.c +++ b/drivers/staging/greybus/vibrator-gb.c @@ -11,11 +11,13 @@ #include #include #include +#include #include "greybus.h" struct gb_vibrator_device { struct gb_connection *connection; struct device *dev; + int minor; /* vibrator minor number */ u8 version_major; u8 version_minor; }; @@ -202,7 +204,7 @@ static struct class vibrator_class = { #endif }; -static int minor; +static DEFINE_IDR(minors); static int gb_vibrator_connection_init(struct gb_connection *connection) { @@ -221,17 +223,21 @@ static int gb_vibrator_connection_init(struct gb_connection *connection) goto error; /* - * FIXME: for now we create a device in sysfs for the vibrator, but odds - * are there is a "real" device somewhere in the kernel for this, but I + * For now we create a device in sysfs for the vibrator, but odds are + * there is a "real" device somewhere in the kernel for this, but I * can't find it at the moment... */ + vib->minor = idr_alloc(&minors, vib, 0, 0, GFP_KERNEL); + if (vib->minor < 0) { + retval = vib->minor; + goto error; + } dev = device_create(&vibrator_class, &connection->dev, MKDEV(0, 0), vib, - "vibrator%d", minor); + "vibrator%d", vib->minor); if (IS_ERR(dev)) { retval = -EINVAL; goto error; } - minor++; vib->dev = dev; #if LINUX_VERSION_CODE <= KERNEL_VERSION(3,11,0) @@ -261,6 +267,7 @@ static void gb_vibrator_connection_exit(struct gb_connection *connection) #if LINUX_VERSION_CODE <= KERNEL_VERSION(3,11,0) sysfs_remove_group(&vib->dev->kobj, vibrator_groups[0]); #endif + idr_remove(&minors, vib->minor); device_unregister(vib->dev); kfree(vib); } -- cgit v0.10.2 From 6e5dd0bbbb046df2b6a5ba72d74b611c1f15f467 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 17 Nov 2014 18:08:28 -0600 Subject: greybus: kill greybus_{get,put}_gbuf() These functions are never used, so we can get rid of them. Since there's no reference-getting function any more, we no longer need "gbuf_mutex" to avoid racing gets and puts, so get rid of that too. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 6f8873a..92da632 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -62,8 +62,6 @@ struct gbuf *greybus_alloc_gbuf(struct greybus_host_device *hd, } EXPORT_SYMBOL_GPL(greybus_alloc_gbuf); -static DEFINE_MUTEX(gbuf_mutex); - static void free_gbuf(struct kref *kref) { struct gbuf *gbuf = container_of(kref, struct gbuf, kref); @@ -71,25 +69,15 @@ static void free_gbuf(struct kref *kref) gbuf->hd->driver->free_gbuf_data(gbuf); kmem_cache_free(gbuf_head_cache, gbuf); - mutex_unlock(&gbuf_mutex); } void greybus_free_gbuf(struct gbuf *gbuf) { /* drop the reference count and get out of here */ - kref_put_mutex(&gbuf->kref, free_gbuf, &gbuf_mutex); + kref_put(&gbuf->kref, free_gbuf); } EXPORT_SYMBOL_GPL(greybus_free_gbuf); -struct gbuf *greybus_get_gbuf(struct gbuf *gbuf) -{ - mutex_lock(&gbuf_mutex); - kref_get(&gbuf->kref); - mutex_unlock(&gbuf_mutex); - return gbuf; -} -EXPORT_SYMBOL_GPL(greybus_get_gbuf); - int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) { gbuf->status = -EINPROGRESS; diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 90469bb..3af3382 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -184,8 +184,6 @@ struct gbuf *greybus_alloc_gbuf(struct greybus_host_device *hd, u16 dest_cport_id, unsigned int size, gfp_t gfp_mask); void greybus_free_gbuf(struct gbuf *gbuf); -struct gbuf *greybus_get_gbuf(struct gbuf *gbuf); -#define greybus_put_gbuf greybus_free_gbuf int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t mem_flags); void greybus_kill_gbuf(struct gbuf *gbuf); -- cgit v0.10.2 From 2f528c8bf7199c5eba93ea344a502910dc3a2806 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 17 Nov 2014 18:08:29 -0600 Subject: greybus: kill gbuf->kref Since there is only ever one reference to a gbuf, we don't need a kref to figure out when it can be freed. Get rid of the kref and its supporting code. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 92da632..1d0dd4a 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include @@ -46,7 +45,6 @@ struct gbuf *greybus_alloc_gbuf(struct greybus_host_device *hd, if (!gbuf) return NULL; - kref_init(&gbuf->kref); gbuf->hd = hd; gbuf->dest_cport_id = dest_cport_id; gbuf->status = -EBADR; /* Initial value--means "never set" */ @@ -62,20 +60,12 @@ struct gbuf *greybus_alloc_gbuf(struct greybus_host_device *hd, } EXPORT_SYMBOL_GPL(greybus_alloc_gbuf); -static void free_gbuf(struct kref *kref) +void greybus_free_gbuf(struct gbuf *gbuf) { - struct gbuf *gbuf = container_of(kref, struct gbuf, kref); - gbuf->hd->driver->free_gbuf_data(gbuf); kmem_cache_free(gbuf_head_cache, gbuf); } - -void greybus_free_gbuf(struct gbuf *gbuf) -{ - /* drop the reference count and get out of here */ - kref_put(&gbuf->kref, free_gbuf); -} EXPORT_SYMBOL_GPL(greybus_free_gbuf); int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 3af3382..1731700 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -119,8 +119,6 @@ */ struct gbuf { - struct kref kref; - struct greybus_host_device *hd; u16 dest_cport_id; /* Destination CPort id */ int status; -- cgit v0.10.2 From 3c3cef400ea7eadc87a66a974cd9e388ad99640a Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 17 Nov 2014 18:08:30 -0600 Subject: greybus: move the definition of struct gbuf We no longer need struct gbuf defined in "greybus.h". An upcoming patch will embed a gbuf struct (not a pointer) into the operation structure, and to do that we'll need the struct defined prior to the operation. Just move the gbuf definition into "operation.h". Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 1731700..d6bfe6b 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -56,80 +56,6 @@ #define HOST_DEV_CPORT_ID_MAX CONFIG_HOST_DEV_CPORT_ID_MAX #define CPORT_ID_BAD U16_MAX /* UniPro max id is 4095 */ -/* - gbuf - - This is the "main" data structure to send / receive Greybus messages - - There are two different "views" of a gbuf structure: - - a greybus driver - - a greybus host controller - - A Greybus driver needs to worry about the following: - - creating a gbuf - - putting data into a gbuf - - sending a gbuf to a device - - receiving a gbuf from a device - - Creating a gbuf: - A greybus driver calls greybus_alloc_gbuf() - Putting data into a gbuf: - copy data into gbuf->transfer_buffer - Send a gbuf: - A greybus driver calls greybus_submit_gbuf() - The completion function in a gbuf will be called if the gbuf is successful - or not. That completion function runs in user context. After the - completion function is called, the gbuf must not be touched again as the - greybus core "owns" it. But, if a greybus driver wants to "hold on" to a - gbuf after the completion function has been called, a reference must be - grabbed on the gbuf with a call to greybus_get_gbuf(). When finished with - the gbuf, call greybus_free_gbuf() and when the last reference count is - dropped, it will be removed from the system. - Receive a gbuf: - A greybus driver calls gb_register_cport_complete() with a pointer to the - callback function to be called for when a gbuf is received from a specific - cport and device. That callback will be made in user context with a gbuf - when it is received. To stop receiving messages, call - gb_deregister_cport_complete() for a specific cport. - - - Greybus Host controller drivers need to provide - - a way to allocate the transfer buffer for a gbuf - - a way to free the transfer buffer for a gbuf when it is "finished" - - a way to submit gbuf for transmissions - - notify the core the gbuf is complete - - receive gbuf from the wire and submit them to the core - - a way to send and receive svc messages - Allocate a transfer buffer - the host controller function alloc_gbuf_data is called - Free a transfer buffer - the host controller function free_gbuf_data is called - Submit a gbuf to the hardware - the host controller function submit_gbuf is called - Notify the gbuf is complete - the host controller driver must call greybus_gbuf_finished() - Submit a SVC message to the hardware - the host controller function send_svc_msg is called - Receive gbuf messages - the host controller driver must call greybus_cport_in() with the data - Reveive SVC messages from the hardware - The host controller driver must call greybus_svc_in - - -*/ - -struct gbuf { - struct greybus_host_device *hd; - u16 dest_cport_id; /* Destination CPort id */ - int status; - - void *transfer_buffer; - u32 transfer_buffer_length; - - void *hcd_data; /* for the HCD to track the gbuf */ -}; - - /* For SP1 hardware, we are going to "hardcode" each device to have all logical * blocks in order to be able to address them as one unified "unit". Then * higher up layers will then be able to talk to them as one logical block and @@ -142,6 +68,7 @@ struct gbuf { struct greybus_host_device; struct svc_msg; +struct gbuf; /* Greybus "Host driver" structure, needed by a host controller driver to be * able to handle both SVC control as well as "real" greybus messages diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index dc15c2f..c193136 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -11,6 +11,8 @@ #include +struct gb_operation; + enum gb_operation_status { GB_OP_SUCCESS = 0, GB_OP_INVALID = 1, @@ -22,6 +24,17 @@ enum gb_operation_status { GB_OP_TIMEOUT = 0xff, }; +struct gbuf { + struct greybus_host_device *hd; + u16 dest_cport_id; /* Destination CPort id */ + int status; + + void *transfer_buffer; + u32 transfer_buffer_length; + + void *hcd_data; /* for the HCD to track the gbuf */ +}; + /* * A Greybus operation is a remote procedure call performed over a * connection between the AP and a function on Greybus module. @@ -50,7 +63,6 @@ enum gb_operation_status { * is guaranteed to be 64-bit aligned. * XXX and callback? */ -struct gb_operation; typedef void (*gb_operation_callback)(struct gb_operation *); struct gb_operation { struct gb_connection *connection; -- cgit v0.10.2 From 3690a826fae5102ed5daed2340926885980d51ab Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 17 Nov 2014 18:08:31 -0600 Subject: greybus: define struct gb_message A Greybus buffer (gbuf) is a generic buffer used for data transfer over a Greybus interconnect. We only ever use gbufs in operations, which always involve exactly two of them. The lifetime of a gbuf is therefore directly connected to the lifetime of an operation, so there no real need to manage gbufs separate from operations. This patch begins the process of removing the gbuf abstraction, on favor of a new data type, gb_message. The purpose of a gb_message is--like a gbuf--to represent data to be transferred over Greybus. However a gb_message is oriented toward the more restrictive way we do Greybus transfers--as operation messages (either a request or a response). This patch simply defines the structure in its initial form, and defines the request and response fields in a Greybus operation structure as embedded instances of that type. The gbuf pointer is defined within the gb_message structure, and as a result lots of code needs to be tweaked to reference the request and response gbufs as subfields of the request and response structures. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index 473df4d4..6f4609d 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -153,7 +153,7 @@ static int gb_gpio_proto_version_operation(struct gb_gpio_controller *gb_gpio_co goto out; } - response = operation->response_payload; + response = operation->response.payload; if (response->status) { gb_connection_err(connection, "version response %hhu", response->status); @@ -199,7 +199,7 @@ static int gb_gpio_line_count_operation(struct gb_gpio_controller *gb_gpio_contr goto out; } - response = operation->response_payload; + response = operation->response.payload; if (response->status) { gb_connection_err(connection, "line count response %hhu", response->status); @@ -234,7 +234,7 @@ static int gb_gpio_activate_operation(struct gb_gpio_controller *gb_gpio_control sizeof(*request), sizeof(*response)); if (!operation) return -ENOMEM; - request = operation->request_payload; + request = operation->request.payload; request->which = which; /* Synchronous operation--no callback */ @@ -244,7 +244,7 @@ static int gb_gpio_activate_operation(struct gb_gpio_controller *gb_gpio_control goto out; } - response = operation->response_payload; + response = operation->response.payload; if (response->status) { gb_connection_err(connection, "activate response %hhu", response->status); @@ -278,7 +278,7 @@ static int gb_gpio_deactivate_operation(struct gb_gpio_controller *gb_gpio_contr sizeof(*request), sizeof(*response)); if (!operation) return -ENOMEM; - request = operation->request_payload; + request = operation->request.payload; request->which = which; /* Synchronous operation--no callback */ @@ -288,7 +288,7 @@ static int gb_gpio_deactivate_operation(struct gb_gpio_controller *gb_gpio_contr goto out; } - response = operation->response_payload; + response = operation->response.payload; if (response->status) { gb_connection_err(connection, "deactivate response %hhu", response->status); @@ -320,7 +320,7 @@ static int gb_gpio_get_direction_operation(struct gb_gpio_controller *gb_gpio_co sizeof(*request), sizeof(*response)); if (!operation) return -ENOMEM; - request = operation->request_payload; + request = operation->request.payload; request->which = which; /* Synchronous operation--no callback */ @@ -330,7 +330,7 @@ static int gb_gpio_get_direction_operation(struct gb_gpio_controller *gb_gpio_co goto out; } - response = operation->response_payload; + response = operation->response.payload; if (response->status) { gb_connection_err(connection, "get direction response %hhu", response->status); @@ -369,7 +369,7 @@ static int gb_gpio_direction_in_operation(struct gb_gpio_controller *gb_gpio_con sizeof(*request), sizeof(*response)); if (!operation) return -ENOMEM; - request = operation->request_payload; + request = operation->request.payload; request->which = which; /* Synchronous operation--no callback */ @@ -379,7 +379,7 @@ static int gb_gpio_direction_in_operation(struct gb_gpio_controller *gb_gpio_con goto out; } - response = operation->response_payload; + response = operation->response.payload; if (response->status) { gb_connection_err(connection, "direction in response %hhu", response->status); @@ -412,7 +412,7 @@ static int gb_gpio_direction_out_operation(struct gb_gpio_controller *gb_gpio_co sizeof(*request), sizeof(*response)); if (!operation) return -ENOMEM; - request = operation->request_payload; + request = operation->request.payload; request->which = which; request->value = value_high ? 1 : 0; @@ -423,7 +423,7 @@ static int gb_gpio_direction_out_operation(struct gb_gpio_controller *gb_gpio_co goto out; } - response = operation->response_payload; + response = operation->response.payload; if (response->status) { gb_connection_err(connection, "direction out response %hhu", response->status); @@ -456,7 +456,7 @@ static int gb_gpio_get_value_operation(struct gb_gpio_controller *gb_gpio_contro sizeof(*request), sizeof(*response)); if (!operation) return -ENOMEM; - request = operation->request_payload; + request = operation->request.payload; request->which = which; /* Synchronous operation--no callback */ @@ -466,7 +466,7 @@ static int gb_gpio_get_value_operation(struct gb_gpio_controller *gb_gpio_contro goto out; } - response = operation->response_payload; + response = operation->response.payload; if (response->status) { gb_connection_err(connection, "get value response %hhu", response->status); @@ -507,7 +507,7 @@ static int gb_gpio_set_value_operation(struct gb_gpio_controller *gb_gpio_contro sizeof(*request), sizeof(*response)); if (!operation) return -ENOMEM; - request = operation->request_payload; + request = operation->request.payload; request->which = which; request->value = value_high ? 1 : 0; @@ -518,7 +518,7 @@ static int gb_gpio_set_value_operation(struct gb_gpio_controller *gb_gpio_contro goto out; } - response = operation->response_payload; + response = operation->response.payload; if (response->status) { gb_connection_err(connection, "set value response %hhu", response->status); @@ -554,7 +554,7 @@ static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *gb_gpio_con sizeof(*request), sizeof(*response)); if (!operation) return -ENOMEM; - request = operation->request_payload; + request = operation->request.payload; request->which = which; request->usec = cpu_to_le16(debounce_usec); @@ -565,7 +565,7 @@ static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *gb_gpio_con goto out; } - response = operation->response_payload; + response = operation->response.payload; if (response->status) { gb_connection_err(connection, "set debounce response %hhu", response->status); diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index c179078..3374173 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -118,7 +118,7 @@ static int gb_i2c_proto_version_operation(struct gb_i2c_device *gb_i2c_dev) goto out; } - response = operation->response_payload; + response = operation->response.payload; if (response->status) { gb_connection_err(connection, "version response %hhu", response->status); @@ -170,7 +170,7 @@ static int gb_i2c_functionality_operation(struct gb_i2c_device *gb_i2c_dev) goto out; } - response = operation->response_payload; + response = operation->response.payload; if (response->status) { gb_connection_err(connection, "functionality response %hhu", response->status); @@ -198,7 +198,7 @@ static int gb_i2c_timeout_operation(struct gb_i2c_device *gb_i2c_dev, u16 msec) sizeof(*request), sizeof(*response)); if (!operation) return -ENOMEM; - request = operation->request_payload; + request = operation->request.payload; request->msec = cpu_to_le16(msec); /* Synchronous operation--no callback */ @@ -208,7 +208,7 @@ static int gb_i2c_timeout_operation(struct gb_i2c_device *gb_i2c_dev, u16 msec) goto out; } - response = operation->response_payload; + response = operation->response.payload; if (response->status) { gb_connection_err(connection, "timeout response %hhu", response->status); @@ -235,7 +235,7 @@ static int gb_i2c_retries_operation(struct gb_i2c_device *gb_i2c_dev, sizeof(*request), sizeof(*response)); if (!operation) return -ENOMEM; - request = operation->request_payload; + request = operation->request.payload; request->retries = retries; /* Synchronous operation--no callback */ @@ -245,7 +245,7 @@ static int gb_i2c_retries_operation(struct gb_i2c_device *gb_i2c_dev, goto out; } - response = operation->response_payload; + response = operation->response.payload; if (response->status) { gb_connection_err(connection, "retries response %hhu", response->status); @@ -321,7 +321,7 @@ gb_i2c_transfer_request(struct gb_connection *connection, if (!operation) return NULL; - request = operation->request_payload; + request = operation->request.payload; request->op_count = cpu_to_le16(op_count); /* Fill in the ops array */ op = &request->ops[0]; @@ -380,7 +380,7 @@ static int gb_i2c_transfer_operation(struct gb_i2c_device *gb_i2c_dev, goto out; } - response = operation->response_payload; + response = operation->response.payload; if (response->status) { if (response->status == GB_OP_RETRY) { ret = -EAGAIN; diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index c0161a2..82f4f20 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -71,7 +71,7 @@ static void gb_pending_operation_insert(struct gb_operation *operation) spin_unlock_irq(&gb_operations_lock); /* Store the operation id in the request header */ - header = operation->request->transfer_buffer; + header = operation->request.gbuf->transfer_buffer; header->id = cpu_to_le16(operation->id); } @@ -124,7 +124,7 @@ int gb_operation_wait(struct gb_operation *operation) ret = wait_for_completion_interruptible(&operation->completion); /* If interrupted, cancel the in-flight buffer */ if (ret < 0) - greybus_kill_gbuf(operation->request); + greybus_kill_gbuf(operation->request.gbuf); return ret; } @@ -134,7 +134,7 @@ static void gb_operation_request_handle(struct gb_operation *operation) struct gb_protocol *protocol = operation->connection->protocol; struct gb_operation_msg_hdr *header; - header = operation->request->transfer_buffer; + header = operation->request.gbuf->transfer_buffer; /* * If the protocol has no incoming request handler, report @@ -164,7 +164,7 @@ static void gb_operation_recv_work(struct work_struct *recv_work) bool incoming_request; operation = container_of(recv_work, struct gb_operation, recv_work); - incoming_request = operation->response == NULL; + incoming_request = operation->response.gbuf == NULL; if (incoming_request) gb_operation_request_handle(operation); gb_operation_complete(operation); @@ -257,23 +257,25 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, return NULL; operation->connection = connection; - operation->request = gb_operation_gbuf_create(operation, type, + operation->request.gbuf = gb_operation_gbuf_create(operation, type, request_size, outgoing); - if (!operation->request) + if (!operation->request.gbuf) goto err_cache; - operation->request_payload = operation->request->transfer_buffer + + operation->request.operation = operation; + operation->request.payload = operation->request.gbuf->transfer_buffer + sizeof(struct gb_operation_msg_hdr); if (outgoing) { type |= GB_OPERATION_TYPE_RESPONSE; - operation->response = gb_operation_gbuf_create(operation, + operation->response.gbuf = gb_operation_gbuf_create(operation, type, response_size, false); - if (!operation->response) + if (!operation->response.gbuf) goto err_request; - operation->response_payload = - operation->response->transfer_buffer + + operation->response.operation = operation; + operation->response.payload = + operation->response.gbuf->transfer_buffer + sizeof(struct gb_operation_msg_hdr); } @@ -290,7 +292,7 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, return operation; err_request: - greybus_free_gbuf(operation->request); + greybus_free_gbuf(operation->request.gbuf); err_cache: kmem_cache_free(gb_operation_cache, operation); @@ -311,8 +313,8 @@ static void _gb_operation_destroy(struct kref *kref) list_del(&operation->links); spin_unlock_irq(&gb_operations_lock); - greybus_free_gbuf(operation->response); - greybus_free_gbuf(operation->request); + greybus_free_gbuf(operation->response.gbuf); + greybus_free_gbuf(operation->request.gbuf); kmem_cache_free(gb_operation_cache, operation); } @@ -349,7 +351,7 @@ int gb_operation_request_send(struct gb_operation *operation, */ operation->callback = callback; gb_pending_operation_insert(operation); - ret = greybus_submit_gbuf(operation->request, GFP_KERNEL); + ret = greybus_submit_gbuf(operation->request.gbuf, GFP_KERNEL); if (ret) return ret; @@ -414,7 +416,7 @@ void gb_connection_operation_recv(struct gb_connection *connection, } cancel_delayed_work(&operation->timeout_work); gb_pending_operation_remove(operation); - gbuf = operation->response; + gbuf = operation->response.gbuf; if (size > gbuf->transfer_buffer_length) { operation->result = GB_OP_OVERFLOW; gb_connection_err(connection, "recv buffer too small"); @@ -429,7 +431,7 @@ void gb_connection_operation_recv(struct gb_connection *connection, gb_connection_err(connection, "can't create operation"); return; } - gbuf = operation->request; + gbuf = operation->request.gbuf; } memcpy(gbuf->transfer_buffer, data, msg_size); @@ -444,9 +446,9 @@ void gb_connection_operation_recv(struct gb_connection *connection, void gb_operation_cancel(struct gb_operation *operation) { operation->canceled = true; - greybus_kill_gbuf(operation->request); - if (operation->response) - greybus_kill_gbuf(operation->response); + greybus_kill_gbuf(operation->request.gbuf); + if (operation->response.gbuf) + greybus_kill_gbuf(operation->response.gbuf); } int gb_operation_init(void) diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index c193136..a187134 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -35,6 +35,12 @@ struct gbuf { void *hcd_data; /* for the HCD to track the gbuf */ }; +struct gb_message { + void *payload; + struct gb_operation *operation; + struct gbuf *gbuf; +}; + /* * A Greybus operation is a remote procedure call performed over a * connection between the AP and a function on Greybus module. @@ -66,8 +72,8 @@ struct gbuf { typedef void (*gb_operation_callback)(struct gb_operation *); struct gb_operation { struct gb_connection *connection; - struct gbuf *request; - struct gbuf *response; + struct gb_message request; + struct gb_message response; u16 id; bool canceled; @@ -79,10 +85,6 @@ struct gb_operation { struct kref kref; struct list_head links; /* connection->{operations,pending} */ - - /* These are what's used by caller */ - void *request_payload; - void *response_payload; }; void gb_connection_operation_recv(struct gb_connection *connection, diff --git a/drivers/staging/greybus/pwm-gb.c b/drivers/staging/greybus/pwm-gb.c index 44a4f64..0f46552 100644 --- a/drivers/staging/greybus/pwm-gb.c +++ b/drivers/staging/greybus/pwm-gb.c @@ -110,7 +110,7 @@ static int gb_pwm_proto_version_operation(struct gb_pwm_chip *pwmc) goto out; } - response = operation->response_payload; + response = operation->response.payload; if (response->status) { gb_connection_err(connection, "version response %hhu", response->status); @@ -151,7 +151,7 @@ static int gb_pwm_count_operation(struct gb_pwm_chip *pwmc) goto out; } - response = operation->response_payload; + response = operation->response.payload; if (response->status) { gb_connection_err(connection, "pwm count response %hhu", response->status); @@ -181,7 +181,7 @@ static int gb_pwm_activate_operation(struct gb_pwm_chip *pwmc, sizeof(*request), sizeof(*response)); if (!operation) return -ENOMEM; - request = operation->request_payload; + request = operation->request.payload; request->which = which; /* Synchronous operation--no callback */ @@ -191,7 +191,7 @@ static int gb_pwm_activate_operation(struct gb_pwm_chip *pwmc, goto out; } - response = operation->response_payload; + response = operation->response.payload; if (response->status) { gb_connection_err(connection, "activate response %hhu", response->status); @@ -220,7 +220,7 @@ static int gb_pwm_deactivate_operation(struct gb_pwm_chip *pwmc, sizeof(*request), sizeof(*response)); if (!operation) return -ENOMEM; - request = operation->request_payload; + request = operation->request.payload; request->which = which; /* Synchronous operation--no callback */ @@ -230,7 +230,7 @@ static int gb_pwm_deactivate_operation(struct gb_pwm_chip *pwmc, goto out; } - response = operation->response_payload; + response = operation->response.payload; if (response->status) { gb_connection_err(connection, "deactivate response %hhu", response->status); @@ -258,7 +258,7 @@ static int gb_pwm_config_operation(struct gb_pwm_chip *pwmc, sizeof(*request), sizeof(*response)); if (!operation) return -ENOMEM; - request = operation->request_payload; + request = operation->request.payload; request->which = which; request->duty = duty; request->period = period; @@ -270,7 +270,7 @@ static int gb_pwm_config_operation(struct gb_pwm_chip *pwmc, goto out; } - response = operation->response_payload; + response = operation->response.payload; if (response->status) { gb_connection_err(connection, "config response %hhu", response->status); @@ -299,7 +299,7 @@ static int gb_pwm_set_polarity_operation(struct gb_pwm_chip *pwmc, sizeof(*request), sizeof(*response)); if (!operation) return -ENOMEM; - request = operation->request_payload; + request = operation->request.payload; request->which = which; request->polarity = polarity; @@ -310,7 +310,7 @@ static int gb_pwm_set_polarity_operation(struct gb_pwm_chip *pwmc, goto out; } - response = operation->response_payload; + response = operation->response.payload; if (response->status) { gb_connection_err(connection, "set polarity response %hhu", response->status); @@ -339,7 +339,7 @@ static int gb_pwm_enable_operation(struct gb_pwm_chip *pwmc, sizeof(*request), sizeof(*response)); if (!operation) return -ENOMEM; - request = operation->request_payload; + request = operation->request.payload; request->which = which; /* Synchronous operation--no callback */ @@ -349,7 +349,7 @@ static int gb_pwm_enable_operation(struct gb_pwm_chip *pwmc, goto out; } - response = operation->response_payload; + response = operation->response.payload; if (response->status) { gb_connection_err(connection, "enable response %hhu", response->status); @@ -378,7 +378,7 @@ static int gb_pwm_disable_operation(struct gb_pwm_chip *pwmc, sizeof(*request), sizeof(*response)); if (!operation) return -ENOMEM; - request = operation->request_payload; + request = operation->request.payload; request->which = which; /* Synchronous operation--no callback */ @@ -388,7 +388,7 @@ static int gb_pwm_disable_operation(struct gb_pwm_chip *pwmc, goto out; } - response = operation->response_payload; + response = operation->response.payload; if (response->status) { gb_connection_err(connection, "disable response %hhu", response->status); diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index a4f745a..a8c342e 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -229,7 +229,7 @@ static int send_data(struct gb_tty *tty, u16 size, const u8 *data) sizeof(*response)); if (!operation) return -ENOMEM; - request = operation->request_payload; + request = operation->request.payload; request->size = cpu_to_le16(size); memcpy(&request->data[0], data, size); @@ -241,7 +241,7 @@ static int send_data(struct gb_tty *tty, u16 size, const u8 *data) goto out; } - response = operation->response_payload; + response = operation->response.payload; if (response->status) { gb_connection_err(connection, "send data response %hhu", response->status); @@ -267,7 +267,7 @@ static int send_line_coding(struct gb_tty *tty, sizeof(*response)); if (!operation) return -ENOMEM; - request = operation->request_payload; + request = operation->request.payload; memcpy(&request->line_coding, line_coding, sizeof(*line_coding)); /* Synchronous operation--no callback */ @@ -278,7 +278,7 @@ static int send_line_coding(struct gb_tty *tty, goto out; } - response = operation->response_payload; + response = operation->response.payload; if (response->status) { gb_connection_err(connection, "send line coding response %hhu", response->status); @@ -304,7 +304,7 @@ static int send_control(struct gb_tty *tty, u16 control) sizeof(*response)); if (!operation) return -ENOMEM; - request = operation->request_payload; + request = operation->request.payload; request->control = cpu_to_le16(control); /* Synchronous operation--no callback */ @@ -315,7 +315,7 @@ static int send_control(struct gb_tty *tty, u16 control) goto out; } - response = operation->response_payload; + response = operation->response.payload; if (response->status) { gb_connection_err(connection, "send control response %hhu", response->status); @@ -345,7 +345,7 @@ static int send_break(struct gb_tty *tty, u8 state) sizeof(*response)); if (!operation) return -ENOMEM; - request = operation->request_payload; + request = operation->request.payload; request->state = state; /* Synchronous operation--no callback */ @@ -356,7 +356,7 @@ static int send_break(struct gb_tty *tty, u8 state) goto out; } - response = operation->response_payload; + response = operation->response.payload; if (response->status) { gb_connection_err(connection, "send break response %hhu", response->status); -- cgit v0.10.2 From c7f82d5dc07181b56b9596adab3a3891ace357fd Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 17 Nov 2014 18:08:32 -0600 Subject: greybus: start using struct gb_message This converts some of the operation code to start leveraging the new gb_message type. Instead of creating the request and response gbufs, we initialize (and tear down with a new function) the request and response message structures. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 82f4f20..18186fd 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -23,6 +23,7 @@ /* * XXX This needs to be coordinated with host driver parameters + * XXX May need to reduce to allow for message header within a page */ #define GB_OPERATION_MESSAGE_SIZE_MAX 4096 @@ -196,36 +197,56 @@ static void operation_timeout(struct work_struct *work) * initialize it here (it'll be overwritten by the incoming * message). */ -static struct gbuf *gb_operation_gbuf_create(struct gb_operation *operation, - u8 type, size_t size, - bool data_out) +static int gb_operation_message_init(struct gb_operation *operation, + u8 type, size_t size, + bool request, bool data_out) { struct gb_connection *connection = operation->connection; + struct gb_message *message; struct gb_operation_msg_hdr *header; - struct gbuf *gbuf; gfp_t gfp_flags = data_out ? GFP_KERNEL : GFP_ATOMIC; u16 dest_cport_id; if (size > GB_OPERATION_MESSAGE_SIZE_MAX) - return NULL; /* Message too big */ + return -E2BIG; + if (request) { + message = &operation->request; + } else { + message = &operation->response; + type |= GB_OPERATION_TYPE_RESPONSE; + } if (data_out) dest_cport_id = connection->interface_cport_id; else dest_cport_id = CPORT_ID_BAD; + + if (message->gbuf) + return -EALREADY; /* Sanity check */ size += sizeof(*header); - gbuf = greybus_alloc_gbuf(connection->hd, dest_cport_id, + message->gbuf = greybus_alloc_gbuf(connection->hd, dest_cport_id, size, gfp_flags); - if (!gbuf) - return NULL; + if (!message->gbuf) + return -ENOMEM; /* Fill in the header structure */ - header = (struct gb_operation_msg_hdr *)gbuf->transfer_buffer; + header = (struct gb_operation_msg_hdr *)message->gbuf->transfer_buffer; header->size = cpu_to_le16(size); header->id = 0; /* Filled in when submitted */ header->type = type; - return gbuf; + message->payload = header + 1; + message->operation = operation; + + return 0; +} + +static void gb_operation_message_exit(struct gb_message *message) +{ + message->operation = NULL; + message->payload = NULL; + greybus_free_gbuf(message->gbuf); + message->gbuf = NULL; } /* @@ -251,32 +272,23 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, struct gb_operation *operation; gfp_t gfp_flags = response_size ? GFP_KERNEL : GFP_ATOMIC; bool outgoing = response_size != 0; + int ret; operation = kmem_cache_zalloc(gb_operation_cache, gfp_flags); if (!operation) return NULL; operation->connection = connection; - operation->request.gbuf = gb_operation_gbuf_create(operation, type, - request_size, - outgoing); - if (!operation->request.gbuf) + ret = gb_operation_message_init(operation, type, request_size, + true, outgoing); + if (ret) goto err_cache; - operation->request.operation = operation; - operation->request.payload = operation->request.gbuf->transfer_buffer + - sizeof(struct gb_operation_msg_hdr); if (outgoing) { - type |= GB_OPERATION_TYPE_RESPONSE; - operation->response.gbuf = gb_operation_gbuf_create(operation, - type, response_size, - false); - if (!operation->response.gbuf) + ret = gb_operation_message_init(operation, type, response_size, + false, false); + if (ret) goto err_request; - operation->response.operation = operation; - operation->response.payload = - operation->response.gbuf->transfer_buffer + - sizeof(struct gb_operation_msg_hdr); } INIT_WORK(&operation->recv_work, gb_operation_recv_work); @@ -292,7 +304,7 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, return operation; err_request: - greybus_free_gbuf(operation->request.gbuf); + gb_operation_message_exit(&operation->request); err_cache: kmem_cache_free(gb_operation_cache, operation); @@ -313,8 +325,8 @@ static void _gb_operation_destroy(struct kref *kref) list_del(&operation->links); spin_unlock_irq(&gb_operations_lock); - greybus_free_gbuf(operation->response.gbuf); - greybus_free_gbuf(operation->request.gbuf); + gb_operation_message_exit(&operation->response); + gb_operation_message_exit(&operation->request); kmem_cache_free(gb_operation_cache, operation); } -- cgit v0.10.2 From bb88896eaf2577b8938f05a8f70c45cee0714a18 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 17 Nov 2014 18:08:33 -0600 Subject: greybus: move gbuf initialization to caller Change greybus_alloc_gbuf() so all it does is allocate the gbuf data structure. Move all of the initialization of the gbuf structure in the caller. Do the inverse in the caller prior to freeing the gbuf structure via greybus_free_gbuf(). Use a null gbuf->transfer_buffer pointer rather than a null gbuf pointer to indicate an unused gbuf. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 1d0dd4a..5ffd257 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -38,32 +38,12 @@ struct gbuf *greybus_alloc_gbuf(struct greybus_host_device *hd, unsigned int size, gfp_t gfp_mask) { - struct gbuf *gbuf; - int retval; - - gbuf = kmem_cache_zalloc(gbuf_head_cache, gfp_mask); - if (!gbuf) - return NULL; - - gbuf->hd = hd; - gbuf->dest_cport_id = dest_cport_id; - gbuf->status = -EBADR; /* Initial value--means "never set" */ - - /* Host controller specific allocation for the actual buffer */ - retval = hd->driver->alloc_gbuf_data(gbuf, size, gfp_mask); - if (retval) { - kmem_cache_free(gbuf_head_cache, gbuf); - return NULL; - } - - return gbuf; + return kmem_cache_zalloc(gbuf_head_cache, gfp_mask); } EXPORT_SYMBOL_GPL(greybus_alloc_gbuf); void greybus_free_gbuf(struct gbuf *gbuf) { - gbuf->hd->driver->free_gbuf_data(gbuf); - kmem_cache_free(gbuf_head_cache, gbuf); } EXPORT_SYMBOL_GPL(greybus_free_gbuf); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index d6bfe6b..e1f918d 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -106,7 +106,8 @@ void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, u8 *data, size_t length); struct gbuf *greybus_alloc_gbuf(struct greybus_host_device *hd, - u16 dest_cport_id, unsigned int size, + u16 dest_cport_id, + unsigned int size, gfp_t gfp_mask); void greybus_free_gbuf(struct gbuf *gbuf); diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 18186fd..ab03e3e 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -202,10 +202,13 @@ static int gb_operation_message_init(struct gb_operation *operation, bool request, bool data_out) { struct gb_connection *connection = operation->connection; + struct greybus_host_device *hd = connection->hd; struct gb_message *message; struct gb_operation_msg_hdr *header; + struct gbuf *gbuf; gfp_t gfp_flags = data_out ? GFP_KERNEL : GFP_ATOMIC; u16 dest_cport_id; + int ret; if (size > GB_OPERATION_MESSAGE_SIZE_MAX) return -E2BIG; @@ -224,19 +227,27 @@ static int gb_operation_message_init(struct gb_operation *operation, if (message->gbuf) return -EALREADY; /* Sanity check */ size += sizeof(*header); - message->gbuf = greybus_alloc_gbuf(connection->hd, dest_cport_id, - size, gfp_flags); - if (!message->gbuf) + gbuf = greybus_alloc_gbuf(hd, dest_cport_id, size, gfp_flags); + if (!gbuf) return -ENOMEM; + gbuf->hd = hd; + gbuf->dest_cport_id = dest_cport_id; + gbuf->status = -EBADR; /* Initial value--means "never set" */ + ret = hd->driver->alloc_gbuf_data(gbuf, size, gfp_flags); + if (ret) { + greybus_free_gbuf(gbuf); + return ret; + } /* Fill in the header structure */ - header = (struct gb_operation_msg_hdr *)message->gbuf->transfer_buffer; + header = (struct gb_operation_msg_hdr *)gbuf->transfer_buffer; header->size = cpu_to_le16(size); header->id = 0; /* Filled in when submitted */ header->type = type; message->payload = header + 1; message->operation = operation; + message->gbuf = gbuf; return 0; } @@ -245,6 +256,7 @@ static void gb_operation_message_exit(struct gb_message *message) { message->operation = NULL; message->payload = NULL; + message->gbuf->hd->driver->free_gbuf_data(message->gbuf); greybus_free_gbuf(message->gbuf); message->gbuf = NULL; } -- cgit v0.10.2 From f7935e333ad2f94ccf8dcc8185a2ec836bb81adb Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 17 Nov 2014 18:08:34 -0600 Subject: greybus: use null gbuf->transfer_buffer Make sure gbuf->transfer_buffer gets reset to NULL when the buffer is freed. We can leverage that to do a little extra error checking. We'll also use a null transfer buffer in the next patch to indicate an unused gbuf. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index e24012a..e276f0c 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -99,6 +99,9 @@ static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, u32 cport_reserve = gbuf->dest_cport_id == CPORT_ID_BAD ? 0 : 1; u8 *buffer; + if (gbuf->transfer_buffer) + return -EALREADY; + if (size > ES1_GBUF_MSG_SIZE) { pr_err("guf was asked to be bigger than %ld!\n", ES1_GBUF_MSG_SIZE); @@ -146,6 +149,7 @@ static void free_gbuf_data(struct gbuf *gbuf) if (gbuf->dest_cport_id != CPORT_ID_BAD) transfer_buffer--; /* Back up to cport id */ kfree(transfer_buffer); + gbuf->transfer_buffer = NULL; } #define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ @@ -214,6 +218,8 @@ static int submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) struct urb *urb; transfer_buffer = gbuf->transfer_buffer; + if (!transfer_buffer) + return -EINVAL; buffer = &transfer_buffer[-1]; /* yes, we mean -1 */ /* Find a free urb */ -- cgit v0.10.2 From bc46fabccdf4565f1228d4d775680d9c85934024 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 17 Nov 2014 18:08:35 -0600 Subject: greybus: embed gbufs into operation message structure Embed the gbuf structures for operation messages into the message structure rather than pointing to a dynamically allocated one. Use a null gbuf->transfer_buffer pointer rather than a null gbuf pointer to indicate an unused gbuf. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index ab03e3e..7eaea71 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -72,7 +72,7 @@ static void gb_pending_operation_insert(struct gb_operation *operation) spin_unlock_irq(&gb_operations_lock); /* Store the operation id in the request header */ - header = operation->request.gbuf->transfer_buffer; + header = operation->request.gbuf.transfer_buffer; header->id = cpu_to_le16(operation->id); } @@ -125,7 +125,7 @@ int gb_operation_wait(struct gb_operation *operation) ret = wait_for_completion_interruptible(&operation->completion); /* If interrupted, cancel the in-flight buffer */ if (ret < 0) - greybus_kill_gbuf(operation->request.gbuf); + greybus_kill_gbuf(&operation->request.gbuf); return ret; } @@ -135,7 +135,7 @@ static void gb_operation_request_handle(struct gb_operation *operation) struct gb_protocol *protocol = operation->connection->protocol; struct gb_operation_msg_hdr *header; - header = operation->request.gbuf->transfer_buffer; + header = operation->request.gbuf.transfer_buffer; /* * If the protocol has no incoming request handler, report @@ -165,7 +165,7 @@ static void gb_operation_recv_work(struct work_struct *recv_work) bool incoming_request; operation = container_of(recv_work, struct gb_operation, recv_work); - incoming_request = operation->response.gbuf == NULL; + incoming_request = operation->response.gbuf.transfer_buffer == NULL; if (incoming_request) gb_operation_request_handle(operation); gb_operation_complete(operation); @@ -212,6 +212,7 @@ static int gb_operation_message_init(struct gb_operation *operation, if (size > GB_OPERATION_MESSAGE_SIZE_MAX) return -E2BIG; + size += sizeof(*header); if (request) { message = &operation->request; @@ -219,25 +220,19 @@ static int gb_operation_message_init(struct gb_operation *operation, message = &operation->response; type |= GB_OPERATION_TYPE_RESPONSE; } + gbuf = &message->gbuf; + if (data_out) dest_cport_id = connection->interface_cport_id; else dest_cport_id = CPORT_ID_BAD; - if (message->gbuf) - return -EALREADY; /* Sanity check */ - size += sizeof(*header); - gbuf = greybus_alloc_gbuf(hd, dest_cport_id, size, gfp_flags); - if (!gbuf) - return -ENOMEM; gbuf->hd = hd; gbuf->dest_cport_id = dest_cport_id; gbuf->status = -EBADR; /* Initial value--means "never set" */ ret = hd->driver->alloc_gbuf_data(gbuf, size, gfp_flags); - if (ret) { - greybus_free_gbuf(gbuf); + if (ret) return ret; - } /* Fill in the header structure */ header = (struct gb_operation_msg_hdr *)gbuf->transfer_buffer; @@ -247,7 +242,6 @@ static int gb_operation_message_init(struct gb_operation *operation, message->payload = header + 1; message->operation = operation; - message->gbuf = gbuf; return 0; } @@ -256,9 +250,7 @@ static void gb_operation_message_exit(struct gb_message *message) { message->operation = NULL; message->payload = NULL; - message->gbuf->hd->driver->free_gbuf_data(message->gbuf); - greybus_free_gbuf(message->gbuf); - message->gbuf = NULL; + message->gbuf.hd->driver->free_gbuf_data(&message->gbuf); } /* @@ -375,7 +367,7 @@ int gb_operation_request_send(struct gb_operation *operation, */ operation->callback = callback; gb_pending_operation_insert(operation); - ret = greybus_submit_gbuf(operation->request.gbuf, GFP_KERNEL); + ret = greybus_submit_gbuf(&operation->request.gbuf, GFP_KERNEL); if (ret) return ret; @@ -440,7 +432,7 @@ void gb_connection_operation_recv(struct gb_connection *connection, } cancel_delayed_work(&operation->timeout_work); gb_pending_operation_remove(operation); - gbuf = operation->response.gbuf; + gbuf = &operation->response.gbuf; if (size > gbuf->transfer_buffer_length) { operation->result = GB_OP_OVERFLOW; gb_connection_err(connection, "recv buffer too small"); @@ -455,7 +447,7 @@ void gb_connection_operation_recv(struct gb_connection *connection, gb_connection_err(connection, "can't create operation"); return; } - gbuf = operation->request.gbuf; + gbuf = &operation->request.gbuf; } memcpy(gbuf->transfer_buffer, data, msg_size); @@ -470,9 +462,9 @@ void gb_connection_operation_recv(struct gb_connection *connection, void gb_operation_cancel(struct gb_operation *operation) { operation->canceled = true; - greybus_kill_gbuf(operation->request.gbuf); - if (operation->response.gbuf) - greybus_kill_gbuf(operation->response.gbuf); + greybus_kill_gbuf(&operation->request.gbuf); + if (operation->response.gbuf.transfer_buffer) + greybus_kill_gbuf(&operation->response.gbuf); } int gb_operation_init(void) diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index a187134..f43531d 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -38,7 +38,7 @@ struct gbuf { struct gb_message { void *payload; struct gb_operation *operation; - struct gbuf *gbuf; + struct gbuf gbuf; }; /* -- cgit v0.10.2 From 4e5007e5c27e012dd50db4c96cb9f57d235df1ee Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 17 Nov 2014 18:08:36 -0600 Subject: greybus: kill the gbuf slab cache Nobody dynamically allocates gbufs any more, so we can get rid of the allocation and free routines, as as the slab cache and its related code. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 26e4b44..588e624 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -226,12 +226,6 @@ static int __init gb_init(void) goto error_ap; } - retval = gb_gbuf_init(); - if (retval) { - pr_err("gb_gbuf_init failed\n"); - goto error_gbuf; - } - retval = gb_operation_init(); if (retval) { pr_err("gb_operation_init failed\n"); @@ -250,8 +244,6 @@ static int __init gb_init(void) error_protocol: gb_operation_exit(); error_operation: - gb_gbuf_exit(); -error_gbuf: gb_ap_exit(); error_ap: bus_unregister(&greybus_bus_type); @@ -265,7 +257,6 @@ static void __exit gb_exit(void) { gb_protocol_exit(); gb_operation_exit(); - gb_gbuf_exit(); gb_ap_exit(); bus_unregister(&greybus_bus_type); gb_debugfs_cleanup(); diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 5ffd257..d47cf36 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -13,41 +13,9 @@ #include #include #include -#include #include "greybus.h" -static struct kmem_cache *gbuf_head_cache; - -/** - * greybus_alloc_gbuf - allocate a greybus buffer - * - * @gmod: greybus device that wants to allocate this - * @cport: cport to send the data to - * @complete: callback when the gbuf is finished with - * @size: size of the buffer - * @gfp_mask: allocation mask - * - * TODO: someday it will be nice to handle DMA, but for now, due to the - * architecture we are stuck with, the greybus core has to allocate the buffer - * that the driver can then fill up with the data to be sent out. Curse - * hardware designers for this issue... - */ -struct gbuf *greybus_alloc_gbuf(struct greybus_host_device *hd, - u16 dest_cport_id, - unsigned int size, - gfp_t gfp_mask) -{ - return kmem_cache_zalloc(gbuf_head_cache, gfp_mask); -} -EXPORT_SYMBOL_GPL(greybus_alloc_gbuf); - -void greybus_free_gbuf(struct gbuf *gbuf) -{ - kmem_cache_free(gbuf_head_cache, gbuf); -} -EXPORT_SYMBOL_GPL(greybus_free_gbuf); - int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) { gbuf->status = -EINPROGRESS; @@ -77,16 +45,3 @@ void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, gb_connection_operation_recv(connection, data, length); } EXPORT_SYMBOL_GPL(greybus_cport_in); - -int gb_gbuf_init(void) -{ - gbuf_head_cache = kmem_cache_create("gbuf_head_cache", - sizeof(struct gbuf), 0, 0, NULL); - return 0; -} - -void gb_gbuf_exit(void) -{ - kmem_cache_destroy(gbuf_head_cache); - gbuf_head_cache = NULL; -} diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index e1f918d..30d5625 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -105,12 +105,6 @@ void greybus_remove_hd(struct greybus_host_device *hd); void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, u8 *data, size_t length); -struct gbuf *greybus_alloc_gbuf(struct greybus_host_device *hd, - u16 dest_cport_id, - unsigned int size, - gfp_t gfp_mask); -void greybus_free_gbuf(struct gbuf *gbuf); - int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t mem_flags); void greybus_kill_gbuf(struct gbuf *gbuf); -- cgit v0.10.2 From 374e6a269cc3b1f044be78215c3e96021796de7d Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 17 Nov 2014 18:08:37 -0600 Subject: greybus: kill off the last of gbuf.c Only three functions remain in "gbuf.c". Move one of them into "connection.c" and the other two into "operation.c". Some more cleanup is coming that will further straighten out gbufs but for now there's no sense in drawing this out any longer. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 7ec70fe..c19fc84 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -1,5 +1,4 @@ greybus-y := core.o \ - gbuf.o \ sysfs.o \ debugfs.o \ ap.o \ diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index cb6e2e1..258d96c 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -29,6 +29,21 @@ struct gb_connection *gb_hd_connection_find(struct greybus_host_device *hd, return connection; } +void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, + u8 *data, size_t length) +{ + struct gb_connection *connection; + + connection = gb_hd_connection_find(hd, cport_id); + if (!connection) { + dev_err(hd->parent, + "nonexistent connection (%zu bytes dropped)\n", length); + return; + } + gb_connection_operation_recv(connection, data, length); +} +EXPORT_SYMBOL_GPL(greybus_cport_in); + /* * Allocate an available CPort Id for use for the host side of the * given connection. The lowest-available id is returned, so the diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 5e96967..bcaad47 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -53,6 +53,8 @@ void gb_connection_exit(struct gb_connection *connection); struct gb_connection *gb_hd_connection_find(struct greybus_host_device *hd, u16 cport_id); +void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, + u8 *data, size_t length); __printf(2, 3) void gb_connection_err(struct gb_connection *connection, const char *fmt, ...); diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c deleted file mode 100644 index d47cf36..0000000 --- a/drivers/staging/greybus/gbuf.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Greybus gbuf handling - * - * Copyright 2014 Google Inc. - * - * Released under the GPLv2 only. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include - -#include "greybus.h" - -int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) -{ - gbuf->status = -EINPROGRESS; - - return gbuf->hd->driver->submit_gbuf(gbuf, gfp_mask); -} - -void greybus_kill_gbuf(struct gbuf *gbuf) -{ - if (gbuf->status != -EINPROGRESS) - return; - - gbuf->hd->driver->kill_gbuf(gbuf); -} - -void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, - u8 *data, size_t length) -{ - struct gb_connection *connection; - - connection = gb_hd_connection_find(hd, cport_id); - if (!connection) { - dev_err(hd->parent, - "nonexistent connection (%zu bytes dropped)\n", length); - return; - } - gb_connection_operation_recv(connection, data, length); -} -EXPORT_SYMBOL_GPL(greybus_cport_in); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 30d5625..301bd45 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -102,12 +102,6 @@ struct greybus_host_device { struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *hd, struct device *parent); void greybus_remove_hd(struct greybus_host_device *hd); -void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, - u8 *data, size_t length); - -int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t mem_flags); -void greybus_kill_gbuf(struct gbuf *gbuf); - struct greybus_driver { const char *name; diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 7eaea71..2239883 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -103,6 +103,20 @@ gb_pending_operation_find(struct gb_connection *connection, u16 id) return found ? operation : NULL; } +static int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) +{ + gbuf->status = -EINPROGRESS; + + return gbuf->hd->driver->submit_gbuf(gbuf, gfp_mask); +} + +static void greybus_kill_gbuf(struct gbuf *gbuf) +{ + if (gbuf->status != -EINPROGRESS) + return; + + gbuf->hd->driver->kill_gbuf(gbuf); +} /* * An operations's response message has arrived. If no callback was * supplied it was submitted for asynchronous completion, so we notify -- cgit v0.10.2 From 4b992018da759ff471872a3483b03cb0a649b698 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Nov 2014 12:21:27 -0800 Subject: greybus: vibrator-gb: fix up api changes responses changed in 'master' so fix up things so that the vibrator driver works properly. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/vibrator-gb.c b/drivers/staging/greybus/vibrator-gb.c index e423751..b9ec772 100644 --- a/drivers/staging/greybus/vibrator-gb.c +++ b/drivers/staging/greybus/vibrator-gb.c @@ -134,7 +134,7 @@ static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms) sizeof(*request), sizeof(*response)); if (!operation) return -ENOMEM; - request = operation->request_payload; + request = operation->request.payload; request->timeout_ms = cpu_to_le16(timeout_ms); /* Synchronous operation--no callback */ @@ -145,7 +145,7 @@ static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms) goto out; } - response = operation->response_payload; + response = operation->response.payload; if (response->status) { gb_connection_err(connection, "send data response %hhu", response->status); -- cgit v0.10.2 From 4f83b8d34964ef343afe5e8f731a0e37e311a42d Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 18 Nov 2014 13:26:38 -0600 Subject: greybus: fix an allocation flag bug We allocate message buffers with GFP_KERNEL allocation flags if possible. However when an incoming request message is received we can be in interrupt context, so we must use GFP_ATOMIC in that case. The computation of gfp_flags in gb_operation_message_init() is wrong. It is needlessly using GFP_ATOMIC when allocating outbound response buffers. Fix the flawed logic. Change the name of "data_out" to be "outbound" to be consistent with usage elsewhere. (Data/messages are "inbound" or "outbound"; requests are "incoming" or "outgoing".) Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 2239883..103fc97 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -213,14 +213,14 @@ static void operation_timeout(struct work_struct *work) */ static int gb_operation_message_init(struct gb_operation *operation, u8 type, size_t size, - bool request, bool data_out) + bool request, bool outbound) { struct gb_connection *connection = operation->connection; struct greybus_host_device *hd = connection->hd; struct gb_message *message; struct gb_operation_msg_hdr *header; struct gbuf *gbuf; - gfp_t gfp_flags = data_out ? GFP_KERNEL : GFP_ATOMIC; + gfp_t gfp_flags = request && !outbound ? GFP_ATOMIC : GFP_KERNEL; u16 dest_cport_id; int ret; @@ -236,7 +236,7 @@ static int gb_operation_message_init(struct gb_operation *operation, } gbuf = &message->gbuf; - if (data_out) + if (outbound) dest_cport_id = connection->interface_cport_id; else dest_cport_id = CPORT_ID_BAD; -- cgit v0.10.2 From 5259ef138cbc78c537ca9f375eb0d18f21320c01 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 18 Nov 2014 13:26:39 -0600 Subject: greybus: prepend cport byte for all gbufs Treat communication buffers for both inbound and outbound data the same way, prepending a "destination cport id" byte before the data in the buffer. Currently this is done only for outbound data buffers. This isn't needed for inbound data, but handling it this way allows the free routine to work without knowing whether the buffer was used for sending or receiving. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index e276f0c..062fb1a 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -96,7 +96,7 @@ static void cport_out_callback(struct urb *urb); static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask) { - u32 cport_reserve = gbuf->dest_cport_id == CPORT_ID_BAD ? 0 : 1; + u8 dest_cport_id = gbuf->dest_cport_id; u8 *buffer; if (gbuf->transfer_buffer) @@ -107,29 +107,29 @@ static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, ES1_GBUF_MSG_SIZE); } - /* For ES2 we need to figure out what cport is going to what endpoint, - * but for ES1, it's so dirt simple, we don't have a choice... + /* + * For ES1 we need to insert a byte at the front of the data + * to indicate the destination CPort id. So we allocate one + * extra byte to allow for that. * - * Also, do a "slow" allocation now, if we need speed, use a cache + * This is only needed for outbound data, but we handle + * buffers for inbound data the same way for consistency. * - * For ES1 outbound buffers need to insert their target - * CPort Id before the data; set aside an extra byte for - * that purpose in that case. + * XXX Do we need to indicate the destination device id too? */ - buffer = kzalloc(cport_reserve + size, gfp_mask); + buffer = kzalloc(1 + size, gfp_mask); if (!buffer) return -ENOMEM; /* Insert the cport id for outbound buffers */ - if (cport_reserve) { - if (gbuf->dest_cport_id > (u16)U8_MAX) { - pr_err("gbuf->dest_cport_id (%hd) is out of range!\n", - gbuf->dest_cport_id); - kfree(buffer); - return -EINVAL; - } - *buffer++ = gbuf->dest_cport_id; + if (dest_cport_id != CPORT_ID_BAD && dest_cport_id > (u16)U8_MAX) { + pr_err("dest_cport_id (%hd) is out of range!\n", + gbuf->dest_cport_id); + kfree(buffer); + return -EINVAL; } + *buffer++ = gbuf->dest_cport_id; + gbuf->transfer_buffer = buffer; gbuf->transfer_buffer_length = size; @@ -145,9 +145,8 @@ static void free_gbuf_data(struct gbuf *gbuf) if (!transfer_buffer) return; - /* Account for the cport id in outbound buffers */ - if (gbuf->dest_cport_id != CPORT_ID_BAD) - transfer_buffer--; /* Back up to cport id */ + /* Account for the prepended cport id */ + transfer_buffer--; kfree(transfer_buffer); gbuf->transfer_buffer = NULL; } @@ -222,6 +221,12 @@ static int submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) return -EINVAL; buffer = &transfer_buffer[-1]; /* yes, we mean -1 */ + /* Do one last check of the target CPort id */ + if (*buffer == CPORT_ID_BAD) { + pr_err("request to submit inbound buffer\n"); + return -EINVAL; + } + /* Find a free urb */ urb = next_free_urb(es1, gfp_mask); if (!urb) -- cgit v0.10.2 From 06a4a061f1917ab6dfdddfbf4a13c0a87f207602 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 18 Nov 2014 13:26:40 -0600 Subject: greybus: improve data buffer alignment For ES1 we need to insert the destination CPort id in whatever we supply for sending over UniPro. Currently we allocate one extra byte supply the caller with an address that's offset by one from the beginning of the allocated space. As a result we always return a poorly-aligned buffer pointer. Instead, allocate enough space so that we can return a better aligned buffer to the caller. Notes: - It may be that it's more important to supply an aligned address to the hardware. - We probably need to be more careful about writing into these buffers at unaligned offsets anyway. (E.g., writing a 2-byte value at an odd offset can't be assumed to work.) Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 062fb1a..a98a2cb 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -20,7 +20,6 @@ #define ES1_SVC_MSG_SIZE (sizeof(struct svc_msg) + SZ_64K) #define ES1_GBUF_MSG_SIZE PAGE_SIZE - static const struct usb_device_id id_table[] = { /* Made up numbers for the SVC USB Bridge in ES1 */ { USB_DEVICE(0xffff, 0x0001) }, @@ -109,17 +108,19 @@ static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, /* * For ES1 we need to insert a byte at the front of the data - * to indicate the destination CPort id. So we allocate one - * extra byte to allow for that. + * to indicate the destination CPort id. We only need one + * extra byte, but we allocate four extra bytes to allow the + * buffer returned to be aligned on a four-byte boundary. * * This is only needed for outbound data, but we handle * buffers for inbound data the same way for consistency. * * XXX Do we need to indicate the destination device id too? */ - buffer = kzalloc(1 + size, gfp_mask); + buffer = kzalloc(GB_BUFFER_ALIGN + size, gfp_mask); if (!buffer) return -ENOMEM; + buffer += GB_BUFFER_ALIGN; /* Insert the cport id for outbound buffers */ if (dest_cport_id != CPORT_ID_BAD && dest_cport_id > (u16)U8_MAX) { @@ -128,7 +129,7 @@ static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, kfree(buffer); return -EINVAL; } - *buffer++ = gbuf->dest_cport_id; + *(buffer - 1) = gbuf->dest_cport_id; gbuf->transfer_buffer = buffer; gbuf->transfer_buffer_length = size; @@ -145,8 +146,8 @@ static void free_gbuf_data(struct gbuf *gbuf) if (!transfer_buffer) return; - /* Account for the prepended cport id */ - transfer_buffer--; + /* Account for the space set aside for the prepended cport id */ + transfer_buffer -= GB_BUFFER_ALIGN; kfree(transfer_buffer); gbuf->transfer_buffer = NULL; } diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 301bd45..fa80651 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -70,6 +70,9 @@ struct greybus_host_device; struct svc_msg; struct gbuf; +/* Buffers allocated from the host driver will be aligned to this multiple */ +#define GB_BUFFER_ALIGN sizeof(u32) + /* Greybus "Host driver" structure, needed by a host controller driver to be * able to handle both SVC control as well as "real" greybus messages */ -- cgit v0.10.2 From 0f4c808a7ea2ee3d81f5c3047bd14d7057cbfe37 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 18 Nov 2014 13:26:41 -0600 Subject: greybus: fill in destination data at send time For ES1 we need to insert the destination CPort id before the data to be sent over UniPro. Currently this is done at the time the buffer is created, but there's no need to do so until we're actually going to send the content of the buffer. Move the setting of that destination information into submit_gbuf(). Note that this allows us to defer initializing a few other gbuf fields until after we know the buffer allocation has succeeded. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index a98a2cb..a92f893 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -95,7 +95,6 @@ static void cport_out_callback(struct urb *urb); static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask) { - u8 dest_cport_id = gbuf->dest_cport_id; u8 *buffer; if (gbuf->transfer_buffer) @@ -122,15 +121,6 @@ static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, return -ENOMEM; buffer += GB_BUFFER_ALIGN; - /* Insert the cport id for outbound buffers */ - if (dest_cport_id != CPORT_ID_BAD && dest_cport_id > (u16)U8_MAX) { - pr_err("dest_cport_id (%hd) is out of range!\n", - gbuf->dest_cport_id); - kfree(buffer); - return -EINVAL; - } - *(buffer - 1) = gbuf->dest_cport_id; - gbuf->transfer_buffer = buffer; gbuf->transfer_buffer_length = size; @@ -212,6 +202,7 @@ static int submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) struct greybus_host_device *hd = gbuf->hd; struct es1_ap_dev *es1 = hd_to_es1(hd); struct usb_device *udev = es1->usb_dev; + u16 dest_cport_id = gbuf->dest_cport_id; int retval; u8 *transfer_buffer; u8 *buffer; @@ -222,11 +213,17 @@ static int submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) return -EINVAL; buffer = &transfer_buffer[-1]; /* yes, we mean -1 */ - /* Do one last check of the target CPort id */ - if (*buffer == CPORT_ID_BAD) { - pr_err("request to submit inbound buffer\n"); + /* Do one last check of the target CPort id before filling it in */ + if (dest_cport_id == CPORT_ID_BAD) { + pr_err("request to send inbound data buffer\n"); + return -EINVAL; + } + if (dest_cport_id > (u16)U8_MAX) { + pr_err("dest_cport_id (%hd) is out of range for ES1\n", + dest_cport_id); return -EINVAL; } + *buffer = dest_cport_id; /* Find a free urb */ urb = next_free_urb(es1, gfp_mask); diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 103fc97..b5cd9a2 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -241,12 +241,12 @@ static int gb_operation_message_init(struct gb_operation *operation, else dest_cport_id = CPORT_ID_BAD; - gbuf->hd = hd; - gbuf->dest_cport_id = dest_cport_id; - gbuf->status = -EBADR; /* Initial value--means "never set" */ ret = hd->driver->alloc_gbuf_data(gbuf, size, gfp_flags); if (ret) return ret; + gbuf->hd = hd; + gbuf->dest_cport_id = dest_cport_id; + gbuf->status = -EBADR; /* Initial value--means "never set" */ /* Fill in the header structure */ header = (struct gb_operation_msg_hdr *)gbuf->transfer_buffer; -- cgit v0.10.2 From d2a259f213c925f404eb7491fae8fa03a56b3467 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 18 Nov 2014 13:26:42 -0600 Subject: greybus: allocate space without gbufs This begins the transition to buffer allocation that does not rely on the gbuf construct. The host driver allocation routine will return a pointer to the buffer to be used, and the caller will be responsible for keeping track of that pointer, as well as the requested buffer size. Rename the allocation method to reflect it's no longer tied to a gbuf. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 588e624..ab50e2d 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -169,7 +169,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver * Validate that the driver implements all of the callbacks * so that we don't have to every time we make them. */ - if ((!driver->alloc_gbuf_data) || + if ((!driver->buffer_alloc) || (!driver->free_gbuf_data) || (!driver->submit_svc) || (!driver->submit_gbuf) || diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index a92f893..98ab05d 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -85,21 +85,12 @@ static inline struct es1_ap_dev *hd_to_es1(struct greybus_host_device *hd) static void cport_out_callback(struct urb *urb); /* - * Allocate the actual buffer for this gbuf and device and cport - * - * We are responsible for setting the following fields in a struct gbuf: - * void *hcpriv; - * void *transfer_buffer; - * u32 transfer_buffer_length; + * Allocate a buffer to be sent via UniPro. */ -static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, - gfp_t gfp_mask) +static void *buffer_alloc(unsigned int size, gfp_t gfp_mask) { u8 *buffer; - if (gbuf->transfer_buffer) - return -EALREADY; - if (size > ES1_GBUF_MSG_SIZE) { pr_err("guf was asked to be bigger than %ld!\n", ES1_GBUF_MSG_SIZE); @@ -117,14 +108,10 @@ static int alloc_gbuf_data(struct gbuf *gbuf, unsigned int size, * XXX Do we need to indicate the destination device id too? */ buffer = kzalloc(GB_BUFFER_ALIGN + size, gfp_mask); - if (!buffer) - return -ENOMEM; - buffer += GB_BUFFER_ALIGN; + if (buffer) + buffer += GB_BUFFER_ALIGN; - gbuf->transfer_buffer = buffer; - gbuf->transfer_buffer_length = size; - - return 0; + return buffer; } /* Free the memory we allocated with a gbuf */ @@ -252,7 +239,7 @@ static void kill_gbuf(struct gbuf *gbuf) static struct greybus_host_driver es1_driver = { .hd_priv_size = sizeof(struct es1_ap_dev), - .alloc_gbuf_data = alloc_gbuf_data, + .buffer_alloc = buffer_alloc, .free_gbuf_data = free_gbuf_data, .submit_svc = submit_svc, .submit_gbuf = submit_gbuf, diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index fa80651..82ab1e6 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -79,8 +79,7 @@ struct gbuf; struct greybus_host_driver { size_t hd_priv_size; - int (*alloc_gbuf_data)(struct gbuf *gbuf, unsigned int size, - gfp_t gfp_mask); + void *(*buffer_alloc)(unsigned int size, gfp_t gfp_mask); void (*free_gbuf_data)(struct gbuf *gbuf); int (*submit_svc)(struct svc_msg *svc_msg, struct greybus_host_device *hd); diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index b5cd9a2..e3669a7 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -222,7 +222,6 @@ static int gb_operation_message_init(struct gb_operation *operation, struct gbuf *gbuf; gfp_t gfp_flags = request && !outbound ? GFP_ATOMIC : GFP_KERNEL; u16 dest_cport_id; - int ret; if (size > GB_OPERATION_MESSAGE_SIZE_MAX) return -E2BIG; @@ -241,9 +240,10 @@ static int gb_operation_message_init(struct gb_operation *operation, else dest_cport_id = CPORT_ID_BAD; - ret = hd->driver->alloc_gbuf_data(gbuf, size, gfp_flags); - if (ret) - return ret; + gbuf->transfer_buffer = hd->driver->buffer_alloc(size, gfp_flags); + if (!gbuf->transfer_buffer) + return -ENOMEM; + gbuf->transfer_buffer_length = size; gbuf->hd = hd; gbuf->dest_cport_id = dest_cport_id; gbuf->status = -EBADR; /* Initial value--means "never set" */ -- cgit v0.10.2 From 9ec5411adf7cd872424f579701a91fffd508270b Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 18 Nov 2014 13:26:43 -0600 Subject: greybus: free space without gbufs Switch the host driver free routine to take a pointer to the previously-allocated buffer that should be freed. Rename the method to reflect it's no longer tied to a gbuf. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index ab50e2d..0f03521 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -169,8 +169,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver * Validate that the driver implements all of the callbacks * so that we don't have to every time we make them. */ - if ((!driver->buffer_alloc) || - (!driver->free_gbuf_data) || + if ((!driver->buffer_alloc) || (!driver->buffer_free) || (!driver->submit_svc) || (!driver->submit_gbuf) || (!driver->kill_gbuf)) { diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 98ab05d..660c363 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -114,19 +114,18 @@ static void *buffer_alloc(unsigned int size, gfp_t gfp_mask) return buffer; } -/* Free the memory we allocated with a gbuf */ -static void free_gbuf_data(struct gbuf *gbuf) +/* Free a previously-allocated buffer */ +static void buffer_free(void *buffer) { - u8 *transfer_buffer = gbuf->transfer_buffer; + u8 *allocated = buffer; - /* Can be called with a NULL transfer_buffer on some error paths */ - if (!transfer_buffer) + /* Can be called with a NULL buffer on some error paths */ + if (!allocated) return; /* Account for the space set aside for the prepended cport id */ - transfer_buffer -= GB_BUFFER_ALIGN; - kfree(transfer_buffer); - gbuf->transfer_buffer = NULL; + allocated -= GB_BUFFER_ALIGN; + kfree(allocated); } #define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ @@ -240,7 +239,7 @@ static void kill_gbuf(struct gbuf *gbuf) static struct greybus_host_driver es1_driver = { .hd_priv_size = sizeof(struct es1_ap_dev), .buffer_alloc = buffer_alloc, - .free_gbuf_data = free_gbuf_data, + .buffer_free = buffer_free, .submit_svc = submit_svc, .submit_gbuf = submit_gbuf, .kill_gbuf = kill_gbuf, diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 82ab1e6..f27dcaf 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -80,7 +80,7 @@ struct greybus_host_driver { size_t hd_priv_size; void *(*buffer_alloc)(unsigned int size, gfp_t gfp_mask); - void (*free_gbuf_data)(struct gbuf *gbuf); + void (*buffer_free)(void *buffer); int (*submit_svc)(struct svc_msg *svc_msg, struct greybus_host_device *hd); int (*submit_gbuf)(struct gbuf *gbuf, gfp_t gfp_mask); diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index e3669a7..c04aced 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -264,7 +264,9 @@ static void gb_operation_message_exit(struct gb_message *message) { message->operation = NULL; message->payload = NULL; - message->gbuf.hd->driver->free_gbuf_data(&message->gbuf); + message->gbuf.hd->driver->buffer_free(message->gbuf.transfer_buffer); + message->gbuf.transfer_buffer = NULL; + message->gbuf.transfer_buffer_length = 0; } /* -- cgit v0.10.2 From a9163b2c30c9e110530ed5f56bc5296bb152aa98 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 18 Nov 2014 13:26:44 -0600 Subject: greybus: cancel buffers via magic cookie Change the interface for canceling in-flight buffers to take a magic cookie value as argument rather than a gbuf. Right now we pass the gbuf->hcd_data pointer that's assumed to have been set by the submit routine. But the next patch will change the submit routine to return the cookie to be used, and the caller will be responsible for keeping track of it. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 0f03521..39f8c4a 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -170,9 +170,9 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver * so that we don't have to every time we make them. */ if ((!driver->buffer_alloc) || (!driver->buffer_free) || - (!driver->submit_svc) || (!driver->submit_gbuf) || - (!driver->kill_gbuf)) { + (!driver->buffer_cancel) || + (!driver->submit_svc)) { pr_err("Must implement all greybus_host_driver callbacks!\n"); return NULL; } diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 660c363..c4a7def 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -226,13 +226,15 @@ static int submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) return retval; } -static void kill_gbuf(struct gbuf *gbuf) +static void buffer_cancel(void *cookie) { - struct urb *urb = gbuf->hcd_data; - - if (!urb) - return; + struct urb *urb = cookie; + /* + * We really should be defensive and track all outstanding + * (sent) buffers rather than trusting the cookie provided + * is valid. For the time being, this will do. + */ usb_kill_urb(urb); } @@ -240,9 +242,9 @@ static struct greybus_host_driver es1_driver = { .hd_priv_size = sizeof(struct es1_ap_dev), .buffer_alloc = buffer_alloc, .buffer_free = buffer_free, - .submit_svc = submit_svc, .submit_gbuf = submit_gbuf, - .kill_gbuf = kill_gbuf, + .buffer_cancel = buffer_cancel, + .submit_svc = submit_svc, }; /* Common function to report consistent warnings based on URB status */ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index f27dcaf..a9b2b45 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -81,10 +81,10 @@ struct greybus_host_driver { void *(*buffer_alloc)(unsigned int size, gfp_t gfp_mask); void (*buffer_free)(void *buffer); + int (*submit_gbuf)(struct gbuf *gbuf, gfp_t gfp_mask); + void (*buffer_cancel)(void *cookie); int (*submit_svc)(struct svc_msg *svc_msg, struct greybus_host_device *hd); - int (*submit_gbuf)(struct gbuf *gbuf, gfp_t gfp_mask); - void (*kill_gbuf)(struct gbuf *gbuf); }; struct greybus_host_device { diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index c04aced..26c9dd6 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -115,8 +115,9 @@ static void greybus_kill_gbuf(struct gbuf *gbuf) if (gbuf->status != -EINPROGRESS) return; - gbuf->hd->driver->kill_gbuf(gbuf); + gbuf->hd->driver->buffer_cancel(gbuf->hcd_data); } + /* * An operations's response message has arrived. If no callback was * supplied it was submitted for asynchronous completion, so we notify -- cgit v0.10.2 From fa23ffeee6949ab5962fe2727ffb107574123aaf Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 18 Nov 2014 13:26:45 -0600 Subject: greybus: stash hd as context for all URBs This changes the context value stashed with each USB URB so that it is always the host device pointer. In cport_out_callback() this allows us to get away with *not* requiring the gbuf for handling completions any more. We are (currently) ignoring the gbuf status value returned anyway, so we'll skip setting it altogether. Greg's comments in cport_out_callback() point out that ignoring this was misguided, and handling send errors will be put in place in an upcoming patch. The context is set to the host device pointer for SVC receive and CPort receive URBs for consistency--because we can. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index c4a7def..9801d08f 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -221,7 +221,7 @@ static int submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, es1->cport_out_endpoint), buffer, gbuf->transfer_buffer_length + 1, - cport_out_callback, gbuf); + cport_out_callback, hd); retval = usb_submit_urb(urb, gfp_mask); return retval; } @@ -320,7 +320,8 @@ static void ap_disconnect(struct usb_interface *interface) /* Callback for when we get a SVC message */ static void svc_in_callback(struct urb *urb) { - struct es1_ap_dev *es1 = urb->context; + struct greybus_host_device *hd = urb->context; + struct es1_ap_dev *es1 = hd_to_es1(hd); struct device *dev = &urb->dev->dev; int status = check_urb_status(urb); int retval; @@ -346,8 +347,9 @@ exit: static void cport_in_callback(struct urb *urb) { + struct greybus_host_device *hd = urb->context; + struct es1_ap_dev *es1 = hd_to_es1(hd); struct device *dev = &urb->dev->dev; - struct es1_ap_dev *es1 = urb->context; int status = check_urb_status(urb); int retval; u8 cport; @@ -387,15 +389,12 @@ exit: static void cport_out_callback(struct urb *urb) { - struct gbuf *gbuf = urb->context; - struct es1_ap_dev *es1 = hd_to_es1(gbuf->hd); + struct greybus_host_device *hd = urb->context; + struct es1_ap_dev *es1 = hd_to_es1(hd); unsigned long flags; + /* int status = check_urb_status(urb); */ int i; - /* Record whether the transfer was successful */ - gbuf->status = check_urb_status(urb); - gbuf->hcd_data = NULL; - /* * See if this was an urb in our pool, if so mark it "free", otherwise * we need to free it ourselves. @@ -414,6 +413,8 @@ static void cport_out_callback(struct urb *urb) usb_free_urb(urb); /* + * Rest assured Greg, this craziness is getting fixed. + * * Yes, you are right, we aren't telling anyone that the urb finished. * "That's crazy! How does this all even work?" you might be saying. * The "magic" is the idea that greybus works on the "operation" level, @@ -520,7 +521,7 @@ static int ap_probe(struct usb_interface *interface, usb_fill_int_urb(es1->svc_urb, udev, usb_rcvintpipe(udev, es1->svc_endpoint), es1->svc_buffer, ES1_SVC_MSG_SIZE, svc_in_callback, - es1, svc_interval); + hd, svc_interval); retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); if (retval) goto error; @@ -540,7 +541,7 @@ static int ap_probe(struct usb_interface *interface, usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, es1->cport_in_endpoint), buffer, ES1_GBUF_MSG_SIZE, cport_in_callback, - es1); + hd); es1->cport_in_urb[i] = urb; es1->cport_in_buffer[i] = buffer; retval = usb_submit_urb(urb, GFP_KERNEL); -- cgit v0.10.2 From 58a5bdc7358ae87d2f7b8c85319f624651b7555b Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 18 Nov 2014 13:26:46 -0600 Subject: greybus: send buffers without gbufs Change the method that sends messages so that it sends "raw" buffers rather than gbufs. To do this, we supply the host device and destination CPort when sending. As with other recent patches, change the name of the method to reflect that we're no longer dealing with gbufs. The interface has changed as well. Now this routine will return a "cookie" value. The cookie is used to represent the outgoing request, and is supplied by the caller if necessary to cancel a previously-sent buffer. We'll store the result in gbuf->hcd_data for now (which produces the same result as before...). Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 39f8c4a..04fc541 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -170,8 +170,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver * so that we don't have to every time we make them. */ if ((!driver->buffer_alloc) || (!driver->buffer_free) || - (!driver->submit_gbuf) || - (!driver->buffer_cancel) || + (!driver->buffer_send) || (!driver->buffer_cancel) || (!driver->submit_svc)) { pr_err("Must implement all greybus_host_driver callbacks!\n"); return NULL; diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 9801d08f..3404dc5 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -183,47 +183,65 @@ static struct urb *next_free_urb(struct es1_ap_dev *es1, gfp_t gfp_mask) return urb; } -static int submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) +/* + * Returns an opaque cookie value if successful, or a pointer coded + * error otherwise. If the caller wishes to cancel the in-flight + * buffer, it must supply the returned cookie to the cancel routine. + */ +static void *buffer_send(struct greybus_host_device *hd, u16 dest_cport_id, + void *buffer, size_t buffer_size, gfp_t gfp_mask) { - struct greybus_host_device *hd = gbuf->hd; struct es1_ap_dev *es1 = hd_to_es1(hd); struct usb_device *udev = es1->usb_dev; - u16 dest_cport_id = gbuf->dest_cport_id; + u8 *transfer_buffer = buffer; + int transfer_buffer_size; int retval; - u8 *transfer_buffer; - u8 *buffer; struct urb *urb; - transfer_buffer = gbuf->transfer_buffer; - if (!transfer_buffer) - return -EINVAL; - buffer = &transfer_buffer[-1]; /* yes, we mean -1 */ + if (!buffer) { + pr_err("null buffer supplied to send\n"); + return ERR_PTR(-EINVAL); + } + if (buffer_size > (size_t)INT_MAX) { + pr_err("bad buffer size (%zu) supplied to send\n", buffer_size); + return ERR_PTR(-EINVAL); + } + transfer_buffer--; + transfer_buffer_size = buffer_size + 1; - /* Do one last check of the target CPort id before filling it in */ + /* + * The data actually transferred will include an indication + * of where the data should be sent. Do one last check of + * the target CPort id before filling it in. + */ if (dest_cport_id == CPORT_ID_BAD) { pr_err("request to send inbound data buffer\n"); - return -EINVAL; + return ERR_PTR(-EINVAL); } if (dest_cport_id > (u16)U8_MAX) { pr_err("dest_cport_id (%hd) is out of range for ES1\n", dest_cport_id); - return -EINVAL; + return ERR_PTR(-EINVAL); } - *buffer = dest_cport_id; + /* OK, the destination is fine; record it in the transfer buffer */ + *transfer_buffer = dest_cport_id; /* Find a free urb */ urb = next_free_urb(es1, gfp_mask); if (!urb) - return -ENOMEM; - - gbuf->hcd_data = urb; + return ERR_PTR(-ENOMEM); usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, es1->cport_out_endpoint), - buffer, gbuf->transfer_buffer_length + 1, + transfer_buffer, transfer_buffer_size, cport_out_callback, hd); retval = usb_submit_urb(urb, gfp_mask); - return retval; + if (retval) { + pr_err("error %d submitting URB\n", retval); + return ERR_PTR(retval); + } + + return urb; } static void buffer_cancel(void *cookie) @@ -242,7 +260,7 @@ static struct greybus_host_driver es1_driver = { .hd_priv_size = sizeof(struct es1_ap_dev), .buffer_alloc = buffer_alloc, .buffer_free = buffer_free, - .submit_gbuf = submit_gbuf, + .buffer_send = buffer_send, .buffer_cancel = buffer_cancel, .submit_svc = submit_svc, }; diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index a9b2b45..4ac7376 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -81,7 +81,8 @@ struct greybus_host_driver { void *(*buffer_alloc)(unsigned int size, gfp_t gfp_mask); void (*buffer_free)(void *buffer); - int (*submit_gbuf)(struct gbuf *gbuf, gfp_t gfp_mask); + void *(*buffer_send)(struct greybus_host_device *hd, u16 dest_cport_id, + void *buffer, size_t buffer_size, gfp_t gfp_mask); void (*buffer_cancel)(void *cookie); int (*submit_svc)(struct svc_msg *svc_msg, struct greybus_host_device *hd); diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 26c9dd6..33cc414 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -106,8 +106,16 @@ gb_pending_operation_find(struct gb_connection *connection, u16 id) static int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) { gbuf->status = -EINPROGRESS; - - return gbuf->hd->driver->submit_gbuf(gbuf, gfp_mask); + gbuf->hcd_data = gbuf->hd->driver->buffer_send(gbuf->hd, + gbuf->dest_cport_id, gbuf->transfer_buffer, + gbuf->transfer_buffer_length, gfp_mask); + if (IS_ERR(gbuf->hcd_data)) { + gbuf->status = PTR_ERR(gbuf->hcd_data); + gbuf->hcd_data = NULL; + + return gbuf->status; + } + return 0; } static void greybus_kill_gbuf(struct gbuf *gbuf) -- cgit v0.10.2 From 6a70736aca05d4c8acd80f30bf485dd785ae1a2b Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 18 Nov 2014 13:26:47 -0600 Subject: greybus: rework message initialization Rework gb_opreation_message_init() so it doesn't use a struct gbuf local variable. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 33cc414..57694e0 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -228,7 +228,6 @@ static int gb_operation_message_init(struct gb_operation *operation, struct greybus_host_device *hd = connection->hd; struct gb_message *message; struct gb_operation_msg_hdr *header; - struct gbuf *gbuf; gfp_t gfp_flags = request && !outbound ? GFP_ATOMIC : GFP_KERNEL; u16 dest_cport_id; @@ -242,23 +241,22 @@ static int gb_operation_message_init(struct gb_operation *operation, message = &operation->response; type |= GB_OPERATION_TYPE_RESPONSE; } - gbuf = &message->gbuf; if (outbound) dest_cport_id = connection->interface_cport_id; else dest_cport_id = CPORT_ID_BAD; - gbuf->transfer_buffer = hd->driver->buffer_alloc(size, gfp_flags); - if (!gbuf->transfer_buffer) + message->gbuf.transfer_buffer = hd->driver->buffer_alloc(size, gfp_flags); + if (!message->gbuf.transfer_buffer) return -ENOMEM; - gbuf->transfer_buffer_length = size; - gbuf->hd = hd; - gbuf->dest_cport_id = dest_cport_id; - gbuf->status = -EBADR; /* Initial value--means "never set" */ + message->gbuf.transfer_buffer_length = size; + message->gbuf.hd = hd; + message->gbuf.dest_cport_id = dest_cport_id; + message->gbuf.status = -EBADR; /* Initial value--means "never set" */ /* Fill in the header structure */ - header = (struct gb_operation_msg_hdr *)gbuf->transfer_buffer; + header = message->gbuf.transfer_buffer; header->size = cpu_to_le16(size); header->id = 0; /* Filled in when submitted */ header->type = type; -- cgit v0.10.2 From 002fe66a7d8bdbea058025a5804f5e0a375226da Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 18 Nov 2014 13:26:48 -0600 Subject: greybus: send messages, not gbufs Rework greybus_submit_gbuf() to be oriented toward an operation message rather than a gbuf, and rename it accordingly. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 57694e0..d22b927 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -103,17 +103,21 @@ gb_pending_operation_find(struct gb_connection *connection, u16 id) return found ? operation : NULL; } -static int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) +static int gb_message_send(struct gb_message *message, gfp_t gfp_mask) { - gbuf->status = -EINPROGRESS; - gbuf->hcd_data = gbuf->hd->driver->buffer_send(gbuf->hd, - gbuf->dest_cport_id, gbuf->transfer_buffer, - gbuf->transfer_buffer_length, gfp_mask); - if (IS_ERR(gbuf->hcd_data)) { - gbuf->status = PTR_ERR(gbuf->hcd_data); - gbuf->hcd_data = NULL; - - return gbuf->status; + struct greybus_host_device *hd = message->gbuf.hd; + + message->gbuf.status = -EINPROGRESS; + message->gbuf.hcd_data = hd->driver->buffer_send(hd, + message->gbuf.dest_cport_id, + message->gbuf.transfer_buffer, + message->gbuf.transfer_buffer_length, + gfp_mask); + if (IS_ERR(message->gbuf.hcd_data)) { + message->gbuf.status = PTR_ERR(message->gbuf.hcd_data); + message->gbuf.hcd_data = NULL; + + return message->gbuf.status; } return 0; } @@ -390,7 +394,7 @@ int gb_operation_request_send(struct gb_operation *operation, */ operation->callback = callback; gb_pending_operation_insert(operation); - ret = greybus_submit_gbuf(&operation->request.gbuf, GFP_KERNEL); + ret = gb_message_send(&operation->request, GFP_KERNEL); if (ret) return ret; -- cgit v0.10.2 From 35b1342bb040a1e12d82b46ae296f660684a2d23 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 18 Nov 2014 13:26:49 -0600 Subject: greybus: cancel messages, not gbufs Rework greybus_kill_gbuf() to be oriented toward an operation message rather than a gbuf, and rename it. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index d22b927..5d5cce6 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -122,12 +122,12 @@ static int gb_message_send(struct gb_message *message, gfp_t gfp_mask) return 0; } -static void greybus_kill_gbuf(struct gbuf *gbuf) +static void gb_message_cancel(struct gb_message *message) { - if (gbuf->status != -EINPROGRESS) + if (message->gbuf.status != -EINPROGRESS) return; - gbuf->hd->driver->buffer_cancel(gbuf->hcd_data); + message->gbuf.hd->driver->buffer_cancel(message->gbuf.hcd_data); } /* @@ -152,7 +152,7 @@ int gb_operation_wait(struct gb_operation *operation) ret = wait_for_completion_interruptible(&operation->completion); /* If interrupted, cancel the in-flight buffer */ if (ret < 0) - greybus_kill_gbuf(&operation->request.gbuf); + gb_message_cancel(&operation->request); return ret; } @@ -489,9 +489,9 @@ void gb_connection_operation_recv(struct gb_connection *connection, void gb_operation_cancel(struct gb_operation *operation) { operation->canceled = true; - greybus_kill_gbuf(&operation->request.gbuf); + gb_message_cancel(&operation->request); if (operation->response.gbuf.transfer_buffer) - greybus_kill_gbuf(&operation->response.gbuf); + gb_message_cancel(&operation->response); } int gb_operation_init(void) -- cgit v0.10.2 From 61089e89e50ba10592670518c0f5611c33d64f39 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 18 Nov 2014 13:26:50 -0600 Subject: greybus: rework receve handling Rework gb_connection_operation_recv() to be more oriented toward an operation message, and to no longer use a struct gbuf local variable. Rename it to be a little more wieldy. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 258d96c..584f491 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -40,7 +40,7 @@ void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, "nonexistent connection (%zu bytes dropped)\n", length); return; } - gb_connection_operation_recv(connection, data, length); + gb_connection_recv(connection, data, length); } EXPORT_SYMBOL_GPL(greybus_cport_in); diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 5d5cce6..254864e 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -431,12 +431,12 @@ int gb_operation_response_send(struct gb_operation *operation) * data into the buffer and do remaining handling via a work queue. * */ -void gb_connection_operation_recv(struct gb_connection *connection, +void gb_connection_recv(struct gb_connection *connection, void *data, size_t size) { struct gb_operation_msg_hdr *header; struct gb_operation *operation; - struct gbuf *gbuf; + struct gb_message *message; u16 msg_size; if (connection->state != GB_CONNECTION_STATE_ENABLED) @@ -459,8 +459,8 @@ void gb_connection_operation_recv(struct gb_connection *connection, } cancel_delayed_work(&operation->timeout_work); gb_pending_operation_remove(operation); - gbuf = &operation->response.gbuf; - if (size > gbuf->transfer_buffer_length) { + message = &operation->response; + if (size > message->gbuf.transfer_buffer_length) { operation->result = GB_OP_OVERFLOW; gb_connection_err(connection, "recv buffer too small"); return; @@ -474,10 +474,10 @@ void gb_connection_operation_recv(struct gb_connection *connection, gb_connection_err(connection, "can't create operation"); return; } - gbuf = &operation->request.gbuf; + message = &operation->request; } - memcpy(gbuf->transfer_buffer, data, msg_size); + memcpy(message->gbuf.transfer_buffer, data, msg_size); /* The rest will be handled in work queue context */ queue_work(gb_operation_recv_workqueue, &operation->recv_work); diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index f43531d..a9d4b8a 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -87,7 +87,7 @@ struct gb_operation { struct list_head links; /* connection->{operations,pending} */ }; -void gb_connection_operation_recv(struct gb_connection *connection, +void gb_connection_recv(struct gb_connection *connection, void *data, size_t size); struct gb_operation *gb_operation_create(struct gb_connection *connection, -- cgit v0.10.2 From e238e641ee79db947f1f1222204ae12258061d94 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 18 Nov 2014 13:26:51 -0600 Subject: greybus: kill the last gbuf remnants All the code has now been adjusted such that we can do away with the old gbuf structure. Three unused references remained in "greybus.h", so those are deleted. Other than that most of the changes were done by simple global substitution. The gb_message structure incorporates the fields that were previously found its embedded gbuf structure. A few names have been changed in the process: gbuf->transfer_buffer message->buffer gbuf->transfer_buffer_size message->buffer_size gbuf->hcd_data; message->cookie Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 4ac7376..3df2b5a 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -68,7 +68,6 @@ struct greybus_host_device; struct svc_msg; -struct gbuf; /* Buffers allocated from the host driver will be aligned to this multiple */ #define GB_BUFFER_ALIGN sizeof(u32) @@ -156,8 +155,6 @@ int gb_ap_init(void); void gb_ap_exit(void); int gb_debugfs_init(void); void gb_debugfs_cleanup(void); -int gb_gbuf_init(void); -void gb_gbuf_exit(void); extern struct bus_type greybus_bus_type; extern const struct attribute_group *greybus_module_groups[]; diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 254864e..6c082cc 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -72,7 +72,7 @@ static void gb_pending_operation_insert(struct gb_operation *operation) spin_unlock_irq(&gb_operations_lock); /* Store the operation id in the request header */ - header = operation->request.gbuf.transfer_buffer; + header = operation->request.buffer; header->id = cpu_to_le16(operation->id); } @@ -105,29 +105,29 @@ gb_pending_operation_find(struct gb_connection *connection, u16 id) static int gb_message_send(struct gb_message *message, gfp_t gfp_mask) { - struct greybus_host_device *hd = message->gbuf.hd; + struct greybus_host_device *hd = message->hd; - message->gbuf.status = -EINPROGRESS; - message->gbuf.hcd_data = hd->driver->buffer_send(hd, - message->gbuf.dest_cport_id, - message->gbuf.transfer_buffer, - message->gbuf.transfer_buffer_length, + message->status = -EINPROGRESS; + message->cookie = hd->driver->buffer_send(hd, + message->dest_cport_id, + message->buffer, + message->buffer_size, gfp_mask); - if (IS_ERR(message->gbuf.hcd_data)) { - message->gbuf.status = PTR_ERR(message->gbuf.hcd_data); - message->gbuf.hcd_data = NULL; + if (IS_ERR(message->cookie)) { + message->status = PTR_ERR(message->cookie); + message->cookie = NULL; - return message->gbuf.status; + return message->status; } return 0; } static void gb_message_cancel(struct gb_message *message) { - if (message->gbuf.status != -EINPROGRESS) + if (message->status != -EINPROGRESS) return; - message->gbuf.hd->driver->buffer_cancel(message->gbuf.hcd_data); + message->hd->driver->buffer_cancel(message->cookie); } /* @@ -162,7 +162,7 @@ static void gb_operation_request_handle(struct gb_operation *operation) struct gb_protocol *protocol = operation->connection->protocol; struct gb_operation_msg_hdr *header; - header = operation->request.gbuf.transfer_buffer; + header = operation->request.buffer; /* * If the protocol has no incoming request handler, report @@ -192,7 +192,7 @@ static void gb_operation_recv_work(struct work_struct *recv_work) bool incoming_request; operation = container_of(recv_work, struct gb_operation, recv_work); - incoming_request = operation->response.gbuf.transfer_buffer == NULL; + incoming_request = operation->response.buffer == NULL; if (incoming_request) gb_operation_request_handle(operation); gb_operation_complete(operation); @@ -251,16 +251,16 @@ static int gb_operation_message_init(struct gb_operation *operation, else dest_cport_id = CPORT_ID_BAD; - message->gbuf.transfer_buffer = hd->driver->buffer_alloc(size, gfp_flags); - if (!message->gbuf.transfer_buffer) + message->buffer = hd->driver->buffer_alloc(size, gfp_flags); + if (!message->buffer) return -ENOMEM; - message->gbuf.transfer_buffer_length = size; - message->gbuf.hd = hd; - message->gbuf.dest_cport_id = dest_cport_id; - message->gbuf.status = -EBADR; /* Initial value--means "never set" */ + message->buffer_size = size; + message->hd = hd; + message->dest_cport_id = dest_cport_id; + message->status = -EBADR; /* Initial value--means "never set" */ /* Fill in the header structure */ - header = message->gbuf.transfer_buffer; + header = message->buffer; header->size = cpu_to_le16(size); header->id = 0; /* Filled in when submitted */ header->type = type; @@ -275,9 +275,9 @@ static void gb_operation_message_exit(struct gb_message *message) { message->operation = NULL; message->payload = NULL; - message->gbuf.hd->driver->buffer_free(message->gbuf.transfer_buffer); - message->gbuf.transfer_buffer = NULL; - message->gbuf.transfer_buffer_length = 0; + message->hd->driver->buffer_free(message->buffer); + message->buffer = NULL; + message->buffer_size = 0; } /* @@ -390,7 +390,7 @@ int gb_operation_request_send(struct gb_operation *operation, * XXX * I think the order of operations is going to be * significant, and if so, we may need a mutex to surround - * setting the operation id and submitting the gbuf. + * setting the operation id and submitting the buffer. */ operation->callback = callback; gb_pending_operation_insert(operation); @@ -460,7 +460,7 @@ void gb_connection_recv(struct gb_connection *connection, cancel_delayed_work(&operation->timeout_work); gb_pending_operation_remove(operation); message = &operation->response; - if (size > message->gbuf.transfer_buffer_length) { + if (size > message->buffer_size) { operation->result = GB_OP_OVERFLOW; gb_connection_err(connection, "recv buffer too small"); return; @@ -477,7 +477,7 @@ void gb_connection_recv(struct gb_connection *connection, message = &operation->request; } - memcpy(message->gbuf.transfer_buffer, data, msg_size); + memcpy(message->buffer, data, msg_size); /* The rest will be handled in work queue context */ queue_work(gb_operation_recv_workqueue, &operation->recv_work); @@ -490,7 +490,7 @@ void gb_operation_cancel(struct gb_operation *operation) { operation->canceled = true; gb_message_cancel(&operation->request); - if (operation->response.gbuf.transfer_buffer) + if (operation->response.buffer) gb_message_cancel(&operation->response); } diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index a9d4b8a..2fcb181 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -24,21 +24,17 @@ enum gb_operation_status { GB_OP_TIMEOUT = 0xff, }; -struct gbuf { - struct greybus_host_device *hd; - u16 dest_cport_id; /* Destination CPort id */ - int status; - - void *transfer_buffer; - u32 transfer_buffer_length; - - void *hcd_data; /* for the HCD to track the gbuf */ -}; - struct gb_message { void *payload; struct gb_operation *operation; - struct gbuf gbuf; + struct greybus_host_device *hd; + u16 dest_cport_id; /* Destination CPort id */ + int status; + + void *buffer; + size_t buffer_size; + + void *cookie; }; /* -- cgit v0.10.2 From 3ed67aba9f3b2af83b9b9cf7cd6f7ab25de5acc2 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 18 Nov 2014 13:26:52 -0600 Subject: greybus: stop storing hd in message The host device pointer doesn't have to be stored in every message. It can be derived by following up the chain of pointers back to the operation's connection. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 6c082cc..23cf745 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -105,10 +105,10 @@ gb_pending_operation_find(struct gb_connection *connection, u16 id) static int gb_message_send(struct gb_message *message, gfp_t gfp_mask) { - struct greybus_host_device *hd = message->hd; + struct gb_connection *connection = message->operation->connection; message->status = -EINPROGRESS; - message->cookie = hd->driver->buffer_send(hd, + message->cookie = connection->hd->driver->buffer_send(connection->hd, message->dest_cport_id, message->buffer, message->buffer_size, @@ -124,10 +124,13 @@ static int gb_message_send(struct gb_message *message, gfp_t gfp_mask) static void gb_message_cancel(struct gb_message *message) { + struct greybus_host_device *hd; + if (message->status != -EINPROGRESS) return; - message->hd->driver->buffer_cancel(message->cookie); + hd = message->operation->connection->hd; + hd->driver->buffer_cancel(message->cookie); } /* @@ -255,7 +258,6 @@ static int gb_operation_message_init(struct gb_operation *operation, if (!message->buffer) return -ENOMEM; message->buffer_size = size; - message->hd = hd; message->dest_cport_id = dest_cport_id; message->status = -EBADR; /* Initial value--means "never set" */ @@ -273,9 +275,13 @@ static int gb_operation_message_init(struct gb_operation *operation, static void gb_operation_message_exit(struct gb_message *message) { + struct greybus_host_device *hd; + + hd = message->operation->connection->hd; + hd->driver->buffer_free(message->buffer); + message->operation = NULL; message->payload = NULL; - message->hd->driver->buffer_free(message->buffer); message->buffer = NULL; message->buffer_size = 0; } diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 2fcb181..5e068ff 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -26,8 +26,8 @@ enum gb_operation_status { struct gb_message { void *payload; + struct gb_operation *operation; - struct greybus_host_device *hd; u16 dest_cport_id; /* Destination CPort id */ int status; -- cgit v0.10.2 From 1f764af77c6adb3b4035b8f41b48198f251dc7f8 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 18 Nov 2014 13:26:53 -0600 Subject: greybus: stop storing dest_cport_id in message We can derive the destination CPort id of any (outbound) message from the connection it's operation is associated with. So we don't need to store that information in every message. As a result, we no longer need to record it at message initialization time. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 23cf745..705b195 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -106,10 +106,11 @@ gb_pending_operation_find(struct gb_connection *connection, u16 id) static int gb_message_send(struct gb_message *message, gfp_t gfp_mask) { struct gb_connection *connection = message->operation->connection; + u16 dest_cport_id = connection->interface_cport_id; message->status = -EINPROGRESS; message->cookie = connection->hd->driver->buffer_send(connection->hd, - message->dest_cport_id, + dest_cport_id, message->buffer, message->buffer_size, gfp_mask); @@ -236,7 +237,6 @@ static int gb_operation_message_init(struct gb_operation *operation, struct gb_message *message; struct gb_operation_msg_hdr *header; gfp_t gfp_flags = request && !outbound ? GFP_ATOMIC : GFP_KERNEL; - u16 dest_cport_id; if (size > GB_OPERATION_MESSAGE_SIZE_MAX) return -E2BIG; @@ -249,16 +249,10 @@ static int gb_operation_message_init(struct gb_operation *operation, type |= GB_OPERATION_TYPE_RESPONSE; } - if (outbound) - dest_cport_id = connection->interface_cport_id; - else - dest_cport_id = CPORT_ID_BAD; - message->buffer = hd->driver->buffer_alloc(size, gfp_flags); if (!message->buffer) return -ENOMEM; message->buffer_size = size; - message->dest_cport_id = dest_cport_id; message->status = -EBADR; /* Initial value--means "never set" */ /* Fill in the header structure */ diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 5e068ff..81fd7f7 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -28,7 +28,6 @@ struct gb_message { void *payload; struct gb_operation *operation; - u16 dest_cport_id; /* Destination CPort id */ int status; void *buffer; -- cgit v0.10.2 From de80073a1768b0fb01df0e597225047fd66e8044 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 18 Nov 2014 13:26:54 -0600 Subject: greybus: pass gfp_flags for message allocation The only reason gb_operation_message_init() gets its "outbound" argument is so we can determine what allocation flags to use. Just pass the flags in directly instead. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 705b195..96f4c68 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -230,13 +230,12 @@ static void operation_timeout(struct work_struct *work) */ static int gb_operation_message_init(struct gb_operation *operation, u8 type, size_t size, - bool request, bool outbound) + bool request, gfp_t gfp_flags) { struct gb_connection *connection = operation->connection; struct greybus_host_device *hd = connection->hd; struct gb_message *message; struct gb_operation_msg_hdr *header; - gfp_t gfp_flags = request && !outbound ? GFP_ATOMIC : GFP_KERNEL; if (size > GB_OPERATION_MESSAGE_SIZE_MAX) return -E2BIG; @@ -311,13 +310,13 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, operation->connection = connection; ret = gb_operation_message_init(operation, type, request_size, - true, outgoing); + true, gfp_flags); if (ret) goto err_cache; if (outgoing) { ret = gb_operation_message_init(operation, type, response_size, - false, false); + false, GFP_KERNEL); if (ret) goto err_request; } -- cgit v0.10.2 From 42a946688d4b992d176a887638e7943d61a3e8f5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 19 Nov 2014 10:36:23 -0800 Subject: greybus: vibrator-gb.c: fix up incorrect comment s/i2c/vibrator/ Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/vibrator-gb.c b/drivers/staging/greybus/vibrator-gb.c index b9ec772..9b15ae2 100644 --- a/drivers/staging/greybus/vibrator-gb.c +++ b/drivers/staging/greybus/vibrator-gb.c @@ -22,7 +22,7 @@ struct gb_vibrator_device { u8 version_minor; }; -/* Version of the Greybus i2c protocol we support */ +/* Version of the Greybus vibrator protocol we support */ #define GB_VIBRATOR_VERSION_MAJOR 0x00 #define GB_VIBRATOR_VERSION_MINOR 0x01 -- cgit v0.10.2 From e2dabb7c3173020a7497b18d7430a895f80ba9ce Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 19 Nov 2014 17:24:56 +0530 Subject: greybus: ap: remove extra parameter to convert_ap_message() Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 990e5c0..d68221b 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -249,11 +249,11 @@ static void svc_suspend(struct svc_function_suspend *suspend, dev_err(hd->parent, "Got an suspend message???\n"); } -static struct svc_msg *convert_ap_message(struct ap_msg *ap_msg, - struct greybus_host_device *hd) +static struct svc_msg *convert_ap_message(struct ap_msg *ap_msg) { struct svc_msg *svc_msg; struct svc_msg_header *header; + struct greybus_host_device *hd = ap_msg->hd; svc_msg = (struct svc_msg *)ap_msg->data; header = &svc_msg->header; @@ -285,7 +285,7 @@ static void ap_process_event(struct work_struct *work) hd = ap_msg->hd; /* Turn the "raw" data into a real message */ - svc_msg = convert_ap_message(ap_msg, hd); + svc_msg = convert_ap_message(ap_msg); if (!svc_msg) return; -- cgit v0.10.2 From a4040ab7e68ee9b1e4750f42c93b49bc53768b0c Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 19 Nov 2014 17:24:57 +0530 Subject: greybus: ap: keep all svc function routines together Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index d68221b..ef64068 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -60,6 +60,24 @@ static int svc_msg_send(struct svc_msg *svc_msg, struct greybus_host_device *hd) } +int svc_set_route_send(struct gb_interface *interface, + struct greybus_host_device *hd) +{ + struct svc_msg *svc_msg; + + svc_msg = svc_msg_alloc(SVC_FUNCTION_UNIPRO_NETWORK_MANAGEMENT); + if (!svc_msg) + return -ENOMEM; + + svc_msg->header.function_id = SVC_FUNCTION_UNIPRO_NETWORK_MANAGEMENT; + svc_msg->header.message_type = SVC_MSG_DATA; + svc_msg->header.payload_length = + cpu_to_le16(sizeof(struct svc_function_unipro_set_route)); + svc_msg->management.set_route.device_id = interface->device_id; + + return svc_msg_send(svc_msg, hd); +} + static void svc_handshake(struct svc_function_handshake *handshake, int payload_length, struct greybus_host_device *hd) { @@ -104,24 +122,6 @@ static void svc_handshake(struct svc_function_handshake *handshake, (void)svc_msg_send(svc_msg, hd); } -int svc_set_route_send(struct gb_interface *interface, - struct greybus_host_device *hd) -{ - struct svc_msg *svc_msg; - - svc_msg = svc_msg_alloc(SVC_FUNCTION_UNIPRO_NETWORK_MANAGEMENT); - if (!svc_msg) - return -ENOMEM; - - svc_msg->header.function_id = SVC_FUNCTION_UNIPRO_NETWORK_MANAGEMENT; - svc_msg->header.message_type = SVC_MSG_DATA; - svc_msg->header.payload_length = - cpu_to_le16(sizeof(struct svc_function_unipro_set_route)); - svc_msg->management.set_route.device_id = interface->device_id; - - return svc_msg_send(svc_msg, hd); -} - static void svc_management(struct svc_function_unipro_management *management, int payload_length, struct greybus_host_device *hd) { -- cgit v0.10.2 From 64e69291d9d6c14c133910bb0d8b5072fbd4397d Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 19 Nov 2014 17:24:58 +0530 Subject: greybus: Pass '*ptr' to sizeof() wherever possible Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index ef64068..a3bf146 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -83,7 +83,7 @@ static void svc_handshake(struct svc_function_handshake *handshake, { struct svc_msg *svc_msg; - if (payload_length != sizeof(struct svc_function_handshake)) { + if (payload_length != sizeof(*handshake)) { dev_err(hd->parent, "Illegal size of svc handshake message %d\n", payload_length); @@ -114,7 +114,7 @@ static void svc_handshake(struct svc_function_handshake *handshake, svc_msg->header.function_id = SVC_FUNCTION_HANDSHAKE; svc_msg->header.message_type = SVC_MSG_DATA; svc_msg->header.payload_length = - cpu_to_le16(sizeof(struct svc_function_handshake)); + cpu_to_le16(sizeof(*handshake)); svc_msg->handshake.version_major = GREYBUS_VERSION_MAJOR; svc_msg->handshake.version_minor = GREYBUS_VERSION_MINOR; svc_msg->handshake.handshake_type = SVC_HANDSHAKE_AP_HELLO; @@ -128,7 +128,7 @@ static void svc_management(struct svc_function_unipro_management *management, struct gb_module *module; int ret; - if (payload_length != sizeof(struct svc_function_unipro_management)) { + if (payload_length != sizeof(*management)) { dev_err(hd->parent, "Illegal size of svc management message %d\n", payload_length); @@ -221,7 +221,7 @@ static void svc_power(struct svc_function_power *power, * big, we can just check the union of the whole structure to validate * the size of this message. */ - if (payload_length != sizeof(struct svc_function_power)) { + if (payload_length != sizeof(*power)) { dev_err(hd->parent, "Illegal size of svc power message %d\n", payload_length); diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index 3374173..c810c42 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -311,8 +311,8 @@ gb_i2c_transfer_request(struct gb_connection *connection, else data_out_size += (u32)msg->len; - request_size = sizeof(struct gb_i2c_transfer_request); - request_size += msg_count * sizeof(struct gb_i2c_transfer_op); + request_size = sizeof(*request); + request_size += msg_count * sizeof(*op); request_size += data_out_size; /* Response consists only of incoming data */ diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 9014611..3754035 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -81,7 +81,7 @@ static int identify_descriptor(struct greybus_descriptor *desc, size_t size) } break; case GREYBUS_TYPE_STRING: - expected_size = sizeof(struct greybus_descriptor_header); + expected_size = sizeof(*desc_header); expected_size += sizeof(struct greybus_descriptor_string); expected_size += (size_t)desc->string.length; if (desc_size < expected_size) { diff --git a/drivers/staging/greybus/sdio-gb.c b/drivers/staging/greybus/sdio-gb.c index 4775ed0..3f11365 100644 --- a/drivers/staging/greybus/sdio-gb.c +++ b/drivers/staging/greybus/sdio-gb.c @@ -46,7 +46,7 @@ static int gb_sdio_connection_init(struct gb_connection *connection) struct mmc_host *mmc; struct gb_sdio_host *host; - mmc = mmc_alloc_host(sizeof(struct gb_sdio_host), &connection->dev); + mmc = mmc_alloc_host(sizeof(*host), &connection->dev); if (!mmc) return -ENOMEM; -- cgit v0.10.2 From c002b0ec60c5d7acc8cc7af88ed6845f3e656fc7 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 19 Nov 2014 17:24:59 +0530 Subject: greybus: ap: function_id is already set by svc_msg_alloc() Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index a3bf146..3536717 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -69,7 +69,6 @@ int svc_set_route_send(struct gb_interface *interface, if (!svc_msg) return -ENOMEM; - svc_msg->header.function_id = SVC_FUNCTION_UNIPRO_NETWORK_MANAGEMENT; svc_msg->header.message_type = SVC_MSG_DATA; svc_msg->header.payload_length = cpu_to_le16(sizeof(struct svc_function_unipro_set_route)); @@ -111,7 +110,6 @@ static void svc_handshake(struct svc_function_handshake *handshake, if (!svc_msg) return; - svc_msg->header.function_id = SVC_FUNCTION_HANDSHAKE; svc_msg->header.message_type = SVC_MSG_DATA; svc_msg->header.payload_length = cpu_to_le16(sizeof(*handshake)); -- cgit v0.10.2 From 2292bac5e76846387152d1d20b10cb79f8c1b14b Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 19 Nov 2014 12:27:13 -0600 Subject: greybus: explicitly mark cookies as opaque Use simple macros to mark the conversion of an URB pointer into an opaque cookie value (and vice-versa). We scramble some bits, but the main point is to make it explicit where we're returning and using opaque values. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 3404dc5..658506d 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -16,6 +16,13 @@ #include "svc_msg.h" #include "kernel_ver.h" +/* + * Macros for making pointers explicitly opaque, such that the result + * isn't valid but also can't be mistaken for an ERR_PTR() value. + */ +#define conceal_urb(urb) ((void *)((uintptr_t)(urb) ^ 0xbad)) +#define reveal_urb(cookie) ((void *)((uintptr_t)(cookie) ^ 0xbad)) + /* Memory sizes for the buffers sent to/from the ES1 controller */ #define ES1_SVC_MSG_SIZE (sizeof(struct svc_msg) + SZ_64K) #define ES1_GBUF_MSG_SIZE PAGE_SIZE @@ -241,12 +248,12 @@ static void *buffer_send(struct greybus_host_device *hd, u16 dest_cport_id, return ERR_PTR(retval); } - return urb; + return conceal_urb(urb); } static void buffer_cancel(void *cookie) { - struct urb *urb = cookie; + struct urb *urb = reveal_urb(cookie); /* * We really should be defensive and track all outstanding -- cgit v0.10.2 From c41f1651c4962e56548a5b580e60f66a724357e7 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 19 Nov 2014 12:27:14 -0600 Subject: greybus: tidy up svc_in_callback() and cport_in_callback() The only use of local variable "es1" in in svc_in_callback() and cport_in_callback() is to get at its hd field. But we already have that, so we can get rid of that local variable. Also, rename the "cport" variable "cport_id" in cport_in_callback() is to match the convention used elsewhere, and make it the proper u16 type. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 658506d..7745b81 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -346,7 +346,6 @@ static void ap_disconnect(struct usb_interface *interface) static void svc_in_callback(struct urb *urb) { struct greybus_host_device *hd = urb->context; - struct es1_ap_dev *es1 = hd_to_es1(hd); struct device *dev = &urb->dev->dev; int status = check_urb_status(urb); int retval; @@ -361,7 +360,7 @@ static void svc_in_callback(struct urb *urb) /* We have a message, create a new message structure, add it to the * list, and wake up our thread that will process the messages. */ - greybus_svc_in(es1->hd, urb->transfer_buffer, urb->actual_length); + greybus_svc_in(hd, urb->transfer_buffer, urb->actual_length); exit: /* resubmit the urb to get more messages */ @@ -373,11 +372,10 @@ exit: static void cport_in_callback(struct urb *urb) { struct greybus_host_device *hd = urb->context; - struct es1_ap_dev *es1 = hd_to_es1(hd); struct device *dev = &urb->dev->dev; int status = check_urb_status(urb); int retval; - u8 cport; + u16 cport_id; u8 *data; if (status) { @@ -398,11 +396,11 @@ static void cport_in_callback(struct urb *urb) * the stream is "real" data */ data = urb->transfer_buffer; - cport = data[0]; + cport_id = (u16)data[0]; data = &data[1]; /* Pass this data to the greybus core */ - greybus_cport_in(es1->hd, cport, data, urb->actual_length - 1); + greybus_cport_in(hd, cport_id, data, urb->actual_length - 1); exit: /* put our urb back in the request pool */ -- cgit v0.10.2 From 6014718d4db9d48a980d70c66a7617293db633e6 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 19 Nov 2014 12:27:15 -0600 Subject: greybus: get rid of message status We (sort of) maintain the status of each message, but we shouldn't need to. Right now we're not using it consistently in any case. If a message fails to send, the caller will know to destroy the operation that contained it. If a message has been sent (i.e., handed to the host device layer) it'll have a non-null cookie pointer. If a does complete in error, we can update the status of the operation that contains it. That isn't happening right now but it will soon. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 96f4c68..05a61d8 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -107,28 +107,30 @@ static int gb_message_send(struct gb_message *message, gfp_t gfp_mask) { struct gb_connection *connection = message->operation->connection; u16 dest_cport_id = connection->interface_cport_id; + int ret = 0; - message->status = -EINPROGRESS; message->cookie = connection->hd->driver->buffer_send(connection->hd, dest_cport_id, message->buffer, message->buffer_size, gfp_mask); if (IS_ERR(message->cookie)) { - message->status = PTR_ERR(message->cookie); + ret = PTR_ERR(message->cookie); message->cookie = NULL; - - return message->status; } - return 0; + return ret; } +/* + * Cancel a message whose buffer we have passed to the host device + * layer to be sent. + */ static void gb_message_cancel(struct gb_message *message) { struct greybus_host_device *hd; - if (message->status != -EINPROGRESS) - return; + if (!message->cookie) + return; /* Don't bother if the message isn't in flight */ hd = message->operation->connection->hd; hd->driver->buffer_cancel(message->cookie); @@ -252,7 +254,6 @@ static int gb_operation_message_init(struct gb_operation *operation, if (!message->buffer) return -ENOMEM; message->buffer_size = size; - message->status = -EBADR; /* Initial value--means "never set" */ /* Fill in the header structure */ header = message->buffer; diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 81fd7f7..80ee158 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -28,7 +28,6 @@ struct gb_message { void *payload; struct gb_operation *operation; - int status; void *buffer; size_t buffer_size; -- cgit v0.10.2 From 8fc71a73363f742c70ef5d570b795583124efd29 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 19 Nov 2014 12:27:16 -0600 Subject: greybus: use "operation_id" for certain values A message header contains a field "id" that is an operation id. Since the field doesn't identify the message itself, rename this field so it's clearer what it's referring to. Similarly gb_pending_operation_find() has a parameter "id" that is really an operation id, so rename that as well. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 05a61d8..bd50c6e 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -48,9 +48,9 @@ static struct workqueue_struct *gb_operation_recv_workqueue; * header, and is 64-bit aligned. */ struct gb_operation_msg_hdr { - __le16 size; /* Size in bytes of header + payload */ - __le16 id; /* Operation unique id */ - __u8 type; /* E.g GB_I2C_TYPE_* or GB_GPIO_TYPE_* */ + __le16 size; /* Size in bytes of header + payload */ + __le16 operation_id; /* Operation unique id */ + __u8 type; /* E.g GB_I2C_TYPE_* or GB_GPIO_TYPE_* */ /* 3 bytes pad, must be zero (ignore when read) */ } __aligned(sizeof(u64)); @@ -73,7 +73,7 @@ static void gb_pending_operation_insert(struct gb_operation *operation) /* Store the operation id in the request header */ header = operation->request.buffer; - header->id = cpu_to_le16(operation->id); + header->operation_id = cpu_to_le16(operation->id); } static void gb_pending_operation_remove(struct gb_operation *operation) @@ -87,14 +87,14 @@ static void gb_pending_operation_remove(struct gb_operation *operation) } static struct gb_operation * -gb_pending_operation_find(struct gb_connection *connection, u16 id) +gb_pending_operation_find(struct gb_connection *connection, u16 operation_id) { struct gb_operation *operation; bool found = false; spin_lock_irq(&gb_operations_lock); list_for_each_entry(operation, &connection->pending, links) - if (operation->id == id) { + if (operation->id == operation_id) { found = true; break; } @@ -258,7 +258,7 @@ static int gb_operation_message_init(struct gb_operation *operation, /* Fill in the header structure */ header = message->buffer; header->size = cpu_to_le16(size); - header->id = 0; /* Filled in when submitted */ + header->operation_id = 0; /* Filled in when submitted */ header->type = type; message->payload = header + 1; @@ -450,9 +450,9 @@ void gb_connection_recv(struct gb_connection *connection, header = data; msg_size = le16_to_cpu(header->size); if (header->type & GB_OPERATION_TYPE_RESPONSE) { - u16 id = le16_to_cpu(header->id); + u16 operation_id = le16_to_cpu(header->operation_id); - operation = gb_pending_operation_find(connection, id); + operation = gb_pending_operation_find(connection, operation_id); if (!operation) { gb_connection_err(connection, "operation not found"); return; -- cgit v0.10.2 From d37b1db13f8b5f3ad27aff5aa487b4ea2a298aa4 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 19 Nov 2014 12:27:17 -0600 Subject: greybus: refactor gb_connection_recv() Define two helper functions to break down handling of a received message. One is used to handle receiving an incoming request message, the other for a response message. Three other changes are made: - We verify message size recorded in the message header does not exceed the amount of data that's arriving. - We no longer warn if a request' recorded message size differs from the number of bytes that have arrived. - We now record the operation id for an incoming request. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index bd50c6e..520214b 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -418,29 +418,83 @@ int gb_operation_response_send(struct gb_operation *operation) } /* - * Handle data arriving on a connection. As soon as we return, the - * incoming data buffer will be reused, so we need to copy the data - * into one of our own operation message buffers. - * - * If the incoming data is an operation response message, look up - * the operation and copy the incoming data into its response - * buffer. Otherwise allocate a new operation and copy the incoming - * data into its request buffer. + * We've received data on a connection, and it doesn't look like a + * response, so we assume it's a request. * * This is called in interrupt context, so just copy the incoming - * data into the buffer and do remaining handling via a work queue. + * data into the request buffer and handle the rest via workqueue. + */ +void gb_connection_recv_request(struct gb_connection *connection, + u16 operation_id, u8 type, void *data, size_t size) +{ + struct gb_operation *operation; + + operation = gb_operation_create(connection, type, size, 0); + if (!operation) { + gb_connection_err(connection, "can't create operation"); + return; /* XXX Respond with pre-allocated ENOMEM */ + } + operation->id = operation_id; + memcpy(operation->request.buffer, data, size); + + /* The rest will be handled in work queue context */ + queue_work(gb_operation_recv_workqueue, &operation->recv_work); +} + +/* + * We've received data that appears to be an operation response + * message. Look up the operation, and record that we've received + * its repsonse. * + * This is called in interrupt context, so just copy the incoming + * data into the response buffer and handle the rest via workqueue. + */ +static void gb_connection_recv_response(struct gb_connection *connection, + u16 operation_id, void *data, size_t size) +{ + struct gb_operation *operation; + struct gb_message *message; + + operation = gb_pending_operation_find(connection, operation_id); + if (!operation) { + gb_connection_err(connection, "operation not found"); + return; + } + + cancel_delayed_work(&operation->timeout_work); + gb_pending_operation_remove(operation); + + message = &operation->response; + if (size > message->buffer_size) { + operation->result = GB_OP_OVERFLOW; + gb_connection_err(connection, "recv buffer too small"); + return; /* XXX Should still complete operation */ + } + operation->result = GB_OP_SUCCESS; /* XXX Maybe not yet? */ + + memcpy(message->buffer, data, size); + + /* The rest will be handled in work queue context */ + queue_work(gb_operation_recv_workqueue, &operation->recv_work); +} + +/* + * Handle data arriving on a connection. As soon as we return the + * supplied data buffer will be reused (so unless we do something + * with, it's effectively dropped). */ void gb_connection_recv(struct gb_connection *connection, void *data, size_t size) { struct gb_operation_msg_hdr *header; - struct gb_operation *operation; - struct gb_message *message; - u16 msg_size; + size_t msg_size; + u16 operation_id; - if (connection->state != GB_CONNECTION_STATE_ENABLED) + if (connection->state != GB_CONNECTION_STATE_ENABLED) { + gb_connection_err(connection, "dropping %zu received bytes", + size); return; + } if (size < sizeof(*header)) { gb_connection_err(connection, "message too small"); @@ -448,39 +502,19 @@ void gb_connection_recv(struct gb_connection *connection, } header = data; - msg_size = le16_to_cpu(header->size); - if (header->type & GB_OPERATION_TYPE_RESPONSE) { - u16 operation_id = le16_to_cpu(header->operation_id); - - operation = gb_pending_operation_find(connection, operation_id); - if (!operation) { - gb_connection_err(connection, "operation not found"); - return; - } - cancel_delayed_work(&operation->timeout_work); - gb_pending_operation_remove(operation); - message = &operation->response; - if (size > message->buffer_size) { - operation->result = GB_OP_OVERFLOW; - gb_connection_err(connection, "recv buffer too small"); - return; - } - operation->result = GB_OP_SUCCESS; - } else { - WARN_ON(msg_size != size); - operation = gb_operation_create(connection, header->type, - msg_size, 0); - if (!operation) { - gb_connection_err(connection, "can't create operation"); - return; - } - message = &operation->request; + msg_size = (size_t)le16_to_cpu(header->size); + if (msg_size > size) { + gb_connection_err(connection, "incomplete message"); + return; /* XXX Should still complete operation */ } - memcpy(message->buffer, data, msg_size); - - /* The rest will be handled in work queue context */ - queue_work(gb_operation_recv_workqueue, &operation->recv_work); + operation_id = le16_to_cpu(header->operation_id); + if (header->type & GB_OPERATION_TYPE_RESPONSE) + gb_connection_recv_response(connection, operation_id, + data, msg_size); + else + gb_connection_recv_request(connection, operation_id, + header->type, data, msg_size); } /* -- cgit v0.10.2 From 8abf4148030d42825d4f76f4a3cf734dbc2bcd2b Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 19 Nov 2014 17:25:00 +0530 Subject: greybus: operation: don't complete operation twice Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 520214b..a2b27ae 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -176,14 +176,12 @@ static void gb_operation_request_handle(struct gb_operation *operation) */ if (protocol->request_recv) { protocol->request_recv(header->type, operation); - goto out; + return; } gb_connection_err(operation->connection, "unexpected incoming request type 0x%02hhx\n", header->type); operation->result = GB_OP_PROTOCOL_BAD; -out: - gb_operation_complete(operation); } /* -- cgit v0.10.2 From 0bbfe04cd945df79c52924284b2242508fef4e47 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 19 Nov 2014 16:29:14 -0600 Subject: greybus: fix battery_operation() This patch fixes some problems with the battery protocol driver. First, when gb_operation_create() is called, it creates buffers of the requested sizes to hold the operation request and response messages. There is therefore no reason to allocate a local response buffer. By the time the (synchronous) gb_operation_request_send() call returns, the operation response buffer will have been filled in. (In addition, the content of local_response was not being filled before its contents were used...) Next, all the message structures are misnamed. The structures that are defined are all the content of operation response messages (not request messages). So this changes all the types names to properly reflect their role. All the local variables using these types are similarly renamed. I added a new type, gb_generic_battery_response, to be used for casting the fake_response used in battery_operation(). Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index 4bd7aed..101c3de 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -54,7 +54,7 @@ struct gb_battery_proto_version_response { #define GB_BATTERY_TECH_NiCd 0x0005 #define GB_BATTERY_TECH_LiMn 0x0006 -struct gb_battery_technology_request { +struct gb_battery_technology_response { __u8 status; __le32 technology; }; @@ -66,50 +66,53 @@ struct gb_battery_technology_request { #define GB_BATTERY_STATUS_NOT_CHARGING 0x0003 #define GB_BATTERY_STATUS_FULL 0x0004 -struct gb_battery_status_request { +struct gb_battery_status_response { __u8 status; __le16 battery_status; }; -struct gb_battery_max_voltage_request { +struct gb_battery_max_voltage_response { __u8 status; __le32 max_voltage; }; -struct gb_battery_capacity_request { +struct gb_battery_capacity_response { __u8 status; __le32 capacity; }; -struct gb_battery_temperature_request { +struct gb_battery_temperature_response { __u8 status; __le32 temperature; }; -struct gb_battery_voltage_request { +struct gb_battery_voltage_response { __u8 status; __le32 voltage; }; +/* Generia response structure--prefix for all other responses */ +struct gb_generic_battery_response { + __u8 status; +}; +/* + * None of the battery operation requests have any payload. This + * function implements all of the requests by allowing the caller to + * supply a buffer into which the operation response should be + * copied. + */ static int battery_operation(struct gb_battery *gb, int type, void *response, int response_size) { struct gb_connection *connection = gb->connection; struct gb_operation *operation; - struct gb_battery_technology_request *fake_request; - u8 *local_response; + struct gb_generic_battery_response *fake_response; int ret; - local_response = kmalloc(response_size, GFP_KERNEL); - if (!local_response) - return -ENOMEM; - operation = gb_operation_create(connection, type, 0, response_size); - if (!operation) { - kfree(local_response); + if (!operation) return -ENOMEM; - } /* Synchronous operation--no callback */ ret = gb_operation_request_send(operation, NULL); @@ -123,18 +126,17 @@ static int battery_operation(struct gb_battery *gb, int type, * layout for where the status is, so cast this to a random request so * we can see the status easier. */ - fake_request = (struct gb_battery_technology_request *)local_response; - if (fake_request->status) { + fake_response = operation->response.payload; + if (fake_response->status) { gb_connection_err(connection, "version response %hhu", - fake_request->status); + fake_response->status); ret = -EIO; } else { - /* Good request, so copy to the caller's buffer */ - memcpy(response, local_response, response_size); + /* Good response, so copy to the caller's buffer */ + memcpy(response, fake_response, response_size); } out: gb_operation_destroy(operation); - kfree(local_response); return ret; } @@ -145,33 +147,33 @@ out: */ static int get_version(struct gb_battery *gb) { - struct gb_battery_proto_version_response version_request; + struct gb_battery_proto_version_response version_response; int retval; retval = battery_operation(gb, GB_BATTERY_TYPE_PROTOCOL_VERSION, - &version_request, sizeof(version_request)); + &version_response, sizeof(version_response)); if (retval) return retval; - if (version_request.major > GB_BATTERY_VERSION_MAJOR) { + if (version_response.major > GB_BATTERY_VERSION_MAJOR) { pr_err("unsupported major version (%hhu > %hhu)\n", - version_request.major, GB_BATTERY_VERSION_MAJOR); + version_response.major, GB_BATTERY_VERSION_MAJOR); return -ENOTSUPP; } - gb->version_major = version_request.major; - gb->version_minor = version_request.minor; + gb->version_major = version_response.major; + gb->version_minor = version_response.minor; return 0; } static int get_tech(struct gb_battery *gb) { - struct gb_battery_technology_request tech_request; + struct gb_battery_technology_response tech_response; u32 technology; int retval; retval = battery_operation(gb, GB_BATTERY_TYPE_TECHNOLOGY, - &tech_request, sizeof(tech_request)); + &tech_response, sizeof(tech_response)); if (retval) return retval; @@ -180,7 +182,7 @@ static int get_tech(struct gb_battery *gb) * "identical" which should allow gcc to optomize the code away to * nothing. */ - technology = le32_to_cpu(tech_request.technology); + technology = le32_to_cpu(tech_response.technology); switch (technology) { case GB_BATTERY_TECH_NiMH: technology = POWER_SUPPLY_TECHNOLOGY_NiMH; @@ -210,12 +212,12 @@ static int get_tech(struct gb_battery *gb) static int get_status(struct gb_battery *gb) { - struct gb_battery_status_request status_request; + struct gb_battery_status_response status_response; u16 battery_status; int retval; retval = battery_operation(gb, GB_BATTERY_TYPE_STATUS, - &status_request, sizeof(status_request)); + &status_response, sizeof(status_response)); if (retval) return retval; @@ -224,7 +226,7 @@ static int get_status(struct gb_battery *gb) * "identical" which should allow gcc to optomize the code away to * nothing. */ - battery_status = le16_to_cpu(status_request.battery_status); + battery_status = le16_to_cpu(status_response.battery_status); switch (battery_status) { case GB_BATTERY_STATUS_CHARGING: battery_status = POWER_SUPPLY_STATUS_CHARGING; @@ -248,61 +250,61 @@ static int get_status(struct gb_battery *gb) static int get_max_voltage(struct gb_battery *gb) { - struct gb_battery_max_voltage_request volt_request; + struct gb_battery_max_voltage_response volt_response; u32 max_voltage; int retval; retval = battery_operation(gb, GB_BATTERY_TYPE_MAX_VOLTAGE, - &volt_request, sizeof(volt_request)); + &volt_response, sizeof(volt_response)); if (retval) return retval; - max_voltage = le32_to_cpu(volt_request.max_voltage); + max_voltage = le32_to_cpu(volt_response.max_voltage); return max_voltage; } static int get_capacity(struct gb_battery *gb) { - struct gb_battery_capacity_request capacity_request; + struct gb_battery_capacity_response capacity_response; u32 capacity; int retval; retval = battery_operation(gb, GB_BATTERY_TYPE_CAPACITY, - &capacity_request, sizeof(capacity_request)); + &capacity_response, sizeof(capacity_response)); if (retval) return retval; - capacity = le32_to_cpu(capacity_request.capacity); + capacity = le32_to_cpu(capacity_response.capacity); return capacity; } static int get_temp(struct gb_battery *gb) { - struct gb_battery_temperature_request temp_request; + struct gb_battery_temperature_response temp_response; u32 temperature; int retval; retval = battery_operation(gb, GB_BATTERY_TYPE_TEMPERATURE, - &temp_request, sizeof(temp_request)); + &temp_response, sizeof(temp_response)); if (retval) return retval; - temperature = le32_to_cpu(temp_request.temperature); + temperature = le32_to_cpu(temp_response.temperature); return temperature; } static int get_voltage(struct gb_battery *gb) { - struct gb_battery_voltage_request voltage_request; + struct gb_battery_voltage_response voltage_response; u32 voltage; int retval; retval = battery_operation(gb, GB_BATTERY_TYPE_VOLTAGE, - &voltage_request, sizeof(voltage_request)); + &voltage_response, sizeof(voltage_response)); if (retval) return retval; - voltage = le32_to_cpu(voltage_request.voltage); + voltage = le32_to_cpu(voltage_response.voltage); return voltage; } -- cgit v0.10.2 From bc091356ccbf2e08b2a8818efce043669f131e59 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 19 Nov 2014 16:29:15 -0600 Subject: greybus: fix uart request_operation() This fixes a problem similar to what was found in the battery protcool driver code. There's no need to allocate a local buffer, that already set up by gb_operation_create(). Just use that instead. Change a few variable names to reflect that they hold response messages, not request messages. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index a8c342e..d01956a 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -144,19 +144,12 @@ static int request_operation(struct gb_connection *connection, int type, void *response, int response_size) { struct gb_operation *operation; - struct gb_uart_simple_response *fake_request; - u8 *local_response; + struct gb_uart_simple_response *fake_response; int ret; - local_response = kmalloc(response_size, GFP_KERNEL); - if (!local_response) - return -ENOMEM; - operation = gb_operation_create(connection, type, 0, response_size); - if (!operation) { - kfree(local_response); + if (!operation) return -ENOMEM; - } /* Synchronous operation--no callback */ ret = gb_operation_request_send(operation, NULL); @@ -170,19 +163,18 @@ static int request_operation(struct gb_connection *connection, int type, * layout for where the status is, so cast this to a random request so * we can see the status easier. */ - fake_request = (struct gb_uart_simple_response *)local_response; - if (fake_request->status) { + fake_response = operation->response.payload; + if (fake_response->status) { gb_connection_err(connection, "response %hhu", - fake_request->status); + fake_response->status); ret = -EIO; } else { /* Good request, so copy to the caller's buffer */ if (response_size && response) - memcpy(response, local_response, response_size); + memcpy(response, fake_response, response_size); } out: gb_operation_destroy(operation); - kfree(local_response); return ret; } @@ -193,23 +185,23 @@ out: */ static int get_version(struct gb_tty *tty) { - struct gb_uart_proto_version_response version_request; + struct gb_uart_proto_version_response version_response; int retval; retval = request_operation(tty->connection, GB_UART_REQ_PROTOCOL_VERSION, - &version_request, sizeof(version_request)); + &version_response, sizeof(version_response)); if (retval) return retval; - if (version_request.major > GB_UART_VERSION_MAJOR) { + if (version_response.major > GB_UART_VERSION_MAJOR) { pr_err("unsupported major version (%hhu > %hhu)\n", - version_request.major, GB_UART_VERSION_MAJOR); + version_response.major, GB_UART_VERSION_MAJOR); return -ENOTSUPP; } - tty->version_major = version_request.major; - tty->version_minor = version_request.minor; + tty->version_major = version_response.major; + tty->version_minor = version_response.minor; return 0; } -- cgit v0.10.2 From d122382f88e0a2849e758acb46140d3085b3dc61 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 19 Nov 2014 17:05:14 -0600 Subject: greybus: fix vibrator request_operation() And this fixes a problem similar the last two, this time found in the vibrator protcool driver code. Change a variable name in get_version() to reflect that it holds a response message, not a request message. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/vibrator-gb.c b/drivers/staging/greybus/vibrator-gb.c index 9b15ae2..3e46fa6 100644 --- a/drivers/staging/greybus/vibrator-gb.c +++ b/drivers/staging/greybus/vibrator-gb.c @@ -51,19 +51,12 @@ static int request_operation(struct gb_connection *connection, int type, void *response, int response_size) { struct gb_operation *operation; - struct gb_vibrator_simple_response *fake_request; - u8 *local_response; + struct gb_vibrator_simple_response *fake_response; int ret; - local_response = kmalloc(response_size, GFP_KERNEL); - if (!local_response) - return -ENOMEM; - operation = gb_operation_create(connection, type, 0, response_size); - if (!operation) { - kfree(local_response); + if (!operation) return -ENOMEM; - } /* Synchronous operation--no callback */ ret = gb_operation_request_send(operation, NULL); @@ -77,19 +70,18 @@ static int request_operation(struct gb_connection *connection, int type, * layout for where the status is, so cast this to a random request so * we can see the status easier. */ - fake_request = (struct gb_vibrator_simple_response *)local_response; - if (fake_request->status) { + fake_response = operation->response.payload; + if (fake_response->status) { gb_connection_err(connection, "response %hhu", - fake_request->status); + fake_response->status); ret = -EIO; } else { /* Good request, so copy to the caller's buffer */ if (response_size && response) - memcpy(response, local_response, response_size); + memcpy(response, fake_response, response_size); } out: gb_operation_destroy(operation); - kfree(local_response); return ret; } @@ -101,24 +93,24 @@ out: static int get_version(struct gb_vibrator_device *vib) { struct gb_connection *connection = vib->connection; - struct gb_vibrator_proto_version_response version_request; + struct gb_vibrator_proto_version_response version_response; int retval; retval = request_operation(connection, GB_VIBRATOR_TYPE_PROTOCOL_VERSION, - &version_request, sizeof(version_request)); + &version_response, sizeof(version_response)); if (retval) return retval; - if (version_request.major > GB_VIBRATOR_VERSION_MAJOR) { + if (version_response.major > GB_VIBRATOR_VERSION_MAJOR) { dev_err(&connection->dev, "unsupported major version (%hhu > %hhu)\n", - version_request.major, GB_VIBRATOR_VERSION_MAJOR); + version_response.major, GB_VIBRATOR_VERSION_MAJOR); return -ENOTSUPP; } - vib->version_major = version_request.major; - vib->version_minor = version_request.minor; + vib->version_major = version_response.major; + vib->version_minor = version_response.minor; return 0; } -- cgit v0.10.2 From 980c7c509eb36c693576ad342a11455f530db0b9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 19 Nov 2014 14:23:00 -0800 Subject: greybus: uart-gb: handle throttle/unthrottle properly This hooks up throttle/unthrottle to properly toggle the RTS line or do XON/XOFF if that is how the port is set up. Note, if the UART itself can handle XON/XOFF, we would need to send the correct character down to it, to have the firmware in the device set up the chip to use it automatically when needed. The odds of someone wanting to use this type of flow control is slim, so this isn't implemented at this point in time. Also fill in a few more fields in the get_serial_info ioctl, to make tools like stty(1) happier. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index d01956a..460947e 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -116,10 +116,7 @@ struct gb_tty { u16 cport_id; unsigned int minor; unsigned char clocal; - unsigned int throttled:1; - unsigned int throttle_req:1; bool disconnected; - int writesize; // FIXME - set this somehow. spinlock_t read_lock; spinlock_t write_lock; struct async_icount iocount; @@ -567,25 +564,39 @@ static int gb_tty_tiocmset(struct tty_struct *tty, unsigned int set, static void gb_tty_throttle(struct tty_struct *tty) { struct gb_tty *gb_tty = tty->driver_data; + unsigned char stop_char; + int retval; + + if (I_IXOFF(tty)) { + stop_char = STOP_CHAR(tty); + retval = gb_tty_write(tty, &stop_char, 1); + if (retval <= 0) + return; + } + + if (tty->termios.c_cflag & CRTSCTS) { + gb_tty->ctrlout &= ~GB_UART_CTRL_RTS; + retval = send_control(gb_tty, gb_tty->ctrlout); + } - spin_lock_irq(&gb_tty->read_lock); - gb_tty->throttle_req = 1; - spin_unlock_irq(&gb_tty->read_lock); } static void gb_tty_unthrottle(struct tty_struct *tty) { struct gb_tty *gb_tty = tty->driver_data; - unsigned int was_throttled; + unsigned char start_char; + int retval; - spin_lock_irq(&gb_tty->read_lock); - was_throttled = gb_tty->throttled; - gb_tty->throttle_req = 0; - gb_tty->throttled = 0; - spin_unlock_irq(&gb_tty->read_lock); + if (I_IXOFF(tty)) { + start_char = START_CHAR(tty); + retval = gb_tty_write(tty, &start_char, 1); + if (retval <= 0) + return; + } - if (was_throttled) { - // FIXME - send more data + if (tty->termios.c_cflag & CRTSCTS) { + gb_tty->ctrlout |= GB_UART_CTRL_RTS; + retval = send_control(gb_tty, gb_tty->ctrlout); } } @@ -598,9 +609,11 @@ static int get_serial_info(struct gb_tty *gb_tty, return -EINVAL; memset(&tmp, 0, sizeof(tmp)); - tmp.flags = ASYNC_LOW_LATENCY; - tmp.xmit_fifo_size = gb_tty->writesize; - tmp.baud_base = 0; // FIXME + tmp.flags = ASYNC_LOW_LATENCY | ASYNC_SKIP_TEST; + tmp.type = PORT_16550A; + tmp.line = gb_tty->minor; + tmp.xmit_fifo_size = 16; + tmp.baud_base = 9600; tmp.close_delay = gb_tty->port.close_delay / 10; tmp.closing_wait = gb_tty->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ? ASYNC_CLOSING_WAIT_NONE : gb_tty->port.closing_wait / 10; -- cgit v0.10.2 From dcec19fb1b10b62e02db9e234f0091509545971e Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 19 Nov 2014 17:55:01 -0600 Subject: greybus: get rid of uart request_operation() In "uart-gb.c", request_operation() function is only used by get_version(). Since it's not reused, it probably subtracts rather than adds value. So just incorporate what it does into get_version() and get rid of request_operation(). Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 460947e..e68f4a2 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -136,15 +136,19 @@ static DEFINE_IDR(tty_minors); static DEFINE_MUTEX(table_lock); static atomic_t reference_count = ATOMIC_INIT(0); - -static int request_operation(struct gb_connection *connection, int type, - void *response, int response_size) +/* + * This request only uses the connection field, and if successful, + * fills in the major and minor protocol version of the target. + */ +static int get_version(struct gb_tty *tty) { struct gb_operation *operation; - struct gb_uart_simple_response *fake_response; + struct gb_uart_proto_version_response *response; int ret; - operation = gb_operation_create(connection, type, 0, response_size); + operation = gb_operation_create(tty->connection, + GB_UART_REQ_PROTOCOL_VERSION, + 0, sizeof(*response)); if (!operation) return -ENOMEM; @@ -155,20 +159,23 @@ static int request_operation(struct gb_connection *connection, int type, goto out; } - /* - * We only want to look at the status, and all requests have the same - * layout for where the status is, so cast this to a random request so - * we can see the status easier. - */ - fake_response = operation->response.payload; - if (fake_response->status) { - gb_connection_err(connection, "response %hhu", - fake_response->status); + response = operation->response.payload; + if (response->status) { + gb_connection_err(tty->connection, "response %hhu", + response->status); ret = -EIO; } else { - /* Good request, so copy to the caller's buffer */ - if (response_size && response) - memcpy(response, fake_response, response_size); + if (response->major > GB_UART_VERSION_MAJOR) { + pr_err("unsupported major version (%hhu > %hhu)\n", + response->major, GB_UART_VERSION_MAJOR); + ret = -ENOTSUPP; + goto out; + } + tty->version_major = response->major; + tty->version_minor = response->minor; + + pr_debug("%s: version_major = %u version_minor = %u\n", + __func__, tty->version_major, tty->version_minor); } out: gb_operation_destroy(operation); @@ -176,32 +183,6 @@ out: return ret; } -/* - * This request only uses the connection field, and if successful, - * fills in the major and minor protocol version of the target. - */ -static int get_version(struct gb_tty *tty) -{ - struct gb_uart_proto_version_response version_response; - int retval; - - retval = request_operation(tty->connection, - GB_UART_REQ_PROTOCOL_VERSION, - &version_response, sizeof(version_response)); - if (retval) - return retval; - - if (version_response.major > GB_UART_VERSION_MAJOR) { - pr_err("unsupported major version (%hhu > %hhu)\n", - version_response.major, GB_UART_VERSION_MAJOR); - return -ENOTSUPP; - } - - tty->version_major = version_response.major; - tty->version_minor = version_response.minor; - return 0; -} - static int send_data(struct gb_tty *tty, u16 size, const u8 *data) { struct gb_connection *connection = tty->connection; -- cgit v0.10.2 From 30a2964f8455ede0f2416a3b6a28b60acc4b569c Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 19 Nov 2014 17:55:02 -0600 Subject: greybus: distinguish incoming from outgoing requests When we remove the mandatory status byte from response messages we will no longer be able to use a zero-sized response to indicate an operation is to be used for an incoming request. Define a new function gb_operation_create_incoming() to be used for incoming operations. Change (and rename) gb_operation_create() to be a helper that takes a Boolean to indicate which type is to be created, and use a simple wrapper to expose the outgoing operation creation routine. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index a2b27ae..8214a37 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -294,13 +294,13 @@ static void gb_operation_message_exit(struct gb_message *message) * Returns a pointer to the new operation or a null pointer if an * error occurs. */ -struct gb_operation *gb_operation_create(struct gb_connection *connection, - u8 type, size_t request_size, - size_t response_size) +static struct gb_operation * +gb_operation_create_common(struct gb_connection *connection, bool outgoing, + u8 type, size_t request_size, + size_t response_size) { struct gb_operation *operation; gfp_t gfp_flags = response_size ? GFP_KERNEL : GFP_ATOMIC; - bool outgoing = response_size != 0; int ret; operation = kmem_cache_zalloc(gb_operation_cache, gfp_flags); @@ -340,6 +340,23 @@ err_cache: return NULL; } +struct gb_operation *gb_operation_create(struct gb_connection *connection, + u8 type, size_t request_size, + size_t response_size) +{ + return gb_operation_create_common(connection, true, type, + request_size, response_size); +} + +static struct gb_operation * +gb_operation_create_incoming(struct gb_connection *connection, + u8 type, size_t request_size, + size_t response_size) +{ + return gb_operation_create_common(connection, false, type, + request_size, response_size); +} + /* * Destroy a previously created operation. */ @@ -427,7 +444,7 @@ void gb_connection_recv_request(struct gb_connection *connection, { struct gb_operation *operation; - operation = gb_operation_create(connection, type, size, 0); + operation = gb_operation_create_incoming(connection, type, size, 0); if (!operation) { gb_connection_err(connection, "can't create operation"); return; /* XXX Respond with pre-allocated ENOMEM */ -- cgit v0.10.2 From d30df426ffc055586ec63359aee27458af10214f Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 19 Nov 2014 17:55:03 -0600 Subject: greybus: send operation result in response message header Define a result byte in an operation response message header. All the protocols now define the mandatory status as the first byte in their response message. Assume that, for the moment, and save that value into the header result field (until we can get the simulator set up to handle the new protocol). Record the result from the response header as the result of the overall operation. Start enforcing the rule that we ignore all response payload (in fact, the entire message) if we see a non-zero result value. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 8214a37..3011020 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -34,14 +34,22 @@ static struct workqueue_struct *gb_operation_recv_workqueue; /* * All operation messages (both requests and responses) begin with - * a common header that encodes the size of the data (header - * included). This header also contains a unique identifier, which - * is used to keep track of in-flight operations. Finally, the - * header contains a operation type field, whose interpretation is - * dependent on what type of device lies on the other end of the - * connection. Response messages are distinguished from request - * messages by setting the high bit (0x80) in the operation type - * value. + * a header that encodes the size of the data (header included). + * This header also contains a unique identifier, which is used to + * keep track of in-flight operations. The header contains an + * operation type field, whose interpretation is dependent on what + * type of protocol is used over the connection. + * + * The high bit (0x80) of the operation type field is used to + * indicate whether the message is a request (clear) or a response + * (set). + * + * Response messages include an additional status byte, which + * communicates the result of the corresponding request. A zero + * status value means the operation completed successfully. Any + * other value indicates an error; in this case, the payload of the + * response message (if any) is ignored. The status byte must be + * zero in the header for a request message. * * The wire format for all numeric fields in the header is little * endian. Any operation-specific data begins immediately after the @@ -51,7 +59,8 @@ struct gb_operation_msg_hdr { __le16 size; /* Size in bytes of header + payload */ __le16 operation_id; /* Operation unique id */ __u8 type; /* E.g GB_I2C_TYPE_* or GB_GPIO_TYPE_* */ - /* 3 bytes pad, must be zero (ignore when read) */ + __u8 result; /* Result of request (in responses only) */ + /* 2 bytes pad, must be zero (ignore when read) */ } __aligned(sizeof(u64)); /* XXX Could be per-host device, per-module, or even per-connection */ @@ -469,6 +478,7 @@ static void gb_connection_recv_response(struct gb_connection *connection, { struct gb_operation *operation; struct gb_message *message; + struct gb_operation_msg_hdr *header; operation = gb_pending_operation_find(connection, operation_id); if (!operation) { @@ -485,9 +495,13 @@ static void gb_connection_recv_response(struct gb_connection *connection, gb_connection_err(connection, "recv buffer too small"); return; /* XXX Should still complete operation */ } - operation->result = GB_OP_SUCCESS; /* XXX Maybe not yet? */ - memcpy(message->buffer, data, size); + /* Hack the status from the buffer into the header */ + header = message->buffer; + header->result = *(char *)message->payload; /* Eeew. */ + operation->result = header->result; + if (operation->result == GB_OP_SUCCESS) + memcpy(message->buffer, data, size); /* The rest will be handled in work queue context */ queue_work(gb_operation_recv_workqueue, &operation->recv_work); -- cgit v0.10.2 From bc717fcbf673b0852a474b869efb9bfd0989b012 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 19 Nov 2014 17:55:04 -0600 Subject: greybus: define gb_operation_status_map() Define a common function that maps an operation status value to a Linux negative errno. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 3011020..cfc341e 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -288,6 +288,35 @@ static void gb_operation_message_exit(struct gb_message *message) } /* + * Map an enum gb_operation_status value (which is represted in a + * message as a single back a single byte) to an appropriate Linux + * negative errno. + */ +int gb_operation_status_map(u8 status) +{ + switch (status) { + case GB_OP_SUCCESS: + return 0; + case GB_OP_INVALID: + return -EINVAL; + case GB_OP_NO_MEMORY: + return -ENOMEM; + case GB_OP_INTERRUPTED: + return -EINTR; + case GB_OP_RETRY: + return -EAGAIN; + case GB_OP_PROTOCOL_BAD: + return -EPROTONOSUPPORT; + case GB_OP_OVERFLOW: + return -E2BIG; + case GB_OP_TIMEOUT: + return -ETIMEDOUT; + default: + return -EIO; + } +} + +/* * Create a Greybus operation to be sent over the given connection. * The request buffer will big enough for a payload of the given * size. Outgoing requests must specify the size of the response diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 80ee158..6547291 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -101,6 +101,8 @@ int gb_operation_response_send(struct gb_operation *operation); void gb_operation_cancel(struct gb_operation *operation); int gb_operation_wait(struct gb_operation *operation); +int gb_operation_status_map(u8 status); + int gb_operation_init(void); void gb_operation_exit(void); -- cgit v0.10.2 From 25d0f81a0ec9263618b6e7e75879e963d438bc11 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 19 Nov 2014 17:55:05 -0600 Subject: greybus: remove status from all responses This is a pervasive change, but not really a big one. However: ============== Pay attention to this ============== If you're doing any testing with "gbsim" you need to update that program in sync with this change, because it changes the protocol used between them. ============== Pay attention to this ============== The status of a request is now recorded in the header of a response message. The previous patch put that header status byte in place, and this one removes the status byte from all the response messages. And finally, since we're modifying all these files anyway... Use gb_operation_status_map() to come up with a return code to use, given an operation response. Right now most errors simply result in -EIO getting returned. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index 101c3de..1c85341 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -40,7 +40,6 @@ struct gb_battery { #define GB_BATTERY_TYPE_VOLTAGE 0x07 struct gb_battery_proto_version_response { - __u8 status; __u8 major; __u8 minor; }; @@ -55,7 +54,6 @@ struct gb_battery_proto_version_response { #define GB_BATTERY_TECH_LiMn 0x0006 struct gb_battery_technology_response { - __u8 status; __le32 technology; }; @@ -67,35 +65,25 @@ struct gb_battery_technology_response { #define GB_BATTERY_STATUS_FULL 0x0004 struct gb_battery_status_response { - __u8 status; __le16 battery_status; }; struct gb_battery_max_voltage_response { - __u8 status; __le32 max_voltage; }; struct gb_battery_capacity_response { - __u8 status; __le32 capacity; }; struct gb_battery_temperature_response { - __u8 status; __le32 temperature; }; struct gb_battery_voltage_response { - __u8 status; __le32 voltage; }; -/* Generia response structure--prefix for all other responses */ -struct gb_generic_battery_response { - __u8 status; -}; - /* * None of the battery operation requests have any payload. This * function implements all of the requests by allowing the caller to @@ -107,7 +95,6 @@ static int battery_operation(struct gb_battery *gb, int type, { struct gb_connection *connection = gb->connection; struct gb_operation *operation; - struct gb_generic_battery_response *fake_response; int ret; operation = gb_operation_create(connection, type, 0, response_size); @@ -126,14 +113,13 @@ static int battery_operation(struct gb_battery *gb, int type, * layout for where the status is, so cast this to a random request so * we can see the status easier. */ - fake_response = operation->response.payload; - if (fake_response->status) { - gb_connection_err(connection, "version response %hhu", - fake_response->status); - ret = -EIO; + if (operation->result) { + ret = gb_operation_status_map(operation->result); + gb_connection_err(connection, "operation result %hhu", + operation->result); } else { /* Good response, so copy to the caller's buffer */ - memcpy(response, fake_response, response_size); + memcpy(response, operation->response.payload, response_size); } out: gb_operation_destroy(operation); diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index 6f4609d..8ef00a7 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -55,14 +55,12 @@ struct gb_gpio_controller { /* version request has no payload */ struct gb_gpio_proto_version_response { - __u8 status; __u8 major; __u8 minor; }; /* line count request has no payload */ struct gb_gpio_line_count_response { - __u8 status; __u8 count; }; @@ -70,44 +68,35 @@ struct gb_gpio_activate_request { __u8 which; }; struct gb_gpio_activate_response { - __u8 status; }; struct gb_gpio_deactivate_request { __u8 which; }; -struct gb_gpio_deactivate_response { - __u8 status; -}; +/* deactivate response has no payload */ struct gb_gpio_get_direction_request { __u8 which; }; struct gb_gpio_get_direction_response { - __u8 status; __u8 direction; }; struct gb_gpio_direction_in_request { __u8 which; }; -struct gb_gpio_direction_in_response { - __u8 status; -}; +/* direction in response has no payload */ struct gb_gpio_direction_out_request { __u8 which; __u8 value; }; -struct gb_gpio_direction_out_response { - __u8 status; -}; +/* direction out response has no payload */ struct gb_gpio_get_value_request { __u8 which; }; struct gb_gpio_get_value_response { - __u8 status; __u8 value; }; @@ -115,17 +104,13 @@ struct gb_gpio_set_value_request { __u8 which; __u8 value; }; -struct gb_gpio_set_value_response { - __u8 status; -}; +/* set value response has no payload */ struct gb_gpio_set_debounce_request { __u8 which; __le16 usec; }; -struct gb_gpio_set_debounce_response { - __u8 status; -}; +/* debounce response has no payload */ /* @@ -153,12 +138,12 @@ static int gb_gpio_proto_version_operation(struct gb_gpio_controller *gb_gpio_co goto out; } - response = operation->response.payload; - if (response->status) { - gb_connection_err(connection, "version response %hhu", - response->status); - ret = -EIO; + if (operation->result) { + ret = gb_operation_status_map(operation->result); + gb_connection_err(connection, "version result %hhu", + operation->result); } else { + response = operation->response.payload; if (response->major > GB_GPIO_VERSION_MAJOR) { pr_err("unsupported major version (%hhu > %hhu)\n", response->major, GB_GPIO_VERSION_MAJOR); @@ -199,12 +184,12 @@ static int gb_gpio_line_count_operation(struct gb_gpio_controller *gb_gpio_contr goto out; } - response = operation->response.payload; - if (response->status) { - gb_connection_err(connection, "line count response %hhu", - response->status); - ret = -EIO; + if (operation->result) { + ret = gb_operation_status_map(operation->result); + gb_connection_err(connection, "line count result %hhu", + operation->result); } else { + response = operation->response.payload; gb_gpio_controller->line_max = response->count; pr_debug("%s: count = %u\n", __func__, @@ -222,7 +207,6 @@ static int gb_gpio_activate_operation(struct gb_gpio_controller *gb_gpio_control struct gb_connection *connection = gb_gpio_controller->connection; struct gb_operation *operation; struct gb_gpio_activate_request *request; - struct gb_gpio_activate_response *response; int ret; if (which > gb_gpio_controller->line_max) @@ -231,7 +215,7 @@ static int gb_gpio_activate_operation(struct gb_gpio_controller *gb_gpio_control /* activate response has no payload */ operation = gb_operation_create(connection, GB_GPIO_TYPE_ACTIVATE, - sizeof(*request), sizeof(*response)); + sizeof(*request), 0); if (!operation) return -ENOMEM; request = operation->request.payload; @@ -244,11 +228,10 @@ static int gb_gpio_activate_operation(struct gb_gpio_controller *gb_gpio_control goto out; } - response = operation->response.payload; - if (response->status) { - gb_connection_err(connection, "activate response %hhu", - response->status); - ret = -EIO; + if (operation->result) { + ret = gb_operation_status_map(operation->result); + gb_connection_err(connection, "activate result %hhu", + operation->result); } else { gb_gpio_controller->lines[which].active = true; @@ -266,7 +249,6 @@ static int gb_gpio_deactivate_operation(struct gb_gpio_controller *gb_gpio_contr struct gb_connection *connection = gb_gpio_controller->connection; struct gb_operation *operation; struct gb_gpio_deactivate_request *request; - struct gb_gpio_deactivate_response *response; int ret; if (which > gb_gpio_controller->line_max) @@ -275,7 +257,7 @@ static int gb_gpio_deactivate_operation(struct gb_gpio_controller *gb_gpio_contr /* deactivate response has no payload */ operation = gb_operation_create(connection, GB_GPIO_TYPE_DEACTIVATE, - sizeof(*request), sizeof(*response)); + sizeof(*request), 0); if (!operation) return -ENOMEM; request = operation->request.payload; @@ -288,11 +270,10 @@ static int gb_gpio_deactivate_operation(struct gb_gpio_controller *gb_gpio_contr goto out; } - response = operation->response.payload; - if (response->status) { - gb_connection_err(connection, "deactivate response %hhu", - response->status); - ret = -EIO; + if (operation->result) { + ret = gb_operation_status_map(operation->result); + gb_connection_err(connection, "deactivate result %hhu", + operation->result); } else { gb_gpio_controller->lines[which].active = false; pr_debug("%s: %u is now inactive\n", __func__, which); @@ -330,14 +311,15 @@ static int gb_gpio_get_direction_operation(struct gb_gpio_controller *gb_gpio_co goto out; } - response = operation->response.payload; - if (response->status) { - gb_connection_err(connection, "get direction response %hhu", - response->status); - ret = -EIO; + if (operation->result) { + ret = gb_operation_status_map(operation->result); + gb_connection_err(connection, "get direction result %hhu", + operation->result); } else { - u8 direction = response->direction; + u8 direction; + response = operation->response.payload; + direction = response->direction; if (direction && direction != 1) pr_warn("gpio %u direction was %u (should be 0 or 1)\n", which, direction); @@ -357,7 +339,6 @@ static int gb_gpio_direction_in_operation(struct gb_gpio_controller *gb_gpio_con struct gb_connection *connection = gb_gpio_controller->connection; struct gb_operation *operation; struct gb_gpio_direction_in_request *request; - struct gb_gpio_direction_in_response *response; int ret; if (which > gb_gpio_controller->line_max) @@ -366,7 +347,7 @@ static int gb_gpio_direction_in_operation(struct gb_gpio_controller *gb_gpio_con /* direction_in response has no payload */ operation = gb_operation_create(connection, GB_GPIO_TYPE_DIRECTION_IN, - sizeof(*request), sizeof(*response)); + sizeof(*request), 0); if (!operation) return -ENOMEM; request = operation->request.payload; @@ -379,11 +360,10 @@ static int gb_gpio_direction_in_operation(struct gb_gpio_controller *gb_gpio_con goto out; } - response = operation->response.payload; - if (response->status) { - gb_connection_err(connection, "direction in response %hhu", - response->status); - ret = -EIO; + if (operation->result) { + ret = gb_operation_status_map(operation->result); + gb_connection_err(connection, "direction in result %hhu", + operation->result); } else { gb_gpio_controller->lines[which].direction = 1; pr_debug("%s: direction of %u is now in\n", __func__, which); @@ -400,7 +380,6 @@ static int gb_gpio_direction_out_operation(struct gb_gpio_controller *gb_gpio_co struct gb_connection *connection = gb_gpio_controller->connection; struct gb_operation *operation; struct gb_gpio_direction_out_request *request; - struct gb_gpio_direction_out_response *response; int ret; if (which > gb_gpio_controller->line_max) @@ -409,7 +388,7 @@ static int gb_gpio_direction_out_operation(struct gb_gpio_controller *gb_gpio_co /* direction_out response has no payload */ operation = gb_operation_create(connection, GB_GPIO_TYPE_DIRECTION_OUT, - sizeof(*request), sizeof(*response)); + sizeof(*request), 0); if (!operation) return -ENOMEM; request = operation->request.payload; @@ -423,11 +402,10 @@ static int gb_gpio_direction_out_operation(struct gb_gpio_controller *gb_gpio_co goto out; } - response = operation->response.payload; - if (response->status) { - gb_connection_err(connection, "direction out response %hhu", - response->status); - ret = -EIO; + if (operation->result) { + ret = gb_operation_status_map(operation->result); + gb_connection_err(connection, "direction out result %hhu", + operation->result); } else { gb_gpio_controller->lines[which].direction = 0; pr_debug("%s: direction of %u is now out, value %s\n", __func__, @@ -466,14 +444,15 @@ static int gb_gpio_get_value_operation(struct gb_gpio_controller *gb_gpio_contro goto out; } - response = operation->response.payload; - if (response->status) { - gb_connection_err(connection, "get value response %hhu", - response->status); - ret = -EIO; + if (operation->result) { + ret = gb_operation_status_map(operation->result); + gb_connection_err(connection, "get value result %hhu", + operation->result); } else { - u8 value = response->value; + u8 value; + response = operation->response.payload; + value = response->value; if (value && value != 1) pr_warn("gpio %u value was %u (should be 0 or 1)\n", which, value); @@ -495,7 +474,6 @@ static int gb_gpio_set_value_operation(struct gb_gpio_controller *gb_gpio_contro struct gb_connection *connection = gb_gpio_controller->connection; struct gb_operation *operation; struct gb_gpio_set_value_request *request; - struct gb_gpio_set_value_response *response; int ret; if (which > gb_gpio_controller->line_max) @@ -504,7 +482,7 @@ static int gb_gpio_set_value_operation(struct gb_gpio_controller *gb_gpio_contro /* set_value response has no payload */ operation = gb_operation_create(connection, GB_GPIO_TYPE_SET_VALUE, - sizeof(*request), sizeof(*response)); + sizeof(*request), 0); if (!operation) return -ENOMEM; request = operation->request.payload; @@ -518,11 +496,10 @@ static int gb_gpio_set_value_operation(struct gb_gpio_controller *gb_gpio_contro goto out; } - response = operation->response.payload; - if (response->status) { - gb_connection_err(connection, "set value response %hhu", - response->status); - ret = -EIO; + if (operation->result) { + ret = gb_operation_status_map(operation->result); + gb_connection_err(connection, "set value result %hhu", + operation->result); } else { /* XXX should this set direction to out? */ gb_gpio_controller->lines[which].value = request->value; @@ -542,7 +519,6 @@ static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *gb_gpio_con struct gb_connection *connection = gb_gpio_controller->connection; struct gb_operation *operation; struct gb_gpio_set_debounce_request *request; - struct gb_gpio_set_debounce_response *response; int ret; if (which > gb_gpio_controller->line_max) @@ -551,7 +527,7 @@ static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *gb_gpio_con /* set_debounce response has no payload */ operation = gb_operation_create(connection, GB_GPIO_TYPE_SET_DEBOUNCE, - sizeof(*request), sizeof(*response)); + sizeof(*request), 0); if (!operation) return -ENOMEM; request = operation->request.payload; @@ -565,11 +541,10 @@ static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *gb_gpio_con goto out; } - response = operation->response.payload; - if (response->status) { - gb_connection_err(connection, "set debounce response %hhu", - response->status); - ret = -EIO; + if (operation->result) { + ret = gb_operation_status_map(operation->result); + gb_connection_err(connection, "set debounce result %hhu", + operation->result); } else { gb_gpio_controller->lines[which].debounce_usec = le16_to_cpu(request->usec); pr_debug("%s: debounce of %u is now %hu usec\n", __func__, which, diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index c810c42..9a090f4 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -43,30 +43,24 @@ struct gb_i2c_device { /* version request has no payload */ struct gb_i2c_proto_version_response { - __u8 status; __u8 major; __u8 minor; }; /* functionality request has no payload */ struct gb_i2c_functionality_response { - __u8 status; __le32 functionality; }; struct gb_i2c_timeout_request { __le16 msec; }; -struct gb_i2c_timeout_response { - __u8 status; -}; +/* timeout response has no payload */ struct gb_i2c_retries_request { __u8 retries; }; -struct gb_i2c_retries_response { - __u8 status; -}; +/* retries response has no payload */ /* * Outgoing data immediately follows the op count and ops array. @@ -89,7 +83,6 @@ struct gb_i2c_transfer_request { struct gb_i2c_transfer_op ops[0]; /* op_count of these */ }; struct gb_i2c_transfer_response { - __u8 status; __u8 data[0]; /* inbound data */ }; @@ -118,12 +111,12 @@ static int gb_i2c_proto_version_operation(struct gb_i2c_device *gb_i2c_dev) goto out; } - response = operation->response.payload; - if (response->status) { - gb_connection_err(connection, "version response %hhu", - response->status); - ret = -EIO; + if (operation->result) { + ret = gb_operation_status_map(operation->result); + gb_connection_err(connection, "version result %hhu", + operation->result); } else { + response = operation->response.payload; if (response->major > GB_I2C_VERSION_MAJOR) { pr_err("unsupported major version (%hhu > %hhu)\n", response->major, GB_I2C_VERSION_MAJOR); @@ -170,12 +163,12 @@ static int gb_i2c_functionality_operation(struct gb_i2c_device *gb_i2c_dev) goto out; } - response = operation->response.payload; - if (response->status) { - gb_connection_err(connection, "functionality response %hhu", - response->status); - ret = -EIO; + if (operation->result) { + ret = gb_operation_status_map(operation->result); + gb_connection_err(connection, "functionality result %hhu", + operation->result); } else { + response = operation->response.payload; functionality = le32_to_cpu(response->functionality); gb_i2c_dev->functionality = gb_i2c_functionality_map(functionality); @@ -191,11 +184,10 @@ static int gb_i2c_timeout_operation(struct gb_i2c_device *gb_i2c_dev, u16 msec) struct gb_connection *connection = gb_i2c_dev->connection; struct gb_operation *operation; struct gb_i2c_timeout_request *request; - struct gb_i2c_timeout_response *response; int ret; operation = gb_operation_create(connection, GB_I2C_TYPE_TIMEOUT, - sizeof(*request), sizeof(*response)); + sizeof(*request), 0); if (!operation) return -ENOMEM; request = operation->request.payload; @@ -208,11 +200,10 @@ static int gb_i2c_timeout_operation(struct gb_i2c_device *gb_i2c_dev, u16 msec) goto out; } - response = operation->response.payload; - if (response->status) { - gb_connection_err(connection, "timeout response %hhu", - response->status); - ret = -EIO; + if (operation->result) { + ret = gb_operation_status_map(operation->result); + gb_connection_err(connection, "timeout result %hhu", + operation->result); } else { gb_i2c_dev->timeout_msec = msec; } @@ -228,11 +219,10 @@ static int gb_i2c_retries_operation(struct gb_i2c_device *gb_i2c_dev, struct gb_connection *connection = gb_i2c_dev->connection; struct gb_operation *operation; struct gb_i2c_retries_request *request; - struct gb_i2c_retries_response *response; int ret; operation = gb_operation_create(connection, GB_I2C_TYPE_RETRIES, - sizeof(*request), sizeof(*response)); + sizeof(*request), 0); if (!operation) return -ENOMEM; request = operation->request.payload; @@ -245,11 +235,10 @@ static int gb_i2c_retries_operation(struct gb_i2c_device *gb_i2c_dev, goto out; } - response = operation->response.payload; - if (response->status) { - gb_connection_err(connection, "retries response %hhu", - response->status); - ret = -EIO; + if (operation->result) { + ret = gb_operation_status_map(operation->result); + gb_connection_err(connection, "retries result %hhu", + operation->result); } else { gb_i2c_dev->retries = retries; } @@ -380,16 +369,14 @@ static int gb_i2c_transfer_operation(struct gb_i2c_device *gb_i2c_dev, goto out; } - response = operation->response.payload; - if (response->status) { - if (response->status == GB_OP_RETRY) { - ret = -EAGAIN; - } else { - gb_connection_err(connection, "transfer response %hhu", - response->status); - ret = -EIO; + if (operation->result) { + ret = gb_operation_status_map(operation->result); + if (ret != -EAGAIN) { + gb_connection_err(connection, "transfer result %hhu", + operation->result); } } else { + response = operation->response.payload; gb_i2c_transfer_response(msgs, msg_count, response->data); ret = msg_count; } diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index cfc341e..e647425 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -525,10 +525,11 @@ static void gb_connection_recv_response(struct gb_connection *connection, return; /* XXX Should still complete operation */ } - /* Hack the status from the buffer into the header */ + /* The status in the response is the result of the operation */ header = message->buffer; - header->result = *(char *)message->payload; /* Eeew. */ operation->result = header->result; + + /* We must ignore the payload if a bad status is returned */ if (operation->result == GB_OP_SUCCESS) memcpy(message->buffer, data, size); diff --git a/drivers/staging/greybus/pwm-gb.c b/drivers/staging/greybus/pwm-gb.c index 0f46552..0b66f8c 100644 --- a/drivers/staging/greybus/pwm-gb.c +++ b/drivers/staging/greybus/pwm-gb.c @@ -41,20 +41,14 @@ struct gb_pwm_chip { #define GB_PWM_TYPE_DISABLE 0x08 #define GB_PWM_TYPE_RESPONSE 0x80 /* OR'd with rest */ -struct gb_pwm_simple_response { - __u8 status; -}; - /* version request has no payload */ struct gb_pwm_proto_version_response { - __u8 status; __u8 major; __u8 minor; }; /* pwm count request has no payload */ struct gb_pwm_count_response { - __u8 status; __u8 count; }; @@ -110,12 +104,12 @@ static int gb_pwm_proto_version_operation(struct gb_pwm_chip *pwmc) goto out; } - response = operation->response.payload; - if (response->status) { - gb_connection_err(connection, "version response %hhu", - response->status); - ret = -EIO; + if (operation->result) { + ret = gb_operation_status_map(operation->result); + gb_connection_err(connection, "version result %hhu", + operation->result); } else { + response = operation->response.payload; if (response->major > GB_PWM_VERSION_MAJOR) { pr_err("unsupported major version (%hhu > %hhu)\n", response->major, GB_PWM_VERSION_MAJOR); @@ -151,12 +145,12 @@ static int gb_pwm_count_operation(struct gb_pwm_chip *pwmc) goto out; } - response = operation->response.payload; - if (response->status) { - gb_connection_err(connection, "pwm count response %hhu", - response->status); - ret = -EIO; + if (operation->result) { + ret = gb_operation_status_map(operation->result); + gb_connection_err(connection, "pwm count result %hhu", + operation->result); } else + response = operation->response.payload; pwmc->pwm_max = response->count; out: gb_operation_destroy(operation); @@ -170,7 +164,6 @@ static int gb_pwm_activate_operation(struct gb_pwm_chip *pwmc, struct gb_connection *connection = pwmc->connection; struct gb_operation *operation; struct gb_pwm_activate_request *request; - struct gb_pwm_simple_response *response; int ret; if (which > pwmc->pwm_max) @@ -178,7 +171,7 @@ static int gb_pwm_activate_operation(struct gb_pwm_chip *pwmc, /* activate response has no payload */ operation = gb_operation_create(connection, GB_PWM_TYPE_ACTIVATE, - sizeof(*request), sizeof(*response)); + sizeof(*request), 0); if (!operation) return -ENOMEM; request = operation->request.payload; @@ -191,11 +184,10 @@ static int gb_pwm_activate_operation(struct gb_pwm_chip *pwmc, goto out; } - response = operation->response.payload; - if (response->status) { - gb_connection_err(connection, "activate response %hhu", - response->status); - ret = -EIO; + if (operation->result) { + ret = gb_operation_status_map(operation->result); + gb_connection_err(connection, "activate result %hhu", + operation->result); } out: gb_operation_destroy(operation); @@ -209,7 +201,6 @@ static int gb_pwm_deactivate_operation(struct gb_pwm_chip *pwmc, struct gb_connection *connection = pwmc->connection; struct gb_operation *operation; struct gb_pwm_deactivate_request *request; - struct gb_pwm_simple_response *response; int ret; if (which > pwmc->pwm_max) @@ -217,7 +208,7 @@ static int gb_pwm_deactivate_operation(struct gb_pwm_chip *pwmc, /* deactivate response has no payload */ operation = gb_operation_create(connection, GB_PWM_TYPE_DEACTIVATE, - sizeof(*request), sizeof(*response)); + sizeof(*request), 0); if (!operation) return -ENOMEM; request = operation->request.payload; @@ -230,11 +221,10 @@ static int gb_pwm_deactivate_operation(struct gb_pwm_chip *pwmc, goto out; } - response = operation->response.payload; - if (response->status) { - gb_connection_err(connection, "deactivate response %hhu", - response->status); - ret = -EIO; + if (operation->result) { + ret = gb_operation_status_map(operation->result); + gb_connection_err(connection, "deactivate result %hhu", + operation->result); } out: gb_operation_destroy(operation); @@ -248,14 +238,13 @@ static int gb_pwm_config_operation(struct gb_pwm_chip *pwmc, struct gb_connection *connection = pwmc->connection; struct gb_operation *operation; struct gb_pwm_config_request *request; - struct gb_pwm_simple_response *response; int ret; if (which > pwmc->pwm_max) return -EINVAL; operation = gb_operation_create(connection, GB_PWM_TYPE_CONFIG, - sizeof(*request), sizeof(*response)); + sizeof(*request), 0); if (!operation) return -ENOMEM; request = operation->request.payload; @@ -270,11 +259,10 @@ static int gb_pwm_config_operation(struct gb_pwm_chip *pwmc, goto out; } - response = operation->response.payload; - if (response->status) { - gb_connection_err(connection, "config response %hhu", - response->status); - ret = -EIO; + if (operation->result) { + ret = gb_operation_status_map(operation->result); + gb_connection_err(connection, "config result %hhu", + operation->result); } out: gb_operation_destroy(operation); @@ -289,14 +277,13 @@ static int gb_pwm_set_polarity_operation(struct gb_pwm_chip *pwmc, struct gb_connection *connection = pwmc->connection; struct gb_operation *operation; struct gb_pwm_polarity_request *request; - struct gb_pwm_simple_response *response; int ret; if (which > pwmc->pwm_max) return -EINVAL; operation = gb_operation_create(connection, GB_PWM_TYPE_POLARITY, - sizeof(*request), sizeof(*response)); + sizeof(*request), 0); if (!operation) return -ENOMEM; request = operation->request.payload; @@ -310,11 +297,10 @@ static int gb_pwm_set_polarity_operation(struct gb_pwm_chip *pwmc, goto out; } - response = operation->response.payload; - if (response->status) { - gb_connection_err(connection, "set polarity response %hhu", - response->status); - ret = -EIO; + if (operation->result) { + ret = gb_operation_status_map(operation->result); + gb_connection_err(connection, "set polarity result %hhu", + operation->result); } out: gb_operation_destroy(operation); @@ -328,7 +314,6 @@ static int gb_pwm_enable_operation(struct gb_pwm_chip *pwmc, struct gb_connection *connection = pwmc->connection; struct gb_operation *operation; struct gb_pwm_enable_request *request; - struct gb_pwm_simple_response *response; int ret; if (which > pwmc->pwm_max) @@ -336,7 +321,7 @@ static int gb_pwm_enable_operation(struct gb_pwm_chip *pwmc, /* enable response has no payload */ operation = gb_operation_create(connection, GB_PWM_TYPE_ENABLE, - sizeof(*request), sizeof(*response)); + sizeof(*request), 0); if (!operation) return -ENOMEM; request = operation->request.payload; @@ -349,11 +334,10 @@ static int gb_pwm_enable_operation(struct gb_pwm_chip *pwmc, goto out; } - response = operation->response.payload; - if (response->status) { - gb_connection_err(connection, "enable response %hhu", - response->status); - ret = -EIO; + if (operation->result) { + ret = gb_operation_status_map(operation->result); + gb_connection_err(connection, "enable result %hhu", + operation->result); } out: gb_operation_destroy(operation); @@ -367,7 +351,6 @@ static int gb_pwm_disable_operation(struct gb_pwm_chip *pwmc, struct gb_connection *connection = pwmc->connection; struct gb_operation *operation; struct gb_pwm_disable_request *request; - struct gb_pwm_simple_response *response; int ret; if (which > pwmc->pwm_max) @@ -375,7 +358,7 @@ static int gb_pwm_disable_operation(struct gb_pwm_chip *pwmc, /* disable response has no payload */ operation = gb_operation_create(connection, GB_PWM_TYPE_DISABLE, - sizeof(*request), sizeof(*response)); + sizeof(*request), 0); if (!operation) return -ENOMEM; request = operation->request.payload; @@ -388,11 +371,10 @@ static int gb_pwm_disable_operation(struct gb_pwm_chip *pwmc, goto out; } - response = operation->response.payload; - if (response->status) { - gb_connection_err(connection, "disable response %hhu", - response->status); - ret = -EIO; + if (operation->result) { + ret = gb_operation_status_map(operation->result); + gb_connection_err(connection, "disable result %hhu", + operation->result); } out: gb_operation_destroy(operation); diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index e68f4a2..1be00d6 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -49,7 +49,6 @@ #define GB_UART_TYPE_RESPONSE 0x80 /* OR'd with rest */ struct gb_uart_proto_version_response { - __u8 status; __u8 major; __u8 minor; }; @@ -106,10 +105,6 @@ struct gb_uart_serial_state_request { __u16 control; }; -struct gb_uart_simple_response { - __u8 status; -}; - struct gb_tty { struct tty_port port; struct gb_connection *connection; @@ -159,11 +154,10 @@ static int get_version(struct gb_tty *tty) goto out; } - response = operation->response.payload; - if (response->status) { - gb_connection_err(tty->connection, "response %hhu", - response->status); - ret = -EIO; + if (operation->result) { + ret = gb_operation_status_map(operation->result); + gb_connection_err(tty->connection, "result %hhu", + operation->result); } else { if (response->major > GB_UART_VERSION_MAJOR) { pr_err("unsupported major version (%hhu > %hhu)\n", @@ -188,15 +182,13 @@ static int send_data(struct gb_tty *tty, u16 size, const u8 *data) struct gb_connection *connection = tty->connection; struct gb_operation *operation; struct gb_uart_send_data_request *request; - struct gb_uart_simple_response *response; int retval; if (!data || !size) return 0; operation = gb_operation_create(connection, GB_UART_REQ_SEND_DATA, - sizeof(*request) + size, - sizeof(*response)); + sizeof(*request) + size, 0); if (!operation) return -ENOMEM; request = operation->request.payload; @@ -211,11 +203,10 @@ static int send_data(struct gb_tty *tty, u16 size, const u8 *data) goto out; } - response = operation->response.payload; - if (response->status) { - gb_connection_err(connection, "send data response %hhu", - response->status); - retval = -EIO; + if (operation->result) { + retval = gb_operation_status_map(operation->result); + gb_connection_err(connection, "send data result %hhu", + operation->result); } out: gb_operation_destroy(operation); @@ -229,12 +220,10 @@ static int send_line_coding(struct gb_tty *tty, struct gb_connection *connection = tty->connection; struct gb_operation *operation; struct gb_uart_set_line_coding_request *request; - struct gb_uart_simple_response *response; int retval; operation = gb_operation_create(connection, GB_UART_REQ_SET_LINE_CODING, - sizeof(*request), - sizeof(*response)); + sizeof(*request), 0); if (!operation) return -ENOMEM; request = operation->request.payload; @@ -248,11 +237,10 @@ static int send_line_coding(struct gb_tty *tty, goto out; } - response = operation->response.payload; - if (response->status) { - gb_connection_err(connection, "send line coding response %hhu", - response->status); - retval = -EIO; + if (operation->result) { + retval = gb_operation_status_map(operation->result); + gb_connection_err(connection, "send line coding result %hhu", + operation->result); } out: gb_operation_destroy(operation); @@ -265,13 +253,11 @@ static int send_control(struct gb_tty *tty, u16 control) struct gb_connection *connection = tty->connection; struct gb_operation *operation; struct gb_uart_set_control_line_state_request *request; - struct gb_uart_simple_response *response; int retval; operation = gb_operation_create(connection, GB_UART_REQ_SET_CONTROL_LINE_STATE, - sizeof(*request), - sizeof(*response)); + sizeof(*request), 0); if (!operation) return -ENOMEM; request = operation->request.payload; @@ -285,11 +271,10 @@ static int send_control(struct gb_tty *tty, u16 control) goto out; } - response = operation->response.payload; - if (response->status) { - gb_connection_err(connection, "send control response %hhu", - response->status); - retval = -EIO; + if (operation->result) { + retval = gb_operation_status_map(operation->result); + gb_connection_err(connection, "send control result %hhu", + operation->result); } out: gb_operation_destroy(operation); @@ -302,7 +287,6 @@ static int send_break(struct gb_tty *tty, u8 state) struct gb_connection *connection = tty->connection; struct gb_operation *operation; struct gb_uart_set_break_request *request; - struct gb_uart_simple_response *response; int retval; if ((state != 0) && (state != 1)) { @@ -311,8 +295,7 @@ static int send_break(struct gb_tty *tty, u8 state) } operation = gb_operation_create(connection, GB_UART_REQ_SET_BREAK, - sizeof(*request), - sizeof(*response)); + sizeof(*request), 0); if (!operation) return -ENOMEM; request = operation->request.payload; @@ -326,11 +309,10 @@ static int send_break(struct gb_tty *tty, u8 state) goto out; } - response = operation->response.payload; - if (response->status) { - gb_connection_err(connection, "send break response %hhu", - response->status); - retval = -EIO; + if (operation->result) { + retval = gb_operation_status_map(operation->result); + gb_connection_err(connection, "send break result %hhu", + operation->result); } out: gb_operation_destroy(operation); diff --git a/drivers/staging/greybus/vibrator-gb.c b/drivers/staging/greybus/vibrator-gb.c index 3e46fa6..9ad3cb0 100644 --- a/drivers/staging/greybus/vibrator-gb.c +++ b/drivers/staging/greybus/vibrator-gb.c @@ -34,7 +34,6 @@ struct gb_vibrator_device { #define GB_VIBRATOR_TYPE_RESPONSE 0x80 /* OR'd with rest */ struct gb_vibrator_proto_version_response { - __u8 status; __u8 major; __u8 minor; }; @@ -43,15 +42,10 @@ struct gb_vibrator_on_request { __le16 timeout_ms; }; -struct gb_vibrator_simple_response { - __u8 status; -}; - static int request_operation(struct gb_connection *connection, int type, void *response, int response_size) { struct gb_operation *operation; - struct gb_vibrator_simple_response *fake_response; int ret; operation = gb_operation_create(connection, type, 0, response_size); @@ -70,15 +64,15 @@ static int request_operation(struct gb_connection *connection, int type, * layout for where the status is, so cast this to a random request so * we can see the status easier. */ - fake_response = operation->response.payload; - if (fake_response->status) { - gb_connection_err(connection, "response %hhu", - fake_response->status); - ret = -EIO; + if (operation->result) { + ret = gb_operation_status_map(operation->result); + gb_connection_err(connection, "operation result %hhu", + operation->result); } else { /* Good request, so copy to the caller's buffer */ if (response_size && response) - memcpy(response, fake_response, response_size); + memcpy(response, operation->response.payload, + response_size); } out: gb_operation_destroy(operation); @@ -119,11 +113,10 @@ static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms) struct gb_connection *connection = vib->connection; struct gb_operation *operation; struct gb_vibrator_on_request *request; - struct gb_vibrator_simple_response *response; int retval; operation = gb_operation_create(connection, GB_VIBRATOR_TYPE_ON, - sizeof(*request), sizeof(*response)); + sizeof(*request), 0); if (!operation) return -ENOMEM; request = operation->request.payload; @@ -137,11 +130,10 @@ static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms) goto out; } - response = operation->response.payload; - if (response->status) { - gb_connection_err(connection, "send data response %hhu", - response->status); - retval = -EIO; + if (operation->result) { + retval = gb_operation_status_map(operation->result); + gb_connection_err(connection, "send data result %hhu", + operation->result); } out: gb_operation_destroy(operation); -- cgit v0.10.2 From 9ffb4b8b398a7c420a94372abcde05a41ac23ccb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 19 Nov 2014 16:56:13 -0800 Subject: greybus: uart-gb: fix up typo from previous patch moving the status variable around. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 1be00d6..8df3bfb 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -159,6 +159,7 @@ static int get_version(struct gb_tty *tty) gb_connection_err(tty->connection, "result %hhu", operation->result); } else { + response = operation->response.payload; if (response->major > GB_UART_VERSION_MAJOR) { pr_err("unsupported major version (%hhu > %hhu)\n", response->major, GB_UART_VERSION_MAJOR); -- cgit v0.10.2 From 4589f0666334edf220402cc4d791657e3565f9f7 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 19 Nov 2014 17:02:21 -0800 Subject: greybus: pwm-gb.c: fix up missing { } for else This was a compiler warning, which looked correct, but was trying to tell us something else... Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/pwm-gb.c b/drivers/staging/greybus/pwm-gb.c index 0b66f8c..c92d8e2 100644 --- a/drivers/staging/greybus/pwm-gb.c +++ b/drivers/staging/greybus/pwm-gb.c @@ -149,9 +149,10 @@ static int gb_pwm_count_operation(struct gb_pwm_chip *pwmc) ret = gb_operation_status_map(operation->result); gb_connection_err(connection, "pwm count result %hhu", operation->result); - } else + } else { response = operation->response.payload; pwmc->pwm_max = response->count; + } out: gb_operation_destroy(operation); -- cgit v0.10.2 From 7486dfd161e4474b20e9acf5ca4c8c439cd0def6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 19 Nov 2014 19:09:53 -0800 Subject: greybus: add -Wall to the build flags In an attempt to turn on as many options as we can to catch warnings early, let's enable -Wall. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index b254516..81174b9 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -23,6 +23,9 @@ KERNELVER ?= $(shell uname -r) KERNELDIR ?= /lib/modules/$(KERNELVER)/build PWD := $(shell pwd) +# add -Wall to try to catch everything we can. +ccFlags-y := -Wall + all: module module: -- cgit v0.10.2 From 5e68995784ad7ef8410661f3970bebf272fd322f Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 20 Nov 2014 15:37:05 -0600 Subject: greybus: drop a now-empty structure One structure, gb_gpio_activate_response, was not deleted even though it now has no contents. Delete it. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index 8ef00a7..f2e2eef 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -67,8 +67,7 @@ struct gb_gpio_line_count_response { struct gb_gpio_activate_request { __u8 which; }; -struct gb_gpio_activate_response { -}; +/* activate response has no payload */ struct gb_gpio_deactivate_request { __u8 which; -- cgit v0.10.2 From e8b48d1586abd62dd1749520dccd4bac784ce680 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 20 Nov 2014 15:37:06 -0600 Subject: greybus: fix a timeout race Whenever we send a request message we start a timer to ensure the we don't wait too long for the matching response to arrive. Currently we set up the timeout *after* sending the message, but that is subject to a race--the response could arrive (and the timeout prematurely disabled) before the timeout is even set up. Set up the timeout before sending the message. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index e647425..3e3fc73 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -447,13 +447,20 @@ int gb_operation_request_send(struct gb_operation *operation, */ operation->callback = callback; gb_pending_operation_insert(operation); + + /* + * We impose a time limit for requests to complete. We need + * to set the timer before we send the request though, so we + * don't lose a race with the receipt of the resposne. + */ + timeout = msecs_to_jiffies(OPERATION_TIMEOUT_DEFAULT); + schedule_delayed_work(&operation->timeout_work, timeout); + + /* All set, send the request */ ret = gb_message_send(&operation->request, GFP_KERNEL); if (ret) return ret; - /* We impose a time limit for requests to complete. */ - timeout = msecs_to_jiffies(OPERATION_TIMEOUT_DEFAULT); - schedule_delayed_work(&operation->timeout_work, timeout); if (!callback) ret = gb_operation_wait(operation); -- cgit v0.10.2 From 8d55f4c6d9a29f4b3483231f6d88458333ee36ed Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 20 Nov 2014 15:37:07 -0600 Subject: greybus: complete overflow responses If a response arrives for an operation request and the allotted buffer isn't big enough we report the error, but we don't finish processing the response. Instead, set the operation result, but then finish processing the response (no different from any other operation error). This will allow the normal completion handling to occur for this error case. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 3e3fc73..d91cd5b 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -526,16 +526,15 @@ static void gb_connection_recv_response(struct gb_connection *connection, gb_pending_operation_remove(operation); message = &operation->response; - if (size > message->buffer_size) { - operation->result = GB_OP_OVERFLOW; + if (size <= message->buffer_size) { + /* Transfer the operation result from the response header */ + header = message->buffer; + operation->result = header->result; + } else { gb_connection_err(connection, "recv buffer too small"); - return; /* XXX Should still complete operation */ + operation->result = GB_OP_OVERFLOW; } - /* The status in the response is the result of the operation */ - header = message->buffer; - operation->result = header->result; - /* We must ignore the payload if a bad status is returned */ if (operation->result == GB_OP_SUCCESS) memcpy(message->buffer, data, size); -- cgit v0.10.2 From 8b337308e7ff71cd6ae6d9c04260f8ada6e98c9e Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 20 Nov 2014 16:09:13 -0600 Subject: greybus: have greybus allocate its own buffers Rather than having the host driver allocate the buffers that the Greybus core uses to hold its data for sending or receiving, have the host driver define what it requires those buffers to look like. Two constraints define what the host driver requires: the maximum number of bytes that the host device can send in a single request; and a statement of the "headroom" that needs to be present for use by the host device. The direct description of the headroom is that it's the extra byte the host device needs at the beginning of the "data" portion of the buffer so the ES1 driver can insert the destination CPort id. But more generally, the host driver could put other data in there as well. By stating these two parameters, Greybus can allocate the buffers it uses by itself. The host driver still allocates the buffers it uses for receiving data--the content of those are copied as needed into Greybus buffers when data arrives. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 04fc541..2c50dd3 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -169,8 +169,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver * Validate that the driver implements all of the callbacks * so that we don't have to every time we make them. */ - if ((!driver->buffer_alloc) || (!driver->buffer_free) || - (!driver->buffer_send) || (!driver->buffer_cancel) || + if ((!driver->buffer_send) || (!driver->buffer_cancel) || (!driver->submit_svc)) { pr_err("Must implement all greybus_host_driver callbacks!\n"); return NULL; diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 7745b81..8843643 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -25,7 +25,7 @@ /* Memory sizes for the buffers sent to/from the ES1 controller */ #define ES1_SVC_MSG_SIZE (sizeof(struct svc_msg) + SZ_64K) -#define ES1_GBUF_MSG_SIZE PAGE_SIZE +#define ES1_GBUF_MSG_SIZE_MAX PAGE_SIZE static const struct usb_device_id id_table[] = { /* Made up numbers for the SVC USB Bridge in ES1 */ @@ -92,47 +92,41 @@ static inline struct es1_ap_dev *hd_to_es1(struct greybus_host_device *hd) static void cport_out_callback(struct urb *urb); /* - * Allocate a buffer to be sent via UniPro. + * Buffer constraints for the host driver. + * + * A "buffer" is used to hold data to be transferred for Greybus by + * the host driver. A buffer is represented by a "buffer pointer", + * which defines a region of memory used by the host driver for + * transferring the data. When Greybus allocates a buffer, it must + * do so subject to the constraints associated with the host driver. + * These constraints are specified by two parameters: the + * headroom; and the maximum buffer size. + * + * +------------------+ + * | Host driver | \ + * | reserved area | }- headroom + * | . . . | / + * buffer pointer ---> +------------------+ + * | Buffer space for | \ + * | transferred data | }- buffer size + * | . . . | / (limited to size_max) + * +------------------+ + * + * headroom: Every buffer must have at least this much space + * *before* the buffer pointer, reserved for use by the + * host driver. I.e., ((char *)buffer - headroom) must + * point to valid memory, usable only by the host driver. + * size_max: The maximum size of a buffer (not including the + * headroom) must not exceed this. */ -static void *buffer_alloc(unsigned int size, gfp_t gfp_mask) +static void hd_buffer_constraints(struct greybus_host_device *hd) { - u8 *buffer; - - if (size > ES1_GBUF_MSG_SIZE) { - pr_err("guf was asked to be bigger than %ld!\n", - ES1_GBUF_MSG_SIZE); - } - /* - * For ES1 we need to insert a byte at the front of the data - * to indicate the destination CPort id. We only need one - * extra byte, but we allocate four extra bytes to allow the - * buffer returned to be aligned on a four-byte boundary. - * - * This is only needed for outbound data, but we handle - * buffers for inbound data the same way for consistency. - * - * XXX Do we need to indicate the destination device id too? + * Only one byte is required, but this produces a result + * that's better aligned for the user. */ - buffer = kzalloc(GB_BUFFER_ALIGN + size, gfp_mask); - if (buffer) - buffer += GB_BUFFER_ALIGN; - - return buffer; -} - -/* Free a previously-allocated buffer */ -static void buffer_free(void *buffer) -{ - u8 *allocated = buffer; - - /* Can be called with a NULL buffer on some error paths */ - if (!allocated) - return; - - /* Account for the space set aside for the prepended cport id */ - allocated -= GB_BUFFER_ALIGN; - kfree(allocated); + hd->buffer_headroom = sizeof(u32); /* For cport id */ + hd->buffer_size_max = ES1_GBUF_MSG_SIZE_MAX; } #define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ @@ -265,8 +259,6 @@ static void buffer_cancel(void *cookie) static struct greybus_host_driver es1_driver = { .hd_priv_size = sizeof(struct es1_ap_dev), - .buffer_alloc = buffer_alloc, - .buffer_free = buffer_free, .buffer_send = buffer_send, .buffer_cancel = buffer_cancel, .submit_svc = submit_svc, @@ -493,6 +485,9 @@ static int ap_probe(struct usb_interface *interface, return -ENOMEM; } + /* Fill in the buffer allocation constraints */ + hd_buffer_constraints(hd); + es1 = hd_to_es1(hd); es1->hd = hd; es1->usb_intf = interface; @@ -557,14 +552,14 @@ static int ap_probe(struct usb_interface *interface, urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) goto error; - buffer = kmalloc(ES1_GBUF_MSG_SIZE, GFP_KERNEL); + buffer = kmalloc(ES1_GBUF_MSG_SIZE_MAX, GFP_KERNEL); if (!buffer) goto error; usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, es1->cport_in_endpoint), - buffer, ES1_GBUF_MSG_SIZE, cport_in_callback, - hd); + buffer, ES1_GBUF_MSG_SIZE_MAX, + cport_in_callback, hd); es1->cport_in_urb[i] = urb; es1->cport_in_buffer[i] = buffer; retval = usb_submit_urb(urb, GFP_KERNEL); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 3df2b5a..8fda37c 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -78,8 +78,6 @@ struct svc_msg; struct greybus_host_driver { size_t hd_priv_size; - void *(*buffer_alloc)(unsigned int size, gfp_t gfp_mask); - void (*buffer_free)(void *buffer); void *(*buffer_send)(struct greybus_host_device *hd, u16 dest_cport_id, void *buffer, size_t buffer_size, gfp_t gfp_mask); void (*buffer_cancel)(void *cookie); @@ -97,6 +95,10 @@ struct greybus_host_device { struct ida cport_id_map; u8 device_id; + /* Host device buffer constraints */ + size_t buffer_headroom; + size_t buffer_size_max; + /* Private data for the host driver */ unsigned long hd_priv[0] __aligned(sizeof(s64)); }; diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index d91cd5b..6c66c26 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -229,6 +229,27 @@ static void operation_timeout(struct work_struct *work) gb_operation_complete(operation); } +static void * +gb_buffer_alloc(struct greybus_host_device *hd, size_t size, gfp_t gfp_flags) +{ + u8 *buffer; + + buffer = kzalloc(hd->buffer_headroom + size, gfp_flags); + if (buffer) + buffer += hd->buffer_headroom; + + return buffer; +} + +static void +gb_buffer_free(struct greybus_host_device *hd, void *buffer) +{ + u8 *allocated = buffer; + + if (allocated) + kfree(allocated - hd->buffer_headroom); +} + /* * Allocate a buffer to be used for an operation request or response * message. For outgoing messages, both types of message contain a @@ -246,9 +267,9 @@ static int gb_operation_message_init(struct gb_operation *operation, struct gb_message *message; struct gb_operation_msg_hdr *header; - if (size > GB_OPERATION_MESSAGE_SIZE_MAX) - return -E2BIG; size += sizeof(*header); + if (size > hd->buffer_size_max) + return -E2BIG; if (request) { message = &operation->request; @@ -257,7 +278,7 @@ static int gb_operation_message_init(struct gb_operation *operation, type |= GB_OPERATION_TYPE_RESPONSE; } - message->buffer = hd->driver->buffer_alloc(size, gfp_flags); + message->buffer = gb_buffer_alloc(hd, size, gfp_flags); if (!message->buffer) return -ENOMEM; message->buffer_size = size; @@ -279,7 +300,7 @@ static void gb_operation_message_exit(struct gb_message *message) struct greybus_host_device *hd; hd = message->operation->connection->hd; - hd->driver->buffer_free(message->buffer); + gb_buffer_free(hd, message->buffer); message->operation = NULL; message->payload = NULL; -- cgit v0.10.2 From 0a4e14a882aeefc7cb1bebff240b4d1c770065a4 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 20 Nov 2014 16:09:14 -0600 Subject: greybus: rename message buffer fields The beginning of an operation message always contains the message header. Rename the "buffer" field in an operation message to be "header" to reflect this. Change its type as well. The size of a message is the combined size of its header and its payload. Rename the "buffer_size" field in a message header to be simply "size", so message->size describes exactly that. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 6c66c26..f6940a3 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -81,7 +81,7 @@ static void gb_pending_operation_insert(struct gb_operation *operation) spin_unlock_irq(&gb_operations_lock); /* Store the operation id in the request header */ - header = operation->request.buffer; + header = operation->request.header; header->operation_id = cpu_to_le16(operation->id); } @@ -120,8 +120,8 @@ static int gb_message_send(struct gb_message *message, gfp_t gfp_mask) message->cookie = connection->hd->driver->buffer_send(connection->hd, dest_cport_id, - message->buffer, - message->buffer_size, + message->header, + message->size, gfp_mask); if (IS_ERR(message->cookie)) { ret = PTR_ERR(message->cookie); @@ -177,7 +177,7 @@ static void gb_operation_request_handle(struct gb_operation *operation) struct gb_protocol *protocol = operation->connection->protocol; struct gb_operation_msg_hdr *header; - header = operation->request.buffer; + header = operation->request.header; /* * If the protocol has no incoming request handler, report @@ -205,7 +205,7 @@ static void gb_operation_recv_work(struct work_struct *recv_work) bool incoming_request; operation = container_of(recv_work, struct gb_operation, recv_work); - incoming_request = operation->response.buffer == NULL; + incoming_request = operation->response.header == NULL; if (incoming_request) gb_operation_request_handle(operation); gb_operation_complete(operation); @@ -278,13 +278,13 @@ static int gb_operation_message_init(struct gb_operation *operation, type |= GB_OPERATION_TYPE_RESPONSE; } - message->buffer = gb_buffer_alloc(hd, size, gfp_flags); - if (!message->buffer) + message->header = gb_buffer_alloc(hd, size, gfp_flags); + if (!message->header) return -ENOMEM; - message->buffer_size = size; + message->size = size; /* Fill in the header structure */ - header = message->buffer; + header = message->header; header->size = cpu_to_le16(size); header->operation_id = 0; /* Filled in when submitted */ header->type = type; @@ -300,12 +300,12 @@ static void gb_operation_message_exit(struct gb_message *message) struct greybus_host_device *hd; hd = message->operation->connection->hd; - gb_buffer_free(hd, message->buffer); + gb_buffer_free(hd, message->header); message->operation = NULL; message->payload = NULL; - message->buffer = NULL; - message->buffer_size = 0; + message->header = NULL; + message->size = 0; } /* @@ -516,7 +516,7 @@ void gb_connection_recv_request(struct gb_connection *connection, return; /* XXX Respond with pre-allocated ENOMEM */ } operation->id = operation_id; - memcpy(operation->request.buffer, data, size); + memcpy(operation->request.header, data, size); /* The rest will be handled in work queue context */ queue_work(gb_operation_recv_workqueue, &operation->recv_work); @@ -547,9 +547,9 @@ static void gb_connection_recv_response(struct gb_connection *connection, gb_pending_operation_remove(operation); message = &operation->response; - if (size <= message->buffer_size) { + if (size <= message->size) { /* Transfer the operation result from the response header */ - header = message->buffer; + header = message->header; operation->result = header->result; } else { gb_connection_err(connection, "recv buffer too small"); @@ -558,7 +558,7 @@ static void gb_connection_recv_response(struct gb_connection *connection, /* We must ignore the payload if a bad status is returned */ if (operation->result == GB_OP_SUCCESS) - memcpy(message->buffer, data, size); + memcpy(message->header, data, size); /* The rest will be handled in work queue context */ queue_work(gb_operation_recv_workqueue, &operation->recv_work); @@ -610,7 +610,7 @@ void gb_operation_cancel(struct gb_operation *operation) { operation->canceled = true; gb_message_cancel(&operation->request); - if (operation->response.buffer) + if (operation->response.header) gb_message_cancel(&operation->response); } diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 6547291..38b2833 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -25,14 +25,12 @@ enum gb_operation_status { }; struct gb_message { - void *payload; + struct gb_operation_msg_hdr *header; + void *payload; + size_t size; /* header + payload */ + struct gb_operation *operation; - struct gb_operation *operation; - - void *buffer; - size_t buffer_size; - - void *cookie; + void *cookie; }; /* -- cgit v0.10.2 From c08b1ddaeb6e8f3c22b15f80e7475c809490a716 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 20 Nov 2014 16:09:15 -0600 Subject: greybus: dynamically allocate requests and responses Have an operation's request and response messages be dynamically allocated rather than embedded in an operation. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index 1c85341..02178f5 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -119,7 +119,7 @@ static int battery_operation(struct gb_battery *gb, int type, operation->result); } else { /* Good response, so copy to the caller's buffer */ - memcpy(response, operation->response.payload, response_size); + memcpy(response, operation->response->payload, response_size); } out: gb_operation_destroy(operation); diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index f2e2eef..170f8aa 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -142,7 +142,7 @@ static int gb_gpio_proto_version_operation(struct gb_gpio_controller *gb_gpio_co gb_connection_err(connection, "version result %hhu", operation->result); } else { - response = operation->response.payload; + response = operation->response->payload; if (response->major > GB_GPIO_VERSION_MAJOR) { pr_err("unsupported major version (%hhu > %hhu)\n", response->major, GB_GPIO_VERSION_MAJOR); @@ -188,7 +188,7 @@ static int gb_gpio_line_count_operation(struct gb_gpio_controller *gb_gpio_contr gb_connection_err(connection, "line count result %hhu", operation->result); } else { - response = operation->response.payload; + response = operation->response->payload; gb_gpio_controller->line_max = response->count; pr_debug("%s: count = %u\n", __func__, @@ -217,7 +217,7 @@ static int gb_gpio_activate_operation(struct gb_gpio_controller *gb_gpio_control sizeof(*request), 0); if (!operation) return -ENOMEM; - request = operation->request.payload; + request = operation->request->payload; request->which = which; /* Synchronous operation--no callback */ @@ -259,7 +259,7 @@ static int gb_gpio_deactivate_operation(struct gb_gpio_controller *gb_gpio_contr sizeof(*request), 0); if (!operation) return -ENOMEM; - request = operation->request.payload; + request = operation->request->payload; request->which = which; /* Synchronous operation--no callback */ @@ -300,7 +300,7 @@ static int gb_gpio_get_direction_operation(struct gb_gpio_controller *gb_gpio_co sizeof(*request), sizeof(*response)); if (!operation) return -ENOMEM; - request = operation->request.payload; + request = operation->request->payload; request->which = which; /* Synchronous operation--no callback */ @@ -317,7 +317,7 @@ static int gb_gpio_get_direction_operation(struct gb_gpio_controller *gb_gpio_co } else { u8 direction; - response = operation->response.payload; + response = operation->response->payload; direction = response->direction; if (direction && direction != 1) pr_warn("gpio %u direction was %u (should be 0 or 1)\n", @@ -349,7 +349,7 @@ static int gb_gpio_direction_in_operation(struct gb_gpio_controller *gb_gpio_con sizeof(*request), 0); if (!operation) return -ENOMEM; - request = operation->request.payload; + request = operation->request->payload; request->which = which; /* Synchronous operation--no callback */ @@ -390,7 +390,7 @@ static int gb_gpio_direction_out_operation(struct gb_gpio_controller *gb_gpio_co sizeof(*request), 0); if (!operation) return -ENOMEM; - request = operation->request.payload; + request = operation->request->payload; request->which = which; request->value = value_high ? 1 : 0; @@ -433,7 +433,7 @@ static int gb_gpio_get_value_operation(struct gb_gpio_controller *gb_gpio_contro sizeof(*request), sizeof(*response)); if (!operation) return -ENOMEM; - request = operation->request.payload; + request = operation->request->payload; request->which = which; /* Synchronous operation--no callback */ @@ -450,7 +450,7 @@ static int gb_gpio_get_value_operation(struct gb_gpio_controller *gb_gpio_contro } else { u8 value; - response = operation->response.payload; + response = operation->response->payload; value = response->value; if (value && value != 1) pr_warn("gpio %u value was %u (should be 0 or 1)\n", @@ -484,7 +484,7 @@ static int gb_gpio_set_value_operation(struct gb_gpio_controller *gb_gpio_contro sizeof(*request), 0); if (!operation) return -ENOMEM; - request = operation->request.payload; + request = operation->request->payload; request->which = which; request->value = value_high ? 1 : 0; @@ -529,7 +529,7 @@ static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *gb_gpio_con sizeof(*request), 0); if (!operation) return -ENOMEM; - request = operation->request.payload; + request = operation->request->payload; request->which = which; request->usec = cpu_to_le16(debounce_usec); diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index 9a090f4..2a5fb82 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -116,7 +116,7 @@ static int gb_i2c_proto_version_operation(struct gb_i2c_device *gb_i2c_dev) gb_connection_err(connection, "version result %hhu", operation->result); } else { - response = operation->response.payload; + response = operation->response->payload; if (response->major > GB_I2C_VERSION_MAJOR) { pr_err("unsupported major version (%hhu > %hhu)\n", response->major, GB_I2C_VERSION_MAJOR); @@ -168,7 +168,7 @@ static int gb_i2c_functionality_operation(struct gb_i2c_device *gb_i2c_dev) gb_connection_err(connection, "functionality result %hhu", operation->result); } else { - response = operation->response.payload; + response = operation->response->payload; functionality = le32_to_cpu(response->functionality); gb_i2c_dev->functionality = gb_i2c_functionality_map(functionality); @@ -190,7 +190,7 @@ static int gb_i2c_timeout_operation(struct gb_i2c_device *gb_i2c_dev, u16 msec) sizeof(*request), 0); if (!operation) return -ENOMEM; - request = operation->request.payload; + request = operation->request->payload; request->msec = cpu_to_le16(msec); /* Synchronous operation--no callback */ @@ -225,7 +225,7 @@ static int gb_i2c_retries_operation(struct gb_i2c_device *gb_i2c_dev, sizeof(*request), 0); if (!operation) return -ENOMEM; - request = operation->request.payload; + request = operation->request->payload; request->retries = retries; /* Synchronous operation--no callback */ @@ -310,7 +310,7 @@ gb_i2c_transfer_request(struct gb_connection *connection, if (!operation) return NULL; - request = operation->request.payload; + request = operation->request->payload; request->op_count = cpu_to_le16(op_count); /* Fill in the ops array */ op = &request->ops[0]; @@ -376,7 +376,7 @@ static int gb_i2c_transfer_operation(struct gb_i2c_device *gb_i2c_dev, operation->result); } } else { - response = operation->response.payload; + response = operation->response->payload; gb_i2c_transfer_response(msgs, msg_count, response->data); ret = msg_count; } diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index f6940a3..b02c531 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -81,7 +81,7 @@ static void gb_pending_operation_insert(struct gb_operation *operation) spin_unlock_irq(&gb_operations_lock); /* Store the operation id in the request header */ - header = operation->request.header; + header = operation->request->header; header->operation_id = cpu_to_le16(operation->id); } @@ -167,7 +167,7 @@ int gb_operation_wait(struct gb_operation *operation) ret = wait_for_completion_interruptible(&operation->completion); /* If interrupted, cancel the in-flight buffer */ if (ret < 0) - gb_message_cancel(&operation->request); + gb_message_cancel(operation->request); return ret; } @@ -177,7 +177,7 @@ static void gb_operation_request_handle(struct gb_operation *operation) struct gb_protocol *protocol = operation->connection->protocol; struct gb_operation_msg_hdr *header; - header = operation->request.header; + header = operation->request->header; /* * If the protocol has no incoming request handler, report @@ -205,7 +205,7 @@ static void gb_operation_recv_work(struct work_struct *recv_work) bool incoming_request; operation = container_of(recv_work, struct gb_operation, recv_work); - incoming_request = operation->response.header == NULL; + incoming_request = operation->response->header == NULL; if (incoming_request) gb_operation_request_handle(operation); gb_operation_complete(operation); @@ -251,61 +251,53 @@ gb_buffer_free(struct greybus_host_device *hd, void *buffer) } /* - * Allocate a buffer to be used for an operation request or response - * message. For outgoing messages, both types of message contain a + * Allocate a message to be used for an operation request or + * response. For outgoing messages, both types of message contain a * common header, which is filled in here. Incoming requests or * responses also contain the same header, but there's no need to * initialize it here (it'll be overwritten by the incoming * message). */ -static int gb_operation_message_init(struct gb_operation *operation, - u8 type, size_t size, - bool request, gfp_t gfp_flags) +static struct gb_message * +gb_operation_message_alloc(struct greybus_host_device *hd, u8 type, + size_t size, gfp_t gfp_flags) { - struct gb_connection *connection = operation->connection; - struct greybus_host_device *hd = connection->hd; struct gb_message *message; struct gb_operation_msg_hdr *header; size += sizeof(*header); if (size > hd->buffer_size_max) - return -E2BIG; + return NULL; - if (request) { - message = &operation->request; - } else { - message = &operation->response; - type |= GB_OPERATION_TYPE_RESPONSE; - } + message = kzalloc(sizeof(*message), gfp_flags); + if (!message) + return NULL; - message->header = gb_buffer_alloc(hd, size, gfp_flags); - if (!message->header) - return -ENOMEM; - message->size = size; + header = gb_buffer_alloc(hd, size, gfp_flags); + if (!header) { + kfree(message); + return NULL; + } /* Fill in the header structure */ - header = message->header; header->size = cpu_to_le16(size); header->operation_id = 0; /* Filled in when submitted */ header->type = type; + message->header = header; message->payload = header + 1; - message->operation = operation; + message->size = size; - return 0; + return message; } -static void gb_operation_message_exit(struct gb_message *message) +static void gb_operation_message_free(struct gb_message *message) { struct greybus_host_device *hd; hd = message->operation->connection->hd; gb_buffer_free(hd, message->header); - - message->operation = NULL; - message->payload = NULL; - message->header = NULL; - message->size = 0; + kfree(message); } /* @@ -358,25 +350,28 @@ gb_operation_create_common(struct gb_connection *connection, bool outgoing, u8 type, size_t request_size, size_t response_size) { + struct greybus_host_device *hd = connection->hd; struct gb_operation *operation; gfp_t gfp_flags = response_size ? GFP_KERNEL : GFP_ATOMIC; - int ret; operation = kmem_cache_zalloc(gb_operation_cache, gfp_flags); if (!operation) return NULL; operation->connection = connection; - ret = gb_operation_message_init(operation, type, request_size, - true, gfp_flags); - if (ret) + operation->request = gb_operation_message_alloc(hd, type, request_size, + gfp_flags); + if (!operation->request) goto err_cache; + operation->request->operation = operation; if (outgoing) { - ret = gb_operation_message_init(operation, type, response_size, - false, GFP_KERNEL); - if (ret) + type |= GB_OPERATION_TYPE_RESPONSE; + operation->response = gb_operation_message_alloc(hd, type, + response_size, GFP_KERNEL); + if (!operation->response) goto err_request; + operation->response->operation = operation; } INIT_WORK(&operation->recv_work, gb_operation_recv_work); @@ -392,7 +387,7 @@ gb_operation_create_common(struct gb_connection *connection, bool outgoing, return operation; err_request: - gb_operation_message_exit(&operation->request); + gb_operation_message_free(operation->request); err_cache: kmem_cache_free(gb_operation_cache, operation); @@ -430,8 +425,8 @@ static void _gb_operation_destroy(struct kref *kref) list_del(&operation->links); spin_unlock_irq(&gb_operations_lock); - gb_operation_message_exit(&operation->response); - gb_operation_message_exit(&operation->request); + gb_operation_message_free(operation->response); + gb_operation_message_free(operation->request); kmem_cache_free(gb_operation_cache, operation); } @@ -478,7 +473,7 @@ int gb_operation_request_send(struct gb_operation *operation, schedule_delayed_work(&operation->timeout_work, timeout); /* All set, send the request */ - ret = gb_message_send(&operation->request, GFP_KERNEL); + ret = gb_message_send(operation->request, GFP_KERNEL); if (ret) return ret; @@ -516,7 +511,7 @@ void gb_connection_recv_request(struct gb_connection *connection, return; /* XXX Respond with pre-allocated ENOMEM */ } operation->id = operation_id; - memcpy(operation->request.header, data, size); + memcpy(operation->request->header, data, size); /* The rest will be handled in work queue context */ queue_work(gb_operation_recv_workqueue, &operation->recv_work); @@ -546,7 +541,7 @@ static void gb_connection_recv_response(struct gb_connection *connection, cancel_delayed_work(&operation->timeout_work); gb_pending_operation_remove(operation); - message = &operation->response; + message = operation->response; if (size <= message->size) { /* Transfer the operation result from the response header */ header = message->header; @@ -609,9 +604,9 @@ void gb_connection_recv(struct gb_connection *connection, void gb_operation_cancel(struct gb_operation *operation) { operation->canceled = true; - gb_message_cancel(&operation->request); - if (operation->response.header) - gb_message_cancel(&operation->response); + gb_message_cancel(operation->request); + if (operation->response->header) + gb_message_cancel(operation->response); } int gb_operation_init(void) diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 38b2833..567bb70 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -64,8 +64,8 @@ struct gb_message { typedef void (*gb_operation_callback)(struct gb_operation *); struct gb_operation { struct gb_connection *connection; - struct gb_message request; - struct gb_message response; + struct gb_message *request; + struct gb_message *response; u16 id; bool canceled; diff --git a/drivers/staging/greybus/pwm-gb.c b/drivers/staging/greybus/pwm-gb.c index c92d8e2..d3d39be 100644 --- a/drivers/staging/greybus/pwm-gb.c +++ b/drivers/staging/greybus/pwm-gb.c @@ -109,7 +109,7 @@ static int gb_pwm_proto_version_operation(struct gb_pwm_chip *pwmc) gb_connection_err(connection, "version result %hhu", operation->result); } else { - response = operation->response.payload; + response = operation->response->payload; if (response->major > GB_PWM_VERSION_MAJOR) { pr_err("unsupported major version (%hhu > %hhu)\n", response->major, GB_PWM_VERSION_MAJOR); @@ -150,7 +150,7 @@ static int gb_pwm_count_operation(struct gb_pwm_chip *pwmc) gb_connection_err(connection, "pwm count result %hhu", operation->result); } else { - response = operation->response.payload; + response = operation->response->payload; pwmc->pwm_max = response->count; } out: @@ -175,7 +175,7 @@ static int gb_pwm_activate_operation(struct gb_pwm_chip *pwmc, sizeof(*request), 0); if (!operation) return -ENOMEM; - request = operation->request.payload; + request = operation->request->payload; request->which = which; /* Synchronous operation--no callback */ @@ -212,7 +212,7 @@ static int gb_pwm_deactivate_operation(struct gb_pwm_chip *pwmc, sizeof(*request), 0); if (!operation) return -ENOMEM; - request = operation->request.payload; + request = operation->request->payload; request->which = which; /* Synchronous operation--no callback */ @@ -248,7 +248,7 @@ static int gb_pwm_config_operation(struct gb_pwm_chip *pwmc, sizeof(*request), 0); if (!operation) return -ENOMEM; - request = operation->request.payload; + request = operation->request->payload; request->which = which; request->duty = duty; request->period = period; @@ -287,7 +287,7 @@ static int gb_pwm_set_polarity_operation(struct gb_pwm_chip *pwmc, sizeof(*request), 0); if (!operation) return -ENOMEM; - request = operation->request.payload; + request = operation->request->payload; request->which = which; request->polarity = polarity; @@ -325,7 +325,7 @@ static int gb_pwm_enable_operation(struct gb_pwm_chip *pwmc, sizeof(*request), 0); if (!operation) return -ENOMEM; - request = operation->request.payload; + request = operation->request->payload; request->which = which; /* Synchronous operation--no callback */ @@ -362,7 +362,7 @@ static int gb_pwm_disable_operation(struct gb_pwm_chip *pwmc, sizeof(*request), 0); if (!operation) return -ENOMEM; - request = operation->request.payload; + request = operation->request->payload; request->which = which; /* Synchronous operation--no callback */ diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 8df3bfb..7d7e223 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -159,7 +159,7 @@ static int get_version(struct gb_tty *tty) gb_connection_err(tty->connection, "result %hhu", operation->result); } else { - response = operation->response.payload; + response = operation->response->payload; if (response->major > GB_UART_VERSION_MAJOR) { pr_err("unsupported major version (%hhu > %hhu)\n", response->major, GB_UART_VERSION_MAJOR); @@ -192,7 +192,7 @@ static int send_data(struct gb_tty *tty, u16 size, const u8 *data) sizeof(*request) + size, 0); if (!operation) return -ENOMEM; - request = operation->request.payload; + request = operation->request->payload; request->size = cpu_to_le16(size); memcpy(&request->data[0], data, size); @@ -227,7 +227,7 @@ static int send_line_coding(struct gb_tty *tty, sizeof(*request), 0); if (!operation) return -ENOMEM; - request = operation->request.payload; + request = operation->request->payload; memcpy(&request->line_coding, line_coding, sizeof(*line_coding)); /* Synchronous operation--no callback */ @@ -261,7 +261,7 @@ static int send_control(struct gb_tty *tty, u16 control) sizeof(*request), 0); if (!operation) return -ENOMEM; - request = operation->request.payload; + request = operation->request->payload; request->control = cpu_to_le16(control); /* Synchronous operation--no callback */ @@ -299,7 +299,7 @@ static int send_break(struct gb_tty *tty, u8 state) sizeof(*request), 0); if (!operation) return -ENOMEM; - request = operation->request.payload; + request = operation->request->payload; request->state = state; /* Synchronous operation--no callback */ diff --git a/drivers/staging/greybus/vibrator-gb.c b/drivers/staging/greybus/vibrator-gb.c index 9ad3cb0..b974973 100644 --- a/drivers/staging/greybus/vibrator-gb.c +++ b/drivers/staging/greybus/vibrator-gb.c @@ -71,7 +71,7 @@ static int request_operation(struct gb_connection *connection, int type, } else { /* Good request, so copy to the caller's buffer */ if (response_size && response) - memcpy(response, operation->response.payload, + memcpy(response, operation->response->payload, response_size); } out: @@ -119,7 +119,7 @@ static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms) sizeof(*request), 0); if (!operation) return -ENOMEM; - request = operation->request.payload; + request = operation->request->payload; request->timeout_ms = cpu_to_le16(timeout_ms); /* Synchronous operation--no callback */ -- cgit v0.10.2 From 87d208feb74f4297ac2677215252bf7da65e0650 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 20 Nov 2014 16:09:16 -0600 Subject: greybus: embed message buffer into message structure Embed the buffer for message data into the message structure itself. This allows us to use a single allocation for each message, and more importantly will allow us to derive the message structure describing a message from the buffer itself. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index b02c531..c9988fd 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -229,27 +229,6 @@ static void operation_timeout(struct work_struct *work) gb_operation_complete(operation); } -static void * -gb_buffer_alloc(struct greybus_host_device *hd, size_t size, gfp_t gfp_flags) -{ - u8 *buffer; - - buffer = kzalloc(hd->buffer_headroom + size, gfp_flags); - if (buffer) - buffer += hd->buffer_headroom; - - return buffer; -} - -static void -gb_buffer_free(struct greybus_host_device *hd, void *buffer) -{ - u8 *allocated = buffer; - - if (allocated) - kfree(allocated - hd->buffer_headroom); -} - /* * Allocate a message to be used for an operation request or * response. For outgoing messages, both types of message contain a @@ -257,46 +236,47 @@ gb_buffer_free(struct greybus_host_device *hd, void *buffer) * responses also contain the same header, but there's no need to * initialize it here (it'll be overwritten by the incoming * message). + * + * Our message structure consists of: + * message structure + * headroom + * message header \_ these combined are + * message payload / the message size */ static struct gb_message * gb_operation_message_alloc(struct greybus_host_device *hd, u8 type, - size_t size, gfp_t gfp_flags) + size_t payload_size, gfp_t gfp_flags) { struct gb_message *message; struct gb_operation_msg_hdr *header; + size_t message_size = payload_size + sizeof(*header); + size_t size; + u8 *buffer; - size += sizeof(*header); - if (size > hd->buffer_size_max) + if (message_size > hd->buffer_size_max) return NULL; - message = kzalloc(sizeof(*message), gfp_flags); + size = sizeof(*message) + hd->buffer_headroom + message_size; + message = kzalloc(size, gfp_flags); if (!message) return NULL; - - header = gb_buffer_alloc(hd, size, gfp_flags); - if (!header) { - kfree(message); - return NULL; - } + buffer = &message->buffer[0]; + header = (struct gb_operation_msg_hdr *)(buffer + hd->buffer_headroom); /* Fill in the header structure */ - header->size = cpu_to_le16(size); + header->size = cpu_to_le16(message_size); header->operation_id = 0; /* Filled in when submitted */ header->type = type; message->header = header; message->payload = header + 1; - message->size = size; + message->size = message_size; return message; } static void gb_operation_message_free(struct gb_message *message) { - struct greybus_host_device *hd; - - hd = message->operation->connection->hd; - gb_buffer_free(hd, message->header); kfree(message); } diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 567bb70..2fdb41c 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -31,6 +31,8 @@ struct gb_message { struct gb_operation *operation; void *cookie; + + u8 buffer[]; }; /* -- cgit v0.10.2 From d98b52b04e5bd3d8c47ca9a9bffcf08a43c944c3 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 20 Nov 2014 16:09:17 -0600 Subject: greybus: define greybus_data_sent() Define greybus_data_sent(), which is a callback the host driver makes when a buffer send request has completed. The main use for this is to actively detect errors that can occur while sending. (Something like this existed at one time and was removed.) This also defines gb_hd_message_find(), which looks up a message pointer associated with a buffer sent over a given host device. This is now a pretty trival mapping. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 8843643..f32c981 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -407,10 +407,19 @@ static void cport_out_callback(struct urb *urb) struct greybus_host_device *hd = urb->context; struct es1_ap_dev *es1 = hd_to_es1(hd); unsigned long flags; - /* int status = check_urb_status(urb); */ + int status = check_urb_status(urb); + u8 *data = urb->transfer_buffer + 1; int i; /* + * Tell the submitter that the buffer send (attempt) is + * complete, and report the status. The submitter's buffer + * starts after the one-byte CPort id we inserted. + */ + data = urb->transfer_buffer + 1; + greybus_data_sent(hd, data, status); + + /* * See if this was an urb in our pool, if so mark it "free", otherwise * we need to free it ourselves. */ diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index c9988fd..74dd48a 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -230,6 +230,24 @@ static void operation_timeout(struct work_struct *work) } /* + * Given a pointer to the header in a message sent on a given host + * device, return the associated message structure. (This "header" + * is just the buffer pointer we supply to the host device for + * sending.) + */ +static struct gb_message * +gb_hd_message_find(struct greybus_host_device *hd, void *header) +{ + struct gb_message *message; + u8 *result; + + result = (u8 *)header - hd->buffer_headroom - sizeof(*message); + message = (struct gb_message *)result; + + return message; +} + +/* * Allocate a message to be used for an operation request or * response. For outgoing messages, both types of message contain a * common header, which is filled in here. Incoming requests or @@ -474,6 +492,32 @@ int gb_operation_response_send(struct gb_operation *operation) } /* + * This function is called when a buffer send request has completed. + * The "header" is the message header--the beginning of what we + * asked to have sent. + * + * XXX Mismatch between errno here and operation result code + */ +void +greybus_data_sent(struct greybus_host_device *hd, void *header, int status) +{ + struct gb_message *message; + struct gb_operation *operation; + + /* If there's no error, there's really nothing to do */ + if (!status) + return; /* Mark it complete? */ + + /* XXX Right now we assume we're an outgoing request */ + message = gb_hd_message_find(hd, header); + operation = message->operation; + gb_connection_err(operation->connection, "send error %d\n", status); + operation->result = status; /* XXX */ + gb_operation_complete(operation); +} +EXPORT_SYMBOL_GPL(greybus_data_sent); + +/* * We've received data on a connection, and it doesn't look like a * response, so we assume it's a request. * diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 2fdb41c..3e5e1f5 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -103,6 +103,9 @@ int gb_operation_wait(struct gb_operation *operation); int gb_operation_status_map(u8 status); +void greybus_data_sent(struct greybus_host_device *hd, + void *header, int status); + int gb_operation_init(void); void gb_operation_exit(void); -- cgit v0.10.2 From de3557d927735d14a16e44475c078d6ff3060d10 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 20 Nov 2014 16:09:18 -0600 Subject: greybus: rename greybus_cport_in() This function is associated with a host device (interface), not a CPort. Change its name to reflect that, and to match its "sent" callback counterpart. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 584f491..8cb2af3 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -29,7 +29,11 @@ struct gb_connection *gb_hd_connection_find(struct greybus_host_device *hd, return connection; } -void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, +/* + * Callback from the host driver to let us know that data has been + * received on the interface. + */ +void greybus_data_rcvd(struct greybus_host_device *hd, u16 cport_id, u8 *data, size_t length) { struct gb_connection *connection; @@ -42,7 +46,7 @@ void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, } gb_connection_recv(connection, data, length); } -EXPORT_SYMBOL_GPL(greybus_cport_in); +EXPORT_SYMBOL_GPL(greybus_data_rcvd); /* * Allocate an available CPort Id for use for the host side of the diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index bcaad47..e190944 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -53,7 +53,7 @@ void gb_connection_exit(struct gb_connection *connection); struct gb_connection *gb_hd_connection_find(struct greybus_host_device *hd, u16 cport_id); -void greybus_cport_in(struct greybus_host_device *hd, u16 cport_id, +void greybus_data_rcvd(struct greybus_host_device *hd, u16 cport_id, u8 *data, size_t length); __printf(2, 3) void gb_connection_err(struct gb_connection *connection, const char *fmt, ...); diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index f32c981..3daa6eb 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -392,7 +392,7 @@ static void cport_in_callback(struct urb *urb) data = &data[1]; /* Pass this data to the greybus core */ - greybus_cport_in(hd, cport_id, data, urb->actual_length - 1); + greybus_data_rcvd(hd, cport_id, data, urb->actual_length - 1); exit: /* put our urb back in the request pool */ -- cgit v0.10.2 From 696e0ccabd45d4aabf22d2b4a035c3b144a1607c Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 21 Nov 2014 11:26:30 +0530 Subject: greybus: Random spell fixes Reviewed-by: Alex Elder Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index 02178f5..13ade43 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -165,7 +165,7 @@ static int get_tech(struct gb_battery *gb) /* * Map greybus values to power_supply values. Hopefully these are - * "identical" which should allow gcc to optomize the code away to + * "identical" which should allow gcc to optimize the code away to * nothing. */ technology = le32_to_cpu(tech_response.technology); @@ -209,7 +209,7 @@ static int get_status(struct gb_battery *gb) /* * Map greybus values to power_supply values. Hopefully these are - * "identical" which should allow gcc to optomize the code away to + * "identical" which should allow gcc to optimize the code away to * nothing. */ battery_status = le16_to_cpu(status_response.battery_status); diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index e190944..8cde114 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -37,7 +37,7 @@ struct gb_connection { u16 op_cycle; struct list_head operations; - struct list_head pending; /* awaiting reponse */ + struct list_head pending; /* awaiting response */ void *private; }; diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 2c50dd3..9203ebd 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -39,7 +39,7 @@ static int greybus_module_match(struct device *dev, struct device_driver *drv) id = gb_module_match_id(gmod, driver->id_table); if (id) return 1; - /* FIXME - Dyanmic ids? */ + /* FIXME - Dynamic ids? */ return 0; } diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 3daa6eb..bab6f25 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -450,7 +450,7 @@ static void cport_out_callback(struct urb *urb) * * This protocol is "needed" due to some hardware restrictions on the * current generation of Unipro controllers. Think about it for a - * minute, this is a USB driver, talking to a Unipro bridge, impediance + * minute, this is a USB driver, talking to a Unipro bridge, impedance * mismatch is huge, yet the Unipro controller are even more * underpowered than this little USB controller. We rely on the round * trip to keep stalls in the Unipro controllers from happening so that diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 3754035..28abd2a 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -46,7 +46,7 @@ static void release_manifest_descriptors(void) /* * Validate the given descriptor. Its reported size must fit within - * the number of bytes reamining, and it must have a recognized + * the number of bytes remaining, and it must have a recognized * type. Check that the reported size is at least as big as what * we expect to see. (It could be bigger, perhaps for a new version * of the format.) diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index f432bea..f72e6ae 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -68,7 +68,7 @@ struct device_type greybus_module_type = { }; /* - * A Greybus module represents a user-replacable component on an Ara + * A Greybus module represents a user-replicable component on an Ara * phone. * * Create a gb_module structure to represent a discovered module. diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 74dd48a..4420465 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -146,7 +146,7 @@ static void gb_message_cancel(struct gb_message *message) } /* - * An operations's response message has arrived. If no callback was + * An operation's response message has arrived. If no callback was * supplied it was submitted for asynchronous completion, so we notify * any waiters. Otherwise we assume calling the completion is enough * and nobody else will be waiting. @@ -169,7 +169,6 @@ int gb_operation_wait(struct gb_operation *operation) if (ret < 0) gb_message_cancel(operation->request); return ret; - } static void gb_operation_request_handle(struct gb_operation *operation) @@ -299,9 +298,8 @@ static void gb_operation_message_free(struct gb_message *message) } /* - * Map an enum gb_operation_status value (which is represted in a - * message as a single back a single byte) to an appropriate Linux - * negative errno. + * Map an enum gb_operation_status value (which is represented in a + * message as a single byte) to an appropriate Linux negative errno. */ int gb_operation_status_map(u8 status) { @@ -329,7 +327,7 @@ int gb_operation_status_map(u8 status) /* * Create a Greybus operation to be sent over the given connection. - * The request buffer will big enough for a payload of the given + * The request buffer will be big enough for a payload of the given * size. Outgoing requests must specify the size of the response * buffer size, which must be sufficient to hold all expected * response data. @@ -544,7 +542,7 @@ void gb_connection_recv_request(struct gb_connection *connection, /* * We've received data that appears to be an operation response * message. Look up the operation, and record that we've received - * its repsonse. + * its response. * * This is called in interrupt context, so just copy the incoming * data into the response buffer and handle the rest via workqueue. diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index 346120f..55ef387 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -38,7 +38,7 @@ static struct gb_protocol *_gb_protocol_find(u8 id, u8 major, u8 minor) return NULL; } -/* Returns true if protocol was succesfully registered, false otherwise */ +/* Returns true if protocol was successfully registered, false otherwise */ bool gb_protocol_register(struct gb_protocol *protocol) { struct gb_protocol *existing; @@ -93,7 +93,7 @@ bool gb_protocol_register(struct gb_protocol *protocol) * XXX Currently this fails (and reports an error to the caller) if * XXX the protocol is currently in use. We may want to forcefully * XXX kill off a protocol and all its active users at some point. - * XXX But I think that's better handled by quescing modules that + * XXX But I think that's better handled by quiescing modules that * XXX have users and having those users drop their reference. * * Returns true if successful, false otherwise. diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 7d7e223..48fad7b 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -816,7 +816,7 @@ static void gb_uart_connection_exit(struct gb_connection *connection) tty_unregister_device(gb_tty_driver, gb_tty->minor); - /* FIXME - free transmit / recieve buffers */ + /* FIXME - free transmit / receive buffers */ tty_port_put(&gb_tty->port); -- cgit v0.10.2 From 23383defa8395eb34d02dd4d4fc1d95e95c5603d Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 21 Nov 2014 19:29:12 -0600 Subject: greybus: use errno for operation result An in-core operation structure tracks the progress of an operation. Currently it holds a result field that was intended to take the status value that arrives in an operation response message header. But operations can fail for reasons other than that, and it's inconvenient to try to represent those using the operation status codes. So change the operation->result field to be an int, and switch to storing negative errno values in it. Rename it "errno" to make it obvious how to interpret the value. This patch makes another change, which simplifies the protocol drivers a lot. It's being done as part of this patch because it affects all the same code as the above change does. If desired I can split this into two separate patches. If a caller makes a synchronous gb_operation_request_send() request (i.e., no callback function is supplied), and the operation request and response messages were transferred successfully, have gb_operation_request_send() return the result of the request (i.e., operation->errno). This allows the caller (or more generally, any caller of gb_request_wait() to avoid having to look at this field for every successful send. Any caller that does an asynchronous request will of course need to look at request->errno in the callback function to see the result of the operation. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index 13ade43..ae03869 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -88,7 +88,7 @@ struct gb_battery_voltage_response { * None of the battery operation requests have any payload. This * function implements all of the requests by allowing the caller to * supply a buffer into which the operation response should be - * copied. + * copied. If there is an error, the response buffer is left alone. */ static int battery_operation(struct gb_battery *gb, int type, void *response, int response_size) @@ -103,25 +103,10 @@ static int battery_operation(struct gb_battery *gb, int type, /* Synchronous operation--no callback */ ret = gb_operation_request_send(operation, NULL); - if (ret) { + if (ret) pr_err("version operation failed (%d)\n", ret); - goto out; - } - - /* - * We only want to look at the status, and all requests have the same - * layout for where the status is, so cast this to a random request so - * we can see the status easier. - */ - if (operation->result) { - ret = gb_operation_status_map(operation->result); - gb_connection_err(connection, "operation result %hhu", - operation->result); - } else { - /* Good response, so copy to the caller's buffer */ + else /* Good response, so copy to the caller's buffer */ memcpy(response, operation->response->payload, response_size); - } -out: gb_operation_destroy(operation); return ret; diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index 170f8aa..c6c85d8 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -116,7 +116,8 @@ struct gb_gpio_set_debounce_request { * This request only uses the connection field, and if successful, * fills in the major and minor protocol version of the target. */ -static int gb_gpio_proto_version_operation(struct gb_gpio_controller *gb_gpio_controller) +static int +gb_gpio_proto_version_operation(struct gb_gpio_controller *gb_gpio_controller) { struct gb_connection *connection = gb_gpio_controller->connection; struct gb_operation *operation; @@ -137,24 +138,14 @@ static int gb_gpio_proto_version_operation(struct gb_gpio_controller *gb_gpio_co goto out; } - if (operation->result) { - ret = gb_operation_status_map(operation->result); - gb_connection_err(connection, "version result %hhu", - operation->result); + response = operation->response->payload; + if (response->major > GB_GPIO_VERSION_MAJOR) { + pr_err("unsupported major version (%hhu > %hhu)\n", + response->major, GB_GPIO_VERSION_MAJOR); + ret = -ENOTSUPP; } else { - response = operation->response->payload; - if (response->major > GB_GPIO_VERSION_MAJOR) { - pr_err("unsupported major version (%hhu > %hhu)\n", - response->major, GB_GPIO_VERSION_MAJOR); - ret = -ENOTSUPP; - goto out; - } gb_gpio_controller->version_major = response->major; gb_gpio_controller->version_minor = response->minor; - - pr_debug("%s: version_major = %u version_minor = %u\n", __func__, - gb_gpio_controller->version_major, - gb_gpio_controller->version_minor); } out: gb_operation_destroy(operation); @@ -180,21 +171,10 @@ static int gb_gpio_line_count_operation(struct gb_gpio_controller *gb_gpio_contr ret = gb_operation_request_send(operation, NULL); if (ret) { pr_err("line count operation failed (%d)\n", ret); - goto out; - } - - if (operation->result) { - ret = gb_operation_status_map(operation->result); - gb_connection_err(connection, "line count result %hhu", - operation->result); } else { response = operation->response->payload; gb_gpio_controller->line_max = response->count; - - pr_debug("%s: count = %u\n", __func__, - gb_gpio_controller->line_max + 1); } -out: gb_operation_destroy(operation); return ret; @@ -222,21 +202,10 @@ static int gb_gpio_activate_operation(struct gb_gpio_controller *gb_gpio_control /* Synchronous operation--no callback */ ret = gb_operation_request_send(operation, NULL); - if (ret) { + if (ret) pr_err("activate operation failed (%d)\n", ret); - goto out; - } - - if (operation->result) { - ret = gb_operation_status_map(operation->result); - gb_connection_err(connection, "activate result %hhu", - operation->result); - } else { + else gb_gpio_controller->lines[which].active = true; - - pr_debug("%s: %u is now active\n", __func__, which); - } -out: gb_operation_destroy(operation); return ret; @@ -264,20 +233,10 @@ static int gb_gpio_deactivate_operation(struct gb_gpio_controller *gb_gpio_contr /* Synchronous operation--no callback */ ret = gb_operation_request_send(operation, NULL); - if (ret) { + if (ret) pr_err("deactivate operation failed (%d)\n", ret); - goto out; - } - - if (operation->result) { - ret = gb_operation_status_map(operation->result); - gb_connection_err(connection, "deactivate result %hhu", - operation->result); - } else { + else gb_gpio_controller->lines[which].active = false; - pr_debug("%s: %u is now inactive\n", __func__, which); - } -out: gb_operation_destroy(operation); return ret; @@ -291,6 +250,7 @@ static int gb_gpio_get_direction_operation(struct gb_gpio_controller *gb_gpio_co struct gb_gpio_get_direction_request *request; struct gb_gpio_get_direction_response *response; int ret; + u8 direction; if (which > gb_gpio_controller->line_max) return -EINVAL; @@ -310,22 +270,12 @@ static int gb_gpio_get_direction_operation(struct gb_gpio_controller *gb_gpio_co goto out; } - if (operation->result) { - ret = gb_operation_status_map(operation->result); - gb_connection_err(connection, "get direction result %hhu", - operation->result); - } else { - u8 direction; - - response = operation->response->payload; - direction = response->direction; - if (direction && direction != 1) - pr_warn("gpio %u direction was %u (should be 0 or 1)\n", - which, direction); - gb_gpio_controller->lines[which].direction = direction ? 1 : 0; - pr_debug("%s: direction of %u is %s\n", __func__, which, - direction ? "in" : "out"); - } + response = operation->response->payload; + direction = response->direction; + if (direction && direction != 1) + pr_warn("gpio %u direction was %u (should be 0 or 1)\n", + which, direction); + gb_gpio_controller->lines[which].direction = direction ? 1 : 0; out: gb_operation_destroy(operation); @@ -354,20 +304,10 @@ static int gb_gpio_direction_in_operation(struct gb_gpio_controller *gb_gpio_con /* Synchronous operation--no callback */ ret = gb_operation_request_send(operation, NULL); - if (ret) { + if (ret) pr_err("direction in operation failed (%d)\n", ret); - goto out; - } - - if (operation->result) { - ret = gb_operation_status_map(operation->result); - gb_connection_err(connection, "direction in result %hhu", - operation->result); - } else { + else gb_gpio_controller->lines[which].direction = 1; - pr_debug("%s: direction of %u is now in\n", __func__, which); - } -out: gb_operation_destroy(operation); return ret; @@ -396,21 +336,10 @@ static int gb_gpio_direction_out_operation(struct gb_gpio_controller *gb_gpio_co /* Synchronous operation--no callback */ ret = gb_operation_request_send(operation, NULL); - if (ret) { + if (ret) pr_err("direction out operation failed (%d)\n", ret); - goto out; - } - - if (operation->result) { - ret = gb_operation_status_map(operation->result); - gb_connection_err(connection, "direction out result %hhu", - operation->result); - } else { + else gb_gpio_controller->lines[which].direction = 0; - pr_debug("%s: direction of %u is now out, value %s\n", __func__, - which, value_high ? "high" : "low"); - } -out: gb_operation_destroy(operation); return ret; @@ -424,6 +353,7 @@ static int gb_gpio_get_value_operation(struct gb_gpio_controller *gb_gpio_contro struct gb_gpio_get_value_request *request; struct gb_gpio_get_value_response *response; int ret; + u8 value; if (which > gb_gpio_controller->line_max) return -EINVAL; @@ -443,24 +373,12 @@ static int gb_gpio_get_value_operation(struct gb_gpio_controller *gb_gpio_contro goto out; } - if (operation->result) { - ret = gb_operation_status_map(operation->result); - gb_connection_err(connection, "get value result %hhu", - operation->result); - } else { - u8 value; - - response = operation->response->payload; - value = response->value; - if (value && value != 1) - pr_warn("gpio %u value was %u (should be 0 or 1)\n", - which, value); - gb_gpio_controller->lines[which].value = value ? 1 : 0; - /* XXX should this set direction to out? */ - pr_debug("%s: value of %u is %s\n", __func__, which, - gb_gpio_controller->lines[which].value ? "high" : - "low"); - } + response = operation->response->payload; + value = response->value; + if (value && value != 1) + pr_warn("gpio %u value was %u (should be 0 or 1)\n", + which, value); + gb_gpio_controller->lines[which].value = value ? 1 : 0; out: gb_operation_destroy(operation); @@ -490,23 +408,10 @@ static int gb_gpio_set_value_operation(struct gb_gpio_controller *gb_gpio_contro /* Synchronous operation--no callback */ ret = gb_operation_request_send(operation, NULL); - if (ret) { + if (ret) pr_err("set value operation failed (%d)\n", ret); - goto out; - } - - if (operation->result) { - ret = gb_operation_status_map(operation->result); - gb_connection_err(connection, "set value result %hhu", - operation->result); - } else { - /* XXX should this set direction to out? */ + else /* XXX should this set direction to out? */ gb_gpio_controller->lines[which].value = request->value; - pr_debug("%s: out value of %u is now %s\n", __func__, which, - gb_gpio_controller->lines[which].value ? "high" : - "low"); - } -out: gb_operation_destroy(operation); return ret; @@ -535,21 +440,11 @@ static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *gb_gpio_con /* Synchronous operation--no callback */ ret = gb_operation_request_send(operation, NULL); - if (ret) { + if (ret) pr_err("set debounce operation failed (%d)\n", ret); - goto out; - } - - if (operation->result) { - ret = gb_operation_status_map(operation->result); - gb_connection_err(connection, "set debounce result %hhu", - operation->result); - } else { - gb_gpio_controller->lines[which].debounce_usec = le16_to_cpu(request->usec); - pr_debug("%s: debounce of %u is now %hu usec\n", __func__, which, - gb_gpio_controller->lines[which].debounce_usec); - } -out: + else + gb_gpio_controller->lines[which].debounce_usec = + le16_to_cpu(request->usec); gb_operation_destroy(operation); return ret; @@ -562,7 +457,6 @@ static int gb_gpio_request(struct gpio_chip *chip, unsigned offset) if (offset < 0 || offset >= chip->ngpio) return -EINVAL; - pr_debug("%s: passed check\n", __func__); ret = gb_gpio_activate_operation(gb_gpio_controller, (u8)offset); if (ret) ; /* return ret; */ diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index 2a5fb82..6b2fd7e9 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -111,23 +111,16 @@ static int gb_i2c_proto_version_operation(struct gb_i2c_device *gb_i2c_dev) goto out; } - if (operation->result) { - ret = gb_operation_status_map(operation->result); - gb_connection_err(connection, "version result %hhu", - operation->result); - } else { - response = operation->response->payload; - if (response->major > GB_I2C_VERSION_MAJOR) { - pr_err("unsupported major version (%hhu > %hhu)\n", - response->major, GB_I2C_VERSION_MAJOR); - ret = -ENOTSUPP; - goto out; - } - gb_i2c_dev->version_major = response->major; - gb_i2c_dev->version_minor = response->minor; + response = operation->response->payload; + if (response->major > GB_I2C_VERSION_MAJOR) { + pr_err("unsupported major version (%hhu > %hhu)\n", + response->major, GB_I2C_VERSION_MAJOR); + ret = -ENOTSUPP; + goto out; } + gb_i2c_dev->version_major = response->major; + gb_i2c_dev->version_minor = response->minor; out: - gb_operation_destroy(operation); return ret; @@ -163,16 +156,9 @@ static int gb_i2c_functionality_operation(struct gb_i2c_device *gb_i2c_dev) goto out; } - if (operation->result) { - ret = gb_operation_status_map(operation->result); - gb_connection_err(connection, "functionality result %hhu", - operation->result); - } else { - response = operation->response->payload; - functionality = le32_to_cpu(response->functionality); - gb_i2c_dev->functionality = - gb_i2c_functionality_map(functionality); - } + response = operation->response->payload; + functionality = le32_to_cpu(response->functionality); + gb_i2c_dev->functionality = gb_i2c_functionality_map(functionality); out: gb_operation_destroy(operation); @@ -195,19 +181,10 @@ static int gb_i2c_timeout_operation(struct gb_i2c_device *gb_i2c_dev, u16 msec) /* Synchronous operation--no callback */ ret = gb_operation_request_send(operation, NULL); - if (ret) { + if (ret) pr_err("timeout operation failed (%d)\n", ret); - goto out; - } - - if (operation->result) { - ret = gb_operation_status_map(operation->result); - gb_connection_err(connection, "timeout result %hhu", - operation->result); - } else { + else gb_i2c_dev->timeout_msec = msec; - } -out: gb_operation_destroy(operation); return ret; @@ -230,19 +207,10 @@ static int gb_i2c_retries_operation(struct gb_i2c_device *gb_i2c_dev, /* Synchronous operation--no callback */ ret = gb_operation_request_send(operation, NULL); - if (ret) { + if (ret) pr_err("retries operation failed (%d)\n", ret); - goto out; - } - - if (operation->result) { - ret = gb_operation_status_map(operation->result); - gb_connection_err(connection, "retries result %hhu", - operation->result); - } else { + else gb_i2c_dev->retries = retries; - } -out: gb_operation_destroy(operation); return ret; @@ -365,22 +333,13 @@ static int gb_i2c_transfer_operation(struct gb_i2c_device *gb_i2c_dev, /* Synchronous operation--no callback */ ret = gb_operation_request_send(operation, NULL); if (ret) { - pr_err("transfer operation failed (%d)\n", ret); - goto out; - } - - if (operation->result) { - ret = gb_operation_status_map(operation->result); - if (ret != -EAGAIN) { - gb_connection_err(connection, "transfer result %hhu", - operation->result); - } + if (ret != -EAGAIN) + pr_err("transfer operation failed (%d)\n", ret); } else { response = operation->response->payload; gb_i2c_transfer_response(msgs, msg_count, response->data); ret = msg_count; } -out: gb_operation_destroy(operation); return ret; diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 4420465..5ab1c47 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -159,7 +159,11 @@ static void gb_operation_complete(struct gb_operation *operation) complete_all(&operation->completion); } -/* Wait for a submitted operation to complete */ +/* + * Wait for a submitted operation to complete. Returns -RESTARTSYS + * if the wait was interrupted. Otherwise returns the result of the + * operation. + */ int gb_operation_wait(struct gb_operation *operation) { int ret; @@ -168,6 +172,8 @@ int gb_operation_wait(struct gb_operation *operation) /* If interrupted, cancel the in-flight buffer */ if (ret < 0) gb_message_cancel(operation->request); + else + ret = operation->errno; return ret; } @@ -189,7 +195,7 @@ static void gb_operation_request_handle(struct gb_operation *operation) gb_connection_err(operation->connection, "unexpected incoming request type 0x%02hhx\n", header->type); - operation->result = GB_OP_PROTOCOL_BAD; + operation->errno = -EPROTONOSUPPORT; } /* @@ -224,7 +230,7 @@ static void operation_timeout(struct work_struct *work) operation = container_of(work, struct gb_operation, timeout_work.work); pr_debug("%s: timeout!\n", __func__); - operation->result = GB_OP_TIMEOUT; + operation->errno = -ETIMEDOUT; gb_operation_complete(operation); } @@ -470,13 +476,10 @@ int gb_operation_request_send(struct gb_operation *operation, /* All set, send the request */ ret = gb_message_send(operation->request, GFP_KERNEL); - if (ret) + if (ret || callback) return ret; - if (!callback) - ret = gb_operation_wait(operation); - - return ret; + return gb_operation_wait(operation); } /* @@ -493,8 +496,6 @@ int gb_operation_response_send(struct gb_operation *operation) * This function is called when a buffer send request has completed. * The "header" is the message header--the beginning of what we * asked to have sent. - * - * XXX Mismatch between errno here and operation result code */ void greybus_data_sent(struct greybus_host_device *hd, void *header, int status) @@ -510,7 +511,7 @@ greybus_data_sent(struct greybus_host_device *hd, void *header, int status) message = gb_hd_message_find(hd, header); operation = message->operation; gb_connection_err(operation->connection, "send error %d\n", status); - operation->result = status; /* XXX */ + operation->errno = status; gb_operation_complete(operation); } EXPORT_SYMBOL_GPL(greybus_data_sent); @@ -567,14 +568,14 @@ static void gb_connection_recv_response(struct gb_connection *connection, if (size <= message->size) { /* Transfer the operation result from the response header */ header = message->header; - operation->result = header->result; + operation->errno = gb_operation_status_map(header->result); } else { gb_connection_err(connection, "recv buffer too small"); - operation->result = GB_OP_OVERFLOW; + operation->errno = -E2BIG; } /* We must ignore the payload if a bad status is returned */ - if (operation->result == GB_OP_SUCCESS) + if (!operation->errno) memcpy(message->header, data, size); /* The rest will be handled in work queue context */ diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 3e5e1f5..33d5003 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -13,7 +13,7 @@ struct gb_operation; -enum gb_operation_status { +enum gb_operation_result { GB_OP_SUCCESS = 0, GB_OP_INVALID = 1, GB_OP_NO_MEMORY = 2, @@ -71,7 +71,8 @@ struct gb_operation { u16 id; bool canceled; - u8 result; + int errno; /* Operation result */ + struct work_struct recv_work; gb_operation_callback callback; /* If asynchronous */ struct completion completion; /* Used if no callback */ diff --git a/drivers/staging/greybus/pwm-gb.c b/drivers/staging/greybus/pwm-gb.c index d3d39be..e146b24 100644 --- a/drivers/staging/greybus/pwm-gb.c +++ b/drivers/staging/greybus/pwm-gb.c @@ -104,21 +104,15 @@ static int gb_pwm_proto_version_operation(struct gb_pwm_chip *pwmc) goto out; } - if (operation->result) { - ret = gb_operation_status_map(operation->result); - gb_connection_err(connection, "version result %hhu", - operation->result); - } else { - response = operation->response->payload; - if (response->major > GB_PWM_VERSION_MAJOR) { - pr_err("unsupported major version (%hhu > %hhu)\n", - response->major, GB_PWM_VERSION_MAJOR); - ret = -ENOTSUPP; - goto out; - } - pwmc->version_major = response->major; - pwmc->version_minor = response->minor; + response = operation->response->payload; + if (response->major > GB_PWM_VERSION_MAJOR) { + pr_err("unsupported major version (%hhu > %hhu)\n", + response->major, GB_PWM_VERSION_MAJOR); + ret = -ENOTSUPP; + goto out; } + pwmc->version_major = response->major; + pwmc->version_minor = response->minor; out: gb_operation_destroy(operation); @@ -142,18 +136,10 @@ static int gb_pwm_count_operation(struct gb_pwm_chip *pwmc) ret = gb_operation_request_send(operation, NULL); if (ret) { pr_err("line count operation failed (%d)\n", ret); - goto out; - } - - if (operation->result) { - ret = gb_operation_status_map(operation->result); - gb_connection_err(connection, "pwm count result %hhu", - operation->result); } else { response = operation->response->payload; pwmc->pwm_max = response->count; } -out: gb_operation_destroy(operation); return ret; @@ -180,17 +166,8 @@ static int gb_pwm_activate_operation(struct gb_pwm_chip *pwmc, /* Synchronous operation--no callback */ ret = gb_operation_request_send(operation, NULL); - if (ret) { + if (ret) pr_err("activate operation failed (%d)\n", ret); - goto out; - } - - if (operation->result) { - ret = gb_operation_status_map(operation->result); - gb_connection_err(connection, "activate result %hhu", - operation->result); - } -out: gb_operation_destroy(operation); return ret; @@ -217,17 +194,8 @@ static int gb_pwm_deactivate_operation(struct gb_pwm_chip *pwmc, /* Synchronous operation--no callback */ ret = gb_operation_request_send(operation, NULL); - if (ret) { + if (ret) pr_err("deactivate operation failed (%d)\n", ret); - goto out; - } - - if (operation->result) { - ret = gb_operation_status_map(operation->result); - gb_connection_err(connection, "deactivate result %hhu", - operation->result); - } -out: gb_operation_destroy(operation); return ret; @@ -255,17 +223,8 @@ static int gb_pwm_config_operation(struct gb_pwm_chip *pwmc, /* Synchronous operation--no callback */ ret = gb_operation_request_send(operation, NULL); - if (ret) { + if (ret) pr_err("config operation failed (%d)\n", ret); - goto out; - } - - if (operation->result) { - ret = gb_operation_status_map(operation->result); - gb_connection_err(connection, "config result %hhu", - operation->result); - } -out: gb_operation_destroy(operation); return ret; @@ -293,17 +252,8 @@ static int gb_pwm_set_polarity_operation(struct gb_pwm_chip *pwmc, /* Synchronous operation--no callback */ ret = gb_operation_request_send(operation, NULL); - if (ret) { + if (ret) pr_err("set polarity operation failed (%d)\n", ret); - goto out; - } - - if (operation->result) { - ret = gb_operation_status_map(operation->result); - gb_connection_err(connection, "set polarity result %hhu", - operation->result); - } -out: gb_operation_destroy(operation); return ret; @@ -330,17 +280,8 @@ static int gb_pwm_enable_operation(struct gb_pwm_chip *pwmc, /* Synchronous operation--no callback */ ret = gb_operation_request_send(operation, NULL); - if (ret) { + if (ret) pr_err("enable operation failed (%d)\n", ret); - goto out; - } - - if (operation->result) { - ret = gb_operation_status_map(operation->result); - gb_connection_err(connection, "enable result %hhu", - operation->result); - } -out: gb_operation_destroy(operation); return ret; @@ -367,17 +308,8 @@ static int gb_pwm_disable_operation(struct gb_pwm_chip *pwmc, /* Synchronous operation--no callback */ ret = gb_operation_request_send(operation, NULL); - if (ret) { + if (ret) pr_err("disable operation failed (%d)\n", ret); - goto out; - } - - if (operation->result) { - ret = gb_operation_status_map(operation->result); - gb_connection_err(connection, "disable result %hhu", - operation->result); - } -out: gb_operation_destroy(operation); return ret; diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 48fad7b..e9faf31 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -154,24 +154,18 @@ static int get_version(struct gb_tty *tty) goto out; } - if (operation->result) { - ret = gb_operation_status_map(operation->result); - gb_connection_err(tty->connection, "result %hhu", - operation->result); - } else { - response = operation->response->payload; - if (response->major > GB_UART_VERSION_MAJOR) { - pr_err("unsupported major version (%hhu > %hhu)\n", - response->major, GB_UART_VERSION_MAJOR); - ret = -ENOTSUPP; - goto out; - } - tty->version_major = response->major; - tty->version_minor = response->minor; - - pr_debug("%s: version_major = %u version_minor = %u\n", - __func__, tty->version_major, tty->version_minor); + response = operation->response->payload; + if (response->major > GB_UART_VERSION_MAJOR) { + pr_err("unsupported major version (%hhu > %hhu)\n", + response->major, GB_UART_VERSION_MAJOR); + ret = -ENOTSUPP; + goto out; } + tty->version_major = response->major; + tty->version_minor = response->minor; + + pr_debug("%s: version_major = %u version_minor = %u\n", + __func__, tty->version_major, tty->version_minor); out: gb_operation_destroy(operation); @@ -198,18 +192,9 @@ static int send_data(struct gb_tty *tty, u16 size, const u8 *data) /* Synchronous operation--no callback */ retval = gb_operation_request_send(operation, NULL); - if (retval) { + if (retval) dev_err(&connection->dev, "send data operation failed (%d)\n", retval); - goto out; - } - - if (operation->result) { - retval = gb_operation_status_map(operation->result); - gb_connection_err(connection, "send data result %hhu", - operation->result); - } -out: gb_operation_destroy(operation); return retval; @@ -232,18 +217,9 @@ static int send_line_coding(struct gb_tty *tty, /* Synchronous operation--no callback */ retval = gb_operation_request_send(operation, NULL); - if (retval) { + if (retval) dev_err(&connection->dev, "send line coding operation failed (%d)\n", retval); - goto out; - } - - if (operation->result) { - retval = gb_operation_status_map(operation->result); - gb_connection_err(connection, "send line coding result %hhu", - operation->result); - } -out: gb_operation_destroy(operation); return retval; @@ -266,18 +242,9 @@ static int send_control(struct gb_tty *tty, u16 control) /* Synchronous operation--no callback */ retval = gb_operation_request_send(operation, NULL); - if (retval) { + if (retval) dev_err(&connection->dev, "send control operation failed (%d)\n", retval); - goto out; - } - - if (operation->result) { - retval = gb_operation_status_map(operation->result); - gb_connection_err(connection, "send control result %hhu", - operation->result); - } -out: gb_operation_destroy(operation); return retval; @@ -304,18 +271,9 @@ static int send_break(struct gb_tty *tty, u8 state) /* Synchronous operation--no callback */ retval = gb_operation_request_send(operation, NULL); - if (retval) { + if (retval) dev_err(&connection->dev, "send break operation failed (%d)\n", retval); - goto out; - } - - if (operation->result) { - retval = gb_operation_status_map(operation->result); - gb_connection_err(connection, "send break result %hhu", - operation->result); - } -out: gb_operation_destroy(operation); return retval; diff --git a/drivers/staging/greybus/vibrator-gb.c b/drivers/staging/greybus/vibrator-gb.c index b974973..b65a586 100644 --- a/drivers/staging/greybus/vibrator-gb.c +++ b/drivers/staging/greybus/vibrator-gb.c @@ -42,6 +42,13 @@ struct gb_vibrator_on_request { __le16 timeout_ms; }; +/* + * The get_version and turn_off vibrator operations have no payload. + * This function implements these requests by allowing the caller to + * supply a buffer into which the operation response should be + * copied. The turn_off operation, there is no response either. + * If there is an error, the response buffer is left alone. + */ static int request_operation(struct gb_connection *connection, int type, void *response, int response_size) { @@ -54,27 +61,11 @@ static int request_operation(struct gb_connection *connection, int type, /* Synchronous operation--no callback */ ret = gb_operation_request_send(operation, NULL); - if (ret) { + if (ret) pr_err("version operation failed (%d)\n", ret); - goto out; - } - - /* - * We only want to look at the status, and all requests have the same - * layout for where the status is, so cast this to a random request so - * we can see the status easier. - */ - if (operation->result) { - ret = gb_operation_status_map(operation->result); - gb_connection_err(connection, "operation result %hhu", - operation->result); - } else { - /* Good request, so copy to the caller's buffer */ - if (response_size && response) - memcpy(response, operation->response->payload, - response_size); - } -out: + else if (response_size && response) + memcpy(response, operation->response->payload, + response_size); gb_operation_destroy(operation); return ret; @@ -124,18 +115,9 @@ static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms) /* Synchronous operation--no callback */ retval = gb_operation_request_send(operation, NULL); - if (retval) { + if (retval) dev_err(&connection->dev, "send data operation failed (%d)\n", retval); - goto out; - } - - if (operation->result) { - retval = gb_operation_status_map(operation->result); - gb_connection_err(connection, "send data result %hhu", - operation->result); - } -out: gb_operation_destroy(operation); return retval; -- cgit v0.10.2 From ee637a9b0e7452c1e3fa12f2d70bc4736a486096 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 21 Nov 2014 19:29:13 -0600 Subject: greybus: abandon incoming requests for now Change the operation "receive workqueue" to be just the operation "workqueue". All it does is complete an operation in non-atomic context. This is all that's required for an outgoing request. Similarly, ignore any notion that a response will only exist for outgoing requests in gb_operation_cancel(). I'm doing this in the interest of getting the outgoing request path verified without the encumbrance of any preconceptions about how incoming requests need to work. When I finally turn my full attenion to incoming requests I'll adapt the code as needed. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 5ab1c47..4e4fa8b 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -30,7 +30,7 @@ static struct kmem_cache *gb_operation_cache; /* Workqueue to handle Greybus operation completions. */ -static struct workqueue_struct *gb_operation_recv_workqueue; +static struct workqueue_struct *gb_operation_workqueue; /* * All operation messages (both requests and responses) begin with @@ -177,6 +177,7 @@ int gb_operation_wait(struct gb_operation *operation) return ret; } +#if 0 static void gb_operation_request_handle(struct gb_operation *operation) { struct gb_protocol *protocol = operation->connection->protocol; @@ -197,22 +198,17 @@ static void gb_operation_request_handle(struct gb_operation *operation) "unexpected incoming request type 0x%02hhx\n", header->type); operation->errno = -EPROTONOSUPPORT; } +#endif /* - * Either this operation contains an incoming request, or its - * response has arrived. An incoming request will have a null - * response buffer pointer (it is the responsibility of the request - * handler to allocate and fill in the response buffer). + * Complete an operation in non-atomic context. The operation's + * result value should have been set before queueing this. */ -static void gb_operation_recv_work(struct work_struct *recv_work) +static void gb_operation_work(struct work_struct *work) { struct gb_operation *operation; - bool incoming_request; - operation = container_of(recv_work, struct gb_operation, recv_work); - incoming_request = operation->response->header == NULL; - if (incoming_request) - gb_operation_request_handle(operation); + operation = container_of(work, struct gb_operation, work); gb_operation_complete(operation); } @@ -376,7 +372,7 @@ gb_operation_create_common(struct gb_connection *connection, bool outgoing, operation->response->operation = operation; } - INIT_WORK(&operation->recv_work, gb_operation_recv_work); + INIT_WORK(&operation->work, gb_operation_work); operation->callback = NULL; /* set at submit time */ init_completion(&operation->completion); INIT_DELAYED_WORK(&operation->timeout_work, operation_timeout); @@ -536,8 +532,9 @@ void gb_connection_recv_request(struct gb_connection *connection, operation->id = operation_id; memcpy(operation->request->header, data, size); - /* The rest will be handled in work queue context */ - queue_work(gb_operation_recv_workqueue, &operation->recv_work); + /* XXX Right now this will just complete the operation */ + operation->errno = -ENOSYS; + queue_work(gb_operation_workqueue, &operation->work); } /* @@ -579,7 +576,7 @@ static void gb_connection_recv_response(struct gb_connection *connection, memcpy(message->header, data, size); /* The rest will be handled in work queue context */ - queue_work(gb_operation_recv_workqueue, &operation->recv_work); + queue_work(gb_operation_workqueue, &operation->work); } /* @@ -628,8 +625,7 @@ void gb_operation_cancel(struct gb_operation *operation) { operation->canceled = true; gb_message_cancel(operation->request); - if (operation->response->header) - gb_message_cancel(operation->response); + gb_message_cancel(operation->response); } int gb_operation_init(void) @@ -639,8 +635,8 @@ int gb_operation_init(void) if (!gb_operation_cache) return -ENOMEM; - gb_operation_recv_workqueue = alloc_workqueue("greybus_recv", 0, 1); - if (!gb_operation_recv_workqueue) { + gb_operation_workqueue = alloc_workqueue("greybus_operation", 0, 1); + if (!gb_operation_workqueue) { kmem_cache_destroy(gb_operation_cache); gb_operation_cache = NULL; return -ENOMEM; @@ -651,8 +647,8 @@ int gb_operation_init(void) void gb_operation_exit(void) { - destroy_workqueue(gb_operation_recv_workqueue); - gb_operation_recv_workqueue = NULL; + destroy_workqueue(gb_operation_workqueue); + gb_operation_workqueue = NULL; kmem_cache_destroy(gb_operation_cache); gb_operation_cache = NULL; } diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 33d5003..f608844 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -73,7 +73,7 @@ struct gb_operation { int errno; /* Operation result */ - struct work_struct recv_work; + struct work_struct work; gb_operation_callback callback; /* If asynchronous */ struct completion completion; /* Used if no callback */ struct delayed_work timeout_work; -- cgit v0.10.2 From 583c3117a4d36499adfe6de186826d59f5c4d788 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 21 Nov 2014 19:29:14 -0600 Subject: greybus: handle data send errors in workqueue The data sent callback can execute in atomic context. If an error occurred, we shouldn't be completing the operation right then and there. Instead, hand it off to the operation workqueue to complete the operation. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 4e4fa8b..9ad714e 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -506,9 +506,8 @@ greybus_data_sent(struct greybus_host_device *hd, void *header, int status) /* XXX Right now we assume we're an outgoing request */ message = gb_hd_message_find(hd, header); operation = message->operation; - gb_connection_err(operation->connection, "send error %d\n", status); operation->errno = status; - gb_operation_complete(operation); + queue_work(gb_operation_workqueue, &operation->work); } EXPORT_SYMBOL_GPL(greybus_data_sent); -- cgit v0.10.2 From deb4b9efb30606b8cb1150b8ae1e922405f60f8d Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 21 Nov 2014 19:29:15 -0600 Subject: greybus: add a reference to pending operations Grab an extra reference to an operation before sending it. Drop that reference at the end of its completion handling. It turns out gb_operation_get() got deleted along the way, so this re-introduces it. We're assuming we only get a reference when there's at least one in existence so we don't need a semaphore to protect it. Emphasize this by *not* returning a pointer to the referenced operation. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 9ad714e..ab27cd9 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -157,6 +157,7 @@ static void gb_operation_complete(struct gb_operation *operation) operation->callback(operation); else complete_all(&operation->completion); + gb_operation_put(operation); } /* @@ -410,6 +411,14 @@ gb_operation_create_incoming(struct gb_connection *connection, } /* + * Get an additional reference on an operation. + */ +void gb_operation_get(struct gb_operation *operation) +{ + kref_get(&operation->kref); +} + +/* * Destroy a previously created operation. */ static void _gb_operation_destroy(struct kref *kref) @@ -429,6 +438,10 @@ static void _gb_operation_destroy(struct kref *kref) kmem_cache_free(gb_operation_cache, operation); } +/* + * Drop a reference on an operation, and destroy it when the last + * one is gone. + */ void gb_operation_put(struct gb_operation *operation) { if (!WARN_ON(!operation)) @@ -454,11 +467,11 @@ int gb_operation_request_send(struct gb_operation *operation, return -ENOTCONN; /* - * XXX - * I think the order of operations is going to be - * significant, and if so, we may need a mutex to surround - * setting the operation id and submitting the buffer. + * First, get an extra reference on the operation. + * It'll be dropped when the operation completes. */ + gb_operation_get(operation); + operation->callback = callback; gb_pending_operation_insert(operation); diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index f608844..befce15 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -88,7 +88,7 @@ void gb_connection_recv(struct gb_connection *connection, struct gb_operation *gb_operation_create(struct gb_connection *connection, u8 type, size_t request_size, size_t response_size); -struct gb_operation *gb_operation_get(struct gb_operation *operation); +void gb_operation_get(struct gb_operation *operation); void gb_operation_put(struct gb_operation *operation); static inline void gb_operation_destroy(struct gb_operation *operation) { -- cgit v0.10.2 From 0e3d0e8fad52ed478647a1a122e21c7deb7f96cf Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 21 Nov 2014 19:29:16 -0600 Subject: greybus: minor tweak in gb_connection_recv_response() Any time we queue work on the operation work queue we need to have set the operation errno first. This patch moves the assignment of that field to be immediately prior to the queue_work() call in gb_connection_recv_response(), so it is easier to see at a glance that this has been done. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index ab27cd9..32cd235 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -563,6 +563,7 @@ static void gb_connection_recv_response(struct gb_connection *connection, struct gb_operation *operation; struct gb_message *message; struct gb_operation_msg_hdr *header; + int result; operation = gb_pending_operation_find(connection, operation_id); if (!operation) { @@ -577,17 +578,18 @@ static void gb_connection_recv_response(struct gb_connection *connection, if (size <= message->size) { /* Transfer the operation result from the response header */ header = message->header; - operation->errno = gb_operation_status_map(header->result); + result = gb_operation_status_map(header->result); } else { gb_connection_err(connection, "recv buffer too small"); - operation->errno = -E2BIG; + result = -E2BIG; } /* We must ignore the payload if a bad status is returned */ - if (!operation->errno) + if (!result) memcpy(message->header, data, size); /* The rest will be handled in work queue context */ + operation->errno = result; queue_work(gb_operation_workqueue, &operation->work); } -- cgit v0.10.2 From f68c05c0216e09ed93b12894747d8583dc5b8f8e Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 21 Nov 2014 19:29:17 -0600 Subject: greybus: cancel operation on timeout If an operation times out, we need to cancel whatever message it has in-flight. Do that instead of completing the operation, in the timeout handler. When the in-flight request message is canceled its completion function will lead to the proper completion of the operation. Change gb_operation_cancel() so it takes the errno that it's supposed to assign as the result of the operation. Note that we want to preserve the original -ETIMEDOUT error, so don't overwrite the operation result value if it has already been set. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 8cb2af3..6503546 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -212,7 +212,7 @@ void gb_connection_destroy(struct gb_connection *connection) if (WARN_ON(!list_empty(&connection->operations))) { list_for_each_entry_safe(operation, next, &connection->operations, links) - gb_operation_cancel(operation); + gb_operation_cancel(operation, -ESHUTDOWN); } spin_lock_irq(&gb_connections_lock); list_del(&connection->interface_links); diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 32cd235..dc12e6d 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -215,20 +215,13 @@ static void gb_operation_work(struct work_struct *work) /* * Timeout call for the operation. - * - * If this fires, something went wrong, so mark the result as timed out, and - * run the completion handler, which (hopefully) should clean up the operation - * properly. */ -static void operation_timeout(struct work_struct *work) +static void gb_operation_timeout(struct work_struct *work) { struct gb_operation *operation; operation = container_of(work, struct gb_operation, timeout_work.work); - pr_debug("%s: timeout!\n", __func__); - - operation->errno = -ETIMEDOUT; - gb_operation_complete(operation); + gb_operation_cancel(operation, -ETIMEDOUT); } /* @@ -376,7 +369,7 @@ gb_operation_create_common(struct gb_connection *connection, bool outgoing, INIT_WORK(&operation->work, gb_operation_work); operation->callback = NULL; /* set at submit time */ init_completion(&operation->completion); - INIT_DELAYED_WORK(&operation->timeout_work, operation_timeout); + INIT_DELAYED_WORK(&operation->timeout_work, gb_operation_timeout); kref_init(&operation->kref); spin_lock_irq(&gb_operations_lock); @@ -633,11 +626,11 @@ void gb_connection_recv(struct gb_connection *connection, } /* - * Cancel an operation. + * Cancel an operation, and record the given error to indicate why. */ -void gb_operation_cancel(struct gb_operation *operation) +void gb_operation_cancel(struct gb_operation *operation, int errno) { - operation->canceled = true; + operation->errno = errno; gb_message_cancel(operation->request); gb_message_cancel(operation->response); } diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index befce15..d24e5e0 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -69,7 +69,6 @@ struct gb_operation { struct gb_message *request; struct gb_message *response; u16 id; - bool canceled; int errno; /* Operation result */ @@ -99,7 +98,7 @@ int gb_operation_request_send(struct gb_operation *operation, gb_operation_callback callback); int gb_operation_response_send(struct gb_operation *operation); -void gb_operation_cancel(struct gb_operation *operation); +void gb_operation_cancel(struct gb_operation *operation, int errno); int gb_operation_wait(struct gb_operation *operation); int gb_operation_status_map(u8 status); -- cgit v0.10.2 From 7035833f081cefc3953a6a72a61767967f59a59e Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 21 Nov 2014 19:29:18 -0600 Subject: greybus: cancel whole operation on interrupt Cancel the operation--not just the request message--if waiting for a synchronous operation to complete is interrupted. Return the operation result (which in that case will be -EINTR). The cancelation will result in the normal operation completion path being taken before returning. Make gb_operation_wait() private, since it's only ever used for for synchronous operations. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index dc12e6d..f4d984f 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -161,21 +161,18 @@ static void gb_operation_complete(struct gb_operation *operation) } /* - * Wait for a submitted operation to complete. Returns -RESTARTSYS - * if the wait was interrupted. Otherwise returns the result of the - * operation. + * Wait for a submitted operation to complete. Returns the result + * of the operation; this will be -EINTR if the wait was interrupted. */ -int gb_operation_wait(struct gb_operation *operation) +static int gb_operation_wait(struct gb_operation *operation) { int ret; ret = wait_for_completion_interruptible(&operation->completion); - /* If interrupted, cancel the in-flight buffer */ if (ret < 0) - gb_message_cancel(operation->request); - else - ret = operation->errno; - return ret; + gb_operation_cancel(operation, -EINTR); + + return operation->errno; } #if 0 diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index d24e5e0..c391b28 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -99,7 +99,6 @@ int gb_operation_request_send(struct gb_operation *operation, int gb_operation_response_send(struct gb_operation *operation); void gb_operation_cancel(struct gb_operation *operation, int errno); -int gb_operation_wait(struct gb_operation *operation); int gb_operation_status_map(u8 status); -- cgit v0.10.2 From 2cf72a233a5d29bee380e89d325cde422a0c6bac Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 21 Nov 2014 19:29:19 -0600 Subject: greybus: kill gb_operation_wait() When a caller wants an operation to complete synchronously, there is generally no need for any other threads to wait for the operation's completion. So here's no need for gb_operation_wait() to be available for synchronous requests. At the moment, all operations are done synchronously. Knowing that, get rid of the public gb_operation_wait() function, and open-code it in gb_operation_request_send(). The public wait function can be re-implemented when it's really needed. With that function gone, the only waiter for the completion of an operation is the submitter itself, and only then if it's synchronous. So rather than complete_all(), we can simply use complete() to signal the submitter. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index f4d984f..032973c 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -156,25 +156,10 @@ static void gb_operation_complete(struct gb_operation *operation) if (operation->callback) operation->callback(operation); else - complete_all(&operation->completion); + complete(&operation->completion); gb_operation_put(operation); } -/* - * Wait for a submitted operation to complete. Returns the result - * of the operation; this will be -EINTR if the wait was interrupted. - */ -static int gb_operation_wait(struct gb_operation *operation) -{ - int ret; - - ret = wait_for_completion_interruptible(&operation->completion); - if (ret < 0) - gb_operation_cancel(operation, -EINTR); - - return operation->errno; -} - #if 0 static void gb_operation_request_handle(struct gb_operation *operation) { @@ -478,7 +463,12 @@ int gb_operation_request_send(struct gb_operation *operation, if (ret || callback) return ret; - return gb_operation_wait(operation); + /* Cancel the operation if interrupted */ + ret = wait_for_completion_interruptible(&operation->completion); + if (ret < 0) + gb_operation_cancel(operation, -EINTR); + + return operation->errno; } /* -- cgit v0.10.2 From 10c69399043351e5c68f07bedd14fe2fdbf32cb4 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 21 Nov 2014 19:29:20 -0600 Subject: greybus: rework synchronous operation completion The only time we need a completion signaled on a request is when the request provided no callback function. In that case, we wait for a completion on behalf of the caller. If an interrupt occurs, we attempt to cancel the message that's been sent, but we don't actually complete the operation as required. Instead of simply waiting for the completion, put in place a special callback function for the synchronous operation. The only job the callback has is to signal completion, allowing the waiter to know it's done. This means gb_operation_complete() will always have a non-null callback pointer, so it becomes a simple wrapper, and we can get rid of it and invoke the callback directly, in gb_operation_work(). Be defensive by checking for a null callback pointer, and reset it to NULL once it's been called. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 032973c..180d028 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -145,21 +145,6 @@ static void gb_message_cancel(struct gb_message *message) hd->driver->buffer_cancel(message->cookie); } -/* - * An operation's response message has arrived. If no callback was - * supplied it was submitted for asynchronous completion, so we notify - * any waiters. Otherwise we assume calling the completion is enough - * and nobody else will be waiting. - */ -static void gb_operation_complete(struct gb_operation *operation) -{ - if (operation->callback) - operation->callback(operation); - else - complete(&operation->completion); - gb_operation_put(operation); -} - #if 0 static void gb_operation_request_handle(struct gb_operation *operation) { @@ -192,7 +177,12 @@ static void gb_operation_work(struct work_struct *work) struct gb_operation *operation; operation = container_of(work, struct gb_operation, work); - gb_operation_complete(operation); + if (WARN_ON(!operation->callback)) + return; + + operation->callback(operation); + operation->callback = NULL; + gb_operation_put(operation); } /* @@ -423,14 +413,22 @@ void gb_operation_put(struct gb_operation *operation) kref_put(&operation->kref, _gb_operation_destroy); } +/* Tell the requester we're done */ +static void gb_operation_sync_callback(struct gb_operation *operation) +{ + complete(&operation->completion); +} + /* * Send an operation request message. The caller has filled in * any payload so the request message is ready to go. If non-null, * the callback function supplied will be called when the response - * message has arrived indicating the operation is complete. A null + * message has arrived indicating the operation is complete. In + * that case, the callback function is responsible for extracting + * the result of the operation from operation->errno if desired, + * and dropping the final reference to the operation. A null * callback function is used for a synchronous request; return from - * this function won't occur until the operation is complete (or an - * interrupt occurs). + * this function won't occur until the operation is complete. */ int gb_operation_request_send(struct gb_operation *operation, gb_operation_callback callback) @@ -447,7 +445,11 @@ int gb_operation_request_send(struct gb_operation *operation, */ gb_operation_get(operation); - operation->callback = callback; + /* A null callback pointer means synchronous return */ + if (callback) + operation->callback = callback; + else + operation->callback = gb_operation_sync_callback; gb_pending_operation_insert(operation); /* -- cgit v0.10.2 From 10aa801d331609c38a58e0c4e73fd31103ffa230 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 24 Nov 2014 11:19:13 -0800 Subject: greybus: operation: create gb_operation_sync for sending "simple" messages Everyone keeps doing the same create/send/destroy logic all over the place, so abstract that out to a simple function that can handle any arbritrary request and/or response. This will let us save lots of duplicated logic in the protocol drivers. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 180d028..35fcb88 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -624,6 +624,60 @@ void gb_operation_cancel(struct gb_operation *operation, int errno) gb_message_cancel(operation->response); } +/** + * gb_operation_sync: implement a "simple" synchronous gb operation. + * @connection: the Greybus connection to send this to + * @type: the type of operation to send + * @request: pointer to a memory buffer to copy the request from + * @request_size: size of @request + * @response: pointer to a memory buffer to copy the response to + * @response_size: the size of @response. + * + * This function implements a simple synchronous Greybus operation. It sends + * the provided operation request and waits (sleeps) until the corresponding + * operation response message has been successfully received, or an error + * occurs. @request and @response are buffers to hold the request and response + * data respectively, and if they are not NULL, their size must be specified in + * @request_size and @response_size. + * + * If a response payload is to come back, and @response is not NULL, + * @response_size number of bytes will be copied into @response if the operation + * is successful. + * + * If there is an error, the response buffer is left alone. + */ +int gb_operation_sync(struct gb_connection *connection, int type, + void *request, int request_size, + void *response, int response_size) +{ + struct gb_operation *operation; + int ret; + + if ((response_size && !response) || + (request_size && !request)) + return -EINVAL; + + operation = gb_operation_create(connection, type, + request_size, response_size); + if (!operation) + return -ENOMEM; + + if (request_size) + memcpy(&operation->request->payload, request, request_size); + + /* Synchronous operation--no callback */ + ret = gb_operation_request_send(operation, NULL); + if (ret) + pr_err("version operation failed (%d)\n", ret); + else + if (response_size) + memcpy(response, operation->response->payload, + response_size); + gb_operation_destroy(operation); + + return ret; +} + int gb_operation_init(void) { gb_operation_cache = kmem_cache_create("gb_operation_cache", diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index c391b28..bc5c164 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -105,6 +105,10 @@ int gb_operation_status_map(u8 status); void greybus_data_sent(struct greybus_host_device *hd, void *header, int status); +int gb_operation_sync(struct gb_connection *connection, int type, + void *request, int request_size, + void *response, int response_size); + int gb_operation_init(void); void gb_operation_exit(void); -- cgit v0.10.2 From d5671a6a24066dbf717ed83c143df7145377756c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 23 Nov 2014 17:45:19 -0800 Subject: greybus: battery-gb: convert to use gb_operation_sync This converts the battery protocol driver to use gb_operation_sync, removing the hand-rolled version of the same function. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index ae03869..d28be04 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -85,34 +85,6 @@ struct gb_battery_voltage_response { }; /* - * None of the battery operation requests have any payload. This - * function implements all of the requests by allowing the caller to - * supply a buffer into which the operation response should be - * copied. If there is an error, the response buffer is left alone. - */ -static int battery_operation(struct gb_battery *gb, int type, - void *response, int response_size) -{ - struct gb_connection *connection = gb->connection; - struct gb_operation *operation; - int ret; - - operation = gb_operation_create(connection, type, 0, response_size); - if (!operation) - return -ENOMEM; - - /* Synchronous operation--no callback */ - ret = gb_operation_request_send(operation, NULL); - if (ret) - pr_err("version operation failed (%d)\n", ret); - else /* Good response, so copy to the caller's buffer */ - memcpy(response, operation->response->payload, response_size); - gb_operation_destroy(operation); - - return ret; -} - -/* * This request only uses the connection field, and if successful, * fills in the major and minor protocol version of the target. */ @@ -121,7 +93,9 @@ static int get_version(struct gb_battery *gb) struct gb_battery_proto_version_response version_response; int retval; - retval = battery_operation(gb, GB_BATTERY_TYPE_PROTOCOL_VERSION, + retval = gb_operation_sync(gb->connection, + GB_BATTERY_TYPE_PROTOCOL_VERSION, + NULL, 0, &version_response, sizeof(version_response)); if (retval) return retval; @@ -143,7 +117,8 @@ static int get_tech(struct gb_battery *gb) u32 technology; int retval; - retval = battery_operation(gb, GB_BATTERY_TYPE_TECHNOLOGY, + retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_TECHNOLOGY, + NULL, 0, &tech_response, sizeof(tech_response)); if (retval) return retval; @@ -187,7 +162,8 @@ static int get_status(struct gb_battery *gb) u16 battery_status; int retval; - retval = battery_operation(gb, GB_BATTERY_TYPE_STATUS, + retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_STATUS, + NULL, 0, &status_response, sizeof(status_response)); if (retval) return retval; @@ -225,7 +201,8 @@ static int get_max_voltage(struct gb_battery *gb) u32 max_voltage; int retval; - retval = battery_operation(gb, GB_BATTERY_TYPE_MAX_VOLTAGE, + retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_MAX_VOLTAGE, + NULL, 0, &volt_response, sizeof(volt_response)); if (retval) return retval; @@ -240,8 +217,9 @@ static int get_capacity(struct gb_battery *gb) u32 capacity; int retval; - retval = battery_operation(gb, GB_BATTERY_TYPE_CAPACITY, - &capacity_response, sizeof(capacity_response)); + retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_CAPACITY, + NULL, 0, &capacity_response, + sizeof(capacity_response)); if (retval) return retval; @@ -255,7 +233,8 @@ static int get_temp(struct gb_battery *gb) u32 temperature; int retval; - retval = battery_operation(gb, GB_BATTERY_TYPE_TEMPERATURE, + retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_TEMPERATURE, + NULL, 0, &temp_response, sizeof(temp_response)); if (retval) return retval; @@ -270,7 +249,8 @@ static int get_voltage(struct gb_battery *gb) u32 voltage; int retval; - retval = battery_operation(gb, GB_BATTERY_TYPE_VOLTAGE, + retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_VOLTAGE, + NULL, 0, &voltage_response, sizeof(voltage_response)); if (retval) return retval; -- cgit v0.10.2 From ac3d24930226fac39ea6023577a03b9b5da4d5f6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 23 Nov 2014 17:45:20 -0800 Subject: greybus: vibrator-gb: convert to use gb_operation_sync This converts the vibrator protocol driver to use gb_operation_sync, removing the hand-rolled version of the same function, as well as removing an open-coded version for a request when turning on the vibrator motor. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/vibrator-gb.c b/drivers/staging/greybus/vibrator-gb.c index b65a586..d00301d 100644 --- a/drivers/staging/greybus/vibrator-gb.c +++ b/drivers/staging/greybus/vibrator-gb.c @@ -43,35 +43,6 @@ struct gb_vibrator_on_request { }; /* - * The get_version and turn_off vibrator operations have no payload. - * This function implements these requests by allowing the caller to - * supply a buffer into which the operation response should be - * copied. The turn_off operation, there is no response either. - * If there is an error, the response buffer is left alone. - */ -static int request_operation(struct gb_connection *connection, int type, - void *response, int response_size) -{ - struct gb_operation *operation; - int ret; - - operation = gb_operation_create(connection, type, 0, response_size); - if (!operation) - return -ENOMEM; - - /* Synchronous operation--no callback */ - ret = gb_operation_request_send(operation, NULL); - if (ret) - pr_err("version operation failed (%d)\n", ret); - else if (response_size && response) - memcpy(response, operation->response->payload, - response_size); - gb_operation_destroy(operation); - - return ret; -} - -/* * This request only uses the connection field, and if successful, * fills in the major and minor protocol version of the target. */ @@ -81,8 +52,9 @@ static int get_version(struct gb_vibrator_device *vib) struct gb_vibrator_proto_version_response version_response; int retval; - retval = request_operation(connection, + retval = gb_operation_sync(connection, GB_VIBRATOR_TYPE_PROTOCOL_VERSION, + NULL, 0, &version_response, sizeof(version_response)); if (retval) return retval; @@ -101,33 +73,17 @@ static int get_version(struct gb_vibrator_device *vib) static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms) { - struct gb_connection *connection = vib->connection; - struct gb_operation *operation; - struct gb_vibrator_on_request *request; - int retval; - - operation = gb_operation_create(connection, GB_VIBRATOR_TYPE_ON, - sizeof(*request), 0); - if (!operation) - return -ENOMEM; - request = operation->request->payload; - request->timeout_ms = cpu_to_le16(timeout_ms); + struct gb_vibrator_on_request request; - /* Synchronous operation--no callback */ - retval = gb_operation_request_send(operation, NULL); - if (retval) - dev_err(&connection->dev, - "send data operation failed (%d)\n", retval); - gb_operation_destroy(operation); - - return retval; + request.timeout_ms = cpu_to_le16(timeout_ms); + return gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_ON, + &request, sizeof(request), NULL, 0); } static int turn_off(struct gb_vibrator_device *vib) { - struct gb_connection *connection = vib->connection; - - return request_operation(connection, GB_VIBRATOR_TYPE_OFF, NULL, 0); + return gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_OFF, + NULL, 0, NULL, 0); } static ssize_t timeout_store(struct device *dev, struct device_attribute *attr, -- cgit v0.10.2 From e51f1d1a7711e2d68922dab08e2edc13fea8925a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 23 Nov 2014 17:45:21 -0800 Subject: greybus: uart-gb: convert to use gb_operation_sync This converts the UART protocol driver to use gb_operation_sync, removing lots of places where the create/send/destroy pattern was being used to send greybus messages. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index e9faf31..10d00b7 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -137,146 +137,82 @@ static atomic_t reference_count = ATOMIC_INIT(0); */ static int get_version(struct gb_tty *tty) { - struct gb_operation *operation; - struct gb_uart_proto_version_response *response; + struct gb_uart_proto_version_response response; int ret; - operation = gb_operation_create(tty->connection, - GB_UART_REQ_PROTOCOL_VERSION, - 0, sizeof(*response)); - if (!operation) - return -ENOMEM; - - /* Synchronous operation--no callback */ - ret = gb_operation_request_send(operation, NULL); - if (ret) { - pr_err("version operation failed (%d)\n", ret); - goto out; - } + ret = gb_operation_sync(tty->connection, + GB_UART_REQ_PROTOCOL_VERSION, + NULL, 0, &response, sizeof(response)); + if (ret) + return ret; - response = operation->response->payload; - if (response->major > GB_UART_VERSION_MAJOR) { + if (response.major > GB_UART_VERSION_MAJOR) { pr_err("unsupported major version (%hhu > %hhu)\n", - response->major, GB_UART_VERSION_MAJOR); - ret = -ENOTSUPP; - goto out; + response.major, GB_UART_VERSION_MAJOR); + return -ENOTSUPP; } - tty->version_major = response->major; - tty->version_minor = response->minor; + tty->version_major = response.major; + tty->version_minor = response.minor; pr_debug("%s: version_major = %u version_minor = %u\n", __func__, tty->version_major, tty->version_minor); -out: - gb_operation_destroy(operation); - - return ret; + return 0; } static int send_data(struct gb_tty *tty, u16 size, const u8 *data) { - struct gb_connection *connection = tty->connection; - struct gb_operation *operation; struct gb_uart_send_data_request *request; int retval; if (!data || !size) return 0; - operation = gb_operation_create(connection, GB_UART_REQ_SEND_DATA, - sizeof(*request) + size, 0); - if (!operation) + request = kmalloc(sizeof(*request) + size, GFP_KERNEL); + if (!request) return -ENOMEM; - request = operation->request->payload; + request->size = cpu_to_le16(size); memcpy(&request->data[0], data, size); + retval = gb_operation_sync(tty->connection, GB_UART_REQ_SEND_DATA, + request, sizeof(*request) + size, NULL, 0); - /* Synchronous operation--no callback */ - retval = gb_operation_request_send(operation, NULL); - if (retval) - dev_err(&connection->dev, - "send data operation failed (%d)\n", retval); - gb_operation_destroy(operation); - + kfree(request); return retval; } static int send_line_coding(struct gb_tty *tty, struct gb_serial_line_coding *line_coding) { - struct gb_connection *connection = tty->connection; - struct gb_operation *operation; - struct gb_uart_set_line_coding_request *request; - int retval; - - operation = gb_operation_create(connection, GB_UART_REQ_SET_LINE_CODING, - sizeof(*request), 0); - if (!operation) - return -ENOMEM; - request = operation->request->payload; - memcpy(&request->line_coding, line_coding, sizeof(*line_coding)); - - /* Synchronous operation--no callback */ - retval = gb_operation_request_send(operation, NULL); - if (retval) - dev_err(&connection->dev, - "send line coding operation failed (%d)\n", retval); - gb_operation_destroy(operation); + struct gb_uart_set_line_coding_request request; - return retval; + memcpy(&request.line_coding, line_coding, sizeof(*line_coding)); + return gb_operation_sync(tty->connection, GB_UART_REQ_SET_LINE_CODING, + &request, sizeof(request), NULL, 0); } static int send_control(struct gb_tty *tty, u16 control) { - struct gb_connection *connection = tty->connection; - struct gb_operation *operation; - struct gb_uart_set_control_line_state_request *request; - int retval; - - operation = gb_operation_create(connection, - GB_UART_REQ_SET_CONTROL_LINE_STATE, - sizeof(*request), 0); - if (!operation) - return -ENOMEM; - request = operation->request->payload; - request->control = cpu_to_le16(control); + struct gb_uart_set_control_line_state_request request; - /* Synchronous operation--no callback */ - retval = gb_operation_request_send(operation, NULL); - if (retval) - dev_err(&connection->dev, - "send control operation failed (%d)\n", retval); - gb_operation_destroy(operation); - - return retval; + request.control = cpu_to_le16(control); + return gb_operation_sync(tty->connection, + GB_UART_REQ_SET_CONTROL_LINE_STATE, + &request, sizeof(request), NULL, 0); } static int send_break(struct gb_tty *tty, u8 state) { - struct gb_connection *connection = tty->connection; - struct gb_operation *operation; - struct gb_uart_set_break_request *request; - int retval; + struct gb_uart_set_break_request request; if ((state != 0) && (state != 1)) { - dev_err(&connection->dev, "invalid break state of %d\n", state); + dev_err(&tty->connection->dev, + "invalid break state of %d\n", state); return -EINVAL; } - operation = gb_operation_create(connection, GB_UART_REQ_SET_BREAK, - sizeof(*request), 0); - if (!operation) - return -ENOMEM; - request = operation->request->payload; - request->state = state; - - /* Synchronous operation--no callback */ - retval = gb_operation_request_send(operation, NULL); - if (retval) - dev_err(&connection->dev, - "send break operation failed (%d)\n", retval); - gb_operation_destroy(operation); - - return retval; + request.state = state; + return gb_operation_sync(tty->connection, GB_UART_REQ_SET_BREAK, + &request, sizeof(request), NULL, 0); } -- cgit v0.10.2 From 7d5bbb173559328cdd63a729870baac69d3631f6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 23 Nov 2014 17:45:22 -0800 Subject: greybus: gpio-gb: convert to use gb_operation_sync This converts the GPIO protocol driver to use gb_operation_sync, removing lots of places where the create/send/destroy pattern was being used to send greybus messages. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index c6c85d8..09d77c1 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -116,337 +116,193 @@ struct gb_gpio_set_debounce_request { * This request only uses the connection field, and if successful, * fills in the major and minor protocol version of the target. */ -static int -gb_gpio_proto_version_operation(struct gb_gpio_controller *gb_gpio_controller) +static int gb_gpio_proto_version_operation(struct gb_gpio_controller *ggc) { - struct gb_connection *connection = gb_gpio_controller->connection; - struct gb_operation *operation; - struct gb_gpio_proto_version_response *response; + struct gb_gpio_proto_version_response response; int ret; - /* protocol version request has no payload */ - operation = gb_operation_create(connection, - GB_GPIO_TYPE_PROTOCOL_VERSION, - 0, sizeof(*response)); - if (!operation) - return -ENOMEM; - - /* Synchronous operation--no callback */ - ret = gb_operation_request_send(operation, NULL); - if (ret) { - pr_err("version operation failed (%d)\n", ret); - goto out; - } + ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_PROTOCOL_VERSION, + NULL, 0, &response, sizeof(response)); + if (ret) + return ret; - response = operation->response->payload; - if (response->major > GB_GPIO_VERSION_MAJOR) { + if (response.major > GB_GPIO_VERSION_MAJOR) { pr_err("unsupported major version (%hhu > %hhu)\n", - response->major, GB_GPIO_VERSION_MAJOR); - ret = -ENOTSUPP; - } else { - gb_gpio_controller->version_major = response->major; - gb_gpio_controller->version_minor = response->minor; + response.major, GB_GPIO_VERSION_MAJOR); + return -ENOTSUPP; } -out: - gb_operation_destroy(operation); - - return ret; + ggc->version_major = response.major; + ggc->version_minor = response.minor; + return 0; } -static int gb_gpio_line_count_operation(struct gb_gpio_controller *gb_gpio_controller) +static int gb_gpio_line_count_operation(struct gb_gpio_controller *ggc) { - struct gb_connection *connection = gb_gpio_controller->connection; - struct gb_operation *operation; - struct gb_gpio_line_count_response *response; + struct gb_gpio_line_count_response response; int ret; - /* line count request has no payload */ - operation = gb_operation_create(connection, - GB_GPIO_TYPE_LINE_COUNT, - 0, sizeof(*response)); - if (!operation) - return -ENOMEM; - - /* Synchronous operation--no callback */ - ret = gb_operation_request_send(operation, NULL); - if (ret) { - pr_err("line count operation failed (%d)\n", ret); - } else { - response = operation->response->payload; - gb_gpio_controller->line_max = response->count; - } - gb_operation_destroy(operation); - + ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_LINE_COUNT, + NULL, 0, &response, sizeof(response)); + if (!ret) + ggc->line_max = response.count; return ret; } -static int gb_gpio_activate_operation(struct gb_gpio_controller *gb_gpio_controller, - u8 which) +static int gb_gpio_activate_operation(struct gb_gpio_controller *ggc, u8 which) { - struct gb_connection *connection = gb_gpio_controller->connection; - struct gb_operation *operation; - struct gb_gpio_activate_request *request; + struct gb_gpio_activate_request request; int ret; - if (which > gb_gpio_controller->line_max) + if (which > ggc->line_max) return -EINVAL; - /* activate response has no payload */ - operation = gb_operation_create(connection, - GB_GPIO_TYPE_ACTIVATE, - sizeof(*request), 0); - if (!operation) - return -ENOMEM; - request = operation->request->payload; - request->which = which; - - /* Synchronous operation--no callback */ - ret = gb_operation_request_send(operation, NULL); - if (ret) - pr_err("activate operation failed (%d)\n", ret); - else - gb_gpio_controller->lines[which].active = true; - gb_operation_destroy(operation); - + request.which = which; + ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_ACTIVATE, + &request, sizeof(request), NULL, 0); + if (!ret) + ggc->lines[which].active = true; return ret; } -static int gb_gpio_deactivate_operation(struct gb_gpio_controller *gb_gpio_controller, +static int gb_gpio_deactivate_operation(struct gb_gpio_controller *ggc, u8 which) { - struct gb_connection *connection = gb_gpio_controller->connection; - struct gb_operation *operation; - struct gb_gpio_deactivate_request *request; + struct gb_gpio_deactivate_request request; int ret; - if (which > gb_gpio_controller->line_max) + if (which > ggc->line_max) return -EINVAL; - /* deactivate response has no payload */ - operation = gb_operation_create(connection, - GB_GPIO_TYPE_DEACTIVATE, - sizeof(*request), 0); - if (!operation) - return -ENOMEM; - request = operation->request->payload; - request->which = which; - - /* Synchronous operation--no callback */ - ret = gb_operation_request_send(operation, NULL); - if (ret) - pr_err("deactivate operation failed (%d)\n", ret); - else - gb_gpio_controller->lines[which].active = false; - gb_operation_destroy(operation); - + request.which = which; + ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DEACTIVATE, + &request, sizeof(request), NULL, 0); + if (!ret) + ggc->lines[which].active = false; return ret; } -static int gb_gpio_get_direction_operation(struct gb_gpio_controller *gb_gpio_controller, +static int gb_gpio_get_direction_operation(struct gb_gpio_controller *ggc, u8 which) { - struct gb_connection *connection = gb_gpio_controller->connection; - struct gb_operation *operation; - struct gb_gpio_get_direction_request *request; - struct gb_gpio_get_direction_response *response; + struct gb_gpio_get_direction_request request; + struct gb_gpio_get_direction_response response; int ret; u8 direction; - if (which > gb_gpio_controller->line_max) + if (which > ggc->line_max) return -EINVAL; - operation = gb_operation_create(connection, - GB_GPIO_TYPE_GET_DIRECTION, - sizeof(*request), sizeof(*response)); - if (!operation) - return -ENOMEM; - request = operation->request->payload; - request->which = which; - - /* Synchronous operation--no callback */ - ret = gb_operation_request_send(operation, NULL); - if (ret) { - pr_err("get direction operation failed (%d)\n", ret); - goto out; - } + request.which = which; + ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_GET_DIRECTION, + &request, sizeof(request), + &response, sizeof(response)); + if (ret) + return ret; - response = operation->response->payload; - direction = response->direction; + direction = response.direction; if (direction && direction != 1) pr_warn("gpio %u direction was %u (should be 0 or 1)\n", which, direction); - gb_gpio_controller->lines[which].direction = direction ? 1 : 0; -out: - gb_operation_destroy(operation); - - return ret; + ggc->lines[which].direction = direction ? 1 : 0; + return 0; } -static int gb_gpio_direction_in_operation(struct gb_gpio_controller *gb_gpio_controller, +static int gb_gpio_direction_in_operation(struct gb_gpio_controller *ggc, u8 which) { - struct gb_connection *connection = gb_gpio_controller->connection; - struct gb_operation *operation; - struct gb_gpio_direction_in_request *request; + struct gb_gpio_direction_in_request request; int ret; - if (which > gb_gpio_controller->line_max) + if (which > ggc->line_max) return -EINVAL; - /* direction_in response has no payload */ - operation = gb_operation_create(connection, - GB_GPIO_TYPE_DIRECTION_IN, - sizeof(*request), 0); - if (!operation) - return -ENOMEM; - request = operation->request->payload; - request->which = which; - - /* Synchronous operation--no callback */ - ret = gb_operation_request_send(operation, NULL); - if (ret) - pr_err("direction in operation failed (%d)\n", ret); - else - gb_gpio_controller->lines[which].direction = 1; - gb_operation_destroy(operation); - + request.which = which; + ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DIRECTION_IN, + &request, sizeof(request), NULL, 0); + if (!ret) + ggc->lines[which].direction = 1; return ret; } -static int gb_gpio_direction_out_operation(struct gb_gpio_controller *gb_gpio_controller, +static int gb_gpio_direction_out_operation(struct gb_gpio_controller *ggc, u8 which, bool value_high) { - struct gb_connection *connection = gb_gpio_controller->connection; - struct gb_operation *operation; - struct gb_gpio_direction_out_request *request; + struct gb_gpio_direction_out_request request; int ret; - if (which > gb_gpio_controller->line_max) + if (which > ggc->line_max) return -EINVAL; - /* direction_out response has no payload */ - operation = gb_operation_create(connection, - GB_GPIO_TYPE_DIRECTION_OUT, - sizeof(*request), 0); - if (!operation) - return -ENOMEM; - request = operation->request->payload; - request->which = which; - request->value = value_high ? 1 : 0; - - /* Synchronous operation--no callback */ - ret = gb_operation_request_send(operation, NULL); - if (ret) - pr_err("direction out operation failed (%d)\n", ret); - else - gb_gpio_controller->lines[which].direction = 0; - gb_operation_destroy(operation); - + request.which = which; + request.value = value_high ? 1 : 0; + ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DIRECTION_OUT, + &request, sizeof(request), NULL, 0); + if (!ret) + ggc->lines[which].direction = 0; return ret; } -static int gb_gpio_get_value_operation(struct gb_gpio_controller *gb_gpio_controller, +static int gb_gpio_get_value_operation(struct gb_gpio_controller *ggc, u8 which) { - struct gb_connection *connection = gb_gpio_controller->connection; - struct gb_operation *operation; - struct gb_gpio_get_value_request *request; - struct gb_gpio_get_value_response *response; + struct gb_gpio_get_value_request request; + struct gb_gpio_get_value_response response; int ret; u8 value; - if (which > gb_gpio_controller->line_max) + if (which > ggc->line_max) return -EINVAL; - operation = gb_operation_create(connection, - GB_GPIO_TYPE_GET_VALUE, - sizeof(*request), sizeof(*response)); - if (!operation) - return -ENOMEM; - request = operation->request->payload; - request->which = which; - - /* Synchronous operation--no callback */ - ret = gb_operation_request_send(operation, NULL); - if (ret) { - pr_err("get value operation failed (%d)\n", ret); - goto out; - } + request.which = which; + ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_GET_VALUE, + &request, sizeof(request), + &response, sizeof(response)); + if (ret) + return ret; - response = operation->response->payload; - value = response->value; + value = response.value; if (value && value != 1) pr_warn("gpio %u value was %u (should be 0 or 1)\n", which, value); - gb_gpio_controller->lines[which].value = value ? 1 : 0; -out: - gb_operation_destroy(operation); - - return ret; + ggc->lines[which].value = value ? 1 : 0; + return 0; } -static int gb_gpio_set_value_operation(struct gb_gpio_controller *gb_gpio_controller, +static int gb_gpio_set_value_operation(struct gb_gpio_controller *ggc, u8 which, bool value_high) { - struct gb_connection *connection = gb_gpio_controller->connection; - struct gb_operation *operation; - struct gb_gpio_set_value_request *request; + struct gb_gpio_set_value_request request; int ret; - if (which > gb_gpio_controller->line_max) + if (which > ggc->line_max) return -EINVAL; - /* set_value response has no payload */ - operation = gb_operation_create(connection, - GB_GPIO_TYPE_SET_VALUE, - sizeof(*request), 0); - if (!operation) - return -ENOMEM; - request = operation->request->payload; - request->which = which; - request->value = value_high ? 1 : 0; - - /* Synchronous operation--no callback */ - ret = gb_operation_request_send(operation, NULL); - if (ret) - pr_err("set value operation failed (%d)\n", ret); - else /* XXX should this set direction to out? */ - gb_gpio_controller->lines[which].value = request->value; - gb_operation_destroy(operation); - + request.which = which; + request.value = value_high ? 1 : 0; + ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_SET_VALUE, + &request, sizeof(request), NULL, 0); + if (!ret) { + /* XXX should this set direction to out? */ + ggc->lines[which].value = request.value; + } return ret; } -static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *gb_gpio_controller, +static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *ggc, u8 which, u16 debounce_usec) { - struct gb_connection *connection = gb_gpio_controller->connection; - struct gb_operation *operation; - struct gb_gpio_set_debounce_request *request; + struct gb_gpio_set_debounce_request request; int ret; - if (which > gb_gpio_controller->line_max) + if (which > ggc->line_max) return -EINVAL; - /* set_debounce response has no payload */ - operation = gb_operation_create(connection, - GB_GPIO_TYPE_SET_DEBOUNCE, - sizeof(*request), 0); - if (!operation) - return -ENOMEM; - request = operation->request->payload; - request->which = which; - request->usec = cpu_to_le16(debounce_usec); - - /* Synchronous operation--no callback */ - ret = gb_operation_request_send(operation, NULL); - if (ret) - pr_err("set debounce operation failed (%d)\n", ret); - else - gb_gpio_controller->lines[which].debounce_usec = - le16_to_cpu(request->usec); - gb_operation_destroy(operation); - + request.which = which; + request.usec = cpu_to_le16(debounce_usec); + ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_SET_DEBOUNCE, + &request, sizeof(request), NULL, 0); + if (!ret) + ggc->lines[which].debounce_usec = debounce_usec; return ret; } -- cgit v0.10.2 From 5a8b8314db138b9cc59f710a91b291cbe1486001 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 23 Nov 2014 17:45:23 -0800 Subject: greybus: i2c-gb: convert to use gb_operation_sync This converts the I2C protocol driver to use gb_operation_sync, removing lots of places where the create/send/destroy pattern was being used to send greybus messages. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index 6b2fd7e9..19a7df9 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -92,38 +92,23 @@ struct gb_i2c_transfer_response { */ static int gb_i2c_proto_version_operation(struct gb_i2c_device *gb_i2c_dev) { - struct gb_connection *connection = gb_i2c_dev->connection; - struct gb_operation *operation; - struct gb_i2c_proto_version_response *response; + struct gb_i2c_proto_version_response response; int ret; - /* A protocol version request has no payload */ - operation = gb_operation_create(connection, - GB_I2C_TYPE_PROTOCOL_VERSION, - 0, sizeof(*response)); - if (!operation) - return -ENOMEM; - - /* Synchronous operation--no callback */ - ret = gb_operation_request_send(operation, NULL); - if (ret) { - pr_err("version operation failed (%d)\n", ret); - goto out; - } + ret = gb_operation_sync(gb_i2c_dev->connection, + GB_I2C_TYPE_PROTOCOL_VERSION, + NULL, 0, &response, sizeof(response)); + if (ret) + return ret; - response = operation->response->payload; - if (response->major > GB_I2C_VERSION_MAJOR) { + if (response.major > GB_I2C_VERSION_MAJOR) { pr_err("unsupported major version (%hhu > %hhu)\n", - response->major, GB_I2C_VERSION_MAJOR); - ret = -ENOTSUPP; - goto out; + response.major, GB_I2C_VERSION_MAJOR); + return -ENOTSUPP; } - gb_i2c_dev->version_major = response->major; - gb_i2c_dev->version_minor = response->minor; -out: - gb_operation_destroy(operation); - - return ret; + gb_i2c_dev->version_major = response.major; + gb_i2c_dev->version_minor = response.minor; + return 0; } /* @@ -136,56 +121,34 @@ static u32 gb_i2c_functionality_map(u32 gb_i2c_functionality) static int gb_i2c_functionality_operation(struct gb_i2c_device *gb_i2c_dev) { - struct gb_connection *connection = gb_i2c_dev->connection; - struct gb_operation *operation; - struct gb_i2c_functionality_response *response; + struct gb_i2c_functionality_response response; u32 functionality; int ret; - /* A functionality request has no payload */ - operation = gb_operation_create(connection, - GB_I2C_TYPE_FUNCTIONALITY, - 0, sizeof(*response)); - if (!operation) - return -ENOMEM; - - /* Synchronous operation--no callback */ - ret = gb_operation_request_send(operation, NULL); - if (ret) { - pr_err("functionality operation failed (%d)\n", ret); - goto out; - } + ret = gb_operation_sync(gb_i2c_dev->connection, + GB_I2C_TYPE_FUNCTIONALITY, + NULL, 0, &response, sizeof(response)); + if (ret) + return ret; - response = operation->response->payload; - functionality = le32_to_cpu(response->functionality); + functionality = le32_to_cpu(response.functionality); gb_i2c_dev->functionality = gb_i2c_functionality_map(functionality); -out: - gb_operation_destroy(operation); - return ret; + return 0; } static int gb_i2c_timeout_operation(struct gb_i2c_device *gb_i2c_dev, u16 msec) { - struct gb_connection *connection = gb_i2c_dev->connection; - struct gb_operation *operation; - struct gb_i2c_timeout_request *request; + struct gb_i2c_timeout_request request; int ret; - operation = gb_operation_create(connection, GB_I2C_TYPE_TIMEOUT, - sizeof(*request), 0); - if (!operation) - return -ENOMEM; - request = operation->request->payload; - request->msec = cpu_to_le16(msec); - - /* Synchronous operation--no callback */ - ret = gb_operation_request_send(operation, NULL); + request.msec = cpu_to_le16(msec); + ret = gb_operation_sync(gb_i2c_dev->connection, GB_I2C_TYPE_TIMEOUT, + &request, sizeof(request), NULL, 0); if (ret) pr_err("timeout operation failed (%d)\n", ret); else gb_i2c_dev->timeout_msec = msec; - gb_operation_destroy(operation); return ret; } @@ -193,25 +156,16 @@ static int gb_i2c_timeout_operation(struct gb_i2c_device *gb_i2c_dev, u16 msec) static int gb_i2c_retries_operation(struct gb_i2c_device *gb_i2c_dev, u8 retries) { - struct gb_connection *connection = gb_i2c_dev->connection; - struct gb_operation *operation; - struct gb_i2c_retries_request *request; + struct gb_i2c_retries_request request; int ret; - operation = gb_operation_create(connection, GB_I2C_TYPE_RETRIES, - sizeof(*request), 0); - if (!operation) - return -ENOMEM; - request = operation->request->payload; - request->retries = retries; - - /* Synchronous operation--no callback */ - ret = gb_operation_request_send(operation, NULL); + request.retries = retries; + ret = gb_operation_sync(gb_i2c_dev->connection, GB_I2C_TYPE_RETRIES, + &request, sizeof(request), NULL, 0); if (ret) pr_err("retries operation failed (%d)\n", ret); else gb_i2c_dev->retries = retries; - gb_operation_destroy(operation); return ret; } -- cgit v0.10.2 From bf2329fd7d2795b9ce7146ca9e7092a7f507ce59 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 23 Nov 2014 17:45:24 -0800 Subject: greybus: pwm-gb: convert to use gb_operation_sync This converts the PWM protocol driver to use gb_operation_sync, removing lots of places where the create/send/destroy pattern was being used to send greybus messages. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/pwm-gb.c b/drivers/staging/greybus/pwm-gb.c index e146b24..bd1379f 100644 --- a/drivers/staging/greybus/pwm-gb.c +++ b/drivers/staging/greybus/pwm-gb.c @@ -85,234 +85,118 @@ struct gb_pwm_disable_request { */ static int gb_pwm_proto_version_operation(struct gb_pwm_chip *pwmc) { - struct gb_connection *connection = pwmc->connection; - struct gb_operation *operation; - struct gb_pwm_proto_version_response *response; + struct gb_pwm_proto_version_response response; int ret; - /* protocol version request has no payload */ - operation = gb_operation_create(connection, - GB_PWM_TYPE_PROTOCOL_VERSION, - 0, sizeof(*response)); - if (!operation) - return -ENOMEM; + ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_PROTOCOL_VERSION, + NULL, 0, &response, sizeof(response)); - /* Synchronous operation--no callback */ - ret = gb_operation_request_send(operation, NULL); - if (ret) { - pr_err("version operation failed (%d)\n", ret); - goto out; - } + if (ret) + return ret; - response = operation->response->payload; - if (response->major > GB_PWM_VERSION_MAJOR) { + if (response.major > GB_PWM_VERSION_MAJOR) { pr_err("unsupported major version (%hhu > %hhu)\n", - response->major, GB_PWM_VERSION_MAJOR); - ret = -ENOTSUPP; - goto out; + response.major, GB_PWM_VERSION_MAJOR); + return -ENOTSUPP; } - pwmc->version_major = response->major; - pwmc->version_minor = response->minor; -out: - gb_operation_destroy(operation); - - return ret; + pwmc->version_major = response.major; + pwmc->version_minor = response.minor; + return 0; } static int gb_pwm_count_operation(struct gb_pwm_chip *pwmc) { - struct gb_connection *connection = pwmc->connection; - struct gb_operation *operation; - struct gb_pwm_count_response *response; + struct gb_pwm_count_response response; int ret; - /* pwm count request has no payload */ - operation = gb_operation_create(connection, GB_PWM_TYPE_PWM_COUNT, - 0, sizeof(*response)); - if (!operation) - return -ENOMEM; - - /* Synchronous operation--no callback */ - ret = gb_operation_request_send(operation, NULL); - if (ret) { - pr_err("line count operation failed (%d)\n", ret); - } else { - response = operation->response->payload; - pwmc->pwm_max = response->count; - } - gb_operation_destroy(operation); - - return ret; + ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_PWM_COUNT, + NULL, 0, &response, sizeof(response)); + if (ret) + return ret; + pwmc->pwm_max = response.count; + return 0; } static int gb_pwm_activate_operation(struct gb_pwm_chip *pwmc, u8 which) { - struct gb_connection *connection = pwmc->connection; - struct gb_operation *operation; - struct gb_pwm_activate_request *request; - int ret; + struct gb_pwm_activate_request request; if (which > pwmc->pwm_max) return -EINVAL; - /* activate response has no payload */ - operation = gb_operation_create(connection, GB_PWM_TYPE_ACTIVATE, - sizeof(*request), 0); - if (!operation) - return -ENOMEM; - request = operation->request->payload; - request->which = which; - - /* Synchronous operation--no callback */ - ret = gb_operation_request_send(operation, NULL); - if (ret) - pr_err("activate operation failed (%d)\n", ret); - gb_operation_destroy(operation); - - return ret; + request.which = which; + return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_ACTIVATE, + &request, sizeof(request), NULL, 0); } static int gb_pwm_deactivate_operation(struct gb_pwm_chip *pwmc, u8 which) { - struct gb_connection *connection = pwmc->connection; - struct gb_operation *operation; - struct gb_pwm_deactivate_request *request; - int ret; + struct gb_pwm_deactivate_request request; if (which > pwmc->pwm_max) return -EINVAL; - /* deactivate response has no payload */ - operation = gb_operation_create(connection, GB_PWM_TYPE_DEACTIVATE, - sizeof(*request), 0); - if (!operation) - return -ENOMEM; - request = operation->request->payload; - request->which = which; - - /* Synchronous operation--no callback */ - ret = gb_operation_request_send(operation, NULL); - if (ret) - pr_err("deactivate operation failed (%d)\n", ret); - gb_operation_destroy(operation); - - return ret; + request.which = which; + return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_DEACTIVATE, + &request, sizeof(request), NULL, 0); } static int gb_pwm_config_operation(struct gb_pwm_chip *pwmc, u8 which, u32 duty, u32 period) { - struct gb_connection *connection = pwmc->connection; - struct gb_operation *operation; - struct gb_pwm_config_request *request; - int ret; + struct gb_pwm_config_request request; if (which > pwmc->pwm_max) return -EINVAL; - operation = gb_operation_create(connection, GB_PWM_TYPE_CONFIG, - sizeof(*request), 0); - if (!operation) - return -ENOMEM; - request = operation->request->payload; - request->which = which; - request->duty = duty; - request->period = period; - - /* Synchronous operation--no callback */ - ret = gb_operation_request_send(operation, NULL); - if (ret) - pr_err("config operation failed (%d)\n", ret); - gb_operation_destroy(operation); - - return ret; + request.which = which; + request.duty = duty; + request.period = period; + return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_CONFIG, + &request, sizeof(request), NULL, 0); } static int gb_pwm_set_polarity_operation(struct gb_pwm_chip *pwmc, u8 which, u8 polarity) { - struct gb_connection *connection = pwmc->connection; - struct gb_operation *operation; - struct gb_pwm_polarity_request *request; - int ret; + struct gb_pwm_polarity_request request; if (which > pwmc->pwm_max) return -EINVAL; - operation = gb_operation_create(connection, GB_PWM_TYPE_POLARITY, - sizeof(*request), 0); - if (!operation) - return -ENOMEM; - request = operation->request->payload; - request->which = which; - request->polarity = polarity; - - /* Synchronous operation--no callback */ - ret = gb_operation_request_send(operation, NULL); - if (ret) - pr_err("set polarity operation failed (%d)\n", ret); - gb_operation_destroy(operation); - - return ret; + request.which = which; + request.polarity = polarity; + return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_POLARITY, + &request, sizeof(request), NULL, 0); } static int gb_pwm_enable_operation(struct gb_pwm_chip *pwmc, u8 which) { - struct gb_connection *connection = pwmc->connection; - struct gb_operation *operation; - struct gb_pwm_enable_request *request; - int ret; + struct gb_pwm_enable_request request; if (which > pwmc->pwm_max) return -EINVAL; - /* enable response has no payload */ - operation = gb_operation_create(connection, GB_PWM_TYPE_ENABLE, - sizeof(*request), 0); - if (!operation) - return -ENOMEM; - request = operation->request->payload; - request->which = which; - - /* Synchronous operation--no callback */ - ret = gb_operation_request_send(operation, NULL); - if (ret) - pr_err("enable operation failed (%d)\n", ret); - gb_operation_destroy(operation); - - return ret; + request.which = which; + return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_ENABLE, + &request, sizeof(request), NULL, 0); } static int gb_pwm_disable_operation(struct gb_pwm_chip *pwmc, u8 which) { - struct gb_connection *connection = pwmc->connection; - struct gb_operation *operation; - struct gb_pwm_disable_request *request; - int ret; + struct gb_pwm_disable_request request; if (which > pwmc->pwm_max) return -EINVAL; - /* disable response has no payload */ - operation = gb_operation_create(connection, GB_PWM_TYPE_DISABLE, - sizeof(*request), 0); - if (!operation) - return -ENOMEM; - request = operation->request->payload; - request->which = which; - - /* Synchronous operation--no callback */ - ret = gb_operation_request_send(operation, NULL); - if (ret) - pr_err("disable operation failed (%d)\n", ret); - gb_operation_destroy(operation); - - return ret; + request.which = which; + return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_DISABLE, + &request, sizeof(request), NULL, 0); } static int gb_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) -- cgit v0.10.2 From ecc25a7f58d9be842f591800f13f932396fb72af Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 24 Nov 2014 09:25:24 +0530 Subject: greybus: es1-ap-usb: don't use 'es1' after it is freed greybus_remove_hd() will free memory allocated to 'es1' and so using it after the routine has returned isn't right. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index bab6f25..2047843 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -293,6 +293,7 @@ static int check_urb_status(struct urb *urb) static void ap_disconnect(struct usb_interface *interface) { struct es1_ap_dev *es1; + struct usb_device *udev; int i; es1 = usb_get_intfdata(interface); @@ -329,9 +330,10 @@ static void ap_disconnect(struct usb_interface *interface) es1->svc_buffer = NULL; usb_set_intfdata(interface, NULL); + udev = es1->usb_dev; greybus_remove_hd(es1->hd); - usb_put_dev(es1->usb_dev); + usb_put_dev(udev); } /* Callback for when we get a SVC message */ -- cgit v0.10.2 From 9f240f20caf93090d82949d59d467dcde341560b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 24 Nov 2014 13:52:25 -0800 Subject: greybus: uart-gb: clean up send_line_coding We always pass the same option to send_line_coding() for the line_coding structure, which is already in the struct gb_tty variable, so just remove the second parameter as it's not needed. This logic came from the cdc-acm.c driver, where it's also not needed anymore, I'll go fix up that later on when I get a chance. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 10d00b7..6432c64 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -180,12 +180,12 @@ static int send_data(struct gb_tty *tty, u16 size, const u8 *data) return retval; } -static int send_line_coding(struct gb_tty *tty, - struct gb_serial_line_coding *line_coding) +static int send_line_coding(struct gb_tty *tty) { struct gb_uart_set_line_coding_request request; - memcpy(&request.line_coding, line_coding, sizeof(*line_coding)); + memcpy(&request.line_coding, &tty->line_coding, + sizeof(tty->line_coding)); return gb_operation_sync(tty->connection, GB_UART_REQ_SET_LINE_CODING, &request, sizeof(request), NULL, 0); } @@ -384,7 +384,7 @@ static void gb_tty_set_termios(struct tty_struct *tty, if (memcpy(&gb_tty->line_coding, &newline, sizeof(newline))) { memcpy(&gb_tty->line_coding, &newline, sizeof(newline)); - send_line_coding(gb_tty, &gb_tty->line_coding); + send_line_coding(gb_tty); } } @@ -668,7 +668,7 @@ static int gb_uart_connection_init(struct gb_connection *connection) gb_tty->line_coding.format = GB_SERIAL_1_STOP_BITS; gb_tty->line_coding.parity = GB_SERIAL_NO_PARITY; gb_tty->line_coding.data = 8; - send_line_coding(gb_tty, &gb_tty->line_coding); + send_line_coding(gb_tty); tty_dev = tty_port_register_device(&gb_tty->port, gb_tty_driver, minor, &connection->dev); -- cgit v0.10.2 From ba986b5ab97f59669cc5d174a8a7359b8600e2e5 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 25 Nov 2014 11:33:13 -0600 Subject: greybus: encapsulate operation result access Hide the setting and getting of the operation result (stored in operation->errno) behind a pair of accessor functions. Only the operation core should be setting the result, but operations that complete asynchronously will need access to the result so expose the function that provides that. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 35fcb88..f42e6d2 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -66,6 +66,16 @@ struct gb_operation_msg_hdr { /* XXX Could be per-host device, per-module, or even per-connection */ static DEFINE_SPINLOCK(gb_operations_lock); +static void gb_operation_result_set(struct gb_operation *operation, int result) +{ + operation->errno = result; +} + +int gb_operation_result(struct gb_operation *operation) +{ + return operation->errno; +} + static void gb_pending_operation_insert(struct gb_operation *operation) { struct gb_connection *connection = operation->connection; @@ -164,7 +174,7 @@ static void gb_operation_request_handle(struct gb_operation *operation) gb_connection_err(operation->connection, "unexpected incoming request type 0x%02hhx\n", header->type); - operation->errno = -EPROTONOSUPPORT; + gb_operation_result_set(operation, -EPROTONOSUPPORT); } #endif @@ -424,11 +434,12 @@ static void gb_operation_sync_callback(struct gb_operation *operation) * any payload so the request message is ready to go. If non-null, * the callback function supplied will be called when the response * message has arrived indicating the operation is complete. In - * that case, the callback function is responsible for extracting - * the result of the operation from operation->errno if desired, - * and dropping the final reference to the operation. A null - * callback function is used for a synchronous request; return from - * this function won't occur until the operation is complete. + * that case, the callback function is responsible for fetching the + * result of the operation using gb_operation_result() if desired, + * and dropping the final reference to (i.e., destroying) the + * operation. A null callback function is used for a synchronous + * request; in that case return from this function won't occur until + * the operation is complete. */ int gb_operation_request_send(struct gb_operation *operation, gb_operation_callback callback) @@ -470,7 +481,7 @@ int gb_operation_request_send(struct gb_operation *operation, if (ret < 0) gb_operation_cancel(operation, -EINTR); - return operation->errno; + return gb_operation_result(operation); } /* @@ -501,7 +512,7 @@ greybus_data_sent(struct greybus_host_device *hd, void *header, int status) /* XXX Right now we assume we're an outgoing request */ message = gb_hd_message_find(hd, header); operation = message->operation; - operation->errno = status; + gb_operation_result_set(operation, status); queue_work(gb_operation_workqueue, &operation->work); } EXPORT_SYMBOL_GPL(greybus_data_sent); @@ -527,7 +538,7 @@ void gb_connection_recv_request(struct gb_connection *connection, memcpy(operation->request->header, data, size); /* XXX Right now this will just complete the operation */ - operation->errno = -ENOSYS; + gb_operation_result_set(operation, -ENOSYS); queue_work(gb_operation_workqueue, &operation->work); } @@ -571,7 +582,7 @@ static void gb_connection_recv_response(struct gb_connection *connection, memcpy(message->header, data, size); /* The rest will be handled in work queue context */ - operation->errno = result; + gb_operation_result_set(operation, result); queue_work(gb_operation_workqueue, &operation->work); } @@ -619,7 +630,7 @@ void gb_connection_recv(struct gb_connection *connection, */ void gb_operation_cancel(struct gb_operation *operation, int errno) { - operation->errno = errno; + gb_operation_result_set(operation, errno); gb_message_cancel(operation->request); gb_message_cancel(operation->response); } diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index bc5c164..7f835d2 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -84,6 +84,8 @@ struct gb_operation { void gb_connection_recv(struct gb_connection *connection, void *data, size_t size); +int gb_operation_result(struct gb_operation *operation); + struct gb_operation *gb_operation_create(struct gb_connection *connection, u8 type, size_t request_size, size_t response_size); -- cgit v0.10.2 From abe9a3006fd95d34e69617b65824613e503b9b77 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 25 Nov 2014 11:33:14 -0600 Subject: greybus: first operation error prevails If an operation already has an error result recorded, don't overwrite it with a new error code. In order to ensure a request completes exactly once, return a Boolean indicating whether setting the result was successful. If two threads are racing to complete an operation (for example if a slow-but-normal response message arrives at the same time timeout processing commences) only the one that sets the final result will finish its activity. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index f42e6d2..49b0f19 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -66,9 +66,12 @@ struct gb_operation_msg_hdr { /* XXX Could be per-host device, per-module, or even per-connection */ static DEFINE_SPINLOCK(gb_operations_lock); -static void gb_operation_result_set(struct gb_operation *operation, int result) +static bool gb_operation_result_set(struct gb_operation *operation, int result) { + if (operation->errno) + return false; operation->errno = result; + return true; } int gb_operation_result(struct gb_operation *operation) @@ -174,7 +177,7 @@ static void gb_operation_request_handle(struct gb_operation *operation) gb_connection_err(operation->connection, "unexpected incoming request type 0x%02hhx\n", header->type); - gb_operation_result_set(operation, -EPROTONOSUPPORT); + (void)gb_operation_result_set(operation, -EPROTONOSUPPORT); } #endif @@ -512,8 +515,8 @@ greybus_data_sent(struct greybus_host_device *hd, void *header, int status) /* XXX Right now we assume we're an outgoing request */ message = gb_hd_message_find(hd, header); operation = message->operation; - gb_operation_result_set(operation, status); - queue_work(gb_operation_workqueue, &operation->work); + if (gb_operation_result_set(operation, status)) + queue_work(gb_operation_workqueue, &operation->work); } EXPORT_SYMBOL_GPL(greybus_data_sent); @@ -538,8 +541,8 @@ void gb_connection_recv_request(struct gb_connection *connection, memcpy(operation->request->header, data, size); /* XXX Right now this will just complete the operation */ - gb_operation_result_set(operation, -ENOSYS); - queue_work(gb_operation_workqueue, &operation->work); + if (gb_operation_result_set(operation, -ENOSYS)) + queue_work(gb_operation_workqueue, &operation->work); } /* @@ -582,8 +585,8 @@ static void gb_connection_recv_response(struct gb_connection *connection, memcpy(message->header, data, size); /* The rest will be handled in work queue context */ - gb_operation_result_set(operation, result); - queue_work(gb_operation_workqueue, &operation->work); + if (gb_operation_result_set(operation, result)) + queue_work(gb_operation_workqueue, &operation->work); } /* @@ -630,9 +633,10 @@ void gb_connection_recv(struct gb_connection *connection, */ void gb_operation_cancel(struct gb_operation *operation, int errno) { - gb_operation_result_set(operation, errno); - gb_message_cancel(operation->request); - gb_message_cancel(operation->response); + if (gb_operation_result_set(operation, errno)) { + gb_message_cancel(operation->request); + gb_message_cancel(operation->response); + } } /** -- cgit v0.10.2 From 3deb37d4ad04c6cb18564f5af2c88c10fa6bfc76 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 25 Nov 2014 11:33:15 -0600 Subject: greybus: use special operation result valus This is more or less re-implementing this commit: 96f95d4 greybus: update gbuf status for completion handlers But this time we're doing this for an operation, not the gbuf. Define an initial operation result value (-EBADR) to signify that no valid result has been set. Nobody should ever set that value after the operation is initially created. Since only the operation core code sets the result, an attempt to set -EBADR would be a bug. Define another known operation result value (-EINPROGRESS) for an outgoing operation whose request has been sent but whose response has not yet been successfully received. This should the first (non-initial) result value set, and it should happen exactly once. Any other attempt to set this value once set would be a bug. Finally, once the request message is in flight, the result value will be set exactly once more, to indicate the final result of the operation. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 49b0f19..82fd7e9 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -66,17 +66,43 @@ struct gb_operation_msg_hdr { /* XXX Could be per-host device, per-module, or even per-connection */ static DEFINE_SPINLOCK(gb_operations_lock); +/* + * Set an operation's result. Initially an outgoing operation's + * errno value is -EBADR. If no error occurs before sending the + * request message the only valid value operation->errno can be + * set to is -EINPROGRESS, indicating the request has been (or + * rather is about to be) sent. At that point nobody should + * be looking at the result until the reponse arrives. + * + * The first time the result gets set after the request has been + * sent, that result "sticks." That is, if two concurrent threads + * race to set the result, the first one wins. The return value + * tells the caller whether its result was recorded; if not the + * has nothing more to do. + */ static bool gb_operation_result_set(struct gb_operation *operation, int result) { - if (operation->errno) + if (WARN_ON(result == -EBADR)) + return false; + + if (result == -EINPROGRESS) { + if (WARN_ON(operation->errno != -EBADR)) + return false; + } else if (operation->errno != -EINPROGRESS) { return false; + } operation->errno = result; + return true; } int gb_operation_result(struct gb_operation *operation) { - return operation->errno; + int result = operation->errno; + + WARN_ON(result == -EINPROGRESS); + + return result; } static void gb_pending_operation_insert(struct gb_operation *operation) @@ -350,6 +376,7 @@ gb_operation_create_common(struct gb_connection *connection, bool outgoing, goto err_request; operation->response->operation = operation; } + operation->errno = -EBADR; /* Initial value--means "never set" */ INIT_WORK(&operation->work, gb_operation_work); operation->callback = NULL; /* set at submit time */ @@ -475,6 +502,7 @@ int gb_operation_request_send(struct gb_operation *operation, schedule_delayed_work(&operation->timeout_work, timeout); /* All set, send the request */ + gb_operation_result_set(operation, -EINPROGRESS); ret = gb_message_send(operation->request, GFP_KERNEL); if (ret || callback) return ret; -- cgit v0.10.2 From 1a365154c24a3fd48b96ad25cb67a483124d56ad Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 25 Nov 2014 13:06:44 -0600 Subject: greybus: fix some error codes Change the message result values used in two cases. First, use -EMSGSIZE rather than -E2BIG to represent a message that is larger than the buffer intended to hold it. That is the proper code for this situation. Second, use -ECANCELED rather than -EINTR for an operation that has been canceled. The definition of that error is literally "Operation Canceled" so it seems like the right thing to do. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 82fd7e9..5e5c097 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -324,7 +324,7 @@ int gb_operation_status_map(u8 status) case GB_OP_PROTOCOL_BAD: return -EPROTONOSUPPORT; case GB_OP_OVERFLOW: - return -E2BIG; + return -EMSGSIZE; case GB_OP_TIMEOUT: return -ETIMEDOUT; default: @@ -510,7 +510,7 @@ int gb_operation_request_send(struct gb_operation *operation, /* Cancel the operation if interrupted */ ret = wait_for_completion_interruptible(&operation->completion); if (ret < 0) - gb_operation_cancel(operation, -EINTR); + gb_operation_cancel(operation, -ECANCELED); return gb_operation_result(operation); } @@ -605,7 +605,7 @@ static void gb_connection_recv_response(struct gb_connection *connection, result = gb_operation_status_map(header->result); } else { gb_connection_err(connection, "recv buffer too small"); - result = -E2BIG; + result = -EMSGSIZE; } /* We must ignore the payload if a bad status is returned */ -- cgit v0.10.2 From aa3a4d12093b818ac2b9fe3e0454ae0090201254 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 25 Nov 2014 13:06:45 -0600 Subject: greybus: enforce receive buffer size When an operation is created its receive buffer size is specified. In all current cases, the size supplied for the receive buffer is exactly the size that should be returned. In other words, if any fewer than that many bytes arrived in a response, it would be an error. So tighten the check on the number of bytes arriving for a response message, ensuring that the number of bytes received is *exactly the same* as the number of bytes available (rather than just less than). We'll expand our interpretation of of -EMSGSIZE to mean "wrong message size" rather than just "message too long." If we someday encounter an actual case where we want to be able to successfully receive something less than the full receive buffer we can adjust the code to handle that (and give it a way to tell the receiver how many bytes are present). Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 5e5c097..c3864bd 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -599,12 +599,13 @@ static void gb_connection_recv_response(struct gb_connection *connection, gb_pending_operation_remove(operation); message = operation->response; - if (size <= message->size) { + if (size == message->size) { /* Transfer the operation result from the response header */ header = message->header; result = gb_operation_status_map(header->result); } else { - gb_connection_err(connection, "recv buffer too small"); + gb_connection_err(connection, "bad message size (%zu != %zu)", + size, message->size); result = -EMSGSIZE; } -- cgit v0.10.2 From 894cbc31360102fe51babdb82be69885f317843b Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 25 Nov 2014 16:54:02 -0600 Subject: greybus: update operation result atomically An operation result can be set both in and out of interrupt context. For example, a response message could be arriving at the same time a timeout of the operation is getting processed. We therefore need to ensure the result is accessed atomically. Protect updates to the errno field using the operations spinlock. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index c3864bd..b4ef820 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -82,18 +82,32 @@ static DEFINE_SPINLOCK(gb_operations_lock); */ static bool gb_operation_result_set(struct gb_operation *operation, int result) { + int prev; + + /* Nobody should be setting -EBADR */ if (WARN_ON(result == -EBADR)) return false; + /* Are we sending the request message? */ if (result == -EINPROGRESS) { - if (WARN_ON(operation->errno != -EBADR)) - return false; - } else if (operation->errno != -EINPROGRESS) { - return false; + /* Yes, but verify the result has not already been set */ + spin_lock_irq(&gb_operations_lock); + prev = operation->errno; + if (prev == -EBADR) + operation->errno = result; + spin_unlock_irq(&gb_operations_lock); + + return !WARN_ON(prev != -EBADR); } - operation->errno = result; - return true; + /* Trying to set final status; only the first one succeeds */ + spin_lock_irq(&gb_operations_lock); + prev = operation->errno; + if (prev == -EINPROGRESS) + operation->errno = result; + spin_unlock_irq(&gb_operations_lock); + + return prev == -EINPROGRESS; } int gb_operation_result(struct gb_operation *operation) -- cgit v0.10.2 From f34541d7e823bff1be8e0d497e01dcbaf9c65edb Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 25 Nov 2014 16:54:03 -0600 Subject: greybus: ignore a null cookie when canceling buffer It's possible for an in-flight buffer to be recorded as sent *after* a thread has begin the process of canceling it. In that case the Greybus message cookie will be set to NULL, and that value can end up getting passed to buffer_cancel(). Change buffer_cancel() so it properly handles (ignores) a null cookie pointer. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 2047843..1832d0f 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -245,16 +245,22 @@ static void *buffer_send(struct greybus_host_device *hd, u16 dest_cport_id, return conceal_urb(urb); } +/* + * The cookie value supplied is the value that buffer_send() + * returned to its caller. It identifies the buffer that should be + * canceled. This function must also handle (which is to say, + * ignore) a null cookie value. + */ static void buffer_cancel(void *cookie) { - struct urb *urb = reveal_urb(cookie); /* * We really should be defensive and track all outstanding * (sent) buffers rather than trusting the cookie provided * is valid. For the time being, this will do. */ - usb_kill_urb(urb); + if (cookie) + usb_kill_urb(reveal_urb(cookie)); } static struct greybus_host_driver es1_driver = { -- cgit v0.10.2 From 43cdae5c3cbc000146cccbbfc651105feba9525e Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 25 Nov 2014 16:54:04 -0600 Subject: greybus: protect cookie with a mutex When a Greybus message is sent, the host driver supplies a cookie for Greybus to use to identify the sent message in the event it needs to be canceled. The cookie will be non-null while the message is in flight, and a null pointer otherwise. There are two problems with this, which arise out of the fact that a message can be canceled at any time--even concurrent with it getting sent (such as when Greybus is getting shut down). First, the host driver's buffer_send method can return an error value, which is non-null but not a valid cookie. So we need to ensure such a bogus cookie is never used to cancel a message. Second, we can't resolve that problem by assigning message->cookie only after we've determined it's not an error. The instant buffer_send() returns, the message may well be in flight and *should* be canceled at shutdown, so we need the cookie value to reflect that. In order to avoid these problems, protect access to a message's cookie value with a mutex. A spin lock can't be used because the window that needs protecting covers code that can block. We reset the cookie value to NULL as soon as the host driver has notified us it has been sent (or failed to). Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index b4ef820..226565d 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -32,6 +32,9 @@ static struct kmem_cache *gb_operation_cache; /* Workqueue to handle Greybus operation completions. */ static struct workqueue_struct *gb_operation_workqueue; +/* Protects the cookie representing whether a message is in flight */ +static DEFINE_MUTEX(gb_message_mutex); + /* * All operation messages (both requests and responses) begin with * a header that encodes the size of the data (header included). @@ -170,16 +173,20 @@ static int gb_message_send(struct gb_message *message, gfp_t gfp_mask) struct gb_connection *connection = message->operation->connection; u16 dest_cport_id = connection->interface_cport_id; int ret = 0; + void *cookie; - message->cookie = connection->hd->driver->buffer_send(connection->hd, + mutex_lock(&gb_message_mutex); + cookie = connection->hd->driver->buffer_send(connection->hd, dest_cport_id, message->header, message->size, gfp_mask); - if (IS_ERR(message->cookie)) { - ret = PTR_ERR(message->cookie); - message->cookie = NULL; - } + if (IS_ERR(cookie)) + ret = PTR_ERR(cookie); + else + message->cookie = cookie; + mutex_unlock(&gb_message_mutex); + return ret; } @@ -189,13 +196,14 @@ static int gb_message_send(struct gb_message *message, gfp_t gfp_mask) */ static void gb_message_cancel(struct gb_message *message) { - struct greybus_host_device *hd; - - if (!message->cookie) - return; /* Don't bother if the message isn't in flight */ + mutex_lock(&gb_message_mutex); + if (message->cookie) { + struct greybus_host_device *hd; - hd = message->operation->connection->hd; - hd->driver->buffer_cancel(message->cookie); + hd = message->operation->connection->hd; + hd->driver->buffer_cancel(message->cookie); + } + mutex_unlock(&gb_message_mutex); } #if 0 @@ -550,12 +558,16 @@ greybus_data_sent(struct greybus_host_device *hd, void *header, int status) struct gb_message *message; struct gb_operation *operation; - /* If there's no error, there's really nothing to do */ + /* XXX Right now we assume we're an outgoing request */ + message = gb_hd_message_find(hd, header); + + /* Record that the message is no longer in flight */ + message->cookie = NULL; + + /* If there's no error, there's really nothing more to do */ if (!status) return; /* Mark it complete? */ - /* XXX Right now we assume we're an outgoing request */ - message = gb_hd_message_find(hd, header); operation = message->operation; if (gb_operation_result_set(operation, status)) queue_work(gb_operation_workqueue, &operation->work); -- cgit v0.10.2 From 615772aace9c87bdcae038cea37c69c85373dba4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 25 Nov 2014 16:59:21 -0800 Subject: greybus: usb-gb: import a "buildable" version of the usb-gb.c driver Based on Fabien's original driver, this version is converted (mostly) to the new greybus operation apis. Lots of things still to do, not the least being hooking up proper responses... Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 81174b9..4fa9b3f 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -14,7 +14,8 @@ greybus-y := core.o \ sdio-gb.o \ uart-gb.o \ battery-gb.o \ - vibrator-gb.o + vibrator-gb.o \ + usb-gb.o obj-m += greybus.o obj-m += es1-ap-usb.o diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index 55ef387..31ba172 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -193,11 +193,16 @@ bool gb_protocol_init(void) pr_err("error initializing vibrator protocol\n"); ret = false; } + if (!gb_usb_protocol_init()) { + pr_err("error initializing usb protocol\n"); + ret = false; + } return ret; } void gb_protocol_exit(void) { + gb_usb_protocol_exit(); gb_vibrator_protocol_exit(); gb_sdio_protocol_exit(); gb_uart_protocol_exit(); diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index 69a4007..0ced63e 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -67,6 +67,9 @@ extern void gb_sdio_protocol_exit(void); extern bool gb_vibrator_protocol_init(void); extern void gb_vibrator_protocol_exit(void); +extern bool gb_usb_protocol_init(void); +extern void gb_usb_protocol_exit(void); + bool gb_protocol_init(void); void gb_protocol_exit(void); diff --git a/drivers/staging/greybus/usb-gb.c b/drivers/staging/greybus/usb-gb.c new file mode 100644 index 0000000..ab4e093 --- /dev/null +++ b/drivers/staging/greybus/usb-gb.c @@ -0,0 +1,393 @@ +/* + * USB host driver for the Greybus "generic" USB module. + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + * + */ +#include +#include +#include +#include +#include + +#include "greybus.h" + +/* Version of the Greybus USB protocol we support */ +#define GB_USB_VERSION_MAJOR 0x00 +#define GB_USB_VERSION_MINOR 0x01 + +/* Greybus USB request types */ +#define GB_USB_TYPE_INVALID 0x00 +#define GB_USB_TYPE_PROTOCOL_VERSION 0x01 +#define GB_USB_TYPE_HCD_STOP 0x02 +#define GB_USB_TYPE_HCD_START 0x03 +#define GB_USB_TYPE_URB_ENQUEUE 0x04 +#define GB_USB_TYPE_URB_DEQUEUE 0x05 +#define GB_USB_TYPE_ENDPOINT_DISABLE 0x06 +#define GB_USB_TYPE_HUB_CONTROL 0x07 +#define GB_USB_TYPE_GET_FRAME_NUMBER 0x08 +#define GB_USB_TYPE_HUB_STATUS_DATA 0x09 + +struct gb_usb_proto_version_response { + __u8 major; + __u8 minor; +}; + +struct gb_usb_urb_enqueue_request { + __le32 pipe; + __le32 transfer_flags; + __le32 transfer_buffer_length; + __le32 maxpacket; + __le32 interval; + __le64 hcpriv_ep; + __le32 number_of_packets; + u8 setup_packet[8]; + u8 payload[0]; +}; + +struct gb_usb_urb_dequeue_request { + __le64 hcpriv_ep; +}; + +struct gb_usb_endpoint_disable_request { + __le64 hcpriv; +}; + +struct gb_usb_hub_control_request { + __le16 typeReq; + __le16 wValue; + __le16 wIndex; + __le16 wLength; +}; + +struct gb_usb_hub_control_response { + u8 buf[0]; +}; + +struct gb_usb_header { + __le16 size; + __le16 id; + __u8 type; +}; + +struct gb_usb_hub_status { + __le32 status; + __le16 buf_size; + u8 buf[0]; +}; + +static struct gb_usb_hub_status *hub_status; // FIXME!!! +static DEFINE_SPINLOCK(hub_status_lock); +static atomic_t frame_number; // FIXME!!! + +struct gb_usb_device { + struct gb_connection *connection; + + struct usb_hcd *hcd; + u8 version_major; + u8 version_minor; +}; + +#define to_gb_usb_device(d) ((struct gb_usb_device*) d->hcd_priv) + +static int get_version(struct gb_usb_device *dev) +{ + struct gb_usb_proto_version_response response; + int ret; + + ret = gb_operation_sync(dev->connection, + GB_USB_TYPE_PROTOCOL_VERSION, + NULL, 0, &response, sizeof(response)); + if (ret) + return ret; + + if (response.major > GB_USB_VERSION_MAJOR) { + pr_err("unsupported major version (%hhu > %hhu)\n", + response.major, GB_USB_VERSION_MAJOR); + return -ENOTSUPP; + } + dev->version_major = response.major; + dev->version_minor = response.minor; + return 0; +} + +static void hcd_stop(struct usb_hcd *hcd) +{ + struct gb_usb_device *dev = to_gb_usb_device(hcd); + int ret; + + ret = gb_operation_sync(dev->connection, GB_USB_TYPE_HCD_STOP, + NULL, 0, NULL, 0); + if (ret) + dev_err(&dev->connection->dev, "HCD stop failed '%d'\n", ret); +} + +static int hcd_start(struct usb_hcd *hcd) +{ + struct usb_bus *bus = hcd_to_bus(hcd); + struct gb_usb_device *dev = to_gb_usb_device(hcd); + int ret; + + ret = gb_operation_sync(dev->connection, GB_USB_TYPE_HCD_START, + NULL, 0, NULL, 0); + if (ret) { + dev_err(&dev->connection->dev, "HCD start failed '%d'\n", ret); + return ret; + } + + hcd->state = HC_STATE_RUNNING; + if (bus->root_hub) + usb_hcd_resume_root_hub(hcd); + return 0; +} + +static int urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) +{ + struct gb_usb_device *dev = to_gb_usb_device(hcd); + struct gb_usb_urb_enqueue_request *request; + struct gb_operation *operation; + int ret; + + operation = gb_operation_create(dev->connection, + GB_USB_TYPE_URB_ENQUEUE, + sizeof(*request) + + urb->transfer_buffer_length, 0); + if (!operation) + return -ENODEV; + + request = operation->request->payload; + request->pipe = cpu_to_le32(urb->pipe); + request->transfer_flags = cpu_to_le32(urb->transfer_flags); + request->transfer_buffer_length = cpu_to_le32(urb->transfer_buffer_length); + request->interval = cpu_to_le32(urb->interval); + request->hcpriv_ep = cpu_to_le64(urb->ep->hcpriv); + request->number_of_packets = cpu_to_le32(urb->number_of_packets); + + memcpy(request->setup_packet, urb->setup_packet, 8); + memcpy(&request->payload, urb->transfer_buffer, + urb->transfer_buffer_length); + + ret = gb_operation_request_send(operation, NULL); + gb_operation_destroy(operation); + + return ret; +} + +static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) +{ + struct gb_usb_device *dev = to_gb_usb_device(hcd); + struct gb_usb_urb_dequeue_request request; + int ret; + + urb->ep->hcpriv = NULL; + request.hcpriv_ep = cpu_to_le64(urb->hcpriv); + ret = gb_operation_sync(dev->connection, GB_USB_TYPE_URB_DEQUEUE, + &request, sizeof(request), NULL, 0); + urb->hcpriv = NULL; + return ret; +} + +static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep) +{ + struct gb_usb_device *dev = to_gb_usb_device(hcd); + struct gb_usb_endpoint_disable_request request; + int ret; + + request.hcpriv = cpu_to_le64(ep->hcpriv); + ret = gb_operation_sync(dev->connection, GB_USB_TYPE_ENDPOINT_DISABLE, + &request, sizeof(request), NULL, 0); + ep->hcpriv = NULL; +} + +static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) +{ +} + +static int get_frame_number(struct usb_hcd *hcd) +{ + return atomic_read(&frame_number); +} + +static int hub_status_data(struct usb_hcd *hcd, char *buf) +{ + int retval; + unsigned long flags; + + spin_lock_irqsave(&hub_status_lock, flags); + memcpy(buf, hub_status->buf, le16_to_cpu(hub_status->buf_size)); + retval = le32_to_cpu(hub_status->status); + spin_unlock_irqrestore(&hub_status_lock, flags); + + return retval; +} + +static int hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, + char *buf, u16 wLength) +{ + struct gb_usb_hub_control_request request; + struct gb_usb_device *dev = to_gb_usb_device(hcd); + int ret; + + request.typeReq = cpu_to_le16(typeReq); + request.wValue = cpu_to_le16(wValue); + request.wIndex = cpu_to_le16(wIndex); + request.wLength = cpu_to_le16(wLength); + + // FIXME - buf needs to come back in struct gb_usb_hub_control_response + // for some types of requests, depending on typeReq. Do we do this in a + // "generic" way, or only ask for a response for the ones we "know" need + // a response (a small subset of all valid typeReq, thankfully.) + ret = gb_operation_sync(dev->connection, GB_USB_TYPE_HUB_CONTROL, + &request, sizeof(request), NULL, 0); + + return ret; +} + +static struct hc_driver usb_gb_hc_driver = { + .description = "greybus_usb", + .product_desc = "GB-Bridge USB Controller", /* TODO: Get this from GPB ?*/ + .flags = HCD_MEMORY | HCD_USB2, /* FIXME: Get this from GPB */ + .hcd_priv_size = sizeof(struct gb_usb_device), + + .start = hcd_start, + .stop = hcd_stop, + .urb_enqueue = urb_enqueue, + .urb_dequeue = urb_dequeue, + .endpoint_disable = endpoint_disable, + .endpoint_reset = endpoint_reset, + .get_frame_number = get_frame_number, + .hub_status_data = hub_status_data, + .hub_control = hub_control, +}; + +#if 0 +static inline void gb_usb_handle_get_frame_number(struct gbuf *gbuf) +{ + __le32 frame_num; + const size_t packet_size = sizeof(struct gb_usb_header) + + sizeof(frame_num); + struct gb_usb_header* hdr = gbuf->transfer_buffer; + + if (le16_to_cpu(hdr->size) != packet_size) { + pr_err("%s(): dropping packet too small\n", __func__); + return; + } + + frame_num = (__le32) ((char*) gbuf->transfer_buffer + + sizeof(struct gb_usb_header)); + atomic_set(&frame_number, le32_to_cpu(frame_num)); +} + +static inline void gb_usb_handle_hubs_status_data(struct gbuf *gbuf) +{ + struct gb_usb_hub_status *new_hubstatus, *hubstatus; + struct gb_usb_header* hdr = gbuf->transfer_buffer; + const size_t min_packet_size = sizeof(struct gb_usb_header) + + sizeof(struct gb_usb_hub_status); + unsigned long flags; + + if (le16_to_cpu(hdr->size) < min_packet_size) { + pr_err("%s(): dropping packet too small\n", __func__); + return; + } + + hubstatus = (struct gb_usb_hub_status*) ((char*) gbuf->transfer_buffer + + sizeof(struct gb_usb_header)); + + if (le16_to_cpu(hdr->size) != min_packet_size + hubstatus->buf_size) { + pr_err("%s(): invalid packet size, dropping packet\n", + __func__); + return; + } + + new_hubstatus = kmalloc(hubstatus->buf_size, GFP_KERNEL); + memcpy(&new_hubstatus, hubstatus, hubstatus->buf_size); + + spin_lock_irqsave(&hub_status_lock, flags); + hubstatus = hub_status; + hub_status = new_hubstatus; + spin_unlock_irqrestore(&hub_status_lock, flags); + + kfree(hubstatus); +} + +static void gb_usb_in_handler(struct gbuf *gbuf) +{ + struct gb_usb_header* hdr = gbuf->transfer_buffer; + + switch (hdr->type) { + case GB_USB_TYPE_GET_FRAME_NUMBER: + gb_usb_handle_get_frame_number(gbuf); + break; + + case GB_USB_TYPE_HUB_STATUS_DATA: + gb_usb_handle_hubs_status_data(gbuf); + break; + } +} +#endif + +static int gb_usb_connection_init(struct gb_connection *connection) +{ + struct device *dev = &connection->dev; + struct gb_usb_device *gb_usb_dev; + + int retval; + + gb_usb_dev = kzalloc(sizeof(*gb_usb_dev), GFP_KERNEL); + if (!gb_usb_dev) + return -ENOMEM; + + gb_usb_dev->connection = connection; + + /* Check for compatible protocol version */ + retval = get_version(gb_usb_dev); + if (retval) + goto error_create_hcd; + + gb_usb_dev->hcd = usb_create_hcd(&usb_gb_hc_driver, dev, dev_name(dev)); + if (!gb_usb_dev->hcd) { + retval = -ENODEV; + goto error_create_hcd; + } + + gb_usb_dev->hcd->has_tt = 1; + gb_usb_dev->hcd->hcd_priv[0] = (unsigned long) gb_usb_dev; + + retval = usb_add_hcd(gb_usb_dev->hcd, 0, 0); + if (retval) + goto error_add_hcd; + + return 0; +error_add_hcd: + usb_put_hcd(gb_usb_dev->hcd); +error_create_hcd: + kfree(gb_usb_dev); + return retval; +} + +static void gb_usb_connection_exit(struct gb_connection *connection) +{ + // FIXME - tear everything down! +} + +static struct gb_protocol usb_protocol = { + .id = GREYBUS_PROTOCOL_USB, + .major = 0, + .minor = 1, + .connection_init = gb_usb_connection_init, + .connection_exit = gb_usb_connection_exit, + .request_recv = NULL, /* FIXME we have requests!!! */ +}; + +bool gb_usb_protocol_init(void) +{ + return gb_protocol_register(&usb_protocol); +} + +void gb_usb_protocol_exit(void) +{ + gb_protocol_deregister(&usb_protocol); +} -- cgit v0.10.2 From 94b15d7613e861563b9f06fac2c273ca8e2fc269 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 1 Dec 2014 07:53:06 -0600 Subject: greybus: use outgoing flag when creating operation In gb_operation_create_common(), a zero response size is still being used to determine whether to use GFP_KERNEL or GFP_ATOMIC when allocating a message. Use the value of the "outgoing" parameter to decide this instead. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 226565d..7617410 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -377,7 +377,7 @@ gb_operation_create_common(struct gb_connection *connection, bool outgoing, { struct greybus_host_device *hd = connection->hd; struct gb_operation *operation; - gfp_t gfp_flags = response_size ? GFP_KERNEL : GFP_ATOMIC; + gfp_t gfp_flags = outgoing ? GFP_KERNEL : GFP_ATOMIC; operation = kmem_cache_zalloc(gb_operation_cache, gfp_flags); if (!operation) -- cgit v0.10.2 From ab3cf8dc7db6755d216173b04043b0e0cd24415b Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 1 Dec 2014 07:53:07 -0600 Subject: greybus: enforce max representable message size We represent the size of a message using a 16-bit field. It's possible for a host driver to advertise a maximum message size that's bigger than that. If that happens, reduce the host device's maximum buffer size to the maximum we can represent the first time a message is allocated. This information is actually only used by the Greybus code, but because we're modifying a value that's "owned" by the host driver, issue a warning when this limit is being imposed Ensure (at build time) that our own definition is sane as well. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 7617410..8a023cb 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -299,6 +299,12 @@ gb_operation_message_alloc(struct greybus_host_device *hd, u8 type, size_t size; u8 *buffer; + if (hd->buffer_size_max > GB_OPERATION_MESSAGE_SIZE_MAX) { + pr_warn("limiting buffer size to %u\n", + GB_OPERATION_MESSAGE_SIZE_MAX); + hd->buffer_size_max = GB_OPERATION_MESSAGE_SIZE_MAX; + } + if (message_size > hd->buffer_size_max) return NULL; @@ -750,6 +756,9 @@ int gb_operation_sync(struct gb_connection *connection, int type, int gb_operation_init(void) { + BUILD_BUG_ON(GB_OPERATION_MESSAGE_SIZE_MAX > + U16_MAX - sizeof(struct gb_operation_msg_hdr)); + gb_operation_cache = kmem_cache_create("gb_operation_cache", sizeof(struct gb_operation), 0, 0, NULL); if (!gb_operation_cache) -- cgit v0.10.2 From 2fb2d2a73f27bdd90a86d14c143e000e95d3c9d2 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 1 Dec 2014 07:53:08 -0600 Subject: greybus: define -EILSEQ to mean implementation error Reserve operation result code -EILSEQ to represent that the code that implements an operation is broken. This is used (initially) for any attempt to set the result to -EBADR (which is reserved for an operation in initial state), or for an attempt to set the result of an operation that is *not* in initial state to -EINPROGRESS. Note that we still use -EIO gb_operation_status_map() to represent a gb_operation_result value that isn't recognized. In gb_operation_result(), warn if operation->errno is -EBADR. That is another value that indicates the operation is not in a state where it's valid to query an operation's result. Update a bunch of comments above gb_operation_result_set() to explain constraints on operation->errno. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 8a023cb..905c6de 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -70,44 +70,70 @@ struct gb_operation_msg_hdr { static DEFINE_SPINLOCK(gb_operations_lock); /* - * Set an operation's result. Initially an outgoing operation's - * errno value is -EBADR. If no error occurs before sending the - * request message the only valid value operation->errno can be - * set to is -EINPROGRESS, indicating the request has been (or - * rather is about to be) sent. At that point nobody should - * be looking at the result until the reponse arrives. + * Set an operation's result. + * + * Initially an outgoing operation's errno value is -EBADR. + * If no error occurs before sending the request message the only + * valid value operation->errno can be set to is -EINPROGRESS, + * indicating the request has been (or rather is about to be) sent. + * At that point nobody should be looking at the result until the + * reponse arrives. * * The first time the result gets set after the request has been * sent, that result "sticks." That is, if two concurrent threads * race to set the result, the first one wins. The return value * tells the caller whether its result was recorded; if not the - * has nothing more to do. + * caller has nothing more to do. + * + * The result value -EILSEQ is reserved to signal an implementation + * error; if it's ever observed, the code performing the request has + * done something fundamentally wrong. It is an error to try to set + * the result to -EBADR, and attempts to do so result in a warning, + * and -EILSEQ is used instead. Similarly, the only valid result + * value to set for an operation in initial state is -EINPROGRESS. + * Attempts to do otherwise will also record a (successful) -EILSEQ + * operation result. */ static bool gb_operation_result_set(struct gb_operation *operation, int result) { int prev; - /* Nobody should be setting -EBADR */ - if (WARN_ON(result == -EBADR)) - return false; - - /* Are we sending the request message? */ if (result == -EINPROGRESS) { - /* Yes, but verify the result has not already been set */ + /* + * -EINPROGRESS is used to indicate the request is + * in flight. It should be the first result value + * set after the initial -EBADR. Issue a warning + * and record an implementation error if it's + * set at any other time. + */ spin_lock_irq(&gb_operations_lock); prev = operation->errno; if (prev == -EBADR) operation->errno = result; + else + operation->errno = -EILSEQ; spin_unlock_irq(&gb_operations_lock); + WARN_ON(prev != -EBADR); - return !WARN_ON(prev != -EBADR); + return true; } - /* Trying to set final status; only the first one succeeds */ + /* + * The first result value set after a request has been sent + * will be the final result of the operation. Subsequent + * attempts to set the result are ignored. + * + * Note that -EBADR is a reserved "initial state" result + * value. Attempts to set this value result in a warning, + * and the result code is set to -EILSEQ instead. + */ + if (WARN_ON(result == -EBADR)) + result = -EILSEQ; /* Nobody should be setting -EBADR */ + spin_lock_irq(&gb_operations_lock); prev = operation->errno; if (prev == -EINPROGRESS) - operation->errno = result; + operation->errno = result; /* First and final result */ spin_unlock_irq(&gb_operations_lock); return prev == -EINPROGRESS; @@ -117,6 +143,7 @@ int gb_operation_result(struct gb_operation *operation) { int result = operation->errno; + WARN_ON(result == -EBADR); WARN_ON(result == -EINPROGRESS); return result; -- cgit v0.10.2 From 57248face3894f0b3e97ff1c9e9e8b8b22033ec3 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 1 Dec 2014 07:53:09 -0600 Subject: greybus: renumber operation result values Define a new operation status GB_OP_MALFUNCTION, which will be used to represent that something unexpected happened while handling an operation. This is intended as an indication similar to a BUG() call--whatever went wrong should *never* happen and because it's unexpected we need to treat it as a fatal error. Define another new operation status GB_OP_UNKNOWN_ERROR, which will represent the case where an operation ended in error, but the error was not recognized to be properly represented by one of the other status values. Renumber the operation status values, defining those that are produced by core operations code ahead of those that are more likely to come from operation handlers. Represent the values in hexadecimal to emphasize that they must be represented with 8 bits. The Use 0xff for GB_OP_MALFUNCTION instead of GB_OP_TIMEOUT; the latter is special, but a malfunction is in a class by itself. Reorder the cases in gb_operation_status_map() to match their numeric order. Map GB_OP_UNKNOWN_ERROR to -EIO in gb_operation_status_map(). Map GB_OP_MALFUNCTION to -EILSEQ in gb_operation_status_map(), since that value is used to represent an implementation error. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 905c6de..0841ab2 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -368,20 +368,23 @@ int gb_operation_status_map(u8 status) switch (status) { case GB_OP_SUCCESS: return 0; - case GB_OP_INVALID: - return -EINVAL; - case GB_OP_NO_MEMORY: - return -ENOMEM; case GB_OP_INTERRUPTED: return -EINTR; - case GB_OP_RETRY: - return -EAGAIN; + case GB_OP_TIMEOUT: + return -ETIMEDOUT; + case GB_OP_NO_MEMORY: + return -ENOMEM; case GB_OP_PROTOCOL_BAD: return -EPROTONOSUPPORT; case GB_OP_OVERFLOW: return -EMSGSIZE; - case GB_OP_TIMEOUT: - return -ETIMEDOUT; + case GB_OP_INVALID: + return -EINVAL; + case GB_OP_RETRY: + return -EAGAIN; + case GB_OP_MALFUNCTION: + return -EILSEQ; + case GB_OP_UNKNOWN_ERROR: default: return -EIO; } diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 7f835d2..feff823 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -14,14 +14,16 @@ struct gb_operation; enum gb_operation_result { - GB_OP_SUCCESS = 0, - GB_OP_INVALID = 1, - GB_OP_NO_MEMORY = 2, - GB_OP_INTERRUPTED = 3, - GB_OP_RETRY = 4, - GB_OP_PROTOCOL_BAD = 5, - GB_OP_OVERFLOW = 6, - GB_OP_TIMEOUT = 0xff, + GB_OP_SUCCESS = 0x00, + GB_OP_INTERRUPTED = 0x01, + GB_OP_TIMEOUT = 0x02, + GB_OP_NO_MEMORY = 0x03, + GB_OP_PROTOCOL_BAD = 0x04, + GB_OP_OVERFLOW = 0x05, + GB_OP_INVALID = 0x06, + GB_OP_RETRY = 0x07, + GB_OP_UNKNOWN_ERROR = 0xfe, + GB_OP_MALFUNCTION = 0xff, }; struct gb_message { -- cgit v0.10.2 From e413614b01763a84940168f253426fca89cdc38c Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 1 Dec 2014 07:53:10 -0600 Subject: greybus: drop gfp_mask from gb_message_send() We will only send messages from process context. Drop the gfp_mask parameter from gb_message_send(), and just supply GFP_KERNEL to the host driver's buffer_send method. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 0841ab2..75900d3 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -195,7 +195,7 @@ gb_pending_operation_find(struct gb_connection *connection, u16 operation_id) return found ? operation : NULL; } -static int gb_message_send(struct gb_message *message, gfp_t gfp_mask) +static int gb_message_send(struct gb_message *message) { struct gb_connection *connection = message->operation->connection; u16 dest_cport_id = connection->interface_cport_id; @@ -207,7 +207,7 @@ static int gb_message_send(struct gb_message *message, gfp_t gfp_mask) dest_cport_id, message->header, message->size, - gfp_mask); + GFP_KERNEL); if (IS_ERR(cookie)) ret = PTR_ERR(cookie); else @@ -561,7 +561,7 @@ int gb_operation_request_send(struct gb_operation *operation, /* All set, send the request */ gb_operation_result_set(operation, -EINPROGRESS); - ret = gb_message_send(operation->request, GFP_KERNEL); + ret = gb_message_send(operation->request); if (ret || callback) return ret; -- cgit v0.10.2 From e5fbc07360f1ed9da423abc2ab96a12f2d7a7632 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 1 Dec 2014 07:53:11 -0600 Subject: greybus: always drop reference in gb_operation_work() Currently we issue a warning in gb_operation_work() if an operation has no callback function defined. But we return without dropping the reference to the operation as we should. Stop warning if there's no callback, call it only if it's defined, and always drop the operation reference before returning. This means we're now treating a NULL callback pointer as a normal condition. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 75900d3..aaac037 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -265,11 +265,10 @@ static void gb_operation_work(struct work_struct *work) struct gb_operation *operation; operation = container_of(work, struct gb_operation, work); - if (WARN_ON(!operation->callback)) - return; - - operation->callback(operation); - operation->callback = NULL; + if (operation->callback) { + operation->callback(operation); + operation->callback = NULL; + } gb_operation_put(operation); } -- cgit v0.10.2 From 85a0442893444c044c0dde979c0372d7369ab45f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 1 Dec 2014 20:42:20 -0800 Subject: greybus: operation: fix up sparse warning gb_connection_recv_request should be static, so mark it as such. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index aaac037..d973b57 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -616,8 +616,9 @@ EXPORT_SYMBOL_GPL(greybus_data_sent); * This is called in interrupt context, so just copy the incoming * data into the request buffer and handle the rest via workqueue. */ -void gb_connection_recv_request(struct gb_connection *connection, - u16 operation_id, u8 type, void *data, size_t size) +static void gb_connection_recv_request(struct gb_connection *connection, + u16 operation_id, u8 type, void *data, + size_t size) { struct gb_operation *operation; -- cgit v0.10.2 From 34db1f91e674ba8c7df674ac6692c2604ea1ece5 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 2 Dec 2014 08:30:28 -0600 Subject: greybus: move copy of incoming request data Currently incoming request data is copied into a request message buffer in gb_connection_recv_request(). Move that--along with the assignment of the message id--into gb_operation_create_incoming(). Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index d973b57..1e0ce7d 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -465,11 +465,19 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, static struct gb_operation * gb_operation_create_incoming(struct gb_connection *connection, - u8 type, size_t request_size, - size_t response_size) + u16 operation_id, u8 type, + void *data, size_t request_size) { - return gb_operation_create_common(connection, false, type, - request_size, response_size); + struct gb_operation *operation; + + operation = gb_operation_create_common(connection, false, type, + request_size, 0); + if (operation) { + operation->id = operation_id; + memcpy(operation->request->header, data, request_size); + } + + return operation; } /* @@ -622,13 +630,12 @@ static void gb_connection_recv_request(struct gb_connection *connection, { struct gb_operation *operation; - operation = gb_operation_create_incoming(connection, type, size, 0); + operation = gb_operation_create_incoming(connection, operation_id, + type, data, size); if (!operation) { gb_connection_err(connection, "can't create operation"); return; /* XXX Respond with pre-allocated ENOMEM */ } - operation->id = operation_id; - memcpy(operation->request->header, data, size); /* XXX Right now this will just complete the operation */ if (gb_operation_result_set(operation, -ENOSYS)) -- cgit v0.10.2 From f71e1cc1944d0a82aff032acd9bb25dff5187d37 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 2 Dec 2014 08:30:29 -0600 Subject: greybus: short message is OK for errors We enforce a rule that a response message must completely fill the buffer that's been allocated to hold it. However, if an error occurs, the payload is off limits, so we should allow a short message to convey an error result. Change gb_connection_recv_response() to require the right message size only if there's no error. One other thing: The arriving data is only being copied into the response buffer if the request was successful. That means the response message header is assumed to have been initialized. That isn't a valid assumption. So change it so that if an error is seen, the header portion of the message is copied into the response buffer--but only the header. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 1e0ce7d..2fd60cc 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -655,7 +655,6 @@ static void gb_connection_recv_response(struct gb_connection *connection, { struct gb_operation *operation; struct gb_message *message; - struct gb_operation_msg_hdr *header; int result; operation = gb_pending_operation_find(connection, operation_id); @@ -668,19 +667,17 @@ static void gb_connection_recv_response(struct gb_connection *connection, gb_pending_operation_remove(operation); message = operation->response; - if (size == message->size) { - /* Transfer the operation result from the response header */ - header = message->header; - result = gb_operation_status_map(header->result); - } else { + result = gb_operation_status_map(message->header->result); + if (!result && size != message->size) { gb_connection_err(connection, "bad message size (%zu != %zu)", size, message->size); result = -EMSGSIZE; } /* We must ignore the payload if a bad status is returned */ - if (!result) - memcpy(message->header, data, size); + if (result) + size = sizeof(*message->header); + memcpy(message->header, data, size); /* The rest will be handled in work queue context */ if (gb_operation_result_set(operation, result)) -- cgit v0.10.2 From 64ce39a3463776a6ccf6770f588a265bca2468ca Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 2 Dec 2014 08:30:30 -0600 Subject: greybus: pass result in gb_connection_recv_response() Pass the operation result to gb_connection_recv_response() as a parameter. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 2fd60cc..c4898f6 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -651,11 +651,11 @@ static void gb_connection_recv_request(struct gb_connection *connection, * data into the response buffer and handle the rest via workqueue. */ static void gb_connection_recv_response(struct gb_connection *connection, - u16 operation_id, void *data, size_t size) + u16 operation_id, u8 result, void *data, size_t size) { struct gb_operation *operation; struct gb_message *message; - int result; + int errno = gb_operation_status_map(result); operation = gb_pending_operation_find(connection, operation_id); if (!operation) { @@ -667,20 +667,19 @@ static void gb_connection_recv_response(struct gb_connection *connection, gb_pending_operation_remove(operation); message = operation->response; - result = gb_operation_status_map(message->header->result); - if (!result && size != message->size) { + if (!errno && size != message->size) { gb_connection_err(connection, "bad message size (%zu != %zu)", size, message->size); - result = -EMSGSIZE; + errno = -EMSGSIZE; } /* We must ignore the payload if a bad status is returned */ - if (result) + if (errno) size = sizeof(*message->header); memcpy(message->header, data, size); /* The rest will be handled in work queue context */ - if (gb_operation_result_set(operation, result)) + if (gb_operation_result_set(operation, errno)) queue_work(gb_operation_workqueue, &operation->work); } @@ -717,7 +716,7 @@ void gb_connection_recv(struct gb_connection *connection, operation_id = le16_to_cpu(header->operation_id); if (header->type & GB_OPERATION_TYPE_RESPONSE) gb_connection_recv_response(connection, operation_id, - data, msg_size); + header->result, data, msg_size); else gb_connection_recv_request(connection, operation_id, header->type, data, msg_size); -- cgit v0.10.2 From 55f66a88dbd718c2133ac759eee4ff51f516bf45 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 2 Dec 2014 08:30:31 -0600 Subject: greybus: enforce non-zero operation type requirement The operation type 0x00 is reserved as an explicitly invalid operation type in all protocols. Enforce this. Add a check for callers who erroneously have the RESPONSE message type flag set in the operation type passed in gb_operation_create(). Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index c4898f6..53fffb1 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -455,10 +455,23 @@ err_cache: return NULL; } +/* + * Create a new operation associated with the given connection. The + * request and response sizes provided are the number of bytes + * required to hold the request/response payload only. Both of + * these are allowed to be 0. Note that 0x00 is reserved as an + * invalid operation type for all protocols, and this is enforced + * here. + */ struct gb_operation *gb_operation_create(struct gb_connection *connection, u8 type, size_t request_size, size_t response_size) { + if (WARN_ON_ONCE(!type)) + return NULL; + if (WARN_ON_ONCE(type & GB_OPERATION_TYPE_RESPONSE)) + type &= ~GB_OPERATION_TYPE_RESPONSE; + return gb_operation_create_common(connection, true, type, request_size, response_size); } -- cgit v0.10.2 From ea64cd9a5e83605bdb6374b48d3aa84f0d08abde Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 2 Dec 2014 08:30:32 -0600 Subject: greybus: use operation type 0 to signal incoming data When incoming data is going to be handled as a request, we create a new operation whose request buffer will hold the received data. There is no need to initialize the message header in such a request buffer because it will be immediately overwritten. Use operation type value of 0x00 in gb_operation_create_common() to signal that we are creating an incoming operation, and therefore do not need to initialize the request message header. This allows us to get rid of the Boolean "outgoing" parameter. As a result, we can stop supplying the "type" parameter to both gb_operation_create_incoming() and gb_connection_recv_request(). Update the header comments for gb_operation_message_alloc() and gb_operation_create_common(). Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 53fffb1..f474e8f 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -302,12 +302,14 @@ gb_hd_message_find(struct greybus_host_device *hd, void *header) } /* - * Allocate a message to be used for an operation request or - * response. For outgoing messages, both types of message contain a - * common header, which is filled in here. Incoming requests or - * responses also contain the same header, but there's no need to - * initialize it here (it'll be overwritten by the incoming - * message). + * Allocate a message to be used for an operation request or response. + * Both types of message contain a common header. The request message + * for an outgoing operation is outbound, as is the response message + * for an incoming operation. The message header for an outbound + * message is partially initialized here. + * + * The headers for inbound messages don't need to be initialized; + * they'll be filled in by arriving data. * * Our message structure consists of: * message structure @@ -341,15 +343,31 @@ gb_operation_message_alloc(struct greybus_host_device *hd, u8 type, buffer = &message->buffer[0]; header = (struct gb_operation_msg_hdr *)(buffer + hd->buffer_headroom); - /* Fill in the header structure */ - header->size = cpu_to_le16(message_size); - header->operation_id = 0; /* Filled in when submitted */ - header->type = type; - message->header = header; message->payload = header + 1; message->size = message_size; + /* + * The type supplied for incoming message buffers will be + * 0x00. Such buffers will be overwritten by arriving data + * so there's no need to initialize the message header. + */ + if (type) { + /* + * For a request, the operation id gets filled in + * when the message is sent. For a response, it + * will be copied from the request by the caller. + * + * The result field in a request message must be + * zero. It will be set just prior to sending for + * a response. + */ + header->size = cpu_to_le16(message_size); + header->operation_id = 0; + header->type = type; + header->result = 0; + } + return message; } @@ -392,27 +410,32 @@ int gb_operation_status_map(u8 status) /* * Create a Greybus operation to be sent over the given connection. * The request buffer will be big enough for a payload of the given - * size. Outgoing requests must specify the size of the response - * buffer size, which must be sufficient to hold all expected - * response data. + * size. + * + * For outgoing requests, the request message's header will be + * initialized with the type of the request and the message size. + * Outgoing operations must also specify the response buffer size, + * which must be sufficient to hold all expected response data. The + * response message header will eventually be overwritten, so there's + * no need to initialize it here. * - * Incoming requests will supply a response size of 0, and in that - * case no response buffer is allocated. (A response always - * includes a status byte, so 0 is not a valid size.) Whatever - * handles the operation request is responsible for allocating the - * response buffer. + * Request messages for incoming operations can arrive in interrupt + * context, so they must be allocated with GFP_ATOMIC. In this case + * the request buffer will be immediately overwritten, so there is + * no need to initialize the message header. Responsibility for + * allocating a response buffer lies with the incoming request + * handler for a protocol. So we don't allocate that here. * * Returns a pointer to the new operation or a null pointer if an * error occurs. */ static struct gb_operation * -gb_operation_create_common(struct gb_connection *connection, bool outgoing, - u8 type, size_t request_size, - size_t response_size) +gb_operation_create_common(struct gb_connection *connection, u8 type, + size_t request_size, size_t response_size) { struct greybus_host_device *hd = connection->hd; struct gb_operation *operation; - gfp_t gfp_flags = outgoing ? GFP_KERNEL : GFP_ATOMIC; + gfp_t gfp_flags = type ? GFP_KERNEL : GFP_ATOMIC; operation = kmem_cache_zalloc(gb_operation_cache, gfp_flags); if (!operation) @@ -425,7 +448,8 @@ gb_operation_create_common(struct gb_connection *connection, bool outgoing, goto err_cache; operation->request->operation = operation; - if (outgoing) { + /* Allocate the response buffer for outgoing operations */ + if (type) { type |= GB_OPERATION_TYPE_RESPONSE; operation->response = gb_operation_message_alloc(hd, type, response_size, GFP_KERNEL); @@ -472,21 +496,19 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, if (WARN_ON_ONCE(type & GB_OPERATION_TYPE_RESPONSE)) type &= ~GB_OPERATION_TYPE_RESPONSE; - return gb_operation_create_common(connection, true, type, + return gb_operation_create_common(connection, type, request_size, response_size); } static struct gb_operation * -gb_operation_create_incoming(struct gb_connection *connection, - u16 operation_id, u8 type, +gb_operation_create_incoming(struct gb_connection *connection, u16 id, void *data, size_t request_size) { struct gb_operation *operation; - operation = gb_operation_create_common(connection, false, type, - request_size, 0); + operation = gb_operation_create_common(connection, 0, request_size, 0); if (operation) { - operation->id = operation_id; + operation->id = id; memcpy(operation->request->header, data, request_size); } @@ -638,13 +660,13 @@ EXPORT_SYMBOL_GPL(greybus_data_sent); * data into the request buffer and handle the rest via workqueue. */ static void gb_connection_recv_request(struct gb_connection *connection, - u16 operation_id, u8 type, void *data, + u16 operation_id, void *data, size_t size) { struct gb_operation *operation; operation = gb_operation_create_incoming(connection, operation_id, - type, data, size); + data, size); if (!operation) { gb_connection_err(connection, "can't create operation"); return; /* XXX Respond with pre-allocated ENOMEM */ @@ -732,7 +754,7 @@ void gb_connection_recv(struct gb_connection *connection, header->result, data, msg_size); else gb_connection_recv_request(connection, operation_id, - header->type, data, msg_size); + data, msg_size); } /* -- cgit v0.10.2 From dc779229b538f1b5cd5d20a5afdfdfb4c83e5429 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 2 Dec 2014 08:30:33 -0600 Subject: greybus: introduce gb_operation_message_init() Separate the allocation of a message structure from its basic initialization. This will allow very common fixed-size operation response buffers to be allocated from a slab cache. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index f474e8f..d335bd2 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -301,6 +301,43 @@ gb_hd_message_find(struct greybus_host_device *hd, void *header) return message; } +static void gb_operation_message_init(struct greybus_host_device *hd, + struct gb_message *message, u16 operation_id, + size_t message_size, u8 type) +{ + struct gb_operation_msg_hdr *header; + u8 *buffer; + + BUG_ON(message_size < sizeof(*header)); + buffer = &message->buffer[0]; + header = (struct gb_operation_msg_hdr *)(buffer + hd->buffer_headroom); + + message->header = header; + message->payload = header + 1; + message->size = message_size; + + /* + * The type supplied for incoming message buffers will be + * 0x00. Such buffers will be overwritten by arriving data + * so there's no need to initialize the message header. + */ + if (type) { + /* + * For a request, the operation id gets filled in + * when the message is sent. For a response, it + * will be copied from the request by the caller. + * + * The result field in a request message must be + * zero. It will be set just prior to sending for + * a response. + */ + header->size = cpu_to_le16(message_size); + header->operation_id = 0; + header->type = type; + header->result = 0; + } +} + /* * Allocate a message to be used for an operation request or response. * Both types of message contain a common header. The request message @@ -325,7 +362,6 @@ gb_operation_message_alloc(struct greybus_host_device *hd, u8 type, struct gb_operation_msg_hdr *header; size_t message_size = payload_size + sizeof(*header); size_t size; - u8 *buffer; if (hd->buffer_size_max > GB_OPERATION_MESSAGE_SIZE_MAX) { pr_warn("limiting buffer size to %u\n", @@ -340,33 +376,9 @@ gb_operation_message_alloc(struct greybus_host_device *hd, u8 type, message = kzalloc(size, gfp_flags); if (!message) return NULL; - buffer = &message->buffer[0]; - header = (struct gb_operation_msg_hdr *)(buffer + hd->buffer_headroom); - message->header = header; - message->payload = header + 1; - message->size = message_size; - - /* - * The type supplied for incoming message buffers will be - * 0x00. Such buffers will be overwritten by arriving data - * so there's no need to initialize the message header. - */ - if (type) { - /* - * For a request, the operation id gets filled in - * when the message is sent. For a response, it - * will be copied from the request by the caller. - * - * The result field in a request message must be - * zero. It will be set just prior to sending for - * a response. - */ - header->size = cpu_to_le16(message_size); - header->operation_id = 0; - header->type = type; - header->result = 0; - } + /* Initialize the message. Operation id is filled in later. */ + gb_operation_message_init(hd, message, 0, message_size, type); return message; } -- cgit v0.10.2 From 835fb5e4985de46aafb7fbcf975663d375e7b4b4 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 2 Dec 2014 08:30:34 -0600 Subject: greybus: enforce a buffer headroom maximum size Define a maximum size that a host device can use for its private area ahead of the payload space used by Greybus in a message buffer. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 1832d0f..f551907 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -127,6 +127,7 @@ static void hd_buffer_constraints(struct greybus_host_device *hd) */ hd->buffer_headroom = sizeof(u32); /* For cport id */ hd->buffer_size_max = ES1_GBUF_MSG_SIZE_MAX; + BUILD_BUG_ON(hd->buffer_headroom > GB_BUFFER_HEADROOM_MAX); } #define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 8fda37c..11f4e55 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -69,6 +69,14 @@ struct greybus_host_device; struct svc_msg; +/* + * When the Greybus code allocates a buffer it sets aside bytes + * prior to the beginning of the payload area for the host device's + * exclusive use. The size is specified by hd->buffer_headroom, and + * which can't be greater than GB_BUFFER_HEADROOM_MAX. + */ +#define GB_BUFFER_HEADROOM_MAX sizeof(u64) + /* Buffers allocated from the host driver will be aligned to this multiple */ #define GB_BUFFER_ALIGN sizeof(u32) -- cgit v0.10.2 From 0cffcac3051fa1447d8a452ab5e0029bbe100777 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 2 Dec 2014 08:30:35 -0600 Subject: greybus: create a slab cache for simple messages A large number of request and response message types have no payload. Such "simple" messages have a known, fixed maximum size, so we can preallocate and use a pool (slab cache) of them. Here are two benefits to doing this: - There can be (small) performance and memory utilization benefits to using a slab cache. - Error responses can be sent with no payload; the cache is likely to have a free entry to use for an error response even in a low memory situation. The plan here is that an incoming request handler that has no response payload to fill will not need to allocate a response message. If no message has been allocated when a response is to be sent, one will be allocated from the cache by the core code. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index d335bd2..2a6f361 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -28,6 +28,7 @@ #define GB_OPERATION_MESSAGE_SIZE_MAX 4096 static struct kmem_cache *gb_operation_cache; +static struct kmem_cache *gb_simple_message_cache; /* Workqueue to handle Greybus operation completions. */ static struct workqueue_struct *gb_operation_workqueue; @@ -369,11 +370,19 @@ gb_operation_message_alloc(struct greybus_host_device *hd, u8 type, hd->buffer_size_max = GB_OPERATION_MESSAGE_SIZE_MAX; } - if (message_size > hd->buffer_size_max) - return NULL; + /* Allocate the message. Use the slab cache for simple messages */ + if (payload_size) { + if (message_size > hd->buffer_size_max) { + pr_warn("requested message size too big (%zu > %zu)\n", + message_size, hd->buffer_size_max); + return NULL; + } - size = sizeof(*message) + hd->buffer_headroom + message_size; - message = kzalloc(size, gfp_flags); + size = sizeof(*message) + hd->buffer_headroom + message_size; + message = kzalloc(size, gfp_flags); + } else { + message = kmem_cache_zalloc(gb_simple_message_cache, gfp_flags); + } if (!message) return NULL; @@ -385,7 +394,10 @@ gb_operation_message_alloc(struct greybus_host_device *hd, u8 type, static void gb_operation_message_free(struct gb_message *message) { - kfree(message); + if (message->size > sizeof(message->header)) + kfree(message); + else + kmem_cache_free(gb_simple_message_cache, message); } /* @@ -836,22 +848,46 @@ int gb_operation_sync(struct gb_connection *connection, int type, int gb_operation_init(void) { + size_t size; + BUILD_BUG_ON(GB_OPERATION_MESSAGE_SIZE_MAX > U16_MAX - sizeof(struct gb_operation_msg_hdr)); + /* + * A message structure with consists of: + * - the message structure itself + * - the headroom set aside for the host device + * - the message header + * - space for the message payload + * Messages with no payload are a fairly common case and + * have a known fixed maximum size, so we use a slab cache + * for them. + */ + size = sizeof(struct gb_message) + GB_BUFFER_HEADROOM_MAX + + sizeof(struct gb_operation_msg_hdr); + gb_simple_message_cache = kmem_cache_create("gb_simple_message_cache", + size, 0, 0, NULL); + if (!gb_simple_message_cache) + return -ENOMEM; + gb_operation_cache = kmem_cache_create("gb_operation_cache", sizeof(struct gb_operation), 0, 0, NULL); if (!gb_operation_cache) - return -ENOMEM; + goto err_simple; gb_operation_workqueue = alloc_workqueue("greybus_operation", 0, 1); - if (!gb_operation_workqueue) { - kmem_cache_destroy(gb_operation_cache); - gb_operation_cache = NULL; - return -ENOMEM; - } + if (!gb_operation_workqueue) + goto err_operation; return 0; +err_operation: + kmem_cache_destroy(gb_operation_cache); + gb_operation_cache = NULL; +err_simple: + kmem_cache_destroy(gb_simple_message_cache); + gb_simple_message_cache = NULL; + + return -ENOMEM; } void gb_operation_exit(void) @@ -860,4 +896,6 @@ void gb_operation_exit(void) gb_operation_workqueue = NULL; kmem_cache_destroy(gb_operation_cache); gb_operation_cache = NULL; + kmem_cache_destroy(gb_simple_message_cache); + gb_simple_message_cache = NULL; } -- cgit v0.10.2 From d2d2c0fe70ff09510f56bd341e2ab415b7b5e947 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 2 Dec 2014 08:30:36 -0600 Subject: greybus: set result in gb_operation_response_send() Change gb_operation_response_send() so it takes an errno to assign as an operation's result. This emphasizes that setting the result should be the last thing done to an incoming operation before sending its response. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 2a6f361..c80eb33 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -642,8 +642,13 @@ int gb_operation_request_send(struct gb_operation *operation, /* * Send a response for an incoming operation request. */ -int gb_operation_response_send(struct gb_operation *operation) +int gb_operation_response_send(struct gb_operation *operation, int errno) { + /* Record the result */ + if (!gb_operation_result_set(operation, errno)) { + pr_err("request result already set\n"); + return -EIO; /* Shouldn't happen */ + } gb_operation_destroy(operation); return 0; diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index feff823..ed344f8 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -100,7 +100,7 @@ static inline void gb_operation_destroy(struct gb_operation *operation) int gb_operation_request_send(struct gb_operation *operation, gb_operation_callback callback); -int gb_operation_response_send(struct gb_operation *operation); +int gb_operation_response_send(struct gb_operation *operation, int errno); void gb_operation_cancel(struct gb_operation *operation, int errno); -- cgit v0.10.2 From d4a1ff674dfbd120930dbd011773b3ae79385449 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 2 Dec 2014 08:30:37 -0600 Subject: greybus: activate incoming request handling Un-comment gb_operation_request_handle(), which was recently disabled to avoid distraction. In gb_connection_recv_request(), activate handling incoming requests by defining gb_operation_request_handle() as an incoming operation's callback function. Incoming operation requests have Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index c80eb33..8ffc54b 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -234,7 +234,6 @@ static void gb_message_cancel(struct gb_message *message) mutex_unlock(&gb_message_mutex); } -#if 0 static void gb_operation_request_handle(struct gb_operation *operation) { struct gb_protocol *protocol = operation->connection->protocol; @@ -253,13 +252,21 @@ static void gb_operation_request_handle(struct gb_operation *operation) gb_connection_err(operation->connection, "unexpected incoming request type 0x%02hhx\n", header->type); - (void)gb_operation_result_set(operation, -EPROTONOSUPPORT); + if (gb_operation_result_set(operation, -EPROTONOSUPPORT)) + queue_work(gb_operation_workqueue, &operation->work); + else + WARN(true, "failed to mark request bad\n"); } -#endif /* - * Complete an operation in non-atomic context. The operation's - * result value should have been set before queueing this. + * Complete an operation in non-atomic context. For incoming + * requests, the callback function is the request handler, and + * the operation result should be -EINPROGRESS at this point. + * + * For outgoing requests, the operation result value should have + * been set before queueing this. The operation callback function + * allows the original requester to know the request has completed + * and its result is available. */ static void gb_operation_work(struct work_struct *work) { @@ -665,19 +672,29 @@ greybus_data_sent(struct greybus_host_device *hd, void *header, int status) struct gb_message *message; struct gb_operation *operation; - /* XXX Right now we assume we're an outgoing request */ + /* Get the message and record that it is no longer in flight */ message = gb_hd_message_find(hd, header); - - /* Record that the message is no longer in flight */ message->cookie = NULL; - /* If there's no error, there's really nothing more to do */ - if (!status) - return; /* Mark it complete? */ - + /* + * If the message was a response, we just need to drop our + * reference to the operation. If an error occurred, report + * it. + * + * For requests, if there's no error, there's nothing more + * to do until the response arrives. If an error occurred + * attempting to send it, record that as the result of + * the operation and schedule its completion. + */ operation = message->operation; - if (gb_operation_result_set(operation, status)) - queue_work(gb_operation_workqueue, &operation->work); + if (message == operation->response) { + if (status) + pr_err("error %d sending response\n", status); + gb_operation_put(operation); + } else if (status) { + if (gb_operation_result_set(operation, status)) + queue_work(gb_operation_workqueue, &operation->work); + } } EXPORT_SYMBOL_GPL(greybus_data_sent); @@ -701,8 +718,18 @@ static void gb_connection_recv_request(struct gb_connection *connection, return; /* XXX Respond with pre-allocated ENOMEM */ } - /* XXX Right now this will just complete the operation */ - if (gb_operation_result_set(operation, -ENOSYS)) + /* + * Incoming requests are handled by arranging for the + * request handler to be the operation's callback function. + * + * The last thing the handler does is send a response + * message. The callback function is then cleared (in + * gb_operation_work()). The original reference to the + * operation will be dropped when the response has been + * sent. + */ + operation->callback = gb_operation_request_handle; + if (gb_operation_result_set(operation, -EINPROGRESS)) queue_work(gb_operation_workqueue, &operation->work); } -- cgit v0.10.2 From 0c90fff4e35c1322a52709f17d630431c7deb931 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 2 Dec 2014 08:30:38 -0600 Subject: greybus: introduce gb_operation_errno_map() Define gb_operation_errno_map(), which maps an operation->errno into the u8 value that represents it in the status field of an operation response header. It'll be used in an upcoming patch. Make gb_operation_status_map() a private function. It's not used outside "operation.c" and I don't believe it ever should be. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 8ffc54b..f324681 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -411,7 +411,7 @@ static void gb_operation_message_free(struct gb_message *message) * Map an enum gb_operation_status value (which is represented in a * message as a single byte) to an appropriate Linux negative errno. */ -int gb_operation_status_map(u8 status) +static int gb_operation_status_map(u8 status) { switch (status) { case GB_OP_SUCCESS: @@ -439,6 +439,39 @@ int gb_operation_status_map(u8 status) } /* + * Map a Linux errno value (from operation->errno) into the value + * that should represent it in a response message status sent + * over the wire. Returns an enum gb_operation_status value (which + * is represented in a message as a single byte). + */ +static u8 gb_operation_errno_map(int errno) +{ + switch (errno) { + case 0: + return GB_OP_SUCCESS; + case -EINTR: + return GB_OP_INTERRUPTED; + case -ETIMEDOUT: + return GB_OP_TIMEOUT; + case -ENOMEM: + return GB_OP_NO_MEMORY; + case -EPROTONOSUPPORT: + return GB_OP_PROTOCOL_BAD; + case -EMSGSIZE: + return GB_OP_OVERFLOW; /* Could be underflow too */ + case -EINVAL: + return GB_OP_INVALID; + case -EAGAIN: + return GB_OP_RETRY; + case -EILSEQ: + return GB_OP_MALFUNCTION; + case -EIO: + default: + return GB_OP_UNKNOWN_ERROR; + } +} + +/* * Create a Greybus operation to be sent over the given connection. * The request buffer will be big enough for a payload of the given * size. @@ -656,6 +689,7 @@ int gb_operation_response_send(struct gb_operation *operation, int errno) pr_err("request result already set\n"); return -EIO; /* Shouldn't happen */ } + (void)gb_operation_errno_map; /* avoid a build warning */ gb_operation_destroy(operation); return 0; diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index ed344f8..adaec7c 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -104,8 +104,6 @@ int gb_operation_response_send(struct gb_operation *operation, int errno); void gb_operation_cancel(struct gb_operation *operation, int errno); -int gb_operation_status_map(u8 status); - void greybus_data_sent(struct greybus_host_device *hd, void *header, int status); -- cgit v0.10.2 From 82e26f73b2a8ee4acc2507494430aa5774da2b74 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 2 Dec 2014 08:30:39 -0600 Subject: greybus: send operation response messages Define a helper function gb_operation_response_alloc() and use it to allocate the response buffer for outgoing operations in gb_operation_create_common(. Use it also in gb_operation_response_send() if the caller has not allocated a response buffer. Once a response buffer is allocated, fill in its result code and send it. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index f324681..1409d31 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -471,6 +471,34 @@ static u8 gb_operation_errno_map(int errno) } } +bool gb_operation_response_alloc(struct gb_operation *operation, + size_t response_size) +{ + struct greybus_host_device *hd = operation->connection->hd; + struct gb_operation_msg_hdr *request_header; + struct gb_message *response; + u8 type; + + request_header = operation->request->header; + type = request_header->type | GB_OPERATION_TYPE_RESPONSE; + response = gb_operation_message_alloc(hd, type, response_size, + GFP_KERNEL); + if (!response) + return false; + response->operation = operation; + + /* + * Size and type get initialized when the message is + * allocated. The errno will be set before sending. All + * that's left is the operation id, which we copy from the + * request message header (as-is, in little-endian order). + */ + response->header->operation_id = request_header->operation_id; + operation->response = response; + + return true; +} + /* * Create a Greybus operation to be sent over the given connection. * The request buffer will be big enough for a payload of the given @@ -513,14 +541,9 @@ gb_operation_create_common(struct gb_connection *connection, u8 type, operation->request->operation = operation; /* Allocate the response buffer for outgoing operations */ - if (type) { - type |= GB_OPERATION_TYPE_RESPONSE; - operation->response = gb_operation_message_alloc(hd, type, - response_size, GFP_KERNEL); - if (!operation->response) + if (type) + if (!gb_operation_response_alloc(operation, response_size)) goto err_request; - operation->response->operation = operation; - } operation->errno = -EBADR; /* Initial value--means "never set" */ INIT_WORK(&operation->work, gb_operation_work); @@ -680,7 +703,13 @@ int gb_operation_request_send(struct gb_operation *operation, } /* - * Send a response for an incoming operation request. + * Send a response for an incoming operation request. A non-zero + * errno indicates a failed operation. + * + * If there is any response payload, the incoming request handler is + * responsible for allocating the response message. Otherwise the + * it can simply supply the result errno; this function will + * allocate the response message if necessary. */ int gb_operation_response_send(struct gb_operation *operation, int errno) { @@ -689,10 +718,19 @@ int gb_operation_response_send(struct gb_operation *operation, int errno) pr_err("request result already set\n"); return -EIO; /* Shouldn't happen */ } - (void)gb_operation_errno_map; /* avoid a build warning */ - gb_operation_destroy(operation); - return 0; + if (!operation->response) { + if (!gb_operation_response_alloc(operation, 0)) { + pr_err("error allocating response\n"); + /* XXX Respond with pre-allocated -ENOMEM? */ + return -ENOMEM; + } + } + + /* Fill in the response header and send it */ + operation->response->header->result = gb_operation_errno_map(errno); + + return gb_message_send(operation->response); } /* diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index adaec7c..c60decb 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -98,6 +98,9 @@ static inline void gb_operation_destroy(struct gb_operation *operation) gb_operation_put(operation); } +bool gb_operation_response_alloc(struct gb_operation *operation, + size_t response_size); + int gb_operation_request_send(struct gb_operation *operation, gb_operation_callback callback); int gb_operation_response_send(struct gb_operation *operation, int errno); -- cgit v0.10.2 From 583d233fa9d6fffd028af5219bcb5753bcb7b5ef Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 2 Dec 2014 15:48:09 -0600 Subject: greybus: use little-endian in PWM requests The PWM config request defines two 32-bit values using u32. All over-the-wire values have to be in little-endian format. Fix this. Signed-off-by: Alex Elder Acked-by: Matt Porter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/pwm-gb.c b/drivers/staging/greybus/pwm-gb.c index bd1379f..9678b64 100644 --- a/drivers/staging/greybus/pwm-gb.c +++ b/drivers/staging/greybus/pwm-gb.c @@ -62,8 +62,8 @@ struct gb_pwm_deactivate_request { struct gb_pwm_config_request { __u8 which; - __u32 duty; - __u32 period; + __le32 duty; + __le32 period; }; struct gb_pwm_polarity_request { @@ -152,8 +152,8 @@ static int gb_pwm_config_operation(struct gb_pwm_chip *pwmc, return -EINVAL; request.which = which; - request.duty = duty; - request.period = period; + request.duty = cpu_to_le32(duty); + request.period = cpu_to_le32(period); return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_CONFIG, &request, sizeof(request), NULL, 0); } -- cgit v0.10.2 From 6cd6ec55f4940bcddeed65e4eebb6190a64a4eb7 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 2 Dec 2014 17:03:51 -0600 Subject: greybus: fix a bug in gb_operation_sync() The memcpy of request data into the request payload was copying the data into the wrong location. Fix that. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 1409d31..d3ba658 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -935,7 +935,7 @@ int gb_operation_sync(struct gb_connection *connection, int type, return -ENOMEM; if (request_size) - memcpy(&operation->request->payload, request, request_size); + memcpy(operation->request->payload, request, request_size); /* Synchronous operation--no callback */ ret = gb_operation_request_send(operation, NULL); -- cgit v0.10.2 From c939c2f8fe85a8099d553ae5c12b9a24ef735d05 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 2 Dec 2014 17:25:11 -0600 Subject: greybus: define the invalid operation type symbolically Use a symbolic constant (rather than just "0") to represent an explicitly invalid operation type. The protocols have all reserved that value for that purpose--this just makes it explicit in the core code (since we now leverage its existence). Fix the code so it uses the new symbolic value. Define it in "operation.h" for all to see. Move the common definition of the GB_OPERATION_TYPE_RESPONSE flag mask there as well. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index d3ba658..b2ebbe4 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -13,12 +13,6 @@ #include "greybus.h" -/* - * The top bit of the type in an operation message header indicates - * whether the message is a request (bit clear) or response (bit set) - */ -#define GB_OPERATION_TYPE_RESPONSE 0x80 - #define OPERATION_TIMEOUT_DEFAULT 1000 /* milliseconds */ /* @@ -329,7 +323,7 @@ static void gb_operation_message_init(struct greybus_host_device *hd, * 0x00. Such buffers will be overwritten by arriving data * so there's no need to initialize the message header. */ - if (type) { + if (type != GB_OPERATION_TYPE_INVALID) { /* * For a request, the operation id gets filled in * when the message is sent. For a response, it @@ -527,8 +521,17 @@ gb_operation_create_common(struct gb_connection *connection, u8 type, { struct greybus_host_device *hd = connection->hd; struct gb_operation *operation; - gfp_t gfp_flags = type ? GFP_KERNEL : GFP_ATOMIC; + gfp_t gfp_flags; + /* + * An incoming request will pass an invalid operation type, + * because the header will get overwritten anyway. These + * occur in interrupt context, so we must use GFP_ATOMIC. + */ + if (type == GB_OPERATION_TYPE_INVALID) + gfp_flags = GFP_ATOMIC; + else + gfp_flags = GFP_KERNEL; operation = kmem_cache_zalloc(gb_operation_cache, gfp_flags); if (!operation) return NULL; @@ -541,7 +544,7 @@ gb_operation_create_common(struct gb_connection *connection, u8 type, operation->request->operation = operation; /* Allocate the response buffer for outgoing operations */ - if (type) + if (type != GB_OPERATION_TYPE_INVALID) if (!gb_operation_response_alloc(operation, response_size)) goto err_request; operation->errno = -EBADR; /* Initial value--means "never set" */ @@ -578,7 +581,7 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, u8 type, size_t request_size, size_t response_size) { - if (WARN_ON_ONCE(!type)) + if (WARN_ON_ONCE(type == GB_OPERATION_TYPE_INVALID)) return NULL; if (WARN_ON_ONCE(type & GB_OPERATION_TYPE_RESPONSE)) type &= ~GB_OPERATION_TYPE_RESPONSE; @@ -593,7 +596,9 @@ gb_operation_create_incoming(struct gb_connection *connection, u16 id, { struct gb_operation *operation; - operation = gb_operation_create_common(connection, 0, request_size, 0); + operation = gb_operation_create_common(connection, + GB_OPERATION_TYPE_INVALID, + request_size, 0); if (operation) { operation->id = id; memcpy(operation->request->header, data, request_size); diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index c60decb..40b2e7d 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -13,6 +13,18 @@ struct gb_operation; +/* + * No protocol may define an operation that has numeric value 0x00. + * It is reserved as an explicitly invalid value. + */ +#define GB_OPERATION_TYPE_INVALID ((u8)0x00) + +/* + * The top bit of the type in an operation message header indicates + * whether the message is a request (bit clear) or response (bit set) + */ +#define GB_OPERATION_TYPE_RESPONSE ((u8)0x80) + enum gb_operation_result { GB_OP_SUCCESS = 0x00, GB_OP_INTERRUPTED = 0x01, -- cgit v0.10.2 From 0ba02c4d1675c426f38f3beb6b6cb1a3d9aeff97 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 3 Dec 2014 08:35:06 -0600 Subject: greybus: don't use 0 as an operation id Stop allowing 0x0000 to be used as an operation id. That id will be reserved for use by operations that will return no response message. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index b2ebbe4..c0e206d 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -151,10 +151,11 @@ static void gb_pending_operation_insert(struct gb_operation *operation) /* * Assign the operation's id and move it into its - * connection's pending list. + * connection's pending list. Zero is a reserved operation + * id. */ spin_lock_irq(&gb_operations_lock); - operation->id = ++connection->op_cycle; + operation->id = ++connection->op_cycle % U16_MAX + 1; list_move_tail(&operation->links, &connection->pending); spin_unlock_irq(&gb_operations_lock); -- cgit v0.10.2 From afb2e1342e75b55be8834efc5b1c77f654572df8 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 3 Dec 2014 08:35:07 -0600 Subject: greybus: get rid of pending operations list A connection has two lists of operations, and an operation is always on one or the other of them. One of them contains the operations that are currently "in flight". We really don't expect to have very many in-flight operations on any given connection (in fact, at the moment it's always exactly one). So there's no significant performance benefit to keeping these in a separate list. An in-flight operation can also be distinguished by its errno field holding -EINPROGRESS. Get rid of the pending list, and search all operations rather than the pending list when looking up a response message's operation. Rename gb_pending_operation_find() accordingly. There's no longer any need to remove operations from the pending list, and the insertion function no longer has anything to do with a pending list. Just open code what was the insertion function (it now has only to do with assigning the operation id). Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 6503546..7fbfcdc 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -192,7 +192,6 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, spin_unlock_irq(&gb_connections_lock); INIT_LIST_HEAD(&connection->operations); - INIT_LIST_HEAD(&connection->pending); return connection; } diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 8cde114..035fced 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -37,7 +37,6 @@ struct gb_connection { u16 op_cycle; struct list_head operations; - struct list_head pending; /* awaiting response */ void *private; }; diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index c0e206d..6ed1d479 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -144,44 +144,14 @@ int gb_operation_result(struct gb_operation *operation) return result; } -static void gb_pending_operation_insert(struct gb_operation *operation) -{ - struct gb_connection *connection = operation->connection; - struct gb_operation_msg_hdr *header; - - /* - * Assign the operation's id and move it into its - * connection's pending list. Zero is a reserved operation - * id. - */ - spin_lock_irq(&gb_operations_lock); - operation->id = ++connection->op_cycle % U16_MAX + 1; - list_move_tail(&operation->links, &connection->pending); - spin_unlock_irq(&gb_operations_lock); - - /* Store the operation id in the request header */ - header = operation->request->header; - header->operation_id = cpu_to_le16(operation->id); -} - -static void gb_pending_operation_remove(struct gb_operation *operation) -{ - struct gb_connection *connection = operation->connection; - - /* Take us off of the list of pending operations */ - spin_lock_irq(&gb_operations_lock); - list_move_tail(&operation->links, &connection->operations); - spin_unlock_irq(&gb_operations_lock); -} - static struct gb_operation * -gb_pending_operation_find(struct gb_connection *connection, u16 operation_id) +gb_operation_find(struct gb_connection *connection, u16 operation_id) { struct gb_operation *operation; bool found = false; spin_lock_irq(&gb_operations_lock); - list_for_each_entry(operation, &connection->pending, links) + list_for_each_entry(operation, &connection->operations, links) if (operation->id == operation_id) { found = true; break; @@ -667,10 +637,12 @@ static void gb_operation_sync_callback(struct gb_operation *operation) int gb_operation_request_send(struct gb_operation *operation, gb_operation_callback callback) { + struct gb_connection *connection = operation->connection; + struct gb_operation_msg_hdr *header; unsigned long timeout; int ret; - if (operation->connection->state != GB_CONNECTION_STATE_ENABLED) + if (connection->state != GB_CONNECTION_STATE_ENABLED) return -ENOTCONN; /* @@ -684,7 +656,16 @@ int gb_operation_request_send(struct gb_operation *operation, operation->callback = callback; else operation->callback = gb_operation_sync_callback; - gb_pending_operation_insert(operation); + + /* + * Assign the operation's id, and store it in the request header. + * Zero is a reserved operation id. + */ + spin_lock_irq(&gb_operations_lock); + operation->id = ++connection->op_cycle % U16_MAX + 1; + spin_unlock_irq(&gb_operations_lock); + header = operation->request->header; + header->operation_id = cpu_to_le16(operation->id); /* * We impose a time limit for requests to complete. We need @@ -826,14 +807,13 @@ static void gb_connection_recv_response(struct gb_connection *connection, struct gb_message *message; int errno = gb_operation_status_map(result); - operation = gb_pending_operation_find(connection, operation_id); + operation = gb_operation_find(connection, operation_id); if (!operation) { gb_connection_err(connection, "operation not found"); return; } cancel_delayed_work(&operation->timeout_work); - gb_pending_operation_remove(operation); message = operation->response; if (!errno && size != message->size) { diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 40b2e7d..c73d9b9 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -92,7 +92,7 @@ struct gb_operation { struct delayed_work timeout_work; struct kref kref; - struct list_head links; /* connection->{operations,pending} */ + struct list_head links; /* connection->operations */ }; void gb_connection_recv(struct gb_connection *connection, -- cgit v0.10.2 From 4afb7fd0154753711e7bc68790f6f5de8dbed39e Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 3 Dec 2014 08:35:08 -0600 Subject: greybus: make op_cycle atomic (again) There's no need to protect updating a connections operation id cycle counter with the operations spinlock. That spinlock protects connection lists, which do not interact with the cycle counter. All that we require is that it gets updated atomically, and we can express that requirement in its type. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 7fbfcdc..e59a777 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -191,6 +191,7 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, list_add_tail(&connection->interface_links, &interface->connections); spin_unlock_irq(&gb_connections_lock); + atomic_set(&connection->op_cycle, 0); INIT_LIST_HEAD(&connection->operations); return connection; diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 035fced..7568161 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -35,7 +35,7 @@ struct gb_connection { enum gb_connection_state state; - u16 op_cycle; + atomic_t op_cycle; struct list_head operations; void *private; diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 6ed1d479..15a6e3b 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -640,6 +640,7 @@ int gb_operation_request_send(struct gb_operation *operation, struct gb_connection *connection = operation->connection; struct gb_operation_msg_hdr *header; unsigned long timeout; + unsigned int cycle; int ret; if (connection->state != GB_CONNECTION_STATE_ENABLED) @@ -661,9 +662,8 @@ int gb_operation_request_send(struct gb_operation *operation, * Assign the operation's id, and store it in the request header. * Zero is a reserved operation id. */ - spin_lock_irq(&gb_operations_lock); - operation->id = ++connection->op_cycle % U16_MAX + 1; - spin_unlock_irq(&gb_operations_lock); + cycle = (unsigned int)atomic_inc_return(&connection->op_cycle); + operation->id = (u16)(cycle % U16_MAX + 1); header = operation->request->header; header->operation_id = cpu_to_le16(operation->id); -- cgit v0.10.2 From c25572ca943a1f8c2db7a8063c166d12480bb69d Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 3 Dec 2014 08:35:09 -0600 Subject: greybus: introduce gb_operation_request_send_sync() Define a new function used to initiate a synchronous operation. It sends the operation request message and doesn't return until the response has been received and/or the operation's result has been set. This gets rid of the convention that a null callback pointer signifies a synchronous operation. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index 19a7df9..bd1bada 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -285,7 +285,7 @@ static int gb_i2c_transfer_operation(struct gb_i2c_device *gb_i2c_dev, return -ENOMEM; /* Synchronous operation--no callback */ - ret = gb_operation_request_send(operation, NULL); + ret = gb_operation_request_send_sync(operation); if (ret) { if (ret != -EAGAIN) pr_err("transfer operation failed (%d)\n", ret); diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 15a6e3b..c62f200 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -641,7 +641,6 @@ int gb_operation_request_send(struct gb_operation *operation, struct gb_operation_msg_hdr *header; unsigned long timeout; unsigned int cycle; - int ret; if (connection->state != GB_CONNECTION_STATE_ENABLED) return -ENOTCONN; @@ -652,11 +651,12 @@ int gb_operation_request_send(struct gb_operation *operation, */ gb_operation_get(operation); - /* A null callback pointer means synchronous return */ - if (callback) - operation->callback = callback; - else - operation->callback = gb_operation_sync_callback; + /* + * Record the callback function, which is executed in + * non-atomic (workqueue) context when the final result + * of an operation has been set. + */ + operation->callback = callback; /* * Assign the operation's id, and store it in the request header. @@ -677,8 +677,22 @@ int gb_operation_request_send(struct gb_operation *operation, /* All set, send the request */ gb_operation_result_set(operation, -EINPROGRESS); - ret = gb_message_send(operation->request); - if (ret || callback) + + return gb_message_send(operation->request); +} + +/* + * Send a synchronous operation. This function is expected to + * block, returning only when the response has arrived, (or when an + * error is detected. The return value is the result of the + * operation. + */ +int gb_operation_request_send_sync(struct gb_operation *operation) +{ + int ret; + + ret = gb_operation_request_send(operation, gb_operation_sync_callback); + if (ret) return ret; /* Cancel the operation if interrupted */ @@ -923,8 +937,7 @@ int gb_operation_sync(struct gb_connection *connection, int type, if (request_size) memcpy(operation->request->payload, request, request_size); - /* Synchronous operation--no callback */ - ret = gb_operation_request_send(operation, NULL); + ret = gb_operation_request_send_sync(operation); if (ret) pr_err("version operation failed (%d)\n", ret); else diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index c73d9b9..3415e8b 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -115,6 +115,7 @@ bool gb_operation_response_alloc(struct gb_operation *operation, int gb_operation_request_send(struct gb_operation *operation, gb_operation_callback callback); +int gb_operation_request_send_sync(struct gb_operation *operation); int gb_operation_response_send(struct gb_operation *operation, int errno); void gb_operation_cancel(struct gb_operation *operation, int errno); diff --git a/drivers/staging/greybus/usb-gb.c b/drivers/staging/greybus/usb-gb.c index ab4e093..e5da72a 100644 --- a/drivers/staging/greybus/usb-gb.c +++ b/drivers/staging/greybus/usb-gb.c @@ -169,7 +169,7 @@ static int urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) memcpy(&request->payload, urb->transfer_buffer, urb->transfer_buffer_length); - ret = gb_operation_request_send(operation, NULL); + ret = gb_operation_request_send_sync(operation); gb_operation_destroy(operation); return ret; -- cgit v0.10.2 From 62749a056ab48994956cf14abcd5622db4a4a0cb Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 3 Dec 2014 12:27:41 -0600 Subject: greybus: fix an error message The error message printed by gb_operation_sync() if the operation fails is wrong. Fix it. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index c62f200..109b94f 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -939,7 +939,7 @@ int gb_operation_sync(struct gb_connection *connection, int type, ret = gb_operation_request_send_sync(operation); if (ret) - pr_err("version operation failed (%d)\n", ret); + pr_err("synchronous operation failed (%d)\n", ret); else if (response_size) memcpy(response, operation->response->payload, -- cgit v0.10.2 From 93bbe859b75616ebdc33722c3b30cf36e74161a8 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 3 Dec 2014 12:27:42 -0600 Subject: greybus: set up connection->private properly The connection->private pointer should refer to a protocol-specific data structure. Change two protocol drivers (USB and vibrator) so they now set this. In addition, because the setup routine may need access to the data structure, the private pointer should be set early--as early as possible. Make the UART, i2c, and GPIO protocol drivers set the private pointer earlier. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index 09d77c1..c573cce 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -472,6 +472,7 @@ static int gb_gpio_connection_init(struct gb_connection *connection) if (!gb_gpio_controller) return -ENOMEM; gb_gpio_controller->connection = connection; + connection->private = gb_gpio_controller; ret = gb_gpio_controller_setup(gb_gpio_controller); if (ret) @@ -502,7 +503,6 @@ static int gb_gpio_connection_init(struct gb_connection *connection) pr_err("Failed to register GPIO\n"); return ret; } - connection->private = gb_gpio_controller; return 0; out_err: diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index bd1bada..8936389 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -377,6 +377,7 @@ static int gb_i2c_connection_init(struct gb_connection *connection) return -ENOMEM; gb_i2c_dev->connection = connection; /* refcount? */ + connection->private = gb_i2c_dev; ret = gb_i2c_device_setup(gb_i2c_dev); if (ret) @@ -399,8 +400,6 @@ static int gb_i2c_connection_init(struct gb_connection *connection) if (ret) goto out_err; - connection->private = gb_i2c_dev; - return 0; out_err: /* kref_put(gb_i2c_dev->connection) */ diff --git a/drivers/staging/greybus/pwm-gb.c b/drivers/staging/greybus/pwm-gb.c index 9678b64..c505f1d 100644 --- a/drivers/staging/greybus/pwm-gb.c +++ b/drivers/staging/greybus/pwm-gb.c @@ -266,6 +266,7 @@ static int gb_pwm_connection_init(struct gb_connection *connection) if (!pwmc) return -ENOMEM; pwmc->connection = connection; + connection->private = pwmc; /* Check for compatible protocol version */ ret = gb_pwm_proto_version_operation(pwmc); @@ -290,7 +291,6 @@ static int gb_pwm_connection_init(struct gb_connection *connection) pr_err("Failed to register PWM\n"); return ret; } - connection->private = pwmc; return 0; out_err: diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 6432c64..fad8635 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -637,6 +637,7 @@ static int gb_uart_connection_init(struct gb_connection *connection) if (!gb_tty) return -ENOMEM; gb_tty->connection = connection; + connection->private = gb_tty; /* Check for compatible protocol version */ retval = get_version(gb_tty); @@ -659,8 +660,6 @@ static int gb_uart_connection_init(struct gb_connection *connection) init_waitqueue_head(&gb_tty->wioctl); mutex_init(&gb_tty->mutex); - connection->private = gb_tty; - send_control(gb_tty, gb_tty->ctrlout); /* initialize the uart to be 9600n81 */ diff --git a/drivers/staging/greybus/usb-gb.c b/drivers/staging/greybus/usb-gb.c index e5da72a..b3092ed 100644 --- a/drivers/staging/greybus/usb-gb.c +++ b/drivers/staging/greybus/usb-gb.c @@ -341,6 +341,7 @@ static int gb_usb_connection_init(struct gb_connection *connection) return -ENOMEM; gb_usb_dev->connection = connection; + connection->private = gb_usb_dev; /* Check for compatible protocol version */ retval = get_version(gb_usb_dev); diff --git a/drivers/staging/greybus/vibrator-gb.c b/drivers/staging/greybus/vibrator-gb.c index d00301d..8970c69 100644 --- a/drivers/staging/greybus/vibrator-gb.c +++ b/drivers/staging/greybus/vibrator-gb.c @@ -139,6 +139,7 @@ static int gb_vibrator_connection_init(struct gb_connection *connection) return -ENOMEM; vib->connection = connection; + connection->private = vib; retval = get_version(vib); if (retval) -- cgit v0.10.2 From 7a9366aa1e8645c12c0050b417358089c216d14f Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 3 Dec 2014 12:27:43 -0600 Subject: greybus: don't let i2c code assume non-null payload pointer This is in preparation for an upcoming patch, which makes the payload pointer be NULL when a message has zero bytes of payload. It ensures a null payload pointer never gets dereferenced. To do this we pass the response structure to gb_i2c_transfer_response() rather than just its data, and if it's null, returning immediately. Rearrange the logic in gb_i2c_transfer_operation() a bit. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index 8936389..f63b60e 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -258,11 +258,15 @@ gb_i2c_transfer_request(struct gb_connection *connection, } static void gb_i2c_transfer_response(struct i2c_msg *msgs, u32 msg_count, - void *data) + struct gb_i2c_transfer_response *response) { struct i2c_msg *msg = msgs; + u8 *data; u32 i; + if (!response) + return; + data = response->data; for (i = 0; i < msg_count; i++) { if (msg->flags & I2C_M_RD) { memcpy(msg->buf, data, msg->len); @@ -276,7 +280,6 @@ static int gb_i2c_transfer_operation(struct gb_i2c_device *gb_i2c_dev, struct i2c_msg *msgs, u32 msg_count) { struct gb_connection *connection = gb_i2c_dev->connection; - struct gb_i2c_transfer_response *response; struct gb_operation *operation; int ret; @@ -284,15 +287,15 @@ static int gb_i2c_transfer_operation(struct gb_i2c_device *gb_i2c_dev, if (!operation) return -ENOMEM; - /* Synchronous operation--no callback */ ret = gb_operation_request_send_sync(operation); - if (ret) { - if (ret != -EAGAIN) - pr_err("transfer operation failed (%d)\n", ret); - } else { + if (!ret) { + struct gb_i2c_transfer_response *response; + response = operation->response->payload; - gb_i2c_transfer_response(msgs, msg_count, response->data); + gb_i2c_transfer_response(msgs, msg_count, response); ret = msg_count; + } else if (ret != -EAGAIN) { + pr_err("transfer operation failed (%d)\n", ret); } gb_operation_destroy(operation); -- cgit v0.10.2 From 7cfa699556731c0c7d93793c419eb83f37107de2 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 3 Dec 2014 12:27:44 -0600 Subject: greybus: only record message payload size An asynchronous operation will want to know how big the response message it receives is. Rather than require the sender to record that information, expose a new field "payload_size" available to the protocol code for this purpose. An operation message consists of a header and a payload. The size of the message can be derived from the size of the payload, so record only the payload size and not the size of the whole message. Reorder the fields in a message structure. Update the description of the message header structure. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 109b94f..6a1d3e6 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -32,15 +32,13 @@ static DEFINE_MUTEX(gb_message_mutex); /* * All operation messages (both requests and responses) begin with - * a header that encodes the size of the data (header included). - * This header also contains a unique identifier, which is used to - * keep track of in-flight operations. The header contains an + * a header that encodes the size of the message (header included). + * This header also contains a unique identifier, that associates a + * response message with its operation. The header contains an * operation type field, whose interpretation is dependent on what - * type of protocol is used over the connection. - * - * The high bit (0x80) of the operation type field is used to - * indicate whether the message is a request (clear) or a response - * (set). + * type of protocol is used over the connection. The high bit + * (0x80) of the operation type field is used to indicate whether + * the message is a request (clear) or a response (set). * * Response messages include an additional status byte, which * communicates the result of the corresponding request. A zero @@ -163,6 +161,7 @@ gb_operation_find(struct gb_connection *connection, u16 operation_id) static int gb_message_send(struct gb_message *message) { + size_t message_size = sizeof(*message->header) + message->payload_size; struct gb_connection *connection = message->operation->connection; u16 dest_cport_id = connection->interface_cport_id; int ret = 0; @@ -172,7 +171,7 @@ static int gb_message_send(struct gb_message *message) cookie = connection->hd->driver->buffer_send(connection->hd, dest_cport_id, message->header, - message->size, + message_size, GFP_KERNEL); if (IS_ERR(cookie)) ret = PTR_ERR(cookie); @@ -276,18 +275,17 @@ gb_hd_message_find(struct greybus_host_device *hd, void *header) static void gb_operation_message_init(struct greybus_host_device *hd, struct gb_message *message, u16 operation_id, - size_t message_size, u8 type) + size_t payload_size, u8 type) { struct gb_operation_msg_hdr *header; u8 *buffer; - BUG_ON(message_size < sizeof(*header)); buffer = &message->buffer[0]; header = (struct gb_operation_msg_hdr *)(buffer + hd->buffer_headroom); message->header = header; message->payload = header + 1; - message->size = message_size; + message->payload_size = payload_size; /* * The type supplied for incoming message buffers will be @@ -295,6 +293,8 @@ static void gb_operation_message_init(struct greybus_host_device *hd, * so there's no need to initialize the message header. */ if (type != GB_OPERATION_TYPE_INVALID) { + u16 message_size = (u16)(sizeof(*header) + payload_size); + /* * For a request, the operation id gets filled in * when the message is sent. For a response, it @@ -359,14 +359,14 @@ gb_operation_message_alloc(struct greybus_host_device *hd, u8 type, return NULL; /* Initialize the message. Operation id is filled in later. */ - gb_operation_message_init(hd, message, 0, message_size, type); + gb_operation_message_init(hd, message, 0, payload_size, type); return message; } static void gb_operation_message_free(struct gb_message *message) { - if (message->size > sizeof(message->header)) + if (message->payload_size) kfree(message); else kmem_cache_free(gb_simple_message_cache, message); @@ -820,6 +820,7 @@ static void gb_connection_recv_response(struct gb_connection *connection, struct gb_operation *operation; struct gb_message *message; int errno = gb_operation_status_map(result); + size_t message_size; operation = gb_operation_find(connection, operation_id); if (!operation) { @@ -830,9 +831,10 @@ static void gb_connection_recv_response(struct gb_connection *connection, cancel_delayed_work(&operation->timeout_work); message = operation->response; - if (!errno && size != message->size) { + message_size = sizeof(*message->header) + message->payload_size; + if (!errno && size != message_size) { gb_connection_err(connection, "bad message size (%zu != %zu)", - size, message->size); + size, message_size); errno = -EMSGSIZE; } diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 3415e8b..a79e88a 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -38,13 +38,18 @@ enum gb_operation_result { GB_OP_MALFUNCTION = 0xff, }; +/* + * Protocol code should only examine the payload and payload_size + * fields. All other fields are intended to be private to the + * operations core code. + */ struct gb_message { - struct gb_operation_msg_hdr *header; - void *payload; - size_t size; /* header + payload */ struct gb_operation *operation; - void *cookie; + struct gb_operation_msg_hdr *header; + + void *payload; + size_t payload_size; u8 buffer[]; }; -- cgit v0.10.2 From 746e0ef95ade8dd6d8633679a87ab573b5e1f69e Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 3 Dec 2014 12:27:45 -0600 Subject: greybus: use null pointer for empty payload Currently message->payload always points to the address immediately following the header in a message. If the payload length is 0, this is not a valid pointer. Change the code to assign a null pointer to the payload in this case. I have verified that no code dereferences the payload pointer unless the payload is known to have non-zero size. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 6a1d3e6..6197167 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -284,7 +284,7 @@ static void gb_operation_message_init(struct greybus_host_device *hd, header = (struct gb_operation_msg_hdr *)(buffer + hd->buffer_headroom); message->header = header; - message->payload = header + 1; + message->payload = payload_size ? header + 1 : NULL; message->payload_size = payload_size; /* -- cgit v0.10.2 From 82b5e3feb71482fe63f3c62d81a1528a890dfe74 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 3 Dec 2014 12:27:46 -0600 Subject: greybus: record type in operation structure I've gone back and forth on this, but now that I'm looking at asynchronous operations I know that the asynchronous callback will want to know what type of operation it is handling, and right now that's only available in the message header. So record an operation's type in the operation structure, and use it in a few spots where the header type was being used previously. Pass the type to gb_operation_create_incoming() so it can fill it in after the operation has been created. Clean up the crap comments above the definition of the operation structure. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 6197167..046ed2a 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -13,6 +13,7 @@ #include "greybus.h" +/* The default amount of time a request is given to complete */ #define OPERATION_TIMEOUT_DEFAULT 1000 /* milliseconds */ /* @@ -59,7 +60,10 @@ struct gb_operation_msg_hdr { /* 2 bytes pad, must be zero (ignore when read) */ } __aligned(sizeof(u64)); -/* XXX Could be per-host device, per-module, or even per-connection */ +/* + * Protects access to connection operations lists, as well as + * updates to operation->errno. + */ static DEFINE_SPINLOCK(gb_operations_lock); /* @@ -201,21 +205,18 @@ static void gb_message_cancel(struct gb_message *message) static void gb_operation_request_handle(struct gb_operation *operation) { struct gb_protocol *protocol = operation->connection->protocol; - struct gb_operation_msg_hdr *header; - - header = operation->request->header; /* * If the protocol has no incoming request handler, report * an error and mark the request bad. */ if (protocol->request_recv) { - protocol->request_recv(header->type, operation); + protocol->request_recv(operation->type, operation); return; } gb_connection_err(operation->connection, - "unexpected incoming request type 0x%02hhx\n", header->type); + "unexpected incoming request type 0x%02hhx\n", operation->type); if (gb_operation_result_set(operation, -EPROTONOSUPPORT)) queue_work(gb_operation_workqueue, &operation->work); else @@ -444,8 +445,7 @@ bool gb_operation_response_alloc(struct gb_operation *operation, struct gb_message *response; u8 type; - request_header = operation->request->header; - type = request_header->type | GB_OPERATION_TYPE_RESPONSE; + type = operation->type | GB_OPERATION_TYPE_RESPONSE; response = gb_operation_message_alloc(hd, type, response_size, GFP_KERNEL); if (!response) @@ -458,6 +458,7 @@ bool gb_operation_response_alloc(struct gb_operation *operation, * that's left is the operation id, which we copy from the * request message header (as-is, in little-endian order). */ + request_header = operation->request->header; response->header->operation_id = request_header->operation_id; operation->response = response; @@ -515,9 +516,11 @@ gb_operation_create_common(struct gb_connection *connection, u8 type, operation->request->operation = operation; /* Allocate the response buffer for outgoing operations */ - if (type != GB_OPERATION_TYPE_INVALID) + if (type != GB_OPERATION_TYPE_INVALID) { if (!gb_operation_response_alloc(operation, response_size)) goto err_request; + operation->type = type; + } operation->errno = -EBADR; /* Initial value--means "never set" */ INIT_WORK(&operation->work, gb_operation_work); @@ -563,7 +566,7 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, static struct gb_operation * gb_operation_create_incoming(struct gb_connection *connection, u16 id, - void *data, size_t request_size) + u8 type, void *data, size_t request_size) { struct gb_operation *operation; @@ -572,6 +575,7 @@ gb_operation_create_incoming(struct gb_connection *connection, u16 id, request_size, 0); if (operation) { operation->id = id; + operation->type = type; memcpy(operation->request->header, data, request_size); } @@ -779,13 +783,13 @@ EXPORT_SYMBOL_GPL(greybus_data_sent); * data into the request buffer and handle the rest via workqueue. */ static void gb_connection_recv_request(struct gb_connection *connection, - u16 operation_id, void *data, - size_t size) + u16 operation_id, u8 type, + void *data, size_t size) { struct gb_operation *operation; operation = gb_operation_create_incoming(connection, operation_id, - data, size); + type, data, size); if (!operation) { gb_connection_err(connection, "can't create operation"); return; /* XXX Respond with pre-allocated ENOMEM */ @@ -884,7 +888,7 @@ void gb_connection_recv(struct gb_connection *connection, header->result, data, msg_size); else gb_connection_recv_request(connection, operation_id, - data, msg_size); + header->type, data, msg_size); } /* diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index a79e88a..a173aa9 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -56,39 +56,31 @@ struct gb_message { /* * A Greybus operation is a remote procedure call performed over a - * connection between the AP and a function on Greybus module. - * Every operation consists of a request message sent to the other - * end of the connection coupled with a reply returned to the - * sender. - * - * The state for managing active requests on a connection is held in - * the connection structure. + * connection between two UniPro interfaces. * - * YADA YADA + * Every operation consists of a request message sent to the other + * end of the connection coupled with a reply message returned to + * the sender. Every operation has a type, whose interpretation is + * dependent on the protocol associated with the connection. * - * submitting each request and providing its matching response to - * the caller when it arrives. Operations normally complete - * asynchronously, and when an operation's response arrives its - * callback function is executed. The callback pointer is supplied - * at the time the operation is submitted; a null callback pointer - * causes synchronous operation--the caller is blocked until - * the response arrives. In addition, it is possible to await - * the completion of a submitted asynchronous operation. + * Only four things in an operation structure are intended to be + * directly usable by protocol handlers: the operation's connection + * pointer; the operation type; the request message payload (and + * size); and the response message payload (and size). Note that a + * message with a 0-byte payload has a null message payload pointer. * - * A Greybus device operation includes a Greybus buffer to hold the - * data sent to the device. The only field within a Greybus - * operation that should be used by a caller is the payload pointer, - * which should be used to populate the request data. This pointer - * is guaranteed to be 64-bit aligned. - * XXX and callback? + * In addition, every operation has a result, which is an errno + * value. Protocol handlers access the operation result using + * gb_operation_result(). */ typedef void (*gb_operation_callback)(struct gb_operation *); struct gb_operation { struct gb_connection *connection; struct gb_message *request; struct gb_message *response; - u16 id; + u8 type; + u16 id; int errno; /* Operation result */ struct work_struct work; -- cgit v0.10.2 From 6b7dff889c129a310136ce1aad334e4abec13743 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 8 Dec 2014 17:45:10 -0500 Subject: greybus: battery-gb.c: add new functions from Greybus spec document. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index d28be04..f469a8d 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -35,9 +35,12 @@ struct gb_battery { #define GB_BATTERY_TYPE_TECHNOLOGY 0x02 #define GB_BATTERY_TYPE_STATUS 0x03 #define GB_BATTERY_TYPE_MAX_VOLTAGE 0x04 -#define GB_BATTERY_TYPE_CAPACITY 0x05 +#define GB_BATTERY_TYPE_PERCENT_CAPACITY 0x05 #define GB_BATTERY_TYPE_TEMPERATURE 0x06 #define GB_BATTERY_TYPE_VOLTAGE 0x07 +#define GB_BATTERY_TYPE_CURRENT 0x08 +#define GB_BATTERY_TYPE_CAPACITY 0x09 // TODO - POWER_SUPPLY_PROP_CURRENT_MAX +#define GB_BATTERY_TYPE_SHUTDOWN_TEMP 0x0a // TODO - POWER_SUPPLY_PROP_TEMP_ALERT_MAX struct gb_battery_proto_version_response { __u8 major; @@ -211,13 +214,14 @@ static int get_max_voltage(struct gb_battery *gb) return max_voltage; } -static int get_capacity(struct gb_battery *gb) +static int get_percent_capacity(struct gb_battery *gb) { struct gb_battery_capacity_response capacity_response; u32 capacity; int retval; - retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_CAPACITY, + retval = gb_operation_sync(gb->connection, + GB_BATTERY_TYPE_PERCENT_CAPACITY, NULL, 0, &capacity_response, sizeof(capacity_response)); if (retval) @@ -279,7 +283,7 @@ static int get_property(struct power_supply *b, break; case POWER_SUPPLY_PROP_CAPACITY: - val->intval = get_capacity(gb); + val->intval = get_percent_capacity(gb); break; case POWER_SUPPLY_PROP_TEMP: -- cgit v0.10.2 From 5f474d49436134e0f36d7bc3fb10babebc5e824f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 9 Dec 2014 14:57:04 -0500 Subject: greybus: greybus_manifest.h: add FIXME for version The version field is going to go away, but after the demo, not before. Note that in the header file. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index e2ec558..f44f337 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -71,7 +71,7 @@ enum greybus_class_type { struct greybus_descriptor_module { __le16 vendor; __le16 product; - __le16 version; + __le16 version; // TODO - remove after Dec demo. __u8 vendor_stringid; __u8 product_stringid; __le64 unique_id; -- cgit v0.10.2 From aa26351d0bb5b3ecf9bccacc9b05209b3d2af8ca Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 10 Dec 2014 08:43:33 -0600 Subject: greybus: define GB_OP_NONEXISTENT The i2c protocol needs a way to indicate an i2c device doesn't exist (which is not necessarily an error). Define GB_OP_NONEXISTENT to indicate this, and updating the status<->errno mapping functions accordingly. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 046ed2a..742eccc 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -396,6 +396,8 @@ static int gb_operation_status_map(u8 status) return -EINVAL; case GB_OP_RETRY: return -EAGAIN; + case GB_OP_NONEXISTENT: + return -ENODEV; case GB_OP_MALFUNCTION: return -EILSEQ; case GB_OP_UNKNOWN_ERROR: @@ -431,6 +433,8 @@ static u8 gb_operation_errno_map(int errno) return GB_OP_RETRY; case -EILSEQ: return GB_OP_MALFUNCTION; + case -ENODEV: + return GB_OP_NONEXISTENT; case -EIO: default: return GB_OP_UNKNOWN_ERROR; diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index a173aa9..1ade52b 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -34,6 +34,7 @@ enum gb_operation_result { GB_OP_OVERFLOW = 0x05, GB_OP_INVALID = 0x06, GB_OP_RETRY = 0x07, + GB_OP_NONEXISTENT = 0x08, GB_OP_UNKNOWN_ERROR = 0xfe, GB_OP_MALFUNCTION = 0xff, }; -- cgit v0.10.2 From 7de3e650fb736bf7c40e20f5dc866c544376119c Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 10 Dec 2014 14:50:48 -0600 Subject: greybus: ENODEV can be an expected error too When probing for i2c devices, a read transfer operation can be used. In this case, it is expected that some devices will not be found, so ENODEV is an expected failure. Don't issue a warning if the return value is -ENODEV. Note: I anticipate we might have to be more precise in identifying this specific case, but for now this eliminates a bogus warning when probing i2c devices. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index f63b60e..4ef6ea1 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -276,6 +276,14 @@ static void gb_i2c_transfer_response(struct i2c_msg *msgs, u32 msg_count, } } +/* + * Some i2c transfer operations return results that are expected. + */ +static bool gb_i2c_expected_transfer_error(int errno) +{ + return errno == -EAGAIN || errno == -ENODEV; +} + static int gb_i2c_transfer_operation(struct gb_i2c_device *gb_i2c_dev, struct i2c_msg *msgs, u32 msg_count) { @@ -294,7 +302,7 @@ static int gb_i2c_transfer_operation(struct gb_i2c_device *gb_i2c_dev, response = operation->response->payload; gb_i2c_transfer_response(msgs, msg_count, response); ret = msg_count; - } else if (ret != -EAGAIN) { + } else if (!gb_i2c_expected_transfer_error(ret)) { pr_err("transfer operation failed (%d)\n", ret); } gb_operation_destroy(operation); -- cgit v0.10.2 From 0a9c4d70d372a85252c00a94cd45622b657397be Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 11 Dec 2014 16:48:38 -0600 Subject: greybus: switch cport id used for sends In talking with Perry today I learned that the CPort id expected to supplied over the HSIC interface to the APB is different from the way I understood it. My understanding was that the CPort id to supply always specified the CPort id on the other end of a connection. However, Perry says the mapping between local CPort id and remote CPort id (and device id) is done by the host UniPro interface. So whether sending or receiving data, the CPort id that the Greybus code should supply to the AP Bridge is the one representing the AP side of a connection. This patch fixes this. The receive side already used that CPort id; it's only the sending code that needed to be changed. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index f551907..2776997 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -190,7 +190,7 @@ static struct urb *next_free_urb(struct es1_ap_dev *es1, gfp_t gfp_mask) * error otherwise. If the caller wishes to cancel the in-flight * buffer, it must supply the returned cookie to the cancel routine. */ -static void *buffer_send(struct greybus_host_device *hd, u16 dest_cport_id, +static void *buffer_send(struct greybus_host_device *hd, u16 cport_id, void *buffer, size_t buffer_size, gfp_t gfp_mask) { struct es1_ap_dev *es1 = hd_to_es1(hd); @@ -216,17 +216,16 @@ static void *buffer_send(struct greybus_host_device *hd, u16 dest_cport_id, * of where the data should be sent. Do one last check of * the target CPort id before filling it in. */ - if (dest_cport_id == CPORT_ID_BAD) { + if (cport_id == CPORT_ID_BAD) { pr_err("request to send inbound data buffer\n"); return ERR_PTR(-EINVAL); } - if (dest_cport_id > (u16)U8_MAX) { - pr_err("dest_cport_id (%hd) is out of range for ES1\n", - dest_cport_id); + if (cport_id > (u16)U8_MAX) { + pr_err("cport_id (%hd) is out of range for ES1\n", cport_id); return ERR_PTR(-EINVAL); } /* OK, the destination is fine; record it in the transfer buffer */ - *transfer_buffer = dest_cport_id; + *transfer_buffer = cport_id; /* Find a free urb */ urb = next_free_urb(es1, gfp_mask); @@ -393,8 +392,8 @@ static void cport_in_callback(struct urb *urb) } /* - * The CPort number is the first byte of the data stream, the rest of - * the stream is "real" data + * Our CPort number is the first byte of the data stream, + * the rest of the stream is "real" data */ data = urb->transfer_buffer; cport_id = (u16)data[0]; diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 742eccc..6c815d2 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -167,13 +167,12 @@ static int gb_message_send(struct gb_message *message) { size_t message_size = sizeof(*message->header) + message->payload_size; struct gb_connection *connection = message->operation->connection; - u16 dest_cport_id = connection->interface_cport_id; int ret = 0; void *cookie; mutex_lock(&gb_message_mutex); cookie = connection->hd->driver->buffer_send(connection->hd, - dest_cport_id, + connection->hd_cport_id, message->header, message_size, GFP_KERNEL); -- cgit v0.10.2 From 3763f960a497fed19666dfd3366e28d6bc12b2c2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 11 Dec 2014 17:10:52 -0500 Subject: greybus: uart-gb.c: don't include module.h No need to specifically include the greybus module.h here, greybus.h already does so and we will be renaming it soon. Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index fad8635..8599da2 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -28,7 +28,6 @@ #include #include "greybus.h" -#include "module.h" #define GB_NUM_MINORS 255 /* 255 is enough for anyone... */ #define GB_NAME "ttyGB" -- cgit v0.10.2 From 708c126695611f2028aaa152398c75a03aeb1344 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 11 Dec 2014 17:10:53 -0500 Subject: greybus: module versions: remove them We removed the module version from the spec, so remove them from the code as well. It's still in the manifest as we need to sync with gbsim / firmware when we do that, which will happen sometime in the next weeks. Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 28abd2a..57cd594 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -273,7 +273,6 @@ static bool gb_manifest_parse_module(struct gb_module *gmod, gmod->vendor = le16_to_cpu(desc_module->vendor); gmod->product = le16_to_cpu(desc_module->product); - gmod->version = le16_to_cpu(desc_module->version); gmod->unique_id = le64_to_cpu(desc_module->unique_id); /* Release the module descriptor, now that we're done with it */ diff --git a/drivers/staging/greybus/module.h b/drivers/staging/greybus/module.h index 9e5358b..facc8ba 100644 --- a/drivers/staging/greybus/module.h +++ b/drivers/staging/greybus/module.h @@ -23,7 +23,6 @@ struct gb_module { /* Information taken from the manifest module descriptor */ u16 vendor; u16 product; - u16 version; char *vendor_string; char *product_string; u64 unique_id; diff --git a/drivers/staging/greybus/sysfs.c b/drivers/staging/greybus/sysfs.c index 44b0c70..f9d56e1 100644 --- a/drivers/staging/greybus/sysfs.c +++ b/drivers/staging/greybus/sysfs.c @@ -32,7 +32,6 @@ static DEVICE_ATTR_RO(module_##field) gb_module_attr(vendor, x); gb_module_attr(product, x); -gb_module_attr(version, x); gb_module_attr(unique_id, llX); gb_module_attr(vendor_string, s); gb_module_attr(product_string, s); @@ -40,7 +39,6 @@ gb_module_attr(product_string, s); static struct attribute *module_attrs[] = { &dev_attr_module_vendor.attr, &dev_attr_module_product.attr, - &dev_attr_module_version.attr, &dev_attr_module_unique_id.attr, &dev_attr_module_vendor_string.attr, &dev_attr_module_product_string.attr, -- cgit v0.10.2 From 1cd9ba1477f25e9137403162092452f176dd30b4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 11 Dec 2014 17:10:54 -0500 Subject: greybus: module: remove obsolete gb_tty pointer We aren't using this anymore, so remove gb_tty from struct gb_module. Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index f72e6ae..c424a5a 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -132,8 +132,6 @@ void gb_module_destroy(struct gb_module *gmod) list_del(&gmod->links); spin_unlock_irq(&gb_modules_lock); - /* XXX Do something with gmod->gb_tty */ - gb_interface_destroy(gmod); kfree(gmod->product_string); diff --git a/drivers/staging/greybus/module.h b/drivers/staging/greybus/module.h index facc8ba..2fdca57 100644 --- a/drivers/staging/greybus/module.h +++ b/drivers/staging/greybus/module.h @@ -28,8 +28,6 @@ struct gb_module { u64 unique_id; struct greybus_host_device *hd; - - struct gb_tty *gb_tty; }; #define to_gb_module(d) container_of(d, struct gb_module, dev) -- cgit v0.10.2 From e50522209a2e86ffac2d8c9a99c0979914cff5dd Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 11 Dec 2014 17:10:55 -0500 Subject: greybus: interface_block: rename module.[c|h] to interface_block.[c|h] "modules" in the driver model here, are really "interface blocks" as that is what they are physically tied to. So rename the files before we start changing the code to make it obvious what is going on. Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 4fa9b3f..41186b7 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -3,7 +3,7 @@ greybus-y := core.o \ debugfs.o \ ap.o \ manifest.o \ - module.o \ + interface_block.o \ interface.o \ connection.o \ protocol.o \ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 11f4e55..101b711 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -23,7 +23,7 @@ #include "greybus_id.h" #include "greybus_manifest.h" #include "manifest.h" -#include "module.h" +#include "interface_block.h" #include "interface.h" #include "connection.h" #include "protocol.h" diff --git a/drivers/staging/greybus/interface_block.c b/drivers/staging/greybus/interface_block.c new file mode 100644 index 0000000..c424a5a --- /dev/null +++ b/drivers/staging/greybus/interface_block.c @@ -0,0 +1,201 @@ +/* + * Greybus modules + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ + +#include "greybus.h" + +/* XXX This could be per-host device */ +static DEFINE_SPINLOCK(gb_modules_lock); + +static int gb_module_match_one_id(struct gb_module *gmod, + const struct greybus_module_id *id) +{ + if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_VENDOR) && + (id->vendor != gmod->vendor)) + return 0; + + if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_PRODUCT) && + (id->product != gmod->product)) + return 0; + + if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_SERIAL) && + (id->unique_id != gmod->unique_id)) + return 0; + + return 1; +} + +const struct greybus_module_id *gb_module_match_id(struct gb_module *gmod, + const struct greybus_module_id *id) +{ + if (id == NULL) + return NULL; + + for (; id->vendor || id->product || id->unique_id || + id->driver_info; id++) { + if (gb_module_match_one_id(gmod, id)) + return id; + } + + return NULL; +} + +struct gb_module *gb_module_find(struct greybus_host_device *hd, u8 module_id) +{ + struct gb_module *module; + + list_for_each_entry(module, &hd->modules, links) + if (module->module_id == module_id) + return module; + + return NULL; +} + +static void greybus_module_release(struct device *dev) +{ + struct gb_module *gmod = to_gb_module(dev); + + kfree(gmod); +} + +struct device_type greybus_module_type = { + .name = "greybus_module", + .release = greybus_module_release, +}; + +/* + * A Greybus module represents a user-replicable component on an Ara + * phone. + * + * Create a gb_module structure to represent a discovered module. + * The position within the Endo is encoded in the "module_id" argument. + * Returns a pointer to the new module or a null pointer if a + * failure occurs due to memory exhaustion. + */ +struct gb_module *gb_module_create(struct greybus_host_device *hd, u8 module_id) +{ + struct gb_module *gmod; + int retval; + + gmod = gb_module_find(hd, module_id); + if (gmod) { + dev_err(hd->parent, "Duplicate module id %d will not be created\n", + module_id); + return NULL; + } + + gmod = kzalloc(sizeof(*gmod), GFP_KERNEL); + if (!gmod) + return NULL; + + gmod->hd = hd; /* XXX refcount? */ + gmod->module_id = module_id; + INIT_LIST_HEAD(&gmod->interfaces); + + gmod->dev.parent = hd->parent; + gmod->dev.bus = &greybus_bus_type; + gmod->dev.type = &greybus_module_type; + gmod->dev.groups = greybus_module_groups; + gmod->dev.dma_mask = hd->parent->dma_mask; + device_initialize(&gmod->dev); + dev_set_name(&gmod->dev, "%d", module_id); + + retval = device_add(&gmod->dev); + if (retval) { + pr_err("failed to add module device for id 0x%02hhx\n", + module_id); + put_device(&gmod->dev); + kfree(gmod); + return NULL; + } + + spin_lock_irq(&gb_modules_lock); + list_add_tail(&gmod->links, &hd->modules); + spin_unlock_irq(&gb_modules_lock); + + return gmod; +} + +/* + * Tear down a previously set up module. + */ +void gb_module_destroy(struct gb_module *gmod) +{ + if (WARN_ON(!gmod)) + return; + + spin_lock_irq(&gb_modules_lock); + list_del(&gmod->links); + spin_unlock_irq(&gb_modules_lock); + + gb_interface_destroy(gmod); + + kfree(gmod->product_string); + kfree(gmod->vendor_string); + /* kref_put(module->hd); */ + + device_del(&gmod->dev); +} + +/** + * gb_add_module + * + * Pass in a buffer that _should_ contain a Greybus module manifest + * and register a greybus device structure with the kernel core. + */ +void gb_add_module(struct greybus_host_device *hd, u8 module_id, + u8 *data, int size) +{ + struct gb_module *gmod; + + gmod = gb_module_create(hd, module_id); + if (!gmod) { + dev_err(hd->parent, "failed to create module\n"); + return; + } + + /* + * Parse the manifest and build up our data structures + * representing what's in it. + */ + if (!gb_manifest_parse(gmod, data, size)) { + dev_err(hd->parent, "manifest error\n"); + goto err_module; + } + + /* + * XXX + * We've successfully parsed the manifest. Now we need to + * allocate CPort Id's for connecting to the CPorts found on + * other modules. For each of these, establish a connection + * between the local and remote CPorts (including + * configuring the switch to allow them to communicate). + */ + + return; + +err_module: + gb_module_destroy(gmod); +} + +void gb_remove_module(struct greybus_host_device *hd, u8 module_id) +{ + struct gb_module *gmod = gb_module_find(hd, module_id); + + if (gmod) + gb_module_destroy(gmod); + else + dev_err(hd->parent, "module id %d not found\n", module_id); +} + +void gb_remove_modules(struct greybus_host_device *hd) +{ + struct gb_module *gmod, *temp; + + list_for_each_entry_safe(gmod, temp, &hd->modules, links) + gb_module_destroy(gmod); +} diff --git a/drivers/staging/greybus/interface_block.h b/drivers/staging/greybus/interface_block.h new file mode 100644 index 0000000..2fdca57 --- /dev/null +++ b/drivers/staging/greybus/interface_block.h @@ -0,0 +1,55 @@ +/* + * Greybus modules + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ + +#ifndef __MODULE_H +#define __MODULE_H + +/* Increase these values if needed */ +#define MAX_CPORTS_PER_MODULE 10 +#define MAX_STRINGS_PER_MODULE 10 + +struct gb_module { + struct device dev; + + struct list_head interfaces; + struct list_head links; /* greybus_host_device->modules */ + u8 module_id; /* Physical location within the Endo */ + + /* Information taken from the manifest module descriptor */ + u16 vendor; + u16 product; + char *vendor_string; + char *product_string; + u64 unique_id; + + struct greybus_host_device *hd; +}; +#define to_gb_module(d) container_of(d, struct gb_module, dev) + +static inline void +gb_module_set_drvdata(struct gb_module *gmod, void *data) +{ + dev_set_drvdata(&gmod->dev, data); +} + +static inline void *gb_module_get_drvdata(struct gb_module *gmod) +{ + return dev_get_drvdata(&gmod->dev); +} + +const struct greybus_module_id *gb_module_match_id(struct gb_module *gmod, + const struct greybus_module_id *id); + +struct gb_module *gb_module_create(struct greybus_host_device *hd, + u8 module_id); +void gb_module_destroy(struct gb_module *module); + +struct gb_module *gb_module_find(struct greybus_host_device *hd, + u8 module_id); + +#endif /* __MODULE_H */ diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c deleted file mode 100644 index c424a5a..0000000 --- a/drivers/staging/greybus/module.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Greybus modules - * - * Copyright 2014 Google Inc. - * - * Released under the GPLv2 only. - */ - -#include "greybus.h" - -/* XXX This could be per-host device */ -static DEFINE_SPINLOCK(gb_modules_lock); - -static int gb_module_match_one_id(struct gb_module *gmod, - const struct greybus_module_id *id) -{ - if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_VENDOR) && - (id->vendor != gmod->vendor)) - return 0; - - if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_PRODUCT) && - (id->product != gmod->product)) - return 0; - - if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_SERIAL) && - (id->unique_id != gmod->unique_id)) - return 0; - - return 1; -} - -const struct greybus_module_id *gb_module_match_id(struct gb_module *gmod, - const struct greybus_module_id *id) -{ - if (id == NULL) - return NULL; - - for (; id->vendor || id->product || id->unique_id || - id->driver_info; id++) { - if (gb_module_match_one_id(gmod, id)) - return id; - } - - return NULL; -} - -struct gb_module *gb_module_find(struct greybus_host_device *hd, u8 module_id) -{ - struct gb_module *module; - - list_for_each_entry(module, &hd->modules, links) - if (module->module_id == module_id) - return module; - - return NULL; -} - -static void greybus_module_release(struct device *dev) -{ - struct gb_module *gmod = to_gb_module(dev); - - kfree(gmod); -} - -struct device_type greybus_module_type = { - .name = "greybus_module", - .release = greybus_module_release, -}; - -/* - * A Greybus module represents a user-replicable component on an Ara - * phone. - * - * Create a gb_module structure to represent a discovered module. - * The position within the Endo is encoded in the "module_id" argument. - * Returns a pointer to the new module or a null pointer if a - * failure occurs due to memory exhaustion. - */ -struct gb_module *gb_module_create(struct greybus_host_device *hd, u8 module_id) -{ - struct gb_module *gmod; - int retval; - - gmod = gb_module_find(hd, module_id); - if (gmod) { - dev_err(hd->parent, "Duplicate module id %d will not be created\n", - module_id); - return NULL; - } - - gmod = kzalloc(sizeof(*gmod), GFP_KERNEL); - if (!gmod) - return NULL; - - gmod->hd = hd; /* XXX refcount? */ - gmod->module_id = module_id; - INIT_LIST_HEAD(&gmod->interfaces); - - gmod->dev.parent = hd->parent; - gmod->dev.bus = &greybus_bus_type; - gmod->dev.type = &greybus_module_type; - gmod->dev.groups = greybus_module_groups; - gmod->dev.dma_mask = hd->parent->dma_mask; - device_initialize(&gmod->dev); - dev_set_name(&gmod->dev, "%d", module_id); - - retval = device_add(&gmod->dev); - if (retval) { - pr_err("failed to add module device for id 0x%02hhx\n", - module_id); - put_device(&gmod->dev); - kfree(gmod); - return NULL; - } - - spin_lock_irq(&gb_modules_lock); - list_add_tail(&gmod->links, &hd->modules); - spin_unlock_irq(&gb_modules_lock); - - return gmod; -} - -/* - * Tear down a previously set up module. - */ -void gb_module_destroy(struct gb_module *gmod) -{ - if (WARN_ON(!gmod)) - return; - - spin_lock_irq(&gb_modules_lock); - list_del(&gmod->links); - spin_unlock_irq(&gb_modules_lock); - - gb_interface_destroy(gmod); - - kfree(gmod->product_string); - kfree(gmod->vendor_string); - /* kref_put(module->hd); */ - - device_del(&gmod->dev); -} - -/** - * gb_add_module - * - * Pass in a buffer that _should_ contain a Greybus module manifest - * and register a greybus device structure with the kernel core. - */ -void gb_add_module(struct greybus_host_device *hd, u8 module_id, - u8 *data, int size) -{ - struct gb_module *gmod; - - gmod = gb_module_create(hd, module_id); - if (!gmod) { - dev_err(hd->parent, "failed to create module\n"); - return; - } - - /* - * Parse the manifest and build up our data structures - * representing what's in it. - */ - if (!gb_manifest_parse(gmod, data, size)) { - dev_err(hd->parent, "manifest error\n"); - goto err_module; - } - - /* - * XXX - * We've successfully parsed the manifest. Now we need to - * allocate CPort Id's for connecting to the CPorts found on - * other modules. For each of these, establish a connection - * between the local and remote CPorts (including - * configuring the switch to allow them to communicate). - */ - - return; - -err_module: - gb_module_destroy(gmod); -} - -void gb_remove_module(struct greybus_host_device *hd, u8 module_id) -{ - struct gb_module *gmod = gb_module_find(hd, module_id); - - if (gmod) - gb_module_destroy(gmod); - else - dev_err(hd->parent, "module id %d not found\n", module_id); -} - -void gb_remove_modules(struct greybus_host_device *hd) -{ - struct gb_module *gmod, *temp; - - list_for_each_entry_safe(gmod, temp, &hd->modules, links) - gb_module_destroy(gmod); -} diff --git a/drivers/staging/greybus/module.h b/drivers/staging/greybus/module.h deleted file mode 100644 index 2fdca57..0000000 --- a/drivers/staging/greybus/module.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Greybus modules - * - * Copyright 2014 Google Inc. - * - * Released under the GPLv2 only. - */ - -#ifndef __MODULE_H -#define __MODULE_H - -/* Increase these values if needed */ -#define MAX_CPORTS_PER_MODULE 10 -#define MAX_STRINGS_PER_MODULE 10 - -struct gb_module { - struct device dev; - - struct list_head interfaces; - struct list_head links; /* greybus_host_device->modules */ - u8 module_id; /* Physical location within the Endo */ - - /* Information taken from the manifest module descriptor */ - u16 vendor; - u16 product; - char *vendor_string; - char *product_string; - u64 unique_id; - - struct greybus_host_device *hd; -}; -#define to_gb_module(d) container_of(d, struct gb_module, dev) - -static inline void -gb_module_set_drvdata(struct gb_module *gmod, void *data) -{ - dev_set_drvdata(&gmod->dev, data); -} - -static inline void *gb_module_get_drvdata(struct gb_module *gmod) -{ - return dev_get_drvdata(&gmod->dev); -} - -const struct greybus_module_id *gb_module_match_id(struct gb_module *gmod, - const struct greybus_module_id *id); - -struct gb_module *gb_module_create(struct greybus_host_device *hd, - u8 module_id); -void gb_module_destroy(struct gb_module *module); - -struct gb_module *gb_module_find(struct greybus_host_device *hd, - u8 module_id); - -#endif /* __MODULE_H */ -- cgit v0.10.2 From 4ec7b07915523aa19ec31ec7e07cb8d903d39526 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 11 Dec 2014 17:10:56 -0500 Subject: greybus: interface_block: s/gb_module/gb_interface_block/ Rename struct gb_module to struct gb_interface_block It's a complex rename, some functions got their name changed where needed, but primarily this change is focused on the structure and where it is used. Future changes will clean up the remaining usages of the term "module" in individual changes, this one spanned the whole subsystem so do it all at once. Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 3536717..89debab 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -123,7 +123,7 @@ static void svc_handshake(struct svc_function_handshake *handshake, static void svc_management(struct svc_function_unipro_management *management, int payload_length, struct greybus_host_device *hd) { - struct gb_module *module; + struct gb_interface_block *gb_ib; int ret; if (payload_length != sizeof(*management)) { @@ -138,18 +138,18 @@ static void svc_management(struct svc_function_unipro_management *management, hd->device_id = management->ap_id.device_id; break; case SVC_MANAGEMENT_LINK_UP: - module = gb_module_find(hd, management->link_up.module_id); - if (!module) { + gb_ib = gb_ib_find(hd, management->link_up.module_id); + if (!gb_ib) { dev_err(hd->parent, "Module ID %d not found\n", management->link_up.module_id); return; } - ret = gb_interface_init(module, + ret = gb_interface_init(gb_ib, management->link_up.interface_id, management->link_up.device_id); if (ret) dev_err(hd->parent, "error %d initializing " - "module %hhu interface %hhu\n", + "interface block %hhu interface %hhu\n", ret, management->link_up.module_id, management->link_up.interface_id); break; diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index f469a8d..e4a5a85 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -340,7 +340,7 @@ static int gb_battery_connection_init(struct gb_connection *connection) b->num_properties = ARRAY_SIZE(battery_props), b->get_property = get_property, - retval = power_supply_register(&connection->interface->gmod->dev, b); + retval = power_supply_register(&connection->interface->gb_ib->dev, b); if (retval) { kfree(gb); return retval; diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index e59a777..7d5f461 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -155,7 +155,7 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, return NULL; } - hd = interface->gmod->hd; + hd = interface->gb_ib->hd; connection->hd = hd; if (!gb_connection_hd_cport_id_alloc(connection)) { gb_protocol_put(connection->protocol); @@ -236,7 +236,7 @@ void gb_connection_err(struct gb_connection *connection, const char *fmt, ...) vaf.va = &args; pr_err("greybus: [%hhu:%hhu:%hu]: %pV\n", - connection->interface->gmod->module_id, + connection->interface->gb_ib->module_id, connection->interface->id, connection->interface_cport_id, &vaf); diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 9203ebd..31460ab 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -33,10 +33,10 @@ EXPORT_SYMBOL_GPL(greybus_disabled); static int greybus_module_match(struct device *dev, struct device_driver *drv) { struct greybus_driver *driver = to_greybus_driver(drv); - struct gb_module *gmod = to_gb_module(dev); + struct gb_interface_block *gb_ib = to_gb_interface_block(dev); const struct greybus_module_id *id; - id = gb_module_match_id(gmod, driver->id_table); + id = gb_ib_match_id(gb_ib, driver->id_table); if (id) return 1; /* FIXME - Dynamic ids? */ @@ -45,19 +45,19 @@ static int greybus_module_match(struct device *dev, struct device_driver *drv) static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) { - struct gb_module *gmod = NULL; + struct gb_interface_block *gb_ib = NULL; struct gb_interface *interface = NULL; struct gb_connection *connection = NULL; - if (is_gb_module(dev)) { - gmod = to_gb_module(dev); + if (is_gb_interface_block(dev)) { + gb_ib = to_gb_interface_block(dev); } else if (is_gb_interface(dev)) { interface = to_gb_interface(dev); - gmod = interface->gmod; + gb_ib = interface->gb_ib; } else if (is_gb_connection(dev)) { connection = to_gb_connection(dev); interface = connection->interface; - gmod = interface->gmod; + gb_ib = interface->gb_ib; } else { dev_WARN(dev, "uevent for unknown greybus device \"type\"!\n"); return -EINVAL; @@ -93,16 +93,16 @@ struct bus_type greybus_bus_type = { static int greybus_probe(struct device *dev) { struct greybus_driver *driver = to_greybus_driver(dev->driver); - struct gb_module *gmod = to_gb_module(dev); + struct gb_interface_block *gb_ib = to_gb_interface_block(dev); const struct greybus_module_id *id; int retval; /* match id */ - id = gb_module_match_id(gmod, driver->id_table); + id = gb_ib_match_id(gb_ib, driver->id_table); if (!id) return -ENODEV; - retval = driver->probe(gmod, id); + retval = driver->probe(gb_ib, id); if (retval) return retval; @@ -112,9 +112,9 @@ static int greybus_probe(struct device *dev) static int greybus_remove(struct device *dev) { struct greybus_driver *driver = to_greybus_driver(dev->driver); - struct gb_module *gmod = to_gb_module(dev); + struct gb_interface_block *gb_ib = to_gb_interface_block(dev); - driver->disconnect(gmod); + driver->disconnect(gb_ib); return 0; } diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 101b711..84516cb 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -118,12 +118,12 @@ void greybus_remove_hd(struct greybus_host_device *hd); struct greybus_driver { const char *name; - int (*probe)(struct gb_module *gmod, + int (*probe)(struct gb_interface_block *gb_ib, const struct greybus_module_id *id); - void (*disconnect)(struct gb_module *gmod); + void (*disconnect)(struct gb_interface_block *gb_ib); - int (*suspend)(struct gb_module *gmod, pm_message_t message); - int (*resume)(struct gb_module *gmod); + int (*suspend)(struct gb_interface_block *gb_ib, pm_message_t message); + int (*resume)(struct gb_interface_block *gb_ib); const struct greybus_module_id *id_table; @@ -175,13 +175,13 @@ void gb_uart_device_exit(struct gb_connection *connection); int svc_set_route_send(struct gb_interface *interface, struct greybus_host_device *hd); -extern struct device_type greybus_module_type; +extern struct device_type greybus_interface_block_type; extern struct device_type greybus_interface_type; extern struct device_type greybus_connection_type; -static inline int is_gb_module(const struct device *dev) +static inline int is_gb_interface_block(const struct device *dev) { - return dev->type == &greybus_module_type; + return dev->type == &greybus_interface_block_type; } static inline int is_gb_interface(const struct device *dev) diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 38c104f..0108100 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -52,7 +52,7 @@ static DEFINE_SPINLOCK(gb_interfaces_lock); * pointer if a failure occurs due to memory exhaustion. */ struct gb_interface * -gb_interface_create(struct gb_module *gmod, u8 interface_id) +gb_interface_create(struct gb_interface_block *gb_ib, u8 interface_id) { struct gb_interface *interface; int retval; @@ -61,19 +61,19 @@ gb_interface_create(struct gb_module *gmod, u8 interface_id) if (!interface) return NULL; - interface->gmod = gmod; + interface->gb_ib = gb_ib; interface->id = interface_id; interface->device_id = 0xff; /* Invalid device id to start with */ INIT_LIST_HEAD(&interface->connections); /* Build up the interface device structures and register it with the * driver core */ - interface->dev.parent = &gmod->dev; + interface->dev.parent = &gb_ib->dev; interface->dev.bus = &greybus_bus_type; interface->dev.type = &greybus_interface_type; interface->dev.groups = interface_groups; device_initialize(&interface->dev); - dev_set_name(&interface->dev, "%d:%d", gmod->module_id, interface_id); + dev_set_name(&interface->dev, "%d:%d", gb_ib->module_id, interface_id); retval = device_add(&interface->dev); if (retval) { @@ -85,7 +85,7 @@ gb_interface_create(struct gb_module *gmod, u8 interface_id) } spin_lock_irq(&gb_interfaces_lock); - list_add_tail(&interface->links, &gmod->interfaces); + list_add_tail(&interface->links, &gb_ib->interfaces); spin_unlock_irq(&gb_interfaces_lock); return interface; @@ -94,16 +94,16 @@ gb_interface_create(struct gb_module *gmod, u8 interface_id) /* * Tear down a previously set up interface. */ -void gb_interface_destroy(struct gb_module *gmod) +void gb_interface_destroy(struct gb_interface_block *gb_ib) { struct gb_interface *interface; struct gb_interface *temp; - if (WARN_ON(!gmod)) + if (WARN_ON(!gb_ib)) return; spin_lock_irq(&gb_interfaces_lock); - list_for_each_entry_safe(interface, temp, &gmod->interfaces, links) { + list_for_each_entry_safe(interface, temp, &gb_ib->interfaces, links) { list_del(&interface->links); gb_interface_connections_exit(interface); device_del(&interface->dev); @@ -111,28 +111,28 @@ void gb_interface_destroy(struct gb_module *gmod) spin_unlock_irq(&gb_interfaces_lock); } -int gb_interface_init(struct gb_module *gmod, u8 interface_id, u8 device_id) +int gb_interface_init(struct gb_interface_block *gb_ib, u8 interface_id, u8 device_id) { struct gb_interface *interface; int ret; - interface = gb_interface_find(gmod, interface_id); + interface = gb_interface_find(gb_ib, interface_id); if (!interface) { - dev_err(gmod->hd->parent, "module %hhu not found\n", + dev_err(gb_ib->hd->parent, "module %hhu not found\n", interface_id); return -ENOENT; } interface->device_id = device_id; - ret = svc_set_route_send(interface, gmod->hd); + ret = svc_set_route_send(interface, gb_ib->hd); if (ret) { - dev_err(gmod->hd->parent, "failed to set route (%d)\n", ret); + dev_err(gb_ib->hd->parent, "failed to set route (%d)\n", ret); return ret; } ret = gb_interface_connections_init(interface); if (ret) { - dev_err(gmod->hd->parent, "module interface init error %d\n", + dev_err(gb_ib->hd->parent, "module interface init error %d\n", ret); /* XXX clear route */ return ret; @@ -141,13 +141,13 @@ int gb_interface_init(struct gb_module *gmod, u8 interface_id, u8 device_id) return 0; } -struct gb_interface *gb_interface_find(struct gb_module *module, +struct gb_interface *gb_interface_find(struct gb_interface_block *gb_ib, u8 interface_id) { struct gb_interface *interface; spin_lock_irq(&gb_interfaces_lock); - list_for_each_entry(interface, &module->interfaces, links) + list_for_each_entry(interface, &gb_ib->interfaces, links) if (interface->id == interface_id) { spin_unlock_irq(&gb_interfaces_lock); return interface; diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index bfd1781..2f435fd 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -13,7 +13,7 @@ struct gb_interface { struct device dev; - struct gb_module *gmod; + struct gb_interface_block *gb_ib; u8 id; u8 device_id; struct list_head connections; @@ -22,11 +22,11 @@ struct gb_interface { }; #define to_gb_interface(d) container_of(d, struct gb_interface, dev) -struct gb_interface *gb_interface_create(struct gb_module *gmod, u8 module_id); -void gb_interface_destroy(struct gb_module *gmod); -int gb_interface_init(struct gb_module *gmod, u8 module_id, u8 device_id); +struct gb_interface *gb_interface_create(struct gb_interface_block *gb_ib, u8 module_id); +void gb_interface_destroy(struct gb_interface_block *gb_ib); +int gb_interface_init(struct gb_interface_block *gb_ib, u8 module_id, u8 device_id); -struct gb_interface *gb_interface_find(struct gb_module *gmod, u8 interface_id); +struct gb_interface *gb_interface_find(struct gb_interface_block *gb_ib, u8 interface_id); int gb_interface_connections_init(struct gb_interface *interface); void gb_interface_connections_exit(struct gb_interface *interface); diff --git a/drivers/staging/greybus/interface_block.c b/drivers/staging/greybus/interface_block.c index c424a5a..10b3f50 100644 --- a/drivers/staging/greybus/interface_block.c +++ b/drivers/staging/greybus/interface_block.c @@ -11,25 +11,25 @@ /* XXX This could be per-host device */ static DEFINE_SPINLOCK(gb_modules_lock); -static int gb_module_match_one_id(struct gb_module *gmod, +static int gb_module_match_one_id(struct gb_interface_block *gb_ib, const struct greybus_module_id *id) { if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_VENDOR) && - (id->vendor != gmod->vendor)) + (id->vendor != gb_ib->vendor)) return 0; if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_PRODUCT) && - (id->product != gmod->product)) + (id->product != gb_ib->product)) return 0; if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_SERIAL) && - (id->unique_id != gmod->unique_id)) + (id->unique_id != gb_ib->unique_id)) return 0; return 1; } -const struct greybus_module_id *gb_module_match_id(struct gb_module *gmod, +const struct greybus_module_id *gb_ib_match_id(struct gb_interface_block *gb_ib, const struct greybus_module_id *id) { if (id == NULL) @@ -37,108 +37,110 @@ const struct greybus_module_id *gb_module_match_id(struct gb_module *gmod, for (; id->vendor || id->product || id->unique_id || id->driver_info; id++) { - if (gb_module_match_one_id(gmod, id)) + if (gb_module_match_one_id(gb_ib, id)) return id; } return NULL; } -struct gb_module *gb_module_find(struct greybus_host_device *hd, u8 module_id) +struct gb_interface_block *gb_ib_find(struct greybus_host_device *hd, u8 module_id) { - struct gb_module *module; + struct gb_interface_block *gb_ib; - list_for_each_entry(module, &hd->modules, links) - if (module->module_id == module_id) - return module; + list_for_each_entry(gb_ib, &hd->modules, links) + if (gb_ib->module_id == module_id) + return gb_ib; return NULL; } -static void greybus_module_release(struct device *dev) +static void greybus_ib_release(struct device *dev) { - struct gb_module *gmod = to_gb_module(dev); + struct gb_interface_block *gb_ib = to_gb_interface_block(dev); - kfree(gmod); + kfree(gb_ib); } -struct device_type greybus_module_type = { - .name = "greybus_module", - .release = greybus_module_release, +struct device_type greybus_interface_block_type = { + .name = "greybus_interface_block", + .release = greybus_ib_release, }; /* * A Greybus module represents a user-replicable component on an Ara - * phone. + * phone. An interface block is the physical connection on that module. A + * module may have more than one interface block. * - * Create a gb_module structure to represent a discovered module. + * Create a gb_interface_block structure to represent a discovered module. * The position within the Endo is encoded in the "module_id" argument. * Returns a pointer to the new module or a null pointer if a * failure occurs due to memory exhaustion. */ -struct gb_module *gb_module_create(struct greybus_host_device *hd, u8 module_id) +static struct gb_interface_block *gb_ib_create(struct greybus_host_device *hd, + u8 module_id) { - struct gb_module *gmod; + struct gb_interface_block *gb_ib; int retval; - gmod = gb_module_find(hd, module_id); - if (gmod) { + gb_ib = gb_ib_find(hd, module_id); + if (gb_ib) { dev_err(hd->parent, "Duplicate module id %d will not be created\n", module_id); return NULL; } - gmod = kzalloc(sizeof(*gmod), GFP_KERNEL); - if (!gmod) + gb_ib = kzalloc(sizeof(*gb_ib), GFP_KERNEL); + if (!gb_ib) return NULL; - gmod->hd = hd; /* XXX refcount? */ - gmod->module_id = module_id; - INIT_LIST_HEAD(&gmod->interfaces); + gb_ib->hd = hd; /* XXX refcount? */ + gb_ib->module_id = module_id; + INIT_LIST_HEAD(&gb_ib->interfaces); - gmod->dev.parent = hd->parent; - gmod->dev.bus = &greybus_bus_type; - gmod->dev.type = &greybus_module_type; - gmod->dev.groups = greybus_module_groups; - gmod->dev.dma_mask = hd->parent->dma_mask; - device_initialize(&gmod->dev); - dev_set_name(&gmod->dev, "%d", module_id); + gb_ib->dev.parent = hd->parent; + gb_ib->dev.bus = &greybus_bus_type; + gb_ib->dev.type = &greybus_interface_block_type; + gb_ib->dev.groups = greybus_module_groups; + gb_ib->dev.dma_mask = hd->parent->dma_mask; + device_initialize(&gb_ib->dev); + dev_set_name(&gb_ib->dev, "%d", module_id); - retval = device_add(&gmod->dev); + retval = device_add(&gb_ib->dev); if (retval) { pr_err("failed to add module device for id 0x%02hhx\n", module_id); - put_device(&gmod->dev); - kfree(gmod); + put_device(&gb_ib->dev); + kfree(gb_ib); return NULL; } spin_lock_irq(&gb_modules_lock); - list_add_tail(&gmod->links, &hd->modules); + list_add_tail(&gb_ib->links, &hd->modules); spin_unlock_irq(&gb_modules_lock); - return gmod; + return gb_ib; } /* * Tear down a previously set up module. */ -void gb_module_destroy(struct gb_module *gmod) +static void gb_ib_destroy(struct gb_interface_block *gb_ib) { - if (WARN_ON(!gmod)) + if (WARN_ON(!gb_ib)) return; spin_lock_irq(&gb_modules_lock); - list_del(&gmod->links); + list_del(&gb_ib->links); spin_unlock_irq(&gb_modules_lock); - gb_interface_destroy(gmod); + gb_interface_destroy(gb_ib); - kfree(gmod->product_string); - kfree(gmod->vendor_string); + kfree(gb_ib->product_string); + kfree(gb_ib->vendor_string); /* kref_put(module->hd); */ - device_del(&gmod->dev); + device_del(&gb_ib->dev); } /** @@ -150,11 +152,11 @@ void gb_module_destroy(struct gb_module *gmod) void gb_add_module(struct greybus_host_device *hd, u8 module_id, u8 *data, int size) { - struct gb_module *gmod; + struct gb_interface_block *gb_ib; - gmod = gb_module_create(hd, module_id); - if (!gmod) { - dev_err(hd->parent, "failed to create module\n"); + gb_ib = gb_ib_create(hd, module_id); + if (!gb_ib) { + dev_err(hd->parent, "failed to create interface block\n"); return; } @@ -162,7 +164,7 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, * Parse the manifest and build up our data structures * representing what's in it. */ - if (!gb_manifest_parse(gmod, data, size)) { + if (!gb_manifest_parse(gb_ib, data, size)) { dev_err(hd->parent, "manifest error\n"); goto err_module; } @@ -179,23 +181,23 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, return; err_module: - gb_module_destroy(gmod); + gb_ib_destroy(gb_ib); } void gb_remove_module(struct greybus_host_device *hd, u8 module_id) { - struct gb_module *gmod = gb_module_find(hd, module_id); + struct gb_interface_block *gb_ib = gb_ib_find(hd, module_id); - if (gmod) - gb_module_destroy(gmod); + if (gb_ib) + gb_ib_destroy(gb_ib); else - dev_err(hd->parent, "module id %d not found\n", module_id); + dev_err(hd->parent, "interface block id %d not found\n", module_id); } void gb_remove_modules(struct greybus_host_device *hd) { - struct gb_module *gmod, *temp; + struct gb_interface_block *gb_ib, *temp; - list_for_each_entry_safe(gmod, temp, &hd->modules, links) - gb_module_destroy(gmod); + list_for_each_entry_safe(gb_ib, temp, &hd->modules, links) + gb_ib_destroy(gb_ib); } diff --git a/drivers/staging/greybus/interface_block.h b/drivers/staging/greybus/interface_block.h index 2fdca57..b751ce4 100644 --- a/drivers/staging/greybus/interface_block.h +++ b/drivers/staging/greybus/interface_block.h @@ -1,19 +1,21 @@ /* - * Greybus modules + * Greybus Interface Block code * * Copyright 2014 Google Inc. * * Released under the GPLv2 only. */ -#ifndef __MODULE_H -#define __MODULE_H +#ifndef __INTERFACE_BLOCK_H +#define __INTERFACE_BLOCK_H /* Increase these values if needed */ #define MAX_CPORTS_PER_MODULE 10 #define MAX_STRINGS_PER_MODULE 10 -struct gb_module { + +/* Greybus "public" definitions" */ +struct gb_interface_block { struct device dev; struct list_head interfaces; @@ -29,27 +31,26 @@ struct gb_module { struct greybus_host_device *hd; }; -#define to_gb_module(d) container_of(d, struct gb_module, dev) +#define to_gb_interface_block(d) container_of(d, struct gb_interface_block, dev) static inline void -gb_module_set_drvdata(struct gb_module *gmod, void *data) +gb_interface_block_set_drvdata(struct gb_interface_block *gb_ib, void *data) { - dev_set_drvdata(&gmod->dev, data); + dev_set_drvdata(&gb_ib->dev, data); } -static inline void *gb_module_get_drvdata(struct gb_module *gmod) +static inline void * +gb_interface_block_get_drvdata(struct gb_interface_block *gb_ib) { - return dev_get_drvdata(&gmod->dev); + return dev_get_drvdata(&gb_ib->dev); } -const struct greybus_module_id *gb_module_match_id(struct gb_module *gmod, - const struct greybus_module_id *id); +/* Greybus "private" definitions */ -struct gb_module *gb_module_create(struct greybus_host_device *hd, - u8 module_id); -void gb_module_destroy(struct gb_module *module); +const struct greybus_module_id *gb_ib_match_id(struct gb_interface_block *gb_ib, + const struct greybus_module_id *id); -struct gb_module *gb_module_find(struct greybus_host_device *hd, - u8 module_id); +struct gb_interface_block *gb_ib_find(struct greybus_host_device *hd, + u8 module_id); -#endif /* __MODULE_H */ +#endif /* __INTERFACE_BLOCK_H */ diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 57cd594..67aa927 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -217,7 +217,7 @@ static u32 gb_manifest_parse_cports(struct gb_interface *interface) * structures. Returns the number of interfaces set up for the * given module. */ -static u32 gb_manifest_parse_interfaces(struct gb_module *gmod) +static u32 gb_manifest_parse_interfaces(struct gb_interface_block *gb_ib) { u32 count = 0; @@ -239,7 +239,7 @@ static u32 gb_manifest_parse_interfaces(struct gb_module *gmod) /* Found one. Set up its interface structure*/ desc_interface = descriptor->data; - interface = gb_interface_create(gmod, desc_interface->id); + interface = gb_interface_create(gb_ib, desc_interface->id); if (!interface) return 0; /* Error */ @@ -256,41 +256,41 @@ static u32 gb_manifest_parse_interfaces(struct gb_module *gmod) return count; } -static bool gb_manifest_parse_module(struct gb_module *gmod, +static bool gb_manifest_parse_module(struct gb_interface_block *gb_ib, struct manifest_desc *module_desc) { struct greybus_descriptor_module *desc_module = module_desc->data; /* Handle the strings first--they can fail */ - gmod->vendor_string = gb_string_get(desc_module->vendor_stringid); - if (IS_ERR(gmod->vendor_string)) + gb_ib->vendor_string = gb_string_get(desc_module->vendor_stringid); + if (IS_ERR(gb_ib->vendor_string)) return false; - gmod->product_string = gb_string_get(desc_module->product_stringid); - if (IS_ERR(gmod->product_string)) { + gb_ib->product_string = gb_string_get(desc_module->product_stringid); + if (IS_ERR(gb_ib->product_string)) { goto out_free_vendor_string; } - gmod->vendor = le16_to_cpu(desc_module->vendor); - gmod->product = le16_to_cpu(desc_module->product); - gmod->unique_id = le64_to_cpu(desc_module->unique_id); + gb_ib->vendor = le16_to_cpu(desc_module->vendor); + gb_ib->product = le16_to_cpu(desc_module->product); + gb_ib->unique_id = le64_to_cpu(desc_module->unique_id); /* Release the module descriptor, now that we're done with it */ release_manifest_descriptor(module_desc); /* A module must have at least one interface descriptor */ - if (!gb_manifest_parse_interfaces(gmod)) { + if (!gb_manifest_parse_interfaces(gb_ib)) { pr_err("manifest interface descriptors not valid\n"); goto out_err; } return true; out_err: - kfree(gmod->product_string); - gmod->product_string = NULL; + kfree(gb_ib->product_string); + gb_ib->product_string = NULL; out_free_vendor_string: - kfree(gmod->vendor_string); - gmod->vendor_string = NULL; + kfree(gb_ib->vendor_string); + gb_ib->vendor_string = NULL; return false; } @@ -318,7 +318,7 @@ out_free_vendor_string: * * Returns true if parsing was successful, false otherwise. */ -bool gb_manifest_parse(struct gb_module *gmod, void *data, size_t size) +bool gb_manifest_parse(struct gb_interface_block *gb_ib, void *data, size_t size) { struct greybus_manifest *manifest; struct greybus_manifest_header *header; @@ -388,7 +388,7 @@ bool gb_manifest_parse(struct gb_module *gmod, void *data, size_t size) } /* Parse the module manifest, starting with the module descriptor */ - result = gb_manifest_parse_module(gmod, module_desc); + result = gb_manifest_parse_module(gb_ib, module_desc); /* * We really should have no remaining descriptors, but we diff --git a/drivers/staging/greybus/manifest.h b/drivers/staging/greybus/manifest.h index a1fe2c12..7c82a45 100644 --- a/drivers/staging/greybus/manifest.h +++ b/drivers/staging/greybus/manifest.h @@ -9,7 +9,7 @@ #ifndef __MANIFEST_H #define __MANIFEST_H -struct gb_module; -bool gb_manifest_parse(struct gb_module *gmod, void *data, size_t size); +struct gb_interface_block; +bool gb_manifest_parse(struct gb_interface_block *gb_ib, void *data, size_t size); #endif /* __MANIFEST_H */ diff --git a/drivers/staging/greybus/sysfs.c b/drivers/staging/greybus/sysfs.c index f9d56e1..28d1b8d 100644 --- a/drivers/staging/greybus/sysfs.c +++ b/drivers/staging/greybus/sysfs.c @@ -25,8 +25,8 @@ static ssize_t module_##field##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ - struct gb_module *gmod = to_gb_module(dev); \ - return sprintf(buf, "%"#type"\n", gmod->field); \ + struct gb_interface_block *gb_ib = to_gb_interface_block(dev); \ + return sprintf(buf, "%"#type"\n", gb_ib->field); \ } \ static DEVICE_ATTR_RO(module_##field) -- cgit v0.10.2 From 8ede6e36dfa88a4c0a0e66f34fb177af3beaab8f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 11 Dec 2014 17:10:57 -0500 Subject: greybus: interface_block: rename the sysfs files to not have 'module' in them The sysfs files for an interface block should not have 'module' in them. This was a hold-over from when we thought we were going to have all attributes of a "module" in one directory. Remove the prefix as it's not needed, and is confusing considering modules can not have strings or any of these attributes. Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 84516cb..632b1cd 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -167,7 +167,7 @@ int gb_debugfs_init(void); void gb_debugfs_cleanup(void); extern struct bus_type greybus_bus_type; -extern const struct attribute_group *greybus_module_groups[]; +extern const struct attribute_group *greybus_interface_block_groups[]; int gb_uart_device_init(struct gb_connection *connection); void gb_uart_device_exit(struct gb_connection *connection); diff --git a/drivers/staging/greybus/interface_block.c b/drivers/staging/greybus/interface_block.c index 10b3f50..7b18f48 100644 --- a/drivers/staging/greybus/interface_block.c +++ b/drivers/staging/greybus/interface_block.c @@ -101,7 +101,7 @@ static struct gb_interface_block *gb_ib_create(struct greybus_host_device *hd, gb_ib->dev.parent = hd->parent; gb_ib->dev.bus = &greybus_bus_type; gb_ib->dev.type = &greybus_interface_block_type; - gb_ib->dev.groups = greybus_module_groups; + gb_ib->dev.groups = greybus_interface_block_groups; gb_ib->dev.dma_mask = hd->parent->dma_mask; device_initialize(&gb_ib->dev); dev_set_name(&gb_ib->dev, "%d", module_id); diff --git a/drivers/staging/greybus/sysfs.c b/drivers/staging/greybus/sysfs.c index 28d1b8d..ae44c89 100644 --- a/drivers/staging/greybus/sysfs.c +++ b/drivers/staging/greybus/sysfs.c @@ -20,37 +20,37 @@ #include "kernel_ver.h" /* Module fields */ -#define gb_module_attr(field, type) \ -static ssize_t module_##field##_show(struct device *dev, \ +#define gb_ib_attr(field, type) \ +static ssize_t field##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ struct gb_interface_block *gb_ib = to_gb_interface_block(dev); \ return sprintf(buf, "%"#type"\n", gb_ib->field); \ } \ -static DEVICE_ATTR_RO(module_##field) - -gb_module_attr(vendor, x); -gb_module_attr(product, x); -gb_module_attr(unique_id, llX); -gb_module_attr(vendor_string, s); -gb_module_attr(product_string, s); - -static struct attribute *module_attrs[] = { - &dev_attr_module_vendor.attr, - &dev_attr_module_product.attr, - &dev_attr_module_unique_id.attr, - &dev_attr_module_vendor_string.attr, - &dev_attr_module_product_string.attr, +static DEVICE_ATTR_RO(field) + +gb_ib_attr(vendor, x); +gb_ib_attr(product, x); +gb_ib_attr(unique_id, llX); +gb_ib_attr(vendor_string, s); +gb_ib_attr(product_string, s); + +static struct attribute *interface_block_attrs[] = { + &dev_attr_vendor.attr, + &dev_attr_product.attr, + &dev_attr_unique_id.attr, + &dev_attr_vendor_string.attr, + &dev_attr_product_string.attr, NULL, }; -static struct attribute_group module_attr_grp = { - .attrs = module_attrs, +static struct attribute_group interface_block_attr_grp = { + .attrs = interface_block_attrs, }; -const struct attribute_group *greybus_module_groups[] = { - &module_attr_grp, +const struct attribute_group *greybus_interface_block_groups[] = { + &interface_block_attr_grp, NULL, }; -- cgit v0.10.2 From fc2a8fbec71fe12d58154191cc10775e2881ef1b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 11 Dec 2014 17:10:58 -0500 Subject: greybus: sysfs documentation: Document the greybus interface block sysfs files. Documentation, what, really? Yes. Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus new file mode 100644 index 0000000..cd1d812 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -0,0 +1,35 @@ +What: /sys/bus/greybus/device/.../product +Date: December 2014 +KernelVersion: 3.XX +Contact: Greg Kroah-Hartman +Description: + Product ID of a Greybus interface block. + +What: /sys/bus/greybus/device/.../product_string +Date: December 2014 +KernelVersion: 3.XX +Contact: Greg Kroah-Hartman +Description: + Product ID string of a Greybus interface block. + +What: /sys/bus/greybus/device/.../unique_id +Date: December 2014 +KernelVersion: 3.XX +Contact: Greg Kroah-Hartman +Description: + Unique ID of a Greybus interface block. + +What: /sys/bus/greybus/device/.../vendor +Date: December 2014 +KernelVersion: 3.XX +Contact: Greg Kroah-Hartman +Description: + Vendor ID of a Greybus interface block. + +What: /sys/bus/greybus/device/.../vendor_string +Date: December 2014 +KernelVersion: 3.XX +Contact: Greg Kroah-Hartman +Description: + Vendor ID string of a Greybus interface block. + -- cgit v0.10.2 From ab88eb58c7a56ded2fd3ec4b9184075ff415cad3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 11 Dec 2014 17:10:59 -0500 Subject: greybus: interface_block: move sysfs files into the interface_block.c file No need to keep these out in sysfs.c, move them into the interface_block.c file so that we can see them easier, and remove some variable definitions by taking advantage of the attribute group macro. Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 41186b7..29aa4d6 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -1,5 +1,4 @@ greybus-y := core.o \ - sysfs.o \ debugfs.o \ ap.o \ manifest.o \ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 632b1cd..b32dd61 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -167,7 +167,6 @@ int gb_debugfs_init(void); void gb_debugfs_cleanup(void); extern struct bus_type greybus_bus_type; -extern const struct attribute_group *greybus_interface_block_groups[]; int gb_uart_device_init(struct gb_connection *connection); void gb_uart_device_exit(struct gb_connection *connection); diff --git a/drivers/staging/greybus/interface_block.c b/drivers/staging/greybus/interface_block.c index 7b18f48..3f173ae 100644 --- a/drivers/staging/greybus/interface_block.c +++ b/drivers/staging/greybus/interface_block.c @@ -1,5 +1,5 @@ /* - * Greybus modules + * Greybus interface block code * * Copyright 2014 Google Inc. * @@ -8,6 +8,34 @@ #include "greybus.h" +/* interface block sysfs attributes */ +#define gb_ib_attr(field, type) \ +static ssize_t field##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct gb_interface_block *gb_ib = to_gb_interface_block(dev); \ + return sprintf(buf, "%"#type"\n", gb_ib->field); \ +} \ +static DEVICE_ATTR_RO(field) + +gb_ib_attr(vendor, x); +gb_ib_attr(product, x); +gb_ib_attr(unique_id, llX); +gb_ib_attr(vendor_string, s); +gb_ib_attr(product_string, s); + +static struct attribute *interface_block_attrs[] = { + &dev_attr_vendor.attr, + &dev_attr_product.attr, + &dev_attr_unique_id.attr, + &dev_attr_vendor_string.attr, + &dev_attr_product_string.attr, + NULL, +}; +ATTRIBUTE_GROUPS(interface_block); + + /* XXX This could be per-host device */ static DEFINE_SPINLOCK(gb_modules_lock); @@ -101,7 +129,7 @@ static struct gb_interface_block *gb_ib_create(struct greybus_host_device *hd, gb_ib->dev.parent = hd->parent; gb_ib->dev.bus = &greybus_bus_type; gb_ib->dev.type = &greybus_interface_block_type; - gb_ib->dev.groups = greybus_interface_block_groups; + gb_ib->dev.groups = interface_block_groups; gb_ib->dev.dma_mask = hd->parent->dma_mask; device_initialize(&gb_ib->dev); dev_set_name(&gb_ib->dev, "%d", module_id); diff --git a/drivers/staging/greybus/sysfs.c b/drivers/staging/greybus/sysfs.c deleted file mode 100644 index ae44c89..0000000 --- a/drivers/staging/greybus/sysfs.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Greybus sysfs file functions - * - * Copyright 2014 Google Inc. - * - * Released under the GPLv2 only. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include - -#include "greybus.h" -#include "kernel_ver.h" - -/* Module fields */ -#define gb_ib_attr(field, type) \ -static ssize_t field##_show(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct gb_interface_block *gb_ib = to_gb_interface_block(dev); \ - return sprintf(buf, "%"#type"\n", gb_ib->field); \ -} \ -static DEVICE_ATTR_RO(field) - -gb_ib_attr(vendor, x); -gb_ib_attr(product, x); -gb_ib_attr(unique_id, llX); -gb_ib_attr(vendor_string, s); -gb_ib_attr(product_string, s); - -static struct attribute *interface_block_attrs[] = { - &dev_attr_vendor.attr, - &dev_attr_product.attr, - &dev_attr_unique_id.attr, - &dev_attr_vendor_string.attr, - &dev_attr_product_string.attr, - NULL, -}; - -static struct attribute_group interface_block_attr_grp = { - .attrs = interface_block_attrs, -}; - -const struct attribute_group *greybus_interface_block_groups[] = { - &interface_block_attr_grp, - NULL, -}; - -- cgit v0.10.2 From a500a8a6ef283f47efaddde8c8b7213a76a731c5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 11 Dec 2014 17:11:00 -0500 Subject: greybus: connection: document the sysfs files Document what the sysfs files are for connections, so that people have a chance to understand what they can be used for. Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index cd1d812..b734c67 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -33,3 +33,23 @@ Contact: Greg Kroah-Hartman Description: Vendor ID string of a Greybus interface block. +What: /sys/bus/greybus/device/.../state +Date: December 2014 +KernelVersion: 3.XX +Contact: Greg Kroah-Hartman +Description: + The current state of a Greybus connection. + + It will be one of the following values: + 0 - invalid + 1 - disabled + 2 - enabled + 3 - error + 4 - destroying + +What: /sys/bus/greybus/device/.../protocol_id +Date: December 2014 +KernelVersion: 3.XX +Contact: Greg Kroah-Hartman +Description: + The protocol id of a Greybus connection. -- cgit v0.10.2 From 640f13ecc879163dd45c213fbbef8ffc825d95bb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 11 Dec 2014 17:11:01 -0500 Subject: greybus: interface: document sysfs files Yes, an interface has a device id sysfs file, so we need to document it. Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index b734c67..2491201 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -53,3 +53,10 @@ KernelVersion: 3.XX Contact: Greg Kroah-Hartman Description: The protocol id of a Greybus connection. + +What: /sys/bus/greybus/device/.../device_id +Date: December 2014 +KernelVersion: 3.XX +Contact: Greg Kroah-Hartman +Description: + The device id of a Greybus interface. -- cgit v0.10.2 From 2f0c8aa4e6710a939da64412da0bdd7bb9aa5557 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 11 Dec 2014 17:11:02 -0500 Subject: greybus: driver matching: Greybus drivers bind to interface blocks, not modules Because of this, rename greybus_module_id to greybus_interface_block_id. We still need to add a way for a "class" driver to be bound to an interface, but for now, all we really need is the vendor/product pair as the GP Bridge interface block is going to be our main user. Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 31460ab..66c54d7 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -34,7 +34,7 @@ static int greybus_module_match(struct device *dev, struct device_driver *drv) { struct greybus_driver *driver = to_greybus_driver(drv); struct gb_interface_block *gb_ib = to_gb_interface_block(dev); - const struct greybus_module_id *id; + const struct greybus_interface_block_id *id; id = gb_ib_match_id(gb_ib, driver->id_table); if (id) @@ -94,7 +94,7 @@ static int greybus_probe(struct device *dev) { struct greybus_driver *driver = to_greybus_driver(dev->driver); struct gb_interface_block *gb_ib = to_gb_interface_block(dev); - const struct greybus_module_id *id; + const struct greybus_interface_block_id *id; int retval; /* match id */ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index b32dd61..95567b8 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -119,13 +119,13 @@ struct greybus_driver { const char *name; int (*probe)(struct gb_interface_block *gb_ib, - const struct greybus_module_id *id); + const struct greybus_interface_block_id *id); void (*disconnect)(struct gb_interface_block *gb_ib); int (*suspend)(struct gb_interface_block *gb_ib, pm_message_t message); int (*resume)(struct gb_interface_block *gb_ib); - const struct greybus_module_id *id_table; + const struct greybus_interface_block_id *id_table; struct device_driver driver; }; diff --git a/drivers/staging/greybus/greybus_id.h b/drivers/staging/greybus/greybus_id.h index c6cd2e8..da70aab 100644 --- a/drivers/staging/greybus/greybus_id.h +++ b/drivers/staging/greybus/greybus_id.h @@ -9,7 +9,7 @@ #include -struct greybus_module_id { +struct greybus_interface_block_id { __u16 match_flags; __u16 vendor; __u16 product; @@ -18,9 +18,9 @@ struct greybus_module_id { kernel_ulong_t driver_info __aligned(sizeof(kernel_ulong_t)); }; -/* Used to match the greybus_module_id */ -#define GREYBUS_DEVICE_ID_MATCH_VENDOR BIT(0) -#define GREYBUS_DEVICE_ID_MATCH_PRODUCT BIT(1) -#define GREYBUS_DEVICE_ID_MATCH_SERIAL BIT(2) +/* Used to match the greybus_interface_block_id */ +#define GREYBUS_ID_MATCH_VENDOR BIT(0) +#define GREYBUS_ID_MATCH_PRODUCT BIT(1) +#define GREYBUS_ID_MATCH_SERIAL BIT(2) #endif /* __LINUX_GREYBUS_H */ diff --git a/drivers/staging/greybus/interface_block.c b/drivers/staging/greybus/interface_block.c index 3f173ae..882763d 100644 --- a/drivers/staging/greybus/interface_block.c +++ b/drivers/staging/greybus/interface_block.c @@ -39,33 +39,34 @@ ATTRIBUTE_GROUPS(interface_block); /* XXX This could be per-host device */ static DEFINE_SPINLOCK(gb_modules_lock); -static int gb_module_match_one_id(struct gb_interface_block *gb_ib, - const struct greybus_module_id *id) +static int gb_ib_match_one_id(struct gb_interface_block *gb_ib, + const struct greybus_interface_block_id *id) { - if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_VENDOR) && + if ((id->match_flags & GREYBUS_ID_MATCH_VENDOR) && (id->vendor != gb_ib->vendor)) return 0; - if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_PRODUCT) && + if ((id->match_flags & GREYBUS_ID_MATCH_PRODUCT) && (id->product != gb_ib->product)) return 0; - if ((id->match_flags & GREYBUS_DEVICE_ID_MATCH_SERIAL) && + if ((id->match_flags & GREYBUS_ID_MATCH_SERIAL) && (id->unique_id != gb_ib->unique_id)) return 0; return 1; } -const struct greybus_module_id *gb_ib_match_id(struct gb_interface_block *gb_ib, - const struct greybus_module_id *id) +const struct greybus_interface_block_id * +gb_ib_match_id(struct gb_interface_block *gb_ib, + const struct greybus_interface_block_id *id) { if (id == NULL) return NULL; for (; id->vendor || id->product || id->unique_id || id->driver_info; id++) { - if (gb_module_match_one_id(gb_ib, id)) + if (gb_ib_match_one_id(gb_ib, id)) return id; } diff --git a/drivers/staging/greybus/interface_block.h b/drivers/staging/greybus/interface_block.h index b751ce4..7a166fd 100644 --- a/drivers/staging/greybus/interface_block.h +++ b/drivers/staging/greybus/interface_block.h @@ -47,8 +47,9 @@ gb_interface_block_get_drvdata(struct gb_interface_block *gb_ib) /* Greybus "private" definitions */ -const struct greybus_module_id *gb_ib_match_id(struct gb_interface_block *gb_ib, - const struct greybus_module_id *id); +const struct greybus_interface_block_id * + gb_ib_match_id(struct gb_interface_block *gb_ib, + const struct greybus_interface_block_id *id); struct gb_interface_block *gb_ib_find(struct greybus_host_device *hd, u8 module_id); -- cgit v0.10.2 From a46e96719dc9180e80fe0cb81f4cdd3757b1e9cd Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 12 Dec 2014 12:08:42 -0600 Subject: greybus: add Linaro copyrights I was asked to add a Linaro copyright to all Greybus source files that anyone at Linaro has modified. This patch does that. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 89debab..4fa2ad9 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -2,6 +2,7 @@ * Greybus "AP" message loop handling * * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. * * Released under the GPLv2 only. */ diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index e4a5a85..3ed7639 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -2,6 +2,7 @@ * Battery driver for a Greybus module. * * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. * * Released under the GPLv2 only. */ diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 7d5f461..1658fdb 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -2,6 +2,7 @@ * Greybus connections * * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. * * Released under the GPLv2 only. */ diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 7568161..5c3fad3f 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -2,6 +2,7 @@ * Greybus connections * * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. * * Released under the GPLv2 only. */ diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 66c54d7..032710c 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -2,6 +2,7 @@ * Greybus "Core" * * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. * * Released under the GPLv2 only. */ diff --git a/drivers/staging/greybus/debugfs.c b/drivers/staging/greybus/debugfs.c index 4755a36..770b7c0 100644 --- a/drivers/staging/greybus/debugfs.c +++ b/drivers/staging/greybus/debugfs.c @@ -2,6 +2,7 @@ * Greybus debugfs code * * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. * * Released under the GPLv2 only. */ diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 2776997..41f56da 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -2,6 +2,7 @@ * Greybus "AP" USB driver * * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. * * Released under the GPLv2 only. */ diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index c573cce..152ba50 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -2,6 +2,7 @@ * GPIO Greybus driver. * * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. * * Released under the GPLv2 only. */ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 95567b8..8216c93 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -2,6 +2,7 @@ * Greybus driver and device API * * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. * * Released under the GPLv2 only. */ diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index f44f337..deff5c7 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -5,6 +5,7 @@ * details on these values and structures. * * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. * * Released under the GPLv2 and BSD licenses. */ diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index 4ef6ea1..491fac4 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -2,6 +2,7 @@ * I2C bridge driver for the Greybus "generic" I2C module. * * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. * * Released under the GPLv2 only. */ diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 0108100..742781c 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -2,6 +2,7 @@ * Greybus interfaces * * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. * * Released under the GPLv2 only. */ diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 2f435fd..c0c66b8 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -2,6 +2,7 @@ * Greybus interfaces * * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. * * Released under the GPLv2 only. */ diff --git a/drivers/staging/greybus/interface_block.c b/drivers/staging/greybus/interface_block.c index 882763d..ab4c833 100644 --- a/drivers/staging/greybus/interface_block.c +++ b/drivers/staging/greybus/interface_block.c @@ -2,6 +2,7 @@ * Greybus interface block code * * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. * * Released under the GPLv2 only. */ diff --git a/drivers/staging/greybus/interface_block.h b/drivers/staging/greybus/interface_block.h index 7a166fd..03da567 100644 --- a/drivers/staging/greybus/interface_block.h +++ b/drivers/staging/greybus/interface_block.h @@ -2,6 +2,7 @@ * Greybus Interface Block code * * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. * * Released under the GPLv2 only. */ diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index a39ceaf..66c2713 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -2,6 +2,7 @@ * Greybus kernel "version" glue logic. * * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. * * Released under the GPLv2 only. * diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 67aa927..01a69a3 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -2,6 +2,7 @@ * Greybus module manifest parsing * * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. * * Released under the GPLv2 only. */ diff --git a/drivers/staging/greybus/manifest.h b/drivers/staging/greybus/manifest.h index 7c82a45..a8316a0 100644 --- a/drivers/staging/greybus/manifest.h +++ b/drivers/staging/greybus/manifest.h @@ -2,6 +2,7 @@ * Greybus module manifest parsing * * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. * * Released under the GPLv2 only. */ diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 6c815d2..a057c83 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -2,6 +2,7 @@ * Greybus operations * * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. * * Released under the GPLv2 only. */ diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 1ade52b..e6da827 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -2,6 +2,7 @@ * Greybus operations * * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. * * Released under the GPLv2 only. */ diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index 31ba172..4ca3ae5 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -2,6 +2,7 @@ * Greybus protocol handling * * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. * * Released under the GPLv2 only. */ diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index 0ced63e..7d33b20 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -2,6 +2,7 @@ * Greybus protocol handling * * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. * * Released under the GPLv2 only. */ diff --git a/drivers/staging/greybus/sdio-gb.c b/drivers/staging/greybus/sdio-gb.c index 3f11365..8de7dc4 100644 --- a/drivers/staging/greybus/sdio-gb.c +++ b/drivers/staging/greybus/sdio-gb.c @@ -2,6 +2,7 @@ * SD/MMC Greybus driver. * * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. * * Released under the GPLv2 only. */ diff --git a/drivers/staging/greybus/svc_msg.h b/drivers/staging/greybus/svc_msg.h index 5b54512..1f8c4d5 100644 --- a/drivers/staging/greybus/svc_msg.h +++ b/drivers/staging/greybus/svc_msg.h @@ -5,6 +5,7 @@ * details on these values and structures. * * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. * * Released under the GPLv2 and BSD license. */ diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 8599da2..faba00e 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -2,6 +2,7 @@ * UART driver for the Greybus "generic" UART module. * * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. * * Released under the GPLv2 only. * diff --git a/drivers/staging/greybus/usb-gb.c b/drivers/staging/greybus/usb-gb.c index b3092ed..2b5f69e 100644 --- a/drivers/staging/greybus/usb-gb.c +++ b/drivers/staging/greybus/usb-gb.c @@ -2,6 +2,7 @@ * USB host driver for the Greybus "generic" USB module. * * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. * * Released under the GPLv2 only. * diff --git a/drivers/staging/greybus/vibrator-gb.c b/drivers/staging/greybus/vibrator-gb.c index 8970c69..fb48112 100644 --- a/drivers/staging/greybus/vibrator-gb.c +++ b/drivers/staging/greybus/vibrator-gb.c @@ -2,6 +2,7 @@ * Greybus Vibrator protocol driver. * * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. * * Released under the GPLv2 only. */ -- cgit v0.10.2 From 3bdec69931d889f2ee5dccafbc8cee6a364bb249 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 12 Dec 2014 17:10:16 -0500 Subject: greybus: bundle: rename interface.[c|h] to bundle.[c|h] We are renameing the "interface" term to "bundle" so rename the files before we start changing structure names to make it easier for people to see what really is happening in the changes. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 29aa4d6..08cdaf1 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -3,7 +3,7 @@ greybus-y := core.o \ ap.o \ manifest.o \ interface_block.o \ - interface.o \ + bundle.o \ connection.o \ protocol.o \ operation.o \ diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c new file mode 100644 index 0000000..742781c --- /dev/null +++ b/drivers/staging/greybus/bundle.c @@ -0,0 +1,186 @@ +/* + * Greybus interfaces + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include "greybus.h" + +static ssize_t device_id_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct gb_interface *interface = to_gb_interface(dev); + + return sprintf(buf, "%d", interface->device_id); +} +static DEVICE_ATTR_RO(device_id); + +static struct attribute *interface_attrs[] = { + &dev_attr_device_id.attr, + NULL, +}; + +ATTRIBUTE_GROUPS(interface); + +static void gb_interface_release(struct device *dev) +{ + struct gb_interface *interface = to_gb_interface(dev); + + kfree(interface); +} + +struct device_type greybus_interface_type = { + .name = "greybus_interface", + .release = gb_interface_release, +}; + + +/* XXX This could be per-host device or per-module */ +static DEFINE_SPINLOCK(gb_interfaces_lock); + +/* + * A Greybus interface represents a UniPro device present on a + * module. For Project Ara, each active Interface Block on a module + * implements a UniPro device, and therefore a Greybus interface. A + * Greybus module has at least one interface, but can have two (or + * even more). + * + * Create a gb_interface structure to represent a discovered + * interface. Returns a pointer to the new interface or a null + * pointer if a failure occurs due to memory exhaustion. + */ +struct gb_interface * +gb_interface_create(struct gb_interface_block *gb_ib, u8 interface_id) +{ + struct gb_interface *interface; + int retval; + + interface = kzalloc(sizeof(*interface), GFP_KERNEL); + if (!interface) + return NULL; + + interface->gb_ib = gb_ib; + interface->id = interface_id; + interface->device_id = 0xff; /* Invalid device id to start with */ + INIT_LIST_HEAD(&interface->connections); + + /* Build up the interface device structures and register it with the + * driver core */ + interface->dev.parent = &gb_ib->dev; + interface->dev.bus = &greybus_bus_type; + interface->dev.type = &greybus_interface_type; + interface->dev.groups = interface_groups; + device_initialize(&interface->dev); + dev_set_name(&interface->dev, "%d:%d", gb_ib->module_id, interface_id); + + retval = device_add(&interface->dev); + if (retval) { + pr_err("failed to add interface device for id 0x%02hhx\n", + interface_id); + put_device(&interface->dev); + kfree(interface); + return NULL; + } + + spin_lock_irq(&gb_interfaces_lock); + list_add_tail(&interface->links, &gb_ib->interfaces); + spin_unlock_irq(&gb_interfaces_lock); + + return interface; +} + +/* + * Tear down a previously set up interface. + */ +void gb_interface_destroy(struct gb_interface_block *gb_ib) +{ + struct gb_interface *interface; + struct gb_interface *temp; + + if (WARN_ON(!gb_ib)) + return; + + spin_lock_irq(&gb_interfaces_lock); + list_for_each_entry_safe(interface, temp, &gb_ib->interfaces, links) { + list_del(&interface->links); + gb_interface_connections_exit(interface); + device_del(&interface->dev); + } + spin_unlock_irq(&gb_interfaces_lock); +} + +int gb_interface_init(struct gb_interface_block *gb_ib, u8 interface_id, u8 device_id) +{ + struct gb_interface *interface; + int ret; + + interface = gb_interface_find(gb_ib, interface_id); + if (!interface) { + dev_err(gb_ib->hd->parent, "module %hhu not found\n", + interface_id); + return -ENOENT; + } + interface->device_id = device_id; + + ret = svc_set_route_send(interface, gb_ib->hd); + if (ret) { + dev_err(gb_ib->hd->parent, "failed to set route (%d)\n", ret); + return ret; + } + + ret = gb_interface_connections_init(interface); + if (ret) { + dev_err(gb_ib->hd->parent, "module interface init error %d\n", + ret); + /* XXX clear route */ + return ret; + } + + return 0; +} + +struct gb_interface *gb_interface_find(struct gb_interface_block *gb_ib, + u8 interface_id) +{ + struct gb_interface *interface; + + spin_lock_irq(&gb_interfaces_lock); + list_for_each_entry(interface, &gb_ib->interfaces, links) + if (interface->id == interface_id) { + spin_unlock_irq(&gb_interfaces_lock); + return interface; + } + spin_unlock_irq(&gb_interfaces_lock); + + return NULL; +} + +int gb_interface_connections_init(struct gb_interface *interface) +{ + struct gb_connection *connection; + int ret = 0; + + list_for_each_entry(connection, &interface->connections, + interface_links) { + ret = gb_connection_init(connection); + if (ret) + break; + } + + return ret; +} + +void gb_interface_connections_exit(struct gb_interface *interface) +{ + struct gb_connection *connection; + struct gb_connection *next; + + list_for_each_entry_safe(connection, next, &interface->connections, + interface_links) { + gb_connection_exit(connection); + gb_connection_destroy(connection); + } +} diff --git a/drivers/staging/greybus/bundle.h b/drivers/staging/greybus/bundle.h new file mode 100644 index 0000000..c0c66b8 --- /dev/null +++ b/drivers/staging/greybus/bundle.h @@ -0,0 +1,35 @@ +/* + * Greybus interfaces + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#ifndef __INTERFACE_H +#define __INTERFACE_H + +#include + +struct gb_interface { + struct device dev; + struct gb_interface_block *gb_ib; + u8 id; + u8 device_id; + struct list_head connections; + + struct list_head links; /* module->interfaces */ +}; +#define to_gb_interface(d) container_of(d, struct gb_interface, dev) + +struct gb_interface *gb_interface_create(struct gb_interface_block *gb_ib, u8 module_id); +void gb_interface_destroy(struct gb_interface_block *gb_ib); +int gb_interface_init(struct gb_interface_block *gb_ib, u8 module_id, u8 device_id); + +struct gb_interface *gb_interface_find(struct gb_interface_block *gb_ib, u8 interface_id); + +int gb_interface_connections_init(struct gb_interface *interface); +void gb_interface_connections_exit(struct gb_interface *interface); + +#endif /* __INTERFACE_H */ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 8216c93..f243dd2 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -25,7 +25,7 @@ #include "greybus_manifest.h" #include "manifest.h" #include "interface_block.h" -#include "interface.h" +#include "bundle.h" #include "connection.h" #include "protocol.h" #include "operation.h" diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c deleted file mode 100644 index 742781c..0000000 --- a/drivers/staging/greybus/interface.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Greybus interfaces - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#include "greybus.h" - -static ssize_t device_id_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct gb_interface *interface = to_gb_interface(dev); - - return sprintf(buf, "%d", interface->device_id); -} -static DEVICE_ATTR_RO(device_id); - -static struct attribute *interface_attrs[] = { - &dev_attr_device_id.attr, - NULL, -}; - -ATTRIBUTE_GROUPS(interface); - -static void gb_interface_release(struct device *dev) -{ - struct gb_interface *interface = to_gb_interface(dev); - - kfree(interface); -} - -struct device_type greybus_interface_type = { - .name = "greybus_interface", - .release = gb_interface_release, -}; - - -/* XXX This could be per-host device or per-module */ -static DEFINE_SPINLOCK(gb_interfaces_lock); - -/* - * A Greybus interface represents a UniPro device present on a - * module. For Project Ara, each active Interface Block on a module - * implements a UniPro device, and therefore a Greybus interface. A - * Greybus module has at least one interface, but can have two (or - * even more). - * - * Create a gb_interface structure to represent a discovered - * interface. Returns a pointer to the new interface or a null - * pointer if a failure occurs due to memory exhaustion. - */ -struct gb_interface * -gb_interface_create(struct gb_interface_block *gb_ib, u8 interface_id) -{ - struct gb_interface *interface; - int retval; - - interface = kzalloc(sizeof(*interface), GFP_KERNEL); - if (!interface) - return NULL; - - interface->gb_ib = gb_ib; - interface->id = interface_id; - interface->device_id = 0xff; /* Invalid device id to start with */ - INIT_LIST_HEAD(&interface->connections); - - /* Build up the interface device structures and register it with the - * driver core */ - interface->dev.parent = &gb_ib->dev; - interface->dev.bus = &greybus_bus_type; - interface->dev.type = &greybus_interface_type; - interface->dev.groups = interface_groups; - device_initialize(&interface->dev); - dev_set_name(&interface->dev, "%d:%d", gb_ib->module_id, interface_id); - - retval = device_add(&interface->dev); - if (retval) { - pr_err("failed to add interface device for id 0x%02hhx\n", - interface_id); - put_device(&interface->dev); - kfree(interface); - return NULL; - } - - spin_lock_irq(&gb_interfaces_lock); - list_add_tail(&interface->links, &gb_ib->interfaces); - spin_unlock_irq(&gb_interfaces_lock); - - return interface; -} - -/* - * Tear down a previously set up interface. - */ -void gb_interface_destroy(struct gb_interface_block *gb_ib) -{ - struct gb_interface *interface; - struct gb_interface *temp; - - if (WARN_ON(!gb_ib)) - return; - - spin_lock_irq(&gb_interfaces_lock); - list_for_each_entry_safe(interface, temp, &gb_ib->interfaces, links) { - list_del(&interface->links); - gb_interface_connections_exit(interface); - device_del(&interface->dev); - } - spin_unlock_irq(&gb_interfaces_lock); -} - -int gb_interface_init(struct gb_interface_block *gb_ib, u8 interface_id, u8 device_id) -{ - struct gb_interface *interface; - int ret; - - interface = gb_interface_find(gb_ib, interface_id); - if (!interface) { - dev_err(gb_ib->hd->parent, "module %hhu not found\n", - interface_id); - return -ENOENT; - } - interface->device_id = device_id; - - ret = svc_set_route_send(interface, gb_ib->hd); - if (ret) { - dev_err(gb_ib->hd->parent, "failed to set route (%d)\n", ret); - return ret; - } - - ret = gb_interface_connections_init(interface); - if (ret) { - dev_err(gb_ib->hd->parent, "module interface init error %d\n", - ret); - /* XXX clear route */ - return ret; - } - - return 0; -} - -struct gb_interface *gb_interface_find(struct gb_interface_block *gb_ib, - u8 interface_id) -{ - struct gb_interface *interface; - - spin_lock_irq(&gb_interfaces_lock); - list_for_each_entry(interface, &gb_ib->interfaces, links) - if (interface->id == interface_id) { - spin_unlock_irq(&gb_interfaces_lock); - return interface; - } - spin_unlock_irq(&gb_interfaces_lock); - - return NULL; -} - -int gb_interface_connections_init(struct gb_interface *interface) -{ - struct gb_connection *connection; - int ret = 0; - - list_for_each_entry(connection, &interface->connections, - interface_links) { - ret = gb_connection_init(connection); - if (ret) - break; - } - - return ret; -} - -void gb_interface_connections_exit(struct gb_interface *interface) -{ - struct gb_connection *connection; - struct gb_connection *next; - - list_for_each_entry_safe(connection, next, &interface->connections, - interface_links) { - gb_connection_exit(connection); - gb_connection_destroy(connection); - } -} diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h deleted file mode 100644 index c0c66b8..0000000 --- a/drivers/staging/greybus/interface.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Greybus interfaces - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#ifndef __INTERFACE_H -#define __INTERFACE_H - -#include - -struct gb_interface { - struct device dev; - struct gb_interface_block *gb_ib; - u8 id; - u8 device_id; - struct list_head connections; - - struct list_head links; /* module->interfaces */ -}; -#define to_gb_interface(d) container_of(d, struct gb_interface, dev) - -struct gb_interface *gb_interface_create(struct gb_interface_block *gb_ib, u8 module_id); -void gb_interface_destroy(struct gb_interface_block *gb_ib); -int gb_interface_init(struct gb_interface_block *gb_ib, u8 module_id, u8 device_id); - -struct gb_interface *gb_interface_find(struct gb_interface_block *gb_ib, u8 interface_id); - -int gb_interface_connections_init(struct gb_interface *interface); -void gb_interface_connections_exit(struct gb_interface *interface); - -#endif /* __INTERFACE_H */ -- cgit v0.10.2 From f9b1df64a9f98e9c2fe38bec86b11740743e3661 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 12 Dec 2014 17:10:18 -0500 Subject: greybus: es1-ap-usb: don't protest when getting -EPROTO USB errors -EPROTO happens when devices are starting to go away in a system, or there is something wrong on the USB connection. Either way, it's safe to resubmit the urb for this error, don't complain to userspace about this, as the user will see this for every device removed, which looks scary, but means nothing. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index 41f56da..27416e4 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -352,7 +352,7 @@ static void svc_in_callback(struct urb *urb) int retval; if (status) { - if (status == -EAGAIN) + if ((status == -EAGAIN) || (status == -EPROTO)) goto exit; dev_err(dev, "urb svc in error %d (dropped)\n", status); return; @@ -380,7 +380,7 @@ static void cport_in_callback(struct urb *urb) u8 *data; if (status) { - if (status == -EAGAIN) + if ((status == -EAGAIN) || (status == -EPROTO)) goto exit; dev_err(dev, "urb cport in error %d (dropped)\n", status); return; -- cgit v0.10.2 From 1db0a5ff3a32c78082e7ef0264e71aa8afa3be96 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 12 Dec 2014 17:10:17 -0500 Subject: greybus: bundle: s/gb_interface/gb_bundle/g Rename struct gb_interface to struct gb_bundle It's a lot of renaming, some structures got renamed and also some fields, but the goal was to rename things to make sense with the new naming of how the system is put together in the 'driver model' view. Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 2491201..748ea3e 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -59,4 +59,4 @@ Date: December 2014 KernelVersion: 3.XX Contact: Greg Kroah-Hartman Description: - The device id of a Greybus interface. + The device id of a Greybus bundle. diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 4fa2ad9..a5ac2bb 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -61,7 +61,7 @@ static int svc_msg_send(struct svc_msg *svc_msg, struct greybus_host_device *hd) } -int svc_set_route_send(struct gb_interface *interface, +int svc_set_route_send(struct gb_bundle *bundle, struct greybus_host_device *hd) { struct svc_msg *svc_msg; @@ -73,7 +73,7 @@ int svc_set_route_send(struct gb_interface *interface, svc_msg->header.message_type = SVC_MSG_DATA; svc_msg->header.payload_length = cpu_to_le16(sizeof(struct svc_function_unipro_set_route)); - svc_msg->management.set_route.device_id = interface->device_id; + svc_msg->management.set_route.device_id = bundle->device_id; return svc_msg_send(svc_msg, hd); } @@ -145,12 +145,12 @@ static void svc_management(struct svc_function_unipro_management *management, management->link_up.module_id); return; } - ret = gb_interface_init(gb_ib, + ret = gb_bundle_init(gb_ib, management->link_up.interface_id, management->link_up.device_id); if (ret) dev_err(hd->parent, "error %d initializing " - "interface block %hhu interface %hhu\n", + "interface block %hhu bundle %hhu\n", ret, management->link_up.module_id, management->link_up.interface_id); break; diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index 3ed7639..83cb642 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -341,7 +341,7 @@ static int gb_battery_connection_init(struct gb_connection *connection) b->num_properties = ARRAY_SIZE(battery_props), b->get_property = get_property, - retval = power_supply_register(&connection->interface->gb_ib->dev, b); + retval = power_supply_register(&connection->bundle->gb_ib->dev, b); if (retval) { kfree(gb); return retval; diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 742781c..8854615 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -1,5 +1,5 @@ /* - * Greybus interfaces + * Greybus bundles * * Copyright 2014 Google Inc. * Copyright 2014 Linaro Ltd. @@ -9,131 +9,128 @@ #include "greybus.h" +static void gb_bundle_connections_exit(struct gb_bundle *bundle); +static int gb_bundle_connections_init(struct gb_bundle *bundle); + + static ssize_t device_id_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct gb_interface *interface = to_gb_interface(dev); + struct gb_bundle *bundle = to_gb_bundle(dev); - return sprintf(buf, "%d", interface->device_id); + return sprintf(buf, "%d", bundle->device_id); } static DEVICE_ATTR_RO(device_id); -static struct attribute *interface_attrs[] = { +static struct attribute *bundle_attrs[] = { &dev_attr_device_id.attr, NULL, }; -ATTRIBUTE_GROUPS(interface); +ATTRIBUTE_GROUPS(bundle); -static void gb_interface_release(struct device *dev) +static void gb_bundle_release(struct device *dev) { - struct gb_interface *interface = to_gb_interface(dev); + struct gb_bundle *bundle = to_gb_bundle(dev); - kfree(interface); + kfree(bundle); } -struct device_type greybus_interface_type = { - .name = "greybus_interface", - .release = gb_interface_release, +struct device_type greybus_bundle_type = { + .name = "greybus_bundle", + .release = gb_bundle_release, }; /* XXX This could be per-host device or per-module */ -static DEFINE_SPINLOCK(gb_interfaces_lock); +static DEFINE_SPINLOCK(gb_bundles_lock); /* - * A Greybus interface represents a UniPro device present on a - * module. For Project Ara, each active Interface Block on a module - * implements a UniPro device, and therefore a Greybus interface. A - * Greybus module has at least one interface, but can have two (or - * even more). - * - * Create a gb_interface structure to represent a discovered - * interface. Returns a pointer to the new interface or a null + * Create a gb_bundle structure to represent a discovered + * bundle. Returns a pointer to the new bundle or a null * pointer if a failure occurs due to memory exhaustion. */ -struct gb_interface * -gb_interface_create(struct gb_interface_block *gb_ib, u8 interface_id) +struct gb_bundle *gb_bundle_create(struct gb_interface_block *gb_ib, u8 interface_id) { - struct gb_interface *interface; + struct gb_bundle *bundle; int retval; - interface = kzalloc(sizeof(*interface), GFP_KERNEL); - if (!interface) + bundle = kzalloc(sizeof(*bundle), GFP_KERNEL); + if (!bundle) return NULL; - interface->gb_ib = gb_ib; - interface->id = interface_id; - interface->device_id = 0xff; /* Invalid device id to start with */ - INIT_LIST_HEAD(&interface->connections); + bundle->gb_ib = gb_ib; + bundle->id = interface_id; + bundle->device_id = 0xff; /* Invalid device id to start with */ + INIT_LIST_HEAD(&bundle->connections); - /* Build up the interface device structures and register it with the + /* Build up the bundle device structures and register it with the * driver core */ - interface->dev.parent = &gb_ib->dev; - interface->dev.bus = &greybus_bus_type; - interface->dev.type = &greybus_interface_type; - interface->dev.groups = interface_groups; - device_initialize(&interface->dev); - dev_set_name(&interface->dev, "%d:%d", gb_ib->module_id, interface_id); - - retval = device_add(&interface->dev); + bundle->dev.parent = &gb_ib->dev; + bundle->dev.bus = &greybus_bus_type; + bundle->dev.type = &greybus_bundle_type; + bundle->dev.groups = bundle_groups; + device_initialize(&bundle->dev); + dev_set_name(&bundle->dev, "%d:%d", gb_ib->module_id, interface_id); + + retval = device_add(&bundle->dev); if (retval) { - pr_err("failed to add interface device for id 0x%02hhx\n", + pr_err("failed to add bundle device for id 0x%02hhx\n", interface_id); - put_device(&interface->dev); - kfree(interface); + put_device(&bundle->dev); + kfree(bundle); return NULL; } - spin_lock_irq(&gb_interfaces_lock); - list_add_tail(&interface->links, &gb_ib->interfaces); - spin_unlock_irq(&gb_interfaces_lock); + spin_lock_irq(&gb_bundles_lock); + list_add_tail(&bundle->links, &gb_ib->interfaces); + spin_unlock_irq(&gb_bundles_lock); - return interface; + return bundle; } /* - * Tear down a previously set up interface. + * Tear down a previously set up bundle. */ -void gb_interface_destroy(struct gb_interface_block *gb_ib) +void gb_bundle_destroy(struct gb_interface_block *gb_ib) { - struct gb_interface *interface; - struct gb_interface *temp; + struct gb_bundle *bundle; + struct gb_bundle *temp; if (WARN_ON(!gb_ib)) return; - spin_lock_irq(&gb_interfaces_lock); - list_for_each_entry_safe(interface, temp, &gb_ib->interfaces, links) { - list_del(&interface->links); - gb_interface_connections_exit(interface); - device_del(&interface->dev); + spin_lock_irq(&gb_bundles_lock); + list_for_each_entry_safe(bundle, temp, &gb_ib->interfaces, links) { + list_del(&bundle->links); + gb_bundle_connections_exit(bundle); + device_del(&bundle->dev); } - spin_unlock_irq(&gb_interfaces_lock); + spin_unlock_irq(&gb_bundles_lock); } -int gb_interface_init(struct gb_interface_block *gb_ib, u8 interface_id, u8 device_id) +int gb_bundle_init(struct gb_interface_block *gb_ib, u8 bundle_id, u8 device_id) { - struct gb_interface *interface; + struct gb_bundle *bundle; int ret; - interface = gb_interface_find(gb_ib, interface_id); - if (!interface) { - dev_err(gb_ib->hd->parent, "module %hhu not found\n", - interface_id); + bundle = gb_bundle_find(gb_ib, bundle_id); + if (!bundle) { + dev_err(gb_ib->hd->parent, "bundle %hhu not found\n", + bundle_id); return -ENOENT; } - interface->device_id = device_id; + bundle->device_id = device_id; - ret = svc_set_route_send(interface, gb_ib->hd); + ret = svc_set_route_send(bundle, gb_ib->hd); if (ret) { dev_err(gb_ib->hd->parent, "failed to set route (%d)\n", ret); return ret; } - ret = gb_interface_connections_init(interface); + ret = gb_bundle_connections_init(bundle); if (ret) { - dev_err(gb_ib->hd->parent, "module interface init error %d\n", + dev_err(gb_ib->hd->parent, "interface bundle init error %d\n", ret); /* XXX clear route */ return ret; @@ -142,29 +139,27 @@ int gb_interface_init(struct gb_interface_block *gb_ib, u8 interface_id, u8 devi return 0; } -struct gb_interface *gb_interface_find(struct gb_interface_block *gb_ib, - u8 interface_id) +struct gb_bundle *gb_bundle_find(struct gb_interface_block *gb_ib, u8 bundle_id) { - struct gb_interface *interface; + struct gb_bundle *bundle; - spin_lock_irq(&gb_interfaces_lock); - list_for_each_entry(interface, &gb_ib->interfaces, links) - if (interface->id == interface_id) { - spin_unlock_irq(&gb_interfaces_lock); - return interface; + spin_lock_irq(&gb_bundles_lock); + list_for_each_entry(bundle, &gb_ib->interfaces, links) + if (bundle->id == bundle_id) { + spin_unlock_irq(&gb_bundles_lock); + return bundle; } - spin_unlock_irq(&gb_interfaces_lock); + spin_unlock_irq(&gb_bundles_lock); return NULL; } -int gb_interface_connections_init(struct gb_interface *interface) +static int gb_bundle_connections_init(struct gb_bundle *bundle) { struct gb_connection *connection; int ret = 0; - list_for_each_entry(connection, &interface->connections, - interface_links) { + list_for_each_entry(connection, &bundle->connections, bundle_links) { ret = gb_connection_init(connection); if (ret) break; @@ -173,13 +168,13 @@ int gb_interface_connections_init(struct gb_interface *interface) return ret; } -void gb_interface_connections_exit(struct gb_interface *interface) +static void gb_bundle_connections_exit(struct gb_bundle *bundle) { struct gb_connection *connection; struct gb_connection *next; - list_for_each_entry_safe(connection, next, &interface->connections, - interface_links) { + list_for_each_entry_safe(connection, next, &bundle->connections, + bundle_links) { gb_connection_exit(connection); gb_connection_destroy(connection); } diff --git a/drivers/staging/greybus/bundle.h b/drivers/staging/greybus/bundle.h index c0c66b8..ad14a47 100644 --- a/drivers/staging/greybus/bundle.h +++ b/drivers/staging/greybus/bundle.h @@ -1,5 +1,5 @@ /* - * Greybus interfaces + * Greybus bundles * * Copyright 2014 Google Inc. * Copyright 2014 Linaro Ltd. @@ -7,29 +7,28 @@ * Released under the GPLv2 only. */ -#ifndef __INTERFACE_H -#define __INTERFACE_H +#ifndef __BUNDLE_H +#define __BUNDLE_H #include -struct gb_interface { +/* Greybus "public" definitions" */ +struct gb_bundle { struct device dev; struct gb_interface_block *gb_ib; u8 id; u8 device_id; struct list_head connections; - struct list_head links; /* module->interfaces */ + struct list_head links; /* interface->bundles */ }; -#define to_gb_interface(d) container_of(d, struct gb_interface, dev) +#define to_gb_bundle(d) container_of(d, struct gb_bundle, dev) -struct gb_interface *gb_interface_create(struct gb_interface_block *gb_ib, u8 module_id); -void gb_interface_destroy(struct gb_interface_block *gb_ib); -int gb_interface_init(struct gb_interface_block *gb_ib, u8 module_id, u8 device_id); +/* Greybus "private" definitions" */ +struct gb_bundle *gb_bundle_create(struct gb_interface_block *gb_ib, u8 module_id); +void gb_bundle_destroy(struct gb_interface_block *gb_ib); +int gb_bundle_init(struct gb_interface_block *gb_ib, u8 module_id, u8 device_id); -struct gb_interface *gb_interface_find(struct gb_interface_block *gb_ib, u8 interface_id); +struct gb_bundle *gb_bundle_find(struct gb_interface_block *gb_ib, u8 bundle_id); -int gb_interface_connections_init(struct gb_interface *interface); -void gb_interface_connections_exit(struct gb_interface *interface); - -#endif /* __INTERFACE_H */ +#endif /* __BUNDLE_H */ diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 1658fdb..2a54b3e 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -32,7 +32,7 @@ struct gb_connection *gb_hd_connection_find(struct greybus_host_device *hd, /* * Callback from the host driver to let us know that data has been - * received on the interface. + * received on the bundle. */ void greybus_data_rcvd(struct greybus_host_device *hd, u16 cport_id, u8 *data, size_t length) @@ -135,7 +135,7 @@ struct device_type greybus_connection_type = { * Returns a pointer to the new connection if successful, or a null * pointer otherwise. */ -struct gb_connection *gb_connection_create(struct gb_interface *interface, +struct gb_connection *gb_connection_create(struct gb_bundle *bundle, u16 cport_id, u8 protocol_id) { struct gb_connection *connection; @@ -156,7 +156,7 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, return NULL; } - hd = interface->gb_ib->hd; + hd = bundle->gb_ib->hd; connection->hd = hd; if (!gb_connection_hd_cport_id_alloc(connection)) { gb_protocol_put(connection->protocol); @@ -164,17 +164,17 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, return NULL; } - connection->interface = interface; - connection->interface_cport_id = cport_id; + connection->bundle = bundle; + connection->bundle_cport_id = cport_id; connection->state = GB_CONNECTION_STATE_DISABLED; - connection->dev.parent = &interface->dev; + connection->dev.parent = &bundle->dev; connection->dev.bus = &greybus_bus_type; connection->dev.type = &greybus_connection_type; connection->dev.groups = connection_groups; device_initialize(&connection->dev); dev_set_name(&connection->dev, "%s:%d", - dev_name(&interface->dev), cport_id); + dev_name(&bundle->dev), cport_id); retval = device_add(&connection->dev); if (retval) { @@ -189,7 +189,7 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, spin_lock_irq(&gb_connections_lock); list_add_tail(&connection->hd_links, &hd->connections); - list_add_tail(&connection->interface_links, &interface->connections); + list_add_tail(&connection->bundle_links, &bundle->connections); spin_unlock_irq(&gb_connections_lock); atomic_set(&connection->op_cycle, 0); @@ -216,7 +216,7 @@ void gb_connection_destroy(struct gb_connection *connection) gb_operation_cancel(operation, -ESHUTDOWN); } spin_lock_irq(&gb_connections_lock); - list_del(&connection->interface_links); + list_del(&connection->bundle_links); list_del(&connection->hd_links); spin_unlock_irq(&gb_connections_lock); @@ -237,9 +237,9 @@ void gb_connection_err(struct gb_connection *connection, const char *fmt, ...) vaf.va = &args; pr_err("greybus: [%hhu:%hhu:%hu]: %pV\n", - connection->interface->gb_ib->module_id, - connection->interface->id, - connection->interface_cport_id, &vaf); + connection->bundle->gb_ib->module_id, + connection->bundle->id, + connection->bundle_cport_id, &vaf); va_end(args); } diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 5c3fad3f..caf52b8 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -24,13 +24,13 @@ enum gb_connection_state { struct gb_connection { struct greybus_host_device *hd; - struct gb_interface *interface; + struct gb_bundle *bundle; struct device dev; u16 hd_cport_id; - u16 interface_cport_id; + u16 bundle_cport_id; struct list_head hd_links; - struct list_head interface_links; + struct list_head bundle_links; struct gb_protocol *protocol; @@ -43,7 +43,7 @@ struct gb_connection { }; #define to_gb_connection(d) container_of(d, struct gb_connection, dev) -struct gb_connection *gb_connection_create(struct gb_interface *interface, +struct gb_connection *gb_connection_create(struct gb_bundle *bundle, u16 cport_id, u8 protocol_id); void gb_connection_destroy(struct gb_connection *connection); diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 032710c..eef28e1a 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -47,18 +47,18 @@ static int greybus_module_match(struct device *dev, struct device_driver *drv) static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) { struct gb_interface_block *gb_ib = NULL; - struct gb_interface *interface = NULL; + struct gb_bundle *bundle = NULL; struct gb_connection *connection = NULL; if (is_gb_interface_block(dev)) { gb_ib = to_gb_interface_block(dev); - } else if (is_gb_interface(dev)) { - interface = to_gb_interface(dev); - gb_ib = interface->gb_ib; + } else if (is_gb_bundle(dev)) { + bundle = to_gb_bundle(dev); + gb_ib = bundle->gb_ib; } else if (is_gb_connection(dev)) { connection = to_gb_connection(dev); - interface = connection->interface; - gb_ib = interface->gb_ib; + bundle = connection->bundle; + gb_ib = bundle->gb_ib; } else { dev_WARN(dev, "uevent for unknown greybus device \"type\"!\n"); return -EINVAL; @@ -70,9 +70,9 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) return 0; } - if (interface) { + if (bundle) { // FIXME - // add a uevent that can "load" a interface type + // add a uevent that can "load" a bundle type // This is what we need to bind a driver to so use the info // in gmod here as well return 0; diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index f243dd2..230cc28 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -172,11 +172,11 @@ extern struct bus_type greybus_bus_type; int gb_uart_device_init(struct gb_connection *connection); void gb_uart_device_exit(struct gb_connection *connection); -int svc_set_route_send(struct gb_interface *interface, +int svc_set_route_send(struct gb_bundle *bundle, struct greybus_host_device *hd); extern struct device_type greybus_interface_block_type; -extern struct device_type greybus_interface_type; +extern struct device_type greybus_bundle_type; extern struct device_type greybus_connection_type; static inline int is_gb_interface_block(const struct device *dev) @@ -184,9 +184,9 @@ static inline int is_gb_interface_block(const struct device *dev) return dev->type == &greybus_interface_block_type; } -static inline int is_gb_interface(const struct device *dev) +static inline int is_gb_bundle(const struct device *dev) { - return dev->type == &greybus_interface_type; + return dev->type == &greybus_bundle_type; } static inline int is_gb_connection(const struct device *dev) diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index deff5c7..398630c 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -106,13 +106,13 @@ struct greybus_descriptor_interface { }; /* - * A CPort descriptor indicates the id of the interface within the + * A CPort descriptor indicates the id of the bundle within the * module it's associated with, along with the CPort id used to * address the CPort. The protocol id defines the format of messages * exchanged using the CPort. */ struct greybus_descriptor_cport { - __u8 interface; + __u8 bundle; __le16 id; __u8 protocol_id; /* enum greybus_protocol */ }; diff --git a/drivers/staging/greybus/interface_block.c b/drivers/staging/greybus/interface_block.c index ab4c833..ee51613 100644 --- a/drivers/staging/greybus/interface_block.c +++ b/drivers/staging/greybus/interface_block.c @@ -164,7 +164,7 @@ static void gb_ib_destroy(struct gb_interface_block *gb_ib) list_del(&gb_ib->links); spin_unlock_irq(&gb_modules_lock); - gb_interface_destroy(gb_ib); + gb_bundle_destroy(gb_ib); kfree(gb_ib->product_string); kfree(gb_ib->vendor_string); diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 01a69a3..7661ca7 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -172,10 +172,10 @@ static char *gb_string_get(u8 string_id) /* * Find cport descriptors in the manifest and set up data structures - * for the functions that use them. Returns the number of interfaces - * set up for the given module, or 0 if there is an error. + * for the functions that use them. Returns the number of bundles + * set up for the given interface, or 0 if there is an error. */ -static u32 gb_manifest_parse_cports(struct gb_interface *interface) +static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) { u32 count = 0; @@ -190,7 +190,7 @@ static u32 gb_manifest_parse_cports(struct gb_interface *interface) list_for_each_entry(descriptor, &manifest_descs, links) { if (descriptor->type == GREYBUS_TYPE_CPORT) { desc_cport = descriptor->data; - if (desc_cport->interface == interface->id) { + if (desc_cport->bundle == bundle->id) { found = true; break; } @@ -202,7 +202,7 @@ static u32 gb_manifest_parse_cports(struct gb_interface *interface) /* Found one. Set up its function structure */ protocol_id = desc_cport->protocol_id; cport_id = le16_to_cpu(desc_cport->id); - if (!gb_connection_create(interface, cport_id, protocol_id)) + if (!gb_connection_create(bundle, cport_id, protocol_id)) return 0; /* Error */ count++; @@ -214,21 +214,21 @@ static u32 gb_manifest_parse_cports(struct gb_interface *interface) } /* - * Find interface descriptors in the manifest and set up their data - * structures. Returns the number of interfaces set up for the + * Find bundle descriptors in the manifest and set up their data + * structures. Returns the number of bundles set up for the * given module. */ -static u32 gb_manifest_parse_interfaces(struct gb_interface_block *gb_ib) +static u32 gb_manifest_parse_bundles(struct gb_interface_block *gb_ib) { u32 count = 0; while (true) { struct manifest_desc *descriptor; struct greybus_descriptor_interface *desc_interface; - struct gb_interface *interface; + struct gb_bundle *bundle; bool found = false; - /* Find an interface descriptor */ + /* Find an bundle descriptor */ list_for_each_entry(descriptor, &manifest_descs, links) { if (descriptor->type == GREYBUS_TYPE_INTERFACE) { found = true; @@ -238,19 +238,19 @@ static u32 gb_manifest_parse_interfaces(struct gb_interface_block *gb_ib) if (!found) break; - /* Found one. Set up its interface structure*/ + /* Found one. Set up its bundle structure*/ desc_interface = descriptor->data; - interface = gb_interface_create(gb_ib, desc_interface->id); - if (!interface) + bundle = gb_bundle_create(gb_ib, desc_interface->id); + if (!bundle) return 0; /* Error */ - /* Now go set up this interface's functions and cports */ - if (!gb_manifest_parse_cports(interface)) + /* Now go set up this bundle's functions and cports */ + if (!gb_manifest_parse_cports(bundle)) return 0; /* Error parsing cports */ count++; - /* Done with this interface descriptor */ + /* Done with this bundle descriptor */ release_manifest_descriptor(descriptor); } @@ -279,9 +279,9 @@ static bool gb_manifest_parse_module(struct gb_interface_block *gb_ib, /* Release the module descriptor, now that we're done with it */ release_manifest_descriptor(module_desc); - /* A module must have at least one interface descriptor */ - if (!gb_manifest_parse_interfaces(gb_ib)) { - pr_err("manifest interface descriptors not valid\n"); + /* An interface must have at least one bundle descriptor */ + if (!gb_manifest_parse_bundles(gb_ib)) { + pr_err("manifest bundle descriptors not valid\n"); goto out_err; } @@ -314,7 +314,7 @@ out_free_vendor_string: * information it contains, and then remove that descriptor (and any * string descriptors it refers to) from further consideration. * - * After that we look for the module's interfaces--there must be at + * After that we look for the interface block's bundles--there must be at * least one of those. * * Returns true if parsing was successful, false otherwise. -- cgit v0.10.2 From e232b791d5a4c597626fbbd02f613a8a5474d7c4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 19 Dec 2014 14:56:29 -0800 Subject: greybus: interface_block.c: rename the "interfaces" list "bundles" Alex pointed out one rename I missed previously, this fixes up the interface_block list of bundles name. Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 8854615..bad6cf6 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -83,7 +83,7 @@ struct gb_bundle *gb_bundle_create(struct gb_interface_block *gb_ib, u8 interfac } spin_lock_irq(&gb_bundles_lock); - list_add_tail(&bundle->links, &gb_ib->interfaces); + list_add_tail(&bundle->links, &gb_ib->bundles); spin_unlock_irq(&gb_bundles_lock); return bundle; @@ -101,7 +101,7 @@ void gb_bundle_destroy(struct gb_interface_block *gb_ib) return; spin_lock_irq(&gb_bundles_lock); - list_for_each_entry_safe(bundle, temp, &gb_ib->interfaces, links) { + list_for_each_entry_safe(bundle, temp, &gb_ib->bundles, links) { list_del(&bundle->links); gb_bundle_connections_exit(bundle); device_del(&bundle->dev); @@ -144,7 +144,7 @@ struct gb_bundle *gb_bundle_find(struct gb_interface_block *gb_ib, u8 bundle_id) struct gb_bundle *bundle; spin_lock_irq(&gb_bundles_lock); - list_for_each_entry(bundle, &gb_ib->interfaces, links) + list_for_each_entry(bundle, &gb_ib->bundles, links) if (bundle->id == bundle_id) { spin_unlock_irq(&gb_bundles_lock); return bundle; diff --git a/drivers/staging/greybus/interface_block.c b/drivers/staging/greybus/interface_block.c index ee51613..f47c8fc 100644 --- a/drivers/staging/greybus/interface_block.c +++ b/drivers/staging/greybus/interface_block.c @@ -126,7 +126,7 @@ static struct gb_interface_block *gb_ib_create(struct greybus_host_device *hd, gb_ib->hd = hd; /* XXX refcount? */ gb_ib->module_id = module_id; - INIT_LIST_HEAD(&gb_ib->interfaces); + INIT_LIST_HEAD(&gb_ib->bundles); gb_ib->dev.parent = hd->parent; gb_ib->dev.bus = &greybus_bus_type; diff --git a/drivers/staging/greybus/interface_block.h b/drivers/staging/greybus/interface_block.h index 03da567..e0846d8 100644 --- a/drivers/staging/greybus/interface_block.h +++ b/drivers/staging/greybus/interface_block.h @@ -19,7 +19,7 @@ struct gb_interface_block { struct device dev; - struct list_head interfaces; + struct list_head bundles; struct list_head links; /* greybus_host_device->modules */ u8 module_id; /* Physical location within the Endo */ -- cgit v0.10.2 From a93938a23d4d0210d06ea106a132bcab491d3885 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 19 Dec 2014 14:56:30 -0800 Subject: greybus: rename interface_block.[c|h] -> interface.[c|h] Interface_block is being renamed to interface, so move the file first. Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 08cdaf1..6c0b0ca 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -2,7 +2,7 @@ greybus-y := core.o \ debugfs.o \ ap.o \ manifest.o \ - interface_block.o \ + interface.o \ bundle.o \ connection.o \ protocol.o \ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 230cc28..e0c5eb7 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -24,7 +24,7 @@ #include "greybus_id.h" #include "greybus_manifest.h" #include "manifest.h" -#include "interface_block.h" +#include "interface.h" #include "bundle.h" #include "connection.h" #include "protocol.h" diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c new file mode 100644 index 0000000..f47c8fc --- /dev/null +++ b/drivers/staging/greybus/interface.c @@ -0,0 +1,233 @@ +/* + * Greybus interface block code + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include "greybus.h" + +/* interface block sysfs attributes */ +#define gb_ib_attr(field, type) \ +static ssize_t field##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct gb_interface_block *gb_ib = to_gb_interface_block(dev); \ + return sprintf(buf, "%"#type"\n", gb_ib->field); \ +} \ +static DEVICE_ATTR_RO(field) + +gb_ib_attr(vendor, x); +gb_ib_attr(product, x); +gb_ib_attr(unique_id, llX); +gb_ib_attr(vendor_string, s); +gb_ib_attr(product_string, s); + +static struct attribute *interface_block_attrs[] = { + &dev_attr_vendor.attr, + &dev_attr_product.attr, + &dev_attr_unique_id.attr, + &dev_attr_vendor_string.attr, + &dev_attr_product_string.attr, + NULL, +}; +ATTRIBUTE_GROUPS(interface_block); + + +/* XXX This could be per-host device */ +static DEFINE_SPINLOCK(gb_modules_lock); + +static int gb_ib_match_one_id(struct gb_interface_block *gb_ib, + const struct greybus_interface_block_id *id) +{ + if ((id->match_flags & GREYBUS_ID_MATCH_VENDOR) && + (id->vendor != gb_ib->vendor)) + return 0; + + if ((id->match_flags & GREYBUS_ID_MATCH_PRODUCT) && + (id->product != gb_ib->product)) + return 0; + + if ((id->match_flags & GREYBUS_ID_MATCH_SERIAL) && + (id->unique_id != gb_ib->unique_id)) + return 0; + + return 1; +} + +const struct greybus_interface_block_id * +gb_ib_match_id(struct gb_interface_block *gb_ib, + const struct greybus_interface_block_id *id) +{ + if (id == NULL) + return NULL; + + for (; id->vendor || id->product || id->unique_id || + id->driver_info; id++) { + if (gb_ib_match_one_id(gb_ib, id)) + return id; + } + + return NULL; +} + +struct gb_interface_block *gb_ib_find(struct greybus_host_device *hd, u8 module_id) +{ + struct gb_interface_block *gb_ib; + + list_for_each_entry(gb_ib, &hd->modules, links) + if (gb_ib->module_id == module_id) + return gb_ib; + + return NULL; +} + +static void greybus_ib_release(struct device *dev) +{ + struct gb_interface_block *gb_ib = to_gb_interface_block(dev); + + kfree(gb_ib); +} + +struct device_type greybus_interface_block_type = { + .name = "greybus_interface_block", + .release = greybus_ib_release, +}; + +/* + * A Greybus module represents a user-replicable component on an Ara + * phone. An interface block is the physical connection on that module. A + * module may have more than one interface block. + * + * Create a gb_interface_block structure to represent a discovered module. + * The position within the Endo is encoded in the "module_id" argument. + * Returns a pointer to the new module or a null pointer if a + * failure occurs due to memory exhaustion. + */ +static struct gb_interface_block *gb_ib_create(struct greybus_host_device *hd, + u8 module_id) +{ + struct gb_interface_block *gb_ib; + int retval; + + gb_ib = gb_ib_find(hd, module_id); + if (gb_ib) { + dev_err(hd->parent, "Duplicate module id %d will not be created\n", + module_id); + return NULL; + } + + gb_ib = kzalloc(sizeof(*gb_ib), GFP_KERNEL); + if (!gb_ib) + return NULL; + + gb_ib->hd = hd; /* XXX refcount? */ + gb_ib->module_id = module_id; + INIT_LIST_HEAD(&gb_ib->bundles); + + gb_ib->dev.parent = hd->parent; + gb_ib->dev.bus = &greybus_bus_type; + gb_ib->dev.type = &greybus_interface_block_type; + gb_ib->dev.groups = interface_block_groups; + gb_ib->dev.dma_mask = hd->parent->dma_mask; + device_initialize(&gb_ib->dev); + dev_set_name(&gb_ib->dev, "%d", module_id); + + retval = device_add(&gb_ib->dev); + if (retval) { + pr_err("failed to add module device for id 0x%02hhx\n", + module_id); + put_device(&gb_ib->dev); + kfree(gb_ib); + return NULL; + } + + spin_lock_irq(&gb_modules_lock); + list_add_tail(&gb_ib->links, &hd->modules); + spin_unlock_irq(&gb_modules_lock); + + return gb_ib; +} + +/* + * Tear down a previously set up module. + */ +static void gb_ib_destroy(struct gb_interface_block *gb_ib) +{ + if (WARN_ON(!gb_ib)) + return; + + spin_lock_irq(&gb_modules_lock); + list_del(&gb_ib->links); + spin_unlock_irq(&gb_modules_lock); + + gb_bundle_destroy(gb_ib); + + kfree(gb_ib->product_string); + kfree(gb_ib->vendor_string); + /* kref_put(module->hd); */ + + device_del(&gb_ib->dev); +} + +/** + * gb_add_module + * + * Pass in a buffer that _should_ contain a Greybus module manifest + * and register a greybus device structure with the kernel core. + */ +void gb_add_module(struct greybus_host_device *hd, u8 module_id, + u8 *data, int size) +{ + struct gb_interface_block *gb_ib; + + gb_ib = gb_ib_create(hd, module_id); + if (!gb_ib) { + dev_err(hd->parent, "failed to create interface block\n"); + return; + } + + /* + * Parse the manifest and build up our data structures + * representing what's in it. + */ + if (!gb_manifest_parse(gb_ib, data, size)) { + dev_err(hd->parent, "manifest error\n"); + goto err_module; + } + + /* + * XXX + * We've successfully parsed the manifest. Now we need to + * allocate CPort Id's for connecting to the CPorts found on + * other modules. For each of these, establish a connection + * between the local and remote CPorts (including + * configuring the switch to allow them to communicate). + */ + + return; + +err_module: + gb_ib_destroy(gb_ib); +} + +void gb_remove_module(struct greybus_host_device *hd, u8 module_id) +{ + struct gb_interface_block *gb_ib = gb_ib_find(hd, module_id); + + if (gb_ib) + gb_ib_destroy(gb_ib); + else + dev_err(hd->parent, "interface block id %d not found\n", module_id); +} + +void gb_remove_modules(struct greybus_host_device *hd) +{ + struct gb_interface_block *gb_ib, *temp; + + list_for_each_entry_safe(gb_ib, temp, &hd->modules, links) + gb_ib_destroy(gb_ib); +} diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h new file mode 100644 index 0000000..5c7cebc --- /dev/null +++ b/drivers/staging/greybus/interface.h @@ -0,0 +1,58 @@ +/* + * Greybus Interface Block code + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#ifndef __INTERFACE_H +#define __INTERFACE_H + +/* Increase these values if needed */ +#define MAX_CPORTS_PER_MODULE 10 +#define MAX_STRINGS_PER_MODULE 10 + + +/* Greybus "public" definitions" */ +struct gb_interface_block { + struct device dev; + + struct list_head bundles; + struct list_head links; /* greybus_host_device->modules */ + u8 module_id; /* Physical location within the Endo */ + + /* Information taken from the manifest module descriptor */ + u16 vendor; + u16 product; + char *vendor_string; + char *product_string; + u64 unique_id; + + struct greybus_host_device *hd; +}; +#define to_gb_interface_block(d) container_of(d, struct gb_interface_block, dev) + +static inline void +gb_interface_block_set_drvdata(struct gb_interface_block *gb_ib, void *data) +{ + dev_set_drvdata(&gb_ib->dev, data); +} + +static inline void * +gb_interface_block_get_drvdata(struct gb_interface_block *gb_ib) +{ + return dev_get_drvdata(&gb_ib->dev); +} + +/* Greybus "private" definitions */ + +const struct greybus_interface_block_id * + gb_ib_match_id(struct gb_interface_block *gb_ib, + const struct greybus_interface_block_id *id); + +struct gb_interface_block *gb_ib_find(struct greybus_host_device *hd, + u8 module_id); + +#endif /* __INTERFACE_H */ diff --git a/drivers/staging/greybus/interface_block.c b/drivers/staging/greybus/interface_block.c deleted file mode 100644 index f47c8fc..0000000 --- a/drivers/staging/greybus/interface_block.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Greybus interface block code - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#include "greybus.h" - -/* interface block sysfs attributes */ -#define gb_ib_attr(field, type) \ -static ssize_t field##_show(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct gb_interface_block *gb_ib = to_gb_interface_block(dev); \ - return sprintf(buf, "%"#type"\n", gb_ib->field); \ -} \ -static DEVICE_ATTR_RO(field) - -gb_ib_attr(vendor, x); -gb_ib_attr(product, x); -gb_ib_attr(unique_id, llX); -gb_ib_attr(vendor_string, s); -gb_ib_attr(product_string, s); - -static struct attribute *interface_block_attrs[] = { - &dev_attr_vendor.attr, - &dev_attr_product.attr, - &dev_attr_unique_id.attr, - &dev_attr_vendor_string.attr, - &dev_attr_product_string.attr, - NULL, -}; -ATTRIBUTE_GROUPS(interface_block); - - -/* XXX This could be per-host device */ -static DEFINE_SPINLOCK(gb_modules_lock); - -static int gb_ib_match_one_id(struct gb_interface_block *gb_ib, - const struct greybus_interface_block_id *id) -{ - if ((id->match_flags & GREYBUS_ID_MATCH_VENDOR) && - (id->vendor != gb_ib->vendor)) - return 0; - - if ((id->match_flags & GREYBUS_ID_MATCH_PRODUCT) && - (id->product != gb_ib->product)) - return 0; - - if ((id->match_flags & GREYBUS_ID_MATCH_SERIAL) && - (id->unique_id != gb_ib->unique_id)) - return 0; - - return 1; -} - -const struct greybus_interface_block_id * -gb_ib_match_id(struct gb_interface_block *gb_ib, - const struct greybus_interface_block_id *id) -{ - if (id == NULL) - return NULL; - - for (; id->vendor || id->product || id->unique_id || - id->driver_info; id++) { - if (gb_ib_match_one_id(gb_ib, id)) - return id; - } - - return NULL; -} - -struct gb_interface_block *gb_ib_find(struct greybus_host_device *hd, u8 module_id) -{ - struct gb_interface_block *gb_ib; - - list_for_each_entry(gb_ib, &hd->modules, links) - if (gb_ib->module_id == module_id) - return gb_ib; - - return NULL; -} - -static void greybus_ib_release(struct device *dev) -{ - struct gb_interface_block *gb_ib = to_gb_interface_block(dev); - - kfree(gb_ib); -} - -struct device_type greybus_interface_block_type = { - .name = "greybus_interface_block", - .release = greybus_ib_release, -}; - -/* - * A Greybus module represents a user-replicable component on an Ara - * phone. An interface block is the physical connection on that module. A - * module may have more than one interface block. - * - * Create a gb_interface_block structure to represent a discovered module. - * The position within the Endo is encoded in the "module_id" argument. - * Returns a pointer to the new module or a null pointer if a - * failure occurs due to memory exhaustion. - */ -static struct gb_interface_block *gb_ib_create(struct greybus_host_device *hd, - u8 module_id) -{ - struct gb_interface_block *gb_ib; - int retval; - - gb_ib = gb_ib_find(hd, module_id); - if (gb_ib) { - dev_err(hd->parent, "Duplicate module id %d will not be created\n", - module_id); - return NULL; - } - - gb_ib = kzalloc(sizeof(*gb_ib), GFP_KERNEL); - if (!gb_ib) - return NULL; - - gb_ib->hd = hd; /* XXX refcount? */ - gb_ib->module_id = module_id; - INIT_LIST_HEAD(&gb_ib->bundles); - - gb_ib->dev.parent = hd->parent; - gb_ib->dev.bus = &greybus_bus_type; - gb_ib->dev.type = &greybus_interface_block_type; - gb_ib->dev.groups = interface_block_groups; - gb_ib->dev.dma_mask = hd->parent->dma_mask; - device_initialize(&gb_ib->dev); - dev_set_name(&gb_ib->dev, "%d", module_id); - - retval = device_add(&gb_ib->dev); - if (retval) { - pr_err("failed to add module device for id 0x%02hhx\n", - module_id); - put_device(&gb_ib->dev); - kfree(gb_ib); - return NULL; - } - - spin_lock_irq(&gb_modules_lock); - list_add_tail(&gb_ib->links, &hd->modules); - spin_unlock_irq(&gb_modules_lock); - - return gb_ib; -} - -/* - * Tear down a previously set up module. - */ -static void gb_ib_destroy(struct gb_interface_block *gb_ib) -{ - if (WARN_ON(!gb_ib)) - return; - - spin_lock_irq(&gb_modules_lock); - list_del(&gb_ib->links); - spin_unlock_irq(&gb_modules_lock); - - gb_bundle_destroy(gb_ib); - - kfree(gb_ib->product_string); - kfree(gb_ib->vendor_string); - /* kref_put(module->hd); */ - - device_del(&gb_ib->dev); -} - -/** - * gb_add_module - * - * Pass in a buffer that _should_ contain a Greybus module manifest - * and register a greybus device structure with the kernel core. - */ -void gb_add_module(struct greybus_host_device *hd, u8 module_id, - u8 *data, int size) -{ - struct gb_interface_block *gb_ib; - - gb_ib = gb_ib_create(hd, module_id); - if (!gb_ib) { - dev_err(hd->parent, "failed to create interface block\n"); - return; - } - - /* - * Parse the manifest and build up our data structures - * representing what's in it. - */ - if (!gb_manifest_parse(gb_ib, data, size)) { - dev_err(hd->parent, "manifest error\n"); - goto err_module; - } - - /* - * XXX - * We've successfully parsed the manifest. Now we need to - * allocate CPort Id's for connecting to the CPorts found on - * other modules. For each of these, establish a connection - * between the local and remote CPorts (including - * configuring the switch to allow them to communicate). - */ - - return; - -err_module: - gb_ib_destroy(gb_ib); -} - -void gb_remove_module(struct greybus_host_device *hd, u8 module_id) -{ - struct gb_interface_block *gb_ib = gb_ib_find(hd, module_id); - - if (gb_ib) - gb_ib_destroy(gb_ib); - else - dev_err(hd->parent, "interface block id %d not found\n", module_id); -} - -void gb_remove_modules(struct greybus_host_device *hd) -{ - struct gb_interface_block *gb_ib, *temp; - - list_for_each_entry_safe(gb_ib, temp, &hd->modules, links) - gb_ib_destroy(gb_ib); -} diff --git a/drivers/staging/greybus/interface_block.h b/drivers/staging/greybus/interface_block.h deleted file mode 100644 index e0846d8..0000000 --- a/drivers/staging/greybus/interface_block.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Greybus Interface Block code - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#ifndef __INTERFACE_BLOCK_H -#define __INTERFACE_BLOCK_H - -/* Increase these values if needed */ -#define MAX_CPORTS_PER_MODULE 10 -#define MAX_STRINGS_PER_MODULE 10 - - -/* Greybus "public" definitions" */ -struct gb_interface_block { - struct device dev; - - struct list_head bundles; - struct list_head links; /* greybus_host_device->modules */ - u8 module_id; /* Physical location within the Endo */ - - /* Information taken from the manifest module descriptor */ - u16 vendor; - u16 product; - char *vendor_string; - char *product_string; - u64 unique_id; - - struct greybus_host_device *hd; -}; -#define to_gb_interface_block(d) container_of(d, struct gb_interface_block, dev) - -static inline void -gb_interface_block_set_drvdata(struct gb_interface_block *gb_ib, void *data) -{ - dev_set_drvdata(&gb_ib->dev, data); -} - -static inline void * -gb_interface_block_get_drvdata(struct gb_interface_block *gb_ib) -{ - return dev_get_drvdata(&gb_ib->dev); -} - -/* Greybus "private" definitions */ - -const struct greybus_interface_block_id * - gb_ib_match_id(struct gb_interface_block *gb_ib, - const struct greybus_interface_block_id *id); - -struct gb_interface_block *gb_ib_find(struct greybus_host_device *hd, - u8 module_id); - -#endif /* __INTERFACE_BLOCK_H */ -- cgit v0.10.2 From 4ab9b3c24b009fdc55465977153c5deffd31b0c0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 19 Dec 2014 14:56:31 -0800 Subject: greybus: interface: s/gb_interface_block/gb_interface/g Rename struct gb_interface_block to struct gb_interface Lots of renaming, and variable renames as well (gb_ib->intf), but all should be sane with regards to the new naming scheme we are using. Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index a5ac2bb..f9c63e4 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -124,7 +124,7 @@ static void svc_handshake(struct svc_function_handshake *handshake, static void svc_management(struct svc_function_unipro_management *management, int payload_length, struct greybus_host_device *hd) { - struct gb_interface_block *gb_ib; + struct gb_interface *intf; int ret; if (payload_length != sizeof(*management)) { @@ -139,18 +139,18 @@ static void svc_management(struct svc_function_unipro_management *management, hd->device_id = management->ap_id.device_id; break; case SVC_MANAGEMENT_LINK_UP: - gb_ib = gb_ib_find(hd, management->link_up.module_id); - if (!gb_ib) { + intf = gb_interface_find(hd, management->link_up.module_id); + if (!intf) { dev_err(hd->parent, "Module ID %d not found\n", management->link_up.module_id); return; } - ret = gb_bundle_init(gb_ib, + ret = gb_bundle_init(intf, management->link_up.interface_id, management->link_up.device_id); if (ret) - dev_err(hd->parent, "error %d initializing " - "interface block %hhu bundle %hhu\n", + dev_err(hd->parent, + "error %d initializing interface %hhu bundle %hhu\n", ret, management->link_up.module_id, management->link_up.interface_id); break; diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index 83cb642..df1d7ee 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -341,7 +341,7 @@ static int gb_battery_connection_init(struct gb_connection *connection) b->num_properties = ARRAY_SIZE(battery_props), b->get_property = get_property, - retval = power_supply_register(&connection->bundle->gb_ib->dev, b); + retval = power_supply_register(&connection->bundle->intf->dev, b); if (retval) { kfree(gb); return retval; diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index bad6cf6..2ac67a24 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -50,7 +50,7 @@ static DEFINE_SPINLOCK(gb_bundles_lock); * bundle. Returns a pointer to the new bundle or a null * pointer if a failure occurs due to memory exhaustion. */ -struct gb_bundle *gb_bundle_create(struct gb_interface_block *gb_ib, u8 interface_id) +struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 interface_id) { struct gb_bundle *bundle; int retval; @@ -59,19 +59,19 @@ struct gb_bundle *gb_bundle_create(struct gb_interface_block *gb_ib, u8 interfac if (!bundle) return NULL; - bundle->gb_ib = gb_ib; + bundle->intf = intf; bundle->id = interface_id; bundle->device_id = 0xff; /* Invalid device id to start with */ INIT_LIST_HEAD(&bundle->connections); /* Build up the bundle device structures and register it with the * driver core */ - bundle->dev.parent = &gb_ib->dev; + bundle->dev.parent = &intf->dev; bundle->dev.bus = &greybus_bus_type; bundle->dev.type = &greybus_bundle_type; bundle->dev.groups = bundle_groups; device_initialize(&bundle->dev); - dev_set_name(&bundle->dev, "%d:%d", gb_ib->module_id, interface_id); + dev_set_name(&bundle->dev, "%d:%d", intf->module_id, interface_id); retval = device_add(&bundle->dev); if (retval) { @@ -83,7 +83,7 @@ struct gb_bundle *gb_bundle_create(struct gb_interface_block *gb_ib, u8 interfac } spin_lock_irq(&gb_bundles_lock); - list_add_tail(&bundle->links, &gb_ib->bundles); + list_add_tail(&bundle->links, &intf->bundles); spin_unlock_irq(&gb_bundles_lock); return bundle; @@ -92,16 +92,16 @@ struct gb_bundle *gb_bundle_create(struct gb_interface_block *gb_ib, u8 interfac /* * Tear down a previously set up bundle. */ -void gb_bundle_destroy(struct gb_interface_block *gb_ib) +void gb_bundle_destroy(struct gb_interface *intf) { struct gb_bundle *bundle; struct gb_bundle *temp; - if (WARN_ON(!gb_ib)) + if (WARN_ON(!intf)) return; spin_lock_irq(&gb_bundles_lock); - list_for_each_entry_safe(bundle, temp, &gb_ib->bundles, links) { + list_for_each_entry_safe(bundle, temp, &intf->bundles, links) { list_del(&bundle->links); gb_bundle_connections_exit(bundle); device_del(&bundle->dev); @@ -109,28 +109,27 @@ void gb_bundle_destroy(struct gb_interface_block *gb_ib) spin_unlock_irq(&gb_bundles_lock); } -int gb_bundle_init(struct gb_interface_block *gb_ib, u8 bundle_id, u8 device_id) +int gb_bundle_init(struct gb_interface *intf, u8 bundle_id, u8 device_id) { struct gb_bundle *bundle; int ret; - bundle = gb_bundle_find(gb_ib, bundle_id); + bundle = gb_bundle_find(intf, bundle_id); if (!bundle) { - dev_err(gb_ib->hd->parent, "bundle %hhu not found\n", - bundle_id); + dev_err(intf->hd->parent, "bundle %hhu not found\n", bundle_id); return -ENOENT; } bundle->device_id = device_id; - ret = svc_set_route_send(bundle, gb_ib->hd); + ret = svc_set_route_send(bundle, intf->hd); if (ret) { - dev_err(gb_ib->hd->parent, "failed to set route (%d)\n", ret); + dev_err(intf->hd->parent, "failed to set route (%d)\n", ret); return ret; } ret = gb_bundle_connections_init(bundle); if (ret) { - dev_err(gb_ib->hd->parent, "interface bundle init error %d\n", + dev_err(intf->hd->parent, "interface bundle init error %d\n", ret); /* XXX clear route */ return ret; @@ -139,12 +138,12 @@ int gb_bundle_init(struct gb_interface_block *gb_ib, u8 bundle_id, u8 device_id) return 0; } -struct gb_bundle *gb_bundle_find(struct gb_interface_block *gb_ib, u8 bundle_id) +struct gb_bundle *gb_bundle_find(struct gb_interface *intf, u8 bundle_id) { struct gb_bundle *bundle; spin_lock_irq(&gb_bundles_lock); - list_for_each_entry(bundle, &gb_ib->bundles, links) + list_for_each_entry(bundle, &intf->bundles, links) if (bundle->id == bundle_id) { spin_unlock_irq(&gb_bundles_lock); return bundle; diff --git a/drivers/staging/greybus/bundle.h b/drivers/staging/greybus/bundle.h index ad14a47..c3c66fa 100644 --- a/drivers/staging/greybus/bundle.h +++ b/drivers/staging/greybus/bundle.h @@ -15,7 +15,7 @@ /* Greybus "public" definitions" */ struct gb_bundle { struct device dev; - struct gb_interface_block *gb_ib; + struct gb_interface *intf; u8 id; u8 device_id; struct list_head connections; @@ -25,10 +25,10 @@ struct gb_bundle { #define to_gb_bundle(d) container_of(d, struct gb_bundle, dev) /* Greybus "private" definitions" */ -struct gb_bundle *gb_bundle_create(struct gb_interface_block *gb_ib, u8 module_id); -void gb_bundle_destroy(struct gb_interface_block *gb_ib); -int gb_bundle_init(struct gb_interface_block *gb_ib, u8 module_id, u8 device_id); +struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 module_id); +void gb_bundle_destroy(struct gb_interface *intf); +int gb_bundle_init(struct gb_interface *intf, u8 module_id, u8 device_id); -struct gb_bundle *gb_bundle_find(struct gb_interface_block *gb_ib, u8 bundle_id); +struct gb_bundle *gb_bundle_find(struct gb_interface *intf, u8 bundle_id); #endif /* __BUNDLE_H */ diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 2a54b3e..2d61ee7 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -156,7 +156,7 @@ struct gb_connection *gb_connection_create(struct gb_bundle *bundle, return NULL; } - hd = bundle->gb_ib->hd; + hd = bundle->intf->hd; connection->hd = hd; if (!gb_connection_hd_cport_id_alloc(connection)) { gb_protocol_put(connection->protocol); @@ -237,7 +237,7 @@ void gb_connection_err(struct gb_connection *connection, const char *fmt, ...) vaf.va = &args; pr_err("greybus: [%hhu:%hhu:%hu]: %pV\n", - connection->bundle->gb_ib->module_id, + connection->bundle->intf->module_id, connection->bundle->id, connection->bundle_cport_id, &vaf); diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index eef28e1a..a0e0af5 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -34,10 +34,10 @@ EXPORT_SYMBOL_GPL(greybus_disabled); static int greybus_module_match(struct device *dev, struct device_driver *drv) { struct greybus_driver *driver = to_greybus_driver(drv); - struct gb_interface_block *gb_ib = to_gb_interface_block(dev); + struct gb_interface *intf = to_gb_interface(dev); const struct greybus_interface_block_id *id; - id = gb_ib_match_id(gb_ib, driver->id_table); + id = gb_interface_match_id(intf, driver->id_table); if (id) return 1; /* FIXME - Dynamic ids? */ @@ -46,19 +46,19 @@ static int greybus_module_match(struct device *dev, struct device_driver *drv) static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) { - struct gb_interface_block *gb_ib = NULL; + struct gb_interface *intf = NULL; struct gb_bundle *bundle = NULL; struct gb_connection *connection = NULL; - if (is_gb_interface_block(dev)) { - gb_ib = to_gb_interface_block(dev); + if (is_gb_interface(dev)) { + intf = to_gb_interface(dev); } else if (is_gb_bundle(dev)) { bundle = to_gb_bundle(dev); - gb_ib = bundle->gb_ib; + intf = bundle->intf; } else if (is_gb_connection(dev)) { connection = to_gb_connection(dev); bundle = connection->bundle; - gb_ib = bundle->gb_ib; + intf = bundle->intf; } else { dev_WARN(dev, "uevent for unknown greybus device \"type\"!\n"); return -EINVAL; @@ -94,16 +94,16 @@ struct bus_type greybus_bus_type = { static int greybus_probe(struct device *dev) { struct greybus_driver *driver = to_greybus_driver(dev->driver); - struct gb_interface_block *gb_ib = to_gb_interface_block(dev); + struct gb_interface *intf = to_gb_interface(dev); const struct greybus_interface_block_id *id; int retval; /* match id */ - id = gb_ib_match_id(gb_ib, driver->id_table); + id = gb_interface_match_id(intf, driver->id_table); if (!id) return -ENODEV; - retval = driver->probe(gb_ib, id); + retval = driver->probe(intf, id); if (retval) return retval; @@ -113,9 +113,9 @@ static int greybus_probe(struct device *dev) static int greybus_remove(struct device *dev) { struct greybus_driver *driver = to_greybus_driver(dev->driver); - struct gb_interface_block *gb_ib = to_gb_interface_block(dev); + struct gb_interface *intf = to_gb_interface(dev); - driver->disconnect(gb_ib); + driver->disconnect(intf); return 0; } diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index e0c5eb7..bca0e66 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -119,12 +119,12 @@ void greybus_remove_hd(struct greybus_host_device *hd); struct greybus_driver { const char *name; - int (*probe)(struct gb_interface_block *gb_ib, + int (*probe)(struct gb_interface *intf, const struct greybus_interface_block_id *id); - void (*disconnect)(struct gb_interface_block *gb_ib); + void (*disconnect)(struct gb_interface *intf); - int (*suspend)(struct gb_interface_block *gb_ib, pm_message_t message); - int (*resume)(struct gb_interface_block *gb_ib); + int (*suspend)(struct gb_interface *intf, pm_message_t message); + int (*resume)(struct gb_interface *intf); const struct greybus_interface_block_id *id_table; @@ -175,13 +175,13 @@ void gb_uart_device_exit(struct gb_connection *connection); int svc_set_route_send(struct gb_bundle *bundle, struct greybus_host_device *hd); -extern struct device_type greybus_interface_block_type; +extern struct device_type greybus_interface_type; extern struct device_type greybus_bundle_type; extern struct device_type greybus_connection_type; -static inline int is_gb_interface_block(const struct device *dev) +static inline int is_gb_interface(const struct device *dev) { - return dev->type == &greybus_interface_block_type; + return dev->type == &greybus_interface_type; } static inline int is_gb_bundle(const struct device *dev) diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index f47c8fc..f2c9354 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -1,5 +1,5 @@ /* - * Greybus interface block code + * Greybus interface code * * Copyright 2014 Google Inc. * Copyright 2014 Linaro Ltd. @@ -9,24 +9,24 @@ #include "greybus.h" -/* interface block sysfs attributes */ -#define gb_ib_attr(field, type) \ -static ssize_t field##_show(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ +/* interface sysfs attributes */ +#define gb_interface_attr(field, type) \ +static ssize_t field##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ { \ - struct gb_interface_block *gb_ib = to_gb_interface_block(dev); \ - return sprintf(buf, "%"#type"\n", gb_ib->field); \ + struct gb_interface *intf = to_gb_interface(dev); \ + return sprintf(buf, "%"#type"\n", intf->field); \ } \ static DEVICE_ATTR_RO(field) -gb_ib_attr(vendor, x); -gb_ib_attr(product, x); -gb_ib_attr(unique_id, llX); -gb_ib_attr(vendor_string, s); -gb_ib_attr(product_string, s); +gb_interface_attr(vendor, x); +gb_interface_attr(product, x); +gb_interface_attr(unique_id, llX); +gb_interface_attr(vendor_string, s); +gb_interface_attr(product_string, s); -static struct attribute *interface_block_attrs[] = { +static struct attribute *interface_attrs[] = { &dev_attr_vendor.attr, &dev_attr_product.attr, &dev_attr_unique_id.attr, @@ -34,143 +34,144 @@ static struct attribute *interface_block_attrs[] = { &dev_attr_product_string.attr, NULL, }; -ATTRIBUTE_GROUPS(interface_block); +ATTRIBUTE_GROUPS(interface); /* XXX This could be per-host device */ static DEFINE_SPINLOCK(gb_modules_lock); -static int gb_ib_match_one_id(struct gb_interface_block *gb_ib, - const struct greybus_interface_block_id *id) +static int gb_interface_match_one_id(struct gb_interface *intf, + const struct greybus_interface_block_id *id) { if ((id->match_flags & GREYBUS_ID_MATCH_VENDOR) && - (id->vendor != gb_ib->vendor)) + (id->vendor != intf->vendor)) return 0; if ((id->match_flags & GREYBUS_ID_MATCH_PRODUCT) && - (id->product != gb_ib->product)) + (id->product != intf->product)) return 0; if ((id->match_flags & GREYBUS_ID_MATCH_SERIAL) && - (id->unique_id != gb_ib->unique_id)) + (id->unique_id != intf->unique_id)) return 0; return 1; } const struct greybus_interface_block_id * -gb_ib_match_id(struct gb_interface_block *gb_ib, - const struct greybus_interface_block_id *id) +gb_interface_match_id(struct gb_interface *intf, + const struct greybus_interface_block_id *id) { if (id == NULL) return NULL; for (; id->vendor || id->product || id->unique_id || id->driver_info; id++) { - if (gb_ib_match_one_id(gb_ib, id)) + if (gb_interface_match_one_id(intf, id)) return id; } return NULL; } -struct gb_interface_block *gb_ib_find(struct greybus_host_device *hd, u8 module_id) +struct gb_interface *gb_interface_find(struct greybus_host_device *hd, + u8 module_id) { - struct gb_interface_block *gb_ib; + struct gb_interface *intf; - list_for_each_entry(gb_ib, &hd->modules, links) - if (gb_ib->module_id == module_id) - return gb_ib; + list_for_each_entry(intf, &hd->modules, links) + if (intf->module_id == module_id) + return intf; return NULL; } -static void greybus_ib_release(struct device *dev) +static void greybus_interface_release(struct device *dev) { - struct gb_interface_block *gb_ib = to_gb_interface_block(dev); + struct gb_interface *intf = to_gb_interface(dev); - kfree(gb_ib); + kfree(intf); } -struct device_type greybus_interface_block_type = { - .name = "greybus_interface_block", - .release = greybus_ib_release, +struct device_type greybus_interface_type = { + .name = "greybus_interface", + .release = greybus_interface_release, }; /* * A Greybus module represents a user-replicable component on an Ara - * phone. An interface block is the physical connection on that module. A - * module may have more than one interface block. + * phone. An interface is the physical connection on that module. A + * module may have more than one interface. * - * Create a gb_interface_block structure to represent a discovered module. + * Create a gb_interface structure to represent a discovered module. * The position within the Endo is encoded in the "module_id" argument. * Returns a pointer to the new module or a null pointer if a * failure occurs due to memory exhaustion. */ -static struct gb_interface_block *gb_ib_create(struct greybus_host_device *hd, - u8 module_id) +static struct gb_interface *gb_interface_create(struct greybus_host_device *hd, + u8 module_id) { - struct gb_interface_block *gb_ib; + struct gb_interface *intf; int retval; - gb_ib = gb_ib_find(hd, module_id); - if (gb_ib) { + intf = gb_interface_find(hd, module_id); + if (intf) { dev_err(hd->parent, "Duplicate module id %d will not be created\n", module_id); return NULL; } - gb_ib = kzalloc(sizeof(*gb_ib), GFP_KERNEL); - if (!gb_ib) + intf = kzalloc(sizeof(*intf), GFP_KERNEL); + if (!intf) return NULL; - gb_ib->hd = hd; /* XXX refcount? */ - gb_ib->module_id = module_id; - INIT_LIST_HEAD(&gb_ib->bundles); + intf->hd = hd; /* XXX refcount? */ + intf->module_id = module_id; + INIT_LIST_HEAD(&intf->bundles); - gb_ib->dev.parent = hd->parent; - gb_ib->dev.bus = &greybus_bus_type; - gb_ib->dev.type = &greybus_interface_block_type; - gb_ib->dev.groups = interface_block_groups; - gb_ib->dev.dma_mask = hd->parent->dma_mask; - device_initialize(&gb_ib->dev); - dev_set_name(&gb_ib->dev, "%d", module_id); + intf->dev.parent = hd->parent; + intf->dev.bus = &greybus_bus_type; + intf->dev.type = &greybus_interface_type; + intf->dev.groups = interface_groups; + intf->dev.dma_mask = hd->parent->dma_mask; + device_initialize(&intf->dev); + dev_set_name(&intf->dev, "%d", module_id); - retval = device_add(&gb_ib->dev); + retval = device_add(&intf->dev); if (retval) { pr_err("failed to add module device for id 0x%02hhx\n", module_id); - put_device(&gb_ib->dev); - kfree(gb_ib); + put_device(&intf->dev); + kfree(intf); return NULL; } spin_lock_irq(&gb_modules_lock); - list_add_tail(&gb_ib->links, &hd->modules); + list_add_tail(&intf->links, &hd->modules); spin_unlock_irq(&gb_modules_lock); - return gb_ib; + return intf; } /* * Tear down a previously set up module. */ -static void gb_ib_destroy(struct gb_interface_block *gb_ib) +static void gb_interface_destroy(struct gb_interface *intf) { - if (WARN_ON(!gb_ib)) + if (WARN_ON(!intf)) return; spin_lock_irq(&gb_modules_lock); - list_del(&gb_ib->links); + list_del(&intf->links); spin_unlock_irq(&gb_modules_lock); - gb_bundle_destroy(gb_ib); + gb_bundle_destroy(intf); - kfree(gb_ib->product_string); - kfree(gb_ib->vendor_string); + kfree(intf->product_string); + kfree(intf->vendor_string); /* kref_put(module->hd); */ - device_del(&gb_ib->dev); + device_del(&intf->dev); } /** @@ -182,11 +183,11 @@ static void gb_ib_destroy(struct gb_interface_block *gb_ib) void gb_add_module(struct greybus_host_device *hd, u8 module_id, u8 *data, int size) { - struct gb_interface_block *gb_ib; + struct gb_interface *intf; - gb_ib = gb_ib_create(hd, module_id); - if (!gb_ib) { - dev_err(hd->parent, "failed to create interface block\n"); + intf = gb_interface_create(hd, module_id); + if (!intf) { + dev_err(hd->parent, "failed to create interface\n"); return; } @@ -194,7 +195,7 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, * Parse the manifest and build up our data structures * representing what's in it. */ - if (!gb_manifest_parse(gb_ib, data, size)) { + if (!gb_manifest_parse(intf, data, size)) { dev_err(hd->parent, "manifest error\n"); goto err_module; } @@ -211,23 +212,23 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, return; err_module: - gb_ib_destroy(gb_ib); + gb_interface_destroy(intf); } void gb_remove_module(struct greybus_host_device *hd, u8 module_id) { - struct gb_interface_block *gb_ib = gb_ib_find(hd, module_id); + struct gb_interface *intf = gb_interface_find(hd, module_id); - if (gb_ib) - gb_ib_destroy(gb_ib); + if (intf) + gb_interface_destroy(intf); else - dev_err(hd->parent, "interface block id %d not found\n", module_id); + dev_err(hd->parent, "interface id %d not found\n", module_id); } void gb_remove_modules(struct greybus_host_device *hd) { - struct gb_interface_block *gb_ib, *temp; + struct gb_interface *intf, *temp; - list_for_each_entry_safe(gb_ib, temp, &hd->modules, links) - gb_ib_destroy(gb_ib); + list_for_each_entry_safe(intf, temp, &hd->modules, links) + gb_interface_destroy(intf); } diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 5c7cebc..52adc83 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -16,7 +16,7 @@ /* Greybus "public" definitions" */ -struct gb_interface_block { +struct gb_interface { struct device dev; struct list_head bundles; @@ -32,27 +32,26 @@ struct gb_interface_block { struct greybus_host_device *hd; }; -#define to_gb_interface_block(d) container_of(d, struct gb_interface_block, dev) +#define to_gb_interface(d) container_of(d, struct gb_interface, dev) -static inline void -gb_interface_block_set_drvdata(struct gb_interface_block *gb_ib, void *data) +static inline void gb_interface_set_drvdata(struct gb_interface *intf, + void *data) { - dev_set_drvdata(&gb_ib->dev, data); + dev_set_drvdata(&intf->dev, data); } -static inline void * -gb_interface_block_get_drvdata(struct gb_interface_block *gb_ib) +static inline void * gb_interface__get_drvdata(struct gb_interface *intf) { - return dev_get_drvdata(&gb_ib->dev); + return dev_get_drvdata(&intf->dev); } /* Greybus "private" definitions */ const struct greybus_interface_block_id * - gb_ib_match_id(struct gb_interface_block *gb_ib, - const struct greybus_interface_block_id *id); + gb_interface_match_id(struct gb_interface *intf, + const struct greybus_interface_block_id *id); -struct gb_interface_block *gb_ib_find(struct greybus_host_device *hd, - u8 module_id); +struct gb_interface *gb_interface_find(struct greybus_host_device *hd, + u8 module_id); #endif /* __INTERFACE_H */ diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 7661ca7..f4cd422 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -218,7 +218,7 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) * structures. Returns the number of bundles set up for the * given module. */ -static u32 gb_manifest_parse_bundles(struct gb_interface_block *gb_ib) +static u32 gb_manifest_parse_bundles(struct gb_interface *intf) { u32 count = 0; @@ -240,7 +240,7 @@ static u32 gb_manifest_parse_bundles(struct gb_interface_block *gb_ib) /* Found one. Set up its bundle structure*/ desc_interface = descriptor->data; - bundle = gb_bundle_create(gb_ib, desc_interface->id); + bundle = gb_bundle_create(intf, desc_interface->id); if (!bundle) return 0; /* Error */ @@ -257,41 +257,41 @@ static u32 gb_manifest_parse_bundles(struct gb_interface_block *gb_ib) return count; } -static bool gb_manifest_parse_module(struct gb_interface_block *gb_ib, - struct manifest_desc *module_desc) +static bool gb_manifest_parse_module(struct gb_interface *intf, + struct manifest_desc *module_desc) { struct greybus_descriptor_module *desc_module = module_desc->data; /* Handle the strings first--they can fail */ - gb_ib->vendor_string = gb_string_get(desc_module->vendor_stringid); - if (IS_ERR(gb_ib->vendor_string)) + intf->vendor_string = gb_string_get(desc_module->vendor_stringid); + if (IS_ERR(intf->vendor_string)) return false; - gb_ib->product_string = gb_string_get(desc_module->product_stringid); - if (IS_ERR(gb_ib->product_string)) { + intf->product_string = gb_string_get(desc_module->product_stringid); + if (IS_ERR(intf->product_string)) { goto out_free_vendor_string; } - gb_ib->vendor = le16_to_cpu(desc_module->vendor); - gb_ib->product = le16_to_cpu(desc_module->product); - gb_ib->unique_id = le64_to_cpu(desc_module->unique_id); + intf->vendor = le16_to_cpu(desc_module->vendor); + intf->product = le16_to_cpu(desc_module->product); + intf->unique_id = le64_to_cpu(desc_module->unique_id); /* Release the module descriptor, now that we're done with it */ release_manifest_descriptor(module_desc); /* An interface must have at least one bundle descriptor */ - if (!gb_manifest_parse_bundles(gb_ib)) { + if (!gb_manifest_parse_bundles(intf)) { pr_err("manifest bundle descriptors not valid\n"); goto out_err; } return true; out_err: - kfree(gb_ib->product_string); - gb_ib->product_string = NULL; + kfree(intf->product_string); + intf->product_string = NULL; out_free_vendor_string: - kfree(gb_ib->vendor_string); - gb_ib->vendor_string = NULL; + kfree(intf->vendor_string); + intf->vendor_string = NULL; return false; } @@ -314,12 +314,12 @@ out_free_vendor_string: * information it contains, and then remove that descriptor (and any * string descriptors it refers to) from further consideration. * - * After that we look for the interface block's bundles--there must be at + * After that we look for the interface's bundles--there must be at * least one of those. * * Returns true if parsing was successful, false otherwise. */ -bool gb_manifest_parse(struct gb_interface_block *gb_ib, void *data, size_t size) +bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size) { struct greybus_manifest *manifest; struct greybus_manifest_header *header; @@ -389,7 +389,7 @@ bool gb_manifest_parse(struct gb_interface_block *gb_ib, void *data, size_t size } /* Parse the module manifest, starting with the module descriptor */ - result = gb_manifest_parse_module(gb_ib, module_desc); + result = gb_manifest_parse_module(intf, module_desc); /* * We really should have no remaining descriptors, but we diff --git a/drivers/staging/greybus/manifest.h b/drivers/staging/greybus/manifest.h index a8316a0..90fb62d 100644 --- a/drivers/staging/greybus/manifest.h +++ b/drivers/staging/greybus/manifest.h @@ -10,7 +10,7 @@ #ifndef __MANIFEST_H #define __MANIFEST_H -struct gb_interface_block; -bool gb_manifest_parse(struct gb_interface_block *gb_ib, void *data, size_t size); +struct gb_interface; +bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size); #endif /* __MANIFEST_H */ diff --git a/drivers/staging/greybus/svc_msg.h b/drivers/staging/greybus/svc_msg.h index 1f8c4d5..471baa5 100644 --- a/drivers/staging/greybus/svc_msg.h +++ b/drivers/staging/greybus/svc_msg.h @@ -83,9 +83,8 @@ enum svc_function_hotplug_event { }; /* XXX - * Does a hotplug come from module insertion, or from detection - * of each interface block (UniPro device) in a module? Assume - * the former for now. + * Does a hotplug come from module insertion, or from detection of each + * interface (UniPro device) in a module? Assume the former for now. */ struct svc_function_hotplug { __u8 hotplug_event; /* enum svc_function_hotplug_event */ @@ -116,7 +115,7 @@ struct svc_function_power_battery_status_request { }; /* XXX - * Each interface block carries power, so it's possible these things + * Each interface carries power, so it's possible these things * are associated with each UniPro device and not just the module. * For now it's safe to assume it's per-module. */ @@ -145,7 +144,7 @@ enum svc_function_suspend_command_type { SVC_SUSPEND_FIXME_2 = 0x01, }; -/* We'll want independent control for multi-interface block modules */ +/* We'll want independent control for multi-interface modules */ struct svc_function_suspend { __u8 suspend_command_type; /* enum function_suspend_command_type */ __u8 device_id; -- cgit v0.10.2 From edb0e0b5a17d28c7207197f415c41ab25e75b5d5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 19 Dec 2014 14:56:32 -0800 Subject: greybus: interface: rename greybus_interface_block_id to greybus_interface_id This moves the id structure name to not have "block" in it, as that doesn't make sense anymore with the renaming of the gb_interface structure. Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index a0e0af5..96410cb 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -35,7 +35,7 @@ static int greybus_module_match(struct device *dev, struct device_driver *drv) { struct greybus_driver *driver = to_greybus_driver(drv); struct gb_interface *intf = to_gb_interface(dev); - const struct greybus_interface_block_id *id; + const struct greybus_interface_id *id; id = gb_interface_match_id(intf, driver->id_table); if (id) @@ -95,7 +95,7 @@ static int greybus_probe(struct device *dev) { struct greybus_driver *driver = to_greybus_driver(dev->driver); struct gb_interface *intf = to_gb_interface(dev); - const struct greybus_interface_block_id *id; + const struct greybus_interface_id *id; int retval; /* match id */ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index bca0e66..4db5956 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -120,13 +120,13 @@ struct greybus_driver { const char *name; int (*probe)(struct gb_interface *intf, - const struct greybus_interface_block_id *id); + const struct greybus_interface_id *id); void (*disconnect)(struct gb_interface *intf); int (*suspend)(struct gb_interface *intf, pm_message_t message); int (*resume)(struct gb_interface *intf); - const struct greybus_interface_block_id *id_table; + const struct greybus_interface_id *id_table; struct device_driver driver; }; diff --git a/drivers/staging/greybus/greybus_id.h b/drivers/staging/greybus/greybus_id.h index da70aab..53da8e7 100644 --- a/drivers/staging/greybus/greybus_id.h +++ b/drivers/staging/greybus/greybus_id.h @@ -9,7 +9,7 @@ #include -struct greybus_interface_block_id { +struct greybus_interface_id { __u16 match_flags; __u16 vendor; __u16 product; @@ -18,7 +18,7 @@ struct greybus_interface_block_id { kernel_ulong_t driver_info __aligned(sizeof(kernel_ulong_t)); }; -/* Used to match the greybus_interface_block_id */ +/* Used to match the greybus_interface_id */ #define GREYBUS_ID_MATCH_VENDOR BIT(0) #define GREYBUS_ID_MATCH_PRODUCT BIT(1) #define GREYBUS_ID_MATCH_SERIAL BIT(2) diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index f2c9354..d840ae6 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -41,7 +41,7 @@ ATTRIBUTE_GROUPS(interface); static DEFINE_SPINLOCK(gb_modules_lock); static int gb_interface_match_one_id(struct gb_interface *intf, - const struct greybus_interface_block_id *id) + const struct greybus_interface_id *id) { if ((id->match_flags & GREYBUS_ID_MATCH_VENDOR) && (id->vendor != intf->vendor)) @@ -58,9 +58,9 @@ static int gb_interface_match_one_id(struct gb_interface *intf, return 1; } -const struct greybus_interface_block_id * +const struct greybus_interface_id * gb_interface_match_id(struct gb_interface *intf, - const struct greybus_interface_block_id *id) + const struct greybus_interface_id *id) { if (id == NULL) return NULL; diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 52adc83..f6f16df 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -47,9 +47,9 @@ static inline void * gb_interface__get_drvdata(struct gb_interface *intf) /* Greybus "private" definitions */ -const struct greybus_interface_block_id * +const struct greybus_interface_id * gb_interface_match_id(struct gb_interface *intf, - const struct greybus_interface_block_id *id); + const struct greybus_interface_id *id); struct gb_interface *gb_interface_find(struct greybus_host_device *hd, u8 module_id); -- cgit v0.10.2 From 426fa950595af017f5e96ff8bde972e06605ed34 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 19 Dec 2014 14:56:33 -0800 Subject: greybus: interface.h: remove unused #defines MAX_CPORTS_PER_MODULE and MAX_STRINGS_PER_MODULE are not used anywhere anymore, so remove them lest someone thing we have limits. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index f6f16df..75f8135 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -10,11 +10,6 @@ #ifndef __INTERFACE_H #define __INTERFACE_H -/* Increase these values if needed */ -#define MAX_CPORTS_PER_MODULE 10 -#define MAX_STRINGS_PER_MODULE 10 - - /* Greybus "public" definitions" */ struct gb_interface { struct device dev; -- cgit v0.10.2 From 0e51032f381738e3e854febc627936e1c4d8deda Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 19 Dec 2014 14:56:34 -0800 Subject: greybus: greybus_id.h: minor typo fixes Align up the BIT() #defines and properly comment the include block define. Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_id.h b/drivers/staging/greybus/greybus_id.h index 53da8e7..3c462ef 100644 --- a/drivers/staging/greybus/greybus_id.h +++ b/drivers/staging/greybus/greybus_id.h @@ -20,7 +20,7 @@ struct greybus_interface_id { /* Used to match the greybus_interface_id */ #define GREYBUS_ID_MATCH_VENDOR BIT(0) -#define GREYBUS_ID_MATCH_PRODUCT BIT(1) +#define GREYBUS_ID_MATCH_PRODUCT BIT(1) #define GREYBUS_ID_MATCH_SERIAL BIT(2) -#endif /* __LINUX_GREYBUS_H */ +#endif /* __LINUX_GREYBUS_ID_H */ -- cgit v0.10.2 From 13e6aacf60ad6791268238b989a081edfe47e7d2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 19 Dec 2014 14:56:35 -0800 Subject: greybus: interface: we really are creating/destroying interfaces not modules. rename gb_add_module -> gb_add_interface rename gb_remove_modules -> gb_remove_interfaces rename gb_remove_module -> gb_remove_interface And move the function prototypes to interface.h, where they belong. Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index f9c63e4..e69566b 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -175,8 +175,8 @@ static void svc_hotplug(struct svc_function_hotplug *hotplug, return; } dev_dbg(hd->parent, "module id %d added\n", module_id); - gb_add_module(hd, module_id, hotplug->data, - payload_length - 0x02); + gb_add_interface(hd, module_id, hotplug->data, + payload_length - 0x02); break; case SVC_HOTUNPLUG_EVENT: @@ -189,7 +189,7 @@ static void svc_hotplug(struct svc_function_hotplug *hotplug, return; } dev_dbg(hd->parent, "module id %d removed\n", module_id); - gb_remove_module(hd, module_id); + gb_remove_interface(hd, module_id); break; default: diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 96410cb..3e00055 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -195,7 +195,7 @@ void greybus_remove_hd(struct greybus_host_device *hd) { /* Tear down all modules that happen to be associated with this host * controller */ - gb_remove_modules(hd); + gb_remove_interfaces(hd); kref_put_mutex(&hd->kref, free_hd, &hd_mutex); } EXPORT_SYMBOL_GPL(greybus_remove_hd); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 4db5956..7071892 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -154,13 +154,6 @@ void greybus_deregister(struct greybus_driver *driver); int greybus_disabled(void); -/* Internal functions to gb module, move to internal .h file eventually. */ - -void gb_add_module(struct greybus_host_device *hd, u8 module_id, - u8 *data, int size); -void gb_remove_module(struct greybus_host_device *hd, u8 module_id); -void gb_remove_modules(struct greybus_host_device *hd); - int greybus_svc_in(struct greybus_host_device *hd, u8 *data, int length); int gb_ap_init(void); void gb_ap_exit(void); diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index d840ae6..67b14df 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -175,13 +175,13 @@ static void gb_interface_destroy(struct gb_interface *intf) } /** - * gb_add_module + * gb_add_interface * * Pass in a buffer that _should_ contain a Greybus module manifest * and register a greybus device structure with the kernel core. */ -void gb_add_module(struct greybus_host_device *hd, u8 module_id, - u8 *data, int size) +void gb_add_interface(struct greybus_host_device *hd, u8 module_id, + u8 *data, int size) { struct gb_interface *intf; @@ -197,7 +197,7 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, */ if (!gb_manifest_parse(intf, data, size)) { dev_err(hd->parent, "manifest error\n"); - goto err_module; + goto err_parse; } /* @@ -211,11 +211,11 @@ void gb_add_module(struct greybus_host_device *hd, u8 module_id, return; -err_module: +err_parse: gb_interface_destroy(intf); } -void gb_remove_module(struct greybus_host_device *hd, u8 module_id) +void gb_remove_interface(struct greybus_host_device *hd, u8 module_id) { struct gb_interface *intf = gb_interface_find(hd, module_id); @@ -225,7 +225,7 @@ void gb_remove_module(struct greybus_host_device *hd, u8 module_id) dev_err(hd->parent, "interface id %d not found\n", module_id); } -void gb_remove_modules(struct greybus_host_device *hd) +void gb_remove_interfaces(struct greybus_host_device *hd) { struct gb_interface *intf, *temp; diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 75f8135..70dad49e 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -49,4 +49,10 @@ const struct greybus_interface_id * struct gb_interface *gb_interface_find(struct greybus_host_device *hd, u8 module_id); +void gb_add_interface(struct greybus_host_device *hd, u8 module_id, + u8 *data, int size); +void gb_remove_interface(struct greybus_host_device *hd, u8 module_id); +void gb_remove_interfaces(struct greybus_host_device *hd); + + #endif /* __INTERFACE_H */ -- cgit v0.10.2 From 1cd56a80969d7c5cfc74d847c6f81cc2ab8dc829 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 19 Dec 2014 14:56:36 -0800 Subject: greybus: greybus_host_device: rename modules -> interfaces This is really a list of interfaces, not modules, so rename it so that we don't get confused when we really do add modules to the whole system later on. Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 3e00055..c90f74c 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -183,7 +183,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver kref_init(&hd->kref); hd->parent = parent; hd->driver = driver; - INIT_LIST_HEAD(&hd->modules); + INIT_LIST_HEAD(&hd->interfaces); INIT_LIST_HEAD(&hd->connections); ida_init(&hd->cport_id_map); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 7071892..ced329a 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -99,7 +99,7 @@ struct greybus_host_device { struct device *parent; const struct greybus_host_driver *driver; - struct list_head modules; + struct list_head interfaces; struct list_head connections; struct ida cport_id_map; u8 device_id; diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 67b14df..d4ec788 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -79,7 +79,7 @@ struct gb_interface *gb_interface_find(struct greybus_host_device *hd, { struct gb_interface *intf; - list_for_each_entry(intf, &hd->modules, links) + list_for_each_entry(intf, &hd->interfaces, links) if (intf->module_id == module_id) return intf; @@ -147,7 +147,7 @@ static struct gb_interface *gb_interface_create(struct greybus_host_device *hd, } spin_lock_irq(&gb_modules_lock); - list_add_tail(&intf->links, &hd->modules); + list_add_tail(&intf->links, &hd->interfaces); spin_unlock_irq(&gb_modules_lock); return intf; @@ -229,6 +229,6 @@ void gb_remove_interfaces(struct greybus_host_device *hd) { struct gb_interface *intf, *temp; - list_for_each_entry_safe(intf, temp, &hd->modules, links) + list_for_each_entry_safe(intf, temp, &hd->interfaces, links) gb_interface_destroy(intf); } diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 70dad49e..5dd2c20 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -15,7 +15,7 @@ struct gb_interface { struct device dev; struct list_head bundles; - struct list_head links; /* greybus_host_device->modules */ + struct list_head links; /* greybus_host_device->interfaces */ u8 module_id; /* Physical location within the Endo */ /* Information taken from the manifest module descriptor */ -- cgit v0.10.2 From 4901175f282792450f899b86b2d5d0048d6c11b2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 19 Dec 2014 14:56:37 -0800 Subject: greybus: interface: rename gb_modules_lock -> gb_interfaces_lock It's a local interface lock, not a modules lock, so rename it. Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index d4ec788..96897f2 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -38,7 +38,7 @@ ATTRIBUTE_GROUPS(interface); /* XXX This could be per-host device */ -static DEFINE_SPINLOCK(gb_modules_lock); +static DEFINE_SPINLOCK(gb_interfaces_lock); static int gb_interface_match_one_id(struct gb_interface *intf, const struct greybus_interface_id *id) @@ -146,9 +146,9 @@ static struct gb_interface *gb_interface_create(struct greybus_host_device *hd, return NULL; } - spin_lock_irq(&gb_modules_lock); + spin_lock_irq(&gb_interfaces_lock); list_add_tail(&intf->links, &hd->interfaces); - spin_unlock_irq(&gb_modules_lock); + spin_unlock_irq(&gb_interfaces_lock); return intf; } @@ -161,9 +161,9 @@ static void gb_interface_destroy(struct gb_interface *intf) if (WARN_ON(!intf)) return; - spin_lock_irq(&gb_modules_lock); + spin_lock_irq(&gb_interfaces_lock); list_del(&intf->links); - spin_unlock_irq(&gb_modules_lock); + spin_unlock_irq(&gb_interfaces_lock); gb_bundle_destroy(intf); -- cgit v0.10.2 From df671553cbe286e885e61b61f8c126e034854a89 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 21 Dec 2014 14:10:26 -0800 Subject: greybus: add module support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modules in the greybus system sit above the interface, so insert them early in the sysfs tree. We dynamically create them when we have an interface that references a module, as we don't get a "module create" message directly. They also dynamically go away when the last interface associated with a module is removed. Naming scheme for modules/interfaces/bundles/connections is bumped up by one ':', and now looks like the following: /sys/bus/greybus $ tree . ├── devices │   ├── 7 -> ../../../devices/pci0000:00/0000:00:14.0/usb1/1-1/7 │   ├── 7:7 -> ../../../devices/pci0000:00/0000:00:14.0/usb1/1-1/7/7:7 │   ├── 7:7:0 -> ../../../devices/pci0000:00/0000:00:14.0/usb1/1-1/7/7:7/7:7:0 │   └── 7:7:0:1 -> ../../../devices/pci0000:00/0000:00:14.0/usb1/1-1/7/7:7/7:7:0/7:7:0:1 ├── drivers ├── drivers_autoprobe ├── drivers_probe └── uevent 6 directories, 3 files /sys/bus/greybus $ grep . devices/*/uevent devices/7/uevent:DEVTYPE=greybus_module devices/7:7/uevent:DEVTYPE=greybus_interface devices/7:7:0/uevent:DEVTYPE=greybus_bundle devices/7:7:0:1/uevent:DEVTYPE=greybus_connection We still have some "confusion" about interface ids and module ids, which will be cleaned up later when the svc control protocol changes die down, right now we just name a module after the interface as we don't have any modules that have multiple interfaces in our systems. This has been tested with gbsim. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 6c0b0ca..0d3977d 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -2,6 +2,7 @@ greybus-y := core.o \ debugfs.o \ ap.o \ manifest.o \ + module.o \ interface.o \ bundle.o \ connection.o \ diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 2ac67a24..28a8222 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -71,7 +71,7 @@ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 interface_id) bundle->dev.type = &greybus_bundle_type; bundle->dev.groups = bundle_groups; device_initialize(&bundle->dev); - dev_set_name(&bundle->dev, "%d:%d", intf->module_id, interface_id); + dev_set_name(&bundle->dev, "%s:%d", dev_name(&intf->dev), interface_id); retval = device_add(&bundle->dev); if (retval) { diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 2d61ee7..3f786bf 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -237,7 +237,7 @@ void gb_connection_err(struct gb_connection *connection, const char *fmt, ...) vaf.va = &args; pr_err("greybus: [%hhu:%hhu:%hu]: %pV\n", - connection->bundle->intf->module_id, + connection->bundle->intf->module->module_id, connection->bundle->id, connection->bundle_cport_id, &vaf); diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index c90f74c..f6ca89a 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -46,11 +46,14 @@ static int greybus_module_match(struct device *dev, struct device_driver *drv) static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) { + struct gb_module *module = NULL; struct gb_interface *intf = NULL; struct gb_bundle *bundle = NULL; struct gb_connection *connection = NULL; - if (is_gb_interface(dev)) { + if (is_gb_module(dev)) { + module = to_gb_module(dev); + } else if (is_gb_interface(dev)) { intf = to_gb_interface(dev); } else if (is_gb_bundle(dev)) { bundle = to_gb_bundle(dev); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index ced329a..68382b3 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -24,6 +24,7 @@ #include "greybus_id.h" #include "greybus_manifest.h" #include "manifest.h" +#include "module.h" #include "interface.h" #include "bundle.h" #include "connection.h" @@ -168,10 +169,16 @@ void gb_uart_device_exit(struct gb_connection *connection); int svc_set_route_send(struct gb_bundle *bundle, struct greybus_host_device *hd); +extern struct device_type greybus_module_type; extern struct device_type greybus_interface_type; extern struct device_type greybus_bundle_type; extern struct device_type greybus_connection_type; +static inline int is_gb_module(const struct device *dev) +{ + return dev->type == &greybus_module_type; +} + static inline int is_gb_interface(const struct device *dev) { return dev->type == &greybus_interface_type; diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 96897f2..4b502c6 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -74,13 +74,15 @@ gb_interface_match_id(struct gb_interface *intf, return NULL; } +// FIXME, odds are you don't want to call this function, rework the caller to +// not need it please. struct gb_interface *gb_interface_find(struct greybus_host_device *hd, u8 module_id) { struct gb_interface *intf; list_for_each_entry(intf, &hd->interfaces, links) - if (intf->module_id == module_id) + if (intf->module->module_id == module_id) return intf; return NULL; @@ -105,43 +107,51 @@ struct device_type greybus_interface_type = { * * Create a gb_interface structure to represent a discovered module. * The position within the Endo is encoded in the "module_id" argument. - * Returns a pointer to the new module or a null pointer if a + * Returns a pointer to the new interfce or a null pointer if a * failure occurs due to memory exhaustion. */ static struct gb_interface *gb_interface_create(struct greybus_host_device *hd, u8 module_id) { + struct gb_module *module; struct gb_interface *intf; int retval; + u8 interface_id = module_id; - intf = gb_interface_find(hd, module_id); + // FIXME we need an interface id here to check for this properly! + intf = gb_interface_find(hd, interface_id); if (intf) { dev_err(hd->parent, "Duplicate module id %d will not be created\n", module_id); return NULL; } + module = gb_module_find_or_create(hd, module_id); + if (!module) + return NULL; + intf = kzalloc(sizeof(*intf), GFP_KERNEL); if (!intf) return NULL; intf->hd = hd; /* XXX refcount? */ - intf->module_id = module_id; + intf->module = module; INIT_LIST_HEAD(&intf->bundles); - intf->dev.parent = hd->parent; + intf->dev.parent = &module->dev; intf->dev.bus = &greybus_bus_type; intf->dev.type = &greybus_interface_type; intf->dev.groups = interface_groups; intf->dev.dma_mask = hd->parent->dma_mask; device_initialize(&intf->dev); - dev_set_name(&intf->dev, "%d", module_id); + dev_set_name(&intf->dev, "%s:%d", dev_name(&module->dev), interface_id); retval = device_add(&intf->dev); if (retval) { pr_err("failed to add module device for id 0x%02hhx\n", module_id); put_device(&intf->dev); + put_device(&module->dev); kfree(intf); return NULL; } @@ -169,6 +179,7 @@ static void gb_interface_destroy(struct gb_interface *intf) kfree(intf->product_string); kfree(intf->vendor_string); + put_device(&intf->module->dev); /* kref_put(module->hd); */ device_del(&intf->dev); diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 5dd2c20..fd5001e 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -16,7 +16,7 @@ struct gb_interface { struct list_head bundles; struct list_head links; /* greybus_host_device->interfaces */ - u8 module_id; /* Physical location within the Endo */ + u8 interface_id; /* Physical location within the Endo */ /* Information taken from the manifest module descriptor */ u16 vendor; @@ -25,6 +25,7 @@ struct gb_interface { char *product_string; u64 unique_id; + struct gb_module *module; struct greybus_host_device *hd; }; #define to_gb_interface(d) container_of(d, struct gb_interface, dev) diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index 66c2713..f0010a8 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -21,6 +21,11 @@ } #endif +#ifndef __ATTR_RW +#define __ATTR_RW(_name) __ATTR(_name, (S_IWUSR | S_IRUGO), \ + _name##_show, _name##_store) +#endif + #ifndef DEVICE_ATTR_RO #define DEVICE_ATTR_RO(_name) \ struct device_attribute dev_attr_##_name = __ATTR_RO(_name) @@ -31,6 +36,11 @@ struct device_attribute dev_attr_##_name = __ATTR_WO(_name) #endif +#ifndef DEVICE_ATTR_RW +#define DEVICE_ATTR_RW(_name) \ + struct device_attribute dev_attr_##_name = __ATTR_RW(_name) +#endif + #ifndef U8_MAX #define U8_MAX ((u8)~0U) #endif /* ! U8_MAX */ diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c new file mode 100644 index 0000000..625e2d4 --- /dev/null +++ b/drivers/staging/greybus/module.c @@ -0,0 +1,140 @@ +/* + * Greybus module code + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include "greybus.h" + + +/* + * List of modules in the system. We really should just walk the list the + * driver core provides us, but as we have lots of different things on the same + * "bus" at the same time, a single list of modules is simplest for now. + */ +static DEFINE_SPINLOCK(gb_modules_lock); +static LIST_HEAD(module_list); + +/* module sysfs attributes */ +#define gb_module_attr(field, type) \ +static ssize_t field##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct gb_module *module = to_gb_module(dev); \ + return sprintf(buf, "%"#type"\n", module->field); \ +} \ +static DEVICE_ATTR_RO(field) + +// FIXME, do we really need this attribute? +gb_module_attr(module_id, x); + +static ssize_t epm_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + // FIXME, implement something here + return sprintf(buf, "1\n"); +} + +static ssize_t epm_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + // FIXME, implement something here. + return 0; +} +static DEVICE_ATTR_RW(epm); + +static struct attribute *module_attrs[] = { + &dev_attr_module_id.attr, + &dev_attr_epm.attr, + NULL, +}; +ATTRIBUTE_GROUPS(module); + +static void greybus_module_release(struct device *dev) +{ + struct gb_module *module = to_gb_module(dev); + + spin_lock(&gb_modules_lock); + list_del(&module->list); + spin_unlock(&gb_modules_lock); + + kfree(module); +} + +struct device_type greybus_module_type = { + .name = "greybus_module", + .release = greybus_module_release, +}; + +/* + * Search the list of modules in the system. If one is found, return it, with + * the reference count incremented. + */ +static struct gb_module *gb_module_find(u8 module_id) +{ + struct gb_module *module; + + spin_lock(&gb_modules_lock); + list_for_each_entry(module, &module_list, list) { + if (module->module_id == module_id) { + get_device(&module->dev); + goto exit; + } + } + module = NULL; +exit: + spin_unlock(&gb_modules_lock); + return module; +} + +static struct gb_module *gb_module_create(struct greybus_host_device *hd, + u8 module_id) +{ + struct gb_module *module; + int retval; + + module = kzalloc(sizeof(*module), GFP_KERNEL); + if (!module) + return NULL; + + module->module_id = module_id; + module->dev.parent = hd->parent; + module->dev.bus = &greybus_bus_type; + module->dev.type = &greybus_module_type; + module->dev.groups = module_groups; + module->dev.dma_mask = hd->parent->dma_mask; + device_initialize(&module->dev); + dev_set_name(&module->dev, "%d", module_id); + + retval = device_add(&module->dev); + if (retval) { + pr_err("failed to add module device for id 0x%02hhx\n", + module_id); + put_device(&module->dev); + kfree(module); + return NULL; + } + + spin_lock(&gb_modules_lock); + list_add_tail(&module->list, &module_list); + spin_unlock(&gb_modules_lock); + + return module; +} + +struct gb_module *gb_module_find_or_create(struct greybus_host_device *hd, + u8 module_id) +{ + struct gb_module *module; + + module = gb_module_find(module_id); + if (module) + return module; + + return gb_module_create(hd, module_id); +} + diff --git a/drivers/staging/greybus/module.h b/drivers/staging/greybus/module.h new file mode 100644 index 0000000..9ca7c28 --- /dev/null +++ b/drivers/staging/greybus/module.h @@ -0,0 +1,28 @@ +/* + * Greybus module code + * + * Copyright 2014 Google Inc. + * + * Released under the GPLv2 only. + */ + +#ifndef __MODULE_H +#define __MODULE_H + +/* Greybus "public" definitions" */ +struct gb_module { + struct device dev; + + struct list_head list; + u8 module_id; /* Physical location within the Endo */ +}; +#define to_gb_module(d) container_of(d, struct gb_module, dev) + +struct greybus_host_device; + +/* Greybus "private" definitions */ +struct gb_module *gb_module_find_or_create(struct greybus_host_device *hd, + u8 module_id); + + +#endif /* __MODULE_H */ -- cgit v0.10.2 From 86cad66677942601941c2b516ece2f5741123eda Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 23 Dec 2014 15:16:50 -0800 Subject: greybus: interface: remove global manifest_descs list The list was global and had no locking. It's not like we were ever parsing more than one manifest at the same time right now, but we might in the future. And we really want this to be local to the interface itself, for future work redoing how to bind protocols to bundles, so move the list to the interface structure. Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 4b502c6..d2b2e3d 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -137,6 +137,7 @@ static struct gb_interface *gb_interface_create(struct greybus_host_device *hd, intf->hd = hd; /* XXX refcount? */ intf->module = module; INIT_LIST_HEAD(&intf->bundles); + INIT_LIST_HEAD(&intf->manifest_descs); intf->dev.parent = &module->dev; intf->dev.bus = &greybus_bus_type; diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index fd5001e..f5b0cef 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -16,6 +16,7 @@ struct gb_interface { struct list_head bundles; struct list_head links; /* greybus_host_device->interfaces */ + struct list_head manifest_descs; u8 interface_id; /* Physical location within the Endo */ /* Information taken from the manifest module descriptor */ diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index f4cd422..8b61b34 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -28,20 +28,18 @@ struct manifest_desc { enum greybus_descriptor_type type; }; -static LIST_HEAD(manifest_descs); - static void release_manifest_descriptor(struct manifest_desc *descriptor) { list_del(&descriptor->links); kfree(descriptor); } -static void release_manifest_descriptors(void) +static void release_manifest_descriptors(struct gb_interface *intf) { struct manifest_desc *descriptor; struct manifest_desc *next; - list_for_each_entry_safe(descriptor, next, &manifest_descs, links) + list_for_each_entry_safe(descriptor, next, &intf->manifest_descs, links) release_manifest_descriptor(descriptor); } @@ -55,7 +53,8 @@ static void release_manifest_descriptors(void) * Returns the number of bytes consumed by the descriptor, or a * negative errno. */ -static int identify_descriptor(struct greybus_descriptor *desc, size_t size) +static int identify_descriptor(struct gb_interface *intf, + struct greybus_descriptor *desc, size_t size) { struct greybus_descriptor_header *desc_header = &desc->header; struct manifest_desc *descriptor; @@ -116,7 +115,7 @@ static int identify_descriptor(struct greybus_descriptor *desc, size_t size) descriptor->size = desc_size; descriptor->data = (u8 *)desc + sizeof(*desc_header); descriptor->type = desc_header->type; - list_add_tail(&descriptor->links, &manifest_descs); + list_add_tail(&descriptor->links, &intf->manifest_descs); return desc_size; } @@ -132,7 +131,7 @@ static int identify_descriptor(struct greybus_descriptor *desc, size_t size) * Otherwise returns a pointer to a newly-allocated copy of the * descriptor string, or an error-coded pointer on failure. */ -static char *gb_string_get(u8 string_id) +static char *gb_string_get(struct gb_interface *intf, u8 string_id) { struct greybus_descriptor_string *desc_string; struct manifest_desc *descriptor; @@ -143,7 +142,7 @@ static char *gb_string_get(u8 string_id) if (!string_id) return NULL; - list_for_each_entry(descriptor, &manifest_descs, links) { + list_for_each_entry(descriptor, &intf->manifest_descs, links) { if (descriptor->type != GREYBUS_TYPE_STRING) continue; @@ -175,7 +174,8 @@ static char *gb_string_get(u8 string_id) * for the functions that use them. Returns the number of bundles * set up for the given interface, or 0 if there is an error. */ -static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) +static u32 gb_manifest_parse_cports(struct gb_interface *intf, + struct gb_bundle *bundle) { u32 count = 0; @@ -187,7 +187,7 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) bool found = false; /* Find a cport descriptor */ - list_for_each_entry(descriptor, &manifest_descs, links) { + list_for_each_entry(descriptor, &intf->manifest_descs, links) { if (descriptor->type == GREYBUS_TYPE_CPORT) { desc_cport = descriptor->data; if (desc_cport->bundle == bundle->id) { @@ -229,7 +229,7 @@ static u32 gb_manifest_parse_bundles(struct gb_interface *intf) bool found = false; /* Find an bundle descriptor */ - list_for_each_entry(descriptor, &manifest_descs, links) { + list_for_each_entry(descriptor, &intf->manifest_descs, links) { if (descriptor->type == GREYBUS_TYPE_INTERFACE) { found = true; break; @@ -245,7 +245,7 @@ static u32 gb_manifest_parse_bundles(struct gb_interface *intf) return 0; /* Error */ /* Now go set up this bundle's functions and cports */ - if (!gb_manifest_parse_cports(bundle)) + if (!gb_manifest_parse_cports(intf, bundle)) return 0; /* Error parsing cports */ count++; @@ -263,11 +263,12 @@ static bool gb_manifest_parse_module(struct gb_interface *intf, struct greybus_descriptor_module *desc_module = module_desc->data; /* Handle the strings first--they can fail */ - intf->vendor_string = gb_string_get(desc_module->vendor_stringid); + intf->vendor_string = gb_string_get(intf, desc_module->vendor_stringid); if (IS_ERR(intf->vendor_string)) return false; - intf->product_string = gb_string_get(desc_module->product_stringid); + intf->product_string = gb_string_get(intf, + desc_module->product_stringid); if (IS_ERR(intf->product_string)) { goto out_free_vendor_string; } @@ -331,7 +332,7 @@ bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size) bool result; /* Manifest descriptor list should be empty here */ - if (WARN_ON(!list_empty(&manifest_descs))) + if (WARN_ON(!list_empty(&intf->manifest_descs))) return false; /* we have to have at _least_ the manifest header */ @@ -364,7 +365,7 @@ bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size) while (size) { int desc_size; - desc_size = identify_descriptor(desc, size); + desc_size = identify_descriptor(intf, desc, size); if (desc_size <= 0) { if (!desc_size) pr_err("zero-sized manifest descriptor\n"); @@ -376,7 +377,7 @@ bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size) } /* There must be a single module descriptor */ - list_for_each_entry(descriptor, &manifest_descs, links) { + list_for_each_entry(descriptor, &intf->manifest_descs, links) { if (descriptor->type == GREYBUS_TYPE_MODULE) if (!found++) module_desc = descriptor; @@ -395,10 +396,10 @@ bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size) * We really should have no remaining descriptors, but we * don't know what newer format manifests might leave. */ - if (result && !list_empty(&manifest_descs)) + if (result && !list_empty(&intf->manifest_descs)) pr_info("excess descriptors in module manifest\n"); out: - release_manifest_descriptors(); + release_manifest_descriptors(intf); return result; } -- cgit v0.10.2 From 7c7d5b9a942eea5ae450487d47a95c1d0f9a4e64 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 23 Dec 2014 15:16:51 -0800 Subject: greybus: protocol: switch gb_protocol_register() to return an int We will want to return this value as a return value for module_init() and bool does not play well with module_init(). So make it a "real" error value and return int and fix up all callers of the function. Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index df1d7ee..f6b0dd6 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -367,7 +367,7 @@ static struct gb_protocol battery_protocol = { .request_recv = NULL, /* no incoming requests */ }; -bool gb_battery_protocol_init(void) +int gb_battery_protocol_init(void) { return gb_protocol_register(&battery_protocol); } diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index 152ba50..cf60a4a 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -532,7 +532,7 @@ static struct gb_protocol gpio_protocol = { .request_recv = NULL, /* no incoming requests */ }; -bool gb_gpio_protocol_init(void) +int gb_gpio_protocol_init(void) { return gb_protocol_register(&gpio_protocol); } diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index 491fac4..b78de6b 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -438,7 +438,7 @@ static struct gb_protocol i2c_protocol = { .request_recv = NULL, /* no incoming requests */ }; -bool gb_i2c_protocol_init(void) +int gb_i2c_protocol_init(void) { return gb_protocol_register(&i2c_protocol); } diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index 4ca3ae5..227c531 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -39,8 +39,7 @@ static struct gb_protocol *_gb_protocol_find(u8 id, u8 major, u8 minor) return NULL; } -/* Returns true if protocol was successfully registered, false otherwise */ -bool gb_protocol_register(struct gb_protocol *protocol) +int gb_protocol_register(struct gb_protocol *protocol) { struct gb_protocol *existing; u8 id = protocol->id; @@ -75,7 +74,7 @@ bool gb_protocol_register(struct gb_protocol *protocol) /* A matching protocol has already been registered */ spin_unlock_irq(&gb_protocols_lock); - return false; + return -EEXIST; } /* @@ -85,7 +84,7 @@ bool gb_protocol_register(struct gb_protocol *protocol) list_add_tail(&protocol->links, &existing->links); spin_unlock_irq(&gb_protocols_lock); - return true; + return 0; } /* @@ -99,10 +98,13 @@ bool gb_protocol_register(struct gb_protocol *protocol) * * Returns true if successful, false otherwise. */ -bool gb_protocol_deregister(struct gb_protocol *protocol) +int gb_protocol_deregister(struct gb_protocol *protocol) { u8 protocol_count = 0; + if (!protocol) + return 0; + spin_lock_irq(&gb_protocols_lock); protocol = _gb_protocol_find(protocol->id, protocol->major, protocol->minor); @@ -166,35 +168,35 @@ bool gb_protocol_init(void) { bool ret = true; - if (!gb_battery_protocol_init()) { + if (gb_battery_protocol_init()) { pr_err("error initializing battery protocol\n"); ret = false; } - if (!gb_gpio_protocol_init()) { + if (gb_gpio_protocol_init()) { pr_err("error initializing gpio protocol\n"); ret = false; } - if (!gb_i2c_protocol_init()) { + if (gb_i2c_protocol_init()) { pr_err("error initializing i2c protocol\n"); ret = false; } - if (!gb_pwm_protocol_init()) { + if (gb_pwm_protocol_init()) { pr_err("error initializing pwm protocol\n"); ret = false; } - if (!gb_uart_protocol_init()) { + if (gb_uart_protocol_init()) { pr_err("error initializing uart protocol\n"); ret = false; } - if (!gb_sdio_protocol_init()) { + if (gb_sdio_protocol_init()) { pr_err("error initializing sdio protocol\n"); ret = false; } - if (!gb_vibrator_protocol_init()) { + if (gb_vibrator_protocol_init()) { pr_err("error initializing vibrator protocol\n"); ret = false; } - if (!gb_usb_protocol_init()) { + if (gb_usb_protocol_init()) { pr_err("error initializing usb protocol\n"); ret = false; } diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index 7d33b20..49214d6 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -36,8 +36,8 @@ struct gb_protocol { gb_request_recv_t request_recv; }; -bool gb_protocol_register(struct gb_protocol *protocol); -bool gb_protocol_deregister(struct gb_protocol *protocol); +int gb_protocol_register(struct gb_protocol *protocol); +int gb_protocol_deregister(struct gb_protocol *protocol); struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor); void gb_protocol_put(struct gb_protocol *protocol); @@ -47,28 +47,28 @@ void gb_protocol_put(struct gb_protocol *protocol); * Declared here for now. They could be added via modules, or maybe * just use initcalls (which level?). */ -extern bool gb_battery_protocol_init(void); +extern int gb_battery_protocol_init(void); extern void gb_battery_protocol_exit(void); -extern bool gb_gpio_protocol_init(void); +extern int gb_gpio_protocol_init(void); extern void gb_gpio_protocol_exit(void); -extern bool gb_i2c_protocol_init(void); +extern int gb_i2c_protocol_init(void); extern void gb_i2c_protocol_exit(void); -extern bool gb_pwm_protocol_init(void); +extern int gb_pwm_protocol_init(void); extern void gb_pwm_protocol_exit(void); -extern bool gb_uart_protocol_init(void); +extern int gb_uart_protocol_init(void); extern void gb_uart_protocol_exit(void); -extern bool gb_sdio_protocol_init(void); +extern int gb_sdio_protocol_init(void); extern void gb_sdio_protocol_exit(void); -extern bool gb_vibrator_protocol_init(void); +extern int gb_vibrator_protocol_init(void); extern void gb_vibrator_protocol_exit(void); -extern bool gb_usb_protocol_init(void); +extern int gb_usb_protocol_init(void); extern void gb_usb_protocol_exit(void); bool gb_protocol_init(void); diff --git a/drivers/staging/greybus/pwm-gb.c b/drivers/staging/greybus/pwm-gb.c index c505f1d..5f02e78 100644 --- a/drivers/staging/greybus/pwm-gb.c +++ b/drivers/staging/greybus/pwm-gb.c @@ -319,7 +319,7 @@ static struct gb_protocol pwm_protocol = { .request_recv = NULL, /* no incoming requests */ }; -bool gb_pwm_protocol_init(void) +int gb_pwm_protocol_init(void) { return gb_protocol_register(&pwm_protocol); } diff --git a/drivers/staging/greybus/sdio-gb.c b/drivers/staging/greybus/sdio-gb.c index 8de7dc4..13293a6 100644 --- a/drivers/staging/greybus/sdio-gb.c +++ b/drivers/staging/greybus/sdio-gb.c @@ -87,7 +87,7 @@ static struct gb_protocol sdio_protocol = { .request_recv = NULL, /* no incoming requests */ }; -bool gb_sdio_protocol_init(void) +int gb_sdio_protocol_init(void) { return gb_protocol_register(&sdio_protocol); } diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index faba00e..825de74 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -775,7 +775,7 @@ static struct gb_protocol uart_protocol = { .request_recv = NULL, /* FIXME we have 2 types of requests!!! */ }; -bool gb_uart_protocol_init(void) +int gb_uart_protocol_init(void) { return gb_protocol_register(&uart_protocol); } diff --git a/drivers/staging/greybus/usb-gb.c b/drivers/staging/greybus/usb-gb.c index 2b5f69e..b3ba50b 100644 --- a/drivers/staging/greybus/usb-gb.c +++ b/drivers/staging/greybus/usb-gb.c @@ -384,7 +384,7 @@ static struct gb_protocol usb_protocol = { .request_recv = NULL, /* FIXME we have requests!!! */ }; -bool gb_usb_protocol_init(void) +int gb_usb_protocol_init(void) { return gb_protocol_register(&usb_protocol); } diff --git a/drivers/staging/greybus/vibrator-gb.c b/drivers/staging/greybus/vibrator-gb.c index fb48112..3ef7d06 100644 --- a/drivers/staging/greybus/vibrator-gb.c +++ b/drivers/staging/greybus/vibrator-gb.c @@ -205,7 +205,7 @@ static struct gb_protocol vibrator_protocol = { .request_recv = NULL, /* no incoming requests */ }; -bool gb_vibrator_protocol_init(void) +int gb_vibrator_protocol_init(void) { int retval; -- cgit v0.10.2 From df469a942301c9bf4d939e1139c1a435079b288a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 23 Dec 2014 15:16:52 -0800 Subject: greybus: export needed symbols for protocols Protocol handlers need some greybus symbols, so export them so that they can be built outside of the greybus core. Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 3f786bf..191df53 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -243,6 +243,7 @@ void gb_connection_err(struct gb_connection *connection, const char *fmt, ...) va_end(args); } +EXPORT_SYMBOL_GPL(gb_connection_err); int gb_connection_init(struct gb_connection *connection) { diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index a057c83..087e0cc 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -567,6 +567,7 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, return gb_operation_create_common(connection, type, request_size, response_size); } +EXPORT_SYMBOL_GPL(gb_operation_create); static struct gb_operation * gb_operation_create_incoming(struct gb_connection *connection, u16 id, @@ -623,6 +624,7 @@ void gb_operation_put(struct gb_operation *operation) if (!WARN_ON(!operation)) kref_put(&operation->kref, _gb_operation_destroy); } +EXPORT_SYMBOL_GPL(gb_operation_put); /* Tell the requester we're done */ static void gb_operation_sync_callback(struct gb_operation *operation) @@ -710,6 +712,7 @@ int gb_operation_request_send_sync(struct gb_operation *operation) return gb_operation_result(operation); } +EXPORT_SYMBOL_GPL(gb_operation_request_send_sync); /* * Send a response for an incoming operation request. A non-zero @@ -958,6 +961,7 @@ int gb_operation_sync(struct gb_connection *connection, int type, return ret; } +EXPORT_SYMBOL_GPL(gb_operation_sync); int gb_operation_init(void) { diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index 227c531..7536a30 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -86,6 +86,7 @@ int gb_protocol_register(struct gb_protocol *protocol) return 0; } +EXPORT_SYMBOL_GPL(gb_protocol_register); /* * De-register a previously registered protocol. @@ -117,6 +118,7 @@ int gb_protocol_deregister(struct gb_protocol *protocol) return protocol && !protocol_count; } +EXPORT_SYMBOL_GPL(gb_protocol_deregister); /* Returns the requested protocol if available, or a null pointer */ struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor) -- cgit v0.10.2 From fb69cb506c16d38de2c3b62ea4cf6e8728bd4348 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 23 Dec 2014 15:16:53 -0800 Subject: greybus: protocol: split binding of prototcols to connections out of init When adding a new protocol to the system, walk all bundles and try to hook up any connections that do not have a protocol already. This sets the stage to allow for protocols to be loaded at any time, not just before the device is seen in the system. Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 28a8222..973ea39 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -45,6 +45,36 @@ struct device_type greybus_bundle_type = { /* XXX This could be per-host device or per-module */ static DEFINE_SPINLOCK(gb_bundles_lock); +static int __bundle_bind_protocols(struct device *dev, void *data) +{ + struct gb_bundle *bundle; + struct gb_connection *connection; + + if (!is_gb_bundle(dev)) + return 0; + + bundle = to_gb_bundle(dev); + + list_for_each_entry(connection, &bundle->connections, bundle_links) { + gb_connection_bind_protocol(connection); + } + + return 0; +} + +/* + * Walk all bundles in the system, and see if any connections are not bound to a + * specific prototcol. If they are not, then try to find one for it and bind it + * to it. + * + * This is called after registering a new protocol. + */ +void gb_bundle_bind_protocols(void) +{ + bus_for_each_dev(&greybus_bus_type, NULL, NULL, + __bundle_bind_protocols); +} + /* * Create a gb_bundle structure to represent a discovered * bundle. Returns a pointer to the new bundle or a null diff --git a/drivers/staging/greybus/bundle.h b/drivers/staging/greybus/bundle.h index c3c66fa..e11d456 100644 --- a/drivers/staging/greybus/bundle.h +++ b/drivers/staging/greybus/bundle.h @@ -30,5 +30,6 @@ void gb_bundle_destroy(struct gb_interface *intf); int gb_bundle_init(struct gb_interface *intf, u8 module_id, u8 device_id); struct gb_bundle *gb_bundle_find(struct gb_interface *intf, u8 bundle_id); +void gb_bundle_bind_protocols(void); #endif /* __BUNDLE_H */ diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 191df53..2f70837 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -124,6 +124,32 @@ struct device_type greybus_connection_type = { .release = gb_connection_release, }; + +void gb_connection_bind_protocol(struct gb_connection *connection) +{ + struct gb_bundle *bundle; + struct gb_protocol *protocol; + + /* If we already have a protocol bound here, just return */ + if (connection->protocol) + return; + + protocol = gb_protocol_get(connection->protocol_id, + connection->major, + connection->minor); + if (!protocol) + return; + connection->protocol = protocol; + + /* + * If we have a valid device_id for the bundle, then we have an active + * device, so bring up the connection at the same time. + * */ + bundle = connection->bundle; + if (bundle->device_id != 0xff) + gb_connection_init(connection); +} + /* * Set up a Greybus connection, representing the bidirectional link * between a CPort on a (local) Greybus host device and a CPort on @@ -148,13 +174,9 @@ struct gb_connection *gb_connection_create(struct gb_bundle *bundle, if (!connection) return NULL; - /* XXX Will have to establish connections to get version */ - connection->protocol = gb_protocol_get(protocol_id, major, minor); - if (!connection->protocol) { - pr_err("protocol 0x%02hhx not found\n", protocol_id); - kfree(connection); - return NULL; - } + connection->protocol_id = protocol_id; + connection->major = major; + connection->minor = minor; hd = bundle->intf->hd; connection->hd = hd; @@ -187,6 +209,12 @@ struct gb_connection *gb_connection_create(struct gb_bundle *bundle, return NULL; } + /* XXX Will have to establish connections to get version */ + gb_connection_bind_protocol(connection); + if (!connection->protocol) + dev_warn(&bundle->dev, + "protocol 0x%02hhx handler not found\n", protocol_id); + spin_lock_irq(&gb_connections_lock); list_add_tail(&connection->hd_links, &hd->connections); list_add_tail(&connection->bundle_links, &bundle->connections); @@ -250,8 +278,8 @@ int gb_connection_init(struct gb_connection *connection) int ret; if (!connection->protocol) { - gb_connection_err(connection, "uninitialized connection"); - return -EIO; + dev_warn(&connection->dev, "init without protocol.\n"); + return 0; } /* Need to enable the connection to initialize it */ @@ -266,7 +294,7 @@ int gb_connection_init(struct gb_connection *connection) void gb_connection_exit(struct gb_connection *connection) { if (!connection->protocol) { - gb_connection_err(connection, "uninitialized connection"); + dev_warn(&connection->dev, "exit without protocol.\n"); return; } connection->state = GB_CONNECTION_STATE_DESTROYING; diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index caf52b8..b07df79 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -33,6 +33,9 @@ struct gb_connection { struct list_head bundle_links; struct gb_protocol *protocol; + u8 protocol_id; + u8 major; + u8 minor; enum gb_connection_state state; @@ -58,4 +61,6 @@ void greybus_data_rcvd(struct greybus_host_device *hd, u16 cport_id, __printf(2, 3) void gb_connection_err(struct gb_connection *connection, const char *fmt, ...); +void gb_connection_bind_protocol(struct gb_connection *connection); + #endif /* __CONNECTION_H */ diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 087e0cc..44cfd50 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -206,6 +206,9 @@ static void gb_operation_request_handle(struct gb_operation *operation) { struct gb_protocol *protocol = operation->connection->protocol; + if (!protocol) + return; + /* * If the protocol has no incoming request handler, report * an error and mark the request bad. diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index 7536a30..2527532 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -84,6 +84,12 @@ int gb_protocol_register(struct gb_protocol *protocol) list_add_tail(&protocol->links, &existing->links); spin_unlock_irq(&gb_protocols_lock); + /* + * Go try to bind any unbound connections, as we have a + * new protocol in the system + */ + gb_bundle_bind_protocols(); + return 0; } EXPORT_SYMBOL_GPL(gb_protocol_register); -- cgit v0.10.2 From 900ceba9e480f49bb8fef688994b4fbdb1688b77 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 23 Dec 2014 15:16:54 -0800 Subject: greybus: i2c-gb: split out into a stand-alone kernel module. This splits the i2c-gb protocol into a stand-alone kernel module. It's not going to stay in this fashion for long, this was done to test the "can a protcol be loaded later" logic. Future refactoring is going to move the gpbridge protocols to a separate kernel module, where this protocol is going to live. But for now, split it out, it is good to test with, and shows a bug in gbsim at the moment. Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 0d3977d..6ce00c2 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -8,7 +8,6 @@ greybus-y := core.o \ connection.o \ protocol.o \ operation.o \ - i2c-gb.o \ gpio-gb.o \ pwm-gb.o \ sdio-gb.o \ @@ -18,6 +17,7 @@ greybus-y := core.o \ usb-gb.o obj-m += greybus.o +obj-m += i2c-gb.o obj-m += es1-ap-usb.o KERNELVER ?= $(shell uname -r) diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index b78de6b..d430bea 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -438,12 +438,6 @@ static struct gb_protocol i2c_protocol = { .request_recv = NULL, /* no incoming requests */ }; -int gb_i2c_protocol_init(void) -{ - return gb_protocol_register(&i2c_protocol); -} +gb_protocol_driver(&i2c_protocol); -void gb_i2c_protocol_exit(void) -{ - gb_protocol_deregister(&i2c_protocol); -} +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index 2527532..ee8ee3e 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -184,10 +184,6 @@ bool gb_protocol_init(void) pr_err("error initializing gpio protocol\n"); ret = false; } - if (gb_i2c_protocol_init()) { - pr_err("error initializing i2c protocol\n"); - ret = false; - } if (gb_pwm_protocol_init()) { pr_err("error initializing pwm protocol\n"); ret = false; @@ -217,7 +213,6 @@ void gb_protocol_exit(void) gb_vibrator_protocol_exit(); gb_sdio_protocol_exit(); gb_uart_protocol_exit(); - gb_i2c_protocol_exit(); gb_gpio_protocol_exit(); gb_battery_protocol_exit(); } diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index 49214d6..e2555b7 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -53,9 +53,6 @@ extern void gb_battery_protocol_exit(void); extern int gb_gpio_protocol_init(void); extern void gb_gpio_protocol_exit(void); -extern int gb_i2c_protocol_init(void); -extern void gb_i2c_protocol_exit(void); - extern int gb_pwm_protocol_init(void); extern void gb_pwm_protocol_exit(void); @@ -74,4 +71,16 @@ extern void gb_usb_protocol_exit(void); bool gb_protocol_init(void); void gb_protocol_exit(void); +#define gb_protocol_driver(__protocol) \ +static int __init protocol_init(void) \ +{ \ + return gb_protocol_register(__protocol); \ +} \ +module_init(protocol_init); \ +static void __exit protocol_exit(void) \ +{ \ + gb_protocol_deregister(__protocol); \ +} \ +module_exit(protocol_exit); + #endif /* __PROTOCOL_H */ -- cgit v0.10.2 From 1b6ea0db016941a0919c17839c1772cceb1955c1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Dec 2014 13:01:39 -0800 Subject: greybus: bundle: create GB_DEVICE_ID_BAD Use a "name" for when we don't have a valid device id yet, instead of a magic value of 0xff. Reported-by: Alex Elder Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 973ea39..96153c5 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -91,9 +91,11 @@ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 interface_id) bundle->intf = intf; bundle->id = interface_id; - bundle->device_id = 0xff; /* Invalid device id to start with */ INIT_LIST_HEAD(&bundle->connections); + /* Invalid device id to start with */ + bundle->device_id = GB_DEVICE_ID_BAD; + /* Build up the bundle device structures and register it with the * driver core */ bundle->dev.parent = &intf->dev; diff --git a/drivers/staging/greybus/bundle.h b/drivers/staging/greybus/bundle.h index e11d456..62969cf 100644 --- a/drivers/staging/greybus/bundle.h +++ b/drivers/staging/greybus/bundle.h @@ -24,6 +24,8 @@ struct gb_bundle { }; #define to_gb_bundle(d) container_of(d, struct gb_bundle, dev) +#define GB_DEVICE_ID_BAD 0xff + /* Greybus "private" definitions" */ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 module_id); void gb_bundle_destroy(struct gb_interface *intf); diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 2f70837..82b03c3 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -146,7 +146,7 @@ void gb_connection_bind_protocol(struct gb_connection *connection) * device, so bring up the connection at the same time. * */ bundle = connection->bundle; - if (bundle->device_id != 0xff) + if (bundle->device_id != GB_DEVICE_ID_BAD) gb_connection_init(connection); } -- cgit v0.10.2 From 12a5dfc9acf690504e7266a8f310702bc9e6872c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Dec 2014 13:01:40 -0800 Subject: greybus: protocol: add a module owner to a protocol Now that protocols can be in a module, we need to reference count them to lock them into memory so they can't be removed while in use. So add a module owner structure, and have it automatically be assigned when registering the protocol. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index ee8ee3e..c6c0fd3 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -39,13 +39,15 @@ static struct gb_protocol *_gb_protocol_find(u8 id, u8 major, u8 minor) return NULL; } -int gb_protocol_register(struct gb_protocol *protocol) +int __gb_protocol_register(struct gb_protocol *protocol, struct module *module) { struct gb_protocol *existing; u8 id = protocol->id; u8 major = protocol->major; u8 minor = protocol->minor; + protocol->owner = module; + /* * The protocols list is sorted first by protocol id (low to * high), then by major version (high to low), and finally @@ -92,7 +94,7 @@ int gb_protocol_register(struct gb_protocol *protocol) return 0; } -EXPORT_SYMBOL_GPL(gb_protocol_register); +EXPORT_SYMBOL_GPL(__gb_protocol_register); /* * De-register a previously registered protocol. @@ -135,9 +137,13 @@ struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor) spin_lock_irq(&gb_protocols_lock); protocol = _gb_protocol_find(id, major, minor); if (protocol) { - protocol_count = protocol->count; - if (protocol_count != U8_MAX) - protocol->count++; + if (!try_module_get(protocol->owner)) { + protocol = NULL; + } else { + protocol_count = protocol->count; + if (protocol_count != U8_MAX) + protocol->count++; + } } spin_unlock_irq(&gb_protocols_lock); @@ -163,6 +169,7 @@ void gb_protocol_put(struct gb_protocol *protocol) protocol_count = protocol->count; if (protocol_count) protocol->count--; + module_put(protocol->owner); } spin_unlock_irq(&gb_protocols_lock); if (protocol) diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index e2555b7..62f024d 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -34,11 +34,15 @@ struct gb_protocol { gb_connection_init_t connection_init; gb_connection_exit_t connection_exit; gb_request_recv_t request_recv; + struct module *owner; }; -int gb_protocol_register(struct gb_protocol *protocol); +int __gb_protocol_register(struct gb_protocol *protocol, struct module *module); int gb_protocol_deregister(struct gb_protocol *protocol); +#define gb_protocol_register(protocol) \ + __gb_protocol_register(protocol, THIS_MODULE) + struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor); void gb_protocol_put(struct gb_protocol *protocol); -- cgit v0.10.2 From 66b676fd88a681b149e98c462e2c0337c2848770 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Dec 2014 13:01:41 -0800 Subject: greybus: vibrator-gb: move vibrator protocol to a stand-alone module. We can't use the gb_protocol_driver() macro here as we need to do some init and exit logic when loading and removing, so "open code" the module init and exit functions. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 6ce00c2..f728468 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -13,11 +13,11 @@ greybus-y := core.o \ sdio-gb.o \ uart-gb.o \ battery-gb.o \ - vibrator-gb.o \ usb-gb.o obj-m += greybus.o obj-m += i2c-gb.o +obj-m += vibrator-gb.o obj-m += es1-ap-usb.o KERNELVER ?= $(shell uname -r) diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index c6c0fd3..0d3c336 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -203,10 +203,6 @@ bool gb_protocol_init(void) pr_err("error initializing sdio protocol\n"); ret = false; } - if (gb_vibrator_protocol_init()) { - pr_err("error initializing vibrator protocol\n"); - ret = false; - } if (gb_usb_protocol_init()) { pr_err("error initializing usb protocol\n"); ret = false; @@ -217,7 +213,6 @@ bool gb_protocol_init(void) void gb_protocol_exit(void) { gb_usb_protocol_exit(); - gb_vibrator_protocol_exit(); gb_sdio_protocol_exit(); gb_uart_protocol_exit(); gb_gpio_protocol_exit(); diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index 62f024d..7b1c09c 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -66,9 +66,6 @@ extern void gb_uart_protocol_exit(void); extern int gb_sdio_protocol_init(void); extern void gb_sdio_protocol_exit(void); -extern int gb_vibrator_protocol_init(void); -extern void gb_vibrator_protocol_exit(void); - extern int gb_usb_protocol_init(void); extern void gb_usb_protocol_exit(void); diff --git a/drivers/staging/greybus/vibrator-gb.c b/drivers/staging/greybus/vibrator-gb.c index 3ef7d06..71c96d3 100644 --- a/drivers/staging/greybus/vibrator-gb.c +++ b/drivers/staging/greybus/vibrator-gb.c @@ -205,7 +205,7 @@ static struct gb_protocol vibrator_protocol = { .request_recv = NULL, /* no incoming requests */ }; -int gb_vibrator_protocol_init(void) +static __init int protocol_init(void) { int retval; @@ -216,8 +216,13 @@ int gb_vibrator_protocol_init(void) return gb_protocol_register(&vibrator_protocol); } -void gb_vibrator_protocol_exit(void) +static __exit void protocol_exit(void) { gb_protocol_deregister(&vibrator_protocol); class_unregister(&vibrator_class); } + +module_init(protocol_init); +module_exit(protocol_exit); + +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 7dd26263248c6c567c05772959d4d6a21240daa8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Dec 2014 13:01:42 -0800 Subject: greybus: battery-gb: move the battery protocol out to a stand-alone module This moves the battery class protocol to be a stand-alone kernel module. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index f728468..79cb193 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -12,12 +12,12 @@ greybus-y := core.o \ pwm-gb.o \ sdio-gb.o \ uart-gb.o \ - battery-gb.o \ usb-gb.o obj-m += greybus.o obj-m += i2c-gb.o obj-m += vibrator-gb.o +obj-m += battery-gb.o obj-m += es1-ap-usb.o KERNELVER ?= $(shell uname -r) diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index f6b0dd6..7ce3737 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -367,12 +367,6 @@ static struct gb_protocol battery_protocol = { .request_recv = NULL, /* no incoming requests */ }; -int gb_battery_protocol_init(void) -{ - return gb_protocol_register(&battery_protocol); -} +gb_protocol_driver(&battery_protocol); -void gb_battery_protocol_exit(void) -{ - gb_protocol_deregister(&battery_protocol); -} +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index 0d3c336..e32f4ac 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -183,10 +183,6 @@ bool gb_protocol_init(void) { bool ret = true; - if (gb_battery_protocol_init()) { - pr_err("error initializing battery protocol\n"); - ret = false; - } if (gb_gpio_protocol_init()) { pr_err("error initializing gpio protocol\n"); ret = false; @@ -216,5 +212,4 @@ void gb_protocol_exit(void) gb_sdio_protocol_exit(); gb_uart_protocol_exit(); gb_gpio_protocol_exit(); - gb_battery_protocol_exit(); } diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index 7b1c09c..1acc615 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -51,9 +51,6 @@ void gb_protocol_put(struct gb_protocol *protocol); * Declared here for now. They could be added via modules, or maybe * just use initcalls (which level?). */ -extern int gb_battery_protocol_init(void); -extern void gb_battery_protocol_exit(void); - extern int gb_gpio_protocol_init(void); extern void gb_gpio_protocol_exit(void); -- cgit v0.10.2 From e1308c1fb675878ace7a489c50b2ae52c598d294 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Dec 2014 13:01:43 -0800 Subject: greybus: gpb: Create a "GP Bridge" kernel module This bundles together the existing GP Bridged PHY protocols that were part of the Greybus core: USB, UART, SDIO, PWM, and GPIO. This is now a stand-alone kernel module. More logic will be moving here in the future to handle bridged devices. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 79cb193..5d73aed 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -7,14 +7,17 @@ greybus-y := core.o \ bundle.o \ connection.o \ protocol.o \ - operation.o \ - gpio-gb.o \ - pwm-gb.o \ + operation.o + +gpbridge-y := gpb.o \ sdio-gb.o \ uart-gb.o \ + pwm-gb.o \ + gpio-gb.o \ usb-gb.o obj-m += greybus.o +obj-m += gpbridge.o obj-m += i2c-gb.o obj-m += vibrator-gb.o obj-m += battery-gb.o diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index f6ca89a..ee8bba5 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -233,17 +233,8 @@ static int __init gb_init(void) goto error_operation; } - if (!gb_protocol_init()) { - /* This only fails for duplicate protocol registration */ - retval = -EEXIST; - pr_err("gb_protocol_init failed\n"); - goto error_protocol; - } - return 0; /* Success */ -error_protocol: - gb_operation_exit(); error_operation: gb_ap_exit(); error_ap: @@ -256,7 +247,6 @@ error_bus: static void __exit gb_exit(void) { - gb_protocol_exit(); gb_operation_exit(); gb_ap_exit(); bus_unregister(&greybus_bus_type); diff --git a/drivers/staging/greybus/gpb.c b/drivers/staging/greybus/gpb.c new file mode 100644 index 0000000..0c4f46c --- /dev/null +++ b/drivers/staging/greybus/gpb.c @@ -0,0 +1,70 @@ +/* + * Greybus GP Bridge driver + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include + +#include "greybus.h" + + +static int __init gpbridge_init(void) +{ + if (gb_gpio_protocol_init()) { + pr_err("error initializing gpio protocol\n"); + goto error_gpio; + } + if (gb_pwm_protocol_init()) { + pr_err("error initializing pwm protocol\n"); + goto error_pwm; + } + if (gb_uart_protocol_init()) { + pr_err("error initializing uart protocol\n"); + goto error_uart; + } + if (gb_sdio_protocol_init()) { + pr_err("error initializing sdio protocol\n"); + goto error_sdio; + } + if (gb_usb_protocol_init()) { + pr_err("error initializing usb protocol\n"); + goto error_usb; + } + return 0; + +error_usb: + gb_sdio_protocol_exit(); +error_sdio: + gb_uart_protocol_exit(); +error_uart: + gb_pwm_protocol_exit(); +error_pwm: + gb_gpio_protocol_exit(); +error_gpio: + return -EPROTO; +} + +static void __exit gpbridge_exit(void) +{ + gb_usb_protocol_exit(); + gb_sdio_protocol_exit(); + gb_uart_protocol_exit(); + gb_pwm_protocol_exit(); + gb_gpio_protocol_exit(); +} + +module_init(gpbridge_init); +module_exit(gpbridge_exit); + +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index e32f4ac..654adbc 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -178,38 +178,3 @@ void gb_protocol_put(struct gb_protocol *protocol) pr_err("protocol id %hhu version %hhu.%hhu not found\n", protocol->id, major, minor); } - -bool gb_protocol_init(void) -{ - bool ret = true; - - if (gb_gpio_protocol_init()) { - pr_err("error initializing gpio protocol\n"); - ret = false; - } - if (gb_pwm_protocol_init()) { - pr_err("error initializing pwm protocol\n"); - ret = false; - } - if (gb_uart_protocol_init()) { - pr_err("error initializing uart protocol\n"); - ret = false; - } - if (gb_sdio_protocol_init()) { - pr_err("error initializing sdio protocol\n"); - ret = false; - } - if (gb_usb_protocol_init()) { - pr_err("error initializing usb protocol\n"); - ret = false; - } - return ret; -} - -void gb_protocol_exit(void) -{ - gb_usb_protocol_exit(); - gb_sdio_protocol_exit(); - gb_uart_protocol_exit(); - gb_gpio_protocol_exit(); -} diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index 1acc615..1f6fd74 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -66,9 +66,6 @@ extern void gb_sdio_protocol_exit(void); extern int gb_usb_protocol_init(void); extern void gb_usb_protocol_exit(void); -bool gb_protocol_init(void); -void gb_protocol_exit(void); - #define gb_protocol_driver(__protocol) \ static int __init protocol_init(void) \ { \ -- cgit v0.10.2 From 2c07817e72450e6fab7b49c3cbb35799bc418880 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Dec 2014 13:01:44 -0800 Subject: greybus: i2c-gb: move i2c protocol into the gpbridge driver The i2c protocol belongs in the gpbridge driver, so move it there. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 5d73aed..8e6551b 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -14,11 +14,11 @@ gpbridge-y := gpb.o \ uart-gb.o \ pwm-gb.o \ gpio-gb.o \ + i2c-gb.o \ usb-gb.o obj-m += greybus.o obj-m += gpbridge.o -obj-m += i2c-gb.o obj-m += vibrator-gb.o obj-m += battery-gb.o obj-m += es1-ap-usb.o diff --git a/drivers/staging/greybus/gpb.c b/drivers/staging/greybus/gpb.c index 0c4f46c..0776df6 100644 --- a/drivers/staging/greybus/gpb.c +++ b/drivers/staging/greybus/gpb.c @@ -41,8 +41,14 @@ static int __init gpbridge_init(void) pr_err("error initializing usb protocol\n"); goto error_usb; } + if (gb_i2c_protocol_init()) { + pr_err("error initializing usb protocol\n"); + goto error_i2c; + } return 0; +error_i2c: + gb_usb_protocol_exit(); error_usb: gb_sdio_protocol_exit(); error_sdio: @@ -57,6 +63,7 @@ error_gpio: static void __exit gpbridge_exit(void) { + gb_i2c_protocol_exit(); gb_usb_protocol_exit(); gb_sdio_protocol_exit(); gb_uart_protocol_exit(); diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index d430bea..b78de6b 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -438,6 +438,12 @@ static struct gb_protocol i2c_protocol = { .request_recv = NULL, /* no incoming requests */ }; -gb_protocol_driver(&i2c_protocol); +int gb_i2c_protocol_init(void) +{ + return gb_protocol_register(&i2c_protocol); +} -MODULE_LICENSE("GPL v2"); +void gb_i2c_protocol_exit(void) +{ + gb_protocol_deregister(&i2c_protocol); +} diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index 1f6fd74..2d4fcfa 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -66,6 +66,9 @@ extern void gb_sdio_protocol_exit(void); extern int gb_usb_protocol_init(void); extern void gb_usb_protocol_exit(void); +extern int gb_i2c_protocol_init(void); +extern void gb_i2c_protocol_exit(void); + #define gb_protocol_driver(__protocol) \ static int __init protocol_init(void) \ { \ -- cgit v0.10.2 From e5646710c1836abb038415d3009f1c72d6794b77 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Dec 2014 13:01:46 -0800 Subject: greybus: module: get rid of global list of modules Use the list that the driver core keeps of our structure, no need to duplicate it with a local list as well. This gets rid of a static lock too, always a nice thing to do. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index 625e2d4..56a55fe 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -10,14 +10,6 @@ #include "greybus.h" -/* - * List of modules in the system. We really should just walk the list the - * driver core provides us, but as we have lots of different things on the same - * "bus" at the same time, a single list of modules is simplest for now. - */ -static DEFINE_SPINLOCK(gb_modules_lock); -static LIST_HEAD(module_list); - /* module sysfs attributes */ #define gb_module_attr(field, type) \ static ssize_t field##_show(struct device *dev, \ @@ -58,10 +50,6 @@ static void greybus_module_release(struct device *dev) { struct gb_module *module = to_gb_module(dev); - spin_lock(&gb_modules_lock); - list_del(&module->list); - spin_unlock(&gb_modules_lock); - kfree(module); } @@ -70,24 +58,35 @@ struct device_type greybus_module_type = { .release = greybus_module_release, }; +static int module_find(struct device *dev, void *data) +{ + struct gb_module *module; + u8 *module_id = data; + + if (!is_gb_module(dev)) + return 0; + + module = to_gb_module(dev); + if (module->module_id == *module_id) + return 1; + + return 0; +} + /* * Search the list of modules in the system. If one is found, return it, with * the reference count incremented. */ static struct gb_module *gb_module_find(u8 module_id) { - struct gb_module *module; + struct device *dev; + struct gb_module *module = NULL; + + dev = bus_find_device(&greybus_bus_type, NULL, + &module_id, module_find); + if (dev) + module = to_gb_module(dev); - spin_lock(&gb_modules_lock); - list_for_each_entry(module, &module_list, list) { - if (module->module_id == module_id) { - get_device(&module->dev); - goto exit; - } - } - module = NULL; -exit: - spin_unlock(&gb_modules_lock); return module; } @@ -119,10 +118,6 @@ static struct gb_module *gb_module_create(struct greybus_host_device *hd, return NULL; } - spin_lock(&gb_modules_lock); - list_add_tail(&module->list, &module_list); - spin_unlock(&gb_modules_lock); - return module; } diff --git a/drivers/staging/greybus/module.h b/drivers/staging/greybus/module.h index 9ca7c28..75a8818 100644 --- a/drivers/staging/greybus/module.h +++ b/drivers/staging/greybus/module.h @@ -12,8 +12,6 @@ /* Greybus "public" definitions" */ struct gb_module { struct device dev; - - struct list_head list; u8 module_id; /* Physical location within the Endo */ }; #define to_gb_module(d) container_of(d, struct gb_module, dev) -- cgit v0.10.2 From 7422a1ec2e208762cacd3c3368e6313046b3e3d5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Dec 2014 13:01:45 -0800 Subject: greybus: protocol: name protocols. We want to be able to "blame" a protocol for things at times, so give them a name we can refer to them by. Announce when they are added or removed from the system so we have a chance to know what is going on in the kernel logs. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c index 7ce3737..2130d73 100644 --- a/drivers/staging/greybus/battery-gb.c +++ b/drivers/staging/greybus/battery-gb.c @@ -359,6 +359,7 @@ static void gb_battery_connection_exit(struct gb_connection *connection) } static struct gb_protocol battery_protocol = { + .name = "battery", .id = GREYBUS_PROTOCOL_BATTERY, .major = 0, .minor = 1, diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index cf60a4a..5fcd018 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -524,6 +524,7 @@ static void gb_gpio_connection_exit(struct gb_connection *connection) } static struct gb_protocol gpio_protocol = { + .name = "gpio", .id = GREYBUS_PROTOCOL_GPIO, .major = 0, .minor = 1, diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index b78de6b..3b86258 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -430,6 +430,7 @@ static void gb_i2c_connection_exit(struct gb_connection *connection) } static struct gb_protocol i2c_protocol = { + .name = "i2c", .id = GREYBUS_PROTOCOL_I2C, .major = 0, .minor = 1, diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index 654adbc..4d6ffdd 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -7,6 +7,8 @@ * Released under the GPLv2 only. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include "greybus.h" /* Global list of registered protocols */ @@ -86,6 +88,8 @@ int __gb_protocol_register(struct gb_protocol *protocol, struct module *module) list_add_tail(&protocol->links, &existing->links); spin_unlock_irq(&gb_protocols_lock); + pr_info("Registered %s protocol.\n", protocol->name); + /* * Go try to bind any unbound connections, as we have a * new protocol in the system @@ -124,6 +128,9 @@ int gb_protocol_deregister(struct gb_protocol *protocol) } spin_unlock_irq(&gb_protocols_lock); + if (protocol) + pr_info("Deregistered %s protocol.\n", protocol->name); + return protocol && !protocol_count; } EXPORT_SYMBOL_GPL(gb_protocol_deregister); diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index 2d4fcfa..8bda524 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -35,6 +35,7 @@ struct gb_protocol { gb_connection_exit_t connection_exit; gb_request_recv_t request_recv; struct module *owner; + char *name; }; int __gb_protocol_register(struct gb_protocol *protocol, struct module *module); diff --git a/drivers/staging/greybus/pwm-gb.c b/drivers/staging/greybus/pwm-gb.c index 5f02e78..91f7b87 100644 --- a/drivers/staging/greybus/pwm-gb.c +++ b/drivers/staging/greybus/pwm-gb.c @@ -311,6 +311,7 @@ static void gb_pwm_connection_exit(struct gb_connection *connection) } static struct gb_protocol pwm_protocol = { + .name = "pwm", .id = GREYBUS_PROTOCOL_PWM, .major = 0, .minor = 1, diff --git a/drivers/staging/greybus/sdio-gb.c b/drivers/staging/greybus/sdio-gb.c index 13293a6..d324846 100644 --- a/drivers/staging/greybus/sdio-gb.c +++ b/drivers/staging/greybus/sdio-gb.c @@ -79,6 +79,7 @@ static void gb_sdio_connection_exit(struct gb_connection *connection) } static struct gb_protocol sdio_protocol = { + .name = "sdio", .id = GREYBUS_PROTOCOL_SDIO, .major = 0, .minor = 1, diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c index 825de74..0320620 100644 --- a/drivers/staging/greybus/uart-gb.c +++ b/drivers/staging/greybus/uart-gb.c @@ -767,6 +767,7 @@ static void gb_tty_exit(void) } static struct gb_protocol uart_protocol = { + .name = "uart", .id = GREYBUS_PROTOCOL_UART, .major = 0, .minor = 1, diff --git a/drivers/staging/greybus/usb-gb.c b/drivers/staging/greybus/usb-gb.c index b3ba50b..010ef9e 100644 --- a/drivers/staging/greybus/usb-gb.c +++ b/drivers/staging/greybus/usb-gb.c @@ -376,6 +376,7 @@ static void gb_usb_connection_exit(struct gb_connection *connection) } static struct gb_protocol usb_protocol = { + .name = "usb", .id = GREYBUS_PROTOCOL_USB, .major = 0, .minor = 1, diff --git a/drivers/staging/greybus/vibrator-gb.c b/drivers/staging/greybus/vibrator-gb.c index 71c96d3..c85d950 100644 --- a/drivers/staging/greybus/vibrator-gb.c +++ b/drivers/staging/greybus/vibrator-gb.c @@ -197,6 +197,7 @@ static void gb_vibrator_connection_exit(struct gb_connection *connection) } static struct gb_protocol vibrator_protocol = { + .name = "vibrator", .id = GREYBUS_PROTOCOL_VIBRATOR, .major = 0, .minor = 1, -- cgit v0.10.2 From 23ad7bb96bb59e1f91a95a494cca303a8f7d300a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Dec 2014 13:12:10 -0800 Subject: greybus: protocol: fix oops when no protocol is assigned When removing a connection with no protocol assigned to it, the kernel oopses as we always thought protocols were always there. Fix that problem, oopses are bad. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index 4d6ffdd..562401d 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -165,10 +165,16 @@ struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor) void gb_protocol_put(struct gb_protocol *protocol) { - u8 major = protocol->major; - u8 minor = protocol->minor; + u8 major; + u8 minor; u8 protocol_count; + if (!protocol) + return; + + major = protocol->major; + minor = protocol->minor; + spin_lock_irq(&gb_protocols_lock); protocol = _gb_protocol_find(protocol->id, protocol->major, protocol->minor); -- cgit v0.10.2 From 88e70a6846dbc3cb94d3dd2bb488bc743a1f14f1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 23 Dec 2014 16:09:26 -0800 Subject: greybus: sysfs: put a \n at the end of all sysfs files Right now some sysfs attributes have \n and some do not, so fix that and put \n at the end of all of them to make it easier to parse things properly in userspace. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 96153c5..d020660 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -18,7 +18,7 @@ static ssize_t device_id_show(struct device *dev, struct device_attribute *attr, { struct gb_bundle *bundle = to_gb_bundle(dev); - return sprintf(buf, "%d", bundle->device_id); + return sprintf(buf, "%d\n", bundle->device_id); } static DEVICE_ATTR_RO(device_id); diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 82b03c3..c805022 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -91,7 +91,7 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr, { struct gb_connection *connection = to_gb_connection(dev); - return sprintf(buf, "%d", connection->state); + return sprintf(buf, "%d\n", connection->state); } static DEVICE_ATTR_RO(state); @@ -100,7 +100,7 @@ protocol_id_show(struct device *dev, struct device_attribute *attr, char *buf) { struct gb_connection *connection = to_gb_connection(dev); - return sprintf(buf, "%d", connection->protocol->id); + return sprintf(buf, "%d\n", connection->protocol->id); } static DEVICE_ATTR_RO(protocol_id); -- cgit v0.10.2 From e2ed07f1e6926d5b6da8bc29c1ec552ecdb7085b Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Wed, 14 Jan 2015 10:23:49 +0100 Subject: greybus: i2c-gb: fix bad message size in gb_i2c The data_in_size variable was set to 1 for the status byte. But now, the status byte has move to header. Then, the status byte is "allocated" twice and cause bad message size error. Signed-off-by: Alexandre Bailon Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c index 3b86258..c967ae3 100644 --- a/drivers/staging/greybus/i2c-gb.c +++ b/drivers/staging/greybus/i2c-gb.c @@ -199,7 +199,7 @@ gb_i2c_transfer_request(struct gb_connection *connection, struct gb_i2c_transfer_op *op; struct i2c_msg *msg; u32 data_out_size = 0; - u32 data_in_size = 1; /* Response begins with a status byte */ + u32 data_in_size = 0; size_t request_size; void *data; u16 op_count; -- cgit v0.10.2 From 025677def8717bd34dc1b554ade30b3b07626cab Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 14 Jan 2015 14:55:24 -0800 Subject: greybus: Makefile: provide install target Provide an install Makefile target for those that want to install the kernel modules. Signed-off-by: Greg Kroah-Hartman -- v3: resend to list, somehow this thread got taken private and v2 never made it there. v2: add -a option to depmod, thanks to Mitchell diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 8e6551b..bdb175c 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -46,3 +46,7 @@ clean: coccicheck: $(MAKE) -C $(KERNELDIR) M=$(PWD) coccicheck +install: module + mkdir -p /lib/modules/$(KERNELVER)/kernel/drivers/greybus/ + cp -f *.ko /lib/modules/$(KERNELVER)/kernel/drivers/greybus/ + depmod -a $(KERNELVER) -- cgit v0.10.2 From 71479f6c6ba19320ff1f5acb74e1a7fd28abd346 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 14 Jan 2015 17:07:59 -0800 Subject: greybus: rename gpbridge.ko to gb-phy.ko This module provides the Bridged PHY protocols, so name the thing properly. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index bdb175c..24000e9 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -9,7 +9,7 @@ greybus-y := core.o \ protocol.o \ operation.o -gpbridge-y := gpb.o \ +gb-phy-y := gpb.o \ sdio-gb.o \ uart-gb.o \ pwm-gb.o \ @@ -18,7 +18,7 @@ gpbridge-y := gpb.o \ usb-gb.o obj-m += greybus.o -obj-m += gpbridge.o +obj-m += gb-phy.o obj-m += vibrator-gb.o obj-m += battery-gb.o obj-m += es1-ap-usb.o -- cgit v0.10.2 From 419a8cf1816a9fa73071e6020847bbb81e4b9cca Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 14 Jan 2015 17:08:00 -0800 Subject: greybus: rename vibrator-gb.ko to gb-vibrator.ko Use the "gb" prefix for module names, not a suffix. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 24000e9..c4bab94 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -19,7 +19,7 @@ gb-phy-y := gpb.o \ obj-m += greybus.o obj-m += gb-phy.o -obj-m += vibrator-gb.o +obj-m += gb-vibrator.o obj-m += battery-gb.o obj-m += es1-ap-usb.o diff --git a/drivers/staging/greybus/gb-vibrator.c b/drivers/staging/greybus/gb-vibrator.c new file mode 100644 index 0000000..c85d950 --- /dev/null +++ b/drivers/staging/greybus/gb-vibrator.c @@ -0,0 +1,229 @@ +/* + * Greybus Vibrator protocol driver. + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include +#include +#include "greybus.h" + +struct gb_vibrator_device { + struct gb_connection *connection; + struct device *dev; + int minor; /* vibrator minor number */ + u8 version_major; + u8 version_minor; +}; + +/* Version of the Greybus vibrator protocol we support */ +#define GB_VIBRATOR_VERSION_MAJOR 0x00 +#define GB_VIBRATOR_VERSION_MINOR 0x01 + +/* Greybus Vibrator request types */ +#define GB_VIBRATOR_TYPE_INVALID 0x00 +#define GB_VIBRATOR_TYPE_PROTOCOL_VERSION 0x01 +#define GB_VIBRATOR_TYPE_ON 0x02 +#define GB_VIBRATOR_TYPE_OFF 0x03 +#define GB_VIBRATOR_TYPE_RESPONSE 0x80 /* OR'd with rest */ + +struct gb_vibrator_proto_version_response { + __u8 major; + __u8 minor; +}; + +struct gb_vibrator_on_request { + __le16 timeout_ms; +}; + +/* + * This request only uses the connection field, and if successful, + * fills in the major and minor protocol version of the target. + */ +static int get_version(struct gb_vibrator_device *vib) +{ + struct gb_connection *connection = vib->connection; + struct gb_vibrator_proto_version_response version_response; + int retval; + + retval = gb_operation_sync(connection, + GB_VIBRATOR_TYPE_PROTOCOL_VERSION, + NULL, 0, + &version_response, sizeof(version_response)); + if (retval) + return retval; + + if (version_response.major > GB_VIBRATOR_VERSION_MAJOR) { + dev_err(&connection->dev, + "unsupported major version (%hhu > %hhu)\n", + version_response.major, GB_VIBRATOR_VERSION_MAJOR); + return -ENOTSUPP; + } + + vib->version_major = version_response.major; + vib->version_minor = version_response.minor; + return 0; +} + +static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms) +{ + struct gb_vibrator_on_request request; + + request.timeout_ms = cpu_to_le16(timeout_ms); + return gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_ON, + &request, sizeof(request), NULL, 0); +} + +static int turn_off(struct gb_vibrator_device *vib) +{ + return gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_OFF, + NULL, 0, NULL, 0); +} + +static ssize_t timeout_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct gb_vibrator_device *vib = dev_get_drvdata(dev); + unsigned long val; + int retval; + + retval = kstrtoul(buf, 10, &val); + if (retval < 0) { + dev_err(dev, "could not parse timeout value %d\n", retval); + return retval; + } + + if (val < 0) + return -EINVAL; + if (val) + retval = turn_on(vib, (u16)val); + else + retval = turn_off(vib); + if (retval) + return retval; + + return count; +} +static DEVICE_ATTR_WO(timeout); + +static struct attribute *vibrator_attrs[] = { + &dev_attr_timeout.attr, + NULL, +}; +ATTRIBUTE_GROUPS(vibrator); + +static struct class vibrator_class = { + .name = "vibrator", + .owner = THIS_MODULE, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) + .dev_groups = vibrator_groups, +#endif +}; + +static DEFINE_IDR(minors); + +static int gb_vibrator_connection_init(struct gb_connection *connection) +{ + struct gb_vibrator_device *vib; + struct device *dev; + int retval; + + vib = kzalloc(sizeof(*vib), GFP_KERNEL); + if (!vib) + return -ENOMEM; + + vib->connection = connection; + connection->private = vib; + + retval = get_version(vib); + if (retval) + goto error; + + /* + * For now we create a device in sysfs for the vibrator, but odds are + * there is a "real" device somewhere in the kernel for this, but I + * can't find it at the moment... + */ + vib->minor = idr_alloc(&minors, vib, 0, 0, GFP_KERNEL); + if (vib->minor < 0) { + retval = vib->minor; + goto error; + } + dev = device_create(&vibrator_class, &connection->dev, MKDEV(0, 0), vib, + "vibrator%d", vib->minor); + if (IS_ERR(dev)) { + retval = -EINVAL; + goto error; + } + vib->dev = dev; + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(3,11,0) + /* + * Newer kernels handle this in a race-free manner, by the dev_groups + * field in the struct class up above. But for older kernels, we need + * to "open code this :( + */ + retval = sysfs_create_group(&dev->kobj, vibrator_groups[0]); + if (retval) { + device_unregister(dev); + goto error; + } +#endif + + return 0; + +error: + kfree(vib); + return retval; +} + +static void gb_vibrator_connection_exit(struct gb_connection *connection) +{ + struct gb_vibrator_device *vib = connection->private; + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(3,11,0) + sysfs_remove_group(&vib->dev->kobj, vibrator_groups[0]); +#endif + idr_remove(&minors, vib->minor); + device_unregister(vib->dev); + kfree(vib); +} + +static struct gb_protocol vibrator_protocol = { + .name = "vibrator", + .id = GREYBUS_PROTOCOL_VIBRATOR, + .major = 0, + .minor = 1, + .connection_init = gb_vibrator_connection_init, + .connection_exit = gb_vibrator_connection_exit, + .request_recv = NULL, /* no incoming requests */ +}; + +static __init int protocol_init(void) +{ + int retval; + + retval = class_register(&vibrator_class); + if (retval) + return retval; + + return gb_protocol_register(&vibrator_protocol); +} + +static __exit void protocol_exit(void) +{ + gb_protocol_deregister(&vibrator_protocol); + class_unregister(&vibrator_class); +} + +module_init(protocol_init); +module_exit(protocol_exit); + +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/vibrator-gb.c b/drivers/staging/greybus/vibrator-gb.c deleted file mode 100644 index c85d950..0000000 --- a/drivers/staging/greybus/vibrator-gb.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Greybus Vibrator protocol driver. - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#include -#include -#include -#include -#include -#include -#include "greybus.h" - -struct gb_vibrator_device { - struct gb_connection *connection; - struct device *dev; - int minor; /* vibrator minor number */ - u8 version_major; - u8 version_minor; -}; - -/* Version of the Greybus vibrator protocol we support */ -#define GB_VIBRATOR_VERSION_MAJOR 0x00 -#define GB_VIBRATOR_VERSION_MINOR 0x01 - -/* Greybus Vibrator request types */ -#define GB_VIBRATOR_TYPE_INVALID 0x00 -#define GB_VIBRATOR_TYPE_PROTOCOL_VERSION 0x01 -#define GB_VIBRATOR_TYPE_ON 0x02 -#define GB_VIBRATOR_TYPE_OFF 0x03 -#define GB_VIBRATOR_TYPE_RESPONSE 0x80 /* OR'd with rest */ - -struct gb_vibrator_proto_version_response { - __u8 major; - __u8 minor; -}; - -struct gb_vibrator_on_request { - __le16 timeout_ms; -}; - -/* - * This request only uses the connection field, and if successful, - * fills in the major and minor protocol version of the target. - */ -static int get_version(struct gb_vibrator_device *vib) -{ - struct gb_connection *connection = vib->connection; - struct gb_vibrator_proto_version_response version_response; - int retval; - - retval = gb_operation_sync(connection, - GB_VIBRATOR_TYPE_PROTOCOL_VERSION, - NULL, 0, - &version_response, sizeof(version_response)); - if (retval) - return retval; - - if (version_response.major > GB_VIBRATOR_VERSION_MAJOR) { - dev_err(&connection->dev, - "unsupported major version (%hhu > %hhu)\n", - version_response.major, GB_VIBRATOR_VERSION_MAJOR); - return -ENOTSUPP; - } - - vib->version_major = version_response.major; - vib->version_minor = version_response.minor; - return 0; -} - -static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms) -{ - struct gb_vibrator_on_request request; - - request.timeout_ms = cpu_to_le16(timeout_ms); - return gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_ON, - &request, sizeof(request), NULL, 0); -} - -static int turn_off(struct gb_vibrator_device *vib) -{ - return gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_OFF, - NULL, 0, NULL, 0); -} - -static ssize_t timeout_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct gb_vibrator_device *vib = dev_get_drvdata(dev); - unsigned long val; - int retval; - - retval = kstrtoul(buf, 10, &val); - if (retval < 0) { - dev_err(dev, "could not parse timeout value %d\n", retval); - return retval; - } - - if (val < 0) - return -EINVAL; - if (val) - retval = turn_on(vib, (u16)val); - else - retval = turn_off(vib); - if (retval) - return retval; - - return count; -} -static DEVICE_ATTR_WO(timeout); - -static struct attribute *vibrator_attrs[] = { - &dev_attr_timeout.attr, - NULL, -}; -ATTRIBUTE_GROUPS(vibrator); - -static struct class vibrator_class = { - .name = "vibrator", - .owner = THIS_MODULE, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) - .dev_groups = vibrator_groups, -#endif -}; - -static DEFINE_IDR(minors); - -static int gb_vibrator_connection_init(struct gb_connection *connection) -{ - struct gb_vibrator_device *vib; - struct device *dev; - int retval; - - vib = kzalloc(sizeof(*vib), GFP_KERNEL); - if (!vib) - return -ENOMEM; - - vib->connection = connection; - connection->private = vib; - - retval = get_version(vib); - if (retval) - goto error; - - /* - * For now we create a device in sysfs for the vibrator, but odds are - * there is a "real" device somewhere in the kernel for this, but I - * can't find it at the moment... - */ - vib->minor = idr_alloc(&minors, vib, 0, 0, GFP_KERNEL); - if (vib->minor < 0) { - retval = vib->minor; - goto error; - } - dev = device_create(&vibrator_class, &connection->dev, MKDEV(0, 0), vib, - "vibrator%d", vib->minor); - if (IS_ERR(dev)) { - retval = -EINVAL; - goto error; - } - vib->dev = dev; - -#if LINUX_VERSION_CODE <= KERNEL_VERSION(3,11,0) - /* - * Newer kernels handle this in a race-free manner, by the dev_groups - * field in the struct class up above. But for older kernels, we need - * to "open code this :( - */ - retval = sysfs_create_group(&dev->kobj, vibrator_groups[0]); - if (retval) { - device_unregister(dev); - goto error; - } -#endif - - return 0; - -error: - kfree(vib); - return retval; -} - -static void gb_vibrator_connection_exit(struct gb_connection *connection) -{ - struct gb_vibrator_device *vib = connection->private; - -#if LINUX_VERSION_CODE <= KERNEL_VERSION(3,11,0) - sysfs_remove_group(&vib->dev->kobj, vibrator_groups[0]); -#endif - idr_remove(&minors, vib->minor); - device_unregister(vib->dev); - kfree(vib); -} - -static struct gb_protocol vibrator_protocol = { - .name = "vibrator", - .id = GREYBUS_PROTOCOL_VIBRATOR, - .major = 0, - .minor = 1, - .connection_init = gb_vibrator_connection_init, - .connection_exit = gb_vibrator_connection_exit, - .request_recv = NULL, /* no incoming requests */ -}; - -static __init int protocol_init(void) -{ - int retval; - - retval = class_register(&vibrator_class); - if (retval) - return retval; - - return gb_protocol_register(&vibrator_protocol); -} - -static __exit void protocol_exit(void) -{ - gb_protocol_deregister(&vibrator_protocol); - class_unregister(&vibrator_class); -} - -module_init(protocol_init); -module_exit(protocol_exit); - -MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 347fedb70dfd29a159832a1d6a8b46bfb25b89dd Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 14 Jan 2015 17:08:01 -0800 Subject: greybus: rename battery-gb.c to gb-battery.c Use the "gb" prefix for module names, not a suffix. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index c4bab94..1734480 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -20,7 +20,7 @@ gb-phy-y := gpb.o \ obj-m += greybus.o obj-m += gb-phy.o obj-m += gb-vibrator.o -obj-m += battery-gb.o +obj-m += gb-battery.o obj-m += es1-ap-usb.o KERNELVER ?= $(shell uname -r) diff --git a/drivers/staging/greybus/battery-gb.c b/drivers/staging/greybus/battery-gb.c deleted file mode 100644 index 2130d73..0000000 --- a/drivers/staging/greybus/battery-gb.c +++ /dev/null @@ -1,373 +0,0 @@ -/* - * Battery driver for a Greybus module. - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#include -#include -#include -#include -#include "greybus.h" - -struct gb_battery { - struct power_supply bat; - // FIXME - // we will want to keep the battery stats in here as we will be getting - // updates from the SVC "on the fly" so we don't have to always go ask - // the battery for some information. Hopefully... - struct gb_connection *connection; - u8 version_major; - u8 version_minor; - -}; -#define to_gb_battery(x) container_of(x, struct gb_battery, bat) - -/* Version of the Greybus battery protocol we support */ -#define GB_BATTERY_VERSION_MAJOR 0x00 -#define GB_BATTERY_VERSION_MINOR 0x01 - -/* Greybus battery request types */ -#define GB_BATTERY_TYPE_INVALID 0x00 -#define GB_BATTERY_TYPE_PROTOCOL_VERSION 0x01 -#define GB_BATTERY_TYPE_TECHNOLOGY 0x02 -#define GB_BATTERY_TYPE_STATUS 0x03 -#define GB_BATTERY_TYPE_MAX_VOLTAGE 0x04 -#define GB_BATTERY_TYPE_PERCENT_CAPACITY 0x05 -#define GB_BATTERY_TYPE_TEMPERATURE 0x06 -#define GB_BATTERY_TYPE_VOLTAGE 0x07 -#define GB_BATTERY_TYPE_CURRENT 0x08 -#define GB_BATTERY_TYPE_CAPACITY 0x09 // TODO - POWER_SUPPLY_PROP_CURRENT_MAX -#define GB_BATTERY_TYPE_SHUTDOWN_TEMP 0x0a // TODO - POWER_SUPPLY_PROP_TEMP_ALERT_MAX - -struct gb_battery_proto_version_response { - __u8 major; - __u8 minor; -}; - -/* Should match up with battery types in linux/power_supply.h */ -#define GB_BATTERY_TECH_UNKNOWN 0x0000 -#define GB_BATTERY_TECH_NiMH 0x0001 -#define GB_BATTERY_TECH_LION 0x0002 -#define GB_BATTERY_TECH_LIPO 0x0003 -#define GB_BATTERY_TECH_LiFe 0x0004 -#define GB_BATTERY_TECH_NiCd 0x0005 -#define GB_BATTERY_TECH_LiMn 0x0006 - -struct gb_battery_technology_response { - __le32 technology; -}; - -/* Should match up with battery status in linux/power_supply.h */ -#define GB_BATTERY_STATUS_UNKNOWN 0x0000 -#define GB_BATTERY_STATUS_CHARGING 0x0001 -#define GB_BATTERY_STATUS_DISCHARGING 0x0002 -#define GB_BATTERY_STATUS_NOT_CHARGING 0x0003 -#define GB_BATTERY_STATUS_FULL 0x0004 - -struct gb_battery_status_response { - __le16 battery_status; -}; - -struct gb_battery_max_voltage_response { - __le32 max_voltage; -}; - -struct gb_battery_capacity_response { - __le32 capacity; -}; - -struct gb_battery_temperature_response { - __le32 temperature; -}; - -struct gb_battery_voltage_response { - __le32 voltage; -}; - -/* - * This request only uses the connection field, and if successful, - * fills in the major and minor protocol version of the target. - */ -static int get_version(struct gb_battery *gb) -{ - struct gb_battery_proto_version_response version_response; - int retval; - - retval = gb_operation_sync(gb->connection, - GB_BATTERY_TYPE_PROTOCOL_VERSION, - NULL, 0, - &version_response, sizeof(version_response)); - if (retval) - return retval; - - if (version_response.major > GB_BATTERY_VERSION_MAJOR) { - pr_err("unsupported major version (%hhu > %hhu)\n", - version_response.major, GB_BATTERY_VERSION_MAJOR); - return -ENOTSUPP; - } - - gb->version_major = version_response.major; - gb->version_minor = version_response.minor; - return 0; -} - -static int get_tech(struct gb_battery *gb) -{ - struct gb_battery_technology_response tech_response; - u32 technology; - int retval; - - retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_TECHNOLOGY, - NULL, 0, - &tech_response, sizeof(tech_response)); - if (retval) - return retval; - - /* - * Map greybus values to power_supply values. Hopefully these are - * "identical" which should allow gcc to optimize the code away to - * nothing. - */ - technology = le32_to_cpu(tech_response.technology); - switch (technology) { - case GB_BATTERY_TECH_NiMH: - technology = POWER_SUPPLY_TECHNOLOGY_NiMH; - break; - case GB_BATTERY_TECH_LION: - technology = POWER_SUPPLY_TECHNOLOGY_LION; - break; - case GB_BATTERY_TECH_LIPO: - technology = POWER_SUPPLY_TECHNOLOGY_LIPO; - break; - case GB_BATTERY_TECH_LiFe: - technology = POWER_SUPPLY_TECHNOLOGY_LiFe; - break; - case GB_BATTERY_TECH_NiCd: - technology = POWER_SUPPLY_TECHNOLOGY_NiCd; - break; - case GB_BATTERY_TECH_LiMn: - technology = POWER_SUPPLY_TECHNOLOGY_LiMn; - break; - case GB_BATTERY_TECH_UNKNOWN: - default: - technology = POWER_SUPPLY_TECHNOLOGY_UNKNOWN; - break; - } - return technology; -} - -static int get_status(struct gb_battery *gb) -{ - struct gb_battery_status_response status_response; - u16 battery_status; - int retval; - - retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_STATUS, - NULL, 0, - &status_response, sizeof(status_response)); - if (retval) - return retval; - - /* - * Map greybus values to power_supply values. Hopefully these are - * "identical" which should allow gcc to optimize the code away to - * nothing. - */ - battery_status = le16_to_cpu(status_response.battery_status); - switch (battery_status) { - case GB_BATTERY_STATUS_CHARGING: - battery_status = POWER_SUPPLY_STATUS_CHARGING; - break; - case GB_BATTERY_STATUS_DISCHARGING: - battery_status = POWER_SUPPLY_STATUS_DISCHARGING; - break; - case GB_BATTERY_STATUS_NOT_CHARGING: - battery_status = POWER_SUPPLY_STATUS_NOT_CHARGING; - break; - case GB_BATTERY_STATUS_FULL: - battery_status = POWER_SUPPLY_STATUS_FULL; - break; - case GB_BATTERY_STATUS_UNKNOWN: - default: - battery_status = POWER_SUPPLY_STATUS_UNKNOWN; - break; - } - return battery_status; -} - -static int get_max_voltage(struct gb_battery *gb) -{ - struct gb_battery_max_voltage_response volt_response; - u32 max_voltage; - int retval; - - retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_MAX_VOLTAGE, - NULL, 0, - &volt_response, sizeof(volt_response)); - if (retval) - return retval; - - max_voltage = le32_to_cpu(volt_response.max_voltage); - return max_voltage; -} - -static int get_percent_capacity(struct gb_battery *gb) -{ - struct gb_battery_capacity_response capacity_response; - u32 capacity; - int retval; - - retval = gb_operation_sync(gb->connection, - GB_BATTERY_TYPE_PERCENT_CAPACITY, - NULL, 0, &capacity_response, - sizeof(capacity_response)); - if (retval) - return retval; - - capacity = le32_to_cpu(capacity_response.capacity); - return capacity; -} - -static int get_temp(struct gb_battery *gb) -{ - struct gb_battery_temperature_response temp_response; - u32 temperature; - int retval; - - retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_TEMPERATURE, - NULL, 0, - &temp_response, sizeof(temp_response)); - if (retval) - return retval; - - temperature = le32_to_cpu(temp_response.temperature); - return temperature; -} - -static int get_voltage(struct gb_battery *gb) -{ - struct gb_battery_voltage_response voltage_response; - u32 voltage; - int retval; - - retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_VOLTAGE, - NULL, 0, - &voltage_response, sizeof(voltage_response)); - if (retval) - return retval; - - voltage = le32_to_cpu(voltage_response.voltage); - return voltage; -} - -static int get_property(struct power_supply *b, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct gb_battery *gb = to_gb_battery(b); - - switch (psp) { - case POWER_SUPPLY_PROP_TECHNOLOGY: - val->intval = get_tech(gb); - break; - - case POWER_SUPPLY_PROP_STATUS: - val->intval = get_status(gb); - break; - - case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: - val->intval = get_max_voltage(gb); - break; - - case POWER_SUPPLY_PROP_CAPACITY: - val->intval = get_percent_capacity(gb); - break; - - case POWER_SUPPLY_PROP_TEMP: - val->intval = get_temp(gb); - break; - - case POWER_SUPPLY_PROP_VOLTAGE_NOW: - val->intval = get_voltage(gb); - break; - - default: - return -EINVAL; - } - - return 0; -} - -// FIXME - verify this list, odds are some can be removed and others added. -static enum power_supply_property battery_props[] = { - POWER_SUPPLY_PROP_TECHNOLOGY, - POWER_SUPPLY_PROP_STATUS, - POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, - POWER_SUPPLY_PROP_CAPACITY, - POWER_SUPPLY_PROP_TEMP, - POWER_SUPPLY_PROP_VOLTAGE_NOW, -}; - -static int gb_battery_connection_init(struct gb_connection *connection) -{ - struct gb_battery *gb; - struct power_supply *b; - int retval; - - gb = kzalloc(sizeof(*gb), GFP_KERNEL); - if (!gb) - return -ENOMEM; - - gb->connection = connection; - connection->private = gb; - - /* Check the version */ - retval = get_version(gb); - if (retval) { - kfree(gb); - return retval; - } - - b = &gb->bat; - // FIXME - get a better (i.e. unique) name - // FIXME - anything else needs to be set? - b->name = "gb_battery"; - b->type = POWER_SUPPLY_TYPE_BATTERY, - b->properties = battery_props, - b->num_properties = ARRAY_SIZE(battery_props), - b->get_property = get_property, - - retval = power_supply_register(&connection->bundle->intf->dev, b); - if (retval) { - kfree(gb); - return retval; - } - - return 0; -} - -static void gb_battery_connection_exit(struct gb_connection *connection) -{ - struct gb_battery *gb = connection->private; - - power_supply_unregister(&gb->bat); - kfree(gb); -} - -static struct gb_protocol battery_protocol = { - .name = "battery", - .id = GREYBUS_PROTOCOL_BATTERY, - .major = 0, - .minor = 1, - .connection_init = gb_battery_connection_init, - .connection_exit = gb_battery_connection_exit, - .request_recv = NULL, /* no incoming requests */ -}; - -gb_protocol_driver(&battery_protocol); - -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/gb-battery.c b/drivers/staging/greybus/gb-battery.c new file mode 100644 index 0000000..2130d73 --- /dev/null +++ b/drivers/staging/greybus/gb-battery.c @@ -0,0 +1,373 @@ +/* + * Battery driver for a Greybus module. + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include "greybus.h" + +struct gb_battery { + struct power_supply bat; + // FIXME + // we will want to keep the battery stats in here as we will be getting + // updates from the SVC "on the fly" so we don't have to always go ask + // the battery for some information. Hopefully... + struct gb_connection *connection; + u8 version_major; + u8 version_minor; + +}; +#define to_gb_battery(x) container_of(x, struct gb_battery, bat) + +/* Version of the Greybus battery protocol we support */ +#define GB_BATTERY_VERSION_MAJOR 0x00 +#define GB_BATTERY_VERSION_MINOR 0x01 + +/* Greybus battery request types */ +#define GB_BATTERY_TYPE_INVALID 0x00 +#define GB_BATTERY_TYPE_PROTOCOL_VERSION 0x01 +#define GB_BATTERY_TYPE_TECHNOLOGY 0x02 +#define GB_BATTERY_TYPE_STATUS 0x03 +#define GB_BATTERY_TYPE_MAX_VOLTAGE 0x04 +#define GB_BATTERY_TYPE_PERCENT_CAPACITY 0x05 +#define GB_BATTERY_TYPE_TEMPERATURE 0x06 +#define GB_BATTERY_TYPE_VOLTAGE 0x07 +#define GB_BATTERY_TYPE_CURRENT 0x08 +#define GB_BATTERY_TYPE_CAPACITY 0x09 // TODO - POWER_SUPPLY_PROP_CURRENT_MAX +#define GB_BATTERY_TYPE_SHUTDOWN_TEMP 0x0a // TODO - POWER_SUPPLY_PROP_TEMP_ALERT_MAX + +struct gb_battery_proto_version_response { + __u8 major; + __u8 minor; +}; + +/* Should match up with battery types in linux/power_supply.h */ +#define GB_BATTERY_TECH_UNKNOWN 0x0000 +#define GB_BATTERY_TECH_NiMH 0x0001 +#define GB_BATTERY_TECH_LION 0x0002 +#define GB_BATTERY_TECH_LIPO 0x0003 +#define GB_BATTERY_TECH_LiFe 0x0004 +#define GB_BATTERY_TECH_NiCd 0x0005 +#define GB_BATTERY_TECH_LiMn 0x0006 + +struct gb_battery_technology_response { + __le32 technology; +}; + +/* Should match up with battery status in linux/power_supply.h */ +#define GB_BATTERY_STATUS_UNKNOWN 0x0000 +#define GB_BATTERY_STATUS_CHARGING 0x0001 +#define GB_BATTERY_STATUS_DISCHARGING 0x0002 +#define GB_BATTERY_STATUS_NOT_CHARGING 0x0003 +#define GB_BATTERY_STATUS_FULL 0x0004 + +struct gb_battery_status_response { + __le16 battery_status; +}; + +struct gb_battery_max_voltage_response { + __le32 max_voltage; +}; + +struct gb_battery_capacity_response { + __le32 capacity; +}; + +struct gb_battery_temperature_response { + __le32 temperature; +}; + +struct gb_battery_voltage_response { + __le32 voltage; +}; + +/* + * This request only uses the connection field, and if successful, + * fills in the major and minor protocol version of the target. + */ +static int get_version(struct gb_battery *gb) +{ + struct gb_battery_proto_version_response version_response; + int retval; + + retval = gb_operation_sync(gb->connection, + GB_BATTERY_TYPE_PROTOCOL_VERSION, + NULL, 0, + &version_response, sizeof(version_response)); + if (retval) + return retval; + + if (version_response.major > GB_BATTERY_VERSION_MAJOR) { + pr_err("unsupported major version (%hhu > %hhu)\n", + version_response.major, GB_BATTERY_VERSION_MAJOR); + return -ENOTSUPP; + } + + gb->version_major = version_response.major; + gb->version_minor = version_response.minor; + return 0; +} + +static int get_tech(struct gb_battery *gb) +{ + struct gb_battery_technology_response tech_response; + u32 technology; + int retval; + + retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_TECHNOLOGY, + NULL, 0, + &tech_response, sizeof(tech_response)); + if (retval) + return retval; + + /* + * Map greybus values to power_supply values. Hopefully these are + * "identical" which should allow gcc to optimize the code away to + * nothing. + */ + technology = le32_to_cpu(tech_response.technology); + switch (technology) { + case GB_BATTERY_TECH_NiMH: + technology = POWER_SUPPLY_TECHNOLOGY_NiMH; + break; + case GB_BATTERY_TECH_LION: + technology = POWER_SUPPLY_TECHNOLOGY_LION; + break; + case GB_BATTERY_TECH_LIPO: + technology = POWER_SUPPLY_TECHNOLOGY_LIPO; + break; + case GB_BATTERY_TECH_LiFe: + technology = POWER_SUPPLY_TECHNOLOGY_LiFe; + break; + case GB_BATTERY_TECH_NiCd: + technology = POWER_SUPPLY_TECHNOLOGY_NiCd; + break; + case GB_BATTERY_TECH_LiMn: + technology = POWER_SUPPLY_TECHNOLOGY_LiMn; + break; + case GB_BATTERY_TECH_UNKNOWN: + default: + technology = POWER_SUPPLY_TECHNOLOGY_UNKNOWN; + break; + } + return technology; +} + +static int get_status(struct gb_battery *gb) +{ + struct gb_battery_status_response status_response; + u16 battery_status; + int retval; + + retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_STATUS, + NULL, 0, + &status_response, sizeof(status_response)); + if (retval) + return retval; + + /* + * Map greybus values to power_supply values. Hopefully these are + * "identical" which should allow gcc to optimize the code away to + * nothing. + */ + battery_status = le16_to_cpu(status_response.battery_status); + switch (battery_status) { + case GB_BATTERY_STATUS_CHARGING: + battery_status = POWER_SUPPLY_STATUS_CHARGING; + break; + case GB_BATTERY_STATUS_DISCHARGING: + battery_status = POWER_SUPPLY_STATUS_DISCHARGING; + break; + case GB_BATTERY_STATUS_NOT_CHARGING: + battery_status = POWER_SUPPLY_STATUS_NOT_CHARGING; + break; + case GB_BATTERY_STATUS_FULL: + battery_status = POWER_SUPPLY_STATUS_FULL; + break; + case GB_BATTERY_STATUS_UNKNOWN: + default: + battery_status = POWER_SUPPLY_STATUS_UNKNOWN; + break; + } + return battery_status; +} + +static int get_max_voltage(struct gb_battery *gb) +{ + struct gb_battery_max_voltage_response volt_response; + u32 max_voltage; + int retval; + + retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_MAX_VOLTAGE, + NULL, 0, + &volt_response, sizeof(volt_response)); + if (retval) + return retval; + + max_voltage = le32_to_cpu(volt_response.max_voltage); + return max_voltage; +} + +static int get_percent_capacity(struct gb_battery *gb) +{ + struct gb_battery_capacity_response capacity_response; + u32 capacity; + int retval; + + retval = gb_operation_sync(gb->connection, + GB_BATTERY_TYPE_PERCENT_CAPACITY, + NULL, 0, &capacity_response, + sizeof(capacity_response)); + if (retval) + return retval; + + capacity = le32_to_cpu(capacity_response.capacity); + return capacity; +} + +static int get_temp(struct gb_battery *gb) +{ + struct gb_battery_temperature_response temp_response; + u32 temperature; + int retval; + + retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_TEMPERATURE, + NULL, 0, + &temp_response, sizeof(temp_response)); + if (retval) + return retval; + + temperature = le32_to_cpu(temp_response.temperature); + return temperature; +} + +static int get_voltage(struct gb_battery *gb) +{ + struct gb_battery_voltage_response voltage_response; + u32 voltage; + int retval; + + retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_VOLTAGE, + NULL, 0, + &voltage_response, sizeof(voltage_response)); + if (retval) + return retval; + + voltage = le32_to_cpu(voltage_response.voltage); + return voltage; +} + +static int get_property(struct power_supply *b, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct gb_battery *gb = to_gb_battery(b); + + switch (psp) { + case POWER_SUPPLY_PROP_TECHNOLOGY: + val->intval = get_tech(gb); + break; + + case POWER_SUPPLY_PROP_STATUS: + val->intval = get_status(gb); + break; + + case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: + val->intval = get_max_voltage(gb); + break; + + case POWER_SUPPLY_PROP_CAPACITY: + val->intval = get_percent_capacity(gb); + break; + + case POWER_SUPPLY_PROP_TEMP: + val->intval = get_temp(gb); + break; + + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + val->intval = get_voltage(gb); + break; + + default: + return -EINVAL; + } + + return 0; +} + +// FIXME - verify this list, odds are some can be removed and others added. +static enum power_supply_property battery_props[] = { + POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, + POWER_SUPPLY_PROP_CAPACITY, + POWER_SUPPLY_PROP_TEMP, + POWER_SUPPLY_PROP_VOLTAGE_NOW, +}; + +static int gb_battery_connection_init(struct gb_connection *connection) +{ + struct gb_battery *gb; + struct power_supply *b; + int retval; + + gb = kzalloc(sizeof(*gb), GFP_KERNEL); + if (!gb) + return -ENOMEM; + + gb->connection = connection; + connection->private = gb; + + /* Check the version */ + retval = get_version(gb); + if (retval) { + kfree(gb); + return retval; + } + + b = &gb->bat; + // FIXME - get a better (i.e. unique) name + // FIXME - anything else needs to be set? + b->name = "gb_battery"; + b->type = POWER_SUPPLY_TYPE_BATTERY, + b->properties = battery_props, + b->num_properties = ARRAY_SIZE(battery_props), + b->get_property = get_property, + + retval = power_supply_register(&connection->bundle->intf->dev, b); + if (retval) { + kfree(gb); + return retval; + } + + return 0; +} + +static void gb_battery_connection_exit(struct gb_connection *connection) +{ + struct gb_battery *gb = connection->private; + + power_supply_unregister(&gb->bat); + kfree(gb); +} + +static struct gb_protocol battery_protocol = { + .name = "battery", + .id = GREYBUS_PROTOCOL_BATTERY, + .major = 0, + .minor = 1, + .connection_init = gb_battery_connection_init, + .connection_exit = gb_battery_connection_exit, + .request_recv = NULL, /* no incoming requests */ +}; + +gb_protocol_driver(&battery_protocol); + +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 60a7ad7cae9d095d2de55aac7c05f258f89b0ad5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 14 Jan 2015 17:08:02 -0800 Subject: greybus: rename es1-ap-usb.ko to gb-es1.ko Use the "gb-" prefix for the ES1 Host controller driver. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 1734480..5a7c58d 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -21,7 +21,7 @@ obj-m += greybus.o obj-m += gb-phy.o obj-m += gb-vibrator.o obj-m += gb-battery.o -obj-m += es1-ap-usb.o +obj-m += gb-es1.o KERNELVER ?= $(shell uname -r) KERNELDIR ?= /lib/modules/$(KERNELVER)/build diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c deleted file mode 100644 index 27416e4..0000000 --- a/drivers/staging/greybus/es1-ap-usb.c +++ /dev/null @@ -1,617 +0,0 @@ -/* - * Greybus "AP" USB driver - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - * - * Released under the GPLv2 only. - */ -#include -#include -#include -#include -#include -#include - -#include "greybus.h" -#include "svc_msg.h" -#include "kernel_ver.h" - -/* - * Macros for making pointers explicitly opaque, such that the result - * isn't valid but also can't be mistaken for an ERR_PTR() value. - */ -#define conceal_urb(urb) ((void *)((uintptr_t)(urb) ^ 0xbad)) -#define reveal_urb(cookie) ((void *)((uintptr_t)(cookie) ^ 0xbad)) - -/* Memory sizes for the buffers sent to/from the ES1 controller */ -#define ES1_SVC_MSG_SIZE (sizeof(struct svc_msg) + SZ_64K) -#define ES1_GBUF_MSG_SIZE_MAX PAGE_SIZE - -static const struct usb_device_id id_table[] = { - /* Made up numbers for the SVC USB Bridge in ES1 */ - { USB_DEVICE(0xffff, 0x0001) }, - { }, -}; -MODULE_DEVICE_TABLE(usb, id_table); - -/* - * Number of CPort IN urbs in flight at any point in time. - * Adjust if we are having stalls in the USB buffer due to not enough urbs in - * flight. - */ -#define NUM_CPORT_IN_URB 4 - -/* Number of CPort OUT urbs in flight at any point in time. - * Adjust if we get messages saying we are out of urbs in the system log. - */ -#define NUM_CPORT_OUT_URB 8 - -/** - * es1_ap_dev - ES1 USB Bridge to AP structure - * @usb_dev: pointer to the USB device we are. - * @usb_intf: pointer to the USB interface we are bound to. - * @hd: pointer to our greybus_host_device structure - * @control_endpoint: endpoint to send data to SVC - * @svc_endpoint: endpoint for SVC data in - * @cport_in_endpoint: bulk in endpoint for CPort data - * @cport-out_endpoint: bulk out endpoint for CPort data - * @svc_buffer: buffer for SVC messages coming in on @svc_endpoint - * @svc_urb: urb for SVC messages coming in on @svc_endpoint - * @cport_in_urb: array of urbs for the CPort in messages - * @cport_in_buffer: array of buffers for the @cport_in_urb urbs - * @cport_out_urb: array of urbs for the CPort out messages - * @cport_out_urb_busy: array of flags to see if the @cport_out_urb is busy or - * not. - * @cport_out_urb_lock: locks the @cport_out_urb_busy "list" - */ -struct es1_ap_dev { - struct usb_device *usb_dev; - struct usb_interface *usb_intf; - struct greybus_host_device *hd; - - __u8 control_endpoint; - __u8 svc_endpoint; - __u8 cport_in_endpoint; - __u8 cport_out_endpoint; - - u8 *svc_buffer; - struct urb *svc_urb; - - struct urb *cport_in_urb[NUM_CPORT_IN_URB]; - u8 *cport_in_buffer[NUM_CPORT_IN_URB]; - struct urb *cport_out_urb[NUM_CPORT_OUT_URB]; - bool cport_out_urb_busy[NUM_CPORT_OUT_URB]; - spinlock_t cport_out_urb_lock; -}; - -static inline struct es1_ap_dev *hd_to_es1(struct greybus_host_device *hd) -{ - return (struct es1_ap_dev *)&hd->hd_priv; -} - -static void cport_out_callback(struct urb *urb); - -/* - * Buffer constraints for the host driver. - * - * A "buffer" is used to hold data to be transferred for Greybus by - * the host driver. A buffer is represented by a "buffer pointer", - * which defines a region of memory used by the host driver for - * transferring the data. When Greybus allocates a buffer, it must - * do so subject to the constraints associated with the host driver. - * These constraints are specified by two parameters: the - * headroom; and the maximum buffer size. - * - * +------------------+ - * | Host driver | \ - * | reserved area | }- headroom - * | . . . | / - * buffer pointer ---> +------------------+ - * | Buffer space for | \ - * | transferred data | }- buffer size - * | . . . | / (limited to size_max) - * +------------------+ - * - * headroom: Every buffer must have at least this much space - * *before* the buffer pointer, reserved for use by the - * host driver. I.e., ((char *)buffer - headroom) must - * point to valid memory, usable only by the host driver. - * size_max: The maximum size of a buffer (not including the - * headroom) must not exceed this. - */ -static void hd_buffer_constraints(struct greybus_host_device *hd) -{ - /* - * Only one byte is required, but this produces a result - * that's better aligned for the user. - */ - hd->buffer_headroom = sizeof(u32); /* For cport id */ - hd->buffer_size_max = ES1_GBUF_MSG_SIZE_MAX; - BUILD_BUG_ON(hd->buffer_headroom > GB_BUFFER_HEADROOM_MAX); -} - -#define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ -static int submit_svc(struct svc_msg *svc_msg, struct greybus_host_device *hd) -{ - struct es1_ap_dev *es1 = hd_to_es1(hd); - int retval; - - /* SVC messages go down our control pipe */ - retval = usb_control_msg(es1->usb_dev, - usb_sndctrlpipe(es1->usb_dev, - es1->control_endpoint), - 0x01, /* vendor request AP message */ - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - 0x00, 0x00, - (char *)svc_msg, - sizeof(*svc_msg), - ES1_TIMEOUT); - if (retval != sizeof(*svc_msg)) - return retval; - - return 0; -} - -static struct urb *next_free_urb(struct es1_ap_dev *es1, gfp_t gfp_mask) -{ - struct urb *urb = NULL; - unsigned long flags; - int i; - - spin_lock_irqsave(&es1->cport_out_urb_lock, flags); - - /* Look in our pool of allocated urbs first, as that's the "fastest" */ - for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - if (es1->cport_out_urb_busy[i] == false) { - es1->cport_out_urb_busy[i] = true; - urb = es1->cport_out_urb[i]; - break; - } - } - spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); - if (urb) - return urb; - - /* - * Crap, pool is empty, complain to the syslog and go allocate one - * dynamically as we have to succeed. - */ - dev_err(&es1->usb_dev->dev, - "No free CPort OUT urbs, having to dynamically allocate one!\n"); - urb = usb_alloc_urb(0, gfp_mask); - if (!urb) - return NULL; - - return urb; -} - -/* - * Returns an opaque cookie value if successful, or a pointer coded - * error otherwise. If the caller wishes to cancel the in-flight - * buffer, it must supply the returned cookie to the cancel routine. - */ -static void *buffer_send(struct greybus_host_device *hd, u16 cport_id, - void *buffer, size_t buffer_size, gfp_t gfp_mask) -{ - struct es1_ap_dev *es1 = hd_to_es1(hd); - struct usb_device *udev = es1->usb_dev; - u8 *transfer_buffer = buffer; - int transfer_buffer_size; - int retval; - struct urb *urb; - - if (!buffer) { - pr_err("null buffer supplied to send\n"); - return ERR_PTR(-EINVAL); - } - if (buffer_size > (size_t)INT_MAX) { - pr_err("bad buffer size (%zu) supplied to send\n", buffer_size); - return ERR_PTR(-EINVAL); - } - transfer_buffer--; - transfer_buffer_size = buffer_size + 1; - - /* - * The data actually transferred will include an indication - * of where the data should be sent. Do one last check of - * the target CPort id before filling it in. - */ - if (cport_id == CPORT_ID_BAD) { - pr_err("request to send inbound data buffer\n"); - return ERR_PTR(-EINVAL); - } - if (cport_id > (u16)U8_MAX) { - pr_err("cport_id (%hd) is out of range for ES1\n", cport_id); - return ERR_PTR(-EINVAL); - } - /* OK, the destination is fine; record it in the transfer buffer */ - *transfer_buffer = cport_id; - - /* Find a free urb */ - urb = next_free_urb(es1, gfp_mask); - if (!urb) - return ERR_PTR(-ENOMEM); - - usb_fill_bulk_urb(urb, udev, - usb_sndbulkpipe(udev, es1->cport_out_endpoint), - transfer_buffer, transfer_buffer_size, - cport_out_callback, hd); - retval = usb_submit_urb(urb, gfp_mask); - if (retval) { - pr_err("error %d submitting URB\n", retval); - return ERR_PTR(retval); - } - - return conceal_urb(urb); -} - -/* - * The cookie value supplied is the value that buffer_send() - * returned to its caller. It identifies the buffer that should be - * canceled. This function must also handle (which is to say, - * ignore) a null cookie value. - */ -static void buffer_cancel(void *cookie) -{ - - /* - * We really should be defensive and track all outstanding - * (sent) buffers rather than trusting the cookie provided - * is valid. For the time being, this will do. - */ - if (cookie) - usb_kill_urb(reveal_urb(cookie)); -} - -static struct greybus_host_driver es1_driver = { - .hd_priv_size = sizeof(struct es1_ap_dev), - .buffer_send = buffer_send, - .buffer_cancel = buffer_cancel, - .submit_svc = submit_svc, -}; - -/* Common function to report consistent warnings based on URB status */ -static int check_urb_status(struct urb *urb) -{ - struct device *dev = &urb->dev->dev; - int status = urb->status; - - switch (status) { - case 0: - return 0; - - case -EOVERFLOW: - dev_err(dev, "%s: overflow actual length is %d\n", - __func__, urb->actual_length); - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - case -EILSEQ: - case -EPROTO: - /* device is gone, stop sending */ - return status; - } - dev_err(dev, "%s: unknown status %d\n", __func__, status); - - return -EAGAIN; -} - -static void ap_disconnect(struct usb_interface *interface) -{ - struct es1_ap_dev *es1; - struct usb_device *udev; - int i; - - es1 = usb_get_intfdata(interface); - if (!es1) - return; - - /* Tear down everything! */ - for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - struct urb *urb = es1->cport_out_urb[i]; - - if (!urb) - break; - usb_kill_urb(urb); - usb_free_urb(urb); - es1->cport_out_urb[i] = NULL; - es1->cport_out_urb_busy[i] = false; /* just to be anal */ - } - - for (i = 0; i < NUM_CPORT_IN_URB; ++i) { - struct urb *urb = es1->cport_in_urb[i]; - - if (!urb) - break; - usb_kill_urb(urb); - usb_free_urb(urb); - kfree(es1->cport_in_buffer[i]); - es1->cport_in_buffer[i] = NULL; - } - - usb_kill_urb(es1->svc_urb); - usb_free_urb(es1->svc_urb); - es1->svc_urb = NULL; - kfree(es1->svc_buffer); - es1->svc_buffer = NULL; - - usb_set_intfdata(interface, NULL); - udev = es1->usb_dev; - greybus_remove_hd(es1->hd); - - usb_put_dev(udev); -} - -/* Callback for when we get a SVC message */ -static void svc_in_callback(struct urb *urb) -{ - struct greybus_host_device *hd = urb->context; - struct device *dev = &urb->dev->dev; - int status = check_urb_status(urb); - int retval; - - if (status) { - if ((status == -EAGAIN) || (status == -EPROTO)) - goto exit; - dev_err(dev, "urb svc in error %d (dropped)\n", status); - return; - } - - /* We have a message, create a new message structure, add it to the - * list, and wake up our thread that will process the messages. - */ - greybus_svc_in(hd, urb->transfer_buffer, urb->actual_length); - -exit: - /* resubmit the urb to get more messages */ - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - dev_err(dev, "Can not submit urb for AP data: %d\n", retval); -} - -static void cport_in_callback(struct urb *urb) -{ - struct greybus_host_device *hd = urb->context; - struct device *dev = &urb->dev->dev; - int status = check_urb_status(urb); - int retval; - u16 cport_id; - u8 *data; - - if (status) { - if ((status == -EAGAIN) || (status == -EPROTO)) - goto exit; - dev_err(dev, "urb cport in error %d (dropped)\n", status); - return; - } - - /* The size has to be at least one, for the cport id */ - if (!urb->actual_length) { - dev_err(dev, "%s: no cport id in input buffer?\n", __func__); - goto exit; - } - - /* - * Our CPort number is the first byte of the data stream, - * the rest of the stream is "real" data - */ - data = urb->transfer_buffer; - cport_id = (u16)data[0]; - data = &data[1]; - - /* Pass this data to the greybus core */ - greybus_data_rcvd(hd, cport_id, data, urb->actual_length - 1); - -exit: - /* put our urb back in the request pool */ - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - dev_err(dev, "%s: error %d in submitting urb.\n", - __func__, retval); -} - -static void cport_out_callback(struct urb *urb) -{ - struct greybus_host_device *hd = urb->context; - struct es1_ap_dev *es1 = hd_to_es1(hd); - unsigned long flags; - int status = check_urb_status(urb); - u8 *data = urb->transfer_buffer + 1; - int i; - - /* - * Tell the submitter that the buffer send (attempt) is - * complete, and report the status. The submitter's buffer - * starts after the one-byte CPort id we inserted. - */ - data = urb->transfer_buffer + 1; - greybus_data_sent(hd, data, status); - - /* - * See if this was an urb in our pool, if so mark it "free", otherwise - * we need to free it ourselves. - */ - spin_lock_irqsave(&es1->cport_out_urb_lock, flags); - for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - if (urb == es1->cport_out_urb[i]) { - es1->cport_out_urb_busy[i] = false; - urb = NULL; - break; - } - } - spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); - - /* If urb is not NULL, then we need to free this urb */ - usb_free_urb(urb); - - /* - * Rest assured Greg, this craziness is getting fixed. - * - * Yes, you are right, we aren't telling anyone that the urb finished. - * "That's crazy! How does this all even work?" you might be saying. - * The "magic" is the idea that greybus works on the "operation" level, - * not the "send a buffer" level. All operations are "round-trip" with - * a response from the device that the operation finished, or it will - * time out. Because of that, we don't care that this urb finished, or - * failed, or did anything else, as higher levels of the protocol stack - * will handle completions and timeouts and the rest. - * - * This protocol is "needed" due to some hardware restrictions on the - * current generation of Unipro controllers. Think about it for a - * minute, this is a USB driver, talking to a Unipro bridge, impedance - * mismatch is huge, yet the Unipro controller are even more - * underpowered than this little USB controller. We rely on the round - * trip to keep stalls in the Unipro controllers from happening so that - * we can keep data flowing properly, no matter how slow it might be. - * - * Once again, a wonderful bus protocol cut down in its prime by a naive - * controller chip. We dream of the day we have a "real" HCD for - * Unipro. Until then, we suck it up and make the hardware work, as - * that's the job of the firmware and kernel. - * - */ -} - -/* - * The ES1 USB Bridge device contains 4 endpoints - * 1 Control - usual USB stuff + AP -> SVC messages - * 1 Interrupt IN - SVC -> AP messages - * 1 Bulk IN - CPort data in - * 1 Bulk OUT - CPort data out - */ -static int ap_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct es1_ap_dev *es1; - struct greybus_host_device *hd; - struct usb_device *udev; - struct usb_host_interface *iface_desc; - struct usb_endpoint_descriptor *endpoint; - bool int_in_found = false; - bool bulk_in_found = false; - bool bulk_out_found = false; - int retval = -ENOMEM; - int i; - u8 svc_interval = 0; - - udev = usb_get_dev(interface_to_usbdev(interface)); - - hd = greybus_create_hd(&es1_driver, &udev->dev); - if (!hd) { - usb_put_dev(udev); - return -ENOMEM; - } - - /* Fill in the buffer allocation constraints */ - hd_buffer_constraints(hd); - - es1 = hd_to_es1(hd); - es1->hd = hd; - es1->usb_intf = interface; - es1->usb_dev = udev; - spin_lock_init(&es1->cport_out_urb_lock); - usb_set_intfdata(interface, es1); - - /* Control endpoint is the pipe to talk to this AP, so save it off */ - endpoint = &udev->ep0.desc; - es1->control_endpoint = endpoint->bEndpointAddress; - - /* find all 3 of our endpoints */ - iface_desc = interface->cur_altsetting; - for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { - endpoint = &iface_desc->endpoint[i].desc; - - if (usb_endpoint_is_int_in(endpoint)) { - es1->svc_endpoint = endpoint->bEndpointAddress; - svc_interval = endpoint->bInterval; - int_in_found = true; - } else if (usb_endpoint_is_bulk_in(endpoint)) { - es1->cport_in_endpoint = endpoint->bEndpointAddress; - bulk_in_found = true; - } else if (usb_endpoint_is_bulk_out(endpoint)) { - es1->cport_out_endpoint = endpoint->bEndpointAddress; - bulk_out_found = true; - } else { - dev_err(&udev->dev, - "Unknown endpoint type found, address %x\n", - endpoint->bEndpointAddress); - } - } - if ((int_in_found == false) || - (bulk_in_found == false) || - (bulk_out_found == false)) { - dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n"); - goto error; - } - - /* Create our buffer and URB to get SVC messages, and start it up */ - es1->svc_buffer = kmalloc(ES1_SVC_MSG_SIZE, GFP_KERNEL); - if (!es1->svc_buffer) - goto error; - - es1->svc_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!es1->svc_urb) - goto error; - - usb_fill_int_urb(es1->svc_urb, udev, - usb_rcvintpipe(udev, es1->svc_endpoint), - es1->svc_buffer, ES1_SVC_MSG_SIZE, svc_in_callback, - hd, svc_interval); - retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); - if (retval) - goto error; - - /* Allocate buffers for our cport in messages and start them up */ - for (i = 0; i < NUM_CPORT_IN_URB; ++i) { - struct urb *urb; - u8 *buffer; - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) - goto error; - buffer = kmalloc(ES1_GBUF_MSG_SIZE_MAX, GFP_KERNEL); - if (!buffer) - goto error; - - usb_fill_bulk_urb(urb, udev, - usb_rcvbulkpipe(udev, es1->cport_in_endpoint), - buffer, ES1_GBUF_MSG_SIZE_MAX, - cport_in_callback, hd); - es1->cport_in_urb[i] = urb; - es1->cport_in_buffer[i] = buffer; - retval = usb_submit_urb(urb, GFP_KERNEL); - if (retval) - goto error; - } - - /* Allocate urbs for our CPort OUT messages */ - for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - struct urb *urb; - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) - goto error; - - es1->cport_out_urb[i] = urb; - es1->cport_out_urb_busy[i] = false; /* just to be anal */ - } - - return 0; -error: - ap_disconnect(interface); - - return retval; -} - -static struct usb_driver es1_ap_driver = { - .name = "es1_ap_driver", - .probe = ap_probe, - .disconnect = ap_disconnect, - .id_table = id_table, -}; - -module_usb_driver(es1_ap_driver); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Greg Kroah-Hartman "); diff --git a/drivers/staging/greybus/gb-es1.c b/drivers/staging/greybus/gb-es1.c new file mode 100644 index 0000000..27416e4 --- /dev/null +++ b/drivers/staging/greybus/gb-es1.c @@ -0,0 +1,617 @@ +/* + * Greybus "AP" USB driver + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ +#include +#include +#include +#include +#include +#include + +#include "greybus.h" +#include "svc_msg.h" +#include "kernel_ver.h" + +/* + * Macros for making pointers explicitly opaque, such that the result + * isn't valid but also can't be mistaken for an ERR_PTR() value. + */ +#define conceal_urb(urb) ((void *)((uintptr_t)(urb) ^ 0xbad)) +#define reveal_urb(cookie) ((void *)((uintptr_t)(cookie) ^ 0xbad)) + +/* Memory sizes for the buffers sent to/from the ES1 controller */ +#define ES1_SVC_MSG_SIZE (sizeof(struct svc_msg) + SZ_64K) +#define ES1_GBUF_MSG_SIZE_MAX PAGE_SIZE + +static const struct usb_device_id id_table[] = { + /* Made up numbers for the SVC USB Bridge in ES1 */ + { USB_DEVICE(0xffff, 0x0001) }, + { }, +}; +MODULE_DEVICE_TABLE(usb, id_table); + +/* + * Number of CPort IN urbs in flight at any point in time. + * Adjust if we are having stalls in the USB buffer due to not enough urbs in + * flight. + */ +#define NUM_CPORT_IN_URB 4 + +/* Number of CPort OUT urbs in flight at any point in time. + * Adjust if we get messages saying we are out of urbs in the system log. + */ +#define NUM_CPORT_OUT_URB 8 + +/** + * es1_ap_dev - ES1 USB Bridge to AP structure + * @usb_dev: pointer to the USB device we are. + * @usb_intf: pointer to the USB interface we are bound to. + * @hd: pointer to our greybus_host_device structure + * @control_endpoint: endpoint to send data to SVC + * @svc_endpoint: endpoint for SVC data in + * @cport_in_endpoint: bulk in endpoint for CPort data + * @cport-out_endpoint: bulk out endpoint for CPort data + * @svc_buffer: buffer for SVC messages coming in on @svc_endpoint + * @svc_urb: urb for SVC messages coming in on @svc_endpoint + * @cport_in_urb: array of urbs for the CPort in messages + * @cport_in_buffer: array of buffers for the @cport_in_urb urbs + * @cport_out_urb: array of urbs for the CPort out messages + * @cport_out_urb_busy: array of flags to see if the @cport_out_urb is busy or + * not. + * @cport_out_urb_lock: locks the @cport_out_urb_busy "list" + */ +struct es1_ap_dev { + struct usb_device *usb_dev; + struct usb_interface *usb_intf; + struct greybus_host_device *hd; + + __u8 control_endpoint; + __u8 svc_endpoint; + __u8 cport_in_endpoint; + __u8 cport_out_endpoint; + + u8 *svc_buffer; + struct urb *svc_urb; + + struct urb *cport_in_urb[NUM_CPORT_IN_URB]; + u8 *cport_in_buffer[NUM_CPORT_IN_URB]; + struct urb *cport_out_urb[NUM_CPORT_OUT_URB]; + bool cport_out_urb_busy[NUM_CPORT_OUT_URB]; + spinlock_t cport_out_urb_lock; +}; + +static inline struct es1_ap_dev *hd_to_es1(struct greybus_host_device *hd) +{ + return (struct es1_ap_dev *)&hd->hd_priv; +} + +static void cport_out_callback(struct urb *urb); + +/* + * Buffer constraints for the host driver. + * + * A "buffer" is used to hold data to be transferred for Greybus by + * the host driver. A buffer is represented by a "buffer pointer", + * which defines a region of memory used by the host driver for + * transferring the data. When Greybus allocates a buffer, it must + * do so subject to the constraints associated with the host driver. + * These constraints are specified by two parameters: the + * headroom; and the maximum buffer size. + * + * +------------------+ + * | Host driver | \ + * | reserved area | }- headroom + * | . . . | / + * buffer pointer ---> +------------------+ + * | Buffer space for | \ + * | transferred data | }- buffer size + * | . . . | / (limited to size_max) + * +------------------+ + * + * headroom: Every buffer must have at least this much space + * *before* the buffer pointer, reserved for use by the + * host driver. I.e., ((char *)buffer - headroom) must + * point to valid memory, usable only by the host driver. + * size_max: The maximum size of a buffer (not including the + * headroom) must not exceed this. + */ +static void hd_buffer_constraints(struct greybus_host_device *hd) +{ + /* + * Only one byte is required, but this produces a result + * that's better aligned for the user. + */ + hd->buffer_headroom = sizeof(u32); /* For cport id */ + hd->buffer_size_max = ES1_GBUF_MSG_SIZE_MAX; + BUILD_BUG_ON(hd->buffer_headroom > GB_BUFFER_HEADROOM_MAX); +} + +#define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ +static int submit_svc(struct svc_msg *svc_msg, struct greybus_host_device *hd) +{ + struct es1_ap_dev *es1 = hd_to_es1(hd); + int retval; + + /* SVC messages go down our control pipe */ + retval = usb_control_msg(es1->usb_dev, + usb_sndctrlpipe(es1->usb_dev, + es1->control_endpoint), + 0x01, /* vendor request AP message */ + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + 0x00, 0x00, + (char *)svc_msg, + sizeof(*svc_msg), + ES1_TIMEOUT); + if (retval != sizeof(*svc_msg)) + return retval; + + return 0; +} + +static struct urb *next_free_urb(struct es1_ap_dev *es1, gfp_t gfp_mask) +{ + struct urb *urb = NULL; + unsigned long flags; + int i; + + spin_lock_irqsave(&es1->cport_out_urb_lock, flags); + + /* Look in our pool of allocated urbs first, as that's the "fastest" */ + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + if (es1->cport_out_urb_busy[i] == false) { + es1->cport_out_urb_busy[i] = true; + urb = es1->cport_out_urb[i]; + break; + } + } + spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); + if (urb) + return urb; + + /* + * Crap, pool is empty, complain to the syslog and go allocate one + * dynamically as we have to succeed. + */ + dev_err(&es1->usb_dev->dev, + "No free CPort OUT urbs, having to dynamically allocate one!\n"); + urb = usb_alloc_urb(0, gfp_mask); + if (!urb) + return NULL; + + return urb; +} + +/* + * Returns an opaque cookie value if successful, or a pointer coded + * error otherwise. If the caller wishes to cancel the in-flight + * buffer, it must supply the returned cookie to the cancel routine. + */ +static void *buffer_send(struct greybus_host_device *hd, u16 cport_id, + void *buffer, size_t buffer_size, gfp_t gfp_mask) +{ + struct es1_ap_dev *es1 = hd_to_es1(hd); + struct usb_device *udev = es1->usb_dev; + u8 *transfer_buffer = buffer; + int transfer_buffer_size; + int retval; + struct urb *urb; + + if (!buffer) { + pr_err("null buffer supplied to send\n"); + return ERR_PTR(-EINVAL); + } + if (buffer_size > (size_t)INT_MAX) { + pr_err("bad buffer size (%zu) supplied to send\n", buffer_size); + return ERR_PTR(-EINVAL); + } + transfer_buffer--; + transfer_buffer_size = buffer_size + 1; + + /* + * The data actually transferred will include an indication + * of where the data should be sent. Do one last check of + * the target CPort id before filling it in. + */ + if (cport_id == CPORT_ID_BAD) { + pr_err("request to send inbound data buffer\n"); + return ERR_PTR(-EINVAL); + } + if (cport_id > (u16)U8_MAX) { + pr_err("cport_id (%hd) is out of range for ES1\n", cport_id); + return ERR_PTR(-EINVAL); + } + /* OK, the destination is fine; record it in the transfer buffer */ + *transfer_buffer = cport_id; + + /* Find a free urb */ + urb = next_free_urb(es1, gfp_mask); + if (!urb) + return ERR_PTR(-ENOMEM); + + usb_fill_bulk_urb(urb, udev, + usb_sndbulkpipe(udev, es1->cport_out_endpoint), + transfer_buffer, transfer_buffer_size, + cport_out_callback, hd); + retval = usb_submit_urb(urb, gfp_mask); + if (retval) { + pr_err("error %d submitting URB\n", retval); + return ERR_PTR(retval); + } + + return conceal_urb(urb); +} + +/* + * The cookie value supplied is the value that buffer_send() + * returned to its caller. It identifies the buffer that should be + * canceled. This function must also handle (which is to say, + * ignore) a null cookie value. + */ +static void buffer_cancel(void *cookie) +{ + + /* + * We really should be defensive and track all outstanding + * (sent) buffers rather than trusting the cookie provided + * is valid. For the time being, this will do. + */ + if (cookie) + usb_kill_urb(reveal_urb(cookie)); +} + +static struct greybus_host_driver es1_driver = { + .hd_priv_size = sizeof(struct es1_ap_dev), + .buffer_send = buffer_send, + .buffer_cancel = buffer_cancel, + .submit_svc = submit_svc, +}; + +/* Common function to report consistent warnings based on URB status */ +static int check_urb_status(struct urb *urb) +{ + struct device *dev = &urb->dev->dev; + int status = urb->status; + + switch (status) { + case 0: + return 0; + + case -EOVERFLOW: + dev_err(dev, "%s: overflow actual length is %d\n", + __func__, urb->actual_length); + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + case -EILSEQ: + case -EPROTO: + /* device is gone, stop sending */ + return status; + } + dev_err(dev, "%s: unknown status %d\n", __func__, status); + + return -EAGAIN; +} + +static void ap_disconnect(struct usb_interface *interface) +{ + struct es1_ap_dev *es1; + struct usb_device *udev; + int i; + + es1 = usb_get_intfdata(interface); + if (!es1) + return; + + /* Tear down everything! */ + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + struct urb *urb = es1->cport_out_urb[i]; + + if (!urb) + break; + usb_kill_urb(urb); + usb_free_urb(urb); + es1->cport_out_urb[i] = NULL; + es1->cport_out_urb_busy[i] = false; /* just to be anal */ + } + + for (i = 0; i < NUM_CPORT_IN_URB; ++i) { + struct urb *urb = es1->cport_in_urb[i]; + + if (!urb) + break; + usb_kill_urb(urb); + usb_free_urb(urb); + kfree(es1->cport_in_buffer[i]); + es1->cport_in_buffer[i] = NULL; + } + + usb_kill_urb(es1->svc_urb); + usb_free_urb(es1->svc_urb); + es1->svc_urb = NULL; + kfree(es1->svc_buffer); + es1->svc_buffer = NULL; + + usb_set_intfdata(interface, NULL); + udev = es1->usb_dev; + greybus_remove_hd(es1->hd); + + usb_put_dev(udev); +} + +/* Callback for when we get a SVC message */ +static void svc_in_callback(struct urb *urb) +{ + struct greybus_host_device *hd = urb->context; + struct device *dev = &urb->dev->dev; + int status = check_urb_status(urb); + int retval; + + if (status) { + if ((status == -EAGAIN) || (status == -EPROTO)) + goto exit; + dev_err(dev, "urb svc in error %d (dropped)\n", status); + return; + } + + /* We have a message, create a new message structure, add it to the + * list, and wake up our thread that will process the messages. + */ + greybus_svc_in(hd, urb->transfer_buffer, urb->actual_length); + +exit: + /* resubmit the urb to get more messages */ + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) + dev_err(dev, "Can not submit urb for AP data: %d\n", retval); +} + +static void cport_in_callback(struct urb *urb) +{ + struct greybus_host_device *hd = urb->context; + struct device *dev = &urb->dev->dev; + int status = check_urb_status(urb); + int retval; + u16 cport_id; + u8 *data; + + if (status) { + if ((status == -EAGAIN) || (status == -EPROTO)) + goto exit; + dev_err(dev, "urb cport in error %d (dropped)\n", status); + return; + } + + /* The size has to be at least one, for the cport id */ + if (!urb->actual_length) { + dev_err(dev, "%s: no cport id in input buffer?\n", __func__); + goto exit; + } + + /* + * Our CPort number is the first byte of the data stream, + * the rest of the stream is "real" data + */ + data = urb->transfer_buffer; + cport_id = (u16)data[0]; + data = &data[1]; + + /* Pass this data to the greybus core */ + greybus_data_rcvd(hd, cport_id, data, urb->actual_length - 1); + +exit: + /* put our urb back in the request pool */ + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) + dev_err(dev, "%s: error %d in submitting urb.\n", + __func__, retval); +} + +static void cport_out_callback(struct urb *urb) +{ + struct greybus_host_device *hd = urb->context; + struct es1_ap_dev *es1 = hd_to_es1(hd); + unsigned long flags; + int status = check_urb_status(urb); + u8 *data = urb->transfer_buffer + 1; + int i; + + /* + * Tell the submitter that the buffer send (attempt) is + * complete, and report the status. The submitter's buffer + * starts after the one-byte CPort id we inserted. + */ + data = urb->transfer_buffer + 1; + greybus_data_sent(hd, data, status); + + /* + * See if this was an urb in our pool, if so mark it "free", otherwise + * we need to free it ourselves. + */ + spin_lock_irqsave(&es1->cport_out_urb_lock, flags); + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + if (urb == es1->cport_out_urb[i]) { + es1->cport_out_urb_busy[i] = false; + urb = NULL; + break; + } + } + spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); + + /* If urb is not NULL, then we need to free this urb */ + usb_free_urb(urb); + + /* + * Rest assured Greg, this craziness is getting fixed. + * + * Yes, you are right, we aren't telling anyone that the urb finished. + * "That's crazy! How does this all even work?" you might be saying. + * The "magic" is the idea that greybus works on the "operation" level, + * not the "send a buffer" level. All operations are "round-trip" with + * a response from the device that the operation finished, or it will + * time out. Because of that, we don't care that this urb finished, or + * failed, or did anything else, as higher levels of the protocol stack + * will handle completions and timeouts and the rest. + * + * This protocol is "needed" due to some hardware restrictions on the + * current generation of Unipro controllers. Think about it for a + * minute, this is a USB driver, talking to a Unipro bridge, impedance + * mismatch is huge, yet the Unipro controller are even more + * underpowered than this little USB controller. We rely on the round + * trip to keep stalls in the Unipro controllers from happening so that + * we can keep data flowing properly, no matter how slow it might be. + * + * Once again, a wonderful bus protocol cut down in its prime by a naive + * controller chip. We dream of the day we have a "real" HCD for + * Unipro. Until then, we suck it up and make the hardware work, as + * that's the job of the firmware and kernel. + * + */ +} + +/* + * The ES1 USB Bridge device contains 4 endpoints + * 1 Control - usual USB stuff + AP -> SVC messages + * 1 Interrupt IN - SVC -> AP messages + * 1 Bulk IN - CPort data in + * 1 Bulk OUT - CPort data out + */ +static int ap_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct es1_ap_dev *es1; + struct greybus_host_device *hd; + struct usb_device *udev; + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + bool int_in_found = false; + bool bulk_in_found = false; + bool bulk_out_found = false; + int retval = -ENOMEM; + int i; + u8 svc_interval = 0; + + udev = usb_get_dev(interface_to_usbdev(interface)); + + hd = greybus_create_hd(&es1_driver, &udev->dev); + if (!hd) { + usb_put_dev(udev); + return -ENOMEM; + } + + /* Fill in the buffer allocation constraints */ + hd_buffer_constraints(hd); + + es1 = hd_to_es1(hd); + es1->hd = hd; + es1->usb_intf = interface; + es1->usb_dev = udev; + spin_lock_init(&es1->cport_out_urb_lock); + usb_set_intfdata(interface, es1); + + /* Control endpoint is the pipe to talk to this AP, so save it off */ + endpoint = &udev->ep0.desc; + es1->control_endpoint = endpoint->bEndpointAddress; + + /* find all 3 of our endpoints */ + iface_desc = interface->cur_altsetting; + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i].desc; + + if (usb_endpoint_is_int_in(endpoint)) { + es1->svc_endpoint = endpoint->bEndpointAddress; + svc_interval = endpoint->bInterval; + int_in_found = true; + } else if (usb_endpoint_is_bulk_in(endpoint)) { + es1->cport_in_endpoint = endpoint->bEndpointAddress; + bulk_in_found = true; + } else if (usb_endpoint_is_bulk_out(endpoint)) { + es1->cport_out_endpoint = endpoint->bEndpointAddress; + bulk_out_found = true; + } else { + dev_err(&udev->dev, + "Unknown endpoint type found, address %x\n", + endpoint->bEndpointAddress); + } + } + if ((int_in_found == false) || + (bulk_in_found == false) || + (bulk_out_found == false)) { + dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n"); + goto error; + } + + /* Create our buffer and URB to get SVC messages, and start it up */ + es1->svc_buffer = kmalloc(ES1_SVC_MSG_SIZE, GFP_KERNEL); + if (!es1->svc_buffer) + goto error; + + es1->svc_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!es1->svc_urb) + goto error; + + usb_fill_int_urb(es1->svc_urb, udev, + usb_rcvintpipe(udev, es1->svc_endpoint), + es1->svc_buffer, ES1_SVC_MSG_SIZE, svc_in_callback, + hd, svc_interval); + retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); + if (retval) + goto error; + + /* Allocate buffers for our cport in messages and start them up */ + for (i = 0; i < NUM_CPORT_IN_URB; ++i) { + struct urb *urb; + u8 *buffer; + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) + goto error; + buffer = kmalloc(ES1_GBUF_MSG_SIZE_MAX, GFP_KERNEL); + if (!buffer) + goto error; + + usb_fill_bulk_urb(urb, udev, + usb_rcvbulkpipe(udev, es1->cport_in_endpoint), + buffer, ES1_GBUF_MSG_SIZE_MAX, + cport_in_callback, hd); + es1->cport_in_urb[i] = urb; + es1->cport_in_buffer[i] = buffer; + retval = usb_submit_urb(urb, GFP_KERNEL); + if (retval) + goto error; + } + + /* Allocate urbs for our CPort OUT messages */ + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + struct urb *urb; + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) + goto error; + + es1->cport_out_urb[i] = urb; + es1->cport_out_urb_busy[i] = false; /* just to be anal */ + } + + return 0; +error: + ap_disconnect(interface); + + return retval; +} + +static struct usb_driver es1_ap_driver = { + .name = "es1_ap_driver", + .probe = ap_probe, + .disconnect = ap_disconnect, + .id_table = id_table, +}; + +module_usb_driver(es1_ap_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Greg Kroah-Hartman "); -- cgit v0.10.2 From c86117a8a8b4aaff67a65dc9a415352f48ef45d0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 14 Jan 2015 17:08:03 -0800 Subject: greybus: Move the es1_ap_desc.c file to Documentation directory This .c file isn't needed by the kernel driver, it's there for firmware developers only, so just move it into the Documentation directory to reduce confusion. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/Documentation/es1_ap_desc.c b/drivers/staging/greybus/Documentation/es1_ap_desc.c new file mode 100644 index 0000000..1502089 --- /dev/null +++ b/drivers/staging/greybus/Documentation/es1_ap_desc.c @@ -0,0 +1,70 @@ +/* ES1 AP Bridge Chip USB descriptor definitions */ + +static const u8 es1_dev_descriptor[] = { + 0x12, /* __u8 bLength */ + 0x01, /* __u8 bDescriptorType; Device */ + 0x00, 0x02 /* __le16 bcdUSB v2.0 */ + 0x00, /* __u8 bDeviceClass */ + 0x00, /* __u8 bDeviceClass */ + 0x00, /* __u8 bDeviceSubClass; */ + 0x00, /* __u8 bDeviceProtocol; */ + 0x40, /* __u8 bMaxPacketSize0; 2^64 = 512 Bytes */ + + 0xff, 0xff, /* __le16 idVendor; 0xffff made up for now */ + 0x01, 0x00, /* __le16 idProduct; 0x0001 made up for now */ + 0x01, 0x00, /* __le16 bcdDevice; ES1 */ + + 0x03, /* __u8 iManufacturer; */ + 0x02, /* __u8 iProduct; */ + 0x01, /* __u8 iSerialNumber; */ + 0x01 /* __u8 bNumConfigurations; */ +}; + +static const u8 es1_config_descriptor[] = { + /* one configuration */ + 0x09, /* __u8 bLength; */ + 0x02, /* __u8 bDescriptorType; Configuration */ + 0x19, 0x00, /* __le16 wTotalLength; */ + 0x01, /* __u8 bNumInterfaces; (1) */ + 0x01, /* __u8 bConfigurationValue; */ + 0x00, /* __u8 iConfiguration; */ + 0xc0, /* __u8 bmAttributes; + Bit 7: must be set, + 6: Self-powered, + 5: Remote wakeup, + 4..0: resvd */ + 0x00, /* __u8 MaxPower; */ + + /* one interface */ + 0x09, /* __u8 if_bLength; */ + 0x04, /* __u8 if_bDescriptorType; Interface */ + 0x00, /* __u8 if_bInterfaceNumber; */ + 0x00, /* __u8 if_bAlternateSetting; */ + 0x03, /* __u8 if_bNumEndpoints; */ + 0xff, /* __u8 if_bInterfaceClass; Vendor-specific */ + 0xff, /* __u8 if_bInterfaceSubClass; Vendor-specific */ + 0xff, /* __u8 if_bInterfaceProtocol; Vendor-specific */ + 0x00, /* __u8 if_iInterface; */ + + /* three endpoints */ + 0x07, /* __u8 ep_bLength; */ + 0x05, /* __u8 ep_bDescriptorType; Endpoint */ + 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ + 0x03, /* __u8 ep_bmAttributes; Interrupt */ + 0x00, 0x04, /* __le16 ep_wMaxPacketSize; 1024 */ + 0x40, /* __u8 ep_bInterval; 64ms */ + + 0x07, /* __u8 ep_bLength; */ + 0x05, /* __u8 ep_bDescriptorType; Endpoint */ + 0x82, /* __u8 ep_bEndpointAddress; IN Endpoint 2 */ + 0x02, /* __u8 ep_bmAttributes; Bulk */ + 0x00, 0x04, /* __le16 ep_wMaxPacketSize; 1024 */ + 0x40 /* __u8 ep_bInterval; */ + + 0x07, /* __u8 ep_bLength; */ + 0x05, /* __u8 ep_bDescriptorType; Endpoint */ + 0x02, /* __u8 ep_bEndpointAddress; Out Endpoint 2 */ + 0x02, /* __u8 ep_bmAttributes; Bulk */ + 0x00, 0x04, /* __le16 ep_wMaxPacketSize; 1024 */ + 0x40 /* __u8 ep_bInterval; */ +}; diff --git a/drivers/staging/greybus/es1_ap_desc.c b/drivers/staging/greybus/es1_ap_desc.c deleted file mode 100644 index 1502089..0000000 --- a/drivers/staging/greybus/es1_ap_desc.c +++ /dev/null @@ -1,70 +0,0 @@ -/* ES1 AP Bridge Chip USB descriptor definitions */ - -static const u8 es1_dev_descriptor[] = { - 0x12, /* __u8 bLength */ - 0x01, /* __u8 bDescriptorType; Device */ - 0x00, 0x02 /* __le16 bcdUSB v2.0 */ - 0x00, /* __u8 bDeviceClass */ - 0x00, /* __u8 bDeviceClass */ - 0x00, /* __u8 bDeviceSubClass; */ - 0x00, /* __u8 bDeviceProtocol; */ - 0x40, /* __u8 bMaxPacketSize0; 2^64 = 512 Bytes */ - - 0xff, 0xff, /* __le16 idVendor; 0xffff made up for now */ - 0x01, 0x00, /* __le16 idProduct; 0x0001 made up for now */ - 0x01, 0x00, /* __le16 bcdDevice; ES1 */ - - 0x03, /* __u8 iManufacturer; */ - 0x02, /* __u8 iProduct; */ - 0x01, /* __u8 iSerialNumber; */ - 0x01 /* __u8 bNumConfigurations; */ -}; - -static const u8 es1_config_descriptor[] = { - /* one configuration */ - 0x09, /* __u8 bLength; */ - 0x02, /* __u8 bDescriptorType; Configuration */ - 0x19, 0x00, /* __le16 wTotalLength; */ - 0x01, /* __u8 bNumInterfaces; (1) */ - 0x01, /* __u8 bConfigurationValue; */ - 0x00, /* __u8 iConfiguration; */ - 0xc0, /* __u8 bmAttributes; - Bit 7: must be set, - 6: Self-powered, - 5: Remote wakeup, - 4..0: resvd */ - 0x00, /* __u8 MaxPower; */ - - /* one interface */ - 0x09, /* __u8 if_bLength; */ - 0x04, /* __u8 if_bDescriptorType; Interface */ - 0x00, /* __u8 if_bInterfaceNumber; */ - 0x00, /* __u8 if_bAlternateSetting; */ - 0x03, /* __u8 if_bNumEndpoints; */ - 0xff, /* __u8 if_bInterfaceClass; Vendor-specific */ - 0xff, /* __u8 if_bInterfaceSubClass; Vendor-specific */ - 0xff, /* __u8 if_bInterfaceProtocol; Vendor-specific */ - 0x00, /* __u8 if_iInterface; */ - - /* three endpoints */ - 0x07, /* __u8 ep_bLength; */ - 0x05, /* __u8 ep_bDescriptorType; Endpoint */ - 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ - 0x03, /* __u8 ep_bmAttributes; Interrupt */ - 0x00, 0x04, /* __le16 ep_wMaxPacketSize; 1024 */ - 0x40, /* __u8 ep_bInterval; 64ms */ - - 0x07, /* __u8 ep_bLength; */ - 0x05, /* __u8 ep_bDescriptorType; Endpoint */ - 0x82, /* __u8 ep_bEndpointAddress; IN Endpoint 2 */ - 0x02, /* __u8 ep_bmAttributes; Bulk */ - 0x00, 0x04, /* __le16 ep_wMaxPacketSize; 1024 */ - 0x40 /* __u8 ep_bInterval; */ - - 0x07, /* __u8 ep_bLength; */ - 0x05, /* __u8 ep_bDescriptorType; Endpoint */ - 0x02, /* __u8 ep_bEndpointAddress; Out Endpoint 2 */ - 0x02, /* __u8 ep_bmAttributes; Bulk */ - 0x00, 0x04, /* __le16 ep_wMaxPacketSize; 1024 */ - 0x40 /* __u8 ep_bInterval; */ -}; -- cgit v0.10.2 From 4e2b07e9ab8f8ddc7f6dbb6617ddb2bc704d15e9 Mon Sep 17 00:00:00 2001 From: Bill Pemberton Date: Thu, 15 Jan 2015 21:18:26 -0500 Subject: greybus: gb-vibrator: remove useless if in timeout_store() val is an unsigned long so there is no point in checking if it is less than zero. Signed-off-by: Bill Pemberton Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gb-vibrator.c b/drivers/staging/greybus/gb-vibrator.c index c85d950..b5332df 100644 --- a/drivers/staging/greybus/gb-vibrator.c +++ b/drivers/staging/greybus/gb-vibrator.c @@ -100,8 +100,6 @@ static ssize_t timeout_store(struct device *dev, struct device_attribute *attr, return retval; } - if (val < 0) - return -EINVAL; if (val) retval = turn_on(vib, (u16)val); else -- cgit v0.10.2 From 9d677cf604212313f41097e2f542e1923d717086 Mon Sep 17 00:00:00 2001 From: Bill Pemberton Date: Thu, 15 Jan 2015 21:18:27 -0500 Subject: greybus: Add FIXME warnings for possible NULL dereferences Signed-off-by: Bill Pemberton Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 44cfd50..f014906 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -742,6 +742,7 @@ int gb_operation_response_send(struct gb_operation *operation, int errno) } } + /* FIXME operation->response could still be NULL here */ /* Fill in the response header and send it */ operation->response->header->result = gb_operation_errno_map(errno); diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index 562401d..b8ae707 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -188,6 +188,9 @@ void gb_protocol_put(struct gb_protocol *protocol) if (protocol) WARN_ON(!protocol_count); else + /* FIXME a different message is needed since this one + * will result in a NULL dereference + */ pr_err("protocol id %hhu version %hhu.%hhu not found\n", protocol->id, major, minor); } -- cgit v0.10.2 From 76590b1e882f4c275df695ae0641fb2d059cd9c3 Mon Sep 17 00:00:00 2001 From: Bill Pemberton Date: Fri, 16 Jan 2015 13:57:32 -0500 Subject: greybus: gpio-gb: remove checks for negative offset variable offset is defined as unsigned so there is no point checking for negative values of offset. Signed-off-by: Bill Pemberton Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c index 5fcd018..4997588 100644 --- a/drivers/staging/greybus/gpio-gb.c +++ b/drivers/staging/greybus/gpio-gb.c @@ -312,7 +312,7 @@ static int gb_gpio_request(struct gpio_chip *chip, unsigned offset) struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); int ret; - if (offset < 0 || offset >= chip->ngpio) + if (offset >= chip->ngpio) return -EINVAL; ret = gb_gpio_activate_operation(gb_gpio_controller, (u8)offset); if (ret) @@ -325,7 +325,7 @@ static void gb_gpio_free(struct gpio_chip *chip, unsigned offset) struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); int ret; - if (offset < 0 || offset >= chip->ngpio) { + if (offset >= chip->ngpio) { pr_err("bad offset %u supplied (must be 0..%u)\n", offset, chip->ngpio - 1); return; @@ -341,7 +341,7 @@ static int gb_gpio_get_direction(struct gpio_chip *chip, unsigned offset) u8 which; int ret; - if (offset < 0 || offset >= chip->ngpio) + if (offset >= chip->ngpio) return -EINVAL; which = (u8)offset; ret = gb_gpio_get_direction_operation(gb_gpio_controller, which); @@ -355,7 +355,7 @@ static int gb_gpio_direction_input(struct gpio_chip *chip, unsigned offset) struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); int ret; - if (offset < 0 || offset >= chip->ngpio) + if (offset >= chip->ngpio) return -EINVAL; ret = gb_gpio_direction_in_operation(gb_gpio_controller, (u8)offset); if (ret) @@ -369,7 +369,7 @@ static int gb_gpio_direction_output(struct gpio_chip *chip, unsigned offset, struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); int ret; - if (offset < 0 || offset >= chip->ngpio) + if (offset >= chip->ngpio) return -EINVAL; ret = gb_gpio_direction_out_operation(gb_gpio_controller, (u8)offset, !!value); if (ret) @@ -383,7 +383,7 @@ static int gb_gpio_get(struct gpio_chip *chip, unsigned offset) u8 which; int ret; - if (offset < 0 || offset >= chip->ngpio) + if (offset >= chip->ngpio) return -EINVAL; which = (u8)offset; ret = gb_gpio_get_value_operation(gb_gpio_controller, which); @@ -414,7 +414,7 @@ static int gb_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, u16 usec; int ret; - if (offset < 0 || offset >= chip->ngpio) + if (offset >= chip->ngpio) return -EINVAL; if (debounce > (unsigned int)U16_MAX) return -EINVAL; @@ -428,7 +428,7 @@ static int gb_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, static int gb_gpio_to_irq(struct gpio_chip *chip, unsigned offset) { - if (offset < 0 || offset >= chip->ngpio) + if (offset >= chip->ngpio) return -EINVAL; return 0; /* XXX */ -- cgit v0.10.2 From 7bad4e85b8f988a182cce7949591923e091a509e Mon Sep 17 00:00:00 2001 From: Perry Hung Date: Wed, 14 Jan 2015 16:19:26 -0500 Subject: greybus: gb_operation: replace timeout workqueue If an operation is issued and the response never comes back, gb_operation_timeout() cancels the operation but never wakes up the waiter in gb_operation_request_send(). This patch removes the timeout workqueue and changes the request wait to wait_for_completion_interruptible_timeout(), with timeout set to OPERATION_TIMEOUT_DEFAULT. Signed-off-by: Perry Hung Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index f014906..0ee4475 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -248,16 +248,6 @@ static void gb_operation_work(struct work_struct *work) gb_operation_put(operation); } -/* - * Timeout call for the operation. - */ -static void gb_operation_timeout(struct work_struct *work) -{ - struct gb_operation *operation; - - operation = container_of(work, struct gb_operation, timeout_work.work); - gb_operation_cancel(operation, -ETIMEDOUT); -} /* * Given a pointer to the header in a message sent on a given host @@ -533,7 +523,6 @@ gb_operation_create_common(struct gb_connection *connection, u8 type, INIT_WORK(&operation->work, gb_operation_work); operation->callback = NULL; /* set at submit time */ init_completion(&operation->completion); - INIT_DELAYED_WORK(&operation->timeout_work, gb_operation_timeout); kref_init(&operation->kref); spin_lock_irq(&gb_operations_lock); @@ -652,7 +641,6 @@ int gb_operation_request_send(struct gb_operation *operation, { struct gb_connection *connection = operation->connection; struct gb_operation_msg_hdr *header; - unsigned long timeout; unsigned int cycle; if (connection->state != GB_CONNECTION_STATE_ENABLED) @@ -680,14 +668,6 @@ int gb_operation_request_send(struct gb_operation *operation, header = operation->request->header; header->operation_id = cpu_to_le16(operation->id); - /* - * We impose a time limit for requests to complete. We need - * to set the timer before we send the request though, so we - * don't lose a race with the receipt of the resposne. - */ - timeout = msecs_to_jiffies(OPERATION_TIMEOUT_DEFAULT); - schedule_delayed_work(&operation->timeout_work, timeout); - /* All set, send the request */ gb_operation_result_set(operation, -EINPROGRESS); @@ -703,15 +683,21 @@ int gb_operation_request_send(struct gb_operation *operation, int gb_operation_request_send_sync(struct gb_operation *operation) { int ret; + unsigned long timeout; ret = gb_operation_request_send(operation, gb_operation_sync_callback); if (ret) return ret; - /* Cancel the operation if interrupted */ - ret = wait_for_completion_interruptible(&operation->completion); - if (ret < 0) + timeout = msecs_to_jiffies(OPERATION_TIMEOUT_DEFAULT); + ret = wait_for_completion_interruptible_timeout(&operation->completion, timeout); + if (ret < 0) { + /* Cancel the operation if interrupted */ gb_operation_cancel(operation, -ECANCELED); + } else if (ret == 0) { + /* Cancel the operation if op timed out */ + gb_operation_cancel(operation, -ETIMEDOUT); + } return gb_operation_result(operation); } @@ -843,8 +829,6 @@ static void gb_connection_recv_response(struct gb_connection *connection, return; } - cancel_delayed_work(&operation->timeout_work); - message = operation->response; message_size = sizeof(*message->header) + message->payload_size; if (!errno && size != message_size) { diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index e6da827..6784f98 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -88,7 +88,6 @@ struct gb_operation { struct work_struct work; gb_operation_callback callback; /* If asynchronous */ struct completion completion; /* Used if no callback */ - struct delayed_work timeout_work; struct kref kref; struct list_head links; /* connection->operations */ -- cgit v0.10.2 From a1f2e40b1a30c2b8a2dfc40d859550081195b57a Mon Sep 17 00:00:00 2001 From: Perry Hung Date: Wed, 14 Jan 2015 16:19:27 -0500 Subject: greybus: gb_operation: drop operation refcount on cancel An extra reference is taken out on an operation in gb_operation_request_send(). If the response never arrives, we need to put back the reference. Signed-off-by: Perry Hung Tested-by: Mitchell Tasman Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 0ee4475..82ff306 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -895,6 +895,7 @@ void gb_operation_cancel(struct gb_operation *operation, int errno) gb_message_cancel(operation->request); gb_message_cancel(operation->response); } + gb_operation_put(operation); } /** -- cgit v0.10.2 From b976266051569557377ce63984b1562a8651838c Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Tue, 20 Jan 2015 16:31:45 +0000 Subject: greybus: es1: remove useless statement just return the result of usb_alloc_urb up, no need to rededunt check for NULL Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gb-es1.c b/drivers/staging/greybus/gb-es1.c index 27416e4..f44c26d 100644 --- a/drivers/staging/greybus/gb-es1.c +++ b/drivers/staging/greybus/gb-es1.c @@ -180,8 +180,6 @@ static struct urb *next_free_urb(struct es1_ap_dev *es1, gfp_t gfp_mask) dev_err(&es1->usb_dev->dev, "No free CPort OUT urbs, having to dynamically allocate one!\n"); urb = usb_alloc_urb(0, gfp_mask); - if (!urb) - return NULL; return urb; } -- cgit v0.10.2 From 0008d9d0ad0a2e854f2f3f61d58cdc44d98760ff Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Tue, 20 Jan 2015 16:38:44 +0000 Subject: greybus: es1: release urb on error path if error is return when submiting the urb, we need to make sure to release the urb from the pool, or from the dinamicly allocated. As in it, factor out the free code and create the free_urb function. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gb-es1.c b/drivers/staging/greybus/gb-es1.c index f44c26d..96c7c81 100644 --- a/drivers/staging/greybus/gb-es1.c +++ b/drivers/staging/greybus/gb-es1.c @@ -184,6 +184,28 @@ static struct urb *next_free_urb(struct es1_ap_dev *es1, gfp_t gfp_mask) return urb; } +static void free_urb(struct es1_ap_dev *es1, struct urb *urb) +{ + unsigned long flags; + int i; + /* + * See if this was an urb in our pool, if so mark it "free", otherwise + * we need to free it ourselves. + */ + spin_lock_irqsave(&es1->cport_out_urb_lock, flags); + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + if (urb == es1->cport_out_urb[i]) { + es1->cport_out_urb_busy[i] = false; + urb = NULL; + break; + } + } + spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); + + /* If urb is not NULL, then we need to free this urb */ + usb_free_urb(urb); +} + /* * Returns an opaque cookie value if successful, or a pointer coded * error otherwise. If the caller wishes to cancel the in-flight @@ -238,6 +260,7 @@ static void *buffer_send(struct greybus_host_device *hd, u16 cport_id, retval = usb_submit_urb(urb, gfp_mask); if (retval) { pr_err("error %d submitting URB\n", retval); + free_urb(es1, urb); return ERR_PTR(retval); } @@ -413,10 +436,8 @@ static void cport_out_callback(struct urb *urb) { struct greybus_host_device *hd = urb->context; struct es1_ap_dev *es1 = hd_to_es1(hd); - unsigned long flags; int status = check_urb_status(urb); u8 *data = urb->transfer_buffer + 1; - int i; /* * Tell the submitter that the buffer send (attempt) is @@ -426,23 +447,7 @@ static void cport_out_callback(struct urb *urb) data = urb->transfer_buffer + 1; greybus_data_sent(hd, data, status); - /* - * See if this was an urb in our pool, if so mark it "free", otherwise - * we need to free it ourselves. - */ - spin_lock_irqsave(&es1->cport_out_urb_lock, flags); - for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - if (urb == es1->cport_out_urb[i]) { - es1->cport_out_urb_busy[i] = false; - urb = NULL; - break; - } - } - spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); - - /* If urb is not NULL, then we need to free this urb */ - usb_free_urb(urb); - + free_urb(es1, urb); /* * Rest assured Greg, this craziness is getting fixed. * -- cgit v0.10.2 From 580c47d8b4643730be2aef344562953377239ea3 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Tue, 20 Jan 2015 17:26:18 +0000 Subject: greybus: protocol: dedup protocol find code in protocol register replace the protocol find code with the call to the already existing function. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index b8ae707..12bbc2f 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -20,6 +20,13 @@ static struct gb_protocol *_gb_protocol_find(u8 id, u8 major, u8 minor) { struct gb_protocol *protocol; + /* + * The protocols list is sorted first by protocol id (low to + * high), then by major version (high to low), and finally + * by minor version (high to low). Searching only by + * protocol id will produce the newest implemented version + * of the protocol. + */ list_for_each_entry(protocol, &gb_protocols, links) { if (protocol->id < id) continue; @@ -50,34 +57,12 @@ int __gb_protocol_register(struct gb_protocol *protocol, struct module *module) protocol->owner = module; - /* - * The protocols list is sorted first by protocol id (low to - * high), then by major version (high to low), and finally - * by minor version (high to low). Searching only by - * protocol id will produce the newest implemented version - * of the protocol. - */ spin_lock_irq(&gb_protocols_lock); - list_for_each_entry(existing, &gb_protocols, links) { - if (existing->id < id) - continue; - if (existing->id > id) - break; - - if (existing->major > major) - continue; - if (existing->major < major) - break; - - if (existing->minor > minor) - continue; - if (existing->minor < minor) - break; - - /* A matching protocol has already been registered */ + /* check if the protocol already wos registered */ + existing = _gb_protocol_find(id, major, minor); + if (existing) { spin_unlock_irq(&gb_protocols_lock); - return -EEXIST; } -- cgit v0.10.2 From 2ec515bfff5b13c4efd0d260683b1213f3069ab4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 Jan 2015 09:47:21 +0800 Subject: greybus: es1: no need to assign a variable we return directly In next_free_urb(), just return usb_alloc_urb(), don't waste the time assigning it to a local variable that we then return. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gb-es1.c b/drivers/staging/greybus/gb-es1.c index 96c7c81..2ec5d7b 100644 --- a/drivers/staging/greybus/gb-es1.c +++ b/drivers/staging/greybus/gb-es1.c @@ -179,9 +179,7 @@ static struct urb *next_free_urb(struct es1_ap_dev *es1, gfp_t gfp_mask) */ dev_err(&es1->usb_dev->dev, "No free CPort OUT urbs, having to dynamically allocate one!\n"); - urb = usb_alloc_urb(0, gfp_mask); - - return urb; + return usb_alloc_urb(0, gfp_mask); } static void free_urb(struct es1_ap_dev *es1, struct urb *urb) -- cgit v0.10.2 From f587027e793cf8947c7cc408a2167db2b8218b15 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 Jan 2015 10:24:15 +0800 Subject: greybus: es2: add ES2 Greybus Host driver This is just a copy of ES1 for now, things will start to diverge soon. Any common functionality will be factored out over time. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 5a7c58d..a5d5470 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -22,6 +22,7 @@ obj-m += gb-phy.o obj-m += gb-vibrator.o obj-m += gb-battery.o obj-m += gb-es1.o +obj-m += gb-es2.o KERNELVER ?= $(shell uname -r) KERNELDIR ?= /lib/modules/$(KERNELVER)/build diff --git a/drivers/staging/greybus/gb-es2.c b/drivers/staging/greybus/gb-es2.c new file mode 100644 index 0000000..4154cce --- /dev/null +++ b/drivers/staging/greybus/gb-es2.c @@ -0,0 +1,618 @@ +/* + * Greybus "AP" USB driver for "ES2" controller chips + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ +#include +#include +#include +#include +#include +#include + +#include "greybus.h" +#include "svc_msg.h" +#include "kernel_ver.h" + +/* + * Macros for making pointers explicitly opaque, such that the result + * isn't valid but also can't be mistaken for an ERR_PTR() value. + */ +#define conceal_urb(urb) ((void *)((uintptr_t)(urb) ^ 0xbad)) +#define reveal_urb(cookie) ((void *)((uintptr_t)(cookie) ^ 0xbad)) + +/* Memory sizes for the buffers sent to/from the ES1 controller */ +#define ES1_SVC_MSG_SIZE (sizeof(struct svc_msg) + SZ_64K) +#define ES1_GBUF_MSG_SIZE_MAX PAGE_SIZE + +static const struct usb_device_id id_table[] = { + /* Made up numbers for the SVC USB Bridge in ES1 */ + { USB_DEVICE(0xffff, 0x0001) }, + { }, +}; +MODULE_DEVICE_TABLE(usb, id_table); + +/* + * Number of CPort IN urbs in flight at any point in time. + * Adjust if we are having stalls in the USB buffer due to not enough urbs in + * flight. + */ +#define NUM_CPORT_IN_URB 4 + +/* Number of CPort OUT urbs in flight at any point in time. + * Adjust if we get messages saying we are out of urbs in the system log. + */ +#define NUM_CPORT_OUT_URB 8 + +/** + * es1_ap_dev - ES1 USB Bridge to AP structure + * @usb_dev: pointer to the USB device we are. + * @usb_intf: pointer to the USB interface we are bound to. + * @hd: pointer to our greybus_host_device structure + * @control_endpoint: endpoint to send data to SVC + * @svc_endpoint: endpoint for SVC data in + * @cport_in_endpoint: bulk in endpoint for CPort data + * @cport-out_endpoint: bulk out endpoint for CPort data + * @svc_buffer: buffer for SVC messages coming in on @svc_endpoint + * @svc_urb: urb for SVC messages coming in on @svc_endpoint + * @cport_in_urb: array of urbs for the CPort in messages + * @cport_in_buffer: array of buffers for the @cport_in_urb urbs + * @cport_out_urb: array of urbs for the CPort out messages + * @cport_out_urb_busy: array of flags to see if the @cport_out_urb is busy or + * not. + * @cport_out_urb_lock: locks the @cport_out_urb_busy "list" + */ +struct es1_ap_dev { + struct usb_device *usb_dev; + struct usb_interface *usb_intf; + struct greybus_host_device *hd; + + __u8 control_endpoint; + __u8 svc_endpoint; + __u8 cport_in_endpoint; + __u8 cport_out_endpoint; + + u8 *svc_buffer; + struct urb *svc_urb; + + struct urb *cport_in_urb[NUM_CPORT_IN_URB]; + u8 *cport_in_buffer[NUM_CPORT_IN_URB]; + struct urb *cport_out_urb[NUM_CPORT_OUT_URB]; + bool cport_out_urb_busy[NUM_CPORT_OUT_URB]; + spinlock_t cport_out_urb_lock; +}; + +static inline struct es1_ap_dev *hd_to_es1(struct greybus_host_device *hd) +{ + return (struct es1_ap_dev *)&hd->hd_priv; +} + +static void cport_out_callback(struct urb *urb); + +/* + * Buffer constraints for the host driver. + * + * A "buffer" is used to hold data to be transferred for Greybus by + * the host driver. A buffer is represented by a "buffer pointer", + * which defines a region of memory used by the host driver for + * transferring the data. When Greybus allocates a buffer, it must + * do so subject to the constraints associated with the host driver. + * These constraints are specified by two parameters: the + * headroom; and the maximum buffer size. + * + * +------------------+ + * | Host driver | \ + * | reserved area | }- headroom + * | . . . | / + * buffer pointer ---> +------------------+ + * | Buffer space for | \ + * | transferred data | }- buffer size + * | . . . | / (limited to size_max) + * +------------------+ + * + * headroom: Every buffer must have at least this much space + * *before* the buffer pointer, reserved for use by the + * host driver. I.e., ((char *)buffer - headroom) must + * point to valid memory, usable only by the host driver. + * size_max: The maximum size of a buffer (not including the + * headroom) must not exceed this. + */ +static void hd_buffer_constraints(struct greybus_host_device *hd) +{ + /* + * Only one byte is required, but this produces a result + * that's better aligned for the user. + */ + hd->buffer_headroom = sizeof(u32); /* For cport id */ + hd->buffer_size_max = ES1_GBUF_MSG_SIZE_MAX; + BUILD_BUG_ON(hd->buffer_headroom > GB_BUFFER_HEADROOM_MAX); +} + +#define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ +static int submit_svc(struct svc_msg *svc_msg, struct greybus_host_device *hd) +{ + struct es1_ap_dev *es1 = hd_to_es1(hd); + int retval; + + /* SVC messages go down our control pipe */ + retval = usb_control_msg(es1->usb_dev, + usb_sndctrlpipe(es1->usb_dev, + es1->control_endpoint), + 0x01, /* vendor request AP message */ + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + 0x00, 0x00, + (char *)svc_msg, + sizeof(*svc_msg), + ES1_TIMEOUT); + if (retval != sizeof(*svc_msg)) + return retval; + + return 0; +} + +static struct urb *next_free_urb(struct es1_ap_dev *es1, gfp_t gfp_mask) +{ + struct urb *urb = NULL; + unsigned long flags; + int i; + + spin_lock_irqsave(&es1->cport_out_urb_lock, flags); + + /* Look in our pool of allocated urbs first, as that's the "fastest" */ + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + if (es1->cport_out_urb_busy[i] == false) { + es1->cport_out_urb_busy[i] = true; + urb = es1->cport_out_urb[i]; + break; + } + } + spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); + if (urb) + return urb; + + /* + * Crap, pool is empty, complain to the syslog and go allocate one + * dynamically as we have to succeed. + */ + dev_err(&es1->usb_dev->dev, + "No free CPort OUT urbs, having to dynamically allocate one!\n"); + return usb_alloc_urb(0, gfp_mask); +} + +static void free_urb(struct es1_ap_dev *es1, struct urb *urb) +{ + unsigned long flags; + int i; + /* + * See if this was an urb in our pool, if so mark it "free", otherwise + * we need to free it ourselves. + */ + spin_lock_irqsave(&es1->cport_out_urb_lock, flags); + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + if (urb == es1->cport_out_urb[i]) { + es1->cport_out_urb_busy[i] = false; + urb = NULL; + break; + } + } + spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); + + /* If urb is not NULL, then we need to free this urb */ + usb_free_urb(urb); +} + +/* + * Returns an opaque cookie value if successful, or a pointer coded + * error otherwise. If the caller wishes to cancel the in-flight + * buffer, it must supply the returned cookie to the cancel routine. + */ +static void *buffer_send(struct greybus_host_device *hd, u16 cport_id, + void *buffer, size_t buffer_size, gfp_t gfp_mask) +{ + struct es1_ap_dev *es1 = hd_to_es1(hd); + struct usb_device *udev = es1->usb_dev; + u8 *transfer_buffer = buffer; + int transfer_buffer_size; + int retval; + struct urb *urb; + + if (!buffer) { + pr_err("null buffer supplied to send\n"); + return ERR_PTR(-EINVAL); + } + if (buffer_size > (size_t)INT_MAX) { + pr_err("bad buffer size (%zu) supplied to send\n", buffer_size); + return ERR_PTR(-EINVAL); + } + transfer_buffer--; + transfer_buffer_size = buffer_size + 1; + + /* + * The data actually transferred will include an indication + * of where the data should be sent. Do one last check of + * the target CPort id before filling it in. + */ + if (cport_id == CPORT_ID_BAD) { + pr_err("request to send inbound data buffer\n"); + return ERR_PTR(-EINVAL); + } + if (cport_id > (u16)U8_MAX) { + pr_err("cport_id (%hd) is out of range for ES1\n", cport_id); + return ERR_PTR(-EINVAL); + } + /* OK, the destination is fine; record it in the transfer buffer */ + *transfer_buffer = cport_id; + + /* Find a free urb */ + urb = next_free_urb(es1, gfp_mask); + if (!urb) + return ERR_PTR(-ENOMEM); + + usb_fill_bulk_urb(urb, udev, + usb_sndbulkpipe(udev, es1->cport_out_endpoint), + transfer_buffer, transfer_buffer_size, + cport_out_callback, hd); + retval = usb_submit_urb(urb, gfp_mask); + if (retval) { + pr_err("error %d submitting URB\n", retval); + free_urb(es1, urb); + return ERR_PTR(retval); + } + + return conceal_urb(urb); +} + +/* + * The cookie value supplied is the value that buffer_send() + * returned to its caller. It identifies the buffer that should be + * canceled. This function must also handle (which is to say, + * ignore) a null cookie value. + */ +static void buffer_cancel(void *cookie) +{ + + /* + * We really should be defensive and track all outstanding + * (sent) buffers rather than trusting the cookie provided + * is valid. For the time being, this will do. + */ + if (cookie) + usb_kill_urb(reveal_urb(cookie)); +} + +static struct greybus_host_driver es1_driver = { + .hd_priv_size = sizeof(struct es1_ap_dev), + .buffer_send = buffer_send, + .buffer_cancel = buffer_cancel, + .submit_svc = submit_svc, +}; + +/* Common function to report consistent warnings based on URB status */ +static int check_urb_status(struct urb *urb) +{ + struct device *dev = &urb->dev->dev; + int status = urb->status; + + switch (status) { + case 0: + return 0; + + case -EOVERFLOW: + dev_err(dev, "%s: overflow actual length is %d\n", + __func__, urb->actual_length); + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + case -EILSEQ: + case -EPROTO: + /* device is gone, stop sending */ + return status; + } + dev_err(dev, "%s: unknown status %d\n", __func__, status); + + return -EAGAIN; +} + +static void ap_disconnect(struct usb_interface *interface) +{ + struct es1_ap_dev *es1; + struct usb_device *udev; + int i; + + es1 = usb_get_intfdata(interface); + if (!es1) + return; + + /* Tear down everything! */ + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + struct urb *urb = es1->cport_out_urb[i]; + + if (!urb) + break; + usb_kill_urb(urb); + usb_free_urb(urb); + es1->cport_out_urb[i] = NULL; + es1->cport_out_urb_busy[i] = false; /* just to be anal */ + } + + for (i = 0; i < NUM_CPORT_IN_URB; ++i) { + struct urb *urb = es1->cport_in_urb[i]; + + if (!urb) + break; + usb_kill_urb(urb); + usb_free_urb(urb); + kfree(es1->cport_in_buffer[i]); + es1->cport_in_buffer[i] = NULL; + } + + usb_kill_urb(es1->svc_urb); + usb_free_urb(es1->svc_urb); + es1->svc_urb = NULL; + kfree(es1->svc_buffer); + es1->svc_buffer = NULL; + + usb_set_intfdata(interface, NULL); + udev = es1->usb_dev; + greybus_remove_hd(es1->hd); + + usb_put_dev(udev); +} + +/* Callback for when we get a SVC message */ +static void svc_in_callback(struct urb *urb) +{ + struct greybus_host_device *hd = urb->context; + struct device *dev = &urb->dev->dev; + int status = check_urb_status(urb); + int retval; + + if (status) { + if ((status == -EAGAIN) || (status == -EPROTO)) + goto exit; + dev_err(dev, "urb svc in error %d (dropped)\n", status); + return; + } + + /* We have a message, create a new message structure, add it to the + * list, and wake up our thread that will process the messages. + */ + greybus_svc_in(hd, urb->transfer_buffer, urb->actual_length); + +exit: + /* resubmit the urb to get more messages */ + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) + dev_err(dev, "Can not submit urb for AP data: %d\n", retval); +} + +static void cport_in_callback(struct urb *urb) +{ + struct greybus_host_device *hd = urb->context; + struct device *dev = &urb->dev->dev; + int status = check_urb_status(urb); + int retval; + u16 cport_id; + u8 *data; + + if (status) { + if ((status == -EAGAIN) || (status == -EPROTO)) + goto exit; + dev_err(dev, "urb cport in error %d (dropped)\n", status); + return; + } + + /* The size has to be at least one, for the cport id */ + if (!urb->actual_length) { + dev_err(dev, "%s: no cport id in input buffer?\n", __func__); + goto exit; + } + + /* + * Our CPort number is the first byte of the data stream, + * the rest of the stream is "real" data + */ + data = urb->transfer_buffer; + cport_id = (u16)data[0]; + data = &data[1]; + + /* Pass this data to the greybus core */ + greybus_data_rcvd(hd, cport_id, data, urb->actual_length - 1); + +exit: + /* put our urb back in the request pool */ + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) + dev_err(dev, "%s: error %d in submitting urb.\n", + __func__, retval); +} + +static void cport_out_callback(struct urb *urb) +{ + struct greybus_host_device *hd = urb->context; + struct es1_ap_dev *es1 = hd_to_es1(hd); + int status = check_urb_status(urb); + u8 *data = urb->transfer_buffer + 1; + + /* + * Tell the submitter that the buffer send (attempt) is + * complete, and report the status. The submitter's buffer + * starts after the one-byte CPort id we inserted. + */ + data = urb->transfer_buffer + 1; + greybus_data_sent(hd, data, status); + + free_urb(es1, urb); + /* + * Rest assured Greg, this craziness is getting fixed. + * + * Yes, you are right, we aren't telling anyone that the urb finished. + * "That's crazy! How does this all even work?" you might be saying. + * The "magic" is the idea that greybus works on the "operation" level, + * not the "send a buffer" level. All operations are "round-trip" with + * a response from the device that the operation finished, or it will + * time out. Because of that, we don't care that this urb finished, or + * failed, or did anything else, as higher levels of the protocol stack + * will handle completions and timeouts and the rest. + * + * This protocol is "needed" due to some hardware restrictions on the + * current generation of Unipro controllers. Think about it for a + * minute, this is a USB driver, talking to a Unipro bridge, impedance + * mismatch is huge, yet the Unipro controller are even more + * underpowered than this little USB controller. We rely on the round + * trip to keep stalls in the Unipro controllers from happening so that + * we can keep data flowing properly, no matter how slow it might be. + * + * Once again, a wonderful bus protocol cut down in its prime by a naive + * controller chip. We dream of the day we have a "real" HCD for + * Unipro. Until then, we suck it up and make the hardware work, as + * that's the job of the firmware and kernel. + * + */ +} + +/* + * The ES1 USB Bridge device contains 4 endpoints + * 1 Control - usual USB stuff + AP -> SVC messages + * 1 Interrupt IN - SVC -> AP messages + * 1 Bulk IN - CPort data in + * 1 Bulk OUT - CPort data out + */ +static int ap_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct es1_ap_dev *es1; + struct greybus_host_device *hd; + struct usb_device *udev; + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + bool int_in_found = false; + bool bulk_in_found = false; + bool bulk_out_found = false; + int retval = -ENOMEM; + int i; + u8 svc_interval = 0; + + udev = usb_get_dev(interface_to_usbdev(interface)); + + hd = greybus_create_hd(&es1_driver, &udev->dev); + if (!hd) { + usb_put_dev(udev); + return -ENOMEM; + } + + /* Fill in the buffer allocation constraints */ + hd_buffer_constraints(hd); + + es1 = hd_to_es1(hd); + es1->hd = hd; + es1->usb_intf = interface; + es1->usb_dev = udev; + spin_lock_init(&es1->cport_out_urb_lock); + usb_set_intfdata(interface, es1); + + /* Control endpoint is the pipe to talk to this AP, so save it off */ + endpoint = &udev->ep0.desc; + es1->control_endpoint = endpoint->bEndpointAddress; + + /* find all 3 of our endpoints */ + iface_desc = interface->cur_altsetting; + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i].desc; + + if (usb_endpoint_is_int_in(endpoint)) { + es1->svc_endpoint = endpoint->bEndpointAddress; + svc_interval = endpoint->bInterval; + int_in_found = true; + } else if (usb_endpoint_is_bulk_in(endpoint)) { + es1->cport_in_endpoint = endpoint->bEndpointAddress; + bulk_in_found = true; + } else if (usb_endpoint_is_bulk_out(endpoint)) { + es1->cport_out_endpoint = endpoint->bEndpointAddress; + bulk_out_found = true; + } else { + dev_err(&udev->dev, + "Unknown endpoint type found, address %x\n", + endpoint->bEndpointAddress); + } + } + if ((int_in_found == false) || + (bulk_in_found == false) || + (bulk_out_found == false)) { + dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n"); + goto error; + } + + /* Create our buffer and URB to get SVC messages, and start it up */ + es1->svc_buffer = kmalloc(ES1_SVC_MSG_SIZE, GFP_KERNEL); + if (!es1->svc_buffer) + goto error; + + es1->svc_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!es1->svc_urb) + goto error; + + usb_fill_int_urb(es1->svc_urb, udev, + usb_rcvintpipe(udev, es1->svc_endpoint), + es1->svc_buffer, ES1_SVC_MSG_SIZE, svc_in_callback, + hd, svc_interval); + retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); + if (retval) + goto error; + + /* Allocate buffers for our cport in messages and start them up */ + for (i = 0; i < NUM_CPORT_IN_URB; ++i) { + struct urb *urb; + u8 *buffer; + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) + goto error; + buffer = kmalloc(ES1_GBUF_MSG_SIZE_MAX, GFP_KERNEL); + if (!buffer) + goto error; + + usb_fill_bulk_urb(urb, udev, + usb_rcvbulkpipe(udev, es1->cport_in_endpoint), + buffer, ES1_GBUF_MSG_SIZE_MAX, + cport_in_callback, hd); + es1->cport_in_urb[i] = urb; + es1->cport_in_buffer[i] = buffer; + retval = usb_submit_urb(urb, GFP_KERNEL); + if (retval) + goto error; + } + + /* Allocate urbs for our CPort OUT messages */ + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + struct urb *urb; + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) + goto error; + + es1->cport_out_urb[i] = urb; + es1->cport_out_urb_busy[i] = false; /* just to be anal */ + } + + return 0; +error: + ap_disconnect(interface); + + return retval; +} + +static struct usb_driver es1_ap_driver = { + .name = "es1_ap_driver", + .probe = ap_probe, + .disconnect = ap_disconnect, + .id_table = id_table, +}; + +module_usb_driver(es1_ap_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Greg Kroah-Hartman "); -- cgit v0.10.2 From 5357cf323110ee4a3f4a12870618eca28672c7b9 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 21 Jan 2015 16:10:40 +0530 Subject: greybus: Remove "-gb" suffix from .c files Some files are prefixed with "gb-" and some are suffixed with "-gb". The rationale behind the first one is that the modules would be named so, i.e. gb-*.ko. But there is no reason to keep the "-gb" suffix in the second case. Remove the unnecessary suffix. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index a5d5470..55b4a37 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -10,12 +10,12 @@ greybus-y := core.o \ operation.o gb-phy-y := gpb.o \ - sdio-gb.o \ - uart-gb.o \ - pwm-gb.o \ - gpio-gb.o \ - i2c-gb.o \ - usb-gb.o + sdio.o \ + uart.o \ + pwm.o \ + gpio.o \ + i2c.o \ + usb.o obj-m += greybus.o obj-m += gb-phy.o diff --git a/drivers/staging/greybus/gpio-gb.c b/drivers/staging/greybus/gpio-gb.c deleted file mode 100644 index 4997588..0000000 --- a/drivers/staging/greybus/gpio-gb.c +++ /dev/null @@ -1,544 +0,0 @@ -/* - * GPIO Greybus driver. - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#include -#include -#include -#include -#include "greybus.h" - -struct gb_gpio_line { - /* The following has to be an array of line_max entries */ - /* --> make them just a flags field */ - u8 active: 1, - direction: 1, /* 0 = output, 1 = input */ - value: 1; /* 0 = low, 1 = high */ - u16 debounce_usec; -}; - -struct gb_gpio_controller { - struct gb_connection *connection; - u8 version_major; - u8 version_minor; - u8 line_max; /* max line number */ - struct gb_gpio_line *lines; - - struct gpio_chip chip; -}; -#define gpio_chip_to_gb_gpio_controller(chip) \ - container_of(chip, struct gb_gpio_controller, chip) - -/* Version of the Greybus GPIO protocol we support */ -#define GB_GPIO_VERSION_MAJOR 0x00 -#define GB_GPIO_VERSION_MINOR 0x01 - -/* Greybus GPIO request types */ -#define GB_GPIO_TYPE_INVALID 0x00 -#define GB_GPIO_TYPE_PROTOCOL_VERSION 0x01 -#define GB_GPIO_TYPE_LINE_COUNT 0x02 -#define GB_GPIO_TYPE_ACTIVATE 0x03 -#define GB_GPIO_TYPE_DEACTIVATE 0x04 -#define GB_GPIO_TYPE_GET_DIRECTION 0x05 -#define GB_GPIO_TYPE_DIRECTION_IN 0x06 -#define GB_GPIO_TYPE_DIRECTION_OUT 0x07 -#define GB_GPIO_TYPE_GET_VALUE 0x08 -#define GB_GPIO_TYPE_SET_VALUE 0x09 -#define GB_GPIO_TYPE_SET_DEBOUNCE 0x0a -#define GB_GPIO_TYPE_RESPONSE 0x80 /* OR'd with rest */ - -#define GB_GPIO_DEBOUNCE_USEC_DEFAULT 0 /* microseconds */ - -/* version request has no payload */ -struct gb_gpio_proto_version_response { - __u8 major; - __u8 minor; -}; - -/* line count request has no payload */ -struct gb_gpio_line_count_response { - __u8 count; -}; - -struct gb_gpio_activate_request { - __u8 which; -}; -/* activate response has no payload */ - -struct gb_gpio_deactivate_request { - __u8 which; -}; -/* deactivate response has no payload */ - -struct gb_gpio_get_direction_request { - __u8 which; -}; -struct gb_gpio_get_direction_response { - __u8 direction; -}; - -struct gb_gpio_direction_in_request { - __u8 which; -}; -/* direction in response has no payload */ - -struct gb_gpio_direction_out_request { - __u8 which; - __u8 value; -}; -/* direction out response has no payload */ - -struct gb_gpio_get_value_request { - __u8 which; -}; -struct gb_gpio_get_value_response { - __u8 value; -}; - -struct gb_gpio_set_value_request { - __u8 which; - __u8 value; -}; -/* set value response has no payload */ - -struct gb_gpio_set_debounce_request { - __u8 which; - __le16 usec; -}; -/* debounce response has no payload */ - - -/* - * This request only uses the connection field, and if successful, - * fills in the major and minor protocol version of the target. - */ -static int gb_gpio_proto_version_operation(struct gb_gpio_controller *ggc) -{ - struct gb_gpio_proto_version_response response; - int ret; - - ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_PROTOCOL_VERSION, - NULL, 0, &response, sizeof(response)); - if (ret) - return ret; - - if (response.major > GB_GPIO_VERSION_MAJOR) { - pr_err("unsupported major version (%hhu > %hhu)\n", - response.major, GB_GPIO_VERSION_MAJOR); - return -ENOTSUPP; - } - ggc->version_major = response.major; - ggc->version_minor = response.minor; - return 0; -} - -static int gb_gpio_line_count_operation(struct gb_gpio_controller *ggc) -{ - struct gb_gpio_line_count_response response; - int ret; - - ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_LINE_COUNT, - NULL, 0, &response, sizeof(response)); - if (!ret) - ggc->line_max = response.count; - return ret; -} - -static int gb_gpio_activate_operation(struct gb_gpio_controller *ggc, u8 which) -{ - struct gb_gpio_activate_request request; - int ret; - - if (which > ggc->line_max) - return -EINVAL; - - request.which = which; - ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_ACTIVATE, - &request, sizeof(request), NULL, 0); - if (!ret) - ggc->lines[which].active = true; - return ret; -} - -static int gb_gpio_deactivate_operation(struct gb_gpio_controller *ggc, - u8 which) -{ - struct gb_gpio_deactivate_request request; - int ret; - - if (which > ggc->line_max) - return -EINVAL; - - request.which = which; - ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DEACTIVATE, - &request, sizeof(request), NULL, 0); - if (!ret) - ggc->lines[which].active = false; - return ret; -} - -static int gb_gpio_get_direction_operation(struct gb_gpio_controller *ggc, - u8 which) -{ - struct gb_gpio_get_direction_request request; - struct gb_gpio_get_direction_response response; - int ret; - u8 direction; - - if (which > ggc->line_max) - return -EINVAL; - - request.which = which; - ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_GET_DIRECTION, - &request, sizeof(request), - &response, sizeof(response)); - if (ret) - return ret; - - direction = response.direction; - if (direction && direction != 1) - pr_warn("gpio %u direction was %u (should be 0 or 1)\n", - which, direction); - ggc->lines[which].direction = direction ? 1 : 0; - return 0; -} - -static int gb_gpio_direction_in_operation(struct gb_gpio_controller *ggc, - u8 which) -{ - struct gb_gpio_direction_in_request request; - int ret; - - if (which > ggc->line_max) - return -EINVAL; - - request.which = which; - ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DIRECTION_IN, - &request, sizeof(request), NULL, 0); - if (!ret) - ggc->lines[which].direction = 1; - return ret; -} - -static int gb_gpio_direction_out_operation(struct gb_gpio_controller *ggc, - u8 which, bool value_high) -{ - struct gb_gpio_direction_out_request request; - int ret; - - if (which > ggc->line_max) - return -EINVAL; - - request.which = which; - request.value = value_high ? 1 : 0; - ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DIRECTION_OUT, - &request, sizeof(request), NULL, 0); - if (!ret) - ggc->lines[which].direction = 0; - return ret; -} - -static int gb_gpio_get_value_operation(struct gb_gpio_controller *ggc, - u8 which) -{ - struct gb_gpio_get_value_request request; - struct gb_gpio_get_value_response response; - int ret; - u8 value; - - if (which > ggc->line_max) - return -EINVAL; - - request.which = which; - ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_GET_VALUE, - &request, sizeof(request), - &response, sizeof(response)); - if (ret) - return ret; - - value = response.value; - if (value && value != 1) - pr_warn("gpio %u value was %u (should be 0 or 1)\n", - which, value); - ggc->lines[which].value = value ? 1 : 0; - return 0; -} - -static int gb_gpio_set_value_operation(struct gb_gpio_controller *ggc, - u8 which, bool value_high) -{ - struct gb_gpio_set_value_request request; - int ret; - - if (which > ggc->line_max) - return -EINVAL; - - request.which = which; - request.value = value_high ? 1 : 0; - ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_SET_VALUE, - &request, sizeof(request), NULL, 0); - if (!ret) { - /* XXX should this set direction to out? */ - ggc->lines[which].value = request.value; - } - return ret; -} - -static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *ggc, - u8 which, u16 debounce_usec) -{ - struct gb_gpio_set_debounce_request request; - int ret; - - if (which > ggc->line_max) - return -EINVAL; - - request.which = which; - request.usec = cpu_to_le16(debounce_usec); - ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_SET_DEBOUNCE, - &request, sizeof(request), NULL, 0); - if (!ret) - ggc->lines[which].debounce_usec = debounce_usec; - return ret; -} - -static int gb_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); - int ret; - - if (offset >= chip->ngpio) - return -EINVAL; - ret = gb_gpio_activate_operation(gb_gpio_controller, (u8)offset); - if (ret) - ; /* return ret; */ - return 0; -} - -static void gb_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); - int ret; - - if (offset >= chip->ngpio) { - pr_err("bad offset %u supplied (must be 0..%u)\n", - offset, chip->ngpio - 1); - return; - } - ret = gb_gpio_deactivate_operation(gb_gpio_controller, (u8)offset); - if (ret) - ; /* return ret; */ -} - -static int gb_gpio_get_direction(struct gpio_chip *chip, unsigned offset) -{ - struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); - u8 which; - int ret; - - if (offset >= chip->ngpio) - return -EINVAL; - which = (u8)offset; - ret = gb_gpio_get_direction_operation(gb_gpio_controller, which); - if (ret) - ; /* return ret; */ - return gb_gpio_controller->lines[which].direction ? 1 : 0; -} - -static int gb_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -{ - struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); - int ret; - - if (offset >= chip->ngpio) - return -EINVAL; - ret = gb_gpio_direction_in_operation(gb_gpio_controller, (u8)offset); - if (ret) - ; /* return ret; */ - return 0; -} - -static int gb_gpio_direction_output(struct gpio_chip *chip, unsigned offset, - int value) -{ - struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); - int ret; - - if (offset >= chip->ngpio) - return -EINVAL; - ret = gb_gpio_direction_out_operation(gb_gpio_controller, (u8)offset, !!value); - if (ret) - ; /* return ret; */ - return 0; -} - -static int gb_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); - u8 which; - int ret; - - if (offset >= chip->ngpio) - return -EINVAL; - which = (u8)offset; - ret = gb_gpio_get_value_operation(gb_gpio_controller, which); - if (ret) - return ret; - return (int)gb_gpio_controller->lines[which].value; -} - -static void gb_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); - int ret; - - if (offset < 0 || offset >= chip->ngpio) { - pr_err("bad offset %u supplied (must be 0..%u)\n", - offset, chip->ngpio - 1); - return; - } - ret = gb_gpio_set_value_operation(gb_gpio_controller, (u8)offset, !!value); - if (ret) - ; /* return ret; */ -} - -static int gb_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, - unsigned debounce) -{ - struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); - u16 usec; - int ret; - - if (offset >= chip->ngpio) - return -EINVAL; - if (debounce > (unsigned int)U16_MAX) - return -EINVAL; - usec = (u8)debounce; - ret = gb_gpio_set_debounce_operation(gb_gpio_controller, (u8)offset, usec); - if (ret) - ; /* return ret; */ - - return 0; /* XXX */ -} - -static int gb_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ - if (offset >= chip->ngpio) - return -EINVAL; - - return 0; /* XXX */ -} - -static void gb_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) -{ - return; /* XXX */ -} - -static int gb_gpio_controller_setup(struct gb_gpio_controller *gb_gpio_controller) -{ - u32 line_count; - size_t size; - int ret; - - /* First thing we need to do is check the version */ - ret = gb_gpio_proto_version_operation(gb_gpio_controller); - if (ret) - ; /* return ret; */ - - /* Now find out how many lines there are */ - ret = gb_gpio_line_count_operation(gb_gpio_controller); - if (ret) - ; /* return ret; */ - line_count = (u32)gb_gpio_controller->line_max + 1; - size = line_count * sizeof(*gb_gpio_controller->lines); - gb_gpio_controller->lines = kzalloc(size, GFP_KERNEL); - if (!gb_gpio_controller->lines) - return -ENOMEM; - - return ret; -} - -static int gb_gpio_connection_init(struct gb_connection *connection) -{ - struct gb_gpio_controller *gb_gpio_controller; - struct gpio_chip *gpio; - int ret; - - gb_gpio_controller = kzalloc(sizeof(*gb_gpio_controller), GFP_KERNEL); - if (!gb_gpio_controller) - return -ENOMEM; - gb_gpio_controller->connection = connection; - connection->private = gb_gpio_controller; - - ret = gb_gpio_controller_setup(gb_gpio_controller); - if (ret) - goto out_err; - - gpio = &gb_gpio_controller->chip; - - gpio->label = "greybus_gpio"; - gpio->owner = THIS_MODULE; /* XXX Module get? */ - - gpio->request = gb_gpio_request; - gpio->free = gb_gpio_free; - gpio->get_direction = gb_gpio_get_direction; - gpio->direction_input = gb_gpio_direction_input; - gpio->direction_output = gb_gpio_direction_output; - gpio->get = gb_gpio_get; - gpio->set = gb_gpio_set; - gpio->set_debounce = gb_gpio_set_debounce; - gpio->to_irq = gb_gpio_to_irq; - gpio->dbg_show = gb_gpio_dbg_show; - - gpio->base = -1; /* Allocate base dynamically */ - gpio->ngpio = gb_gpio_controller->line_max + 1; - gpio->can_sleep = true; /* XXX */ - - ret = gpiochip_add(gpio); - if (ret) { - pr_err("Failed to register GPIO\n"); - return ret; - } - - return 0; -out_err: - kfree(gb_gpio_controller); - return ret; -} - -static void gb_gpio_connection_exit(struct gb_connection *connection) -{ - struct gb_gpio_controller *gb_gpio_controller = connection->private; - - if (!gb_gpio_controller) - return; - - gb_gpiochip_remove(&gb_gpio_controller->chip); - /* kref_put(gb_gpio_controller->connection) */ - kfree(gb_gpio_controller); -} - -static struct gb_protocol gpio_protocol = { - .name = "gpio", - .id = GREYBUS_PROTOCOL_GPIO, - .major = 0, - .minor = 1, - .connection_init = gb_gpio_connection_init, - .connection_exit = gb_gpio_connection_exit, - .request_recv = NULL, /* no incoming requests */ -}; - -int gb_gpio_protocol_init(void) -{ - return gb_protocol_register(&gpio_protocol); -} - -void gb_gpio_protocol_exit(void) -{ - gb_protocol_deregister(&gpio_protocol); -} diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c new file mode 100644 index 0000000..4997588 --- /dev/null +++ b/drivers/staging/greybus/gpio.c @@ -0,0 +1,544 @@ +/* + * GPIO Greybus driver. + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include "greybus.h" + +struct gb_gpio_line { + /* The following has to be an array of line_max entries */ + /* --> make them just a flags field */ + u8 active: 1, + direction: 1, /* 0 = output, 1 = input */ + value: 1; /* 0 = low, 1 = high */ + u16 debounce_usec; +}; + +struct gb_gpio_controller { + struct gb_connection *connection; + u8 version_major; + u8 version_minor; + u8 line_max; /* max line number */ + struct gb_gpio_line *lines; + + struct gpio_chip chip; +}; +#define gpio_chip_to_gb_gpio_controller(chip) \ + container_of(chip, struct gb_gpio_controller, chip) + +/* Version of the Greybus GPIO protocol we support */ +#define GB_GPIO_VERSION_MAJOR 0x00 +#define GB_GPIO_VERSION_MINOR 0x01 + +/* Greybus GPIO request types */ +#define GB_GPIO_TYPE_INVALID 0x00 +#define GB_GPIO_TYPE_PROTOCOL_VERSION 0x01 +#define GB_GPIO_TYPE_LINE_COUNT 0x02 +#define GB_GPIO_TYPE_ACTIVATE 0x03 +#define GB_GPIO_TYPE_DEACTIVATE 0x04 +#define GB_GPIO_TYPE_GET_DIRECTION 0x05 +#define GB_GPIO_TYPE_DIRECTION_IN 0x06 +#define GB_GPIO_TYPE_DIRECTION_OUT 0x07 +#define GB_GPIO_TYPE_GET_VALUE 0x08 +#define GB_GPIO_TYPE_SET_VALUE 0x09 +#define GB_GPIO_TYPE_SET_DEBOUNCE 0x0a +#define GB_GPIO_TYPE_RESPONSE 0x80 /* OR'd with rest */ + +#define GB_GPIO_DEBOUNCE_USEC_DEFAULT 0 /* microseconds */ + +/* version request has no payload */ +struct gb_gpio_proto_version_response { + __u8 major; + __u8 minor; +}; + +/* line count request has no payload */ +struct gb_gpio_line_count_response { + __u8 count; +}; + +struct gb_gpio_activate_request { + __u8 which; +}; +/* activate response has no payload */ + +struct gb_gpio_deactivate_request { + __u8 which; +}; +/* deactivate response has no payload */ + +struct gb_gpio_get_direction_request { + __u8 which; +}; +struct gb_gpio_get_direction_response { + __u8 direction; +}; + +struct gb_gpio_direction_in_request { + __u8 which; +}; +/* direction in response has no payload */ + +struct gb_gpio_direction_out_request { + __u8 which; + __u8 value; +}; +/* direction out response has no payload */ + +struct gb_gpio_get_value_request { + __u8 which; +}; +struct gb_gpio_get_value_response { + __u8 value; +}; + +struct gb_gpio_set_value_request { + __u8 which; + __u8 value; +}; +/* set value response has no payload */ + +struct gb_gpio_set_debounce_request { + __u8 which; + __le16 usec; +}; +/* debounce response has no payload */ + + +/* + * This request only uses the connection field, and if successful, + * fills in the major and minor protocol version of the target. + */ +static int gb_gpio_proto_version_operation(struct gb_gpio_controller *ggc) +{ + struct gb_gpio_proto_version_response response; + int ret; + + ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_PROTOCOL_VERSION, + NULL, 0, &response, sizeof(response)); + if (ret) + return ret; + + if (response.major > GB_GPIO_VERSION_MAJOR) { + pr_err("unsupported major version (%hhu > %hhu)\n", + response.major, GB_GPIO_VERSION_MAJOR); + return -ENOTSUPP; + } + ggc->version_major = response.major; + ggc->version_minor = response.minor; + return 0; +} + +static int gb_gpio_line_count_operation(struct gb_gpio_controller *ggc) +{ + struct gb_gpio_line_count_response response; + int ret; + + ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_LINE_COUNT, + NULL, 0, &response, sizeof(response)); + if (!ret) + ggc->line_max = response.count; + return ret; +} + +static int gb_gpio_activate_operation(struct gb_gpio_controller *ggc, u8 which) +{ + struct gb_gpio_activate_request request; + int ret; + + if (which > ggc->line_max) + return -EINVAL; + + request.which = which; + ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_ACTIVATE, + &request, sizeof(request), NULL, 0); + if (!ret) + ggc->lines[which].active = true; + return ret; +} + +static int gb_gpio_deactivate_operation(struct gb_gpio_controller *ggc, + u8 which) +{ + struct gb_gpio_deactivate_request request; + int ret; + + if (which > ggc->line_max) + return -EINVAL; + + request.which = which; + ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DEACTIVATE, + &request, sizeof(request), NULL, 0); + if (!ret) + ggc->lines[which].active = false; + return ret; +} + +static int gb_gpio_get_direction_operation(struct gb_gpio_controller *ggc, + u8 which) +{ + struct gb_gpio_get_direction_request request; + struct gb_gpio_get_direction_response response; + int ret; + u8 direction; + + if (which > ggc->line_max) + return -EINVAL; + + request.which = which; + ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_GET_DIRECTION, + &request, sizeof(request), + &response, sizeof(response)); + if (ret) + return ret; + + direction = response.direction; + if (direction && direction != 1) + pr_warn("gpio %u direction was %u (should be 0 or 1)\n", + which, direction); + ggc->lines[which].direction = direction ? 1 : 0; + return 0; +} + +static int gb_gpio_direction_in_operation(struct gb_gpio_controller *ggc, + u8 which) +{ + struct gb_gpio_direction_in_request request; + int ret; + + if (which > ggc->line_max) + return -EINVAL; + + request.which = which; + ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DIRECTION_IN, + &request, sizeof(request), NULL, 0); + if (!ret) + ggc->lines[which].direction = 1; + return ret; +} + +static int gb_gpio_direction_out_operation(struct gb_gpio_controller *ggc, + u8 which, bool value_high) +{ + struct gb_gpio_direction_out_request request; + int ret; + + if (which > ggc->line_max) + return -EINVAL; + + request.which = which; + request.value = value_high ? 1 : 0; + ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DIRECTION_OUT, + &request, sizeof(request), NULL, 0); + if (!ret) + ggc->lines[which].direction = 0; + return ret; +} + +static int gb_gpio_get_value_operation(struct gb_gpio_controller *ggc, + u8 which) +{ + struct gb_gpio_get_value_request request; + struct gb_gpio_get_value_response response; + int ret; + u8 value; + + if (which > ggc->line_max) + return -EINVAL; + + request.which = which; + ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_GET_VALUE, + &request, sizeof(request), + &response, sizeof(response)); + if (ret) + return ret; + + value = response.value; + if (value && value != 1) + pr_warn("gpio %u value was %u (should be 0 or 1)\n", + which, value); + ggc->lines[which].value = value ? 1 : 0; + return 0; +} + +static int gb_gpio_set_value_operation(struct gb_gpio_controller *ggc, + u8 which, bool value_high) +{ + struct gb_gpio_set_value_request request; + int ret; + + if (which > ggc->line_max) + return -EINVAL; + + request.which = which; + request.value = value_high ? 1 : 0; + ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_SET_VALUE, + &request, sizeof(request), NULL, 0); + if (!ret) { + /* XXX should this set direction to out? */ + ggc->lines[which].value = request.value; + } + return ret; +} + +static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *ggc, + u8 which, u16 debounce_usec) +{ + struct gb_gpio_set_debounce_request request; + int ret; + + if (which > ggc->line_max) + return -EINVAL; + + request.which = which; + request.usec = cpu_to_le16(debounce_usec); + ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_SET_DEBOUNCE, + &request, sizeof(request), NULL, 0); + if (!ret) + ggc->lines[which].debounce_usec = debounce_usec; + return ret; +} + +static int gb_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); + int ret; + + if (offset >= chip->ngpio) + return -EINVAL; + ret = gb_gpio_activate_operation(gb_gpio_controller, (u8)offset); + if (ret) + ; /* return ret; */ + return 0; +} + +static void gb_gpio_free(struct gpio_chip *chip, unsigned offset) +{ + struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); + int ret; + + if (offset >= chip->ngpio) { + pr_err("bad offset %u supplied (must be 0..%u)\n", + offset, chip->ngpio - 1); + return; + } + ret = gb_gpio_deactivate_operation(gb_gpio_controller, (u8)offset); + if (ret) + ; /* return ret; */ +} + +static int gb_gpio_get_direction(struct gpio_chip *chip, unsigned offset) +{ + struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); + u8 which; + int ret; + + if (offset >= chip->ngpio) + return -EINVAL; + which = (u8)offset; + ret = gb_gpio_get_direction_operation(gb_gpio_controller, which); + if (ret) + ; /* return ret; */ + return gb_gpio_controller->lines[which].direction ? 1 : 0; +} + +static int gb_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); + int ret; + + if (offset >= chip->ngpio) + return -EINVAL; + ret = gb_gpio_direction_in_operation(gb_gpio_controller, (u8)offset); + if (ret) + ; /* return ret; */ + return 0; +} + +static int gb_gpio_direction_output(struct gpio_chip *chip, unsigned offset, + int value) +{ + struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); + int ret; + + if (offset >= chip->ngpio) + return -EINVAL; + ret = gb_gpio_direction_out_operation(gb_gpio_controller, (u8)offset, !!value); + if (ret) + ; /* return ret; */ + return 0; +} + +static int gb_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); + u8 which; + int ret; + + if (offset >= chip->ngpio) + return -EINVAL; + which = (u8)offset; + ret = gb_gpio_get_value_operation(gb_gpio_controller, which); + if (ret) + return ret; + return (int)gb_gpio_controller->lines[which].value; +} + +static void gb_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); + int ret; + + if (offset < 0 || offset >= chip->ngpio) { + pr_err("bad offset %u supplied (must be 0..%u)\n", + offset, chip->ngpio - 1); + return; + } + ret = gb_gpio_set_value_operation(gb_gpio_controller, (u8)offset, !!value); + if (ret) + ; /* return ret; */ +} + +static int gb_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, + unsigned debounce) +{ + struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); + u16 usec; + int ret; + + if (offset >= chip->ngpio) + return -EINVAL; + if (debounce > (unsigned int)U16_MAX) + return -EINVAL; + usec = (u8)debounce; + ret = gb_gpio_set_debounce_operation(gb_gpio_controller, (u8)offset, usec); + if (ret) + ; /* return ret; */ + + return 0; /* XXX */ +} + +static int gb_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +{ + if (offset >= chip->ngpio) + return -EINVAL; + + return 0; /* XXX */ +} + +static void gb_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) +{ + return; /* XXX */ +} + +static int gb_gpio_controller_setup(struct gb_gpio_controller *gb_gpio_controller) +{ + u32 line_count; + size_t size; + int ret; + + /* First thing we need to do is check the version */ + ret = gb_gpio_proto_version_operation(gb_gpio_controller); + if (ret) + ; /* return ret; */ + + /* Now find out how many lines there are */ + ret = gb_gpio_line_count_operation(gb_gpio_controller); + if (ret) + ; /* return ret; */ + line_count = (u32)gb_gpio_controller->line_max + 1; + size = line_count * sizeof(*gb_gpio_controller->lines); + gb_gpio_controller->lines = kzalloc(size, GFP_KERNEL); + if (!gb_gpio_controller->lines) + return -ENOMEM; + + return ret; +} + +static int gb_gpio_connection_init(struct gb_connection *connection) +{ + struct gb_gpio_controller *gb_gpio_controller; + struct gpio_chip *gpio; + int ret; + + gb_gpio_controller = kzalloc(sizeof(*gb_gpio_controller), GFP_KERNEL); + if (!gb_gpio_controller) + return -ENOMEM; + gb_gpio_controller->connection = connection; + connection->private = gb_gpio_controller; + + ret = gb_gpio_controller_setup(gb_gpio_controller); + if (ret) + goto out_err; + + gpio = &gb_gpio_controller->chip; + + gpio->label = "greybus_gpio"; + gpio->owner = THIS_MODULE; /* XXX Module get? */ + + gpio->request = gb_gpio_request; + gpio->free = gb_gpio_free; + gpio->get_direction = gb_gpio_get_direction; + gpio->direction_input = gb_gpio_direction_input; + gpio->direction_output = gb_gpio_direction_output; + gpio->get = gb_gpio_get; + gpio->set = gb_gpio_set; + gpio->set_debounce = gb_gpio_set_debounce; + gpio->to_irq = gb_gpio_to_irq; + gpio->dbg_show = gb_gpio_dbg_show; + + gpio->base = -1; /* Allocate base dynamically */ + gpio->ngpio = gb_gpio_controller->line_max + 1; + gpio->can_sleep = true; /* XXX */ + + ret = gpiochip_add(gpio); + if (ret) { + pr_err("Failed to register GPIO\n"); + return ret; + } + + return 0; +out_err: + kfree(gb_gpio_controller); + return ret; +} + +static void gb_gpio_connection_exit(struct gb_connection *connection) +{ + struct gb_gpio_controller *gb_gpio_controller = connection->private; + + if (!gb_gpio_controller) + return; + + gb_gpiochip_remove(&gb_gpio_controller->chip); + /* kref_put(gb_gpio_controller->connection) */ + kfree(gb_gpio_controller); +} + +static struct gb_protocol gpio_protocol = { + .name = "gpio", + .id = GREYBUS_PROTOCOL_GPIO, + .major = 0, + .minor = 1, + .connection_init = gb_gpio_connection_init, + .connection_exit = gb_gpio_connection_exit, + .request_recv = NULL, /* no incoming requests */ +}; + +int gb_gpio_protocol_init(void) +{ + return gb_protocol_register(&gpio_protocol); +} + +void gb_gpio_protocol_exit(void) +{ + gb_protocol_deregister(&gpio_protocol); +} diff --git a/drivers/staging/greybus/i2c-gb.c b/drivers/staging/greybus/i2c-gb.c deleted file mode 100644 index c967ae3..0000000 --- a/drivers/staging/greybus/i2c-gb.c +++ /dev/null @@ -1,450 +0,0 @@ -/* - * I2C bridge driver for the Greybus "generic" I2C module. - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#include -#include -#include -#include - -#include "greybus.h" - -struct gb_i2c_device { - struct gb_connection *connection; - u8 version_major; - u8 version_minor; - - u32 functionality; - u16 timeout_msec; - u8 retries; - - struct i2c_adapter adapter; -}; - -/* Version of the Greybus i2c protocol we support */ -#define GB_I2C_VERSION_MAJOR 0x00 -#define GB_I2C_VERSION_MINOR 0x01 - -/* Greybus i2c request types */ -#define GB_I2C_TYPE_INVALID 0x00 -#define GB_I2C_TYPE_PROTOCOL_VERSION 0x01 -#define GB_I2C_TYPE_FUNCTIONALITY 0x02 -#define GB_I2C_TYPE_TIMEOUT 0x03 -#define GB_I2C_TYPE_RETRIES 0x04 -#define GB_I2C_TYPE_TRANSFER 0x05 -#define GB_I2C_TYPE_RESPONSE 0x80 /* OR'd with rest */ - -#define GB_I2C_RETRIES_DEFAULT 3 -#define GB_I2C_TIMEOUT_DEFAULT 1000 /* milliseconds */ - -/* version request has no payload */ -struct gb_i2c_proto_version_response { - __u8 major; - __u8 minor; -}; - -/* functionality request has no payload */ -struct gb_i2c_functionality_response { - __le32 functionality; -}; - -struct gb_i2c_timeout_request { - __le16 msec; -}; -/* timeout response has no payload */ - -struct gb_i2c_retries_request { - __u8 retries; -}; -/* retries response has no payload */ - -/* - * Outgoing data immediately follows the op count and ops array. - * The data for each write (master -> slave) op in the array is sent - * in order, with no (e.g. pad) bytes separating them. - * - * Short reads cause the entire transfer request to fail So response - * payload consists only of bytes read, and the number of bytes is - * exactly what was specified in the corresponding op. Like - * outgoing data, the incoming data is in order and contiguous. - */ -struct gb_i2c_transfer_op { - __le16 addr; - __le16 flags; - __le16 size; -}; - -struct gb_i2c_transfer_request { - __le16 op_count; - struct gb_i2c_transfer_op ops[0]; /* op_count of these */ -}; -struct gb_i2c_transfer_response { - __u8 data[0]; /* inbound data */ -}; - -/* - * This request only uses the connection field, and if successful, - * fills in the major and minor protocol version of the target. - */ -static int gb_i2c_proto_version_operation(struct gb_i2c_device *gb_i2c_dev) -{ - struct gb_i2c_proto_version_response response; - int ret; - - ret = gb_operation_sync(gb_i2c_dev->connection, - GB_I2C_TYPE_PROTOCOL_VERSION, - NULL, 0, &response, sizeof(response)); - if (ret) - return ret; - - if (response.major > GB_I2C_VERSION_MAJOR) { - pr_err("unsupported major version (%hhu > %hhu)\n", - response.major, GB_I2C_VERSION_MAJOR); - return -ENOTSUPP; - } - gb_i2c_dev->version_major = response.major; - gb_i2c_dev->version_minor = response.minor; - return 0; -} - -/* - * Map Greybus i2c functionality bits into Linux ones - */ -static u32 gb_i2c_functionality_map(u32 gb_i2c_functionality) -{ - return gb_i2c_functionality; /* All bits the same for now */ -} - -static int gb_i2c_functionality_operation(struct gb_i2c_device *gb_i2c_dev) -{ - struct gb_i2c_functionality_response response; - u32 functionality; - int ret; - - ret = gb_operation_sync(gb_i2c_dev->connection, - GB_I2C_TYPE_FUNCTIONALITY, - NULL, 0, &response, sizeof(response)); - if (ret) - return ret; - - functionality = le32_to_cpu(response.functionality); - gb_i2c_dev->functionality = gb_i2c_functionality_map(functionality); - - return 0; -} - -static int gb_i2c_timeout_operation(struct gb_i2c_device *gb_i2c_dev, u16 msec) -{ - struct gb_i2c_timeout_request request; - int ret; - - request.msec = cpu_to_le16(msec); - ret = gb_operation_sync(gb_i2c_dev->connection, GB_I2C_TYPE_TIMEOUT, - &request, sizeof(request), NULL, 0); - if (ret) - pr_err("timeout operation failed (%d)\n", ret); - else - gb_i2c_dev->timeout_msec = msec; - - return ret; -} - -static int gb_i2c_retries_operation(struct gb_i2c_device *gb_i2c_dev, - u8 retries) -{ - struct gb_i2c_retries_request request; - int ret; - - request.retries = retries; - ret = gb_operation_sync(gb_i2c_dev->connection, GB_I2C_TYPE_RETRIES, - &request, sizeof(request), NULL, 0); - if (ret) - pr_err("retries operation failed (%d)\n", ret); - else - gb_i2c_dev->retries = retries; - - return ret; -} - - -/* - * Map Linux i2c_msg flags into Greybus i2c transfer op flags. - */ -static u16 gb_i2c_transfer_op_flags_map(u16 flags) -{ - return flags; /* All flags the same for now */ -} - -static void -gb_i2c_fill_transfer_op(struct gb_i2c_transfer_op *op, struct i2c_msg *msg) -{ - u16 flags = gb_i2c_transfer_op_flags_map(msg->flags); - - op->addr = cpu_to_le16(msg->addr); - op->flags = cpu_to_le16(flags); - op->size = cpu_to_le16(msg->len); -} - -static struct gb_operation * -gb_i2c_transfer_request(struct gb_connection *connection, - struct i2c_msg *msgs, u32 msg_count) -{ - struct gb_i2c_transfer_request *request; - struct gb_operation *operation; - struct gb_i2c_transfer_op *op; - struct i2c_msg *msg; - u32 data_out_size = 0; - u32 data_in_size = 0; - size_t request_size; - void *data; - u16 op_count; - u32 i; - - if (msg_count > (u32)U16_MAX) { - gb_connection_err(connection, "msg_count (%u) too big", - msg_count); - return NULL; - } - op_count = (u16)msg_count; - - /* - * In addition to space for all message descriptors we need - * to have enough to hold all outbound message data. - */ - msg = msgs; - for (i = 0; i < msg_count; i++, msg++) - if (msg->flags & I2C_M_RD) - data_in_size += (u32)msg->len; - else - data_out_size += (u32)msg->len; - - request_size = sizeof(*request); - request_size += msg_count * sizeof(*op); - request_size += data_out_size; - - /* Response consists only of incoming data */ - operation = gb_operation_create(connection, GB_I2C_TYPE_TRANSFER, - request_size, data_in_size); - if (!operation) - return NULL; - - request = operation->request->payload; - request->op_count = cpu_to_le16(op_count); - /* Fill in the ops array */ - op = &request->ops[0]; - msg = msgs; - for (i = 0; i < msg_count; i++) - gb_i2c_fill_transfer_op(op++, msg++); - - if (!data_out_size) - return operation; - - /* Copy over the outgoing data; it starts after the last op */ - data = op; - msg = msgs; - for (i = 0; i < msg_count; i++) { - if (!(msg->flags & I2C_M_RD)) { - memcpy(data, msg->buf, msg->len); - data += msg->len; - } - msg++; - } - - return operation; -} - -static void gb_i2c_transfer_response(struct i2c_msg *msgs, u32 msg_count, - struct gb_i2c_transfer_response *response) -{ - struct i2c_msg *msg = msgs; - u8 *data; - u32 i; - - if (!response) - return; - data = response->data; - for (i = 0; i < msg_count; i++) { - if (msg->flags & I2C_M_RD) { - memcpy(msg->buf, data, msg->len); - data += msg->len; - } - msg++; - } -} - -/* - * Some i2c transfer operations return results that are expected. - */ -static bool gb_i2c_expected_transfer_error(int errno) -{ - return errno == -EAGAIN || errno == -ENODEV; -} - -static int gb_i2c_transfer_operation(struct gb_i2c_device *gb_i2c_dev, - struct i2c_msg *msgs, u32 msg_count) -{ - struct gb_connection *connection = gb_i2c_dev->connection; - struct gb_operation *operation; - int ret; - - operation = gb_i2c_transfer_request(connection, msgs, msg_count); - if (!operation) - return -ENOMEM; - - ret = gb_operation_request_send_sync(operation); - if (!ret) { - struct gb_i2c_transfer_response *response; - - response = operation->response->payload; - gb_i2c_transfer_response(msgs, msg_count, response); - ret = msg_count; - } else if (!gb_i2c_expected_transfer_error(ret)) { - pr_err("transfer operation failed (%d)\n", ret); - } - gb_operation_destroy(operation); - - return ret; -} - -static int gb_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, - int msg_count) -{ - struct gb_i2c_device *gb_i2c_dev; - - gb_i2c_dev = i2c_get_adapdata(adap); - - return gb_i2c_transfer_operation(gb_i2c_dev, msgs, msg_count); -} - -#if 0 -/* Later */ -static int gb_i2c_smbus_xfer(struct i2c_adapter *adap, - u16 addr, unsigned short flags, char read_write, - u8 command, int size, union i2c_smbus_data *data) -{ - struct gb_i2c_device *gb_i2c_dev; - - gb_i2c_dev = i2c_get_adapdata(adap); - - return 0; -} -#endif - -static u32 gb_i2c_functionality(struct i2c_adapter *adap) -{ - struct gb_i2c_device *gb_i2c_dev = i2c_get_adapdata(adap); - - return gb_i2c_dev->functionality; -} - -static const struct i2c_algorithm gb_i2c_algorithm = { - .master_xfer = gb_i2c_master_xfer, - /* .smbus_xfer = gb_i2c_smbus_xfer, */ - .functionality = gb_i2c_functionality, -}; - -/* - * Do initial setup of the i2c device. This includes verifying we - * can support it (based on the protocol version it advertises). - * If that's OK, we get and cached its functionality bits, and - * set up the retry count and timeout. - * - * Note: gb_i2c_dev->connection is assumed to have been valid. - */ -static int gb_i2c_device_setup(struct gb_i2c_device *gb_i2c_dev) -{ - int ret; - - /* First thing we need to do is check the version */ - ret = gb_i2c_proto_version_operation(gb_i2c_dev); - if (ret) - return ret; - - /* Assume the functionality never changes, just get it once */ - ret = gb_i2c_functionality_operation(gb_i2c_dev); - if (ret) - return ret; - - /* Set up our default retry count and timeout */ - ret = gb_i2c_retries_operation(gb_i2c_dev, GB_I2C_RETRIES_DEFAULT); - if (ret) - return ret; - - return gb_i2c_timeout_operation(gb_i2c_dev, GB_I2C_TIMEOUT_DEFAULT); -} - -static int gb_i2c_connection_init(struct gb_connection *connection) -{ - struct gb_i2c_device *gb_i2c_dev; - struct i2c_adapter *adapter; - int ret; - - gb_i2c_dev = kzalloc(sizeof(*gb_i2c_dev), GFP_KERNEL); - if (!gb_i2c_dev) - return -ENOMEM; - - gb_i2c_dev->connection = connection; /* refcount? */ - connection->private = gb_i2c_dev; - - ret = gb_i2c_device_setup(gb_i2c_dev); - if (ret) - goto out_err; - - /* Looks good; up our i2c adapter */ - adapter = &gb_i2c_dev->adapter; - adapter->owner = THIS_MODULE; - adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - adapter->algo = &gb_i2c_algorithm; - /* adapter->algo_data = what? */ - adapter->timeout = gb_i2c_dev->timeout_msec * HZ / 1000; - adapter->retries = gb_i2c_dev->retries; - - adapter->dev.parent = &connection->dev; - snprintf(adapter->name, sizeof(adapter->name), "Greybus i2c adapter"); - i2c_set_adapdata(adapter, gb_i2c_dev); - - ret = i2c_add_adapter(adapter); - if (ret) - goto out_err; - - return 0; -out_err: - /* kref_put(gb_i2c_dev->connection) */ - kfree(gb_i2c_dev); - - return ret; -} - -static void gb_i2c_connection_exit(struct gb_connection *connection) -{ - struct gb_i2c_device *gb_i2c_dev = connection->private; - - i2c_del_adapter(&gb_i2c_dev->adapter); - /* kref_put(gb_i2c_dev->connection) */ - kfree(gb_i2c_dev); -} - -static struct gb_protocol i2c_protocol = { - .name = "i2c", - .id = GREYBUS_PROTOCOL_I2C, - .major = 0, - .minor = 1, - .connection_init = gb_i2c_connection_init, - .connection_exit = gb_i2c_connection_exit, - .request_recv = NULL, /* no incoming requests */ -}; - -int gb_i2c_protocol_init(void) -{ - return gb_protocol_register(&i2c_protocol); -} - -void gb_i2c_protocol_exit(void) -{ - gb_protocol_deregister(&i2c_protocol); -} diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c new file mode 100644 index 0000000..c967ae3 --- /dev/null +++ b/drivers/staging/greybus/i2c.c @@ -0,0 +1,450 @@ +/* + * I2C bridge driver for the Greybus "generic" I2C module. + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include + +#include "greybus.h" + +struct gb_i2c_device { + struct gb_connection *connection; + u8 version_major; + u8 version_minor; + + u32 functionality; + u16 timeout_msec; + u8 retries; + + struct i2c_adapter adapter; +}; + +/* Version of the Greybus i2c protocol we support */ +#define GB_I2C_VERSION_MAJOR 0x00 +#define GB_I2C_VERSION_MINOR 0x01 + +/* Greybus i2c request types */ +#define GB_I2C_TYPE_INVALID 0x00 +#define GB_I2C_TYPE_PROTOCOL_VERSION 0x01 +#define GB_I2C_TYPE_FUNCTIONALITY 0x02 +#define GB_I2C_TYPE_TIMEOUT 0x03 +#define GB_I2C_TYPE_RETRIES 0x04 +#define GB_I2C_TYPE_TRANSFER 0x05 +#define GB_I2C_TYPE_RESPONSE 0x80 /* OR'd with rest */ + +#define GB_I2C_RETRIES_DEFAULT 3 +#define GB_I2C_TIMEOUT_DEFAULT 1000 /* milliseconds */ + +/* version request has no payload */ +struct gb_i2c_proto_version_response { + __u8 major; + __u8 minor; +}; + +/* functionality request has no payload */ +struct gb_i2c_functionality_response { + __le32 functionality; +}; + +struct gb_i2c_timeout_request { + __le16 msec; +}; +/* timeout response has no payload */ + +struct gb_i2c_retries_request { + __u8 retries; +}; +/* retries response has no payload */ + +/* + * Outgoing data immediately follows the op count and ops array. + * The data for each write (master -> slave) op in the array is sent + * in order, with no (e.g. pad) bytes separating them. + * + * Short reads cause the entire transfer request to fail So response + * payload consists only of bytes read, and the number of bytes is + * exactly what was specified in the corresponding op. Like + * outgoing data, the incoming data is in order and contiguous. + */ +struct gb_i2c_transfer_op { + __le16 addr; + __le16 flags; + __le16 size; +}; + +struct gb_i2c_transfer_request { + __le16 op_count; + struct gb_i2c_transfer_op ops[0]; /* op_count of these */ +}; +struct gb_i2c_transfer_response { + __u8 data[0]; /* inbound data */ +}; + +/* + * This request only uses the connection field, and if successful, + * fills in the major and minor protocol version of the target. + */ +static int gb_i2c_proto_version_operation(struct gb_i2c_device *gb_i2c_dev) +{ + struct gb_i2c_proto_version_response response; + int ret; + + ret = gb_operation_sync(gb_i2c_dev->connection, + GB_I2C_TYPE_PROTOCOL_VERSION, + NULL, 0, &response, sizeof(response)); + if (ret) + return ret; + + if (response.major > GB_I2C_VERSION_MAJOR) { + pr_err("unsupported major version (%hhu > %hhu)\n", + response.major, GB_I2C_VERSION_MAJOR); + return -ENOTSUPP; + } + gb_i2c_dev->version_major = response.major; + gb_i2c_dev->version_minor = response.minor; + return 0; +} + +/* + * Map Greybus i2c functionality bits into Linux ones + */ +static u32 gb_i2c_functionality_map(u32 gb_i2c_functionality) +{ + return gb_i2c_functionality; /* All bits the same for now */ +} + +static int gb_i2c_functionality_operation(struct gb_i2c_device *gb_i2c_dev) +{ + struct gb_i2c_functionality_response response; + u32 functionality; + int ret; + + ret = gb_operation_sync(gb_i2c_dev->connection, + GB_I2C_TYPE_FUNCTIONALITY, + NULL, 0, &response, sizeof(response)); + if (ret) + return ret; + + functionality = le32_to_cpu(response.functionality); + gb_i2c_dev->functionality = gb_i2c_functionality_map(functionality); + + return 0; +} + +static int gb_i2c_timeout_operation(struct gb_i2c_device *gb_i2c_dev, u16 msec) +{ + struct gb_i2c_timeout_request request; + int ret; + + request.msec = cpu_to_le16(msec); + ret = gb_operation_sync(gb_i2c_dev->connection, GB_I2C_TYPE_TIMEOUT, + &request, sizeof(request), NULL, 0); + if (ret) + pr_err("timeout operation failed (%d)\n", ret); + else + gb_i2c_dev->timeout_msec = msec; + + return ret; +} + +static int gb_i2c_retries_operation(struct gb_i2c_device *gb_i2c_dev, + u8 retries) +{ + struct gb_i2c_retries_request request; + int ret; + + request.retries = retries; + ret = gb_operation_sync(gb_i2c_dev->connection, GB_I2C_TYPE_RETRIES, + &request, sizeof(request), NULL, 0); + if (ret) + pr_err("retries operation failed (%d)\n", ret); + else + gb_i2c_dev->retries = retries; + + return ret; +} + + +/* + * Map Linux i2c_msg flags into Greybus i2c transfer op flags. + */ +static u16 gb_i2c_transfer_op_flags_map(u16 flags) +{ + return flags; /* All flags the same for now */ +} + +static void +gb_i2c_fill_transfer_op(struct gb_i2c_transfer_op *op, struct i2c_msg *msg) +{ + u16 flags = gb_i2c_transfer_op_flags_map(msg->flags); + + op->addr = cpu_to_le16(msg->addr); + op->flags = cpu_to_le16(flags); + op->size = cpu_to_le16(msg->len); +} + +static struct gb_operation * +gb_i2c_transfer_request(struct gb_connection *connection, + struct i2c_msg *msgs, u32 msg_count) +{ + struct gb_i2c_transfer_request *request; + struct gb_operation *operation; + struct gb_i2c_transfer_op *op; + struct i2c_msg *msg; + u32 data_out_size = 0; + u32 data_in_size = 0; + size_t request_size; + void *data; + u16 op_count; + u32 i; + + if (msg_count > (u32)U16_MAX) { + gb_connection_err(connection, "msg_count (%u) too big", + msg_count); + return NULL; + } + op_count = (u16)msg_count; + + /* + * In addition to space for all message descriptors we need + * to have enough to hold all outbound message data. + */ + msg = msgs; + for (i = 0; i < msg_count; i++, msg++) + if (msg->flags & I2C_M_RD) + data_in_size += (u32)msg->len; + else + data_out_size += (u32)msg->len; + + request_size = sizeof(*request); + request_size += msg_count * sizeof(*op); + request_size += data_out_size; + + /* Response consists only of incoming data */ + operation = gb_operation_create(connection, GB_I2C_TYPE_TRANSFER, + request_size, data_in_size); + if (!operation) + return NULL; + + request = operation->request->payload; + request->op_count = cpu_to_le16(op_count); + /* Fill in the ops array */ + op = &request->ops[0]; + msg = msgs; + for (i = 0; i < msg_count; i++) + gb_i2c_fill_transfer_op(op++, msg++); + + if (!data_out_size) + return operation; + + /* Copy over the outgoing data; it starts after the last op */ + data = op; + msg = msgs; + for (i = 0; i < msg_count; i++) { + if (!(msg->flags & I2C_M_RD)) { + memcpy(data, msg->buf, msg->len); + data += msg->len; + } + msg++; + } + + return operation; +} + +static void gb_i2c_transfer_response(struct i2c_msg *msgs, u32 msg_count, + struct gb_i2c_transfer_response *response) +{ + struct i2c_msg *msg = msgs; + u8 *data; + u32 i; + + if (!response) + return; + data = response->data; + for (i = 0; i < msg_count; i++) { + if (msg->flags & I2C_M_RD) { + memcpy(msg->buf, data, msg->len); + data += msg->len; + } + msg++; + } +} + +/* + * Some i2c transfer operations return results that are expected. + */ +static bool gb_i2c_expected_transfer_error(int errno) +{ + return errno == -EAGAIN || errno == -ENODEV; +} + +static int gb_i2c_transfer_operation(struct gb_i2c_device *gb_i2c_dev, + struct i2c_msg *msgs, u32 msg_count) +{ + struct gb_connection *connection = gb_i2c_dev->connection; + struct gb_operation *operation; + int ret; + + operation = gb_i2c_transfer_request(connection, msgs, msg_count); + if (!operation) + return -ENOMEM; + + ret = gb_operation_request_send_sync(operation); + if (!ret) { + struct gb_i2c_transfer_response *response; + + response = operation->response->payload; + gb_i2c_transfer_response(msgs, msg_count, response); + ret = msg_count; + } else if (!gb_i2c_expected_transfer_error(ret)) { + pr_err("transfer operation failed (%d)\n", ret); + } + gb_operation_destroy(operation); + + return ret; +} + +static int gb_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, + int msg_count) +{ + struct gb_i2c_device *gb_i2c_dev; + + gb_i2c_dev = i2c_get_adapdata(adap); + + return gb_i2c_transfer_operation(gb_i2c_dev, msgs, msg_count); +} + +#if 0 +/* Later */ +static int gb_i2c_smbus_xfer(struct i2c_adapter *adap, + u16 addr, unsigned short flags, char read_write, + u8 command, int size, union i2c_smbus_data *data) +{ + struct gb_i2c_device *gb_i2c_dev; + + gb_i2c_dev = i2c_get_adapdata(adap); + + return 0; +} +#endif + +static u32 gb_i2c_functionality(struct i2c_adapter *adap) +{ + struct gb_i2c_device *gb_i2c_dev = i2c_get_adapdata(adap); + + return gb_i2c_dev->functionality; +} + +static const struct i2c_algorithm gb_i2c_algorithm = { + .master_xfer = gb_i2c_master_xfer, + /* .smbus_xfer = gb_i2c_smbus_xfer, */ + .functionality = gb_i2c_functionality, +}; + +/* + * Do initial setup of the i2c device. This includes verifying we + * can support it (based on the protocol version it advertises). + * If that's OK, we get and cached its functionality bits, and + * set up the retry count and timeout. + * + * Note: gb_i2c_dev->connection is assumed to have been valid. + */ +static int gb_i2c_device_setup(struct gb_i2c_device *gb_i2c_dev) +{ + int ret; + + /* First thing we need to do is check the version */ + ret = gb_i2c_proto_version_operation(gb_i2c_dev); + if (ret) + return ret; + + /* Assume the functionality never changes, just get it once */ + ret = gb_i2c_functionality_operation(gb_i2c_dev); + if (ret) + return ret; + + /* Set up our default retry count and timeout */ + ret = gb_i2c_retries_operation(gb_i2c_dev, GB_I2C_RETRIES_DEFAULT); + if (ret) + return ret; + + return gb_i2c_timeout_operation(gb_i2c_dev, GB_I2C_TIMEOUT_DEFAULT); +} + +static int gb_i2c_connection_init(struct gb_connection *connection) +{ + struct gb_i2c_device *gb_i2c_dev; + struct i2c_adapter *adapter; + int ret; + + gb_i2c_dev = kzalloc(sizeof(*gb_i2c_dev), GFP_KERNEL); + if (!gb_i2c_dev) + return -ENOMEM; + + gb_i2c_dev->connection = connection; /* refcount? */ + connection->private = gb_i2c_dev; + + ret = gb_i2c_device_setup(gb_i2c_dev); + if (ret) + goto out_err; + + /* Looks good; up our i2c adapter */ + adapter = &gb_i2c_dev->adapter; + adapter->owner = THIS_MODULE; + adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; + adapter->algo = &gb_i2c_algorithm; + /* adapter->algo_data = what? */ + adapter->timeout = gb_i2c_dev->timeout_msec * HZ / 1000; + adapter->retries = gb_i2c_dev->retries; + + adapter->dev.parent = &connection->dev; + snprintf(adapter->name, sizeof(adapter->name), "Greybus i2c adapter"); + i2c_set_adapdata(adapter, gb_i2c_dev); + + ret = i2c_add_adapter(adapter); + if (ret) + goto out_err; + + return 0; +out_err: + /* kref_put(gb_i2c_dev->connection) */ + kfree(gb_i2c_dev); + + return ret; +} + +static void gb_i2c_connection_exit(struct gb_connection *connection) +{ + struct gb_i2c_device *gb_i2c_dev = connection->private; + + i2c_del_adapter(&gb_i2c_dev->adapter); + /* kref_put(gb_i2c_dev->connection) */ + kfree(gb_i2c_dev); +} + +static struct gb_protocol i2c_protocol = { + .name = "i2c", + .id = GREYBUS_PROTOCOL_I2C, + .major = 0, + .minor = 1, + .connection_init = gb_i2c_connection_init, + .connection_exit = gb_i2c_connection_exit, + .request_recv = NULL, /* no incoming requests */ +}; + +int gb_i2c_protocol_init(void) +{ + return gb_protocol_register(&i2c_protocol); +} + +void gb_i2c_protocol_exit(void) +{ + gb_protocol_deregister(&i2c_protocol); +} diff --git a/drivers/staging/greybus/pwm-gb.c b/drivers/staging/greybus/pwm-gb.c deleted file mode 100644 index 91f7b87..0000000 --- a/drivers/staging/greybus/pwm-gb.c +++ /dev/null @@ -1,331 +0,0 @@ -/* - * PWM Greybus driver. - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#include -#include -#include -#include -#include "greybus.h" - -struct gb_pwm_chip { - struct gb_connection *connection; - u8 version_major; - u8 version_minor; - u8 pwm_max; /* max pwm number */ - - struct pwm_chip chip; - struct pwm_chip *pwm; -}; -#define pwm_chip_to_gb_pwm_chip(chip) \ - container_of(chip, struct gb_pwm_chip, chip) - -/* Version of the Greybus PWM protocol we support */ -#define GB_PWM_VERSION_MAJOR 0x00 -#define GB_PWM_VERSION_MINOR 0x01 - -/* Greybus PWM request types */ -#define GB_PWM_TYPE_INVALID 0x00 -#define GB_PWM_TYPE_PROTOCOL_VERSION 0x01 -#define GB_PWM_TYPE_PWM_COUNT 0x02 -#define GB_PWM_TYPE_ACTIVATE 0x03 -#define GB_PWM_TYPE_DEACTIVATE 0x04 -#define GB_PWM_TYPE_CONFIG 0x05 -#define GB_PWM_TYPE_POLARITY 0x06 -#define GB_PWM_TYPE_ENABLE 0x07 -#define GB_PWM_TYPE_DISABLE 0x08 -#define GB_PWM_TYPE_RESPONSE 0x80 /* OR'd with rest */ - -/* version request has no payload */ -struct gb_pwm_proto_version_response { - __u8 major; - __u8 minor; -}; - -/* pwm count request has no payload */ -struct gb_pwm_count_response { - __u8 count; -}; - -struct gb_pwm_activate_request { - __u8 which; -}; - -struct gb_pwm_deactivate_request { - __u8 which; -}; - -struct gb_pwm_config_request { - __u8 which; - __le32 duty; - __le32 period; -}; - -struct gb_pwm_polarity_request { - __u8 which; - __u8 polarity; -}; - -struct gb_pwm_enable_request { - __u8 which; -}; - -struct gb_pwm_disable_request { - __u8 which; -}; - -/* - * This request only uses the connection field, and if successful, - * fills in the major and minor protocol version of the target. - */ -static int gb_pwm_proto_version_operation(struct gb_pwm_chip *pwmc) -{ - struct gb_pwm_proto_version_response response; - int ret; - - ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_PROTOCOL_VERSION, - NULL, 0, &response, sizeof(response)); - - if (ret) - return ret; - - if (response.major > GB_PWM_VERSION_MAJOR) { - pr_err("unsupported major version (%hhu > %hhu)\n", - response.major, GB_PWM_VERSION_MAJOR); - return -ENOTSUPP; - } - pwmc->version_major = response.major; - pwmc->version_minor = response.minor; - return 0; -} - -static int gb_pwm_count_operation(struct gb_pwm_chip *pwmc) -{ - struct gb_pwm_count_response response; - int ret; - - ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_PWM_COUNT, - NULL, 0, &response, sizeof(response)); - if (ret) - return ret; - pwmc->pwm_max = response.count; - return 0; -} - -static int gb_pwm_activate_operation(struct gb_pwm_chip *pwmc, - u8 which) -{ - struct gb_pwm_activate_request request; - - if (which > pwmc->pwm_max) - return -EINVAL; - - request.which = which; - return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_ACTIVATE, - &request, sizeof(request), NULL, 0); -} - -static int gb_pwm_deactivate_operation(struct gb_pwm_chip *pwmc, - u8 which) -{ - struct gb_pwm_deactivate_request request; - - if (which > pwmc->pwm_max) - return -EINVAL; - - request.which = which; - return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_DEACTIVATE, - &request, sizeof(request), NULL, 0); -} - -static int gb_pwm_config_operation(struct gb_pwm_chip *pwmc, - u8 which, u32 duty, u32 period) -{ - struct gb_pwm_config_request request; - - if (which > pwmc->pwm_max) - return -EINVAL; - - request.which = which; - request.duty = cpu_to_le32(duty); - request.period = cpu_to_le32(period); - return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_CONFIG, - &request, sizeof(request), NULL, 0); -} - - -static int gb_pwm_set_polarity_operation(struct gb_pwm_chip *pwmc, - u8 which, u8 polarity) -{ - struct gb_pwm_polarity_request request; - - if (which > pwmc->pwm_max) - return -EINVAL; - - request.which = which; - request.polarity = polarity; - return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_POLARITY, - &request, sizeof(request), NULL, 0); -} - -static int gb_pwm_enable_operation(struct gb_pwm_chip *pwmc, - u8 which) -{ - struct gb_pwm_enable_request request; - - if (which > pwmc->pwm_max) - return -EINVAL; - - request.which = which; - return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_ENABLE, - &request, sizeof(request), NULL, 0); -} - -static int gb_pwm_disable_operation(struct gb_pwm_chip *pwmc, - u8 which) -{ - struct gb_pwm_disable_request request; - - if (which > pwmc->pwm_max) - return -EINVAL; - - request.which = which; - return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_DISABLE, - &request, sizeof(request), NULL, 0); -} - -static int gb_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) -{ - struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); - - return gb_pwm_activate_operation(pwmc, pwm->hwpwm); -}; - -static void gb_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) -{ - struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); - - if (test_bit(PWMF_ENABLED, &pwm->flags)) - dev_warn(chip->dev, "freeing PWM device without disabling\n"); - - gb_pwm_deactivate_operation(pwmc, pwm->hwpwm); -} - -static int gb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, - int duty_ns, int period_ns) -{ - struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); - - return gb_pwm_config_operation(pwmc, pwm->hwpwm, duty_ns, period_ns); -}; - -static int gb_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm, - enum pwm_polarity polarity) -{ - struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); - - return gb_pwm_set_polarity_operation(pwmc, pwm->hwpwm, polarity); -}; - -static int gb_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) -{ - struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); - - return gb_pwm_enable_operation(pwmc, pwm->hwpwm); -}; - -static void gb_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) -{ - struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); - - gb_pwm_disable_operation(pwmc, pwm->hwpwm); -}; - -static const struct pwm_ops gb_pwm_ops = { - .request = gb_pwm_request, - .free = gb_pwm_free, - .config = gb_pwm_config, - .set_polarity = gb_pwm_set_polarity, - .enable = gb_pwm_enable, - .disable = gb_pwm_disable, - .owner = THIS_MODULE, -}; - -static int gb_pwm_connection_init(struct gb_connection *connection) -{ - struct gb_pwm_chip *pwmc; - struct pwm_chip *pwm; - int ret; - - pwmc = kzalloc(sizeof(*pwmc), GFP_KERNEL); - if (!pwmc) - return -ENOMEM; - pwmc->connection = connection; - connection->private = pwmc; - - /* Check for compatible protocol version */ - ret = gb_pwm_proto_version_operation(pwmc); - if (ret) - goto out_err; - - /* Query number of pwms present */ - ret = gb_pwm_count_operation(pwmc); - if (ret) - goto out_err; - - pwm = &pwmc->chip; - - pwm->dev = &connection->dev; - pwm->ops = &gb_pwm_ops; - pwm->base = -1; /* Allocate base dynamically */ - pwm->npwm = pwmc->pwm_max + 1; - pwm->can_sleep = true; /* FIXME */ - - ret = pwmchip_add(pwm); - if (ret) { - pr_err("Failed to register PWM\n"); - return ret; - } - - return 0; -out_err: - kfree(pwmc); - return ret; -} - -static void gb_pwm_connection_exit(struct gb_connection *connection) -{ - struct gb_pwm_chip *pwmc = connection->private; - - if (!pwmc) - return; - - pwmchip_remove(&pwmc->chip); - /* kref_put(pwmc->connection) */ - kfree(pwmc); -} - -static struct gb_protocol pwm_protocol = { - .name = "pwm", - .id = GREYBUS_PROTOCOL_PWM, - .major = 0, - .minor = 1, - .connection_init = gb_pwm_connection_init, - .connection_exit = gb_pwm_connection_exit, - .request_recv = NULL, /* no incoming requests */ -}; - -int gb_pwm_protocol_init(void) -{ - return gb_protocol_register(&pwm_protocol); -} - -void gb_pwm_protocol_exit(void) -{ - gb_protocol_deregister(&pwm_protocol); -} diff --git a/drivers/staging/greybus/pwm.c b/drivers/staging/greybus/pwm.c new file mode 100644 index 0000000..91f7b87 --- /dev/null +++ b/drivers/staging/greybus/pwm.c @@ -0,0 +1,331 @@ +/* + * PWM Greybus driver. + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include "greybus.h" + +struct gb_pwm_chip { + struct gb_connection *connection; + u8 version_major; + u8 version_minor; + u8 pwm_max; /* max pwm number */ + + struct pwm_chip chip; + struct pwm_chip *pwm; +}; +#define pwm_chip_to_gb_pwm_chip(chip) \ + container_of(chip, struct gb_pwm_chip, chip) + +/* Version of the Greybus PWM protocol we support */ +#define GB_PWM_VERSION_MAJOR 0x00 +#define GB_PWM_VERSION_MINOR 0x01 + +/* Greybus PWM request types */ +#define GB_PWM_TYPE_INVALID 0x00 +#define GB_PWM_TYPE_PROTOCOL_VERSION 0x01 +#define GB_PWM_TYPE_PWM_COUNT 0x02 +#define GB_PWM_TYPE_ACTIVATE 0x03 +#define GB_PWM_TYPE_DEACTIVATE 0x04 +#define GB_PWM_TYPE_CONFIG 0x05 +#define GB_PWM_TYPE_POLARITY 0x06 +#define GB_PWM_TYPE_ENABLE 0x07 +#define GB_PWM_TYPE_DISABLE 0x08 +#define GB_PWM_TYPE_RESPONSE 0x80 /* OR'd with rest */ + +/* version request has no payload */ +struct gb_pwm_proto_version_response { + __u8 major; + __u8 minor; +}; + +/* pwm count request has no payload */ +struct gb_pwm_count_response { + __u8 count; +}; + +struct gb_pwm_activate_request { + __u8 which; +}; + +struct gb_pwm_deactivate_request { + __u8 which; +}; + +struct gb_pwm_config_request { + __u8 which; + __le32 duty; + __le32 period; +}; + +struct gb_pwm_polarity_request { + __u8 which; + __u8 polarity; +}; + +struct gb_pwm_enable_request { + __u8 which; +}; + +struct gb_pwm_disable_request { + __u8 which; +}; + +/* + * This request only uses the connection field, and if successful, + * fills in the major and minor protocol version of the target. + */ +static int gb_pwm_proto_version_operation(struct gb_pwm_chip *pwmc) +{ + struct gb_pwm_proto_version_response response; + int ret; + + ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_PROTOCOL_VERSION, + NULL, 0, &response, sizeof(response)); + + if (ret) + return ret; + + if (response.major > GB_PWM_VERSION_MAJOR) { + pr_err("unsupported major version (%hhu > %hhu)\n", + response.major, GB_PWM_VERSION_MAJOR); + return -ENOTSUPP; + } + pwmc->version_major = response.major; + pwmc->version_minor = response.minor; + return 0; +} + +static int gb_pwm_count_operation(struct gb_pwm_chip *pwmc) +{ + struct gb_pwm_count_response response; + int ret; + + ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_PWM_COUNT, + NULL, 0, &response, sizeof(response)); + if (ret) + return ret; + pwmc->pwm_max = response.count; + return 0; +} + +static int gb_pwm_activate_operation(struct gb_pwm_chip *pwmc, + u8 which) +{ + struct gb_pwm_activate_request request; + + if (which > pwmc->pwm_max) + return -EINVAL; + + request.which = which; + return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_ACTIVATE, + &request, sizeof(request), NULL, 0); +} + +static int gb_pwm_deactivate_operation(struct gb_pwm_chip *pwmc, + u8 which) +{ + struct gb_pwm_deactivate_request request; + + if (which > pwmc->pwm_max) + return -EINVAL; + + request.which = which; + return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_DEACTIVATE, + &request, sizeof(request), NULL, 0); +} + +static int gb_pwm_config_operation(struct gb_pwm_chip *pwmc, + u8 which, u32 duty, u32 period) +{ + struct gb_pwm_config_request request; + + if (which > pwmc->pwm_max) + return -EINVAL; + + request.which = which; + request.duty = cpu_to_le32(duty); + request.period = cpu_to_le32(period); + return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_CONFIG, + &request, sizeof(request), NULL, 0); +} + + +static int gb_pwm_set_polarity_operation(struct gb_pwm_chip *pwmc, + u8 which, u8 polarity) +{ + struct gb_pwm_polarity_request request; + + if (which > pwmc->pwm_max) + return -EINVAL; + + request.which = which; + request.polarity = polarity; + return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_POLARITY, + &request, sizeof(request), NULL, 0); +} + +static int gb_pwm_enable_operation(struct gb_pwm_chip *pwmc, + u8 which) +{ + struct gb_pwm_enable_request request; + + if (which > pwmc->pwm_max) + return -EINVAL; + + request.which = which; + return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_ENABLE, + &request, sizeof(request), NULL, 0); +} + +static int gb_pwm_disable_operation(struct gb_pwm_chip *pwmc, + u8 which) +{ + struct gb_pwm_disable_request request; + + if (which > pwmc->pwm_max) + return -EINVAL; + + request.which = which; + return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_DISABLE, + &request, sizeof(request), NULL, 0); +} + +static int gb_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); + + return gb_pwm_activate_operation(pwmc, pwm->hwpwm); +}; + +static void gb_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); + + if (test_bit(PWMF_ENABLED, &pwm->flags)) + dev_warn(chip->dev, "freeing PWM device without disabling\n"); + + gb_pwm_deactivate_operation(pwmc, pwm->hwpwm); +} + +static int gb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, + int duty_ns, int period_ns) +{ + struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); + + return gb_pwm_config_operation(pwmc, pwm->hwpwm, duty_ns, period_ns); +}; + +static int gb_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm, + enum pwm_polarity polarity) +{ + struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); + + return gb_pwm_set_polarity_operation(pwmc, pwm->hwpwm, polarity); +}; + +static int gb_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); + + return gb_pwm_enable_operation(pwmc, pwm->hwpwm); +}; + +static void gb_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); + + gb_pwm_disable_operation(pwmc, pwm->hwpwm); +}; + +static const struct pwm_ops gb_pwm_ops = { + .request = gb_pwm_request, + .free = gb_pwm_free, + .config = gb_pwm_config, + .set_polarity = gb_pwm_set_polarity, + .enable = gb_pwm_enable, + .disable = gb_pwm_disable, + .owner = THIS_MODULE, +}; + +static int gb_pwm_connection_init(struct gb_connection *connection) +{ + struct gb_pwm_chip *pwmc; + struct pwm_chip *pwm; + int ret; + + pwmc = kzalloc(sizeof(*pwmc), GFP_KERNEL); + if (!pwmc) + return -ENOMEM; + pwmc->connection = connection; + connection->private = pwmc; + + /* Check for compatible protocol version */ + ret = gb_pwm_proto_version_operation(pwmc); + if (ret) + goto out_err; + + /* Query number of pwms present */ + ret = gb_pwm_count_operation(pwmc); + if (ret) + goto out_err; + + pwm = &pwmc->chip; + + pwm->dev = &connection->dev; + pwm->ops = &gb_pwm_ops; + pwm->base = -1; /* Allocate base dynamically */ + pwm->npwm = pwmc->pwm_max + 1; + pwm->can_sleep = true; /* FIXME */ + + ret = pwmchip_add(pwm); + if (ret) { + pr_err("Failed to register PWM\n"); + return ret; + } + + return 0; +out_err: + kfree(pwmc); + return ret; +} + +static void gb_pwm_connection_exit(struct gb_connection *connection) +{ + struct gb_pwm_chip *pwmc = connection->private; + + if (!pwmc) + return; + + pwmchip_remove(&pwmc->chip); + /* kref_put(pwmc->connection) */ + kfree(pwmc); +} + +static struct gb_protocol pwm_protocol = { + .name = "pwm", + .id = GREYBUS_PROTOCOL_PWM, + .major = 0, + .minor = 1, + .connection_init = gb_pwm_connection_init, + .connection_exit = gb_pwm_connection_exit, + .request_recv = NULL, /* no incoming requests */ +}; + +int gb_pwm_protocol_init(void) +{ + return gb_protocol_register(&pwm_protocol); +} + +void gb_pwm_protocol_exit(void) +{ + gb_protocol_deregister(&pwm_protocol); +} diff --git a/drivers/staging/greybus/sdio-gb.c b/drivers/staging/greybus/sdio-gb.c deleted file mode 100644 index d324846..0000000 --- a/drivers/staging/greybus/sdio-gb.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * SD/MMC Greybus driver. - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#include -#include -#include - -#include "greybus.h" - -struct gb_sdio_host { - struct gb_connection *connection; - struct mmc_host *mmc; - struct mmc_request *mrq; - // FIXME - some lock? -}; - -static void gb_sd_request(struct mmc_host *mmc, struct mmc_request *mrq) -{ - // FIXME - do something here... -} - -static void gb_sd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) -{ - // FIXME - do something here... -} - -static int gb_sd_get_ro(struct mmc_host *mmc) -{ - // FIXME - do something here... - return 0; -} - -static const struct mmc_host_ops gb_sd_ops = { - .request = gb_sd_request, - .set_ios = gb_sd_set_ios, - .get_ro = gb_sd_get_ro, -}; - -static int gb_sdio_connection_init(struct gb_connection *connection) -{ - struct mmc_host *mmc; - struct gb_sdio_host *host; - - mmc = mmc_alloc_host(sizeof(*host), &connection->dev); - if (!mmc) - return -ENOMEM; - - host = mmc_priv(mmc); - host->mmc = mmc; - - mmc->ops = &gb_sd_ops; - // FIXME - set up size limits we can handle. - // FIXME - register the host controller. - - host->connection = connection; - connection->private = host; - return 0; -} - -static void gb_sdio_connection_exit(struct gb_connection *connection) -{ - struct mmc_host *mmc; - struct gb_sdio_host *host; - - host = connection->private; - if (!host) - return; - - mmc = host->mmc; - mmc_remove_host(mmc); - mmc_free_host(mmc); - connection->private = NULL; -} - -static struct gb_protocol sdio_protocol = { - .name = "sdio", - .id = GREYBUS_PROTOCOL_SDIO, - .major = 0, - .minor = 1, - .connection_init = gb_sdio_connection_init, - .connection_exit = gb_sdio_connection_exit, - .request_recv = NULL, /* no incoming requests */ -}; - -int gb_sdio_protocol_init(void) -{ - return gb_protocol_register(&sdio_protocol); -} - -void gb_sdio_protocol_exit(void) -{ - gb_protocol_deregister(&sdio_protocol); -} diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c new file mode 100644 index 0000000..d324846 --- /dev/null +++ b/drivers/staging/greybus/sdio.c @@ -0,0 +1,99 @@ +/* + * SD/MMC Greybus driver. + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include + +#include "greybus.h" + +struct gb_sdio_host { + struct gb_connection *connection; + struct mmc_host *mmc; + struct mmc_request *mrq; + // FIXME - some lock? +}; + +static void gb_sd_request(struct mmc_host *mmc, struct mmc_request *mrq) +{ + // FIXME - do something here... +} + +static void gb_sd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) +{ + // FIXME - do something here... +} + +static int gb_sd_get_ro(struct mmc_host *mmc) +{ + // FIXME - do something here... + return 0; +} + +static const struct mmc_host_ops gb_sd_ops = { + .request = gb_sd_request, + .set_ios = gb_sd_set_ios, + .get_ro = gb_sd_get_ro, +}; + +static int gb_sdio_connection_init(struct gb_connection *connection) +{ + struct mmc_host *mmc; + struct gb_sdio_host *host; + + mmc = mmc_alloc_host(sizeof(*host), &connection->dev); + if (!mmc) + return -ENOMEM; + + host = mmc_priv(mmc); + host->mmc = mmc; + + mmc->ops = &gb_sd_ops; + // FIXME - set up size limits we can handle. + // FIXME - register the host controller. + + host->connection = connection; + connection->private = host; + return 0; +} + +static void gb_sdio_connection_exit(struct gb_connection *connection) +{ + struct mmc_host *mmc; + struct gb_sdio_host *host; + + host = connection->private; + if (!host) + return; + + mmc = host->mmc; + mmc_remove_host(mmc); + mmc_free_host(mmc); + connection->private = NULL; +} + +static struct gb_protocol sdio_protocol = { + .name = "sdio", + .id = GREYBUS_PROTOCOL_SDIO, + .major = 0, + .minor = 1, + .connection_init = gb_sdio_connection_init, + .connection_exit = gb_sdio_connection_exit, + .request_recv = NULL, /* no incoming requests */ +}; + +int gb_sdio_protocol_init(void) +{ + return gb_protocol_register(&sdio_protocol); +} + +void gb_sdio_protocol_exit(void) +{ + gb_protocol_deregister(&sdio_protocol); +} diff --git a/drivers/staging/greybus/uart-gb.c b/drivers/staging/greybus/uart-gb.c deleted file mode 100644 index 0320620..0000000 --- a/drivers/staging/greybus/uart-gb.c +++ /dev/null @@ -1,787 +0,0 @@ -/* - * UART driver for the Greybus "generic" UART module. - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - * - * Released under the GPLv2 only. - * - * Heavily based on drivers/usb/class/cdc-acm.c and - * drivers/usb/serial/usb-serial.c. - */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "greybus.h" - -#define GB_NUM_MINORS 255 /* 255 is enough for anyone... */ -#define GB_NAME "ttyGB" - -/* Version of the Greybus PWM protocol we support */ -#define GB_UART_VERSION_MAJOR 0x00 -#define GB_UART_VERSION_MINOR 0x01 - -/* Greybus UART request types */ -#define GB_UART_REQ_INVALID 0x00 -#define GB_UART_REQ_PROTOCOL_VERSION 0x01 -#define GB_UART_REQ_SEND_DATA 0x02 -#define GB_UART_REQ_RECEIVE_DATA 0x03 /* Unsolicited data */ -#define GB_UART_REQ_SET_LINE_CODING 0x04 -#define GB_UART_REQ_SET_CONTROL_LINE_STATE 0x05 -#define GB_UART_REQ_SET_BREAK 0x06 -#define GB_UART_REQ_SERIAL_STATE 0x07 /* Unsolicited data */ -#define GB_UART_TYPE_RESPONSE 0x80 /* OR'd with rest */ - -struct gb_uart_proto_version_response { - __u8 major; - __u8 minor; -}; - -struct gb_uart_send_data_request { - __le16 size; - __u8 data[0]; -}; - -struct gb_serial_line_coding { - __le32 rate; - __u8 format; -#define GB_SERIAL_1_STOP_BITS 0 -#define GB_SERIAL_1_5_STOP_BITS 1 -#define GB_SERIAL_2_STOP_BITS 2 - - __u8 parity; -#define GB_SERIAL_NO_PARITY 0 -#define GB_SERIAL_ODD_PARITY 1 -#define GB_SERIAL_EVEN_PARITY 2 -#define GB_SERIAL_MARK_PARITY 3 -#define GB_SERIAL_SPACE_PARITY 4 - - __u8 data; -} __attribute__ ((packed)); - -struct gb_uart_set_line_coding_request { - struct gb_serial_line_coding line_coding; -}; - -/* output control lines */ -#define GB_UART_CTRL_DTR 0x01 -#define GB_UART_CTRL_RTS 0x02 - -struct gb_uart_set_control_line_state_request { - __le16 control; -}; - -struct gb_uart_set_break_request { - __u8 state; -}; - -/* input control lines and line errors */ -#define GB_UART_CTRL_DCD 0x01 -#define GB_UART_CTRL_DSR 0x02 -#define GB_UART_CTRL_BRK 0x04 -#define GB_UART_CTRL_RI 0x08 - -#define GB_UART_CTRL_FRAMING 0x10 -#define GB_UART_CTRL_PARITY 0x20 -#define GB_UART_CTRL_OVERRUN 0x40 - -struct gb_uart_serial_state_request { - __u16 control; -}; - -struct gb_tty { - struct tty_port port; - struct gb_connection *connection; - u16 cport_id; - unsigned int minor; - unsigned char clocal; - bool disconnected; - spinlock_t read_lock; - spinlock_t write_lock; - struct async_icount iocount; - struct async_icount oldcount; - wait_queue_head_t wioctl; - struct mutex mutex; - u8 version_major; - u8 version_minor; - unsigned int ctrlin; /* input control lines */ - unsigned int ctrlout; /* output control lines */ - struct gb_serial_line_coding line_coding; -}; - - -static struct tty_driver *gb_tty_driver; -static DEFINE_IDR(tty_minors); -static DEFINE_MUTEX(table_lock); -static atomic_t reference_count = ATOMIC_INIT(0); - -/* - * This request only uses the connection field, and if successful, - * fills in the major and minor protocol version of the target. - */ -static int get_version(struct gb_tty *tty) -{ - struct gb_uart_proto_version_response response; - int ret; - - ret = gb_operation_sync(tty->connection, - GB_UART_REQ_PROTOCOL_VERSION, - NULL, 0, &response, sizeof(response)); - if (ret) - return ret; - - if (response.major > GB_UART_VERSION_MAJOR) { - pr_err("unsupported major version (%hhu > %hhu)\n", - response.major, GB_UART_VERSION_MAJOR); - return -ENOTSUPP; - } - tty->version_major = response.major; - tty->version_minor = response.minor; - - pr_debug("%s: version_major = %u version_minor = %u\n", - __func__, tty->version_major, tty->version_minor); - return 0; -} - -static int send_data(struct gb_tty *tty, u16 size, const u8 *data) -{ - struct gb_uart_send_data_request *request; - int retval; - - if (!data || !size) - return 0; - - request = kmalloc(sizeof(*request) + size, GFP_KERNEL); - if (!request) - return -ENOMEM; - - request->size = cpu_to_le16(size); - memcpy(&request->data[0], data, size); - retval = gb_operation_sync(tty->connection, GB_UART_REQ_SEND_DATA, - request, sizeof(*request) + size, NULL, 0); - - kfree(request); - return retval; -} - -static int send_line_coding(struct gb_tty *tty) -{ - struct gb_uart_set_line_coding_request request; - - memcpy(&request.line_coding, &tty->line_coding, - sizeof(tty->line_coding)); - return gb_operation_sync(tty->connection, GB_UART_REQ_SET_LINE_CODING, - &request, sizeof(request), NULL, 0); -} - -static int send_control(struct gb_tty *tty, u16 control) -{ - struct gb_uart_set_control_line_state_request request; - - request.control = cpu_to_le16(control); - return gb_operation_sync(tty->connection, - GB_UART_REQ_SET_CONTROL_LINE_STATE, - &request, sizeof(request), NULL, 0); -} - -static int send_break(struct gb_tty *tty, u8 state) -{ - struct gb_uart_set_break_request request; - - if ((state != 0) && (state != 1)) { - dev_err(&tty->connection->dev, - "invalid break state of %d\n", state); - return -EINVAL; - } - - request.state = state; - return gb_operation_sync(tty->connection, GB_UART_REQ_SET_BREAK, - &request, sizeof(request), NULL, 0); -} - - -static struct gb_tty *get_gb_by_minor(unsigned minor) -{ - struct gb_tty *gb_tty; - - mutex_lock(&table_lock); - gb_tty = idr_find(&tty_minors, minor); - if (gb_tty) { - mutex_lock(&gb_tty->mutex); - if (gb_tty->disconnected) { - mutex_unlock(&gb_tty->mutex); - gb_tty = NULL; - } else { - tty_port_get(&gb_tty->port); - mutex_unlock(&gb_tty->mutex); - } - } - mutex_unlock(&table_lock); - return gb_tty; -} - -static int alloc_minor(struct gb_tty *gb_tty) -{ - int minor; - - mutex_lock(&table_lock); - minor = idr_alloc(&tty_minors, gb_tty, 0, GB_NUM_MINORS, GFP_KERNEL); - mutex_unlock(&table_lock); - if (minor >= 0) - gb_tty->minor = minor; - return minor; -} - -static void release_minor(struct gb_tty *gb_tty) -{ - int minor = gb_tty->minor; - - gb_tty->minor = 0; /* Maybe should use an invalid value instead */ - mutex_lock(&table_lock); - idr_remove(&tty_minors, minor); - mutex_unlock(&table_lock); -} - -static int gb_tty_install(struct tty_driver *driver, struct tty_struct *tty) -{ - struct gb_tty *gb_tty; - int retval; - - gb_tty = get_gb_by_minor(tty->index); - if (!gb_tty) - return -ENODEV; - - retval = tty_standard_install(driver, tty); - if (retval) - goto error; - - tty->driver_data = gb_tty; - return 0; -error: - tty_port_put(&gb_tty->port); - return retval; -} - -static int gb_tty_open(struct tty_struct *tty, struct file *file) -{ - struct gb_tty *gb_tty = tty->driver_data; - - return tty_port_open(&gb_tty->port, tty, file); -} - -static void gb_tty_close(struct tty_struct *tty, struct file *file) -{ - struct gb_tty *gb_tty = tty->driver_data; - - tty_port_close(&gb_tty->port, tty, file); -} - -static void gb_tty_cleanup(struct tty_struct *tty) -{ - struct gb_tty *gb_tty = tty->driver_data; - - tty_port_put(&gb_tty->port); -} - -static void gb_tty_hangup(struct tty_struct *tty) -{ - struct gb_tty *gb_tty = tty->driver_data; - - tty_port_hangup(&gb_tty->port); -} - -static int gb_tty_write(struct tty_struct *tty, const unsigned char *buf, - int count) -{ - struct gb_tty *gb_tty = tty->driver_data; - - return send_data(gb_tty, count, buf); -} - -static int gb_tty_write_room(struct tty_struct *tty) -{ -// struct gb_tty *gb_tty = tty->driver_data; - - // FIXME - how much do we want to say we have room for? - return 0; -} - -static int gb_tty_chars_in_buffer(struct tty_struct *tty) -{ -// struct gb_tty *gb_tty = tty->driver_data; - - // FIXME - how many left to send? - return 0; -} - -static int gb_tty_break_ctl(struct tty_struct *tty, int state) -{ - struct gb_tty *gb_tty = tty->driver_data; - - return send_break(gb_tty, state ? 1 : 0); -} - -static void gb_tty_set_termios(struct tty_struct *tty, - struct ktermios *termios_old) -{ - struct gb_tty *gb_tty = tty->driver_data; - struct ktermios *termios = &tty->termios; - struct gb_serial_line_coding newline; - int newctrl = gb_tty->ctrlout; - - newline.rate = cpu_to_le32(tty_get_baud_rate(tty)); - newline.format = termios->c_cflag & CSTOPB ? 2 : 0; - newline.parity = 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.data = 5; - break; - case CS6: - newline.data = 6; - break; - case CS7: - newline.data = 7; - break; - case CS8: - default: - newline.data = 8; - break; - } - - /* FIXME: needs to clear unsupported bits in the termios */ - gb_tty->clocal = ((termios->c_cflag & CLOCAL) != 0); - - if (C_BAUD(tty) == B0) { - newline.rate = gb_tty->line_coding.rate; - newctrl &= GB_UART_CTRL_DTR; - } else if (termios_old && (termios_old->c_cflag & CBAUD) == B0) { - newctrl |= GB_UART_CTRL_DTR; - } - - if (newctrl != gb_tty->ctrlout) { - gb_tty->ctrlout = newctrl; - send_control(gb_tty, newctrl); - } - - if (memcpy(&gb_tty->line_coding, &newline, sizeof(newline))) { - memcpy(&gb_tty->line_coding, &newline, sizeof(newline)); - send_line_coding(gb_tty); - } -} - -static int gb_tty_tiocmget(struct tty_struct *tty) -{ - struct gb_tty *gb_tty = tty->driver_data; - - return (gb_tty->ctrlout & GB_UART_CTRL_DTR ? TIOCM_DTR : 0) | - (gb_tty->ctrlout & GB_UART_CTRL_RTS ? TIOCM_RTS : 0) | - (gb_tty->ctrlin & GB_UART_CTRL_DSR ? TIOCM_DSR : 0) | - (gb_tty->ctrlin & GB_UART_CTRL_RI ? TIOCM_RI : 0) | - (gb_tty->ctrlin & GB_UART_CTRL_DCD ? TIOCM_CD : 0) | - TIOCM_CTS; -} - -static int gb_tty_tiocmset(struct tty_struct *tty, unsigned int set, - unsigned int clear) -{ - struct gb_tty *gb_tty = tty->driver_data; - unsigned int newctrl = gb_tty->ctrlout; - - set = (set & TIOCM_DTR ? GB_UART_CTRL_DTR : 0) | - (set & TIOCM_RTS ? GB_UART_CTRL_RTS : 0); - clear = (clear & TIOCM_DTR ? GB_UART_CTRL_DTR : 0) | - (clear & TIOCM_RTS ? GB_UART_CTRL_RTS : 0); - - newctrl = (newctrl & ~clear) | set; - if (gb_tty->ctrlout == newctrl) - return 0; - - gb_tty->ctrlout = newctrl; - return send_control(gb_tty, newctrl); -} - -static void gb_tty_throttle(struct tty_struct *tty) -{ - struct gb_tty *gb_tty = tty->driver_data; - unsigned char stop_char; - int retval; - - if (I_IXOFF(tty)) { - stop_char = STOP_CHAR(tty); - retval = gb_tty_write(tty, &stop_char, 1); - if (retval <= 0) - return; - } - - if (tty->termios.c_cflag & CRTSCTS) { - gb_tty->ctrlout &= ~GB_UART_CTRL_RTS; - retval = send_control(gb_tty, gb_tty->ctrlout); - } - -} - -static void gb_tty_unthrottle(struct tty_struct *tty) -{ - struct gb_tty *gb_tty = tty->driver_data; - unsigned char start_char; - int retval; - - if (I_IXOFF(tty)) { - start_char = START_CHAR(tty); - retval = gb_tty_write(tty, &start_char, 1); - if (retval <= 0) - return; - } - - if (tty->termios.c_cflag & CRTSCTS) { - gb_tty->ctrlout |= GB_UART_CTRL_RTS; - retval = send_control(gb_tty, gb_tty->ctrlout); - } -} - -static int get_serial_info(struct gb_tty *gb_tty, - struct serial_struct __user *info) -{ - struct serial_struct tmp; - - if (!info) - return -EINVAL; - - memset(&tmp, 0, sizeof(tmp)); - tmp.flags = ASYNC_LOW_LATENCY | ASYNC_SKIP_TEST; - tmp.type = PORT_16550A; - tmp.line = gb_tty->minor; - tmp.xmit_fifo_size = 16; - tmp.baud_base = 9600; - tmp.close_delay = gb_tty->port.close_delay / 10; - tmp.closing_wait = gb_tty->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ? - ASYNC_CLOSING_WAIT_NONE : gb_tty->port.closing_wait / 10; - - if (copy_to_user(info, &tmp, sizeof(tmp))) - return -EFAULT; - return 0; -} - -static int set_serial_info(struct gb_tty *gb_tty, - struct serial_struct __user *newinfo) -{ - struct serial_struct new_serial; - unsigned int closing_wait; - unsigned int close_delay; - int retval = 0; - - if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) - return -EFAULT; - - close_delay = new_serial.close_delay * 10; - closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ? - ASYNC_CLOSING_WAIT_NONE : new_serial.closing_wait * 10; - - mutex_lock(&gb_tty->port.mutex); - if (!capable(CAP_SYS_ADMIN)) { - if ((close_delay != gb_tty->port.close_delay) || - (closing_wait != gb_tty->port.closing_wait)) - retval = -EPERM; - else - retval = -EOPNOTSUPP; - } else { - gb_tty->port.close_delay = close_delay; - gb_tty->port.closing_wait = closing_wait; - } - mutex_unlock(&gb_tty->port.mutex); - return retval; -} - -static int wait_serial_change(struct gb_tty *gb_tty, unsigned long arg) -{ - int retval = 0; - DECLARE_WAITQUEUE(wait, current); - struct async_icount old; - struct async_icount new; - - if (!(arg & (TIOCM_DSR | TIOCM_RI | TIOCM_CD))) - return -EINVAL; - - do { - spin_lock_irq(&gb_tty->read_lock); - old = gb_tty->oldcount; - new = gb_tty->iocount; - gb_tty->oldcount = new; - spin_unlock_irq(&gb_tty->read_lock); - - if ((arg & TIOCM_DSR) && (old.dsr != new.dsr)) - break; - if ((arg & TIOCM_CD) && (old.dcd != new.dcd)) - break; - if ((arg & TIOCM_RI) && (old.rng != new.rng)) - break; - - add_wait_queue(&gb_tty->wioctl, &wait); - set_current_state(TASK_INTERRUPTIBLE); - schedule(); - remove_wait_queue(&gb_tty->wioctl, &wait); - if (gb_tty->disconnected) { - if (arg & TIOCM_CD) - break; - retval = -ENODEV; - } else if (signal_pending(current)) { - retval = -ERESTARTSYS; - } - } while (!retval); - - return retval; -} - -static int get_serial_usage(struct gb_tty *gb_tty, - struct serial_icounter_struct __user *count) -{ - struct serial_icounter_struct icount; - int retval = 0; - - memset(&icount, 0, sizeof(icount)); - icount.dsr = gb_tty->iocount.dsr; - icount.rng = gb_tty->iocount.rng; - icount.dcd = gb_tty->iocount.dcd; - icount.frame = gb_tty->iocount.frame; - icount.overrun = gb_tty->iocount.overrun; - icount.parity = gb_tty->iocount.parity; - icount.brk = gb_tty->iocount.brk; - - if (copy_to_user(count, &icount, sizeof(icount)) > 0) - retval = -EFAULT; - - return retval; -} - -static int gb_tty_ioctl(struct tty_struct *tty, unsigned int cmd, - unsigned long arg) -{ - struct gb_tty *gb_tty = tty->driver_data; - - switch (cmd) { - case TIOCGSERIAL: - return get_serial_info(gb_tty, - (struct serial_struct __user *)arg); - case TIOCSSERIAL: - return set_serial_info(gb_tty, - (struct serial_struct __user *)arg); - case TIOCMIWAIT: - return wait_serial_change(gb_tty, arg); - case TIOCGICOUNT: - return get_serial_usage(gb_tty, - (struct serial_icounter_struct __user *)arg); - } - - return -ENOIOCTLCMD; -} - - -static const struct tty_operations gb_ops = { - .install = gb_tty_install, - .open = gb_tty_open, - .close = gb_tty_close, - .cleanup = gb_tty_cleanup, - .hangup = gb_tty_hangup, - .write = gb_tty_write, - .write_room = gb_tty_write_room, - .ioctl = gb_tty_ioctl, - .throttle = gb_tty_throttle, - .unthrottle = gb_tty_unthrottle, - .chars_in_buffer = gb_tty_chars_in_buffer, - .break_ctl = gb_tty_break_ctl, - .set_termios = gb_tty_set_termios, - .tiocmget = gb_tty_tiocmget, - .tiocmset = gb_tty_tiocmset, -}; - - -static int gb_tty_init(void); -static void gb_tty_exit(void); - -static int gb_uart_connection_init(struct gb_connection *connection) -{ - struct gb_tty *gb_tty; - struct device *tty_dev; - int retval; - int minor; - - /* First time here, initialize the tty structures */ - if (atomic_inc_return(&reference_count) == 1) { - retval = gb_tty_init(); - if (retval) { - atomic_dec(&reference_count); - return retval; - } - } - - gb_tty = kzalloc(sizeof(*gb_tty), GFP_KERNEL); - if (!gb_tty) - return -ENOMEM; - gb_tty->connection = connection; - connection->private = gb_tty; - - /* Check for compatible protocol version */ - retval = get_version(gb_tty); - if (retval) - goto error_version; - - minor = alloc_minor(gb_tty); - if (minor < 0) { - if (minor == -ENOSPC) { - dev_err(&connection->dev, - "no more free minor numbers\n"); - return -ENODEV; - } - return minor; - } - - gb_tty->minor = minor; - spin_lock_init(&gb_tty->write_lock); - spin_lock_init(&gb_tty->read_lock); - init_waitqueue_head(&gb_tty->wioctl); - mutex_init(&gb_tty->mutex); - - send_control(gb_tty, gb_tty->ctrlout); - - /* initialize the uart to be 9600n81 */ - gb_tty->line_coding.rate = cpu_to_le32(9600); - gb_tty->line_coding.format = GB_SERIAL_1_STOP_BITS; - gb_tty->line_coding.parity = GB_SERIAL_NO_PARITY; - gb_tty->line_coding.data = 8; - send_line_coding(gb_tty); - - tty_dev = tty_port_register_device(&gb_tty->port, gb_tty_driver, minor, - &connection->dev); - if (IS_ERR(tty_dev)) { - retval = PTR_ERR(tty_dev); - goto error; - } - - return 0; -error: - release_minor(gb_tty); -error_version: - connection->private = NULL; - kfree(gb_tty); - return retval; -} - -static void gb_uart_connection_exit(struct gb_connection *connection) -{ - struct gb_tty *gb_tty = connection->private; - struct tty_struct *tty; - - if (!gb_tty) - return; - - mutex_lock(&gb_tty->mutex); - gb_tty->disconnected = true; - - wake_up_all(&gb_tty->wioctl); - connection->private = NULL; - mutex_unlock(&gb_tty->mutex); - - tty = tty_port_tty_get(&gb_tty->port); - if (tty) { - tty_vhangup(tty); - tty_kref_put(tty); - } - /* FIXME - stop all traffic */ - - tty_unregister_device(gb_tty_driver, gb_tty->minor); - - /* FIXME - free transmit / receive buffers */ - - tty_port_put(&gb_tty->port); - - kfree(gb_tty); - - /* If last device is gone, tear down the tty structures */ - if (atomic_dec_return(&reference_count) == 0) - gb_tty_exit(); -} - -static int gb_tty_init(void) -{ - int retval = 0; - - gb_tty_driver = tty_alloc_driver(GB_NUM_MINORS, 0); - if (IS_ERR(gb_tty_driver)) { - pr_err("Can not allocate tty driver\n"); - retval = -ENOMEM; - goto fail_unregister_dev; - } - - gb_tty_driver->driver_name = "gb"; - gb_tty_driver->name = GB_NAME; - gb_tty_driver->major = 0; - gb_tty_driver->minor_start = 0; - gb_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; - gb_tty_driver->subtype = SERIAL_TYPE_NORMAL; - gb_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; - gb_tty_driver->init_termios = tty_std_termios; - gb_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - tty_set_operations(gb_tty_driver, &gb_ops); - - retval = tty_register_driver(gb_tty_driver); - if (retval) { - pr_err("Can not register tty driver: %d\n", retval); - goto fail_put_gb_tty; - } - - return 0; - -fail_put_gb_tty: - put_tty_driver(gb_tty_driver); -fail_unregister_dev: - return retval; -} - -static void gb_tty_exit(void) -{ - int major = MAJOR(gb_tty_driver->major); - int minor = gb_tty_driver->minor_start; - - tty_unregister_driver(gb_tty_driver); - put_tty_driver(gb_tty_driver); - unregister_chrdev_region(MKDEV(major, minor), GB_NUM_MINORS); -} - -static struct gb_protocol uart_protocol = { - .name = "uart", - .id = GREYBUS_PROTOCOL_UART, - .major = 0, - .minor = 1, - .connection_init = gb_uart_connection_init, - .connection_exit = gb_uart_connection_exit, - .request_recv = NULL, /* FIXME we have 2 types of requests!!! */ -}; - -int gb_uart_protocol_init(void) -{ - return gb_protocol_register(&uart_protocol); -} - -void gb_uart_protocol_exit(void) -{ - gb_protocol_deregister(&uart_protocol); -} diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c new file mode 100644 index 0000000..0320620 --- /dev/null +++ b/drivers/staging/greybus/uart.c @@ -0,0 +1,787 @@ +/* + * UART driver for the Greybus "generic" UART module. + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + * + * Heavily based on drivers/usb/class/cdc-acm.c and + * drivers/usb/serial/usb-serial.c. + */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "greybus.h" + +#define GB_NUM_MINORS 255 /* 255 is enough for anyone... */ +#define GB_NAME "ttyGB" + +/* Version of the Greybus PWM protocol we support */ +#define GB_UART_VERSION_MAJOR 0x00 +#define GB_UART_VERSION_MINOR 0x01 + +/* Greybus UART request types */ +#define GB_UART_REQ_INVALID 0x00 +#define GB_UART_REQ_PROTOCOL_VERSION 0x01 +#define GB_UART_REQ_SEND_DATA 0x02 +#define GB_UART_REQ_RECEIVE_DATA 0x03 /* Unsolicited data */ +#define GB_UART_REQ_SET_LINE_CODING 0x04 +#define GB_UART_REQ_SET_CONTROL_LINE_STATE 0x05 +#define GB_UART_REQ_SET_BREAK 0x06 +#define GB_UART_REQ_SERIAL_STATE 0x07 /* Unsolicited data */ +#define GB_UART_TYPE_RESPONSE 0x80 /* OR'd with rest */ + +struct gb_uart_proto_version_response { + __u8 major; + __u8 minor; +}; + +struct gb_uart_send_data_request { + __le16 size; + __u8 data[0]; +}; + +struct gb_serial_line_coding { + __le32 rate; + __u8 format; +#define GB_SERIAL_1_STOP_BITS 0 +#define GB_SERIAL_1_5_STOP_BITS 1 +#define GB_SERIAL_2_STOP_BITS 2 + + __u8 parity; +#define GB_SERIAL_NO_PARITY 0 +#define GB_SERIAL_ODD_PARITY 1 +#define GB_SERIAL_EVEN_PARITY 2 +#define GB_SERIAL_MARK_PARITY 3 +#define GB_SERIAL_SPACE_PARITY 4 + + __u8 data; +} __attribute__ ((packed)); + +struct gb_uart_set_line_coding_request { + struct gb_serial_line_coding line_coding; +}; + +/* output control lines */ +#define GB_UART_CTRL_DTR 0x01 +#define GB_UART_CTRL_RTS 0x02 + +struct gb_uart_set_control_line_state_request { + __le16 control; +}; + +struct gb_uart_set_break_request { + __u8 state; +}; + +/* input control lines and line errors */ +#define GB_UART_CTRL_DCD 0x01 +#define GB_UART_CTRL_DSR 0x02 +#define GB_UART_CTRL_BRK 0x04 +#define GB_UART_CTRL_RI 0x08 + +#define GB_UART_CTRL_FRAMING 0x10 +#define GB_UART_CTRL_PARITY 0x20 +#define GB_UART_CTRL_OVERRUN 0x40 + +struct gb_uart_serial_state_request { + __u16 control; +}; + +struct gb_tty { + struct tty_port port; + struct gb_connection *connection; + u16 cport_id; + unsigned int minor; + unsigned char clocal; + bool disconnected; + spinlock_t read_lock; + spinlock_t write_lock; + struct async_icount iocount; + struct async_icount oldcount; + wait_queue_head_t wioctl; + struct mutex mutex; + u8 version_major; + u8 version_minor; + unsigned int ctrlin; /* input control lines */ + unsigned int ctrlout; /* output control lines */ + struct gb_serial_line_coding line_coding; +}; + + +static struct tty_driver *gb_tty_driver; +static DEFINE_IDR(tty_minors); +static DEFINE_MUTEX(table_lock); +static atomic_t reference_count = ATOMIC_INIT(0); + +/* + * This request only uses the connection field, and if successful, + * fills in the major and minor protocol version of the target. + */ +static int get_version(struct gb_tty *tty) +{ + struct gb_uart_proto_version_response response; + int ret; + + ret = gb_operation_sync(tty->connection, + GB_UART_REQ_PROTOCOL_VERSION, + NULL, 0, &response, sizeof(response)); + if (ret) + return ret; + + if (response.major > GB_UART_VERSION_MAJOR) { + pr_err("unsupported major version (%hhu > %hhu)\n", + response.major, GB_UART_VERSION_MAJOR); + return -ENOTSUPP; + } + tty->version_major = response.major; + tty->version_minor = response.minor; + + pr_debug("%s: version_major = %u version_minor = %u\n", + __func__, tty->version_major, tty->version_minor); + return 0; +} + +static int send_data(struct gb_tty *tty, u16 size, const u8 *data) +{ + struct gb_uart_send_data_request *request; + int retval; + + if (!data || !size) + return 0; + + request = kmalloc(sizeof(*request) + size, GFP_KERNEL); + if (!request) + return -ENOMEM; + + request->size = cpu_to_le16(size); + memcpy(&request->data[0], data, size); + retval = gb_operation_sync(tty->connection, GB_UART_REQ_SEND_DATA, + request, sizeof(*request) + size, NULL, 0); + + kfree(request); + return retval; +} + +static int send_line_coding(struct gb_tty *tty) +{ + struct gb_uart_set_line_coding_request request; + + memcpy(&request.line_coding, &tty->line_coding, + sizeof(tty->line_coding)); + return gb_operation_sync(tty->connection, GB_UART_REQ_SET_LINE_CODING, + &request, sizeof(request), NULL, 0); +} + +static int send_control(struct gb_tty *tty, u16 control) +{ + struct gb_uart_set_control_line_state_request request; + + request.control = cpu_to_le16(control); + return gb_operation_sync(tty->connection, + GB_UART_REQ_SET_CONTROL_LINE_STATE, + &request, sizeof(request), NULL, 0); +} + +static int send_break(struct gb_tty *tty, u8 state) +{ + struct gb_uart_set_break_request request; + + if ((state != 0) && (state != 1)) { + dev_err(&tty->connection->dev, + "invalid break state of %d\n", state); + return -EINVAL; + } + + request.state = state; + return gb_operation_sync(tty->connection, GB_UART_REQ_SET_BREAK, + &request, sizeof(request), NULL, 0); +} + + +static struct gb_tty *get_gb_by_minor(unsigned minor) +{ + struct gb_tty *gb_tty; + + mutex_lock(&table_lock); + gb_tty = idr_find(&tty_minors, minor); + if (gb_tty) { + mutex_lock(&gb_tty->mutex); + if (gb_tty->disconnected) { + mutex_unlock(&gb_tty->mutex); + gb_tty = NULL; + } else { + tty_port_get(&gb_tty->port); + mutex_unlock(&gb_tty->mutex); + } + } + mutex_unlock(&table_lock); + return gb_tty; +} + +static int alloc_minor(struct gb_tty *gb_tty) +{ + int minor; + + mutex_lock(&table_lock); + minor = idr_alloc(&tty_minors, gb_tty, 0, GB_NUM_MINORS, GFP_KERNEL); + mutex_unlock(&table_lock); + if (minor >= 0) + gb_tty->minor = minor; + return minor; +} + +static void release_minor(struct gb_tty *gb_tty) +{ + int minor = gb_tty->minor; + + gb_tty->minor = 0; /* Maybe should use an invalid value instead */ + mutex_lock(&table_lock); + idr_remove(&tty_minors, minor); + mutex_unlock(&table_lock); +} + +static int gb_tty_install(struct tty_driver *driver, struct tty_struct *tty) +{ + struct gb_tty *gb_tty; + int retval; + + gb_tty = get_gb_by_minor(tty->index); + if (!gb_tty) + return -ENODEV; + + retval = tty_standard_install(driver, tty); + if (retval) + goto error; + + tty->driver_data = gb_tty; + return 0; +error: + tty_port_put(&gb_tty->port); + return retval; +} + +static int gb_tty_open(struct tty_struct *tty, struct file *file) +{ + struct gb_tty *gb_tty = tty->driver_data; + + return tty_port_open(&gb_tty->port, tty, file); +} + +static void gb_tty_close(struct tty_struct *tty, struct file *file) +{ + struct gb_tty *gb_tty = tty->driver_data; + + tty_port_close(&gb_tty->port, tty, file); +} + +static void gb_tty_cleanup(struct tty_struct *tty) +{ + struct gb_tty *gb_tty = tty->driver_data; + + tty_port_put(&gb_tty->port); +} + +static void gb_tty_hangup(struct tty_struct *tty) +{ + struct gb_tty *gb_tty = tty->driver_data; + + tty_port_hangup(&gb_tty->port); +} + +static int gb_tty_write(struct tty_struct *tty, const unsigned char *buf, + int count) +{ + struct gb_tty *gb_tty = tty->driver_data; + + return send_data(gb_tty, count, buf); +} + +static int gb_tty_write_room(struct tty_struct *tty) +{ +// struct gb_tty *gb_tty = tty->driver_data; + + // FIXME - how much do we want to say we have room for? + return 0; +} + +static int gb_tty_chars_in_buffer(struct tty_struct *tty) +{ +// struct gb_tty *gb_tty = tty->driver_data; + + // FIXME - how many left to send? + return 0; +} + +static int gb_tty_break_ctl(struct tty_struct *tty, int state) +{ + struct gb_tty *gb_tty = tty->driver_data; + + return send_break(gb_tty, state ? 1 : 0); +} + +static void gb_tty_set_termios(struct tty_struct *tty, + struct ktermios *termios_old) +{ + struct gb_tty *gb_tty = tty->driver_data; + struct ktermios *termios = &tty->termios; + struct gb_serial_line_coding newline; + int newctrl = gb_tty->ctrlout; + + newline.rate = cpu_to_le32(tty_get_baud_rate(tty)); + newline.format = termios->c_cflag & CSTOPB ? 2 : 0; + newline.parity = 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.data = 5; + break; + case CS6: + newline.data = 6; + break; + case CS7: + newline.data = 7; + break; + case CS8: + default: + newline.data = 8; + break; + } + + /* FIXME: needs to clear unsupported bits in the termios */ + gb_tty->clocal = ((termios->c_cflag & CLOCAL) != 0); + + if (C_BAUD(tty) == B0) { + newline.rate = gb_tty->line_coding.rate; + newctrl &= GB_UART_CTRL_DTR; + } else if (termios_old && (termios_old->c_cflag & CBAUD) == B0) { + newctrl |= GB_UART_CTRL_DTR; + } + + if (newctrl != gb_tty->ctrlout) { + gb_tty->ctrlout = newctrl; + send_control(gb_tty, newctrl); + } + + if (memcpy(&gb_tty->line_coding, &newline, sizeof(newline))) { + memcpy(&gb_tty->line_coding, &newline, sizeof(newline)); + send_line_coding(gb_tty); + } +} + +static int gb_tty_tiocmget(struct tty_struct *tty) +{ + struct gb_tty *gb_tty = tty->driver_data; + + return (gb_tty->ctrlout & GB_UART_CTRL_DTR ? TIOCM_DTR : 0) | + (gb_tty->ctrlout & GB_UART_CTRL_RTS ? TIOCM_RTS : 0) | + (gb_tty->ctrlin & GB_UART_CTRL_DSR ? TIOCM_DSR : 0) | + (gb_tty->ctrlin & GB_UART_CTRL_RI ? TIOCM_RI : 0) | + (gb_tty->ctrlin & GB_UART_CTRL_DCD ? TIOCM_CD : 0) | + TIOCM_CTS; +} + +static int gb_tty_tiocmset(struct tty_struct *tty, unsigned int set, + unsigned int clear) +{ + struct gb_tty *gb_tty = tty->driver_data; + unsigned int newctrl = gb_tty->ctrlout; + + set = (set & TIOCM_DTR ? GB_UART_CTRL_DTR : 0) | + (set & TIOCM_RTS ? GB_UART_CTRL_RTS : 0); + clear = (clear & TIOCM_DTR ? GB_UART_CTRL_DTR : 0) | + (clear & TIOCM_RTS ? GB_UART_CTRL_RTS : 0); + + newctrl = (newctrl & ~clear) | set; + if (gb_tty->ctrlout == newctrl) + return 0; + + gb_tty->ctrlout = newctrl; + return send_control(gb_tty, newctrl); +} + +static void gb_tty_throttle(struct tty_struct *tty) +{ + struct gb_tty *gb_tty = tty->driver_data; + unsigned char stop_char; + int retval; + + if (I_IXOFF(tty)) { + stop_char = STOP_CHAR(tty); + retval = gb_tty_write(tty, &stop_char, 1); + if (retval <= 0) + return; + } + + if (tty->termios.c_cflag & CRTSCTS) { + gb_tty->ctrlout &= ~GB_UART_CTRL_RTS; + retval = send_control(gb_tty, gb_tty->ctrlout); + } + +} + +static void gb_tty_unthrottle(struct tty_struct *tty) +{ + struct gb_tty *gb_tty = tty->driver_data; + unsigned char start_char; + int retval; + + if (I_IXOFF(tty)) { + start_char = START_CHAR(tty); + retval = gb_tty_write(tty, &start_char, 1); + if (retval <= 0) + return; + } + + if (tty->termios.c_cflag & CRTSCTS) { + gb_tty->ctrlout |= GB_UART_CTRL_RTS; + retval = send_control(gb_tty, gb_tty->ctrlout); + } +} + +static int get_serial_info(struct gb_tty *gb_tty, + struct serial_struct __user *info) +{ + struct serial_struct tmp; + + if (!info) + return -EINVAL; + + memset(&tmp, 0, sizeof(tmp)); + tmp.flags = ASYNC_LOW_LATENCY | ASYNC_SKIP_TEST; + tmp.type = PORT_16550A; + tmp.line = gb_tty->minor; + tmp.xmit_fifo_size = 16; + tmp.baud_base = 9600; + tmp.close_delay = gb_tty->port.close_delay / 10; + tmp.closing_wait = gb_tty->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ? + ASYNC_CLOSING_WAIT_NONE : gb_tty->port.closing_wait / 10; + + if (copy_to_user(info, &tmp, sizeof(tmp))) + return -EFAULT; + return 0; +} + +static int set_serial_info(struct gb_tty *gb_tty, + struct serial_struct __user *newinfo) +{ + struct serial_struct new_serial; + unsigned int closing_wait; + unsigned int close_delay; + int retval = 0; + + if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) + return -EFAULT; + + close_delay = new_serial.close_delay * 10; + closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ? + ASYNC_CLOSING_WAIT_NONE : new_serial.closing_wait * 10; + + mutex_lock(&gb_tty->port.mutex); + if (!capable(CAP_SYS_ADMIN)) { + if ((close_delay != gb_tty->port.close_delay) || + (closing_wait != gb_tty->port.closing_wait)) + retval = -EPERM; + else + retval = -EOPNOTSUPP; + } else { + gb_tty->port.close_delay = close_delay; + gb_tty->port.closing_wait = closing_wait; + } + mutex_unlock(&gb_tty->port.mutex); + return retval; +} + +static int wait_serial_change(struct gb_tty *gb_tty, unsigned long arg) +{ + int retval = 0; + DECLARE_WAITQUEUE(wait, current); + struct async_icount old; + struct async_icount new; + + if (!(arg & (TIOCM_DSR | TIOCM_RI | TIOCM_CD))) + return -EINVAL; + + do { + spin_lock_irq(&gb_tty->read_lock); + old = gb_tty->oldcount; + new = gb_tty->iocount; + gb_tty->oldcount = new; + spin_unlock_irq(&gb_tty->read_lock); + + if ((arg & TIOCM_DSR) && (old.dsr != new.dsr)) + break; + if ((arg & TIOCM_CD) && (old.dcd != new.dcd)) + break; + if ((arg & TIOCM_RI) && (old.rng != new.rng)) + break; + + add_wait_queue(&gb_tty->wioctl, &wait); + set_current_state(TASK_INTERRUPTIBLE); + schedule(); + remove_wait_queue(&gb_tty->wioctl, &wait); + if (gb_tty->disconnected) { + if (arg & TIOCM_CD) + break; + retval = -ENODEV; + } else if (signal_pending(current)) { + retval = -ERESTARTSYS; + } + } while (!retval); + + return retval; +} + +static int get_serial_usage(struct gb_tty *gb_tty, + struct serial_icounter_struct __user *count) +{ + struct serial_icounter_struct icount; + int retval = 0; + + memset(&icount, 0, sizeof(icount)); + icount.dsr = gb_tty->iocount.dsr; + icount.rng = gb_tty->iocount.rng; + icount.dcd = gb_tty->iocount.dcd; + icount.frame = gb_tty->iocount.frame; + icount.overrun = gb_tty->iocount.overrun; + icount.parity = gb_tty->iocount.parity; + icount.brk = gb_tty->iocount.brk; + + if (copy_to_user(count, &icount, sizeof(icount)) > 0) + retval = -EFAULT; + + return retval; +} + +static int gb_tty_ioctl(struct tty_struct *tty, unsigned int cmd, + unsigned long arg) +{ + struct gb_tty *gb_tty = tty->driver_data; + + switch (cmd) { + case TIOCGSERIAL: + return get_serial_info(gb_tty, + (struct serial_struct __user *)arg); + case TIOCSSERIAL: + return set_serial_info(gb_tty, + (struct serial_struct __user *)arg); + case TIOCMIWAIT: + return wait_serial_change(gb_tty, arg); + case TIOCGICOUNT: + return get_serial_usage(gb_tty, + (struct serial_icounter_struct __user *)arg); + } + + return -ENOIOCTLCMD; +} + + +static const struct tty_operations gb_ops = { + .install = gb_tty_install, + .open = gb_tty_open, + .close = gb_tty_close, + .cleanup = gb_tty_cleanup, + .hangup = gb_tty_hangup, + .write = gb_tty_write, + .write_room = gb_tty_write_room, + .ioctl = gb_tty_ioctl, + .throttle = gb_tty_throttle, + .unthrottle = gb_tty_unthrottle, + .chars_in_buffer = gb_tty_chars_in_buffer, + .break_ctl = gb_tty_break_ctl, + .set_termios = gb_tty_set_termios, + .tiocmget = gb_tty_tiocmget, + .tiocmset = gb_tty_tiocmset, +}; + + +static int gb_tty_init(void); +static void gb_tty_exit(void); + +static int gb_uart_connection_init(struct gb_connection *connection) +{ + struct gb_tty *gb_tty; + struct device *tty_dev; + int retval; + int minor; + + /* First time here, initialize the tty structures */ + if (atomic_inc_return(&reference_count) == 1) { + retval = gb_tty_init(); + if (retval) { + atomic_dec(&reference_count); + return retval; + } + } + + gb_tty = kzalloc(sizeof(*gb_tty), GFP_KERNEL); + if (!gb_tty) + return -ENOMEM; + gb_tty->connection = connection; + connection->private = gb_tty; + + /* Check for compatible protocol version */ + retval = get_version(gb_tty); + if (retval) + goto error_version; + + minor = alloc_minor(gb_tty); + if (minor < 0) { + if (minor == -ENOSPC) { + dev_err(&connection->dev, + "no more free minor numbers\n"); + return -ENODEV; + } + return minor; + } + + gb_tty->minor = minor; + spin_lock_init(&gb_tty->write_lock); + spin_lock_init(&gb_tty->read_lock); + init_waitqueue_head(&gb_tty->wioctl); + mutex_init(&gb_tty->mutex); + + send_control(gb_tty, gb_tty->ctrlout); + + /* initialize the uart to be 9600n81 */ + gb_tty->line_coding.rate = cpu_to_le32(9600); + gb_tty->line_coding.format = GB_SERIAL_1_STOP_BITS; + gb_tty->line_coding.parity = GB_SERIAL_NO_PARITY; + gb_tty->line_coding.data = 8; + send_line_coding(gb_tty); + + tty_dev = tty_port_register_device(&gb_tty->port, gb_tty_driver, minor, + &connection->dev); + if (IS_ERR(tty_dev)) { + retval = PTR_ERR(tty_dev); + goto error; + } + + return 0; +error: + release_minor(gb_tty); +error_version: + connection->private = NULL; + kfree(gb_tty); + return retval; +} + +static void gb_uart_connection_exit(struct gb_connection *connection) +{ + struct gb_tty *gb_tty = connection->private; + struct tty_struct *tty; + + if (!gb_tty) + return; + + mutex_lock(&gb_tty->mutex); + gb_tty->disconnected = true; + + wake_up_all(&gb_tty->wioctl); + connection->private = NULL; + mutex_unlock(&gb_tty->mutex); + + tty = tty_port_tty_get(&gb_tty->port); + if (tty) { + tty_vhangup(tty); + tty_kref_put(tty); + } + /* FIXME - stop all traffic */ + + tty_unregister_device(gb_tty_driver, gb_tty->minor); + + /* FIXME - free transmit / receive buffers */ + + tty_port_put(&gb_tty->port); + + kfree(gb_tty); + + /* If last device is gone, tear down the tty structures */ + if (atomic_dec_return(&reference_count) == 0) + gb_tty_exit(); +} + +static int gb_tty_init(void) +{ + int retval = 0; + + gb_tty_driver = tty_alloc_driver(GB_NUM_MINORS, 0); + if (IS_ERR(gb_tty_driver)) { + pr_err("Can not allocate tty driver\n"); + retval = -ENOMEM; + goto fail_unregister_dev; + } + + gb_tty_driver->driver_name = "gb"; + gb_tty_driver->name = GB_NAME; + gb_tty_driver->major = 0; + gb_tty_driver->minor_start = 0; + gb_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; + gb_tty_driver->subtype = SERIAL_TYPE_NORMAL; + gb_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; + gb_tty_driver->init_termios = tty_std_termios; + gb_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + tty_set_operations(gb_tty_driver, &gb_ops); + + retval = tty_register_driver(gb_tty_driver); + if (retval) { + pr_err("Can not register tty driver: %d\n", retval); + goto fail_put_gb_tty; + } + + return 0; + +fail_put_gb_tty: + put_tty_driver(gb_tty_driver); +fail_unregister_dev: + return retval; +} + +static void gb_tty_exit(void) +{ + int major = MAJOR(gb_tty_driver->major); + int minor = gb_tty_driver->minor_start; + + tty_unregister_driver(gb_tty_driver); + put_tty_driver(gb_tty_driver); + unregister_chrdev_region(MKDEV(major, minor), GB_NUM_MINORS); +} + +static struct gb_protocol uart_protocol = { + .name = "uart", + .id = GREYBUS_PROTOCOL_UART, + .major = 0, + .minor = 1, + .connection_init = gb_uart_connection_init, + .connection_exit = gb_uart_connection_exit, + .request_recv = NULL, /* FIXME we have 2 types of requests!!! */ +}; + +int gb_uart_protocol_init(void) +{ + return gb_protocol_register(&uart_protocol); +} + +void gb_uart_protocol_exit(void) +{ + gb_protocol_deregister(&uart_protocol); +} diff --git a/drivers/staging/greybus/usb-gb.c b/drivers/staging/greybus/usb-gb.c deleted file mode 100644 index 010ef9e..0000000 --- a/drivers/staging/greybus/usb-gb.c +++ /dev/null @@ -1,396 +0,0 @@ -/* - * USB host driver for the Greybus "generic" USB module. - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - * - * Released under the GPLv2 only. - * - */ -#include -#include -#include -#include -#include - -#include "greybus.h" - -/* Version of the Greybus USB protocol we support */ -#define GB_USB_VERSION_MAJOR 0x00 -#define GB_USB_VERSION_MINOR 0x01 - -/* Greybus USB request types */ -#define GB_USB_TYPE_INVALID 0x00 -#define GB_USB_TYPE_PROTOCOL_VERSION 0x01 -#define GB_USB_TYPE_HCD_STOP 0x02 -#define GB_USB_TYPE_HCD_START 0x03 -#define GB_USB_TYPE_URB_ENQUEUE 0x04 -#define GB_USB_TYPE_URB_DEQUEUE 0x05 -#define GB_USB_TYPE_ENDPOINT_DISABLE 0x06 -#define GB_USB_TYPE_HUB_CONTROL 0x07 -#define GB_USB_TYPE_GET_FRAME_NUMBER 0x08 -#define GB_USB_TYPE_HUB_STATUS_DATA 0x09 - -struct gb_usb_proto_version_response { - __u8 major; - __u8 minor; -}; - -struct gb_usb_urb_enqueue_request { - __le32 pipe; - __le32 transfer_flags; - __le32 transfer_buffer_length; - __le32 maxpacket; - __le32 interval; - __le64 hcpriv_ep; - __le32 number_of_packets; - u8 setup_packet[8]; - u8 payload[0]; -}; - -struct gb_usb_urb_dequeue_request { - __le64 hcpriv_ep; -}; - -struct gb_usb_endpoint_disable_request { - __le64 hcpriv; -}; - -struct gb_usb_hub_control_request { - __le16 typeReq; - __le16 wValue; - __le16 wIndex; - __le16 wLength; -}; - -struct gb_usb_hub_control_response { - u8 buf[0]; -}; - -struct gb_usb_header { - __le16 size; - __le16 id; - __u8 type; -}; - -struct gb_usb_hub_status { - __le32 status; - __le16 buf_size; - u8 buf[0]; -}; - -static struct gb_usb_hub_status *hub_status; // FIXME!!! -static DEFINE_SPINLOCK(hub_status_lock); -static atomic_t frame_number; // FIXME!!! - -struct gb_usb_device { - struct gb_connection *connection; - - struct usb_hcd *hcd; - u8 version_major; - u8 version_minor; -}; - -#define to_gb_usb_device(d) ((struct gb_usb_device*) d->hcd_priv) - -static int get_version(struct gb_usb_device *dev) -{ - struct gb_usb_proto_version_response response; - int ret; - - ret = gb_operation_sync(dev->connection, - GB_USB_TYPE_PROTOCOL_VERSION, - NULL, 0, &response, sizeof(response)); - if (ret) - return ret; - - if (response.major > GB_USB_VERSION_MAJOR) { - pr_err("unsupported major version (%hhu > %hhu)\n", - response.major, GB_USB_VERSION_MAJOR); - return -ENOTSUPP; - } - dev->version_major = response.major; - dev->version_minor = response.minor; - return 0; -} - -static void hcd_stop(struct usb_hcd *hcd) -{ - struct gb_usb_device *dev = to_gb_usb_device(hcd); - int ret; - - ret = gb_operation_sync(dev->connection, GB_USB_TYPE_HCD_STOP, - NULL, 0, NULL, 0); - if (ret) - dev_err(&dev->connection->dev, "HCD stop failed '%d'\n", ret); -} - -static int hcd_start(struct usb_hcd *hcd) -{ - struct usb_bus *bus = hcd_to_bus(hcd); - struct gb_usb_device *dev = to_gb_usb_device(hcd); - int ret; - - ret = gb_operation_sync(dev->connection, GB_USB_TYPE_HCD_START, - NULL, 0, NULL, 0); - if (ret) { - dev_err(&dev->connection->dev, "HCD start failed '%d'\n", ret); - return ret; - } - - hcd->state = HC_STATE_RUNNING; - if (bus->root_hub) - usb_hcd_resume_root_hub(hcd); - return 0; -} - -static int urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) -{ - struct gb_usb_device *dev = to_gb_usb_device(hcd); - struct gb_usb_urb_enqueue_request *request; - struct gb_operation *operation; - int ret; - - operation = gb_operation_create(dev->connection, - GB_USB_TYPE_URB_ENQUEUE, - sizeof(*request) + - urb->transfer_buffer_length, 0); - if (!operation) - return -ENODEV; - - request = operation->request->payload; - request->pipe = cpu_to_le32(urb->pipe); - request->transfer_flags = cpu_to_le32(urb->transfer_flags); - request->transfer_buffer_length = cpu_to_le32(urb->transfer_buffer_length); - request->interval = cpu_to_le32(urb->interval); - request->hcpriv_ep = cpu_to_le64(urb->ep->hcpriv); - request->number_of_packets = cpu_to_le32(urb->number_of_packets); - - memcpy(request->setup_packet, urb->setup_packet, 8); - memcpy(&request->payload, urb->transfer_buffer, - urb->transfer_buffer_length); - - ret = gb_operation_request_send_sync(operation); - gb_operation_destroy(operation); - - return ret; -} - -static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) -{ - struct gb_usb_device *dev = to_gb_usb_device(hcd); - struct gb_usb_urb_dequeue_request request; - int ret; - - urb->ep->hcpriv = NULL; - request.hcpriv_ep = cpu_to_le64(urb->hcpriv); - ret = gb_operation_sync(dev->connection, GB_USB_TYPE_URB_DEQUEUE, - &request, sizeof(request), NULL, 0); - urb->hcpriv = NULL; - return ret; -} - -static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep) -{ - struct gb_usb_device *dev = to_gb_usb_device(hcd); - struct gb_usb_endpoint_disable_request request; - int ret; - - request.hcpriv = cpu_to_le64(ep->hcpriv); - ret = gb_operation_sync(dev->connection, GB_USB_TYPE_ENDPOINT_DISABLE, - &request, sizeof(request), NULL, 0); - ep->hcpriv = NULL; -} - -static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) -{ -} - -static int get_frame_number(struct usb_hcd *hcd) -{ - return atomic_read(&frame_number); -} - -static int hub_status_data(struct usb_hcd *hcd, char *buf) -{ - int retval; - unsigned long flags; - - spin_lock_irqsave(&hub_status_lock, flags); - memcpy(buf, hub_status->buf, le16_to_cpu(hub_status->buf_size)); - retval = le32_to_cpu(hub_status->status); - spin_unlock_irqrestore(&hub_status_lock, flags); - - return retval; -} - -static int hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, - char *buf, u16 wLength) -{ - struct gb_usb_hub_control_request request; - struct gb_usb_device *dev = to_gb_usb_device(hcd); - int ret; - - request.typeReq = cpu_to_le16(typeReq); - request.wValue = cpu_to_le16(wValue); - request.wIndex = cpu_to_le16(wIndex); - request.wLength = cpu_to_le16(wLength); - - // FIXME - buf needs to come back in struct gb_usb_hub_control_response - // for some types of requests, depending on typeReq. Do we do this in a - // "generic" way, or only ask for a response for the ones we "know" need - // a response (a small subset of all valid typeReq, thankfully.) - ret = gb_operation_sync(dev->connection, GB_USB_TYPE_HUB_CONTROL, - &request, sizeof(request), NULL, 0); - - return ret; -} - -static struct hc_driver usb_gb_hc_driver = { - .description = "greybus_usb", - .product_desc = "GB-Bridge USB Controller", /* TODO: Get this from GPB ?*/ - .flags = HCD_MEMORY | HCD_USB2, /* FIXME: Get this from GPB */ - .hcd_priv_size = sizeof(struct gb_usb_device), - - .start = hcd_start, - .stop = hcd_stop, - .urb_enqueue = urb_enqueue, - .urb_dequeue = urb_dequeue, - .endpoint_disable = endpoint_disable, - .endpoint_reset = endpoint_reset, - .get_frame_number = get_frame_number, - .hub_status_data = hub_status_data, - .hub_control = hub_control, -}; - -#if 0 -static inline void gb_usb_handle_get_frame_number(struct gbuf *gbuf) -{ - __le32 frame_num; - const size_t packet_size = sizeof(struct gb_usb_header) + - sizeof(frame_num); - struct gb_usb_header* hdr = gbuf->transfer_buffer; - - if (le16_to_cpu(hdr->size) != packet_size) { - pr_err("%s(): dropping packet too small\n", __func__); - return; - } - - frame_num = (__le32) ((char*) gbuf->transfer_buffer + - sizeof(struct gb_usb_header)); - atomic_set(&frame_number, le32_to_cpu(frame_num)); -} - -static inline void gb_usb_handle_hubs_status_data(struct gbuf *gbuf) -{ - struct gb_usb_hub_status *new_hubstatus, *hubstatus; - struct gb_usb_header* hdr = gbuf->transfer_buffer; - const size_t min_packet_size = sizeof(struct gb_usb_header) + - sizeof(struct gb_usb_hub_status); - unsigned long flags; - - if (le16_to_cpu(hdr->size) < min_packet_size) { - pr_err("%s(): dropping packet too small\n", __func__); - return; - } - - hubstatus = (struct gb_usb_hub_status*) ((char*) gbuf->transfer_buffer - + sizeof(struct gb_usb_header)); - - if (le16_to_cpu(hdr->size) != min_packet_size + hubstatus->buf_size) { - pr_err("%s(): invalid packet size, dropping packet\n", - __func__); - return; - } - - new_hubstatus = kmalloc(hubstatus->buf_size, GFP_KERNEL); - memcpy(&new_hubstatus, hubstatus, hubstatus->buf_size); - - spin_lock_irqsave(&hub_status_lock, flags); - hubstatus = hub_status; - hub_status = new_hubstatus; - spin_unlock_irqrestore(&hub_status_lock, flags); - - kfree(hubstatus); -} - -static void gb_usb_in_handler(struct gbuf *gbuf) -{ - struct gb_usb_header* hdr = gbuf->transfer_buffer; - - switch (hdr->type) { - case GB_USB_TYPE_GET_FRAME_NUMBER: - gb_usb_handle_get_frame_number(gbuf); - break; - - case GB_USB_TYPE_HUB_STATUS_DATA: - gb_usb_handle_hubs_status_data(gbuf); - break; - } -} -#endif - -static int gb_usb_connection_init(struct gb_connection *connection) -{ - struct device *dev = &connection->dev; - struct gb_usb_device *gb_usb_dev; - - int retval; - - gb_usb_dev = kzalloc(sizeof(*gb_usb_dev), GFP_KERNEL); - if (!gb_usb_dev) - return -ENOMEM; - - gb_usb_dev->connection = connection; - connection->private = gb_usb_dev; - - /* Check for compatible protocol version */ - retval = get_version(gb_usb_dev); - if (retval) - goto error_create_hcd; - - gb_usb_dev->hcd = usb_create_hcd(&usb_gb_hc_driver, dev, dev_name(dev)); - if (!gb_usb_dev->hcd) { - retval = -ENODEV; - goto error_create_hcd; - } - - gb_usb_dev->hcd->has_tt = 1; - gb_usb_dev->hcd->hcd_priv[0] = (unsigned long) gb_usb_dev; - - retval = usb_add_hcd(gb_usb_dev->hcd, 0, 0); - if (retval) - goto error_add_hcd; - - return 0; -error_add_hcd: - usb_put_hcd(gb_usb_dev->hcd); -error_create_hcd: - kfree(gb_usb_dev); - return retval; -} - -static void gb_usb_connection_exit(struct gb_connection *connection) -{ - // FIXME - tear everything down! -} - -static struct gb_protocol usb_protocol = { - .name = "usb", - .id = GREYBUS_PROTOCOL_USB, - .major = 0, - .minor = 1, - .connection_init = gb_usb_connection_init, - .connection_exit = gb_usb_connection_exit, - .request_recv = NULL, /* FIXME we have requests!!! */ -}; - -int gb_usb_protocol_init(void) -{ - return gb_protocol_register(&usb_protocol); -} - -void gb_usb_protocol_exit(void) -{ - gb_protocol_deregister(&usb_protocol); -} diff --git a/drivers/staging/greybus/usb.c b/drivers/staging/greybus/usb.c new file mode 100644 index 0000000..010ef9e --- /dev/null +++ b/drivers/staging/greybus/usb.c @@ -0,0 +1,396 @@ +/* + * USB host driver for the Greybus "generic" USB module. + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + * + */ +#include +#include +#include +#include +#include + +#include "greybus.h" + +/* Version of the Greybus USB protocol we support */ +#define GB_USB_VERSION_MAJOR 0x00 +#define GB_USB_VERSION_MINOR 0x01 + +/* Greybus USB request types */ +#define GB_USB_TYPE_INVALID 0x00 +#define GB_USB_TYPE_PROTOCOL_VERSION 0x01 +#define GB_USB_TYPE_HCD_STOP 0x02 +#define GB_USB_TYPE_HCD_START 0x03 +#define GB_USB_TYPE_URB_ENQUEUE 0x04 +#define GB_USB_TYPE_URB_DEQUEUE 0x05 +#define GB_USB_TYPE_ENDPOINT_DISABLE 0x06 +#define GB_USB_TYPE_HUB_CONTROL 0x07 +#define GB_USB_TYPE_GET_FRAME_NUMBER 0x08 +#define GB_USB_TYPE_HUB_STATUS_DATA 0x09 + +struct gb_usb_proto_version_response { + __u8 major; + __u8 minor; +}; + +struct gb_usb_urb_enqueue_request { + __le32 pipe; + __le32 transfer_flags; + __le32 transfer_buffer_length; + __le32 maxpacket; + __le32 interval; + __le64 hcpriv_ep; + __le32 number_of_packets; + u8 setup_packet[8]; + u8 payload[0]; +}; + +struct gb_usb_urb_dequeue_request { + __le64 hcpriv_ep; +}; + +struct gb_usb_endpoint_disable_request { + __le64 hcpriv; +}; + +struct gb_usb_hub_control_request { + __le16 typeReq; + __le16 wValue; + __le16 wIndex; + __le16 wLength; +}; + +struct gb_usb_hub_control_response { + u8 buf[0]; +}; + +struct gb_usb_header { + __le16 size; + __le16 id; + __u8 type; +}; + +struct gb_usb_hub_status { + __le32 status; + __le16 buf_size; + u8 buf[0]; +}; + +static struct gb_usb_hub_status *hub_status; // FIXME!!! +static DEFINE_SPINLOCK(hub_status_lock); +static atomic_t frame_number; // FIXME!!! + +struct gb_usb_device { + struct gb_connection *connection; + + struct usb_hcd *hcd; + u8 version_major; + u8 version_minor; +}; + +#define to_gb_usb_device(d) ((struct gb_usb_device*) d->hcd_priv) + +static int get_version(struct gb_usb_device *dev) +{ + struct gb_usb_proto_version_response response; + int ret; + + ret = gb_operation_sync(dev->connection, + GB_USB_TYPE_PROTOCOL_VERSION, + NULL, 0, &response, sizeof(response)); + if (ret) + return ret; + + if (response.major > GB_USB_VERSION_MAJOR) { + pr_err("unsupported major version (%hhu > %hhu)\n", + response.major, GB_USB_VERSION_MAJOR); + return -ENOTSUPP; + } + dev->version_major = response.major; + dev->version_minor = response.minor; + return 0; +} + +static void hcd_stop(struct usb_hcd *hcd) +{ + struct gb_usb_device *dev = to_gb_usb_device(hcd); + int ret; + + ret = gb_operation_sync(dev->connection, GB_USB_TYPE_HCD_STOP, + NULL, 0, NULL, 0); + if (ret) + dev_err(&dev->connection->dev, "HCD stop failed '%d'\n", ret); +} + +static int hcd_start(struct usb_hcd *hcd) +{ + struct usb_bus *bus = hcd_to_bus(hcd); + struct gb_usb_device *dev = to_gb_usb_device(hcd); + int ret; + + ret = gb_operation_sync(dev->connection, GB_USB_TYPE_HCD_START, + NULL, 0, NULL, 0); + if (ret) { + dev_err(&dev->connection->dev, "HCD start failed '%d'\n", ret); + return ret; + } + + hcd->state = HC_STATE_RUNNING; + if (bus->root_hub) + usb_hcd_resume_root_hub(hcd); + return 0; +} + +static int urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) +{ + struct gb_usb_device *dev = to_gb_usb_device(hcd); + struct gb_usb_urb_enqueue_request *request; + struct gb_operation *operation; + int ret; + + operation = gb_operation_create(dev->connection, + GB_USB_TYPE_URB_ENQUEUE, + sizeof(*request) + + urb->transfer_buffer_length, 0); + if (!operation) + return -ENODEV; + + request = operation->request->payload; + request->pipe = cpu_to_le32(urb->pipe); + request->transfer_flags = cpu_to_le32(urb->transfer_flags); + request->transfer_buffer_length = cpu_to_le32(urb->transfer_buffer_length); + request->interval = cpu_to_le32(urb->interval); + request->hcpriv_ep = cpu_to_le64(urb->ep->hcpriv); + request->number_of_packets = cpu_to_le32(urb->number_of_packets); + + memcpy(request->setup_packet, urb->setup_packet, 8); + memcpy(&request->payload, urb->transfer_buffer, + urb->transfer_buffer_length); + + ret = gb_operation_request_send_sync(operation); + gb_operation_destroy(operation); + + return ret; +} + +static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) +{ + struct gb_usb_device *dev = to_gb_usb_device(hcd); + struct gb_usb_urb_dequeue_request request; + int ret; + + urb->ep->hcpriv = NULL; + request.hcpriv_ep = cpu_to_le64(urb->hcpriv); + ret = gb_operation_sync(dev->connection, GB_USB_TYPE_URB_DEQUEUE, + &request, sizeof(request), NULL, 0); + urb->hcpriv = NULL; + return ret; +} + +static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep) +{ + struct gb_usb_device *dev = to_gb_usb_device(hcd); + struct gb_usb_endpoint_disable_request request; + int ret; + + request.hcpriv = cpu_to_le64(ep->hcpriv); + ret = gb_operation_sync(dev->connection, GB_USB_TYPE_ENDPOINT_DISABLE, + &request, sizeof(request), NULL, 0); + ep->hcpriv = NULL; +} + +static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) +{ +} + +static int get_frame_number(struct usb_hcd *hcd) +{ + return atomic_read(&frame_number); +} + +static int hub_status_data(struct usb_hcd *hcd, char *buf) +{ + int retval; + unsigned long flags; + + spin_lock_irqsave(&hub_status_lock, flags); + memcpy(buf, hub_status->buf, le16_to_cpu(hub_status->buf_size)); + retval = le32_to_cpu(hub_status->status); + spin_unlock_irqrestore(&hub_status_lock, flags); + + return retval; +} + +static int hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, + char *buf, u16 wLength) +{ + struct gb_usb_hub_control_request request; + struct gb_usb_device *dev = to_gb_usb_device(hcd); + int ret; + + request.typeReq = cpu_to_le16(typeReq); + request.wValue = cpu_to_le16(wValue); + request.wIndex = cpu_to_le16(wIndex); + request.wLength = cpu_to_le16(wLength); + + // FIXME - buf needs to come back in struct gb_usb_hub_control_response + // for some types of requests, depending on typeReq. Do we do this in a + // "generic" way, or only ask for a response for the ones we "know" need + // a response (a small subset of all valid typeReq, thankfully.) + ret = gb_operation_sync(dev->connection, GB_USB_TYPE_HUB_CONTROL, + &request, sizeof(request), NULL, 0); + + return ret; +} + +static struct hc_driver usb_gb_hc_driver = { + .description = "greybus_usb", + .product_desc = "GB-Bridge USB Controller", /* TODO: Get this from GPB ?*/ + .flags = HCD_MEMORY | HCD_USB2, /* FIXME: Get this from GPB */ + .hcd_priv_size = sizeof(struct gb_usb_device), + + .start = hcd_start, + .stop = hcd_stop, + .urb_enqueue = urb_enqueue, + .urb_dequeue = urb_dequeue, + .endpoint_disable = endpoint_disable, + .endpoint_reset = endpoint_reset, + .get_frame_number = get_frame_number, + .hub_status_data = hub_status_data, + .hub_control = hub_control, +}; + +#if 0 +static inline void gb_usb_handle_get_frame_number(struct gbuf *gbuf) +{ + __le32 frame_num; + const size_t packet_size = sizeof(struct gb_usb_header) + + sizeof(frame_num); + struct gb_usb_header* hdr = gbuf->transfer_buffer; + + if (le16_to_cpu(hdr->size) != packet_size) { + pr_err("%s(): dropping packet too small\n", __func__); + return; + } + + frame_num = (__le32) ((char*) gbuf->transfer_buffer + + sizeof(struct gb_usb_header)); + atomic_set(&frame_number, le32_to_cpu(frame_num)); +} + +static inline void gb_usb_handle_hubs_status_data(struct gbuf *gbuf) +{ + struct gb_usb_hub_status *new_hubstatus, *hubstatus; + struct gb_usb_header* hdr = gbuf->transfer_buffer; + const size_t min_packet_size = sizeof(struct gb_usb_header) + + sizeof(struct gb_usb_hub_status); + unsigned long flags; + + if (le16_to_cpu(hdr->size) < min_packet_size) { + pr_err("%s(): dropping packet too small\n", __func__); + return; + } + + hubstatus = (struct gb_usb_hub_status*) ((char*) gbuf->transfer_buffer + + sizeof(struct gb_usb_header)); + + if (le16_to_cpu(hdr->size) != min_packet_size + hubstatus->buf_size) { + pr_err("%s(): invalid packet size, dropping packet\n", + __func__); + return; + } + + new_hubstatus = kmalloc(hubstatus->buf_size, GFP_KERNEL); + memcpy(&new_hubstatus, hubstatus, hubstatus->buf_size); + + spin_lock_irqsave(&hub_status_lock, flags); + hubstatus = hub_status; + hub_status = new_hubstatus; + spin_unlock_irqrestore(&hub_status_lock, flags); + + kfree(hubstatus); +} + +static void gb_usb_in_handler(struct gbuf *gbuf) +{ + struct gb_usb_header* hdr = gbuf->transfer_buffer; + + switch (hdr->type) { + case GB_USB_TYPE_GET_FRAME_NUMBER: + gb_usb_handle_get_frame_number(gbuf); + break; + + case GB_USB_TYPE_HUB_STATUS_DATA: + gb_usb_handle_hubs_status_data(gbuf); + break; + } +} +#endif + +static int gb_usb_connection_init(struct gb_connection *connection) +{ + struct device *dev = &connection->dev; + struct gb_usb_device *gb_usb_dev; + + int retval; + + gb_usb_dev = kzalloc(sizeof(*gb_usb_dev), GFP_KERNEL); + if (!gb_usb_dev) + return -ENOMEM; + + gb_usb_dev->connection = connection; + connection->private = gb_usb_dev; + + /* Check for compatible protocol version */ + retval = get_version(gb_usb_dev); + if (retval) + goto error_create_hcd; + + gb_usb_dev->hcd = usb_create_hcd(&usb_gb_hc_driver, dev, dev_name(dev)); + if (!gb_usb_dev->hcd) { + retval = -ENODEV; + goto error_create_hcd; + } + + gb_usb_dev->hcd->has_tt = 1; + gb_usb_dev->hcd->hcd_priv[0] = (unsigned long) gb_usb_dev; + + retval = usb_add_hcd(gb_usb_dev->hcd, 0, 0); + if (retval) + goto error_add_hcd; + + return 0; +error_add_hcd: + usb_put_hcd(gb_usb_dev->hcd); +error_create_hcd: + kfree(gb_usb_dev); + return retval; +} + +static void gb_usb_connection_exit(struct gb_connection *connection) +{ + // FIXME - tear everything down! +} + +static struct gb_protocol usb_protocol = { + .name = "usb", + .id = GREYBUS_PROTOCOL_USB, + .major = 0, + .minor = 1, + .connection_init = gb_usb_connection_init, + .connection_exit = gb_usb_connection_exit, + .request_recv = NULL, /* FIXME we have requests!!! */ +}; + +int gb_usb_protocol_init(void) +{ + return gb_protocol_register(&usb_protocol); +} + +void gb_usb_protocol_exit(void) +{ + gb_protocol_deregister(&usb_protocol); +} -- cgit v0.10.2 From 98abb4146ed31f1ec97145ef808d864096d31c4b Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 21 Jan 2015 16:10:41 +0530 Subject: greybus: Remove "gb-" prefix from .c files Some files are still prefixed with "gb-" with the reasoning that the modules would be named so, i.e. gb-*.ko. But this can be done by playing a bit in Makefile instead and keep uniform naming of .c files. Lets try it. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 55b4a37..79af812 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -17,6 +17,12 @@ gb-phy-y := gpb.o \ i2c.o \ usb.o +# Prefix all modules with gb- +gb-vibrator-y := vibrator.o +gb-battery-y := battery.o +gb-es1-y := es1.o +gb-es2-y := es2.o + obj-m += greybus.o obj-m += gb-phy.o obj-m += gb-vibrator.o diff --git a/drivers/staging/greybus/battery.c b/drivers/staging/greybus/battery.c new file mode 100644 index 0000000..2130d73 --- /dev/null +++ b/drivers/staging/greybus/battery.c @@ -0,0 +1,373 @@ +/* + * Battery driver for a Greybus module. + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include "greybus.h" + +struct gb_battery { + struct power_supply bat; + // FIXME + // we will want to keep the battery stats in here as we will be getting + // updates from the SVC "on the fly" so we don't have to always go ask + // the battery for some information. Hopefully... + struct gb_connection *connection; + u8 version_major; + u8 version_minor; + +}; +#define to_gb_battery(x) container_of(x, struct gb_battery, bat) + +/* Version of the Greybus battery protocol we support */ +#define GB_BATTERY_VERSION_MAJOR 0x00 +#define GB_BATTERY_VERSION_MINOR 0x01 + +/* Greybus battery request types */ +#define GB_BATTERY_TYPE_INVALID 0x00 +#define GB_BATTERY_TYPE_PROTOCOL_VERSION 0x01 +#define GB_BATTERY_TYPE_TECHNOLOGY 0x02 +#define GB_BATTERY_TYPE_STATUS 0x03 +#define GB_BATTERY_TYPE_MAX_VOLTAGE 0x04 +#define GB_BATTERY_TYPE_PERCENT_CAPACITY 0x05 +#define GB_BATTERY_TYPE_TEMPERATURE 0x06 +#define GB_BATTERY_TYPE_VOLTAGE 0x07 +#define GB_BATTERY_TYPE_CURRENT 0x08 +#define GB_BATTERY_TYPE_CAPACITY 0x09 // TODO - POWER_SUPPLY_PROP_CURRENT_MAX +#define GB_BATTERY_TYPE_SHUTDOWN_TEMP 0x0a // TODO - POWER_SUPPLY_PROP_TEMP_ALERT_MAX + +struct gb_battery_proto_version_response { + __u8 major; + __u8 minor; +}; + +/* Should match up with battery types in linux/power_supply.h */ +#define GB_BATTERY_TECH_UNKNOWN 0x0000 +#define GB_BATTERY_TECH_NiMH 0x0001 +#define GB_BATTERY_TECH_LION 0x0002 +#define GB_BATTERY_TECH_LIPO 0x0003 +#define GB_BATTERY_TECH_LiFe 0x0004 +#define GB_BATTERY_TECH_NiCd 0x0005 +#define GB_BATTERY_TECH_LiMn 0x0006 + +struct gb_battery_technology_response { + __le32 technology; +}; + +/* Should match up with battery status in linux/power_supply.h */ +#define GB_BATTERY_STATUS_UNKNOWN 0x0000 +#define GB_BATTERY_STATUS_CHARGING 0x0001 +#define GB_BATTERY_STATUS_DISCHARGING 0x0002 +#define GB_BATTERY_STATUS_NOT_CHARGING 0x0003 +#define GB_BATTERY_STATUS_FULL 0x0004 + +struct gb_battery_status_response { + __le16 battery_status; +}; + +struct gb_battery_max_voltage_response { + __le32 max_voltage; +}; + +struct gb_battery_capacity_response { + __le32 capacity; +}; + +struct gb_battery_temperature_response { + __le32 temperature; +}; + +struct gb_battery_voltage_response { + __le32 voltage; +}; + +/* + * This request only uses the connection field, and if successful, + * fills in the major and minor protocol version of the target. + */ +static int get_version(struct gb_battery *gb) +{ + struct gb_battery_proto_version_response version_response; + int retval; + + retval = gb_operation_sync(gb->connection, + GB_BATTERY_TYPE_PROTOCOL_VERSION, + NULL, 0, + &version_response, sizeof(version_response)); + if (retval) + return retval; + + if (version_response.major > GB_BATTERY_VERSION_MAJOR) { + pr_err("unsupported major version (%hhu > %hhu)\n", + version_response.major, GB_BATTERY_VERSION_MAJOR); + return -ENOTSUPP; + } + + gb->version_major = version_response.major; + gb->version_minor = version_response.minor; + return 0; +} + +static int get_tech(struct gb_battery *gb) +{ + struct gb_battery_technology_response tech_response; + u32 technology; + int retval; + + retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_TECHNOLOGY, + NULL, 0, + &tech_response, sizeof(tech_response)); + if (retval) + return retval; + + /* + * Map greybus values to power_supply values. Hopefully these are + * "identical" which should allow gcc to optimize the code away to + * nothing. + */ + technology = le32_to_cpu(tech_response.technology); + switch (technology) { + case GB_BATTERY_TECH_NiMH: + technology = POWER_SUPPLY_TECHNOLOGY_NiMH; + break; + case GB_BATTERY_TECH_LION: + technology = POWER_SUPPLY_TECHNOLOGY_LION; + break; + case GB_BATTERY_TECH_LIPO: + technology = POWER_SUPPLY_TECHNOLOGY_LIPO; + break; + case GB_BATTERY_TECH_LiFe: + technology = POWER_SUPPLY_TECHNOLOGY_LiFe; + break; + case GB_BATTERY_TECH_NiCd: + technology = POWER_SUPPLY_TECHNOLOGY_NiCd; + break; + case GB_BATTERY_TECH_LiMn: + technology = POWER_SUPPLY_TECHNOLOGY_LiMn; + break; + case GB_BATTERY_TECH_UNKNOWN: + default: + technology = POWER_SUPPLY_TECHNOLOGY_UNKNOWN; + break; + } + return technology; +} + +static int get_status(struct gb_battery *gb) +{ + struct gb_battery_status_response status_response; + u16 battery_status; + int retval; + + retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_STATUS, + NULL, 0, + &status_response, sizeof(status_response)); + if (retval) + return retval; + + /* + * Map greybus values to power_supply values. Hopefully these are + * "identical" which should allow gcc to optimize the code away to + * nothing. + */ + battery_status = le16_to_cpu(status_response.battery_status); + switch (battery_status) { + case GB_BATTERY_STATUS_CHARGING: + battery_status = POWER_SUPPLY_STATUS_CHARGING; + break; + case GB_BATTERY_STATUS_DISCHARGING: + battery_status = POWER_SUPPLY_STATUS_DISCHARGING; + break; + case GB_BATTERY_STATUS_NOT_CHARGING: + battery_status = POWER_SUPPLY_STATUS_NOT_CHARGING; + break; + case GB_BATTERY_STATUS_FULL: + battery_status = POWER_SUPPLY_STATUS_FULL; + break; + case GB_BATTERY_STATUS_UNKNOWN: + default: + battery_status = POWER_SUPPLY_STATUS_UNKNOWN; + break; + } + return battery_status; +} + +static int get_max_voltage(struct gb_battery *gb) +{ + struct gb_battery_max_voltage_response volt_response; + u32 max_voltage; + int retval; + + retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_MAX_VOLTAGE, + NULL, 0, + &volt_response, sizeof(volt_response)); + if (retval) + return retval; + + max_voltage = le32_to_cpu(volt_response.max_voltage); + return max_voltage; +} + +static int get_percent_capacity(struct gb_battery *gb) +{ + struct gb_battery_capacity_response capacity_response; + u32 capacity; + int retval; + + retval = gb_operation_sync(gb->connection, + GB_BATTERY_TYPE_PERCENT_CAPACITY, + NULL, 0, &capacity_response, + sizeof(capacity_response)); + if (retval) + return retval; + + capacity = le32_to_cpu(capacity_response.capacity); + return capacity; +} + +static int get_temp(struct gb_battery *gb) +{ + struct gb_battery_temperature_response temp_response; + u32 temperature; + int retval; + + retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_TEMPERATURE, + NULL, 0, + &temp_response, sizeof(temp_response)); + if (retval) + return retval; + + temperature = le32_to_cpu(temp_response.temperature); + return temperature; +} + +static int get_voltage(struct gb_battery *gb) +{ + struct gb_battery_voltage_response voltage_response; + u32 voltage; + int retval; + + retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_VOLTAGE, + NULL, 0, + &voltage_response, sizeof(voltage_response)); + if (retval) + return retval; + + voltage = le32_to_cpu(voltage_response.voltage); + return voltage; +} + +static int get_property(struct power_supply *b, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct gb_battery *gb = to_gb_battery(b); + + switch (psp) { + case POWER_SUPPLY_PROP_TECHNOLOGY: + val->intval = get_tech(gb); + break; + + case POWER_SUPPLY_PROP_STATUS: + val->intval = get_status(gb); + break; + + case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: + val->intval = get_max_voltage(gb); + break; + + case POWER_SUPPLY_PROP_CAPACITY: + val->intval = get_percent_capacity(gb); + break; + + case POWER_SUPPLY_PROP_TEMP: + val->intval = get_temp(gb); + break; + + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + val->intval = get_voltage(gb); + break; + + default: + return -EINVAL; + } + + return 0; +} + +// FIXME - verify this list, odds are some can be removed and others added. +static enum power_supply_property battery_props[] = { + POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, + POWER_SUPPLY_PROP_CAPACITY, + POWER_SUPPLY_PROP_TEMP, + POWER_SUPPLY_PROP_VOLTAGE_NOW, +}; + +static int gb_battery_connection_init(struct gb_connection *connection) +{ + struct gb_battery *gb; + struct power_supply *b; + int retval; + + gb = kzalloc(sizeof(*gb), GFP_KERNEL); + if (!gb) + return -ENOMEM; + + gb->connection = connection; + connection->private = gb; + + /* Check the version */ + retval = get_version(gb); + if (retval) { + kfree(gb); + return retval; + } + + b = &gb->bat; + // FIXME - get a better (i.e. unique) name + // FIXME - anything else needs to be set? + b->name = "gb_battery"; + b->type = POWER_SUPPLY_TYPE_BATTERY, + b->properties = battery_props, + b->num_properties = ARRAY_SIZE(battery_props), + b->get_property = get_property, + + retval = power_supply_register(&connection->bundle->intf->dev, b); + if (retval) { + kfree(gb); + return retval; + } + + return 0; +} + +static void gb_battery_connection_exit(struct gb_connection *connection) +{ + struct gb_battery *gb = connection->private; + + power_supply_unregister(&gb->bat); + kfree(gb); +} + +static struct gb_protocol battery_protocol = { + .name = "battery", + .id = GREYBUS_PROTOCOL_BATTERY, + .major = 0, + .minor = 1, + .connection_init = gb_battery_connection_init, + .connection_exit = gb_battery_connection_exit, + .request_recv = NULL, /* no incoming requests */ +}; + +gb_protocol_driver(&battery_protocol); + +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c new file mode 100644 index 0000000..2ec5d7b --- /dev/null +++ b/drivers/staging/greybus/es1.c @@ -0,0 +1,618 @@ +/* + * Greybus "AP" USB driver + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ +#include +#include +#include +#include +#include +#include + +#include "greybus.h" +#include "svc_msg.h" +#include "kernel_ver.h" + +/* + * Macros for making pointers explicitly opaque, such that the result + * isn't valid but also can't be mistaken for an ERR_PTR() value. + */ +#define conceal_urb(urb) ((void *)((uintptr_t)(urb) ^ 0xbad)) +#define reveal_urb(cookie) ((void *)((uintptr_t)(cookie) ^ 0xbad)) + +/* Memory sizes for the buffers sent to/from the ES1 controller */ +#define ES1_SVC_MSG_SIZE (sizeof(struct svc_msg) + SZ_64K) +#define ES1_GBUF_MSG_SIZE_MAX PAGE_SIZE + +static const struct usb_device_id id_table[] = { + /* Made up numbers for the SVC USB Bridge in ES1 */ + { USB_DEVICE(0xffff, 0x0001) }, + { }, +}; +MODULE_DEVICE_TABLE(usb, id_table); + +/* + * Number of CPort IN urbs in flight at any point in time. + * Adjust if we are having stalls in the USB buffer due to not enough urbs in + * flight. + */ +#define NUM_CPORT_IN_URB 4 + +/* Number of CPort OUT urbs in flight at any point in time. + * Adjust if we get messages saying we are out of urbs in the system log. + */ +#define NUM_CPORT_OUT_URB 8 + +/** + * es1_ap_dev - ES1 USB Bridge to AP structure + * @usb_dev: pointer to the USB device we are. + * @usb_intf: pointer to the USB interface we are bound to. + * @hd: pointer to our greybus_host_device structure + * @control_endpoint: endpoint to send data to SVC + * @svc_endpoint: endpoint for SVC data in + * @cport_in_endpoint: bulk in endpoint for CPort data + * @cport-out_endpoint: bulk out endpoint for CPort data + * @svc_buffer: buffer for SVC messages coming in on @svc_endpoint + * @svc_urb: urb for SVC messages coming in on @svc_endpoint + * @cport_in_urb: array of urbs for the CPort in messages + * @cport_in_buffer: array of buffers for the @cport_in_urb urbs + * @cport_out_urb: array of urbs for the CPort out messages + * @cport_out_urb_busy: array of flags to see if the @cport_out_urb is busy or + * not. + * @cport_out_urb_lock: locks the @cport_out_urb_busy "list" + */ +struct es1_ap_dev { + struct usb_device *usb_dev; + struct usb_interface *usb_intf; + struct greybus_host_device *hd; + + __u8 control_endpoint; + __u8 svc_endpoint; + __u8 cport_in_endpoint; + __u8 cport_out_endpoint; + + u8 *svc_buffer; + struct urb *svc_urb; + + struct urb *cport_in_urb[NUM_CPORT_IN_URB]; + u8 *cport_in_buffer[NUM_CPORT_IN_URB]; + struct urb *cport_out_urb[NUM_CPORT_OUT_URB]; + bool cport_out_urb_busy[NUM_CPORT_OUT_URB]; + spinlock_t cport_out_urb_lock; +}; + +static inline struct es1_ap_dev *hd_to_es1(struct greybus_host_device *hd) +{ + return (struct es1_ap_dev *)&hd->hd_priv; +} + +static void cport_out_callback(struct urb *urb); + +/* + * Buffer constraints for the host driver. + * + * A "buffer" is used to hold data to be transferred for Greybus by + * the host driver. A buffer is represented by a "buffer pointer", + * which defines a region of memory used by the host driver for + * transferring the data. When Greybus allocates a buffer, it must + * do so subject to the constraints associated with the host driver. + * These constraints are specified by two parameters: the + * headroom; and the maximum buffer size. + * + * +------------------+ + * | Host driver | \ + * | reserved area | }- headroom + * | . . . | / + * buffer pointer ---> +------------------+ + * | Buffer space for | \ + * | transferred data | }- buffer size + * | . . . | / (limited to size_max) + * +------------------+ + * + * headroom: Every buffer must have at least this much space + * *before* the buffer pointer, reserved for use by the + * host driver. I.e., ((char *)buffer - headroom) must + * point to valid memory, usable only by the host driver. + * size_max: The maximum size of a buffer (not including the + * headroom) must not exceed this. + */ +static void hd_buffer_constraints(struct greybus_host_device *hd) +{ + /* + * Only one byte is required, but this produces a result + * that's better aligned for the user. + */ + hd->buffer_headroom = sizeof(u32); /* For cport id */ + hd->buffer_size_max = ES1_GBUF_MSG_SIZE_MAX; + BUILD_BUG_ON(hd->buffer_headroom > GB_BUFFER_HEADROOM_MAX); +} + +#define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ +static int submit_svc(struct svc_msg *svc_msg, struct greybus_host_device *hd) +{ + struct es1_ap_dev *es1 = hd_to_es1(hd); + int retval; + + /* SVC messages go down our control pipe */ + retval = usb_control_msg(es1->usb_dev, + usb_sndctrlpipe(es1->usb_dev, + es1->control_endpoint), + 0x01, /* vendor request AP message */ + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + 0x00, 0x00, + (char *)svc_msg, + sizeof(*svc_msg), + ES1_TIMEOUT); + if (retval != sizeof(*svc_msg)) + return retval; + + return 0; +} + +static struct urb *next_free_urb(struct es1_ap_dev *es1, gfp_t gfp_mask) +{ + struct urb *urb = NULL; + unsigned long flags; + int i; + + spin_lock_irqsave(&es1->cport_out_urb_lock, flags); + + /* Look in our pool of allocated urbs first, as that's the "fastest" */ + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + if (es1->cport_out_urb_busy[i] == false) { + es1->cport_out_urb_busy[i] = true; + urb = es1->cport_out_urb[i]; + break; + } + } + spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); + if (urb) + return urb; + + /* + * Crap, pool is empty, complain to the syslog and go allocate one + * dynamically as we have to succeed. + */ + dev_err(&es1->usb_dev->dev, + "No free CPort OUT urbs, having to dynamically allocate one!\n"); + return usb_alloc_urb(0, gfp_mask); +} + +static void free_urb(struct es1_ap_dev *es1, struct urb *urb) +{ + unsigned long flags; + int i; + /* + * See if this was an urb in our pool, if so mark it "free", otherwise + * we need to free it ourselves. + */ + spin_lock_irqsave(&es1->cport_out_urb_lock, flags); + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + if (urb == es1->cport_out_urb[i]) { + es1->cport_out_urb_busy[i] = false; + urb = NULL; + break; + } + } + spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); + + /* If urb is not NULL, then we need to free this urb */ + usb_free_urb(urb); +} + +/* + * Returns an opaque cookie value if successful, or a pointer coded + * error otherwise. If the caller wishes to cancel the in-flight + * buffer, it must supply the returned cookie to the cancel routine. + */ +static void *buffer_send(struct greybus_host_device *hd, u16 cport_id, + void *buffer, size_t buffer_size, gfp_t gfp_mask) +{ + struct es1_ap_dev *es1 = hd_to_es1(hd); + struct usb_device *udev = es1->usb_dev; + u8 *transfer_buffer = buffer; + int transfer_buffer_size; + int retval; + struct urb *urb; + + if (!buffer) { + pr_err("null buffer supplied to send\n"); + return ERR_PTR(-EINVAL); + } + if (buffer_size > (size_t)INT_MAX) { + pr_err("bad buffer size (%zu) supplied to send\n", buffer_size); + return ERR_PTR(-EINVAL); + } + transfer_buffer--; + transfer_buffer_size = buffer_size + 1; + + /* + * The data actually transferred will include an indication + * of where the data should be sent. Do one last check of + * the target CPort id before filling it in. + */ + if (cport_id == CPORT_ID_BAD) { + pr_err("request to send inbound data buffer\n"); + return ERR_PTR(-EINVAL); + } + if (cport_id > (u16)U8_MAX) { + pr_err("cport_id (%hd) is out of range for ES1\n", cport_id); + return ERR_PTR(-EINVAL); + } + /* OK, the destination is fine; record it in the transfer buffer */ + *transfer_buffer = cport_id; + + /* Find a free urb */ + urb = next_free_urb(es1, gfp_mask); + if (!urb) + return ERR_PTR(-ENOMEM); + + usb_fill_bulk_urb(urb, udev, + usb_sndbulkpipe(udev, es1->cport_out_endpoint), + transfer_buffer, transfer_buffer_size, + cport_out_callback, hd); + retval = usb_submit_urb(urb, gfp_mask); + if (retval) { + pr_err("error %d submitting URB\n", retval); + free_urb(es1, urb); + return ERR_PTR(retval); + } + + return conceal_urb(urb); +} + +/* + * The cookie value supplied is the value that buffer_send() + * returned to its caller. It identifies the buffer that should be + * canceled. This function must also handle (which is to say, + * ignore) a null cookie value. + */ +static void buffer_cancel(void *cookie) +{ + + /* + * We really should be defensive and track all outstanding + * (sent) buffers rather than trusting the cookie provided + * is valid. For the time being, this will do. + */ + if (cookie) + usb_kill_urb(reveal_urb(cookie)); +} + +static struct greybus_host_driver es1_driver = { + .hd_priv_size = sizeof(struct es1_ap_dev), + .buffer_send = buffer_send, + .buffer_cancel = buffer_cancel, + .submit_svc = submit_svc, +}; + +/* Common function to report consistent warnings based on URB status */ +static int check_urb_status(struct urb *urb) +{ + struct device *dev = &urb->dev->dev; + int status = urb->status; + + switch (status) { + case 0: + return 0; + + case -EOVERFLOW: + dev_err(dev, "%s: overflow actual length is %d\n", + __func__, urb->actual_length); + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + case -EILSEQ: + case -EPROTO: + /* device is gone, stop sending */ + return status; + } + dev_err(dev, "%s: unknown status %d\n", __func__, status); + + return -EAGAIN; +} + +static void ap_disconnect(struct usb_interface *interface) +{ + struct es1_ap_dev *es1; + struct usb_device *udev; + int i; + + es1 = usb_get_intfdata(interface); + if (!es1) + return; + + /* Tear down everything! */ + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + struct urb *urb = es1->cport_out_urb[i]; + + if (!urb) + break; + usb_kill_urb(urb); + usb_free_urb(urb); + es1->cport_out_urb[i] = NULL; + es1->cport_out_urb_busy[i] = false; /* just to be anal */ + } + + for (i = 0; i < NUM_CPORT_IN_URB; ++i) { + struct urb *urb = es1->cport_in_urb[i]; + + if (!urb) + break; + usb_kill_urb(urb); + usb_free_urb(urb); + kfree(es1->cport_in_buffer[i]); + es1->cport_in_buffer[i] = NULL; + } + + usb_kill_urb(es1->svc_urb); + usb_free_urb(es1->svc_urb); + es1->svc_urb = NULL; + kfree(es1->svc_buffer); + es1->svc_buffer = NULL; + + usb_set_intfdata(interface, NULL); + udev = es1->usb_dev; + greybus_remove_hd(es1->hd); + + usb_put_dev(udev); +} + +/* Callback for when we get a SVC message */ +static void svc_in_callback(struct urb *urb) +{ + struct greybus_host_device *hd = urb->context; + struct device *dev = &urb->dev->dev; + int status = check_urb_status(urb); + int retval; + + if (status) { + if ((status == -EAGAIN) || (status == -EPROTO)) + goto exit; + dev_err(dev, "urb svc in error %d (dropped)\n", status); + return; + } + + /* We have a message, create a new message structure, add it to the + * list, and wake up our thread that will process the messages. + */ + greybus_svc_in(hd, urb->transfer_buffer, urb->actual_length); + +exit: + /* resubmit the urb to get more messages */ + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) + dev_err(dev, "Can not submit urb for AP data: %d\n", retval); +} + +static void cport_in_callback(struct urb *urb) +{ + struct greybus_host_device *hd = urb->context; + struct device *dev = &urb->dev->dev; + int status = check_urb_status(urb); + int retval; + u16 cport_id; + u8 *data; + + if (status) { + if ((status == -EAGAIN) || (status == -EPROTO)) + goto exit; + dev_err(dev, "urb cport in error %d (dropped)\n", status); + return; + } + + /* The size has to be at least one, for the cport id */ + if (!urb->actual_length) { + dev_err(dev, "%s: no cport id in input buffer?\n", __func__); + goto exit; + } + + /* + * Our CPort number is the first byte of the data stream, + * the rest of the stream is "real" data + */ + data = urb->transfer_buffer; + cport_id = (u16)data[0]; + data = &data[1]; + + /* Pass this data to the greybus core */ + greybus_data_rcvd(hd, cport_id, data, urb->actual_length - 1); + +exit: + /* put our urb back in the request pool */ + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) + dev_err(dev, "%s: error %d in submitting urb.\n", + __func__, retval); +} + +static void cport_out_callback(struct urb *urb) +{ + struct greybus_host_device *hd = urb->context; + struct es1_ap_dev *es1 = hd_to_es1(hd); + int status = check_urb_status(urb); + u8 *data = urb->transfer_buffer + 1; + + /* + * Tell the submitter that the buffer send (attempt) is + * complete, and report the status. The submitter's buffer + * starts after the one-byte CPort id we inserted. + */ + data = urb->transfer_buffer + 1; + greybus_data_sent(hd, data, status); + + free_urb(es1, urb); + /* + * Rest assured Greg, this craziness is getting fixed. + * + * Yes, you are right, we aren't telling anyone that the urb finished. + * "That's crazy! How does this all even work?" you might be saying. + * The "magic" is the idea that greybus works on the "operation" level, + * not the "send a buffer" level. All operations are "round-trip" with + * a response from the device that the operation finished, or it will + * time out. Because of that, we don't care that this urb finished, or + * failed, or did anything else, as higher levels of the protocol stack + * will handle completions and timeouts and the rest. + * + * This protocol is "needed" due to some hardware restrictions on the + * current generation of Unipro controllers. Think about it for a + * minute, this is a USB driver, talking to a Unipro bridge, impedance + * mismatch is huge, yet the Unipro controller are even more + * underpowered than this little USB controller. We rely on the round + * trip to keep stalls in the Unipro controllers from happening so that + * we can keep data flowing properly, no matter how slow it might be. + * + * Once again, a wonderful bus protocol cut down in its prime by a naive + * controller chip. We dream of the day we have a "real" HCD for + * Unipro. Until then, we suck it up and make the hardware work, as + * that's the job of the firmware and kernel. + * + */ +} + +/* + * The ES1 USB Bridge device contains 4 endpoints + * 1 Control - usual USB stuff + AP -> SVC messages + * 1 Interrupt IN - SVC -> AP messages + * 1 Bulk IN - CPort data in + * 1 Bulk OUT - CPort data out + */ +static int ap_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct es1_ap_dev *es1; + struct greybus_host_device *hd; + struct usb_device *udev; + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + bool int_in_found = false; + bool bulk_in_found = false; + bool bulk_out_found = false; + int retval = -ENOMEM; + int i; + u8 svc_interval = 0; + + udev = usb_get_dev(interface_to_usbdev(interface)); + + hd = greybus_create_hd(&es1_driver, &udev->dev); + if (!hd) { + usb_put_dev(udev); + return -ENOMEM; + } + + /* Fill in the buffer allocation constraints */ + hd_buffer_constraints(hd); + + es1 = hd_to_es1(hd); + es1->hd = hd; + es1->usb_intf = interface; + es1->usb_dev = udev; + spin_lock_init(&es1->cport_out_urb_lock); + usb_set_intfdata(interface, es1); + + /* Control endpoint is the pipe to talk to this AP, so save it off */ + endpoint = &udev->ep0.desc; + es1->control_endpoint = endpoint->bEndpointAddress; + + /* find all 3 of our endpoints */ + iface_desc = interface->cur_altsetting; + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i].desc; + + if (usb_endpoint_is_int_in(endpoint)) { + es1->svc_endpoint = endpoint->bEndpointAddress; + svc_interval = endpoint->bInterval; + int_in_found = true; + } else if (usb_endpoint_is_bulk_in(endpoint)) { + es1->cport_in_endpoint = endpoint->bEndpointAddress; + bulk_in_found = true; + } else if (usb_endpoint_is_bulk_out(endpoint)) { + es1->cport_out_endpoint = endpoint->bEndpointAddress; + bulk_out_found = true; + } else { + dev_err(&udev->dev, + "Unknown endpoint type found, address %x\n", + endpoint->bEndpointAddress); + } + } + if ((int_in_found == false) || + (bulk_in_found == false) || + (bulk_out_found == false)) { + dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n"); + goto error; + } + + /* Create our buffer and URB to get SVC messages, and start it up */ + es1->svc_buffer = kmalloc(ES1_SVC_MSG_SIZE, GFP_KERNEL); + if (!es1->svc_buffer) + goto error; + + es1->svc_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!es1->svc_urb) + goto error; + + usb_fill_int_urb(es1->svc_urb, udev, + usb_rcvintpipe(udev, es1->svc_endpoint), + es1->svc_buffer, ES1_SVC_MSG_SIZE, svc_in_callback, + hd, svc_interval); + retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); + if (retval) + goto error; + + /* Allocate buffers for our cport in messages and start them up */ + for (i = 0; i < NUM_CPORT_IN_URB; ++i) { + struct urb *urb; + u8 *buffer; + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) + goto error; + buffer = kmalloc(ES1_GBUF_MSG_SIZE_MAX, GFP_KERNEL); + if (!buffer) + goto error; + + usb_fill_bulk_urb(urb, udev, + usb_rcvbulkpipe(udev, es1->cport_in_endpoint), + buffer, ES1_GBUF_MSG_SIZE_MAX, + cport_in_callback, hd); + es1->cport_in_urb[i] = urb; + es1->cport_in_buffer[i] = buffer; + retval = usb_submit_urb(urb, GFP_KERNEL); + if (retval) + goto error; + } + + /* Allocate urbs for our CPort OUT messages */ + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + struct urb *urb; + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) + goto error; + + es1->cport_out_urb[i] = urb; + es1->cport_out_urb_busy[i] = false; /* just to be anal */ + } + + return 0; +error: + ap_disconnect(interface); + + return retval; +} + +static struct usb_driver es1_ap_driver = { + .name = "es1_ap_driver", + .probe = ap_probe, + .disconnect = ap_disconnect, + .id_table = id_table, +}; + +module_usb_driver(es1_ap_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Greg Kroah-Hartman "); diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c new file mode 100644 index 0000000..4154cce --- /dev/null +++ b/drivers/staging/greybus/es2.c @@ -0,0 +1,618 @@ +/* + * Greybus "AP" USB driver for "ES2" controller chips + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ +#include +#include +#include +#include +#include +#include + +#include "greybus.h" +#include "svc_msg.h" +#include "kernel_ver.h" + +/* + * Macros for making pointers explicitly opaque, such that the result + * isn't valid but also can't be mistaken for an ERR_PTR() value. + */ +#define conceal_urb(urb) ((void *)((uintptr_t)(urb) ^ 0xbad)) +#define reveal_urb(cookie) ((void *)((uintptr_t)(cookie) ^ 0xbad)) + +/* Memory sizes for the buffers sent to/from the ES1 controller */ +#define ES1_SVC_MSG_SIZE (sizeof(struct svc_msg) + SZ_64K) +#define ES1_GBUF_MSG_SIZE_MAX PAGE_SIZE + +static const struct usb_device_id id_table[] = { + /* Made up numbers for the SVC USB Bridge in ES1 */ + { USB_DEVICE(0xffff, 0x0001) }, + { }, +}; +MODULE_DEVICE_TABLE(usb, id_table); + +/* + * Number of CPort IN urbs in flight at any point in time. + * Adjust if we are having stalls in the USB buffer due to not enough urbs in + * flight. + */ +#define NUM_CPORT_IN_URB 4 + +/* Number of CPort OUT urbs in flight at any point in time. + * Adjust if we get messages saying we are out of urbs in the system log. + */ +#define NUM_CPORT_OUT_URB 8 + +/** + * es1_ap_dev - ES1 USB Bridge to AP structure + * @usb_dev: pointer to the USB device we are. + * @usb_intf: pointer to the USB interface we are bound to. + * @hd: pointer to our greybus_host_device structure + * @control_endpoint: endpoint to send data to SVC + * @svc_endpoint: endpoint for SVC data in + * @cport_in_endpoint: bulk in endpoint for CPort data + * @cport-out_endpoint: bulk out endpoint for CPort data + * @svc_buffer: buffer for SVC messages coming in on @svc_endpoint + * @svc_urb: urb for SVC messages coming in on @svc_endpoint + * @cport_in_urb: array of urbs for the CPort in messages + * @cport_in_buffer: array of buffers for the @cport_in_urb urbs + * @cport_out_urb: array of urbs for the CPort out messages + * @cport_out_urb_busy: array of flags to see if the @cport_out_urb is busy or + * not. + * @cport_out_urb_lock: locks the @cport_out_urb_busy "list" + */ +struct es1_ap_dev { + struct usb_device *usb_dev; + struct usb_interface *usb_intf; + struct greybus_host_device *hd; + + __u8 control_endpoint; + __u8 svc_endpoint; + __u8 cport_in_endpoint; + __u8 cport_out_endpoint; + + u8 *svc_buffer; + struct urb *svc_urb; + + struct urb *cport_in_urb[NUM_CPORT_IN_URB]; + u8 *cport_in_buffer[NUM_CPORT_IN_URB]; + struct urb *cport_out_urb[NUM_CPORT_OUT_URB]; + bool cport_out_urb_busy[NUM_CPORT_OUT_URB]; + spinlock_t cport_out_urb_lock; +}; + +static inline struct es1_ap_dev *hd_to_es1(struct greybus_host_device *hd) +{ + return (struct es1_ap_dev *)&hd->hd_priv; +} + +static void cport_out_callback(struct urb *urb); + +/* + * Buffer constraints for the host driver. + * + * A "buffer" is used to hold data to be transferred for Greybus by + * the host driver. A buffer is represented by a "buffer pointer", + * which defines a region of memory used by the host driver for + * transferring the data. When Greybus allocates a buffer, it must + * do so subject to the constraints associated with the host driver. + * These constraints are specified by two parameters: the + * headroom; and the maximum buffer size. + * + * +------------------+ + * | Host driver | \ + * | reserved area | }- headroom + * | . . . | / + * buffer pointer ---> +------------------+ + * | Buffer space for | \ + * | transferred data | }- buffer size + * | . . . | / (limited to size_max) + * +------------------+ + * + * headroom: Every buffer must have at least this much space + * *before* the buffer pointer, reserved for use by the + * host driver. I.e., ((char *)buffer - headroom) must + * point to valid memory, usable only by the host driver. + * size_max: The maximum size of a buffer (not including the + * headroom) must not exceed this. + */ +static void hd_buffer_constraints(struct greybus_host_device *hd) +{ + /* + * Only one byte is required, but this produces a result + * that's better aligned for the user. + */ + hd->buffer_headroom = sizeof(u32); /* For cport id */ + hd->buffer_size_max = ES1_GBUF_MSG_SIZE_MAX; + BUILD_BUG_ON(hd->buffer_headroom > GB_BUFFER_HEADROOM_MAX); +} + +#define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ +static int submit_svc(struct svc_msg *svc_msg, struct greybus_host_device *hd) +{ + struct es1_ap_dev *es1 = hd_to_es1(hd); + int retval; + + /* SVC messages go down our control pipe */ + retval = usb_control_msg(es1->usb_dev, + usb_sndctrlpipe(es1->usb_dev, + es1->control_endpoint), + 0x01, /* vendor request AP message */ + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + 0x00, 0x00, + (char *)svc_msg, + sizeof(*svc_msg), + ES1_TIMEOUT); + if (retval != sizeof(*svc_msg)) + return retval; + + return 0; +} + +static struct urb *next_free_urb(struct es1_ap_dev *es1, gfp_t gfp_mask) +{ + struct urb *urb = NULL; + unsigned long flags; + int i; + + spin_lock_irqsave(&es1->cport_out_urb_lock, flags); + + /* Look in our pool of allocated urbs first, as that's the "fastest" */ + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + if (es1->cport_out_urb_busy[i] == false) { + es1->cport_out_urb_busy[i] = true; + urb = es1->cport_out_urb[i]; + break; + } + } + spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); + if (urb) + return urb; + + /* + * Crap, pool is empty, complain to the syslog and go allocate one + * dynamically as we have to succeed. + */ + dev_err(&es1->usb_dev->dev, + "No free CPort OUT urbs, having to dynamically allocate one!\n"); + return usb_alloc_urb(0, gfp_mask); +} + +static void free_urb(struct es1_ap_dev *es1, struct urb *urb) +{ + unsigned long flags; + int i; + /* + * See if this was an urb in our pool, if so mark it "free", otherwise + * we need to free it ourselves. + */ + spin_lock_irqsave(&es1->cport_out_urb_lock, flags); + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + if (urb == es1->cport_out_urb[i]) { + es1->cport_out_urb_busy[i] = false; + urb = NULL; + break; + } + } + spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); + + /* If urb is not NULL, then we need to free this urb */ + usb_free_urb(urb); +} + +/* + * Returns an opaque cookie value if successful, or a pointer coded + * error otherwise. If the caller wishes to cancel the in-flight + * buffer, it must supply the returned cookie to the cancel routine. + */ +static void *buffer_send(struct greybus_host_device *hd, u16 cport_id, + void *buffer, size_t buffer_size, gfp_t gfp_mask) +{ + struct es1_ap_dev *es1 = hd_to_es1(hd); + struct usb_device *udev = es1->usb_dev; + u8 *transfer_buffer = buffer; + int transfer_buffer_size; + int retval; + struct urb *urb; + + if (!buffer) { + pr_err("null buffer supplied to send\n"); + return ERR_PTR(-EINVAL); + } + if (buffer_size > (size_t)INT_MAX) { + pr_err("bad buffer size (%zu) supplied to send\n", buffer_size); + return ERR_PTR(-EINVAL); + } + transfer_buffer--; + transfer_buffer_size = buffer_size + 1; + + /* + * The data actually transferred will include an indication + * of where the data should be sent. Do one last check of + * the target CPort id before filling it in. + */ + if (cport_id == CPORT_ID_BAD) { + pr_err("request to send inbound data buffer\n"); + return ERR_PTR(-EINVAL); + } + if (cport_id > (u16)U8_MAX) { + pr_err("cport_id (%hd) is out of range for ES1\n", cport_id); + return ERR_PTR(-EINVAL); + } + /* OK, the destination is fine; record it in the transfer buffer */ + *transfer_buffer = cport_id; + + /* Find a free urb */ + urb = next_free_urb(es1, gfp_mask); + if (!urb) + return ERR_PTR(-ENOMEM); + + usb_fill_bulk_urb(urb, udev, + usb_sndbulkpipe(udev, es1->cport_out_endpoint), + transfer_buffer, transfer_buffer_size, + cport_out_callback, hd); + retval = usb_submit_urb(urb, gfp_mask); + if (retval) { + pr_err("error %d submitting URB\n", retval); + free_urb(es1, urb); + return ERR_PTR(retval); + } + + return conceal_urb(urb); +} + +/* + * The cookie value supplied is the value that buffer_send() + * returned to its caller. It identifies the buffer that should be + * canceled. This function must also handle (which is to say, + * ignore) a null cookie value. + */ +static void buffer_cancel(void *cookie) +{ + + /* + * We really should be defensive and track all outstanding + * (sent) buffers rather than trusting the cookie provided + * is valid. For the time being, this will do. + */ + if (cookie) + usb_kill_urb(reveal_urb(cookie)); +} + +static struct greybus_host_driver es1_driver = { + .hd_priv_size = sizeof(struct es1_ap_dev), + .buffer_send = buffer_send, + .buffer_cancel = buffer_cancel, + .submit_svc = submit_svc, +}; + +/* Common function to report consistent warnings based on URB status */ +static int check_urb_status(struct urb *urb) +{ + struct device *dev = &urb->dev->dev; + int status = urb->status; + + switch (status) { + case 0: + return 0; + + case -EOVERFLOW: + dev_err(dev, "%s: overflow actual length is %d\n", + __func__, urb->actual_length); + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + case -EILSEQ: + case -EPROTO: + /* device is gone, stop sending */ + return status; + } + dev_err(dev, "%s: unknown status %d\n", __func__, status); + + return -EAGAIN; +} + +static void ap_disconnect(struct usb_interface *interface) +{ + struct es1_ap_dev *es1; + struct usb_device *udev; + int i; + + es1 = usb_get_intfdata(interface); + if (!es1) + return; + + /* Tear down everything! */ + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + struct urb *urb = es1->cport_out_urb[i]; + + if (!urb) + break; + usb_kill_urb(urb); + usb_free_urb(urb); + es1->cport_out_urb[i] = NULL; + es1->cport_out_urb_busy[i] = false; /* just to be anal */ + } + + for (i = 0; i < NUM_CPORT_IN_URB; ++i) { + struct urb *urb = es1->cport_in_urb[i]; + + if (!urb) + break; + usb_kill_urb(urb); + usb_free_urb(urb); + kfree(es1->cport_in_buffer[i]); + es1->cport_in_buffer[i] = NULL; + } + + usb_kill_urb(es1->svc_urb); + usb_free_urb(es1->svc_urb); + es1->svc_urb = NULL; + kfree(es1->svc_buffer); + es1->svc_buffer = NULL; + + usb_set_intfdata(interface, NULL); + udev = es1->usb_dev; + greybus_remove_hd(es1->hd); + + usb_put_dev(udev); +} + +/* Callback for when we get a SVC message */ +static void svc_in_callback(struct urb *urb) +{ + struct greybus_host_device *hd = urb->context; + struct device *dev = &urb->dev->dev; + int status = check_urb_status(urb); + int retval; + + if (status) { + if ((status == -EAGAIN) || (status == -EPROTO)) + goto exit; + dev_err(dev, "urb svc in error %d (dropped)\n", status); + return; + } + + /* We have a message, create a new message structure, add it to the + * list, and wake up our thread that will process the messages. + */ + greybus_svc_in(hd, urb->transfer_buffer, urb->actual_length); + +exit: + /* resubmit the urb to get more messages */ + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) + dev_err(dev, "Can not submit urb for AP data: %d\n", retval); +} + +static void cport_in_callback(struct urb *urb) +{ + struct greybus_host_device *hd = urb->context; + struct device *dev = &urb->dev->dev; + int status = check_urb_status(urb); + int retval; + u16 cport_id; + u8 *data; + + if (status) { + if ((status == -EAGAIN) || (status == -EPROTO)) + goto exit; + dev_err(dev, "urb cport in error %d (dropped)\n", status); + return; + } + + /* The size has to be at least one, for the cport id */ + if (!urb->actual_length) { + dev_err(dev, "%s: no cport id in input buffer?\n", __func__); + goto exit; + } + + /* + * Our CPort number is the first byte of the data stream, + * the rest of the stream is "real" data + */ + data = urb->transfer_buffer; + cport_id = (u16)data[0]; + data = &data[1]; + + /* Pass this data to the greybus core */ + greybus_data_rcvd(hd, cport_id, data, urb->actual_length - 1); + +exit: + /* put our urb back in the request pool */ + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) + dev_err(dev, "%s: error %d in submitting urb.\n", + __func__, retval); +} + +static void cport_out_callback(struct urb *urb) +{ + struct greybus_host_device *hd = urb->context; + struct es1_ap_dev *es1 = hd_to_es1(hd); + int status = check_urb_status(urb); + u8 *data = urb->transfer_buffer + 1; + + /* + * Tell the submitter that the buffer send (attempt) is + * complete, and report the status. The submitter's buffer + * starts after the one-byte CPort id we inserted. + */ + data = urb->transfer_buffer + 1; + greybus_data_sent(hd, data, status); + + free_urb(es1, urb); + /* + * Rest assured Greg, this craziness is getting fixed. + * + * Yes, you are right, we aren't telling anyone that the urb finished. + * "That's crazy! How does this all even work?" you might be saying. + * The "magic" is the idea that greybus works on the "operation" level, + * not the "send a buffer" level. All operations are "round-trip" with + * a response from the device that the operation finished, or it will + * time out. Because of that, we don't care that this urb finished, or + * failed, or did anything else, as higher levels of the protocol stack + * will handle completions and timeouts and the rest. + * + * This protocol is "needed" due to some hardware restrictions on the + * current generation of Unipro controllers. Think about it for a + * minute, this is a USB driver, talking to a Unipro bridge, impedance + * mismatch is huge, yet the Unipro controller are even more + * underpowered than this little USB controller. We rely on the round + * trip to keep stalls in the Unipro controllers from happening so that + * we can keep data flowing properly, no matter how slow it might be. + * + * Once again, a wonderful bus protocol cut down in its prime by a naive + * controller chip. We dream of the day we have a "real" HCD for + * Unipro. Until then, we suck it up and make the hardware work, as + * that's the job of the firmware and kernel. + * + */ +} + +/* + * The ES1 USB Bridge device contains 4 endpoints + * 1 Control - usual USB stuff + AP -> SVC messages + * 1 Interrupt IN - SVC -> AP messages + * 1 Bulk IN - CPort data in + * 1 Bulk OUT - CPort data out + */ +static int ap_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct es1_ap_dev *es1; + struct greybus_host_device *hd; + struct usb_device *udev; + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + bool int_in_found = false; + bool bulk_in_found = false; + bool bulk_out_found = false; + int retval = -ENOMEM; + int i; + u8 svc_interval = 0; + + udev = usb_get_dev(interface_to_usbdev(interface)); + + hd = greybus_create_hd(&es1_driver, &udev->dev); + if (!hd) { + usb_put_dev(udev); + return -ENOMEM; + } + + /* Fill in the buffer allocation constraints */ + hd_buffer_constraints(hd); + + es1 = hd_to_es1(hd); + es1->hd = hd; + es1->usb_intf = interface; + es1->usb_dev = udev; + spin_lock_init(&es1->cport_out_urb_lock); + usb_set_intfdata(interface, es1); + + /* Control endpoint is the pipe to talk to this AP, so save it off */ + endpoint = &udev->ep0.desc; + es1->control_endpoint = endpoint->bEndpointAddress; + + /* find all 3 of our endpoints */ + iface_desc = interface->cur_altsetting; + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i].desc; + + if (usb_endpoint_is_int_in(endpoint)) { + es1->svc_endpoint = endpoint->bEndpointAddress; + svc_interval = endpoint->bInterval; + int_in_found = true; + } else if (usb_endpoint_is_bulk_in(endpoint)) { + es1->cport_in_endpoint = endpoint->bEndpointAddress; + bulk_in_found = true; + } else if (usb_endpoint_is_bulk_out(endpoint)) { + es1->cport_out_endpoint = endpoint->bEndpointAddress; + bulk_out_found = true; + } else { + dev_err(&udev->dev, + "Unknown endpoint type found, address %x\n", + endpoint->bEndpointAddress); + } + } + if ((int_in_found == false) || + (bulk_in_found == false) || + (bulk_out_found == false)) { + dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n"); + goto error; + } + + /* Create our buffer and URB to get SVC messages, and start it up */ + es1->svc_buffer = kmalloc(ES1_SVC_MSG_SIZE, GFP_KERNEL); + if (!es1->svc_buffer) + goto error; + + es1->svc_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!es1->svc_urb) + goto error; + + usb_fill_int_urb(es1->svc_urb, udev, + usb_rcvintpipe(udev, es1->svc_endpoint), + es1->svc_buffer, ES1_SVC_MSG_SIZE, svc_in_callback, + hd, svc_interval); + retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); + if (retval) + goto error; + + /* Allocate buffers for our cport in messages and start them up */ + for (i = 0; i < NUM_CPORT_IN_URB; ++i) { + struct urb *urb; + u8 *buffer; + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) + goto error; + buffer = kmalloc(ES1_GBUF_MSG_SIZE_MAX, GFP_KERNEL); + if (!buffer) + goto error; + + usb_fill_bulk_urb(urb, udev, + usb_rcvbulkpipe(udev, es1->cport_in_endpoint), + buffer, ES1_GBUF_MSG_SIZE_MAX, + cport_in_callback, hd); + es1->cport_in_urb[i] = urb; + es1->cport_in_buffer[i] = buffer; + retval = usb_submit_urb(urb, GFP_KERNEL); + if (retval) + goto error; + } + + /* Allocate urbs for our CPort OUT messages */ + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + struct urb *urb; + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) + goto error; + + es1->cport_out_urb[i] = urb; + es1->cport_out_urb_busy[i] = false; /* just to be anal */ + } + + return 0; +error: + ap_disconnect(interface); + + return retval; +} + +static struct usb_driver es1_ap_driver = { + .name = "es1_ap_driver", + .probe = ap_probe, + .disconnect = ap_disconnect, + .id_table = id_table, +}; + +module_usb_driver(es1_ap_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Greg Kroah-Hartman "); diff --git a/drivers/staging/greybus/gb-battery.c b/drivers/staging/greybus/gb-battery.c deleted file mode 100644 index 2130d73..0000000 --- a/drivers/staging/greybus/gb-battery.c +++ /dev/null @@ -1,373 +0,0 @@ -/* - * Battery driver for a Greybus module. - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#include -#include -#include -#include -#include "greybus.h" - -struct gb_battery { - struct power_supply bat; - // FIXME - // we will want to keep the battery stats in here as we will be getting - // updates from the SVC "on the fly" so we don't have to always go ask - // the battery for some information. Hopefully... - struct gb_connection *connection; - u8 version_major; - u8 version_minor; - -}; -#define to_gb_battery(x) container_of(x, struct gb_battery, bat) - -/* Version of the Greybus battery protocol we support */ -#define GB_BATTERY_VERSION_MAJOR 0x00 -#define GB_BATTERY_VERSION_MINOR 0x01 - -/* Greybus battery request types */ -#define GB_BATTERY_TYPE_INVALID 0x00 -#define GB_BATTERY_TYPE_PROTOCOL_VERSION 0x01 -#define GB_BATTERY_TYPE_TECHNOLOGY 0x02 -#define GB_BATTERY_TYPE_STATUS 0x03 -#define GB_BATTERY_TYPE_MAX_VOLTAGE 0x04 -#define GB_BATTERY_TYPE_PERCENT_CAPACITY 0x05 -#define GB_BATTERY_TYPE_TEMPERATURE 0x06 -#define GB_BATTERY_TYPE_VOLTAGE 0x07 -#define GB_BATTERY_TYPE_CURRENT 0x08 -#define GB_BATTERY_TYPE_CAPACITY 0x09 // TODO - POWER_SUPPLY_PROP_CURRENT_MAX -#define GB_BATTERY_TYPE_SHUTDOWN_TEMP 0x0a // TODO - POWER_SUPPLY_PROP_TEMP_ALERT_MAX - -struct gb_battery_proto_version_response { - __u8 major; - __u8 minor; -}; - -/* Should match up with battery types in linux/power_supply.h */ -#define GB_BATTERY_TECH_UNKNOWN 0x0000 -#define GB_BATTERY_TECH_NiMH 0x0001 -#define GB_BATTERY_TECH_LION 0x0002 -#define GB_BATTERY_TECH_LIPO 0x0003 -#define GB_BATTERY_TECH_LiFe 0x0004 -#define GB_BATTERY_TECH_NiCd 0x0005 -#define GB_BATTERY_TECH_LiMn 0x0006 - -struct gb_battery_technology_response { - __le32 technology; -}; - -/* Should match up with battery status in linux/power_supply.h */ -#define GB_BATTERY_STATUS_UNKNOWN 0x0000 -#define GB_BATTERY_STATUS_CHARGING 0x0001 -#define GB_BATTERY_STATUS_DISCHARGING 0x0002 -#define GB_BATTERY_STATUS_NOT_CHARGING 0x0003 -#define GB_BATTERY_STATUS_FULL 0x0004 - -struct gb_battery_status_response { - __le16 battery_status; -}; - -struct gb_battery_max_voltage_response { - __le32 max_voltage; -}; - -struct gb_battery_capacity_response { - __le32 capacity; -}; - -struct gb_battery_temperature_response { - __le32 temperature; -}; - -struct gb_battery_voltage_response { - __le32 voltage; -}; - -/* - * This request only uses the connection field, and if successful, - * fills in the major and minor protocol version of the target. - */ -static int get_version(struct gb_battery *gb) -{ - struct gb_battery_proto_version_response version_response; - int retval; - - retval = gb_operation_sync(gb->connection, - GB_BATTERY_TYPE_PROTOCOL_VERSION, - NULL, 0, - &version_response, sizeof(version_response)); - if (retval) - return retval; - - if (version_response.major > GB_BATTERY_VERSION_MAJOR) { - pr_err("unsupported major version (%hhu > %hhu)\n", - version_response.major, GB_BATTERY_VERSION_MAJOR); - return -ENOTSUPP; - } - - gb->version_major = version_response.major; - gb->version_minor = version_response.minor; - return 0; -} - -static int get_tech(struct gb_battery *gb) -{ - struct gb_battery_technology_response tech_response; - u32 technology; - int retval; - - retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_TECHNOLOGY, - NULL, 0, - &tech_response, sizeof(tech_response)); - if (retval) - return retval; - - /* - * Map greybus values to power_supply values. Hopefully these are - * "identical" which should allow gcc to optimize the code away to - * nothing. - */ - technology = le32_to_cpu(tech_response.technology); - switch (technology) { - case GB_BATTERY_TECH_NiMH: - technology = POWER_SUPPLY_TECHNOLOGY_NiMH; - break; - case GB_BATTERY_TECH_LION: - technology = POWER_SUPPLY_TECHNOLOGY_LION; - break; - case GB_BATTERY_TECH_LIPO: - technology = POWER_SUPPLY_TECHNOLOGY_LIPO; - break; - case GB_BATTERY_TECH_LiFe: - technology = POWER_SUPPLY_TECHNOLOGY_LiFe; - break; - case GB_BATTERY_TECH_NiCd: - technology = POWER_SUPPLY_TECHNOLOGY_NiCd; - break; - case GB_BATTERY_TECH_LiMn: - technology = POWER_SUPPLY_TECHNOLOGY_LiMn; - break; - case GB_BATTERY_TECH_UNKNOWN: - default: - technology = POWER_SUPPLY_TECHNOLOGY_UNKNOWN; - break; - } - return technology; -} - -static int get_status(struct gb_battery *gb) -{ - struct gb_battery_status_response status_response; - u16 battery_status; - int retval; - - retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_STATUS, - NULL, 0, - &status_response, sizeof(status_response)); - if (retval) - return retval; - - /* - * Map greybus values to power_supply values. Hopefully these are - * "identical" which should allow gcc to optimize the code away to - * nothing. - */ - battery_status = le16_to_cpu(status_response.battery_status); - switch (battery_status) { - case GB_BATTERY_STATUS_CHARGING: - battery_status = POWER_SUPPLY_STATUS_CHARGING; - break; - case GB_BATTERY_STATUS_DISCHARGING: - battery_status = POWER_SUPPLY_STATUS_DISCHARGING; - break; - case GB_BATTERY_STATUS_NOT_CHARGING: - battery_status = POWER_SUPPLY_STATUS_NOT_CHARGING; - break; - case GB_BATTERY_STATUS_FULL: - battery_status = POWER_SUPPLY_STATUS_FULL; - break; - case GB_BATTERY_STATUS_UNKNOWN: - default: - battery_status = POWER_SUPPLY_STATUS_UNKNOWN; - break; - } - return battery_status; -} - -static int get_max_voltage(struct gb_battery *gb) -{ - struct gb_battery_max_voltage_response volt_response; - u32 max_voltage; - int retval; - - retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_MAX_VOLTAGE, - NULL, 0, - &volt_response, sizeof(volt_response)); - if (retval) - return retval; - - max_voltage = le32_to_cpu(volt_response.max_voltage); - return max_voltage; -} - -static int get_percent_capacity(struct gb_battery *gb) -{ - struct gb_battery_capacity_response capacity_response; - u32 capacity; - int retval; - - retval = gb_operation_sync(gb->connection, - GB_BATTERY_TYPE_PERCENT_CAPACITY, - NULL, 0, &capacity_response, - sizeof(capacity_response)); - if (retval) - return retval; - - capacity = le32_to_cpu(capacity_response.capacity); - return capacity; -} - -static int get_temp(struct gb_battery *gb) -{ - struct gb_battery_temperature_response temp_response; - u32 temperature; - int retval; - - retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_TEMPERATURE, - NULL, 0, - &temp_response, sizeof(temp_response)); - if (retval) - return retval; - - temperature = le32_to_cpu(temp_response.temperature); - return temperature; -} - -static int get_voltage(struct gb_battery *gb) -{ - struct gb_battery_voltage_response voltage_response; - u32 voltage; - int retval; - - retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_VOLTAGE, - NULL, 0, - &voltage_response, sizeof(voltage_response)); - if (retval) - return retval; - - voltage = le32_to_cpu(voltage_response.voltage); - return voltage; -} - -static int get_property(struct power_supply *b, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct gb_battery *gb = to_gb_battery(b); - - switch (psp) { - case POWER_SUPPLY_PROP_TECHNOLOGY: - val->intval = get_tech(gb); - break; - - case POWER_SUPPLY_PROP_STATUS: - val->intval = get_status(gb); - break; - - case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: - val->intval = get_max_voltage(gb); - break; - - case POWER_SUPPLY_PROP_CAPACITY: - val->intval = get_percent_capacity(gb); - break; - - case POWER_SUPPLY_PROP_TEMP: - val->intval = get_temp(gb); - break; - - case POWER_SUPPLY_PROP_VOLTAGE_NOW: - val->intval = get_voltage(gb); - break; - - default: - return -EINVAL; - } - - return 0; -} - -// FIXME - verify this list, odds are some can be removed and others added. -static enum power_supply_property battery_props[] = { - POWER_SUPPLY_PROP_TECHNOLOGY, - POWER_SUPPLY_PROP_STATUS, - POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, - POWER_SUPPLY_PROP_CAPACITY, - POWER_SUPPLY_PROP_TEMP, - POWER_SUPPLY_PROP_VOLTAGE_NOW, -}; - -static int gb_battery_connection_init(struct gb_connection *connection) -{ - struct gb_battery *gb; - struct power_supply *b; - int retval; - - gb = kzalloc(sizeof(*gb), GFP_KERNEL); - if (!gb) - return -ENOMEM; - - gb->connection = connection; - connection->private = gb; - - /* Check the version */ - retval = get_version(gb); - if (retval) { - kfree(gb); - return retval; - } - - b = &gb->bat; - // FIXME - get a better (i.e. unique) name - // FIXME - anything else needs to be set? - b->name = "gb_battery"; - b->type = POWER_SUPPLY_TYPE_BATTERY, - b->properties = battery_props, - b->num_properties = ARRAY_SIZE(battery_props), - b->get_property = get_property, - - retval = power_supply_register(&connection->bundle->intf->dev, b); - if (retval) { - kfree(gb); - return retval; - } - - return 0; -} - -static void gb_battery_connection_exit(struct gb_connection *connection) -{ - struct gb_battery *gb = connection->private; - - power_supply_unregister(&gb->bat); - kfree(gb); -} - -static struct gb_protocol battery_protocol = { - .name = "battery", - .id = GREYBUS_PROTOCOL_BATTERY, - .major = 0, - .minor = 1, - .connection_init = gb_battery_connection_init, - .connection_exit = gb_battery_connection_exit, - .request_recv = NULL, /* no incoming requests */ -}; - -gb_protocol_driver(&battery_protocol); - -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/gb-es1.c b/drivers/staging/greybus/gb-es1.c deleted file mode 100644 index 2ec5d7b..0000000 --- a/drivers/staging/greybus/gb-es1.c +++ /dev/null @@ -1,618 +0,0 @@ -/* - * Greybus "AP" USB driver - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - * - * Released under the GPLv2 only. - */ -#include -#include -#include -#include -#include -#include - -#include "greybus.h" -#include "svc_msg.h" -#include "kernel_ver.h" - -/* - * Macros for making pointers explicitly opaque, such that the result - * isn't valid but also can't be mistaken for an ERR_PTR() value. - */ -#define conceal_urb(urb) ((void *)((uintptr_t)(urb) ^ 0xbad)) -#define reveal_urb(cookie) ((void *)((uintptr_t)(cookie) ^ 0xbad)) - -/* Memory sizes for the buffers sent to/from the ES1 controller */ -#define ES1_SVC_MSG_SIZE (sizeof(struct svc_msg) + SZ_64K) -#define ES1_GBUF_MSG_SIZE_MAX PAGE_SIZE - -static const struct usb_device_id id_table[] = { - /* Made up numbers for the SVC USB Bridge in ES1 */ - { USB_DEVICE(0xffff, 0x0001) }, - { }, -}; -MODULE_DEVICE_TABLE(usb, id_table); - -/* - * Number of CPort IN urbs in flight at any point in time. - * Adjust if we are having stalls in the USB buffer due to not enough urbs in - * flight. - */ -#define NUM_CPORT_IN_URB 4 - -/* Number of CPort OUT urbs in flight at any point in time. - * Adjust if we get messages saying we are out of urbs in the system log. - */ -#define NUM_CPORT_OUT_URB 8 - -/** - * es1_ap_dev - ES1 USB Bridge to AP structure - * @usb_dev: pointer to the USB device we are. - * @usb_intf: pointer to the USB interface we are bound to. - * @hd: pointer to our greybus_host_device structure - * @control_endpoint: endpoint to send data to SVC - * @svc_endpoint: endpoint for SVC data in - * @cport_in_endpoint: bulk in endpoint for CPort data - * @cport-out_endpoint: bulk out endpoint for CPort data - * @svc_buffer: buffer for SVC messages coming in on @svc_endpoint - * @svc_urb: urb for SVC messages coming in on @svc_endpoint - * @cport_in_urb: array of urbs for the CPort in messages - * @cport_in_buffer: array of buffers for the @cport_in_urb urbs - * @cport_out_urb: array of urbs for the CPort out messages - * @cport_out_urb_busy: array of flags to see if the @cport_out_urb is busy or - * not. - * @cport_out_urb_lock: locks the @cport_out_urb_busy "list" - */ -struct es1_ap_dev { - struct usb_device *usb_dev; - struct usb_interface *usb_intf; - struct greybus_host_device *hd; - - __u8 control_endpoint; - __u8 svc_endpoint; - __u8 cport_in_endpoint; - __u8 cport_out_endpoint; - - u8 *svc_buffer; - struct urb *svc_urb; - - struct urb *cport_in_urb[NUM_CPORT_IN_URB]; - u8 *cport_in_buffer[NUM_CPORT_IN_URB]; - struct urb *cport_out_urb[NUM_CPORT_OUT_URB]; - bool cport_out_urb_busy[NUM_CPORT_OUT_URB]; - spinlock_t cport_out_urb_lock; -}; - -static inline struct es1_ap_dev *hd_to_es1(struct greybus_host_device *hd) -{ - return (struct es1_ap_dev *)&hd->hd_priv; -} - -static void cport_out_callback(struct urb *urb); - -/* - * Buffer constraints for the host driver. - * - * A "buffer" is used to hold data to be transferred for Greybus by - * the host driver. A buffer is represented by a "buffer pointer", - * which defines a region of memory used by the host driver for - * transferring the data. When Greybus allocates a buffer, it must - * do so subject to the constraints associated with the host driver. - * These constraints are specified by two parameters: the - * headroom; and the maximum buffer size. - * - * +------------------+ - * | Host driver | \ - * | reserved area | }- headroom - * | . . . | / - * buffer pointer ---> +------------------+ - * | Buffer space for | \ - * | transferred data | }- buffer size - * | . . . | / (limited to size_max) - * +------------------+ - * - * headroom: Every buffer must have at least this much space - * *before* the buffer pointer, reserved for use by the - * host driver. I.e., ((char *)buffer - headroom) must - * point to valid memory, usable only by the host driver. - * size_max: The maximum size of a buffer (not including the - * headroom) must not exceed this. - */ -static void hd_buffer_constraints(struct greybus_host_device *hd) -{ - /* - * Only one byte is required, but this produces a result - * that's better aligned for the user. - */ - hd->buffer_headroom = sizeof(u32); /* For cport id */ - hd->buffer_size_max = ES1_GBUF_MSG_SIZE_MAX; - BUILD_BUG_ON(hd->buffer_headroom > GB_BUFFER_HEADROOM_MAX); -} - -#define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ -static int submit_svc(struct svc_msg *svc_msg, struct greybus_host_device *hd) -{ - struct es1_ap_dev *es1 = hd_to_es1(hd); - int retval; - - /* SVC messages go down our control pipe */ - retval = usb_control_msg(es1->usb_dev, - usb_sndctrlpipe(es1->usb_dev, - es1->control_endpoint), - 0x01, /* vendor request AP message */ - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - 0x00, 0x00, - (char *)svc_msg, - sizeof(*svc_msg), - ES1_TIMEOUT); - if (retval != sizeof(*svc_msg)) - return retval; - - return 0; -} - -static struct urb *next_free_urb(struct es1_ap_dev *es1, gfp_t gfp_mask) -{ - struct urb *urb = NULL; - unsigned long flags; - int i; - - spin_lock_irqsave(&es1->cport_out_urb_lock, flags); - - /* Look in our pool of allocated urbs first, as that's the "fastest" */ - for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - if (es1->cport_out_urb_busy[i] == false) { - es1->cport_out_urb_busy[i] = true; - urb = es1->cport_out_urb[i]; - break; - } - } - spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); - if (urb) - return urb; - - /* - * Crap, pool is empty, complain to the syslog and go allocate one - * dynamically as we have to succeed. - */ - dev_err(&es1->usb_dev->dev, - "No free CPort OUT urbs, having to dynamically allocate one!\n"); - return usb_alloc_urb(0, gfp_mask); -} - -static void free_urb(struct es1_ap_dev *es1, struct urb *urb) -{ - unsigned long flags; - int i; - /* - * See if this was an urb in our pool, if so mark it "free", otherwise - * we need to free it ourselves. - */ - spin_lock_irqsave(&es1->cport_out_urb_lock, flags); - for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - if (urb == es1->cport_out_urb[i]) { - es1->cport_out_urb_busy[i] = false; - urb = NULL; - break; - } - } - spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); - - /* If urb is not NULL, then we need to free this urb */ - usb_free_urb(urb); -} - -/* - * Returns an opaque cookie value if successful, or a pointer coded - * error otherwise. If the caller wishes to cancel the in-flight - * buffer, it must supply the returned cookie to the cancel routine. - */ -static void *buffer_send(struct greybus_host_device *hd, u16 cport_id, - void *buffer, size_t buffer_size, gfp_t gfp_mask) -{ - struct es1_ap_dev *es1 = hd_to_es1(hd); - struct usb_device *udev = es1->usb_dev; - u8 *transfer_buffer = buffer; - int transfer_buffer_size; - int retval; - struct urb *urb; - - if (!buffer) { - pr_err("null buffer supplied to send\n"); - return ERR_PTR(-EINVAL); - } - if (buffer_size > (size_t)INT_MAX) { - pr_err("bad buffer size (%zu) supplied to send\n", buffer_size); - return ERR_PTR(-EINVAL); - } - transfer_buffer--; - transfer_buffer_size = buffer_size + 1; - - /* - * The data actually transferred will include an indication - * of where the data should be sent. Do one last check of - * the target CPort id before filling it in. - */ - if (cport_id == CPORT_ID_BAD) { - pr_err("request to send inbound data buffer\n"); - return ERR_PTR(-EINVAL); - } - if (cport_id > (u16)U8_MAX) { - pr_err("cport_id (%hd) is out of range for ES1\n", cport_id); - return ERR_PTR(-EINVAL); - } - /* OK, the destination is fine; record it in the transfer buffer */ - *transfer_buffer = cport_id; - - /* Find a free urb */ - urb = next_free_urb(es1, gfp_mask); - if (!urb) - return ERR_PTR(-ENOMEM); - - usb_fill_bulk_urb(urb, udev, - usb_sndbulkpipe(udev, es1->cport_out_endpoint), - transfer_buffer, transfer_buffer_size, - cport_out_callback, hd); - retval = usb_submit_urb(urb, gfp_mask); - if (retval) { - pr_err("error %d submitting URB\n", retval); - free_urb(es1, urb); - return ERR_PTR(retval); - } - - return conceal_urb(urb); -} - -/* - * The cookie value supplied is the value that buffer_send() - * returned to its caller. It identifies the buffer that should be - * canceled. This function must also handle (which is to say, - * ignore) a null cookie value. - */ -static void buffer_cancel(void *cookie) -{ - - /* - * We really should be defensive and track all outstanding - * (sent) buffers rather than trusting the cookie provided - * is valid. For the time being, this will do. - */ - if (cookie) - usb_kill_urb(reveal_urb(cookie)); -} - -static struct greybus_host_driver es1_driver = { - .hd_priv_size = sizeof(struct es1_ap_dev), - .buffer_send = buffer_send, - .buffer_cancel = buffer_cancel, - .submit_svc = submit_svc, -}; - -/* Common function to report consistent warnings based on URB status */ -static int check_urb_status(struct urb *urb) -{ - struct device *dev = &urb->dev->dev; - int status = urb->status; - - switch (status) { - case 0: - return 0; - - case -EOVERFLOW: - dev_err(dev, "%s: overflow actual length is %d\n", - __func__, urb->actual_length); - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - case -EILSEQ: - case -EPROTO: - /* device is gone, stop sending */ - return status; - } - dev_err(dev, "%s: unknown status %d\n", __func__, status); - - return -EAGAIN; -} - -static void ap_disconnect(struct usb_interface *interface) -{ - struct es1_ap_dev *es1; - struct usb_device *udev; - int i; - - es1 = usb_get_intfdata(interface); - if (!es1) - return; - - /* Tear down everything! */ - for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - struct urb *urb = es1->cport_out_urb[i]; - - if (!urb) - break; - usb_kill_urb(urb); - usb_free_urb(urb); - es1->cport_out_urb[i] = NULL; - es1->cport_out_urb_busy[i] = false; /* just to be anal */ - } - - for (i = 0; i < NUM_CPORT_IN_URB; ++i) { - struct urb *urb = es1->cport_in_urb[i]; - - if (!urb) - break; - usb_kill_urb(urb); - usb_free_urb(urb); - kfree(es1->cport_in_buffer[i]); - es1->cport_in_buffer[i] = NULL; - } - - usb_kill_urb(es1->svc_urb); - usb_free_urb(es1->svc_urb); - es1->svc_urb = NULL; - kfree(es1->svc_buffer); - es1->svc_buffer = NULL; - - usb_set_intfdata(interface, NULL); - udev = es1->usb_dev; - greybus_remove_hd(es1->hd); - - usb_put_dev(udev); -} - -/* Callback for when we get a SVC message */ -static void svc_in_callback(struct urb *urb) -{ - struct greybus_host_device *hd = urb->context; - struct device *dev = &urb->dev->dev; - int status = check_urb_status(urb); - int retval; - - if (status) { - if ((status == -EAGAIN) || (status == -EPROTO)) - goto exit; - dev_err(dev, "urb svc in error %d (dropped)\n", status); - return; - } - - /* We have a message, create a new message structure, add it to the - * list, and wake up our thread that will process the messages. - */ - greybus_svc_in(hd, urb->transfer_buffer, urb->actual_length); - -exit: - /* resubmit the urb to get more messages */ - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - dev_err(dev, "Can not submit urb for AP data: %d\n", retval); -} - -static void cport_in_callback(struct urb *urb) -{ - struct greybus_host_device *hd = urb->context; - struct device *dev = &urb->dev->dev; - int status = check_urb_status(urb); - int retval; - u16 cport_id; - u8 *data; - - if (status) { - if ((status == -EAGAIN) || (status == -EPROTO)) - goto exit; - dev_err(dev, "urb cport in error %d (dropped)\n", status); - return; - } - - /* The size has to be at least one, for the cport id */ - if (!urb->actual_length) { - dev_err(dev, "%s: no cport id in input buffer?\n", __func__); - goto exit; - } - - /* - * Our CPort number is the first byte of the data stream, - * the rest of the stream is "real" data - */ - data = urb->transfer_buffer; - cport_id = (u16)data[0]; - data = &data[1]; - - /* Pass this data to the greybus core */ - greybus_data_rcvd(hd, cport_id, data, urb->actual_length - 1); - -exit: - /* put our urb back in the request pool */ - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - dev_err(dev, "%s: error %d in submitting urb.\n", - __func__, retval); -} - -static void cport_out_callback(struct urb *urb) -{ - struct greybus_host_device *hd = urb->context; - struct es1_ap_dev *es1 = hd_to_es1(hd); - int status = check_urb_status(urb); - u8 *data = urb->transfer_buffer + 1; - - /* - * Tell the submitter that the buffer send (attempt) is - * complete, and report the status. The submitter's buffer - * starts after the one-byte CPort id we inserted. - */ - data = urb->transfer_buffer + 1; - greybus_data_sent(hd, data, status); - - free_urb(es1, urb); - /* - * Rest assured Greg, this craziness is getting fixed. - * - * Yes, you are right, we aren't telling anyone that the urb finished. - * "That's crazy! How does this all even work?" you might be saying. - * The "magic" is the idea that greybus works on the "operation" level, - * not the "send a buffer" level. All operations are "round-trip" with - * a response from the device that the operation finished, or it will - * time out. Because of that, we don't care that this urb finished, or - * failed, or did anything else, as higher levels of the protocol stack - * will handle completions and timeouts and the rest. - * - * This protocol is "needed" due to some hardware restrictions on the - * current generation of Unipro controllers. Think about it for a - * minute, this is a USB driver, talking to a Unipro bridge, impedance - * mismatch is huge, yet the Unipro controller are even more - * underpowered than this little USB controller. We rely on the round - * trip to keep stalls in the Unipro controllers from happening so that - * we can keep data flowing properly, no matter how slow it might be. - * - * Once again, a wonderful bus protocol cut down in its prime by a naive - * controller chip. We dream of the day we have a "real" HCD for - * Unipro. Until then, we suck it up and make the hardware work, as - * that's the job of the firmware and kernel. - * - */ -} - -/* - * The ES1 USB Bridge device contains 4 endpoints - * 1 Control - usual USB stuff + AP -> SVC messages - * 1 Interrupt IN - SVC -> AP messages - * 1 Bulk IN - CPort data in - * 1 Bulk OUT - CPort data out - */ -static int ap_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct es1_ap_dev *es1; - struct greybus_host_device *hd; - struct usb_device *udev; - struct usb_host_interface *iface_desc; - struct usb_endpoint_descriptor *endpoint; - bool int_in_found = false; - bool bulk_in_found = false; - bool bulk_out_found = false; - int retval = -ENOMEM; - int i; - u8 svc_interval = 0; - - udev = usb_get_dev(interface_to_usbdev(interface)); - - hd = greybus_create_hd(&es1_driver, &udev->dev); - if (!hd) { - usb_put_dev(udev); - return -ENOMEM; - } - - /* Fill in the buffer allocation constraints */ - hd_buffer_constraints(hd); - - es1 = hd_to_es1(hd); - es1->hd = hd; - es1->usb_intf = interface; - es1->usb_dev = udev; - spin_lock_init(&es1->cport_out_urb_lock); - usb_set_intfdata(interface, es1); - - /* Control endpoint is the pipe to talk to this AP, so save it off */ - endpoint = &udev->ep0.desc; - es1->control_endpoint = endpoint->bEndpointAddress; - - /* find all 3 of our endpoints */ - iface_desc = interface->cur_altsetting; - for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { - endpoint = &iface_desc->endpoint[i].desc; - - if (usb_endpoint_is_int_in(endpoint)) { - es1->svc_endpoint = endpoint->bEndpointAddress; - svc_interval = endpoint->bInterval; - int_in_found = true; - } else if (usb_endpoint_is_bulk_in(endpoint)) { - es1->cport_in_endpoint = endpoint->bEndpointAddress; - bulk_in_found = true; - } else if (usb_endpoint_is_bulk_out(endpoint)) { - es1->cport_out_endpoint = endpoint->bEndpointAddress; - bulk_out_found = true; - } else { - dev_err(&udev->dev, - "Unknown endpoint type found, address %x\n", - endpoint->bEndpointAddress); - } - } - if ((int_in_found == false) || - (bulk_in_found == false) || - (bulk_out_found == false)) { - dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n"); - goto error; - } - - /* Create our buffer and URB to get SVC messages, and start it up */ - es1->svc_buffer = kmalloc(ES1_SVC_MSG_SIZE, GFP_KERNEL); - if (!es1->svc_buffer) - goto error; - - es1->svc_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!es1->svc_urb) - goto error; - - usb_fill_int_urb(es1->svc_urb, udev, - usb_rcvintpipe(udev, es1->svc_endpoint), - es1->svc_buffer, ES1_SVC_MSG_SIZE, svc_in_callback, - hd, svc_interval); - retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); - if (retval) - goto error; - - /* Allocate buffers for our cport in messages and start them up */ - for (i = 0; i < NUM_CPORT_IN_URB; ++i) { - struct urb *urb; - u8 *buffer; - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) - goto error; - buffer = kmalloc(ES1_GBUF_MSG_SIZE_MAX, GFP_KERNEL); - if (!buffer) - goto error; - - usb_fill_bulk_urb(urb, udev, - usb_rcvbulkpipe(udev, es1->cport_in_endpoint), - buffer, ES1_GBUF_MSG_SIZE_MAX, - cport_in_callback, hd); - es1->cport_in_urb[i] = urb; - es1->cport_in_buffer[i] = buffer; - retval = usb_submit_urb(urb, GFP_KERNEL); - if (retval) - goto error; - } - - /* Allocate urbs for our CPort OUT messages */ - for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - struct urb *urb; - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) - goto error; - - es1->cport_out_urb[i] = urb; - es1->cport_out_urb_busy[i] = false; /* just to be anal */ - } - - return 0; -error: - ap_disconnect(interface); - - return retval; -} - -static struct usb_driver es1_ap_driver = { - .name = "es1_ap_driver", - .probe = ap_probe, - .disconnect = ap_disconnect, - .id_table = id_table, -}; - -module_usb_driver(es1_ap_driver); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Greg Kroah-Hartman "); diff --git a/drivers/staging/greybus/gb-es2.c b/drivers/staging/greybus/gb-es2.c deleted file mode 100644 index 4154cce..0000000 --- a/drivers/staging/greybus/gb-es2.c +++ /dev/null @@ -1,618 +0,0 @@ -/* - * Greybus "AP" USB driver for "ES2" controller chips - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - * - * Released under the GPLv2 only. - */ -#include -#include -#include -#include -#include -#include - -#include "greybus.h" -#include "svc_msg.h" -#include "kernel_ver.h" - -/* - * Macros for making pointers explicitly opaque, such that the result - * isn't valid but also can't be mistaken for an ERR_PTR() value. - */ -#define conceal_urb(urb) ((void *)((uintptr_t)(urb) ^ 0xbad)) -#define reveal_urb(cookie) ((void *)((uintptr_t)(cookie) ^ 0xbad)) - -/* Memory sizes for the buffers sent to/from the ES1 controller */ -#define ES1_SVC_MSG_SIZE (sizeof(struct svc_msg) + SZ_64K) -#define ES1_GBUF_MSG_SIZE_MAX PAGE_SIZE - -static const struct usb_device_id id_table[] = { - /* Made up numbers for the SVC USB Bridge in ES1 */ - { USB_DEVICE(0xffff, 0x0001) }, - { }, -}; -MODULE_DEVICE_TABLE(usb, id_table); - -/* - * Number of CPort IN urbs in flight at any point in time. - * Adjust if we are having stalls in the USB buffer due to not enough urbs in - * flight. - */ -#define NUM_CPORT_IN_URB 4 - -/* Number of CPort OUT urbs in flight at any point in time. - * Adjust if we get messages saying we are out of urbs in the system log. - */ -#define NUM_CPORT_OUT_URB 8 - -/** - * es1_ap_dev - ES1 USB Bridge to AP structure - * @usb_dev: pointer to the USB device we are. - * @usb_intf: pointer to the USB interface we are bound to. - * @hd: pointer to our greybus_host_device structure - * @control_endpoint: endpoint to send data to SVC - * @svc_endpoint: endpoint for SVC data in - * @cport_in_endpoint: bulk in endpoint for CPort data - * @cport-out_endpoint: bulk out endpoint for CPort data - * @svc_buffer: buffer for SVC messages coming in on @svc_endpoint - * @svc_urb: urb for SVC messages coming in on @svc_endpoint - * @cport_in_urb: array of urbs for the CPort in messages - * @cport_in_buffer: array of buffers for the @cport_in_urb urbs - * @cport_out_urb: array of urbs for the CPort out messages - * @cport_out_urb_busy: array of flags to see if the @cport_out_urb is busy or - * not. - * @cport_out_urb_lock: locks the @cport_out_urb_busy "list" - */ -struct es1_ap_dev { - struct usb_device *usb_dev; - struct usb_interface *usb_intf; - struct greybus_host_device *hd; - - __u8 control_endpoint; - __u8 svc_endpoint; - __u8 cport_in_endpoint; - __u8 cport_out_endpoint; - - u8 *svc_buffer; - struct urb *svc_urb; - - struct urb *cport_in_urb[NUM_CPORT_IN_URB]; - u8 *cport_in_buffer[NUM_CPORT_IN_URB]; - struct urb *cport_out_urb[NUM_CPORT_OUT_URB]; - bool cport_out_urb_busy[NUM_CPORT_OUT_URB]; - spinlock_t cport_out_urb_lock; -}; - -static inline struct es1_ap_dev *hd_to_es1(struct greybus_host_device *hd) -{ - return (struct es1_ap_dev *)&hd->hd_priv; -} - -static void cport_out_callback(struct urb *urb); - -/* - * Buffer constraints for the host driver. - * - * A "buffer" is used to hold data to be transferred for Greybus by - * the host driver. A buffer is represented by a "buffer pointer", - * which defines a region of memory used by the host driver for - * transferring the data. When Greybus allocates a buffer, it must - * do so subject to the constraints associated with the host driver. - * These constraints are specified by two parameters: the - * headroom; and the maximum buffer size. - * - * +------------------+ - * | Host driver | \ - * | reserved area | }- headroom - * | . . . | / - * buffer pointer ---> +------------------+ - * | Buffer space for | \ - * | transferred data | }- buffer size - * | . . . | / (limited to size_max) - * +------------------+ - * - * headroom: Every buffer must have at least this much space - * *before* the buffer pointer, reserved for use by the - * host driver. I.e., ((char *)buffer - headroom) must - * point to valid memory, usable only by the host driver. - * size_max: The maximum size of a buffer (not including the - * headroom) must not exceed this. - */ -static void hd_buffer_constraints(struct greybus_host_device *hd) -{ - /* - * Only one byte is required, but this produces a result - * that's better aligned for the user. - */ - hd->buffer_headroom = sizeof(u32); /* For cport id */ - hd->buffer_size_max = ES1_GBUF_MSG_SIZE_MAX; - BUILD_BUG_ON(hd->buffer_headroom > GB_BUFFER_HEADROOM_MAX); -} - -#define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ -static int submit_svc(struct svc_msg *svc_msg, struct greybus_host_device *hd) -{ - struct es1_ap_dev *es1 = hd_to_es1(hd); - int retval; - - /* SVC messages go down our control pipe */ - retval = usb_control_msg(es1->usb_dev, - usb_sndctrlpipe(es1->usb_dev, - es1->control_endpoint), - 0x01, /* vendor request AP message */ - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - 0x00, 0x00, - (char *)svc_msg, - sizeof(*svc_msg), - ES1_TIMEOUT); - if (retval != sizeof(*svc_msg)) - return retval; - - return 0; -} - -static struct urb *next_free_urb(struct es1_ap_dev *es1, gfp_t gfp_mask) -{ - struct urb *urb = NULL; - unsigned long flags; - int i; - - spin_lock_irqsave(&es1->cport_out_urb_lock, flags); - - /* Look in our pool of allocated urbs first, as that's the "fastest" */ - for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - if (es1->cport_out_urb_busy[i] == false) { - es1->cport_out_urb_busy[i] = true; - urb = es1->cport_out_urb[i]; - break; - } - } - spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); - if (urb) - return urb; - - /* - * Crap, pool is empty, complain to the syslog and go allocate one - * dynamically as we have to succeed. - */ - dev_err(&es1->usb_dev->dev, - "No free CPort OUT urbs, having to dynamically allocate one!\n"); - return usb_alloc_urb(0, gfp_mask); -} - -static void free_urb(struct es1_ap_dev *es1, struct urb *urb) -{ - unsigned long flags; - int i; - /* - * See if this was an urb in our pool, if so mark it "free", otherwise - * we need to free it ourselves. - */ - spin_lock_irqsave(&es1->cport_out_urb_lock, flags); - for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - if (urb == es1->cport_out_urb[i]) { - es1->cport_out_urb_busy[i] = false; - urb = NULL; - break; - } - } - spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); - - /* If urb is not NULL, then we need to free this urb */ - usb_free_urb(urb); -} - -/* - * Returns an opaque cookie value if successful, or a pointer coded - * error otherwise. If the caller wishes to cancel the in-flight - * buffer, it must supply the returned cookie to the cancel routine. - */ -static void *buffer_send(struct greybus_host_device *hd, u16 cport_id, - void *buffer, size_t buffer_size, gfp_t gfp_mask) -{ - struct es1_ap_dev *es1 = hd_to_es1(hd); - struct usb_device *udev = es1->usb_dev; - u8 *transfer_buffer = buffer; - int transfer_buffer_size; - int retval; - struct urb *urb; - - if (!buffer) { - pr_err("null buffer supplied to send\n"); - return ERR_PTR(-EINVAL); - } - if (buffer_size > (size_t)INT_MAX) { - pr_err("bad buffer size (%zu) supplied to send\n", buffer_size); - return ERR_PTR(-EINVAL); - } - transfer_buffer--; - transfer_buffer_size = buffer_size + 1; - - /* - * The data actually transferred will include an indication - * of where the data should be sent. Do one last check of - * the target CPort id before filling it in. - */ - if (cport_id == CPORT_ID_BAD) { - pr_err("request to send inbound data buffer\n"); - return ERR_PTR(-EINVAL); - } - if (cport_id > (u16)U8_MAX) { - pr_err("cport_id (%hd) is out of range for ES1\n", cport_id); - return ERR_PTR(-EINVAL); - } - /* OK, the destination is fine; record it in the transfer buffer */ - *transfer_buffer = cport_id; - - /* Find a free urb */ - urb = next_free_urb(es1, gfp_mask); - if (!urb) - return ERR_PTR(-ENOMEM); - - usb_fill_bulk_urb(urb, udev, - usb_sndbulkpipe(udev, es1->cport_out_endpoint), - transfer_buffer, transfer_buffer_size, - cport_out_callback, hd); - retval = usb_submit_urb(urb, gfp_mask); - if (retval) { - pr_err("error %d submitting URB\n", retval); - free_urb(es1, urb); - return ERR_PTR(retval); - } - - return conceal_urb(urb); -} - -/* - * The cookie value supplied is the value that buffer_send() - * returned to its caller. It identifies the buffer that should be - * canceled. This function must also handle (which is to say, - * ignore) a null cookie value. - */ -static void buffer_cancel(void *cookie) -{ - - /* - * We really should be defensive and track all outstanding - * (sent) buffers rather than trusting the cookie provided - * is valid. For the time being, this will do. - */ - if (cookie) - usb_kill_urb(reveal_urb(cookie)); -} - -static struct greybus_host_driver es1_driver = { - .hd_priv_size = sizeof(struct es1_ap_dev), - .buffer_send = buffer_send, - .buffer_cancel = buffer_cancel, - .submit_svc = submit_svc, -}; - -/* Common function to report consistent warnings based on URB status */ -static int check_urb_status(struct urb *urb) -{ - struct device *dev = &urb->dev->dev; - int status = urb->status; - - switch (status) { - case 0: - return 0; - - case -EOVERFLOW: - dev_err(dev, "%s: overflow actual length is %d\n", - __func__, urb->actual_length); - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - case -EILSEQ: - case -EPROTO: - /* device is gone, stop sending */ - return status; - } - dev_err(dev, "%s: unknown status %d\n", __func__, status); - - return -EAGAIN; -} - -static void ap_disconnect(struct usb_interface *interface) -{ - struct es1_ap_dev *es1; - struct usb_device *udev; - int i; - - es1 = usb_get_intfdata(interface); - if (!es1) - return; - - /* Tear down everything! */ - for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - struct urb *urb = es1->cport_out_urb[i]; - - if (!urb) - break; - usb_kill_urb(urb); - usb_free_urb(urb); - es1->cport_out_urb[i] = NULL; - es1->cport_out_urb_busy[i] = false; /* just to be anal */ - } - - for (i = 0; i < NUM_CPORT_IN_URB; ++i) { - struct urb *urb = es1->cport_in_urb[i]; - - if (!urb) - break; - usb_kill_urb(urb); - usb_free_urb(urb); - kfree(es1->cport_in_buffer[i]); - es1->cport_in_buffer[i] = NULL; - } - - usb_kill_urb(es1->svc_urb); - usb_free_urb(es1->svc_urb); - es1->svc_urb = NULL; - kfree(es1->svc_buffer); - es1->svc_buffer = NULL; - - usb_set_intfdata(interface, NULL); - udev = es1->usb_dev; - greybus_remove_hd(es1->hd); - - usb_put_dev(udev); -} - -/* Callback for when we get a SVC message */ -static void svc_in_callback(struct urb *urb) -{ - struct greybus_host_device *hd = urb->context; - struct device *dev = &urb->dev->dev; - int status = check_urb_status(urb); - int retval; - - if (status) { - if ((status == -EAGAIN) || (status == -EPROTO)) - goto exit; - dev_err(dev, "urb svc in error %d (dropped)\n", status); - return; - } - - /* We have a message, create a new message structure, add it to the - * list, and wake up our thread that will process the messages. - */ - greybus_svc_in(hd, urb->transfer_buffer, urb->actual_length); - -exit: - /* resubmit the urb to get more messages */ - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - dev_err(dev, "Can not submit urb for AP data: %d\n", retval); -} - -static void cport_in_callback(struct urb *urb) -{ - struct greybus_host_device *hd = urb->context; - struct device *dev = &urb->dev->dev; - int status = check_urb_status(urb); - int retval; - u16 cport_id; - u8 *data; - - if (status) { - if ((status == -EAGAIN) || (status == -EPROTO)) - goto exit; - dev_err(dev, "urb cport in error %d (dropped)\n", status); - return; - } - - /* The size has to be at least one, for the cport id */ - if (!urb->actual_length) { - dev_err(dev, "%s: no cport id in input buffer?\n", __func__); - goto exit; - } - - /* - * Our CPort number is the first byte of the data stream, - * the rest of the stream is "real" data - */ - data = urb->transfer_buffer; - cport_id = (u16)data[0]; - data = &data[1]; - - /* Pass this data to the greybus core */ - greybus_data_rcvd(hd, cport_id, data, urb->actual_length - 1); - -exit: - /* put our urb back in the request pool */ - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - dev_err(dev, "%s: error %d in submitting urb.\n", - __func__, retval); -} - -static void cport_out_callback(struct urb *urb) -{ - struct greybus_host_device *hd = urb->context; - struct es1_ap_dev *es1 = hd_to_es1(hd); - int status = check_urb_status(urb); - u8 *data = urb->transfer_buffer + 1; - - /* - * Tell the submitter that the buffer send (attempt) is - * complete, and report the status. The submitter's buffer - * starts after the one-byte CPort id we inserted. - */ - data = urb->transfer_buffer + 1; - greybus_data_sent(hd, data, status); - - free_urb(es1, urb); - /* - * Rest assured Greg, this craziness is getting fixed. - * - * Yes, you are right, we aren't telling anyone that the urb finished. - * "That's crazy! How does this all even work?" you might be saying. - * The "magic" is the idea that greybus works on the "operation" level, - * not the "send a buffer" level. All operations are "round-trip" with - * a response from the device that the operation finished, or it will - * time out. Because of that, we don't care that this urb finished, or - * failed, or did anything else, as higher levels of the protocol stack - * will handle completions and timeouts and the rest. - * - * This protocol is "needed" due to some hardware restrictions on the - * current generation of Unipro controllers. Think about it for a - * minute, this is a USB driver, talking to a Unipro bridge, impedance - * mismatch is huge, yet the Unipro controller are even more - * underpowered than this little USB controller. We rely on the round - * trip to keep stalls in the Unipro controllers from happening so that - * we can keep data flowing properly, no matter how slow it might be. - * - * Once again, a wonderful bus protocol cut down in its prime by a naive - * controller chip. We dream of the day we have a "real" HCD for - * Unipro. Until then, we suck it up and make the hardware work, as - * that's the job of the firmware and kernel. - * - */ -} - -/* - * The ES1 USB Bridge device contains 4 endpoints - * 1 Control - usual USB stuff + AP -> SVC messages - * 1 Interrupt IN - SVC -> AP messages - * 1 Bulk IN - CPort data in - * 1 Bulk OUT - CPort data out - */ -static int ap_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct es1_ap_dev *es1; - struct greybus_host_device *hd; - struct usb_device *udev; - struct usb_host_interface *iface_desc; - struct usb_endpoint_descriptor *endpoint; - bool int_in_found = false; - bool bulk_in_found = false; - bool bulk_out_found = false; - int retval = -ENOMEM; - int i; - u8 svc_interval = 0; - - udev = usb_get_dev(interface_to_usbdev(interface)); - - hd = greybus_create_hd(&es1_driver, &udev->dev); - if (!hd) { - usb_put_dev(udev); - return -ENOMEM; - } - - /* Fill in the buffer allocation constraints */ - hd_buffer_constraints(hd); - - es1 = hd_to_es1(hd); - es1->hd = hd; - es1->usb_intf = interface; - es1->usb_dev = udev; - spin_lock_init(&es1->cport_out_urb_lock); - usb_set_intfdata(interface, es1); - - /* Control endpoint is the pipe to talk to this AP, so save it off */ - endpoint = &udev->ep0.desc; - es1->control_endpoint = endpoint->bEndpointAddress; - - /* find all 3 of our endpoints */ - iface_desc = interface->cur_altsetting; - for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { - endpoint = &iface_desc->endpoint[i].desc; - - if (usb_endpoint_is_int_in(endpoint)) { - es1->svc_endpoint = endpoint->bEndpointAddress; - svc_interval = endpoint->bInterval; - int_in_found = true; - } else if (usb_endpoint_is_bulk_in(endpoint)) { - es1->cport_in_endpoint = endpoint->bEndpointAddress; - bulk_in_found = true; - } else if (usb_endpoint_is_bulk_out(endpoint)) { - es1->cport_out_endpoint = endpoint->bEndpointAddress; - bulk_out_found = true; - } else { - dev_err(&udev->dev, - "Unknown endpoint type found, address %x\n", - endpoint->bEndpointAddress); - } - } - if ((int_in_found == false) || - (bulk_in_found == false) || - (bulk_out_found == false)) { - dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n"); - goto error; - } - - /* Create our buffer and URB to get SVC messages, and start it up */ - es1->svc_buffer = kmalloc(ES1_SVC_MSG_SIZE, GFP_KERNEL); - if (!es1->svc_buffer) - goto error; - - es1->svc_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!es1->svc_urb) - goto error; - - usb_fill_int_urb(es1->svc_urb, udev, - usb_rcvintpipe(udev, es1->svc_endpoint), - es1->svc_buffer, ES1_SVC_MSG_SIZE, svc_in_callback, - hd, svc_interval); - retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); - if (retval) - goto error; - - /* Allocate buffers for our cport in messages and start them up */ - for (i = 0; i < NUM_CPORT_IN_URB; ++i) { - struct urb *urb; - u8 *buffer; - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) - goto error; - buffer = kmalloc(ES1_GBUF_MSG_SIZE_MAX, GFP_KERNEL); - if (!buffer) - goto error; - - usb_fill_bulk_urb(urb, udev, - usb_rcvbulkpipe(udev, es1->cport_in_endpoint), - buffer, ES1_GBUF_MSG_SIZE_MAX, - cport_in_callback, hd); - es1->cport_in_urb[i] = urb; - es1->cport_in_buffer[i] = buffer; - retval = usb_submit_urb(urb, GFP_KERNEL); - if (retval) - goto error; - } - - /* Allocate urbs for our CPort OUT messages */ - for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - struct urb *urb; - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) - goto error; - - es1->cport_out_urb[i] = urb; - es1->cport_out_urb_busy[i] = false; /* just to be anal */ - } - - return 0; -error: - ap_disconnect(interface); - - return retval; -} - -static struct usb_driver es1_ap_driver = { - .name = "es1_ap_driver", - .probe = ap_probe, - .disconnect = ap_disconnect, - .id_table = id_table, -}; - -module_usb_driver(es1_ap_driver); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Greg Kroah-Hartman "); diff --git a/drivers/staging/greybus/gb-vibrator.c b/drivers/staging/greybus/gb-vibrator.c deleted file mode 100644 index b5332df..0000000 --- a/drivers/staging/greybus/gb-vibrator.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Greybus Vibrator protocol driver. - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#include -#include -#include -#include -#include -#include -#include "greybus.h" - -struct gb_vibrator_device { - struct gb_connection *connection; - struct device *dev; - int minor; /* vibrator minor number */ - u8 version_major; - u8 version_minor; -}; - -/* Version of the Greybus vibrator protocol we support */ -#define GB_VIBRATOR_VERSION_MAJOR 0x00 -#define GB_VIBRATOR_VERSION_MINOR 0x01 - -/* Greybus Vibrator request types */ -#define GB_VIBRATOR_TYPE_INVALID 0x00 -#define GB_VIBRATOR_TYPE_PROTOCOL_VERSION 0x01 -#define GB_VIBRATOR_TYPE_ON 0x02 -#define GB_VIBRATOR_TYPE_OFF 0x03 -#define GB_VIBRATOR_TYPE_RESPONSE 0x80 /* OR'd with rest */ - -struct gb_vibrator_proto_version_response { - __u8 major; - __u8 minor; -}; - -struct gb_vibrator_on_request { - __le16 timeout_ms; -}; - -/* - * This request only uses the connection field, and if successful, - * fills in the major and minor protocol version of the target. - */ -static int get_version(struct gb_vibrator_device *vib) -{ - struct gb_connection *connection = vib->connection; - struct gb_vibrator_proto_version_response version_response; - int retval; - - retval = gb_operation_sync(connection, - GB_VIBRATOR_TYPE_PROTOCOL_VERSION, - NULL, 0, - &version_response, sizeof(version_response)); - if (retval) - return retval; - - if (version_response.major > GB_VIBRATOR_VERSION_MAJOR) { - dev_err(&connection->dev, - "unsupported major version (%hhu > %hhu)\n", - version_response.major, GB_VIBRATOR_VERSION_MAJOR); - return -ENOTSUPP; - } - - vib->version_major = version_response.major; - vib->version_minor = version_response.minor; - return 0; -} - -static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms) -{ - struct gb_vibrator_on_request request; - - request.timeout_ms = cpu_to_le16(timeout_ms); - return gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_ON, - &request, sizeof(request), NULL, 0); -} - -static int turn_off(struct gb_vibrator_device *vib) -{ - return gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_OFF, - NULL, 0, NULL, 0); -} - -static ssize_t timeout_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct gb_vibrator_device *vib = dev_get_drvdata(dev); - unsigned long val; - int retval; - - retval = kstrtoul(buf, 10, &val); - if (retval < 0) { - dev_err(dev, "could not parse timeout value %d\n", retval); - return retval; - } - - if (val) - retval = turn_on(vib, (u16)val); - else - retval = turn_off(vib); - if (retval) - return retval; - - return count; -} -static DEVICE_ATTR_WO(timeout); - -static struct attribute *vibrator_attrs[] = { - &dev_attr_timeout.attr, - NULL, -}; -ATTRIBUTE_GROUPS(vibrator); - -static struct class vibrator_class = { - .name = "vibrator", - .owner = THIS_MODULE, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) - .dev_groups = vibrator_groups, -#endif -}; - -static DEFINE_IDR(minors); - -static int gb_vibrator_connection_init(struct gb_connection *connection) -{ - struct gb_vibrator_device *vib; - struct device *dev; - int retval; - - vib = kzalloc(sizeof(*vib), GFP_KERNEL); - if (!vib) - return -ENOMEM; - - vib->connection = connection; - connection->private = vib; - - retval = get_version(vib); - if (retval) - goto error; - - /* - * For now we create a device in sysfs for the vibrator, but odds are - * there is a "real" device somewhere in the kernel for this, but I - * can't find it at the moment... - */ - vib->minor = idr_alloc(&minors, vib, 0, 0, GFP_KERNEL); - if (vib->minor < 0) { - retval = vib->minor; - goto error; - } - dev = device_create(&vibrator_class, &connection->dev, MKDEV(0, 0), vib, - "vibrator%d", vib->minor); - if (IS_ERR(dev)) { - retval = -EINVAL; - goto error; - } - vib->dev = dev; - -#if LINUX_VERSION_CODE <= KERNEL_VERSION(3,11,0) - /* - * Newer kernels handle this in a race-free manner, by the dev_groups - * field in the struct class up above. But for older kernels, we need - * to "open code this :( - */ - retval = sysfs_create_group(&dev->kobj, vibrator_groups[0]); - if (retval) { - device_unregister(dev); - goto error; - } -#endif - - return 0; - -error: - kfree(vib); - return retval; -} - -static void gb_vibrator_connection_exit(struct gb_connection *connection) -{ - struct gb_vibrator_device *vib = connection->private; - -#if LINUX_VERSION_CODE <= KERNEL_VERSION(3,11,0) - sysfs_remove_group(&vib->dev->kobj, vibrator_groups[0]); -#endif - idr_remove(&minors, vib->minor); - device_unregister(vib->dev); - kfree(vib); -} - -static struct gb_protocol vibrator_protocol = { - .name = "vibrator", - .id = GREYBUS_PROTOCOL_VIBRATOR, - .major = 0, - .minor = 1, - .connection_init = gb_vibrator_connection_init, - .connection_exit = gb_vibrator_connection_exit, - .request_recv = NULL, /* no incoming requests */ -}; - -static __init int protocol_init(void) -{ - int retval; - - retval = class_register(&vibrator_class); - if (retval) - return retval; - - return gb_protocol_register(&vibrator_protocol); -} - -static __exit void protocol_exit(void) -{ - gb_protocol_deregister(&vibrator_protocol); - class_unregister(&vibrator_class); -} - -module_init(protocol_init); -module_exit(protocol_exit); - -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/vibrator.c b/drivers/staging/greybus/vibrator.c new file mode 100644 index 0000000..b5332df --- /dev/null +++ b/drivers/staging/greybus/vibrator.c @@ -0,0 +1,227 @@ +/* + * Greybus Vibrator protocol driver. + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include +#include +#include "greybus.h" + +struct gb_vibrator_device { + struct gb_connection *connection; + struct device *dev; + int minor; /* vibrator minor number */ + u8 version_major; + u8 version_minor; +}; + +/* Version of the Greybus vibrator protocol we support */ +#define GB_VIBRATOR_VERSION_MAJOR 0x00 +#define GB_VIBRATOR_VERSION_MINOR 0x01 + +/* Greybus Vibrator request types */ +#define GB_VIBRATOR_TYPE_INVALID 0x00 +#define GB_VIBRATOR_TYPE_PROTOCOL_VERSION 0x01 +#define GB_VIBRATOR_TYPE_ON 0x02 +#define GB_VIBRATOR_TYPE_OFF 0x03 +#define GB_VIBRATOR_TYPE_RESPONSE 0x80 /* OR'd with rest */ + +struct gb_vibrator_proto_version_response { + __u8 major; + __u8 minor; +}; + +struct gb_vibrator_on_request { + __le16 timeout_ms; +}; + +/* + * This request only uses the connection field, and if successful, + * fills in the major and minor protocol version of the target. + */ +static int get_version(struct gb_vibrator_device *vib) +{ + struct gb_connection *connection = vib->connection; + struct gb_vibrator_proto_version_response version_response; + int retval; + + retval = gb_operation_sync(connection, + GB_VIBRATOR_TYPE_PROTOCOL_VERSION, + NULL, 0, + &version_response, sizeof(version_response)); + if (retval) + return retval; + + if (version_response.major > GB_VIBRATOR_VERSION_MAJOR) { + dev_err(&connection->dev, + "unsupported major version (%hhu > %hhu)\n", + version_response.major, GB_VIBRATOR_VERSION_MAJOR); + return -ENOTSUPP; + } + + vib->version_major = version_response.major; + vib->version_minor = version_response.minor; + return 0; +} + +static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms) +{ + struct gb_vibrator_on_request request; + + request.timeout_ms = cpu_to_le16(timeout_ms); + return gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_ON, + &request, sizeof(request), NULL, 0); +} + +static int turn_off(struct gb_vibrator_device *vib) +{ + return gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_OFF, + NULL, 0, NULL, 0); +} + +static ssize_t timeout_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct gb_vibrator_device *vib = dev_get_drvdata(dev); + unsigned long val; + int retval; + + retval = kstrtoul(buf, 10, &val); + if (retval < 0) { + dev_err(dev, "could not parse timeout value %d\n", retval); + return retval; + } + + if (val) + retval = turn_on(vib, (u16)val); + else + retval = turn_off(vib); + if (retval) + return retval; + + return count; +} +static DEVICE_ATTR_WO(timeout); + +static struct attribute *vibrator_attrs[] = { + &dev_attr_timeout.attr, + NULL, +}; +ATTRIBUTE_GROUPS(vibrator); + +static struct class vibrator_class = { + .name = "vibrator", + .owner = THIS_MODULE, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) + .dev_groups = vibrator_groups, +#endif +}; + +static DEFINE_IDR(minors); + +static int gb_vibrator_connection_init(struct gb_connection *connection) +{ + struct gb_vibrator_device *vib; + struct device *dev; + int retval; + + vib = kzalloc(sizeof(*vib), GFP_KERNEL); + if (!vib) + return -ENOMEM; + + vib->connection = connection; + connection->private = vib; + + retval = get_version(vib); + if (retval) + goto error; + + /* + * For now we create a device in sysfs for the vibrator, but odds are + * there is a "real" device somewhere in the kernel for this, but I + * can't find it at the moment... + */ + vib->minor = idr_alloc(&minors, vib, 0, 0, GFP_KERNEL); + if (vib->minor < 0) { + retval = vib->minor; + goto error; + } + dev = device_create(&vibrator_class, &connection->dev, MKDEV(0, 0), vib, + "vibrator%d", vib->minor); + if (IS_ERR(dev)) { + retval = -EINVAL; + goto error; + } + vib->dev = dev; + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(3,11,0) + /* + * Newer kernels handle this in a race-free manner, by the dev_groups + * field in the struct class up above. But for older kernels, we need + * to "open code this :( + */ + retval = sysfs_create_group(&dev->kobj, vibrator_groups[0]); + if (retval) { + device_unregister(dev); + goto error; + } +#endif + + return 0; + +error: + kfree(vib); + return retval; +} + +static void gb_vibrator_connection_exit(struct gb_connection *connection) +{ + struct gb_vibrator_device *vib = connection->private; + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(3,11,0) + sysfs_remove_group(&vib->dev->kobj, vibrator_groups[0]); +#endif + idr_remove(&minors, vib->minor); + device_unregister(vib->dev); + kfree(vib); +} + +static struct gb_protocol vibrator_protocol = { + .name = "vibrator", + .id = GREYBUS_PROTOCOL_VIBRATOR, + .major = 0, + .minor = 1, + .connection_init = gb_vibrator_connection_init, + .connection_exit = gb_vibrator_connection_exit, + .request_recv = NULL, /* no incoming requests */ +}; + +static __init int protocol_init(void) +{ + int retval; + + retval = class_register(&vibrator_class); + if (retval) + return retval; + + return gb_protocol_register(&vibrator_protocol); +} + +static __exit void protocol_exit(void) +{ + gb_protocol_deregister(&vibrator_protocol); + class_unregister(&vibrator_class); +} + +module_init(protocol_init); +module_exit(protocol_exit); + +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 530430b717f02843fe1f2e77e6f52a41e05d6c3a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 21 Jan 2015 18:12:35 +0530 Subject: greybus: uart: s/REQ/TYPE Request type for all other protocols is defined like: GB__TYPE_, but for UART is like: GB__REQ_. Replace REQ with TYPE to make it consistent. It will also be useful in a later patch that creates get_version() routines with the help of a macro. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 0320620..543c889 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -38,14 +38,14 @@ #define GB_UART_VERSION_MINOR 0x01 /* Greybus UART request types */ -#define GB_UART_REQ_INVALID 0x00 -#define GB_UART_REQ_PROTOCOL_VERSION 0x01 -#define GB_UART_REQ_SEND_DATA 0x02 -#define GB_UART_REQ_RECEIVE_DATA 0x03 /* Unsolicited data */ -#define GB_UART_REQ_SET_LINE_CODING 0x04 -#define GB_UART_REQ_SET_CONTROL_LINE_STATE 0x05 -#define GB_UART_REQ_SET_BREAK 0x06 -#define GB_UART_REQ_SERIAL_STATE 0x07 /* Unsolicited data */ +#define GB_UART_TYPE_INVALID 0x00 +#define GB_UART_TYPE_PROTOCOL_VERSION 0x01 +#define GB_UART_TYPE_SEND_DATA 0x02 +#define GB_UART_TYPE_RECEIVE_DATA 0x03 /* Unsolicited data */ +#define GB_UART_TYPE_SET_LINE_CODING 0x04 +#define GB_UART_TYPE_SET_CONTROL_LINE_STATE 0x05 +#define GB_UART_TYPE_SET_BREAK 0x06 +#define GB_UART_TYPE_SERIAL_STATE 0x07 /* Unsolicited data */ #define GB_UART_TYPE_RESPONSE 0x80 /* OR'd with rest */ struct gb_uart_proto_version_response { @@ -141,7 +141,7 @@ static int get_version(struct gb_tty *tty) int ret; ret = gb_operation_sync(tty->connection, - GB_UART_REQ_PROTOCOL_VERSION, + GB_UART_TYPE_PROTOCOL_VERSION, NULL, 0, &response, sizeof(response)); if (ret) return ret; @@ -173,7 +173,7 @@ static int send_data(struct gb_tty *tty, u16 size, const u8 *data) request->size = cpu_to_le16(size); memcpy(&request->data[0], data, size); - retval = gb_operation_sync(tty->connection, GB_UART_REQ_SEND_DATA, + retval = gb_operation_sync(tty->connection, GB_UART_TYPE_SEND_DATA, request, sizeof(*request) + size, NULL, 0); kfree(request); @@ -186,7 +186,7 @@ static int send_line_coding(struct gb_tty *tty) memcpy(&request.line_coding, &tty->line_coding, sizeof(tty->line_coding)); - return gb_operation_sync(tty->connection, GB_UART_REQ_SET_LINE_CODING, + return gb_operation_sync(tty->connection, GB_UART_TYPE_SET_LINE_CODING, &request, sizeof(request), NULL, 0); } @@ -196,7 +196,7 @@ static int send_control(struct gb_tty *tty, u16 control) request.control = cpu_to_le16(control); return gb_operation_sync(tty->connection, - GB_UART_REQ_SET_CONTROL_LINE_STATE, + GB_UART_TYPE_SET_CONTROL_LINE_STATE, &request, sizeof(request), NULL, 0); } @@ -211,7 +211,7 @@ static int send_break(struct gb_tty *tty, u8 state) } request.state = state; - return gb_operation_sync(tty->connection, GB_UART_REQ_SET_BREAK, + return gb_operation_sync(tty->connection, GB_UART_TYPE_SET_BREAK, &request, sizeof(request), NULL, 0); } -- cgit v0.10.2 From 36e79dec96f652110ae2b06bfcf9e67e1b770787 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 21 Jan 2015 18:12:36 +0530 Subject: greybus: create get_version() routines with the help of a macro This gets rid of lots of duplication of code. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery.c b/drivers/staging/greybus/battery.c index 2130d73..c14f44b 100644 --- a/drivers/staging/greybus/battery.c +++ b/drivers/staging/greybus/battery.c @@ -88,32 +88,8 @@ struct gb_battery_voltage_response { __le32 voltage; }; -/* - * This request only uses the connection field, and if successful, - * fills in the major and minor protocol version of the target. - */ -static int get_version(struct gb_battery *gb) -{ - struct gb_battery_proto_version_response version_response; - int retval; - - retval = gb_operation_sync(gb->connection, - GB_BATTERY_TYPE_PROTOCOL_VERSION, - NULL, 0, - &version_response, sizeof(version_response)); - if (retval) - return retval; - - if (version_response.major > GB_BATTERY_VERSION_MAJOR) { - pr_err("unsupported major version (%hhu > %hhu)\n", - version_response.major, GB_BATTERY_VERSION_MAJOR); - return -ENOTSUPP; - } - - gb->version_major = version_response.major; - gb->version_minor = version_response.minor; - return 0; -} +/* Define get_version() routine */ +define_get_version(gb_battery, BATTERY); static int get_tech(struct gb_battery *gb) { diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 4997588..a935833 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -113,29 +113,8 @@ struct gb_gpio_set_debounce_request { /* debounce response has no payload */ -/* - * This request only uses the connection field, and if successful, - * fills in the major and minor protocol version of the target. - */ -static int gb_gpio_proto_version_operation(struct gb_gpio_controller *ggc) -{ - struct gb_gpio_proto_version_response response; - int ret; - - ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_PROTOCOL_VERSION, - NULL, 0, &response, sizeof(response)); - if (ret) - return ret; - - if (response.major > GB_GPIO_VERSION_MAJOR) { - pr_err("unsupported major version (%hhu > %hhu)\n", - response.major, GB_GPIO_VERSION_MAJOR); - return -ENOTSUPP; - } - ggc->version_major = response.major; - ggc->version_minor = response.minor; - return 0; -} +/* Define get_version() routine */ +define_get_version(gb_gpio_controller, GPIO); static int gb_gpio_line_count_operation(struct gb_gpio_controller *ggc) { @@ -446,7 +425,7 @@ static int gb_gpio_controller_setup(struct gb_gpio_controller *gb_gpio_controlle int ret; /* First thing we need to do is check the version */ - ret = gb_gpio_proto_version_operation(gb_gpio_controller); + ret = get_version(gb_gpio_controller); if (ret) ; /* return ret; */ diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c index c967ae3..589691d 100644 --- a/drivers/staging/greybus/i2c.c +++ b/drivers/staging/greybus/i2c.c @@ -87,30 +87,8 @@ struct gb_i2c_transfer_response { __u8 data[0]; /* inbound data */ }; -/* - * This request only uses the connection field, and if successful, - * fills in the major and minor protocol version of the target. - */ -static int gb_i2c_proto_version_operation(struct gb_i2c_device *gb_i2c_dev) -{ - struct gb_i2c_proto_version_response response; - int ret; - - ret = gb_operation_sync(gb_i2c_dev->connection, - GB_I2C_TYPE_PROTOCOL_VERSION, - NULL, 0, &response, sizeof(response)); - if (ret) - return ret; - - if (response.major > GB_I2C_VERSION_MAJOR) { - pr_err("unsupported major version (%hhu > %hhu)\n", - response.major, GB_I2C_VERSION_MAJOR); - return -ENOTSUPP; - } - gb_i2c_dev->version_major = response.major; - gb_i2c_dev->version_minor = response.minor; - return 0; -} +/* Define get_version() routine */ +define_get_version(gb_i2c_device, I2C); /* * Map Greybus i2c functionality bits into Linux ones @@ -361,7 +339,7 @@ static int gb_i2c_device_setup(struct gb_i2c_device *gb_i2c_dev) int ret; /* First thing we need to do is check the version */ - ret = gb_i2c_proto_version_operation(gb_i2c_dev); + ret = get_version(gb_i2c_dev); if (ret) return ret; diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index 12bbc2f..ae8ab21 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -148,6 +148,32 @@ struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor) return protocol; } +int gb_protocol_get_version(struct gb_connection *connection, int type, + void *request, int request_size, + struct gb_protocol_version_response *response, + __u8 major) +{ + int retval; + + retval = gb_operation_sync(connection, type, request, request_size, + response, sizeof(*response)); + if (retval) + return retval; + + if (response->major > major) { + dev_err(&connection->dev, + "unsupported major version (%hhu > %hhu)\n", + response->major, major); + return -ENOTSUPP; + } + + dev_dbg(&connection->dev, "version_major = %u version_minor = %u\n", + response->major, response->minor); + + return 0; +} +EXPORT_SYMBOL_GPL(gb_protocol_get_version); + void gb_protocol_put(struct gb_protocol *protocol) { u8 major; diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index 8bda524..e65cc18 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -14,6 +14,12 @@ struct gb_operation; +/* version request has no payload */ +struct gb_protocol_version_response { + __u8 major; + __u8 minor; +}; + typedef int (*gb_connection_init_t)(struct gb_connection *); typedef void (*gb_connection_exit_t)(struct gb_connection *); typedef void (*gb_request_recv_t)(u8, struct gb_operation *); @@ -45,6 +51,11 @@ int gb_protocol_deregister(struct gb_protocol *protocol); __gb_protocol_register(protocol, THIS_MODULE) struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor); +int gb_protocol_get_version(struct gb_connection *connection, int type, + void *request, int request_size, + struct gb_protocol_version_response *response, + __u8 major); + void gb_protocol_put(struct gb_protocol *protocol); /* @@ -82,4 +93,27 @@ static void __exit protocol_exit(void) \ } \ module_exit(protocol_exit); +/* + * Macro to create get_version() routine for protocols + * @__device: name of the device struct + * @__protocol: name of protocol in CAPITALS + */ +#define define_get_version(__device, __protocol) \ +static int get_version(struct __device *dev) \ +{ \ + struct gb_protocol_version_response response; \ + int retval; \ + \ + retval = gb_protocol_get_version(dev->connection, \ + GB_##__protocol##_TYPE_PROTOCOL_VERSION,\ + NULL, 0, &response, \ + GB_##__protocol##_VERSION_MAJOR); \ + if (retval) \ + return retval; \ + \ + dev->version_major = response.major; \ + dev->version_minor = response.minor; \ + return 0; \ +} + #endif /* __PROTOCOL_H */ diff --git a/drivers/staging/greybus/pwm.c b/drivers/staging/greybus/pwm.c index 91f7b87..7b72523 100644 --- a/drivers/staging/greybus/pwm.c +++ b/drivers/staging/greybus/pwm.c @@ -79,30 +79,8 @@ struct gb_pwm_disable_request { __u8 which; }; -/* - * This request only uses the connection field, and if successful, - * fills in the major and minor protocol version of the target. - */ -static int gb_pwm_proto_version_operation(struct gb_pwm_chip *pwmc) -{ - struct gb_pwm_proto_version_response response; - int ret; - - ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_PROTOCOL_VERSION, - NULL, 0, &response, sizeof(response)); - - if (ret) - return ret; - - if (response.major > GB_PWM_VERSION_MAJOR) { - pr_err("unsupported major version (%hhu > %hhu)\n", - response.major, GB_PWM_VERSION_MAJOR); - return -ENOTSUPP; - } - pwmc->version_major = response.major; - pwmc->version_minor = response.minor; - return 0; -} +/* Define get_version() routine */ +define_get_version(gb_pwm_chip, PWM); static int gb_pwm_count_operation(struct gb_pwm_chip *pwmc) { @@ -269,7 +247,7 @@ static int gb_pwm_connection_init(struct gb_connection *connection) connection->private = pwmc; /* Check for compatible protocol version */ - ret = gb_pwm_proto_version_operation(pwmc); + ret = get_version(pwmc); if (ret) goto out_err; diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 543c889..d0669ae 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -131,33 +131,8 @@ static DEFINE_IDR(tty_minors); static DEFINE_MUTEX(table_lock); static atomic_t reference_count = ATOMIC_INIT(0); -/* - * This request only uses the connection field, and if successful, - * fills in the major and minor protocol version of the target. - */ -static int get_version(struct gb_tty *tty) -{ - struct gb_uart_proto_version_response response; - int ret; - - ret = gb_operation_sync(tty->connection, - GB_UART_TYPE_PROTOCOL_VERSION, - NULL, 0, &response, sizeof(response)); - if (ret) - return ret; - - if (response.major > GB_UART_VERSION_MAJOR) { - pr_err("unsupported major version (%hhu > %hhu)\n", - response.major, GB_UART_VERSION_MAJOR); - return -ENOTSUPP; - } - tty->version_major = response.major; - tty->version_minor = response.minor; - - pr_debug("%s: version_major = %u version_minor = %u\n", - __func__, tty->version_major, tty->version_minor); - return 0; -} +/* Define get_version() routine */ +define_get_version(gb_tty, UART); static int send_data(struct gb_tty *tty, u16 size, const u8 *data) { diff --git a/drivers/staging/greybus/usb.c b/drivers/staging/greybus/usb.c index 010ef9e..c66d768 100644 --- a/drivers/staging/greybus/usb.c +++ b/drivers/staging/greybus/usb.c @@ -93,26 +93,8 @@ struct gb_usb_device { #define to_gb_usb_device(d) ((struct gb_usb_device*) d->hcd_priv) -static int get_version(struct gb_usb_device *dev) -{ - struct gb_usb_proto_version_response response; - int ret; - - ret = gb_operation_sync(dev->connection, - GB_USB_TYPE_PROTOCOL_VERSION, - NULL, 0, &response, sizeof(response)); - if (ret) - return ret; - - if (response.major > GB_USB_VERSION_MAJOR) { - pr_err("unsupported major version (%hhu > %hhu)\n", - response.major, GB_USB_VERSION_MAJOR); - return -ENOTSUPP; - } - dev->version_major = response.major; - dev->version_minor = response.minor; - return 0; -} +/* Define get_version() routine */ +define_get_version(gb_usb_device, USB); static void hcd_stop(struct usb_hcd *hcd) { diff --git a/drivers/staging/greybus/vibrator.c b/drivers/staging/greybus/vibrator.c index b5332df..141ccdb 100644 --- a/drivers/staging/greybus/vibrator.c +++ b/drivers/staging/greybus/vibrator.c @@ -43,34 +43,8 @@ struct gb_vibrator_on_request { __le16 timeout_ms; }; -/* - * This request only uses the connection field, and if successful, - * fills in the major and minor protocol version of the target. - */ -static int get_version(struct gb_vibrator_device *vib) -{ - struct gb_connection *connection = vib->connection; - struct gb_vibrator_proto_version_response version_response; - int retval; - - retval = gb_operation_sync(connection, - GB_VIBRATOR_TYPE_PROTOCOL_VERSION, - NULL, 0, - &version_response, sizeof(version_response)); - if (retval) - return retval; - - if (version_response.major > GB_VIBRATOR_VERSION_MAJOR) { - dev_err(&connection->dev, - "unsupported major version (%hhu > %hhu)\n", - version_response.major, GB_VIBRATOR_VERSION_MAJOR); - return -ENOTSUPP; - } - - vib->version_major = version_response.major; - vib->version_minor = version_response.minor; - return 0; -} +/* Define get_version() routine */ +define_get_version(gb_vibrator_device, VIBRATOR); static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms) { -- cgit v0.10.2 From 89210f64bae6bd6bba90d9e08d1b88b4ba103f59 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 21 Jan 2015 18:12:37 +0530 Subject: greybus: remove unused version-response structs These aren't used anymore and so can be removed. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery.c b/drivers/staging/greybus/battery.c index c14f44b..b968d14 100644 --- a/drivers/staging/greybus/battery.c +++ b/drivers/staging/greybus/battery.c @@ -43,11 +43,6 @@ struct gb_battery { #define GB_BATTERY_TYPE_CAPACITY 0x09 // TODO - POWER_SUPPLY_PROP_CURRENT_MAX #define GB_BATTERY_TYPE_SHUTDOWN_TEMP 0x0a // TODO - POWER_SUPPLY_PROP_TEMP_ALERT_MAX -struct gb_battery_proto_version_response { - __u8 major; - __u8 minor; -}; - /* Should match up with battery types in linux/power_supply.h */ #define GB_BATTERY_TECH_UNKNOWN 0x0000 #define GB_BATTERY_TECH_NiMH 0x0001 diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index a935833..85d89b8 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -54,12 +54,6 @@ struct gb_gpio_controller { #define GB_GPIO_DEBOUNCE_USEC_DEFAULT 0 /* microseconds */ -/* version request has no payload */ -struct gb_gpio_proto_version_response { - __u8 major; - __u8 minor; -}; - /* line count request has no payload */ struct gb_gpio_line_count_response { __u8 count; diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c index 589691d..ca88914 100644 --- a/drivers/staging/greybus/i2c.c +++ b/drivers/staging/greybus/i2c.c @@ -42,12 +42,6 @@ struct gb_i2c_device { #define GB_I2C_RETRIES_DEFAULT 3 #define GB_I2C_TIMEOUT_DEFAULT 1000 /* milliseconds */ -/* version request has no payload */ -struct gb_i2c_proto_version_response { - __u8 major; - __u8 minor; -}; - /* functionality request has no payload */ struct gb_i2c_functionality_response { __le32 functionality; diff --git a/drivers/staging/greybus/pwm.c b/drivers/staging/greybus/pwm.c index 7b72523..e2ab6f5 100644 --- a/drivers/staging/greybus/pwm.c +++ b/drivers/staging/greybus/pwm.c @@ -41,12 +41,6 @@ struct gb_pwm_chip { #define GB_PWM_TYPE_DISABLE 0x08 #define GB_PWM_TYPE_RESPONSE 0x80 /* OR'd with rest */ -/* version request has no payload */ -struct gb_pwm_proto_version_response { - __u8 major; - __u8 minor; -}; - /* pwm count request has no payload */ struct gb_pwm_count_response { __u8 count; diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index d0669ae..575ca56 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -48,11 +48,6 @@ #define GB_UART_TYPE_SERIAL_STATE 0x07 /* Unsolicited data */ #define GB_UART_TYPE_RESPONSE 0x80 /* OR'd with rest */ -struct gb_uart_proto_version_response { - __u8 major; - __u8 minor; -}; - struct gb_uart_send_data_request { __le16 size; __u8 data[0]; diff --git a/drivers/staging/greybus/usb.c b/drivers/staging/greybus/usb.c index c66d768..ff4556f 100644 --- a/drivers/staging/greybus/usb.c +++ b/drivers/staging/greybus/usb.c @@ -31,11 +31,6 @@ #define GB_USB_TYPE_GET_FRAME_NUMBER 0x08 #define GB_USB_TYPE_HUB_STATUS_DATA 0x09 -struct gb_usb_proto_version_response { - __u8 major; - __u8 minor; -}; - struct gb_usb_urb_enqueue_request { __le32 pipe; __le32 transfer_flags; diff --git a/drivers/staging/greybus/vibrator.c b/drivers/staging/greybus/vibrator.c index 141ccdb..b6ec9f2 100644 --- a/drivers/staging/greybus/vibrator.c +++ b/drivers/staging/greybus/vibrator.c @@ -34,11 +34,6 @@ struct gb_vibrator_device { #define GB_VIBRATOR_TYPE_OFF 0x03 #define GB_VIBRATOR_TYPE_RESPONSE 0x80 /* OR'd with rest */ -struct gb_vibrator_proto_version_response { - __u8 major; - __u8 minor; -}; - struct gb_vibrator_on_request { __le16 timeout_ms; }; -- cgit v0.10.2 From c2f792382bc23bddd67a5da72faf9d46bf0f3ef9 Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Thu, 22 Jan 2015 15:23:37 +0800 Subject: greybus: protocol.c: fix a kernel panic caused by __gb_protocol_register __gb_protocol_register check if the protocol is not already registred, and then register it. It register in existing->lists but at this point, existing is always NULL (we exist just before if not). Use gb_protocols instead. Signed-off-by: Alexandre Bailon Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index ae8ab21..400f733 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -70,7 +70,7 @@ int __gb_protocol_register(struct gb_protocol *protocol, struct module *module) * We need to insert the protocol here, before the existing one * (or before the head if we searched the whole list) */ - list_add_tail(&protocol->links, &existing->links); + list_add_tail(&protocol->links, &gb_protocols); spin_unlock_irq(&gb_protocols_lock); pr_info("Registered %s protocol.\n", protocol->name); -- cgit v0.10.2 From f281f2dec14231b5da8ca44100b4e2887724e5fd Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 22 Jan 2015 12:42:39 +0530 Subject: greybus: i2c: fix name conflict between function and struct: gb_i2c_transfer_response 'gb_i2c_transfer_response' is the name given to a function and a struct. Though we don't get any compilation errors/warnings about it, but the names should be unique. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c index ca88914..31528af 100644 --- a/drivers/staging/greybus/i2c.c +++ b/drivers/staging/greybus/i2c.c @@ -230,7 +230,7 @@ gb_i2c_transfer_request(struct gb_connection *connection, return operation; } -static void gb_i2c_transfer_response(struct i2c_msg *msgs, u32 msg_count, +static void gb_i2c_decode_response(struct i2c_msg *msgs, u32 msg_count, struct gb_i2c_transfer_response *response) { struct i2c_msg *msg = msgs; @@ -273,7 +273,7 @@ static int gb_i2c_transfer_operation(struct gb_i2c_device *gb_i2c_dev, struct gb_i2c_transfer_response *response; response = operation->response->payload; - gb_i2c_transfer_response(msgs, msg_count, response); + gb_i2c_decode_response(msgs, msg_count, response); ret = msg_count; } else if (!gb_i2c_expected_transfer_error(ret)) { pr_err("transfer operation failed (%d)\n", ret); -- cgit v0.10.2 From 62aadeeafa1585d6acf3e9b378eb554f57f3bc84 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 22 Jan 2015 12:10:38 +0530 Subject: greybus: i2c: fix name conflict between function and struct: gb_i2c_transfer_request 'gb_i2c_transfer_request' is the name given to a function and a struct. Though we don't get any compilation errors/warnings about it, but the names should be unique. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c index 31528af..0bcd7a9 100644 --- a/drivers/staging/greybus/i2c.c +++ b/drivers/staging/greybus/i2c.c @@ -163,8 +163,8 @@ gb_i2c_fill_transfer_op(struct gb_i2c_transfer_op *op, struct i2c_msg *msg) } static struct gb_operation * -gb_i2c_transfer_request(struct gb_connection *connection, - struct i2c_msg *msgs, u32 msg_count) +gb_i2c_operation_create(struct gb_connection *connection, + struct i2c_msg *msgs, u32 msg_count) { struct gb_i2c_transfer_request *request; struct gb_operation *operation; @@ -264,7 +264,7 @@ static int gb_i2c_transfer_operation(struct gb_i2c_device *gb_i2c_dev, struct gb_operation *operation; int ret; - operation = gb_i2c_transfer_request(connection, msgs, msg_count); + operation = gb_i2c_operation_create(connection, msgs, msg_count); if (!operation) return -ENOMEM; -- cgit v0.10.2 From c1a0a8fccf92d825a6c324c3e2363fefdb3f19da Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 23 Jan 2015 10:05:58 +0800 Subject: greybus: Revert "protocol.c: fix a kernel panic caused by __gb_protocol_register" This reverts commit 57131bf309d34568dd3b8f8e9da7a7ba25e9495e, it isn't going to be needed as the patch this fixes will be reverted. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index 400f733..ae8ab21 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -70,7 +70,7 @@ int __gb_protocol_register(struct gb_protocol *protocol, struct module *module) * We need to insert the protocol here, before the existing one * (or before the head if we searched the whole list) */ - list_add_tail(&protocol->links, &gb_protocols); + list_add_tail(&protocol->links, &existing->links); spin_unlock_irq(&gb_protocols_lock); pr_info("Registered %s protocol.\n", protocol->name); -- cgit v0.10.2 From 6869eb56ebe074bbd34de0fd5e63ad31cd578094 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 23 Jan 2015 10:06:24 +0800 Subject: greybus: Revert "protocol: dedup protocol find code" This reverts commit 241b5fefc54eae95239b0f7dc4e2b0db49457729 as it's wrong, we want to insert into the correct place in the list. Reported-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index ae8ab21..51549e2 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -20,13 +20,6 @@ static struct gb_protocol *_gb_protocol_find(u8 id, u8 major, u8 minor) { struct gb_protocol *protocol; - /* - * The protocols list is sorted first by protocol id (low to - * high), then by major version (high to low), and finally - * by minor version (high to low). Searching only by - * protocol id will produce the newest implemented version - * of the protocol. - */ list_for_each_entry(protocol, &gb_protocols, links) { if (protocol->id < id) continue; @@ -57,12 +50,34 @@ int __gb_protocol_register(struct gb_protocol *protocol, struct module *module) protocol->owner = module; + /* + * The protocols list is sorted first by protocol id (low to + * high), then by major version (high to low), and finally + * by minor version (high to low). Searching only by + * protocol id will produce the newest implemented version + * of the protocol. + */ spin_lock_irq(&gb_protocols_lock); - /* check if the protocol already wos registered */ - existing = _gb_protocol_find(id, major, minor); - if (existing) { + list_for_each_entry(existing, &gb_protocols, links) { + if (existing->id < id) + continue; + if (existing->id > id) + break; + + if (existing->major > major) + continue; + if (existing->major < major) + break; + + if (existing->minor > minor) + continue; + if (existing->minor < minor) + break; + + /* A matching protocol has already been registered */ spin_unlock_irq(&gb_protocols_lock); + return -EEXIST; } -- cgit v0.10.2 From 65760032f5887351537fb3d3e095392a8874aa88 Mon Sep 17 00:00:00 2001 From: Michael Scott Date: Thu, 22 Jan 2015 16:22:20 -0800 Subject: greybus: build: android: replace hard-coded build destination with variable Make sure destination for greybus modules is consistent and easier to maintain Signed-off-by: Michael Scott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Android.mk b/drivers/staging/greybus/Android.mk index 924099b..5d96a24 100644 --- a/drivers/staging/greybus/Android.mk +++ b/drivers/staging/greybus/Android.mk @@ -2,13 +2,15 @@ $(PRODUCT_OUT)/ramdisk.img: build-greybus +GREYBUS_MODULE_OUT_PATH := $(PRODUCT_OUT)/root/lib/modules + include $(CLEAR_VARS) GREYBUS_SRC_PATH := $(ANDROID_BUILD_TOP)/external/greybus/ LOCAL_PATH := $(GREYBUS_SRC_PATH) LOCAL_SRC_FILES := greybus.ko LOCAL_MODULE := $(LOCAL_SRC_FILES) LOCAL_MODULE_CLASS := EXECUTABLES -LOCAL_MODULE_PATH := $(PRODUCT_OUT)/root/lib/modules +LOCAL_MODULE_PATH := $(GREYBUS_MODULE_OUT_PATH) $(LOCAL_PATH)/$(LOCAL_SRC_FILES): build-greybus include $(BUILD_PREBUILT) @@ -26,5 +28,5 @@ build-greybus: android_kernel make clean -C $(GREYBUS_SRC_PATH) cd $(GREYBUS_SRC_PATH) &&\ $(MAKE) -j$(MAKE_JOBS) CROSS_COMPILE=$(KERNEL_TOOLS_PREFIX) $(ARGS) - mkdir -p $(PRODUCT_OUT)/root/lib/modules - cp $(GREYBUS_SRC_PATH)/greybus.ko $(PRODUCT_OUT)/root/lib/modules + mkdir -p $(GREYBUS_MODULE_OUT_PATH) + cp $(GREYBUS_SRC_PATH)/greybus.ko $(GREYBUS_MODULE_OUT_PATH) -- cgit v0.10.2 From 58b978c48bcde959c81f0501be1fdee4b2823687 Mon Sep 17 00:00:00 2001 From: Michael Scott Date: Thu, 22 Jan 2015 16:22:47 -0800 Subject: greybus: build: android: add all greybus modules to the build We now have several modules generated by the greybus build. Let's add any *.ko files we find to the buid. Signed-off-by: Michael Scott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Android.mk b/drivers/staging/greybus/Android.mk index 5d96a24..6f13d35 100644 --- a/drivers/staging/greybus/Android.mk +++ b/drivers/staging/greybus/Android.mk @@ -29,4 +29,6 @@ build-greybus: android_kernel cd $(GREYBUS_SRC_PATH) &&\ $(MAKE) -j$(MAKE_JOBS) CROSS_COMPILE=$(KERNEL_TOOLS_PREFIX) $(ARGS) mkdir -p $(GREYBUS_MODULE_OUT_PATH) - cp $(GREYBUS_SRC_PATH)/greybus.ko $(GREYBUS_MODULE_OUT_PATH) + ko=`find $$GREYBUS_SRC_PATH -type f -name *.ko`;\ + for i in $$ko; do $(KERNEL_TOOLCHAIN_PATH)strip --strip-unneeded $$i;\ + mv $$i $(GREYBUS_MODULE_OUT_PATH)/; done; -- cgit v0.10.2 From e0b179ee782d80b31ccfe8cbcb1505cb703dfdbc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 22 Jan 2015 20:33:41 +0800 Subject: greybus: ap.c: our workqueue should be ordered SVC messages come in in an "order", so don't mess them up by processing them out of order. Fix this by making our work queue ordered, which should keep everything in line. Reported-by: Perry Hung Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index e69566b..3e4d4fb 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -356,7 +356,7 @@ EXPORT_SYMBOL_GPL(greybus_svc_in); int gb_ap_init(void) { - ap_workqueue = alloc_workqueue("greybus_ap", 0, 1); + ap_workqueue = alloc_ordered_workqueue("greybus_ap", 0); if (!ap_workqueue) return -ENOMEM; -- cgit v0.10.2 From 45a706368d9b162dde2455c305158131af37131d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 22 Jan 2015 21:19:25 +0800 Subject: greybus: es1.c: wait until the last possible minute to start the svc messages When initializing the USB device, we were starting up the svc message queue before the cport urbs were allocated. This might not be an issue for "slower" machines, but not having any allocated urbs for a cport might be an issue if we were to handle svc messages. So wait until everything is properly initialized and allocated before starting the svc urb. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 2ec5d7b..bbf1bd1 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -559,9 +559,6 @@ static int ap_probe(struct usb_interface *interface, usb_rcvintpipe(udev, es1->svc_endpoint), es1->svc_buffer, ES1_SVC_MSG_SIZE, svc_in_callback, hd, svc_interval); - retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); - if (retval) - goto error; /* Allocate buffers for our cport in messages and start them up */ for (i = 0; i < NUM_CPORT_IN_URB; ++i) { @@ -598,6 +595,11 @@ static int ap_probe(struct usb_interface *interface, es1->cport_out_urb_busy[i] = false; /* just to be anal */ } + /* Start up our svc urb, which allows events to start flowing */ + retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); + if (retval) + goto error; + return 0; error: ap_disconnect(interface); -- cgit v0.10.2 From 15d651b0dba16a81285686bf52f4d5b1656362d8 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 23 Jan 2015 13:07:45 +0530 Subject: greybus: spi: add bridged-PHY spi protocol driver Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 79af812..a22ad69 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -15,6 +15,7 @@ gb-phy-y := gpb.o \ pwm.o \ gpio.o \ i2c.o \ + spi.o \ usb.o # Prefix all modules with gb- diff --git a/drivers/staging/greybus/gpb.c b/drivers/staging/greybus/gpb.c index 0776df6..5f080d4 100644 --- a/drivers/staging/greybus/gpb.c +++ b/drivers/staging/greybus/gpb.c @@ -45,8 +45,14 @@ static int __init gpbridge_init(void) pr_err("error initializing usb protocol\n"); goto error_i2c; } + if (gb_spi_protocol_init()) { + pr_err("error initializing usb protocol\n"); + goto error_spi; + } return 0; +error_spi: + gb_i2c_protocol_exit(); error_i2c: gb_usb_protocol_exit(); error_usb: @@ -63,6 +69,7 @@ error_gpio: static void __exit gpbridge_exit(void) { + gb_spi_protocol_exit(); gb_i2c_protocol_exit(); gb_usb_protocol_exit(); gb_sdio_protocol_exit(); diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index e65cc18..2d01000 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -81,6 +81,9 @@ extern void gb_usb_protocol_exit(void); extern int gb_i2c_protocol_init(void); extern void gb_i2c_protocol_exit(void); +extern int gb_spi_protocol_init(void); +extern void gb_spi_protocol_exit(void); + #define gb_protocol_driver(__protocol) \ static int __init protocol_init(void) \ { \ diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c new file mode 100644 index 0000000..1185904 --- /dev/null +++ b/drivers/staging/greybus/spi.c @@ -0,0 +1,443 @@ +/* + * SPI bridge driver for the Greybus "generic" SPI module. + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include + +#include "greybus.h" + +struct gb_spi { + struct gb_connection *connection; + u8 version_major; + u8 version_minor; + + /* Modes supported by spi controller */ + u16 mode; + /* constraints of the spi controller */ + u16 flags; + + /* + * copied from kernel: + * + * A mask indicating which values of bits_per_word are supported by the + * controller. Bit n indicates that a bits_per_word n+1 is suported. If + * set, the SPI core will reject any transfer with an unsupported + * bits_per_word. If not set, this value is simply ignored, and it's up + * to the individual driver to perform any validation. + */ + u32 bits_per_word_mask; + + /* + * chipselects will be integral to many controllers; some others might + * use board-specific GPIOs. + */ + u16 num_chipselect; +}; + +/* Version of the Greybus spi protocol we support */ +#define GB_SPI_VERSION_MAJOR 0x00 +#define GB_SPI_VERSION_MINOR 0x01 + +/* Should match up with modes in linux/spi/spi.h */ +#define GB_SPI_MODE_CPHA 0x01 /* clock phase */ +#define GB_SPI_MODE_CPOL 0x02 /* clock polarity */ +#define GB_SPI_MODE_MODE_0 (0|0) /* (original MicroWire) */ +#define GB_SPI_MODE_MODE_1 (0|GB_SPI_MODE_CPHA) +#define GB_SPI_MODE_MODE_2 (GB_SPI_MODE_CPOL|0) +#define GB_SPI_MODE_MODE_3 (GB_SPI_MODE_CPOL|GB_SPI_MODE_CPHA) +#define GB_SPI_MODE_CS_HIGH 0x04 /* chipselect active high? */ +#define GB_SPI_MODE_LSB_FIRST 0x08 /* per-word bits-on-wire */ +#define GB_SPI_MODE_3WIRE 0x10 /* SI/SO signals shared */ +#define GB_SPI_MODE_LOOP 0x20 /* loopback mode */ +#define GB_SPI_MODE_NO_CS 0x40 /* 1 dev/bus, no chipselect */ +#define GB_SPI_MODE_READY 0x80 /* slave pulls low to pause */ + +/* Should match up with flags in linux/spi/spi.h */ +#define GB_SPI_FLAG_HALF_DUPLEX BIT(0) /* can't do full duplex */ +#define GB_SPI_FLAG_NO_RX BIT(1) /* can't do buffer read */ +#define GB_SPI_FLAG_NO_TX BIT(2) /* can't do buffer write */ + +/* Greybus spi request types */ +#define GB_SPI_TYPE_INVALID 0x00 +#define GB_SPI_TYPE_PROTOCOL_VERSION 0x01 +#define GB_SPI_TYPE_MODE 0x02 +#define GB_SPI_TYPE_FLAGS 0x03 +#define GB_SPI_TYPE_BITS_PER_WORD_MASK 0x04 +#define GB_SPI_TYPE_NUM_CHIPSELECT 0x05 +#define GB_SPI_TYPE_TRANSFER 0x06 +#define GB_SPI_TYPE_RESPONSE 0x80 /* OR'd with rest */ + +/* mode request has no payload */ +struct gb_spi_mode_response { + __le16 mode; +}; + +/* flags request has no payload */ +struct gb_spi_flags_response { + __le16 flags; +}; + +/* bits-per-word request has no payload */ +struct gb_spi_bpw_response { + __le32 bits_per_word_mask; +}; + +/* num-chipselects request has no payload */ +struct gb_spi_chipselect_response { + __le16 num_chipselect; +}; + +/** + * struct gb_spi_transfer - a read/write buffer pair + * @speed_hz: Select a speed other than the device default for this transfer. If + * 0 the default (from @spi_device) is used. + * @len: size of rx and tx buffers (in bytes) + * @delay_usecs: microseconds to delay after this transfer before (optionally) + * changing the chipselect status, then starting the next transfer or + * completing this spi_message. + * @cs_change: affects chipselect after this transfer completes + * @bits_per_word: select a bits_per_word other than the device default for this + * transfer. If 0 the default (from @spi_device) is used. + */ +struct gb_spi_transfer { + __le32 speed_hz; + __le32 len; + __le16 delay_usecs; + __u8 cs_change; + __u8 bits_per_word; +}; + +struct gb_spi_transfer_request { + __u8 chip_select; /* of the spi device */ + __u8 mode; /* of the spi device */ + __le16 count; + struct gb_spi_transfer transfers[0]; /* trnasfer_count of these */ +}; + +struct gb_spi_transfer_response { + __u8 data[0]; /* inbound data */ +}; + +/* Routines to transfer data */ +static struct gb_operation * +gb_spi_operation_create(struct gb_connection *connection, + struct spi_message *msg, u32 *total_len) +{ + struct gb_spi_transfer_request *request; + struct spi_device *dev = msg->spi; + struct spi_transfer *xfer; + struct gb_spi_transfer *gb_xfer; + struct gb_operation *operation; + u32 tx_size = 0, rx_size = 0, count = 0, request_size; + void *tx_data; + + /* Find number of transfers queued and tx/rx length in the message */ + list_for_each_entry(xfer, &msg->transfers, transfer_list) { + if (!xfer->tx_buf && !xfer->rx_buf) { + gb_connection_err(connection, + "Bufferless transfer, length %u\n", + xfer->len); + return NULL; + } + + if (xfer->tx_buf) + tx_size += xfer->len; + if (xfer->rx_buf) + rx_size += xfer->len; + + *total_len += xfer->len; + count++; + } + + /* Too many transfers ? */ + if (count > (u32)U16_MAX) { + gb_connection_err(connection, "transfer count (%u) too big", + count); + return NULL; + } + + /* + * In addition to space for all message descriptors we need + * to have enough to hold all tx data. + */ + request_size = sizeof(*request); + request_size += count * sizeof(*gb_xfer); + request_size += tx_size; + + /* Response consists only of incoming data */ + operation = gb_operation_create(connection, GB_SPI_TYPE_TRANSFER, + request_size, rx_size); + if (!operation) + return NULL; + + request = operation->request->payload; + request->count = count; + request->mode = dev->mode; + request->chip_select = dev->chip_select; + + gb_xfer = &request->transfers[0]; + tx_data = gb_xfer + count; /* place tx data after last gb_xfer */ + + /* Fill in the transfers array */ + list_for_each_entry(xfer, &msg->transfers, transfer_list) { + gb_xfer->speed_hz = cpu_to_le16(xfer->speed_hz); + gb_xfer->len = cpu_to_le32(xfer->len); + gb_xfer->delay_usecs = cpu_to_le16(xfer->delay_usecs); + gb_xfer->cs_change = xfer->cs_change; + gb_xfer->bits_per_word = xfer->bits_per_word; + gb_xfer++; + + /* Copy tx data */ + if (xfer->tx_buf) { + memcpy(tx_data, xfer->tx_buf, xfer->len); + tx_data += xfer->len; + } + } + + return operation; +} + +static void gb_spi_decode_response(struct spi_message *msg, + struct gb_spi_transfer_response *response) +{ + struct spi_transfer *xfer; + void *rx_data = response->data; + + list_for_each_entry(xfer, &msg->transfers, transfer_list) { + /* Copy rx data */ + if (xfer->rx_buf) { + memcpy(xfer->rx_buf, rx_data, xfer->len); + rx_data += xfer->len; + } + } +} + +static int gb_spi_transfer_one_message(struct spi_master *master, + struct spi_message *msg) +{ + struct gb_spi *spi = spi_master_get_devdata(master); + struct gb_connection *connection = spi->connection; + struct gb_spi_transfer_response *response; + struct gb_operation *operation; + u32 len = 0; + int ret; + + operation = gb_spi_operation_create(connection, msg, &len); + if (!operation) + return -ENOMEM; + + ret = gb_operation_request_send_sync(operation); + if (!ret) { + response = operation->response->payload; + if (response) + gb_spi_decode_response(msg, response); + } else { + pr_err("transfer operation failed (%d)\n", ret); + } + gb_operation_destroy(operation); + + msg->actual_length = len; + msg->status = 0; + spi_finalize_current_message(master); + + return ret; +} + +static int gb_spi_setup(struct spi_device *spi) +{ + /* Nothing to do for now */ + return 0; +} + +static void gb_spi_cleanup(struct spi_device *spi) +{ + /* Nothing to do for now */ +} + + +/* Routines to get controller infomation */ + +/* Define get_version() routine */ +define_get_version(gb_spi, SPI); + +/* + * Map Greybus spi mode bits/flags/bpw into Linux ones. + * All bits are same for now and so these macro's return same values. + */ +#define gb_spi_mode_map(mode) mode +#define gb_spi_flags_map(flags) flags + +static int gb_spi_mode_operation(struct gb_spi *spi) +{ + struct gb_spi_mode_response response; + u16 mode; + int ret; + + ret = gb_operation_sync(spi->connection, GB_SPI_TYPE_MODE, + NULL, 0, &response, sizeof(response)); + if (ret) + return ret; + + mode = le16_to_cpu(response.mode); + spi->mode = gb_spi_mode_map(mode); + + return 0; +} + +static int gb_spi_flags_operation(struct gb_spi *spi) +{ + struct gb_spi_flags_response response; + u16 flags; + int ret; + + ret = gb_operation_sync(spi->connection, GB_SPI_TYPE_FLAGS, + NULL, 0, &response, sizeof(response)); + if (ret) + return ret; + + flags = le16_to_cpu(response.flags); + spi->flags = gb_spi_flags_map(flags); + + return 0; +} + +static int gb_spi_bpw_operation(struct gb_spi *spi) +{ + struct gb_spi_bpw_response response; + int ret; + + ret = gb_operation_sync(spi->connection, GB_SPI_TYPE_BITS_PER_WORD_MASK, + NULL, 0, &response, sizeof(response)); + if (ret) + return ret; + + spi->bits_per_word_mask = le32_to_cpu(response.bits_per_word_mask); + + return 0; +} + +static int gb_spi_chipselect_operation(struct gb_spi *spi) +{ + struct gb_spi_chipselect_response response; + int ret; + + ret = gb_operation_sync(spi->connection, GB_SPI_TYPE_NUM_CHIPSELECT, + NULL, 0, &response, sizeof(response)); + if (ret) + return ret; + + spi->num_chipselect = le32_to_cpu(response.num_chipselect); + + return 0; +} + +/* + * Initialize the spi device. This includes verifying we can support it (based + * on the protocol version it advertises). If that's OK, we get and cached its + * mode bits & flags. + */ +static int gb_spi_init(struct gb_spi *spi) +{ + int ret; + + /* First thing we need to do is check the version */ + ret = get_version(spi); + if (ret) + return ret; + + /* mode never changes, just get it once */ + ret = gb_spi_mode_operation(spi); + if (ret) + return ret; + + /* flags never changes, just get it once */ + ret = gb_spi_flags_operation(spi); + if (ret) + return ret; + + /* total number of chipselects never changes, just get it once */ + ret = gb_spi_chipselect_operation(spi); + if (ret) + return ret; + + /* bits-per-word-mask never changes, just get it once */ + return gb_spi_bpw_operation(spi); +} + +static int gb_spi_connection_init(struct gb_connection *connection) +{ + struct gb_spi *spi; + struct spi_master *master; + int ret; + + /* Allocate master with space for data */ + master = spi_alloc_master(&connection->dev, sizeof(*spi)); + if (!master) { + gb_connection_err(connection, "cannot alloc SPI master\n"); + return -ENOMEM; + } + + spi = spi_master_get_devdata(master); + spi->connection = connection; + connection->private = master; + + ret = gb_spi_init(spi); + if (ret) + goto out_err; + + master->bus_num = 0; /* How do we get controller id here? */ + master->num_chipselect = spi->num_chipselect; + master->mode_bits = spi->mode; + master->flags = spi->flags; + master->bits_per_word_mask = spi->bits_per_word_mask; + + /* Attach methods */ + master->cleanup = gb_spi_cleanup; + master->setup = gb_spi_setup; + master->transfer_one_message = gb_spi_transfer_one_message; + + ret = spi_register_master(master); + if (!ret) + return 0; + +out_err: + spi_master_put(master); + + return ret; +} + +static void gb_spi_connection_exit(struct gb_connection *connection) +{ + struct spi_master *master = connection->private; + + spi_unregister_master(master); +} + +static struct gb_protocol spi_protocol = { + .name = "spi", + .id = GREYBUS_PROTOCOL_SPI, + .major = 0, + .minor = 1, + .connection_init = gb_spi_connection_init, + .connection_exit = gb_spi_connection_exit, + .request_recv = NULL, +}; + +int gb_spi_protocol_init(void) +{ + return gb_protocol_register(&spi_protocol); +} + +void gb_spi_protocol_exit(void) +{ + gb_protocol_deregister(&spi_protocol); +} -- cgit v0.10.2 From b3b983c2eee8e7464651caa63bbbd6ca4bb65830 Mon Sep 17 00:00:00 2001 From: Michael Scott Date: Tue, 27 Jan 2015 12:14:09 -0800 Subject: greybus: build: android: Fix script which locates .ko files and moves them into ramdisk - Fixed incorrect use of $$GREYBUS_SRC_PATH variable - Added quotes around find pattern to stop shell expansion of "*" Signed-off-by: Michael Scott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Android.mk b/drivers/staging/greybus/Android.mk index 6f13d35..112f4de 100644 --- a/drivers/staging/greybus/Android.mk +++ b/drivers/staging/greybus/Android.mk @@ -29,6 +29,6 @@ build-greybus: android_kernel cd $(GREYBUS_SRC_PATH) &&\ $(MAKE) -j$(MAKE_JOBS) CROSS_COMPILE=$(KERNEL_TOOLS_PREFIX) $(ARGS) mkdir -p $(GREYBUS_MODULE_OUT_PATH) - ko=`find $$GREYBUS_SRC_PATH -type f -name *.ko`;\ + ko=`find $(GREYBUS_SRC_PATH) -type f -name "*.ko"`;\ for i in $$ko; do $(KERNEL_TOOLCHAIN_PATH)strip --strip-unneeded $$i;\ mv $$i $(GREYBUS_MODULE_OUT_PATH)/; done; -- cgit v0.10.2 From f4e6c817b377833a725ba0be80c29fbb59ffd0f7 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 27 Jan 2015 09:08:04 +0530 Subject: greybus: spi:fix sparse warnings Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index 1185904..ad0c179 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -180,7 +180,7 @@ gb_spi_operation_create(struct gb_connection *connection, return NULL; request = operation->request->payload; - request->count = count; + request->count = cpu_to_le16(count); request->mode = dev->mode; request->chip_select = dev->chip_select; @@ -189,7 +189,7 @@ gb_spi_operation_create(struct gb_connection *connection, /* Fill in the transfers array */ list_for_each_entry(xfer, &msg->transfers, transfer_list) { - gb_xfer->speed_hz = cpu_to_le16(xfer->speed_hz); + gb_xfer->speed_hz = cpu_to_le32(xfer->speed_hz); gb_xfer->len = cpu_to_le32(xfer->len); gb_xfer->delay_usecs = cpu_to_le16(xfer->delay_usecs); gb_xfer->cs_change = xfer->cs_change; @@ -335,7 +335,7 @@ static int gb_spi_chipselect_operation(struct gb_spi *spi) if (ret) return ret; - spi->num_chipselect = le32_to_cpu(response.num_chipselect); + spi->num_chipselect = le16_to_cpu(response.num_chipselect); return 0; } -- cgit v0.10.2 From 5f345a5d394270596f532db6611b12a1377fb622 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Tue, 3 Feb 2015 13:17:39 -0500 Subject: greybus: operation: add missing gb_operation_response_send() export Export gb_operation_response_send() for other modules Signed-off-by: Matt Porter Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 82ff306..50498ec 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -734,6 +734,7 @@ int gb_operation_response_send(struct gb_operation *operation, int errno) return gb_message_send(operation->response); } +EXPORT_SYMBOL_GPL(gb_operation_response_send); /* * This function is called when a buffer send request has completed. -- cgit v0.10.2 From 067f3b6bfaa132269756e4e6d0c61360f8d6a4b5 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 12 Feb 2015 11:22:47 +0800 Subject: greybus: connection: fix non-atomic allocations under spin lock Use GFP_ATOMIC for IDA memory allocations under spin lock, which must not sleep. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index c805022..5f60e83 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -63,7 +63,7 @@ static bool gb_connection_hd_cport_id_alloc(struct gb_connection *connection) int id; spin_lock_irq(&gb_connections_lock); - id = ida_simple_get(ida, 0, HOST_DEV_CPORT_ID_MAX, GFP_KERNEL); + id = ida_simple_get(ida, 0, HOST_DEV_CPORT_ID_MAX, GFP_ATOMIC); spin_unlock_irq(&gb_connections_lock); if (id < 0) return false; -- cgit v0.10.2 From 48d7077c007d27851952861d002d660b552b9888 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 13 Feb 2015 11:28:09 +0800 Subject: greybus: bundle: fix sleep-while-atomic in gb_bundle_destroy Make sure to release the spin lock protecting the interface bundle lists before tearing down the connections and removing the bundle device, which are operations that may sleep. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index d020660..93f80dc 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -126,6 +126,7 @@ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 interface_id) */ void gb_bundle_destroy(struct gb_interface *intf) { + LIST_HEAD(list); struct gb_bundle *bundle; struct gb_bundle *temp; @@ -133,12 +134,14 @@ void gb_bundle_destroy(struct gb_interface *intf) return; spin_lock_irq(&gb_bundles_lock); - list_for_each_entry_safe(bundle, temp, &intf->bundles, links) { + list_splice_init(&intf->bundles, &list); + spin_unlock_irq(&gb_bundles_lock); + + list_for_each_entry_safe(bundle, temp, &list, links) { list_del(&bundle->links); gb_bundle_connections_exit(bundle); device_del(&bundle->dev); } - spin_unlock_irq(&gb_bundles_lock); } int gb_bundle_init(struct gb_interface *intf, u8 bundle_id, u8 device_id) -- cgit v0.10.2 From 036aad9d0224f6f29c08abe102df709a27f68c17 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Tue, 17 Feb 2015 10:48:23 -0500 Subject: greybus: gpio: add interrupt handling support Adds gpio interrupt handling support using an irqchip/irqdomain instantiation inside the GB GPIO driver. This implementation works on older kernels such as 3.10 that do not have the gpiolib irqchip helpers. Any line on a Greybus gpiochip may be configured as an interrupt. Once configured, IRQ event messages received from a module fire off the registered interrupt handler. Signed-off-by: Matt Porter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 85d89b8..a55327c 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include "greybus.h" struct gb_gpio_line { @@ -30,9 +32,16 @@ struct gb_gpio_controller { struct gb_gpio_line *lines; struct gpio_chip chip; + struct irq_chip irqc; + struct irq_chip *irqchip; + struct irq_domain *irqdomain; + unsigned int irq_base; + irq_flow_handler_t irq_handler; + unsigned int irq_default_type; }; #define gpio_chip_to_gb_gpio_controller(chip) \ container_of(chip, struct gb_gpio_controller, chip) +#define irq_data_to_gpio_chip(d) (d->domain->host_data) /* Version of the Greybus GPIO protocol we support */ #define GB_GPIO_VERSION_MAJOR 0x00 @@ -50,6 +59,11 @@ struct gb_gpio_controller { #define GB_GPIO_TYPE_GET_VALUE 0x08 #define GB_GPIO_TYPE_SET_VALUE 0x09 #define GB_GPIO_TYPE_SET_DEBOUNCE 0x0a +#define GB_GPIO_TYPE_IRQ_TYPE 0x0b +#define GB_GPIO_TYPE_IRQ_ACK 0x0c +#define GB_GPIO_TYPE_IRQ_MASK 0x0d +#define GB_GPIO_TYPE_IRQ_UNMASK 0x0e +#define GB_GPIO_TYPE_IRQ_EVENT 0x0f #define GB_GPIO_TYPE_RESPONSE 0x80 /* OR'd with rest */ #define GB_GPIO_DEBOUNCE_USEC_DEFAULT 0 /* microseconds */ @@ -106,6 +120,32 @@ struct gb_gpio_set_debounce_request { }; /* debounce response has no payload */ +struct gb_gpio_irq_type_request { + __u8 which; + __u8 type; +}; +/* irq type response has no payload */ + +struct gb_gpio_irq_mask_request { + __u8 which; +}; +/* irq mask response has no payload */ + +struct gb_gpio_irq_unmask_request { + __u8 which; +}; +/* irq unmask response has no payload */ + +struct gb_gpio_irq_ack_request { + __u8 which; +}; +/* irq ack response has no payload */ + +/* irq event requests originate on another module and are handled on the AP */ +struct gb_gpio_irq_event_request { + __u8 which; +}; +/* irq event response has no payload */ /* Define get_version() routine */ define_get_version(gb_gpio_controller, GPIO); @@ -280,6 +320,120 @@ static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *ggc, return ret; } +static void gb_gpio_ack_irq(struct irq_data *d) +{ + struct gpio_chip *chip = irq_data_to_gpio_chip(d); + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_irq_ack_request request; + int ret; + + request.which = d->hwirq; + ret = gb_operation_sync(ggc->connection, + GB_GPIO_TYPE_IRQ_ACK, + &request, sizeof(request), NULL, 0); + if (ret) + pr_err("irq ack operation failed (%d)\n", ret); +} + +static void gb_gpio_mask_irq(struct irq_data *d) +{ + struct gpio_chip *chip = irq_data_to_gpio_chip(d); + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_irq_mask_request request; + int ret; + + request.which = d->hwirq; + ret = gb_operation_sync(ggc->connection, + GB_GPIO_TYPE_IRQ_MASK, + &request, sizeof(request), NULL, 0); + if (ret) + pr_err("irq mask operation failed (%d)\n", ret); +} + +static void gb_gpio_unmask_irq(struct irq_data *d) +{ + struct gpio_chip *chip = irq_data_to_gpio_chip(d); + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_irq_unmask_request request; + int ret; + + request.which = d->hwirq; + ret = gb_operation_sync(ggc->connection, + GB_GPIO_TYPE_IRQ_UNMASK, + &request, sizeof(request), NULL, 0); + if (ret) + pr_err("irq unmask operation failed (%d)\n", ret); +} + +static int gb_gpio_irq_set_type(struct irq_data *d, unsigned int type) +{ + struct gpio_chip *chip = irq_data_to_gpio_chip(d); + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_irq_type_request request; + int ret = 0; + + request.which = d->hwirq; + request.type = type; + + switch (type) { + case IRQ_TYPE_NONE: + break; + case IRQ_TYPE_EDGE_RISING: + case IRQ_TYPE_EDGE_FALLING: + case IRQ_TYPE_EDGE_BOTH: + case IRQ_TYPE_LEVEL_LOW: + case IRQ_TYPE_LEVEL_HIGH: + ret = gb_operation_sync(ggc->connection, + GB_GPIO_TYPE_IRQ_TYPE, + &request, sizeof(request), NULL, 0); + if (ret) + pr_err("irq type operation failed (%d)\n", ret); + break; + default: + pr_err("No such irq type %d", type); + ret = -EINVAL; + } + + return ret; +} + +static void gb_gpio_request_recv(u8 type, struct gb_operation *op) +{ + struct gb_gpio_controller *ggc; + struct gb_connection *connection; + struct gb_message *request; + struct gb_gpio_irq_event_request *event; + int irq; + struct irq_desc *desc; + int ret; + + if (type != GB_GPIO_TYPE_IRQ_EVENT) { + pr_err("unsupported unsolicited request\n"); + return; + } + + connection = op->connection; + ggc = connection->private; + + request = op->request; + event = request->payload; + if (event->which > ggc->line_max) { + pr_err("Unsupported hw irq %d\n", event->which); + return; + } + irq = gpio_to_irq(ggc->irq_base + event->which); + desc = irq_to_desc(irq); + + /* Dispatch interrupt */ + local_irq_disable(); + handle_simple_irq(irq, desc); + local_irq_enable(); + + ret = gb_operation_response_send(op, 0); + if (ret) + pr_err("error %d sending response status %d\n", ret, 0); +} + static int gb_gpio_request(struct gpio_chip *chip, unsigned offset) { struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); @@ -399,14 +553,6 @@ static int gb_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, return 0; /* XXX */ } -static int gb_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ - if (offset >= chip->ngpio) - return -EINVAL; - - return 0; /* XXX */ -} - static void gb_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) { return; /* XXX */ @@ -436,10 +582,148 @@ static int gb_gpio_controller_setup(struct gb_gpio_controller *gb_gpio_controlle return ret; } +/** + * gb_gpio_irq_map() - maps an IRQ into a GB gpio irqchip + * @d: the irqdomain used by this irqchip + * @irq: the global irq number used by this GB gpio irqchip irq + * @hwirq: the local IRQ/GPIO line offset on this GB gpio + * + * This function will set up the mapping for a certain IRQ line on a + * GB gpio by assigning the GB gpio as chip data, and using the irqchip + * stored inside the GB gpio. + */ +static int gb_gpio_irq_map(struct irq_domain *domain, unsigned int irq, + irq_hw_number_t hwirq) +{ + struct gpio_chip *chip = domain->host_data; + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + + irq_set_chip_data(irq, ggc); + irq_set_chip_and_handler(irq, ggc->irqchip, ggc->irq_handler); +#ifdef CONFIG_ARM + set_irq_flags(irq, IRQF_VALID); +#else + irq_set_noprobe(irq); +#endif + /* + * No set-up of the hardware will happen if IRQ_TYPE_NONE + * is passed as default type. + */ + if (ggc->irq_default_type != IRQ_TYPE_NONE) + irq_set_irq_type(irq, ggc->irq_default_type); + + return 0; +} + +static void gb_gpio_irq_unmap(struct irq_domain *d, unsigned int irq) +{ +#ifdef CONFIG_ARM + set_irq_flags(irq, 0); +#endif + irq_set_chip_and_handler(irq, NULL, NULL); + irq_set_chip_data(irq, NULL); +} + +static const struct irq_domain_ops gb_gpio_domain_ops = { + .map = gb_gpio_irq_map, + .unmap = gb_gpio_irq_unmap, +}; + +/** + * gb_gpio_irqchip_remove() - removes an irqchip added to a gb_gpio_controller + * @ggc: the gb_gpio_controller to remove the irqchip from + * + * This is called only from gb_gpio_remove() + */ +static void gb_gpio_irqchip_remove(struct gb_gpio_controller *ggc) +{ + unsigned int offset; + + /* Remove all IRQ mappings and delete the domain */ + if (ggc->irqdomain) { + for (offset = 0; offset < (ggc->line_max + 1); offset++) + irq_dispose_mapping(irq_find_mapping(ggc->irqdomain, offset)); + irq_domain_remove(ggc->irqdomain); + } + + if (ggc->irqchip) { + ggc->irqchip = NULL; + } +} + + +/** + * gb_gpio_irqchip_add() - adds an irqchip to a gpio chip + * @chip: the gpio chip to add the irqchip to + * @irqchip: the irqchip to add to the adapter + * @first_irq: if not dynamically assigned, the base (first) IRQ to + * allocate gpio irqs from + * @handler: the irq handler to use (often a predefined irq core function) + * @type: the default type for IRQs on this irqchip, pass IRQ_TYPE_NONE + * to have the core avoid setting up any default type in the hardware. + * + * This function closely associates a certain irqchip with a certain + * gpio chip, providing an irq domain to translate the local IRQs to + * global irqs, and making sure that the gpio chip + * is passed as chip data to all related functions. Driver callbacks + * need to use container_of() to get their local state containers back + * from the gpio chip passed as chip data. An irqdomain will be stored + * in the gpio chip that shall be used by the driver to handle IRQ number + * translation. The gpio chip will need to be initialized and registered + * before calling this function. + */ +static int gb_gpio_irqchip_add(struct gpio_chip *chip, + struct irq_chip *irqchip, + unsigned int first_irq, + irq_flow_handler_t handler, + unsigned int type) +{ + struct gb_gpio_controller *ggc; + unsigned int offset; + unsigned irq_base; + + if (!chip || !irqchip) + return -EINVAL; + + ggc = gpio_chip_to_gb_gpio_controller(chip); + + ggc->irqchip = irqchip; + ggc->irq_handler = handler; + ggc->irq_default_type = type; + ggc->irqdomain = irq_domain_add_simple(NULL, + ggc->line_max + 1, first_irq, + &gb_gpio_domain_ops, chip); + if (!ggc->irqdomain) { + ggc->irqchip = NULL; + return -EINVAL; + } + + /* + * Prepare the mapping since the irqchip shall be orthogonal to + * any gpio calls. If the first_irq was zero, this is + * necessary to allocate descriptors for all IRQs. + */ + for (offset = 0; offset < (ggc->line_max + 1); offset++) { + irq_base = irq_create_mapping(ggc->irqdomain, offset); + if (offset == 0) + ggc->irq_base = irq_base; + } + + return 0; +} + +static int gb_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +{ + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + + return irq_find_mapping(ggc->irqdomain, offset); +} + static int gb_gpio_connection_init(struct gb_connection *connection) { struct gb_gpio_controller *gb_gpio_controller; struct gpio_chip *gpio; + struct irq_chip *irqc; int ret; gb_gpio_controller = kzalloc(sizeof(*gb_gpio_controller), GFP_KERNEL); @@ -452,9 +736,17 @@ static int gb_gpio_connection_init(struct gb_connection *connection) if (ret) goto out_err; + irqc = &gb_gpio_controller->irqc; + irqc->irq_ack = gb_gpio_ack_irq; + irqc->irq_mask = gb_gpio_mask_irq; + irqc->irq_unmask = gb_gpio_unmask_irq; + irqc->irq_set_type = gb_gpio_irq_set_type; + irqc->name = "greybus_gpio"; + gpio = &gb_gpio_controller->chip; gpio->label = "greybus_gpio"; + gpio->dev = &connection->dev; gpio->owner = THIS_MODULE; /* XXX Module get? */ gpio->request = gb_gpio_request; @@ -465,9 +757,8 @@ static int gb_gpio_connection_init(struct gb_connection *connection) gpio->get = gb_gpio_get; gpio->set = gb_gpio_set; gpio->set_debounce = gb_gpio_set_debounce; - gpio->to_irq = gb_gpio_to_irq; gpio->dbg_show = gb_gpio_dbg_show; - + gpio->to_irq = gb_gpio_to_irq; gpio->base = -1; /* Allocate base dynamically */ gpio->ngpio = gb_gpio_controller->line_max + 1; gpio->can_sleep = true; /* XXX */ @@ -475,10 +766,20 @@ static int gb_gpio_connection_init(struct gb_connection *connection) ret = gpiochip_add(gpio); if (ret) { pr_err("Failed to register GPIO\n"); - return ret; + goto out_err; + } + + ret = gb_gpio_irqchip_add(gpio, irqc, 0, + handle_simple_irq, IRQ_TYPE_NONE); + if (ret) { + pr_err("Couldn't add irqchip to Greybus GPIO controller %d\n", ret); + goto irqchip_err; } return 0; + +irqchip_err: + gb_gpiochip_remove(gpio); out_err: kfree(gb_gpio_controller); return ret; @@ -491,6 +792,7 @@ static void gb_gpio_connection_exit(struct gb_connection *connection) if (!gb_gpio_controller) return; + gb_gpio_irqchip_remove(gb_gpio_controller); gb_gpiochip_remove(&gb_gpio_controller->chip); /* kref_put(gb_gpio_controller->connection) */ kfree(gb_gpio_controller); @@ -503,7 +805,7 @@ static struct gb_protocol gpio_protocol = { .minor = 1, .connection_init = gb_gpio_connection_init, .connection_exit = gb_gpio_connection_exit, - .request_recv = NULL, /* no incoming requests */ + .request_recv = gb_gpio_request_recv, }; int gb_gpio_protocol_init(void) -- cgit v0.10.2 From 35a64f2c492867e5e404b7620c5784603caae8f1 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 13 Feb 2015 14:58:04 +0800 Subject: greybus: gpio: fix memory leaks at init and exit Fix three related memory leaks in the init an exit callbacks, where the gpio-lines array was never freed at all and the controller data wasn't freed in the init error path. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index a55327c..81901bd 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -734,7 +734,7 @@ static int gb_gpio_connection_init(struct gb_connection *connection) ret = gb_gpio_controller_setup(gb_gpio_controller); if (ret) - goto out_err; + goto err_free_controller; irqc = &gb_gpio_controller->irqc; irqc->irq_ack = gb_gpio_ack_irq; @@ -766,7 +766,7 @@ static int gb_gpio_connection_init(struct gb_connection *connection) ret = gpiochip_add(gpio); if (ret) { pr_err("Failed to register GPIO\n"); - goto out_err; + goto err_free_lines; } ret = gb_gpio_irqchip_add(gpio, irqc, 0, @@ -780,7 +780,9 @@ static int gb_gpio_connection_init(struct gb_connection *connection) irqchip_err: gb_gpiochip_remove(gpio); -out_err: +err_free_lines: + kfree(gb_gpio_controller->lines); +err_free_controller: kfree(gb_gpio_controller); return ret; } @@ -795,6 +797,7 @@ static void gb_gpio_connection_exit(struct gb_connection *connection) gb_gpio_irqchip_remove(gb_gpio_controller); gb_gpiochip_remove(&gb_gpio_controller->chip); /* kref_put(gb_gpio_controller->connection) */ + kfree(gb_gpio_controller->lines); kfree(gb_gpio_controller); } -- cgit v0.10.2 From 2bf4c87605879758f299953fa5cf4a4ecb6a4edb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 2 Mar 2015 08:52:07 -0800 Subject: greybus: es2: fix USB id to not be the same as ES1 We don't want to bind to the ES1 device, that would be bad. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 4154cce..d8d45be 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -29,8 +29,8 @@ #define ES1_GBUF_MSG_SIZE_MAX PAGE_SIZE static const struct usb_device_id id_table[] = { - /* Made up numbers for the SVC USB Bridge in ES1 */ - { USB_DEVICE(0xffff, 0x0001) }, + /* Made up numbers for the SVC USB Bridge in ES2 */ + { USB_DEVICE(0xffff, 0x0002) }, { }, }; MODULE_DEVICE_TABLE(usb, id_table); -- cgit v0.10.2 From 184ab534de842a1baf08a0d7f3621b26bcea44dc Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 2 Mar 2015 12:34:40 +0100 Subject: greybus: operation: fix locking issues Fix unconditional re-enabling of interrupts in various operation functions that can all be called with local interrupts disabled from USB completion handlers. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 50498ec..5e859c0 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -94,6 +94,7 @@ static DEFINE_SPINLOCK(gb_operations_lock); */ static bool gb_operation_result_set(struct gb_operation *operation, int result) { + unsigned long flags; int prev; if (result == -EINPROGRESS) { @@ -104,13 +105,13 @@ static bool gb_operation_result_set(struct gb_operation *operation, int result) * and record an implementation error if it's * set at any other time. */ - spin_lock_irq(&gb_operations_lock); + spin_lock_irqsave(&gb_operations_lock, flags); prev = operation->errno; if (prev == -EBADR) operation->errno = result; else operation->errno = -EILSEQ; - spin_unlock_irq(&gb_operations_lock); + spin_unlock_irqrestore(&gb_operations_lock, flags); WARN_ON(prev != -EBADR); return true; @@ -128,11 +129,11 @@ static bool gb_operation_result_set(struct gb_operation *operation, int result) if (WARN_ON(result == -EBADR)) result = -EILSEQ; /* Nobody should be setting -EBADR */ - spin_lock_irq(&gb_operations_lock); + spin_lock_irqsave(&gb_operations_lock, flags); prev = operation->errno; if (prev == -EINPROGRESS) operation->errno = result; /* First and final result */ - spin_unlock_irq(&gb_operations_lock); + spin_unlock_irqrestore(&gb_operations_lock, flags); return prev == -EINPROGRESS; } @@ -151,15 +152,16 @@ static struct gb_operation * gb_operation_find(struct gb_connection *connection, u16 operation_id) { struct gb_operation *operation; + unsigned long flags; bool found = false; - spin_lock_irq(&gb_operations_lock); + spin_lock_irqsave(&gb_operations_lock, flags); list_for_each_entry(operation, &connection->operations, links) if (operation->id == operation_id) { found = true; break; } - spin_unlock_irq(&gb_operations_lock); + spin_unlock_irqrestore(&gb_operations_lock, flags); return found ? operation : NULL; } @@ -490,6 +492,7 @@ gb_operation_create_common(struct gb_connection *connection, u8 type, { struct greybus_host_device *hd = connection->hd; struct gb_operation *operation; + unsigned long flags; gfp_t gfp_flags; /* @@ -525,9 +528,9 @@ gb_operation_create_common(struct gb_connection *connection, u8 type, init_completion(&operation->completion); kref_init(&operation->kref); - spin_lock_irq(&gb_operations_lock); + spin_lock_irqsave(&gb_operations_lock, flags); list_add_tail(&operation->links, &connection->operations); - spin_unlock_irq(&gb_operations_lock); + spin_unlock_irqrestore(&gb_operations_lock, flags); return operation; @@ -593,13 +596,14 @@ void gb_operation_get(struct gb_operation *operation) static void _gb_operation_destroy(struct kref *kref) { struct gb_operation *operation; + unsigned long flags; operation = container_of(kref, struct gb_operation, kref); /* XXX Make sure it's not in flight */ - spin_lock_irq(&gb_operations_lock); + spin_lock_irqsave(&gb_operations_lock, flags); list_del(&operation->links); - spin_unlock_irq(&gb_operations_lock); + spin_unlock_irqrestore(&gb_operations_lock, flags); gb_operation_message_free(operation->response); gb_operation_message_free(operation->request); -- cgit v0.10.2 From d1b20d72ae01a2846ed4cad7bfef0bea717ffb68 Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Mon, 2 Mar 2015 17:32:43 +0100 Subject: greybus: gpio.c: fix a bad irq number When it receive an interrupt, the function gb_gpio_request_recv doesn't use the good gpio number to get the irq number. Then, the expected irq is never fired. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 81901bd..4af5050 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -421,7 +421,7 @@ static void gb_gpio_request_recv(u8 type, struct gb_operation *op) pr_err("Unsupported hw irq %d\n", event->which); return; } - irq = gpio_to_irq(ggc->irq_base + event->which); + irq = gpio_to_irq(ggc->chip.base + event->which); desc = irq_to_desc(irq); /* Dispatch interrupt */ -- cgit v0.10.2 From 8f5eadb7ea6a0c1cbedbfd33d9d0b94dac400d90 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 2 Mar 2015 09:55:26 +0100 Subject: greybus: connection: fix locking in gb_hd_connection_find Fix unconditional re-enabling of interrupts in gb_hd_connection_find, which can be called with local interrupts disabled from the USB completion handler. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 5f60e83..3ec984c 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -18,14 +18,15 @@ struct gb_connection *gb_hd_connection_find(struct greybus_host_device *hd, u16 cport_id) { struct gb_connection *connection = NULL; + unsigned long flags; - spin_lock_irq(&gb_connections_lock); + spin_lock_irqsave(&gb_connections_lock, flags); list_for_each_entry(connection, &hd->connections, hd_links) if (connection->hd_cport_id == cport_id) goto found; connection = NULL; found: - spin_unlock_irq(&gb_connections_lock); + spin_unlock_irqrestore(&gb_connections_lock, flags); return connection; } -- cgit v0.10.2 From b908dec468c95d51922cb72a076fde813622ee54 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 10 Mar 2015 14:41:12 +0530 Subject: greybus: gpb: Fix print mistakes Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpb.c b/drivers/staging/greybus/gpb.c index 5f080d4..6177105 100644 --- a/drivers/staging/greybus/gpb.c +++ b/drivers/staging/greybus/gpb.c @@ -42,11 +42,11 @@ static int __init gpbridge_init(void) goto error_usb; } if (gb_i2c_protocol_init()) { - pr_err("error initializing usb protocol\n"); + pr_err("error initializing i2c protocol\n"); goto error_i2c; } if (gb_spi_protocol_init()) { - pr_err("error initializing usb protocol\n"); + pr_err("error initializing spi protocol\n"); goto error_spi; } return 0; -- cgit v0.10.2 From 96eab779e1985fd0b39426d288d3af38e3bce50c Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 16 Mar 2015 16:49:37 +0530 Subject: greybus: hid: add HID class driver This adds HID transport layer driver for Greybus. Most of the stuff is implemented, but is untested. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index a22ad69..6cb08ae 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -14,6 +14,7 @@ gb-phy-y := gpb.o \ uart.o \ pwm.o \ gpio.o \ + hid.o \ i2c.o \ spi.o \ usb.o diff --git a/drivers/staging/greybus/gpb.c b/drivers/staging/greybus/gpb.c index 6177105..931d739 100644 --- a/drivers/staging/greybus/gpb.c +++ b/drivers/staging/greybus/gpb.c @@ -49,8 +49,14 @@ static int __init gpbridge_init(void) pr_err("error initializing spi protocol\n"); goto error_spi; } + if (gb_hid_protocol_init()) { + pr_err("error initializing hid protocol\n"); + goto error_hid; + } return 0; +error_hid: + gb_spi_protocol_exit(); error_spi: gb_i2c_protocol_exit(); error_i2c: @@ -69,6 +75,7 @@ error_gpio: static void __exit gpbridge_exit(void) { + gb_hid_protocol_exit(); gb_spi_protocol_exit(); gb_i2c_protocol_exit(); gb_usb_protocol_exit(); diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c new file mode 100644 index 0000000..17ca476 --- /dev/null +++ b/drivers/staging/greybus/hid.c @@ -0,0 +1,565 @@ +/* + * HID class driver for the Greybus. + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include +#include + +#include "greybus.h" + +/* Version of the Greybus hid protocol we support */ +#define GB_HID_VERSION_MAJOR 0x00 +#define GB_HID_VERSION_MINOR 0x01 + +/* Greybus HID request types */ +#define GB_HID_TYPE_INVALID 0x00 +#define GB_HID_TYPE_PROTOCOL_VERSION 0x01 +#define GB_HID_TYPE_GET_DESC 0x02 +#define GB_HID_TYPE_GET_REPORT_DESC 0x03 +#define GB_HID_TYPE_PWR_ON 0x04 +#define GB_HID_TYPE_PWR_OFF 0x05 +#define GB_HID_TYPE_GET_REPORT 0x06 +#define GB_HID_TYPE_SET_REPORT 0x07 /* Feature or Output, via control pipe */ +#define GB_HID_TYPE_OUTPUT_REPORT 0x08 /* Output report via interrupt pipe */ +#define GB_HID_TYPE_IRQ_EVENT 0x09 +#define GB_HID_TYPE_RESPONSE 0x80 /* OR'd with rest */ + +/* Report type */ +#define GB_HID_INPUT_REPORT 0 +#define GB_HID_OUTPUT_REPORT 1 +#define GB_HID_FEATURE_REPORT 2 + +/* Different request/response structures */ +/* HID get descriptor response */ +struct gb_hid_desc_response { + __u8 bLength; + __le16 wReportDescLength; + __le16 bcdHID; + __le16 wProductID; + __le16 wVendorID; + __u8 bCountryCode; +} __packed; + +/* HID get report request/response */ +struct gb_hid_get_report_request { + __u8 report_type; + __u8 report_id; +}; + +/* HID set report request */ +struct gb_hid_set_report_request { + __u8 report_type; + __u8 report_id; + __u8 report[0]; +}; + +/* HID input report request, via interrupt pipe */ +struct gb_hid_input_report_request { + __u8 report[0]; +}; + +/* Greybus HID device's structure */ +struct gb_hid { + struct gb_connection *connection; + u8 version_major; + u8 version_minor; + + struct hid_device *hid; + struct gb_hid_desc_response hdesc; + + unsigned long flags; +#define GB_HID_STARTED 0x01 +#define GB_HID_READ_PENDING 0x04 + + unsigned int bufsize; + char *inbuf; +}; + +static DEFINE_MUTEX(gb_hid_open_mutex); + +/* Routines to get controller's infomation over greybus */ + +/* Define get_version() routine */ +define_get_version(gb_hid, HID); + +/* Operations performed on greybus */ +static int gb_hid_get_desc(struct gb_hid *ghid) +{ + return gb_operation_sync(ghid->connection, GB_HID_TYPE_GET_DESC, NULL, + 0, &ghid->hdesc, sizeof(ghid->hdesc)); +} + +static int gb_hid_get_report_desc(struct gb_hid *ghid, char *rdesc) +{ + return gb_operation_sync(ghid->connection, GB_HID_TYPE_GET_REPORT_DESC, + NULL, 0, rdesc, + le16_to_cpu(ghid->hdesc.wReportDescLength)); +} + +static int gb_hid_set_power(struct gb_hid *ghid, int type) +{ + return gb_operation_sync(ghid->connection, type, NULL, 0, NULL, 0); +} + +static int gb_hid_get_report(struct gb_hid *ghid, u8 report_type, u8 report_id, + unsigned char *buf, int len) +{ + struct gb_hid_get_report_request request; + + request.report_type = report_type; + request.report_id = report_id; + + return gb_operation_sync(ghid->connection, GB_HID_TYPE_GET_REPORT, + &request, sizeof(request), buf, len); +} + +/* + * @raw: true: use SET_REPORT HID command, false: send plain OUTPUT report. + * + * Use SET_REPORT for feature reports or if the device does not support the + * output plain report. + */ +static int gb_hid_set_report(struct gb_hid *ghid, u8 report_type, u8 report_id, + unsigned char *buf, int len, int raw) +{ + struct gb_hid_set_report_request *request; + struct gb_operation *operation; + int ret, size = sizeof(*request) + len - 1; + int type = raw ? GB_HID_TYPE_SET_REPORT : GB_HID_TYPE_OUTPUT_REPORT; + + operation = gb_operation_create(ghid->connection, type, size, 0); + if (!operation) + return -ENOMEM; + + request = operation->request->payload; + request->report_type = report_type; + request->report_id = report_id; + memcpy(request->report, buf, len); + + ret = gb_operation_request_send_sync(operation); + if (ret) + pr_err("%s: operation failed (%d)\n", __func__, ret); + else + ret = len; + + gb_operation_destroy(operation); + return ret; +} + +static void gb_hid_irq_handler(u8 type, struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_hid *ghid = connection->private; + struct gb_hid_input_report_request *request = op->request->payload; + int ret, size; + + if (type != GB_HID_TYPE_IRQ_EVENT) { + pr_err("unsupported unsolicited request\n"); + return; + } + + ret = gb_operation_response_send(op, 0); + if (ret) + pr_err("%s: error %d sending response status %d\n", __func__, + ret, 0); + + size = request->report[0] | request->report[1] << 8; + if (!size) { + pr_err("%s: size can't be zero.\n", __func__); + return; + } + + if (test_bit(GB_HID_STARTED, &ghid->flags)) + hid_input_report(ghid->hid, HID_INPUT_REPORT, + request->report + 2, size - 2, 1); +} + + +static int gb_hid_report_len(struct hid_report *report) +{ + return ((report->size - 1) >> 3) + 1 + + report->device->report_enum[report->type].numbered; +} + +static void gb_hid_find_max_report(struct hid_device *hid, unsigned int type, + unsigned int *max) +{ + struct hid_report *report; + unsigned int size; + + list_for_each_entry(report, &hid->report_enum[type].report_list, list) { + size = gb_hid_report_len(report); + if (*max < size) + *max = size; + } +} + +static void gb_hid_free_buffers(struct gb_hid *ghid) +{ + kfree(ghid->inbuf); + ghid->inbuf = NULL; + ghid->bufsize = 0; +} + +static int gb_hid_alloc_buffers(struct gb_hid *ghid, size_t bufsize) +{ + ghid->inbuf = kzalloc(bufsize, GFP_KERNEL); + if (!ghid->inbuf) + return -ENOMEM; + + ghid->bufsize = bufsize; + + return 0; +} + +/* Routines dealing with reports */ +static void gb_hid_init_report(struct gb_hid *ghid, struct hid_report *report) +{ + unsigned int size; + + size = gb_hid_report_len(report); + if (gb_hid_get_report(ghid, report->type, report->id, ghid->inbuf, + size)) + return; + + /* + * hid->driver_lock is held as we are in probe function, + * we just need to setup the input fields, so using + * hid_report_raw_event is safe. + */ + hid_report_raw_event(ghid->hid, report->type, ghid->inbuf, size, 1); +} + +static void gb_hid_init_reports(struct gb_hid *ghid) +{ + struct hid_device *hid = ghid->hid; + struct hid_report *report; + + list_for_each_entry(report, + &hid->report_enum[HID_INPUT_REPORT].report_list, list) + gb_hid_init_report(ghid, report); + + list_for_each_entry(report, + &hid->report_enum[HID_FEATURE_REPORT].report_list, list) + gb_hid_init_report(ghid, report); +} + +static int __gb_hid_get_raw_report(struct hid_device *hid, + unsigned char report_number, __u8 *buf, size_t count, + unsigned char report_type) +{ + struct gb_hid *ghid = hid->driver_data; + int ret; + + if (report_type == HID_OUTPUT_REPORT) + return -EINVAL; + + ret = gb_hid_get_report(ghid, report_type, report_number, buf, count); + if (!ret) + ret = count; + + return ret; +} + +static int __gb_hid_output_raw_report(struct hid_device *hid, __u8 *buf, + size_t len, unsigned char report_type, + bool raw) +{ + struct gb_hid *ghid = hid->driver_data; + int report_id = buf[0]; + int ret; + + if (report_type == HID_INPUT_REPORT) + return -EINVAL; + + if (report_id) { + buf++; + len--; + } + + ret = gb_hid_set_report(ghid, report_type, report_id, buf, len, raw); + if (report_id && ret >= 0) + ret++; /* add report_id to the number of transfered bytes */ + + return 0; +} + +static int gb_hid_raw_request(struct hid_device *hid, unsigned char reportnum, + __u8 *buf, size_t len, unsigned char rtype, + int reqtype) +{ + switch (reqtype) { + case HID_REQ_GET_REPORT: + return __gb_hid_get_raw_report(hid, reportnum, buf, len, rtype); + case HID_REQ_SET_REPORT: + if (buf[0] != reportnum) + return -EINVAL; + return __gb_hid_output_raw_report(hid, buf, len, rtype, true); + default: + return -EIO; + } +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0) +static int gb_hid_output_report(struct hid_device *hid, __u8 *buf, size_t len) +{ + return __gb_hid_output_raw_report(hid, buf, len, HID_OUTPUT_REPORT, + false); +} + +#else + +static int gb_hid_get_raw_report(struct hid_device *hid, + unsigned char reportnum, __u8 *buf, + size_t len, unsigned char rtype) +{ + return gb_hid_raw_request(hid, reportnum, buf, len, rtype, + HID_REQ_GET_REPORT); +} + +static int gb_hid_output_raw_report(struct hid_device *hid, __u8 *buf, + size_t len, unsigned char rtype) +{ + return gb_hid_raw_request(hid, buf[0], buf, len, rtype, + HID_REQ_SET_REPORT); +} +#endif + +/* HID Callbacks */ +static int gb_hid_parse(struct hid_device *hid) +{ + struct gb_hid *ghid = hid->driver_data; + unsigned int rsize; + char *rdesc; + int ret; + + rsize = le16_to_cpu(ghid->hdesc.wReportDescLength); + if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) { + dbg_hid("weird size of report descriptor (%u)\n", rsize); + return -EINVAL; + } + + rdesc = kzalloc(rsize, GFP_KERNEL); + if (!rdesc) { + dbg_hid("couldn't allocate rdesc memory\n"); + return -ENOMEM; + } + + ret = gb_hid_get_report_desc(ghid, rdesc); + if (ret) { + hid_err(hid, "reading report descriptor failed\n"); + goto free_rdesc; + } + + ret = hid_parse_report(hid, rdesc, rsize); + if (ret) + dbg_hid("parsing report descriptor failed\n"); + +free_rdesc: + kfree(rdesc); + + return ret; +} + +static int gb_hid_start(struct hid_device *hid) +{ + struct gb_hid *ghid = hid->driver_data; + unsigned int bufsize = HID_MIN_BUFFER_SIZE; + int ret; + + gb_hid_find_max_report(hid, HID_INPUT_REPORT, &bufsize); + gb_hid_find_max_report(hid, HID_OUTPUT_REPORT, &bufsize); + gb_hid_find_max_report(hid, HID_FEATURE_REPORT, &bufsize); + + if (bufsize > HID_MAX_BUFFER_SIZE) + bufsize = HID_MAX_BUFFER_SIZE; + + ret = gb_hid_alloc_buffers(ghid, bufsize); + if (ret) + return ret; + + if (!(hid->quirks & HID_QUIRK_NO_INIT_REPORTS)) + gb_hid_init_reports(ghid); + + return 0; +} + +static void gb_hid_stop(struct hid_device *hid) +{ + struct gb_hid *ghid = hid->driver_data; + + gb_hid_free_buffers(ghid); +} + +static int gb_hid_open(struct hid_device *hid) +{ + struct gb_hid *ghid = hid->driver_data; + int ret = 0; + + mutex_lock(&gb_hid_open_mutex); + if (!hid->open++) { + ret = gb_hid_set_power(ghid, GB_HID_TYPE_PWR_ON); + if (ret < 0) + hid->open--; + else + set_bit(GB_HID_STARTED, &ghid->flags); + } + mutex_unlock(&gb_hid_open_mutex); + + return ret; +} + +static void gb_hid_close(struct hid_device *hid) +{ + struct gb_hid *ghid = hid->driver_data; + + /* + * Protecting hid->open to make sure we don't restart data acquistion + * due to a resumption we no longer care about.. + */ + mutex_lock(&gb_hid_open_mutex); + if (!--hid->open) { + clear_bit(GB_HID_STARTED, &ghid->flags); + + /* Save some power */ + WARN_ON(gb_hid_set_power(ghid, GB_HID_TYPE_PWR_OFF)); + } + mutex_unlock(&gb_hid_open_mutex); +} + +static int gb_hid_power(struct hid_device *hid, int lvl) +{ + struct gb_hid *ghid = hid->driver_data; + + switch (lvl) { + case PM_HINT_FULLON: + return gb_hid_set_power(ghid, GB_HID_TYPE_PWR_ON); + case PM_HINT_NORMAL: + return gb_hid_set_power(ghid, GB_HID_TYPE_PWR_OFF); + } + + return 0; +} + +/* HID structure to pass callbacks */ +static struct hid_ll_driver gb_hid_ll_driver = { + .parse = gb_hid_parse, + .start = gb_hid_start, + .stop = gb_hid_stop, + .open = gb_hid_open, + .close = gb_hid_close, + .power = gb_hid_power, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0) + .output_report = gb_hid_output_report, + .raw_request = gb_hid_raw_request, +#endif +}; + +static int gb_hid_init(struct gb_hid *ghid) +{ + struct hid_device *hid = ghid->hid; + int ret; + + ret = get_version(ghid); + if (ret) + return ret; + + ret = gb_hid_get_desc(ghid); + if (ret) + return ret; + + hid->version = le16_to_cpu(ghid->hdesc.bcdHID); + hid->vendor = le16_to_cpu(ghid->hdesc.wVendorID); + hid->product = le16_to_cpu(ghid->hdesc.wProductID); + hid->country = ghid->hdesc.bCountryCode; + + hid->driver_data = ghid; + hid->ll_driver = &gb_hid_ll_driver; + hid->dev.parent = &ghid->connection->dev; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0) + hid->hid_get_raw_report = gb_hid_get_raw_report; + hid->hid_output_raw_report = gb_hid_output_raw_report; +#endif +// hid->bus = BUS_GREYBUS; /* Need a bustype for GREYBUS in */ + + /* Set HID device's name */ + snprintf(hid->name, sizeof(hid->name), "%s %04hX:%04hX", + dev_name(&ghid->connection->dev), hid->vendor, hid->product); + + return 0; +} + +static int gb_hid_connection_init(struct gb_connection *connection) +{ + struct hid_device *hid; + struct gb_hid *ghid; + int ret; + + ghid = kzalloc(sizeof(*ghid), GFP_KERNEL); + if (!ghid) + return -ENOMEM; + + hid = hid_allocate_device(); + if (IS_ERR(hid)) { + ret = PTR_ERR(hid); + goto free_ghid; + } + + connection->private = ghid; + ghid->connection = connection; + ghid->hid = hid; + + ret = gb_hid_init(ghid); + if (ret) + goto destroy_hid; + + ret = hid_add_device(hid); + if (!ret) + return 0; + + hid_err(hid, "can't add hid device: %d\n", ret); + +destroy_hid: + hid_destroy_device(hid); +free_ghid: + kfree(ghid); + + return ret; +} + +static void gb_hid_connection_exit(struct gb_connection *connection) +{ + struct gb_hid *ghid = connection->private; + + hid_destroy_device(ghid->hid); + kfree(ghid); +} + +static struct gb_protocol hid_protocol = { + .name = "hid", + .id = GREYBUS_PROTOCOL_HID, + .major = 0, + .minor = 1, + .connection_init = gb_hid_connection_init, + .connection_exit = gb_hid_connection_exit, + .request_recv = gb_hid_irq_handler, +}; + +int gb_hid_protocol_init(void) +{ + return gb_protocol_register(&hid_protocol); +} + +void gb_hid_protocol_exit(void) +{ + gb_protocol_deregister(&hid_protocol); +} diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index 2d01000..a74afef 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -84,6 +84,9 @@ extern void gb_i2c_protocol_exit(void); extern int gb_spi_protocol_init(void); extern void gb_spi_protocol_exit(void); +extern int gb_hid_protocol_init(void); +extern void gb_hid_protocol_exit(void); + #define gb_protocol_driver(__protocol) \ static int __init protocol_init(void) \ { \ -- cgit v0.10.2 From 6a80ed4d2c26b5934f3bfb9beafe73a9c7946d34 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 17 Mar 2015 10:55:50 +0100 Subject: greybus: pwm: fix memory leak in error path Fix memory leak in connection_init error path. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/pwm.c b/drivers/staging/greybus/pwm.c index e2ab6f5..3f508bf 100644 --- a/drivers/staging/greybus/pwm.c +++ b/drivers/staging/greybus/pwm.c @@ -261,7 +261,7 @@ static int gb_pwm_connection_init(struct gb_connection *connection) ret = pwmchip_add(pwm); if (ret) { pr_err("Failed to register PWM\n"); - return ret; + goto out_err; } return 0; -- cgit v0.10.2 From deeb57f5bd990f747815216ab772e92413848f6e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 17 Mar 2015 10:55:51 +0100 Subject: greybus: vibrator: fix memory leak in error path Fix memory leak in connection_init error path. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/vibrator.c b/drivers/staging/greybus/vibrator.c index b6ec9f2..c92c69e 100644 --- a/drivers/staging/greybus/vibrator.c +++ b/drivers/staging/greybus/vibrator.c @@ -127,7 +127,7 @@ static int gb_vibrator_connection_init(struct gb_connection *connection) "vibrator%d", vib->minor); if (IS_ERR(dev)) { retval = -EINVAL; - goto error; + goto err_idr_remove; } vib->dev = dev; @@ -140,12 +140,14 @@ static int gb_vibrator_connection_init(struct gb_connection *connection) retval = sysfs_create_group(&dev->kobj, vibrator_groups[0]); if (retval) { device_unregister(dev); - goto error; + goto err_idr_remove; } #endif return 0; +err_idr_remove: + idr_remove(&minors, vib->minor); error: kfree(vib); return retval; -- cgit v0.10.2 From 44538397e79987080adc619c6fd4edda92093d46 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 17 Mar 2015 10:55:52 +0100 Subject: greybus: connection: fix oops after failed init Make sure not to call connection_exit for connections that have never been initialised (e.g. due to failure to init). This fixes oopses due to null-dereferences and use-after-free in connection_exit callbacks (e.g. trying to remove a gpio-chip that has never been added) when the bundle and interface are ultimately destroyed. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 3ec984c..46e259f 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -298,6 +298,10 @@ void gb_connection_exit(struct gb_connection *connection) dev_warn(&connection->dev, "exit without protocol.\n"); return; } + + if (connection->state != GB_CONNECTION_STATE_ENABLED) + return; + connection->state = GB_CONNECTION_STATE_DESTROYING; connection->protocol->connection_exit(connection); } -- cgit v0.10.2 From fcc4356de4601c83530928e05b041e4ac678fd6a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 17 Mar 2015 18:24:28 +0100 Subject: greybus: gpio: fix set-debounce request alignment Fix alignment of the usec-field in the set-debounce request, which should follow the which-field without any inserted padding. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 4af5050..458565a 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -116,7 +116,7 @@ struct gb_gpio_set_value_request { struct gb_gpio_set_debounce_request { __u8 which; - __le16 usec; + __le16 usec __packed; }; /* debounce response has no payload */ -- cgit v0.10.2 From b41caa99a25f62326be451592c493de29347d142 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 17 Mar 2015 18:24:29 +0100 Subject: greybus: pwm: fix config-request alignment Fix alignment of the duty and period-fields in the config request, which should follow the which-field without any inserted padding. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/pwm.c b/drivers/staging/greybus/pwm.c index 3f508bf..4e38b8a 100644 --- a/drivers/staging/greybus/pwm.c +++ b/drivers/staging/greybus/pwm.c @@ -56,8 +56,8 @@ struct gb_pwm_deactivate_request { struct gb_pwm_config_request { __u8 which; - __le32 duty; - __le32 period; + __le32 duty __packed; + __le32 period __packed; }; struct gb_pwm_polarity_request { -- cgit v0.10.2 From afcf8c715e7cb615dad484913b70c714594ce159 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 17 Mar 2015 18:24:30 +0100 Subject: greybus: uart: remove packed-attribute from line-coding struct Remove packed-attribute from line-coding struct, whose members are all naturally aligned. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 575ca56..51e4f7b 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -68,7 +68,7 @@ struct gb_serial_line_coding { #define GB_SERIAL_SPACE_PARITY 4 __u8 data; -} __attribute__ ((packed)); +}; struct gb_uart_set_line_coding_request { struct gb_serial_line_coding line_coding; -- cgit v0.10.2 From e8f824b6589cd5477adf7a069e7c67918a6bb949 Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Wed, 18 Mar 2015 15:42:51 +0100 Subject: greybus: Export greybus debugfs folder Add gb_debugfs_get method to access to gb_debug_root dentry, in order to use it from other greybus modules. Signed-off-by: Alexandre Bailon Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/debugfs.c b/drivers/staging/greybus/debugfs.c index 770b7c0..b8865d7 100644 --- a/drivers/staging/greybus/debugfs.c +++ b/drivers/staging/greybus/debugfs.c @@ -29,3 +29,9 @@ void gb_debugfs_cleanup(void) debugfs_remove_recursive(gb_debug_root); gb_debug_root = NULL; } + +struct dentry *gb_debugfs_get(void) +{ + return gb_debug_root; +} +EXPORT_SYMBOL_GPL(gb_debugfs_get); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 68382b3..967d64f 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -160,6 +160,7 @@ int gb_ap_init(void); void gb_ap_exit(void); int gb_debugfs_init(void); void gb_debugfs_cleanup(void); +struct dentry *gb_debugfs_get(void); extern struct bus_type greybus_bus_type; -- cgit v0.10.2 From 183f872eb1895359ad41b2f3570c37b212fc29c1 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 19 Mar 2015 17:02:45 +0530 Subject: greybus: operation: s/status/result to match field name Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 5e859c0..b01106f 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -42,11 +42,11 @@ static DEFINE_MUTEX(gb_message_mutex); * (0x80) of the operation type field is used to indicate whether * the message is a request (clear) or a response (set). * - * Response messages include an additional status byte, which + * Response messages include an additional result byte, which * communicates the result of the corresponding request. A zero - * status value means the operation completed successfully. Any + * result value means the operation completed successfully. Any * other value indicates an error; in this case, the payload of the - * response message (if any) is ignored. The status byte must be + * response message (if any) is ignored. The result byte must be * zero in the header for a request message. * * The wire format for all numeric fields in the header is little -- cgit v0.10.2 From 3b6cf2ee3b726747b61285c36a76cc810b102c35 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 19 Mar 2015 17:02:46 +0530 Subject: greybus: operation: Fix comment mistake Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index b01106f..d4b59fe 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -965,7 +965,7 @@ int gb_operation_init(void) U16_MAX - sizeof(struct gb_operation_msg_hdr)); /* - * A message structure with consists of: + * A message structure consists of: * - the message structure itself * - the headroom set aside for the host device * - the message header -- cgit v0.10.2 From 9ee2b61df14f0afe8d7df86d8eaa24e6d59a923b Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 19 Mar 2015 17:02:48 +0530 Subject: greybus: interface: remove double underscore from fn name Also bring * closer to gb_interface_get_drvdata :) Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index f5b0cef..f444e31 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -37,7 +37,7 @@ static inline void gb_interface_set_drvdata(struct gb_interface *intf, dev_set_drvdata(&intf->dev, data); } -static inline void * gb_interface__get_drvdata(struct gb_interface *intf) +static inline void *gb_interface_get_drvdata(struct gb_interface *intf) { return dev_get_drvdata(&intf->dev); } -- cgit v0.10.2 From d71aaf288f7e79e7c7ed9893a1b4e28221d1b8d0 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 19 Mar 2015 17:02:49 +0530 Subject: greybus: core: place module_{init|exit}() right below the routines To follow coding guidelines a bit :) Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index ee8bba5..15408ec 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -244,6 +244,7 @@ error_bus: return retval; } +module_init(gb_init); static void __exit gb_exit(void) { @@ -252,8 +253,6 @@ static void __exit gb_exit(void) bus_unregister(&greybus_bus_type); gb_debugfs_cleanup(); } - -module_init(gb_init); module_exit(gb_exit); MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 292cca99fb9c04888880de4ea9a1984ffcc4e7bd Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 18 Mar 2015 11:41:39 +0530 Subject: greybus: hid: don't support OUTPUT report over interrupt channel There is no interrupt channel as such and so no need to support ->output_report(). Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index 17ca476..fe05a08 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -28,9 +28,8 @@ #define GB_HID_TYPE_PWR_ON 0x04 #define GB_HID_TYPE_PWR_OFF 0x05 #define GB_HID_TYPE_GET_REPORT 0x06 -#define GB_HID_TYPE_SET_REPORT 0x07 /* Feature or Output, via control pipe */ -#define GB_HID_TYPE_OUTPUT_REPORT 0x08 /* Output report via interrupt pipe */ -#define GB_HID_TYPE_IRQ_EVENT 0x09 +#define GB_HID_TYPE_SET_REPORT 0x07 +#define GB_HID_TYPE_IRQ_EVENT 0x08 #define GB_HID_TYPE_RESPONSE 0x80 /* OR'd with rest */ /* Report type */ @@ -122,21 +121,15 @@ static int gb_hid_get_report(struct gb_hid *ghid, u8 report_type, u8 report_id, &request, sizeof(request), buf, len); } -/* - * @raw: true: use SET_REPORT HID command, false: send plain OUTPUT report. - * - * Use SET_REPORT for feature reports or if the device does not support the - * output plain report. - */ static int gb_hid_set_report(struct gb_hid *ghid, u8 report_type, u8 report_id, - unsigned char *buf, int len, int raw) + unsigned char *buf, int len) { struct gb_hid_set_report_request *request; struct gb_operation *operation; int ret, size = sizeof(*request) + len - 1; - int type = raw ? GB_HID_TYPE_SET_REPORT : GB_HID_TYPE_OUTPUT_REPORT; - operation = gb_operation_create(ghid->connection, type, size, 0); + operation = gb_operation_create(ghid->connection, + GB_HID_TYPE_SET_REPORT, size, 0); if (!operation) return -ENOMEM; @@ -271,8 +264,7 @@ static int __gb_hid_get_raw_report(struct hid_device *hid, } static int __gb_hid_output_raw_report(struct hid_device *hid, __u8 *buf, - size_t len, unsigned char report_type, - bool raw) + size_t len, unsigned char report_type) { struct gb_hid *ghid = hid->driver_data; int report_id = buf[0]; @@ -286,7 +278,7 @@ static int __gb_hid_output_raw_report(struct hid_device *hid, __u8 *buf, len--; } - ret = gb_hid_set_report(ghid, report_type, report_id, buf, len, raw); + ret = gb_hid_set_report(ghid, report_type, report_id, buf, len); if (report_id && ret >= 0) ret++; /* add report_id to the number of transfered bytes */ @@ -303,21 +295,13 @@ static int gb_hid_raw_request(struct hid_device *hid, unsigned char reportnum, case HID_REQ_SET_REPORT: if (buf[0] != reportnum) return -EINVAL; - return __gb_hid_output_raw_report(hid, buf, len, rtype, true); + return __gb_hid_output_raw_report(hid, buf, len, rtype); default: return -EIO; } } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0) -static int gb_hid_output_report(struct hid_device *hid, __u8 *buf, size_t len) -{ - return __gb_hid_output_raw_report(hid, buf, len, HID_OUTPUT_REPORT, - false); -} - -#else - +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0) static int gb_hid_get_raw_report(struct hid_device *hid, unsigned char reportnum, __u8 *buf, size_t len, unsigned char rtype) @@ -459,7 +443,6 @@ static struct hid_ll_driver gb_hid_ll_driver = { .close = gb_hid_close, .power = gb_hid_power, #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0) - .output_report = gb_hid_output_report, .raw_request = gb_hid_raw_request, #endif }; -- cgit v0.10.2 From c020d568f5630d38b72b61a97a4d04f1428b9771 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 19 Mar 2015 16:46:13 +0100 Subject: greybus: usb: silence compiler warning This driver is being rewritten, but let's silence a pointer-to-int-cast compiler warning meanwhile. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/usb.c b/drivers/staging/greybus/usb.c index ff4556f..ea97841 100644 --- a/drivers/staging/greybus/usb.c +++ b/drivers/staging/greybus/usb.c @@ -140,7 +140,7 @@ static int urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) request->transfer_flags = cpu_to_le32(urb->transfer_flags); request->transfer_buffer_length = cpu_to_le32(urb->transfer_buffer_length); request->interval = cpu_to_le32(urb->interval); - request->hcpriv_ep = cpu_to_le64(urb->ep->hcpriv); + request->hcpriv_ep = cpu_to_le64((unsigned long)urb->ep->hcpriv); request->number_of_packets = cpu_to_le32(urb->number_of_packets); memcpy(request->setup_packet, urb->setup_packet, 8); @@ -160,7 +160,7 @@ static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) int ret; urb->ep->hcpriv = NULL; - request.hcpriv_ep = cpu_to_le64(urb->hcpriv); + request.hcpriv_ep = cpu_to_le64((unsigned long)urb->hcpriv); ret = gb_operation_sync(dev->connection, GB_USB_TYPE_URB_DEQUEUE, &request, sizeof(request), NULL, 0); urb->hcpriv = NULL; @@ -173,7 +173,7 @@ static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep) struct gb_usb_endpoint_disable_request request; int ret; - request.hcpriv = cpu_to_le64(ep->hcpriv); + request.hcpriv = cpu_to_le64((unsigned long)ep->hcpriv); ret = gb_operation_sync(dev->connection, GB_USB_TYPE_ENDPOINT_DISABLE, &request, sizeof(request), NULL, 0); ep->hcpriv = NULL; -- cgit v0.10.2 From 0b7534b86d672752babd18e061b0d869781e3615 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 19 Mar 2015 16:46:14 +0100 Subject: greybus: ap: fix svc handshake protocol check Fix incorrect SVC handshake protocol check, which would only bail out if both major and minor protocol versions supported by the SVC differed. Since we currently only support one version of the protocol, upgrade the debug message to warning and bail unless the protocol versions match perfectly for now. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 3e4d4fb..d5edef9 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -91,9 +91,10 @@ static void svc_handshake(struct svc_function_handshake *handshake, } /* A new SVC communication channel, let's verify a supported version */ - if ((handshake->version_major != GREYBUS_VERSION_MAJOR) && + if ((handshake->version_major != GREYBUS_VERSION_MAJOR) || (handshake->version_minor != GREYBUS_VERSION_MINOR)) { - dev_dbg(hd->parent, "received invalid greybus version %d:%d\n", + dev_warn(hd->parent, + "received invalid greybus version %u.%u\n", handshake->version_major, handshake->version_minor); return; } -- cgit v0.10.2 From 69bae8910e558356a09f080a02b64d72a0990409 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 19 Mar 2015 16:46:15 +0100 Subject: greybus: ap: fix typo in comment Fix typo in svc_hotplug comment. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index d5edef9..10f3b4d 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -169,7 +169,7 @@ static void svc_hotplug(struct svc_function_hotplug *hotplug, case SVC_HOTPLUG_EVENT: /* Add a new module to the system */ if (payload_length < 0x03) { - /* Hotplug message is at lest 3 bytes big */ + /* Hotplug message is at least 3 bytes big */ dev_err(hd->parent, "Illegal size of svc hotplug message %d\n", payload_length); -- cgit v0.10.2 From fe4c0e548aea5f4bc2df967db69d7d0b509327ef Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 19 Mar 2015 16:46:16 +0100 Subject: greybus: ap: clean up svc link management error path Return immediately on bundle-init failure when processing SVC link up. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 10f3b4d..ea197ac 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -149,11 +149,13 @@ static void svc_management(struct svc_function_unipro_management *management, ret = gb_bundle_init(intf, management->link_up.interface_id, management->link_up.device_id); - if (ret) + if (ret) { dev_err(hd->parent, "error %d initializing interface %hhu bundle %hhu\n", ret, management->link_up.module_id, management->link_up.interface_id); + return; + } break; default: dev_err(hd->parent, "Unhandled UniPro management message\n"); -- cgit v0.10.2 From 25eb732954ee656edd92770f498d28f87086511b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 19 Mar 2015 16:46:17 +0100 Subject: greybus: connection: replace custom error function with dev_err Remove custom connection error function and replace it with dev_err. The standard error function provides more information in the message prefix (e.g. includes the interface id), has a well-known semantics (e.g. does does not add newlines to messages), and is even somewhat shorter to type. Note that some uses of the custom function were already adding double newlines due to the non-standard semantics. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 46e259f..102e1a4 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -255,25 +255,6 @@ void gb_connection_destroy(struct gb_connection *connection) device_del(&connection->dev); } -void gb_connection_err(struct gb_connection *connection, const char *fmt, ...) -{ - struct va_format vaf; - va_list args; - - va_start(args, fmt); - - vaf.fmt = fmt; - vaf.va = &args; - - pr_err("greybus: [%hhu:%hhu:%hu]: %pV\n", - connection->bundle->intf->module->module_id, - connection->bundle->id, - connection->bundle_cport_id, &vaf); - - va_end(args); -} -EXPORT_SYMBOL_GPL(gb_connection_err); - int gb_connection_init(struct gb_connection *connection) { int ret; diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index b07df79..7febf4e 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -58,8 +58,6 @@ struct gb_connection *gb_hd_connection_find(struct greybus_host_device *hd, void greybus_data_rcvd(struct greybus_host_device *hd, u16 cport_id, u8 *data, size_t length); -__printf(2, 3) -void gb_connection_err(struct gb_connection *connection, const char *fmt, ...); void gb_connection_bind_protocol(struct gb_connection *connection); diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c index 0bcd7a9..84d20e5 100644 --- a/drivers/staging/greybus/i2c.c +++ b/drivers/staging/greybus/i2c.c @@ -178,8 +178,8 @@ gb_i2c_operation_create(struct gb_connection *connection, u32 i; if (msg_count > (u32)U16_MAX) { - gb_connection_err(connection, "msg_count (%u) too big", - msg_count); + dev_err(&connection->dev, "msg_count (%u) too big\n", + msg_count); return NULL; } op_count = (u16)msg_count; diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index d4b59fe..83359dd 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -220,7 +220,7 @@ static void gb_operation_request_handle(struct gb_operation *operation) return; } - gb_connection_err(operation->connection, + dev_err(&operation->connection->dev, "unexpected incoming request type 0x%02hhx\n", operation->type); if (gb_operation_result_set(operation, -EPROTONOSUPPORT)) queue_work(gb_operation_workqueue, &operation->work); @@ -793,7 +793,7 @@ static void gb_connection_recv_request(struct gb_connection *connection, operation = gb_operation_create_incoming(connection, operation_id, type, data, size); if (!operation) { - gb_connection_err(connection, "can't create operation"); + dev_err(&connection->dev, "can't create operation\n"); return; /* XXX Respond with pre-allocated ENOMEM */ } @@ -830,14 +830,14 @@ static void gb_connection_recv_response(struct gb_connection *connection, operation = gb_operation_find(connection, operation_id); if (!operation) { - gb_connection_err(connection, "operation not found"); + dev_err(&connection->dev, "operation not found\n"); return; } message = operation->response; message_size = sizeof(*message->header) + message->payload_size; if (!errno && size != message_size) { - gb_connection_err(connection, "bad message size (%zu != %zu)", + dev_err(&connection->dev, "bad message size (%zu != %zu)\n", size, message_size); errno = -EMSGSIZE; } @@ -865,20 +865,20 @@ void gb_connection_recv(struct gb_connection *connection, u16 operation_id; if (connection->state != GB_CONNECTION_STATE_ENABLED) { - gb_connection_err(connection, "dropping %zu received bytes", + dev_err(&connection->dev, "dropping %zu received bytes\n", size); return; } if (size < sizeof(*header)) { - gb_connection_err(connection, "message too small"); + dev_err(&connection->dev, "message too small\n"); return; } header = data; msg_size = (size_t)le16_to_cpu(header->size); if (msg_size > size) { - gb_connection_err(connection, "incomplete message"); + dev_err(&connection->dev, "incomplete message\n"); return; /* XXX Should still complete operation */ } diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index ad0c179..639c9cd 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -143,9 +143,8 @@ gb_spi_operation_create(struct gb_connection *connection, /* Find number of transfers queued and tx/rx length in the message */ list_for_each_entry(xfer, &msg->transfers, transfer_list) { if (!xfer->tx_buf && !xfer->rx_buf) { - gb_connection_err(connection, - "Bufferless transfer, length %u\n", - xfer->len); + dev_err(&connection->dev, + "bufferless transfer, length %u\n", xfer->len); return NULL; } @@ -160,8 +159,8 @@ gb_spi_operation_create(struct gb_connection *connection, /* Too many transfers ? */ if (count > (u32)U16_MAX) { - gb_connection_err(connection, "transfer count (%u) too big", - count); + dev_err(&connection->dev, "transfer count (%u) too big\n", + count); return NULL; } @@ -382,7 +381,7 @@ static int gb_spi_connection_init(struct gb_connection *connection) /* Allocate master with space for data */ master = spi_alloc_master(&connection->dev, sizeof(*spi)); if (!master) { - gb_connection_err(connection, "cannot alloc SPI master\n"); + dev_err(&connection->dev, "cannot alloc SPI master\n"); return -ENOMEM; } -- cgit v0.10.2 From ee8f81b0961fa240ddf4d7740ac501606e4ed230 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 19 Mar 2015 16:46:18 +0100 Subject: greybus: operation: use dev_err in gb_operation_sync Use the more informative dev_err in gb_operation_sync, which includes the connection device name in the error message (which in turn encodes the module, interface, bundle and cport ids). Add missing braces to conditional-construct branches while at it. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 83359dd..c85fd40 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -945,12 +945,15 @@ int gb_operation_sync(struct gb_connection *connection, int type, memcpy(operation->request->payload, request, request_size); ret = gb_operation_request_send_sync(operation); - if (ret) - pr_err("synchronous operation failed (%d)\n", ret); - else - if (response_size) + if (ret) { + dev_err(&connection->dev, "synchronous operation failed: %d\n", + ret); + } else { + if (response_size) { memcpy(response, operation->response->payload, response_size); + } + } gb_operation_destroy(operation); return ret; -- cgit v0.10.2 From c0d209a07beb3550203bfa237d27433a1fbc9cee Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 19 Mar 2015 16:46:19 +0100 Subject: greybus: operation: remove unnecessary cast Remove unnecessary cast of the message size in gb_connection_recv. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index c85fd40..d5fa2f0 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -876,7 +876,7 @@ void gb_connection_recv(struct gb_connection *connection, } header = data; - msg_size = (size_t)le16_to_cpu(header->size); + msg_size = le16_to_cpu(header->size); if (msg_size > size) { dev_err(&connection->dev, "incomplete message\n"); return; /* XXX Should still complete operation */ -- cgit v0.10.2 From c2a66106867343b5c5f017ccc724ba1c1aa9b540 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 19 Mar 2015 16:51:09 +0100 Subject: greybus: gpio: fix truncated debounce times Fix set_debounce, which silently truncated the time argument to 255us even though we support 16-bit values. Also remove the unnecessary explicit cast when verifying the argument. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 458565a..f75dd40 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -543,9 +543,9 @@ static int gb_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, if (offset >= chip->ngpio) return -EINVAL; - if (debounce > (unsigned int)U16_MAX) + if (debounce > U16_MAX) return -EINVAL; - usec = (u8)debounce; + usec = (u16)debounce; ret = gb_gpio_set_debounce_operation(gb_gpio_controller, (u8)offset, usec); if (ret) ; /* return ret; */ -- cgit v0.10.2 From 56c2da1873d68b96458064a306e5bb4c50ccdb5d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 19 Mar 2015 16:51:10 +0100 Subject: greybus: gpio: remove incorrect todo comments The module reference count is incremented by gpiolib when a gpio is requested, and the driver callbacks certainly do sleep. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index f75dd40..6a493d4 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -747,7 +747,7 @@ static int gb_gpio_connection_init(struct gb_connection *connection) gpio->label = "greybus_gpio"; gpio->dev = &connection->dev; - gpio->owner = THIS_MODULE; /* XXX Module get? */ + gpio->owner = THIS_MODULE; gpio->request = gb_gpio_request; gpio->free = gb_gpio_free; @@ -761,7 +761,7 @@ static int gb_gpio_connection_init(struct gb_connection *connection) gpio->to_irq = gb_gpio_to_irq; gpio->base = -1; /* Allocate base dynamically */ gpio->ngpio = gb_gpio_controller->line_max + 1; - gpio->can_sleep = true; /* XXX */ + gpio->can_sleep = true; ret = gpiochip_add(gpio); if (ret) { -- cgit v0.10.2 From 65f5a5f1614d1a3dab375588f5fd03590c87215b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 19 Mar 2015 16:51:11 +0100 Subject: greybus: gpio: remove redundant argument verification Remove redundant verification of gpio numbers (which have already been verified in the gpio-chip callbacks) from greybus-operation helpers. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 6a493d4..a1bf143 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -167,9 +167,6 @@ static int gb_gpio_activate_operation(struct gb_gpio_controller *ggc, u8 which) struct gb_gpio_activate_request request; int ret; - if (which > ggc->line_max) - return -EINVAL; - request.which = which; ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_ACTIVATE, &request, sizeof(request), NULL, 0); @@ -184,9 +181,6 @@ static int gb_gpio_deactivate_operation(struct gb_gpio_controller *ggc, struct gb_gpio_deactivate_request request; int ret; - if (which > ggc->line_max) - return -EINVAL; - request.which = which; ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DEACTIVATE, &request, sizeof(request), NULL, 0); @@ -203,9 +197,6 @@ static int gb_gpio_get_direction_operation(struct gb_gpio_controller *ggc, int ret; u8 direction; - if (which > ggc->line_max) - return -EINVAL; - request.which = which; ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_GET_DIRECTION, &request, sizeof(request), @@ -227,9 +218,6 @@ static int gb_gpio_direction_in_operation(struct gb_gpio_controller *ggc, struct gb_gpio_direction_in_request request; int ret; - if (which > ggc->line_max) - return -EINVAL; - request.which = which; ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DIRECTION_IN, &request, sizeof(request), NULL, 0); @@ -244,9 +232,6 @@ static int gb_gpio_direction_out_operation(struct gb_gpio_controller *ggc, struct gb_gpio_direction_out_request request; int ret; - if (which > ggc->line_max) - return -EINVAL; - request.which = which; request.value = value_high ? 1 : 0; ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DIRECTION_OUT, @@ -264,9 +249,6 @@ static int gb_gpio_get_value_operation(struct gb_gpio_controller *ggc, int ret; u8 value; - if (which > ggc->line_max) - return -EINVAL; - request.which = which; ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_GET_VALUE, &request, sizeof(request), @@ -288,9 +270,6 @@ static int gb_gpio_set_value_operation(struct gb_gpio_controller *ggc, struct gb_gpio_set_value_request request; int ret; - if (which > ggc->line_max) - return -EINVAL; - request.which = which; request.value = value_high ? 1 : 0; ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_SET_VALUE, @@ -308,9 +287,6 @@ static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *ggc, struct gb_gpio_set_debounce_request request; int ret; - if (which > ggc->line_max) - return -EINVAL; - request.which = which; request.usec = cpu_to_le16(debounce_usec); ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_SET_DEBOUNCE, -- cgit v0.10.2 From 83d9cddb85a0cc7497012846567d16add52916d4 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 19 Mar 2015 16:51:12 +0100 Subject: greybus: gpio: remove overly defensive argument verification Remove overly defensive argument verification in gpio-chip callbacks. We should trust gpiolib to get this right (or we would not even get any callback) just like the other gpio drivers do. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index a1bf143..8384ad17 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -415,8 +415,6 @@ static int gb_gpio_request(struct gpio_chip *chip, unsigned offset) struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); int ret; - if (offset >= chip->ngpio) - return -EINVAL; ret = gb_gpio_activate_operation(gb_gpio_controller, (u8)offset); if (ret) ; /* return ret; */ @@ -428,11 +426,6 @@ static void gb_gpio_free(struct gpio_chip *chip, unsigned offset) struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); int ret; - if (offset >= chip->ngpio) { - pr_err("bad offset %u supplied (must be 0..%u)\n", - offset, chip->ngpio - 1); - return; - } ret = gb_gpio_deactivate_operation(gb_gpio_controller, (u8)offset); if (ret) ; /* return ret; */ @@ -444,8 +437,6 @@ static int gb_gpio_get_direction(struct gpio_chip *chip, unsigned offset) u8 which; int ret; - if (offset >= chip->ngpio) - return -EINVAL; which = (u8)offset; ret = gb_gpio_get_direction_operation(gb_gpio_controller, which); if (ret) @@ -458,8 +449,6 @@ static int gb_gpio_direction_input(struct gpio_chip *chip, unsigned offset) struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); int ret; - if (offset >= chip->ngpio) - return -EINVAL; ret = gb_gpio_direction_in_operation(gb_gpio_controller, (u8)offset); if (ret) ; /* return ret; */ @@ -472,8 +461,6 @@ static int gb_gpio_direction_output(struct gpio_chip *chip, unsigned offset, struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); int ret; - if (offset >= chip->ngpio) - return -EINVAL; ret = gb_gpio_direction_out_operation(gb_gpio_controller, (u8)offset, !!value); if (ret) ; /* return ret; */ @@ -486,8 +473,6 @@ static int gb_gpio_get(struct gpio_chip *chip, unsigned offset) u8 which; int ret; - if (offset >= chip->ngpio) - return -EINVAL; which = (u8)offset; ret = gb_gpio_get_value_operation(gb_gpio_controller, which); if (ret) @@ -500,11 +485,6 @@ static void gb_gpio_set(struct gpio_chip *chip, unsigned offset, int value) struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); int ret; - if (offset < 0 || offset >= chip->ngpio) { - pr_err("bad offset %u supplied (must be 0..%u)\n", - offset, chip->ngpio - 1); - return; - } ret = gb_gpio_set_value_operation(gb_gpio_controller, (u8)offset, !!value); if (ret) ; /* return ret; */ @@ -517,8 +497,6 @@ static int gb_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, u16 usec; int ret; - if (offset >= chip->ngpio) - return -EINVAL; if (debounce > U16_MAX) return -EINVAL; usec = (u16)debounce; -- cgit v0.10.2 From bda7e2d1126f20c57f175c37c26c42b41ee4b64f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 19 Mar 2015 16:51:13 +0100 Subject: greybus: gpio: remove unnecessary explicit cast Remove unnecessary explicit cast of line value. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 8384ad17..e0a871d 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -477,7 +477,7 @@ static int gb_gpio_get(struct gpio_chip *chip, unsigned offset) ret = gb_gpio_get_value_operation(gb_gpio_controller, which); if (ret) return ret; - return (int)gb_gpio_controller->lines[which].value; + return gb_gpio_controller->lines[which].value; } static void gb_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -- cgit v0.10.2 From 8aff1aceb28dd692a35f628479357896551ab4e9 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 19 Mar 2015 16:51:14 +0100 Subject: greybus: gpio: make gb_gpio_controller pointer naming consistent Rename all struct gb_gpio_controller-pointer variables "ggc" for consistency and readability reason. This also fixes a bunch of lines that exceeded the 80 columns limit. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index e0a871d..d194274 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -412,10 +412,10 @@ static void gb_gpio_request_recv(u8 type, struct gb_operation *op) static int gb_gpio_request(struct gpio_chip *chip, unsigned offset) { - struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); int ret; - ret = gb_gpio_activate_operation(gb_gpio_controller, (u8)offset); + ret = gb_gpio_activate_operation(ggc, (u8)offset); if (ret) ; /* return ret; */ return 0; @@ -423,33 +423,33 @@ static int gb_gpio_request(struct gpio_chip *chip, unsigned offset) static void gb_gpio_free(struct gpio_chip *chip, unsigned offset) { - struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); int ret; - ret = gb_gpio_deactivate_operation(gb_gpio_controller, (u8)offset); + ret = gb_gpio_deactivate_operation(ggc, (u8)offset); if (ret) ; /* return ret; */ } static int gb_gpio_get_direction(struct gpio_chip *chip, unsigned offset) { - struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); u8 which; int ret; which = (u8)offset; - ret = gb_gpio_get_direction_operation(gb_gpio_controller, which); + ret = gb_gpio_get_direction_operation(ggc, which); if (ret) ; /* return ret; */ - return gb_gpio_controller->lines[which].direction ? 1 : 0; + return ggc->lines[which].direction ? 1 : 0; } static int gb_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { - struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); int ret; - ret = gb_gpio_direction_in_operation(gb_gpio_controller, (u8)offset); + ret = gb_gpio_direction_in_operation(ggc, (u8)offset); if (ret) ; /* return ret; */ return 0; @@ -458,10 +458,10 @@ static int gb_gpio_direction_input(struct gpio_chip *chip, unsigned offset) static int gb_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value) { - struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); int ret; - ret = gb_gpio_direction_out_operation(gb_gpio_controller, (u8)offset, !!value); + ret = gb_gpio_direction_out_operation(ggc, (u8)offset, !!value); if (ret) ; /* return ret; */ return 0; @@ -469,23 +469,23 @@ static int gb_gpio_direction_output(struct gpio_chip *chip, unsigned offset, static int gb_gpio_get(struct gpio_chip *chip, unsigned offset) { - struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); u8 which; int ret; which = (u8)offset; - ret = gb_gpio_get_value_operation(gb_gpio_controller, which); + ret = gb_gpio_get_value_operation(ggc, which); if (ret) return ret; - return gb_gpio_controller->lines[which].value; + return ggc->lines[which].value; } static void gb_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); int ret; - ret = gb_gpio_set_value_operation(gb_gpio_controller, (u8)offset, !!value); + ret = gb_gpio_set_value_operation(ggc, (u8)offset, !!value); if (ret) ; /* return ret; */ } @@ -493,14 +493,14 @@ static void gb_gpio_set(struct gpio_chip *chip, unsigned offset, int value) static int gb_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, unsigned debounce) { - struct gb_gpio_controller *gb_gpio_controller = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); u16 usec; int ret; if (debounce > U16_MAX) return -EINVAL; usec = (u16)debounce; - ret = gb_gpio_set_debounce_operation(gb_gpio_controller, (u8)offset, usec); + ret = gb_gpio_set_debounce_operation(ggc, (u8)offset, usec); if (ret) ; /* return ret; */ @@ -512,25 +512,25 @@ static void gb_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) return; /* XXX */ } -static int gb_gpio_controller_setup(struct gb_gpio_controller *gb_gpio_controller) +static int gb_gpio_controller_setup(struct gb_gpio_controller *ggc) { u32 line_count; size_t size; int ret; /* First thing we need to do is check the version */ - ret = get_version(gb_gpio_controller); + ret = get_version(ggc); if (ret) ; /* return ret; */ /* Now find out how many lines there are */ - ret = gb_gpio_line_count_operation(gb_gpio_controller); + ret = gb_gpio_line_count_operation(ggc); if (ret) ; /* return ret; */ - line_count = (u32)gb_gpio_controller->line_max + 1; - size = line_count * sizeof(*gb_gpio_controller->lines); - gb_gpio_controller->lines = kzalloc(size, GFP_KERNEL); - if (!gb_gpio_controller->lines) + line_count = (u32)ggc->line_max + 1; + size = line_count * sizeof(*ggc->lines); + ggc->lines = kzalloc(size, GFP_KERNEL); + if (!ggc->lines) return -ENOMEM; return ret; @@ -675,29 +675,29 @@ static int gb_gpio_to_irq(struct gpio_chip *chip, unsigned offset) static int gb_gpio_connection_init(struct gb_connection *connection) { - struct gb_gpio_controller *gb_gpio_controller; + struct gb_gpio_controller *ggc; struct gpio_chip *gpio; struct irq_chip *irqc; int ret; - gb_gpio_controller = kzalloc(sizeof(*gb_gpio_controller), GFP_KERNEL); - if (!gb_gpio_controller) + ggc = kzalloc(sizeof(*ggc), GFP_KERNEL); + if (!ggc) return -ENOMEM; - gb_gpio_controller->connection = connection; - connection->private = gb_gpio_controller; + ggc->connection = connection; + connection->private = ggc; - ret = gb_gpio_controller_setup(gb_gpio_controller); + ret = gb_gpio_controller_setup(ggc); if (ret) goto err_free_controller; - irqc = &gb_gpio_controller->irqc; + irqc = &ggc->irqc; irqc->irq_ack = gb_gpio_ack_irq; irqc->irq_mask = gb_gpio_mask_irq; irqc->irq_unmask = gb_gpio_unmask_irq; irqc->irq_set_type = gb_gpio_irq_set_type; irqc->name = "greybus_gpio"; - gpio = &gb_gpio_controller->chip; + gpio = &ggc->chip; gpio->label = "greybus_gpio"; gpio->dev = &connection->dev; @@ -714,7 +714,7 @@ static int gb_gpio_connection_init(struct gb_connection *connection) gpio->dbg_show = gb_gpio_dbg_show; gpio->to_irq = gb_gpio_to_irq; gpio->base = -1; /* Allocate base dynamically */ - gpio->ngpio = gb_gpio_controller->line_max + 1; + gpio->ngpio = ggc->line_max + 1; gpio->can_sleep = true; ret = gpiochip_add(gpio); @@ -735,24 +735,24 @@ static int gb_gpio_connection_init(struct gb_connection *connection) irqchip_err: gb_gpiochip_remove(gpio); err_free_lines: - kfree(gb_gpio_controller->lines); + kfree(ggc->lines); err_free_controller: - kfree(gb_gpio_controller); + kfree(ggc); return ret; } static void gb_gpio_connection_exit(struct gb_connection *connection) { - struct gb_gpio_controller *gb_gpio_controller = connection->private; + struct gb_gpio_controller *ggc = connection->private; - if (!gb_gpio_controller) + if (!ggc) return; - gb_gpio_irqchip_remove(gb_gpio_controller); - gb_gpiochip_remove(&gb_gpio_controller->chip); - /* kref_put(gb_gpio_controller->connection) */ - kfree(gb_gpio_controller->lines); - kfree(gb_gpio_controller); + gb_gpio_irqchip_remove(ggc); + gb_gpiochip_remove(&ggc->chip); + /* kref_put(ggc->connection) */ + kfree(ggc->lines); + kfree(ggc); } static struct gb_protocol gpio_protocol = { -- cgit v0.10.2 From 86c6816158d79228162b6dc2e759e3769dd3ab09 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 19 Mar 2015 16:51:15 +0100 Subject: greybus: gpio: fix error handling Make sure to propagate any errors detected up the call chain. This specifically means that we will detect failed connection init, something which is now handled more gracefully by greybus core. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index d194274..acc8f39 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -175,7 +175,7 @@ static int gb_gpio_activate_operation(struct gb_gpio_controller *ggc, u8 which) return ret; } -static int gb_gpio_deactivate_operation(struct gb_gpio_controller *ggc, +static void gb_gpio_deactivate_operation(struct gb_gpio_controller *ggc, u8 which) { struct gb_gpio_deactivate_request request; @@ -186,7 +186,6 @@ static int gb_gpio_deactivate_operation(struct gb_gpio_controller *ggc, &request, sizeof(request), NULL, 0); if (!ret) ggc->lines[which].active = false; - return ret; } static int gb_gpio_get_direction_operation(struct gb_gpio_controller *ggc, @@ -264,7 +263,7 @@ static int gb_gpio_get_value_operation(struct gb_gpio_controller *ggc, return 0; } -static int gb_gpio_set_value_operation(struct gb_gpio_controller *ggc, +static void gb_gpio_set_value_operation(struct gb_gpio_controller *ggc, u8 which, bool value_high) { struct gb_gpio_set_value_request request; @@ -278,7 +277,6 @@ static int gb_gpio_set_value_operation(struct gb_gpio_controller *ggc, /* XXX should this set direction to out? */ ggc->lines[which].value = request.value; } - return ret; } static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *ggc, @@ -413,22 +411,15 @@ static void gb_gpio_request_recv(u8 type, struct gb_operation *op) static int gb_gpio_request(struct gpio_chip *chip, unsigned offset) { struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); - int ret; - ret = gb_gpio_activate_operation(ggc, (u8)offset); - if (ret) - ; /* return ret; */ - return 0; + return gb_gpio_activate_operation(ggc, (u8)offset); } static void gb_gpio_free(struct gpio_chip *chip, unsigned offset) { struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); - int ret; - ret = gb_gpio_deactivate_operation(ggc, (u8)offset); - if (ret) - ; /* return ret; */ + gb_gpio_deactivate_operation(ggc, (u8)offset); } static int gb_gpio_get_direction(struct gpio_chip *chip, unsigned offset) @@ -440,31 +431,24 @@ static int gb_gpio_get_direction(struct gpio_chip *chip, unsigned offset) which = (u8)offset; ret = gb_gpio_get_direction_operation(ggc, which); if (ret) - ; /* return ret; */ + return ret; + return ggc->lines[which].direction ? 1 : 0; } static int gb_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); - int ret; - ret = gb_gpio_direction_in_operation(ggc, (u8)offset); - if (ret) - ; /* return ret; */ - return 0; + return gb_gpio_direction_in_operation(ggc, (u8)offset); } static int gb_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value) { struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); - int ret; - ret = gb_gpio_direction_out_operation(ggc, (u8)offset, !!value); - if (ret) - ; /* return ret; */ - return 0; + return gb_gpio_direction_out_operation(ggc, (u8)offset, !!value); } static int gb_gpio_get(struct gpio_chip *chip, unsigned offset) @@ -477,17 +461,15 @@ static int gb_gpio_get(struct gpio_chip *chip, unsigned offset) ret = gb_gpio_get_value_operation(ggc, which); if (ret) return ret; + return ggc->lines[which].value; } static void gb_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); - int ret; - ret = gb_gpio_set_value_operation(ggc, (u8)offset, !!value); - if (ret) - ; /* return ret; */ + gb_gpio_set_value_operation(ggc, (u8)offset, !!value); } static int gb_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, @@ -495,16 +477,12 @@ static int gb_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, { struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); u16 usec; - int ret; if (debounce > U16_MAX) return -EINVAL; usec = (u16)debounce; - ret = gb_gpio_set_debounce_operation(ggc, (u8)offset, usec); - if (ret) - ; /* return ret; */ - return 0; /* XXX */ + return gb_gpio_set_debounce_operation(ggc, (u8)offset, usec); } static void gb_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) @@ -521,12 +499,13 @@ static int gb_gpio_controller_setup(struct gb_gpio_controller *ggc) /* First thing we need to do is check the version */ ret = get_version(ggc); if (ret) - ; /* return ret; */ + return ret; /* Now find out how many lines there are */ ret = gb_gpio_line_count_operation(ggc); if (ret) - ; /* return ret; */ + return ret; + line_count = (u32)ggc->line_max + 1; size = line_count * sizeof(*ggc->lines); ggc->lines = kzalloc(size, GFP_KERNEL); -- cgit v0.10.2 From e5032d8511cdb0b7b594863effa2c2a685beaaa5 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 19 Mar 2015 16:51:16 +0100 Subject: greybus: gpio: use dev_err and dev_warn Use the more informative dev_err and dev_warn for messages, and make the messages more uniform. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index acc8f39..a9153a8 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -204,9 +204,11 @@ static int gb_gpio_get_direction_operation(struct gb_gpio_controller *ggc, return ret; direction = response.direction; - if (direction && direction != 1) - pr_warn("gpio %u direction was %u (should be 0 or 1)\n", - which, direction); + if (direction && direction != 1) { + dev_warn(ggc->chip.dev, + "gpio %u direction was %u (should be 0 or 1)\n", + which, direction); + } ggc->lines[which].direction = direction ? 1 : 0; return 0; } @@ -256,9 +258,11 @@ static int gb_gpio_get_value_operation(struct gb_gpio_controller *ggc, return ret; value = response.value; - if (value && value != 1) - pr_warn("gpio %u value was %u (should be 0 or 1)\n", - which, value); + if (value && value != 1) { + dev_warn(ggc->chip.dev, + "gpio %u value was %u (should be 0 or 1)\n", + which, value); + } ggc->lines[which].value = value ? 1 : 0; return 0; } @@ -306,7 +310,7 @@ static void gb_gpio_ack_irq(struct irq_data *d) GB_GPIO_TYPE_IRQ_ACK, &request, sizeof(request), NULL, 0); if (ret) - pr_err("irq ack operation failed (%d)\n", ret); + dev_err(chip->dev, "failed to ack irq: %d\n", ret); } static void gb_gpio_mask_irq(struct irq_data *d) @@ -321,7 +325,7 @@ static void gb_gpio_mask_irq(struct irq_data *d) GB_GPIO_TYPE_IRQ_MASK, &request, sizeof(request), NULL, 0); if (ret) - pr_err("irq mask operation failed (%d)\n", ret); + dev_err(chip->dev, "failed to mask irq: %d\n", ret); } static void gb_gpio_unmask_irq(struct irq_data *d) @@ -336,7 +340,7 @@ static void gb_gpio_unmask_irq(struct irq_data *d) GB_GPIO_TYPE_IRQ_UNMASK, &request, sizeof(request), NULL, 0); if (ret) - pr_err("irq unmask operation failed (%d)\n", ret); + dev_err(chip->dev, "failed to unmask irq: %d\n", ret); } static int gb_gpio_irq_set_type(struct irq_data *d, unsigned int type) @@ -360,11 +364,13 @@ static int gb_gpio_irq_set_type(struct irq_data *d, unsigned int type) ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_IRQ_TYPE, &request, sizeof(request), NULL, 0); - if (ret) - pr_err("irq type operation failed (%d)\n", ret); + if (ret) { + dev_err(chip->dev, "failed to set irq type: %d\n", + ret); + } break; default: - pr_err("No such irq type %d", type); + dev_err(chip->dev, "unsupported irq type: %u\n", type); ret = -EINVAL; } @@ -374,7 +380,7 @@ static int gb_gpio_irq_set_type(struct irq_data *d, unsigned int type) static void gb_gpio_request_recv(u8 type, struct gb_operation *op) { struct gb_gpio_controller *ggc; - struct gb_connection *connection; + struct gb_connection *connection = op->connection; struct gb_message *request; struct gb_gpio_irq_event_request *event; int irq; @@ -382,17 +388,17 @@ static void gb_gpio_request_recv(u8 type, struct gb_operation *op) int ret; if (type != GB_GPIO_TYPE_IRQ_EVENT) { - pr_err("unsupported unsolicited request\n"); + dev_err(&connection->dev, + "unsupported unsolicited request: %u\n", type); return; } - connection = op->connection; ggc = connection->private; request = op->request; event = request->payload; if (event->which > ggc->line_max) { - pr_err("Unsupported hw irq %d\n", event->which); + dev_err(ggc->chip.dev, "invalid hw irq: %d\n", event->which); return; } irq = gpio_to_irq(ggc->chip.base + event->which); @@ -404,8 +410,10 @@ static void gb_gpio_request_recv(u8 type, struct gb_operation *op) local_irq_enable(); ret = gb_operation_response_send(op, 0); - if (ret) - pr_err("error %d sending response status %d\n", ret, 0); + if (ret) { + dev_err(ggc->chip.dev, + "failed to send response status %d: %d\n", 0, ret); + } } static int gb_gpio_request(struct gpio_chip *chip, unsigned offset) @@ -698,14 +706,15 @@ static int gb_gpio_connection_init(struct gb_connection *connection) ret = gpiochip_add(gpio); if (ret) { - pr_err("Failed to register GPIO\n"); + dev_err(&connection->dev, "failed to add gpio chip: %d\n", + ret); goto err_free_lines; } ret = gb_gpio_irqchip_add(gpio, irqc, 0, handle_simple_irq, IRQ_TYPE_NONE); if (ret) { - pr_err("Couldn't add irqchip to Greybus GPIO controller %d\n", ret); + dev_err(&connection->dev, "failed to add irq chip: %d\n", ret); goto irqchip_err; } -- cgit v0.10.2 From 64d2f4e5f94a95b23532efcbc3c955b5086bd890 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 19 Mar 2015 16:51:17 +0100 Subject: greybus: gpio: clean up line-state allocation Clean up allocation of line-state array. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index a9153a8..b18fb7e1 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -500,8 +500,6 @@ static void gb_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) static int gb_gpio_controller_setup(struct gb_gpio_controller *ggc) { - u32 line_count; - size_t size; int ret; /* First thing we need to do is check the version */ @@ -514,9 +512,8 @@ static int gb_gpio_controller_setup(struct gb_gpio_controller *ggc) if (ret) return ret; - line_count = (u32)ggc->line_max + 1; - size = line_count * sizeof(*ggc->lines); - ggc->lines = kzalloc(size, GFP_KERNEL); + ggc->lines = kcalloc(ggc->line_max + 1, sizeof(*ggc->lines), + GFP_KERNEL); if (!ggc->lines) return -ENOMEM; -- cgit v0.10.2 From 7bfa0781406f9df6cb20ce5134faa19d34cb4e18 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 19 Mar 2015 16:55:22 +0100 Subject: greybus: gpio: refuse to set value of input pins Add warning and refuse to set output value for pin configured as input, as the result of such an operation is undefined. Remove incorrect todo-comment suggesting that the driver could implicitly switch direction as part of the call. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index b18fb7e1..7e51840 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -273,14 +273,18 @@ static void gb_gpio_set_value_operation(struct gb_gpio_controller *ggc, struct gb_gpio_set_value_request request; int ret; + if (ggc->lines[which].direction == 1) { + dev_warn(ggc->chip.dev, + "refusing to set value of input gpio %u\n", which); + return; + } + request.which = which; request.value = value_high ? 1 : 0; ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_SET_VALUE, &request, sizeof(request), NULL, 0); - if (!ret) { - /* XXX should this set direction to out? */ + if (!ret) ggc->lines[which].value = request.value; - } } static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *ggc, -- cgit v0.10.2 From 792c17e64383340a75579cdfc6b9b6d2b1647b43 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 19 Mar 2015 16:55:23 +0100 Subject: greybus: gpio: add error messages to callbacks not propagating errors Add error messages on failures to deactivate, set and get operation handlers as any errors would not be detected by the upper layers (either because the callbacks are declared void or expected to return a boolean value). Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 7e51840..2bac28e 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -184,8 +184,13 @@ static void gb_gpio_deactivate_operation(struct gb_gpio_controller *ggc, request.which = which; ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DEACTIVATE, &request, sizeof(request), NULL, 0); - if (!ret) - ggc->lines[which].active = false; + if (ret) { + dev_err(ggc->chip.dev, "failed to deactivate gpio %u\n", + which); + return; + } + + ggc->lines[which].active = false; } static int gb_gpio_get_direction_operation(struct gb_gpio_controller *ggc, @@ -254,8 +259,11 @@ static int gb_gpio_get_value_operation(struct gb_gpio_controller *ggc, ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_GET_VALUE, &request, sizeof(request), &response, sizeof(response)); - if (ret) + if (ret) { + dev_err(ggc->chip.dev, "failed to get value of gpio %u\n", + which); return ret; + } value = response.value; if (value && value != 1) { @@ -283,8 +291,13 @@ static void gb_gpio_set_value_operation(struct gb_gpio_controller *ggc, request.value = value_high ? 1 : 0; ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_SET_VALUE, &request, sizeof(request), NULL, 0); - if (!ret) - ggc->lines[which].value = request.value; + if (ret) { + dev_err(ggc->chip.dev, "failed to set value of gpio %u\n", + which); + return; + } + + ggc->lines[which].value = request.value; } static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *ggc, -- cgit v0.10.2 From 337b068722a21cbbd4c5e925f0ac90209b44a8a8 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 20 Mar 2015 20:29:13 +0530 Subject: greybus: core: Don't initialize greybus if it is disabled Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 15408ec..a25df36 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -207,6 +207,9 @@ static int __init gb_init(void) { int retval; + if (greybus_disabled()) + return -ENODEV; + BUILD_BUG_ON(HOST_DEV_CPORT_ID_MAX >= (long)CPORT_ID_BAD); retval = gb_debugfs_init(); -- cgit v0.10.2 From 59e3344461baeab1a605543aec0ff9ddf209b20f Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Mon, 23 Mar 2015 17:52:37 +0100 Subject: greybus: Dump log from APB1 On AP module (form factor), we don't have access to APBridge JTAG or UART. But sometime, we still need to get log from APBridge. Add a new request in control endpoint to get APBridge logs. Logs can be accessed using debugfs (greybus/apb1_log). Signed-off-by: Alexandre Bailon Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index bbf1bd1..9ad8a76 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -8,10 +8,14 @@ */ #include #include +#include #include #include #include #include +#include +#include +#include #include "greybus.h" #include "svc_msg.h" @@ -35,6 +39,12 @@ static const struct usb_device_id id_table[] = { }; MODULE_DEVICE_TABLE(usb, id_table); +#define APB1_LOG_SIZE SZ_16K +static struct dentry *apb1_log_dentry; +static struct dentry *apb1_log_enable_dentry; +static struct task_struct *apb1_log_task; +static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); + /* * Number of CPort IN urbs in flight at any point in time. * Adjust if we are having stalls in the USB buffer due to not enough urbs in @@ -91,6 +101,7 @@ static inline struct es1_ap_dev *hd_to_es1(struct greybus_host_device *hd) } static void cport_out_callback(struct urb *urb); +static void usb_log_enable(struct es1_ap_dev *es1, int enable); /* * Buffer constraints for the host driver. @@ -326,6 +337,8 @@ static void ap_disconnect(struct usb_interface *interface) if (!es1) return; + usb_log_enable(es1, 0); + /* Tear down everything! */ for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { struct urb *urb = es1->cport_out_urb[i]; @@ -474,6 +487,125 @@ static void cport_out_callback(struct urb *urb) */ } +static void apb1_log_get(struct es1_ap_dev *es1) +{ + char buf[65]; + int retval; + + /* SVC messages go down our control pipe */ + do { + memset(buf, 0, 65); + retval = usb_control_msg(es1->usb_dev, + usb_rcvctrlpipe(es1->usb_dev, + es1->control_endpoint), + 0x02, /* vendor request APB1 log */ + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + 0x00, 0x00, + buf, + 64, + ES1_TIMEOUT); + if (retval > 0) + kfifo_in(&apb1_log_fifo, buf, retval); + } while (retval > 0); +} + +static int apb1_log_poll(void *data) +{ + while (!kthread_should_stop()) { + msleep(1000); + apb1_log_get((struct es1_ap_dev *)data); + } + return 0; +} + +static ssize_t apb1_log_read(struct file *f, char __user *buf, + size_t count, loff_t *ppos) +{ + ssize_t ret; + size_t copied; + char *tmp_buf; + + if (count > APB1_LOG_SIZE) + count = APB1_LOG_SIZE; + + tmp_buf = kmalloc(count, GFP_KERNEL); + if (!tmp_buf) + return -ENOMEM; + + copied = kfifo_out(&apb1_log_fifo, tmp_buf, count); + ret = simple_read_from_buffer(buf, count, ppos, tmp_buf, copied); + + kfree(tmp_buf); + + return ret; +} + +static struct file_operations apb1_log_fops = { + .read = apb1_log_read, +}; + +static void usb_log_enable(struct es1_ap_dev *es1, int enable) +{ + if (enable && apb1_log_task != NULL) + return; + + if (enable) { + /* get log from APB1 */ + apb1_log_task = kthread_run(apb1_log_poll, es1, "apb1_log"); + if (apb1_log_task == ERR_PTR(-ENOMEM)) + return; + apb1_log_dentry = debugfs_create_file("apb1_log", 444, + gb_debugfs_get(), NULL, + &apb1_log_fops); + } else { + if (apb1_log_dentry) { + debugfs_remove(apb1_log_dentry); + apb1_log_dentry = NULL; + } + + if (apb1_log_task) { + kthread_stop(apb1_log_task); + apb1_log_task = NULL; + } + } +} + +static ssize_t apb1_log_enable_read(struct file *f, char __user *buf, + size_t count, loff_t *ppos) +{ + char tmp_buf[3]; + int enable = apb1_log_task != NULL; + sprintf(tmp_buf, "%d\n", enable); + return simple_read_from_buffer(buf, count, ppos, tmp_buf, 3); +} + +static ssize_t apb1_log_enable_write(struct file *f, char __user *buf, + size_t count, loff_t *ppos) +{ + int enable; + char *tmp_buf; + ssize_t retval = -EINVAL; + struct es1_ap_dev *es1 = (struct es1_ap_dev *)f->f_inode->i_private; + + tmp_buf = kmalloc(count, GFP_KERNEL); + if (!tmp_buf) + return -ENOMEM; + + copy_from_user(tmp_buf, buf, count); + if (sscanf(tmp_buf, "%d", &enable) == 1) { + usb_log_enable(es1, enable); + retval = count; + } + kfree(tmp_buf); + + return retval; +} + +static struct file_operations apb1_log_enable_fops = { + .read = apb1_log_enable_read, + .write = apb1_log_enable_write, +}; + /* * The ES1 USB Bridge device contains 4 endpoints * 1 Control - usual USB stuff + AP -> SVC messages @@ -600,6 +732,10 @@ static int ap_probe(struct usb_interface *interface, if (retval) goto error; + apb1_log_enable_dentry = debugfs_create_file("apb1_log_enable", 666, + gb_debugfs_get(), es1, + &apb1_log_enable_fops); + return 0; error: ap_disconnect(interface); -- cgit v0.10.2 From 6c28f09658483dcfb1a7f2adc8160982c652bc83 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 24 Mar 2015 19:55:14 +0100 Subject: greybus: es1: fix build warning for apb1_log_enable_write It's "const char __user *buf", not "char __user *buf". 'make check' is your friend. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 9ad8a76..8de005b 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -579,7 +579,7 @@ static ssize_t apb1_log_enable_read(struct file *f, char __user *buf, return simple_read_from_buffer(buf, count, ppos, tmp_buf, 3); } -static ssize_t apb1_log_enable_write(struct file *f, char __user *buf, +static ssize_t apb1_log_enable_write(struct file *f, const char __user *buf, size_t count, loff_t *ppos) { int enable; -- cgit v0.10.2 From 2f4e236648d9c7f622518ec0098cd1cb6af21659 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 24 Mar 2015 20:03:39 +0100 Subject: greybus: es1: fix tiny whitespace issues No trailing spaces or spaces before tabs are allowed. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 8de005b..4524add 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -129,7 +129,7 @@ static void usb_log_enable(struct es1_ap_dev *es1, int enable); * host driver. I.e., ((char *)buffer - headroom) must * point to valid memory, usable only by the host driver. * size_max: The maximum size of a buffer (not including the - * headroom) must not exceed this. + * headroom) must not exceed this. */ static void hd_buffer_constraints(struct greybus_host_device *hd) { @@ -597,7 +597,7 @@ static ssize_t apb1_log_enable_write(struct file *f, const char __user *buf, retval = count; } kfree(tmp_buf); - + return retval; } -- cgit v0.10.2 From cd674c8d4c3a1a9736ed1e9f8ec8f9ee2aaa26e0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 24 Mar 2015 20:04:49 +0100 Subject: greybus: es1: use and not Asm is only for when you are doing arch-specific stuff, which we aren't doing here. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 4524add..cce3155 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include "greybus.h" #include "svc_msg.h" -- cgit v0.10.2 From 26164edb8fb467a4249fab159709a6cfc50ddc8c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 24 Mar 2015 20:06:41 +0100 Subject: greybus: es1: no need to check for NULL on debugfs_remove() The function can, and even expects NULL, so don't check. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index cce3155..723d8b7 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -558,10 +558,8 @@ static void usb_log_enable(struct es1_ap_dev *es1, int enable) gb_debugfs_get(), NULL, &apb1_log_fops); } else { - if (apb1_log_dentry) { - debugfs_remove(apb1_log_dentry); - apb1_log_dentry = NULL; - } + debugfs_remove(apb1_log_dentry); + apb1_log_dentry = NULL; if (apb1_log_task) { kthread_stop(apb1_log_task); -- cgit v0.10.2 From 4600d03f80aea65f29f324b89d1b3437982f3eba Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 24 Mar 2015 20:08:12 +0100 Subject: greybus: es1: struct file_operations needs to be const We aren't changing these pointers, so mark them read-only as that is the preferred way. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 723d8b7..7e612cb 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -540,7 +540,7 @@ static ssize_t apb1_log_read(struct file *f, char __user *buf, return ret; } -static struct file_operations apb1_log_fops = { +static const struct file_operations apb1_log_fops = { .read = apb1_log_read, }; @@ -599,7 +599,7 @@ static ssize_t apb1_log_enable_write(struct file *f, const char __user *buf, return retval; } -static struct file_operations apb1_log_enable_fops = { +static const struct file_operations apb1_log_enable_fops = { .read = apb1_log_enable_read, .write = apb1_log_enable_write, }; -- cgit v0.10.2 From d52f9973e2de01e6da7beb2e91ece009ffd880a2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 24 Mar 2015 20:10:58 +0100 Subject: greybus: es1: decimal modes are not what are wanted for debugfs decimal is not octal, so use the proper mode settings for the debugfs files. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 7e612cb..796c2ab5 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -554,7 +554,7 @@ static void usb_log_enable(struct es1_ap_dev *es1, int enable) apb1_log_task = kthread_run(apb1_log_poll, es1, "apb1_log"); if (apb1_log_task == ERR_PTR(-ENOMEM)) return; - apb1_log_dentry = debugfs_create_file("apb1_log", 444, + apb1_log_dentry = debugfs_create_file("apb1_log", S_IRUGO, gb_debugfs_get(), NULL, &apb1_log_fops); } else { @@ -730,7 +730,8 @@ static int ap_probe(struct usb_interface *interface, if (retval) goto error; - apb1_log_enable_dentry = debugfs_create_file("apb1_log_enable", 666, + apb1_log_enable_dentry = debugfs_create_file("apb1_log_enable", + (S_IWUSR | S_IRUGO), gb_debugfs_get(), es1, &apb1_log_enable_fops); -- cgit v0.10.2 From 64b8a16f4486912e4aa315497ea13c2d57402fc3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 24 Mar 2015 20:32:40 +0100 Subject: greybus: es1: move debugfs function to use kstrotoint_from_user() No need to duplicate built-in functions that the kernel has, so have the core kernel parse the userspace string. Saves us an allocation and makes the logic simpler. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 796c2ab5..a7fb4b5 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -581,20 +581,19 @@ static ssize_t apb1_log_enable_write(struct file *f, const char __user *buf, size_t count, loff_t *ppos) { int enable; - char *tmp_buf; - ssize_t retval = -EINVAL; + ssize_t retval; struct es1_ap_dev *es1 = (struct es1_ap_dev *)f->f_inode->i_private; - tmp_buf = kmalloc(count, GFP_KERNEL); - if (!tmp_buf) - return -ENOMEM; + retval = kstrtoint_from_user(buf, count, 10, &enable); + if (retval) + return retval; - copy_from_user(tmp_buf, buf, count); - if (sscanf(tmp_buf, "%d", &enable) == 1) { + if (enable) { usb_log_enable(es1, enable); retval = count; + } else { + retval = -EINVAL; } - kfree(tmp_buf); return retval; } -- cgit v0.10.2 From efdc43130cdb3dbcd25d1586e93181abbc714ea5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 24 Mar 2015 20:34:02 +0100 Subject: greybus: es1: fix checkpatch warning about blank lines needed Add a blank line in apb1_log_enable_read() to make checkpatch happy. Oh, and it makes the code more readable too... Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index a7fb4b5..225ef3f 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -573,6 +573,7 @@ static ssize_t apb1_log_enable_read(struct file *f, char __user *buf, { char tmp_buf[3]; int enable = apb1_log_task != NULL; + sprintf(tmp_buf, "%d\n", enable); return simple_read_from_buffer(buf, count, ppos, tmp_buf, 3); } -- cgit v0.10.2 From 0c264c6fc2c3f47d94169a38506cdf151a9ba52e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 24 Mar 2015 20:45:31 +0100 Subject: greybus: es1: separate usb_log enable/disable logic into different functions One function shouldn't do two different things depending on a parameter passed to it, so split usb_log_enable() into usb_log_disable() Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 225ef3f..53d2d47 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -101,7 +101,8 @@ static inline struct es1_ap_dev *hd_to_es1(struct greybus_host_device *hd) } static void cport_out_callback(struct urb *urb); -static void usb_log_enable(struct es1_ap_dev *es1, int enable); +static void usb_log_enable(struct es1_ap_dev *es1); +static void usb_log_disable(struct es1_ap_dev *es1); /* * Buffer constraints for the host driver. @@ -337,7 +338,7 @@ static void ap_disconnect(struct usb_interface *interface) if (!es1) return; - usb_log_enable(es1, 0); + usb_log_disable(es1); /* Tear down everything! */ for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { @@ -544,28 +545,30 @@ static const struct file_operations apb1_log_fops = { .read = apb1_log_read, }; -static void usb_log_enable(struct es1_ap_dev *es1, int enable) +static void usb_log_enable(struct es1_ap_dev *es1) { - if (enable && apb1_log_task != NULL) + if (apb1_log_task != NULL) return; - if (enable) { - /* get log from APB1 */ - apb1_log_task = kthread_run(apb1_log_poll, es1, "apb1_log"); - if (apb1_log_task == ERR_PTR(-ENOMEM)) - return; - apb1_log_dentry = debugfs_create_file("apb1_log", S_IRUGO, - gb_debugfs_get(), NULL, - &apb1_log_fops); - } else { - debugfs_remove(apb1_log_dentry); - apb1_log_dentry = NULL; + /* get log from APB1 */ + apb1_log_task = kthread_run(apb1_log_poll, es1, "apb1_log"); + if (apb1_log_task == ERR_PTR(-ENOMEM)) + return; + apb1_log_dentry = debugfs_create_file("apb1_log", S_IRUGO, + gb_debugfs_get(), NULL, + &apb1_log_fops); +} - if (apb1_log_task) { - kthread_stop(apb1_log_task); - apb1_log_task = NULL; - } - } +static void usb_log_disable(struct es1_ap_dev *es1) +{ + if (apb1_log_task == NULL) + return; + + debugfs_remove(apb1_log_dentry); + apb1_log_dentry = NULL; + + kthread_stop(apb1_log_task); + apb1_log_task = NULL; } static ssize_t apb1_log_enable_read(struct file *f, char __user *buf, @@ -590,7 +593,7 @@ static ssize_t apb1_log_enable_write(struct file *f, const char __user *buf, return retval; if (enable) { - usb_log_enable(es1, enable); + usb_log_enable(es1); retval = count; } else { retval = -EINVAL; -- cgit v0.10.2 From 25d1c37798cd298d726dfb114f0dcaa15824b138 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 24 Mar 2015 20:47:24 +0100 Subject: greybus: es1: allow the debug log to be stopped If you write 0 to the debugfs file, the log will stop being updated. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 53d2d47..8aad4fb 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -592,14 +592,12 @@ static ssize_t apb1_log_enable_write(struct file *f, const char __user *buf, if (retval) return retval; - if (enable) { + if (enable) usb_log_enable(es1); - retval = count; - } else { - retval = -EINVAL; - } + else + usb_log_disable(es1); - return retval; + return count; } static const struct file_operations apb1_log_enable_fops = { -- cgit v0.10.2 From 19b3b2c2aeb7e1e787a65936ada0dabc229620ea Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 24 Mar 2015 17:08:13 +0530 Subject: greybus: manifest: descriptor size should be >= header size We are calculating descriptors expected size differently based on the type of descriptor, that's fine but at few places we aren't taking size of the header into account. And that looks wrong. Lets make sure it is atleast as big as descriptor's header. Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 8b61b34..545a3bd 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -13,6 +13,27 @@ #include "greybus.h" +static const char *get_descriptor_type_string(u8 type) +{ + switch(type) { + case GREYBUS_TYPE_INVALID: + return "invalid"; + case GREYBUS_TYPE_MODULE: + return "module"; + case GREYBUS_TYPE_STRING: + return "string"; + case GREYBUS_TYPE_INTERFACE: + return "interface"; + case GREYBUS_TYPE_CPORT: + return "cport"; + case GREYBUS_TYPE_CLASS: + return "class"; + default: + WARN_ON(1); + return "unknown"; + } +} + /* * We scan the manifest once to identify where all the descriptors * are. The result is a list of these manifest_desc structures. We @@ -72,32 +93,21 @@ static int identify_descriptor(struct gb_interface *intf, return -EINVAL; } + /* Descriptor needs to at least have a header */ + expected_size = sizeof(*desc_header); + switch (desc_header->type) { case GREYBUS_TYPE_MODULE: - if (desc_size < sizeof(struct greybus_descriptor_module)) { - pr_err("module descriptor too small (%u)\n", - desc_size); - return -EINVAL; - } + expected_size += sizeof(struct greybus_descriptor_module); break; case GREYBUS_TYPE_STRING: - expected_size = sizeof(*desc_header); expected_size += sizeof(struct greybus_descriptor_string); - expected_size += (size_t)desc->string.length; - if (desc_size < expected_size) { - pr_err("string descriptor too small (%u)\n", - desc_size); - return -EINVAL; - } + expected_size += desc->string.length; break; case GREYBUS_TYPE_INTERFACE: break; case GREYBUS_TYPE_CPORT: - if (desc_size < sizeof(struct greybus_descriptor_cport)) { - pr_err("cport descriptor too small (%u)\n", - desc_size); - return -EINVAL; - } + expected_size += sizeof(struct greybus_descriptor_cport); break; case GREYBUS_TYPE_CLASS: pr_warn("class descriptor found (ignoring)\n"); @@ -108,6 +118,13 @@ static int identify_descriptor(struct gb_interface *intf, return -EINVAL; } + if (desc_size < expected_size) { + pr_err("%s descriptor too small (%u < %zu)\n", + get_descriptor_type_string(desc_header->type), + desc_size, expected_size); + return -EINVAL; + } + descriptor = kzalloc(sizeof(*descriptor), GFP_KERNEL); if (!descriptor) return -ENOMEM; -- cgit v0.10.2 From 13fe6a9af3d86019a10bdbd3195434e5a795b3b3 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 24 Mar 2015 17:08:14 +0530 Subject: greybus: manifest: don't need to check for desc_size == 0 anymore identify_descriptor() doesn't return 0 anymore and so we don't need to check the returned value against 0. Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 545a3bd..1b9edbc 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -383,9 +383,7 @@ bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size) int desc_size; desc_size = identify_descriptor(intf, desc, size); - if (desc_size <= 0) { - if (!desc_size) - pr_err("zero-sized manifest descriptor\n"); + if (desc_size < 0) { result = false; goto out; } -- cgit v0.10.2 From 0d34be75878093bef5055311c254ae3ff459fd8f Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 24 Mar 2015 20:14:28 +0530 Subject: greybus: Greybus: Place module_init/exit() right after respective routines As mentioned in kernel coding guidelines. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpb.c b/drivers/staging/greybus/gpb.c index 931d739..33bbe79 100644 --- a/drivers/staging/greybus/gpb.c +++ b/drivers/staging/greybus/gpb.c @@ -72,6 +72,7 @@ error_pwm: error_gpio: return -EPROTO; } +module_init(gpbridge_init); static void __exit gpbridge_exit(void) { @@ -84,8 +85,6 @@ static void __exit gpbridge_exit(void) gb_pwm_protocol_exit(); gb_gpio_protocol_exit(); } - -module_init(gpbridge_init); module_exit(gpbridge_exit); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/greybus/vibrator.c b/drivers/staging/greybus/vibrator.c index c92c69e..2943a9b 100644 --- a/drivers/staging/greybus/vibrator.c +++ b/drivers/staging/greybus/vibrator.c @@ -185,14 +185,13 @@ static __init int protocol_init(void) return gb_protocol_register(&vibrator_protocol); } +module_init(protocol_init); static __exit void protocol_exit(void) { gb_protocol_deregister(&vibrator_protocol); class_unregister(&vibrator_class); } - -module_init(protocol_init); module_exit(protocol_exit); MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 71e4938012faff9b84916f5424dbf4dff8d1d09e Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 24 Mar 2015 20:14:29 +0530 Subject: greybus: interface: put module->dev on failures In order to decrement the reference count of module on failures, we must call put_device(module->dev). This was missing for one of the error cases, fix it. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index d2b2e3d..b687908 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -132,7 +132,7 @@ static struct gb_interface *gb_interface_create(struct greybus_host_device *hd, intf = kzalloc(sizeof(*intf), GFP_KERNEL); if (!intf) - return NULL; + goto put_module; intf->hd = hd; /* XXX refcount? */ intf->module = module; @@ -151,10 +151,7 @@ static struct gb_interface *gb_interface_create(struct greybus_host_device *hd, if (retval) { pr_err("failed to add module device for id 0x%02hhx\n", module_id); - put_device(&intf->dev); - put_device(&module->dev); - kfree(intf); - return NULL; + goto free_intf; } spin_lock_irq(&gb_interfaces_lock); @@ -162,6 +159,13 @@ static struct gb_interface *gb_interface_create(struct greybus_host_device *hd, spin_unlock_irq(&gb_interfaces_lock); return intf; + +free_intf: + put_device(&intf->dev); + kfree(intf); +put_module: + put_device(&module->dev); + return NULL; } /* -- cgit v0.10.2 From d3d2bea16149f36b0b654a0874cb9092ff86b134 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 26 Mar 2015 21:25:01 -0500 Subject: greybus: clean up some small messes This is an old patch that I neglected to send out. It's cleaning up a couple things that got committed before I had a chance to comment on them. In operation.c there is a "FIXME" comment that is easily proven wrong by inspection. In gb_protocol_put(), there is another wrong "FIXME" comment as well. We can also use our cached copies of the protocol major and minor version number in another spot. And balance that out by using a cached copy of the protocol id. Signed-off-by: Alex Elder Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index d5fa2f0..5117f0b 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -1,8 +1,8 @@ /* * Greybus operations * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. * * Released under the GPLv2 only. */ @@ -732,7 +732,6 @@ int gb_operation_response_send(struct gb_operation *operation, int errno) } } - /* FIXME operation->response could still be NULL here */ /* Fill in the response header and send it */ operation->response->header->result = gb_operation_errno_map(errno); diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index 51549e2..ba4cc0f 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -1,8 +1,8 @@ /* * Greybus protocol handling * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. * * Released under the GPLv2 only. */ @@ -191,6 +191,7 @@ EXPORT_SYMBOL_GPL(gb_protocol_get_version); void gb_protocol_put(struct gb_protocol *protocol) { + u8 id; u8 major; u8 minor; u8 protocol_count; @@ -198,12 +199,12 @@ void gb_protocol_put(struct gb_protocol *protocol) if (!protocol) return; + id = protocol->id; major = protocol->major; minor = protocol->minor; spin_lock_irq(&gb_protocols_lock); - protocol = _gb_protocol_find(protocol->id, protocol->major, - protocol->minor); + protocol = _gb_protocol_find(id, major, minor); if (protocol) { protocol_count = protocol->count; if (protocol_count) @@ -214,9 +215,6 @@ void gb_protocol_put(struct gb_protocol *protocol) if (protocol) WARN_ON(!protocol_count); else - /* FIXME a different message is needed since this one - * will result in a NULL dereference - */ pr_err("protocol id %hhu version %hhu.%hhu not found\n", - protocol->id, major, minor); + id, major, minor); } -- cgit v0.10.2 From 142f8ddf71e2e081955b4f54ba72c78dbb7b7ce8 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 26 Mar 2015 21:25:06 -0500 Subject: greybus: get rid of {conceal,reveal}_urb() These clever macros were fine for early development, but they're more of a distraction now. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 8aad4fb..239358d 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -21,13 +21,6 @@ #include "svc_msg.h" #include "kernel_ver.h" -/* - * Macros for making pointers explicitly opaque, such that the result - * isn't valid but also can't be mistaken for an ERR_PTR() value. - */ -#define conceal_urb(urb) ((void *)((uintptr_t)(urb) ^ 0xbad)) -#define reveal_urb(cookie) ((void *)((uintptr_t)(cookie) ^ 0xbad)) - /* Memory sizes for the buffers sent to/from the ES1 controller */ #define ES1_SVC_MSG_SIZE (sizeof(struct svc_msg) + SZ_64K) #define ES1_GBUF_MSG_SIZE_MAX PAGE_SIZE @@ -274,7 +267,7 @@ static void *buffer_send(struct greybus_host_device *hd, u16 cport_id, return ERR_PTR(retval); } - return conceal_urb(urb); + return urb; } /* @@ -292,7 +285,7 @@ static void buffer_cancel(void *cookie) * is valid. For the time being, this will do. */ if (cookie) - usb_kill_urb(reveal_urb(cookie)); + usb_kill_urb(cookie); } static struct greybus_host_driver es1_driver = { diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index d8d45be..a73a268 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -1,8 +1,8 @@ /* * Greybus "AP" USB driver for "ES2" controller chips * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. * * Released under the GPLv2 only. */ @@ -17,13 +17,6 @@ #include "svc_msg.h" #include "kernel_ver.h" -/* - * Macros for making pointers explicitly opaque, such that the result - * isn't valid but also can't be mistaken for an ERR_PTR() value. - */ -#define conceal_urb(urb) ((void *)((uintptr_t)(urb) ^ 0xbad)) -#define reveal_urb(cookie) ((void *)((uintptr_t)(cookie) ^ 0xbad)) - /* Memory sizes for the buffers sent to/from the ES1 controller */ #define ES1_SVC_MSG_SIZE (sizeof(struct svc_msg) + SZ_64K) #define ES1_GBUF_MSG_SIZE_MAX PAGE_SIZE @@ -262,7 +255,7 @@ static void *buffer_send(struct greybus_host_device *hd, u16 cport_id, return ERR_PTR(retval); } - return conceal_urb(urb); + return urb; } /* @@ -280,7 +273,7 @@ static void buffer_cancel(void *cookie) * is valid. For the time being, this will do. */ if (cookie) - usb_kill_urb(reveal_urb(cookie)); + usb_kill_urb(cookie); } static struct greybus_host_driver es1_driver = { -- cgit v0.10.2 From 48f70474f48f87cc2dec5ee0a2ba7139bbef3cef Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 27 Mar 2015 11:38:06 +0100 Subject: greybus: debugfs: we shouldn't care if debugfs is working or not This removes the error checking for debugfs initialization as we really don't care if it failed or not. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index a25df36..96265a1d 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -212,11 +212,7 @@ static int __init gb_init(void) BUILD_BUG_ON(HOST_DEV_CPORT_ID_MAX >= (long)CPORT_ID_BAD); - retval = gb_debugfs_init(); - if (retval) { - pr_err("debugfs failed\n"); - return retval; - } + gb_debugfs_init(); retval = bus_register(&greybus_bus_type); if (retval) { diff --git a/drivers/staging/greybus/debugfs.c b/drivers/staging/greybus/debugfs.c index b8865d7..59c5709 100644 --- a/drivers/staging/greybus/debugfs.c +++ b/drivers/staging/greybus/debugfs.c @@ -15,13 +15,9 @@ static struct dentry *gb_debug_root; -int gb_debugfs_init(void) +void gb_debugfs_init(void) { gb_debug_root = debugfs_create_dir("greybus", NULL); - if (!gb_debug_root) - return -ENOENT; - - return 0; } void gb_debugfs_cleanup(void) diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 967d64f..5a7f622 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -158,7 +158,7 @@ int greybus_disabled(void); int greybus_svc_in(struct greybus_host_device *hd, u8 *data, int length); int gb_ap_init(void); void gb_ap_exit(void); -int gb_debugfs_init(void); +void gb_debugfs_init(void); void gb_debugfs_cleanup(void); struct dentry *gb_debugfs_get(void); -- cgit v0.10.2 From ca3ec299c2d090f99fedcc5995dc1f25ab609408 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 27 Mar 2015 11:38:07 +0100 Subject: greybus: es2: sync up with recent es1.c changes This brings the debug log functionality of es1.c to es2.c, along with some other minor cleanups. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index a73a268..e463750 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -8,10 +8,14 @@ */ #include #include +#include #include #include #include #include +#include +#include +#include #include "greybus.h" #include "svc_msg.h" @@ -28,6 +32,12 @@ static const struct usb_device_id id_table[] = { }; MODULE_DEVICE_TABLE(usb, id_table); +#define APB1_LOG_SIZE SZ_16K +static struct dentry *apb1_log_dentry; +static struct dentry *apb1_log_enable_dentry; +static struct task_struct *apb1_log_task; +static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); + /* * Number of CPort IN urbs in flight at any point in time. * Adjust if we are having stalls in the USB buffer due to not enough urbs in @@ -84,6 +94,8 @@ static inline struct es1_ap_dev *hd_to_es1(struct greybus_host_device *hd) } static void cport_out_callback(struct urb *urb); +static void usb_log_enable(struct es1_ap_dev *es1); +static void usb_log_disable(struct es1_ap_dev *es1); /* * Buffer constraints for the host driver. @@ -111,7 +123,7 @@ static void cport_out_callback(struct urb *urb); * host driver. I.e., ((char *)buffer - headroom) must * point to valid memory, usable only by the host driver. * size_max: The maximum size of a buffer (not including the - * headroom) must not exceed this. + * headroom) must not exceed this. */ static void hd_buffer_constraints(struct greybus_host_device *hd) { @@ -319,6 +331,8 @@ static void ap_disconnect(struct usb_interface *interface) if (!es1) return; + usb_log_disable(es1); + /* Tear down everything! */ for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { struct urb *urb = es1->cport_out_urb[i]; @@ -467,6 +481,123 @@ static void cport_out_callback(struct urb *urb) */ } +static void apb1_log_get(struct es1_ap_dev *es1) +{ + char buf[65]; + int retval; + + /* SVC messages go down our control pipe */ + do { + memset(buf, 0, 65); + retval = usb_control_msg(es1->usb_dev, + usb_rcvctrlpipe(es1->usb_dev, + es1->control_endpoint), + 0x02, /* vendor request APB1 log */ + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + 0x00, 0x00, + buf, + 64, + ES1_TIMEOUT); + if (retval > 0) + kfifo_in(&apb1_log_fifo, buf, retval); + } while (retval > 0); +} + +static int apb1_log_poll(void *data) +{ + while (!kthread_should_stop()) { + msleep(1000); + apb1_log_get((struct es1_ap_dev *)data); + } + return 0; +} + +static ssize_t apb1_log_read(struct file *f, char __user *buf, + size_t count, loff_t *ppos) +{ + ssize_t ret; + size_t copied; + char *tmp_buf; + + if (count > APB1_LOG_SIZE) + count = APB1_LOG_SIZE; + + tmp_buf = kmalloc(count, GFP_KERNEL); + if (!tmp_buf) + return -ENOMEM; + + copied = kfifo_out(&apb1_log_fifo, tmp_buf, count); + ret = simple_read_from_buffer(buf, count, ppos, tmp_buf, copied); + + kfree(tmp_buf); + + return ret; +} + +static const struct file_operations apb1_log_fops = { + .read = apb1_log_read, +}; + +static void usb_log_enable(struct es1_ap_dev *es1) +{ + if (apb1_log_task != NULL) + return; + + /* get log from APB1 */ + apb1_log_task = kthread_run(apb1_log_poll, es1, "apb1_log"); + if (apb1_log_task == ERR_PTR(-ENOMEM)) + return; + apb1_log_dentry = debugfs_create_file("apb1_log", S_IRUGO, + gb_debugfs_get(), NULL, + &apb1_log_fops); +} + +static void usb_log_disable(struct es1_ap_dev *es1) +{ + if (apb1_log_task == NULL) + return; + + debugfs_remove(apb1_log_dentry); + apb1_log_dentry = NULL; + + kthread_stop(apb1_log_task); + apb1_log_task = NULL; +} + +static ssize_t apb1_log_enable_read(struct file *f, char __user *buf, + size_t count, loff_t *ppos) +{ + char tmp_buf[3]; + int enable = apb1_log_task != NULL; + + sprintf(tmp_buf, "%d\n", enable); + return simple_read_from_buffer(buf, count, ppos, tmp_buf, 3); +} + +static ssize_t apb1_log_enable_write(struct file *f, const char __user *buf, + size_t count, loff_t *ppos) +{ + int enable; + ssize_t retval; + struct es1_ap_dev *es1 = (struct es1_ap_dev *)f->f_inode->i_private; + + retval = kstrtoint_from_user(buf, count, 10, &enable); + if (retval) + return retval; + + if (enable) + usb_log_enable(es1); + else + usb_log_disable(es1); + + return count; +} + +static const struct file_operations apb1_log_enable_fops = { + .read = apb1_log_enable_read, + .write = apb1_log_enable_write, +}; + /* * The ES1 USB Bridge device contains 4 endpoints * 1 Control - usual USB stuff + AP -> SVC messages @@ -552,9 +683,6 @@ static int ap_probe(struct usb_interface *interface, usb_rcvintpipe(udev, es1->svc_endpoint), es1->svc_buffer, ES1_SVC_MSG_SIZE, svc_in_callback, hd, svc_interval); - retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); - if (retval) - goto error; /* Allocate buffers for our cport in messages and start them up */ for (i = 0; i < NUM_CPORT_IN_URB; ++i) { @@ -591,6 +719,16 @@ static int ap_probe(struct usb_interface *interface, es1->cport_out_urb_busy[i] = false; /* just to be anal */ } + /* Start up our svc urb, which allows events to start flowing */ + retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); + if (retval) + goto error; + + apb1_log_enable_dentry = debugfs_create_file("apb1_log_enable", + (S_IWUSR | S_IRUGO), + gb_debugfs_get(), es1, + &apb1_log_enable_fops); + return 0; error: ap_disconnect(interface); -- cgit v0.10.2 From e2cb6cacad80355b1b9ba864ab9e68b9e4014c21 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 27 Mar 2015 16:32:56 +0530 Subject: greybus: kernel_ver.h: include to fix warning And this is the warning I was getting on kernel version > 3.14 CC [M] greybus/connection.o In file included from include/asm-generic/gpio.h:4:0, from arch/arm/include/asm/gpio.h:9, from include/linux/gpio.h:48, from greybus/kernel_ver.h:59, from greybus/connection.c:12: include/linux/kernel.h:35:0: warning: "U16_MAX" redefined kernel_ver.h is taking care of defining U16_MAX only if is not defined earlier, but it is often included as the first .h file. might be included later, which always defines it, unconditionally. And so this warning. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index f0010a8..12b454e 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -14,6 +14,8 @@ #ifndef __GREYBUS_KERNEL_VER_H #define __GREYBUS_KERNEL_VER_H +#include + #ifndef __ATTR_WO #define __ATTR_WO(_name) { \ .attr = { .name = __stringify(_name), .mode = S_IWUSR }, \ -- cgit v0.10.2 From 1dad6b3515b2cac308a039cf2d081f6b72db1e4a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 27 Mar 2015 12:41:10 +0100 Subject: greybus: operation: fix missing symbol exports Add missing EXPORT_SYMBOL_GPL for gb_operation_response_alloc, gb_operation_result, gb_operation_get, gb_operation_request_send and gb_operation_cancel, which are all supposed to be accessible from protocol handlers. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 5117f0b..5447351 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -147,6 +147,7 @@ int gb_operation_result(struct gb_operation *operation) return result; } +EXPORT_SYMBOL_GPL(gb_operation_result); static struct gb_operation * gb_operation_find(struct gb_connection *connection, u16 operation_id) @@ -463,6 +464,7 @@ bool gb_operation_response_alloc(struct gb_operation *operation, return true; } +EXPORT_SYMBOL_GPL(gb_operation_response_alloc); /* * Create a Greybus operation to be sent over the given connection. @@ -589,6 +591,7 @@ void gb_operation_get(struct gb_operation *operation) { kref_get(&operation->kref); } +EXPORT_SYMBOL_GPL(gb_operation_get); /* * Destroy a previously created operation. @@ -677,6 +680,7 @@ int gb_operation_request_send(struct gb_operation *operation, return gb_message_send(operation->request); } +EXPORT_SYMBOL_GPL(gb_operation_request_send); /* * Send a synchronous operation. This function is expected to @@ -901,6 +905,7 @@ void gb_operation_cancel(struct gb_operation *operation, int errno) } gb_operation_put(operation); } +EXPORT_SYMBOL_GPL(gb_operation_cancel); /** * gb_operation_sync: implement a "simple" synchronous gb operation. -- cgit v0.10.2 From d506283491eb423cb8c6957d91070d3ac2d81b6a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 27 Mar 2015 12:41:11 +0100 Subject: greybus: operation: fix typo in comment Fix typo in comment. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 5447351..41a3deb 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -75,7 +75,7 @@ static DEFINE_SPINLOCK(gb_operations_lock); * valid value operation->errno can be set to is -EINPROGRESS, * indicating the request has been (or rather is about to be) sent. * At that point nobody should be looking at the result until the - * reponse arrives. + * response arrives. * * The first time the result gets set after the request has been * sent, that result "sticks." That is, if two concurrent threads -- cgit v0.10.2 From 37754030b0b9f7b81217b891cdc5f21dd7d29e4d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 27 Mar 2015 12:41:12 +0100 Subject: greybus: operation: fix callback handling and documentation Fix up obsolete comments referring to null callback pointers for synchronous operations, and make sure a callback is always provided when sending a request. Also document that the callback is responsible for dropping the initial (and not necessarily final) reference to the operation. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 41a3deb..c64b2bf 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -244,10 +244,9 @@ static void gb_operation_work(struct work_struct *work) struct gb_operation *operation; operation = container_of(work, struct gb_operation, work); - if (operation->callback) { - operation->callback(operation); - operation->callback = NULL; - } + + operation->callback(operation); + gb_operation_put(operation); } @@ -526,7 +525,6 @@ gb_operation_create_common(struct gb_connection *connection, u8 type, operation->errno = -EBADR; /* Initial value--means "never set" */ INIT_WORK(&operation->work, gb_operation_work); - operation->callback = NULL; /* set at submit time */ init_completion(&operation->completion); kref_init(&operation->kref); @@ -632,16 +630,12 @@ static void gb_operation_sync_callback(struct gb_operation *operation) } /* - * Send an operation request message. The caller has filled in - * any payload so the request message is ready to go. If non-null, - * the callback function supplied will be called when the response - * message has arrived indicating the operation is complete. In - * that case, the callback function is responsible for fetching the - * result of the operation using gb_operation_result() if desired, - * and dropping the final reference to (i.e., destroying) the - * operation. A null callback function is used for a synchronous - * request; in that case return from this function won't occur until - * the operation is complete. + * Send an operation request message. The caller has filled in any payload so + * the request message is ready to go. The callback function supplied will be + * called when the response message has arrived indicating the operation is + * complete. In that case, the callback function is responsible for fetching + * the result of the operation using gb_operation_result() if desired, and + * dropping the initial reference to the operation. */ int gb_operation_request_send(struct gb_operation *operation, gb_operation_callback callback) @@ -650,6 +644,9 @@ int gb_operation_request_send(struct gb_operation *operation, struct gb_operation_msg_hdr *header; unsigned int cycle; + if (!callback) + return -EINVAL; + if (connection->state != GB_CONNECTION_STATE_ENABLED) return -ENOTCONN; @@ -805,10 +802,8 @@ static void gb_connection_recv_request(struct gb_connection *connection, * request handler to be the operation's callback function. * * The last thing the handler does is send a response - * message. The callback function is then cleared (in - * gb_operation_work()). The original reference to the - * operation will be dropped when the response has been - * sent. + * message. The original reference to the operation will be + * dropped when the response has been sent. */ operation->callback = gb_operation_request_handle; if (gb_operation_result_set(operation, -EINPROGRESS)) -- cgit v0.10.2 From 0fb5acc4018c0da61f9084932d0cd816fab77eec Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 27 Mar 2015 12:41:13 +0100 Subject: greybus: operation: fix use-after-free when sending responses Fix use-after-free when sending responses due to reference imbalance. Make sure to take a reference to the operation when sending responses. This reference is dropped in greybus_data_sent when the message has been sent, while the initial reference is dropped in gb_operation_work after processing the corresponding request. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index c64b2bf..ad45dee 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -719,6 +719,8 @@ EXPORT_SYMBOL_GPL(gb_operation_request_send_sync); */ int gb_operation_response_send(struct gb_operation *operation, int errno) { + int ret; + /* Record the result */ if (!gb_operation_result_set(operation, errno)) { pr_err("request result already set\n"); @@ -733,10 +735,17 @@ int gb_operation_response_send(struct gb_operation *operation, int errno) } } + /* Reference will be dropped when message has been sent. */ + gb_operation_get(operation); + /* Fill in the response header and send it */ operation->response->header->result = gb_operation_errno_map(errno); - return gb_message_send(operation->response); + ret = gb_message_send(operation->response); + if (ret) + gb_operation_put(operation); + + return ret; } EXPORT_SYMBOL_GPL(gb_operation_response_send); @@ -802,8 +811,8 @@ static void gb_connection_recv_request(struct gb_connection *connection, * request handler to be the operation's callback function. * * The last thing the handler does is send a response - * message. The original reference to the operation will be - * dropped when the response has been sent. + * message. The initial reference to the operation will be + * dropped when the handler returns. */ operation->callback = gb_operation_request_handle; if (gb_operation_result_set(operation, -EINPROGRESS)) -- cgit v0.10.2 From ea2c2ee80571388ef4641597c00ca10da3728127 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 27 Mar 2015 12:41:14 +0100 Subject: greybus: operation: fix memory leak in request_send error path Make sure to drop the operation reference when sending the request fails to avoid leaking the operation structures. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index ad45dee..dcf987f 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -643,6 +643,7 @@ int gb_operation_request_send(struct gb_operation *operation, struct gb_connection *connection = operation->connection; struct gb_operation_msg_hdr *header; unsigned int cycle; + int ret; if (!callback) return -EINVAL; @@ -675,7 +676,11 @@ int gb_operation_request_send(struct gb_operation *operation, /* All set, send the request */ gb_operation_result_set(operation, -EINPROGRESS); - return gb_message_send(operation->request); + ret = gb_message_send(operation->request); + if (ret) + gb_operation_put(operation); + + return ret; } EXPORT_SYMBOL_GPL(gb_operation_request_send); -- cgit v0.10.2 From ff65be7a58201ca7843813f92192d997a2a4b4ee Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 27 Mar 2015 12:41:15 +0100 Subject: greybus: operation: fix use-after-free and infinite loop on unhandled requests Make sure to return a proper response in case we get a request we do not recognise. This fixes an infinite loop and use-after-free bug, where the freed operations structure would get re-added to the work queue indefinitely. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index dcf987f..f194b1e 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -208,14 +208,11 @@ static void gb_message_cancel(struct gb_message *message) static void gb_operation_request_handle(struct gb_operation *operation) { struct gb_protocol *protocol = operation->connection->protocol; + int ret; if (!protocol) return; - /* - * If the protocol has no incoming request handler, report - * an error and mark the request bad. - */ if (protocol->request_recv) { protocol->request_recv(operation->type, operation); return; @@ -223,10 +220,14 @@ static void gb_operation_request_handle(struct gb_operation *operation) dev_err(&operation->connection->dev, "unexpected incoming request type 0x%02hhx\n", operation->type); - if (gb_operation_result_set(operation, -EPROTONOSUPPORT)) - queue_work(gb_operation_workqueue, &operation->work); - else - WARN(true, "failed to mark request bad\n"); + + ret = gb_operation_response_send(operation, -EPROTONOSUPPORT); + if (ret) { + dev_err(&operation->connection->dev, + "failed to send response %d: %d\n", + -EPROTONOSUPPORT, ret); + return; + } } /* -- cgit v0.10.2 From 772f3e90605641592435ec7c0a960e858925a0fe Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 27 Mar 2015 12:41:16 +0100 Subject: greybus: operation: fix null-deref on operation cancel Incoming operations are created without a response message. If an operation were to be cancelled before it has been fully processed (e.g. on connection destroy), we would get a null-pointer dereference in gb_operation_cancel. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index f194b1e..17f4eab 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -911,7 +911,8 @@ void gb_operation_cancel(struct gb_operation *operation, int errno) { if (gb_operation_result_set(operation, errno)) { gb_message_cancel(operation->request); - gb_message_cancel(operation->response); + if (operation->response) + gb_message_cancel(operation->response); } gb_operation_put(operation); } -- cgit v0.10.2 From 9489667684fbed2114dcdd10cdee2e4d20d9f308 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 27 Mar 2015 12:41:17 +0100 Subject: greybus: operation: fix null-deref on operation destroy Incoming operations are created without a response message. If a protocol driver fails to send a response, or if the operation were to be cancelled before it has been fully processed, we get a null-pointer dereference when the operation is released. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 17f4eab..cb0c87a 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -607,7 +607,8 @@ static void _gb_operation_destroy(struct kref *kref) list_del(&operation->links); spin_unlock_irqrestore(&gb_operations_lock, flags); - gb_operation_message_free(operation->response); + if (operation->response) + gb_operation_message_free(operation->response); gb_operation_message_free(operation->request); kmem_cache_free(gb_operation_cache, operation); -- cgit v0.10.2 From cfa79699cdef2e006f8414587c0e4d62209e4897 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 27 Mar 2015 12:41:18 +0100 Subject: greybus: operation: fix incoming request payload size Fix the payload size of incoming requests, which should not include the operation message-header size. When creating requests we pass the sizes of request and response payloads and greybus core allocates buffers and adds the required headers. Specifically, the payload sizes do not include the message-header size. This is currently not the case for incoming requests however, something which prevents protocol drivers from implementing appropriate input verification and could lead to random data being treated as a valid message in case of a short request. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index cb0c87a..8e37d14 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -567,9 +567,13 @@ EXPORT_SYMBOL_GPL(gb_operation_create); static struct gb_operation * gb_operation_create_incoming(struct gb_connection *connection, u16 id, - u8 type, void *data, size_t request_size) + u8 type, void *data, size_t size) { struct gb_operation *operation; + size_t request_size; + + /* Caller has made sure we at least have a message header. */ + request_size = size - sizeof(struct gb_operation_msg_hdr); operation = gb_operation_create_common(connection, GB_OPERATION_TYPE_INVALID, @@ -577,7 +581,7 @@ gb_operation_create_incoming(struct gb_connection *connection, u16 id, if (operation) { operation->id = id; operation->type = type; - memcpy(operation->request->header, data, request_size); + memcpy(operation->request->header, data, size); } return operation; -- cgit v0.10.2 From e1baa3f0a956764816d0614fb3636ecc7230c171 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 27 Mar 2015 12:41:19 +0100 Subject: greybus: operation: replace pr_err with dev_err Use dev_err whenever we have a connection for more informative error messages. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 8e37d14..878bfdb 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -730,17 +730,19 @@ EXPORT_SYMBOL_GPL(gb_operation_request_send_sync); */ int gb_operation_response_send(struct gb_operation *operation, int errno) { + struct gb_connection *connection = operation->connection; int ret; /* Record the result */ if (!gb_operation_result_set(operation, errno)) { - pr_err("request result already set\n"); + dev_err(&connection->dev, "request result already set\n"); return -EIO; /* Shouldn't happen */ } if (!operation->response) { if (!gb_operation_response_alloc(operation, 0)) { - pr_err("error allocating response\n"); + dev_err(&connection->dev, + "error allocating response\n"); /* XXX Respond with pre-allocated -ENOMEM? */ return -ENOMEM; } @@ -787,8 +789,10 @@ greybus_data_sent(struct greybus_host_device *hd, void *header, int status) */ operation = message->operation; if (message == operation->response) { - if (status) - pr_err("error %d sending response\n", status); + if (status) { + dev_err(&operation->connection->dev, + "error sending response: %d\n", status); + } gb_operation_put(operation); } else if (status) { if (gb_operation_result_set(operation, status)) -- cgit v0.10.2 From 0150bd7f23618eb4feb293f4db007833555a887f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 27 Mar 2015 12:41:20 +0100 Subject: greybus: operation: make incomplete-message errors more informative Include the operation id as well as the received and expected size (from header) when reporting incomplete messages. This information is useful when debugging communication errors. Also invert the size test to match the error message and increase readability. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 878bfdb..2b2b0d6 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -899,8 +899,10 @@ void gb_connection_recv(struct gb_connection *connection, header = data; msg_size = le16_to_cpu(header->size); - if (msg_size > size) { - dev_err(&connection->dev, "incomplete message\n"); + if (size < msg_size) { + dev_err(&connection->dev, + "incomplete message received: 0x%04x (%zu < %zu)\n", + le16_to_cpu(header->operation_id), size, msg_size); return; /* XXX Should still complete operation */ } -- cgit v0.10.2 From 1842dd8b7bc7d713d3c252a501411b5009b3987d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 27 Mar 2015 12:45:41 +0100 Subject: greybus: gpio: fix null-deref on short irq requests Make sure to verify the length of incoming requests before trying to parse the request buffer, which can even be NULL on empty requests. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 2bac28e..7dc675d 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -413,6 +413,12 @@ static void gb_gpio_request_recv(u8 type, struct gb_operation *op) ggc = connection->private; request = op->request; + + if (request->payload_size < sizeof(*event)) { + dev_err(ggc->chip.dev, "short event received\n"); + return; + } + event = request->payload; if (event->which > ggc->line_max) { dev_err(ggc->chip.dev, "invalid hw irq: %d\n", event->which); -- cgit v0.10.2 From 244b5a2344bce5d9675e02da65b24e026926348c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 27 Mar 2015 12:45:42 +0100 Subject: greybus: gpio: fix null-deref on unexpected irq requests Fix null-pointer dereference on failure to look up irq due to missing error handling. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 7dc675d..0500a6f 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -425,7 +425,15 @@ static void gb_gpio_request_recv(u8 type, struct gb_operation *op) return; } irq = gpio_to_irq(ggc->chip.base + event->which); + if (irq < 0) { + dev_err(ggc->chip.dev, "failed to map irq\n"); + return; + } desc = irq_to_desc(irq); + if (!desc) { + dev_err(ggc->chip.dev, "failed to look up irq\n"); + return; + } /* Dispatch interrupt */ local_irq_disable(); -- cgit v0.10.2 From fef96a226eca4eae4aea1657ebcf5b013d6e48b6 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 27 Mar 2015 12:45:43 +0100 Subject: greybus: gpio: fix missing response on request errors Send response also to incoming requests that cannot be fulfilled. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 0500a6f..9a34fc5 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -396,43 +396,47 @@ static int gb_gpio_irq_set_type(struct irq_data *d, unsigned int type) static void gb_gpio_request_recv(u8 type, struct gb_operation *op) { - struct gb_gpio_controller *ggc; struct gb_connection *connection = op->connection; + struct gb_gpio_controller *ggc = connection->private; struct gb_message *request; struct gb_gpio_irq_event_request *event; int irq; struct irq_desc *desc; int ret; + int status; if (type != GB_GPIO_TYPE_IRQ_EVENT) { dev_err(&connection->dev, "unsupported unsolicited request: %u\n", type); - return; + status = -EINVAL; + goto send_response; } - ggc = connection->private; - request = op->request; if (request->payload_size < sizeof(*event)) { dev_err(ggc->chip.dev, "short event received\n"); - return; + status = -EINVAL; + goto send_response; } event = request->payload; if (event->which > ggc->line_max) { dev_err(ggc->chip.dev, "invalid hw irq: %d\n", event->which); - return; + status = -EINVAL; + goto send_response; } irq = gpio_to_irq(ggc->chip.base + event->which); if (irq < 0) { dev_err(ggc->chip.dev, "failed to map irq\n"); - return; + status = -EINVAL; + goto send_response; } desc = irq_to_desc(irq); if (!desc) { dev_err(ggc->chip.dev, "failed to look up irq\n"); - return; + status = -EINVAL; + goto send_response; } /* Dispatch interrupt */ @@ -440,10 +444,13 @@ static void gb_gpio_request_recv(u8 type, struct gb_operation *op) handle_simple_irq(irq, desc); local_irq_enable(); - ret = gb_operation_response_send(op, 0); + status = 0; +send_response: + ret = gb_operation_response_send(op, status); if (ret) { dev_err(ggc->chip.dev, - "failed to send response status %d: %d\n", 0, ret); + "failed to send response status %d: %d\n", + status, ret); } } -- cgit v0.10.2 From b67f2d13db21de2fc948d6f7090fe2b9bae5d5bd Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 27 Mar 2015 12:45:44 +0100 Subject: greybus: hid: replace pr_err with dev_err Replace pr_err with dev_err and clean up error messages somewhat. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index fe05a08..9734c7b 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -139,10 +139,12 @@ static int gb_hid_set_report(struct gb_hid *ghid, u8 report_type, u8 report_id, memcpy(request->report, buf, len); ret = gb_operation_request_send_sync(operation); - if (ret) - pr_err("%s: operation failed (%d)\n", __func__, ret); - else + if (ret) { + dev_err(&operation->connection->dev, + "failed to set report: %d\n", ret); + } else { ret = len; + } gb_operation_destroy(operation); return ret; @@ -156,18 +158,21 @@ static void gb_hid_irq_handler(u8 type, struct gb_operation *op) int ret, size; if (type != GB_HID_TYPE_IRQ_EVENT) { - pr_err("unsupported unsolicited request\n"); + dev_err(&connection->dev, + "unsupported unsolicited request\n"); return; } ret = gb_operation_response_send(op, 0); - if (ret) - pr_err("%s: error %d sending response status %d\n", __func__, - ret, 0); + if (ret) { + dev_err(&connection->dev, + "failed to send response status %d: %d\n", + 0, ret); + } size = request->report[0] | request->report[1] << 8; if (!size) { - pr_err("%s: size can't be zero.\n", __func__); + dev_err(&connection->dev, "bad report size: %d\n", size); return; } -- cgit v0.10.2 From ecf47ab9c5ca1427baea7ab6d3226502d967f19d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 27 Mar 2015 12:45:45 +0100 Subject: greybus: hid: fix success response being sent on errors Make sure to only send a success response if we did not detect any errors. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index 9734c7b..f0da387 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -163,13 +163,6 @@ static void gb_hid_irq_handler(u8 type, struct gb_operation *op) return; } - ret = gb_operation_response_send(op, 0); - if (ret) { - dev_err(&connection->dev, - "failed to send response status %d: %d\n", - 0, ret); - } - size = request->report[0] | request->report[1] << 8; if (!size) { dev_err(&connection->dev, "bad report size: %d\n", size); @@ -179,6 +172,13 @@ static void gb_hid_irq_handler(u8 type, struct gb_operation *op) if (test_bit(GB_HID_STARTED, &ghid->flags)) hid_input_report(ghid->hid, HID_INPUT_REPORT, request->report + 2, size - 2, 1); + + ret = gb_operation_response_send(op, 0); + if (ret) { + dev_err(&connection->dev, + "failed to send response status %d: %d\n", + 0, ret); + } } -- cgit v0.10.2 From 36257f6b4e7671cb12f98d91a6ffdeabdc254d0c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 27 Mar 2015 12:45:46 +0100 Subject: greybus: hid: fix null-deref on short report requests Make sure to verify the length of incoming requests before trying to parse the request buffer, which can even be NULL on empty requests. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index f0da387..a225813 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -163,6 +163,11 @@ static void gb_hid_irq_handler(u8 type, struct gb_operation *op) return; } + if (op->request->payload_size < 2) { + dev_err(&connection->dev, "short report received\n"); + return; + } + size = request->report[0] | request->report[1] << 8; if (!size) { dev_err(&connection->dev, "bad report size: %d\n", size); -- cgit v0.10.2 From 382145beb4a4bb057f17d5b411546b6b56fbacd1 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 27 Mar 2015 12:45:47 +0100 Subject: greybus: hid: fix missing input verification of report events Add minimal verification of incoming report size, before using it to determine what buffer and size to pass on to HID core. Add comment about protocol needing to be revisited. If we are going to be parsing the report data received, then those fields have to be defined in the Greybus specification at least. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index a225813..8e32dfc 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -168,8 +168,12 @@ static void gb_hid_irq_handler(u8 type, struct gb_operation *op) return; } + /* + * FIXME: add report size to Greybus HID protocol if we need to parse + * it here. + */ size = request->report[0] | request->report[1] << 8; - if (!size) { + if (size < 2 || size > op->request->payload_size - 2) { dev_err(&connection->dev, "bad report size: %d\n", size); return; } -- cgit v0.10.2 From d0eb755aeef092f27b3dd2a4c90616f613541f56 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 27 Mar 2015 12:45:48 +0100 Subject: greybus: hid: fix missing response on request errors Send response also to incoming requests that cannot be fulfilled. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index 8e32dfc..cc5708d 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -155,17 +155,20 @@ static void gb_hid_irq_handler(u8 type, struct gb_operation *op) struct gb_connection *connection = op->connection; struct gb_hid *ghid = connection->private; struct gb_hid_input_report_request *request = op->request->payload; + int status; int ret, size; if (type != GB_HID_TYPE_IRQ_EVENT) { dev_err(&connection->dev, "unsupported unsolicited request\n"); - return; + status = -EINVAL; + goto send_response; } if (op->request->payload_size < 2) { dev_err(&connection->dev, "short report received\n"); - return; + status = -EINVAL; + goto send_response; } /* @@ -175,18 +178,21 @@ static void gb_hid_irq_handler(u8 type, struct gb_operation *op) size = request->report[0] | request->report[1] << 8; if (size < 2 || size > op->request->payload_size - 2) { dev_err(&connection->dev, "bad report size: %d\n", size); - return; + status = -EINVAL; + goto send_response; } if (test_bit(GB_HID_STARTED, &ghid->flags)) hid_input_report(ghid->hid, HID_INPUT_REPORT, request->report + 2, size - 2, 1); - ret = gb_operation_response_send(op, 0); + status = 0; +send_response: + ret = gb_operation_response_send(op, status); if (ret) { dev_err(&connection->dev, "failed to send response status %d: %d\n", - 0, ret); + status, ret); } } -- cgit v0.10.2 From 973ccfd62686a2331f43b0053de052d958f50d31 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 27 Mar 2015 12:45:49 +0100 Subject: greybus: operation: refactor response handling Send response to incoming requests from the operation request handler rather than in every protocol request_recv callback. This simplifies request_recv error handling and allows for further code reuse. Note that if we ever get protocols that need to hold off sending responses we could implement this by letting them return a special value (after acquiring the necessary operation references) to suppress the response from being sent by greybus core. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 9a34fc5..20917bf 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -394,7 +394,7 @@ static int gb_gpio_irq_set_type(struct irq_data *d, unsigned int type) return ret; } -static void gb_gpio_request_recv(u8 type, struct gb_operation *op) +static int gb_gpio_request_recv(u8 type, struct gb_operation *op) { struct gb_connection *connection = op->connection; struct gb_gpio_controller *ggc = connection->private; @@ -402,41 +402,35 @@ static void gb_gpio_request_recv(u8 type, struct gb_operation *op) struct gb_gpio_irq_event_request *event; int irq; struct irq_desc *desc; - int ret; - int status; if (type != GB_GPIO_TYPE_IRQ_EVENT) { dev_err(&connection->dev, "unsupported unsolicited request: %u\n", type); - status = -EINVAL; - goto send_response; + return -EINVAL; } request = op->request; if (request->payload_size < sizeof(*event)) { dev_err(ggc->chip.dev, "short event received\n"); - status = -EINVAL; - goto send_response; + return -EINVAL; } event = request->payload; if (event->which > ggc->line_max) { dev_err(ggc->chip.dev, "invalid hw irq: %d\n", event->which); - status = -EINVAL; - goto send_response; + return -EINVAL; } + irq = gpio_to_irq(ggc->chip.base + event->which); if (irq < 0) { dev_err(ggc->chip.dev, "failed to map irq\n"); - status = -EINVAL; - goto send_response; + return -EINVAL; } desc = irq_to_desc(irq); if (!desc) { dev_err(ggc->chip.dev, "failed to look up irq\n"); - status = -EINVAL; - goto send_response; + return -EINVAL; } /* Dispatch interrupt */ @@ -444,14 +438,7 @@ static void gb_gpio_request_recv(u8 type, struct gb_operation *op) handle_simple_irq(irq, desc); local_irq_enable(); - status = 0; -send_response: - ret = gb_operation_response_send(op, status); - if (ret) { - dev_err(ggc->chip.dev, - "failed to send response status %d: %d\n", - status, ret); - } + return 0; } static int gb_gpio_request(struct gpio_chip *chip, unsigned offset) diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index cc5708d..5935aa6 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -150,25 +150,22 @@ static int gb_hid_set_report(struct gb_hid *ghid, u8 report_type, u8 report_id, return ret; } -static void gb_hid_irq_handler(u8 type, struct gb_operation *op) +static int gb_hid_irq_handler(u8 type, struct gb_operation *op) { struct gb_connection *connection = op->connection; struct gb_hid *ghid = connection->private; struct gb_hid_input_report_request *request = op->request->payload; - int status; - int ret, size; + int size; if (type != GB_HID_TYPE_IRQ_EVENT) { dev_err(&connection->dev, "unsupported unsolicited request\n"); - status = -EINVAL; - goto send_response; + return -EINVAL; } if (op->request->payload_size < 2) { dev_err(&connection->dev, "short report received\n"); - status = -EINVAL; - goto send_response; + return -EINVAL; } /* @@ -178,22 +175,14 @@ static void gb_hid_irq_handler(u8 type, struct gb_operation *op) size = request->report[0] | request->report[1] << 8; if (size < 2 || size > op->request->payload_size - 2) { dev_err(&connection->dev, "bad report size: %d\n", size); - status = -EINVAL; - goto send_response; + return -EINVAL; } if (test_bit(GB_HID_STARTED, &ghid->flags)) hid_input_report(ghid->hid, HID_INPUT_REPORT, request->report + 2, size - 2, 1); - status = 0; -send_response: - ret = gb_operation_response_send(op, status); - if (ret) { - dev_err(&connection->dev, - "failed to send response status %d: %d\n", - status, ret); - } + return 0; } diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 2b2b0d6..260774e 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -208,24 +208,27 @@ static void gb_message_cancel(struct gb_message *message) static void gb_operation_request_handle(struct gb_operation *operation) { struct gb_protocol *protocol = operation->connection->protocol; + int status; int ret; if (!protocol) return; if (protocol->request_recv) { - protocol->request_recv(operation->type, operation); - return; - } + status = protocol->request_recv(operation->type, operation); + } else { + dev_err(&operation->connection->dev, + "unexpected incoming request type 0x%02hhx\n", + operation->type); - dev_err(&operation->connection->dev, - "unexpected incoming request type 0x%02hhx\n", operation->type); + status = -EPROTONOSUPPORT; + } - ret = gb_operation_response_send(operation, -EPROTONOSUPPORT); + ret = gb_operation_response_send(operation, status); if (ret) { dev_err(&operation->connection->dev, "failed to send response %d: %d\n", - -EPROTONOSUPPORT, ret); + status, ret); return; } } diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index a74afef..82d9e81 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -22,7 +22,7 @@ struct gb_protocol_version_response { typedef int (*gb_connection_init_t)(struct gb_connection *); typedef void (*gb_connection_exit_t)(struct gb_connection *); -typedef void (*gb_request_recv_t)(u8, struct gb_operation *); +typedef int (*gb_request_recv_t)(u8, struct gb_operation *); /* * Protocols having the same id but different major and/or minor -- cgit v0.10.2 From d8187aa2241136e9fb3801e82fe8c2dfdae06802 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 27 Mar 2015 15:06:24 -0500 Subject: greybus: manifest: use size_t for a size variable In identify_descriptor(), the variable desc_size represents the size of a memory object. So change its type from int to size_t. The return value for this function can be desc_size cast to int. One can verify by inspection this will never exceed INT_MAX. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 1b9edbc..c29a0c8 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -1,8 +1,8 @@ /* * Greybus module manifest parsing * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. * * Released under the GPLv2 only. */ @@ -79,7 +79,7 @@ static int identify_descriptor(struct gb_interface *intf, { struct greybus_descriptor_header *desc_header = &desc->header; struct manifest_desc *descriptor; - int desc_size; + size_t desc_size; size_t expected_size; if (size < sizeof(*desc_header)) { @@ -87,8 +87,8 @@ static int identify_descriptor(struct gb_interface *intf, return -EINVAL; /* Must at least have header */ } - desc_size = (int)le16_to_cpu(desc_header->size); - if ((size_t)desc_size > size) { + desc_size = le16_to_cpu(desc_header->size); + if (desc_size > size) { pr_err("descriptor too big\n"); return -EINVAL; } @@ -119,7 +119,7 @@ static int identify_descriptor(struct gb_interface *intf, } if (desc_size < expected_size) { - pr_err("%s descriptor too small (%u < %zu)\n", + pr_err("%s descriptor too small (%zu < %zu)\n", get_descriptor_type_string(desc_header->type), desc_size, expected_size); return -EINVAL; @@ -134,6 +134,8 @@ static int identify_descriptor(struct gb_interface *intf, descriptor->type = desc_header->type; list_add_tail(&descriptor->links, &intf->manifest_descs); + /* desc_size is is positive and is known to fit in a signed int */ + return desc_size; } -- cgit v0.10.2 From dada3b02a38c2e1d06a43d0d909d48f4db798dfc Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 27 Mar 2015 15:20:49 -0500 Subject: greybus: es1: test apb1_log_task safely When usb_log_enable() is called, the global apb1_log_task is used to hold the result of kthread_run(). It is possible for kthread_run() to return an error pointer, so tests of apb_log_task against NULL are insufficient to determine its validity. Note that kthread_run() never returns NULL so we don't have to check for that. But apb1_log_task is initially NULL, so that global must be both non-null and not an error in order to be considered valid. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 239358d..af8e7b3 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -540,12 +540,12 @@ static const struct file_operations apb1_log_fops = { static void usb_log_enable(struct es1_ap_dev *es1) { - if (apb1_log_task != NULL) + if (!IS_ERR_OR_NULL(apb1_log_task)) return; /* get log from APB1 */ apb1_log_task = kthread_run(apb1_log_poll, es1, "apb1_log"); - if (apb1_log_task == ERR_PTR(-ENOMEM)) + if (IS_ERR(apb1_log_task)) return; apb1_log_dentry = debugfs_create_file("apb1_log", S_IRUGO, gb_debugfs_get(), NULL, @@ -554,7 +554,7 @@ static void usb_log_enable(struct es1_ap_dev *es1) static void usb_log_disable(struct es1_ap_dev *es1) { - if (apb1_log_task == NULL) + if (IS_ERR_OR_NULL(apb1_log_task)) return; debugfs_remove(apb1_log_dentry); @@ -568,7 +568,7 @@ static ssize_t apb1_log_enable_read(struct file *f, char __user *buf, size_t count, loff_t *ppos) { char tmp_buf[3]; - int enable = apb1_log_task != NULL; + int enable = !IS_ERR_OR_NULL(apb1_log_task); sprintf(tmp_buf, "%d\n", enable); return simple_read_from_buffer(buf, count, ppos, tmp_buf, 3); -- cgit v0.10.2 From e0feaf14b102f767d00ee28443f8443e4d76ba8b Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 27 Mar 2015 15:20:49 -0500 Subject: greybus: es2: test apb1_log_task safely When usb_log_enable() is called, the global apb1_log_task is used to hold the result of kthread_run(). It is possible for kthread_run() to return an error pointer, so tests of apb_log_task against NULL are insufficient to determine its validity. Note that kthread_run() never returns NULL so we don't have to check for that. But apb1_log_task is initially NULL, so that global must be both non-null and not an error in order to be considered valid. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index e463750..23e2778 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -540,12 +540,12 @@ static const struct file_operations apb1_log_fops = { static void usb_log_enable(struct es1_ap_dev *es1) { - if (apb1_log_task != NULL) + if (!IS_ERR_OR_NULL(apb1_log_task)) return; /* get log from APB1 */ apb1_log_task = kthread_run(apb1_log_poll, es1, "apb1_log"); - if (apb1_log_task == ERR_PTR(-ENOMEM)) + if (IS_ERR(apb1_log_task)) return; apb1_log_dentry = debugfs_create_file("apb1_log", S_IRUGO, gb_debugfs_get(), NULL, @@ -554,7 +554,7 @@ static void usb_log_enable(struct es1_ap_dev *es1) static void usb_log_disable(struct es1_ap_dev *es1) { - if (apb1_log_task == NULL) + if (IS_ERR_OR_NULL(apb1_log_task)) return; debugfs_remove(apb1_log_dentry); @@ -568,7 +568,7 @@ static ssize_t apb1_log_enable_read(struct file *f, char __user *buf, size_t count, loff_t *ppos) { char tmp_buf[3]; - int enable = apb1_log_task != NULL; + int enable = !IS_ERR_OR_NULL(apb1_log_task); sprintf(tmp_buf, "%d\n", enable); return simple_read_from_buffer(buf, count, ppos, tmp_buf, 3); -- cgit v0.10.2 From 355a7058153e04b53bed3fcb792110294693d386 Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Tue, 31 Mar 2015 09:51:59 +0200 Subject: greybus: Add loopback protocol Add a simple Greybus protocol in order to stress USB and Greybus. This protocol currently support 2 requests: ping and transfer. ping request is useful to measure latency. Kernel send a ping request and firmware should respond with a ping. The transfer request request is useful to stress Greybus and USB. Kernel can send data from 0 to 4k and the firmware must send back the data to kernel. This behaviour of gb-loopback module is controlled via sysfs. Curently, connection sysfs folder is updated with new entries: - type: Type of loopback message to send * 0 => Don't send message * 1 => Send ping message continuously (message without payload) * 2 => Send transer message continuously (message with payload) - size: Size of transfer message payload: 0-4096 bytes - ms_wait: Time to wait between two messages: 0-1024 ms Module also export some statistics about connection: - latency: Time to send and receive one message - frequency: Number of packet sent per second on this cport - throughput: Quantity of data sent and received on this cport - error All this statistics are cleared everytime type, size or ms_wait entries are updated. Signed-off-by: Alexandre Bailon Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 6cb08ae..f6ad19a 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -22,6 +22,7 @@ gb-phy-y := gpb.o \ # Prefix all modules with gb- gb-vibrator-y := vibrator.o gb-battery-y := battery.o +gb-loopback-y := loopback.o gb-es1-y := es1.o gb-es2-y := es2.o @@ -29,6 +30,7 @@ obj-m += greybus.o obj-m += gb-phy.o obj-m += gb-vibrator.o obj-m += gb-battery.o +obj-m += gb-loopback.o obj-m += gb-es1.o obj-m += gb-es2.o diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 398630c..4b2cf92 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -42,6 +42,7 @@ enum greybus_protocol { GREYBUS_PROTOCOL_SENSOR = 0x0e, GREYBUS_PROTOCOL_LED = 0x0f, GREYBUS_PROTOCOL_VIBRATOR = 0x10, + GREYBUS_PROTOCOL_LOOPBACK = 0x11, /* ... */ GREYBUS_PROTOCOL_VENDOR = 0xff, }; diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c new file mode 100644 index 0000000..ae8cc9d --- /dev/null +++ b/drivers/staging/greybus/loopback.c @@ -0,0 +1,390 @@ +/* + * Loopback bridge driver for the Greybus loopback module. + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ +#include +#include +#include +#include +#include +#include +#include "greybus.h" + +struct gb_loopback_stats { + u32 min; + u32 max; + u32 avg; + u32 sum; + u32 count; +}; + +struct gb_loopback { + struct gb_connection *connection; + u8 version_major; + u8 version_minor; + + struct task_struct *task; + + int type; + u32 size; + int ms_wait; + + struct gb_loopback_stats latency; + struct gb_loopback_stats throughput; + struct gb_loopback_stats frequency; + struct timeval ts; + struct timeval te; + u64 elapsed_nsecs; + u32 error; +}; + +/* Version of the Greybus loopback protocol we support */ +#define GB_LOOPBACK_VERSION_MAJOR 0x00 +#define GB_LOOPBACK_VERSION_MINOR 0x01 + +/* Greybus loopback request types */ +#define GB_LOOPBACK_TYPE_INVALID 0x00 +#define GB_LOOPBACK_TYPE_PROTOCOL_VERSION 0x01 +#define GB_LOOPBACK_TYPE_PING 0x02 +#define GB_LOOPBACK_TYPE_TRANSFER 0x03 + +#define GB_LOOPBACK_SIZE_MAX SZ_4K + +/* Define get_version() routine */ +define_get_version(gb_loopback, LOOPBACK); + +/* interface sysfs attributes */ +#define gb_loopback_ro_attr(field, type) \ +static ssize_t field##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct gb_connection *connection = to_gb_connection(dev); \ + struct gb_loopback *gb = \ + (struct gb_loopback *)connection->private; \ + return sprintf(buf, "%"#type"\n", gb->field); \ +} \ +static DEVICE_ATTR_RO(field) + +#define gb_loopback_ro_stats_attr(name, field, type) \ +static ssize_t name##_##field##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct gb_connection *connection = to_gb_connection(dev); \ + struct gb_loopback *gb = \ + (struct gb_loopback *)connection->private; \ + return sprintf(buf, "%"#type"\n", gb->name.field); \ +} \ +static DEVICE_ATTR_RO(name##_##field) + +#define gb_loopback_stats_attrs(field) \ + gb_loopback_ro_stats_attr(field, min, d); \ + gb_loopback_ro_stats_attr(field, max, d); \ + gb_loopback_ro_stats_attr(field, avg, d); + +#define gb_loopback_attr(field, type) \ +static ssize_t field##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct gb_connection *connection = to_gb_connection(dev); \ + struct gb_loopback *gb = \ + (struct gb_loopback *)connection->private; \ + return sprintf(buf, "%"#type"\n", gb->field); \ +} \ +static ssize_t field##_store(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, \ + size_t len) \ +{ \ + int ret; \ + struct gb_connection *connection = to_gb_connection(dev); \ + struct gb_loopback *gb = \ + (struct gb_loopback *)connection->private; \ + ret = sscanf(buf, "%"#type, &gb->field); \ + pr_err("%s = %"#type"\n", #field, gb->field); \ + if (ret != 1) \ + return -EINVAL; \ + gb_loopback_check_attr(gb); \ + return len; \ +} \ +static DEVICE_ATTR_RW(field) + +static void gb_loopback_reset_stats(struct gb_loopback *gb); +static void gb_loopback_check_attr(struct gb_loopback *gb) +{ + if (gb->ms_wait > 1000) + gb->ms_wait = 1000; + if (gb->type > 3) + gb->type = 0; + if (gb->size > GB_LOOPBACK_SIZE_MAX) + gb->size = GB_LOOPBACK_SIZE_MAX; + gb->error = 0; + gb_loopback_reset_stats(gb); +} + +/* Time to send and receive one message */ +gb_loopback_stats_attrs(latency); +/* Number of packet sent per second on this cport */ +gb_loopback_stats_attrs(frequency); +/* Quantity of data sent and received on this cport */ +gb_loopback_stats_attrs(throughput); +gb_loopback_ro_attr(error, d); + +/* + * Type of loopback message to send + * 0 => Don't send message + * 1 => Send ping message continuously (message without payload) + * 2 => Send transer message continuously (message with payload) + */ +gb_loopback_attr(type, d); +/* Size of transfer message payload: 0-4096 bytes */ +gb_loopback_attr(size, u); +/* Time to wait between two messages: 0-1024 ms */ +gb_loopback_attr(ms_wait, d); + +#define dev_stats_attrs(name) \ + &dev_attr_##name##_min.attr, \ + &dev_attr_##name##_max.attr, \ + &dev_attr_##name##_avg.attr + +static struct attribute *loopback_attrs[] = { + dev_stats_attrs(latency), + dev_stats_attrs(frequency), + dev_stats_attrs(throughput), + &dev_attr_type.attr, + &dev_attr_size.attr, + &dev_attr_ms_wait.attr, + &dev_attr_error.attr, + NULL, +}; +ATTRIBUTE_GROUPS(loopback); + +struct gb_loopback_transfer_request { + __le32 len; + __u8 data[0]; +}; + +struct gb_loopback_transfer_response { + __u8 data[0]; +}; + + +static int gb_loopback_transfer(struct gb_loopback *gb, + struct timeval *tping, u32 len) +{ + struct timeval ts, te; + u64 elapsed_nsecs; + struct gb_loopback_transfer_request *request; + struct gb_loopback_transfer_response *response; + int retval; + + request = kmalloc(len + sizeof(*request), GFP_KERNEL); + if (!request) + return -ENOMEM; + response = kmalloc(len + sizeof(*response), GFP_KERNEL); + if (!response) { + kfree(request); + return -ENOMEM; + } + + request->len = cpu_to_le32(len); + + do_gettimeofday(&ts); + retval = gb_operation_sync(gb->connection, GB_LOOPBACK_TYPE_TRANSFER, + request, len + sizeof(*request), + response, len + sizeof(*response)); + do_gettimeofday(&te); + elapsed_nsecs = timeval_to_ns(&te) - timeval_to_ns(&ts); + *tping = ns_to_timeval(elapsed_nsecs); + + if (retval) + goto gb_error; + + if (memcmp(request->data, response->data, len)) + retval = -EREMOTEIO; + +gb_error: + kfree(request); + kfree(response); + + return retval; +} + +static int gb_loopback_ping(struct gb_loopback *gb, struct timeval *tping) +{ + struct timeval ts, te; + u64 elapsed_nsecs; + int retval; + + do_gettimeofday(&ts); + retval = gb_operation_sync(gb->connection, GB_LOOPBACK_TYPE_PING, + NULL, 0, NULL, 0); + do_gettimeofday(&te); + elapsed_nsecs = timeval_to_ns(&te) - timeval_to_ns(&ts); + *tping = ns_to_timeval(elapsed_nsecs); + + return retval; +} + +static void gb_loopback_reset_stats(struct gb_loopback *gb) +{ + struct gb_loopback_stats reset = { + .min = 0xffffffff, + }; + memcpy(&gb->latency, &reset, sizeof(struct gb_loopback_stats)); + memcpy(&gb->throughput, &reset, sizeof(struct gb_loopback_stats)); + memcpy(&gb->frequency, &reset, sizeof(struct gb_loopback_stats)); + memset(&gb->ts, 0, sizeof(struct timeval)); +} + +static void gb_loopback_update_stats(struct gb_loopback_stats *stats, + u64 elapsed_nsecs) +{ + u32 avg; + + if (elapsed_nsecs >= NSEC_PER_SEC) { + if (!stats->count) + avg = stats->sum * (elapsed_nsecs / NSEC_PER_SEC); + else + avg = stats->sum / stats->count; + if (stats->min > avg) + stats->min = avg; + if (stats->max < avg) + stats->max = avg; + stats->avg = avg; + stats->count = 0; + stats->sum = 0; + } +} + +static void gb_loopback_freq_update(struct gb_loopback *gb) +{ + gb->frequency.sum++; + gb_loopback_update_stats(&gb->frequency, gb->elapsed_nsecs); +} + +static void gb_loopback_bw_update(struct gb_loopback *gb, int error) +{ + if (!error) + gb->throughput.sum += gb->size * 2; + gb_loopback_update_stats(&gb->throughput, gb->elapsed_nsecs); +} + +static void gb_loopback_latency_update(struct gb_loopback *gb, + struct timeval *tlat) +{ + u32 lat; + u64 nsecs; + + nsecs = timeval_to_ns(tlat); + lat = nsecs / NSEC_PER_MSEC; + + if (gb->latency.min > lat) + gb->latency.min = lat; + if (gb->latency.max < lat) + gb->latency.max = lat; + gb->latency.sum += lat; + gb->latency.count++; + gb_loopback_update_stats(&gb->latency, gb->elapsed_nsecs); +} + +static int gb_loopback_fn(void *data) +{ + int error = 0; + struct timeval tlat = {0, 0}; + struct gb_loopback *gb = (struct gb_loopback *)data; + + while (!kthread_should_stop()) { + if (gb->type == 0) { + msleep(1000); + continue; + } + if (gb->type == 1) + error = gb_loopback_ping(gb, &tlat); + if (gb->type == 2) + error = gb_loopback_transfer(gb, &tlat, gb->size); + if (error) + gb->error++; + if (gb->ts.tv_usec == 0 && gb->ts.tv_sec == 0) { + do_gettimeofday(&gb->ts); + continue; + } + do_gettimeofday(&gb->te); + gb->elapsed_nsecs = timeval_to_ns(&gb->te) - + timeval_to_ns(&gb->ts); + gb_loopback_freq_update(gb); + if (gb->type == 2) + gb_loopback_bw_update(gb, error); + gb_loopback_latency_update(gb, &tlat); + if (gb->elapsed_nsecs >= NSEC_PER_SEC) + gb->ts = gb->te; + if (gb->ms_wait) + msleep(gb->ms_wait); + + } + return 0; +} + +static int gb_loopback_connection_init(struct gb_connection *connection) +{ + struct gb_loopback *gb; + int retval; + + gb = kzalloc(sizeof(*gb), GFP_KERNEL); + if (!gb) + return -ENOMEM; + + gb->connection = connection; + connection->private = gb; + retval = sysfs_update_group(&connection->dev.kobj, &loopback_group); + if (retval) + goto error; + + /* Check the version */ + retval = get_version(gb); + if (retval) + goto error; + + gb_loopback_reset_stats(gb); + gb->task = kthread_run(gb_loopback_fn, gb, "gb_loopback"); + if (IS_ERR(gb->task)) { + retval = IS_ERR(gb->task); + goto error; + } + + return 0; + +error: + kfree(gb); + return retval; +} + +static void gb_loopback_connection_exit(struct gb_connection *connection) +{ + struct gb_loopback *gb = connection->private; + + if (!IS_ERR_OR_NULL(gb->task)) + kthread_stop(gb->task); + sysfs_remove_group(&connection->dev.kobj, &loopback_group); + kfree(gb); +} + +static struct gb_protocol loopback_protocol = { + .name = "loopback", + .id = GREYBUS_PROTOCOL_LOOPBACK, + .major = GB_LOOPBACK_VERSION_MAJOR, + .minor = GB_LOOPBACK_VERSION_MINOR, + .connection_init = gb_loopback_connection_init, + .connection_exit = gb_loopback_connection_exit, + .request_recv = NULL, /* no incoming requests */ +}; + +gb_protocol_driver(&loopback_protocol); + +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 5679f783b1ef953f5c5706f226580abf45c82c46 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 31 Mar 2015 23:01:45 +0200 Subject: greybus: loopback: fix build breakage about SZ_4K x86 doesn't include SZ_4K somehow so explicitly include to fix the build breakage. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index ae8cc9d..7003bce 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "greybus.h" struct gb_loopback_stats { -- cgit v0.10.2 From 7a51b9362b547b2f02ef88c10636950637c71fa5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 31 Mar 2015 23:02:34 +0200 Subject: greybus: loopback: use the attribute groups, not group We should use the attribute groups, not group, for the device, so add and remove it. No one should ever be updating a sysfs group for a device, as that can be pretty dangerous if you don't duplicate _all_ existing attribute for that device, and I don't think we were doing that here. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 7003bce..9914b52 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -343,7 +343,7 @@ static int gb_loopback_connection_init(struct gb_connection *connection) gb->connection = connection; connection->private = gb; - retval = sysfs_update_group(&connection->dev.kobj, &loopback_group); + retval = sysfs_create_groups(&connection->dev.kobj, loopback_groups); if (retval) goto error; @@ -372,7 +372,7 @@ static void gb_loopback_connection_exit(struct gb_connection *connection) if (!IS_ERR_OR_NULL(gb->task)) kthread_stop(gb->task); - sysfs_remove_group(&connection->dev.kobj, &loopback_group); + sysfs_remove_groups(&connection->dev.kobj, loopback_groups); kfree(gb); } -- cgit v0.10.2 From 66c98986c909bfe789e8b15f805fd28ef4c36b76 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 1 Apr 2015 01:36:23 +0200 Subject: greybus: kernel_ver.h: add sysfs_create_groups() and sysfs_remove_groups() These functions showed up in 3.12 or so, and we are stuck on 3.10 for various reasons, so provide backports in kernel_ver.h so that we can rely on these functions. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index 12b454e..92eb024 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -78,6 +78,8 @@ static inline void gb_gpiochip_remove(struct gpio_chip *chip) * it here. */ #if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0) +#include + #define ATTRIBUTE_GROUPS(name) \ static const struct attribute_group name##_group = { \ .attrs = name##_attrs, \ @@ -86,6 +88,37 @@ static const struct attribute_group *name##_groups[] = { \ &name##_group, \ NULL, \ } + +static inline int sysfs_create_groups(struct kobject *kobj, + const struct attribute_group **groups) +{ + int error = 0; + int i; + + if (!groups) + return 0; + + for (i = 0; groups[i]; i++) { + error = sysfs_create_group(kobj, groups[i]); + if (error) { + while (--i >= 0) + sysfs_remove_group(kobj, groups[i]); + break; + } + } + return error; +} + +static inline void sysfs_remove_groups(struct kobject *kobj, + const struct attribute_group **groups) +{ + int i; + + if (!groups) + return; + for (i = 0; groups[i]; i++) + sysfs_remove_group(kobj, groups[i]); +} #endif #endif /* __GREYBUS_KERNEL_VER_H */ -- cgit v0.10.2 From e4c4b4dce628d529bc073952ddcf272d307d06bd Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 26 Mar 2015 21:25:08 -0500 Subject: greybus: reduce the ranting Cut out some comments that are no longer operative. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index af8e7b3..f559c1d 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -451,34 +451,7 @@ static void cport_out_callback(struct urb *urb) */ data = urb->transfer_buffer + 1; greybus_data_sent(hd, data, status); - free_urb(es1, urb); - /* - * Rest assured Greg, this craziness is getting fixed. - * - * Yes, you are right, we aren't telling anyone that the urb finished. - * "That's crazy! How does this all even work?" you might be saying. - * The "magic" is the idea that greybus works on the "operation" level, - * not the "send a buffer" level. All operations are "round-trip" with - * a response from the device that the operation finished, or it will - * time out. Because of that, we don't care that this urb finished, or - * failed, or did anything else, as higher levels of the protocol stack - * will handle completions and timeouts and the rest. - * - * This protocol is "needed" due to some hardware restrictions on the - * current generation of Unipro controllers. Think about it for a - * minute, this is a USB driver, talking to a Unipro bridge, impedance - * mismatch is huge, yet the Unipro controller are even more - * underpowered than this little USB controller. We rely on the round - * trip to keep stalls in the Unipro controllers from happening so that - * we can keep data flowing properly, no matter how slow it might be. - * - * Once again, a wonderful bus protocol cut down in its prime by a naive - * controller chip. We dream of the day we have a "real" HCD for - * Unipro. Until then, we suck it up and make the hardware work, as - * that's the job of the firmware and kernel. - * - */ } static void apb1_log_get(struct es1_ap_dev *es1) diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 23e2778..a6c47a3 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -451,34 +451,7 @@ static void cport_out_callback(struct urb *urb) */ data = urb->transfer_buffer + 1; greybus_data_sent(hd, data, status); - free_urb(es1, urb); - /* - * Rest assured Greg, this craziness is getting fixed. - * - * Yes, you are right, we aren't telling anyone that the urb finished. - * "That's crazy! How does this all even work?" you might be saying. - * The "magic" is the idea that greybus works on the "operation" level, - * not the "send a buffer" level. All operations are "round-trip" with - * a response from the device that the operation finished, or it will - * time out. Because of that, we don't care that this urb finished, or - * failed, or did anything else, as higher levels of the protocol stack - * will handle completions and timeouts and the rest. - * - * This protocol is "needed" due to some hardware restrictions on the - * current generation of Unipro controllers. Think about it for a - * minute, this is a USB driver, talking to a Unipro bridge, impedance - * mismatch is huge, yet the Unipro controller are even more - * underpowered than this little USB controller. We rely on the round - * trip to keep stalls in the Unipro controllers from happening so that - * we can keep data flowing properly, no matter how slow it might be. - * - * Once again, a wonderful bus protocol cut down in its prime by a naive - * controller chip. We dream of the day we have a "real" HCD for - * Unipro. Until then, we suck it up and make the hardware work, as - * that's the job of the firmware and kernel. - * - */ } static void apb1_log_get(struct es1_ap_dev *es1) -- cgit v0.10.2 From 6023629d3676a07e88a4661fca503e3e48d95299 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 4 Apr 2015 10:54:25 +0200 Subject: greybus: Documentation/sysfs: add a proposed sysfs tree for greybus This adds a proposed sysfs layout for greybus to Documentation to make it easier for people to discuss / test things. It includes a module, an interface, a bundle, and a gpbridge binding to that bundle. This was discussed on the projectara software mailing list. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/01/gpbridge00/gpio/.gitignore b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/01/gpbridge00/gpio/.gitignore new file mode 100644 index 0000000..f935021 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/01/gpbridge00/gpio/.gitignore @@ -0,0 +1 @@ +!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/01/gpbridge00/i2c/.gitignore b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/01/gpbridge00/i2c/.gitignore new file mode 100644 index 0000000..f935021 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/01/gpbridge00/i2c/.gitignore @@ -0,0 +1 @@ +!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/01/gpbridge00/usb/.gitignore b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/01/gpbridge00/usb/.gitignore new file mode 100644 index 0000000..f935021 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/01/gpbridge00/usb/.gitignore @@ -0,0 +1 @@ +!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/firmware b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/firmware new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/manifest b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/manifest new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/product_id b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/product_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/product_name b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/product_name new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/state b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/state new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/uid b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/uid new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/vendor_id b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/vendor_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/vendor_name b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/vendor_name new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/version_major b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/version_major new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/version_minor b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/version_minor new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/epm b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/epm new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/power b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/power new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/present b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/present new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/02/.gitignore b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/02/.gitignore new file mode 100644 index 0000000..f935021 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/02/.gitignore @@ -0,0 +1 @@ +!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/SVC/firmware b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/SVC/firmware new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/SVC/serial_number b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/SVC/serial_number new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/SVC/version b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/SVC/version new file mode 100644 index 0000000..e69de29 -- cgit v0.10.2 From 045235f118917210ab9574c768b2625231e2069b Mon Sep 17 00:00:00 2001 From: Mark Greer Date: Tue, 31 Mar 2015 16:49:56 -0700 Subject: greybus: Initial I2S definitions These are definitions from Mark that I've consolidated into one header file. I'd like to get these merged at some point soon, so the audio driver and gbsim work can avoid having out-of-tree dependencies. Signed-off-by: Mark A. Greer Reviewed-by: Alex Elder Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 4b2cf92..9ab1c82 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -35,7 +35,7 @@ enum greybus_protocol { GREYBUS_PROTOCOL_SDIO = 0x07, GREYBUS_PROTOCOL_BATTERY = 0x08, GREYBUS_PROTOCOL_PWM = 0x09, - GREYBUS_PROTOCOL_I2S = 0x0a, + GREYBUS_PROTOCOL_I2S_MGMT = 0x0a, GREYBUS_PROTOCOL_SPI = 0x0b, GREYBUS_PROTOCOL_DISPLAY = 0x0c, GREYBUS_PROTOCOL_CAMERA = 0x0d, @@ -43,6 +43,8 @@ enum greybus_protocol { GREYBUS_PROTOCOL_LED = 0x0f, GREYBUS_PROTOCOL_VIBRATOR = 0x10, GREYBUS_PROTOCOL_LOOPBACK = 0x11, + GREYBUS_PROTOCOL_I2S_RECEIVER = 0x12, + GREYBUS_PROTOCOL_I2S_TRANSMITTER = 0x13, /* ... */ GREYBUS_PROTOCOL_VENDOR = 0xff, }; diff --git a/drivers/staging/greybus/i2s.h b/drivers/staging/greybus/i2s.h new file mode 100644 index 0000000..5c42756 --- /dev/null +++ b/drivers/staging/greybus/i2s.h @@ -0,0 +1,145 @@ +#ifndef __GB_I2S_H__ +#define __GB_I2S_H__ + +#ifndef BIT +#define BIT(n) (1UL << (n)) +#endif + +#define GB_I2S_MGMT_TYPE_PROTOCOL_VERSION 0x01 +#define GB_I2S_MGMT_TYPE_GET_SUPPORTED_CONFIGURATIONS 0x02 +#define GB_I2S_MGMT_TYPE_SET_CONFIGURATION 0x03 +#define GB_I2S_MGMT_TYPE_SET_SAMPLES_PER_MESSAGE 0x04 +#define GB_I2S_MGMT_TYPE_GET_PROCESSING_DELAY 0x05 +#define GB_I2S_MGMT_TYPE_SET_START_DELAY 0x06 +#define GB_I2S_MGMT_TYPE_ACTIVATE_CPORT 0x07 +#define GB_I2S_MGMT_TYPE_DEACTIVATE_CPORT 0x08 +#define GB_I2S_MGMT_TYPE_REPORT_EVENT 0x09 + +#define GB_I2S_MGMT_BYTE_ORDER_NA BIT(0) +#define GB_I2S_MGMT_BYTE_ORDER_BE BIT(1) +#define GB_I2S_MGMT_BYTE_ORDER_LE BIT(2) + +#define GB_I2S_MGMT_SPATIAL_LOCATION_FL BIT(0) +#define GB_I2S_MGMT_SPATIAL_LOCATION_FR BIT(1) +#define GB_I2S_MGMT_SPATIAL_LOCATION_FC BIT(2) +#define GB_I2S_MGMT_SPATIAL_LOCATION_LFE BIT(3) +#define GB_I2S_MGMT_SPATIAL_LOCATION_BL BIT(4) +#define GB_I2S_MGMT_SPATIAL_LOCATION_BR BIT(5) +#define GB_I2S_MGMT_SPATIAL_LOCATION_FLC BIT(6) +#define GB_I2S_MGMT_SPATIAL_LOCATION_FRC BIT(7) +#define GB_I2S_MGMT_SPATIAL_LOCATION_C BIT(8) /* BC in USB */ +#define GB_I2S_MGMT_SPATIAL_LOCATION_SL BIT(9) +#define GB_I2S_MGMT_SPATIAL_LOCATION_SR BIT(10) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TC BIT(11) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TFL BIT(12) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TFC BIT(13) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TFR BIT(14) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TBL BIT(15) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TBC BIT(16) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TBR BIT(17) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TFLC BIT(18) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TFRC BIT(19) +#define GB_I2S_MGMT_SPATIAL_LOCATION_LLFE BIT(20) +#define GB_I2S_MGMT_SPATIAL_LOCATION_RLFE BIT(21) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TSL BIT(22) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TSR BIT(23) +#define GB_I2S_MGMT_SPATIAL_LOCATION_BC BIT(24) +#define GB_I2S_MGMT_SPATIAL_LOCATION_BLC BIT(25) +#define GB_I2S_MGMT_SPATIAL_LOCATION_BRC BIT(26) +#define GB_I2S_MGMT_SPATIAL_LOCATION_RD BIT(31) + +#define GB_I2S_MGMT_PROTOCOL_PCM BIT(0) +#define GB_I2S_MGMT_PROTOCOL_I2S BIT(1) +#define GB_I2S_MGMT_PROTOCOL_LR_STEREO BIT(2) + +#define GB_I2S_MGMT_ROLE_MASTER BIT(0) +#define GB_I2S_MGMT_ROLE_SLAVE BIT(1) + +#define GB_I2S_MGMT_POLARITY_NORMAL BIT(0) +#define GB_I2S_MGMT_POLARITY_REVERSED BIT(1) + +#define GB_I2S_MGMT_EDGE_RISING BIT(0) +#define GB_I2S_MGMT_EDGE_FALLING BIT(1) + +#define GB_I2S_MGMT_EVENT_UNSPECIFIED 0x1 +#define GB_I2S_MGMT_EVENT_HALT 0x2 +#define GB_I2S_MGMT_EVENT_INTERNAL_ERROR 0x3 +#define GB_I2S_MGMT_EVENT_PROTOCOL_ERROR 0x4 +#define GB_I2S_MGMT_EVENT_FAILURE 0x5 +#define GB_I2S_MGMT_EVENT_OUT_OF_SEQUENCE 0x6 +#define GB_I2S_MGMT_EVENT_UNDERRUN 0x7 +#define GB_I2S_MGMT_EVENT_OVERRUN 0x8 +#define GB_I2S_MGMT_EVENT_CLOCKING 0x9 +#define GB_I2S_MGMT_EVENT_DATA_LEN 0xa + +struct gb_i2s_mgmt_configuration { + __le32 sample_frequency; + __u8 num_channels; + __u8 bytes_per_channel; + __u8 byte_order; + __u8 pad; + __le32 spatial_locations; + __le32 ll_protocol; + __u8 ll_bclk_role; + __u8 ll_wclk_role; + __u8 ll_wclk_polarity; + __u8 ll_wclk_change_edge; + __u8 ll_wclk_tx_edge; + __u8 ll_wclk_rx_edge; + __u8 ll_data_offset; + __u8 ll_pad; +}; + +/* get supported configurations request has no payload */ +struct gb_i2s_mgmt_get_supported_configurations_response { + __u8 config_count; + __u8 pad[3]; + struct gb_i2s_mgmt_configuration config[0]; +}; + +struct gb_i2s_mgmt_set_configuration_request { + struct gb_i2s_mgmt_configuration config; +}; +/* set configuration response has no payload */ + +struct gb_i2s_mgmt_set_samples_per_message_request { + __le16 samples_per_message; +}; +/* set samples per message response has no payload */ + +/* get processing request delay has no payload */ +struct gb_i2s_mgmt_get_processing_delay_response { + __le32 microseconds; +}; + +struct gb_i2s_mgmt_set_start_delay_request { + __le32 microseconds; +}; +/* set start delay response has no payload */ + +struct gb_i2s_mgmt_activate_cport_request { + __le16 cport; +}; +/* activate cport response has no payload */ + +struct gb_i2s_mgmt_deactivate_cport_request { + __le16 cport; +}; +/* deactivate cport response has no payload */ + +struct gb_i2s_mgmt_report_event_request { + __u8 event; +}; +/* report event response has no payload */ + +#define GB_I2S_DATA_TYPE_PROTOCOL_VERSION 0x01 +#define GB_I2S_DATA_TYPE_SEND_DATA 0x02 + +struct gb_i2s_send_data_request { + __le32 sample_number; + __le32 size; + __u8 data[0]; +}; +/* send data has no response at all */ + +#endif /* __GB_I2S_H__ */ -- cgit v0.10.2 From 2352a73212a503dfe77970c48a891c008b7edd5b Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 2 Apr 2015 17:53:47 +0530 Subject: greybus: Unregister devices to get them freed Devices registered with the device-core needs to be freed by calling device_unregister(). For module we are calling just put_device() and for bundle, connection and interface we are calling device_del(). All of these are incomplete and so none of them get freed, i.e. the .release() routine is never called for their devices. Module being a special case that it needs to maintain a refcount or a list of interfaces to trace its usage count. I have chosen refcount. And so once the refcount is zero, we can Unregister the device and module will get free as well. Because of this bug in freeing devices, their sysfs directories were not getting removed properly and after a manifest is parsed with the help of gbsim, removing modules was creating problems. The sysfs directory 'greybus' wasn't getting removed. And inserting the modules again resulted in warnings and insmod failure. WARNING: CPU: 3 PID: 4277 at /build/buildd/linux-3.13.0/fs/sysfs/dir.c:486 sysfs_warn_dup+0x86/0xa0() Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 93f80dc..5ced992 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -140,7 +140,7 @@ void gb_bundle_destroy(struct gb_interface *intf) list_for_each_entry_safe(bundle, temp, &list, links) { list_del(&bundle->links); gb_bundle_connections_exit(bundle); - device_del(&bundle->dev); + device_unregister(&bundle->dev); } } diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 102e1a4..5ec161b 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -252,7 +252,7 @@ void gb_connection_destroy(struct gb_connection *connection) gb_connection_hd_cport_id_free(connection); gb_protocol_put(connection->protocol); - device_del(&connection->dev); + device_unregister(&connection->dev); } int gb_connection_init(struct gb_connection *connection) diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index b687908..122281f 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -173,6 +173,8 @@ put_module: */ static void gb_interface_destroy(struct gb_interface *intf) { + struct gb_module *module; + if (WARN_ON(!intf)) return; @@ -184,10 +186,11 @@ static void gb_interface_destroy(struct gb_interface *intf) kfree(intf->product_string); kfree(intf->vendor_string); - put_device(&intf->module->dev); /* kref_put(module->hd); */ - device_del(&intf->dev); + module = intf->module; + device_unregister(&intf->dev); + gb_module_remove(module); } /** diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index 56a55fe..538182b 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -101,6 +101,7 @@ static struct gb_module *gb_module_create(struct greybus_host_device *hd, return NULL; module->module_id = module_id; + module->refcount = 1; module->dev.parent = hd->parent; module->dev.bus = &greybus_bus_type; module->dev.type = &greybus_module_type; @@ -127,9 +128,20 @@ struct gb_module *gb_module_find_or_create(struct greybus_host_device *hd, struct gb_module *module; module = gb_module_find(module_id); - if (module) + if (module) { + module->refcount++; return module; + } return gb_module_create(hd, module_id); } +void gb_module_remove(struct gb_module *module) +{ + if (!module) + return; + + if (!--module->refcount) + device_unregister(&module->dev); +} + diff --git a/drivers/staging/greybus/module.h b/drivers/staging/greybus/module.h index 75a8818..4f02e46 100644 --- a/drivers/staging/greybus/module.h +++ b/drivers/staging/greybus/module.h @@ -13,6 +13,7 @@ struct gb_module { struct device dev; u8 module_id; /* Physical location within the Endo */ + u16 refcount; }; #define to_gb_module(d) container_of(d, struct gb_module, dev) @@ -21,6 +22,7 @@ struct greybus_host_device; /* Greybus "private" definitions */ struct gb_module *gb_module_find_or_create(struct greybus_host_device *hd, u8 module_id); +void gb_module_remove(struct gb_module *module); #endif /* __MODULE_H */ -- cgit v0.10.2 From c9d9d0d443afab6c4c1ce295c283f0caab56db16 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 1 Apr 2015 20:31:58 +0530 Subject: greybus: interface: Fetch interface id instead of module id during setup There can be more than one interface on a module and we need to know the interface for which the event has occurred. But at the same time we may not need the module id at all. During initial phase when AP is probed, the AP will receive the unique Endo id which shall be enough to draw relationships between interface and module ids. Code for that isn't available today and so lets create another routine to get module id (which needs to be fixed separately), which will simply return interface id passed to it. Now that we have interface id, update rest of the code to use it. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index ea197ac..132ecb4 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -140,10 +140,10 @@ static void svc_management(struct svc_function_unipro_management *management, hd->device_id = management->ap_id.device_id; break; case SVC_MANAGEMENT_LINK_UP: - intf = gb_interface_find(hd, management->link_up.module_id); + intf = gb_interface_find(hd, management->link_up.interface_id); if (!intf) { - dev_err(hd->parent, "Module ID %d not found\n", - management->link_up.module_id); + dev_err(hd->parent, "Interface ID %d not found\n", + management->link_up.interface_id); return; } ret = gb_bundle_init(intf, @@ -151,9 +151,8 @@ static void svc_management(struct svc_function_unipro_management *management, management->link_up.device_id); if (ret) { dev_err(hd->parent, - "error %d initializing interface %hhu bundle %hhu\n", - ret, management->link_up.module_id, - management->link_up.interface_id); + "error %d initializing bundles for interface %hhu\n", + ret, management->link_up.interface_id); return; } break; @@ -165,11 +164,11 @@ static void svc_management(struct svc_function_unipro_management *management, static void svc_hotplug(struct svc_function_hotplug *hotplug, int payload_length, struct greybus_host_device *hd) { - u8 module_id = hotplug->module_id; + u8 interface_id = hotplug->interface_id; switch (hotplug->hotplug_event) { case SVC_HOTPLUG_EVENT: - /* Add a new module to the system */ + /* Add a new interface to the system */ if (payload_length < 0x03) { /* Hotplug message is at least 3 bytes big */ dev_err(hd->parent, @@ -177,13 +176,13 @@ static void svc_hotplug(struct svc_function_hotplug *hotplug, payload_length); return; } - dev_dbg(hd->parent, "module id %d added\n", module_id); - gb_add_interface(hd, module_id, hotplug->data, + dev_dbg(hd->parent, "interface id %d added\n", interface_id); + gb_add_interface(hd, interface_id, hotplug->data, payload_length - 0x02); break; case SVC_HOTUNPLUG_EVENT: - /* Remove a module from the system */ + /* Remove a interface from the system */ if (payload_length != 0x02) { /* Hotunplug message is only 2 bytes big */ dev_err(hd->parent, @@ -191,8 +190,8 @@ static void svc_hotplug(struct svc_function_hotplug *hotplug, payload_length); return; } - dev_dbg(hd->parent, "module id %d removed\n", module_id); - gb_remove_interface(hd, module_id); + dev_dbg(hd->parent, "interface id %d removed\n", interface_id); + gb_remove_interface(hd, interface_id); break; default: @@ -206,7 +205,7 @@ static void svc_hotplug(struct svc_function_hotplug *hotplug, static void svc_power(struct svc_function_power *power, int payload_length, struct greybus_host_device *hd) { - u8 module_id = power->module_id; + u8 interface_id = power->interface_id; /* * The AP is only allowed to get a Battery Status message, not a Battery @@ -230,8 +229,8 @@ static void svc_power(struct svc_function_power *power, return; } - dev_dbg(hd->parent, "power status for module id %d is %d\n", - module_id, power->status.status); + dev_dbg(hd->parent, "power status for interface id %d is %d\n", + interface_id, power->status.status); // FIXME - do something with the power information, like update our // battery information... diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 122281f..5c64bc7 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -77,12 +77,12 @@ gb_interface_match_id(struct gb_interface *intf, // FIXME, odds are you don't want to call this function, rework the caller to // not need it please. struct gb_interface *gb_interface_find(struct greybus_host_device *hd, - u8 module_id) + u8 interface_id) { struct gb_interface *intf; list_for_each_entry(intf, &hd->interfaces, links) - if (intf->module->module_id == module_id) + if (intf->interface_id == interface_id) return intf; return NULL; @@ -105,28 +105,28 @@ struct device_type greybus_interface_type = { * phone. An interface is the physical connection on that module. A * module may have more than one interface. * - * Create a gb_interface structure to represent a discovered module. - * The position within the Endo is encoded in the "module_id" argument. + * Create a gb_interface structure to represent a discovered interface. + * The position of interface within the Endo is encoded in "interface_id" + * argument. + * * Returns a pointer to the new interfce or a null pointer if a * failure occurs due to memory exhaustion. */ static struct gb_interface *gb_interface_create(struct greybus_host_device *hd, - u8 module_id) + u8 interface_id) { struct gb_module *module; struct gb_interface *intf; int retval; - u8 interface_id = module_id; - // FIXME we need an interface id here to check for this properly! intf = gb_interface_find(hd, interface_id); if (intf) { - dev_err(hd->parent, "Duplicate module id %d will not be created\n", - module_id); + dev_err(hd->parent, "Duplicate interface with interface-id: %d will not be created\n", + interface_id); return NULL; } - module = gb_module_find_or_create(hd, module_id); + module = gb_module_find_or_create(hd, get_module_id(interface_id)); if (!module) return NULL; @@ -136,6 +136,7 @@ static struct gb_interface *gb_interface_create(struct greybus_host_device *hd, intf->hd = hd; /* XXX refcount? */ intf->module = module; + intf->interface_id = interface_id; INIT_LIST_HEAD(&intf->bundles); INIT_LIST_HEAD(&intf->manifest_descs); @@ -149,8 +150,8 @@ static struct gb_interface *gb_interface_create(struct greybus_host_device *hd, retval = device_add(&intf->dev); if (retval) { - pr_err("failed to add module device for id 0x%02hhx\n", - module_id); + pr_err("failed to add interface device for id 0x%02hhx\n", + interface_id); goto free_intf; } @@ -199,12 +200,12 @@ static void gb_interface_destroy(struct gb_interface *intf) * Pass in a buffer that _should_ contain a Greybus module manifest * and register a greybus device structure with the kernel core. */ -void gb_add_interface(struct greybus_host_device *hd, u8 module_id, - u8 *data, int size) +void gb_add_interface(struct greybus_host_device *hd, u8 interface_id, u8 *data, + int size) { struct gb_interface *intf; - intf = gb_interface_create(hd, module_id); + intf = gb_interface_create(hd, interface_id); if (!intf) { dev_err(hd->parent, "failed to create interface\n"); return; @@ -234,14 +235,15 @@ err_parse: gb_interface_destroy(intf); } -void gb_remove_interface(struct greybus_host_device *hd, u8 module_id) +void gb_remove_interface(struct greybus_host_device *hd, u8 interface_id) { - struct gb_interface *intf = gb_interface_find(hd, module_id); + struct gb_interface *intf = gb_interface_find(hd, interface_id); if (intf) gb_interface_destroy(intf); else - dev_err(hd->parent, "interface id %d not found\n", module_id); + dev_err(hd->parent, "interface id %d not found\n", + interface_id); } void gb_remove_interfaces(struct greybus_host_device *hd) diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index f444e31..45ce996 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -49,11 +49,11 @@ const struct greybus_interface_id * const struct greybus_interface_id *id); struct gb_interface *gb_interface_find(struct greybus_host_device *hd, - u8 module_id); + u8 interface_id); -void gb_add_interface(struct greybus_host_device *hd, u8 module_id, - u8 *data, int size); -void gb_remove_interface(struct greybus_host_device *hd, u8 module_id); +void gb_add_interface(struct greybus_host_device *hd, u8 interface_id, u8 *data, + int size); +void gb_remove_interface(struct greybus_host_device *hd, u8 interface_id); void gb_remove_interfaces(struct greybus_host_device *hd); diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index 538182b..e8c1c07 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -58,6 +58,17 @@ struct device_type greybus_module_type = { .release = greybus_module_release, }; +u8 get_module_id(u8 interface_id) +{ + /* + * FIXME: + * + * We should be able to find it from Endo ID passed during greybus + * control operation, while setting up AP. + */ + return interface_id; +} + static int module_find(struct device *dev, void *data) { struct gb_module *module; diff --git a/drivers/staging/greybus/module.h b/drivers/staging/greybus/module.h index 4f02e46..f3e3bdd 100644 --- a/drivers/staging/greybus/module.h +++ b/drivers/staging/greybus/module.h @@ -24,5 +24,6 @@ struct gb_module *gb_module_find_or_create(struct greybus_host_device *hd, u8 module_id); void gb_module_remove(struct gb_module *module); +u8 get_module_id(u8 interface_id); #endif /* __MODULE_H */ diff --git a/drivers/staging/greybus/svc_msg.h b/drivers/staging/greybus/svc_msg.h index 471baa5..cb7bb19 100644 --- a/drivers/staging/greybus/svc_msg.h +++ b/drivers/staging/greybus/svc_msg.h @@ -52,13 +52,12 @@ struct svc_function_unipro_set_route { }; struct svc_function_unipro_link_up { - __u8 module_id; - __u8 interface_id; + __u8 interface_id; /* Interface id within the Endo */ __u8 device_id; }; struct svc_function_ap_id { - __u8 module_id; + __u8 interface_id; __u8 device_id; }; @@ -82,13 +81,9 @@ enum svc_function_hotplug_event { SVC_HOTUNPLUG_EVENT = 0x01, }; -/* XXX - * Does a hotplug come from module insertion, or from detection of each - * interface (UniPro device) in a module? Assume the former for now. - */ struct svc_function_hotplug { __u8 hotplug_event; /* enum svc_function_hotplug_event */ - __u8 module_id; + __u8 interface_id; /* Interface id within the Endo */ __u8 data[0]; }; @@ -121,7 +116,7 @@ struct svc_function_power_battery_status_request { */ struct svc_function_power { __u8 power_type; /* enum svc_function_power_type */ - __u8 module_id; + __u8 interface_id; union { struct svc_function_power_battery_status status; struct svc_function_power_battery_status_request request; -- cgit v0.10.2 From 83a0cb593b5517a13f88c8f9ae9ce7e43af4b54b Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 1 Apr 2015 20:31:59 +0530 Subject: greybus: Add bundle descriptor type A bundle corresponds to a device and a greybus driver binds to it. This patch adds a type and descriptor for bundle. This also shuffles the values of 'enum greybus_descriptor_type' to align them with Greybus Specifications. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 9ab1c82..96702f4 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -17,11 +17,12 @@ enum greybus_descriptor_type { GREYBUS_TYPE_INVALID = 0x00, - GREYBUS_TYPE_MODULE = 0x01, + GREYBUS_TYPE_INTERFACE = 0x01, GREYBUS_TYPE_STRING = 0x02, - GREYBUS_TYPE_INTERFACE = 0x03, + GREYBUS_TYPE_BUNDLE = 0x03, GREYBUS_TYPE_CPORT = 0x04, GREYBUS_TYPE_CLASS = 0x05, + GREYBUS_TYPE_MODULE = 0x06, }; enum greybus_protocol { @@ -109,6 +110,30 @@ struct greybus_descriptor_interface { }; /* + * An bundle descriptor defines an identification number and a class type for + * each bundle. + * + * @id: Uniquely identifies a bundle within a interface, its sole purpose is to + * allow CPort descriptors to specify which bundle they are associated with. + * The first bundle will have id 0, second will have 1 and so on. + * + * The largest CPort id associated with an bundle (defined by a + * CPort descriptor in the manifest) is used to determine how to + * encode the device id and module number in UniPro packets + * that use the bundle. + * + * @class_type: It is used by kernel to know the functionality provided by the + * bundle and will be matched against drivers functinality while probing greybus + * driver. It should contain one of the values defined in + * 'enum greybus_class_type'. + * + */ +struct greybus_descriptor_bundle { + __u8 id; /* interface-relative id (0..) */ + __u8 class_type; +}; + +/* * A CPort descriptor indicates the id of the bundle within the * module it's associated with, along with the CPort id used to * address the CPort. The protocol id defines the format of messages @@ -139,6 +164,7 @@ struct greybus_descriptor { struct greybus_descriptor_module module; struct greybus_descriptor_string string; struct greybus_descriptor_interface interface; + struct greybus_descriptor_bundle bundle; struct greybus_descriptor_cport cport; struct greybus_descriptor_class class; }; diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index c29a0c8..c00e378 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -26,6 +26,8 @@ static const char *get_descriptor_type_string(u8 type) return "interface"; case GREYBUS_TYPE_CPORT: return "cport"; + case GREYBUS_TYPE_BUNDLE: + return "bundle"; case GREYBUS_TYPE_CLASS: return "class"; default: -- cgit v0.10.2 From 581baacd33b087e4f7322f42ca8f336f7f0acc4d Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 3 Apr 2015 12:00:48 +0530 Subject: greybus: hid: Use payload-size to get report size Report size isn't passed as first two bytes of the report according to USB-HID spec. Get it from payload-size. Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index 5935aa6..556cf9b 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -155,7 +155,6 @@ static int gb_hid_irq_handler(u8 type, struct gb_operation *op) struct gb_connection *connection = op->connection; struct gb_hid *ghid = connection->private; struct gb_hid_input_report_request *request = op->request->payload; - int size; if (type != GB_HID_TYPE_IRQ_EVENT) { dev_err(&connection->dev, @@ -163,24 +162,9 @@ static int gb_hid_irq_handler(u8 type, struct gb_operation *op) return -EINVAL; } - if (op->request->payload_size < 2) { - dev_err(&connection->dev, "short report received\n"); - return -EINVAL; - } - - /* - * FIXME: add report size to Greybus HID protocol if we need to parse - * it here. - */ - size = request->report[0] | request->report[1] << 8; - if (size < 2 || size > op->request->payload_size - 2) { - dev_err(&connection->dev, "bad report size: %d\n", size); - return -EINVAL; - } - if (test_bit(GB_HID_STARTED, &ghid->flags)) hid_input_report(ghid->hid, HID_INPUT_REPORT, - request->report + 2, size - 2, 1); + request->report, op->request->payload_size, 1); return 0; } -- cgit v0.10.2 From 7c183f70ed5b1fa368559031b1ef2245827f2918 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 1 Apr 2015 20:32:00 +0530 Subject: greybus: bundle: Create bundles using bundle descriptors Currently we are creating bundles based on interface descriptors. An interface can have one or more bundles associated with it and so a bundle must be created based on a bundle descriptor. Also get class_type from bundle descriptor. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 5ced992..47a3413 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -80,7 +80,8 @@ void gb_bundle_bind_protocols(void) * bundle. Returns a pointer to the new bundle or a null * pointer if a failure occurs due to memory exhaustion. */ -struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 interface_id) +struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, + u8 class_type) { struct gb_bundle *bundle; int retval; @@ -90,7 +91,8 @@ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 interface_id) return NULL; bundle->intf = intf; - bundle->id = interface_id; + bundle->id = bundle_id; + bundle->class_type = class_type; INIT_LIST_HEAD(&bundle->connections); /* Invalid device id to start with */ @@ -103,12 +105,12 @@ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 interface_id) bundle->dev.type = &greybus_bundle_type; bundle->dev.groups = bundle_groups; device_initialize(&bundle->dev); - dev_set_name(&bundle->dev, "%s:%d", dev_name(&intf->dev), interface_id); + dev_set_name(&bundle->dev, "%s:%d", dev_name(&intf->dev), bundle_id); retval = device_add(&bundle->dev); if (retval) { pr_err("failed to add bundle device for id 0x%02hhx\n", - interface_id); + bundle_id); put_device(&bundle->dev); kfree(bundle); return NULL; diff --git a/drivers/staging/greybus/bundle.h b/drivers/staging/greybus/bundle.h index 62969cf..385c90a 100644 --- a/drivers/staging/greybus/bundle.h +++ b/drivers/staging/greybus/bundle.h @@ -17,6 +17,7 @@ struct gb_bundle { struct device dev; struct gb_interface *intf; u8 id; + u8 class_type; u8 device_id; struct list_head connections; @@ -27,7 +28,8 @@ struct gb_bundle { #define GB_DEVICE_ID_BAD 0xff /* Greybus "private" definitions" */ -struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 module_id); +struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, + u8 class_type); void gb_bundle_destroy(struct gb_interface *intf); int gb_bundle_init(struct gb_interface *intf, u8 module_id, u8 device_id); diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index c00e378..8541a2a 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -108,6 +108,9 @@ static int identify_descriptor(struct gb_interface *intf, break; case GREYBUS_TYPE_INTERFACE: break; + case GREYBUS_TYPE_BUNDLE: + expected_size += sizeof(struct greybus_descriptor_bundle); + break; case GREYBUS_TYPE_CPORT: expected_size += sizeof(struct greybus_descriptor_cport); break; @@ -237,7 +240,7 @@ static u32 gb_manifest_parse_cports(struct gb_interface *intf, /* * Find bundle descriptors in the manifest and set up their data * structures. Returns the number of bundles set up for the - * given module. + * given interface. */ static u32 gb_manifest_parse_bundles(struct gb_interface *intf) { @@ -245,13 +248,13 @@ static u32 gb_manifest_parse_bundles(struct gb_interface *intf) while (true) { struct manifest_desc *descriptor; - struct greybus_descriptor_interface *desc_interface; + struct greybus_descriptor_bundle *desc_bundle; struct gb_bundle *bundle; bool found = false; /* Find an bundle descriptor */ list_for_each_entry(descriptor, &intf->manifest_descs, links) { - if (descriptor->type == GREYBUS_TYPE_INTERFACE) { + if (descriptor->type == GREYBUS_TYPE_BUNDLE) { found = true; break; } @@ -260,8 +263,9 @@ static u32 gb_manifest_parse_bundles(struct gb_interface *intf) break; /* Found one. Set up its bundle structure*/ - desc_interface = descriptor->data; - bundle = gb_bundle_create(intf, desc_interface->id); + desc_bundle = descriptor->data; + bundle = gb_bundle_create(intf, desc_bundle->id, + desc_bundle->class_type); if (!bundle) return 0; /* Error */ -- cgit v0.10.2 From bb97ea813b1c31a0fc78af3d06a8dbd793ea372b Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 1 Apr 2015 20:32:01 +0530 Subject: greybus: bundle: Initialize all bundles on link-up An interface can have 1 or more bundles. On link-up event, we must initialize all the bundles associated with the interface. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 132ecb4..1dc1339 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -146,9 +146,7 @@ static void svc_management(struct svc_function_unipro_management *management, management->link_up.interface_id); return; } - ret = gb_bundle_init(intf, - management->link_up.interface_id, - management->link_up.device_id); + ret = gb_bundles_init(intf, management->link_up.device_id); if (ret) { dev_err(hd->parent, "error %d initializing bundles for interface %hhu\n", diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 47a3413..9691978 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -146,16 +146,11 @@ void gb_bundle_destroy(struct gb_interface *intf) } } -int gb_bundle_init(struct gb_interface *intf, u8 bundle_id, u8 device_id) +int gb_bundle_init(struct gb_bundle *bundle, u8 device_id) { - struct gb_bundle *bundle; + struct gb_interface *intf = bundle->intf; int ret; - bundle = gb_bundle_find(intf, bundle_id); - if (!bundle) { - dev_err(intf->hd->parent, "bundle %hhu not found\n", bundle_id); - return -ENOENT; - } bundle->device_id = device_id; ret = svc_set_route_send(bundle, intf->hd); @@ -175,6 +170,24 @@ int gb_bundle_init(struct gb_interface *intf, u8 bundle_id, u8 device_id) return 0; } +int gb_bundles_init(struct gb_interface *intf, u8 device_id) +{ + struct gb_bundle *bundle; + int ret = 0; + + list_for_each_entry(bundle, &intf->bundles, links) { + ret = gb_bundle_init(bundle, device_id); + if (ret) { + dev_err(intf->hd->parent, + "Failed to initialize bundle %hhu\n", + bundle->id); + break; + } + } + + return ret; +} + struct gb_bundle *gb_bundle_find(struct gb_interface *intf, u8 bundle_id) { struct gb_bundle *bundle; diff --git a/drivers/staging/greybus/bundle.h b/drivers/staging/greybus/bundle.h index 385c90a..2948098 100644 --- a/drivers/staging/greybus/bundle.h +++ b/drivers/staging/greybus/bundle.h @@ -31,7 +31,8 @@ struct gb_bundle { struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, u8 class_type); void gb_bundle_destroy(struct gb_interface *intf); -int gb_bundle_init(struct gb_interface *intf, u8 module_id, u8 device_id); +int gb_bundle_init(struct gb_bundle *bundle, u8 device_id); +int gb_bundles_init(struct gb_interface *intf, u8 device_id); struct gb_bundle *gb_bundle_find(struct gb_interface *intf, u8 bundle_id); void gb_bundle_bind_protocols(void); -- cgit v0.10.2 From a93db2d1f6939bf260dbdf0d32a20eda3ad2e620 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 1 Apr 2015 20:32:02 +0530 Subject: greybus: manifest: Use interface descriptor instead of module descriptor to get information A module can have more than one interfaces and we get hotplug events or manifests for interfaces, not modules. Details like version, vendor, product id, etc. can be different for different interfaces within the same module and so shall be fetched from interface descriptor instead of module descriptor. So what we have been doing for module descriptors until now must be done for interface descriptors. There can only be one interface descriptor in the manifest. Module descriptor isn't used anymore and probably most of its fields can be removed now. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 96702f4..143e284 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -1,5 +1,5 @@ /* - * Greybus module manifest definition + * Greybus manifest definition * * See "Greybus Application Protocol" document (version 0.1) for * details on these values and structures. @@ -94,19 +94,16 @@ struct greybus_descriptor_string { }; /* - * An interface descriptor simply defines a module-unique id for - * each interface present on a module. Its sole purpose is to allow - * CPort descriptors to specify which interface they are associated - * with. Normally there's only one interface, with id 0. The - * second one must have id 1, and so on consecutively. - * - * The largest CPort id associated with an interface (defined by a - * CPort descriptor in the manifest) is used to determine how to - * encode the device id and module number in UniPro packets - * that use the interface. + * An interface descriptor describes information about an interface as a whole, + * *not* the functions within it. */ struct greybus_descriptor_interface { - __u8 id; /* module-relative id (0..) */ + __le16 vendor; + __le16 product; + __le16 version; // TODO - remove after Dec demo. + __u8 vendor_stringid; + __u8 product_stringid; + __le64 unique_id; }; /* diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 5c64bc7..4d5f190 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -197,7 +197,7 @@ static void gb_interface_destroy(struct gb_interface *intf) /** * gb_add_interface * - * Pass in a buffer that _should_ contain a Greybus module manifest + * Pass in a buffer that _should_ contain a Greybus manifest * and register a greybus device structure with the kernel core. */ void gb_add_interface(struct greybus_host_device *hd, u8 interface_id, u8 *data, diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 45ce996..147c311 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -19,7 +19,7 @@ struct gb_interface { struct list_head manifest_descs; u8 interface_id; /* Physical location within the Endo */ - /* Information taken from the manifest module descriptor */ + /* Information taken from the manifest descriptor */ u16 vendor; u16 product; char *vendor_string; diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 8541a2a..f3d3a2f 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -1,5 +1,5 @@ /* - * Greybus module manifest parsing + * Greybus manifest parsing * * Copyright 2014-2015 Google Inc. * Copyright 2014-2015 Linaro Ltd. @@ -40,7 +40,7 @@ static const char *get_descriptor_type_string(u8 type) * We scan the manifest once to identify where all the descriptors * are. The result is a list of these manifest_desc structures. We * then pick through them for what we're looking for (starting with - * the module descriptor). As each is processed we remove it from + * the interface descriptor). As each is processed we remove it from * the list. When we're done the list should (probably) be empty. */ struct manifest_desc { @@ -107,6 +107,7 @@ static int identify_descriptor(struct gb_interface *intf, expected_size += desc->string.length; break; case GREYBUS_TYPE_INTERFACE: + expected_size += sizeof(struct greybus_descriptor_interface); break; case GREYBUS_TYPE_BUNDLE: expected_size += sizeof(struct greybus_descriptor_bundle); @@ -282,28 +283,28 @@ static u32 gb_manifest_parse_bundles(struct gb_interface *intf) return count; } -static bool gb_manifest_parse_module(struct gb_interface *intf, - struct manifest_desc *module_desc) +static bool gb_manifest_parse_interface(struct gb_interface *intf, + struct manifest_desc *interface_desc) { - struct greybus_descriptor_module *desc_module = module_desc->data; + struct greybus_descriptor_interface *desc_intf = interface_desc->data; /* Handle the strings first--they can fail */ - intf->vendor_string = gb_string_get(intf, desc_module->vendor_stringid); + intf->vendor_string = gb_string_get(intf, desc_intf->vendor_stringid); if (IS_ERR(intf->vendor_string)) return false; intf->product_string = gb_string_get(intf, - desc_module->product_stringid); + desc_intf->product_stringid); if (IS_ERR(intf->product_string)) { goto out_free_vendor_string; } - intf->vendor = le16_to_cpu(desc_module->vendor); - intf->product = le16_to_cpu(desc_module->product); - intf->unique_id = le64_to_cpu(desc_module->unique_id); + intf->vendor = le16_to_cpu(desc_intf->vendor); + intf->product = le16_to_cpu(desc_intf->product); + intf->unique_id = le64_to_cpu(desc_intf->unique_id); - /* Release the module descriptor, now that we're done with it */ - release_manifest_descriptor(module_desc); + /* Release the interface descriptor, now that we're done with it */ + release_manifest_descriptor(interface_desc); /* An interface must have at least one bundle descriptor */ if (!gb_manifest_parse_bundles(intf)) { @@ -323,7 +324,7 @@ out_free_vendor_string: } /* - * Parse a buffer containing a module manifest. + * Parse a buffer containing a Interface manifest. * * If we find anything wrong with the content/format of the buffer * we reject it. @@ -335,7 +336,7 @@ out_free_vendor_string: * the descriptors it contains, keeping track for each its type * and the location size of its data in the buffer. * - * Next we scan the descriptors, looking for a module descriptor; + * Next we scan the descriptors, looking for a interface descriptor; * there must be exactly one of those. When found, we record the * information it contains, and then remove that descriptor (and any * string descriptors it refers to) from further consideration. @@ -351,7 +352,7 @@ bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size) struct greybus_manifest_header *header; struct greybus_descriptor *desc; struct manifest_desc *descriptor; - struct manifest_desc *module_desc = NULL; + struct manifest_desc *interface_desc = NULL; u16 manifest_size; u32 found = 0; bool result; @@ -399,28 +400,28 @@ bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size) size -= desc_size; } - /* There must be a single module descriptor */ + /* There must be a single interface descriptor */ list_for_each_entry(descriptor, &intf->manifest_descs, links) { - if (descriptor->type == GREYBUS_TYPE_MODULE) + if (descriptor->type == GREYBUS_TYPE_INTERFACE) if (!found++) - module_desc = descriptor; + interface_desc = descriptor; } if (found != 1) { - pr_err("manifest must have 1 module descriptor (%u found)\n", + pr_err("manifest must have 1 interface descriptor (%u found)\n", found); result = false; goto out; } - /* Parse the module manifest, starting with the module descriptor */ - result = gb_manifest_parse_module(intf, module_desc); + /* Parse the manifest, starting with the interface descriptor */ + result = gb_manifest_parse_interface(intf, interface_desc); /* * We really should have no remaining descriptors, but we * don't know what newer format manifests might leave. */ if (result && !list_empty(&intf->manifest_descs)) - pr_info("excess descriptors in module manifest\n"); + pr_info("excess descriptors in interface manifest\n"); out: release_manifest_descriptors(intf); diff --git a/drivers/staging/greybus/manifest.h b/drivers/staging/greybus/manifest.h index 90fb62d..d964284 100644 --- a/drivers/staging/greybus/manifest.h +++ b/drivers/staging/greybus/manifest.h @@ -1,5 +1,5 @@ /* - * Greybus module manifest parsing + * Greybus manifest parsing * * Copyright 2014 Google Inc. * Copyright 2014 Linaro Ltd. -- cgit v0.10.2 From 8e2e22d7830616ac37a9045e9e749e35cbc10ffe Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 1 Apr 2015 20:32:03 +0530 Subject: greybus: drop module descriptors Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 143e284..a338683 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -22,7 +22,6 @@ enum greybus_descriptor_type { GREYBUS_TYPE_BUNDLE = 0x03, GREYBUS_TYPE_CPORT = 0x04, GREYBUS_TYPE_CLASS = 0x05, - GREYBUS_TYPE_MODULE = 0x06, }; enum greybus_protocol { @@ -70,19 +69,6 @@ enum greybus_class_type { }; /* - * A module descriptor describes information about a module as a - * whole, *not* the functions within it. - */ -struct greybus_descriptor_module { - __le16 vendor; - __le16 product; - __le16 version; // TODO - remove after Dec demo. - __u8 vendor_stringid; - __u8 product_stringid; - __le64 unique_id; -}; - -/* * The string in a string descriptor is not NUL-terminated. The * size of the descriptor will be rounded up to a multiple of 4 * bytes, by padding the string with 0x00 bytes if necessary. @@ -158,7 +144,6 @@ struct greybus_descriptor_header { struct greybus_descriptor { struct greybus_descriptor_header header; union { - struct greybus_descriptor_module module; struct greybus_descriptor_string string; struct greybus_descriptor_interface interface; struct greybus_descriptor_bundle bundle; diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index f3d3a2f..12eee3a 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -18,8 +18,6 @@ static const char *get_descriptor_type_string(u8 type) switch(type) { case GREYBUS_TYPE_INVALID: return "invalid"; - case GREYBUS_TYPE_MODULE: - return "module"; case GREYBUS_TYPE_STRING: return "string"; case GREYBUS_TYPE_INTERFACE: @@ -99,9 +97,6 @@ static int identify_descriptor(struct gb_interface *intf, expected_size = sizeof(*desc_header); switch (desc_header->type) { - case GREYBUS_TYPE_MODULE: - expected_size += sizeof(struct greybus_descriptor_module); - break; case GREYBUS_TYPE_STRING: expected_size += sizeof(struct greybus_descriptor_string); expected_size += desc->string.length; -- cgit v0.10.2 From 9f5f30e712430912f4cff65e97dd36f9b3bdbe4e Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 1 Apr 2015 20:32:04 +0530 Subject: greybus: driver corresponds to a bundle, not interface A Greybus driver will bind to a bundle, not an interface. Lets follow this rule in code. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 9691978..ce7db97 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -22,8 +22,18 @@ static ssize_t device_id_show(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR_RO(device_id); +static ssize_t class_type_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct gb_bundle *bundle = to_gb_bundle(dev); + + return sprintf(buf, "%d\n", bundle->class_type); +} +static DEVICE_ATTR_RO(class_type); + static struct attribute *bundle_attrs[] = { &dev_attr_device_id.attr, + &dev_attr_class_type.attr, NULL, }; @@ -41,6 +51,44 @@ struct device_type greybus_bundle_type = { .release = gb_bundle_release, }; +static int gb_bundle_match_one_id(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) +{ + if ((id->match_flags & GREYBUS_ID_MATCH_VENDOR) && + (id->vendor != bundle->intf->vendor)) + return 0; + + if ((id->match_flags & GREYBUS_ID_MATCH_PRODUCT) && + (id->product != bundle->intf->product)) + return 0; + + if ((id->match_flags & GREYBUS_ID_MATCH_SERIAL) && + (id->unique_id != bundle->intf->unique_id)) + return 0; + + if ((id->match_flags & GREYBUS_ID_MATCH_CLASS_TYPE) && + (id->class_type != bundle->class_type)) + return 0; + + return 1; +} + +const struct greybus_bundle_id * +gb_bundle_match_id(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) +{ + if (id == NULL) + return NULL; + + for (; id->vendor || id->product || id->unique_id || id->class_type || + id->driver_info; id++) { + if (gb_bundle_match_one_id(bundle, id)) + return id; + } + + return NULL; +} + /* XXX This could be per-host device or per-module */ static DEFINE_SPINLOCK(gb_bundles_lock); diff --git a/drivers/staging/greybus/bundle.h b/drivers/staging/greybus/bundle.h index 2948098..1fcf5b8 100644 --- a/drivers/staging/greybus/bundle.h +++ b/drivers/staging/greybus/bundle.h @@ -37,4 +37,8 @@ int gb_bundles_init(struct gb_interface *intf, u8 device_id); struct gb_bundle *gb_bundle_find(struct gb_interface *intf, u8 bundle_id); void gb_bundle_bind_protocols(void); +const struct greybus_bundle_id * + gb_bundle_match_id(struct gb_bundle *bundle, + const struct greybus_bundle_id *id); + #endif /* __BUNDLE_H */ diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 96265a1d..0ac2fb8 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -34,10 +34,10 @@ EXPORT_SYMBOL_GPL(greybus_disabled); static int greybus_module_match(struct device *dev, struct device_driver *drv) { struct greybus_driver *driver = to_greybus_driver(drv); - struct gb_interface *intf = to_gb_interface(dev); - const struct greybus_interface_id *id; + struct gb_bundle *bundle = to_gb_bundle(dev); + const struct greybus_bundle_id *id; - id = gb_interface_match_id(intf, driver->id_table); + id = gb_bundle_match_id(bundle, driver->id_table); if (id) return 1; /* FIXME - Dynamic ids? */ @@ -97,16 +97,16 @@ struct bus_type greybus_bus_type = { static int greybus_probe(struct device *dev) { struct greybus_driver *driver = to_greybus_driver(dev->driver); - struct gb_interface *intf = to_gb_interface(dev); - const struct greybus_interface_id *id; + struct gb_bundle *bundle = to_gb_bundle(dev); + const struct greybus_bundle_id *id; int retval; /* match id */ - id = gb_interface_match_id(intf, driver->id_table); + id = gb_bundle_match_id(bundle, driver->id_table); if (!id) return -ENODEV; - retval = driver->probe(intf, id); + retval = driver->probe(bundle, id); if (retval) return retval; @@ -116,9 +116,9 @@ static int greybus_probe(struct device *dev) static int greybus_remove(struct device *dev) { struct greybus_driver *driver = to_greybus_driver(dev->driver); - struct gb_interface *intf = to_gb_interface(dev); + struct gb_bundle *bundle = to_gb_bundle(dev); - driver->disconnect(intf); + driver->disconnect(bundle); return 0; } diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 5a7f622..a466fc5 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -120,14 +120,14 @@ void greybus_remove_hd(struct greybus_host_device *hd); struct greybus_driver { const char *name; - int (*probe)(struct gb_interface *intf, - const struct greybus_interface_id *id); - void (*disconnect)(struct gb_interface *intf); + int (*probe)(struct gb_bundle *bundle, + const struct greybus_bundle_id *id); + void (*disconnect)(struct gb_bundle *bundle); - int (*suspend)(struct gb_interface *intf, pm_message_t message); - int (*resume)(struct gb_interface *intf); + int (*suspend)(struct gb_bundle *bundle, pm_message_t message); + int (*resume)(struct gb_bundle *bundle); - const struct greybus_interface_id *id_table; + const struct greybus_bundle_id *id_table; struct device_driver driver; }; diff --git a/drivers/staging/greybus/greybus_id.h b/drivers/staging/greybus/greybus_id.h index 3c462ef..4204a8c 100644 --- a/drivers/staging/greybus/greybus_id.h +++ b/drivers/staging/greybus/greybus_id.h @@ -9,18 +9,20 @@ #include -struct greybus_interface_id { +struct greybus_bundle_id { __u16 match_flags; __u16 vendor; __u16 product; + __u8 class_type; __u64 unique_id; kernel_ulong_t driver_info __aligned(sizeof(kernel_ulong_t)); }; -/* Used to match the greybus_interface_id */ +/* Used to match the greybus_bundle_id */ #define GREYBUS_ID_MATCH_VENDOR BIT(0) #define GREYBUS_ID_MATCH_PRODUCT BIT(1) #define GREYBUS_ID_MATCH_SERIAL BIT(2) +#define GREYBUS_ID_MATCH_CLASS_TYPE BIT(3) #endif /* __LINUX_GREYBUS_ID_H */ diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 4d5f190..5b1d5dd 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -40,40 +40,6 @@ ATTRIBUTE_GROUPS(interface); /* XXX This could be per-host device */ static DEFINE_SPINLOCK(gb_interfaces_lock); -static int gb_interface_match_one_id(struct gb_interface *intf, - const struct greybus_interface_id *id) -{ - if ((id->match_flags & GREYBUS_ID_MATCH_VENDOR) && - (id->vendor != intf->vendor)) - return 0; - - if ((id->match_flags & GREYBUS_ID_MATCH_PRODUCT) && - (id->product != intf->product)) - return 0; - - if ((id->match_flags & GREYBUS_ID_MATCH_SERIAL) && - (id->unique_id != intf->unique_id)) - return 0; - - return 1; -} - -const struct greybus_interface_id * -gb_interface_match_id(struct gb_interface *intf, - const struct greybus_interface_id *id) -{ - if (id == NULL) - return NULL; - - for (; id->vendor || id->product || id->unique_id || - id->driver_info; id++) { - if (gb_interface_match_one_id(intf, id)) - return id; - } - - return NULL; -} - // FIXME, odds are you don't want to call this function, rework the caller to // not need it please. struct gb_interface *gb_interface_find(struct greybus_host_device *hd, diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 147c311..9ee5b55 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -44,10 +44,6 @@ static inline void *gb_interface_get_drvdata(struct gb_interface *intf) /* Greybus "private" definitions */ -const struct greybus_interface_id * - gb_interface_match_id(struct gb_interface *intf, - const struct greybus_interface_id *id); - struct gb_interface *gb_interface_find(struct greybus_host_device *hd, u8 interface_id); -- cgit v0.10.2 From 88e6d37c448062b86211e89d23348d952fd166c0 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 6 Apr 2015 15:49:36 +0530 Subject: greybus: bundle: s/class_type/class Alex suggested to name it class instead of class type. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index ce7db97..3f1aa64 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -22,18 +22,18 @@ static ssize_t device_id_show(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR_RO(device_id); -static ssize_t class_type_show(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t class_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct gb_bundle *bundle = to_gb_bundle(dev); - return sprintf(buf, "%d\n", bundle->class_type); + return sprintf(buf, "%d\n", bundle->class); } -static DEVICE_ATTR_RO(class_type); +static DEVICE_ATTR_RO(class); static struct attribute *bundle_attrs[] = { &dev_attr_device_id.attr, - &dev_attr_class_type.attr, + &dev_attr_class.attr, NULL, }; @@ -66,8 +66,8 @@ static int gb_bundle_match_one_id(struct gb_bundle *bundle, (id->unique_id != bundle->intf->unique_id)) return 0; - if ((id->match_flags & GREYBUS_ID_MATCH_CLASS_TYPE) && - (id->class_type != bundle->class_type)) + if ((id->match_flags & GREYBUS_ID_MATCH_CLASS) && + (id->class != bundle->class)) return 0; return 1; @@ -80,7 +80,7 @@ gb_bundle_match_id(struct gb_bundle *bundle, if (id == NULL) return NULL; - for (; id->vendor || id->product || id->unique_id || id->class_type || + for (; id->vendor || id->product || id->unique_id || id->class || id->driver_info; id++) { if (gb_bundle_match_one_id(bundle, id)) return id; @@ -129,7 +129,7 @@ void gb_bundle_bind_protocols(void) * pointer if a failure occurs due to memory exhaustion. */ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, - u8 class_type) + u8 class) { struct gb_bundle *bundle; int retval; @@ -140,7 +140,7 @@ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, bundle->intf = intf; bundle->id = bundle_id; - bundle->class_type = class_type; + bundle->class = class; INIT_LIST_HEAD(&bundle->connections); /* Invalid device id to start with */ diff --git a/drivers/staging/greybus/bundle.h b/drivers/staging/greybus/bundle.h index 1fcf5b8..3265a00 100644 --- a/drivers/staging/greybus/bundle.h +++ b/drivers/staging/greybus/bundle.h @@ -17,7 +17,7 @@ struct gb_bundle { struct device dev; struct gb_interface *intf; u8 id; - u8 class_type; + u8 class; u8 device_id; struct list_head connections; @@ -29,7 +29,7 @@ struct gb_bundle { /* Greybus "private" definitions" */ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, - u8 class_type); + u8 class); void gb_bundle_destroy(struct gb_interface *intf); int gb_bundle_init(struct gb_bundle *bundle, u8 device_id); int gb_bundles_init(struct gb_interface *intf, u8 device_id); diff --git a/drivers/staging/greybus/greybus_id.h b/drivers/staging/greybus/greybus_id.h index 4204a8c..8e76d42 100644 --- a/drivers/staging/greybus/greybus_id.h +++ b/drivers/staging/greybus/greybus_id.h @@ -13,7 +13,7 @@ struct greybus_bundle_id { __u16 match_flags; __u16 vendor; __u16 product; - __u8 class_type; + __u8 class; __u64 unique_id; kernel_ulong_t driver_info __aligned(sizeof(kernel_ulong_t)); @@ -23,6 +23,6 @@ struct greybus_bundle_id { #define GREYBUS_ID_MATCH_VENDOR BIT(0) #define GREYBUS_ID_MATCH_PRODUCT BIT(1) #define GREYBUS_ID_MATCH_SERIAL BIT(2) -#define GREYBUS_ID_MATCH_CLASS_TYPE BIT(3) +#define GREYBUS_ID_MATCH_CLASS BIT(3) #endif /* __LINUX_GREYBUS_ID_H */ diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index a338683..e855ada 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -93,7 +93,7 @@ struct greybus_descriptor_interface { }; /* - * An bundle descriptor defines an identification number and a class type for + * An bundle descriptor defines an identification number and a class for * each bundle. * * @id: Uniquely identifies a bundle within a interface, its sole purpose is to @@ -105,7 +105,7 @@ struct greybus_descriptor_interface { * encode the device id and module number in UniPro packets * that use the bundle. * - * @class_type: It is used by kernel to know the functionality provided by the + * @class: It is used by kernel to know the functionality provided by the * bundle and will be matched against drivers functinality while probing greybus * driver. It should contain one of the values defined in * 'enum greybus_class_type'. @@ -113,7 +113,7 @@ struct greybus_descriptor_interface { */ struct greybus_descriptor_bundle { __u8 id; /* interface-relative id (0..) */ - __u8 class_type; + __u8 class; }; /* diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 12eee3a..d6cafeb 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -261,7 +261,7 @@ static u32 gb_manifest_parse_bundles(struct gb_interface *intf) /* Found one. Set up its bundle structure*/ desc_bundle = descriptor->data; bundle = gb_bundle_create(intf, desc_bundle->id, - desc_bundle->class_type); + desc_bundle->class); if (!bundle) return 0; /* Error */ -- cgit v0.10.2 From b7744b7f97d1c86d2a480fdc53a22a042ac4dda9 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 7 Apr 2015 11:27:09 +0200 Subject: greybus: es1: drop unnecessary casts Drop unnecessary explicit casts. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index f559c1d..7f7e2fd 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -244,7 +244,7 @@ static void *buffer_send(struct greybus_host_device *hd, u16 cport_id, pr_err("request to send inbound data buffer\n"); return ERR_PTR(-EINVAL); } - if (cport_id > (u16)U8_MAX) { + if (cport_id > U8_MAX) { pr_err("cport_id (%hd) is out of range for ES1\n", cport_id); return ERR_PTR(-EINVAL); } @@ -423,7 +423,7 @@ static void cport_in_callback(struct urb *urb) * the rest of the stream is "real" data */ data = urb->transfer_buffer; - cport_id = (u16)data[0]; + cport_id = data[0]; data = &data[1]; /* Pass this data to the greybus core */ -- cgit v0.10.2 From 79940cf8759558d55b597e27353f6521516aa7ac Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 7 Apr 2015 11:27:10 +0200 Subject: greybus: es1: fix DMA-buffer on stack A stack-allocated buffer is not generally DMA-able and must not be used for USB control transfers. Note that the memset and extra buffer byte were redundant as no more than the bytes actually transferred was ever added to the fifo. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 7f7e2fd..f2c1cde 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -454,14 +454,13 @@ static void cport_out_callback(struct urb *urb) free_urb(es1, urb); } -static void apb1_log_get(struct es1_ap_dev *es1) +#define APB1_LOG_MSG_SIZE 64 +static void apb1_log_get(struct es1_ap_dev *es1, char *buf) { - char buf[65]; int retval; /* SVC messages go down our control pipe */ do { - memset(buf, 0, 65); retval = usb_control_msg(es1->usb_dev, usb_rcvctrlpipe(es1->usb_dev, es1->control_endpoint), @@ -469,7 +468,7 @@ static void apb1_log_get(struct es1_ap_dev *es1) USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0x00, 0x00, buf, - 64, + APB1_LOG_MSG_SIZE, ES1_TIMEOUT); if (retval > 0) kfifo_in(&apb1_log_fifo, buf, retval); @@ -478,10 +477,20 @@ static void apb1_log_get(struct es1_ap_dev *es1) static int apb1_log_poll(void *data) { + struct es1_ap_dev *es1 = data; + char *buf; + + buf = kmalloc(APB1_LOG_MSG_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + while (!kthread_should_stop()) { msleep(1000); - apb1_log_get((struct es1_ap_dev *)data); + apb1_log_get(es1, buf); } + + kfree(buf); + return 0; } -- cgit v0.10.2 From bfd9a94d1aa2a8592749342d8024543ae3ff9e57 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 7 Apr 2015 11:27:11 +0200 Subject: greybus: es1: fix buffer-size limit The maximum buffer size does not include the headroom, so subtract the headroom size from the actual buffer size. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index f2c1cde..b9fd511 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -132,7 +132,7 @@ static void hd_buffer_constraints(struct greybus_host_device *hd) * that's better aligned for the user. */ hd->buffer_headroom = sizeof(u32); /* For cport id */ - hd->buffer_size_max = ES1_GBUF_MSG_SIZE_MAX; + hd->buffer_size_max = ES1_GBUF_MSG_SIZE_MAX - hd->buffer_headroom; BUILD_BUG_ON(hd->buffer_headroom > GB_BUFFER_HEADROOM_MAX); } -- cgit v0.10.2 From c15ccabe8105e2ef5e34e610c068e6f50ff08598 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 7 Apr 2015 11:27:12 +0200 Subject: greybus: es2: sync up with recent es1 changes Fix two bugs in es2 and do some minor clean up. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index a6c47a3..526e23c 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -132,7 +132,7 @@ static void hd_buffer_constraints(struct greybus_host_device *hd) * that's better aligned for the user. */ hd->buffer_headroom = sizeof(u32); /* For cport id */ - hd->buffer_size_max = ES1_GBUF_MSG_SIZE_MAX; + hd->buffer_size_max = ES1_GBUF_MSG_SIZE_MAX - hd->buffer_headroom; BUILD_BUG_ON(hd->buffer_headroom > GB_BUFFER_HEADROOM_MAX); } @@ -244,7 +244,7 @@ static void *buffer_send(struct greybus_host_device *hd, u16 cport_id, pr_err("request to send inbound data buffer\n"); return ERR_PTR(-EINVAL); } - if (cport_id > (u16)U8_MAX) { + if (cport_id > U8_MAX) { pr_err("cport_id (%hd) is out of range for ES1\n", cport_id); return ERR_PTR(-EINVAL); } @@ -423,7 +423,7 @@ static void cport_in_callback(struct urb *urb) * the rest of the stream is "real" data */ data = urb->transfer_buffer; - cport_id = (u16)data[0]; + cport_id = data[0]; data = &data[1]; /* Pass this data to the greybus core */ @@ -454,14 +454,13 @@ static void cport_out_callback(struct urb *urb) free_urb(es1, urb); } -static void apb1_log_get(struct es1_ap_dev *es1) +#define APB1_LOG_MSG_SIZE 64 +static void apb1_log_get(struct es1_ap_dev *es1, char *buf) { - char buf[65]; int retval; /* SVC messages go down our control pipe */ do { - memset(buf, 0, 65); retval = usb_control_msg(es1->usb_dev, usb_rcvctrlpipe(es1->usb_dev, es1->control_endpoint), @@ -469,7 +468,7 @@ static void apb1_log_get(struct es1_ap_dev *es1) USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0x00, 0x00, buf, - 64, + APB1_LOG_MSG_SIZE, ES1_TIMEOUT); if (retval > 0) kfifo_in(&apb1_log_fifo, buf, retval); @@ -478,10 +477,20 @@ static void apb1_log_get(struct es1_ap_dev *es1) static int apb1_log_poll(void *data) { + struct es1_ap_dev *es1 = data; + char *buf; + + buf = kmalloc(APB1_LOG_MSG_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + while (!kthread_should_stop()) { msleep(1000); - apb1_log_get((struct es1_ap_dev *)data); + apb1_log_get(es1, buf); } + + kfree(buf); + return 0; } -- cgit v0.10.2 From 564c72b1c6f753f562e42c2a30a5dc50c194be0f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 7 Apr 2015 11:27:13 +0200 Subject: greybus: operation: fix unaligned memory accesses in receive path The buffer received from our current host driver is 1-byte aligned and will therefore cause unaligned memory accesses if simply cast to an operation-message header. Fix this by making a properly aligned copy of the header in gb_connection_recv_response before accessing its fields. Note that this does not affect protocol drivers as the whole buffer is copied when creating the corresponding request or response before being forwarded. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 260774e..0fd77c9 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -885,7 +885,7 @@ static void gb_connection_recv_response(struct gb_connection *connection, void gb_connection_recv(struct gb_connection *connection, void *data, size_t size) { - struct gb_operation_msg_hdr *header; + struct gb_operation_msg_hdr header; size_t msg_size; u16 operation_id; @@ -895,27 +895,28 @@ void gb_connection_recv(struct gb_connection *connection, return; } - if (size < sizeof(*header)) { + if (size < sizeof(header)) { dev_err(&connection->dev, "message too small\n"); return; } - header = data; - msg_size = le16_to_cpu(header->size); + /* Use memcpy as data may be unaligned */ + memcpy(&header, data, sizeof(header)); + msg_size = le16_to_cpu(header.size); if (size < msg_size) { dev_err(&connection->dev, "incomplete message received: 0x%04x (%zu < %zu)\n", - le16_to_cpu(header->operation_id), size, msg_size); + le16_to_cpu(header.operation_id), size, msg_size); return; /* XXX Should still complete operation */ } - operation_id = le16_to_cpu(header->operation_id); - if (header->type & GB_OPERATION_TYPE_RESPONSE) + operation_id = le16_to_cpu(header.operation_id); + if (header.type & GB_OPERATION_TYPE_RESPONSE) gb_connection_recv_response(connection, operation_id, - header->result, data, msg_size); + header.result, data, msg_size); else gb_connection_recv_request(connection, operation_id, - header->type, data, msg_size); + header.type, data, msg_size); } /* -- cgit v0.10.2 From cbba76f5cdbc14d2ae415c6f949c7d725b06a27b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 7 Apr 2015 11:27:14 +0200 Subject: greybus: remove obsolete buffer-alignment requirement Remove unused and unnecessary buffer-alignment define that host driver were supposed to use. We can handle unaligned incoming buffers just fine by accessing the operation-message header via a copy in the receive path, rather than requiring host drivers to make sure the alignment is correct. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index a466fc5..fb90f96 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -79,9 +79,6 @@ struct svc_msg; */ #define GB_BUFFER_HEADROOM_MAX sizeof(u64) -/* Buffers allocated from the host driver will be aligned to this multiple */ -#define GB_BUFFER_ALIGN sizeof(u32) - /* Greybus "Host driver" structure, needed by a host controller driver to be * able to handle both SVC control as well as "real" greybus messages */ -- cgit v0.10.2 From ac67acd3040affb7a7baa0cc626a3757758ed8a7 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 7 Apr 2015 11:27:15 +0200 Subject: greybus: operation: move message-header definition to header file Move operation message-header to operation.h so that it can be used by host drivers. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 0fd77c9..2dbb1e9 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -33,35 +33,6 @@ static struct workqueue_struct *gb_operation_workqueue; static DEFINE_MUTEX(gb_message_mutex); /* - * All operation messages (both requests and responses) begin with - * a header that encodes the size of the message (header included). - * This header also contains a unique identifier, that associates a - * response message with its operation. The header contains an - * operation type field, whose interpretation is dependent on what - * type of protocol is used over the connection. The high bit - * (0x80) of the operation type field is used to indicate whether - * the message is a request (clear) or a response (set). - * - * Response messages include an additional result byte, which - * communicates the result of the corresponding request. A zero - * result value means the operation completed successfully. Any - * other value indicates an error; in this case, the payload of the - * response message (if any) is ignored. The result byte must be - * zero in the header for a request message. - * - * The wire format for all numeric fields in the header is little - * endian. Any operation-specific data begins immediately after the - * header, and is 64-bit aligned. - */ -struct gb_operation_msg_hdr { - __le16 size; /* Size in bytes of header + payload */ - __le16 operation_id; /* Operation unique id */ - __u8 type; /* E.g GB_I2C_TYPE_* or GB_GPIO_TYPE_* */ - __u8 result; /* Result of request (in responses only) */ - /* 2 bytes pad, must be zero (ignore when read) */ -} __aligned(sizeof(u64)); - -/* * Protects access to connection operations lists, as well as * updates to operation->errno. */ diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 6784f98..5ed1f6e 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -41,6 +41,35 @@ enum gb_operation_result { }; /* + * All operation messages (both requests and responses) begin with + * a header that encodes the size of the message (header included). + * This header also contains a unique identifier, that associates a + * response message with its operation. The header contains an + * operation type field, whose interpretation is dependent on what + * type of protocol is used over the connection. The high bit + * (0x80) of the operation type field is used to indicate whether + * the message is a request (clear) or a response (set). + * + * Response messages include an additional result byte, which + * communicates the result of the corresponding request. A zero + * result value means the operation completed successfully. Any + * other value indicates an error; in this case, the payload of the + * response message (if any) is ignored. The result byte must be + * zero in the header for a request message. + * + * The wire format for all numeric fields in the header is little + * endian. Any operation-specific data begins immediately after the + * header, and is 64-bit aligned. + */ +struct gb_operation_msg_hdr { + __le16 size; /* Size in bytes of header + payload */ + __le16 operation_id; /* Operation unique id */ + __u8 type; /* E.g GB_I2C_TYPE_* or GB_GPIO_TYPE_* */ + __u8 result; /* Result of request (in responses only) */ + /* 2 bytes pad, must be zero (ignore when read) */ +} __aligned(sizeof(u64)); + +/* * Protocol code should only examine the payload and payload_size * fields. All other fields are intended to be private to the * operations core code. -- cgit v0.10.2 From 7cf7bca9ec5659efa9520ffc5a3ff4ef59383560 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 7 Apr 2015 11:27:16 +0200 Subject: greybus: pass messages to host drivers Pass structured greybus messages rather than buffers to the host drivers. This will allow us to separate the transfer buffers from the message structures. Rename the related functions to reflect the new interface. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 0ac2fb8..da62c54 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -173,7 +173,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver * Validate that the driver implements all of the callbacks * so that we don't have to every time we make them. */ - if ((!driver->buffer_send) || (!driver->buffer_cancel) || + if ((!driver->message_send) || (!driver->message_cancel) || (!driver->submit_svc)) { pr_err("Must implement all greybus_host_driver callbacks!\n"); return NULL; diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index b9fd511..55f8c75 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -214,26 +214,21 @@ static void free_urb(struct es1_ap_dev *es1, struct urb *urb) * error otherwise. If the caller wishes to cancel the in-flight * buffer, it must supply the returned cookie to the cancel routine. */ -static void *buffer_send(struct greybus_host_device *hd, u16 cport_id, - void *buffer, size_t buffer_size, gfp_t gfp_mask) +static void *message_send(struct greybus_host_device *hd, u16 cport_id, + struct gb_message *message, gfp_t gfp_mask) { struct es1_ap_dev *es1 = hd_to_es1(hd); struct usb_device *udev = es1->usb_dev; - u8 *transfer_buffer = buffer; + u8 *transfer_buffer; + size_t buffer_size; int transfer_buffer_size; int retval; struct urb *urb; - if (!buffer) { - pr_err("null buffer supplied to send\n"); - return ERR_PTR(-EINVAL); - } - if (buffer_size > (size_t)INT_MAX) { - pr_err("bad buffer size (%zu) supplied to send\n", buffer_size); - return ERR_PTR(-EINVAL); - } - transfer_buffer--; - transfer_buffer_size = buffer_size + 1; + buffer_size = hd->buffer_headroom + sizeof(*message->header) + + message->payload_size; + transfer_buffer = message->buffer + hd->buffer_headroom - 1; + transfer_buffer_size = buffer_size - (hd->buffer_headroom - 1); /* * The data actually transferred will include an indication @@ -259,7 +254,7 @@ static void *buffer_send(struct greybus_host_device *hd, u16 cport_id, usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, es1->cport_out_endpoint), transfer_buffer, transfer_buffer_size, - cport_out_callback, hd); + cport_out_callback, message); retval = usb_submit_urb(urb, gfp_mask); if (retval) { pr_err("error %d submitting URB\n", retval); @@ -271,17 +266,17 @@ static void *buffer_send(struct greybus_host_device *hd, u16 cport_id, } /* - * The cookie value supplied is the value that buffer_send() - * returned to its caller. It identifies the buffer that should be + * The cookie value supplied is the value that message_send() + * returned to its caller. It identifies the message that should be * canceled. This function must also handle (which is to say, * ignore) a null cookie value. */ -static void buffer_cancel(void *cookie) +static void message_cancel(void *cookie) { /* * We really should be defensive and track all outstanding - * (sent) buffers rather than trusting the cookie provided + * (sent) messages rather than trusting the cookie provided * is valid. For the time being, this will do. */ if (cookie) @@ -290,8 +285,8 @@ static void buffer_cancel(void *cookie) static struct greybus_host_driver es1_driver = { .hd_priv_size = sizeof(struct es1_ap_dev), - .buffer_send = buffer_send, - .buffer_cancel = buffer_cancel, + .message_send = message_send, + .message_cancel = message_cancel, .submit_svc = submit_svc, }; @@ -439,18 +434,17 @@ exit: static void cport_out_callback(struct urb *urb) { - struct greybus_host_device *hd = urb->context; + struct gb_message *message = urb->context; + struct greybus_host_device *hd = message->operation->connection->hd; struct es1_ap_dev *es1 = hd_to_es1(hd); int status = check_urb_status(urb); - u8 *data = urb->transfer_buffer + 1; /* - * Tell the submitter that the buffer send (attempt) is - * complete, and report the status. The submitter's buffer - * starts after the one-byte CPort id we inserted. + * Tell the submitter that the message send (attempt) is + * complete, and report the status. */ - data = urb->transfer_buffer + 1; - greybus_data_sent(hd, data, status); + greybus_message_sent(hd, message, status); + free_urb(es1, urb); } diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 526e23c..10b21df 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -214,26 +214,21 @@ static void free_urb(struct es1_ap_dev *es1, struct urb *urb) * error otherwise. If the caller wishes to cancel the in-flight * buffer, it must supply the returned cookie to the cancel routine. */ -static void *buffer_send(struct greybus_host_device *hd, u16 cport_id, - void *buffer, size_t buffer_size, gfp_t gfp_mask) +static void *message_send(struct greybus_host_device *hd, u16 cport_id, + struct gb_message *message, gfp_t gfp_mask) { struct es1_ap_dev *es1 = hd_to_es1(hd); struct usb_device *udev = es1->usb_dev; - u8 *transfer_buffer = buffer; + u8 *transfer_buffer; + size_t buffer_size; int transfer_buffer_size; int retval; struct urb *urb; - if (!buffer) { - pr_err("null buffer supplied to send\n"); - return ERR_PTR(-EINVAL); - } - if (buffer_size > (size_t)INT_MAX) { - pr_err("bad buffer size (%zu) supplied to send\n", buffer_size); - return ERR_PTR(-EINVAL); - } - transfer_buffer--; - transfer_buffer_size = buffer_size + 1; + buffer_size = hd->buffer_headroom + sizeof(*message->header) + + message->payload_size; + transfer_buffer = message->buffer + hd->buffer_headroom - 1; + transfer_buffer_size = buffer_size - (hd->buffer_headroom - 1); /* * The data actually transferred will include an indication @@ -259,7 +254,7 @@ static void *buffer_send(struct greybus_host_device *hd, u16 cport_id, usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, es1->cport_out_endpoint), transfer_buffer, transfer_buffer_size, - cport_out_callback, hd); + cport_out_callback, message); retval = usb_submit_urb(urb, gfp_mask); if (retval) { pr_err("error %d submitting URB\n", retval); @@ -271,17 +266,17 @@ static void *buffer_send(struct greybus_host_device *hd, u16 cport_id, } /* - * The cookie value supplied is the value that buffer_send() - * returned to its caller. It identifies the buffer that should be + * The cookie value supplied is the value that message_send() + * returned to its caller. It identifies the message that should be * canceled. This function must also handle (which is to say, * ignore) a null cookie value. */ -static void buffer_cancel(void *cookie) +static void message_cancel(void *cookie) { /* * We really should be defensive and track all outstanding - * (sent) buffers rather than trusting the cookie provided + * (sent) messages rather than trusting the cookie provided * is valid. For the time being, this will do. */ if (cookie) @@ -290,8 +285,8 @@ static void buffer_cancel(void *cookie) static struct greybus_host_driver es1_driver = { .hd_priv_size = sizeof(struct es1_ap_dev), - .buffer_send = buffer_send, - .buffer_cancel = buffer_cancel, + .message_send = message_send, + .message_cancel = message_cancel, .submit_svc = submit_svc, }; @@ -439,18 +434,17 @@ exit: static void cport_out_callback(struct urb *urb) { - struct greybus_host_device *hd = urb->context; + struct gb_message *message = urb->context; + struct greybus_host_device *hd = message->operation->connection->hd; struct es1_ap_dev *es1 = hd_to_es1(hd); int status = check_urb_status(urb); - u8 *data = urb->transfer_buffer + 1; /* - * Tell the submitter that the buffer send (attempt) is - * complete, and report the status. The submitter's buffer - * starts after the one-byte CPort id we inserted. + * Tell the submitter that the message send (attempt) is + * complete, and report the status. */ - data = urb->transfer_buffer + 1; - greybus_data_sent(hd, data, status); + greybus_message_sent(hd, message, status); + free_urb(es1, urb); } diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index fb90f96..6f156e5 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -85,9 +85,9 @@ struct svc_msg; struct greybus_host_driver { size_t hd_priv_size; - void *(*buffer_send)(struct greybus_host_device *hd, u16 dest_cport_id, - void *buffer, size_t buffer_size, gfp_t gfp_mask); - void (*buffer_cancel)(void *cookie); + void *(*message_send)(struct greybus_host_device *hd, u16 dest_cport_id, + struct gb_message *message, gfp_t gfp_mask); + void (*message_cancel)(void *cookie); int (*submit_svc)(struct svc_msg *svc_msg, struct greybus_host_device *hd); }; diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 2dbb1e9..cdfb893 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -140,16 +140,14 @@ gb_operation_find(struct gb_connection *connection, u16 operation_id) static int gb_message_send(struct gb_message *message) { - size_t message_size = sizeof(*message->header) + message->payload_size; struct gb_connection *connection = message->operation->connection; int ret = 0; void *cookie; mutex_lock(&gb_message_mutex); - cookie = connection->hd->driver->buffer_send(connection->hd, + cookie = connection->hd->driver->message_send(connection->hd, connection->hd_cport_id, - message->header, - message_size, + message, GFP_KERNEL); if (IS_ERR(cookie)) ret = PTR_ERR(cookie); @@ -161,8 +159,7 @@ static int gb_message_send(struct gb_message *message) } /* - * Cancel a message whose buffer we have passed to the host device - * layer to be sent. + * Cancel a message we have passed to the host device layer to be sent. */ static void gb_message_cancel(struct gb_message *message) { @@ -171,7 +168,7 @@ static void gb_message_cancel(struct gb_message *message) struct greybus_host_device *hd; hd = message->operation->connection->hd; - hd->driver->buffer_cancel(message->cookie); + hd->driver->message_cancel(message->cookie); } mutex_unlock(&gb_message_mutex); } @@ -225,25 +222,6 @@ static void gb_operation_work(struct work_struct *work) gb_operation_put(operation); } - -/* - * Given a pointer to the header in a message sent on a given host - * device, return the associated message structure. (This "header" - * is just the buffer pointer we supply to the host device for - * sending.) - */ -static struct gb_message * -gb_hd_message_find(struct greybus_host_device *hd, void *header) -{ - struct gb_message *message; - u8 *result; - - result = (u8 *)header - hd->buffer_headroom - sizeof(*message); - message = (struct gb_message *)result; - - return message; -} - static void gb_operation_message_init(struct greybus_host_device *hd, struct gb_message *message, u16 operation_id, size_t payload_size, u8 type) @@ -737,18 +715,14 @@ int gb_operation_response_send(struct gb_operation *operation, int errno) EXPORT_SYMBOL_GPL(gb_operation_response_send); /* - * This function is called when a buffer send request has completed. - * The "header" is the message header--the beginning of what we - * asked to have sent. + * This function is called when a message send request has completed. */ -void -greybus_data_sent(struct greybus_host_device *hd, void *header, int status) +void greybus_message_sent(struct greybus_host_device *hd, + struct gb_message *message, int status) { - struct gb_message *message; struct gb_operation *operation; /* Get the message and record that it is no longer in flight */ - message = gb_hd_message_find(hd, header); message->cookie = NULL; /* @@ -773,7 +747,7 @@ greybus_data_sent(struct greybus_host_device *hd, void *header, int status) queue_work(gb_operation_workqueue, &operation->work); } } -EXPORT_SYMBOL_GPL(greybus_data_sent); +EXPORT_SYMBOL_GPL(greybus_message_sent); /* * We've received data on a connection, and it doesn't look like a diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 5ed1f6e..cbd347c 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -147,8 +147,8 @@ int gb_operation_response_send(struct gb_operation *operation, int errno); void gb_operation_cancel(struct gb_operation *operation, int errno); -void greybus_data_sent(struct greybus_host_device *hd, - void *header, int status); +void greybus_message_sent(struct greybus_host_device *hd, + struct gb_message *message, int status); int gb_operation_sync(struct gb_connection *connection, int type, void *request, int request_size, -- cgit v0.10.2 From 1e5613b4a673f0670b64fe24f1c987604403e8c1 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 7 Apr 2015 11:27:17 +0200 Subject: greybus: operation: fix potential message corruption Make sure to allocate the message transfer-buffer separately from the containing message structure to avoid data corruption on systems without DMA-coherent caches. The message structure contains state that is updated while the buffer may be used for DMA, something which could lead to data corruption due to cache-line sharing on some architectures. Use the (renamed) message cache for the message structure itself and allocate the buffer separately. If the additional allocation is a concern, the message structures could eventually be allocated as part of the operation structure. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index cdfb893..4d9e321 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -24,7 +24,7 @@ #define GB_OPERATION_MESSAGE_SIZE_MAX 4096 static struct kmem_cache *gb_operation_cache; -static struct kmem_cache *gb_simple_message_cache; +static struct kmem_cache *gb_message_cache; /* Workqueue to handle Greybus operation completions. */ static struct workqueue_struct *gb_operation_workqueue; @@ -229,7 +229,7 @@ static void gb_operation_message_init(struct greybus_host_device *hd, struct gb_operation_msg_hdr *header; u8 *buffer; - buffer = &message->buffer[0]; + buffer = message->buffer; header = (struct gb_operation_msg_hdr *)(buffer + hd->buffer_headroom); message->header = header; @@ -270,8 +270,7 @@ static void gb_operation_message_init(struct greybus_host_device *hd, * The headers for inbound messages don't need to be initialized; * they'll be filled in by arriving data. * - * Our message structure consists of: - * message structure + * Our message buffers have the following layout: * headroom * message header \_ these combined are * message payload / the message size @@ -291,34 +290,37 @@ gb_operation_message_alloc(struct greybus_host_device *hd, u8 type, hd->buffer_size_max = GB_OPERATION_MESSAGE_SIZE_MAX; } - /* Allocate the message. Use the slab cache for simple messages */ - if (payload_size) { - if (message_size > hd->buffer_size_max) { - pr_warn("requested message size too big (%zu > %zu)\n", + if (message_size > hd->buffer_size_max) { + pr_warn("requested message size too big (%zu > %zu)\n", message_size, hd->buffer_size_max); - return NULL; - } - - size = sizeof(*message) + hd->buffer_headroom + message_size; - message = kzalloc(size, gfp_flags); - } else { - message = kmem_cache_zalloc(gb_simple_message_cache, gfp_flags); + return NULL; } + + /* Allocate the message structure and buffer. */ + message = kmem_cache_zalloc(gb_message_cache, gfp_flags); if (!message) return NULL; + size = hd->buffer_headroom + message_size; + message->buffer = kzalloc(size, gfp_flags); + if (!message->buffer) + goto err_free_message; + /* Initialize the message. Operation id is filled in later. */ gb_operation_message_init(hd, message, 0, payload_size, type); return message; + +err_free_message: + kmem_cache_free(gb_message_cache, message); + + return NULL; } static void gb_operation_message_free(struct gb_message *message) { - if (message->payload_size) - kfree(message); - else - kmem_cache_free(gb_simple_message_cache, message); + kfree(message->buffer); + kmem_cache_free(gb_message_cache, message); } /* @@ -937,32 +939,18 @@ EXPORT_SYMBOL_GPL(gb_operation_sync); int gb_operation_init(void) { - size_t size; - BUILD_BUG_ON(GB_OPERATION_MESSAGE_SIZE_MAX > U16_MAX - sizeof(struct gb_operation_msg_hdr)); - /* - * A message structure consists of: - * - the message structure itself - * - the headroom set aside for the host device - * - the message header - * - space for the message payload - * Messages with no payload are a fairly common case and - * have a known fixed maximum size, so we use a slab cache - * for them. - */ - size = sizeof(struct gb_message) + GB_BUFFER_HEADROOM_MAX + - sizeof(struct gb_operation_msg_hdr); - gb_simple_message_cache = kmem_cache_create("gb_simple_message_cache", - size, 0, 0, NULL); - if (!gb_simple_message_cache) + gb_message_cache = kmem_cache_create("gb_message_cache", + sizeof(struct gb_message), 0, 0, NULL); + if (!gb_message_cache) return -ENOMEM; gb_operation_cache = kmem_cache_create("gb_operation_cache", sizeof(struct gb_operation), 0, 0, NULL); if (!gb_operation_cache) - goto err_simple; + goto err_destroy_message_cache; gb_operation_workqueue = alloc_workqueue("greybus_operation", 0, 1); if (!gb_operation_workqueue) @@ -972,9 +960,9 @@ int gb_operation_init(void) err_operation: kmem_cache_destroy(gb_operation_cache); gb_operation_cache = NULL; -err_simple: - kmem_cache_destroy(gb_simple_message_cache); - gb_simple_message_cache = NULL; +err_destroy_message_cache: + kmem_cache_destroy(gb_message_cache); + gb_message_cache = NULL; return -ENOMEM; } @@ -985,6 +973,6 @@ void gb_operation_exit(void) gb_operation_workqueue = NULL; kmem_cache_destroy(gb_operation_cache); gb_operation_cache = NULL; - kmem_cache_destroy(gb_simple_message_cache); - gb_simple_message_cache = NULL; + kmem_cache_destroy(gb_message_cache); + gb_message_cache = NULL; } diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index cbd347c..647e0bf 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -82,7 +82,7 @@ struct gb_message { void *payload; size_t payload_size; - u8 buffer[]; + void *buffer; }; /* -- cgit v0.10.2 From da9dd11943d1409c9992fe058c67e1017426a1d9 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 7 Apr 2015 11:27:18 +0200 Subject: greybus: operation: add explicit padding to message header Add explicit pad bytes to the message header. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 647e0bf..38684f2 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -66,7 +66,7 @@ struct gb_operation_msg_hdr { __le16 operation_id; /* Operation unique id */ __u8 type; /* E.g GB_I2C_TYPE_* or GB_GPIO_TYPE_* */ __u8 result; /* Result of request (in responses only) */ - /* 2 bytes pad, must be zero (ignore when read) */ + __u8 pad[2]; /* must be zero (ignore when read) */ } __aligned(sizeof(u64)); /* -- cgit v0.10.2 From a9cf7da195d99ceac46d46bf5ac31586afb66af7 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 7 Apr 2015 11:27:19 +0200 Subject: greybus: es1: fix transfer-buffer alignment Fix transfer-buffer alignment of outgoing transfers which are currently byte aligned. Some USB host drivers cannot handle byte-aligned buffers and will allocate temporary buffers, which the data is copied to or from on every transfer. This affects for example musb (e.g. Beaglebone Black) and ehci-tegra (e.g. Jetson). Instead of transferring pad bytes on the wire, let's (ab)use the pad bytes of the operation message header to transfer the cport id. This gives us properly aligned buffers and more efficient transfers in both directions. By using both pad bytes, we can also remove the arbitrary limitation of 256 cports. Note that the protocol between the host driver and the UniPro bridge is not necessarily Greybus. As long as the firmware clears the pad bytes before forwarding the data, and the host driver does the same before passing received data up the stack, this should be considered "legal" use. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 55f8c75..bf44835 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "greybus.h" #include "svc_msg.h" @@ -127,13 +128,8 @@ static void usb_log_disable(struct es1_ap_dev *es1); */ static void hd_buffer_constraints(struct greybus_host_device *hd) { - /* - * Only one byte is required, but this produces a result - * that's better aligned for the user. - */ - hd->buffer_headroom = sizeof(u32); /* For cport id */ - hd->buffer_size_max = ES1_GBUF_MSG_SIZE_MAX - hd->buffer_headroom; - BUILD_BUG_ON(hd->buffer_headroom > GB_BUFFER_HEADROOM_MAX); + hd->buffer_headroom = 0; + hd->buffer_size_max = ES1_GBUF_MSG_SIZE_MAX; } #define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ @@ -219,16 +215,13 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id, { struct es1_ap_dev *es1 = hd_to_es1(hd); struct usb_device *udev = es1->usb_dev; - u8 *transfer_buffer; + void *buffer; size_t buffer_size; - int transfer_buffer_size; int retval; struct urb *urb; - buffer_size = hd->buffer_headroom + sizeof(*message->header) + - message->payload_size; - transfer_buffer = message->buffer + hd->buffer_headroom - 1; - transfer_buffer_size = buffer_size - (hd->buffer_headroom - 1); + buffer = message->buffer; + buffer_size = sizeof(*message->header) + message->payload_size; /* * The data actually transferred will include an indication @@ -239,26 +232,27 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id, pr_err("request to send inbound data buffer\n"); return ERR_PTR(-EINVAL); } - if (cport_id > U8_MAX) { - pr_err("cport_id (%hd) is out of range for ES1\n", cport_id); - return ERR_PTR(-EINVAL); - } - /* OK, the destination is fine; record it in the transfer buffer */ - *transfer_buffer = cport_id; /* Find a free urb */ urb = next_free_urb(es1, gfp_mask); if (!urb) return ERR_PTR(-ENOMEM); + /* + * We (ab)use the operation-message header pad bytes to transfer the + * cport id in order to minimise overhead. + */ + put_unaligned_le16(cport_id, message->header->pad); + usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, es1->cport_out_endpoint), - transfer_buffer, transfer_buffer_size, + buffer, buffer_size, cport_out_callback, message); retval = usb_submit_urb(urb, gfp_mask); if (retval) { pr_err("error %d submitting URB\n", retval); free_urb(es1, urb); + put_unaligned_le16(0, message->header->pad); return ERR_PTR(retval); } @@ -395,10 +389,10 @@ static void cport_in_callback(struct urb *urb) { struct greybus_host_device *hd = urb->context; struct device *dev = &urb->dev->dev; + struct gb_operation_msg_hdr *header; int status = check_urb_status(urb); int retval; u16 cport_id; - u8 *data; if (status) { if ((status == -EAGAIN) || (status == -EPROTO)) @@ -407,23 +401,17 @@ static void cport_in_callback(struct urb *urb) return; } - /* The size has to be at least one, for the cport id */ - if (!urb->actual_length) { - dev_err(dev, "%s: no cport id in input buffer?\n", __func__); + if (urb->actual_length < sizeof(*header)) { + dev_err(dev, "%s: short message received\n", __func__); goto exit; } - /* - * Our CPort number is the first byte of the data stream, - * the rest of the stream is "real" data - */ - data = urb->transfer_buffer; - cport_id = data[0]; - data = &data[1]; - - /* Pass this data to the greybus core */ - greybus_data_rcvd(hd, cport_id, data, urb->actual_length - 1); + header = urb->transfer_buffer; + cport_id = get_unaligned_le16(header->pad); + put_unaligned_le16(0, header->pad); + greybus_data_rcvd(hd, cport_id, urb->transfer_buffer, + urb->actual_length); exit: /* put our urb back in the request pool */ retval = usb_submit_urb(urb, GFP_ATOMIC); @@ -439,6 +427,9 @@ static void cport_out_callback(struct urb *urb) struct es1_ap_dev *es1 = hd_to_es1(hd); int status = check_urb_status(urb); + /* Clear the pad bytes used for the cport id */ + put_unaligned_le16(0, message->header->pad); + /* * Tell the submitter that the message send (attempt) is * complete, and report the status. -- cgit v0.10.2 From 491e60d63fde0a9ff09490a070d7bc22ff82c9ce Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 7 Apr 2015 11:27:20 +0200 Subject: greybus: es2: sync up with recent es1 changes Fix transfer-buffer alignment of es2 as well. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 10b21df..45b6815 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "greybus.h" #include "svc_msg.h" @@ -127,13 +128,8 @@ static void usb_log_disable(struct es1_ap_dev *es1); */ static void hd_buffer_constraints(struct greybus_host_device *hd) { - /* - * Only one byte is required, but this produces a result - * that's better aligned for the user. - */ - hd->buffer_headroom = sizeof(u32); /* For cport id */ - hd->buffer_size_max = ES1_GBUF_MSG_SIZE_MAX - hd->buffer_headroom; - BUILD_BUG_ON(hd->buffer_headroom > GB_BUFFER_HEADROOM_MAX); + hd->buffer_headroom = 0; + hd->buffer_size_max = ES1_GBUF_MSG_SIZE_MAX; } #define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ @@ -219,16 +215,13 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id, { struct es1_ap_dev *es1 = hd_to_es1(hd); struct usb_device *udev = es1->usb_dev; - u8 *transfer_buffer; + void *buffer; size_t buffer_size; - int transfer_buffer_size; int retval; struct urb *urb; - buffer_size = hd->buffer_headroom + sizeof(*message->header) + - message->payload_size; - transfer_buffer = message->buffer + hd->buffer_headroom - 1; - transfer_buffer_size = buffer_size - (hd->buffer_headroom - 1); + buffer = message->buffer; + buffer_size = sizeof(*message->header) + message->payload_size; /* * The data actually transferred will include an indication @@ -239,26 +232,27 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id, pr_err("request to send inbound data buffer\n"); return ERR_PTR(-EINVAL); } - if (cport_id > U8_MAX) { - pr_err("cport_id (%hd) is out of range for ES1\n", cport_id); - return ERR_PTR(-EINVAL); - } - /* OK, the destination is fine; record it in the transfer buffer */ - *transfer_buffer = cport_id; /* Find a free urb */ urb = next_free_urb(es1, gfp_mask); if (!urb) return ERR_PTR(-ENOMEM); + /* + * We (ab)use the operation-message header pad bytes to transfer the + * cport id in order to minimise overhead. + */ + put_unaligned_le16(cport_id, message->header->pad); + usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, es1->cport_out_endpoint), - transfer_buffer, transfer_buffer_size, + buffer, buffer_size, cport_out_callback, message); retval = usb_submit_urb(urb, gfp_mask); if (retval) { pr_err("error %d submitting URB\n", retval); free_urb(es1, urb); + put_unaligned_le16(0, message->header->pad); return ERR_PTR(retval); } @@ -395,10 +389,10 @@ static void cport_in_callback(struct urb *urb) { struct greybus_host_device *hd = urb->context; struct device *dev = &urb->dev->dev; + struct gb_operation_msg_hdr *header; int status = check_urb_status(urb); int retval; u16 cport_id; - u8 *data; if (status) { if ((status == -EAGAIN) || (status == -EPROTO)) @@ -407,23 +401,17 @@ static void cport_in_callback(struct urb *urb) return; } - /* The size has to be at least one, for the cport id */ - if (!urb->actual_length) { - dev_err(dev, "%s: no cport id in input buffer?\n", __func__); + if (urb->actual_length < sizeof(*header)) { + dev_err(dev, "%s: short message received\n", __func__); goto exit; } - /* - * Our CPort number is the first byte of the data stream, - * the rest of the stream is "real" data - */ - data = urb->transfer_buffer; - cport_id = data[0]; - data = &data[1]; - - /* Pass this data to the greybus core */ - greybus_data_rcvd(hd, cport_id, data, urb->actual_length - 1); + header = urb->transfer_buffer; + cport_id = get_unaligned_le16(header->pad); + put_unaligned_le16(0, header->pad); + greybus_data_rcvd(hd, cport_id, urb->transfer_buffer, + urb->actual_length); exit: /* put our urb back in the request pool */ retval = usb_submit_urb(urb, GFP_ATOMIC); @@ -439,6 +427,9 @@ static void cport_out_callback(struct urb *urb) struct es1_ap_dev *es1 = hd_to_es1(hd); int status = check_urb_status(urb); + /* Clear the pad bytes used for the cport id */ + put_unaligned_le16(0, message->header->pad); + /* * Tell the submitter that the message send (attempt) is * complete, and report the status. -- cgit v0.10.2 From 24ef4853986e740b90c4647b8ede70ed690185e2 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 7 Apr 2015 11:27:21 +0200 Subject: greybus: drop host-driver buffer headroom Drop the host-driver buffer headroom that was used to transfer the cport id on ES1 and ES2. Rather than transferring additional bytes on the wire and having to deal with buffer-alignment issues (e.g. requiring the headroom to be a multiple of 8 bytes) simply drop the headroom functionality. Host drivers are expected set up their transfer descriptors separately from the data buffers and any intermediate drivers (e.g. for Greybus over USB) can (ab)use the operation message pad bytes for now. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index bf44835..0df7bdd 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -106,29 +106,11 @@ static void usb_log_disable(struct es1_ap_dev *es1); * which defines a region of memory used by the host driver for * transferring the data. When Greybus allocates a buffer, it must * do so subject to the constraints associated with the host driver. - * These constraints are specified by two parameters: the - * headroom; and the maximum buffer size. * - * +------------------+ - * | Host driver | \ - * | reserved area | }- headroom - * | . . . | / - * buffer pointer ---> +------------------+ - * | Buffer space for | \ - * | transferred data | }- buffer size - * | . . . | / (limited to size_max) - * +------------------+ - * - * headroom: Every buffer must have at least this much space - * *before* the buffer pointer, reserved for use by the - * host driver. I.e., ((char *)buffer - headroom) must - * point to valid memory, usable only by the host driver. - * size_max: The maximum size of a buffer (not including the - * headroom) must not exceed this. + * size_max: The maximum size of a buffer */ static void hd_buffer_constraints(struct greybus_host_device *hd) { - hd->buffer_headroom = 0; hd->buffer_size_max = ES1_GBUF_MSG_SIZE_MAX; } diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 45b6815..dfadcb4 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -106,29 +106,11 @@ static void usb_log_disable(struct es1_ap_dev *es1); * which defines a region of memory used by the host driver for * transferring the data. When Greybus allocates a buffer, it must * do so subject to the constraints associated with the host driver. - * These constraints are specified by two parameters: the - * headroom; and the maximum buffer size. * - * +------------------+ - * | Host driver | \ - * | reserved area | }- headroom - * | . . . | / - * buffer pointer ---> +------------------+ - * | Buffer space for | \ - * | transferred data | }- buffer size - * | . . . | / (limited to size_max) - * +------------------+ - * - * headroom: Every buffer must have at least this much space - * *before* the buffer pointer, reserved for use by the - * host driver. I.e., ((char *)buffer - headroom) must - * point to valid memory, usable only by the host driver. - * size_max: The maximum size of a buffer (not including the - * headroom) must not exceed this. + * size_max: The maximum size of a buffer */ static void hd_buffer_constraints(struct greybus_host_device *hd) { - hd->buffer_headroom = 0; hd->buffer_size_max = ES1_GBUF_MSG_SIZE_MAX; } diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 6f156e5..8d4bde3 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -71,14 +71,6 @@ struct greybus_host_device; struct svc_msg; -/* - * When the Greybus code allocates a buffer it sets aside bytes - * prior to the beginning of the payload area for the host device's - * exclusive use. The size is specified by hd->buffer_headroom, and - * which can't be greater than GB_BUFFER_HEADROOM_MAX. - */ -#define GB_BUFFER_HEADROOM_MAX sizeof(u64) - /* Greybus "Host driver" structure, needed by a host controller driver to be * able to handle both SVC control as well as "real" greybus messages */ @@ -103,7 +95,6 @@ struct greybus_host_device { u8 device_id; /* Host device buffer constraints */ - size_t buffer_headroom; size_t buffer_size_max; /* Private data for the host driver */ diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 4d9e321..3639e27 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -230,7 +230,7 @@ static void gb_operation_message_init(struct greybus_host_device *hd, u8 *buffer; buffer = message->buffer; - header = (struct gb_operation_msg_hdr *)(buffer + hd->buffer_headroom); + header = message->buffer; message->header = header; message->payload = payload_size ? header + 1 : NULL; @@ -271,7 +271,6 @@ static void gb_operation_message_init(struct greybus_host_device *hd, * they'll be filled in by arriving data. * * Our message buffers have the following layout: - * headroom * message header \_ these combined are * message payload / the message size */ @@ -282,7 +281,6 @@ gb_operation_message_alloc(struct greybus_host_device *hd, u8 type, struct gb_message *message; struct gb_operation_msg_hdr *header; size_t message_size = payload_size + sizeof(*header); - size_t size; if (hd->buffer_size_max > GB_OPERATION_MESSAGE_SIZE_MAX) { pr_warn("limiting buffer size to %u\n", @@ -301,8 +299,7 @@ gb_operation_message_alloc(struct greybus_host_device *hd, u8 type, if (!message) return NULL; - size = hd->buffer_headroom + message_size; - message->buffer = kzalloc(size, gfp_flags); + message->buffer = kzalloc(message_size, gfp_flags); if (!message->buffer) goto err_free_message; -- cgit v0.10.2 From 764e824e2fa5cca0d7c671ae58e65cd06aed0fce Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 7 Apr 2015 20:26:30 +0200 Subject: greybus: module.c: add attributes This adds the attributes power_control and present to a module. It also removes the unneeded module_id attribute, as that comes from the name of the module itself. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index e8c1c07..780d163 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -11,37 +11,62 @@ /* module sysfs attributes */ -#define gb_module_attr(field, type) \ -static ssize_t field##_show(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct gb_module *module = to_gb_module(dev); \ - return sprintf(buf, "%"#type"\n", module->field); \ -} \ -static DEVICE_ATTR_RO(field) - -// FIXME, do we really need this attribute? -gb_module_attr(module_id, x); - static ssize_t epm_show(struct device *dev, struct device_attribute *attr, char *buf) { - // FIXME, implement something here + // FIXME + // Implement something here when we have a working control protocol return sprintf(buf, "1\n"); } static ssize_t epm_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { - // FIXME, implement something here. + // FIXME + // Implement something here when we have a working control protocol return 0; } static DEVICE_ATTR_RW(epm); +static ssize_t power_control_show(struct device *dev, + struct device_attribute *addr, char *buf) +{ + // FIXME + // Implement something here when we have a working control protocol + return sprintf(buf, "1\n"); +} + +static ssize_t power_control_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + // FIXME + // Implement something here when we have a working control protocol + return 0; +} +static DEVICE_ATTR_RW(power_control); + +static ssize_t present_show(struct device *dev, + struct device_attribute *addr, char *buf) +{ + // FIXME + // Implement something here when we have a working control protocol + return sprintf(buf, "1\n"); +} + +static ssize_t present_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + // FIXME + // Implement something here when we have a working control protocol + return 0; +} +static DEVICE_ATTR_RW(present); + static struct attribute *module_attrs[] = { - &dev_attr_module_id.attr, &dev_attr_epm.attr, + &dev_attr_power_control.attr, + &dev_attr_present.attr, NULL, }; ATTRIBUTE_GROUPS(module); -- cgit v0.10.2 From 0f035acdedcb4f016c2b7cc23758d9191713d951 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 7 Apr 2015 20:26:53 +0200 Subject: greybus: endo: add endo structures and logic This adds endo.c and endo.h and provides functions to create an endo and the initial 0x0555 set of modules. But, it doesn't hook this logic up into the running code yet, that comes next. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index f6ad19a..9945cb8 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -2,6 +2,7 @@ greybus-y := core.o \ debugfs.o \ ap.o \ manifest.o \ + endo.o \ module.o \ interface.o \ bundle.o \ diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index da62c54..7c701f3 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -51,6 +51,14 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) struct gb_bundle *bundle = NULL; struct gb_connection *connection = NULL; + if (is_gb_endo(dev)) { + /* + * Not much to do for an endo, just fall through, as the + * "default" attributes are good enough for us. + */ + return 0; + } + if (is_gb_module(dev)) { module = to_gb_module(dev); } else if (is_gb_interface(dev)) { diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c new file mode 100644 index 0000000..e3bb25f --- /dev/null +++ b/drivers/staging/greybus/endo.c @@ -0,0 +1,164 @@ +/* + * Greybus endo code + * + * Copyright 2015 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include "greybus.h" + +/* endo sysfs attributes */ +static ssize_t serial_number_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_endo *endo = to_gb_endo(dev); + + return sprintf(buf, "%s", &endo->svc.serial_number[0]); +} +static DEVICE_ATTR_RO(serial_number); + +static ssize_t version_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct gb_endo *endo = to_gb_endo(dev); + + return sprintf(buf, "%s", &endo->svc.version[0]); +} +static DEVICE_ATTR_RO(version); + +static struct attribute *endo_attrs[] = { + &dev_attr_serial_number.attr, + &dev_attr_version.attr, + NULL, +}; +static const struct attribute_group endo_group = { + .attrs = endo_attrs, + .name = "SVC", +}; +static const struct attribute_group *endo_groups[] = { + &endo_group, + NULL, +}; + +static void greybus_endo_release(struct device *dev) +{ + struct gb_endo *endo = to_gb_endo(dev); + + kfree(endo); +} + +struct device_type greybus_endo_type = { + .name = "greybus_endo", + .release = greybus_endo_release, +}; + + +/* + * Endo "types" have different module locations, these are tables based on those + * types that list the module ids for the different locations. + * + * List must end with 0x00 in order to properly terminate the list. + */ +static u8 endo_0555[] = { + 0x01, + 0x03, + 0x05, + 0x07, + 0x08, + 0x0a, + 0x0c, + 0x00, +}; + + +static int create_modules(struct gb_endo *endo) +{ + struct gb_module *module; + u8 *endo_modules; + int i; + + /* Depending on the endo type, create a bunch of different modules */ + switch (endo->type) { + case 0x0555: + endo_modules = &endo_0555[0]; + break; + default: + dev_err(&endo->dev, "Unknown endo type 0x%04x, aborting!", + endo->type); + return -EINVAL; + } + + for (i = 0; endo_modules[i] != 0x00; ++i) { +// module = gb_module_create(&endo->dev, endo_modules[i]); + if (!module) + return -EINVAL; + } + + return 0; +} + +static void remove_modules(struct gb_endo *endo) +{ + /* + * We really don't care how many modules have been created, or what the + * configuration of them are, let's just enumerate over everything in + * the system and delete all found modules. + */ + +} + +struct gb_endo *gb_endo_create(struct greybus_host_device *hd) +{ + struct gb_endo *endo; + int retval; + + endo = kzalloc(sizeof(*endo), GFP_KERNEL); + if (!endo) + return NULL; + + endo->dev.parent = hd->parent; + endo->dev.bus = &greybus_bus_type; + endo->dev.type = &greybus_endo_type; + endo->dev.groups = endo_groups; + endo->dev.dma_mask = hd->parent->dma_mask; + device_initialize(&endo->dev); + + // FIXME - determine endo "type" from the SVC + // Also get the version and serial number from the SVC, right now we are + // using "fake" numbers. + strcpy(&endo->svc.serial_number[0], "042"); + strcpy(&endo->svc.version[0], "0.0"); + endo->type = 0x0555; + + dev_set_name(&endo->dev, "endo-0x%04x", endo->type); + retval = device_add(&endo->dev); + if (retval) { + dev_err(hd->parent, "failed to add endo device of type 0x%04x\n", + endo->type); + put_device(&endo->dev); + kfree(endo); + return NULL; + } + + retval = create_modules(endo); + if (retval) { + gb_endo_remove(endo); + return NULL; + } + + return endo; +} + +void gb_endo_remove(struct gb_endo *endo) +{ + if (!endo) + return; + + /* remove all modules first */ + remove_modules(endo); + + device_unregister(&endo->dev); +} + diff --git a/drivers/staging/greybus/endo.h b/drivers/staging/greybus/endo.h new file mode 100644 index 0000000..649093e --- /dev/null +++ b/drivers/staging/greybus/endo.h @@ -0,0 +1,32 @@ +/* + * Greybus endo code + * + * Copyright 2015 Google Inc. + * + * Released under the GPLv2 only. + */ + +#ifndef __ENDO_H +#define __ENDO_H + +/* Greybus "public" definitions" */ +struct gb_svc { + u8 serial_number[10]; + u8 version[10]; +}; + +struct gb_endo { + struct device dev; + struct gb_svc svc; + u16 type; +}; +#define to_gb_endo(d) container_of(d, struct gb_endo, dev) + + +/* Greybus "private" definitions */ +struct greybus_host_device; + +struct gb_endo *gb_endo_create(struct greybus_host_device *hd); +void gb_endo_remove(struct gb_endo *endo); + +#endif /* __ENDO_H */ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 8d4bde3..e0aae42 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -24,6 +24,7 @@ #include "greybus_id.h" #include "greybus_manifest.h" #include "manifest.h" +#include "endo.h" #include "module.h" #include "interface.h" #include "bundle.h" @@ -158,11 +159,17 @@ void gb_uart_device_exit(struct gb_connection *connection); int svc_set_route_send(struct gb_bundle *bundle, struct greybus_host_device *hd); +extern struct device_type greybus_endo_type; extern struct device_type greybus_module_type; extern struct device_type greybus_interface_type; extern struct device_type greybus_bundle_type; extern struct device_type greybus_connection_type; +static inline int is_gb_endo(const struct device *dev) +{ + return dev->type == &greybus_endo_type; +} + static inline int is_gb_module(const struct device *dev) { return dev->type == &greybus_module_type; -- cgit v0.10.2 From a4d9150cbaafd0d58eff54ea928d155ae582aa9c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 7 Apr 2015 20:27:15 +0200 Subject: greybus: endo: hook up endos into the device tree This hooks up the endo, and modules, into the device tree. All modules for a specific endo are created when the host device is initialized. When an interface is registered, the correct module for it is found and that module is used for the sysfs tree. When the interface is removed, the reference on the module is dropped. When the host device goes away, the whole endo and modules are removed at once. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 7c701f3..4580209 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -198,15 +198,25 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver INIT_LIST_HEAD(&hd->connections); ida_init(&hd->cport_id_map); + hd->endo = gb_endo_create(hd); + if (!hd->endo) { + greybus_remove_hd(hd); + return NULL; + } + return hd; } EXPORT_SYMBOL_GPL(greybus_create_hd); void greybus_remove_hd(struct greybus_host_device *hd) { - /* Tear down all modules that happen to be associated with this host - * controller */ + /* + * Tear down all interfaces, modules, and the endo that is associated + * with this host controller before freeing the memory associated with + * the host controller. + */ gb_remove_interfaces(hd); + gb_endo_remove(hd->endo); kref_put_mutex(&hd->kref, free_hd, &hd_mutex); } EXPORT_SYMBOL_GPL(greybus_remove_hd); diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c index e3bb25f..28e1f28 100644 --- a/drivers/staging/greybus/endo.c +++ b/drivers/staging/greybus/endo.c @@ -91,7 +91,7 @@ static int create_modules(struct gb_endo *endo) } for (i = 0; endo_modules[i] != 0x00; ++i) { -// module = gb_module_create(&endo->dev, endo_modules[i]); + module = gb_module_create(&endo->dev, endo_modules[i]); if (!module) return -EINVAL; } @@ -99,16 +99,6 @@ static int create_modules(struct gb_endo *endo) return 0; } -static void remove_modules(struct gb_endo *endo) -{ - /* - * We really don't care how many modules have been created, or what the - * configuration of them are, let's just enumerate over everything in - * the system and delete all found modules. - */ - -} - struct gb_endo *gb_endo_create(struct greybus_host_device *hd) { struct gb_endo *endo; @@ -156,8 +146,8 @@ void gb_endo_remove(struct gb_endo *endo) if (!endo) return; - /* remove all modules first */ - remove_modules(endo); + /* remove all modules for this endo */ + gb_module_remove_all(endo); device_unregister(&endo->dev); } diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index e0aae42..109727f 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -98,6 +98,8 @@ struct greybus_host_device { /* Host device buffer constraints */ size_t buffer_size_max; + struct gb_endo *endo; + /* Private data for the host driver */ unsigned long hd_priv[0] __aligned(sizeof(s64)); }; diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 5b1d5dd..63665a2 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -92,7 +92,7 @@ static struct gb_interface *gb_interface_create(struct greybus_host_device *hd, return NULL; } - module = gb_module_find_or_create(hd, get_module_id(interface_id)); + module = gb_module_find(hd, get_module_id(interface_id)); if (!module) return NULL; @@ -157,7 +157,7 @@ static void gb_interface_destroy(struct gb_interface *intf) module = intf->module; device_unregister(&intf->dev); - gb_module_remove(module); + put_device(&module->dev); } /** diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index 780d163..202f141 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -94,16 +94,22 @@ u8 get_module_id(u8 interface_id) return interface_id; } +struct module_find { + struct gb_endo *endo; + u8 module_id; +}; + static int module_find(struct device *dev, void *data) { struct gb_module *module; - u8 *module_id = data; + struct module_find *find = data; if (!is_gb_module(dev)) return 0; module = to_gb_module(dev); - if (module->module_id == *module_id) + if ((module->module_id == find->module_id) && + (module->dev.parent == &find->endo->dev)) return 1; return 0; @@ -113,21 +119,24 @@ static int module_find(struct device *dev, void *data) * Search the list of modules in the system. If one is found, return it, with * the reference count incremented. */ -static struct gb_module *gb_module_find(u8 module_id) +struct gb_module *gb_module_find(struct greybus_host_device *hd, u8 module_id) { struct device *dev; struct gb_module *module = NULL; + struct module_find find; + + find.module_id = module_id; + find.endo = hd->endo; dev = bus_find_device(&greybus_bus_type, NULL, - &module_id, module_find); + &find, module_find); if (dev) module = to_gb_module(dev); return module; } -static struct gb_module *gb_module_create(struct greybus_host_device *hd, - u8 module_id) +struct gb_module *gb_module_create(struct device *parent, u8 module_id) { struct gb_module *module; int retval; @@ -137,12 +146,11 @@ static struct gb_module *gb_module_create(struct greybus_host_device *hd, return NULL; module->module_id = module_id; - module->refcount = 1; - module->dev.parent = hd->parent; + module->dev.parent = parent; module->dev.bus = &greybus_bus_type; module->dev.type = &greybus_module_type; module->dev.groups = module_groups; - module->dev.dma_mask = hd->parent->dma_mask; + module->dev.dma_mask = parent->dma_mask; device_initialize(&module->dev); dev_set_name(&module->dev, "%d", module_id); @@ -158,26 +166,22 @@ static struct gb_module *gb_module_create(struct greybus_host_device *hd, return module; } -struct gb_module *gb_module_find_or_create(struct greybus_host_device *hd, - u8 module_id) +static int module_remove(struct device *dev, void *data) { struct gb_module *module; + struct gb_endo *endo = data; - module = gb_module_find(module_id); - if (module) { - module->refcount++; - return module; - } + if (!is_gb_module(dev)) + return 0; + + module = to_gb_module(dev); + if (module->dev.parent == &endo->dev) + device_unregister(&module->dev); - return gb_module_create(hd, module_id); + return 0; } -void gb_module_remove(struct gb_module *module) +void gb_module_remove_all(struct gb_endo *endo) { - if (!module) - return; - - if (!--module->refcount) - device_unregister(&module->dev); + bus_for_each_dev(&greybus_bus_type, NULL, endo, module_remove); } - diff --git a/drivers/staging/greybus/module.h b/drivers/staging/greybus/module.h index f3e3bdd..c23ac98 100644 --- a/drivers/staging/greybus/module.h +++ b/drivers/staging/greybus/module.h @@ -13,16 +13,15 @@ struct gb_module { struct device dev; u8 module_id; /* Physical location within the Endo */ - u16 refcount; }; #define to_gb_module(d) container_of(d, struct gb_module, dev) struct greybus_host_device; /* Greybus "private" definitions */ -struct gb_module *gb_module_find_or_create(struct greybus_host_device *hd, - u8 module_id); -void gb_module_remove(struct gb_module *module); +struct gb_module *gb_module_find(struct greybus_host_device *hd, u8 module_id); +struct gb_module *gb_module_create(struct device *parent, u8 module_id); +void gb_module_remove_all(struct gb_endo *endo); u8 get_module_id(u8 interface_id); -- cgit v0.10.2 From f0b678709a7d2c4eefa834db70580a226d212f8a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 7 Apr 2015 20:27:36 +0200 Subject: greybus: Documentation/sysfs-bus-greybus: update kernel version and date The kernel is now on the 4.XX numbering scheme, and it's going to be a while before we merge this code, so pick a date sometime in the future to be safe. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 748ea3e..9a945db 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -1,41 +1,41 @@ What: /sys/bus/greybus/device/.../product -Date: December 2014 -KernelVersion: 3.XX +Date: October 2015 +KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: Product ID of a Greybus interface block. What: /sys/bus/greybus/device/.../product_string -Date: December 2014 -KernelVersion: 3.XX +Date: October 2015 +KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: Product ID string of a Greybus interface block. What: /sys/bus/greybus/device/.../unique_id -Date: December 2014 -KernelVersion: 3.XX +Date: October 2015 +KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: Unique ID of a Greybus interface block. What: /sys/bus/greybus/device/.../vendor -Date: December 2014 -KernelVersion: 3.XX +Date: October 2015 +KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: Vendor ID of a Greybus interface block. What: /sys/bus/greybus/device/.../vendor_string -Date: December 2014 -KernelVersion: 3.XX +Date: October 2015 +KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: Vendor ID string of a Greybus interface block. What: /sys/bus/greybus/device/.../state -Date: December 2014 -KernelVersion: 3.XX +Date: October 2015 +KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: The current state of a Greybus connection. @@ -48,15 +48,15 @@ Description: 4 - destroying What: /sys/bus/greybus/device/.../protocol_id -Date: December 2014 -KernelVersion: 3.XX +Date: October 2015 +KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: The protocol id of a Greybus connection. What: /sys/bus/greybus/device/.../device_id -Date: December 2014 -KernelVersion: 3.XX +Date: October 2015 +KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: The device id of a Greybus bundle. -- cgit v0.10.2 From 7baa184dbd407b4a1b619c6f5f78074f0bb19ae9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 7 Apr 2015 20:27:53 +0200 Subject: greybus: Documentation/sysfs-bus-greybus: document the endo and SVC This documents the endo device, and the SVC specific files that are present in the sysfs device tree. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 9a945db..c0e0c0a 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -1,3 +1,26 @@ +What: /sys/bus/greybus/device/endo-XXXX +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The "root" endo for the Greybus device tree. XXX is + replaced with the numeric value of the endo layout + scheme as documented in the ARA Module Developer Kit. + +What: /sys/bus/greybus/device/endo-XXXX/SVC/serial_number +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The serial number of the SVC device + +What: /sys/bus/greybus/device/endo-XXXX/SVC/version +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The version number of the firmware in the SVC device. + What: /sys/bus/greybus/device/.../product Date: October 2015 KernelVersion: 4.XX -- cgit v0.10.2 From b0235b2263406728a0b6ee8b13be22f07507812d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 7 Apr 2015 20:28:13 +0200 Subject: greybus: Documentation/sysfs-bus-greybus: document module sysfs files This documents the module slot sysfs files "epm", "power_control", and "present". Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index c0e0c0a..4b511db 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -21,6 +21,36 @@ Contact: Greg Kroah-Hartman Description: The version number of the firmware in the SVC device. +What: /sys/bus/greybus/device/endo-XXXX/../epm +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The EPM (Electropermanent Magnet) control file for + the specific module slot the file is present in. + Writing 1 to it turns it on, writing 0 to it turns it + off. Reading the value returns if it is on or off. + +What: /sys/bus/greybus/device/endo-XXXX/../power_control +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The power control file for the specific module slot that + the file is present in. Writing 1 to it turns power on + to the module, writing 0 to it turns power off to the + module. Reading the value returns if it is on or off. + +What: /sys/bus/greybus/device/endo-XXXX/../present +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The "is a module present in the slot" file for the + specific module slot that the file is present in. + This is read-only, 1 means a module is present, 0 means + no module is present. + What: /sys/bus/greybus/device/.../product Date: October 2015 KernelVersion: 4.XX -- cgit v0.10.2 From 453bbea807345db3faab8f4a432b4b1b2b245a27 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Thu, 9 Apr 2015 16:01:31 -0700 Subject: greybus: Move briged phy structure definitions into gpbridge.h In order to facilitate re-use of the gpio, i2c, pwm and i2s structures, split them out of independent files and add them into a shared gpbridge.h This will be a prereq to sharing these headers w/ gbsim. Cc: Alex Elder Cc: Greg Kroah-Hartman CC: Johan Hovold Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpbridge.h b/drivers/staging/greybus/gpbridge.h new file mode 100644 index 0000000..8888238 --- /dev/null +++ b/drivers/staging/greybus/gpbridge.h @@ -0,0 +1,412 @@ +#ifndef __GB_GPBRIDGE_H__ +#define __GB_GPBRIDGE_H__ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2014 - 2015 Google Inc. All rights reserved. + * Copyright(c) 2014 - 2015 Linaro Ltd. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details. + * + * BSD LICENSE + * + * Copyright(c) 2014 - 2015 Google Inc. All rights reserved. + * Copyright(c) 2014 - 2015 Linaro Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. or Linaro Ltd. nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * 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 GOOGLE INC. OR + * LINARO LTD. 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. + */ + + +/* I2C */ + +/* Version of the Greybus i2c protocol we support */ +#define GB_I2C_VERSION_MAJOR 0x00 +#define GB_I2C_VERSION_MINOR 0x01 + +/* Greybus i2c request types */ +#define GB_I2C_TYPE_INVALID 0x00 +#define GB_I2C_TYPE_PROTOCOL_VERSION 0x01 +#define GB_I2C_TYPE_FUNCTIONALITY 0x02 +#define GB_I2C_TYPE_TIMEOUT 0x03 +#define GB_I2C_TYPE_RETRIES 0x04 +#define GB_I2C_TYPE_TRANSFER 0x05 +#define GB_I2C_TYPE_RESPONSE 0x80 /* OR'd with rest */ + +#define GB_I2C_RETRIES_DEFAULT 3 +#define GB_I2C_TIMEOUT_DEFAULT 1000 /* milliseconds */ + +/* functionality request has no payload */ +struct gb_i2c_functionality_response { + __le32 functionality; +}; + +struct gb_i2c_timeout_request { + __le16 msec; +}; +/* timeout response has no payload */ + +struct gb_i2c_retries_request { + __u8 retries; +}; +/* retries response has no payload */ + +/* + * Outgoing data immediately follows the op count and ops array. + * The data for each write (master -> slave) op in the array is sent + * in order, with no (e.g. pad) bytes separating them. + * + * Short reads cause the entire transfer request to fail So response + * payload consists only of bytes read, and the number of bytes is + * exactly what was specified in the corresponding op. Like + * outgoing data, the incoming data is in order and contiguous. + */ +struct gb_i2c_transfer_op { + __le16 addr; + __le16 flags; + __le16 size; +}; + +struct gb_i2c_transfer_request { + __le16 op_count; + struct gb_i2c_transfer_op ops[0]; /* op_count of these */ +}; +struct gb_i2c_transfer_response { + __u8 data[0]; /* inbound data */ +}; + + +/* GPIO */ + +/* Version of the Greybus GPIO protocol we support */ +#define GB_GPIO_VERSION_MAJOR 0x00 +#define GB_GPIO_VERSION_MINOR 0x01 + +/* Greybus GPIO request types */ +#define GB_GPIO_TYPE_INVALID 0x00 +#define GB_GPIO_TYPE_PROTOCOL_VERSION 0x01 +#define GB_GPIO_TYPE_LINE_COUNT 0x02 +#define GB_GPIO_TYPE_ACTIVATE 0x03 +#define GB_GPIO_TYPE_DEACTIVATE 0x04 +#define GB_GPIO_TYPE_GET_DIRECTION 0x05 +#define GB_GPIO_TYPE_DIRECTION_IN 0x06 +#define GB_GPIO_TYPE_DIRECTION_OUT 0x07 +#define GB_GPIO_TYPE_GET_VALUE 0x08 +#define GB_GPIO_TYPE_SET_VALUE 0x09 +#define GB_GPIO_TYPE_SET_DEBOUNCE 0x0a +#define GB_GPIO_TYPE_IRQ_TYPE 0x0b +#define GB_GPIO_TYPE_IRQ_ACK 0x0c +#define GB_GPIO_TYPE_IRQ_MASK 0x0d +#define GB_GPIO_TYPE_IRQ_UNMASK 0x0e +#define GB_GPIO_TYPE_IRQ_EVENT 0x0f +#define GB_GPIO_TYPE_RESPONSE 0x80 /* OR'd with rest */ + +#define GB_GPIO_DEBOUNCE_USEC_DEFAULT 0 /* microseconds */ + +/* line count request has no payload */ +struct gb_gpio_line_count_response { + __u8 count; +}; + +struct gb_gpio_activate_request { + __u8 which; +}; +/* activate response has no payload */ + +struct gb_gpio_deactivate_request { + __u8 which; +}; +/* deactivate response has no payload */ + +struct gb_gpio_get_direction_request { + __u8 which; +}; +struct gb_gpio_get_direction_response { + __u8 direction; +}; + +struct gb_gpio_direction_in_request { + __u8 which; +}; +/* direction in response has no payload */ + +struct gb_gpio_direction_out_request { + __u8 which; + __u8 value; +}; +/* direction out response has no payload */ + +struct gb_gpio_get_value_request { + __u8 which; +}; +struct gb_gpio_get_value_response { + __u8 value; +}; + +struct gb_gpio_set_value_request { + __u8 which; + __u8 value; +}; +/* set value response has no payload */ + +struct gb_gpio_set_debounce_request { + __u8 which; + __le16 usec __packed; +}; +/* debounce response has no payload */ + +struct gb_gpio_irq_type_request { + __u8 which; + __u8 type; +}; +/* irq type response has no payload */ + +struct gb_gpio_irq_mask_request { + __u8 which; +}; +/* irq mask response has no payload */ + +struct gb_gpio_irq_unmask_request { + __u8 which; +}; +/* irq unmask response has no payload */ + +struct gb_gpio_irq_ack_request { + __u8 which; +}; +/* irq ack response has no payload */ + +/* irq event requests originate on another module and are handled on the AP */ +struct gb_gpio_irq_event_request { + __u8 which; +}; +/* irq event response has no payload */ + + +/* PWM */ + +/* Version of the Greybus PWM protocol we support */ +#define GB_PWM_VERSION_MAJOR 0x00 +#define GB_PWM_VERSION_MINOR 0x01 + +/* Greybus PWM request types */ +#define GB_PWM_TYPE_INVALID 0x00 +#define GB_PWM_TYPE_PROTOCOL_VERSION 0x01 +#define GB_PWM_TYPE_PWM_COUNT 0x02 +#define GB_PWM_TYPE_ACTIVATE 0x03 +#define GB_PWM_TYPE_DEACTIVATE 0x04 +#define GB_PWM_TYPE_CONFIG 0x05 +#define GB_PWM_TYPE_POLARITY 0x06 +#define GB_PWM_TYPE_ENABLE 0x07 +#define GB_PWM_TYPE_DISABLE 0x08 +#define GB_PWM_TYPE_RESPONSE 0x80 /* OR'd with rest */ + +/* pwm count request has no payload */ +struct gb_pwm_count_response { + __u8 count; +}; + +struct gb_pwm_activate_request { + __u8 which; +}; + +struct gb_pwm_deactivate_request { + __u8 which; +}; + +struct gb_pwm_config_request { + __u8 which; + __le32 duty __packed; + __le32 period __packed; +}; + +struct gb_pwm_polarity_request { + __u8 which; + __u8 polarity; +}; + +struct gb_pwm_enable_request { + __u8 which; +}; + +struct gb_pwm_disable_request { + __u8 which; +}; + +/* I2S */ +#ifndef BIT +#define BIT(n) (1UL << (n)) +#endif + +#define GB_I2S_MGMT_TYPE_PROTOCOL_VERSION 0x01 +#define GB_I2S_MGMT_TYPE_GET_SUPPORTED_CONFIGURATIONS 0x02 +#define GB_I2S_MGMT_TYPE_SET_CONFIGURATION 0x03 +#define GB_I2S_MGMT_TYPE_SET_SAMPLES_PER_MESSAGE 0x04 +#define GB_I2S_MGMT_TYPE_GET_PROCESSING_DELAY 0x05 +#define GB_I2S_MGMT_TYPE_SET_START_DELAY 0x06 +#define GB_I2S_MGMT_TYPE_ACTIVATE_CPORT 0x07 +#define GB_I2S_MGMT_TYPE_DEACTIVATE_CPORT 0x08 +#define GB_I2S_MGMT_TYPE_REPORT_EVENT 0x09 + +#define GB_I2S_MGMT_BYTE_ORDER_NA BIT(0) +#define GB_I2S_MGMT_BYTE_ORDER_BE BIT(1) +#define GB_I2S_MGMT_BYTE_ORDER_LE BIT(2) + +#define GB_I2S_MGMT_SPATIAL_LOCATION_FL BIT(0) +#define GB_I2S_MGMT_SPATIAL_LOCATION_FR BIT(1) +#define GB_I2S_MGMT_SPATIAL_LOCATION_FC BIT(2) +#define GB_I2S_MGMT_SPATIAL_LOCATION_LFE BIT(3) +#define GB_I2S_MGMT_SPATIAL_LOCATION_BL BIT(4) +#define GB_I2S_MGMT_SPATIAL_LOCATION_BR BIT(5) +#define GB_I2S_MGMT_SPATIAL_LOCATION_FLC BIT(6) +#define GB_I2S_MGMT_SPATIAL_LOCATION_FRC BIT(7) +#define GB_I2S_MGMT_SPATIAL_LOCATION_C BIT(8) /* BC in USB */ +#define GB_I2S_MGMT_SPATIAL_LOCATION_SL BIT(9) +#define GB_I2S_MGMT_SPATIAL_LOCATION_SR BIT(10) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TC BIT(11) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TFL BIT(12) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TFC BIT(13) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TFR BIT(14) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TBL BIT(15) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TBC BIT(16) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TBR BIT(17) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TFLC BIT(18) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TFRC BIT(19) +#define GB_I2S_MGMT_SPATIAL_LOCATION_LLFE BIT(20) +#define GB_I2S_MGMT_SPATIAL_LOCATION_RLFE BIT(21) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TSL BIT(22) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TSR BIT(23) +#define GB_I2S_MGMT_SPATIAL_LOCATION_BC BIT(24) +#define GB_I2S_MGMT_SPATIAL_LOCATION_BLC BIT(25) +#define GB_I2S_MGMT_SPATIAL_LOCATION_BRC BIT(26) +#define GB_I2S_MGMT_SPATIAL_LOCATION_RD BIT(31) + +#define GB_I2S_MGMT_PROTOCOL_PCM BIT(0) +#define GB_I2S_MGMT_PROTOCOL_I2S BIT(1) +#define GB_I2S_MGMT_PROTOCOL_LR_STEREO BIT(2) + +#define GB_I2S_MGMT_ROLE_MASTER BIT(0) +#define GB_I2S_MGMT_ROLE_SLAVE BIT(1) + +#define GB_I2S_MGMT_POLARITY_NORMAL BIT(0) +#define GB_I2S_MGMT_POLARITY_REVERSED BIT(1) + +#define GB_I2S_MGMT_EDGE_RISING BIT(0) +#define GB_I2S_MGMT_EDGE_FALLING BIT(1) + +#define GB_I2S_MGMT_EVENT_UNSPECIFIED 0x1 +#define GB_I2S_MGMT_EVENT_HALT 0x2 +#define GB_I2S_MGMT_EVENT_INTERNAL_ERROR 0x3 +#define GB_I2S_MGMT_EVENT_PROTOCOL_ERROR 0x4 +#define GB_I2S_MGMT_EVENT_FAILURE 0x5 +#define GB_I2S_MGMT_EVENT_OUT_OF_SEQUENCE 0x6 +#define GB_I2S_MGMT_EVENT_UNDERRUN 0x7 +#define GB_I2S_MGMT_EVENT_OVERRUN 0x8 +#define GB_I2S_MGMT_EVENT_CLOCKING 0x9 +#define GB_I2S_MGMT_EVENT_DATA_LEN 0xa + +struct gb_i2s_mgmt_configuration { + __le32 sample_frequency; + __u8 num_channels; + __u8 bytes_per_channel; + __u8 byte_order; + __u8 pad; + __le32 spatial_locations; + __le32 ll_protocol; + __u8 ll_bclk_role; + __u8 ll_wclk_role; + __u8 ll_wclk_polarity; + __u8 ll_wclk_change_edge; + __u8 ll_wclk_tx_edge; + __u8 ll_wclk_rx_edge; + __u8 ll_data_offset; + __u8 ll_pad; +}; + +/* get supported configurations request has no payload */ +struct gb_i2s_mgmt_get_supported_configurations_response { + __u8 config_count; + __u8 pad[3]; + struct gb_i2s_mgmt_configuration config[0]; +}; + +struct gb_i2s_mgmt_set_configuration_request { + struct gb_i2s_mgmt_configuration config; +}; +/* set configuration response has no payload */ + +struct gb_i2s_mgmt_set_samples_per_message_request { + __le16 samples_per_message; +}; +/* set samples per message response has no payload */ + +/* get processing request delay has no payload */ +struct gb_i2s_mgmt_get_processing_delay_response { + __le32 microseconds; +}; + +struct gb_i2s_mgmt_set_start_delay_request { + __le32 microseconds; +}; +/* set start delay response has no payload */ + +struct gb_i2s_mgmt_activate_cport_request { + __le16 cport; +}; +/* activate cport response has no payload */ + +struct gb_i2s_mgmt_deactivate_cport_request { + __le16 cport; +}; +/* deactivate cport response has no payload */ + +struct gb_i2s_mgmt_report_event_request { + __u8 event; +}; +/* report event response has no payload */ + +#define GB_I2S_DATA_TYPE_PROTOCOL_VERSION 0x01 +#define GB_I2S_DATA_TYPE_SEND_DATA 0x02 + +struct gb_i2s_send_data_request { + __le32 sample_number; + __le32 size; + __u8 data[0]; +}; +/* send data has no response at all */ + +#endif /* __GB_GPBRIDGE_H__ */ diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 20917bf..5ed1895 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -14,6 +14,7 @@ #include #include #include "greybus.h" +#include "gpbridge.h" struct gb_gpio_line { /* The following has to be an array of line_max entries */ @@ -43,110 +44,6 @@ struct gb_gpio_controller { container_of(chip, struct gb_gpio_controller, chip) #define irq_data_to_gpio_chip(d) (d->domain->host_data) -/* Version of the Greybus GPIO protocol we support */ -#define GB_GPIO_VERSION_MAJOR 0x00 -#define GB_GPIO_VERSION_MINOR 0x01 - -/* Greybus GPIO request types */ -#define GB_GPIO_TYPE_INVALID 0x00 -#define GB_GPIO_TYPE_PROTOCOL_VERSION 0x01 -#define GB_GPIO_TYPE_LINE_COUNT 0x02 -#define GB_GPIO_TYPE_ACTIVATE 0x03 -#define GB_GPIO_TYPE_DEACTIVATE 0x04 -#define GB_GPIO_TYPE_GET_DIRECTION 0x05 -#define GB_GPIO_TYPE_DIRECTION_IN 0x06 -#define GB_GPIO_TYPE_DIRECTION_OUT 0x07 -#define GB_GPIO_TYPE_GET_VALUE 0x08 -#define GB_GPIO_TYPE_SET_VALUE 0x09 -#define GB_GPIO_TYPE_SET_DEBOUNCE 0x0a -#define GB_GPIO_TYPE_IRQ_TYPE 0x0b -#define GB_GPIO_TYPE_IRQ_ACK 0x0c -#define GB_GPIO_TYPE_IRQ_MASK 0x0d -#define GB_GPIO_TYPE_IRQ_UNMASK 0x0e -#define GB_GPIO_TYPE_IRQ_EVENT 0x0f -#define GB_GPIO_TYPE_RESPONSE 0x80 /* OR'd with rest */ - -#define GB_GPIO_DEBOUNCE_USEC_DEFAULT 0 /* microseconds */ - -/* line count request has no payload */ -struct gb_gpio_line_count_response { - __u8 count; -}; - -struct gb_gpio_activate_request { - __u8 which; -}; -/* activate response has no payload */ - -struct gb_gpio_deactivate_request { - __u8 which; -}; -/* deactivate response has no payload */ - -struct gb_gpio_get_direction_request { - __u8 which; -}; -struct gb_gpio_get_direction_response { - __u8 direction; -}; - -struct gb_gpio_direction_in_request { - __u8 which; -}; -/* direction in response has no payload */ - -struct gb_gpio_direction_out_request { - __u8 which; - __u8 value; -}; -/* direction out response has no payload */ - -struct gb_gpio_get_value_request { - __u8 which; -}; -struct gb_gpio_get_value_response { - __u8 value; -}; - -struct gb_gpio_set_value_request { - __u8 which; - __u8 value; -}; -/* set value response has no payload */ - -struct gb_gpio_set_debounce_request { - __u8 which; - __le16 usec __packed; -}; -/* debounce response has no payload */ - -struct gb_gpio_irq_type_request { - __u8 which; - __u8 type; -}; -/* irq type response has no payload */ - -struct gb_gpio_irq_mask_request { - __u8 which; -}; -/* irq mask response has no payload */ - -struct gb_gpio_irq_unmask_request { - __u8 which; -}; -/* irq unmask response has no payload */ - -struct gb_gpio_irq_ack_request { - __u8 which; -}; -/* irq ack response has no payload */ - -/* irq event requests originate on another module and are handled on the AP */ -struct gb_gpio_irq_event_request { - __u8 which; -}; -/* irq event response has no payload */ - /* Define get_version() routine */ define_get_version(gb_gpio_controller, GPIO); diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c index 84d20e5..6fdbf11 100644 --- a/drivers/staging/greybus/i2c.c +++ b/drivers/staging/greybus/i2c.c @@ -13,6 +13,8 @@ #include #include "greybus.h" +#include "gpbridge.h" + struct gb_i2c_device { struct gb_connection *connection; @@ -26,61 +28,6 @@ struct gb_i2c_device { struct i2c_adapter adapter; }; -/* Version of the Greybus i2c protocol we support */ -#define GB_I2C_VERSION_MAJOR 0x00 -#define GB_I2C_VERSION_MINOR 0x01 - -/* Greybus i2c request types */ -#define GB_I2C_TYPE_INVALID 0x00 -#define GB_I2C_TYPE_PROTOCOL_VERSION 0x01 -#define GB_I2C_TYPE_FUNCTIONALITY 0x02 -#define GB_I2C_TYPE_TIMEOUT 0x03 -#define GB_I2C_TYPE_RETRIES 0x04 -#define GB_I2C_TYPE_TRANSFER 0x05 -#define GB_I2C_TYPE_RESPONSE 0x80 /* OR'd with rest */ - -#define GB_I2C_RETRIES_DEFAULT 3 -#define GB_I2C_TIMEOUT_DEFAULT 1000 /* milliseconds */ - -/* functionality request has no payload */ -struct gb_i2c_functionality_response { - __le32 functionality; -}; - -struct gb_i2c_timeout_request { - __le16 msec; -}; -/* timeout response has no payload */ - -struct gb_i2c_retries_request { - __u8 retries; -}; -/* retries response has no payload */ - -/* - * Outgoing data immediately follows the op count and ops array. - * The data for each write (master -> slave) op in the array is sent - * in order, with no (e.g. pad) bytes separating them. - * - * Short reads cause the entire transfer request to fail So response - * payload consists only of bytes read, and the number of bytes is - * exactly what was specified in the corresponding op. Like - * outgoing data, the incoming data is in order and contiguous. - */ -struct gb_i2c_transfer_op { - __le16 addr; - __le16 flags; - __le16 size; -}; - -struct gb_i2c_transfer_request { - __le16 op_count; - struct gb_i2c_transfer_op ops[0]; /* op_count of these */ -}; -struct gb_i2c_transfer_response { - __u8 data[0]; /* inbound data */ -}; - /* Define get_version() routine */ define_get_version(gb_i2c_device, I2C); diff --git a/drivers/staging/greybus/i2s.h b/drivers/staging/greybus/i2s.h deleted file mode 100644 index 5c42756..0000000 --- a/drivers/staging/greybus/i2s.h +++ /dev/null @@ -1,145 +0,0 @@ -#ifndef __GB_I2S_H__ -#define __GB_I2S_H__ - -#ifndef BIT -#define BIT(n) (1UL << (n)) -#endif - -#define GB_I2S_MGMT_TYPE_PROTOCOL_VERSION 0x01 -#define GB_I2S_MGMT_TYPE_GET_SUPPORTED_CONFIGURATIONS 0x02 -#define GB_I2S_MGMT_TYPE_SET_CONFIGURATION 0x03 -#define GB_I2S_MGMT_TYPE_SET_SAMPLES_PER_MESSAGE 0x04 -#define GB_I2S_MGMT_TYPE_GET_PROCESSING_DELAY 0x05 -#define GB_I2S_MGMT_TYPE_SET_START_DELAY 0x06 -#define GB_I2S_MGMT_TYPE_ACTIVATE_CPORT 0x07 -#define GB_I2S_MGMT_TYPE_DEACTIVATE_CPORT 0x08 -#define GB_I2S_MGMT_TYPE_REPORT_EVENT 0x09 - -#define GB_I2S_MGMT_BYTE_ORDER_NA BIT(0) -#define GB_I2S_MGMT_BYTE_ORDER_BE BIT(1) -#define GB_I2S_MGMT_BYTE_ORDER_LE BIT(2) - -#define GB_I2S_MGMT_SPATIAL_LOCATION_FL BIT(0) -#define GB_I2S_MGMT_SPATIAL_LOCATION_FR BIT(1) -#define GB_I2S_MGMT_SPATIAL_LOCATION_FC BIT(2) -#define GB_I2S_MGMT_SPATIAL_LOCATION_LFE BIT(3) -#define GB_I2S_MGMT_SPATIAL_LOCATION_BL BIT(4) -#define GB_I2S_MGMT_SPATIAL_LOCATION_BR BIT(5) -#define GB_I2S_MGMT_SPATIAL_LOCATION_FLC BIT(6) -#define GB_I2S_MGMT_SPATIAL_LOCATION_FRC BIT(7) -#define GB_I2S_MGMT_SPATIAL_LOCATION_C BIT(8) /* BC in USB */ -#define GB_I2S_MGMT_SPATIAL_LOCATION_SL BIT(9) -#define GB_I2S_MGMT_SPATIAL_LOCATION_SR BIT(10) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TC BIT(11) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TFL BIT(12) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TFC BIT(13) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TFR BIT(14) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TBL BIT(15) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TBC BIT(16) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TBR BIT(17) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TFLC BIT(18) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TFRC BIT(19) -#define GB_I2S_MGMT_SPATIAL_LOCATION_LLFE BIT(20) -#define GB_I2S_MGMT_SPATIAL_LOCATION_RLFE BIT(21) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TSL BIT(22) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TSR BIT(23) -#define GB_I2S_MGMT_SPATIAL_LOCATION_BC BIT(24) -#define GB_I2S_MGMT_SPATIAL_LOCATION_BLC BIT(25) -#define GB_I2S_MGMT_SPATIAL_LOCATION_BRC BIT(26) -#define GB_I2S_MGMT_SPATIAL_LOCATION_RD BIT(31) - -#define GB_I2S_MGMT_PROTOCOL_PCM BIT(0) -#define GB_I2S_MGMT_PROTOCOL_I2S BIT(1) -#define GB_I2S_MGMT_PROTOCOL_LR_STEREO BIT(2) - -#define GB_I2S_MGMT_ROLE_MASTER BIT(0) -#define GB_I2S_MGMT_ROLE_SLAVE BIT(1) - -#define GB_I2S_MGMT_POLARITY_NORMAL BIT(0) -#define GB_I2S_MGMT_POLARITY_REVERSED BIT(1) - -#define GB_I2S_MGMT_EDGE_RISING BIT(0) -#define GB_I2S_MGMT_EDGE_FALLING BIT(1) - -#define GB_I2S_MGMT_EVENT_UNSPECIFIED 0x1 -#define GB_I2S_MGMT_EVENT_HALT 0x2 -#define GB_I2S_MGMT_EVENT_INTERNAL_ERROR 0x3 -#define GB_I2S_MGMT_EVENT_PROTOCOL_ERROR 0x4 -#define GB_I2S_MGMT_EVENT_FAILURE 0x5 -#define GB_I2S_MGMT_EVENT_OUT_OF_SEQUENCE 0x6 -#define GB_I2S_MGMT_EVENT_UNDERRUN 0x7 -#define GB_I2S_MGMT_EVENT_OVERRUN 0x8 -#define GB_I2S_MGMT_EVENT_CLOCKING 0x9 -#define GB_I2S_MGMT_EVENT_DATA_LEN 0xa - -struct gb_i2s_mgmt_configuration { - __le32 sample_frequency; - __u8 num_channels; - __u8 bytes_per_channel; - __u8 byte_order; - __u8 pad; - __le32 spatial_locations; - __le32 ll_protocol; - __u8 ll_bclk_role; - __u8 ll_wclk_role; - __u8 ll_wclk_polarity; - __u8 ll_wclk_change_edge; - __u8 ll_wclk_tx_edge; - __u8 ll_wclk_rx_edge; - __u8 ll_data_offset; - __u8 ll_pad; -}; - -/* get supported configurations request has no payload */ -struct gb_i2s_mgmt_get_supported_configurations_response { - __u8 config_count; - __u8 pad[3]; - struct gb_i2s_mgmt_configuration config[0]; -}; - -struct gb_i2s_mgmt_set_configuration_request { - struct gb_i2s_mgmt_configuration config; -}; -/* set configuration response has no payload */ - -struct gb_i2s_mgmt_set_samples_per_message_request { - __le16 samples_per_message; -}; -/* set samples per message response has no payload */ - -/* get processing request delay has no payload */ -struct gb_i2s_mgmt_get_processing_delay_response { - __le32 microseconds; -}; - -struct gb_i2s_mgmt_set_start_delay_request { - __le32 microseconds; -}; -/* set start delay response has no payload */ - -struct gb_i2s_mgmt_activate_cport_request { - __le16 cport; -}; -/* activate cport response has no payload */ - -struct gb_i2s_mgmt_deactivate_cport_request { - __le16 cport; -}; -/* deactivate cport response has no payload */ - -struct gb_i2s_mgmt_report_event_request { - __u8 event; -}; -/* report event response has no payload */ - -#define GB_I2S_DATA_TYPE_PROTOCOL_VERSION 0x01 -#define GB_I2S_DATA_TYPE_SEND_DATA 0x02 - -struct gb_i2s_send_data_request { - __le32 sample_number; - __le32 size; - __u8 data[0]; -}; -/* send data has no response at all */ - -#endif /* __GB_I2S_H__ */ diff --git a/drivers/staging/greybus/pwm.c b/drivers/staging/greybus/pwm.c index 4e38b8a..7495716 100644 --- a/drivers/staging/greybus/pwm.c +++ b/drivers/staging/greybus/pwm.c @@ -12,6 +12,7 @@ #include #include #include "greybus.h" +#include "gpbridge.h" struct gb_pwm_chip { struct gb_connection *connection; @@ -25,53 +26,6 @@ struct gb_pwm_chip { #define pwm_chip_to_gb_pwm_chip(chip) \ container_of(chip, struct gb_pwm_chip, chip) -/* Version of the Greybus PWM protocol we support */ -#define GB_PWM_VERSION_MAJOR 0x00 -#define GB_PWM_VERSION_MINOR 0x01 - -/* Greybus PWM request types */ -#define GB_PWM_TYPE_INVALID 0x00 -#define GB_PWM_TYPE_PROTOCOL_VERSION 0x01 -#define GB_PWM_TYPE_PWM_COUNT 0x02 -#define GB_PWM_TYPE_ACTIVATE 0x03 -#define GB_PWM_TYPE_DEACTIVATE 0x04 -#define GB_PWM_TYPE_CONFIG 0x05 -#define GB_PWM_TYPE_POLARITY 0x06 -#define GB_PWM_TYPE_ENABLE 0x07 -#define GB_PWM_TYPE_DISABLE 0x08 -#define GB_PWM_TYPE_RESPONSE 0x80 /* OR'd with rest */ - -/* pwm count request has no payload */ -struct gb_pwm_count_response { - __u8 count; -}; - -struct gb_pwm_activate_request { - __u8 which; -}; - -struct gb_pwm_deactivate_request { - __u8 which; -}; - -struct gb_pwm_config_request { - __u8 which; - __le32 duty __packed; - __le32 period __packed; -}; - -struct gb_pwm_polarity_request { - __u8 which; - __u8 polarity; -}; - -struct gb_pwm_enable_request { - __u8 which; -}; - -struct gb_pwm_disable_request { - __u8 which; -}; /* Define get_version() routine */ define_get_version(gb_pwm_chip, PWM); -- cgit v0.10.2 From 67c920b892fc16141734bdf03f9d16974d8a076f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 10 Apr 2015 11:18:49 +0200 Subject: greybus: gpbridge.h: whitespace cleanups Replace #define with #define. Also move the #ifdef block to below the initial comment block, like other .h files are. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpbridge.h b/drivers/staging/greybus/gpbridge.h index 8888238..44a7091 100644 --- a/drivers/staging/greybus/gpbridge.h +++ b/drivers/staging/greybus/gpbridge.h @@ -1,5 +1,3 @@ -#ifndef __GB_GPBRIDGE_H__ -#define __GB_GPBRIDGE_H__ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. @@ -51,24 +49,26 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#ifndef __GB_GPBRIDGE_H__ +#define __GB_GPBRIDGE_H__ /* I2C */ /* Version of the Greybus i2c protocol we support */ -#define GB_I2C_VERSION_MAJOR 0x00 -#define GB_I2C_VERSION_MINOR 0x01 +#define GB_I2C_VERSION_MAJOR 0x00 +#define GB_I2C_VERSION_MINOR 0x01 /* Greybus i2c request types */ -#define GB_I2C_TYPE_INVALID 0x00 -#define GB_I2C_TYPE_PROTOCOL_VERSION 0x01 -#define GB_I2C_TYPE_FUNCTIONALITY 0x02 -#define GB_I2C_TYPE_TIMEOUT 0x03 -#define GB_I2C_TYPE_RETRIES 0x04 -#define GB_I2C_TYPE_TRANSFER 0x05 -#define GB_I2C_TYPE_RESPONSE 0x80 /* OR'd with rest */ +#define GB_I2C_TYPE_INVALID 0x00 +#define GB_I2C_TYPE_PROTOCOL_VERSION 0x01 +#define GB_I2C_TYPE_FUNCTIONALITY 0x02 +#define GB_I2C_TYPE_TIMEOUT 0x03 +#define GB_I2C_TYPE_RETRIES 0x04 +#define GB_I2C_TYPE_TRANSFER 0x05 +#define GB_I2C_TYPE_RESPONSE 0x80 /* OR'd with rest */ -#define GB_I2C_RETRIES_DEFAULT 3 -#define GB_I2C_TIMEOUT_DEFAULT 1000 /* milliseconds */ +#define GB_I2C_RETRIES_DEFAULT 3 +#define GB_I2C_TIMEOUT_DEFAULT 1000 /* milliseconds */ /* functionality request has no payload */ struct gb_i2c_functionality_response { @@ -113,29 +113,29 @@ struct gb_i2c_transfer_response { /* GPIO */ /* Version of the Greybus GPIO protocol we support */ -#define GB_GPIO_VERSION_MAJOR 0x00 -#define GB_GPIO_VERSION_MINOR 0x01 +#define GB_GPIO_VERSION_MAJOR 0x00 +#define GB_GPIO_VERSION_MINOR 0x01 /* Greybus GPIO request types */ -#define GB_GPIO_TYPE_INVALID 0x00 -#define GB_GPIO_TYPE_PROTOCOL_VERSION 0x01 -#define GB_GPIO_TYPE_LINE_COUNT 0x02 -#define GB_GPIO_TYPE_ACTIVATE 0x03 -#define GB_GPIO_TYPE_DEACTIVATE 0x04 -#define GB_GPIO_TYPE_GET_DIRECTION 0x05 -#define GB_GPIO_TYPE_DIRECTION_IN 0x06 -#define GB_GPIO_TYPE_DIRECTION_OUT 0x07 -#define GB_GPIO_TYPE_GET_VALUE 0x08 -#define GB_GPIO_TYPE_SET_VALUE 0x09 -#define GB_GPIO_TYPE_SET_DEBOUNCE 0x0a +#define GB_GPIO_TYPE_INVALID 0x00 +#define GB_GPIO_TYPE_PROTOCOL_VERSION 0x01 +#define GB_GPIO_TYPE_LINE_COUNT 0x02 +#define GB_GPIO_TYPE_ACTIVATE 0x03 +#define GB_GPIO_TYPE_DEACTIVATE 0x04 +#define GB_GPIO_TYPE_GET_DIRECTION 0x05 +#define GB_GPIO_TYPE_DIRECTION_IN 0x06 +#define GB_GPIO_TYPE_DIRECTION_OUT 0x07 +#define GB_GPIO_TYPE_GET_VALUE 0x08 +#define GB_GPIO_TYPE_SET_VALUE 0x09 +#define GB_GPIO_TYPE_SET_DEBOUNCE 0x0a #define GB_GPIO_TYPE_IRQ_TYPE 0x0b #define GB_GPIO_TYPE_IRQ_ACK 0x0c #define GB_GPIO_TYPE_IRQ_MASK 0x0d #define GB_GPIO_TYPE_IRQ_UNMASK 0x0e #define GB_GPIO_TYPE_IRQ_EVENT 0x0f -#define GB_GPIO_TYPE_RESPONSE 0x80 /* OR'd with rest */ +#define GB_GPIO_TYPE_RESPONSE 0x80 /* OR'd with rest */ -#define GB_GPIO_DEBOUNCE_USEC_DEFAULT 0 /* microseconds */ +#define GB_GPIO_DEBOUNCE_USEC_DEFAULT 0 /* microseconds */ /* line count request has no payload */ struct gb_gpio_line_count_response { @@ -220,20 +220,20 @@ struct gb_gpio_irq_event_request { /* PWM */ /* Version of the Greybus PWM protocol we support */ -#define GB_PWM_VERSION_MAJOR 0x00 -#define GB_PWM_VERSION_MINOR 0x01 +#define GB_PWM_VERSION_MAJOR 0x00 +#define GB_PWM_VERSION_MINOR 0x01 /* Greybus PWM request types */ -#define GB_PWM_TYPE_INVALID 0x00 -#define GB_PWM_TYPE_PROTOCOL_VERSION 0x01 -#define GB_PWM_TYPE_PWM_COUNT 0x02 -#define GB_PWM_TYPE_ACTIVATE 0x03 -#define GB_PWM_TYPE_DEACTIVATE 0x04 -#define GB_PWM_TYPE_CONFIG 0x05 -#define GB_PWM_TYPE_POLARITY 0x06 -#define GB_PWM_TYPE_ENABLE 0x07 -#define GB_PWM_TYPE_DISABLE 0x08 -#define GB_PWM_TYPE_RESPONSE 0x80 /* OR'd with rest */ +#define GB_PWM_TYPE_INVALID 0x00 +#define GB_PWM_TYPE_PROTOCOL_VERSION 0x01 +#define GB_PWM_TYPE_PWM_COUNT 0x02 +#define GB_PWM_TYPE_ACTIVATE 0x03 +#define GB_PWM_TYPE_DEACTIVATE 0x04 +#define GB_PWM_TYPE_CONFIG 0x05 +#define GB_PWM_TYPE_POLARITY 0x06 +#define GB_PWM_TYPE_ENABLE 0x07 +#define GB_PWM_TYPE_DISABLE 0x08 +#define GB_PWM_TYPE_RESPONSE 0x80 /* OR'd with rest */ /* pwm count request has no payload */ struct gb_pwm_count_response { -- cgit v0.10.2 From dcd1dadd7ee32b3fd135904fac85c556bac5cbc5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 10 Apr 2015 11:20:35 +0200 Subject: greybus: gpbridge.h: remove BIT() define It's up to other files to define this if it's not present, not this file. Reported-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpbridge.h b/drivers/staging/greybus/gpbridge.h index 44a7091..e230188 100644 --- a/drivers/staging/greybus/gpbridge.h +++ b/drivers/staging/greybus/gpbridge.h @@ -268,9 +268,6 @@ struct gb_pwm_disable_request { }; /* I2S */ -#ifndef BIT -#define BIT(n) (1UL << (n)) -#endif #define GB_I2S_MGMT_TYPE_PROTOCOL_VERSION 0x01 #define GB_I2S_MGMT_TYPE_GET_SUPPORTED_CONFIGURATIONS 0x02 -- cgit v0.10.2 From 1ffc12be5549085faac2d6116f666cb9cbcb2930 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 16 Apr 2015 09:53:59 +0200 Subject: greybus: loopback: fix 64-bit divisions The code uses 64-bit divisions, which should be avoided, and also prevents the module from loading on 32-bit systems: gb_loopback: Unknown symbol __aeabi_uldivmod (err 0) Fix by using the kernel's 64-bit by 32-bit division implementation do_div. Compile tested only. I did not look very closely at the code itself. Perhaps this could be worked around in some other way, but this silences the linker warning and allows the module to be loaded. Reviewed-by: Alex Elder Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 9914b52..9860d64 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -13,6 +13,8 @@ #include #include #include +#include + #include "greybus.h" struct gb_loopback_stats { @@ -248,12 +250,16 @@ static void gb_loopback_update_stats(struct gb_loopback_stats *stats, u64 elapsed_nsecs) { u32 avg; + u64 tmp; if (elapsed_nsecs >= NSEC_PER_SEC) { - if (!stats->count) - avg = stats->sum * (elapsed_nsecs / NSEC_PER_SEC); - else + if (!stats->count) { + tmp = elapsed_nsecs; + do_div(tmp, NSEC_PER_SEC); + avg = stats->sum * tmp; + } else { avg = stats->sum / stats->count; + } if (stats->min > avg) stats->min = avg; if (stats->max < avg) @@ -281,10 +287,11 @@ static void gb_loopback_latency_update(struct gb_loopback *gb, struct timeval *tlat) { u32 lat; - u64 nsecs; + u64 tmp; - nsecs = timeval_to_ns(tlat); - lat = nsecs / NSEC_PER_MSEC; + tmp = timeval_to_ns(tlat); + do_div(tmp, NSEC_PER_MSEC); + lat = tmp; if (gb->latency.min > lat) gb->latency.min = lat; -- cgit v0.10.2 From 75052a5504705aded68e544967fdd1d296470bcc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 13 Apr 2015 19:48:37 +0200 Subject: greybus: bundle: add state sysfs file A bundle has a state file, that is managed by the endo userspace process. This file can be written to and any process that is polling on the file will be woken up and can read the new value. It's a "cheap" IPC for programs that are not allowed to do anything other than read/write to kernel sysfs files. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 4b511db..ab728a4 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -113,3 +113,16 @@ KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: The device id of a Greybus bundle. + +What: /sys/bus/greybus/device/.../state +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + A bundle has a state that is managed by the userspace + Endo process. This file allows that Endo to signal + other Android HALs that the state of the bundle has + changed to a specific value. When written to, any + process watching the file will be woken up, and the new + value can be read. It's a "poor-man's IPC", yes, but + simplifies the Android userspace code immensely. diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 3f1aa64..e7b2199 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -1,8 +1,8 @@ /* * Greybus bundles * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. * * Released under the GPLv2 only. */ @@ -31,9 +31,41 @@ static ssize_t class_show(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR_RO(class); +static ssize_t state_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct gb_bundle *bundle = to_gb_bundle(dev); + + if (bundle->state == NULL) + return sprintf(buf, "\n"); + + return sprintf(buf, "%s\n", bundle->state); +} + +static ssize_t state_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + struct gb_bundle *bundle = to_gb_bundle(dev); + + kfree(bundle->state); + bundle->state = kzalloc(size + 1, GFP_KERNEL); + if (!bundle->state) + return -ENOMEM; + + memcpy(bundle->state, buf, size); + + /* Tell userspace that the file contents changed */ + sysfs_notify(&bundle->dev.kobj, NULL, "state"); + + return size; +} +static DEVICE_ATTR_RW(state); + + static struct attribute *bundle_attrs[] = { &dev_attr_device_id.attr, &dev_attr_class.attr, + &dev_attr_state.attr, NULL, }; @@ -43,6 +75,7 @@ static void gb_bundle_release(struct device *dev) { struct gb_bundle *bundle = to_gb_bundle(dev); + kfree(bundle->state); kfree(bundle); } diff --git a/drivers/staging/greybus/bundle.h b/drivers/staging/greybus/bundle.h index 3265a00..5c12c72 100644 --- a/drivers/staging/greybus/bundle.h +++ b/drivers/staging/greybus/bundle.h @@ -20,6 +20,7 @@ struct gb_bundle { u8 class; u8 device_id; struct list_head connections; + u8 *state; struct list_head links; /* interface->bundles */ }; -- cgit v0.10.2 From 6cf42a447dece6d4b75b59dc531ddddf770ee324 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 13 Apr 2015 19:51:33 +0200 Subject: greybus: MODULE_LICENSE cleanup These are all GPLv2-only kernel modules, so properly set the correct MODULE_LICENSE string to make static checkers happy. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 4580209..db1da8a 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -272,5 +272,5 @@ static void __exit gb_exit(void) } module_exit(gb_exit); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Greg Kroah-Hartman "); diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 0df7bdd..4bba5d5 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -694,5 +694,5 @@ static struct usb_driver es1_ap_driver = { module_usb_driver(es1_ap_driver); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Greg Kroah-Hartman "); diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index dfadcb4..efdd48d 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -694,5 +694,5 @@ static struct usb_driver es1_ap_driver = { module_usb_driver(es1_ap_driver); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Greg Kroah-Hartman "); diff --git a/drivers/staging/greybus/gpb.c b/drivers/staging/greybus/gpb.c index 33bbe79..d5747b2 100644 --- a/drivers/staging/greybus/gpb.c +++ b/drivers/staging/greybus/gpb.c @@ -87,4 +87,4 @@ static void __exit gpbridge_exit(void) } module_exit(gpbridge_exit); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 58d674650b96d7ae81cda68b0cbf40fb3f9a9726 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 28 Apr 2015 19:40:26 +0530 Subject: greybus: endo: Use a real endo id 0x0555 isn't a valid endo id, use a real one. 0x4755 should be the Endo id for the (medium) Spiral 2 prototype. Lets use that. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c index 28e1f28..b8f6163 100644 --- a/drivers/staging/greybus/endo.c +++ b/drivers/staging/greybus/endo.c @@ -61,14 +61,17 @@ struct device_type greybus_endo_type = { * * List must end with 0x00 in order to properly terminate the list. */ -static u8 endo_0555[] = { +static u8 endo_4755[] = { 0x01, 0x03, 0x05, + 0x06, 0x07, 0x08, 0x0a, 0x0c, + 0x0d, + 0x0e, 0x00, }; @@ -81,8 +84,8 @@ static int create_modules(struct gb_endo *endo) /* Depending on the endo type, create a bunch of different modules */ switch (endo->type) { - case 0x0555: - endo_modules = &endo_0555[0]; + case 0x4755: + endo_modules = &endo_4755[0]; break; default: dev_err(&endo->dev, "Unknown endo type 0x%04x, aborting!", @@ -120,7 +123,7 @@ struct gb_endo *gb_endo_create(struct greybus_host_device *hd) // using "fake" numbers. strcpy(&endo->svc.serial_number[0], "042"); strcpy(&endo->svc.version[0], "0.0"); - endo->type = 0x0555; + endo->type = 0x4755; dev_set_name(&endo->dev, "endo-0x%04x", endo->type); retval = device_add(&endo->dev); -- cgit v0.10.2 From 8f8b2297c0a17236ca4b5413e1f737536a8154a1 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 28 Apr 2015 19:40:27 +0530 Subject: greybus: endo: Rename endo's 'type' as 'id' There can be three Endo types: mini, medium and large. And that's what Endo 'type' should refer to. But we have named the 16 bit number that uniquely represents a valid endo, as its type. 'id' seems to be a more suitable name to that instead of 'type'. Lets rename it. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c index b8f6163..b9c7ee6 100644 --- a/drivers/staging/greybus/endo.c +++ b/drivers/staging/greybus/endo.c @@ -82,14 +82,14 @@ static int create_modules(struct gb_endo *endo) u8 *endo_modules; int i; - /* Depending on the endo type, create a bunch of different modules */ - switch (endo->type) { + /* Depending on the endo id, create a bunch of different modules */ + switch (endo->id) { case 0x4755: endo_modules = &endo_4755[0]; break; default: - dev_err(&endo->dev, "Unknown endo type 0x%04x, aborting!", - endo->type); + dev_err(&endo->dev, "Unknown endo id 0x%04x, aborting!", + endo->id); return -EINVAL; } @@ -118,18 +118,18 @@ struct gb_endo *gb_endo_create(struct greybus_host_device *hd) endo->dev.dma_mask = hd->parent->dma_mask; device_initialize(&endo->dev); - // FIXME - determine endo "type" from the SVC + // FIXME - determine endo "id" from the SVC // Also get the version and serial number from the SVC, right now we are // using "fake" numbers. strcpy(&endo->svc.serial_number[0], "042"); strcpy(&endo->svc.version[0], "0.0"); - endo->type = 0x4755; + endo->id = 0x4755; - dev_set_name(&endo->dev, "endo-0x%04x", endo->type); + dev_set_name(&endo->dev, "endo-0x%04x", endo->id); retval = device_add(&endo->dev); if (retval) { - dev_err(hd->parent, "failed to add endo device of type 0x%04x\n", - endo->type); + dev_err(hd->parent, "failed to add endo device of id 0x%04x\n", + endo->id); put_device(&endo->dev); kfree(endo); return NULL; diff --git a/drivers/staging/greybus/endo.h b/drivers/staging/greybus/endo.h index 649093e..a4342aa 100644 --- a/drivers/staging/greybus/endo.h +++ b/drivers/staging/greybus/endo.h @@ -18,7 +18,7 @@ struct gb_svc { struct gb_endo { struct device dev; struct gb_svc svc; - u16 type; + u16 id; }; #define to_gb_endo(d) container_of(d, struct gb_endo, dev) -- cgit v0.10.2 From af6e8b42334c92b2dcbb93e79b0e7ba4f1d51bb4 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 28 Apr 2015 19:51:34 +0530 Subject: greybus: Explicitly mark structures as packed These structures are already marked as __packed, as these are enclosed within: #pragma pack(push, 1) #pragma pack(pop) Lets mark them __packed explicitly. Reviewed-by: Alex Elder Reviewed-by: Johan Hovold Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index e855ada..9096576 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -13,8 +13,6 @@ #ifndef __GREYBUS_MANIFEST_H #define __GREYBUS_MANIFEST_H -#pragma pack(push, 1) - enum greybus_descriptor_type { GREYBUS_TYPE_INVALID = 0x00, GREYBUS_TYPE_INTERFACE = 0x01, @@ -77,7 +75,7 @@ struct greybus_descriptor_string { __u8 length; __u8 id; __u8 string[0]; -}; +} __packed; /* * An interface descriptor describes information about an interface as a whole, @@ -90,7 +88,7 @@ struct greybus_descriptor_interface { __u8 vendor_stringid; __u8 product_stringid; __le64 unique_id; -}; +} __packed; /* * An bundle descriptor defines an identification number and a class for @@ -114,7 +112,7 @@ struct greybus_descriptor_interface { struct greybus_descriptor_bundle { __u8 id; /* interface-relative id (0..) */ __u8 class; -}; +} __packed; /* * A CPort descriptor indicates the id of the bundle within the @@ -126,7 +124,7 @@ struct greybus_descriptor_cport { __u8 bundle; __le16 id; __u8 protocol_id; /* enum greybus_protocol */ -}; +} __packed; /* * A class descriptor defines functionality supplied by a module. @@ -134,12 +132,12 @@ struct greybus_descriptor_cport { */ struct greybus_descriptor_class { __u8 class; /* enum greybus_class_type */ -}; +} __packed; struct greybus_descriptor_header { __le16 size; __u8 type; /* enum greybus_descriptor_type */ -}; +} __packed; struct greybus_descriptor { struct greybus_descriptor_header header; @@ -150,19 +148,17 @@ struct greybus_descriptor { struct greybus_descriptor_cport cport; struct greybus_descriptor_class class; }; -}; +} __packed; struct greybus_manifest_header { __le16 size; __u8 version_major; __u8 version_minor; -}; +} __packed; struct greybus_manifest { struct greybus_manifest_header header; struct greybus_descriptor descriptors[0]; -}; - -#pragma pack(pop) +} __packed; #endif /* __GREYBUS_MANIFEST_H */ diff --git a/drivers/staging/greybus/svc_msg.h b/drivers/staging/greybus/svc_msg.h index cb7bb19..fadc1d7 100644 --- a/drivers/staging/greybus/svc_msg.h +++ b/drivers/staging/greybus/svc_msg.h @@ -13,8 +13,6 @@ #ifndef __SVC_MSG_H #define __SVC_MSG_H -#pragma pack(push, 1) - enum svc_function_id { SVC_FUNCTION_HANDSHAKE = 0x00, SVC_FUNCTION_UNIPRO_NETWORK_MANAGEMENT = 0x01, @@ -33,7 +31,7 @@ struct svc_msg_header { __u8 function_id; /* enum svc_function_id */ __u8 message_type; __le16 payload_length; -}; +} __packed; enum svc_function_handshake_type { SVC_HANDSHAKE_SVC_HELLO = 0x00, @@ -45,21 +43,21 @@ struct svc_function_handshake { __u8 version_major; __u8 version_minor; __u8 handshake_type; /* enum svc_function_handshake_type */ -}; +} __packed; struct svc_function_unipro_set_route { __u8 device_id; -}; +} __packed; struct svc_function_unipro_link_up { __u8 interface_id; /* Interface id within the Endo */ __u8 device_id; -}; +} __packed; struct svc_function_ap_id { __u8 interface_id; __u8 device_id; -}; +} __packed; enum svc_function_management_event { SVC_MANAGEMENT_AP_ID = 0x00, @@ -74,7 +72,7 @@ struct svc_function_unipro_management { struct svc_function_unipro_link_up link_up; struct svc_function_unipro_set_route set_route; }; -}; +} __packed; enum svc_function_hotplug_event { SVC_HOTPLUG_EVENT = 0x00, @@ -85,7 +83,7 @@ struct svc_function_hotplug { __u8 hotplug_event; /* enum svc_function_hotplug_event */ __u8 interface_id; /* Interface id within the Endo */ __u8 data[0]; -}; +} __packed; enum svc_function_power_type { SVC_POWER_BATTERY_STATUS = 0x00, @@ -104,10 +102,10 @@ struct svc_function_power_battery_status { __le16 charge_full; __le16 charge_now; __u8 status; /* enum svc_function_battery_status */ -}; +} __packed; struct svc_function_power_battery_status_request { -}; +} __packed; /* XXX * Each interface carries power, so it's possible these things @@ -121,7 +119,7 @@ struct svc_function_power { struct svc_function_power_battery_status status; struct svc_function_power_battery_status_request request; }; -}; +} __packed; enum svc_function_epm_command_type { SVC_EPM_ENABLE = 0x00, @@ -132,7 +130,7 @@ enum svc_function_epm_command_type { struct svc_function_epm { __u8 epm_command_type; /* enum svc_function_epm_command_type */ __u8 module_id; -}; +} __packed; enum svc_function_suspend_command_type { SVC_SUSPEND_FIXME_1 = 0x00, // FIXME @@ -143,7 +141,7 @@ enum svc_function_suspend_command_type { struct svc_function_suspend { __u8 suspend_command_type; /* enum function_suspend_command_type */ __u8 device_id; -}; +} __packed; struct svc_msg { struct svc_msg_header header; @@ -155,8 +153,6 @@ struct svc_msg { struct svc_function_epm epm; struct svc_function_suspend suspend; }; -}; - -#pragma pack(pop) +} __packed; #endif /* __SVC_MSG_H */ -- cgit v0.10.2 From fa2fbf16f6aaaabee9394edc57dc803b59de6699 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 28 Apr 2015 19:51:35 +0530 Subject: greybus: manifest: Account for padding in string descriptor String descriptors are padded towards the end to align them to 4 byte boundaries. Take that into account while calculating expected size. Reviewed-by: Alex Elder Reviewed-by: Johan Hovold Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index d6cafeb..1253663 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -100,6 +100,9 @@ static int identify_descriptor(struct gb_interface *intf, case GREYBUS_TYPE_STRING: expected_size += sizeof(struct greybus_descriptor_string); expected_size += desc->string.length; + + /* String descriptors are padded to 4 byte boundaries */ + expected_size = ALIGN(expected_size, 4); break; case GREYBUS_TYPE_INTERFACE: expected_size += sizeof(struct greybus_descriptor_interface); -- cgit v0.10.2 From 55b930cd17a7cd66a1fb2a587660a344ea5a9ee2 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 29 Apr 2015 11:02:08 +0530 Subject: greybus: manifest: Warn if descriptor size > expected size A descriptor passed to AP can be bigger than what AP expects, if manifest's minor version is higher with same major number as the AP. As it can have some extra data in descriptor. But, if AP and manifest versions are identical, or if the AP's minor version is greater than the manifest version, we should at least warn (if not fail). Doing this would require some changes to record the manifest version somewhere reachable by identify_descriptor(). For now, just warn if descriptor is bigger than expected. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 1253663..2346ead 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -129,6 +129,13 @@ static int identify_descriptor(struct gb_interface *intf, return -EINVAL; } + /* Descriptor bigger than what we expect */ + if (desc_size > expected_size) { + pr_warn("%s descriptor size mismatch (want %zu got %zu)\n", + get_descriptor_type_string(desc_header->type), + expected_size, desc_size); + } + descriptor = kzalloc(sizeof(*descriptor), GFP_KERNEL); if (!descriptor) return -ENOMEM; -- cgit v0.10.2 From 22fd2a8ade59bb97f0a64282ba5b3903ba3e9e89 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 17 Apr 2015 14:41:47 -0500 Subject: greybus: bundle: use kstrdup() for state file The kernfs code guarantees we'll get a NUL-terminated buffer. Use kstrdup() rather than kzalloc() + memcpy() in state_store() making it slightly clearer what we're doing. This has the added benefit of guaranteeing that the stored string has no NUL character inside it. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index e7b2199..2047e17 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -48,12 +48,10 @@ static ssize_t state_store(struct device *dev, struct device_attribute *attr, struct gb_bundle *bundle = to_gb_bundle(dev); kfree(bundle->state); - bundle->state = kzalloc(size + 1, GFP_KERNEL); + bundle->state = kstrdup(buf, GFP_KERNEL); if (!bundle->state) return -ENOMEM; - memcpy(bundle->state, buf, size); - /* Tell userspace that the file contents changed */ sysfs_notify(&bundle->dev.kobj, NULL, "state"); -- cgit v0.10.2 From 8a5286ed2a0a7d394817a63ae37ae54608a4d3b4 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 28 Apr 2015 19:51:37 +0530 Subject: greybus: manifest: Remove vendor, product and unique-id from interface descriptor These should come from control protocol instead. For now, initialize this statically with a FIXME to not forget it later. Reviewed-by: Alex Elder Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 9096576..1fb0131 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -82,12 +82,9 @@ struct greybus_descriptor_string { * *not* the functions within it. */ struct greybus_descriptor_interface { - __le16 vendor; - __le16 product; __le16 version; // TODO - remove after Dec demo. __u8 vendor_stringid; __u8 product_stringid; - __le64 unique_id; } __packed; /* diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 2346ead..de234d2 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -304,9 +304,11 @@ static bool gb_manifest_parse_interface(struct gb_interface *intf, goto out_free_vendor_string; } - intf->vendor = le16_to_cpu(desc_intf->vendor); - intf->product = le16_to_cpu(desc_intf->product); - intf->unique_id = le64_to_cpu(desc_intf->unique_id); + // FIXME + // Vendor, Product and Unique id must come via control protocol + intf->vendor = 0xffff; + intf->product = 0x0001; + intf->unique_id = 0; /* Release the interface descriptor, now that we're done with it */ release_manifest_descriptor(interface_desc); -- cgit v0.10.2 From 20f087ec5c8c746020c91d296339eebe4d8ed4dd Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 28 Apr 2015 19:51:38 +0530 Subject: greybus: manifest: drop interface-version field It is not required anymore. Drop it. Reviewed-by: Alex Elder Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 1fb0131..bea4de2 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -82,7 +82,6 @@ struct greybus_descriptor_string { * *not* the functions within it. */ struct greybus_descriptor_interface { - __le16 version; // TODO - remove after Dec demo. __u8 vendor_stringid; __u8 product_stringid; } __packed; -- cgit v0.10.2 From b022515ee64b38baed81b83a47783cbb52b9c5f9 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 28 Apr 2015 19:51:39 +0530 Subject: greybus: Remove class descriptor We carry this information as part of bundle descriptor now and this can be removed. Reviewed-by: Alex Elder Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index bea4de2..60f183a 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -19,7 +19,6 @@ enum greybus_descriptor_type { GREYBUS_TYPE_STRING = 0x02, GREYBUS_TYPE_BUNDLE = 0x03, GREYBUS_TYPE_CPORT = 0x04, - GREYBUS_TYPE_CLASS = 0x05, }; enum greybus_protocol { @@ -122,14 +121,6 @@ struct greybus_descriptor_cport { __u8 protocol_id; /* enum greybus_protocol */ } __packed; -/* - * A class descriptor defines functionality supplied by a module. - * Beyond that, not much else is defined yet... - */ -struct greybus_descriptor_class { - __u8 class; /* enum greybus_class_type */ -} __packed; - struct greybus_descriptor_header { __le16 size; __u8 type; /* enum greybus_descriptor_type */ @@ -142,7 +133,6 @@ struct greybus_descriptor { struct greybus_descriptor_interface interface; struct greybus_descriptor_bundle bundle; struct greybus_descriptor_cport cport; - struct greybus_descriptor_class class; }; } __packed; diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index de234d2..597ba70 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -26,8 +26,6 @@ static const char *get_descriptor_type_string(u8 type) return "cport"; case GREYBUS_TYPE_BUNDLE: return "bundle"; - case GREYBUS_TYPE_CLASS: - return "class"; default: WARN_ON(1); return "unknown"; @@ -113,9 +111,6 @@ static int identify_descriptor(struct gb_interface *intf, case GREYBUS_TYPE_CPORT: expected_size += sizeof(struct greybus_descriptor_cport); break; - case GREYBUS_TYPE_CLASS: - pr_warn("class descriptor found (ignoring)\n"); - break; case GREYBUS_TYPE_INVALID: default: pr_err("invalid descriptor type (%hhu)\n", desc_header->type); -- cgit v0.10.2 From 499ee955a132c772d14b839bcec3adef2eebcb6b Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 28 Apr 2015 19:51:40 +0530 Subject: greybus: Explicitly add pad-bytes to manifest descriptors Explicitly add pad-bytes to manifest descriptors to match their layout in greybus specification. Reviewed-by: Alex Elder Reviewed-by: Johan Hovold Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 60f183a..9d32a4c 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -83,6 +83,7 @@ struct greybus_descriptor_string { struct greybus_descriptor_interface { __u8 vendor_stringid; __u8 product_stringid; + __u8 pad[2]; } __packed; /* @@ -107,6 +108,7 @@ struct greybus_descriptor_interface { struct greybus_descriptor_bundle { __u8 id; /* interface-relative id (0..) */ __u8 class; + __u8 pad[2]; } __packed; /* @@ -124,6 +126,7 @@ struct greybus_descriptor_cport { struct greybus_descriptor_header { __le16 size; __u8 type; /* enum greybus_descriptor_type */ + __u8 pad; } __packed; struct greybus_descriptor { -- cgit v0.10.2 From f03eec87720d3427443b64f2d1b237b85d5c68b4 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 28 Apr 2015 19:51:41 +0530 Subject: greybus: Move id-field before bundle-field in CPort Descriptor. Note that this also makes sure the id-field is naturally aligned in case we ever were to remove the __packed attribute. Reviewed-by: Alex Elder Reviewed-by: Johan Hovold Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 9d32a4c..05af029 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -118,8 +118,8 @@ struct greybus_descriptor_bundle { * exchanged using the CPort. */ struct greybus_descriptor_cport { - __u8 bundle; __le16 id; + __u8 bundle; __u8 protocol_id; /* enum greybus_protocol */ } __packed; -- cgit v0.10.2 From a549be518623e0948213bdacd338183bba033229 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 1 May 2015 20:41:00 +0200 Subject: greybus: battery: update for 4.1 power supply api changes The 4.1-rc1 kernel changed the power supply apis such that the structures are now owned by the power supply core, and not the individual drivers. This broke the greybus battery driver, so update it to support both the old and the new apis. The API changes were such that I can't "hide" them in kernel_ver.h, but rather the driver itself needs to have ugly #ifdefs in it. I tried to keep it to a minimum, making a sub-function for initializing the power supply device that is implemented differently for different kernel versions. When this is submitted upstream, or if we ever move our AP development to 4.1 or greater, the support for older kernels can be removed. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Viresh Kumar diff --git a/drivers/staging/greybus/battery.c b/drivers/staging/greybus/battery.c index b968d14..eb688c9 100644 --- a/drivers/staging/greybus/battery.c +++ b/drivers/staging/greybus/battery.c @@ -7,6 +7,7 @@ * Released under the GPLv2 only. */ +#include #include #include #include @@ -14,7 +15,19 @@ #include "greybus.h" struct gb_battery { + /* + * The power supply api changed in 4.1, so handle both the old + * and new apis in the same driver for now, until this is merged + * upstream, when all of these version checks can be removed. + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0) struct power_supply bat; +#define to_gb_battery(x) container_of(x, struct gb_battery, bat) +#else + struct power_supply *bat; + struct power_supply_desc desc; +#define to_gb_battery(x) power_supply_get_drvdata(x) +#endif // FIXME // we will want to keep the battery stats in here as we will be getting // updates from the SVC "on the fly" so we don't have to always go ask @@ -24,7 +37,6 @@ struct gb_battery { u8 version_minor; }; -#define to_gb_battery(x) container_of(x, struct gb_battery, bat) /* Version of the Greybus battery protocol we support */ #define GB_BATTERY_VERSION_MAJOR 0x00 @@ -283,10 +295,56 @@ static enum power_supply_property battery_props[] = { POWER_SUPPLY_PROP_VOLTAGE_NOW, }; +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0) +static int init_and_register(struct gb_connection *connection, + struct gb_battery *gb) +{ + int retval; + + // FIXME - get a better (i.e. unique) name + // FIXME - anything else needs to be set? + gb->bat.name = "gb_battery"; + gb->bat.type = POWER_SUPPLY_TYPE_BATTERY; + gb->bat.properties = battery_props; + gb->bat.num_properties = ARRAY_SIZE(battery_props); + gb->bat.get_property = get_property; + + retval = power_supply_register(&connection->bundle->intf->dev, + &gb->bat); + if (retval) + kfree(gb); + return retval; +} +#else +static int init_and_register(struct gb_connection *connection, + struct gb_battery *gb) +{ + struct power_supply_config cfg = {}; + int retval = 0; + + cfg.drv_data = gb; + + // FIXME - get a better (i.e. unique) name + // FIXME - anything else needs to be set? + gb->desc.name = "gb_battery"; + gb->desc.type = POWER_SUPPLY_TYPE_BATTERY; + gb->desc.properties = battery_props; + gb->desc.num_properties = ARRAY_SIZE(battery_props); + gb->desc.get_property = get_property; + + gb->bat = power_supply_register(&connection->bundle->intf->dev, + &gb->desc, &cfg); + if (IS_ERR(gb->bat)) { + retval = PTR_ERR(gb->bat); + kfree(gb); + } + return retval; +} +#endif + static int gb_battery_connection_init(struct gb_connection *connection) { struct gb_battery *gb; - struct power_supply *b; int retval; gb = kzalloc(sizeof(*gb), GFP_KERNEL); @@ -303,29 +361,18 @@ static int gb_battery_connection_init(struct gb_connection *connection) return retval; } - b = &gb->bat; - // FIXME - get a better (i.e. unique) name - // FIXME - anything else needs to be set? - b->name = "gb_battery"; - b->type = POWER_SUPPLY_TYPE_BATTERY, - b->properties = battery_props, - b->num_properties = ARRAY_SIZE(battery_props), - b->get_property = get_property, - - retval = power_supply_register(&connection->bundle->intf->dev, b); - if (retval) { - kfree(gb); - return retval; - } - - return 0; + return init_and_register(connection, gb); } static void gb_battery_connection_exit(struct gb_connection *connection) { struct gb_battery *gb = connection->private; +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0) power_supply_unregister(&gb->bat); +#else + power_supply_unregister(gb->bat); +#endif kfree(gb); } -- cgit v0.10.2 From 99a4bd5902224065debff524624800bd9806419e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 1 May 2015 21:04:47 +0200 Subject: greybus: kernel_ver.h: fix leading space coding style issues When cutting and pasting some of the ATTR macros into kernel_ver.h, I dropped the tabs. Fix this up and make checkpatch.pl happy. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Viresh Kumar diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index 92eb024..891090f 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -18,14 +18,14 @@ #ifndef __ATTR_WO #define __ATTR_WO(_name) { \ - .attr = { .name = __stringify(_name), .mode = S_IWUSR }, \ - .store = _name##_store, \ + .attr = { .name = __stringify(_name), .mode = S_IWUSR }, \ + .store = _name##_store, \ } #endif #ifndef __ATTR_RW #define __ATTR_RW(_name) __ATTR(_name, (S_IWUSR | S_IRUGO), \ - _name##_show, _name##_store) + _name##_show, _name##_store) #endif #ifndef DEVICE_ATTR_RO -- cgit v0.10.2 From 3906a59c96ac770d54728d2cbd6564cda3b2cdd9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 1 May 2015 21:05:03 +0200 Subject: greybus: kernel_ver.h: add a ' ' character to KERNEL_VERSION() You should always put a space after a ',', so do it for the KERNEL_VERSION() macro as well. This makes checkpatch.pl happy also. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Viresh Kumar diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index 891090f..83d08da 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -60,7 +60,7 @@ #include #include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0) static inline void gb_gpiochip_remove(struct gpio_chip *chip) { gpiochip_remove(chip); @@ -77,7 +77,7 @@ static inline void gb_gpiochip_remove(struct gpio_chip *chip) * ATTRIBUTE_GROUPS showed up in 3.11-rc2, but we need to build on 3.10, so add * it here. */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) #include #define ATTRIBUTE_GROUPS(name) \ -- cgit v0.10.2 From 63ca78b9abe4d216aec08724c9677b86481fa271 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 1 May 2015 21:05:29 +0200 Subject: greybus: kernel_ver.h: add a blank line after a variable definition checkpatch reminds us that a blank line should go after a variable definition, so fix it up here. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Viresh Kumar diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index 83d08da..e63d6cb 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -69,6 +69,7 @@ static inline void gb_gpiochip_remove(struct gpio_chip *chip) static inline void gb_gpiochip_remove(struct gpio_chip *chip) { int ret; + ret = gpiochip_remove(chip); } #endif -- cgit v0.10.2 From f487c802cba56b5f38c5cb5d2eb32b9562f50dde Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 1 May 2015 21:05:50 +0200 Subject: greybus: protocol.h: macros should not have a trailing ';' Remove the trailing ';' character from the gb_protocol_driver() macro as it's not needed and is bad coding style. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Viresh Kumar diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index 82d9e81..d16a582 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -97,7 +97,7 @@ static void __exit protocol_exit(void) \ { \ gb_protocol_deregister(__protocol); \ } \ -module_exit(protocol_exit); +module_exit(protocol_exit) /* * Macro to create get_version() routine for protocols -- cgit v0.10.2 From e80d09af1e8a23c1d9c9da99540855cde21e00a1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 1 May 2015 21:06:12 +0200 Subject: greybus: protocol.h: fix up long lines in define_get_version() No need to go past 80 characters for the define_get_version macro, so fix up the indentation to not do so. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Viresh Kumar diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index d16a582..495d13a 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -110,10 +110,10 @@ static int get_version(struct __device *dev) \ struct gb_protocol_version_response response; \ int retval; \ \ - retval = gb_protocol_get_version(dev->connection, \ - GB_##__protocol##_TYPE_PROTOCOL_VERSION,\ - NULL, 0, &response, \ - GB_##__protocol##_VERSION_MAJOR); \ + retval = gb_protocol_get_version(dev->connection, \ + GB_##__protocol##_TYPE_PROTOCOL_VERSION,\ + NULL, 0, &response, \ + GB_##__protocol##_VERSION_MAJOR); \ if (retval) \ return retval; \ \ -- cgit v0.10.2 From c13c8bf0cccd6a9daf8ea02919aecaa45c842fc7 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 5 May 2015 11:04:22 -0500 Subject: greybus: es2: fix driver name collision with es1 Both ES1 and ES2 drivers cannot be loaded due to a driver name conflict. Give ES2 driver the correct name. Signed-off-by: Rob Herring Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index efdd48d..cc73fbd 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -686,7 +686,7 @@ error: } static struct usb_driver es1_ap_driver = { - .name = "es1_ap_driver", + .name = "es2_ap_driver", .probe = ap_probe, .disconnect = ap_disconnect, .id_table = id_table, -- cgit v0.10.2 From 9ade6d312287fd1729a02e349f5f23483ffc4e1c Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 7 May 2015 13:00:20 -0500 Subject: greybus: battery: free struct on error in caller When a battery connection is initialized, a gb_battery structure for it is allocated in gb_battery_connection_init(). Currently that function ends by calling init_and_register(); in the event an error occurs, init_and_register() is responsible for freeing the allocated gb_battery structure. Make the code a bit better balanced by having the function that allocates the structure be responsible for freeing it in case of error. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery.c b/drivers/staging/greybus/battery.c index eb688c9..c815338 100644 --- a/drivers/staging/greybus/battery.c +++ b/drivers/staging/greybus/battery.c @@ -299,8 +299,6 @@ static enum power_supply_property battery_props[] = { static int init_and_register(struct gb_connection *connection, struct gb_battery *gb) { - int retval; - // FIXME - get a better (i.e. unique) name // FIXME - anything else needs to be set? gb->bat.name = "gb_battery"; @@ -309,18 +307,13 @@ static int init_and_register(struct gb_connection *connection, gb->bat.num_properties = ARRAY_SIZE(battery_props); gb->bat.get_property = get_property; - retval = power_supply_register(&connection->bundle->intf->dev, - &gb->bat); - if (retval) - kfree(gb); - return retval; + return power_supply_register(&connection->bundle->intf->dev, &gb->bat); } #else static int init_and_register(struct gb_connection *connection, struct gb_battery *gb) { struct power_supply_config cfg = {}; - int retval = 0; cfg.drv_data = gb; @@ -334,11 +327,10 @@ static int init_and_register(struct gb_connection *connection, gb->bat = power_supply_register(&connection->bundle->intf->dev, &gb->desc, &cfg); - if (IS_ERR(gb->bat)) { - retval = PTR_ERR(gb->bat); - kfree(gb); - } - return retval; + if (IS_ERR(gb->bat)) + return PTR_ERR(gb->bat); + + return 0; } #endif @@ -356,12 +348,14 @@ static int gb_battery_connection_init(struct gb_connection *connection) /* Check the version */ retval = get_version(gb); - if (retval) { + if (retval) + goto out; + retval = init_and_register(connection, gb); +out: + if (retval) kfree(gb); - return retval; - } - return init_and_register(connection, gb); + return retval; } static void gb_battery_connection_exit(struct gb_connection *connection) -- cgit v0.10.2 From 5c58640d8d66504c43c062e6e7d4ed0ade6bde9e Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 7 May 2015 13:00:21 -0500 Subject: greybus: battery: use feature tag rather than kernel version Conditionally define a new symbol DRIVER_OWNS_PSY_STRUCT, which is set in "kernel_ver.h" based on on the kernel version. Use it to distinguish code used for kernels that differ in whether a power supply structure is owned by the driver, or by the power supply core. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery.c b/drivers/staging/greybus/battery.c index c815338..aad1749 100644 --- a/drivers/staging/greybus/battery.c +++ b/drivers/staging/greybus/battery.c @@ -7,7 +7,6 @@ * Released under the GPLv2 only. */ -#include #include #include #include @@ -20,7 +19,7 @@ struct gb_battery { * and new apis in the same driver for now, until this is merged * upstream, when all of these version checks can be removed. */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0) +#ifdef DRIVER_OWNS_PSY_STRUCT struct power_supply bat; #define to_gb_battery(x) container_of(x, struct gb_battery, bat) #else @@ -295,7 +294,7 @@ static enum power_supply_property battery_props[] = { POWER_SUPPLY_PROP_VOLTAGE_NOW, }; -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0) +#ifdef DRIVER_OWNS_PSY_STRUCT static int init_and_register(struct gb_connection *connection, struct gb_battery *gb) { @@ -362,7 +361,7 @@ static void gb_battery_connection_exit(struct gb_connection *connection) { struct gb_battery *gb = connection->private; -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0) +#ifdef DRIVER_OWNS_PSY_STRUCT power_supply_unregister(&gb->bat); #else power_supply_unregister(gb->bat); diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index e63d6cb..8b8e712 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -15,6 +15,12 @@ #define __GREYBUS_KERNEL_VER_H #include +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0) +/* Commit: 297d716 power_supply: Change ownership from driver to core */ +#define DRIVER_OWNS_PSY_STRUCT +#endif #ifndef __ATTR_WO #define __ATTR_WO(_name) { \ @@ -57,7 +63,6 @@ * 3.17, which they explicitly changed in the 3.17 kernel. Consistency is * overrated. */ -#include #include #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0) -- cgit v0.10.2 From 6d653370c0a67ff9b9b0d8249182d537859b528c Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 7 May 2015 13:03:52 -0500 Subject: greybus: eliminate extra response flag definitions All protocols use the same value to distinguish between request and response message types. This is a requirement. Use GB_MESSAGE_TYPE_RESPONSE rather than GB_OPERATION_TYPE_RESPONSE for the name of the flag used to distiguish between request and response messages. Get rid of the redundant response flag definitions that are associated with specific protocols. Describe the symbolic values as "operation types" rather than "message types" where they are defined. The message type for a request is the same as the operation type; the message type for a response is the operation type OR'd with GB_MESSAGE_TYPE_RESPONSE. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpbridge.h b/drivers/staging/greybus/gpbridge.h index e230188..85d8019 100644 --- a/drivers/staging/greybus/gpbridge.h +++ b/drivers/staging/greybus/gpbridge.h @@ -65,7 +65,6 @@ #define GB_I2C_TYPE_TIMEOUT 0x03 #define GB_I2C_TYPE_RETRIES 0x04 #define GB_I2C_TYPE_TRANSFER 0x05 -#define GB_I2C_TYPE_RESPONSE 0x80 /* OR'd with rest */ #define GB_I2C_RETRIES_DEFAULT 3 #define GB_I2C_TIMEOUT_DEFAULT 1000 /* milliseconds */ @@ -133,7 +132,6 @@ struct gb_i2c_transfer_response { #define GB_GPIO_TYPE_IRQ_MASK 0x0d #define GB_GPIO_TYPE_IRQ_UNMASK 0x0e #define GB_GPIO_TYPE_IRQ_EVENT 0x0f -#define GB_GPIO_TYPE_RESPONSE 0x80 /* OR'd with rest */ #define GB_GPIO_DEBOUNCE_USEC_DEFAULT 0 /* microseconds */ @@ -223,7 +221,7 @@ struct gb_gpio_irq_event_request { #define GB_PWM_VERSION_MAJOR 0x00 #define GB_PWM_VERSION_MINOR 0x01 -/* Greybus PWM request types */ +/* Greybus PWM operation types */ #define GB_PWM_TYPE_INVALID 0x00 #define GB_PWM_TYPE_PROTOCOL_VERSION 0x01 #define GB_PWM_TYPE_PWM_COUNT 0x02 @@ -233,7 +231,6 @@ struct gb_gpio_irq_event_request { #define GB_PWM_TYPE_POLARITY 0x06 #define GB_PWM_TYPE_ENABLE 0x07 #define GB_PWM_TYPE_DISABLE 0x08 -#define GB_PWM_TYPE_RESPONSE 0x80 /* OR'd with rest */ /* pwm count request has no payload */ struct gb_pwm_count_response { diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index 556cf9b..00dc7e5 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -20,7 +20,7 @@ #define GB_HID_VERSION_MAJOR 0x00 #define GB_HID_VERSION_MINOR 0x01 -/* Greybus HID request types */ +/* Greybus HID operation types */ #define GB_HID_TYPE_INVALID 0x00 #define GB_HID_TYPE_PROTOCOL_VERSION 0x01 #define GB_HID_TYPE_GET_DESC 0x02 @@ -30,7 +30,6 @@ #define GB_HID_TYPE_GET_REPORT 0x06 #define GB_HID_TYPE_SET_REPORT 0x07 #define GB_HID_TYPE_IRQ_EVENT 0x08 -#define GB_HID_TYPE_RESPONSE 0x80 /* OR'd with rest */ /* Report type */ #define GB_HID_INPUT_REPORT 0 diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 3639e27..1ec930c 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -396,7 +396,7 @@ bool gb_operation_response_alloc(struct gb_operation *operation, struct gb_message *response; u8 type; - type = operation->type | GB_OPERATION_TYPE_RESPONSE; + type = operation->type | GB_MESSAGE_TYPE_RESPONSE; response = gb_operation_message_alloc(hd, type, response_size, GFP_KERNEL); if (!response) @@ -508,8 +508,8 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, { if (WARN_ON_ONCE(type == GB_OPERATION_TYPE_INVALID)) return NULL; - if (WARN_ON_ONCE(type & GB_OPERATION_TYPE_RESPONSE)) - type &= ~GB_OPERATION_TYPE_RESPONSE; + if (WARN_ON_ONCE(type & GB_MESSAGE_TYPE_RESPONSE)) + type &= ~GB_MESSAGE_TYPE_RESPONSE; return gb_operation_create_common(connection, type, request_size, response_size); @@ -855,7 +855,7 @@ void gb_connection_recv(struct gb_connection *connection, } operation_id = le16_to_cpu(header.operation_id); - if (header.type & GB_OPERATION_TYPE_RESPONSE) + if (header.type & GB_MESSAGE_TYPE_RESPONSE) gb_connection_recv_response(connection, operation_id, header.result, data, msg_size); else diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 38684f2..82b8fe5 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -24,7 +24,7 @@ struct gb_operation; * The top bit of the type in an operation message header indicates * whether the message is a request (bit clear) or response (bit set) */ -#define GB_OPERATION_TYPE_RESPONSE ((u8)0x80) +#define GB_MESSAGE_TYPE_RESPONSE ((u8)0x80) enum gb_operation_result { GB_OP_SUCCESS = 0x00, diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index 639c9cd..731639a 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -66,7 +66,7 @@ struct gb_spi { #define GB_SPI_FLAG_NO_RX BIT(1) /* can't do buffer read */ #define GB_SPI_FLAG_NO_TX BIT(2) /* can't do buffer write */ -/* Greybus spi request types */ +/* Greybus spi operation types */ #define GB_SPI_TYPE_INVALID 0x00 #define GB_SPI_TYPE_PROTOCOL_VERSION 0x01 #define GB_SPI_TYPE_MODE 0x02 @@ -74,7 +74,6 @@ struct gb_spi { #define GB_SPI_TYPE_BITS_PER_WORD_MASK 0x04 #define GB_SPI_TYPE_NUM_CHIPSELECT 0x05 #define GB_SPI_TYPE_TRANSFER 0x06 -#define GB_SPI_TYPE_RESPONSE 0x80 /* OR'd with rest */ /* mode request has no payload */ struct gb_spi_mode_response { diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 51e4f7b..35ab3ca 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -37,7 +37,7 @@ #define GB_UART_VERSION_MAJOR 0x00 #define GB_UART_VERSION_MINOR 0x01 -/* Greybus UART request types */ +/* Greybus UART operation types */ #define GB_UART_TYPE_INVALID 0x00 #define GB_UART_TYPE_PROTOCOL_VERSION 0x01 #define GB_UART_TYPE_SEND_DATA 0x02 @@ -46,7 +46,6 @@ #define GB_UART_TYPE_SET_CONTROL_LINE_STATE 0x05 #define GB_UART_TYPE_SET_BREAK 0x06 #define GB_UART_TYPE_SERIAL_STATE 0x07 /* Unsolicited data */ -#define GB_UART_TYPE_RESPONSE 0x80 /* OR'd with rest */ struct gb_uart_send_data_request { __le16 size; diff --git a/drivers/staging/greybus/vibrator.c b/drivers/staging/greybus/vibrator.c index 2943a9b..aefd2cd 100644 --- a/drivers/staging/greybus/vibrator.c +++ b/drivers/staging/greybus/vibrator.c @@ -27,12 +27,11 @@ struct gb_vibrator_device { #define GB_VIBRATOR_VERSION_MAJOR 0x00 #define GB_VIBRATOR_VERSION_MINOR 0x01 -/* Greybus Vibrator request types */ +/* Greybus Vibrator operation types */ #define GB_VIBRATOR_TYPE_INVALID 0x00 #define GB_VIBRATOR_TYPE_PROTOCOL_VERSION 0x01 #define GB_VIBRATOR_TYPE_ON 0x02 #define GB_VIBRATOR_TYPE_OFF 0x03 -#define GB_VIBRATOR_TYPE_RESPONSE 0x80 /* OR'd with rest */ struct gb_vibrator_on_request { __le16 timeout_ms; -- cgit v0.10.2 From a4749bbeee31204a48fc3bf10c80bb88cf52bab5 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Fri, 8 May 2015 12:57:36 -0700 Subject: greybus: gb-audio: Add integrated greybus audio driver So here's the current greybus audio driver, which I wanted to send out for more serious review and consideration for merging. I've tried to integrate much of the feedback from the last round and most of the hotplug issues that I've found have been resolved. I've tested this via gbsim, and the Android ARA HAL layer seems to work with it. Mark has also successfully played audio with this driver, adding a few hacks to get the codec's i2c connection to probe. Current issues: * Hotplug problem - When gbsim is killed, or the module removed, the greybus driver gets stuck since the android mediaserver process is holding the audio device open. Killing the mediaserver allows things to clean up and allows greybus to accept new gbsim connections. I have a workaround patch to the soc-core.c logic which converts the snd_card_free() call to snd_card_free_when_closed() which allows the greybus connection cleanup to finish. Remaining todos: * Probably need to break apart the mgmt_setup function to integrate better with the constraint logic. I took a really basic stab at this, but more is probably needed. * Figure out how to properly find and tie in the codec's I2C bus-id to the driver. This code requires that the kernel support the following config options, which I've enabled in a separate kernel patch: CONFIG_SND_SIMPLE_CARD CONFIG_SND_SOC_SPDIF CONFIG_SND_SOC_RT5645 I really can't calim to be the sole author of this, since many many fixes and tweaks that have been folded in have come from Mark Greer. His analsysis and debugging is really what has made this dummy-framework driver evolve into an actual audio driver. So much credit and thanks to Mark! Signed-off-by: John Stultz Signed-off-by: Mark A. Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 9945cb8..5158d87 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -10,7 +10,7 @@ greybus-y := core.o \ protocol.o \ operation.o -gb-phy-y := gpb.o \ +gb-phy-y := gpb.o \ sdio.o \ uart.o \ pwm.o \ @@ -18,7 +18,11 @@ gb-phy-y := gpb.o \ hid.o \ i2c.o \ spi.o \ - usb.o + usb.o \ + audio.o \ + audio-pcm.o \ + audio-dai.o \ + audio-gb-cmds.o # Prefix all modules with gb- gb-vibrator-y := vibrator.o diff --git a/drivers/staging/greybus/audio-dai.c b/drivers/staging/greybus/audio-dai.c new file mode 100644 index 0000000..f2c8ca0 --- /dev/null +++ b/drivers/staging/greybus/audio-dai.c @@ -0,0 +1,103 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "greybus.h" +#include "gpbridge.h" +#include "audio.h" + +/* + * This is the greybus cpu dai logic. It really doesn't do much + * other then provide the TRIGGER_START/STOP hooks that start + * and stop the timer sending audio data in the pcm logic. + */ + + +static int gb_dai_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct gb_snd *snd_dev; + + + snd_dev = snd_soc_dai_get_drvdata(rtd->cpu_dai); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + gb_pcm_hrtimer_start(snd_dev); + break; + case SNDRV_PCM_TRIGGER_STOP: + gb_pcm_hrtimer_stop(snd_dev); + break; + default: + return -EINVAL; + } + return 0; +} + +/* + * XXX This is annoying, if we don't have a set_fmt function + * the subsystem returns -ENOTSUPP, which causes applications + * to fail, so add a dummy function here. + */ +static int gb_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + return 0; +} + +static const struct snd_soc_dai_ops gb_dai_ops = { + .trigger = gb_dai_trigger, + .set_fmt = gb_dai_set_fmt, +}; + +struct snd_soc_dai_driver gb_cpu_dai = { + .name = "gb-cpu-dai", + .playback = { + .rates = GB_RATES, + .formats = GB_FMTS, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &gb_dai_ops, +}; + +static const struct snd_soc_component_driver gb_soc_component = { + .name = "gb-component", +}; + +static int gb_plat_probe(struct platform_device *pdev) +{ + struct gb_snd *snd_dev; + int ret; + + snd_dev = (struct gb_snd *)pdev->dev.platform_data; + dev_set_drvdata(&pdev->dev, snd_dev); + + ret = snd_soc_register_component(&pdev->dev, &gb_soc_component, + &gb_cpu_dai, 1); + return ret; +} + +static int gb_plat_remove(struct platform_device *pdev) +{ + snd_soc_unregister_component(&pdev->dev); + snd_soc_unregister_platform(&pdev->dev); + return 0; +} + +struct platform_driver gb_audio_plat_driver = { + .driver = { + .name = "gb-dai-audio", + }, + .probe = gb_plat_probe, + .remove = gb_plat_remove, +}; diff --git a/drivers/staging/greybus/audio-gb-cmds.c b/drivers/staging/greybus/audio-gb-cmds.c new file mode 100644 index 0000000..ef31916 --- /dev/null +++ b/drivers/staging/greybus/audio-gb-cmds.c @@ -0,0 +1,207 @@ +#include +#include "greybus.h" +#include "gpbridge.h" +#include "audio.h" + +#define GB_I2S_MGMT_VERSION_MAJOR 0x00 +#define GB_I2S_MGMT_VERSION_MINOR 0x01 + +#define GB_I2S_DATA_VERSION_MAJOR 0x00 +#define GB_I2S_MGMT_VERSION_MINOR 0x01 + +/*********************************** + * GB I2S helper functions + ***********************************/ +int gb_i2s_mgmt_get_version(struct gb_connection *connection) +{ + struct gb_protocol_version_response response; + + memset(&response, 0, sizeof(response)); + return gb_protocol_get_version(connection, + GB_I2S_MGMT_TYPE_PROTOCOL_VERSION, + NULL, 0, &response, + GB_I2S_MGMT_VERSION_MAJOR); +} + +int gb_i2s_data_get_version(struct gb_connection *connection) +{ + struct gb_protocol_version_response response; + + memset(&response, 0, sizeof(response)); + return gb_protocol_get_version(connection, + GB_I2S_DATA_TYPE_PROTOCOL_VERSION, + NULL, 0, &response, + GB_I2S_DATA_VERSION_MAJOR); +} + +int gb_i2s_mgmt_activate_cport(struct gb_connection *connection, + uint16_t cport) +{ + struct gb_i2s_mgmt_activate_cport_request request; + + memset(&request, 0, sizeof(request)); + request.cport = cport; + + return gb_operation_sync(connection, GB_I2S_MGMT_TYPE_ACTIVATE_CPORT, + &request, sizeof(request), NULL, 0); +} + +int gb_i2s_mgmt_deactivate_cport(struct gb_connection *connection, + uint16_t cport) +{ + struct gb_i2s_mgmt_deactivate_cport_request request; + + memset(&request, 0, sizeof(request)); + request.cport = cport; + + return gb_operation_sync(connection, GB_I2S_MGMT_TYPE_DEACTIVATE_CPORT, + &request, sizeof(request), NULL, 0); +} + +int gb_i2s_mgmt_get_supported_configurations( + struct gb_connection *connection, + struct gb_i2s_mgmt_get_supported_configurations_response *get_cfg, + size_t size) +{ + return gb_operation_sync(connection, + GB_I2S_MGMT_TYPE_GET_SUPPORTED_CONFIGURATIONS, + NULL, 0, get_cfg, size); +} + +int gb_i2s_mgmt_set_configuration(struct gb_connection *connection, + struct gb_i2s_mgmt_set_configuration_request *set_cfg) +{ + return gb_operation_sync(connection, GB_I2S_MGMT_TYPE_SET_CONFIGURATION, + set_cfg, sizeof(*set_cfg), NULL, 0); +} + +int gb_i2s_mgmt_set_samples_per_message( + struct gb_connection *connection, + uint16_t samples_per_message) +{ + struct gb_i2s_mgmt_set_samples_per_message_request request; + + memset(&request, 0, sizeof(request)); + request.samples_per_message = samples_per_message; + + return gb_operation_sync(connection, + GB_I2S_MGMT_TYPE_SET_SAMPLES_PER_MESSAGE, + &request, sizeof(request), NULL, 0); +} + +/* + * XXX This is sort of a generic "setup" function which probably needs + * to be broken up, and tied into the constraints. + * + * I'm on the fence if we should just dictate that we only support + * 48k, 16bit, 2 channel, and avoid doign the whole probe for configurations + * and then picking one. + */ +int gb_i2s_mgmt_setup(struct gb_connection *connection) +{ + struct gb_i2s_mgmt_get_supported_configurations_response *get_cfg; + struct gb_i2s_mgmt_set_configuration_request set_cfg; + struct gb_i2s_mgmt_configuration *cfg; + size_t size; + int i, ret; + + size = sizeof(*get_cfg) + + (CONFIG_COUNT_MAX * sizeof(get_cfg->config[0])); + + get_cfg = kzalloc(size, GFP_KERNEL); + if (!get_cfg) + return -ENOMEM; + + ret = gb_i2s_mgmt_get_supported_configurations(connection, get_cfg, + size); + if (ret) { + pr_err("get_supported_config failed: %d\n", ret); + goto free_get_cfg; + } + + /* Pick 48KHz 16-bits/channel */ + for (i = 0, cfg = get_cfg->config; i < CONFIG_COUNT_MAX; i++, cfg++) { + if ((cfg->sample_frequency == GB_SAMPLE_RATE) && + (cfg->num_channels == 2) && + (cfg->bytes_per_channel == 2) && + (cfg->byte_order & GB_I2S_MGMT_BYTE_ORDER_LE) && + (cfg->spatial_locations == + (GB_I2S_MGMT_SPATIAL_LOCATION_FL | + GB_I2S_MGMT_SPATIAL_LOCATION_FR)) && + (cfg->ll_protocol & GB_I2S_MGMT_PROTOCOL_I2S) && + (cfg->ll_mclk_role & GB_I2S_MGMT_ROLE_MASTER) && + (cfg->ll_bclk_role & GB_I2S_MGMT_ROLE_MASTER) && + (cfg->ll_wclk_role & GB_I2S_MGMT_ROLE_MASTER) && + (cfg->ll_wclk_polarity & GB_I2S_MGMT_POLARITY_NORMAL) && + (cfg->ll_wclk_change_edge & GB_I2S_MGMT_EDGE_FALLING) && + (cfg->ll_wclk_tx_edge & GB_I2S_MGMT_EDGE_FALLING) && + (cfg->ll_wclk_rx_edge & GB_I2S_MGMT_EDGE_RISING) && + (cfg->ll_data_offset == 1)) + break; + } + + if (i >= CONFIG_COUNT_MAX) { + pr_err("No valid configuration\n"); + ret = -EINVAL; + goto free_get_cfg; + } + + memcpy(&set_cfg, cfg, sizeof(set_cfg)); + set_cfg.config.byte_order = GB_I2S_MGMT_BYTE_ORDER_LE; + set_cfg.config.ll_protocol = GB_I2S_MGMT_PROTOCOL_I2S; + set_cfg.config.ll_mclk_role = GB_I2S_MGMT_ROLE_MASTER; + set_cfg.config.ll_bclk_role = GB_I2S_MGMT_ROLE_MASTER; + set_cfg.config.ll_wclk_role = GB_I2S_MGMT_ROLE_MASTER; + set_cfg.config.ll_wclk_polarity = GB_I2S_MGMT_POLARITY_NORMAL; + set_cfg.config.ll_wclk_change_edge = GB_I2S_MGMT_EDGE_RISING; + set_cfg.config.ll_wclk_tx_edge = GB_I2S_MGMT_EDGE_FALLING; + set_cfg.config.ll_wclk_rx_edge = GB_I2S_MGMT_EDGE_RISING; + + ret = gb_i2s_mgmt_set_configuration(connection, &set_cfg); + if (ret) { + pr_err("set_configuration failed: %d\n", ret); + goto free_get_cfg; + } + + ret = gb_i2s_mgmt_set_samples_per_message(connection, + CONFIG_SAMPLES_PER_MSG); + if (ret) { + pr_err("set_samples_per_msg failed: %d\n", ret); + goto free_get_cfg; + } + + /* XXX Add start delay here (probably 1ms) */ + ret = gb_i2s_mgmt_activate_cport(connection, + CONFIG_I2S_REMOTE_DATA_CPORT); + if (ret) { + pr_err("activate_cport failed: %d\n", ret); + goto free_get_cfg; + } + +free_get_cfg: + kfree(get_cfg); + return ret; +} + +int gb_i2s_send_data(struct gb_connection *connection, + void *req_buf, void *source_addr, + size_t len, int sample_num) +{ + struct gb_i2s_send_data_request *gb_req; + int ret; + + gb_req = req_buf; + gb_req->sample_number = sample_num; + + memcpy((void *)&gb_req->data[0], source_addr, len); + + if (len < MAX_SEND_DATA_LEN) + for (; len < MAX_SEND_DATA_LEN; len++) + gb_req->data[len] = gb_req->data[len - SAMPLE_SIZE]; + + gb_req->size = len; + + ret = gb_operation_sync(connection, GB_I2S_DATA_TYPE_SEND_DATA, + (void *) gb_req, SEND_DATA_BUF_LEN, NULL, 0); + return ret; +} diff --git a/drivers/staging/greybus/audio-pcm.c b/drivers/staging/greybus/audio-pcm.c new file mode 100644 index 0000000..28b5e11 --- /dev/null +++ b/drivers/staging/greybus/audio-pcm.c @@ -0,0 +1,262 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "greybus.h" +#include "gpbridge.h" +#include "audio.h" + +/* + * timer/workqueue logic for pushing pcm data. + * + * Since when we are playing audio, we don't get any + * status or feedback from the codec, we have to use a + * hrtimer to trigger sending data to the remote codec. + * However since the hrtimer runs in irq context, so we + * have to schedule a workqueue to actually send the + * greybus data. + */ + +static void gb_pcm_work(struct work_struct *work) +{ + struct gb_snd *snd_dev = container_of(work, struct gb_snd, work); + struct snd_pcm_substream *substream = snd_dev->substream; + struct snd_pcm_runtime *runtime = substream->runtime; + unsigned int stride, frames, oldptr; + int period_elapsed; + char *address; + long len; + + if (!snd_dev) + return; + + if (!atomic_read(&snd_dev->running)) + return; + + address = runtime->dma_area + snd_dev->hwptr_done; + + len = frames_to_bytes(runtime, + runtime->buffer_size) - snd_dev->hwptr_done; + len = min(len, MAX_SEND_DATA_LEN); + gb_i2s_send_data(snd_dev->i2s_tx_connection, snd_dev->send_data_req_buf, + address, len, snd_dev->send_data_sample_count); + + snd_dev->send_data_sample_count += CONFIG_SAMPLES_PER_MSG; + + stride = runtime->frame_bits >> 3; + frames = len/stride; + + snd_pcm_stream_lock(substream); + oldptr = snd_dev->hwptr_done; + snd_dev->hwptr_done += len; + if (snd_dev->hwptr_done >= runtime->buffer_size * stride) + snd_dev->hwptr_done -= runtime->buffer_size * stride; + + frames = (len + (oldptr % stride)) / stride; + + snd_dev->transfer_done += frames; + if (snd_dev->transfer_done >= runtime->period_size) { + snd_dev->transfer_done -= runtime->period_size; + period_elapsed = 1; + } + + snd_pcm_stream_unlock(substream); + if (period_elapsed) + snd_pcm_period_elapsed(snd_dev->substream); +} + +static enum hrtimer_restart gb_pcm_timer_function(struct hrtimer *hrtimer) +{ + struct gb_snd *snd_dev = container_of(hrtimer, struct gb_snd, timer); + + if (!atomic_read(&snd_dev->running)) + return HRTIMER_NORESTART; + queue_work(snd_dev->workqueue, &snd_dev->work); + hrtimer_forward_now(hrtimer, ns_to_ktime(CONFIG_PERIOD_NS)); + return HRTIMER_RESTART; +} + +void gb_pcm_hrtimer_start(struct gb_snd *snd_dev) +{ + atomic_set(&snd_dev->running, 1); + hrtimer_start(&snd_dev->timer, ns_to_ktime(CONFIG_PERIOD_NS), + HRTIMER_MODE_REL); +} + +void gb_pcm_hrtimer_stop(struct gb_snd *snd_dev) +{ + atomic_set(&snd_dev->running, 0); + hrtimer_cancel(&snd_dev->timer); +} + +static int gb_pcm_hrtimer_init(struct gb_snd *snd_dev) +{ + hrtimer_init(&snd_dev->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + snd_dev->timer.function = gb_pcm_timer_function; + atomic_set(&snd_dev->running, 0); + snd_dev->workqueue = alloc_workqueue("gb-audio", WQ_HIGHPRI, 0); + if (!snd_dev->workqueue) + return -ENOMEM; + INIT_WORK(&snd_dev->work, gb_pcm_work); + return 0; +} + + +/* + * Core gb pcm structure + */ +static struct snd_pcm_hardware gb_plat_pcm_hardware = { + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID, + .formats = GB_FMTS, + .rates = GB_RATES, + .rate_min = 8000, + .rate_max = GB_SAMPLE_RATE, + .channels_min = 1, + .channels_max = 2, + /* XXX - All the values below are junk */ + .buffer_bytes_max = 64 * 1024, + .period_bytes_min = 32, + .period_bytes_max = 8192, + .periods_min = 2, + .periods_max = 32, +}; + +static snd_pcm_uframes_t gb_pcm_pointer(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct gb_snd *snd_dev; + + snd_dev = snd_soc_dai_get_drvdata(rtd->cpu_dai); + + return snd_dev->hwptr_done / (substream->runtime->frame_bits >> 3); +} + +static int gb_pcm_prepare(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct gb_snd *snd_dev; + + snd_dev = snd_soc_dai_get_drvdata(rtd->cpu_dai); + snd_dev->hwptr_done = 0; + snd_dev->transfer_done = 0; + return 0; +} + +static unsigned int rates[] = {GB_SAMPLE_RATE}; +static struct snd_pcm_hw_constraint_list constraints_rates = { + .count = ARRAY_SIZE(rates), + .list = rates, + .mask = 0, +}; + +static int gb_pcm_open(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct gb_snd *snd_dev; + unsigned long flags; + int ret; + + snd_dev = snd_soc_dai_get_drvdata(rtd->cpu_dai); + + spin_lock_irqsave(&snd_dev->lock, flags); + runtime->private_data = snd_dev; + snd_dev->substream = substream; + ret = gb_pcm_hrtimer_init(snd_dev); + spin_unlock_irqrestore(&snd_dev->lock, flags); + + if (ret) + return ret; + + snd_soc_set_runtime_hwparams(substream, &gb_plat_pcm_hardware); + + ret = snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + if (ret < 0) + return ret; + + return snd_pcm_hw_constraint_integer(runtime, + SNDRV_PCM_HW_PARAM_PERIODS); +} + +static int gb_pcm_close(struct snd_pcm_substream *substream) +{ + substream->runtime->private_data = NULL; + return 0; +} + +static int gb_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) +{ + return snd_pcm_lib_malloc_pages(substream, + params_buffer_bytes(hw_params)); +} + +static int gb_pcm_hw_free(struct snd_pcm_substream *substream) +{ + return snd_pcm_lib_free_pages(substream); +} + +static struct snd_pcm_ops gb_pcm_ops = { + .open = gb_pcm_open, + .close = gb_pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = gb_pcm_hw_params, + .hw_free = gb_pcm_hw_free, + .prepare = gb_pcm_prepare, + .pointer = gb_pcm_pointer, +}; + +static void gb_pcm_free(struct snd_pcm *pcm) +{ + snd_pcm_lib_preallocate_free_for_all(pcm); +} + +static int gb_pcm_new(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_pcm *pcm = rtd->pcm; + + return snd_pcm_lib_preallocate_pages_for_all( + pcm, + SNDRV_DMA_TYPE_CONTINUOUS, + snd_dma_continuous_data(GFP_KERNEL), + PREALLOC_BUFFER, PREALLOC_BUFFER_MAX); +} + +struct snd_soc_platform_driver gb_soc_platform = { + .ops = &gb_pcm_ops, + .pcm_new = gb_pcm_new, + .pcm_free = gb_pcm_free, +}; + +static int gb_soc_platform_probe(struct platform_device *pdev) +{ + return snd_soc_register_platform(&pdev->dev, &gb_soc_platform); +} + +static int gb_soc_platform_remove(struct platform_device *pdev) +{ + snd_soc_unregister_platform(&pdev->dev); + return 0; +} + +struct platform_driver gb_audio_pcm_driver = { + .driver = { + .name = "gb-pcm-audio", + .owner = THIS_MODULE, + }, + .probe = gb_soc_platform_probe, + .remove = gb_soc_platform_remove, +}; diff --git a/drivers/staging/greybus/audio.c b/drivers/staging/greybus/audio.c new file mode 100644 index 0000000..717e002 --- /dev/null +++ b/drivers/staging/greybus/audio.c @@ -0,0 +1,432 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "greybus.h" +#include "gpbridge.h" +#include "audio.h" + + +#define GB_AUDIO_DATA_DRIVER_NAME "gb_audio_data" +#define GB_AUDIO_MGMT_DRIVER_NAME "gb_audio_mgmt" + +/* + * gb_snd management functions + */ +static DEFINE_SPINLOCK(gb_snd_list_lock); +static LIST_HEAD(gb_snd_list); +static int device_count; + +static struct gb_snd *gb_find_snd(int bundle_id) +{ + struct gb_snd *tmp, *ret = NULL; + unsigned long flags; + + spin_lock_irqsave(&gb_snd_list_lock, flags); + list_for_each_entry(tmp, &gb_snd_list, list) + if (tmp->gb_bundle_id == bundle_id) { + ret = tmp; + break; + } + spin_unlock_irqrestore(&gb_snd_list_lock, flags); + return ret; +} + +static struct gb_snd *gb_get_snd(int bundle_id) +{ + struct gb_snd *snd_dev; + unsigned long flags; + + snd_dev = gb_find_snd(bundle_id); + if (snd_dev) + return snd_dev; + + snd_dev = kzalloc(sizeof(*snd_dev), GFP_KERNEL); + if (!snd_dev) + return NULL; + + spin_lock_init(&snd_dev->lock); + snd_dev->device_count = device_count++; + snd_dev->gb_bundle_id = bundle_id; + spin_lock_irqsave(&gb_snd_list_lock, flags); + list_add(&snd_dev->list, &gb_snd_list); + spin_unlock_irqrestore(&gb_snd_list_lock, flags); + return snd_dev; +} + +static void gb_free_snd(struct gb_snd *snd) +{ + unsigned long flags; + + spin_lock_irqsave(&gb_snd_list_lock, flags); + if (!snd->i2s_tx_connection && + !snd->mgmt_connection) { + list_del(&snd->list); + spin_unlock_irqrestore(&gb_snd_list_lock, flags); + kfree(snd); + } else { + spin_unlock_irqrestore(&gb_snd_list_lock, flags); + } +} + + + + +/* + * This is the ASoC simple card binds the platform codec, + * cpu-dai and codec-dai togheter + */ +struct gb_card_info_object { + struct asoc_simple_card_info card_info; + char codec_name[255]; + char platform_name[255]; + char dai_name[255]; +}; + + +struct asoc_simple_card_info *setup_card_info(int device_count) +{ + struct gb_card_info_object *obj; + + obj = kzalloc(sizeof(struct gb_card_info_object), GFP_KERNEL); + if (!obj) + return NULL; + + obj->card_info.name = "Greybus Audio Module"; + obj->card_info.card = "gb-card"; + obj->card_info.codec = obj->codec_name; + obj->card_info.platform = obj->platform_name; + obj->card_info.cpu_dai.name = obj->dai_name; + obj->card_info.cpu_dai.fmt = GB_FMTS; +#if USE_RT5645 + obj->card_info.daifmt = GB_FMTS; + sprintf(obj->codec_name, "rt5645.%s", "6-001b"); /* XXX do i2c bus addr dynamically */ + obj->card_info.codec_dai.name = "rt5645-aif1"; + obj->card_info.codec_dai.fmt = SND_SOC_DAIFMT_CBM_CFM; + obj->card_info.codec_dai.sysclk = 12288000; +#else + sprintf(obj->codec_name, "spdif-dit"); + obj->card_info.codec_dai.name = "dit-hifi"; +#endif + sprintf(obj->platform_name, "gb-pcm-audio.%i", device_count); + sprintf(obj->dai_name, "gb-dai-audio.%i", device_count); + + return &obj->card_info; +} + +void free_card_info(struct asoc_simple_card_info *ci) +{ + struct gb_card_info_object *obj; + + obj = container_of(ci, struct gb_card_info_object, card_info); + kfree(obj); +} + + +/* + * XXX this is sort of cruddy but I get warnings if + * we don't have dev.release handler set. + */ +static void default_release(struct device *dev) +{ +} + +/* + * GB connection hooks + */ +static int gb_i2s_transmitter_connection_init(struct gb_connection *connection) +{ + struct gb_snd *snd_dev; + struct platform_device *codec, *dai; + struct asoc_simple_card_info *simple_card; + unsigned long flags; + int ret; + + snd_dev = gb_get_snd(connection->bundle->id); + if (!snd_dev) + return -ENOMEM; + + codec = platform_device_register_simple("spdif-dit", -1, NULL, 0); + if (!codec) { + ret = -ENOMEM; + goto out; + } + + dai = platform_device_register_simple("gb-pcm-audio", snd_dev->device_count, NULL, 0); + if (!dai) { + ret = -ENOMEM; + goto out; + } + + simple_card = setup_card_info(snd_dev->device_count); + if (!simple_card) { + ret = -ENOMEM; + goto out; + } + + spin_lock_irqsave(&snd_dev->lock, flags); + snd_dev->card.name = "asoc-simple-card"; + snd_dev->card.id = snd_dev->device_count; + snd_dev->card.dev.release = default_release; /* XXX - suspicious */ + + snd_dev->cpu_dai.name = "gb-dai-audio"; + snd_dev->cpu_dai.id = snd_dev->device_count; + snd_dev->cpu_dai.dev.release = default_release; /* XXX - suspicious */ + + + snd_dev->simple_card_info = simple_card; + snd_dev->card.dev.platform_data = simple_card; + + snd_dev->codec = codec; + snd_dev->i2s_tx_connection = connection; + snd_dev->cpu_dai.dev.platform_data = snd_dev; + snd_dev->i2s_tx_connection->private = snd_dev; + spin_unlock_irqrestore(&snd_dev->lock, flags); + + ret = platform_device_register(&snd_dev->cpu_dai); + if (ret) { + pr_err("cpu_dai platform_device register failed\n"); + goto out_dai; + } + + ret = platform_device_register(&snd_dev->card); + if (ret) { + pr_err("card platform_device register failed\n"); + goto out_card; + } + + ret = gb_i2s_data_get_version(connection); + if (ret) { + pr_err("i2s data get_version() failed: %d\n", ret); + goto out_get_ver; + } + + return 0; + +out_get_ver: + platform_device_unregister(&snd_dev->card); +out_card: + platform_device_unregister(&snd_dev->cpu_dai); +out_dai: + platform_device_unregister(codec); +out: + gb_free_snd(snd_dev); + return ret; +} + +static void gb_i2s_transmitter_connection_exit(struct gb_connection *connection) +{ + struct gb_snd *snd_dev; + + snd_dev = (struct gb_snd *)connection->private; + + platform_device_unregister(&snd_dev->card); + platform_device_unregister(&snd_dev->cpu_dai); + platform_device_unregister(snd_dev->codec); + + free_card_info(snd_dev->simple_card_info); + snd_dev->i2s_tx_connection = NULL; + gb_free_snd(snd_dev); +} + +static int gb_i2s_mgmt_connection_init(struct gb_connection *connection) +{ + struct gb_snd *snd_dev; + unsigned long flags; + int ret; + + snd_dev = gb_get_snd(connection->bundle->id); + if (!snd_dev) + return -ENOMEM; + + spin_lock_irqsave(&snd_dev->lock, flags); + snd_dev->mgmt_connection = connection; + connection->private = snd_dev; + spin_unlock_irqrestore(&snd_dev->lock, flags); + + ret = gb_i2s_mgmt_get_version(connection); + if (ret) { + pr_err("i2s mgmt get_version() failed: %d\n", ret); + goto err_free_snd_dev; + } + + gb_i2s_mgmt_setup(connection); + + snd_dev->send_data_req_buf = kzalloc(SEND_DATA_BUF_LEN, GFP_KERNEL); + + if (!snd_dev->send_data_req_buf) { + ret = -ENOMEM; + goto err_deactivate_cport; + } + + return 0; + +err_deactivate_cport: + gb_i2s_mgmt_deactivate_cport(connection, CONFIG_I2S_REMOTE_DATA_CPORT); +err_free_snd_dev: + gb_free_snd(snd_dev); + return ret; +} + +static void gb_i2s_mgmt_connection_exit(struct gb_connection *connection) +{ + struct gb_snd *snd_dev = (struct gb_snd *)connection->private; + int ret; + + ret = gb_i2s_mgmt_deactivate_cport(connection, + CONFIG_I2S_REMOTE_DATA_CPORT); + if (ret) + pr_err("deactivate_cport failed: %d\n", ret); + + kfree(snd_dev->send_data_req_buf); + snd_dev->send_data_req_buf = NULL; + + snd_dev->mgmt_connection = NULL; + gb_free_snd(snd_dev); +} + +static int gb_i2s_mgmt_report_event_recv(u8 type, struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_i2s_mgmt_report_event_request *req = op->request->payload; + char *event_name; + + if (type != GB_I2S_MGMT_TYPE_REPORT_EVENT) { + dev_err(&connection->dev, "Invalid request type: %d\n", + type); + return -EINVAL; + } + + if (op->request->payload_size < sizeof(*req)) { + dev_err(&connection->dev, "Short request received: %d, %d\n", + op->request->payload_size, sizeof(*req)); + return -EINVAL; + } + + switch (req->event) { + case GB_I2S_MGMT_EVENT_UNSPECIFIED: + event_name = "UNSPECIFIED"; + break; + case GB_I2S_MGMT_EVENT_HALT: + /* XXX Should stop streaming now */ + event_name = "HALT"; + break; + case GB_I2S_MGMT_EVENT_INTERNAL_ERROR: + event_name = "INTERNAL_ERROR"; + break; + case GB_I2S_MGMT_EVENT_PROTOCOL_ERROR: + event_name = "PROTOCOL_ERROR"; + break; + case GB_I2S_MGMT_EVENT_FAILURE: + event_name = "FAILURE"; + break; + case GB_I2S_MGMT_EVENT_OUT_OF_SEQUENCE: + event_name = "OUT_OF_SEQUENCE"; + break; + case GB_I2S_MGMT_EVENT_UNDERRUN: + event_name = "UNDERRUN"; + break; + case GB_I2S_MGMT_EVENT_OVERRUN: + event_name = "OVERRUN"; + break; + case GB_I2S_MGMT_EVENT_CLOCKING: + event_name = "CLOCKING"; + break; + case GB_I2S_MGMT_EVENT_DATA_LEN: + event_name = "DATA_LEN"; + break; + default: + dev_warn(&connection->dev, "Unknown I2S Event received: %d\n", + req->event); + return -EINVAL; + } + + dev_warn(&connection->dev, "I2S Event received: %d - '%s'\n", + req->event, event_name); + + return 0; +} + +static struct gb_protocol gb_i2s_receiver_protocol = { + .name = GB_AUDIO_DATA_DRIVER_NAME, + .id = GREYBUS_PROTOCOL_I2S_RECEIVER, + .major = 0, + .minor = 1, + .connection_init = gb_i2s_transmitter_connection_init, + .connection_exit = gb_i2s_transmitter_connection_exit, + .request_recv = NULL, +}; + +static struct gb_protocol gb_i2s_mgmt_protocol = { + .name = GB_AUDIO_MGMT_DRIVER_NAME, + .id = GREYBUS_PROTOCOL_I2S_MGMT, + .major = 0, + .minor = 1, + .connection_init = gb_i2s_mgmt_connection_init, + .connection_exit = gb_i2s_mgmt_connection_exit, + .request_recv = gb_i2s_mgmt_report_event_recv, +}; + + +/* + * This is the basic hook get things initialized and registered w/ gb + */ + +int gb_audio_protocol_init(void) +{ + int err; + + err = gb_protocol_register(&gb_i2s_mgmt_protocol); + if (err) { + pr_err("Can't register i2s mgmt protocol driver: %d\n", -err); + return err; + } + + err = gb_protocol_register(&gb_i2s_receiver_protocol); + if (err) { + pr_err("Can't register Audio protocol driver: %d\n", -err); + goto err_unregister_i2s_mgmt; + } + + err = platform_driver_register(&gb_audio_plat_driver); + if (err) { + pr_err("Can't register platform driver: %d\n", -err); + goto err_unregister_plat; + } + + err = platform_driver_register(&gb_audio_pcm_driver); + if (err) { + pr_err("Can't register pcm driver: %d\n", -err); + goto err_unregister_pcm; + } + + return 0; + +err_unregister_pcm: + platform_driver_unregister(&gb_audio_plat_driver); +err_unregister_plat: + gb_protocol_deregister(&gb_i2s_receiver_protocol); +err_unregister_i2s_mgmt: + gb_protocol_deregister(&gb_i2s_mgmt_protocol); + return err; +} + +void gb_audio_protocol_exit(void) +{ + platform_driver_unregister(&gb_audio_pcm_driver); + platform_driver_unregister(&gb_audio_plat_driver); + gb_protocol_deregister(&gb_i2s_receiver_protocol); + gb_protocol_deregister(&gb_i2s_mgmt_protocol); +} + + +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/greybus/audio.h b/drivers/staging/greybus/audio.h new file mode 100644 index 0000000..6a337d1 --- /dev/null +++ b/drivers/staging/greybus/audio.h @@ -0,0 +1,100 @@ +#ifndef __GB_AUDIO_H +#define __GB_AUDIO_H +#include +#include +#include +#include +#include +#include +#include "greybus.h" +#include "gpbridge.h" + + +#define GB_SAMPLE_RATE 48000 +#define GB_RATES SNDRV_PCM_RATE_48000 +#define GB_FMTS SNDRV_PCM_FMTBIT_S16_LE +#define PREALLOC_BUFFER (32 * 1024) +#define PREALLOC_BUFFER_MAX (32 * 1024) + +/* assuming 1 ms samples @ 48KHz */ +#define CONFIG_SAMPLES_PER_MSG 48L +#define CONFIG_PERIOD_NS 1000000 /* send msg every 1ms */ + +#define CONFIG_COUNT_MAX 32 +#define CONFIG_I2S_REMOTE_DATA_CPORT 7 /* XXX shouldn't be hardcoded...*/ +#define RT5647_SLAVE_ADDR 0x1b /* from toshiba/quanta code */ + +/* Switch between dummy spdif and jetson rt5645 codec */ +#define USE_RT5645 0 + +#define SAMPLE_SIZE 4 +#define MAX_SEND_DATA_LEN (CONFIG_SAMPLES_PER_MSG * SAMPLE_SIZE) +#define SEND_DATA_BUF_LEN (sizeof(struct gb_i2s_send_data_request) + \ + MAX_SEND_DATA_LEN) + + +/* + * This is the gb_snd structure which ties everything together + * and fakes DMA interrupts via a timer. + */ +struct gb_snd { + struct platform_device card; + struct platform_device cpu_dai; + struct platform_device *codec; + struct asoc_simple_card_info *simple_card_info; + struct gb_connection *mgmt_connection; + struct gb_connection *i2s_tx_connection; + struct gb_connection *i2s_rx_connection; + char *send_data_req_buf; + long send_data_sample_count; + int gb_bundle_id; + int device_count; + struct snd_pcm_substream *substream; + struct hrtimer timer; + atomic_t running; + struct workqueue_struct *workqueue; + struct work_struct work; + int hwptr_done; + int transfer_done; + struct list_head list; + spinlock_t lock; +}; + + +/* + * GB I2S cmd functions + */ +int gb_i2s_mgmt_get_version(struct gb_connection *connection); +int gb_i2s_data_get_version(struct gb_connection *connection); +int gb_i2s_mgmt_activate_cport(struct gb_connection *connection, + uint16_t cport); +int gb_i2s_mgmt_deactivate_cport(struct gb_connection *connection, + uint16_t cport); +int gb_i2s_mgmt_get_supported_configurations( + struct gb_connection *connection, + struct gb_i2s_mgmt_get_supported_configurations_response *get_cfg, + size_t size); +int gb_i2s_mgmt_set_configuration(struct gb_connection *connection, + struct gb_i2s_mgmt_set_configuration_request *set_cfg); +int gb_i2s_mgmt_set_samples_per_message(struct gb_connection *connection, + uint16_t samples_per_message); +int gb_i2s_mgmt_setup(struct gb_connection *connection); +int gb_i2s_send_data(struct gb_connection *connection, void *req_buf, + void *source_addr, size_t len, int sample_num); + + +/* + * GB PCM hooks + */ +void gb_pcm_hrtimer_start(struct gb_snd *snd_dev); +void gb_pcm_hrtimer_stop(struct gb_snd *snd_dev); + + +/* + * Platform drivers + */ +extern struct platform_driver gb_audio_pcm_driver; +extern struct platform_driver gb_audio_plat_driver; + + +#endif /* __GB_AUDIO_H */ diff --git a/drivers/staging/greybus/gpb.c b/drivers/staging/greybus/gpb.c index d5747b2..2324270 100644 --- a/drivers/staging/greybus/gpb.c +++ b/drivers/staging/greybus/gpb.c @@ -53,8 +53,15 @@ static int __init gpbridge_init(void) pr_err("error initializing hid protocol\n"); goto error_hid; } + if (gb_audio_protocol_init()) { + pr_err("error initializing audio protocols\n"); + goto error_audio; + } + return 0; +error_audio: + gb_hid_protocol_exit(); error_hid: gb_spi_protocol_exit(); error_spi: @@ -76,6 +83,7 @@ module_init(gpbridge_init); static void __exit gpbridge_exit(void) { + gb_audio_protocol_exit(); gb_hid_protocol_exit(); gb_spi_protocol_exit(); gb_i2c_protocol_exit(); diff --git a/drivers/staging/greybus/gpbridge.h b/drivers/staging/greybus/gpbridge.h index 85d8019..85cc385 100644 --- a/drivers/staging/greybus/gpbridge.h +++ b/drivers/staging/greybus/gpbridge.h @@ -341,6 +341,7 @@ struct gb_i2s_mgmt_configuration { __u8 pad; __le32 spatial_locations; __le32 ll_protocol; + __u8 ll_mclk_role; __u8 ll_bclk_role; __u8 ll_wclk_role; __u8 ll_wclk_polarity; @@ -348,7 +349,6 @@ struct gb_i2s_mgmt_configuration { __u8 ll_wclk_tx_edge; __u8 ll_wclk_rx_edge; __u8 ll_data_offset; - __u8 ll_pad; }; /* get supported configurations request has no payload */ diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index 495d13a..7958802 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -87,6 +87,9 @@ extern void gb_spi_protocol_exit(void); extern int gb_hid_protocol_init(void); extern void gb_hid_protocol_exit(void); +extern int gb_audio_protocol_init(void); +extern void gb_audio_protocol_exit(void); + #define gb_protocol_driver(__protocol) \ static int __init protocol_init(void) \ { \ -- cgit v0.10.2 From 68fff9604b8bce5cd023585ff41710948e61076e Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 7 May 2015 17:00:50 -0700 Subject: greybus: Support building greybus on host PC Introduce INSTALL_MOD_PATH to allow for building and installing of the greybus modules from a different location. This lets you build the greybus modules on a PC and then install the modules to an SD card in the appropriate location relative to the SD such as /media/sdcard/lib/modules/version and subsequent running of depmod in the same location. If INSTALL_MOD_PATH isn't specified the default behaviour of installing and depmoding to /lib/modules/version is maintained. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 5158d87..f366da6 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -41,6 +41,7 @@ obj-m += gb-es2.o KERNELVER ?= $(shell uname -r) KERNELDIR ?= /lib/modules/$(KERNELVER)/build +INSTALL_MOD_PATH ?= /.. PWD := $(shell pwd) # add -Wall to try to catch everything we can. @@ -63,6 +64,6 @@ coccicheck: $(MAKE) -C $(KERNELDIR) M=$(PWD) coccicheck install: module - mkdir -p /lib/modules/$(KERNELVER)/kernel/drivers/greybus/ - cp -f *.ko /lib/modules/$(KERNELVER)/kernel/drivers/greybus/ - depmod -a $(KERNELVER) + mkdir -p $(INSTALL_MOD_PATH)/lib/modules/$(KERNELVER)/kernel/drivers/greybus/ + cp -f *.ko $(INSTALL_MOD_PATH)/lib/modules/$(KERNELVER)/kernel/drivers/greybus/ + depmod -b $(INSTALL_MOD_PATH) -a $(KERNELVER) -- cgit v0.10.2 From 7f3f356e455dd4438fdad2d45330f0d27bd087b6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 8 May 2015 22:33:36 +0200 Subject: greybus: gb-audio: fix build warning sizeof wants %zu when on a 64bit build, so change the dev_err() call to remove a build warning in the audio.c file. Signed-off-by: Greg Kroah-Hartman Acked-by: John Stultz diff --git a/drivers/staging/greybus/audio.c b/drivers/staging/greybus/audio.c index 717e002..29f5d4b 100644 --- a/drivers/staging/greybus/audio.c +++ b/drivers/staging/greybus/audio.c @@ -307,7 +307,7 @@ static int gb_i2s_mgmt_report_event_recv(u8 type, struct gb_operation *op) } if (op->request->payload_size < sizeof(*req)) { - dev_err(&connection->dev, "Short request received: %d, %d\n", + dev_err(&connection->dev, "Short request received: %zu, %zu\n", op->request->payload_size, sizeof(*req)); return -EINVAL; } -- cgit v0.10.2 From 61c0926eec4153e51f047fbf91b897abeca4cccb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 8 May 2015 22:40:47 +0200 Subject: greybus: gb-audio: fix build breakage on 4.1-rc1 In commit 1efb53a220b7 ("ASoC: simple-card: Remove support for setting differing DAI formats"), the .fmt field was removed from struct asoc_simple_dai. Fix this build breakage by not trying to set it. Signed-off-by: Greg Kroah-Hartman Acked-by: John Stultz diff --git a/drivers/staging/greybus/audio.c b/drivers/staging/greybus/audio.c index 29f5d4b..1ef0903 100644 --- a/drivers/staging/greybus/audio.c +++ b/drivers/staging/greybus/audio.c @@ -106,7 +106,9 @@ struct asoc_simple_card_info *setup_card_info(int device_count) obj->card_info.codec = obj->codec_name; obj->card_info.platform = obj->platform_name; obj->card_info.cpu_dai.name = obj->dai_name; +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0) obj->card_info.cpu_dai.fmt = GB_FMTS; +#endif #if USE_RT5645 obj->card_info.daifmt = GB_FMTS; sprintf(obj->codec_name, "rt5645.%s", "6-001b"); /* XXX do i2c bus addr dynamically */ -- cgit v0.10.2 From 4f4cc1bf070e05d4ee54e569e7ec87168fa8e284 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 8 May 2015 12:58:50 +0530 Subject: greybus: endo: Add code to validate Endo ID Endo is described by a 16 bit value. Which represents the properties of modules, interface and ribs on front and back of endo. This 16 bit value can be used to find all possible pairs of modules and interfaces and creating modules based on that. This patch provides helpers to parse 16 bit Endo ID. (Based on original code written by Alex Elder.) Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c index b9c7ee6..e47ec69 100644 --- a/drivers/staging/greybus/endo.c +++ b/drivers/staging/greybus/endo.c @@ -9,6 +9,26 @@ #include "greybus.h" +/* Endo ID (16 bits long) Masks */ +#define ENDO_ID_MASK 0xFFFF +#define ENDO_LARGE_MASK 0x1000 +#define ENDO_MEDIUM_MASK 0x0400 +#define ENDO_MINI_MASK 0x0100 + +#define ENDO_FRONT_MASK(id) ((id) >> 13) +#define ENDO_BACK_SIDE_RIBS_MASK(ribs) ((1 << (ribs)) - 1) + +/* + * endo_is_medium() should be used only if endo isn't large. And endo_is_mini() + * should be used only if endo isn't large or medium. + */ +#define endo_is_large(id) ((id) & ENDO_LARGE_MASK) +#define endo_is_medium(id) ((id) & ENDO_MEDIUM_MASK) +#define endo_is_mini(id) ((id) & ENDO_MINI_MASK) + +#define endo_back_left_ribs(id, ribs) (((id) >> (ribs)) & ENDO_BACK_SIDE_RIBS_MASK(ribs)) +#define endo_back_right_ribs(id, ribs) ((id) & ENDO_BACK_SIDE_RIBS_MASK(ribs)) + /* endo sysfs attributes */ static ssize_t serial_number_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -55,6 +75,280 @@ struct device_type greybus_endo_type = { }; +/* Validate Endo ID */ + +/* + * The maximum module height is 2 units. This means any adjacent pair of bits + * in the left or right mask must have at least one bit set. + */ +static inline bool modules_oversized(unsigned int count, unsigned int mask) +{ + int i; + + for (i = 0; i < count - 1; i++) + if (!(mask & (0x3 << i))) + return true; + + return false; +} + +/* Reverse a number of least significant bits in a value */ +static u8 reverse_bits(unsigned int value, unsigned int bits) +{ + u8 result = 0; + u8 result_mask = 1 << (bits - 1); + u8 value_mask = 1; + + while (value && result_mask) { + if (value & value_mask) { + result |= result_mask; + value ^= value_mask; + } + value_mask <<= 1; + result_mask >>= 1; + } + + return result; +} + +/* + * An Endo can have at most one instance of a single rib spanning its whole + * width. That is, the left and right bit masks representing the rib positions + * must have at most one bit set in both masks. + */ +static bool single_cross_rib(u8 left_ribs, u8 right_ribs) +{ + u8 span_ribs = left_ribs & right_ribs; + + /* Power of 2 ? */ + if (span_ribs & (span_ribs - 1)) + return false; + return true; +} + +/* + * Each Endo size has its own set of front module configurations. For most, the + * resulting rib mask is the same regardless of the Endo size. The mini Endo + * has a few differences though. + * + * Endo front has 4 interface blocks and 3 rib positions. A maximum of 2 ribs + * are allowed to be present for any endo type. + * + * This routine validates front mask and sets 'front_ribs', its 3 least + * significant bits represent front ribs mask, other are 0. The front values + * should be within range (1..6). + * + * front_ribs bitmask: + * - Bit 0: 1st rib location from top, i.e. between interface 1 and 2. + * - Bit 1: 2nd rib location from top, i.e. between interface 2 and 3. + * - Bit 2: 3rd rib location from top, i.e. between interface 3 and 4. + */ +static bool validate_front_ribs(struct greybus_host_device *hd, + struct endo_layout *layout, bool mini, + u16 endo_id) +{ + u8 front_mask = ENDO_FRONT_MASK(endo_id); + + /* Verify front endo mask is in valid range, i.e. 1-6 */ + + switch (front_mask) { + case 1: + layout->front_ribs = 0x0; + break; + case 2: + layout->front_ribs = 0x1; + break; + case 3: + layout->front_ribs = 0x4; + break; + case 4: + layout->front_ribs = mini ? 0x2 : 0x3; + break; + case 5: + layout->front_ribs = mini ? 0x2 : 0x6; + break; + case 6: + layout->front_ribs = 0x5; + break; + default: + dev_err(hd->parent, + "%s: Invalid endo front mask 0x%02x, id 0x%04x\n", + __func__, front_mask, endo_id); + return false; + } + + return true; +} + +/* + * The rear of an endo has a single vertical "spine", and the modules placed on + * the left and right of that spine are separated by ribs. Only one "cross" + * (i.e. rib that spans the entire width) is allowed of the back of the endo; + * all other ribs reach from the spine to the left or right edge. + * + * The width of the module positions on the left and right of the spine are + * determined by the width of the endo (either 1 or 2 "units"). The height of + * the modules is determined by the placement of the ribs (a module can be + * either 1 or 2 units high). + * + * The lower 13 bits of the 16-bit endo id are used to encode back ribs + * information. The large form factor endo uses all of these bits; the medium + * and mini form factors leave some bits unused (such bits shall be ignored, and + * are 0 for the purposes of this endo id definition). + * + * Each defined bit represents a rib position on one or the other side + * of the spine on the back of an endo. If that bit is set (1), it + * means a rib is present in the corresponding location; otherwise + * there is no rib there. + * + * Rotating an endo 180 degrees does not produce a new rib configuration. A + * single endo id represents a specific configuration of ribs without regard to + * its rotational orientation. We define one canonical id to represent a + * particular endo configuration. + */ +static bool validate_back_ribs(struct greybus_host_device *hd, + struct endo_layout *layout, u16 endo_id) +{ + u8 max_ribs = layout->max_ribs; + u8 left_ribs; + u8 right_ribs; + + /* Extract the left and right rib masks */ + left_ribs = endo_back_left_ribs(endo_id, max_ribs); + right_ribs = endo_back_right_ribs(endo_id, max_ribs); + + if (!single_cross_rib(left_ribs, right_ribs)) { + dev_err(hd->parent, + "%s: More than one spanning rib (left 0x%02x right 0x%02x), id 0x%04x\n", + __func__, left_ribs, right_ribs, endo_id); + return false; + } + + if (modules_oversized(max_ribs, left_ribs)) { + dev_err(hd->parent, + "%s: Oversized module (left) 0x%02x, id 0x%04x\n", + __func__, left_ribs, endo_id); + return false; + } + + if (modules_oversized(max_ribs, right_ribs)) { + dev_err(hd->parent, + "%s: Oversized module (Right) 0x%02x, id 0x%04x\n", + __func__, right_ribs, endo_id); + return false; + } + + /* + * The Endo numbering scheme represents the left and right rib + * configuration in a way that's convenient for looking for multiple + * spanning ribs. But it doesn't match the normal Endo interface + * numbering scheme (increasing counter-clockwise around the back). + * Reverse the right bit positions so they do match. + */ + right_ribs = reverse_bits(right_ribs, max_ribs); + + /* + * A mini or large Endo rotated 180 degrees is still the same Endo. In + * most cases that allows two distinct values to represent the same + * Endo; we choose one of them to be the canonical one (and the other is + * invalid). The canonical one is identified by higher value of left + * ribs mask. + * + * This doesn't apply to medium Endos, because the left and right sides + * are of different widths. + */ + if (max_ribs != ENDO_BACK_RIBS_MEDIUM && left_ribs < right_ribs) { + dev_err(hd->parent, "%s: Non-canonical endo id 0x%04x\n", __func__, + endo_id); + return false; + } + + layout->left_ribs = left_ribs; + layout->right_ribs = right_ribs; + return true; +} + +/* + * Validate the endo-id passed from SVC. Error out if its not a valid Endo, + * else return structure representing ribs positions on front and back of Endo. + */ +static int gb_validate_endo_id(struct greybus_host_device *hd, + struct endo_layout *layout, u16 endo_id) +{ + /* Validate Endo Size */ + if (endo_is_large(endo_id)) { + /* Large Endo type */ + layout->max_ribs = ENDO_BACK_RIBS_LARGE; + } else if (endo_is_medium(endo_id)) { + /* Medium Endo type */ + layout->max_ribs = ENDO_BACK_RIBS_MEDIUM; + } else if (endo_is_mini(endo_id)) { + /* Mini Endo type */ + layout->max_ribs = ENDO_BACK_RIBS_MINI; + } else { + dev_err(hd->parent, "%s: Invalid endo type, id 0x%04x\n", + __func__, endo_id); + return -EINVAL; + } + + if (!validate_back_ribs(hd, layout, endo_id)) + return -EINVAL; + + if (!validate_front_ribs(hd, layout, + layout->max_ribs == ENDO_BACK_RIBS_MINI, + endo_id)) + return -EINVAL; + + return 0; +} + +/* + * Look up which module contains the given interface. + * + * A module's ID is the same as its lowest-numbered interface ID. So the module + * ID for a 1x1 module is always the same as its interface ID. + * + * For Endo Back: + * The module ID for an interface on a 1x2 or 2x2 module (which use two + * interface blocks) can be either the interface ID, or one less than the + * interface ID if there is no rib "above" the interface. + * + * For Endo Front: + * There are three rib locations in front and all of them might be unused, i.e. + * a single module is used for all 4 interfaces. We need to check all ribs in + * that case to find module ID. + */ +u8 endo_get_module_id(struct gb_endo *endo, u8 interface_id) +{ + struct endo_layout *layout = &endo->layout; + unsigned int height = layout->max_ribs + 1; + unsigned int iid = interface_id - 1; + unsigned int mask, rib_mask; + + if (!interface_id) + return 0; + + if (iid < height) { /* back left */ + mask = layout->left_ribs; + } else if (iid < 2 * height) { /* back right */ + mask = layout->right_ribs; + iid -= height; + } else { /* front */ + mask = layout->front_ribs; + iid -= 2 * height; + } + + /* + * Find the next rib *above* this interface to determine the lowest + * interface ID in the module. + */ + rib_mask = 1 << iid; + while ((rib_mask >>= 1) != 0 && !(mask & rib_mask)) + --interface_id; + + return interface_id; +} + /* * Endo "types" have different module locations, these are tables based on those * types that list the module ids for the different locations. diff --git a/drivers/staging/greybus/endo.h b/drivers/staging/greybus/endo.h index a4342aa..dd05269 100644 --- a/drivers/staging/greybus/endo.h +++ b/drivers/staging/greybus/endo.h @@ -15,7 +15,28 @@ struct gb_svc { u8 version[10]; }; +/* Max ribs per Endo size */ +#define ENDO_BACK_RIBS_MINI 0x4 +#define ENDO_BACK_RIBS_MEDIUM 0x5 +#define ENDO_BACK_RIBS_LARGE 0x6 + +/** + * struct endo_layout - represents front/back ribs of the endo. + * + * @front_ribs: Mask of present ribs in front. + * @left_ribs: Mask of present ribs in back (left). + * @right_ribs: Mask of present ribs in back (right). + * @max_ribs: Max ribs on endo back, possible values defined above. + */ +struct endo_layout { + u8 front_ribs; + u8 left_ribs; + u8 right_ribs; + u8 max_ribs; +}; + struct gb_endo { + struct endo_layout layout; struct device dev; struct gb_svc svc; u16 id; @@ -29,4 +50,6 @@ struct greybus_host_device; struct gb_endo *gb_endo_create(struct greybus_host_device *hd); void gb_endo_remove(struct gb_endo *endo); +u8 endo_get_module_id(struct gb_endo *endo, u8 interface_id); + #endif /* __ENDO_H */ -- cgit v0.10.2 From 51e93aea65cdab93ae013b87a7e6b3a9eccef5ad Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 8 May 2015 12:58:51 +0530 Subject: greybus: endo: Create modules after validating Endo ID We already have code to parse Endo ID, lets use it to create modules at run time instead of creating them from a static array. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c index e47ec69..80d9397 100644 --- a/drivers/staging/greybus/endo.c +++ b/drivers/staging/greybus/endo.c @@ -350,45 +350,43 @@ u8 endo_get_module_id(struct gb_endo *endo, u8 interface_id) } /* - * Endo "types" have different module locations, these are tables based on those - * types that list the module ids for the different locations. + * Creates all possible modules for the Endo. * - * List must end with 0x00 in order to properly terminate the list. + * We try to create modules for all possible interface IDs. If a module is + * already created, we skip creating it again with the help of prev_module_id. */ -static u8 endo_4755[] = { - 0x01, - 0x03, - 0x05, - 0x06, - 0x07, - 0x08, - 0x0a, - 0x0c, - 0x0d, - 0x0e, - 0x00, -}; - - static int create_modules(struct gb_endo *endo) { struct gb_module *module; - u8 *endo_modules; - int i; + int prev_module_id = 0; + int interface_id; + int module_id; + int interfaces; - /* Depending on the endo id, create a bunch of different modules */ - switch (endo->id) { - case 0x4755: - endo_modules = &endo_4755[0]; - break; - default: - dev_err(&endo->dev, "Unknown endo id 0x%04x, aborting!", - endo->id); - return -EINVAL; - } + /* + * Total number of interfaces: + * - Front: 4 + * - Back: + * - Left: max_ribs + 1 + * - Right: max_ribs + 1 + */ + interfaces = 4 + (endo->layout.max_ribs + 1) * 2; + + /* Find module corresponding to each interface */ + for (interface_id = 1; interface_id <= interfaces; interface_id++) { + module_id = endo_get_module_id(endo, interface_id); + + if (WARN_ON(!module_id)) + continue; + + /* Skip already created modules */ + if (module_id == prev_module_id) + continue; + + prev_module_id = module_id; - for (i = 0; endo_modules[i] != 0x00; ++i) { - module = gb_module_create(&endo->dev, endo_modules[i]); + /* New module, create it */ + module = gb_module_create(&endo->dev, module_id); if (!module) return -EINVAL; } @@ -396,15 +394,11 @@ static int create_modules(struct gb_endo *endo) return 0; } -struct gb_endo *gb_endo_create(struct greybus_host_device *hd) +static int gb_endo_register(struct greybus_host_device *hd, + struct gb_endo *endo) { - struct gb_endo *endo; int retval; - endo = kzalloc(sizeof(*endo), GFP_KERNEL); - if (!endo) - return NULL; - endo->dev.parent = hd->parent; endo->dev.bus = &greybus_bus_type; endo->dev.type = &greybus_endo_type; @@ -412,12 +406,11 @@ struct gb_endo *gb_endo_create(struct greybus_host_device *hd) endo->dev.dma_mask = hd->parent->dma_mask; device_initialize(&endo->dev); - // FIXME - determine endo "id" from the SVC - // Also get the version and serial number from the SVC, right now we are + // FIXME + // Get the version and serial number from the SVC, right now we are // using "fake" numbers. strcpy(&endo->svc.serial_number[0], "042"); strcpy(&endo->svc.version[0], "0.0"); - endo->id = 0x4755; dev_set_name(&endo->dev, "endo-0x%04x", endo->id); retval = device_add(&endo->dev); @@ -425,10 +418,32 @@ struct gb_endo *gb_endo_create(struct greybus_host_device *hd) dev_err(hd->parent, "failed to add endo device of id 0x%04x\n", endo->id); put_device(&endo->dev); - kfree(endo); - return NULL; } + return retval; +} + +struct gb_endo *gb_endo_create(struct greybus_host_device *hd) +{ + struct gb_endo *endo; + int retval; + u16 endo_id = 0x4755; // FIXME - get endo "ID" from the SVC + + endo = kzalloc(sizeof(*endo), GFP_KERNEL); + if (!endo) + return NULL; + + /* First check if the value supplied is a valid endo id */ + if (gb_validate_endo_id(hd, &endo->layout, endo_id)) + goto free_endo; + + endo->id = endo_id; + + /* Register Endo device */ + if (gb_endo_register(hd, endo)) + goto free_endo; + + /* Create modules/interfaces */ retval = create_modules(endo); if (retval) { gb_endo_remove(endo); @@ -436,6 +451,10 @@ struct gb_endo *gb_endo_create(struct greybus_host_device *hd) } return endo; + +free_endo: + kfree(endo); + return NULL; } void gb_endo_remove(struct gb_endo *endo) diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 63665a2..28b3c4f 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -92,7 +92,7 @@ static struct gb_interface *gb_interface_create(struct greybus_host_device *hd, return NULL; } - module = gb_module_find(hd, get_module_id(interface_id)); + module = gb_module_find(hd, endo_get_module_id(hd->endo, interface_id)); if (!module) return NULL; diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index 202f141..8ed96a8 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -83,17 +83,6 @@ struct device_type greybus_module_type = { .release = greybus_module_release, }; -u8 get_module_id(u8 interface_id) -{ - /* - * FIXME: - * - * We should be able to find it from Endo ID passed during greybus - * control operation, while setting up AP. - */ - return interface_id; -} - struct module_find { struct gb_endo *endo; u8 module_id; @@ -125,6 +114,9 @@ struct gb_module *gb_module_find(struct greybus_host_device *hd, u8 module_id) struct gb_module *module = NULL; struct module_find find; + if (!module_id) + return NULL; + find.module_id = module_id; find.endo = hd->endo; diff --git a/drivers/staging/greybus/module.h b/drivers/staging/greybus/module.h index c23ac98..3b3f421 100644 --- a/drivers/staging/greybus/module.h +++ b/drivers/staging/greybus/module.h @@ -23,6 +23,4 @@ struct gb_module *gb_module_find(struct greybus_host_device *hd, u8 module_id); struct gb_module *gb_module_create(struct device *parent, u8 module_id); void gb_module_remove_all(struct gb_endo *endo); -u8 get_module_id(u8 interface_id); - #endif /* __MODULE_H */ -- cgit v0.10.2 From 563e6b97b87c18ec0d0d1fc541d59d1ee0842a39 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Mon, 11 May 2015 19:22:03 +0100 Subject: greybus: manifest: be coherent with protocol name remane protocol define from GREYBUS_PROTOCOL_LED to GREYBUS_PROTOCOL_LIGHTS to be coherent with the specification. Signed-off-by: Rui Miguel Silva Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 05af029..ce15e1a 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -37,7 +37,7 @@ enum greybus_protocol { GREYBUS_PROTOCOL_DISPLAY = 0x0c, GREYBUS_PROTOCOL_CAMERA = 0x0d, GREYBUS_PROTOCOL_SENSOR = 0x0e, - GREYBUS_PROTOCOL_LED = 0x0f, + GREYBUS_PROTOCOL_LIGHTS = 0x0f, GREYBUS_PROTOCOL_VIBRATOR = 0x10, GREYBUS_PROTOCOL_LOOPBACK = 0x11, GREYBUS_PROTOCOL_I2S_RECEIVER = 0x12, -- cgit v0.10.2 From 13956900b069c98a7c97e32d2f18afa11dcf725c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 11 May 2015 14:09:09 -0700 Subject: greybus: audio: fix some sparse static warnings This makes some functions and structures static, as warned by sparse, as they don't need to be global. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/audio-dai.c b/drivers/staging/greybus/audio-dai.c index f2c8ca0..39b72f0 100644 --- a/drivers/staging/greybus/audio-dai.c +++ b/drivers/staging/greybus/audio-dai.c @@ -59,7 +59,7 @@ static const struct snd_soc_dai_ops gb_dai_ops = { .set_fmt = gb_dai_set_fmt, }; -struct snd_soc_dai_driver gb_cpu_dai = { +static struct snd_soc_dai_driver gb_cpu_dai = { .name = "gb-cpu-dai", .playback = { .rates = GB_RATES, diff --git a/drivers/staging/greybus/audio-pcm.c b/drivers/staging/greybus/audio-pcm.c index 28b5e11..9243630 100644 --- a/drivers/staging/greybus/audio-pcm.c +++ b/drivers/staging/greybus/audio-pcm.c @@ -235,7 +235,7 @@ static int gb_pcm_new(struct snd_soc_pcm_runtime *rtd) PREALLOC_BUFFER, PREALLOC_BUFFER_MAX); } -struct snd_soc_platform_driver gb_soc_platform = { +static struct snd_soc_platform_driver gb_soc_platform = { .ops = &gb_pcm_ops, .pcm_new = gb_pcm_new, .pcm_free = gb_pcm_free, diff --git a/drivers/staging/greybus/audio.c b/drivers/staging/greybus/audio.c index 1ef0903..232ba94 100644 --- a/drivers/staging/greybus/audio.c +++ b/drivers/staging/greybus/audio.c @@ -93,7 +93,7 @@ struct gb_card_info_object { }; -struct asoc_simple_card_info *setup_card_info(int device_count) +static struct asoc_simple_card_info *setup_card_info(int device_count) { struct gb_card_info_object *obj; @@ -125,7 +125,7 @@ struct asoc_simple_card_info *setup_card_info(int device_count) return &obj->card_info; } -void free_card_info(struct asoc_simple_card_info *ci) +static void free_card_info(struct asoc_simple_card_info *ci) { struct gb_card_info_object *obj; -- cgit v0.10.2 From 64a54801ae806d482d72fce9583cce7409ec146c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 11 May 2015 14:09:32 -0700 Subject: greybus: audio: fix a bunch of endian issues sparse is rightfully complaining about a lack of converting when accessing or assigning to little endian fields. Fix them all up to work properly. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/audio-gb-cmds.c b/drivers/staging/greybus/audio-gb-cmds.c index ef31916..daa3181 100644 --- a/drivers/staging/greybus/audio-gb-cmds.c +++ b/drivers/staging/greybus/audio-gb-cmds.c @@ -40,7 +40,7 @@ int gb_i2s_mgmt_activate_cport(struct gb_connection *connection, struct gb_i2s_mgmt_activate_cport_request request; memset(&request, 0, sizeof(request)); - request.cport = cport; + request.cport = cpu_to_le16(cport); return gb_operation_sync(connection, GB_I2S_MGMT_TYPE_ACTIVATE_CPORT, &request, sizeof(request), NULL, 0); @@ -52,7 +52,7 @@ int gb_i2s_mgmt_deactivate_cport(struct gb_connection *connection, struct gb_i2s_mgmt_deactivate_cport_request request; memset(&request, 0, sizeof(request)); - request.cport = cport; + request.cport = cpu_to_le16(cport); return gb_operation_sync(connection, GB_I2S_MGMT_TYPE_DEACTIVATE_CPORT, &request, sizeof(request), NULL, 0); @@ -82,7 +82,7 @@ int gb_i2s_mgmt_set_samples_per_message( struct gb_i2s_mgmt_set_samples_per_message_request request; memset(&request, 0, sizeof(request)); - request.samples_per_message = samples_per_message; + request.samples_per_message = cpu_to_le16(samples_per_message); return gb_operation_sync(connection, GB_I2S_MGMT_TYPE_SET_SAMPLES_PER_MESSAGE, @@ -121,14 +121,14 @@ int gb_i2s_mgmt_setup(struct gb_connection *connection) /* Pick 48KHz 16-bits/channel */ for (i = 0, cfg = get_cfg->config; i < CONFIG_COUNT_MAX; i++, cfg++) { - if ((cfg->sample_frequency == GB_SAMPLE_RATE) && + if ((le32_to_cpu(cfg->sample_frequency) == GB_SAMPLE_RATE) && (cfg->num_channels == 2) && (cfg->bytes_per_channel == 2) && (cfg->byte_order & GB_I2S_MGMT_BYTE_ORDER_LE) && - (cfg->spatial_locations == + (le32_to_cpu(cfg->spatial_locations) == (GB_I2S_MGMT_SPATIAL_LOCATION_FL | GB_I2S_MGMT_SPATIAL_LOCATION_FR)) && - (cfg->ll_protocol & GB_I2S_MGMT_PROTOCOL_I2S) && + (le32_to_cpu(cfg->ll_protocol) & GB_I2S_MGMT_PROTOCOL_I2S) && (cfg->ll_mclk_role & GB_I2S_MGMT_ROLE_MASTER) && (cfg->ll_bclk_role & GB_I2S_MGMT_ROLE_MASTER) && (cfg->ll_wclk_role & GB_I2S_MGMT_ROLE_MASTER) && @@ -148,7 +148,7 @@ int gb_i2s_mgmt_setup(struct gb_connection *connection) memcpy(&set_cfg, cfg, sizeof(set_cfg)); set_cfg.config.byte_order = GB_I2S_MGMT_BYTE_ORDER_LE; - set_cfg.config.ll_protocol = GB_I2S_MGMT_PROTOCOL_I2S; + set_cfg.config.ll_protocol = cpu_to_le32(GB_I2S_MGMT_PROTOCOL_I2S); set_cfg.config.ll_mclk_role = GB_I2S_MGMT_ROLE_MASTER; set_cfg.config.ll_bclk_role = GB_I2S_MGMT_ROLE_MASTER; set_cfg.config.ll_wclk_role = GB_I2S_MGMT_ROLE_MASTER; @@ -191,7 +191,7 @@ int gb_i2s_send_data(struct gb_connection *connection, int ret; gb_req = req_buf; - gb_req->sample_number = sample_num; + gb_req->sample_number = cpu_to_le32(sample_num); memcpy((void *)&gb_req->data[0], source_addr, len); @@ -199,7 +199,7 @@ int gb_i2s_send_data(struct gb_connection *connection, for (; len < MAX_SEND_DATA_LEN; len++) gb_req->data[len] = gb_req->data[len - SAMPLE_SIZE]; - gb_req->size = len; + gb_req->size = cpu_to_le32(len); ret = gb_operation_sync(connection, GB_I2S_DATA_TYPE_SEND_DATA, (void *) gb_req, SEND_DATA_BUF_LEN, NULL, 0); -- cgit v0.10.2 From a04c640e5cf342a491afc06b0d931b7a046aa76b Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 11 May 2015 21:16:34 -0500 Subject: greybus: loopback: fix the type attribute check In gb_loopback_check_attr(), the value of gb->type is checked for validity. The only valid values are 0, 1, and 2. But the check allows the value 3. Fix that. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 9860d64..20aabeb 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -123,7 +123,7 @@ static void gb_loopback_check_attr(struct gb_loopback *gb) { if (gb->ms_wait > 1000) gb->ms_wait = 1000; - if (gb->type > 3) + if (gb->type > 2) gb->type = 0; if (gb->size > GB_LOOPBACK_SIZE_MAX) gb->size = GB_LOOPBACK_SIZE_MAX; -- cgit v0.10.2 From 69f6034792faf0f930f3797a0a3c3c9cf9ac73cc Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 11 May 2015 21:16:35 -0500 Subject: greybus: loopback: return the right error value If an error occurs starting up the loopback thread, the error code is not extracted properly. Fix that. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 20aabeb..85e2fe7 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -362,7 +362,7 @@ static int gb_loopback_connection_init(struct gb_connection *connection) gb_loopback_reset_stats(gb); gb->task = kthread_run(gb_loopback_fn, gb, "gb_loopback"); if (IS_ERR(gb->task)) { - retval = IS_ERR(gb->task); + retval = PTR_ERR(gb->task); goto error; } -- cgit v0.10.2 From 48f19ee8244776a8e7fb47bac1a2b09e9920d035 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 11 May 2015 21:16:36 -0500 Subject: greybus: loopback: fix an incorrect comment Fix a comment that incorrectly says the delay between messages is limited to 1024 msec; it actually must be <= 1000 msec. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 85e2fe7..e1e40ea 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -148,7 +148,7 @@ gb_loopback_ro_attr(error, d); gb_loopback_attr(type, d); /* Size of transfer message payload: 0-4096 bytes */ gb_loopback_attr(size, u); -/* Time to wait between two messages: 0-1024 ms */ +/* Time to wait between two messages: 0-1000 ms */ gb_loopback_attr(ms_wait, d); #define dev_stats_attrs(name) \ -- cgit v0.10.2 From 91262c3ab70a02949db294b55b4cd49b8ae6505e Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 11 May 2015 21:16:37 -0500 Subject: greybus: loopback: symbolically define max wait time Use a symbolic constant to define the maximum time (number of milliseconds) to delay between initiated operations. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index e1e40ea..f7538aa 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -55,6 +55,7 @@ struct gb_loopback { #define GB_LOOPBACK_TYPE_PING 0x02 #define GB_LOOPBACK_TYPE_TRANSFER 0x03 +#define GB_LOOPBACK_MS_WAIT_MAX 1000 #define GB_LOOPBACK_SIZE_MAX SZ_4K /* Define get_version() routine */ @@ -121,8 +122,8 @@ static DEVICE_ATTR_RW(field) static void gb_loopback_reset_stats(struct gb_loopback *gb); static void gb_loopback_check_attr(struct gb_loopback *gb) { - if (gb->ms_wait > 1000) - gb->ms_wait = 1000; + if (gb->ms_wait > GB_LOOPBACK_MS_WAIT_MAX) + gb->ms_wait = GB_LOOPBACK_MS_WAIT_MAX; if (gb->type > 2) gb->type = 0; if (gb->size > GB_LOOPBACK_SIZE_MAX) -- cgit v0.10.2 From 48cc8b8bbaf0a6767380e4e2e55df3258e47bef6 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 11 May 2015 21:16:38 -0500 Subject: greybus: loopback: define loopback functions symbolically Add some symbols to indicate what kind of "function" the loopback thread is supposed to be performing--the type of traffic it generates over its connection. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index f7538aa..decaf71 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -55,6 +55,12 @@ struct gb_loopback { #define GB_LOOPBACK_TYPE_PING 0x02 #define GB_LOOPBACK_TYPE_TRANSFER 0x03 +/* Current function (type of traffic generated by the loopback thread) */ +#define GB_LOOPBACK_FN_NONE 0x00 +#define GB_LOOPBACK_FN_PING 0x01 +#define GB_LOOPBACK_FN_XFER 0x02 +#define GB_LOOPBACK_FN_COUNT 0x03 + #define GB_LOOPBACK_MS_WAIT_MAX 1000 #define GB_LOOPBACK_SIZE_MAX SZ_4K @@ -124,8 +130,8 @@ static void gb_loopback_check_attr(struct gb_loopback *gb) { if (gb->ms_wait > GB_LOOPBACK_MS_WAIT_MAX) gb->ms_wait = GB_LOOPBACK_MS_WAIT_MAX; - if (gb->type > 2) - gb->type = 0; + if (gb->type >= GB_LOOPBACK_FN_COUNT) + gb->type = GB_LOOPBACK_FN_NONE; if (gb->size > GB_LOOPBACK_SIZE_MAX) gb->size = GB_LOOPBACK_SIZE_MAX; gb->error = 0; @@ -310,13 +316,13 @@ static int gb_loopback_fn(void *data) struct gb_loopback *gb = (struct gb_loopback *)data; while (!kthread_should_stop()) { - if (gb->type == 0) { + if (gb->type == GB_LOOPBACK_FN_NONE) { msleep(1000); continue; } - if (gb->type == 1) + if (gb->type == GB_LOOPBACK_FN_PING) error = gb_loopback_ping(gb, &tlat); - if (gb->type == 2) + else if (gb->type == GB_LOOPBACK_FN_XFER) error = gb_loopback_transfer(gb, &tlat, gb->size); if (error) gb->error++; -- cgit v0.10.2 From ac1c2840bd41e89d55fccabe86cf9a3e2d56a652 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 11 May 2015 21:16:39 -0500 Subject: greybus: loopback: support module-initiated requests There's no reason we can't support loopback pings or transfers initiated by the module. Allow it. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index decaf71..285e44b 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -242,6 +242,48 @@ static int gb_loopback_ping(struct gb_loopback *gb, struct timeval *tping) return retval; } +static int gb_loopback_request_recv(u8 type, struct gb_operation *operation) +{ + struct gb_connection *connection = operation->connection; + struct gb_loopback_transfer_request *request; + struct gb_loopback_transfer_response *response; + u32 len; + + /* By convention, the AP initiates the version operation */ + switch (type) { + case GB_LOOPBACK_TYPE_PROTOCOL_VERSION: + dev_err(&connection->dev, + "module-initiated version operation\n"); + return -EINVAL; + case GB_LOOPBACK_TYPE_PING: + return 0; + case GB_LOOPBACK_TYPE_TRANSFER: + if (operation->request->payload_size < sizeof(*request)) { + dev_err(&connection->dev, + "transfer request too small (%zu < %zu)\n", + operation->request->payload_size, + sizeof(*request)); + return -EINVAL; /* -EMSGSIZE */ + } + request = operation->request->payload; + len = le32_to_cpu(request->len); + if (len) { + if (!gb_operation_response_alloc(operation, len)) { + dev_err(&connection->dev, + "error allocating response\n"); + return -ENOMEM; + } + response = operation->response->payload; + memcpy(response->data, request->data, len); + } + return 0; + default: + dev_err(&connection->dev, + "unsupported request: %hhu\n", type); + return -EINVAL; + } +} + static void gb_loopback_reset_stats(struct gb_loopback *gb) { struct gb_loopback_stats reset = { @@ -397,7 +439,7 @@ static struct gb_protocol loopback_protocol = { .minor = GB_LOOPBACK_VERSION_MINOR, .connection_init = gb_loopback_connection_init, .connection_exit = gb_loopback_connection_exit, - .request_recv = NULL, /* no incoming requests */ + .request_recv = gb_loopback_request_recv, }; gb_protocol_driver(&loopback_protocol); -- cgit v0.10.2 From 65cac604b21ae8c99bd501b369c254707f51c252 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Wed, 13 May 2015 18:59:00 +0100 Subject: greybus: make: check kernel configuration options Add checks for options that shall be enabled in the kernel config and for options that shall be disable. To add options to list append them to CONFIG_OPTIONS_ENABLE or CONFIG_OPTIONS_DISABLE respectively. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index f366da6..130758f 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -44,6 +44,22 @@ KERNELDIR ?= /lib/modules/$(KERNELVER)/build INSTALL_MOD_PATH ?= /.. PWD := $(shell pwd) +# kernel config option that shall be enable +CONFIG_OPTIONS_ENABLE := SYSFS SPI USB SND_SOC + +# kernel config option that shall be disable +CONFIG_OPTIONS_DISABLE := + +# this only run in kbuild part of the makefile +ifneq ($(KERNELRELEASE),) +$(foreach opt,$(CONFIG_OPTIONS_ENABLE),$(if $(CONFIG_$(opt)),, \ + $(error CONFIG_$(opt) is disabled in the kernel configuration and must be enable \ + to continue compilation))) +$(foreach opt,$(CONFIG_OPTIONS_DISABLE),$(if $(filter m y, $(CONFIG_$(opt))), \ + $(error CONFIG_$(opt) is enabled in the kernel configuration and must be disable \ + to continue compilation),)) +endif + # add -Wall to try to catch everything we can. ccFlags-y := -Wall -- cgit v0.10.2 From 6f8528e0bea76850a153a98e47ad60aecf112801 Mon Sep 17 00:00:00 2001 From: Phong Tran Date: Thu, 14 May 2015 23:03:04 +0700 Subject: greybus: loopback: add more clean up when init connection fails It should remove the object from sysfs when loopback connection init error. Signed-off-by: Phong Tran Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 285e44b..eeec332 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -401,23 +401,25 @@ static int gb_loopback_connection_init(struct gb_connection *connection) connection->private = gb; retval = sysfs_create_groups(&connection->dev.kobj, loopback_groups); if (retval) - goto error; + goto out_free; /* Check the version */ retval = get_version(gb); if (retval) - goto error; + goto out_get_ver; gb_loopback_reset_stats(gb); gb->task = kthread_run(gb_loopback_fn, gb, "gb_loopback"); if (IS_ERR(gb->task)) { retval = PTR_ERR(gb->task); - goto error; + goto out_get_ver; } return 0; -error: +out_get_ver: + sysfs_remove_groups(&connection->dev.kobj, loopback_groups); +out_free: kfree(gb); return retval; } -- cgit v0.10.2 From 6b17492eee00cbaac20b8431e8fa63f137a9ca5c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 14 May 2015 10:39:35 -0700 Subject: greybus: vibrator: convert idr to be an ida All we need is a simple ida, so use that interface instead of the more "complex" idr one. Bonus is we don't need to fix the locking issue I forgot about when using an idr, as ida has one built-in. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/vibrator.c b/drivers/staging/greybus/vibrator.c index aefd2cd..20f09bb 100644 --- a/drivers/staging/greybus/vibrator.c +++ b/drivers/staging/greybus/vibrator.c @@ -93,7 +93,7 @@ static struct class vibrator_class = { #endif }; -static DEFINE_IDR(minors); +static DEFINE_IDA(minors); static int gb_vibrator_connection_init(struct gb_connection *connection) { @@ -117,7 +117,7 @@ static int gb_vibrator_connection_init(struct gb_connection *connection) * there is a "real" device somewhere in the kernel for this, but I * can't find it at the moment... */ - vib->minor = idr_alloc(&minors, vib, 0, 0, GFP_KERNEL); + vib->minor = ida_simple_get(&minors, 0, 0, GFP_KERNEL); if (vib->minor < 0) { retval = vib->minor; goto error; @@ -126,7 +126,7 @@ static int gb_vibrator_connection_init(struct gb_connection *connection) "vibrator%d", vib->minor); if (IS_ERR(dev)) { retval = -EINVAL; - goto err_idr_remove; + goto err_ida_remove; } vib->dev = dev; @@ -139,14 +139,14 @@ static int gb_vibrator_connection_init(struct gb_connection *connection) retval = sysfs_create_group(&dev->kobj, vibrator_groups[0]); if (retval) { device_unregister(dev); - goto err_idr_remove; + goto err_ida_remove; } #endif return 0; -err_idr_remove: - idr_remove(&minors, vib->minor); +err_ida_remove: + ida_simple_remove(&minors, vib->minor); error: kfree(vib); return retval; @@ -159,7 +159,7 @@ static void gb_vibrator_connection_exit(struct gb_connection *connection) #if LINUX_VERSION_CODE <= KERNEL_VERSION(3,11,0) sysfs_remove_group(&vib->dev->kobj, vibrator_groups[0]); #endif - idr_remove(&minors, vib->minor); + ida_simple_remove(&minors, vib->minor); device_unregister(vib->dev); kfree(vib); } -- cgit v0.10.2 From 5bd5f00c30fa8be047e7905739dcf6ff689718c4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 14 May 2015 10:40:02 -0700 Subject: greybus: connection: remove lock around ida_simple_* functions ida_simple_* has a built-in spinlock, no need to grab another lock when accessing it. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 5ec161b..51d505e 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -63,9 +63,7 @@ static bool gb_connection_hd_cport_id_alloc(struct gb_connection *connection) struct ida *ida = &connection->hd->cport_id_map; int id; - spin_lock_irq(&gb_connections_lock); id = ida_simple_get(ida, 0, HOST_DEV_CPORT_ID_MAX, GFP_ATOMIC); - spin_unlock_irq(&gb_connections_lock); if (id < 0) return false; @@ -81,9 +79,7 @@ static void gb_connection_hd_cport_id_free(struct gb_connection *connection) { struct ida *ida = &connection->hd->cport_id_map; - spin_lock_irq(&gb_connections_lock); ida_simple_remove(ida, connection->hd_cport_id); - spin_unlock_irq(&gb_connections_lock); connection->hd_cport_id = CPORT_ID_BAD; } -- cgit v0.10.2 From e806c7fb8e9bae87fc23958c3789f2c2f96f54a4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 8 May 2015 15:50:17 +0200 Subject: greybus: raw: add raw greybus kernel driver This adds a driver that implements the greybus Raw protocol as specified. It preserves the message boundries by only allowing a read to receive a "full" message, and any write() call also is passed in a single greybus request. Totally untested, given that we have no raw firmware or gbsim code yet. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Rui Miguel Silva diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 130758f..e636fe01 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -28,6 +28,7 @@ gb-phy-y := gpb.o \ gb-vibrator-y := vibrator.o gb-battery-y := battery.o gb-loopback-y := loopback.o +gb-raw-y := raw.o gb-es1-y := es1.o gb-es2-y := es2.o @@ -36,6 +37,7 @@ obj-m += gb-phy.o obj-m += gb-vibrator.o obj-m += gb-battery.o obj-m += gb-loopback.o +obj-m += gb-raw.o obj-m += gb-es1.o obj-m += gb-es2.o diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index ce15e1a..076d711 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -43,6 +43,7 @@ enum greybus_protocol { GREYBUS_PROTOCOL_I2S_RECEIVER = 0x12, GREYBUS_PROTOCOL_I2S_TRANSMITTER = 0x13, /* ... */ + GREYBUS_PROTOCOL_RAW = 0xfe, GREYBUS_PROTOCOL_VENDOR = 0xff, }; diff --git a/drivers/staging/greybus/raw.c b/drivers/staging/greybus/raw.c new file mode 100644 index 0000000..eb43acc --- /dev/null +++ b/drivers/staging/greybus/raw.c @@ -0,0 +1,370 @@ +/* + * Greybus driver for the Raw protocol + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ +#include +#include +#include +#include +#include +#include +#include + +#include "greybus.h" + +struct gb_raw { + struct gb_connection *connection; + u8 version_major; + u8 version_minor; + + struct list_head list; + int list_data; + struct mutex list_lock; + dev_t dev; + struct cdev cdev; + struct device *device; +}; + +/* Version of the Greybus raw protocol we support */ +#define GB_RAW_VERSION_MAJOR 0x00 +#define GB_RAW_VERSION_MINOR 0x01 + +/* Greybus raw request types */ +#define GB_RAW_TYPE_INVALID 0x00 +#define GB_RAW_TYPE_PROTOCOL_VERSION 0x01 +#define GB_RAW_TYPE_SEND 0x02 + +/* Define get_version() routine */ +define_get_version(gb_raw, RAW); + +struct gb_raw_send_request { + __le32 len; + __u8 data[0]; +}; + +struct raw_data { + struct list_head entry; + u32 len; + u8 data[0]; +}; + +static struct class *raw_class; +static int raw_major; +static const struct file_operations raw_fops; +static DEFINE_IDA(minors); + +/* Number of minor devices this driver supports */ +#define NUM_MINORS 256 + +/* Maximum size of any one send data buffer we support */ +#define MAX_PACKET_SIZE (PAGE_SIZE * 2) + +/* + * Maximum size of the data in the receive buffer we allow before we start to + * drop messages on the floor + */ +#define MAX_DATA_SIZE (MAX_PACKET_SIZE * 8) + +/* + * Add the raw data message to the list of received messages. + */ +static int receive_data(struct gb_raw *raw, u32 len, u8 *data) +{ + struct raw_data *raw_data; + int retval = 0; + + if (len > MAX_PACKET_SIZE) { + dev_err(raw->device, "Too big of a data packet, rejected\n"); + return -EINVAL; + } + + mutex_lock(&raw->list_lock); + if ((raw->list_data + len) > MAX_DATA_SIZE) { + dev_err(raw->device, + "Too much data in receive buffer, now dropping packets\n"); + retval = -EINVAL; + goto exit; + } + + raw_data = kmalloc(sizeof(*raw_data) + len, GFP_KERNEL); + if (!raw_data) { + retval = -ENOMEM; + goto exit; + } + + raw->list_data += len; + raw_data->len = len; + memcpy(&raw_data->data[0], data, len); + + list_add_tail(&raw_data->entry, &raw->list); +exit: + mutex_unlock(&raw->list_lock); + return retval; +} + +static int gb_raw_receive(u8 type, struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_raw *raw = connection->private; + struct gb_raw_send_request *receive; + u32 len; + + if (type != GB_RAW_TYPE_SEND) { + dev_err(raw->device, "unknown request type %d\n", type); + return -EINVAL; + } + + /* Verify size of payload */ + if (op->request->payload_size < sizeof(*receive)) { + dev_err(raw->device, "raw receive request too small\n"); + return -EINVAL; + } + receive = op->request->payload; + len = le32_to_cpu(receive->len); + if (len != (int)(op->request->payload_size - sizeof(__le32))) { + dev_err(raw->device, + "raw receive request wrong size %d vs %d\n", + len, + (int)(op->request->payload_size - sizeof(__le32))); + return -EINVAL; + } + if (len == 0) { + dev_err(raw->device, "raw receive request of 0 bytes?\n"); + return -EINVAL; + } + + return receive_data(raw, len, receive->data); +} + +static int gb_raw_send(struct gb_raw *raw, u32 len, const char __user *data) +{ + struct gb_connection *connection = raw->connection; + struct gb_raw_send_request *request; + int retval; + + request = kmalloc(len + sizeof(*request), GFP_KERNEL); + if (!request) + return -ENOMEM; + + if (copy_from_user(&request->data[0], data, len)) { + kfree(request); + return -EFAULT; + } + + request->len = cpu_to_le32(len); + + retval = gb_operation_sync(connection, GB_RAW_TYPE_SEND, + request, len + sizeof(*request), + NULL, 0); + + kfree(request); + return retval; +} + +static int gb_raw_connection_init(struct gb_connection *connection) +{ + struct gb_raw *raw; + int retval; + int minor; + + raw = kzalloc(sizeof(*raw), GFP_KERNEL); + if (!raw) + return -ENOMEM; + + raw->connection = connection; + connection->private = raw; + + /* Check the protocol version */ + retval = get_version(raw); + if (retval) + goto error_free; + + INIT_LIST_HEAD(&raw->list); + mutex_init(&raw->list_lock); + + minor = ida_simple_get(&minors, 0, 0, GFP_KERNEL); + if (minor < 0) { + retval = minor; + goto error_free; + } + + raw->dev = MKDEV(raw_major, minor); + cdev_init(&raw->cdev, &raw_fops); + retval = cdev_add(&raw->cdev, raw->dev, 1); + if (retval) + goto error_cdev; + + raw->device = device_create(raw_class, &connection->dev, raw->dev, raw, + "gb!raw%d", minor); + if (IS_ERR(raw->device)) { + retval = PTR_ERR(raw->device); + goto error_device; + } + + return 0; + +error_device: + cdev_del(&raw->cdev); + +error_cdev: + ida_simple_remove(&minors, minor); + +error_free: + kfree(raw); + return retval; +} + +static void gb_raw_connection_exit(struct gb_connection *connection) +{ + struct gb_raw *raw = connection->private; + struct raw_data *raw_data; + struct raw_data *temp; + + // FIXME - handle removing a connection when the char device node is open. + cdev_del(&raw->cdev); + ida_simple_remove(&minors, MINOR(raw->dev)); + device_del(raw->device); + mutex_lock(&raw->list_lock); + list_for_each_entry_safe(raw_data, temp, &raw->list, entry) { + list_del(&raw_data->entry); + kfree(raw_data); + } + mutex_unlock(&raw->list_lock); + + kfree(raw); +} + +static struct gb_protocol raw_protocol = { + .name = "raw", + .id = GREYBUS_PROTOCOL_RAW, + .major = GB_RAW_VERSION_MAJOR, + .minor = GB_RAW_VERSION_MINOR, + .connection_init = gb_raw_connection_init, + .connection_exit = gb_raw_connection_exit, + .request_recv = gb_raw_receive, +}; + +/* + * Character device node interfaces. + * + * Note, we are using read/write to only allow a single read/write per message. + * This means for read(), you have to provide a big enough buffer for the full + * message to be copied into. If the buffer isn't big enough, the read() will + * fail with -ENOSPC. + */ + +static int raw_open(struct inode *inode, struct file *file) +{ + struct cdev *cdev = inode->i_cdev; + struct gb_raw *raw = container_of(cdev, struct gb_raw, cdev); + + file->private_data = raw; + return 0; +} + +static ssize_t raw_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct gb_raw *raw = file->private_data; + int retval; + + if (!count) + return 0; + + if (count > MAX_PACKET_SIZE) + return -E2BIG; + + retval = gb_raw_send(raw, count, buf); + if (retval) + return retval; + + return count; +} + +static ssize_t raw_read(struct file *file, char __user *buf, size_t count, + loff_t *ppos) +{ + struct gb_raw *raw = file->private_data; + int retval = 0; + struct raw_data *raw_data; + + mutex_lock(&raw->list_lock); + if (list_empty(&raw->list)) + goto exit; + + raw_data = list_first_entry(&raw->list, struct raw_data, entry); + if (raw_data->len > count) { + retval = -ENOSPC; + goto exit; + } + + if (copy_to_user(buf, &raw_data->data[0], raw_data->len)) { + retval = -EFAULT; + goto exit; + } + + list_del(&raw_data->entry); + raw->list_data -= raw_data->len; + retval = raw_data->len; + kfree(raw_data); + +exit: + mutex_unlock(&raw->list_lock); + return retval; +} + +static const struct file_operations raw_fops = { + .owner = THIS_MODULE, + .write = raw_write, + .read = raw_read, + .open = raw_open, + .llseek = noop_llseek, +}; + +static int raw_init(void) +{ + dev_t dev; + int retval; + + raw_class = class_create(THIS_MODULE, "gb_raw"); + if (IS_ERR(raw_class)) { + retval = PTR_ERR(raw_class); + goto error_class; + } + + retval = alloc_chrdev_region(&dev, 0, NUM_MINORS, "gb_raw"); + if (retval < 0) + goto error_chrdev; + + + raw_major = MAJOR(dev); + + retval = gb_protocol_register(&raw_protocol); + if (retval) + goto error_gb; + + return 0; + +error_gb: + unregister_chrdev_region(dev, NUM_MINORS); +error_chrdev: + class_destroy(raw_class); +error_class: + return retval; +} + +static void __exit raw_exit(void) +{ + gb_protocol_deregister(&raw_protocol); + unregister_chrdev_region(MKDEV(raw_major, 0), NUM_MINORS); + class_destroy(raw_class); +} + +module_init(raw_init); +module_exit(raw_exit); + +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 4f8ab1105da2f13ae52dc2f2c31fb7bea1301793 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 20 May 2015 16:31:19 +0530 Subject: greybus: raw: include uaccess.h to fix warning This is what I get over mainline: greybus/raw.c: In function 'gb_raw_send': greybus/raw.c:153:2: error: implicit declaration of function 'copy_from_user' [-Werror=implicit-function-declaration] if (copy_from_user(&request->data[0], data, len)) { ^ greybus/raw.c: In function 'raw_read': greybus/raw.c:305:2: error: implicit declaration of function 'copy_to_user' [-Werror=implicit-function-declaration] if (copy_to_user(buf, &raw_data->data[0], raw_data->len)) { ^ Fix this by including uaccess.h. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/raw.c b/drivers/staging/greybus/raw.c index eb43acc..515c187 100644 --- a/drivers/staging/greybus/raw.c +++ b/drivers/staging/greybus/raw.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "greybus.h" -- cgit v0.10.2 From 8de925b973263694edcb13aa30f2fe0273163c0f Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 20 May 2015 16:32:28 +0530 Subject: greybus: gpio: fix tab/space mistake Spaces were present in place of tab. Fix that. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 5ed1895..6a4a0f2 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -282,7 +282,7 @@ static int gb_gpio_irq_set_type(struct irq_data *d, unsigned int type) dev_err(chip->dev, "failed to set irq type: %d\n", ret); } - break; + break; default: dev_err(chip->dev, "unsupported irq type: %u\n", type); ret = -EINVAL; -- cgit v0.10.2 From 4890f31966a6991e7652f8a365ff59c1ba313c9d Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 20 May 2015 16:33:57 +0530 Subject: greybus: spi: Move structure definitions into gpbridge.h In order to facilitate re-use of spi structures, split them out of independent files and add them into a shared gpbridge.h This will be a prereq to sharing these headers w/ gbsim. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpbridge.h b/drivers/staging/greybus/gpbridge.h index 85cc385..c820805 100644 --- a/drivers/staging/greybus/gpbridge.h +++ b/drivers/staging/greybus/gpbridge.h @@ -403,4 +403,90 @@ struct gb_i2s_send_data_request { }; /* send data has no response at all */ + +/* SPI */ + +/* Version of the Greybus spi protocol we support */ +#define GB_SPI_VERSION_MAJOR 0x00 +#define GB_SPI_VERSION_MINOR 0x01 + +/* Should match up with modes in linux/spi/spi.h */ +#define GB_SPI_MODE_CPHA 0x01 /* clock phase */ +#define GB_SPI_MODE_CPOL 0x02 /* clock polarity */ +#define GB_SPI_MODE_MODE_0 (0|0) /* (original MicroWire) */ +#define GB_SPI_MODE_MODE_1 (0|GB_SPI_MODE_CPHA) +#define GB_SPI_MODE_MODE_2 (GB_SPI_MODE_CPOL|0) +#define GB_SPI_MODE_MODE_3 (GB_SPI_MODE_CPOL|GB_SPI_MODE_CPHA) +#define GB_SPI_MODE_CS_HIGH 0x04 /* chipselect active high? */ +#define GB_SPI_MODE_LSB_FIRST 0x08 /* per-word bits-on-wire */ +#define GB_SPI_MODE_3WIRE 0x10 /* SI/SO signals shared */ +#define GB_SPI_MODE_LOOP 0x20 /* loopback mode */ +#define GB_SPI_MODE_NO_CS 0x40 /* 1 dev/bus, no chipselect */ +#define GB_SPI_MODE_READY 0x80 /* slave pulls low to pause */ + +/* Should match up with flags in linux/spi/spi.h */ +#define GB_SPI_FLAG_HALF_DUPLEX BIT(0) /* can't do full duplex */ +#define GB_SPI_FLAG_NO_RX BIT(1) /* can't do buffer read */ +#define GB_SPI_FLAG_NO_TX BIT(2) /* can't do buffer write */ + +/* Greybus spi operation types */ +#define GB_SPI_TYPE_INVALID 0x00 +#define GB_SPI_TYPE_PROTOCOL_VERSION 0x01 +#define GB_SPI_TYPE_MODE 0x02 +#define GB_SPI_TYPE_FLAGS 0x03 +#define GB_SPI_TYPE_BITS_PER_WORD_MASK 0x04 +#define GB_SPI_TYPE_NUM_CHIPSELECT 0x05 +#define GB_SPI_TYPE_TRANSFER 0x06 + +/* mode request has no payload */ +struct gb_spi_mode_response { + __le16 mode; +}; + +/* flags request has no payload */ +struct gb_spi_flags_response { + __le16 flags; +}; + +/* bits-per-word request has no payload */ +struct gb_spi_bpw_response { + __le32 bits_per_word_mask; +}; + +/* num-chipselects request has no payload */ +struct gb_spi_chipselect_response { + __le16 num_chipselect; +}; + +/** + * struct gb_spi_transfer - a read/write buffer pair + * @speed_hz: Select a speed other than the device default for this transfer. If + * 0 the default (from @spi_device) is used. + * @len: size of rx and tx buffers (in bytes) + * @delay_usecs: microseconds to delay after this transfer before (optionally) + * changing the chipselect status, then starting the next transfer or + * completing this spi_message. + * @cs_change: affects chipselect after this transfer completes + * @bits_per_word: select a bits_per_word other than the device default for this + * transfer. If 0 the default (from @spi_device) is used. + */ +struct gb_spi_transfer { + __le32 speed_hz; + __le32 len; + __le16 delay_usecs; + __u8 cs_change; + __u8 bits_per_word; +}; + +struct gb_spi_transfer_request { + __u8 chip_select; /* of the spi device */ + __u8 mode; /* of the spi device */ + __le16 count; + struct gb_spi_transfer transfers[0]; /* trnasfer_count of these */ +}; + +struct gb_spi_transfer_response { + __u8 data[0]; /* inbound data */ +}; + #endif /* __GB_GPBRIDGE_H__ */ diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index 731639a..a8fb04a 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -14,6 +14,7 @@ #include #include "greybus.h" +#include "gpbridge.h" struct gb_spi { struct gb_connection *connection; @@ -43,89 +44,6 @@ struct gb_spi { u16 num_chipselect; }; -/* Version of the Greybus spi protocol we support */ -#define GB_SPI_VERSION_MAJOR 0x00 -#define GB_SPI_VERSION_MINOR 0x01 - -/* Should match up with modes in linux/spi/spi.h */ -#define GB_SPI_MODE_CPHA 0x01 /* clock phase */ -#define GB_SPI_MODE_CPOL 0x02 /* clock polarity */ -#define GB_SPI_MODE_MODE_0 (0|0) /* (original MicroWire) */ -#define GB_SPI_MODE_MODE_1 (0|GB_SPI_MODE_CPHA) -#define GB_SPI_MODE_MODE_2 (GB_SPI_MODE_CPOL|0) -#define GB_SPI_MODE_MODE_3 (GB_SPI_MODE_CPOL|GB_SPI_MODE_CPHA) -#define GB_SPI_MODE_CS_HIGH 0x04 /* chipselect active high? */ -#define GB_SPI_MODE_LSB_FIRST 0x08 /* per-word bits-on-wire */ -#define GB_SPI_MODE_3WIRE 0x10 /* SI/SO signals shared */ -#define GB_SPI_MODE_LOOP 0x20 /* loopback mode */ -#define GB_SPI_MODE_NO_CS 0x40 /* 1 dev/bus, no chipselect */ -#define GB_SPI_MODE_READY 0x80 /* slave pulls low to pause */ - -/* Should match up with flags in linux/spi/spi.h */ -#define GB_SPI_FLAG_HALF_DUPLEX BIT(0) /* can't do full duplex */ -#define GB_SPI_FLAG_NO_RX BIT(1) /* can't do buffer read */ -#define GB_SPI_FLAG_NO_TX BIT(2) /* can't do buffer write */ - -/* Greybus spi operation types */ -#define GB_SPI_TYPE_INVALID 0x00 -#define GB_SPI_TYPE_PROTOCOL_VERSION 0x01 -#define GB_SPI_TYPE_MODE 0x02 -#define GB_SPI_TYPE_FLAGS 0x03 -#define GB_SPI_TYPE_BITS_PER_WORD_MASK 0x04 -#define GB_SPI_TYPE_NUM_CHIPSELECT 0x05 -#define GB_SPI_TYPE_TRANSFER 0x06 - -/* mode request has no payload */ -struct gb_spi_mode_response { - __le16 mode; -}; - -/* flags request has no payload */ -struct gb_spi_flags_response { - __le16 flags; -}; - -/* bits-per-word request has no payload */ -struct gb_spi_bpw_response { - __le32 bits_per_word_mask; -}; - -/* num-chipselects request has no payload */ -struct gb_spi_chipselect_response { - __le16 num_chipselect; -}; - -/** - * struct gb_spi_transfer - a read/write buffer pair - * @speed_hz: Select a speed other than the device default for this transfer. If - * 0 the default (from @spi_device) is used. - * @len: size of rx and tx buffers (in bytes) - * @delay_usecs: microseconds to delay after this transfer before (optionally) - * changing the chipselect status, then starting the next transfer or - * completing this spi_message. - * @cs_change: affects chipselect after this transfer completes - * @bits_per_word: select a bits_per_word other than the device default for this - * transfer. If 0 the default (from @spi_device) is used. - */ -struct gb_spi_transfer { - __le32 speed_hz; - __le32 len; - __le16 delay_usecs; - __u8 cs_change; - __u8 bits_per_word; -}; - -struct gb_spi_transfer_request { - __u8 chip_select; /* of the spi device */ - __u8 mode; /* of the spi device */ - __le16 count; - struct gb_spi_transfer transfers[0]; /* trnasfer_count of these */ -}; - -struct gb_spi_transfer_response { - __u8 data[0]; /* inbound data */ -}; - /* Routines to transfer data */ static struct gb_operation * gb_spi_operation_create(struct gb_connection *connection, -- cgit v0.10.2 From 8fd46587dbc478168d799fb12828801250086ced Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 20 May 2015 16:47:59 +0530 Subject: greybus: protocol: remove leading underscore from _gb_protocol_find() Remove the unnecessary underscore from _gb_protocol_find(). Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index ba4cc0f..eed77c3 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -16,7 +16,7 @@ static DEFINE_SPINLOCK(gb_protocols_lock); static LIST_HEAD(gb_protocols); /* Caller must hold gb_protocols_lock */ -static struct gb_protocol *_gb_protocol_find(u8 id, u8 major, u8 minor) +static struct gb_protocol *gb_protocol_find(u8 id, u8 major, u8 minor) { struct gb_protocol *protocol; @@ -119,8 +119,8 @@ int gb_protocol_deregister(struct gb_protocol *protocol) return 0; spin_lock_irq(&gb_protocols_lock); - protocol = _gb_protocol_find(protocol->id, protocol->major, - protocol->minor); + protocol = gb_protocol_find(protocol->id, protocol->major, + protocol->minor); if (protocol) { protocol_count = protocol->count; if (!protocol_count) @@ -142,7 +142,7 @@ struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor) u8 protocol_count; spin_lock_irq(&gb_protocols_lock); - protocol = _gb_protocol_find(id, major, minor); + protocol = gb_protocol_find(id, major, minor); if (protocol) { if (!try_module_get(protocol->owner)) { protocol = NULL; @@ -204,7 +204,7 @@ void gb_protocol_put(struct gb_protocol *protocol) minor = protocol->minor; spin_lock_irq(&gb_protocols_lock); - protocol = _gb_protocol_find(id, major, minor); + protocol = gb_protocol_find(id, major, minor); if (protocol) { protocol_count = protocol->count; if (protocol_count) -- cgit v0.10.2 From 12eba9f8ef4e71eed17b08b89835c758c2a0c473 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 20 May 2015 16:48:00 +0530 Subject: greybus: connection: name routines consistently Routines should be named this way: gb__. Fix all routines that don't match this. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 51d505e..e87521e 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -14,7 +14,7 @@ static DEFINE_SPINLOCK(gb_connections_lock); -struct gb_connection *gb_hd_connection_find(struct greybus_host_device *hd, +struct gb_connection *gb_connection_hd_find(struct greybus_host_device *hd, u16 cport_id) { struct gb_connection *connection = NULL; @@ -40,7 +40,7 @@ void greybus_data_rcvd(struct greybus_host_device *hd, u16 cport_id, { struct gb_connection *connection; - connection = gb_hd_connection_find(hd, cport_id); + connection = gb_connection_hd_find(hd, cport_id); if (!connection) { dev_err(hd->parent, "nonexistent connection (%zu bytes dropped)\n", length); diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 7febf4e..93886b4 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -53,7 +53,7 @@ void gb_connection_destroy(struct gb_connection *connection); int gb_connection_init(struct gb_connection *connection); void gb_connection_exit(struct gb_connection *connection); -struct gb_connection *gb_hd_connection_find(struct greybus_host_device *hd, +struct gb_connection *gb_connection_hd_find(struct greybus_host_device *hd, u16 cport_id); void greybus_data_rcvd(struct greybus_host_device *hd, u16 cport_id, -- cgit v0.10.2 From 5ddf738e944b652e8d2ddb17f97c0c72ee05667c Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 20 May 2015 16:48:01 +0530 Subject: greybus: endo: name routines consistently Routines should be named this way: gb__. Fix all routines that don't match this. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c index 80d9397..42f26f0 100644 --- a/drivers/staging/greybus/endo.c +++ b/drivers/staging/greybus/endo.c @@ -62,7 +62,7 @@ static const struct attribute_group *endo_groups[] = { NULL, }; -static void greybus_endo_release(struct device *dev) +static void gb_endo_release(struct device *dev) { struct gb_endo *endo = to_gb_endo(dev); @@ -71,7 +71,7 @@ static void greybus_endo_release(struct device *dev) struct device_type greybus_endo_type = { .name = "greybus_endo", - .release = greybus_endo_release, + .release = gb_endo_release, }; @@ -272,7 +272,7 @@ static bool validate_back_ribs(struct greybus_host_device *hd, * Validate the endo-id passed from SVC. Error out if its not a valid Endo, * else return structure representing ribs positions on front and back of Endo. */ -static int gb_validate_endo_id(struct greybus_host_device *hd, +static int gb_endo_validate_id(struct greybus_host_device *hd, struct endo_layout *layout, u16 endo_id) { /* Validate Endo Size */ @@ -434,7 +434,7 @@ struct gb_endo *gb_endo_create(struct greybus_host_device *hd) return NULL; /* First check if the value supplied is a valid endo id */ - if (gb_validate_endo_id(hd, &endo->layout, endo_id)) + if (gb_endo_validate_id(hd, &endo->layout, endo_id)) goto free_endo; endo->id = endo_id; -- cgit v0.10.2 From 51b5d8d783fe8ee6b272f09ef645747e53166c7f Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 20 May 2015 17:33:51 +0530 Subject: greybus: interface: name routines consistently Routines should be named this way: gb__. Fix all routines that don't match this. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 1dc1339..843ddc2 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -175,7 +175,7 @@ static void svc_hotplug(struct svc_function_hotplug *hotplug, return; } dev_dbg(hd->parent, "interface id %d added\n", interface_id); - gb_add_interface(hd, interface_id, hotplug->data, + gb_interface_add(hd, interface_id, hotplug->data, payload_length - 0x02); break; @@ -189,7 +189,7 @@ static void svc_hotplug(struct svc_function_hotplug *hotplug, return; } dev_dbg(hd->parent, "interface id %d removed\n", interface_id); - gb_remove_interface(hd, interface_id); + gb_interface_remove(hd, interface_id); break; default: diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index db1da8a..45fa4c3 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -215,7 +215,7 @@ void greybus_remove_hd(struct greybus_host_device *hd) * with this host controller before freeing the memory associated with * the host controller. */ - gb_remove_interfaces(hd); + gb_interfaces_remove(hd); gb_endo_remove(hd->endo); kref_put_mutex(&hd->kref, free_hd, &hd_mutex); } diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 28b3c4f..7a4c7dc 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -54,7 +54,7 @@ struct gb_interface *gb_interface_find(struct greybus_host_device *hd, return NULL; } -static void greybus_interface_release(struct device *dev) +static void gb_interface_release(struct device *dev) { struct gb_interface *intf = to_gb_interface(dev); @@ -63,7 +63,7 @@ static void greybus_interface_release(struct device *dev) struct device_type greybus_interface_type = { .name = "greybus_interface", - .release = greybus_interface_release, + .release = gb_interface_release, }; /* @@ -161,12 +161,12 @@ static void gb_interface_destroy(struct gb_interface *intf) } /** - * gb_add_interface + * gb_interface_add * * Pass in a buffer that _should_ contain a Greybus manifest * and register a greybus device structure with the kernel core. */ -void gb_add_interface(struct greybus_host_device *hd, u8 interface_id, u8 *data, +void gb_interface_add(struct greybus_host_device *hd, u8 interface_id, u8 *data, int size) { struct gb_interface *intf; @@ -201,7 +201,7 @@ err_parse: gb_interface_destroy(intf); } -void gb_remove_interface(struct greybus_host_device *hd, u8 interface_id) +void gb_interface_remove(struct greybus_host_device *hd, u8 interface_id) { struct gb_interface *intf = gb_interface_find(hd, interface_id); @@ -212,7 +212,7 @@ void gb_remove_interface(struct greybus_host_device *hd, u8 interface_id) interface_id); } -void gb_remove_interfaces(struct greybus_host_device *hd) +void gb_interfaces_remove(struct greybus_host_device *hd) { struct gb_interface *intf, *temp; diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 9ee5b55..88a7a80 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -47,10 +47,10 @@ static inline void *gb_interface_get_drvdata(struct gb_interface *intf) struct gb_interface *gb_interface_find(struct greybus_host_device *hd, u8 interface_id); -void gb_add_interface(struct greybus_host_device *hd, u8 interface_id, u8 *data, +void gb_interface_add(struct greybus_host_device *hd, u8 interface_id, u8 *data, int size); -void gb_remove_interface(struct greybus_host_device *hd, u8 interface_id); -void gb_remove_interfaces(struct greybus_host_device *hd); +void gb_interface_remove(struct greybus_host_device *hd, u8 interface_id); +void gb_interfaces_remove(struct greybus_host_device *hd); #endif /* __INTERFACE_H */ -- cgit v0.10.2 From c16b63e851e1100e670ab47a094e8c414996e6f9 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 20 May 2015 16:48:04 +0530 Subject: greybus: module: name routines consistently Routines should be named this way: gb__. Fix all routines that don't match this. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index 8ed96a8..07b7e44 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -71,7 +71,7 @@ static struct attribute *module_attrs[] = { }; ATTRIBUTE_GROUPS(module); -static void greybus_module_release(struct device *dev) +static void gb_module_release(struct device *dev) { struct gb_module *module = to_gb_module(dev); @@ -80,7 +80,7 @@ static void greybus_module_release(struct device *dev) struct device_type greybus_module_type = { .name = "greybus_module", - .release = greybus_module_release, + .release = gb_module_release, }; struct module_find { -- cgit v0.10.2 From 8ba2522fa8397c894c2d42ed3461e23862ea6a45 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 20 May 2015 16:54:22 +0530 Subject: greybus: raw: move module_{init|exit} to the end of functions This is what coding guidelines say. Lets do it. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/raw.c b/drivers/staging/greybus/raw.c index 515c187..d93d052 100644 --- a/drivers/staging/greybus/raw.c +++ b/drivers/staging/greybus/raw.c @@ -357,6 +357,7 @@ error_chrdev: error_class: return retval; } +module_init(raw_init); static void __exit raw_exit(void) { @@ -364,8 +365,6 @@ static void __exit raw_exit(void) unregister_chrdev_region(MKDEV(raw_major, 0), NUM_MINORS); class_destroy(raw_class); } - -module_init(raw_init); module_exit(raw_exit); MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From f5db53b4c764ca4d1b1f1ca2bea5e276fc3befe1 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 20 May 2015 16:56:46 +0530 Subject: greybus: gpbridge: rename gpb.c to gpbridge.c That's what followed for .h, etc.. Rename for better consistency. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index e636fe01..e5cae29 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -10,7 +10,7 @@ greybus-y := core.o \ protocol.o \ operation.o -gb-phy-y := gpb.o \ +gb-phy-y := gpbridge.o \ sdio.o \ uart.o \ pwm.o \ diff --git a/drivers/staging/greybus/gpb.c b/drivers/staging/greybus/gpb.c deleted file mode 100644 index 2324270..0000000 --- a/drivers/staging/greybus/gpb.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Greybus GP Bridge driver - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include - -#include "greybus.h" - - -static int __init gpbridge_init(void) -{ - if (gb_gpio_protocol_init()) { - pr_err("error initializing gpio protocol\n"); - goto error_gpio; - } - if (gb_pwm_protocol_init()) { - pr_err("error initializing pwm protocol\n"); - goto error_pwm; - } - if (gb_uart_protocol_init()) { - pr_err("error initializing uart protocol\n"); - goto error_uart; - } - if (gb_sdio_protocol_init()) { - pr_err("error initializing sdio protocol\n"); - goto error_sdio; - } - if (gb_usb_protocol_init()) { - pr_err("error initializing usb protocol\n"); - goto error_usb; - } - if (gb_i2c_protocol_init()) { - pr_err("error initializing i2c protocol\n"); - goto error_i2c; - } - if (gb_spi_protocol_init()) { - pr_err("error initializing spi protocol\n"); - goto error_spi; - } - if (gb_hid_protocol_init()) { - pr_err("error initializing hid protocol\n"); - goto error_hid; - } - if (gb_audio_protocol_init()) { - pr_err("error initializing audio protocols\n"); - goto error_audio; - } - - return 0; - -error_audio: - gb_hid_protocol_exit(); -error_hid: - gb_spi_protocol_exit(); -error_spi: - gb_i2c_protocol_exit(); -error_i2c: - gb_usb_protocol_exit(); -error_usb: - gb_sdio_protocol_exit(); -error_sdio: - gb_uart_protocol_exit(); -error_uart: - gb_pwm_protocol_exit(); -error_pwm: - gb_gpio_protocol_exit(); -error_gpio: - return -EPROTO; -} -module_init(gpbridge_init); - -static void __exit gpbridge_exit(void) -{ - gb_audio_protocol_exit(); - gb_hid_protocol_exit(); - gb_spi_protocol_exit(); - gb_i2c_protocol_exit(); - gb_usb_protocol_exit(); - gb_sdio_protocol_exit(); - gb_uart_protocol_exit(); - gb_pwm_protocol_exit(); - gb_gpio_protocol_exit(); -} -module_exit(gpbridge_exit); - -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c new file mode 100644 index 0000000..2324270 --- /dev/null +++ b/drivers/staging/greybus/gpbridge.c @@ -0,0 +1,98 @@ +/* + * Greybus GP Bridge driver + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include + +#include "greybus.h" + + +static int __init gpbridge_init(void) +{ + if (gb_gpio_protocol_init()) { + pr_err("error initializing gpio protocol\n"); + goto error_gpio; + } + if (gb_pwm_protocol_init()) { + pr_err("error initializing pwm protocol\n"); + goto error_pwm; + } + if (gb_uart_protocol_init()) { + pr_err("error initializing uart protocol\n"); + goto error_uart; + } + if (gb_sdio_protocol_init()) { + pr_err("error initializing sdio protocol\n"); + goto error_sdio; + } + if (gb_usb_protocol_init()) { + pr_err("error initializing usb protocol\n"); + goto error_usb; + } + if (gb_i2c_protocol_init()) { + pr_err("error initializing i2c protocol\n"); + goto error_i2c; + } + if (gb_spi_protocol_init()) { + pr_err("error initializing spi protocol\n"); + goto error_spi; + } + if (gb_hid_protocol_init()) { + pr_err("error initializing hid protocol\n"); + goto error_hid; + } + if (gb_audio_protocol_init()) { + pr_err("error initializing audio protocols\n"); + goto error_audio; + } + + return 0; + +error_audio: + gb_hid_protocol_exit(); +error_hid: + gb_spi_protocol_exit(); +error_spi: + gb_i2c_protocol_exit(); +error_i2c: + gb_usb_protocol_exit(); +error_usb: + gb_sdio_protocol_exit(); +error_sdio: + gb_uart_protocol_exit(); +error_uart: + gb_pwm_protocol_exit(); +error_pwm: + gb_gpio_protocol_exit(); +error_gpio: + return -EPROTO; +} +module_init(gpbridge_init); + +static void __exit gpbridge_exit(void) +{ + gb_audio_protocol_exit(); + gb_hid_protocol_exit(); + gb_spi_protocol_exit(); + gb_i2c_protocol_exit(); + gb_usb_protocol_exit(); + gb_sdio_protocol_exit(); + gb_uart_protocol_exit(); + gb_pwm_protocol_exit(); + gb_gpio_protocol_exit(); +} +module_exit(gpbridge_exit); + +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 27551b1d5f9bc99881915adc558c2c6113846a40 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 20 May 2015 17:20:09 +0530 Subject: greybus: protocol: Add gb_gpbridge_protocol_driver() There are many gpbridge protocol drivers that need gb_protocol_driver() without the module_init/exit() lines. Lets create one for them. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index 7958802..95e5b68 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -90,6 +90,7 @@ extern void gb_hid_protocol_exit(void); extern int gb_audio_protocol_init(void); extern void gb_audio_protocol_exit(void); +/* __protocol: Pointer to struct gb_protocol */ #define gb_protocol_driver(__protocol) \ static int __init protocol_init(void) \ { \ @@ -102,6 +103,17 @@ static void __exit protocol_exit(void) \ } \ module_exit(protocol_exit) +/* __protocol: string matching name of struct gb_protocol */ +#define gb_gpbridge_protocol_driver(__protocol) \ +int __init gb_##__protocol##_init(void) \ +{ \ + return gb_protocol_register(&__protocol); \ +} \ +void __exit gb_##__protocol##_exit(void) \ +{ \ + gb_protocol_deregister(&__protocol); \ +} \ + /* * Macro to create get_version() routine for protocols * @__device: name of the device struct -- cgit v0.10.2 From bdac599c70409bbf48e77971e2b9ecc2a66ef151 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 20 May 2015 17:20:10 +0530 Subject: greybus: Use gb_gpbridge_protocol_init() Start using gb_gpbridge_protocol_init() in gpbridge drivers. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 6a4a0f2..871f2d0 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -672,12 +672,4 @@ static struct gb_protocol gpio_protocol = { .request_recv = gb_gpio_request_recv, }; -int gb_gpio_protocol_init(void) -{ - return gb_protocol_register(&gpio_protocol); -} - -void gb_gpio_protocol_exit(void) -{ - gb_protocol_deregister(&gpio_protocol); -} +gb_gpbridge_protocol_driver(gpio_protocol); diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index 00dc7e5..2f6e68c 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -529,12 +529,4 @@ static struct gb_protocol hid_protocol = { .request_recv = gb_hid_irq_handler, }; -int gb_hid_protocol_init(void) -{ - return gb_protocol_register(&hid_protocol); -} - -void gb_hid_protocol_exit(void) -{ - gb_protocol_deregister(&hid_protocol); -} +gb_gpbridge_protocol_driver(hid_protocol); diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c index 6fdbf11..14fdea1 100644 --- a/drivers/staging/greybus/i2c.c +++ b/drivers/staging/greybus/i2c.c @@ -358,12 +358,4 @@ static struct gb_protocol i2c_protocol = { .request_recv = NULL, /* no incoming requests */ }; -int gb_i2c_protocol_init(void) -{ - return gb_protocol_register(&i2c_protocol); -} - -void gb_i2c_protocol_exit(void) -{ - gb_protocol_deregister(&i2c_protocol); -} +gb_gpbridge_protocol_driver(i2c_protocol); diff --git a/drivers/staging/greybus/pwm.c b/drivers/staging/greybus/pwm.c index 7495716..7f675bf 100644 --- a/drivers/staging/greybus/pwm.c +++ b/drivers/staging/greybus/pwm.c @@ -246,12 +246,4 @@ static struct gb_protocol pwm_protocol = { .request_recv = NULL, /* no incoming requests */ }; -int gb_pwm_protocol_init(void) -{ - return gb_protocol_register(&pwm_protocol); -} - -void gb_pwm_protocol_exit(void) -{ - gb_protocol_deregister(&pwm_protocol); -} +gb_gpbridge_protocol_driver(pwm_protocol); diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index d324846..9a0348c 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -88,12 +88,4 @@ static struct gb_protocol sdio_protocol = { .request_recv = NULL, /* no incoming requests */ }; -int gb_sdio_protocol_init(void) -{ - return gb_protocol_register(&sdio_protocol); -} - -void gb_sdio_protocol_exit(void) -{ - gb_protocol_deregister(&sdio_protocol); -} +gb_gpbridge_protocol_driver(sdio_protocol); diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index a8fb04a..430c3ad 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -348,12 +348,4 @@ static struct gb_protocol spi_protocol = { .request_recv = NULL, }; -int gb_spi_protocol_init(void) -{ - return gb_protocol_register(&spi_protocol); -} - -void gb_spi_protocol_exit(void) -{ - gb_protocol_deregister(&spi_protocol); -} +gb_gpbridge_protocol_driver(spi_protocol); diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 35ab3ca..47de969 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -745,12 +745,4 @@ static struct gb_protocol uart_protocol = { .request_recv = NULL, /* FIXME we have 2 types of requests!!! */ }; -int gb_uart_protocol_init(void) -{ - return gb_protocol_register(&uart_protocol); -} - -void gb_uart_protocol_exit(void) -{ - gb_protocol_deregister(&uart_protocol); -} +gb_gpbridge_protocol_driver(uart_protocol); diff --git a/drivers/staging/greybus/usb.c b/drivers/staging/greybus/usb.c index ea97841..609b7cc 100644 --- a/drivers/staging/greybus/usb.c +++ b/drivers/staging/greybus/usb.c @@ -362,12 +362,4 @@ static struct gb_protocol usb_protocol = { .request_recv = NULL, /* FIXME we have requests!!! */ }; -int gb_usb_protocol_init(void) -{ - return gb_protocol_register(&usb_protocol); -} - -void gb_usb_protocol_exit(void) -{ - gb_protocol_deregister(&usb_protocol); -} +gb_gpbridge_protocol_driver(usb_protocol); -- cgit v0.10.2 From fed78bf6a2452cfb9ef997779c73175a1933206c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 May 2015 11:22:41 +0200 Subject: greybus: remove unnecessary greybus.h includes Remove unnecessary greybus.h include from header files. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 93886b4..8992b75 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -12,8 +12,6 @@ #include -#include "greybus.h" - enum gb_connection_state { GB_CONNECTION_STATE_INVALID = 0, GB_CONNECTION_STATE_DISABLED = 1, diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index 95e5b68..8bc3f76 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -10,8 +10,7 @@ #ifndef __PROTOCOL_H #define __PROTOCOL_H -#include "greybus.h" - +struct gb_connection; struct gb_operation; /* version request has no payload */ -- cgit v0.10.2 From d966820f2c28c621d4912a8277fa43a69242e8d5 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 May 2015 11:22:42 +0200 Subject: greybus: remove unused prototypes from header Remove a couple of unused function prototypes from the greybus header file. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 109727f..0a25d0c 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -155,9 +155,6 @@ struct dentry *gb_debugfs_get(void); extern struct bus_type greybus_bus_type; -int gb_uart_device_init(struct gb_connection *connection); -void gb_uart_device_exit(struct gb_connection *connection); - int svc_set_route_send(struct gb_bundle *bundle, struct greybus_host_device *hd); -- cgit v0.10.2 From d933667a1e44be0d3fa137ec31686303c42c16fc Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 May 2015 11:22:43 +0200 Subject: greybus: fix host-device buffer constraints Host devices impose buffer-size constraints on Greybus core which are taken into account when allocating messages. Make sure to verify these constraints when the host device is allocated, rather than when the first message is allocated. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 45fa4c3..e32d6c4 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -173,7 +173,8 @@ static void free_hd(struct kref *kref) } struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver, - struct device *parent) + struct device *parent, + size_t buffer_size_max) { struct greybus_host_device *hd; @@ -187,6 +188,16 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver return NULL; } + /* + * Make sure to never allocate messages larger than what the Greybus + * protocol supports. + */ + if (buffer_size_max > GB_OPERATION_MESSAGE_SIZE_MAX) { + dev_warn(parent, "limiting buffer size to %u\n", + GB_OPERATION_MESSAGE_SIZE_MAX); + buffer_size_max = GB_OPERATION_MESSAGE_SIZE_MAX; + } + hd = kzalloc(sizeof(*hd) + driver->hd_priv_size, GFP_KERNEL); if (!hd) return NULL; @@ -197,6 +208,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver INIT_LIST_HEAD(&hd->interfaces); INIT_LIST_HEAD(&hd->connections); ida_init(&hd->cport_id_map); + hd->buffer_size_max = buffer_size_max; hd->endo = gb_endo_create(hd); if (!hd->endo) { diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 4bba5d5..e0fae26 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -98,22 +98,6 @@ static void cport_out_callback(struct urb *urb); static void usb_log_enable(struct es1_ap_dev *es1); static void usb_log_disable(struct es1_ap_dev *es1); -/* - * Buffer constraints for the host driver. - * - * A "buffer" is used to hold data to be transferred for Greybus by - * the host driver. A buffer is represented by a "buffer pointer", - * which defines a region of memory used by the host driver for - * transferring the data. When Greybus allocates a buffer, it must - * do so subject to the constraints associated with the host driver. - * - * size_max: The maximum size of a buffer - */ -static void hd_buffer_constraints(struct greybus_host_device *hd) -{ - hd->buffer_size_max = ES1_GBUF_MSG_SIZE_MAX; -} - #define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ static int submit_svc(struct svc_msg *svc_msg, struct greybus_host_device *hd) { @@ -571,15 +555,12 @@ static int ap_probe(struct usb_interface *interface, udev = usb_get_dev(interface_to_usbdev(interface)); - hd = greybus_create_hd(&es1_driver, &udev->dev); + hd = greybus_create_hd(&es1_driver, &udev->dev, ES1_GBUF_MSG_SIZE_MAX); if (!hd) { usb_put_dev(udev); return -ENOMEM; } - /* Fill in the buffer allocation constraints */ - hd_buffer_constraints(hd); - es1 = hd_to_es1(hd); es1->hd = hd; es1->usb_intf = interface; diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index cc73fbd..05aac3d 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -98,22 +98,6 @@ static void cport_out_callback(struct urb *urb); static void usb_log_enable(struct es1_ap_dev *es1); static void usb_log_disable(struct es1_ap_dev *es1); -/* - * Buffer constraints for the host driver. - * - * A "buffer" is used to hold data to be transferred for Greybus by - * the host driver. A buffer is represented by a "buffer pointer", - * which defines a region of memory used by the host driver for - * transferring the data. When Greybus allocates a buffer, it must - * do so subject to the constraints associated with the host driver. - * - * size_max: The maximum size of a buffer - */ -static void hd_buffer_constraints(struct greybus_host_device *hd) -{ - hd->buffer_size_max = ES1_GBUF_MSG_SIZE_MAX; -} - #define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ static int submit_svc(struct svc_msg *svc_msg, struct greybus_host_device *hd) { @@ -571,15 +555,12 @@ static int ap_probe(struct usb_interface *interface, udev = usb_get_dev(interface_to_usbdev(interface)); - hd = greybus_create_hd(&es1_driver, &udev->dev); + hd = greybus_create_hd(&es1_driver, &udev->dev, ES1_GBUF_MSG_SIZE_MAX); if (!hd) { usb_put_dev(udev); return -ENOMEM; } - /* Fill in the buffer allocation constraints */ - hd_buffer_constraints(hd); - es1 = hd_to_es1(hd); es1->hd = hd; es1->usb_intf = interface; diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 0a25d0c..dbb4e78 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -105,7 +105,8 @@ struct greybus_host_device { }; struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *hd, - struct device *parent); + struct device *parent, + size_t buffer_size_max); void greybus_remove_hd(struct greybus_host_device *hd); struct greybus_driver { diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 1ec930c..c78ccc0 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -17,12 +17,6 @@ /* The default amount of time a request is given to complete */ #define OPERATION_TIMEOUT_DEFAULT 1000 /* milliseconds */ -/* - * XXX This needs to be coordinated with host driver parameters - * XXX May need to reduce to allow for message header within a page - */ -#define GB_OPERATION_MESSAGE_SIZE_MAX 4096 - static struct kmem_cache *gb_operation_cache; static struct kmem_cache *gb_message_cache; @@ -282,12 +276,6 @@ gb_operation_message_alloc(struct greybus_host_device *hd, u8 type, struct gb_operation_msg_hdr *header; size_t message_size = payload_size + sizeof(*header); - if (hd->buffer_size_max > GB_OPERATION_MESSAGE_SIZE_MAX) { - pr_warn("limiting buffer size to %u\n", - GB_OPERATION_MESSAGE_SIZE_MAX); - hd->buffer_size_max = GB_OPERATION_MESSAGE_SIZE_MAX; - } - if (message_size > hd->buffer_size_max) { pr_warn("requested message size too big (%zu > %zu)\n", message_size, hd->buffer_size_max); @@ -936,9 +924,6 @@ EXPORT_SYMBOL_GPL(gb_operation_sync); int gb_operation_init(void) { - BUILD_BUG_ON(GB_OPERATION_MESSAGE_SIZE_MAX > - U16_MAX - sizeof(struct gb_operation_msg_hdr)); - gb_message_cache = kmem_cache_create("gb_message_cache", sizeof(struct gb_message), 0, 0, NULL); if (!gb_message_cache) diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 82b8fe5..3b02db5 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -69,6 +69,8 @@ struct gb_operation_msg_hdr { __u8 pad[2]; /* must be zero (ignore when read) */ } __aligned(sizeof(u64)); +#define GB_OPERATION_MESSAGE_SIZE_MAX 4096 + /* * Protocol code should only examine the payload and payload_size * fields. All other fields are intended to be private to the -- cgit v0.10.2 From c38cf10bbe35ba6fa10437809585fd4d0b3b604d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 May 2015 11:22:44 +0200 Subject: greybus: operation: allow maximum-sized messages Increase the maximum allowed buffer size to the full 16-bit range supported by the protocol. Note that host devices will generally use smaller buffers than the maximum. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 3b02db5..1edd512 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -69,7 +69,7 @@ struct gb_operation_msg_hdr { __u8 pad[2]; /* must be zero (ignore when read) */ } __aligned(sizeof(u64)); -#define GB_OPERATION_MESSAGE_SIZE_MAX 4096 +#define GB_OPERATION_MESSAGE_SIZE_MAX U16_MAX /* * Protocol code should only examine the payload and payload_size -- cgit v0.10.2 From 8e929a8230794c4b034d0f4b658aa03702f3800d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 May 2015 11:22:45 +0200 Subject: greybus: core: add lower-limit for host-device buffers Make sure we never end up with a host device with maximum buffer size smaller than the shortest Greybus message. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index e32d6c4..91dcc5b 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -188,6 +188,11 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver return NULL; } + if (buffer_size_max < GB_OPERATION_MESSAGE_SIZE_MIN) { + dev_err(parent, "greybus host-device buffers too small\n"); + return NULL; + } + /* * Make sure to never allocate messages larger than what the Greybus * protocol supports. diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 1edd512..740aacc 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -69,6 +69,7 @@ struct gb_operation_msg_hdr { __u8 pad[2]; /* must be zero (ignore when read) */ } __aligned(sizeof(u64)); +#define GB_OPERATION_MESSAGE_SIZE_MIN sizeof(struct gb_operation_msg_hdr) #define GB_OPERATION_MESSAGE_SIZE_MAX U16_MAX /* -- cgit v0.10.2 From d52b35f6b62c8b9e1b7e10010daa0370f8252f1d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 May 2015 11:22:46 +0200 Subject: greybus: operation: add helper to retrieve max payload size Add helper to retrieve the maximum payload size for operations on a specific connection. Note that the helper is not inlined due to how the header files are currently organised, but it is not expected to be called after a connection has been initialised either. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index c78ccc0..f595b97 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -504,6 +504,14 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, } EXPORT_SYMBOL_GPL(gb_operation_create); +size_t gb_operation_get_payload_size_max(struct gb_connection *connection) +{ + struct greybus_host_device *hd = connection->hd; + + return hd->buffer_size_max - sizeof(struct gb_operation_msg_hdr); +} +EXPORT_SYMBOL_GPL(gb_operation_get_payload_size_max); + static struct gb_operation * gb_operation_create_incoming(struct gb_connection *connection, u16 id, u8 type, void *data, size_t size) diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 740aacc..0199976 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -130,6 +130,7 @@ void gb_connection_recv(struct gb_connection *connection, int gb_operation_result(struct gb_operation *operation); +size_t gb_operation_get_payload_size_max(struct gb_connection *connection); struct gb_operation *gb_operation_create(struct gb_connection *connection, u8 type, size_t request_size, size_t response_size); -- cgit v0.10.2 From 8d346df0620eaeddfa1333d413596898fa7e576a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 May 2015 11:47:24 +0200 Subject: greybus: gpbridge: fix section mismatches Fix section mismatches introduced by b27227ce93c0 ("greybus: Use gb_gpbridge_protocol_init()"), which added __exit annotation to gpbridge-protocol exit functions that are called in the error path of gpbridge_init, which lives in the init section. This triggered the following modpost warning: WARNING: modpost: Found 8 section mismatch(es). Fixes: 16b33d100bff ("protocol: Add gb_gpbridge_protocol_driver()") Fixes: b27227ce93c0 ("greybus: Use gb_gpbridge_protocol_init()") Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index 8bc3f76..f6739f3 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -108,7 +108,7 @@ int __init gb_##__protocol##_init(void) \ { \ return gb_protocol_register(&__protocol); \ } \ -void __exit gb_##__protocol##_exit(void) \ +void gb_##__protocol##_exit(void) \ { \ gb_protocol_deregister(&__protocol); \ } \ -- cgit v0.10.2 From 0e995aab21dc4a74a4e2daca5df027937cb0b975 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Thu, 21 May 2015 15:54:27 -0700 Subject: greybus: gb-audio: Set clock edges to match rt5647 codec requirements The rt5647 codec on speaker and mediabar modules require that the following clock edge settings: ll_wclk_change_edge GB_I2S_MGMT_EDGE_FALLING ll_wclk_tx_edge GB_I2S_MGMT_EDGE_RISING ll_wclk_rx_edge GB_I2S_MGMT_EDGE_FALLING (Those are the setting that work, at least). So make the Greybus audio driver configure the GPBridge with those settings. Signed-off-by: Mark A. Greer Tested-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio-gb-cmds.c b/drivers/staging/greybus/audio-gb-cmds.c index daa3181..ffecf3a 100644 --- a/drivers/staging/greybus/audio-gb-cmds.c +++ b/drivers/staging/greybus/audio-gb-cmds.c @@ -134,8 +134,8 @@ int gb_i2s_mgmt_setup(struct gb_connection *connection) (cfg->ll_wclk_role & GB_I2S_MGMT_ROLE_MASTER) && (cfg->ll_wclk_polarity & GB_I2S_MGMT_POLARITY_NORMAL) && (cfg->ll_wclk_change_edge & GB_I2S_MGMT_EDGE_FALLING) && - (cfg->ll_wclk_tx_edge & GB_I2S_MGMT_EDGE_FALLING) && - (cfg->ll_wclk_rx_edge & GB_I2S_MGMT_EDGE_RISING) && + (cfg->ll_wclk_tx_edge & GB_I2S_MGMT_EDGE_RISING) && + (cfg->ll_wclk_rx_edge & GB_I2S_MGMT_EDGE_FALLING) && (cfg->ll_data_offset == 1)) break; } @@ -153,9 +153,9 @@ int gb_i2s_mgmt_setup(struct gb_connection *connection) set_cfg.config.ll_bclk_role = GB_I2S_MGMT_ROLE_MASTER; set_cfg.config.ll_wclk_role = GB_I2S_MGMT_ROLE_MASTER; set_cfg.config.ll_wclk_polarity = GB_I2S_MGMT_POLARITY_NORMAL; - set_cfg.config.ll_wclk_change_edge = GB_I2S_MGMT_EDGE_RISING; - set_cfg.config.ll_wclk_tx_edge = GB_I2S_MGMT_EDGE_FALLING; - set_cfg.config.ll_wclk_rx_edge = GB_I2S_MGMT_EDGE_RISING; + set_cfg.config.ll_wclk_change_edge = GB_I2S_MGMT_EDGE_FALLING; + set_cfg.config.ll_wclk_tx_edge = GB_I2S_MGMT_EDGE_RISING; + set_cfg.config.ll_wclk_rx_edge = GB_I2S_MGMT_EDGE_FALLING; ret = gb_i2s_mgmt_set_configuration(connection, &set_cfg); if (ret) { -- cgit v0.10.2 From 555a0645b17114c559a2079ed64a8edb079b2339 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Thu, 21 May 2015 15:54:48 -0700 Subject: greybus: gb-audio: Allocate space for 20 configurations The greybus code requires that an operation's response buffer be the exact size of the response; however, the size of the response to the GB_I2S_MGMT_TYPE_GET_SUPPORTED_CONFIGURATIONS operation is unknown. To fix this, an extension to the I2S specification is required. In the meantime, set the number of configurations returned to 20 because that is how many configurations will be returned (using "insider knowledge" of the firmware). Signed-off-by: Mark A. Greer Tested-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio.h b/drivers/staging/greybus/audio.h index 6a337d1..fb88a48 100644 --- a/drivers/staging/greybus/audio.h +++ b/drivers/staging/greybus/audio.h @@ -20,7 +20,7 @@ #define CONFIG_SAMPLES_PER_MSG 48L #define CONFIG_PERIOD_NS 1000000 /* send msg every 1ms */ -#define CONFIG_COUNT_MAX 32 +#define CONFIG_COUNT_MAX 20 #define CONFIG_I2S_REMOTE_DATA_CPORT 7 /* XXX shouldn't be hardcoded...*/ #define RT5647_SLAVE_ADDR 0x1b /* from toshiba/quanta code */ -- cgit v0.10.2 From 34aa7e1cadef05f9494ff1f0c4977e762d9f32fa Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Thu, 21 May 2015 15:56:56 -0700 Subject: greybus: gb-audio: Clean up codec name generation Instead of using the fixed suffix, '6-001b', in the codec name, generate it from the I2S adapter number and I2C address of the codec. Signed-off-by: Mark A. Greer Acked-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio.c b/drivers/staging/greybus/audio.c index 232ba94..3e8c242 100644 --- a/drivers/staging/greybus/audio.c +++ b/drivers/staging/greybus/audio.c @@ -19,6 +19,9 @@ #define GB_AUDIO_DATA_DRIVER_NAME "gb_audio_data" #define GB_AUDIO_MGMT_DRIVER_NAME "gb_audio_mgmt" +#define RT5647_I2C_ADAPTER_NR 6 +#define RT5647_I2C_ADDR 0x1b + /* * gb_snd management functions */ @@ -111,7 +114,8 @@ static struct asoc_simple_card_info *setup_card_info(int device_count) #endif #if USE_RT5645 obj->card_info.daifmt = GB_FMTS; - sprintf(obj->codec_name, "rt5645.%s", "6-001b"); /* XXX do i2c bus addr dynamically */ + sprintf(obj->codec_name, "rt5645.%d-%04x", RT5647_I2C_ADAPTER_NR, + RT5647_I2C_ADDR); obj->card_info.codec_dai.name = "rt5645-aif1"; obj->card_info.codec_dai.fmt = SND_SOC_DAIFMT_CBM_CFM; obj->card_info.codec_dai.sysclk = 12288000; diff --git a/drivers/staging/greybus/audio.h b/drivers/staging/greybus/audio.h index fb88a48..5095df9 100644 --- a/drivers/staging/greybus/audio.h +++ b/drivers/staging/greybus/audio.h @@ -22,7 +22,6 @@ #define CONFIG_COUNT_MAX 20 #define CONFIG_I2S_REMOTE_DATA_CPORT 7 /* XXX shouldn't be hardcoded...*/ -#define RT5647_SLAVE_ADDR 0x1b /* from toshiba/quanta code */ /* Switch between dummy spdif and jetson rt5645 codec */ #define USE_RT5645 0 -- cgit v0.10.2 From 4c739e3adad46aded0428144681fdaa6437b9e84 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Thu, 21 May 2015 15:56:57 -0700 Subject: greybus: gb-audio: Fix DAI formats and master/slave settings Set the various DAI formats so the bridge on the module is the master of all clocks and the codec is the slave. The only DAI protocol currently supported is I2S. Signed-off-by: Mark A. Greer Acked-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio.c b/drivers/staging/greybus/audio.c index 3e8c242..03196a0 100644 --- a/drivers/staging/greybus/audio.c +++ b/drivers/staging/greybus/audio.c @@ -110,14 +110,15 @@ static struct asoc_simple_card_info *setup_card_info(int device_count) obj->card_info.platform = obj->platform_name; obj->card_info.cpu_dai.name = obj->dai_name; #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0) - obj->card_info.cpu_dai.fmt = GB_FMTS; + obj->card_info.cpu_dai.fmt = SND_SOC_DAIFMT_CBM_CFM; #endif #if USE_RT5645 - obj->card_info.daifmt = GB_FMTS; + obj->card_info.daifmt = SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_I2S; sprintf(obj->codec_name, "rt5645.%d-%04x", RT5647_I2C_ADAPTER_NR, RT5647_I2C_ADDR); obj->card_info.codec_dai.name = "rt5645-aif1"; - obj->card_info.codec_dai.fmt = SND_SOC_DAIFMT_CBM_CFM; + obj->card_info.codec_dai.fmt = SND_SOC_DAIFMT_CBS_CFS; obj->card_info.codec_dai.sysclk = 12288000; #else sprintf(obj->codec_name, "spdif-dit"); -- cgit v0.10.2 From 827e27e8fe3cf1ce29343ed87e042075194ac6ca Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Thu, 21 May 2015 15:56:58 -0700 Subject: greybus: gb-audio: cpu_dai.fmt does not exist in v4.1 The asoc_simple_dai structure does not contain the 'fmt' member in Linux kernel version v4.1 and later so only build code that uses it when the kernel version is earlier than v4.1. Signed-off-by: Mark A. Greer Acked-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio.c b/drivers/staging/greybus/audio.c index 03196a0..d4d1eff 100644 --- a/drivers/staging/greybus/audio.c +++ b/drivers/staging/greybus/audio.c @@ -118,7 +118,9 @@ static struct asoc_simple_card_info *setup_card_info(int device_count) sprintf(obj->codec_name, "rt5645.%d-%04x", RT5647_I2C_ADAPTER_NR, RT5647_I2C_ADDR); obj->card_info.codec_dai.name = "rt5645-aif1"; +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0) obj->card_info.codec_dai.fmt = SND_SOC_DAIFMT_CBS_CFS; +#endif obj->card_info.codec_dai.sysclk = 12288000; #else sprintf(obj->codec_name, "spdif-dit"); -- cgit v0.10.2 From 415b83111caac7cd1b90e0df104f81bae8e6e4dd Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Thu, 21 May 2015 15:56:59 -0700 Subject: greybus: gb-audio: Add I2C device for rt5647 codec Add the I2C device node for the rt5647 codec. Eventually, this will be done automatically somewhere else but for now its done in the audio driver. Signed-off-by: Mark A. Greer Acked-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio.c b/drivers/staging/greybus/audio.c index d4d1eff..1cc7c04 100644 --- a/drivers/staging/greybus/audio.c +++ b/drivers/staging/greybus/audio.c @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include @@ -157,6 +156,9 @@ static int gb_i2s_transmitter_connection_init(struct gb_connection *connection) struct gb_snd *snd_dev; struct platform_device *codec, *dai; struct asoc_simple_card_info *simple_card; +#if USE_RT5645 + struct i2c_board_info rt5647_info; +#endif unsigned long flags; int ret; @@ -219,6 +221,18 @@ static int gb_i2s_transmitter_connection_init(struct gb_connection *connection) goto out_get_ver; } +#if USE_RT5645 + rt5647_info.addr = RT5647_I2C_ADDR; + strlcpy(rt5647_info.type, "rt5647", I2C_NAME_SIZE); + + snd_dev->rt5647 = i2c_new_device(i2c_get_adapter(RT5647_I2C_ADAPTER_NR), + &rt5647_info); + if (!snd_dev->rt5647) { + pr_err("can't create rt5647 i2c device\n"); + goto out_get_ver; + } +#endif + return 0; out_get_ver: @@ -238,6 +252,10 @@ static void gb_i2s_transmitter_connection_exit(struct gb_connection *connection) snd_dev = (struct gb_snd *)connection->private; +#if USE_RT5645 + i2c_unregister_device(snd_dev->rt5647); +#endif + platform_device_unregister(&snd_dev->card); platform_device_unregister(&snd_dev->cpu_dai); platform_device_unregister(snd_dev->codec); diff --git a/drivers/staging/greybus/audio.h b/drivers/staging/greybus/audio.h index 5095df9..020a8fc 100644 --- a/drivers/staging/greybus/audio.h +++ b/drivers/staging/greybus/audio.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include "greybus.h" @@ -41,6 +42,7 @@ struct gb_snd { struct platform_device cpu_dai; struct platform_device *codec; struct asoc_simple_card_info *simple_card_info; + struct i2c_client *rt5647; struct gb_connection *mgmt_connection; struct gb_connection *i2s_tx_connection; struct gb_connection *i2s_rx_connection; -- cgit v0.10.2 From e803cf712c48e2923b89e134adde56a004a99722 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Thu, 21 May 2015 15:57:00 -0700 Subject: greybus: gb-audio: Remove useless comment Remove comment about adding start delay since it will be done when support for A/V synchronization is added. Signed-off-by: Mark A. Greer Acked-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio-gb-cmds.c b/drivers/staging/greybus/audio-gb-cmds.c index ffecf3a..8a10128 100644 --- a/drivers/staging/greybus/audio-gb-cmds.c +++ b/drivers/staging/greybus/audio-gb-cmds.c @@ -170,7 +170,6 @@ int gb_i2s_mgmt_setup(struct gb_connection *connection) goto free_get_cfg; } - /* XXX Add start delay here (probably 1ms) */ ret = gb_i2s_mgmt_activate_cport(connection, CONFIG_I2S_REMOTE_DATA_CPORT); if (ret) { -- cgit v0.10.2 From f9a4fee7fad79d46ef6a3b0142bed35638c8d620 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Thu, 21 May 2015 15:57:01 -0700 Subject: greybus: gb-audio: Activate TX CPort in PCM workqueue Currently, the I2S TX CPort is configured and activated during the Greybus audio initialization. Unfortunately, this prevents the audio driver from ever changing the I2S configuration. To allow the I2S configuration to change according to ASOC requests, move the CPort activation & deactivation to the audio-pcm workqueue. Now, when audio is running but the CPort is not active, it will be activated. When audio is not running and the CPort is active, it will be deactivated. This has the side-effect of sending the first piece of audio data immediately after activating the CPort which is really how it should work anyway. Signed-off-by: Mark A. Greer Acked-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio-gb-cmds.c b/drivers/staging/greybus/audio-gb-cmds.c index 8a10128..d625f78 100644 --- a/drivers/staging/greybus/audio-gb-cmds.c +++ b/drivers/staging/greybus/audio-gb-cmds.c @@ -165,17 +165,8 @@ int gb_i2s_mgmt_setup(struct gb_connection *connection) ret = gb_i2s_mgmt_set_samples_per_message(connection, CONFIG_SAMPLES_PER_MSG); - if (ret) { + if (ret) pr_err("set_samples_per_msg failed: %d\n", ret); - goto free_get_cfg; - } - - ret = gb_i2s_mgmt_activate_cport(connection, - CONFIG_I2S_REMOTE_DATA_CPORT); - if (ret) { - pr_err("activate_cport failed: %d\n", ret); - goto free_get_cfg; - } free_get_cfg: kfree(get_cfg); diff --git a/drivers/staging/greybus/audio-pcm.c b/drivers/staging/greybus/audio-pcm.c index 9243630..8eb803a 100644 --- a/drivers/staging/greybus/audio-pcm.c +++ b/drivers/staging/greybus/audio-pcm.c @@ -32,15 +32,33 @@ static void gb_pcm_work(struct work_struct *work) struct snd_pcm_substream *substream = snd_dev->substream; struct snd_pcm_runtime *runtime = substream->runtime; unsigned int stride, frames, oldptr; - int period_elapsed; + int period_elapsed, ret; char *address; long len; if (!snd_dev) return; - if (!atomic_read(&snd_dev->running)) + if (!atomic_read(&snd_dev->running)) { + if (snd_dev->cport_active) { + ret = gb_i2s_mgmt_deactivate_cport( + snd_dev->mgmt_connection, + CONFIG_I2S_REMOTE_DATA_CPORT); + if (ret) /* XXX Do what else with failure? */ + pr_err("deactivate_cport failed: %d\n", ret); + + snd_dev->cport_active = false; + } + return; + } else if (!snd_dev->cport_active) { + ret = gb_i2s_mgmt_activate_cport(snd_dev->mgmt_connection, + CONFIG_I2S_REMOTE_DATA_CPORT); + if (ret) + pr_err("activate_cport failed: %d\n", ret); + + snd_dev->cport_active = true; + } address = runtime->dma_area + snd_dev->hwptr_done; @@ -88,6 +106,7 @@ static enum hrtimer_restart gb_pcm_timer_function(struct hrtimer *hrtimer) void gb_pcm_hrtimer_start(struct gb_snd *snd_dev) { atomic_set(&snd_dev->running, 1); + queue_work(snd_dev->workqueue, &snd_dev->work); /* Activates CPort */ hrtimer_start(&snd_dev->timer, ns_to_ktime(CONFIG_PERIOD_NS), HRTIMER_MODE_REL); } @@ -96,6 +115,7 @@ void gb_pcm_hrtimer_stop(struct gb_snd *snd_dev) { atomic_set(&snd_dev->running, 0); hrtimer_cancel(&snd_dev->timer); + queue_work(snd_dev->workqueue, &snd_dev->work); /* Deactivates CPort */ } static int gb_pcm_hrtimer_init(struct gb_snd *snd_dev) diff --git a/drivers/staging/greybus/audio.c b/drivers/staging/greybus/audio.c index 1cc7c04..1057e46 100644 --- a/drivers/staging/greybus/audio.c +++ b/drivers/staging/greybus/audio.c @@ -292,13 +292,11 @@ static int gb_i2s_mgmt_connection_init(struct gb_connection *connection) if (!snd_dev->send_data_req_buf) { ret = -ENOMEM; - goto err_deactivate_cport; + goto err_free_snd_dev; } return 0; -err_deactivate_cport: - gb_i2s_mgmt_deactivate_cport(connection, CONFIG_I2S_REMOTE_DATA_CPORT); err_free_snd_dev: gb_free_snd(snd_dev); return ret; @@ -307,12 +305,6 @@ err_free_snd_dev: static void gb_i2s_mgmt_connection_exit(struct gb_connection *connection) { struct gb_snd *snd_dev = (struct gb_snd *)connection->private; - int ret; - - ret = gb_i2s_mgmt_deactivate_cport(connection, - CONFIG_I2S_REMOTE_DATA_CPORT); - if (ret) - pr_err("deactivate_cport failed: %d\n", ret); kfree(snd_dev->send_data_req_buf); snd_dev->send_data_req_buf = NULL; diff --git a/drivers/staging/greybus/audio.h b/drivers/staging/greybus/audio.h index 020a8fc..50a9ebb 100644 --- a/drivers/staging/greybus/audio.h +++ b/drivers/staging/greybus/audio.h @@ -53,6 +53,7 @@ struct gb_snd { struct snd_pcm_substream *substream; struct hrtimer timer; atomic_t running; + bool cport_active; struct workqueue_struct *workqueue; struct work_struct work; int hwptr_done; -- cgit v0.10.2 From 48229e592f95b4d0071f7711bd4c0e54104724e4 Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Thu, 21 May 2015 15:57:02 -0700 Subject: greybus: gb-audio: Activate TX connection Bundle CPort ID Currently, the audio driver activates & deactivates a predefined CPort ID but that can vary depending on the manifest data of the module. Instead, use the TX connection's Bundle CPort ID which contains the correct CPort ID. Signed-off-by: Mark A. Greer Acked-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio-pcm.c b/drivers/staging/greybus/audio-pcm.c index 8eb803a..30030f8 100644 --- a/drivers/staging/greybus/audio-pcm.c +++ b/drivers/staging/greybus/audio-pcm.c @@ -42,8 +42,8 @@ static void gb_pcm_work(struct work_struct *work) if (!atomic_read(&snd_dev->running)) { if (snd_dev->cport_active) { ret = gb_i2s_mgmt_deactivate_cport( - snd_dev->mgmt_connection, - CONFIG_I2S_REMOTE_DATA_CPORT); + snd_dev->mgmt_connection, + snd_dev->i2s_tx_connection->bundle_cport_id); if (ret) /* XXX Do what else with failure? */ pr_err("deactivate_cport failed: %d\n", ret); @@ -53,7 +53,7 @@ static void gb_pcm_work(struct work_struct *work) return; } else if (!snd_dev->cport_active) { ret = gb_i2s_mgmt_activate_cport(snd_dev->mgmt_connection, - CONFIG_I2S_REMOTE_DATA_CPORT); + snd_dev->i2s_tx_connection->bundle_cport_id); if (ret) pr_err("activate_cport failed: %d\n", ret); diff --git a/drivers/staging/greybus/audio.h b/drivers/staging/greybus/audio.h index 50a9ebb..012c69a 100644 --- a/drivers/staging/greybus/audio.h +++ b/drivers/staging/greybus/audio.h @@ -22,7 +22,6 @@ #define CONFIG_PERIOD_NS 1000000 /* send msg every 1ms */ #define CONFIG_COUNT_MAX 20 -#define CONFIG_I2S_REMOTE_DATA_CPORT 7 /* XXX shouldn't be hardcoded...*/ /* Switch between dummy spdif and jetson rt5645 codec */ #define USE_RT5645 0 -- cgit v0.10.2 From 6b34099ec326e6c94fc5cf3ce3e1e4a9877c43ea Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Thu, 21 May 2015 15:57:03 -0700 Subject: greybus: gb-audio: Set I2S Configuration according to ASOC requests Currently, the audio driver unconditionally sets the I2S configuration to have a sample rate of 48KHz, two channels, 16 bits per channel, in little endian order. Make this more flexible by setting the I2S configuration according to the arguments passed to the PCM 'hw_params' callback. To accomplish this, query for the supported I2S configurations at Greybus protocol init time and save them in the 'snd_dev' structure. When the 'hw_params' callback is called, compare its arguments to the table of supported configurations. If there is a match, set the I2S connection accordingly. Signed-off-by: Mark A. Greer Acked-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio-gb-cmds.c b/drivers/staging/greybus/audio-gb-cmds.c index d625f78..73f47d8 100644 --- a/drivers/staging/greybus/audio-gb-cmds.c +++ b/drivers/staging/greybus/audio-gb-cmds.c @@ -89,21 +89,12 @@ int gb_i2s_mgmt_set_samples_per_message( &request, sizeof(request), NULL, 0); } -/* - * XXX This is sort of a generic "setup" function which probably needs - * to be broken up, and tied into the constraints. - * - * I'm on the fence if we should just dictate that we only support - * 48k, 16bit, 2 channel, and avoid doign the whole probe for configurations - * and then picking one. - */ -int gb_i2s_mgmt_setup(struct gb_connection *connection) +int gb_i2s_mgmt_get_cfgs(struct gb_snd *snd_dev, + struct gb_connection *connection) { struct gb_i2s_mgmt_get_supported_configurations_response *get_cfg; - struct gb_i2s_mgmt_set_configuration_request set_cfg; - struct gb_i2s_mgmt_configuration *cfg; size_t size; - int i, ret; + int ret; size = sizeof(*get_cfg) + (CONFIG_COUNT_MAX * sizeof(get_cfg->config[0])); @@ -116,19 +107,48 @@ int gb_i2s_mgmt_setup(struct gb_connection *connection) size); if (ret) { pr_err("get_supported_config failed: %d\n", ret); - goto free_get_cfg; + goto err_free_get_cfg; } - /* Pick 48KHz 16-bits/channel */ - for (i = 0, cfg = get_cfg->config; i < CONFIG_COUNT_MAX; i++, cfg++) { - if ((le32_to_cpu(cfg->sample_frequency) == GB_SAMPLE_RATE) && - (cfg->num_channels == 2) && - (cfg->bytes_per_channel == 2) && - (cfg->byte_order & GB_I2S_MGMT_BYTE_ORDER_LE) && - (le32_to_cpu(cfg->spatial_locations) == - (GB_I2S_MGMT_SPATIAL_LOCATION_FL | - GB_I2S_MGMT_SPATIAL_LOCATION_FR)) && - (le32_to_cpu(cfg->ll_protocol) & GB_I2S_MGMT_PROTOCOL_I2S) && + snd_dev->i2s_configs = get_cfg; + + return 0; + +err_free_get_cfg: + kfree(get_cfg); + return ret; +} + +void gb_i2s_mgmt_free_cfgs(struct gb_snd *snd_dev) +{ + kfree(snd_dev->i2s_configs); + snd_dev->i2s_configs = NULL; +} + +int gb_i2s_mgmt_set_cfg(struct gb_snd *snd_dev, int rate, int chans, + int bytes_per_chan, int is_le) +{ + struct gb_i2s_mgmt_set_configuration_request set_cfg; + struct gb_i2s_mgmt_configuration *cfg; + int i, ret; + u8 byte_order = GB_I2S_MGMT_BYTE_ORDER_NA; + + if (bytes_per_chan > 1) { + if (is_le) + byte_order = GB_I2S_MGMT_BYTE_ORDER_LE; + else + byte_order = GB_I2S_MGMT_BYTE_ORDER_BE; + } + + for (i = 0, cfg = snd_dev->i2s_configs->config; + i < CONFIG_COUNT_MAX; + i++, cfg++) { + if ((cfg->sample_frequency == cpu_to_le32(rate)) && + (cfg->num_channels == chans) && + (cfg->bytes_per_channel == bytes_per_chan) && + (cfg->byte_order & byte_order) && + (cfg->ll_protocol & + cpu_to_le32(GB_I2S_MGMT_PROTOCOL_I2S)) && (cfg->ll_mclk_role & GB_I2S_MGMT_ROLE_MASTER) && (cfg->ll_bclk_role & GB_I2S_MGMT_ROLE_MASTER) && (cfg->ll_wclk_role & GB_I2S_MGMT_ROLE_MASTER) && @@ -142,12 +162,11 @@ int gb_i2s_mgmt_setup(struct gb_connection *connection) if (i >= CONFIG_COUNT_MAX) { pr_err("No valid configuration\n"); - ret = -EINVAL; - goto free_get_cfg; + return -EINVAL; } memcpy(&set_cfg, cfg, sizeof(set_cfg)); - set_cfg.config.byte_order = GB_I2S_MGMT_BYTE_ORDER_LE; + set_cfg.config.byte_order = byte_order; set_cfg.config.ll_protocol = cpu_to_le32(GB_I2S_MGMT_PROTOCOL_I2S); set_cfg.config.ll_mclk_role = GB_I2S_MGMT_ROLE_MASTER; set_cfg.config.ll_bclk_role = GB_I2S_MGMT_ROLE_MASTER; @@ -157,19 +176,17 @@ int gb_i2s_mgmt_setup(struct gb_connection *connection) set_cfg.config.ll_wclk_tx_edge = GB_I2S_MGMT_EDGE_RISING; set_cfg.config.ll_wclk_rx_edge = GB_I2S_MGMT_EDGE_FALLING; - ret = gb_i2s_mgmt_set_configuration(connection, &set_cfg); + ret = gb_i2s_mgmt_set_configuration(snd_dev->mgmt_connection, &set_cfg); if (ret) { pr_err("set_configuration failed: %d\n", ret); - goto free_get_cfg; + return ret; } - ret = gb_i2s_mgmt_set_samples_per_message(connection, + ret = gb_i2s_mgmt_set_samples_per_message(snd_dev->mgmt_connection, CONFIG_SAMPLES_PER_MSG); if (ret) pr_err("set_samples_per_msg failed: %d\n", ret); -free_get_cfg: - kfree(get_cfg); return ret; } diff --git a/drivers/staging/greybus/audio-pcm.c b/drivers/staging/greybus/audio-pcm.c index 30030f8..b327008 100644 --- a/drivers/staging/greybus/audio-pcm.c +++ b/drivers/staging/greybus/audio-pcm.c @@ -220,6 +220,21 @@ static int gb_pcm_close(struct snd_pcm_substream *substream) static int gb_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct gb_snd *snd_dev; + int rate, chans, bytes_per_chan, is_le, ret; + + snd_dev = snd_soc_dai_get_drvdata(rtd->cpu_dai); + + rate = params_rate(hw_params); + chans = params_channels(hw_params); + bytes_per_chan = snd_pcm_format_width(params_format(hw_params)) / 8; + is_le = snd_pcm_format_little_endian(params_format(hw_params)); + + ret = gb_i2s_mgmt_set_cfg(snd_dev, rate, chans, bytes_per_chan, is_le); + if (ret) + return ret; + return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); } diff --git a/drivers/staging/greybus/audio.c b/drivers/staging/greybus/audio.c index 1057e46..a1acbb0 100644 --- a/drivers/staging/greybus/audio.c +++ b/drivers/staging/greybus/audio.c @@ -286,17 +286,23 @@ static int gb_i2s_mgmt_connection_init(struct gb_connection *connection) goto err_free_snd_dev; } - gb_i2s_mgmt_setup(connection); + ret = gb_i2s_mgmt_get_cfgs(snd_dev, connection); + if (ret) { + pr_err("can't get i2s configurations: %d\n", ret); + goto err_free_snd_dev; + } snd_dev->send_data_req_buf = kzalloc(SEND_DATA_BUF_LEN, GFP_KERNEL); if (!snd_dev->send_data_req_buf) { ret = -ENOMEM; - goto err_free_snd_dev; + goto err_free_i2s_configs; } return 0; +err_free_i2s_configs: + gb_i2s_mgmt_free_cfgs(snd_dev); err_free_snd_dev: gb_free_snd(snd_dev); return ret; @@ -306,6 +312,8 @@ static void gb_i2s_mgmt_connection_exit(struct gb_connection *connection) { struct gb_snd *snd_dev = (struct gb_snd *)connection->private; + gb_i2s_mgmt_free_cfgs(snd_dev); + kfree(snd_dev->send_data_req_buf); snd_dev->send_data_req_buf = NULL; diff --git a/drivers/staging/greybus/audio.h b/drivers/staging/greybus/audio.h index 012c69a..fa1bb54 100644 --- a/drivers/staging/greybus/audio.h +++ b/drivers/staging/greybus/audio.h @@ -45,6 +45,8 @@ struct gb_snd { struct gb_connection *mgmt_connection; struct gb_connection *i2s_tx_connection; struct gb_connection *i2s_rx_connection; + struct gb_i2s_mgmt_get_supported_configurations_response + *i2s_configs; char *send_data_req_buf; long send_data_sample_count; int gb_bundle_id; @@ -79,7 +81,11 @@ int gb_i2s_mgmt_set_configuration(struct gb_connection *connection, struct gb_i2s_mgmt_set_configuration_request *set_cfg); int gb_i2s_mgmt_set_samples_per_message(struct gb_connection *connection, uint16_t samples_per_message); -int gb_i2s_mgmt_setup(struct gb_connection *connection); +int gb_i2s_mgmt_get_cfgs(struct gb_snd *snd_dev, + struct gb_connection *connection); +void gb_i2s_mgmt_free_cfgs(struct gb_snd *snd_dev); +int gb_i2s_mgmt_set_cfg(struct gb_snd *snd_dev, int rate, int chans, + int bytes_per_chan, int is_le); int gb_i2s_send_data(struct gb_connection *connection, void *req_buf, void *source_addr, size_t len, int sample_num); -- cgit v0.10.2 From 0d17e0c9f164d9c56471438b51ad75f4e894effa Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Thu, 21 May 2015 15:57:04 -0700 Subject: greybus: gb-audio: Set samples per message during init A recent commit moved the I2S samples per message operation to the PCM's 'hw_params' callback. However, the 'hw_params' callback is called numerous times while the samples per message need only be done once (or seldom). Eliminate the unnecessary samples per message operations by doing it only once at Greybus protocol init time. Signed-off-by: Mark A. Greer Acked-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio-gb-cmds.c b/drivers/staging/greybus/audio-gb-cmds.c index 73f47d8..9dbde0d 100644 --- a/drivers/staging/greybus/audio-gb-cmds.c +++ b/drivers/staging/greybus/audio-gb-cmds.c @@ -177,15 +177,8 @@ int gb_i2s_mgmt_set_cfg(struct gb_snd *snd_dev, int rate, int chans, set_cfg.config.ll_wclk_rx_edge = GB_I2S_MGMT_EDGE_FALLING; ret = gb_i2s_mgmt_set_configuration(snd_dev->mgmt_connection, &set_cfg); - if (ret) { - pr_err("set_configuration failed: %d\n", ret); - return ret; - } - - ret = gb_i2s_mgmt_set_samples_per_message(snd_dev->mgmt_connection, - CONFIG_SAMPLES_PER_MSG); if (ret) - pr_err("set_samples_per_msg failed: %d\n", ret); + pr_err("set_configuration failed: %d\n", ret); return ret; } diff --git a/drivers/staging/greybus/audio.c b/drivers/staging/greybus/audio.c index a1acbb0..76b6bdc 100644 --- a/drivers/staging/greybus/audio.c +++ b/drivers/staging/greybus/audio.c @@ -292,6 +292,13 @@ static int gb_i2s_mgmt_connection_init(struct gb_connection *connection) goto err_free_snd_dev; } + ret = gb_i2s_mgmt_set_samples_per_message(snd_dev->mgmt_connection, + CONFIG_SAMPLES_PER_MSG); + if (ret) { + pr_err("set_samples_per_msg failed: %d\n", ret); + goto err_free_i2s_configs; + } + snd_dev->send_data_req_buf = kzalloc(SEND_DATA_BUF_LEN, GFP_KERNEL); if (!snd_dev->send_data_req_buf) { -- cgit v0.10.2 From a702a09f20be5f52ea1789b92a228592f4777084 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 22 May 2015 09:52:42 -0500 Subject: greybus: endo: rename gb_svc Change the name of "struct gb_svc" to be "struct svc_info". The structure now contains only the SVC's serial number and version (and are place holders anyway). We will be defining a structure that represents the SVC for the SVC protocol connection, and I want to take back that name. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c index 42f26f0..859c9c5 100644 --- a/drivers/staging/greybus/endo.c +++ b/drivers/staging/greybus/endo.c @@ -35,7 +35,7 @@ static ssize_t serial_number_show(struct device *dev, { struct gb_endo *endo = to_gb_endo(dev); - return sprintf(buf, "%s", &endo->svc.serial_number[0]); + return sprintf(buf, "%s", &endo->svc_info.serial_number[0]); } static DEVICE_ATTR_RO(serial_number); @@ -44,7 +44,7 @@ static ssize_t version_show(struct device *dev, struct device_attribute *attr, { struct gb_endo *endo = to_gb_endo(dev); - return sprintf(buf, "%s", &endo->svc.version[0]); + return sprintf(buf, "%s", &endo->svc_info.version[0]); } static DEVICE_ATTR_RO(version); @@ -409,8 +409,8 @@ static int gb_endo_register(struct greybus_host_device *hd, // FIXME // Get the version and serial number from the SVC, right now we are // using "fake" numbers. - strcpy(&endo->svc.serial_number[0], "042"); - strcpy(&endo->svc.version[0], "0.0"); + strcpy(&endo->svc_info.serial_number[0], "042"); + strcpy(&endo->svc_info.version[0], "0.0"); dev_set_name(&endo->dev, "endo-0x%04x", endo->id); retval = device_add(&endo->dev); diff --git a/drivers/staging/greybus/endo.h b/drivers/staging/greybus/endo.h index dd05269..2920b13 100644 --- a/drivers/staging/greybus/endo.h +++ b/drivers/staging/greybus/endo.h @@ -10,7 +10,7 @@ #define __ENDO_H /* Greybus "public" definitions" */ -struct gb_svc { +struct gb_svc_info { u8 serial_number[10]; u8 version[10]; }; @@ -36,9 +36,9 @@ struct endo_layout { }; struct gb_endo { - struct endo_layout layout; struct device dev; - struct gb_svc svc; + struct endo_layout layout; + struct gb_svc_info svc_info; u16 id; }; #define to_gb_endo(d) container_of(d, struct gb_endo, dev) -- cgit v0.10.2 From ee3ecf80284d973e491e653f74b2fd936c50bd2c Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 22 May 2015 09:52:43 -0500 Subject: greybus: endo: pass endo_id to gb_endo_create() We are going to want to defer creating the endo until we receive a probe operation from the SVC, which will supply the endo id. Change gb_endo_create() so it passes the endo_id value as an argument. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index e32d6c4..27062e7 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -177,6 +177,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver size_t buffer_size_max) { struct greybus_host_device *hd; + u16 endo_id = 0x4755; // FIXME - get endo "ID" from the SVC /* * Validate that the driver implements all of the callbacks @@ -210,7 +211,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver ida_init(&hd->cport_id_map); hd->buffer_size_max = buffer_size_max; - hd->endo = gb_endo_create(hd); + hd->endo = gb_endo_create(hd, endo_id); if (!hd->endo) { greybus_remove_hd(hd); return NULL; diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c index 859c9c5..fb2f7c9 100644 --- a/drivers/staging/greybus/endo.c +++ b/drivers/staging/greybus/endo.c @@ -423,11 +423,10 @@ static int gb_endo_register(struct greybus_host_device *hd, return retval; } -struct gb_endo *gb_endo_create(struct greybus_host_device *hd) +struct gb_endo *gb_endo_create(struct greybus_host_device *hd, u16 endo_id) { struct gb_endo *endo; int retval; - u16 endo_id = 0x4755; // FIXME - get endo "ID" from the SVC endo = kzalloc(sizeof(*endo), GFP_KERNEL); if (!endo) diff --git a/drivers/staging/greybus/endo.h b/drivers/staging/greybus/endo.h index 2920b13..c1ccbcd 100644 --- a/drivers/staging/greybus/endo.h +++ b/drivers/staging/greybus/endo.h @@ -47,7 +47,7 @@ struct gb_endo { /* Greybus "private" definitions */ struct greybus_host_device; -struct gb_endo *gb_endo_create(struct greybus_host_device *hd); +struct gb_endo *gb_endo_create(struct greybus_host_device *hd, u16 endo_id); void gb_endo_remove(struct gb_endo *endo); u8 endo_get_module_id(struct gb_endo *endo, u8 interface_id); -- cgit v0.10.2 From 6b7d5a1f47914b2e3917fb764b4b3fe3affe7f94 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 22 May 2015 09:52:44 -0500 Subject: greybus: core: return error code when creating endo Return a pointer-coded error from gb_endo_create() rather than just a null pointer in the event an error occurs. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 27062e7..95d8c70 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -177,6 +177,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver size_t buffer_size_max) { struct greybus_host_device *hd; + struct gb_endo *endo; u16 endo_id = 0x4755; // FIXME - get endo "ID" from the SVC /* @@ -211,11 +212,12 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver ida_init(&hd->cport_id_map); hd->buffer_size_max = buffer_size_max; - hd->endo = gb_endo_create(hd, endo_id); - if (!hd->endo) { + endo = gb_endo_create(hd, endo_id); + if (IS_ERR(endo)) { greybus_remove_hd(hd); return NULL; } + hd->endo = endo; return hd; } diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c index fb2f7c9..5b5a3c6 100644 --- a/drivers/staging/greybus/endo.c +++ b/drivers/staging/greybus/endo.c @@ -430,16 +430,19 @@ struct gb_endo *gb_endo_create(struct greybus_host_device *hd, u16 endo_id) endo = kzalloc(sizeof(*endo), GFP_KERNEL); if (!endo) - return NULL; + return ERR_PTR(-ENOMEM); /* First check if the value supplied is a valid endo id */ - if (gb_endo_validate_id(hd, &endo->layout, endo_id)) + if (gb_endo_validate_id(hd, &endo->layout, endo_id)) { + retval = -EINVAL; goto free_endo; + } endo->id = endo_id; /* Register Endo device */ - if (gb_endo_register(hd, endo)) + retval = gb_endo_register(hd, endo); + if (retval) goto free_endo; /* Create modules/interfaces */ @@ -453,7 +456,8 @@ struct gb_endo *gb_endo_create(struct greybus_host_device *hd, u16 endo_id) free_endo: kfree(endo); - return NULL; + + return ERR_PTR(retval); } void gb_endo_remove(struct gb_endo *endo) -- cgit v0.10.2 From 8ea70fe0497c5dd11451e7cf1084844cbdb2a349 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 22 May 2015 09:52:45 -0500 Subject: greybus: core: return error code when creating host device Return a pointer-coded error from greybus_create_hd() rather than NULL in the event an error occurs. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 95d8c70..7bfdbad 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -187,7 +187,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver if ((!driver->message_send) || (!driver->message_cancel) || (!driver->submit_svc)) { pr_err("Must implement all greybus_host_driver callbacks!\n"); - return NULL; + return ERR_PTR(-EINVAL); } /* @@ -202,7 +202,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver hd = kzalloc(sizeof(*hd) + driver->hd_priv_size, GFP_KERNEL); if (!hd) - return NULL; + return ERR_PTR(-ENOMEM); kref_init(&hd->kref); hd->parent = parent; @@ -215,7 +215,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver endo = gb_endo_create(hd, endo_id); if (IS_ERR(endo)) { greybus_remove_hd(hd); - return NULL; + return ERR_CAST(endo); } hd->endo = endo; diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index e0fae26..1ed10f4 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -556,9 +556,9 @@ static int ap_probe(struct usb_interface *interface, udev = usb_get_dev(interface_to_usbdev(interface)); hd = greybus_create_hd(&es1_driver, &udev->dev, ES1_GBUF_MSG_SIZE_MAX); - if (!hd) { + if (IS_ERR(hd)) { usb_put_dev(udev); - return -ENOMEM; + return PTR_ERR(hd); } es1 = hd_to_es1(hd); diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 05aac3d..4733adc 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -556,9 +556,9 @@ static int ap_probe(struct usb_interface *interface, udev = usb_get_dev(interface_to_usbdev(interface)); hd = greybus_create_hd(&es1_driver, &udev->dev, ES1_GBUF_MSG_SIZE_MAX); - if (!hd) { + if (IS_ERR(hd)) { usb_put_dev(udev); - return -ENOMEM; + return PTR_ERR(hd); } es1 = hd_to_es1(hd); -- cgit v0.10.2 From e9385e5d5ab64a0d05758d84f2980943d3f5f12d Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 22 May 2015 12:35:31 -0500 Subject: greybus: include "gpbridge.h" from "greybus.h" Avoid the need for all the source files to include "gpbridge.h" by just having "greybus.h" include it. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio-dai.c b/drivers/staging/greybus/audio-dai.c index 39b72f0..0dd7364 100644 --- a/drivers/staging/greybus/audio-dai.c +++ b/drivers/staging/greybus/audio-dai.c @@ -11,8 +11,8 @@ #include #include #include + #include "greybus.h" -#include "gpbridge.h" #include "audio.h" /* diff --git a/drivers/staging/greybus/audio-gb-cmds.c b/drivers/staging/greybus/audio-gb-cmds.c index 9dbde0d..f6a29ab 100644 --- a/drivers/staging/greybus/audio-gb-cmds.c +++ b/drivers/staging/greybus/audio-gb-cmds.c @@ -1,6 +1,6 @@ #include + #include "greybus.h" -#include "gpbridge.h" #include "audio.h" #define GB_I2S_MGMT_VERSION_MAJOR 0x00 diff --git a/drivers/staging/greybus/audio-pcm.c b/drivers/staging/greybus/audio-pcm.c index b327008..a1faf78 100644 --- a/drivers/staging/greybus/audio-pcm.c +++ b/drivers/staging/greybus/audio-pcm.c @@ -11,8 +11,8 @@ #include #include #include + #include "greybus.h" -#include "gpbridge.h" #include "audio.h" /* diff --git a/drivers/staging/greybus/audio.c b/drivers/staging/greybus/audio.c index 76b6bdc..c873f33 100644 --- a/drivers/staging/greybus/audio.c +++ b/drivers/staging/greybus/audio.c @@ -10,8 +10,8 @@ #include #include #include + #include "greybus.h" -#include "gpbridge.h" #include "audio.h" diff --git a/drivers/staging/greybus/audio.h b/drivers/staging/greybus/audio.h index fa1bb54..c9087c9fc 100644 --- a/drivers/staging/greybus/audio.h +++ b/drivers/staging/greybus/audio.h @@ -7,9 +7,8 @@ #include #include #include -#include "greybus.h" -#include "gpbridge.h" +#include "greybus.h" #define GB_SAMPLE_RATE 48000 #define GB_RATES SNDRV_PCM_RATE_48000 diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 871f2d0..6e5fe5b3 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -14,7 +14,6 @@ #include #include #include "greybus.h" -#include "gpbridge.h" struct gb_gpio_line { /* The following has to be an array of line_max entries */ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index dbb4e78..c58f123 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -23,6 +23,7 @@ #include "kernel_ver.h" #include "greybus_id.h" #include "greybus_manifest.h" +#include "gpbridge.h" #include "manifest.h" #include "endo.h" #include "module.h" diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c index 14fdea1..01afca8 100644 --- a/drivers/staging/greybus/i2c.c +++ b/drivers/staging/greybus/i2c.c @@ -13,8 +13,6 @@ #include #include "greybus.h" -#include "gpbridge.h" - struct gb_i2c_device { struct gb_connection *connection; diff --git a/drivers/staging/greybus/pwm.c b/drivers/staging/greybus/pwm.c index 7f675bf..5dfeb0e 100644 --- a/drivers/staging/greybus/pwm.c +++ b/drivers/staging/greybus/pwm.c @@ -11,8 +11,8 @@ #include #include #include + #include "greybus.h" -#include "gpbridge.h" struct gb_pwm_chip { struct gb_connection *connection; diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index 430c3ad..78a7f85 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -14,7 +14,6 @@ #include #include "greybus.h" -#include "gpbridge.h" struct gb_spi { struct gb_connection *connection; -- cgit v0.10.2 From 22e17edaa7c24d254e572738420873813f47efb5 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 22 May 2015 12:35:32 -0500 Subject: greybus: rename "gpbridge.h" The file "gpbridge.h" is now used as a single place to define all protocol message structures. These protocols are not necessarily related to the GP bridge, so the name of the file is misleading. Rename it "greybus_protocols.h". Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpbridge.h b/drivers/staging/greybus/gpbridge.h deleted file mode 100644 index c820805..0000000 --- a/drivers/staging/greybus/gpbridge.h +++ /dev/null @@ -1,492 +0,0 @@ -/* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2014 - 2015 Google Inc. All rights reserved. - * Copyright(c) 2014 - 2015 Linaro Ltd. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details. - * - * BSD LICENSE - * - * Copyright(c) 2014 - 2015 Google Inc. All rights reserved. - * Copyright(c) 2014 - 2015 Linaro Ltd. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. or Linaro Ltd. nor the names of - * its contributors may be used to endorse or promote products - * derived from this software without specific prior written - * permission. - * - * 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 GOOGLE INC. OR - * LINARO LTD. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __GB_GPBRIDGE_H__ -#define __GB_GPBRIDGE_H__ - -/* I2C */ - -/* Version of the Greybus i2c protocol we support */ -#define GB_I2C_VERSION_MAJOR 0x00 -#define GB_I2C_VERSION_MINOR 0x01 - -/* Greybus i2c request types */ -#define GB_I2C_TYPE_INVALID 0x00 -#define GB_I2C_TYPE_PROTOCOL_VERSION 0x01 -#define GB_I2C_TYPE_FUNCTIONALITY 0x02 -#define GB_I2C_TYPE_TIMEOUT 0x03 -#define GB_I2C_TYPE_RETRIES 0x04 -#define GB_I2C_TYPE_TRANSFER 0x05 - -#define GB_I2C_RETRIES_DEFAULT 3 -#define GB_I2C_TIMEOUT_DEFAULT 1000 /* milliseconds */ - -/* functionality request has no payload */ -struct gb_i2c_functionality_response { - __le32 functionality; -}; - -struct gb_i2c_timeout_request { - __le16 msec; -}; -/* timeout response has no payload */ - -struct gb_i2c_retries_request { - __u8 retries; -}; -/* retries response has no payload */ - -/* - * Outgoing data immediately follows the op count and ops array. - * The data for each write (master -> slave) op in the array is sent - * in order, with no (e.g. pad) bytes separating them. - * - * Short reads cause the entire transfer request to fail So response - * payload consists only of bytes read, and the number of bytes is - * exactly what was specified in the corresponding op. Like - * outgoing data, the incoming data is in order and contiguous. - */ -struct gb_i2c_transfer_op { - __le16 addr; - __le16 flags; - __le16 size; -}; - -struct gb_i2c_transfer_request { - __le16 op_count; - struct gb_i2c_transfer_op ops[0]; /* op_count of these */ -}; -struct gb_i2c_transfer_response { - __u8 data[0]; /* inbound data */ -}; - - -/* GPIO */ - -/* Version of the Greybus GPIO protocol we support */ -#define GB_GPIO_VERSION_MAJOR 0x00 -#define GB_GPIO_VERSION_MINOR 0x01 - -/* Greybus GPIO request types */ -#define GB_GPIO_TYPE_INVALID 0x00 -#define GB_GPIO_TYPE_PROTOCOL_VERSION 0x01 -#define GB_GPIO_TYPE_LINE_COUNT 0x02 -#define GB_GPIO_TYPE_ACTIVATE 0x03 -#define GB_GPIO_TYPE_DEACTIVATE 0x04 -#define GB_GPIO_TYPE_GET_DIRECTION 0x05 -#define GB_GPIO_TYPE_DIRECTION_IN 0x06 -#define GB_GPIO_TYPE_DIRECTION_OUT 0x07 -#define GB_GPIO_TYPE_GET_VALUE 0x08 -#define GB_GPIO_TYPE_SET_VALUE 0x09 -#define GB_GPIO_TYPE_SET_DEBOUNCE 0x0a -#define GB_GPIO_TYPE_IRQ_TYPE 0x0b -#define GB_GPIO_TYPE_IRQ_ACK 0x0c -#define GB_GPIO_TYPE_IRQ_MASK 0x0d -#define GB_GPIO_TYPE_IRQ_UNMASK 0x0e -#define GB_GPIO_TYPE_IRQ_EVENT 0x0f - -#define GB_GPIO_DEBOUNCE_USEC_DEFAULT 0 /* microseconds */ - -/* line count request has no payload */ -struct gb_gpio_line_count_response { - __u8 count; -}; - -struct gb_gpio_activate_request { - __u8 which; -}; -/* activate response has no payload */ - -struct gb_gpio_deactivate_request { - __u8 which; -}; -/* deactivate response has no payload */ - -struct gb_gpio_get_direction_request { - __u8 which; -}; -struct gb_gpio_get_direction_response { - __u8 direction; -}; - -struct gb_gpio_direction_in_request { - __u8 which; -}; -/* direction in response has no payload */ - -struct gb_gpio_direction_out_request { - __u8 which; - __u8 value; -}; -/* direction out response has no payload */ - -struct gb_gpio_get_value_request { - __u8 which; -}; -struct gb_gpio_get_value_response { - __u8 value; -}; - -struct gb_gpio_set_value_request { - __u8 which; - __u8 value; -}; -/* set value response has no payload */ - -struct gb_gpio_set_debounce_request { - __u8 which; - __le16 usec __packed; -}; -/* debounce response has no payload */ - -struct gb_gpio_irq_type_request { - __u8 which; - __u8 type; -}; -/* irq type response has no payload */ - -struct gb_gpio_irq_mask_request { - __u8 which; -}; -/* irq mask response has no payload */ - -struct gb_gpio_irq_unmask_request { - __u8 which; -}; -/* irq unmask response has no payload */ - -struct gb_gpio_irq_ack_request { - __u8 which; -}; -/* irq ack response has no payload */ - -/* irq event requests originate on another module and are handled on the AP */ -struct gb_gpio_irq_event_request { - __u8 which; -}; -/* irq event response has no payload */ - - -/* PWM */ - -/* Version of the Greybus PWM protocol we support */ -#define GB_PWM_VERSION_MAJOR 0x00 -#define GB_PWM_VERSION_MINOR 0x01 - -/* Greybus PWM operation types */ -#define GB_PWM_TYPE_INVALID 0x00 -#define GB_PWM_TYPE_PROTOCOL_VERSION 0x01 -#define GB_PWM_TYPE_PWM_COUNT 0x02 -#define GB_PWM_TYPE_ACTIVATE 0x03 -#define GB_PWM_TYPE_DEACTIVATE 0x04 -#define GB_PWM_TYPE_CONFIG 0x05 -#define GB_PWM_TYPE_POLARITY 0x06 -#define GB_PWM_TYPE_ENABLE 0x07 -#define GB_PWM_TYPE_DISABLE 0x08 - -/* pwm count request has no payload */ -struct gb_pwm_count_response { - __u8 count; -}; - -struct gb_pwm_activate_request { - __u8 which; -}; - -struct gb_pwm_deactivate_request { - __u8 which; -}; - -struct gb_pwm_config_request { - __u8 which; - __le32 duty __packed; - __le32 period __packed; -}; - -struct gb_pwm_polarity_request { - __u8 which; - __u8 polarity; -}; - -struct gb_pwm_enable_request { - __u8 which; -}; - -struct gb_pwm_disable_request { - __u8 which; -}; - -/* I2S */ - -#define GB_I2S_MGMT_TYPE_PROTOCOL_VERSION 0x01 -#define GB_I2S_MGMT_TYPE_GET_SUPPORTED_CONFIGURATIONS 0x02 -#define GB_I2S_MGMT_TYPE_SET_CONFIGURATION 0x03 -#define GB_I2S_MGMT_TYPE_SET_SAMPLES_PER_MESSAGE 0x04 -#define GB_I2S_MGMT_TYPE_GET_PROCESSING_DELAY 0x05 -#define GB_I2S_MGMT_TYPE_SET_START_DELAY 0x06 -#define GB_I2S_MGMT_TYPE_ACTIVATE_CPORT 0x07 -#define GB_I2S_MGMT_TYPE_DEACTIVATE_CPORT 0x08 -#define GB_I2S_MGMT_TYPE_REPORT_EVENT 0x09 - -#define GB_I2S_MGMT_BYTE_ORDER_NA BIT(0) -#define GB_I2S_MGMT_BYTE_ORDER_BE BIT(1) -#define GB_I2S_MGMT_BYTE_ORDER_LE BIT(2) - -#define GB_I2S_MGMT_SPATIAL_LOCATION_FL BIT(0) -#define GB_I2S_MGMT_SPATIAL_LOCATION_FR BIT(1) -#define GB_I2S_MGMT_SPATIAL_LOCATION_FC BIT(2) -#define GB_I2S_MGMT_SPATIAL_LOCATION_LFE BIT(3) -#define GB_I2S_MGMT_SPATIAL_LOCATION_BL BIT(4) -#define GB_I2S_MGMT_SPATIAL_LOCATION_BR BIT(5) -#define GB_I2S_MGMT_SPATIAL_LOCATION_FLC BIT(6) -#define GB_I2S_MGMT_SPATIAL_LOCATION_FRC BIT(7) -#define GB_I2S_MGMT_SPATIAL_LOCATION_C BIT(8) /* BC in USB */ -#define GB_I2S_MGMT_SPATIAL_LOCATION_SL BIT(9) -#define GB_I2S_MGMT_SPATIAL_LOCATION_SR BIT(10) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TC BIT(11) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TFL BIT(12) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TFC BIT(13) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TFR BIT(14) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TBL BIT(15) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TBC BIT(16) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TBR BIT(17) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TFLC BIT(18) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TFRC BIT(19) -#define GB_I2S_MGMT_SPATIAL_LOCATION_LLFE BIT(20) -#define GB_I2S_MGMT_SPATIAL_LOCATION_RLFE BIT(21) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TSL BIT(22) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TSR BIT(23) -#define GB_I2S_MGMT_SPATIAL_LOCATION_BC BIT(24) -#define GB_I2S_MGMT_SPATIAL_LOCATION_BLC BIT(25) -#define GB_I2S_MGMT_SPATIAL_LOCATION_BRC BIT(26) -#define GB_I2S_MGMT_SPATIAL_LOCATION_RD BIT(31) - -#define GB_I2S_MGMT_PROTOCOL_PCM BIT(0) -#define GB_I2S_MGMT_PROTOCOL_I2S BIT(1) -#define GB_I2S_MGMT_PROTOCOL_LR_STEREO BIT(2) - -#define GB_I2S_MGMT_ROLE_MASTER BIT(0) -#define GB_I2S_MGMT_ROLE_SLAVE BIT(1) - -#define GB_I2S_MGMT_POLARITY_NORMAL BIT(0) -#define GB_I2S_MGMT_POLARITY_REVERSED BIT(1) - -#define GB_I2S_MGMT_EDGE_RISING BIT(0) -#define GB_I2S_MGMT_EDGE_FALLING BIT(1) - -#define GB_I2S_MGMT_EVENT_UNSPECIFIED 0x1 -#define GB_I2S_MGMT_EVENT_HALT 0x2 -#define GB_I2S_MGMT_EVENT_INTERNAL_ERROR 0x3 -#define GB_I2S_MGMT_EVENT_PROTOCOL_ERROR 0x4 -#define GB_I2S_MGMT_EVENT_FAILURE 0x5 -#define GB_I2S_MGMT_EVENT_OUT_OF_SEQUENCE 0x6 -#define GB_I2S_MGMT_EVENT_UNDERRUN 0x7 -#define GB_I2S_MGMT_EVENT_OVERRUN 0x8 -#define GB_I2S_MGMT_EVENT_CLOCKING 0x9 -#define GB_I2S_MGMT_EVENT_DATA_LEN 0xa - -struct gb_i2s_mgmt_configuration { - __le32 sample_frequency; - __u8 num_channels; - __u8 bytes_per_channel; - __u8 byte_order; - __u8 pad; - __le32 spatial_locations; - __le32 ll_protocol; - __u8 ll_mclk_role; - __u8 ll_bclk_role; - __u8 ll_wclk_role; - __u8 ll_wclk_polarity; - __u8 ll_wclk_change_edge; - __u8 ll_wclk_tx_edge; - __u8 ll_wclk_rx_edge; - __u8 ll_data_offset; -}; - -/* get supported configurations request has no payload */ -struct gb_i2s_mgmt_get_supported_configurations_response { - __u8 config_count; - __u8 pad[3]; - struct gb_i2s_mgmt_configuration config[0]; -}; - -struct gb_i2s_mgmt_set_configuration_request { - struct gb_i2s_mgmt_configuration config; -}; -/* set configuration response has no payload */ - -struct gb_i2s_mgmt_set_samples_per_message_request { - __le16 samples_per_message; -}; -/* set samples per message response has no payload */ - -/* get processing request delay has no payload */ -struct gb_i2s_mgmt_get_processing_delay_response { - __le32 microseconds; -}; - -struct gb_i2s_mgmt_set_start_delay_request { - __le32 microseconds; -}; -/* set start delay response has no payload */ - -struct gb_i2s_mgmt_activate_cport_request { - __le16 cport; -}; -/* activate cport response has no payload */ - -struct gb_i2s_mgmt_deactivate_cport_request { - __le16 cport; -}; -/* deactivate cport response has no payload */ - -struct gb_i2s_mgmt_report_event_request { - __u8 event; -}; -/* report event response has no payload */ - -#define GB_I2S_DATA_TYPE_PROTOCOL_VERSION 0x01 -#define GB_I2S_DATA_TYPE_SEND_DATA 0x02 - -struct gb_i2s_send_data_request { - __le32 sample_number; - __le32 size; - __u8 data[0]; -}; -/* send data has no response at all */ - - -/* SPI */ - -/* Version of the Greybus spi protocol we support */ -#define GB_SPI_VERSION_MAJOR 0x00 -#define GB_SPI_VERSION_MINOR 0x01 - -/* Should match up with modes in linux/spi/spi.h */ -#define GB_SPI_MODE_CPHA 0x01 /* clock phase */ -#define GB_SPI_MODE_CPOL 0x02 /* clock polarity */ -#define GB_SPI_MODE_MODE_0 (0|0) /* (original MicroWire) */ -#define GB_SPI_MODE_MODE_1 (0|GB_SPI_MODE_CPHA) -#define GB_SPI_MODE_MODE_2 (GB_SPI_MODE_CPOL|0) -#define GB_SPI_MODE_MODE_3 (GB_SPI_MODE_CPOL|GB_SPI_MODE_CPHA) -#define GB_SPI_MODE_CS_HIGH 0x04 /* chipselect active high? */ -#define GB_SPI_MODE_LSB_FIRST 0x08 /* per-word bits-on-wire */ -#define GB_SPI_MODE_3WIRE 0x10 /* SI/SO signals shared */ -#define GB_SPI_MODE_LOOP 0x20 /* loopback mode */ -#define GB_SPI_MODE_NO_CS 0x40 /* 1 dev/bus, no chipselect */ -#define GB_SPI_MODE_READY 0x80 /* slave pulls low to pause */ - -/* Should match up with flags in linux/spi/spi.h */ -#define GB_SPI_FLAG_HALF_DUPLEX BIT(0) /* can't do full duplex */ -#define GB_SPI_FLAG_NO_RX BIT(1) /* can't do buffer read */ -#define GB_SPI_FLAG_NO_TX BIT(2) /* can't do buffer write */ - -/* Greybus spi operation types */ -#define GB_SPI_TYPE_INVALID 0x00 -#define GB_SPI_TYPE_PROTOCOL_VERSION 0x01 -#define GB_SPI_TYPE_MODE 0x02 -#define GB_SPI_TYPE_FLAGS 0x03 -#define GB_SPI_TYPE_BITS_PER_WORD_MASK 0x04 -#define GB_SPI_TYPE_NUM_CHIPSELECT 0x05 -#define GB_SPI_TYPE_TRANSFER 0x06 - -/* mode request has no payload */ -struct gb_spi_mode_response { - __le16 mode; -}; - -/* flags request has no payload */ -struct gb_spi_flags_response { - __le16 flags; -}; - -/* bits-per-word request has no payload */ -struct gb_spi_bpw_response { - __le32 bits_per_word_mask; -}; - -/* num-chipselects request has no payload */ -struct gb_spi_chipselect_response { - __le16 num_chipselect; -}; - -/** - * struct gb_spi_transfer - a read/write buffer pair - * @speed_hz: Select a speed other than the device default for this transfer. If - * 0 the default (from @spi_device) is used. - * @len: size of rx and tx buffers (in bytes) - * @delay_usecs: microseconds to delay after this transfer before (optionally) - * changing the chipselect status, then starting the next transfer or - * completing this spi_message. - * @cs_change: affects chipselect after this transfer completes - * @bits_per_word: select a bits_per_word other than the device default for this - * transfer. If 0 the default (from @spi_device) is used. - */ -struct gb_spi_transfer { - __le32 speed_hz; - __le32 len; - __le16 delay_usecs; - __u8 cs_change; - __u8 bits_per_word; -}; - -struct gb_spi_transfer_request { - __u8 chip_select; /* of the spi device */ - __u8 mode; /* of the spi device */ - __le16 count; - struct gb_spi_transfer transfers[0]; /* trnasfer_count of these */ -}; - -struct gb_spi_transfer_response { - __u8 data[0]; /* inbound data */ -}; - -#endif /* __GB_GPBRIDGE_H__ */ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index c58f123..4920458 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -23,7 +23,7 @@ #include "kernel_ver.h" #include "greybus_id.h" #include "greybus_manifest.h" -#include "gpbridge.h" +#include "greybus_protocols.h" #include "manifest.h" #include "endo.h" #include "module.h" diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h new file mode 100644 index 0000000..c820805 --- /dev/null +++ b/drivers/staging/greybus/greybus_protocols.h @@ -0,0 +1,492 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2014 - 2015 Google Inc. All rights reserved. + * Copyright(c) 2014 - 2015 Linaro Ltd. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details. + * + * BSD LICENSE + * + * Copyright(c) 2014 - 2015 Google Inc. All rights reserved. + * Copyright(c) 2014 - 2015 Linaro Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. or Linaro Ltd. nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * 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 GOOGLE INC. OR + * LINARO LTD. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __GB_GPBRIDGE_H__ +#define __GB_GPBRIDGE_H__ + +/* I2C */ + +/* Version of the Greybus i2c protocol we support */ +#define GB_I2C_VERSION_MAJOR 0x00 +#define GB_I2C_VERSION_MINOR 0x01 + +/* Greybus i2c request types */ +#define GB_I2C_TYPE_INVALID 0x00 +#define GB_I2C_TYPE_PROTOCOL_VERSION 0x01 +#define GB_I2C_TYPE_FUNCTIONALITY 0x02 +#define GB_I2C_TYPE_TIMEOUT 0x03 +#define GB_I2C_TYPE_RETRIES 0x04 +#define GB_I2C_TYPE_TRANSFER 0x05 + +#define GB_I2C_RETRIES_DEFAULT 3 +#define GB_I2C_TIMEOUT_DEFAULT 1000 /* milliseconds */ + +/* functionality request has no payload */ +struct gb_i2c_functionality_response { + __le32 functionality; +}; + +struct gb_i2c_timeout_request { + __le16 msec; +}; +/* timeout response has no payload */ + +struct gb_i2c_retries_request { + __u8 retries; +}; +/* retries response has no payload */ + +/* + * Outgoing data immediately follows the op count and ops array. + * The data for each write (master -> slave) op in the array is sent + * in order, with no (e.g. pad) bytes separating them. + * + * Short reads cause the entire transfer request to fail So response + * payload consists only of bytes read, and the number of bytes is + * exactly what was specified in the corresponding op. Like + * outgoing data, the incoming data is in order and contiguous. + */ +struct gb_i2c_transfer_op { + __le16 addr; + __le16 flags; + __le16 size; +}; + +struct gb_i2c_transfer_request { + __le16 op_count; + struct gb_i2c_transfer_op ops[0]; /* op_count of these */ +}; +struct gb_i2c_transfer_response { + __u8 data[0]; /* inbound data */ +}; + + +/* GPIO */ + +/* Version of the Greybus GPIO protocol we support */ +#define GB_GPIO_VERSION_MAJOR 0x00 +#define GB_GPIO_VERSION_MINOR 0x01 + +/* Greybus GPIO request types */ +#define GB_GPIO_TYPE_INVALID 0x00 +#define GB_GPIO_TYPE_PROTOCOL_VERSION 0x01 +#define GB_GPIO_TYPE_LINE_COUNT 0x02 +#define GB_GPIO_TYPE_ACTIVATE 0x03 +#define GB_GPIO_TYPE_DEACTIVATE 0x04 +#define GB_GPIO_TYPE_GET_DIRECTION 0x05 +#define GB_GPIO_TYPE_DIRECTION_IN 0x06 +#define GB_GPIO_TYPE_DIRECTION_OUT 0x07 +#define GB_GPIO_TYPE_GET_VALUE 0x08 +#define GB_GPIO_TYPE_SET_VALUE 0x09 +#define GB_GPIO_TYPE_SET_DEBOUNCE 0x0a +#define GB_GPIO_TYPE_IRQ_TYPE 0x0b +#define GB_GPIO_TYPE_IRQ_ACK 0x0c +#define GB_GPIO_TYPE_IRQ_MASK 0x0d +#define GB_GPIO_TYPE_IRQ_UNMASK 0x0e +#define GB_GPIO_TYPE_IRQ_EVENT 0x0f + +#define GB_GPIO_DEBOUNCE_USEC_DEFAULT 0 /* microseconds */ + +/* line count request has no payload */ +struct gb_gpio_line_count_response { + __u8 count; +}; + +struct gb_gpio_activate_request { + __u8 which; +}; +/* activate response has no payload */ + +struct gb_gpio_deactivate_request { + __u8 which; +}; +/* deactivate response has no payload */ + +struct gb_gpio_get_direction_request { + __u8 which; +}; +struct gb_gpio_get_direction_response { + __u8 direction; +}; + +struct gb_gpio_direction_in_request { + __u8 which; +}; +/* direction in response has no payload */ + +struct gb_gpio_direction_out_request { + __u8 which; + __u8 value; +}; +/* direction out response has no payload */ + +struct gb_gpio_get_value_request { + __u8 which; +}; +struct gb_gpio_get_value_response { + __u8 value; +}; + +struct gb_gpio_set_value_request { + __u8 which; + __u8 value; +}; +/* set value response has no payload */ + +struct gb_gpio_set_debounce_request { + __u8 which; + __le16 usec __packed; +}; +/* debounce response has no payload */ + +struct gb_gpio_irq_type_request { + __u8 which; + __u8 type; +}; +/* irq type response has no payload */ + +struct gb_gpio_irq_mask_request { + __u8 which; +}; +/* irq mask response has no payload */ + +struct gb_gpio_irq_unmask_request { + __u8 which; +}; +/* irq unmask response has no payload */ + +struct gb_gpio_irq_ack_request { + __u8 which; +}; +/* irq ack response has no payload */ + +/* irq event requests originate on another module and are handled on the AP */ +struct gb_gpio_irq_event_request { + __u8 which; +}; +/* irq event response has no payload */ + + +/* PWM */ + +/* Version of the Greybus PWM protocol we support */ +#define GB_PWM_VERSION_MAJOR 0x00 +#define GB_PWM_VERSION_MINOR 0x01 + +/* Greybus PWM operation types */ +#define GB_PWM_TYPE_INVALID 0x00 +#define GB_PWM_TYPE_PROTOCOL_VERSION 0x01 +#define GB_PWM_TYPE_PWM_COUNT 0x02 +#define GB_PWM_TYPE_ACTIVATE 0x03 +#define GB_PWM_TYPE_DEACTIVATE 0x04 +#define GB_PWM_TYPE_CONFIG 0x05 +#define GB_PWM_TYPE_POLARITY 0x06 +#define GB_PWM_TYPE_ENABLE 0x07 +#define GB_PWM_TYPE_DISABLE 0x08 + +/* pwm count request has no payload */ +struct gb_pwm_count_response { + __u8 count; +}; + +struct gb_pwm_activate_request { + __u8 which; +}; + +struct gb_pwm_deactivate_request { + __u8 which; +}; + +struct gb_pwm_config_request { + __u8 which; + __le32 duty __packed; + __le32 period __packed; +}; + +struct gb_pwm_polarity_request { + __u8 which; + __u8 polarity; +}; + +struct gb_pwm_enable_request { + __u8 which; +}; + +struct gb_pwm_disable_request { + __u8 which; +}; + +/* I2S */ + +#define GB_I2S_MGMT_TYPE_PROTOCOL_VERSION 0x01 +#define GB_I2S_MGMT_TYPE_GET_SUPPORTED_CONFIGURATIONS 0x02 +#define GB_I2S_MGMT_TYPE_SET_CONFIGURATION 0x03 +#define GB_I2S_MGMT_TYPE_SET_SAMPLES_PER_MESSAGE 0x04 +#define GB_I2S_MGMT_TYPE_GET_PROCESSING_DELAY 0x05 +#define GB_I2S_MGMT_TYPE_SET_START_DELAY 0x06 +#define GB_I2S_MGMT_TYPE_ACTIVATE_CPORT 0x07 +#define GB_I2S_MGMT_TYPE_DEACTIVATE_CPORT 0x08 +#define GB_I2S_MGMT_TYPE_REPORT_EVENT 0x09 + +#define GB_I2S_MGMT_BYTE_ORDER_NA BIT(0) +#define GB_I2S_MGMT_BYTE_ORDER_BE BIT(1) +#define GB_I2S_MGMT_BYTE_ORDER_LE BIT(2) + +#define GB_I2S_MGMT_SPATIAL_LOCATION_FL BIT(0) +#define GB_I2S_MGMT_SPATIAL_LOCATION_FR BIT(1) +#define GB_I2S_MGMT_SPATIAL_LOCATION_FC BIT(2) +#define GB_I2S_MGMT_SPATIAL_LOCATION_LFE BIT(3) +#define GB_I2S_MGMT_SPATIAL_LOCATION_BL BIT(4) +#define GB_I2S_MGMT_SPATIAL_LOCATION_BR BIT(5) +#define GB_I2S_MGMT_SPATIAL_LOCATION_FLC BIT(6) +#define GB_I2S_MGMT_SPATIAL_LOCATION_FRC BIT(7) +#define GB_I2S_MGMT_SPATIAL_LOCATION_C BIT(8) /* BC in USB */ +#define GB_I2S_MGMT_SPATIAL_LOCATION_SL BIT(9) +#define GB_I2S_MGMT_SPATIAL_LOCATION_SR BIT(10) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TC BIT(11) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TFL BIT(12) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TFC BIT(13) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TFR BIT(14) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TBL BIT(15) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TBC BIT(16) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TBR BIT(17) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TFLC BIT(18) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TFRC BIT(19) +#define GB_I2S_MGMT_SPATIAL_LOCATION_LLFE BIT(20) +#define GB_I2S_MGMT_SPATIAL_LOCATION_RLFE BIT(21) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TSL BIT(22) +#define GB_I2S_MGMT_SPATIAL_LOCATION_TSR BIT(23) +#define GB_I2S_MGMT_SPATIAL_LOCATION_BC BIT(24) +#define GB_I2S_MGMT_SPATIAL_LOCATION_BLC BIT(25) +#define GB_I2S_MGMT_SPATIAL_LOCATION_BRC BIT(26) +#define GB_I2S_MGMT_SPATIAL_LOCATION_RD BIT(31) + +#define GB_I2S_MGMT_PROTOCOL_PCM BIT(0) +#define GB_I2S_MGMT_PROTOCOL_I2S BIT(1) +#define GB_I2S_MGMT_PROTOCOL_LR_STEREO BIT(2) + +#define GB_I2S_MGMT_ROLE_MASTER BIT(0) +#define GB_I2S_MGMT_ROLE_SLAVE BIT(1) + +#define GB_I2S_MGMT_POLARITY_NORMAL BIT(0) +#define GB_I2S_MGMT_POLARITY_REVERSED BIT(1) + +#define GB_I2S_MGMT_EDGE_RISING BIT(0) +#define GB_I2S_MGMT_EDGE_FALLING BIT(1) + +#define GB_I2S_MGMT_EVENT_UNSPECIFIED 0x1 +#define GB_I2S_MGMT_EVENT_HALT 0x2 +#define GB_I2S_MGMT_EVENT_INTERNAL_ERROR 0x3 +#define GB_I2S_MGMT_EVENT_PROTOCOL_ERROR 0x4 +#define GB_I2S_MGMT_EVENT_FAILURE 0x5 +#define GB_I2S_MGMT_EVENT_OUT_OF_SEQUENCE 0x6 +#define GB_I2S_MGMT_EVENT_UNDERRUN 0x7 +#define GB_I2S_MGMT_EVENT_OVERRUN 0x8 +#define GB_I2S_MGMT_EVENT_CLOCKING 0x9 +#define GB_I2S_MGMT_EVENT_DATA_LEN 0xa + +struct gb_i2s_mgmt_configuration { + __le32 sample_frequency; + __u8 num_channels; + __u8 bytes_per_channel; + __u8 byte_order; + __u8 pad; + __le32 spatial_locations; + __le32 ll_protocol; + __u8 ll_mclk_role; + __u8 ll_bclk_role; + __u8 ll_wclk_role; + __u8 ll_wclk_polarity; + __u8 ll_wclk_change_edge; + __u8 ll_wclk_tx_edge; + __u8 ll_wclk_rx_edge; + __u8 ll_data_offset; +}; + +/* get supported configurations request has no payload */ +struct gb_i2s_mgmt_get_supported_configurations_response { + __u8 config_count; + __u8 pad[3]; + struct gb_i2s_mgmt_configuration config[0]; +}; + +struct gb_i2s_mgmt_set_configuration_request { + struct gb_i2s_mgmt_configuration config; +}; +/* set configuration response has no payload */ + +struct gb_i2s_mgmt_set_samples_per_message_request { + __le16 samples_per_message; +}; +/* set samples per message response has no payload */ + +/* get processing request delay has no payload */ +struct gb_i2s_mgmt_get_processing_delay_response { + __le32 microseconds; +}; + +struct gb_i2s_mgmt_set_start_delay_request { + __le32 microseconds; +}; +/* set start delay response has no payload */ + +struct gb_i2s_mgmt_activate_cport_request { + __le16 cport; +}; +/* activate cport response has no payload */ + +struct gb_i2s_mgmt_deactivate_cport_request { + __le16 cport; +}; +/* deactivate cport response has no payload */ + +struct gb_i2s_mgmt_report_event_request { + __u8 event; +}; +/* report event response has no payload */ + +#define GB_I2S_DATA_TYPE_PROTOCOL_VERSION 0x01 +#define GB_I2S_DATA_TYPE_SEND_DATA 0x02 + +struct gb_i2s_send_data_request { + __le32 sample_number; + __le32 size; + __u8 data[0]; +}; +/* send data has no response at all */ + + +/* SPI */ + +/* Version of the Greybus spi protocol we support */ +#define GB_SPI_VERSION_MAJOR 0x00 +#define GB_SPI_VERSION_MINOR 0x01 + +/* Should match up with modes in linux/spi/spi.h */ +#define GB_SPI_MODE_CPHA 0x01 /* clock phase */ +#define GB_SPI_MODE_CPOL 0x02 /* clock polarity */ +#define GB_SPI_MODE_MODE_0 (0|0) /* (original MicroWire) */ +#define GB_SPI_MODE_MODE_1 (0|GB_SPI_MODE_CPHA) +#define GB_SPI_MODE_MODE_2 (GB_SPI_MODE_CPOL|0) +#define GB_SPI_MODE_MODE_3 (GB_SPI_MODE_CPOL|GB_SPI_MODE_CPHA) +#define GB_SPI_MODE_CS_HIGH 0x04 /* chipselect active high? */ +#define GB_SPI_MODE_LSB_FIRST 0x08 /* per-word bits-on-wire */ +#define GB_SPI_MODE_3WIRE 0x10 /* SI/SO signals shared */ +#define GB_SPI_MODE_LOOP 0x20 /* loopback mode */ +#define GB_SPI_MODE_NO_CS 0x40 /* 1 dev/bus, no chipselect */ +#define GB_SPI_MODE_READY 0x80 /* slave pulls low to pause */ + +/* Should match up with flags in linux/spi/spi.h */ +#define GB_SPI_FLAG_HALF_DUPLEX BIT(0) /* can't do full duplex */ +#define GB_SPI_FLAG_NO_RX BIT(1) /* can't do buffer read */ +#define GB_SPI_FLAG_NO_TX BIT(2) /* can't do buffer write */ + +/* Greybus spi operation types */ +#define GB_SPI_TYPE_INVALID 0x00 +#define GB_SPI_TYPE_PROTOCOL_VERSION 0x01 +#define GB_SPI_TYPE_MODE 0x02 +#define GB_SPI_TYPE_FLAGS 0x03 +#define GB_SPI_TYPE_BITS_PER_WORD_MASK 0x04 +#define GB_SPI_TYPE_NUM_CHIPSELECT 0x05 +#define GB_SPI_TYPE_TRANSFER 0x06 + +/* mode request has no payload */ +struct gb_spi_mode_response { + __le16 mode; +}; + +/* flags request has no payload */ +struct gb_spi_flags_response { + __le16 flags; +}; + +/* bits-per-word request has no payload */ +struct gb_spi_bpw_response { + __le32 bits_per_word_mask; +}; + +/* num-chipselects request has no payload */ +struct gb_spi_chipselect_response { + __le16 num_chipselect; +}; + +/** + * struct gb_spi_transfer - a read/write buffer pair + * @speed_hz: Select a speed other than the device default for this transfer. If + * 0 the default (from @spi_device) is used. + * @len: size of rx and tx buffers (in bytes) + * @delay_usecs: microseconds to delay after this transfer before (optionally) + * changing the chipselect status, then starting the next transfer or + * completing this spi_message. + * @cs_change: affects chipselect after this transfer completes + * @bits_per_word: select a bits_per_word other than the device default for this + * transfer. If 0 the default (from @spi_device) is used. + */ +struct gb_spi_transfer { + __le32 speed_hz; + __le32 len; + __le16 delay_usecs; + __u8 cs_change; + __u8 bits_per_word; +}; + +struct gb_spi_transfer_request { + __u8 chip_select; /* of the spi device */ + __u8 mode; /* of the spi device */ + __le16 count; + struct gb_spi_transfer transfers[0]; /* trnasfer_count of these */ +}; + +struct gb_spi_transfer_response { + __u8 data[0]; /* inbound data */ +}; + +#endif /* __GB_GPBRIDGE_H__ */ -- cgit v0.10.2 From 8a760437229ac327796902098f402ef75955b520 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 22 May 2015 12:56:46 -0500 Subject: greybus: endo: encapsulate computing the max interface id The maximum interface id on an Endo is the result of a non-trivial calculation. It'll be needed for an upcoming patch, so create a macro to compute it. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c index 5b5a3c6..e4faa5c 100644 --- a/drivers/staging/greybus/endo.c +++ b/drivers/staging/greybus/endo.c @@ -29,6 +29,20 @@ #define endo_back_left_ribs(id, ribs) (((id) >> (ribs)) & ENDO_BACK_SIDE_RIBS_MASK(ribs)) #define endo_back_right_ribs(id, ribs) ((id) & ENDO_BACK_SIDE_RIBS_MASK(ribs)) +/* + * An Endo has interface block positions on the front and back. + * Each has numeric ID, starting with 1 (interface 0 represents + * the SVC within the Endo itself). The maximum interface ID is the + * also the number of non-SVC interfaces possible on the endo. + * + * Total number of interfaces: + * - Front: 4 + * - Back left: max_ribs + 1 + * - Back right: max_ribs + 1 + */ +#define max_endo_interface_id(endo_layout) \ + (4 + ((endo_layout)->max_ribs + 1) * 2) + /* endo sysfs attributes */ static ssize_t serial_number_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -361,19 +375,12 @@ static int create_modules(struct gb_endo *endo) int prev_module_id = 0; int interface_id; int module_id; - int interfaces; + int max_id; - /* - * Total number of interfaces: - * - Front: 4 - * - Back: - * - Left: max_ribs + 1 - * - Right: max_ribs + 1 - */ - interfaces = 4 + (endo->layout.max_ribs + 1) * 2; + max_id = max_endo_interface_id(&endo->layout); /* Find module corresponding to each interface */ - for (interface_id = 1; interface_id <= interfaces; interface_id++) { + for (interface_id = 1; interface_id <= max_id; interface_id++) { module_id = endo_get_module_id(endo, interface_id); if (WARN_ON(!module_id)) -- cgit v0.10.2 From e45524f849434074ff91d75bb9360a08aa535ba4 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 22 May 2015 12:56:47 -0500 Subject: greybus: endo: rework some attributes The SVC is not the same as the Endo. There are some attributes (such as the Endo ID) that are independent of attributes of the SVC (like its version). The current "Endo attributes" are really SVC attributes. Rename a few functions and variables to reflect that. Add a new attribute group for Endo-specific attributes, and populate it with the Endo ID. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c index e4faa5c..72037ff 100644 --- a/drivers/staging/greybus/endo.c +++ b/drivers/staging/greybus/endo.c @@ -44,35 +44,57 @@ (4 + ((endo_layout)->max_ribs + 1) * 2) /* endo sysfs attributes */ -static ssize_t serial_number_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t svc_serial_number_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct gb_endo *endo = to_gb_endo(dev); return sprintf(buf, "%s", &endo->svc_info.serial_number[0]); } -static DEVICE_ATTR_RO(serial_number); +static DEVICE_ATTR_RO(svc_serial_number); -static ssize_t version_show(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t svc_version_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct gb_endo *endo = to_gb_endo(dev); return sprintf(buf, "%s", &endo->svc_info.version[0]); } -static DEVICE_ATTR_RO(version); +static DEVICE_ATTR_RO(svc_version); + +static struct attribute *svc_attrs[] = { + &dev_attr_svc_serial_number.attr, + &dev_attr_svc_version.attr, + NULL, +}; + +static const struct attribute_group svc_group = { + .attrs = svc_attrs, + .name = "SVC", +}; + +static ssize_t endo_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_endo *endo = to_gb_endo(dev); + + return sprintf(buf, "0x%04x", endo->id); +} +static DEVICE_ATTR_RO(endo_id); static struct attribute *endo_attrs[] = { - &dev_attr_serial_number.attr, - &dev_attr_version.attr, + &dev_attr_endo_id.attr, NULL, }; + static const struct attribute_group endo_group = { .attrs = endo_attrs, - .name = "SVC", + .name = "Endo", }; + static const struct attribute_group *endo_groups[] = { &endo_group, + &svc_group, NULL, }; -- cgit v0.10.2 From 344943d2cdd85347637d0f3691c8c8bd34432247 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 22 May 2015 12:56:48 -0500 Subject: greybus: endo: record AP interface id The AP resides in a particular position on an Endo, which is identified by an interface ID. (For now we'll assume the AP uses just one interface.) Record the this AP interface ID when creating an Endo. Add a sysfs attribute to display it as well. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 7bfdbad..223c396 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -178,7 +178,8 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver { struct greybus_host_device *hd; struct gb_endo *endo; - u16 endo_id = 0x4755; // FIXME - get endo "ID" from the SVC + u16 endo_id = 0x4755; // FIXME - get endo "ID" from the SVC + u8 ap_intf_id = 0x01; // FIXME - get AP interface ID from the SVC /* * Validate that the driver implements all of the callbacks @@ -212,7 +213,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver ida_init(&hd->cport_id_map); hd->buffer_size_max = buffer_size_max; - endo = gb_endo_create(hd, endo_id); + endo = gb_endo_create(hd, endo_id, ap_intf_id); if (IS_ERR(endo)) { greybus_remove_hd(hd); return ERR_CAST(endo); diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c index 72037ff..7128a04 100644 --- a/drivers/staging/greybus/endo.c +++ b/drivers/staging/greybus/endo.c @@ -82,8 +82,18 @@ static ssize_t endo_id_show(struct device *dev, } static DEVICE_ATTR_RO(endo_id); +static ssize_t ap_intf_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_endo *endo = to_gb_endo(dev); + + return sprintf(buf, "0x%02x", endo->ap_intf_id); +} +static DEVICE_ATTR_RO(ap_intf_id); + static struct attribute *endo_attrs[] = { &dev_attr_endo_id.attr, + &dev_attr_ap_intf_id.attr, NULL, }; @@ -452,7 +462,8 @@ static int gb_endo_register(struct greybus_host_device *hd, return retval; } -struct gb_endo *gb_endo_create(struct greybus_host_device *hd, u16 endo_id) +struct gb_endo *gb_endo_create(struct greybus_host_device *hd, u16 endo_id, + u8 ap_intf_id) { struct gb_endo *endo; int retval; @@ -466,8 +477,12 @@ struct gb_endo *gb_endo_create(struct greybus_host_device *hd, u16 endo_id) retval = -EINVAL; goto free_endo; } - + if (ap_intf_id > max_endo_interface_id(&endo->layout)) { + retval = -EINVAL; + goto free_endo; + } endo->id = endo_id; + endo->ap_intf_id = ap_intf_id; /* Register Endo device */ retval = gb_endo_register(hd, endo); diff --git a/drivers/staging/greybus/endo.h b/drivers/staging/greybus/endo.h index c1ccbcd..01ef5c8 100644 --- a/drivers/staging/greybus/endo.h +++ b/drivers/staging/greybus/endo.h @@ -40,6 +40,7 @@ struct gb_endo { struct endo_layout layout; struct gb_svc_info svc_info; u16 id; + u8 ap_intf_id; }; #define to_gb_endo(d) container_of(d, struct gb_endo, dev) @@ -47,7 +48,8 @@ struct gb_endo { /* Greybus "private" definitions */ struct greybus_host_device; -struct gb_endo *gb_endo_create(struct greybus_host_device *hd, u16 endo_id); +struct gb_endo *gb_endo_create(struct greybus_host_device *hd, + u16 endo_id, u8 ap_intf_id); void gb_endo_remove(struct gb_endo *endo); u8 endo_get_module_id(struct gb_endo *endo, u8 interface_id); -- cgit v0.10.2 From eb765e4e91c8614c11ef2c4af7ce1222a30d6b79 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 22 May 2015 12:56:49 -0500 Subject: greybus: core: don't set up endo until host device is initialized Currently, the data structure representing an Endo is set up at the time a host device gets created. This is too early. Once the control infrastructure is in place, there's no sense in setting up the Endo utnil after we have heard from the SVC via a probe operation on our control CPort. And even then, there's no real point until we've successfully authenticated with the SVC, which will be indicated by the arrival of the Control protocol "connected" operation request notifying us that our SVC CPort is operational. In addition to this logical argument, we also can't actually receive any messages on the Control CPort until the host device is set up and ready to receive messages. At the point we're currently setting up the Endo data structure, that has not yet been done. Define a new exported function greybus_endo_setup(), which will be used (for now) as the entry point for setting up the Endo data structure. Arrange to call it in the host USB driver probe method, *after* we are set up for handling messages. Note: Once the control protocol has been implemented, this function may no longer need to be exported. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 223c396..290bee5 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -177,9 +177,6 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver size_t buffer_size_max) { struct greybus_host_device *hd; - struct gb_endo *endo; - u16 endo_id = 0x4755; // FIXME - get endo "ID" from the SVC - u8 ap_intf_id = 0x01; // FIXME - get AP interface ID from the SVC /* * Validate that the driver implements all of the callbacks @@ -213,16 +210,23 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver ida_init(&hd->cport_id_map); hd->buffer_size_max = buffer_size_max; + return hd; +} +EXPORT_SYMBOL_GPL(greybus_create_hd); + +int greybus_endo_setup(struct greybus_host_device *hd, u16 endo_id, + u8 ap_intf_id) +{ + struct gb_endo *endo; + endo = gb_endo_create(hd, endo_id, ap_intf_id); - if (IS_ERR(endo)) { - greybus_remove_hd(hd); - return ERR_CAST(endo); - } + if (IS_ERR(endo)) + return PTR_ERR(endo); hd->endo = endo; - return hd; + return 0; } -EXPORT_SYMBOL_GPL(greybus_create_hd); +EXPORT_SYMBOL_GPL(greybus_endo_setup); void greybus_remove_hd(struct greybus_host_device *hd) { diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 1ed10f4..f653954 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -551,6 +551,8 @@ static int ap_probe(struct usb_interface *interface, bool bulk_out_found = false; int retval = -ENOMEM; int i; + u16 endo_id = 0x4755; // FIXME - get endo "ID" from the SVC + u8 ap_intf_id = 0x01; // FIXME - get endo "ID" from the SVC u8 svc_interval = 0; udev = usb_get_dev(interface_to_usbdev(interface)); @@ -659,6 +661,17 @@ static int ap_probe(struct usb_interface *interface, gb_debugfs_get(), es1, &apb1_log_enable_fops); + /* + * XXX Soon this will be initiated later, with a combination + * XXX of a Control protocol probe operation and a + * XXX subsequent Control protocol connected operation for + * XXX the SVC connection. At that point we know we're + * XXX properly connected to an Endo. + */ + retval = greybus_endo_setup(hd, endo_id, ap_intf_id); + if (retval) + goto error; + return 0; error: ap_disconnect(interface); diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 4733adc..4f676cf 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -551,6 +551,8 @@ static int ap_probe(struct usb_interface *interface, bool bulk_out_found = false; int retval = -ENOMEM; int i; + u16 endo_id = 0x4755; // FIXME - get endo "ID" from the SVC + u8 ap_intf_id = 0x01; // FIXME - get endo "ID" from the SVC u8 svc_interval = 0; udev = usb_get_dev(interface_to_usbdev(interface)); @@ -659,6 +661,17 @@ static int ap_probe(struct usb_interface *interface, gb_debugfs_get(), es1, &apb1_log_enable_fops); + /* + * XXX Soon this will be initiated later, with a combination + * XXX of a Control protocol probe operation and a + * XXX subsequent Control protocol connected operation for + * XXX the SVC connection. At that point we know we're + * XXX properly connected to an Endo. + */ + retval = greybus_endo_setup(hd, endo_id, ap_intf_id); + if (retval) + goto error; + return 0; error: ap_disconnect(interface); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 4920458..30a93ea 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -108,6 +108,8 @@ struct greybus_host_device { struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *hd, struct device *parent, size_t buffer_size_max); +int greybus_endo_setup(struct greybus_host_device *hd, u16 endo_id, + u8 ap_intf_id); void greybus_remove_hd(struct greybus_host_device *hd); struct greybus_driver { -- cgit v0.10.2 From 2de1a8b1a95ce36288b66a9b7c9f08ea82061b5f Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 22 May 2015 12:59:15 -0500 Subject: greybus: add copyright statements The Greybus audio source files included no copyright statements. Add them. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio-dai.c b/drivers/staging/greybus/audio-dai.c index 0dd7364..9b162bf 100644 --- a/drivers/staging/greybus/audio-dai.c +++ b/drivers/staging/greybus/audio-dai.c @@ -1,3 +1,12 @@ +/* + * Greybus audio Digital Audio Interface (DAI) driver + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + #include #include #include diff --git a/drivers/staging/greybus/audio-gb-cmds.c b/drivers/staging/greybus/audio-gb-cmds.c index f6a29ab..9ca3164 100644 --- a/drivers/staging/greybus/audio-gb-cmds.c +++ b/drivers/staging/greybus/audio-gb-cmds.c @@ -1,3 +1,12 @@ +/* + * Greybus audio commands + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + #include #include "greybus.h" diff --git a/drivers/staging/greybus/audio-pcm.c b/drivers/staging/greybus/audio-pcm.c index a1faf78..c1b6aa5 100644 --- a/drivers/staging/greybus/audio-pcm.c +++ b/drivers/staging/greybus/audio-pcm.c @@ -1,3 +1,12 @@ +/* + * Greybus audio Pulse Code Modulation (PCM) driver + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + #include #include #include diff --git a/drivers/staging/greybus/audio.c b/drivers/staging/greybus/audio.c index c873f33..57c738b 100644 --- a/drivers/staging/greybus/audio.c +++ b/drivers/staging/greybus/audio.c @@ -1,3 +1,12 @@ +/* + * Greybus audio driver + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + #include #include #include diff --git a/drivers/staging/greybus/audio.h b/drivers/staging/greybus/audio.h index c9087c9fc..da95c1b 100644 --- a/drivers/staging/greybus/audio.h +++ b/drivers/staging/greybus/audio.h @@ -1,3 +1,12 @@ +/* + * Greybus audio + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + #ifndef __GB_AUDIO_H #define __GB_AUDIO_H #include -- cgit v0.10.2 From 4441f4759cfdf12840999676d2428a56f6248d8e Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 22 May 2015 12:59:16 -0500 Subject: greybus: update copyrights Update the copyright statements for recently-modified source files. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 290bee5..6106175 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -1,8 +1,8 @@ /* * Greybus "Core" * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. * * Released under the GPLv2 only. */ diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c index 7128a04..1e8485b 100644 --- a/drivers/staging/greybus/endo.c +++ b/drivers/staging/greybus/endo.c @@ -1,8 +1,8 @@ /* * Greybus endo code * - * Copyright 2015 Google Inc. - * Copyright 2014 Linaro Ltd. + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. * * Released under the GPLv2 only. */ diff --git a/drivers/staging/greybus/endo.h b/drivers/staging/greybus/endo.h index 01ef5c8..e211fb7 100644 --- a/drivers/staging/greybus/endo.h +++ b/drivers/staging/greybus/endo.h @@ -2,6 +2,7 @@ * Greybus endo code * * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. * * Released under the GPLv2 only. */ diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index f653954..2acfe74 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -1,8 +1,8 @@ /* - * Greybus "AP" USB driver + * Greybus "AP" USB driver for "ES1" controller chips * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. * * Released under the GPLv2 only. */ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 30a93ea..b9653f6 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -1,8 +1,8 @@ /* * Greybus driver and device API * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. * * Released under the GPLv2 only. */ diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 076d711..de1b1db 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -4,8 +4,8 @@ * See "Greybus Application Protocol" document (version 0.1) for * details on these values and structures. * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. * * Released under the GPLv2 and BSD licenses. */ -- cgit v0.10.2 From 30c6d9d753724bc616ee1e2ca5cadc03747b8b07 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 22 May 2015 13:02:08 -0500 Subject: greybus: introduce SVC protocol This patch adds support for the Greybus SVC protocol. We may want to rearrange protocol numbers at some point, since this is a pretty fundamental protocol. Note: It has only been compile tested; no SVC CPorts have yet been defined, so this code is not yet exercised. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index e5cae29..42804547 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -25,6 +25,7 @@ gb-phy-y := gpbridge.o \ audio-gb-cmds.o # Prefix all modules with gb- +gb-svc-y := svc.o gb-vibrator-y := vibrator.o gb-battery-y := battery.o gb-loopback-y := loopback.o @@ -33,6 +34,7 @@ gb-es1-y := es1.o gb-es2-y := es2.o obj-m += greybus.o +obj-m += gb-svc.o obj-m += gb-phy.o obj-m += gb-vibrator.o obj-m += gb-battery.o diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index b9653f6..86b2f9c 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -26,6 +26,7 @@ #include "greybus_protocols.h" #include "manifest.h" #include "endo.h" +#include "svc.h" #include "module.h" #include "interface.h" #include "bundle.h" diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index de1b1db..d6175ce 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -42,6 +42,7 @@ enum greybus_protocol { GREYBUS_PROTOCOL_LOOPBACK = 0x11, GREYBUS_PROTOCOL_I2S_RECEIVER = 0x12, GREYBUS_PROTOCOL_I2S_TRANSMITTER = 0x13, + GREYBUS_PROTOCOL_SVC = 0x14, /* ... */ GREYBUS_PROTOCOL_RAW = 0xfe, GREYBUS_PROTOCOL_VENDOR = 0xff, diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index c820805..28c40a0 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -489,4 +489,61 @@ struct gb_spi_transfer_response { __u8 data[0]; /* inbound data */ }; +/* Version of the Greybus SVC protocol we support */ +#define GB_SVC_VERSION_MAJOR 0x00 +#define GB_SVC_VERSION_MINOR 0x01 + +/* Greybus SVC request types */ +#define GB_SVC_TYPE_INVALID 0x00 +#define GB_SVC_TYPE_PROTOCOL_VERSION 0x01 +#define GB_SVC_TYPE_INTF_DEVICE_ID 0x02 +#define GB_SVC_TYPE_INTF_HOTPLUG 0x03 +#define GB_SVC_TYPE_INTF_HOT_UNPLUG 0x04 +#define GB_SVC_TYPE_INTF_RESET 0x05 +#define GB_SVC_TYPE_CONN_CREATE 0x06 +#define GB_SVC_TYPE_CONN_DESTROY 0x07 + +struct gb_svc_intf_device_id_request { + __u8 intf_id; + __u8 device_id; +}; +/* device id response has no payload */ + +struct gb_svc_intf_hotplug_request { + __u8 intf_id; + struct { + __le32 unipro_mfg_id; + __le32 unipro_prod_id; + __le32 ara_vend_id; + __le32 ara_prod_id; + } data; +}; +/* hotplug response has no payload */ + +struct gb_svc_intf_hot_unplug_request { + __u8 intf_id; +}; +/* hot unplug response has no payload */ + +struct gb_svc_intf_reset_request { + __u8 intf_id; +}; +/* interface reset response has no payload */ + +struct gb_svc_conn_create_request { + __u8 intf1_id; + __u16 cport1_id; + __u8 intf2_id; + __u16 cport2_id; +}; +/* connection create response has no payload */ + +struct gb_svc_conn_destroy_request { + __u8 intf1_id; + __u16 cport1_id; + __u8 intf2_id; + __u16 cport2_id; +}; +/* connection destroy response has no payload */ + #endif /* __GB_GPBRIDGE_H__ */ diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c new file mode 100644 index 0000000..e39eddb --- /dev/null +++ b/drivers/staging/greybus/svc.c @@ -0,0 +1,256 @@ +/* + * SVC Greybus driver. + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include + +#include "greybus.h" +#include "greybus_protocols.h" + +struct gb_svc { + struct gb_connection *connection; + u8 version_major; + u8 version_minor; +}; + +/* Define get_version() routine */ +define_get_version(gb_svc, SVC); + +static int intf_device_id_operation(struct gb_svc *svc, + u8 intf_id, u8 device_id) +{ + struct gb_svc_intf_device_id_request request; + + request.intf_id = intf_id; + request.device_id = device_id; + + return gb_operation_sync(svc->connection, GB_SVC_TYPE_INTF_DEVICE_ID, + &request, sizeof(request), NULL, 0); +} + +static int intf_reset_operation(struct gb_svc *svc, u8 intf_id) +{ + struct gb_svc_intf_reset_request request; + + request.intf_id = intf_id; + + return gb_operation_sync(svc->connection, GB_SVC_TYPE_INTF_RESET, + &request, sizeof(request), NULL, 0); +} + +static int connection_create_operation(struct gb_svc *svc, + u8 intf1_id, u16 cport1_id, + u8 intf2_id, u16 cport2_id) +{ + struct gb_svc_conn_create_request request; + + request.intf1_id = intf1_id; + request.cport1_id = cport1_id; + request.intf2_id = intf2_id; + request.cport2_id = cport2_id; + + return gb_operation_sync(svc->connection, GB_SVC_TYPE_CONN_CREATE, + &request, sizeof(request), NULL, 0); +} + +static int connection_destroy_operation(struct gb_svc *svc, + u8 intf1_id, u16 cport1_id, + u8 intf2_id, u16 cport2_id) +{ + struct gb_svc_conn_destroy_request request; + + request.intf1_id = intf1_id; + request.cport1_id = cport1_id; + request.intf2_id = intf2_id; + request.cport2_id = cport2_id; + + return gb_operation_sync(svc->connection, GB_SVC_TYPE_CONN_DESTROY, + &request, sizeof(request), NULL, 0); +} + +int gb_svc_intf_device_id(struct gb_svc *svc, u8 intf_id, u8 device_id) +{ + return intf_device_id_operation(svc, intf_id, device_id); +} +EXPORT_SYMBOL_GPL(gb_svc_intf_device_id); + +int gb_svc_intf_reset(struct gb_svc *svc, u8 intf_id) +{ + return intf_reset_operation(svc, intf_id); +} +EXPORT_SYMBOL_GPL(gb_svc_intf_reset); + +int gb_svc_connection_create(struct gb_svc *svc, + u8 intf1_id, u16 cport1_id, + u8 intf2_id, u16 cport2_id) +{ + return connection_create_operation(svc, intf1_id, cport1_id, + intf2_id, cport2_id); +} +EXPORT_SYMBOL_GPL(gb_svc_connection_create); + +int gb_svc_connection_destroy(struct gb_svc *svc, + u8 intf1_id, u16 cport1_id, + u8 intf2_id, u16 cport2_id) +{ + return connection_destroy_operation(svc, intf1_id, cport1_id, + intf2_id, cport2_id); +} +EXPORT_SYMBOL_GPL(gb_svc_connection_destroy); + +static int gb_svc_intf_hotplug_recv(struct gb_operation *op) +{ + struct gb_message *request = op->request; + struct gb_svc_intf_hotplug_request *hotplug; + u8 intf_id; + u32 unipro_mfg_id; + u32 unipro_prod_id; + u32 ara_vend_id; + u32 ara_prod_id; + + if (request->payload_size < sizeof(*hotplug)) { + dev_err(&op->connection->dev, + "short hotplug request received\n"); + return -EINVAL; + } + hotplug = request->payload; + + /* + * Grab the information we need. + * + * XXX I'd really like to acknowledge receipt, and then + * XXX continue processing the request. There's no need + * XXX for the SVC to wait. In fact, it might be best to + * XXX have the SVC get acknowledgement before we proceed. + * */ + intf_id = hotplug->intf_id; + unipro_mfg_id = hotplug->data.unipro_mfg_id; + unipro_prod_id = hotplug->data.unipro_prod_id; + ara_vend_id = hotplug->data.ara_vend_id; + ara_prod_id = hotplug->data.ara_prod_id; + + /* FIXME Set up the interface here; may required firmware download */ + + return 0; +} + +static int gb_svc_intf_hot_unplug_recv(struct gb_operation *op) +{ + struct gb_message *request = op->request; + struct gb_svc_intf_hot_unplug_request *hot_unplug; + u8 intf_id; + + if (request->payload_size < sizeof(*hot_unplug)) { + dev_err(&op->connection->dev, + "short hot unplug request received\n"); + return -EINVAL; + } + hot_unplug = request->payload; + + intf_id = hot_unplug->intf_id; + + /* FIXME Tear down the interface here */ + + return 0; + +} + +static int gb_svc_intf_reset_recv(struct gb_operation *op) +{ + struct gb_message *request = op->request; + struct gb_svc_intf_reset_request *reset; + u8 intf_id; + + if (request->payload_size < sizeof(*reset)) { + dev_err(&op->connection->dev, + "short reset request received\n"); + return -EINVAL; + } + reset = request->payload; + + intf_id = reset->intf_id; + + /* FIXME Reset the interface here */ + + return 0; +} + +static int gb_svc_request_recv(u8 type, struct gb_operation *op) +{ + switch (type) { + case GB_SVC_TYPE_INTF_HOTPLUG: + return gb_svc_intf_hotplug_recv(op); + case GB_SVC_TYPE_INTF_HOT_UNPLUG: + return gb_svc_intf_hot_unplug_recv(op); + case GB_SVC_TYPE_INTF_RESET: + return gb_svc_intf_reset_recv(op); + default: + dev_err(&op->connection->dev, + "unsupported request: %hhu\n", type); + return -EINVAL; + } +} + +/* + * Do initial setup of the SVC. + */ +static int gb_svc_device_setup(struct gb_svc *gb_svc) +{ + /* First thing we need to do is check the version */ + return get_version(gb_svc); +} + +static int gb_svc_connection_init(struct gb_connection *connection) +{ + struct gb_svc *svc; + int ret; + + svc = kzalloc(sizeof(*svc), GFP_KERNEL); + if (!svc) + return -ENOMEM; + + svc->connection = connection; + connection->private = svc; + ret = gb_svc_device_setup(svc); + if (ret) + kfree(svc); + + return ret; +} + +static void gb_svc_connection_exit(struct gb_connection *connection) +{ + struct gb_svc *svc = connection->private; + + if (!svc) + return; + + kfree(svc); +} + +static struct gb_protocol svc_protocol = { + .name = "svc", + .id = GREYBUS_PROTOCOL_SVC, + .major = 0, + .minor = 1, + .connection_init = gb_svc_connection_init, + .connection_exit = gb_svc_connection_exit, + .request_recv = gb_svc_request_recv, +}; + +int gb_svc_protocol_init(void) +{ + return gb_protocol_register(&svc_protocol); +} + +void gb_svc_protocol_exit(void) +{ + gb_protocol_deregister(&svc_protocol); +} diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h new file mode 100644 index 0000000..e26e637 --- /dev/null +++ b/drivers/staging/greybus/svc.h @@ -0,0 +1,22 @@ +/* + * Greybus SVC code + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#ifndef __SVC_H +#define __SVC_H + +struct gb_svc; + +int gb_svc_intf_device_id(struct gb_svc *svc, u8 intf_id, u8 device_id); +int gb_svc_intf_reset(struct gb_svc *svc, u8 intf_id); +int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, + u8 intf2_id, u16 cport2_id); +int gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, + u8 intf2_id, u16 cport2_id); + +#endif /* __SVC_H */ -- cgit v0.10.2 From 1d771fe41e629fad9077a0a1a9cf2771c9a5287d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 26 May 2015 15:29:18 +0200 Subject: greybus: operation: add support for incoming unidirectional operations Add support for incoming, unidirectional operations where the sender of a request does not care about a response. Unidirectional operations have an operation id of 0. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index f595b97..4f7a555 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -686,6 +686,10 @@ int gb_operation_response_send(struct gb_operation *operation, int errno) return -EIO; /* Shouldn't happen */ } + /* Sender of request does not care about response. */ + if (!operation->id) + return 0; + if (!operation->response) { if (!gb_operation_response_alloc(operation, 0)) { dev_err(&connection->dev, -- cgit v0.10.2 From c8d1ad8013681eeb2dc8dac405db3b95284adc1d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 26 May 2015 15:29:19 +0200 Subject: greybus: gpio: fix debugfs output Fix debugfs output by removing the unimplemented, custom dbg_show callback. The default implementation is perfectly sufficient. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 6e5fe5b3..0191bb8 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -414,11 +414,6 @@ static int gb_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, return gb_gpio_set_debounce_operation(ggc, (u8)offset, usec); } -static void gb_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) -{ - return; /* XXX */ -} - static int gb_gpio_controller_setup(struct gb_gpio_controller *ggc) { int ret; @@ -616,7 +611,6 @@ static int gb_gpio_connection_init(struct gb_connection *connection) gpio->get = gb_gpio_get; gpio->set = gb_gpio_set; gpio->set_debounce = gb_gpio_set_debounce; - gpio->dbg_show = gb_gpio_dbg_show; gpio->to_irq = gb_gpio_to_irq; gpio->base = -1; /* Allocate base dynamically */ gpio->ngpio = ggc->line_max + 1; -- cgit v0.10.2 From b8e3ffebac09b29ad4cc0bdbcafbbd77b3278685 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 26 May 2015 15:29:20 +0200 Subject: greybus: gpio: remove unused irq-ack operation Remove unused irq-ack operation, which has never been called and does not make sense for message-signalled interrupts over slow buses. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 0191bb8..c570f62 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -211,21 +211,6 @@ static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *ggc, return ret; } -static void gb_gpio_ack_irq(struct irq_data *d) -{ - struct gpio_chip *chip = irq_data_to_gpio_chip(d); - struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); - struct gb_gpio_irq_ack_request request; - int ret; - - request.which = d->hwirq; - ret = gb_operation_sync(ggc->connection, - GB_GPIO_TYPE_IRQ_ACK, - &request, sizeof(request), NULL, 0); - if (ret) - dev_err(chip->dev, "failed to ack irq: %d\n", ret); -} - static void gb_gpio_mask_irq(struct irq_data *d) { struct gpio_chip *chip = irq_data_to_gpio_chip(d); @@ -591,7 +576,6 @@ static int gb_gpio_connection_init(struct gb_connection *connection) goto err_free_controller; irqc = &ggc->irqc; - irqc->irq_ack = gb_gpio_ack_irq; irqc->irq_mask = gb_gpio_mask_irq; irqc->irq_unmask = gb_gpio_unmask_irq; irqc->irq_set_type = gb_gpio_irq_set_type; diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 28c40a0..0fd42bc 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -128,7 +128,6 @@ struct gb_i2c_transfer_response { #define GB_GPIO_TYPE_SET_VALUE 0x09 #define GB_GPIO_TYPE_SET_DEBOUNCE 0x0a #define GB_GPIO_TYPE_IRQ_TYPE 0x0b -#define GB_GPIO_TYPE_IRQ_ACK 0x0c #define GB_GPIO_TYPE_IRQ_MASK 0x0d #define GB_GPIO_TYPE_IRQ_UNMASK 0x0e #define GB_GPIO_TYPE_IRQ_EVENT 0x0f @@ -203,11 +202,6 @@ struct gb_gpio_irq_unmask_request { }; /* irq unmask response has no payload */ -struct gb_gpio_irq_ack_request { - __u8 which; -}; -/* irq ack response has no payload */ - /* irq event requests originate on another module and are handled on the AP */ struct gb_gpio_irq_event_request { __u8 which; -- cgit v0.10.2 From 2611ebef8322fc12dc3c6b0ec869f1902aa25626 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 26 May 2015 15:29:21 +0200 Subject: greybus: gpio: don't call irq-flow handler directly Use generic_handle_irq_desc rather than call a hardcoded irq-flow handler directly. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index c570f62..526dd7e 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -314,9 +314,8 @@ static int gb_gpio_request_recv(u8 type, struct gb_operation *op) return -EINVAL; } - /* Dispatch interrupt */ local_irq_disable(); - handle_simple_irq(irq, desc); + generic_handle_irq_desc(irq, desc); local_irq_enable(); return 0; -- cgit v0.10.2 From ec762115a5006db8549b3582f7f19849f7cf4ab4 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 26 May 2015 15:29:22 +0200 Subject: greybus: gpio: use irq-domain lookups Use irq_find_mapping directly rather than go through the legacy gpio interface. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 526dd7e..15cc0ea 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -303,9 +303,9 @@ static int gb_gpio_request_recv(u8 type, struct gb_operation *op) return -EINVAL; } - irq = gpio_to_irq(ggc->chip.base + event->which); - if (irq < 0) { - dev_err(ggc->chip.dev, "failed to map irq\n"); + irq = irq_find_mapping(ggc->irqdomain, event->which); + if (!irq) { + dev_err(ggc->chip.dev, "failed to find IRQ\n"); return -EINVAL; } desc = irq_to_desc(irq); -- cgit v0.10.2 From 0cb918d72d8f76b1189a63cefedbc5cb4dad9d54 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 26 May 2015 15:29:23 +0200 Subject: greybus: gpio: rename irq mask and unmask callbacks Rename irq mask and unmask functions to match the callback names. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 15cc0ea..0220a9f 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -211,7 +211,7 @@ static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *ggc, return ret; } -static void gb_gpio_mask_irq(struct irq_data *d) +static void gb_gpio_irq_mask(struct irq_data *d) { struct gpio_chip *chip = irq_data_to_gpio_chip(d); struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); @@ -226,7 +226,7 @@ static void gb_gpio_mask_irq(struct irq_data *d) dev_err(chip->dev, "failed to mask irq: %d\n", ret); } -static void gb_gpio_unmask_irq(struct irq_data *d) +static void gb_gpio_irq_unmask(struct irq_data *d) { struct gpio_chip *chip = irq_data_to_gpio_chip(d); struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); @@ -575,8 +575,8 @@ static int gb_gpio_connection_init(struct gb_connection *connection) goto err_free_controller; irqc = &ggc->irqc; - irqc->irq_mask = gb_gpio_mask_irq; - irqc->irq_unmask = gb_gpio_unmask_irq; + irqc->irq_mask = gb_gpio_irq_mask; + irqc->irq_unmask = gb_gpio_irq_unmask; irqc->irq_set_type = gb_gpio_irq_set_type; irqc->name = "greybus_gpio"; -- cgit v0.10.2 From 25f11ed965bb57b6e25d5464a8cd8b3657319056 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 26 May 2015 15:29:24 +0200 Subject: greybus: gpio: fix atomic sleep when using interrupts The irq-chip callbacks are made in atomic context where we must not do any synchronous greybus operations. Fix the current gpio-interrupt implementation by using the bus-lock functionality provided by the irq subsystem. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 0220a9f..6cf3bb1 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -13,6 +13,8 @@ #include #include #include +#include + #include "greybus.h" struct gb_gpio_line { @@ -22,6 +24,11 @@ struct gb_gpio_line { direction: 1, /* 0 = output, 1 = input */ value: 1; /* 0 = low, 1 = high */ u16 debounce_usec; + + u8 irq_type; + bool irq_type_pending; + bool masked; + bool masked_pending; }; struct gb_gpio_controller { @@ -38,6 +45,7 @@ struct gb_gpio_controller { unsigned int irq_base; irq_flow_handler_t irq_handler; unsigned int irq_default_type; + struct mutex irq_lock; }; #define gpio_chip_to_gb_gpio_controller(chip) \ container_of(chip, struct gb_gpio_controller, chip) @@ -211,68 +219,121 @@ static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *ggc, return ret; } -static void gb_gpio_irq_mask(struct irq_data *d) +static void _gb_gpio_irq_mask(struct gb_gpio_controller *ggc, u8 hwirq) { - struct gpio_chip *chip = irq_data_to_gpio_chip(d); - struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); struct gb_gpio_irq_mask_request request; int ret; - request.which = d->hwirq; + request.which = hwirq; ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_IRQ_MASK, &request, sizeof(request), NULL, 0); if (ret) - dev_err(chip->dev, "failed to mask irq: %d\n", ret); + dev_err(ggc->chip.dev, "failed to mask irq: %d\n", ret); } -static void gb_gpio_irq_unmask(struct irq_data *d) +static void _gb_gpio_irq_unmask(struct gb_gpio_controller *ggc, u8 hwirq) { - struct gpio_chip *chip = irq_data_to_gpio_chip(d); - struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); struct gb_gpio_irq_unmask_request request; int ret; - request.which = d->hwirq; + request.which = hwirq; ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_IRQ_UNMASK, &request, sizeof(request), NULL, 0); if (ret) - dev_err(chip->dev, "failed to unmask irq: %d\n", ret); + dev_err(ggc->chip.dev, "failed to unmask irq: %d\n", ret); } -static int gb_gpio_irq_set_type(struct irq_data *d, unsigned int type) +static void _gb_gpio_irq_set_type(struct gb_gpio_controller *ggc, + u8 hwirq, u8 type) { - struct gpio_chip *chip = irq_data_to_gpio_chip(d); - struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); struct gb_gpio_irq_type_request request; - int ret = 0; + int ret; - request.which = d->hwirq; + request.which = hwirq; request.type = type; + ret = gb_operation_sync(ggc->connection, + GB_GPIO_TYPE_IRQ_TYPE, + &request, sizeof(request), NULL, 0); + if (ret) + dev_err(ggc->chip.dev, "failed to set irq type: %d\n", ret); +} + +static void gb_gpio_irq_mask(struct irq_data *d) +{ + struct gpio_chip *chip = irq_data_to_gpio_chip(d); + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_line *line = &ggc->lines[d->hwirq]; + + line->masked = true; + line->masked_pending = true; +} + +static void gb_gpio_irq_unmask(struct irq_data *d) +{ + struct gpio_chip *chip = irq_data_to_gpio_chip(d); + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_line *line = &ggc->lines[d->hwirq]; + + line->masked = false; + line->masked_pending = true; +} + +static int gb_gpio_irq_set_type(struct irq_data *d, unsigned int type) +{ + struct gpio_chip *chip = irq_data_to_gpio_chip(d); + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_line *line = &ggc->lines[d->hwirq]; + switch (type) { case IRQ_TYPE_NONE: - break; case IRQ_TYPE_EDGE_RISING: case IRQ_TYPE_EDGE_FALLING: case IRQ_TYPE_EDGE_BOTH: case IRQ_TYPE_LEVEL_LOW: case IRQ_TYPE_LEVEL_HIGH: - ret = gb_operation_sync(ggc->connection, - GB_GPIO_TYPE_IRQ_TYPE, - &request, sizeof(request), NULL, 0); - if (ret) { - dev_err(chip->dev, "failed to set irq type: %d\n", - ret); - } break; default: dev_err(chip->dev, "unsupported irq type: %u\n", type); - ret = -EINVAL; + return -EINVAL; } - return ret; + line->irq_type = type; + line->irq_type_pending = true; + + return 0; +} + +static void gb_gpio_irq_bus_lock(struct irq_data *d) +{ + struct gpio_chip *chip = irq_data_to_gpio_chip(d); + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + + mutex_lock(&ggc->irq_lock); +} + +static void gb_gpio_irq_bus_sync_unlock(struct irq_data *d) +{ + struct gpio_chip *chip = irq_data_to_gpio_chip(d); + struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_line *line = &ggc->lines[d->hwirq]; + + if (line->irq_type_pending) { + _gb_gpio_irq_set_type(ggc, d->hwirq, line->irq_type); + line->irq_type_pending = false; + } + + if (line->masked_pending) { + if (line->masked) + _gb_gpio_irq_mask(ggc, d->hwirq); + else + _gb_gpio_irq_unmask(ggc, d->hwirq); + line->masked_pending = false; + } + + mutex_unlock(&ggc->irq_lock); } static int gb_gpio_request_recv(u8 type, struct gb_operation *op) @@ -578,8 +639,12 @@ static int gb_gpio_connection_init(struct gb_connection *connection) irqc->irq_mask = gb_gpio_irq_mask; irqc->irq_unmask = gb_gpio_irq_unmask; irqc->irq_set_type = gb_gpio_irq_set_type; + irqc->irq_bus_lock = gb_gpio_irq_bus_lock; + irqc->irq_bus_sync_unlock = gb_gpio_irq_bus_sync_unlock; irqc->name = "greybus_gpio"; + mutex_init(&ggc->irq_lock); + gpio = &ggc->chip; gpio->label = "greybus_gpio"; -- cgit v0.10.2 From 1409c4d6a841b00f3b4bdf010808a81eda6b7727 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 26 May 2015 15:29:25 +0200 Subject: greybus: gpio: fix interrupt protocol The current interrupt implementation uses the simple irq-flow handler, which means that the interrupt subsystem makes no irq-chip callbacks when handling an interrupt. Specifically, no end-of-interrupt message is sent when the threaded handler has run. This means that we may currently re-enable an interrupt before it has been serviced (i.e. the irq-event operation may complete before the threaded handler has run). The simple flow handler also silently drops a second interrupt arriving while a handler is running. This means that we may lose a second edge interrupt with the current firmware. Switch to a new one-shot interrupt protocol, where the primary handler (firmware) always masks and acks an interrupt before sending an event to the AP. The AP is responsible for unmasking the interrupt when it has been handled. By having the firmware ack an edge interrupt before sending the event, a second edge interrupt will no longer get lost. This one-shot protocol can be implemented in the kernel by using the level irq-flow handler, one-shot interrupts with threaded handlers and bus-lock synchronisation for slow buses. Note that the same flow handler is used for both edge and level interrupts. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 6cf3bb1..8dad9e5 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -672,7 +672,7 @@ static int gb_gpio_connection_init(struct gb_connection *connection) } ret = gb_gpio_irqchip_add(gpio, irqc, 0, - handle_simple_irq, IRQ_TYPE_NONE); + handle_level_irq, IRQ_TYPE_NONE); if (ret) { dev_err(&connection->dev, "failed to add irq chip: %d\n", ret); goto irqchip_err; diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 0fd42bc..81ec3b2 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -206,7 +206,7 @@ struct gb_gpio_irq_unmask_request { struct gb_gpio_irq_event_request { __u8 which; }; -/* irq event response has no payload */ +/* irq event has no response */ /* PWM */ -- cgit v0.10.2 From ea15a40b32dcc068a2af406ba894e2179c315469 Mon Sep 17 00:00:00 2001 From: Phong Tran Date: Wed, 27 May 2015 21:31:02 +0700 Subject: greybus: svc: Fix endian of hotplug request data data of hotplug request should exchange to native CPU format before assignment. Signed-off-by: Phong Tran Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index e39eddb..ffbeac5 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -131,10 +131,10 @@ static int gb_svc_intf_hotplug_recv(struct gb_operation *op) * XXX have the SVC get acknowledgement before we proceed. * */ intf_id = hotplug->intf_id; - unipro_mfg_id = hotplug->data.unipro_mfg_id; - unipro_prod_id = hotplug->data.unipro_prod_id; - ara_vend_id = hotplug->data.ara_vend_id; - ara_prod_id = hotplug->data.ara_prod_id; + unipro_mfg_id = le32_to_cpu(hotplug->data.unipro_mfg_id); + unipro_prod_id = le32_to_cpu(hotplug->data.unipro_prod_id); + ara_vend_id = le32_to_cpu(hotplug->data.ara_vend_id); + ara_prod_id = le32_to_cpu(hotplug->data.ara_prod_id); /* FIXME Set up the interface here; may required firmware download */ -- cgit v0.10.2 From b61fa7bce4acdae51e5b76c358237d1ad5dfdbc5 Mon Sep 17 00:00:00 2001 From: Phong Tran Date: Wed, 27 May 2015 21:31:03 +0700 Subject: greybus: svc: use macro for init and exit protocol Change to gb_gpbridge_protocol_driver for making the consitent with other drivers. Signed-off-by: Phong Tran Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index ffbeac5..4dc10e3 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -245,12 +245,4 @@ static struct gb_protocol svc_protocol = { .request_recv = gb_svc_request_recv, }; -int gb_svc_protocol_init(void) -{ - return gb_protocol_register(&svc_protocol); -} - -void gb_svc_protocol_exit(void) -{ - gb_protocol_deregister(&svc_protocol); -} +gb_gpbridge_protocol_driver(svc_protocol); -- cgit v0.10.2 From 47bf0b44275eaf4659f99b1ddde5da85018aaf46 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 27 May 2015 12:45:07 +0200 Subject: greybus: gpio: update operation types Update the remaining operation types now that the ack operation is gone to avoid leaving a hole in the type definitions. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 81ec3b2..305c33d 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -128,9 +128,9 @@ struct gb_i2c_transfer_response { #define GB_GPIO_TYPE_SET_VALUE 0x09 #define GB_GPIO_TYPE_SET_DEBOUNCE 0x0a #define GB_GPIO_TYPE_IRQ_TYPE 0x0b -#define GB_GPIO_TYPE_IRQ_MASK 0x0d -#define GB_GPIO_TYPE_IRQ_UNMASK 0x0e -#define GB_GPIO_TYPE_IRQ_EVENT 0x0f +#define GB_GPIO_TYPE_IRQ_MASK 0x0c +#define GB_GPIO_TYPE_IRQ_UNMASK 0x0d +#define GB_GPIO_TYPE_IRQ_EVENT 0x0e #define GB_GPIO_DEBOUNCE_USEC_DEFAULT 0 /* microseconds */ -- cgit v0.10.2 From 012d7d4fbeb2b261c679f58e39b31657ffb0191d Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 27 May 2015 14:45:58 -0500 Subject: greybus: greybus_protocols: fix guard tag I neglected to update the "#ifndef/#define" when I renamed "greybus_protocols.h". Fix that. Signed-off-by: Alex Elder Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 305c33d..32d8464 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -49,8 +49,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __GB_GPBRIDGE_H__ -#define __GB_GPBRIDGE_H__ +#ifndef __GREYBUS_PROTOCOLS_H +#define __GREYBUS_PROTOCOLS_H /* I2C */ @@ -540,4 +540,4 @@ struct gb_svc_conn_destroy_request { }; /* connection destroy response has no payload */ -#endif /* __GB_GPBRIDGE_H__ */ +#endif /* __GREYBUS_PROTOCOLS_H */ -- cgit v0.10.2 From bcd8215b49b08194ee6e2968106ac5a14825b689 Mon Sep 17 00:00:00 2001 From: Phong Tran Date: Thu, 28 May 2015 23:21:00 +0700 Subject: greybus: audio: Fix typo for macro I2S data version minor This macro should be DATA not MGMT. Signed-off-by: Phong Tran Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio-gb-cmds.c b/drivers/staging/greybus/audio-gb-cmds.c index 9ca3164..10de34d 100644 --- a/drivers/staging/greybus/audio-gb-cmds.c +++ b/drivers/staging/greybus/audio-gb-cmds.c @@ -16,7 +16,7 @@ #define GB_I2S_MGMT_VERSION_MINOR 0x01 #define GB_I2S_DATA_VERSION_MAJOR 0x00 -#define GB_I2S_MGMT_VERSION_MINOR 0x01 +#define GB_I2S_DATA_VERSION_MINOR 0x01 /*********************************** * GB I2S helper functions -- cgit v0.10.2 From df76422113b0a80198bccf1a3d2515afe00db736 Mon Sep 17 00:00:00 2001 From: Phong Tran Date: Thu, 28 May 2015 23:21:01 +0700 Subject: greybus: audio: Remove the MODULE_LICENSE() This is not a kernel module. It should not use the module license macro. Signed-off-by: Phong Tran Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio.c b/drivers/staging/greybus/audio.c index 57c738b..a077c2b 100644 --- a/drivers/staging/greybus/audio.c +++ b/drivers/staging/greybus/audio.c @@ -470,6 +470,3 @@ void gb_audio_protocol_exit(void) gb_protocol_deregister(&gb_i2s_receiver_protocol); gb_protocol_deregister(&gb_i2s_mgmt_protocol); } - - -MODULE_LICENSE("GPL"); -- cgit v0.10.2 From b4dbf1e13268e5a7d88e8bdc4d4d0c481f8f53e7 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 27 May 2015 11:17:50 -0500 Subject: greybus: add documentation for Endo sysfs files Update the files documenting Greybus-related sysfs files under Documentation/ to reflect the addition of the two recently-added Endo attributes. Signed-off-by: Alex Elder Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index ab728a4..6815b91 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -7,6 +7,25 @@ Description: replaced with the numeric value of the endo layout scheme as documented in the ARA Module Developer Kit. +What: /sys/bus/greybus/device/endo-XXXX/Endo/id +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The Endo ID, which is a 2-byte hexadecimal value + defined by the the Endo layout scheme, documented in + the ARA Module Developer Kit. + +What: /sys/bus/greybus/device/endo-XXXX/Endo/ap_intf_id +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The AP interface ID, a small non-zero integer which + defines the position of the AP module on the Endo. + The interface positions are defined in the ARA + Module Developer Kit. + What: /sys/bus/greybus/device/endo-XXXX/SVC/serial_number Date: October 2015 KernelVersion: 4.XX diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/Endo/ap_intf_id b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/Endo/ap_intf_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/Endo/endo_id b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/Endo/endo_id new file mode 100644 index 0000000..e69de29 -- cgit v0.10.2 From 28e3cedcceecb62ecbc77a35eda3875bbe981f1b Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 27 May 2015 11:17:51 -0500 Subject: greybus: update sysfs documentation files Impose a few editorial conventions on the Greybus-related sysfs files under "Documentation". - Capitalize "Endo" (except in path names) - Capitalize "ID" (except in path names) - Use "..." to indicate unspecified path components (because ".." means something else). - Add the "0x" prior to the "XXXX" representing the Endo ID. Signed-off-by: Alex Elder Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 6815b91..738dcff 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -1,4 +1,4 @@ -What: /sys/bus/greybus/device/endo-XXXX +What: /sys/bus/greybus/device/endo-0xXXXX Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman @@ -7,7 +7,7 @@ Description: replaced with the numeric value of the endo layout scheme as documented in the ARA Module Developer Kit. -What: /sys/bus/greybus/device/endo-XXXX/Endo/id +What: /sys/bus/greybus/device/endo-0xXXXX/Endo/id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman @@ -16,7 +16,7 @@ Description: defined by the the Endo layout scheme, documented in the ARA Module Developer Kit. -What: /sys/bus/greybus/device/endo-XXXX/Endo/ap_intf_id +What: /sys/bus/greybus/device/endo-0xXXXX/Endo/ap_intf_id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman @@ -26,21 +26,21 @@ Description: The interface positions are defined in the ARA Module Developer Kit. -What: /sys/bus/greybus/device/endo-XXXX/SVC/serial_number +What: /sys/bus/greybus/device/endo-0xXXXX/SVC/serial_number Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: The serial number of the SVC device -What: /sys/bus/greybus/device/endo-XXXX/SVC/version +What: /sys/bus/greybus/device/endo-0xXXXX/SVC/version Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: The version number of the firmware in the SVC device. -What: /sys/bus/greybus/device/endo-XXXX/../epm +What: /sys/bus/greybus/device/endo-0xXXXX/.../epm Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman @@ -50,7 +50,7 @@ Description: Writing 1 to it turns it on, writing 0 to it turns it off. Reading the value returns if it is on or off. -What: /sys/bus/greybus/device/endo-XXXX/../power_control +What: /sys/bus/greybus/device/endo-0xXXXX/.../power_control Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman @@ -60,7 +60,7 @@ Description: to the module, writing 0 to it turns power off to the module. Reading the value returns if it is on or off. -What: /sys/bus/greybus/device/endo-XXXX/../present +What: /sys/bus/greybus/device/endo-0xXXXX/.../present Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman @@ -124,14 +124,14 @@ Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: - The protocol id of a Greybus connection. + The protocol ID of a Greybus connection. What: /sys/bus/greybus/device/.../device_id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: - The device id of a Greybus bundle. + The device ID of a Greybus bundle. What: /sys/bus/greybus/device/.../state Date: October 2015 -- cgit v0.10.2 From 312bb84942cb6707cf9b3933a6c74cbe5e9ed037 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 27 May 2015 11:17:52 -0500 Subject: greybus: endo: drop redundant prefixes from sysfs basenames This commit: 7e761e2 endo: rework some attributes added a new "endo_id" attribute, located under a new "Endo" directory in sysfs. The resulting path looks like: Documentation/sysfs/endo-TYPE/Endo/endo_id There's no need to have a separate "Endo" subdirectory to contain Endo-specific attributes. That commit also added "svc_" to some other paths related to the SVC, like: Documentation/sysfs/endo-TYPE/SVC/svc_version The additional "svc_" is redundant. This patch retouches those paths a bit, mainly to remove some redundancy. It also makes the pathname components all lower case. As a result, the above two paths now look like: Documentation/sysfs/endo-TYPE/id Documentation/sysfs/endo-TYPE/svc/version All other Endo sysfs files are updated similarly. Signed-off-by: Alex Elder Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 738dcff..9cd3e02 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -7,7 +7,7 @@ Description: replaced with the numeric value of the endo layout scheme as documented in the ARA Module Developer Kit. -What: /sys/bus/greybus/device/endo-0xXXXX/Endo/id +What: /sys/bus/greybus/device/endo-0xXXXX/id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman @@ -16,7 +16,7 @@ Description: defined by the the Endo layout scheme, documented in the ARA Module Developer Kit. -What: /sys/bus/greybus/device/endo-0xXXXX/Endo/ap_intf_id +What: /sys/bus/greybus/device/endo-0xXXXX/ap_intf_id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman @@ -26,14 +26,14 @@ Description: The interface positions are defined in the ARA Module Developer Kit. -What: /sys/bus/greybus/device/endo-0xXXXX/SVC/serial_number +What: /sys/bus/greybus/device/endo-0xXXXX/svc/serial_number Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: The serial number of the SVC device -What: /sys/bus/greybus/device/endo-0xXXXX/SVC/version +What: /sys/bus/greybus/device/endo-0xXXXX/svc/version Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/Endo/ap_intf_id b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/Endo/ap_intf_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/Endo/endo_id b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/Endo/endo_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/SVC/firmware b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/SVC/firmware deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/SVC/serial_number b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/SVC/serial_number deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/SVC/version b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/SVC/version deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/ap_intf_id b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/ap_intf_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/id b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/svc/firmware b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/svc/firmware new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/svc/serial_number b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/svc/serial_number new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/svc/version b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/svc/version new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c index 1e8485b..aa89868 100644 --- a/drivers/staging/greybus/endo.c +++ b/drivers/staging/greybus/endo.c @@ -44,43 +44,43 @@ (4 + ((endo_layout)->max_ribs + 1) * 2) /* endo sysfs attributes */ -static ssize_t svc_serial_number_show(struct device *dev, +static ssize_t serial_number_show(struct device *dev, struct device_attribute *attr, char *buf) { struct gb_endo *endo = to_gb_endo(dev); return sprintf(buf, "%s", &endo->svc_info.serial_number[0]); } -static DEVICE_ATTR_RO(svc_serial_number); +static DEVICE_ATTR_RO(serial_number); -static ssize_t svc_version_show(struct device *dev, +static ssize_t version_show(struct device *dev, struct device_attribute *attr, char *buf) { struct gb_endo *endo = to_gb_endo(dev); return sprintf(buf, "%s", &endo->svc_info.version[0]); } -static DEVICE_ATTR_RO(svc_version); +static DEVICE_ATTR_RO(version); static struct attribute *svc_attrs[] = { - &dev_attr_svc_serial_number.attr, - &dev_attr_svc_version.attr, + &dev_attr_serial_number.attr, + &dev_attr_version.attr, NULL, }; static const struct attribute_group svc_group = { .attrs = svc_attrs, - .name = "SVC", + .name = "svc", }; -static ssize_t endo_id_show(struct device *dev, +static ssize_t id_show(struct device *dev, struct device_attribute *attr, char *buf) { struct gb_endo *endo = to_gb_endo(dev); return sprintf(buf, "0x%04x", endo->id); } -static DEVICE_ATTR_RO(endo_id); +static DEVICE_ATTR_RO(id); static ssize_t ap_intf_id_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -92,14 +92,13 @@ static ssize_t ap_intf_id_show(struct device *dev, static DEVICE_ATTR_RO(ap_intf_id); static struct attribute *endo_attrs[] = { - &dev_attr_endo_id.attr, + &dev_attr_id.attr, &dev_attr_ap_intf_id.attr, NULL, }; static const struct attribute_group endo_group = { .attrs = endo_attrs, - .name = "Endo", }; static const struct attribute_group *endo_groups[] = { -- cgit v0.10.2 From e6cebf8770472f0cd8ac8dd887316164822228a6 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 27 May 2015 11:17:53 -0500 Subject: greybus: endo: delete "0xXXXX" portion in sysfs "endo" directory With the Endo "id" attribute in place, there's no need to encode the ID of an Endo in its sysfs path. So get rid of it. Signed-off-by: Alex Elder Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 9cd3e02..0268dd2 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -1,4 +1,4 @@ -What: /sys/bus/greybus/device/endo-0xXXXX +What: /sys/bus/greybus/device/endo Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman @@ -7,7 +7,7 @@ Description: replaced with the numeric value of the endo layout scheme as documented in the ARA Module Developer Kit. -What: /sys/bus/greybus/device/endo-0xXXXX/id +What: /sys/bus/greybus/device/endo/id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman @@ -16,7 +16,7 @@ Description: defined by the the Endo layout scheme, documented in the ARA Module Developer Kit. -What: /sys/bus/greybus/device/endo-0xXXXX/ap_intf_id +What: /sys/bus/greybus/device/endo/ap_intf_id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman @@ -26,21 +26,21 @@ Description: The interface positions are defined in the ARA Module Developer Kit. -What: /sys/bus/greybus/device/endo-0xXXXX/svc/serial_number +What: /sys/bus/greybus/device/endo/svc/serial_number Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: The serial number of the SVC device -What: /sys/bus/greybus/device/endo-0xXXXX/svc/version +What: /sys/bus/greybus/device/endo/svc/version Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: The version number of the firmware in the SVC device. -What: /sys/bus/greybus/device/endo-0xXXXX/.../epm +What: /sys/bus/greybus/device/endo/../epm Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman @@ -50,7 +50,7 @@ Description: Writing 1 to it turns it on, writing 0 to it turns it off. Reading the value returns if it is on or off. -What: /sys/bus/greybus/device/endo-0xXXXX/.../power_control +What: /sys/bus/greybus/device/endo/.../power_control Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman @@ -60,7 +60,7 @@ Description: to the module, writing 0 to it turns power off to the module. Reading the value returns if it is on or off. -What: /sys/bus/greybus/device/endo-0xXXXX/.../present +What: /sys/bus/greybus/device/endo/.../present Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/01/gpbridge00/gpio/.gitignore b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/01/gpbridge00/gpio/.gitignore deleted file mode 100644 index f935021..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/01/gpbridge00/gpio/.gitignore +++ /dev/null @@ -1 +0,0 @@ -!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/01/gpbridge00/i2c/.gitignore b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/01/gpbridge00/i2c/.gitignore deleted file mode 100644 index f935021..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/01/gpbridge00/i2c/.gitignore +++ /dev/null @@ -1 +0,0 @@ -!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/01/gpbridge00/usb/.gitignore b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/01/gpbridge00/usb/.gitignore deleted file mode 100644 index f935021..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/01/gpbridge00/usb/.gitignore +++ /dev/null @@ -1 +0,0 @@ -!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/firmware b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/firmware deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/manifest b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/manifest deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/product_id b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/product_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/product_name b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/product_name deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/state b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/state deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/uid b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/uid deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/version_major b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/version_major deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/version_minor b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/version_minor deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/epm b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/epm deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/power b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/power deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/present b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/present deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/02/.gitignore b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/02/.gitignore deleted file mode 100644 index f935021..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/02/.gitignore +++ /dev/null @@ -1 +0,0 @@ -!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/ap_intf_id b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/ap_intf_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/id b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/svc/firmware b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/svc/firmware deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/svc/serial_number b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/svc/serial_number deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/svc/version b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/svc/version deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/01/01/01/01/gpbridge00/gpio/.gitignore b/drivers/staging/greybus/Documentation/sysfs/endo/01/01/01/01/gpbridge00/gpio/.gitignore new file mode 100644 index 0000000..f935021 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/endo/01/01/01/01/gpbridge00/gpio/.gitignore @@ -0,0 +1 @@ +!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/01/01/01/01/gpbridge00/i2c/.gitignore b/drivers/staging/greybus/Documentation/sysfs/endo/01/01/01/01/gpbridge00/i2c/.gitignore new file mode 100644 index 0000000..f935021 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/endo/01/01/01/01/gpbridge00/i2c/.gitignore @@ -0,0 +1 @@ +!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/01/01/01/01/gpbridge00/usb/.gitignore b/drivers/staging/greybus/Documentation/sysfs/endo/01/01/01/01/gpbridge00/usb/.gitignore new file mode 100644 index 0000000..f935021 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/endo/01/01/01/01/gpbridge00/usb/.gitignore @@ -0,0 +1 @@ +!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/01/01/firmware b/drivers/staging/greybus/Documentation/sysfs/endo/01/01/firmware new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/01/01/manifest b/drivers/staging/greybus/Documentation/sysfs/endo/01/01/manifest new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/01/01/product_id b/drivers/staging/greybus/Documentation/sysfs/endo/01/01/product_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/01/01/product_name b/drivers/staging/greybus/Documentation/sysfs/endo/01/01/product_name new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/01/01/state b/drivers/staging/greybus/Documentation/sysfs/endo/01/01/state new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/01/01/uid b/drivers/staging/greybus/Documentation/sysfs/endo/01/01/uid new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/01/01/version_major b/drivers/staging/greybus/Documentation/sysfs/endo/01/01/version_major new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/01/01/version_minor b/drivers/staging/greybus/Documentation/sysfs/endo/01/01/version_minor new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/01/epm b/drivers/staging/greybus/Documentation/sysfs/endo/01/epm new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/01/power b/drivers/staging/greybus/Documentation/sysfs/endo/01/power new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/01/present b/drivers/staging/greybus/Documentation/sysfs/endo/01/present new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/02/02/.gitignore b/drivers/staging/greybus/Documentation/sysfs/endo/02/02/.gitignore new file mode 100644 index 0000000..f935021 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/endo/02/02/.gitignore @@ -0,0 +1 @@ +!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/ap_intf_id b/drivers/staging/greybus/Documentation/sysfs/endo/ap_intf_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/id b/drivers/staging/greybus/Documentation/sysfs/endo/id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/svc/svc/firmware b/drivers/staging/greybus/Documentation/sysfs/endo/svc/svc/firmware new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/svc/svc/serial_number b/drivers/staging/greybus/Documentation/sysfs/endo/svc/svc/serial_number new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/svc/svc/version b/drivers/staging/greybus/Documentation/sysfs/endo/svc/svc/version new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c index aa89868..d71f328 100644 --- a/drivers/staging/greybus/endo.c +++ b/drivers/staging/greybus/endo.c @@ -438,6 +438,7 @@ static int gb_endo_register(struct greybus_host_device *hd, int retval; endo->dev.parent = hd->parent; + endo->dev.init_name = "endo"; endo->dev.bus = &greybus_bus_type; endo->dev.type = &greybus_endo_type; endo->dev.groups = endo_groups; @@ -450,7 +451,6 @@ static int gb_endo_register(struct greybus_host_device *hd, strcpy(&endo->svc_info.serial_number[0], "042"); strcpy(&endo->svc_info.version[0], "0.0"); - dev_set_name(&endo->dev, "endo-0x%04x", endo->id); retval = device_add(&endo->dev); if (retval) { dev_err(hd->parent, "failed to add endo device of id 0x%04x\n", -- cgit v0.10.2 From 4bf3780982bde534d931ae77a0a6d46335c488ab Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 28 May 2015 19:03:33 +0200 Subject: greybus: gpio: remove unused debounce define Remove unused debounce define from protocol header. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 32d8464..25c9a38 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -132,8 +132,6 @@ struct gb_i2c_transfer_response { #define GB_GPIO_TYPE_IRQ_UNMASK 0x0d #define GB_GPIO_TYPE_IRQ_EVENT 0x0e -#define GB_GPIO_DEBOUNCE_USEC_DEFAULT 0 /* microseconds */ - /* line count request has no payload */ struct gb_gpio_line_count_response { __u8 count; -- cgit v0.10.2 From 7ba864a19f97f06b0a685b083449b7278b635823 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 28 May 2015 19:03:34 +0200 Subject: greybus: gpio: add irq-type defines Add Greybus GPIO IRQ-type defines rather than rely on the current Linux implementation. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 8dad9e5..9590914 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -286,21 +286,33 @@ static int gb_gpio_irq_set_type(struct irq_data *d, unsigned int type) struct gpio_chip *chip = irq_data_to_gpio_chip(d); struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); struct gb_gpio_line *line = &ggc->lines[d->hwirq]; + u8 irq_type; switch (type) { case IRQ_TYPE_NONE: + irq_type = GB_GPIO_IRQ_TYPE_NONE; + break; case IRQ_TYPE_EDGE_RISING: + irq_type = GB_GPIO_IRQ_TYPE_EDGE_RISING; + break; case IRQ_TYPE_EDGE_FALLING: + irq_type = GB_GPIO_IRQ_TYPE_EDGE_FALLING; + break; case IRQ_TYPE_EDGE_BOTH: + irq_type = GB_GPIO_IRQ_TYPE_EDGE_BOTH; + break; case IRQ_TYPE_LEVEL_LOW: + irq_type = GB_GPIO_IRQ_TYPE_LEVEL_LOW; + break; case IRQ_TYPE_LEVEL_HIGH: + irq_type = GB_GPIO_IRQ_TYPE_LEVEL_HIGH; break; default: dev_err(chip->dev, "unsupported irq type: %u\n", type); return -EINVAL; } - line->irq_type = type; + line->irq_type = irq_type; line->irq_type_pending = true; return 0; diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 25c9a38..81f01d9 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -132,6 +132,13 @@ struct gb_i2c_transfer_response { #define GB_GPIO_TYPE_IRQ_UNMASK 0x0d #define GB_GPIO_TYPE_IRQ_EVENT 0x0e +#define GB_GPIO_IRQ_TYPE_NONE 0x00 +#define GB_GPIO_IRQ_TYPE_EDGE_RISING 0x01 +#define GB_GPIO_IRQ_TYPE_EDGE_FALLING 0x02 +#define GB_GPIO_IRQ_TYPE_EDGE_BOTH 0x03 +#define GB_GPIO_IRQ_TYPE_LEVEL_HIGH 0x04 +#define GB_GPIO_IRQ_TYPE_LEVEL_LOW 0x08 + /* line count request has no payload */ struct gb_gpio_line_count_response { __u8 count; -- cgit v0.10.2 From 3cb494cd6c5d3ca1c381553f5379ca9577f8e871 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 1 Jun 2015 17:43:36 +0530 Subject: greybus: endo: Add missing '\n' sprintf() for sysfs files Because of the missing '\n', this is how the output of reading endo sysfs files looks: root# cat /sys/bus/greybus/devices/endo/id 0x4755root# Fix it by including \n to the end of the printed string. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c index d71f328..4f9ae4b 100644 --- a/drivers/staging/greybus/endo.c +++ b/drivers/staging/greybus/endo.c @@ -49,7 +49,7 @@ static ssize_t serial_number_show(struct device *dev, { struct gb_endo *endo = to_gb_endo(dev); - return sprintf(buf, "%s", &endo->svc_info.serial_number[0]); + return sprintf(buf, "%s\n", &endo->svc_info.serial_number[0]); } static DEVICE_ATTR_RO(serial_number); @@ -58,7 +58,7 @@ static ssize_t version_show(struct device *dev, { struct gb_endo *endo = to_gb_endo(dev); - return sprintf(buf, "%s", &endo->svc_info.version[0]); + return sprintf(buf, "%s\n", &endo->svc_info.version[0]); } static DEVICE_ATTR_RO(version); @@ -78,7 +78,7 @@ static ssize_t id_show(struct device *dev, { struct gb_endo *endo = to_gb_endo(dev); - return sprintf(buf, "0x%04x", endo->id); + return sprintf(buf, "0x%04x\n", endo->id); } static DEVICE_ATTR_RO(id); @@ -87,7 +87,7 @@ static ssize_t ap_intf_id_show(struct device *dev, { struct gb_endo *endo = to_gb_endo(dev); - return sprintf(buf, "0x%02x", endo->ap_intf_id); + return sprintf(buf, "0x%02x\n", endo->ap_intf_id); } static DEVICE_ATTR_RO(ap_intf_id); -- cgit v0.10.2 From 55f2291142efa42acab362bf71b52e03bd275a42 Mon Sep 17 00:00:00 2001 From: Phong Tran Date: Mon, 1 Jun 2015 22:19:45 +0700 Subject: greybus: uart: Fix the memory leak in connection init If alloc minor is error, gb_tty should free. Signed-off-by: Phong Tran Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 47de969..590bc9f 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -618,9 +618,11 @@ static int gb_uart_connection_init(struct gb_connection *connection) if (minor == -ENOSPC) { dev_err(&connection->dev, "no more free minor numbers\n"); - return -ENODEV; + retval = -ENODEV; + goto error_version; } - return minor; + retval = minor; + goto error_version; } gb_tty->minor = minor; -- cgit v0.10.2 From 4ef53485c3d2d7a36c163c0409c8e3eb324a70d4 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 2 Jun 2015 13:40:44 +0100 Subject: greybus: uart: Move UART protocol structs/defines to greybus_protocols.h gbsim depends on the structures and defines in greybus_protocols.h generally in order to simulate firmware. Move UART defines into this header to facilitate. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 81f01d9..04f3b22 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -545,4 +545,73 @@ struct gb_svc_conn_destroy_request { }; /* connection destroy response has no payload */ +/* UART */ + +/* Version of the Greybus UART protocol we support */ +#define GB_UART_VERSION_MAJOR 0x00 +#define GB_UART_VERSION_MINOR 0x01 + +/* Greybus UART operation types */ +#define GB_UART_TYPE_INVALID 0x00 +#define GB_UART_TYPE_PROTOCOL_VERSION 0x01 +#define GB_UART_TYPE_SEND_DATA 0x02 +#define GB_UART_TYPE_RECEIVE_DATA 0x03 /* Unsolicited data */ +#define GB_UART_TYPE_SET_LINE_CODING 0x04 +#define GB_UART_TYPE_SET_CONTROL_LINE_STATE 0x05 +#define GB_UART_TYPE_SET_BREAK 0x06 +#define GB_UART_TYPE_SERIAL_STATE 0x07 /* Unsolicited data */ + +struct gb_uart_send_data_request { + __le16 size; + __u8 data[0]; +}; + +struct gb_serial_line_coding { + __le32 rate; + __u8 format; +#define GB_SERIAL_1_STOP_BITS 0 +#define GB_SERIAL_1_5_STOP_BITS 1 +#define GB_SERIAL_2_STOP_BITS 2 + + __u8 parity; +#define GB_SERIAL_NO_PARITY 0 +#define GB_SERIAL_ODD_PARITY 1 +#define GB_SERIAL_EVEN_PARITY 2 +#define GB_SERIAL_MARK_PARITY 3 +#define GB_SERIAL_SPACE_PARITY 4 + + __u8 data; +}; + +struct gb_uart_set_line_coding_request { + struct gb_serial_line_coding line_coding; +}; + +/* output control lines */ +#define GB_UART_CTRL_DTR 0x01 +#define GB_UART_CTRL_RTS 0x02 + +struct gb_uart_set_control_line_state_request { + __le16 control; +}; + +struct gb_uart_set_break_request { + __u8 state; +}; + +/* input control lines and line errors */ +#define GB_UART_CTRL_DCD 0x01 +#define GB_UART_CTRL_DSR 0x02 +#define GB_UART_CTRL_BRK 0x04 +#define GB_UART_CTRL_RI 0x08 + +#define GB_UART_CTRL_FRAMING 0x10 +#define GB_UART_CTRL_PARITY 0x20 +#define GB_UART_CTRL_OVERRUN 0x40 + +struct gb_uart_serial_state_request { + __u16 control; +}; + #endif /* __GREYBUS_PROTOCOLS_H */ + diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 590bc9f..a4c0127 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -33,72 +33,6 @@ #define GB_NUM_MINORS 255 /* 255 is enough for anyone... */ #define GB_NAME "ttyGB" -/* Version of the Greybus PWM protocol we support */ -#define GB_UART_VERSION_MAJOR 0x00 -#define GB_UART_VERSION_MINOR 0x01 - -/* Greybus UART operation types */ -#define GB_UART_TYPE_INVALID 0x00 -#define GB_UART_TYPE_PROTOCOL_VERSION 0x01 -#define GB_UART_TYPE_SEND_DATA 0x02 -#define GB_UART_TYPE_RECEIVE_DATA 0x03 /* Unsolicited data */ -#define GB_UART_TYPE_SET_LINE_CODING 0x04 -#define GB_UART_TYPE_SET_CONTROL_LINE_STATE 0x05 -#define GB_UART_TYPE_SET_BREAK 0x06 -#define GB_UART_TYPE_SERIAL_STATE 0x07 /* Unsolicited data */ - -struct gb_uart_send_data_request { - __le16 size; - __u8 data[0]; -}; - -struct gb_serial_line_coding { - __le32 rate; - __u8 format; -#define GB_SERIAL_1_STOP_BITS 0 -#define GB_SERIAL_1_5_STOP_BITS 1 -#define GB_SERIAL_2_STOP_BITS 2 - - __u8 parity; -#define GB_SERIAL_NO_PARITY 0 -#define GB_SERIAL_ODD_PARITY 1 -#define GB_SERIAL_EVEN_PARITY 2 -#define GB_SERIAL_MARK_PARITY 3 -#define GB_SERIAL_SPACE_PARITY 4 - - __u8 data; -}; - -struct gb_uart_set_line_coding_request { - struct gb_serial_line_coding line_coding; -}; - -/* output control lines */ -#define GB_UART_CTRL_DTR 0x01 -#define GB_UART_CTRL_RTS 0x02 - -struct gb_uart_set_control_line_state_request { - __le16 control; -}; - -struct gb_uart_set_break_request { - __u8 state; -}; - -/* input control lines and line errors */ -#define GB_UART_CTRL_DCD 0x01 -#define GB_UART_CTRL_DSR 0x02 -#define GB_UART_CTRL_BRK 0x04 -#define GB_UART_CTRL_RI 0x08 - -#define GB_UART_CTRL_FRAMING 0x10 -#define GB_UART_CTRL_PARITY 0x20 -#define GB_UART_CTRL_OVERRUN 0x40 - -struct gb_uart_serial_state_request { - __u16 control; -}; - struct gb_tty { struct tty_port port; struct gb_connection *connection; -- cgit v0.10.2 From 11fca140c92555f299808968061e81deb7c11821 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 2 Jun 2015 13:40:45 +0100 Subject: greybus: uart: Tidy naming convention to more closely match spec Update tabs and naming of structures to match the naming used in the greybus specification more closely. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 04f3b22..642f942 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -561,35 +561,38 @@ struct gb_svc_conn_destroy_request { #define GB_UART_TYPE_SET_BREAK 0x06 #define GB_UART_TYPE_SERIAL_STATE 0x07 /* Unsolicited data */ +/* Represents data from AP -> Module */ struct gb_uart_send_data_request { __le16 size; __u8 data[0]; }; -struct gb_serial_line_coding { +/* Represents data from Module -> AP */ +struct gb_uart_recv_data_request { + __le16 size; + __u8 data[0]; +}; + +struct gb_uart_set_line_coding_request { __le32 rate; __u8 format; -#define GB_SERIAL_1_STOP_BITS 0 -#define GB_SERIAL_1_5_STOP_BITS 1 -#define GB_SERIAL_2_STOP_BITS 2 +#define GB_SERIAL_1_STOP_BITS 0 +#define GB_SERIAL_1_5_STOP_BITS 1 +#define GB_SERIAL_2_STOP_BITS 2 __u8 parity; -#define GB_SERIAL_NO_PARITY 0 -#define GB_SERIAL_ODD_PARITY 1 -#define GB_SERIAL_EVEN_PARITY 2 -#define GB_SERIAL_MARK_PARITY 3 -#define GB_SERIAL_SPACE_PARITY 4 - - __u8 data; -}; +#define GB_SERIAL_NO_PARITY 0 +#define GB_SERIAL_ODD_PARITY 1 +#define GB_SERIAL_EVEN_PARITY 2 +#define GB_SERIAL_MARK_PARITY 3 +#define GB_SERIAL_SPACE_PARITY 4 -struct gb_uart_set_line_coding_request { - struct gb_serial_line_coding line_coding; + __u8 data_bits; }; /* output control lines */ -#define GB_UART_CTRL_DTR 0x01 -#define GB_UART_CTRL_RTS 0x02 +#define GB_UART_CTRL_DTR 0x01 +#define GB_UART_CTRL_RTS 0x02 struct gb_uart_set_control_line_state_request { __le16 control; @@ -600,14 +603,14 @@ struct gb_uart_set_break_request { }; /* input control lines and line errors */ -#define GB_UART_CTRL_DCD 0x01 -#define GB_UART_CTRL_DSR 0x02 -#define GB_UART_CTRL_BRK 0x04 -#define GB_UART_CTRL_RI 0x08 - -#define GB_UART_CTRL_FRAMING 0x10 -#define GB_UART_CTRL_PARITY 0x20 -#define GB_UART_CTRL_OVERRUN 0x40 +#define GB_UART_CTRL_DCD 0x01 +#define GB_UART_CTRL_DSR 0x02 +#define GB_UART_CTRL_BRK 0x04 +#define GB_UART_CTRL_RI 0x08 + +#define GB_UART_CTRL_FRAMING 0x10 +#define GB_UART_CTRL_PARITY 0x20 +#define GB_UART_CTRL_OVERRUN 0x40 struct gb_uart_serial_state_request { __u16 control; diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index a4c0127..673eec4 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -33,6 +33,13 @@ #define GB_NUM_MINORS 255 /* 255 is enough for anyone... */ #define GB_NAME "ttyGB" +struct gb_tty_line_coding { + __le32 rate; + __u8 format; + __u8 parity; + __u8 data_bits; +}; + struct gb_tty { struct tty_port port; struct gb_connection *connection; @@ -50,10 +57,9 @@ struct gb_tty { u8 version_minor; unsigned int ctrlin; /* input control lines */ unsigned int ctrlout; /* output control lines */ - struct gb_serial_line_coding line_coding; + struct gb_tty_line_coding line_coding; }; - static struct tty_driver *gb_tty_driver; static DEFINE_IDR(tty_minors); static DEFINE_MUTEX(table_lock); @@ -87,7 +93,7 @@ static int send_line_coding(struct gb_tty *tty) { struct gb_uart_set_line_coding_request request; - memcpy(&request.line_coding, &tty->line_coding, + memcpy(&request, &tty->line_coding, sizeof(tty->line_coding)); return gb_operation_sync(tty->connection, GB_UART_TYPE_SET_LINE_CODING, &request, sizeof(request), NULL, 0); @@ -245,7 +251,7 @@ static void gb_tty_set_termios(struct tty_struct *tty, { struct gb_tty *gb_tty = tty->driver_data; struct ktermios *termios = &tty->termios; - struct gb_serial_line_coding newline; + struct gb_tty_line_coding newline; int newctrl = gb_tty->ctrlout; newline.rate = cpu_to_le32(tty_get_baud_rate(tty)); @@ -256,17 +262,17 @@ static void gb_tty_set_termios(struct tty_struct *tty, switch (termios->c_cflag & CSIZE) { case CS5: - newline.data = 5; + newline.data_bits = 5; break; case CS6: - newline.data = 6; + newline.data_bits = 6; break; case CS7: - newline.data = 7; + newline.data_bits = 7; break; case CS8: default: - newline.data = 8; + newline.data_bits = 8; break; } @@ -571,7 +577,7 @@ static int gb_uart_connection_init(struct gb_connection *connection) gb_tty->line_coding.rate = cpu_to_le32(9600); gb_tty->line_coding.format = GB_SERIAL_1_STOP_BITS; gb_tty->line_coding.parity = GB_SERIAL_NO_PARITY; - gb_tty->line_coding.data = 8; + gb_tty->line_coding.data_bits = 8; send_line_coding(gb_tty); tty_dev = tty_port_register_device(&gb_tty->port, gb_tty_driver, minor, -- cgit v0.10.2 From f5537d46cb2e062ca4a67ac86168b2bff9895615 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 2 Jun 2015 13:40:46 +0100 Subject: greybus: uart: Reduce UART count from 255 to 16 Arbitrary number 255 is both not aligned and probably too big. Move the UART count down to 16 which is still large but, more realistic. 8 may be too few for future testing setups, 16 should accomodate any. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 673eec4..4cad629 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -30,7 +30,7 @@ #include "greybus.h" -#define GB_NUM_MINORS 255 /* 255 is enough for anyone... */ +#define GB_NUM_MINORS 16 /* 16 is is more than enough */ #define GB_NAME "ttyGB" struct gb_tty_line_coding { -- cgit v0.10.2 From f95ad78c72e72bcc922e75b80b35c6e9549b9d72 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 2 Jun 2015 13:40:47 +0100 Subject: greybus: uart: Update uart.c to register tty ports For each new UART connection we need to do a tty_port_init else we'll crash when trying to access the tty mutex later on. Base the TTY major/minor numbers on non-zero values. Supply an empty operations structure for the newly regitered port. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 4cad629..c47667d 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -522,6 +522,7 @@ static const struct tty_operations gb_ops = { .tiocmset = gb_tty_tiocmset, }; +static struct tty_port_operations null_ops = { }; static int gb_tty_init(void); static void gb_tty_exit(void); @@ -545,6 +546,7 @@ static int gb_uart_connection_init(struct gb_connection *connection) gb_tty = kzalloc(sizeof(*gb_tty), GFP_KERNEL); if (!gb_tty) return -ENOMEM; + gb_tty->connection = connection; connection->private = gb_tty; @@ -571,6 +573,9 @@ static int gb_uart_connection_init(struct gb_connection *connection) init_waitqueue_head(&gb_tty->wioctl); mutex_init(&gb_tty->mutex); + tty_port_init(&gb_tty->port); + gb_tty->port.ops = &null_ops; + send_control(gb_tty, gb_tty->ctrlout); /* initialize the uart to be 9600n81 */ @@ -589,6 +594,7 @@ static int gb_uart_connection_init(struct gb_connection *connection) return 0; error: + tty_port_destroy(&gb_tty->port); release_minor(gb_tty); error_version: connection->private = NULL; @@ -623,7 +629,7 @@ static void gb_uart_connection_exit(struct gb_connection *connection) /* FIXME - free transmit / receive buffers */ tty_port_put(&gb_tty->port); - + tty_port_destroy(&gb_tty->port); kfree(gb_tty); /* If last device is gone, tear down the tty structures */ -- cgit v0.10.2 From 563bd79b2ddd12dd9da89635dc218d6c706a4130 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 2 Jun 2015 13:40:48 +0100 Subject: greybus: uart: send_data should return size or error gb_operation_sync returns 0 on success but the calling function expects the number of bytes written on success or a negative errno Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index c47667d..928b83d 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -71,7 +71,7 @@ define_get_version(gb_tty, UART); static int send_data(struct gb_tty *tty, u16 size, const u8 *data) { struct gb_uart_send_data_request *request; - int retval; + int ret; if (!data || !size) return 0; @@ -82,11 +82,13 @@ static int send_data(struct gb_tty *tty, u16 size, const u8 *data) request->size = cpu_to_le16(size); memcpy(&request->data[0], data, size); - retval = gb_operation_sync(tty->connection, GB_UART_TYPE_SEND_DATA, - request, sizeof(*request) + size, NULL, 0); - + ret = gb_operation_sync(tty->connection, GB_UART_TYPE_SEND_DATA, + request, sizeof(*request) + size, NULL, 0); kfree(request); - return retval; + if (ret) + return ret; + else + return size; } static int send_line_coding(struct gb_tty *tty) -- cgit v0.10.2 From dd1c64ede97f163e5ab2fdebfe3f4095f4638120 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 2 Jun 2015 13:40:49 +0100 Subject: greybus: uart: kmalloc for send_data once only Make kmalloc for the send buffer a one time alloc based on the MTU for a given greybus link. The write_room for an gb_operation_sync then will be the size of the buffer we use for a single operation. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 928b83d..ed03ba4 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -42,6 +42,8 @@ struct gb_tty_line_coding { struct gb_tty { struct tty_port port; + void *buffer; + u32 buffer_payload_max; struct gb_connection *connection; u16 cport_id; unsigned int minor; @@ -76,15 +78,13 @@ static int send_data(struct gb_tty *tty, u16 size, const u8 *data) if (!data || !size) return 0; - request = kmalloc(sizeof(*request) + size, GFP_KERNEL); - if (!request) - return -ENOMEM; - + if (size > tty->buffer_payload_max) + size = tty->buffer_payload_max; + request = tty->buffer; request->size = cpu_to_le16(size); memcpy(&request->data[0], data, size); ret = gb_operation_sync(tty->connection, GB_UART_TYPE_SEND_DATA, request, sizeof(*request) + size, NULL, 0); - kfree(request); if (ret) return ret; else @@ -227,17 +227,13 @@ static int gb_tty_write(struct tty_struct *tty, const unsigned char *buf, static int gb_tty_write_room(struct tty_struct *tty) { -// struct gb_tty *gb_tty = tty->driver_data; + struct gb_tty *gb_tty = tty->driver_data; - // FIXME - how much do we want to say we have room for? - return 0; + return gb_tty->buffer_payload_max; } static int gb_tty_chars_in_buffer(struct tty_struct *tty) { -// struct gb_tty *gb_tty = tty->driver_data; - - // FIXME - how many left to send? return 0; } @@ -549,6 +545,19 @@ static int gb_uart_connection_init(struct gb_connection *connection) if (!gb_tty) return -ENOMEM; + gb_tty->buffer_payload_max = + gb_operation_get_payload_size_max(connection); + if (!gb_tty->buffer_payload_max) { + kfree(gb_tty); + return -EINVAL; + } + + gb_tty->buffer = kzalloc(gb_tty->buffer_payload_max, GFP_KERNEL); + if (!gb_tty->buffer) { + kfree(gb_tty); + return -ENOMEM; + } + gb_tty->connection = connection; connection->private = gb_tty; @@ -600,6 +609,7 @@ error: release_minor(gb_tty); error_version: connection->private = NULL; + kfree(gb_tty->buffer); kfree(gb_tty); return retval; } @@ -632,6 +642,7 @@ static void gb_uart_connection_exit(struct gb_connection *connection) tty_port_put(&gb_tty->port); tty_port_destroy(&gb_tty->port); + kfree(gb_tty->buffer); kfree(gb_tty); /* If last device is gone, tear down the tty structures */ -- cgit v0.10.2 From 1c087015b9ee80829a6e34e36715c668493eb607 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 2 Jun 2015 13:40:50 +0100 Subject: greybus: uart: Add gb_uart_request_recv for receiving async UART data gb_uart_request_recv job in life is to process unsolicited greybus mesages from the UART. Hook the incoming UART data and pass to the TTY layer. Line-state changes still TBD. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index ed03ba4..2d19d39 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -70,6 +70,47 @@ static atomic_t reference_count = ATOMIC_INIT(0); /* Define get_version() routine */ define_get_version(gb_tty, UART); +static int gb_uart_request_recv(u8 type, struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_tty *gb_tty = connection->private; + struct gb_message *request = op->request; + struct gb_uart_recv_data_request *receive_data; + struct gb_uart_serial_state_request *serial_state; + struct tty_port *port = &gb_tty->port; + int count; + int ret = 0; + + switch (type) { + case GB_UART_TYPE_RECEIVE_DATA: + receive_data = request->payload; + count = gb_tty->buffer_payload_max - sizeof(*receive_data); + if (!receive_data->size || receive_data->size > count) + return -EINVAL; + + count = tty_insert_flip_string(port, receive_data->data, + receive_data->size); + if (count != receive_data->size) { + dev_err(&connection->dev, + "UART: RX 0x%08x bytes only wrote 0x%08x\n", + receive_data->size, count); + } + if (count) + tty_flip_buffer_push(port); + break; + case GB_UART_TYPE_SERIAL_STATE: + serial_state = request->payload; + /* TODO: Parse state change and translate to tty API. */ + break; + default: + dev_err(&connection->dev, + "unsupported unsolicited request: %02x\n", type); + ret = -EINVAL; + } + + return ret; +} + static int send_data(struct gb_tty *tty, u16 size, const u8 *data) { struct gb_uart_send_data_request *request; @@ -703,7 +744,7 @@ static struct gb_protocol uart_protocol = { .minor = 1, .connection_init = gb_uart_connection_init, .connection_exit = gb_uart_connection_exit, - .request_recv = NULL, /* FIXME we have 2 types of requests!!! */ + .request_recv = gb_uart_request_recv, }; gb_gpbridge_protocol_driver(uart_protocol); -- cgit v0.10.2 From 62229a1bda8abdc54dabada79798885f4f2da79c Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 2 Jun 2015 13:40:51 +0100 Subject: greybus: uart: Remove magic numbers make struct gb_tty variable names consistent Use defines for the data format command. Tidy up naming of gb_tty variables. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 2d19d39..37bb2e2 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -142,28 +142,28 @@ static int send_line_coding(struct gb_tty *tty) &request, sizeof(request), NULL, 0); } -static int send_control(struct gb_tty *tty, u16 control) +static int send_control(struct gb_tty *gb_tty, u16 control) { struct gb_uart_set_control_line_state_request request; request.control = cpu_to_le16(control); - return gb_operation_sync(tty->connection, + return gb_operation_sync(gb_tty->connection, GB_UART_TYPE_SET_CONTROL_LINE_STATE, &request, sizeof(request), NULL, 0); } -static int send_break(struct gb_tty *tty, u8 state) +static int send_break(struct gb_tty *gb_tty, u8 state) { struct gb_uart_set_break_request request; if ((state != 0) && (state != 1)) { - dev_err(&tty->connection->dev, + dev_err(&gb_tty->connection->dev, "invalid break state of %d\n", state); return -EINVAL; } request.state = state; - return gb_operation_sync(tty->connection, GB_UART_TYPE_SET_BREAK, + return gb_operation_sync(gb_tty->connection, GB_UART_TYPE_SET_BREAK, &request, sizeof(request), NULL, 0); } @@ -294,7 +294,8 @@ static void gb_tty_set_termios(struct tty_struct *tty, int newctrl = gb_tty->ctrlout; newline.rate = cpu_to_le32(tty_get_baud_rate(tty)); - newline.format = termios->c_cflag & CSTOPB ? 2 : 0; + newline.format = termios->c_cflag & CSTOPB ? + GB_SERIAL_2_STOP_BITS : GB_SERIAL_1_STOP_BITS; newline.parity = termios->c_cflag & PARENB ? (termios->c_cflag & PARODD ? 1 : 2) + (termios->c_cflag & CMSPAR ? 2 : 0) : 0; -- cgit v0.10.2 From 4cfabf09dbcbd1ca44567542247925f02f71e656 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 4 Jun 2015 09:58:21 +0530 Subject: greybus: operation: Remove unused variable 'buffer' 'buffer' isn't used in this function, remove it. Reviewed-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 4f7a555..88b9f6a 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -221,9 +221,7 @@ static void gb_operation_message_init(struct greybus_host_device *hd, size_t payload_size, u8 type) { struct gb_operation_msg_hdr *header; - u8 *buffer; - buffer = message->buffer; header = message->buffer; message->header = header; -- cgit v0.10.2 From d7353ceadaf96a60b4163177ec9f8202655f1ace Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 4 Jun 2015 10:18:01 +0530 Subject: greybus: s/bundle_cport_id/intf_cport_id This isn't unique just for the bundle but the complete interface. Its wrong to call it bundle_cport_id. Lets name it intf_cport_id to make things clear. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio-pcm.c b/drivers/staging/greybus/audio-pcm.c index c1b6aa5..4d2f0ab 100644 --- a/drivers/staging/greybus/audio-pcm.c +++ b/drivers/staging/greybus/audio-pcm.c @@ -52,7 +52,7 @@ static void gb_pcm_work(struct work_struct *work) if (snd_dev->cport_active) { ret = gb_i2s_mgmt_deactivate_cport( snd_dev->mgmt_connection, - snd_dev->i2s_tx_connection->bundle_cport_id); + snd_dev->i2s_tx_connection->intf_cport_id); if (ret) /* XXX Do what else with failure? */ pr_err("deactivate_cport failed: %d\n", ret); @@ -62,7 +62,7 @@ static void gb_pcm_work(struct work_struct *work) return; } else if (!snd_dev->cport_active) { ret = gb_i2s_mgmt_activate_cport(snd_dev->mgmt_connection, - snd_dev->i2s_tx_connection->bundle_cport_id); + snd_dev->i2s_tx_connection->intf_cport_id); if (ret) pr_err("activate_cport failed: %d\n", ret); diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index e87521e..6f0d3e9 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -184,7 +184,7 @@ struct gb_connection *gb_connection_create(struct gb_bundle *bundle, } connection->bundle = bundle; - connection->bundle_cport_id = cport_id; + connection->intf_cport_id = cport_id; connection->state = GB_CONNECTION_STATE_DISABLED; connection->dev.parent = &bundle->dev; diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 8992b75..d39d476 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -25,7 +25,7 @@ struct gb_connection { struct gb_bundle *bundle; struct device dev; u16 hd_cport_id; - u16 bundle_cport_id; + u16 intf_cport_id; struct list_head hd_links; struct list_head bundle_links; -- cgit v0.10.2 From 4a0418700871936cddec3a2b3c5a029ec0b2d6a3 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Sun, 7 Jun 2015 09:13:15 +0530 Subject: greybus: Generate greybus wide unique ids for endo devices Currently we name the endo device as "endo". And it shows up with the same name in sysfs directory: /sys/bus/greybus/devices/. But each device in kernel should be represented by a unique id in kernel, and "endo" isn't unique. Lets generate unique ids for endo devices. The ida mechanism for allocating ids may be overkill but it works. Reviewed-by: Alex Elder Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 0a24822..9bbbf37 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -18,6 +18,8 @@ #include "greybus.h" +extern struct ida greybus_endo_id_map; + /* Allow greybus to be disabled at boot if needed */ static bool nogreybus; #ifdef MODULE @@ -263,6 +265,8 @@ static int __init gb_init(void) goto error_bus; } + ida_init(&greybus_endo_id_map); + retval = gb_ap_init(); if (retval) { pr_err("gb_ap_init failed\n"); diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c index 4f9ae4b..b89b14f 100644 --- a/drivers/staging/greybus/endo.c +++ b/drivers/staging/greybus/endo.c @@ -43,6 +43,8 @@ #define max_endo_interface_id(endo_layout) \ (4 + ((endo_layout)->max_ribs + 1) * 2) +struct ida greybus_endo_id_map; + /* endo sysfs attributes */ static ssize_t serial_number_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -432,18 +434,51 @@ static int create_modules(struct gb_endo *endo) return 0; } +/* + * Allocate an available Id to uniquely identify the endo device. The lowest + * available id is returned, so the first call is guaranteed to allocate endo Id + * 0. + * + * Assigns the endo's id and returns 0 if successful. + * Returns error otherwise. + */ +static int gb_endo_id_alloc(struct gb_endo *endo) +{ + int id; + + id = ida_simple_get(&greybus_endo_id_map, 0, 0, GFP_ATOMIC); + if (id < 0) + return id; + + endo->dev_id = (u16)id; + + return 0; +} + +/* + * Free a previously-allocated Endo Id. + */ +static void gb_endo_id_free(struct gb_endo *endo) +{ + ida_simple_remove(&greybus_endo_id_map, endo->dev_id); +} + static int gb_endo_register(struct greybus_host_device *hd, struct gb_endo *endo) { int retval; + retval = gb_endo_id_alloc(endo); + if (retval) + return retval; + endo->dev.parent = hd->parent; - endo->dev.init_name = "endo"; endo->dev.bus = &greybus_bus_type; endo->dev.type = &greybus_endo_type; endo->dev.groups = endo_groups; endo->dev.dma_mask = hd->parent->dma_mask; device_initialize(&endo->dev); + dev_set_name(&endo->dev, "endo%hu", endo->dev_id); // FIXME // Get the version and serial number from the SVC, right now we are @@ -456,6 +491,7 @@ static int gb_endo_register(struct greybus_host_device *hd, dev_err(hd->parent, "failed to add endo device of id 0x%04x\n", endo->id); put_device(&endo->dev); + gb_endo_id_free(endo); } return retval; @@ -511,6 +547,7 @@ void gb_endo_remove(struct gb_endo *endo) /* remove all modules for this endo */ gb_module_remove_all(endo); + gb_endo_id_free(endo); device_unregister(&endo->dev); } diff --git a/drivers/staging/greybus/endo.h b/drivers/staging/greybus/endo.h index e211fb7..2547b63 100644 --- a/drivers/staging/greybus/endo.h +++ b/drivers/staging/greybus/endo.h @@ -40,6 +40,7 @@ struct gb_endo { struct device dev; struct endo_layout layout; struct gb_svc_info svc_info; + u16 dev_id; u16 id; u8 ap_intf_id; }; -- cgit v0.10.2 From cf6b62d904f184fd13dbba56d77e9a8fbf98eda7 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Sun, 7 Jun 2015 09:13:16 +0530 Subject: greybus: Prefix module-id with endo id Prefix module-id with endo-id to uniquely identify it for the entire kernel. Reviewed-by: Alex Elder Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index 07b7e44..d770654 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -144,7 +144,7 @@ struct gb_module *gb_module_create(struct device *parent, u8 module_id) module->dev.groups = module_groups; module->dev.dma_mask = parent->dma_mask; device_initialize(&module->dev); - dev_set_name(&module->dev, "%d", module_id); + dev_set_name(&module->dev, "%s:%hhu", dev_name(parent), module_id); retval = device_add(&module->dev); if (retval) { -- cgit v0.10.2 From 0dac67c84c4d1e4d2ab510cbe7fafb9bac7002ea Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 8 Jun 2015 12:05:10 -0500 Subject: greybus: svc: driver is basic to Greybus (not GP Bridge) The SVC protocol driver should have been defined as a basic Greybus protocol driver, not a GP Bridge protocol driver. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 4dc10e3..f022838 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -245,4 +245,4 @@ static struct gb_protocol svc_protocol = { .request_recv = gb_svc_request_recv, }; -gb_gpbridge_protocol_driver(svc_protocol); +gb_protocol_driver(&svc_protocol); -- cgit v0.10.2 From 8bd0ae6e7295a06f8e64dcca1a91bb14ca6c07b0 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 8 Jun 2015 12:05:11 -0500 Subject: greybus: connection: make gb_connection_hd_find() private Give gb_connection_hd_find() static scope; it's never used outside "connection.c". Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 6f0d3e9..a774f67 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -14,8 +14,8 @@ static DEFINE_SPINLOCK(gb_connections_lock); -struct gb_connection *gb_connection_hd_find(struct greybus_host_device *hd, - u16 cport_id) +static struct gb_connection * +gb_connection_hd_find(struct greybus_host_device *hd, u16 cport_id) { struct gb_connection *connection = NULL; unsigned long flags; diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index d39d476..acf9183 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -51,9 +51,6 @@ void gb_connection_destroy(struct gb_connection *connection); int gb_connection_init(struct gb_connection *connection); void gb_connection_exit(struct gb_connection *connection); -struct gb_connection *gb_connection_hd_find(struct greybus_host_device *hd, - u16 cport_id); - void greybus_data_rcvd(struct greybus_host_device *hd, u16 cport_id, u8 *data, size_t length); -- cgit v0.10.2 From 81c3a77207450cb4187e8af700797e7d3209a568 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 8 Jun 2015 12:05:12 -0500 Subject: greybus: uart: properly interpret receive data size In gb_uart_request_recv(), the receive data size is in little-endian format. Do the proper byte swapping of that value before using it. Found by "make check". Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 37bb2e2..6db4993 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -78,6 +78,7 @@ static int gb_uart_request_recv(u8 type, struct gb_operation *op) struct gb_uart_recv_data_request *receive_data; struct gb_uart_serial_state_request *serial_state; struct tty_port *port = &gb_tty->port; + u16 recv_data_size; int count; int ret = 0; @@ -85,15 +86,16 @@ static int gb_uart_request_recv(u8 type, struct gb_operation *op) case GB_UART_TYPE_RECEIVE_DATA: receive_data = request->payload; count = gb_tty->buffer_payload_max - sizeof(*receive_data); - if (!receive_data->size || receive_data->size > count) + recv_data_size = le16_to_cpu(receive_data->size); + if (!recv_data_size || recv_data_size > count) return -EINVAL; count = tty_insert_flip_string(port, receive_data->data, - receive_data->size); - if (count != receive_data->size) { + recv_data_size); + if (count != recv_data_size) { dev_err(&connection->dev, "UART: RX 0x%08x bytes only wrote 0x%08x\n", - receive_data->size, count); + recv_data_size, count); } if (count) tty_flip_buffer_push(port); -- cgit v0.10.2 From fd1c2e541cbc48fe4a49e9fe1e98fd02af4bcf84 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 8 Jun 2015 12:05:13 -0500 Subject: greybus: core: rename greybus_deregister() Rename greybus_deregister() to be greybus_deregister_driver(), so its name mirrors the greybus_register_driver() function it matches. Define greybus_deregister() to be a trivial macro. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 9bbbf37..23e0359 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -155,11 +155,11 @@ int greybus_register_driver(struct greybus_driver *driver, struct module *owner, } EXPORT_SYMBOL_GPL(greybus_register_driver); -void greybus_deregister(struct greybus_driver *driver) +void greybus_deregister_driver(struct greybus_driver *driver) { driver_unregister(&driver->driver); } -EXPORT_SYMBOL_GPL(greybus_deregister); +EXPORT_SYMBOL_GPL(greybus_deregister_driver); static DEFINE_MUTEX(hd_mutex); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 86b2f9c..05eab4c 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -132,11 +132,13 @@ struct greybus_driver { /* Don't call these directly, use the module_greybus_driver() macro instead */ int greybus_register_driver(struct greybus_driver *driver, struct module *module, const char *mod_name); -void greybus_deregister(struct greybus_driver *driver); +void greybus_deregister_driver(struct greybus_driver *driver); /* define to get proper THIS_MODULE and KBUILD_MODNAME values */ #define greybus_register(driver) \ greybus_register_driver(driver, THIS_MODULE, KBUILD_MODNAME) +#define greybus_deregister(driver) \ + greybus_deregister_driver(driver) /** * module_greybus_driver() - Helper macro for registering a Greybus driver -- cgit v0.10.2 From d51c0ffb5cd1e92884e847f2cac6935c6d866779 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 8 Jun 2015 12:05:14 -0500 Subject: greybus: manifest: clean up a few pr_err() calls Provide a little more information in two pr_err() calls. Also enclose a reported condition in parentheses, to match the style used everywhere else in the file. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 597ba70..2022183 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -81,13 +81,14 @@ static int identify_descriptor(struct gb_interface *intf, size_t expected_size; if (size < sizeof(*desc_header)) { - pr_err("manifest too small\n"); + pr_err("manifest too small (%zu < %zu)\n", + size, sizeof(*desc_header)); return -EINVAL; /* Must at least have header */ } desc_size = le16_to_cpu(desc_header->size); if (desc_size > size) { - pr_err("descriptor too big\n"); + pr_err("descriptor too big (%zu > %zu)\n", desc_size, size); return -EINVAL; } @@ -374,7 +375,7 @@ bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size) header = &manifest->header; manifest_size = le16_to_cpu(header->size); if (manifest_size != size) { - pr_err("manifest size mismatch %zu != %hu\n", + pr_err("manifest size mismatch (%zu != %hu)\n", size, manifest_size); return false; } -- cgit v0.10.2 From 928f2abd5ff12fa4851b762df7c32e749e846b7c Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 4 Jun 2015 18:16:45 +0530 Subject: greybus: Tear down devices in the reverse order Normally, its a good practice to free resources in the reverse order in which they are allocated, so that all the dependencies can be sorted out properly. This is true while creating/destroying devices as well. For example consider this scenario (I faced a crash with control protocol due to this). For a new module, we will first create a bundle+connection for the control cport and then create other bundles/connections after parsing manifest. And while destroying interface on module hot unplug, we are removing the devices in the order they are added. And so the bundle/connection for the control cport are destroyed first. But, control cport was still required while destroying other bundles/connections. To solve this problem, lets destroy the resources in the reverse order in which they are added. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 2047e17..a6b1b34 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -196,7 +196,7 @@ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, } spin_lock_irq(&gb_bundles_lock); - list_add_tail(&bundle->links, &intf->bundles); + list_add(&bundle->links, &intf->bundles); spin_unlock_irq(&gb_bundles_lock); return bundle; diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index a774f67..5ab744b 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -213,8 +213,8 @@ struct gb_connection *gb_connection_create(struct gb_bundle *bundle, "protocol 0x%02hhx handler not found\n", protocol_id); spin_lock_irq(&gb_connections_lock); - list_add_tail(&connection->hd_links, &hd->connections); - list_add_tail(&connection->bundle_links, &bundle->connections); + list_add(&connection->hd_links, &hd->connections); + list_add(&connection->bundle_links, &bundle->connections); spin_unlock_irq(&gb_connections_lock); atomic_set(&connection->op_cycle, 0); diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 7a4c7dc..3483f848 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -122,7 +122,7 @@ static struct gb_interface *gb_interface_create(struct greybus_host_device *hd, } spin_lock_irq(&gb_interfaces_lock); - list_add_tail(&intf->links, &hd->interfaces); + list_add(&intf->links, &hd->interfaces); spin_unlock_irq(&gb_interfaces_lock); return intf; -- cgit v0.10.2 From f2e2b06fefe448de14cc009f865d879a8c334f4d Mon Sep 17 00:00:00 2001 From: Phong Tran Date: Tue, 9 Jun 2015 20:28:17 +0700 Subject: greybus: endo: move endo id map declaration to endo.h There is a sparse warning. The endo id map is also used in endo.c. Should define in endo.h Signed-off-by: Phong Tran Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 23e0359..a4d7057 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -18,8 +18,6 @@ #include "greybus.h" -extern struct ida greybus_endo_id_map; - /* Allow greybus to be disabled at boot if needed */ static bool nogreybus; #ifdef MODULE diff --git a/drivers/staging/greybus/endo.h b/drivers/staging/greybus/endo.h index 2547b63..63dbadf 100644 --- a/drivers/staging/greybus/endo.h +++ b/drivers/staging/greybus/endo.h @@ -46,6 +46,7 @@ struct gb_endo { }; #define to_gb_endo(d) container_of(d, struct gb_endo, dev) +extern struct ida greybus_endo_id_map; /* Greybus "private" definitions */ struct greybus_host_device; -- cgit v0.10.2 From 61b65a394cdbf5ed9117ad0da184a3f90a9b914a Mon Sep 17 00:00:00 2001 From: Phong Tran Date: Tue, 9 Jun 2015 20:28:18 +0700 Subject: greybus: uart: remove the redundant unregister chrdev The unregister_chrdev_region() does twice here. The chrdev region was unregistered inside tty_unregister_driver(). Signed-off-by: Phong Tran Reviewed-by: Alex Elder Reviewed-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 6db4993..7e94632a 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -732,12 +732,8 @@ fail_unregister_dev: static void gb_tty_exit(void) { - int major = MAJOR(gb_tty_driver->major); - int minor = gb_tty_driver->minor_start; - tty_unregister_driver(gb_tty_driver); put_tty_driver(gb_tty_driver); - unregister_chrdev_region(MKDEV(major, minor), GB_NUM_MINORS); } static struct gb_protocol uart_protocol = { -- cgit v0.10.2 From cce310367603f8a91be0078bb6ddef2fecaf64ad Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 9 Jun 2015 13:47:48 -0700 Subject: greybus: es?: decrease buffer size to 2k The firmware is having a hard time with 4k buffers and memory allocation, so decrease the size on the host side to 2k. Also move away from using PAGE_SIZE to denote 4k as that's not the case on all architectures, and someone, someday, might get a rude surprise. Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 2acfe74..45241c3 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -24,7 +24,7 @@ /* Memory sizes for the buffers sent to/from the ES1 controller */ #define ES1_SVC_MSG_SIZE (sizeof(struct svc_msg) + SZ_64K) -#define ES1_GBUF_MSG_SIZE_MAX PAGE_SIZE +#define ES1_GBUF_MSG_SIZE_MAX 2048 static const struct usb_device_id id_table[] = { /* Made up numbers for the SVC USB Bridge in ES1 */ diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 4f676cf..b5b395f 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -24,7 +24,7 @@ /* Memory sizes for the buffers sent to/from the ES1 controller */ #define ES1_SVC_MSG_SIZE (sizeof(struct svc_msg) + SZ_64K) -#define ES1_GBUF_MSG_SIZE_MAX PAGE_SIZE +#define ES1_GBUF_MSG_SIZE_MAX 2048 static const struct usb_device_id id_table[] = { /* Made up numbers for the SVC USB Bridge in ES2 */ -- cgit v0.10.2 From 45f427a02ecee25885542ad1e449b1ae72b85a53 Mon Sep 17 00:00:00 2001 From: Mark Greer Date: Tue, 9 Jun 2015 15:29:35 -0700 Subject: greybus: gb-audio: Reset sample count when CPort deactivated The sample count placed in Greybus I2S audio messages should be reset every time a new audio stream is set up. However, the current code does not do the reset so make it so it does. Signed-off-by: Mark Greer Acked-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio-pcm.c b/drivers/staging/greybus/audio-pcm.c index 4d2f0ab..fa5e85d 100644 --- a/drivers/staging/greybus/audio-pcm.c +++ b/drivers/staging/greybus/audio-pcm.c @@ -57,6 +57,7 @@ static void gb_pcm_work(struct work_struct *work) pr_err("deactivate_cport failed: %d\n", ret); snd_dev->cport_active = false; + snd_dev->send_data_sample_count = 0; } return; -- cgit v0.10.2 From 190241a362480e193e7b5f7a9fd9ff492c4acb31 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 9 Jun 2015 17:42:49 -0500 Subject: greybus: drop some unnecessary headers There's no need to include anything other than "greybus.h" in "connection.c". Same thing in "core.c" and "manifest.c" and "svc.c". Some files need headers included, but most come along with "greybus.h". Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 5ab744b..8f528c16 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -7,9 +7,6 @@ * Released under the GPLv2 only. */ -#include - -#include "kernel_ver.h" #include "greybus.h" static DEFINE_SPINLOCK(gb_connections_lock); diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index a4d7057..e7a280c 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -9,13 +9,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include -#include -#include -#include -#include -#include - #include "greybus.h" /* Allow greybus to be disabled at boot if needed */ diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 45241c3..56c80c6 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -6,16 +6,11 @@ * * Released under the GPLv2 only. */ -#include -#include #include -#include -#include #include #include #include #include -#include #include #include "greybus.h" diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index b5b395f..5257779 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -6,16 +6,11 @@ * * Released under the GPLv2 only. */ -#include -#include #include -#include -#include #include #include #include #include -#include #include #include "greybus.h" diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 2022183..f4fe4f3 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -9,8 +9,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include - #include "greybus.h" static const char *get_descriptor_type_string(u8 type) diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index f022838..ba85e81 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -7,12 +7,7 @@ * Released under the GPLv2 only. */ -#include -#include -#include - #include "greybus.h" -#include "greybus_protocols.h" struct gb_svc { struct gb_connection *connection; -- cgit v0.10.2 From 47ed2c92406f94ac0f122ebf0e05fc63d3f0c02a Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 9 Jun 2015 17:42:50 -0500 Subject: greybus: tag core init and exit functions The top-level functions gb_init() and gb_exit() are tagged with __init and __exit, respectively. These functions call a few other functions that are similarly used only at initialization and termination time. So mark those functions accordingly. Note that, because gb_ap_exit() and gb_debugfs_cleanup() are called by gb_init() in error paths, these functions cannot be declared with the __exit attribute. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 843ddc2..07375cc 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -354,7 +354,7 @@ int greybus_svc_in(struct greybus_host_device *hd, u8 *data, int size) } EXPORT_SYMBOL_GPL(greybus_svc_in); -int gb_ap_init(void) +int __init gb_ap_init(void) { ap_workqueue = alloc_ordered_workqueue("greybus_ap", 0); if (!ap_workqueue) diff --git a/drivers/staging/greybus/debugfs.c b/drivers/staging/greybus/debugfs.c index 59c5709..725565d 100644 --- a/drivers/staging/greybus/debugfs.c +++ b/drivers/staging/greybus/debugfs.c @@ -15,7 +15,7 @@ static struct dentry *gb_debug_root; -void gb_debugfs_init(void) +void __init gb_debugfs_init(void) { gb_debug_root = debugfs_create_dir("greybus", NULL); } diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 05eab4c..cf7c441 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -154,9 +154,9 @@ void greybus_deregister_driver(struct greybus_driver *driver); int greybus_disabled(void); int greybus_svc_in(struct greybus_host_device *hd, u8 *data, int length); -int gb_ap_init(void); +int gb_ap_init(void) __init; void gb_ap_exit(void); -void gb_debugfs_init(void); +void gb_debugfs_init(void) __init; void gb_debugfs_cleanup(void); struct dentry *gb_debugfs_get(void); diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 88b9f6a..49bc628 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -932,7 +932,7 @@ int gb_operation_sync(struct gb_connection *connection, int type, } EXPORT_SYMBOL_GPL(gb_operation_sync); -int gb_operation_init(void) +int __init gb_operation_init(void) { gb_message_cache = kmem_cache_create("gb_message_cache", sizeof(struct gb_message), 0, 0, NULL); @@ -959,7 +959,7 @@ err_destroy_message_cache: return -ENOMEM; } -void gb_operation_exit(void) +void __exit gb_operation_exit(void) { destroy_workqueue(gb_operation_workqueue); gb_operation_workqueue = NULL; diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 0199976..fcd6566 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -158,7 +158,7 @@ int gb_operation_sync(struct gb_connection *connection, int type, void *request, int request_size, void *response, int response_size); -int gb_operation_init(void); -void gb_operation_exit(void); +int gb_operation_init(void) __init; +void gb_operation_exit(void) __exit; #endif /* !__OPERATION_H */ -- cgit v0.10.2 From f35ab903ef6dad781a3de25ab37850499d2a39d4 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 9 Jun 2015 17:42:51 -0500 Subject: greybus: endo: define endo_init() and endo_exit() Define init and exit functions to do one-time setup and teardown of endo-related functionality. Currently they're place holders; the next patch will populate them. Note that we now call gb_operation_exit() from gb_init(), so we can no longer mark that function with __exit. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index e7a280c..8da120b 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -252,7 +252,7 @@ static int __init gb_init(void) retval = bus_register(&greybus_bus_type); if (retval) { - pr_err("bus_register failed\n"); + pr_err("bus_register failed (%d)\n", retval); goto error_bus; } @@ -260,18 +260,26 @@ static int __init gb_init(void) retval = gb_ap_init(); if (retval) { - pr_err("gb_ap_init failed\n"); + pr_err("gb_ap_init failed (%d)\n", retval); goto error_ap; } retval = gb_operation_init(); if (retval) { - pr_err("gb_operation_init failed\n"); + pr_err("gb_operation_init failed (%d)\n", retval); goto error_operation; } + retval = gb_endo_init(); + if (retval) { + pr_err("gb_endo_init failed (%d)\n", retval); + goto error_endo; + } + return 0; /* Success */ +error_endo: + gb_operation_exit(); error_operation: gb_ap_exit(); error_ap: @@ -285,12 +293,12 @@ module_init(gb_init); static void __exit gb_exit(void) { + gb_endo_exit(); gb_operation_exit(); gb_ap_exit(); bus_unregister(&greybus_bus_type); gb_debugfs_cleanup(); } module_exit(gb_exit); - MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Greg Kroah-Hartman "); diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c index b89b14f..37bd8ae 100644 --- a/drivers/staging/greybus/endo.c +++ b/drivers/staging/greybus/endo.c @@ -551,3 +551,11 @@ void gb_endo_remove(struct gb_endo *endo) device_unregister(&endo->dev); } +int __init gb_endo_init(void) +{ + return 0; +} + +void __exit gb_endo_exit(void) +{ +} diff --git a/drivers/staging/greybus/endo.h b/drivers/staging/greybus/endo.h index 63dbadf..0ff40e9 100644 --- a/drivers/staging/greybus/endo.h +++ b/drivers/staging/greybus/endo.h @@ -51,6 +51,9 @@ extern struct ida greybus_endo_id_map; /* Greybus "private" definitions */ struct greybus_host_device; +int gb_endo_init(void) __init; +void gb_endo_exit(void) __exit; + struct gb_endo *gb_endo_create(struct greybus_host_device *hd, u16 endo_id, u8 ap_intf_id); void gb_endo_remove(struct gb_endo *endo); diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 49bc628..a713daf 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -959,7 +959,7 @@ err_destroy_message_cache: return -ENOMEM; } -void __exit gb_operation_exit(void) +void gb_operation_exit(void) { destroy_workqueue(gb_operation_workqueue); gb_operation_workqueue = NULL; diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index fcd6566..6eed6bc 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -159,6 +159,6 @@ int gb_operation_sync(struct gb_connection *connection, int type, void *response, int response_size); int gb_operation_init(void) __init; -void gb_operation_exit(void) __exit; +void gb_operation_exit(void); #endif /* !__OPERATION_H */ -- cgit v0.10.2 From 79dda60987bc8df963c910bbcbfd9dc11bfada03 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 9 Jun 2015 17:42:52 -0500 Subject: greybus: endo: clean up id assignment code Recently code was added (back) to assign a unique id to each endo, so satisfy uniqueness requirements of the Linux device subsystem. An ID allocator is used to manage the space of IDs. Now that we have gb_endo_init(), we can initialize the map there, and fully hide the ID map within "endo.c". The original functions gb_endo_id_alloc() and gb_endo_id_free() provided a nice abstract interface, but the direct ID allocation calls are quite simple, so just call them directly. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 8da120b..18b5d5f 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -256,8 +256,6 @@ static int __init gb_init(void) goto error_bus; } - ida_init(&greybus_endo_id_map); - retval = gb_ap_init(); if (retval) { pr_err("gb_ap_init failed (%d)\n", retval); diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c index 37bd8ae..c778614 100644 --- a/drivers/staging/greybus/endo.c +++ b/drivers/staging/greybus/endo.c @@ -43,7 +43,7 @@ #define max_endo_interface_id(endo_layout) \ (4 + ((endo_layout)->max_ribs + 1) * 2) -struct ida greybus_endo_id_map; +static struct ida greybus_endo_id_map; /* endo sysfs attributes */ static ssize_t serial_number_show(struct device *dev, @@ -434,42 +434,13 @@ static int create_modules(struct gb_endo *endo) return 0; } -/* - * Allocate an available Id to uniquely identify the endo device. The lowest - * available id is returned, so the first call is guaranteed to allocate endo Id - * 0. - * - * Assigns the endo's id and returns 0 if successful. - * Returns error otherwise. - */ -static int gb_endo_id_alloc(struct gb_endo *endo) -{ - int id; - - id = ida_simple_get(&greybus_endo_id_map, 0, 0, GFP_ATOMIC); - if (id < 0) - return id; - - endo->dev_id = (u16)id; - - return 0; -} - -/* - * Free a previously-allocated Endo Id. - */ -static void gb_endo_id_free(struct gb_endo *endo) -{ - ida_simple_remove(&greybus_endo_id_map, endo->dev_id); -} - static int gb_endo_register(struct greybus_host_device *hd, struct gb_endo *endo) { int retval; - retval = gb_endo_id_alloc(endo); - if (retval) + retval = ida_simple_get(&greybus_endo_id_map, 0, 0, GFP_ATOMIC); + if (retval < 0) return retval; endo->dev.parent = hd->parent; @@ -491,7 +462,7 @@ static int gb_endo_register(struct greybus_host_device *hd, dev_err(hd->parent, "failed to add endo device of id 0x%04x\n", endo->id); put_device(&endo->dev); - gb_endo_id_free(endo); + ida_simple_remove(&greybus_endo_id_map, endo->dev_id); } return retval; @@ -547,12 +518,14 @@ void gb_endo_remove(struct gb_endo *endo) /* remove all modules for this endo */ gb_module_remove_all(endo); - gb_endo_id_free(endo); + ida_simple_remove(&greybus_endo_id_map, endo->dev_id); device_unregister(&endo->dev); } int __init gb_endo_init(void) { + ida_init(&greybus_endo_id_map); + return 0; } diff --git a/drivers/staging/greybus/endo.h b/drivers/staging/greybus/endo.h index 0ff40e9..d9f4976 100644 --- a/drivers/staging/greybus/endo.h +++ b/drivers/staging/greybus/endo.h @@ -46,8 +46,6 @@ struct gb_endo { }; #define to_gb_endo(d) container_of(d, struct gb_endo, dev) -extern struct ida greybus_endo_id_map; - /* Greybus "private" definitions */ struct greybus_host_device; -- cgit v0.10.2 From d393c98f11a8a3355387d52386c885bc89970176 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 9 Jun 2015 17:42:53 -0500 Subject: greybus: manifest: really minor cleanups This patch incorporates some very small cleanups to "manifest.c": - Rearrange code a bit in gb_manifest_parse() that ensures a manifest is big enough to hold a header. If the manifest is exactly the size of a header, the error reported will now be "...must have 1 interface..." rather than "short manifest". - Fix the function comment for gb_manifest_parse_cports(). - Use "an interface," not "a interface," and don't capitalize. - Delete some braces when getting interface product string. - A few other minor changes to comments and white space. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index f4fe4f3..b937dde 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -67,8 +67,8 @@ static void release_manifest_descriptors(struct gb_interface *intf) * we expect to see. (It could be bigger, perhaps for a new version * of the format.) * - * Returns the number of bytes consumed by the descriptor, or a - * negative errno. + * Returns the (non-zero) number of bytes consumed by the descriptor, + * or a negative errno. */ static int identify_descriptor(struct gb_interface *intf, struct greybus_descriptor *desc, size_t size) @@ -135,11 +135,11 @@ static int identify_descriptor(struct gb_interface *intf, return -ENOMEM; descriptor->size = desc_size; - descriptor->data = (u8 *)desc + sizeof(*desc_header); + descriptor->data = (char *)desc + sizeof(*desc_header); descriptor->type = desc_header->type; list_add_tail(&descriptor->links, &intf->manifest_descs); - /* desc_size is is positive and is known to fit in a signed int */ + /* desc_size is positive and is known to fit in a signed int */ return desc_size; } @@ -167,7 +167,6 @@ static char *gb_string_get(struct gb_interface *intf, u8 string_id) return NULL; list_for_each_entry(descriptor, &intf->manifest_descs, links) { - if (descriptor->type != GREYBUS_TYPE_STRING) continue; @@ -181,7 +180,7 @@ static char *gb_string_get(struct gb_interface *intf, u8 string_id) return ERR_PTR(-ENOENT); /* Allocate an extra byte so we can guarantee it's NUL-terminated */ - string = kmemdup(&desc_string->string, (size_t)desc_string->length + 1, + string = kmemdup(&desc_string->string, desc_string->length + 1, GFP_KERNEL); if (!string) return ERR_PTR(-ENOMEM); @@ -194,9 +193,10 @@ static char *gb_string_get(struct gb_interface *intf, u8 string_id) } /* - * Find cport descriptors in the manifest and set up data structures - * for the functions that use them. Returns the number of bundles - * set up for the given interface, or 0 if there is an error. + * Find cport descriptors in the manifest associated with the given + * bundle, and set up data structures for the functions that use + * them. Returns the number of cports set up for the bundle, or 0 + * if there is an error. */ static u32 gb_manifest_parse_cports(struct gb_interface *intf, struct gb_bundle *bundle) @@ -292,11 +292,9 @@ static bool gb_manifest_parse_interface(struct gb_interface *intf, if (IS_ERR(intf->vendor_string)) return false; - intf->product_string = gb_string_get(intf, - desc_intf->product_stringid); - if (IS_ERR(intf->product_string)) { + intf->product_string = gb_string_get(intf, desc_intf->product_stringid); + if (IS_ERR(intf->product_string)) goto out_free_vendor_string; - } // FIXME // Vendor, Product and Unique id must come via control protocol @@ -325,7 +323,7 @@ out_free_vendor_string: } /* - * Parse a buffer containing a Interface manifest. + * Parse a buffer containing an interface manifest. * * If we find anything wrong with the content/format of the buffer * we reject it. @@ -337,7 +335,7 @@ out_free_vendor_string: * the descriptors it contains, keeping track for each its type * and the location size of its data in the buffer. * - * Next we scan the descriptors, looking for a interface descriptor; + * Next we scan the descriptors, looking for an interface descriptor; * there must be exactly one of those. When found, we record the * information it contains, and then remove that descriptor (and any * string descriptors it refers to) from further consideration. @@ -363,8 +361,8 @@ bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size) return false; /* we have to have at _least_ the manifest header */ - if (size <= sizeof(manifest->header)) { - pr_err("short manifest (%zu)\n", size); + if (size < sizeof(*header)) { + pr_err("short manifest (%zu < %zu)\n", size, sizeof(*header)); return false; } -- cgit v0.10.2 From c46839d1cc418aad43c66344888cd266b689acf9 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 9 Jun 2015 17:42:54 -0500 Subject: greybus: manifest: use bundle's embedded interface pointer An initialized bundle structure contains a pointer to its interface. Because of this there's no need to provide the interface pointer to gb_manifest_parse_cports(). This also precludes the possibility of passing a bad interface pointer. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index b937dde..d20cd80 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -198,9 +198,9 @@ static char *gb_string_get(struct gb_interface *intf, u8 string_id) * them. Returns the number of cports set up for the bundle, or 0 * if there is an error. */ -static u32 gb_manifest_parse_cports(struct gb_interface *intf, - struct gb_bundle *bundle) +static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) { + struct gb_interface *intf = bundle->intf; u32 count = 0; while (true) { @@ -270,7 +270,7 @@ static u32 gb_manifest_parse_bundles(struct gb_interface *intf) return 0; /* Error */ /* Now go set up this bundle's functions and cports */ - if (!gb_manifest_parse_cports(intf, bundle)) + if (!gb_manifest_parse_cports(bundle)) return 0; /* Error parsing cports */ count++; -- cgit v0.10.2 From a6b13eb648fd3d03d45e722f81f26eed9bdecb87 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 9 Jun 2015 17:42:55 -0500 Subject: greybus: manifest: rework cport parsing Rework the the code that parses the manifest for CPorts associated with a bundle so it only touches each manifest descriptor once. (Previously the list was scanned from the beginning repeatedly until all bundle CPorts were found.) Shorten the name of the descriptor variable, to avoid line wrap. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index d20cd80..1b79161 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -201,27 +201,23 @@ static char *gb_string_get(struct gb_interface *intf, u8 string_id) static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) { struct gb_interface *intf = bundle->intf; + struct manifest_desc *desc; + struct manifest_desc *next; + u8 bundle_id = bundle->id; u32 count = 0; - while (true) { - struct manifest_desc *descriptor; + /* Set up all cport descriptors associated with this bundle */ + list_for_each_entry_safe(desc, next, &intf->manifest_descs, links) { struct greybus_descriptor_cport *desc_cport; u8 protocol_id; u16 cport_id; - bool found = false; - /* Find a cport descriptor */ - list_for_each_entry(descriptor, &intf->manifest_descs, links) { - if (descriptor->type == GREYBUS_TYPE_CPORT) { - desc_cport = descriptor->data; - if (desc_cport->bundle == bundle->id) { - found = true; - break; - } - } - } - if (!found) - break; + if (desc->type != GREYBUS_TYPE_CPORT) + continue; + + desc_cport = desc->data; + if (desc_cport->bundle != bundle_id) + continue; /* Found one. Set up its function structure */ protocol_id = desc_cport->protocol_id; @@ -230,8 +226,9 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) return 0; /* Error */ count++; + /* Release the cport descriptor */ - release_manifest_descriptor(descriptor); + release_manifest_descriptor(desc); } return count; -- cgit v0.10.2 From c27a253fc0481b46759082c72d196777ea459a6e Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 9 Jun 2015 17:42:56 -0500 Subject: greybus: manifest: rework bundle parsing Rework the the code that parses the manifest for bundles so it only touches each manifest descriptor once. (Previously the list was scanned from the beginning repeatedly until all bundles were found.) Shorten the name of the descriptor variable, to avoid line wrap. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 1b79161..9881b7a 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -241,26 +241,19 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) */ static u32 gb_manifest_parse_bundles(struct gb_interface *intf) { + struct manifest_desc *desc; + struct manifest_desc *next; u32 count = 0; - while (true) { - struct manifest_desc *descriptor; + list_for_each_entry_safe(desc, next, &intf->manifest_descs, links) { struct greybus_descriptor_bundle *desc_bundle; struct gb_bundle *bundle; - bool found = false; - - /* Find an bundle descriptor */ - list_for_each_entry(descriptor, &intf->manifest_descs, links) { - if (descriptor->type == GREYBUS_TYPE_BUNDLE) { - found = true; - break; - } - } - if (!found) - break; + + if (desc->type != GREYBUS_TYPE_BUNDLE) + continue; /* Found one. Set up its bundle structure*/ - desc_bundle = descriptor->data; + desc_bundle = desc->data; bundle = gb_bundle_create(intf, desc_bundle->id, desc_bundle->class); if (!bundle) @@ -273,7 +266,7 @@ static u32 gb_manifest_parse_bundles(struct gb_interface *intf) count++; /* Done with this bundle descriptor */ - release_manifest_descriptor(descriptor); + release_manifest_descriptor(desc); } return count; -- cgit v0.10.2 From 8267616b3ef73b22c9ed5b87905c13fc332fe507 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 9 Jun 2015 17:42:57 -0500 Subject: greybus: bundle: check for duplicate bundle ids Check at bundle creation time to ensure we're not creating a bundle with an id that's the same as one that's already been created. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index a6b1b34..6e9d03a 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -165,6 +165,16 @@ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, struct gb_bundle *bundle; int retval; + /* + * Reject any attempt to reuse a bundle id. We initialize + * these serially, so there's no need to worry about keeping + * the interface bundle list locked here. + */ + if (gb_bundle_find(intf, bundle_id)) { + pr_err("duplicate bundle id 0x%02hhx\n", bundle_id); + return NULL; + } + bundle = kzalloc(sizeof(*bundle), GFP_KERNEL); if (!bundle) return NULL; -- cgit v0.10.2 From f5c2be9e9bd934973d3e51b933bf7c03f85d2010 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 9 Jun 2015 17:42:58 -0500 Subject: greybus: connection: check for duplicate cport ids Check at connection creation time for an attempt to create a connection with an interface CPort ID that's the same as one that's already been created. Define a new helper function to look for such a duplicate. The check for a duplicate is only performed at initialization time, and CPorts are initialized serially for each bundle, so there's no need to acquire the list lock for this search. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 8f528c16..ab6c60e 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -11,10 +11,22 @@ static DEFINE_SPINLOCK(gb_connections_lock); +/* This is only used at initialization time; no locking is required. */ +static struct gb_connection * +gb_connection_intf_find(struct greybus_host_device *hd, u16 cport_id) +{ + struct gb_connection *connection; + + list_for_each_entry(connection, &hd->connections, hd_links) + if (connection->intf_cport_id == cport_id) + return connection; + return NULL; +} + static struct gb_connection * gb_connection_hd_find(struct greybus_host_device *hd, u16 cport_id) { - struct gb_connection *connection = NULL; + struct gb_connection *connection; unsigned long flags; spin_lock_irqsave(&gb_connections_lock, flags); @@ -22,7 +34,7 @@ gb_connection_hd_find(struct greybus_host_device *hd, u16 cport_id) if (connection->hd_cport_id == cport_id) goto found; connection = NULL; - found: +found: spin_unlock_irqrestore(&gb_connections_lock, flags); return connection; @@ -159,21 +171,29 @@ struct gb_connection *gb_connection_create(struct gb_bundle *bundle, u16 cport_id, u8 protocol_id) { struct gb_connection *connection; - struct greybus_host_device *hd; + struct greybus_host_device *hd = bundle->intf->hd; int retval; u8 major = 0; u8 minor = 1; + /* + * If a manifest tries to reuse a cport, reject it. We + * initialize connections serially so we don't need to worry + * about holding the connection lock. + */ + if (gb_connection_intf_find(hd, cport_id)) { + pr_err("duplicate interface cport id 0x%04hx\n", cport_id); + return NULL; + } + connection = kzalloc(sizeof(*connection), GFP_KERNEL); if (!connection) return NULL; + connection->hd = hd; connection->protocol_id = protocol_id; connection->major = major; connection->minor = minor; - - hd = bundle->intf->hd; - connection->hd = hd; if (!gb_connection_hd_cport_id_alloc(connection)) { gb_protocol_put(connection->protocol); kfree(connection); -- cgit v0.10.2 From 0ffacf3b8ae169a26c941345b7fa54e1624f6b95 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 11 Jun 2015 16:39:42 +0530 Subject: greybus: endo: Fix compilation warning WARNING: /home/viresh/work/repos/ara/greybus/greybus.o(.init.text+0xb8): Section mismatch in reference from the function init_module() to the function .exit.text:gb_endo_exit() The function __init init_module() references a function __exit gb_endo_exit(). Fix it by removing __exit from endo_exit(). Fixes: cf64356c5151 ("endo: define endo_init() and endo_exit()") Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c index c778614..baa4aa5 100644 --- a/drivers/staging/greybus/endo.c +++ b/drivers/staging/greybus/endo.c @@ -529,6 +529,6 @@ int __init gb_endo_init(void) return 0; } -void __exit gb_endo_exit(void) +void gb_endo_exit(void) { } diff --git a/drivers/staging/greybus/endo.h b/drivers/staging/greybus/endo.h index d9f4976..ad5728c 100644 --- a/drivers/staging/greybus/endo.h +++ b/drivers/staging/greybus/endo.h @@ -50,7 +50,7 @@ struct gb_endo { struct greybus_host_device; int gb_endo_init(void) __init; -void gb_endo_exit(void) __exit; +void gb_endo_exit(void); struct gb_endo *gb_endo_create(struct greybus_host_device *hd, u16 endo_id, u8 ap_intf_id); -- cgit v0.10.2 From 3d0421e0ab5315051b949ea70dee37c15e860706 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 11 Jun 2015 09:22:51 -0700 Subject: greybus: remove __init from .h files __init does not belong in a .h file, as it does not do anything there, so remove all instances of it. Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/endo.h b/drivers/staging/greybus/endo.h index ad5728c..3622428 100644 --- a/drivers/staging/greybus/endo.h +++ b/drivers/staging/greybus/endo.h @@ -49,7 +49,7 @@ struct gb_endo { /* Greybus "private" definitions */ struct greybus_host_device; -int gb_endo_init(void) __init; +int gb_endo_init(void); void gb_endo_exit(void); struct gb_endo *gb_endo_create(struct greybus_host_device *hd, diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index cf7c441..05eab4c 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -154,9 +154,9 @@ void greybus_deregister_driver(struct greybus_driver *driver); int greybus_disabled(void); int greybus_svc_in(struct greybus_host_device *hd, u8 *data, int length); -int gb_ap_init(void) __init; +int gb_ap_init(void); void gb_ap_exit(void); -void gb_debugfs_init(void) __init; +void gb_debugfs_init(void); void gb_debugfs_cleanup(void); struct dentry *gb_debugfs_get(void); diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 6eed6bc..0199976 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -158,7 +158,7 @@ int gb_operation_sync(struct gb_connection *connection, int type, void *request, int request_size, void *response, int response_size); -int gb_operation_init(void) __init; +int gb_operation_init(void); void gb_operation_exit(void); #endif /* !__OPERATION_H */ -- cgit v0.10.2 From 55a8e3550364a35bc5d40fa0e445049a5df62627 Mon Sep 17 00:00:00 2001 From: Phong Tran Date: Wed, 10 Jun 2015 21:03:17 +0700 Subject: greybus: uart: fix the clean up while uart initiates connection unsucessfully There is lack of unregister and free the tty driver. This patch fixes it. Signed-off-by: Phong Tran Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 7e94632a..2092870 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -586,20 +586,22 @@ static int gb_uart_connection_init(struct gb_connection *connection) } gb_tty = kzalloc(sizeof(*gb_tty), GFP_KERNEL); - if (!gb_tty) - return -ENOMEM; + if (!gb_tty) { + retval = -ENOMEM; + goto error_alloc; + } gb_tty->buffer_payload_max = gb_operation_get_payload_size_max(connection); if (!gb_tty->buffer_payload_max) { - kfree(gb_tty); - return -EINVAL; + retval = -EINVAL; + goto error_payload; } gb_tty->buffer = kzalloc(gb_tty->buffer_payload_max, GFP_KERNEL); if (!gb_tty->buffer) { - kfree(gb_tty); - return -ENOMEM; + retval = -ENOMEM; + goto error_payload; } gb_tty->connection = connection; @@ -654,7 +656,11 @@ error: error_version: connection->private = NULL; kfree(gb_tty->buffer); +error_payload: kfree(gb_tty); +error_alloc: + if (atomic_dec_return(&reference_count) == 0) + gb_tty_exit(); return retval; } -- cgit v0.10.2 From 856618f3fb6506f277adf060717590d03d3fb559 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 12 Jun 2015 10:21:06 -0500 Subject: greybus: connection: remove extra kfree() call When an error occurs in the device_add() call for a connection, the device reference is dropped as required. Because that's the device's only reference, that will also lead to gb_connection_release() being called, which frees the connection structure. Right now we're then making an extra request to free the connection, which is wrong. Fix that. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index ab6c60e..bf5fa10 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -219,7 +219,7 @@ struct gb_connection *gb_connection_create(struct gb_bundle *bundle, gb_connection_hd_cport_id_free(connection); gb_protocol_put(connection->protocol); put_device(&connection->dev); - kfree(connection); + return NULL; } -- cgit v0.10.2 From deb58ca8299598f81123dd92456c0cc3a9a38555 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 12 Jun 2015 10:21:07 -0500 Subject: greybus: connection: drop unneeded gb_protocol_put() calls Although a connection records its protocol id when it gets created, its protocol handler doesn't actually get assigned until gb_connection_bind_protocol() is called. In gb_connection_create() there are some error paths in which a reference to the connection's protocol is released before the protocol handler has been associated with the connection. Get rid of those calls. As a result, we will never pass a null protocol pointer to gb_protocol_put(). Add a precautionary warning in that function in the event that ever occurs. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index bf5fa10..abd7411 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -195,7 +195,6 @@ struct gb_connection *gb_connection_create(struct gb_bundle *bundle, connection->major = major; connection->minor = minor; if (!gb_connection_hd_cport_id_alloc(connection)) { - gb_protocol_put(connection->protocol); kfree(connection); return NULL; } @@ -217,7 +216,6 @@ struct gb_connection *gb_connection_create(struct gb_bundle *bundle, pr_err("failed to add connection device for cport 0x%04hx\n", cport_id); gb_connection_hd_cport_id_free(connection); - gb_protocol_put(connection->protocol); put_device(&connection->dev); return NULL; @@ -264,6 +262,7 @@ void gb_connection_destroy(struct gb_connection *connection) gb_connection_hd_cport_id_free(connection); gb_protocol_put(connection->protocol); + connection->protocol = NULL; device_unregister(&connection->dev); } diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index eed77c3..6aebbbd 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -196,7 +196,7 @@ void gb_protocol_put(struct gb_protocol *protocol) u8 minor; u8 protocol_count; - if (!protocol) + if (WARN_ON(!protocol)) return; id = protocol->id; -- cgit v0.10.2 From f9b0366f16c3926e92e7d108fe8666fac671d026 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 12 Jun 2015 10:21:08 -0500 Subject: greybus: connection: un-abstract host cport id allocation I did this recently for the endo id allocation code. It's clearer now that the allocation of a CPort ID to use for the AP side of a connection is not very complicated, and it happens in a pretty controlled environment. The functions that abstract getting and releasing those ids don't really add that much value. This patch removes gb_connection_hd_cport_id_alloc() and gb_connection_hd_cport_id_free(), and just open-codes their activity in the few places they are called. It is obvious now that the CPort ID allocation isn't done in atomic context, so we can change the ida_simple_get() call to use GFP_KERNEL. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index abd7411..7236e47 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -59,39 +59,6 @@ void greybus_data_rcvd(struct greybus_host_device *hd, u16 cport_id, } EXPORT_SYMBOL_GPL(greybus_data_rcvd); -/* - * Allocate an available CPort Id for use for the host side of the - * given connection. The lowest-available id is returned, so the - * first call is guaranteed to allocate CPort Id 0. - * - * Assigns the connection's hd_cport_id and returns true if successful. - * Returns false otherwise. - */ -static bool gb_connection_hd_cport_id_alloc(struct gb_connection *connection) -{ - struct ida *ida = &connection->hd->cport_id_map; - int id; - - id = ida_simple_get(ida, 0, HOST_DEV_CPORT_ID_MAX, GFP_ATOMIC); - if (id < 0) - return false; - - connection->hd_cport_id = (u16)id; - - return true; -} - -/* - * Free a previously-allocated CPort Id on the given host device. - */ -static void gb_connection_hd_cport_id_free(struct gb_connection *connection) -{ - struct ida *ida = &connection->hd->cport_id_map; - - ida_simple_remove(ida, connection->hd_cport_id); - connection->hd_cport_id = CPORT_ID_BAD; -} - static ssize_t state_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -172,6 +139,7 @@ struct gb_connection *gb_connection_create(struct gb_bundle *bundle, { struct gb_connection *connection; struct greybus_host_device *hd = bundle->intf->hd; + struct ida *id_map = &hd->cport_id_map; int retval; u8 major = 0; u8 minor = 1; @@ -190,17 +158,20 @@ struct gb_connection *gb_connection_create(struct gb_bundle *bundle, if (!connection) return NULL; + retval = ida_simple_get(id_map, 0, HOST_DEV_CPORT_ID_MAX, GFP_KERNEL); + if (retval < 0) { + kfree(connection); + return NULL; + } + connection->hd_cport_id = (u16)retval; + connection->intf_cport_id = cport_id; connection->hd = hd; + connection->protocol_id = protocol_id; connection->major = major; connection->minor = minor; - if (!gb_connection_hd_cport_id_alloc(connection)) { - kfree(connection); - return NULL; - } connection->bundle = bundle; - connection->intf_cport_id = cport_id; connection->state = GB_CONNECTION_STATE_DISABLED; connection->dev.parent = &bundle->dev; @@ -213,10 +184,14 @@ struct gb_connection *gb_connection_create(struct gb_bundle *bundle, retval = device_add(&connection->dev); if (retval) { + struct ida *id_map = &connection->hd->cport_id_map; + + ida_simple_remove(id_map, connection->hd_cport_id); + connection->hd_cport_id = CPORT_ID_BAD; + put_device(&connection->dev); + pr_err("failed to add connection device for cport 0x%04hx\n", cport_id); - gb_connection_hd_cport_id_free(connection); - put_device(&connection->dev); return NULL; } @@ -245,6 +220,7 @@ void gb_connection_destroy(struct gb_connection *connection) { struct gb_operation *operation; struct gb_operation *next; + struct ida *id_map; if (WARN_ON(!connection)) return; @@ -260,10 +236,13 @@ void gb_connection_destroy(struct gb_connection *connection) list_del(&connection->hd_links); spin_unlock_irq(&gb_connections_lock); - gb_connection_hd_cport_id_free(connection); gb_protocol_put(connection->protocol); connection->protocol = NULL; + id_map = &connection->hd->cport_id_map; + ida_simple_remove(id_map, connection->hd_cport_id); + connection->hd_cport_id = CPORT_ID_BAD; + device_unregister(&connection->dev); } -- cgit v0.10.2 From 52e8ce317fe51dea86777b164b63e41e50f8a7bf Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 12 Jun 2015 10:21:09 -0500 Subject: greybus: manifest: clean up properly when parsing cports Currently, if an error occurs creating a connection, we simply return an error without cleaning up any of the connections that had already been successfully set up. Add code to destroy connections that have been created in the event an error occurs. Add a check to ensure the bundle's list of connections was empty before parsing for CPorts begins. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 9881b7a..0b509cd 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -201,11 +201,16 @@ static char *gb_string_get(struct gb_interface *intf, u8 string_id) static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) { struct gb_interface *intf = bundle->intf; + struct gb_connection *connection; + struct gb_connection *connection_next; struct manifest_desc *desc; struct manifest_desc *next; u8 bundle_id = bundle->id; u32 count = 0; + if (WARN_ON(!list_empty(&bundle->connections))) + return 0; + /* Set up all cport descriptors associated with this bundle */ list_for_each_entry_safe(desc, next, &intf->manifest_descs, links) { struct greybus_descriptor_cport *desc_cport; @@ -223,7 +228,7 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) protocol_id = desc_cport->protocol_id; cport_id = le16_to_cpu(desc_cport->id); if (!gb_connection_create(bundle, cport_id, protocol_id)) - return 0; /* Error */ + goto cleanup; count++; @@ -232,6 +237,14 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) } return count; +cleanup: + /* An error occurred; undo any changes we've made */ + list_for_each_entry_safe(connection, connection_next, + &bundle->connections, bundle_links) { + gb_connection_destroy(connection); + count--; + } + return 0; /* Error; count should also be 0 */ } /* -- cgit v0.10.2 From bc942083585da78a5287089023aebcc8952c21f4 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 12 Jun 2015 10:21:10 -0500 Subject: greybus: bundle: refactor gb_bundle_find() Rearrange gb_bundle_find() so it follows the pattern used by gb_connection_find(). Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 6e9d03a..89568b2 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -283,13 +283,13 @@ struct gb_bundle *gb_bundle_find(struct gb_interface *intf, u8 bundle_id) spin_lock_irq(&gb_bundles_lock); list_for_each_entry(bundle, &intf->bundles, links) - if (bundle->id == bundle_id) { - spin_unlock_irq(&gb_bundles_lock); - return bundle; - } + if (bundle->id == bundle_id) + goto found; + bundle = NULL; +found: spin_unlock_irq(&gb_bundles_lock); - return NULL; + return bundle; } static int gb_bundle_connections_init(struct gb_bundle *bundle) -- cgit v0.10.2 From fe53b45ca8143e7f1073ff31d7c4cfb4e92dc824 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 12 Jun 2015 10:21:11 -0500 Subject: greybus: bundle: fix gb_bundle_destroy() Currently gb_bundle_destroy() takes an interface as an argument, and really doesn't do what a function by that name should do. What it now does is delete all bundles associated with a given interface. What it should do is destroy a single bundle. Move the looping logic out of gb_bundle_destroy() and into its caller, gb_interface_destroy(). Pass each bundle in an interface to gb_bundle_destroy(), which will do what's required to destroy a single bundle (including removing it from its interface's bundle list under protection of the lock). Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 89568b2..8d0e86f 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -215,24 +215,14 @@ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, /* * Tear down a previously set up bundle. */ -void gb_bundle_destroy(struct gb_interface *intf) +void gb_bundle_destroy(struct gb_bundle *bundle) { - LIST_HEAD(list); - struct gb_bundle *bundle; - struct gb_bundle *temp; - - if (WARN_ON(!intf)) - return; - spin_lock_irq(&gb_bundles_lock); - list_splice_init(&intf->bundles, &list); + list_del(&bundle->links); spin_unlock_irq(&gb_bundles_lock); - list_for_each_entry_safe(bundle, temp, &list, links) { - list_del(&bundle->links); - gb_bundle_connections_exit(bundle); - device_unregister(&bundle->dev); - } + gb_bundle_connections_exit(bundle); + device_unregister(&bundle->dev); } int gb_bundle_init(struct gb_bundle *bundle, u8 device_id) diff --git a/drivers/staging/greybus/bundle.h b/drivers/staging/greybus/bundle.h index 5c12c72..887883d 100644 --- a/drivers/staging/greybus/bundle.h +++ b/drivers/staging/greybus/bundle.h @@ -31,7 +31,7 @@ struct gb_bundle { /* Greybus "private" definitions" */ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, u8 class); -void gb_bundle_destroy(struct gb_interface *intf); +void gb_bundle_destroy(struct gb_bundle *bundle); int gb_bundle_init(struct gb_bundle *bundle, u8 device_id); int gb_bundles_init(struct gb_interface *intf, u8 device_id); diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 3483f848..5b1621c 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -141,6 +141,8 @@ put_module: static void gb_interface_destroy(struct gb_interface *intf) { struct gb_module *module; + struct gb_bundle *bundle; + struct gb_bundle *next; if (WARN_ON(!intf)) return; @@ -149,11 +151,11 @@ static void gb_interface_destroy(struct gb_interface *intf) list_del(&intf->links); spin_unlock_irq(&gb_interfaces_lock); - gb_bundle_destroy(intf); + list_for_each_entry_safe(bundle, next, &intf->bundles, links) + gb_bundle_destroy(bundle); kfree(intf->product_string); kfree(intf->vendor_string); - /* kref_put(module->hd); */ module = intf->module; device_unregister(&intf->dev); -- cgit v0.10.2 From 2a64fb0e1e13eee53e56805d8a1f0ff7bbf57306 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 12 Jun 2015 10:21:12 -0500 Subject: greybus: manifest: clean up properly when parsing bundles Currently, if an error occurs creating a bundle, we simply return an error without cleaning up any of the bundles that had already been successfully set up. Add code to destroy bundles that have been created in the event an error occurs. Add a check to ensure the interface's list of bundles was empty before parsing for bundles begins. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 0b509cd..e329f37 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -256,11 +256,15 @@ static u32 gb_manifest_parse_bundles(struct gb_interface *intf) { struct manifest_desc *desc; struct manifest_desc *next; + struct gb_bundle *bundle; + struct gb_bundle *bundle_next; u32 count = 0; + if (WARN_ON(!list_empty(&intf->bundles))) + return 0; + list_for_each_entry_safe(desc, next, &intf->manifest_descs, links) { struct greybus_descriptor_bundle *desc_bundle; - struct gb_bundle *bundle; if (desc->type != GREYBUS_TYPE_BUNDLE) continue; @@ -270,11 +274,11 @@ static u32 gb_manifest_parse_bundles(struct gb_interface *intf) bundle = gb_bundle_create(intf, desc_bundle->id, desc_bundle->class); if (!bundle) - return 0; /* Error */ + goto cleanup; /* Now go set up this bundle's functions and cports */ if (!gb_manifest_parse_cports(bundle)) - return 0; /* Error parsing cports */ + goto cleanup; count++; @@ -283,6 +287,13 @@ static u32 gb_manifest_parse_bundles(struct gb_interface *intf) } return count; +cleanup: + /* An error occurred; undo any changes we've made */ + list_for_each_entry_safe(bundle, bundle_next, &intf->bundles, links) { + gb_bundle_destroy(bundle); + count--; + } + return 0; /* Error; count should also be 0 */ } static bool gb_manifest_parse_interface(struct gb_interface *intf, -- cgit v0.10.2 From 821c620afa1ad29be6a85a9a3f691e32e973a317 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Sat, 13 Jun 2015 11:02:07 -0500 Subject: greybus: introduce cport_id_valid() Define a public predicate that defines whether a CPort ID is valid. Use it in the message_send() routine, and make the message reported more accurately reflect the error. Also use it to check whether the CPort ID in a received message is valid; if it is not, just drop the message. Get rid of local variable "buffer" in message_send(); it adds no value. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 56c80c6..e68ee48 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -176,21 +176,17 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id, { struct es1_ap_dev *es1 = hd_to_es1(hd); struct usb_device *udev = es1->usb_dev; - void *buffer; size_t buffer_size; int retval; struct urb *urb; - buffer = message->buffer; - buffer_size = sizeof(*message->header) + message->payload_size; - /* * The data actually transferred will include an indication * of where the data should be sent. Do one last check of * the target CPort id before filling it in. */ - if (cport_id == CPORT_ID_BAD) { - pr_err("request to send inbound data buffer\n"); + if (!cport_id_valid(cport_id)) { + pr_err("invalid destination cport 0x%02x\n", cport_id); return ERR_PTR(-EINVAL); } @@ -205,9 +201,11 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id, */ put_unaligned_le16(cport_id, message->header->pad); + buffer_size = sizeof(*message->header) + message->payload_size; + usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, es1->cport_out_endpoint), - buffer, buffer_size, + message->buffer, buffer_size, cport_out_callback, message); retval = usb_submit_urb(urb, gfp_mask); if (retval) { @@ -371,8 +369,12 @@ static void cport_in_callback(struct urb *urb) cport_id = get_unaligned_le16(header->pad); put_unaligned_le16(0, header->pad); - greybus_data_rcvd(hd, cport_id, urb->transfer_buffer, + if (cport_id_valid(cport_id)) + greybus_data_rcvd(hd, cport_id, urb->transfer_buffer, urb->actual_length); + else + dev_err(dev, "%s: invalid cport id 0x%02x received\n", + __func__, cport_id); exit: /* put our urb back in the request pool */ retval = usb_submit_urb(urb, GFP_ATOMIC); diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 5257779..daa2e51 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -176,21 +176,17 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id, { struct es1_ap_dev *es1 = hd_to_es1(hd); struct usb_device *udev = es1->usb_dev; - void *buffer; size_t buffer_size; int retval; struct urb *urb; - buffer = message->buffer; - buffer_size = sizeof(*message->header) + message->payload_size; - /* * The data actually transferred will include an indication * of where the data should be sent. Do one last check of * the target CPort id before filling it in. */ - if (cport_id == CPORT_ID_BAD) { - pr_err("request to send inbound data buffer\n"); + if (!cport_id_valid(cport_id)) { + pr_err("invalid destination cport 0x%02x\n", cport_id); return ERR_PTR(-EINVAL); } @@ -205,9 +201,11 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id, */ put_unaligned_le16(cport_id, message->header->pad); + buffer_size = sizeof(*message->header) + message->payload_size; + usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, es1->cport_out_endpoint), - buffer, buffer_size, + message->buffer, buffer_size, cport_out_callback, message); retval = usb_submit_urb(urb, gfp_mask); if (retval) { @@ -371,8 +369,12 @@ static void cport_in_callback(struct urb *urb) cport_id = get_unaligned_le16(header->pad); put_unaligned_le16(0, header->pad); - greybus_data_rcvd(hd, cport_id, urb->transfer_buffer, + if (cport_id_valid(cport_id)) + greybus_data_rcvd(hd, cport_id, urb->transfer_buffer, urb->actual_length); + else + dev_err(dev, "%s: invalid cport id 0x%02x received\n", + __func__, cport_id); exit: /* put our urb back in the request pool */ retval = usb_submit_urb(urb, GFP_ATOMIC); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 05eab4c..518f142 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -196,5 +196,10 @@ static inline int is_gb_connection(const struct device *dev) return dev->type == &greybus_connection_type; } +static inline bool cport_id_valid(u16 cport_id) +{ + return cport_id != CPORT_ID_BAD; +} + #endif /* __KERNEL__ */ #endif /* __LINUX_GREYBUS_H */ -- cgit v0.10.2 From d29b3d631e572400b45b5f9e48e432493663b0fc Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Sat, 13 Jun 2015 11:02:08 -0500 Subject: greybus: esX: encapsulate packing cport id into header For the ES1 and ES2 host interfaces we encode the CPort ID over which the message should be sent within the message itself. The CPort ID is recorded in unused pad bytes found in the operation message header in order to avoid introducing misaligned messages. This patch defines some helper routines to abstract this activity. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index e68ee48..945dbe6 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -167,6 +167,32 @@ static void free_urb(struct es1_ap_dev *es1, struct urb *urb) } /* + * We (ab)use the operation-message header pad bytes to transfer the + * cport id in order to minimise overhead. + */ +static void +gb_message_cport_pack(struct gb_operation_msg_hdr *header, u16 cport_id) +{ + put_unaligned_le16(cport_id, header->pad); +} + +/* Clear the pad bytes used for the CPort id */ +static void gb_message_cport_clear(struct gb_operation_msg_hdr *header) +{ + put_unaligned_le16(0, header->pad); +} + +/* Extract the CPort id packed into the header, and clear it */ +static u16 gb_message_cport_unpack(struct gb_operation_msg_hdr *header) +{ + u16 cport_id = get_unaligned_le16(header->pad); + + gb_message_cport_clear(header); + + return cport_id; +} + +/* * Returns an opaque cookie value if successful, or a pointer coded * error otherwise. If the caller wishes to cancel the in-flight * buffer, it must supply the returned cookie to the cancel routine. @@ -195,11 +221,8 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id, if (!urb) return ERR_PTR(-ENOMEM); - /* - * We (ab)use the operation-message header pad bytes to transfer the - * cport id in order to minimise overhead. - */ - put_unaligned_le16(cport_id, message->header->pad); + /* Pack the cport id into the message header */ + gb_message_cport_pack(message->header, cport_id); buffer_size = sizeof(*message->header) + message->payload_size; @@ -211,7 +234,7 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id, if (retval) { pr_err("error %d submitting URB\n", retval); free_urb(es1, urb); - put_unaligned_le16(0, message->header->pad); + gb_message_cport_clear(message->header); return ERR_PTR(retval); } @@ -365,9 +388,9 @@ static void cport_in_callback(struct urb *urb) goto exit; } + /* Extract the CPort id, which is packed in the message header */ header = urb->transfer_buffer; - cport_id = get_unaligned_le16(header->pad); - put_unaligned_le16(0, header->pad); + cport_id = gb_message_cport_unpack(header); if (cport_id_valid(cport_id)) greybus_data_rcvd(hd, cport_id, urb->transfer_buffer, @@ -390,8 +413,7 @@ static void cport_out_callback(struct urb *urb) struct es1_ap_dev *es1 = hd_to_es1(hd); int status = check_urb_status(urb); - /* Clear the pad bytes used for the cport id */ - put_unaligned_le16(0, message->header->pad); + gb_message_cport_clear(message->header); /* * Tell the submitter that the message send (attempt) is diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index daa2e51..d6966bf 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -167,6 +167,32 @@ static void free_urb(struct es1_ap_dev *es1, struct urb *urb) } /* + * We (ab)use the operation-message header pad bytes to transfer the + * cport id in order to minimise overhead. + */ +static void +gb_message_cport_pack(struct gb_operation_msg_hdr *header, u16 cport_id) +{ + put_unaligned_le16(cport_id, header->pad); +} + +/* Clear the pad bytes used for the CPort id */ +static void gb_message_cport_clear(struct gb_operation_msg_hdr *header) +{ + put_unaligned_le16(0, header->pad); +} + +/* Extract the CPort id packed into the header, and clear it */ +static u16 gb_message_cport_unpack(struct gb_operation_msg_hdr *header) +{ + u16 cport_id = get_unaligned_le16(header->pad); + + gb_message_cport_clear(header); + + return cport_id; +} + +/* * Returns an opaque cookie value if successful, or a pointer coded * error otherwise. If the caller wishes to cancel the in-flight * buffer, it must supply the returned cookie to the cancel routine. @@ -195,11 +221,8 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id, if (!urb) return ERR_PTR(-ENOMEM); - /* - * We (ab)use the operation-message header pad bytes to transfer the - * cport id in order to minimise overhead. - */ - put_unaligned_le16(cport_id, message->header->pad); + /* Pack the cport id into the message header */ + gb_message_cport_pack(message->header, cport_id); buffer_size = sizeof(*message->header) + message->payload_size; @@ -211,7 +234,7 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id, if (retval) { pr_err("error %d submitting URB\n", retval); free_urb(es1, urb); - put_unaligned_le16(0, message->header->pad); + gb_message_cport_clear(message->header); return ERR_PTR(retval); } @@ -365,9 +388,9 @@ static void cport_in_callback(struct urb *urb) goto exit; } + /* Extract the CPort id, which is packed in the message header */ header = urb->transfer_buffer; - cport_id = get_unaligned_le16(header->pad); - put_unaligned_le16(0, header->pad); + cport_id = gb_message_cport_unpack(header); if (cport_id_valid(cport_id)) greybus_data_rcvd(hd, cport_id, urb->transfer_buffer, @@ -390,8 +413,7 @@ static void cport_out_callback(struct urb *urb) struct es1_ap_dev *es1 = hd_to_es1(hd); int status = check_urb_status(urb); - /* Clear the pad bytes used for the cport id */ - put_unaligned_le16(0, message->header->pad); + gb_message_cport_clear(message->header); /* * Tell the submitter that the message send (attempt) is -- cgit v0.10.2 From fb690ca96f9a7aff8bc8135ce23606e243f4cbae Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Sat, 13 Jun 2015 11:02:09 -0500 Subject: greybus: rename HOST_DEV_CPORT_ID_MAX We limit the number of host-side CPorts to a fixed maximum (which is less than the 4096 that UniPro allows). This patch imposes a similar limit on the CPort IDs defined by modules (signaling an error if one too large is found in a manifest). It seems reasonable to use the same value for both limits. Change the name of the constant that defines the host limit and use it for both. Update cport_id_valid() to enforce the maximum. (Ultimately we should impose a limit like this; this change is being made in preparation for supporting multiple connections over a single CPort.) Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 7236e47..9467aab 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -158,7 +158,7 @@ struct gb_connection *gb_connection_create(struct gb_bundle *bundle, if (!connection) return NULL; - retval = ida_simple_get(id_map, 0, HOST_DEV_CPORT_ID_MAX, GFP_KERNEL); + retval = ida_simple_get(id_map, 0, CPORT_ID_MAX, GFP_KERNEL); if (retval < 0) { kfree(connection); return NULL; diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 18b5d5f..d4fffec 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -246,7 +246,7 @@ static int __init gb_init(void) if (greybus_disabled()) return -ENODEV; - BUILD_BUG_ON(HOST_DEV_CPORT_ID_MAX >= (long)CPORT_ID_BAD); + BUILD_BUG_ON(CPORT_ID_MAX >= (long)CPORT_ID_BAD); gb_debugfs_init(); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 518f142..5c6f960 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -52,14 +52,14 @@ .serial_number = (s), /* XXX I couldn't get my Kconfig file to be noticed for out-of-tree build */ -#ifndef CONFIG_HOST_DEV_CPORT_ID_MAX -#define CONFIG_HOST_DEV_CPORT_ID_MAX 128 -#endif /* !CONFIG_HOST_DEV_CPORT_ID_MAX */ +#ifndef CONFIG_CPORT_ID_MAX +#define CONFIG_CPORT_ID_MAX 128 +#endif /* !CONFIG_CPORT_ID_MAX */ /* Maximum number of CPorts usable by a host device */ /* XXX This should really be determined by the AP module manifest */ -#define HOST_DEV_CPORT_ID_MAX CONFIG_HOST_DEV_CPORT_ID_MAX -#define CPORT_ID_BAD U16_MAX /* UniPro max id is 4095 */ +#define CPORT_ID_MAX CONFIG_CPORT_ID_MAX +#define CPORT_ID_BAD U16_MAX /* UniPro max id is 4095 */ /* For SP1 hardware, we are going to "hardcode" each device to have all logical * blocks in order to be able to address them as one unified "unit". Then @@ -198,7 +198,7 @@ static inline int is_gb_connection(const struct device *dev) static inline bool cport_id_valid(u16 cport_id) { - return cport_id != CPORT_ID_BAD; + return cport_id != CPORT_ID_BAD && cport_id <= CPORT_ID_MAX; } #endif /* __KERNEL__ */ diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index e329f37..ad55a73 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -224,9 +224,12 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) if (desc_cport->bundle != bundle_id) continue; + cport_id = le16_to_cpu(desc_cport->id); + if (cport_id > CPORT_ID_MAX) + goto cleanup; + /* Found one. Set up its function structure */ protocol_id = desc_cport->protocol_id; - cport_id = le16_to_cpu(desc_cport->id); if (!gb_connection_create(bundle, cport_id, protocol_id)) goto cleanup; -- cgit v0.10.2 From 88d18a975ddac4fa849909c2ae178b0c126f7f8e Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Sat, 13 Jun 2015 11:02:10 -0500 Subject: greybus: reserve host cport id 0 For ES1 and ES2, we use pad bytes in an operation message header to encode the CPort ID used for transferring the message. The pad bytes should otherwise be zero, and we ensure this as the message is passed to or from the upper layer. If host-side CPort ID 0 is used, we have no way of knowing whether the CPort field has been "packed" into the header. To allow detection of this, reserve host CPort id 0. Update cport_id_valid() to treat 0 as invalid. (CPort ID 0 is reserved by one of the UniPro standards. We'll assume for now that we never use it for Greybus.) Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index d4fffec..bc9c1eb 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -170,6 +170,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver size_t buffer_size_max) { struct greybus_host_device *hd; + int ret; /* * Validate that the driver implements all of the callbacks @@ -200,12 +201,19 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver if (!hd) return ERR_PTR(-ENOMEM); + ida_init(&hd->cport_id_map); + /* Reserve CPort id 0 */ + ret = ida_simple_get(&hd->cport_id_map, 0, 1, GFP_KERNEL); + if (ret < 0) { + kfree(hd); + return ERR_PTR(ret); + } + kref_init(&hd->kref); hd->parent = parent; hd->driver = driver; INIT_LIST_HEAD(&hd->interfaces); INIT_LIST_HEAD(&hd->connections); - ida_init(&hd->cport_id_map); hd->buffer_size_max = buffer_size_max; return hd; diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 5c6f960..d727dea 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -198,7 +198,7 @@ static inline int is_gb_connection(const struct device *dev) static inline bool cport_id_valid(u16 cport_id) { - return cport_id != CPORT_ID_BAD && cport_id <= CPORT_ID_MAX; + return cport_id && cport_id != CPORT_ID_BAD && cport_id <= CPORT_ID_MAX; } #endif /* __KERNEL__ */ -- cgit v0.10.2 From 4bc1389de9fcaaaf2f93e278f588858fb4fe2038 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Sat, 13 Jun 2015 11:02:11 -0500 Subject: greybus: esX: use one byte to encode cport ids in header We now limit the maximum value for both host and module CPort ids, and we know they can always be represented in a single byte. Make use of this by using only one of the two pad bytes for encoding the CPort id in a message header. (Note that we have never used a CPort higher than 255. Encoding such a small CPort id in little endian 2-byte format has the same result as what is done here.) Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 945dbe6..d6824b6 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -173,19 +173,19 @@ static void free_urb(struct es1_ap_dev *es1, struct urb *urb) static void gb_message_cport_pack(struct gb_operation_msg_hdr *header, u16 cport_id) { - put_unaligned_le16(cport_id, header->pad); + header->pad[0] = cport_id; } /* Clear the pad bytes used for the CPort id */ static void gb_message_cport_clear(struct gb_operation_msg_hdr *header) { - put_unaligned_le16(0, header->pad); + header->pad[0] = 0; } /* Extract the CPort id packed into the header, and clear it */ static u16 gb_message_cport_unpack(struct gb_operation_msg_hdr *header) { - u16 cport_id = get_unaligned_le16(header->pad); + u16 cport_id = header->pad[0]; gb_message_cport_clear(header); @@ -574,6 +574,9 @@ static int ap_probe(struct usb_interface *interface, u8 ap_intf_id = 0x01; // FIXME - get endo "ID" from the SVC u8 svc_interval = 0; + /* We need to fit a CPort ID in one byte of a message header */ + BUILD_BUG_ON(CPORT_ID_MAX > U8_MAX); + udev = usb_get_dev(interface_to_usbdev(interface)); hd = greybus_create_hd(&es1_driver, &udev->dev, ES1_GBUF_MSG_SIZE_MAX); diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index d6966bf..450a016 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -173,19 +173,19 @@ static void free_urb(struct es1_ap_dev *es1, struct urb *urb) static void gb_message_cport_pack(struct gb_operation_msg_hdr *header, u16 cport_id) { - put_unaligned_le16(cport_id, header->pad); + header->pad[0] = cport_id; } /* Clear the pad bytes used for the CPort id */ static void gb_message_cport_clear(struct gb_operation_msg_hdr *header) { - put_unaligned_le16(0, header->pad); + header->pad[0] = 0; } /* Extract the CPort id packed into the header, and clear it */ static u16 gb_message_cport_unpack(struct gb_operation_msg_hdr *header) { - u16 cport_id = get_unaligned_le16(header->pad); + u16 cport_id = header->pad[0]; gb_message_cport_clear(header); @@ -574,6 +574,9 @@ static int ap_probe(struct usb_interface *interface, u8 ap_intf_id = 0x01; // FIXME - get endo "ID" from the SVC u8 svc_interval = 0; + /* We need to fit a CPort ID in one byte of a message header */ + BUILD_BUG_ON(CPORT_ID_MAX > U8_MAX); + udev = usb_get_dev(interface_to_usbdev(interface)); hd = greybus_create_hd(&es1_driver, &udev->dev, ES1_GBUF_MSG_SIZE_MAX); -- cgit v0.10.2 From 799baa24dbe449154dcde3bb607d254b8162f901 Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Mon, 15 Jun 2015 18:08:10 +0200 Subject: greybus: es1.c: Don't use magic value for USB control request Signed-off-by: Alexandre Bailon Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 56c80c6..9ae824a 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -46,6 +46,12 @@ static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); */ #define NUM_CPORT_OUT_URB 8 +/* vendor request AP message */ +#define REQUEST_SVC 0x01 + +/* vendor request APB1 log */ +#define REQUEST_LOG 0x02 + /** * es1_ap_dev - ES1 USB Bridge to AP structure * @usb_dev: pointer to the USB device we are. @@ -103,7 +109,7 @@ static int submit_svc(struct svc_msg *svc_msg, struct greybus_host_device *hd) retval = usb_control_msg(es1->usb_dev, usb_sndctrlpipe(es1->usb_dev, es1->control_endpoint), - 0x01, /* vendor request AP message */ + REQUEST_SVC, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0x00, 0x00, (char *)svc_msg, @@ -410,7 +416,7 @@ static void apb1_log_get(struct es1_ap_dev *es1, char *buf) retval = usb_control_msg(es1->usb_dev, usb_rcvctrlpipe(es1->usb_dev, es1->control_endpoint), - 0x02, /* vendor request APB1 log */ + REQUEST_LOG, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0x00, 0x00, buf, -- cgit v0.10.2 From 611c17390e7b47b3f311a9304439eaa4de94dbae Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Mon, 15 Jun 2015 18:08:11 +0200 Subject: greybus: es2.c: Don't use magic value for USB control request Signed-off-by: Alexandre Bailon Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 5257779..a35c79a 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -46,6 +46,12 @@ static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); */ #define NUM_CPORT_OUT_URB 8 +/* vendor request AP message */ +#define REQUEST_SVC 0x01 + +/* vendor request APB1 log */ +#define REQUEST_LOG 0x02 + /** * es1_ap_dev - ES1 USB Bridge to AP structure * @usb_dev: pointer to the USB device we are. @@ -103,7 +109,7 @@ static int submit_svc(struct svc_msg *svc_msg, struct greybus_host_device *hd) retval = usb_control_msg(es1->usb_dev, usb_sndctrlpipe(es1->usb_dev, es1->control_endpoint), - 0x01, /* vendor request AP message */ + REQUEST_SVC, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0x00, 0x00, (char *)svc_msg, @@ -410,7 +416,7 @@ static void apb1_log_get(struct es1_ap_dev *es1, char *buf) retval = usb_control_msg(es1->usb_dev, usb_rcvctrlpipe(es1->usb_dev, es1->control_endpoint), - 0x02, /* vendor request APB1 log */ + REQUEST_LOG, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0x00, 0x00, buf, -- cgit v0.10.2 From ddc09acd469523dc4a15bce30103743d243bc9ba Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Mon, 15 Jun 2015 18:08:12 +0200 Subject: greybus: es2.c: create dedicated struct for cport_in and cport_out Instead of keep cport buffers, urbs and endpoints in es1_ap_dev, move them in two dedicated struct (es1_cport_in and es1_cport_out), in order to ease the migration to es2 (increase the number of endpoint). Signed-off-by: Alexandre Bailon Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index a35c79a..9b6c3cf 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -52,6 +52,24 @@ static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); /* vendor request APB1 log */ #define REQUEST_LOG 0x02 +/* + * @endpoint: bulk in endpoint for CPort data + * @urb: array of urbs for the CPort in messages + * @buffer: array of buffers for the @cport_in_urb urbs + */ +struct es1_cport_in { + __u8 endpoint; + struct urb *urb[NUM_CPORT_IN_URB]; + u8 *buffer[NUM_CPORT_IN_URB]; +}; + +/* + * @endpoint: bulk out endpoint for CPort data + */ +struct es1_cport_out { + __u8 endpoint; +}; + /** * es1_ap_dev - ES1 USB Bridge to AP structure * @usb_dev: pointer to the USB device we are. @@ -59,12 +77,11 @@ static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); * @hd: pointer to our greybus_host_device structure * @control_endpoint: endpoint to send data to SVC * @svc_endpoint: endpoint for SVC data in - * @cport_in_endpoint: bulk in endpoint for CPort data - * @cport-out_endpoint: bulk out endpoint for CPort data + * @svc_buffer: buffer for SVC messages coming in on @svc_endpoint * @svc_urb: urb for SVC messages coming in on @svc_endpoint - * @cport_in_urb: array of urbs for the CPort in messages - * @cport_in_buffer: array of buffers for the @cport_in_urb urbs + * @cport_in: endpoint, urbs and buffer for cport in messages + * @cport_out: endpoint for for cport out messages * @cport_out_urb: array of urbs for the CPort out messages * @cport_out_urb_busy: array of flags to see if the @cport_out_urb is busy or * not. @@ -77,14 +94,12 @@ struct es1_ap_dev { __u8 control_endpoint; __u8 svc_endpoint; - __u8 cport_in_endpoint; - __u8 cport_out_endpoint; u8 *svc_buffer; struct urb *svc_urb; - struct urb *cport_in_urb[NUM_CPORT_IN_URB]; - u8 *cport_in_buffer[NUM_CPORT_IN_URB]; + struct es1_cport_in cport_in; + struct es1_cport_out cport_out; struct urb *cport_out_urb[NUM_CPORT_OUT_URB]; bool cport_out_urb_busy[NUM_CPORT_OUT_URB]; spinlock_t cport_out_urb_lock; @@ -212,7 +227,7 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id, put_unaligned_le16(cport_id, message->header->pad); usb_fill_bulk_urb(urb, udev, - usb_sndbulkpipe(udev, es1->cport_out_endpoint), + usb_sndbulkpipe(udev, es1->cport_out.endpoint), buffer, buffer_size, cport_out_callback, message); retval = usb_submit_urb(urb, gfp_mask); @@ -302,14 +317,14 @@ static void ap_disconnect(struct usb_interface *interface) } for (i = 0; i < NUM_CPORT_IN_URB; ++i) { - struct urb *urb = es1->cport_in_urb[i]; + struct urb *urb = es1->cport_in.urb[i]; if (!urb) break; usb_kill_urb(urb); usb_free_urb(urb); - kfree(es1->cport_in_buffer[i]); - es1->cport_in_buffer[i] = NULL; + kfree(es1->cport_in.buffer[i]); + es1->cport_in.buffer[i] = NULL; } usb_kill_urb(es1->svc_urb); @@ -585,10 +600,10 @@ static int ap_probe(struct usb_interface *interface, svc_interval = endpoint->bInterval; int_in_found = true; } else if (usb_endpoint_is_bulk_in(endpoint)) { - es1->cport_in_endpoint = endpoint->bEndpointAddress; + es1->cport_in.endpoint = endpoint->bEndpointAddress; bulk_in_found = true; } else if (usb_endpoint_is_bulk_out(endpoint)) { - es1->cport_out_endpoint = endpoint->bEndpointAddress; + es1->cport_out.endpoint = endpoint->bEndpointAddress; bulk_out_found = true; } else { dev_err(&udev->dev, @@ -630,11 +645,11 @@ static int ap_probe(struct usb_interface *interface, goto error; usb_fill_bulk_urb(urb, udev, - usb_rcvbulkpipe(udev, es1->cport_in_endpoint), + usb_rcvbulkpipe(udev, es1->cport_in.endpoint), buffer, ES1_GBUF_MSG_SIZE_MAX, cport_in_callback, hd); - es1->cport_in_urb[i] = urb; - es1->cport_in_buffer[i] = buffer; + es1->cport_in.urb[i] = urb; + es1->cport_in.buffer[i] = buffer; retval = usb_submit_urb(urb, GFP_KERNEL); if (retval) goto error; -- cgit v0.10.2 From 606addd2847ccc56a70fe90d6861081f9a1cf7c1 Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Mon, 15 Jun 2015 18:08:13 +0200 Subject: greybus: es2.c: Increase the number of bulk endpoints ES2 support 16 endpoints. Update es2.c to allocate endpoints, urbs and buffers for these new endpoints. Currently, they are not yet used and es2.c is working in legacy mode (only original endpoints are used). Signed-off-by: Alexandre Bailon Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 9b6c3cf..a1cf1ac 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -34,6 +34,9 @@ static struct dentry *apb1_log_enable_dentry; static struct task_struct *apb1_log_task; static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); +/* Number of bulk in and bulk out couple */ +#define NUM_BULKS 7 + /* * Number of CPort IN urbs in flight at any point in time. * Adjust if we are having stalls in the USB buffer due to not enough urbs in @@ -44,7 +47,7 @@ static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); /* Number of CPort OUT urbs in flight at any point in time. * Adjust if we get messages saying we are out of urbs in the system log. */ -#define NUM_CPORT_OUT_URB 8 +#define NUM_CPORT_OUT_URB (8 * NUM_BULKS) /* vendor request AP message */ #define REQUEST_SVC 0x01 @@ -98,8 +101,8 @@ struct es1_ap_dev { u8 *svc_buffer; struct urb *svc_urb; - struct es1_cport_in cport_in; - struct es1_cport_out cport_out; + struct es1_cport_in cport_in[NUM_BULKS]; + struct es1_cport_out cport_out[NUM_BULKS]; struct urb *cport_out_urb[NUM_CPORT_OUT_URB]; bool cport_out_urb_busy[NUM_CPORT_OUT_URB]; spinlock_t cport_out_urb_lock; @@ -201,6 +204,7 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id, size_t buffer_size; int retval; struct urb *urb; + int bulk_ep_set = 0; buffer = message->buffer; buffer_size = sizeof(*message->header) + message->payload_size; @@ -227,7 +231,8 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id, put_unaligned_le16(cport_id, message->header->pad); usb_fill_bulk_urb(urb, udev, - usb_sndbulkpipe(udev, es1->cport_out.endpoint), + usb_sndbulkpipe(udev, + es1->cport_out[bulk_ep_set].endpoint), buffer, buffer_size, cport_out_callback, message); retval = usb_submit_urb(urb, gfp_mask); @@ -296,6 +301,7 @@ static void ap_disconnect(struct usb_interface *interface) { struct es1_ap_dev *es1; struct usb_device *udev; + int bulk_in; int i; es1 = usb_get_intfdata(interface); @@ -316,15 +322,18 @@ static void ap_disconnect(struct usb_interface *interface) es1->cport_out_urb_busy[i] = false; /* just to be anal */ } - for (i = 0; i < NUM_CPORT_IN_URB; ++i) { - struct urb *urb = es1->cport_in.urb[i]; - - if (!urb) - break; - usb_kill_urb(urb); - usb_free_urb(urb); - kfree(es1->cport_in.buffer[i]); - es1->cport_in.buffer[i] = NULL; + for (bulk_in = 0; bulk_in < NUM_BULKS; bulk_in++) { + struct es1_cport_in *cport_in = &es1->cport_in[bulk_in]; + for (i = 0; i < NUM_CPORT_IN_URB; ++i) { + struct urb *urb = cport_in->urb[i]; + + if (!urb) + break; + usb_kill_urb(urb); + usb_free_urb(urb); + kfree(cport_in->buffer[i]); + cport_in->buffer[i] = NULL; + } } usb_kill_urb(es1->svc_urb); @@ -563,8 +572,8 @@ static int ap_probe(struct usb_interface *interface, struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; bool int_in_found = false; - bool bulk_in_found = false; - bool bulk_out_found = false; + int bulk_in = 0; + int bulk_out = 0; int retval = -ENOMEM; int i; u16 endo_id = 0x4755; // FIXME - get endo "ID" from the SVC @@ -600,11 +609,11 @@ static int ap_probe(struct usb_interface *interface, svc_interval = endpoint->bInterval; int_in_found = true; } else if (usb_endpoint_is_bulk_in(endpoint)) { - es1->cport_in.endpoint = endpoint->bEndpointAddress; - bulk_in_found = true; + es1->cport_in[bulk_in++].endpoint = + endpoint->bEndpointAddress; } else if (usb_endpoint_is_bulk_out(endpoint)) { - es1->cport_out.endpoint = endpoint->bEndpointAddress; - bulk_out_found = true; + es1->cport_out[bulk_out++].endpoint = + endpoint->bEndpointAddress; } else { dev_err(&udev->dev, "Unknown endpoint type found, address %x\n", @@ -612,8 +621,8 @@ static int ap_probe(struct usb_interface *interface, } } if ((int_in_found == false) || - (bulk_in_found == false) || - (bulk_out_found == false)) { + (bulk_in == 0) || + (bulk_out == 0)) { dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n"); goto error; } @@ -633,26 +642,30 @@ static int ap_probe(struct usb_interface *interface, hd, svc_interval); /* Allocate buffers for our cport in messages and start them up */ - for (i = 0; i < NUM_CPORT_IN_URB; ++i) { - struct urb *urb; - u8 *buffer; - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) - goto error; - buffer = kmalloc(ES1_GBUF_MSG_SIZE_MAX, GFP_KERNEL); - if (!buffer) - goto error; - - usb_fill_bulk_urb(urb, udev, - usb_rcvbulkpipe(udev, es1->cport_in.endpoint), - buffer, ES1_GBUF_MSG_SIZE_MAX, - cport_in_callback, hd); - es1->cport_in.urb[i] = urb; - es1->cport_in.buffer[i] = buffer; - retval = usb_submit_urb(urb, GFP_KERNEL); - if (retval) - goto error; + for (bulk_in = 0; bulk_in < NUM_BULKS; bulk_in++) { + struct es1_cport_in *cport_in = &es1->cport_in[bulk_in]; + for (i = 0; i < NUM_CPORT_IN_URB; ++i) { + struct urb *urb; + u8 *buffer; + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) + goto error; + buffer = kmalloc(ES1_GBUF_MSG_SIZE_MAX, GFP_KERNEL); + if (!buffer) + goto error; + + usb_fill_bulk_urb(urb, udev, + usb_rcvbulkpipe(udev, + cport_in->endpoint), + buffer, ES1_GBUF_MSG_SIZE_MAX, + cport_in_callback, hd); + cport_in->urb[i] = urb; + cport_in->buffer[i] = buffer; + retval = usb_submit_urb(urb, GFP_KERNEL); + if (retval) + goto error; + } } /* Allocate urbs for our CPort OUT messages */ -- cgit v0.10.2 From fc1a536e603f5e096ae82c1a4195af41f0f5ee99 Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Mon, 15 Jun 2015 18:08:14 +0200 Subject: greybus: es2.c: add a control request for endpoints mapping ES2 give us more endpoints. Use them to map one cport to two endpoints (in and out). Because there is more cports than endpoints, we still need to mux other cports traffic on 2 endpoints. Firmware currently assumes these endpoints are 2 and 3. By default, all cports are muxed. To map one cport to 2 endpoints, use map_cport_to_ep(). Signed-off-by: Alexandre Bailon Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index a1cf1ac..4e99044 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -34,6 +34,9 @@ static struct dentry *apb1_log_enable_dentry; static struct task_struct *apb1_log_task; static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); +/* Number of cport present on USB bridge */ +#define CPORT_MAX 44 + /* Number of bulk in and bulk out couple */ #define NUM_BULKS 7 @@ -55,6 +58,9 @@ static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); /* vendor request APB1 log */ #define REQUEST_LOG 0x02 +/* vendor request to map a cport to bulk in and bulk out endpoints */ +#define REQUEST_EP_MAPPING 0x03 + /* * @endpoint: bulk in endpoint for CPort data * @urb: array of urbs for the CPort in messages @@ -106,6 +112,14 @@ struct es1_ap_dev { struct urb *cport_out_urb[NUM_CPORT_OUT_URB]; bool cport_out_urb_busy[NUM_CPORT_OUT_URB]; spinlock_t cport_out_urb_lock; + + int cport_to_ep[CPORT_MAX]; +}; + +struct cport_to_ep { + __le16 cport_id; + __u8 endpoint_in; + __u8 endpoint_out; }; static inline struct es1_ap_dev *hd_to_es1(struct greybus_host_device *hd) @@ -117,6 +131,13 @@ static void cport_out_callback(struct urb *urb); static void usb_log_enable(struct es1_ap_dev *es1); static void usb_log_disable(struct es1_ap_dev *es1); +static int cport_to_ep(struct es1_ap_dev *es1, u16 cport_id) +{ + if (cport_id >= CPORT_MAX) + return 0; + return es1->cport_to_ep[cport_id]; +} + #define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ static int submit_svc(struct svc_msg *svc_msg, struct greybus_host_device *hd) { @@ -139,6 +160,60 @@ static int submit_svc(struct svc_msg *svc_msg, struct greybus_host_device *hd) return 0; } +static int ep_in_use(struct es1_ap_dev *es1, int bulk_ep_set) +{ + int i; + + for (i = 0; i < CPORT_MAX; i++) { + if (es1->cport_to_ep[i] == bulk_ep_set) + return 1; + } + return 0; +} + +int map_cport_to_ep(struct es1_ap_dev *es1, + u16 cport_id, int bulk_ep_set) +{ + int retval; + struct cport_to_ep *cport_to_ep; + + if (bulk_ep_set == 0 || bulk_ep_set >= NUM_BULKS) + return -EINVAL; + if (cport_id >= CPORT_MAX) + return -EINVAL; + if (bulk_ep_set && ep_in_use(es1, bulk_ep_set)) + return -EINVAL; + + cport_to_ep = kmalloc(sizeof(*cport_to_ep), GFP_KERNEL); + if (!cport_to_ep) + return -ENOMEM; + + es1->cport_to_ep[cport_id] = bulk_ep_set; + cport_to_ep->cport_id = cpu_to_le16(cport_id); + cport_to_ep->endpoint_in = es1->cport_in[bulk_ep_set].endpoint; + cport_to_ep->endpoint_out = es1->cport_out[bulk_ep_set].endpoint; + + retval = usb_control_msg(es1->usb_dev, + usb_sndctrlpipe(es1->usb_dev, + es1->control_endpoint), + REQUEST_EP_MAPPING, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + 0x00, 0x00, + (char *)cport_to_ep, + sizeof(*cport_to_ep), + ES1_TIMEOUT); + if (retval == sizeof(*cport_to_ep)) + retval = 0; + kfree(cport_to_ep); + + return retval; +} + +int unmap_cport(struct es1_ap_dev *es1, u16 cport_id) +{ + return map_cport_to_ep(es1, cport_id, 0); +} + static struct urb *next_free_urb(struct es1_ap_dev *es1, gfp_t gfp_mask) { struct urb *urb = NULL; @@ -204,7 +279,7 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id, size_t buffer_size; int retval; struct urb *urb; - int bulk_ep_set = 0; + int bulk_ep_set; buffer = message->buffer; buffer_size = sizeof(*message->header) + message->payload_size; @@ -230,6 +305,7 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id, */ put_unaligned_le16(cport_id, message->header->pad); + bulk_ep_set = cport_to_ep(es1, cport_id); usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, es1->cport_out[bulk_ep_set].endpoint), -- cgit v0.10.2 From fd7b435f21239a022057b014aff0836403bfa54a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 16 Jun 2015 19:43:05 -0700 Subject: greybus: Revert "greybus: reserve host cport id 0" This reverts commit 698d4bd3e7541a660a3c3665f0af9e787650a239 as Alex says it is broken. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index bc9c1eb..d4fffec 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -170,7 +170,6 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver size_t buffer_size_max) { struct greybus_host_device *hd; - int ret; /* * Validate that the driver implements all of the callbacks @@ -201,19 +200,12 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver if (!hd) return ERR_PTR(-ENOMEM); - ida_init(&hd->cport_id_map); - /* Reserve CPort id 0 */ - ret = ida_simple_get(&hd->cport_id_map, 0, 1, GFP_KERNEL); - if (ret < 0) { - kfree(hd); - return ERR_PTR(ret); - } - kref_init(&hd->kref); hd->parent = parent; hd->driver = driver; INIT_LIST_HEAD(&hd->interfaces); INIT_LIST_HEAD(&hd->connections); + ida_init(&hd->cport_id_map); hd->buffer_size_max = buffer_size_max; return hd; diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index d727dea..5c6f960 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -198,7 +198,7 @@ static inline int is_gb_connection(const struct device *dev) static inline bool cport_id_valid(u16 cport_id) { - return cport_id && cport_id != CPORT_ID_BAD && cport_id <= CPORT_ID_MAX; + return cport_id != CPORT_ID_BAD && cport_id <= CPORT_ID_MAX; } #endif /* __KERNEL__ */ -- cgit v0.10.2 From 3ee2266c720520dd2bcf90974f184a22d6e53d06 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 16 Jun 2015 11:28:11 +0100 Subject: greybus: uart: Latch modem control signals for tciomget Latch signals coming from UART module for - GB_UART_CTRL_DCD - GB_UART_CTRL_DSR - GB_UART_CTRL_RI Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 2092870..3b06cd4 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -102,7 +102,7 @@ static int gb_uart_request_recv(u8 type, struct gb_operation *op) break; case GB_UART_TYPE_SERIAL_STATE: serial_state = request->payload; - /* TODO: Parse state change and translate to tty API. */ + gb_tty->ctrlin = le16_to_cpu(serial_state->control); break; default: dev_err(&connection->dev, -- cgit v0.10.2 From cdb5781d9fd5f9728a799a26590d2da5794fb1b0 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 18 Jun 2015 16:41:58 +0100 Subject: greybus: uart: Fix sparse warning Greg reported sparse picked up the following warning: /home/gregkh/ara/greybus/uart.c:105:34: warning: cast to restricted __le16 This is due to the control variable in gb_uart_serial_state_request which needs to be declared __le16 not __u16. Signed-off-by: Bryan O'Donoghue Reported-by: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 642f942..684ad03 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -613,7 +613,7 @@ struct gb_uart_set_break_request { #define GB_UART_CTRL_OVERRUN 0x40 struct gb_uart_serial_state_request { - __u16 control; + __le16 control; }; #endif /* __GREYBUS_PROTOCOLS_H */ -- cgit v0.10.2 From 656f22e94ec793252c7d1b220da5566042a62040 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Mon, 22 Jun 2015 14:03:51 +0100 Subject: greybus: makefile: add MMC to the required option list Add MMC to the list of options that shall be enable. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 42804547..1715f45 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -49,7 +49,7 @@ INSTALL_MOD_PATH ?= /.. PWD := $(shell pwd) # kernel config option that shall be enable -CONFIG_OPTIONS_ENABLE := SYSFS SPI USB SND_SOC +CONFIG_OPTIONS_ENABLE := SYSFS SPI USB SND_SOC MMC # kernel config option that shall be disable CONFIG_OPTIONS_DISABLE := -- cgit v0.10.2 From 3b6ecd6de6b4d8aad200d256b0c09d536a15df29 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Mon, 22 Jun 2015 14:03:52 +0100 Subject: greybus: sdio: extend sdio implementation Extend sdio implementation, as it for now it was basically stubs. This implementation is compile tested only since there is no fw or simulation support yet. Next step is to add sdio support to gbsim and test it with success using the mmc_test facility. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 684ad03..c64f6cb 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -616,5 +616,165 @@ struct gb_uart_serial_state_request { __le16 control; }; +/* SDIO */ +/* Version of the Greybus sdio protocol we support */ +#define GB_SDIO_VERSION_MAJOR 0x00 +#define GB_SDIO_VERSION_MINOR 0x01 + +/* Version of the Greybus SDIO protocol we support */ +#define GB_SDIO_VERSION_MAJOR 0x00 +#define GB_SDIO_VERSION_MINOR 0x01 + +/* Greybus SDIO operation types */ +#define GB_SDIO_TYPE_INVALID 0x00 +#define GB_SDIO_TYPE_PROTOCOL_VERSION 0x01 +#define GB_SDIO_TYPE_GET_CAPABILITIES 0x02 +#define GB_SDIO_TYPE_SET_IOS 0x03 +#define GB_SDIO_TYPE_COMMAND 0x04 +#define GB_SDIO_TYPE_TRANSFER 0x05 +#define GB_SDIO_TYPE_EVENT 0x06 + +/* get caps response: request has no payload */ +struct gb_sdio_get_caps_response { + __le32 caps; +#define GB_SDIO_CAP_NONREMOVABLE 0x00000001 +#define GB_SDIO_CAP_4_BIT_DATA 0x00000002 +#define GB_SDIO_CAP_8_BIT_DATA 0x00000004 +#define GB_SDIO_CAP_MMC_HS 0x00000008 +#define GB_SDIO_CAP_SD_HS 0x00000010 +#define GB_SDIO_CAP_ERASE 0x00000020 +#define GB_SDIO_CAP_1_2V_DDR 0x00000040 +#define GB_SDIO_CAP_1_8V_DDR 0x00000080 +#define GB_SDIO_CAP_POWER_OFF_CARD 0x00000100 +#define GB_SDIO_CAP_UHS_SDR12 0x00000200 +#define GB_SDIO_CAP_UHS_SDR25 0x00000400 +#define GB_SDIO_CAP_UHS_SDR50 0x00000800 +#define GB_SDIO_CAP_UHS_SDR104 0x00001000 +#define GB_SDIO_CAP_UHS_DDR50 0x00002000 +#define GB_SDIO_CAP_DRIVER_TYPE_A 0x00004000 +#define GB_SDIO_CAP_DRIVER_TYPE_C 0x00008000 +#define GB_SDIO_CAP_DRIVER_TYPE_D 0x00010000 +#define GB_SDIO_CAP_HS200_1_2V 0x00020000 +#define GB_SDIO_CAP_HS200_1_8V 0x00040000 +#define GB_SDIO_CAP_HS400_1_2V 0x00080000 +#define GB_SDIO_CAP_HS400_1_8V 0x00100000 + + /* see possible values below at vdd */ + __le32 ocr; + __le16 max_blk_count; + __le16 max_blk_size; +}; + +/* set ios request: response has no payload */ +struct gb_sdio_set_ios_request { + __le32 clock; + __le32 vdd; +#define GB_SDIO_VDD_165_195 0x00000001 +#define GB_SDIO_VDD_20_21 0x00000002 +#define GB_SDIO_VDD_21_22 0x00000004 +#define GB_SDIO_VDD_22_23 0x00000008 +#define GB_SDIO_VDD_23_24 0x00000010 +#define GB_SDIO_VDD_24_25 0x00000020 +#define GB_SDIO_VDD_25_26 0x00000040 +#define GB_SDIO_VDD_26_27 0x00000080 +#define GB_SDIO_VDD_27_28 0x00000100 +#define GB_SDIO_VDD_28_29 0x00000200 +#define GB_SDIO_VDD_29_30 0x00000400 +#define GB_SDIO_VDD_30_31 0x00000800 +#define GB_SDIO_VDD_31_32 0x00001000 +#define GB_SDIO_VDD_32_33 0x00002000 +#define GB_SDIO_VDD_33_34 0x00004000 +#define GB_SDIO_VDD_34_35 0x00008000 +#define GB_SDIO_VDD_35_36 0x00010000 + + __u8 bus_mode; +#define GB_SDIO_BUSMODE_OPENDRAIN 0x00 +#define GB_SDIO_BUSMODE_PUSHPULL 0x01 + + __u8 power_mode; +#define GB_SDIO_POWER_OFF 0x00 +#define GB_SDIO_POWER_UP 0x01 +#define GB_SDIO_POWER_ON 0x02 +#define GB_SDIO_POWER_UNDEFINED 0x03 + + __u8 bus_width; +#define GB_SDIO_BUS_WIDTH_1 0x00 +#define GB_SDIO_BUS_WIDTH_4 0x02 +#define GB_SDIO_BUS_WIDTH_8 0x03 + + __u8 timing; +#define GB_SDIO_TIMING_LEGACY 0x00 +#define GB_SDIO_TIMING_MMC_HS 0x01 +#define GB_SDIO_TIMING_SD_HS 0x02 +#define GB_SDIO_TIMING_UHS_SDR12 0x03 +#define GB_SDIO_TIMING_UHS_SDR25 0x04 +#define GB_SDIO_TIMING_UHS_SDR50 0x05 +#define GB_SDIO_TIMING_UHS_SDR104 0x06 +#define GB_SDIO_TIMING_UHS_DDR50 0x07 +#define GB_SDIO_TIMING_MMC_DDR52 0x08 +#define GB_SDIO_TIMING_MMC_HS200 0x09 +#define GB_SDIO_TIMING_MMC_HS400 0x0A + + __u8 signal_voltage; +#define GB_SDIO_SIGNAL_VOLTAGE_330 0x00 +#define GB_SDIO_SIGNAL_VOLTAGE_180 0x01 +#define GB_SDIO_SIGNAL_VOLTAGE_120 0x02 + + __u8 drv_type; +#define GB_SDIO_SET_DRIVER_TYPE_B 0x00 +#define GB_SDIO_SET_DRIVER_TYPE_A 0x01 +#define GB_SDIO_SET_DRIVER_TYPE_C 0x02 +#define GB_SDIO_SET_DRIVER_TYPE_D 0x03 +}; + +/* command request */ +struct gb_sdio_command_request { + __u8 cmd; + __u8 cmd_flags; +#define GB_SDIO_RSP_NONE 0x00 +#define GB_SDIO_RSP_R1_R5_R6_R7 0x01 +#define GB_SDIO_RSP_R1B 0x02 +#define GB_SDIO_RSP_R2 0x03 +#define GB_SDIO_RSP_R3_R4 0x04 + + __u8 cmd_type; +#define GB_SDIO_CMD_AC 0x00 +#define GB_SDIO_CMD_ADTC 0x01 +#define GB_SDIO_CMD_BCR 0x02 +#define GB_SDIO_CMD_BC 0x03 + + __le32 cmd_arg; +}; + +struct gb_sdio_command_response { + __le32 resp[4]; +}; + +/* transfer request */ +struct gb_sdio_transfer_request { + __u8 data_flags; +#define GB_SDIO_DATA_WRITE 0x01 +#define GB_SDIO_DATA_READ 0x02 +#define GB_SDIO_DATA_STREAM 0x04 + + __le16 data_blocks; + __le16 data_blksz; + __u8 data[0]; +}; + +struct gb_sdio_transfer_response { + __le16 data_blocks; + __le16 data_blksz; + __u8 data[0]; +}; + +/* event request: generated by module and is defined as unidirectional */ +struct gb_sdio_event_request { + __u8 event; +#define GB_SDIO_CARD_INSERTED 0x01 +#define GB_SDIO_CARD_REMOVED 0x02 +#define GB_SDIO_WP 0x04 +}; + #endif /* __GREYBUS_PROTOCOLS_H */ diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index 9a0348c..1fd17c8 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -1,51 +1,626 @@ /* * SD/MMC Greybus driver. * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. * * Released under the GPLv2 only. */ #include -#include +#include #include +#include +#include +#include #include "greybus.h" struct gb_sdio_host { - struct gb_connection *connection; - struct mmc_host *mmc; - struct mmc_request *mrq; - // FIXME - some lock? + struct gb_connection *connection; + u8 version_major; + u8 version_minor; + struct mmc_host *mmc; + struct mmc_request *mrq; + struct mutex lock; /* lock for this host */ + size_t data_max; + void *xfer_buffer; + spinlock_t xfer; /* lock to cancel ongoing transfer */ + bool xfer_stop; + struct work_struct mrqwork; + bool removed; + bool card_present; + bool read_only; }; -static void gb_sd_request(struct mmc_host *mmc, struct mmc_request *mrq) +static struct workqueue_struct *gb_sdio_mrq_workqueue; + +/* Define get_version() routine */ +define_get_version(gb_sdio_host, SDIO); + +static void _gb_sdio_set_host_caps(struct gb_sdio_host *host, u32 r) { - // FIXME - do something here... + u32 caps = 0; + u32 caps2 = 0; + + caps = (r & GB_SDIO_CAP_NONREMOVABLE ? MMC_CAP_NONREMOVABLE : 0) | + (r & GB_SDIO_CAP_4_BIT_DATA ? MMC_CAP_4_BIT_DATA : 0) | + (r & GB_SDIO_CAP_8_BIT_DATA ? MMC_CAP_8_BIT_DATA : 0) | + (r & GB_SDIO_CAP_MMC_HS ? MMC_CAP_MMC_HIGHSPEED : 0) | + (r & GB_SDIO_CAP_SD_HS ? MMC_CAP_SD_HIGHSPEED : 0) | + (r & GB_SDIO_CAP_ERASE ? MMC_CAP_ERASE : 0) | + (r & GB_SDIO_CAP_1_2V_DDR ? MMC_CAP_1_2V_DDR : 0) | + (r & GB_SDIO_CAP_1_8V_DDR ? MMC_CAP_1_8V_DDR : 0) | + (r & GB_SDIO_CAP_POWER_OFF_CARD ? MMC_CAP_POWER_OFF_CARD : 0) | + (r & GB_SDIO_CAP_UHS_SDR12 ? MMC_CAP_UHS_SDR12 : 0) | + (r & GB_SDIO_CAP_UHS_SDR25 ? MMC_CAP_UHS_SDR25 : 0) | + (r & GB_SDIO_CAP_UHS_SDR50 ? MMC_CAP_UHS_SDR50 : 0) | + (r & GB_SDIO_CAP_UHS_SDR104 ? MMC_CAP_UHS_SDR104 : 0) | + (r & GB_SDIO_CAP_UHS_DDR50 ? MMC_CAP_UHS_DDR50 : 0) | + (r & GB_SDIO_CAP_DRIVER_TYPE_A ? MMC_CAP_DRIVER_TYPE_A : 0) | + (r & GB_SDIO_CAP_DRIVER_TYPE_C ? MMC_CAP_DRIVER_TYPE_C : 0) | + (r & GB_SDIO_CAP_DRIVER_TYPE_D ? MMC_CAP_DRIVER_TYPE_D : 0); + + caps2 = (r & GB_SDIO_CAP_HS200_1_2V ? MMC_CAP2_HS200_1_2V_SDR : 0) | + (r & GB_SDIO_CAP_HS200_1_8V ? MMC_CAP2_HS200_1_8V_SDR : 0) | + (r & GB_SDIO_CAP_HS400_1_2V ? MMC_CAP2_HS400_1_2V : 0) | + (r & GB_SDIO_CAP_HS400_1_8V ? MMC_CAP2_HS400_1_8V : 0); + + host->mmc->caps = caps; + host->mmc->caps2 = caps2; + + if (caps & MMC_CAP_NONREMOVABLE) + host->card_present = true; } -static void gb_sd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) +static int gb_sdio_get_caps(struct gb_sdio_host *host) { - // FIXME - do something here... + struct gb_sdio_get_caps_response response; + struct mmc_host *mmc = host->mmc; + u16 data_max; + u32 blksz; + u32 r; + int ret; + + ret = gb_operation_sync(host->connection, GB_SDIO_TYPE_GET_CAPABILITIES, + NULL, 0, &response, sizeof(response)); + if (ret < 0) + return ret; + r = le32_to_cpu(response.caps); + + _gb_sdio_set_host_caps(host, r); + + /* get the max block size that could fit our payload */ + data_max = gb_operation_get_payload_size_max(host->connection); + data_max = min(data_max - sizeof(struct gb_sdio_transfer_request), + data_max - sizeof(struct gb_sdio_transfer_response)); + + blksz = min(le16_to_cpu(response.max_blk_size), data_max); + blksz = max_t(u32, 512, blksz); + + mmc->max_blk_size = rounddown_pow_of_two(blksz); + mmc->max_blk_count = le16_to_cpu(response.max_blk_count); + host->data_max = data_max; + + /* get ocr supported values */ + mmc->ocr_avail = le32_to_cpu(response.ocr); + mmc->ocr_avail_sdio = mmc->ocr_avail; + mmc->ocr_avail_sd = mmc->ocr_avail; + mmc->ocr_avail_mmc = mmc->ocr_avail; + + return 0; } -static int gb_sd_get_ro(struct mmc_host *mmc) +static int gb_sdio_event_recv(u8 type, struct gb_operation *op) { - // FIXME - do something here... + struct gb_connection *connection = op->connection; + struct gb_sdio_host *host = connection->private; + struct gb_message *request; + struct gb_sdio_event_request *payload; + u8 state_changed = 0; + u8 event; + + if (type != GB_SDIO_TYPE_EVENT) { + dev_err(&connection->dev, + "unsupported unsolicited event: %u\n", type); + return -EINVAL; + } + + request = op->request; + + if (request->payload_size != sizeof(*payload)) { + dev_err(mmc_dev(host->mmc), "wrong event size received\n"); + return -EINVAL; + } + + payload = request->payload; + event = payload->event; + + switch (event) { + case GB_SDIO_CARD_INSERTED: + if (!mmc_card_is_removable(host->mmc)) + return 0; + if (host->card_present) + return 0; + host->card_present = true; + state_changed = 1; + break; + case GB_SDIO_CARD_REMOVED: + if (!mmc_card_is_removable(host->mmc)) + return 0; + if (!(host->card_present)) + return 0; + host->card_present = false; + state_changed = 1; + break; + case GB_SDIO_WP: + host->read_only = true; + break; + default: + dev_err(mmc_dev(host->mmc), "wrong event received %d\n", event); + return -EINVAL; + } + + if (state_changed) { + dev_info(mmc_dev(host->mmc), "card %s now event\n", + (host->card_present ? "inserted" : "removed")); + mmc_detect_change(host->mmc, 0); + } + return 0; } -static const struct mmc_host_ops gb_sd_ops = { - .request = gb_sd_request, - .set_ios = gb_sd_set_ios, - .get_ro = gb_sd_get_ro, +static int gb_sdio_set_ios(struct gb_sdio_host *host, + struct gb_sdio_set_ios_request *request) +{ + return gb_operation_sync(host->connection, GB_SDIO_TYPE_SET_IOS, + request, sizeof(*request), NULL, 0); +} + +static int _gb_sdio_send(struct gb_sdio_host *host, struct mmc_data *data, + size_t len, u16 nblocks, off_t skip) +{ + struct gb_sdio_transfer_request *request; + struct gb_sdio_transfer_response response; + struct scatterlist *sg = data->sg; + unsigned int sg_len = data->sg_len; + size_t copied; + u16 send_blksz; + u16 send_blocks; + int ret; + + WARN_ON(len > host->data_max); + + request = host->xfer_buffer; + request->data_flags = (data->flags >> 8); + request->data_blocks = cpu_to_le16(nblocks); + request->data_blksz = cpu_to_le16(data->blksz); + + copied = sg_pcopy_to_buffer(sg, sg_len, &request->data[0] + skip, len, + skip); + + if (copied != len) + return -EINVAL; + + ret = gb_operation_sync(host->connection, GB_SDIO_TYPE_TRANSFER, + request, len, &response, sizeof(response)); + if (ret < 0) + return ret; + + send_blocks = le16_to_cpu(response.data_blocks); + send_blksz = le16_to_cpu(response.data_blksz); + + if (len != send_blksz * send_blocks) + return -EINVAL; + + return ret; +} + +static int _gb_sdio_recv(struct gb_sdio_host *host, struct mmc_data *data, + size_t len, u16 nblocks, off_t skip) +{ + struct gb_sdio_transfer_request request; + struct gb_sdio_transfer_response *response; + struct scatterlist *sg = data->sg; + unsigned int sg_len = data->sg_len; + size_t copied; + u16 recv_blksz; + u16 recv_blocks; + int ret; + + WARN_ON(len > host->data_max); + + request.data_flags = (data->flags >> 8); + request.data_blocks = cpu_to_le16(nblocks); + request.data_blksz = cpu_to_le16(data->blksz); + + response = host->xfer_buffer; + + ret = gb_operation_sync(host->connection, GB_SDIO_TYPE_TRANSFER, + &request, sizeof(request), response, len); + if (ret < 0) + return ret; + + recv_blocks = le16_to_cpu(response->data_blocks); + recv_blksz = le16_to_cpu(response->data_blksz); + + if (len != recv_blksz * recv_blocks) + return -EINVAL; + + copied = sg_pcopy_from_buffer(sg, sg_len, &response->data[0] + skip, + len, skip); + if (copied != len) + return -EINVAL; + + return 0; +} + +static int gb_sdio_transfer(struct gb_sdio_host *host, struct mmc_request *mrq) +{ + struct mmc_data *data = mrq->data; + size_t left, len; + off_t skip = 0; + int ret = 0; + u16 nblocks; + + left = data->blksz * data->blocks; + + while (left) { + /* check is a stop transmission is pending */ + spin_lock(&host->xfer); + if (host->xfer_stop) { + host->xfer_stop = false; + spin_unlock(&host->xfer); + ret = -EINTR; + goto out; + } + spin_unlock(&host->xfer); + len = min(left, host->data_max); + nblocks = do_div(len, data->blksz); + len = nblocks * data->blksz; + + if (data->flags & MMC_DATA_READ) { + ret = _gb_sdio_recv(host, data, len, nblocks, skip); + if (ret < 0) + goto out; + } else { + ret = _gb_sdio_send(host, data, len, nblocks, skip); + if (ret < 0) + goto out; + } + data->bytes_xfered += len; + left -= len; + skip += len; + } + +out: + data->error = ret; + return ret; +} + +static int gb_sdio_command(struct gb_sdio_host *host, struct mmc_command *cmd) +{ + struct gb_sdio_command_request request; + struct gb_sdio_command_response response; + u8 cmd_flags; + u8 cmd_type; + int i; + int ret = 0; + + switch (mmc_resp_type(cmd)) { + case MMC_RSP_NONE: + cmd_flags = GB_SDIO_RSP_NONE; + break; + case MMC_RSP_R1: + cmd_flags = GB_SDIO_RSP_R1_R5_R6_R7; + break; + case MMC_RSP_R1B: + cmd_flags = GB_SDIO_RSP_R1B; + break; + case MMC_RSP_R2: + cmd_flags = GB_SDIO_RSP_R2; + break; + case MMC_RSP_R3: + cmd_flags = GB_SDIO_RSP_R3_R4; + default: + dev_err(mmc_dev(host->mmc), "cmd flag invalid %04x\n", + mmc_resp_type(cmd)); + ret = -EINVAL; + goto out; + } + + switch (mmc_cmd_type(cmd)) { + case MMC_CMD_BC: + cmd_type = GB_SDIO_CMD_BC; + break; + case MMC_CMD_BCR: + cmd_type = GB_SDIO_CMD_BCR; + break; + case MMC_CMD_AC: + cmd_type = GB_SDIO_CMD_AC; + break; + case MMC_CMD_ADTC: + cmd_type = GB_SDIO_CMD_ADTC; + break; + default: + dev_err(mmc_dev(host->mmc), "cmd type invalid %04x\n", + mmc_cmd_type(cmd)); + ret = -EINVAL; + goto out; + } + + request.cmd = cmd->opcode; + request.cmd_flags = cmd_flags; + request.cmd_type = cmd_type; + request.cmd_arg = cpu_to_le32(cmd->arg); + + ret = gb_operation_sync(host->connection, GB_SDIO_TYPE_COMMAND, + &request, sizeof(request), &response, + sizeof(response)); + if (ret < 0) + goto out; + + /* no response expected */ + if (cmd_flags & GB_SDIO_RSP_NONE) + goto out; + + /* long response expected */ + if (cmd_flags & GB_SDIO_RSP_R2) + for (i = 0; i < 4; i++) + cmd->resp[i] = le32_to_cpu(response.resp[i]); + else + cmd->resp[0] = le32_to_cpu(response.resp[0]); + +out: + cmd->error = ret; + return ret; +} + +static void gb_sdio_mrq_work(struct work_struct *work) +{ + struct gb_sdio_host *host; + struct mmc_request *mrq; + int ret; + + host = container_of(work, struct gb_sdio_host, mrqwork); + + mutex_lock(&host->lock); + if (host->removed) { + mrq->cmd->error = -ESHUTDOWN; + goto done; + } + + mrq = host->mrq; + + if (mrq->sbc) { + ret = gb_sdio_command(host, mrq->sbc); + if (ret < 0) + goto done; + } + + ret = gb_sdio_command(host, mrq->cmd); + if (ret < 0) + goto done; + + if (mrq->data) { + ret = gb_sdio_transfer(host, host->mrq); + if (ret < 0) + goto done; + } + + if (mrq->data->stop) { + ret = gb_sdio_command(host, mrq->data->stop); + if (ret < 0) + goto done; + } + +done: + mrq = NULL; + mutex_unlock(&host->lock); + mmc_request_done(host->mmc, mrq); +} + +static void gb_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) +{ + struct gb_sdio_host *host = mmc_priv(mmc); + struct mmc_command *cmd = mrq->cmd; + + /* Check if it is a cancel to ongoing transfer */ + if (cmd->opcode == MMC_STOP_TRANSMISSION) { + spin_lock(&host->xfer); + host->xfer_stop = true; + spin_unlock(&host->xfer); + } + + mutex_lock(&host->lock); + + WARN_ON(host->mrq); + host->mrq = mrq; + + if (host->removed) { + mrq->cmd->error = -ESHUTDOWN; + goto out; + } + if (!host->card_present) { + mrq->cmd->error = -ENOMEDIUM; + goto out; + } + + queue_work(gb_sdio_mrq_workqueue, &host->mrqwork); + + mutex_unlock(&host->lock); + return; + +out: + host->mrq = NULL; + mutex_unlock(&host->lock); + mmc_request_done(mmc, mrq); +} + +static void gb_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) +{ + struct gb_sdio_host *host = mmc_priv(mmc); + struct gb_sdio_set_ios_request request; + int ret; + u8 power_mode; + u8 bus_width; + u8 timing; + u8 signal_voltage; + u8 drv_type; + + mutex_lock(&host->lock); + request.clock = cpu_to_le32(ios->clock); + request.vdd = cpu_to_le32(1 << ios->vdd); + + request.bus_mode = (ios->bus_mode == MMC_BUSMODE_OPENDRAIN ? + GB_SDIO_BUSMODE_OPENDRAIN : + GB_SDIO_BUSMODE_PUSHPULL); + + switch (ios->power_mode) { + case MMC_POWER_OFF: + power_mode = GB_SDIO_POWER_OFF; + break; + case MMC_POWER_UP: + power_mode = GB_SDIO_POWER_UP; + break; + case MMC_POWER_ON: + power_mode = GB_SDIO_POWER_ON; + break; + case MMC_POWER_UNDEFINED: + default: + power_mode = GB_SDIO_POWER_UNDEFINED; + break; + } + request.power_mode = power_mode; + + switch (ios->bus_width) { + case MMC_BUS_WIDTH_1: + bus_width = GB_SDIO_BUS_WIDTH_1; + break; + case MMC_BUS_WIDTH_4: + default: + bus_width = GB_SDIO_BUS_WIDTH_4; + break; + case MMC_BUS_WIDTH_8: + bus_width = GB_SDIO_BUS_WIDTH_8; + break; + } + request.bus_width = bus_width; + + switch (ios->timing) { + case MMC_TIMING_LEGACY: + default: + timing = GB_SDIO_TIMING_LEGACY; + break; + case MMC_TIMING_MMC_HS: + timing = GB_SDIO_TIMING_MMC_HS; + break; + case MMC_TIMING_SD_HS: + timing = GB_SDIO_TIMING_SD_HS; + break; + case MMC_TIMING_UHS_SDR12: + timing = GB_SDIO_TIMING_UHS_SDR12; + break; + case MMC_TIMING_UHS_SDR25: + timing = GB_SDIO_TIMING_UHS_SDR25; + break; + case MMC_TIMING_UHS_SDR50: + timing = GB_SDIO_TIMING_UHS_SDR50; + break; + case MMC_TIMING_UHS_SDR104: + timing = GB_SDIO_TIMING_UHS_SDR104; + break; + case MMC_TIMING_UHS_DDR50: + timing = GB_SDIO_TIMING_UHS_DDR50; + break; + case MMC_TIMING_MMC_DDR52: + timing = GB_SDIO_TIMING_MMC_DDR52; + break; + case MMC_TIMING_MMC_HS200: + timing = GB_SDIO_TIMING_MMC_HS200; + break; + case MMC_TIMING_MMC_HS400: + timing = GB_SDIO_TIMING_MMC_HS400; + break; + } + request.timing = timing; + + switch (ios->signal_voltage) { + case MMC_SIGNAL_VOLTAGE_330: + signal_voltage = GB_SDIO_SIGNAL_VOLTAGE_330; + break; + case MMC_SIGNAL_VOLTAGE_180: + default: + signal_voltage = GB_SDIO_SIGNAL_VOLTAGE_180; + break; + case MMC_SIGNAL_VOLTAGE_120: + signal_voltage = GB_SDIO_SIGNAL_VOLTAGE_120; + break; + } + request.signal_voltage = signal_voltage; + + switch (ios->drv_type) { + case MMC_SET_DRIVER_TYPE_A: + drv_type = GB_SDIO_SET_DRIVER_TYPE_A; + break; + case MMC_SET_DRIVER_TYPE_C: + drv_type = GB_SDIO_SET_DRIVER_TYPE_C; + break; + case MMC_SET_DRIVER_TYPE_D: + drv_type = GB_SDIO_SET_DRIVER_TYPE_D; + break; + case MMC_SET_DRIVER_TYPE_B: + default: + drv_type = GB_SDIO_SET_DRIVER_TYPE_B; + break; + } + request.drv_type = drv_type; + + ret = gb_sdio_set_ios(host, &request); + if (ret < 0) + goto out; + + memcpy(&mmc->ios, ios, sizeof(mmc->ios)); + +out: + mutex_unlock(&host->lock); +} + +static int gb_mmc_get_ro(struct mmc_host *mmc) +{ + struct gb_sdio_host *host = mmc_priv(mmc); + + mutex_lock(&host->lock); + if (host->removed) + return -ESHUTDOWN; + mutex_unlock(&host->lock); + return host->card_present; +} + +static int gb_mmc_get_cd(struct mmc_host *mmc) +{ + struct gb_sdio_host *host = mmc_priv(mmc); + + mutex_lock(&host->lock); + if (host->removed) + return -ESHUTDOWN; + mutex_unlock(&host->lock); + return host->read_only; +} + +static const struct mmc_host_ops gb_sdio_ops = { + .request = gb_mmc_request, + .set_ios = gb_mmc_set_ios, + .get_ro = gb_mmc_get_ro, + .get_cd = gb_mmc_get_cd, }; static int gb_sdio_connection_init(struct gb_connection *connection) { struct mmc_host *mmc; struct gb_sdio_host *host; + size_t max_buffer; + int ret = 0; mmc = mmc_alloc_host(sizeof(*host), &connection->dev); if (!mmc) @@ -54,38 +629,82 @@ static int gb_sdio_connection_init(struct gb_connection *connection) host = mmc_priv(mmc); host->mmc = mmc; - mmc->ops = &gb_sd_ops; - // FIXME - set up size limits we can handle. - // FIXME - register the host controller. - host->connection = connection; connection->private = host; - return 0; + + ret = get_version(host); + if (ret < 0) + goto free_mmc; + + ret = gb_sdio_get_caps(host); + if (ret < 0) + goto free_mmc; + + mmc->ops = &gb_sdio_ops; + + /* for now we just make a map 1:1 between max blocks and segments */ + mmc->max_segs = host->mmc->max_blk_count; + mmc->max_seg_size = host->mmc->max_blk_size; + + mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; + + max_buffer = gb_operation_get_payload_size_max(host->connection); + host->xfer_buffer = kzalloc(max_buffer, GFP_KERNEL); + if (!host->xfer_buffer) { + ret = -ENOMEM; + goto free_mmc; + } + mutex_init(&host->lock); + spin_lock_init(&host->xfer); + gb_sdio_mrq_workqueue = alloc_workqueue("gb_sdio_mrq", 0, 1); + INIT_WORK(&host->mrqwork, gb_sdio_mrq_work); + + ret = mmc_add_host(mmc); + if (ret < 0) + goto free_work; + + return ret; + +free_work: + destroy_workqueue(gb_sdio_mrq_workqueue); + kfree(host->xfer_buffer); + +free_mmc: + connection->private = NULL; + mmc_free_host(mmc); + + return ret; } static void gb_sdio_connection_exit(struct gb_connection *connection) { struct mmc_host *mmc; - struct gb_sdio_host *host; + struct gb_sdio_host *host = connection->private; - host = connection->private; if (!host) return; + mutex_lock(&host->lock); + host->removed = true; mmc = host->mmc; - mmc_remove_host(mmc); - mmc_free_host(mmc); connection->private = NULL; + mutex_unlock(&host->lock); + + flush_workqueue(gb_sdio_mrq_workqueue); + destroy_workqueue(gb_sdio_mrq_workqueue); + mmc_free_host(mmc); + mmc_remove_host(mmc); + kfree(host->xfer_buffer); } static struct gb_protocol sdio_protocol = { .name = "sdio", .id = GREYBUS_PROTOCOL_SDIO, - .major = 0, - .minor = 1, + .major = GB_SDIO_VERSION_MAJOR, + .minor = GB_SDIO_VERSION_MINOR, .connection_init = gb_sdio_connection_init, .connection_exit = gb_sdio_connection_exit, - .request_recv = NULL, /* no incoming requests */ + .request_recv = gb_sdio_event_recv, }; gb_gpbridge_protocol_driver(sdio_protocol); -- cgit v0.10.2 From b08488bea5929f14b1e08d701652427bf63a9b47 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 22 Jun 2015 16:36:47 +0530 Subject: greybus: manifest: Allow bundles/connections list to be non-empty at manifest parsing A connection and a bundle will be created for interfaces at the very beginning for control protocol's functioning. And so the list of bundles and connections for a interface will be non-empty by the time manifest is parsed. Currently we are firing a WARN when these lists are found to be non-empty. Lets fix that to contain single bundle and connection for control protocol. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index ad55a73..377c449 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -208,9 +208,6 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) u8 bundle_id = bundle->id; u32 count = 0; - if (WARN_ON(!list_empty(&bundle->connections))) - return 0; - /* Set up all cport descriptors associated with this bundle */ list_for_each_entry_safe(desc, next, &intf->manifest_descs, links) { struct greybus_descriptor_cport *desc_cport; @@ -263,9 +260,6 @@ static u32 gb_manifest_parse_bundles(struct gb_interface *intf) struct gb_bundle *bundle_next; u32 count = 0; - if (WARN_ON(!list_empty(&intf->bundles))) - return 0; - list_for_each_entry_safe(desc, next, &intf->manifest_descs, links) { struct greybus_descriptor_bundle *desc_bundle; -- cgit v0.10.2 From cdee4f7505dbb06671a41f63b295d3d7680d760c Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 22 Jun 2015 16:42:26 +0530 Subject: greybus: Add control protocol support Add control protocol driver that is responsible for handling operations on control CPort. The AP also needs to support incoming requests on its control port. Features not implemented yet are marked as TODO for now. NOTE: This also fixes cport-bundle-id to 0 and cport-id to 2 for control protocol. Reviewed-by: Alex Elder Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 1715f45..4f66ff3 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -8,6 +8,7 @@ greybus-y := core.o \ bundle.o \ connection.o \ protocol.o \ + control.o \ operation.o gb-phy-y := gpbridge.o \ diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c new file mode 100644 index 0000000..c19814d --- /dev/null +++ b/drivers/staging/greybus/control.c @@ -0,0 +1,150 @@ +/* + * Greybus CPort control protocol. + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include "greybus.h" + +/* Define get_version() routine */ +define_get_version(gb_control, CONTROL); + +/* Get Manifest's size from the interface */ +int gb_control_get_manifest_size_operation(struct gb_interface *intf) +{ + struct gb_control_get_manifest_size_response response; + struct gb_connection *connection = intf->control->connection; + int ret; + + ret = gb_operation_sync(connection, GB_CONTROL_TYPE_GET_MANIFEST_SIZE, + NULL, 0, &response, sizeof(response)); + if (ret) { + dev_err(&connection->dev, + "%s: Manifest size get operation failed (%d)\n", + __func__, ret); + return ret; + } + + return le16_to_cpu(response.size); +} + +/* Reads Manifest from the interface */ +int gb_control_get_manifest_operation(struct gb_interface *intf, void *manifest, + size_t size) +{ + struct gb_connection *connection = intf->control->connection; + + return gb_operation_sync(connection, GB_CONTROL_TYPE_GET_MANIFEST, + NULL, 0, manifest, size); +} + +int gb_control_connected_operation(struct gb_control *control, u16 cport_id) +{ + struct gb_control_connected_request request; + + request.cport_id = cpu_to_le16(cport_id); + return gb_operation_sync(control->connection, GB_CONTROL_TYPE_CONNECTED, + &request, sizeof(request), NULL, 0); +} + +int gb_control_disconnected_operation(struct gb_control *control, u16 cport_id) +{ + struct gb_control_disconnected_request request; + + request.cport_id = cpu_to_le16(cport_id); + return gb_operation_sync(control->connection, + GB_CONTROL_TYPE_DISCONNECTED, &request, + sizeof(request), NULL, 0); +} + +static int gb_control_request_recv(u8 type, struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_protocol_version_response *version; + + switch (type) { + case GB_CONTROL_TYPE_PROBE_AP: + // TODO + // Send authenticated block of data, confirming this module is + // an AP. + break; + case GB_CONTROL_TYPE_PROTOCOL_VERSION: + if (!gb_operation_response_alloc(op, sizeof(*version))) { + dev_err(&connection->dev, + "%s: error allocating response\n", __func__); + return -ENOMEM; + } + + version = op->response->payload; + version->major = GB_CONTROL_VERSION_MAJOR; + version->minor = GB_CONTROL_VERSION_MINOR; + break; + case GB_CONTROL_TYPE_CONNECTED: + case GB_CONTROL_TYPE_DISCONNECTED: + break; + default: + WARN_ON(1); + break; + } + + return 0; +} + +static int gb_control_connection_init(struct gb_connection *connection) +{ + struct gb_control *control; + int ret; + + control = kzalloc(sizeof(*control), GFP_KERNEL); + if (!control) + return -ENOMEM; + + control->connection = connection; + connection->private = control; + + ret = get_version(control); + if (ret) + kfree(control); + + /* Set interface's control connection */ + connection->bundle->intf->control = control; + + return ret; +} + +static void gb_control_connection_exit(struct gb_connection *connection) +{ + struct gb_control *control = connection->private; + + if (WARN_ON(connection->bundle->intf->control != control)) + return; + + connection->bundle->intf->control = NULL; + kfree(control); +} + +static struct gb_protocol control_protocol = { + .name = "control", + .id = GREYBUS_PROTOCOL_CONTROL, + .major = 0, + .minor = 1, + .connection_init = gb_control_connection_init, + .connection_exit = gb_control_connection_exit, + .request_recv = gb_control_request_recv, +}; + +int gb_control_protocol_init(void) +{ + return gb_protocol_register(&control_protocol); +} + +void gb_control_protocol_exit(void) +{ + gb_protocol_deregister(&control_protocol); +} diff --git a/drivers/staging/greybus/control.h b/drivers/staging/greybus/control.h new file mode 100644 index 0000000..6e41a2b --- /dev/null +++ b/drivers/staging/greybus/control.h @@ -0,0 +1,27 @@ +/* + * Greybus CPort control protocol + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#ifndef __CONTROL_H +#define __CONTROL_H + +struct gb_control { + struct gb_connection *connection; + u8 version_major; + u8 version_minor; +}; + +int gb_control_connected_operation(struct gb_control *control, u16 cport_id); +int gb_control_disconnected_operation(struct gb_control *control, u16 cport_id); +int gb_control_get_manifest_size_operation(struct gb_interface *intf); +int gb_control_get_manifest_operation(struct gb_interface *intf, void *manifest, + size_t size); + +int gb_control_protocol_init(void); +void gb_control_protocol_exit(void); +#endif /* __CONTROL_H */ diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index d4fffec..8d16e10 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -274,8 +274,16 @@ static int __init gb_init(void) goto error_endo; } + retval = gb_control_protocol_init(); + if (retval) { + pr_err("gb_control_protocol_init failed\n"); + goto error_control; + } + return 0; /* Success */ +error_control: + gb_endo_exit(); error_endo: gb_operation_exit(); error_operation: @@ -291,6 +299,7 @@ module_init(gb_init); static void __exit gb_exit(void) { + gb_control_protocol_exit(); gb_endo_exit(); gb_operation_exit(); gb_ap_exit(); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 5c6f960..6874939 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -28,6 +28,7 @@ #include "endo.h" #include "svc.h" #include "module.h" +#include "control.h" #include "interface.h" #include "bundle.h" #include "connection.h" diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index c64f6cb..9f9b722 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -52,6 +52,45 @@ #ifndef __GREYBUS_PROTOCOLS_H #define __GREYBUS_PROTOCOLS_H +/* Control Protocol */ + +/* Bundle-id and cport-id for control cport */ +#define GB_CONTROL_BUNDLE_ID 0 +#define GB_CONTROL_CPORT_ID 2 + +/* Version of the Greybus control protocol we support */ +#define GB_CONTROL_VERSION_MAJOR 0x00 +#define GB_CONTROL_VERSION_MINOR 0x01 + +/* Greybus control request types */ +#define GB_CONTROL_TYPE_INVALID 0x00 +#define GB_CONTROL_TYPE_PROTOCOL_VERSION 0x01 +#define GB_CONTROL_TYPE_PROBE_AP 0x02 +#define GB_CONTROL_TYPE_GET_MANIFEST_SIZE 0x03 +#define GB_CONTROL_TYPE_GET_MANIFEST 0x04 +#define GB_CONTROL_TYPE_CONNECTED 0x05 +#define GB_CONTROL_TYPE_DISCONNECTED 0x06 + +/* Control protocol manifest get size request has no payload*/ +struct gb_control_get_manifest_size_response { + __le16 size; +}; + +/* Control protocol manifest get request has no payload */ +struct gb_control_get_manifest_response { + __u8 data[0]; +}; + +/* Control protocol [dis]connected request */ +struct gb_control_connected_request { + __le16 cport_id; +}; + +struct gb_control_disconnected_request { + __le16 cport_id; +}; +/* Control protocol [dis]connected response has no payload */ + /* I2C */ /* Version of the Greybus i2c protocol we support */ diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 88a7a80..9c566b2 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -13,6 +13,7 @@ /* Greybus "public" definitions" */ struct gb_interface { struct device dev; + struct gb_control *control; struct list_head bundles; struct list_head links; /* greybus_host_device->interfaces */ -- cgit v0.10.2 From 6c68da264b080f749e8848b0227e6bb7d7c72f21 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 22 Jun 2015 16:42:27 +0530 Subject: greybus: interface: Get manifest using Control protocol Control protocol is ready to be used for fetching manifest. Lets do it. This changes few things: - Creates/initializes bundle/connection for control protocol initially and skips doing the same later. - Manifest is parsed at link-up now, instead of hotplug which was the case earlier. This is because we need device_id (provided during link-up) for registering bundle. - Manifest is fetched using control protocol. So the sequence of events is: Event Previously Now ----- ---------- --- Interface Hotplug create intf create intf parse mfst Interface Link Up init bundles create control conn get mfst size get mfst parse mfst init bundles Reviewed-by: Alex Elder Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 07375cc..113fd87 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -146,10 +146,10 @@ static void svc_management(struct svc_function_unipro_management *management, management->link_up.interface_id); return; } - ret = gb_bundles_init(intf, management->link_up.device_id); + ret = gb_interface_init(intf, management->link_up.device_id); if (ret) { dev_err(hd->parent, - "error %d initializing bundles for interface %hhu\n", + "error %d initializing interface %hhu\n", ret, management->link_up.interface_id); return; } @@ -175,8 +175,7 @@ static void svc_hotplug(struct svc_function_hotplug *hotplug, return; } dev_dbg(hd->parent, "interface id %d added\n", interface_id); - gb_interface_add(hd, interface_id, hotplug->data, - payload_length - 0x02); + gb_interface_create(hd, interface_id); break; case SVC_HOTUNPLUG_EVENT: diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 8d0e86f..a5172e5 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -230,6 +230,10 @@ int gb_bundle_init(struct gb_bundle *bundle, u8 device_id) struct gb_interface *intf = bundle->intf; int ret; + /* Don't reinitialize control cport's bundle */ + if (intf->control && bundle->id == GB_CONTROL_BUNDLE_ID) + return 0; + bundle->device_id = device_id; ret = svc_set_route_send(bundle, intf->hd); diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 5b1621c..901c4ac 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -67,6 +67,36 @@ struct device_type greybus_interface_type = { }; /* + * Create kernel structures corresponding to a bundle and connection for + * managing control CPort. Also initialize the bundle, which will request SVC to + * set route and will initialize the control protocol for this connection. + */ +static int gb_create_control_connection(struct gb_interface *intf, u8 device_id) +{ + struct gb_bundle *bundle; + int ret; + + bundle = gb_bundle_create(intf, GB_CONTROL_BUNDLE_ID, + GREYBUS_CLASS_CONTROL); + if (!bundle) + return -EINVAL; + + if (!gb_connection_create(bundle, GB_CONTROL_CPORT_ID, + GREYBUS_PROTOCOL_CONTROL)) + return -EINVAL; + + ret = gb_bundle_init(bundle, device_id); + if (ret) { + dev_err(&intf->dev, + "error %d initializing bundles for interface %hu\n", + ret, intf->interface_id); + return ret; + } + + return 0; +} + +/* * A Greybus module represents a user-replicable component on an Ara * phone. An interface is the physical connection on that module. A * module may have more than one interface. @@ -78,8 +108,8 @@ struct device_type greybus_interface_type = { * Returns a pointer to the new interfce or a null pointer if a * failure occurs due to memory exhaustion. */ -static struct gb_interface *gb_interface_create(struct greybus_host_device *hd, - u8 interface_id) +struct gb_interface *gb_interface_create(struct greybus_host_device *hd, + u8 interface_id) { struct gb_module *module; struct gb_interface *intf; @@ -165,29 +195,60 @@ static void gb_interface_destroy(struct gb_interface *intf) /** * gb_interface_add * - * Pass in a buffer that _should_ contain a Greybus manifest - * and register a greybus device structure with the kernel core. + * Create connection for control CPort and then request/parse manifest. + * Finally initialize all the bundles to set routes via SVC and initialize all + * connections. */ -void gb_interface_add(struct greybus_host_device *hd, u8 interface_id, u8 *data, - int size) +int gb_interface_init(struct gb_interface *intf, u8 device_id) { - struct gb_interface *intf; + int ret, size; + void *manifest; + + /* Establish control CPort connection */ + ret = gb_create_control_connection(intf, device_id); + if (ret) { + dev_err(&intf->dev, "Failed to create control CPort connection (%d)\n", ret); + return ret; + } - intf = gb_interface_create(hd, interface_id); - if (!intf) { - dev_err(hd->parent, "failed to create interface\n"); - return; + /* Get manifest size using control protocol on CPort */ + size = gb_control_get_manifest_size_operation(intf); + if (size <= 0) { + dev_err(&intf->dev, "%s: Failed to get manifest size (%d)\n", + __func__, size); + if (size) + return size; + else + return -EINVAL; + } + + manifest = kmalloc(size, GFP_KERNEL); + if (!manifest) + return -ENOMEM; + + /* Get manifest using control protocol on CPort */ + ret = gb_control_get_manifest_operation(intf, manifest, size); + if (ret) { + dev_err(&intf->dev, "%s: Failed to get manifest\n", __func__); + goto free_manifest; } /* - * Parse the manifest and build up our data structures - * representing what's in it. + * Parse the manifest and build up our data structures representing + * what's in it. */ - if (!gb_manifest_parse(intf, data, size)) { - dev_err(hd->parent, "manifest error\n"); - goto err_parse; + if (!gb_manifest_parse(intf, manifest, size)) { + dev_err(&intf->dev, "%s: Failed to parse manifest\n", __func__); + ret = -EINVAL; + goto free_manifest; } + ret = gb_bundles_init(intf, device_id); + if (ret) + dev_err(&intf->dev, + "Error %d initializing bundles for interface %hu\n", + ret, intf->interface_id); + /* * XXX * We've successfully parsed the manifest. Now we need to @@ -197,10 +258,9 @@ void gb_interface_add(struct greybus_host_device *hd, u8 interface_id, u8 *data, * configuring the switch to allow them to communicate). */ - return; - -err_parse: - gb_interface_destroy(intf); +free_manifest: + kfree(manifest); + return ret; } void gb_interface_remove(struct greybus_host_device *hd, u8 interface_id) diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 9c566b2..90dbff1 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -48,8 +48,9 @@ static inline void *gb_interface_get_drvdata(struct gb_interface *intf) struct gb_interface *gb_interface_find(struct greybus_host_device *hd, u8 interface_id); -void gb_interface_add(struct greybus_host_device *hd, u8 interface_id, u8 *data, - int size); +struct gb_interface *gb_interface_create(struct greybus_host_device *hd, + u8 interface_id); +int gb_interface_init(struct gb_interface *intf, u8 device_id); void gb_interface_remove(struct greybus_host_device *hd, u8 interface_id); void gb_interfaces_remove(struct greybus_host_device *hd); diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 377c449..bd5753f 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -225,11 +225,17 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) if (cport_id > CPORT_ID_MAX) goto cleanup; + /* Don't recreate connection for control cport */ + if (cport_id == GB_CONTROL_CPORT_ID) + goto release_descriptor; + /* Found one. Set up its function structure */ protocol_id = desc_cport->protocol_id; + if (!gb_connection_create(bundle, cport_id, protocol_id)) goto cleanup; +release_descriptor: count++; /* Release the cport descriptor */ @@ -268,11 +274,19 @@ static u32 gb_manifest_parse_bundles(struct gb_interface *intf) /* Found one. Set up its bundle structure*/ desc_bundle = desc->data; + + /* Don't recreate bundle for control cport */ + if (desc_bundle->id == GB_CONTROL_BUNDLE_ID) { + bundle = intf->control->connection->bundle; + goto parse_cports; + } + bundle = gb_bundle_create(intf, desc_bundle->id, desc_bundle->class); if (!bundle) goto cleanup; +parse_cports: /* Now go set up this bundle's functions and cports */ if (!gb_manifest_parse_cports(bundle)) goto cleanup; -- cgit v0.10.2 From 87c8eb8d09387de7263a7c2c75536db4aa50e056 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 22 Jun 2015 16:42:28 +0530 Subject: greybus: hotplug function doesn't need to contain manifest now Manifest is fetched with control protocol now and so we don't need space for it in hotplug data. Reviewed-by: Alex Elder Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 113fd87..869f934 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -167,8 +167,7 @@ static void svc_hotplug(struct svc_function_hotplug *hotplug, switch (hotplug->hotplug_event) { case SVC_HOTPLUG_EVENT: /* Add a new interface to the system */ - if (payload_length < 0x03) { - /* Hotplug message is at least 3 bytes big */ + if (payload_length != sizeof(*hotplug)) { dev_err(hd->parent, "Illegal size of svc hotplug message %d\n", payload_length); @@ -180,8 +179,7 @@ static void svc_hotplug(struct svc_function_hotplug *hotplug, case SVC_HOTUNPLUG_EVENT: /* Remove a interface from the system */ - if (payload_length != 0x02) { - /* Hotunplug message is only 2 bytes big */ + if (payload_length != sizeof(*hotplug)) { dev_err(hd->parent, "Illegal size of svc hotunplug message %d\n", payload_length); diff --git a/drivers/staging/greybus/svc_msg.h b/drivers/staging/greybus/svc_msg.h index fadc1d7..3c628c5 100644 --- a/drivers/staging/greybus/svc_msg.h +++ b/drivers/staging/greybus/svc_msg.h @@ -82,7 +82,6 @@ enum svc_function_hotplug_event { struct svc_function_hotplug { __u8 hotplug_event; /* enum svc_function_hotplug_event */ __u8 interface_id; /* Interface id within the Endo */ - __u8 data[0]; } __packed; enum svc_function_power_type { -- cgit v0.10.2 From f18327e8ebf4738140e9b33a2de99bb8e526a269 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 22 Jun 2015 16:42:29 +0530 Subject: greybus: connection: send [dis]connected events over control CPort The AP needs to send connected and disconnection events to all interfaces, before a CPort (other than control CPort) can be used. For now do it which we initialize the connection, but it should be moved to operations code later. Reviewed-by: Alex Elder Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 9467aab..564011a 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -248,6 +248,7 @@ void gb_connection_destroy(struct gb_connection *connection) int gb_connection_init(struct gb_connection *connection) { + int cport_id = connection->intf_cport_id; int ret; if (!connection->protocol) { @@ -255,6 +256,22 @@ int gb_connection_init(struct gb_connection *connection) return 0; } + /* + * Inform Interface about Active CPorts. We don't need to do this + * operation for control cport. + */ + if (cport_id != GB_CONTROL_CPORT_ID) { + struct gb_control *control = connection->bundle->intf->control; + + ret = gb_control_connected_operation(control, cport_id); + if (ret) { + dev_warn(&connection->dev, + "Failed to connect CPort-%d (%d)\n", + cport_id, ret); + return 0; + } + } + /* Need to enable the connection to initialize it */ connection->state = GB_CONNECTION_STATE_ENABLED; ret = connection->protocol->connection_init(connection); @@ -266,6 +283,8 @@ int gb_connection_init(struct gb_connection *connection) void gb_connection_exit(struct gb_connection *connection) { + int cport_id = connection->intf_cport_id; + if (!connection->protocol) { dev_warn(&connection->dev, "exit without protocol.\n"); return; @@ -276,4 +295,19 @@ void gb_connection_exit(struct gb_connection *connection) connection->state = GB_CONNECTION_STATE_DESTROYING; connection->protocol->connection_exit(connection); + + /* + * Inform Interface about In-active CPorts. We don't need to do this + * operation for control cport. + */ + if (cport_id != GB_CONTROL_CPORT_ID) { + struct gb_control *control = connection->bundle->intf->control; + int ret; + + ret = gb_control_disconnected_operation(control, cport_id); + if (ret) + dev_warn(&connection->dev, + "Failed to disconnect CPort-%d (%d)\n", + cport_id, ret); + } } -- cgit v0.10.2 From 730a2f6d1066e7771d5b85b8e9ec5ed09b153d01 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 22 Jun 2015 16:42:30 +0530 Subject: greybus: control: Warn if non-control cport/bundles have control protocol/classes It is possible that (by mistake) the manifest contains non-control cports with their protocol set as control-protocol or non-control bundle with their class set as control-class. Catch such cases, WARN for them and finally ignore them. Also WARN if the control cport doesn't have its protocol as control-protocol and control bundle doesn't have its class as control-class. Reviewed-by: Alex Elder Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index bd5753f..ce4e89c 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -225,12 +225,20 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) if (cport_id > CPORT_ID_MAX) goto cleanup; + /* Found one. Set up its function structure */ + protocol_id = desc_cport->protocol_id; + /* Don't recreate connection for control cport */ - if (cport_id == GB_CONTROL_CPORT_ID) + if (cport_id == GB_CONTROL_CPORT_ID) { + /* This should have protocol set to control protocol*/ + WARN_ON(protocol_id != GREYBUS_PROTOCOL_CONTROL); + goto release_descriptor; + } - /* Found one. Set up its function structure */ - protocol_id = desc_cport->protocol_id; + /* Nothing else should have its protocol as control protocol */ + if (WARN_ON(protocol_id == GREYBUS_PROTOCOL_CONTROL)) + goto release_descriptor; if (!gb_connection_create(bundle, cport_id, protocol_id)) goto cleanup; @@ -277,10 +285,17 @@ static u32 gb_manifest_parse_bundles(struct gb_interface *intf) /* Don't recreate bundle for control cport */ if (desc_bundle->id == GB_CONTROL_BUNDLE_ID) { + /* This should have class set to control class */ + WARN_ON(desc_bundle->class != GREYBUS_CLASS_CONTROL); + bundle = intf->control->connection->bundle; goto parse_cports; } + /* Nothing else should have its class set to control class */ + if (WARN_ON(desc_bundle->class == GREYBUS_CLASS_CONTROL)) + goto release_descriptor; + bundle = gb_bundle_create(intf, desc_bundle->id, desc_bundle->class); if (!bundle) @@ -291,6 +306,7 @@ parse_cports: if (!gb_manifest_parse_cports(bundle)) goto cleanup; +release_descriptor: count++; /* Done with this bundle descriptor */ -- cgit v0.10.2 From 5656ab99a0ff9136613ab1da509ccd6d7652d173 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Wed, 24 Jun 2015 23:20:26 +0100 Subject: greybus: sdio: fix defines for older kernels Some of the options for mmc host, are not defined in older kernels. MMC_CAP2_HS400_1_2V, MMC_CAP2_HS400_1_8V, MMC_TIMING_MMC_DDR52 and MMC_TIMING_MMC_HS400. To not use them for older versions. Signed-off-by: Rui Miguel Silva Tested-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index 8b8e712..f95f302 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -127,4 +127,12 @@ static inline void sysfs_remove_groups(struct kobject *kobj, } #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) +#define MMC_HS400_SUPPORTED +#define MMC_DDR52_DEFINED +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0) +#define MMC_POWER_UNDEFINED_SUPPORTED +#endif #endif /* __GREYBUS_KERNEL_VER_H */ diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index 1fd17c8..16abf7c 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -62,9 +62,11 @@ static void _gb_sdio_set_host_caps(struct gb_sdio_host *host, u32 r) (r & GB_SDIO_CAP_DRIVER_TYPE_D ? MMC_CAP_DRIVER_TYPE_D : 0); caps2 = (r & GB_SDIO_CAP_HS200_1_2V ? MMC_CAP2_HS200_1_2V_SDR : 0) | - (r & GB_SDIO_CAP_HS200_1_8V ? MMC_CAP2_HS200_1_8V_SDR : 0) | +#ifdef MMC_HS400_SUPPORTED (r & GB_SDIO_CAP_HS400_1_2V ? MMC_CAP2_HS400_1_2V : 0) | - (r & GB_SDIO_CAP_HS400_1_8V ? MMC_CAP2_HS400_1_8V : 0); + (r & GB_SDIO_CAP_HS400_1_8V ? MMC_CAP2_HS400_1_8V : 0) | +#endif + (r & GB_SDIO_CAP_HS200_1_8V ? MMC_CAP2_HS200_1_8V_SDR : 0); host->mmc->caps = caps; host->mmc->caps2 = caps2; @@ -478,6 +480,7 @@ static void gb_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) switch (ios->power_mode) { case MMC_POWER_OFF: + default: power_mode = GB_SDIO_POWER_OFF; break; case MMC_POWER_UP: @@ -486,10 +489,11 @@ static void gb_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) case MMC_POWER_ON: power_mode = GB_SDIO_POWER_ON; break; +#ifdef MMC_POWER_UNDEFINED_SUPPORTED case MMC_POWER_UNDEFINED: - default: power_mode = GB_SDIO_POWER_UNDEFINED; break; +#endif } request.power_mode = power_mode; @@ -533,15 +537,19 @@ static void gb_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) case MMC_TIMING_UHS_DDR50: timing = GB_SDIO_TIMING_UHS_DDR50; break; +#ifdef MMC_DDR52_DEFINED case MMC_TIMING_MMC_DDR52: timing = GB_SDIO_TIMING_MMC_DDR52; break; +#endif case MMC_TIMING_MMC_HS200: timing = GB_SDIO_TIMING_MMC_HS200; break; +#ifdef MMC_HS400_SUPPORTED case MMC_TIMING_MMC_HS400: timing = GB_SDIO_TIMING_MMC_HS400; break; +#endif } request.timing = timing; -- cgit v0.10.2 From 8a01b408a6b071862efadf905bad60d10612e78a Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Wed, 24 Jun 2015 23:20:27 +0100 Subject: greybus: kernel_ver: add sg copy operations for kernel < 3.11 For older kernel, < 3.11, no copy to/from buffer with skip support was defined. This could break builds for this versions of kernel. Add them here. Signed-off-by: Rui Miguel Silva Tested-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index f95f302..4fb949b 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -135,4 +135,104 @@ static inline void sysfs_remove_groups(struct kobject *kobj, #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0) #define MMC_POWER_UNDEFINED_SUPPORTED #endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) +#include +static inline bool sg_miter_get_next_page(struct sg_mapping_iter *miter) +{ + if (!miter->__remaining) { + struct scatterlist *sg; + unsigned long pgoffset; + + if (!__sg_page_iter_next(&miter->piter)) + return false; + + sg = miter->piter.sg; + pgoffset = miter->piter.sg_pgoffset; + + miter->__offset = pgoffset ? 0 : sg->offset; + miter->__remaining = sg->offset + sg->length - + (pgoffset << PAGE_SHIFT) - miter->__offset; + miter->__remaining = min_t(unsigned long, miter->__remaining, + PAGE_SIZE - miter->__offset); + } + + return true; +} + +static inline bool sg_miter_skip(struct sg_mapping_iter *miter, off_t offset) +{ + sg_miter_stop(miter); + + while (offset) { + off_t consumed; + + if (!sg_miter_get_next_page(miter)) + return false; + + consumed = min_t(off_t, offset, miter->__remaining); + miter->__offset += consumed; + miter->__remaining -= consumed; + offset -= consumed; + } + + return true; +} + +static inline size_t _sg_copy_buffer(struct scatterlist *sgl, + unsigned int nents, void *buf, + size_t buflen, off_t skip, + bool to_buffer) +{ + unsigned int offset = 0; + struct sg_mapping_iter miter; + unsigned long flags; + unsigned int sg_flags = SG_MITER_ATOMIC; + + if (to_buffer) + sg_flags |= SG_MITER_FROM_SG; + else + sg_flags |= SG_MITER_TO_SG; + + sg_miter_start(&miter, sgl, nents, sg_flags); + + if (!sg_miter_skip(&miter, skip)) + return false; + + local_irq_save(flags); + + while (sg_miter_next(&miter) && offset < buflen) { + unsigned int len; + + len = min(miter.length, buflen - offset); + + if (to_buffer) + memcpy(buf + offset, miter.addr, len); + else + memcpy(miter.addr, buf + offset, len); + + offset += len; + } + + sg_miter_stop(&miter); + + local_irq_restore(flags); + return offset; +} + +static inline size_t sg_pcopy_to_buffer(struct scatterlist *sgl, + unsigned int nents, void *buf, + size_t buflen, off_t skip) +{ + return _sg_copy_buffer(sgl, nents, buf, buflen, skip, true); +} + +static inline size_t sg_pcopy_from_buffer(struct scatterlist *sgl, + unsigned int nents, void *buf, + size_t buflen, off_t skip) +{ + return _sg_copy_buffer(sgl, nents, buf, buflen, skip, false); +} +#endif + #endif /* __GREYBUS_KERNEL_VER_H */ -- cgit v0.10.2 From 86f918ee7f941c383ee32ad28dca6e48a04b6074 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 23 Jun 2015 14:17:41 +0200 Subject: greybus: esx: fix null-deref on hotplug events We must be prepared to receive hotplug events as soon as we submit the SVC URB. Since commit 2eb8a6a947d7 ("core: don't set up endo until host device is initialized") this is no longer the case as the endo would not have been setup, something which may lead to a null-pointer dereference in endo_get_module_id() when the interface is created (see oops below with an added dev_dbg for hd->endo). Fix this by setting up the endo before submitting the SVC URB. [ 28.810610] gb_interface_create - hd->endo = (null) [ 28.816020] Unable to handle kernel NULL pointer dereference at virtual address 0000022b [ 28.824952] pgd = c0004000 [ 28.827880] [0000022b] *pgd=00000000 [ 28.831913] Internal error: Oops: 17 [#1] PREEMPT ARM [ 28.837183] Modules linked in: gb_es1(O+) greybus(O) netconsole [ 28.843419] CPU: 0 PID: 21 Comm: kworker/u2:1 Tainted: G O 4.1.0-rc7 #12 [ 28.851576] Hardware name: Generic AM33XX (Flattened Device Tree) [ 28.857978] Workqueue: greybus_ap ap_process_event [greybus] [ 28.863890] task: cf2961c0 ti: cf29c000 task.ti: cf29c000 [ 28.869529] PC is at endo_get_module_id+0x18/0x88 [greybus] [ 28.875355] LR is at gb_interface_add+0x88/0x204 [greybus] [ 28.881070] pc : [] lr : [] psr: 20070013 [ 28.881070] sp : cf29de08 ip : cf29de18 fp : cf29de14 [ 28.893021] r10: 00000001 r9 : 0000005a r8 : cd813ec6 [ 28.898461] r7 : 00000058 r6 : cf7fa200 r5 : 00000001 r4 : cf7fa20c [ 28.905261] r3 : 00000000 r2 : cf2961c0 r1 : 00000001 r0 : 00000000 [ 28.912067] Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel [ 28.919677] Control: 10c5387d Table: 8f508019 DAC: 00000015 [ 28.925663] Process kworker/u2:1 (pid: 21, stack limit = 0xcf29c210) [ 28.932279] Stack: (0xcf29de08 to 0xcf29e000) [ 28.936823] de00: cf29de44 cf29de18 bf005dac bf0052c8 00000058 cd813ec0 [ 28.945349] de20: cf58b60c bf00afe0 cf7fa200 cf58b600 0000005a 00000001 cf29de84 cf29de48 [ 28.953865] de40: bf004844 bf005d30 00000000 cf02d800 cf29de6c cf29de60 c00759a0 cf58b60c [ 28.962389] de60: cf2742c0 cf02d800 cf0c6000 cf29dea8 c07b745c 00000000 cf29dee4 cf29de88 [ 28.970908] de80: c005943c bf004560 00000001 00000000 c0059354 cf02d800 c0059c0c 00000001 [ 28.979426] dea0: 00000000 00000000 bf00b314 00000000 00000000 bf009144 c04e3710 cf02d800 [ 28.987945] dec0: cf2742d8 cf02d830 00000088 c0059bd0 00000000 cf2742c0 cf29df24 cf29dee8 [ 28.996464] dee0: c0059b78 c0059248 cf29c000 cf245d40 c0776890 c07b6bf3 00000000 00000000 [ 29.004983] df00: cf245d40 cf2742c0 c0059b20 00000000 00000000 00000000 cf29dfac cf29df28 [ 29.013502] df20: c005fe90 c0059b2c c07812d0 00000000 cf29df4c cf2742c0 00000000 00000001 [ 29.022025] df40: dead4ead ffffffff ffffffff c07c86b0 00000000 00000000 c05fd8e8 cf29df5c [ 29.030542] df60: cf29df5c 00000000 00000001 dead4ead ffffffff ffffffff c07c86b0 00000000 [ 29.039062] df80: 00000000 c05fd8e8 cf29df88 cf29df88 cf245d40 c005fd98 00000000 00000000 [ 29.047581] dfa0: 00000000 cf29dfb0 c00108f8 c005fda4 00000000 00000000 00000000 00000000 [ 29.056105] dfc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 [ 29.064623] dfe0: 00000000 00000000 00000000 00000000 00000013 00000000 ffff0000 ffff0000 [ 29.073178] [] (endo_get_module_id [greybus]) from [] (gb_interface_add+0x88/0x204 [greybus]) [ 29.083887] [] (gb_interface_add [greybus]) from [] (ap_process_event+0x2f0/0x4d8 [greybus]) [ 29.094527] [] (ap_process_event [greybus]) from [] (process_one_work+0x200/0x8e4) [ 29.104228] [] (process_one_work) from [] (worker_thread+0x58/0x500) [ 29.112668] [] (worker_thread) from [] (kthread+0xf8/0x110) [ 29.120295] [] (kthread) from [] (ret_from_fork+0x14/0x3c) [ 29.127825] Code: e24cb004 e52de004 e8bd4000 e3510000 (e5d0c22b) [ 29.137481] ---[ end trace ad95c3c26bdc98ce ]--- Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index f9a6c54c..067b4c1 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -679,16 +679,6 @@ static int ap_probe(struct usb_interface *interface, es1->cport_out_urb_busy[i] = false; /* just to be anal */ } - /* Start up our svc urb, which allows events to start flowing */ - retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); - if (retval) - goto error; - - apb1_log_enable_dentry = debugfs_create_file("apb1_log_enable", - (S_IWUSR | S_IRUGO), - gb_debugfs_get(), es1, - &apb1_log_enable_fops); - /* * XXX Soon this will be initiated later, with a combination * XXX of a Control protocol probe operation and a @@ -700,6 +690,15 @@ static int ap_probe(struct usb_interface *interface, if (retval) goto error; + /* Start up our svc urb, which allows events to start flowing */ + retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); + if (retval) + goto error; + + apb1_log_enable_dentry = debugfs_create_file("apb1_log_enable", + (S_IWUSR | S_IRUGO), + gb_debugfs_get(), es1, + &apb1_log_enable_fops); return 0; error: ap_disconnect(interface); diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 274d1d4..97fa2e0 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -783,16 +783,6 @@ static int ap_probe(struct usb_interface *interface, es1->cport_out_urb_busy[i] = false; /* just to be anal */ } - /* Start up our svc urb, which allows events to start flowing */ - retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); - if (retval) - goto error; - - apb1_log_enable_dentry = debugfs_create_file("apb1_log_enable", - (S_IWUSR | S_IRUGO), - gb_debugfs_get(), es1, - &apb1_log_enable_fops); - /* * XXX Soon this will be initiated later, with a combination * XXX of a Control protocol probe operation and a @@ -804,6 +794,15 @@ static int ap_probe(struct usb_interface *interface, if (retval) goto error; + /* Start up our svc urb, which allows events to start flowing */ + retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); + if (retval) + goto error; + + apb1_log_enable_dentry = debugfs_create_file("apb1_log_enable", + (S_IWUSR | S_IRUGO), + gb_debugfs_get(), es1, + &apb1_log_enable_fops); return 0; error: ap_disconnect(interface); -- cgit v0.10.2 From f4706b848ec6c58f797604112d30272db8d5e8dd Mon Sep 17 00:00:00 2001 From: Mark Greer Date: Fri, 26 Jun 2015 16:38:46 -0700 Subject: greybus: gb-audio: Ensure i2c adapter struct exists before using The current audio code uses i2c_get_adapter() without checking that a non-NULL pointer is returned (i.e., that the i2c device actually exists). When that happens, the system panics. Fix the potential panic by erroring out with -ENODEV when i2c_get_adapter() returns NULL. CC: John Stultz Signed-off-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio.c b/drivers/staging/greybus/audio.c index a077c2b..9f5f959 100644 --- a/drivers/staging/greybus/audio.c +++ b/drivers/staging/greybus/audio.c @@ -167,6 +167,7 @@ static int gb_i2s_transmitter_connection_init(struct gb_connection *connection) struct asoc_simple_card_info *simple_card; #if USE_RT5645 struct i2c_board_info rt5647_info; + struct i2c_adapter *i2c_adap; #endif unsigned long flags; int ret; @@ -234,8 +235,14 @@ static int gb_i2s_transmitter_connection_init(struct gb_connection *connection) rt5647_info.addr = RT5647_I2C_ADDR; strlcpy(rt5647_info.type, "rt5647", I2C_NAME_SIZE); - snd_dev->rt5647 = i2c_new_device(i2c_get_adapter(RT5647_I2C_ADAPTER_NR), - &rt5647_info); + i2c_adap = i2c_get_adapter(RT5647_I2C_ADAPTER_NR); + if (!i2c_adap) { + pr_err("codec unavailable\n"); + ret = -ENODEV; + goto out_get_ver; + } + + snd_dev->rt5647 = i2c_new_device(i2c_adap, &rt5647_info); if (!snd_dev->rt5647) { pr_err("can't create rt5647 i2c device\n"); goto out_get_ver; -- cgit v0.10.2 From 153f4784b428b3b5ef9d43ab9f8fa5322bc3717c Mon Sep 17 00:00:00 2001 From: Phong Tran Date: Fri, 26 Jun 2015 21:05:11 +0700 Subject: greybus: sdio: remove the redefine of sdio major and minor The macro of sdio version major and minor is defined twice. This patch remove the redundant one. Signed-off-by: Phong Tran Reviewed-by: Rui Miguel Silva Reviewed-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 9f9b722..83f8dc2 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -660,10 +660,6 @@ struct gb_uart_serial_state_request { #define GB_SDIO_VERSION_MAJOR 0x00 #define GB_SDIO_VERSION_MINOR 0x01 -/* Version of the Greybus SDIO protocol we support */ -#define GB_SDIO_VERSION_MAJOR 0x00 -#define GB_SDIO_VERSION_MINOR 0x01 - /* Greybus SDIO operation types */ #define GB_SDIO_TYPE_INVALID 0x00 #define GB_SDIO_TYPE_PROTOCOL_VERSION 0x01 -- cgit v0.10.2 From 9b86bdf96ef79e5e286628cb2e3ea6639db71904 Mon Sep 17 00:00:00 2001 From: Phong Tran Date: Fri, 26 Jun 2015 21:05:12 +0700 Subject: greybus: sdio: change the order of remove and free mmc host The mmc host should be removed frist. Then it will be freed. Signed-off-by: Phong Tran Reviewed-by: Rui Miguel Silva Reviewed-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index 16abf7c..cf12592 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -700,8 +700,8 @@ static void gb_sdio_connection_exit(struct gb_connection *connection) flush_workqueue(gb_sdio_mrq_workqueue); destroy_workqueue(gb_sdio_mrq_workqueue); - mmc_free_host(mmc); mmc_remove_host(mmc); + mmc_free_host(mmc); kfree(host->xfer_buffer); } -- cgit v0.10.2 From 93a99e8a105aeaec432995196c21ffedcd0c0cad Mon Sep 17 00:00:00 2001 From: Phong Tran Date: Fri, 26 Jun 2015 21:05:13 +0700 Subject: greybus: sdio: correct the usage of mmc request in work queues handler The mmc request should assigned before use. Then It should avoid freeing before using in mmc_request_done(). Signed-off-by: Phong Tran Reviewed-by: Rui Miguel Silva Reviewed-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index cf12592..30ebd42 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -387,13 +387,18 @@ static void gb_sdio_mrq_work(struct work_struct *work) host = container_of(work, struct gb_sdio_host, mrqwork); mutex_lock(&host->lock); + mrq = host->mrq; + if (!mrq) { + mutex_unlock(&host->lock); + dev_err(mmc_dev(host->mmc), "mmc request is NULL"); + return; + } + if (host->removed) { mrq->cmd->error = -ESHUTDOWN; goto done; } - mrq = host->mrq; - if (mrq->sbc) { ret = gb_sdio_command(host, mrq->sbc); if (ret < 0) @@ -417,7 +422,7 @@ static void gb_sdio_mrq_work(struct work_struct *work) } done: - mrq = NULL; + host->mrq = NULL; mutex_unlock(&host->lock); mmc_request_done(host->mmc, mrq); } -- cgit v0.10.2 From dccbe40ff97ac24ad8e99486df1cc2143bb99ff7 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 30 Jun 2015 11:40:18 +0530 Subject: greybus: define more greybus classes There are new protocols defined which don't belong to any existing class, add more classes to support them. Reported-by: Alexandre Bailon Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index d6175ce..f84cfeb 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -64,6 +64,9 @@ enum greybus_class_type { GREYBUS_CLASS_DISPLAY = 0x0c, GREYBUS_CLASS_CAMERA = 0x0d, GREYBUS_CLASS_SENSOR = 0x0e, + GREYBUS_CLASS_LIGHTS = 0x0f, + GREYBUS_CLASS_VIBRATOR = 0x10, + GREYBUS_CLASS_LOOPBACK = 0x11, GREYBUS_CLASS_VENDOR = 0xff, }; -- cgit v0.10.2 From 802362d4a621a03b394b3082b40e5471bf5268ad Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 29 Jun 2015 18:09:13 +0100 Subject: greybus: uart: Relocate UART parity/overrun/framing/break signals Parity/overrun/framing and break signals have been moved to the receive-data message to more easily associate the signals with the TTY API. Update the definitions in the protocol header and add a flags field to the receive-data structure to facilitate transmission of those signal with the receive-data message. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 83f8dc2..44522b0 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -606,9 +606,16 @@ struct gb_uart_send_data_request { __u8 data[0]; }; +/* recv-data-request flags */ +#define GB_UART_RECV_FLAG_FRAMING 0x01 /* Framing error */ +#define GB_UART_RECV_FLAG_PARITY 0x02 /* Parity error */ +#define GB_UART_RECV_FLAG_OVERRUN 0x04 /* Overrun error */ +#define GB_UART_RECV_FLAG_BREAK 0x08 /* Break */ + /* Represents data from Module -> AP */ struct gb_uart_recv_data_request { __le16 size; + __u8 flags; __u8 data[0]; }; @@ -644,12 +651,7 @@ struct gb_uart_set_break_request { /* input control lines and line errors */ #define GB_UART_CTRL_DCD 0x01 #define GB_UART_CTRL_DSR 0x02 -#define GB_UART_CTRL_BRK 0x04 -#define GB_UART_CTRL_RI 0x08 - -#define GB_UART_CTRL_FRAMING 0x10 -#define GB_UART_CTRL_PARITY 0x20 -#define GB_UART_CTRL_OVERRUN 0x40 +#define GB_UART_CTRL_RI 0x04 struct gb_uart_serial_state_request { __le16 control; -- cgit v0.10.2 From 4c025cf4168fe679b8a56eed210349458a142d07 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 29 Jun 2015 18:09:14 +0100 Subject: greybus: uart: Add support for UART error signals After reviewing the UART specification for greybus break, parity, framing and over-run errors were moved to the receive-data message. This patch implements that specification change in the UART protocol driver. Matching code in gbsim has been tested with this change. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 3b06cd4..73e3c99 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -70,35 +70,56 @@ static atomic_t reference_count = ATOMIC_INIT(0); /* Define get_version() routine */ define_get_version(gb_tty, UART); +static int gb_uart_receive_data(struct gb_tty *gb_tty, + struct gb_connection *connection, + struct gb_uart_recv_data_request *receive_data) +{ + struct tty_port *port = &gb_tty->port; + u16 recv_data_size; + int count; + unsigned long tty_flags = TTY_NORMAL; + + count = gb_tty->buffer_payload_max - sizeof(*receive_data); + recv_data_size = le16_to_cpu(receive_data->size); + if (!recv_data_size || recv_data_size > count) + return -EINVAL; + + if (receive_data->flags) { + if (receive_data->flags & GB_UART_RECV_FLAG_BREAK) + tty_flags = TTY_BREAK; + else if (receive_data->flags & GB_UART_RECV_FLAG_PARITY) + tty_flags = TTY_PARITY; + else if (receive_data->flags & GB_UART_RECV_FLAG_FRAMING) + tty_flags = TTY_FRAME; + + /* overrun is special, not associated with a char */ + if (receive_data->flags & GB_UART_RECV_FLAG_OVERRUN) + tty_insert_flip_char(port, 0, TTY_OVERRUN); + } + count = tty_insert_flip_string_fixed_flag(port, receive_data->data, + tty_flags, recv_data_size); + if (count != recv_data_size) { + dev_err(&connection->dev, + "UART: RX 0x%08x bytes only wrote 0x%08x\n", + recv_data_size, count); + } + if (count) + tty_flip_buffer_push(port); + return 0; +} + static int gb_uart_request_recv(u8 type, struct gb_operation *op) { struct gb_connection *connection = op->connection; struct gb_tty *gb_tty = connection->private; struct gb_message *request = op->request; - struct gb_uart_recv_data_request *receive_data; struct gb_uart_serial_state_request *serial_state; - struct tty_port *port = &gb_tty->port; - u16 recv_data_size; - int count; int ret = 0; switch (type) { case GB_UART_TYPE_RECEIVE_DATA: - receive_data = request->payload; - count = gb_tty->buffer_payload_max - sizeof(*receive_data); - recv_data_size = le16_to_cpu(receive_data->size); - if (!recv_data_size || recv_data_size > count) - return -EINVAL; - - count = tty_insert_flip_string(port, receive_data->data, - recv_data_size); - if (count != recv_data_size) { - dev_err(&connection->dev, - "UART: RX 0x%08x bytes only wrote 0x%08x\n", - recv_data_size, count); - } - if (count) - tty_flip_buffer_push(port); + ret = gb_uart_receive_data(gb_tty, connection, + request->payload); break; case GB_UART_TYPE_SERIAL_STATE: serial_state = request->payload; -- cgit v0.10.2 From ba4b099ca8e30b064d06bf9fc3f1a2bbcb8e1818 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 29 Jun 2015 18:09:15 +0100 Subject: greybus: uart: Update UART to reflect field size changes The greybus UART protocol specification was updated to reduce the size of the control field in serial-state-request and line-state-request. This patch updates the kernel protocol driver to reflect the specification changes. Once applied gbsim changes will be also be updated automatically since gbsim depends on the header being modified directly. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 44522b0..6f8c15e 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -641,7 +641,7 @@ struct gb_uart_set_line_coding_request { #define GB_UART_CTRL_RTS 0x02 struct gb_uart_set_control_line_state_request { - __le16 control; + __u8 control; }; struct gb_uart_set_break_request { @@ -654,7 +654,7 @@ struct gb_uart_set_break_request { #define GB_UART_CTRL_RI 0x04 struct gb_uart_serial_state_request { - __le16 control; + __u8 control; }; /* SDIO */ diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 73e3c99..7abcd1c 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -57,8 +57,8 @@ struct gb_tty { struct mutex mutex; u8 version_major; u8 version_minor; - unsigned int ctrlin; /* input control lines */ - unsigned int ctrlout; /* output control lines */ + u8 ctrlin; /* input control lines */ + u8 ctrlout; /* output control lines */ struct gb_tty_line_coding line_coding; }; @@ -123,7 +123,7 @@ static int gb_uart_request_recv(u8 type, struct gb_operation *op) break; case GB_UART_TYPE_SERIAL_STATE: serial_state = request->payload; - gb_tty->ctrlin = le16_to_cpu(serial_state->control); + gb_tty->ctrlin = serial_state->control; break; default: dev_err(&connection->dev, @@ -165,11 +165,11 @@ static int send_line_coding(struct gb_tty *tty) &request, sizeof(request), NULL, 0); } -static int send_control(struct gb_tty *gb_tty, u16 control) +static int send_control(struct gb_tty *gb_tty, u8 control) { struct gb_uart_set_control_line_state_request request; - request.control = cpu_to_le16(control); + request.control = control; return gb_operation_sync(gb_tty->connection, GB_UART_TYPE_SET_CONTROL_LINE_STATE, &request, sizeof(request), NULL, 0); @@ -314,7 +314,7 @@ static void gb_tty_set_termios(struct tty_struct *tty, struct gb_tty *gb_tty = tty->driver_data; struct ktermios *termios = &tty->termios; struct gb_tty_line_coding newline; - int newctrl = gb_tty->ctrlout; + u8 newctrl = gb_tty->ctrlout; newline.rate = cpu_to_le32(tty_get_baud_rate(tty)); newline.format = termios->c_cflag & CSTOPB ? @@ -376,7 +376,7 @@ static int gb_tty_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct gb_tty *gb_tty = tty->driver_data; - unsigned int newctrl = gb_tty->ctrlout; + u8 newctrl = gb_tty->ctrlout; set = (set & TIOCM_DTR ? GB_UART_CTRL_DTR : 0) | (set & TIOCM_RTS ? GB_UART_CTRL_RTS : 0); -- cgit v0.10.2 From 7eb8919b0f984b4b2e3764976383d4a98dbc82e2 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 1 Jul 2015 12:13:50 +0530 Subject: greybus: svc: Fix doc-style comment Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index ba85e81..cd87045 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -124,7 +124,7 @@ static int gb_svc_intf_hotplug_recv(struct gb_operation *op) * XXX continue processing the request. There's no need * XXX for the SVC to wait. In fact, it might be best to * XXX have the SVC get acknowledgement before we proceed. - * */ + */ intf_id = hotplug->intf_id; unipro_mfg_id = le32_to_cpu(hotplug->data.unipro_mfg_id); unipro_prod_id = le32_to_cpu(hotplug->data.unipro_prod_id); -- cgit v0.10.2 From 06e305f1e377a6a4e658bd165e20af4c099fb76a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 1 Jul 2015 12:13:51 +0530 Subject: greybus: svc: Use macro's for major/minor numbers We have already defined macro's for SVC's major/minor numbers, lets use them. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index cd87045..75b3337 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -233,8 +233,8 @@ static void gb_svc_connection_exit(struct gb_connection *connection) static struct gb_protocol svc_protocol = { .name = "svc", .id = GREYBUS_PROTOCOL_SVC, - .major = 0, - .minor = 1, + .major = GB_SVC_VERSION_MAJOR, + .minor = GB_SVC_VERSION_MINOR, .connection_init = gb_svc_connection_init, .connection_exit = gb_svc_connection_exit, .request_recv = gb_svc_request_recv, -- cgit v0.10.2 From e18822e3d02c8f296fe42e0e8bda7e2e626a4714 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 1 Jul 2015 12:13:52 +0530 Subject: greybus: Rename gb_gpbridge_protocol_driver() as gb_builtin_protocol_driver() This macro is also required by core protocols like control and svc, and hence the 'gpbridge' name doesn't fit anymore. Lets call this macro gb_builtin_protocol_driver(). Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 9590914..6539530 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -725,4 +725,4 @@ static struct gb_protocol gpio_protocol = { .request_recv = gb_gpio_request_recv, }; -gb_gpbridge_protocol_driver(gpio_protocol); +gb_builtin_protocol_driver(gpio_protocol); diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index 2f6e68c..1214b7a 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -529,4 +529,4 @@ static struct gb_protocol hid_protocol = { .request_recv = gb_hid_irq_handler, }; -gb_gpbridge_protocol_driver(hid_protocol); +gb_builtin_protocol_driver(hid_protocol); diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c index 01afca8..5eb7703 100644 --- a/drivers/staging/greybus/i2c.c +++ b/drivers/staging/greybus/i2c.c @@ -356,4 +356,4 @@ static struct gb_protocol i2c_protocol = { .request_recv = NULL, /* no incoming requests */ }; -gb_gpbridge_protocol_driver(i2c_protocol); +gb_builtin_protocol_driver(i2c_protocol); diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index f6739f3..3f226e3 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -103,7 +103,7 @@ static void __exit protocol_exit(void) \ module_exit(protocol_exit) /* __protocol: string matching name of struct gb_protocol */ -#define gb_gpbridge_protocol_driver(__protocol) \ +#define gb_builtin_protocol_driver(__protocol) \ int __init gb_##__protocol##_init(void) \ { \ return gb_protocol_register(&__protocol); \ diff --git a/drivers/staging/greybus/pwm.c b/drivers/staging/greybus/pwm.c index 5dfeb0e..be7131a 100644 --- a/drivers/staging/greybus/pwm.c +++ b/drivers/staging/greybus/pwm.c @@ -246,4 +246,4 @@ static struct gb_protocol pwm_protocol = { .request_recv = NULL, /* no incoming requests */ }; -gb_gpbridge_protocol_driver(pwm_protocol); +gb_builtin_protocol_driver(pwm_protocol); diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index 30ebd42..f028e14 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -720,4 +720,4 @@ static struct gb_protocol sdio_protocol = { .request_recv = gb_sdio_event_recv, }; -gb_gpbridge_protocol_driver(sdio_protocol); +gb_builtin_protocol_driver(sdio_protocol); diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index 78a7f85..3743618 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -347,4 +347,4 @@ static struct gb_protocol spi_protocol = { .request_recv = NULL, }; -gb_gpbridge_protocol_driver(spi_protocol); +gb_builtin_protocol_driver(spi_protocol); diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 7abcd1c..e2a456f 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -773,4 +773,4 @@ static struct gb_protocol uart_protocol = { .request_recv = gb_uart_request_recv, }; -gb_gpbridge_protocol_driver(uart_protocol); +gb_builtin_protocol_driver(uart_protocol); diff --git a/drivers/staging/greybus/usb.c b/drivers/staging/greybus/usb.c index 609b7cc..888f514 100644 --- a/drivers/staging/greybus/usb.c +++ b/drivers/staging/greybus/usb.c @@ -362,4 +362,4 @@ static struct gb_protocol usb_protocol = { .request_recv = NULL, /* FIXME we have requests!!! */ }; -gb_gpbridge_protocol_driver(usb_protocol); +gb_builtin_protocol_driver(usb_protocol); -- cgit v0.10.2 From 463e8736a3a5038732f681a7f1e9f6975d25b3fd Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 1 Jul 2015 12:13:53 +0530 Subject: greybus: control: Use gb_builtin_protocol_driver() No need to write simple init/exit routines, use gb_builtin_protocol_driver(). Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index c19814d..d7870fc 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -138,13 +138,4 @@ static struct gb_protocol control_protocol = { .connection_exit = gb_control_connection_exit, .request_recv = gb_control_request_recv, }; - -int gb_control_protocol_init(void) -{ - return gb_protocol_register(&control_protocol); -} - -void gb_control_protocol_exit(void) -{ - gb_protocol_deregister(&control_protocol); -} +gb_builtin_protocol_driver(control_protocol); -- cgit v0.10.2 From b758d68618ffda2f6c1c1d40f90350429e9f7092 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 1 Jul 2015 12:13:54 +0530 Subject: greybus: connection: bind protocol after the connection is operational We may bind protocol with a connection from gb_connection_create(), if bundle's device_id is already set. That's not the case until now. But if the protocol is initialized with a call to protocol->connection_init() from this place, kernel will crash. This will happen because the connection isn't fully initialized yet, for example its operation list isn't initialized yet. And as soon as the protocol driver tries to send a request to the module from its connection_init() callback, we will add an operation to this uninitialized list. And it will crash while doing: prev->next = new; Try to bind the connection with a protocol only after the connection is ready for operations. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 564011a..6cd9fe2 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -196,12 +196,6 @@ struct gb_connection *gb_connection_create(struct gb_bundle *bundle, return NULL; } - /* XXX Will have to establish connections to get version */ - gb_connection_bind_protocol(connection); - if (!connection->protocol) - dev_warn(&bundle->dev, - "protocol 0x%02hhx handler not found\n", protocol_id); - spin_lock_irq(&gb_connections_lock); list_add(&connection->hd_links, &hd->connections); list_add(&connection->bundle_links, &bundle->connections); @@ -210,6 +204,12 @@ struct gb_connection *gb_connection_create(struct gb_bundle *bundle, atomic_set(&connection->op_cycle, 0); INIT_LIST_HEAD(&connection->operations); + /* XXX Will have to establish connections to get version */ + gb_connection_bind_protocol(connection); + if (!connection->protocol) + dev_warn(&bundle->dev, + "protocol 0x%02hhx handler not found\n", protocol_id); + return connection; } -- cgit v0.10.2 From c3a1617099cb57da038297cfc40abedb1fe7a287 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 1 Jul 2015 12:13:56 +0530 Subject: greybus: connection: intf_cport_id is local to an interface intf_cport_id is local to an interface and same intf_cport_id can be used for two separate interface blocks. For finding a connection for an interface, we are matching intf_cport_id of the connection with cport_id, passed as argument. This is wrong, as it can match for a connection on a different interface block. Fix it by also comparing interface block for which connection is requested. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 6cd9fe2..85b2a33 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -13,12 +13,14 @@ static DEFINE_SPINLOCK(gb_connections_lock); /* This is only used at initialization time; no locking is required. */ static struct gb_connection * -gb_connection_intf_find(struct greybus_host_device *hd, u16 cport_id) +gb_connection_intf_find(struct gb_interface *intf, u16 cport_id) { + struct greybus_host_device *hd = intf->hd; struct gb_connection *connection; list_for_each_entry(connection, &hd->connections, hd_links) - if (connection->intf_cport_id == cport_id) + if (connection->bundle->intf == intf && + connection->intf_cport_id == cport_id) return connection; return NULL; } @@ -149,7 +151,7 @@ struct gb_connection *gb_connection_create(struct gb_bundle *bundle, * initialize connections serially so we don't need to worry * about holding the connection lock. */ - if (gb_connection_intf_find(hd, cport_id)) { + if (gb_connection_intf_find(bundle->intf, cport_id)) { pr_err("duplicate interface cport id 0x%04hx\n", cport_id); return NULL; } -- cgit v0.10.2 From 7e9017d482a2678ed32e7f60e6bfea10bab2dfa1 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 1 Jul 2015 12:13:57 +0530 Subject: greybus: svc: Drop svc_set_route_send() The responsibility of this routine is to configure ARA switch to establish a connection between a cport on the AP and a cport on an interface. The SVC protocol is responsible for such requests and we already have connection_{create|destroy}_operation() to take care of this. Moreover, this request is not served by the firmware or gbsim today and they just print a debug message on this request. And so it is safe to drop svc_set_route_send() function and fix the required functionality of configuring the switch in svc protocol driver later. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 869f934..fc23817 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -60,24 +60,6 @@ static int svc_msg_send(struct svc_msg *svc_msg, struct greybus_host_device *hd) return retval; } - -int svc_set_route_send(struct gb_bundle *bundle, - struct greybus_host_device *hd) -{ - struct svc_msg *svc_msg; - - svc_msg = svc_msg_alloc(SVC_FUNCTION_UNIPRO_NETWORK_MANAGEMENT); - if (!svc_msg) - return -ENOMEM; - - svc_msg->header.message_type = SVC_MSG_DATA; - svc_msg->header.payload_length = - cpu_to_le16(sizeof(struct svc_function_unipro_set_route)); - svc_msg->management.set_route.device_id = bundle->device_id; - - return svc_msg_send(svc_msg, hd); -} - static void svc_handshake(struct svc_function_handshake *handshake, int payload_length, struct greybus_host_device *hd) { diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index a5172e5..e636230 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -236,12 +236,6 @@ int gb_bundle_init(struct gb_bundle *bundle, u8 device_id) bundle->device_id = device_id; - ret = svc_set_route_send(bundle, intf->hd); - if (ret) { - dev_err(intf->hd->parent, "failed to set route (%d)\n", ret); - return ret; - } - ret = gb_bundle_connections_init(bundle); if (ret) { dev_err(intf->hd->parent, "interface bundle init error %d\n", diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 6874939..c1157df 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -163,9 +163,6 @@ struct dentry *gb_debugfs_get(void); extern struct bus_type greybus_bus_type; -int svc_set_route_send(struct gb_bundle *bundle, - struct greybus_host_device *hd); - extern struct device_type greybus_endo_type; extern struct device_type greybus_module_type; extern struct device_type greybus_interface_type; -- cgit v0.10.2 From c3add7883c70b625b99c37ca89e6ec8733037ce3 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 1 Jul 2015 12:13:58 +0530 Subject: greybus: interface: device_id belongs to the interface While introducing bundles, the device_id also got moved to the bundle, whereas it identifies an interface block to the AP. Move it back to interface instead of bundle. Calls to gb_bundle(s)_init() are dropped as connections will be initialized while they are created now, as device_id will be valid. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 0268dd2..808fde9 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -105,6 +105,13 @@ Contact: Greg Kroah-Hartman Description: Vendor ID string of a Greybus interface block. +What: /sys/bus/greybus/device/.../device_id +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The device ID of a Greybus interface block. + What: /sys/bus/greybus/device/.../state Date: October 2015 KernelVersion: 4.XX @@ -126,13 +133,6 @@ Contact: Greg Kroah-Hartman Description: The protocol ID of a Greybus connection. -What: /sys/bus/greybus/device/.../device_id -Date: October 2015 -KernelVersion: 4.XX -Contact: Greg Kroah-Hartman -Description: - The device ID of a Greybus bundle. - What: /sys/bus/greybus/device/.../state Date: October 2015 KernelVersion: 4.XX diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index e636230..c6694ae 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -13,15 +13,6 @@ static void gb_bundle_connections_exit(struct gb_bundle *bundle); static int gb_bundle_connections_init(struct gb_bundle *bundle); -static ssize_t device_id_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct gb_bundle *bundle = to_gb_bundle(dev); - - return sprintf(buf, "%d\n", bundle->device_id); -} -static DEVICE_ATTR_RO(device_id); - static ssize_t class_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -61,7 +52,6 @@ static DEVICE_ATTR_RW(state); static struct attribute *bundle_attrs[] = { - &dev_attr_device_id.attr, &dev_attr_class.attr, &dev_attr_state.attr, NULL, @@ -184,9 +174,6 @@ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, bundle->class = class; INIT_LIST_HEAD(&bundle->connections); - /* Invalid device id to start with */ - bundle->device_id = GB_DEVICE_ID_BAD; - /* Build up the bundle device structures and register it with the * driver core */ bundle->dev.parent = &intf->dev; @@ -225,7 +212,7 @@ void gb_bundle_destroy(struct gb_bundle *bundle) device_unregister(&bundle->dev); } -int gb_bundle_init(struct gb_bundle *bundle, u8 device_id) +int gb_bundle_init(struct gb_bundle *bundle) { struct gb_interface *intf = bundle->intf; int ret; @@ -234,8 +221,6 @@ int gb_bundle_init(struct gb_bundle *bundle, u8 device_id) if (intf->control && bundle->id == GB_CONTROL_BUNDLE_ID) return 0; - bundle->device_id = device_id; - ret = gb_bundle_connections_init(bundle); if (ret) { dev_err(intf->hd->parent, "interface bundle init error %d\n", @@ -247,13 +232,13 @@ int gb_bundle_init(struct gb_bundle *bundle, u8 device_id) return 0; } -int gb_bundles_init(struct gb_interface *intf, u8 device_id) +int gb_bundles_init(struct gb_interface *intf) { struct gb_bundle *bundle; int ret = 0; list_for_each_entry(bundle, &intf->bundles, links) { - ret = gb_bundle_init(bundle, device_id); + ret = gb_bundle_init(bundle); if (ret) { dev_err(intf->hd->parent, "Failed to initialize bundle %hhu\n", diff --git a/drivers/staging/greybus/bundle.h b/drivers/staging/greybus/bundle.h index 887883d..60033b8 100644 --- a/drivers/staging/greybus/bundle.h +++ b/drivers/staging/greybus/bundle.h @@ -18,7 +18,6 @@ struct gb_bundle { struct gb_interface *intf; u8 id; u8 class; - u8 device_id; struct list_head connections; u8 *state; @@ -32,8 +31,8 @@ struct gb_bundle { struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, u8 class); void gb_bundle_destroy(struct gb_bundle *bundle); -int gb_bundle_init(struct gb_bundle *bundle, u8 device_id); -int gb_bundles_init(struct gb_interface *intf, u8 device_id); +int gb_bundle_init(struct gb_bundle *bundle); +int gb_bundles_init(struct gb_interface *intf); struct gb_bundle *gb_bundle_find(struct gb_interface *intf, u8 bundle_id); void gb_bundle_bind_protocols(void); diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 85b2a33..2e306d1 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -102,7 +102,7 @@ struct device_type greybus_connection_type = { void gb_connection_bind_protocol(struct gb_connection *connection) { - struct gb_bundle *bundle; + struct gb_interface *intf; struct gb_protocol *protocol; /* If we already have a protocol bound here, just return */ @@ -117,11 +117,11 @@ void gb_connection_bind_protocol(struct gb_connection *connection) connection->protocol = protocol; /* - * If we have a valid device_id for the bundle, then we have an active - * device, so bring up the connection at the same time. + * If we have a valid device_id for the interface block, then we have an + * active device, so bring up the connection at the same time. * */ - bundle = connection->bundle; - if (bundle->device_id != GB_DEVICE_ID_BAD) + intf = connection->bundle->intf; + if (intf->device_id != GB_DEVICE_ID_BAD) gb_connection_init(connection); } diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 901c4ac..f9fd479 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -20,6 +20,7 @@ static ssize_t field##_show(struct device *dev, \ } \ static DEVICE_ATTR_RO(field) +gb_interface_attr(device_id, d); gb_interface_attr(vendor, x); gb_interface_attr(product, x); gb_interface_attr(unique_id, llX); @@ -27,6 +28,7 @@ gb_interface_attr(vendor_string, s); gb_interface_attr(product_string, s); static struct attribute *interface_attrs[] = { + &dev_attr_device_id.attr, &dev_attr_vendor.attr, &dev_attr_product.attr, &dev_attr_unique_id.attr, @@ -71,10 +73,9 @@ struct device_type greybus_interface_type = { * managing control CPort. Also initialize the bundle, which will request SVC to * set route and will initialize the control protocol for this connection. */ -static int gb_create_control_connection(struct gb_interface *intf, u8 device_id) +static int gb_create_control_connection(struct gb_interface *intf) { struct gb_bundle *bundle; - int ret; bundle = gb_bundle_create(intf, GB_CONTROL_BUNDLE_ID, GREYBUS_CLASS_CONTROL); @@ -85,14 +86,6 @@ static int gb_create_control_connection(struct gb_interface *intf, u8 device_id) GREYBUS_PROTOCOL_CONTROL)) return -EINVAL; - ret = gb_bundle_init(bundle, device_id); - if (ret) { - dev_err(&intf->dev, - "error %d initializing bundles for interface %hu\n", - ret, intf->interface_id); - return ret; - } - return 0; } @@ -136,6 +129,9 @@ struct gb_interface *gb_interface_create(struct greybus_host_device *hd, INIT_LIST_HEAD(&intf->bundles); INIT_LIST_HEAD(&intf->manifest_descs); + /* Invalid device id to start with */ + intf->device_id = GB_DEVICE_ID_BAD; + intf->dev.parent = &module->dev; intf->dev.bus = &greybus_bus_type; intf->dev.type = &greybus_interface_type; @@ -204,8 +200,10 @@ int gb_interface_init(struct gb_interface *intf, u8 device_id) int ret, size; void *manifest; + intf->device_id = device_id; + /* Establish control CPort connection */ - ret = gb_create_control_connection(intf, device_id); + ret = gb_create_control_connection(intf); if (ret) { dev_err(&intf->dev, "Failed to create control CPort connection (%d)\n", ret); return ret; @@ -243,12 +241,6 @@ int gb_interface_init(struct gb_interface *intf, u8 device_id) goto free_manifest; } - ret = gb_bundles_init(intf, device_id); - if (ret) - dev_err(&intf->dev, - "Error %d initializing bundles for interface %hu\n", - ret, intf->interface_id); - /* * XXX * We've successfully parsed the manifest. Now we need to diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 90dbff1..86eb894 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -19,6 +19,7 @@ struct gb_interface { struct list_head links; /* greybus_host_device->interfaces */ struct list_head manifest_descs; u8 interface_id; /* Physical location within the Endo */ + u8 device_id; /* Device id allocated for the interface block by the SVC */ /* Information taken from the manifest descriptor */ u16 vendor; -- cgit v0.10.2 From 5677d48b9735ca43f546d8e21dd36a993b770090 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 1 Jul 2015 12:13:59 +0530 Subject: greybus: bundles: remove gb_bundle(s)_init() They aren't used anymore, remove them. This also gets rid of gb_bundle_connections_init(). Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index c6694ae..694bcce 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -10,8 +10,6 @@ #include "greybus.h" static void gb_bundle_connections_exit(struct gb_bundle *bundle); -static int gb_bundle_connections_init(struct gb_bundle *bundle); - static ssize_t class_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -212,44 +210,6 @@ void gb_bundle_destroy(struct gb_bundle *bundle) device_unregister(&bundle->dev); } -int gb_bundle_init(struct gb_bundle *bundle) -{ - struct gb_interface *intf = bundle->intf; - int ret; - - /* Don't reinitialize control cport's bundle */ - if (intf->control && bundle->id == GB_CONTROL_BUNDLE_ID) - return 0; - - ret = gb_bundle_connections_init(bundle); - if (ret) { - dev_err(intf->hd->parent, "interface bundle init error %d\n", - ret); - /* XXX clear route */ - return ret; - } - - return 0; -} - -int gb_bundles_init(struct gb_interface *intf) -{ - struct gb_bundle *bundle; - int ret = 0; - - list_for_each_entry(bundle, &intf->bundles, links) { - ret = gb_bundle_init(bundle); - if (ret) { - dev_err(intf->hd->parent, - "Failed to initialize bundle %hhu\n", - bundle->id); - break; - } - } - - return ret; -} - struct gb_bundle *gb_bundle_find(struct gb_interface *intf, u8 bundle_id) { struct gb_bundle *bundle; @@ -265,20 +225,6 @@ found: return bundle; } -static int gb_bundle_connections_init(struct gb_bundle *bundle) -{ - struct gb_connection *connection; - int ret = 0; - - list_for_each_entry(connection, &bundle->connections, bundle_links) { - ret = gb_connection_init(connection); - if (ret) - break; - } - - return ret; -} - static void gb_bundle_connections_exit(struct gb_bundle *bundle) { struct gb_connection *connection; diff --git a/drivers/staging/greybus/bundle.h b/drivers/staging/greybus/bundle.h index 60033b8..9134df7 100644 --- a/drivers/staging/greybus/bundle.h +++ b/drivers/staging/greybus/bundle.h @@ -31,8 +31,6 @@ struct gb_bundle { struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, u8 class); void gb_bundle_destroy(struct gb_bundle *bundle); -int gb_bundle_init(struct gb_bundle *bundle); -int gb_bundles_init(struct gb_interface *intf); struct gb_bundle *gb_bundle_find(struct gb_interface *intf, u8 bundle_id); void gb_bundle_bind_protocols(void); -- cgit v0.10.2 From 3e136cc9e05e1a34d8602a4d4e31c9d93ccbbdf7 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 1 Jul 2015 12:37:21 +0200 Subject: greybus: operation/esx: fix message-cancellation lifetime bugs The current host-controller message-cancellation implementation suffer from a lifetime bug as dynamically allocated URBs would complete and be deallocated while being unlinked as part of cancellation. The current locking is also insufficient to prevent the related race where the URB is deallocated before being unlinked. Fix this by pushing the cancellation implementation from greybus core down to the host-controller drivers, and replace the "cookie" pointer with a hcpriv field that those drivers can use to maintain their state with the required locking and reference counting in place. Specifically the drivers need to acquire a reference to the URB under a lock before calling usb_kill_urb as part of cancellation. Note that this also removes the insufficient gb_message_mutex, which also effectively prevented us from implementing support for submissions from atomic context. Instead the host-controller drivers must now explicitly make sure that the pre-allocated URBs are not reused while cancellation is in progress. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 067b4c1..0cb7a3c 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -68,6 +68,8 @@ static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); * @cport_out_urb: array of urbs for the CPort out messages * @cport_out_urb_busy: array of flags to see if the @cport_out_urb is busy or * not. + * @cport_out_urb_cancelled: array of flags indicating whether the + * corresponding @cport_out_urb is being cancelled * @cport_out_urb_lock: locks the @cport_out_urb_busy "list" */ struct es1_ap_dev { @@ -87,6 +89,7 @@ struct es1_ap_dev { u8 *cport_in_buffer[NUM_CPORT_IN_URB]; struct urb *cport_out_urb[NUM_CPORT_OUT_URB]; bool cport_out_urb_busy[NUM_CPORT_OUT_URB]; + bool cport_out_urb_cancelled[NUM_CPORT_OUT_URB]; spinlock_t cport_out_urb_lock; }; @@ -131,7 +134,8 @@ static struct urb *next_free_urb(struct es1_ap_dev *es1, gfp_t gfp_mask) /* Look in our pool of allocated urbs first, as that's the "fastest" */ for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - if (es1->cport_out_urb_busy[i] == false) { + if (es1->cport_out_urb_busy[i] == false && + es1->cport_out_urb_cancelled[i] == false) { es1->cport_out_urb_busy[i] = true; urb = es1->cport_out_urb[i]; break; @@ -199,11 +203,10 @@ static u16 gb_message_cport_unpack(struct gb_operation_msg_hdr *header) } /* - * Returns an opaque cookie value if successful, or a pointer coded - * error otherwise. If the caller wishes to cancel the in-flight - * buffer, it must supply the returned cookie to the cancel routine. + * Returns zero if the message was successfully queued, or a negative errno + * otherwise. */ -static void *message_send(struct greybus_host_device *hd, u16 cport_id, +static int message_send(struct greybus_host_device *hd, u16 cport_id, struct gb_message *message, gfp_t gfp_mask) { struct es1_ap_dev *es1 = hd_to_es1(hd); @@ -211,6 +214,7 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id, size_t buffer_size; int retval; struct urb *urb; + unsigned long flags; /* * The data actually transferred will include an indication @@ -219,13 +223,17 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id, */ if (!cport_id_valid(cport_id)) { pr_err("invalid destination cport 0x%02x\n", cport_id); - return ERR_PTR(-EINVAL); + return -EINVAL; } /* Find a free urb */ urb = next_free_urb(es1, gfp_mask); if (!urb) - return ERR_PTR(-ENOMEM); + return -ENOMEM; + + spin_lock_irqsave(&es1->cport_out_urb_lock, flags); + message->hcpriv = urb; + spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); /* Pack the cport id into the message header */ gb_message_cport_pack(message->header, cport_id); @@ -239,30 +247,56 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id, retval = usb_submit_urb(urb, gfp_mask); if (retval) { pr_err("error %d submitting URB\n", retval); + + spin_lock_irqsave(&es1->cport_out_urb_lock, flags); + message->hcpriv = NULL; + spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); + free_urb(es1, urb); gb_message_cport_clear(message->header); - return ERR_PTR(retval); + + return retval; } - return urb; + return 0; } /* - * The cookie value supplied is the value that message_send() - * returned to its caller. It identifies the message that should be - * canceled. This function must also handle (which is to say, - * ignore) a null cookie value. + * Can not be called in atomic context. */ -static void message_cancel(void *cookie) +static void message_cancel(struct gb_message *message) { + struct greybus_host_device *hd = message->operation->connection->hd; + struct es1_ap_dev *es1 = hd_to_es1(hd); + struct urb *urb; + int i; - /* - * We really should be defensive and track all outstanding - * (sent) messages rather than trusting the cookie provided - * is valid. For the time being, this will do. - */ - if (cookie) - usb_kill_urb(cookie); + might_sleep(); + + spin_lock_irq(&es1->cport_out_urb_lock); + urb = message->hcpriv; + + /* Prevent dynamically allocated urb from being deallocated. */ + usb_get_urb(urb); + + /* Prevent pre-allocated urb from being reused. */ + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + if (urb == es1->cport_out_urb[i]) { + es1->cport_out_urb_cancelled[i] = true; + break; + } + } + spin_unlock_irq(&es1->cport_out_urb_lock); + + usb_kill_urb(urb); + + if (i < NUM_CPORT_OUT_URB) { + spin_lock_irq(&es1->cport_out_urb_lock); + es1->cport_out_urb_cancelled[i] = false; + spin_unlock_irq(&es1->cport_out_urb_lock); + } + + usb_free_urb(urb); } static struct greybus_host_driver es1_driver = { @@ -418,6 +452,7 @@ static void cport_out_callback(struct urb *urb) struct greybus_host_device *hd = message->operation->connection->hd; struct es1_ap_dev *es1 = hd_to_es1(hd); int status = check_urb_status(urb); + unsigned long flags; gb_message_cport_clear(message->header); @@ -427,6 +462,10 @@ static void cport_out_callback(struct urb *urb) */ greybus_message_sent(hd, message, status); + spin_lock_irqsave(&es1->cport_out_urb_lock, flags); + message->hcpriv = NULL; + spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); + free_urb(es1, urb); } diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 97fa2e0..323721a 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -94,6 +94,8 @@ struct es1_cport_out { * @cport_out_urb: array of urbs for the CPort out messages * @cport_out_urb_busy: array of flags to see if the @cport_out_urb is busy or * not. + * @cport_out_urb_cancelled: array of flags indicating whether the + * corresponding @cport_out_urb is being cancelled * @cport_out_urb_lock: locks the @cport_out_urb_busy "list" */ struct es1_ap_dev { @@ -111,6 +113,7 @@ struct es1_ap_dev { struct es1_cport_out cport_out[NUM_BULKS]; struct urb *cport_out_urb[NUM_CPORT_OUT_URB]; bool cport_out_urb_busy[NUM_CPORT_OUT_URB]; + bool cport_out_urb_cancelled[NUM_CPORT_OUT_URB]; spinlock_t cport_out_urb_lock; int cport_to_ep[CPORT_MAX]; @@ -224,7 +227,8 @@ static struct urb *next_free_urb(struct es1_ap_dev *es1, gfp_t gfp_mask) /* Look in our pool of allocated urbs first, as that's the "fastest" */ for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - if (es1->cport_out_urb_busy[i] == false) { + if (es1->cport_out_urb_busy[i] == false && + es1->cport_out_urb_cancelled[i] == false) { es1->cport_out_urb_busy[i] = true; urb = es1->cport_out_urb[i]; break; @@ -292,11 +296,10 @@ static u16 gb_message_cport_unpack(struct gb_operation_msg_hdr *header) } /* - * Returns an opaque cookie value if successful, or a pointer coded - * error otherwise. If the caller wishes to cancel the in-flight - * buffer, it must supply the returned cookie to the cancel routine. + * Returns zero if the message was successfully queued, or a negative errno + * otherwise. */ -static void *message_send(struct greybus_host_device *hd, u16 cport_id, +static int message_send(struct greybus_host_device *hd, u16 cport_id, struct gb_message *message, gfp_t gfp_mask) { struct es1_ap_dev *es1 = hd_to_es1(hd); @@ -305,6 +308,7 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id, int retval; struct urb *urb; int bulk_ep_set; + unsigned long flags; /* * The data actually transferred will include an indication @@ -313,13 +317,17 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id, */ if (!cport_id_valid(cport_id)) { pr_err("invalid destination cport 0x%02x\n", cport_id); - return ERR_PTR(-EINVAL); + return -EINVAL; } /* Find a free urb */ urb = next_free_urb(es1, gfp_mask); if (!urb) - return ERR_PTR(-ENOMEM); + return -ENOMEM; + + spin_lock_irqsave(&es1->cport_out_urb_lock, flags); + message->hcpriv = urb; + spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); /* Pack the cport id into the message header */ gb_message_cport_pack(message->header, cport_id); @@ -335,30 +343,56 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id, retval = usb_submit_urb(urb, gfp_mask); if (retval) { pr_err("error %d submitting URB\n", retval); + + spin_lock_irqsave(&es1->cport_out_urb_lock, flags); + message->hcpriv = NULL; + spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); + free_urb(es1, urb); gb_message_cport_clear(message->header); - return ERR_PTR(retval); + + return retval; } - return urb; + return 0; } /* - * The cookie value supplied is the value that message_send() - * returned to its caller. It identifies the message that should be - * canceled. This function must also handle (which is to say, - * ignore) a null cookie value. + * Can not be called in atomic context. */ -static void message_cancel(void *cookie) +static void message_cancel(struct gb_message *message) { + struct greybus_host_device *hd = message->operation->connection->hd; + struct es1_ap_dev *es1 = hd_to_es1(hd); + struct urb *urb; + int i; - /* - * We really should be defensive and track all outstanding - * (sent) messages rather than trusting the cookie provided - * is valid. For the time being, this will do. - */ - if (cookie) - usb_kill_urb(cookie); + might_sleep(); + + spin_lock_irq(&es1->cport_out_urb_lock); + urb = message->hcpriv; + + /* Prevent dynamically allocated urb from being deallocated. */ + usb_get_urb(urb); + + /* Prevent pre-allocated urb from being reused. */ + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + if (urb == es1->cport_out_urb[i]) { + es1->cport_out_urb_cancelled[i] = true; + break; + } + } + spin_unlock_irq(&es1->cport_out_urb_lock); + + usb_kill_urb(urb); + + if (i < NUM_CPORT_OUT_URB) { + spin_lock_irq(&es1->cport_out_urb_lock); + es1->cport_out_urb_cancelled[i] = false; + spin_unlock_irq(&es1->cport_out_urb_lock); + } + + usb_free_urb(urb); } static struct greybus_host_driver es1_driver = { @@ -518,6 +552,7 @@ static void cport_out_callback(struct urb *urb) struct greybus_host_device *hd = message->operation->connection->hd; struct es1_ap_dev *es1 = hd_to_es1(hd); int status = check_urb_status(urb); + unsigned long flags; gb_message_cport_clear(message->header); @@ -527,6 +562,10 @@ static void cport_out_callback(struct urb *urb) */ greybus_message_sent(hd, message, status); + spin_lock_irqsave(&es1->cport_out_urb_lock, flags); + message->hcpriv = NULL; + spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); + free_urb(es1, urb); } diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index c1157df..e795016 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -81,9 +81,9 @@ struct svc_msg; struct greybus_host_driver { size_t hd_priv_size; - void *(*message_send)(struct greybus_host_device *hd, u16 dest_cport_id, + int (*message_send)(struct greybus_host_device *hd, u16 dest_cport_id, struct gb_message *message, gfp_t gfp_mask); - void (*message_cancel)(void *cookie); + void (*message_cancel)(struct gb_message *message); int (*submit_svc)(struct svc_msg *svc_msg, struct greybus_host_device *hd); }; diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index a713daf..b125bde 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -23,9 +23,6 @@ static struct kmem_cache *gb_message_cache; /* Workqueue to handle Greybus operation completions. */ static struct workqueue_struct *gb_operation_workqueue; -/* Protects the cookie representing whether a message is in flight */ -static DEFINE_MUTEX(gb_message_mutex); - /* * Protects access to connection operations lists, as well as * updates to operation->errno. @@ -135,21 +132,11 @@ gb_operation_find(struct gb_connection *connection, u16 operation_id) static int gb_message_send(struct gb_message *message) { struct gb_connection *connection = message->operation->connection; - int ret = 0; - void *cookie; - mutex_lock(&gb_message_mutex); - cookie = connection->hd->driver->message_send(connection->hd, + return connection->hd->driver->message_send(connection->hd, connection->hd_cport_id, message, GFP_KERNEL); - if (IS_ERR(cookie)) - ret = PTR_ERR(cookie); - else - message->cookie = cookie; - mutex_unlock(&gb_message_mutex); - - return ret; } /* @@ -157,14 +144,9 @@ static int gb_message_send(struct gb_message *message) */ static void gb_message_cancel(struct gb_message *message) { - mutex_lock(&gb_message_mutex); - if (message->cookie) { - struct greybus_host_device *hd; + struct greybus_host_device *hd = message->operation->connection->hd; - hd = message->operation->connection->hd; - hd->driver->message_cancel(message->cookie); - } - mutex_unlock(&gb_message_mutex); + hd->driver->message_cancel(message); } static void gb_operation_request_handle(struct gb_operation *operation) @@ -719,9 +701,6 @@ void greybus_message_sent(struct greybus_host_device *hd, { struct gb_operation *operation; - /* Get the message and record that it is no longer in flight */ - message->cookie = NULL; - /* * If the message was a response, we just need to drop our * reference to the operation. If an error occurred, report diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 0199976..ad4574b 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -73,19 +73,20 @@ struct gb_operation_msg_hdr { #define GB_OPERATION_MESSAGE_SIZE_MAX U16_MAX /* - * Protocol code should only examine the payload and payload_size - * fields. All other fields are intended to be private to the - * operations core code. + * Protocol code should only examine the payload and payload_size fields, and + * host-controller drivers may use the hcpriv field. All other fields are + * intended to be private to the operations core code. */ struct gb_message { struct gb_operation *operation; - void *cookie; struct gb_operation_msg_hdr *header; void *payload; size_t payload_size; void *buffer; + + void *hcpriv; }; /* -- cgit v0.10.2 From e420721b47ef5b0d521584d4efc89ff64bd0cd74 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 1 Jul 2015 12:37:22 +0200 Subject: greybus: operation: allow atomic operation allocations Add gfp mask argument to gb_operation_create to allow operations to be allocated in atomic context. Signed-off-by: Johan Hovold Reviewed-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index 1214b7a..a367fd5 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -128,7 +128,8 @@ static int gb_hid_set_report(struct gb_hid *ghid, u8 report_type, u8 report_id, int ret, size = sizeof(*request) + len - 1; operation = gb_operation_create(ghid->connection, - GB_HID_TYPE_SET_REPORT, size, 0); + GB_HID_TYPE_SET_REPORT, size, 0, + GFP_KERNEL); if (!operation) return -ENOMEM; diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c index 5eb7703..9514e69 100644 --- a/drivers/staging/greybus/i2c.c +++ b/drivers/staging/greybus/i2c.c @@ -146,7 +146,7 @@ gb_i2c_operation_create(struct gb_connection *connection, /* Response consists only of incoming data */ operation = gb_operation_create(connection, GB_I2C_TYPE_TRANSFER, - request_size, data_in_size); + request_size, data_in_size, GFP_KERNEL); if (!operation) return NULL; diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index b125bde..4019b03 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -409,22 +409,13 @@ EXPORT_SYMBOL_GPL(gb_operation_response_alloc); */ static struct gb_operation * gb_operation_create_common(struct gb_connection *connection, u8 type, - size_t request_size, size_t response_size) + size_t request_size, size_t response_size, + gfp_t gfp_flags) { struct greybus_host_device *hd = connection->hd; struct gb_operation *operation; unsigned long flags; - gfp_t gfp_flags; - /* - * An incoming request will pass an invalid operation type, - * because the header will get overwritten anyway. These - * occur in interrupt context, so we must use GFP_ATOMIC. - */ - if (type == GB_OPERATION_TYPE_INVALID) - gfp_flags = GFP_ATOMIC; - else - gfp_flags = GFP_KERNEL; operation = kmem_cache_zalloc(gb_operation_cache, gfp_flags); if (!operation) return NULL; @@ -472,7 +463,8 @@ err_cache: */ struct gb_operation *gb_operation_create(struct gb_connection *connection, u8 type, size_t request_size, - size_t response_size) + size_t response_size, + gfp_t gfp) { if (WARN_ON_ONCE(type == GB_OPERATION_TYPE_INVALID)) return NULL; @@ -480,7 +472,7 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, type &= ~GB_MESSAGE_TYPE_RESPONSE; return gb_operation_create_common(connection, type, - request_size, response_size); + request_size, response_size, gfp); } EXPORT_SYMBOL_GPL(gb_operation_create); @@ -504,7 +496,7 @@ gb_operation_create_incoming(struct gb_connection *connection, u16 id, operation = gb_operation_create_common(connection, GB_OPERATION_TYPE_INVALID, - request_size, 0); + request_size, 0, GFP_ATOMIC); if (operation) { operation->id = id; operation->type = type; @@ -888,7 +880,8 @@ int gb_operation_sync(struct gb_connection *connection, int type, return -EINVAL; operation = gb_operation_create(connection, type, - request_size, response_size); + request_size, response_size, + GFP_KERNEL); if (!operation) return -ENOMEM; diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index ad4574b..3956648 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -134,7 +134,8 @@ int gb_operation_result(struct gb_operation *operation); size_t gb_operation_get_payload_size_max(struct gb_connection *connection); struct gb_operation *gb_operation_create(struct gb_connection *connection, u8 type, size_t request_size, - size_t response_size); + size_t response_size, + gfp_t gfp); void gb_operation_get(struct gb_operation *operation); void gb_operation_put(struct gb_operation *operation); static inline void gb_operation_destroy(struct gb_operation *operation) diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index 3743618..306fb07 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -90,7 +90,7 @@ gb_spi_operation_create(struct gb_connection *connection, /* Response consists only of incoming data */ operation = gb_operation_create(connection, GB_SPI_TYPE_TRANSFER, - request_size, rx_size); + request_size, rx_size, GFP_KERNEL); if (!operation) return NULL; diff --git a/drivers/staging/greybus/usb.c b/drivers/staging/greybus/usb.c index 888f514..e49fffd 100644 --- a/drivers/staging/greybus/usb.c +++ b/drivers/staging/greybus/usb.c @@ -131,7 +131,8 @@ static int urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) operation = gb_operation_create(dev->connection, GB_USB_TYPE_URB_ENQUEUE, sizeof(*request) + - urb->transfer_buffer_length, 0); + urb->transfer_buffer_length, 0, + GFP_KERNEL); if (!operation) return -ENODEV; -- cgit v0.10.2 From a52c4352aef85538d194a9714fe742b18e6fb80f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 1 Jul 2015 12:37:23 +0200 Subject: greybus: operation: allow atomic request submissions Add gfp mask argument to gb_operation_request_send in order to allow submissions from atomic context. Note that responses are currently always sent from non-atomic context as incoming requests are processed in a work queue. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 4019b03..eee315c 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -129,7 +129,7 @@ gb_operation_find(struct gb_connection *connection, u16 operation_id) return found ? operation : NULL; } -static int gb_message_send(struct gb_message *message) +static int gb_message_send(struct gb_message *message, gfp_t gfp) { struct gb_connection *connection = message->operation->connection; @@ -563,7 +563,8 @@ static void gb_operation_sync_callback(struct gb_operation *operation) * dropping the initial reference to the operation. */ int gb_operation_request_send(struct gb_operation *operation, - gb_operation_callback callback) + gb_operation_callback callback, + gfp_t gfp) { struct gb_connection *connection = operation->connection; struct gb_operation_msg_hdr *header; @@ -601,7 +602,7 @@ int gb_operation_request_send(struct gb_operation *operation, /* All set, send the request */ gb_operation_result_set(operation, -EINPROGRESS); - ret = gb_message_send(operation->request); + ret = gb_message_send(operation->request, gfp); if (ret) gb_operation_put(operation); @@ -620,7 +621,8 @@ int gb_operation_request_send_sync(struct gb_operation *operation) int ret; unsigned long timeout; - ret = gb_operation_request_send(operation, gb_operation_sync_callback); + ret = gb_operation_request_send(operation, gb_operation_sync_callback, + GFP_KERNEL); if (ret) return ret; @@ -677,7 +679,7 @@ int gb_operation_response_send(struct gb_operation *operation, int errno) /* Fill in the response header and send it */ operation->response->header->result = gb_operation_errno_map(errno); - ret = gb_message_send(operation->response); + ret = gb_message_send(operation->response, GFP_KERNEL); if (ret) gb_operation_put(operation); diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 3956648..4063223 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -147,7 +147,8 @@ bool gb_operation_response_alloc(struct gb_operation *operation, size_t response_size); int gb_operation_request_send(struct gb_operation *operation, - gb_operation_callback callback); + gb_operation_callback callback, + gfp_t gfp); int gb_operation_request_send_sync(struct gb_operation *operation); int gb_operation_response_send(struct gb_operation *operation, int errno); -- cgit v0.10.2 From abb722e79a07b0a438a3782fd3f7d8c85f541d5f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 1 Jul 2015 12:37:24 +0200 Subject: greybus: operation: make response helper static Since commit 46ce118a2678 ("operation: refactor response handling") sending operation responses is handled by greybus core so there is currently no need to export the response helper. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index eee315c..3392b42 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -29,6 +29,9 @@ static struct workqueue_struct *gb_operation_workqueue; */ static DEFINE_SPINLOCK(gb_operations_lock); +static int gb_operation_response_send(struct gb_operation *operation, + int errno); + /* * Set an operation's result. * @@ -649,7 +652,8 @@ EXPORT_SYMBOL_GPL(gb_operation_request_send_sync); * it can simply supply the result errno; this function will * allocate the response message if necessary. */ -int gb_operation_response_send(struct gb_operation *operation, int errno) +static int gb_operation_response_send(struct gb_operation *operation, + int errno) { struct gb_connection *connection = operation->connection; int ret; @@ -685,7 +689,6 @@ int gb_operation_response_send(struct gb_operation *operation, int errno) return ret; } -EXPORT_SYMBOL_GPL(gb_operation_response_send); /* * This function is called when a message send request has completed. diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 4063223..3bf7571 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -150,7 +150,6 @@ int gb_operation_request_send(struct gb_operation *operation, gb_operation_callback callback, gfp_t gfp); int gb_operation_request_send_sync(struct gb_operation *operation); -int gb_operation_response_send(struct gb_operation *operation, int errno); void gb_operation_cancel(struct gb_operation *operation, int errno); -- cgit v0.10.2 From 73f9d73f124ccba16403971b5101d4a947161481 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 1 Jul 2015 12:37:25 +0200 Subject: greybus: operation: fix cancellation use-after-free The final reference of an operation will be put after its completion handler has run, so we must not drop the reference if it has already been scheduled to avoid use-after-free. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 3392b42..7adfa63 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -846,8 +846,8 @@ void gb_operation_cancel(struct gb_operation *operation, int errno) gb_message_cancel(operation->request); if (operation->response) gb_message_cancel(operation->response); + gb_operation_put(operation); } - gb_operation_put(operation); } EXPORT_SYMBOL_GPL(gb_operation_cancel); -- cgit v0.10.2 From 710067e2ef42473c823fc8176ca9536b1a42c491 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 1 Jul 2015 12:37:26 +0200 Subject: greybus: operation: add incoming-operation flag Add flag field to struct gb_operation, and a first flag GB_OPERATION_FLAG_INCOMING to identify incoming operations. Pass an initial set of flags when allocating new operations, and use these to identify incoming operations rather than overloading the meaning of GB_OPERATION_TYPE_INVALID. This also allows us to set the type for all operations during allocation. Also add convenience helper to identify incoming operations. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 7adfa63..ad09599 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -413,7 +413,7 @@ EXPORT_SYMBOL_GPL(gb_operation_response_alloc); static struct gb_operation * gb_operation_create_common(struct gb_connection *connection, u8 type, size_t request_size, size_t response_size, - gfp_t gfp_flags) + unsigned long op_flags, gfp_t gfp_flags) { struct greybus_host_device *hd = connection->hd; struct gb_operation *operation; @@ -431,11 +431,13 @@ gb_operation_create_common(struct gb_connection *connection, u8 type, operation->request->operation = operation; /* Allocate the response buffer for outgoing operations */ - if (type != GB_OPERATION_TYPE_INVALID) { + if (!(op_flags & GB_OPERATION_FLAG_INCOMING)) { if (!gb_operation_response_alloc(operation, response_size)) goto err_request; - operation->type = type; } + + operation->flags = op_flags; + operation->type = type; operation->errno = -EBADR; /* Initial value--means "never set" */ INIT_WORK(&operation->work, gb_operation_work); @@ -475,7 +477,7 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, type &= ~GB_MESSAGE_TYPE_RESPONSE; return gb_operation_create_common(connection, type, - request_size, response_size, gfp); + request_size, response_size, 0, gfp); } EXPORT_SYMBOL_GPL(gb_operation_create); @@ -493,16 +495,15 @@ gb_operation_create_incoming(struct gb_connection *connection, u16 id, { struct gb_operation *operation; size_t request_size; + unsigned long flags = GB_OPERATION_FLAG_INCOMING; /* Caller has made sure we at least have a message header. */ request_size = size - sizeof(struct gb_operation_msg_hdr); - operation = gb_operation_create_common(connection, - GB_OPERATION_TYPE_INVALID, - request_size, 0, GFP_ATOMIC); + operation = gb_operation_create_common(connection, type, + request_size, 0, flags, GFP_ATOMIC); if (operation) { operation->id = id; - operation->type = type; memcpy(operation->request->header, data, size); } diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 3bf7571..b6bbc84 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -89,6 +89,8 @@ struct gb_message { void *hcpriv; }; +#define GB_OPERATION_FLAG_INCOMING BIT(0) + /* * A Greybus operation is a remote procedure call performed over a * connection between two UniPro interfaces. @@ -113,8 +115,9 @@ struct gb_operation { struct gb_connection *connection; struct gb_message *request; struct gb_message *response; - u8 type; + unsigned long flags; + u8 type; u16 id; int errno; /* Operation result */ @@ -126,6 +129,12 @@ struct gb_operation { struct list_head links; /* connection->operations */ }; +static inline bool +gb_operation_is_incoming(struct gb_operation *operation) +{ + return operation->flags & GB_OPERATION_FLAG_INCOMING; +} + void gb_connection_recv(struct gb_connection *connection, void *data, size_t size); -- cgit v0.10.2 From e3398811c3c3b90501ca67c5de683953efe6cdde Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 1 Jul 2015 12:37:27 +0200 Subject: greybus: operation: add unidirectional-operation flag Add flag to identify unidirectional operations. Use convenience helper rather than open coding the identification when suppressing response messages. Signed-off-by: Johan Hovold Reviewed-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index ad09599..b32010b 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -500,6 +500,9 @@ gb_operation_create_incoming(struct gb_connection *connection, u16 id, /* Caller has made sure we at least have a message header. */ request_size = size - sizeof(struct gb_operation_msg_hdr); + if (!id) + flags |= GB_OPERATION_FLAG_UNIDIRECTIONAL; + operation = gb_operation_create_common(connection, type, request_size, 0, flags, GFP_ATOMIC); if (operation) { @@ -666,7 +669,7 @@ static int gb_operation_response_send(struct gb_operation *operation, } /* Sender of request does not care about response. */ - if (!operation->id) + if (gb_operation_is_unidirectional(operation)) return 0; if (!operation->response) { diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index b6bbc84..07e43a7 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -90,6 +90,7 @@ struct gb_message { }; #define GB_OPERATION_FLAG_INCOMING BIT(0) +#define GB_OPERATION_FLAG_UNIDIRECTIONAL BIT(1) /* * A Greybus operation is a remote procedure call performed over a @@ -135,6 +136,12 @@ gb_operation_is_incoming(struct gb_operation *operation) return operation->flags & GB_OPERATION_FLAG_INCOMING; } +static inline bool +gb_operation_is_unidirectional(struct gb_operation *operation) +{ + return operation->flags & GB_OPERATION_FLAG_UNIDIRECTIONAL; +} + void gb_connection_recv(struct gb_connection *connection, void *data, size_t size); -- cgit v0.10.2 From 2593261d5ca39b0f1afe926ffab907daeb246086 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 1 Jul 2015 12:37:28 +0200 Subject: greybus: operation: remove obsolete operation-field comments Remove obsolete operation-field comments. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 07e43a7..c16f64d 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -123,8 +123,8 @@ struct gb_operation { int errno; /* Operation result */ struct work_struct work; - gb_operation_callback callback; /* If asynchronous */ - struct completion completion; /* Used if no callback */ + gb_operation_callback callback; + struct completion completion; struct kref kref; struct list_head links; /* connection->operations */ -- cgit v0.10.2 From 1635304d6384e258d197ca1bc5f2f6418eae28e2 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 1 Jul 2015 12:37:29 +0200 Subject: greybus: operation: drop redundant oom message Drop redundant OOM message, which would already have been logged by the memory subsystem. Also remove a FIXME about possibly sending a pre-allocated response, which is neither possible or desirable. If we ever run out of memory we have bigger problems then getting a response back to firmware. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index b32010b..d6e1db8 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -673,12 +673,8 @@ static int gb_operation_response_send(struct gb_operation *operation, return 0; if (!operation->response) { - if (!gb_operation_response_alloc(operation, 0)) { - dev_err(&connection->dev, - "error allocating response\n"); - /* XXX Respond with pre-allocated -ENOMEM? */ + if (!gb_operation_response_alloc(operation, 0)) return -ENOMEM; - } } /* Reference will be dropped when message has been sent. */ -- cgit v0.10.2 From fde7382b47c5fbb64be81420d267f1e314cfee94 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 1 Jul 2015 12:37:30 +0200 Subject: greybus: operation: allocate response before setting result Make sure to allocate a response message before setting the operation result. This is needed to handle cancellation of incoming operations. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index d6e1db8..881dddc 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -662,6 +662,12 @@ static int gb_operation_response_send(struct gb_operation *operation, struct gb_connection *connection = operation->connection; int ret; + if (!operation->response && + !gb_operation_is_unidirectional(operation)) { + if (!gb_operation_response_alloc(operation, 0)) + return -ENOMEM; + } + /* Record the result */ if (!gb_operation_result_set(operation, errno)) { dev_err(&connection->dev, "request result already set\n"); @@ -672,11 +678,6 @@ static int gb_operation_response_send(struct gb_operation *operation, if (gb_operation_is_unidirectional(operation)) return 0; - if (!operation->response) { - if (!gb_operation_response_alloc(operation, 0)) - return -ENOMEM; - } - /* Reference will be dropped when message has been sent. */ gb_operation_get(operation); -- cgit v0.10.2 From 188f9785cfc5b1dc306ef1ca36e4c8dd203ccf56 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 1 Jul 2015 12:37:31 +0200 Subject: greybus: operation: fix cancellation of responses An operation with a response in-flight will already have set the operation result and would therefore never be cancelled by the current implementation. Note that the reference taken when sending the result will be dropped in the message completion callback. Also note that an incoming, non-unidirectional messages will always have an allocated response if its result has been set. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 881dddc..9e2ff7d 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -845,9 +845,10 @@ void gb_operation_cancel(struct gb_operation *operation, int errno) { if (gb_operation_result_set(operation, errno)) { gb_message_cancel(operation->request); - if (operation->response) - gb_message_cancel(operation->response); gb_operation_put(operation); + } else if (gb_operation_is_incoming(operation)) { + if (!gb_operation_is_unidirectional(operation)) + gb_message_cancel(operation->response); } } EXPORT_SYMBOL_GPL(gb_operation_cancel); -- cgit v0.10.2 From 3a97cddfe82b9e668d6fc7cd2e6ce7540ec06554 Mon Sep 17 00:00:00 2001 From: Perry Hung Date: Fri, 3 Jul 2015 00:27:12 -0400 Subject: greybus: makefile: fix unused cflags The ccflags variable was spelled wrong, so no extra compilation flags could be specified. The proper flag is 'ccflags-y.' Signed-off-by: Perry Hung Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 4f66ff3..163cd13 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -66,7 +66,7 @@ $(foreach opt,$(CONFIG_OPTIONS_DISABLE),$(if $(filter m y, $(CONFIG_$(opt))), \ endif # add -Wall to try to catch everything we can. -ccFlags-y := -Wall +ccflags-y := -Wall all: module -- cgit v0.10.2 From 513926501dc0d43ce78fd72d00acc9be7fa8c405 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Thu, 2 Jul 2015 19:32:05 +0100 Subject: greybus: examples: add manifest file for sdio Add example manifest file for sdio. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/examples/IID1-simple-sdio-module.mnfs b/drivers/staging/greybus/examples/IID1-simple-sdio-module.mnfs new file mode 100644 index 0000000..10ec8b4 --- /dev/null +++ b/drivers/staging/greybus/examples/IID1-simple-sdio-module.mnfs @@ -0,0 +1,53 @@ +; +; Simple GPIO Interface Manifest +; +; Copyright 2014 Google Inc. +; Copyright 2014 Linaro Ltd. +; +; Provided under the three clause BSD license found in the LICENSE file. +; + +[manifest-header] +version-major = 0 +version-minor = 1 + +[interface-descriptor] +vendor-string-id = 1 +product-string-id = 2 + +; Interface vendor string (id can't be 0) +[string-descriptor "1"] +id = 1 +string = Project Ara + +; Interface product string (id can't be 0) +[string-descriptor "2"] +id = 2 +string = Simple SDIO Interface + +; Control cport and bundle are optional. +; - Control cport's id must be 2 and its bundle number must be 0. +; - No other bundle or control cport may use these values. +; - Class and protocol of bundle and cport must be marked as 0x00. +; +;Control protocol on CPort 2 +[cport-descriptor "2"] +bundle = 0 +id = 2 +protocol = 0x00 + +;Control protocol Bundle 0 +[bundle-descriptor "0"] +class = 0 +id = 0 + +; GPIO protocol on CPort 1 +[cport-descriptor "1"] +bundle = 1 +id = 1 +protocol = 0x07 + +; Bundle 1 +[bundle-descriptor "1"] +class = 7 +id = 1 -- cgit v0.10.2 From df22363d2ada5ef4708310208ff10649adb0b08d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 5 Jul 2015 18:11:21 -0700 Subject: greybus: Revert "examples: add manifest file for sdio" This reverts commit 22690d72ae145cf12ae3df033670ed8ad7ecdde7. It was meant for the gbsim repo, not this one :( Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/examples/IID1-simple-sdio-module.mnfs b/drivers/staging/greybus/examples/IID1-simple-sdio-module.mnfs deleted file mode 100644 index 10ec8b4..0000000 --- a/drivers/staging/greybus/examples/IID1-simple-sdio-module.mnfs +++ /dev/null @@ -1,53 +0,0 @@ -; -; Simple GPIO Interface Manifest -; -; Copyright 2014 Google Inc. -; Copyright 2014 Linaro Ltd. -; -; Provided under the three clause BSD license found in the LICENSE file. -; - -[manifest-header] -version-major = 0 -version-minor = 1 - -[interface-descriptor] -vendor-string-id = 1 -product-string-id = 2 - -; Interface vendor string (id can't be 0) -[string-descriptor "1"] -id = 1 -string = Project Ara - -; Interface product string (id can't be 0) -[string-descriptor "2"] -id = 2 -string = Simple SDIO Interface - -; Control cport and bundle are optional. -; - Control cport's id must be 2 and its bundle number must be 0. -; - No other bundle or control cport may use these values. -; - Class and protocol of bundle and cport must be marked as 0x00. -; -;Control protocol on CPort 2 -[cport-descriptor "2"] -bundle = 0 -id = 2 -protocol = 0x00 - -;Control protocol Bundle 0 -[bundle-descriptor "0"] -class = 0 -id = 0 - -; GPIO protocol on CPort 1 -[cport-descriptor "1"] -bundle = 1 -id = 1 -protocol = 0x07 - -; Bundle 1 -[bundle-descriptor "1"] -class = 7 -id = 1 -- cgit v0.10.2 From ef0cc0ec8d80a18c83aec41321ebeba639cfa09a Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Thu, 2 Jul 2015 19:11:30 +0100 Subject: greybus: sdio: split cmd_flags to there meaning Instead of using values in the command cmd_flags field use the real flags in a bit mask. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 6f8c15e..498f6e9 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -769,10 +769,11 @@ struct gb_sdio_command_request { __u8 cmd; __u8 cmd_flags; #define GB_SDIO_RSP_NONE 0x00 -#define GB_SDIO_RSP_R1_R5_R6_R7 0x01 -#define GB_SDIO_RSP_R1B 0x02 -#define GB_SDIO_RSP_R2 0x03 -#define GB_SDIO_RSP_R3_R4 0x04 +#define GB_SDIO_RSP_PRESENT 0x01 +#define GB_SDIO_RSP_136 0x02 +#define GB_SDIO_RSP_CRC 0x04 +#define GB_SDIO_RSP_BUSY 0x08 +#define GB_SDIO_RSP_OPCODE 0x10 __u8 cmd_type; #define GB_SDIO_CMD_AC 0x00 diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index f028e14..e842cae 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -38,6 +38,14 @@ static struct workqueue_struct *gb_sdio_mrq_workqueue; /* Define get_version() routine */ define_get_version(gb_sdio_host, SDIO); +#define GB_SDIO_RSP_R1_R5_R6_R7 (GB_SDIO_RSP_PRESENT | GB_SDIO_RSP_CRC | \ + GB_SDIO_RSP_OPCODE) +#define GB_SDIO_RSP_R3_R4 (GB_SDIO_RSP_PRESENT) +#define GB_SDIO_RSP_R2 (GB_SDIO_RSP_PRESENT | GB_SDIO_RSP_CRC | \ + GB_SDIO_RSP_136) +#define GB_SDIO_RSP_R1B (GB_SDIO_RSP_PRESENT | GB_SDIO_RSP_CRC | \ + GB_SDIO_RSP_OPCODE | GB_SDIO_RSP_BUSY) + static void _gb_sdio_set_host_caps(struct gb_sdio_host *host, u32 r) { u32 caps = 0; -- cgit v0.10.2 From c36d31cbc57635f7e66176d84d7b8688796a01d3 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Thu, 2 Jul 2015 19:11:31 +0100 Subject: greybus: sdio: rework of event handler Between the time connection with module is up and the host is added, we can receive events (card inserted/removed, write protection switch), so until the setup is complete we queue the events received and handle them after. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index e842cae..53cb46f 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -28,6 +28,7 @@ struct gb_sdio_host { spinlock_t xfer; /* lock to cancel ongoing transfer */ bool xfer_stop; struct work_struct mrqwork; + u8 queued_events; bool removed; bool card_present; bool read_only; @@ -121,54 +122,40 @@ static int gb_sdio_get_caps(struct gb_sdio_host *host) return 0; } -static int gb_sdio_event_recv(u8 type, struct gb_operation *op) +static void _gb_queue_event(struct gb_sdio_host *host, u8 event) { - struct gb_connection *connection = op->connection; - struct gb_sdio_host *host = connection->private; - struct gb_message *request; - struct gb_sdio_event_request *payload; - u8 state_changed = 0; - u8 event; - - if (type != GB_SDIO_TYPE_EVENT) { - dev_err(&connection->dev, - "unsupported unsolicited event: %u\n", type); - return -EINVAL; - } - - request = op->request; + if (event & GB_SDIO_CARD_INSERTED) + host->queued_events &= ~GB_SDIO_CARD_REMOVED; + else if (event & GB_SDIO_CARD_REMOVED) + host->queued_events &= ~GB_SDIO_CARD_INSERTED; - if (request->payload_size != sizeof(*payload)) { - dev_err(mmc_dev(host->mmc), "wrong event size received\n"); - return -EINVAL; - } + host->queued_events |= event; +} - payload = request->payload; - event = payload->event; +static int _gb_sdio_process_events(struct gb_sdio_host *host, u8 event) +{ + u8 state_changed = 0; - switch (event) { - case GB_SDIO_CARD_INSERTED: + if (event & GB_SDIO_CARD_INSERTED) { if (!mmc_card_is_removable(host->mmc)) return 0; if (host->card_present) return 0; host->card_present = true; state_changed = 1; - break; - case GB_SDIO_CARD_REMOVED: + } + + if (event & GB_SDIO_CARD_REMOVED) { if (!mmc_card_is_removable(host->mmc)) return 0; if (!(host->card_present)) return 0; host->card_present = false; state_changed = 1; - break; - case GB_SDIO_WP: + } + + if (event & GB_SDIO_WP) { host->read_only = true; - break; - default: - dev_err(mmc_dev(host->mmc), "wrong event received %d\n", event); - return -EINVAL; } if (state_changed) { @@ -180,6 +167,39 @@ static int gb_sdio_event_recv(u8 type, struct gb_operation *op) return 0; } +static int gb_sdio_event_recv(u8 type, struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_sdio_host *host = connection->private; + struct gb_message *request; + struct gb_sdio_event_request *payload; + int ret = 0; + u8 event; + + if (type != GB_SDIO_TYPE_EVENT) { + dev_err(&connection->dev, + "unsupported unsolicited event: %u\n", type); + return -EINVAL; + } + + request = op->request; + + if (request->payload_size != sizeof(*payload)) { + dev_err(mmc_dev(host->mmc), "wrong event size received\n"); + return -EINVAL; + } + + payload = request->payload; + event = payload->event; + + if (host->removed) + _gb_queue_event(host, event); + else + ret = _gb_sdio_process_events(host, event); + + return ret; +} + static int gb_sdio_set_ios(struct gb_sdio_host *host, struct gb_sdio_set_ios_request *request) { @@ -649,6 +669,7 @@ static int gb_sdio_connection_init(struct gb_connection *connection) host = mmc_priv(mmc); host->mmc = mmc; + host->removed = true; host->connection = connection; connection->private = host; @@ -683,6 +704,9 @@ static int gb_sdio_connection_init(struct gb_connection *connection) ret = mmc_add_host(mmc); if (ret < 0) goto free_work; + host->removed = false; + ret = _gb_sdio_process_events(host, host->queued_events); + host->queued_events = 0; return ret; -- cgit v0.10.2 From 08ccc9be680debdeb9eb2dcaa83c5fc7cd71f487 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Thu, 2 Jul 2015 19:11:32 +0100 Subject: greybus: sdio: fix return of get_cd and get_ro Functions were returning the wrong flag for the expected value. Swap them. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index 53cb46f..f6adf09 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -635,7 +635,7 @@ static int gb_mmc_get_ro(struct mmc_host *mmc) if (host->removed) return -ESHUTDOWN; mutex_unlock(&host->lock); - return host->card_present; + return host->read_only; } static int gb_mmc_get_cd(struct mmc_host *mmc) @@ -646,7 +646,7 @@ static int gb_mmc_get_cd(struct mmc_host *mmc) if (host->removed) return -ESHUTDOWN; mutex_unlock(&host->lock); - return host->read_only; + return host->card_present; } static const struct mmc_host_ops gb_sdio_ops = { -- cgit v0.10.2 From 7a5cd5aea29a6fa0d99fb3b667b96b8d5f4e596c Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Thu, 2 Jul 2015 19:11:33 +0100 Subject: greybus: sdio: fix call to stop command if no data exist If data is not available the stop command could dereference NULL. Fetch the stop command directly from the request instead. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index f6adf09..8dd833e 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -443,8 +443,8 @@ static void gb_sdio_mrq_work(struct work_struct *work) goto done; } - if (mrq->data->stop) { - ret = gb_sdio_command(host, mrq->data->stop); + if (mrq->stop) { + ret = gb_sdio_command(host, mrq->stop); if (ret < 0) goto done; } -- cgit v0.10.2 From 882edf59fcfa400547bdb509e67f2266471f838d Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Thu, 2 Jul 2015 19:11:34 +0100 Subject: greybus: sdio: pass only data pointer to tranfer funtion No need to pass the all request to the transfer related funtctions. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index 8dd833e..8e7b7ba 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -285,9 +285,8 @@ static int _gb_sdio_recv(struct gb_sdio_host *host, struct mmc_data *data, return 0; } -static int gb_sdio_transfer(struct gb_sdio_host *host, struct mmc_request *mrq) +static int gb_sdio_transfer(struct gb_sdio_host *host, struct mmc_data *data) { - struct mmc_data *data = mrq->data; size_t left, len; off_t skip = 0; int ret = 0; @@ -438,7 +437,7 @@ static void gb_sdio_mrq_work(struct work_struct *work) goto done; if (mrq->data) { - ret = gb_sdio_transfer(host, host->mrq); + ret = gb_sdio_transfer(host, host->mrq->data); if (ret < 0) goto done; } -- cgit v0.10.2 From 73f4a5217968d51d9685732512d268c71b78a347 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Thu, 2 Jul 2015 19:11:35 +0100 Subject: greybus: sdio: check number of blocks in transfer Before initiating a transfers, check if the command (for single block) match the number of blocks in the request. While at it, fix also a missing break. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index 8e7b7ba..544dbda 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -47,6 +47,14 @@ define_get_version(gb_sdio_host, SDIO); #define GB_SDIO_RSP_R1B (GB_SDIO_RSP_PRESENT | GB_SDIO_RSP_CRC | \ GB_SDIO_RSP_OPCODE | GB_SDIO_RSP_BUSY) +static inline bool single_op(struct mmc_command *cmd) +{ + uint32_t opcode = cmd->opcode; + + return opcode == MMC_WRITE_BLOCK || + opcode == MMC_READ_SINGLE_BLOCK; +} + static void _gb_sdio_set_host_caps(struct gb_sdio_host *host, u32 r) { u32 caps = 0; @@ -292,6 +300,11 @@ static int gb_sdio_transfer(struct gb_sdio_host *host, struct mmc_data *data) int ret = 0; u16 nblocks; + if (single_op(data->mrq->cmd) && data->blocks > 1) { + ret = -ETIMEDOUT; + goto out; + } + left = data->blksz * data->blocks; while (left) { @@ -351,6 +364,7 @@ static int gb_sdio_command(struct gb_sdio_host *host, struct mmc_command *cmd) break; case MMC_RSP_R3: cmd_flags = GB_SDIO_RSP_R3_R4; + break; default: dev_err(mmc_dev(host->mmc), "cmd flag invalid %04x\n", mmc_resp_type(cmd)); -- cgit v0.10.2 From f85451d8f58cd6df8643838b249016449f4d6218 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Thu, 2 Jul 2015 19:11:36 +0100 Subject: greybus: sdio: add need poll to host caps As we do not have, yet, a event callback to notify core about changes we add the MMC_CAP_NEEDS_POLL capability to the rest of the caps received from the module. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index 544dbda..33d5fe6 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -85,7 +85,7 @@ static void _gb_sdio_set_host_caps(struct gb_sdio_host *host, u32 r) #endif (r & GB_SDIO_CAP_HS200_1_8V ? MMC_CAP2_HS200_1_8V_SDR : 0); - host->mmc->caps = caps; + host->mmc->caps = caps | MMC_CAP_NEEDS_POLL; host->mmc->caps2 = caps2; if (caps & MMC_CAP_NONREMOVABLE) -- cgit v0.10.2 From 9ddf133371fd87ddf543e8b26389ca26f2d9fc3c Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Thu, 2 Jul 2015 19:11:37 +0100 Subject: greybus: sdio: fix transfer buffer handling and blocks counting Fix copy to/from scatterlist destination buffer offset, fix calculation of blocks to be transfer and make a more verbose out of error when the blocks receive/send do not match. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index 33d5fe6..a709bd6 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -234,22 +234,25 @@ static int _gb_sdio_send(struct gb_sdio_host *host, struct mmc_data *data, request->data_blocks = cpu_to_le16(nblocks); request->data_blksz = cpu_to_le16(data->blksz); - copied = sg_pcopy_to_buffer(sg, sg_len, &request->data[0] + skip, len, - skip); + copied = sg_pcopy_to_buffer(sg, sg_len, &request->data[0], len, skip); if (copied != len) return -EINVAL; ret = gb_operation_sync(host->connection, GB_SDIO_TYPE_TRANSFER, - request, len, &response, sizeof(response)); + request, len + sizeof(*request), + &response, sizeof(response)); if (ret < 0) return ret; send_blocks = le16_to_cpu(response.data_blocks); send_blksz = le16_to_cpu(response.data_blksz); - if (len != send_blksz * send_blocks) + if (len != send_blksz * send_blocks) { + dev_err(mmc_dev(host->mmc), "send: size received: %zu != %d\n", + len, send_blksz * send_blocks); return -EINVAL; + } return ret; } @@ -275,18 +278,22 @@ static int _gb_sdio_recv(struct gb_sdio_host *host, struct mmc_data *data, response = host->xfer_buffer; ret = gb_operation_sync(host->connection, GB_SDIO_TYPE_TRANSFER, - &request, sizeof(request), response, len); + &request, sizeof(request), response, len + + sizeof(*response)); if (ret < 0) return ret; recv_blocks = le16_to_cpu(response->data_blocks); recv_blksz = le16_to_cpu(response->data_blksz); - if (len != recv_blksz * recv_blocks) + if (len != recv_blksz * recv_blocks) { + dev_err(mmc_dev(host->mmc), "recv: size received: %d != %zu\n", + recv_blksz * recv_blocks, len); return -EINVAL; + } - copied = sg_pcopy_from_buffer(sg, sg_len, &response->data[0] + skip, - len, skip); + copied = sg_pcopy_from_buffer(sg, sg_len, &response->data[0], len, + skip); if (copied != len) return -EINVAL; @@ -318,7 +325,7 @@ static int gb_sdio_transfer(struct gb_sdio_host *host, struct mmc_data *data) } spin_unlock(&host->xfer); len = min(left, host->data_max); - nblocks = do_div(len, data->blksz); + nblocks = len / data->blksz; len = nblocks * data->blksz; if (data->flags & MMC_DATA_READ) { -- cgit v0.10.2 From 6fa1adbcdd28f27b639954e5bb202a2de281679a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 3 Jul 2015 17:00:25 +0530 Subject: greybus: connection: Exit connection before destroying it gb_connection_create() can initialize a connection if bundle->device id is valid. And so the connection must be destroyed by calling gb_connection_exit() before gb_connection_destroy(). This wasn't done in the code that is parsing the manifest. Fix it. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index ce4e89c..bea565f 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -255,6 +255,7 @@ cleanup: /* An error occurred; undo any changes we've made */ list_for_each_entry_safe(connection, connection_next, &bundle->connections, bundle_links) { + gb_connection_exit(connection); gb_connection_destroy(connection); count--; } -- cgit v0.10.2 From b950dc28bd47949fed64afa28c01c90be5dca43b Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 3 Jul 2015 17:00:26 +0530 Subject: greybus: interface: Fix comment mistake (s/add/init) Function's name is gb_interface_init(), not gb_interface_add(). Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index f9fd479..1e5e629 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -189,7 +189,7 @@ static void gb_interface_destroy(struct gb_interface *intf) } /** - * gb_interface_add + * gb_interface_init * * Create connection for control CPort and then request/parse manifest. * Finally initialize all the bundles to set routes via SVC and initialize all -- cgit v0.10.2 From 87c016ee908b8727f8d812bf3a36844be20d3410 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 3 Jul 2015 17:00:27 +0530 Subject: greybus: connection: Use connection->dev for printing messages We failed to bind a protocol for the connection, not for bundle. And so connection's 'dev' must be used for printing message. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 2e306d1..6994a84 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -209,7 +209,7 @@ struct gb_connection *gb_connection_create(struct gb_bundle *bundle, /* XXX Will have to establish connections to get version */ gb_connection_bind_protocol(connection); if (!connection->protocol) - dev_warn(&bundle->dev, + dev_warn(&connection->dev, "protocol 0x%02hhx handler not found\n", protocol_id); return connection; -- cgit v0.10.2 From ab69c4cea3b4ddf6bce4db810db37a3911b08e15 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 3 Jul 2015 17:00:29 +0530 Subject: greybus: svc: SVC is part of greybus core Its an essential part of greybus core and shouldn't be present as a separate module. Make it part of greybus.ko module. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 163cd13..1467c5b 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -9,6 +9,7 @@ greybus-y := core.o \ connection.o \ protocol.o \ control.o \ + svc.o \ operation.o gb-phy-y := gpbridge.o \ @@ -26,7 +27,6 @@ gb-phy-y := gpbridge.o \ audio-gb-cmds.o # Prefix all modules with gb- -gb-svc-y := svc.o gb-vibrator-y := vibrator.o gb-battery-y := battery.o gb-loopback-y := loopback.o @@ -35,7 +35,6 @@ gb-es1-y := es1.o gb-es2-y := es2.o obj-m += greybus.o -obj-m += gb-svc.o obj-m += gb-phy.o obj-m += gb-vibrator.o obj-m += gb-battery.o diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 8d16e10..925e1dc 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -280,8 +280,16 @@ static int __init gb_init(void) goto error_control; } + retval = gb_svc_protocol_init(); + if (retval) { + pr_err("gb_svc_protocol_init failed\n"); + goto error_svc; + } + return 0; /* Success */ +error_svc: + gb_control_protocol_exit(); error_control: gb_endo_exit(); error_endo: @@ -299,6 +307,7 @@ module_init(gb_init); static void __exit gb_exit(void) { + gb_svc_protocol_exit(); gb_control_protocol_exit(); gb_endo_exit(); gb_operation_exit(); diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 75b3337..8a5a9b7 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -239,5 +239,4 @@ static struct gb_protocol svc_protocol = { .connection_exit = gb_svc_connection_exit, .request_recv = gb_svc_request_recv, }; - -gb_protocol_driver(&svc_protocol); +gb_builtin_protocol_driver(svc_protocol); diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index e26e637..b039aea 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -19,4 +19,6 @@ int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, int gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id); +int gb_svc_protocol_init(void); +void gb_svc_protocol_exit(void); #endif /* __SVC_H */ -- cgit v0.10.2 From 6ceb8fdeaec665642de944ee47d11440e72a5e26 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 3 Jul 2015 17:00:30 +0530 Subject: greybus: svc: save pointer to struct gb_svc in struct gb_interface Its another special protocol (just like control protocol) and is required to be accessed from other files, lets save a pointer to it in interface structure. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 86eb894..c2bcb92 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -14,6 +14,7 @@ struct gb_interface { struct device dev; struct gb_control *control; + struct gb_svc *svc; struct list_head bundles; struct list_head links; /* greybus_host_device->interfaces */ diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 8a5a9b7..ce789c9 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -9,12 +9,6 @@ #include "greybus.h" -struct gb_svc { - struct gb_connection *connection; - u8 version_major; - u8 version_minor; -}; - /* Define get_version() routine */ define_get_version(gb_svc, SVC); @@ -217,6 +211,9 @@ static int gb_svc_connection_init(struct gb_connection *connection) if (ret) kfree(svc); + /* Set interface's svc connection */ + connection->bundle->intf->svc = svc; + return ret; } @@ -224,9 +221,11 @@ static void gb_svc_connection_exit(struct gb_connection *connection) { struct gb_svc *svc = connection->private; - if (!svc) + if (WARN_ON(connection->bundle->intf->svc != svc)) return; + connection->bundle->intf->svc = NULL; + kfree(svc); } diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index b039aea..ebabe5f 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -10,7 +10,12 @@ #ifndef __SVC_H #define __SVC_H -struct gb_svc; +struct gb_svc { + struct gb_connection *connection; + u8 version_major; + u8 version_minor; +}; + int gb_svc_intf_device_id(struct gb_svc *svc, u8 intf_id, u8 device_id); int gb_svc_intf_reset(struct gb_svc *svc, u8 intf_id); -- cgit v0.10.2 From 5c1ac6945526c76258869c8c04632ab5ae61bdab Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 8 Jul 2015 10:44:09 -0700 Subject: greybus: properly cleanup ida and idr structures when shutting down idr and ida structures have internal memory allocated that needs to be freed when modules are removed. So call the proper idr_destroy() or ida_destroy() functions on the module exit path to free the memory. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/raw.c b/drivers/staging/greybus/raw.c index d93d052..3be96db 100644 --- a/drivers/staging/greybus/raw.c +++ b/drivers/staging/greybus/raw.c @@ -364,6 +364,7 @@ static void __exit raw_exit(void) gb_protocol_deregister(&raw_protocol); unregister_chrdev_region(MKDEV(raw_major, 0), NUM_MINORS); class_destroy(raw_class); + ida_destroy(&minors); } module_exit(raw_exit); diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index e2a456f..3932f86 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -761,6 +761,7 @@ static void gb_tty_exit(void) { tty_unregister_driver(gb_tty_driver); put_tty_driver(gb_tty_driver); + idr_destroy(&tty_minors); } static struct gb_protocol uart_protocol = { diff --git a/drivers/staging/greybus/vibrator.c b/drivers/staging/greybus/vibrator.c index 20f09bb..62b3552 100644 --- a/drivers/staging/greybus/vibrator.c +++ b/drivers/staging/greybus/vibrator.c @@ -190,6 +190,7 @@ static __exit void protocol_exit(void) { gb_protocol_deregister(&vibrator_protocol); class_unregister(&vibrator_class); + ida_destroy(&minors); } module_exit(protocol_exit); -- cgit v0.10.2 From 85109f7ddde4b1842bfb08741a8b461e31ef2c4f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 9 Jul 2015 15:17:58 +0200 Subject: greybus: operation: fix operation-destroy race Make sure to acquire the connection-list lock atomically when releasing the final reference. This allows the list to be traversed and references to be acquired (while holding the lock) without racing with the destructor. Suggested-by: Greg Kroah-Hartman Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 9e2ff7d..f8d7df9 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -528,14 +528,12 @@ EXPORT_SYMBOL_GPL(gb_operation_get); static void _gb_operation_destroy(struct kref *kref) { struct gb_operation *operation; - unsigned long flags; operation = container_of(kref, struct gb_operation, kref); /* XXX Make sure it's not in flight */ - spin_lock_irqsave(&gb_operations_lock, flags); list_del(&operation->links); - spin_unlock_irqrestore(&gb_operations_lock, flags); + spin_unlock(&gb_operations_lock); if (operation->response) gb_operation_message_free(operation->response); @@ -550,8 +548,11 @@ static void _gb_operation_destroy(struct kref *kref) */ void gb_operation_put(struct gb_operation *operation) { - if (!WARN_ON(!operation)) - kref_put(&operation->kref, _gb_operation_destroy); + if (WARN_ON(!operation)) + return; + + kref_put_spinlock_irqsave(&operation->kref, _gb_operation_destroy, + &gb_operations_lock); } EXPORT_SYMBOL_GPL(gb_operation_put); -- cgit v0.10.2 From 0581f28efb86d8eb7e7f6baf712578477f7c868e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 9 Jul 2015 15:17:59 +0200 Subject: greybus: operation: fix use-after-free in response receive path Fix potential use-after-free in response receive path, due to lack of reference counting when looking up operations on a connection. Make sure to acquire a reference to the operation while holding the connection-list lock. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index f8d7df9..8f99c8e 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -114,6 +114,10 @@ int gb_operation_result(struct gb_operation *operation) } EXPORT_SYMBOL_GPL(gb_operation_result); +/* + * Looks up an operation on a connection and returns a refcounted pointer if + * found, or NULL otherwise. + */ static struct gb_operation * gb_operation_find(struct gb_connection *connection, u16 operation_id) { @@ -124,6 +128,7 @@ gb_operation_find(struct gb_connection *connection, u16 operation_id) spin_lock_irqsave(&gb_operations_lock, flags); list_for_each_entry(operation, &connection->operations, links) if (operation->id == operation_id) { + gb_operation_get(operation); found = true; break; } @@ -795,6 +800,8 @@ static void gb_connection_recv_response(struct gb_connection *connection, /* The rest will be handled in work queue context */ if (gb_operation_result_set(operation, errno)) queue_work(gb_operation_workqueue, &operation->work); + + gb_operation_put(operation); } /* -- cgit v0.10.2 From 048a7ffe274280c27fc572ba3ec7150eba6efc40 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 9 Jul 2015 15:18:00 +0200 Subject: greybus: operation: fix outgoing-response corruption Fix potential corruption of outgoing responses by verifying that the operations is indeed outgoing when receiving a response. Failure to do so could lead to an incoming response corrupting an outgoing response that uses the same operation id. Reported-by: Viresh Kumar Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 8f99c8e..8539462 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -115,11 +115,11 @@ int gb_operation_result(struct gb_operation *operation) EXPORT_SYMBOL_GPL(gb_operation_result); /* - * Looks up an operation on a connection and returns a refcounted pointer if - * found, or NULL otherwise. + * Looks up an outgoing operation on a connection and returns a refcounted + * pointer if found, or NULL otherwise. */ static struct gb_operation * -gb_operation_find(struct gb_connection *connection, u16 operation_id) +gb_operation_find_outgoing(struct gb_connection *connection, u16 operation_id) { struct gb_operation *operation; unsigned long flags; @@ -127,7 +127,8 @@ gb_operation_find(struct gb_connection *connection, u16 operation_id) spin_lock_irqsave(&gb_operations_lock, flags); list_for_each_entry(operation, &connection->operations, links) - if (operation->id == operation_id) { + if (operation->id == operation_id && + !gb_operation_is_incoming(operation)) { gb_operation_get(operation); found = true; break; @@ -778,7 +779,7 @@ static void gb_connection_recv_response(struct gb_connection *connection, int errno = gb_operation_status_map(result); size_t message_size; - operation = gb_operation_find(connection, operation_id); + operation = gb_operation_find_outgoing(connection, operation_id); if (!operation) { dev_err(&connection->dev, "operation not found\n"); return; -- cgit v0.10.2 From e4340b13fd2cf9bcf1f0a40ae15de454ffdb74f8 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 9 Jul 2015 15:18:01 +0200 Subject: greybus: operation: fix incoming-response corruption Make sure not to update the response message buffer for an operation that is already scheduled for completion. Currently if we get two incoming responses with the same id, the second one would overwrite the response message buffer. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 8539462..b78c55f 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -796,11 +796,12 @@ static void gb_connection_recv_response(struct gb_connection *connection, /* We must ignore the payload if a bad status is returned */ if (errno) size = sizeof(*message->header); - memcpy(message->header, data, size); /* The rest will be handled in work queue context */ - if (gb_operation_result_set(operation, errno)) + if (gb_operation_result_set(operation, errno)) { + memcpy(message->header, data, size); queue_work(gb_operation_workqueue, &operation->work); + } gb_operation_put(operation); } -- cgit v0.10.2 From e99f305bb7cc3e22c508440d2a52e8c84c9b507a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 9 Jul 2015 10:56:30 +0530 Subject: greybus: Cleanup connection leftovers This wouldn't happen normally, but in a buggy corner case it is possible that all the connections aren't removed properly and they are still present after the interfaces and endo are removed. Warn in such a case and cleanup connections, so that /sys/bus/greybus/ can be removed while removing greybus modules. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 6994a84..65a2bd5 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -313,3 +313,13 @@ void gb_connection_exit(struct gb_connection *connection) cport_id, ret); } } + +void gb_hd_connections_exit(struct greybus_host_device *hd) +{ + struct gb_connection *connection; + + list_for_each_entry(connection, &hd->connections, hd_links) { + gb_connection_exit(connection); + gb_connection_destroy(connection); + } +} diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index acf9183..ad699db 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -50,6 +50,7 @@ void gb_connection_destroy(struct gb_connection *connection); int gb_connection_init(struct gb_connection *connection); void gb_connection_exit(struct gb_connection *connection); +void gb_hd_connections_exit(struct greybus_host_device *hd); void greybus_data_rcvd(struct greybus_host_device *hd, u16 cport_id, u8 *data, size_t length); diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 925e1dc..3b1be2d 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -235,6 +235,13 @@ void greybus_remove_hd(struct greybus_host_device *hd) */ gb_interfaces_remove(hd); gb_endo_remove(hd->endo); + + /* + * Make sure there are no leftovers that can potentially corrupt sysfs. + */ + if (WARN_ON(!list_empty(&hd->connections))) + gb_hd_connections_exit(hd); + kref_put_mutex(&hd->kref, free_hd, &hd_mutex); } EXPORT_SYMBOL_GPL(greybus_remove_hd); -- cgit v0.10.2 From f9f971a2e5b5094cf12480976fb1765376414eac Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 13 Jul 2015 20:20:45 +0100 Subject: greybus: loopback: Move loopback operation definitions In order to have one point of type definition for gbsim move the loopback operation definitions to greybus_protocols.h. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 498f6e9..9823d16 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -657,6 +657,27 @@ struct gb_uart_serial_state_request { __u8 control; }; +/* Loopback */ + +/* Version of the Greybus loopback protocol we support */ +#define GB_LOOPBACK_VERSION_MAJOR 0x00 +#define GB_LOOPBACK_VERSION_MINOR 0x01 + +/* Greybus loopback request types */ +#define GB_LOOPBACK_TYPE_INVALID 0x00 +#define GB_LOOPBACK_TYPE_PROTOCOL_VERSION 0x01 +#define GB_LOOPBACK_TYPE_PING 0x02 +#define GB_LOOPBACK_TYPE_TRANSFER 0x03 + +struct gb_loopback_transfer_request { + __le32 len; + __u8 data[0]; +}; + +struct gb_loopback_transfer_response { + __u8 data[0]; +}; + /* SDIO */ /* Version of the Greybus sdio protocol we support */ #define GB_SDIO_VERSION_MAJOR 0x00 diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index eeec332..59c437b 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -45,16 +45,6 @@ struct gb_loopback { u32 error; }; -/* Version of the Greybus loopback protocol we support */ -#define GB_LOOPBACK_VERSION_MAJOR 0x00 -#define GB_LOOPBACK_VERSION_MINOR 0x01 - -/* Greybus loopback request types */ -#define GB_LOOPBACK_TYPE_INVALID 0x00 -#define GB_LOOPBACK_TYPE_PROTOCOL_VERSION 0x01 -#define GB_LOOPBACK_TYPE_PING 0x02 -#define GB_LOOPBACK_TYPE_TRANSFER 0x03 - /* Current function (type of traffic generated by the loopback thread) */ #define GB_LOOPBACK_FN_NONE 0x00 #define GB_LOOPBACK_FN_PING 0x01 @@ -175,16 +165,6 @@ static struct attribute *loopback_attrs[] = { }; ATTRIBUTE_GROUPS(loopback); -struct gb_loopback_transfer_request { - __le32 len; - __u8 data[0]; -}; - -struct gb_loopback_transfer_response { - __u8 data[0]; -}; - - static int gb_loopback_transfer(struct gb_loopback *gb, struct timeval *tping, u32 len) { -- cgit v0.10.2 From a0ee3d3ea6c1b8d731ca68c78db53035862ab3ae Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 13 Jul 2015 20:20:46 +0100 Subject: greybus: loopback: remove magic number in state-machine Magic number 2 used instead of define GB_LOOPBACK_TYPE_PING, remove and and use the define instead. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 59c437b..9ede480 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -356,7 +356,7 @@ static int gb_loopback_fn(void *data) gb->elapsed_nsecs = timeval_to_ns(&gb->te) - timeval_to_ns(&gb->ts); gb_loopback_freq_update(gb); - if (gb->type == 2) + if (gb->type == GB_LOOPBACK_TYPE_PING) gb_loopback_bw_update(gb, error); gb_loopback_latency_update(gb, &tlat); if (gb->elapsed_nsecs >= NSEC_PER_SEC) -- cgit v0.10.2 From 74a240a029fd0fa692bd857f15ceb6eda4897c5d Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 13 Jul 2015 20:20:47 +0100 Subject: greybus: loopback: remove spurious pr_err in sysfs store Dangling debug code removed. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 9ede480..6cd4acf 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -107,7 +107,6 @@ static ssize_t field##_store(struct device *dev, \ struct gb_loopback *gb = \ (struct gb_loopback *)connection->private; \ ret = sscanf(buf, "%"#type, &gb->field); \ - pr_err("%s = %"#type"\n", #field, gb->field); \ if (ret != 1) \ return -EINVAL; \ gb_loopback_check_attr(gb); \ -- cgit v0.10.2 From a598f4384d9e95532781adc316793983ed27139d Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 13 Jul 2015 20:20:48 +0100 Subject: greybus: loopback: make loopback type input equivalent to protocol type Sepcifying loopback operation type with a type value that is internal to the loopback driver is non-intunitive and requires reading code to understand. Remove confusing duplicate definitions and update code to accept the greybus-specification function identity defintiions as the appropriate type values for initiating loopback operations. See greybus-spec section 10.16.1 'Greybus Loopback Message Types' for a full list of valid messages to set this type field to. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 6cd4acf..bdbebd6 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -45,12 +45,6 @@ struct gb_loopback { u32 error; }; -/* Current function (type of traffic generated by the loopback thread) */ -#define GB_LOOPBACK_FN_NONE 0x00 -#define GB_LOOPBACK_FN_PING 0x01 -#define GB_LOOPBACK_FN_XFER 0x02 -#define GB_LOOPBACK_FN_COUNT 0x03 - #define GB_LOOPBACK_MS_WAIT_MAX 1000 #define GB_LOOPBACK_SIZE_MAX SZ_4K @@ -117,10 +111,16 @@ static DEVICE_ATTR_RW(field) static void gb_loopback_reset_stats(struct gb_loopback *gb); static void gb_loopback_check_attr(struct gb_loopback *gb) { + switch (gb->type) { + case GB_LOOPBACK_TYPE_PING: + case GB_LOOPBACK_TYPE_TRANSFER: + break; + default: + gb->type = 0; + break; + } if (gb->ms_wait > GB_LOOPBACK_MS_WAIT_MAX) gb->ms_wait = GB_LOOPBACK_MS_WAIT_MAX; - if (gb->type >= GB_LOOPBACK_FN_COUNT) - gb->type = GB_LOOPBACK_FN_NONE; if (gb->size > GB_LOOPBACK_SIZE_MAX) gb->size = GB_LOOPBACK_SIZE_MAX; gb->error = 0; @@ -337,13 +337,13 @@ static int gb_loopback_fn(void *data) struct gb_loopback *gb = (struct gb_loopback *)data; while (!kthread_should_stop()) { - if (gb->type == GB_LOOPBACK_FN_NONE) { + if (!gb->type) { msleep(1000); continue; } - if (gb->type == GB_LOOPBACK_FN_PING) + if (gb->type == GB_LOOPBACK_TYPE_PING) error = gb_loopback_ping(gb, &tlat); - else if (gb->type == GB_LOOPBACK_FN_XFER) + else if (gb->type == GB_LOOPBACK_TYPE_TRANSFER) error = gb_loopback_transfer(gb, &tlat, gb->size); if (error) gb->error++; -- cgit v0.10.2 From 384a7a3c4f8bf96a6b2e0bddafec41f929b50958 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 13 Jul 2015 20:20:49 +0100 Subject: greybus: loopback: add sink to loopback protocol Loopback sink command will operate as an amalgam of the ping and tranfer operations. Sink will send an ACK'd variable size operation over greybus. Unlike the transfer type which transmits the received data back, the sink type will simply ACK without sending the received data back. This patch adds the kernel side of the sink command. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 9823d16..d3cce68 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -668,6 +668,7 @@ struct gb_uart_serial_state_request { #define GB_LOOPBACK_TYPE_PROTOCOL_VERSION 0x01 #define GB_LOOPBACK_TYPE_PING 0x02 #define GB_LOOPBACK_TYPE_TRANSFER 0x03 +#define GB_LOOPBACK_TYPE_SINK 0x04 struct gb_loopback_transfer_request { __le32 len; diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index bdbebd6..678690f 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -114,6 +114,7 @@ static void gb_loopback_check_attr(struct gb_loopback *gb) switch (gb->type) { case GB_LOOPBACK_TYPE_PING: case GB_LOOPBACK_TYPE_TRANSFER: + case GB_LOOPBACK_TYPE_SINK: break; default: gb->type = 0; @@ -164,6 +165,31 @@ static struct attribute *loopback_attrs[] = { }; ATTRIBUTE_GROUPS(loopback); +static int gb_loopback_sink(struct gb_loopback *gb, + struct timeval *tping, u32 len) +{ + struct timeval ts, te; + u64 elapsed_nsecs; + struct gb_loopback_transfer_request *request; + int retval; + + request = kmalloc(len + sizeof(*request), GFP_KERNEL); + if (!request) + return -ENOMEM; + + request->len = cpu_to_le32(len); + + do_gettimeofday(&ts); + retval = gb_operation_sync(gb->connection, GB_LOOPBACK_TYPE_SINK, + request, len + sizeof(*request), NULL, 0); + do_gettimeofday(&te); + elapsed_nsecs = timeval_to_ns(&te) - timeval_to_ns(&ts); + *tping = ns_to_timeval(elapsed_nsecs); + + kfree(request); + return retval; +} + static int gb_loopback_transfer(struct gb_loopback *gb, struct timeval *tping, u32 len) { @@ -235,6 +261,7 @@ static int gb_loopback_request_recv(u8 type, struct gb_operation *operation) "module-initiated version operation\n"); return -EINVAL; case GB_LOOPBACK_TYPE_PING: + case GB_LOOPBACK_TYPE_SINK: return 0; case GB_LOOPBACK_TYPE_TRANSFER: if (operation->request->payload_size < sizeof(*request)) { @@ -345,6 +372,8 @@ static int gb_loopback_fn(void *data) error = gb_loopback_ping(gb, &tlat); else if (gb->type == GB_LOOPBACK_TYPE_TRANSFER) error = gb_loopback_transfer(gb, &tlat, gb->size); + else if (gb->type == GB_LOOPBACK_TYPE_SINK) + error = gb_loopback_sink(gb, &tlat, gb->size); if (error) gb->error++; if (gb->ts.tv_usec == 0 && gb->ts.tv_sec == 0) { -- cgit v0.10.2 From c3bba87a7ab57e636a8c96ddd36fdedfefe4848c Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 13 Jul 2015 20:20:50 +0100 Subject: greybus: loopback: truncate maximum loop data to link size Get maximum payload by way of gb_operation_get_payload_size_max() and truncate any requested loopback size greater than this value. RX of data from firmware over the specified size will not be accepted. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 678690f..f490648 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -34,6 +34,7 @@ struct gb_loopback { int type; u32 size; + u32 size_max; int ms_wait; struct gb_loopback_stats latency; @@ -46,7 +47,6 @@ struct gb_loopback { }; #define GB_LOOPBACK_MS_WAIT_MAX 1000 -#define GB_LOOPBACK_SIZE_MAX SZ_4K /* Define get_version() routine */ define_get_version(gb_loopback, LOOPBACK); @@ -122,8 +122,8 @@ static void gb_loopback_check_attr(struct gb_loopback *gb) } if (gb->ms_wait > GB_LOOPBACK_MS_WAIT_MAX) gb->ms_wait = GB_LOOPBACK_MS_WAIT_MAX; - if (gb->size > GB_LOOPBACK_SIZE_MAX) - gb->size = GB_LOOPBACK_SIZE_MAX; + if (gb->size > gb->size_max) + gb->size = gb->size_max; gb->error = 0; gb_loopback_reset_stats(gb); } @@ -182,6 +182,7 @@ static int gb_loopback_sink(struct gb_loopback *gb, do_gettimeofday(&ts); retval = gb_operation_sync(gb->connection, GB_LOOPBACK_TYPE_SINK, request, len + sizeof(*request), NULL, 0); + do_gettimeofday(&te); elapsed_nsecs = timeval_to_ns(&te) - timeval_to_ns(&ts); *tping = ns_to_timeval(elapsed_nsecs); @@ -250,6 +251,7 @@ static int gb_loopback_ping(struct gb_loopback *gb, struct timeval *tping) static int gb_loopback_request_recv(u8 type, struct gb_operation *operation) { struct gb_connection *connection = operation->connection; + struct gb_loopback *gb = connection->private; struct gb_loopback_transfer_request *request; struct gb_loopback_transfer_response *response; u32 len; @@ -273,6 +275,13 @@ static int gb_loopback_request_recv(u8 type, struct gb_operation *operation) } request = operation->request->payload; len = le32_to_cpu(request->len); + if (len > gb->size_max) { + dev_err(&connection->dev, + "transfer request too large (%zu > %zu)\n", + len, gb->size_max); + return -EINVAL; + } + if (len) { if (!gb_operation_response_alloc(operation, len)) { dev_err(&connection->dev, @@ -416,6 +425,14 @@ static int gb_loopback_connection_init(struct gb_connection *connection) if (retval) goto out_get_ver; + /* Calculate maximum payload */ + gb->size_max = gb_operation_get_payload_size_max(connection); + if (gb->size_max <= sizeof(struct gb_loopback_transfer_request)) { + retval = -EINVAL; + goto out_get_ver; + } + gb->size_max -= sizeof(struct gb_loopback_transfer_request); + gb_loopback_reset_stats(gb); gb->task = kthread_run(gb_loopback_fn, gb, "gb_loopback"); if (IS_ERR(gb->task)) { -- cgit v0.10.2 From f7908e4d6def2cbeb16af29abceb1c6944d91f0c Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 13 Jul 2015 20:20:51 +0100 Subject: greybus: loopback: update throughput metrics to improve granularity Throughput capture should account for the entire size of the data going out on the wire. In addition throughput should be captured for each supported loopback operation. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index f490648..b92232b 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -340,10 +340,26 @@ static void gb_loopback_freq_update(struct gb_loopback *gb) gb_loopback_update_stats(&gb->frequency, gb->elapsed_nsecs); } -static void gb_loopback_bw_update(struct gb_loopback *gb, int error) +static void gb_loopback_throughput_update(struct gb_loopback *gb) { - if (!error) - gb->throughput.sum += gb->size * 2; + u32 aggregate_size = sizeof(struct gb_operation_msg_hdr) * 2; + + switch (gb->type) { + case GB_LOOPBACK_TYPE_PING: + break; + case GB_LOOPBACK_TYPE_SINK: + aggregate_size += sizeof(struct gb_loopback_transfer_request) + + gb->size; + break; + case GB_LOOPBACK_TYPE_TRANSFER: + aggregate_size += sizeof(struct gb_loopback_transfer_request) + + sizeof(struct gb_loopback_transfer_response) + + gb->size * 2; + break; + default: + return; + } + gb->throughput.sum += aggregate_size; gb_loopback_update_stats(&gb->throughput, gb->elapsed_nsecs); } @@ -393,8 +409,7 @@ static int gb_loopback_fn(void *data) gb->elapsed_nsecs = timeval_to_ns(&gb->te) - timeval_to_ns(&gb->ts); gb_loopback_freq_update(gb); - if (gb->type == GB_LOOPBACK_TYPE_PING) - gb_loopback_bw_update(gb, error); + gb_loopback_throughput_update(gb); gb_loopback_latency_update(gb, &tlat); if (gb->elapsed_nsecs >= NSEC_PER_SEC) gb->ts = gb->te; -- cgit v0.10.2 From 52af141b8224e428ee135bbeb508646b40d03fb5 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 14 Jul 2015 00:53:12 +0100 Subject: greybus: loopback: fix broken tabs in greybus_protocols.h Copy/paste of code from one file to another missed inappropriate use of tab after define. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index d3cce68..b32d6ab 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -660,14 +660,14 @@ struct gb_uart_serial_state_request { /* Loopback */ /* Version of the Greybus loopback protocol we support */ -#define GB_LOOPBACK_VERSION_MAJOR 0x00 -#define GB_LOOPBACK_VERSION_MINOR 0x01 +#define GB_LOOPBACK_VERSION_MAJOR 0x00 +#define GB_LOOPBACK_VERSION_MINOR 0x01 /* Greybus loopback request types */ -#define GB_LOOPBACK_TYPE_INVALID 0x00 -#define GB_LOOPBACK_TYPE_PROTOCOL_VERSION 0x01 -#define GB_LOOPBACK_TYPE_PING 0x02 -#define GB_LOOPBACK_TYPE_TRANSFER 0x03 +#define GB_LOOPBACK_TYPE_INVALID 0x00 +#define GB_LOOPBACK_TYPE_PROTOCOL_VERSION 0x01 +#define GB_LOOPBACK_TYPE_PING 0x02 +#define GB_LOOPBACK_TYPE_TRANSFER 0x03 #define GB_LOOPBACK_TYPE_SINK 0x04 struct gb_loopback_transfer_request { -- cgit v0.10.2 From e51eafebf83b236d4d43ed13b809c504e2d38d54 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 14 Jul 2015 00:53:13 +0100 Subject: greybus: loopback: fix 64bit printf format error Last patchset missed compilation on 64 bit contained warning. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index b92232b..f07fc0a 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -34,7 +34,7 @@ struct gb_loopback { int type; u32 size; - u32 size_max; + size_t size_max; int ms_wait; struct gb_loopback_stats latency; @@ -254,7 +254,7 @@ static int gb_loopback_request_recv(u8 type, struct gb_operation *operation) struct gb_loopback *gb = connection->private; struct gb_loopback_transfer_request *request; struct gb_loopback_transfer_response *response; - u32 len; + size_t len; /* By convention, the AP initiates the version operation */ switch (type) { -- cgit v0.10.2 From a5192032a2a9475c837c2b4b6fc3df02d617c7b0 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 14 Jul 2015 02:10:18 +0100 Subject: greybus: uart: fix typo in defintion Fixing needless redefinition of operation types in gbsim reveals this typo GB_UART_TYPE_SET_BREAK -> GB_UART_TYPE_SEND_BREAK. This patch should be applied in lock-step to the patch to gbsim 'gbsim/uart: remove unnecessary redefinition of operation types' since gbsim does not contain the typo. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index b32d6ab..839f3a6 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -597,7 +597,7 @@ struct gb_svc_conn_destroy_request { #define GB_UART_TYPE_RECEIVE_DATA 0x03 /* Unsolicited data */ #define GB_UART_TYPE_SET_LINE_CODING 0x04 #define GB_UART_TYPE_SET_CONTROL_LINE_STATE 0x05 -#define GB_UART_TYPE_SET_BREAK 0x06 +#define GB_UART_TYPE_SEND_BREAK 0x06 #define GB_UART_TYPE_SERIAL_STATE 0x07 /* Unsolicited data */ /* Represents data from AP -> Module */ diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 3932f86..0166c4c 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -186,7 +186,7 @@ static int send_break(struct gb_tty *gb_tty, u8 state) } request.state = state; - return gb_operation_sync(gb_tty->connection, GB_UART_TYPE_SET_BREAK, + return gb_operation_sync(gb_tty->connection, GB_UART_TYPE_SEND_BREAK, &request, sizeof(request), NULL, 0); } -- cgit v0.10.2 From fffc151381473384629d78cb89b7f7bbb9dc53b0 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 14 Jul 2015 15:43:23 +0200 Subject: greybus: operation: fix another cancellation use-after-free An incoming operation could already be scheduled even if gb_operation_result_set succeeds as its initial status is -EINPROGRESS. Avoid potential use-after-free by never dropping the reference count for incoming operations as part of cancellation. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index b78c55f..41aec76 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -853,12 +853,17 @@ void gb_connection_recv(struct gb_connection *connection, */ void gb_operation_cancel(struct gb_operation *operation, int errno) { - if (gb_operation_result_set(operation, errno)) { - gb_message_cancel(operation->request); - gb_operation_put(operation); - } else if (gb_operation_is_incoming(operation)) { - if (!gb_operation_is_unidirectional(operation)) + if (gb_operation_is_incoming(operation)) { + /* Cancel response if it has been allocated */ + if (!gb_operation_result_set(operation, errno) && + !gb_operation_is_unidirectional(operation)) { gb_message_cancel(operation->response); + } + } else { + if (gb_operation_result_set(operation, errno)) { + gb_message_cancel(operation->request); + gb_operation_put(operation); + } } } EXPORT_SYMBOL_GPL(gb_operation_cancel); -- cgit v0.10.2 From 9a586bd2bb80a268345cc8ccfa702413359ece06 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 14 Jul 2015 15:43:24 +0200 Subject: greybus: operation: clean up create-incoming error path Clean up gb_operation_create_incoming error path by returning immediately on allocation failures. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 41aec76..081694c 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -511,10 +511,11 @@ gb_operation_create_incoming(struct gb_connection *connection, u16 id, operation = gb_operation_create_common(connection, type, request_size, 0, flags, GFP_ATOMIC); - if (operation) { - operation->id = id; - memcpy(operation->request->header, data, size); - } + if (!operation) + return NULL; + + operation->id = id; + memcpy(operation->request->header, data, size); return operation; } -- cgit v0.10.2 From 3eeac7e37ce9856e53693772dfe81a79b57b5a00 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 14 Jul 2015 15:43:25 +0200 Subject: greybus: operation: add active counter Add active counter to track operations that are in use. Note that the active count is always less than the reference count. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 081694c..abe44c1 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -32,6 +32,18 @@ static DEFINE_SPINLOCK(gb_operations_lock); static int gb_operation_response_send(struct gb_operation *operation, int errno); +/* Caller holds operation reference. */ +static inline void gb_operation_get_active(struct gb_operation *operation) +{ + atomic_inc(&operation->active); +} + +/* Caller holds operation reference. */ +static inline void gb_operation_put_active(struct gb_operation *operation) +{ + atomic_dec(&operation->active); +} + /* * Set an operation's result. * @@ -204,6 +216,7 @@ static void gb_operation_work(struct work_struct *work) operation->callback(operation); + gb_operation_put_active(operation); gb_operation_put(operation); } @@ -449,6 +462,7 @@ gb_operation_create_common(struct gb_connection *connection, u8 type, INIT_WORK(&operation->work, gb_operation_work); init_completion(&operation->completion); kref_init(&operation->kref); + atomic_set(&operation->active, 0); spin_lock_irqsave(&gb_operations_lock, flags); list_add_tail(&operation->links, &connection->operations); @@ -597,6 +611,7 @@ int gb_operation_request_send(struct gb_operation *operation, * It'll be dropped when the operation completes. */ gb_operation_get(operation); + gb_operation_get_active(operation); /* * Record the callback function, which is executed in @@ -618,8 +633,10 @@ int gb_operation_request_send(struct gb_operation *operation, gb_operation_result_set(operation, -EINPROGRESS); ret = gb_message_send(operation->request, gfp); - if (ret) + if (ret) { + gb_operation_put_active(operation); gb_operation_put(operation); + } return ret; } @@ -688,13 +705,16 @@ static int gb_operation_response_send(struct gb_operation *operation, /* Reference will be dropped when message has been sent. */ gb_operation_get(operation); + gb_operation_get_active(operation); /* Fill in the response header and send it */ operation->response->header->result = gb_operation_errno_map(errno); ret = gb_message_send(operation->response, GFP_KERNEL); - if (ret) + if (ret) { + gb_operation_put_active(operation); gb_operation_put(operation); + } return ret; } @@ -723,6 +743,7 @@ void greybus_message_sent(struct greybus_host_device *hd, dev_err(&operation->connection->dev, "error sending response: %d\n", status); } + gb_operation_put_active(operation); gb_operation_put(operation); } else if (status) { if (gb_operation_result_set(operation, status)) @@ -751,6 +772,8 @@ static void gb_connection_recv_request(struct gb_connection *connection, return; /* XXX Respond with pre-allocated ENOMEM */ } + gb_operation_get_active(operation); + /* * Incoming requests are handled by arranging for the * request handler to be the operation's callback function. @@ -863,6 +886,7 @@ void gb_operation_cancel(struct gb_operation *operation, int errno) } else { if (gb_operation_result_set(operation, errno)) { gb_message_cancel(operation->request); + gb_operation_put_active(operation); gb_operation_put(operation); } } diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index c16f64d..b323866 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -127,6 +127,8 @@ struct gb_operation { struct completion completion; struct kref kref; + atomic_t active; + struct list_head links; /* connection->operations */ }; -- cgit v0.10.2 From fd7134a3cd0a1b3f91e66922534a796145c85eef Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 14 Jul 2015 15:43:26 +0200 Subject: greybus: operation: make cancellation synchronous Make sure to wait for the operation to become inactive before returning after having cancelled an operation. This makes sure that any ongoing operation completion callbacks have finished. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 65a2bd5..b9f9b11 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -227,7 +227,6 @@ void gb_connection_destroy(struct gb_connection *connection) if (WARN_ON(!connection)) return; - /* XXX Need to wait for any outstanding requests to complete */ if (WARN_ON(!list_empty(&connection->operations))) { list_for_each_entry_safe(operation, next, &connection->operations, links) diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index abe44c1..5e8ea02 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include "greybus.h" @@ -23,6 +25,9 @@ static struct kmem_cache *gb_message_cache; /* Workqueue to handle Greybus operation completions. */ static struct workqueue_struct *gb_operation_workqueue; +/* Wait queue for synchronous cancellations. */ +static DECLARE_WAIT_QUEUE_HEAD(gb_operation_cancellation_queue); + /* * Protects access to connection operations lists, as well as * updates to operation->errno. @@ -41,7 +46,15 @@ static inline void gb_operation_get_active(struct gb_operation *operation) /* Caller holds operation reference. */ static inline void gb_operation_put_active(struct gb_operation *operation) { - atomic_dec(&operation->active); + if (atomic_dec_and_test(&operation->active)) { + if (atomic_read(&operation->waiters)) + wake_up(&gb_operation_cancellation_queue); + } +} + +static inline bool gb_operation_is_active(struct gb_operation *operation) +{ + return atomic_read(&operation->active); } /* @@ -463,6 +476,7 @@ gb_operation_create_common(struct gb_connection *connection, u8 type, init_completion(&operation->completion); kref_init(&operation->kref); atomic_set(&operation->active, 0); + atomic_set(&operation->waiters, 0); spin_lock_irqsave(&gb_operations_lock, flags); list_add_tail(&operation->links, &connection->operations); @@ -873,7 +887,8 @@ void gb_connection_recv(struct gb_connection *connection, } /* - * Cancel an operation, and record the given error to indicate why. + * Cancel an operation synchronously, and record the given error to indicate + * why. */ void gb_operation_cancel(struct gb_operation *operation, int errno) { @@ -890,6 +905,11 @@ void gb_operation_cancel(struct gb_operation *operation, int errno) gb_operation_put(operation); } } + + atomic_inc(&operation->waiters); + wait_event(gb_operation_cancellation_queue, + !gb_operation_is_active(operation)); + atomic_dec(&operation->waiters); } EXPORT_SYMBOL_GPL(gb_operation_cancel); diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index b323866..c8aaf90 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -128,6 +128,7 @@ struct gb_operation { struct kref kref; atomic_t active; + atomic_t waiters; struct list_head links; /* connection->operations */ }; -- cgit v0.10.2 From db1481ba7f36c2f5f74d19918bdf315a1ef8226b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 14 Jul 2015 15:43:27 +0200 Subject: greybus: operation: complete operations on cancellation Make sure to call the operation completion callback also when the operation is being cancelled. The completion callback may need to release resources allocated at submission and the driver should be informed that the operation has failed due to cancellation. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 5e8ea02..1e181d5 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -901,8 +901,7 @@ void gb_operation_cancel(struct gb_operation *operation, int errno) } else { if (gb_operation_result_set(operation, errno)) { gb_message_cancel(operation->request); - gb_operation_put_active(operation); - gb_operation_put(operation); + queue_work(gb_operation_workqueue, &operation->work); } } -- cgit v0.10.2 From c600e535a72d0d3ec4b3e8e323e5602cbc49004e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 14 Jul 2015 15:43:28 +0200 Subject: greybus: operation: clean up operation work function Call request handler helper explicitly from the work function rather than overload the operation completion callback. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 1e181d5..0adb727 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -212,9 +212,10 @@ static void gb_operation_request_handle(struct gb_operation *operation) } /* - * Complete an operation in non-atomic context. For incoming - * requests, the callback function is the request handler, and - * the operation result should be -EINPROGRESS at this point. + * Process operation work. + * + * For incoming requests, call the protocol request handler. The operation + * result should be -EINPROGRESS at this point. * * For outgoing requests, the operation result value should have * been set before queueing this. The operation callback function @@ -227,7 +228,10 @@ static void gb_operation_work(struct work_struct *work) operation = container_of(work, struct gb_operation, work); - operation->callback(operation); + if (gb_operation_is_incoming(operation)) + gb_operation_request_handle(operation); + else + operation->callback(operation); gb_operation_put_active(operation); gb_operation_put(operation); @@ -789,14 +793,9 @@ static void gb_connection_recv_request(struct gb_connection *connection, gb_operation_get_active(operation); /* - * Incoming requests are handled by arranging for the - * request handler to be the operation's callback function. - * - * The last thing the handler does is send a response - * message. The initial reference to the operation will be - * dropped when the handler returns. + * The initial reference to the operation will be dropped when the + * request handler returns. */ - operation->callback = gb_operation_request_handle; if (gb_operation_result_set(operation, -EINPROGRESS)) queue_work(gb_operation_workqueue, &operation->work); } -- cgit v0.10.2 From 886c6069bc0e16b7215b326831478ed700451038 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 14 Jul 2015 15:43:29 +0200 Subject: greybus: operation: suppress response submission on connection tear down Suppress response submission on connection tear down as we do with requests. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 0adb727..2729b48 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -705,6 +705,9 @@ static int gb_operation_response_send(struct gb_operation *operation, struct gb_connection *connection = operation->connection; int ret; + if (connection->state != GB_CONNECTION_STATE_ENABLED) + return -ENOTCONN; + if (!operation->response && !gb_operation_is_unidirectional(operation)) { if (!gb_operation_response_alloc(operation, 0)) -- cgit v0.10.2 From cad09a8f8ce843aa11f9a6a8a7aa5c6d6591147b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 14 Jul 2015 15:43:30 +0200 Subject: greybus: connection: add connection-state locking Add locking, and the implied barriers, to connection-state updates. This will be used to fix a number of races in the operations and connection-tear-down implementations. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index b9f9b11..abc1f86 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -65,8 +65,13 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr, char *buf) { struct gb_connection *connection = to_gb_connection(dev); + enum gb_connection_state state; - return sprintf(buf, "%d\n", connection->state); + spin_lock_irq(&connection->lock); + state = connection->state; + spin_unlock_irq(&connection->lock); + + return sprintf(buf, "%d\n", state); } static DEVICE_ATTR_RO(state); @@ -204,6 +209,7 @@ struct gb_connection *gb_connection_create(struct gb_bundle *bundle, spin_unlock_irq(&gb_connections_lock); atomic_set(&connection->op_cycle, 0); + spin_lock_init(&connection->lock); INIT_LIST_HEAD(&connection->operations); /* XXX Will have to establish connections to get version */ @@ -274,10 +280,16 @@ int gb_connection_init(struct gb_connection *connection) } /* Need to enable the connection to initialize it */ + spin_lock_irq(&connection->lock); connection->state = GB_CONNECTION_STATE_ENABLED; + spin_unlock_irq(&connection->lock); + ret = connection->protocol->connection_init(connection); - if (ret) + if (ret) { + spin_lock_irq(&connection->lock); connection->state = GB_CONNECTION_STATE_ERROR; + spin_unlock_irq(&connection->lock); + } return ret; } @@ -291,10 +303,14 @@ void gb_connection_exit(struct gb_connection *connection) return; } - if (connection->state != GB_CONNECTION_STATE_ENABLED) + spin_lock_irq(&connection->lock); + if (connection->state != GB_CONNECTION_STATE_ENABLED) { + spin_unlock_irq(&connection->lock); return; - + } connection->state = GB_CONNECTION_STATE_DESTROYING; + spin_unlock_irq(&connection->lock); + connection->protocol->connection_exit(connection); /* diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index ad699db..c2b71fe 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -35,6 +35,7 @@ struct gb_connection { u8 major; u8 minor; + spinlock_t lock; enum gb_connection_state state; atomic_t op_cycle; -- cgit v0.10.2 From 008974cb528d301895797fec0f7d4fd64d01fce0 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 14 Jul 2015 15:43:31 +0200 Subject: greybus: operation: fix connection tear down Fix connection tear down, which was done in an unsafe way that could result in use-after-free as the per-connection list of operations was iterated without any locking or refcounting. Specifically, the operations list was iterated without holding any locks or operation refcounts even though operations were being both removed from the list and deallocated during per-operation cancellation. Any operation completing during tear down could also cause corruption. Change the per-connection operation list to only contain active operations and use the recently introduced active counter to maintain the list. Add new helper that is called on connection tear down to cancel all outstanding operations in a safe way by using proper locks and making sure to hold a reference to any operation being cancelled. Note that by verifying the connection state before incrementing the active count we can make sure that all active operations have been cancelled and that no new ones have been started when the helper returns. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index abc1f86..2d19082 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -222,22 +222,45 @@ struct gb_connection *gb_connection_create(struct gb_bundle *bundle, } /* + * Cancel all active operations on a connection. + * + * Should only be called during connection tear down. + */ +static void gb_connection_cancel_operations(struct gb_connection *connection, + int errno) +{ + struct gb_operation *operation; + + spin_lock_irq(&connection->lock); + + WARN_ON(!list_empty(&connection->operations)); + + while (!list_empty(&connection->operations)) { + operation = list_last_entry(&connection->operations, + struct gb_operation, links); + gb_operation_get(operation); + spin_unlock_irq(&connection->lock); + + gb_operation_cancel(operation, errno); + gb_operation_put(operation); + + spin_lock_irq(&connection->lock); + } + spin_unlock_irq(&connection->lock); +} + +/* * Tear down a previously set up connection. */ void gb_connection_destroy(struct gb_connection *connection) { - struct gb_operation *operation; - struct gb_operation *next; struct ida *id_map; if (WARN_ON(!connection)) return; - if (WARN_ON(!list_empty(&connection->operations))) { - list_for_each_entry_safe(operation, next, - &connection->operations, links) - gb_operation_cancel(operation, -ESHUTDOWN); - } + gb_connection_cancel_operations(connection, -ESHUTDOWN); + spin_lock_irq(&gb_connections_lock); list_del(&connection->bundle_links); list_del(&connection->hd_links); diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index c2b71fe..fb7a1fb 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -37,9 +37,9 @@ struct gb_connection { spinlock_t lock; enum gb_connection_state state; + struct list_head operations; atomic_t op_cycle; - struct list_head operations; void *private; }; diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 2729b48..5cd4665 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -29,32 +29,65 @@ static struct workqueue_struct *gb_operation_workqueue; static DECLARE_WAIT_QUEUE_HEAD(gb_operation_cancellation_queue); /* - * Protects access to connection operations lists, as well as - * updates to operation->errno. + * Protects updates to operation->errno. */ static DEFINE_SPINLOCK(gb_operations_lock); static int gb_operation_response_send(struct gb_operation *operation, int errno); -/* Caller holds operation reference. */ -static inline void gb_operation_get_active(struct gb_operation *operation) +/* + * Increment operation active count and add to connection list unless the + * connection is going away. + * + * Caller holds operation reference. + */ +static int gb_operation_get_active(struct gb_operation *operation) { - atomic_inc(&operation->active); + struct gb_connection *connection = operation->connection; + unsigned long flags; + + spin_lock_irqsave(&connection->lock, flags); + + if (connection->state != GB_CONNECTION_STATE_ENABLED) { + spin_unlock_irqrestore(&connection->lock, flags); + return -ENOTCONN; + } + + if (operation->active++ == 0) + list_add_tail(&operation->links, &connection->operations); + + spin_unlock_irqrestore(&connection->lock, flags); + + return 0; } /* Caller holds operation reference. */ -static inline void gb_operation_put_active(struct gb_operation *operation) +static void gb_operation_put_active(struct gb_operation *operation) { - if (atomic_dec_and_test(&operation->active)) { + struct gb_connection *connection = operation->connection; + unsigned long flags; + + spin_lock_irqsave(&connection->lock, flags); + if (--operation->active == 0) { + list_del(&operation->links); if (atomic_read(&operation->waiters)) wake_up(&gb_operation_cancellation_queue); } + spin_unlock_irqrestore(&connection->lock, flags); } -static inline bool gb_operation_is_active(struct gb_operation *operation) +static bool gb_operation_is_active(struct gb_operation *operation) { - return atomic_read(&operation->active); + struct gb_connection *connection = operation->connection; + unsigned long flags; + bool ret; + + spin_lock_irqsave(&connection->lock, flags); + ret = operation->active; + spin_unlock_irqrestore(&connection->lock, flags); + + return ret; } /* @@ -150,7 +183,7 @@ gb_operation_find_outgoing(struct gb_connection *connection, u16 operation_id) unsigned long flags; bool found = false; - spin_lock_irqsave(&gb_operations_lock, flags); + spin_lock_irqsave(&connection->lock, flags); list_for_each_entry(operation, &connection->operations, links) if (operation->id == operation_id && !gb_operation_is_incoming(operation)) { @@ -158,7 +191,7 @@ gb_operation_find_outgoing(struct gb_connection *connection, u16 operation_id) found = true; break; } - spin_unlock_irqrestore(&gb_operations_lock, flags); + spin_unlock_irqrestore(&connection->lock, flags); return found ? operation : NULL; } @@ -453,7 +486,6 @@ gb_operation_create_common(struct gb_connection *connection, u8 type, { struct greybus_host_device *hd = connection->hd; struct gb_operation *operation; - unsigned long flags; operation = kmem_cache_zalloc(gb_operation_cache, gfp_flags); if (!operation) @@ -479,13 +511,8 @@ gb_operation_create_common(struct gb_connection *connection, u8 type, INIT_WORK(&operation->work, gb_operation_work); init_completion(&operation->completion); kref_init(&operation->kref); - atomic_set(&operation->active, 0); atomic_set(&operation->waiters, 0); - spin_lock_irqsave(&gb_operations_lock, flags); - list_add_tail(&operation->links, &connection->operations); - spin_unlock_irqrestore(&gb_operations_lock, flags); - return operation; err_request: @@ -570,10 +597,6 @@ static void _gb_operation_destroy(struct kref *kref) operation = container_of(kref, struct gb_operation, kref); - /* XXX Make sure it's not in flight */ - list_del(&operation->links); - spin_unlock(&gb_operations_lock); - if (operation->response) gb_operation_message_free(operation->response); gb_operation_message_free(operation->request); @@ -590,8 +613,7 @@ void gb_operation_put(struct gb_operation *operation) if (WARN_ON(!operation)) return; - kref_put_spinlock_irqsave(&operation->kref, _gb_operation_destroy, - &gb_operations_lock); + kref_put(&operation->kref, _gb_operation_destroy); } EXPORT_SYMBOL_GPL(gb_operation_put); @@ -621,15 +643,14 @@ int gb_operation_request_send(struct gb_operation *operation, if (!callback) return -EINVAL; - if (connection->state != GB_CONNECTION_STATE_ENABLED) - return -ENOTCONN; - /* * First, get an extra reference on the operation. * It'll be dropped when the operation completes. */ gb_operation_get(operation); - gb_operation_get_active(operation); + ret = gb_operation_get_active(operation); + if (ret) + goto err_put; /* * Record the callback function, which is executed in @@ -651,10 +672,15 @@ int gb_operation_request_send(struct gb_operation *operation, gb_operation_result_set(operation, -EINPROGRESS); ret = gb_message_send(operation->request, gfp); - if (ret) { - gb_operation_put_active(operation); - gb_operation_put(operation); - } + if (ret) + goto err_put_active; + + return 0; + +err_put_active: + gb_operation_put_active(operation); +err_put: + gb_operation_put(operation); return ret; } @@ -705,9 +731,6 @@ static int gb_operation_response_send(struct gb_operation *operation, struct gb_connection *connection = operation->connection; int ret; - if (connection->state != GB_CONNECTION_STATE_ENABLED) - return -ENOTCONN; - if (!operation->response && !gb_operation_is_unidirectional(operation)) { if (!gb_operation_response_alloc(operation, 0)) @@ -726,16 +749,23 @@ static int gb_operation_response_send(struct gb_operation *operation, /* Reference will be dropped when message has been sent. */ gb_operation_get(operation); - gb_operation_get_active(operation); + ret = gb_operation_get_active(operation); + if (ret) + goto err_put; /* Fill in the response header and send it */ operation->response->header->result = gb_operation_errno_map(errno); ret = gb_message_send(operation->response, GFP_KERNEL); - if (ret) { - gb_operation_put_active(operation); - gb_operation_put(operation); - } + if (ret) + goto err_put_active; + + return 0; + +err_put_active: + gb_operation_put_active(operation); +err_put: + gb_operation_put(operation); return ret; } @@ -785,6 +815,7 @@ static void gb_connection_recv_request(struct gb_connection *connection, void *data, size_t size) { struct gb_operation *operation; + int ret; operation = gb_operation_create_incoming(connection, operation_id, type, data, size); @@ -793,7 +824,11 @@ static void gb_connection_recv_request(struct gb_connection *connection, return; /* XXX Respond with pre-allocated ENOMEM */ } - gb_operation_get_active(operation); + ret = gb_operation_get_active(operation); + if (ret) { + gb_operation_put(operation); + return; + } /* * The initial reference to the operation will be dropped when the diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index c8aaf90..26ecd66 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -127,9 +127,9 @@ struct gb_operation { struct completion completion; struct kref kref; - atomic_t active; atomic_t waiters; + int active; struct list_head links; /* connection->operations */ }; -- cgit v0.10.2 From 7f1b67cd535673cef9b9c9fa772d04015f64bd8e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 14 Jul 2015 15:43:32 +0200 Subject: greybus: connection: fix protocol tear-down race Make sure to cancel all active operations before calling protocol connection_exit to prevent use-after-free issues when the protocol state is being deallocated (e.g. late processing of already-queued requests or completions). Note that already-queued requests or completions will be processed as part of cancellation. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 2d19082..ac9b2d1 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -232,9 +232,6 @@ static void gb_connection_cancel_operations(struct gb_connection *connection, struct gb_operation *operation; spin_lock_irq(&connection->lock); - - WARN_ON(!list_empty(&connection->operations)); - while (!list_empty(&connection->operations)) { operation = list_last_entry(&connection->operations, struct gb_operation, links); @@ -259,8 +256,6 @@ void gb_connection_destroy(struct gb_connection *connection) if (WARN_ON(!connection)) return; - gb_connection_cancel_operations(connection, -ESHUTDOWN); - spin_lock_irq(&gb_connections_lock); list_del(&connection->bundle_links); list_del(&connection->hd_links); @@ -334,6 +329,8 @@ void gb_connection_exit(struct gb_connection *connection) connection->state = GB_CONNECTION_STATE_DESTROYING; spin_unlock_irq(&connection->lock); + gb_connection_cancel_operations(connection, -ESHUTDOWN); + connection->protocol->connection_exit(connection); /* -- cgit v0.10.2 From 3325a4ad7122acdbfae5360cafc7152b32eefd57 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 14 Jul 2015 15:43:33 +0200 Subject: greybus: operation: fix operation look-up race Make sure to fully initialise the operation before adding it to the active list when sending a request. The operation should be fully initialised before adding it to the active list to avoid racing with operation look up when receiving a response, something which could potentially lead to a match against some earlier (or intermediate) value of the id field. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 5cd4665..f7b0aa9 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -642,16 +642,6 @@ int gb_operation_request_send(struct gb_operation *operation, if (!callback) return -EINVAL; - - /* - * First, get an extra reference on the operation. - * It'll be dropped when the operation completes. - */ - gb_operation_get(operation); - ret = gb_operation_get_active(operation); - if (ret) - goto err_put; - /* * Record the callback function, which is executed in * non-atomic (workqueue) context when the final result @@ -668,9 +658,17 @@ int gb_operation_request_send(struct gb_operation *operation, header = operation->request->header; header->operation_id = cpu_to_le16(operation->id); - /* All set, send the request */ gb_operation_result_set(operation, -EINPROGRESS); + /* + * Get an extra reference on the operation. It'll be dropped when the + * operation completes. + */ + gb_operation_get(operation); + ret = gb_operation_get_active(operation); + if (ret) + goto err_put; + ret = gb_message_send(operation->request, gfp); if (ret) goto err_put_active; -- cgit v0.10.2 From 0eb8c1159839dcb6c97fba82e5a8698d9c30f815 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 14 Jul 2015 15:43:34 +0200 Subject: greybus: operation: fix response-cancellation race Make sure the request handler has submitted the response before cancelling it during operation cancellation. This prevents cancelling not-yet-submitted messages. It currently also avoids us ending up with an active message on a stalled connection (e.g. due to E2EFC). Note that the call to gb_operation_result_set() is now redundant but is kept as a precaution to guarantee that a response has indeed been allocated as part of response submission. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index f7b0aa9..0576f19 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -928,10 +928,14 @@ void gb_connection_recv(struct gb_connection *connection, void gb_operation_cancel(struct gb_operation *operation, int errno) { if (gb_operation_is_incoming(operation)) { - /* Cancel response if it has been allocated */ - if (!gb_operation_result_set(operation, errno) && - !gb_operation_is_unidirectional(operation)) { - gb_message_cancel(operation->response); + if (!gb_operation_is_unidirectional(operation)) { + /* + * Make sure the request handler has submitted the + * response before cancelling it. + */ + flush_work(&operation->work); + if (!gb_operation_result_set(operation, errno)) + gb_message_cancel(operation->response); } } else { if (gb_operation_result_set(operation, errno)) { -- cgit v0.10.2 From 5a3be769e92ea993f8a8c27b89571c276d874733 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 14 Jul 2015 15:43:35 +0200 Subject: greybus: operation: split incoming and outgoing cancellation Split incoming and outgoing operation-cancellation helpers. Incoming operations are only cancelled as part of connection tear down and is specifically not needed in the driver API. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index ac9b2d1..81a5df0 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -238,7 +238,11 @@ static void gb_connection_cancel_operations(struct gb_connection *connection, gb_operation_get(operation); spin_unlock_irq(&connection->lock); - gb_operation_cancel(operation, errno); + if (gb_operation_is_incoming(operation)) + gb_operation_cancel_incoming(operation, errno); + else + gb_operation_cancel(operation, errno); + gb_operation_put(operation); spin_lock_irq(&connection->lock); diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 0576f19..17b07fb 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -922,26 +922,17 @@ void gb_connection_recv(struct gb_connection *connection, } /* - * Cancel an operation synchronously, and record the given error to indicate - * why. + * Cancel an outgoing operation synchronously, and record the given error to + * indicate why. */ void gb_operation_cancel(struct gb_operation *operation, int errno) { - if (gb_operation_is_incoming(operation)) { - if (!gb_operation_is_unidirectional(operation)) { - /* - * Make sure the request handler has submitted the - * response before cancelling it. - */ - flush_work(&operation->work); - if (!gb_operation_result_set(operation, errno)) - gb_message_cancel(operation->response); - } - } else { - if (gb_operation_result_set(operation, errno)) { - gb_message_cancel(operation->request); - queue_work(gb_operation_workqueue, &operation->work); - } + if (WARN_ON(gb_operation_is_incoming(operation))) + return; + + if (gb_operation_result_set(operation, errno)) { + gb_message_cancel(operation->request); + queue_work(gb_operation_workqueue, &operation->work); } atomic_inc(&operation->waiters); @@ -951,6 +942,31 @@ void gb_operation_cancel(struct gb_operation *operation, int errno) } EXPORT_SYMBOL_GPL(gb_operation_cancel); +/* + * Cancel an incoming operation synchronously. Called during connection tear + * down. + */ +void gb_operation_cancel_incoming(struct gb_operation *operation, int errno) +{ + if (WARN_ON(!gb_operation_is_incoming(operation))) + return; + + if (!gb_operation_is_unidirectional(operation)) { + /* + * Make sure the request handler has submitted the response + * before cancelling it. + */ + flush_work(&operation->work); + if (!gb_operation_result_set(operation, errno)) + gb_message_cancel(operation->response); + } + + atomic_inc(&operation->waiters); + wait_event(gb_operation_cancellation_queue, + !gb_operation_is_active(operation)); + atomic_dec(&operation->waiters); +} + /** * gb_operation_sync: implement a "simple" synchronous gb operation. * @connection: the Greybus connection to send this to diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 26ecd66..d7e59a3f 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -171,6 +171,7 @@ int gb_operation_request_send(struct gb_operation *operation, int gb_operation_request_send_sync(struct gb_operation *operation); void gb_operation_cancel(struct gb_operation *operation, int errno); +void gb_operation_cancel_incoming(struct gb_operation *operation, int errno); void greybus_message_sent(struct greybus_host_device *hd, struct gb_message *message, int status); -- cgit v0.10.2 From 4f2c08aba792d4c778774e90e47865718eb1b7f8 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 14 Jul 2015 15:43:36 +0200 Subject: greybus: operation: allow drivers to define custom timeouts Add new interface gb_operation_request_send_sync_timeout, which allows drivers to define a custom operation timeout instead of the default one-second timeout. The timeout is expected to depend on protocol and operation and therefore needs to be configurable. Note that that a timeout of zero is used to wait indefinitely. Reviewed-by: Bryan O'Donoghue Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 17b07fb..63c4a5b 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -16,9 +16,6 @@ #include "greybus.h" -/* The default amount of time a request is given to complete */ -#define OPERATION_TIMEOUT_DEFAULT 1000 /* milliseconds */ - static struct kmem_cache *gb_operation_cache; static struct kmem_cache *gb_message_cache; @@ -690,18 +687,24 @@ EXPORT_SYMBOL_GPL(gb_operation_request_send); * error is detected. The return value is the result of the * operation. */ -int gb_operation_request_send_sync(struct gb_operation *operation) +int gb_operation_request_send_sync_timeout(struct gb_operation *operation, + unsigned int timeout) { int ret; - unsigned long timeout; + unsigned long timeout_jiffies; ret = gb_operation_request_send(operation, gb_operation_sync_callback, GFP_KERNEL); if (ret) return ret; - timeout = msecs_to_jiffies(OPERATION_TIMEOUT_DEFAULT); - ret = wait_for_completion_interruptible_timeout(&operation->completion, timeout); + if (timeout) + timeout_jiffies = msecs_to_jiffies(timeout); + else + timeout_jiffies = MAX_SCHEDULE_TIMEOUT; + + ret = wait_for_completion_interruptible_timeout(&operation->completion, + timeout_jiffies); if (ret < 0) { /* Cancel the operation if interrupted */ gb_operation_cancel(operation, -ECANCELED); @@ -712,7 +715,7 @@ int gb_operation_request_send_sync(struct gb_operation *operation) return gb_operation_result(operation); } -EXPORT_SYMBOL_GPL(gb_operation_request_send_sync); +EXPORT_SYMBOL_GPL(gb_operation_request_send_sync_timeout); /* * Send a response for an incoming operation request. A non-zero diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index d7e59a3f..f06dd11 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -14,6 +14,9 @@ struct gb_operation; +/* The default amount of time a request is given to complete */ +#define GB_OPERATION_TIMEOUT_DEFAULT 1000 /* milliseconds */ + /* * No protocol may define an operation that has numeric value 0x00. * It is reserved as an explicitly invalid value. @@ -168,7 +171,14 @@ bool gb_operation_response_alloc(struct gb_operation *operation, int gb_operation_request_send(struct gb_operation *operation, gb_operation_callback callback, gfp_t gfp); -int gb_operation_request_send_sync(struct gb_operation *operation); +int gb_operation_request_send_sync_timeout(struct gb_operation *operation, + unsigned int timeout); +static inline int +gb_operation_request_send_sync(struct gb_operation *operation) +{ + return gb_operation_request_send_sync_timeout(operation, + GB_OPERATION_TIMEOUT_DEFAULT); +} void gb_operation_cancel(struct gb_operation *operation, int errno); void gb_operation_cancel_incoming(struct gb_operation *operation, int errno); -- cgit v0.10.2 From 129a06f541d3ff4228589b4b9f0a4681dafb0042 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 14 Jul 2015 15:43:37 +0200 Subject: greybus: operation: add gb_operation_sync_timeout helper Add gb_operation_sync_timeout convenience function, which allows drivers to configure the operation timeout. Reviewed-by: Bryan O'Donoghue Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 63c4a5b..a99505c 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -978,6 +978,7 @@ void gb_operation_cancel_incoming(struct gb_operation *operation, int errno) * @request_size: size of @request * @response: pointer to a memory buffer to copy the response to * @response_size: the size of @response. + * @timeout: operation timeout in milliseconds * * This function implements a simple synchronous Greybus operation. It sends * the provided operation request and waits (sleeps) until the corresponding @@ -992,9 +993,10 @@ void gb_operation_cancel_incoming(struct gb_operation *operation, int errno) * * If there is an error, the response buffer is left alone. */ -int gb_operation_sync(struct gb_connection *connection, int type, - void *request, int request_size, - void *response, int response_size) +int gb_operation_sync_timeout(struct gb_connection *connection, int type, + void *request, int request_size, + void *response, int response_size, + unsigned int timeout) { struct gb_operation *operation; int ret; @@ -1012,7 +1014,7 @@ int gb_operation_sync(struct gb_connection *connection, int type, if (request_size) memcpy(operation->request->payload, request, request_size); - ret = gb_operation_request_send_sync(operation); + ret = gb_operation_request_send_sync_timeout(operation, timeout); if (ret) { dev_err(&connection->dev, "synchronous operation failed: %d\n", ret); @@ -1026,7 +1028,7 @@ int gb_operation_sync(struct gb_connection *connection, int type, return ret; } -EXPORT_SYMBOL_GPL(gb_operation_sync); +EXPORT_SYMBOL_GPL(gb_operation_sync_timeout); int __init gb_operation_init(void) { diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index f06dd11..6854703 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -186,9 +186,19 @@ void gb_operation_cancel_incoming(struct gb_operation *operation, int errno); void greybus_message_sent(struct greybus_host_device *hd, struct gb_message *message, int status); -int gb_operation_sync(struct gb_connection *connection, int type, +int gb_operation_sync_timeout(struct gb_connection *connection, int type, + void *request, int request_size, + void *response, int response_size, + unsigned int timeout); + +static inline int gb_operation_sync(struct gb_connection *connection, int type, void *request, int request_size, - void *response, int response_size); + void *response, int response_size) +{ + return gb_operation_sync_timeout(connection, type, + request, request_size, response, response_size, + GB_OPERATION_TIMEOUT_DEFAULT); +} int gb_operation_init(void); void gb_operation_exit(void); -- cgit v0.10.2 From 93047af23c8389d1a63883dcb59cd8c2fd472b45 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 16 Jul 2015 11:44:01 +0200 Subject: greybus: kernel_ver: add list_last_entry for old kernels Add list_last_entry macro for kernels older than 3.13. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index 4fb949b..c2e92df 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -235,4 +235,9 @@ static inline size_t sg_pcopy_from_buffer(struct scatterlist *sgl, } #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) +#define list_last_entry(ptr, type, member) \ + list_entry((ptr)->prev, type, member) +#endif + #endif /* __GREYBUS_KERNEL_VER_H */ -- cgit v0.10.2 From 1c7658cf5165586acff901b7e6ef27d8d5f2818d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 17 Jul 2015 18:50:25 +0200 Subject: greybus: operation: fix atomic response allocation Response allocation also needs a GFP-flags argument as a response is allocated as part of an outgoing operation. Fixes: 9aa174d202e5 ("operation: allow atomic operation allocations") Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index d7870fc..a69a703 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -75,7 +75,8 @@ static int gb_control_request_recv(u8 type, struct gb_operation *op) // an AP. break; case GB_CONTROL_TYPE_PROTOCOL_VERSION: - if (!gb_operation_response_alloc(op, sizeof(*version))) { + if (!gb_operation_response_alloc(op, sizeof(*version), + GFP_KERNEL)) { dev_err(&connection->dev, "%s: error allocating response\n", __func__); return -ENOMEM; diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index f07fc0a..fe3a57b 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -283,7 +283,8 @@ static int gb_loopback_request_recv(u8 type, struct gb_operation *operation) } if (len) { - if (!gb_operation_response_alloc(operation, len)) { + if (!gb_operation_response_alloc(operation, len, + GFP_KERNEL)) { dev_err(&connection->dev, "error allocating response\n"); return -ENOMEM; diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index a99505c..0fe50d8 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -426,7 +426,7 @@ static u8 gb_operation_errno_map(int errno) } bool gb_operation_response_alloc(struct gb_operation *operation, - size_t response_size) + size_t response_size, gfp_t gfp) { struct greybus_host_device *hd = operation->connection->hd; struct gb_operation_msg_hdr *request_header; @@ -434,8 +434,7 @@ bool gb_operation_response_alloc(struct gb_operation *operation, u8 type; type = operation->type | GB_MESSAGE_TYPE_RESPONSE; - response = gb_operation_message_alloc(hd, type, response_size, - GFP_KERNEL); + response = gb_operation_message_alloc(hd, type, response_size, gfp); if (!response) return false; response->operation = operation; @@ -497,8 +496,10 @@ gb_operation_create_common(struct gb_connection *connection, u8 type, /* Allocate the response buffer for outgoing operations */ if (!(op_flags & GB_OPERATION_FLAG_INCOMING)) { - if (!gb_operation_response_alloc(operation, response_size)) + if (!gb_operation_response_alloc(operation, response_size, + gfp_flags)) { goto err_request; + } } operation->flags = op_flags; @@ -734,7 +735,7 @@ static int gb_operation_response_send(struct gb_operation *operation, if (!operation->response && !gb_operation_is_unidirectional(operation)) { - if (!gb_operation_response_alloc(operation, 0)) + if (!gb_operation_response_alloc(operation, 0, GFP_KERNEL)) return -ENOMEM; } diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 6854703..00189e9 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -166,7 +166,7 @@ static inline void gb_operation_destroy(struct gb_operation *operation) } bool gb_operation_response_alloc(struct gb_operation *operation, - size_t response_size); + size_t response_size, gfp_t gfp); int gb_operation_request_send(struct gb_operation *operation, gb_operation_callback callback, -- cgit v0.10.2 From b84abdcb419ff7e2e654381587c61b043a5bc661 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 17 Jul 2015 18:50:26 +0200 Subject: greybus: operation: fix atomic message submission The recently added GFP-flags argument to gb_message_send was never used. Fixes: 9218fac2a24d ("operation: allow atomic request submissions") Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 0fe50d8..f2d12e8 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -200,7 +200,7 @@ static int gb_message_send(struct gb_message *message, gfp_t gfp) return connection->hd->driver->message_send(connection->hd, connection->hd_cport_id, message, - GFP_KERNEL); + gfp); } /* -- cgit v0.10.2 From 392bf9fb2d017c15152380b654b9bfe51a61bff7 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 21 Jul 2015 17:44:08 +0530 Subject: greybus: connections: comment style fix Replace '* *' with '*'. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 81a5df0..edee5fb 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -124,7 +124,7 @@ void gb_connection_bind_protocol(struct gb_connection *connection) /* * If we have a valid device_id for the interface block, then we have an * active device, so bring up the connection at the same time. - * */ + */ intf = connection->bundle->intf; if (intf->device_id != GB_DEVICE_ID_BAD) gb_connection_init(connection); -- cgit v0.10.2 From 25366869577860c12f0dc8b28e2e34c6265a5a7a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 21 Jul 2015 17:44:09 +0530 Subject: greybus: interface: drop stale comment We don't do what the comment says, drop it. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 1e5e629..dfc31a0 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -70,8 +70,7 @@ struct device_type greybus_interface_type = { /* * Create kernel structures corresponding to a bundle and connection for - * managing control CPort. Also initialize the bundle, which will request SVC to - * set route and will initialize the control protocol for this connection. + * managing control CPort. */ static int gb_create_control_connection(struct gb_interface *intf) { -- cgit v0.10.2 From 948b3bd592817a7d6dd566823ac1279b37637f5c Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 21 Jul 2015 17:44:10 +0530 Subject: greybus: sync protocol and class definitions Class types aren't in sync with protocol types, lets keep them in sync for now. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index f84cfeb..9c4d7ca 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -67,6 +67,11 @@ enum greybus_class_type { GREYBUS_CLASS_LIGHTS = 0x0f, GREYBUS_CLASS_VIBRATOR = 0x10, GREYBUS_CLASS_LOOPBACK = 0x11, + GREYBUS_CLASS_I2S_RECEIVER = 0x12, + GREYBUS_CLASS_I2S_TRANSMITTER = 0x13, + GREYBUS_CLASS_SVC = 0x14, + /* ... */ + GREYBUS_CLASS_RAW = 0xfe, GREYBUS_CLASS_VENDOR = 0xff, }; -- cgit v0.10.2 From 6366d73fd49b68b5c1f4ebddc00d79e3cd7b6e3d Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 21 Jul 2015 17:44:11 +0530 Subject: greybus: protocol: move version_response structure to greybus_protocols.h Version response structure is also required by external entities like gbsim and so its structure should be moved to greybus_protocols.h. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 839f3a6..fe4b2dd 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -58,6 +58,15 @@ #define GB_CONTROL_BUNDLE_ID 0 #define GB_CONTROL_CPORT_ID 2 + +/* version request has no payload */ +struct gb_protocol_version_response { + __u8 major; + __u8 minor; +}; + +/* Control Protocol */ + /* Version of the Greybus control protocol we support */ #define GB_CONTROL_VERSION_MAJOR 0x00 #define GB_CONTROL_VERSION_MINOR 0x01 diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index 3f226e3..758b36e 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -13,12 +13,6 @@ struct gb_connection; struct gb_operation; -/* version request has no payload */ -struct gb_protocol_version_response { - __u8 major; - __u8 minor; -}; - typedef int (*gb_connection_init_t)(struct gb_connection *); typedef void (*gb_connection_exit_t)(struct gb_connection *); typedef int (*gb_request_recv_t)(u8, struct gb_operation *); -- cgit v0.10.2 From c8dd60db6cae0800e44e68e4c2c0c1af136414be Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 21 Jul 2015 17:44:12 +0530 Subject: greybus: Define device ids for AP/SVC/modules Define device-ids for AP, SVC and modules (starting id only). Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index fe4b2dd..0056c2a 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -52,7 +52,12 @@ #ifndef __GREYBUS_PROTOCOLS_H #define __GREYBUS_PROTOCOLS_H -/* Control Protocol */ +/* Fixed IDs for control/svc protocols */ + +/* Device ID of SVC and AP */ +#define GB_DEVICE_ID_SVC 0 +#define GB_DEVICE_ID_AP 1 +#define GB_DEVICE_ID_MODULES_START 2 /* Bundle-id and cport-id for control cport */ #define GB_CONTROL_BUNDLE_ID 0 -- cgit v0.10.2 From ec320625be76641c9f4d594335330a5544716304 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 21 Jul 2015 17:44:13 +0530 Subject: greybus: Define cport/bundle for SVC protocol For now, the plan is to use a single cport for both control and svc protocol. Defining separate macros for control and svc protocol's cport/bundle would make the code more flexible, in case we need two separate cports in future. Lets define cport/bundle for svc protocol as well. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 0056c2a..44957bd 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -59,11 +59,19 @@ #define GB_DEVICE_ID_AP 1 #define GB_DEVICE_ID_MODULES_START 2 -/* Bundle-id and cport-id for control cport */ +/* + * Bundle/cport for control/svc cport: The same bundle/cport is shared by both + * CONTROL and SVC protocols for communication between AP and SVC. + */ +#define GB_SVC_BUNDLE_ID 0 +#define GB_SVC_CPORT_ID 2 #define GB_CONTROL_BUNDLE_ID 0 #define GB_CONTROL_CPORT_ID 2 +/* Control Protocol */ + + /* version request has no payload */ struct gb_protocol_version_response { __u8 major; -- cgit v0.10.2 From e602df658888d0dc1d51ab907036c67b87ca9f3a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 21 Jul 2015 17:44:14 +0530 Subject: greybus: connection: don't send connected/disconnected events for SVC connection SVC is also a special protocol (like control) and AP doesn't need to send (dis)connected events for its cport. Lets skip them. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index edee5fb..9187a36 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -289,7 +289,7 @@ int gb_connection_init(struct gb_connection *connection) * Inform Interface about Active CPorts. We don't need to do this * operation for control cport. */ - if (cport_id != GB_CONTROL_CPORT_ID) { + if (cport_id != GB_CONTROL_CPORT_ID && cport_id != GB_SVC_CPORT_ID) { struct gb_control *control = connection->bundle->intf->control; ret = gb_control_connected_operation(control, cport_id); @@ -341,7 +341,7 @@ void gb_connection_exit(struct gb_connection *connection) * Inform Interface about In-active CPorts. We don't need to do this * operation for control cport. */ - if (cport_id != GB_CONTROL_CPORT_ID) { + if (cport_id != GB_CONTROL_CPORT_ID && cport_id != GB_SVC_CPORT_ID) { struct gb_control *control = connection->bundle->intf->control; int ret; -- cgit v0.10.2 From 007f979216bda08bb899c78d4f20c229d5fe6845 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 21 Jul 2015 17:44:15 +0530 Subject: greybus: connection: Create gb_connection_create_range() to specify hd-cport-id range We need to allocate specific hd-cport-id for AP's control/svc protocols. Support that by splitting functionality of gb_connection_create() into a new routine, which takes range of hd_cport_id's to allocate from. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 9187a36..c6e1d70 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -141,8 +141,9 @@ void gb_connection_bind_protocol(struct gb_connection *connection) * Returns a pointer to the new connection if successful, or a null * pointer otherwise. */ -struct gb_connection *gb_connection_create(struct gb_bundle *bundle, - u16 cport_id, u8 protocol_id) +struct gb_connection * +gb_connection_create_range(struct gb_bundle *bundle, u16 cport_id, + u8 protocol_id, u32 ida_start, u32 ida_end) { struct gb_connection *connection; struct greybus_host_device *hd = bundle->intf->hd; @@ -165,7 +166,7 @@ struct gb_connection *gb_connection_create(struct gb_bundle *bundle, if (!connection) return NULL; - retval = ida_simple_get(id_map, 0, CPORT_ID_MAX, GFP_KERNEL); + retval = ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL); if (retval < 0) { kfree(connection); return NULL; @@ -221,6 +222,13 @@ struct gb_connection *gb_connection_create(struct gb_bundle *bundle, return connection; } +struct gb_connection *gb_connection_create(struct gb_bundle *bundle, + u16 cport_id, u8 protocol_id) +{ + return gb_connection_create_range(bundle, cport_id, protocol_id, 0, + CPORT_ID_MAX); +} + /* * Cancel all active operations on a connection. * diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index fb7a1fb..bba14b5 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -47,6 +47,9 @@ struct gb_connection { struct gb_connection *gb_connection_create(struct gb_bundle *bundle, u16 cport_id, u8 protocol_id); +struct gb_connection *gb_connection_create_range(struct gb_bundle *bundle, + u16 cport_id, u8 protocol_id, u32 ida_start, + u32 ida_end); void gb_connection_destroy(struct gb_connection *connection); int gb_connection_init(struct gb_connection *connection); -- cgit v0.10.2 From 75662e5ca9e0d85fd3e94e51712e79c18c10064f Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 21 Jul 2015 17:44:16 +0530 Subject: greybus: connection: Allow a bundle-less connection We need a bundle-less connection for AP's SVC protocol, as that will be used much before the endo layout and interface-id of the AP is known to greybus core. This updates gb_connection_create_range() to take few more arguments, which were earlier fetched from the 'bundle' pointer. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index c6e1d70..feb6e49 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -107,7 +107,6 @@ struct device_type greybus_connection_type = { void gb_connection_bind_protocol(struct gb_connection *connection) { - struct gb_interface *intf; struct gb_protocol *protocol; /* If we already have a protocol bound here, just return */ @@ -125,8 +124,9 @@ void gb_connection_bind_protocol(struct gb_connection *connection) * If we have a valid device_id for the interface block, then we have an * active device, so bring up the connection at the same time. */ - intf = connection->bundle->intf; - if (intf->device_id != GB_DEVICE_ID_BAD) + if ((!connection->bundle && + connection->hd_cport_id == GB_SVC_CPORT_ID) || + connection->bundle->intf->device_id != GB_DEVICE_ID_BAD) gb_connection_init(connection); } @@ -142,11 +142,12 @@ void gb_connection_bind_protocol(struct gb_connection *connection) * pointer otherwise. */ struct gb_connection * -gb_connection_create_range(struct gb_bundle *bundle, u16 cport_id, - u8 protocol_id, u32 ida_start, u32 ida_end) +gb_connection_create_range(struct greybus_host_device *hd, + struct gb_bundle *bundle, struct device *parent, + u16 cport_id, u8 protocol_id, u32 ida_start, + u32 ida_end) { struct gb_connection *connection; - struct greybus_host_device *hd = bundle->intf->hd; struct ida *id_map = &hd->cport_id_map; int retval; u8 major = 0; @@ -157,7 +158,7 @@ gb_connection_create_range(struct gb_bundle *bundle, u16 cport_id, * initialize connections serially so we don't need to worry * about holding the connection lock. */ - if (gb_connection_intf_find(bundle->intf, cport_id)) { + if (bundle && gb_connection_intf_find(bundle->intf, cport_id)) { pr_err("duplicate interface cport id 0x%04hx\n", cport_id); return NULL; } @@ -182,13 +183,13 @@ gb_connection_create_range(struct gb_bundle *bundle, u16 cport_id, connection->bundle = bundle; connection->state = GB_CONNECTION_STATE_DISABLED; - connection->dev.parent = &bundle->dev; + connection->dev.parent = parent; connection->dev.bus = &greybus_bus_type; connection->dev.type = &greybus_connection_type; connection->dev.groups = connection_groups; device_initialize(&connection->dev); dev_set_name(&connection->dev, "%s:%d", - dev_name(&bundle->dev), cport_id); + dev_name(parent), cport_id); retval = device_add(&connection->dev); if (retval) { @@ -206,7 +207,12 @@ gb_connection_create_range(struct gb_bundle *bundle, u16 cport_id, spin_lock_irq(&gb_connections_lock); list_add(&connection->hd_links, &hd->connections); - list_add(&connection->bundle_links, &bundle->connections); + + if (bundle) + list_add(&connection->bundle_links, &bundle->connections); + else + INIT_LIST_HEAD(&connection->bundle_links); + spin_unlock_irq(&gb_connections_lock); atomic_set(&connection->op_cycle, 0); @@ -225,8 +231,9 @@ gb_connection_create_range(struct gb_bundle *bundle, u16 cport_id, struct gb_connection *gb_connection_create(struct gb_bundle *bundle, u16 cport_id, u8 protocol_id) { - return gb_connection_create_range(bundle, cport_id, protocol_id, 0, - CPORT_ID_MAX); + return gb_connection_create_range(bundle->intf->hd, bundle, + &bundle->dev, cport_id, protocol_id, + 0, CPORT_ID_MAX); } /* diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index bba14b5..d8fbce4 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -47,9 +47,10 @@ struct gb_connection { struct gb_connection *gb_connection_create(struct gb_bundle *bundle, u16 cport_id, u8 protocol_id); -struct gb_connection *gb_connection_create_range(struct gb_bundle *bundle, - u16 cport_id, u8 protocol_id, u32 ida_start, - u32 ida_end); +struct gb_connection *gb_connection_create_range(struct greybus_host_device *hd, + struct gb_bundle *bundle, struct device *parent, + u16 cport_id, u8 protocol_id, u32 ida_start, + u32 ida_end); void gb_connection_destroy(struct gb_connection *connection); int gb_connection_init(struct gb_connection *connection); -- cgit v0.10.2 From 7a24a3f6ce507a3169bbc38fc70b9d0919a44cd5 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 21 Jul 2015 17:44:17 +0530 Subject: greybus: interface: Update gb_create_control_connection() to support SVC protocol We need to create bundle/connection for svc cport after the endo layout and interface id is known to the AP. gb_create_control_connection() can be reused for this, but it should be renamed to something more appropriate, as its not about control-connection anymore. Lets name it gb_create_bundle_connection(). Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index dfc31a0..6d61285 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -70,19 +70,39 @@ struct device_type greybus_interface_type = { /* * Create kernel structures corresponding to a bundle and connection for - * managing control CPort. + * managing control/svc CPort. */ -static int gb_create_control_connection(struct gb_interface *intf) +int gb_create_bundle_connection(struct gb_interface *intf, u8 class) { struct gb_bundle *bundle; + u32 ida_start, ida_end; + u8 bundle_id, protocol_id; + u16 cport_id; + + if (class == GREYBUS_CLASS_CONTROL) { + protocol_id = GREYBUS_PROTOCOL_CONTROL; + bundle_id = GB_CONTROL_BUNDLE_ID; + cport_id = GB_CONTROL_CPORT_ID; + ida_start = 0; + ida_end = CPORT_ID_MAX; + } else if (class == GREYBUS_CLASS_SVC) { + protocol_id = GREYBUS_PROTOCOL_SVC; + bundle_id = GB_SVC_BUNDLE_ID; + cport_id = GB_SVC_CPORT_ID; + ida_start = GB_SVC_CPORT_ID; + ida_end = GB_SVC_CPORT_ID + 1; + } else { + WARN_ON(1); + return -EINVAL; + } - bundle = gb_bundle_create(intf, GB_CONTROL_BUNDLE_ID, - GREYBUS_CLASS_CONTROL); + bundle = gb_bundle_create(intf, bundle_id, class); if (!bundle) return -EINVAL; - if (!gb_connection_create(bundle, GB_CONTROL_CPORT_ID, - GREYBUS_PROTOCOL_CONTROL)) + if (!gb_connection_create_range(bundle->intf->hd, bundle, &bundle->dev, + cport_id, protocol_id, ida_start, + ida_end)) return -EINVAL; return 0; @@ -202,7 +222,7 @@ int gb_interface_init(struct gb_interface *intf, u8 device_id) intf->device_id = device_id; /* Establish control CPort connection */ - ret = gb_create_control_connection(intf); + ret = gb_create_bundle_connection(intf, GREYBUS_CLASS_CONTROL); if (ret) { dev_err(&intf->dev, "Failed to create control CPort connection (%d)\n", ret); return ret; diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index c2bcb92..04d330c 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -56,5 +56,5 @@ int gb_interface_init(struct gb_interface *intf, u8 device_id); void gb_interface_remove(struct greybus_host_device *hd, u8 interface_id); void gb_interfaces_remove(struct greybus_host_device *hd); - +int gb_create_bundle_connection(struct gb_interface *intf, u8 class); #endif /* __INTERFACE_H */ -- cgit v0.10.2 From d3d448406772e421fb7ed8efd4d02d96cb2ab6f9 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 21 Jul 2015 17:44:18 +0530 Subject: greybus: svc: Add helpers to create AP<->SVC connection SVC connection is required before the AP knows its position on the endo and type of endo. To enable message processing between the AP and SVC at this time, we need a partially initialized connection which can handle these messages. Once the AP receives more information from the SVC, it can discard this partially initialized connection and create a proper one, tied to a bundle and interface. Destroying the partially initialized connection is a bit tricky, as it is required to send a response to svc-hello. That part will be properly fixed separately. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index e795016..2214f44 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -102,6 +102,7 @@ struct greybus_host_device { size_t buffer_size_max; struct gb_endo *endo; + struct gb_connection *initial_svc_connection; /* Private data for the host driver */ unsigned long hd_priv[0] __aligned(sizeof(s64)); diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 6d61285..f1e2956 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -183,7 +183,7 @@ put_module: /* * Tear down a previously set up module. */ -static void gb_interface_destroy(struct gb_interface *intf) +void gb_interface_destroy(struct gb_interface *intf) { struct gb_module *module; struct gb_bundle *bundle; diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 04d330c..9a9260c 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -53,6 +53,7 @@ struct gb_interface *gb_interface_find(struct greybus_host_device *hd, struct gb_interface *gb_interface_create(struct greybus_host_device *hd, u8 interface_id); int gb_interface_init(struct gb_interface *intf, u8 device_id); +void gb_interface_destroy(struct gb_interface *intf); void gb_interface_remove(struct greybus_host_device *hd, u8 interface_id); void gb_interfaces_remove(struct greybus_host_device *hd); diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index ce789c9..1382384 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -12,6 +12,66 @@ /* Define get_version() routine */ define_get_version(gb_svc, SVC); +/* + * AP's SVC cport is required early to get messages from the SVC. This happens + * even before the Endo is created and hence any modules or interfaces. + * + * This is a temporary connection, used only at initial bootup. + */ +struct gb_connection * +gb_ap_svc_connection_create(struct greybus_host_device *hd) +{ + struct gb_connection *connection; + + connection = gb_connection_create_range(hd, NULL, hd->parent, + GB_SVC_CPORT_ID, + GREYBUS_PROTOCOL_SVC, + GB_SVC_CPORT_ID, + GB_SVC_CPORT_ID + 1); + + return connection; +} +EXPORT_SYMBOL_GPL(gb_ap_svc_connection_create); + +/* + * We know endo-type and AP's interface id now, lets create a proper svc + * connection (and its interface/bundle) now and get rid of the initial + * 'partially' initialized one svc connection. + */ +static struct gb_interface * +gb_ap_interface_create(struct greybus_host_device *hd, + struct gb_connection *connection, u8 interface_id) +{ + struct gb_interface *intf; + struct device *dev = &hd->endo->dev; + int ret; + + intf = gb_interface_create(hd, interface_id); + if (!intf) { + dev_err(dev, "%s: Failed to create interface with id %hhu\n", + __func__, interface_id); + return NULL; + } + + intf->device_id = GB_DEVICE_ID_AP; + + /* + * XXX: Disable the initial svc connection here, but don't destroy it + * yet. We do need to send a response of 'svc-hello message' on that. + */ + + /* Establish new control CPort connection */ + ret = gb_create_bundle_connection(intf, GREYBUS_CLASS_SVC); + if (ret) { + dev_err(&intf->dev, "%s: Failed to create svc connection (%d %d)\n", + __func__, interface_id, ret); + gb_interface_destroy(intf); + intf = NULL; + } + + return intf; +} + static int intf_device_id_operation(struct gb_svc *svc, u8 intf_id, u8 device_id) { @@ -207,6 +267,22 @@ static int gb_svc_connection_init(struct gb_connection *connection) svc->connection = connection; connection->private = svc; + + /* + * SVC connection is created twice: + * - before the interface-id of the AP and the endo type is known. + * - after receiving endo type and interface-id of the AP from the SVC. + * + * We should do light-weight initialization for the first case. + */ + if (!connection->bundle) { + WARN_ON(connection->hd->initial_svc_connection); + connection->hd->initial_svc_connection = connection; + return 0; + } + + ida_init(&greybus_svc_device_id_map); + ret = gb_svc_device_setup(svc); if (ret) kfree(svc); @@ -221,11 +297,15 @@ static void gb_svc_connection_exit(struct gb_connection *connection) { struct gb_svc *svc = connection->private; - if (WARN_ON(connection->bundle->intf->svc != svc)) - return; - - connection->bundle->intf->svc = NULL; + if (connection->hd->initial_svc_connection == connection) { + connection->hd->initial_svc_connection = NULL; + } else { + if (WARN_ON(connection->bundle->intf->svc != svc)) + return; + connection->bundle->intf->svc = NULL; + } + connection->private = NULL; kfree(svc); } diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index ebabe5f..6649780 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -26,4 +26,7 @@ int gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, int gb_svc_protocol_init(void); void gb_svc_protocol_exit(void); + +struct gb_connection * +gb_ap_svc_connection_create(struct greybus_host_device *hd); #endif /* __SVC_H */ -- cgit v0.10.2 From ead35460b5aaeeff5e0376fbae761cc59feb2237 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 21 Jul 2015 17:44:19 +0530 Subject: greybus: svc: Implement SVC requests Some of the SVC request are already partially implement, whereas few others are not. This patch implements and updates these requests. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 44957bd..61fe9dc 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -556,12 +556,22 @@ struct gb_spi_transfer_response { /* Greybus SVC request types */ #define GB_SVC_TYPE_INVALID 0x00 #define GB_SVC_TYPE_PROTOCOL_VERSION 0x01 -#define GB_SVC_TYPE_INTF_DEVICE_ID 0x02 -#define GB_SVC_TYPE_INTF_HOTPLUG 0x03 -#define GB_SVC_TYPE_INTF_HOT_UNPLUG 0x04 -#define GB_SVC_TYPE_INTF_RESET 0x05 -#define GB_SVC_TYPE_CONN_CREATE 0x06 -#define GB_SVC_TYPE_CONN_DESTROY 0x07 +#define GB_SVC_TYPE_SVC_HELLO 0x02 +#define GB_SVC_TYPE_INTF_DEVICE_ID 0x03 +#define GB_SVC_TYPE_INTF_HOTPLUG 0x04 +#define GB_SVC_TYPE_INTF_HOT_UNPLUG 0x05 +#define GB_SVC_TYPE_INTF_RESET 0x06 +#define GB_SVC_TYPE_CONN_CREATE 0x07 +#define GB_SVC_TYPE_CONN_DESTROY 0x08 + +/* SVC version request/response have same payload as gb_protocol_version_response */ + +/* SVC protocol hello request */ +struct gb_svc_hello_request { + __le16 endo_id; + __u8 interface_id; +}; +/* hello response has no payload */ struct gb_svc_intf_device_id_request { __u8 intf_id; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 1382384..ee46779 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -9,6 +9,8 @@ #include "greybus.h" +static struct ida greybus_svc_device_id_map; + /* Define get_version() routine */ define_get_version(gb_svc, SVC); @@ -154,22 +156,99 @@ int gb_svc_connection_destroy(struct gb_svc *svc, } EXPORT_SYMBOL_GPL(gb_svc_connection_destroy); +static int gb_svc_version_request(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_protocol_version_response *version; + struct device *dev = &connection->dev; + + version = op->request->payload; + + if (version->major > GB_SVC_VERSION_MAJOR) { + dev_err(&connection->dev, + "unsupported major version (%hhu > %hhu)\n", + version->major, GB_SVC_VERSION_MAJOR); + return -ENOTSUPP; + } + + if (!gb_operation_response_alloc(op, sizeof(*version), GFP_KERNEL)) { + dev_err(dev, "%s: error allocating response\n", + __func__); + return -ENOMEM; + } + + version = op->response->payload; + version->major = GB_SVC_VERSION_MAJOR; + version->minor = GB_SVC_VERSION_MINOR; + return 0; +} + +static int gb_svc_hello(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct greybus_host_device *hd = connection->hd; + struct gb_svc_hello_request *hello_request; + struct device *dev = &connection->dev; + struct gb_interface *intf; + u16 endo_id; + u8 interface_id; + int ret; + + /* Hello message should be received only during early bootup */ + WARN_ON(hd->initial_svc_connection != connection); + + /* + * SVC sends information about the endo and interface-id on the hello + * request, use that to create an endo. + */ + if (op->request->payload_size != sizeof(*hello_request)) { + dev_err(dev, "%s: Illegal size of hello request (%d %d)\n", + __func__, op->request->payload_size, + sizeof(*hello_request)); + return -EINVAL; + } + + hello_request = op->request->payload; + endo_id = le16_to_cpu(hello_request->endo_id); + interface_id = hello_request->interface_id; + + /* Setup Endo */ + ret = greybus_endo_setup(hd, endo_id, interface_id); + if (ret) + return ret; + + /* + * Endo and its modules are ready now, fix AP's partially initialized + * svc protocol and its connection. + */ + intf = gb_ap_interface_create(hd, connection, interface_id); + if (!intf) { + gb_endo_remove(hd->endo); + return ret; + } + + return 0; +} + static int gb_svc_intf_hotplug_recv(struct gb_operation *op) { struct gb_message *request = op->request; - struct gb_svc_intf_hotplug_request *hotplug; - u8 intf_id; + struct gb_svc_intf_hotplug_request *hotplug = request->payload; + struct gb_svc *svc = op->connection->private; + struct greybus_host_device *hd = op->connection->bundle->intf->hd; + struct device *dev = &op->connection->dev; + struct gb_interface *intf; + u8 intf_id, device_id; u32 unipro_mfg_id; u32 unipro_prod_id; u32 ara_vend_id; u32 ara_prod_id; + int ret; if (request->payload_size < sizeof(*hotplug)) { - dev_err(&op->connection->dev, - "short hotplug request received\n"); + dev_err(dev, "%s: short hotplug request received\n", __func__); return -EINVAL; } - hotplug = request->payload; /* * Grab the information we need. @@ -185,15 +264,68 @@ static int gb_svc_intf_hotplug_recv(struct gb_operation *op) ara_vend_id = le32_to_cpu(hotplug->data.ara_vend_id); ara_prod_id = le32_to_cpu(hotplug->data.ara_prod_id); - /* FIXME Set up the interface here; may required firmware download */ + // FIXME May require firmware download + intf = gb_interface_create(hd, intf_id); + if (!intf) { + dev_err(dev, "%s: Failed to create interface with id %hhu\n", + __func__, intf_id); + return -EINVAL; + } + + /* + * Create a device id for the interface: + * - device id 0 (GB_DEVICE_ID_SVC) belongs to the SVC + * - device id 1 (GB_DEVICE_ID_AP) belongs to the AP + * + * XXX Do we need to allocate device ID for SVC or the AP here? And what + * XXX about an AP with multiple interface blocks? + */ + device_id = ida_simple_get(&greybus_svc_device_id_map, + GB_DEVICE_ID_MODULES_START, 0, GFP_ATOMIC); + if (device_id < 0) { + ret = device_id; + dev_err(dev, "%s: Failed to allocate device id for interface with id %hhu (%d)\n", + __func__, intf_id, ret); + goto destroy_interface; + } + + ret = intf_device_id_operation(svc, intf_id, device_id); + if (ret) { + dev_err(dev, "%s: Device id operation failed, interface %hhu device_id %hhu (%d)\n", + __func__, intf_id, device_id, ret); + goto ida_put; + } + + ret = gb_interface_init(intf, device_id); + if (ret) { + dev_err(dev, "%s: Failed to initialize interface, interface %hhu device_id %hhu (%d)\n", + __func__, intf_id, device_id, ret); + goto svc_id_free; + } return 0; + +svc_id_free: + /* + * XXX Should we tell SVC that this id doesn't belong to interface + * XXX anymore. + */ +ida_put: + ida_simple_remove(&greybus_svc_device_id_map, device_id); +destroy_interface: + gb_interface_remove(hd, intf_id); + + return ret; } static int gb_svc_intf_hot_unplug_recv(struct gb_operation *op) { struct gb_message *request = op->request; - struct gb_svc_intf_hot_unplug_request *hot_unplug; + struct gb_svc_intf_hot_unplug_request *hot_unplug = request->payload; + struct greybus_host_device *hd = op->connection->bundle->intf->hd; + struct device *dev = &op->connection->dev; + u8 device_id; + struct gb_interface *intf; u8 intf_id; if (request->payload_size < sizeof(*hot_unplug)) { @@ -201,14 +333,21 @@ static int gb_svc_intf_hot_unplug_recv(struct gb_operation *op) "short hot unplug request received\n"); return -EINVAL; } - hot_unplug = request->payload; intf_id = hot_unplug->intf_id; - /* FIXME Tear down the interface here */ + intf = gb_interface_find(hd, intf_id); + if (!intf) { + dev_err(dev, "%s: Couldn't find interface for id %hhu\n", + __func__, intf_id); + return -EINVAL; + } - return 0; + device_id = intf->device_id; + gb_interface_remove(hd, intf_id); + ida_simple_remove(&greybus_svc_device_id_map, device_id); + return 0; } static int gb_svc_intf_reset_recv(struct gb_operation *op) @@ -234,6 +373,10 @@ static int gb_svc_intf_reset_recv(struct gb_operation *op) static int gb_svc_request_recv(u8 type, struct gb_operation *op) { switch (type) { + case GB_SVC_TYPE_PROTOCOL_VERSION: + return gb_svc_version_request(op); + case GB_SVC_TYPE_SVC_HELLO: + return gb_svc_hello(op); case GB_SVC_TYPE_INTF_HOTPLUG: return gb_svc_intf_hotplug_recv(op); case GB_SVC_TYPE_INTF_HOT_UNPLUG: -- cgit v0.10.2 From 18d777cd6686dbaf30fd7b1f7bddc5090c60bc98 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 21 Jul 2015 17:44:20 +0530 Subject: greybus: svc: No need of a separate version request SVC already provided version to the AP on version-request, no need to ask for that again. Drop it. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index ee46779..c9bbdc0 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -11,9 +11,6 @@ static struct ida greybus_svc_device_id_map; -/* Define get_version() routine */ -define_get_version(gb_svc, SVC); - /* * AP's SVC cport is required early to get messages from the SVC. This happens * even before the Endo is created and hence any modules or interfaces. @@ -390,19 +387,9 @@ static int gb_svc_request_recv(u8 type, struct gb_operation *op) } } -/* - * Do initial setup of the SVC. - */ -static int gb_svc_device_setup(struct gb_svc *gb_svc) -{ - /* First thing we need to do is check the version */ - return get_version(gb_svc); -} - static int gb_svc_connection_init(struct gb_connection *connection) { struct gb_svc *svc; - int ret; svc = kzalloc(sizeof(*svc), GFP_KERNEL); if (!svc) @@ -426,14 +413,10 @@ static int gb_svc_connection_init(struct gb_connection *connection) ida_init(&greybus_svc_device_id_map); - ret = gb_svc_device_setup(svc); - if (ret) - kfree(svc); - /* Set interface's svc connection */ connection->bundle->intf->svc = svc; - return ret; + return 0; } static void gb_svc_connection_exit(struct gb_connection *connection) -- cgit v0.10.2 From b38fe3472d38933b9fb751918a09d65f1483ef8b Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 21 Jul 2015 09:10:27 +0100 Subject: greybus: manifest: reserve control connection cport/bundle ids 5ae6906e ('interface: Get manifest using Control protocol') in gb_create_control_connection introduces the concept that the Control Protocol is at cport_id 2 and bundle_id 0. Currently the manifest parsing code does not enforce that concept and as a result it is possible for a manifest to declare the Control Protocol at a different address. Based on that change 6a6945c9684e ('greybus-spec/control: Formally define Control Protocol reserved addresses') makes the above coding convention a formal requirement of the greybus specification. This patch implements the change introduced in the specification @ 6a6945c9684e. This patch will reject a manifest if it doesn't match the critiera laid down in the spec. This patch makes three changes: - Changes gb_manifest_parse_cports so that only GB_CONTROL_CPORT_ID may have a protocol_id of GREYBUS_PROTOCOL_CONTROL, otherwise the manifest will be rejected. - Changes gb_manifest_parse_bundles so that only GB_CONTROL_BUNDLE_ID may have a class of GREYBUS_CLASS_CONTROL, otherwise the manifest will be rejected. - gb_connection_exit() and gb_connection_destroy() are removed from gb_manifest_parse_cports on error - since gb_manifest_parse_bundles() already has a call into gb_bundle_destroy() which will again call gb_connection_exit() and gb_connection_destroy() leading to an oops. Signed-off-by: Bryan O'Donoghue Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index bea565f..a84c071 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -201,18 +201,16 @@ static char *gb_string_get(struct gb_interface *intf, u8 string_id) static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) { struct gb_interface *intf = bundle->intf; - struct gb_connection *connection; - struct gb_connection *connection_next; struct manifest_desc *desc; struct manifest_desc *next; u8 bundle_id = bundle->id; + u8 protocol_id; + u16 cport_id; u32 count = 0; /* Set up all cport descriptors associated with this bundle */ list_for_each_entry_safe(desc, next, &intf->manifest_descs, links) { struct greybus_descriptor_cport *desc_cport; - u8 protocol_id; - u16 cport_id; if (desc->type != GREYBUS_TYPE_CPORT) continue; @@ -223,25 +221,26 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) cport_id = le16_to_cpu(desc_cport->id); if (cport_id > CPORT_ID_MAX) - goto cleanup; + goto exit; /* Found one. Set up its function structure */ protocol_id = desc_cport->protocol_id; - /* Don't recreate connection for control cport */ + /* Validate declarations of the control protocol CPort */ if (cport_id == GB_CONTROL_CPORT_ID) { /* This should have protocol set to control protocol*/ - WARN_ON(protocol_id != GREYBUS_PROTOCOL_CONTROL); - + if (protocol_id != GREYBUS_PROTOCOL_CONTROL) + goto print_error_exit; + /* Don't recreate connection for control cport */ goto release_descriptor; } - /* Nothing else should have its protocol as control protocol */ - if (WARN_ON(protocol_id == GREYBUS_PROTOCOL_CONTROL)) - goto release_descriptor; + if (protocol_id == GREYBUS_PROTOCOL_CONTROL) { + goto print_error_exit; + } if (!gb_connection_create(bundle, cport_id, protocol_id)) - goto cleanup; + goto exit; release_descriptor: count++; @@ -251,14 +250,14 @@ release_descriptor: } return count; -cleanup: - /* An error occurred; undo any changes we've made */ - list_for_each_entry_safe(connection, connection_next, - &bundle->connections, bundle_links) { - gb_connection_exit(connection); - gb_connection_destroy(connection); - count--; - } +print_error_exit: + /* A control protocol parse error was encountered */ + dev_err(&bundle->dev, + "cport_id, protocol_id 0x%04hx,0x%04hx want 0x%04hx,0x%04hx\n", + cport_id, protocol_id, GB_CONTROL_CPORT_ID, + GREYBUS_PROTOCOL_CONTROL); +exit: + return 0; /* Error; count should also be 0 */ } @@ -287,15 +286,24 @@ static u32 gb_manifest_parse_bundles(struct gb_interface *intf) /* Don't recreate bundle for control cport */ if (desc_bundle->id == GB_CONTROL_BUNDLE_ID) { /* This should have class set to control class */ - WARN_ON(desc_bundle->class != GREYBUS_CLASS_CONTROL); + if (desc_bundle->class != GREYBUS_CLASS_CONTROL) { + dev_err(&intf->dev, + "bad class 0x%02x for control bundle\n", + desc_bundle->class); + goto cleanup; + } bundle = intf->control->connection->bundle; goto parse_cports; } /* Nothing else should have its class set to control class */ - if (WARN_ON(desc_bundle->class == GREYBUS_CLASS_CONTROL)) - goto release_descriptor; + if (desc_bundle->class == GREYBUS_CLASS_CONTROL) { + dev_err(&intf->dev, + "bundle 0x%02x cannot use control class\n", + desc_bundle->id); + goto cleanup; + } bundle = gb_bundle_create(intf, desc_bundle->id, desc_bundle->class); @@ -307,11 +315,9 @@ parse_cports: if (!gb_manifest_parse_cports(bundle)) goto cleanup; -release_descriptor: - count++; - /* Done with this bundle descriptor */ release_manifest_descriptor(desc); + count++; } return count; -- cgit v0.10.2 From 09fb10fe4fc04785eb8a0065c64dd9728ed71dbe Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 21 Jul 2015 09:10:28 +0100 Subject: greybus: manifest: convert pr_err to dev_err This patch converts a dangling pr_err in the manifest parsing error path to a dev_err in order to remain consistent with similar error messages elsewhere. Signed-off-by: Bryan O'Donoghue Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index a84c071..559b2ee 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -355,7 +355,7 @@ static bool gb_manifest_parse_interface(struct gb_interface *intf, /* An interface must have at least one bundle descriptor */ if (!gb_manifest_parse_bundles(intf)) { - pr_err("manifest bundle descriptors not valid\n"); + dev_err(&intf->dev, "manifest bundle descriptors not valid\n"); goto out_err; } -- cgit v0.10.2 From 3156be7deec47564853d13308090828c35f89cb9 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 21 Jul 2015 23:50:06 +0100 Subject: greybus: loopback: timestamp seeding should not drop metrics In the current code if the ts variable is not initialized then any data already gathered in a previous loopback command is dropped instead of logged. Also the timestamping of ts is done after the greybus operation. This delayed time-stamping means that the delta between the before and after timestamps is incorrect and if a delay in-between loopback operations has been specified by the user, the ts timestamp will be very skewed indeed. - Move the ts initialization directly before the greybus operation. - Remove the continue statement on first initialization of the ts variable. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index fe3a57b..2de939f2 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -394,6 +394,8 @@ static int gb_loopback_fn(void *data) msleep(1000); continue; } + if (gb->ts.tv_usec == 0 && gb->ts.tv_sec == 0) + do_gettimeofday(&gb->ts); if (gb->type == GB_LOOPBACK_TYPE_PING) error = gb_loopback_ping(gb, &tlat); else if (gb->type == GB_LOOPBACK_TYPE_TRANSFER) @@ -402,10 +404,6 @@ static int gb_loopback_fn(void *data) error = gb_loopback_sink(gb, &tlat, gb->size); if (error) gb->error++; - if (gb->ts.tv_usec == 0 && gb->ts.tv_sec == 0) { - do_gettimeofday(&gb->ts); - continue; - } do_gettimeofday(&gb->te); gb->elapsed_nsecs = timeval_to_ns(&gb->te) - timeval_to_ns(&gb->ts); -- cgit v0.10.2 From 799a3f03572afa77913f2adc136c87a4b0c64850 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 21 Jul 2015 23:50:07 +0100 Subject: greybus: loopback: update loopback operation description comment Old comment needs updating to match 8a282c411ba0 ('greybus/loopback: make loopback type input equivalent to protocol type') Signed-off-by: Bryan O'Donoghue Reviewed-by: Patrick Titiano Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 2de939f2..66385c9 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -137,10 +137,12 @@ gb_loopback_stats_attrs(throughput); gb_loopback_ro_attr(error, d); /* - * Type of loopback message to send + * Type of loopback message to send based on protocol type definitions * 0 => Don't send message - * 1 => Send ping message continuously (message without payload) - * 2 => Send transer message continuously (message with payload) + * 2 => Send ping message continuously (message without payload) + * 3 => Send transer message continuously (message with payload, + * payload returned in response) + * 4 => Send a sink message (message with payload, no payload in response) */ gb_loopback_attr(type, d); /* Size of transfer message payload: 0-4096 bytes */ -- cgit v0.10.2 From 00af6583d15038cfaa81a99632122b67d49de403 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 21 Jul 2015 23:50:08 +0100 Subject: greybus: loopback: run operations a set number of times In order to extract a meaningful set of data out of loopback metrics it makes sense to have the ability to specify how many times a loopback operation should run and then to stop when the threshold is hit. This will allow exactly the same loopback data pattern to be run again and again, which is a fundamental prerequisite to instrumenting and characterizing the loopback interface over time. This patch introduces a simple sysfs controlled variable iteration_max. iteration_max is the maximum number of iterations to run for a given set. iteration_count is used internally to count from zero to iteration_max if-and-only-if iteration_max is non zero. If iteration_max is zero then the original behaviour of running the test command ad infinitum is maintained. User-space should incrementally poll the iteration_count to determine when the sequence is finished. To accomplish this we move away from running as many commands as possible in a one second window and instead run a fixed number of commands and log the time it takes for those commands to complete in aggregate. Since we are no longer resetting counters every one second, the tracker variables have been moved from u32 to u64 to allow for reasonably long tests to gather reasonably large amounts of data, without fear of over-flowing the data-points. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 66385c9..6597394 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -18,11 +18,11 @@ #include "greybus.h" struct gb_loopback_stats { - u32 min; - u32 max; - u32 avg; - u32 sum; - u32 count; + u64 min; + u64 max; + u64 avg; + u64 sum; + u64 count; }; struct gb_loopback { @@ -34,6 +34,8 @@ struct gb_loopback { int type; u32 size; + u32 iteration_max; + u32 iteration_count; size_t size_max; int ms_wait; @@ -77,9 +79,9 @@ static ssize_t name##_##field##_show(struct device *dev, \ static DEVICE_ATTR_RO(name##_##field) #define gb_loopback_stats_attrs(field) \ - gb_loopback_ro_stats_attr(field, min, d); \ - gb_loopback_ro_stats_attr(field, max, d); \ - gb_loopback_ro_stats_attr(field, avg, d); + gb_loopback_ro_stats_attr(field, min, llu); \ + gb_loopback_ro_stats_attr(field, max, llu); \ + gb_loopback_ro_stats_attr(field, avg, llu); #define gb_loopback_attr(field, type) \ static ssize_t field##_show(struct device *dev, \ @@ -125,6 +127,7 @@ static void gb_loopback_check_attr(struct gb_loopback *gb) if (gb->size > gb->size_max) gb->size = gb->size_max; gb->error = 0; + gb->iteration_count = 0; gb_loopback_reset_stats(gb); } @@ -135,6 +138,7 @@ gb_loopback_stats_attrs(frequency); /* Quantity of data sent and received on this cport */ gb_loopback_stats_attrs(throughput); gb_loopback_ro_attr(error, d); +gb_loopback_ro_attr(iteration_count, u); /* * Type of loopback message to send based on protocol type definitions @@ -149,6 +153,8 @@ gb_loopback_attr(type, d); gb_loopback_attr(size, u); /* Time to wait between two messages: 0-1000 ms */ gb_loopback_attr(ms_wait, d); +/* Maximum iterations for a given operation: 1-(2^32-1), 0 implies infinite */ +gb_loopback_attr(iteration_max, u); #define dev_stats_attrs(name) \ &dev_attr_##name##_min.attr, \ @@ -162,6 +168,8 @@ static struct attribute *loopback_attrs[] = { &dev_attr_type.attr, &dev_attr_size.attr, &dev_attr_ms_wait.attr, + &dev_attr_iteration_count.attr, + &dev_attr_iteration_max.attr, &dev_attr_error.attr, NULL, }; @@ -313,38 +321,29 @@ static void gb_loopback_reset_stats(struct gb_loopback *gb) memset(&gb->ts, 0, sizeof(struct timeval)); } -static void gb_loopback_update_stats(struct gb_loopback_stats *stats, - u64 elapsed_nsecs) +static void gb_loopback_update_stats(struct gb_loopback_stats *stats, u64 val) { - u32 avg; - u64 tmp; - - if (elapsed_nsecs >= NSEC_PER_SEC) { - if (!stats->count) { - tmp = elapsed_nsecs; - do_div(tmp, NSEC_PER_SEC); - avg = stats->sum * tmp; - } else { - avg = stats->sum / stats->count; - } - if (stats->min > avg) - stats->min = avg; - if (stats->max < avg) - stats->max = avg; - stats->avg = avg; - stats->count = 0; - stats->sum = 0; - } + if (stats->min > val) + stats->min = val; + if (stats->max < val) + stats->max = val; + stats->sum += val; + stats->count++; + stats->avg = stats->sum; + do_div(stats->avg, stats->count); } -static void gb_loopback_freq_update(struct gb_loopback *gb) +static void gb_loopback_frequency_update(struct gb_loopback *gb, u32 latency) { - gb->frequency.sum++; - gb_loopback_update_stats(&gb->frequency, gb->elapsed_nsecs); + u32 freq = USEC_PER_SEC; + + do_div(freq, latency); + gb_loopback_update_stats(&gb->frequency, freq); } -static void gb_loopback_throughput_update(struct gb_loopback *gb) +static void gb_loopback_throughput_update(struct gb_loopback *gb, u32 latency) { + u32 throughput; u32 aggregate_size = sizeof(struct gb_operation_msg_hdr) * 2; switch (gb->type) { @@ -362,27 +361,31 @@ static void gb_loopback_throughput_update(struct gb_loopback *gb) default: return; } - gb->throughput.sum += aggregate_size; - gb_loopback_update_stats(&gb->throughput, gb->elapsed_nsecs); + + /* Calculate bytes per second */ + throughput = USEC_PER_SEC; + do_div(throughput, latency); + throughput *= aggregate_size; + gb_loopback_update_stats(&gb->throughput, throughput); } -static void gb_loopback_latency_update(struct gb_loopback *gb, +static void gb_loopback_calculate_stats(struct gb_loopback *gb, struct timeval *tlat) { u32 lat; u64 tmp; - tmp = timeval_to_ns(tlat); - do_div(tmp, NSEC_PER_MSEC); + /* Express latency in terms of microseconds */ + tmp = gb->elapsed_nsecs; + do_div(tmp, NSEC_PER_USEC); lat = tmp; - if (gb->latency.min > lat) - gb->latency.min = lat; - if (gb->latency.max < lat) - gb->latency.max = lat; - gb->latency.sum += lat; - gb->latency.count++; - gb_loopback_update_stats(&gb->latency, gb->elapsed_nsecs); + /* Log latency stastic */ + gb_loopback_update_stats(&gb->latency, lat); + + /* Log throughput and frequency using latency as benchmark */ + gb_loopback_throughput_update(gb, lat); + gb_loopback_frequency_update(gb, lat); } static int gb_loopback_fn(void *data) @@ -396,6 +399,14 @@ static int gb_loopback_fn(void *data) msleep(1000); continue; } + if (gb->iteration_max) { + if (gb->iteration_count < gb->iteration_max) { + gb->iteration_count++; + } else { + gb->type = 0; + continue; + } + } if (gb->ts.tv_usec == 0 && gb->ts.tv_sec == 0) do_gettimeofday(&gb->ts); if (gb->type == GB_LOOPBACK_TYPE_PING) @@ -409,11 +420,8 @@ static int gb_loopback_fn(void *data) do_gettimeofday(&gb->te); gb->elapsed_nsecs = timeval_to_ns(&gb->te) - timeval_to_ns(&gb->ts); - gb_loopback_freq_update(gb); - gb_loopback_throughput_update(gb); - gb_loopback_latency_update(gb, &tlat); - if (gb->elapsed_nsecs >= NSEC_PER_SEC) - gb->ts = gb->te; + gb_loopback_calculate_stats(gb, &tlat); + gb->ts = gb->te; if (gb->ms_wait) msleep(gb->ms_wait); -- cgit v0.10.2 From e140c75ed9f6897c682e7ac321ef64948f005e64 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 21 Jul 2015 23:50:09 +0100 Subject: greybus: loopback: add commentary to sysfs variables Add some missing comments. Add a TODO to look at doing iteration_count with KOBJ_CHANGE event instead of having user-space poll the value reported in iteration_count to determine when a test set is complete. Signed-off-by: Bryan O'Donoghue Reviewed-by: Patrick Titiano Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 6597394..cc19f1b 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -137,8 +137,11 @@ gb_loopback_stats_attrs(latency); gb_loopback_stats_attrs(frequency); /* Quantity of data sent and received on this cport */ gb_loopback_stats_attrs(throughput); +/* Number of errors encountered during loop */ gb_loopback_ro_attr(error, d); +/* The current index of the for (i = 0; i < iteration_max; i++) loop */ gb_loopback_ro_attr(iteration_count, u); +/* TODO iteration_count might be better with the KOBJ_CHANGE event */ /* * Type of loopback message to send based on protocol type definitions -- cgit v0.10.2 From 583cbf50e0a4c8918811f245860922353420a378 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 21 Jul 2015 23:50:10 +0100 Subject: greybus: loopback: rename frequency to requests The name frequency does not adequately describe the data-point tracking the number of greybus operations performed in a second by the loopback code. Firmware team is moving towards calling this variable requests-per-second or similar. This patch renames to keep the namespace consistent. Signed-off-by: Bryan O'Donoghue Reviewed-by: Patrick Titiano Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index cc19f1b..50eacd1 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -41,7 +41,7 @@ struct gb_loopback { struct gb_loopback_stats latency; struct gb_loopback_stats throughput; - struct gb_loopback_stats frequency; + struct gb_loopback_stats requests_per_second; struct timeval ts; struct timeval te; u64 elapsed_nsecs; @@ -133,8 +133,8 @@ static void gb_loopback_check_attr(struct gb_loopback *gb) /* Time to send and receive one message */ gb_loopback_stats_attrs(latency); -/* Number of packet sent per second on this cport */ -gb_loopback_stats_attrs(frequency); +/* Number of requests sent per second on this cport */ +gb_loopback_stats_attrs(requests_per_second); /* Quantity of data sent and received on this cport */ gb_loopback_stats_attrs(throughput); /* Number of errors encountered during loop */ @@ -166,7 +166,7 @@ gb_loopback_attr(iteration_max, u); static struct attribute *loopback_attrs[] = { dev_stats_attrs(latency), - dev_stats_attrs(frequency), + dev_stats_attrs(requests_per_second), dev_stats_attrs(throughput), &dev_attr_type.attr, &dev_attr_size.attr, @@ -320,7 +320,8 @@ static void gb_loopback_reset_stats(struct gb_loopback *gb) }; memcpy(&gb->latency, &reset, sizeof(struct gb_loopback_stats)); memcpy(&gb->throughput, &reset, sizeof(struct gb_loopback_stats)); - memcpy(&gb->frequency, &reset, sizeof(struct gb_loopback_stats)); + memcpy(&gb->requests_per_second, &reset, + sizeof(struct gb_loopback_stats)); memset(&gb->ts, 0, sizeof(struct timeval)); } @@ -336,12 +337,12 @@ static void gb_loopback_update_stats(struct gb_loopback_stats *stats, u64 val) do_div(stats->avg, stats->count); } -static void gb_loopback_frequency_update(struct gb_loopback *gb, u32 latency) +static void gb_loopback_requests_update(struct gb_loopback *gb, u32 latency) { - u32 freq = USEC_PER_SEC; + u32 req = USEC_PER_SEC; - do_div(freq, latency); - gb_loopback_update_stats(&gb->frequency, freq); + do_div(req, latency); + gb_loopback_update_stats(&gb->requests_per_second, req); } static void gb_loopback_throughput_update(struct gb_loopback *gb, u32 latency) @@ -386,9 +387,9 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb, /* Log latency stastic */ gb_loopback_update_stats(&gb->latency, lat); - /* Log throughput and frequency using latency as benchmark */ + /* Log throughput and requests using latency as benchmark */ gb_loopback_throughput_update(gb, lat); - gb_loopback_frequency_update(gb, lat); + gb_loopback_requests_update(gb, lat); } static int gb_loopback_fn(void *data) -- cgit v0.10.2 From b4bd734ea60c4fd5a79c0e7fff4940686ff3cbc8 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 22 Jul 2015 17:49:17 +0200 Subject: greybus: operation: fix operation ordering Make the operation work queue single threaded. The operation work queue was meant to be single threaded, but due to a missing flag instead allowed one active task per CPU, something which could lead to requests being processed out of order on SMP systems. Signed-off-by: Johan Hovold Tested-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index f2d12e8..e98fc65 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -1043,7 +1043,8 @@ int __init gb_operation_init(void) if (!gb_operation_cache) goto err_destroy_message_cache; - gb_operation_workqueue = alloc_workqueue("greybus_operation", 0, 1); + gb_operation_workqueue = alloc_workqueue("greybus_operation", + WQ_UNBOUND, 1); if (!gb_operation_workqueue) goto err_operation; -- cgit v0.10.2 From a4e08469ebd913e8145b8ab3ad0b40cfdd451240 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 22 Jul 2015 17:49:18 +0200 Subject: greybus: operation: clean up greybus_message_sent Add connection variable to greybus_message_sent. This will be put to more use by a follow-up up patch. Signed-off-by: Johan Hovold Tested-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index e98fc65..6b87bcd 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -778,7 +778,8 @@ err_put: void greybus_message_sent(struct greybus_host_device *hd, struct gb_message *message, int status) { - struct gb_operation *operation; + struct gb_operation *operation = message->operation; + struct gb_connection *connection = operation->connection; /* * If the message was a response, we just need to drop our @@ -790,10 +791,9 @@ void greybus_message_sent(struct greybus_host_device *hd, * attempting to send it, record that as the result of * the operation and schedule its completion. */ - operation = message->operation; if (message == operation->response) { if (status) { - dev_err(&operation->connection->dev, + dev_err(&connection->dev, "error sending response: %d\n", status); } gb_operation_put_active(operation); -- cgit v0.10.2 From 4e2b1e46abf4eef013ab7297a215e21d3c22004e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 22 Jul 2015 17:49:19 +0200 Subject: greybus: connection: fix connection initialisation Make sure connection is fully initialised before registering the connection device and adding it to the host-device and bundle lists. Signed-off-by: Johan Hovold Tested-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index feb6e49..4663397 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -183,6 +183,10 @@ gb_connection_create_range(struct greybus_host_device *hd, connection->bundle = bundle; connection->state = GB_CONNECTION_STATE_DISABLED; + atomic_set(&connection->op_cycle, 0); + spin_lock_init(&connection->lock); + INIT_LIST_HEAD(&connection->operations); + connection->dev.parent = parent; connection->dev.bus = &greybus_bus_type; connection->dev.type = &greybus_connection_type; @@ -215,10 +219,6 @@ gb_connection_create_range(struct greybus_host_device *hd, spin_unlock_irq(&gb_connections_lock); - atomic_set(&connection->op_cycle, 0); - spin_lock_init(&connection->lock); - INIT_LIST_HEAD(&connection->operations); - /* XXX Will have to establish connections to get version */ gb_connection_bind_protocol(connection); if (!connection->protocol) -- cgit v0.10.2 From 155b9f175e2c4b36bf433a1b58e90319ea890de8 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 23 Jul 2015 10:30:47 +0530 Subject: greybus: svc: Fix build warning on 64bit systems MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix below warnings that only generate for a 64 bit system: greybus/svc.c:202:16: warning: format ‘%d’ expects argument of type ‘int’, but argument 4 has type ‘size_t {aka long unsigned int}’ [-Wformat=] dev_err(dev, "%s: Illegal size of hello request (%d %d)\n", ^ greybus/svc.c:202:16: warning: format ‘%d’ expects argument of type ‘int’, but argument 5 has type ‘long unsigned int’ [-Wformat=] Fixes: 9cbe73e0cf45 ("svc: Implement SVC requests") Reported-by: Greg KH Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index c9bbdc0..ebd282d 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -199,7 +199,7 @@ static int gb_svc_hello(struct gb_operation *op) * request, use that to create an endo. */ if (op->request->payload_size != sizeof(*hello_request)) { - dev_err(dev, "%s: Illegal size of hello request (%d %d)\n", + dev_err(dev, "%s: Illegal size of hello request (%zu %zu)\n", __func__, op->request->payload_size, sizeof(*hello_request)); return -EINVAL; -- cgit v0.10.2 From 2975617421f843cac23eeb573a31d541f2aef9cf Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 22 Jul 2015 18:21:04 -0700 Subject: greybus: connection: prevent oops for protocol_id sysfs file If we don't have a protocol assigned to a connection, don't oops when trying to read the "protocol_id" sysfs file. Fixes Jira SW-968. Reported-by: Alexandre Bailon Signed-off-by: Greg Kroah-Hartman Reviewed-by: Viresh Kumar diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 4663397..cac04dd 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -80,7 +80,10 @@ protocol_id_show(struct device *dev, struct device_attribute *attr, char *buf) { struct gb_connection *connection = to_gb_connection(dev); - return sprintf(buf, "%d\n", connection->protocol->id); + if (connection->protocol) + return sprintf(buf, "%d\n", connection->protocol->id); + else + return -EINVAL; } static DEVICE_ATTR_RO(protocol_id); -- cgit v0.10.2 From 7c63a827d088363d89883a3b24af9bd2a6926924 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 23 Jul 2015 10:50:00 +0200 Subject: greybus: connection: clean up connection creation Add variable for the host cport id rather than overload retval. Remove redundant automatic variable for the id map. Tested-by: Rui Miguel Silva Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index cac04dd..1820676 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -152,6 +152,7 @@ gb_connection_create_range(struct greybus_host_device *hd, { struct gb_connection *connection; struct ida *id_map = &hd->cport_id_map; + int hd_cport_id; int retval; u8 major = 0; u8 minor = 1; @@ -170,12 +171,12 @@ gb_connection_create_range(struct greybus_host_device *hd, if (!connection) return NULL; - retval = ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL); - if (retval < 0) { + hd_cport_id = ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL); + if (hd_cport_id < 0) { kfree(connection); return NULL; } - connection->hd_cport_id = (u16)retval; + connection->hd_cport_id = hd_cport_id; connection->intf_cport_id = cport_id; connection->hd = hd; @@ -200,8 +201,6 @@ gb_connection_create_range(struct greybus_host_device *hd, retval = device_add(&connection->dev); if (retval) { - struct ida *id_map = &connection->hd->cport_id_map; - ida_simple_remove(id_map, connection->hd_cport_id); connection->hd_cport_id = CPORT_ID_BAD; put_device(&connection->dev); -- cgit v0.10.2 From 10f9fa133a295fa0f2f36c1a481b7e8b82b12891 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 23 Jul 2015 10:50:01 +0200 Subject: greybus: connection: clean up creation error paths Clean up connection-creation error paths. Tested-by: Rui Miguel Silva Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 1820676..555625c 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -167,15 +167,14 @@ gb_connection_create_range(struct greybus_host_device *hd, return NULL; } + hd_cport_id = ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL); + if (hd_cport_id < 0) + return NULL; + connection = kzalloc(sizeof(*connection), GFP_KERNEL); if (!connection) - return NULL; + goto err_remove_ida; - hd_cport_id = ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL); - if (hd_cport_id < 0) { - kfree(connection); - return NULL; - } connection->hd_cport_id = hd_cport_id; connection->intf_cport_id = cport_id; connection->hd = hd; @@ -201,14 +200,13 @@ gb_connection_create_range(struct greybus_host_device *hd, retval = device_add(&connection->dev); if (retval) { - ida_simple_remove(id_map, connection->hd_cport_id); connection->hd_cport_id = CPORT_ID_BAD; put_device(&connection->dev); pr_err("failed to add connection device for cport 0x%04hx\n", cport_id); - return NULL; + goto err_remove_ida; } spin_lock_irq(&gb_connections_lock); @@ -228,6 +226,11 @@ gb_connection_create_range(struct greybus_host_device *hd, "protocol 0x%02hhx handler not found\n", protocol_id); return connection; + +err_remove_ida: + ida_simple_remove(id_map, hd_cport_id); + + return NULL; } struct gb_connection *gb_connection_create(struct gb_bundle *bundle, -- cgit v0.10.2 From 5a5bc354c65d9e5f255f1861212ec5fa4852a891 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 23 Jul 2015 10:50:02 +0200 Subject: greybus: operation: use per-connection work queues Replace the global operation work queue with per-connection work queues. There is no need to keep operations strictly ordered across connections, something which only adds unnecessary latency. Tested-by: Rui Miguel Silva Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 555625c..b88abed 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -7,6 +7,8 @@ * Released under the GPLv2 only. */ +#include + #include "greybus.h" static DEFINE_SPINLOCK(gb_connections_lock); @@ -99,6 +101,7 @@ static void gb_connection_release(struct device *dev) { struct gb_connection *connection = to_gb_connection(dev); + destroy_workqueue(connection->wq); kfree(connection); } @@ -190,6 +193,11 @@ gb_connection_create_range(struct greybus_host_device *hd, spin_lock_init(&connection->lock); INIT_LIST_HEAD(&connection->operations); + connection->wq = alloc_workqueue("%s:%d", WQ_UNBOUND, 1, + dev_name(parent), cport_id); + if (!connection->wq) + goto err_free_connection; + connection->dev.parent = parent; connection->dev.bus = &greybus_bus_type; connection->dev.type = &greybus_connection_type; @@ -227,6 +235,8 @@ gb_connection_create_range(struct greybus_host_device *hd, return connection; +err_free_connection: + kfree(connection); err_remove_ida: ida_simple_remove(id_map, hd_cport_id); diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index d8fbce4..6b40c4a 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -39,6 +39,8 @@ struct gb_connection { enum gb_connection_state state; struct list_head operations; + struct workqueue_struct *wq; + atomic_t op_cycle; void *private; diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 6b87bcd..69218aa 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -19,9 +19,6 @@ static struct kmem_cache *gb_operation_cache; static struct kmem_cache *gb_message_cache; -/* Workqueue to handle Greybus operation completions. */ -static struct workqueue_struct *gb_operation_workqueue; - /* Wait queue for synchronous cancellations. */ static DECLARE_WAIT_QUEUE_HEAD(gb_operation_cancellation_queue); @@ -800,7 +797,7 @@ void greybus_message_sent(struct greybus_host_device *hd, gb_operation_put(operation); } else if (status) { if (gb_operation_result_set(operation, status)) - queue_work(gb_operation_workqueue, &operation->work); + queue_work(connection->wq, &operation->work); } } EXPORT_SYMBOL_GPL(greybus_message_sent); @@ -837,7 +834,7 @@ static void gb_connection_recv_request(struct gb_connection *connection, * request handler returns. */ if (gb_operation_result_set(operation, -EINPROGRESS)) - queue_work(gb_operation_workqueue, &operation->work); + queue_work(connection->wq, &operation->work); } /* @@ -877,7 +874,7 @@ static void gb_connection_recv_response(struct gb_connection *connection, /* The rest will be handled in work queue context */ if (gb_operation_result_set(operation, errno)) { memcpy(message->header, data, size); - queue_work(gb_operation_workqueue, &operation->work); + queue_work(connection->wq, &operation->work); } gb_operation_put(operation); @@ -931,12 +928,14 @@ void gb_connection_recv(struct gb_connection *connection, */ void gb_operation_cancel(struct gb_operation *operation, int errno) { + struct gb_connection *connection = operation->connection; + if (WARN_ON(gb_operation_is_incoming(operation))) return; if (gb_operation_result_set(operation, errno)) { gb_message_cancel(operation->request); - queue_work(gb_operation_workqueue, &operation->work); + queue_work(connection->wq, &operation->work); } atomic_inc(&operation->waiters); @@ -1043,15 +1042,8 @@ int __init gb_operation_init(void) if (!gb_operation_cache) goto err_destroy_message_cache; - gb_operation_workqueue = alloc_workqueue("greybus_operation", - WQ_UNBOUND, 1); - if (!gb_operation_workqueue) - goto err_operation; - return 0; -err_operation: - kmem_cache_destroy(gb_operation_cache); - gb_operation_cache = NULL; + err_destroy_message_cache: kmem_cache_destroy(gb_message_cache); gb_message_cache = NULL; @@ -1061,8 +1053,6 @@ err_destroy_message_cache: void gb_operation_exit(void) { - destroy_workqueue(gb_operation_workqueue); - gb_operation_workqueue = NULL; kmem_cache_destroy(gb_operation_cache); gb_operation_cache = NULL; kmem_cache_destroy(gb_message_cache); -- cgit v0.10.2 From 701615f82f29d0cce28a397267f847de3ee93b6e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 23 Jul 2015 10:50:03 +0200 Subject: greybus: operation: add completion work queue Add dedicated bound work queue for operation completions and use the connection work queues for incoming requests only. There is no need to keep responses ordered internally or with respect to requests. Instead allow operations to complete as soon as possible when a response arrives (or the operation is cancelled). Note that this also allows synchronous requests to be submitted from request handlers as responses will no longer be blocked on the same single-threaded work queue. Similarly, operations can now also be cancelled from a request handler. Tested-by: Rui Miguel Silva Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 69218aa..4e9c4a8 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -19,6 +19,9 @@ static struct kmem_cache *gb_operation_cache; static struct kmem_cache *gb_message_cache; +/* Workqueue to handle Greybus operation completions. */ +static struct workqueue_struct *gb_operation_completion_wq; + /* Wait queue for synchronous cancellations. */ static DECLARE_WAIT_QUEUE_HEAD(gb_operation_cancellation_queue); @@ -796,8 +799,10 @@ void greybus_message_sent(struct greybus_host_device *hd, gb_operation_put_active(operation); gb_operation_put(operation); } else if (status) { - if (gb_operation_result_set(operation, status)) - queue_work(connection->wq, &operation->work); + if (gb_operation_result_set(operation, status)) { + queue_work(gb_operation_completion_wq, + &operation->work); + } } } EXPORT_SYMBOL_GPL(greybus_message_sent); @@ -874,7 +879,7 @@ static void gb_connection_recv_response(struct gb_connection *connection, /* The rest will be handled in work queue context */ if (gb_operation_result_set(operation, errno)) { memcpy(message->header, data, size); - queue_work(connection->wq, &operation->work); + queue_work(gb_operation_completion_wq, &operation->work); } gb_operation_put(operation); @@ -928,14 +933,12 @@ void gb_connection_recv(struct gb_connection *connection, */ void gb_operation_cancel(struct gb_operation *operation, int errno) { - struct gb_connection *connection = operation->connection; - if (WARN_ON(gb_operation_is_incoming(operation))) return; if (gb_operation_result_set(operation, errno)) { gb_message_cancel(operation->request); - queue_work(connection->wq, &operation->work); + queue_work(gb_operation_completion_wq, &operation->work); } atomic_inc(&operation->waiters); @@ -1042,8 +1045,16 @@ int __init gb_operation_init(void) if (!gb_operation_cache) goto err_destroy_message_cache; + gb_operation_completion_wq = alloc_workqueue("greybus_completion", + 0, 0); + if (!gb_operation_completion_wq) + goto err_destroy_operation_cache; + return 0; +err_destroy_operation_cache: + kmem_cache_destroy(gb_operation_cache); + gb_operation_cache = NULL; err_destroy_message_cache: kmem_cache_destroy(gb_message_cache); gb_message_cache = NULL; @@ -1053,6 +1064,8 @@ err_destroy_message_cache: void gb_operation_exit(void) { + destroy_workqueue(gb_operation_completion_wq); + gb_operation_completion_wq = NULL; kmem_cache_destroy(gb_operation_cache); gb_operation_cache = NULL; kmem_cache_destroy(gb_message_cache); -- cgit v0.10.2 From c2939f41bca86d30388e6fa48e469a4e748b71e2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 22 Jul 2015 11:09:23 -0700 Subject: greybus: loopback: add poll support to the iteration_count sysfs file This adds the ability to poll on "iteration_count" in sysfs and be woken up when it changes, saving some cycles constantly hammering on the file waiting for it to change. Signed-off-by: Greg Kroah-Hartman Tested-by: Bryan O'Donoghue diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 50eacd1..08f0bee 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -141,7 +141,6 @@ gb_loopback_stats_attrs(throughput); gb_loopback_ro_attr(error, d); /* The current index of the for (i = 0; i < iteration_max; i++) loop */ gb_loopback_ro_attr(iteration_count, u); -/* TODO iteration_count might be better with the KOBJ_CHANGE event */ /* * Type of loopback message to send based on protocol type definitions @@ -406,6 +405,8 @@ static int gb_loopback_fn(void *data) if (gb->iteration_max) { if (gb->iteration_count < gb->iteration_max) { gb->iteration_count++; + sysfs_notify(&gb->connection->dev.kobj, NULL, + "iteration_count"); } else { gb->type = 0; continue; -- cgit v0.10.2 From 3dfe8aaaeede22b0601c95cf1a4c2eadcb3851ba Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Fri, 24 Jul 2015 10:02:56 +0100 Subject: greybus: loopback: convert loopback wake/sleep to a waitqueue Current code will incrementally poll for gb->type == 0 and sleep. This type of polling strategy wastes cycles. This patch changes the sleep strategy by introducing a wait-queue which waits for gb->type != 0 or kthread_should_stop() to wake-up and work or to wake-up and terminate. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 08f0bee..2294948 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -31,6 +31,7 @@ struct gb_loopback { u8 version_minor; struct task_struct *task; + wait_queue_head_t wq; int type; u32 size; @@ -113,22 +114,24 @@ static DEVICE_ATTR_RW(field) static void gb_loopback_reset_stats(struct gb_loopback *gb); static void gb_loopback_check_attr(struct gb_loopback *gb) { + if (gb->ms_wait > GB_LOOPBACK_MS_WAIT_MAX) + gb->ms_wait = GB_LOOPBACK_MS_WAIT_MAX; + if (gb->size > gb->size_max) + gb->size = gb->size_max; + gb->error = 0; + gb->iteration_count = 0; + gb_loopback_reset_stats(gb); + switch (gb->type) { case GB_LOOPBACK_TYPE_PING: case GB_LOOPBACK_TYPE_TRANSFER: case GB_LOOPBACK_TYPE_SINK: + wake_up(&gb->wq); break; default: gb->type = 0; break; } - if (gb->ms_wait > GB_LOOPBACK_MS_WAIT_MAX) - gb->ms_wait = GB_LOOPBACK_MS_WAIT_MAX; - if (gb->size > gb->size_max) - gb->size = gb->size_max; - gb->error = 0; - gb->iteration_count = 0; - gb_loopback_reset_stats(gb); } /* Time to send and receive one message */ @@ -397,11 +400,12 @@ static int gb_loopback_fn(void *data) struct timeval tlat = {0, 0}; struct gb_loopback *gb = (struct gb_loopback *)data; - while (!kthread_should_stop()) { - if (!gb->type) { - msleep(1000); - continue; - } + while (1) { + if (!gb->type) + wait_event_interruptible(gb->wq, gb->type || + kthread_should_stop()); + if (kthread_should_stop()) + break; if (gb->iteration_max) { if (gb->iteration_count < gb->iteration_max) { gb->iteration_count++; @@ -429,7 +433,6 @@ static int gb_loopback_fn(void *data) gb->ts = gb->te; if (gb->ms_wait) msleep(gb->ms_wait); - } return 0; } @@ -463,6 +466,7 @@ static int gb_loopback_connection_init(struct gb_connection *connection) gb->size_max -= sizeof(struct gb_loopback_transfer_request); gb_loopback_reset_stats(gb); + init_waitqueue_head(&gb->wq); gb->task = kthread_run(gb_loopback_fn, gb, "gb_loopback"); if (IS_ERR(gb->task)) { retval = PTR_ERR(gb->task); -- cgit v0.10.2 From 67c93ae6f544a0953d1159ffcc0dd14bea77fc53 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 24 Jul 2015 15:32:19 +0530 Subject: greybus: svc: fully initialize the partially initialized connection SVC hello message is received now and we should fully initialize the partially initialized connection. This can be done by removing and re-adding the device corresponding to the connection. Signed-off-by: Viresh Kumar Tested-by: Perry Hung Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index b88abed..0cd716d 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -111,6 +111,30 @@ struct device_type greybus_connection_type = { }; +int svc_update_connection(struct gb_interface *intf, + struct gb_connection *connection) +{ + struct gb_bundle *bundle; + + bundle = gb_bundle_create(intf, GB_SVC_BUNDLE_ID, GREYBUS_CLASS_SVC); + if (!bundle) + return -EINVAL; + + device_del(&connection->dev); + connection->bundle = bundle; + connection->dev.parent = &bundle->dev; + dev_set_name(&connection->dev, "%s:%d", dev_name(&bundle->dev), + GB_SVC_CPORT_ID); + + WARN_ON(device_add(&connection->dev)); + + spin_lock_irq(&gb_connections_lock); + list_add(&connection->bundle_links, &bundle->connections); + spin_unlock_irq(&gb_connections_lock); + + return 0; +} + void gb_connection_bind_protocol(struct gb_connection *connection) { struct gb_protocol *protocol; diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 6b40c4a..f02b9d9 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -47,6 +47,8 @@ struct gb_connection { }; #define to_gb_connection(d) container_of(d, struct gb_connection, dev) +int svc_update_connection(struct gb_interface *intf, + struct gb_connection *connection); struct gb_connection *gb_connection_create(struct gb_bundle *bundle, u16 cport_id, u8 protocol_id); struct gb_connection *gb_connection_create_range(struct greybus_host_device *hd, diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index ebd282d..28a4ca9 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -43,7 +43,6 @@ gb_ap_interface_create(struct greybus_host_device *hd, { struct gb_interface *intf; struct device *dev = &hd->endo->dev; - int ret; intf = gb_interface_create(hd, interface_id); if (!intf) { @@ -53,20 +52,7 @@ gb_ap_interface_create(struct greybus_host_device *hd, } intf->device_id = GB_DEVICE_ID_AP; - - /* - * XXX: Disable the initial svc connection here, but don't destroy it - * yet. We do need to send a response of 'svc-hello message' on that. - */ - - /* Establish new control CPort connection */ - ret = gb_create_bundle_connection(intf, GREYBUS_CLASS_SVC); - if (ret) { - dev_err(&intf->dev, "%s: Failed to create svc connection (%d %d)\n", - __func__, interface_id, ret); - gb_interface_destroy(intf); - intf = NULL; - } + svc_update_connection(intf, connection); return intf; } -- cgit v0.10.2 From dcd05008e491252280c178d9d5300a885b4f4548 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 24 Jul 2015 15:32:20 +0530 Subject: greybus: svc: connection is created only once now We no longer create a fresh connection on receiving svc-hello message, but rather update the initial one. Update 'initial_svc_connection' after the connection is fully initialized. Look for the partially initialized connection while removing hd, as hd might be removed before getting svc-hello requests from svc. Also update gb_svc_connection_init() to initialize id_map on the first (and the only) call to connection-init function. We also can't update connection->bundle->intf->svc, as its a bundle-less connection. Lets stop updating intf->svc as its not really used. Signed-off-by: Viresh Kumar Tested-by: Perry Hung Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 3b1be2d..bbfae4a 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -236,6 +236,12 @@ void greybus_remove_hd(struct greybus_host_device *hd) gb_interfaces_remove(hd); gb_endo_remove(hd->endo); + /* Is the SVC still using the partially uninitialized connection ? */ + if (hd->initial_svc_connection) { + gb_connection_exit(hd->initial_svc_connection); + gb_connection_destroy(hd->initial_svc_connection); + } + /* * Make sure there are no leftovers that can potentially corrupt sysfs. */ diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 28a4ca9..969c389 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -54,6 +54,9 @@ gb_ap_interface_create(struct greybus_host_device *hd, intf->device_id = GB_DEVICE_ID_AP; svc_update_connection(intf, connection); + /* Its no longer a partially initialized connection */ + hd->initial_svc_connection = NULL; + return intf; } @@ -384,24 +387,11 @@ static int gb_svc_connection_init(struct gb_connection *connection) svc->connection = connection; connection->private = svc; - /* - * SVC connection is created twice: - * - before the interface-id of the AP and the endo type is known. - * - after receiving endo type and interface-id of the AP from the SVC. - * - * We should do light-weight initialization for the first case. - */ - if (!connection->bundle) { - WARN_ON(connection->hd->initial_svc_connection); - connection->hd->initial_svc_connection = connection; - return 0; - } + WARN_ON(connection->hd->initial_svc_connection); + connection->hd->initial_svc_connection = connection; ida_init(&greybus_svc_device_id_map); - /* Set interface's svc connection */ - connection->bundle->intf->svc = svc; - return 0; } @@ -409,14 +399,6 @@ static void gb_svc_connection_exit(struct gb_connection *connection) { struct gb_svc *svc = connection->private; - if (connection->hd->initial_svc_connection == connection) { - connection->hd->initial_svc_connection = NULL; - } else { - if (WARN_ON(connection->bundle->intf->svc != svc)) - return; - connection->bundle->intf->svc = NULL; - } - connection->private = NULL; kfree(svc); } -- cgit v0.10.2 From b45864d40ca6f453a708d1e74c2108424ac15bdb Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 24 Jul 2015 15:32:21 +0530 Subject: greybus: svc: remove interface->svc pointer Its not updated/used anymore, remove it. Also move back the struct gb_svc to svc.c as its not referenced by external users anymore. Signed-off-by: Viresh Kumar Tested-by: Perry Hung Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 9a9260c..fc2d29f 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -14,7 +14,6 @@ struct gb_interface { struct device dev; struct gb_control *control; - struct gb_svc *svc; struct list_head bundles; struct list_head links; /* greybus_host_device->interfaces */ diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 969c389..5f2b2b4 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -9,6 +9,12 @@ #include "greybus.h" +struct gb_svc { + struct gb_connection *connection; + u8 version_major; + u8 version_minor; +}; + static struct ida greybus_svc_device_id_map; /* diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index 6649780..ee39479 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -10,12 +10,7 @@ #ifndef __SVC_H #define __SVC_H -struct gb_svc { - struct gb_connection *connection; - u8 version_major; - u8 version_minor; -}; - +struct gb_svc; int gb_svc_intf_device_id(struct gb_svc *svc, u8 intf_id, u8 device_id); int gb_svc_intf_reset(struct gb_svc *svc, u8 intf_id); -- cgit v0.10.2 From 23119de4e69c8a96f10de4bcc62d3751e7d77eb4 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 24 Jul 2015 15:32:22 +0530 Subject: greybus: interface: localize gb_interface_destroy() Its not referenced by svc or any other code anymore, lets stop exposing it to rest of the files. Signed-off-by: Viresh Kumar Tested-by: Perry Hung Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index fc2d29f..558e6db 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -52,7 +52,6 @@ struct gb_interface *gb_interface_find(struct greybus_host_device *hd, struct gb_interface *gb_interface_create(struct greybus_host_device *hd, u8 interface_id); int gb_interface_init(struct gb_interface *intf, u8 device_id); -void gb_interface_destroy(struct gb_interface *intf); void gb_interface_remove(struct greybus_host_device *hd, u8 interface_id); void gb_interfaces_remove(struct greybus_host_device *hd); -- cgit v0.10.2 From e619e8505b66229fdf2735ac00891d340111b0a8 Mon Sep 17 00:00:00 2001 From: Perry Hung Date: Fri, 24 Jul 2015 19:02:29 -0400 Subject: greybus: battery: fix panic on operation error If an operation times out or otherwise returns an error, val->intval should not be set and an error-code should be returned. Fixes a panic on unload while receiving -ENOTCONN. Signed-off-by: Perry Hung Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery.c b/drivers/staging/greybus/battery.c index aad1749..e666239 100644 --- a/drivers/staging/greybus/battery.c +++ b/drivers/staging/greybus/battery.c @@ -281,7 +281,7 @@ static int get_property(struct power_supply *b, return -EINVAL; } - return 0; + return (val->intval < 0) ? val->intval : 0; } // FIXME - verify this list, odds are some can be removed and others added. -- cgit v0.10.2 From 52fa38327b39f1d307447023a8eea1f7b7ca0039 Mon Sep 17 00:00:00 2001 From: Perry Hung Date: Fri, 24 Jul 2015 19:02:30 -0400 Subject: greybus: connection: silence warning on unbound protocols If a protocol was not successfully created, we can't drop the refcount on it. This might happen for example if the connection fails to bind a protocol. Silences a warning on cleanup. Signed-off-by: Perry Hung Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 0cd716d..c57deb2 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -319,7 +319,8 @@ void gb_connection_destroy(struct gb_connection *connection) list_del(&connection->hd_links); spin_unlock_irq(&gb_connections_lock); - gb_protocol_put(connection->protocol); + if (connection->protocol) + gb_protocol_put(connection->protocol); connection->protocol = NULL; id_map = &connection->hd->cport_id_map; diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index 6aebbbd..06b4841 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -196,9 +196,6 @@ void gb_protocol_put(struct gb_protocol *protocol) u8 minor; u8 protocol_count; - if (WARN_ON(!protocol)) - return; - id = protocol->id; major = protocol->major; minor = protocol->minor; -- cgit v0.10.2 From 77c461fa861ac813143510caaa712bfb93d15b63 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 24 Jul 2015 18:42:03 +0530 Subject: greybus: connection: compare hd_cport_id for matching SVC protocol SVC protocol isn't per interface, but per entire entire endo. And so svc cport id must be matched against hd_cport_id, not per-interface cport id. Fixes: 82edfac17e5f ("connection: don't send connected/disconnected events for SVC connection") Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index c57deb2..b32da8a 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -344,7 +344,8 @@ int gb_connection_init(struct gb_connection *connection) * Inform Interface about Active CPorts. We don't need to do this * operation for control cport. */ - if (cport_id != GB_CONTROL_CPORT_ID && cport_id != GB_SVC_CPORT_ID) { + if (cport_id != GB_CONTROL_CPORT_ID && + connection->hd_cport_id != GB_SVC_CPORT_ID) { struct gb_control *control = connection->bundle->intf->control; ret = gb_control_connected_operation(control, cport_id); @@ -396,7 +397,8 @@ void gb_connection_exit(struct gb_connection *connection) * Inform Interface about In-active CPorts. We don't need to do this * operation for control cport. */ - if (cport_id != GB_CONTROL_CPORT_ID && cport_id != GB_SVC_CPORT_ID) { + if (cport_id != GB_CONTROL_CPORT_ID && + connection->hd_cport_id != GB_SVC_CPORT_ID) { struct gb_control *control = connection->bundle->intf->control; int ret; -- cgit v0.10.2 From 8aa013526e62639e4e1dd1bec75a84fe27ab7432 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 24 Jul 2015 15:32:23 +0530 Subject: greybus: es1/2: Lets start using svc protocol All bits and pieces are in place now. Lets start using svc protocol instead of stuff present in ap.c. Signed-off-by: Viresh Kumar Tested-by: Perry Hung Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 0cb7a3c..7d764a5 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -615,8 +615,6 @@ static int ap_probe(struct usb_interface *interface, bool bulk_out_found = false; int retval = -ENOMEM; int i; - u16 endo_id = 0x4755; // FIXME - get endo "ID" from the SVC - u8 ap_intf_id = 0x01; // FIXME - get endo "ID" from the SVC u8 svc_interval = 0; /* We need to fit a CPort ID in one byte of a message header */ @@ -718,16 +716,11 @@ static int ap_probe(struct usb_interface *interface, es1->cport_out_urb_busy[i] = false; /* just to be anal */ } - /* - * XXX Soon this will be initiated later, with a combination - * XXX of a Control protocol probe operation and a - * XXX subsequent Control protocol connected operation for - * XXX the SVC connection. At that point we know we're - * XXX properly connected to an Endo. - */ - retval = greybus_endo_setup(hd, endo_id, ap_intf_id); - if (retval) + /* Initialize AP's greybus interface */ + if (!gb_ap_svc_connection_create(hd)) { + retval = -EINVAL; goto error; + } /* Start up our svc urb, which allows events to start flowing */ retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 323721a..7621e95 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -715,8 +715,6 @@ static int ap_probe(struct usb_interface *interface, int bulk_out = 0; int retval = -ENOMEM; int i; - u16 endo_id = 0x4755; // FIXME - get endo "ID" from the SVC - u8 ap_intf_id = 0x01; // FIXME - get endo "ID" from the SVC u8 svc_interval = 0; /* We need to fit a CPort ID in one byte of a message header */ @@ -822,16 +820,11 @@ static int ap_probe(struct usb_interface *interface, es1->cport_out_urb_busy[i] = false; /* just to be anal */ } - /* - * XXX Soon this will be initiated later, with a combination - * XXX of a Control protocol probe operation and a - * XXX subsequent Control protocol connected operation for - * XXX the SVC connection. At that point we know we're - * XXX properly connected to an Endo. - */ - retval = greybus_endo_setup(hd, endo_id, ap_intf_id); - if (retval) + /* Initialize AP's greybus interface */ + if (!gb_ap_svc_connection_create(hd)) { + retval = -EINVAL; goto error; + } /* Start up our svc urb, which allows events to start flowing */ retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); -- cgit v0.10.2 From 8c116e8d8e99ba6220f1a2cf8bc40b8d34d583d3 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 24 Jul 2015 15:32:24 +0530 Subject: greybus: Switch to Cport 0 for svc and control protocol Initially we fixed it to Cport 2, but its changed to Cport 0 now. Lets switch that in code as well. Signed-off-by: Viresh Kumar Tested-by: Perry Hung Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 61fe9dc..9708e93 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -64,9 +64,9 @@ * CONTROL and SVC protocols for communication between AP and SVC. */ #define GB_SVC_BUNDLE_ID 0 -#define GB_SVC_CPORT_ID 2 +#define GB_SVC_CPORT_ID 0 #define GB_CONTROL_BUNDLE_ID 0 -#define GB_CONTROL_CPORT_ID 2 +#define GB_CONTROL_CPORT_ID 0 /* Control Protocol */ -- cgit v0.10.2 From 972e84a8dc3c1fdcff5e423866559c87354cec68 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 24 Jul 2015 16:47:07 -0700 Subject: greybus: es1: remove svc endpoint message handling We have switched over to use the "new" svc messages, no more need to have a special USB endpoint to handle them, they come through the normal CPort messages. Based on a patch from Viresh. Tested-by: Viresh Kumar Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 7d764a5..82a7c67 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -18,7 +18,6 @@ #include "kernel_ver.h" /* Memory sizes for the buffers sent to/from the ES1 controller */ -#define ES1_SVC_MSG_SIZE (sizeof(struct svc_msg) + SZ_64K) #define ES1_GBUF_MSG_SIZE_MAX 2048 static const struct usb_device_id id_table[] = { @@ -58,11 +57,8 @@ static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); * @usb_intf: pointer to the USB interface we are bound to. * @hd: pointer to our greybus_host_device structure * @control_endpoint: endpoint to send data to SVC - * @svc_endpoint: endpoint for SVC data in * @cport_in_endpoint: bulk in endpoint for CPort data * @cport-out_endpoint: bulk out endpoint for CPort data - * @svc_buffer: buffer for SVC messages coming in on @svc_endpoint - * @svc_urb: urb for SVC messages coming in on @svc_endpoint * @cport_in_urb: array of urbs for the CPort in messages * @cport_in_buffer: array of buffers for the @cport_in_urb urbs * @cport_out_urb: array of urbs for the CPort out messages @@ -78,13 +74,9 @@ struct es1_ap_dev { struct greybus_host_device *hd; __u8 control_endpoint; - __u8 svc_endpoint; __u8 cport_in_endpoint; __u8 cport_out_endpoint; - u8 *svc_buffer; - struct urb *svc_urb; - struct urb *cport_in_urb[NUM_CPORT_IN_URB]; u8 *cport_in_buffer[NUM_CPORT_IN_URB]; struct urb *cport_out_urb[NUM_CPORT_OUT_URB]; @@ -367,12 +359,6 @@ static void ap_disconnect(struct usb_interface *interface) es1->cport_in_buffer[i] = NULL; } - usb_kill_urb(es1->svc_urb); - usb_free_urb(es1->svc_urb); - es1->svc_urb = NULL; - kfree(es1->svc_buffer); - es1->svc_buffer = NULL; - usb_set_intfdata(interface, NULL); udev = es1->usb_dev; greybus_remove_hd(es1->hd); @@ -380,33 +366,6 @@ static void ap_disconnect(struct usb_interface *interface) usb_put_dev(udev); } -/* Callback for when we get a SVC message */ -static void svc_in_callback(struct urb *urb) -{ - struct greybus_host_device *hd = urb->context; - struct device *dev = &urb->dev->dev; - int status = check_urb_status(urb); - int retval; - - if (status) { - if ((status == -EAGAIN) || (status == -EPROTO)) - goto exit; - dev_err(dev, "urb svc in error %d (dropped)\n", status); - return; - } - - /* We have a message, create a new message structure, add it to the - * list, and wake up our thread that will process the messages. - */ - greybus_svc_in(hd, urb->transfer_buffer, urb->actual_length); - -exit: - /* resubmit the urb to get more messages */ - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - dev_err(dev, "Can not submit urb for AP data: %d\n", retval); -} - static void cport_in_callback(struct urb *urb) { struct greybus_host_device *hd = urb->context; @@ -610,12 +569,10 @@ static int ap_probe(struct usb_interface *interface, struct usb_device *udev; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; - bool int_in_found = false; bool bulk_in_found = false; bool bulk_out_found = false; int retval = -ENOMEM; int i; - u8 svc_interval = 0; /* We need to fit a CPort ID in one byte of a message header */ BUILD_BUG_ON(CPORT_ID_MAX > U8_MAX); @@ -644,11 +601,7 @@ static int ap_probe(struct usb_interface *interface, for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; - if (usb_endpoint_is_int_in(endpoint)) { - es1->svc_endpoint = endpoint->bEndpointAddress; - svc_interval = endpoint->bInterval; - int_in_found = true; - } else if (usb_endpoint_is_bulk_in(endpoint)) { + if (usb_endpoint_is_bulk_in(endpoint)) { es1->cport_in_endpoint = endpoint->bEndpointAddress; bulk_in_found = true; } else if (usb_endpoint_is_bulk_out(endpoint)) { @@ -660,27 +613,12 @@ static int ap_probe(struct usb_interface *interface, endpoint->bEndpointAddress); } } - if ((int_in_found == false) || - (bulk_in_found == false) || + if ((bulk_in_found == false) || (bulk_out_found == false)) { dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n"); goto error; } - /* Create our buffer and URB to get SVC messages, and start it up */ - es1->svc_buffer = kmalloc(ES1_SVC_MSG_SIZE, GFP_KERNEL); - if (!es1->svc_buffer) - goto error; - - es1->svc_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!es1->svc_urb) - goto error; - - usb_fill_int_urb(es1->svc_urb, udev, - usb_rcvintpipe(udev, es1->svc_endpoint), - es1->svc_buffer, ES1_SVC_MSG_SIZE, svc_in_callback, - hd, svc_interval); - /* Allocate buffers for our cport in messages and start them up */ for (i = 0; i < NUM_CPORT_IN_URB; ++i) { struct urb *urb; @@ -722,11 +660,6 @@ static int ap_probe(struct usb_interface *interface, goto error; } - /* Start up our svc urb, which allows events to start flowing */ - retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); - if (retval) - goto error; - apb1_log_enable_dentry = debugfs_create_file("apb1_log_enable", (S_IWUSR | S_IRUGO), gb_debugfs_get(), es1, -- cgit v0.10.2 From 939799057e69f9691919e987b145d5e009358905 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 24 Jul 2015 17:09:48 -0700 Subject: greybus: es2: remove svc endpoint message handling We have switched over to use the "new" svc messages, no more need to have a special USB endpoint to handle them, they come through the normal CPort messages. Based on a patch from Viresh. Tested-by: Viresh Kumar Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 7621e95..c353ca5 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -18,7 +18,6 @@ #include "kernel_ver.h" /* Memory sizes for the buffers sent to/from the ES1 controller */ -#define ES1_SVC_MSG_SIZE (sizeof(struct svc_msg) + SZ_64K) #define ES1_GBUF_MSG_SIZE_MAX 2048 static const struct usb_device_id id_table[] = { @@ -85,10 +84,7 @@ struct es1_cport_out { * @usb_intf: pointer to the USB interface we are bound to. * @hd: pointer to our greybus_host_device structure * @control_endpoint: endpoint to send data to SVC - * @svc_endpoint: endpoint for SVC data in - * @svc_buffer: buffer for SVC messages coming in on @svc_endpoint - * @svc_urb: urb for SVC messages coming in on @svc_endpoint * @cport_in: endpoint, urbs and buffer for cport in messages * @cport_out: endpoint for for cport out messages * @cport_out_urb: array of urbs for the CPort out messages @@ -104,10 +100,6 @@ struct es1_ap_dev { struct greybus_host_device *hd; __u8 control_endpoint; - __u8 svc_endpoint; - - u8 *svc_buffer; - struct urb *svc_urb; struct es1_cport_in cport_in[NUM_BULKS]; struct es1_cport_out cport_out[NUM_BULKS]; @@ -467,12 +459,6 @@ static void ap_disconnect(struct usb_interface *interface) } } - usb_kill_urb(es1->svc_urb); - usb_free_urb(es1->svc_urb); - es1->svc_urb = NULL; - kfree(es1->svc_buffer); - es1->svc_buffer = NULL; - usb_set_intfdata(interface, NULL); udev = es1->usb_dev; greybus_remove_hd(es1->hd); @@ -480,33 +466,6 @@ static void ap_disconnect(struct usb_interface *interface) usb_put_dev(udev); } -/* Callback for when we get a SVC message */ -static void svc_in_callback(struct urb *urb) -{ - struct greybus_host_device *hd = urb->context; - struct device *dev = &urb->dev->dev; - int status = check_urb_status(urb); - int retval; - - if (status) { - if ((status == -EAGAIN) || (status == -EPROTO)) - goto exit; - dev_err(dev, "urb svc in error %d (dropped)\n", status); - return; - } - - /* We have a message, create a new message structure, add it to the - * list, and wake up our thread that will process the messages. - */ - greybus_svc_in(hd, urb->transfer_buffer, urb->actual_length); - -exit: - /* resubmit the urb to get more messages */ - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - dev_err(dev, "Can not submit urb for AP data: %d\n", retval); -} - static void cport_in_callback(struct urb *urb) { struct greybus_host_device *hd = urb->context; @@ -710,12 +669,10 @@ static int ap_probe(struct usb_interface *interface, struct usb_device *udev; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; - bool int_in_found = false; int bulk_in = 0; int bulk_out = 0; int retval = -ENOMEM; int i; - u8 svc_interval = 0; /* We need to fit a CPort ID in one byte of a message header */ BUILD_BUG_ON(CPORT_ID_MAX > U8_MAX); @@ -744,11 +701,7 @@ static int ap_probe(struct usb_interface *interface, for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; - if (usb_endpoint_is_int_in(endpoint)) { - es1->svc_endpoint = endpoint->bEndpointAddress; - svc_interval = endpoint->bInterval; - int_in_found = true; - } else if (usb_endpoint_is_bulk_in(endpoint)) { + if (usb_endpoint_is_bulk_in(endpoint)) { es1->cport_in[bulk_in++].endpoint = endpoint->bEndpointAddress; } else if (usb_endpoint_is_bulk_out(endpoint)) { @@ -760,27 +713,12 @@ static int ap_probe(struct usb_interface *interface, endpoint->bEndpointAddress); } } - if ((int_in_found == false) || - (bulk_in == 0) || + if ((bulk_in == 0) || (bulk_out == 0)) { dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n"); goto error; } - /* Create our buffer and URB to get SVC messages, and start it up */ - es1->svc_buffer = kmalloc(ES1_SVC_MSG_SIZE, GFP_KERNEL); - if (!es1->svc_buffer) - goto error; - - es1->svc_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!es1->svc_urb) - goto error; - - usb_fill_int_urb(es1->svc_urb, udev, - usb_rcvintpipe(udev, es1->svc_endpoint), - es1->svc_buffer, ES1_SVC_MSG_SIZE, svc_in_callback, - hd, svc_interval); - /* Allocate buffers for our cport in messages and start them up */ for (bulk_in = 0; bulk_in < NUM_BULKS; bulk_in++) { struct es1_cport_in *cport_in = &es1->cport_in[bulk_in]; @@ -826,11 +764,6 @@ static int ap_probe(struct usb_interface *interface, goto error; } - /* Start up our svc urb, which allows events to start flowing */ - retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); - if (retval) - goto error; - apb1_log_enable_dentry = debugfs_create_file("apb1_log_enable", (S_IWUSR | S_IRUGO), gb_debugfs_get(), es1, -- cgit v0.10.2 From 0af7268882755ae8c3807129dfbbdbe836fd0228 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 24 Jul 2015 15:32:26 +0530 Subject: greybus: get rid of old svc-protocol Its not used anymore as we have more sophisticated svc protocol in place, lets get rid of earlier code. Signed-off-by: Viresh Kumar Tested-by: Perry Hung Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 1467c5b..d14bf4d 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -1,6 +1,5 @@ greybus-y := core.o \ debugfs.o \ - ap.o \ manifest.o \ endo.o \ module.o \ diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c deleted file mode 100644 index fc23817..0000000 --- a/drivers/staging/greybus/ap.c +++ /dev/null @@ -1,351 +0,0 @@ -/* - * Greybus "AP" message loop handling - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include "svc_msg.h" -#include "greybus_manifest.h" -#include "greybus.h" - -struct ap_msg { - u8 *data; - size_t size; - struct greybus_host_device *hd; - struct work_struct event; -}; - -static struct workqueue_struct *ap_workqueue; - -static struct svc_msg *svc_msg_alloc(enum svc_function_id id) -{ - struct svc_msg *svc_msg; - - svc_msg = kzalloc((sizeof *svc_msg), GFP_KERNEL); - if (!svc_msg) - return NULL; - - // FIXME - verify we are only sending function IDs we should be - svc_msg->header.function_id = id; - return svc_msg; -} - -static void svc_msg_free(struct svc_msg *svc_msg) -{ - kfree(svc_msg); -} - -static int svc_msg_send(struct svc_msg *svc_msg, struct greybus_host_device *hd) -{ - int retval; - - // FIXME - Do we need to do more than just pass it to the hd and then - // free it? - retval = hd->driver->submit_svc(svc_msg, hd); - - svc_msg_free(svc_msg); - return retval; -} - -static void svc_handshake(struct svc_function_handshake *handshake, - int payload_length, struct greybus_host_device *hd) -{ - struct svc_msg *svc_msg; - - if (payload_length != sizeof(*handshake)) { - dev_err(hd->parent, - "Illegal size of svc handshake message %d\n", - payload_length); - return; - } - - /* A new SVC communication channel, let's verify a supported version */ - if ((handshake->version_major != GREYBUS_VERSION_MAJOR) || - (handshake->version_minor != GREYBUS_VERSION_MINOR)) { - dev_warn(hd->parent, - "received invalid greybus version %u.%u\n", - handshake->version_major, handshake->version_minor); - return; - } - - /* Validate that the handshake came from the SVC */ - if (handshake->handshake_type != SVC_HANDSHAKE_SVC_HELLO) { - /* we don't know what to do with this, log it and return */ - dev_dbg(hd->parent, "received invalid handshake type %d\n", - handshake->handshake_type); - return; - } - - /* Send back a AP_HELLO message */ - svc_msg = svc_msg_alloc(SVC_FUNCTION_HANDSHAKE); - if (!svc_msg) - return; - - svc_msg->header.message_type = SVC_MSG_DATA; - svc_msg->header.payload_length = - cpu_to_le16(sizeof(*handshake)); - svc_msg->handshake.version_major = GREYBUS_VERSION_MAJOR; - svc_msg->handshake.version_minor = GREYBUS_VERSION_MINOR; - svc_msg->handshake.handshake_type = SVC_HANDSHAKE_AP_HELLO; - - (void)svc_msg_send(svc_msg, hd); -} - -static void svc_management(struct svc_function_unipro_management *management, - int payload_length, struct greybus_host_device *hd) -{ - struct gb_interface *intf; - int ret; - - if (payload_length != sizeof(*management)) { - dev_err(hd->parent, - "Illegal size of svc management message %d\n", - payload_length); - return; - } - - switch (management->management_packet_type) { - case SVC_MANAGEMENT_AP_ID: - hd->device_id = management->ap_id.device_id; - break; - case SVC_MANAGEMENT_LINK_UP: - intf = gb_interface_find(hd, management->link_up.interface_id); - if (!intf) { - dev_err(hd->parent, "Interface ID %d not found\n", - management->link_up.interface_id); - return; - } - ret = gb_interface_init(intf, management->link_up.device_id); - if (ret) { - dev_err(hd->parent, - "error %d initializing interface %hhu\n", - ret, management->link_up.interface_id); - return; - } - break; - default: - dev_err(hd->parent, "Unhandled UniPro management message\n"); - } -} - -static void svc_hotplug(struct svc_function_hotplug *hotplug, - int payload_length, struct greybus_host_device *hd) -{ - u8 interface_id = hotplug->interface_id; - - switch (hotplug->hotplug_event) { - case SVC_HOTPLUG_EVENT: - /* Add a new interface to the system */ - if (payload_length != sizeof(*hotplug)) { - dev_err(hd->parent, - "Illegal size of svc hotplug message %d\n", - payload_length); - return; - } - dev_dbg(hd->parent, "interface id %d added\n", interface_id); - gb_interface_create(hd, interface_id); - break; - - case SVC_HOTUNPLUG_EVENT: - /* Remove a interface from the system */ - if (payload_length != sizeof(*hotplug)) { - dev_err(hd->parent, - "Illegal size of svc hotunplug message %d\n", - payload_length); - return; - } - dev_dbg(hd->parent, "interface id %d removed\n", interface_id); - gb_interface_remove(hd, interface_id); - break; - - default: - dev_err(hd->parent, - "Received invalid hotplug message type %d\n", - hotplug->hotplug_event); - break; - } -} - -static void svc_power(struct svc_function_power *power, - int payload_length, struct greybus_host_device *hd) -{ - u8 interface_id = power->interface_id; - - /* - * The AP is only allowed to get a Battery Status message, not a Battery - * Status Request - */ - if (power->power_type != SVC_POWER_BATTERY_STATUS) { - dev_err(hd->parent, "Received invalid power type %d\n", - power->power_type); - return; - } - - /* - * As struct struct svc_function_power_battery_status_request is 0 bytes - * big, we can just check the union of the whole structure to validate - * the size of this message. - */ - if (payload_length != sizeof(*power)) { - dev_err(hd->parent, - "Illegal size of svc power message %d\n", - payload_length); - return; - } - - dev_dbg(hd->parent, "power status for interface id %d is %d\n", - interface_id, power->status.status); - - // FIXME - do something with the power information, like update our - // battery information... -} - -static void svc_epm(struct svc_function_epm *epm, - int payload_length, struct greybus_host_device *hd) -{ - /* What? An AP should not get this message */ - dev_err(hd->parent, "Got an EPM message???\n"); -} - -static void svc_suspend(struct svc_function_suspend *suspend, - int payload_length, struct greybus_host_device *hd) -{ - /* What? An AP should not get this message */ - dev_err(hd->parent, "Got an suspend message???\n"); -} - -static struct svc_msg *convert_ap_message(struct ap_msg *ap_msg) -{ - struct svc_msg *svc_msg; - struct svc_msg_header *header; - struct greybus_host_device *hd = ap_msg->hd; - - svc_msg = (struct svc_msg *)ap_msg->data; - header = &svc_msg->header; - - /* Validate the message type */ - if (header->message_type != SVC_MSG_DATA) { - dev_err(hd->parent, "message type %d received?\n", - header->message_type); - return NULL; - } - - /* - * The validation of the size of the message buffer happens in each - * svc_* function, due to the different types of messages, keeping the - * logic for each message only in one place. - */ - - return svc_msg; -} - -static void ap_process_event(struct work_struct *work) -{ - struct svc_msg *svc_msg; - struct greybus_host_device *hd; - struct ap_msg *ap_msg; - int payload_length; - - ap_msg = container_of(work, struct ap_msg, event); - hd = ap_msg->hd; - - /* Turn the "raw" data into a real message */ - svc_msg = convert_ap_message(ap_msg); - if (!svc_msg) - return; - - payload_length = le16_to_cpu(svc_msg->header.payload_length); - - /* Look at the message to figure out what to do with it */ - switch (svc_msg->header.function_id) { - case SVC_FUNCTION_HANDSHAKE: - svc_handshake(&svc_msg->handshake, payload_length, hd); - break; - case SVC_FUNCTION_UNIPRO_NETWORK_MANAGEMENT: - svc_management(&svc_msg->management, payload_length, hd); - break; - case SVC_FUNCTION_HOTPLUG: - svc_hotplug(&svc_msg->hotplug, payload_length, hd); - break; - case SVC_FUNCTION_POWER: - svc_power(&svc_msg->power, payload_length, hd); - break; - case SVC_FUNCTION_EPM: - svc_epm(&svc_msg->epm, payload_length, hd); - break; - case SVC_FUNCTION_SUSPEND: - svc_suspend(&svc_msg->suspend, payload_length, hd); - break; - default: - dev_err(hd->parent, "received invalid SVC function ID %d\n", - svc_msg->header.function_id); - } - - /* clean the message up */ - kfree(ap_msg->data); - kfree(ap_msg); -} - -int greybus_svc_in(struct greybus_host_device *hd, u8 *data, int size) -{ - struct ap_msg *ap_msg; - - /* - * Totally naive copy the message into a new structure that we slowly - * create and add it to the list. Let's get this working, the odds of - * this being any "slow path" for AP messages is really low at this - * point in time, but you never know, so this comment is here to point - * out that maybe we should use a slab allocator, or even just not copy - * the data, but use it directly and force the urbs to be "new" each - * time. - */ - - /* Note - this can, and will, be called in interrupt context. */ - ap_msg = kmalloc(sizeof(*ap_msg), GFP_ATOMIC); - if (!ap_msg) - return -ENOMEM; - ap_msg->data = kmalloc(size, GFP_ATOMIC); - if (!ap_msg->data) { - kfree(ap_msg); - return -ENOMEM; - } - memcpy(ap_msg->data, data, size); - ap_msg->size = size; - ap_msg->hd = hd; - - INIT_WORK(&ap_msg->event, ap_process_event); - queue_work(ap_workqueue, &ap_msg->event); - - return 0; -} -EXPORT_SYMBOL_GPL(greybus_svc_in); - -int __init gb_ap_init(void) -{ - ap_workqueue = alloc_ordered_workqueue("greybus_ap", 0); - if (!ap_workqueue) - return -ENOMEM; - - return 0; -} - -void gb_ap_exit(void) -{ - destroy_workqueue(ap_workqueue); - ap_workqueue = NULL; -} - - diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index bbfae4a..18075f7 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -269,12 +269,6 @@ static int __init gb_init(void) goto error_bus; } - retval = gb_ap_init(); - if (retval) { - pr_err("gb_ap_init failed (%d)\n", retval); - goto error_ap; - } - retval = gb_operation_init(); if (retval) { pr_err("gb_operation_init failed (%d)\n", retval); @@ -308,8 +302,6 @@ error_control: error_endo: gb_operation_exit(); error_operation: - gb_ap_exit(); -error_ap: bus_unregister(&greybus_bus_type); error_bus: gb_debugfs_cleanup(); @@ -324,7 +316,6 @@ static void __exit gb_exit(void) gb_control_protocol_exit(); gb_endo_exit(); gb_operation_exit(); - gb_ap_exit(); bus_unregister(&greybus_bus_type); gb_debugfs_cleanup(); } diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 2214f44..90f9962 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -156,8 +156,6 @@ void greybus_deregister_driver(struct greybus_driver *driver); int greybus_disabled(void); int greybus_svc_in(struct greybus_host_device *hd, u8 *data, int length); -int gb_ap_init(void); -void gb_ap_exit(void); void gb_debugfs_init(void); void gb_debugfs_cleanup(void); struct dentry *gb_debugfs_get(void); -- cgit v0.10.2 From 4de9b5679a13e4154a201996115ceb4a9f95cadb Mon Sep 17 00:00:00 2001 From: Perry Hung Date: Fri, 24 Jul 2015 19:02:31 -0400 Subject: greybus: svc: add route create operation Implement the SVC Protocol Route Create Operation. Tested-by: Viresh Kumar Reviewed-by: Viresh Kumar Signed-off-by: Perry Hung Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 9708e93..5b97073 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -563,6 +563,7 @@ struct gb_spi_transfer_response { #define GB_SVC_TYPE_INTF_RESET 0x06 #define GB_SVC_TYPE_CONN_CREATE 0x07 #define GB_SVC_TYPE_CONN_DESTROY 0x08 +#define GB_SVC_TYPE_ROUTE_CREATE 0x0b /* SVC version request/response have same payload as gb_protocol_version_response */ @@ -616,6 +617,13 @@ struct gb_svc_conn_destroy_request { }; /* connection destroy response has no payload */ +struct gb_svc_route_create_request { + __u8 intf1_id; + __u8 dev1_id; + __u8 intf2_id; + __u8 dev2_id; +}; + /* UART */ /* Version of the Greybus UART protocol we support */ diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 5f2b2b4..f332129 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -118,6 +118,20 @@ static int connection_destroy_operation(struct gb_svc *svc, &request, sizeof(request), NULL, 0); } +static int route_create_operation(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, + u8 intf2_id, u8 dev2_id) +{ + struct gb_svc_route_create_request request; + + request.intf1_id = intf1_id; + request.dev1_id = dev1_id; + request.intf2_id = intf2_id; + request.dev2_id = dev2_id; + + return gb_operation_sync(svc->connection, GB_SVC_TYPE_ROUTE_CREATE, + &request, sizeof(request), NULL, 0); +} + int gb_svc_intf_device_id(struct gb_svc *svc, u8 intf_id, u8 device_id) { return intf_device_id_operation(svc, intf_id, device_id); @@ -148,6 +162,13 @@ int gb_svc_connection_destroy(struct gb_svc *svc, } EXPORT_SYMBOL_GPL(gb_svc_connection_destroy); +int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, + u8 intf2_id, u8 dev2_id) { + return route_create_operation(svc, intf1_id, dev1_id, + intf2_id, dev2_id); +} +EXPORT_SYMBOL_GPL(gb_svc_route_create); + static int gb_svc_version_request(struct gb_operation *op) { struct gb_connection *connection = op->connection; -- cgit v0.10.2 From 5d6896d24a7bf557816677abdac225074576f8a3 Mon Sep 17 00:00:00 2001 From: Perry Hung Date: Fri, 24 Jul 2015 19:02:32 -0400 Subject: greybus: svc: create bidirectional routes on hotplug request Upon receiving a hotplug request, we need to prepare the routing table to allow packets to flow between the AP interface and the newly detected interface. Tested-by: Viresh Kumar Reviewed-by: Viresh Kumar Signed-off-by: Perry Hung Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index f332129..3d18087 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -309,6 +309,25 @@ static int gb_svc_intf_hotplug_recv(struct gb_operation *op) goto ida_put; } + /* + * Create a two-way route between the AP and the new interface + */ + ret = route_create_operation(svc, hd->endo->ap_intf_id, + GB_DEVICE_ID_AP, intf_id, device_id); + if (ret) { + dev_err(dev, "%s: Route create operation failed, interface %hhu device_id %hhu (%d)\n", + __func__, intf_id, device_id, ret); + goto ida_put; + } + + ret = route_create_operation(svc, intf_id, device_id, + hd->endo->ap_intf_id, GB_DEVICE_ID_AP); + if (ret) { + dev_err(dev, "%s: Route create operation failed, interface %hhu device_id %hhu (%d)\n", + __func__, intf_id, device_id, ret); + goto ida_put; + } + ret = gb_interface_init(intf, device_id); if (ret) { dev_err(dev, "%s: Failed to initialize interface, interface %hhu device_id %hhu (%d)\n", -- cgit v0.10.2 From 9c1552d7c4a97acb759ab41635197d213d677c9e Mon Sep 17 00:00:00 2001 From: Perry Hung Date: Fri, 24 Jul 2015 19:02:33 -0400 Subject: greybus: svc: connection: ask SVC to create connections Ask the SVC to do all the necessary bits for creating a new connection. This is skipped for the initial SVC connection. Tested-by: Viresh Kumar Reviewed-by: Viresh Kumar Signed-off-by: Perry Hung Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index b32da8a..1a657f70 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -251,7 +251,12 @@ gb_connection_create_range(struct greybus_host_device *hd, spin_unlock_irq(&gb_connections_lock); - /* XXX Will have to establish connections to get version */ + if (hd_cport_id != GB_SVC_CPORT_ID) { + gb_svc_connection_create(hd->svc, + hd->endo->ap_intf_id, hd_cport_id, + bundle->intf->interface_id, cport_id); + } + gb_connection_bind_protocol(connection); if (!connection->protocol) dev_warn(&connection->dev, diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 90f9962..ef11b96 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -103,6 +103,7 @@ struct greybus_host_device { struct gb_endo *endo; struct gb_connection *initial_svc_connection; + struct gb_svc *svc; /* Private data for the host driver */ unsigned long hd_priv[0] __aligned(sizeof(s64)); diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 3d18087..b718a88 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -430,6 +430,7 @@ static int gb_svc_connection_init(struct gb_connection *connection) if (!svc) return -ENOMEM; + connection->hd->svc = svc; svc->connection = connection; connection->private = svc; @@ -445,6 +446,7 @@ static void gb_svc_connection_exit(struct gb_connection *connection) { struct gb_svc *svc = connection->private; + connection->hd->svc = NULL; connection->private = NULL; kfree(svc); } -- cgit v0.10.2 From e50b7be565a888ff0b1ac38247cc3c34e1f9c2f7 Mon Sep 17 00:00:00 2001 From: Perry Hung Date: Fri, 24 Jul 2015 19:02:34 -0400 Subject: greybus: svc: add flags and traffic class parameter to connection create op The AP needs to be able to specify L4 CPort flags and traffic class parameters on a connection-by-connection basis. Extend the connection create operation to accept these. Since there's no policy to decide these, fix them at TC0 with end-to-end-flow control, controlled segment dropping, and CPort safety valve enabled. Tested-by: Viresh Kumar Reviewed-by: Viresh Kumar Signed-off-by: Perry Hung Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 5b97073..e2d38df 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -606,6 +606,8 @@ struct gb_svc_conn_create_request { __u16 cport1_id; __u8 intf2_id; __u16 cport2_id; + __u8 tc; + __u8 flags; }; /* connection create response has no payload */ diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index b718a88..b94a84a 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -9,6 +9,10 @@ #include "greybus.h" +#define CPORT_FLAGS_E2EFC (1) +#define CPORT_FLAGS_CSD_N (2) +#define CPORT_FLAGS_CSV_N (4) + struct gb_svc { struct gb_connection *connection; u8 version_major; @@ -98,6 +102,12 @@ static int connection_create_operation(struct gb_svc *svc, request.cport1_id = cport1_id; request.intf2_id = intf2_id; request.cport2_id = cport2_id; + /* + * XXX: fix connections paramaters to TC0 and all CPort flags + * for now. + */ + request.tc = 0; + request.flags = CPORT_FLAGS_CSV_N | CPORT_FLAGS_E2EFC; return gb_operation_sync(svc->connection, GB_SVC_TYPE_CONN_CREATE, &request, sizeof(request), NULL, 0); -- cgit v0.10.2 From 90c807e4fb19dba5db3ec7b6a86b0038aa574f84 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 24 Jul 2015 17:15:59 -0700 Subject: greybus: greybus.h: remove greybus_svc_in() The function is gone, remove it from the header file as well. Tested-by: Viresh Kumar Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index ef11b96..a011495 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -156,7 +156,6 @@ void greybus_deregister_driver(struct greybus_driver *driver); int greybus_disabled(void); -int greybus_svc_in(struct greybus_host_device *hd, u8 *data, int length); void gb_debugfs_init(void); void gb_debugfs_cleanup(void); struct dentry *gb_debugfs_get(void); -- cgit v0.10.2 From d187576fbe66995a97eebddaa27474b50407d18f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 24 Jul 2015 17:19:21 -0700 Subject: greybus: remove submit_svc from the host driver The callback is never used anymore, so remove it from struct greybus_host_driver as well as from the es1 and es2 drivers. Tested-by: Viresh Kumar Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 18075f7..49a28ba 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -175,8 +175,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver * Validate that the driver implements all of the callbacks * so that we don't have to every time we make them. */ - if ((!driver->message_send) || (!driver->message_cancel) || - (!driver->submit_svc)) { + if ((!driver->message_send) || (!driver->message_cancel)) { pr_err("Must implement all greybus_host_driver callbacks!\n"); return ERR_PTR(-EINVAL); } diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 82a7c67..e203180 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -14,7 +14,6 @@ #include #include "greybus.h" -#include "svc_msg.h" #include "kernel_ver.h" /* Memory sizes for the buffers sent to/from the ES1 controller */ @@ -95,26 +94,6 @@ static void usb_log_enable(struct es1_ap_dev *es1); static void usb_log_disable(struct es1_ap_dev *es1); #define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ -static int submit_svc(struct svc_msg *svc_msg, struct greybus_host_device *hd) -{ - struct es1_ap_dev *es1 = hd_to_es1(hd); - int retval; - - /* SVC messages go down our control pipe */ - retval = usb_control_msg(es1->usb_dev, - usb_sndctrlpipe(es1->usb_dev, - es1->control_endpoint), - REQUEST_SVC, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - 0x00, 0x00, - (char *)svc_msg, - sizeof(*svc_msg), - ES1_TIMEOUT); - if (retval != sizeof(*svc_msg)) - return retval; - - return 0; -} static struct urb *next_free_urb(struct es1_ap_dev *es1, gfp_t gfp_mask) { @@ -295,7 +274,6 @@ static struct greybus_host_driver es1_driver = { .hd_priv_size = sizeof(struct es1_ap_dev), .message_send = message_send, .message_cancel = message_cancel, - .submit_svc = submit_svc, }; /* Common function to report consistent warnings based on URB status */ diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index c353ca5..aba1927 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -14,7 +14,6 @@ #include #include "greybus.h" -#include "svc_msg.h" #include "kernel_ver.h" /* Memory sizes for the buffers sent to/from the ES1 controller */ @@ -134,26 +133,6 @@ static int cport_to_ep(struct es1_ap_dev *es1, u16 cport_id) } #define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ -static int submit_svc(struct svc_msg *svc_msg, struct greybus_host_device *hd) -{ - struct es1_ap_dev *es1 = hd_to_es1(hd); - int retval; - - /* SVC messages go down our control pipe */ - retval = usb_control_msg(es1->usb_dev, - usb_sndctrlpipe(es1->usb_dev, - es1->control_endpoint), - REQUEST_SVC, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - 0x00, 0x00, - (char *)svc_msg, - sizeof(*svc_msg), - ES1_TIMEOUT); - if (retval != sizeof(*svc_msg)) - return retval; - - return 0; -} static int ep_in_use(struct es1_ap_dev *es1, int bulk_ep_set) { @@ -391,7 +370,6 @@ static struct greybus_host_driver es1_driver = { .hd_priv_size = sizeof(struct es1_ap_dev), .message_send = message_send, .message_cancel = message_cancel, - .submit_svc = submit_svc, }; /* Common function to report consistent warnings based on URB status */ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index a011495..30ea4a4 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -84,8 +84,6 @@ struct greybus_host_driver { int (*message_send)(struct greybus_host_device *hd, u16 dest_cport_id, struct gb_message *message, gfp_t gfp_mask); void (*message_cancel)(struct gb_message *message); - int (*submit_svc)(struct svc_msg *svc_msg, - struct greybus_host_device *hd); }; struct greybus_host_device { -- cgit v0.10.2 From 4bc88276ebc4ec329fea0e7f811a5cc55ca869ae Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 24 Jul 2015 17:21:25 -0700 Subject: greybus: interface: make gb_interface_destroy() static The function is only called locally, so mark it static to make sparse happy. Tested-by: Viresh Kumar Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index f1e2956..4a26bf6 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -183,7 +183,7 @@ put_module: /* * Tear down a previously set up module. */ -void gb_interface_destroy(struct gb_interface *intf) +static void interface_destroy(struct gb_interface *intf) { struct gb_module *module; struct gb_bundle *bundle; @@ -279,7 +279,7 @@ void gb_interface_remove(struct greybus_host_device *hd, u8 interface_id) struct gb_interface *intf = gb_interface_find(hd, interface_id); if (intf) - gb_interface_destroy(intf); + interface_destroy(intf); else dev_err(hd->parent, "interface id %d not found\n", interface_id); @@ -290,5 +290,5 @@ void gb_interfaces_remove(struct greybus_host_device *hd) struct gb_interface *intf, *temp; list_for_each_entry_safe(intf, temp, &hd->interfaces, links) - gb_interface_destroy(intf); + interface_destroy(intf); } -- cgit v0.10.2 From 5a202efe63dde70885ba91c294690dbbf054a184 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Sat, 25 Jul 2015 10:10:05 +0530 Subject: greybus: es1: create svc connection early enough The svc connection needs to be ready before creating the URBs, otherwise the svc version request might come in before the AP was ready to parse them. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index e203180..5418f46 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -563,6 +563,12 @@ static int ap_probe(struct usb_interface *interface, return PTR_ERR(hd); } + /* Initialize AP's greybus interface */ + if (!gb_ap_svc_connection_create(hd)) { + retval = -EINVAL; + goto error; + } + es1 = hd_to_es1(hd); es1->hd = hd; es1->usb_intf = interface; @@ -632,12 +638,6 @@ static int ap_probe(struct usb_interface *interface, es1->cport_out_urb_busy[i] = false; /* just to be anal */ } - /* Initialize AP's greybus interface */ - if (!gb_ap_svc_connection_create(hd)) { - retval = -EINVAL; - goto error; - } - apb1_log_enable_dentry = debugfs_create_file("apb1_log_enable", (S_IWUSR | S_IRUGO), gb_debugfs_get(), es1, diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index aba1927..d2c054a 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -663,6 +663,12 @@ static int ap_probe(struct usb_interface *interface, return PTR_ERR(hd); } + /* Initialize AP's greybus interface */ + if (!gb_ap_svc_connection_create(hd)) { + retval = -EINVAL; + goto error; + } + es1 = hd_to_es1(hd); es1->hd = hd; es1->usb_intf = interface; @@ -736,12 +742,6 @@ static int ap_probe(struct usb_interface *interface, es1->cport_out_urb_busy[i] = false; /* just to be anal */ } - /* Initialize AP's greybus interface */ - if (!gb_ap_svc_connection_create(hd)) { - retval = -EINVAL; - goto error; - } - apb1_log_enable_dentry = debugfs_create_file("apb1_log_enable", (S_IWUSR | S_IRUGO), gb_debugfs_get(), es1, -- cgit v0.10.2 From d8742156c1c0125b709c262c5a564bb828e126dc Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Sat, 25 Jul 2015 10:10:06 +0530 Subject: greybus: remove svc_msg.h Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 30ea4a4..cdade1e 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -73,7 +73,6 @@ */ struct greybus_host_device; -struct svc_msg; /* Greybus "Host driver" structure, needed by a host controller driver to be * able to handle both SVC control as well as "real" greybus messages diff --git a/drivers/staging/greybus/svc_msg.h b/drivers/staging/greybus/svc_msg.h deleted file mode 100644 index 3c628c5..0000000 --- a/drivers/staging/greybus/svc_msg.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Greybus AP <-> SVC message structure format. - * - * See "Greybus Application Protocol" document (version 0.1) for - * details on these values and structures. - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - * - * Released under the GPLv2 and BSD license. - */ - -#ifndef __SVC_MSG_H -#define __SVC_MSG_H - -enum svc_function_id { - SVC_FUNCTION_HANDSHAKE = 0x00, - SVC_FUNCTION_UNIPRO_NETWORK_MANAGEMENT = 0x01, - SVC_FUNCTION_HOTPLUG = 0x02, - SVC_FUNCTION_POWER = 0x03, - SVC_FUNCTION_EPM = 0x04, - SVC_FUNCTION_SUSPEND = 0x05, -}; - -enum svc_msg_type { - SVC_MSG_DATA = 0x00, - SVC_MSG_ERROR = 0xff, -}; - -struct svc_msg_header { - __u8 function_id; /* enum svc_function_id */ - __u8 message_type; - __le16 payload_length; -} __packed; - -enum svc_function_handshake_type { - SVC_HANDSHAKE_SVC_HELLO = 0x00, - SVC_HANDSHAKE_AP_HELLO = 0x01, - SVC_HANDSHAKE_MODULE_HELLO = 0x02, -}; - -struct svc_function_handshake { - __u8 version_major; - __u8 version_minor; - __u8 handshake_type; /* enum svc_function_handshake_type */ -} __packed; - -struct svc_function_unipro_set_route { - __u8 device_id; -} __packed; - -struct svc_function_unipro_link_up { - __u8 interface_id; /* Interface id within the Endo */ - __u8 device_id; -} __packed; - -struct svc_function_ap_id { - __u8 interface_id; - __u8 device_id; -} __packed; - -enum svc_function_management_event { - SVC_MANAGEMENT_AP_ID = 0x00, - SVC_MANAGEMENT_LINK_UP = 0x01, - SVC_MANAGEMENT_SET_ROUTE = 0x02, -}; - -struct svc_function_unipro_management { - __u8 management_packet_type; /* enum svc_function_management_event */ - union { - struct svc_function_ap_id ap_id; - struct svc_function_unipro_link_up link_up; - struct svc_function_unipro_set_route set_route; - }; -} __packed; - -enum svc_function_hotplug_event { - SVC_HOTPLUG_EVENT = 0x00, - SVC_HOTUNPLUG_EVENT = 0x01, -}; - -struct svc_function_hotplug { - __u8 hotplug_event; /* enum svc_function_hotplug_event */ - __u8 interface_id; /* Interface id within the Endo */ -} __packed; - -enum svc_function_power_type { - SVC_POWER_BATTERY_STATUS = 0x00, - SVC_POWER_BATTERY_STATUS_REQUEST = 0x01, -}; - -enum svc_function_battery_status { - SVC_BATTERY_UNKNOWN = 0x00, - SVC_BATTERY_CHARGING = 0x01, - SVC_BATTERY_DISCHARGING = 0x02, - SVC_BATTERY_NOT_CHARGING = 0x03, - SVC_BATTERY_FULL = 0x04, -}; - -struct svc_function_power_battery_status { - __le16 charge_full; - __le16 charge_now; - __u8 status; /* enum svc_function_battery_status */ -} __packed; - -struct svc_function_power_battery_status_request { -} __packed; - -/* XXX - * Each interface carries power, so it's possible these things - * are associated with each UniPro device and not just the module. - * For now it's safe to assume it's per-module. - */ -struct svc_function_power { - __u8 power_type; /* enum svc_function_power_type */ - __u8 interface_id; - union { - struct svc_function_power_battery_status status; - struct svc_function_power_battery_status_request request; - }; -} __packed; - -enum svc_function_epm_command_type { - SVC_EPM_ENABLE = 0x00, - SVC_EPM_DISABLE = 0x01, -}; - -/* EPM's are associated with the module */ -struct svc_function_epm { - __u8 epm_command_type; /* enum svc_function_epm_command_type */ - __u8 module_id; -} __packed; - -enum svc_function_suspend_command_type { - SVC_SUSPEND_FIXME_1 = 0x00, // FIXME - SVC_SUSPEND_FIXME_2 = 0x01, -}; - -/* We'll want independent control for multi-interface modules */ -struct svc_function_suspend { - __u8 suspend_command_type; /* enum function_suspend_command_type */ - __u8 device_id; -} __packed; - -struct svc_msg { - struct svc_msg_header header; - union { - struct svc_function_handshake handshake; - struct svc_function_unipro_management management; - struct svc_function_hotplug hotplug; - struct svc_function_power power; - struct svc_function_epm epm; - struct svc_function_suspend suspend; - }; -} __packed; - -#endif /* __SVC_MSG_H */ -- cgit v0.10.2 From fe166c6a2b9225d71b1b4f1035603e189f6c3640 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 27 Jul 2015 14:23:44 -0700 Subject: greybus: core: clean up ida memory for host controller We forgot to free any ida internal structures that were used by this host controller structure when we free the memory for the controller. So fix that up by doing so in the release function. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Viresh Kumar diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 49a28ba..7d5cd99 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -161,6 +161,7 @@ static void free_hd(struct kref *kref) hd = container_of(kref, struct greybus_host_device, kref); + ida_destroy(&hd->cport_id_map); kfree(hd); mutex_unlock(&hd_mutex); } -- cgit v0.10.2 From 9612f2bcd466364a244b8c2a012de69abd8fb258 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 28 Jul 2015 07:28:42 +0530 Subject: greybus: initialize svc connection while creating hd Its really part of initializing the host device and is required for every 'hd' that is created. Lets move the call to do basic initialization of svc connection to greybus_create_hd(). Also add a comment to specify why we need to do it that early. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 7d5cd99..9f105fb 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -208,6 +208,21 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver ida_init(&hd->cport_id_map); hd->buffer_size_max = buffer_size_max; + /* + * Initialize AP's SVC protocol connection: + * + * This is required as part of early initialization of the host device + * as we need this connection in order to start any kind of message + * exchange between the AP and the SVC. SVC will start with a + * 'get-version' request followed by a 'svc-hello' message and at that + * time we will create a fully initialized svc-connection, as we need + * endo-id and AP's interface id for that. + */ + if (!gb_ap_svc_connection_create(hd)) { + kref_put_mutex(&hd->kref, free_hd, &hd_mutex); + return ERR_PTR(-ENOMEM); + } + return hd; } EXPORT_SYMBOL_GPL(greybus_create_hd); diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 5418f46..c1fab37 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -563,12 +563,6 @@ static int ap_probe(struct usb_interface *interface, return PTR_ERR(hd); } - /* Initialize AP's greybus interface */ - if (!gb_ap_svc_connection_create(hd)) { - retval = -EINVAL; - goto error; - } - es1 = hd_to_es1(hd); es1->hd = hd; es1->usb_intf = interface; diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index d2c054a..558345c 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -663,12 +663,6 @@ static int ap_probe(struct usb_interface *interface, return PTR_ERR(hd); } - /* Initialize AP's greybus interface */ - if (!gb_ap_svc_connection_create(hd)) { - retval = -EINVAL; - goto error; - } - es1 = hd_to_es1(hd); es1->hd = hd; es1->usb_intf = interface; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index b94a84a..784b770 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -40,7 +40,6 @@ gb_ap_svc_connection_create(struct greybus_host_device *hd) return connection; } -EXPORT_SYMBOL_GPL(gb_ap_svc_connection_create); /* * We know endo-type and AP's interface id now, lets create a proper svc -- cgit v0.10.2 From a7e60062b022d1ce1104610d0b0c37322aeb66b6 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 28 Jul 2015 18:34:35 +0100 Subject: greybus: loopback: remove redundant timestamping It is of more interest to graphing system performance to base our timestamps on the time it takes a greybus_operation_sync() to complete. Higher level timestamping code is less accurate and not relevant to throughput and latency characterization. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 2294948..5f7c1a6 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -43,8 +43,6 @@ struct gb_loopback { struct gb_loopback_stats latency; struct gb_loopback_stats throughput; struct gb_loopback_stats requests_per_second; - struct timeval ts; - struct timeval te; u64 elapsed_nsecs; u32 error; }; @@ -180,11 +178,9 @@ static struct attribute *loopback_attrs[] = { }; ATTRIBUTE_GROUPS(loopback); -static int gb_loopback_sink(struct gb_loopback *gb, - struct timeval *tping, u32 len) +static int gb_loopback_sink(struct gb_loopback *gb, u32 len) { struct timeval ts, te; - u64 elapsed_nsecs; struct gb_loopback_transfer_request *request; int retval; @@ -199,18 +195,15 @@ static int gb_loopback_sink(struct gb_loopback *gb, request, len + sizeof(*request), NULL, 0); do_gettimeofday(&te); - elapsed_nsecs = timeval_to_ns(&te) - timeval_to_ns(&ts); - *tping = ns_to_timeval(elapsed_nsecs); + gb->elapsed_nsecs = timeval_to_ns(&te) - timeval_to_ns(&ts); kfree(request); return retval; } -static int gb_loopback_transfer(struct gb_loopback *gb, - struct timeval *tping, u32 len) +static int gb_loopback_transfer(struct gb_loopback *gb, u32 len) { struct timeval ts, te; - u64 elapsed_nsecs; struct gb_loopback_transfer_request *request; struct gb_loopback_transfer_response *response; int retval; @@ -231,8 +224,7 @@ static int gb_loopback_transfer(struct gb_loopback *gb, request, len + sizeof(*request), response, len + sizeof(*response)); do_gettimeofday(&te); - elapsed_nsecs = timeval_to_ns(&te) - timeval_to_ns(&ts); - *tping = ns_to_timeval(elapsed_nsecs); + gb->elapsed_nsecs = timeval_to_ns(&te) - timeval_to_ns(&ts); if (retval) goto gb_error; @@ -247,18 +239,16 @@ gb_error: return retval; } -static int gb_loopback_ping(struct gb_loopback *gb, struct timeval *tping) +static int gb_loopback_ping(struct gb_loopback *gb) { struct timeval ts, te; - u64 elapsed_nsecs; int retval; do_gettimeofday(&ts); retval = gb_operation_sync(gb->connection, GB_LOOPBACK_TYPE_PING, NULL, 0, NULL, 0); do_gettimeofday(&te); - elapsed_nsecs = timeval_to_ns(&te) - timeval_to_ns(&ts); - *tping = ns_to_timeval(elapsed_nsecs); + gb->elapsed_nsecs = timeval_to_ns(&te) - timeval_to_ns(&ts); return retval; } @@ -324,7 +314,6 @@ static void gb_loopback_reset_stats(struct gb_loopback *gb) memcpy(&gb->throughput, &reset, sizeof(struct gb_loopback_stats)); memcpy(&gb->requests_per_second, &reset, sizeof(struct gb_loopback_stats)); - memset(&gb->ts, 0, sizeof(struct timeval)); } static void gb_loopback_update_stats(struct gb_loopback_stats *stats, u64 val) @@ -375,8 +364,7 @@ static void gb_loopback_throughput_update(struct gb_loopback *gb, u32 latency) gb_loopback_update_stats(&gb->throughput, throughput); } -static void gb_loopback_calculate_stats(struct gb_loopback *gb, - struct timeval *tlat) +static void gb_loopback_calculate_stats(struct gb_loopback *gb) { u32 lat; u64 tmp; @@ -397,7 +385,6 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb, static int gb_loopback_fn(void *data) { int error = 0; - struct timeval tlat = {0, 0}; struct gb_loopback *gb = (struct gb_loopback *)data; while (1) { @@ -416,21 +403,15 @@ static int gb_loopback_fn(void *data) continue; } } - if (gb->ts.tv_usec == 0 && gb->ts.tv_sec == 0) - do_gettimeofday(&gb->ts); if (gb->type == GB_LOOPBACK_TYPE_PING) - error = gb_loopback_ping(gb, &tlat); + error = gb_loopback_ping(gb); else if (gb->type == GB_LOOPBACK_TYPE_TRANSFER) - error = gb_loopback_transfer(gb, &tlat, gb->size); + error = gb_loopback_transfer(gb, gb->size); else if (gb->type == GB_LOOPBACK_TYPE_SINK) - error = gb_loopback_sink(gb, &tlat, gb->size); + error = gb_loopback_sink(gb, gb->size); if (error) gb->error++; - do_gettimeofday(&gb->te); - gb->elapsed_nsecs = timeval_to_ns(&gb->te) - - timeval_to_ns(&gb->ts); - gb_loopback_calculate_stats(gb, &tlat); - gb->ts = gb->te; + gb_loopback_calculate_stats(gb); if (gb->ms_wait) msleep(gb->ms_wait); } -- cgit v0.10.2 From 85d678c0bee883c63b760b35a4104feac9018a0f Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 28 Jul 2015 18:34:36 +0100 Subject: greybus: loopback: make loopback code thread safe Current code allows a sysfs callback and a kernel worker thread to write all over and act upon data that could be in the process of being updated by the other. This patch adds a reasonably coarse mutex to enscure sync between the two. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 5f7c1a6..afba422 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -8,6 +8,7 @@ */ #include #include +#include #include #include #include @@ -30,6 +31,7 @@ struct gb_loopback { u8 version_major; u8 version_minor; + struct mutex mutex; struct task_struct *task; wait_queue_head_t wq; @@ -101,10 +103,13 @@ static ssize_t field##_store(struct device *dev, \ struct gb_connection *connection = to_gb_connection(dev); \ struct gb_loopback *gb = \ (struct gb_loopback *)connection->private; \ + mutex_lock(&gb->mutex); \ ret = sscanf(buf, "%"#type, &gb->field); \ if (ret != 1) \ - return -EINVAL; \ - gb_loopback_check_attr(gb); \ + len = -EINVAL; \ + else \ + gb_loopback_check_attr(gb); \ + mutex_unlock(&gb->mutex); \ return len; \ } \ static DEVICE_ATTR_RW(field) @@ -385,6 +390,7 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb) static int gb_loopback_fn(void *data) { int error = 0; + int ms_wait; struct gb_loopback *gb = (struct gb_loopback *)data; while (1) { @@ -393,6 +399,8 @@ static int gb_loopback_fn(void *data) kthread_should_stop()); if (kthread_should_stop()) break; + + mutex_lock(&gb->mutex); if (gb->iteration_max) { if (gb->iteration_count < gb->iteration_max) { gb->iteration_count++; @@ -400,6 +408,7 @@ static int gb_loopback_fn(void *data) "iteration_count"); } else { gb->type = 0; + mutex_unlock(&gb->mutex); continue; } } @@ -412,8 +421,10 @@ static int gb_loopback_fn(void *data) if (error) gb->error++; gb_loopback_calculate_stats(gb); - if (gb->ms_wait) - msleep(gb->ms_wait); + ms_wait = gb->ms_wait; + mutex_unlock(&gb->mutex); + if (ms_wait) + msleep(ms_wait); } return 0; } @@ -448,6 +459,7 @@ static int gb_loopback_connection_init(struct gb_connection *connection) gb_loopback_reset_stats(gb); init_waitqueue_head(&gb->wq); + mutex_init(&gb->mutex); gb->task = kthread_run(gb_loopback_fn, gb, "gb_loopback"); if (IS_ERR(gb->task)) { retval = PTR_ERR(gb->task); -- cgit v0.10.2 From cbd204b48dc445a194d3892e2f46644f9074f308 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 28 Jul 2015 18:34:38 +0100 Subject: greybus: loopback: provide interface to read all latency data-points The current loopback code provides the minimum, maximum and average latency values for a given test set. It would be highly useful for user-space to have access to each one of the latency metrics in order to graph outliers. This patch adds a simple character device interface implmenting a read() interface that allows user-space to read out the saved latency metrics which have been stored in a kfifo for this purpose. A module parameter is provided to allow varying the depth of the kfifo in order to allow a user to capture potentially large data sets. This version sets the default depth for the kfifo at 8192 dwords. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index afba422..7b3ce13 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -14,6 +14,10 @@ #include #include #include +#include +#include +#include + #include #include "greybus.h" @@ -31,9 +35,13 @@ struct gb_loopback { u8 version_major; u8 version_minor; + struct kfifo kfifo; struct mutex mutex; struct task_struct *task; wait_queue_head_t wq; + dev_t dev; + struct cdev cdev; + struct device *device; int type; u32 size; @@ -49,6 +57,21 @@ struct gb_loopback { u32 error; }; +#define GB_LOOPBACK_FIFO_DEFAULT 8192 + +static struct class *loopback_class; +static int loopback_major; +static const struct file_operations loopback_fops; +static DEFINE_IDA(minors); +static unsigned kfifo_depth = GB_LOOPBACK_FIFO_DEFAULT; +module_param(kfifo_depth, uint, 0444); + +/* Number of minor devices this driver supports */ +#define NUM_MINORS 256 + +/* Maximum size of any one send data buffer we support */ +#define MAX_PACKET_SIZE (PAGE_SIZE * 2) + #define GB_LOOPBACK_MS_WAIT_MAX 1000 /* Define get_version() routine */ @@ -129,6 +152,7 @@ static void gb_loopback_check_attr(struct gb_loopback *gb) case GB_LOOPBACK_TYPE_PING: case GB_LOOPBACK_TYPE_TRANSFER: case GB_LOOPBACK_TYPE_SINK: + kfifo_reset_out(&gb->kfifo); wake_up(&gb->wq); break; default: @@ -381,6 +405,7 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb) /* Log latency stastic */ gb_loopback_update_stats(&gb->latency, lat); + kfifo_in(&gb->kfifo, (unsigned char *)&lat, sizeof(lat)); /* Log throughput and requests using latency as benchmark */ gb_loopback_throughput_update(gb, lat); @@ -433,10 +458,12 @@ static int gb_loopback_connection_init(struct gb_connection *connection) { struct gb_loopback *gb; int retval; + int minor; gb = kzalloc(sizeof(*gb), GFP_KERNEL); if (!gb) return -ENOMEM; + gb_loopback_reset_stats(gb); gb->connection = connection; connection->private = gb; @@ -444,6 +471,13 @@ static int gb_loopback_connection_init(struct gb_connection *connection) if (retval) goto out_free; + /* Get a minor number */ + minor = ida_simple_get(&minors, 0, 0, GFP_KERNEL); + if (minor < 0) { + retval = minor; + goto out_free; + } + /* Check the version */ retval = get_version(gb); if (retval) @@ -457,17 +491,44 @@ static int gb_loopback_connection_init(struct gb_connection *connection) } gb->size_max -= sizeof(struct gb_loopback_transfer_request); - gb_loopback_reset_stats(gb); + /* Allocate kfifo */ + if (kfifo_alloc(&gb->kfifo, kfifo_depth * sizeof(u32), + GFP_KERNEL)) { + retval = -ENOMEM; + goto out_get_ver; + } + + /* Create device entry */ + gb->dev = MKDEV(loopback_major, minor); + cdev_init(&gb->cdev, &loopback_fops); + retval = cdev_add(&gb->cdev, gb->dev, 1); + if (retval) + goto out_cdev; + + gb->device = device_create(loopback_class, &connection->dev, gb->dev, + gb, "gb!loopback%d", minor); + if (IS_ERR(gb->device)) { + retval = PTR_ERR(gb->device); + goto out_device; + } + + /* Fork worker thread */ init_waitqueue_head(&gb->wq); mutex_init(&gb->mutex); gb->task = kthread_run(gb_loopback_fn, gb, "gb_loopback"); if (IS_ERR(gb->task)) { retval = PTR_ERR(gb->task); - goto out_get_ver; + goto out_kfifo; } return 0; +out_device: + cdev_del(&gb->cdev); +out_cdev: + ida_simple_remove(&minors, minor); +out_kfifo: + kfifo_free(&gb->kfifo); out_get_ver: sysfs_remove_groups(&connection->dev.kobj, loopback_groups); out_free: @@ -481,6 +542,11 @@ static void gb_loopback_connection_exit(struct gb_connection *connection) if (!IS_ERR_OR_NULL(gb->task)) kthread_stop(gb->task); + + cdev_del(&gb->cdev); + ida_simple_remove(&minors, MINOR(gb->dev)); + device_del(gb->device); + kfifo_free(&gb->kfifo); sysfs_remove_groups(&connection->dev.kobj, loopback_groups); kfree(gb); } @@ -495,6 +561,80 @@ static struct gb_protocol loopback_protocol = { .request_recv = gb_loopback_request_recv, }; -gb_protocol_driver(&loopback_protocol); +static int loopback_open(struct inode *inode, struct file *file) +{ + struct cdev *cdev = inode->i_cdev; + struct gb_loopback *gb = container_of(cdev, struct gb_loopback, cdev); + + file->private_data = gb; + return 0; +} + +static ssize_t loopback_read(struct file *file, char __user *buf, size_t count, + loff_t *ppos) +{ + struct gb_loopback *gb = file->private_data; + size_t fifo_len; + int retval; + + if (!count || count%sizeof(u32)) + return -EINVAL; + + mutex_lock(&gb->mutex); + fifo_len = kfifo_len(&gb->kfifo); + if (kfifo_to_user(&gb->kfifo, buf, min(fifo_len, count), &retval) != 0) + retval = -EIO; + mutex_unlock(&gb->mutex); + + return retval; +} + +static const struct file_operations loopback_fops = { + .owner = THIS_MODULE, + .read = loopback_read, + .open = loopback_open, + .llseek = noop_llseek, +}; + +static int loopback_init(void) +{ + dev_t dev; + int retval; + + loopback_class = class_create(THIS_MODULE, "gb_loopback"); + if (IS_ERR(loopback_class)) { + retval = PTR_ERR(loopback_class); + goto error_class; + } + + retval = alloc_chrdev_region(&dev, 0, NUM_MINORS, "gb_loopback"); + if (retval < 0) + goto error_chrdev; + + loopback_major = MAJOR(dev); + + retval = gb_protocol_register(&loopback_protocol); + if (retval) + goto error_gb; + + return 0; + +error_gb: + unregister_chrdev_region(dev, NUM_MINORS); +error_chrdev: + class_destroy(loopback_class); +error_class: + return retval; +} +module_init(loopback_init); + +static void __exit loopback_exit(void) +{ + gb_protocol_deregister(&loopback_protocol); + unregister_chrdev_region(MKDEV(loopback_major, 0), NUM_MINORS); + class_destroy(loopback_class); + ida_destroy(&minors); +} +module_exit(loopback_exit); MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From cb60f4960ea03d373899c2c21b0611404025c31f Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 28 Jul 2015 18:34:39 +0100 Subject: greybus: loopback: warn user if kfifo cannot log all data The depth of the kfifo used to log the latency data for user-space can be moved upwards or downward by way of a module parameter. The user may still specify a test set that's larger than the number of kfifo elements we have available. If the user specifies more iterations than can be logged give a warning as feedback and continue with the test. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 7b3ce13..08a77fe 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -131,14 +131,15 @@ static ssize_t field##_store(struct device *dev, \ if (ret != 1) \ len = -EINVAL; \ else \ - gb_loopback_check_attr(gb); \ + gb_loopback_check_attr(connection, gb); \ mutex_unlock(&gb->mutex); \ return len; \ } \ static DEVICE_ATTR_RW(field) static void gb_loopback_reset_stats(struct gb_loopback *gb); -static void gb_loopback_check_attr(struct gb_loopback *gb) +static void gb_loopback_check_attr(struct gb_connection *connection, + struct gb_loopback *gb) { if (gb->ms_wait > GB_LOOPBACK_MS_WAIT_MAX) gb->ms_wait = GB_LOOPBACK_MS_WAIT_MAX; @@ -148,6 +149,12 @@ static void gb_loopback_check_attr(struct gb_loopback *gb) gb->iteration_count = 0; gb_loopback_reset_stats(gb); + if (kfifo_depth < gb->iteration_max) { + dev_warn(&connection->dev, + "iteration_max %u kfifo_depth %u cannot log all data\n", + gb->iteration_max, kfifo_depth); + } + switch (gb->type) { case GB_LOOPBACK_TYPE_PING: case GB_LOOPBACK_TYPE_TRANSFER: -- cgit v0.10.2 From 3eac885de205ef57c3d434a8a4e2eadfd4cedde7 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 29 Jul 2015 10:05:09 -0700 Subject: greybus: svc: revert svc changes to keep things working for a while. The firmware for the svc changes isn't quite ready, so revert the whole set of patches in one hunk to get things back to a working state for the other firmware developers. The svc patches will be added back in a separate branch. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index d14bf4d..1467c5b 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -1,5 +1,6 @@ greybus-y := core.o \ debugfs.o \ + ap.o \ manifest.o \ endo.o \ module.o \ diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c new file mode 100644 index 0000000..fc23817 --- /dev/null +++ b/drivers/staging/greybus/ap.c @@ -0,0 +1,351 @@ +/* + * Greybus "AP" message loop handling + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include "svc_msg.h" +#include "greybus_manifest.h" +#include "greybus.h" + +struct ap_msg { + u8 *data; + size_t size; + struct greybus_host_device *hd; + struct work_struct event; +}; + +static struct workqueue_struct *ap_workqueue; + +static struct svc_msg *svc_msg_alloc(enum svc_function_id id) +{ + struct svc_msg *svc_msg; + + svc_msg = kzalloc((sizeof *svc_msg), GFP_KERNEL); + if (!svc_msg) + return NULL; + + // FIXME - verify we are only sending function IDs we should be + svc_msg->header.function_id = id; + return svc_msg; +} + +static void svc_msg_free(struct svc_msg *svc_msg) +{ + kfree(svc_msg); +} + +static int svc_msg_send(struct svc_msg *svc_msg, struct greybus_host_device *hd) +{ + int retval; + + // FIXME - Do we need to do more than just pass it to the hd and then + // free it? + retval = hd->driver->submit_svc(svc_msg, hd); + + svc_msg_free(svc_msg); + return retval; +} + +static void svc_handshake(struct svc_function_handshake *handshake, + int payload_length, struct greybus_host_device *hd) +{ + struct svc_msg *svc_msg; + + if (payload_length != sizeof(*handshake)) { + dev_err(hd->parent, + "Illegal size of svc handshake message %d\n", + payload_length); + return; + } + + /* A new SVC communication channel, let's verify a supported version */ + if ((handshake->version_major != GREYBUS_VERSION_MAJOR) || + (handshake->version_minor != GREYBUS_VERSION_MINOR)) { + dev_warn(hd->parent, + "received invalid greybus version %u.%u\n", + handshake->version_major, handshake->version_minor); + return; + } + + /* Validate that the handshake came from the SVC */ + if (handshake->handshake_type != SVC_HANDSHAKE_SVC_HELLO) { + /* we don't know what to do with this, log it and return */ + dev_dbg(hd->parent, "received invalid handshake type %d\n", + handshake->handshake_type); + return; + } + + /* Send back a AP_HELLO message */ + svc_msg = svc_msg_alloc(SVC_FUNCTION_HANDSHAKE); + if (!svc_msg) + return; + + svc_msg->header.message_type = SVC_MSG_DATA; + svc_msg->header.payload_length = + cpu_to_le16(sizeof(*handshake)); + svc_msg->handshake.version_major = GREYBUS_VERSION_MAJOR; + svc_msg->handshake.version_minor = GREYBUS_VERSION_MINOR; + svc_msg->handshake.handshake_type = SVC_HANDSHAKE_AP_HELLO; + + (void)svc_msg_send(svc_msg, hd); +} + +static void svc_management(struct svc_function_unipro_management *management, + int payload_length, struct greybus_host_device *hd) +{ + struct gb_interface *intf; + int ret; + + if (payload_length != sizeof(*management)) { + dev_err(hd->parent, + "Illegal size of svc management message %d\n", + payload_length); + return; + } + + switch (management->management_packet_type) { + case SVC_MANAGEMENT_AP_ID: + hd->device_id = management->ap_id.device_id; + break; + case SVC_MANAGEMENT_LINK_UP: + intf = gb_interface_find(hd, management->link_up.interface_id); + if (!intf) { + dev_err(hd->parent, "Interface ID %d not found\n", + management->link_up.interface_id); + return; + } + ret = gb_interface_init(intf, management->link_up.device_id); + if (ret) { + dev_err(hd->parent, + "error %d initializing interface %hhu\n", + ret, management->link_up.interface_id); + return; + } + break; + default: + dev_err(hd->parent, "Unhandled UniPro management message\n"); + } +} + +static void svc_hotplug(struct svc_function_hotplug *hotplug, + int payload_length, struct greybus_host_device *hd) +{ + u8 interface_id = hotplug->interface_id; + + switch (hotplug->hotplug_event) { + case SVC_HOTPLUG_EVENT: + /* Add a new interface to the system */ + if (payload_length != sizeof(*hotplug)) { + dev_err(hd->parent, + "Illegal size of svc hotplug message %d\n", + payload_length); + return; + } + dev_dbg(hd->parent, "interface id %d added\n", interface_id); + gb_interface_create(hd, interface_id); + break; + + case SVC_HOTUNPLUG_EVENT: + /* Remove a interface from the system */ + if (payload_length != sizeof(*hotplug)) { + dev_err(hd->parent, + "Illegal size of svc hotunplug message %d\n", + payload_length); + return; + } + dev_dbg(hd->parent, "interface id %d removed\n", interface_id); + gb_interface_remove(hd, interface_id); + break; + + default: + dev_err(hd->parent, + "Received invalid hotplug message type %d\n", + hotplug->hotplug_event); + break; + } +} + +static void svc_power(struct svc_function_power *power, + int payload_length, struct greybus_host_device *hd) +{ + u8 interface_id = power->interface_id; + + /* + * The AP is only allowed to get a Battery Status message, not a Battery + * Status Request + */ + if (power->power_type != SVC_POWER_BATTERY_STATUS) { + dev_err(hd->parent, "Received invalid power type %d\n", + power->power_type); + return; + } + + /* + * As struct struct svc_function_power_battery_status_request is 0 bytes + * big, we can just check the union of the whole structure to validate + * the size of this message. + */ + if (payload_length != sizeof(*power)) { + dev_err(hd->parent, + "Illegal size of svc power message %d\n", + payload_length); + return; + } + + dev_dbg(hd->parent, "power status for interface id %d is %d\n", + interface_id, power->status.status); + + // FIXME - do something with the power information, like update our + // battery information... +} + +static void svc_epm(struct svc_function_epm *epm, + int payload_length, struct greybus_host_device *hd) +{ + /* What? An AP should not get this message */ + dev_err(hd->parent, "Got an EPM message???\n"); +} + +static void svc_suspend(struct svc_function_suspend *suspend, + int payload_length, struct greybus_host_device *hd) +{ + /* What? An AP should not get this message */ + dev_err(hd->parent, "Got an suspend message???\n"); +} + +static struct svc_msg *convert_ap_message(struct ap_msg *ap_msg) +{ + struct svc_msg *svc_msg; + struct svc_msg_header *header; + struct greybus_host_device *hd = ap_msg->hd; + + svc_msg = (struct svc_msg *)ap_msg->data; + header = &svc_msg->header; + + /* Validate the message type */ + if (header->message_type != SVC_MSG_DATA) { + dev_err(hd->parent, "message type %d received?\n", + header->message_type); + return NULL; + } + + /* + * The validation of the size of the message buffer happens in each + * svc_* function, due to the different types of messages, keeping the + * logic for each message only in one place. + */ + + return svc_msg; +} + +static void ap_process_event(struct work_struct *work) +{ + struct svc_msg *svc_msg; + struct greybus_host_device *hd; + struct ap_msg *ap_msg; + int payload_length; + + ap_msg = container_of(work, struct ap_msg, event); + hd = ap_msg->hd; + + /* Turn the "raw" data into a real message */ + svc_msg = convert_ap_message(ap_msg); + if (!svc_msg) + return; + + payload_length = le16_to_cpu(svc_msg->header.payload_length); + + /* Look at the message to figure out what to do with it */ + switch (svc_msg->header.function_id) { + case SVC_FUNCTION_HANDSHAKE: + svc_handshake(&svc_msg->handshake, payload_length, hd); + break; + case SVC_FUNCTION_UNIPRO_NETWORK_MANAGEMENT: + svc_management(&svc_msg->management, payload_length, hd); + break; + case SVC_FUNCTION_HOTPLUG: + svc_hotplug(&svc_msg->hotplug, payload_length, hd); + break; + case SVC_FUNCTION_POWER: + svc_power(&svc_msg->power, payload_length, hd); + break; + case SVC_FUNCTION_EPM: + svc_epm(&svc_msg->epm, payload_length, hd); + break; + case SVC_FUNCTION_SUSPEND: + svc_suspend(&svc_msg->suspend, payload_length, hd); + break; + default: + dev_err(hd->parent, "received invalid SVC function ID %d\n", + svc_msg->header.function_id); + } + + /* clean the message up */ + kfree(ap_msg->data); + kfree(ap_msg); +} + +int greybus_svc_in(struct greybus_host_device *hd, u8 *data, int size) +{ + struct ap_msg *ap_msg; + + /* + * Totally naive copy the message into a new structure that we slowly + * create and add it to the list. Let's get this working, the odds of + * this being any "slow path" for AP messages is really low at this + * point in time, but you never know, so this comment is here to point + * out that maybe we should use a slab allocator, or even just not copy + * the data, but use it directly and force the urbs to be "new" each + * time. + */ + + /* Note - this can, and will, be called in interrupt context. */ + ap_msg = kmalloc(sizeof(*ap_msg), GFP_ATOMIC); + if (!ap_msg) + return -ENOMEM; + ap_msg->data = kmalloc(size, GFP_ATOMIC); + if (!ap_msg->data) { + kfree(ap_msg); + return -ENOMEM; + } + memcpy(ap_msg->data, data, size); + ap_msg->size = size; + ap_msg->hd = hd; + + INIT_WORK(&ap_msg->event, ap_process_event); + queue_work(ap_workqueue, &ap_msg->event); + + return 0; +} +EXPORT_SYMBOL_GPL(greybus_svc_in); + +int __init gb_ap_init(void) +{ + ap_workqueue = alloc_ordered_workqueue("greybus_ap", 0); + if (!ap_workqueue) + return -ENOMEM; + + return 0; +} + +void gb_ap_exit(void) +{ + destroy_workqueue(ap_workqueue); + ap_workqueue = NULL; +} + + diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 1a657f70..b32da8a 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -251,12 +251,7 @@ gb_connection_create_range(struct greybus_host_device *hd, spin_unlock_irq(&gb_connections_lock); - if (hd_cport_id != GB_SVC_CPORT_ID) { - gb_svc_connection_create(hd->svc, - hd->endo->ap_intf_id, hd_cport_id, - bundle->intf->interface_id, cport_id); - } - + /* XXX Will have to establish connections to get version */ gb_connection_bind_protocol(connection); if (!connection->protocol) dev_warn(&connection->dev, diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 9f105fb..225fa4f 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -176,7 +176,8 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver * Validate that the driver implements all of the callbacks * so that we don't have to every time we make them. */ - if ((!driver->message_send) || (!driver->message_cancel)) { + if ((!driver->message_send) || (!driver->message_cancel) || + (!driver->submit_svc)) { pr_err("Must implement all greybus_host_driver callbacks!\n"); return ERR_PTR(-EINVAL); } @@ -208,21 +209,6 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver ida_init(&hd->cport_id_map); hd->buffer_size_max = buffer_size_max; - /* - * Initialize AP's SVC protocol connection: - * - * This is required as part of early initialization of the host device - * as we need this connection in order to start any kind of message - * exchange between the AP and the SVC. SVC will start with a - * 'get-version' request followed by a 'svc-hello' message and at that - * time we will create a fully initialized svc-connection, as we need - * endo-id and AP's interface id for that. - */ - if (!gb_ap_svc_connection_create(hd)) { - kref_put_mutex(&hd->kref, free_hd, &hd_mutex); - return ERR_PTR(-ENOMEM); - } - return hd; } EXPORT_SYMBOL_GPL(greybus_create_hd); @@ -284,6 +270,12 @@ static int __init gb_init(void) goto error_bus; } + retval = gb_ap_init(); + if (retval) { + pr_err("gb_ap_init failed (%d)\n", retval); + goto error_ap; + } + retval = gb_operation_init(); if (retval) { pr_err("gb_operation_init failed (%d)\n", retval); @@ -317,6 +309,8 @@ error_control: error_endo: gb_operation_exit(); error_operation: + gb_ap_exit(); +error_ap: bus_unregister(&greybus_bus_type); error_bus: gb_debugfs_cleanup(); @@ -331,6 +325,7 @@ static void __exit gb_exit(void) gb_control_protocol_exit(); gb_endo_exit(); gb_operation_exit(); + gb_ap_exit(); bus_unregister(&greybus_bus_type); gb_debugfs_cleanup(); } diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index c1fab37..0cb7a3c 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -14,9 +14,11 @@ #include #include "greybus.h" +#include "svc_msg.h" #include "kernel_ver.h" /* Memory sizes for the buffers sent to/from the ES1 controller */ +#define ES1_SVC_MSG_SIZE (sizeof(struct svc_msg) + SZ_64K) #define ES1_GBUF_MSG_SIZE_MAX 2048 static const struct usb_device_id id_table[] = { @@ -56,8 +58,11 @@ static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); * @usb_intf: pointer to the USB interface we are bound to. * @hd: pointer to our greybus_host_device structure * @control_endpoint: endpoint to send data to SVC + * @svc_endpoint: endpoint for SVC data in * @cport_in_endpoint: bulk in endpoint for CPort data * @cport-out_endpoint: bulk out endpoint for CPort data + * @svc_buffer: buffer for SVC messages coming in on @svc_endpoint + * @svc_urb: urb for SVC messages coming in on @svc_endpoint * @cport_in_urb: array of urbs for the CPort in messages * @cport_in_buffer: array of buffers for the @cport_in_urb urbs * @cport_out_urb: array of urbs for the CPort out messages @@ -73,9 +78,13 @@ struct es1_ap_dev { struct greybus_host_device *hd; __u8 control_endpoint; + __u8 svc_endpoint; __u8 cport_in_endpoint; __u8 cport_out_endpoint; + u8 *svc_buffer; + struct urb *svc_urb; + struct urb *cport_in_urb[NUM_CPORT_IN_URB]; u8 *cport_in_buffer[NUM_CPORT_IN_URB]; struct urb *cport_out_urb[NUM_CPORT_OUT_URB]; @@ -94,6 +103,26 @@ static void usb_log_enable(struct es1_ap_dev *es1); static void usb_log_disable(struct es1_ap_dev *es1); #define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ +static int submit_svc(struct svc_msg *svc_msg, struct greybus_host_device *hd) +{ + struct es1_ap_dev *es1 = hd_to_es1(hd); + int retval; + + /* SVC messages go down our control pipe */ + retval = usb_control_msg(es1->usb_dev, + usb_sndctrlpipe(es1->usb_dev, + es1->control_endpoint), + REQUEST_SVC, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + 0x00, 0x00, + (char *)svc_msg, + sizeof(*svc_msg), + ES1_TIMEOUT); + if (retval != sizeof(*svc_msg)) + return retval; + + return 0; +} static struct urb *next_free_urb(struct es1_ap_dev *es1, gfp_t gfp_mask) { @@ -274,6 +303,7 @@ static struct greybus_host_driver es1_driver = { .hd_priv_size = sizeof(struct es1_ap_dev), .message_send = message_send, .message_cancel = message_cancel, + .submit_svc = submit_svc, }; /* Common function to report consistent warnings based on URB status */ @@ -337,6 +367,12 @@ static void ap_disconnect(struct usb_interface *interface) es1->cport_in_buffer[i] = NULL; } + usb_kill_urb(es1->svc_urb); + usb_free_urb(es1->svc_urb); + es1->svc_urb = NULL; + kfree(es1->svc_buffer); + es1->svc_buffer = NULL; + usb_set_intfdata(interface, NULL); udev = es1->usb_dev; greybus_remove_hd(es1->hd); @@ -344,6 +380,33 @@ static void ap_disconnect(struct usb_interface *interface) usb_put_dev(udev); } +/* Callback for when we get a SVC message */ +static void svc_in_callback(struct urb *urb) +{ + struct greybus_host_device *hd = urb->context; + struct device *dev = &urb->dev->dev; + int status = check_urb_status(urb); + int retval; + + if (status) { + if ((status == -EAGAIN) || (status == -EPROTO)) + goto exit; + dev_err(dev, "urb svc in error %d (dropped)\n", status); + return; + } + + /* We have a message, create a new message structure, add it to the + * list, and wake up our thread that will process the messages. + */ + greybus_svc_in(hd, urb->transfer_buffer, urb->actual_length); + +exit: + /* resubmit the urb to get more messages */ + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) + dev_err(dev, "Can not submit urb for AP data: %d\n", retval); +} + static void cport_in_callback(struct urb *urb) { struct greybus_host_device *hd = urb->context; @@ -547,10 +610,14 @@ static int ap_probe(struct usb_interface *interface, struct usb_device *udev; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; + bool int_in_found = false; bool bulk_in_found = false; bool bulk_out_found = false; int retval = -ENOMEM; int i; + u16 endo_id = 0x4755; // FIXME - get endo "ID" from the SVC + u8 ap_intf_id = 0x01; // FIXME - get endo "ID" from the SVC + u8 svc_interval = 0; /* We need to fit a CPort ID in one byte of a message header */ BUILD_BUG_ON(CPORT_ID_MAX > U8_MAX); @@ -579,7 +646,11 @@ static int ap_probe(struct usb_interface *interface, for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; - if (usb_endpoint_is_bulk_in(endpoint)) { + if (usb_endpoint_is_int_in(endpoint)) { + es1->svc_endpoint = endpoint->bEndpointAddress; + svc_interval = endpoint->bInterval; + int_in_found = true; + } else if (usb_endpoint_is_bulk_in(endpoint)) { es1->cport_in_endpoint = endpoint->bEndpointAddress; bulk_in_found = true; } else if (usb_endpoint_is_bulk_out(endpoint)) { @@ -591,12 +662,27 @@ static int ap_probe(struct usb_interface *interface, endpoint->bEndpointAddress); } } - if ((bulk_in_found == false) || + if ((int_in_found == false) || + (bulk_in_found == false) || (bulk_out_found == false)) { dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n"); goto error; } + /* Create our buffer and URB to get SVC messages, and start it up */ + es1->svc_buffer = kmalloc(ES1_SVC_MSG_SIZE, GFP_KERNEL); + if (!es1->svc_buffer) + goto error; + + es1->svc_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!es1->svc_urb) + goto error; + + usb_fill_int_urb(es1->svc_urb, udev, + usb_rcvintpipe(udev, es1->svc_endpoint), + es1->svc_buffer, ES1_SVC_MSG_SIZE, svc_in_callback, + hd, svc_interval); + /* Allocate buffers for our cport in messages and start them up */ for (i = 0; i < NUM_CPORT_IN_URB; ++i) { struct urb *urb; @@ -632,6 +718,22 @@ static int ap_probe(struct usb_interface *interface, es1->cport_out_urb_busy[i] = false; /* just to be anal */ } + /* + * XXX Soon this will be initiated later, with a combination + * XXX of a Control protocol probe operation and a + * XXX subsequent Control protocol connected operation for + * XXX the SVC connection. At that point we know we're + * XXX properly connected to an Endo. + */ + retval = greybus_endo_setup(hd, endo_id, ap_intf_id); + if (retval) + goto error; + + /* Start up our svc urb, which allows events to start flowing */ + retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); + if (retval) + goto error; + apb1_log_enable_dentry = debugfs_create_file("apb1_log_enable", (S_IWUSR | S_IRUGO), gb_debugfs_get(), es1, diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 558345c..323721a 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -14,9 +14,11 @@ #include #include "greybus.h" +#include "svc_msg.h" #include "kernel_ver.h" /* Memory sizes for the buffers sent to/from the ES1 controller */ +#define ES1_SVC_MSG_SIZE (sizeof(struct svc_msg) + SZ_64K) #define ES1_GBUF_MSG_SIZE_MAX 2048 static const struct usb_device_id id_table[] = { @@ -83,7 +85,10 @@ struct es1_cport_out { * @usb_intf: pointer to the USB interface we are bound to. * @hd: pointer to our greybus_host_device structure * @control_endpoint: endpoint to send data to SVC + * @svc_endpoint: endpoint for SVC data in + * @svc_buffer: buffer for SVC messages coming in on @svc_endpoint + * @svc_urb: urb for SVC messages coming in on @svc_endpoint * @cport_in: endpoint, urbs and buffer for cport in messages * @cport_out: endpoint for for cport out messages * @cport_out_urb: array of urbs for the CPort out messages @@ -99,6 +104,10 @@ struct es1_ap_dev { struct greybus_host_device *hd; __u8 control_endpoint; + __u8 svc_endpoint; + + u8 *svc_buffer; + struct urb *svc_urb; struct es1_cport_in cport_in[NUM_BULKS]; struct es1_cport_out cport_out[NUM_BULKS]; @@ -133,6 +142,26 @@ static int cport_to_ep(struct es1_ap_dev *es1, u16 cport_id) } #define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ +static int submit_svc(struct svc_msg *svc_msg, struct greybus_host_device *hd) +{ + struct es1_ap_dev *es1 = hd_to_es1(hd); + int retval; + + /* SVC messages go down our control pipe */ + retval = usb_control_msg(es1->usb_dev, + usb_sndctrlpipe(es1->usb_dev, + es1->control_endpoint), + REQUEST_SVC, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + 0x00, 0x00, + (char *)svc_msg, + sizeof(*svc_msg), + ES1_TIMEOUT); + if (retval != sizeof(*svc_msg)) + return retval; + + return 0; +} static int ep_in_use(struct es1_ap_dev *es1, int bulk_ep_set) { @@ -370,6 +399,7 @@ static struct greybus_host_driver es1_driver = { .hd_priv_size = sizeof(struct es1_ap_dev), .message_send = message_send, .message_cancel = message_cancel, + .submit_svc = submit_svc, }; /* Common function to report consistent warnings based on URB status */ @@ -437,6 +467,12 @@ static void ap_disconnect(struct usb_interface *interface) } } + usb_kill_urb(es1->svc_urb); + usb_free_urb(es1->svc_urb); + es1->svc_urb = NULL; + kfree(es1->svc_buffer); + es1->svc_buffer = NULL; + usb_set_intfdata(interface, NULL); udev = es1->usb_dev; greybus_remove_hd(es1->hd); @@ -444,6 +480,33 @@ static void ap_disconnect(struct usb_interface *interface) usb_put_dev(udev); } +/* Callback for when we get a SVC message */ +static void svc_in_callback(struct urb *urb) +{ + struct greybus_host_device *hd = urb->context; + struct device *dev = &urb->dev->dev; + int status = check_urb_status(urb); + int retval; + + if (status) { + if ((status == -EAGAIN) || (status == -EPROTO)) + goto exit; + dev_err(dev, "urb svc in error %d (dropped)\n", status); + return; + } + + /* We have a message, create a new message structure, add it to the + * list, and wake up our thread that will process the messages. + */ + greybus_svc_in(hd, urb->transfer_buffer, urb->actual_length); + +exit: + /* resubmit the urb to get more messages */ + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) + dev_err(dev, "Can not submit urb for AP data: %d\n", retval); +} + static void cport_in_callback(struct urb *urb) { struct greybus_host_device *hd = urb->context; @@ -647,10 +710,14 @@ static int ap_probe(struct usb_interface *interface, struct usb_device *udev; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; + bool int_in_found = false; int bulk_in = 0; int bulk_out = 0; int retval = -ENOMEM; int i; + u16 endo_id = 0x4755; // FIXME - get endo "ID" from the SVC + u8 ap_intf_id = 0x01; // FIXME - get endo "ID" from the SVC + u8 svc_interval = 0; /* We need to fit a CPort ID in one byte of a message header */ BUILD_BUG_ON(CPORT_ID_MAX > U8_MAX); @@ -679,7 +746,11 @@ static int ap_probe(struct usb_interface *interface, for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; - if (usb_endpoint_is_bulk_in(endpoint)) { + if (usb_endpoint_is_int_in(endpoint)) { + es1->svc_endpoint = endpoint->bEndpointAddress; + svc_interval = endpoint->bInterval; + int_in_found = true; + } else if (usb_endpoint_is_bulk_in(endpoint)) { es1->cport_in[bulk_in++].endpoint = endpoint->bEndpointAddress; } else if (usb_endpoint_is_bulk_out(endpoint)) { @@ -691,12 +762,27 @@ static int ap_probe(struct usb_interface *interface, endpoint->bEndpointAddress); } } - if ((bulk_in == 0) || + if ((int_in_found == false) || + (bulk_in == 0) || (bulk_out == 0)) { dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n"); goto error; } + /* Create our buffer and URB to get SVC messages, and start it up */ + es1->svc_buffer = kmalloc(ES1_SVC_MSG_SIZE, GFP_KERNEL); + if (!es1->svc_buffer) + goto error; + + es1->svc_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!es1->svc_urb) + goto error; + + usb_fill_int_urb(es1->svc_urb, udev, + usb_rcvintpipe(udev, es1->svc_endpoint), + es1->svc_buffer, ES1_SVC_MSG_SIZE, svc_in_callback, + hd, svc_interval); + /* Allocate buffers for our cport in messages and start them up */ for (bulk_in = 0; bulk_in < NUM_BULKS; bulk_in++) { struct es1_cport_in *cport_in = &es1->cport_in[bulk_in]; @@ -736,6 +822,22 @@ static int ap_probe(struct usb_interface *interface, es1->cport_out_urb_busy[i] = false; /* just to be anal */ } + /* + * XXX Soon this will be initiated later, with a combination + * XXX of a Control protocol probe operation and a + * XXX subsequent Control protocol connected operation for + * XXX the SVC connection. At that point we know we're + * XXX properly connected to an Endo. + */ + retval = greybus_endo_setup(hd, endo_id, ap_intf_id); + if (retval) + goto error; + + /* Start up our svc urb, which allows events to start flowing */ + retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); + if (retval) + goto error; + apb1_log_enable_dentry = debugfs_create_file("apb1_log_enable", (S_IWUSR | S_IRUGO), gb_debugfs_get(), es1, diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index cdade1e..2214f44 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -73,6 +73,7 @@ */ struct greybus_host_device; +struct svc_msg; /* Greybus "Host driver" structure, needed by a host controller driver to be * able to handle both SVC control as well as "real" greybus messages @@ -83,6 +84,8 @@ struct greybus_host_driver { int (*message_send)(struct greybus_host_device *hd, u16 dest_cport_id, struct gb_message *message, gfp_t gfp_mask); void (*message_cancel)(struct gb_message *message); + int (*submit_svc)(struct svc_msg *svc_msg, + struct greybus_host_device *hd); }; struct greybus_host_device { @@ -100,7 +103,6 @@ struct greybus_host_device { struct gb_endo *endo; struct gb_connection *initial_svc_connection; - struct gb_svc *svc; /* Private data for the host driver */ unsigned long hd_priv[0] __aligned(sizeof(s64)); @@ -153,6 +155,9 @@ void greybus_deregister_driver(struct greybus_driver *driver); int greybus_disabled(void); +int greybus_svc_in(struct greybus_host_device *hd, u8 *data, int length); +int gb_ap_init(void); +void gb_ap_exit(void); void gb_debugfs_init(void); void gb_debugfs_cleanup(void); struct dentry *gb_debugfs_get(void); diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index e2d38df..61fe9dc 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -64,9 +64,9 @@ * CONTROL and SVC protocols for communication between AP and SVC. */ #define GB_SVC_BUNDLE_ID 0 -#define GB_SVC_CPORT_ID 0 +#define GB_SVC_CPORT_ID 2 #define GB_CONTROL_BUNDLE_ID 0 -#define GB_CONTROL_CPORT_ID 0 +#define GB_CONTROL_CPORT_ID 2 /* Control Protocol */ @@ -563,7 +563,6 @@ struct gb_spi_transfer_response { #define GB_SVC_TYPE_INTF_RESET 0x06 #define GB_SVC_TYPE_CONN_CREATE 0x07 #define GB_SVC_TYPE_CONN_DESTROY 0x08 -#define GB_SVC_TYPE_ROUTE_CREATE 0x0b /* SVC version request/response have same payload as gb_protocol_version_response */ @@ -606,8 +605,6 @@ struct gb_svc_conn_create_request { __u16 cport1_id; __u8 intf2_id; __u16 cport2_id; - __u8 tc; - __u8 flags; }; /* connection create response has no payload */ @@ -619,13 +616,6 @@ struct gb_svc_conn_destroy_request { }; /* connection destroy response has no payload */ -struct gb_svc_route_create_request { - __u8 intf1_id; - __u8 dev1_id; - __u8 intf2_id; - __u8 dev2_id; -}; - /* UART */ /* Version of the Greybus UART protocol we support */ diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 4a26bf6..f1e2956 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -183,7 +183,7 @@ put_module: /* * Tear down a previously set up module. */ -static void interface_destroy(struct gb_interface *intf) +void gb_interface_destroy(struct gb_interface *intf) { struct gb_module *module; struct gb_bundle *bundle; @@ -279,7 +279,7 @@ void gb_interface_remove(struct greybus_host_device *hd, u8 interface_id) struct gb_interface *intf = gb_interface_find(hd, interface_id); if (intf) - interface_destroy(intf); + gb_interface_destroy(intf); else dev_err(hd->parent, "interface id %d not found\n", interface_id); @@ -290,5 +290,5 @@ void gb_interfaces_remove(struct greybus_host_device *hd) struct gb_interface *intf, *temp; list_for_each_entry_safe(intf, temp, &hd->interfaces, links) - interface_destroy(intf); + gb_interface_destroy(intf); } diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 784b770..5f2b2b4 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -9,10 +9,6 @@ #include "greybus.h" -#define CPORT_FLAGS_E2EFC (1) -#define CPORT_FLAGS_CSD_N (2) -#define CPORT_FLAGS_CSV_N (4) - struct gb_svc { struct gb_connection *connection; u8 version_major; @@ -40,6 +36,7 @@ gb_ap_svc_connection_create(struct greybus_host_device *hd) return connection; } +EXPORT_SYMBOL_GPL(gb_ap_svc_connection_create); /* * We know endo-type and AP's interface id now, lets create a proper svc @@ -101,12 +98,6 @@ static int connection_create_operation(struct gb_svc *svc, request.cport1_id = cport1_id; request.intf2_id = intf2_id; request.cport2_id = cport2_id; - /* - * XXX: fix connections paramaters to TC0 and all CPort flags - * for now. - */ - request.tc = 0; - request.flags = CPORT_FLAGS_CSV_N | CPORT_FLAGS_E2EFC; return gb_operation_sync(svc->connection, GB_SVC_TYPE_CONN_CREATE, &request, sizeof(request), NULL, 0); @@ -127,20 +118,6 @@ static int connection_destroy_operation(struct gb_svc *svc, &request, sizeof(request), NULL, 0); } -static int route_create_operation(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, - u8 intf2_id, u8 dev2_id) -{ - struct gb_svc_route_create_request request; - - request.intf1_id = intf1_id; - request.dev1_id = dev1_id; - request.intf2_id = intf2_id; - request.dev2_id = dev2_id; - - return gb_operation_sync(svc->connection, GB_SVC_TYPE_ROUTE_CREATE, - &request, sizeof(request), NULL, 0); -} - int gb_svc_intf_device_id(struct gb_svc *svc, u8 intf_id, u8 device_id) { return intf_device_id_operation(svc, intf_id, device_id); @@ -171,13 +148,6 @@ int gb_svc_connection_destroy(struct gb_svc *svc, } EXPORT_SYMBOL_GPL(gb_svc_connection_destroy); -int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, - u8 intf2_id, u8 dev2_id) { - return route_create_operation(svc, intf1_id, dev1_id, - intf2_id, dev2_id); -} -EXPORT_SYMBOL_GPL(gb_svc_route_create); - static int gb_svc_version_request(struct gb_operation *op) { struct gb_connection *connection = op->connection; @@ -318,25 +288,6 @@ static int gb_svc_intf_hotplug_recv(struct gb_operation *op) goto ida_put; } - /* - * Create a two-way route between the AP and the new interface - */ - ret = route_create_operation(svc, hd->endo->ap_intf_id, - GB_DEVICE_ID_AP, intf_id, device_id); - if (ret) { - dev_err(dev, "%s: Route create operation failed, interface %hhu device_id %hhu (%d)\n", - __func__, intf_id, device_id, ret); - goto ida_put; - } - - ret = route_create_operation(svc, intf_id, device_id, - hd->endo->ap_intf_id, GB_DEVICE_ID_AP); - if (ret) { - dev_err(dev, "%s: Route create operation failed, interface %hhu device_id %hhu (%d)\n", - __func__, intf_id, device_id, ret); - goto ida_put; - } - ret = gb_interface_init(intf, device_id); if (ret) { dev_err(dev, "%s: Failed to initialize interface, interface %hhu device_id %hhu (%d)\n", @@ -439,7 +390,6 @@ static int gb_svc_connection_init(struct gb_connection *connection) if (!svc) return -ENOMEM; - connection->hd->svc = svc; svc->connection = connection; connection->private = svc; @@ -455,7 +405,6 @@ static void gb_svc_connection_exit(struct gb_connection *connection) { struct gb_svc *svc = connection->private; - connection->hd->svc = NULL; connection->private = NULL; kfree(svc); } diff --git a/drivers/staging/greybus/svc_msg.h b/drivers/staging/greybus/svc_msg.h new file mode 100644 index 0000000..3c628c5 --- /dev/null +++ b/drivers/staging/greybus/svc_msg.h @@ -0,0 +1,157 @@ +/* + * Greybus AP <-> SVC message structure format. + * + * See "Greybus Application Protocol" document (version 0.1) for + * details on these values and structures. + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 and BSD license. + */ + +#ifndef __SVC_MSG_H +#define __SVC_MSG_H + +enum svc_function_id { + SVC_FUNCTION_HANDSHAKE = 0x00, + SVC_FUNCTION_UNIPRO_NETWORK_MANAGEMENT = 0x01, + SVC_FUNCTION_HOTPLUG = 0x02, + SVC_FUNCTION_POWER = 0x03, + SVC_FUNCTION_EPM = 0x04, + SVC_FUNCTION_SUSPEND = 0x05, +}; + +enum svc_msg_type { + SVC_MSG_DATA = 0x00, + SVC_MSG_ERROR = 0xff, +}; + +struct svc_msg_header { + __u8 function_id; /* enum svc_function_id */ + __u8 message_type; + __le16 payload_length; +} __packed; + +enum svc_function_handshake_type { + SVC_HANDSHAKE_SVC_HELLO = 0x00, + SVC_HANDSHAKE_AP_HELLO = 0x01, + SVC_HANDSHAKE_MODULE_HELLO = 0x02, +}; + +struct svc_function_handshake { + __u8 version_major; + __u8 version_minor; + __u8 handshake_type; /* enum svc_function_handshake_type */ +} __packed; + +struct svc_function_unipro_set_route { + __u8 device_id; +} __packed; + +struct svc_function_unipro_link_up { + __u8 interface_id; /* Interface id within the Endo */ + __u8 device_id; +} __packed; + +struct svc_function_ap_id { + __u8 interface_id; + __u8 device_id; +} __packed; + +enum svc_function_management_event { + SVC_MANAGEMENT_AP_ID = 0x00, + SVC_MANAGEMENT_LINK_UP = 0x01, + SVC_MANAGEMENT_SET_ROUTE = 0x02, +}; + +struct svc_function_unipro_management { + __u8 management_packet_type; /* enum svc_function_management_event */ + union { + struct svc_function_ap_id ap_id; + struct svc_function_unipro_link_up link_up; + struct svc_function_unipro_set_route set_route; + }; +} __packed; + +enum svc_function_hotplug_event { + SVC_HOTPLUG_EVENT = 0x00, + SVC_HOTUNPLUG_EVENT = 0x01, +}; + +struct svc_function_hotplug { + __u8 hotplug_event; /* enum svc_function_hotplug_event */ + __u8 interface_id; /* Interface id within the Endo */ +} __packed; + +enum svc_function_power_type { + SVC_POWER_BATTERY_STATUS = 0x00, + SVC_POWER_BATTERY_STATUS_REQUEST = 0x01, +}; + +enum svc_function_battery_status { + SVC_BATTERY_UNKNOWN = 0x00, + SVC_BATTERY_CHARGING = 0x01, + SVC_BATTERY_DISCHARGING = 0x02, + SVC_BATTERY_NOT_CHARGING = 0x03, + SVC_BATTERY_FULL = 0x04, +}; + +struct svc_function_power_battery_status { + __le16 charge_full; + __le16 charge_now; + __u8 status; /* enum svc_function_battery_status */ +} __packed; + +struct svc_function_power_battery_status_request { +} __packed; + +/* XXX + * Each interface carries power, so it's possible these things + * are associated with each UniPro device and not just the module. + * For now it's safe to assume it's per-module. + */ +struct svc_function_power { + __u8 power_type; /* enum svc_function_power_type */ + __u8 interface_id; + union { + struct svc_function_power_battery_status status; + struct svc_function_power_battery_status_request request; + }; +} __packed; + +enum svc_function_epm_command_type { + SVC_EPM_ENABLE = 0x00, + SVC_EPM_DISABLE = 0x01, +}; + +/* EPM's are associated with the module */ +struct svc_function_epm { + __u8 epm_command_type; /* enum svc_function_epm_command_type */ + __u8 module_id; +} __packed; + +enum svc_function_suspend_command_type { + SVC_SUSPEND_FIXME_1 = 0x00, // FIXME + SVC_SUSPEND_FIXME_2 = 0x01, +}; + +/* We'll want independent control for multi-interface modules */ +struct svc_function_suspend { + __u8 suspend_command_type; /* enum function_suspend_command_type */ + __u8 device_id; +} __packed; + +struct svc_msg { + struct svc_msg_header header; + union { + struct svc_function_handshake handshake; + struct svc_function_unipro_management management; + struct svc_function_hotplug hotplug; + struct svc_function_power power; + struct svc_function_epm epm; + struct svc_function_suspend suspend; + }; +} __packed; + +#endif /* __SVC_MSG_H */ -- cgit v0.10.2 From 619dccd27b4a9747a42d8dc3e2ed32e32cf29f8a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 24 Jul 2015 15:32:23 +0530 Subject: greybus: es1/2: Lets start using svc protocol All bits and pieces are in place now. Lets start using svc protocol instead of stuff present in ap.c. Signed-off-by: Viresh Kumar Tested-by: Perry Hung Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 0cb7a3c..7d764a5 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -615,8 +615,6 @@ static int ap_probe(struct usb_interface *interface, bool bulk_out_found = false; int retval = -ENOMEM; int i; - u16 endo_id = 0x4755; // FIXME - get endo "ID" from the SVC - u8 ap_intf_id = 0x01; // FIXME - get endo "ID" from the SVC u8 svc_interval = 0; /* We need to fit a CPort ID in one byte of a message header */ @@ -718,16 +716,11 @@ static int ap_probe(struct usb_interface *interface, es1->cport_out_urb_busy[i] = false; /* just to be anal */ } - /* - * XXX Soon this will be initiated later, with a combination - * XXX of a Control protocol probe operation and a - * XXX subsequent Control protocol connected operation for - * XXX the SVC connection. At that point we know we're - * XXX properly connected to an Endo. - */ - retval = greybus_endo_setup(hd, endo_id, ap_intf_id); - if (retval) + /* Initialize AP's greybus interface */ + if (!gb_ap_svc_connection_create(hd)) { + retval = -EINVAL; goto error; + } /* Start up our svc urb, which allows events to start flowing */ retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 323721a..7621e95 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -715,8 +715,6 @@ static int ap_probe(struct usb_interface *interface, int bulk_out = 0; int retval = -ENOMEM; int i; - u16 endo_id = 0x4755; // FIXME - get endo "ID" from the SVC - u8 ap_intf_id = 0x01; // FIXME - get endo "ID" from the SVC u8 svc_interval = 0; /* We need to fit a CPort ID in one byte of a message header */ @@ -822,16 +820,11 @@ static int ap_probe(struct usb_interface *interface, es1->cport_out_urb_busy[i] = false; /* just to be anal */ } - /* - * XXX Soon this will be initiated later, with a combination - * XXX of a Control protocol probe operation and a - * XXX subsequent Control protocol connected operation for - * XXX the SVC connection. At that point we know we're - * XXX properly connected to an Endo. - */ - retval = greybus_endo_setup(hd, endo_id, ap_intf_id); - if (retval) + /* Initialize AP's greybus interface */ + if (!gb_ap_svc_connection_create(hd)) { + retval = -EINVAL; goto error; + } /* Start up our svc urb, which allows events to start flowing */ retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); -- cgit v0.10.2 From ef5d949a8b4eb311d60f38afb83c2c135d785b8a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 24 Jul 2015 15:32:24 +0530 Subject: greybus: Switch to Cport 0 for svc and control protocol Initially we fixed it to Cport 2, but its changed to Cport 0 now. Lets switch that in code as well. Signed-off-by: Viresh Kumar Tested-by: Perry Hung Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 61fe9dc..9708e93 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -64,9 +64,9 @@ * CONTROL and SVC protocols for communication between AP and SVC. */ #define GB_SVC_BUNDLE_ID 0 -#define GB_SVC_CPORT_ID 2 +#define GB_SVC_CPORT_ID 0 #define GB_CONTROL_BUNDLE_ID 0 -#define GB_CONTROL_CPORT_ID 2 +#define GB_CONTROL_CPORT_ID 0 /* Control Protocol */ -- cgit v0.10.2 From 1a95812d4656817ded72bba50c74020b5b21589f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 24 Jul 2015 16:47:07 -0700 Subject: greybus: es1: remove svc endpoint message handling We have switched over to use the "new" svc messages, no more need to have a special USB endpoint to handle them, they come through the normal CPort messages. Based on a patch from Viresh. Tested-by: Viresh Kumar Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 7d764a5..82a7c67 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -18,7 +18,6 @@ #include "kernel_ver.h" /* Memory sizes for the buffers sent to/from the ES1 controller */ -#define ES1_SVC_MSG_SIZE (sizeof(struct svc_msg) + SZ_64K) #define ES1_GBUF_MSG_SIZE_MAX 2048 static const struct usb_device_id id_table[] = { @@ -58,11 +57,8 @@ static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); * @usb_intf: pointer to the USB interface we are bound to. * @hd: pointer to our greybus_host_device structure * @control_endpoint: endpoint to send data to SVC - * @svc_endpoint: endpoint for SVC data in * @cport_in_endpoint: bulk in endpoint for CPort data * @cport-out_endpoint: bulk out endpoint for CPort data - * @svc_buffer: buffer for SVC messages coming in on @svc_endpoint - * @svc_urb: urb for SVC messages coming in on @svc_endpoint * @cport_in_urb: array of urbs for the CPort in messages * @cport_in_buffer: array of buffers for the @cport_in_urb urbs * @cport_out_urb: array of urbs for the CPort out messages @@ -78,13 +74,9 @@ struct es1_ap_dev { struct greybus_host_device *hd; __u8 control_endpoint; - __u8 svc_endpoint; __u8 cport_in_endpoint; __u8 cport_out_endpoint; - u8 *svc_buffer; - struct urb *svc_urb; - struct urb *cport_in_urb[NUM_CPORT_IN_URB]; u8 *cport_in_buffer[NUM_CPORT_IN_URB]; struct urb *cport_out_urb[NUM_CPORT_OUT_URB]; @@ -367,12 +359,6 @@ static void ap_disconnect(struct usb_interface *interface) es1->cport_in_buffer[i] = NULL; } - usb_kill_urb(es1->svc_urb); - usb_free_urb(es1->svc_urb); - es1->svc_urb = NULL; - kfree(es1->svc_buffer); - es1->svc_buffer = NULL; - usb_set_intfdata(interface, NULL); udev = es1->usb_dev; greybus_remove_hd(es1->hd); @@ -380,33 +366,6 @@ static void ap_disconnect(struct usb_interface *interface) usb_put_dev(udev); } -/* Callback for when we get a SVC message */ -static void svc_in_callback(struct urb *urb) -{ - struct greybus_host_device *hd = urb->context; - struct device *dev = &urb->dev->dev; - int status = check_urb_status(urb); - int retval; - - if (status) { - if ((status == -EAGAIN) || (status == -EPROTO)) - goto exit; - dev_err(dev, "urb svc in error %d (dropped)\n", status); - return; - } - - /* We have a message, create a new message structure, add it to the - * list, and wake up our thread that will process the messages. - */ - greybus_svc_in(hd, urb->transfer_buffer, urb->actual_length); - -exit: - /* resubmit the urb to get more messages */ - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - dev_err(dev, "Can not submit urb for AP data: %d\n", retval); -} - static void cport_in_callback(struct urb *urb) { struct greybus_host_device *hd = urb->context; @@ -610,12 +569,10 @@ static int ap_probe(struct usb_interface *interface, struct usb_device *udev; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; - bool int_in_found = false; bool bulk_in_found = false; bool bulk_out_found = false; int retval = -ENOMEM; int i; - u8 svc_interval = 0; /* We need to fit a CPort ID in one byte of a message header */ BUILD_BUG_ON(CPORT_ID_MAX > U8_MAX); @@ -644,11 +601,7 @@ static int ap_probe(struct usb_interface *interface, for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; - if (usb_endpoint_is_int_in(endpoint)) { - es1->svc_endpoint = endpoint->bEndpointAddress; - svc_interval = endpoint->bInterval; - int_in_found = true; - } else if (usb_endpoint_is_bulk_in(endpoint)) { + if (usb_endpoint_is_bulk_in(endpoint)) { es1->cport_in_endpoint = endpoint->bEndpointAddress; bulk_in_found = true; } else if (usb_endpoint_is_bulk_out(endpoint)) { @@ -660,27 +613,12 @@ static int ap_probe(struct usb_interface *interface, endpoint->bEndpointAddress); } } - if ((int_in_found == false) || - (bulk_in_found == false) || + if ((bulk_in_found == false) || (bulk_out_found == false)) { dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n"); goto error; } - /* Create our buffer and URB to get SVC messages, and start it up */ - es1->svc_buffer = kmalloc(ES1_SVC_MSG_SIZE, GFP_KERNEL); - if (!es1->svc_buffer) - goto error; - - es1->svc_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!es1->svc_urb) - goto error; - - usb_fill_int_urb(es1->svc_urb, udev, - usb_rcvintpipe(udev, es1->svc_endpoint), - es1->svc_buffer, ES1_SVC_MSG_SIZE, svc_in_callback, - hd, svc_interval); - /* Allocate buffers for our cport in messages and start them up */ for (i = 0; i < NUM_CPORT_IN_URB; ++i) { struct urb *urb; @@ -722,11 +660,6 @@ static int ap_probe(struct usb_interface *interface, goto error; } - /* Start up our svc urb, which allows events to start flowing */ - retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); - if (retval) - goto error; - apb1_log_enable_dentry = debugfs_create_file("apb1_log_enable", (S_IWUSR | S_IRUGO), gb_debugfs_get(), es1, -- cgit v0.10.2 From b767ee402070ce467a2b8470706740b55dd3af21 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 24 Jul 2015 17:09:48 -0700 Subject: greybus: es2: remove svc endpoint message handling We have switched over to use the "new" svc messages, no more need to have a special USB endpoint to handle them, they come through the normal CPort messages. Based on a patch from Viresh. Tested-by: Viresh Kumar Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 7621e95..c353ca5 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -18,7 +18,6 @@ #include "kernel_ver.h" /* Memory sizes for the buffers sent to/from the ES1 controller */ -#define ES1_SVC_MSG_SIZE (sizeof(struct svc_msg) + SZ_64K) #define ES1_GBUF_MSG_SIZE_MAX 2048 static const struct usb_device_id id_table[] = { @@ -85,10 +84,7 @@ struct es1_cport_out { * @usb_intf: pointer to the USB interface we are bound to. * @hd: pointer to our greybus_host_device structure * @control_endpoint: endpoint to send data to SVC - * @svc_endpoint: endpoint for SVC data in - * @svc_buffer: buffer for SVC messages coming in on @svc_endpoint - * @svc_urb: urb for SVC messages coming in on @svc_endpoint * @cport_in: endpoint, urbs and buffer for cport in messages * @cport_out: endpoint for for cport out messages * @cport_out_urb: array of urbs for the CPort out messages @@ -104,10 +100,6 @@ struct es1_ap_dev { struct greybus_host_device *hd; __u8 control_endpoint; - __u8 svc_endpoint; - - u8 *svc_buffer; - struct urb *svc_urb; struct es1_cport_in cport_in[NUM_BULKS]; struct es1_cport_out cport_out[NUM_BULKS]; @@ -467,12 +459,6 @@ static void ap_disconnect(struct usb_interface *interface) } } - usb_kill_urb(es1->svc_urb); - usb_free_urb(es1->svc_urb); - es1->svc_urb = NULL; - kfree(es1->svc_buffer); - es1->svc_buffer = NULL; - usb_set_intfdata(interface, NULL); udev = es1->usb_dev; greybus_remove_hd(es1->hd); @@ -480,33 +466,6 @@ static void ap_disconnect(struct usb_interface *interface) usb_put_dev(udev); } -/* Callback for when we get a SVC message */ -static void svc_in_callback(struct urb *urb) -{ - struct greybus_host_device *hd = urb->context; - struct device *dev = &urb->dev->dev; - int status = check_urb_status(urb); - int retval; - - if (status) { - if ((status == -EAGAIN) || (status == -EPROTO)) - goto exit; - dev_err(dev, "urb svc in error %d (dropped)\n", status); - return; - } - - /* We have a message, create a new message structure, add it to the - * list, and wake up our thread that will process the messages. - */ - greybus_svc_in(hd, urb->transfer_buffer, urb->actual_length); - -exit: - /* resubmit the urb to get more messages */ - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - dev_err(dev, "Can not submit urb for AP data: %d\n", retval); -} - static void cport_in_callback(struct urb *urb) { struct greybus_host_device *hd = urb->context; @@ -710,12 +669,10 @@ static int ap_probe(struct usb_interface *interface, struct usb_device *udev; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; - bool int_in_found = false; int bulk_in = 0; int bulk_out = 0; int retval = -ENOMEM; int i; - u8 svc_interval = 0; /* We need to fit a CPort ID in one byte of a message header */ BUILD_BUG_ON(CPORT_ID_MAX > U8_MAX); @@ -744,11 +701,7 @@ static int ap_probe(struct usb_interface *interface, for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; - if (usb_endpoint_is_int_in(endpoint)) { - es1->svc_endpoint = endpoint->bEndpointAddress; - svc_interval = endpoint->bInterval; - int_in_found = true; - } else if (usb_endpoint_is_bulk_in(endpoint)) { + if (usb_endpoint_is_bulk_in(endpoint)) { es1->cport_in[bulk_in++].endpoint = endpoint->bEndpointAddress; } else if (usb_endpoint_is_bulk_out(endpoint)) { @@ -760,27 +713,12 @@ static int ap_probe(struct usb_interface *interface, endpoint->bEndpointAddress); } } - if ((int_in_found == false) || - (bulk_in == 0) || + if ((bulk_in == 0) || (bulk_out == 0)) { dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n"); goto error; } - /* Create our buffer and URB to get SVC messages, and start it up */ - es1->svc_buffer = kmalloc(ES1_SVC_MSG_SIZE, GFP_KERNEL); - if (!es1->svc_buffer) - goto error; - - es1->svc_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!es1->svc_urb) - goto error; - - usb_fill_int_urb(es1->svc_urb, udev, - usb_rcvintpipe(udev, es1->svc_endpoint), - es1->svc_buffer, ES1_SVC_MSG_SIZE, svc_in_callback, - hd, svc_interval); - /* Allocate buffers for our cport in messages and start them up */ for (bulk_in = 0; bulk_in < NUM_BULKS; bulk_in++) { struct es1_cport_in *cport_in = &es1->cport_in[bulk_in]; @@ -826,11 +764,6 @@ static int ap_probe(struct usb_interface *interface, goto error; } - /* Start up our svc urb, which allows events to start flowing */ - retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL); - if (retval) - goto error; - apb1_log_enable_dentry = debugfs_create_file("apb1_log_enable", (S_IWUSR | S_IRUGO), gb_debugfs_get(), es1, -- cgit v0.10.2 From 38e7b48b0c2e9c3fe2831d824466dc52d1393e7c Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 24 Jul 2015 15:32:26 +0530 Subject: greybus: get rid of old svc-protocol Its not used anymore as we have more sophisticated svc protocol in place, lets get rid of earlier code. Signed-off-by: Viresh Kumar Tested-by: Perry Hung Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 1467c5b..d14bf4d 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -1,6 +1,5 @@ greybus-y := core.o \ debugfs.o \ - ap.o \ manifest.o \ endo.o \ module.o \ diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c deleted file mode 100644 index fc23817..0000000 --- a/drivers/staging/greybus/ap.c +++ /dev/null @@ -1,351 +0,0 @@ -/* - * Greybus "AP" message loop handling - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include "svc_msg.h" -#include "greybus_manifest.h" -#include "greybus.h" - -struct ap_msg { - u8 *data; - size_t size; - struct greybus_host_device *hd; - struct work_struct event; -}; - -static struct workqueue_struct *ap_workqueue; - -static struct svc_msg *svc_msg_alloc(enum svc_function_id id) -{ - struct svc_msg *svc_msg; - - svc_msg = kzalloc((sizeof *svc_msg), GFP_KERNEL); - if (!svc_msg) - return NULL; - - // FIXME - verify we are only sending function IDs we should be - svc_msg->header.function_id = id; - return svc_msg; -} - -static void svc_msg_free(struct svc_msg *svc_msg) -{ - kfree(svc_msg); -} - -static int svc_msg_send(struct svc_msg *svc_msg, struct greybus_host_device *hd) -{ - int retval; - - // FIXME - Do we need to do more than just pass it to the hd and then - // free it? - retval = hd->driver->submit_svc(svc_msg, hd); - - svc_msg_free(svc_msg); - return retval; -} - -static void svc_handshake(struct svc_function_handshake *handshake, - int payload_length, struct greybus_host_device *hd) -{ - struct svc_msg *svc_msg; - - if (payload_length != sizeof(*handshake)) { - dev_err(hd->parent, - "Illegal size of svc handshake message %d\n", - payload_length); - return; - } - - /* A new SVC communication channel, let's verify a supported version */ - if ((handshake->version_major != GREYBUS_VERSION_MAJOR) || - (handshake->version_minor != GREYBUS_VERSION_MINOR)) { - dev_warn(hd->parent, - "received invalid greybus version %u.%u\n", - handshake->version_major, handshake->version_minor); - return; - } - - /* Validate that the handshake came from the SVC */ - if (handshake->handshake_type != SVC_HANDSHAKE_SVC_HELLO) { - /* we don't know what to do with this, log it and return */ - dev_dbg(hd->parent, "received invalid handshake type %d\n", - handshake->handshake_type); - return; - } - - /* Send back a AP_HELLO message */ - svc_msg = svc_msg_alloc(SVC_FUNCTION_HANDSHAKE); - if (!svc_msg) - return; - - svc_msg->header.message_type = SVC_MSG_DATA; - svc_msg->header.payload_length = - cpu_to_le16(sizeof(*handshake)); - svc_msg->handshake.version_major = GREYBUS_VERSION_MAJOR; - svc_msg->handshake.version_minor = GREYBUS_VERSION_MINOR; - svc_msg->handshake.handshake_type = SVC_HANDSHAKE_AP_HELLO; - - (void)svc_msg_send(svc_msg, hd); -} - -static void svc_management(struct svc_function_unipro_management *management, - int payload_length, struct greybus_host_device *hd) -{ - struct gb_interface *intf; - int ret; - - if (payload_length != sizeof(*management)) { - dev_err(hd->parent, - "Illegal size of svc management message %d\n", - payload_length); - return; - } - - switch (management->management_packet_type) { - case SVC_MANAGEMENT_AP_ID: - hd->device_id = management->ap_id.device_id; - break; - case SVC_MANAGEMENT_LINK_UP: - intf = gb_interface_find(hd, management->link_up.interface_id); - if (!intf) { - dev_err(hd->parent, "Interface ID %d not found\n", - management->link_up.interface_id); - return; - } - ret = gb_interface_init(intf, management->link_up.device_id); - if (ret) { - dev_err(hd->parent, - "error %d initializing interface %hhu\n", - ret, management->link_up.interface_id); - return; - } - break; - default: - dev_err(hd->parent, "Unhandled UniPro management message\n"); - } -} - -static void svc_hotplug(struct svc_function_hotplug *hotplug, - int payload_length, struct greybus_host_device *hd) -{ - u8 interface_id = hotplug->interface_id; - - switch (hotplug->hotplug_event) { - case SVC_HOTPLUG_EVENT: - /* Add a new interface to the system */ - if (payload_length != sizeof(*hotplug)) { - dev_err(hd->parent, - "Illegal size of svc hotplug message %d\n", - payload_length); - return; - } - dev_dbg(hd->parent, "interface id %d added\n", interface_id); - gb_interface_create(hd, interface_id); - break; - - case SVC_HOTUNPLUG_EVENT: - /* Remove a interface from the system */ - if (payload_length != sizeof(*hotplug)) { - dev_err(hd->parent, - "Illegal size of svc hotunplug message %d\n", - payload_length); - return; - } - dev_dbg(hd->parent, "interface id %d removed\n", interface_id); - gb_interface_remove(hd, interface_id); - break; - - default: - dev_err(hd->parent, - "Received invalid hotplug message type %d\n", - hotplug->hotplug_event); - break; - } -} - -static void svc_power(struct svc_function_power *power, - int payload_length, struct greybus_host_device *hd) -{ - u8 interface_id = power->interface_id; - - /* - * The AP is only allowed to get a Battery Status message, not a Battery - * Status Request - */ - if (power->power_type != SVC_POWER_BATTERY_STATUS) { - dev_err(hd->parent, "Received invalid power type %d\n", - power->power_type); - return; - } - - /* - * As struct struct svc_function_power_battery_status_request is 0 bytes - * big, we can just check the union of the whole structure to validate - * the size of this message. - */ - if (payload_length != sizeof(*power)) { - dev_err(hd->parent, - "Illegal size of svc power message %d\n", - payload_length); - return; - } - - dev_dbg(hd->parent, "power status for interface id %d is %d\n", - interface_id, power->status.status); - - // FIXME - do something with the power information, like update our - // battery information... -} - -static void svc_epm(struct svc_function_epm *epm, - int payload_length, struct greybus_host_device *hd) -{ - /* What? An AP should not get this message */ - dev_err(hd->parent, "Got an EPM message???\n"); -} - -static void svc_suspend(struct svc_function_suspend *suspend, - int payload_length, struct greybus_host_device *hd) -{ - /* What? An AP should not get this message */ - dev_err(hd->parent, "Got an suspend message???\n"); -} - -static struct svc_msg *convert_ap_message(struct ap_msg *ap_msg) -{ - struct svc_msg *svc_msg; - struct svc_msg_header *header; - struct greybus_host_device *hd = ap_msg->hd; - - svc_msg = (struct svc_msg *)ap_msg->data; - header = &svc_msg->header; - - /* Validate the message type */ - if (header->message_type != SVC_MSG_DATA) { - dev_err(hd->parent, "message type %d received?\n", - header->message_type); - return NULL; - } - - /* - * The validation of the size of the message buffer happens in each - * svc_* function, due to the different types of messages, keeping the - * logic for each message only in one place. - */ - - return svc_msg; -} - -static void ap_process_event(struct work_struct *work) -{ - struct svc_msg *svc_msg; - struct greybus_host_device *hd; - struct ap_msg *ap_msg; - int payload_length; - - ap_msg = container_of(work, struct ap_msg, event); - hd = ap_msg->hd; - - /* Turn the "raw" data into a real message */ - svc_msg = convert_ap_message(ap_msg); - if (!svc_msg) - return; - - payload_length = le16_to_cpu(svc_msg->header.payload_length); - - /* Look at the message to figure out what to do with it */ - switch (svc_msg->header.function_id) { - case SVC_FUNCTION_HANDSHAKE: - svc_handshake(&svc_msg->handshake, payload_length, hd); - break; - case SVC_FUNCTION_UNIPRO_NETWORK_MANAGEMENT: - svc_management(&svc_msg->management, payload_length, hd); - break; - case SVC_FUNCTION_HOTPLUG: - svc_hotplug(&svc_msg->hotplug, payload_length, hd); - break; - case SVC_FUNCTION_POWER: - svc_power(&svc_msg->power, payload_length, hd); - break; - case SVC_FUNCTION_EPM: - svc_epm(&svc_msg->epm, payload_length, hd); - break; - case SVC_FUNCTION_SUSPEND: - svc_suspend(&svc_msg->suspend, payload_length, hd); - break; - default: - dev_err(hd->parent, "received invalid SVC function ID %d\n", - svc_msg->header.function_id); - } - - /* clean the message up */ - kfree(ap_msg->data); - kfree(ap_msg); -} - -int greybus_svc_in(struct greybus_host_device *hd, u8 *data, int size) -{ - struct ap_msg *ap_msg; - - /* - * Totally naive copy the message into a new structure that we slowly - * create and add it to the list. Let's get this working, the odds of - * this being any "slow path" for AP messages is really low at this - * point in time, but you never know, so this comment is here to point - * out that maybe we should use a slab allocator, or even just not copy - * the data, but use it directly and force the urbs to be "new" each - * time. - */ - - /* Note - this can, and will, be called in interrupt context. */ - ap_msg = kmalloc(sizeof(*ap_msg), GFP_ATOMIC); - if (!ap_msg) - return -ENOMEM; - ap_msg->data = kmalloc(size, GFP_ATOMIC); - if (!ap_msg->data) { - kfree(ap_msg); - return -ENOMEM; - } - memcpy(ap_msg->data, data, size); - ap_msg->size = size; - ap_msg->hd = hd; - - INIT_WORK(&ap_msg->event, ap_process_event); - queue_work(ap_workqueue, &ap_msg->event); - - return 0; -} -EXPORT_SYMBOL_GPL(greybus_svc_in); - -int __init gb_ap_init(void) -{ - ap_workqueue = alloc_ordered_workqueue("greybus_ap", 0); - if (!ap_workqueue) - return -ENOMEM; - - return 0; -} - -void gb_ap_exit(void) -{ - destroy_workqueue(ap_workqueue); - ap_workqueue = NULL; -} - - diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 225fa4f..cd15a94 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -270,12 +270,6 @@ static int __init gb_init(void) goto error_bus; } - retval = gb_ap_init(); - if (retval) { - pr_err("gb_ap_init failed (%d)\n", retval); - goto error_ap; - } - retval = gb_operation_init(); if (retval) { pr_err("gb_operation_init failed (%d)\n", retval); @@ -309,8 +303,6 @@ error_control: error_endo: gb_operation_exit(); error_operation: - gb_ap_exit(); -error_ap: bus_unregister(&greybus_bus_type); error_bus: gb_debugfs_cleanup(); @@ -325,7 +317,6 @@ static void __exit gb_exit(void) gb_control_protocol_exit(); gb_endo_exit(); gb_operation_exit(); - gb_ap_exit(); bus_unregister(&greybus_bus_type); gb_debugfs_cleanup(); } diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 2214f44..90f9962 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -156,8 +156,6 @@ void greybus_deregister_driver(struct greybus_driver *driver); int greybus_disabled(void); int greybus_svc_in(struct greybus_host_device *hd, u8 *data, int length); -int gb_ap_init(void); -void gb_ap_exit(void); void gb_debugfs_init(void); void gb_debugfs_cleanup(void); struct dentry *gb_debugfs_get(void); -- cgit v0.10.2 From e08aaa49df7866c1a786dc01ce4f8a47c6aaa954 Mon Sep 17 00:00:00 2001 From: Perry Hung Date: Fri, 24 Jul 2015 19:02:31 -0400 Subject: greybus: svc: add route create operation Implement the SVC Protocol Route Create Operation. Tested-by: Viresh Kumar Reviewed-by: Viresh Kumar Signed-off-by: Perry Hung Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 9708e93..5b97073 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -563,6 +563,7 @@ struct gb_spi_transfer_response { #define GB_SVC_TYPE_INTF_RESET 0x06 #define GB_SVC_TYPE_CONN_CREATE 0x07 #define GB_SVC_TYPE_CONN_DESTROY 0x08 +#define GB_SVC_TYPE_ROUTE_CREATE 0x0b /* SVC version request/response have same payload as gb_protocol_version_response */ @@ -616,6 +617,13 @@ struct gb_svc_conn_destroy_request { }; /* connection destroy response has no payload */ +struct gb_svc_route_create_request { + __u8 intf1_id; + __u8 dev1_id; + __u8 intf2_id; + __u8 dev2_id; +}; + /* UART */ /* Version of the Greybus UART protocol we support */ diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 5f2b2b4..f332129 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -118,6 +118,20 @@ static int connection_destroy_operation(struct gb_svc *svc, &request, sizeof(request), NULL, 0); } +static int route_create_operation(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, + u8 intf2_id, u8 dev2_id) +{ + struct gb_svc_route_create_request request; + + request.intf1_id = intf1_id; + request.dev1_id = dev1_id; + request.intf2_id = intf2_id; + request.dev2_id = dev2_id; + + return gb_operation_sync(svc->connection, GB_SVC_TYPE_ROUTE_CREATE, + &request, sizeof(request), NULL, 0); +} + int gb_svc_intf_device_id(struct gb_svc *svc, u8 intf_id, u8 device_id) { return intf_device_id_operation(svc, intf_id, device_id); @@ -148,6 +162,13 @@ int gb_svc_connection_destroy(struct gb_svc *svc, } EXPORT_SYMBOL_GPL(gb_svc_connection_destroy); +int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, + u8 intf2_id, u8 dev2_id) { + return route_create_operation(svc, intf1_id, dev1_id, + intf2_id, dev2_id); +} +EXPORT_SYMBOL_GPL(gb_svc_route_create); + static int gb_svc_version_request(struct gb_operation *op) { struct gb_connection *connection = op->connection; -- cgit v0.10.2 From 7e275465fabd58065ec49c770bd4446f41a13e87 Mon Sep 17 00:00:00 2001 From: Perry Hung Date: Fri, 24 Jul 2015 19:02:32 -0400 Subject: greybus: svc: create bidirectional routes on hotplug request Upon receiving a hotplug request, we need to prepare the routing table to allow packets to flow between the AP interface and the newly detected interface. Tested-by: Viresh Kumar Reviewed-by: Viresh Kumar Signed-off-by: Perry Hung Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index f332129..3d18087 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -309,6 +309,25 @@ static int gb_svc_intf_hotplug_recv(struct gb_operation *op) goto ida_put; } + /* + * Create a two-way route between the AP and the new interface + */ + ret = route_create_operation(svc, hd->endo->ap_intf_id, + GB_DEVICE_ID_AP, intf_id, device_id); + if (ret) { + dev_err(dev, "%s: Route create operation failed, interface %hhu device_id %hhu (%d)\n", + __func__, intf_id, device_id, ret); + goto ida_put; + } + + ret = route_create_operation(svc, intf_id, device_id, + hd->endo->ap_intf_id, GB_DEVICE_ID_AP); + if (ret) { + dev_err(dev, "%s: Route create operation failed, interface %hhu device_id %hhu (%d)\n", + __func__, intf_id, device_id, ret); + goto ida_put; + } + ret = gb_interface_init(intf, device_id); if (ret) { dev_err(dev, "%s: Failed to initialize interface, interface %hhu device_id %hhu (%d)\n", -- cgit v0.10.2 From 75a60ed20d1ad58983e04dee27faae454e81d6a5 Mon Sep 17 00:00:00 2001 From: Perry Hung Date: Fri, 24 Jul 2015 19:02:33 -0400 Subject: greybus: svc: connection: ask SVC to create connections Ask the SVC to do all the necessary bits for creating a new connection. This is skipped for the initial SVC connection. Tested-by: Viresh Kumar Reviewed-by: Viresh Kumar Signed-off-by: Perry Hung Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index b32da8a..1a657f70 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -251,7 +251,12 @@ gb_connection_create_range(struct greybus_host_device *hd, spin_unlock_irq(&gb_connections_lock); - /* XXX Will have to establish connections to get version */ + if (hd_cport_id != GB_SVC_CPORT_ID) { + gb_svc_connection_create(hd->svc, + hd->endo->ap_intf_id, hd_cport_id, + bundle->intf->interface_id, cport_id); + } + gb_connection_bind_protocol(connection); if (!connection->protocol) dev_warn(&connection->dev, diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 90f9962..ef11b96 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -103,6 +103,7 @@ struct greybus_host_device { struct gb_endo *endo; struct gb_connection *initial_svc_connection; + struct gb_svc *svc; /* Private data for the host driver */ unsigned long hd_priv[0] __aligned(sizeof(s64)); diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 3d18087..b718a88 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -430,6 +430,7 @@ static int gb_svc_connection_init(struct gb_connection *connection) if (!svc) return -ENOMEM; + connection->hd->svc = svc; svc->connection = connection; connection->private = svc; @@ -445,6 +446,7 @@ static void gb_svc_connection_exit(struct gb_connection *connection) { struct gb_svc *svc = connection->private; + connection->hd->svc = NULL; connection->private = NULL; kfree(svc); } -- cgit v0.10.2 From 0b22649755df615d4b82b625f938a31435ff1726 Mon Sep 17 00:00:00 2001 From: Perry Hung Date: Fri, 24 Jul 2015 19:02:34 -0400 Subject: greybus: svc: add flags and traffic class parameter to connection create op The AP needs to be able to specify L4 CPort flags and traffic class parameters on a connection-by-connection basis. Extend the connection create operation to accept these. Since there's no policy to decide these, fix them at TC0 with end-to-end-flow control, controlled segment dropping, and CPort safety valve enabled. Tested-by: Viresh Kumar Reviewed-by: Viresh Kumar Signed-off-by: Perry Hung Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 5b97073..e2d38df 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -606,6 +606,8 @@ struct gb_svc_conn_create_request { __u16 cport1_id; __u8 intf2_id; __u16 cport2_id; + __u8 tc; + __u8 flags; }; /* connection create response has no payload */ diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index b718a88..b94a84a 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -9,6 +9,10 @@ #include "greybus.h" +#define CPORT_FLAGS_E2EFC (1) +#define CPORT_FLAGS_CSD_N (2) +#define CPORT_FLAGS_CSV_N (4) + struct gb_svc { struct gb_connection *connection; u8 version_major; @@ -98,6 +102,12 @@ static int connection_create_operation(struct gb_svc *svc, request.cport1_id = cport1_id; request.intf2_id = intf2_id; request.cport2_id = cport2_id; + /* + * XXX: fix connections paramaters to TC0 and all CPort flags + * for now. + */ + request.tc = 0; + request.flags = CPORT_FLAGS_CSV_N | CPORT_FLAGS_E2EFC; return gb_operation_sync(svc->connection, GB_SVC_TYPE_CONN_CREATE, &request, sizeof(request), NULL, 0); -- cgit v0.10.2 From 8476ec60e1111839469779bb0bba1eade95e53c5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 24 Jul 2015 17:15:59 -0700 Subject: greybus: greybus.h: remove greybus_svc_in() The function is gone, remove it from the header file as well. Tested-by: Viresh Kumar Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index ef11b96..a011495 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -156,7 +156,6 @@ void greybus_deregister_driver(struct greybus_driver *driver); int greybus_disabled(void); -int greybus_svc_in(struct greybus_host_device *hd, u8 *data, int length); void gb_debugfs_init(void); void gb_debugfs_cleanup(void); struct dentry *gb_debugfs_get(void); -- cgit v0.10.2 From 260998ebc6c5e4a2518347eb4f99629fac4fe6cb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 24 Jul 2015 17:19:21 -0700 Subject: greybus: remove submit_svc from the host driver The callback is never used anymore, so remove it from struct greybus_host_driver as well as from the es1 and es2 drivers. Tested-by: Viresh Kumar Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index cd15a94..7d5cd99 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -176,8 +176,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver * Validate that the driver implements all of the callbacks * so that we don't have to every time we make them. */ - if ((!driver->message_send) || (!driver->message_cancel) || - (!driver->submit_svc)) { + if ((!driver->message_send) || (!driver->message_cancel)) { pr_err("Must implement all greybus_host_driver callbacks!\n"); return ERR_PTR(-EINVAL); } diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 82a7c67..e203180 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -14,7 +14,6 @@ #include #include "greybus.h" -#include "svc_msg.h" #include "kernel_ver.h" /* Memory sizes for the buffers sent to/from the ES1 controller */ @@ -95,26 +94,6 @@ static void usb_log_enable(struct es1_ap_dev *es1); static void usb_log_disable(struct es1_ap_dev *es1); #define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ -static int submit_svc(struct svc_msg *svc_msg, struct greybus_host_device *hd) -{ - struct es1_ap_dev *es1 = hd_to_es1(hd); - int retval; - - /* SVC messages go down our control pipe */ - retval = usb_control_msg(es1->usb_dev, - usb_sndctrlpipe(es1->usb_dev, - es1->control_endpoint), - REQUEST_SVC, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - 0x00, 0x00, - (char *)svc_msg, - sizeof(*svc_msg), - ES1_TIMEOUT); - if (retval != sizeof(*svc_msg)) - return retval; - - return 0; -} static struct urb *next_free_urb(struct es1_ap_dev *es1, gfp_t gfp_mask) { @@ -295,7 +274,6 @@ static struct greybus_host_driver es1_driver = { .hd_priv_size = sizeof(struct es1_ap_dev), .message_send = message_send, .message_cancel = message_cancel, - .submit_svc = submit_svc, }; /* Common function to report consistent warnings based on URB status */ diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index c353ca5..aba1927 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -14,7 +14,6 @@ #include #include "greybus.h" -#include "svc_msg.h" #include "kernel_ver.h" /* Memory sizes for the buffers sent to/from the ES1 controller */ @@ -134,26 +133,6 @@ static int cport_to_ep(struct es1_ap_dev *es1, u16 cport_id) } #define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ -static int submit_svc(struct svc_msg *svc_msg, struct greybus_host_device *hd) -{ - struct es1_ap_dev *es1 = hd_to_es1(hd); - int retval; - - /* SVC messages go down our control pipe */ - retval = usb_control_msg(es1->usb_dev, - usb_sndctrlpipe(es1->usb_dev, - es1->control_endpoint), - REQUEST_SVC, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - 0x00, 0x00, - (char *)svc_msg, - sizeof(*svc_msg), - ES1_TIMEOUT); - if (retval != sizeof(*svc_msg)) - return retval; - - return 0; -} static int ep_in_use(struct es1_ap_dev *es1, int bulk_ep_set) { @@ -391,7 +370,6 @@ static struct greybus_host_driver es1_driver = { .hd_priv_size = sizeof(struct es1_ap_dev), .message_send = message_send, .message_cancel = message_cancel, - .submit_svc = submit_svc, }; /* Common function to report consistent warnings based on URB status */ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index a011495..30ea4a4 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -84,8 +84,6 @@ struct greybus_host_driver { int (*message_send)(struct greybus_host_device *hd, u16 dest_cport_id, struct gb_message *message, gfp_t gfp_mask); void (*message_cancel)(struct gb_message *message); - int (*submit_svc)(struct svc_msg *svc_msg, - struct greybus_host_device *hd); }; struct greybus_host_device { -- cgit v0.10.2 From d45b1b8674cbefe1358a042d800f84766e534ba5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 24 Jul 2015 17:21:25 -0700 Subject: greybus: interface: make gb_interface_destroy() static The function is only called locally, so mark it static to make sparse happy. Tested-by: Viresh Kumar Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index f1e2956..4a26bf6 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -183,7 +183,7 @@ put_module: /* * Tear down a previously set up module. */ -void gb_interface_destroy(struct gb_interface *intf) +static void interface_destroy(struct gb_interface *intf) { struct gb_module *module; struct gb_bundle *bundle; @@ -279,7 +279,7 @@ void gb_interface_remove(struct greybus_host_device *hd, u8 interface_id) struct gb_interface *intf = gb_interface_find(hd, interface_id); if (intf) - gb_interface_destroy(intf); + interface_destroy(intf); else dev_err(hd->parent, "interface id %d not found\n", interface_id); @@ -290,5 +290,5 @@ void gb_interfaces_remove(struct greybus_host_device *hd) struct gb_interface *intf, *temp; list_for_each_entry_safe(intf, temp, &hd->interfaces, links) - gb_interface_destroy(intf); + interface_destroy(intf); } -- cgit v0.10.2 From 0b161d0a92717d57fd1598e326a68e859bf92a48 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Sat, 25 Jul 2015 10:10:05 +0530 Subject: greybus: es1: create svc connection early enough The svc connection needs to be ready before creating the URBs, otherwise the svc version request might come in before the AP was ready to parse them. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index e203180..5418f46 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -563,6 +563,12 @@ static int ap_probe(struct usb_interface *interface, return PTR_ERR(hd); } + /* Initialize AP's greybus interface */ + if (!gb_ap_svc_connection_create(hd)) { + retval = -EINVAL; + goto error; + } + es1 = hd_to_es1(hd); es1->hd = hd; es1->usb_intf = interface; @@ -632,12 +638,6 @@ static int ap_probe(struct usb_interface *interface, es1->cport_out_urb_busy[i] = false; /* just to be anal */ } - /* Initialize AP's greybus interface */ - if (!gb_ap_svc_connection_create(hd)) { - retval = -EINVAL; - goto error; - } - apb1_log_enable_dentry = debugfs_create_file("apb1_log_enable", (S_IWUSR | S_IRUGO), gb_debugfs_get(), es1, diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index aba1927..d2c054a 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -663,6 +663,12 @@ static int ap_probe(struct usb_interface *interface, return PTR_ERR(hd); } + /* Initialize AP's greybus interface */ + if (!gb_ap_svc_connection_create(hd)) { + retval = -EINVAL; + goto error; + } + es1 = hd_to_es1(hd); es1->hd = hd; es1->usb_intf = interface; @@ -736,12 +742,6 @@ static int ap_probe(struct usb_interface *interface, es1->cport_out_urb_busy[i] = false; /* just to be anal */ } - /* Initialize AP's greybus interface */ - if (!gb_ap_svc_connection_create(hd)) { - retval = -EINVAL; - goto error; - } - apb1_log_enable_dentry = debugfs_create_file("apb1_log_enable", (S_IWUSR | S_IRUGO), gb_debugfs_get(), es1, -- cgit v0.10.2 From ca539a67c6a25e47233fdab67bdf1d4db00f883f Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Sat, 25 Jul 2015 10:10:06 +0530 Subject: greybus: remove svc_msg.h Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 30ea4a4..cdade1e 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -73,7 +73,6 @@ */ struct greybus_host_device; -struct svc_msg; /* Greybus "Host driver" structure, needed by a host controller driver to be * able to handle both SVC control as well as "real" greybus messages diff --git a/drivers/staging/greybus/svc_msg.h b/drivers/staging/greybus/svc_msg.h deleted file mode 100644 index 3c628c5..0000000 --- a/drivers/staging/greybus/svc_msg.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Greybus AP <-> SVC message structure format. - * - * See "Greybus Application Protocol" document (version 0.1) for - * details on these values and structures. - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - * - * Released under the GPLv2 and BSD license. - */ - -#ifndef __SVC_MSG_H -#define __SVC_MSG_H - -enum svc_function_id { - SVC_FUNCTION_HANDSHAKE = 0x00, - SVC_FUNCTION_UNIPRO_NETWORK_MANAGEMENT = 0x01, - SVC_FUNCTION_HOTPLUG = 0x02, - SVC_FUNCTION_POWER = 0x03, - SVC_FUNCTION_EPM = 0x04, - SVC_FUNCTION_SUSPEND = 0x05, -}; - -enum svc_msg_type { - SVC_MSG_DATA = 0x00, - SVC_MSG_ERROR = 0xff, -}; - -struct svc_msg_header { - __u8 function_id; /* enum svc_function_id */ - __u8 message_type; - __le16 payload_length; -} __packed; - -enum svc_function_handshake_type { - SVC_HANDSHAKE_SVC_HELLO = 0x00, - SVC_HANDSHAKE_AP_HELLO = 0x01, - SVC_HANDSHAKE_MODULE_HELLO = 0x02, -}; - -struct svc_function_handshake { - __u8 version_major; - __u8 version_minor; - __u8 handshake_type; /* enum svc_function_handshake_type */ -} __packed; - -struct svc_function_unipro_set_route { - __u8 device_id; -} __packed; - -struct svc_function_unipro_link_up { - __u8 interface_id; /* Interface id within the Endo */ - __u8 device_id; -} __packed; - -struct svc_function_ap_id { - __u8 interface_id; - __u8 device_id; -} __packed; - -enum svc_function_management_event { - SVC_MANAGEMENT_AP_ID = 0x00, - SVC_MANAGEMENT_LINK_UP = 0x01, - SVC_MANAGEMENT_SET_ROUTE = 0x02, -}; - -struct svc_function_unipro_management { - __u8 management_packet_type; /* enum svc_function_management_event */ - union { - struct svc_function_ap_id ap_id; - struct svc_function_unipro_link_up link_up; - struct svc_function_unipro_set_route set_route; - }; -} __packed; - -enum svc_function_hotplug_event { - SVC_HOTPLUG_EVENT = 0x00, - SVC_HOTUNPLUG_EVENT = 0x01, -}; - -struct svc_function_hotplug { - __u8 hotplug_event; /* enum svc_function_hotplug_event */ - __u8 interface_id; /* Interface id within the Endo */ -} __packed; - -enum svc_function_power_type { - SVC_POWER_BATTERY_STATUS = 0x00, - SVC_POWER_BATTERY_STATUS_REQUEST = 0x01, -}; - -enum svc_function_battery_status { - SVC_BATTERY_UNKNOWN = 0x00, - SVC_BATTERY_CHARGING = 0x01, - SVC_BATTERY_DISCHARGING = 0x02, - SVC_BATTERY_NOT_CHARGING = 0x03, - SVC_BATTERY_FULL = 0x04, -}; - -struct svc_function_power_battery_status { - __le16 charge_full; - __le16 charge_now; - __u8 status; /* enum svc_function_battery_status */ -} __packed; - -struct svc_function_power_battery_status_request { -} __packed; - -/* XXX - * Each interface carries power, so it's possible these things - * are associated with each UniPro device and not just the module. - * For now it's safe to assume it's per-module. - */ -struct svc_function_power { - __u8 power_type; /* enum svc_function_power_type */ - __u8 interface_id; - union { - struct svc_function_power_battery_status status; - struct svc_function_power_battery_status_request request; - }; -} __packed; - -enum svc_function_epm_command_type { - SVC_EPM_ENABLE = 0x00, - SVC_EPM_DISABLE = 0x01, -}; - -/* EPM's are associated with the module */ -struct svc_function_epm { - __u8 epm_command_type; /* enum svc_function_epm_command_type */ - __u8 module_id; -} __packed; - -enum svc_function_suspend_command_type { - SVC_SUSPEND_FIXME_1 = 0x00, // FIXME - SVC_SUSPEND_FIXME_2 = 0x01, -}; - -/* We'll want independent control for multi-interface modules */ -struct svc_function_suspend { - __u8 suspend_command_type; /* enum function_suspend_command_type */ - __u8 device_id; -} __packed; - -struct svc_msg { - struct svc_msg_header header; - union { - struct svc_function_handshake handshake; - struct svc_function_unipro_management management; - struct svc_function_hotplug hotplug; - struct svc_function_power power; - struct svc_function_epm epm; - struct svc_function_suspend suspend; - }; -} __packed; - -#endif /* __SVC_MSG_H */ -- cgit v0.10.2 From e75b82bfc72533be25ce42241ca2d07b607ee705 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 28 Jul 2015 07:28:42 +0530 Subject: greybus: initialize svc connection while creating hd Its really part of initializing the host device and is required for every 'hd' that is created. Lets move the call to do basic initialization of svc connection to greybus_create_hd(). Also add a comment to specify why we need to do it that early. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 7d5cd99..9f105fb 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -208,6 +208,21 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver ida_init(&hd->cport_id_map); hd->buffer_size_max = buffer_size_max; + /* + * Initialize AP's SVC protocol connection: + * + * This is required as part of early initialization of the host device + * as we need this connection in order to start any kind of message + * exchange between the AP and the SVC. SVC will start with a + * 'get-version' request followed by a 'svc-hello' message and at that + * time we will create a fully initialized svc-connection, as we need + * endo-id and AP's interface id for that. + */ + if (!gb_ap_svc_connection_create(hd)) { + kref_put_mutex(&hd->kref, free_hd, &hd_mutex); + return ERR_PTR(-ENOMEM); + } + return hd; } EXPORT_SYMBOL_GPL(greybus_create_hd); diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 5418f46..c1fab37 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -563,12 +563,6 @@ static int ap_probe(struct usb_interface *interface, return PTR_ERR(hd); } - /* Initialize AP's greybus interface */ - if (!gb_ap_svc_connection_create(hd)) { - retval = -EINVAL; - goto error; - } - es1 = hd_to_es1(hd); es1->hd = hd; es1->usb_intf = interface; diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index d2c054a..558345c 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -663,12 +663,6 @@ static int ap_probe(struct usb_interface *interface, return PTR_ERR(hd); } - /* Initialize AP's greybus interface */ - if (!gb_ap_svc_connection_create(hd)) { - retval = -EINVAL; - goto error; - } - es1 = hd_to_es1(hd); es1->hd = hd; es1->usb_intf = interface; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index b94a84a..784b770 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -40,7 +40,6 @@ gb_ap_svc_connection_create(struct greybus_host_device *hd) return connection; } -EXPORT_SYMBOL_GPL(gb_ap_svc_connection_create); /* * We know endo-type and AP's interface id now, lets create a proper svc -- cgit v0.10.2 From 48ed3f6e4202c9ddadac057108c273b8be85a78d Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 30 Jul 2015 22:13:27 +0530 Subject: greybus: connection: remove special check for svc cport id This is required to get things working for now, after the latest revert of svc protocol is done. Currently svc's cport id is set to 2 and that hd cport id will be used for the third connection we make. And that protocol (which is i2c in one of the cases), may not work as the (dis)connected event isn't sent for it. Fix this by getting rid of svc protocol check from (dis)connected events for now. This must be reverted later, once svc protocol is included again. Signed-off-by: Viresh Kumar Tested-by: Mark Greer Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index b32da8a..3b553e6 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -344,8 +344,7 @@ int gb_connection_init(struct gb_connection *connection) * Inform Interface about Active CPorts. We don't need to do this * operation for control cport. */ - if (cport_id != GB_CONTROL_CPORT_ID && - connection->hd_cport_id != GB_SVC_CPORT_ID) { + if (cport_id != GB_CONTROL_CPORT_ID) { struct gb_control *control = connection->bundle->intf->control; ret = gb_control_connected_operation(control, cport_id); @@ -397,8 +396,7 @@ void gb_connection_exit(struct gb_connection *connection) * Inform Interface about In-active CPorts. We don't need to do this * operation for control cport. */ - if (cport_id != GB_CONTROL_CPORT_ID && - connection->hd_cport_id != GB_SVC_CPORT_ID) { + if (cport_id != GB_CONTROL_CPORT_ID) { struct gb_control *control = connection->bundle->intf->control; int ret; -- cgit v0.10.2 From 32574ff3e4360e7c98fe5b2d54afb652aca45a8d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 30 Jul 2015 12:22:09 -0700 Subject: greybus: Revert "connection: remove special check for svc cport id" This reverts commit 60b1d71fdfc2c5266051a1297df01ea0b1f3ba99 as we want the port number to be correct in the svc branch. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index e7f9c2f..1a657f70 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -349,7 +349,8 @@ int gb_connection_init(struct gb_connection *connection) * Inform Interface about Active CPorts. We don't need to do this * operation for control cport. */ - if (cport_id != GB_CONTROL_CPORT_ID) { + if (cport_id != GB_CONTROL_CPORT_ID && + connection->hd_cport_id != GB_SVC_CPORT_ID) { struct gb_control *control = connection->bundle->intf->control; ret = gb_control_connected_operation(control, cport_id); @@ -401,7 +402,8 @@ void gb_connection_exit(struct gb_connection *connection) * Inform Interface about In-active CPorts. We don't need to do this * operation for control cport. */ - if (cport_id != GB_CONTROL_CPORT_ID) { + if (cport_id != GB_CONTROL_CPORT_ID && + connection->hd_cport_id != GB_SVC_CPORT_ID) { struct gb_control *control = connection->bundle->intf->control; int ret; -- cgit v0.10.2 From 3a6b5aeec771205d35f28616a610d9ed5d2c49b2 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 30 Jul 2015 20:30:36 +0200 Subject: greybus: usb: clean up driver Remove unused, broken or unneeded code and constructs. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/usb.c b/drivers/staging/greybus/usb.c index e49fffd..04c8783 100644 --- a/drivers/staging/greybus/usb.c +++ b/drivers/staging/greybus/usb.c @@ -24,32 +24,7 @@ #define GB_USB_TYPE_PROTOCOL_VERSION 0x01 #define GB_USB_TYPE_HCD_STOP 0x02 #define GB_USB_TYPE_HCD_START 0x03 -#define GB_USB_TYPE_URB_ENQUEUE 0x04 -#define GB_USB_TYPE_URB_DEQUEUE 0x05 -#define GB_USB_TYPE_ENDPOINT_DISABLE 0x06 #define GB_USB_TYPE_HUB_CONTROL 0x07 -#define GB_USB_TYPE_GET_FRAME_NUMBER 0x08 -#define GB_USB_TYPE_HUB_STATUS_DATA 0x09 - -struct gb_usb_urb_enqueue_request { - __le32 pipe; - __le32 transfer_flags; - __le32 transfer_buffer_length; - __le32 maxpacket; - __le32 interval; - __le64 hcpriv_ep; - __le32 number_of_packets; - u8 setup_packet[8]; - u8 payload[0]; -}; - -struct gb_usb_urb_dequeue_request { - __le64 hcpriv_ep; -}; - -struct gb_usb_endpoint_disable_request { - __le64 hcpriv; -}; struct gb_usb_hub_control_request { __le16 typeReq; @@ -62,22 +37,6 @@ struct gb_usb_hub_control_response { u8 buf[0]; }; -struct gb_usb_header { - __le16 size; - __le16 id; - __u8 type; -}; - -struct gb_usb_hub_status { - __le32 status; - __le16 buf_size; - u8 buf[0]; -}; - -static struct gb_usb_hub_status *hub_status; // FIXME!!! -static DEFINE_SPINLOCK(hub_status_lock); -static atomic_t frame_number; // FIXME!!! - struct gb_usb_device { struct gb_connection *connection; @@ -123,83 +82,22 @@ static int hcd_start(struct usb_hcd *hcd) static int urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) { - struct gb_usb_device *dev = to_gb_usb_device(hcd); - struct gb_usb_urb_enqueue_request *request; - struct gb_operation *operation; - int ret; - - operation = gb_operation_create(dev->connection, - GB_USB_TYPE_URB_ENQUEUE, - sizeof(*request) + - urb->transfer_buffer_length, 0, - GFP_KERNEL); - if (!operation) - return -ENODEV; - - request = operation->request->payload; - request->pipe = cpu_to_le32(urb->pipe); - request->transfer_flags = cpu_to_le32(urb->transfer_flags); - request->transfer_buffer_length = cpu_to_le32(urb->transfer_buffer_length); - request->interval = cpu_to_le32(urb->interval); - request->hcpriv_ep = cpu_to_le64((unsigned long)urb->ep->hcpriv); - request->number_of_packets = cpu_to_le32(urb->number_of_packets); - - memcpy(request->setup_packet, urb->setup_packet, 8); - memcpy(&request->payload, urb->transfer_buffer, - urb->transfer_buffer_length); - - ret = gb_operation_request_send_sync(operation); - gb_operation_destroy(operation); - - return ret; + return -ENXIO; } static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) { - struct gb_usb_device *dev = to_gb_usb_device(hcd); - struct gb_usb_urb_dequeue_request request; - int ret; - - urb->ep->hcpriv = NULL; - request.hcpriv_ep = cpu_to_le64((unsigned long)urb->hcpriv); - ret = gb_operation_sync(dev->connection, GB_USB_TYPE_URB_DEQUEUE, - &request, sizeof(request), NULL, 0); - urb->hcpriv = NULL; - return ret; -} - -static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep) -{ - struct gb_usb_device *dev = to_gb_usb_device(hcd); - struct gb_usb_endpoint_disable_request request; - int ret; - - request.hcpriv = cpu_to_le64((unsigned long)ep->hcpriv); - ret = gb_operation_sync(dev->connection, GB_USB_TYPE_ENDPOINT_DISABLE, - &request, sizeof(request), NULL, 0); - ep->hcpriv = NULL; -} - -static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) -{ + return -ENXIO; } static int get_frame_number(struct usb_hcd *hcd) { - return atomic_read(&frame_number); + return 0; } static int hub_status_data(struct usb_hcd *hcd, char *buf) { - int retval; - unsigned long flags; - - spin_lock_irqsave(&hub_status_lock, flags); - memcpy(buf, hub_status->buf, le16_to_cpu(hub_status->buf_size)); - retval = le32_to_cpu(hub_status->status); - spin_unlock_irqrestore(&hub_status_lock, flags); - - return retval; + return 0; } static int hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, @@ -232,82 +130,15 @@ static struct hc_driver usb_gb_hc_driver = { .start = hcd_start, .stop = hcd_stop, + .urb_enqueue = urb_enqueue, .urb_dequeue = urb_dequeue, - .endpoint_disable = endpoint_disable, - .endpoint_reset = endpoint_reset, + .get_frame_number = get_frame_number, .hub_status_data = hub_status_data, .hub_control = hub_control, }; -#if 0 -static inline void gb_usb_handle_get_frame_number(struct gbuf *gbuf) -{ - __le32 frame_num; - const size_t packet_size = sizeof(struct gb_usb_header) + - sizeof(frame_num); - struct gb_usb_header* hdr = gbuf->transfer_buffer; - - if (le16_to_cpu(hdr->size) != packet_size) { - pr_err("%s(): dropping packet too small\n", __func__); - return; - } - - frame_num = (__le32) ((char*) gbuf->transfer_buffer + - sizeof(struct gb_usb_header)); - atomic_set(&frame_number, le32_to_cpu(frame_num)); -} - -static inline void gb_usb_handle_hubs_status_data(struct gbuf *gbuf) -{ - struct gb_usb_hub_status *new_hubstatus, *hubstatus; - struct gb_usb_header* hdr = gbuf->transfer_buffer; - const size_t min_packet_size = sizeof(struct gb_usb_header) + - sizeof(struct gb_usb_hub_status); - unsigned long flags; - - if (le16_to_cpu(hdr->size) < min_packet_size) { - pr_err("%s(): dropping packet too small\n", __func__); - return; - } - - hubstatus = (struct gb_usb_hub_status*) ((char*) gbuf->transfer_buffer - + sizeof(struct gb_usb_header)); - - if (le16_to_cpu(hdr->size) != min_packet_size + hubstatus->buf_size) { - pr_err("%s(): invalid packet size, dropping packet\n", - __func__); - return; - } - - new_hubstatus = kmalloc(hubstatus->buf_size, GFP_KERNEL); - memcpy(&new_hubstatus, hubstatus, hubstatus->buf_size); - - spin_lock_irqsave(&hub_status_lock, flags); - hubstatus = hub_status; - hub_status = new_hubstatus; - spin_unlock_irqrestore(&hub_status_lock, flags); - - kfree(hubstatus); -} - -static void gb_usb_in_handler(struct gbuf *gbuf) -{ - struct gb_usb_header* hdr = gbuf->transfer_buffer; - - switch (hdr->type) { - case GB_USB_TYPE_GET_FRAME_NUMBER: - gb_usb_handle_get_frame_number(gbuf); - break; - - case GB_USB_TYPE_HUB_STATUS_DATA: - gb_usb_handle_hubs_status_data(gbuf); - break; - } -} -#endif - static int gb_usb_connection_init(struct gb_connection *connection) { struct device *dev = &connection->dev; -- cgit v0.10.2 From 583804f7137737e07e69eaed2904cf043f226a83 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 30 Jul 2015 20:30:37 +0200 Subject: greybus: usb: renumber operation types Renumber the current operation types. NOTE: Protocol change. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/usb.c b/drivers/staging/greybus/usb.c index 04c8783..2a146d7 100644 --- a/drivers/staging/greybus/usb.c +++ b/drivers/staging/greybus/usb.c @@ -22,9 +22,9 @@ /* Greybus USB request types */ #define GB_USB_TYPE_INVALID 0x00 #define GB_USB_TYPE_PROTOCOL_VERSION 0x01 -#define GB_USB_TYPE_HCD_STOP 0x02 -#define GB_USB_TYPE_HCD_START 0x03 -#define GB_USB_TYPE_HUB_CONTROL 0x07 +#define GB_USB_TYPE_HCD_START 0x02 +#define GB_USB_TYPE_HCD_STOP 0x03 +#define GB_USB_TYPE_HUB_CONTROL 0x04 struct gb_usb_hub_control_request { __le16 typeReq; -- cgit v0.10.2 From cc9bd53eb1bf50e265a8f8741a624bf67851f5c0 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 30 Jul 2015 20:30:38 +0200 Subject: greybus: usb: fix hcd allocation, deregistration and deallocation Fix allocation, deregistration and deallocation of USB HCD, and update the hcd_priv helper functions. The HCD private data was not allocated correctly, something which would lead to a crash when accessed in hcd_start. The HCD was neither reregistered or deallocated on connection tear down. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/usb.c b/drivers/staging/greybus/usb.c index 2a146d7..1ba731e 100644 --- a/drivers/staging/greybus/usb.c +++ b/drivers/staging/greybus/usb.c @@ -40,12 +40,19 @@ struct gb_usb_hub_control_response { struct gb_usb_device { struct gb_connection *connection; - struct usb_hcd *hcd; u8 version_major; u8 version_minor; }; -#define to_gb_usb_device(d) ((struct gb_usb_device*) d->hcd_priv) +static inline struct gb_usb_device *to_gb_usb_device(struct usb_hcd *hcd) +{ + return (struct gb_usb_device *)hcd->hcd_priv; +} + +static inline struct usb_hcd *gb_usb_device_to_hcd(struct gb_usb_device *dev) +{ + return container_of((void *)dev, struct usb_hcd, hcd_priv); +} /* Define get_version() routine */ define_get_version(gb_usb_device, USB); @@ -143,45 +150,44 @@ static int gb_usb_connection_init(struct gb_connection *connection) { struct device *dev = &connection->dev; struct gb_usb_device *gb_usb_dev; + struct usb_hcd *hcd; int retval; - gb_usb_dev = kzalloc(sizeof(*gb_usb_dev), GFP_KERNEL); - if (!gb_usb_dev) + hcd = usb_create_hcd(&usb_gb_hc_driver, dev, dev_name(dev)); + if (!hcd) return -ENOMEM; + gb_usb_dev = to_gb_usb_device(hcd); gb_usb_dev->connection = connection; connection->private = gb_usb_dev; /* Check for compatible protocol version */ retval = get_version(gb_usb_dev); if (retval) - goto error_create_hcd; - - gb_usb_dev->hcd = usb_create_hcd(&usb_gb_hc_driver, dev, dev_name(dev)); - if (!gb_usb_dev->hcd) { - retval = -ENODEV; - goto error_create_hcd; - } + goto err_put_hcd; - gb_usb_dev->hcd->has_tt = 1; - gb_usb_dev->hcd->hcd_priv[0] = (unsigned long) gb_usb_dev; + hcd->has_tt = 1; - retval = usb_add_hcd(gb_usb_dev->hcd, 0, 0); + retval = usb_add_hcd(hcd, 0, 0); if (retval) - goto error_add_hcd; + goto err_put_hcd; return 0; -error_add_hcd: - usb_put_hcd(gb_usb_dev->hcd); -error_create_hcd: - kfree(gb_usb_dev); + +err_put_hcd: + usb_put_hcd(hcd); + return retval; } static void gb_usb_connection_exit(struct gb_connection *connection) { - // FIXME - tear everything down! + struct gb_usb_device *gb_usb_dev = connection->private; + struct usb_hcd *hcd = gb_usb_device_to_hcd(gb_usb_dev); + + usb_remove_hcd(hcd); + usb_put_hcd(hcd); } static struct gb_protocol usb_protocol = { -- cgit v0.10.2 From b1e4a1f8519aebfbf99bee8b3839498f6645e2d7 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 30 Jul 2015 20:30:39 +0200 Subject: greybus: usb: fix hc_driver fields Fix hc_driver description, product_desc and flags fields. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/usb.c b/drivers/staging/greybus/usb.c index 1ba731e..151e49f 100644 --- a/drivers/staging/greybus/usb.c +++ b/drivers/staging/greybus/usb.c @@ -130,11 +130,12 @@ static int hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, } static struct hc_driver usb_gb_hc_driver = { - .description = "greybus_usb", - .product_desc = "GB-Bridge USB Controller", /* TODO: Get this from GPB ?*/ - .flags = HCD_MEMORY | HCD_USB2, /* FIXME: Get this from GPB */ + .description = "greybus-hcd", + .product_desc = "Greybus USB Host Controller", .hcd_priv_size = sizeof(struct gb_usb_device), + .flags = HCD_USB2, + .start = hcd_start, .stop = hcd_stop, -- cgit v0.10.2 From a422ecd28eb03eca86d2445d8d690402e183838b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 30 Jul 2015 20:30:40 +0200 Subject: greybus: usb: implement hub_control callback Implement the hub_control callback. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/usb.c b/drivers/staging/greybus/usb.c index 151e49f..17a5d7a 100644 --- a/drivers/staging/greybus/usb.c +++ b/drivers/staging/greybus/usb.c @@ -110,21 +110,41 @@ static int hub_status_data(struct usb_hcd *hcd, char *buf) static int hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) { - struct gb_usb_hub_control_request request; struct gb_usb_device *dev = to_gb_usb_device(hcd); + struct gb_operation *operation; + struct gb_usb_hub_control_request *request; + struct gb_usb_hub_control_response *response; + size_t response_size; int ret; - request.typeReq = cpu_to_le16(typeReq); - request.wValue = cpu_to_le16(wValue); - request.wIndex = cpu_to_le16(wIndex); - request.wLength = cpu_to_le16(wLength); - - // FIXME - buf needs to come back in struct gb_usb_hub_control_response - // for some types of requests, depending on typeReq. Do we do this in a - // "generic" way, or only ask for a response for the ones we "know" need - // a response (a small subset of all valid typeReq, thankfully.) - ret = gb_operation_sync(dev->connection, GB_USB_TYPE_HUB_CONTROL, - &request, sizeof(request), NULL, 0); + /* FIXME: handle unspecified lengths */ + response_size = sizeof(*response) + wLength; + + operation = gb_operation_create(dev->connection, + GB_USB_TYPE_HUB_CONTROL, + sizeof(*request), + response_size, + GFP_KERNEL); + if (!operation) + return -ENOMEM; + + request = operation->request->payload; + request->typeReq = cpu_to_le16(typeReq); + request->wValue = cpu_to_le16(wValue); + request->wIndex = cpu_to_le16(wIndex); + request->wLength = cpu_to_le16(wLength); + + ret = gb_operation_request_send_sync(operation); + if (ret) + goto out; + + if (wLength) { + /* Greybus core has verified response size */ + response = operation->response->payload; + memcpy(buf, response->buf, wLength); + } +out: + gb_operation_put(operation); return ret; } -- cgit v0.10.2 From a96493560cd16095fd00a936bfa9de8614bab842 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 30 Jul 2015 20:30:41 +0200 Subject: greybus: usb: disable protocol driver The USB bridged-PHY protocol driver currently depends on changes to USB core that are not yet upstream. Disable for now. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/usb.c b/drivers/staging/greybus/usb.c index 17a5d7a..50173b9 100644 --- a/drivers/staging/greybus/usb.c +++ b/drivers/staging/greybus/usb.c @@ -190,6 +190,18 @@ static int gb_usb_connection_init(struct gb_connection *connection) hcd->has_tt = 1; + /* + * FIXME: The USB bridged-PHY protocol driver depends on changes to + * USB core which are not yet upstream. + * + * Disable for now. + */ + if (1) { + dev_warn(&connection->dev, "USB protocol disabled\n"); + retval = -EPROTONOSUPPORT; + goto err_put_hcd; + } + retval = usb_add_hcd(hcd, 0, 0); if (retval) goto err_put_hcd; -- cgit v0.10.2 From f47c1b023ee55737ab5f6b6f479cab06a5a03ba2 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 29 Jul 2015 11:42:53 +0530 Subject: greybus: operation: Drop alignment attribute from operation message header The buffers allocated for message header is already 64 bit aligned and we have explicit pad bytes in the header structure, to 64 bit align the operation specific data. And so there is no need to add the aligned attribute to the operation message header. Drop it. Suggested-by: Johan Hovold Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 00189e9..1b7cc6a 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -62,7 +62,7 @@ enum gb_operation_result { * * The wire format for all numeric fields in the header is little * endian. Any operation-specific data begins immediately after the - * header, and is 64-bit aligned. + * header. */ struct gb_operation_msg_hdr { __le16 size; /* Size in bytes of header + payload */ @@ -70,7 +70,7 @@ struct gb_operation_msg_hdr { __u8 type; /* E.g GB_I2C_TYPE_* or GB_GPIO_TYPE_* */ __u8 result; /* Result of request (in responses only) */ __u8 pad[2]; /* must be zero (ignore when read) */ -} __aligned(sizeof(u64)); +}; #define GB_OPERATION_MESSAGE_SIZE_MIN sizeof(struct gb_operation_msg_hdr) #define GB_OPERATION_MESSAGE_SIZE_MAX U16_MAX -- cgit v0.10.2 From e34fae58f6e004baf26ddac937ac13bd53b7c5f2 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 29 Jul 2015 11:42:54 +0530 Subject: greybus: operation: Move operation header to greybus_protocols.h This should be exposed to external users (like gbsim). Move it to greybus_protocols.h. Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 61fe9dc..9192ee7 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -69,9 +69,38 @@ #define GB_CONTROL_CPORT_ID 2 -/* Control Protocol */ +/* + * All operation messages (both requests and responses) begin with + * a header that encodes the size of the message (header included). + * This header also contains a unique identifier, that associates a + * response message with its operation. The header contains an + * operation type field, whose interpretation is dependent on what + * type of protocol is used over the connection. The high bit + * (0x80) of the operation type field is used to indicate whether + * the message is a request (clear) or a response (set). + * + * Response messages include an additional result byte, which + * communicates the result of the corresponding request. A zero + * result value means the operation completed successfully. Any + * other value indicates an error; in this case, the payload of the + * response message (if any) is ignored. The result byte must be + * zero in the header for a request message. + * + * The wire format for all numeric fields in the header is little + * endian. Any operation-specific data begins immediately after the + * header. + */ +struct gb_operation_msg_hdr { + __le16 size; /* Size in bytes of header + payload */ + __le16 operation_id; /* Operation unique id */ + __u8 type; /* E.g GB_I2C_TYPE_* or GB_GPIO_TYPE_* */ + __u8 result; /* Result of request (in responses only) */ + __u8 pad[2]; /* must be zero (ignore when read) */ +}; +/* Control Protocol */ + /* version request has no payload */ struct gb_protocol_version_response { __u8 major; diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 1b7cc6a..16488d0 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -43,35 +43,6 @@ enum gb_operation_result { GB_OP_MALFUNCTION = 0xff, }; -/* - * All operation messages (both requests and responses) begin with - * a header that encodes the size of the message (header included). - * This header also contains a unique identifier, that associates a - * response message with its operation. The header contains an - * operation type field, whose interpretation is dependent on what - * type of protocol is used over the connection. The high bit - * (0x80) of the operation type field is used to indicate whether - * the message is a request (clear) or a response (set). - * - * Response messages include an additional result byte, which - * communicates the result of the corresponding request. A zero - * result value means the operation completed successfully. Any - * other value indicates an error; in this case, the payload of the - * response message (if any) is ignored. The result byte must be - * zero in the header for a request message. - * - * The wire format for all numeric fields in the header is little - * endian. Any operation-specific data begins immediately after the - * header. - */ -struct gb_operation_msg_hdr { - __le16 size; /* Size in bytes of header + payload */ - __le16 operation_id; /* Operation unique id */ - __u8 type; /* E.g GB_I2C_TYPE_* or GB_GPIO_TYPE_* */ - __u8 result; /* Result of request (in responses only) */ - __u8 pad[2]; /* must be zero (ignore when read) */ -}; - #define GB_OPERATION_MESSAGE_SIZE_MIN sizeof(struct gb_operation_msg_hdr) #define GB_OPERATION_MESSAGE_SIZE_MAX U16_MAX -- cgit v0.10.2 From 46d26c5d57daaa39a5f396b13544cdb4ec15d284 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Sat, 1 Aug 2015 11:50:37 +0200 Subject: greybus: greybus_protocols: fix typo in comment Fix misspelled variable name in comment. Reviewed-by: Alex Elder Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 9192ee7..0441de5 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -571,7 +571,7 @@ struct gb_spi_transfer_request { __u8 chip_select; /* of the spi device */ __u8 mode; /* of the spi device */ __le16 count; - struct gb_spi_transfer transfers[0]; /* trnasfer_count of these */ + struct gb_spi_transfer transfers[0]; /* count of these */ }; struct gb_spi_transfer_response { -- cgit v0.10.2 From 2130f09871a70ce425b8d328a641b7a1935ca831 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Sat, 1 Aug 2015 11:50:38 +0200 Subject: greybus: svc: fix message packing Add missing packed attributes to prevent implicit structure padding. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 0441de5..121300a 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -599,7 +599,7 @@ struct gb_spi_transfer_response { struct gb_svc_hello_request { __le16 endo_id; __u8 interface_id; -}; +} __packed; /* hello response has no payload */ struct gb_svc_intf_device_id_request { @@ -616,7 +616,7 @@ struct gb_svc_intf_hotplug_request { __le32 ara_vend_id; __le32 ara_prod_id; } data; -}; +} __packed; /* hotplug response has no payload */ struct gb_svc_intf_hot_unplug_request { @@ -634,7 +634,7 @@ struct gb_svc_conn_create_request { __u16 cport1_id; __u8 intf2_id; __u16 cport2_id; -}; +} __packed; /* connection create response has no payload */ struct gb_svc_conn_destroy_request { @@ -642,7 +642,7 @@ struct gb_svc_conn_destroy_request { __u16 cport1_id; __u8 intf2_id; __u16 cport2_id; -}; +} __packed; /* connection destroy response has no payload */ /* UART */ -- cgit v0.10.2 From cfc5f2c6deb5493d5854036f3d0f396ea4a3e99d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Sat, 1 Aug 2015 11:50:39 +0200 Subject: greybus: uart: fix message packing Add missing packed attributes to prevent implicit structure padding. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 121300a..cdd5b54 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -678,7 +678,7 @@ struct gb_uart_recv_data_request { __le16 size; __u8 flags; __u8 data[0]; -}; +} __packed; struct gb_uart_set_line_coding_request { __le32 rate; @@ -695,7 +695,7 @@ struct gb_uart_set_line_coding_request { #define GB_SERIAL_SPACE_PARITY 4 __u8 data_bits; -}; +} __packed; /* output control lines */ #define GB_UART_CTRL_DTR 0x01 -- cgit v0.10.2 From 8bbd9edcb71cee96fa7a835f3e445841b8c48fd7 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Sat, 1 Aug 2015 11:50:40 +0200 Subject: greybus: sdio: fix message packing Add missing packed attributes to prevent implicit structure padding. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index cdd5b54..e49376d 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -845,7 +845,7 @@ struct gb_sdio_set_ios_request { #define GB_SDIO_SET_DRIVER_TYPE_A 0x01 #define GB_SDIO_SET_DRIVER_TYPE_C 0x02 #define GB_SDIO_SET_DRIVER_TYPE_D 0x03 -}; +} __packed; /* command request */ struct gb_sdio_command_request { @@ -865,7 +865,7 @@ struct gb_sdio_command_request { #define GB_SDIO_CMD_BC 0x03 __le32 cmd_arg; -}; +} __packed; struct gb_sdio_command_response { __le32 resp[4]; @@ -881,7 +881,7 @@ struct gb_sdio_transfer_request { __le16 data_blocks; __le16 data_blksz; __u8 data[0]; -}; +} __packed; struct gb_sdio_transfer_response { __le16 data_blocks; -- cgit v0.10.2 From 5b559e64578783b944691f6f9e7c19812d2fced6 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Sat, 1 Aug 2015 11:50:41 +0200 Subject: greybus: greybus_protocols: use only type attributes for message packing For consistency reasons, use only type attributes for message packing. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index e49376d..290b85f 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -277,8 +277,8 @@ struct gb_gpio_set_value_request { struct gb_gpio_set_debounce_request { __u8 which; - __le16 usec __packed; -}; + __le16 usec; +} __packed; /* debounce response has no payload */ struct gb_gpio_irq_type_request { @@ -336,9 +336,9 @@ struct gb_pwm_deactivate_request { struct gb_pwm_config_request { __u8 which; - __le32 duty __packed; - __le32 period __packed; -}; + __le32 duty; + __le32 period; +} __packed; struct gb_pwm_polarity_request { __u8 which; -- cgit v0.10.2 From 03cb4fa92ae76cebdb519c92fd3839ac291eac0f Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 29 Jul 2015 11:44:08 +0530 Subject: greybus: svc: Move '{' to a new line in function definitions That's the style we follow for kernel code. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 784b770..b89e889 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -172,7 +172,8 @@ int gb_svc_connection_destroy(struct gb_svc *svc, EXPORT_SYMBOL_GPL(gb_svc_connection_destroy); int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, - u8 intf2_id, u8 dev2_id) { + u8 intf2_id, u8 dev2_id) +{ return route_create_operation(svc, intf1_id, dev1_id, intf2_id, dev2_id); } -- cgit v0.10.2 From bfb287a17e79f8d9bd6a99cf79634c4493ad7028 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 3 Aug 2015 12:57:09 -0500 Subject: greybus: interface: declare gb_interface_destroy() Add a public declaration for gb_interface_destroy(), matching gb_interface_create(). It's not yet used outside "interface.c" but I suppose it could be, and its scope is currently public. Signed-off-by: Alex Elder Reviewed-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 558e6db..e60a370 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -51,6 +51,7 @@ struct gb_interface *gb_interface_find(struct greybus_host_device *hd, struct gb_interface *gb_interface_create(struct greybus_host_device *hd, u8 interface_id); +void gb_interface_destroy(struct gb_interface *intf); int gb_interface_init(struct gb_interface *intf, u8 device_id); void gb_interface_remove(struct greybus_host_device *hd, u8 interface_id); void gb_interfaces_remove(struct greybus_host_device *hd); -- cgit v0.10.2 From 006335a02677ed20dbff44f398a9cbf823db0293 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 3 Aug 2015 12:57:10 -0500 Subject: greybus: looback: fix two typos Fix two misspellings. And add spaces around a '%' operator. Signed-off-by: Alex Elder Reviewed-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 08a77fe..08f7780 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -183,7 +183,7 @@ gb_loopback_ro_attr(iteration_count, u); * Type of loopback message to send based on protocol type definitions * 0 => Don't send message * 2 => Send ping message continuously (message without payload) - * 3 => Send transer message continuously (message with payload, + * 3 => Send transfer message continuously (message with payload, * payload returned in response) * 4 => Send a sink message (message with payload, no payload in response) */ @@ -410,7 +410,7 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb) do_div(tmp, NSEC_PER_USEC); lat = tmp; - /* Log latency stastic */ + /* Log latency statistic */ gb_loopback_update_stats(&gb->latency, lat); kfifo_in(&gb->kfifo, (unsigned char *)&lat, sizeof(lat)); @@ -584,7 +584,7 @@ static ssize_t loopback_read(struct file *file, char __user *buf, size_t count, size_t fifo_len; int retval; - if (!count || count%sizeof(u32)) + if (!count || count % sizeof(u32)) return -EINVAL; mutex_lock(&gb->mutex); -- cgit v0.10.2 From 3f12c3ed21d9e28ae2dc50a6c567ee5d5c6054d1 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 3 Aug 2015 12:57:11 -0500 Subject: greybus: loopback: drop unneeded casts for void pointers There is no need to cast a void pointer to a particular type. Drop the casts used in this way, mainly in the attribute definition macros. Signed-off-by: Alex Elder Reviewed-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 08f7780..66059a9 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -84,8 +84,7 @@ static ssize_t field##_show(struct device *dev, \ char *buf) \ { \ struct gb_connection *connection = to_gb_connection(dev); \ - struct gb_loopback *gb = \ - (struct gb_loopback *)connection->private; \ + struct gb_loopback *gb = connection->private; \ return sprintf(buf, "%"#type"\n", gb->field); \ } \ static DEVICE_ATTR_RO(field) @@ -96,8 +95,7 @@ static ssize_t name##_##field##_show(struct device *dev, \ char *buf) \ { \ struct gb_connection *connection = to_gb_connection(dev); \ - struct gb_loopback *gb = \ - (struct gb_loopback *)connection->private; \ + struct gb_loopback *gb = connection->private; \ return sprintf(buf, "%"#type"\n", gb->name.field); \ } \ static DEVICE_ATTR_RO(name##_##field) @@ -113,8 +111,7 @@ static ssize_t field##_show(struct device *dev, \ char *buf) \ { \ struct gb_connection *connection = to_gb_connection(dev); \ - struct gb_loopback *gb = \ - (struct gb_loopback *)connection->private; \ + struct gb_loopback *gb = connection->private; \ return sprintf(buf, "%"#type"\n", gb->field); \ } \ static ssize_t field##_store(struct device *dev, \ @@ -124,8 +121,7 @@ static ssize_t field##_store(struct device *dev, \ { \ int ret; \ struct gb_connection *connection = to_gb_connection(dev); \ - struct gb_loopback *gb = \ - (struct gb_loopback *)connection->private; \ + struct gb_loopback *gb = connection->private; \ mutex_lock(&gb->mutex); \ ret = sscanf(buf, "%"#type, &gb->field); \ if (ret != 1) \ @@ -423,7 +419,7 @@ static int gb_loopback_fn(void *data) { int error = 0; int ms_wait; - struct gb_loopback *gb = (struct gb_loopback *)data; + struct gb_loopback *gb = data; while (1) { if (!gb->type) -- cgit v0.10.2 From 3320e784550551ae8ae5c22d58e6b90addafe8a4 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 3 Aug 2015 12:57:12 -0500 Subject: greybus: loopback: use U64_MAX for initialization Use the largest representable value when initializing the "min" field when resetting loopback statistics. Signed-off-by: Alex Elder Reviewed-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 66059a9..cdefaff 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -340,7 +340,7 @@ static int gb_loopback_request_recv(u8 type, struct gb_operation *operation) static void gb_loopback_reset_stats(struct gb_loopback *gb) { struct gb_loopback_stats reset = { - .min = 0xffffffff, + .min = U64_MAX, }; memcpy(&gb->latency, &reset, sizeof(struct gb_loopback_stats)); memcpy(&gb->throughput, &reset, sizeof(struct gb_loopback_stats)); -- cgit v0.10.2 From a6e7e53548b0d54aab0a5c5449e7093a495555d8 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 3 Aug 2015 12:57:13 -0500 Subject: greybus: loopback: use u32 for stats update The only values supplied to gb_loopback_update_stats() are 32-bits, so change the type of the second argument to reflect that. Signed-off-by: Alex Elder Reviewed-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index cdefaff..2042bed 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -348,7 +348,7 @@ static void gb_loopback_reset_stats(struct gb_loopback *gb) sizeof(struct gb_loopback_stats)); } -static void gb_loopback_update_stats(struct gb_loopback_stats *stats, u64 val) +static void gb_loopback_update_stats(struct gb_loopback_stats *stats, u32 val) { if (stats->min > val) stats->min = val; -- cgit v0.10.2 From e051c82b2ba7fb3e237595c4f6d106e04a86baa1 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 3 Aug 2015 12:57:14 -0500 Subject: greybus: loopback: record 32-bit min and max The minimum and maximum values for stats values are always 32 bits. Change the type for these fields to reflect this. Signed-off-by: Alex Elder Reviewed-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 2042bed..2ec6c80 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -23,8 +23,8 @@ #include "greybus.h" struct gb_loopback_stats { - u64 min; - u64 max; + u32 min; + u32 max; u64 avg; u64 sum; u64 count; @@ -101,8 +101,8 @@ static ssize_t name##_##field##_show(struct device *dev, \ static DEVICE_ATTR_RO(name##_##field) #define gb_loopback_stats_attrs(field) \ - gb_loopback_ro_stats_attr(field, min, llu); \ - gb_loopback_ro_stats_attr(field, max, llu); \ + gb_loopback_ro_stats_attr(field, min, u); \ + gb_loopback_ro_stats_attr(field, max, u); \ gb_loopback_ro_stats_attr(field, avg, llu); #define gb_loopback_attr(field, type) \ @@ -340,7 +340,7 @@ static int gb_loopback_request_recv(u8 type, struct gb_operation *operation) static void gb_loopback_reset_stats(struct gb_loopback *gb) { struct gb_loopback_stats reset = { - .min = U64_MAX, + .min = U32_MAX, }; memcpy(&gb->latency, &reset, sizeof(struct gb_loopback_stats)); memcpy(&gb->throughput, &reset, sizeof(struct gb_loopback_stats)); -- cgit v0.10.2 From e13fc28f728ae6aa5e72c90a35d4fb0298205c6c Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 3 Aug 2015 12:57:15 -0500 Subject: greybus: loopback: use a 32-bit count The count of statistical samples recorded is currently a 64-bit value. 32 bits is sufficient, and in fact anything more than that won't work for the do_div() call it's pass to anyway. So make the count field be 32 bits. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 2ec6c80..580e002 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -27,7 +27,7 @@ struct gb_loopback_stats { u32 max; u64 avg; u64 sum; - u64 count; + u32 count; }; struct gb_loopback { -- cgit v0.10.2 From b937aa9e2a5e69cea4a0cc59b2d4dc7a0323ef60 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 3 Aug 2015 12:57:16 -0500 Subject: greybus: loopback: error is an unsigned attribute The error count is unsigned, so fix the format specifier used in its attribute definition. Signed-off-by: Alex Elder Reviewed-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 580e002..283a684 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -171,7 +171,7 @@ gb_loopback_stats_attrs(requests_per_second); /* Quantity of data sent and received on this cport */ gb_loopback_stats_attrs(throughput); /* Number of errors encountered during loop */ -gb_loopback_ro_attr(error, d); +gb_loopback_ro_attr(error, u); /* The current index of the for (i = 0; i < iteration_max; i++) loop */ gb_loopback_ro_attr(iteration_count, u); -- cgit v0.10.2 From 19c2a443c9efc87ae19d0ef7a5d212614a92479e Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 3 Aug 2015 12:57:17 -0500 Subject: greybus: loopback: all read-only attributes are unsigned The only values passed to the gb_loopback_ro_attr() macro are unsigned 32-bit values. So there's no need to pass a "type" format specifier. Signed-off-by: Alex Elder Reviewed-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 283a684..6afacdb 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -78,14 +78,14 @@ module_param(kfifo_depth, uint, 0444); define_get_version(gb_loopback, LOOPBACK); /* interface sysfs attributes */ -#define gb_loopback_ro_attr(field, type) \ +#define gb_loopback_ro_attr(field) \ static ssize_t field##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ struct gb_connection *connection = to_gb_connection(dev); \ struct gb_loopback *gb = connection->private; \ - return sprintf(buf, "%"#type"\n", gb->field); \ + return sprintf(buf, "%u\n", gb->field); \ } \ static DEVICE_ATTR_RO(field) @@ -171,9 +171,9 @@ gb_loopback_stats_attrs(requests_per_second); /* Quantity of data sent and received on this cport */ gb_loopback_stats_attrs(throughput); /* Number of errors encountered during loop */ -gb_loopback_ro_attr(error, u); +gb_loopback_ro_attr(error); /* The current index of the for (i = 0; i < iteration_max; i++) loop */ -gb_loopback_ro_attr(iteration_count, u); +gb_loopback_ro_attr(iteration_count); /* * Type of loopback message to send based on protocol type definitions -- cgit v0.10.2 From 7a135a965c62f7abdf8f3acc5ca45a03d27b272c Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 3 Aug 2015 12:57:18 -0500 Subject: greybus: loopback: use separate attribute macro for average Define a separate macro for displaying the average of the samples collected. This will be used so we can calculate the average only when requested, rather than every time a new value gets recorded. Signed-off-by: Alex Elder Reviewed-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 6afacdb..432eeab 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -100,10 +100,21 @@ static ssize_t name##_##field##_show(struct device *dev, \ } \ static DEVICE_ATTR_RO(name##_##field) +#define gb_loopback_ro_avg_attr(name) \ +static ssize_t name##_avg_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct gb_connection *connection = to_gb_connection(dev); \ + struct gb_loopback *gb = connection->private; \ + return sprintf(buf, "%llu\n", gb->name.avg); \ +} \ +static DEVICE_ATTR_RO(name##_avg) + #define gb_loopback_stats_attrs(field) \ gb_loopback_ro_stats_attr(field, min, u); \ gb_loopback_ro_stats_attr(field, max, u); \ - gb_loopback_ro_stats_attr(field, avg, llu); + gb_loopback_ro_avg_attr(field); #define gb_loopback_attr(field, type) \ static ssize_t field##_show(struct device *dev, \ -- cgit v0.10.2 From ff71d395f3cd5e5efe4b9b3c94c2d41581fb9d8c Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 3 Aug 2015 12:57:19 -0500 Subject: greybus: loopback: compute average stats on demand only Stop recording and updating the average every time a sample is recorded. Instead, compute it from the sum and count only when it's required. Signed-off-by: Alex Elder Reviewed-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 432eeab..e76f8a7 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -25,7 +25,6 @@ struct gb_loopback_stats { u32 min; u32 max; - u64 avg; u64 sum; u32 count; }; @@ -107,7 +106,11 @@ static ssize_t name##_avg_show(struct device *dev, \ { \ struct gb_connection *connection = to_gb_connection(dev); \ struct gb_loopback *gb = connection->private; \ - return sprintf(buf, "%llu\n", gb->name.avg); \ + struct gb_loopback_stats *stats = &gb->name; \ + u32 count = stats->count ? stats->count : 1; \ + u64 avg = stats->sum + count / 2; /* round closest */ \ + u32 rem = do_div(avg, count); \ + return sprintf(buf, "%llu.%06u\n", avg, 1000000 * rem / count); \ } \ static DEVICE_ATTR_RO(name##_avg) @@ -367,8 +370,6 @@ static void gb_loopback_update_stats(struct gb_loopback_stats *stats, u32 val) stats->max = val; stats->sum += val; stats->count++; - stats->avg = stats->sum; - do_div(stats->avg, stats->count); } static void gb_loopback_requests_update(struct gb_loopback *gb, u32 latency) -- cgit v0.10.2 From 1fb807cf6da0b65af4ba6ab100d38ebef17ff25e Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 3 Aug 2015 12:57:20 -0500 Subject: greybus: loopback: fix connection cleanup paths The error paths in gb_loopback_connection_init() are kind of screwed up--not in proper order, and the label naming convention seems a little inconsistent. Fix this, ensuring each error cleans up the setup that's been done up to that point. Use the convention that the label indicates the first thing that needs to be cleaned up. Reorder the statements in gb_loopback_connection_exit() to match the order of cleanup in gb_loopback_connection_init(). Signed-off-by: Alex Elder Reviewed-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index e76f8a7..564276d 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -490,19 +490,19 @@ static int gb_loopback_connection_init(struct gb_connection *connection) minor = ida_simple_get(&minors, 0, 0, GFP_KERNEL); if (minor < 0) { retval = minor; - goto out_free; + goto out_sysfs; } /* Check the version */ retval = get_version(gb); if (retval) - goto out_get_ver; + goto out_minor; /* Calculate maximum payload */ gb->size_max = gb_operation_get_payload_size_max(connection); if (gb->size_max <= sizeof(struct gb_loopback_transfer_request)) { retval = -EINVAL; - goto out_get_ver; + goto out_minor; } gb->size_max -= sizeof(struct gb_loopback_transfer_request); @@ -510,7 +510,7 @@ static int gb_loopback_connection_init(struct gb_connection *connection) if (kfifo_alloc(&gb->kfifo, kfifo_depth * sizeof(u32), GFP_KERNEL)) { retval = -ENOMEM; - goto out_get_ver; + goto out_minor; } /* Create device entry */ @@ -518,13 +518,13 @@ static int gb_loopback_connection_init(struct gb_connection *connection) cdev_init(&gb->cdev, &loopback_fops); retval = cdev_add(&gb->cdev, gb->dev, 1); if (retval) - goto out_cdev; + goto out_kfifo; gb->device = device_create(loopback_class, &connection->dev, gb->dev, gb, "gb!loopback%d", minor); if (IS_ERR(gb->device)) { retval = PTR_ERR(gb->device); - goto out_device; + goto out_cdev; } /* Fork worker thread */ @@ -533,21 +533,25 @@ static int gb_loopback_connection_init(struct gb_connection *connection) gb->task = kthread_run(gb_loopback_fn, gb, "gb_loopback"); if (IS_ERR(gb->task)) { retval = PTR_ERR(gb->task); - goto out_kfifo; + goto out_device; } return 0; out_device: - cdev_del(&gb->cdev); + device_del(gb->device); out_cdev: - ida_simple_remove(&minors, minor); + cdev_del(&gb->cdev); out_kfifo: kfifo_free(&gb->kfifo); -out_get_ver: +out_minor: + ida_simple_remove(&minors, minor); +out_sysfs: sysfs_remove_groups(&connection->dev.kobj, loopback_groups); out_free: + connection->private = NULL; kfree(gb); + return retval; } @@ -555,13 +559,14 @@ static void gb_loopback_connection_exit(struct gb_connection *connection) { struct gb_loopback *gb = connection->private; + connection->private = NULL; if (!IS_ERR_OR_NULL(gb->task)) kthread_stop(gb->task); - cdev_del(&gb->cdev); - ida_simple_remove(&minors, MINOR(gb->dev)); device_del(gb->device); + cdev_del(&gb->cdev); kfifo_free(&gb->kfifo); + ida_simple_remove(&minors, MINOR(gb->dev)); sysfs_remove_groups(&connection->dev.kobj, loopback_groups); kfree(gb); } -- cgit v0.10.2 From 47a96858b526e14882438e455ec078fc7e51155b Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 4 Aug 2015 13:44:10 -0500 Subject: greybus: kernel_ver.h: define U32_MAX and U64_MAX These were not defined, and I just posted patches that use them. Signed-off-by: Alex Elder Tested-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index c2e92df..d0e05e6 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -57,6 +57,14 @@ #define U16_MAX ((u16)(~0U)) #endif /* !U16_MAX */ +#ifndef U32_MAX +#define U32_MAX ((u32)(~0U)) +#endif /* !U32_MAX */ + +#ifndef U64_MAX +#define U64_MAX ((u64)(~0U)) +#endif /* !U64_MAX */ + /* * The GPIO api sucks rocks in places, like removal, so work around their * explicit requirements of catching the return value for kernels older than -- cgit v0.10.2 From 7fea641c94d645bf30712cb6e6c498597c7e5634 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 6 Aug 2015 12:44:52 +0530 Subject: greybus: raw: Print expected/actual payload size on mismatch Print (expected-payload-size actual-payload-size), when the size doesn't match for requests received by the module. This gives more details required for debugging the issue. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/raw.c b/drivers/staging/greybus/raw.c index 3be96db..a17a986 100644 --- a/drivers/staging/greybus/raw.c +++ b/drivers/staging/greybus/raw.c @@ -121,7 +121,8 @@ static int gb_raw_receive(u8 type, struct gb_operation *op) /* Verify size of payload */ if (op->request->payload_size < sizeof(*receive)) { - dev_err(raw->device, "raw receive request too small\n"); + dev_err(raw->device, "raw receive request too small (%zu < %zu)\n", + op->request->payload_size, sizeof(*receive)); return -EINVAL; } receive = op->request->payload; -- cgit v0.10.2 From 782c3b732889b5fbce796a4b548d47a43e4d8c42 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 6 Aug 2015 12:44:51 +0530 Subject: greybus: gpio: Print expected/actual payload size on mismatch Print (expected-payload-size actual-payload-size), when the size doesn't match for requests received by the module. This gives more details required for debugging the issue. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 6539530..caee9d1 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -366,7 +366,8 @@ static int gb_gpio_request_recv(u8 type, struct gb_operation *op) request = op->request; if (request->payload_size < sizeof(*event)) { - dev_err(ggc->chip.dev, "short event received\n"); + dev_err(ggc->chip.dev, "short event received (%zu < %zu)\n", + request->payload_size, sizeof(*event)); return -EINVAL; } -- cgit v0.10.2 From 6d05ad3c4226024ad78dfbd2ab683b760ab56389 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 6 Aug 2015 12:44:54 +0530 Subject: greybus: svc: Print expected/actual payload size on mismatch Print (expected-payload-size actual-payload-size), when the size doesn't match for requests received by the module. This gives more details required for debugging the issue. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index b89e889..4d59cbb 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -269,7 +269,8 @@ static int gb_svc_intf_hotplug_recv(struct gb_operation *op) int ret; if (request->payload_size < sizeof(*hotplug)) { - dev_err(dev, "%s: short hotplug request received\n", __func__); + dev_err(dev, "%s: short hotplug request received (%zu < %zu)\n", + __func__, request->payload_size, sizeof(*hotplug)); return -EINVAL; } @@ -372,7 +373,8 @@ static int gb_svc_intf_hot_unplug_recv(struct gb_operation *op) if (request->payload_size < sizeof(*hot_unplug)) { dev_err(&op->connection->dev, - "short hot unplug request received\n"); + "short hot unplug request received (%zu < %zu)\n", + request->payload_size, sizeof(*hot_unplug)); return -EINVAL; } @@ -400,7 +402,8 @@ static int gb_svc_intf_reset_recv(struct gb_operation *op) if (request->payload_size < sizeof(*reset)) { dev_err(&op->connection->dev, - "short reset request received\n"); + "short reset request received (%zu < %zu)\n", + request->payload_size, sizeof(*reset)); return -EINVAL; } reset = request->payload; -- cgit v0.10.2 From 067906f6906922ad784452218b09bfb2b9519643 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 6 Aug 2015 12:44:55 +0530 Subject: greybus: svc: Handle hotplug request from a workqueue Bringing up a module can be time consuming, as that may require lots of initialization on the module side. Over that, we may also need to download the firmware first and flash that on the module. In order to make other hotplug events to not wait for all this to finish, handle most of module hotplug stuff outside of the hotplug callback, with help of a workqueue. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 4d59cbb..4bf55e0 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -8,6 +8,7 @@ */ #include "greybus.h" +#include #define CPORT_FLAGS_E2EFC (1) #define CPORT_FLAGS_CSD_N (2) @@ -19,6 +20,12 @@ struct gb_svc { u8 version_minor; }; +struct svc_hotplug { + struct work_struct work; + struct gb_connection *connection; + struct gb_svc_intf_hotplug_request data; +}; + static struct ida greybus_svc_device_id_map; /* @@ -253,13 +260,19 @@ static int gb_svc_hello(struct gb_operation *op) return 0; } -static int gb_svc_intf_hotplug_recv(struct gb_operation *op) +/* + * 'struct svc_hotplug' should be freed by svc_process_hotplug() before it + * returns, irrespective of success or Failure in bringing up the module. + */ +static void svc_process_hotplug(struct work_struct *work) { - struct gb_message *request = op->request; - struct gb_svc_intf_hotplug_request *hotplug = request->payload; - struct gb_svc *svc = op->connection->private; - struct greybus_host_device *hd = op->connection->bundle->intf->hd; - struct device *dev = &op->connection->dev; + struct svc_hotplug *svc_hotplug = container_of(work, struct svc_hotplug, + work); + struct gb_svc_intf_hotplug_request *hotplug = &svc_hotplug->data; + struct gb_connection *connection = svc_hotplug->connection; + struct gb_svc *svc = connection->private; + struct greybus_host_device *hd = connection->bundle->intf->hd; + struct device *dev = &connection->dev; struct gb_interface *intf; u8 intf_id, device_id; u32 unipro_mfg_id; @@ -268,19 +281,8 @@ static int gb_svc_intf_hotplug_recv(struct gb_operation *op) u32 ara_prod_id; int ret; - if (request->payload_size < sizeof(*hotplug)) { - dev_err(dev, "%s: short hotplug request received (%zu < %zu)\n", - __func__, request->payload_size, sizeof(*hotplug)); - return -EINVAL; - } - /* * Grab the information we need. - * - * XXX I'd really like to acknowledge receipt, and then - * XXX continue processing the request. There's no need - * XXX for the SVC to wait. In fact, it might be best to - * XXX have the SVC get acknowledgement before we proceed. */ intf_id = hotplug->intf_id; unipro_mfg_id = le32_to_cpu(hotplug->data.unipro_mfg_id); @@ -293,7 +295,7 @@ static int gb_svc_intf_hotplug_recv(struct gb_operation *op) if (!intf) { dev_err(dev, "%s: Failed to create interface with id %hhu\n", __func__, intf_id); - return -EINVAL; + goto free_svc_hotplug; } /* @@ -346,7 +348,7 @@ static int gb_svc_intf_hotplug_recv(struct gb_operation *op) goto svc_id_free; } - return 0; + goto free_svc_hotplug; svc_id_free: /* @@ -357,8 +359,43 @@ ida_put: ida_simple_remove(&greybus_svc_device_id_map, device_id); destroy_interface: gb_interface_remove(hd, intf_id); +free_svc_hotplug: + kfree(svc_hotplug); +} - return ret; +/* + * Bringing up a module can be time consuming, as that may require lots of + * initialization on the module side. Over that, we may also need to download + * the firmware first and flash that on the module. + * + * In order to make other hotplug events to not wait for all this to finish, + * handle most of module hotplug stuff outside of the hotplug callback, with + * help of a workqueue. + */ +static int gb_svc_intf_hotplug_recv(struct gb_operation *op) +{ + struct gb_message *request = op->request; + struct svc_hotplug *svc_hotplug; + + if (request->payload_size < sizeof(svc_hotplug->data)) { + dev_err(&op->connection->dev, + "%s: short hotplug request received (%zu < %zu)\n", + __func__, request->payload_size, + sizeof(svc_hotplug->data)); + return -EINVAL; + } + + svc_hotplug = kmalloc(sizeof(*svc_hotplug), GFP_ATOMIC); + if (!svc_hotplug) + return -ENOMEM; + + svc_hotplug->connection = op->connection; + memcpy(&svc_hotplug->data, op->request->payload, sizeof(svc_hotplug->data)); + + INIT_WORK(&svc_hotplug->work, svc_process_hotplug); + queue_work(system_unbound_wq, &svc_hotplug->work); + + return 0; } static int gb_svc_intf_hot_unplug_recv(struct gb_operation *op) -- cgit v0.10.2 From f1f6fa44ae49e91c0a5fe9e0c6e5614e6aa22283 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Sat, 8 Aug 2015 08:09:32 +0530 Subject: greybus: sdio: error out only for smaller payloads received != was used in place of <, while comparing expected and actual payload size. The module may be running a higher version of the protocol and might have some extra fields (towards the end) in the structure, and the AP needs to ignore them. This also updates the print (expected-payload-size < actual-payload-size), when the size doesn't match for requests received by the module. This gives more details required for debugging. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index a709bd6..345cfff 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -192,8 +192,9 @@ static int gb_sdio_event_recv(u8 type, struct gb_operation *op) request = op->request; - if (request->payload_size != sizeof(*payload)) { - dev_err(mmc_dev(host->mmc), "wrong event size received\n"); + if (request->payload_size < sizeof(*payload)) { + dev_err(mmc_dev(host->mmc), "wrong event size received (%zu < %zu)\n", + request->payload_size, sizeof(*payload)); return -EINVAL; } -- cgit v0.10.2 From d79ae495e2ddb2b6f39376c4eed080dbc1b074d5 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Sat, 8 Aug 2015 10:25:32 +0530 Subject: greybus: hid: spell fix (s/infomation/information) Minor spell fix. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index a367fd5..d423f8e 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -84,7 +84,7 @@ struct gb_hid { static DEFINE_MUTEX(gb_hid_open_mutex); -/* Routines to get controller's infomation over greybus */ +/* Routines to get controller's information over greybus */ /* Define get_version() routine */ define_get_version(gb_hid, HID); -- cgit v0.10.2 From 8cbd20aa0de89eb344e05d51ae3bedfabeae360a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Sat, 8 Aug 2015 10:25:33 +0530 Subject: greybus: battery: Use (already defined) major/minor macros We already have macros for these, use them instead of writing fixed values. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery.c b/drivers/staging/greybus/battery.c index e666239..43799a3 100644 --- a/drivers/staging/greybus/battery.c +++ b/drivers/staging/greybus/battery.c @@ -372,8 +372,8 @@ static void gb_battery_connection_exit(struct gb_connection *connection) static struct gb_protocol battery_protocol = { .name = "battery", .id = GREYBUS_PROTOCOL_BATTERY, - .major = 0, - .minor = 1, + .major = GB_BATTERY_VERSION_MAJOR, + .minor = GB_BATTERY_VERSION_MINOR, .connection_init = gb_battery_connection_init, .connection_exit = gb_battery_connection_exit, .request_recv = NULL, /* no incoming requests */ -- cgit v0.10.2 From 8590ed30be0d3164073d90d1bcf728dd776487c4 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Sat, 8 Aug 2015 10:25:34 +0530 Subject: greybus: gpio: Use (already defined) major/minor macros We already have macros for these, use them instead of writing fixed values. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index caee9d1..a5db014 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -719,8 +719,8 @@ static void gb_gpio_connection_exit(struct gb_connection *connection) static struct gb_protocol gpio_protocol = { .name = "gpio", .id = GREYBUS_PROTOCOL_GPIO, - .major = 0, - .minor = 1, + .major = GB_GPIO_VERSION_MAJOR, + .minor = GB_GPIO_VERSION_MINOR, .connection_init = gb_gpio_connection_init, .connection_exit = gb_gpio_connection_exit, .request_recv = gb_gpio_request_recv, -- cgit v0.10.2 From 34ec36457f360fd2930fbf6e4cdfd6f7bc4d98c1 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Sat, 8 Aug 2015 10:25:35 +0530 Subject: greybus: hid: Use (already defined) major/minor macros We already have macros for these, use them instead of writing fixed values. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index d423f8e..0baed86 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -523,8 +523,8 @@ static void gb_hid_connection_exit(struct gb_connection *connection) static struct gb_protocol hid_protocol = { .name = "hid", .id = GREYBUS_PROTOCOL_HID, - .major = 0, - .minor = 1, + .major = GB_HID_VERSION_MAJOR, + .minor = GB_HID_VERSION_MINOR, .connection_init = gb_hid_connection_init, .connection_exit = gb_hid_connection_exit, .request_recv = gb_hid_irq_handler, -- cgit v0.10.2 From bbd80cc166dc841f6bab7fe721da157c6371e84b Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Sat, 8 Aug 2015 10:25:36 +0530 Subject: greybus: i2c: Use (already defined) major/minor macros We already have macros for these, use them instead of writing fixed values. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c index 9514e69..edb6753 100644 --- a/drivers/staging/greybus/i2c.c +++ b/drivers/staging/greybus/i2c.c @@ -349,8 +349,8 @@ static void gb_i2c_connection_exit(struct gb_connection *connection) static struct gb_protocol i2c_protocol = { .name = "i2c", .id = GREYBUS_PROTOCOL_I2C, - .major = 0, - .minor = 1, + .major = GB_I2C_VERSION_MAJOR, + .minor = GB_I2C_VERSION_MINOR, .connection_init = gb_i2c_connection_init, .connection_exit = gb_i2c_connection_exit, .request_recv = NULL, /* no incoming requests */ -- cgit v0.10.2 From 3fb97e43ba4ab094a72d9b9fe165e476e756c4ed Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Sat, 8 Aug 2015 10:25:37 +0530 Subject: greybus: pwm: Use (already defined) major/minor macros We already have macros for these, use them instead of writing fixed values. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/pwm.c b/drivers/staging/greybus/pwm.c index be7131a..c7f8c63 100644 --- a/drivers/staging/greybus/pwm.c +++ b/drivers/staging/greybus/pwm.c @@ -239,8 +239,8 @@ static void gb_pwm_connection_exit(struct gb_connection *connection) static struct gb_protocol pwm_protocol = { .name = "pwm", .id = GREYBUS_PROTOCOL_PWM, - .major = 0, - .minor = 1, + .major = GB_PWM_VERSION_MAJOR, + .minor = GB_PWM_VERSION_MINOR, .connection_init = gb_pwm_connection_init, .connection_exit = gb_pwm_connection_exit, .request_recv = NULL, /* no incoming requests */ -- cgit v0.10.2 From 7549219d4ea0a9d8b78c3819dff8dcdb9db14eb1 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Sat, 8 Aug 2015 10:25:38 +0530 Subject: greybus: spi: Use (already defined) major/minor macros We already have macros for these, use them instead of writing fixed values. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index 306fb07..77d6bf0 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -340,8 +340,8 @@ static void gb_spi_connection_exit(struct gb_connection *connection) static struct gb_protocol spi_protocol = { .name = "spi", .id = GREYBUS_PROTOCOL_SPI, - .major = 0, - .minor = 1, + .major = GB_SPI_VERSION_MAJOR, + .minor = GB_SPI_VERSION_MINOR, .connection_init = gb_spi_connection_init, .connection_exit = gb_spi_connection_exit, .request_recv = NULL, -- cgit v0.10.2 From 9475fb5c5ad1d61a37c2bd47fb94dcf55b59aaf2 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Sat, 8 Aug 2015 10:25:39 +0530 Subject: greybus: uart: Use (already defined) major/minor macros We already have macros for these, use them instead of writing fixed values. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 0166c4c..7a51c7c 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -767,8 +767,8 @@ static void gb_tty_exit(void) static struct gb_protocol uart_protocol = { .name = "uart", .id = GREYBUS_PROTOCOL_UART, - .major = 0, - .minor = 1, + .major = GB_UART_VERSION_MAJOR, + .minor = GB_UART_VERSION_MINOR, .connection_init = gb_uart_connection_init, .connection_exit = gb_uart_connection_exit, .request_recv = gb_uart_request_recv, -- cgit v0.10.2 From f514b5c31435909960fe32e309d7417c52629cc1 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Sat, 8 Aug 2015 10:25:40 +0530 Subject: greybus: usb: Use (already defined) major/minor macros We already have macros for these, use them instead of writing fixed values. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/usb.c b/drivers/staging/greybus/usb.c index 50173b9..80c42b2 100644 --- a/drivers/staging/greybus/usb.c +++ b/drivers/staging/greybus/usb.c @@ -226,8 +226,8 @@ static void gb_usb_connection_exit(struct gb_connection *connection) static struct gb_protocol usb_protocol = { .name = "usb", .id = GREYBUS_PROTOCOL_USB, - .major = 0, - .minor = 1, + .major = GB_USB_VERSION_MAJOR, + .minor = GB_USB_VERSION_MINOR, .connection_init = gb_usb_connection_init, .connection_exit = gb_usb_connection_exit, .request_recv = NULL, /* FIXME we have requests!!! */ -- cgit v0.10.2 From f0a1698f18722fccb920448285b8fc87f793870a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Sat, 8 Aug 2015 10:25:41 +0530 Subject: greybus: vibrator: Use (already defined) major/minor macros We already have macros for these, use them instead of writing fixed values. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/vibrator.c b/drivers/staging/greybus/vibrator.c index 62b3552..df9c4b1 100644 --- a/drivers/staging/greybus/vibrator.c +++ b/drivers/staging/greybus/vibrator.c @@ -167,8 +167,8 @@ static void gb_vibrator_connection_exit(struct gb_connection *connection) static struct gb_protocol vibrator_protocol = { .name = "vibrator", .id = GREYBUS_PROTOCOL_VIBRATOR, - .major = 0, - .minor = 1, + .major = GB_VIBRATOR_VERSION_MAJOR, + .minor = GB_VIBRATOR_VERSION_MINOR, .connection_init = gb_vibrator_connection_init, .connection_exit = gb_vibrator_connection_exit, .request_recv = NULL, /* no incoming requests */ -- cgit v0.10.2 From 33f06a75eecaa34b43c83f57280c6ef1ffedd101 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 7 Aug 2015 18:06:43 +0530 Subject: greybus: svc: Remove FIXME for firmware download Its handled by the firmware driver now, drop the FIXME comment from svc code. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 5f2b2b4..7ac45a9 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -256,7 +256,6 @@ static int gb_svc_intf_hotplug_recv(struct gb_operation *op) ara_vend_id = le32_to_cpu(hotplug->data.ara_vend_id); ara_prod_id = le32_to_cpu(hotplug->data.ara_prod_id); - // FIXME May require firmware download intf = gb_interface_create(hd, intf_id); if (!intf) { dev_err(dev, "%s: Failed to create interface with id %hhu\n", -- cgit v0.10.2 From 10c7ae04e36f05a82dd23eb314092c77df2c2049 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 11 Aug 2015 07:29:18 +0530 Subject: greybus: audio: Add '<' to the print message for short messages This increases readability a bit more, as it tells which value is actual size and which one is expected size. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio.c b/drivers/staging/greybus/audio.c index 9f5f959..0e9bec5 100644 --- a/drivers/staging/greybus/audio.c +++ b/drivers/staging/greybus/audio.c @@ -357,7 +357,7 @@ static int gb_i2s_mgmt_report_event_recv(u8 type, struct gb_operation *op) } if (op->request->payload_size < sizeof(*req)) { - dev_err(&connection->dev, "Short request received: %zu, %zu\n", + dev_err(&connection->dev, "Short request received (%zu < %zu)\n", op->request->payload_size, sizeof(*req)); return -EINVAL; } -- cgit v0.10.2 From 0c32d2a5b2a6f284efd196d568e1df3db5999c5d Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 11 Aug 2015 07:29:19 +0530 Subject: greybus: svc: error out only for smaller payloads received != was used in place of <, while comparing expected and actual payload size. The module may be running a higher version of the protocol and might have some extra fields (towards the end) in the structure, and the AP needs to ignore them. This also updates the print (expected-payload-size < actual-payload-size), when the size doesn't match for requests received by the module. This gives more details required for debugging. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 7ac45a9..17ffb13 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -193,8 +193,8 @@ static int gb_svc_hello(struct gb_operation *op) * SVC sends information about the endo and interface-id on the hello * request, use that to create an endo. */ - if (op->request->payload_size != sizeof(*hello_request)) { - dev_err(dev, "%s: Illegal size of hello request (%zu %zu)\n", + if (op->request->payload_size < sizeof(*hello_request)) { + dev_err(dev, "%s: Illegal size of hello request (%zu < %zu)\n", __func__, op->request->payload_size, sizeof(*hello_request)); return -EINVAL; -- cgit v0.10.2 From 186906590280c907ee497ed5e48bb94926d7b960 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 11 Aug 2015 07:35:56 +0530 Subject: greybus: connection: disconnect connection on failures during initialization Its possible for connection_init() to fail, in such cases the disconnected event must be sent to the module. It is missing currently, fix it. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 3b553e6..7a5840b 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -330,6 +330,27 @@ void gb_connection_destroy(struct gb_connection *connection) device_unregister(&connection->dev); } +static void gb_connection_disconnected(struct gb_connection *connection) +{ + struct gb_control *control; + int cport_id = connection->intf_cport_id; + int ret; + + /* + * Inform Interface about In-active CPorts. We don't need to do this + * operation for control cport. + */ + if (cport_id == GB_CONTROL_CPORT_ID) + return; + + control = connection->bundle->intf->control; + + ret = gb_control_disconnected_operation(control, cport_id); + if (ret) + dev_warn(&connection->dev, + "Failed to disconnect CPort-%d (%d)\n", cport_id, ret); +} + int gb_connection_init(struct gb_connection *connection) { int cport_id = connection->intf_cport_id; @@ -366,15 +387,18 @@ int gb_connection_init(struct gb_connection *connection) spin_lock_irq(&connection->lock); connection->state = GB_CONNECTION_STATE_ERROR; spin_unlock_irq(&connection->lock); + goto disconnect; } + return 0; + +disconnect: + gb_connection_disconnected(connection); return ret; } void gb_connection_exit(struct gb_connection *connection) { - int cport_id = connection->intf_cport_id; - if (!connection->protocol) { dev_warn(&connection->dev, "exit without protocol.\n"); return; @@ -391,21 +415,7 @@ void gb_connection_exit(struct gb_connection *connection) gb_connection_cancel_operations(connection, -ESHUTDOWN); connection->protocol->connection_exit(connection); - - /* - * Inform Interface about In-active CPorts. We don't need to do this - * operation for control cport. - */ - if (cport_id != GB_CONTROL_CPORT_ID) { - struct gb_control *control = connection->bundle->intf->control; - int ret; - - ret = gb_control_disconnected_operation(control, cport_id); - if (ret) - dev_warn(&connection->dev, - "Failed to disconnect CPort-%d (%d)\n", - cport_id, ret); - } + gb_connection_disconnected(connection); } void gb_hd_connections_exit(struct greybus_host_device *hd) -- cgit v0.10.2 From 2b11a45d29f52c94fdea1d8f1c7baa25cb7368bb Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 11 Aug 2015 07:35:57 +0530 Subject: greybus: define greybus wide protocol request numbers Some request numbers (like invalid and get_version) are same across all protocols. Create common macros for them. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 290b85f..b95d24b 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -99,6 +99,10 @@ struct gb_operation_msg_hdr { }; +/* Generic request numbers supported by all modules */ +#define GB_REQUEST_TYPE_INVALID 0x00 +#define GB_REQUEST_TYPE_PROTOCOL_VERSION 0x01 + /* Control Protocol */ /* version request has no payload */ -- cgit v0.10.2 From d653f4b19163aa9f3a8046bd6e895b8615856d11 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 11 Aug 2015 07:35:58 +0530 Subject: greybus: connection: Save major/minor supported by module Save major/minor number supported by the module inside connection structure, as this can be used later. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index f02b9d9..0dbbc20 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -34,6 +34,8 @@ struct gb_connection { u8 protocol_id; u8 major; u8 minor; + u8 module_major; + u8 module_minor; spinlock_t lock; enum gb_connection_state state; diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index 06b4841..ba80f55 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -182,6 +182,9 @@ int gb_protocol_get_version(struct gb_connection *connection, int type, return -ENOTSUPP; } + connection->module_major = response->major; + connection->module_minor = response->minor; + dev_dbg(&connection->dev, "version_major = %u version_minor = %u\n", response->major, response->minor); -- cgit v0.10.2 From 7ba26a8ced4a391133aa899a61647154d8d4d24c Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 11 Aug 2015 07:35:59 +0530 Subject: greybus: connection: request protocol version before initializing connection This can (should) be done from a common place as its required for most of the protocols. Do it. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 7a5840b..b1f1df8 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -382,17 +382,34 @@ int gb_connection_init(struct gb_connection *connection) connection->state = GB_CONNECTION_STATE_ENABLED; spin_unlock_irq(&connection->lock); - ret = connection->protocol->connection_init(connection); - if (ret) { - spin_lock_irq(&connection->lock); - connection->state = GB_CONNECTION_STATE_ERROR; - spin_unlock_irq(&connection->lock); - goto disconnect; + /* + * Request protocol version supported by the module. We don't need to do + * this for SVC as that is initiated by the SVC. + */ + if (connection->hd_cport_id != GB_SVC_CPORT_ID) { + struct gb_protocol_version_response response; + + ret = gb_protocol_get_version(connection, + GB_REQUEST_TYPE_PROTOCOL_VERSION, + NULL, 0, &response, + connection->protocol->major); + if (ret) { + dev_err(&connection->dev, + "Failed to get version CPort-%d (%d)\n", + cport_id, ret); + goto disconnect; + } } - return 0; + ret = connection->protocol->connection_init(connection); + if (!ret) + return 0; disconnect: + spin_lock_irq(&connection->lock); + connection->state = GB_CONNECTION_STATE_ERROR; + spin_unlock_irq(&connection->lock); + gb_connection_disconnected(connection); return ret; } -- cgit v0.10.2 From 9937a60a06ea21acc6680615258109a417ed25a8 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 11 Aug 2015 07:36:00 +0530 Subject: greybus: audio: Drop get_version support This is done from a common place now, no need to replicate it. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio-gb-cmds.c b/drivers/staging/greybus/audio-gb-cmds.c index 10de34d..112aed9 100644 --- a/drivers/staging/greybus/audio-gb-cmds.c +++ b/drivers/staging/greybus/audio-gb-cmds.c @@ -12,37 +12,9 @@ #include "greybus.h" #include "audio.h" -#define GB_I2S_MGMT_VERSION_MAJOR 0x00 -#define GB_I2S_MGMT_VERSION_MINOR 0x01 - -#define GB_I2S_DATA_VERSION_MAJOR 0x00 -#define GB_I2S_DATA_VERSION_MINOR 0x01 - /*********************************** * GB I2S helper functions ***********************************/ -int gb_i2s_mgmt_get_version(struct gb_connection *connection) -{ - struct gb_protocol_version_response response; - - memset(&response, 0, sizeof(response)); - return gb_protocol_get_version(connection, - GB_I2S_MGMT_TYPE_PROTOCOL_VERSION, - NULL, 0, &response, - GB_I2S_MGMT_VERSION_MAJOR); -} - -int gb_i2s_data_get_version(struct gb_connection *connection) -{ - struct gb_protocol_version_response response; - - memset(&response, 0, sizeof(response)); - return gb_protocol_get_version(connection, - GB_I2S_DATA_TYPE_PROTOCOL_VERSION, - NULL, 0, &response, - GB_I2S_DATA_VERSION_MAJOR); -} - int gb_i2s_mgmt_activate_cport(struct gb_connection *connection, uint16_t cport) { diff --git a/drivers/staging/greybus/audio.c b/drivers/staging/greybus/audio.c index 0e9bec5..6754c90 100644 --- a/drivers/staging/greybus/audio.c +++ b/drivers/staging/greybus/audio.c @@ -225,12 +225,6 @@ static int gb_i2s_transmitter_connection_init(struct gb_connection *connection) goto out_card; } - ret = gb_i2s_data_get_version(connection); - if (ret) { - pr_err("i2s data get_version() failed: %d\n", ret); - goto out_get_ver; - } - #if USE_RT5645 rt5647_info.addr = RT5647_I2C_ADDR; strlcpy(rt5647_info.type, "rt5647", I2C_NAME_SIZE); @@ -251,8 +245,10 @@ static int gb_i2s_transmitter_connection_init(struct gb_connection *connection) return 0; +#if USE_RT5645 out_get_ver: platform_device_unregister(&snd_dev->card); +#endif out_card: platform_device_unregister(&snd_dev->cpu_dai); out_dai: @@ -296,12 +292,6 @@ static int gb_i2s_mgmt_connection_init(struct gb_connection *connection) connection->private = snd_dev; spin_unlock_irqrestore(&snd_dev->lock, flags); - ret = gb_i2s_mgmt_get_version(connection); - if (ret) { - pr_err("i2s mgmt get_version() failed: %d\n", ret); - goto err_free_snd_dev; - } - ret = gb_i2s_mgmt_get_cfgs(snd_dev, connection); if (ret) { pr_err("can't get i2s configurations: %d\n", ret); diff --git a/drivers/staging/greybus/audio.h b/drivers/staging/greybus/audio.h index da95c1b..e497593 100644 --- a/drivers/staging/greybus/audio.h +++ b/drivers/staging/greybus/audio.h @@ -75,8 +75,6 @@ struct gb_snd { /* * GB I2S cmd functions */ -int gb_i2s_mgmt_get_version(struct gb_connection *connection); -int gb_i2s_data_get_version(struct gb_connection *connection); int gb_i2s_mgmt_activate_cport(struct gb_connection *connection, uint16_t cport); int gb_i2s_mgmt_deactivate_cport(struct gb_connection *connection, -- cgit v0.10.2 From f8cbc30de009fdf11aff0c5d9d5dfb3f8ceb4990 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 11 Aug 2015 07:36:01 +0530 Subject: greybus: battery: Drop get_version support This is done from a common place now, no need to replicate it. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery.c b/drivers/staging/greybus/battery.c index 43799a3..a56eb81 100644 --- a/drivers/staging/greybus/battery.c +++ b/drivers/staging/greybus/battery.c @@ -32,8 +32,6 @@ struct gb_battery { // updates from the SVC "on the fly" so we don't have to always go ask // the battery for some information. Hopefully... struct gb_connection *connection; - u8 version_major; - u8 version_minor; }; @@ -42,8 +40,6 @@ struct gb_battery { #define GB_BATTERY_VERSION_MINOR 0x01 /* Greybus battery request types */ -#define GB_BATTERY_TYPE_INVALID 0x00 -#define GB_BATTERY_TYPE_PROTOCOL_VERSION 0x01 #define GB_BATTERY_TYPE_TECHNOLOGY 0x02 #define GB_BATTERY_TYPE_STATUS 0x03 #define GB_BATTERY_TYPE_MAX_VOLTAGE 0x04 @@ -94,9 +90,6 @@ struct gb_battery_voltage_response { __le32 voltage; }; -/* Define get_version() routine */ -define_get_version(gb_battery, BATTERY); - static int get_tech(struct gb_battery *gb) { struct gb_battery_technology_response tech_response; @@ -345,12 +338,7 @@ static int gb_battery_connection_init(struct gb_connection *connection) gb->connection = connection; connection->private = gb; - /* Check the version */ - retval = get_version(gb); - if (retval) - goto out; retval = init_and_register(connection, gb); -out: if (retval) kfree(gb); -- cgit v0.10.2 From 507d75c4f4502cae84b50dcb0c246d67913e9ab5 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 11 Aug 2015 07:36:02 +0530 Subject: greybus: control: Drop get_version support This is done from a common place now, no need to replicate it. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index a69a703..605e6134 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -12,9 +12,6 @@ #include #include "greybus.h" -/* Define get_version() routine */ -define_get_version(gb_control, CONTROL); - /* Get Manifest's size from the interface */ int gb_control_get_manifest_size_operation(struct gb_interface *intf) { @@ -100,7 +97,6 @@ static int gb_control_request_recv(u8 type, struct gb_operation *op) static int gb_control_connection_init(struct gb_connection *connection) { struct gb_control *control; - int ret; control = kzalloc(sizeof(*control), GFP_KERNEL); if (!control) @@ -109,14 +105,10 @@ static int gb_control_connection_init(struct gb_connection *connection) control->connection = connection; connection->private = control; - ret = get_version(control); - if (ret) - kfree(control); - /* Set interface's control connection */ connection->bundle->intf->control = control; - return ret; + return 0; } static void gb_control_connection_exit(struct gb_connection *connection) diff --git a/drivers/staging/greybus/control.h b/drivers/staging/greybus/control.h index 6e41a2b..3248d96 100644 --- a/drivers/staging/greybus/control.h +++ b/drivers/staging/greybus/control.h @@ -12,8 +12,6 @@ struct gb_control { struct gb_connection *connection; - u8 version_major; - u8 version_minor; }; int gb_control_connected_operation(struct gb_control *control, u16 cport_id); -- cgit v0.10.2 From 03490fdbe745a6af23527df32e6ceab4b5749a8f Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 11 Aug 2015 07:36:03 +0530 Subject: greybus: gpio: Drop get_version support This is done from a common place now, no need to replicate it. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index a5db014..6a04a1b 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -33,8 +33,6 @@ struct gb_gpio_line { struct gb_gpio_controller { struct gb_connection *connection; - u8 version_major; - u8 version_minor; u8 line_max; /* max line number */ struct gb_gpio_line *lines; @@ -51,9 +49,6 @@ struct gb_gpio_controller { container_of(chip, struct gb_gpio_controller, chip) #define irq_data_to_gpio_chip(d) (d->domain->host_data) -/* Define get_version() routine */ -define_get_version(gb_gpio_controller, GPIO); - static int gb_gpio_line_count_operation(struct gb_gpio_controller *ggc) { struct gb_gpio_line_count_response response; @@ -476,11 +471,6 @@ static int gb_gpio_controller_setup(struct gb_gpio_controller *ggc) { int ret; - /* First thing we need to do is check the version */ - ret = get_version(ggc); - if (ret) - return ret; - /* Now find out how many lines there are */ ret = gb_gpio_line_count_operation(ggc); if (ret) -- cgit v0.10.2 From 2dad338c9c28f464c9717e9d0391997b649e3acd Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 11 Aug 2015 07:36:04 +0530 Subject: greybus: hid: Drop get_version support This is done from a common place now, no need to replicate it. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index 0baed86..887dbac 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -68,8 +68,6 @@ struct gb_hid_input_report_request { /* Greybus HID device's structure */ struct gb_hid { struct gb_connection *connection; - u8 version_major; - u8 version_minor; struct hid_device *hid; struct gb_hid_desc_response hdesc; @@ -86,9 +84,6 @@ static DEFINE_MUTEX(gb_hid_open_mutex); /* Routines to get controller's information over greybus */ -/* Define get_version() routine */ -define_get_version(gb_hid, HID); - /* Operations performed on greybus */ static int gb_hid_get_desc(struct gb_hid *ghid) { @@ -445,10 +440,6 @@ static int gb_hid_init(struct gb_hid *ghid) struct hid_device *hid = ghid->hid; int ret; - ret = get_version(ghid); - if (ret) - return ret; - ret = gb_hid_get_desc(ghid); if (ret) return ret; -- cgit v0.10.2 From d8886f4a06593fd1849a5076e08488c0ebaf74a3 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 11 Aug 2015 07:36:05 +0530 Subject: greybus: i2c: Drop get_version support This is done from a common place now, no need to replicate it. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c index edb6753..75b92d6 100644 --- a/drivers/staging/greybus/i2c.c +++ b/drivers/staging/greybus/i2c.c @@ -16,8 +16,6 @@ struct gb_i2c_device { struct gb_connection *connection; - u8 version_major; - u8 version_minor; u32 functionality; u16 timeout_msec; @@ -26,9 +24,6 @@ struct gb_i2c_device { struct i2c_adapter adapter; }; -/* Define get_version() routine */ -define_get_version(gb_i2c_device, I2C); - /* * Map Greybus i2c functionality bits into Linux ones */ @@ -277,11 +272,6 @@ static int gb_i2c_device_setup(struct gb_i2c_device *gb_i2c_dev) { int ret; - /* First thing we need to do is check the version */ - ret = get_version(gb_i2c_dev); - if (ret) - return ret; - /* Assume the functionality never changes, just get it once */ ret = gb_i2c_functionality_operation(gb_i2c_dev); if (ret) -- cgit v0.10.2 From 47d3cfbbadfb761aaf3967df314f860f8a324f8d Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 11 Aug 2015 07:36:06 +0530 Subject: greybus: loopback: Drop get_version support This is done from a common place now, no need to replicate it. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 564276d..88c329a 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -31,8 +31,6 @@ struct gb_loopback_stats { struct gb_loopback { struct gb_connection *connection; - u8 version_major; - u8 version_minor; struct kfifo kfifo; struct mutex mutex; @@ -73,9 +71,6 @@ module_param(kfifo_depth, uint, 0444); #define GB_LOOPBACK_MS_WAIT_MAX 1000 -/* Define get_version() routine */ -define_get_version(gb_loopback, LOOPBACK); - /* interface sysfs attributes */ #define gb_loopback_ro_attr(field) \ static ssize_t field##_show(struct device *dev, \ @@ -493,11 +488,6 @@ static int gb_loopback_connection_init(struct gb_connection *connection) goto out_sysfs; } - /* Check the version */ - retval = get_version(gb); - if (retval) - goto out_minor; - /* Calculate maximum payload */ gb->size_max = gb_operation_get_payload_size_max(connection); if (gb->size_max <= sizeof(struct gb_loopback_transfer_request)) { -- cgit v0.10.2 From 2e93d02c18ce39430a0cf0c591f067067bad2181 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 11 Aug 2015 07:36:07 +0530 Subject: greybus: pwm: Drop get_version support This is done from a common place now, no need to replicate it. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/pwm.c b/drivers/staging/greybus/pwm.c index c7f8c63..5f33589 100644 --- a/drivers/staging/greybus/pwm.c +++ b/drivers/staging/greybus/pwm.c @@ -16,8 +16,6 @@ struct gb_pwm_chip { struct gb_connection *connection; - u8 version_major; - u8 version_minor; u8 pwm_max; /* max pwm number */ struct pwm_chip chip; @@ -27,9 +25,6 @@ struct gb_pwm_chip { container_of(chip, struct gb_pwm_chip, chip) -/* Define get_version() routine */ -define_get_version(gb_pwm_chip, PWM); - static int gb_pwm_count_operation(struct gb_pwm_chip *pwmc) { struct gb_pwm_count_response response; @@ -194,11 +189,6 @@ static int gb_pwm_connection_init(struct gb_connection *connection) pwmc->connection = connection; connection->private = pwmc; - /* Check for compatible protocol version */ - ret = get_version(pwmc); - if (ret) - goto out_err; - /* Query number of pwms present */ ret = gb_pwm_count_operation(pwmc); if (ret) -- cgit v0.10.2 From f06eda1b1744fcde6769eee22bceb7d9fee23bf5 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 11 Aug 2015 07:36:08 +0530 Subject: greybus: raw: Drop get_version support This is done from a common place now, no need to replicate it. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/raw.c b/drivers/staging/greybus/raw.c index a17a986..215d421 100644 --- a/drivers/staging/greybus/raw.c +++ b/drivers/staging/greybus/raw.c @@ -19,8 +19,6 @@ struct gb_raw { struct gb_connection *connection; - u8 version_major; - u8 version_minor; struct list_head list; int list_data; @@ -35,13 +33,8 @@ struct gb_raw { #define GB_RAW_VERSION_MINOR 0x01 /* Greybus raw request types */ -#define GB_RAW_TYPE_INVALID 0x00 -#define GB_RAW_TYPE_PROTOCOL_VERSION 0x01 #define GB_RAW_TYPE_SEND 0x02 -/* Define get_version() routine */ -define_get_version(gb_raw, RAW); - struct gb_raw_send_request { __le32 len; __u8 data[0]; @@ -180,11 +173,6 @@ static int gb_raw_connection_init(struct gb_connection *connection) raw->connection = connection; connection->private = raw; - /* Check the protocol version */ - retval = get_version(raw); - if (retval) - goto error_free; - INIT_LIST_HEAD(&raw->list); mutex_init(&raw->list_lock); -- cgit v0.10.2 From 7071ca1df5e26949e6a24684f52d45ca18f07077 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 11 Aug 2015 07:36:09 +0530 Subject: greybus: sdio: Drop get_version support This is done from a common place now, no need to replicate it. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index 345cfff..24b2e31 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -18,8 +18,6 @@ struct gb_sdio_host { struct gb_connection *connection; - u8 version_major; - u8 version_minor; struct mmc_host *mmc; struct mmc_request *mrq; struct mutex lock; /* lock for this host */ @@ -36,9 +34,6 @@ struct gb_sdio_host { static struct workqueue_struct *gb_sdio_mrq_workqueue; -/* Define get_version() routine */ -define_get_version(gb_sdio_host, SDIO); - #define GB_SDIO_RSP_R1_R5_R6_R7 (GB_SDIO_RSP_PRESENT | GB_SDIO_RSP_CRC | \ GB_SDIO_RSP_OPCODE) #define GB_SDIO_RSP_R3_R4 (GB_SDIO_RSP_PRESENT) @@ -695,10 +690,6 @@ static int gb_sdio_connection_init(struct gb_connection *connection) host->connection = connection; connection->private = host; - ret = get_version(host); - if (ret < 0) - goto free_mmc; - ret = gb_sdio_get_caps(host); if (ret < 0) goto free_mmc; -- cgit v0.10.2 From 3fb0c8f516e06cb3bc39610aeb1311b8376bdc61 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 11 Aug 2015 07:36:10 +0530 Subject: greybus: spi: Drop get_version support This is done from a common place now, no need to replicate it. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index 77d6bf0..ef3cc33 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -17,8 +17,6 @@ struct gb_spi { struct gb_connection *connection; - u8 version_major; - u8 version_minor; /* Modes supported by spi controller */ u16 mode; @@ -181,9 +179,6 @@ static void gb_spi_cleanup(struct spi_device *spi) /* Routines to get controller infomation */ -/* Define get_version() routine */ -define_get_version(gb_spi, SPI); - /* * Map Greybus spi mode bits/flags/bpw into Linux ones. * All bits are same for now and so these macro's return same values. @@ -264,11 +259,6 @@ static int gb_spi_init(struct gb_spi *spi) { int ret; - /* First thing we need to do is check the version */ - ret = get_version(spi); - if (ret) - return ret; - /* mode never changes, just get it once */ ret = gb_spi_mode_operation(spi); if (ret) -- cgit v0.10.2 From a94e14486477b5738061ac09ab69025985c1eda5 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 11 Aug 2015 07:36:11 +0530 Subject: greybus: uart: Drop get_version support This is done from a common place now, no need to replicate it. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 7a51c7c..9e8bf6f 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -55,8 +55,6 @@ struct gb_tty { struct async_icount oldcount; wait_queue_head_t wioctl; struct mutex mutex; - u8 version_major; - u8 version_minor; u8 ctrlin; /* input control lines */ u8 ctrlout; /* output control lines */ struct gb_tty_line_coding line_coding; @@ -67,9 +65,6 @@ static DEFINE_IDR(tty_minors); static DEFINE_MUTEX(table_lock); static atomic_t reference_count = ATOMIC_INIT(0); -/* Define get_version() routine */ -define_get_version(gb_tty, UART); - static int gb_uart_receive_data(struct gb_tty *gb_tty, struct gb_connection *connection, struct gb_uart_recv_data_request *receive_data) @@ -628,21 +623,16 @@ static int gb_uart_connection_init(struct gb_connection *connection) gb_tty->connection = connection; connection->private = gb_tty; - /* Check for compatible protocol version */ - retval = get_version(gb_tty); - if (retval) - goto error_version; - minor = alloc_minor(gb_tty); if (minor < 0) { if (minor == -ENOSPC) { dev_err(&connection->dev, "no more free minor numbers\n"); retval = -ENODEV; - goto error_version; + goto error_minor; } retval = minor; - goto error_version; + goto error_minor; } gb_tty->minor = minor; @@ -674,7 +664,7 @@ static int gb_uart_connection_init(struct gb_connection *connection) error: tty_port_destroy(&gb_tty->port); release_minor(gb_tty); -error_version: +error_minor: connection->private = NULL; kfree(gb_tty->buffer); error_payload: -- cgit v0.10.2 From 0a12a187fdaa90108a681423a7f1e8ef135a1544 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 11 Aug 2015 07:36:12 +0530 Subject: greybus: usb: Drop get_version support This is done from a common place now, no need to replicate it. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/usb.c b/drivers/staging/greybus/usb.c index 80c42b2..2133d0d 100644 --- a/drivers/staging/greybus/usb.c +++ b/drivers/staging/greybus/usb.c @@ -20,8 +20,6 @@ #define GB_USB_VERSION_MINOR 0x01 /* Greybus USB request types */ -#define GB_USB_TYPE_INVALID 0x00 -#define GB_USB_TYPE_PROTOCOL_VERSION 0x01 #define GB_USB_TYPE_HCD_START 0x02 #define GB_USB_TYPE_HCD_STOP 0x03 #define GB_USB_TYPE_HUB_CONTROL 0x04 @@ -39,9 +37,6 @@ struct gb_usb_hub_control_response { struct gb_usb_device { struct gb_connection *connection; - - u8 version_major; - u8 version_minor; }; static inline struct gb_usb_device *to_gb_usb_device(struct usb_hcd *hcd) @@ -54,9 +49,6 @@ static inline struct usb_hcd *gb_usb_device_to_hcd(struct gb_usb_device *dev) return container_of((void *)dev, struct usb_hcd, hcd_priv); } -/* Define get_version() routine */ -define_get_version(gb_usb_device, USB); - static void hcd_stop(struct usb_hcd *hcd) { struct gb_usb_device *dev = to_gb_usb_device(hcd); @@ -183,11 +175,6 @@ static int gb_usb_connection_init(struct gb_connection *connection) gb_usb_dev->connection = connection; connection->private = gb_usb_dev; - /* Check for compatible protocol version */ - retval = get_version(gb_usb_dev); - if (retval) - goto err_put_hcd; - hcd->has_tt = 1; /* -- cgit v0.10.2 From a404504a8651250b2632cf62356de6c77a923430 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 11 Aug 2015 07:36:13 +0530 Subject: greybus: vibrator: Drop get_version support This is done from a common place now, no need to replicate it. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/vibrator.c b/drivers/staging/greybus/vibrator.c index df9c4b1..96d649a 100644 --- a/drivers/staging/greybus/vibrator.c +++ b/drivers/staging/greybus/vibrator.c @@ -19,8 +19,6 @@ struct gb_vibrator_device { struct gb_connection *connection; struct device *dev; int minor; /* vibrator minor number */ - u8 version_major; - u8 version_minor; }; /* Version of the Greybus vibrator protocol we support */ @@ -28,8 +26,6 @@ struct gb_vibrator_device { #define GB_VIBRATOR_VERSION_MINOR 0x01 /* Greybus Vibrator operation types */ -#define GB_VIBRATOR_TYPE_INVALID 0x00 -#define GB_VIBRATOR_TYPE_PROTOCOL_VERSION 0x01 #define GB_VIBRATOR_TYPE_ON 0x02 #define GB_VIBRATOR_TYPE_OFF 0x03 @@ -37,9 +33,6 @@ struct gb_vibrator_on_request { __le16 timeout_ms; }; -/* Define get_version() routine */ -define_get_version(gb_vibrator_device, VIBRATOR); - static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms) { struct gb_vibrator_on_request request; @@ -108,10 +101,6 @@ static int gb_vibrator_connection_init(struct gb_connection *connection) vib->connection = connection; connection->private = vib; - retval = get_version(vib); - if (retval) - goto error; - /* * For now we create a device in sysfs for the vibrator, but odds are * there is a "real" device somewhere in the kernel for this, but I -- cgit v0.10.2 From 3ea959e3911e0c9ae49eb855d7b4f744349eb977 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 11 Aug 2015 07:36:14 +0530 Subject: greybus: svc: preserve major/minor of protocol supported by SVC These weren't preserved earlier, save them in the connection structure instead of creating its own fields.. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 17ffb13..025b2ba 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -11,8 +11,6 @@ struct gb_svc { struct gb_connection *connection; - u8 version_major; - u8 version_minor; }; static struct ida greybus_svc_device_id_map; @@ -163,6 +161,9 @@ static int gb_svc_version_request(struct gb_operation *op) return -ENOTSUPP; } + connection->module_major = version->major; + connection->module_minor = version->minor; + if (!gb_operation_response_alloc(op, sizeof(*version), GFP_KERNEL)) { dev_err(dev, "%s: error allocating response\n", __func__); -- cgit v0.10.2 From b9938c49131f1d2c65e8783a5a17ff6a96d9ce89 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 11 Aug 2015 07:36:15 +0530 Subject: greybus: protocol: Drop define_get_version support No more users now, drop it. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index 758b36e..45606ad 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -107,27 +107,4 @@ void gb_##__protocol##_exit(void) \ gb_protocol_deregister(&__protocol); \ } \ -/* - * Macro to create get_version() routine for protocols - * @__device: name of the device struct - * @__protocol: name of protocol in CAPITALS - */ -#define define_get_version(__device, __protocol) \ -static int get_version(struct __device *dev) \ -{ \ - struct gb_protocol_version_response response; \ - int retval; \ - \ - retval = gb_protocol_get_version(dev->connection, \ - GB_##__protocol##_TYPE_PROTOCOL_VERSION,\ - NULL, 0, &response, \ - GB_##__protocol##_VERSION_MAJOR); \ - if (retval) \ - return retval; \ - \ - dev->version_major = response.major; \ - dev->version_minor = response.minor; \ - return 0; \ -} - #endif /* __PROTOCOL_H */ -- cgit v0.10.2 From bf81454738990e7acd089e1b8aac8bab6a54637f Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 11 Aug 2015 07:36:16 +0530 Subject: greybus: protocol: Remove unnecessary params of gb_protocol_get_version() Some of the parameters are not really required, drop them. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index b1f1df8..88383b6 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -387,12 +387,7 @@ int gb_connection_init(struct gb_connection *connection) * this for SVC as that is initiated by the SVC. */ if (connection->hd_cport_id != GB_SVC_CPORT_ID) { - struct gb_protocol_version_response response; - - ret = gb_protocol_get_version(connection, - GB_REQUEST_TYPE_PROTOCOL_VERSION, - NULL, 0, &response, - connection->protocol->major); + ret = gb_protocol_get_version(connection, NULL, 0); if (ret) { dev_err(&connection->dev, "Failed to get version CPort-%d (%d)\n", diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index ba80f55..b63e28c 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -163,30 +163,30 @@ struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor) return protocol; } -int gb_protocol_get_version(struct gb_connection *connection, int type, - void *request, int request_size, - struct gb_protocol_version_response *response, - __u8 major) +int gb_protocol_get_version(struct gb_connection *connection, void *request, + int request_size) { + struct gb_protocol_version_response response; int retval; - retval = gb_operation_sync(connection, type, request, request_size, - response, sizeof(*response)); + retval = gb_operation_sync(connection, GB_REQUEST_TYPE_PROTOCOL_VERSION, + request, request_size, &response, + sizeof(response)); if (retval) return retval; - if (response->major > major) { + if (response.major > connection->protocol->major) { dev_err(&connection->dev, "unsupported major version (%hhu > %hhu)\n", - response->major, major); + response.major, connection->protocol->major); return -ENOTSUPP; } - connection->module_major = response->major; - connection->module_minor = response->minor; + connection->module_major = response.major; + connection->module_minor = response.minor; dev_dbg(&connection->dev, "version_major = %u version_minor = %u\n", - response->major, response->minor); + response.major, response.minor); return 0; } diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index 45606ad..34a7f18 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -44,10 +44,8 @@ int gb_protocol_deregister(struct gb_protocol *protocol); __gb_protocol_register(protocol, THIS_MODULE) struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor); -int gb_protocol_get_version(struct gb_connection *connection, int type, - void *request, int request_size, - struct gb_protocol_version_response *response, - __u8 major); +int gb_protocol_get_version(struct gb_connection *connection, void *request, + int request_size); void gb_protocol_put(struct gb_protocol *protocol); -- cgit v0.10.2 From 8ebc998f5fb146b7304fb7ac4e4d80059b6197fe Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 11 Aug 2015 13:50:50 +0100 Subject: greybus: connection: fix jump label on device_add failure On device_add() failure in gb_connection_create_range() we jump to err_remove_ida. Instead we should be jumping to err_free_connection, so change the flow to accomodate. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 88383b6..3765aa8 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -238,7 +238,7 @@ gb_connection_create_range(struct greybus_host_device *hd, pr_err("failed to add connection device for cport 0x%04hx\n", cport_id); - goto err_remove_ida; + goto err_free_connection; } spin_lock_irq(&gb_connections_lock); -- cgit v0.10.2 From a1a4a29cb9e9593a1f47d549af212f35f131e6cc Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 11 Aug 2015 13:50:51 +0100 Subject: greybus: connection: add a timestamp kfifo to track connection handoff For the ES2 test activity it may be beneficial to have a performance metric that doesn't include any of the greybus stack malloc, workqueues etc. In order to faciltate, this patch adds a simple kfifo structure to hold two timestamp values. One timestamp will represent the last reasonable point a greybus outbound timestamp can be taken, the other timestamp will represent the first reasonable point an inbound timestamp can be taken. In order to facilitate this model, tracking the timestamps in the connection structure appears to be the best place to keep store of this data. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 3765aa8..0ec5b0d 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -11,6 +11,10 @@ #include "greybus.h" +#define GB_CONNECTION_TS_KFIFO_ELEMENTS 2 +#define GB_CONNECTION_TS_KFIFO_LEN \ + (GB_CONNECTION_TS_KFIFO_ELEMENTS * sizeof(struct timeval)) + static DEFINE_SPINLOCK(gb_connections_lock); /* This is only used at initialization time; no locking is required. */ @@ -63,6 +67,29 @@ void greybus_data_rcvd(struct greybus_host_device *hd, u16 cport_id, } EXPORT_SYMBOL_GPL(greybus_data_rcvd); +void gb_connection_push_timestamp(struct gb_connection *connection) +{ + struct timeval tv; + + do_gettimeofday(&tv); + kfifo_in_locked(&connection->ts_kfifo, (void *)&tv, + sizeof(struct timeval), &connection->lock); +} +EXPORT_SYMBOL_GPL(gb_connection_push_timestamp); + +int gb_connection_pop_timestamp(struct gb_connection *connection, + struct timeval *tv) +{ + int retval; + + if (!kfifo_len(&connection->ts_kfifo)) + return -ENOMEM; + retval = kfifo_out_locked(&connection->ts_kfifo, (void *)tv, + sizeof(*tv), &connection->lock); + return retval; +} +EXPORT_SYMBOL_GPL(gb_connection_pop_timestamp); + static ssize_t state_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -102,6 +129,7 @@ static void gb_connection_release(struct device *dev) struct gb_connection *connection = to_gb_connection(dev); destroy_workqueue(connection->wq); + kfifo_free(&connection->ts_kfifo); kfree(connection); } @@ -222,6 +250,10 @@ gb_connection_create_range(struct greybus_host_device *hd, if (!connection->wq) goto err_free_connection; + if (kfifo_alloc(&connection->ts_kfifo, GB_CONNECTION_TS_KFIFO_LEN, + GFP_KERNEL)) + goto err_free_connection; + connection->dev.parent = parent; connection->dev.bus = &greybus_bus_type; connection->dev.type = &greybus_connection_type; @@ -238,7 +270,7 @@ gb_connection_create_range(struct greybus_host_device *hd, pr_err("failed to add connection device for cport 0x%04hx\n", cport_id); - goto err_free_connection; + goto err_free_kfifo; } spin_lock_irq(&gb_connections_lock); @@ -259,6 +291,8 @@ gb_connection_create_range(struct greybus_host_device *hd, return connection; +err_free_kfifo: + kfifo_free(&connection->ts_kfifo); err_free_connection: kfree(connection); err_remove_ida: diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 0dbbc20..a26a480 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -11,6 +11,7 @@ #define __CONNECTION_H #include +#include enum gb_connection_state { GB_CONNECTION_STATE_INVALID = 0, @@ -42,6 +43,7 @@ struct gb_connection { struct list_head operations; struct workqueue_struct *wq; + struct kfifo ts_kfifo; atomic_t op_cycle; @@ -65,6 +67,9 @@ void gb_hd_connections_exit(struct greybus_host_device *hd); void greybus_data_rcvd(struct greybus_host_device *hd, u16 cport_id, u8 *data, size_t length); +void gb_connection_push_timestamp(struct gb_connection *connection); +int gb_connection_pop_timestamp(struct gb_connection *connection, + struct timeval *tv); void gb_connection_bind_protocol(struct gb_connection *connection); -- cgit v0.10.2 From 3f2a809e8b4c69f61de17c3efe144b9dba23924b Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 11 Aug 2015 13:50:52 +0100 Subject: greybus: es-drivers: add outbound timestamp to connection In order to facilitate grabbing a timestamp that doesn't include greybus overhead, this patch adds a timestamp right before usb_submit_urb() for both es1.c and es2.c. Long term the timestmaping of messages like this probably wants to go away but, for the moment it may have some use to the firmware people instrumenting the performance of the system. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 0cb7a3c..7fe1eaa 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -16,6 +16,7 @@ #include "greybus.h" #include "svc_msg.h" #include "kernel_ver.h" +#include "connection.h" /* Memory sizes for the buffers sent to/from the ES1 controller */ #define ES1_SVC_MSG_SIZE (sizeof(struct svc_msg) + SZ_64K) @@ -244,6 +245,7 @@ static int message_send(struct greybus_host_device *hd, u16 cport_id, usb_sndbulkpipe(udev, es1->cport_out_endpoint), message->buffer, buffer_size, cport_out_callback, message); + gb_connection_push_timestamp(message->operation->connection); retval = usb_submit_urb(urb, gfp_mask); if (retval) { pr_err("error %d submitting URB\n", retval); diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 323721a..43cbc4d 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -16,6 +16,7 @@ #include "greybus.h" #include "svc_msg.h" #include "kernel_ver.h" +#include "connection.h" /* Memory sizes for the buffers sent to/from the ES1 controller */ #define ES1_SVC_MSG_SIZE (sizeof(struct svc_msg) + SZ_64K) @@ -340,6 +341,7 @@ static int message_send(struct greybus_host_device *hd, u16 cport_id, es1->cport_out[bulk_ep_set].endpoint), message->buffer, buffer_size, cport_out_callback, message); + gb_connection_push_timestamp(message->operation->connection); retval = usb_submit_urb(urb, gfp_mask); if (retval) { pr_err("error %d submitting URB\n", retval); -- cgit v0.10.2 From 4c192665f0183150cff38b6954687752f3461e13 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 11 Aug 2015 13:50:53 +0100 Subject: greybus: loopback: functionally decompose calculation of turn-around times We have a pattern similar to this over and over again gb->elapsed_nsecs = timeval_to_ns(&te) - timeval_to_ns(&ts); good software practice dictates we functionally decompose this. This patch decomposes into gb_loopback_calc_latency(). Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 88c329a..ac38644 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -219,6 +219,16 @@ static struct attribute *loopback_attrs[] = { }; ATTRIBUTE_GROUPS(loopback); +static void gb_loopback_calc_latency(struct gb_loopback *gb, + struct timeval *ts, struct timeval *te) +{ + u64 t1, t2; + + t1 = timeval_to_ns(ts); + t2 = timeval_to_ns(te); + gb->elapsed_nsecs = t2 - t1; +} + static int gb_loopback_sink(struct gb_loopback *gb, u32 len) { struct timeval ts, te; @@ -236,7 +246,7 @@ static int gb_loopback_sink(struct gb_loopback *gb, u32 len) request, len + sizeof(*request), NULL, 0); do_gettimeofday(&te); - gb->elapsed_nsecs = timeval_to_ns(&te) - timeval_to_ns(&ts); + gb_loopback_calc_latency(gb, &ts, &te); kfree(request); return retval; @@ -265,7 +275,7 @@ static int gb_loopback_transfer(struct gb_loopback *gb, u32 len) request, len + sizeof(*request), response, len + sizeof(*response)); do_gettimeofday(&te); - gb->elapsed_nsecs = timeval_to_ns(&te) - timeval_to_ns(&ts); + gb_loopback_calc_latency(gb, &ts, &te); if (retval) goto gb_error; @@ -289,7 +299,7 @@ static int gb_loopback_ping(struct gb_loopback *gb) retval = gb_operation_sync(gb->connection, GB_LOOPBACK_TYPE_PING, NULL, 0, NULL, 0); do_gettimeofday(&te); - gb->elapsed_nsecs = timeval_to_ns(&te) - timeval_to_ns(&ts); + gb_loopback_calc_latency(gb, &ts, &te); return retval; } -- cgit v0.10.2 From fd489e1ac617d662e248557afd8aa06ee731440b Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 11 Aug 2015 13:50:54 +0100 Subject: greybus: loopback: handle timestamp roll-over This patch ensures we account for roll-over in the loopback driver. do_gettimeofday() is used to grab a timestamp. Two timestamps are derived one before and one after a gb_operation_sync(), however since do_gettimeofday() returns the number of seconds and mircoseconds that have elapsed today - we need to account for a situation where the timestamp starts at say 23:59:999us rolls over and the end time is now earlier than the start time. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index ac38644..852b6be 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -22,6 +22,8 @@ #include "greybus.h" +#define NSEC_PER_DAY 86400000000000ULL + struct gb_loopback_stats { u32 min; u32 max; @@ -226,7 +228,10 @@ static void gb_loopback_calc_latency(struct gb_loopback *gb, t1 = timeval_to_ns(ts); t2 = timeval_to_ns(te); - gb->elapsed_nsecs = t2 - t1; + if (t2 > t1) + gb->elapsed_nsecs = t2 - t1; + else + gb->elapsed_nsecs = NSEC_PER_DAY - t2 + t1; } static int gb_loopback_sink(struct gb_loopback *gb, u32 len) -- cgit v0.10.2 From 3944a454f1d5634cdcd8b8844199d67a1110dccb Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 12 Aug 2015 09:19:31 +0530 Subject: greybus: interface: Preserve data received during hotplug event This shall be used later to find a firmware blob for the interface, lets save it in the interface structure. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index e60a370..38210ad 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -28,6 +28,12 @@ struct gb_interface { char *product_string; u64 unique_id; + /* Information taken from the hotplug event */ + u32 unipro_mfg_id; + u32 unipro_prod_id; + u32 ara_vend_id; + u32 ara_prod_id; + struct gb_module *module; struct greybus_host_device *hd; }; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 025b2ba..73e7947 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -232,10 +232,6 @@ static int gb_svc_intf_hotplug_recv(struct gb_operation *op) struct device *dev = &op->connection->dev; struct gb_interface *intf; u8 intf_id, device_id; - u32 unipro_mfg_id; - u32 unipro_prod_id; - u32 ara_vend_id; - u32 ara_prod_id; int ret; if (request->payload_size < sizeof(*hotplug)) { @@ -252,10 +248,6 @@ static int gb_svc_intf_hotplug_recv(struct gb_operation *op) * XXX have the SVC get acknowledgement before we proceed. */ intf_id = hotplug->intf_id; - unipro_mfg_id = le32_to_cpu(hotplug->data.unipro_mfg_id); - unipro_prod_id = le32_to_cpu(hotplug->data.unipro_prod_id); - ara_vend_id = le32_to_cpu(hotplug->data.ara_vend_id); - ara_prod_id = le32_to_cpu(hotplug->data.ara_prod_id); intf = gb_interface_create(hd, intf_id); if (!intf) { @@ -264,6 +256,11 @@ static int gb_svc_intf_hotplug_recv(struct gb_operation *op) return -EINVAL; } + intf->unipro_mfg_id = le32_to_cpu(hotplug->data.unipro_mfg_id); + intf->unipro_prod_id = le32_to_cpu(hotplug->data.unipro_prod_id); + intf->ara_vend_id = le32_to_cpu(hotplug->data.ara_vend_id); + intf->ara_prod_id = le32_to_cpu(hotplug->data.ara_prod_id); + /* * Create a device id for the interface: * - device id 0 (GB_DEVICE_ID_SVC) belongs to the SVC -- cgit v0.10.2 From 738599c0dd7fef4d28f416ff9b0b3bc1b07468d2 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 12 Aug 2015 09:19:32 +0530 Subject: greybus: protocol: Create request structure from within gb_protocol_get_version() The version request can only send the version of protocol for which it is initiated and gb_protocol_get_version() has all the information to create the request structure. Replace the 'request' and 'request_size' arguments to gb_protocol_get_version() with a bool to know if the version information of the protocol should be sent or not. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 0ec5b0d..2b2be3f 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -421,7 +421,7 @@ int gb_connection_init(struct gb_connection *connection) * this for SVC as that is initiated by the SVC. */ if (connection->hd_cport_id != GB_SVC_CPORT_ID) { - ret = gb_protocol_get_version(connection, NULL, 0); + ret = gb_protocol_get_version(connection, false); if (ret) { dev_err(&connection->dev, "Failed to get version CPort-%d (%d)\n", diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index b63e28c..5bdc2c0 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -163,12 +163,20 @@ struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor) return protocol; } -int gb_protocol_get_version(struct gb_connection *connection, void *request, - int request_size) +int gb_protocol_get_version(struct gb_connection *connection, bool send_request) { struct gb_protocol_version_response response; + struct gb_protocol_version_response *request = NULL; + int request_size = 0; int retval; + if (send_request) { + response.major = connection->protocol->major; + response.minor = connection->protocol->minor; + request = &response; + request_size = sizeof(*request); + } + retval = gb_operation_sync(connection, GB_REQUEST_TYPE_PROTOCOL_VERSION, request, request_size, &response, sizeof(response)); diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index 34a7f18..87b5a10 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -44,8 +44,7 @@ int gb_protocol_deregister(struct gb_protocol *protocol); __gb_protocol_register(protocol, THIS_MODULE) struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor); -int gb_protocol_get_version(struct gb_connection *connection, void *request, - int request_size); +int gb_protocol_get_version(struct gb_connection *connection, bool send_request); void gb_protocol_put(struct gb_protocol *protocol); -- cgit v0.10.2 From 90f1b617d88f145506e9061436069583cb82d101 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 12 Aug 2015 09:19:33 +0530 Subject: greybus: Add firmware protocol driver This adds firmware protocol driver based on the latest specs available on mailing lists. This uses the firmware framework present in kernel. Refer Documentation/firmware_class/README on how it works. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 1467c5b..3c32d14 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -10,6 +10,7 @@ greybus-y := core.o \ protocol.o \ control.o \ svc.o \ + firmware.o \ operation.o gb-phy-y := gpbridge.o \ diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 225fa4f..6edeec9 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -300,8 +300,16 @@ static int __init gb_init(void) goto error_svc; } + retval = gb_firmware_protocol_init(); + if (retval) { + pr_err("gb_firmware_protocol_init failed\n"); + goto error_firmware; + } + return 0; /* Success */ +error_firmware: + gb_svc_protocol_exit(); error_svc: gb_control_protocol_exit(); error_control: @@ -321,6 +329,7 @@ module_init(gb_init); static void __exit gb_exit(void) { + gb_firmware_protocol_exit(); gb_svc_protocol_exit(); gb_control_protocol_exit(); gb_endo_exit(); diff --git a/drivers/staging/greybus/firmware.c b/drivers/staging/greybus/firmware.c new file mode 100644 index 0000000..13efaab --- /dev/null +++ b/drivers/staging/greybus/firmware.c @@ -0,0 +1,199 @@ +/* + * FIRMWARE Greybus driver. + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include + +#include "greybus.h" + +struct gb_firmware { + struct gb_connection *connection; + const struct firmware *fw; +}; + +static void free_firmware(struct gb_firmware *firmware) +{ + release_firmware(firmware->fw); + firmware->fw = NULL; +} + +/* This returns path of the firmware blob on the disk */ +static int download_firmware(struct gb_firmware *firmware, u8 stage) +{ + struct gb_connection *connection = firmware->connection; + struct gb_interface *intf = connection->bundle->intf; + char firmware_name[28]; + + /* Already have a firmware, free it */ + if (firmware->fw) + free_firmware(firmware); + + /* + * Create firmware name + * + * XXX Name it properly.. + */ + sprintf(firmware_name, "ara:%04x:%04x:%04x:%04x:%04x.fw", intf->unipro_mfg_id, + intf->unipro_prod_id, intf->ara_vend_id, intf->ara_prod_id, + stage); + + return request_firmware(&firmware->fw, firmware_name, &connection->dev); +} + +static int gb_firmware_size_request(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_firmware *firmware = connection->private; + struct gb_firmware_size_request *size_request = op->request->payload; + struct gb_firmware_size_response *size_response; + struct device *dev = &connection->dev; + int ret; + + if (op->request->payload_size != sizeof(*size_request)) { + dev_err(dev, "%s: illegal size of firmware size request (%zu != %zu)\n", + __func__, op->request->payload_size, + sizeof(*size_request)); + return -EINVAL; + } + + ret = download_firmware(firmware, size_request->stage); + if (ret) { + dev_err(dev, "%s: failed to download firmware (%d)\n", __func__, + ret); + return ret; + } + + if (!gb_operation_response_alloc(op, sizeof(*size_response), + GFP_KERNEL)) { + dev_err(dev, "%s: error allocating response\n", __func__); + free_firmware(firmware); + return -ENOMEM; + } + + size_response = op->response->payload; + size_response->size = cpu_to_le32(firmware->fw->size); + + return 0; +} + +static int gb_firmware_get_firmware(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_firmware *firmware = connection->private; + struct gb_firmware_get_firmware_request *firmware_request = op->request->payload; + struct gb_firmware_get_firmware_response *firmware_response; + struct device *dev = &connection->dev; + unsigned int offset, size; + + if (op->request->payload_size != sizeof(*firmware_request)) { + dev_err(dev, "%s: Illegal size of get firmware request (%zu %zu)\n", + __func__, op->request->payload_size, + sizeof(*firmware_request)); + return -EINVAL; + } + + if (!firmware->fw) { + dev_err(dev, "%s: firmware not available\n", __func__); + return -EINVAL; + } + + offset = le32_to_cpu(firmware_request->offset); + size = le32_to_cpu(firmware_request->size); + + if (!gb_operation_response_alloc(op, sizeof(*firmware_response) + size, + GFP_KERNEL)) { + dev_err(dev, "%s: error allocating response\n", __func__); + return -ENOMEM; + } + + firmware_response = op->response->payload; + memcpy(firmware_response->data, firmware->fw->data + offset, size); + + return 0; +} + +static int gb_firmware_ready_to_boot(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_firmware_ready_to_boot_request *rtb_request = op->request->payload; + struct device *dev = &connection->dev; + u8 stage, status; + + if (op->request->payload_size != sizeof(*rtb_request)) { + dev_err(dev, "%s: Illegal size of ready to boot request (%zu %zu)\n", + __func__, op->request->payload_size, + sizeof(*rtb_request)); + return -EINVAL; + } + + stage = rtb_request->stage; + status = rtb_request->status; + + /* Return error if the blob was invalid */ + if (status == GB_FIRMWARE_BOOT_STATUS_INVALID) + return -EINVAL; + + /* + * XXX Should we return error for insecure firmware? + */ + + return 0; +} + +static int gb_firmware_request_recv(u8 type, struct gb_operation *op) +{ + switch (type) { + case GB_FIRMWARE_TYPE_FIRMWARE_SIZE: + return gb_firmware_size_request(op); + case GB_FIRMWARE_TYPE_GET_FIRMWARE: + return gb_firmware_get_firmware(op); + case GB_FIRMWARE_TYPE_READY_TO_BOOT: + return gb_firmware_ready_to_boot(op); + default: + dev_err(&op->connection->dev, + "unsupported request: %hhu\n", type); + return -EINVAL; + } +} + +static int gb_firmware_connection_init(struct gb_connection *connection) +{ + struct gb_firmware *firmware; + + firmware = kzalloc(sizeof(*firmware), GFP_KERNEL); + if (!firmware) + return -ENOMEM; + + firmware->connection = connection; + connection->private = firmware; + + return 0; +} + +static void gb_firmware_connection_exit(struct gb_connection *connection) +{ + struct gb_firmware *firmware = connection->private; + + /* Release firmware */ + if (firmware->fw) + free_firmware(firmware); + + connection->private = NULL; + kfree(firmware); +} + +static struct gb_protocol firmware_protocol = { + .name = "firmware", + .id = GREYBUS_PROTOCOL_FIRMWARE, + .major = GB_FIRMWARE_VERSION_MAJOR, + .minor = GB_FIRMWARE_VERSION_MINOR, + .connection_init = gb_firmware_connection_init, + .connection_exit = gb_firmware_connection_exit, + .request_recv = gb_firmware_request_recv, +}; +gb_builtin_protocol_driver(firmware_protocol); diff --git a/drivers/staging/greybus/firmware.h b/drivers/staging/greybus/firmware.h new file mode 100644 index 0000000..548d297 --- /dev/null +++ b/drivers/staging/greybus/firmware.h @@ -0,0 +1,16 @@ +/* + * Greybus firmware code + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#ifndef __FIRMWARE_H +#define __FIRMWARE_H + +int gb_firmware_protocol_init(void); +void gb_firmware_protocol_exit(void); + +#endif /* __FIRMWARE_H */ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 2214f44..0d4ca70 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -27,6 +27,7 @@ #include "manifest.h" #include "endo.h" #include "svc.h" +#include "firmware.h" #include "module.h" #include "control.h" #include "interface.h" diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 9c4d7ca..687adf2 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -43,6 +43,7 @@ enum greybus_protocol { GREYBUS_PROTOCOL_I2S_RECEIVER = 0x12, GREYBUS_PROTOCOL_I2S_TRANSMITTER = 0x13, GREYBUS_PROTOCOL_SVC = 0x14, + GREYBUS_PROTOCOL_FIRMWARE = 0x15, /* ... */ GREYBUS_PROTOCOL_RAW = 0xfe, GREYBUS_PROTOCOL_VENDOR = 0xff, @@ -70,6 +71,7 @@ enum greybus_class_type { GREYBUS_CLASS_I2S_RECEIVER = 0x12, GREYBUS_CLASS_I2S_TRANSMITTER = 0x13, GREYBUS_CLASS_SVC = 0x14, + GREYBUS_CLASS_FIRMWARE = 0x15, /* ... */ GREYBUS_CLASS_RAW = 0xfe, GREYBUS_CLASS_VENDOR = 0xff, diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index b95d24b..357ecd3 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -146,6 +146,60 @@ struct gb_control_disconnected_request { }; /* Control protocol [dis]connected response has no payload */ + +/* Firmware Protocol */ + +/* Version of the Greybus firmware protocol we support */ +#define GB_FIRMWARE_VERSION_MAJOR 0x00 +#define GB_FIRMWARE_VERSION_MINOR 0x01 + +/* Greybus firmware request types */ +#define GB_FIRMWARE_TYPE_INVALID 0x00 +#define GB_FIRMWARE_TYPE_PROTOCOL_VERSION 0x01 +#define GB_FIRMWARE_TYPE_FIRMWARE_SIZE 0x02 +#define GB_FIRMWARE_TYPE_GET_FIRMWARE 0x03 +#define GB_FIRMWARE_TYPE_READY_TO_BOOT 0x04 + +/* Greybus firmware boot stages */ +#define GB_FIRMWARE_BOOT_STAGE_ONE 0x01 /* Reserved for the boot ROM */ +#define GB_FIRMWARE_BOOT_STAGE_TWO 0x02 /* Firmware package to be loaded by the boot ROM */ +#define GB_FIRMWARE_BOOT_STAGE_THREE 0x03 /* Module personality package loaded by Stage 2 firmware */ + +/* Greybus firmware ready to boot status */ +#define GB_FIRMWARE_BOOT_STATUS_INVALID 0x00 /* Firmware blob could not be validated */ +#define GB_FIRMWARE_BOOT_STATUS_INSECURE 0x01 /* Firmware blob is valid but insecure */ +#define GB_FIRMWARE_BOOT_STATUS_SECURE 0x02 /* Firmware blob is valid and secure */ + +/* Max firmware data fetch size in bytes */ +#define GB_FIRMWARE_FETCH_MAX 2000 + +/* Firmware protocol firmware size request/response */ +struct gb_firmware_size_request { + __u8 stage; +}; + +struct gb_firmware_size_response { + __le32 size; +}; + +/* Firmware protocol get firmware request/response */ +struct gb_firmware_get_firmware_request { + __le32 offset; + __le32 size; +}; + +struct gb_firmware_get_firmware_response { + __u8 data[0]; +}; + +/* Firmware protocol Ready to boot request */ +struct gb_firmware_ready_to_boot_request { + __u8 stage; + __u8 status; +}; +/* Firmware protocol Ready to boot response has no payload */ + + /* I2C */ /* Version of the Greybus i2c protocol we support */ -- cgit v0.10.2 From 58dab0f2a872be5dc2bdb15f3dc487b4a1b41aaf Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 12 Aug 2015 09:19:34 +0530 Subject: greybus: connection: Send protocol version for firmware protocol As per greybus specs, we need to send the protocol version for firmware protocol and so this special case Hack. Probably we should always send the protocol version AP supports and kill this hack completely. But then it requires updates to specs as well, and that should be done after some discussion. For now, add a FIXME for that and a special case for firmware protocol. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 2b2be3f..6078443 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -421,7 +421,19 @@ int gb_connection_init(struct gb_connection *connection) * this for SVC as that is initiated by the SVC. */ if (connection->hd_cport_id != GB_SVC_CPORT_ID) { - ret = gb_protocol_get_version(connection, false); + bool send_request = false; + + /* + * We need to send the protocol version of the firmware protocol + * supported by AP and so this special case. + */ + if (connection->protocol->id == GREYBUS_PROTOCOL_FIRMWARE) + send_request = true; + + // FIXME: Should we always send the protocol version AP can + // support ? + + ret = gb_protocol_get_version(connection, send_request); if (ret) { dev_err(&connection->dev, "Failed to get version CPort-%d (%d)\n", -- cgit v0.10.2 From 1cb5fa47c54ba045593c4dfede72338107ba2133 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 12 Aug 2015 11:04:06 +0530 Subject: greybus: protocol: send own protocol version while requesting it The greybus specifications clearly say (for all protocols) that the sender is responsible for sending the highest version of protocol it supports, while it requests the same from the receiver. But the greybus code never followed that. Fix, this by always sending AP's version of the protocol, while requesting the same from svc/module. This also renames 'response' to 'version' in gb_protocol_get_version() as it is used for both request/response. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index eae6ad1..27b64d6 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -428,19 +428,7 @@ int gb_connection_init(struct gb_connection *connection) * this for SVC as that is initiated by the SVC. */ if (connection->hd_cport_id != GB_SVC_CPORT_ID) { - bool send_request = false; - - /* - * We need to send the protocol version of the firmware protocol - * supported by AP and so this special case. - */ - if (connection->protocol->id == GREYBUS_PROTOCOL_FIRMWARE) - send_request = true; - - // FIXME: Should we always send the protocol version AP can - // support ? - - ret = gb_protocol_get_version(connection, send_request); + ret = gb_protocol_get_version(connection); if (ret) { dev_err(&connection->dev, "Failed to get version CPort-%d (%d)\n", diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index 5bdc2c0..1c74659 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -163,38 +163,32 @@ struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor) return protocol; } -int gb_protocol_get_version(struct gb_connection *connection, bool send_request) +int gb_protocol_get_version(struct gb_connection *connection) { - struct gb_protocol_version_response response; - struct gb_protocol_version_response *request = NULL; - int request_size = 0; + struct gb_protocol_version_response version; int retval; - if (send_request) { - response.major = connection->protocol->major; - response.minor = connection->protocol->minor; - request = &response; - request_size = sizeof(*request); - } + version.major = connection->protocol->major; + version.minor = connection->protocol->minor; retval = gb_operation_sync(connection, GB_REQUEST_TYPE_PROTOCOL_VERSION, - request, request_size, &response, - sizeof(response)); + &version, sizeof(version), &version, + sizeof(version)); if (retval) return retval; - if (response.major > connection->protocol->major) { + if (version.major > connection->protocol->major) { dev_err(&connection->dev, "unsupported major version (%hhu > %hhu)\n", - response.major, connection->protocol->major); + version.major, connection->protocol->major); return -ENOTSUPP; } - connection->module_major = response.major; - connection->module_minor = response.minor; + connection->module_major = version.major; + connection->module_minor = version.minor; dev_dbg(&connection->dev, "version_major = %u version_minor = %u\n", - response.major, response.minor); + version.major, version.minor); return 0; } diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index 87b5a10..8d55a4a 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -44,7 +44,7 @@ int gb_protocol_deregister(struct gb_protocol *protocol); __gb_protocol_register(protocol, THIS_MODULE) struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor); -int gb_protocol_get_version(struct gb_connection *connection, bool send_request); +int gb_protocol_get_version(struct gb_connection *connection); void gb_protocol_put(struct gb_protocol *protocol); -- cgit v0.10.2 From ce83294348fee40d4173f5e5b41c2999405149b4 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 12 Aug 2015 11:51:10 +0530 Subject: greybus: battery: Move request/response structure/definitions to greybus_protocols.h These must be exposed to external modules, like gbsim. Move them to greybus_protocols.h file. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery.c b/drivers/staging/greybus/battery.c index a56eb81..6b354de 100644 --- a/drivers/staging/greybus/battery.c +++ b/drivers/staging/greybus/battery.c @@ -35,61 +35,6 @@ struct gb_battery { }; -/* Version of the Greybus battery protocol we support */ -#define GB_BATTERY_VERSION_MAJOR 0x00 -#define GB_BATTERY_VERSION_MINOR 0x01 - -/* Greybus battery request types */ -#define GB_BATTERY_TYPE_TECHNOLOGY 0x02 -#define GB_BATTERY_TYPE_STATUS 0x03 -#define GB_BATTERY_TYPE_MAX_VOLTAGE 0x04 -#define GB_BATTERY_TYPE_PERCENT_CAPACITY 0x05 -#define GB_BATTERY_TYPE_TEMPERATURE 0x06 -#define GB_BATTERY_TYPE_VOLTAGE 0x07 -#define GB_BATTERY_TYPE_CURRENT 0x08 -#define GB_BATTERY_TYPE_CAPACITY 0x09 // TODO - POWER_SUPPLY_PROP_CURRENT_MAX -#define GB_BATTERY_TYPE_SHUTDOWN_TEMP 0x0a // TODO - POWER_SUPPLY_PROP_TEMP_ALERT_MAX - -/* Should match up with battery types in linux/power_supply.h */ -#define GB_BATTERY_TECH_UNKNOWN 0x0000 -#define GB_BATTERY_TECH_NiMH 0x0001 -#define GB_BATTERY_TECH_LION 0x0002 -#define GB_BATTERY_TECH_LIPO 0x0003 -#define GB_BATTERY_TECH_LiFe 0x0004 -#define GB_BATTERY_TECH_NiCd 0x0005 -#define GB_BATTERY_TECH_LiMn 0x0006 - -struct gb_battery_technology_response { - __le32 technology; -}; - -/* Should match up with battery status in linux/power_supply.h */ -#define GB_BATTERY_STATUS_UNKNOWN 0x0000 -#define GB_BATTERY_STATUS_CHARGING 0x0001 -#define GB_BATTERY_STATUS_DISCHARGING 0x0002 -#define GB_BATTERY_STATUS_NOT_CHARGING 0x0003 -#define GB_BATTERY_STATUS_FULL 0x0004 - -struct gb_battery_status_response { - __le16 battery_status; -}; - -struct gb_battery_max_voltage_response { - __le32 max_voltage; -}; - -struct gb_battery_capacity_response { - __le32 capacity; -}; - -struct gb_battery_temperature_response { - __le32 temperature; -}; - -struct gb_battery_voltage_response { - __le32 voltage; -}; - static int get_tech(struct gb_battery *gb) { struct gb_battery_technology_response tech_response; diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 43a0728..e0aed3b 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -200,6 +200,64 @@ struct gb_firmware_ready_to_boot_request { /* Firmware protocol Ready to boot response has no payload */ +/* BATTERY */ + +/* Version of the Greybus battery protocol we support */ +#define GB_BATTERY_VERSION_MAJOR 0x00 +#define GB_BATTERY_VERSION_MINOR 0x01 + +/* Greybus battery request types */ +#define GB_BATTERY_TYPE_TECHNOLOGY 0x02 +#define GB_BATTERY_TYPE_STATUS 0x03 +#define GB_BATTERY_TYPE_MAX_VOLTAGE 0x04 +#define GB_BATTERY_TYPE_PERCENT_CAPACITY 0x05 +#define GB_BATTERY_TYPE_TEMPERATURE 0x06 +#define GB_BATTERY_TYPE_VOLTAGE 0x07 +#define GB_BATTERY_TYPE_CURRENT 0x08 +#define GB_BATTERY_TYPE_CAPACITY 0x09 // TODO - POWER_SUPPLY_PROP_CURRENT_MAX +#define GB_BATTERY_TYPE_SHUTDOWN_TEMP 0x0a // TODO - POWER_SUPPLY_PROP_TEMP_ALERT_MAX + +/* Should match up with battery types in linux/power_supply.h */ +#define GB_BATTERY_TECH_UNKNOWN 0x0000 +#define GB_BATTERY_TECH_NiMH 0x0001 +#define GB_BATTERY_TECH_LION 0x0002 +#define GB_BATTERY_TECH_LIPO 0x0003 +#define GB_BATTERY_TECH_LiFe 0x0004 +#define GB_BATTERY_TECH_NiCd 0x0005 +#define GB_BATTERY_TECH_LiMn 0x0006 + +struct gb_battery_technology_response { + __le32 technology; +}; + +/* Should match up with battery status in linux/power_supply.h */ +#define GB_BATTERY_STATUS_UNKNOWN 0x0000 +#define GB_BATTERY_STATUS_CHARGING 0x0001 +#define GB_BATTERY_STATUS_DISCHARGING 0x0002 +#define GB_BATTERY_STATUS_NOT_CHARGING 0x0003 +#define GB_BATTERY_STATUS_FULL 0x0004 + +struct gb_battery_status_response { + __le16 battery_status; +}; + +struct gb_battery_max_voltage_response { + __le32 max_voltage; +}; + +struct gb_battery_capacity_response { + __le32 capacity; +}; + +struct gb_battery_temperature_response { + __le32 temperature; +}; + +struct gb_battery_voltage_response { + __le32 voltage; +}; + + /* I2C */ /* Version of the Greybus i2c protocol we support */ -- cgit v0.10.2 From 51aee043ecdb890bbfd33e4cb3b73269ee8371e3 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 12 Aug 2015 11:51:11 +0530 Subject: greybus: hid: Move request/response structure/definitions to greybus_protocols.h These must be exposed to external modules, like gbsim. Move them to greybus_protocols.h file. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index e0aed3b..0ba11f8 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -258,6 +258,58 @@ struct gb_battery_voltage_response { }; +/* HID */ + +/* Version of the Greybus hid protocol we support */ +#define GB_HID_VERSION_MAJOR 0x00 +#define GB_HID_VERSION_MINOR 0x01 + +/* Greybus HID operation types */ +#define GB_HID_TYPE_INVALID 0x00 +#define GB_HID_TYPE_PROTOCOL_VERSION 0x01 +#define GB_HID_TYPE_GET_DESC 0x02 +#define GB_HID_TYPE_GET_REPORT_DESC 0x03 +#define GB_HID_TYPE_PWR_ON 0x04 +#define GB_HID_TYPE_PWR_OFF 0x05 +#define GB_HID_TYPE_GET_REPORT 0x06 +#define GB_HID_TYPE_SET_REPORT 0x07 +#define GB_HID_TYPE_IRQ_EVENT 0x08 + +/* Report type */ +#define GB_HID_INPUT_REPORT 0 +#define GB_HID_OUTPUT_REPORT 1 +#define GB_HID_FEATURE_REPORT 2 + +/* Different request/response structures */ +/* HID get descriptor response */ +struct gb_hid_desc_response { + __u8 bLength; + __le16 wReportDescLength; + __le16 bcdHID; + __le16 wProductID; + __le16 wVendorID; + __u8 bCountryCode; +} __packed; + +/* HID get report request/response */ +struct gb_hid_get_report_request { + __u8 report_type; + __u8 report_id; +}; + +/* HID set report request */ +struct gb_hid_set_report_request { + __u8 report_type; + __u8 report_id; + __u8 report[0]; +}; + +/* HID input report request, via interrupt pipe */ +struct gb_hid_input_report_request { + __u8 report[0]; +}; + + /* I2C */ /* Version of the Greybus i2c protocol we support */ diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index 887dbac..0044b84 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -16,55 +16,6 @@ #include "greybus.h" -/* Version of the Greybus hid protocol we support */ -#define GB_HID_VERSION_MAJOR 0x00 -#define GB_HID_VERSION_MINOR 0x01 - -/* Greybus HID operation types */ -#define GB_HID_TYPE_INVALID 0x00 -#define GB_HID_TYPE_PROTOCOL_VERSION 0x01 -#define GB_HID_TYPE_GET_DESC 0x02 -#define GB_HID_TYPE_GET_REPORT_DESC 0x03 -#define GB_HID_TYPE_PWR_ON 0x04 -#define GB_HID_TYPE_PWR_OFF 0x05 -#define GB_HID_TYPE_GET_REPORT 0x06 -#define GB_HID_TYPE_SET_REPORT 0x07 -#define GB_HID_TYPE_IRQ_EVENT 0x08 - -/* Report type */ -#define GB_HID_INPUT_REPORT 0 -#define GB_HID_OUTPUT_REPORT 1 -#define GB_HID_FEATURE_REPORT 2 - -/* Different request/response structures */ -/* HID get descriptor response */ -struct gb_hid_desc_response { - __u8 bLength; - __le16 wReportDescLength; - __le16 bcdHID; - __le16 wProductID; - __le16 wVendorID; - __u8 bCountryCode; -} __packed; - -/* HID get report request/response */ -struct gb_hid_get_report_request { - __u8 report_type; - __u8 report_id; -}; - -/* HID set report request */ -struct gb_hid_set_report_request { - __u8 report_type; - __u8 report_id; - __u8 report[0]; -}; - -/* HID input report request, via interrupt pipe */ -struct gb_hid_input_report_request { - __u8 report[0]; -}; - /* Greybus HID device's structure */ struct gb_hid { struct gb_connection *connection; -- cgit v0.10.2 From d65e3a22aa3ef28f068cdc38ac82f3e1914cde9a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 13 Aug 2015 10:04:45 +0530 Subject: greybus: raw: Move request/response structure/definitions to greybus_protocols.h These must be exposed to external modules, like gbsim. Move them to greybus_protocols.h file. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 0ba11f8..09a4466 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -823,6 +823,22 @@ struct gb_svc_route_create_request { __u8 dev2_id; }; + +/* RAW */ + +/* Version of the Greybus raw protocol we support */ +#define GB_RAW_VERSION_MAJOR 0x00 +#define GB_RAW_VERSION_MINOR 0x01 + +/* Greybus raw request types */ +#define GB_RAW_TYPE_SEND 0x02 + +struct gb_raw_send_request { + __le32 len; + __u8 data[0]; +}; + + /* UART */ /* Version of the Greybus UART protocol we support */ diff --git a/drivers/staging/greybus/raw.c b/drivers/staging/greybus/raw.c index 215d421..ce0f59d 100644 --- a/drivers/staging/greybus/raw.c +++ b/drivers/staging/greybus/raw.c @@ -28,18 +28,6 @@ struct gb_raw { struct device *device; }; -/* Version of the Greybus raw protocol we support */ -#define GB_RAW_VERSION_MAJOR 0x00 -#define GB_RAW_VERSION_MINOR 0x01 - -/* Greybus raw request types */ -#define GB_RAW_TYPE_SEND 0x02 - -struct gb_raw_send_request { - __le32 len; - __u8 data[0]; -}; - struct raw_data { struct list_head entry; u32 len; -- cgit v0.10.2 From 22322c474551c208625d3b95ffba39b1882fa645 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 13 Aug 2015 10:35:29 +0530 Subject: greybus: connection: Destroy wq on failure Need to destroy the wq created earlier, do it. Fixes: d0f1778a6b67 ("greybus/connection: add a timestamp kfifo to track connection handoff") Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 27b64d6..d0f499d 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -252,7 +252,7 @@ gb_connection_create_range(struct greybus_host_device *hd, if (kfifo_alloc(&connection->ts_kfifo, GB_CONNECTION_TS_KFIFO_LEN, GFP_KERNEL)) - goto err_free_connection; + goto err_destroy_wq; connection->dev.parent = parent; connection->dev.bus = &greybus_bus_type; @@ -298,6 +298,8 @@ gb_connection_create_range(struct greybus_host_device *hd, err_free_kfifo: kfifo_free(&connection->ts_kfifo); +err_destroy_wq: + destroy_workqueue(connection->wq); err_free_connection: kfree(connection); err_remove_ida: -- cgit v0.10.2 From 435ea76218c9f3257990c6da8b37bf7708598f49 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 13 Aug 2015 10:40:28 +0530 Subject: greybus: connection: Don't free resources freed by gb_connection_release() We are already doing put_device() here and so don't need to free resources directly, except ida. Fixes: afde17fe0b61 ("greybus/connection: fix jump label on device_add failure") Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index d0f499d..7eb2868 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -270,7 +270,7 @@ gb_connection_create_range(struct greybus_host_device *hd, pr_err("failed to add connection device for cport 0x%04hx\n", cport_id); - goto err_free_kfifo; + goto err_remove_ida; } spin_lock_irq(&gb_connections_lock); @@ -296,8 +296,6 @@ gb_connection_create_range(struct greybus_host_device *hd, return connection; -err_free_kfifo: - kfifo_free(&connection->ts_kfifo); err_destroy_wq: destroy_workqueue(connection->wq); err_free_connection: -- cgit v0.10.2 From 0e2462d1b71b15790d37f9f66b01cdf1003a8e72 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 14 Aug 2015 07:57:38 +0530 Subject: greybus: Drop protocol specific _PROTOCOL_VERSION and _INVALID macros Greybus core supports protocol independent macros for this now, use them. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index 605e6134..e675c5c 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -71,7 +71,7 @@ static int gb_control_request_recv(u8 type, struct gb_operation *op) // Send authenticated block of data, confirming this module is // an AP. break; - case GB_CONTROL_TYPE_PROTOCOL_VERSION: + case GB_REQUEST_TYPE_PROTOCOL_VERSION: if (!gb_operation_response_alloc(op, sizeof(*version), GFP_KERNEL)) { dev_err(&connection->dev, diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 09a4466..a80c2f2 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -118,8 +118,6 @@ struct gb_protocol_version_response { #define GB_CONTROL_VERSION_MINOR 0x01 /* Greybus control request types */ -#define GB_CONTROL_TYPE_INVALID 0x00 -#define GB_CONTROL_TYPE_PROTOCOL_VERSION 0x01 #define GB_CONTROL_TYPE_PROBE_AP 0x02 #define GB_CONTROL_TYPE_GET_MANIFEST_SIZE 0x03 #define GB_CONTROL_TYPE_GET_MANIFEST 0x04 @@ -154,8 +152,6 @@ struct gb_control_disconnected_request { #define GB_FIRMWARE_VERSION_MINOR 0x01 /* Greybus firmware request types */ -#define GB_FIRMWARE_TYPE_INVALID 0x00 -#define GB_FIRMWARE_TYPE_PROTOCOL_VERSION 0x01 #define GB_FIRMWARE_TYPE_FIRMWARE_SIZE 0x02 #define GB_FIRMWARE_TYPE_GET_FIRMWARE 0x03 #define GB_FIRMWARE_TYPE_READY_TO_BOOT 0x04 @@ -265,8 +261,6 @@ struct gb_battery_voltage_response { #define GB_HID_VERSION_MINOR 0x01 /* Greybus HID operation types */ -#define GB_HID_TYPE_INVALID 0x00 -#define GB_HID_TYPE_PROTOCOL_VERSION 0x01 #define GB_HID_TYPE_GET_DESC 0x02 #define GB_HID_TYPE_GET_REPORT_DESC 0x03 #define GB_HID_TYPE_PWR_ON 0x04 @@ -317,8 +311,6 @@ struct gb_hid_input_report_request { #define GB_I2C_VERSION_MINOR 0x01 /* Greybus i2c request types */ -#define GB_I2C_TYPE_INVALID 0x00 -#define GB_I2C_TYPE_PROTOCOL_VERSION 0x01 #define GB_I2C_TYPE_FUNCTIONALITY 0x02 #define GB_I2C_TYPE_TIMEOUT 0x03 #define GB_I2C_TYPE_RETRIES 0x04 @@ -374,8 +366,6 @@ struct gb_i2c_transfer_response { #define GB_GPIO_VERSION_MINOR 0x01 /* Greybus GPIO request types */ -#define GB_GPIO_TYPE_INVALID 0x00 -#define GB_GPIO_TYPE_PROTOCOL_VERSION 0x01 #define GB_GPIO_TYPE_LINE_COUNT 0x02 #define GB_GPIO_TYPE_ACTIVATE 0x03 #define GB_GPIO_TYPE_DEACTIVATE 0x04 @@ -479,8 +469,6 @@ struct gb_gpio_irq_event_request { #define GB_PWM_VERSION_MINOR 0x01 /* Greybus PWM operation types */ -#define GB_PWM_TYPE_INVALID 0x00 -#define GB_PWM_TYPE_PROTOCOL_VERSION 0x01 #define GB_PWM_TYPE_PWM_COUNT 0x02 #define GB_PWM_TYPE_ACTIVATE 0x03 #define GB_PWM_TYPE_DEACTIVATE 0x04 @@ -523,7 +511,6 @@ struct gb_pwm_disable_request { /* I2S */ -#define GB_I2S_MGMT_TYPE_PROTOCOL_VERSION 0x01 #define GB_I2S_MGMT_TYPE_GET_SUPPORTED_CONFIGURATIONS 0x02 #define GB_I2S_MGMT_TYPE_SET_CONFIGURATION 0x03 #define GB_I2S_MGMT_TYPE_SET_SAMPLES_PER_MESSAGE 0x04 @@ -650,7 +637,6 @@ struct gb_i2s_mgmt_report_event_request { }; /* report event response has no payload */ -#define GB_I2S_DATA_TYPE_PROTOCOL_VERSION 0x01 #define GB_I2S_DATA_TYPE_SEND_DATA 0x02 struct gb_i2s_send_data_request { @@ -687,8 +673,6 @@ struct gb_i2s_send_data_request { #define GB_SPI_FLAG_NO_TX BIT(2) /* can't do buffer write */ /* Greybus spi operation types */ -#define GB_SPI_TYPE_INVALID 0x00 -#define GB_SPI_TYPE_PROTOCOL_VERSION 0x01 #define GB_SPI_TYPE_MODE 0x02 #define GB_SPI_TYPE_FLAGS 0x03 #define GB_SPI_TYPE_BITS_PER_WORD_MASK 0x04 @@ -751,8 +735,6 @@ struct gb_spi_transfer_response { #define GB_SVC_VERSION_MINOR 0x01 /* Greybus SVC request types */ -#define GB_SVC_TYPE_INVALID 0x00 -#define GB_SVC_TYPE_PROTOCOL_VERSION 0x01 #define GB_SVC_TYPE_SVC_HELLO 0x02 #define GB_SVC_TYPE_INTF_DEVICE_ID 0x03 #define GB_SVC_TYPE_INTF_HOTPLUG 0x04 @@ -846,8 +828,6 @@ struct gb_raw_send_request { #define GB_UART_VERSION_MINOR 0x01 /* Greybus UART operation types */ -#define GB_UART_TYPE_INVALID 0x00 -#define GB_UART_TYPE_PROTOCOL_VERSION 0x01 #define GB_UART_TYPE_SEND_DATA 0x02 #define GB_UART_TYPE_RECEIVE_DATA 0x03 /* Unsolicited data */ #define GB_UART_TYPE_SET_LINE_CODING 0x04 @@ -919,8 +899,6 @@ struct gb_uart_serial_state_request { #define GB_LOOPBACK_VERSION_MINOR 0x01 /* Greybus loopback request types */ -#define GB_LOOPBACK_TYPE_INVALID 0x00 -#define GB_LOOPBACK_TYPE_PROTOCOL_VERSION 0x01 #define GB_LOOPBACK_TYPE_PING 0x02 #define GB_LOOPBACK_TYPE_TRANSFER 0x03 #define GB_LOOPBACK_TYPE_SINK 0x04 @@ -940,8 +918,6 @@ struct gb_loopback_transfer_response { #define GB_SDIO_VERSION_MINOR 0x01 /* Greybus SDIO operation types */ -#define GB_SDIO_TYPE_INVALID 0x00 -#define GB_SDIO_TYPE_PROTOCOL_VERSION 0x01 #define GB_SDIO_TYPE_GET_CAPABILITIES 0x02 #define GB_SDIO_TYPE_SET_IOS 0x03 #define GB_SDIO_TYPE_COMMAND 0x04 diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 852b6be..cf525f8 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -319,7 +319,7 @@ static int gb_loopback_request_recv(u8 type, struct gb_operation *operation) /* By convention, the AP initiates the version operation */ switch (type) { - case GB_LOOPBACK_TYPE_PROTOCOL_VERSION: + case GB_REQUEST_TYPE_PROTOCOL_VERSION: dev_err(&connection->dev, "module-initiated version operation\n"); return -EINVAL; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 5ff7cf3..452f81b 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -452,7 +452,7 @@ static int gb_svc_intf_reset_recv(struct gb_operation *op) static int gb_svc_request_recv(u8 type, struct gb_operation *op) { switch (type) { - case GB_SVC_TYPE_PROTOCOL_VERSION: + case GB_REQUEST_TYPE_PROTOCOL_VERSION: return gb_svc_version_request(op); case GB_SVC_TYPE_SVC_HELLO: return gb_svc_hello(op); -- cgit v0.10.2 From 21e3a3ed9b8257e8e885458eb7573385c7e4ce26 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 14 Aug 2015 08:12:30 +0530 Subject: greybus: operation: print message type on errors This can be very useful debug information, print it. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 4e9c4a8..0bb5b8d 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -235,8 +235,8 @@ static void gb_operation_request_handle(struct gb_operation *operation) ret = gb_operation_response_send(operation, status); if (ret) { dev_err(&operation->connection->dev, - "failed to send response %d: %d\n", - status, ret); + "failed to send response %d for type 0x%02hhx: %d\n", + status, operation->type, ret); return; } } @@ -794,7 +794,8 @@ void greybus_message_sent(struct greybus_host_device *hd, if (message == operation->response) { if (status) { dev_err(&connection->dev, - "error sending response: %d\n", status); + "error sending response type 0x%02hhx: %d\n", + operation->type, status); } gb_operation_put_active(operation); gb_operation_put(operation); @@ -867,8 +868,8 @@ static void gb_connection_recv_response(struct gb_connection *connection, message = operation->response; message_size = sizeof(*message->header) + message->payload_size; if (!errno && size != message_size) { - dev_err(&connection->dev, "bad message size (%zu != %zu)\n", - size, message_size); + dev_err(&connection->dev, "bad message (0x%02hhx) size (%zu != %zu)\n", + size, message_size, message->header->type); errno = -EMSGSIZE; } @@ -913,8 +914,9 @@ void gb_connection_recv(struct gb_connection *connection, msg_size = le16_to_cpu(header.size); if (size < msg_size) { dev_err(&connection->dev, - "incomplete message received: 0x%04x (%zu < %zu)\n", - le16_to_cpu(header.operation_id), size, msg_size); + "incomplete message received for type 0x%02hhx: 0x%04x (%zu < %zu)\n", + header.type, le16_to_cpu(header.operation_id), size, + msg_size); return; /* XXX Should still complete operation */ } @@ -1019,8 +1021,8 @@ int gb_operation_sync_timeout(struct gb_connection *connection, int type, ret = gb_operation_request_send_sync_timeout(operation, timeout); if (ret) { - dev_err(&connection->dev, "synchronous operation failed: %d\n", - ret); + dev_err(&connection->dev, "synchronous operation failed: 0x%02hhx (%d)\n", + type, ret); } else { if (response_size) { memcpy(response, operation->response->payload, -- cgit v0.10.2 From dc4a10693f3f0e6658b06dd1947643637c0476a4 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 14 Aug 2015 17:07:10 +0530 Subject: greybus: loopback: Send some sensible data Signed-off-by: Viresh Kumar Reviewed-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index cf525f8..39ad414 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -273,6 +273,8 @@ static int gb_loopback_transfer(struct gb_loopback *gb, u32 len) return -ENOMEM; } + memset(request->data, 0x5A, len); + request->len = cpu_to_le32(len); do_gettimeofday(&ts); -- cgit v0.10.2 From dc366f8e397c41ba582821e24abdc2bc4ae80a47 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 14 Aug 2015 17:07:11 +0530 Subject: greybus: loopback: Print error on data mismatch Signed-off-by: Viresh Kumar Reviewed-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 39ad414..3263d83 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -287,8 +287,10 @@ static int gb_loopback_transfer(struct gb_loopback *gb, u32 len) if (retval) goto gb_error; - if (memcmp(request->data, response->data, len)) + if (memcmp(request->data, response->data, len)) { + pr_info("%s: Loopback Data doesn't match\n", __func__); retval = -EREMOTEIO; + } gb_error: kfree(request); -- cgit v0.10.2 From 13fcfbb6c5bbd7aee7e9980313dc29469357c5cd Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Fri, 14 Aug 2015 13:58:18 +0100 Subject: greybus: makefile: add needed config options for lights Add a function to check kernel versions and append the necessary options to support LEDS_CLASS, LEDS_CLASS_FLASH and V4L2_FLASH_LED_CLASS depending of the kernel version. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 1162703..3006ede 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -49,13 +49,26 @@ INSTALL_MOD_PATH ?= /.. PWD := $(shell pwd) # kernel config option that shall be enable -CONFIG_OPTIONS_ENABLE := SYSFS SPI USB SND_SOC MMC +CONFIG_OPTIONS_ENABLE := SYSFS SPI USB SND_SOC MMC LEDS_CLASS # kernel config option that shall be disable CONFIG_OPTIONS_DISABLE := # this only run in kbuild part of the makefile ifneq ($(KERNELRELEASE),) +# This function returns the argument version if current kernel version is minor +# than the passed version, return 1 if equal or the current kernel version if it +# is greater than argument version. +kvers_cmp=$(shell [[ "$(KERNELVERSION)" == "$(1)" ]] && echo 1 || echo -e "$(1)\n$(KERNELVERSION)" | sort -V | tail -1) + +ifneq ($(call kvers_cmp,"3.19.0"),3.19.0) + CONFIG_OPTIONS_ENABLE += LEDS_CLASS_FLASH +endif + +ifneq ($(call kvers_cmp,"4.2.0"),4.2.0) + CONFIG_OPTIONS_ENABLE += V4L2_FLASH_LED_CLASS +endif + $(foreach opt,$(CONFIG_OPTIONS_ENABLE),$(if $(CONFIG_$(opt)),, \ $(error CONFIG_$(opt) is disabled in the kernel configuration and must be enable \ to continue compilation))) -- cgit v0.10.2 From 2870b52bae4c81823ffcb3ed2b0626fb39d64f48 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Fri, 14 Aug 2015 13:58:19 +0100 Subject: greybus: lights: add lights implementation This patch adds lights implementation for Greybus Lights class, it allows multiplexing of lights devices using the same connection. Also adds two sysfs entries to led class (color, fade) which are commonly used in several existing LED devices. It support 2 major class of devices (normal LED and flash type), for the first it registers to led_classdev, for the latest it registers in the led_classdev_flash and v4l2_flash, depending on the support of the kernel version. Each Module can have N light devices attach and each light can have multiple channel associated: glights |->light0 | |->channel0 | |->channel1 | | .... | |->channeln |->... |->lightn |->channel0 |->channel1 | .... |->channeln Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 3006ede..5c29b63 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -30,6 +30,7 @@ gb-phy-y := gpbridge.o \ gb-vibrator-y := vibrator.o gb-battery-y := battery.o gb-loopback-y := loopback.o +gb-light-y := light.o gb-raw-y := raw.o gb-es1-y := es1.o gb-es2-y := es2.o @@ -39,6 +40,7 @@ obj-m += gb-phy.o obj-m += gb-vibrator.o obj-m += gb-battery.o obj-m += gb-loopback.o +obj-m += gb-light.o obj-m += gb-raw.o obj-m += gb-es1.o obj-m += gb-es2.o diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index a80c2f2..32b927f 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -1067,5 +1067,181 @@ struct gb_sdio_event_request { #define GB_SDIO_WP 0x04 }; +/* Lights */ + +#define GB_LIGHTS_VERSION_MAJOR 0x00 +#define GB_LIGHTS_VERSION_MINOR 0x01 + +/* Greybus Lights request types */ +#define GB_LIGHTS_TYPE_INVALID 0x00 +#define GB_LIGHTS_TYPE_PROTOCOL_VERSION 0x01 +#define GB_LIGHTS_TYPE_GET_LIGHTS 0x02 +#define GB_LIGHTS_TYPE_GET_LIGHT_CONFIG 0x03 +#define GB_LIGHTS_TYPE_GET_CHANNEL_CONFIG 0x04 +#define GB_LIGHTS_TYPE_GET_CHANNEL_FLASH_CONFIG 0x05 +#define GB_LIGHTS_TYPE_SET_BRIGHTNESS 0x06 +#define GB_LIGHTS_TYPE_SET_BLINK 0x07 +#define GB_LIGHTS_TYPE_SET_COLOR 0x08 +#define GB_LIGHTS_TYPE_SET_FADE 0x09 +#define GB_LIGHTS_TYPE_EVENT 0x0A +#define GB_LIGHTS_TYPE_SET_FLASH_INTENSITY 0x0B +#define GB_LIGHTS_TYPE_SET_FLASH_STROBE 0x0C +#define GB_LIGHTS_TYPE_SET_FLASH_TIMEOUT 0x0D +#define GB_LIGHTS_TYPE_GET_FLASH_FAULT 0x0E + +/* Greybus Light modes */ + +/* + * if you add any specific mode below, update also the + * GB_CHANNEL_MODE_DEFINED_RANGE value accordingly + */ +#define GB_CHANNEL_MODE_NONE 0x00000000 +#define GB_CHANNEL_MODE_BATTERY 0x00000001 +#define GB_CHANNEL_MODE_POWER 0x00000002 +#define GB_CHANNEL_MODE_WIRELESS 0x00000004 +#define GB_CHANNEL_MODE_BLUETOOTH 0x00000008 +#define GB_CHANNEL_MODE_KEYBOARD 0x00000010 +#define GB_CHANNEL_MODE_BUTTONS 0x00000020 +#define GB_CHANNEL_MODE_NOTIFICATION 0x00000040 +#define GB_CHANNEL_MODE_ATTENTION 0x00000080 +#define GB_CHANNEL_MODE_FLASH 0x00000100 +#define GB_CHANNEL_MODE_TORCH 0x00000200 +#define GB_CHANNEL_MODE_INDICATOR 0x00000400 + +/* Lights Mode valid bit values */ +#define GB_CHANNEL_MODE_DEFINED_RANGE 0x000004FF +#define GB_CHANNEL_MODE_VENDOR_RANGE 0x00F00000 + +/* Greybus Light Channels Flags */ +#define GB_LIGHT_CHANNEL_MULTICOLOR 0x00000001 +#define GB_LIGHT_CHANNEL_FADER 0x00000002 +#define GB_LIGHT_CHANNEL_BLINK 0x00000004 + +/* get count of lights in module */ +struct gb_lights_get_lights_response { + __u8 lights_count; +}; + +/* light config request payload */ +struct gb_lights_get_light_config_request { + __u8 id; +}; + +/* light config response payload */ +struct gb_lights_get_light_config_response { + __u8 channel_count; + __u8 name[32]; +}; + +/* channel config request payload */ +struct gb_lights_get_channel_config_request { + __u8 light_id; + __u8 channel_id; +}; + +/* channel flash config request payload */ +struct gb_lights_get_channel_flash_config_request { + __u8 light_id; + __u8 channel_id; +}; + +/* channel config response payload */ +struct gb_lights_get_channel_config_response { + __u8 max_brightness; + __le32 flags; + __le32 color; + __u8 color_name[32]; + __le32 mode; + __u8 mode_name[32]; +} __packed; + +/* channel flash config response payload */ +struct gb_lights_get_channel_flash_config_response { + __le32 intensity_min_uA; + __le32 intensity_max_uA; + __le32 intensity_step_uA; + __le32 timeout_min_us; + __le32 timeout_max_us; + __le32 timeout_step_us; +}; + +/* blink request payload: response have no payload */ +struct gb_lights_blink_request { + __u8 light_id; + __u8 channel_id; + __le16 time_on_ms; + __le16 time_off_ms; +}; + +/* set brightness request payload: response have no payload */ +struct gb_lights_set_brightness_request { + __u8 light_id; + __u8 channel_id; + __u8 brightness; +}; + +/* set color request payload: response have no payload */ +struct gb_lights_set_color_request { + __u8 light_id; + __u8 channel_id; + __le32 color; +} __packed; + +/* set fade request payload: response have no payload */ +struct gb_lights_set_fade_request { + __u8 light_id; + __u8 channel_id; + __u8 fade_in; + __u8 fade_out; +}; + +/* event request: generated by module */ +struct gb_lights_event_request { + __u8 light_id; + __u8 event; +#define GB_LIGHTS_LIGHT_CONFIG 0x01 +}; + +/* set flash intensity request payload: response have no payload */ +struct gb_lights_set_flash_intensity_request { + __u8 light_id; + __u8 channel_id; + __le32 intensity_uA; +} __packed; + +/* set flash strobe state request payload: response have no payload */ +struct gb_lights_set_flash_strobe_request { + __u8 light_id; + __u8 channel_id; + __u8 state; +}; + +/* set flash timeout request payload: response have no payload */ +struct gb_lights_set_flash_timeout_request { + __u8 light_id; + __u8 channel_id; + __le32 timeout_us; +} __packed; + +/* get flash fault request payload */ +struct gb_lights_get_flash_fault_request { + __u8 light_id; + __u8 channel_id; +}; + +/* get flash fault response payload */ +struct gb_lights_get_flash_fault_response { + __le32 fault; +#define GB_LIGHTS_FLASH_FAULT_OVER_VOLTAGE 0x00000000 +#define GB_LIGHTS_FLASH_FAULT_TIMEOUT 0x00000001 +#define GB_LIGHTS_FLASH_FAULT_OVER_TEMPERATURE 0x00000002 +#define GB_LIGHTS_FLASH_FAULT_SHORT_CIRCUIT 0x00000004 +#define GB_LIGHTS_FLASH_FAULT_OVER_CURRENT 0x00000008 +#define GB_LIGHTS_FLASH_FAULT_INDICATOR 0x00000010 +#define GB_LIGHTS_FLASH_FAULT_UNDER_VOLTAGE 0x00000020 +#define GB_LIGHTS_FLASH_FAULT_INPUT_VOLTAGE 0x00000040 +#define GB_LIGHTS_FLASH_FAULT_LED_OVER_TEMPERATURE 0x00000080 +}; + #endif /* __GREYBUS_PROTOCOLS_H */ diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index d0e05e6..f3cb189 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -248,4 +248,45 @@ static inline size_t sg_pcopy_from_buffer(struct scatterlist *sgl, list_entry((ptr)->prev, type, member) #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0) +/* + * Before this version the led classdev did not support groups + */ +#define LED_HAVE_GROUPS +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) +/* + * At this time the internal API for the set brightness was changed to the async + * version, and one sync API was added to handle cases that need immediate + * effect. Also, the led class flash and lock for sysfs access was introduced. + */ +#define LED_HAVE_SET_SYNC +#define LED_HAVE_FLASH +#define LED_HAVE_LOCK +#include +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0) +/* + * From this version upper it was introduced the possibility to disable led + * sysfs entries to handle control of the led device to v4l2, which was + * implemented later. So, before that this should return false. + */ +#include +static inline bool led_sysfs_is_disabled(struct led_classdev *led_cdev) +{ + return false; +} +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) +/* + * New helper functions for registering/unregistering flash led devices as v4l2 + * subdevices were added. + */ +#define V4L2_HAVE_FLASH +#include +#endif + #endif /* __GREYBUS_KERNEL_VER_H */ diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c new file mode 100644 index 0000000..e8ef7f5 --- /dev/null +++ b/drivers/staging/greybus/light.c @@ -0,0 +1,1201 @@ +/* + * Greybus Lights protocol driver. + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include + +#include "greybus.h" +#include "greybus_protocols.h" + +#define NAMES_MAX 32 + +struct gb_channel { + u8 id; + u32 flags; + u32 color; + char *color_name; + u8 fade_in; + u8 fade_out; + u32 mode; + char *mode_name; + struct attribute **attrs; + struct attribute_group *attr_group; + const struct attribute_group **attr_groups; + struct work_struct work_brightness_set; + struct led_classdev *led; +#ifdef LED_HAVE_FLASH + struct led_classdev_flash fled; + struct led_flash_setting intensity_uA; + struct led_flash_setting timeout_us; +#else + struct led_classdev cled; +#endif + struct gb_light *light; + bool is_registered; + bool releasing; + bool strobe_state; +}; + +struct gb_light { + u8 id; + char *name; + struct gb_lights *glights; + u32 flags; + u8 channels_count; + struct gb_channel *channels; + bool has_flash; +#ifdef V4L2_HAVE_FLASH + struct v4l2_flash *v4l2_flash; +#endif +}; + +struct gb_lights { + struct gb_connection *connection; + u8 lights_count; + struct gb_light *lights; + struct mutex lights_lock; +}; + +static void gb_lights_channel_free(struct gb_channel *channel); + +static struct gb_connection *get_conn_from_channel(struct gb_channel *channel) +{ + return channel->light->glights->connection; +} + +static struct gb_connection *get_conn_from_light(struct gb_light *light) +{ + return light->glights->connection; +} + +static bool is_channel_flash(struct gb_channel *channel) +{ + return !!(channel->mode & (GB_CHANNEL_MODE_FLASH | GB_CHANNEL_MODE_TORCH + | GB_CHANNEL_MODE_INDICATOR)); +} + +#ifdef LED_HAVE_FLASH +static struct gb_channel *get_channel_from_cdev(struct led_classdev *cdev) +{ + struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(cdev); + + return container_of(fled_cdev, struct gb_channel, fled); +} + +static struct led_classdev *get_channel_cdev(struct gb_channel *channel) +{ + return &channel->fled.led_cdev; +} + +static struct gb_channel *get_channel_from_mode(struct gb_light *light, + u32 mode) +{ + struct gb_channel *channel = NULL; + int i; + + for (i = 0; i < light->channels_count; i++) { + channel = &light->channels[i]; + if (channel && channel->mode == mode) + break; + } + return channel; +} + +static int __gb_lights_flash_intensity_set(struct gb_channel *channel, + u32 intensity) +{ + struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_lights_set_flash_intensity_request req; + + if (channel->releasing) + return -ESHUTDOWN; + + req.light_id = channel->light->id; + req.channel_id = channel->id; + req.intensity_uA = cpu_to_le32(intensity); + + return gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_FLASH_INTENSITY, + &req, sizeof(req), NULL, 0); +} + +static int __gb_lights_flash_brightness_set(struct gb_channel *channel) +{ + u32 intensity; + + /* If the channel is flash we need to get the attached torch channel */ + if (channel->mode & GB_CHANNEL_MODE_FLASH) + channel = get_channel_from_mode(channel->light, + GB_CHANNEL_MODE_TORCH); + + /* For not flash we need to convert brightness to intensity */ + intensity = channel->intensity_uA.min + + (channel->intensity_uA.step * channel->led->brightness); + + return __gb_lights_flash_intensity_set(channel, intensity); +} +#else /* LED_HAVE_FLASH */ +static struct gb_channel *get_channel_from_cdev(struct led_classdev *cdev) +{ + return container_of(cdev, struct gb_channel, cled); +} + +static struct led_classdev *get_channel_cdev(struct gb_channel *channel) +{ + return &channel->cled; +} + +static int __gb_lights_flash_brightness_set(struct gb_channel *channel) +{ + return 0; +} +#endif /* !LED_HAVE_FLASH */ + +#ifdef LED_HAVE_GROUPS +static int gb_lights_color_set(struct gb_channel *channel, u32 color); +static int gb_lights_fade_set(struct gb_channel *channel); + +#ifdef LED_HAVE_LOCK +static void led_lock(struct led_classdev *cdev) +{ + mutex_lock(&cdev->led_access); +} + +static void led_unlock(struct led_classdev *cdev) +{ + mutex_unlock(&cdev->led_access); +} +#else +static void led_lock(struct led_classdev *cdev) +{ +} + +static void led_unlock(struct led_classdev *cdev) +{ +} +#endif /* !LED_HAVE_LOCK */ + +#define gb_lights_fade_attr(__dir) \ +static ssize_t fade_##__dir##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct led_classdev *cdev = dev_get_drvdata(dev); \ + struct gb_channel *channel = get_channel_from_cdev(cdev); \ + \ + return sprintf(buf, "%u\n", channel->fade_##__dir); \ +} \ + \ +static ssize_t fade_##__dir##_store(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, size_t size) \ +{ \ + struct led_classdev *cdev = dev_get_drvdata(dev); \ + struct gb_channel *channel = get_channel_from_cdev(cdev); \ + u8 fade; \ + int ret; \ + \ + led_lock(cdev); \ + if (led_sysfs_is_disabled(cdev)) { \ + ret = -EBUSY; \ + goto unlock; \ + } \ + \ + ret = kstrtou8(buf, 0, &fade); \ + if (ret < 0) { \ + dev_err(dev, "could not parse fade value %d\n", ret); \ + goto unlock; \ + } \ + if (channel->fade_##__dir == fade) \ + goto unlock; \ + channel->fade_##__dir = fade; \ + \ + ret = gb_lights_fade_set(channel); \ + if (ret < 0) \ + goto unlock; \ + \ + ret = size; \ +unlock: \ + led_unlock(cdev); \ + return ret; \ +} \ +static DEVICE_ATTR_RW(fade_##__dir) + +gb_lights_fade_attr(in); +gb_lights_fade_attr(out); + +static ssize_t color_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct led_classdev *cdev = dev_get_drvdata(dev); + struct gb_channel *channel = get_channel_from_cdev(cdev); + + return sprintf(buf, "0x%08x\n", channel->color); +} + +static ssize_t color_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + struct led_classdev *cdev = dev_get_drvdata(dev); + struct gb_channel *channel = get_channel_from_cdev(cdev); + u32 color; + int ret; + + led_lock(cdev); + if (led_sysfs_is_disabled(cdev)) { + ret = -EBUSY; + goto unlock; + } + ret = kstrtou32(buf, 0, &color); + if (ret < 0) { + dev_err(dev, "could not parse color value %d\n", ret); + goto unlock; + } + + ret = gb_lights_color_set(channel, color); + if (ret < 0) + goto unlock; + + channel->color = color; + ret = size; +unlock: + led_unlock(cdev); + return ret; +} +static DEVICE_ATTR_RW(color); + +static int channel_attr_groups_set(struct gb_channel *channel, + struct led_classdev *cdev) +{ + int attr = 0; + int size = 0; + + if (channel->flags & GB_LIGHT_CHANNEL_MULTICOLOR) + size++; + if (channel->flags & GB_LIGHT_CHANNEL_FADER) + size++; + + if (!size) + return 0; + + /* Set attributes based in the channel flags */ + channel->attrs = kcalloc(size, sizeof(**channel->attrs), GFP_KERNEL); + if (!channel->attrs) + return -ENOMEM; + channel->attr_group = kcalloc(1, sizeof(*channel->attr_group), + GFP_KERNEL); + if (!channel->attr_group) + return -ENOMEM; + channel->attr_groups = kcalloc(2, sizeof(*channel->attr_groups), + GFP_KERNEL); + if (!channel->attr_groups) + return -ENOMEM; + + if (channel->flags & GB_LIGHT_CHANNEL_MULTICOLOR) + channel->attrs[attr++] = &dev_attr_color.attr; + if (channel->flags & GB_LIGHT_CHANNEL_FADER) { + channel->attrs[attr++] = &dev_attr_fade_in.attr; + channel->attrs[attr++] = &dev_attr_fade_out.attr; + } + + channel->attr_group->attrs = channel->attrs; + + channel->attr_groups[0] = channel->attr_group; + + cdev->groups = channel->attr_groups; + + return 0; +} + +static int gb_lights_fade_set(struct gb_channel *channel) +{ + struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_lights_set_fade_request req; + + if (channel->releasing) + return -ESHUTDOWN; + + req.light_id = channel->light->id; + req.channel_id = channel->id; + req.fade_in = channel->fade_in; + req.fade_out = channel->fade_out; + return gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_FADE, + &req, sizeof(req), NULL, 0); +} + +static int gb_lights_color_set(struct gb_channel *channel, u32 color) +{ + struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_lights_set_color_request req; + + if (channel->releasing) + return -ESHUTDOWN; + + req.light_id = channel->light->id; + req.channel_id = channel->id; + req.color = cpu_to_le32(color); + return gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_COLOR, + &req, sizeof(req), NULL, 0); +} +#else /* LED_HAVE_GROUPS */ +static int channel_attr_groups_set(struct gb_channel *channel, + struct led_classdev *cdev) +{ + return 0; +} +#endif /* !LED_HAVE_GROUPS */ + +static int __gb_lights_led_brightness_set(struct gb_channel *channel) +{ + struct gb_lights_set_brightness_request req; + struct gb_connection *connection = get_conn_from_channel(channel); + + req.light_id = channel->light->id; + req.channel_id = channel->id; + req.brightness = (u8)channel->led->brightness; + + return gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_BRIGHTNESS, + &req, sizeof(req), NULL, 0); +} + +static int __gb_lights_brightness_set(struct gb_channel *channel) +{ + int ret; + + if (channel->releasing) + return 0; + + if (is_channel_flash(channel)) + ret = __gb_lights_flash_brightness_set(channel); + else + ret = __gb_lights_led_brightness_set(channel); + + return ret; +} + +static void gb_brightness_set_work(struct work_struct *work) +{ + struct gb_channel *channel = container_of(work, struct gb_channel, + work_brightness_set); + + __gb_lights_brightness_set(channel); +} + +#ifdef LED_HAVE_SET_SYNC +static int gb_brightness_set_sync(struct led_classdev *cdev, + enum led_brightness value) +{ + struct gb_channel *channel = get_channel_from_cdev(cdev); + + channel->led->brightness = value; + + return __gb_lights_brightness_set(channel); +} +#endif + +static void gb_brightness_set(struct led_classdev *cdev, + enum led_brightness value) +{ + struct gb_channel *channel = get_channel_from_cdev(cdev); + + if (channel->releasing) + return; + + cdev->brightness = value; + schedule_work(&channel->work_brightness_set); +} + +static enum led_brightness gb_brightness_get(struct led_classdev *cdev) + +{ + struct gb_channel *channel = get_channel_from_cdev(cdev); + + return channel->led->brightness; +} + +static int gb_blink_set(struct led_classdev *cdev, unsigned long *delay_on, + unsigned long *delay_off) +{ + struct gb_channel *channel = get_channel_from_cdev(cdev); + struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_lights_blink_request req; + + if (channel->releasing) + return -ESHUTDOWN; + + req.light_id = channel->light->id; + req.channel_id = channel->id; + req.time_on_ms = cpu_to_le16(*delay_on); + req.time_off_ms = cpu_to_le16(*delay_off); + + return gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_BLINK, &req, + sizeof(req), NULL, 0); +} + +static void gb_lights_led_operations_set(struct gb_channel *channel, + struct led_classdev *cdev) +{ + cdev->brightness_set = gb_brightness_set; + cdev->brightness_get = gb_brightness_get; +#ifdef LED_HAVE_SET_SYNC + cdev->brightness_set_sync = gb_brightness_set_sync; +#endif + INIT_WORK(&channel->work_brightness_set, gb_brightness_set_work); + + if (channel->flags & GB_LIGHT_CHANNEL_BLINK) + cdev->blink_set = gb_blink_set; +} + +#ifdef V4L2_HAVE_FLASH +/* V4L2 specific helpers */ +static void __gb_lights_channel_v4l2_config(struct led_flash_setting *channel_s, + struct led_flash_setting *v4l2_s) +{ + v4l2_s->min = channel_s->min; + v4l2_s->max = channel_s->max; + v4l2_s->step = channel_s->step; + /* For v4l2 val is the default value */ + v4l2_s->val = channel_s->max; +} + +static int gb_lights_light_v4l2_register(struct gb_light *light) +{ + struct gb_connection *connection = get_conn_from_light(light); + struct device *dev = &connection->dev; + struct v4l2_flash_config *sd_cfg; + struct led_classdev_flash *fled; + struct led_classdev_flash *iled = NULL; + struct gb_channel *channel_torch, *channel_ind, *channel_flash; + int ret = 0; + + sd_cfg = kcalloc(1, sizeof(*sd_cfg), GFP_KERNEL); + if (!sd_cfg) + return -ENOMEM; + + channel_torch = get_channel_from_mode(light, GB_CHANNEL_MODE_TORCH); + if (channel_torch) + __gb_lights_channel_v4l2_config(&channel_torch->intensity_uA, + &sd_cfg->torch_intensity); + + channel_ind = get_channel_from_mode(light, GB_CHANNEL_MODE_INDICATOR); + if (channel_ind) { + __gb_lights_channel_v4l2_config(&channel_ind->intensity_uA, + &sd_cfg->indicator_intensity); + iled = &channel_ind->fled; + } + + channel_flash = get_channel_from_mode(light, GB_CHANNEL_MODE_FLASH); + WARN_ON(!channel_flash); + + fled = &channel_flash->fled; + + snprintf(sd_cfg->dev_name, sizeof(sd_cfg->dev_name), "%s", light->name); + + /* Set the possible values to faults, in our case all faults */ + sd_cfg->flash_faults = LED_FAULT_OVER_VOLTAGE | LED_FAULT_TIMEOUT | + LED_FAULT_OVER_TEMPERATURE | LED_FAULT_SHORT_CIRCUIT | + LED_FAULT_OVER_CURRENT | LED_FAULT_INDICATOR | + LED_FAULT_UNDER_VOLTAGE | LED_FAULT_INPUT_VOLTAGE | + LED_FAULT_LED_OVER_TEMPERATURE; + + light->v4l2_flash = v4l2_flash_init(dev, NULL, fled, iled, + NULL, sd_cfg); + if (IS_ERR_OR_NULL(light->v4l2_flash)) { + ret = PTR_ERR(light->v4l2_flash); + goto out_free; + } + + return ret; + +out_free: + kfree(sd_cfg); + return ret; +} + +static void gb_lights_light_v4l2_unregister(struct gb_light *light) +{ + v4l2_flash_release(light->v4l2_flash); +} +#else +static int gb_lights_light_v4l2_register(struct gb_light *light) +{ + struct gb_connection *connection = get_conn_from_light(light); + + dev_err(&connection->dev, "no support for v4l2 subdevices\n"); + return 0; +} + +static void gb_lights_light_v4l2_unregister(struct gb_light *light) +{ +} +#endif + +#ifdef LED_HAVE_FLASH +/* Flash specific operations */ +static int gb_lights_flash_intensity_set(struct led_classdev_flash *fcdev, + u32 brightness) +{ + struct gb_channel *channel = container_of(fcdev, struct gb_channel, + fled); + int ret; + + ret = __gb_lights_flash_intensity_set(channel, brightness); + if (ret < 0) + return ret; + + fcdev->brightness.val = brightness; + + return 0; +} + +static int gb_lights_flash_intensity_get(struct led_classdev_flash *fcdev, + u32 *brightness) +{ + *brightness = fcdev->brightness.val; + + return 0; +} + +static int gb_lights_flash_strobe_set(struct led_classdev_flash *fcdev, + bool state) +{ + struct gb_channel *channel = container_of(fcdev, struct gb_channel, + fled); + struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_lights_set_flash_strobe_request req; + int ret; + + if (channel->releasing) + return -ESHUTDOWN; + + req.light_id = channel->light->id; + req.channel_id = channel->id; + req.state = state ? 1 : 0; + + ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_FLASH_STROBE, + &req, sizeof(req), NULL, 0); + if (ret < 0) + return ret; + channel->strobe_state = state; + + return 0; +} + +static int gb_lights_flash_strobe_get(struct led_classdev_flash *fcdev, + bool *state) +{ + struct gb_channel *channel = container_of(fcdev, struct gb_channel, + fled); + + *state = channel->strobe_state; + return 0; +} + +static int gb_lights_flash_timeout_set(struct led_classdev_flash *fcdev, + u32 timeout) +{ + struct gb_channel *channel = container_of(fcdev, struct gb_channel, + fled); + struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_lights_set_flash_timeout_request req; + int ret; + + if (channel->releasing) + return -ESHUTDOWN; + + req.light_id = channel->light->id; + req.channel_id = channel->id; + req.timeout_us = cpu_to_le32(timeout); + + ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_FLASH_TIMEOUT, + &req, sizeof(req), NULL, 0); + if (ret < 0) + return ret; + fcdev->timeout.val = timeout; + + return 0; +} + +static int gb_lights_flash_fault_get(struct led_classdev_flash *fcdev, + u32 *fault) +{ + struct gb_channel *channel = container_of(fcdev, struct gb_channel, + fled); + struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_lights_get_flash_fault_request req; + struct gb_lights_get_flash_fault_response resp; + int ret; + + if (channel->releasing) + return -ESHUTDOWN; + + req.light_id = channel->light->id; + req.channel_id = channel->id; + + ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_GET_FLASH_FAULT, + &req, sizeof(req), &resp, sizeof(resp)); + if (ret < 0) + return ret; + + *fault = le32_to_cpu(resp.fault); + + return 0; +} + +static const struct led_flash_ops gb_lights_flash_ops = { + .flash_brightness_set = gb_lights_flash_intensity_set, + .flash_brightness_get = gb_lights_flash_intensity_get, + .strobe_set = gb_lights_flash_strobe_set, + .strobe_get = gb_lights_flash_strobe_get, + .timeout_set = gb_lights_flash_timeout_set, + .fault_get = gb_lights_flash_fault_get, +}; + +static int __gb_lights_channel_torch_attach(struct gb_channel *channel, + struct gb_channel *channel_torch) +{ + char *name; + + /* we can only attach torch to a flash channel */ + if (!(channel->mode & GB_CHANNEL_MODE_FLASH)) + return 0; + + /* Move torch brightness to the destination */ + channel->led->max_brightness = channel_torch->led->max_brightness; + + /* append mode name to flash name */ + name = kasprintf(GFP_KERNEL, "%s_%s", channel->led->name, + channel_torch->mode_name); + if (!name) + return -ENOMEM; + kfree(channel->led->name); + channel->led->name = name; + + /* free original torch channel resources */ + gb_lights_channel_free(channel_torch); + + channel_torch->led = channel->led; + + return 0; +} + +static int __gb_lights_flash_led_register(struct gb_channel *channel) +{ + struct gb_connection *connection = get_conn_from_channel(channel); + struct led_classdev_flash *fled = &channel->fled; + struct led_flash_setting *fset; + struct gb_channel *channel_torch; + int ret; + + fled->ops = &gb_lights_flash_ops; + + fled->led_cdev.flags |= LED_DEV_CAP_FLASH; + + fset = &fled->brightness; + fset->min = channel->intensity_uA.min; + fset->max = channel->intensity_uA.max; + fset->step = channel->intensity_uA.step; + + /* Only the flash mode have the timeout constraints settings */ + if (channel->mode & GB_CHANNEL_MODE_FLASH) { + fset = &fled->timeout; + fset->min = channel->timeout_us.min; + fset->max = channel->timeout_us.max; + fset->step = channel->timeout_us.step; + } + + /* + * If light have torch mode channel, this channel will be the led + * classdev of the registered above flash classdev + */ + channel_torch = get_channel_from_mode(channel->light, + GB_CHANNEL_MODE_TORCH); + if (channel_torch) { + ret = __gb_lights_channel_torch_attach(channel, channel_torch); + if (ret < 0) + goto fail; + } + + ret = led_classdev_flash_register(&connection->bundle->intf->dev, + fled); + if (ret < 0) + goto fail; + + channel->is_registered = true; + return 0; +fail: + channel->led = NULL; + return ret; +} + +static void __gb_lights_flash_led_unregister(struct gb_channel *channel) +{ + if (!channel->is_registered) + return; + + led_classdev_flash_unregister(&channel->fled); +} + +static int gb_lights_channel_flash_config(struct gb_channel *channel) +{ + struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_lights_get_channel_flash_config_request req; + struct gb_lights_get_channel_flash_config_response conf; + struct led_flash_setting *fset; + int ret; + + req.light_id = channel->light->id; + req.channel_id = channel->id; + + ret = gb_operation_sync(connection, + GB_LIGHTS_TYPE_GET_CHANNEL_FLASH_CONFIG, + &req, sizeof(req), &conf, sizeof(conf)); + if (ret < 0) + return ret; + + /* + * Intensity constraints for flash related modes: flash, torch, + * indicator. They will be needed for v4l2 registration. + */ + fset = &channel->intensity_uA; + fset->min = le32_to_cpu(conf.intensity_min_uA); + fset->max = le32_to_cpu(conf.intensity_max_uA); + fset->step = le32_to_cpu(conf.intensity_step_uA); + + /* + * On flash type, max brightness is set as the number of intensity steps + * available. + */ + channel->led->max_brightness = (fset->max - fset->min) / fset->step; + + /* Only the flash mode have the timeout constraints settings */ + if (channel->mode & GB_CHANNEL_MODE_FLASH) { + fset = &channel->timeout_us; + fset->min = le32_to_cpu(conf.timeout_min_us); + fset->max = le32_to_cpu(conf.timeout_max_us); + fset->step = le32_to_cpu(conf.timeout_step_us); + } + + return 0; +} +#else +static int gb_lights_channel_flash_config(struct gb_channel *channel) +{ + struct gb_connection *connection = get_conn_from_channel(channel); + + dev_err(&connection->dev, "no support for flash devices\n"); + return 0; +} + +static int __gb_lights_flash_led_register(struct gb_channel *channel) +{ + return 0; +} + +static void __gb_lights_flash_led_unregister(struct gb_channel *channel) +{ +} + +#endif /* LED_HAVE_FLASH */ + +static int __gb_lights_led_register(struct gb_channel *channel) +{ + struct gb_connection *connection = get_conn_from_channel(channel); + struct led_classdev *cdev = get_channel_cdev(channel); + int ret; + + ret = led_classdev_register(&connection->bundle->intf->dev, + cdev); + if (ret < 0) + channel->led = NULL; + else + channel->is_registered = true; + return ret; +} + +static int gb_lights_channel_register(struct gb_channel *channel) +{ + /* Normal LED channel, just register in led classdev and we are done */ + if (!is_channel_flash(channel)) + return __gb_lights_led_register(channel); + + /* + * Flash Type need more work, register flash classdev, indicator as + * flash classdev, torch will be led classdev of the flash classdev. + */ + if (!(channel->mode & GB_CHANNEL_MODE_TORCH)) + return __gb_lights_flash_led_register(channel); + + return 0; +} + +static void __gb_lights_led_unregister(struct gb_channel *channel) +{ + struct led_classdev *cdev = get_channel_cdev(channel); + + if (!channel->is_registered) + return; + + led_classdev_unregister(cdev); + channel->led = NULL; +} + +static void gb_lights_channel_unregister(struct gb_channel *channel) +{ + /* The same as register, handle channels differently */ + if (!is_channel_flash(channel)) { + __gb_lights_led_unregister(channel); + return; + } + + if (channel->mode & GB_CHANNEL_MODE_TORCH) + __gb_lights_led_unregister(channel); + else + __gb_lights_flash_led_unregister(channel); +} + +static int gb_lights_channel_config(struct gb_light *light, + struct gb_channel *channel) +{ + struct gb_lights_get_channel_config_response conf; + struct gb_lights_get_channel_config_request req; + struct gb_connection *connection = get_conn_from_light(light); + struct led_classdev *cdev = get_channel_cdev(channel); + char *name; + int ret; + + req.light_id = light->id; + req.channel_id = channel->id; + + ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_GET_CHANNEL_CONFIG, + &req, sizeof(req), &conf, sizeof(conf)); + if (ret < 0) + return ret; + + channel->light = light; + channel->mode = le32_to_cpu(conf.mode); + channel->flags = le32_to_cpu(conf.flags); + channel->color = le32_to_cpu(conf.color); + channel->color_name = kstrndup(conf.color_name, NAMES_MAX, GFP_KERNEL); + if (!channel->color_name) + return -ENOMEM; + channel->mode_name = kstrndup(conf.mode_name, NAMES_MAX, GFP_KERNEL); + if (!channel->mode_name) + return -ENOMEM; + + channel->led = cdev; + + name = kasprintf(GFP_KERNEL, "%s:%s:%s", light->name, + channel->color_name, channel->mode_name); + if (!name) + return -ENOMEM; + + cdev->name = name; + + cdev->max_brightness = conf.max_brightness; + + ret = channel_attr_groups_set(channel, cdev); + if (ret < 0) + return ret; + + gb_lights_led_operations_set(channel, cdev); + + /* + * If it is not a flash related channel (flash, torch or indicator) we + * are done here. If not, continue and fetch flash related + * configurations. + */ + if (!is_channel_flash(channel)) + return ret; + + light->has_flash = true; + + ret = gb_lights_channel_flash_config(channel); + if (ret < 0) + return ret; + + return ret; +} + +static int gb_lights_light_config(struct gb_lights *glights, u8 id) +{ + struct gb_light *light = &glights->lights[id]; + struct gb_lights_get_light_config_request req; + struct gb_lights_get_light_config_response conf; + int ret; + int i; + + light->glights = glights; + light->id = id; + + req.id = id; + + ret = gb_operation_sync(glights->connection, + GB_LIGHTS_TYPE_GET_LIGHT_CONFIG, + &req, sizeof(req), &conf, sizeof(conf)); + if (ret < 0) + return ret; + + if (!conf.channel_count) + return -EINVAL; + if (!strlen(conf.name)) + return -EINVAL; + + light->channels_count = conf.channel_count; + light->name = kstrndup(conf.name, NAMES_MAX, GFP_KERNEL); + + light->channels = kzalloc(light->channels_count * + sizeof(struct gb_channel), GFP_KERNEL); + if (!light->channels) + return -ENOMEM; + + /* First we collect all the configurations for all channels */ + for (i = 0; i < light->channels_count; i++) { + light->channels[i].id = i; + ret = gb_lights_channel_config(light, &light->channels[i]); + if (ret < 0) + return ret; + } + + /* + * Then, if everything went ok in getting configurations, we register + * the classdev, flash classdev and v4l2 subsystem, if a flash device is + * found. + */ + for (i = 0; i < light->channels_count; i++) { + ret = gb_lights_channel_register(&light->channels[i]); + if (ret < 0) + return ret; + } + + if (light->has_flash) { + ret = gb_lights_light_v4l2_register(light); + if (ret < 0) + return ret; + } + + return 0; +} + +static void gb_lights_channel_free(struct gb_channel *channel) +{ + if (&channel->work_brightness_set) + flush_work(&channel->work_brightness_set); + kfree(channel->attrs); + kfree(channel->attr_group); + kfree(channel->attr_groups); + kfree(channel->color_name); + kfree(channel->mode_name); +} + +static void gb_lights_channel_release(struct gb_channel *channel) +{ + if (!channel) + return; + + channel->releasing = true; + + gb_lights_channel_unregister(channel); + + gb_lights_channel_free(channel); +} + +static void gb_lights_light_release(struct gb_light *light) +{ + int i; + int count; + + if (!light) + return; + + count = light->channels_count; + + if (light->has_flash) + gb_lights_light_v4l2_unregister(light); + + for (i = 0; i < count; i++) { + gb_lights_channel_release(&light->channels[i]); + light->channels_count--; + } + kfree(light->channels); + kfree(light->name); +} + +static void gb_lights_release(struct gb_lights *glights) +{ + int i; + + if (!glights) + return; + + mutex_lock(&glights->lights_lock); + if (!glights->lights) + goto free_glights; + + for (i = 0; i < glights->lights_count; i++) + gb_lights_light_release(&glights->lights[i]); + + kfree(glights->lights); + +free_glights: + mutex_unlock(&glights->lights_lock); + mutex_destroy(&glights->lights_lock); + kfree(glights); +} + +static int gb_lights_get_count(struct gb_lights *glights) +{ + struct gb_lights_get_lights_response resp; + int ret; + + ret = gb_operation_sync(glights->connection, GB_LIGHTS_TYPE_GET_LIGHTS, + NULL, 0, &resp, sizeof(resp)); + if (ret < 0) + return ret; + + if (!resp.lights_count) + return -EINVAL; + + glights->lights_count = resp.lights_count; + + return 0; +} + +static int gb_lights_setup(struct gb_lights *glights) +{ + struct gb_connection *connection = glights->connection; + int ret; + int i; + + mutex_lock(&glights->lights_lock); + ret = gb_lights_get_count(glights); + if (ret < 0) + goto out; + + glights->lights = kzalloc(glights->lights_count * + sizeof(struct gb_light), GFP_KERNEL); + if (!glights->lights) { + ret = -ENOMEM; + goto out; + } + + for (i = 0; i < glights->lights_count; i++) { + ret = gb_lights_light_config(glights, i); + if (ret < 0) { + dev_err(&connection->dev, + "Fail to configure lights device\n"); + goto out; + } + } + +out: + mutex_unlock(&glights->lights_lock); + return ret; +} + +static int gb_lights_event_recv(u8 type, struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_lights *glights = connection->private; + struct gb_message *request; + struct gb_lights_event_request *payload; + int ret = 0; + u8 light_id; + u8 event; + + if (type != GB_LIGHTS_TYPE_EVENT) { + dev_err(&connection->dev, + "Unsupported unsolicited event: %u\n", type); + return -EINVAL; + } + + request = op->request; + + if (request->payload_size < sizeof(*payload)) { + dev_err(&connection->dev, + "Wrong event size received (%zu < %zu)\n", + request->payload_size, sizeof(*payload)); + return -EINVAL; + } + + payload = request->payload; + light_id = payload->light_id; + + if (light_id >= glights->lights_count || !&glights->lights[light_id]) { + dev_err(&connection->dev, + "Event received for unconfigured light id: %d\n", + light_id); + return -EINVAL; + } + + event = payload->event; + + if (event & GB_LIGHTS_LIGHT_CONFIG) { + mutex_lock(&glights->lights_lock); + gb_lights_light_release(&glights->lights[light_id]); + ret = gb_lights_light_config(glights, light_id); + if (ret < 0) + gb_lights_light_release(&glights->lights[light_id]); + mutex_unlock(&glights->lights_lock); + } + + return ret; +} + +static int gb_lights_connection_init(struct gb_connection *connection) +{ + struct gb_lights *glights; + int ret; + + glights = kzalloc(sizeof(*glights), GFP_KERNEL); + if (!glights) + return -ENOMEM; + + glights->connection = connection; + connection->private = glights; + + mutex_init(&glights->lights_lock); + + /* + * Setup all the lights devices over this connection, if anything goes + * wrong tear down all lights + */ + ret = gb_lights_setup(glights); + if (ret < 0) + goto out; + + return 0; + +out: + gb_lights_release(glights); + return ret; +} + +static void gb_lights_connection_exit(struct gb_connection *connection) +{ + struct gb_lights *glights = connection->private; + + gb_lights_release(glights); +} + +static struct gb_protocol lights_protocol = { + .name = "lights", + .id = GREYBUS_PROTOCOL_LIGHTS, + .major = GB_LIGHTS_VERSION_MAJOR, + .minor = GB_LIGHTS_VERSION_MINOR, + .connection_init = gb_lights_connection_init, + .connection_exit = gb_lights_connection_exit, + .request_recv = gb_lights_event_recv, +}; + +gb_protocol_driver(&lights_protocol); + +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 1ab2e8918de583f7f98289448af6d8784a4c4ced Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Sun, 16 Aug 2015 00:48:03 +0100 Subject: greybus: makefile: use POSIX functions for kernel cmp [[, == and echo -e are bash/zsh-ism and not POSIX, so when using a POSIX shell the kernel_cmp can issue some warnings and not work properly. Use only POSIX operators for kernel version compare. Signed-off-by: Rui Miguel Silva Tested-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 5c29b63..31b025d 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -61,7 +61,7 @@ ifneq ($(KERNELRELEASE),) # This function returns the argument version if current kernel version is minor # than the passed version, return 1 if equal or the current kernel version if it # is greater than argument version. -kvers_cmp=$(shell [[ "$(KERNELVERSION)" == "$(1)" ]] && echo 1 || echo -e "$(1)\n$(KERNELVERSION)" | sort -V | tail -1) +kvers_cmp=$(shell [ "$(KERNELVERSION)" = "$(1)" ] && echo 1 || printf "$(1)\n$(KERNELVERSION)" | sort -V | tail -1) ifneq ($(call kvers_cmp,"3.19.0"),3.19.0) CONFIG_OPTIONS_ENABLE += LEDS_CLASS_FLASH -- cgit v0.10.2 From 4be6ea54d46166dcd8f7673b87b578c611577c29 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Sat, 15 Aug 2015 08:54:18 +0530 Subject: greybus: operation: Fix wrong order of arguments The order of arguments is wrong and that shows up as a warning only on 64 bit machines. Fixes: cb0ef0c019ab ("operation: print message type on errors") Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 0bb5b8d..f9b71e7 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -869,7 +869,7 @@ static void gb_connection_recv_response(struct gb_connection *connection, message_size = sizeof(*message->header) + message->payload_size; if (!errno && size != message_size) { dev_err(&connection->dev, "bad message (0x%02hhx) size (%zu != %zu)\n", - size, message_size, message->header->type); + message->header->type, size, message_size); errno = -EMSGSIZE; } -- cgit v0.10.2 From 7ee582680230f56ad43afc9cbb46e050e1027afb Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Mon, 17 Aug 2015 17:03:43 +0100 Subject: greybus: greybus_protocol: remove unused lights macros Greybus core now handle the _INVALID and PROTOCOL_VERSION types, so no need to have specific protocol macros for this. Just drop them. Signed-off-by: Rui Miguel Silva Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 32b927f..0c11bec 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -1073,8 +1073,6 @@ struct gb_sdio_event_request { #define GB_LIGHTS_VERSION_MINOR 0x01 /* Greybus Lights request types */ -#define GB_LIGHTS_TYPE_INVALID 0x00 -#define GB_LIGHTS_TYPE_PROTOCOL_VERSION 0x01 #define GB_LIGHTS_TYPE_GET_LIGHTS 0x02 #define GB_LIGHTS_TYPE_GET_LIGHT_CONFIG 0x03 #define GB_LIGHTS_TYPE_GET_CHANNEL_CONFIG 0x04 -- cgit v0.10.2 From 464dc8cbdeb4a58791b9b6dc90e17e4b4f7d0d90 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 17 Aug 2015 00:57:16 +0100 Subject: greybus: interface: change typo replicable => replaceable 'user-replicable' means something that a user can replicate. 'user-replaceable' means something that a user can replace. We defintely mean to say replaceable not replicable here. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 4a26bf6..c5211a3 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -109,7 +109,7 @@ int gb_create_bundle_connection(struct gb_interface *intf, u8 class) } /* - * A Greybus module represents a user-replicable component on an Ara + * A Greybus module represents a user-replaceable component on an Ara * phone. An interface is the physical connection on that module. A * module may have more than one interface. * -- cgit v0.10.2 From 2f8423046f21093818ffc4fae917f8e9dd8e9931 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 17 Aug 2015 00:55:02 +0100 Subject: greybus: loopback: add ability to graph greybus latency This patch adds the ability to graph the latency of the overhead introduced by the greybus stack in the roundtrip time AP->Module->AP. Since this is a small number it is reported in nanoseconds, not mircoseconds. This data can also be derived with tracepoints but it's being provided in this format to export to CSV file more easily than with tracepoints. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 3263d83..74bc2b4 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -50,9 +50,11 @@ struct gb_loopback { int ms_wait; struct gb_loopback_stats latency; + struct gb_loopback_stats latency_gb; struct gb_loopback_stats throughput; struct gb_loopback_stats requests_per_second; u64 elapsed_nsecs; + u64 elapsed_nsecs_gb; u32 error; }; @@ -177,6 +179,8 @@ static void gb_loopback_check_attr(struct gb_connection *connection, /* Time to send and receive one message */ gb_loopback_stats_attrs(latency); +/* Time to send and receive one message not including greybus */ +gb_loopback_stats_attrs(latency_gb); /* Number of requests sent per second on this cport */ gb_loopback_stats_attrs(requests_per_second); /* Quantity of data sent and received on this cport */ @@ -209,6 +213,7 @@ gb_loopback_attr(iteration_max, u); static struct attribute *loopback_attrs[] = { dev_stats_attrs(latency), + dev_stats_attrs(latency_gb), dev_stats_attrs(requests_per_second), dev_stats_attrs(throughput), &dev_attr_type.attr, @@ -221,17 +226,16 @@ static struct attribute *loopback_attrs[] = { }; ATTRIBUTE_GROUPS(loopback); -static void gb_loopback_calc_latency(struct gb_loopback *gb, - struct timeval *ts, struct timeval *te) +static u64 gb_loopback_calc_latency(struct timeval *ts, struct timeval *te) { u64 t1, t2; t1 = timeval_to_ns(ts); t2 = timeval_to_ns(te); if (t2 > t1) - gb->elapsed_nsecs = t2 - t1; + return t2 - t1; else - gb->elapsed_nsecs = NSEC_PER_DAY - t2 + t1; + return NSEC_PER_DAY - t2 + t1; } static int gb_loopback_sink(struct gb_loopback *gb, u32 len) @@ -251,7 +255,15 @@ static int gb_loopback_sink(struct gb_loopback *gb, u32 len) request, len + sizeof(*request), NULL, 0); do_gettimeofday(&te); - gb_loopback_calc_latency(gb, &ts, &te); + + /* Calculate the total time the message took */ + gb->elapsed_nsecs = gb_loopback_calc_latency(&ts, &te); + + /* Calculate non-greybus related component of the latency */ + gb_connection_pop_timestamp(gb->connection, &ts); + gb_connection_pop_timestamp(gb->connection, &te); + gb->elapsed_nsecs_gb = gb_loopback_calc_latency(&ts, &te); + kfree(request); return retval; @@ -282,7 +294,14 @@ static int gb_loopback_transfer(struct gb_loopback *gb, u32 len) request, len + sizeof(*request), response, len + sizeof(*response)); do_gettimeofday(&te); - gb_loopback_calc_latency(gb, &ts, &te); + + /* Calculate the total time the message took */ + gb->elapsed_nsecs = gb_loopback_calc_latency(&ts, &te); + + /* Calculate non-greybus related component of the latency */ + gb_connection_pop_timestamp(gb->connection, &ts); + gb_connection_pop_timestamp(gb->connection, &te); + gb->elapsed_nsecs_gb = gb_loopback_calc_latency(&ts, &te); if (retval) goto gb_error; @@ -308,7 +327,14 @@ static int gb_loopback_ping(struct gb_loopback *gb) retval = gb_operation_sync(gb->connection, GB_LOOPBACK_TYPE_PING, NULL, 0, NULL, 0); do_gettimeofday(&te); - gb_loopback_calc_latency(gb, &ts, &te); + + /* Calculate the total time the message took */ + gb->elapsed_nsecs = gb_loopback_calc_latency(&ts, &te); + + /* Calculate non-greybus related component of the latency */ + gb_connection_pop_timestamp(gb->connection, &ts); + gb_connection_pop_timestamp(gb->connection, &te); + gb->elapsed_nsecs_gb = gb_loopback_calc_latency(&ts, &te); return retval; } @@ -371,6 +397,7 @@ static void gb_loopback_reset_stats(struct gb_loopback *gb) .min = U32_MAX, }; memcpy(&gb->latency, &reset, sizeof(struct gb_loopback_stats)); + memcpy(&gb->latency_gb, &reset, sizeof(struct gb_loopback_stats)); memcpy(&gb->throughput, &reset, sizeof(struct gb_loopback_stats)); memcpy(&gb->requests_per_second, &reset, sizeof(struct gb_loopback_stats)); @@ -439,6 +466,11 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb) /* Log throughput and requests using latency as benchmark */ gb_loopback_throughput_update(gb, lat); gb_loopback_requests_update(gb, lat); + + /* Calculate the greybus related latency number in nanoseconds */ + tmp = gb->elapsed_nsecs - gb->elapsed_nsecs_gb; + lat = tmp; + gb_loopback_update_stats(&gb->latency_gb, lat); } static int gb_loopback_fn(void *data) -- cgit v0.10.2 From aa27bf82694de73f850581d5c928d99b16032be7 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 17 Aug 2015 00:55:03 +0100 Subject: greybus: loopback: convert sample report interface to debugfs Greg previously suggested switching over to debugfs instead of a char interface to report raw samples to user-space. At the time we agreed not to go for that change. However later patches in this series are made simpler if debugfs is used instead of /dev, so it makes sense to make the conversion now for that reason. This patch removes the char interface and replaces it with a debugfs interface. Raw samples will be acquired from /sys/kernel/debug/gb_loopback/raw_latency_endo0:x:y:z:w where x = y = z = w = Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 74bc2b4..5f66048 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -31,16 +32,21 @@ struct gb_loopback_stats { u32 count; }; +struct gb_loopback_device { + struct dentry *root; + u32 count; +}; + +static struct gb_loopback_device gb_dev; + struct gb_loopback { struct gb_connection *connection; + struct dentry *file; struct kfifo kfifo; struct mutex mutex; struct task_struct *task; wait_queue_head_t wq; - dev_t dev; - struct cdev cdev; - struct device *device; int type; u32 size; @@ -60,16 +66,9 @@ struct gb_loopback { #define GB_LOOPBACK_FIFO_DEFAULT 8192 -static struct class *loopback_class; -static int loopback_major; -static const struct file_operations loopback_fops; -static DEFINE_IDA(minors); static unsigned kfifo_depth = GB_LOOPBACK_FIFO_DEFAULT; module_param(kfifo_depth, uint, 0444); -/* Number of minor devices this driver supports */ -#define NUM_MINORS 256 - /* Maximum size of any one send data buffer we support */ #define MAX_PACKET_SIZE (PAGE_SIZE * 2) @@ -515,35 +514,72 @@ static int gb_loopback_fn(void *data) return 0; } +static int gb_loopback_dbgfs_latency_show(struct seq_file *s, void *unused) +{ + struct gb_loopback *gb = s->private; + u32 latency; + int retval; + + if (kfifo_len(&gb->kfifo) == 0) { + retval = -EAGAIN; + goto done; + } + + mutex_lock(&gb->mutex); + retval = kfifo_out(&gb->kfifo, &latency, sizeof(latency)); + if (retval > 0) { + seq_printf(s, "%u", latency); + retval = 0; + } + mutex_unlock(&gb->mutex); +done: + return retval; +} + +static int gb_loopback_latency_open(struct inode *inode, struct file *file) +{ + return single_open(file, gb_loopback_dbgfs_latency_show, + inode->i_private); +} + +static const struct file_operations gb_loopback_debugfs_latency_ops = { + .open = gb_loopback_latency_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +#define DEBUGFS_NAMELEN 24 + static int gb_loopback_connection_init(struct gb_connection *connection) { struct gb_loopback *gb; int retval; - int minor; + char name[DEBUGFS_NAMELEN]; gb = kzalloc(sizeof(*gb), GFP_KERNEL); if (!gb) return -ENOMEM; gb_loopback_reset_stats(gb); + snprintf(name, sizeof(name), "raw_latency_endo0:%d:%d:%d:%d", + connection->bundle->intf->module->module_id, + connection->bundle->intf->interface_id, + connection->bundle->id, + connection->intf_cport_id); + gb->file = debugfs_create_file(name, S_IFREG | S_IRUGO, gb_dev.root, gb, + &gb_loopback_debugfs_latency_ops); gb->connection = connection; connection->private = gb; retval = sysfs_create_groups(&connection->dev.kobj, loopback_groups); if (retval) - goto out_free; - - /* Get a minor number */ - minor = ida_simple_get(&minors, 0, 0, GFP_KERNEL); - if (minor < 0) { - retval = minor; - goto out_sysfs; - } + goto out_debugfs; /* Calculate maximum payload */ gb->size_max = gb_operation_get_payload_size_max(connection); if (gb->size_max <= sizeof(struct gb_loopback_transfer_request)) { retval = -EINVAL; - goto out_minor; + goto out_sysfs; } gb->size_max -= sizeof(struct gb_loopback_transfer_request); @@ -551,21 +587,7 @@ static int gb_loopback_connection_init(struct gb_connection *connection) if (kfifo_alloc(&gb->kfifo, kfifo_depth * sizeof(u32), GFP_KERNEL)) { retval = -ENOMEM; - goto out_minor; - } - - /* Create device entry */ - gb->dev = MKDEV(loopback_major, minor); - cdev_init(&gb->cdev, &loopback_fops); - retval = cdev_add(&gb->cdev, gb->dev, 1); - if (retval) - goto out_kfifo; - - gb->device = device_create(loopback_class, &connection->dev, gb->dev, - gb, "gb!loopback%d", minor); - if (IS_ERR(gb->device)) { - retval = PTR_ERR(gb->device); - goto out_cdev; + goto out_sysfs; } /* Fork worker thread */ @@ -574,22 +596,18 @@ static int gb_loopback_connection_init(struct gb_connection *connection) gb->task = kthread_run(gb_loopback_fn, gb, "gb_loopback"); if (IS_ERR(gb->task)) { retval = PTR_ERR(gb->task); - goto out_device; + goto out_kfifo; } + gb_dev.count++; return 0; -out_device: - device_del(gb->device); -out_cdev: - cdev_del(&gb->cdev); out_kfifo: kfifo_free(&gb->kfifo); -out_minor: - ida_simple_remove(&minors, minor); out_sysfs: sysfs_remove_groups(&connection->dev.kobj, loopback_groups); -out_free: +out_debugfs: + debugfs_remove(gb->file); connection->private = NULL; kfree(gb); @@ -600,15 +618,14 @@ static void gb_loopback_connection_exit(struct gb_connection *connection) { struct gb_loopback *gb = connection->private; + gb_dev.count--; connection->private = NULL; if (!IS_ERR_OR_NULL(gb->task)) kthread_stop(gb->task); - device_del(gb->device); - cdev_del(&gb->cdev); kfifo_free(&gb->kfifo); - ida_simple_remove(&minors, MINOR(gb->dev)); sysfs_remove_groups(&connection->dev.kobj, loopback_groups); + debugfs_remove(gb->file); kfree(gb); } @@ -622,79 +639,17 @@ static struct gb_protocol loopback_protocol = { .request_recv = gb_loopback_request_recv, }; -static int loopback_open(struct inode *inode, struct file *file) -{ - struct cdev *cdev = inode->i_cdev; - struct gb_loopback *gb = container_of(cdev, struct gb_loopback, cdev); - - file->private_data = gb; - return 0; -} - -static ssize_t loopback_read(struct file *file, char __user *buf, size_t count, - loff_t *ppos) -{ - struct gb_loopback *gb = file->private_data; - size_t fifo_len; - int retval; - - if (!count || count % sizeof(u32)) - return -EINVAL; - - mutex_lock(&gb->mutex); - fifo_len = kfifo_len(&gb->kfifo); - if (kfifo_to_user(&gb->kfifo, buf, min(fifo_len, count), &retval) != 0) - retval = -EIO; - mutex_unlock(&gb->mutex); - - return retval; -} - -static const struct file_operations loopback_fops = { - .owner = THIS_MODULE, - .read = loopback_read, - .open = loopback_open, - .llseek = noop_llseek, -}; - static int loopback_init(void) { - dev_t dev; - int retval; - - loopback_class = class_create(THIS_MODULE, "gb_loopback"); - if (IS_ERR(loopback_class)) { - retval = PTR_ERR(loopback_class); - goto error_class; - } - - retval = alloc_chrdev_region(&dev, 0, NUM_MINORS, "gb_loopback"); - if (retval < 0) - goto error_chrdev; - - loopback_major = MAJOR(dev); - - retval = gb_protocol_register(&loopback_protocol); - if (retval) - goto error_gb; - - return 0; - -error_gb: - unregister_chrdev_region(dev, NUM_MINORS); -error_chrdev: - class_destroy(loopback_class); -error_class: - return retval; + gb_dev.root = debugfs_create_dir("gb_loopback", NULL); + return gb_protocol_register(&loopback_protocol); } module_init(loopback_init); static void __exit loopback_exit(void) { + debugfs_remove_recursive(gb_dev.root); gb_protocol_deregister(&loopback_protocol); - unregister_chrdev_region(MKDEV(loopback_major, 0), NUM_MINORS); - class_destroy(loopback_class); - ida_destroy(&minors); } module_exit(loopback_exit); -- cgit v0.10.2 From 67d1eeceb1aab4a192a0f132cd230d41932ba91e Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 17 Aug 2015 00:55:04 +0100 Subject: greybus: loopback: support synchronized tests over multiple cports The loopback code as currently implemented allows free running threads to blast data to cports in isolation, however no overall stastics are gathered for the aggregate throughput to a given module. This patch moves derivation of stastics for all cports to one structure so that 1 to n cports will report their overall stastics in one place. Later patches update the sysfs/debugfs accessor functions to provide the per-module and per-connection data separately. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 5f66048..b46ded2 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -35,6 +35,27 @@ struct gb_loopback_stats { struct gb_loopback_device { struct dentry *root; u32 count; + + struct mutex mutex; + struct list_head list; + wait_queue_head_t wq; + + int type; + u32 size; + u32 iteration_max; + u32 iteration_count; + size_t size_max; + int ms_wait; + u32 error; + + struct timeval start; + struct timeval end; + + /* Overall stats */ + struct gb_loopback_stats latency; + struct gb_loopback_stats latency_gb; + struct gb_loopback_stats throughput; + struct gb_loopback_stats requests_per_second; }; static struct gb_loopback_device gb_dev; @@ -46,19 +67,15 @@ struct gb_loopback { struct kfifo kfifo; struct mutex mutex; struct task_struct *task; - wait_queue_head_t wq; - - int type; - u32 size; - u32 iteration_max; - u32 iteration_count; - size_t size_max; - int ms_wait; + struct list_head entry; + /* Per connection stats */ struct gb_loopback_stats latency; struct gb_loopback_stats latency_gb; struct gb_loopback_stats throughput; struct gb_loopback_stats requests_per_second; + + u32 iteration_count; u64 elapsed_nsecs; u64 elapsed_nsecs_gb; u32 error; @@ -133,45 +150,86 @@ static ssize_t field##_store(struct device *dev, \ { \ int ret; \ struct gb_connection *connection = to_gb_connection(dev); \ - struct gb_loopback *gb = connection->private; \ - mutex_lock(&gb->mutex); \ + mutex_lock(&gb_dev.mutex); \ ret = sscanf(buf, "%"#type, &gb->field); \ if (ret != 1) \ len = -EINVAL; \ else \ - gb_loopback_check_attr(connection, gb); \ - mutex_unlock(&gb->mutex); \ + gb_loopback_check_attr(connection); \ + mutex_unlock(&gb_dev.mutex); \ return len; \ } \ static DEVICE_ATTR_RW(field) -static void gb_loopback_reset_stats(struct gb_loopback *gb); -static void gb_loopback_check_attr(struct gb_connection *connection, - struct gb_loopback *gb) +#define gb_dev_loopback_ro_attr(field) \ +static ssize_t field##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + return sprintf(buf, "%u\n", gb_dev.field); \ +} \ +static DEVICE_ATTR_RO(field) + +#define gb_dev_loopback_rw_attr(field, type) \ +static ssize_t field##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + return sprintf(buf, "%"#type"\n", gb_dev.field); \ +} \ +static ssize_t field##_store(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, \ + size_t len) \ +{ \ + int ret; \ + struct gb_connection *connection = to_gb_connection(dev); \ + mutex_lock(&gb_dev.mutex); \ + ret = sscanf(buf, "%"#type, &gb_dev.field); \ + if (ret != 1) \ + len = -EINVAL; \ + else \ + gb_loopback_check_attr(&gb_dev, connection); \ + mutex_unlock(&gb_dev.mutex); \ + return len; \ +} \ +static DEVICE_ATTR_RW(field) + +static void gb_loopback_reset_stats(struct gb_loopback_device *gb_dev); +static void gb_loopback_check_attr(struct gb_loopback_device *gb_dev, + struct gb_connection *connection) { - if (gb->ms_wait > GB_LOOPBACK_MS_WAIT_MAX) - gb->ms_wait = GB_LOOPBACK_MS_WAIT_MAX; - if (gb->size > gb->size_max) - gb->size = gb->size_max; - gb->error = 0; - gb->iteration_count = 0; - gb_loopback_reset_stats(gb); - - if (kfifo_depth < gb->iteration_max) { - dev_warn(&connection->dev, - "iteration_max %u kfifo_depth %u cannot log all data\n", - gb->iteration_max, kfifo_depth); + struct gb_loopback *gb; + + if (gb_dev->ms_wait > GB_LOOPBACK_MS_WAIT_MAX) + gb_dev->ms_wait = GB_LOOPBACK_MS_WAIT_MAX; + if (gb_dev->size > gb_dev->size_max) + gb_dev->size = gb_dev->size_max; + gb_dev->iteration_count = 0; + gb_dev->error = 0; + + list_for_each_entry(gb, &gb_dev->list, entry) { + mutex_lock(&gb->mutex); + gb->iteration_count = 0; + gb->error = 0; + if (kfifo_depth < gb_dev->iteration_max) { + dev_warn(&connection->dev, + "cannot log bytes %u kfifo_depth %u\n", + gb_dev->iteration_max, kfifo_depth); + } + kfifo_reset_out(&gb->kfifo); + mutex_unlock(&gb->mutex); } - switch (gb->type) { + switch (gb_dev->type) { case GB_LOOPBACK_TYPE_PING: case GB_LOOPBACK_TYPE_TRANSFER: case GB_LOOPBACK_TYPE_SINK: - kfifo_reset_out(&gb->kfifo); - wake_up(&gb->wq); + gb_loopback_reset_stats(gb_dev); + wake_up(&gb_dev->wq); break; default: - gb->type = 0; + gb_dev->type = 0; break; } } @@ -186,8 +244,6 @@ gb_loopback_stats_attrs(requests_per_second); gb_loopback_stats_attrs(throughput); /* Number of errors encountered during loop */ gb_loopback_ro_attr(error); -/* The current index of the for (i = 0; i < iteration_max; i++) loop */ -gb_loopback_ro_attr(iteration_count); /* * Type of loopback message to send based on protocol type definitions @@ -197,13 +253,15 @@ gb_loopback_ro_attr(iteration_count); * payload returned in response) * 4 => Send a sink message (message with payload, no payload in response) */ -gb_loopback_attr(type, d); +gb_dev_loopback_rw_attr(type, d); /* Size of transfer message payload: 0-4096 bytes */ -gb_loopback_attr(size, u); +gb_dev_loopback_rw_attr(size, u); /* Time to wait between two messages: 0-1000 ms */ -gb_loopback_attr(ms_wait, d); +gb_dev_loopback_rw_attr(ms_wait, d); /* Maximum iterations for a given operation: 1-(2^32-1), 0 implies infinite */ -gb_loopback_attr(iteration_max, u); +gb_dev_loopback_rw_attr(iteration_max, u); +/* The current index of the for (i = 0; i < iteration_max; i++) loop */ +gb_dev_loopback_ro_attr(iteration_count); #define dev_stats_attrs(name) \ &dev_attr_##name##_min.attr, \ @@ -341,7 +399,6 @@ static int gb_loopback_ping(struct gb_loopback *gb) static int gb_loopback_request_recv(u8 type, struct gb_operation *operation) { struct gb_connection *connection = operation->connection; - struct gb_loopback *gb = connection->private; struct gb_loopback_transfer_request *request; struct gb_loopback_transfer_response *response; size_t len; @@ -365,10 +422,10 @@ static int gb_loopback_request_recv(u8 type, struct gb_operation *operation) } request = operation->request->payload; len = le32_to_cpu(request->len); - if (len > gb->size_max) { + if (len > gb_dev.size_max) { dev_err(&connection->dev, "transfer request too large (%zu > %zu)\n", - len, gb->size_max); + len, gb_dev.size_max); return -EINVAL; } @@ -390,15 +447,34 @@ static int gb_loopback_request_recv(u8 type, struct gb_operation *operation) } } -static void gb_loopback_reset_stats(struct gb_loopback *gb) +static void gb_loopback_reset_stats(struct gb_loopback_device *gb_dev) { struct gb_loopback_stats reset = { .min = U32_MAX, }; - memcpy(&gb->latency, &reset, sizeof(struct gb_loopback_stats)); - memcpy(&gb->latency_gb, &reset, sizeof(struct gb_loopback_stats)); - memcpy(&gb->throughput, &reset, sizeof(struct gb_loopback_stats)); - memcpy(&gb->requests_per_second, &reset, + struct gb_loopback *gb; + + /* Reset per-connection stats */ + list_for_each_entry(gb, &gb_dev->list, entry) { + mutex_lock(&gb->mutex); + memcpy(&gb->latency, &reset, + sizeof(struct gb_loopback_stats)); + memcpy(&gb->latency_gb, &reset, + sizeof(struct gb_loopback_stats)); + memcpy(&gb->throughput, &reset, + sizeof(struct gb_loopback_stats)); + memcpy(&gb->requests_per_second, &reset, + sizeof(struct gb_loopback_stats)); + mutex_unlock(&gb->mutex); + } + + /* Reset aggregate stats */ + memset(&gb_dev->start, 0, sizeof(struct timeval)); + memset(&gb_dev->end, 0, sizeof(struct timeval)); + memcpy(&gb_dev->latency, &reset, sizeof(struct gb_loopback_stats)); + memcpy(&gb_dev->latency_gb, &reset, sizeof(struct gb_loopback_stats)); + memcpy(&gb_dev->throughput, &reset, sizeof(struct gb_loopback_stats)); + memcpy(&gb_dev->requests_per_second, &reset, sizeof(struct gb_loopback_stats)); } @@ -417,6 +493,7 @@ static void gb_loopback_requests_update(struct gb_loopback *gb, u32 latency) u32 req = USEC_PER_SEC; do_div(req, latency); + gb_loopback_update_stats(&gb_dev.requests_per_second, req); gb_loopback_update_stats(&gb->requests_per_second, req); } @@ -425,17 +502,17 @@ static void gb_loopback_throughput_update(struct gb_loopback *gb, u32 latency) u32 throughput; u32 aggregate_size = sizeof(struct gb_operation_msg_hdr) * 2; - switch (gb->type) { + switch (gb_dev.type) { case GB_LOOPBACK_TYPE_PING: break; case GB_LOOPBACK_TYPE_SINK: aggregate_size += sizeof(struct gb_loopback_transfer_request) + - gb->size; + gb_dev.size; break; case GB_LOOPBACK_TYPE_TRANSFER: aggregate_size += sizeof(struct gb_loopback_transfer_request) + sizeof(struct gb_loopback_transfer_response) + - gb->size * 2; + gb_dev.size * 2; break; default: return; @@ -445,6 +522,7 @@ static void gb_loopback_throughput_update(struct gb_loopback *gb, u32 latency) throughput = USEC_PER_SEC; do_div(throughput, latency); throughput *= aggregate_size; + gb_loopback_update_stats(&gb_dev.throughput, throughput); gb_loopback_update_stats(&gb->throughput, throughput); } @@ -459,7 +537,10 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb) lat = tmp; /* Log latency statistic */ + gb_loopback_update_stats(&gb_dev.latency, lat); gb_loopback_update_stats(&gb->latency, lat); + + /* Raw latency log on a per thread basis */ kfifo_in(&gb->kfifo, (unsigned char *)&lat, sizeof(lat)); /* Log throughput and requests using latency as benchmark */ @@ -469,6 +550,7 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb) /* Calculate the greybus related latency number in nanoseconds */ tmp = gb->elapsed_nsecs - gb->elapsed_nsecs_gb; lat = tmp; + gb_loopback_update_stats(&gb_dev.latency_gb, lat); gb_loopback_update_stats(&gb->latency_gb, lat); } @@ -476,38 +558,74 @@ static int gb_loopback_fn(void *data) { int error = 0; int ms_wait; + int type; + u32 size; + u32 low_count; struct gb_loopback *gb = data; + struct gb_loopback *gb_list; while (1) { - if (!gb->type) - wait_event_interruptible(gb->wq, gb->type || + if (!gb_dev.type) + wait_event_interruptible(gb_dev.wq, gb_dev.type || kthread_should_stop()); if (kthread_should_stop()) break; - mutex_lock(&gb->mutex); - if (gb->iteration_max) { - if (gb->iteration_count < gb->iteration_max) { - gb->iteration_count++; + mutex_lock(&gb_dev.mutex); + if (gb_dev.iteration_max) { + /* Determine overall lowest count */ + low_count = gb->iteration_count; + list_for_each_entry(gb_list, &gb_dev.list, entry) { + if (gb_list->iteration_count < low_count) + low_count = gb_list->iteration_count; + } + /* All threads achieved at least low_count iterations */ + if (gb_dev.iteration_count < low_count) { + gb_dev.iteration_count = low_count; sysfs_notify(&gb->connection->dev.kobj, NULL, "iteration_count"); - } else { - gb->type = 0; - mutex_unlock(&gb->mutex); + } + /* Optionally terminate */ + if (gb_dev.iteration_count == gb_dev.iteration_max) { + gb_dev.type = 0; + mutex_unlock(&gb_dev.mutex); continue; } } - if (gb->type == GB_LOOPBACK_TYPE_PING) + size = gb_dev.size; + ms_wait = gb_dev.ms_wait; + type = gb_dev.type; + mutex_unlock(&gb_dev.mutex); + + mutex_lock(&gb->mutex); + if (gb->iteration_count >= gb_dev.iteration_max) { + /* If this thread finished before siblings then sleep */ + ms_wait = 1; + mutex_unlock(&gb->mutex); + goto sleep; + } + /* Else operations to perform */ + if (type == GB_LOOPBACK_TYPE_PING) error = gb_loopback_ping(gb); - else if (gb->type == GB_LOOPBACK_TYPE_TRANSFER) - error = gb_loopback_transfer(gb, gb->size); - else if (gb->type == GB_LOOPBACK_TYPE_SINK) - error = gb_loopback_sink(gb, gb->size); - if (error) + else if (type == GB_LOOPBACK_TYPE_TRANSFER) + error = gb_loopback_transfer(gb, size); + else if (type == GB_LOOPBACK_TYPE_SINK) + error = gb_loopback_sink(gb, size); + mutex_unlock(&gb->mutex); + + mutex_lock(&gb_dev.mutex); + mutex_lock(&gb->mutex); + + if (error) { + gb_dev.error++; gb->error++; + } gb_loopback_calculate_stats(gb); - ms_wait = gb->ms_wait; + gb->iteration_count++; + mutex_unlock(&gb->mutex); + mutex_unlock(&gb_dev.mutex); +sleep: if (ms_wait) msleep(ms_wait); } @@ -549,7 +667,7 @@ static const struct file_operations gb_loopback_debugfs_latency_ops = { .release = single_release, }; -#define DEBUGFS_NAMELEN 24 +#define DEBUGFS_NAMELEN 32 static int gb_loopback_connection_init(struct gb_connection *connection) { @@ -560,7 +678,7 @@ static int gb_loopback_connection_init(struct gb_connection *connection) gb = kzalloc(sizeof(*gb), GFP_KERNEL); if (!gb) return -ENOMEM; - gb_loopback_reset_stats(gb); + gb_loopback_reset_stats(&gb_dev); snprintf(name, sizeof(name), "raw_latency_endo0:%d:%d:%d:%d", connection->bundle->intf->module->module_id, @@ -576,12 +694,14 @@ static int gb_loopback_connection_init(struct gb_connection *connection) goto out_debugfs; /* Calculate maximum payload */ - gb->size_max = gb_operation_get_payload_size_max(connection); - if (gb->size_max <= sizeof(struct gb_loopback_transfer_request)) { + mutex_lock(&gb_dev.mutex); + gb_dev.size_max = gb_operation_get_payload_size_max(connection); + if (gb_dev.size_max <= sizeof(struct gb_loopback_transfer_request)) { retval = -EINVAL; goto out_sysfs; } - gb->size_max -= sizeof(struct gb_loopback_transfer_request); + gb_dev.size_max -= sizeof(struct gb_loopback_transfer_request); + mutex_unlock(&gb_dev.mutex); /* Allocate kfifo */ if (kfifo_alloc(&gb->kfifo, kfifo_depth * sizeof(u32), @@ -591,7 +711,6 @@ static int gb_loopback_connection_init(struct gb_connection *connection) } /* Fork worker thread */ - init_waitqueue_head(&gb->wq); mutex_init(&gb->mutex); gb->task = kthread_run(gb_loopback_fn, gb, "gb_loopback"); if (IS_ERR(gb->task)) { @@ -599,6 +718,9 @@ static int gb_loopback_connection_init(struct gb_connection *connection) goto out_kfifo; } + mutex_lock(&gb_dev.mutex); + list_add_tail(&gb->entry, &gb_dev.list); + mutex_unlock(&gb_dev.mutex); gb_dev.count++; return 0; @@ -641,7 +763,11 @@ static struct gb_protocol loopback_protocol = { static int loopback_init(void) { + init_waitqueue_head(&gb_dev.wq); + INIT_LIST_HEAD(&gb_dev.list); + mutex_init(&gb_dev.mutex); gb_dev.root = debugfs_create_dir("gb_loopback", NULL); + return gb_protocol_register(&loopback_protocol); } module_init(loopback_init); -- cgit v0.10.2 From bd416103b204494e29b095e28c5a7b6a77e8f2b9 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 17 Aug 2015 00:55:05 +0100 Subject: greybus: loopback: add gb_loopback_nsec_to_usec_latency A helper function to convert from a nanosecond value to a latency value expressed in mircoseconds. This will be used again in subsequent patches. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index b46ded2..4879edd 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -283,6 +283,15 @@ static struct attribute *loopback_attrs[] = { }; ATTRIBUTE_GROUPS(loopback); +static u32 gb_loopback_nsec_to_usec_latency(u64 elapsed_nsecs) +{ + u32 lat; + + do_div(elapsed_nsecs, NSEC_PER_USEC); + lat = elapsed_nsecs; + return lat; +} + static u64 gb_loopback_calc_latency(struct timeval *ts, struct timeval *te) { u64 t1, t2; @@ -532,9 +541,7 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb) u64 tmp; /* Express latency in terms of microseconds */ - tmp = gb->elapsed_nsecs; - do_div(tmp, NSEC_PER_USEC); - lat = tmp; + lat = gb_loopback_nsec_to_usec_latency(gb->elapsed_nsecs); /* Log latency statistic */ gb_loopback_update_stats(&gb_dev.latency, lat); -- cgit v0.10.2 From 7c985351d40475ab752b230d5761e646973cb59b Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 17 Aug 2015 00:55:06 +0100 Subject: greybus: loopback: functionally decompose gb_loopback_calc_latency The __gb_loopback_calc_latency will be useful in later patches. Provide it here and use as intended. Later on we just want to use the timestamp rollover detection, so split it out now. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 4879edd..39375f1 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -292,16 +292,22 @@ static u32 gb_loopback_nsec_to_usec_latency(u64 elapsed_nsecs) return lat; } +static u64 __gb_loopback_calc_latency(u64 t1, u64 t2) +{ + if (t2 > t1) + return t2 - t1; + else + return NSEC_PER_DAY - t2 + t1; +} + static u64 gb_loopback_calc_latency(struct timeval *ts, struct timeval *te) { u64 t1, t2; t1 = timeval_to_ns(ts); t2 = timeval_to_ns(te); - if (t2 > t1) - return t2 - t1; - else - return NSEC_PER_DAY - t2 + t1; + + return __gb_loopback_calc_latency(t1, t2); } static int gb_loopback_sink(struct gb_loopback *gb, u32 len) -- cgit v0.10.2 From 4b0ea00caf837160b25482d48d1f7a95ba47d318 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 17 Aug 2015 00:55:07 +0100 Subject: greybus: loopback: graph round-trip time for all threads This patch adds the ability to time the delta between all threads like this t1 = timestmap(); thread1:gb_operation_sync(); thread2:gb_operation_sync(); t2 = timestamp(); In order to enable that behaviour without forcing an undesirable checkpointing scheme this patch introduces a kfifo for each thread to store the raw timestamps and calculate a time difference. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 39375f1..0d2de70 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -36,6 +36,7 @@ struct gb_loopback_device { struct dentry *root; u32 count; + struct kfifo kfifo; struct mutex mutex; struct list_head list; wait_queue_head_t wq; @@ -64,7 +65,8 @@ struct gb_loopback { struct gb_connection *connection; struct dentry *file; - struct kfifo kfifo; + struct kfifo kfifo_lat; + struct kfifo kfifo_ts; struct mutex mutex; struct task_struct *task; struct list_head entry; @@ -75,6 +77,7 @@ struct gb_loopback { struct gb_loopback_stats throughput; struct gb_loopback_stats requests_per_second; + u32 lbid; u32 iteration_count; u64 elapsed_nsecs; u64 elapsed_nsecs_gb; @@ -217,7 +220,8 @@ static void gb_loopback_check_attr(struct gb_loopback_device *gb_dev, "cannot log bytes %u kfifo_depth %u\n", gb_dev->iteration_max, kfifo_depth); } - kfifo_reset_out(&gb->kfifo); + kfifo_reset_out(&gb->kfifo_lat); + kfifo_reset_out(&gb->kfifo_ts); mutex_unlock(&gb->mutex); } @@ -225,6 +229,7 @@ static void gb_loopback_check_attr(struct gb_loopback_device *gb_dev, case GB_LOOPBACK_TYPE_PING: case GB_LOOPBACK_TYPE_TRANSFER: case GB_LOOPBACK_TYPE_SINK: + kfifo_reset_out(&gb_dev->kfifo); gb_loopback_reset_stats(gb_dev); wake_up(&gb_dev->wq); break; @@ -310,6 +315,13 @@ static u64 gb_loopback_calc_latency(struct timeval *ts, struct timeval *te) return __gb_loopback_calc_latency(t1, t2); } +static void gb_loopback_push_latency_ts(struct gb_loopback *gb, + struct timeval *ts, struct timeval *te) +{ + kfifo_in(&gb->kfifo_ts, (unsigned char *)ts, sizeof(*ts)); + kfifo_in(&gb->kfifo_ts, (unsigned char *)te, sizeof(*te)); +} + static int gb_loopback_sink(struct gb_loopback *gb, u32 len) { struct timeval ts, te; @@ -329,6 +341,7 @@ static int gb_loopback_sink(struct gb_loopback *gb, u32 len) do_gettimeofday(&te); /* Calculate the total time the message took */ + gb_loopback_push_latency_ts(gb, &ts, &te); gb->elapsed_nsecs = gb_loopback_calc_latency(&ts, &te); /* Calculate non-greybus related component of the latency */ @@ -368,6 +381,7 @@ static int gb_loopback_transfer(struct gb_loopback *gb, u32 len) do_gettimeofday(&te); /* Calculate the total time the message took */ + gb_loopback_push_latency_ts(gb, &ts, &te); gb->elapsed_nsecs = gb_loopback_calc_latency(&ts, &te); /* Calculate non-greybus related component of the latency */ @@ -401,6 +415,7 @@ static int gb_loopback_ping(struct gb_loopback *gb) do_gettimeofday(&te); /* Calculate the total time the message took */ + gb_loopback_push_latency_ts(gb, &ts, &te); gb->elapsed_nsecs = gb_loopback_calc_latency(&ts, &te); /* Calculate non-greybus related component of the latency */ @@ -541,6 +556,59 @@ static void gb_loopback_throughput_update(struct gb_loopback *gb, u32 latency) gb_loopback_update_stats(&gb->throughput, throughput); } +static int gb_loopback_calculate_aggregate_stats(void) +{ + struct gb_loopback *gb; + struct timeval ts; + struct timeval te; + u64 t1, t2; + u64 ts_min; + u64 te_max; + u64 elapsed_nsecs; + u32 lat; + int i, latched; + int rollover = 0; + + for (i = 0; i < gb_dev.iteration_max; i++) { + latched = 0; + ts_min = 0; + te_max = 0; + list_for_each_entry(gb, &gb_dev.list, entry) { + if (kfifo_out(&gb->kfifo_ts, &ts, sizeof(ts)) < sizeof(ts)) + goto error; + if (kfifo_out(&gb->kfifo_ts, &te, sizeof(te)) < sizeof(te)) + goto error; + t1 = timeval_to_ns(&ts); + t2 = timeval_to_ns(&te); + + /* minimum timestamp is always what we want */ + if (latched == 0 || t1 < ts_min) + ts_min = t1; + + /* maximum timestamp needs to handle rollover */ + if (t2 > t1) { + if (latched == 0 || t2 > te_max) + te_max = t2; + } else { + if (latched == 0 || rollover == 0) + te_max = t2; + if (rollover == 1 && t2 > te_max) + te_max = t2; + rollover = 1; + } + latched = 1; + } + /* Calculate the aggregate timestamp */ + elapsed_nsecs = __gb_loopback_calc_latency(ts_min, te_max); + lat = gb_loopback_nsec_to_usec_latency(elapsed_nsecs); + kfifo_in(&gb_dev.kfifo, (unsigned char *)&lat, sizeof(lat)); + } + return 0; +error: + kfifo_reset_out(&gb_dev.kfifo); + return -ENOMEM; +} + static void gb_loopback_calculate_stats(struct gb_loopback *gb) { u32 lat; @@ -554,7 +622,7 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb) gb_loopback_update_stats(&gb->latency, lat); /* Raw latency log on a per thread basis */ - kfifo_in(&gb->kfifo, (unsigned char *)&lat, sizeof(lat)); + kfifo_in(&gb->kfifo_lat, (unsigned char *)&lat, sizeof(lat)); /* Log throughput and requests using latency as benchmark */ gb_loopback_throughput_update(gb, lat); @@ -600,6 +668,7 @@ static int gb_loopback_fn(void *data) } /* Optionally terminate */ if (gb_dev.iteration_count == gb_dev.iteration_max) { + gb_loopback_calculate_aggregate_stats(); gb_dev.type = 0; mutex_unlock(&gb_dev.mutex); continue; @@ -645,28 +714,37 @@ sleep: return 0; } -static int gb_loopback_dbgfs_latency_show(struct seq_file *s, void *unused) +static int gb_loopback_dbgfs_latency_show_common(struct seq_file *s, + struct kfifo *kfifo, + struct mutex *mutex) { - struct gb_loopback *gb = s->private; u32 latency; int retval; - if (kfifo_len(&gb->kfifo) == 0) { + if (kfifo_len(kfifo) == 0) { retval = -EAGAIN; goto done; } - mutex_lock(&gb->mutex); - retval = kfifo_out(&gb->kfifo, &latency, sizeof(latency)); + mutex_lock(mutex); + retval = kfifo_out(kfifo, &latency, sizeof(latency)); if (retval > 0) { seq_printf(s, "%u", latency); retval = 0; } - mutex_unlock(&gb->mutex); + mutex_unlock(mutex); done: return retval; } +static int gb_loopback_dbgfs_latency_show(struct seq_file *s, void *unused) +{ + struct gb_loopback *gb = s->private; + + return gb_loopback_dbgfs_latency_show_common(s, &gb->kfifo_lat, + &gb->mutex); +} + static int gb_loopback_latency_open(struct inode *inode, struct file *file) { return single_open(file, gb_loopback_dbgfs_latency_show, @@ -717,18 +795,24 @@ static int gb_loopback_connection_init(struct gb_connection *connection) mutex_unlock(&gb_dev.mutex); /* Allocate kfifo */ - if (kfifo_alloc(&gb->kfifo, kfifo_depth * sizeof(u32), + if (kfifo_alloc(&gb->kfifo_lat, kfifo_depth * sizeof(u32), GFP_KERNEL)) { retval = -ENOMEM; goto out_sysfs; } + if (kfifo_alloc(&gb->kfifo_ts, kfifo_depth * sizeof(struct timeval) * 2, + GFP_KERNEL)) { + retval = -ENOMEM; + goto out_kfifo0; + } /* Fork worker thread */ mutex_init(&gb->mutex); + gb->lbid = 1 << gb_dev.count; gb->task = kthread_run(gb_loopback_fn, gb, "gb_loopback"); if (IS_ERR(gb->task)) { retval = PTR_ERR(gb->task); - goto out_kfifo; + goto out_kfifo1; } mutex_lock(&gb_dev.mutex); @@ -737,8 +821,10 @@ static int gb_loopback_connection_init(struct gb_connection *connection) gb_dev.count++; return 0; -out_kfifo: - kfifo_free(&gb->kfifo); +out_kfifo1: + kfifo_free(&gb->kfifo_ts); +out_kfifo0: + kfifo_free(&gb->kfifo_lat); out_sysfs: sysfs_remove_groups(&connection->dev.kobj, loopback_groups); out_debugfs: @@ -758,7 +844,8 @@ static void gb_loopback_connection_exit(struct gb_connection *connection) if (!IS_ERR_OR_NULL(gb->task)) kthread_stop(gb->task); - kfifo_free(&gb->kfifo); + kfifo_free(&gb->kfifo_lat); + kfifo_free(&gb->kfifo_ts); sysfs_remove_groups(&connection->dev.kobj, loopback_groups); debugfs_remove(gb->file); kfree(gb); @@ -774,20 +861,58 @@ static struct gb_protocol loopback_protocol = { .request_recv = gb_loopback_request_recv, }; +static int gb_loopback_dbgfs_dev_latency_show(struct seq_file *s, void *unused) +{ + struct gb_loopback_device *gb_dev = s->private; + + return gb_loopback_dbgfs_latency_show_common(s, &gb_dev->kfifo, + &gb_dev->mutex); +} + +static int gb_loopback_dev_latency_open(struct inode *inode, struct file *file) +{ + return single_open(file, gb_loopback_dbgfs_dev_latency_show, + inode->i_private); +} + +static const struct file_operations gb_loopback_debugfs_dev_latency_ops = { + .open = gb_loopback_dev_latency_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static int loopback_init(void) { + int retval; + init_waitqueue_head(&gb_dev.wq); INIT_LIST_HEAD(&gb_dev.list); mutex_init(&gb_dev.mutex); gb_dev.root = debugfs_create_dir("gb_loopback", NULL); - return gb_protocol_register(&loopback_protocol); + if (kfifo_alloc(&gb_dev.kfifo, kfifo_depth * sizeof(u32), GFP_KERNEL)) { + retval = -ENOMEM; + goto error_debugfs; + } + + debugfs_create_file("aggregate_latency", S_IFREG | S_IRUGO, + gb_dev.root, &gb_dev, + &gb_loopback_debugfs_dev_latency_ops); + retval = gb_protocol_register(&loopback_protocol); + if (!retval) + return retval; + +error_debugfs: + debugfs_remove_recursive(gb_dev.root); + return retval; } module_init(loopback_init); static void __exit loopback_exit(void) { debugfs_remove_recursive(gb_dev.root); + kfifo_free(&gb_dev.kfifo); gb_protocol_deregister(&loopback_protocol); } module_exit(loopback_exit); -- cgit v0.10.2 From 84cfad02b7d9ee0ec910a40aa96850c337a0d745 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 17 Aug 2015 00:55:08 +0100 Subject: greybus: loopback: add bitmask of connections to include in test Feature add which enables the ability to select a bit-mask of connections to run when executing a loopback test set. This is a feature add to facilitate testing on the firmware side minus the necessity to recompile firmware to support unicast (v) multicast (v) bitmask. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 0d2de70..b362635 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -42,6 +42,7 @@ struct gb_loopback_device { wait_queue_head_t wq; int type; + u32 mask; u32 size; u32 iteration_max; u32 iteration_count; @@ -267,6 +268,8 @@ gb_dev_loopback_rw_attr(ms_wait, d); gb_dev_loopback_rw_attr(iteration_max, u); /* The current index of the for (i = 0; i < iteration_max; i++) loop */ gb_dev_loopback_ro_attr(iteration_count); +/* A bit-mask of destination connecitons to include in the test run */ +gb_dev_loopback_rw_attr(mask, u); #define dev_stats_attrs(name) \ &dev_attr_##name##_min.attr, \ @@ -283,6 +286,7 @@ static struct attribute *loopback_attrs[] = { &dev_attr_ms_wait.attr, &dev_attr_iteration_count.attr, &dev_attr_iteration_max.attr, + &dev_attr_mask.attr, &dev_attr_error.attr, NULL, }; @@ -322,6 +326,11 @@ static void gb_loopback_push_latency_ts(struct gb_loopback *gb, kfifo_in(&gb->kfifo_ts, (unsigned char *)te, sizeof(*te)); } +static int gb_loopback_active(struct gb_loopback *gb) +{ + return (gb_dev.mask == 0 || (gb_dev.mask & gb->lbid)); +} + static int gb_loopback_sink(struct gb_loopback *gb, u32 len) { struct timeval ts, te; @@ -574,6 +583,8 @@ static int gb_loopback_calculate_aggregate_stats(void) ts_min = 0; te_max = 0; list_for_each_entry(gb, &gb_dev.list, entry) { + if (!gb_loopback_active(gb)) + continue; if (kfifo_out(&gb->kfifo_ts, &ts, sizeof(ts)) < sizeof(ts)) goto error; if (kfifo_out(&gb->kfifo_ts, &te, sizeof(te)) < sizeof(te)) @@ -653,10 +664,14 @@ static int gb_loopback_fn(void *data) break; mutex_lock(&gb_dev.mutex); + if (!gb_loopback_active(gb)) + goto unlock_continue; if (gb_dev.iteration_max) { /* Determine overall lowest count */ low_count = gb->iteration_count; list_for_each_entry(gb_list, &gb_dev.list, entry) { + if (!gb_loopback_active(gb_list)) + continue; if (gb_list->iteration_count < low_count) low_count = gb_list->iteration_count; } @@ -670,8 +685,7 @@ static int gb_loopback_fn(void *data) if (gb_dev.iteration_count == gb_dev.iteration_max) { gb_loopback_calculate_aggregate_stats(); gb_dev.type = 0; - mutex_unlock(&gb_dev.mutex); - continue; + goto unlock_continue; } } size = gb_dev.size; @@ -706,6 +720,7 @@ static int gb_loopback_fn(void *data) gb->iteration_count++; mutex_unlock(&gb->mutex); +unlock_continue: mutex_unlock(&gb_dev.mutex); sleep: if (ms_wait) -- cgit v0.10.2 From 42b9da5efe63e42298094a23edf00d2e0830812c Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 17 Aug 2015 00:55:09 +0100 Subject: greybus: loopback: initialized ms_wait negate warning ms_wait = 0; caught by a compiler warning. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index b362635..ff2e792 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -649,7 +649,7 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb) static int gb_loopback_fn(void *data) { int error = 0; - int ms_wait; + int ms_wait = 0; int type; u32 size; u32 low_count; -- cgit v0.10.2 From a5a0ba4318aafaa0686893ba62b2ab34598d88c7 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 17 Aug 2015 00:55:10 +0100 Subject: greybus: loopback: remove checkpatch error causing macro checkpatch.pl is choking on a later change to dev_stats_attrs, where checkpatch expects to see the values encapsulated in curly brackets. Encapsulating in curly brackets will cause a compiler error. To resolve the dichotomy this patch drops the macros and adds the arrary declarations directly. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index ff2e792..0a9bc91 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -271,16 +271,19 @@ gb_dev_loopback_ro_attr(iteration_count); /* A bit-mask of destination connecitons to include in the test run */ gb_dev_loopback_rw_attr(mask, u); -#define dev_stats_attrs(name) \ - &dev_attr_##name##_min.attr, \ - &dev_attr_##name##_max.attr, \ - &dev_attr_##name##_avg.attr - static struct attribute *loopback_attrs[] = { - dev_stats_attrs(latency), - dev_stats_attrs(latency_gb), - dev_stats_attrs(requests_per_second), - dev_stats_attrs(throughput), + &dev_attr_latency_min.attr, + &dev_attr_latency_max.attr, + &dev_attr_latency_avg.attr, + &dev_attr_latency_gb_min.attr, + &dev_attr_latency_gb_max.attr, + &dev_attr_latency_gb_avg.attr, + &dev_attr_requests_per_second_min.attr, + &dev_attr_requests_per_second_max.attr, + &dev_attr_requests_per_second_avg.attr, + &dev_attr_throughput_min.attr, + &dev_attr_throughput_max.attr, + &dev_attr_throughput_avg.attr, &dev_attr_type.attr, &dev_attr_size.attr, &dev_attr_ms_wait.attr, -- cgit v0.10.2 From f06272b283e15951bae9b9af24cff74b7fcabaef Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 17 Aug 2015 00:55:11 +0100 Subject: greybus: loopback: add module level sys/debug fs data points Code this far has used the first connection's sysfs entry to present variables intended to control the entire test - across multiple connections. This patch changes that so that the module level variables only appear at the end0:x level in sysfs. Example: Total counts for errors over the entire set of connections will be here /sys/bus/greybus/devices/endo0:x/error_dev In contrast an error for each connection will be presented like this /sys/bus/greybus/devices/endo0:x:y:z:w/error_con x = y = z = w = Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 0a9bc91..01bed43 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -96,47 +96,68 @@ module_param(kfifo_depth, uint, 0444); #define GB_LOOPBACK_MS_WAIT_MAX 1000 /* interface sysfs attributes */ -#define gb_loopback_ro_attr(field) \ -static ssize_t field##_show(struct device *dev, \ +#define gb_loopback_ro_attr(field, pfx, conn) \ +static ssize_t field##_##pfx##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ - struct gb_connection *connection = to_gb_connection(dev); \ - struct gb_loopback *gb = connection->private; \ - return sprintf(buf, "%u\n", gb->field); \ + struct gb_connection *connection; \ + struct gb_loopback *gb; \ + if (conn) { \ + connection = to_gb_connection(dev); \ + gb = connection->private; \ + return sprintf(buf, "%u\n", gb->field); \ + } else { \ + return sprintf(buf, "%u\n", gb_dev.field); \ + } \ } \ -static DEVICE_ATTR_RO(field) +static DEVICE_ATTR_RO(field##_##pfx) -#define gb_loopback_ro_stats_attr(name, field, type) \ -static ssize_t name##_##field##_show(struct device *dev, \ +#define gb_loopback_ro_stats_attr(name, field, type, pfx, conn) \ +static ssize_t name##_##field##_##pfx##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ - struct gb_connection *connection = to_gb_connection(dev); \ - struct gb_loopback *gb = connection->private; \ - return sprintf(buf, "%"#type"\n", gb->name.field); \ + struct gb_connection *connection; \ + struct gb_loopback *gb; \ + if (conn) { \ + connection = to_gb_connection(dev); \ + gb = connection->private; \ + return sprintf(buf, "%"#type"\n", gb->name.field); \ + } else { \ + return sprintf(buf, "%"#type"\n", gb_dev.name.field); \ + } \ } \ -static DEVICE_ATTR_RO(name##_##field) +static DEVICE_ATTR_RO(name##_##field##_##pfx) -#define gb_loopback_ro_avg_attr(name) \ -static ssize_t name##_avg_show(struct device *dev, \ +#define gb_loopback_ro_avg_attr(name, pfx, conn) \ +static ssize_t name##_avg_##pfx##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ - struct gb_connection *connection = to_gb_connection(dev); \ - struct gb_loopback *gb = connection->private; \ - struct gb_loopback_stats *stats = &gb->name; \ - u32 count = stats->count ? stats->count : 1; \ - u64 avg = stats->sum + count / 2; /* round closest */ \ - u32 rem = do_div(avg, count); \ + struct gb_loopback_stats *stats; \ + struct gb_connection *connection; \ + struct gb_loopback *gb; \ + u64 avg; \ + u32 count, rem; \ + if (conn) { \ + connection = to_gb_connection(dev); \ + gb = connection->private; \ + stats = &gb->name; \ + } else { \ + stats = &gb_dev.name; \ + } \ + count = stats->count ? stats->count : 1; \ + avg = stats->sum + count / 2; /* round closest */ \ + rem = do_div(avg, count); \ return sprintf(buf, "%llu.%06u\n", avg, 1000000 * rem / count); \ } \ -static DEVICE_ATTR_RO(name##_avg) +static DEVICE_ATTR_RO(name##_avg_##pfx) -#define gb_loopback_stats_attrs(field) \ - gb_loopback_ro_stats_attr(field, min, u); \ - gb_loopback_ro_stats_attr(field, max, u); \ - gb_loopback_ro_avg_attr(field); +#define gb_loopback_stats_attrs(field, pfx, conn) \ + gb_loopback_ro_stats_attr(field, min, u, pfx, conn); \ + gb_loopback_ro_stats_attr(field, max, u, pfx, conn); \ + gb_loopback_ro_avg_attr(field, pfx, conn) #define gb_loopback_attr(field, type) \ static ssize_t field##_show(struct device *dev, \ @@ -165,8 +186,8 @@ static ssize_t field##_store(struct device *dev, \ } \ static DEVICE_ATTR_RW(field) -#define gb_dev_loopback_ro_attr(field) \ -static ssize_t field##_show(struct device *dev, \ +#define gb_dev_loopback_ro_attr(field, conn) \ +static ssize_t field##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ @@ -241,15 +262,20 @@ static void gb_loopback_check_attr(struct gb_loopback_device *gb_dev, } /* Time to send and receive one message */ -gb_loopback_stats_attrs(latency); +gb_loopback_stats_attrs(latency, dev, false); +gb_loopback_stats_attrs(latency, con, true); /* Time to send and receive one message not including greybus */ -gb_loopback_stats_attrs(latency_gb); +gb_loopback_stats_attrs(latency_gb, dev, false); +gb_loopback_stats_attrs(latency_gb, con, true); /* Number of requests sent per second on this cport */ -gb_loopback_stats_attrs(requests_per_second); +gb_loopback_stats_attrs(requests_per_second, dev, false); +gb_loopback_stats_attrs(requests_per_second, con, true); /* Quantity of data sent and received on this cport */ -gb_loopback_stats_attrs(throughput); +gb_loopback_stats_attrs(throughput, dev, false); +gb_loopback_stats_attrs(throughput, con, true); /* Number of errors encountered during loop */ -gb_loopback_ro_attr(error); +gb_loopback_ro_attr(error, dev, false); +gb_loopback_ro_attr(error, con, true); /* * Type of loopback message to send based on protocol type definitions @@ -267,33 +293,51 @@ gb_dev_loopback_rw_attr(ms_wait, d); /* Maximum iterations for a given operation: 1-(2^32-1), 0 implies infinite */ gb_dev_loopback_rw_attr(iteration_max, u); /* The current index of the for (i = 0; i < iteration_max; i++) loop */ -gb_dev_loopback_ro_attr(iteration_count); +gb_dev_loopback_ro_attr(iteration_count, false); /* A bit-mask of destination connecitons to include in the test run */ gb_dev_loopback_rw_attr(mask, u); -static struct attribute *loopback_attrs[] = { - &dev_attr_latency_min.attr, - &dev_attr_latency_max.attr, - &dev_attr_latency_avg.attr, - &dev_attr_latency_gb_min.attr, - &dev_attr_latency_gb_max.attr, - &dev_attr_latency_gb_avg.attr, - &dev_attr_requests_per_second_min.attr, - &dev_attr_requests_per_second_max.attr, - &dev_attr_requests_per_second_avg.attr, - &dev_attr_throughput_min.attr, - &dev_attr_throughput_max.attr, - &dev_attr_throughput_avg.attr, +static struct attribute *loopback_dev_attrs[] = { + &dev_attr_latency_min_dev.attr, + &dev_attr_latency_max_dev.attr, + &dev_attr_latency_avg_dev.attr, + &dev_attr_latency_gb_min_dev.attr, + &dev_attr_latency_gb_max_dev.attr, + &dev_attr_latency_gb_avg_dev.attr, + &dev_attr_requests_per_second_min_dev.attr, + &dev_attr_requests_per_second_max_dev.attr, + &dev_attr_requests_per_second_avg_dev.attr, + &dev_attr_throughput_min_dev.attr, + &dev_attr_throughput_max_dev.attr, + &dev_attr_throughput_avg_dev.attr, &dev_attr_type.attr, &dev_attr_size.attr, &dev_attr_ms_wait.attr, &dev_attr_iteration_count.attr, &dev_attr_iteration_max.attr, &dev_attr_mask.attr, - &dev_attr_error.attr, + &dev_attr_error_dev.attr, NULL, }; -ATTRIBUTE_GROUPS(loopback); +ATTRIBUTE_GROUPS(loopback_dev); + +static struct attribute *loopback_con_attrs[] = { + &dev_attr_latency_min_con.attr, + &dev_attr_latency_max_con.attr, + &dev_attr_latency_avg_con.attr, + &dev_attr_latency_gb_min_con.attr, + &dev_attr_latency_gb_max_con.attr, + &dev_attr_latency_gb_avg_con.attr, + &dev_attr_requests_per_second_min_con.attr, + &dev_attr_requests_per_second_max_con.attr, + &dev_attr_requests_per_second_avg_con.attr, + &dev_attr_throughput_min_con.attr, + &dev_attr_throughput_max_con.attr, + &dev_attr_throughput_avg_con.attr, + &dev_attr_error_con.attr, + NULL, +}; +ATTRIBUTE_GROUPS(loopback_con); static u32 gb_loopback_nsec_to_usec_latency(u64 elapsed_nsecs) { @@ -776,6 +820,27 @@ static const struct file_operations gb_loopback_debugfs_latency_ops = { .release = single_release, }; +static int gb_loopback_dbgfs_dev_latency_show(struct seq_file *s, void *unused) +{ + struct gb_loopback_device *gb_dev = s->private; + + return gb_loopback_dbgfs_latency_show_common(s, &gb_dev->kfifo, + &gb_dev->mutex); +} + +static int gb_loopback_dev_latency_open(struct inode *inode, struct file *file) +{ + return single_open(file, gb_loopback_dbgfs_dev_latency_show, + inode->i_private); +} + +static const struct file_operations gb_loopback_debugfs_dev_latency_ops = { + .open = gb_loopback_dev_latency_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + #define DEBUGFS_NAMELEN 32 static int gb_loopback_connection_init(struct gb_connection *connection) @@ -783,12 +848,39 @@ static int gb_loopback_connection_init(struct gb_connection *connection) struct gb_loopback *gb; int retval; char name[DEBUGFS_NAMELEN]; + struct kobject *kobj = &connection->bundle->intf->module->dev.kobj; gb = kzalloc(sizeof(*gb), GFP_KERNEL); if (!gb) return -ENOMEM; gb_loopback_reset_stats(&gb_dev); + /* If this is the first connection - create a module endo0:x entries */ + mutex_lock(&gb_dev.mutex); + if (!gb_dev.count) { + snprintf(name, sizeof(name), "raw_latency_endo0:%d", + connection->bundle->intf->module->module_id); + debugfs_create_file(name, S_IFREG | S_IRUGO, + gb_dev.root, &gb_dev, + &gb_loopback_debugfs_dev_latency_ops); + retval = sysfs_create_groups(kobj, loopback_dev_groups); + if (retval) { + mutex_unlock(&gb_dev.mutex); + goto out_sysfs; + } + /* Calculate maximum payload */ + gb_dev.size_max = gb_operation_get_payload_size_max(connection); + if (gb_dev.size_max <= + sizeof(struct gb_loopback_transfer_request)) { + retval = -EINVAL; + mutex_unlock(&gb_dev.mutex); + goto out_sysfs; + } + gb_dev.size_max -= sizeof(struct gb_loopback_transfer_request); + } + mutex_unlock(&gb_dev.mutex); + + /* Create per-connection sysfs and debugfs data-points */ snprintf(name, sizeof(name), "raw_latency_endo0:%d:%d:%d:%d", connection->bundle->intf->module->module_id, connection->bundle->intf->interface_id, @@ -798,25 +890,16 @@ static int gb_loopback_connection_init(struct gb_connection *connection) &gb_loopback_debugfs_latency_ops); gb->connection = connection; connection->private = gb; - retval = sysfs_create_groups(&connection->dev.kobj, loopback_groups); + retval = sysfs_create_groups(&connection->dev.kobj, + loopback_con_groups); if (retval) - goto out_debugfs; - - /* Calculate maximum payload */ - mutex_lock(&gb_dev.mutex); - gb_dev.size_max = gb_operation_get_payload_size_max(connection); - if (gb_dev.size_max <= sizeof(struct gb_loopback_transfer_request)) { - retval = -EINVAL; - goto out_sysfs; - } - gb_dev.size_max -= sizeof(struct gb_loopback_transfer_request); - mutex_unlock(&gb_dev.mutex); + goto out_sysfs_dev; /* Allocate kfifo */ if (kfifo_alloc(&gb->kfifo_lat, kfifo_depth * sizeof(u32), GFP_KERNEL)) { retval = -ENOMEM; - goto out_sysfs; + goto out_sysfs_conn; } if (kfifo_alloc(&gb->kfifo_ts, kfifo_depth * sizeof(struct timeval) * 2, GFP_KERNEL)) { @@ -843,11 +926,14 @@ out_kfifo1: kfifo_free(&gb->kfifo_ts); out_kfifo0: kfifo_free(&gb->kfifo_lat); -out_sysfs: - sysfs_remove_groups(&connection->dev.kobj, loopback_groups); -out_debugfs: +out_sysfs_conn: + sysfs_remove_groups(&connection->dev.kobj, loopback_con_groups); +out_sysfs_dev: + if (!gb_dev.count) + sysfs_remove_groups(kobj, loopback_dev_groups); debugfs_remove(gb->file); connection->private = NULL; +out_sysfs: kfree(gb); return retval; @@ -856,6 +942,7 @@ out_debugfs: static void gb_loopback_connection_exit(struct gb_connection *connection) { struct gb_loopback *gb = connection->private; + struct kobject *kobj = &connection->bundle->intf->module->dev.kobj; gb_dev.count--; connection->private = NULL; @@ -864,7 +951,9 @@ static void gb_loopback_connection_exit(struct gb_connection *connection) kfifo_free(&gb->kfifo_lat); kfifo_free(&gb->kfifo_ts); - sysfs_remove_groups(&connection->dev.kobj, loopback_groups); + if (!gb_dev.count) + sysfs_remove_groups(kobj, loopback_dev_groups); + sysfs_remove_groups(&connection->dev.kobj, loopback_con_groups); debugfs_remove(gb->file); kfree(gb); } @@ -879,27 +968,6 @@ static struct gb_protocol loopback_protocol = { .request_recv = gb_loopback_request_recv, }; -static int gb_loopback_dbgfs_dev_latency_show(struct seq_file *s, void *unused) -{ - struct gb_loopback_device *gb_dev = s->private; - - return gb_loopback_dbgfs_latency_show_common(s, &gb_dev->kfifo, - &gb_dev->mutex); -} - -static int gb_loopback_dev_latency_open(struct inode *inode, struct file *file) -{ - return single_open(file, gb_loopback_dbgfs_dev_latency_show, - inode->i_private); -} - -static const struct file_operations gb_loopback_debugfs_dev_latency_ops = { - .open = gb_loopback_dev_latency_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - static int loopback_init(void) { int retval; @@ -914,9 +982,6 @@ static int loopback_init(void) goto error_debugfs; } - debugfs_create_file("aggregate_latency", S_IFREG | S_IRUGO, - gb_dev.root, &gb_dev, - &gb_loopback_debugfs_dev_latency_ops); retval = gb_protocol_register(&loopback_protocol); if (!retval) return retval; -- cgit v0.10.2 From 98676ca83680a2ca6afb38e900b3d956f6917185 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 17 Aug 2015 00:55:12 +0100 Subject: greybus: loopback: fix typo in comment Alex previously post a patch to fix this typo. Somehow it fell through the cracks in the meantime. Do it again 'stastic' is a word 'statistic' is not. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 01bed43..8dd648c 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -675,7 +675,7 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb) /* Express latency in terms of microseconds */ lat = gb_loopback_nsec_to_usec_latency(gb->elapsed_nsecs); - /* Log latency statistic */ + /* Log latency stastic */ gb_loopback_update_stats(&gb_dev.latency, lat); gb_loopback_update_stats(&gb->latency, lat); -- cgit v0.10.2 From 977e209ab41073def3cf0e1034c429a832ba54df Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Mon, 31 Aug 2015 09:00:16 +0200 Subject: greybus: es1/es2: set transfer flag to send a zero-length packet Greybus messages with a multiple size of 512B generate timeouts (any other message size doesn't). 512B is exactly the packet size of a bulk out endpoint. Hence USB device is expecting a short (< 512B) or zero-length packet to finish the transfer, which is never generated and causes the timeout. Set the transfer flag to send a zero-length packet in this situation. Signed-off-by: Alexandre Bailon Reviewed-by: Patrick Titiano Reviewed-by: Johan Hovold Signed-off-by: Johan Hovold diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 2aa2717..ddc26de 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -216,6 +216,7 @@ static int message_send(struct greybus_host_device *hd, u16 cport_id, usb_sndbulkpipe(udev, es1->cport_out_endpoint), message->buffer, buffer_size, cport_out_callback, message); + urb->transfer_flags |= URB_ZERO_PACKET; gb_connection_push_timestamp(message->operation->connection); retval = usb_submit_urb(urb, gfp_mask); if (retval) { diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 008685b..295cc68 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -312,6 +312,7 @@ static int message_send(struct greybus_host_device *hd, u16 cport_id, es1->cport_out[bulk_ep_set].endpoint), message->buffer, buffer_size, cport_out_callback, message); + urb->transfer_flags |= URB_ZERO_PACKET; gb_connection_push_timestamp(message->operation->connection); retval = usb_submit_urb(urb, gfp_mask); if (retval) { -- cgit v0.10.2 From af0b4d5a19e3d49059afe91307fce980291f43f9 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 28 Aug 2015 11:58:24 +0200 Subject: greybus: firmware: fix potential stack corruption Use snprintf when generating the firmware name to avoid stack corruption if the fixed-size buffer overflows. Note that the current buffer size appears to expect 16-bit ids while the they are actually 32-bit, something which could trigger the corruption. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar diff --git a/drivers/staging/greybus/firmware.c b/drivers/staging/greybus/firmware.c index 13efaab..e888b7a 100644 --- a/drivers/staging/greybus/firmware.c +++ b/drivers/staging/greybus/firmware.c @@ -38,9 +38,10 @@ static int download_firmware(struct gb_firmware *firmware, u8 stage) * * XXX Name it properly.. */ - sprintf(firmware_name, "ara:%04x:%04x:%04x:%04x:%04x.fw", intf->unipro_mfg_id, - intf->unipro_prod_id, intf->ara_vend_id, intf->ara_prod_id, - stage); + snprintf(firmware_name, sizeof(firmware_name), + "ara:%04x:%04x:%04x:%04x:%04x.fw", + intf->unipro_mfg_id, intf->unipro_prod_id, + intf->ara_vend_id, intf->ara_prod_id, stage); return request_firmware(&firmware->fw, firmware_name, &connection->dev); } -- cgit v0.10.2 From 2d465d57c8bbb0da96f352447e283e06bfa8513c Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Thu, 20 Aug 2015 15:20:17 +0100 Subject: greybus: sdio: fix command type defines Broadcast command with response and without response where swapped related to what is defined in greybus specification. Make it coherent with the document. Signed-off-by: Rui Miguel Silva Signed-off-by: Johan Hovold diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 0c11bec..b84c710 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -1031,8 +1031,8 @@ struct gb_sdio_command_request { __u8 cmd_type; #define GB_SDIO_CMD_AC 0x00 #define GB_SDIO_CMD_ADTC 0x01 -#define GB_SDIO_CMD_BCR 0x02 -#define GB_SDIO_CMD_BC 0x03 +#define GB_SDIO_CMD_BC 0x02 +#define GB_SDIO_CMD_BCR 0x03 __le32 cmd_arg; } __packed; -- cgit v0.10.2 From c01c77ce4b2a7a39134d90f90ab964926ef88123 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 1 Sep 2015 12:25:24 +0200 Subject: greybus: endo: fix endo-id allocation flag Use GFP_KERNEL for endo ida allocation in gb_endo_register, which is not called from atomic context. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c index baa4aa5..84d695d 100644 --- a/drivers/staging/greybus/endo.c +++ b/drivers/staging/greybus/endo.c @@ -439,7 +439,7 @@ static int gb_endo_register(struct greybus_host_device *hd, { int retval; - retval = ida_simple_get(&greybus_endo_id_map, 0, 0, GFP_ATOMIC); + retval = ida_simple_get(&greybus_endo_id_map, 0, 0, GFP_KERNEL); if (retval < 0) return retval; -- cgit v0.10.2 From 89f637f716a90ec9da7a26d53ad883ea2b806e66 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 1 Sep 2015 12:25:25 +0200 Subject: greybus: svc: fix device-id allocation flag Use GFP_KERNEL for device-id allocation in svc_process_hotplug, which is called from a work queue. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 452f81b..029b5a7 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -304,7 +304,7 @@ static void svc_process_hotplug(struct work_struct *work) * XXX about an AP with multiple interface blocks? */ device_id = ida_simple_get(&greybus_svc_device_id_map, - GB_DEVICE_ID_MODULES_START, 0, GFP_ATOMIC); + GB_DEVICE_ID_MODULES_START, 0, GFP_KERNEL); if (device_id < 0) { ret = device_id; dev_err(dev, "%s: Failed to allocate device id for interface with id %hhu (%d)\n", -- cgit v0.10.2 From 287bba82fe2f74dd89f7f24f2da438a7974e57af Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 1 Sep 2015 12:25:26 +0200 Subject: greybus: svc: fix hot-plug-state allocation flag Use GFP_KERNEL for hot-plug state allocation in gb_svc_intf_hotplug_recv, which is called from a request handler (i.e. a work queue). Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 029b5a7..db00922 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -382,7 +382,7 @@ static int gb_svc_intf_hotplug_recv(struct gb_operation *op) return -EINVAL; } - svc_hotplug = kmalloc(sizeof(*svc_hotplug), GFP_ATOMIC); + svc_hotplug = kmalloc(sizeof(*svc_hotplug), GFP_KERNEL); if (!svc_hotplug) return -ENOMEM; -- cgit v0.10.2 From 505c9d27b804f2b1e1e6432a89876df197432bbe Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 1 Sep 2015 12:25:27 +0200 Subject: greybus: interface: fix potential attribute-buffer overflow Use scnprintf in the generic attribute helper, which does not currently check for buffer overflow. The attribute helper is used to print generic strings, which could potentially overflow the buffer. Note that the only strings currently exported are taken from greybus string descriptors and should therefore be limited to 255 chars. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Reviewed-by: Bryan O'Donoghue diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index c5211a3..0c3613e 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -16,7 +16,7 @@ static ssize_t field##_show(struct device *dev, \ char *buf) \ { \ struct gb_interface *intf = to_gb_interface(dev); \ - return sprintf(buf, "%"#type"\n", intf->field); \ + return scnprintf(buf, PAGE_SIZE, "%"#type"\n", intf->field); \ } \ static DEVICE_ATTR_RO(field) -- cgit v0.10.2 From 2630fbf828ed921bd52cfe1fbacc9ad16aa2f47a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 1 Sep 2015 12:25:28 +0200 Subject: greybus: pwm: replace pr_err with dev_err Replace pr_err with the more descriptive dev_err. Also include the error code on failure to register the PWM chip. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar diff --git a/drivers/staging/greybus/pwm.c b/drivers/staging/greybus/pwm.c index 5f33589..d91905f 100644 --- a/drivers/staging/greybus/pwm.c +++ b/drivers/staging/greybus/pwm.c @@ -204,7 +204,7 @@ static int gb_pwm_connection_init(struct gb_connection *connection) ret = pwmchip_add(pwm); if (ret) { - pr_err("Failed to register PWM\n"); + dev_err(&connection->dev, "failed to register PWM: %d\n", ret); goto out_err; } -- cgit v0.10.2 From b9fb704afd6e2e3c749fc076f1d8fa36ae695d4d Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 1 Sep 2015 17:16:16 +0530 Subject: greybus: svc: get hd directly from connection There is no need to perform connection->bundle->intf->hd as the same can be done with connection->hd. Signed-off-by: Viresh Kumar Signed-off-by: Johan Hovold diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index db00922..ac8ff44 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -272,7 +272,7 @@ static void svc_process_hotplug(struct work_struct *work) struct gb_svc_intf_hotplug_request *hotplug = &svc_hotplug->data; struct gb_connection *connection = svc_hotplug->connection; struct gb_svc *svc = connection->private; - struct greybus_host_device *hd = connection->bundle->intf->hd; + struct greybus_host_device *hd = connection->hd; struct device *dev = &connection->dev; struct gb_interface *intf; u8 intf_id, device_id; @@ -399,7 +399,7 @@ static int gb_svc_intf_hot_unplug_recv(struct gb_operation *op) { struct gb_message *request = op->request; struct gb_svc_intf_hot_unplug_request *hot_unplug = request->payload; - struct greybus_host_device *hd = op->connection->bundle->intf->hd; + struct greybus_host_device *hd = op->connection->hd; struct device *dev = &op->connection->dev; u8 device_id; struct gb_interface *intf; -- cgit v0.10.2 From e074a2e2874aaa96da3e54d98ecb886201d96435 Mon Sep 17 00:00:00 2001 From: Fabien Parent Date: Wed, 2 Sep 2015 15:50:34 +0200 Subject: greybus: es2: rename misnamed CPORT_MAX into CPORT_COUNT Rename the misnamed macro CPORT_MAX into CPORT_COUNT. CPORT_MAX could let people think that the macro is holding the value of the last CPort ID usable. Signed-off-by: Fabien Parent Reviewed-by: Johan Hovold Signed-off-by: Johan Hovold diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 295cc68..6808089 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -34,7 +34,7 @@ static struct task_struct *apb1_log_task; static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); /* Number of cport present on USB bridge */ -#define CPORT_MAX 44 +#define CPORT_COUNT 44 /* Number of bulk in and bulk out couple */ #define NUM_BULKS 7 @@ -108,7 +108,7 @@ struct es1_ap_dev { bool cport_out_urb_cancelled[NUM_CPORT_OUT_URB]; spinlock_t cport_out_urb_lock; - int cport_to_ep[CPORT_MAX]; + int cport_to_ep[CPORT_COUNT]; }; struct cport_to_ep { @@ -128,7 +128,7 @@ static void usb_log_disable(struct es1_ap_dev *es1); static int cport_to_ep(struct es1_ap_dev *es1, u16 cport_id) { - if (cport_id >= CPORT_MAX) + if (cport_id >= CPORT_COUNT) return 0; return es1->cport_to_ep[cport_id]; } @@ -139,7 +139,7 @@ static int ep_in_use(struct es1_ap_dev *es1, int bulk_ep_set) { int i; - for (i = 0; i < CPORT_MAX; i++) { + for (i = 0; i < CPORT_COUNT; i++) { if (es1->cport_to_ep[i] == bulk_ep_set) return 1; } @@ -154,7 +154,7 @@ int map_cport_to_ep(struct es1_ap_dev *es1, if (bulk_ep_set == 0 || bulk_ep_set >= NUM_BULKS) return -EINVAL; - if (cport_id >= CPORT_MAX) + if (cport_id >= CPORT_COUNT) return -EINVAL; if (bulk_ep_set && ep_in_use(es1, bulk_ep_set)) return -EINVAL; -- cgit v0.10.2 From 144670c2ae3f9b452e021a9032b25730d296ba53 Mon Sep 17 00:00:00 2001 From: Fabien Parent Date: Wed, 2 Sep 2015 15:50:35 +0200 Subject: greybus: add num_cports field to greybus hd This commit is doing the preparation work in order to get the number of cports supported from the UniPro IP instead of using a constant defined in a Kconfig file. Greybus host device is now holding the cport count, and all the code will now use this value instead of the constant CPORT_ID_MAX when referring to an AP's CPort ID. Signed-off-by: Fabien Parent [johan: es1 supports 256 cports, minor style changes ] Signed-off-by: Johan Hovold diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 7eb2868..286e7da 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -311,7 +311,7 @@ struct gb_connection *gb_connection_create(struct gb_bundle *bundle, { return gb_connection_create_range(bundle->intf->hd, bundle, &bundle->dev, cport_id, protocol_id, - 0, CPORT_ID_MAX); + 0, bundle->intf->hd->num_cports - 1); } /* diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index af71d02..3ba744b 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -168,7 +168,8 @@ static void free_hd(struct kref *kref) struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver, struct device *parent, - size_t buffer_size_max) + size_t buffer_size_max, + size_t num_cports) { struct greybus_host_device *hd; @@ -186,6 +187,11 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver return NULL; } + if (num_cports == 0 || num_cports > CPORT_ID_MAX) { + dev_err(parent, "Invalid number of CPorts: %zu\n", num_cports); + return ERR_PTR(-EINVAL); + } + /* * Make sure to never allocate messages larger than what the Greybus * protocol supports. @@ -207,6 +213,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver INIT_LIST_HEAD(&hd->connections); ida_init(&hd->cport_id_map); hd->buffer_size_max = buffer_size_max; + hd->num_cports = num_cports; /* * Initialize AP's SVC protocol connection: diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index ddc26de..fc4297a 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -33,6 +33,9 @@ static struct dentry *apb1_log_enable_dentry; static struct task_struct *apb1_log_task; static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); +/* Number of CPorts supported by es1 */ +#define CPORT_COUNT 256 + /* * Number of CPort IN urbs in flight at any point in time. * Adjust if we are having stalls in the USB buffer due to not enough urbs in @@ -193,7 +196,7 @@ static int message_send(struct greybus_host_device *hd, u16 cport_id, * of where the data should be sent. Do one last check of * the target CPort id before filling it in. */ - if (!cport_id_valid(cport_id)) { + if (!cport_id_valid(hd, cport_id)) { pr_err("invalid destination cport 0x%02x\n", cport_id); return -EINVAL; } @@ -372,7 +375,7 @@ static void cport_in_callback(struct urb *urb) header = urb->transfer_buffer; cport_id = gb_message_cport_unpack(header); - if (cport_id_valid(cport_id)) + if (cport_id_valid(hd, cport_id)) greybus_data_rcvd(hd, cport_id, urb->transfer_buffer, urb->actual_length); else @@ -560,7 +563,8 @@ static int ap_probe(struct usb_interface *interface, udev = usb_get_dev(interface_to_usbdev(interface)); - hd = greybus_create_hd(&es1_driver, &udev->dev, ES1_GBUF_MSG_SIZE_MAX); + hd = greybus_create_hd(&es1_driver, &udev->dev, ES1_GBUF_MSG_SIZE_MAX, + CPORT_COUNT); if (IS_ERR(hd)) { usb_put_dev(udev); return PTR_ERR(hd); diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 6808089..4b1f34f 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -128,7 +128,7 @@ static void usb_log_disable(struct es1_ap_dev *es1); static int cport_to_ep(struct es1_ap_dev *es1, u16 cport_id) { - if (cport_id >= CPORT_COUNT) + if (cport_id >= es1->hd->num_cports) return 0; return es1->cport_to_ep[cport_id]; } @@ -139,7 +139,7 @@ static int ep_in_use(struct es1_ap_dev *es1, int bulk_ep_set) { int i; - for (i = 0; i < CPORT_COUNT; i++) { + for (i = 0; i < es1->hd->num_cports; i++) { if (es1->cport_to_ep[i] == bulk_ep_set) return 1; } @@ -154,7 +154,7 @@ int map_cport_to_ep(struct es1_ap_dev *es1, if (bulk_ep_set == 0 || bulk_ep_set >= NUM_BULKS) return -EINVAL; - if (cport_id >= CPORT_COUNT) + if (cport_id >= es1->hd->num_cports) return -EINVAL; if (bulk_ep_set && ep_in_use(es1, bulk_ep_set)) return -EINVAL; @@ -287,7 +287,7 @@ static int message_send(struct greybus_host_device *hd, u16 cport_id, * of where the data should be sent. Do one last check of * the target CPort id before filling it in. */ - if (!cport_id_valid(cport_id)) { + if (!cport_id_valid(hd, cport_id)) { pr_err("invalid destination cport 0x%02x\n", cport_id); return -EINVAL; } @@ -472,7 +472,7 @@ static void cport_in_callback(struct urb *urb) header = urb->transfer_buffer; cport_id = gb_message_cport_unpack(header); - if (cport_id_valid(cport_id)) + if (cport_id_valid(hd, cport_id)) greybus_data_rcvd(hd, cport_id, urb->transfer_buffer, urb->actual_length); else @@ -660,7 +660,8 @@ static int ap_probe(struct usb_interface *interface, udev = usb_get_dev(interface_to_usbdev(interface)); - hd = greybus_create_hd(&es1_driver, &udev->dev, ES1_GBUF_MSG_SIZE_MAX); + hd = greybus_create_hd(&es1_driver, &udev->dev, ES1_GBUF_MSG_SIZE_MAX, + CPORT_COUNT); if (IS_ERR(hd)) { usb_put_dev(udev); return PTR_ERR(hd); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 5726555..27a7724 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -96,6 +96,9 @@ struct greybus_host_device { struct ida cport_id_map; u8 device_id; + /* Number of CPorts supported by the UniPro IP */ + size_t num_cports; + /* Host device buffer constraints */ size_t buffer_size_max; @@ -109,7 +112,8 @@ struct greybus_host_device { struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *hd, struct device *parent, - size_t buffer_size_max); + size_t buffer_size_max, + size_t num_cports); int greybus_endo_setup(struct greybus_host_device *hd, u16 endo_id, u8 ap_intf_id); void greybus_remove_hd(struct greybus_host_device *hd); @@ -191,9 +195,9 @@ static inline int is_gb_connection(const struct device *dev) return dev->type == &greybus_connection_type; } -static inline bool cport_id_valid(u16 cport_id) +static inline bool cport_id_valid(struct greybus_host_device *hd, u16 cport_id) { - return cport_id != CPORT_ID_BAD && cport_id <= CPORT_ID_MAX; + return cport_id != CPORT_ID_BAD && cport_id < hd->num_cports; } #endif /* __KERNEL__ */ diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 0c3613e..c38fb8b 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -84,7 +84,7 @@ int gb_create_bundle_connection(struct gb_interface *intf, u8 class) bundle_id = GB_CONTROL_BUNDLE_ID; cport_id = GB_CONTROL_CPORT_ID; ida_start = 0; - ida_end = CPORT_ID_MAX; + ida_end = intf->hd->num_cports - 1; } else if (class == GREYBUS_CLASS_SVC) { protocol_id = GREYBUS_PROTOCOL_SVC; bundle_id = GB_SVC_BUNDLE_ID; -- cgit v0.10.2 From c011d558e19aa9b6bb739426f5553bf3e1ad5a69 Mon Sep 17 00:00:00 2001 From: Fabien Parent Date: Wed, 2 Sep 2015 15:50:36 +0200 Subject: greybus: es2: dynamically allocate array for cport <-> ep mapping In order to be able to dynamically determine the number of CPorts supported by the UniPro IP instead of hardcoding the value we need to dynamically allocate the array that is doing the cport-ep mapping. Signed-off-by: Fabien Parent Reviewed-by: Johan Hovold Signed-off-by: Johan Hovold diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 4b1f34f..909ca6a 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -108,7 +108,7 @@ struct es1_ap_dev { bool cport_out_urb_cancelled[NUM_CPORT_OUT_URB]; spinlock_t cport_out_urb_lock; - int cport_to_ep[CPORT_COUNT]; + int *cport_to_ep; }; struct cport_to_ep { @@ -443,6 +443,7 @@ static void ap_disconnect(struct usb_interface *interface) usb_set_intfdata(interface, NULL); udev = es1->usb_dev; greybus_remove_hd(es1->hd); + kfree(es1->cport_to_ep); usb_put_dev(udev); } @@ -678,6 +679,13 @@ static int ap_probe(struct usb_interface *interface, endpoint = &udev->ep0.desc; es1->control_endpoint = endpoint->bEndpointAddress; + es1->cport_to_ep = kcalloc(hd->num_cports, sizeof(*es1->cport_to_ep), + GFP_KERNEL); + if (!es1->cport_to_ep) { + retval = -ENOMEM; + goto error; + } + /* find all 3 of our endpoints */ iface_desc = interface->cur_altsetting; for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { -- cgit v0.10.2 From 24a6112fa53e8a08de21b063abb22d10c2595048 Mon Sep 17 00:00:00 2001 From: Fabien Parent Date: Wed, 2 Sep 2015 15:50:37 +0200 Subject: greybus: es2: get cport count from apb1 usb device Use the control request REQUEST_CPORT_COUNT in order to get the number of CPorts supported by the UniPro IP. Signed-off-by: Fabien Parent Signed-off-by: Johan Hovold diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 909ca6a..13605b8 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -33,9 +33,6 @@ static struct dentry *apb1_log_enable_dentry; static struct task_struct *apb1_log_task; static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); -/* Number of cport present on USB bridge */ -#define CPORT_COUNT 44 - /* Number of bulk in and bulk out couple */ #define NUM_BULKS 7 @@ -60,6 +57,9 @@ static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); /* vendor request to map a cport to bulk in and bulk out endpoints */ #define REQUEST_EP_MAPPING 0x03 +/* vendor request to get the number of cports available */ +#define REQUEST_CPORT_COUNT 0x04 + /* * @endpoint: bulk in endpoint for CPort data * @urb: array of urbs for the CPort in messages @@ -636,6 +636,39 @@ static const struct file_operations apb1_log_enable_fops = { .write = apb1_log_enable_write, }; +static int apb1_get_cport_count(struct usb_device *udev) +{ + int retval; + __le16 *cport_count; + + cport_count = kmalloc(sizeof(*cport_count), GFP_KERNEL); + if (!cport_count) + return -ENOMEM; + + retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + REQUEST_CPORT_COUNT, + USB_DIR_IN | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, 0, 0, cport_count, + sizeof(*cport_count), ES1_TIMEOUT); + if (retval < 0) { + dev_err(&udev->dev, "Cannot retrieve CPort count: %d\n", + retval); + goto out; + } + + retval = le16_to_cpu(*cport_count); + + /* We need to fit a CPort ID in one byte of a message header */ + if (retval > U8_MAX) { + retval = U8_MAX; + dev_warn(&udev->dev, "Limiting number of CPorts to U8_MAX\n"); + } + +out: + kfree(cport_count); + return retval; +} + /* * The ES1 USB Bridge device contains 4 endpoints * 1 Control - usual USB stuff + AP -> SVC messages @@ -655,14 +688,20 @@ static int ap_probe(struct usb_interface *interface, int bulk_out = 0; int retval = -ENOMEM; int i; - - /* We need to fit a CPort ID in one byte of a message header */ - BUILD_BUG_ON(CPORT_ID_MAX > U8_MAX); + int num_cports; udev = usb_get_dev(interface_to_usbdev(interface)); + num_cports = apb1_get_cport_count(udev); + if (num_cports < 0) { + usb_put_dev(udev); + dev_err(&udev->dev, "Cannot retrieve CPort count: %d\n", + num_cports); + return num_cports; + } + hd = greybus_create_hd(&es1_driver, &udev->dev, ES1_GBUF_MSG_SIZE_MAX, - CPORT_COUNT); + num_cports); if (IS_ERR(hd)) { usb_put_dev(udev); return PTR_ERR(hd); -- cgit v0.10.2 From f470ead894e3d33e70f62d43b8e255beb37f183b Mon Sep 17 00:00:00 2001 From: Fabien Parent Date: Wed, 2 Sep 2015 15:50:38 +0200 Subject: greybus: es{1,2}: remove control endpoint field There is no need to store the endpoint number of the control requests since the default control endpoint is used and the USB standard defines for it a fixed endpoint number of 0. Remove every instance of the field control_endpoint and replace it with a hardcoded 0 value. Signed-off-by: Fabien Parent Reviewed-by: Johan Hovold Signed-off-by: Johan Hovold diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index fc4297a..f049d65 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -59,7 +59,6 @@ static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); * @usb_dev: pointer to the USB device we are. * @usb_intf: pointer to the USB interface we are bound to. * @hd: pointer to our greybus_host_device structure - * @control_endpoint: endpoint to send data to SVC * @cport_in_endpoint: bulk in endpoint for CPort data * @cport-out_endpoint: bulk out endpoint for CPort data * @cport_in_urb: array of urbs for the CPort in messages @@ -76,7 +75,6 @@ struct es1_ap_dev { struct usb_interface *usb_intf; struct greybus_host_device *hd; - __u8 control_endpoint; __u8 cport_in_endpoint; __u8 cport_out_endpoint; @@ -420,8 +418,7 @@ static void apb1_log_get(struct es1_ap_dev *es1, char *buf) /* SVC messages go down our control pipe */ do { retval = usb_control_msg(es1->usb_dev, - usb_rcvctrlpipe(es1->usb_dev, - es1->control_endpoint), + usb_rcvctrlpipe(es1->usb_dev, 0), REQUEST_LOG, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0x00, 0x00, @@ -577,10 +574,6 @@ static int ap_probe(struct usb_interface *interface, spin_lock_init(&es1->cport_out_urb_lock); usb_set_intfdata(interface, es1); - /* Control endpoint is the pipe to talk to this AP, so save it off */ - endpoint = &udev->ep0.desc; - es1->control_endpoint = endpoint->bEndpointAddress; - /* find all 3 of our endpoints */ iface_desc = interface->cur_altsetting; for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 13605b8..d6bd210 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -83,7 +83,6 @@ struct es1_cport_out { * @usb_dev: pointer to the USB device we are. * @usb_intf: pointer to the USB interface we are bound to. * @hd: pointer to our greybus_host_device structure - * @control_endpoint: endpoint to send data to SVC * @cport_in: endpoint, urbs and buffer for cport in messages * @cport_out: endpoint for for cport out messages @@ -99,8 +98,6 @@ struct es1_ap_dev { struct usb_interface *usb_intf; struct greybus_host_device *hd; - __u8 control_endpoint; - struct es1_cport_in cport_in[NUM_BULKS]; struct es1_cport_out cport_out[NUM_BULKS]; struct urb *cport_out_urb[NUM_CPORT_OUT_URB]; @@ -169,8 +166,7 @@ int map_cport_to_ep(struct es1_ap_dev *es1, cport_to_ep->endpoint_out = es1->cport_out[bulk_ep_set].endpoint; retval = usb_control_msg(es1->usb_dev, - usb_sndctrlpipe(es1->usb_dev, - es1->control_endpoint), + usb_sndctrlpipe(es1->usb_dev, 0), REQUEST_EP_MAPPING, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0x00, 0x00, @@ -518,8 +514,7 @@ static void apb1_log_get(struct es1_ap_dev *es1, char *buf) /* SVC messages go down our control pipe */ do { retval = usb_control_msg(es1->usb_dev, - usb_rcvctrlpipe(es1->usb_dev, - es1->control_endpoint), + usb_rcvctrlpipe(es1->usb_dev, 0), REQUEST_LOG, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0x00, 0x00, @@ -714,10 +709,6 @@ static int ap_probe(struct usb_interface *interface, spin_lock_init(&es1->cport_out_urb_lock); usb_set_intfdata(interface, es1); - /* Control endpoint is the pipe to talk to this AP, so save it off */ - endpoint = &udev->ep0.desc; - es1->control_endpoint = endpoint->bEndpointAddress; - es1->cport_to_ep = kcalloc(hd->num_cports, sizeof(*es1->cport_to_ep), GFP_KERNEL); if (!es1->cport_to_ep) { -- cgit v0.10.2 From 1a58a3befaccdf84f5a31e3cecd26c8d57c10890 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 2 Sep 2015 17:37:38 +0200 Subject: greybus: core: fix hd-creation error path Make sure to return an errno when a host-device buffer-size check fails. Fixes: 1f92f6404614 ("core: return error code when creating host device") Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 3ba744b..605a088 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -184,7 +184,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver if (buffer_size_max < GB_OPERATION_MESSAGE_SIZE_MIN) { dev_err(parent, "greybus host-device buffers too small\n"); - return NULL; + return ERR_PTR(-EINVAL); } if (num_cports == 0 || num_cports > CPORT_ID_MAX) { -- cgit v0.10.2 From 239adcf6bd68dd7b1910f236e7f2854de535e7aa Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 2 Sep 2015 18:03:20 +0200 Subject: greybus: es1: fix build-time cport constraint The CPort count of es1 is now defined by CPORT_COUNT. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index f049d65..2b4bb07 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -556,7 +556,7 @@ static int ap_probe(struct usb_interface *interface, int i; /* We need to fit a CPort ID in one byte of a message header */ - BUILD_BUG_ON(CPORT_ID_MAX > U8_MAX); + BUILD_BUG_ON(CPORT_COUNT > U8_MAX + 1); udev = usb_get_dev(interface_to_usbdev(interface)); -- cgit v0.10.2 From 1dc53922655a1f2537488a9d52aa99d111f38f66 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 2 Sep 2015 18:03:21 +0200 Subject: greybus: fix cport-id defines The CPORT_ID_MAX define has been used by host drivers as a device limit, but also for sanity checks when parsing manifests. Now that it's only used for sanity checks we can increase it to the specification maximum (4095) and get rid of the config-option that could be used to override the previous limit (128). Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 27a7724..8e215f8 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -53,15 +53,9 @@ .match_flags = GREYBUS_DEVICE_ID_MATCH_SERIAL, \ .serial_number = (s), -/* XXX I couldn't get my Kconfig file to be noticed for out-of-tree build */ -#ifndef CONFIG_CPORT_ID_MAX -#define CONFIG_CPORT_ID_MAX 128 -#endif /* !CONFIG_CPORT_ID_MAX */ - -/* Maximum number of CPorts usable by a host device */ -/* XXX This should really be determined by the AP module manifest */ -#define CPORT_ID_MAX CONFIG_CPORT_ID_MAX -#define CPORT_ID_BAD U16_MAX /* UniPro max id is 4095 */ +/* Maximum number of CPorts */ +#define CPORT_ID_MAX 4095 /* UniPro max id is 4095 */ +#define CPORT_ID_BAD U16_MAX /* For SP1 hardware, we are going to "hardcode" each device to have all logical * blocks in order to be able to address them as one unified "unit". Then -- cgit v0.10.2 From 3a17dd413a1857fc92b22e54c03cae155f106056 Mon Sep 17 00:00:00 2001 From: Vishal Bhoj Date: Wed, 2 Sep 2015 22:35:19 -0700 Subject: greybus: build: android: avoid building for targets that don't have kernel binary For sdk related targets, the greybus build will error out due to missing kernel dependency. Let's avoid those targets by checking TARGET_NO_KERNEL. Signed-off-by: Vishal Bhoj Signed-off-by: Michael Scott Signed-off-by: Johan Hovold diff --git a/drivers/staging/greybus/Android.mk b/drivers/staging/greybus/Android.mk index 112f4de..3357499 100644 --- a/drivers/staging/greybus/Android.mk +++ b/drivers/staging/greybus/Android.mk @@ -1,6 +1,8 @@ .PHONY: build-greybus +ifneq ($(TARGET_NO_KERNEL), true) $(PRODUCT_OUT)/ramdisk.img: build-greybus +endif GREYBUS_MODULE_OUT_PATH := $(PRODUCT_OUT)/root/lib/modules -- cgit v0.10.2 From f66427adfd407ea08236ab541df192e15671b6cf Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 2 Sep 2015 21:27:13 +0530 Subject: greybus: svc: Include system headers at the top System headers should get included before greybus.h. Its followed everywhere except svc.c. Fix it. Reported-by: Johan Hovold Signed-off-by: Viresh Kumar Signed-off-by: Johan Hovold diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index ac8ff44..3b37dfe 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -7,9 +7,10 @@ * Released under the GPLv2 only. */ -#include "greybus.h" #include +#include "greybus.h" + #define CPORT_FLAGS_E2EFC (1) #define CPORT_FLAGS_CSD_N (2) #define CPORT_FLAGS_CSV_N (4) -- cgit v0.10.2 From 3ccb1600babfda0c71cba376e21f4f95a61080a2 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Sep 2015 15:42:22 +0530 Subject: greybus: svc: reject invalid state requests The request sequence for SVC protocol is fixed at least upto SVC_HELLO request. The first request has to be Protocol Version, followed by SVC_HELLO. Any other request can follow them, but these two. Add another field in 'struct gb_svc' that keeps track of current state of the protocol driver. It tracks only upto SVC_HELLO, as we don't need to track later ones. Also add a comment, about the order in which the requests are allowed and why a race can't happen while accessing 'state'. This removes the WARN_ON() in gb_svc_hello() as we track state transition with 'state' field. This also fixes a crash, when the hotplug request is received before fully initializing the svc connection. The crash mostly happens while accessing svc->connection->bundle, which is NULL, but can happen at other places too, as svc connection isn't fully initialized. Reported-by: Johan Hovold Signed-off-by: Viresh Kumar [johan: add 0x-prefix to warning message ] Signed-off-by: Johan Hovold diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 3b37dfe..42b89ee 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -15,8 +15,15 @@ #define CPORT_FLAGS_CSD_N (2) #define CPORT_FLAGS_CSV_N (4) +enum gb_svc_state { + GB_SVC_STATE_RESET, + GB_SVC_STATE_PROTOCOL_VERSION, + GB_SVC_STATE_SVC_HELLO, +}; + struct gb_svc { struct gb_connection *connection; + enum gb_svc_state state; }; struct svc_hotplug { @@ -226,9 +233,6 @@ static int gb_svc_hello(struct gb_operation *op) u8 interface_id; int ret; - /* Hello message should be received only during early bootup */ - WARN_ON(hd->initial_svc_connection != connection); - /* * SVC sends information about the endo and interface-id on the hello * request, use that to create an endo. @@ -452,11 +456,53 @@ static int gb_svc_intf_reset_recv(struct gb_operation *op) static int gb_svc_request_recv(u8 type, struct gb_operation *op) { + struct gb_connection *connection = op->connection; + struct gb_svc *svc = connection->private; + int ret = 0; + + /* + * SVC requests need to follow a specific order (at least initially) and + * below code takes care of enforcing that. The expected order is: + * - PROTOCOL_VERSION + * - SVC_HELLO + * - Any other request, but the earlier two. + * + * Incoming requests are guaranteed to be serialized and so we don't + * need to protect 'state' for any races. + */ switch (type) { case GB_REQUEST_TYPE_PROTOCOL_VERSION: - return gb_svc_version_request(op); + if (svc->state != GB_SVC_STATE_RESET) + ret = -EINVAL; + break; case GB_SVC_TYPE_SVC_HELLO: - return gb_svc_hello(op); + if (svc->state != GB_SVC_STATE_PROTOCOL_VERSION) + ret = -EINVAL; + break; + default: + if (svc->state != GB_SVC_STATE_SVC_HELLO) + ret = -EINVAL; + break; + } + + if (ret) { + dev_warn(&connection->dev, + "unexpected SVC request 0x%02x received (state %u)\n", + type, svc->state); + return ret; + } + + switch (type) { + case GB_REQUEST_TYPE_PROTOCOL_VERSION: + ret = gb_svc_version_request(op); + if (!ret) + svc->state = GB_SVC_STATE_PROTOCOL_VERSION; + return ret; + case GB_SVC_TYPE_SVC_HELLO: + ret = gb_svc_hello(op); + if (!ret) + svc->state = GB_SVC_STATE_SVC_HELLO; + return ret; case GB_SVC_TYPE_INTF_HOTPLUG: return gb_svc_intf_hotplug_recv(op); case GB_SVC_TYPE_INTF_HOT_UNPLUG: @@ -479,6 +525,7 @@ static int gb_svc_connection_init(struct gb_connection *connection) return -ENOMEM; connection->hd->svc = svc; + svc->state = GB_SVC_STATE_RESET; svc->connection = connection; connection->private = svc; -- cgit v0.10.2 From d6ec787299c242775ef1e49c6f558121effa248c Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 31 Aug 2015 17:21:02 +0530 Subject: greybus: greybus_protocols: svc: Add missing comment All request/responses either have a structure representing them or a comment saying the request/response payload doesn't exist. The comment was missing for route create response message, add it. Reviewed-by: Johan Hovold Signed-off-by: Viresh Kumar Signed-off-by: Johan Hovold diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index b84c710..846f3e3 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -804,6 +804,7 @@ struct gb_svc_route_create_request { __u8 intf2_id; __u8 dev2_id; }; +/* route create response has no payload */ /* RAW */ -- cgit v0.10.2 From 829a91e7155e4cb5c90e99ebd6048c7618b29e9b Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 31 Aug 2015 17:21:03 +0530 Subject: greybus: greybus_protocols: Pack structure as required by the module firmware These structures are expected to be packed by the module firmware code, but the kernel wasn't following it until now. Its all working currently because compiler doesn't add any pad bytes for these structures, as their elements are already aligned to their size. But these structures can change in future and we better mark them packed. Signed-off-by: Viresh Kumar Signed-off-by: Johan Hovold diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 846f3e3..1984e5e 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -172,27 +172,27 @@ struct gb_control_disconnected_request { /* Firmware protocol firmware size request/response */ struct gb_firmware_size_request { __u8 stage; -}; +} __packed; struct gb_firmware_size_response { __le32 size; -}; +} __packed; /* Firmware protocol get firmware request/response */ struct gb_firmware_get_firmware_request { __le32 offset; __le32 size; -}; +} __packed; struct gb_firmware_get_firmware_response { __u8 data[0]; -}; +} __packed; /* Firmware protocol Ready to boot request */ struct gb_firmware_ready_to_boot_request { __u8 stage; __u8 status; -}; +} __packed; /* Firmware protocol Ready to boot response has no payload */ @@ -756,7 +756,7 @@ struct gb_svc_hello_request { struct gb_svc_intf_device_id_request { __u8 intf_id; __u8 device_id; -}; +} __packed; /* device id response has no payload */ struct gb_svc_intf_hotplug_request { @@ -772,12 +772,12 @@ struct gb_svc_intf_hotplug_request { struct gb_svc_intf_hot_unplug_request { __u8 intf_id; -}; +} __packed; /* hot unplug response has no payload */ struct gb_svc_intf_reset_request { __u8 intf_id; -}; +} __packed; /* interface reset response has no payload */ struct gb_svc_conn_create_request { @@ -803,7 +803,7 @@ struct gb_svc_route_create_request { __u8 dev1_id; __u8 intf2_id; __u8 dev2_id; -}; +} __packed; /* route create response has no payload */ -- cgit v0.10.2 From b701686a3e6739bc8bd94fba13809e25a4ce1bd3 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 31 Aug 2015 17:21:04 +0530 Subject: greybus: greybus_protocols: Pack all request/response structure These structures are exchanged between the AP and the module and must be packed to avoid any unwanted holes. Its all working currently because compiler doesn't add any pad bytes for these structures, as their elements are already aligned to their size. But these structures can change in future and we better mark them packed. Signed-off-by: Viresh Kumar Signed-off-by: Johan Hovold diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 1984e5e..c8bfced 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -96,7 +96,7 @@ struct gb_operation_msg_hdr { __u8 type; /* E.g GB_I2C_TYPE_* or GB_GPIO_TYPE_* */ __u8 result; /* Result of request (in responses only) */ __u8 pad[2]; /* must be zero (ignore when read) */ -}; +} __packed; /* Generic request numbers supported by all modules */ @@ -109,7 +109,7 @@ struct gb_operation_msg_hdr { struct gb_protocol_version_response { __u8 major; __u8 minor; -}; +} __packed; /* Control Protocol */ @@ -127,21 +127,21 @@ struct gb_protocol_version_response { /* Control protocol manifest get size request has no payload*/ struct gb_control_get_manifest_size_response { __le16 size; -}; +} __packed; /* Control protocol manifest get request has no payload */ struct gb_control_get_manifest_response { __u8 data[0]; -}; +} __packed; /* Control protocol [dis]connected request */ struct gb_control_connected_request { __le16 cport_id; -}; +} __packed; struct gb_control_disconnected_request { __le16 cport_id; -}; +} __packed; /* Control protocol [dis]connected response has no payload */ @@ -224,7 +224,7 @@ struct gb_firmware_ready_to_boot_request { struct gb_battery_technology_response { __le32 technology; -}; +} __packed; /* Should match up with battery status in linux/power_supply.h */ #define GB_BATTERY_STATUS_UNKNOWN 0x0000 @@ -235,23 +235,23 @@ struct gb_battery_technology_response { struct gb_battery_status_response { __le16 battery_status; -}; +} __packed; struct gb_battery_max_voltage_response { __le32 max_voltage; -}; +} __packed; struct gb_battery_capacity_response { __le32 capacity; -}; +} __packed; struct gb_battery_temperature_response { __le32 temperature; -}; +} __packed; struct gb_battery_voltage_response { __le32 voltage; -}; +} __packed; /* HID */ @@ -289,19 +289,19 @@ struct gb_hid_desc_response { struct gb_hid_get_report_request { __u8 report_type; __u8 report_id; -}; +} __packed; /* HID set report request */ struct gb_hid_set_report_request { __u8 report_type; __u8 report_id; __u8 report[0]; -}; +} __packed; /* HID input report request, via interrupt pipe */ struct gb_hid_input_report_request { __u8 report[0]; -}; +} __packed; /* I2C */ @@ -322,16 +322,16 @@ struct gb_hid_input_report_request { /* functionality request has no payload */ struct gb_i2c_functionality_response { __le32 functionality; -}; +} __packed; struct gb_i2c_timeout_request { __le16 msec; -}; +} __packed; /* timeout response has no payload */ struct gb_i2c_retries_request { __u8 retries; -}; +} __packed; /* retries response has no payload */ /* @@ -348,15 +348,15 @@ struct gb_i2c_transfer_op { __le16 addr; __le16 flags; __le16 size; -}; +} __packed; struct gb_i2c_transfer_request { __le16 op_count; struct gb_i2c_transfer_op ops[0]; /* op_count of these */ -}; +} __packed; struct gb_i2c_transfer_response { __u8 data[0]; /* inbound data */ -}; +} __packed; /* GPIO */ @@ -390,47 +390,47 @@ struct gb_i2c_transfer_response { /* line count request has no payload */ struct gb_gpio_line_count_response { __u8 count; -}; +} __packed; struct gb_gpio_activate_request { __u8 which; -}; +} __packed; /* activate response has no payload */ struct gb_gpio_deactivate_request { __u8 which; -}; +} __packed; /* deactivate response has no payload */ struct gb_gpio_get_direction_request { __u8 which; -}; +} __packed; struct gb_gpio_get_direction_response { __u8 direction; -}; +} __packed; struct gb_gpio_direction_in_request { __u8 which; -}; +} __packed; /* direction in response has no payload */ struct gb_gpio_direction_out_request { __u8 which; __u8 value; -}; +} __packed; /* direction out response has no payload */ struct gb_gpio_get_value_request { __u8 which; -}; +} __packed; struct gb_gpio_get_value_response { __u8 value; -}; +} __packed; struct gb_gpio_set_value_request { __u8 which; __u8 value; -}; +} __packed; /* set value response has no payload */ struct gb_gpio_set_debounce_request { @@ -442,23 +442,23 @@ struct gb_gpio_set_debounce_request { struct gb_gpio_irq_type_request { __u8 which; __u8 type; -}; +} __packed; /* irq type response has no payload */ struct gb_gpio_irq_mask_request { __u8 which; -}; +} __packed; /* irq mask response has no payload */ struct gb_gpio_irq_unmask_request { __u8 which; -}; +} __packed; /* irq unmask response has no payload */ /* irq event requests originate on another module and are handled on the AP */ struct gb_gpio_irq_event_request { __u8 which; -}; +} __packed; /* irq event has no response */ @@ -480,15 +480,15 @@ struct gb_gpio_irq_event_request { /* pwm count request has no payload */ struct gb_pwm_count_response { __u8 count; -}; +} __packed; struct gb_pwm_activate_request { __u8 which; -}; +} __packed; struct gb_pwm_deactivate_request { __u8 which; -}; +} __packed; struct gb_pwm_config_request { __u8 which; @@ -499,15 +499,15 @@ struct gb_pwm_config_request { struct gb_pwm_polarity_request { __u8 which; __u8 polarity; -}; +} __packed; struct gb_pwm_enable_request { __u8 which; -}; +} __packed; struct gb_pwm_disable_request { __u8 which; -}; +} __packed; /* I2S */ @@ -593,48 +593,48 @@ struct gb_i2s_mgmt_configuration { __u8 ll_wclk_tx_edge; __u8 ll_wclk_rx_edge; __u8 ll_data_offset; -}; +} __packed; /* get supported configurations request has no payload */ struct gb_i2s_mgmt_get_supported_configurations_response { __u8 config_count; __u8 pad[3]; struct gb_i2s_mgmt_configuration config[0]; -}; +} __packed; struct gb_i2s_mgmt_set_configuration_request { struct gb_i2s_mgmt_configuration config; -}; +} __packed; /* set configuration response has no payload */ struct gb_i2s_mgmt_set_samples_per_message_request { __le16 samples_per_message; -}; +} __packed; /* set samples per message response has no payload */ /* get processing request delay has no payload */ struct gb_i2s_mgmt_get_processing_delay_response { __le32 microseconds; -}; +} __packed; struct gb_i2s_mgmt_set_start_delay_request { __le32 microseconds; -}; +} __packed; /* set start delay response has no payload */ struct gb_i2s_mgmt_activate_cport_request { __le16 cport; -}; +} __packed; /* activate cport response has no payload */ struct gb_i2s_mgmt_deactivate_cport_request { __le16 cport; -}; +} __packed; /* deactivate cport response has no payload */ struct gb_i2s_mgmt_report_event_request { __u8 event; -}; +} __packed; /* report event response has no payload */ #define GB_I2S_DATA_TYPE_SEND_DATA 0x02 @@ -643,7 +643,7 @@ struct gb_i2s_send_data_request { __le32 sample_number; __le32 size; __u8 data[0]; -}; +} __packed; /* send data has no response at all */ @@ -682,22 +682,22 @@ struct gb_i2s_send_data_request { /* mode request has no payload */ struct gb_spi_mode_response { __le16 mode; -}; +} __packed; /* flags request has no payload */ struct gb_spi_flags_response { __le16 flags; -}; +} __packed; /* bits-per-word request has no payload */ struct gb_spi_bpw_response { __le32 bits_per_word_mask; -}; +} __packed; /* num-chipselects request has no payload */ struct gb_spi_chipselect_response { __le16 num_chipselect; -}; +} __packed; /** * struct gb_spi_transfer - a read/write buffer pair @@ -717,18 +717,18 @@ struct gb_spi_transfer { __le16 delay_usecs; __u8 cs_change; __u8 bits_per_word; -}; +} __packed; struct gb_spi_transfer_request { __u8 chip_select; /* of the spi device */ __u8 mode; /* of the spi device */ __le16 count; struct gb_spi_transfer transfers[0]; /* count of these */ -}; +} __packed; struct gb_spi_transfer_response { __u8 data[0]; /* inbound data */ -}; +} __packed; /* Version of the Greybus SVC protocol we support */ #define GB_SVC_VERSION_MAJOR 0x00 @@ -819,7 +819,7 @@ struct gb_svc_route_create_request { struct gb_raw_send_request { __le32 len; __u8 data[0]; -}; +} __packed; /* UART */ @@ -840,7 +840,7 @@ struct gb_raw_send_request { struct gb_uart_send_data_request { __le16 size; __u8 data[0]; -}; +} __packed; /* recv-data-request flags */ #define GB_UART_RECV_FLAG_FRAMING 0x01 /* Framing error */ @@ -878,11 +878,11 @@ struct gb_uart_set_line_coding_request { struct gb_uart_set_control_line_state_request { __u8 control; -}; +} __packed; struct gb_uart_set_break_request { __u8 state; -}; +} __packed; /* input control lines and line errors */ #define GB_UART_CTRL_DCD 0x01 @@ -891,7 +891,7 @@ struct gb_uart_set_break_request { struct gb_uart_serial_state_request { __u8 control; -}; +} __packed; /* Loopback */ @@ -907,11 +907,11 @@ struct gb_uart_serial_state_request { struct gb_loopback_transfer_request { __le32 len; __u8 data[0]; -}; +} __packed; struct gb_loopback_transfer_response { __u8 data[0]; -}; +} __packed; /* SDIO */ /* Version of the Greybus sdio protocol we support */ @@ -954,7 +954,7 @@ struct gb_sdio_get_caps_response { __le32 ocr; __le16 max_blk_count; __le16 max_blk_size; -}; +} __packed; /* set ios request: response has no payload */ struct gb_sdio_set_ios_request { @@ -1040,7 +1040,7 @@ struct gb_sdio_command_request { struct gb_sdio_command_response { __le32 resp[4]; -}; +} __packed; /* transfer request */ struct gb_sdio_transfer_request { @@ -1058,7 +1058,7 @@ struct gb_sdio_transfer_response { __le16 data_blocks; __le16 data_blksz; __u8 data[0]; -}; +} __packed; /* event request: generated by module and is defined as unidirectional */ struct gb_sdio_event_request { @@ -1066,7 +1066,7 @@ struct gb_sdio_event_request { #define GB_SDIO_CARD_INSERTED 0x01 #define GB_SDIO_CARD_REMOVED 0x02 #define GB_SDIO_WP 0x04 -}; +} __packed; /* Lights */ @@ -1119,30 +1119,30 @@ struct gb_sdio_event_request { /* get count of lights in module */ struct gb_lights_get_lights_response { __u8 lights_count; -}; +} __packed; /* light config request payload */ struct gb_lights_get_light_config_request { __u8 id; -}; +} __packed; /* light config response payload */ struct gb_lights_get_light_config_response { __u8 channel_count; __u8 name[32]; -}; +} __packed; /* channel config request payload */ struct gb_lights_get_channel_config_request { __u8 light_id; __u8 channel_id; -}; +} __packed; /* channel flash config request payload */ struct gb_lights_get_channel_flash_config_request { __u8 light_id; __u8 channel_id; -}; +} __packed; /* channel config response payload */ struct gb_lights_get_channel_config_response { @@ -1162,7 +1162,7 @@ struct gb_lights_get_channel_flash_config_response { __le32 timeout_min_us; __le32 timeout_max_us; __le32 timeout_step_us; -}; +} __packed; /* blink request payload: response have no payload */ struct gb_lights_blink_request { @@ -1170,14 +1170,14 @@ struct gb_lights_blink_request { __u8 channel_id; __le16 time_on_ms; __le16 time_off_ms; -}; +} __packed; /* set brightness request payload: response have no payload */ struct gb_lights_set_brightness_request { __u8 light_id; __u8 channel_id; __u8 brightness; -}; +} __packed; /* set color request payload: response have no payload */ struct gb_lights_set_color_request { @@ -1192,14 +1192,14 @@ struct gb_lights_set_fade_request { __u8 channel_id; __u8 fade_in; __u8 fade_out; -}; +} __packed; /* event request: generated by module */ struct gb_lights_event_request { __u8 light_id; __u8 event; #define GB_LIGHTS_LIGHT_CONFIG 0x01 -}; +} __packed; /* set flash intensity request payload: response have no payload */ struct gb_lights_set_flash_intensity_request { @@ -1213,7 +1213,7 @@ struct gb_lights_set_flash_strobe_request { __u8 light_id; __u8 channel_id; __u8 state; -}; +} __packed; /* set flash timeout request payload: response have no payload */ struct gb_lights_set_flash_timeout_request { @@ -1226,7 +1226,7 @@ struct gb_lights_set_flash_timeout_request { struct gb_lights_get_flash_fault_request { __u8 light_id; __u8 channel_id; -}; +} __packed; /* get flash fault response payload */ struct gb_lights_get_flash_fault_response { @@ -1240,7 +1240,7 @@ struct gb_lights_get_flash_fault_response { #define GB_LIGHTS_FLASH_FAULT_UNDER_VOLTAGE 0x00000020 #define GB_LIGHTS_FLASH_FAULT_INPUT_VOLTAGE 0x00000040 #define GB_LIGHTS_FLASH_FAULT_LED_OVER_TEMPERATURE 0x00000080 -}; +} __packed; #endif /* __GREYBUS_PROTOCOLS_H */ -- cgit v0.10.2 From d9fcffff2c5442225cec21f55e74fb752e67e57f Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 31 Aug 2015 17:21:05 +0530 Subject: greybus: svc: No need to return errors from [gb_]svc_connection_destroy() These routines are responsible to destroy a connection that is going away, the return value is of no use. At best, print an error message to show that we got an error. Make their return type void. Reviewed-by: Johan Hovold Signed-off-by: Viresh Kumar Signed-off-by: Johan Hovold diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 42b89ee..e56cb18 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -125,19 +125,26 @@ static int connection_create_operation(struct gb_svc *svc, &request, sizeof(request), NULL, 0); } -static int connection_destroy_operation(struct gb_svc *svc, +static void connection_destroy_operation(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id) { struct gb_svc_conn_destroy_request request; + struct gb_connection *connection = svc->connection; + int ret; request.intf1_id = intf1_id; request.cport1_id = cport1_id; request.intf2_id = intf2_id; request.cport2_id = cport2_id; - return gb_operation_sync(svc->connection, GB_SVC_TYPE_CONN_DESTROY, - &request, sizeof(request), NULL, 0); + ret = gb_operation_sync(connection, GB_SVC_TYPE_CONN_DESTROY, + &request, sizeof(request), NULL, 0); + if (ret) { + dev_err(&connection->dev, + "failed to destroy connection (%hhx:%hx %hhx:%hx) %d\n", + intf1_id, cport1_id, intf2_id, cport2_id, ret); + } } static int route_create_operation(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, @@ -175,12 +182,11 @@ int gb_svc_connection_create(struct gb_svc *svc, } EXPORT_SYMBOL_GPL(gb_svc_connection_create); -int gb_svc_connection_destroy(struct gb_svc *svc, - u8 intf1_id, u16 cport1_id, - u8 intf2_id, u16 cport2_id) +void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, + u8 intf2_id, u16 cport2_id) { - return connection_destroy_operation(svc, intf1_id, cport1_id, - intf2_id, cport2_id); + connection_destroy_operation(svc, intf1_id, cport1_id, intf2_id, + cport2_id); } EXPORT_SYMBOL_GPL(gb_svc_connection_destroy); diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index ee39479..dae4a08 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -16,8 +16,8 @@ int gb_svc_intf_device_id(struct gb_svc *svc, u8 intf_id, u8 device_id); int gb_svc_intf_reset(struct gb_svc *svc, u8 intf_id); int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id); -int gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, - u8 intf2_id, u16 cport2_id); +void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, + u8 intf2_id, u16 cport2_id); int gb_svc_protocol_init(void); void gb_svc_protocol_exit(void); -- cgit v0.10.2 From 3f0e9183b443ca7cae058372906a652f97301c11 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 31 Aug 2015 17:21:06 +0530 Subject: greybus: svc: Kill unnecessary wrapper functions Not sure why they were created, but there is no need for them. Kill them. Reviewed-by: Johan Hovold Signed-off-by: Viresh Kumar Signed-off-by: Johan Hovold diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index e56cb18..005c28a 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -82,8 +82,7 @@ gb_ap_interface_create(struct greybus_host_device *hd, return intf; } -static int intf_device_id_operation(struct gb_svc *svc, - u8 intf_id, u8 device_id) +int gb_svc_intf_device_id(struct gb_svc *svc, u8 intf_id, u8 device_id) { struct gb_svc_intf_device_id_request request; @@ -93,8 +92,9 @@ static int intf_device_id_operation(struct gb_svc *svc, return gb_operation_sync(svc->connection, GB_SVC_TYPE_INTF_DEVICE_ID, &request, sizeof(request), NULL, 0); } +EXPORT_SYMBOL_GPL(gb_svc_intf_device_id); -static int intf_reset_operation(struct gb_svc *svc, u8 intf_id) +int gb_svc_intf_reset(struct gb_svc *svc, u8 intf_id) { struct gb_svc_intf_reset_request request; @@ -103,8 +103,9 @@ static int intf_reset_operation(struct gb_svc *svc, u8 intf_id) return gb_operation_sync(svc->connection, GB_SVC_TYPE_INTF_RESET, &request, sizeof(request), NULL, 0); } +EXPORT_SYMBOL_GPL(gb_svc_intf_reset); -static int connection_create_operation(struct gb_svc *svc, +int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id) { @@ -124,10 +125,10 @@ static int connection_create_operation(struct gb_svc *svc, return gb_operation_sync(svc->connection, GB_SVC_TYPE_CONN_CREATE, &request, sizeof(request), NULL, 0); } +EXPORT_SYMBOL_GPL(gb_svc_connection_create); -static void connection_destroy_operation(struct gb_svc *svc, - u8 intf1_id, u16 cport1_id, - u8 intf2_id, u16 cport2_id) +void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, + u8 intf2_id, u16 cport2_id) { struct gb_svc_conn_destroy_request request; struct gb_connection *connection = svc->connection; @@ -146,9 +147,10 @@ static void connection_destroy_operation(struct gb_svc *svc, intf1_id, cport1_id, intf2_id, cport2_id, ret); } } +EXPORT_SYMBOL_GPL(gb_svc_connection_destroy); -static int route_create_operation(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, - u8 intf2_id, u8 dev2_id) +int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, + u8 intf2_id, u8 dev2_id) { struct gb_svc_route_create_request request; @@ -160,42 +162,6 @@ static int route_create_operation(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, return gb_operation_sync(svc->connection, GB_SVC_TYPE_ROUTE_CREATE, &request, sizeof(request), NULL, 0); } - -int gb_svc_intf_device_id(struct gb_svc *svc, u8 intf_id, u8 device_id) -{ - return intf_device_id_operation(svc, intf_id, device_id); -} -EXPORT_SYMBOL_GPL(gb_svc_intf_device_id); - -int gb_svc_intf_reset(struct gb_svc *svc, u8 intf_id) -{ - return intf_reset_operation(svc, intf_id); -} -EXPORT_SYMBOL_GPL(gb_svc_intf_reset); - -int gb_svc_connection_create(struct gb_svc *svc, - u8 intf1_id, u16 cport1_id, - u8 intf2_id, u16 cport2_id) -{ - return connection_create_operation(svc, intf1_id, cport1_id, - intf2_id, cport2_id); -} -EXPORT_SYMBOL_GPL(gb_svc_connection_create); - -void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, - u8 intf2_id, u16 cport2_id) -{ - connection_destroy_operation(svc, intf1_id, cport1_id, intf2_id, - cport2_id); -} -EXPORT_SYMBOL_GPL(gb_svc_connection_destroy); - -int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, - u8 intf2_id, u8 dev2_id) -{ - return route_create_operation(svc, intf1_id, dev1_id, - intf2_id, dev2_id); -} EXPORT_SYMBOL_GPL(gb_svc_route_create); static int gb_svc_version_request(struct gb_operation *op) @@ -323,7 +289,7 @@ static void svc_process_hotplug(struct work_struct *work) goto destroy_interface; } - ret = intf_device_id_operation(svc, intf_id, device_id); + ret = gb_svc_intf_device_id(svc, intf_id, device_id); if (ret) { dev_err(dev, "%s: Device id operation failed, interface %hhu device_id %hhu (%d)\n", __func__, intf_id, device_id, ret); @@ -333,16 +299,16 @@ static void svc_process_hotplug(struct work_struct *work) /* * Create a two-way route between the AP and the new interface */ - ret = route_create_operation(svc, hd->endo->ap_intf_id, - GB_DEVICE_ID_AP, intf_id, device_id); + ret = gb_svc_route_create(svc, hd->endo->ap_intf_id, GB_DEVICE_ID_AP, + intf_id, device_id); if (ret) { dev_err(dev, "%s: Route create operation failed, interface %hhu device_id %hhu (%d)\n", __func__, intf_id, device_id, ret); goto ida_put; } - ret = route_create_operation(svc, intf_id, device_id, - hd->endo->ap_intf_id, GB_DEVICE_ID_AP); + ret = gb_svc_route_create(svc, intf_id, device_id, hd->endo->ap_intf_id, + GB_DEVICE_ID_AP); if (ret) { dev_err(dev, "%s: Route create operation failed, interface %hhu device_id %hhu (%d)\n", __func__, intf_id, device_id, ret); -- cgit v0.10.2 From 505f16cc05a4ddeafe5efe33645123fed194d811 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 31 Aug 2015 17:21:07 +0530 Subject: greybus: svc: unexport few internal functions There are no external users of these, and probably would never be. Make them static. Reviewed-by: Johan Hovold Signed-off-by: Viresh Kumar Signed-off-by: Johan Hovold diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 005c28a..b32519a 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -82,7 +82,7 @@ gb_ap_interface_create(struct greybus_host_device *hd, return intf; } -int gb_svc_intf_device_id(struct gb_svc *svc, u8 intf_id, u8 device_id) +static int gb_svc_intf_device_id(struct gb_svc *svc, u8 intf_id, u8 device_id) { struct gb_svc_intf_device_id_request request; @@ -92,7 +92,6 @@ int gb_svc_intf_device_id(struct gb_svc *svc, u8 intf_id, u8 device_id) return gb_operation_sync(svc->connection, GB_SVC_TYPE_INTF_DEVICE_ID, &request, sizeof(request), NULL, 0); } -EXPORT_SYMBOL_GPL(gb_svc_intf_device_id); int gb_svc_intf_reset(struct gb_svc *svc, u8 intf_id) { @@ -149,8 +148,8 @@ void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, } EXPORT_SYMBOL_GPL(gb_svc_connection_destroy); -int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, - u8 intf2_id, u8 dev2_id) +static int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, + u8 intf2_id, u8 dev2_id) { struct gb_svc_route_create_request request; @@ -162,7 +161,6 @@ int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, return gb_operation_sync(svc->connection, GB_SVC_TYPE_ROUTE_CREATE, &request, sizeof(request), NULL, 0); } -EXPORT_SYMBOL_GPL(gb_svc_route_create); static int gb_svc_version_request(struct gb_operation *op) { diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index dae4a08..f1acb82 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -12,7 +12,6 @@ struct gb_svc; -int gb_svc_intf_device_id(struct gb_svc *svc, u8 intf_id, u8 device_id); int gb_svc_intf_reset(struct gb_svc *svc, u8 intf_id); int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id); -- cgit v0.10.2 From ad14b9e9ec4973416a911a5d3c59caedc048a279 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 31 Aug 2015 17:21:08 +0530 Subject: greybus: bundle: kill unnecessary forward declaration of routine Move the function to an earlier place, to kill the unnecessary forward declaration. Reviewed-by: Bryan O'Donoghue Reviewed-by: Johan Hovold Signed-off-by: Viresh Kumar Signed-off-by: Johan Hovold diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 694bcce..459c62a 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -9,8 +9,6 @@ #include "greybus.h" -static void gb_bundle_connections_exit(struct gb_bundle *bundle); - static ssize_t class_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -197,6 +195,18 @@ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, return bundle; } +static void gb_bundle_connections_exit(struct gb_bundle *bundle) +{ + struct gb_connection *connection; + struct gb_connection *next; + + list_for_each_entry_safe(connection, next, &bundle->connections, + bundle_links) { + gb_connection_exit(connection); + gb_connection_destroy(connection); + } +} + /* * Tear down a previously set up bundle. */ @@ -224,15 +234,3 @@ found: return bundle; } - -static void gb_bundle_connections_exit(struct gb_bundle *bundle) -{ - struct gb_connection *connection; - struct gb_connection *next; - - list_for_each_entry_safe(connection, next, &bundle->connections, - bundle_links) { - gb_connection_exit(connection); - gb_connection_destroy(connection); - } -} -- cgit v0.10.2 From 630096899120321791f0ca6fea7ad7f9bd572e20 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 31 Aug 2015 17:21:09 +0530 Subject: greybus: connection: staticize gb_connection_init() Its not used by external users, mark it static. This required some shuffling of the code. Reviewed-by: Bryan O'Donoghue Reviewed-by: Johan Hovold Signed-off-by: Viresh Kumar Signed-off-by: Johan Hovold diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 286e7da..62cbeb3 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -163,31 +163,6 @@ int svc_update_connection(struct gb_interface *intf, return 0; } -void gb_connection_bind_protocol(struct gb_connection *connection) -{ - struct gb_protocol *protocol; - - /* If we already have a protocol bound here, just return */ - if (connection->protocol) - return; - - protocol = gb_protocol_get(connection->protocol_id, - connection->major, - connection->minor); - if (!protocol) - return; - connection->protocol = protocol; - - /* - * If we have a valid device_id for the interface block, then we have an - * active device, so bring up the connection at the same time. - */ - if ((!connection->bundle && - connection->hd_cport_id == GB_SVC_CPORT_ID) || - connection->bundle->intf->device_id != GB_DEVICE_ID_BAD) - gb_connection_init(connection); -} - /* * Set up a Greybus connection, representing the bidirectional link * between a CPort on a (local) Greybus host device and a CPort on @@ -391,7 +366,7 @@ static void gb_connection_disconnected(struct gb_connection *connection) "Failed to disconnect CPort-%d (%d)\n", cport_id, ret); } -int gb_connection_init(struct gb_connection *connection) +static int gb_connection_init(struct gb_connection *connection) { int cport_id = connection->intf_cport_id; int ret; @@ -480,3 +455,28 @@ void gb_hd_connections_exit(struct greybus_host_device *hd) gb_connection_destroy(connection); } } + +void gb_connection_bind_protocol(struct gb_connection *connection) +{ + struct gb_protocol *protocol; + + /* If we already have a protocol bound here, just return */ + if (connection->protocol) + return; + + protocol = gb_protocol_get(connection->protocol_id, + connection->major, + connection->minor); + if (!protocol) + return; + connection->protocol = protocol; + + /* + * If we have a valid device_id for the interface block, then we have an + * active device, so bring up the connection at the same time. + */ + if ((!connection->bundle && + connection->hd_cport_id == GB_SVC_CPORT_ID) || + connection->bundle->intf->device_id != GB_DEVICE_ID_BAD) + gb_connection_init(connection); +} diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index a26a480..f1b5863 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -61,7 +61,6 @@ struct gb_connection *gb_connection_create_range(struct greybus_host_device *hd, u32 ida_end); void gb_connection_destroy(struct gb_connection *connection); -int gb_connection_init(struct gb_connection *connection); void gb_connection_exit(struct gb_connection *connection); void gb_hd_connections_exit(struct greybus_host_device *hd); -- cgit v0.10.2 From 3dca03de9db7c467811bdfcb0b3b90cb9a184a8f Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 31 Aug 2015 17:21:10 +0530 Subject: greybus: connection: convert connected dev_warn() to dev_err() Failures from control-connected operations are fatal errors and must be reported with dev_err() instead of dev_warn(). Fix it. Reviewed-by: Johan Hovold Signed-off-by: Viresh Kumar [ johan: do not promote disconnected warnings, update summary ] Signed-off-by: Johan Hovold diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 62cbeb3..f89b199 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -386,9 +386,9 @@ static int gb_connection_init(struct gb_connection *connection) ret = gb_control_connected_operation(control, cport_id); if (ret) { - dev_warn(&connection->dev, - "Failed to connect CPort-%d (%d)\n", - cport_id, ret); + dev_err(&connection->dev, + "Failed to connect CPort-%d (%d)\n", + cport_id, ret); return 0; } } -- cgit v0.10.2 From 58f469a7da3c0b2e126851f850780de20182708b Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 31 Aug 2015 17:21:11 +0530 Subject: greybus: connection: no need to verify connection->protocol connection->protocol will always be valid in gb_connection_init() as it is called only from a single routine, after initializing the 'protocol' field. No need to check it again. Reviewed-by: Bryan O'Donoghue Reviewed-by: Johan Hovold Signed-off-by: Viresh Kumar Signed-off-by: Johan Hovold diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index f89b199..557fe6d 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -371,11 +371,6 @@ static int gb_connection_init(struct gb_connection *connection) int cport_id = connection->intf_cport_id; int ret; - if (!connection->protocol) { - dev_warn(&connection->dev, "init without protocol.\n"); - return 0; - } - /* * Inform Interface about Active CPorts. We don't need to do this * operation for control cport. -- cgit v0.10.2 From 4c583f42c3cc0b6ebb678f5e7ecd5374479bfc22 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 31 Aug 2015 17:21:12 +0530 Subject: greybus: connection: Propagate error properly We just got an error, propagate the exact return value instead of 0. Reviewed-by: Bryan O'Donoghue Reviewed-by: Johan Hovold Signed-off-by: Viresh Kumar Signed-off-by: Johan Hovold diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 557fe6d..8fe056d 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -384,7 +384,7 @@ static int gb_connection_init(struct gb_connection *connection) dev_err(&connection->dev, "Failed to connect CPort-%d (%d)\n", cport_id, ret); - return 0; + return ret; } } -- cgit v0.10.2 From fda2381bd2d96b4f45806e4796d558eec678e3c6 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 31 Aug 2015 17:21:13 +0530 Subject: greybus: connection: call gb_connection_exit() from gb_connection_destroy() Both the routines are always called together and in the same sequence. Rather than duplicating this at different places, make gb_connection_destroy() call gb_connection_exit(). This also makes it more sensible, as gb_connection_init() is never called directly by the users and so its its counterpart shouldn't be called directly as well. Signed-off-by: Viresh Kumar Signed-off-by: Johan Hovold diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 459c62a..5c09bcc 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -201,10 +201,8 @@ static void gb_bundle_connections_exit(struct gb_bundle *bundle) struct gb_connection *next; list_for_each_entry_safe(connection, next, &bundle->connections, - bundle_links) { - gb_connection_exit(connection); + bundle_links) gb_connection_destroy(connection); - } } /* diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 8fe056d..2987053 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -318,32 +318,6 @@ static void gb_connection_cancel_operations(struct gb_connection *connection, spin_unlock_irq(&connection->lock); } -/* - * Tear down a previously set up connection. - */ -void gb_connection_destroy(struct gb_connection *connection) -{ - struct ida *id_map; - - if (WARN_ON(!connection)) - return; - - spin_lock_irq(&gb_connections_lock); - list_del(&connection->bundle_links); - list_del(&connection->hd_links); - spin_unlock_irq(&gb_connections_lock); - - if (connection->protocol) - gb_protocol_put(connection->protocol); - connection->protocol = NULL; - - id_map = &connection->hd->cport_id_map; - ida_simple_remove(id_map, connection->hd_cport_id); - connection->hd_cport_id = CPORT_ID_BAD; - - device_unregister(&connection->dev); -} - static void gb_connection_disconnected(struct gb_connection *connection) { struct gb_control *control; @@ -420,7 +394,7 @@ disconnect: return ret; } -void gb_connection_exit(struct gb_connection *connection) +static void gb_connection_exit(struct gb_connection *connection) { if (!connection->protocol) { dev_warn(&connection->dev, "exit without protocol.\n"); @@ -441,14 +415,40 @@ void gb_connection_exit(struct gb_connection *connection) gb_connection_disconnected(connection); } +/* + * Tear down a previously set up connection. + */ +void gb_connection_destroy(struct gb_connection *connection) +{ + struct ida *id_map; + + if (WARN_ON(!connection)) + return; + + gb_connection_exit(connection); + + spin_lock_irq(&gb_connections_lock); + list_del(&connection->bundle_links); + list_del(&connection->hd_links); + spin_unlock_irq(&gb_connections_lock); + + if (connection->protocol) + gb_protocol_put(connection->protocol); + connection->protocol = NULL; + + id_map = &connection->hd->cport_id_map; + ida_simple_remove(id_map, connection->hd_cport_id); + connection->hd_cport_id = CPORT_ID_BAD; + + device_unregister(&connection->dev); +} + void gb_hd_connections_exit(struct greybus_host_device *hd) { struct gb_connection *connection; - list_for_each_entry(connection, &hd->connections, hd_links) { - gb_connection_exit(connection); + list_for_each_entry(connection, &hd->connections, hd_links) gb_connection_destroy(connection); - } } void gb_connection_bind_protocol(struct gb_connection *connection) diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index f1b5863..0b442fe 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -60,8 +60,6 @@ struct gb_connection *gb_connection_create_range(struct greybus_host_device *hd, u16 cport_id, u8 protocol_id, u32 ida_start, u32 ida_end); void gb_connection_destroy(struct gb_connection *connection); - -void gb_connection_exit(struct gb_connection *connection); void gb_hd_connections_exit(struct greybus_host_device *hd); void greybus_data_rcvd(struct greybus_host_device *hd, u16 cport_id, diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 605a088..3c89cb3 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -259,10 +259,8 @@ void greybus_remove_hd(struct greybus_host_device *hd) gb_endo_remove(hd->endo); /* Is the SVC still using the partially uninitialized connection ? */ - if (hd->initial_svc_connection) { - gb_connection_exit(hd->initial_svc_connection); + if (hd->initial_svc_connection) gb_connection_destroy(hd->initial_svc_connection); - } /* * Make sure there are no leftovers that can potentially corrupt sysfs. -- cgit v0.10.2 From 50bb9ccaa0e12823e7f225ce1571d4ae3d1f83e0 Mon Sep 17 00:00:00 2001 From: Fabien Parent Date: Mon, 31 Aug 2015 17:21:14 +0530 Subject: greybus: connection: fail to bind if connection init fails gb_connection_init() can fail and will return proper error code in that case, but the caller is ignoring it currently. Fix that by properly handling errors returned from gb_connection_init() and propagating them to callers of gb_connection_bind_protocol(). Signed-off-by: Fabien Parent Signed-off-by: Viresh Kumar Signed-off-by: Johan Hovold diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 2987053..d0642bc 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -451,19 +451,20 @@ void gb_hd_connections_exit(struct greybus_host_device *hd) gb_connection_destroy(connection); } -void gb_connection_bind_protocol(struct gb_connection *connection) +int gb_connection_bind_protocol(struct gb_connection *connection) { struct gb_protocol *protocol; + int ret; /* If we already have a protocol bound here, just return */ if (connection->protocol) - return; + return 0; protocol = gb_protocol_get(connection->protocol_id, connection->major, connection->minor); if (!protocol) - return; + return 0; connection->protocol = protocol; /* @@ -472,6 +473,14 @@ void gb_connection_bind_protocol(struct gb_connection *connection) */ if ((!connection->bundle && connection->hd_cport_id == GB_SVC_CPORT_ID) || - connection->bundle->intf->device_id != GB_DEVICE_ID_BAD) - gb_connection_init(connection); + connection->bundle->intf->device_id != GB_DEVICE_ID_BAD) { + ret = gb_connection_init(connection); + if (ret) { + gb_protocol_put(protocol); + connection->protocol = NULL; + return ret; + } + } + + return 0; } diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 0b442fe..e3ae01d 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -68,6 +68,6 @@ void gb_connection_push_timestamp(struct gb_connection *connection); int gb_connection_pop_timestamp(struct gb_connection *connection, struct timeval *tv); -void gb_connection_bind_protocol(struct gb_connection *connection); +int gb_connection_bind_protocol(struct gb_connection *connection); #endif /* __CONNECTION_H */ -- cgit v0.10.2 From 6c0d57b4e612c00b14852c2f8b179d518462ea6c Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 31 Aug 2015 17:21:15 +0530 Subject: greybus: connection: protocol can be NULL in gb_connection_exit() gb_connection_exit() is getting called from gb_connection_destroy() now, which will get called from failure path of gb_connection_create_range() (in a later commit). And at that point connection->protocol will be NULL. Don't print an error message if this happens in gb_connection_exit(). Signed-off-by: Viresh Kumar Signed-off-by: Johan Hovold diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index d0642bc..466ea36 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -396,10 +396,8 @@ disconnect: static void gb_connection_exit(struct gb_connection *connection) { - if (!connection->protocol) { - dev_warn(&connection->dev, "exit without protocol.\n"); + if (!connection->protocol) return; - } spin_lock_irq(&connection->lock); if (connection->state != GB_CONNECTION_STATE_ENABLED) { -- cgit v0.10.2 From 2111134fe413311ea2e89c7ffc66abb68ada5982 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 4 Sep 2015 15:10:09 +0530 Subject: greybus: spi: Allow spi-core to allocate bus numbers dynamically And that fixes these warnings generated with BDB: WARNING: at /home/viresh/ara/jetson-kernel-build/tegra/fs/sysfs/dir.c:530 sysfs_add_one+0xa4/0xb4() sysfs: cannot create duplicate filename '/class/spi_master/spi0' Modules linked in: gb_es2(O) gb_phy(O) greybus(O) CPU: 2 PID: 111 Comm: kworker/u8:3 Tainted: G W O 3.10.40-gf32f9c5ca7e8 #2 Workqueue: events_unbound svc_process_hotplug [greybus] [] (unwind_backtrace+0x0/0x13c) from [] (show_stack+0x18/0x1c) [] (show_stack+0x18/0x1c) from [] (warn_slowpath_common+0x5c/0x74) [] (warn_slowpath_common+0x5c/0x74) from [] (warn_slowpath_fmt+0x38/0x48) [] (warn_slowpath_fmt+0x38/0x48) from [] (sysfs_add_one+0xa4/0xb4) [] (sysfs_add_one+0xa4/0xb4) from [] (sysfs_do_create_link_sd+0xc0/0x20c) [] (sysfs_do_create_link_sd+0xc0/0x20c) from [] (device_add+0x2e8/0x5f4) [] (device_add+0x2e8/0x5f4) from [] (spi_register_master+0x15c/0x654) [] (spi_register_master+0x15c/0x654) from [] (gb_spi_connection_init+0x164/0x19c [gb_phy]) [] (gb_spi_connection_init+0x164/0x19c [gb_phy]) from [] (gb_connection_bind_protocol+0x160/0x1b4 [greybus]) [] (gb_connection_bind_protocol+0x160/0x1b4 [greybus]) from [] (gb_connection_create_range+0x228/0x2fc [greybus]) [] (gb_connection_create_range+0x228/0x2fc [greybus]) from [] (gb_connection_create+0x40/0x48 [greybus]) [] (gb_connection_create+0x40/0x48 [greybus]) from [] (gb_manifest_parse+0x61c/0x628 [greybus]) [] (gb_manifest_parse+0x61c/0x628 [greybus]) from [] (gb_interface_init+0x130/0x170 [greybus]) [] (gb_interface_init+0x130/0x170 [greybus]) from [] (svc_process_hotplug+0x214/0x258 [greybus]) [] (svc_process_hotplug+0x214/0x258 [greybus]) from [] (process_one_work+0x13c/0x454) [] (process_one_work+0x13c/0x454) from [] (worker_thread+0x140/0x3dc) [] (worker_thread+0x140/0x3dc) from [] (kthread+0xe0/0xe4) [] (kthread+0xe0/0xe4) from [] (ret_from_fork+0x14/0x20) Reported-by: Mitchell Tasman Suggested-by: Johan Hovold Signed-off-by: Viresh Kumar Signed-off-by: Johan Hovold diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index ef3cc33..e5d2166 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -299,7 +299,7 @@ static int gb_spi_connection_init(struct gb_connection *connection) if (ret) goto out_err; - master->bus_num = 0; /* How do we get controller id here? */ + master->bus_num = -1; /* Allow spi-core to allocate it dynamically */ master->num_chipselect = spi->num_chipselect; master->mode_bits = spi->mode; master->flags = spi->flags; -- cgit v0.10.2 From 8afd831ea00822fdc811ff640ef62352619d64c0 Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Fri, 4 Sep 2015 16:55:40 +0200 Subject: greybus: Greybus driver: add a new callbacks to driver Add connection_create and connection_destroy callbacks. ES2 can map a cport to a pair of endpoints. Because ES2 have only a few pair of endpoints, ES2 need to have access to some high level connection information such as protocol id to effectively map the cports. These callback will provide these information and help ES2 to map cports. Signed-off-by: Alexandre Bailon Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 466ea36..c25e570 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -262,6 +262,8 @@ gb_connection_create_range(struct greybus_host_device *hd, gb_svc_connection_create(hd->svc, hd->endo->ap_intf_id, hd_cport_id, bundle->intf->interface_id, cport_id); + if (hd->driver->connection_create) + hd->driver->connection_create(connection); } gb_connection_bind_protocol(connection); @@ -430,6 +432,9 @@ void gb_connection_destroy(struct gb_connection *connection) list_del(&connection->hd_links); spin_unlock_irq(&gb_connections_lock); + if (connection->hd->driver->connection_destroy) + connection->hd->driver->connection_destroy(connection); + if (connection->protocol) gb_protocol_put(connection->protocol); connection->protocol = NULL; diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 8e215f8..9f2eb1f 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -75,6 +75,8 @@ struct greybus_host_device; struct greybus_host_driver { size_t hd_priv_size; + void (*connection_create)(struct gb_connection *connection); + void (*connection_destroy)(struct gb_connection *connection); int (*message_send)(struct greybus_host_device *hd, u16 dest_cport_id, struct gb_message *message, gfp_t gfp_mask); void (*message_cancel)(struct gb_message *message); -- cgit v0.10.2 From 566830fdb1b666b5159709a9e66ed5f2c85f58b7 Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Fri, 4 Sep 2015 16:55:42 +0200 Subject: greybus: es2: update the bulk_ep_set value accepted by map_to_cpor_ep() The endpoint set 0 is currently considered as invalid. But 0 mean muxed cports on ep1 and ep2, then it must not return -EINVAL. Signed-off-by: Alexandre Bailon Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index d6bd210..96090aa 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -149,7 +149,7 @@ int map_cport_to_ep(struct es1_ap_dev *es1, int retval; struct cport_to_ep *cport_to_ep; - if (bulk_ep_set == 0 || bulk_ep_set >= NUM_BULKS) + if (bulk_ep_set < 0 || bulk_ep_set >= NUM_BULKS) return -EINVAL; if (cport_id >= es1->hd->num_cports) return -EINVAL; -- cgit v0.10.2 From ff477d073f2e71a1fa59f86cb44bd9d48674a71b Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Fri, 4 Sep 2015 16:53:31 +0100 Subject: greybus: loopback: make sure to list_del on connection_exit gb_loopback_connection_exit does a kfree on a data structure associated with a loopback connection but fails to do a corresponding list_del(). On subsequent enumerations this can lead to a NULL pointer dereference. Each list_add in gb_loopback_connection_init() must have a corresponding list_del in gb_loopback_connection_exit(), this patch adds the relevant list_del() and ensures that an appropriate mutex protecting gb_dev.list is held while doing so. Signed-off-by: Bryan O'Donoghue Reported-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 8dd648c..231d1d4 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -944,18 +944,23 @@ static void gb_loopback_connection_exit(struct gb_connection *connection) struct gb_loopback *gb = connection->private; struct kobject *kobj = &connection->bundle->intf->module->dev.kobj; - gb_dev.count--; - connection->private = NULL; if (!IS_ERR_OR_NULL(gb->task)) kthread_stop(gb->task); + mutex_lock(&gb_dev.mutex); + + connection->private = NULL; kfifo_free(&gb->kfifo_lat); kfifo_free(&gb->kfifo_ts); if (!gb_dev.count) sysfs_remove_groups(kobj, loopback_dev_groups); sysfs_remove_groups(&connection->dev.kobj, loopback_con_groups); debugfs_remove(gb->file); + list_del(&gb->entry); kfree(gb); + gb_dev.count--; + + mutex_unlock(&gb_dev.mutex); } static struct gb_protocol loopback_protocol = { -- cgit v0.10.2 From 98d7fbcad90b43f4e4fe03ef3261dbdcb6fe220f Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 7 Sep 2015 16:01:19 +0530 Subject: greybus: manifest: don't reject the interface on failing to initialize a cport A 'bundle' represents a device in greybus. It may require multiple cports for its functioning. If we fail to setup any cport of a bundle, we better reject the complete bundle as the device may not be able to function properly then. But, failing to setup a cport of bundle X doesn't mean that the device corresponding to bundle Y will not work properly. Bundles should be treated as separate independent devices. While parsing manifest for an interface, treat bundles as separate entities and don't reject entire interface and its bundles on failing to initialize a cport. But make sure the bundle which needs the cport, gets destroyed properly. We now release the bundle descriptor before parsing the cports, but that shouldn't make any difference. Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 559b2ee..eda0f55 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -273,6 +273,7 @@ static u32 gb_manifest_parse_bundles(struct gb_interface *intf) struct gb_bundle *bundle; struct gb_bundle *bundle_next; u32 count = 0; + u8 bundle_id; list_for_each_entry_safe(desc, next, &intf->manifest_descs, links) { struct greybus_descriptor_bundle *desc_bundle; @@ -282,9 +283,10 @@ static u32 gb_manifest_parse_bundles(struct gb_interface *intf) /* Found one. Set up its bundle structure*/ desc_bundle = desc->data; + bundle_id = desc_bundle->id; /* Don't recreate bundle for control cport */ - if (desc_bundle->id == GB_CONTROL_BUNDLE_ID) { + if (bundle_id == GB_CONTROL_BUNDLE_ID) { /* This should have class set to control class */ if (desc_bundle->class != GREYBUS_CLASS_CONTROL) { dev_err(&intf->dev, @@ -301,22 +303,47 @@ static u32 gb_manifest_parse_bundles(struct gb_interface *intf) if (desc_bundle->class == GREYBUS_CLASS_CONTROL) { dev_err(&intf->dev, "bundle 0x%02x cannot use control class\n", - desc_bundle->id); + bundle_id); goto cleanup; } - bundle = gb_bundle_create(intf, desc_bundle->id, - desc_bundle->class); + bundle = gb_bundle_create(intf, bundle_id, desc_bundle->class); if (!bundle) goto cleanup; parse_cports: - /* Now go set up this bundle's functions and cports */ - if (!gb_manifest_parse_cports(bundle)) - goto cleanup; - /* Done with this bundle descriptor */ release_manifest_descriptor(desc); + + /* + * Now go set up this bundle's functions and cports. + * + * A 'bundle' represents a device in greybus. It may require + * multiple cports for its functioning. If we fail to setup any + * cport of a bundle, we better reject the complete bundle as + * the device may not be able to function properly then. + * + * But, failing to setup a cport of bundle X doesn't mean that + * the device corresponding to bundle Y will not work properly. + * Bundles should be treated as separate independent devices. + * + * While parsing manifest for an interface, treat bundles as + * separate entities and don't reject entire interface and its + * bundles on failing to initialize a cport. But make sure the + * bundle which needs the cport, gets destroyed properly. + * + * The control bundle and its connections are special. The + * entire manifest should be rejected if we failed to initialize + * the control bundle/connections. + */ + if (!gb_manifest_parse_cports(bundle)) { + if (bundle_id == GB_CONTROL_BUNDLE_ID) + goto cleanup; + + gb_bundle_destroy(bundle); + continue; + } + count++; } -- cgit v0.10.2 From 4317f874f48d14fbd5b1d408336843dbe129ab3e Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 7 Sep 2015 16:01:20 +0530 Subject: greybus: manifest: release cport descriptors to avoid 'excess descriptors' warning If we fail to initialize a cport of a bundle, we abort the entire bundle. But that leads to following (unnecessary) warnings as few of the cport descriptors, belonging to the aborted bundle were never parsed: "greybus: excess descriptors in interface manifest" Fix that by releasing all cport descriptors for the aborted bundle. Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index eda0f55..2264ec59 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -258,6 +258,19 @@ print_error_exit: GREYBUS_PROTOCOL_CONTROL); exit: + /* + * Free all cports for this bundle to avoid 'excess descriptors' + * warnings. + */ + list_for_each_entry_safe(desc, next, &intf->manifest_descs, links) { + struct greybus_descriptor_cport *desc_cport = desc->data; + + if (desc->type != GREYBUS_TYPE_CPORT) + continue; + if (desc_cport->bundle == bundle_id) + release_manifest_descriptor(desc); + } + return 0; /* Error; count should also be 0 */ } -- cgit v0.10.2 From a1163fae63079f01c24d9c062b1e22e5ada89f91 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 7 Sep 2015 16:01:21 +0530 Subject: greybus: connection: call gb_svc_connection_create() from gb_connection_init() There are two operations which very much work together: - AP asks the SVC to create a connection between a cport of AP and a cport of module. - AP tells the module that the connection is created. Its better (logically) to do these two operations together and so call gb_svc_connection_create() from gb_connection_init() instead. Also check its return value properly. Reviewed-by: Johan Hovold Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index c25e570..973d841 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -258,14 +258,6 @@ gb_connection_create_range(struct greybus_host_device *hd, spin_unlock_irq(&gb_connections_lock); - if (hd_cport_id != GB_SVC_CPORT_ID) { - gb_svc_connection_create(hd->svc, - hd->endo->ap_intf_id, hd_cport_id, - bundle->intf->interface_id, cport_id); - if (hd->driver->connection_create) - hd->driver->connection_create(connection); - } - gb_connection_bind_protocol(connection); if (!connection->protocol) dev_warn(&connection->dev, @@ -345,9 +337,30 @@ static void gb_connection_disconnected(struct gb_connection *connection) static int gb_connection_init(struct gb_connection *connection) { int cport_id = connection->intf_cport_id; + struct greybus_host_device *hd = connection->hd; int ret; /* + * Request the SVC to create a connection from AP's cport to interface's + * cport. + */ + if (connection->hd_cport_id != GB_SVC_CPORT_ID) { + ret = gb_svc_connection_create(hd->svc, + hd->endo->ap_intf_id, connection->hd_cport_id, + connection->bundle->intf->interface_id, + cport_id); + if (ret) { + dev_err(&connection->dev, + "%s: Failed to create svc connection (%d)\n", + __func__, ret); + return ret; + } + + if (hd->driver->connection_create) + hd->driver->connection_create(connection); + } + + /* * Inform Interface about Active CPorts. We don't need to do this * operation for control cport. */ -- cgit v0.10.2 From 1b7a9cd5a54536af5a97738097780369779c62d9 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 7 Sep 2015 16:01:22 +0530 Subject: greybus: connection: destroy svc connection on connection exit or errors While initializing a connection, the AP requests the SVC to create a connection between a cport on AP and a cport on the Module. The opposite of that is missing, when connection is destroyed or if errors occur after creating the connection. Fix it. Reviewed-by: Johan Hovold Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 973d841..de3962a 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -312,6 +312,19 @@ static void gb_connection_cancel_operations(struct gb_connection *connection, spin_unlock_irq(&connection->lock); } +static void +gb_connection_svc_connection_destroy(struct gb_connection *connection) +{ + if (connection->hd_cport_id == GB_SVC_CPORT_ID) + return; + + gb_svc_connection_destroy(connection->hd->svc, + connection->hd->endo->ap_intf_id, + connection->hd_cport_id, + connection->bundle->intf->interface_id, + connection->intf_cport_id); +} + static void gb_connection_disconnected(struct gb_connection *connection) { struct gb_control *control; @@ -373,7 +386,7 @@ static int gb_connection_init(struct gb_connection *connection) dev_err(&connection->dev, "Failed to connect CPort-%d (%d)\n", cport_id, ret); - return ret; + goto svc_destroy; } } @@ -406,6 +419,9 @@ disconnect: spin_unlock_irq(&connection->lock); gb_connection_disconnected(connection); +svc_destroy: + gb_connection_svc_connection_destroy(connection); + return ret; } @@ -426,6 +442,7 @@ static void gb_connection_exit(struct gb_connection *connection) connection->protocol->connection_exit(connection); gb_connection_disconnected(connection); + gb_connection_svc_connection_destroy(connection); } /* -- cgit v0.10.2 From fb198317fd89ec02582ffd4ca318ec088d06c74e Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 7 Sep 2015 16:01:23 +0530 Subject: greybus: connection: Call connection_destroy() from gb_connection_svc_connection_destroy() connection_create() is called right after svc is requested to create the connection and so connection_destroy() must be called just before we request the SVC to destroy the connection. Over that, this fixes the inconsistency where connection_create() is called for all connections except SVC connection, but connection_destroy() is called always. Acked-by: Alexandre Bailon Fixes: 5313ca607afb ("Greybus driver: add a new callbacks to driver") Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index de3962a..e1a7705 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -318,6 +318,9 @@ gb_connection_svc_connection_destroy(struct gb_connection *connection) if (connection->hd_cport_id == GB_SVC_CPORT_ID) return; + if (connection->hd->driver->connection_destroy) + connection->hd->driver->connection_destroy(connection); + gb_svc_connection_destroy(connection->hd->svc, connection->hd->endo->ap_intf_id, connection->hd_cport_id, @@ -462,9 +465,6 @@ void gb_connection_destroy(struct gb_connection *connection) list_del(&connection->hd_links); spin_unlock_irq(&gb_connections_lock); - if (connection->hd->driver->connection_destroy) - connection->hd->driver->connection_destroy(connection); - if (connection->protocol) gb_protocol_put(connection->protocol); connection->protocol = NULL; -- cgit v0.10.2 From 5a5296bb8d67e90866d352b93ecce95d08b77fc0 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 7 Sep 2015 16:01:24 +0530 Subject: greybus: Add flags to struct gb_protocol This helps in removing special per-protocol code, with the help of generic flags passed by protocol drivers. Reviewed-by: Johan Hovold Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index e1a7705..3dcbb78 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -315,7 +315,7 @@ static void gb_connection_cancel_operations(struct gb_connection *connection, static void gb_connection_svc_connection_destroy(struct gb_connection *connection) { - if (connection->hd_cport_id == GB_SVC_CPORT_ID) + if (connection->protocol->flags & GB_PROTOCOL_SKIP_SVC_CONNECTION) return; if (connection->hd->driver->connection_destroy) @@ -334,12 +334,8 @@ static void gb_connection_disconnected(struct gb_connection *connection) int cport_id = connection->intf_cport_id; int ret; - /* - * Inform Interface about In-active CPorts. We don't need to do this - * operation for control cport. - */ - if ((cport_id == GB_CONTROL_CPORT_ID) || - (connection->hd_cport_id == GB_SVC_CPORT_ID)) + /* Inform Interface about inactive CPorts */ + if (connection->protocol->flags & GB_PROTOCOL_SKIP_CONTROL_DISCONNECTED) return; control = connection->bundle->intf->control; @@ -354,13 +350,14 @@ static int gb_connection_init(struct gb_connection *connection) { int cport_id = connection->intf_cport_id; struct greybus_host_device *hd = connection->hd; + struct gb_protocol *protocol = connection->protocol; int ret; /* * Request the SVC to create a connection from AP's cport to interface's * cport. */ - if (connection->hd_cport_id != GB_SVC_CPORT_ID) { + if (!(protocol->flags & GB_PROTOCOL_SKIP_SVC_CONNECTION)) { ret = gb_svc_connection_create(hd->svc, hd->endo->ap_intf_id, connection->hd_cport_id, connection->bundle->intf->interface_id, @@ -375,13 +372,8 @@ static int gb_connection_init(struct gb_connection *connection) if (hd->driver->connection_create) hd->driver->connection_create(connection); } - - /* - * Inform Interface about Active CPorts. We don't need to do this - * operation for control cport. - */ - if (cport_id != GB_CONTROL_CPORT_ID && - connection->hd_cport_id != GB_SVC_CPORT_ID) { + /* Inform Interface about active CPorts */ + if (!(protocol->flags & GB_PROTOCOL_SKIP_CONTROL_CONNECTED)) { struct gb_control *control = connection->bundle->intf->control; ret = gb_control_connected_operation(control, cport_id); @@ -402,7 +394,7 @@ static int gb_connection_init(struct gb_connection *connection) * Request protocol version supported by the module. We don't need to do * this for SVC as that is initiated by the SVC. */ - if (connection->hd_cport_id != GB_SVC_CPORT_ID) { + if (!(protocol->flags & GB_PROTOCOL_SKIP_VERSION)) { ret = gb_protocol_get_version(connection); if (ret) { dev_err(&connection->dev, @@ -412,7 +404,7 @@ static int gb_connection_init(struct gb_connection *connection) } } - ret = connection->protocol->connection_init(connection); + ret = protocol->connection_init(connection); if (!ret) return 0; @@ -505,7 +497,7 @@ int gb_connection_bind_protocol(struct gb_connection *connection) * active device, so bring up the connection at the same time. */ if ((!connection->bundle && - connection->hd_cport_id == GB_SVC_CPORT_ID) || + protocol->flags & GB_PROTOCOL_NO_BUNDLE) || connection->bundle->intf->device_id != GB_DEVICE_ID_BAD) { ret = gb_connection_init(connection); if (ret) { diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index e675c5c..c092beb 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -130,5 +130,7 @@ static struct gb_protocol control_protocol = { .connection_init = gb_control_connection_init, .connection_exit = gb_control_connection_exit, .request_recv = gb_control_request_recv, + .flags = GB_PROTOCOL_SKIP_CONTROL_CONNECTED | + GB_PROTOCOL_SKIP_CONTROL_DISCONNECTED, }; gb_builtin_protocol_driver(control_protocol); diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index 8d55a4a..d856885 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -13,6 +13,13 @@ struct gb_connection; struct gb_operation; +/* Possible flags for protocol drivers */ +#define GB_PROTOCOL_SKIP_CONTROL_CONNECTED BIT(0) /* Don't sent connected requests */ +#define GB_PROTOCOL_SKIP_CONTROL_DISCONNECTED BIT(1) /* Don't sent disconnected requests */ +#define GB_PROTOCOL_NO_BUNDLE BIT(2) /* Protocol May have a bundle-less connection */ +#define GB_PROTOCOL_SKIP_VERSION BIT(3) /* Don't send get_version() requests */ +#define GB_PROTOCOL_SKIP_SVC_CONNECTION BIT(4) /* Don't send SVC connection requests */ + typedef int (*gb_connection_init_t)(struct gb_connection *); typedef void (*gb_connection_exit_t)(struct gb_connection *); typedef int (*gb_request_recv_t)(u8, struct gb_operation *); @@ -27,6 +34,7 @@ struct gb_protocol { u8 major; u8 minor; u8 count; + unsigned long flags; struct list_head links; /* global list */ diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index b32519a..21dafcc 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -524,5 +524,10 @@ static struct gb_protocol svc_protocol = { .connection_init = gb_svc_connection_init, .connection_exit = gb_svc_connection_exit, .request_recv = gb_svc_request_recv, + .flags = GB_PROTOCOL_SKIP_CONTROL_CONNECTED | + GB_PROTOCOL_SKIP_CONTROL_DISCONNECTED | + GB_PROTOCOL_NO_BUNDLE | + GB_PROTOCOL_SKIP_VERSION | + GB_PROTOCOL_SKIP_SVC_CONNECTION, }; gb_builtin_protocol_driver(svc_protocol); -- cgit v0.10.2 From bb10685246b4a4885e569306eca0bb64ded1b4f0 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 7 Sep 2015 16:01:25 +0530 Subject: greybus: svc: No need of per-direction route-create requests The route-create request creates bi-directional routes and there is no need to make separate calls for setting up routes on both the directions. Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 21dafcc..71a4869 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -148,6 +148,7 @@ void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, } EXPORT_SYMBOL_GPL(gb_svc_connection_destroy); +/* Creates bi-directional routes between the devices */ static int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, u8 intf2_id, u8 dev2_id) { @@ -305,14 +306,6 @@ static void svc_process_hotplug(struct work_struct *work) goto ida_put; } - ret = gb_svc_route_create(svc, intf_id, device_id, hd->endo->ap_intf_id, - GB_DEVICE_ID_AP); - if (ret) { - dev_err(dev, "%s: Route create operation failed, interface %hhu device_id %hhu (%d)\n", - __func__, intf_id, device_id, ret); - goto ida_put; - } - ret = gb_interface_init(intf, device_id); if (ret) { dev_err(dev, "%s: Failed to initialize interface, interface %hhu device_id %hhu (%d)\n", -- cgit v0.10.2 From 0a020570ed2f7817998870a9451526ffe492c44a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 7 Sep 2015 18:05:26 +0530 Subject: greybus: svc: destroy the route on module hot-unplug We created two-way routes between the AP and module's interface on hotplug, and forgot to remove them on hot-unplug. The same is also required while handling errors in hotplug case. Reviewed-by: Johan Hovold Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index c8bfced..77a7c49 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -743,6 +743,7 @@ struct gb_spi_transfer_response { #define GB_SVC_TYPE_CONN_CREATE 0x07 #define GB_SVC_TYPE_CONN_DESTROY 0x08 #define GB_SVC_TYPE_ROUTE_CREATE 0x0b +#define GB_SVC_TYPE_ROUTE_DESTROY 0x0c /* SVC version request/response have same payload as gb_protocol_version_response */ @@ -806,6 +807,12 @@ struct gb_svc_route_create_request { } __packed; /* route create response has no payload */ +struct gb_svc_route_destroy_request { + __u8 intf1_id; + __u8 intf2_id; +} __packed; +/* route destroy response has no payload */ + /* RAW */ diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 71a4869..73fad4a 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -163,6 +163,24 @@ static int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, &request, sizeof(request), NULL, 0); } +/* Destroys bi-directional routes between the devices */ +static void gb_svc_route_destroy(struct gb_svc *svc, u8 intf1_id, u8 intf2_id) +{ + struct gb_svc_route_destroy_request request; + int ret; + + request.intf1_id = intf1_id; + request.intf2_id = intf2_id; + + ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_ROUTE_DESTROY, + &request, sizeof(request), NULL, 0); + if (ret) { + dev_err(&svc->connection->dev, + "failed to destroy route (%hhx %hhx) %d\n", + intf1_id, intf2_id, ret); + } +} + static int gb_svc_version_request(struct gb_operation *op) { struct gb_connection *connection = op->connection; @@ -303,18 +321,20 @@ static void svc_process_hotplug(struct work_struct *work) if (ret) { dev_err(dev, "%s: Route create operation failed, interface %hhu device_id %hhu (%d)\n", __func__, intf_id, device_id, ret); - goto ida_put; + goto svc_id_free; } ret = gb_interface_init(intf, device_id); if (ret) { dev_err(dev, "%s: Failed to initialize interface, interface %hhu device_id %hhu (%d)\n", __func__, intf_id, device_id, ret); - goto svc_id_free; + goto destroy_route; } goto free_svc_hotplug; +destroy_route: + gb_svc_route_destroy(svc, hd->endo->ap_intf_id, intf_id); svc_id_free: /* * XXX Should we tell SVC that this id doesn't belong to interface @@ -369,6 +389,7 @@ static int gb_svc_intf_hot_unplug_recv(struct gb_operation *op) struct gb_svc_intf_hot_unplug_request *hot_unplug = request->payload; struct greybus_host_device *hd = op->connection->hd; struct device *dev = &op->connection->dev; + struct gb_svc *svc = op->connection->private; u8 device_id; struct gb_interface *intf; u8 intf_id; @@ -391,6 +412,12 @@ static int gb_svc_intf_hot_unplug_recv(struct gb_operation *op) device_id = intf->device_id; gb_interface_remove(hd, intf_id); + + /* + * Destroy the two-way route between the AP and the interface. + */ + gb_svc_route_destroy(svc, hd->endo->ap_intf_id, intf_id); + ida_simple_remove(&greybus_svc_device_id_map, device_id); return 0; -- cgit v0.10.2 From 8552ca0f3634bf6aaf8f752fb9a73652326117eb Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 7 Sep 2015 17:56:58 +0530 Subject: greybus: connection: Add sysfs 'ap_cport_id' file for connections Its a very useful piece of information, i.e. the cport id of the AP to which the cport of the module is connected, and is required lots of times. It isn't known in advance as it is allocated at runtime. This patch creates another file 'ap_cport_id', only for the connection directories, which will give the cport id of the AP. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 808fde9..acc4054 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -126,6 +126,14 @@ Description: 3 - error 4 - destroying +What: /sys/bus/greybus/device/.../ap_cport_id +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The cport ID of the AP, to which cport of the module is + connected. + What: /sys/bus/greybus/device/.../protocol_id Date: October 2015 KernelVersion: 4.XX diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 3dcbb78..dc45298 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -116,9 +116,18 @@ protocol_id_show(struct device *dev, struct device_attribute *attr, char *buf) } static DEVICE_ATTR_RO(protocol_id); +static ssize_t +ap_cport_id_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct gb_connection *connection = to_gb_connection(dev); + return sprintf(buf, "%hu\n", connection->hd_cport_id); +} +static DEVICE_ATTR_RO(ap_cport_id); + static struct attribute *connection_attrs[] = { &dev_attr_state.attr, &dev_attr_protocol_id.attr, + &dev_attr_ap_cport_id.attr, NULL, }; -- cgit v0.10.2 From 6de00a5f32e09b58879175f2942ebeac699d3534 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 14 Sep 2015 10:48:39 +0100 Subject: greybus: loopback: ensure count decrement happens before sysfs_remove_groups This patches fixes a case where gb_dev.count is decremented too late in the exit() routine. Signed-off-by: Bryan O'Donoghue Reported-by: Viresh Kumar Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 231d1d4..33c21cf 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -952,14 +952,13 @@ static void gb_loopback_connection_exit(struct gb_connection *connection) connection->private = NULL; kfifo_free(&gb->kfifo_lat); kfifo_free(&gb->kfifo_ts); + gb_dev.count--; if (!gb_dev.count) sysfs_remove_groups(kobj, loopback_dev_groups); sysfs_remove_groups(&connection->dev.kobj, loopback_con_groups); debugfs_remove(gb->file); list_del(&gb->entry); kfree(gb); - gb_dev.count--; - mutex_unlock(&gb_dev.mutex); } -- cgit v0.10.2 From 29f020290d8897e3ed6ed8a8f8938c0b8545bbcd Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 14 Sep 2015 10:48:40 +0100 Subject: greybus: loopback: hold a coarse lock while init/exit run This patch holds gb_dev.mutex for the duration of init and exit to reduce complexity while ensuring that init and exit run atomically with respect to slave threads @ gb_loopback_fn(). Signed-off-by: Bryan O'Donoghue Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 33c21cf..7e1f527 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -864,21 +864,18 @@ static int gb_loopback_connection_init(struct gb_connection *connection) gb_dev.root, &gb_dev, &gb_loopback_debugfs_dev_latency_ops); retval = sysfs_create_groups(kobj, loopback_dev_groups); - if (retval) { - mutex_unlock(&gb_dev.mutex); + if (retval) goto out_sysfs; - } + /* Calculate maximum payload */ gb_dev.size_max = gb_operation_get_payload_size_max(connection); if (gb_dev.size_max <= sizeof(struct gb_loopback_transfer_request)) { retval = -EINVAL; - mutex_unlock(&gb_dev.mutex); goto out_sysfs; } gb_dev.size_max -= sizeof(struct gb_loopback_transfer_request); } - mutex_unlock(&gb_dev.mutex); /* Create per-connection sysfs and debugfs data-points */ snprintf(name, sizeof(name), "raw_latency_endo0:%d:%d:%d:%d", @@ -916,10 +913,9 @@ static int gb_loopback_connection_init(struct gb_connection *connection) goto out_kfifo1; } - mutex_lock(&gb_dev.mutex); list_add_tail(&gb->entry, &gb_dev.list); - mutex_unlock(&gb_dev.mutex); gb_dev.count++; + mutex_unlock(&gb_dev.mutex); return 0; out_kfifo1: @@ -934,6 +930,7 @@ out_sysfs_dev: debugfs_remove(gb->file); connection->private = NULL; out_sysfs: + mutex_unlock(&gb_dev.mutex); kfree(gb); return retval; -- cgit v0.10.2 From 5f3e0d17a3938ee253b6e6b7d16033121645b3a4 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 14 Sep 2015 10:48:41 +0100 Subject: greybus: loopback: exit kfree after mutex release init doesn't have a lock for kzalloc so exit shouldn't have lock with the corresponding kfree. Signed-off-by: Bryan O'Donoghue Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 7e1f527..745490a 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -955,8 +955,8 @@ static void gb_loopback_connection_exit(struct gb_connection *connection) sysfs_remove_groups(&connection->dev.kobj, loopback_con_groups); debugfs_remove(gb->file); list_del(&gb->entry); - kfree(gb); mutex_unlock(&gb_dev.mutex); + kfree(gb); } static struct gb_protocol loopback_protocol = { -- cgit v0.10.2 From c7ea5ed6f2790240a8ddaf98905a9465a37e839e Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 14 Sep 2015 10:48:42 +0100 Subject: greybus: loopback: ensure debugfs entires are cleaned up on exit bdd4bba4 ('greybus/loopback: add module level sys/debug fs data points') added a debugfs entry attached to gb_dev but omitted the cleanup on gb_init error and gb_exit. This patchs fixes the missing debugfs_remove(). Signed-off-by: Bryan O'Donoghue Reported-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 745490a..8bfeec8 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -34,6 +34,7 @@ struct gb_loopback_stats { struct gb_loopback_device { struct dentry *root; + struct dentry *file; u32 count; struct kfifo kfifo; @@ -860,9 +861,9 @@ static int gb_loopback_connection_init(struct gb_connection *connection) if (!gb_dev.count) { snprintf(name, sizeof(name), "raw_latency_endo0:%d", connection->bundle->intf->module->module_id); - debugfs_create_file(name, S_IFREG | S_IRUGO, - gb_dev.root, &gb_dev, - &gb_loopback_debugfs_dev_latency_ops); + gb_dev.file = debugfs_create_file(name, S_IFREG | S_IRUGO, + gb_dev.root, &gb_dev, + &gb_loopback_debugfs_dev_latency_ops); retval = sysfs_create_groups(kobj, loopback_dev_groups); if (retval) goto out_sysfs; @@ -925,8 +926,10 @@ out_kfifo0: out_sysfs_conn: sysfs_remove_groups(&connection->dev.kobj, loopback_con_groups); out_sysfs_dev: - if (!gb_dev.count) + if (!gb_dev.count) { sysfs_remove_groups(kobj, loopback_dev_groups); + debugfs_remove(gb_dev.file); + } debugfs_remove(gb->file); connection->private = NULL; out_sysfs: @@ -950,8 +953,10 @@ static void gb_loopback_connection_exit(struct gb_connection *connection) kfifo_free(&gb->kfifo_lat); kfifo_free(&gb->kfifo_ts); gb_dev.count--; - if (!gb_dev.count) + if (!gb_dev.count) { sysfs_remove_groups(kobj, loopback_dev_groups); + debugfs_remove(gb_dev.file); + } sysfs_remove_groups(&connection->dev.kobj, loopback_con_groups); debugfs_remove(gb->file); list_del(&gb->entry); -- cgit v0.10.2 From 909cdeb5d81926bb294394919ba84bf9b98d5744 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 14 Sep 2015 10:48:43 +0100 Subject: greybus: loopback: ensure sysfs entries are cleaned up on exit bdd4bba4 ('greybus/loopback: add module level sys/debug fs data points') added a sysfs entry attached to gb_dev but missed the jump to out_sysfs_dev This patchs fixes the missing jump to out_sysfs_dev. Signed-off-by: Bryan O'Donoghue Reported-by: Viresh Kumar Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 8bfeec8..338522a 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -873,7 +873,7 @@ static int gb_loopback_connection_init(struct gb_connection *connection) if (gb_dev.size_max <= sizeof(struct gb_loopback_transfer_request)) { retval = -EINVAL; - goto out_sysfs; + goto out_sysfs_dev; } gb_dev.size_max -= sizeof(struct gb_loopback_transfer_request); } -- cgit v0.10.2 From f2cfa7043940cdda5c9e945b1cf5c66da172bc33 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 14 Sep 2015 10:48:44 +0100 Subject: greybus: loopback: convert pr_info to dev_err This patch fixes and invalid use of pr_info() in favour of dev_err(); Signed-off-by: Bryan O'Donoghue Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 338522a..a9b901f 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -450,7 +450,7 @@ static int gb_loopback_transfer(struct gb_loopback *gb, u32 len) goto gb_error; if (memcmp(request->data, response->data, len)) { - pr_info("%s: Loopback Data doesn't match\n", __func__); + dev_err(&gb->connection->dev, "Loopback Data doesn't match\n"); retval = -EREMOTEIO; } -- cgit v0.10.2 From 4a655ad4c2b83815ccab5057e29bf0f6c981a94e Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 14 Sep 2015 10:48:45 +0100 Subject: greybus: loopback: add response len to loopback protocol This patch adds a len field to the loopback protocol. This field is validated in gb_loopback_transfer() and stuffed in gb_loopback_request_recv(). Signed-off-by: Bryan O'Donoghue Reviewed-by: Patrick Titiano Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 77a7c49..76fea9a 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -917,6 +917,7 @@ struct gb_loopback_transfer_request { } __packed; struct gb_loopback_transfer_response { + __le32 len; __u8 data[0]; } __packed; diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index a9b901f..ba65457 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -524,6 +524,7 @@ static int gb_loopback_request_recv(u8 type, struct gb_operation *operation) return -ENOMEM; } response = operation->response->payload; + response->len = cpu_to_le32(len); memcpy(response->data, request->data, len); } return 0; -- cgit v0.10.2 From 5015115def3ed9907fb018180be969cf2f2f116d Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 14 Sep 2015 10:48:46 +0100 Subject: greybus: loopback: sort list of connections for masking purposes In user-space we specify a list of connections as a bit-mask with the assumption that a list such is indexed as indicated below. end0:3:3:1:1 = 1 end0:3:3:2:3 = 2 end0:3:3:3:4 = 4 Current code assigns bitmask ids based on the order of discovery, however user-space has no idea what the order of discovery is. This patch sorts the linked list of connections associated with the loopback driver and assigns a bit-id based on the sorted list - not the order of discovery. This change therefore enforces the end-users idea that end0:3:3:1:1 above is always denoted by bit 1 - even if from the AP's perspective it was the last entry discovered. Signed-off-by: Bryan O'Donoghue Reviewed-by: Patrick Titiano Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index ba65457..a62e122 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -843,6 +844,50 @@ static const struct file_operations gb_loopback_debugfs_dev_latency_ops = { .release = single_release, }; +static int gb_loopback_bus_id_compare(void *priv, struct list_head *lha, + struct list_head *lhb) +{ + struct gb_loopback *a = list_entry(lha, struct gb_loopback, entry); + struct gb_loopback *b = list_entry(lhb, struct gb_loopback, entry); + struct gb_connection *ca = a->connection; + struct gb_connection *cb = b->connection; + + if (ca->bundle->intf->module->module_id < + cb->bundle->intf->module->module_id) + return -1; + if (cb->bundle->intf->module->module_id < + ca->bundle->intf->module->module_id) + return 1; + if (ca->bundle->intf->interface_id < cb->bundle->intf->interface_id) + return -1; + if (cb->bundle->intf->interface_id < ca->bundle->intf->interface_id) + return 1; + if (ca->bundle->id < cb->bundle->id) + return -1; + if (cb->bundle->id < ca->bundle->id) + return 1; + if (ca->intf_cport_id < cb->intf_cport_id) + return -1; + else if (cb->intf_cport_id < ca->intf_cport_id) + return 1; + + return 0; +} + +static void gb_loopback_insert_id(struct gb_loopback *gb) +{ + struct gb_loopback *gb_list; + u32 new_lbid = 0; + + /* perform an insertion sort */ + list_add_tail(&gb->entry, &gb_dev.list); + list_sort(NULL, &gb_dev.list, gb_loopback_bus_id_compare); + list_for_each_entry(gb_list, &gb_dev.list, entry) { + gb_list->lbid = 1 << new_lbid; + new_lbid++; + } +} + #define DEBUGFS_NAMELEN 32 static int gb_loopback_connection_init(struct gb_connection *connection) @@ -908,14 +953,13 @@ static int gb_loopback_connection_init(struct gb_connection *connection) /* Fork worker thread */ mutex_init(&gb->mutex); - gb->lbid = 1 << gb_dev.count; gb->task = kthread_run(gb_loopback_fn, gb, "gb_loopback"); if (IS_ERR(gb->task)) { retval = PTR_ERR(gb->task); goto out_kfifo1; } - list_add_tail(&gb->entry, &gb_dev.list); + gb_loopback_insert_id(gb); gb_dev.count++; mutex_unlock(&gb_dev.mutex); return 0; -- cgit v0.10.2 From fbb8edbafe1525c4168108a46c1134f5a7cd27c4 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 14 Sep 2015 10:48:47 +0100 Subject: greybus: loopback: add gb_loopback_operation_sync In order to extract timestamps from gb_message instead of gb_connection we will need access to the gb_operation structure. A first step to that is to create our own gb_loopback_operation_sync which will call gb_operation_request_send_sync() directly. Once loopback is using this function internally it will be possible to convert to gb_message based timestamps and drop gb_connection based timestamps in two seperate patches. Signed-off-by: Bryan O'Donoghue Reviewed-by: Patrick Titiano Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index a62e122..6155b50 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -380,22 +380,43 @@ static int gb_loopback_active(struct gb_loopback *gb) return (gb_dev.mask == 0 || (gb_dev.mask & gb->lbid)); } -static int gb_loopback_sink(struct gb_loopback *gb, u32 len) +static int gb_loopback_operation_sync(struct gb_loopback *gb, int type, + void *request, int request_size, + void *response, int response_size) { + struct gb_operation *operation; struct timeval ts, te; - struct gb_loopback_transfer_request *request; - int retval; - - request = kmalloc(len + sizeof(*request), GFP_KERNEL); - if (!request) - return -ENOMEM; - - request->len = cpu_to_le32(len); + int ret; do_gettimeofday(&ts); - retval = gb_operation_sync(gb->connection, GB_LOOPBACK_TYPE_SINK, - request, len + sizeof(*request), NULL, 0); + operation = gb_operation_create(gb->connection, type, request_size, + response_size, GFP_KERNEL); + if (!operation) { + ret = -ENOMEM; + goto error; + } + if (request_size) + memcpy(operation->request->payload, request, request_size); + + ret = gb_operation_request_send_sync(operation); + if (ret) { + dev_err(&gb->connection->dev, + "synchronous operation failed: %d\n", ret); + } else { + if (response_size == operation->response->payload_size) { + memcpy(response, operation->response->payload, + response_size); + } else { + dev_err(&gb->connection->dev, + "response size %zu expected %d\n", + operation->response->payload_size, + response_size); + } + } + gb_operation_destroy(operation); + +error: do_gettimeofday(&te); /* Calculate the total time the message took */ @@ -407,14 +428,28 @@ static int gb_loopback_sink(struct gb_loopback *gb, u32 len) gb_connection_pop_timestamp(gb->connection, &te); gb->elapsed_nsecs_gb = gb_loopback_calc_latency(&ts, &te); + return ret; +} + +static int gb_loopback_sink(struct gb_loopback *gb, u32 len) +{ + struct gb_loopback_transfer_request *request; + int retval; + + request = kmalloc(len + sizeof(*request), GFP_KERNEL); + if (!request) + return -ENOMEM; + request->len = cpu_to_le32(len); + retval = gb_loopback_operation_sync(gb, GB_LOOPBACK_TYPE_SINK, + request, len + sizeof(*request), + NULL, 0); kfree(request); return retval; } static int gb_loopback_transfer(struct gb_loopback *gb, u32 len) { - struct timeval ts, te; struct gb_loopback_transfer_request *request; struct gb_loopback_transfer_response *response; int retval; @@ -431,22 +466,9 @@ static int gb_loopback_transfer(struct gb_loopback *gb, u32 len) memset(request->data, 0x5A, len); request->len = cpu_to_le32(len); - - do_gettimeofday(&ts); - retval = gb_operation_sync(gb->connection, GB_LOOPBACK_TYPE_TRANSFER, - request, len + sizeof(*request), - response, len + sizeof(*response)); - do_gettimeofday(&te); - - /* Calculate the total time the message took */ - gb_loopback_push_latency_ts(gb, &ts, &te); - gb->elapsed_nsecs = gb_loopback_calc_latency(&ts, &te); - - /* Calculate non-greybus related component of the latency */ - gb_connection_pop_timestamp(gb->connection, &ts); - gb_connection_pop_timestamp(gb->connection, &te); - gb->elapsed_nsecs_gb = gb_loopback_calc_latency(&ts, &te); - + retval = gb_loopback_operation_sync(gb, GB_LOOPBACK_TYPE_TRANSFER, + request, len + sizeof(*request), + response, len + sizeof(*response)); if (retval) goto gb_error; @@ -464,24 +486,8 @@ gb_error: static int gb_loopback_ping(struct gb_loopback *gb) { - struct timeval ts, te; - int retval; - - do_gettimeofday(&ts); - retval = gb_operation_sync(gb->connection, GB_LOOPBACK_TYPE_PING, - NULL, 0, NULL, 0); - do_gettimeofday(&te); - - /* Calculate the total time the message took */ - gb_loopback_push_latency_ts(gb, &ts, &te); - gb->elapsed_nsecs = gb_loopback_calc_latency(&ts, &te); - - /* Calculate non-greybus related component of the latency */ - gb_connection_pop_timestamp(gb->connection, &ts); - gb_connection_pop_timestamp(gb->connection, &te); - gb->elapsed_nsecs_gb = gb_loopback_calc_latency(&ts, &te); - - return retval; + return gb_loopback_operation_sync(gb, GB_LOOPBACK_TYPE_PING, + NULL, 0, NULL, 0); } static int gb_loopback_request_recv(u8 type, struct gb_operation *operation) -- cgit v0.10.2 From 26717ed328b5d238b5c6268912d45703b99b79d0 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 14 Sep 2015 10:48:55 +0100 Subject: greybus: loopback: use dev_name to populate sysfsname dev_name() will give a nice string representing the end0:X:Y:Z:W name mitigating the need to pick apart the various nested data structures and print out their various identifiers. Signed-off-by: Bryan O'Donoghue Suggested-by: Viresh Kumar Reviewed-by: Patrick Titiano Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 6155b50..5124536 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -931,11 +931,8 @@ static int gb_loopback_connection_init(struct gb_connection *connection) } /* Create per-connection sysfs and debugfs data-points */ - snprintf(name, sizeof(name), "raw_latency_endo0:%d:%d:%d:%d", - connection->bundle->intf->module->module_id, - connection->bundle->intf->interface_id, - connection->bundle->id, - connection->intf_cport_id); + snprintf(name, sizeof(name), "raw_latency_endo0:%s", + dev_name(&connection->dev)); gb->file = debugfs_create_file(name, S_IFREG | S_IRUGO, gb_dev.root, gb, &gb_loopback_debugfs_latency_ops); gb->connection = connection; -- cgit v0.10.2 From 19151c3dd4cfcced6f173a9b1e5aba07d7d1d9b9 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 9 Sep 2015 21:08:29 +0530 Subject: greybus: svc: Implement DME peer get/set attributes helpers These are required to get/set DME attributes of the modules. This is implemented based on the greybus specifications. Reviewed-by: Johan Hovold Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 76fea9a..6fd20bd 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -742,6 +742,8 @@ struct gb_spi_transfer_response { #define GB_SVC_TYPE_INTF_RESET 0x06 #define GB_SVC_TYPE_CONN_CREATE 0x07 #define GB_SVC_TYPE_CONN_DESTROY 0x08 +#define GB_SVC_TYPE_DME_PEER_GET 0x09 +#define GB_SVC_TYPE_DME_PEER_SET 0x0a #define GB_SVC_TYPE_ROUTE_CREATE 0x0b #define GB_SVC_TYPE_ROUTE_DESTROY 0x0c @@ -799,6 +801,28 @@ struct gb_svc_conn_destroy_request { } __packed; /* connection destroy response has no payload */ +struct gb_svc_dme_peer_get_request { + __u8 intf_id; + __u16 attr; + __u16 selector; +} __packed; + +struct gb_svc_dme_peer_get_response { + __u16 result_code; + __u32 attr_value; +} __packed; + +struct gb_svc_dme_peer_set_request { + __u8 intf_id; + __u16 attr; + __u16 selector; + __u32 value; +} __packed; + +struct gb_svc_dme_peer_set_response { + __u16 result_code; +} __packed; + struct gb_svc_route_create_request { __u8 intf1_id; __u8 dev1_id; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 73fad4a..241b9da 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -104,6 +104,78 @@ int gb_svc_intf_reset(struct gb_svc *svc, u8 intf_id) } EXPORT_SYMBOL_GPL(gb_svc_intf_reset); +int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, + u32 *value) +{ + struct gb_svc_dme_peer_get_request request; + struct gb_svc_dme_peer_get_response response; + u16 result; + int ret; + + request.intf_id = intf_id; + request.attr = cpu_to_le16(attr); + request.selector = cpu_to_le16(selector); + + ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_DME_PEER_GET, + &request, sizeof(request), + &response, sizeof(response)); + if (ret) { + dev_err(&svc->connection->dev, + "failed to get DME attribute (%hhu %hx %hu) %d\n", + intf_id, attr, selector, ret); + return ret; + } + + result = le16_to_cpu(response.result_code); + if (result) { + dev_err(&svc->connection->dev, + "Unipro error %hu while getting DME attribute (%hhu %hx %hu)\n", + result, intf_id, attr, selector); + return -EINVAL; + } + + if (value) + *value = le32_to_cpu(response.attr_value); + + return 0; +} +EXPORT_SYMBOL_GPL(gb_svc_dme_peer_get); + +int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, + u32 value) +{ + struct gb_svc_dme_peer_set_request request; + struct gb_svc_dme_peer_set_response response; + u16 result; + int ret; + + request.intf_id = intf_id; + request.attr = cpu_to_le16(attr); + request.selector = cpu_to_le16(selector); + request.value = cpu_to_le32(value); + + ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_DME_PEER_SET, + &request, sizeof(request), + &response, sizeof(response)); + if (ret) { + dev_err(&svc->connection->dev, + "failed to set DME attribute (%hhu %hx %hu %u) %d\n", + intf_id, attr, selector, value, ret); + return ret; + } + + result = le16_to_cpu(response.result_code); + if (result) { + dev_err(&svc->connection->dev, + "Unipro error %hu while setting DME attribute (%hhu %hx %hu %u)\n", + result, intf_id, attr, selector, value); + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL_GPL(gb_svc_dme_peer_set); + int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id) diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index f1acb82..75518f8 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -17,6 +17,10 @@ int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id); void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id); +int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, + u32 *value); +int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, + u32 value); int gb_svc_protocol_init(void); void gb_svc_protocol_exit(void); -- cgit v0.10.2 From 8bcc2d80dd6aaed009bd0212cf844ef39131547a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 9 Sep 2015 21:08:30 +0530 Subject: greybus: firmware: firmware's file name is 32 characters long 28 is the wrong value and should be 32 instead. Reviewed-by: Johan Hovold Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/firmware.c b/drivers/staging/greybus/firmware.c index e888b7a..fbc6048 100644 --- a/drivers/staging/greybus/firmware.c +++ b/drivers/staging/greybus/firmware.c @@ -27,7 +27,7 @@ static int download_firmware(struct gb_firmware *firmware, u8 stage) { struct gb_connection *connection = firmware->connection; struct gb_interface *intf = connection->bundle->intf; - char firmware_name[28]; + char firmware_name[32]; /* Already have a firmware, free it */ if (firmware->fw) -- cgit v0.10.2 From c9733b78ca4734a10e1c9b7a23b44fc1736d9daa Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 9 Sep 2015 21:08:31 +0530 Subject: greybus: firmware: Fix incorrect firmware file's name All the id-fields are 32 bit long instead of 16 bits and so we will need 8 characters per field instead of four. Also the stage field is only one byte long and so needs just two characters to represent it. Reported-by: Johan Hovold Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/firmware.c b/drivers/staging/greybus/firmware.c index fbc6048..b8f33e7 100644 --- a/drivers/staging/greybus/firmware.c +++ b/drivers/staging/greybus/firmware.c @@ -27,7 +27,7 @@ static int download_firmware(struct gb_firmware *firmware, u8 stage) { struct gb_connection *connection = firmware->connection; struct gb_interface *intf = connection->bundle->intf; - char firmware_name[32]; + char firmware_name[46]; /* Already have a firmware, free it */ if (firmware->fw) @@ -39,7 +39,7 @@ static int download_firmware(struct gb_firmware *firmware, u8 stage) * XXX Name it properly.. */ snprintf(firmware_name, sizeof(firmware_name), - "ara:%04x:%04x:%04x:%04x:%04x.fw", + "ara:%08x:%08x:%08x:%08x:%02x.fw", intf->unipro_mfg_id, intf->unipro_prod_id, intf->ara_vend_id, intf->ara_prod_id, stage); -- cgit v0.10.2 From 1a8862863a7171e8b97fe8833bb3a78770a8aaee Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 9 Sep 2015 21:08:32 +0530 Subject: greybus: firmware: firmware image name has .tftf instead of .fw That's how the bootrom-tool names it, and that's how the kernel should expect it. Reviewed-by: Johan Hovold Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/firmware.c b/drivers/staging/greybus/firmware.c index b8f33e7..fdd5e0c 100644 --- a/drivers/staging/greybus/firmware.c +++ b/drivers/staging/greybus/firmware.c @@ -27,7 +27,7 @@ static int download_firmware(struct gb_firmware *firmware, u8 stage) { struct gb_connection *connection = firmware->connection; struct gb_interface *intf = connection->bundle->intf; - char firmware_name[46]; + char firmware_name[48]; /* Already have a firmware, free it */ if (firmware->fw) @@ -39,7 +39,7 @@ static int download_firmware(struct gb_firmware *firmware, u8 stage) * XXX Name it properly.. */ snprintf(firmware_name, sizeof(firmware_name), - "ara:%08x:%08x:%08x:%08x:%02x.fw", + "ara:%08x:%08x:%08x:%08x:%02x.tftf", intf->unipro_mfg_id, intf->unipro_prod_id, intf->ara_vend_id, intf->ara_prod_id, stage); -- cgit v0.10.2 From 4c9e228407a25a99876b979479ff76208ab7de47 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 9 Sep 2015 21:08:33 +0530 Subject: greybus: firmware: Send AP-ready operation Module's Bootrom needs a way to know (currently), when to start sending requests to the AP. The version request is sent before connection_init() routine is called, and if the module sends the request right after receiving version request, the connection->private field will be NULL. Fix this TEMPORARILY by sending an AP_READY request. Reviewed-by: Johan Hovold Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/firmware.c b/drivers/staging/greybus/firmware.c index fdd5e0c..5642bc3 100644 --- a/drivers/staging/greybus/firmware.c +++ b/drivers/staging/greybus/firmware.c @@ -165,6 +165,7 @@ static int gb_firmware_request_recv(u8 type, struct gb_operation *op) static int gb_firmware_connection_init(struct gb_connection *connection) { struct gb_firmware *firmware; + int ret; firmware = kzalloc(sizeof(*firmware), GFP_KERNEL); if (!firmware) @@ -173,6 +174,20 @@ static int gb_firmware_connection_init(struct gb_connection *connection) firmware->connection = connection; connection->private = firmware; + /* + * Module's Bootrom needs a way to know (currently), when to start + * sending requests to the AP. The version request is sent before this + * routine is called, and if the module sends the request right after + * receiving version request, the connection->private field will be + * NULL. + * + * Fix this TEMPORARILY by sending an AP_READY request. + */ + ret = gb_operation_sync(connection, GB_FIRMWARE_TYPE_AP_READY, NULL, 0, + NULL, 0); + if (ret) + dev_err(&connection->dev, "Failed to send AP READY (%d)\n", ret); + return 0; } diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 6fd20bd..d77e039 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -155,6 +155,7 @@ struct gb_control_disconnected_request { #define GB_FIRMWARE_TYPE_FIRMWARE_SIZE 0x02 #define GB_FIRMWARE_TYPE_GET_FIRMWARE 0x03 #define GB_FIRMWARE_TYPE_READY_TO_BOOT 0x04 +#define GB_FIRMWARE_TYPE_AP_READY 0x05 /* Request with no-payload */ /* Greybus firmware boot stages */ #define GB_FIRMWARE_BOOT_STAGE_ONE 0x01 /* Reserved for the boot ROM */ -- cgit v0.10.2 From d7849bffc622b3405ef226364d67bb81af48c152 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 14 Sep 2015 20:19:02 +0200 Subject: greybus: vibrator: fix tear-down race Do not release the minor number until after the device has been deregistered. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/vibrator.c b/drivers/staging/greybus/vibrator.c index 96d649a..fd40cda 100644 --- a/drivers/staging/greybus/vibrator.c +++ b/drivers/staging/greybus/vibrator.c @@ -148,8 +148,8 @@ static void gb_vibrator_connection_exit(struct gb_connection *connection) #if LINUX_VERSION_CODE <= KERNEL_VERSION(3,11,0) sysfs_remove_group(&vib->dev->kobj, vibrator_groups[0]); #endif - ida_simple_remove(&minors, vib->minor); device_unregister(vib->dev); + ida_simple_remove(&minors, vib->minor); kfree(vib); } -- cgit v0.10.2 From e5265266ec6360702feb6ff69d1aec9e318ae1f6 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 14 Sep 2015 20:19:03 +0200 Subject: greybus: sdio: fix tear-down use-after-free The mmc-driver private data must not be accessed after mmc_free_host() has released it. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index 24b2e31..14617e3 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -750,8 +750,8 @@ static void gb_sdio_connection_exit(struct gb_connection *connection) flush_workqueue(gb_sdio_mrq_workqueue); destroy_workqueue(gb_sdio_mrq_workqueue); mmc_remove_host(mmc); - mmc_free_host(mmc); kfree(host->xfer_buffer); + mmc_free_host(mmc); } static struct gb_protocol sdio_protocol = { -- cgit v0.10.2 From b9154df5cfd2d4cc180f425f0b26e095ce1ffdbc Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 14 Sep 2015 20:19:04 +0200 Subject: greybus: sdio: fix work-queue leak and use-after-free A single global work-queue pointer was used for the per-connection workqueue, something which would lead to memory leaks and all sorts of bad things if there are ever more than one SDIO connection in a system. Also add the missing error handling when allocating the queue. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index 14617e3..bfa1181 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -25,6 +25,7 @@ struct gb_sdio_host { void *xfer_buffer; spinlock_t xfer; /* lock to cancel ongoing transfer */ bool xfer_stop; + struct workqueue_struct *mrq_workqueue; struct work_struct mrqwork; u8 queued_events; bool removed; @@ -32,7 +33,6 @@ struct gb_sdio_host { bool read_only; }; -static struct workqueue_struct *gb_sdio_mrq_workqueue; #define GB_SDIO_RSP_R1_R5_R6_R7 (GB_SDIO_RSP_PRESENT | GB_SDIO_RSP_CRC | \ GB_SDIO_RSP_OPCODE) @@ -497,7 +497,7 @@ static void gb_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) goto out; } - queue_work(gb_sdio_mrq_workqueue, &host->mrqwork); + queue_work(host->mrq_workqueue, &host->mrqwork); mutex_unlock(&host->lock); return; @@ -710,7 +710,12 @@ static int gb_sdio_connection_init(struct gb_connection *connection) } mutex_init(&host->lock); spin_lock_init(&host->xfer); - gb_sdio_mrq_workqueue = alloc_workqueue("gb_sdio_mrq", 0, 1); + host->mrq_workqueue = alloc_workqueue("mmc-%s", 0, 1, + dev_name(&connection->dev)); + if (!host->mrq_workqueue) { + ret = -ENOMEM; + goto free_buffer; + } INIT_WORK(&host->mrqwork, gb_sdio_mrq_work); ret = mmc_add_host(mmc); @@ -723,9 +728,9 @@ static int gb_sdio_connection_init(struct gb_connection *connection) return ret; free_work: - destroy_workqueue(gb_sdio_mrq_workqueue); + destroy_workqueue(host->mrq_workqueue); +free_buffer: kfree(host->xfer_buffer); - free_mmc: connection->private = NULL; mmc_free_host(mmc); @@ -747,8 +752,8 @@ static void gb_sdio_connection_exit(struct gb_connection *connection) connection->private = NULL; mutex_unlock(&host->lock); - flush_workqueue(gb_sdio_mrq_workqueue); - destroy_workqueue(gb_sdio_mrq_workqueue); + flush_workqueue(host->mrq_workqueue); + destroy_workqueue(host->mrq_workqueue); mmc_remove_host(mmc); kfree(host->xfer_buffer); mmc_free_host(mmc); -- cgit v0.10.2 From 1ff3dc920500c2f1cdfaa08c6812f19e05a36da1 Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Mon, 14 Sep 2015 18:20:42 +0200 Subject: greybus: es2: rename misnamed variables and methods Some methods and variables name were a lot confusing. Replace it or add ep_pair in methods or varaibles name to make sources less confusing. Signed-off-by: Alexandre Bailon Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 96090aa..2ac2c1b 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -123,7 +123,7 @@ static void cport_out_callback(struct urb *urb); static void usb_log_enable(struct es1_ap_dev *es1); static void usb_log_disable(struct es1_ap_dev *es1); -static int cport_to_ep(struct es1_ap_dev *es1, u16 cport_id) +static int cport_to_ep_pair(struct es1_ap_dev *es1, u16 cport_id) { if (cport_id >= es1->hd->num_cports) return 0; @@ -132,38 +132,38 @@ static int cport_to_ep(struct es1_ap_dev *es1, u16 cport_id) #define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ -static int ep_in_use(struct es1_ap_dev *es1, int bulk_ep_set) +static int ep_pair_in_use(struct es1_ap_dev *es1, int ep_pair) { int i; for (i = 0; i < es1->hd->num_cports; i++) { - if (es1->cport_to_ep[i] == bulk_ep_set) + if (es1->cport_to_ep[i] == ep_pair) return 1; } return 0; } int map_cport_to_ep(struct es1_ap_dev *es1, - u16 cport_id, int bulk_ep_set) + u16 cport_id, int ep_pair) { int retval; struct cport_to_ep *cport_to_ep; - if (bulk_ep_set < 0 || bulk_ep_set >= NUM_BULKS) + if (ep_pair < 0 || ep_pair >= NUM_BULKS) return -EINVAL; if (cport_id >= es1->hd->num_cports) return -EINVAL; - if (bulk_ep_set && ep_in_use(es1, bulk_ep_set)) + if (ep_pair && ep_pair_in_use(es1, ep_pair)) return -EINVAL; cport_to_ep = kmalloc(sizeof(*cport_to_ep), GFP_KERNEL); if (!cport_to_ep) return -ENOMEM; - es1->cport_to_ep[cport_id] = bulk_ep_set; + es1->cport_to_ep[cport_id] = ep_pair; cport_to_ep->cport_id = cpu_to_le16(cport_id); - cport_to_ep->endpoint_in = es1->cport_in[bulk_ep_set].endpoint; - cport_to_ep->endpoint_out = es1->cport_out[bulk_ep_set].endpoint; + cport_to_ep->endpoint_in = es1->cport_in[ep_pair].endpoint; + cport_to_ep->endpoint_out = es1->cport_out[ep_pair].endpoint; retval = usb_control_msg(es1->usb_dev, usb_sndctrlpipe(es1->usb_dev, 0), @@ -275,7 +275,7 @@ static int message_send(struct greybus_host_device *hd, u16 cport_id, size_t buffer_size; int retval; struct urb *urb; - int bulk_ep_set; + int ep_pair; unsigned long flags; /* @@ -302,10 +302,10 @@ static int message_send(struct greybus_host_device *hd, u16 cport_id, buffer_size = sizeof(*message->header) + message->payload_size; - bulk_ep_set = cport_to_ep(es1, cport_id); + ep_pair = cport_to_ep_pair(es1, cport_id); usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, - es1->cport_out[bulk_ep_set].endpoint), + es1->cport_out[ep_pair].endpoint), message->buffer, buffer_size, cport_out_callback, message); urb->transfer_flags |= URB_ZERO_PACKET; -- cgit v0.10.2 From 64c9cabcac57904b8a6d6ae9e8a90c258762c86b Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Mon, 14 Sep 2015 18:20:43 +0200 Subject: greybus: es2: change (un)map methods to static Endpoints pair will only be managed by es2 driver. map_cport_to_ep() and unmap_cport() should be static. Signed-off-by: Alexandre Bailon Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 2ac2c1b..ec06dc6 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -143,7 +143,7 @@ static int ep_pair_in_use(struct es1_ap_dev *es1, int ep_pair) return 0; } -int map_cport_to_ep(struct es1_ap_dev *es1, +static int map_cport_to_ep(struct es1_ap_dev *es1, u16 cport_id, int ep_pair) { int retval; @@ -180,7 +180,7 @@ int map_cport_to_ep(struct es1_ap_dev *es1, return retval; } -int unmap_cport(struct es1_ap_dev *es1, u16 cport_id) +static int unmap_cport(struct es1_ap_dev *es1, u16 cport_id) { return map_cport_to_ep(es1, cport_id, 0); } -- cgit v0.10.2 From e5acf736caac014de39f618f7725164b75176fea Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Mon, 14 Sep 2015 18:20:44 +0200 Subject: greybus: es2: add some documentation about endpoints mapping Signed-off-by: Alexandre Bailon Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index ec06dc6..834ccd4 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -108,6 +108,12 @@ struct es1_ap_dev { int *cport_to_ep; }; +/** + * cport_to_ep - information about cport to endpoints mapping + * @cport_id: the id of cport to map to endpoints + * @endpoint_in: the endpoint number to use for in transfer + * @endpoint_out: he endpoint number to use for out transfer + */ struct cport_to_ep { __le16 cport_id; __u8 endpoint_in; @@ -123,6 +129,7 @@ static void cport_out_callback(struct urb *urb); static void usb_log_enable(struct es1_ap_dev *es1); static void usb_log_disable(struct es1_ap_dev *es1); +/* Get the endpoints pair mapped to the cport */ static int cport_to_ep_pair(struct es1_ap_dev *es1, u16 cport_id) { if (cport_id >= es1->hd->num_cports) @@ -132,6 +139,7 @@ static int cport_to_ep_pair(struct es1_ap_dev *es1, u16 cport_id) #define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ +/* Test if the endpoints pair is already mapped to a cport */ static int ep_pair_in_use(struct es1_ap_dev *es1, int ep_pair) { int i; @@ -143,6 +151,7 @@ static int ep_pair_in_use(struct es1_ap_dev *es1, int ep_pair) return 0; } +/* Configure the endpoint mapping and send the request to APBridge */ static int map_cport_to_ep(struct es1_ap_dev *es1, u16 cport_id, int ep_pair) { @@ -180,6 +189,7 @@ static int map_cport_to_ep(struct es1_ap_dev *es1, return retval; } +/* Unmap a cport: use the muxed endpoints pair */ static int unmap_cport(struct es1_ap_dev *es1, u16 cport_id) { return map_cport_to_ep(es1, cport_id, 0); -- cgit v0.10.2 From c09db1820f7ae71d0b1aad7cd1efafab0a880917 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 15 Sep 2015 09:18:08 +0200 Subject: greybus: svc: fix ida memory leak The device-id map was never deallocated on SVC-connection tear down. Also make the map per-SVC-connection (there should still be only one) rather than use a global pointer. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 241b9da..5a130e5 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -24,6 +24,7 @@ enum gb_svc_state { struct gb_svc { struct gb_connection *connection; enum gb_svc_state state; + struct ida device_id_map; }; struct svc_hotplug { @@ -32,7 +33,6 @@ struct svc_hotplug { struct gb_svc_intf_hotplug_request data; }; -static struct ida greybus_svc_device_id_map; /* * AP's SVC cport is required early to get messages from the SVC. This happens @@ -369,7 +369,7 @@ static void svc_process_hotplug(struct work_struct *work) * XXX Do we need to allocate device ID for SVC or the AP here? And what * XXX about an AP with multiple interface blocks? */ - device_id = ida_simple_get(&greybus_svc_device_id_map, + device_id = ida_simple_get(&svc->device_id_map, GB_DEVICE_ID_MODULES_START, 0, GFP_KERNEL); if (device_id < 0) { ret = device_id; @@ -413,7 +413,7 @@ svc_id_free: * XXX anymore. */ ida_put: - ida_simple_remove(&greybus_svc_device_id_map, device_id); + ida_simple_remove(&svc->device_id_map, device_id); destroy_interface: gb_interface_remove(hd, intf_id); free_svc_hotplug: @@ -490,7 +490,7 @@ static int gb_svc_intf_hot_unplug_recv(struct gb_operation *op) */ gb_svc_route_destroy(svc, hd->endo->ap_intf_id, intf_id); - ida_simple_remove(&greybus_svc_device_id_map, device_id); + ida_simple_remove(&svc->device_id_map, device_id); return 0; } @@ -594,7 +594,7 @@ static int gb_svc_connection_init(struct gb_connection *connection) WARN_ON(connection->hd->initial_svc_connection); connection->hd->initial_svc_connection = connection; - ida_init(&greybus_svc_device_id_map); + ida_init(&svc->device_id_map); return 0; } @@ -603,6 +603,7 @@ static void gb_svc_connection_exit(struct gb_connection *connection) { struct gb_svc *svc = connection->private; + ida_destroy(&svc->device_id_map); connection->hd->svc = NULL; connection->private = NULL; kfree(svc); -- cgit v0.10.2 From 59832931cbafa9211ec9ff8434b6d914f82f0f18 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 15 Sep 2015 10:48:00 +0200 Subject: greybus: svc: fix version response The SVC-protocol driver currently accepts the version offered by the SVC, but still responded with a hard-coded version. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 5a130e5..075d81d 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -278,8 +278,9 @@ static int gb_svc_version_request(struct gb_operation *op) } version = op->response->payload; - version->major = GB_SVC_VERSION_MAJOR; - version->minor = GB_SVC_VERSION_MINOR; + version->major = connection->module_major; + version->minor = connection->module_minor; + return 0; } -- cgit v0.10.2 From cfb16906860d76b5afe192d32fb79cf9af853b92 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 15 Sep 2015 10:48:01 +0200 Subject: greybus: greybus_protocols: add missing version-request definition Add the missing version-request definition that was falsely claimed to be empty. Update the generic version-request helper and SVC version-request handler to use the request definition rather than rely on the response happening to have the same layout, something which also improves readability. Remove a misplaced "Control Protocol" header while at it. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index d77e039..9b2d189 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -103,9 +103,11 @@ struct gb_operation_msg_hdr { #define GB_REQUEST_TYPE_INVALID 0x00 #define GB_REQUEST_TYPE_PROTOCOL_VERSION 0x01 -/* Control Protocol */ +struct gb_protocol_version_request { + __u8 major; + __u8 minor; +} __packed; -/* version request has no payload */ struct gb_protocol_version_response { __u8 major; __u8 minor; @@ -748,7 +750,10 @@ struct gb_spi_transfer_response { #define GB_SVC_TYPE_ROUTE_CREATE 0x0b #define GB_SVC_TYPE_ROUTE_DESTROY 0x0c -/* SVC version request/response have same payload as gb_protocol_version_response */ +/* + * SVC version request/response has the same payload as + * gb_protocol_version_request/response. + */ /* SVC protocol hello request */ struct gb_svc_hello_request { diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index 1c74659..c93f963 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -165,30 +165,31 @@ struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor) int gb_protocol_get_version(struct gb_connection *connection) { - struct gb_protocol_version_response version; + struct gb_protocol_version_request request; + struct gb_protocol_version_response response; int retval; - version.major = connection->protocol->major; - version.minor = connection->protocol->minor; + request.major = connection->protocol->major; + request.minor = connection->protocol->minor; retval = gb_operation_sync(connection, GB_REQUEST_TYPE_PROTOCOL_VERSION, - &version, sizeof(version), &version, - sizeof(version)); + &request, sizeof(request), &response, + sizeof(response)); if (retval) return retval; - if (version.major > connection->protocol->major) { + if (response.major > connection->protocol->major) { dev_err(&connection->dev, "unsupported major version (%hhu > %hhu)\n", - version.major, connection->protocol->major); + response.major, connection->protocol->major); return -ENOTSUPP; } - connection->module_major = version.major; - connection->module_minor = version.minor; + connection->module_major = response.major; + connection->module_minor = response.minor; dev_dbg(&connection->dev, "version_major = %u version_minor = %u\n", - version.major, version.minor); + response.major, response.minor); return 0; } diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 075d81d..28f03dc 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -256,30 +256,31 @@ static void gb_svc_route_destroy(struct gb_svc *svc, u8 intf1_id, u8 intf2_id) static int gb_svc_version_request(struct gb_operation *op) { struct gb_connection *connection = op->connection; - struct gb_protocol_version_response *version; + struct gb_protocol_version_request *request; + struct gb_protocol_version_response *response; struct device *dev = &connection->dev; - version = op->request->payload; + request = op->request->payload; - if (version->major > GB_SVC_VERSION_MAJOR) { + if (request->major > GB_SVC_VERSION_MAJOR) { dev_err(&connection->dev, "unsupported major version (%hhu > %hhu)\n", - version->major, GB_SVC_VERSION_MAJOR); + request->major, GB_SVC_VERSION_MAJOR); return -ENOTSUPP; } - connection->module_major = version->major; - connection->module_minor = version->minor; + connection->module_major = request->major; + connection->module_minor = request->minor; - if (!gb_operation_response_alloc(op, sizeof(*version), GFP_KERNEL)) { + if (!gb_operation_response_alloc(op, sizeof(*response), GFP_KERNEL)) { dev_err(dev, "%s: error allocating response\n", __func__); return -ENOMEM; } - version = op->response->payload; - version->major = connection->module_major; - version->minor = connection->module_minor; + response = op->response->payload; + response->major = connection->module_major; + response->minor = connection->module_minor; return 0; } -- cgit v0.10.2 From 2498050b03399cc0df32863f9a4c2a63b1f30d79 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Tue, 15 Sep 2015 15:33:51 +0100 Subject: greybus: svc: fix endianness for svc message Some fields in svc request were not being set with the correct endianness, which will trigger the following sparse issues as example: greybus/svc.c:116:22: warning: incorrect type in assignment (different base types) greybus/svc.c:116:22: expected unsigned short [unsigned] [assigned] [usertype] attr greybus/svc.c:116:22: got restricted __le16 [usertype] Signed-off-by: Rui Miguel Silva Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 9b2d189..b3d0c57 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -791,9 +791,9 @@ struct gb_svc_intf_reset_request { struct gb_svc_conn_create_request { __u8 intf1_id; - __u16 cport1_id; + __le16 cport1_id; __u8 intf2_id; - __u16 cport2_id; + __le16 cport2_id; __u8 tc; __u8 flags; } __packed; @@ -801,32 +801,32 @@ struct gb_svc_conn_create_request { struct gb_svc_conn_destroy_request { __u8 intf1_id; - __u16 cport1_id; + __le16 cport1_id; __u8 intf2_id; - __u16 cport2_id; + __le16 cport2_id; } __packed; /* connection destroy response has no payload */ struct gb_svc_dme_peer_get_request { __u8 intf_id; - __u16 attr; - __u16 selector; + __le16 attr; + __le16 selector; } __packed; struct gb_svc_dme_peer_get_response { - __u16 result_code; - __u32 attr_value; + __le16 result_code; + __le32 attr_value; } __packed; struct gb_svc_dme_peer_set_request { __u8 intf_id; - __u16 attr; - __u16 selector; - __u32 value; + __le16 attr; + __le16 selector; + __le32 value; } __packed; struct gb_svc_dme_peer_set_response { - __u16 result_code; + __le16 result_code; } __packed; struct gb_svc_route_create_request { diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 28f03dc..35e2fb5 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -183,9 +183,9 @@ int gb_svc_connection_create(struct gb_svc *svc, struct gb_svc_conn_create_request request; request.intf1_id = intf1_id; - request.cport1_id = cport1_id; + request.cport1_id = cpu_to_le16(cport1_id); request.intf2_id = intf2_id; - request.cport2_id = cport2_id; + request.cport2_id = cpu_to_le16(cport2_id); /* * XXX: fix connections paramaters to TC0 and all CPort flags * for now. @@ -206,9 +206,9 @@ void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, int ret; request.intf1_id = intf1_id; - request.cport1_id = cport1_id; + request.cport1_id = cpu_to_le16(cport1_id); request.intf2_id = intf2_id; - request.cport2_id = cport2_id; + request.cport2_id = cpu_to_le16(cport2_id); ret = gb_operation_sync(connection, GB_SVC_TYPE_CONN_DESTROY, &request, sizeof(request), NULL, 0); -- cgit v0.10.2 From ced6007a6d2d48efb32d2ca48a13304a04470659 Mon Sep 17 00:00:00 2001 From: Fabien Parent Date: Wed, 16 Sep 2015 03:29:35 +0200 Subject: greybus: es{1,2}: remove obselete define The SVC Control request is obsolete and not used anymore. Remove the related define. Signed-off-by: Fabien Parent Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 2b4bb07..e44bf6c 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -48,9 +48,6 @@ static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); */ #define NUM_CPORT_OUT_URB 8 -/* vendor request AP message */ -#define REQUEST_SVC 0x01 - /* vendor request APB1 log */ #define REQUEST_LOG 0x02 diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 834ccd4..cd33aa7 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -48,9 +48,6 @@ static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); */ #define NUM_CPORT_OUT_URB (8 * NUM_BULKS) -/* vendor request AP message */ -#define REQUEST_SVC 0x01 - /* vendor request APB1 log */ #define REQUEST_LOG 0x02 -- cgit v0.10.2 From a95c258c6fe6b4929f52398d1b6cd5432efe2c86 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 17 Sep 2015 13:17:21 +0200 Subject: greybus: connection: clean up svc-connection creation Move SVC-connection creation to its own helper. Note that the connection_create host-driver callback is really unrelated to the SVC connection, and will be removed by a later patch. It is is included for now as the connection_destroy callback is currently made from the SVC-connection-destroy helper. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index dc45298..8abac19 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -321,6 +321,37 @@ static void gb_connection_cancel_operations(struct gb_connection *connection, spin_unlock_irq(&connection->lock); } +/* + * Request the SVC to create a connection from AP's cport to interface's + * cport. + */ +static int +gb_connection_svc_connection_create(struct gb_connection *connection) +{ + struct greybus_host_device *hd = connection->hd; + struct gb_protocol *protocol = connection->protocol; + int ret; + + if (protocol->flags & GB_PROTOCOL_SKIP_SVC_CONNECTION) + return 0; + + ret = gb_svc_connection_create(hd->svc, + hd->endo->ap_intf_id, + connection->hd_cport_id, + connection->bundle->intf->interface_id, + connection->intf_cport_id); + if (ret) { + dev_err(&connection->dev, + "failed to create svc connection: %d\n", ret); + return ret; + } + + if (hd->driver->connection_create) + hd->driver->connection_create(connection); + + return 0; +} + static void gb_connection_svc_connection_destroy(struct gb_connection *connection) { @@ -358,29 +389,13 @@ static void gb_connection_disconnected(struct gb_connection *connection) static int gb_connection_init(struct gb_connection *connection) { int cport_id = connection->intf_cport_id; - struct greybus_host_device *hd = connection->hd; struct gb_protocol *protocol = connection->protocol; int ret; - /* - * Request the SVC to create a connection from AP's cport to interface's - * cport. - */ - if (!(protocol->flags & GB_PROTOCOL_SKIP_SVC_CONNECTION)) { - ret = gb_svc_connection_create(hd->svc, - hd->endo->ap_intf_id, connection->hd_cport_id, - connection->bundle->intf->interface_id, - cport_id); - if (ret) { - dev_err(&connection->dev, - "%s: Failed to create svc connection (%d)\n", - __func__, ret); - return ret; - } + ret = gb_connection_svc_connection_create(connection); + if (ret) + return ret; - if (hd->driver->connection_create) - hd->driver->connection_create(connection); - } /* Inform Interface about active CPorts */ if (!(protocol->flags & GB_PROTOCOL_SKIP_CONTROL_CONNECTED)) { struct gb_control *control = connection->bundle->intf->control; -- cgit v0.10.2 From 8d7a712ca86b4da7220b8c3da37f118fed3e0bb2 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 17 Sep 2015 13:17:22 +0200 Subject: greybus: connection: clean up init error paths Clearly mark error-path labels as such and clean up control flow. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 8abac19..5b8aa04 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -405,7 +405,7 @@ static int gb_connection_init(struct gb_connection *connection) dev_err(&connection->dev, "Failed to connect CPort-%d (%d)\n", cport_id, ret); - goto svc_destroy; + goto err_svc_destroy; } } @@ -424,21 +424,23 @@ static int gb_connection_init(struct gb_connection *connection) dev_err(&connection->dev, "Failed to get version CPort-%d (%d)\n", cport_id, ret); - goto disconnect; + goto err_disconnect; } } ret = protocol->connection_init(connection); - if (!ret) - return 0; + if (ret) + goto err_disconnect; + + return 0; -disconnect: +err_disconnect: spin_lock_irq(&connection->lock); connection->state = GB_CONNECTION_STATE_ERROR; spin_unlock_irq(&connection->lock); gb_connection_disconnected(connection); -svc_destroy: +err_svc_destroy: gb_connection_svc_connection_destroy(connection); return ret; -- cgit v0.10.2 From 72d748226379979e4a2e3e1ebf5379fa57f6f3fe Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 17 Sep 2015 13:17:23 +0200 Subject: greybus: connection: clean up control-disconnected helper Rename helper to the more descriptive gb_connection_control_disconnected(). Use u16 for cport number, remove redundant cport number from warning message, and shorten a long line. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 5b8aa04..ac78792 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -368,22 +368,25 @@ gb_connection_svc_connection_destroy(struct gb_connection *connection) connection->intf_cport_id); } -static void gb_connection_disconnected(struct gb_connection *connection) +/* Inform Interface about inactive CPorts */ +static void +gb_connection_control_disconnected(struct gb_connection *connection) { + struct gb_protocol *protocol = connection->protocol; struct gb_control *control; - int cport_id = connection->intf_cport_id; + u16 cport_id = connection->intf_cport_id; int ret; - /* Inform Interface about inactive CPorts */ - if (connection->protocol->flags & GB_PROTOCOL_SKIP_CONTROL_DISCONNECTED) + if (protocol->flags & GB_PROTOCOL_SKIP_CONTROL_DISCONNECTED) return; control = connection->bundle->intf->control; ret = gb_control_disconnected_operation(control, cport_id); - if (ret) + if (ret) { dev_warn(&connection->dev, - "Failed to disconnect CPort-%d (%d)\n", cport_id, ret); + "failed to disconnect cport: %d\n", ret); + } } static int gb_connection_init(struct gb_connection *connection) @@ -439,7 +442,7 @@ err_disconnect: connection->state = GB_CONNECTION_STATE_ERROR; spin_unlock_irq(&connection->lock); - gb_connection_disconnected(connection); + gb_connection_control_disconnected(connection); err_svc_destroy: gb_connection_svc_connection_destroy(connection); @@ -462,7 +465,7 @@ static void gb_connection_exit(struct gb_connection *connection) gb_connection_cancel_operations(connection, -ESHUTDOWN); connection->protocol->connection_exit(connection); - gb_connection_disconnected(connection); + gb_connection_control_disconnected(connection); gb_connection_svc_connection_destroy(connection); } -- cgit v0.10.2 From 9d7fc25b3c05a3330002560c19f0dfbfe83ea8a0 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 17 Sep 2015 13:17:24 +0200 Subject: greybus: connection: add control-connected helper Add control-connected helper to improve readability. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index ac78792..de55812 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -368,6 +368,29 @@ gb_connection_svc_connection_destroy(struct gb_connection *connection) connection->intf_cport_id); } +/* Inform Interface about active CPorts */ +static int gb_connection_control_connected(struct gb_connection *connection) +{ + struct gb_protocol *protocol = connection->protocol; + struct gb_control *control; + u16 cport_id = connection->intf_cport_id; + int ret; + + if (protocol->flags & GB_PROTOCOL_SKIP_CONTROL_CONNECTED) + return 0; + + control = connection->bundle->intf->control; + + ret = gb_control_connected_operation(control, cport_id); + if (ret) { + dev_err(&connection->dev, + "failed to connect cport: %d\n", ret); + return ret; + } + + return 0; +} + /* Inform Interface about inactive CPorts */ static void gb_connection_control_disconnected(struct gb_connection *connection) @@ -399,18 +422,9 @@ static int gb_connection_init(struct gb_connection *connection) if (ret) return ret; - /* Inform Interface about active CPorts */ - if (!(protocol->flags & GB_PROTOCOL_SKIP_CONTROL_CONNECTED)) { - struct gb_control *control = connection->bundle->intf->control; - - ret = gb_control_connected_operation(control, cport_id); - if (ret) { - dev_err(&connection->dev, - "Failed to connect CPort-%d (%d)\n", - cport_id, ret); - goto err_svc_destroy; - } - } + ret = gb_connection_control_connected(connection); + if (ret) + goto err_svc_destroy; /* Need to enable the connection to initialize it */ spin_lock_irq(&connection->lock); -- cgit v0.10.2 From 2846d3ed2e5608bcdb773cf308af7fabbfcb663e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 17 Sep 2015 13:17:25 +0200 Subject: greybus: connection: add protocol-version helper Add protocol-version to improve readability. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index de55812..91d1e47 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -412,9 +412,30 @@ gb_connection_control_disconnected(struct gb_connection *connection) } } +/* + * Request protocol version supported by the module. We don't need to do + * this for SVC as that is initiated by the SVC. + */ +static int gb_connection_protocol_get_version(struct gb_connection *connection) +{ + struct gb_protocol *protocol = connection->protocol; + int ret; + + if (protocol->flags & GB_PROTOCOL_SKIP_VERSION) + return 0; + + ret = gb_protocol_get_version(connection); + if (ret) { + dev_err(&connection->dev, + "failed to get protocol version: %d\n", ret); + return ret; + } + + return 0; +} + static int gb_connection_init(struct gb_connection *connection) { - int cport_id = connection->intf_cport_id; struct gb_protocol *protocol = connection->protocol; int ret; @@ -431,19 +452,9 @@ static int gb_connection_init(struct gb_connection *connection) connection->state = GB_CONNECTION_STATE_ENABLED; spin_unlock_irq(&connection->lock); - /* - * Request protocol version supported by the module. We don't need to do - * this for SVC as that is initiated by the SVC. - */ - if (!(protocol->flags & GB_PROTOCOL_SKIP_VERSION)) { - ret = gb_protocol_get_version(connection); - if (ret) { - dev_err(&connection->dev, - "Failed to get version CPort-%d (%d)\n", - cport_id, ret); - goto err_disconnect; - } - } + ret = gb_connection_protocol_get_version(connection); + if (ret) + goto err_disconnect; ret = protocol->connection_init(connection); if (ret) -- cgit v0.10.2 From d7ea30a57145d13a6e74c90e4f7277cb8705bcc1 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 17 Sep 2015 13:17:26 +0200 Subject: greybus: hd: add optional cport enable and disable callbacks Add optional cport enable and disable callbacks to the greybus host drivers, that can be used to initialise and allocate/release resources associated with a cport during connection setup/teardown (e.g. software queues and hardware state). Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 91d1e47..b4947f0 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -284,6 +284,34 @@ err_remove_ida: return NULL; } +static int gb_connection_hd_cport_enable(struct gb_connection *connection) +{ + struct greybus_host_device *hd = connection->hd; + int ret; + + if (!hd->driver->cport_enable) + return 0; + + ret = hd->driver->cport_enable(hd, connection->hd_cport_id); + if (ret) { + dev_err(&connection->dev, + "failed to enable host cport: %d\n", ret); + return ret; + } + + return 0; +} + +static void gb_connection_hd_cport_disable(struct gb_connection *connection) +{ + struct greybus_host_device *hd = connection->hd; + + if (!hd->driver->cport_disable) + return; + + hd->driver->cport_disable(hd, connection->hd_cport_id); +} + struct gb_connection *gb_connection_create(struct gb_bundle *bundle, u16 cport_id, u8 protocol_id) { @@ -439,10 +467,14 @@ static int gb_connection_init(struct gb_connection *connection) struct gb_protocol *protocol = connection->protocol; int ret; - ret = gb_connection_svc_connection_create(connection); + ret = gb_connection_hd_cport_enable(connection); if (ret) return ret; + ret = gb_connection_svc_connection_create(connection); + if (ret) + goto err_hd_cport_disable; + ret = gb_connection_control_connected(connection); if (ret) goto err_svc_destroy; @@ -470,6 +502,8 @@ err_disconnect: gb_connection_control_disconnected(connection); err_svc_destroy: gb_connection_svc_connection_destroy(connection); +err_hd_cport_disable: + gb_connection_hd_cport_disable(connection); return ret; } @@ -492,6 +526,7 @@ static void gb_connection_exit(struct gb_connection *connection) connection->protocol->connection_exit(connection); gb_connection_control_disconnected(connection); gb_connection_svc_connection_destroy(connection); + gb_connection_hd_cport_disable(connection); } /* diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 9f2eb1f..a320d58 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -75,6 +75,8 @@ struct greybus_host_device; struct greybus_host_driver { size_t hd_priv_size; + int (*cport_enable)(struct greybus_host_device *hd, u16 cport_id); + int (*cport_disable)(struct greybus_host_device *hd, u16 cport_id); void (*connection_create)(struct gb_connection *connection); void (*connection_destroy)(struct gb_connection *connection); int (*message_send)(struct greybus_host_device *hd, u16 dest_cport_id, -- cgit v0.10.2 From 3afe952127e6379b32ba0d845231dbe952d6117b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 17 Sep 2015 13:17:27 +0200 Subject: greybus: hd: remove connection-create/destroy callbacks These host-driver callbacks were intended to allow host drivers to prepare a cport, something which can now be handled by the cport enable/disable callbacks instead. The current create/destroy are somewhat confusingly named as they were not supposed to create or destroy connections. They were however called from the unrelated helper functions that do create and destroy SVC connections. Furthermore, no errors were returned should the create callback fail, which should have caused the connection initialisation to fail. Remove these unused callbacks for now, and let us use the cport enable/disable callbacks that should be able handle all host cport initialisation (possibly after also adding an interface to provide information for endpoint-cport mapping). Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index b4947f0..f154131 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -374,9 +374,6 @@ gb_connection_svc_connection_create(struct gb_connection *connection) return ret; } - if (hd->driver->connection_create) - hd->driver->connection_create(connection); - return 0; } @@ -386,9 +383,6 @@ gb_connection_svc_connection_destroy(struct gb_connection *connection) if (connection->protocol->flags & GB_PROTOCOL_SKIP_SVC_CONNECTION) return; - if (connection->hd->driver->connection_destroy) - connection->hd->driver->connection_destroy(connection); - gb_svc_connection_destroy(connection->hd->svc, connection->hd->endo->ap_intf_id, connection->hd_cport_id, diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index a320d58..e4e53c1 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -77,8 +77,6 @@ struct greybus_host_driver { int (*cport_enable)(struct greybus_host_device *hd, u16 cport_id); int (*cport_disable)(struct greybus_host_device *hd, u16 cport_id); - void (*connection_create)(struct gb_connection *connection); - void (*connection_destroy)(struct gb_connection *connection); int (*message_send)(struct greybus_host_device *hd, u16 dest_cport_id, struct gb_message *message, gfp_t gfp_mask); void (*message_cancel)(struct gb_message *message); -- cgit v0.10.2 From 2e49b15763cc460cabc0713e05c7d24fb892d9ad Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 15 Sep 2015 11:04:30 +0530 Subject: greybus: Documentation: Update sysfs-bus-greybus The file names here weren't in sync with what we have today and the updates give a better picture of the same. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index acc4054..b2e699c 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -1,46 +1,54 @@ -What: /sys/bus/greybus/device/endo +What: /sys/bus/greybus/device/endoE Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: - The "root" endo for the Greybus device tree. XXX is - replaced with the numeric value of the endo layout - scheme as documented in the ARA Module Developer Kit. + The "root" endo devices for the Greybus device tree. E + is replaced with a 2 byte number representing the endo, + mostly 0. -What: /sys/bus/greybus/device/endo/id +What: /sys/bus/greybus/device/endoE/id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: The Endo ID, which is a 2-byte hexadecimal value - defined by the the Endo layout scheme, documented in + defined by the Endo layout scheme, documented in the ARA Module Developer Kit. -What: /sys/bus/greybus/device/endo/ap_intf_id +What: /sys/bus/greybus/device/endoE/ap_intf_id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: - The AP interface ID, a small non-zero integer which + The AP interface ID, a 1-byte non-zero integer which defines the position of the AP module on the Endo. The interface positions are defined in the ARA Module Developer Kit. -What: /sys/bus/greybus/device/endo/svc/serial_number +What: /sys/bus/greybus/device/endoE/svc/serial_number Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: The serial number of the SVC device -What: /sys/bus/greybus/device/endo/svc/version +What: /sys/bus/greybus/device/endoE/svc/version Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: The version number of the firmware in the SVC device. -What: /sys/bus/greybus/device/endo/../epm +What: /sys/bus/greybus/device/endoE:M +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + A module slot on the endoE, M is replaced by a 1-byte + number representing the module slot. + +What: /sys/bus/greybus/device/endoE:M/epm Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman @@ -50,7 +58,7 @@ Description: Writing 1 to it turns it on, writing 0 to it turns it off. Reading the value returns if it is on or off. -What: /sys/bus/greybus/device/endo/.../power_control +What: /sys/bus/greybus/device/endoE:M/power_control Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman @@ -60,7 +68,7 @@ Description: to the module, writing 0 to it turns power off to the module. Reading the value returns if it is on or off. -What: /sys/bus/greybus/device/endo/.../present +What: /sys/bus/greybus/device/endoE:M/present Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman @@ -70,63 +78,93 @@ Description: This is read-only, 1 means a module is present, 0 means no module is present. -What: /sys/bus/greybus/device/.../product +What: /sys/bus/greybus/device/endoE:M:I +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + An Interface I on the module slot M on the endoE, I is + replaced by a 1-byte number representing the interface. + +What: /sys/bus/greybus/device/endoE:M:I/device_id +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The device ID of a Greybus interface block. + +What: /sys/bus/greybus/device/endoE:M:I/product Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: Product ID of a Greybus interface block. -What: /sys/bus/greybus/device/.../product_string +What: /sys/bus/greybus/device/endoE:M:I/product_string Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: Product ID string of a Greybus interface block. -What: /sys/bus/greybus/device/.../unique_id +What: /sys/bus/greybus/device/endoE:M:I/unique_id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: Unique ID of a Greybus interface block. -What: /sys/bus/greybus/device/.../vendor +What: /sys/bus/greybus/device/endoE:M:I/vendor Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: Vendor ID of a Greybus interface block. -What: /sys/bus/greybus/device/.../vendor_string +What: /sys/bus/greybus/device/endoE:M:I/vendor_string Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: Vendor ID string of a Greybus interface block. -What: /sys/bus/greybus/device/.../device_id +What: /sys/bus/greybus/device/endoE:M:I:B Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: - The device ID of a Greybus interface block. + A bundle B on the Interface I, B is replaced by a 1-byte + number representing the bundle. -What: /sys/bus/greybus/device/.../state +What: /sys/bus/greybus/device/endoE:M:I:B/class Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: - The current state of a Greybus connection. + The greybus class of the bundle B. - It will be one of the following values: - 0 - invalid - 1 - disabled - 2 - enabled - 3 - error - 4 - destroying +What: /sys/bus/greybus/device/endoE:M:I:B/state +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + A bundle has a state that is managed by the userspace + Endo process. This file allows that Endo to signal + other Android HALs that the state of the bundle has + changed to a specific value. When written to, any + process watching the file will be woken up, and the new + value can be read. It's a "poor-man's IPC", yes, but + simplifies the Android userspace code immensely. -What: /sys/bus/greybus/device/.../ap_cport_id +What: /sys/bus/greybus/device/endoE:M:I:B:C +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + A cport C within bundle B, C is replaced by a 2-byte + number representing the cport. + +What: /sys/bus/greybus/device/endoE:M:I:B:C/ap_cport_id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman @@ -134,22 +172,23 @@ Description: The cport ID of the AP, to which cport of the module is connected. -What: /sys/bus/greybus/device/.../protocol_id +What: /sys/bus/greybus/device/endoE:M:I:B:C/protocol_id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: - The protocol ID of a Greybus connection. + The protocol ID of a Greybus cport. -What: /sys/bus/greybus/device/.../state +What: /sys/bus/greybus/device/endoE:M:I:B:C/state Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: - A bundle has a state that is managed by the userspace - Endo process. This file allows that Endo to signal - other Android HALs that the state of the bundle has - changed to a specific value. When written to, any - process watching the file will be woken up, and the new - value can be read. It's a "poor-man's IPC", yes, but - simplifies the Android userspace code immensely. + The current state of a Greybus connection. + + It will be one of the following values: + 0 - invalid + 1 - disabled + 2 - enabled + 3 - error + 4 - destroying -- cgit v0.10.2 From bb03ed920166a1fa2df77d5ef96ff1d749fa2967 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Fri, 18 Sep 2015 16:38:44 +0100 Subject: greybus: tracepoints: add tracepoint definitions This patch adds greybus_trace.h with the following trace definitions - trace_gb_message_send - trace_gb_message_recv_request - trace_gb_message_recv_response - trace_gb_message_cancel_incoming - trace_gb_message_cancel_outgoing Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h new file mode 100644 index 0000000..abceb3a --- /dev/null +++ b/drivers/staging/greybus/greybus_trace.h @@ -0,0 +1,120 @@ +/* + * Greybus driver and device API + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM greybus + +#if !defined(_TRACE_GREYBUS_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_GREYBUS_H + +#include + +struct gb_message; + +DECLARE_EVENT_CLASS(gb_message, + + TP_PROTO(struct gb_message *message), + + TP_ARGS(message), + + TP_STRUCT__entry( + __string(name, dev_name(&message->operation->connection->dev)) + __field(u16, op_id) + __field(u16, intf_cport_id) + __field(u16, hd_cport_id) + __field(size_t, payload_size) + ), + + TP_fast_assign( + __assign_str(name, dev_name(&message->operation->connection->dev)) + __entry->op_id = message->operation->id; + __entry->intf_cport_id = + message->operation->connection->intf_cport_id; + __entry->hd_cport_id = + message->operation->connection->hd_cport_id; + __entry->payload_size = message->payload_size; + ), + + TP_printk("greybus:%s op=%04x if_id=%04x hd_id=%04x l=%zu", + __get_str(name), __entry->op_id, __entry->intf_cport_id, + __entry->hd_cport_id, __entry->payload_size) +); + +/* + * tracepoint name greybus:gb_message_send + * description send a greybus message + * location operation.c:gb_message_send + */ +DEFINE_EVENT(gb_message, gb_message_send, + + TP_PROTO(struct gb_message *message), + + TP_ARGS(message) +); + +/* + * tracepoint name greybus:gb_message_recv_request + * description receive a greybus request + * location operation.c:gb_connection_recv_request + */ +DEFINE_EVENT(gb_message, gb_message_recv_request, + + TP_PROTO(struct gb_message *message), + + TP_ARGS(message) +); + +/* + * tracepoint name greybus:gb_message_recv_response + * description receive a greybus response + * location operation.c:gb_connection_recv_response + */ +DEFINE_EVENT(gb_message, gb_message_recv_response, + + TP_PROTO(struct gb_message *message), + + TP_ARGS(message) +); + +/* + * tracepoint name greybus:gb_message_cancel_outgoing + * description cancel outgoing greybus request + * location operation.c:gb_message_cancel + */ +DEFINE_EVENT(gb_message, gb_message_cancel_outgoing, + + TP_PROTO(struct gb_message *message), + + TP_ARGS(message) +); + +/* + * tracepoint name greybus:gb_message_cancel_incoming + * description cancel incoming greybus request + * location operation.c:gb_message_cancel_incoming + */ +DEFINE_EVENT(gb_message, gb_message_cancel_incoming, + + TP_PROTO(struct gb_message *message), + + TP_ARGS(message) +); + +#endif /* _TRACE_GREYBUS_H */ + +/* This part must be outside protection */ +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . + +/* + * TRACE_INCLUDE_FILE is not needed if the filename and TRACE_SYSTEM are equal + */ +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE greybus_trace +#include + -- cgit v0.10.2 From 5c8ad599b942a9a027045e69fc76c84f23c0acf0 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Fri, 18 Sep 2015 16:38:45 +0100 Subject: greybus: operation, core: hook tracepoints into message opertions This patch hooks tracepoints for greybus messages - trace_gb_message_send - trace_gb_message_recv_request - trace_gb_message_recv_response - trace_gb_message_cancel_outgoing - trace_gb_message_cancel_incoming It provides standard tracepoints at /sys/kernel/debug/tracing/events/greybus/gb_message_send /sys/kernel/debug/tracing/events/greybus/gb_message_recv_response /sys/kernel/debug/tracing/events/greybus/gb_message_recv_request /sys/kernel/debug/tracing/events/greybus/gb_message_cancel_outgoing /sys/kernel/debug/tracing/events/greybus/gb_message_cancel_incoming Giving outputs like gb_message_recv_request: greybus:1-1.1:0 op=0001 if_id=0000 hd_id=0000 l=2 gb_message_send: greybus:1-1.1:0 op=0001 if_id=0000 hd_id=0000 l=2 Similarly perf events can be viewed with standard perf tools e.g. root@beaglebone:~# perf list 'greybus:*' greybus:gb_message_send [Tracepoint event] greybus:gb_message_recv_request [Tracepoint event] greybus:gb_message_recv_response [Tracepoint event] greybus:gb_message_cancel_outgoing [Tracepoint event] greybus:gb_message_cancel_incoming [Tracepoint event] Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 31b025d..af28053 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -82,6 +82,9 @@ endif # add -Wall to try to catch everything we can. ccflags-y := -Wall +# needed for trace events +ccflags-y += -I$(src) + all: module module: diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 3c89cb3..765e0db8 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -9,7 +9,9 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#define CREATE_TRACE_POINTS #include "greybus.h" +#include "greybus_trace.h" /* Allow greybus to be disabled at boot if needed */ static bool nogreybus; @@ -347,6 +349,7 @@ static void __exit gb_exit(void) gb_operation_exit(); bus_unregister(&greybus_bus_type); gb_debugfs_cleanup(); + tracepoint_synchronize_unregister(); } module_exit(gb_exit); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index f9b71e7..d159831 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -15,6 +15,7 @@ #include #include "greybus.h" +#include "greybus_trace.h" static struct kmem_cache *gb_operation_cache; static struct kmem_cache *gb_message_cache; @@ -197,6 +198,7 @@ static int gb_message_send(struct gb_message *message, gfp_t gfp) { struct gb_connection *connection = message->operation->connection; + trace_gb_message_send(message); return connection->hd->driver->message_send(connection->hd, connection->hd_cport_id, message, @@ -834,6 +836,7 @@ static void gb_connection_recv_request(struct gb_connection *connection, gb_operation_put(operation); return; } + trace_gb_message_recv_request(operation->request); /* * The initial reference to the operation will be dropped when the @@ -872,6 +875,7 @@ static void gb_connection_recv_response(struct gb_connection *connection, message->header->type, size, message_size); errno = -EMSGSIZE; } + trace_gb_message_recv_response(operation->response); /* We must ignore the payload if a bad status is returned */ if (errno) @@ -942,6 +946,7 @@ void gb_operation_cancel(struct gb_operation *operation, int errno) gb_message_cancel(operation->request); queue_work(gb_operation_completion_wq, &operation->work); } + trace_gb_message_cancel_outgoing(operation->request); atomic_inc(&operation->waiters); wait_event(gb_operation_cancellation_queue, @@ -968,6 +973,7 @@ void gb_operation_cancel_incoming(struct gb_operation *operation, int errno) if (!gb_operation_result_set(operation, errno)) gb_message_cancel(operation->response); } + trace_gb_message_cancel_incoming(operation->response); atomic_inc(&operation->waiters); wait_event(gb_operation_cancellation_queue, -- cgit v0.10.2 From 608f6619a295ce755061a046e967d8e32c2f4f5b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 22 Sep 2015 09:42:52 -0700 Subject: greybus: es2: comment out unused functions The Qualcomm kernel builds with -Werror so the existing es2.c driver breaks the build due to unused static functions. As we are still hashing out exactly how to implement this logic at the moment, just comment out the functions to make the build be clean, no logic changes happen here at all. Reported-by: Michael Scott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index cd33aa7..3a5f93f 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -136,6 +136,8 @@ static int cport_to_ep_pair(struct es1_ap_dev *es1, u16 cport_id) #define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ +/* Disable for now until we work all of this out to keep a warning-free build */ +#if 0 /* Test if the endpoints pair is already mapped to a cport */ static int ep_pair_in_use(struct es1_ap_dev *es1, int ep_pair) { @@ -191,6 +193,7 @@ static int unmap_cport(struct es1_ap_dev *es1, u16 cport_id) { return map_cport_to_ep(es1, cport_id, 0); } +#endif static struct urb *next_free_urb(struct es1_ap_dev *es1, gfp_t gfp_mask) { -- cgit v0.10.2 From d090446a915f109e65f3b2643269b134e1ddb4ef Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 22 Sep 2015 18:06:37 -0700 Subject: greybus: loopback: drop dependency on internal timestamps This patch drops tracking of internal latencies, it's possible to derive these times via kernel tracepoints and some user-space scripting. Since there's no other use of the internal timestamp than the loopback driver we remove the connection.c, connection.h, es1.c, es2.c and loopback.c inter-dependency in one go. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index f154131..05a9b54 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -67,29 +67,6 @@ void greybus_data_rcvd(struct greybus_host_device *hd, u16 cport_id, } EXPORT_SYMBOL_GPL(greybus_data_rcvd); -void gb_connection_push_timestamp(struct gb_connection *connection) -{ - struct timeval tv; - - do_gettimeofday(&tv); - kfifo_in_locked(&connection->ts_kfifo, (void *)&tv, - sizeof(struct timeval), &connection->lock); -} -EXPORT_SYMBOL_GPL(gb_connection_push_timestamp); - -int gb_connection_pop_timestamp(struct gb_connection *connection, - struct timeval *tv) -{ - int retval; - - if (!kfifo_len(&connection->ts_kfifo)) - return -ENOMEM; - retval = kfifo_out_locked(&connection->ts_kfifo, (void *)tv, - sizeof(*tv), &connection->lock); - return retval; -} -EXPORT_SYMBOL_GPL(gb_connection_pop_timestamp); - static ssize_t state_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -138,7 +115,6 @@ static void gb_connection_release(struct device *dev) struct gb_connection *connection = to_gb_connection(dev); destroy_workqueue(connection->wq); - kfifo_free(&connection->ts_kfifo); kfree(connection); } @@ -234,10 +210,6 @@ gb_connection_create_range(struct greybus_host_device *hd, if (!connection->wq) goto err_free_connection; - if (kfifo_alloc(&connection->ts_kfifo, GB_CONNECTION_TS_KFIFO_LEN, - GFP_KERNEL)) - goto err_destroy_wq; - connection->dev.parent = parent; connection->dev.bus = &greybus_bus_type; connection->dev.type = &greybus_connection_type; @@ -274,8 +246,6 @@ gb_connection_create_range(struct greybus_host_device *hd, return connection; -err_destroy_wq: - destroy_workqueue(connection->wq); err_free_connection: kfree(connection); err_remove_ida: diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index e3ae01d..27ec597 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -43,7 +43,6 @@ struct gb_connection { struct list_head operations; struct workqueue_struct *wq; - struct kfifo ts_kfifo; atomic_t op_cycle; @@ -64,9 +63,6 @@ void gb_hd_connections_exit(struct greybus_host_device *hd); void greybus_data_rcvd(struct greybus_host_device *hd, u16 cport_id, u8 *data, size_t length); -void gb_connection_push_timestamp(struct gb_connection *connection); -int gb_connection_pop_timestamp(struct gb_connection *connection, - struct timeval *tv); int gb_connection_bind_protocol(struct gb_connection *connection); diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index e44bf6c..7292815 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -215,7 +215,6 @@ static int message_send(struct greybus_host_device *hd, u16 cport_id, message->buffer, buffer_size, cport_out_callback, message); urb->transfer_flags |= URB_ZERO_PACKET; - gb_connection_push_timestamp(message->operation->connection); retval = usb_submit_urb(urb, gfp_mask); if (retval) { pr_err("error %d submitting URB\n", retval); diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 3a5f93f..7542101 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -319,7 +319,6 @@ static int message_send(struct greybus_host_device *hd, u16 cport_id, message->buffer, buffer_size, cport_out_callback, message); urb->transfer_flags |= URB_ZERO_PACKET; - gb_connection_push_timestamp(message->operation->connection); retval = usb_submit_urb(urb, gfp_mask); if (retval) { pr_err("error %d submitting URB\n", retval); diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 5124536..7ccf9a2 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -57,7 +57,6 @@ struct gb_loopback_device { /* Overall stats */ struct gb_loopback_stats latency; - struct gb_loopback_stats latency_gb; struct gb_loopback_stats throughput; struct gb_loopback_stats requests_per_second; }; @@ -76,14 +75,12 @@ struct gb_loopback { /* Per connection stats */ struct gb_loopback_stats latency; - struct gb_loopback_stats latency_gb; struct gb_loopback_stats throughput; struct gb_loopback_stats requests_per_second; u32 lbid; u32 iteration_count; u64 elapsed_nsecs; - u64 elapsed_nsecs_gb; u32 error; }; @@ -266,9 +263,6 @@ static void gb_loopback_check_attr(struct gb_loopback_device *gb_dev, /* Time to send and receive one message */ gb_loopback_stats_attrs(latency, dev, false); gb_loopback_stats_attrs(latency, con, true); -/* Time to send and receive one message not including greybus */ -gb_loopback_stats_attrs(latency_gb, dev, false); -gb_loopback_stats_attrs(latency_gb, con, true); /* Number of requests sent per second on this cport */ gb_loopback_stats_attrs(requests_per_second, dev, false); gb_loopback_stats_attrs(requests_per_second, con, true); @@ -303,9 +297,6 @@ static struct attribute *loopback_dev_attrs[] = { &dev_attr_latency_min_dev.attr, &dev_attr_latency_max_dev.attr, &dev_attr_latency_avg_dev.attr, - &dev_attr_latency_gb_min_dev.attr, - &dev_attr_latency_gb_max_dev.attr, - &dev_attr_latency_gb_avg_dev.attr, &dev_attr_requests_per_second_min_dev.attr, &dev_attr_requests_per_second_max_dev.attr, &dev_attr_requests_per_second_avg_dev.attr, @@ -327,9 +318,6 @@ static struct attribute *loopback_con_attrs[] = { &dev_attr_latency_min_con.attr, &dev_attr_latency_max_con.attr, &dev_attr_latency_avg_con.attr, - &dev_attr_latency_gb_min_con.attr, - &dev_attr_latency_gb_max_con.attr, - &dev_attr_latency_gb_avg_con.attr, &dev_attr_requests_per_second_min_con.attr, &dev_attr_requests_per_second_max_con.attr, &dev_attr_requests_per_second_avg_con.attr, @@ -423,11 +411,6 @@ error: gb_loopback_push_latency_ts(gb, &ts, &te); gb->elapsed_nsecs = gb_loopback_calc_latency(&ts, &te); - /* Calculate non-greybus related component of the latency */ - gb_connection_pop_timestamp(gb->connection, &ts); - gb_connection_pop_timestamp(gb->connection, &te); - gb->elapsed_nsecs_gb = gb_loopback_calc_latency(&ts, &te); - return ret; } @@ -554,8 +537,6 @@ static void gb_loopback_reset_stats(struct gb_loopback_device *gb_dev) mutex_lock(&gb->mutex); memcpy(&gb->latency, &reset, sizeof(struct gb_loopback_stats)); - memcpy(&gb->latency_gb, &reset, - sizeof(struct gb_loopback_stats)); memcpy(&gb->throughput, &reset, sizeof(struct gb_loopback_stats)); memcpy(&gb->requests_per_second, &reset, @@ -567,7 +548,6 @@ static void gb_loopback_reset_stats(struct gb_loopback_device *gb_dev) memset(&gb_dev->start, 0, sizeof(struct timeval)); memset(&gb_dev->end, 0, sizeof(struct timeval)); memcpy(&gb_dev->latency, &reset, sizeof(struct gb_loopback_stats)); - memcpy(&gb_dev->latency_gb, &reset, sizeof(struct gb_loopback_stats)); memcpy(&gb_dev->throughput, &reset, sizeof(struct gb_loopback_stats)); memcpy(&gb_dev->requests_per_second, &reset, sizeof(struct gb_loopback_stats)); @@ -679,7 +659,6 @@ error: static void gb_loopback_calculate_stats(struct gb_loopback *gb) { u32 lat; - u64 tmp; /* Express latency in terms of microseconds */ lat = gb_loopback_nsec_to_usec_latency(gb->elapsed_nsecs); @@ -694,12 +673,6 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb) /* Log throughput and requests using latency as benchmark */ gb_loopback_throughput_update(gb, lat); gb_loopback_requests_update(gb, lat); - - /* Calculate the greybus related latency number in nanoseconds */ - tmp = gb->elapsed_nsecs - gb->elapsed_nsecs_gb; - lat = tmp; - gb_loopback_update_stats(&gb_dev.latency_gb, lat); - gb_loopback_update_stats(&gb->latency_gb, lat); } static int gb_loopback_fn(void *data) -- cgit v0.10.2 From 32b2b16737d40d0aea6e7a02740ce47acd4fdd2e Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 22 Sep 2015 18:06:38 -0700 Subject: greybus: tracepoints: add tracepoints for host_device tx/rx This patch adds new tracepoint declarations to greybus_trace.h to allow for capture of greybus host device tx and rx events. These two tracepoints allow an observer to see the point where the hardware interface driver performs the relevant read or write to receive or write the data it's been given from the higher layer greybus driver. The following two new tracepoints are declared: - trace_gb_host_device_send - trace_gb_host_device_recv Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 765e0db8..ea23aaf 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -13,6 +13,9 @@ #include "greybus.h" #include "greybus_trace.h" +EXPORT_TRACEPOINT_SYMBOL_GPL(gb_host_device_send); +EXPORT_TRACEPOINT_SYMBOL_GPL(gb_host_device_recv); + /* Allow greybus to be disabled at boot if needed */ static bool nogreybus; #ifdef MODULE diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h index abceb3a..6c88d34 100644 --- a/drivers/staging/greybus/greybus_trace.h +++ b/drivers/staging/greybus/greybus_trace.h @@ -15,6 +15,7 @@ #include struct gb_message; +struct greybus_host_device; DECLARE_EVENT_CLASS(gb_message, @@ -105,6 +106,55 @@ DEFINE_EVENT(gb_message, gb_message_cancel_incoming, TP_ARGS(message) ); +DECLARE_EVENT_CLASS(gb_host_device, + + TP_PROTO(struct greybus_host_device *hd, u16 intf_cport_id, + size_t payload_size), + + TP_ARGS(hd, intf_cport_id, payload_size), + + TP_STRUCT__entry( + __string(name, dev_name(hd->parent)) + __field(u16, intf_cport_id) + __field(size_t, payload_size) + ), + + TP_fast_assign( + __assign_str(name, dev_name(hd->parent)) + __entry->intf_cport_id = intf_cport_id; + __entry->payload_size = payload_size; + ), + + TP_printk("greybus:%s if_id=%04x l=%zu", __get_str(name), + __entry->intf_cport_id, __entry->payload_size) +); + +/* + * tracepoint name greybus:gb_host_device_send + * description tracepoint representing the point data are transmitted + * location es1.c/es2.c:message_send + */ +DEFINE_EVENT(gb_host_device, gb_host_device_send, + + TP_PROTO(struct greybus_host_device *hd, u16 intf_cport_id, + size_t payload_size), + + TP_ARGS(hd, intf_cport_id, payload_size) +); + +/* + * tracepoint name greybus:gb_host_device_recv + * description tracepoint representing the point data are received + * location es1.c/es2.c:cport_in_callback + */ +DEFINE_EVENT(gb_host_device, gb_host_device_recv, + + TP_PROTO(struct greybus_host_device *hd, u16 intf_cport_id, + size_t payload_size), + + TP_ARGS(hd, intf_cport_id, payload_size) +); + #endif /* _TRACE_GREYBUS_H */ /* This part must be outside protection */ -- cgit v0.10.2 From 6872c46129d00d0fcc0b32d73498fc86d6823137 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Tue, 22 Sep 2015 18:06:39 -0700 Subject: greybus: es1, es2: hook tracepoints to hardware send/recv operations This patch hooks tracepoints for the handoff point to/from hardware. With these tracepoints in place we can view the time between gb_message_send and usb_submit_urb and similarly we can view the time between cport_in_callback and gb_message_recv_response/gb_message_recv_request - trace_gb_host_device_send - trace_gb_host_device_recv It provides standard tracepoints at /sys/kernel/debug/tracing/events/greybus/gb_host_device_send /sys/kernel/debug/tracing/events/greybus/gb_host_device_recv Giving outputs like gb_host_device_recv: greybus:2-1 if_id=0000 l=10 gb_host_device_send: greybus:2-1 if_id=0000 l=10 Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 7292815..f2853ff 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -16,6 +16,7 @@ #include "greybus.h" #include "kernel_ver.h" #include "connection.h" +#include "greybus_trace.h" /* Memory sizes for the buffers sent to/from the ES1 controller */ #define ES1_GBUF_MSG_SIZE_MAX 2048 @@ -215,6 +216,7 @@ static int message_send(struct greybus_host_device *hd, u16 cport_id, message->buffer, buffer_size, cport_out_callback, message); urb->transfer_flags |= URB_ZERO_PACKET; + trace_gb_host_device_send(hd, cport_id, buffer_size); retval = usb_submit_urb(urb, gfp_mask); if (retval) { pr_err("error %d submitting URB\n", retval); @@ -369,12 +371,14 @@ static void cport_in_callback(struct urb *urb) header = urb->transfer_buffer; cport_id = gb_message_cport_unpack(header); - if (cport_id_valid(hd, cport_id)) + if (cport_id_valid(hd, cport_id)) { + trace_gb_host_device_recv(hd, cport_id, urb->actual_length); greybus_data_rcvd(hd, cport_id, urb->transfer_buffer, urb->actual_length); - else + } else { dev_err(dev, "%s: invalid cport id 0x%02x received\n", __func__, cport_id); + } exit: /* put our urb back in the request pool */ retval = usb_submit_urb(urb, GFP_ATOMIC); diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 7542101..8fee116 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -16,6 +16,7 @@ #include "greybus.h" #include "kernel_ver.h" #include "connection.h" +#include "greybus_trace.h" /* Memory sizes for the buffers sent to/from the ES1 controller */ #define ES1_GBUF_MSG_SIZE_MAX 2048 @@ -319,6 +320,7 @@ static int message_send(struct greybus_host_device *hd, u16 cport_id, message->buffer, buffer_size, cport_out_callback, message); urb->transfer_flags |= URB_ZERO_PACKET; + trace_gb_host_device_send(hd, cport_id, buffer_size); retval = usb_submit_urb(urb, gfp_mask); if (retval) { pr_err("error %d submitting URB\n", retval); @@ -478,12 +480,14 @@ static void cport_in_callback(struct urb *urb) header = urb->transfer_buffer; cport_id = gb_message_cport_unpack(header); - if (cport_id_valid(hd, cport_id)) + if (cport_id_valid(hd, cport_id)) { + trace_gb_host_device_recv(hd, cport_id, urb->actual_length); greybus_data_rcvd(hd, cport_id, urb->transfer_buffer, urb->actual_length); - else + } else { dev_err(dev, "%s: invalid cport id 0x%02x received\n", __func__, cport_id); + } exit: /* put our urb back in the request pool */ retval = usb_submit_urb(urb, GFP_ATOMIC); -- cgit v0.10.2 From f01f7a9851f9c75467373ba7797394dba91825da Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Wed, 23 Sep 2015 09:31:31 -0700 Subject: greybus: loopback: move sysfs entries to /sys/bus/greybus/devices/endo0 Currently we have sysfs entries that are created when the first incoming connection is created as sub-nodes of the module associated with that connection e.g. /sys/bus/grebus/devices/endo0:X where X is the module identifier associated with the new connection. This is conceptually incorrect since the sysfs entries we create actually aren't bound to a module. Depending on the order connections are brought up we can also have a situation where /sys/bus/greybus/devices/endo0:X has high-level control sysfs data-points but /sys/bus/greybus/devices/endo0:Y does not. Rather than needlessly replicate data-points across each endo0:X, endo0:Y, endo0:Z sysfs directories it is more sensible to locate the entries in /sys/bus/greybus/devices/endo0. Signed-off-by: Bryan O'Donoghue Reviewed-by: Patrick Titiano Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 7ccf9a2..3151876 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -874,7 +874,7 @@ static int gb_loopback_connection_init(struct gb_connection *connection) struct gb_loopback *gb; int retval; char name[DEBUGFS_NAMELEN]; - struct kobject *kobj = &connection->bundle->intf->module->dev.kobj; + struct kobject *kobj = &connection->hd->endo->dev.kobj; gb = kzalloc(sizeof(*gb), GFP_KERNEL); if (!gb) @@ -963,7 +963,7 @@ out_sysfs: static void gb_loopback_connection_exit(struct gb_connection *connection) { struct gb_loopback *gb = connection->private; - struct kobject *kobj = &connection->bundle->intf->module->dev.kobj; + struct kobject *kobj = &connection->hd->endo->dev.kobj; if (!IS_ERR_OR_NULL(gb->task)) kthread_stop(gb->task); -- cgit v0.10.2 From 42d7f7e884fcce78301ca88da3434f0fcbf3fee5 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Wed, 23 Sep 2015 09:31:32 -0700 Subject: greybus: loopback: masked out threads should sleep If a thread is masked out it should not consume CPU cycles during a test. We set an arbitrary 100 millisecond sleep time for each masked out thread. Reasonably blunt instrument to ensure threads with nothing to do don't end up thrashing the acquisition/release of mutexes. Signed-off-by: Bryan O'Donoghue Reviewed-by: Patrick Titiano Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 3151876..764ee83 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -693,8 +693,10 @@ static int gb_loopback_fn(void *data) break; mutex_lock(&gb_dev.mutex); - if (!gb_loopback_active(gb)) + if (!gb_loopback_active(gb)) { + ms_wait = 100; goto unlock_continue; + } if (gb_dev.iteration_max) { /* Determine overall lowest count */ low_count = gb->iteration_count; -- cgit v0.10.2 From 8d8d36da750ccba4c9ba9a293b3a338afd0b75b0 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Wed, 23 Sep 2015 09:31:33 -0700 Subject: greybus: loopback: drop redundant endo0 string from debugfs entry name dev_name() will return the endo0 component of the string on it's own, there's no need to include it in the snprintf() when construting the debugfs name. This fixes 'endo0' appearing more than once in the debugfs name - shamefully slipped through testing cb570c93783f ('greybus/loopback: use dev_name to populate sysfsname'). Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 764ee83..e728216 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -906,7 +906,7 @@ static int gb_loopback_connection_init(struct gb_connection *connection) } /* Create per-connection sysfs and debugfs data-points */ - snprintf(name, sizeof(name), "raw_latency_endo0:%s", + snprintf(name, sizeof(name), "raw_latency_%s", dev_name(&connection->dev)); gb->file = debugfs_create_file(name, S_IFREG | S_IRUGO, gb_dev.root, gb, &gb_loopback_debugfs_latency_ops); -- cgit v0.10.2 From c83d4abe1dfd6aec45f594ad756fb5256263c5b8 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Wed, 23 Sep 2015 09:31:34 -0700 Subject: greybus: loopback: remove module specific identifier from debugfs name The datapoint we are using to return metrics across modules and cports shouldn't have a module identifier in it i.e. /sys/kernel/debug/gb_loopback/raw_latency_endo0 not /sys/kernel/debug/gb_loopback/raw_latency_endo0:X This patch removes the module_id used up to this point. Including module_id actually ends up making life harder in user-space so dropping it. Signed-off-by: Bryan O'Donoghue Reviewed-by: Patrick Titiano Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index e728216..5a6354e 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -883,11 +883,10 @@ static int gb_loopback_connection_init(struct gb_connection *connection) return -ENOMEM; gb_loopback_reset_stats(&gb_dev); - /* If this is the first connection - create a module endo0:x entries */ + /* If this is the first connection - create a module endo0 entry */ mutex_lock(&gb_dev.mutex); if (!gb_dev.count) { - snprintf(name, sizeof(name), "raw_latency_endo0:%d", - connection->bundle->intf->module->module_id); + snprintf(name, sizeof(name), "raw_latency_endo0"); gb_dev.file = debugfs_create_file(name, S_IFREG | S_IRUGO, gb_dev.root, &gb_dev, &gb_loopback_debugfs_dev_latency_ops); -- cgit v0.10.2 From c06307c3b476a40dfc853af34af76b591115e42c Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 23 Sep 2015 16:48:07 -0700 Subject: greybus: svc: Use 'dev' instead '&op->connection->dev' We already have a variable to access '&op->connection->dev' directly, lets reuse it. Signed-off-by: Viresh Kumar Reviewed-by: Jean Pihet Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 35e2fb5..056351f 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -469,8 +469,7 @@ static int gb_svc_intf_hot_unplug_recv(struct gb_operation *op) u8 intf_id; if (request->payload_size < sizeof(*hot_unplug)) { - dev_err(&op->connection->dev, - "short hot unplug request received (%zu < %zu)\n", + dev_err(dev, "short hot unplug request received (%zu < %zu)\n", request->payload_size, sizeof(*hot_unplug)); return -EINVAL; } -- cgit v0.10.2 From bbaca7115167088e8177ab8cc7aafdcb8666dea9 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 23 Sep 2015 16:48:08 -0700 Subject: greybus: svc: Allow consecutive hotplug events for the same module There are two cases where the AP may receive hotplug event for an existing interface, without first getting a hot-unplug request for it. - bootrom loading the firmware image and booting into that, which only generates a hotplug event. i.e. no hot-unplug event, as the module never went away. - Or the firmware on the module crashed and sent hotplug request again to the SVC, which got propagated to AP. Handle such cases by first removing the interface, with a clear print message shown to the user. And then following the normal hotplug sequence to add the interface. Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 056351f..0e029ce 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -329,6 +329,25 @@ static int gb_svc_hello(struct gb_operation *op) return 0; } +static void svc_intf_remove(struct gb_connection *connection, + struct gb_interface *intf) +{ + struct greybus_host_device *hd = connection->hd; + struct gb_svc *svc = connection->private; + u8 intf_id = intf->interface_id; + u8 device_id; + + device_id = intf->device_id; + gb_interface_remove(hd, intf_id); + + /* + * Destroy the two-way route between the AP and the interface. + */ + gb_svc_route_destroy(svc, hd->endo->ap_intf_id, intf_id); + + ida_simple_remove(&svc->device_id_map, device_id); +} + /* * 'struct svc_hotplug' should be freed by svc_process_hotplug() before it * returns, irrespective of success or Failure in bringing up the module. @@ -351,6 +370,27 @@ static void svc_process_hotplug(struct work_struct *work) */ intf_id = hotplug->intf_id; + intf = gb_interface_find(hd, intf_id); + if (intf) { + /* + * We have received a hotplug request for an interface that + * already exists. + * + * This can happen in cases like: + * - bootrom loading the firmware image and booting into that, + * which only generates a hotplug event. i.e. no hot-unplug + * event. + * - Or the firmware on the module crashed and sent hotplug + * request again to the SVC, which got propagated to AP. + * + * Remove the interface and add it again, and let user know + * about this with a print message. + */ + dev_info(dev, "Removed interface (%hhu) to add it again\n", + intf_id); + svc_intf_remove(connection, intf); + } + intf = gb_interface_create(hd, intf_id); if (!intf) { dev_err(dev, "%s: Failed to create interface with id %hhu\n", @@ -463,8 +503,6 @@ static int gb_svc_intf_hot_unplug_recv(struct gb_operation *op) struct gb_svc_intf_hot_unplug_request *hot_unplug = request->payload; struct greybus_host_device *hd = op->connection->hd; struct device *dev = &op->connection->dev; - struct gb_svc *svc = op->connection->private; - u8 device_id; struct gb_interface *intf; u8 intf_id; @@ -483,15 +521,7 @@ static int gb_svc_intf_hot_unplug_recv(struct gb_operation *op) return -EINVAL; } - device_id = intf->device_id; - gb_interface_remove(hd, intf_id); - - /* - * Destroy the two-way route between the AP and the interface. - */ - gb_svc_route_destroy(svc, hd->endo->ap_intf_id, intf_id); - - ida_simple_remove(&svc->device_id_map, device_id); + svc_intf_remove(op->connection, intf); return 0; } -- cgit v0.10.2 From 6bec5c78e59dd847c095f4a868baf14be871c8bb Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 24 Sep 2015 14:40:29 -0700 Subject: greybus: svc: Read and clear module's boot status As per the module's boot sequence diagram, the AP needs to read/clear T_TstSrcIncrement attribute on hotplug (svc) events. Implement that. FIXME: This is module-hardware dependent and needs to be extended for every type of module we want to support. [ Based on work by Marti & Eli to clear the attribute with DME set] Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index b3d0c57..117f55e 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -829,6 +829,10 @@ struct gb_svc_dme_peer_set_response { __le16 result_code; } __packed; +/* Attributes for peer get/set operations */ +#define DME_ATTR_SELECTOR_INDEX 0 +#define DME_ATTR_T_TST_SRC_INCREMENT 0x4083 + struct gb_svc_route_create_request { __u8 intf1_id; __u8 dev1_id; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 0e029ce..b59d76f 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -176,6 +176,42 @@ int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, } EXPORT_SYMBOL_GPL(gb_svc_dme_peer_set); +/* + * T_TstSrcIncrement is written by the module on ES2 as a stand-in for boot + * status attribute. AP needs to read and clear it, after reading a non-zero + * value from it. + * + * FIXME: This is module-hardware dependent and needs to be extended for every + * type of module we want to support. + */ +static int gb_svc_read_and_clear_module_boot_status(struct gb_interface *intf) +{ + struct greybus_host_device *hd = intf->hd; + int ret; + u32 value; + + /* Read and clear boot status in T_TstSrcIncrement */ + ret = gb_svc_dme_peer_get(hd->svc, intf->interface_id, + DME_ATTR_T_TST_SRC_INCREMENT, + DME_ATTR_SELECTOR_INDEX, &value); + + if (ret) + return ret; + + /* + * A nonzero boot status indicates the module has finished + * booting. Clear it. + */ + if (!value) { + dev_err(&intf->dev, "Module not ready yet\n"); + return -ENODEV; + } + + return gb_svc_dme_peer_set(hd->svc, intf->interface_id, + DME_ATTR_T_TST_SRC_INCREMENT, + DME_ATTR_SELECTOR_INDEX, 0); +} + int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id) @@ -398,6 +434,10 @@ static void svc_process_hotplug(struct work_struct *work) goto free_svc_hotplug; } + ret = gb_svc_read_and_clear_module_boot_status(intf); + if (ret) + goto destroy_interface; + intf->unipro_mfg_id = le32_to_cpu(hotplug->data.unipro_mfg_id); intf->unipro_prod_id = le32_to_cpu(hotplug->data.unipro_prod_id); intf->ara_vend_id = le32_to_cpu(hotplug->data.ara_vend_id); -- cgit v0.10.2 From 80d1ede88ab081bd901bd5b3dc2461083915d1d1 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 23 Sep 2015 16:48:10 -0700 Subject: greybus: interface: Pass interface pointer to gb_interface_remove() The callers already have a valid interface pointer and there is no need for gb_interface_remove() to find the interface again. Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index c38fb8b..b0253ce 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -183,7 +183,7 @@ put_module: /* * Tear down a previously set up module. */ -static void interface_destroy(struct gb_interface *intf) +void gb_interface_remove(struct gb_interface *intf) { struct gb_module *module; struct gb_bundle *bundle; @@ -207,6 +207,14 @@ static void interface_destroy(struct gb_interface *intf) put_device(&module->dev); } +void gb_interfaces_remove(struct greybus_host_device *hd) +{ + struct gb_interface *intf, *temp; + + list_for_each_entry_safe(intf, temp, &hd->interfaces, links) + gb_interface_remove(intf); +} + /** * gb_interface_init * @@ -273,22 +281,3 @@ free_manifest: kfree(manifest); return ret; } - -void gb_interface_remove(struct greybus_host_device *hd, u8 interface_id) -{ - struct gb_interface *intf = gb_interface_find(hd, interface_id); - - if (intf) - interface_destroy(intf); - else - dev_err(hd->parent, "interface id %d not found\n", - interface_id); -} - -void gb_interfaces_remove(struct greybus_host_device *hd) -{ - struct gb_interface *intf, *temp; - - list_for_each_entry_safe(intf, temp, &hd->interfaces, links) - interface_destroy(intf); -} diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 38210ad..42b5d01 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -59,7 +59,7 @@ struct gb_interface *gb_interface_create(struct greybus_host_device *hd, u8 interface_id); void gb_interface_destroy(struct gb_interface *intf); int gb_interface_init(struct gb_interface *intf, u8 device_id); -void gb_interface_remove(struct greybus_host_device *hd, u8 interface_id); +void gb_interface_remove(struct gb_interface *intf); void gb_interfaces_remove(struct greybus_host_device *hd); int gb_create_bundle_connection(struct gb_interface *intf, u8 class); diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index b59d76f..da2ffd6 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -374,7 +374,7 @@ static void svc_intf_remove(struct gb_connection *connection, u8 device_id; device_id = intf->device_id; - gb_interface_remove(hd, intf_id); + gb_interface_remove(intf); /* * Destroy the two-way route between the AP and the interface. @@ -497,7 +497,7 @@ svc_id_free: ida_put: ida_simple_remove(&svc->device_id_map, device_id); destroy_interface: - gb_interface_remove(hd, intf_id); + gb_interface_remove(intf); free_svc_hotplug: kfree(svc_hotplug); } -- cgit v0.10.2 From 78cd67777b71f38dec710dc26f48b685ef6cf120 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 23 Sep 2015 16:48:11 -0700 Subject: greybus: interface: gb_interface_create() isn't called for existing interfaces The callers are ensuring that another interface doesn't exist with the same interface id and so there is no need to check that from gb_interface_create() anymore. Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index b0253ce..64bf91a 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -127,13 +127,6 @@ struct gb_interface *gb_interface_create(struct greybus_host_device *hd, struct gb_interface *intf; int retval; - intf = gb_interface_find(hd, interface_id); - if (intf) { - dev_err(hd->parent, "Duplicate interface with interface-id: %d will not be created\n", - interface_id); - return NULL; - } - module = gb_module_find(hd, endo_get_module_id(hd->endo, interface_id)); if (!module) return NULL; -- cgit v0.10.2 From 06986a2cbe7a3d20ed8a8651afd80f08948f3ee6 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 23 Sep 2015 16:48:12 -0700 Subject: greybus: firmware: drop 'stage' from ready-to-boot request The spec says that it doesn't need it, so dropping it. Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/firmware.c b/drivers/staging/greybus/firmware.c index 5642bc3..884b7e2 100644 --- a/drivers/staging/greybus/firmware.c +++ b/drivers/staging/greybus/firmware.c @@ -123,7 +123,7 @@ static int gb_firmware_ready_to_boot(struct gb_operation *op) struct gb_connection *connection = op->connection; struct gb_firmware_ready_to_boot_request *rtb_request = op->request->payload; struct device *dev = &connection->dev; - u8 stage, status; + u8 status; if (op->request->payload_size != sizeof(*rtb_request)) { dev_err(dev, "%s: Illegal size of ready to boot request (%zu %zu)\n", @@ -132,7 +132,6 @@ static int gb_firmware_ready_to_boot(struct gb_operation *op) return -EINVAL; } - stage = rtb_request->stage; status = rtb_request->status; /* Return error if the blob was invalid */ diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 117f55e..4819cd0 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -193,7 +193,6 @@ struct gb_firmware_get_firmware_response { /* Firmware protocol Ready to boot request */ struct gb_firmware_ready_to_boot_request { - __u8 stage; __u8 status; } __packed; /* Firmware protocol Ready to boot response has no payload */ -- cgit v0.10.2 From 336dfeaba1f6dd3b07571e0010707f716a1c6ee8 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 23 Sep 2015 16:48:13 -0700 Subject: greybus: firmware: Don't send control-disconnected event for firmware protocol After downloading the firmware for the next boot stage, module's firmware (for current boot stage) jumps into it and the new firmware and sends hotplug request to SVC. On hotplug request from the SVC, the AP first removes the existing interface. At this time, there is no point sending disconnected event for the firmware protocol, for the firmware used in previous stage, as the new firmware wouldn't be aware about it. Set flags for firmware protocol to skip control-disconnected operations. Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/firmware.c b/drivers/staging/greybus/firmware.c index 884b7e2..e04ed6b 100644 --- a/drivers/staging/greybus/firmware.c +++ b/drivers/staging/greybus/firmware.c @@ -210,5 +210,6 @@ static struct gb_protocol firmware_protocol = { .connection_init = gb_firmware_connection_init, .connection_exit = gb_firmware_connection_exit, .request_recv = gb_firmware_request_recv, + .flags = GB_PROTOCOL_SKIP_CONTROL_DISCONNECTED, }; gb_builtin_protocol_driver(firmware_protocol); -- cgit v0.10.2 From 58c85123d9a1801af2558a0c925d90fe1599c27f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Sat, 26 Sep 2015 14:37:59 -0700 Subject: greybus: es1/2: fix use-after-free in completion callback Reset the hcpriv field before returning the message to greybus core in the OUT-URB completion callback. This fixes a use-after-free bug when sending responses to incoming requests as the final reference is then dropped when the message is returned. Reported-by: Michael Scott Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index f2853ff..2c56aaf 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -397,16 +397,16 @@ static void cport_out_callback(struct urb *urb) gb_message_cport_clear(message->header); + spin_lock_irqsave(&es1->cport_out_urb_lock, flags); + message->hcpriv = NULL; + spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); + /* * Tell the submitter that the message send (attempt) is * complete, and report the status. */ greybus_message_sent(hd, message, status); - spin_lock_irqsave(&es1->cport_out_urb_lock, flags); - message->hcpriv = NULL; - spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); - free_urb(es1, urb); } diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 8fee116..22b67d2 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -506,16 +506,16 @@ static void cport_out_callback(struct urb *urb) gb_message_cport_clear(message->header); + spin_lock_irqsave(&es1->cport_out_urb_lock, flags); + message->hcpriv = NULL; + spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); + /* * Tell the submitter that the message send (attempt) is * complete, and report the status. */ greybus_message_sent(hd, message, status); - spin_lock_irqsave(&es1->cport_out_urb_lock, flags); - message->hcpriv = NULL; - spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); - free_urb(es1, urb); } -- cgit v0.10.2 From 6ab1ce4d542ea1b5ffa40321e021d95de47880ea Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Sat, 26 Sep 2015 17:59:15 -0700 Subject: greybus: operation: remove gb_operation_destroy Remove legacy interface to "destroy" operations, which is now just a wrapper for gb_operation_put. The old interface name hides the fact that all operations are refcounted and may live on even after having "destroyed" them. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index 0044b84..a2f0612 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -92,7 +92,8 @@ static int gb_hid_set_report(struct gb_hid *ghid, u8 report_type, u8 report_id, ret = len; } - gb_operation_destroy(operation); + gb_operation_put(operation); + return ret; } diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c index 75b92d6..bf6d11b 100644 --- a/drivers/staging/greybus/i2c.c +++ b/drivers/staging/greybus/i2c.c @@ -218,7 +218,8 @@ static int gb_i2c_transfer_operation(struct gb_i2c_device *gb_i2c_dev, } else if (!gb_i2c_expected_transfer_error(ret)) { pr_err("transfer operation failed (%d)\n", ret); } - gb_operation_destroy(operation); + + gb_operation_put(operation); return ret; } diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 5a6354e..5cbb8cb 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -402,7 +402,8 @@ static int gb_loopback_operation_sync(struct gb_loopback *gb, int type, response_size); } } - gb_operation_destroy(operation); + + gb_operation_put(operation); error: do_gettimeofday(&te); diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index d159831..fae6ee9 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -1035,7 +1035,8 @@ int gb_operation_sync_timeout(struct gb_connection *connection, int type, response_size); } } - gb_operation_destroy(operation); + + gb_operation_put(operation); return ret; } diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 16488d0..0f44ec8 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -131,10 +131,6 @@ struct gb_operation *gb_operation_create(struct gb_connection *connection, gfp_t gfp); void gb_operation_get(struct gb_operation *operation); void gb_operation_put(struct gb_operation *operation); -static inline void gb_operation_destroy(struct gb_operation *operation) -{ - gb_operation_put(operation); -} bool gb_operation_response_alloc(struct gb_operation *operation, size_t response_size, gfp_t gfp); diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index e5d2166..393f28a 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -156,7 +156,8 @@ static int gb_spi_transfer_one_message(struct spi_master *master, } else { pr_err("transfer operation failed (%d)\n", ret); } - gb_operation_destroy(operation); + + gb_operation_put(operation); msg->actual_length = len; msg->status = 0; -- cgit v0.10.2 From 4ee144170a74c990eea2ccec46ab438bc233d2d8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 29 Sep 2015 20:39:17 +0200 Subject: greybus: gpio: handle api change in generic_handle_irq_desc() generic_handle_irq_desc changed the api in the 4.2 kernel, so fix up the gpio driver to handle this properly to keep it working. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 6a04a1b..c41812a 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -384,7 +384,11 @@ static int gb_gpio_request_recv(u8 type, struct gb_operation *op) } local_irq_disable(); +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0) generic_handle_irq_desc(irq, desc); +#else + generic_handle_irq_desc(desc); +#endif local_irq_enable(); return 0; -- cgit v0.10.2 From 3c9426ad27840e2d1175e3b090cba98f539c10c6 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Wed, 30 Sep 2015 11:11:57 +0100 Subject: greybus: gpio: fix generic_handle_irq_desc api change The generic_handle_irq_desc api only have changed in 4.3.0, so check against the correct version, if not will break builds for 4.2.x. Fixes: e7895cfc476 ("gpio: handle api change in generic_handle_irq_desc()") Signed-off-by: Rui Miguel Silva Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index c41812a..6c653ad 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -384,7 +384,7 @@ static int gb_gpio_request_recv(u8 type, struct gb_operation *op) } local_irq_disable(); -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0) generic_handle_irq_desc(irq, desc); #else generic_handle_irq_desc(desc); -- cgit v0.10.2 From adc401417eb87cfb6ce93e0f66eea19ee40fe5b8 Mon Sep 17 00:00:00 2001 From: Michael Scott Date: Fri, 2 Oct 2015 12:05:33 -0700 Subject: greybus: build: android: replace Linaro build specific logic with AOSP equivalents When using greybus build in a different Android setup, it was noted that several portions of this makefile rely on Linaro specific build items. Replace these with more generic build steps. - ANDROID_64 is only defined by Linaro build tasks, use TARGET_ARCH to establish ARCH= parameter for greybus build - KERNEL_TOOLS_PREFIX is only defined by Linaro build tasks. AOSP has a near equivalent variable: TARGET_TOOLS_PREFIX - build-greybus was dependant on subtask: android_kernel a task defined only by Linaro build tasks. Replace with a generic dependancy to the kernel binary located in $OUT (INSTALLED_KERNEL_TARGET). End result is the same: kernel must be built before greybus modules Signed-off-by: Michael Scott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Android.mk b/drivers/staging/greybus/Android.mk index 3357499..47af2d3 100644 --- a/drivers/staging/greybus/Android.mk +++ b/drivers/staging/greybus/Android.mk @@ -5,6 +5,7 @@ $(PRODUCT_OUT)/ramdisk.img: build-greybus endif GREYBUS_MODULE_OUT_PATH := $(PRODUCT_OUT)/root/lib/modules +GREYBUS_CC_PREFIX := $(shell cd `dirname $(TARGET_TOOLS_PREFIX)` && pwd)/$(shell basename $(TARGET_TOOLS_PREFIX)) include $(CLEAR_VARS) GREYBUS_SRC_PATH := $(ANDROID_BUILD_TOP)/external/greybus/ @@ -17,19 +18,14 @@ $(LOCAL_PATH)/$(LOCAL_SRC_FILES): build-greybus include $(BUILD_PREBUILT) KDIRARG := KERNELDIR="${ANDROID_PRODUCT_OUT}/obj/kernel" -ifneq ($(ANDROID_64),) - ARCHARG := ARCH=arm64 - FLAGARG := EXTRA_CFLAGS+=-fno-pic -else - ARCHARG := ARCH=arm - FLAGARG := EXTRA_CFLAGS+=-fno-pic -endif +ARCHARG := ARCH=$(TARGET_ARCH) +FLAGARG := EXTRA_CFLAGS+=-fno-pic ARGS := $(KDIRARG) $(ARCHARG) $(FLAGARG) -build-greybus: android_kernel +build-greybus: $(INSTALLED_KERNEL_TARGET) make clean -C $(GREYBUS_SRC_PATH) cd $(GREYBUS_SRC_PATH) &&\ - $(MAKE) -j$(MAKE_JOBS) CROSS_COMPILE=$(KERNEL_TOOLS_PREFIX) $(ARGS) + $(MAKE) -j$(MAKE_JOBS) CROSS_COMPILE=$(GREYBUS_CC_PREFIX) $(ARGS) mkdir -p $(GREYBUS_MODULE_OUT_PATH) ko=`find $(GREYBUS_SRC_PATH) -type f -name "*.ko"`;\ for i in $$ko; do $(KERNEL_TOOLCHAIN_PATH)strip --strip-unneeded $$i;\ -- cgit v0.10.2 From d3247a3fc7123f7001829a6ece731cf23e56a829 Mon Sep 17 00:00:00 2001 From: Michael Scott Date: Mon, 5 Oct 2015 12:33:04 -0700 Subject: greybus: build: android: fix strip module build step Currently, the greybus module .ko files are quite large and the following error was observed during Android build for each greybus module: strip: Unable to recognise the format of the input file `` Fix the strip build step by replacing the undefined KERNEL_TOOLCHAIN_PATH variable with the GREYBUS_CC_PREFIX variable. Also used as the CROSS_COMPILER value for the module make. Signed-off-by: Michael Scott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Android.mk b/drivers/staging/greybus/Android.mk index 47af2d3..74948cd 100644 --- a/drivers/staging/greybus/Android.mk +++ b/drivers/staging/greybus/Android.mk @@ -28,5 +28,5 @@ build-greybus: $(INSTALLED_KERNEL_TARGET) $(MAKE) -j$(MAKE_JOBS) CROSS_COMPILE=$(GREYBUS_CC_PREFIX) $(ARGS) mkdir -p $(GREYBUS_MODULE_OUT_PATH) ko=`find $(GREYBUS_SRC_PATH) -type f -name "*.ko"`;\ - for i in $$ko; do $(KERNEL_TOOLCHAIN_PATH)strip --strip-unneeded $$i;\ + for i in $$ko; do $(GREYBUS_CC_PREFIX)strip --strip-unneeded $$i;\ mv $$i $(GREYBUS_MODULE_OUT_PATH)/; done; -- cgit v0.10.2 From 1575ef18aea40ab1f6915917901a80ca780188a6 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 7 Oct 2015 15:40:24 -0400 Subject: greybus: svc: skip setting flags for boot over unipro We need to skip setting E2EFC and other flags to the SVC connection create request, for all cports, on an interface that need to boot over unipro, i.e. interfaces required to download firmware. This also adds a FIXME as we need to do it differently for ES3. Tested-by: Eli Sennesh Signed-off-by: Viresh Kumar Signed-off by: Eli Sennesh Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 05a9b54..6b56b30 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -328,16 +328,19 @@ gb_connection_svc_connection_create(struct gb_connection *connection) { struct greybus_host_device *hd = connection->hd; struct gb_protocol *protocol = connection->protocol; + struct gb_interface *intf; int ret; if (protocol->flags & GB_PROTOCOL_SKIP_SVC_CONNECTION) return 0; + intf = connection->bundle->intf; ret = gb_svc_connection_create(hd->svc, hd->endo->ap_intf_id, connection->hd_cport_id, - connection->bundle->intf->interface_id, - connection->intf_cport_id); + intf->interface_id, + connection->intf_cport_id, + intf->boot_over_unipro); if (ret) { dev_err(&connection->dev, "failed to create svc connection: %d\n", ret); diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 4819cd0..dbf409f 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -832,6 +832,13 @@ struct gb_svc_dme_peer_set_response { #define DME_ATTR_SELECTOR_INDEX 0 #define DME_ATTR_T_TST_SRC_INCREMENT 0x4083 +/* Return value from TST_SRC_INCREMENT */ +#define DME_TSI_SPI_BOOT_STARTED 0x02 +#define DME_TSI_TRUSTED_SPI_BOOT_FINISHED 0x03 +#define DME_TSI_UNTRUSTED_SPI_BOOT_FINISHED 0x04 +#define DME_TSI_UNIPRO_BOOT_STARTED 0x06 +#define DME_TSI_FALLBACK_UNIPRO_BOOT_STARTED 0x09 + struct gb_svc_route_create_request { __u8 intf1_id; __u8 dev1_id; diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 42b5d01..9bce94f 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -36,6 +36,9 @@ struct gb_interface { struct gb_module *module; struct greybus_host_device *hd; + + /* The interface needs to boot over unipro */ + bool boot_over_unipro; }; #define to_gb_interface(d) container_of(d, struct gb_interface, dev) diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index da2ffd6..4b9eb38 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -207,6 +207,18 @@ static int gb_svc_read_and_clear_module_boot_status(struct gb_interface *intf) return -ENODEV; } + /* + * Check if the module needs to boot from unipro. + * For ES2: We need to check lowest 8 bits of 'value'. + * For ES3: We need to check highest 8 bits out of 32 of 'value'. + * + * FIXME: Add code to find if we are on ES2 or ES3 to have separate + * checks. + */ + if (value == DME_TSI_UNIPRO_BOOT_STARTED || + value == DME_TSI_FALLBACK_UNIPRO_BOOT_STARTED) + intf->boot_over_unipro = true; + return gb_svc_dme_peer_set(hd->svc, intf->interface_id, DME_ATTR_T_TST_SRC_INCREMENT, DME_ATTR_SELECTOR_INDEX, 0); @@ -214,7 +226,8 @@ static int gb_svc_read_and_clear_module_boot_status(struct gb_interface *intf) int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, - u8 intf2_id, u16 cport2_id) + u8 intf2_id, u16 cport2_id, + bool boot_over_unipro) { struct gb_svc_conn_create_request request; @@ -227,7 +240,16 @@ int gb_svc_connection_create(struct gb_svc *svc, * for now. */ request.tc = 0; - request.flags = CPORT_FLAGS_CSV_N | CPORT_FLAGS_E2EFC; + + /* + * We need to skip setting E2EFC and other flags to the connection + * create request, for all cports, on an interface that need to boot + * over unipro, i.e. interfaces required to download firmware. + */ + if (boot_over_unipro) + request.flags = CPORT_FLAGS_CSV_N | CPORT_FLAGS_CSD_N; + else + request.flags = CPORT_FLAGS_CSV_N | CPORT_FLAGS_E2EFC; return gb_operation_sync(svc->connection, GB_SVC_TYPE_CONN_CREATE, &request, sizeof(request), NULL, 0); diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index 75518f8..3357d31 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -14,7 +14,7 @@ struct gb_svc; int gb_svc_intf_reset(struct gb_svc *svc, u8 intf_id); int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, - u8 intf2_id, u16 cport2_id); + u8 intf2_id, u16 cport2_id, bool boot_over_unipro); void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id); int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, -- cgit v0.10.2 From e0f875c336f792d4c2b0d09436426724ae14713e Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Thu, 8 Oct 2015 12:10:51 +0100 Subject: greybus: sdio: add field to get_caps response Frequency maximum and minimum are needed to complete the configuration of the controller. Add them to get_caps response operation. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index dbf409f..44a2133 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -1002,6 +1002,8 @@ struct gb_sdio_get_caps_response { __le32 ocr; __le16 max_blk_count; __le16 max_blk_size; + __le32 f_min; + __le32 f_max; } __packed; /* set ios request: response has no payload */ diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index bfa1181..ff68956 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -122,6 +122,10 @@ static int gb_sdio_get_caps(struct gb_sdio_host *host) mmc->ocr_avail_sd = mmc->ocr_avail; mmc->ocr_avail_mmc = mmc->ocr_avail; + /* get frequency range values */ + mmc->f_min = le32_to_cpu(response.f_min); + mmc->f_max = le32_to_cpu(response.f_max); + return 0; } -- cgit v0.10.2 From 6cac7dc3aaaef8161ac80c5980cec10427996abf Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Thu, 8 Oct 2015 12:10:52 +0100 Subject: greybus: sdio: fix card removable detection In kernel versions bellow 3.15, the mmc_card_is_removable helper function has an extra check used for a suspend/resume hack. This made the gd_sdio_process_event to behave badly handling the module card insert event in that versions. So, just test bit the flag that we need, instead of using the helper function. This way will work in all kernel versions. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index ff68956..e5e3b77 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -144,7 +144,7 @@ static int _gb_sdio_process_events(struct gb_sdio_host *host, u8 event) u8 state_changed = 0; if (event & GB_SDIO_CARD_INSERTED) { - if (!mmc_card_is_removable(host->mmc)) + if (host->mmc->caps & MMC_CAP_NONREMOVABLE) return 0; if (host->card_present) return 0; @@ -153,7 +153,7 @@ static int _gb_sdio_process_events(struct gb_sdio_host *host, u8 event) } if (event & GB_SDIO_CARD_REMOVED) { - if (!mmc_card_is_removable(host->mmc)) + if (host->mmc->caps & MMC_CAP_NONREMOVABLE) return 0; if (!(host->card_present)) return 0; -- cgit v0.10.2 From dcb8d8d3e1f929e155cc262d9fbe060f94c02e35 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Thu, 8 Oct 2015 12:10:53 +0100 Subject: greybus: sdio: convert greybus ocr values to mmc ones It was missing the translation between the ocr vdd values of greybus to mmc_core values. This would make the detection of range voltage fail. mmc: host doesn't support card's voltages Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index e5e3b77..21a7b67 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -87,12 +87,35 @@ static void _gb_sdio_set_host_caps(struct gb_sdio_host *host, u32 r) host->card_present = true; } +static u32 _gb_sdio_get_host_ocr(u32 ocr) +{ + return (((ocr & GB_SDIO_VDD_165_195) ? MMC_VDD_165_195 : 0) | + ((ocr & GB_SDIO_VDD_20_21) ? MMC_VDD_20_21 : 0) | + ((ocr & GB_SDIO_VDD_21_22) ? MMC_VDD_21_22 : 0) | + ((ocr & GB_SDIO_VDD_22_23) ? MMC_VDD_22_23 : 0) | + ((ocr & GB_SDIO_VDD_23_24) ? MMC_VDD_23_24 : 0) | + ((ocr & GB_SDIO_VDD_24_25) ? MMC_VDD_24_25 : 0) | + ((ocr & GB_SDIO_VDD_25_26) ? MMC_VDD_25_26 : 0) | + ((ocr & GB_SDIO_VDD_26_27) ? MMC_VDD_26_27 : 0) | + ((ocr & GB_SDIO_VDD_27_28) ? MMC_VDD_27_28 : 0) | + ((ocr & GB_SDIO_VDD_28_29) ? MMC_VDD_28_29 : 0) | + ((ocr & GB_SDIO_VDD_29_30) ? MMC_VDD_29_30 : 0) | + ((ocr & GB_SDIO_VDD_30_31) ? MMC_VDD_30_31 : 0) | + ((ocr & GB_SDIO_VDD_31_32) ? MMC_VDD_31_32 : 0) | + ((ocr & GB_SDIO_VDD_32_33) ? MMC_VDD_32_33 : 0) | + ((ocr & GB_SDIO_VDD_33_34) ? MMC_VDD_33_34 : 0) | + ((ocr & GB_SDIO_VDD_34_35) ? MMC_VDD_34_35 : 0) | + ((ocr & GB_SDIO_VDD_35_36) ? MMC_VDD_35_36 : 0) + ); +} + static int gb_sdio_get_caps(struct gb_sdio_host *host) { struct gb_sdio_get_caps_response response; struct mmc_host *mmc = host->mmc; u16 data_max; u32 blksz; + u32 ocr; u32 r; int ret; @@ -117,7 +140,8 @@ static int gb_sdio_get_caps(struct gb_sdio_host *host) host->data_max = data_max; /* get ocr supported values */ - mmc->ocr_avail = le32_to_cpu(response.ocr); + ocr = _gb_sdio_get_host_ocr(le32_to_cpu(response.ocr)); + mmc->ocr_avail = ocr; mmc->ocr_avail_sdio = mmc->ocr_avail; mmc->ocr_avail_sd = mmc->ocr_avail; mmc->ocr_avail_mmc = mmc->ocr_avail; -- cgit v0.10.2 From f064b872e7a0ee48d5d33278aeb30ffa7ee1c5f5 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Thu, 8 Oct 2015 12:10:54 +0100 Subject: greybus: sdio: clarify operator precedence When translating capabilities from greybus to mmc values add some parentheses to clarify operation precedence and avoid static analyses warnings. [sdio.c:81]: (style) Clarify calculation precedence for '&' and '?' Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index 21a7b67..aaca70e 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -55,30 +55,30 @@ static void _gb_sdio_set_host_caps(struct gb_sdio_host *host, u32 r) u32 caps = 0; u32 caps2 = 0; - caps = (r & GB_SDIO_CAP_NONREMOVABLE ? MMC_CAP_NONREMOVABLE : 0) | - (r & GB_SDIO_CAP_4_BIT_DATA ? MMC_CAP_4_BIT_DATA : 0) | - (r & GB_SDIO_CAP_8_BIT_DATA ? MMC_CAP_8_BIT_DATA : 0) | - (r & GB_SDIO_CAP_MMC_HS ? MMC_CAP_MMC_HIGHSPEED : 0) | - (r & GB_SDIO_CAP_SD_HS ? MMC_CAP_SD_HIGHSPEED : 0) | - (r & GB_SDIO_CAP_ERASE ? MMC_CAP_ERASE : 0) | - (r & GB_SDIO_CAP_1_2V_DDR ? MMC_CAP_1_2V_DDR : 0) | - (r & GB_SDIO_CAP_1_8V_DDR ? MMC_CAP_1_8V_DDR : 0) | - (r & GB_SDIO_CAP_POWER_OFF_CARD ? MMC_CAP_POWER_OFF_CARD : 0) | - (r & GB_SDIO_CAP_UHS_SDR12 ? MMC_CAP_UHS_SDR12 : 0) | - (r & GB_SDIO_CAP_UHS_SDR25 ? MMC_CAP_UHS_SDR25 : 0) | - (r & GB_SDIO_CAP_UHS_SDR50 ? MMC_CAP_UHS_SDR50 : 0) | - (r & GB_SDIO_CAP_UHS_SDR104 ? MMC_CAP_UHS_SDR104 : 0) | - (r & GB_SDIO_CAP_UHS_DDR50 ? MMC_CAP_UHS_DDR50 : 0) | - (r & GB_SDIO_CAP_DRIVER_TYPE_A ? MMC_CAP_DRIVER_TYPE_A : 0) | - (r & GB_SDIO_CAP_DRIVER_TYPE_C ? MMC_CAP_DRIVER_TYPE_C : 0) | - (r & GB_SDIO_CAP_DRIVER_TYPE_D ? MMC_CAP_DRIVER_TYPE_D : 0); - - caps2 = (r & GB_SDIO_CAP_HS200_1_2V ? MMC_CAP2_HS200_1_2V_SDR : 0) | + caps = ((r & GB_SDIO_CAP_NONREMOVABLE) ? MMC_CAP_NONREMOVABLE : 0) | + ((r & GB_SDIO_CAP_4_BIT_DATA) ? MMC_CAP_4_BIT_DATA : 0) | + ((r & GB_SDIO_CAP_8_BIT_DATA) ? MMC_CAP_8_BIT_DATA : 0) | + ((r & GB_SDIO_CAP_MMC_HS) ? MMC_CAP_MMC_HIGHSPEED : 0) | + ((r & GB_SDIO_CAP_SD_HS) ? MMC_CAP_SD_HIGHSPEED : 0) | + ((r & GB_SDIO_CAP_ERASE) ? MMC_CAP_ERASE : 0) | + ((r & GB_SDIO_CAP_1_2V_DDR) ? MMC_CAP_1_2V_DDR : 0) | + ((r & GB_SDIO_CAP_1_8V_DDR) ? MMC_CAP_1_8V_DDR : 0) | + ((r & GB_SDIO_CAP_POWER_OFF_CARD) ? MMC_CAP_POWER_OFF_CARD : 0) | + ((r & GB_SDIO_CAP_UHS_SDR12) ? MMC_CAP_UHS_SDR12 : 0) | + ((r & GB_SDIO_CAP_UHS_SDR25) ? MMC_CAP_UHS_SDR25 : 0) | + ((r & GB_SDIO_CAP_UHS_SDR50) ? MMC_CAP_UHS_SDR50 : 0) | + ((r & GB_SDIO_CAP_UHS_SDR104) ? MMC_CAP_UHS_SDR104 : 0) | + ((r & GB_SDIO_CAP_UHS_DDR50) ? MMC_CAP_UHS_DDR50 : 0) | + ((r & GB_SDIO_CAP_DRIVER_TYPE_A) ? MMC_CAP_DRIVER_TYPE_A : 0) | + ((r & GB_SDIO_CAP_DRIVER_TYPE_C) ? MMC_CAP_DRIVER_TYPE_C : 0) | + ((r & GB_SDIO_CAP_DRIVER_TYPE_D) ? MMC_CAP_DRIVER_TYPE_D : 0); + + caps2 = ((r & GB_SDIO_CAP_HS200_1_2V) ? MMC_CAP2_HS200_1_2V_SDR : 0) | #ifdef MMC_HS400_SUPPORTED - (r & GB_SDIO_CAP_HS400_1_2V ? MMC_CAP2_HS400_1_2V : 0) | - (r & GB_SDIO_CAP_HS400_1_8V ? MMC_CAP2_HS400_1_8V : 0) | + ((r & GB_SDIO_CAP_HS400_1_2V) ? MMC_CAP2_HS400_1_2V : 0) | + ((r & GB_SDIO_CAP_HS400_1_8V) ? MMC_CAP2_HS400_1_8V : 0) | #endif - (r & GB_SDIO_CAP_HS200_1_8V ? MMC_CAP2_HS200_1_8V_SDR : 0); + ((r & GB_SDIO_CAP_HS200_1_8V) ? MMC_CAP2_HS200_1_8V_SDR : 0); host->mmc->caps = caps | MMC_CAP_NEEDS_POLL; host->mmc->caps2 = caps2; -- cgit v0.10.2 From 82ee1e6cde3d9500f3dfc9cefc259b89e87a8865 Mon Sep 17 00:00:00 2001 From: Fabien Parent Date: Tue, 13 Oct 2015 17:34:50 +0200 Subject: greybus: es2: implement cport reset control request Toshiba UniPro IP requires to reset the CPort that has been used in a previous connection. This commit implement a new control request in order to reset CPorts on an APBridgeA. Signed-off-by: Fabien Parent Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 22b67d2..f077038 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -58,6 +58,9 @@ static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); /* vendor request to get the number of cports available */ #define REQUEST_CPORT_COUNT 0x04 +/* vendor request to reset a cport state */ +#define REQUEST_RESET_CPORT 0x05 + /* * @endpoint: bulk in endpoint for CPort data * @urb: array of urbs for the CPort in messages @@ -376,10 +379,44 @@ static void message_cancel(struct gb_message *message) usb_free_urb(urb); } +static int cport_reset(struct greybus_host_device *hd, u16 cport_id) +{ + struct es1_ap_dev *es1 = hd_to_es1(hd); + struct usb_device *udev = es1->usb_dev; + int retval; + + retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + REQUEST_RESET_CPORT, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, 0, cport_id, + NULL, 0, ES1_TIMEOUT); + if (retval < 0) { + dev_err(&udev->dev, "failed to reset cport %hu: %d\n", cport_id, + retval); + return retval; + } + + return 0; +} + +static int cport_enable(struct greybus_host_device *hd, u16 cport_id) +{ + int retval; + + if (cport_id != GB_SVC_CPORT_ID) { + retval = cport_reset(hd, cport_id); + if (retval) + return retval; + } + + return 0; +} + static struct greybus_host_driver es1_driver = { .hd_priv_size = sizeof(struct es1_ap_dev), .message_send = message_send, .message_cancel = message_cancel, + .cport_enable = cport_enable, }; /* Common function to report consistent warnings based on URB status */ -- cgit v0.10.2 From 67b81757dad8979e0cd85512fc0e5dfe80e2e96f Mon Sep 17 00:00:00 2001 From: Fabien Parent Date: Tue, 13 Oct 2015 17:34:51 +0200 Subject: greybus: connection: destroy connection on failing to bind it gb_connection_bind_protocol() returns proper error codes now and we should destroy the connection on failures. This change also fixes a NULL deref on hotplug when the control connection fails to initialize. Signed-off-by: Fabien Parent Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 6b56b30..bd3f83b 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -239,7 +239,14 @@ gb_connection_create_range(struct greybus_host_device *hd, spin_unlock_irq(&gb_connections_lock); - gb_connection_bind_protocol(connection); + retval = gb_connection_bind_protocol(connection); + if (retval) { + dev_err(&connection->dev, "failed to bind protocol: %d\n", + retval); + gb_connection_destroy(connection); + return NULL; + } + if (!connection->protocol) dev_warn(&connection->dev, "protocol 0x%02hhx handler not found\n", protocol_id); -- cgit v0.10.2 From 305a031e1ae006eb3cbac5c4c7fd441596f0fe45 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 13 Oct 2015 19:10:20 +0200 Subject: greybus: es1/es2: clean up error messages Replace the remaining pr_err with dev_err, and drop redundant function prefixes. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 2c56aaf..4d70e89 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -193,7 +193,8 @@ static int message_send(struct greybus_host_device *hd, u16 cport_id, * the target CPort id before filling it in. */ if (!cport_id_valid(hd, cport_id)) { - pr_err("invalid destination cport 0x%02x\n", cport_id); + dev_err(&udev->dev, "invalid destination cport 0x%02x\n", + cport_id); return -EINVAL; } @@ -219,7 +220,7 @@ static int message_send(struct greybus_host_device *hd, u16 cport_id, trace_gb_host_device_send(hd, cport_id, buffer_size); retval = usb_submit_urb(urb, gfp_mask); if (retval) { - pr_err("error %d submitting URB\n", retval); + dev_err(&udev->dev, "failed to submit out-urb: %d\n", retval); spin_lock_irqsave(&es1->cport_out_urb_lock, flags); message->hcpriv = NULL; @@ -363,7 +364,7 @@ static void cport_in_callback(struct urb *urb) } if (urb->actual_length < sizeof(*header)) { - dev_err(dev, "%s: short message received\n", __func__); + dev_err(dev, "short message received\n"); goto exit; } @@ -376,15 +377,13 @@ static void cport_in_callback(struct urb *urb) greybus_data_rcvd(hd, cport_id, urb->transfer_buffer, urb->actual_length); } else { - dev_err(dev, "%s: invalid cport id 0x%02x received\n", - __func__, cport_id); + dev_err(dev, "invalid cport id 0x%02x received\n", cport_id); } exit: /* put our urb back in the request pool */ retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) - dev_err(dev, "%s: error %d in submitting urb.\n", - __func__, retval); + dev_err(dev, "failed to resubmit in-urb: %d\n", retval); } static void cport_out_callback(struct urb *urb) diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index f077038..5faf80a 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -298,7 +298,8 @@ static int message_send(struct greybus_host_device *hd, u16 cport_id, * the target CPort id before filling it in. */ if (!cport_id_valid(hd, cport_id)) { - pr_err("invalid destination cport 0x%02x\n", cport_id); + dev_err(&udev->dev, "invalid destination cport 0x%02x\n", + cport_id); return -EINVAL; } @@ -326,7 +327,7 @@ static int message_send(struct greybus_host_device *hd, u16 cport_id, trace_gb_host_device_send(hd, cport_id, buffer_size); retval = usb_submit_urb(urb, gfp_mask); if (retval) { - pr_err("error %d submitting URB\n", retval); + dev_err(&udev->dev, "failed to submit out-urb: %d\n", retval); spin_lock_irqsave(&es1->cport_out_urb_lock, flags); message->hcpriv = NULL; @@ -509,7 +510,7 @@ static void cport_in_callback(struct urb *urb) } if (urb->actual_length < sizeof(*header)) { - dev_err(dev, "%s: short message received\n", __func__); + dev_err(dev, "short message received\n"); goto exit; } @@ -522,15 +523,13 @@ static void cport_in_callback(struct urb *urb) greybus_data_rcvd(hd, cport_id, urb->transfer_buffer, urb->actual_length); } else { - dev_err(dev, "%s: invalid cport id 0x%02x received\n", - __func__, cport_id); + dev_err(dev, "invalid cport id 0x%02x received\n", cport_id); } exit: /* put our urb back in the request pool */ retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) - dev_err(dev, "%s: error %d in submitting urb.\n", - __func__, retval); + dev_err(dev, "failed to resubmit in-urb: %d\n", retval); } static void cport_out_callback(struct urb *urb) -- cgit v0.10.2 From aae5a44ff5a22c3c3398e68c89a4513c75725fd7 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 13 Oct 2015 19:10:21 +0200 Subject: greybus: connection: replace pr_err with dev_err Replace a couple of pr_err with more informative dev_err and clean up the messages somewhat. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index bd3f83b..1158674 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -178,7 +178,7 @@ gb_connection_create_range(struct greybus_host_device *hd, * about holding the connection lock. */ if (bundle && gb_connection_intf_find(bundle->intf, cport_id)) { - pr_err("duplicate interface cport id 0x%04hx\n", cport_id); + dev_err(parent, "cport 0x%04hx already connected\n", cport_id); return NULL; } @@ -223,8 +223,8 @@ gb_connection_create_range(struct greybus_host_device *hd, connection->hd_cport_id = CPORT_ID_BAD; put_device(&connection->dev); - pr_err("failed to add connection device for cport 0x%04hx\n", - cport_id); + dev_err(parent, "failed to register connection to cport %04hx: %d\n", + cport_id, retval); goto err_remove_ida; } -- cgit v0.10.2 From ff65e20ee534a5720bacd0b4058458e234ec51d6 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 13 Oct 2015 19:10:22 +0200 Subject: greybus: operation: drop OOM-response FIXME Drop FIXME about sending responses in OOM situations. If we fail to allocate an operation for an incoming request, we have bigger problems than to worry about sending a response. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index fae6ee9..969309e 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -828,7 +828,7 @@ static void gb_connection_recv_request(struct gb_connection *connection, type, data, size); if (!operation) { dev_err(&connection->dev, "can't create operation\n"); - return; /* XXX Respond with pre-allocated ENOMEM */ + return; } ret = gb_operation_get_active(operation); -- cgit v0.10.2 From 0b1118a9efa9a00e449158bb7bb74249dc92c888 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 13 Oct 2015 19:10:23 +0200 Subject: greybus: operation: clean up error messages Clean up and improve error messages. Demote a warning message to warning level. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 969309e..56375c9 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -827,7 +827,7 @@ static void gb_connection_recv_request(struct gb_connection *connection, operation = gb_operation_create_incoming(connection, operation_id, type, data, size); if (!operation) { - dev_err(&connection->dev, "can't create operation\n"); + dev_err(&connection->dev, "can't create incoming operation\n"); return; } @@ -864,14 +864,16 @@ static void gb_connection_recv_response(struct gb_connection *connection, operation = gb_operation_find_outgoing(connection, operation_id); if (!operation) { - dev_err(&connection->dev, "operation not found\n"); + dev_err(&connection->dev, "unexpected response 0x%04hx received\n", + operation_id); return; } message = operation->response; message_size = sizeof(*message->header) + message->payload_size; if (!errno && size != message_size) { - dev_err(&connection->dev, "bad message (0x%02hhx) size (%zu != %zu)\n", + dev_err(&connection->dev, + "malformed response of type 0x%02hhx received (%zu != %zu)\n", message->header->type, size, message_size); errno = -EMSGSIZE; } @@ -903,13 +905,13 @@ void gb_connection_recv(struct gb_connection *connection, u16 operation_id; if (connection->state != GB_CONNECTION_STATE_ENABLED) { - dev_err(&connection->dev, "dropping %zu received bytes\n", + dev_warn(&connection->dev, "dropping %zu received bytes\n", size); return; } if (size < sizeof(header)) { - dev_err(&connection->dev, "message too small\n"); + dev_err(&connection->dev, "short message received\n"); return; } @@ -918,8 +920,8 @@ void gb_connection_recv(struct gb_connection *connection, msg_size = le16_to_cpu(header.size); if (size < msg_size) { dev_err(&connection->dev, - "incomplete message received for type 0x%02hhx: 0x%04x (%zu < %zu)\n", - header.type, le16_to_cpu(header.operation_id), size, + "incomplete message 0x%04hx of type 0x%02hhx received (%zu < %zu)\n", + le16_to_cpu(header.operation_id), header.type, size, msg_size); return; /* XXX Should still complete operation */ } @@ -1027,7 +1029,8 @@ int gb_operation_sync_timeout(struct gb_connection *connection, int type, ret = gb_operation_request_send_sync_timeout(operation, timeout); if (ret) { - dev_err(&connection->dev, "synchronous operation failed: 0x%02hhx (%d)\n", + dev_err(&connection->dev, + "synchronous operation of type 0x%02hhx failed: %d\n", type, ret); } else { if (response_size) { -- cgit v0.10.2 From 78033844daa64c83d91dca73eb1fbcae56c42fac Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 13 Oct 2015 19:10:24 +0200 Subject: greybus: protocol: warn on bad deregistration A protocol should be deregistered exactly once when the protocol module is being unloaded. This means that protocol deregister will never be called with active users as we take a module reference when looking up a protocol. Remove comment suggesting that we could one day forcefully stop a user of a protocol, and issue a big warning if a protocol is deregistered more than once or at some other time than during module unload (e.g. with active users). Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index c93f963..140baa6 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -102,36 +102,24 @@ EXPORT_SYMBOL_GPL(__gb_protocol_register); /* * De-register a previously registered protocol. - * - * XXX Currently this fails (and reports an error to the caller) if - * XXX the protocol is currently in use. We may want to forcefully - * XXX kill off a protocol and all its active users at some point. - * XXX But I think that's better handled by quiescing modules that - * XXX have users and having those users drop their reference. - * - * Returns true if successful, false otherwise. */ -int gb_protocol_deregister(struct gb_protocol *protocol) +void gb_protocol_deregister(struct gb_protocol *protocol) { - u8 protocol_count = 0; - if (!protocol) - return 0; + return; spin_lock_irq(&gb_protocols_lock); protocol = gb_protocol_find(protocol->id, protocol->major, protocol->minor); - if (protocol) { - protocol_count = protocol->count; - if (!protocol_count) - list_del(&protocol->links); + if (WARN_ON(!protocol || protocol->count)) { + spin_unlock_irq(&gb_protocols_lock); + return; } - spin_unlock_irq(&gb_protocols_lock); - if (protocol) - pr_info("Deregistered %s protocol.\n", protocol->name); + list_del(&protocol->links); + spin_unlock_irq(&gb_protocols_lock); - return protocol && !protocol_count; + pr_info("Deregistered %s protocol.\n", protocol->name); } EXPORT_SYMBOL_GPL(gb_protocol_deregister); diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index d856885..2e0f4d6 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -46,7 +46,7 @@ struct gb_protocol { }; int __gb_protocol_register(struct gb_protocol *protocol, struct module *module); -int gb_protocol_deregister(struct gb_protocol *protocol); +void gb_protocol_deregister(struct gb_protocol *protocol); #define gb_protocol_register(protocol) \ __gb_protocol_register(protocol, THIS_MODULE) -- cgit v0.10.2 From 519bf3c3b9c09619ca90f67b194714bb5f30d491 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 13 Oct 2015 19:10:25 +0200 Subject: greybus: protocol: warn on protocol put errors Issue a warning if we fail to look up a protocol when dropping a reference. This should never happen as we hold a reference to the protocol module and protocols should only be deregistered at module unload. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index 140baa6..b9de152 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -188,7 +188,6 @@ void gb_protocol_put(struct gb_protocol *protocol) u8 id; u8 major; u8 minor; - u8 protocol_count; id = protocol->id; major = protocol->major; @@ -196,16 +195,11 @@ void gb_protocol_put(struct gb_protocol *protocol) spin_lock_irq(&gb_protocols_lock); protocol = gb_protocol_find(id, major, minor); - if (protocol) { - protocol_count = protocol->count; - if (protocol_count) - protocol->count--; - module_put(protocol->owner); - } + if (WARN_ON(!protocol || !protocol->count)) + goto out; + + protocol->count--; + module_put(protocol->owner); +out: spin_unlock_irq(&gb_protocols_lock); - if (protocol) - WARN_ON(!protocol_count); - else - pr_err("protocol id %hhu version %hhu.%hhu not found\n", - id, major, minor); } -- cgit v0.10.2 From 4505c4d44a660866f2006eacafcb8c7d182ec182 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 13 Oct 2015 19:10:26 +0200 Subject: greybus: protocol: make version debug message more informative Include function, protocol name and id when printing the version response debug message. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index b9de152..41190e8 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -155,10 +155,11 @@ int gb_protocol_get_version(struct gb_connection *connection) { struct gb_protocol_version_request request; struct gb_protocol_version_response response; + struct gb_protocol *protocol = connection->protocol; int retval; - request.major = connection->protocol->major; - request.minor = connection->protocol->minor; + request.major = protocol->major; + request.minor = protocol->minor; retval = gb_operation_sync(connection, GB_REQUEST_TYPE_PROTOCOL_VERSION, &request, sizeof(request), &response, @@ -176,8 +177,10 @@ int gb_protocol_get_version(struct gb_connection *connection) connection->module_major = response.major; connection->module_minor = response.minor; - dev_dbg(&connection->dev, "version_major = %u version_minor = %u\n", - response.major, response.minor); + + dev_dbg(&connection->dev, "%s - %s (0x%02hhx) v%hhu.%hhu\n", __func__, + protocol->name, protocol->id, + response.major, response.minor); return 0; } -- cgit v0.10.2 From d4efa68803667ab9d3ff6786462d2702b89e58de Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 13 Oct 2015 19:10:27 +0200 Subject: greybus: vibrator: add missing protocol-register error handling Add missing error handling when registering the vibrator protocol during module init. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/vibrator.c b/drivers/staging/greybus/vibrator.c index fd40cda..2b80326 100644 --- a/drivers/staging/greybus/vibrator.c +++ b/drivers/staging/greybus/vibrator.c @@ -171,7 +171,16 @@ static __init int protocol_init(void) if (retval) return retval; - return gb_protocol_register(&vibrator_protocol); + retval = gb_protocol_register(&vibrator_protocol); + if (retval) + goto err_class_unregister; + + return 0; + +err_class_unregister: + class_unregister(&vibrator_class); + + return retval; } module_init(protocol_init); -- cgit v0.10.2 From 9942fc8b14f21525622b85031b19c7ab5b16b339 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 13 Oct 2015 19:10:28 +0200 Subject: greybus: protocol: make protocol-lookup error message more informative Make protocol lookup error more informative, by moving it to gb_connection_bind_protocol and using dev_err. Also make sure to use hex format for the protocol id as that is what is used everywhere else. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 1158674..ca812f8 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -551,8 +551,13 @@ int gb_connection_bind_protocol(struct gb_connection *connection) protocol = gb_protocol_get(connection->protocol_id, connection->major, connection->minor); - if (!protocol) + if (!protocol) { + dev_warn(&connection->dev, + "protocol 0x%02hhx version %hhu.%hhu not found\n", + connection->protocol_id, + connection->major, connection->minor); return 0; + } connection->protocol = protocol; /* diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index 41190e8..889cff2 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -144,9 +144,6 @@ struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor) if (protocol) WARN_ON(protocol_count == U8_MAX); - else - pr_err("protocol id %hhu version %hhu.%hhu not found\n", - id, major, minor); return protocol; } -- cgit v0.10.2 From 7f0efa06795fea3f04578cf3016d393f9293cd4f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 13 Oct 2015 19:10:29 +0200 Subject: greybus: connection: remove duplicate protocol lookup error message Remove duplicate protocol lookup error message, which has already been logged. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index ca812f8..743ea67 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -247,10 +247,6 @@ gb_connection_create_range(struct greybus_host_device *hd, return NULL; } - if (!connection->protocol) - dev_warn(&connection->dev, - "protocol 0x%02hhx handler not found\n", protocol_id); - return connection; err_free_connection: -- cgit v0.10.2 From 650f38e3160aeaaa77c9e689850ba4c4f78ecb2e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 13 Oct 2015 19:10:30 +0200 Subject: greybus: build: add pwm to config options to enable Add PWM to the kernel config options that shall be enabled. When PWM is not enabled connection init will fail with greybus endo0:3:4:9:9: failed to register PWM: -22 when using the default manifest. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index af28053..a627340 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -51,7 +51,7 @@ INSTALL_MOD_PATH ?= /.. PWD := $(shell pwd) # kernel config option that shall be enable -CONFIG_OPTIONS_ENABLE := SYSFS SPI USB SND_SOC MMC LEDS_CLASS +CONFIG_OPTIONS_ENABLE := PWM SYSFS SPI USB SND_SOC MMC LEDS_CLASS # kernel config option that shall be disable CONFIG_OPTIONS_DISABLE := -- cgit v0.10.2 From 0010245e2c6e431f24c1d80521866f963e148c03 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 13 Oct 2015 11:27:58 +0200 Subject: greybus: gpio: handle set_irq_flags api change The ARM-specific set_irq_flags helper has been removed in 4.3. Instead of doing conditional compilation on the kernel version to avoid build breakages, simply use the genirq interface directly. Suggested-by: Rob Herring Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 6c653ad..5ac859e 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -506,11 +506,7 @@ static int gb_gpio_irq_map(struct irq_domain *domain, unsigned int irq, irq_set_chip_data(irq, ggc); irq_set_chip_and_handler(irq, ggc->irqchip, ggc->irq_handler); -#ifdef CONFIG_ARM - set_irq_flags(irq, IRQF_VALID); -#else irq_set_noprobe(irq); -#endif /* * No set-up of the hardware will happen if IRQ_TYPE_NONE * is passed as default type. @@ -523,9 +519,6 @@ static int gb_gpio_irq_map(struct irq_domain *domain, unsigned int irq, static void gb_gpio_irq_unmap(struct irq_domain *d, unsigned int irq) { -#ifdef CONFIG_ARM - set_irq_flags(irq, 0); -#endif irq_set_chip_and_handler(irq, NULL, NULL); irq_set_chip_data(irq, NULL); } -- cgit v0.10.2 From 04db334667b167b6f7c64e791defcb1bc61cfd3a Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 12 Oct 2015 15:45:05 +0100 Subject: greybus: loopback: add reserved fields to track firmware latencies The greybus specification has been extended to include two new reserved fields, which the implementation is using to track internal firmware latencies. This change adds the appropriate fields to the corresponding kernel header. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 44a2133..fedb1b1 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -958,6 +958,8 @@ struct gb_loopback_transfer_request { struct gb_loopback_transfer_response { __le32 len; + __le32 reserved0; + __le32 reserved1; __u8 data[0]; } __packed; -- cgit v0.10.2 From 5ae2f55b3571408caa6ee0dc908dc60131da7cf6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 14 Oct 2015 11:12:06 -0700 Subject: greybus: vibrator: use the bundle struct device instead of the connector We are removing struct device from the gb_connection structure in the near future. The gb_bundle structure's struct device should be used as a replacement. This patch moves the vibrator driver to use the bundle pointer instead of the connection pointer. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/vibrator.c b/drivers/staging/greybus/vibrator.c index 2b80326..04737c8 100644 --- a/drivers/staging/greybus/vibrator.c +++ b/drivers/staging/greybus/vibrator.c @@ -111,8 +111,8 @@ static int gb_vibrator_connection_init(struct gb_connection *connection) retval = vib->minor; goto error; } - dev = device_create(&vibrator_class, &connection->dev, MKDEV(0, 0), vib, - "vibrator%d", vib->minor); + dev = device_create(&vibrator_class, &connection->bundle->dev, + MKDEV(0, 0), vib, "vibrator%d", vib->minor); if (IS_ERR(dev)) { retval = -EINVAL; goto err_ida_remove; -- cgit v0.10.2 From 4f30bf3aef416ce6870a6da68e42957aeb4edb76 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 14 Oct 2015 11:15:12 -0700 Subject: greybus: uart: use the bundle struct device instead of the connector We are removing struct device from the gb_connection structure in the near future. The gb_bundle structure's struct device should be used as a replacement. This patch moves the uart driver to use the bundle pointer instead of the connection pointer. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 9e8bf6f..ec978a4 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -94,7 +94,7 @@ static int gb_uart_receive_data(struct gb_tty *gb_tty, count = tty_insert_flip_string_fixed_flag(port, receive_data->data, tty_flags, recv_data_size); if (count != recv_data_size) { - dev_err(&connection->dev, + dev_err(&connection->bundle->dev, "UART: RX 0x%08x bytes only wrote 0x%08x\n", recv_data_size, count); } @@ -121,7 +121,7 @@ static int gb_uart_request_recv(u8 type, struct gb_operation *op) gb_tty->ctrlin = serial_state->control; break; default: - dev_err(&connection->dev, + dev_err(&connection->bundle->dev, "unsupported unsolicited request: %02x\n", type); ret = -EINVAL; } @@ -175,7 +175,7 @@ static int send_break(struct gb_tty *gb_tty, u8 state) struct gb_uart_set_break_request request; if ((state != 0) && (state != 1)) { - dev_err(&gb_tty->connection->dev, + dev_err(&gb_tty->connection->bundle->dev, "invalid break state of %d\n", state); return -EINVAL; } @@ -626,7 +626,7 @@ static int gb_uart_connection_init(struct gb_connection *connection) minor = alloc_minor(gb_tty); if (minor < 0) { if (minor == -ENOSPC) { - dev_err(&connection->dev, + dev_err(&connection->bundle->dev, "no more free minor numbers\n"); retval = -ENODEV; goto error_minor; @@ -654,7 +654,7 @@ static int gb_uart_connection_init(struct gb_connection *connection) send_line_coding(gb_tty); tty_dev = tty_port_register_device(&gb_tty->port, gb_tty_driver, minor, - &connection->dev); + &connection->bundle->dev); if (IS_ERR(tty_dev)) { retval = PTR_ERR(tty_dev); goto error; -- cgit v0.10.2 From 1cb9e38c8c17b16b2712aaf2ca4d3509f0fe9366 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 14 Oct 2015 11:15:38 -0700 Subject: greybus: spi: use the bundle struct device instead of the connector We are removing struct device from the gb_connection structure in the near future. The gb_bundle structure's struct device should be used as a replacement. This patch moves the spi driver to use the bundle pointer instead of the connection pointer. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index 393f28a..33e86f9 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -57,7 +57,7 @@ gb_spi_operation_create(struct gb_connection *connection, /* Find number of transfers queued and tx/rx length in the message */ list_for_each_entry(xfer, &msg->transfers, transfer_list) { if (!xfer->tx_buf && !xfer->rx_buf) { - dev_err(&connection->dev, + dev_err(&connection->bundle->dev, "bufferless transfer, length %u\n", xfer->len); return NULL; } @@ -73,8 +73,8 @@ gb_spi_operation_create(struct gb_connection *connection, /* Too many transfers ? */ if (count > (u32)U16_MAX) { - dev_err(&connection->dev, "transfer count (%u) too big\n", - count); + dev_err(&connection->bundle->dev, + "transfer count (%u) too big\n", count); return NULL; } @@ -286,9 +286,9 @@ static int gb_spi_connection_init(struct gb_connection *connection) int ret; /* Allocate master with space for data */ - master = spi_alloc_master(&connection->dev, sizeof(*spi)); + master = spi_alloc_master(&connection->bundle->dev, sizeof(*spi)); if (!master) { - dev_err(&connection->dev, "cannot alloc SPI master\n"); + dev_err(&connection->bundle->dev, "cannot alloc SPI master\n"); return -ENOMEM; } -- cgit v0.10.2 From b2a637d72df790dbb8550627903c93ec8df4e9f7 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 14 Oct 2015 11:16:24 -0700 Subject: greybus: hid: use the bundle struct device instead of the connector We are removing struct device from the gb_connection structure in the near future. The gb_bundle structure's struct device should be used as a replacement. This patch moves the hid driver to use the bundle pointer instead of the connection pointer. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index a2f0612..3ac9c10 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -86,7 +86,7 @@ static int gb_hid_set_report(struct gb_hid *ghid, u8 report_type, u8 report_id, ret = gb_operation_request_send_sync(operation); if (ret) { - dev_err(&operation->connection->dev, + dev_err(&operation->connection->bundle->dev, "failed to set report: %d\n", ret); } else { ret = len; @@ -104,7 +104,7 @@ static int gb_hid_irq_handler(u8 type, struct gb_operation *op) struct gb_hid_input_report_request *request = op->request->payload; if (type != GB_HID_TYPE_IRQ_EVENT) { - dev_err(&connection->dev, + dev_err(&connection->bundle->dev, "unsupported unsolicited request\n"); return -EINVAL; } @@ -403,7 +403,7 @@ static int gb_hid_init(struct gb_hid *ghid) hid->driver_data = ghid; hid->ll_driver = &gb_hid_ll_driver; - hid->dev.parent = &ghid->connection->dev; + hid->dev.parent = &ghid->connection->bundle->dev; #if LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0) hid->hid_get_raw_report = gb_hid_get_raw_report; hid->hid_output_raw_report = gb_hid_output_raw_report; @@ -412,7 +412,8 @@ static int gb_hid_init(struct gb_hid *ghid) /* Set HID device's name */ snprintf(hid->name, sizeof(hid->name), "%s %04hX:%04hX", - dev_name(&ghid->connection->dev), hid->vendor, hid->product); + dev_name(&ghid->connection->bundle->dev), + hid->vendor, hid->product); return 0; } -- cgit v0.10.2 From 283dc01fb0ca32254bd5111c22cd9d9d4c4a0216 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 14 Oct 2015 11:16:49 -0700 Subject: greybus: audio: use the bundle struct device instead of the connector We are removing struct device from the gb_connection structure in the near future. The gb_bundle structure's struct device should be used as a replacement. This patch moves the audio driver to use the bundle pointer instead of the connection pointer. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/audio.c b/drivers/staging/greybus/audio.c index 6754c90..684229c 100644 --- a/drivers/staging/greybus/audio.c +++ b/drivers/staging/greybus/audio.c @@ -341,13 +341,14 @@ static int gb_i2s_mgmt_report_event_recv(u8 type, struct gb_operation *op) char *event_name; if (type != GB_I2S_MGMT_TYPE_REPORT_EVENT) { - dev_err(&connection->dev, "Invalid request type: %d\n", + dev_err(&connection->bundle->dev, "Invalid request type: %d\n", type); return -EINVAL; } if (op->request->payload_size < sizeof(*req)) { - dev_err(&connection->dev, "Short request received (%zu < %zu)\n", + dev_err(&connection->bundle->dev, + "Short request received (%zu < %zu)\n", op->request->payload_size, sizeof(*req)); return -EINVAL; } @@ -385,12 +386,12 @@ static int gb_i2s_mgmt_report_event_recv(u8 type, struct gb_operation *op) event_name = "DATA_LEN"; break; default: - dev_warn(&connection->dev, "Unknown I2S Event received: %d\n", - req->event); + dev_warn(&connection->bundle->dev, + "Unknown I2S Event received: %d\n", req->event); return -EINVAL; } - dev_warn(&connection->dev, "I2S Event received: %d - '%s'\n", + dev_warn(&connection->bundle->dev, "I2S Event received: %d - '%s'\n", req->event, event_name); return 0; -- cgit v0.10.2 From 0a72bd36df947855d7e546ac2e91972860f6894b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 14 Oct 2015 11:17:29 -0700 Subject: greybus: firmware: use the bundle struct device instead of the connector We are removing struct device from the gb_connection structure in the near future. The gb_bundle structure's struct device should be used as a replacement. This patch moves the firmware driver to use the bundle pointer instead of the connection pointer. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/firmware.c b/drivers/staging/greybus/firmware.c index e04ed6b..b16f133 100644 --- a/drivers/staging/greybus/firmware.c +++ b/drivers/staging/greybus/firmware.c @@ -43,7 +43,8 @@ static int download_firmware(struct gb_firmware *firmware, u8 stage) intf->unipro_mfg_id, intf->unipro_prod_id, intf->ara_vend_id, intf->ara_prod_id, stage); - return request_firmware(&firmware->fw, firmware_name, &connection->dev); + return request_firmware(&firmware->fw, firmware_name, + &connection->bundle->dev); } static int gb_firmware_size_request(struct gb_operation *op) @@ -52,7 +53,7 @@ static int gb_firmware_size_request(struct gb_operation *op) struct gb_firmware *firmware = connection->private; struct gb_firmware_size_request *size_request = op->request->payload; struct gb_firmware_size_response *size_response; - struct device *dev = &connection->dev; + struct device *dev = &connection->bundle->dev; int ret; if (op->request->payload_size != sizeof(*size_request)) { @@ -88,7 +89,7 @@ static int gb_firmware_get_firmware(struct gb_operation *op) struct gb_firmware *firmware = connection->private; struct gb_firmware_get_firmware_request *firmware_request = op->request->payload; struct gb_firmware_get_firmware_response *firmware_response; - struct device *dev = &connection->dev; + struct device *dev = &connection->bundle->dev; unsigned int offset, size; if (op->request->payload_size != sizeof(*firmware_request)) { @@ -122,7 +123,7 @@ static int gb_firmware_ready_to_boot(struct gb_operation *op) { struct gb_connection *connection = op->connection; struct gb_firmware_ready_to_boot_request *rtb_request = op->request->payload; - struct device *dev = &connection->dev; + struct device *dev = &connection->bundle->dev; u8 status; if (op->request->payload_size != sizeof(*rtb_request)) { @@ -155,7 +156,7 @@ static int gb_firmware_request_recv(u8 type, struct gb_operation *op) case GB_FIRMWARE_TYPE_READY_TO_BOOT: return gb_firmware_ready_to_boot(op); default: - dev_err(&op->connection->dev, + dev_err(&op->connection->bundle->dev, "unsupported request: %hhu\n", type); return -EINVAL; } @@ -185,7 +186,7 @@ static int gb_firmware_connection_init(struct gb_connection *connection) ret = gb_operation_sync(connection, GB_FIRMWARE_TYPE_AP_READY, NULL, 0, NULL, 0); if (ret) - dev_err(&connection->dev, "Failed to send AP READY (%d)\n", ret); + dev_err(&connection->bundle->dev, "Failed to send AP READY (%d)\n", ret); return 0; } -- cgit v0.10.2 From c7eb46e459f2a05fa52656ae9d767aa498482ecf Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 14 Oct 2015 11:17:55 -0700 Subject: greybus: gpio: use the bundle struct device instead of the connector We are removing struct device from the gb_connection structure in the near future. The gb_bundle structure's struct device should be used as a replacement. This patch moves the gpio driver to use the bundle pointer instead of the connection pointer. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 5ac859e..5830dc9 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -353,7 +353,7 @@ static int gb_gpio_request_recv(u8 type, struct gb_operation *op) struct irq_desc *desc; if (type != GB_GPIO_TYPE_IRQ_EVENT) { - dev_err(&connection->dev, + dev_err(&connection->bundle->dev, "unsupported unsolicited request: %u\n", type); return -EINVAL; } @@ -648,7 +648,7 @@ static int gb_gpio_connection_init(struct gb_connection *connection) gpio = &ggc->chip; gpio->label = "greybus_gpio"; - gpio->dev = &connection->dev; + gpio->dev = &connection->bundle->dev; gpio->owner = THIS_MODULE; gpio->request = gb_gpio_request; @@ -666,15 +666,16 @@ static int gb_gpio_connection_init(struct gb_connection *connection) ret = gpiochip_add(gpio); if (ret) { - dev_err(&connection->dev, "failed to add gpio chip: %d\n", - ret); + dev_err(&connection->bundle->dev, + "failed to add gpio chip: %d\n", ret); goto err_free_lines; } ret = gb_gpio_irqchip_add(gpio, irqc, 0, handle_level_irq, IRQ_TYPE_NONE); if (ret) { - dev_err(&connection->dev, "failed to add irq chip: %d\n", ret); + dev_err(&connection->bundle->dev, + "failed to add irq chip: %d\n", ret); goto irqchip_err; } -- cgit v0.10.2 From c01e16e3cb120938db87af91248e91f3552a1b73 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 14 Oct 2015 11:18:32 -0700 Subject: greybus: i2c: use the bundle struct device instead of the connector We are removing struct device from the gb_connection structure in the near future. The gb_bundle structure's struct device should be used as a replacement. This patch moves the i2c driver to use the bundle pointer instead of the connection pointer. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c index bf6d11b..5a5af36 100644 --- a/drivers/staging/greybus/i2c.c +++ b/drivers/staging/greybus/i2c.c @@ -118,7 +118,7 @@ gb_i2c_operation_create(struct gb_connection *connection, u32 i; if (msg_count > (u32)U16_MAX) { - dev_err(&connection->dev, "msg_count (%u) too big\n", + dev_err(&connection->bundle->dev, "msg_count (%u) too big\n", msg_count); return NULL; } @@ -312,7 +312,7 @@ static int gb_i2c_connection_init(struct gb_connection *connection) adapter->timeout = gb_i2c_dev->timeout_msec * HZ / 1000; adapter->retries = gb_i2c_dev->retries; - adapter->dev.parent = &connection->dev; + adapter->dev.parent = &connection->bundle->dev; snprintf(adapter->name, sizeof(adapter->name), "Greybus i2c adapter"); i2c_set_adapdata(adapter, gb_i2c_dev); -- cgit v0.10.2 From 8d5732f4be9411ddf9e6dc6b4d761f3b06999d94 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 14 Oct 2015 11:18:50 -0700 Subject: greybus: pwm: use the bundle struct device instead of the connector We are removing struct device from the gb_connection structure in the near future. The gb_bundle structure's struct device should be used as a replacement. This patch moves the pwm driver to use the bundle pointer instead of the connection pointer. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/pwm.c b/drivers/staging/greybus/pwm.c index d91905f..c3a3a9d 100644 --- a/drivers/staging/greybus/pwm.c +++ b/drivers/staging/greybus/pwm.c @@ -196,7 +196,7 @@ static int gb_pwm_connection_init(struct gb_connection *connection) pwm = &pwmc->chip; - pwm->dev = &connection->dev; + pwm->dev = &connection->bundle->dev; pwm->ops = &gb_pwm_ops; pwm->base = -1; /* Allocate base dynamically */ pwm->npwm = pwmc->pwm_max + 1; @@ -204,7 +204,8 @@ static int gb_pwm_connection_init(struct gb_connection *connection) ret = pwmchip_add(pwm); if (ret) { - dev_err(&connection->dev, "failed to register PWM: %d\n", ret); + dev_err(&connection->bundle->dev, + "failed to register PWM: %d\n", ret); goto out_err; } -- cgit v0.10.2 From 5fd18b37c6a718d9daf8719ac81e4aa67ded4106 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 14 Oct 2015 11:19:09 -0700 Subject: greybus: light : use the bundle struct device instead of the connector We are removing struct device from the gb_connection structure in the near future. The gb_bundle structure's struct device should be used as a replacement. This patch moves the light driver to use the bundle pointer instead of the connection pointer. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index e8ef7f5..664be97 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -469,7 +469,7 @@ static void __gb_lights_channel_v4l2_config(struct led_flash_setting *channel_s, static int gb_lights_light_v4l2_register(struct gb_light *light) { struct gb_connection *connection = get_conn_from_light(light); - struct device *dev = &connection->dev; + struct device *dev = &connection->bundle->dev; struct v4l2_flash_config *sd_cfg; struct led_classdev_flash *fled; struct led_classdev_flash *iled = NULL; @@ -529,7 +529,7 @@ static int gb_lights_light_v4l2_register(struct gb_light *light) { struct gb_connection *connection = get_conn_from_light(light); - dev_err(&connection->dev, "no support for v4l2 subdevices\n"); + dev_err(&connection->bundle->dev, "no support for v4l2 subdevices\n"); return 0; } @@ -791,7 +791,7 @@ static int gb_lights_channel_flash_config(struct gb_channel *channel) { struct gb_connection *connection = get_conn_from_channel(channel); - dev_err(&connection->dev, "no support for flash devices\n"); + dev_err(&connection->bundle->dev, "no support for flash devices\n"); return 0; } @@ -1090,7 +1090,7 @@ static int gb_lights_setup(struct gb_lights *glights) for (i = 0; i < glights->lights_count; i++) { ret = gb_lights_light_config(glights, i); if (ret < 0) { - dev_err(&connection->dev, + dev_err(&connection->bundle->dev, "Fail to configure lights device\n"); goto out; } @@ -1104,6 +1104,7 @@ out: static int gb_lights_event_recv(u8 type, struct gb_operation *op) { struct gb_connection *connection = op->connection; + struct device *dev = &connection->bundle->dev; struct gb_lights *glights = connection->private; struct gb_message *request; struct gb_lights_event_request *payload; @@ -1112,16 +1113,14 @@ static int gb_lights_event_recv(u8 type, struct gb_operation *op) u8 event; if (type != GB_LIGHTS_TYPE_EVENT) { - dev_err(&connection->dev, - "Unsupported unsolicited event: %u\n", type); + dev_err(dev, "Unsupported unsolicited event: %u\n", type); return -EINVAL; } request = op->request; if (request->payload_size < sizeof(*payload)) { - dev_err(&connection->dev, - "Wrong event size received (%zu < %zu)\n", + dev_err(dev, "Wrong event size received (%zu < %zu)\n", request->payload_size, sizeof(*payload)); return -EINVAL; } @@ -1130,8 +1129,7 @@ static int gb_lights_event_recv(u8 type, struct gb_operation *op) light_id = payload->light_id; if (light_id >= glights->lights_count || !&glights->lights[light_id]) { - dev_err(&connection->dev, - "Event received for unconfigured light id: %d\n", + dev_err(dev, "Event received for unconfigured light id: %d\n", light_id); return -EINVAL; } -- cgit v0.10.2 From 61c80575b90797bb3e74e2e2510eaa376bc8e4cb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 14 Oct 2015 11:19:42 -0700 Subject: greybus: sdio: use the bundle struct device instead of the connector We are removing struct device from the gb_connection structure in the near future. The gb_bundle structure's struct device should be used as a replacement. This patch moves the sdio driver to use the bundle pointer instead of the connection pointer. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index aaca70e..b5e4af3 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -208,7 +208,7 @@ static int gb_sdio_event_recv(u8 type, struct gb_operation *op) u8 event; if (type != GB_SDIO_TYPE_EVENT) { - dev_err(&connection->dev, + dev_err(&connection->bundle->dev, "unsupported unsolicited event: %u\n", type); return -EINVAL; } @@ -707,7 +707,7 @@ static int gb_sdio_connection_init(struct gb_connection *connection) size_t max_buffer; int ret = 0; - mmc = mmc_alloc_host(sizeof(*host), &connection->dev); + mmc = mmc_alloc_host(sizeof(*host), &connection->bundle->dev); if (!mmc) return -ENOMEM; @@ -739,7 +739,7 @@ static int gb_sdio_connection_init(struct gb_connection *connection) mutex_init(&host->lock); spin_lock_init(&host->xfer); host->mrq_workqueue = alloc_workqueue("mmc-%s", 0, 1, - dev_name(&connection->dev)); + dev_name(&connection->bundle->dev)); if (!host->mrq_workqueue) { ret = -ENOMEM; goto free_buffer; -- cgit v0.10.2 From dfdc6e12c8a3b1bc0c123abeb3679208b31a19f6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 14 Oct 2015 11:20:00 -0700 Subject: greybus: usb: use the bundle struct device instead of the connector We are removing struct device from the gb_connection structure in the near future. The gb_bundle structure's struct device should be used as a replacement. This patch moves the usb driver to use the bundle pointer instead of the connection pointer. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/usb.c b/drivers/staging/greybus/usb.c index 2133d0d..6647868 100644 --- a/drivers/staging/greybus/usb.c +++ b/drivers/staging/greybus/usb.c @@ -57,7 +57,8 @@ static void hcd_stop(struct usb_hcd *hcd) ret = gb_operation_sync(dev->connection, GB_USB_TYPE_HCD_STOP, NULL, 0, NULL, 0); if (ret) - dev_err(&dev->connection->dev, "HCD stop failed '%d'\n", ret); + dev_err(&dev->connection->bundle->dev, + "HCD stop failed '%d'\n", ret); } static int hcd_start(struct usb_hcd *hcd) @@ -69,7 +70,8 @@ static int hcd_start(struct usb_hcd *hcd) ret = gb_operation_sync(dev->connection, GB_USB_TYPE_HCD_START, NULL, 0, NULL, 0); if (ret) { - dev_err(&dev->connection->dev, "HCD start failed '%d'\n", ret); + dev_err(&dev->connection->bundle->dev, + "HCD start failed '%d'\n", ret); return ret; } @@ -161,7 +163,7 @@ static struct hc_driver usb_gb_hc_driver = { static int gb_usb_connection_init(struct gb_connection *connection) { - struct device *dev = &connection->dev; + struct device *dev = &connection->bundle->dev; struct gb_usb_device *gb_usb_dev; struct usb_hcd *hcd; @@ -184,7 +186,7 @@ static int gb_usb_connection_init(struct gb_connection *connection) * Disable for now. */ if (1) { - dev_warn(&connection->dev, "USB protocol disabled\n"); + dev_warn(dev, "USB protocol disabled\n"); retval = -EPROTONOSUPPORT; goto err_put_hcd; } -- cgit v0.10.2 From c3aa6556659fe25b2fb27b86e65c6610b4066950 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 14 Oct 2015 11:21:06 -0700 Subject: greybus: operation: use the bundle struct device instead of the connector We are removing struct device from the gb_connection structure in the near future. The gb_bundle structure's struct device should be used as a replacement. This patch moves the operation code to use to use the bundle pointer instead of the connection pointer when printing out error messages. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 56375c9..3e29d21 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -227,7 +227,7 @@ static void gb_operation_request_handle(struct gb_operation *operation) if (protocol->request_recv) { status = protocol->request_recv(operation->type, operation); } else { - dev_err(&operation->connection->dev, + dev_err(&operation->connection->bundle->dev, "unexpected incoming request type 0x%02hhx\n", operation->type); @@ -236,7 +236,7 @@ static void gb_operation_request_handle(struct gb_operation *operation) ret = gb_operation_response_send(operation, status); if (ret) { - dev_err(&operation->connection->dev, + dev_err(&operation->connection->bundle->dev, "failed to send response %d for type 0x%02hhx: %d\n", status, operation->type, ret); return; @@ -743,7 +743,7 @@ static int gb_operation_response_send(struct gb_operation *operation, /* Record the result */ if (!gb_operation_result_set(operation, errno)) { - dev_err(&connection->dev, "request result already set\n"); + dev_err(&connection->bundle->dev, "request result already set\n"); return -EIO; /* Shouldn't happen */ } @@ -795,7 +795,7 @@ void greybus_message_sent(struct greybus_host_device *hd, */ if (message == operation->response) { if (status) { - dev_err(&connection->dev, + dev_err(&connection->bundle->dev, "error sending response type 0x%02hhx: %d\n", operation->type, status); } @@ -827,7 +827,8 @@ static void gb_connection_recv_request(struct gb_connection *connection, operation = gb_operation_create_incoming(connection, operation_id, type, data, size); if (!operation) { - dev_err(&connection->dev, "can't create incoming operation\n"); + dev_err(&connection->bundle->dev, + "can't create incoming operation\n"); return; } @@ -864,15 +865,15 @@ static void gb_connection_recv_response(struct gb_connection *connection, operation = gb_operation_find_outgoing(connection, operation_id); if (!operation) { - dev_err(&connection->dev, "unexpected response 0x%04hx received\n", - operation_id); + dev_err(&connection->bundle->dev, + "unexpected response 0x%04hx received\n", operation_id); return; } message = operation->response; message_size = sizeof(*message->header) + message->payload_size; if (!errno && size != message_size) { - dev_err(&connection->dev, + dev_err(&connection->bundle->dev, "malformed response of type 0x%02hhx received (%zu != %zu)\n", message->header->type, size, message_size); errno = -EMSGSIZE; @@ -901,17 +902,17 @@ void gb_connection_recv(struct gb_connection *connection, void *data, size_t size) { struct gb_operation_msg_hdr header; + struct device *dev = &connection->bundle->dev; size_t msg_size; u16 operation_id; if (connection->state != GB_CONNECTION_STATE_ENABLED) { - dev_warn(&connection->dev, "dropping %zu received bytes\n", - size); + dev_warn(dev, "dropping %zu received bytes\n", size); return; } if (size < sizeof(header)) { - dev_err(&connection->dev, "short message received\n"); + dev_err(dev, "short message received\n"); return; } @@ -919,7 +920,7 @@ void gb_connection_recv(struct gb_connection *connection, memcpy(&header, data, sizeof(header)); msg_size = le16_to_cpu(header.size); if (size < msg_size) { - dev_err(&connection->dev, + dev_err(dev, "incomplete message 0x%04hx of type 0x%02hhx received (%zu < %zu)\n", le16_to_cpu(header.operation_id), header.type, size, msg_size); @@ -1029,7 +1030,7 @@ int gb_operation_sync_timeout(struct gb_connection *connection, int type, ret = gb_operation_request_send_sync_timeout(operation, timeout); if (ret) { - dev_err(&connection->dev, + dev_err(&connection->bundle->dev, "synchronous operation of type 0x%02hhx failed: %d\n", type, ret); } else { -- cgit v0.10.2 From defa37ea9b9396ddc3ba9f556c1f89fec15c260b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 14 Oct 2015 11:22:39 -0700 Subject: greybus: control: use the bundle struct device instead of the connector We are removing struct device from the gb_connection structure in the near future. The gb_bundle structure's struct device should be used as a replacement. This patch moves the control code to use the bundle pointer instead of the connection pointer for printing out error messages. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index c092beb..630b5b6 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -22,7 +22,7 @@ int gb_control_get_manifest_size_operation(struct gb_interface *intf) ret = gb_operation_sync(connection, GB_CONTROL_TYPE_GET_MANIFEST_SIZE, NULL, 0, &response, sizeof(response)); if (ret) { - dev_err(&connection->dev, + dev_err(&connection->bundle->dev, "%s: Manifest size get operation failed (%d)\n", __func__, ret); return ret; @@ -74,7 +74,7 @@ static int gb_control_request_recv(u8 type, struct gb_operation *op) case GB_REQUEST_TYPE_PROTOCOL_VERSION: if (!gb_operation_response_alloc(op, sizeof(*version), GFP_KERNEL)) { - dev_err(&connection->dev, + dev_err(&connection->bundle->dev, "%s: error allocating response\n", __func__); return -ENOMEM; } -- cgit v0.10.2 From 29a167ec87fb971931a033766e9e387d0fcabe7d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 14 Oct 2015 11:31:00 -0700 Subject: greybus: raw: use the bundle struct device instead of the connector We are removing struct device from the gb_connection structure in the near future. The gb_bundle structure's struct device should be used as a replacement. This patch moves the raw driver to use the bundle pointer instead of the connection pointer. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder diff --git a/drivers/staging/greybus/raw.c b/drivers/staging/greybus/raw.c index ce0f59d..fa5025d 100644 --- a/drivers/staging/greybus/raw.c +++ b/drivers/staging/greybus/raw.c @@ -176,8 +176,8 @@ static int gb_raw_connection_init(struct gb_connection *connection) if (retval) goto error_cdev; - raw->device = device_create(raw_class, &connection->dev, raw->dev, raw, - "gb!raw%d", minor); + raw->device = device_create(raw_class, &connection->bundle->dev, + raw->dev, raw, "gb!raw%d", minor); if (IS_ERR(raw->device)) { retval = PTR_ERR(raw->device); goto error_device; -- cgit v0.10.2 From 608ab2fe99396eff941256d7f0ae7b91438e6cc1 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 15 Oct 2015 16:10:41 +0100 Subject: greybus: es1,es2: add USB vendor command to timestamp As part of an effort to get deep inspection of latencies throughout the greybus network including HSIC, UniPro and firmware incurred latencies a new command to the APBridge to tag a known offset with timestamping data has been introduced. This patch adds that code to the es1 and es2 drivers. - latency_tag_enable - latency_tag_disable Respectively send the enable/disable command to APBridge on a per-CPort basis. This allows only specified cports to have timestamping data added by APBridge, leaving any CPort not specifically enabled untouched. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 4d70e89..ba025e7 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -52,6 +52,10 @@ static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); /* vendor request APB1 log */ #define REQUEST_LOG 0x02 +/* vendor request to time the latency of messages on a given cport */ +#define REQUEST_LATENCY_TAG_EN 0x06 +#define REQUEST_LATENCY_TAG_DIS 0x07 + /** * es1_ap_dev - ES1 USB Bridge to AP structure * @usb_dev: pointer to the USB device we are. @@ -273,10 +277,60 @@ static void message_cancel(struct gb_message *message) usb_free_urb(urb); } +static int latency_tag_enable(struct greybus_host_device *hd, u16 cport_id) +{ + int retval; + struct es1_ap_dev *es1 = hd_to_es1(hd); + struct usb_device *udev = es1->usb_dev; + + if (!cport_id_valid(hd, cport_id)) { + dev_err(&udev->dev, "invalid destination cport 0x%02x\n", + cport_id); + return -EINVAL; + } + + retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + REQUEST_LATENCY_TAG_EN, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, cport_id, 0, NULL, + 0, ES1_TIMEOUT); + + if (retval < 0) + dev_err(&udev->dev, "Cannot enable latency tag for cport %d\n", + cport_id); + return retval; +} + +static int latency_tag_disable(struct greybus_host_device *hd, u16 cport_id) +{ + int retval; + struct es1_ap_dev *es1 = hd_to_es1(hd); + struct usb_device *udev = es1->usb_dev; + + if (!cport_id_valid(hd, cport_id)) { + dev_err(&udev->dev, "invalid destination cport 0x%02x\n", + cport_id); + return -EINVAL; + } + + retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + REQUEST_LATENCY_TAG_DIS, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, cport_id, 0, NULL, + 0, ES1_TIMEOUT); + + if (retval < 0) + dev_err(&udev->dev, "Cannot disable latency tag for cport %d\n", + cport_id); + return retval; +} + static struct greybus_host_driver es1_driver = { .hd_priv_size = sizeof(struct es1_ap_dev), .message_send = message_send, .message_cancel = message_cancel, + .latency_tag_enable = latency_tag_enable, + .latency_tag_disable = latency_tag_disable, }; /* Common function to report consistent warnings based on URB status */ diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 5faf80a..f947983 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -61,6 +61,10 @@ static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); /* vendor request to reset a cport state */ #define REQUEST_RESET_CPORT 0x05 +/* vendor request to time the latency of messages on a given cport */ +#define REQUEST_LATENCY_TAG_EN 0x06 +#define REQUEST_LATENCY_TAG_DIS 0x07 + /* * @endpoint: bulk in endpoint for CPort data * @urb: array of urbs for the CPort in messages @@ -413,11 +417,61 @@ static int cport_enable(struct greybus_host_device *hd, u16 cport_id) return 0; } +static int latency_tag_enable(struct greybus_host_device *hd, u16 cport_id) +{ + int retval; + struct es1_ap_dev *es1 = hd_to_es1(hd); + struct usb_device *udev = es1->usb_dev; + + if (!cport_id_valid(hd, cport_id)) { + dev_err(&udev->dev, "invalid destination cport 0x%02x\n", + cport_id); + return -EINVAL; + } + + retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + REQUEST_LATENCY_TAG_EN, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, cport_id, 0, NULL, + 0, ES1_TIMEOUT); + + if (retval < 0) + dev_err(&udev->dev, "Cannot enable latency tag for cport %d\n", + cport_id); + return retval; +} + +static int latency_tag_disable(struct greybus_host_device *hd, u16 cport_id) +{ + int retval; + struct es1_ap_dev *es1 = hd_to_es1(hd); + struct usb_device *udev = es1->usb_dev; + + if (!cport_id_valid(hd, cport_id)) { + dev_err(&udev->dev, "invalid destination cport 0x%02x\n", + cport_id); + return -EINVAL; + } + + retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + REQUEST_LATENCY_TAG_DIS, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, cport_id, 0, NULL, + 0, ES1_TIMEOUT); + + if (retval < 0) + dev_err(&udev->dev, "Cannot disable latency tag for cport %d\n", + cport_id); + return retval; +} + static struct greybus_host_driver es1_driver = { .hd_priv_size = sizeof(struct es1_ap_dev), .message_send = message_send, .message_cancel = message_cancel, .cport_enable = cport_enable, + .latency_tag_enable = latency_tag_enable, + .latency_tag_disable = latency_tag_disable, }; /* Common function to report consistent warnings based on URB status */ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index e4e53c1..ec4a738 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -80,6 +80,9 @@ struct greybus_host_driver { int (*message_send)(struct greybus_host_device *hd, u16 dest_cport_id, struct gb_message *message, gfp_t gfp_mask); void (*message_cancel)(struct gb_message *message); + int (*latency_tag_enable)(struct greybus_host_device *hd, u16 cport_id); + int (*latency_tag_disable)(struct greybus_host_device *hd, + u16 cport_id); }; struct greybus_host_device { -- cgit v0.10.2 From e7e2efc438ba721000ed4b747f159e41571570a7 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 15 Oct 2015 16:10:42 +0100 Subject: greybus: connection: add latency tag enable/disable callbacks This patch adds a layered wrapper around optional latency tag enable/disable commands to APBridge. When set APBridge and GPBridge will insert timing information into reserved fields in the loopback response header. Correspondingly when unset no timing information will be included in the response payload. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 743ea67..3b731da 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -527,6 +527,38 @@ void gb_connection_destroy(struct gb_connection *connection) device_unregister(&connection->dev); } +void gb_connection_latency_tag_enable(struct gb_connection *connection) +{ + struct greybus_host_device *hd = connection->hd; + int ret; + + if (!hd->driver->latency_tag_enable) + return; + + ret = hd->driver->latency_tag_enable(hd, connection->hd_cport_id); + if (ret) { + dev_err(&connection->dev, + "failed to enable latency tag: %d\n", ret); + } +} +EXPORT_SYMBOL_GPL(gb_connection_latency_tag_enable); + +void gb_connection_latency_tag_disable(struct gb_connection *connection) +{ + struct greybus_host_device *hd = connection->hd; + int ret; + + if (!hd->driver->latency_tag_disable) + return; + + ret = hd->driver->latency_tag_disable(hd, connection->hd_cport_id); + if (ret) { + dev_err(&connection->dev, + "failed to disable latency tag: %d\n", ret); + } +} +EXPORT_SYMBOL_GPL(gb_connection_latency_tag_disable); + void gb_hd_connections_exit(struct greybus_host_device *hd) { struct gb_connection *connection; diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 27ec597..2eaf186 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -66,4 +66,7 @@ void greybus_data_rcvd(struct greybus_host_device *hd, u16 cport_id, int gb_connection_bind_protocol(struct gb_connection *connection); +void gb_connection_latency_tag_enable(struct gb_connection *connection); +void gb_connection_latency_tag_disable(struct gb_connection *connection); + #endif /* __CONNECTION_H */ -- cgit v0.10.2 From fd58926ebef4a5afa238f35cc99c1f99653c40a4 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 15 Oct 2015 16:10:43 +0100 Subject: greybus: loopback: send command to APBridge to tag throughput A USB vendor command has been added to APBridge to allow for tagging of specific CPort identifiers with internal timing data, specifically geared towards capturing and understanding latencies in the UniPro fabric. This patch sends a command to APBridge for each known loopback CPort to tag data as appropriate. Subsequent patches will present this data to user-space for ongoing integration analysis. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 5cbb8cb..95cba82 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -23,6 +23,7 @@ #include #include "greybus.h" +#include "connection.h" #define NSEC_PER_DAY 86400000000000ULL @@ -938,6 +939,7 @@ static int gb_loopback_connection_init(struct gb_connection *connection) } gb_loopback_insert_id(gb); + gb_connection_latency_tag_enable(connection); gb_dev.count++; mutex_unlock(&gb_dev.mutex); return 0; @@ -975,6 +977,7 @@ static void gb_loopback_connection_exit(struct gb_connection *connection) connection->private = NULL; kfifo_free(&gb->kfifo_lat); kfifo_free(&gb->kfifo_ts); + gb_connection_latency_tag_disable(connection); gb_dev.count--; if (!gb_dev.count) { sysfs_remove_groups(kobj, loopback_dev_groups); -- cgit v0.10.2 From e6227ee64782e1cda88a70512ac2b0ae8fda2203 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 15 Oct 2015 16:10:44 +0100 Subject: greybus: loopback: add tracker variables to hold firmware timestamps This patch adds tracker variables to hold the incoming firmware derived timestamps where apbridge_latency_ts will contain the APBridge's view of the UniPro turn-around time and gpbridge_latency_ts will contain the GPBridge's view of it's own internal latency. Both values are reported in microseconds. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 95cba82..d2a88af 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -83,6 +83,8 @@ struct gb_loopback { u32 iteration_count; u64 elapsed_nsecs; u32 error; + u32 apbridge_latency_ts; + u32 gpbridge_latency_ts; }; #define GB_LOOPBACK_FIFO_DEFAULT 8192 -- cgit v0.10.2 From 1ec5843ee9889914be80a6763e58a79064716023 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 15 Oct 2015 16:10:45 +0100 Subject: greybus: loopback: capture and present firmware supplied latencies In order to provide deep inspection of the greybus/UniPro system instrumentation of 1. APBridge's view of UniPro latency 2. GPBridge's view of internal firmware-only latency have both been added and reported to the AP in the transfer loopback response header. When this data are present we latch and average it over the number of requested cycles, presenting it to user-space via sysfs. This patch adds the following sysfs entries for each loopback CPort - apbridge_unipro_latency_avg_con - apbridge_unipro_latency_max_con - apbridge_unipro_latency_min_con - gpbridge_firmware_latency_avg_con - gpbridge_firmware_latency_max_con - gpbridge_firmware_latency_min_con and the following sysfs entries representing the average values across all available CPorts - apbridge_unipro_latency_avg_dev - apbridge_unipro_latency_max_dev - apbridge_unipro_latency_min_dev - gpbridge_firmware_latency_avg_dev - gpbridge_firmware_latency_max_dev - gpbridge_firmware_latency_min_dev Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index d2a88af..1ac86c1 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -60,6 +60,8 @@ struct gb_loopback_device { struct gb_loopback_stats latency; struct gb_loopback_stats throughput; struct gb_loopback_stats requests_per_second; + struct gb_loopback_stats apbridge_unipro_latency; + struct gb_loopback_stats gpbridge_firmware_latency; }; static struct gb_loopback_device gb_dev; @@ -78,6 +80,8 @@ struct gb_loopback { struct gb_loopback_stats latency; struct gb_loopback_stats throughput; struct gb_loopback_stats requests_per_second; + struct gb_loopback_stats apbridge_unipro_latency; + struct gb_loopback_stats gpbridge_firmware_latency; u32 lbid; u32 iteration_count; @@ -272,6 +276,12 @@ gb_loopback_stats_attrs(requests_per_second, con, true); /* Quantity of data sent and received on this cport */ gb_loopback_stats_attrs(throughput, dev, false); gb_loopback_stats_attrs(throughput, con, true); +/* Latency across the UniPro link from APBridge's perspective */ +gb_loopback_stats_attrs(apbridge_unipro_latency, dev, false); +gb_loopback_stats_attrs(apbridge_unipro_latency, con, true); +/* Firmware induced overhead in the GPBridge */ +gb_loopback_stats_attrs(gpbridge_firmware_latency, dev, false); +gb_loopback_stats_attrs(gpbridge_firmware_latency, con, true); /* Number of errors encountered during loop */ gb_loopback_ro_attr(error, dev, false); gb_loopback_ro_attr(error, con, true); @@ -306,6 +316,12 @@ static struct attribute *loopback_dev_attrs[] = { &dev_attr_throughput_min_dev.attr, &dev_attr_throughput_max_dev.attr, &dev_attr_throughput_avg_dev.attr, + &dev_attr_apbridge_unipro_latency_min_dev.attr, + &dev_attr_apbridge_unipro_latency_max_dev.attr, + &dev_attr_apbridge_unipro_latency_avg_dev.attr, + &dev_attr_gpbridge_firmware_latency_min_dev.attr, + &dev_attr_gpbridge_firmware_latency_max_dev.attr, + &dev_attr_gpbridge_firmware_latency_avg_dev.attr, &dev_attr_type.attr, &dev_attr_size.attr, &dev_attr_ms_wait.attr, @@ -327,6 +343,12 @@ static struct attribute *loopback_con_attrs[] = { &dev_attr_throughput_min_con.attr, &dev_attr_throughput_max_con.attr, &dev_attr_throughput_avg_con.attr, + &dev_attr_apbridge_unipro_latency_min_con.attr, + &dev_attr_apbridge_unipro_latency_max_con.attr, + &dev_attr_apbridge_unipro_latency_avg_con.attr, + &dev_attr_gpbridge_firmware_latency_min_con.attr, + &dev_attr_gpbridge_firmware_latency_max_con.attr, + &dev_attr_gpbridge_firmware_latency_avg_con.attr, &dev_attr_error_con.attr, NULL, }; @@ -463,6 +485,8 @@ static int gb_loopback_transfer(struct gb_loopback *gb, u32 len) dev_err(&gb->connection->dev, "Loopback Data doesn't match\n"); retval = -EREMOTEIO; } + gb->apbridge_latency_ts = (u32)__le32_to_cpu(response->reserved0); + gb->gpbridge_latency_ts = (u32)__le32_to_cpu(response->reserved1); gb_error: kfree(request); @@ -545,6 +569,10 @@ static void gb_loopback_reset_stats(struct gb_loopback_device *gb_dev) sizeof(struct gb_loopback_stats)); memcpy(&gb->requests_per_second, &reset, sizeof(struct gb_loopback_stats)); + memcpy(&gb->apbridge_unipro_latency, &reset, + sizeof(struct gb_loopback_stats)); + memcpy(&gb->gpbridge_firmware_latency, &reset, + sizeof(struct gb_loopback_stats)); mutex_unlock(&gb->mutex); } @@ -555,6 +583,10 @@ static void gb_loopback_reset_stats(struct gb_loopback_device *gb_dev) memcpy(&gb_dev->throughput, &reset, sizeof(struct gb_loopback_stats)); memcpy(&gb_dev->requests_per_second, &reset, sizeof(struct gb_loopback_stats)); + memcpy(&gb_dev->apbridge_unipro_latency, &reset, + sizeof(struct gb_loopback_stats)); + memcpy(&gb_dev->gpbridge_firmware_latency, &reset, + sizeof(struct gb_loopback_stats)); } static void gb_loopback_update_stats(struct gb_loopback_stats *stats, u32 val) @@ -677,6 +709,16 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb) /* Log throughput and requests using latency as benchmark */ gb_loopback_throughput_update(gb, lat); gb_loopback_requests_update(gb, lat); + + /* Log the firmware supplied latency values */ + gb_loopback_update_stats(&gb_dev.apbridge_unipro_latency, + gb->apbridge_latency_ts); + gb_loopback_update_stats(&gb->apbridge_unipro_latency, + gb->apbridge_latency_ts); + gb_loopback_update_stats(&gb_dev.gpbridge_firmware_latency, + gb->gpbridge_latency_ts); + gb_loopback_update_stats(&gb->gpbridge_firmware_latency, + gb->gpbridge_latency_ts); } static int gb_loopback_fn(void *data) @@ -736,6 +778,8 @@ static int gb_loopback_fn(void *data) goto sleep; } /* Else operations to perform */ + gb->apbridge_latency_ts = 0; + gb->gpbridge_latency_ts = 0; if (type == GB_LOOPBACK_TYPE_PING) error = gb_loopback_ping(gb); else if (type == GB_LOOPBACK_TYPE_TRANSFER) -- cgit v0.10.2 From 10ed1938767ec90a264b73b337ec17a0a674847a Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Thu, 15 Oct 2015 23:56:51 +0100 Subject: greybus: sdio: send data block details at command request If SDIO request include data to be transfer send details (data blocks and block size) in command request, as it seems some controllers need this info prior to set the registers correctly. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index fedb1b1..02ba40f 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -1088,6 +1088,8 @@ struct gb_sdio_command_request { #define GB_SDIO_CMD_BCR 0x03 __le32 cmd_arg; + __le16 data_blocks; + __le16 data_blksz; } __packed; struct gb_sdio_command_response { diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index b5e4af3..201cfe5 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -373,8 +373,9 @@ out: static int gb_sdio_command(struct gb_sdio_host *host, struct mmc_command *cmd) { - struct gb_sdio_command_request request; + struct gb_sdio_command_request request = {0}; struct gb_sdio_command_response response; + struct mmc_data *data = host->mrq->data; u8 cmd_flags; u8 cmd_type; int i; @@ -427,6 +428,11 @@ static int gb_sdio_command(struct gb_sdio_host *host, struct mmc_command *cmd) request.cmd_flags = cmd_flags; request.cmd_type = cmd_type; request.cmd_arg = cpu_to_le32(cmd->arg); + /* some controllers need to know at command time data details */ + if (data) { + request.data_blocks = cpu_to_le16(data->blocks); + request.data_blksz = cpu_to_le16(data->blksz); + } ret = gb_operation_sync(host->connection, GB_SDIO_TYPE_COMMAND, &request, sizeof(request), &response, -- cgit v0.10.2 From b6789ee55b99fbc26aa16e4f485397e86498bf51 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Thu, 15 Oct 2015 23:56:52 +0100 Subject: greybus: sdio: some cleanups in command function Some cleanups in gb_sdio_command function, ret does not need to be initialize and mrq is already pointing to request, no need to get it from host. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index 201cfe5..beb3574 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -379,7 +379,7 @@ static int gb_sdio_command(struct gb_sdio_host *host, struct mmc_command *cmd) u8 cmd_flags; u8 cmd_type; int i; - int ret = 0; + int ret; switch (mmc_resp_type(cmd)) { case MMC_RSP_NONE: @@ -488,7 +488,7 @@ static void gb_sdio_mrq_work(struct work_struct *work) goto done; if (mrq->data) { - ret = gb_sdio_transfer(host, host->mrq->data); + ret = gb_sdio_transfer(host, mrq->data); if (ret < 0) goto done; } -- cgit v0.10.2 From b750fa3370485356b5cddda7c0f7fc9bea056fa8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 16 Oct 2015 16:56:38 -0700 Subject: greybus: connection: remove 'struct device' from 'struct gb_connection' We don't want this in the driver core, as nothing will be binding to it, that's the job of a bundle. So remove the struct device and use a kref to handle reference counting instead. Note, I don't think we really need a kref, but it keeps the lifetime the same as before, and is the simplest change for now. In the future it might be easier to just attach all connections to the bundle and clean them up when the bundle is removed. Also remove the cport sysfs documentation as it's no longer relevant. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Viresh Kumar Reviewed-by: Alex Elder Reviewed-by: Johan Hovold diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index b2e699c..22a0c7f 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -155,40 +155,3 @@ Description: process watching the file will be woken up, and the new value can be read. It's a "poor-man's IPC", yes, but simplifies the Android userspace code immensely. - -What: /sys/bus/greybus/device/endoE:M:I:B:C -Date: October 2015 -KernelVersion: 4.XX -Contact: Greg Kroah-Hartman -Description: - A cport C within bundle B, C is replaced by a 2-byte - number representing the cport. - -What: /sys/bus/greybus/device/endoE:M:I:B:C/ap_cport_id -Date: October 2015 -KernelVersion: 4.XX -Contact: Greg Kroah-Hartman -Description: - The cport ID of the AP, to which cport of the module is - connected. - -What: /sys/bus/greybus/device/endoE:M:I:B:C/protocol_id -Date: October 2015 -KernelVersion: 4.XX -Contact: Greg Kroah-Hartman -Description: - The protocol ID of a Greybus cport. - -What: /sys/bus/greybus/device/endoE:M:I:B:C/state -Date: October 2015 -KernelVersion: 4.XX -Contact: Greg Kroah-Hartman -Description: - The current state of a Greybus connection. - - It will be one of the following values: - 0 - invalid - 1 - disabled - 2 - enabled - 3 - error - 4 - destroying diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 3b731da..abd8577 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -67,63 +67,18 @@ void greybus_data_rcvd(struct greybus_host_device *hd, u16 cport_id, } EXPORT_SYMBOL_GPL(greybus_data_rcvd); -static ssize_t state_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct gb_connection *connection = to_gb_connection(dev); - enum gb_connection_state state; - - spin_lock_irq(&connection->lock); - state = connection->state; - spin_unlock_irq(&connection->lock); - - return sprintf(buf, "%d\n", state); -} -static DEVICE_ATTR_RO(state); - -static ssize_t -protocol_id_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct gb_connection *connection = to_gb_connection(dev); - - if (connection->protocol) - return sprintf(buf, "%d\n", connection->protocol->id); - else - return -EINVAL; -} -static DEVICE_ATTR_RO(protocol_id); - -static ssize_t -ap_cport_id_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct gb_connection *connection = to_gb_connection(dev); - return sprintf(buf, "%hu\n", connection->hd_cport_id); -} -static DEVICE_ATTR_RO(ap_cport_id); - -static struct attribute *connection_attrs[] = { - &dev_attr_state.attr, - &dev_attr_protocol_id.attr, - &dev_attr_ap_cport_id.attr, - NULL, -}; - -ATTRIBUTE_GROUPS(connection); +static DEFINE_MUTEX(connection_mutex); -static void gb_connection_release(struct device *dev) +static void gb_connection_kref_release(struct kref *kref) { - struct gb_connection *connection = to_gb_connection(dev); + struct gb_connection *connection; + connection = container_of(kref, struct gb_connection, kref); destroy_workqueue(connection->wq); kfree(connection); + mutex_unlock(&connection_mutex); } -struct device_type greybus_connection_type = { - .name = "greybus_connection", - .release = gb_connection_release, -}; - - int svc_update_connection(struct gb_interface *intf, struct gb_connection *connection) { @@ -133,13 +88,7 @@ int svc_update_connection(struct gb_interface *intf, if (!bundle) return -EINVAL; - device_del(&connection->dev); connection->bundle = bundle; - connection->dev.parent = &bundle->dev; - dev_set_name(&connection->dev, "%s:%d", dev_name(&bundle->dev), - GB_SVC_CPORT_ID); - - WARN_ON(device_add(&connection->dev)); spin_lock_irq(&gb_connections_lock); list_add(&connection->bundle_links, &bundle->connections); @@ -210,24 +159,7 @@ gb_connection_create_range(struct greybus_host_device *hd, if (!connection->wq) goto err_free_connection; - connection->dev.parent = parent; - connection->dev.bus = &greybus_bus_type; - connection->dev.type = &greybus_connection_type; - connection->dev.groups = connection_groups; - device_initialize(&connection->dev); - dev_set_name(&connection->dev, "%s:%d", - dev_name(parent), cport_id); - - retval = device_add(&connection->dev); - if (retval) { - connection->hd_cport_id = CPORT_ID_BAD; - put_device(&connection->dev); - - dev_err(parent, "failed to register connection to cport %04hx: %d\n", - cport_id, retval); - - goto err_remove_ida; - } + kref_init(&connection->kref); spin_lock_irq(&gb_connections_lock); list_add(&connection->hd_links, &hd->connections); @@ -524,7 +456,8 @@ void gb_connection_destroy(struct gb_connection *connection) ida_simple_remove(id_map, connection->hd_cport_id); connection->hd_cport_id = CPORT_ID_BAD; - device_unregister(&connection->dev); + kref_put_mutex(&connection->kref, gb_connection_kref_release, + &connection_mutex); } void gb_connection_latency_tag_enable(struct gb_connection *connection) diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 2eaf186..af425a2 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -24,7 +24,7 @@ enum gb_connection_state { struct gb_connection { struct greybus_host_device *hd; struct gb_bundle *bundle; - struct device dev; + struct kref kref; u16 hd_cport_id; u16 intf_cport_id; @@ -48,7 +48,6 @@ struct gb_connection { void *private; }; -#define to_gb_connection(d) container_of(d, struct gb_connection, dev) int svc_update_connection(struct gb_interface *intf, struct gb_connection *connection); -- cgit v0.10.2 From 30482c1e63f3530f38f9364b90e35f1e9a990a4c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 16 Oct 2015 16:56:23 -0700 Subject: greybus: connection: use the bundle struct device instead of the connector We are removing struct device from the gb_connection structure in the near future. The gb_bundle structure's struct device should be used as a replacement. This patch moves the connection code to use the bundle pointer instead of the connection pointer for some error messages. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Viresh Kumar Reviewed-by: Alex Elder Reviewed-by: Johan Hovold diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index abd8577..0be78fe 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -173,8 +173,8 @@ gb_connection_create_range(struct greybus_host_device *hd, retval = gb_connection_bind_protocol(connection); if (retval) { - dev_err(&connection->dev, "failed to bind protocol: %d\n", - retval); + dev_err(&bundle->dev, "%d: failed to bind protocol: %d\n", + cport_id, retval); gb_connection_destroy(connection); return NULL; } @@ -199,8 +199,8 @@ static int gb_connection_hd_cport_enable(struct gb_connection *connection) ret = hd->driver->cport_enable(hd, connection->hd_cport_id); if (ret) { - dev_err(&connection->dev, - "failed to enable host cport: %d\n", ret); + dev_err(&connection->bundle->dev, + "failed to enable host cport: %d\n", ret); return ret; } @@ -277,8 +277,8 @@ gb_connection_svc_connection_create(struct gb_connection *connection) connection->intf_cport_id, intf->boot_over_unipro); if (ret) { - dev_err(&connection->dev, - "failed to create svc connection: %d\n", ret); + dev_err(&connection->bundle->dev, + "failed to create svc connection: %d\n", ret); return ret; } @@ -313,8 +313,8 @@ static int gb_connection_control_connected(struct gb_connection *connection) ret = gb_control_connected_operation(control, cport_id); if (ret) { - dev_err(&connection->dev, - "failed to connect cport: %d\n", ret); + dev_err(&connection->bundle->dev, + "failed to connect cport: %d\n", ret); return ret; } @@ -337,8 +337,8 @@ gb_connection_control_disconnected(struct gb_connection *connection) ret = gb_control_disconnected_operation(control, cport_id); if (ret) { - dev_warn(&connection->dev, - "failed to disconnect cport: %d\n", ret); + dev_warn(&connection->bundle->dev, + "failed to disconnect cport: %d\n", ret); } } @@ -356,8 +356,8 @@ static int gb_connection_protocol_get_version(struct gb_connection *connection) ret = gb_protocol_get_version(connection); if (ret) { - dev_err(&connection->dev, - "failed to get protocol version: %d\n", ret); + dev_err(&connection->bundle->dev, + "failed to get protocol version: %d\n", ret); return ret; } @@ -470,7 +470,7 @@ void gb_connection_latency_tag_enable(struct gb_connection *connection) ret = hd->driver->latency_tag_enable(hd, connection->hd_cport_id); if (ret) { - dev_err(&connection->dev, + dev_err(&connection->bundle->dev, "failed to enable latency tag: %d\n", ret); } } @@ -486,7 +486,7 @@ void gb_connection_latency_tag_disable(struct gb_connection *connection) ret = hd->driver->latency_tag_disable(hd, connection->hd_cport_id); if (ret) { - dev_err(&connection->dev, + dev_err(&connection->bundle->dev, "failed to disable latency tag: %d\n", ret); } } @@ -513,7 +513,7 @@ int gb_connection_bind_protocol(struct gb_connection *connection) connection->major, connection->minor); if (!protocol) { - dev_warn(&connection->dev, + dev_warn(&connection->bundle->dev, "protocol 0x%02hhx version %hhu.%hhu not found\n", connection->protocol_id, connection->major, connection->minor); -- cgit v0.10.2 From d9a9ea1b88190a31957489377fd3fee246888373 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 16 Oct 2015 16:55:46 -0700 Subject: greybus: loopback: use the bundle struct device instead of the connector We are removing struct device from the gb_connection structure in the near future. The gb_bundle structure's struct device should be used as a replacement. This patch moves the loopback driver to use the bundle pointer instead of the connection pointer. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Viresh Kumar Reviewed-by: Alex Elder Reviewed-by: Johan Hovold diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 1ac86c1..e1b1be0 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -107,11 +107,11 @@ static ssize_t field##_##pfx##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ - struct gb_connection *connection; \ + struct gb_bundle *bundle; \ struct gb_loopback *gb; \ if (conn) { \ - connection = to_gb_connection(dev); \ - gb = connection->private; \ + bundle = to_gb_bundle(dev); \ + gb = bundle->private; \ return sprintf(buf, "%u\n", gb->field); \ } else { \ return sprintf(buf, "%u\n", gb_dev.field); \ @@ -124,11 +124,11 @@ static ssize_t name##_##field##_##pfx##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ - struct gb_connection *connection; \ + struct gb_bundle *bundle; \ struct gb_loopback *gb; \ if (conn) { \ - connection = to_gb_connection(dev); \ - gb = connection->private; \ + bundle = to_gb_bundle(dev); \ + gb = bundle->private; \ return sprintf(buf, "%"#type"\n", gb->name.field); \ } else { \ return sprintf(buf, "%"#type"\n", gb_dev.name.field); \ @@ -142,13 +142,13 @@ static ssize_t name##_avg_##pfx##_show(struct device *dev, \ char *buf) \ { \ struct gb_loopback_stats *stats; \ - struct gb_connection *connection; \ + struct gb_bundle *bundle; \ struct gb_loopback *gb; \ u64 avg; \ u32 count, rem; \ if (conn) { \ - connection = to_gb_connection(dev); \ - gb = connection->private; \ + bundle = to_gb_bundle(dev); \ + gb = bundle->private; \ stats = &gb->name; \ } else { \ stats = &gb_dev.name; \ @@ -170,8 +170,8 @@ static ssize_t field##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ - struct gb_connection *connection = to_gb_connection(dev); \ - struct gb_loopback *gb = connection->private; \ + struct gb_bundle *bundle = to_gb_bundle(dev); \ + struct gb_loopback *gb = bundle->private; \ return sprintf(buf, "%"#type"\n", gb->field); \ } \ static ssize_t field##_store(struct device *dev, \ @@ -180,13 +180,13 @@ static ssize_t field##_store(struct device *dev, \ size_t len) \ { \ int ret; \ - struct gb_connection *connection = to_gb_connection(dev); \ + struct gb_bundle *bundle = to_gb_bundle(dev); \ mutex_lock(&gb_dev.mutex); \ ret = sscanf(buf, "%"#type, &gb->field); \ if (ret != 1) \ len = -EINVAL; \ else \ - gb_loopback_check_attr(connection); \ + gb_loopback_check_attr(&gb_dev, bundle); \ mutex_unlock(&gb_dev.mutex); \ return len; \ } \ @@ -214,13 +214,13 @@ static ssize_t field##_store(struct device *dev, \ size_t len) \ { \ int ret; \ - struct gb_connection *connection = to_gb_connection(dev); \ + struct gb_bundle *bundle = to_gb_bundle(dev); \ mutex_lock(&gb_dev.mutex); \ ret = sscanf(buf, "%"#type, &gb_dev.field); \ if (ret != 1) \ len = -EINVAL; \ else \ - gb_loopback_check_attr(&gb_dev, connection); \ + gb_loopback_check_attr(&gb_dev, bundle); \ mutex_unlock(&gb_dev.mutex); \ return len; \ } \ @@ -228,7 +228,7 @@ static DEVICE_ATTR_RW(field) static void gb_loopback_reset_stats(struct gb_loopback_device *gb_dev); static void gb_loopback_check_attr(struct gb_loopback_device *gb_dev, - struct gb_connection *connection) + struct gb_bundle *bundle) { struct gb_loopback *gb; @@ -244,7 +244,7 @@ static void gb_loopback_check_attr(struct gb_loopback_device *gb_dev, gb->iteration_count = 0; gb->error = 0; if (kfifo_depth < gb_dev->iteration_max) { - dev_warn(&connection->dev, + dev_warn(&bundle->dev, "cannot log bytes %u kfifo_depth %u\n", gb_dev->iteration_max, kfifo_depth); } @@ -414,14 +414,14 @@ static int gb_loopback_operation_sync(struct gb_loopback *gb, int type, ret = gb_operation_request_send_sync(operation); if (ret) { - dev_err(&gb->connection->dev, + dev_err(&gb->connection->bundle->dev, "synchronous operation failed: %d\n", ret); } else { if (response_size == operation->response->payload_size) { memcpy(response, operation->response->payload, response_size); } else { - dev_err(&gb->connection->dev, + dev_err(&gb->connection->bundle->dev, "response size %zu expected %d\n", operation->response->payload_size, response_size); @@ -482,7 +482,8 @@ static int gb_loopback_transfer(struct gb_loopback *gb, u32 len) goto gb_error; if (memcmp(request->data, response->data, len)) { - dev_err(&gb->connection->dev, "Loopback Data doesn't match\n"); + dev_err(&gb->connection->bundle->dev, + "Loopback Data doesn't match\n"); retval = -EREMOTEIO; } gb->apbridge_latency_ts = (u32)__le32_to_cpu(response->reserved0); @@ -506,21 +507,20 @@ static int gb_loopback_request_recv(u8 type, struct gb_operation *operation) struct gb_connection *connection = operation->connection; struct gb_loopback_transfer_request *request; struct gb_loopback_transfer_response *response; + struct device *dev = &connection->bundle->dev; size_t len; /* By convention, the AP initiates the version operation */ switch (type) { case GB_REQUEST_TYPE_PROTOCOL_VERSION: - dev_err(&connection->dev, - "module-initiated version operation\n"); + dev_err(dev, "module-initiated version operation\n"); return -EINVAL; case GB_LOOPBACK_TYPE_PING: case GB_LOOPBACK_TYPE_SINK: return 0; case GB_LOOPBACK_TYPE_TRANSFER: if (operation->request->payload_size < sizeof(*request)) { - dev_err(&connection->dev, - "transfer request too small (%zu < %zu)\n", + dev_err(dev, "transfer request too small (%zu < %zu)\n", operation->request->payload_size, sizeof(*request)); return -EINVAL; /* -EMSGSIZE */ @@ -528,8 +528,7 @@ static int gb_loopback_request_recv(u8 type, struct gb_operation *operation) request = operation->request->payload; len = le32_to_cpu(request->len); if (len > gb_dev.size_max) { - dev_err(&connection->dev, - "transfer request too large (%zu > %zu)\n", + dev_err(dev, "transfer request too large (%zu > %zu)\n", len, gb_dev.size_max); return -EINVAL; } @@ -537,8 +536,7 @@ static int gb_loopback_request_recv(u8 type, struct gb_operation *operation) if (len) { if (!gb_operation_response_alloc(operation, len, GFP_KERNEL)) { - dev_err(&connection->dev, - "error allocating response\n"); + dev_err(dev, "error allocating response\n"); return -ENOMEM; } response = operation->response->payload; @@ -547,8 +545,7 @@ static int gb_loopback_request_recv(u8 type, struct gb_operation *operation) } return 0; default: - dev_err(&connection->dev, - "unsupported request: %hhu\n", type); + dev_err(dev, "unsupported request: %hhu\n", type); return -EINVAL; } } @@ -755,8 +752,8 @@ static int gb_loopback_fn(void *data) /* All threads achieved at least low_count iterations */ if (gb_dev.iteration_count < low_count) { gb_dev.iteration_count = low_count; - sysfs_notify(&gb->connection->dev.kobj, NULL, - "iteration_count"); + sysfs_notify(&gb->connection->bundle->dev.kobj, + NULL, "iteration_count"); } /* Optionally terminate */ if (gb_dev.iteration_count == gb_dev.iteration_max) { @@ -954,12 +951,12 @@ static int gb_loopback_connection_init(struct gb_connection *connection) /* Create per-connection sysfs and debugfs data-points */ snprintf(name, sizeof(name), "raw_latency_%s", - dev_name(&connection->dev)); + dev_name(&connection->bundle->dev)); gb->file = debugfs_create_file(name, S_IFREG | S_IRUGO, gb_dev.root, gb, &gb_loopback_debugfs_latency_ops); gb->connection = connection; - connection->private = gb; - retval = sysfs_create_groups(&connection->dev.kobj, + connection->bundle->private = gb; + retval = sysfs_create_groups(&connection->bundle->dev.kobj, loopback_con_groups); if (retval) goto out_sysfs_dev; @@ -995,14 +992,14 @@ out_kfifo1: out_kfifo0: kfifo_free(&gb->kfifo_lat); out_sysfs_conn: - sysfs_remove_groups(&connection->dev.kobj, loopback_con_groups); + sysfs_remove_groups(&connection->bundle->dev.kobj, loopback_con_groups); out_sysfs_dev: if (!gb_dev.count) { sysfs_remove_groups(kobj, loopback_dev_groups); debugfs_remove(gb_dev.file); } debugfs_remove(gb->file); - connection->private = NULL; + connection->bundle->private = NULL; out_sysfs: mutex_unlock(&gb_dev.mutex); kfree(gb); @@ -1012,7 +1009,7 @@ out_sysfs: static void gb_loopback_connection_exit(struct gb_connection *connection) { - struct gb_loopback *gb = connection->private; + struct gb_loopback *gb = connection->bundle->private; struct kobject *kobj = &connection->hd->endo->dev.kobj; if (!IS_ERR_OR_NULL(gb->task)) @@ -1020,7 +1017,7 @@ static void gb_loopback_connection_exit(struct gb_connection *connection) mutex_lock(&gb_dev.mutex); - connection->private = NULL; + connection->bundle->private = NULL; kfifo_free(&gb->kfifo_lat); kfifo_free(&gb->kfifo_ts); gb_connection_latency_tag_disable(connection); @@ -1029,7 +1026,8 @@ static void gb_loopback_connection_exit(struct gb_connection *connection) sysfs_remove_groups(kobj, loopback_dev_groups); debugfs_remove(gb_dev.file); } - sysfs_remove_groups(&connection->dev.kobj, loopback_con_groups); + sysfs_remove_groups(&connection->bundle->dev.kobj, + loopback_con_groups); debugfs_remove(gb->file); list_del(&gb->entry); mutex_unlock(&gb_dev.mutex); -- cgit v0.10.2 From 5d9c68da01e80c145bfc5e28ccb27b17d3a016b3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 16 Oct 2015 16:55:29 -0700 Subject: greybus: greybus_trace: use the bundle struct device instead of the connector We are removing struct device from the gb_connection structure in the near future. The gb_bundle structure's struct device should be used as a replacement. This patch moves the greybus trace code to use the bundle pointer instead of the connection pointer when printing out tracing messages. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Viresh Kumar Reviewed-by: Alex Elder Reviewed-by: Johan Hovold diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h index 6c88d34..e5e3cc0 100644 --- a/drivers/staging/greybus/greybus_trace.h +++ b/drivers/staging/greybus/greybus_trace.h @@ -24,7 +24,7 @@ DECLARE_EVENT_CLASS(gb_message, TP_ARGS(message), TP_STRUCT__entry( - __string(name, dev_name(&message->operation->connection->dev)) + __string(name, dev_name(&message->operation->connection->bundle->dev)) __field(u16, op_id) __field(u16, intf_cport_id) __field(u16, hd_cport_id) @@ -32,7 +32,7 @@ DECLARE_EVENT_CLASS(gb_message, ), TP_fast_assign( - __assign_str(name, dev_name(&message->operation->connection->dev)) + __assign_str(name, dev_name(&message->operation->connection->bundle->dev)) __entry->op_id = message->operation->id; __entry->intf_cport_id = message->operation->connection->intf_cport_id; -- cgit v0.10.2 From 7e4c8d713539b608a11a38102a203a1a8acd345a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 16 Oct 2015 16:54:18 -0700 Subject: greybus: protocol: use the bundle struct device instead of the connector We are removing struct device from the gb_connection structure in the near future. The gb_bundle structure's struct device should be used as a replacement. This patch moves the protocol code to use the bundle pointer instead of the connection pointer when printing out error messages. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Viresh Kumar Reviewed-by: Alex Elder Reviewed-by: Johan Hovold diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index 889cff2..1790d1a 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -165,19 +165,19 @@ int gb_protocol_get_version(struct gb_connection *connection) return retval; if (response.major > connection->protocol->major) { - dev_err(&connection->dev, - "unsupported major version (%hhu > %hhu)\n", - response.major, connection->protocol->major); + dev_err(&connection->bundle->dev, + "%d: unsupported major version (%hhu > %hhu)\n", + connection->intf_cport_id, response.major, + connection->protocol->major); return -ENOTSUPP; } connection->module_major = response.major; connection->module_minor = response.minor; - - dev_dbg(&connection->dev, "%s - %s (0x%02hhx) v%hhu.%hhu\n", __func__, - protocol->name, protocol->id, - response.major, response.minor); + dev_dbg(&connection->bundle->dev, + "%d: %s (0x%02hhx) v%hhu.%hhu\n", connection->intf_cport_id, + protocol->name, protocol->id, response.major, response.minor); return 0; } -- cgit v0.10.2 From 6ea462a4fc21b523dc139fdb920524f066633a35 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 16 Oct 2015 16:54:00 -0700 Subject: greybus: bundle.h: add a private field to struct gb_bundle The gb_bundle structure needs a private field if we are going to be able to replace the gb_connection device with this one for all use cases. Ideally we could use the private pointer within the struct device, but for now let's just try to mirror how people were using the gb_connection structure to make the patches simpler, and the logic the same. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Viresh Kumar Reviewed-by: Alex Elder Reviewed-by: Johan Hovold diff --git a/drivers/staging/greybus/bundle.h b/drivers/staging/greybus/bundle.h index 9134df7..24ddd44 100644 --- a/drivers/staging/greybus/bundle.h +++ b/drivers/staging/greybus/bundle.h @@ -22,6 +22,7 @@ struct gb_bundle { u8 *state; struct list_head links; /* interface->bundles */ + void *private; }; #define to_gb_bundle(d) container_of(d, struct gb_bundle, dev) -- cgit v0.10.2 From c69b98d15fff68e83396d800f43508a1dab4130a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 16 Oct 2015 16:53:46 -0700 Subject: greybus: core: remove uevent handling for gb_connection As we are going to be removing the struct device from gb_connection, there is no need to do anything for uevents for them. So just remove the code. It wasn't doing anything anyway, so no functionality is lost here at all. As is_gb_connection() is no longer used, that is also removed in this patch. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Viresh Kumar Reviewed-by: Alex Elder Reviewed-by: Johan Hovold diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index ea23aaf..5e1c755 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -47,7 +47,6 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) struct gb_module *module = NULL; struct gb_interface *intf = NULL; struct gb_bundle *bundle = NULL; - struct gb_connection *connection = NULL; if (is_gb_endo(dev)) { /* @@ -64,21 +63,11 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) } else if (is_gb_bundle(dev)) { bundle = to_gb_bundle(dev); intf = bundle->intf; - } else if (is_gb_connection(dev)) { - connection = to_gb_connection(dev); - bundle = connection->bundle; - intf = bundle->intf; } else { dev_WARN(dev, "uevent for unknown greybus device \"type\"!\n"); return -EINVAL; } - if (connection) { - // FIXME - // add a uevent that can "load" a connection type - return 0; - } - if (bundle) { // FIXME // add a uevent that can "load" a bundle type diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index ec4a738..ae59756 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -189,11 +189,6 @@ static inline int is_gb_bundle(const struct device *dev) return dev->type == &greybus_bundle_type; } -static inline int is_gb_connection(const struct device *dev) -{ - return dev->type == &greybus_connection_type; -} - static inline bool cport_id_valid(struct greybus_host_device *hd, u16 cport_id) { return cport_id != CPORT_ID_BAD && cport_id < hd->num_cports; -- cgit v0.10.2 From b50a24e9471290fae7f7d16be467b3b0937d3d0e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 16 Oct 2015 16:53:31 -0700 Subject: greybus: svc: don't trust any struct devices As the svc code is "odd" in how things are set up at initial connection time, we can't always "know" that we have a valid bundle to use for error messages. So just punt and always use pr_*() calls to ensure that we never incorrectly dereference a pointer. This will get fixed up soon, but for now, let's just live with a bit messier error messages in the log. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Viresh Kumar Reviewed-by: Alex Elder Reviewed-by: Johan Hovold diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 4b9eb38..e5cd897 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -7,6 +7,7 @@ * Released under the GPLv2 only. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include #include "greybus.h" @@ -120,17 +121,15 @@ int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, &request, sizeof(request), &response, sizeof(response)); if (ret) { - dev_err(&svc->connection->dev, - "failed to get DME attribute (%hhu %hx %hu) %d\n", - intf_id, attr, selector, ret); + pr_err("failed to get DME attribute (%hhu %hx %hu) %d\n", + intf_id, attr, selector, ret); return ret; } result = le16_to_cpu(response.result_code); if (result) { - dev_err(&svc->connection->dev, - "Unipro error %hu while getting DME attribute (%hhu %hx %hu)\n", - result, intf_id, attr, selector); + pr_err("Unipro error %hu while getting DME attribute (%hhu %hx %hu)\n", + result, intf_id, attr, selector); return -EINVAL; } @@ -158,17 +157,15 @@ int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, &request, sizeof(request), &response, sizeof(response)); if (ret) { - dev_err(&svc->connection->dev, - "failed to set DME attribute (%hhu %hx %hu %u) %d\n", - intf_id, attr, selector, value, ret); + pr_err("failed to set DME attribute (%hhu %hx %hu %u) %d\n", + intf_id, attr, selector, value, ret); return ret; } result = le16_to_cpu(response.result_code); if (result) { - dev_err(&svc->connection->dev, - "Unipro error %hu while setting DME attribute (%hhu %hx %hu %u)\n", - result, intf_id, attr, selector, value); + pr_err("Unipro error %hu while setting DME attribute (%hhu %hx %hu %u)\n", + result, intf_id, attr, selector, value); return -EINVAL; } @@ -270,11 +267,9 @@ void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, ret = gb_operation_sync(connection, GB_SVC_TYPE_CONN_DESTROY, &request, sizeof(request), NULL, 0); - if (ret) { - dev_err(&connection->dev, - "failed to destroy connection (%hhx:%hx %hhx:%hx) %d\n", - intf1_id, cport1_id, intf2_id, cport2_id, ret); - } + if (ret) + pr_err("failed to destroy connection (%hhx:%hx %hhx:%hx) %d\n", + intf1_id, cport1_id, intf2_id, cport2_id, ret); } EXPORT_SYMBOL_GPL(gb_svc_connection_destroy); @@ -304,11 +299,9 @@ static void gb_svc_route_destroy(struct gb_svc *svc, u8 intf1_id, u8 intf2_id) ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_ROUTE_DESTROY, &request, sizeof(request), NULL, 0); - if (ret) { - dev_err(&svc->connection->dev, - "failed to destroy route (%hhx %hhx) %d\n", + if (ret) + pr_err("failed to destroy route (%hhx %hhx) %d\n", intf1_id, intf2_id, ret); - } } static int gb_svc_version_request(struct gb_operation *op) @@ -316,14 +309,13 @@ static int gb_svc_version_request(struct gb_operation *op) struct gb_connection *connection = op->connection; struct gb_protocol_version_request *request; struct gb_protocol_version_response *response; - struct device *dev = &connection->dev; request = op->request->payload; if (request->major > GB_SVC_VERSION_MAJOR) { - dev_err(&connection->dev, - "unsupported major version (%hhu > %hhu)\n", - request->major, GB_SVC_VERSION_MAJOR); + pr_err("%d: unsupported major version (%hhu > %hhu)\n", + connection->intf_cport_id, request->major, + GB_SVC_VERSION_MAJOR); return -ENOTSUPP; } @@ -331,8 +323,8 @@ static int gb_svc_version_request(struct gb_operation *op) connection->module_minor = request->minor; if (!gb_operation_response_alloc(op, sizeof(*response), GFP_KERNEL)) { - dev_err(dev, "%s: error allocating response\n", - __func__); + pr_err("%d: error allocating response\n", + connection->intf_cport_id); return -ENOMEM; } @@ -348,7 +340,6 @@ static int gb_svc_hello(struct gb_operation *op) struct gb_connection *connection = op->connection; struct greybus_host_device *hd = connection->hd; struct gb_svc_hello_request *hello_request; - struct device *dev = &connection->dev; struct gb_interface *intf; u16 endo_id; u8 interface_id; @@ -359,9 +350,9 @@ static int gb_svc_hello(struct gb_operation *op) * request, use that to create an endo. */ if (op->request->payload_size < sizeof(*hello_request)) { - dev_err(dev, "%s: Illegal size of hello request (%zu < %zu)\n", - __func__, op->request->payload_size, - sizeof(*hello_request)); + pr_err("%d: Illegal size of hello request (%zu < %zu)\n", + connection->intf_cport_id, op->request->payload_size, + sizeof(*hello_request)); return -EINVAL; } @@ -418,7 +409,6 @@ static void svc_process_hotplug(struct work_struct *work) struct gb_connection *connection = svc_hotplug->connection; struct gb_svc *svc = connection->private; struct greybus_host_device *hd = connection->hd; - struct device *dev = &connection->dev; struct gb_interface *intf; u8 intf_id, device_id; int ret; @@ -444,15 +434,15 @@ static void svc_process_hotplug(struct work_struct *work) * Remove the interface and add it again, and let user know * about this with a print message. */ - dev_info(dev, "Removed interface (%hhu) to add it again\n", - intf_id); + pr_info("%d: Removed interface (%hhu) to add it again\n", + connection->intf_cport_id, intf_id); svc_intf_remove(connection, intf); } intf = gb_interface_create(hd, intf_id); if (!intf) { - dev_err(dev, "%s: Failed to create interface with id %hhu\n", - __func__, intf_id); + pr_err("%d: Failed to create interface with id %hhu\n", + connection->intf_cport_id, intf_id); goto free_svc_hotplug; } @@ -477,15 +467,15 @@ static void svc_process_hotplug(struct work_struct *work) GB_DEVICE_ID_MODULES_START, 0, GFP_KERNEL); if (device_id < 0) { ret = device_id; - dev_err(dev, "%s: Failed to allocate device id for interface with id %hhu (%d)\n", - __func__, intf_id, ret); + pr_err("%d: Failed to allocate device id for interface with id %hhu (%d)\n", + connection->intf_cport_id, intf_id, ret); goto destroy_interface; } ret = gb_svc_intf_device_id(svc, intf_id, device_id); if (ret) { - dev_err(dev, "%s: Device id operation failed, interface %hhu device_id %hhu (%d)\n", - __func__, intf_id, device_id, ret); + pr_err("%d: Device id operation failed, interface %hhu device_id %hhu (%d)\n", + connection->intf_cport_id, intf_id, device_id, ret); goto ida_put; } @@ -495,15 +485,15 @@ static void svc_process_hotplug(struct work_struct *work) ret = gb_svc_route_create(svc, hd->endo->ap_intf_id, GB_DEVICE_ID_AP, intf_id, device_id); if (ret) { - dev_err(dev, "%s: Route create operation failed, interface %hhu device_id %hhu (%d)\n", - __func__, intf_id, device_id, ret); + pr_err("%d: Route create operation failed, interface %hhu device_id %hhu (%d)\n", + connection->intf_cport_id, intf_id, device_id, ret); goto svc_id_free; } ret = gb_interface_init(intf, device_id); if (ret) { - dev_err(dev, "%s: Failed to initialize interface, interface %hhu device_id %hhu (%d)\n", - __func__, intf_id, device_id, ret); + pr_err("%d: Failed to initialize interface, interface %hhu device_id %hhu (%d)\n", + connection->intf_cport_id, intf_id, device_id, ret); goto destroy_route; } @@ -539,10 +529,9 @@ static int gb_svc_intf_hotplug_recv(struct gb_operation *op) struct svc_hotplug *svc_hotplug; if (request->payload_size < sizeof(svc_hotplug->data)) { - dev_err(&op->connection->dev, - "%s: short hotplug request received (%zu < %zu)\n", - __func__, request->payload_size, - sizeof(svc_hotplug->data)); + pr_err("%d: short hotplug request received (%zu < %zu)\n", + op->connection->intf_cport_id, request->payload_size, + sizeof(svc_hotplug->data)); return -EINVAL; } @@ -564,13 +553,13 @@ static int gb_svc_intf_hot_unplug_recv(struct gb_operation *op) struct gb_message *request = op->request; struct gb_svc_intf_hot_unplug_request *hot_unplug = request->payload; struct greybus_host_device *hd = op->connection->hd; - struct device *dev = &op->connection->dev; struct gb_interface *intf; u8 intf_id; if (request->payload_size < sizeof(*hot_unplug)) { - dev_err(dev, "short hot unplug request received (%zu < %zu)\n", - request->payload_size, sizeof(*hot_unplug)); + pr_err("connection %d: short hot unplug request received (%zu < %zu)\n", + op->connection->intf_cport_id, request->payload_size, + sizeof(*hot_unplug)); return -EINVAL; } @@ -578,8 +567,8 @@ static int gb_svc_intf_hot_unplug_recv(struct gb_operation *op) intf = gb_interface_find(hd, intf_id); if (!intf) { - dev_err(dev, "%s: Couldn't find interface for id %hhu\n", - __func__, intf_id); + pr_err("connection %d: Couldn't find interface for id %hhu\n", + op->connection->intf_cport_id, intf_id); return -EINVAL; } @@ -595,9 +584,9 @@ static int gb_svc_intf_reset_recv(struct gb_operation *op) u8 intf_id; if (request->payload_size < sizeof(*reset)) { - dev_err(&op->connection->dev, - "short reset request received (%zu < %zu)\n", - request->payload_size, sizeof(*reset)); + pr_err("connection %d: short reset request received (%zu < %zu)\n", + op->connection->intf_cport_id, request->payload_size, + sizeof(*reset)); return -EINVAL; } reset = request->payload; @@ -641,9 +630,8 @@ static int gb_svc_request_recv(u8 type, struct gb_operation *op) } if (ret) { - dev_warn(&connection->dev, - "unexpected SVC request 0x%02x received (state %u)\n", - type, svc->state); + pr_warn("connection %d: unexpected SVC request 0x%02x received (state %u)\n", + connection->intf_cport_id, type, svc->state); return ret; } @@ -665,8 +653,8 @@ static int gb_svc_request_recv(u8 type, struct gb_operation *op) case GB_SVC_TYPE_INTF_RESET: return gb_svc_intf_reset_recv(op); default: - dev_err(&op->connection->dev, - "unsupported request: %hhu\n", type); + pr_err("connection %d: unsupported request: %hhu\n", + connection->intf_cport_id, type); return -EINVAL; } } -- cgit v0.10.2 From d517f274e9db414ae4d6df5173c3e7f41b9dac66 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Wed, 21 Oct 2015 16:50:20 +0530 Subject: greybus: platform: Add platform driver for DB3 AP bridge With DB3, we now have AP as a master as far as AP bridges are concerned. SVC will talk only to AP and AP will control bridges; unlike other module interfaces. So AP supposed to manage/control bridges in all power states including power on reset. During power on reset AP should follow below sequence - Sequence (treated as a Cold Boot) Stage-1 ======= AP: - Power On (Power up from PMIC to AP) - AP start booting Since power to AP bridges are controlled through gpio, power is gated to APB1 & 2 No ref_clk to APB available (under SVC's control) - AP configures USB hub to enable HSIC interface to APB - As part of platform driver probe, AP follow below sequence - Set the pinctrl in default state - Hold APBs in reset by pulling down reset pin - Enable power to APB by enabling regulator and switches - De-assert (set 'low') 'boot_ret' signal - AP will assert (set 'high') the wake_detect signal, triggering connect/detect event to the SVC - AP waits for wake pulse from SVC SVC: - Power On (power up from PMIC to SVC) - SVC starts booting - SVC will de-assert reset signal to unipro switch - Switch starts booting - SVC confirms switch boot status using SPI (or something) - SVC waits for 300 msec (ES2 known issue) - SVC waits for detect/connect event from AP Stage-2 ======= SVC: - ON connect/detect event, SVC send back wake pulse (cold boot) to AP over wake_detect pin, if SVC boot is completed. AP: - On wake pulse from SVC (for cold boot), AP de-asserts (set high') reset signal to APB 1 and/or 2 - Bridges starts booting - Eventually Unipro linkup occurs Testing: - Build tested against Helium kernel - Due to unavailability of MSM and DB3 platform, only minimal testing has been done. - Code has been modified for validation on Helium + SDB platform. Mostly dts changes for gpio numbers And debug messages to check gpio values - On Helium + SDB platform, with addition of debug messages validated the sequence. TODO list: - Currently _only_ supports power on sequence (cold boot). Both warm and cold boot support. Cold and Warm boot is differentiated based on pulse width of wake_detect signal >=5 msec = Cold boot else Warm boot - No support for Power management So the "power-down", "power-off", "wake_in" and "wake_out" signals are not explored/implemented. - Support for Work thread repetitive wake signal if no response from peer May required for PM support, as we have delays in the sequences - pinctrl states, specially to make sure we enable right pullup or pulldown when we set wake_detect pin to input - Convert gpio list into an array, and associated xxx-gpio-name property Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index a627340..b8dc36b 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -34,6 +34,7 @@ gb-light-y := light.o gb-raw-y := raw.o gb-es1-y := es1.o gb-es2-y := es2.o +gb-db3-y := db3-platform.o obj-m += greybus.o obj-m += gb-phy.o @@ -44,6 +45,7 @@ obj-m += gb-light.o obj-m += gb-raw.o obj-m += gb-es1.o obj-m += gb-es2.o +obj-m += gb-db3.o KERNELVER ?= $(shell uname -r) KERNELDIR ?= /lib/modules/$(KERNELVER)/build diff --git a/drivers/staging/greybus/db3-platform.c b/drivers/staging/greybus/db3-platform.c new file mode 100644 index 0000000..4391348 --- /dev/null +++ b/drivers/staging/greybus/db3-platform.c @@ -0,0 +1,378 @@ +/* + * DB3 Platform driver for AP bridge control interface. + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum apb_state { + APB_STATE_OFF, + APB_STATE_ACTIVE, + APB_STATE_STANDBY, +}; + +/* + * Control GPIO signals to and from AP <=> AP Bridges + */ +struct apb_ctrl_gpios { + int wake_detect; /* bi-dir, maps to WAKE_MOD and WAKE_FRAME signals */ + int reset; + int boot_ret; + int pwroff; + int wake_in; + int wake_out; + int pwrdn; +}; + +struct apb_ctrl_drvdata { + struct apb_ctrl_gpios ctrl; + + unsigned int wake_detect_irq; + enum apb_state state; + + struct regulator *vcore; + struct regulator *vio; + + struct pinctrl *pinctrl; + struct pinctrl_state *pin_default; + + /* To protect concurrent access of GPIO registers, need protection */ + spinlock_t lock; +}; + +static inline void assert_wake(unsigned int wake_detect) +{ + gpio_set_value(wake_detect, 1); +} + +static inline void deassert_wake(unsigned int wake_detect) +{ + gpio_set_value(wake_detect, 0); +} + +static irqreturn_t apb_ctrl_wake_detect_irq(int irq, void *devid) +{ + struct apb_ctrl_drvdata *apb_data = devid; + unsigned long flags; + + /* + * TODO: + * Since currently SoC gpio's are being used we are safe here + * But ideally we should create a workqueue and process the control + * signals, especially when we start using GPIO's over slow + * buses like I2C. + */ + if (!gpio_is_valid(apb_data->ctrl.wake_detect) && + !gpio_is_valid(apb_data->ctrl.reset)) + return IRQ_HANDLED; /* Should it be IRQ_NONE ?? */ + + spin_lock_irqsave(&apb_data->lock, flags); + + if (apb_data->state != APB_STATE_ACTIVE) { + /* Bring bridge out of reset on this event */ + gpio_set_value(apb_data->ctrl.reset, 0); + apb_data->state = APB_STATE_ACTIVE; + } else { + /* + * Assert Wake_OUT signal to APB + * It would resemble WakeDetect module's signal pass-through + */ + /* + * We have to generate the pulse, so we may need to schedule + * workqueue here. + * + * Also, since we are using both rising and falling edge for + * interrupt trigger, we may not need workqueue. Just pass + * through the value to bridge. + * Just read GPIO value and pass it to the bridge + */ + } + + spin_unlock_irqrestore(&apb_data->lock, flags); + + return IRQ_HANDLED; +} + +static void apb_ctrl_cleanup(struct apb_ctrl_drvdata *apb_data) +{ + if (apb_data->vcore && regulator_is_enabled(apb_data->vcore) > 0) + regulator_disable(apb_data->vcore); + + if (apb_data->vio && regulator_is_enabled(apb_data->vio) > 0) + regulator_disable(apb_data->vio); + + /* As part of exit, put APB back in reset state */ + if (gpio_is_valid(apb_data->ctrl.reset)) + gpio_set_value(apb_data->ctrl.reset, 1); + + /* TODO: May have to send an event to SVC about this exit */ +} + +/* + * Note: Please do not modify the below sequence, as it is as per the spec + */ +static int apb_ctrl_init_seq(struct device *dev, + struct apb_ctrl_drvdata *apb_data) +{ + int ret; + + pinctrl_select_state(apb_data->pinctrl, apb_data->pin_default); + + /* Hold APB in reset state */ + ret = devm_gpio_request_one(dev, apb_data->ctrl.reset, + GPIOF_OUT_INIT_LOW, "reset"); + if (ret) { + dev_err(dev, "Failed requesting reset gpio %d\n", + apb_data->ctrl.reset); + return ret; + } + + /* Enable power to APB */ + if (apb_data->vcore) { + ret = regulator_enable(apb_data->vcore); + if (ret) { + dev_err(dev, "failed to enable core regulator\n"); + return ret; + } + } + + if (apb_data->vio) { + ret = regulator_enable(apb_data->vio); + if (ret) { + dev_err(dev, "failed to enable IO regulator\n"); + return ret; + } + } + + /* + * We should be safe here to deassert boot retention signal, as + * we are only supporting cold boot as of now. + */ + ret = devm_gpio_request_one(dev, apb_data->ctrl.boot_ret, + GPIOF_OUT_INIT_LOW, "boot retention"); + if (ret) { + dev_err(dev, "Failed requesting reset gpio %d\n", + apb_data->ctrl.boot_ret); + return ret; + } + + ret = devm_gpio_request(dev, apb_data->ctrl.wake_detect, "wake detect"); + if (ret) + dev_err(dev, "Failed requesting wake_detect gpio %d\n", + apb_data->ctrl.wake_detect); + + return ret; +} + +static int apb_ctrl_get_devtree_data(struct device *dev, + struct apb_ctrl_drvdata *apb_data) +{ + struct device_node *np = dev->of_node; + + /* fetch control signals */ + apb_data->ctrl.wake_detect = of_get_named_gpio(np, "wake-detect-gpios", 0); + if (apb_data->ctrl.wake_detect < 0 || + !gpio_is_valid(apb_data->ctrl.wake_detect)) { + dev_err(dev, "failed to get wake detect gpio\n"); + return apb_data->ctrl.wake_detect; + } + + apb_data->ctrl.reset = of_get_named_gpio(np, "reset-gpios", 0); + if (apb_data->ctrl.wake_detect < 0 || + !gpio_is_valid(apb_data->ctrl.reset)) { + dev_err(dev, "failed to get wake detect gpio\n"); + return apb_data->ctrl.wake_detect; + } + + apb_data->ctrl.boot_ret = of_get_named_gpio(np, "boot-ret-gpios", 0); + if (apb_data->ctrl.boot_ret < 0 || + !gpio_is_valid(apb_data->ctrl.boot_ret)) { + dev_err(dev, "failed to get boot retention gpio\n"); + return apb_data->ctrl.boot_ret; + } + + /* It's not mandetory to support power management interface */ + apb_data->ctrl.pwroff = of_get_named_gpio(np, "pwr-off-gpios", 0); + if (apb_data->ctrl.pwroff < 0 || + !gpio_is_valid(apb_data->ctrl.pwroff)) + dev_info(dev, "failed to get power off gpio\n"); + + apb_data->ctrl.pwrdn = of_get_named_gpio(np, "pwr-down-gpios", 0); + if (apb_data->ctrl.pwrdn < 0 || + !gpio_is_valid(apb_data->ctrl.pwrdn)) + dev_info(dev, "failed to get power down gpio\n"); + + /* Regulators are optional, as we may have fixed supply coming in */ + apb_data->vcore = devm_regulator_get(dev, "vcore"); + if (IS_ERR_OR_NULL(apb_data->vcore)) { + dev_info(dev, "no core regulator found\n"); + apb_data->vcore = NULL; + } + + apb_data->vio = devm_regulator_get(dev, "vio"); + if (IS_ERR_OR_NULL(apb_data->vio)) { + dev_info(dev, "no IO regulator found\n"); + apb_data->vio = NULL; + } + + apb_data->pinctrl = devm_pinctrl_get(dev); + if (IS_ERR(apb_data->pinctrl)) { + dev_err(dev, "could not get pinctrl handle\n"); + return PTR_ERR(apb_data->pinctrl); + } + apb_data->pin_default = pinctrl_lookup_state(apb_data->pinctrl, "default"); + if (IS_ERR(apb_data->pin_default)) { + dev_err(dev, "could not get default pin state\n"); + return PTR_ERR(apb_data->pin_default); + } + + return 0; +} + +static int apb_ctrl_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct apb_ctrl_drvdata *apb_data; + int ret; + + apb_data = devm_kzalloc(&pdev->dev, sizeof(*apb_data), GFP_KERNEL); + if (!apb_data) + return -ENOMEM; + + ret = apb_ctrl_get_devtree_data(dev, apb_data); + if (ret) { + dev_err(dev, "failed to get devicetree data %d\n", ret); + return ret; + } + + ret = apb_ctrl_init_seq(dev, apb_data); + if (ret) { + dev_err(dev, "failed to set init state of control signal %d\n", + ret); + goto exit; + } + + platform_set_drvdata(pdev, apb_data); + + apb_data->state = APB_STATE_OFF; + /* + * Assert AP module detect signal by pulling wake_detect low + */ + deassert_wake(apb_data->ctrl.wake_detect); + + /* + * In order to receive an interrupt, the GPIO must be set to input mode + * + * As per WDM spec, for the cold boot, the wake pulse must be + * >= 5000 usec, but at this stage it is power up sequence, + * so we always treat it as cold boot. + */ + gpio_direction_input(apb_data->ctrl.wake_detect); + + ret = devm_request_irq(dev, gpio_to_irq(apb_data->ctrl.wake_detect), + apb_ctrl_wake_detect_irq, + IRQF_TRIGGER_RISING, + "wake detect", apb_data); + if (ret) { + dev_err(&pdev->dev, "failed to request wake detect IRQ\n"); + goto exit; + } + + /* + * Interrupt handling for WAKE_IN (from bridge) signal is required + * + * Assumption here is, AP already would have woken up and in the + * WAKE_IN/WAKE_FRAME event from bridge, as AP would pass-through event + * to SVC. + * + * Not sure anything else needs to take care here. + */ + dev_err(dev, "Device registered successfully \n"); + return 0; + +exit: + apb_ctrl_cleanup(apb_data); + return ret; +} + +static int apb_ctrl_remove(struct platform_device *pdev) +{ + struct apb_ctrl_drvdata *apb_data = platform_get_drvdata(pdev); + + if (apb_data) + apb_ctrl_cleanup(apb_data); + + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static int apb_ctrl_suspend(struct device *dev) +{ + /* + * If timing profile premits, we may shutdown bridge + * completely + * + * TODO: sequence ?? + * + * Also, need to make sure we meet precondition for unipro suspend + * Precondition: Definition ??? + */ + return 0; +} + +static int apb_ctrl_resume(struct device *dev) +{ + /* + * Atleast for ES2 we have to meet the delay requirement between + * unipro switch and AP bridge init, depending on whether bridge is in + * OFF state or standby state. + * + * Based on whether bridge is in standby or OFF state we may have to + * assert multiple signals. Please refer to WDM spec, for more info. + * + */ + return 0; +} + +static SIMPLE_DEV_PM_OPS(apb_ctrl_pm_ops, apb_ctrl_suspend, apb_ctrl_resume); + +static struct of_device_id apb_ctrl_of_match[] = { + { .compatible = "usbffff,2", }, + { }, +}; +MODULE_DEVICE_TABLE(of, apb_ctrl_of_match); + +static struct platform_driver apb_ctrl_device_driver = { + .probe = apb_ctrl_probe, + .remove = apb_ctrl_remove, + .driver = { + .name = "unipro-APbridge", + .pm = &apb_ctrl_pm_ops, + .of_match_table = of_match_ptr(apb_ctrl_of_match), + } +}; + +module_platform_driver(apb_ctrl_device_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Vaibhav Hiremath "); +MODULE_DESCRIPTION("AP Bridge Control Driver for DB3 platform"); -- cgit v0.10.2 From 16cd787d2d54a47b1d8575bb96bff4b0edc7000b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 21 Oct 2015 11:51:42 +0200 Subject: greybus: endo: fix use-after-free in error path Fix use-after-free in endo-registration error path by moving the id-release to the device release function. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c index 84d695d..c0dc43f 100644 --- a/drivers/staging/greybus/endo.c +++ b/drivers/staging/greybus/endo.c @@ -113,6 +113,7 @@ static void gb_endo_release(struct device *dev) { struct gb_endo *endo = to_gb_endo(dev); + ida_simple_remove(&greybus_endo_id_map, endo->dev_id); kfree(endo); } @@ -462,7 +463,6 @@ static int gb_endo_register(struct greybus_host_device *hd, dev_err(hd->parent, "failed to add endo device of id 0x%04x\n", endo->id); put_device(&endo->dev); - ida_simple_remove(&greybus_endo_id_map, endo->dev_id); } return retval; @@ -518,7 +518,6 @@ void gb_endo_remove(struct gb_endo *endo) /* remove all modules for this endo */ gb_module_remove_all(endo); - ida_simple_remove(&greybus_endo_id_map, endo->dev_id); device_unregister(&endo->dev); } -- cgit v0.10.2 From 3014712fe1dc26640178319e55f3a80ce42a4775 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 21 Oct 2015 11:51:43 +0200 Subject: greybus: endo: fix device-id allocation During endo registration, a unique device id was allocated but then never used. Instead the default dev_id 0 (due to kzalloc) was used for device-generation and later for id-deallocation. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c index c0dc43f..37d2dec 100644 --- a/drivers/staging/greybus/endo.c +++ b/drivers/staging/greybus/endo.c @@ -438,11 +438,14 @@ static int create_modules(struct gb_endo *endo) static int gb_endo_register(struct greybus_host_device *hd, struct gb_endo *endo) { + int dev_id; int retval; - retval = ida_simple_get(&greybus_endo_id_map, 0, 0, GFP_KERNEL); - if (retval < 0) - return retval; + dev_id = ida_simple_get(&greybus_endo_id_map, 0, 0, GFP_KERNEL); + if (dev_id < 0) + return dev_id; + + endo->dev_id = dev_id; endo->dev.parent = hd->parent; endo->dev.bus = &greybus_bus_type; -- cgit v0.10.2 From 8d1043a30fc23a3f8a95b972beb694dd948bbe45 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 21 Oct 2015 15:26:43 +0530 Subject: greybus: bundle: fix double freeing of bundle structure The bundle will be released by gb_bundle_release() once all references for the bundle are dropped. And so there is no need to free it in the error path specially. Reviewed-by: Johan Hovold Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 5c09bcc..01745f4 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -184,7 +184,6 @@ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, pr_err("failed to add bundle device for id 0x%02hhx\n", bundle_id); put_device(&bundle->dev); - kfree(bundle); return NULL; } -- cgit v0.10.2 From 63e8a14b1f9107ee2b51205385695be43ca40d5e Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 21 Oct 2015 15:26:44 +0530 Subject: greybus: interface: fix double freeing of interface structure The interface will be released by gb_interface_release() once all references for the interface are dropped. And so there is no need to free it in the error path specially. Reviewed-by: Johan Hovold Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 64bf91a..5d238d3 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -167,7 +167,6 @@ struct gb_interface *gb_interface_create(struct greybus_host_device *hd, free_intf: put_device(&intf->dev); - kfree(intf); put_module: put_device(&module->dev); return NULL; -- cgit v0.10.2 From f7d3ad9828eba01ed2f5ccc1a12b8b1362ed02b4 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 21 Oct 2015 15:26:45 +0530 Subject: greybus: module: fix double freeing of module structure The module will be released by gb_module_release() once all references for the module are dropped. And so there is no need to free it in the error path specially. Reviewed-by: Johan Hovold Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index d770654..43e8bab 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -151,7 +151,6 @@ struct gb_module *gb_module_create(struct device *parent, u8 module_id) pr_err("failed to add module device for id 0x%02hhx\n", module_id); put_device(&module->dev); - kfree(module); return NULL; } -- cgit v0.10.2 From 92cc1d225282592b19a91604cc23a99013d22802 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 21 Oct 2015 15:42:44 +0530 Subject: greybus: endo: move greybus_endo_setup() to endo.c It belongs to the endo layer and should be placed in endo.c instead. Do it. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 5e1c755..be75456 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -228,20 +228,6 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver } EXPORT_SYMBOL_GPL(greybus_create_hd); -int greybus_endo_setup(struct greybus_host_device *hd, u16 endo_id, - u8 ap_intf_id) -{ - struct gb_endo *endo; - - endo = gb_endo_create(hd, endo_id, ap_intf_id); - if (IS_ERR(endo)) - return PTR_ERR(endo); - hd->endo = endo; - - return 0; -} -EXPORT_SYMBOL_GPL(greybus_endo_setup); - void greybus_remove_hd(struct greybus_host_device *hd) { /* diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c index 37d2dec..726b1d3 100644 --- a/drivers/staging/greybus/endo.c +++ b/drivers/staging/greybus/endo.c @@ -524,6 +524,20 @@ void gb_endo_remove(struct gb_endo *endo) device_unregister(&endo->dev); } +int greybus_endo_setup(struct greybus_host_device *hd, u16 endo_id, + u8 ap_intf_id) +{ + struct gb_endo *endo; + + endo = gb_endo_create(hd, endo_id, ap_intf_id); + if (IS_ERR(endo)) + return PTR_ERR(endo); + hd->endo = endo; + + return 0; +} +EXPORT_SYMBOL_GPL(greybus_endo_setup); + int __init gb_endo_init(void) { ida_init(&greybus_endo_id_map); diff --git a/drivers/staging/greybus/endo.h b/drivers/staging/greybus/endo.h index 3622428..0b5384d 100644 --- a/drivers/staging/greybus/endo.h +++ b/drivers/staging/greybus/endo.h @@ -55,6 +55,8 @@ void gb_endo_exit(void); struct gb_endo *gb_endo_create(struct greybus_host_device *hd, u16 endo_id, u8 ap_intf_id); void gb_endo_remove(struct gb_endo *endo); +int greybus_endo_setup(struct greybus_host_device *hd, u16 endo_id, + u8 ap_intf_id); u8 endo_get_module_id(struct gb_endo *endo, u8 interface_id); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index ae59756..524a412 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -113,8 +113,6 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *hd, struct device *parent, size_t buffer_size_max, size_t num_cports); -int greybus_endo_setup(struct greybus_host_device *hd, u16 endo_id, - u8 ap_intf_id); void greybus_remove_hd(struct greybus_host_device *hd); struct greybus_driver { -- cgit v0.10.2 From d934a88d50f92230e48b944c729021fc39c65d98 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 22 Oct 2015 08:58:16 -0500 Subject: greybus: db3-platform: fix code that fetches reset GPIO The code that fetches the reset GPIO for an AP bridge suffers from an apparent copy/paste error. Fix it. Signed-off-by: Alex Elder Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/db3-platform.c b/drivers/staging/greybus/db3-platform.c index 4391348..61048f5 100644 --- a/drivers/staging/greybus/db3-platform.c +++ b/drivers/staging/greybus/db3-platform.c @@ -196,10 +196,10 @@ static int apb_ctrl_get_devtree_data(struct device *dev, } apb_data->ctrl.reset = of_get_named_gpio(np, "reset-gpios", 0); - if (apb_data->ctrl.wake_detect < 0 || + if (apb_data->ctrl.reset < 0 || !gpio_is_valid(apb_data->ctrl.reset)) { - dev_err(dev, "failed to get wake detect gpio\n"); - return apb_data->ctrl.wake_detect; + dev_err(dev, "failed to get reset gpio\n"); + return apb_data->ctrl.reset; } apb_data->ctrl.boot_ret = of_get_named_gpio(np, "boot-ret-gpios", 0); -- cgit v0.10.2 From 863e652e3f0e6fc3794a3cb5fbab1a3a652f349e Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 22 Oct 2015 08:58:17 -0500 Subject: greybus: db3-platform: fix some typos Fix misspelled "mandatory," and use "GPIOs" for the plural form (no apostrophe and capitalized) in comments. Signed-off-by: Alex Elder Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/db3-platform.c b/drivers/staging/greybus/db3-platform.c index 61048f5..4919337 100644 --- a/drivers/staging/greybus/db3-platform.c +++ b/drivers/staging/greybus/db3-platform.c @@ -75,9 +75,9 @@ static irqreturn_t apb_ctrl_wake_detect_irq(int irq, void *devid) /* * TODO: - * Since currently SoC gpio's are being used we are safe here + * Since currently SoC GPIOs are being used we are safe here * But ideally we should create a workqueue and process the control - * signals, especially when we start using GPIO's over slow + * signals, especially when we start using GPIOs over slow * buses like I2C. */ if (!gpio_is_valid(apb_data->ctrl.wake_detect) && @@ -209,7 +209,7 @@ static int apb_ctrl_get_devtree_data(struct device *dev, return apb_data->ctrl.boot_ret; } - /* It's not mandetory to support power management interface */ + /* It's not mandatory to support power management interface */ apb_data->ctrl.pwroff = of_get_named_gpio(np, "pwr-off-gpios", 0); if (apb_data->ctrl.pwroff < 0 || !gpio_is_valid(apb_data->ctrl.pwroff)) -- cgit v0.10.2 From ed8fbc2d5611716413c2e31693256c7156692372 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 22 Oct 2015 20:06:57 +0530 Subject: greybus: db3-platform: Use dev_info for success messages Used dev_err() by mistake, fix it. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/db3-platform.c b/drivers/staging/greybus/db3-platform.c index 4919337..3adc68d 100644 --- a/drivers/staging/greybus/db3-platform.c +++ b/drivers/staging/greybus/db3-platform.c @@ -305,7 +305,7 @@ static int apb_ctrl_probe(struct platform_device *pdev) * * Not sure anything else needs to take care here. */ - dev_err(dev, "Device registered successfully \n"); + dev_info(dev, "Device registered successfully \n"); return 0; exit: -- cgit v0.10.2 From 76be20a2f39d3b08bdf9b653419fbd367920e856 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 22 Oct 2015 13:03:26 -0500 Subject: greybus: db3-platform: get rid of redundant gpio tests In apb_ctrl_get_devtree_data(), the value returned by of_get_named_gpio() has a redundant test for a negative return value. GPIO numbers are non-negative, so this test is redundant--testing gpio_is_valid() is sufficient. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/db3-platform.c b/drivers/staging/greybus/db3-platform.c index 3adc68d..31f27f0 100644 --- a/drivers/staging/greybus/db3-platform.c +++ b/drivers/staging/greybus/db3-platform.c @@ -189,35 +189,30 @@ static int apb_ctrl_get_devtree_data(struct device *dev, /* fetch control signals */ apb_data->ctrl.wake_detect = of_get_named_gpio(np, "wake-detect-gpios", 0); - if (apb_data->ctrl.wake_detect < 0 || - !gpio_is_valid(apb_data->ctrl.wake_detect)) { + if (!gpio_is_valid(apb_data->ctrl.wake_detect)) { dev_err(dev, "failed to get wake detect gpio\n"); return apb_data->ctrl.wake_detect; } apb_data->ctrl.reset = of_get_named_gpio(np, "reset-gpios", 0); - if (apb_data->ctrl.reset < 0 || - !gpio_is_valid(apb_data->ctrl.reset)) { + if (!gpio_is_valid(apb_data->ctrl.reset)) { dev_err(dev, "failed to get reset gpio\n"); return apb_data->ctrl.reset; } apb_data->ctrl.boot_ret = of_get_named_gpio(np, "boot-ret-gpios", 0); - if (apb_data->ctrl.boot_ret < 0 || - !gpio_is_valid(apb_data->ctrl.boot_ret)) { + if (!gpio_is_valid(apb_data->ctrl.boot_ret)) { dev_err(dev, "failed to get boot retention gpio\n"); return apb_data->ctrl.boot_ret; } /* It's not mandatory to support power management interface */ apb_data->ctrl.pwroff = of_get_named_gpio(np, "pwr-off-gpios", 0); - if (apb_data->ctrl.pwroff < 0 || - !gpio_is_valid(apb_data->ctrl.pwroff)) + if (!gpio_is_valid(apb_data->ctrl.pwroff)) dev_info(dev, "failed to get power off gpio\n"); apb_data->ctrl.pwrdn = of_get_named_gpio(np, "pwr-down-gpios", 0); - if (apb_data->ctrl.pwrdn < 0 || - !gpio_is_valid(apb_data->ctrl.pwrdn)) + if (!gpio_is_valid(apb_data->ctrl.pwrdn)) dev_info(dev, "failed to get power down gpio\n"); /* Regulators are optional, as we may have fixed supply coming in */ -- cgit v0.10.2 From 8f0a654f38c8008b7156c6efbb59272ed474930e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 22 Oct 2015 16:40:41 -0700 Subject: greybus: es2: use official USB vendor/device id We now have an officially assigned Google USB device id for the APBridge, so add in support for it in the es2 driver. The old entry can be removed once the firmware has caught up and uses the new number. We should use the version field to determine ES1/ES2/ES3, but that will come later, for now, grab anything with this device id. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index f947983..7b4ff46 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -22,8 +22,8 @@ #define ES1_GBUF_MSG_SIZE_MAX 2048 static const struct usb_device_id id_table[] = { - /* Made up numbers for the SVC USB Bridge in ES2 */ - { USB_DEVICE(0xffff, 0x0002) }, + { USB_DEVICE(0xffff, 0x0002) }, /* Made up number, delete once firmware is fixed to use real number */ + { USB_DEVICE(0x18d1, 0x1eaf) }, { }, }; MODULE_DEVICE_TABLE(usb, id_table); -- cgit v0.10.2 From 4b1d82047ebbb108e9961fffd51f8ccd54459221 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 27 Oct 2015 22:18:37 -0500 Subject: greybus: es2: rename es2 data structures I tried this once before and Greg NAK'd it because at that point the es2 code was nearly identical to the es1 code. This is no longer the case, and we need to diverge further, so I think it's time to go down that path. The ap_dev structure changed significantly for ES2 versus ES1 as of this commit: 667f8d3 es2.c: create dedicated struct for cport_in and cport_out Since the structures are no longer the same, they should not have the same name. This patch renames three data structures so the "1" is replaced with a "2", to reflect the Toshiba AP bridge chip revision we are working with. The structures are: es1_ap_dev -> es2_ap_dev es1_cport_in -> es2_cport_in es1_cport_out -> es2_cport_out It changes names of symbols having this type as well. To finish the job, all references "ES1" (in comments and in symbol names) have been switched to use "ES2" instead. The result is a lot of changes, but they amount to a global search and replace of "es1" with "es2" (and "ES1" with "ES2"), and the result has been compile tested. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 7b4ff46..e51516f 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -18,8 +18,8 @@ #include "connection.h" #include "greybus_trace.h" -/* Memory sizes for the buffers sent to/from the ES1 controller */ -#define ES1_GBUF_MSG_SIZE_MAX 2048 +/* Memory sizes for the buffers sent to/from the ES2 controller */ +#define ES2_GBUF_MSG_SIZE_MAX 2048 static const struct usb_device_id id_table[] = { { USB_DEVICE(0xffff, 0x0002) }, /* Made up number, delete once firmware is fixed to use real number */ @@ -70,7 +70,7 @@ static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); * @urb: array of urbs for the CPort in messages * @buffer: array of buffers for the @cport_in_urb urbs */ -struct es1_cport_in { +struct es2_cport_in { __u8 endpoint; struct urb *urb[NUM_CPORT_IN_URB]; u8 *buffer[NUM_CPORT_IN_URB]; @@ -79,12 +79,12 @@ struct es1_cport_in { /* * @endpoint: bulk out endpoint for CPort data */ -struct es1_cport_out { +struct es2_cport_out { __u8 endpoint; }; /** - * es1_ap_dev - ES1 USB Bridge to AP structure + * es2_ap_dev - ES2 USB Bridge to AP structure * @usb_dev: pointer to the USB device we are. * @usb_intf: pointer to the USB interface we are bound to. * @hd: pointer to our greybus_host_device structure @@ -98,13 +98,13 @@ struct es1_cport_out { * corresponding @cport_out_urb is being cancelled * @cport_out_urb_lock: locks the @cport_out_urb_busy "list" */ -struct es1_ap_dev { +struct es2_ap_dev { struct usb_device *usb_dev; struct usb_interface *usb_intf; struct greybus_host_device *hd; - struct es1_cport_in cport_in[NUM_BULKS]; - struct es1_cport_out cport_out[NUM_BULKS]; + struct es2_cport_in cport_in[NUM_BULKS]; + struct es2_cport_out cport_out[NUM_BULKS]; struct urb *cport_out_urb[NUM_CPORT_OUT_URB]; bool cport_out_urb_busy[NUM_CPORT_OUT_URB]; bool cport_out_urb_cancelled[NUM_CPORT_OUT_URB]; @@ -125,41 +125,41 @@ struct cport_to_ep { __u8 endpoint_out; }; -static inline struct es1_ap_dev *hd_to_es1(struct greybus_host_device *hd) +static inline struct es2_ap_dev *hd_to_es2(struct greybus_host_device *hd) { - return (struct es1_ap_dev *)&hd->hd_priv; + return (struct es2_ap_dev *)&hd->hd_priv; } static void cport_out_callback(struct urb *urb); -static void usb_log_enable(struct es1_ap_dev *es1); -static void usb_log_disable(struct es1_ap_dev *es1); +static void usb_log_enable(struct es2_ap_dev *es2); +static void usb_log_disable(struct es2_ap_dev *es2); /* Get the endpoints pair mapped to the cport */ -static int cport_to_ep_pair(struct es1_ap_dev *es1, u16 cport_id) +static int cport_to_ep_pair(struct es2_ap_dev *es2, u16 cport_id) { - if (cport_id >= es1->hd->num_cports) + if (cport_id >= es2->hd->num_cports) return 0; - return es1->cport_to_ep[cport_id]; + return es2->cport_to_ep[cport_id]; } -#define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ +#define ES2_TIMEOUT 500 /* 500 ms for the SVC to do something */ /* Disable for now until we work all of this out to keep a warning-free build */ #if 0 /* Test if the endpoints pair is already mapped to a cport */ -static int ep_pair_in_use(struct es1_ap_dev *es1, int ep_pair) +static int ep_pair_in_use(struct es2_ap_dev *es2, int ep_pair) { int i; - for (i = 0; i < es1->hd->num_cports; i++) { - if (es1->cport_to_ep[i] == ep_pair) + for (i = 0; i < es2->hd->num_cports; i++) { + if (es2->cport_to_ep[i] == ep_pair) return 1; } return 0; } /* Configure the endpoint mapping and send the request to APBridge */ -static int map_cport_to_ep(struct es1_ap_dev *es1, +static int map_cport_to_ep(struct es2_ap_dev *es2, u16 cport_id, int ep_pair) { int retval; @@ -167,28 +167,28 @@ static int map_cport_to_ep(struct es1_ap_dev *es1, if (ep_pair < 0 || ep_pair >= NUM_BULKS) return -EINVAL; - if (cport_id >= es1->hd->num_cports) + if (cport_id >= es2->hd->num_cports) return -EINVAL; - if (ep_pair && ep_pair_in_use(es1, ep_pair)) + if (ep_pair && ep_pair_in_use(es2, ep_pair)) return -EINVAL; cport_to_ep = kmalloc(sizeof(*cport_to_ep), GFP_KERNEL); if (!cport_to_ep) return -ENOMEM; - es1->cport_to_ep[cport_id] = ep_pair; + es2->cport_to_ep[cport_id] = ep_pair; cport_to_ep->cport_id = cpu_to_le16(cport_id); - cport_to_ep->endpoint_in = es1->cport_in[ep_pair].endpoint; - cport_to_ep->endpoint_out = es1->cport_out[ep_pair].endpoint; + cport_to_ep->endpoint_in = es2->cport_in[ep_pair].endpoint; + cport_to_ep->endpoint_out = es2->cport_out[ep_pair].endpoint; - retval = usb_control_msg(es1->usb_dev, - usb_sndctrlpipe(es1->usb_dev, 0), + retval = usb_control_msg(es2->usb_dev, + usb_sndctrlpipe(es2->usb_dev, 0), REQUEST_EP_MAPPING, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0x00, 0x00, (char *)cport_to_ep, sizeof(*cport_to_ep), - ES1_TIMEOUT); + ES2_TIMEOUT); if (retval == sizeof(*cport_to_ep)) retval = 0; kfree(cport_to_ep); @@ -197,30 +197,30 @@ static int map_cport_to_ep(struct es1_ap_dev *es1, } /* Unmap a cport: use the muxed endpoints pair */ -static int unmap_cport(struct es1_ap_dev *es1, u16 cport_id) +static int unmap_cport(struct es2_ap_dev *es2, u16 cport_id) { - return map_cport_to_ep(es1, cport_id, 0); + return map_cport_to_ep(es2, cport_id, 0); } #endif -static struct urb *next_free_urb(struct es1_ap_dev *es1, gfp_t gfp_mask) +static struct urb *next_free_urb(struct es2_ap_dev *es2, gfp_t gfp_mask) { struct urb *urb = NULL; unsigned long flags; int i; - spin_lock_irqsave(&es1->cport_out_urb_lock, flags); + spin_lock_irqsave(&es2->cport_out_urb_lock, flags); /* Look in our pool of allocated urbs first, as that's the "fastest" */ for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - if (es1->cport_out_urb_busy[i] == false && - es1->cport_out_urb_cancelled[i] == false) { - es1->cport_out_urb_busy[i] = true; - urb = es1->cport_out_urb[i]; + if (es2->cport_out_urb_busy[i] == false && + es2->cport_out_urb_cancelled[i] == false) { + es2->cport_out_urb_busy[i] = true; + urb = es2->cport_out_urb[i]; break; } } - spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); + spin_unlock_irqrestore(&es2->cport_out_urb_lock, flags); if (urb) return urb; @@ -228,12 +228,12 @@ static struct urb *next_free_urb(struct es1_ap_dev *es1, gfp_t gfp_mask) * Crap, pool is empty, complain to the syslog and go allocate one * dynamically as we have to succeed. */ - dev_err(&es1->usb_dev->dev, + dev_err(&es2->usb_dev->dev, "No free CPort OUT urbs, having to dynamically allocate one!\n"); return usb_alloc_urb(0, gfp_mask); } -static void free_urb(struct es1_ap_dev *es1, struct urb *urb) +static void free_urb(struct es2_ap_dev *es2, struct urb *urb) { unsigned long flags; int i; @@ -241,15 +241,15 @@ static void free_urb(struct es1_ap_dev *es1, struct urb *urb) * See if this was an urb in our pool, if so mark it "free", otherwise * we need to free it ourselves. */ - spin_lock_irqsave(&es1->cport_out_urb_lock, flags); + spin_lock_irqsave(&es2->cport_out_urb_lock, flags); for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - if (urb == es1->cport_out_urb[i]) { - es1->cport_out_urb_busy[i] = false; + if (urb == es2->cport_out_urb[i]) { + es2->cport_out_urb_busy[i] = false; urb = NULL; break; } } - spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); + spin_unlock_irqrestore(&es2->cport_out_urb_lock, flags); /* If urb is not NULL, then we need to free this urb */ usb_free_urb(urb); @@ -288,8 +288,8 @@ static u16 gb_message_cport_unpack(struct gb_operation_msg_hdr *header) static int message_send(struct greybus_host_device *hd, u16 cport_id, struct gb_message *message, gfp_t gfp_mask) { - struct es1_ap_dev *es1 = hd_to_es1(hd); - struct usb_device *udev = es1->usb_dev; + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct usb_device *udev = es2->usb_dev; size_t buffer_size; int retval; struct urb *urb; @@ -308,23 +308,23 @@ static int message_send(struct greybus_host_device *hd, u16 cport_id, } /* Find a free urb */ - urb = next_free_urb(es1, gfp_mask); + urb = next_free_urb(es2, gfp_mask); if (!urb) return -ENOMEM; - spin_lock_irqsave(&es1->cport_out_urb_lock, flags); + spin_lock_irqsave(&es2->cport_out_urb_lock, flags); message->hcpriv = urb; - spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); + spin_unlock_irqrestore(&es2->cport_out_urb_lock, flags); /* Pack the cport id into the message header */ gb_message_cport_pack(message->header, cport_id); buffer_size = sizeof(*message->header) + message->payload_size; - ep_pair = cport_to_ep_pair(es1, cport_id); + ep_pair = cport_to_ep_pair(es2, cport_id); usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, - es1->cport_out[ep_pair].endpoint), + es2->cport_out[ep_pair].endpoint), message->buffer, buffer_size, cport_out_callback, message); urb->transfer_flags |= URB_ZERO_PACKET; @@ -333,11 +333,11 @@ static int message_send(struct greybus_host_device *hd, u16 cport_id, if (retval) { dev_err(&udev->dev, "failed to submit out-urb: %d\n", retval); - spin_lock_irqsave(&es1->cport_out_urb_lock, flags); + spin_lock_irqsave(&es2->cport_out_urb_lock, flags); message->hcpriv = NULL; - spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); + spin_unlock_irqrestore(&es2->cport_out_urb_lock, flags); - free_urb(es1, urb); + free_urb(es2, urb); gb_message_cport_clear(message->header); return retval; @@ -352,13 +352,13 @@ static int message_send(struct greybus_host_device *hd, u16 cport_id, static void message_cancel(struct gb_message *message) { struct greybus_host_device *hd = message->operation->connection->hd; - struct es1_ap_dev *es1 = hd_to_es1(hd); + struct es2_ap_dev *es2 = hd_to_es2(hd); struct urb *urb; int i; might_sleep(); - spin_lock_irq(&es1->cport_out_urb_lock); + spin_lock_irq(&es2->cport_out_urb_lock); urb = message->hcpriv; /* Prevent dynamically allocated urb from being deallocated. */ @@ -366,19 +366,19 @@ static void message_cancel(struct gb_message *message) /* Prevent pre-allocated urb from being reused. */ for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - if (urb == es1->cport_out_urb[i]) { - es1->cport_out_urb_cancelled[i] = true; + if (urb == es2->cport_out_urb[i]) { + es2->cport_out_urb_cancelled[i] = true; break; } } - spin_unlock_irq(&es1->cport_out_urb_lock); + spin_unlock_irq(&es2->cport_out_urb_lock); usb_kill_urb(urb); if (i < NUM_CPORT_OUT_URB) { - spin_lock_irq(&es1->cport_out_urb_lock); - es1->cport_out_urb_cancelled[i] = false; - spin_unlock_irq(&es1->cport_out_urb_lock); + spin_lock_irq(&es2->cport_out_urb_lock); + es2->cport_out_urb_cancelled[i] = false; + spin_unlock_irq(&es2->cport_out_urb_lock); } usb_free_urb(urb); @@ -386,15 +386,15 @@ static void message_cancel(struct gb_message *message) static int cport_reset(struct greybus_host_device *hd, u16 cport_id) { - struct es1_ap_dev *es1 = hd_to_es1(hd); - struct usb_device *udev = es1->usb_dev; + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct usb_device *udev = es2->usb_dev; int retval; retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), REQUEST_RESET_CPORT, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0, cport_id, - NULL, 0, ES1_TIMEOUT); + NULL, 0, ES2_TIMEOUT); if (retval < 0) { dev_err(&udev->dev, "failed to reset cport %hu: %d\n", cport_id, retval); @@ -420,8 +420,8 @@ static int cport_enable(struct greybus_host_device *hd, u16 cport_id) static int latency_tag_enable(struct greybus_host_device *hd, u16 cport_id) { int retval; - struct es1_ap_dev *es1 = hd_to_es1(hd); - struct usb_device *udev = es1->usb_dev; + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct usb_device *udev = es2->usb_dev; if (!cport_id_valid(hd, cport_id)) { dev_err(&udev->dev, "invalid destination cport 0x%02x\n", @@ -433,7 +433,7 @@ static int latency_tag_enable(struct greybus_host_device *hd, u16 cport_id) REQUEST_LATENCY_TAG_EN, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, cport_id, 0, NULL, - 0, ES1_TIMEOUT); + 0, ES2_TIMEOUT); if (retval < 0) dev_err(&udev->dev, "Cannot enable latency tag for cport %d\n", @@ -444,8 +444,8 @@ static int latency_tag_enable(struct greybus_host_device *hd, u16 cport_id) static int latency_tag_disable(struct greybus_host_device *hd, u16 cport_id) { int retval; - struct es1_ap_dev *es1 = hd_to_es1(hd); - struct usb_device *udev = es1->usb_dev; + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct usb_device *udev = es2->usb_dev; if (!cport_id_valid(hd, cport_id)) { dev_err(&udev->dev, "invalid destination cport 0x%02x\n", @@ -457,7 +457,7 @@ static int latency_tag_disable(struct greybus_host_device *hd, u16 cport_id) REQUEST_LATENCY_TAG_DIS, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, cport_id, 0, NULL, - 0, ES1_TIMEOUT); + 0, ES2_TIMEOUT); if (retval < 0) dev_err(&udev->dev, "Cannot disable latency tag for cport %d\n", @@ -465,8 +465,8 @@ static int latency_tag_disable(struct greybus_host_device *hd, u16 cport_id) return retval; } -static struct greybus_host_driver es1_driver = { - .hd_priv_size = sizeof(struct es1_ap_dev), +static struct greybus_host_driver es2_driver = { + .hd_priv_size = sizeof(struct es2_ap_dev), .message_send = message_send, .message_cancel = message_cancel, .cport_enable = cport_enable, @@ -502,31 +502,32 @@ static int check_urb_status(struct urb *urb) static void ap_disconnect(struct usb_interface *interface) { - struct es1_ap_dev *es1; + struct es2_ap_dev *es2; struct usb_device *udev; int bulk_in; int i; - es1 = usb_get_intfdata(interface); - if (!es1) + es2 = usb_get_intfdata(interface); + if (!es2) return; - usb_log_disable(es1); + usb_log_disable(es2); /* Tear down everything! */ for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - struct urb *urb = es1->cport_out_urb[i]; + struct urb *urb = es2->cport_out_urb[i]; if (!urb) break; usb_kill_urb(urb); usb_free_urb(urb); - es1->cport_out_urb[i] = NULL; - es1->cport_out_urb_busy[i] = false; /* just to be anal */ + es2->cport_out_urb[i] = NULL; + es2->cport_out_urb_busy[i] = false; /* just to be anal */ } for (bulk_in = 0; bulk_in < NUM_BULKS; bulk_in++) { - struct es1_cport_in *cport_in = &es1->cport_in[bulk_in]; + struct es2_cport_in *cport_in = &es2->cport_in[bulk_in]; + for (i = 0; i < NUM_CPORT_IN_URB; ++i) { struct urb *urb = cport_in->urb[i]; @@ -540,9 +541,9 @@ static void ap_disconnect(struct usb_interface *interface) } usb_set_intfdata(interface, NULL); - udev = es1->usb_dev; - greybus_remove_hd(es1->hd); - kfree(es1->cport_to_ep); + udev = es2->usb_dev; + greybus_remove_hd(es2->hd); + kfree(es2->cport_to_ep); usb_put_dev(udev); } @@ -590,15 +591,15 @@ static void cport_out_callback(struct urb *urb) { struct gb_message *message = urb->context; struct greybus_host_device *hd = message->operation->connection->hd; - struct es1_ap_dev *es1 = hd_to_es1(hd); + struct es2_ap_dev *es2 = hd_to_es2(hd); int status = check_urb_status(urb); unsigned long flags; gb_message_cport_clear(message->header); - spin_lock_irqsave(&es1->cport_out_urb_lock, flags); + spin_lock_irqsave(&es2->cport_out_urb_lock, flags); message->hcpriv = NULL; - spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); + spin_unlock_irqrestore(&es2->cport_out_urb_lock, flags); /* * Tell the submitter that the message send (attempt) is @@ -606,24 +607,24 @@ static void cport_out_callback(struct urb *urb) */ greybus_message_sent(hd, message, status); - free_urb(es1, urb); + free_urb(es2, urb); } #define APB1_LOG_MSG_SIZE 64 -static void apb1_log_get(struct es1_ap_dev *es1, char *buf) +static void apb1_log_get(struct es2_ap_dev *es2, char *buf) { int retval; /* SVC messages go down our control pipe */ do { - retval = usb_control_msg(es1->usb_dev, - usb_rcvctrlpipe(es1->usb_dev, 0), + retval = usb_control_msg(es2->usb_dev, + usb_rcvctrlpipe(es2->usb_dev, 0), REQUEST_LOG, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0x00, 0x00, buf, APB1_LOG_MSG_SIZE, - ES1_TIMEOUT); + ES2_TIMEOUT); if (retval > 0) kfifo_in(&apb1_log_fifo, buf, retval); } while (retval > 0); @@ -631,7 +632,7 @@ static void apb1_log_get(struct es1_ap_dev *es1, char *buf) static int apb1_log_poll(void *data) { - struct es1_ap_dev *es1 = data; + struct es2_ap_dev *es2 = data; char *buf; buf = kmalloc(APB1_LOG_MSG_SIZE, GFP_KERNEL); @@ -640,7 +641,7 @@ static int apb1_log_poll(void *data) while (!kthread_should_stop()) { msleep(1000); - apb1_log_get(es1, buf); + apb1_log_get(es2, buf); } kfree(buf); @@ -674,13 +675,13 @@ static const struct file_operations apb1_log_fops = { .read = apb1_log_read, }; -static void usb_log_enable(struct es1_ap_dev *es1) +static void usb_log_enable(struct es2_ap_dev *es2) { if (!IS_ERR_OR_NULL(apb1_log_task)) return; /* get log from APB1 */ - apb1_log_task = kthread_run(apb1_log_poll, es1, "apb1_log"); + apb1_log_task = kthread_run(apb1_log_poll, es2, "apb1_log"); if (IS_ERR(apb1_log_task)) return; apb1_log_dentry = debugfs_create_file("apb1_log", S_IRUGO, @@ -688,7 +689,7 @@ static void usb_log_enable(struct es1_ap_dev *es1) &apb1_log_fops); } -static void usb_log_disable(struct es1_ap_dev *es1) +static void usb_log_disable(struct es2_ap_dev *es2) { if (IS_ERR_OR_NULL(apb1_log_task)) return; @@ -703,8 +704,8 @@ static void usb_log_disable(struct es1_ap_dev *es1) static ssize_t apb1_log_enable_read(struct file *f, char __user *buf, size_t count, loff_t *ppos) { - char tmp_buf[3]; int enable = !IS_ERR_OR_NULL(apb1_log_task); + char tmp_buf[3]; sprintf(tmp_buf, "%d\n", enable); return simple_read_from_buffer(buf, count, ppos, tmp_buf, 3); @@ -715,16 +716,16 @@ static ssize_t apb1_log_enable_write(struct file *f, const char __user *buf, { int enable; ssize_t retval; - struct es1_ap_dev *es1 = (struct es1_ap_dev *)f->f_inode->i_private; + struct es2_ap_dev *es2 = (struct es2_ap_dev *)f->f_inode->i_private; retval = kstrtoint_from_user(buf, count, 10, &enable); if (retval) return retval; if (enable) - usb_log_enable(es1); + usb_log_enable(es2); else - usb_log_disable(es1); + usb_log_disable(es2); return count; } @@ -747,7 +748,7 @@ static int apb1_get_cport_count(struct usb_device *udev) REQUEST_CPORT_COUNT, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0, 0, cport_count, - sizeof(*cport_count), ES1_TIMEOUT); + sizeof(*cport_count), ES2_TIMEOUT); if (retval < 0) { dev_err(&udev->dev, "Cannot retrieve CPort count: %d\n", retval); @@ -768,7 +769,7 @@ out: } /* - * The ES1 USB Bridge device contains 4 endpoints + * The ES2 USB Bridge device contains 4 endpoints * 1 Control - usual USB stuff + AP -> SVC messages * 1 Interrupt IN - SVC -> AP messages * 1 Bulk IN - CPort data in @@ -777,7 +778,7 @@ out: static int ap_probe(struct usb_interface *interface, const struct usb_device_id *id) { - struct es1_ap_dev *es1; + struct es2_ap_dev *es2; struct greybus_host_device *hd; struct usb_device *udev; struct usb_host_interface *iface_desc; @@ -798,23 +799,23 @@ static int ap_probe(struct usb_interface *interface, return num_cports; } - hd = greybus_create_hd(&es1_driver, &udev->dev, ES1_GBUF_MSG_SIZE_MAX, + hd = greybus_create_hd(&es2_driver, &udev->dev, ES2_GBUF_MSG_SIZE_MAX, num_cports); if (IS_ERR(hd)) { usb_put_dev(udev); return PTR_ERR(hd); } - es1 = hd_to_es1(hd); - es1->hd = hd; - es1->usb_intf = interface; - es1->usb_dev = udev; - spin_lock_init(&es1->cport_out_urb_lock); - usb_set_intfdata(interface, es1); + es2 = hd_to_es2(hd); + es2->hd = hd; + es2->usb_intf = interface; + es2->usb_dev = udev; + spin_lock_init(&es2->cport_out_urb_lock); + usb_set_intfdata(interface, es2); - es1->cport_to_ep = kcalloc(hd->num_cports, sizeof(*es1->cport_to_ep), + es2->cport_to_ep = kcalloc(hd->num_cports, sizeof(*es2->cport_to_ep), GFP_KERNEL); - if (!es1->cport_to_ep) { + if (!es2->cport_to_ep) { retval = -ENOMEM; goto error; } @@ -825,10 +826,10 @@ static int ap_probe(struct usb_interface *interface, endpoint = &iface_desc->endpoint[i].desc; if (usb_endpoint_is_bulk_in(endpoint)) { - es1->cport_in[bulk_in++].endpoint = + es2->cport_in[bulk_in++].endpoint = endpoint->bEndpointAddress; } else if (usb_endpoint_is_bulk_out(endpoint)) { - es1->cport_out[bulk_out++].endpoint = + es2->cport_out[bulk_out++].endpoint = endpoint->bEndpointAddress; } else { dev_err(&udev->dev, @@ -844,7 +845,8 @@ static int ap_probe(struct usb_interface *interface, /* Allocate buffers for our cport in messages and start them up */ for (bulk_in = 0; bulk_in < NUM_BULKS; bulk_in++) { - struct es1_cport_in *cport_in = &es1->cport_in[bulk_in]; + struct es2_cport_in *cport_in = &es2->cport_in[bulk_in]; + for (i = 0; i < NUM_CPORT_IN_URB; ++i) { struct urb *urb; u8 *buffer; @@ -852,14 +854,14 @@ static int ap_probe(struct usb_interface *interface, urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) goto error; - buffer = kmalloc(ES1_GBUF_MSG_SIZE_MAX, GFP_KERNEL); + buffer = kmalloc(ES2_GBUF_MSG_SIZE_MAX, GFP_KERNEL); if (!buffer) goto error; usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, cport_in->endpoint), - buffer, ES1_GBUF_MSG_SIZE_MAX, + buffer, ES2_GBUF_MSG_SIZE_MAX, cport_in_callback, hd); cport_in->urb[i] = urb; cport_in->buffer[i] = buffer; @@ -877,13 +879,13 @@ static int ap_probe(struct usb_interface *interface, if (!urb) goto error; - es1->cport_out_urb[i] = urb; - es1->cport_out_urb_busy[i] = false; /* just to be anal */ + es2->cport_out_urb[i] = urb; + es2->cport_out_urb_busy[i] = false; /* just to be anal */ } apb1_log_enable_dentry = debugfs_create_file("apb1_log_enable", (S_IWUSR | S_IRUGO), - gb_debugfs_get(), es1, + gb_debugfs_get(), es2, &apb1_log_enable_fops); return 0; error: @@ -892,14 +894,14 @@ error: return retval; } -static struct usb_driver es1_ap_driver = { +static struct usb_driver es2_ap_driver = { .name = "es2_ap_driver", .probe = ap_probe, .disconnect = ap_disconnect, .id_table = id_table, }; -module_usb_driver(es1_ap_driver); +module_usb_driver(es2_ap_driver); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Greg Kroah-Hartman "); -- cgit v0.10.2 From 1482b3e1a8ab924cca4dc7e2ac9f40c0e9ff37c9 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 27 Oct 2015 22:18:38 -0500 Subject: greybus: es2: move APB log task into the es2_ap_dev struct If an APB has a logging task it is associated with that APB. Move the task pointer into the es2_ap_dev structure rather than having it be a single global. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index e51516f..a4b54d3 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -31,7 +31,6 @@ MODULE_DEVICE_TABLE(usb, id_table); #define APB1_LOG_SIZE SZ_16K static struct dentry *apb1_log_dentry; static struct dentry *apb1_log_enable_dentry; -static struct task_struct *apb1_log_task; static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); /* Number of bulk in and bulk out couple */ @@ -97,6 +96,8 @@ struct es2_cport_out { * @cport_out_urb_cancelled: array of flags indicating whether the * corresponding @cport_out_urb is being cancelled * @cport_out_urb_lock: locks the @cport_out_urb_busy "list" + * + * @apb1_log_task: task pointer for logging thread */ struct es2_ap_dev { struct usb_device *usb_dev; @@ -111,6 +112,8 @@ struct es2_ap_dev { spinlock_t cport_out_urb_lock; int *cport_to_ep; + + struct task_struct *apb1_log_task; }; /** @@ -677,12 +680,12 @@ static const struct file_operations apb1_log_fops = { static void usb_log_enable(struct es2_ap_dev *es2) { - if (!IS_ERR_OR_NULL(apb1_log_task)) + if (!IS_ERR_OR_NULL(es2->apb1_log_task)) return; /* get log from APB1 */ - apb1_log_task = kthread_run(apb1_log_poll, es2, "apb1_log"); - if (IS_ERR(apb1_log_task)) + es2->apb1_log_task = kthread_run(apb1_log_poll, es2, "apb1_log"); + if (IS_ERR(es2->apb1_log_task)) return; apb1_log_dentry = debugfs_create_file("apb1_log", S_IRUGO, gb_debugfs_get(), NULL, @@ -691,20 +694,21 @@ static void usb_log_enable(struct es2_ap_dev *es2) static void usb_log_disable(struct es2_ap_dev *es2) { - if (IS_ERR_OR_NULL(apb1_log_task)) + if (IS_ERR_OR_NULL(es2->apb1_log_task)) return; debugfs_remove(apb1_log_dentry); apb1_log_dentry = NULL; - kthread_stop(apb1_log_task); - apb1_log_task = NULL; + kthread_stop(es2->apb1_log_task); + es2->apb1_log_task = NULL; } static ssize_t apb1_log_enable_read(struct file *f, char __user *buf, size_t count, loff_t *ppos) { - int enable = !IS_ERR_OR_NULL(apb1_log_task); + struct es2_ap_dev *es2 = f->f_inode->i_private; + int enable = !IS_ERR_OR_NULL(es2->apb1_log_task); char tmp_buf[3]; sprintf(tmp_buf, "%d\n", enable); @@ -716,7 +720,7 @@ static ssize_t apb1_log_enable_write(struct file *f, const char __user *buf, { int enable; ssize_t retval; - struct es2_ap_dev *es2 = (struct es2_ap_dev *)f->f_inode->i_private; + struct es2_ap_dev *es2 = f->f_inode->i_private; retval = kstrtoint_from_user(buf, count, 10, &enable); if (retval) -- cgit v0.10.2 From 8995a39d6d030b48633c9a2ed85d3244907acff0 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 27 Oct 2015 22:18:39 -0500 Subject: greybus: es2: move logging fifo into es2 struct Continue moving the logging data structures into the es2 AP data structure rather than having it be a single global. This patch moves the fifo. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index a4b54d3..3de5ba19 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -31,7 +31,6 @@ MODULE_DEVICE_TABLE(usb, id_table); #define APB1_LOG_SIZE SZ_16K static struct dentry *apb1_log_dentry; static struct dentry *apb1_log_enable_dentry; -static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); /* Number of bulk in and bulk out couple */ #define NUM_BULKS 7 @@ -98,6 +97,7 @@ struct es2_cport_out { * @cport_out_urb_lock: locks the @cport_out_urb_busy "list" * * @apb1_log_task: task pointer for logging thread + * @apb1_log_fifo: kernel FIFO to carry logged data */ struct es2_ap_dev { struct usb_device *usb_dev; @@ -114,6 +114,7 @@ struct es2_ap_dev { int *cport_to_ep; struct task_struct *apb1_log_task; + DECLARE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); }; /** @@ -629,7 +630,7 @@ static void apb1_log_get(struct es2_ap_dev *es2, char *buf) APB1_LOG_MSG_SIZE, ES2_TIMEOUT); if (retval > 0) - kfifo_in(&apb1_log_fifo, buf, retval); + kfifo_in(&es2->apb1_log_fifo, buf, retval); } while (retval > 0); } @@ -655,6 +656,7 @@ static int apb1_log_poll(void *data) static ssize_t apb1_log_read(struct file *f, char __user *buf, size_t count, loff_t *ppos) { + struct es2_ap_dev *es2 = f->f_inode->i_private; ssize_t ret; size_t copied; char *tmp_buf; @@ -666,7 +668,7 @@ static ssize_t apb1_log_read(struct file *f, char __user *buf, if (!tmp_buf) return -ENOMEM; - copied = kfifo_out(&apb1_log_fifo, tmp_buf, count); + copied = kfifo_out(&es2->apb1_log_fifo, tmp_buf, count); ret = simple_read_from_buffer(buf, count, ppos, tmp_buf, copied); kfree(tmp_buf); @@ -815,6 +817,7 @@ static int ap_probe(struct usb_interface *interface, es2->usb_intf = interface; es2->usb_dev = udev; spin_lock_init(&es2->cport_out_urb_lock); + INIT_KFIFO(es2->apb1_log_fifo); usb_set_intfdata(interface, es2); es2->cport_to_ep = kcalloc(hd->num_cports, sizeof(*es2->cport_to_ep), -- cgit v0.10.2 From cbec7e2919f04d3d1abea1cde93a8052e2e8ef04 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 27 Oct 2015 22:18:40 -0500 Subject: greybus: es2: move logging dentries into es2 struct Finish moving the logging data structures into the es2 AP data structure rather than having it be a single global. This patch moves the two dentries related to logging. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 3de5ba19..fc3930f 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -29,8 +29,6 @@ static const struct usb_device_id id_table[] = { MODULE_DEVICE_TABLE(usb, id_table); #define APB1_LOG_SIZE SZ_16K -static struct dentry *apb1_log_dentry; -static struct dentry *apb1_log_enable_dentry; /* Number of bulk in and bulk out couple */ #define NUM_BULKS 7 @@ -97,6 +95,8 @@ struct es2_cport_out { * @cport_out_urb_lock: locks the @cport_out_urb_busy "list" * * @apb1_log_task: task pointer for logging thread + * @apb1_log_dentry: file system entry for the log file interface + * @apb1_log_enable_dentry: file system entry for enabling logging * @apb1_log_fifo: kernel FIFO to carry logged data */ struct es2_ap_dev { @@ -114,6 +114,8 @@ struct es2_ap_dev { int *cport_to_ep; struct task_struct *apb1_log_task; + struct dentry *apb1_log_dentry; + struct dentry *apb1_log_enable_dentry; DECLARE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); }; @@ -689,7 +691,7 @@ static void usb_log_enable(struct es2_ap_dev *es2) es2->apb1_log_task = kthread_run(apb1_log_poll, es2, "apb1_log"); if (IS_ERR(es2->apb1_log_task)) return; - apb1_log_dentry = debugfs_create_file("apb1_log", S_IRUGO, + es2->apb1_log_dentry = debugfs_create_file("apb1_log", S_IRUGO, gb_debugfs_get(), NULL, &apb1_log_fops); } @@ -699,8 +701,8 @@ static void usb_log_disable(struct es2_ap_dev *es2) if (IS_ERR_OR_NULL(es2->apb1_log_task)) return; - debugfs_remove(apb1_log_dentry); - apb1_log_dentry = NULL; + debugfs_remove(es2->apb1_log_dentry); + es2->apb1_log_dentry = NULL; kthread_stop(es2->apb1_log_task); es2->apb1_log_task = NULL; @@ -890,7 +892,7 @@ static int ap_probe(struct usb_interface *interface, es2->cport_out_urb_busy[i] = false; /* just to be anal */ } - apb1_log_enable_dentry = debugfs_create_file("apb1_log_enable", + es2->apb1_log_enable_dentry = debugfs_create_file("apb1_log_enable", (S_IWUSR | S_IRUGO), gb_debugfs_get(), es2, &apb1_log_enable_fops); -- cgit v0.10.2 From 3be0e17d62d5a9b14d764935b2b2de9c8d6b379a Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 27 Oct 2015 22:18:41 -0500 Subject: greybus: es2: don't assume just one AP bridge Previously we had only one AP bridge connected to the AP. We will now have two. Now that the have moved the logging related symbols into the AP device, we can stop assuming there's only on of them. Specifically, rename symbols like "apb1_*" to be just "apb_*", because the "1" is no longer meaningful. Signed-off-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index fc3930f..b43435f 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -94,10 +94,10 @@ struct es2_cport_out { * corresponding @cport_out_urb is being cancelled * @cport_out_urb_lock: locks the @cport_out_urb_busy "list" * - * @apb1_log_task: task pointer for logging thread - * @apb1_log_dentry: file system entry for the log file interface - * @apb1_log_enable_dentry: file system entry for enabling logging - * @apb1_log_fifo: kernel FIFO to carry logged data + * @apb_log_task: task pointer for logging thread + * @apb_log_dentry: file system entry for the log file interface + * @apb_log_enable_dentry: file system entry for enabling logging + * @apb_log_fifo: kernel FIFO to carry logged data */ struct es2_ap_dev { struct usb_device *usb_dev; @@ -113,10 +113,10 @@ struct es2_ap_dev { int *cport_to_ep; - struct task_struct *apb1_log_task; - struct dentry *apb1_log_dentry; - struct dentry *apb1_log_enable_dentry; - DECLARE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); + struct task_struct *apb_log_task; + struct dentry *apb_log_dentry; + struct dentry *apb_log_enable_dentry; + DECLARE_KFIFO(apb_log_fifo, char, APB1_LOG_SIZE); }; /** @@ -617,7 +617,7 @@ static void cport_out_callback(struct urb *urb) } #define APB1_LOG_MSG_SIZE 64 -static void apb1_log_get(struct es2_ap_dev *es2, char *buf) +static void apb_log_get(struct es2_ap_dev *es2, char *buf) { int retval; @@ -632,11 +632,11 @@ static void apb1_log_get(struct es2_ap_dev *es2, char *buf) APB1_LOG_MSG_SIZE, ES2_TIMEOUT); if (retval > 0) - kfifo_in(&es2->apb1_log_fifo, buf, retval); + kfifo_in(&es2->apb_log_fifo, buf, retval); } while (retval > 0); } -static int apb1_log_poll(void *data) +static int apb_log_poll(void *data) { struct es2_ap_dev *es2 = data; char *buf; @@ -647,7 +647,7 @@ static int apb1_log_poll(void *data) while (!kthread_should_stop()) { msleep(1000); - apb1_log_get(es2, buf); + apb_log_get(es2, buf); } kfree(buf); @@ -655,7 +655,7 @@ static int apb1_log_poll(void *data) return 0; } -static ssize_t apb1_log_read(struct file *f, char __user *buf, +static ssize_t apb_log_read(struct file *f, char __user *buf, size_t count, loff_t *ppos) { struct es2_ap_dev *es2 = f->f_inode->i_private; @@ -670,7 +670,7 @@ static ssize_t apb1_log_read(struct file *f, char __user *buf, if (!tmp_buf) return -ENOMEM; - copied = kfifo_out(&es2->apb1_log_fifo, tmp_buf, count); + copied = kfifo_out(&es2->apb_log_fifo, tmp_buf, count); ret = simple_read_from_buffer(buf, count, ppos, tmp_buf, copied); kfree(tmp_buf); @@ -678,48 +678,49 @@ static ssize_t apb1_log_read(struct file *f, char __user *buf, return ret; } -static const struct file_operations apb1_log_fops = { - .read = apb1_log_read, +static const struct file_operations apb_log_fops = { + .read = apb_log_read, }; static void usb_log_enable(struct es2_ap_dev *es2) { - if (!IS_ERR_OR_NULL(es2->apb1_log_task)) + if (!IS_ERR_OR_NULL(es2->apb_log_task)) return; /* get log from APB1 */ - es2->apb1_log_task = kthread_run(apb1_log_poll, es2, "apb1_log"); - if (IS_ERR(es2->apb1_log_task)) + es2->apb_log_task = kthread_run(apb_log_poll, es2, "apb_log"); + if (IS_ERR(es2->apb_log_task)) return; - es2->apb1_log_dentry = debugfs_create_file("apb1_log", S_IRUGO, + /* XXX We will need to rename this per APB */ + es2->apb_log_dentry = debugfs_create_file("apb_log", S_IRUGO, gb_debugfs_get(), NULL, - &apb1_log_fops); + &apb_log_fops); } static void usb_log_disable(struct es2_ap_dev *es2) { - if (IS_ERR_OR_NULL(es2->apb1_log_task)) + if (IS_ERR_OR_NULL(es2->apb_log_task)) return; - debugfs_remove(es2->apb1_log_dentry); - es2->apb1_log_dentry = NULL; + debugfs_remove(es2->apb_log_dentry); + es2->apb_log_dentry = NULL; - kthread_stop(es2->apb1_log_task); - es2->apb1_log_task = NULL; + kthread_stop(es2->apb_log_task); + es2->apb_log_task = NULL; } -static ssize_t apb1_log_enable_read(struct file *f, char __user *buf, +static ssize_t apb_log_enable_read(struct file *f, char __user *buf, size_t count, loff_t *ppos) { struct es2_ap_dev *es2 = f->f_inode->i_private; - int enable = !IS_ERR_OR_NULL(es2->apb1_log_task); + int enable = !IS_ERR_OR_NULL(es2->apb_log_task); char tmp_buf[3]; sprintf(tmp_buf, "%d\n", enable); return simple_read_from_buffer(buf, count, ppos, tmp_buf, 3); } -static ssize_t apb1_log_enable_write(struct file *f, const char __user *buf, +static ssize_t apb_log_enable_write(struct file *f, const char __user *buf, size_t count, loff_t *ppos) { int enable; @@ -738,12 +739,12 @@ static ssize_t apb1_log_enable_write(struct file *f, const char __user *buf, return count; } -static const struct file_operations apb1_log_enable_fops = { - .read = apb1_log_enable_read, - .write = apb1_log_enable_write, +static const struct file_operations apb_log_enable_fops = { + .read = apb_log_enable_read, + .write = apb_log_enable_write, }; -static int apb1_get_cport_count(struct usb_device *udev) +static int apb_get_cport_count(struct usb_device *udev) { int retval; __le16 *cport_count; @@ -799,7 +800,7 @@ static int ap_probe(struct usb_interface *interface, udev = usb_get_dev(interface_to_usbdev(interface)); - num_cports = apb1_get_cport_count(udev); + num_cports = apb_get_cport_count(udev); if (num_cports < 0) { usb_put_dev(udev); dev_err(&udev->dev, "Cannot retrieve CPort count: %d\n", @@ -819,7 +820,7 @@ static int ap_probe(struct usb_interface *interface, es2->usb_intf = interface; es2->usb_dev = udev; spin_lock_init(&es2->cport_out_urb_lock); - INIT_KFIFO(es2->apb1_log_fifo); + INIT_KFIFO(es2->apb_log_fifo); usb_set_intfdata(interface, es2); es2->cport_to_ep = kcalloc(hd->num_cports, sizeof(*es2->cport_to_ep), @@ -892,10 +893,11 @@ static int ap_probe(struct usb_interface *interface, es2->cport_out_urb_busy[i] = false; /* just to be anal */ } - es2->apb1_log_enable_dentry = debugfs_create_file("apb1_log_enable", + /* XXX We will need to rename this per APB */ + es2->apb_log_enable_dentry = debugfs_create_file("apb_log_enable", (S_IWUSR | S_IRUGO), gb_debugfs_get(), es2, - &apb1_log_enable_fops); + &apb_log_enable_fops); return 0; error: ap_disconnect(interface); -- cgit v0.10.2 From b350007219f65df8594e62c731e29ff3ad2f4d61 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 29 Oct 2015 16:58:24 +0000 Subject: greybus: manifest: fix the placement of arguments to pr_err We're one character out here in the placement of the inputs to pr_err(). Later patches show this up when pushing through checkpatch.pl. This patch fixes by moving the offending variables one character left. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 2264ec59..3e61b66 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -467,8 +467,8 @@ bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size) /* Validate major/minor number */ if (header->version_major > GREYBUS_VERSION_MAJOR) { pr_err("manifest version too new (%hhu.%hhu > %hhu.%hhu)\n", - header->version_major, header->version_minor, - GREYBUS_VERSION_MAJOR, GREYBUS_VERSION_MINOR); + header->version_major, header->version_minor, + GREYBUS_VERSION_MAJOR, GREYBUS_VERSION_MINOR); return false; } -- cgit v0.10.2 From 8417f5e56c8d67371f1810dfa0d1871f0119e89d Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 29 Oct 2015 16:58:29 +0000 Subject: greybus: audio-pcm: fix use of variable unitialized Compiling with clang shows that period_elapsed will be used as a branch conditional unitialized whenever snd_dev->transfer_done < runtime->period_size. Since stack can grow up/down as we proceed though the call stack this should be fixed. This patch fixes by explicitly initalizing period_elapsed to zero. Signed-off-by: Bryan O'Donoghue Reviewed-by: Alex Elder Reviewed-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio-pcm.c b/drivers/staging/greybus/audio-pcm.c index fa5e85d..e62152a 100644 --- a/drivers/staging/greybus/audio-pcm.c +++ b/drivers/staging/greybus/audio-pcm.c @@ -91,6 +91,7 @@ static void gb_pcm_work(struct work_struct *work) frames = (len + (oldptr % stride)) / stride; + period_elapsed = 0; snd_dev->transfer_done += frames; if (snd_dev->transfer_done >= runtime->period_size) { snd_dev->transfer_done -= runtime->period_size; -- cgit v0.10.2 From 53be091214572ffb55e482fe0cd53f2dc37c246a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 2 Nov 2015 11:56:58 +0100 Subject: greybus: connection: remove unused time-stamp defines Remove unused time-stamp defines, that were left in when the time-stamp fifo was removed. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 0be78fe..aef450f 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -11,10 +11,6 @@ #include "greybus.h" -#define GB_CONNECTION_TS_KFIFO_ELEMENTS 2 -#define GB_CONNECTION_TS_KFIFO_LEN \ - (GB_CONNECTION_TS_KFIFO_ELEMENTS * sizeof(struct timeval)) - static DEFINE_SPINLOCK(gb_connections_lock); /* This is only used at initialization time; no locking is required. */ -- cgit v0.10.2 From 41a7fe27d6ee34f9752648805d596de0948a9873 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 2 Nov 2015 11:56:59 +0100 Subject: greybus: control: remove unused request handler Remove request handler for control protocol that makes no sense as we do not have any incoming control requests defined. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index 630b5b6..ffc07a4 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -60,40 +60,6 @@ int gb_control_disconnected_operation(struct gb_control *control, u16 cport_id) sizeof(request), NULL, 0); } -static int gb_control_request_recv(u8 type, struct gb_operation *op) -{ - struct gb_connection *connection = op->connection; - struct gb_protocol_version_response *version; - - switch (type) { - case GB_CONTROL_TYPE_PROBE_AP: - // TODO - // Send authenticated block of data, confirming this module is - // an AP. - break; - case GB_REQUEST_TYPE_PROTOCOL_VERSION: - if (!gb_operation_response_alloc(op, sizeof(*version), - GFP_KERNEL)) { - dev_err(&connection->bundle->dev, - "%s: error allocating response\n", __func__); - return -ENOMEM; - } - - version = op->response->payload; - version->major = GB_CONTROL_VERSION_MAJOR; - version->minor = GB_CONTROL_VERSION_MINOR; - break; - case GB_CONTROL_TYPE_CONNECTED: - case GB_CONTROL_TYPE_DISCONNECTED: - break; - default: - WARN_ON(1); - break; - } - - return 0; -} - static int gb_control_connection_init(struct gb_connection *connection) { struct gb_control *control; @@ -129,7 +95,6 @@ static struct gb_protocol control_protocol = { .minor = 1, .connection_init = gb_control_connection_init, .connection_exit = gb_control_connection_exit, - .request_recv = gb_control_request_recv, .flags = GB_PROTOCOL_SKIP_CONTROL_CONNECTED | GB_PROTOCOL_SKIP_CONTROL_DISCONNECTED, }; -- cgit v0.10.2 From 4d5c446b53655da886822a01b5d004704b564f8d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 2 Nov 2015 11:56:57 +0100 Subject: greybus: es2: update obsolete bridge-device comments Update obsolete bridge-device comments to better describe our current ES2 endpoint layout. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index b43435f..870c9cb 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -778,11 +778,10 @@ out: } /* - * The ES2 USB Bridge device contains 4 endpoints - * 1 Control - usual USB stuff + AP -> SVC messages - * 1 Interrupt IN - SVC -> AP messages - * 1 Bulk IN - CPort data in - * 1 Bulk OUT - CPort data out + * The ES2 USB Bridge device has 15 endpoints + * 1 Control - usual USB stuff + AP -> APBridgeA messages + * 7 Bulk IN - CPort data in + * 7 Bulk OUT - CPort data out */ static int ap_probe(struct usb_interface *interface, const struct usb_device_id *id) @@ -830,7 +829,7 @@ static int ap_probe(struct usb_interface *interface, goto error; } - /* find all 3 of our endpoints */ + /* find all bulk endpoints */ iface_desc = interface->cur_altsetting; for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; -- cgit v0.10.2 From e96e61686388f92af8283cabe5dad158b5fd1f6e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 3 Nov 2015 12:11:32 +0100 Subject: greybus: remove unused host-device id Remove unused device_id field from host-device structure. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 524a412..f51465e 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -93,7 +93,6 @@ struct greybus_host_device { struct list_head interfaces; struct list_head connections; struct ida cport_id_map; - u8 device_id; /* Number of CPorts supported by the UniPro IP */ size_t num_cports; -- cgit v0.10.2 From 0e30550665cafe61776aa9730f876ade9a02a258 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 3 Nov 2015 12:11:31 +0100 Subject: greybus: remove unused connection device type The connection device type is no longer used. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index f51465e..edee11a 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -164,7 +164,6 @@ extern struct device_type greybus_endo_type; extern struct device_type greybus_module_type; extern struct device_type greybus_interface_type; extern struct device_type greybus_bundle_type; -extern struct device_type greybus_connection_type; static inline int is_gb_endo(const struct device *dev) { -- cgit v0.10.2 From e6c88bf31e9ef22e3503e0f905cb6fa3c8c53f26 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 3 Nov 2015 12:11:30 +0100 Subject: greybus: connection: use bundle device for bundle error messages It is safe to use the bundle device for error messages when we know we have a bundle. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index aef450f..c70518ed 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -123,7 +123,8 @@ gb_connection_create_range(struct greybus_host_device *hd, * about holding the connection lock. */ if (bundle && gb_connection_intf_find(bundle->intf, cport_id)) { - dev_err(parent, "cport 0x%04hx already connected\n", cport_id); + dev_err(&bundle->dev, "cport 0x%04hx already connected\n", + cport_id); return NULL; } -- cgit v0.10.2 From 21dcc9e50339642dfd241fa081a9b2ab6a34221a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 3 Nov 2015 12:11:29 +0100 Subject: greybus: connection: fix potential null-deref in hd_cport_enable Use parent of host device for error messages as the connections bundle may be NULL. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index c70518ed..e16ed4e 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -196,7 +196,7 @@ static int gb_connection_hd_cport_enable(struct gb_connection *connection) ret = hd->driver->cport_enable(hd, connection->hd_cport_id); if (ret) { - dev_err(&connection->bundle->dev, + dev_err(hd->parent, "failed to enable host cport: %d\n", ret); return ret; } -- cgit v0.10.2 From a6e0363cb06989e9584820d3f5c0faad1cc35eae Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 3 Nov 2015 12:11:28 +0100 Subject: greybus: connection: fix potential null-deref in connection create We allow connections without bundles so we must not use the bundle device for error messages after binding the protocol. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index e16ed4e..c3cd69c 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -170,7 +170,7 @@ gb_connection_create_range(struct greybus_host_device *hd, retval = gb_connection_bind_protocol(connection); if (retval) { - dev_err(&bundle->dev, "%d: failed to bind protocol: %d\n", + dev_err(parent, "%d: failed to bind protocol: %d\n", cport_id, retval); gb_connection_destroy(connection); return NULL; -- cgit v0.10.2 From 5245a90564b0c3f781e0c60cdbeb3b3b34c970df Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 3 Nov 2015 12:11:27 +0100 Subject: greybus: connection: fix potential null-deref when binding protocol We can have connections without bundles so we must not use the bundle device for error messages when failing to look up a protocol. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index c3cd69c..294e72e8 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -510,7 +510,7 @@ int gb_connection_bind_protocol(struct gb_connection *connection) connection->major, connection->minor); if (!protocol) { - dev_warn(&connection->bundle->dev, + dev_warn(connection->hd->parent, "protocol 0x%02hhx version %hhu.%hhu not found\n", connection->protocol_id, connection->major, connection->minor); -- cgit v0.10.2 From fcfc762f17616e9c720214d85b88ed672e767499 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 3 Nov 2015 12:11:26 +0100 Subject: greybus: connection: kill gb_hd_connections_exit Connections are destroyed as part of interface tear down. If we fail to do that properly it's a bug that should be fixed rather than papered over by a fall-back clean up function. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 294e72e8..de774b9 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -489,14 +489,6 @@ void gb_connection_latency_tag_disable(struct gb_connection *connection) } EXPORT_SYMBOL_GPL(gb_connection_latency_tag_disable); -void gb_hd_connections_exit(struct greybus_host_device *hd) -{ - struct gb_connection *connection; - - list_for_each_entry(connection, &hd->connections, hd_links) - gb_connection_destroy(connection); -} - int gb_connection_bind_protocol(struct gb_connection *connection) { struct gb_protocol *protocol; diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index af425a2..06c7711 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -58,7 +58,6 @@ struct gb_connection *gb_connection_create_range(struct greybus_host_device *hd, u16 cport_id, u8 protocol_id, u32 ida_start, u32 ida_end); void gb_connection_destroy(struct gb_connection *connection); -void gb_hd_connections_exit(struct greybus_host_device *hd); void greybus_data_rcvd(struct greybus_host_device *hd, u16 cport_id, u8 *data, size_t length); diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index be75456..726bf64 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -242,12 +242,6 @@ void greybus_remove_hd(struct greybus_host_device *hd) if (hd->initial_svc_connection) gb_connection_destroy(hd->initial_svc_connection); - /* - * Make sure there are no leftovers that can potentially corrupt sysfs. - */ - if (WARN_ON(!list_empty(&hd->connections))) - gb_hd_connections_exit(hd); - kref_put_mutex(&hd->kref, free_hd, &hd_mutex); } EXPORT_SYMBOL_GPL(greybus_remove_hd); -- cgit v0.10.2 From 26b7ba66c1d698e7d377f61d310b5cfa1cfcf2a0 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 3 Nov 2015 12:11:25 +0100 Subject: greybus: endo: fix ida memory leak Fix yet another ida memory leak due to failure to call the destructor. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c index 726b1d3..7f24c79 100644 --- a/drivers/staging/greybus/endo.c +++ b/drivers/staging/greybus/endo.c @@ -547,4 +547,5 @@ int __init gb_endo_init(void) void gb_endo_exit(void) { + ida_destroy(&greybus_endo_id_map); } -- cgit v0.10.2 From 04fdd6a51a5b3b448047b83624dbfac85d3daf9a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 3 Nov 2015 18:03:21 +0100 Subject: greybus: remove obsolete comment Remove obsolete comment about the driver model. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index edee11a..219b2ff 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -57,16 +57,6 @@ #define CPORT_ID_MAX 4095 /* UniPro max id is 4095 */ #define CPORT_ID_BAD U16_MAX -/* For SP1 hardware, we are going to "hardcode" each device to have all logical - * blocks in order to be able to address them as one unified "unit". Then - * higher up layers will then be able to talk to them as one logical block and - * properly know how they are hooked together (i.e. which i2c port is on the - * same module as the gpio pins, etc.) - * - * So, put the "private" data structures here in greybus.h and link to them off - * of the "main" gb_module structure. - */ - struct greybus_host_device; /* Greybus "Host driver" structure, needed by a host controller driver to be -- cgit v0.10.2 From 7bc6faaca7d829d4e6f5d65909d5068f73b76bda Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 3 Nov 2015 18:03:22 +0100 Subject: greybus: create host-device compilation unit Move everything host-device related to hd.c and hd.h. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index b8dc36b..ba60430 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -1,5 +1,6 @@ greybus-y := core.o \ debugfs.o \ + hd.o \ manifest.o \ endo.o \ module.o \ diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 726bf64..4396f90 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -146,106 +146,6 @@ void greybus_deregister_driver(struct greybus_driver *driver) } EXPORT_SYMBOL_GPL(greybus_deregister_driver); - -static DEFINE_MUTEX(hd_mutex); - -static void free_hd(struct kref *kref) -{ - struct greybus_host_device *hd; - - hd = container_of(kref, struct greybus_host_device, kref); - - ida_destroy(&hd->cport_id_map); - kfree(hd); - mutex_unlock(&hd_mutex); -} - -struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver, - struct device *parent, - size_t buffer_size_max, - size_t num_cports) -{ - struct greybus_host_device *hd; - - /* - * Validate that the driver implements all of the callbacks - * so that we don't have to every time we make them. - */ - if ((!driver->message_send) || (!driver->message_cancel)) { - pr_err("Must implement all greybus_host_driver callbacks!\n"); - return ERR_PTR(-EINVAL); - } - - if (buffer_size_max < GB_OPERATION_MESSAGE_SIZE_MIN) { - dev_err(parent, "greybus host-device buffers too small\n"); - return ERR_PTR(-EINVAL); - } - - if (num_cports == 0 || num_cports > CPORT_ID_MAX) { - dev_err(parent, "Invalid number of CPorts: %zu\n", num_cports); - return ERR_PTR(-EINVAL); - } - - /* - * Make sure to never allocate messages larger than what the Greybus - * protocol supports. - */ - if (buffer_size_max > GB_OPERATION_MESSAGE_SIZE_MAX) { - dev_warn(parent, "limiting buffer size to %u\n", - GB_OPERATION_MESSAGE_SIZE_MAX); - buffer_size_max = GB_OPERATION_MESSAGE_SIZE_MAX; - } - - hd = kzalloc(sizeof(*hd) + driver->hd_priv_size, GFP_KERNEL); - if (!hd) - return ERR_PTR(-ENOMEM); - - kref_init(&hd->kref); - hd->parent = parent; - hd->driver = driver; - INIT_LIST_HEAD(&hd->interfaces); - INIT_LIST_HEAD(&hd->connections); - ida_init(&hd->cport_id_map); - hd->buffer_size_max = buffer_size_max; - hd->num_cports = num_cports; - - /* - * Initialize AP's SVC protocol connection: - * - * This is required as part of early initialization of the host device - * as we need this connection in order to start any kind of message - * exchange between the AP and the SVC. SVC will start with a - * 'get-version' request followed by a 'svc-hello' message and at that - * time we will create a fully initialized svc-connection, as we need - * endo-id and AP's interface id for that. - */ - if (!gb_ap_svc_connection_create(hd)) { - kref_put_mutex(&hd->kref, free_hd, &hd_mutex); - return ERR_PTR(-ENOMEM); - } - - return hd; -} -EXPORT_SYMBOL_GPL(greybus_create_hd); - -void greybus_remove_hd(struct greybus_host_device *hd) -{ - /* - * Tear down all interfaces, modules, and the endo that is associated - * with this host controller before freeing the memory associated with - * the host controller. - */ - gb_interfaces_remove(hd); - gb_endo_remove(hd->endo); - - /* Is the SVC still using the partially uninitialized connection ? */ - if (hd->initial_svc_connection) - gb_connection_destroy(hd->initial_svc_connection); - - kref_put_mutex(&hd->kref, free_hd, &hd_mutex); -} -EXPORT_SYMBOL_GPL(greybus_remove_hd); - static int __init gb_init(void) { int retval; diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 219b2ff..8eb63e0 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -25,6 +25,7 @@ #include "greybus_manifest.h" #include "greybus_protocols.h" #include "manifest.h" +#include "hd.h" #include "endo.h" #include "svc.h" #include "firmware.h" @@ -57,53 +58,6 @@ #define CPORT_ID_MAX 4095 /* UniPro max id is 4095 */ #define CPORT_ID_BAD U16_MAX -struct greybus_host_device; - -/* Greybus "Host driver" structure, needed by a host controller driver to be - * able to handle both SVC control as well as "real" greybus messages - */ -struct greybus_host_driver { - size_t hd_priv_size; - - int (*cport_enable)(struct greybus_host_device *hd, u16 cport_id); - int (*cport_disable)(struct greybus_host_device *hd, u16 cport_id); - int (*message_send)(struct greybus_host_device *hd, u16 dest_cport_id, - struct gb_message *message, gfp_t gfp_mask); - void (*message_cancel)(struct gb_message *message); - int (*latency_tag_enable)(struct greybus_host_device *hd, u16 cport_id); - int (*latency_tag_disable)(struct greybus_host_device *hd, - u16 cport_id); -}; - -struct greybus_host_device { - struct kref kref; - struct device *parent; - const struct greybus_host_driver *driver; - - struct list_head interfaces; - struct list_head connections; - struct ida cport_id_map; - - /* Number of CPorts supported by the UniPro IP */ - size_t num_cports; - - /* Host device buffer constraints */ - size_t buffer_size_max; - - struct gb_endo *endo; - struct gb_connection *initial_svc_connection; - struct gb_svc *svc; - - /* Private data for the host driver */ - unsigned long hd_priv[0] __aligned(sizeof(s64)); -}; - -struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *hd, - struct device *parent, - size_t buffer_size_max, - size_t num_cports); -void greybus_remove_hd(struct greybus_host_device *hd); - struct greybus_driver { const char *name; diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c new file mode 100644 index 0000000..3ac8507 --- /dev/null +++ b/drivers/staging/greybus/hd.c @@ -0,0 +1,115 @@ +/* + * Greybus Host Device + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include + +#include "greybus.h" + +static DEFINE_MUTEX(hd_mutex); + + +static void free_hd(struct kref *kref) +{ + struct greybus_host_device *hd; + + hd = container_of(kref, struct greybus_host_device, kref); + + ida_destroy(&hd->cport_id_map); + kfree(hd); + mutex_unlock(&hd_mutex); +} + +struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver, + struct device *parent, + size_t buffer_size_max, + size_t num_cports) +{ + struct greybus_host_device *hd; + + /* + * Validate that the driver implements all of the callbacks + * so that we don't have to every time we make them. + */ + if ((!driver->message_send) || (!driver->message_cancel)) { + pr_err("Must implement all greybus_host_driver callbacks!\n"); + return ERR_PTR(-EINVAL); + } + + if (buffer_size_max < GB_OPERATION_MESSAGE_SIZE_MIN) { + dev_err(parent, "greybus host-device buffers too small\n"); + return ERR_PTR(-EINVAL); + } + + if (num_cports == 0 || num_cports > CPORT_ID_MAX) { + dev_err(parent, "Invalid number of CPorts: %zu\n", num_cports); + return ERR_PTR(-EINVAL); + } + + /* + * Make sure to never allocate messages larger than what the Greybus + * protocol supports. + */ + if (buffer_size_max > GB_OPERATION_MESSAGE_SIZE_MAX) { + dev_warn(parent, "limiting buffer size to %u\n", + GB_OPERATION_MESSAGE_SIZE_MAX); + buffer_size_max = GB_OPERATION_MESSAGE_SIZE_MAX; + } + + hd = kzalloc(sizeof(*hd) + driver->hd_priv_size, GFP_KERNEL); + if (!hd) + return ERR_PTR(-ENOMEM); + + kref_init(&hd->kref); + hd->parent = parent; + hd->driver = driver; + INIT_LIST_HEAD(&hd->interfaces); + INIT_LIST_HEAD(&hd->connections); + ida_init(&hd->cport_id_map); + hd->buffer_size_max = buffer_size_max; + hd->num_cports = num_cports; + + /* + * Initialize AP's SVC protocol connection: + * + * This is required as part of early initialization of the host device + * as we need this connection in order to start any kind of message + * exchange between the AP and the SVC. SVC will start with a + * 'get-version' request followed by a 'svc-hello' message and at that + * time we will create a fully initialized svc-connection, as we need + * endo-id and AP's interface id for that. + */ + if (!gb_ap_svc_connection_create(hd)) { + kref_put_mutex(&hd->kref, free_hd, &hd_mutex); + return ERR_PTR(-ENOMEM); + } + + return hd; +} +EXPORT_SYMBOL_GPL(greybus_create_hd); + +void greybus_remove_hd(struct greybus_host_device *hd) +{ + /* + * Tear down all interfaces, modules, and the endo that is associated + * with this host controller before freeing the memory associated with + * the host controller. + */ + gb_interfaces_remove(hd); + gb_endo_remove(hd->endo); + + /* Is the SVC still using the partially uninitialized connection ? */ + if (hd->initial_svc_connection) + gb_connection_destroy(hd->initial_svc_connection); + + kref_put_mutex(&hd->kref, free_hd, &hd_mutex); +} +EXPORT_SYMBOL_GPL(greybus_remove_hd); diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h new file mode 100644 index 0000000..df953d4 --- /dev/null +++ b/drivers/staging/greybus/hd.h @@ -0,0 +1,61 @@ +/* + * Greybus Host Device + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#ifndef __HD_H +#define __HD_H + +struct greybus_host_device; +struct gb_message; + +/* Greybus "Host driver" structure, needed by a host controller driver to be + * able to handle both SVC control as well as "real" greybus messages + */ +struct greybus_host_driver { + size_t hd_priv_size; + + int (*cport_enable)(struct greybus_host_device *hd, u16 cport_id); + int (*cport_disable)(struct greybus_host_device *hd, u16 cport_id); + int (*message_send)(struct greybus_host_device *hd, u16 dest_cport_id, + struct gb_message *message, gfp_t gfp_mask); + void (*message_cancel)(struct gb_message *message); + int (*latency_tag_enable)(struct greybus_host_device *hd, u16 cport_id); + int (*latency_tag_disable)(struct greybus_host_device *hd, + u16 cport_id); +}; + +struct greybus_host_device { + struct kref kref; + struct device *parent; + const struct greybus_host_driver *driver; + + struct list_head interfaces; + struct list_head connections; + struct ida cport_id_map; + + /* Number of CPorts supported by the UniPro IP */ + size_t num_cports; + + /* Host device buffer constraints */ + size_t buffer_size_max; + + struct gb_endo *endo; + struct gb_connection *initial_svc_connection; + struct gb_svc *svc; + + /* Private data for the host driver */ + unsigned long hd_priv[0] __aligned(sizeof(s64)); +}; + +struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *hd, + struct device *parent, + size_t buffer_size_max, + size_t num_cports); +void greybus_remove_hd(struct greybus_host_device *hd); + +#endif /* __HD_H */ -- cgit v0.10.2 From 2537636abae5b81a1de5ad7511a29306f39b2167 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 3 Nov 2015 18:03:23 +0100 Subject: greybus: hd: rename host-device structure Rename host-device structure gb_host_device to match our other structures. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index de774b9..96dabf7 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -17,7 +17,7 @@ static DEFINE_SPINLOCK(gb_connections_lock); static struct gb_connection * gb_connection_intf_find(struct gb_interface *intf, u16 cport_id) { - struct greybus_host_device *hd = intf->hd; + struct gb_host_device *hd = intf->hd; struct gb_connection *connection; list_for_each_entry(connection, &hd->connections, hd_links) @@ -28,7 +28,7 @@ gb_connection_intf_find(struct gb_interface *intf, u16 cport_id) } static struct gb_connection * -gb_connection_hd_find(struct greybus_host_device *hd, u16 cport_id) +gb_connection_hd_find(struct gb_host_device *hd, u16 cport_id) { struct gb_connection *connection; unsigned long flags; @@ -48,7 +48,7 @@ found: * Callback from the host driver to let us know that data has been * received on the bundle. */ -void greybus_data_rcvd(struct greybus_host_device *hd, u16 cport_id, +void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id, u8 *data, size_t length) { struct gb_connection *connection; @@ -105,7 +105,7 @@ int svc_update_connection(struct gb_interface *intf, * pointer otherwise. */ struct gb_connection * -gb_connection_create_range(struct greybus_host_device *hd, +gb_connection_create_range(struct gb_host_device *hd, struct gb_bundle *bundle, struct device *parent, u16 cport_id, u8 protocol_id, u32 ida_start, u32 ida_end) @@ -188,7 +188,7 @@ err_remove_ida: static int gb_connection_hd_cport_enable(struct gb_connection *connection) { - struct greybus_host_device *hd = connection->hd; + struct gb_host_device *hd = connection->hd; int ret; if (!hd->driver->cport_enable) @@ -206,7 +206,7 @@ static int gb_connection_hd_cport_enable(struct gb_connection *connection) static void gb_connection_hd_cport_disable(struct gb_connection *connection) { - struct greybus_host_device *hd = connection->hd; + struct gb_host_device *hd = connection->hd; if (!hd->driver->cport_disable) return; @@ -258,7 +258,7 @@ static void gb_connection_cancel_operations(struct gb_connection *connection, static int gb_connection_svc_connection_create(struct gb_connection *connection) { - struct greybus_host_device *hd = connection->hd; + struct gb_host_device *hd = connection->hd; struct gb_protocol *protocol = connection->protocol; struct gb_interface *intf; int ret; @@ -459,7 +459,7 @@ void gb_connection_destroy(struct gb_connection *connection) void gb_connection_latency_tag_enable(struct gb_connection *connection) { - struct greybus_host_device *hd = connection->hd; + struct gb_host_device *hd = connection->hd; int ret; if (!hd->driver->latency_tag_enable) @@ -475,7 +475,7 @@ EXPORT_SYMBOL_GPL(gb_connection_latency_tag_enable); void gb_connection_latency_tag_disable(struct gb_connection *connection) { - struct greybus_host_device *hd = connection->hd; + struct gb_host_device *hd = connection->hd; int ret; if (!hd->driver->latency_tag_disable) diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 06c7711..6163082 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -22,7 +22,7 @@ enum gb_connection_state { }; struct gb_connection { - struct greybus_host_device *hd; + struct gb_host_device *hd; struct gb_bundle *bundle; struct kref kref; u16 hd_cport_id; @@ -53,13 +53,13 @@ int svc_update_connection(struct gb_interface *intf, struct gb_connection *connection); struct gb_connection *gb_connection_create(struct gb_bundle *bundle, u16 cport_id, u8 protocol_id); -struct gb_connection *gb_connection_create_range(struct greybus_host_device *hd, +struct gb_connection *gb_connection_create_range(struct gb_host_device *hd, struct gb_bundle *bundle, struct device *parent, u16 cport_id, u8 protocol_id, u32 ida_start, u32 ida_end); void gb_connection_destroy(struct gb_connection *connection); -void greybus_data_rcvd(struct greybus_host_device *hd, u16 cport_id, +void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id, u8 *data, size_t length); int gb_connection_bind_protocol(struct gb_connection *connection); diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c index 7f24c79..df4afb2 100644 --- a/drivers/staging/greybus/endo.c +++ b/drivers/staging/greybus/endo.c @@ -191,7 +191,7 @@ static bool single_cross_rib(u8 left_ribs, u8 right_ribs) * - Bit 1: 2nd rib location from top, i.e. between interface 2 and 3. * - Bit 2: 3rd rib location from top, i.e. between interface 3 and 4. */ -static bool validate_front_ribs(struct greybus_host_device *hd, +static bool validate_front_ribs(struct gb_host_device *hd, struct endo_layout *layout, bool mini, u16 endo_id) { @@ -254,7 +254,7 @@ static bool validate_front_ribs(struct greybus_host_device *hd, * its rotational orientation. We define one canonical id to represent a * particular endo configuration. */ -static bool validate_back_ribs(struct greybus_host_device *hd, +static bool validate_back_ribs(struct gb_host_device *hd, struct endo_layout *layout, u16 endo_id) { u8 max_ribs = layout->max_ribs; @@ -320,7 +320,7 @@ static bool validate_back_ribs(struct greybus_host_device *hd, * Validate the endo-id passed from SVC. Error out if its not a valid Endo, * else return structure representing ribs positions on front and back of Endo. */ -static int gb_endo_validate_id(struct greybus_host_device *hd, +static int gb_endo_validate_id(struct gb_host_device *hd, struct endo_layout *layout, u16 endo_id) { /* Validate Endo Size */ @@ -435,7 +435,7 @@ static int create_modules(struct gb_endo *endo) return 0; } -static int gb_endo_register(struct greybus_host_device *hd, +static int gb_endo_register(struct gb_host_device *hd, struct gb_endo *endo) { int dev_id; @@ -471,7 +471,7 @@ static int gb_endo_register(struct greybus_host_device *hd, return retval; } -struct gb_endo *gb_endo_create(struct greybus_host_device *hd, u16 endo_id, +struct gb_endo *gb_endo_create(struct gb_host_device *hd, u16 endo_id, u8 ap_intf_id) { struct gb_endo *endo; @@ -524,7 +524,7 @@ void gb_endo_remove(struct gb_endo *endo) device_unregister(&endo->dev); } -int greybus_endo_setup(struct greybus_host_device *hd, u16 endo_id, +int greybus_endo_setup(struct gb_host_device *hd, u16 endo_id, u8 ap_intf_id) { struct gb_endo *endo; diff --git a/drivers/staging/greybus/endo.h b/drivers/staging/greybus/endo.h index 0b5384d..20a8649 100644 --- a/drivers/staging/greybus/endo.h +++ b/drivers/staging/greybus/endo.h @@ -47,15 +47,15 @@ struct gb_endo { #define to_gb_endo(d) container_of(d, struct gb_endo, dev) /* Greybus "private" definitions */ -struct greybus_host_device; +struct gb_host_device; int gb_endo_init(void); void gb_endo_exit(void); -struct gb_endo *gb_endo_create(struct greybus_host_device *hd, +struct gb_endo *gb_endo_create(struct gb_host_device *hd, u16 endo_id, u8 ap_intf_id); void gb_endo_remove(struct gb_endo *endo); -int greybus_endo_setup(struct greybus_host_device *hd, u16 endo_id, +int greybus_endo_setup(struct gb_host_device *hd, u16 endo_id, u8 ap_intf_id); u8 endo_get_module_id(struct gb_endo *endo, u8 interface_id); diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index ba025e7..07e1a14 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -60,7 +60,7 @@ static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); * es1_ap_dev - ES1 USB Bridge to AP structure * @usb_dev: pointer to the USB device we are. * @usb_intf: pointer to the USB interface we are bound to. - * @hd: pointer to our greybus_host_device structure + * @hd: pointer to our gb_host_device structure * @cport_in_endpoint: bulk in endpoint for CPort data * @cport-out_endpoint: bulk out endpoint for CPort data * @cport_in_urb: array of urbs for the CPort in messages @@ -75,7 +75,7 @@ static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); struct es1_ap_dev { struct usb_device *usb_dev; struct usb_interface *usb_intf; - struct greybus_host_device *hd; + struct gb_host_device *hd; __u8 cport_in_endpoint; __u8 cport_out_endpoint; @@ -88,7 +88,7 @@ struct es1_ap_dev { spinlock_t cport_out_urb_lock; }; -static inline struct es1_ap_dev *hd_to_es1(struct greybus_host_device *hd) +static inline struct es1_ap_dev *hd_to_es1(struct gb_host_device *hd) { return (struct es1_ap_dev *)&hd->hd_priv; } @@ -181,7 +181,7 @@ static u16 gb_message_cport_unpack(struct gb_operation_msg_hdr *header) * Returns zero if the message was successfully queued, or a negative errno * otherwise. */ -static int message_send(struct greybus_host_device *hd, u16 cport_id, +static int message_send(struct gb_host_device *hd, u16 cport_id, struct gb_message *message, gfp_t gfp_mask) { struct es1_ap_dev *es1 = hd_to_es1(hd); @@ -244,7 +244,7 @@ static int message_send(struct greybus_host_device *hd, u16 cport_id, */ static void message_cancel(struct gb_message *message) { - struct greybus_host_device *hd = message->operation->connection->hd; + struct gb_host_device *hd = message->operation->connection->hd; struct es1_ap_dev *es1 = hd_to_es1(hd); struct urb *urb; int i; @@ -277,7 +277,7 @@ static void message_cancel(struct gb_message *message) usb_free_urb(urb); } -static int latency_tag_enable(struct greybus_host_device *hd, u16 cport_id) +static int latency_tag_enable(struct gb_host_device *hd, u16 cport_id) { int retval; struct es1_ap_dev *es1 = hd_to_es1(hd); @@ -301,7 +301,7 @@ static int latency_tag_enable(struct greybus_host_device *hd, u16 cport_id) return retval; } -static int latency_tag_disable(struct greybus_host_device *hd, u16 cport_id) +static int latency_tag_disable(struct gb_host_device *hd, u16 cport_id) { int retval; struct es1_ap_dev *es1 = hd_to_es1(hd); @@ -403,7 +403,7 @@ static void ap_disconnect(struct usb_interface *interface) static void cport_in_callback(struct urb *urb) { - struct greybus_host_device *hd = urb->context; + struct gb_host_device *hd = urb->context; struct device *dev = &urb->dev->dev; struct gb_operation_msg_hdr *header; int status = check_urb_status(urb); @@ -443,7 +443,7 @@ exit: static void cport_out_callback(struct urb *urb) { struct gb_message *message = urb->context; - struct greybus_host_device *hd = message->operation->connection->hd; + struct gb_host_device *hd = message->operation->connection->hd; struct es1_ap_dev *es1 = hd_to_es1(hd); int status = check_urb_status(urb); unsigned long flags; @@ -599,7 +599,7 @@ static int ap_probe(struct usb_interface *interface, const struct usb_device_id *id) { struct es1_ap_dev *es1; - struct greybus_host_device *hd; + struct gb_host_device *hd; struct usb_device *udev; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 870c9cb..8860f60 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -83,7 +83,7 @@ struct es2_cport_out { * es2_ap_dev - ES2 USB Bridge to AP structure * @usb_dev: pointer to the USB device we are. * @usb_intf: pointer to the USB interface we are bound to. - * @hd: pointer to our greybus_host_device structure + * @hd: pointer to our gb_host_device structure * @cport_in: endpoint, urbs and buffer for cport in messages * @cport_out: endpoint for for cport out messages @@ -102,7 +102,7 @@ struct es2_cport_out { struct es2_ap_dev { struct usb_device *usb_dev; struct usb_interface *usb_intf; - struct greybus_host_device *hd; + struct gb_host_device *hd; struct es2_cport_in cport_in[NUM_BULKS]; struct es2_cport_out cport_out[NUM_BULKS]; @@ -131,7 +131,7 @@ struct cport_to_ep { __u8 endpoint_out; }; -static inline struct es2_ap_dev *hd_to_es2(struct greybus_host_device *hd) +static inline struct es2_ap_dev *hd_to_es2(struct gb_host_device *hd) { return (struct es2_ap_dev *)&hd->hd_priv; } @@ -291,7 +291,7 @@ static u16 gb_message_cport_unpack(struct gb_operation_msg_hdr *header) * Returns zero if the message was successfully queued, or a negative errno * otherwise. */ -static int message_send(struct greybus_host_device *hd, u16 cport_id, +static int message_send(struct gb_host_device *hd, u16 cport_id, struct gb_message *message, gfp_t gfp_mask) { struct es2_ap_dev *es2 = hd_to_es2(hd); @@ -357,7 +357,7 @@ static int message_send(struct greybus_host_device *hd, u16 cport_id, */ static void message_cancel(struct gb_message *message) { - struct greybus_host_device *hd = message->operation->connection->hd; + struct gb_host_device *hd = message->operation->connection->hd; struct es2_ap_dev *es2 = hd_to_es2(hd); struct urb *urb; int i; @@ -390,7 +390,7 @@ static void message_cancel(struct gb_message *message) usb_free_urb(urb); } -static int cport_reset(struct greybus_host_device *hd, u16 cport_id) +static int cport_reset(struct gb_host_device *hd, u16 cport_id) { struct es2_ap_dev *es2 = hd_to_es2(hd); struct usb_device *udev = es2->usb_dev; @@ -410,7 +410,7 @@ static int cport_reset(struct greybus_host_device *hd, u16 cport_id) return 0; } -static int cport_enable(struct greybus_host_device *hd, u16 cport_id) +static int cport_enable(struct gb_host_device *hd, u16 cport_id) { int retval; @@ -423,7 +423,7 @@ static int cport_enable(struct greybus_host_device *hd, u16 cport_id) return 0; } -static int latency_tag_enable(struct greybus_host_device *hd, u16 cport_id) +static int latency_tag_enable(struct gb_host_device *hd, u16 cport_id) { int retval; struct es2_ap_dev *es2 = hd_to_es2(hd); @@ -447,7 +447,7 @@ static int latency_tag_enable(struct greybus_host_device *hd, u16 cport_id) return retval; } -static int latency_tag_disable(struct greybus_host_device *hd, u16 cport_id) +static int latency_tag_disable(struct gb_host_device *hd, u16 cport_id) { int retval; struct es2_ap_dev *es2 = hd_to_es2(hd); @@ -556,7 +556,7 @@ static void ap_disconnect(struct usb_interface *interface) static void cport_in_callback(struct urb *urb) { - struct greybus_host_device *hd = urb->context; + struct gb_host_device *hd = urb->context; struct device *dev = &urb->dev->dev; struct gb_operation_msg_hdr *header; int status = check_urb_status(urb); @@ -596,7 +596,7 @@ exit: static void cport_out_callback(struct urb *urb) { struct gb_message *message = urb->context; - struct greybus_host_device *hd = message->operation->connection->hd; + struct gb_host_device *hd = message->operation->connection->hd; struct es2_ap_dev *es2 = hd_to_es2(hd); int status = check_urb_status(urb); unsigned long flags; @@ -787,7 +787,7 @@ static int ap_probe(struct usb_interface *interface, const struct usb_device_id *id) { struct es2_ap_dev *es2; - struct greybus_host_device *hd; + struct gb_host_device *hd; struct usb_device *udev; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 8eb63e0..1b6f56f 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -129,7 +129,7 @@ static inline int is_gb_bundle(const struct device *dev) return dev->type == &greybus_bundle_type; } -static inline bool cport_id_valid(struct greybus_host_device *hd, u16 cport_id) +static inline bool cport_id_valid(struct gb_host_device *hd, u16 cport_id) { return cport_id != CPORT_ID_BAD && cport_id < hd->num_cports; } diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h index e5e3cc0..d38f9e0 100644 --- a/drivers/staging/greybus/greybus_trace.h +++ b/drivers/staging/greybus/greybus_trace.h @@ -15,7 +15,7 @@ #include struct gb_message; -struct greybus_host_device; +struct gb_host_device; DECLARE_EVENT_CLASS(gb_message, @@ -108,7 +108,7 @@ DEFINE_EVENT(gb_message, gb_message_cancel_incoming, DECLARE_EVENT_CLASS(gb_host_device, - TP_PROTO(struct greybus_host_device *hd, u16 intf_cport_id, + TP_PROTO(struct gb_host_device *hd, u16 intf_cport_id, size_t payload_size), TP_ARGS(hd, intf_cport_id, payload_size), @@ -136,7 +136,7 @@ DECLARE_EVENT_CLASS(gb_host_device, */ DEFINE_EVENT(gb_host_device, gb_host_device_send, - TP_PROTO(struct greybus_host_device *hd, u16 intf_cport_id, + TP_PROTO(struct gb_host_device *hd, u16 intf_cport_id, size_t payload_size), TP_ARGS(hd, intf_cport_id, payload_size) @@ -149,7 +149,7 @@ DEFINE_EVENT(gb_host_device, gb_host_device_send, */ DEFINE_EVENT(gb_host_device, gb_host_device_recv, - TP_PROTO(struct greybus_host_device *hd, u16 intf_cport_id, + TP_PROTO(struct gb_host_device *hd, u16 intf_cport_id, size_t payload_size), TP_ARGS(hd, intf_cport_id, payload_size) diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index 3ac8507..a09a920 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -19,21 +19,21 @@ static DEFINE_MUTEX(hd_mutex); static void free_hd(struct kref *kref) { - struct greybus_host_device *hd; + struct gb_host_device *hd; - hd = container_of(kref, struct greybus_host_device, kref); + hd = container_of(kref, struct gb_host_device, kref); ida_destroy(&hd->cport_id_map); kfree(hd); mutex_unlock(&hd_mutex); } -struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver, +struct gb_host_device *greybus_create_hd(struct greybus_host_driver *driver, struct device *parent, size_t buffer_size_max, size_t num_cports) { - struct greybus_host_device *hd; + struct gb_host_device *hd; /* * Validate that the driver implements all of the callbacks @@ -96,7 +96,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver } EXPORT_SYMBOL_GPL(greybus_create_hd); -void greybus_remove_hd(struct greybus_host_device *hd) +void greybus_remove_hd(struct gb_host_device *hd) { /* * Tear down all interfaces, modules, and the endo that is associated diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h index df953d4..122790d 100644 --- a/drivers/staging/greybus/hd.h +++ b/drivers/staging/greybus/hd.h @@ -10,7 +10,7 @@ #ifndef __HD_H #define __HD_H -struct greybus_host_device; +struct gb_host_device; struct gb_message; /* Greybus "Host driver" structure, needed by a host controller driver to be @@ -19,17 +19,16 @@ struct gb_message; struct greybus_host_driver { size_t hd_priv_size; - int (*cport_enable)(struct greybus_host_device *hd, u16 cport_id); - int (*cport_disable)(struct greybus_host_device *hd, u16 cport_id); - int (*message_send)(struct greybus_host_device *hd, u16 dest_cport_id, + int (*cport_enable)(struct gb_host_device *hd, u16 cport_id); + int (*cport_disable)(struct gb_host_device *hd, u16 cport_id); + int (*message_send)(struct gb_host_device *hd, u16 dest_cport_id, struct gb_message *message, gfp_t gfp_mask); void (*message_cancel)(struct gb_message *message); - int (*latency_tag_enable)(struct greybus_host_device *hd, u16 cport_id); - int (*latency_tag_disable)(struct greybus_host_device *hd, - u16 cport_id); + int (*latency_tag_enable)(struct gb_host_device *hd, u16 cport_id); + int (*latency_tag_disable)(struct gb_host_device *hd, u16 cport_id); }; -struct greybus_host_device { +struct gb_host_device { struct kref kref; struct device *parent; const struct greybus_host_driver *driver; @@ -52,10 +51,10 @@ struct greybus_host_device { unsigned long hd_priv[0] __aligned(sizeof(s64)); }; -struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *hd, +struct gb_host_device *greybus_create_hd(struct greybus_host_driver *hd, struct device *parent, size_t buffer_size_max, size_t num_cports); -void greybus_remove_hd(struct greybus_host_device *hd); +void greybus_remove_hd(struct gb_host_device *hd); #endif /* __HD_H */ diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 5d238d3..275a8c7 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -44,7 +44,7 @@ static DEFINE_SPINLOCK(gb_interfaces_lock); // FIXME, odds are you don't want to call this function, rework the caller to // not need it please. -struct gb_interface *gb_interface_find(struct greybus_host_device *hd, +struct gb_interface *gb_interface_find(struct gb_host_device *hd, u8 interface_id) { struct gb_interface *intf; @@ -120,7 +120,7 @@ int gb_create_bundle_connection(struct gb_interface *intf, u8 class) * Returns a pointer to the new interfce or a null pointer if a * failure occurs due to memory exhaustion. */ -struct gb_interface *gb_interface_create(struct greybus_host_device *hd, +struct gb_interface *gb_interface_create(struct gb_host_device *hd, u8 interface_id) { struct gb_module *module; @@ -199,7 +199,7 @@ void gb_interface_remove(struct gb_interface *intf) put_device(&module->dev); } -void gb_interfaces_remove(struct greybus_host_device *hd) +void gb_interfaces_remove(struct gb_host_device *hd) { struct gb_interface *intf, *temp; diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 9bce94f..248c991 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -16,7 +16,7 @@ struct gb_interface { struct gb_control *control; struct list_head bundles; - struct list_head links; /* greybus_host_device->interfaces */ + struct list_head links; /* gb_host_device->interfaces */ struct list_head manifest_descs; u8 interface_id; /* Physical location within the Endo */ u8 device_id; /* Device id allocated for the interface block by the SVC */ @@ -35,7 +35,7 @@ struct gb_interface { u32 ara_prod_id; struct gb_module *module; - struct greybus_host_device *hd; + struct gb_host_device *hd; /* The interface needs to boot over unipro */ bool boot_over_unipro; @@ -55,15 +55,15 @@ static inline void *gb_interface_get_drvdata(struct gb_interface *intf) /* Greybus "private" definitions */ -struct gb_interface *gb_interface_find(struct greybus_host_device *hd, +struct gb_interface *gb_interface_find(struct gb_host_device *hd, u8 interface_id); -struct gb_interface *gb_interface_create(struct greybus_host_device *hd, +struct gb_interface *gb_interface_create(struct gb_host_device *hd, u8 interface_id); void gb_interface_destroy(struct gb_interface *intf); int gb_interface_init(struct gb_interface *intf, u8 device_id); void gb_interface_remove(struct gb_interface *intf); -void gb_interfaces_remove(struct greybus_host_device *hd); +void gb_interfaces_remove(struct gb_host_device *hd); int gb_create_bundle_connection(struct gb_interface *intf, u8 class); #endif /* __INTERFACE_H */ diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index 43e8bab..e3d7a66 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -108,7 +108,7 @@ static int module_find(struct device *dev, void *data) * Search the list of modules in the system. If one is found, return it, with * the reference count incremented. */ -struct gb_module *gb_module_find(struct greybus_host_device *hd, u8 module_id) +struct gb_module *gb_module_find(struct gb_host_device *hd, u8 module_id) { struct device *dev; struct gb_module *module = NULL; diff --git a/drivers/staging/greybus/module.h b/drivers/staging/greybus/module.h index 3b3f421..2b36fe9 100644 --- a/drivers/staging/greybus/module.h +++ b/drivers/staging/greybus/module.h @@ -16,10 +16,10 @@ struct gb_module { }; #define to_gb_module(d) container_of(d, struct gb_module, dev) -struct greybus_host_device; +struct gb_host_device; /* Greybus "private" definitions */ -struct gb_module *gb_module_find(struct greybus_host_device *hd, u8 module_id); +struct gb_module *gb_module_find(struct gb_host_device *hd, u8 module_id); struct gb_module *gb_module_create(struct device *parent, u8 module_id); void gb_module_remove_all(struct gb_endo *endo); diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 3e29d21..1643880 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -210,7 +210,7 @@ static int gb_message_send(struct gb_message *message, gfp_t gfp) */ static void gb_message_cancel(struct gb_message *message) { - struct greybus_host_device *hd = message->operation->connection->hd; + struct gb_host_device *hd = message->operation->connection->hd; hd->driver->message_cancel(message); } @@ -269,7 +269,7 @@ static void gb_operation_work(struct work_struct *work) gb_operation_put(operation); } -static void gb_operation_message_init(struct greybus_host_device *hd, +static void gb_operation_message_init(struct gb_host_device *hd, struct gb_message *message, u16 operation_id, size_t payload_size, u8 type) { @@ -320,7 +320,7 @@ static void gb_operation_message_init(struct greybus_host_device *hd, * message payload / the message size */ static struct gb_message * -gb_operation_message_alloc(struct greybus_host_device *hd, u8 type, +gb_operation_message_alloc(struct gb_host_device *hd, u8 type, size_t payload_size, gfp_t gfp_flags) { struct gb_message *message; @@ -430,7 +430,7 @@ static u8 gb_operation_errno_map(int errno) bool gb_operation_response_alloc(struct gb_operation *operation, size_t response_size, gfp_t gfp) { - struct greybus_host_device *hd = operation->connection->hd; + struct gb_host_device *hd = operation->connection->hd; struct gb_operation_msg_hdr *request_header; struct gb_message *response; u8 type; @@ -482,7 +482,7 @@ gb_operation_create_common(struct gb_connection *connection, u8 type, size_t request_size, size_t response_size, unsigned long op_flags, gfp_t gfp_flags) { - struct greybus_host_device *hd = connection->hd; + struct gb_host_device *hd = connection->hd; struct gb_operation *operation; operation = kmem_cache_zalloc(gb_operation_cache, gfp_flags); @@ -548,7 +548,7 @@ EXPORT_SYMBOL_GPL(gb_operation_create); size_t gb_operation_get_payload_size_max(struct gb_connection *connection) { - struct greybus_host_device *hd = connection->hd; + struct gb_host_device *hd = connection->hd; return hd->buffer_size_max - sizeof(struct gb_operation_msg_hdr); } @@ -777,7 +777,7 @@ err_put: /* * This function is called when a message send request has completed. */ -void greybus_message_sent(struct greybus_host_device *hd, +void greybus_message_sent(struct gb_host_device *hd, struct gb_message *message, int status) { struct gb_operation *operation = message->operation; diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 0f44ec8..c3f7ce7 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -150,7 +150,7 @@ gb_operation_request_send_sync(struct gb_operation *operation) void gb_operation_cancel(struct gb_operation *operation, int errno); void gb_operation_cancel_incoming(struct gb_operation *operation, int errno); -void greybus_message_sent(struct greybus_host_device *hd, +void greybus_message_sent(struct gb_host_device *hd, struct gb_message *message, int status); int gb_operation_sync_timeout(struct gb_connection *connection, int type, diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index e5cd897..c2633e2 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -42,7 +42,7 @@ struct svc_hotplug { * This is a temporary connection, used only at initial bootup. */ struct gb_connection * -gb_ap_svc_connection_create(struct greybus_host_device *hd) +gb_ap_svc_connection_create(struct gb_host_device *hd) { struct gb_connection *connection; @@ -61,7 +61,7 @@ gb_ap_svc_connection_create(struct greybus_host_device *hd) * 'partially' initialized one svc connection. */ static struct gb_interface * -gb_ap_interface_create(struct greybus_host_device *hd, +gb_ap_interface_create(struct gb_host_device *hd, struct gb_connection *connection, u8 interface_id) { struct gb_interface *intf; @@ -183,7 +183,7 @@ EXPORT_SYMBOL_GPL(gb_svc_dme_peer_set); */ static int gb_svc_read_and_clear_module_boot_status(struct gb_interface *intf) { - struct greybus_host_device *hd = intf->hd; + struct gb_host_device *hd = intf->hd; int ret; u32 value; @@ -338,7 +338,7 @@ static int gb_svc_version_request(struct gb_operation *op) static int gb_svc_hello(struct gb_operation *op) { struct gb_connection *connection = op->connection; - struct greybus_host_device *hd = connection->hd; + struct gb_host_device *hd = connection->hd; struct gb_svc_hello_request *hello_request; struct gb_interface *intf; u16 endo_id; @@ -381,7 +381,7 @@ static int gb_svc_hello(struct gb_operation *op) static void svc_intf_remove(struct gb_connection *connection, struct gb_interface *intf) { - struct greybus_host_device *hd = connection->hd; + struct gb_host_device *hd = connection->hd; struct gb_svc *svc = connection->private; u8 intf_id = intf->interface_id; u8 device_id; @@ -408,7 +408,7 @@ static void svc_process_hotplug(struct work_struct *work) struct gb_svc_intf_hotplug_request *hotplug = &svc_hotplug->data; struct gb_connection *connection = svc_hotplug->connection; struct gb_svc *svc = connection->private; - struct greybus_host_device *hd = connection->hd; + struct gb_host_device *hd = connection->hd; struct gb_interface *intf; u8 intf_id, device_id; int ret; @@ -552,7 +552,7 @@ static int gb_svc_intf_hot_unplug_recv(struct gb_operation *op) { struct gb_message *request = op->request; struct gb_svc_intf_hot_unplug_request *hot_unplug = request->payload; - struct greybus_host_device *hd = op->connection->hd; + struct gb_host_device *hd = op->connection->hd; struct gb_interface *intf; u8 intf_id; diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index 3357d31..d2f406f 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -25,6 +25,6 @@ int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, int gb_svc_protocol_init(void); void gb_svc_protocol_exit(void); -struct gb_connection * -gb_ap_svc_connection_create(struct greybus_host_device *hd); +struct gb_connection *gb_ap_svc_connection_create(struct gb_host_device *hd); + #endif /* __SVC_H */ -- cgit v0.10.2 From a8cc020f3f8ec684f0c48d30524ae8198b56038b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 3 Nov 2015 18:03:24 +0100 Subject: greybus: hd: rename host-driver structure Rename host-driver structure to gb_hd_driver to more clearly separate it from the host-device structure. Also remove an outdated description of the struct. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 07e1a14..0156db2 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -325,7 +325,7 @@ static int latency_tag_disable(struct gb_host_device *hd, u16 cport_id) return retval; } -static struct greybus_host_driver es1_driver = { +static struct gb_hd_driver es1_driver = { .hd_priv_size = sizeof(struct es1_ap_dev), .message_send = message_send, .message_cancel = message_cancel, diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 8860f60..903e321 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -471,7 +471,7 @@ static int latency_tag_disable(struct gb_host_device *hd, u16 cport_id) return retval; } -static struct greybus_host_driver es2_driver = { +static struct gb_hd_driver es2_driver = { .hd_priv_size = sizeof(struct es2_ap_dev), .message_send = message_send, .message_cancel = message_cancel, diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index a09a920..910e1d2 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -28,7 +28,7 @@ static void free_hd(struct kref *kref) mutex_unlock(&hd_mutex); } -struct gb_host_device *greybus_create_hd(struct greybus_host_driver *driver, +struct gb_host_device *greybus_create_hd(struct gb_hd_driver *driver, struct device *parent, size_t buffer_size_max, size_t num_cports) @@ -40,7 +40,7 @@ struct gb_host_device *greybus_create_hd(struct greybus_host_driver *driver, * so that we don't have to every time we make them. */ if ((!driver->message_send) || (!driver->message_cancel)) { - pr_err("Must implement all greybus_host_driver callbacks!\n"); + pr_err("Must implement all gb_hd_driver callbacks!\n"); return ERR_PTR(-EINVAL); } diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h index 122790d..7aea0c5 100644 --- a/drivers/staging/greybus/hd.h +++ b/drivers/staging/greybus/hd.h @@ -13,10 +13,7 @@ struct gb_host_device; struct gb_message; -/* Greybus "Host driver" structure, needed by a host controller driver to be - * able to handle both SVC control as well as "real" greybus messages - */ -struct greybus_host_driver { +struct gb_hd_driver { size_t hd_priv_size; int (*cport_enable)(struct gb_host_device *hd, u16 cport_id); @@ -31,7 +28,7 @@ struct greybus_host_driver { struct gb_host_device { struct kref kref; struct device *parent; - const struct greybus_host_driver *driver; + const struct gb_hd_driver *driver; struct list_head interfaces; struct list_head connections; @@ -51,7 +48,7 @@ struct gb_host_device { unsigned long hd_priv[0] __aligned(sizeof(s64)); }; -struct gb_host_device *greybus_create_hd(struct greybus_host_driver *hd, +struct gb_host_device *greybus_create_hd(struct gb_hd_driver *driver, struct device *parent, size_t buffer_size_max, size_t num_cports); -- cgit v0.10.2 From d6e139bc15118ceb9173ee03e3f2db63b57e0f77 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 3 Nov 2015 18:03:25 +0100 Subject: greybus: hd: use common prefix for exported functions Rename the exported functions using the common gb_-prefix. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 0156db2..2386087 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -396,7 +396,7 @@ static void ap_disconnect(struct usb_interface *interface) usb_set_intfdata(interface, NULL); udev = es1->usb_dev; - greybus_remove_hd(es1->hd); + gb_hd_remove(es1->hd); usb_put_dev(udev); } @@ -613,8 +613,8 @@ static int ap_probe(struct usb_interface *interface, udev = usb_get_dev(interface_to_usbdev(interface)); - hd = greybus_create_hd(&es1_driver, &udev->dev, ES1_GBUF_MSG_SIZE_MAX, - CPORT_COUNT); + hd = gb_hd_create(&es1_driver, &udev->dev, ES1_GBUF_MSG_SIZE_MAX, + CPORT_COUNT); if (IS_ERR(hd)) { usb_put_dev(udev); return PTR_ERR(hd); diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 903e321..1e786a6 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -548,7 +548,7 @@ static void ap_disconnect(struct usb_interface *interface) usb_set_intfdata(interface, NULL); udev = es2->usb_dev; - greybus_remove_hd(es2->hd); + gb_hd_remove(es2->hd); kfree(es2->cport_to_ep); usb_put_dev(udev); @@ -807,8 +807,8 @@ static int ap_probe(struct usb_interface *interface, return num_cports; } - hd = greybus_create_hd(&es2_driver, &udev->dev, ES2_GBUF_MSG_SIZE_MAX, - num_cports); + hd = gb_hd_create(&es2_driver, &udev->dev, ES2_GBUF_MSG_SIZE_MAX, + num_cports); if (IS_ERR(hd)) { usb_put_dev(udev); return PTR_ERR(hd); diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index 910e1d2..6f29eb4 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -28,10 +28,10 @@ static void free_hd(struct kref *kref) mutex_unlock(&hd_mutex); } -struct gb_host_device *greybus_create_hd(struct gb_hd_driver *driver, - struct device *parent, - size_t buffer_size_max, - size_t num_cports) +struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, + struct device *parent, + size_t buffer_size_max, + size_t num_cports) { struct gb_host_device *hd; @@ -94,9 +94,9 @@ struct gb_host_device *greybus_create_hd(struct gb_hd_driver *driver, return hd; } -EXPORT_SYMBOL_GPL(greybus_create_hd); +EXPORT_SYMBOL_GPL(gb_hd_create); -void greybus_remove_hd(struct gb_host_device *hd) +void gb_hd_remove(struct gb_host_device *hd) { /* * Tear down all interfaces, modules, and the endo that is associated @@ -112,4 +112,4 @@ void greybus_remove_hd(struct gb_host_device *hd) kref_put_mutex(&hd->kref, free_hd, &hd_mutex); } -EXPORT_SYMBOL_GPL(greybus_remove_hd); +EXPORT_SYMBOL_GPL(gb_hd_remove); diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h index 7aea0c5..91fcccb 100644 --- a/drivers/staging/greybus/hd.h +++ b/drivers/staging/greybus/hd.h @@ -48,10 +48,10 @@ struct gb_host_device { unsigned long hd_priv[0] __aligned(sizeof(s64)); }; -struct gb_host_device *greybus_create_hd(struct gb_hd_driver *driver, - struct device *parent, - size_t buffer_size_max, - size_t num_cports); -void greybus_remove_hd(struct gb_host_device *hd); +struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, + struct device *parent, + size_t buffer_size_max, + size_t num_cports); +void gb_hd_remove(struct gb_host_device *hd); #endif /* __HD_H */ -- cgit v0.10.2 From ddc88eff2b0848e9c95bc4c39b53c52ed7991285 Mon Sep 17 00:00:00 2001 From: Mark Greer Date: Wed, 4 Nov 2015 09:47:21 -0700 Subject: greybus: audio: Remove I2S Bridged-PHY Protcol based audio driver The Greybus I2S Bridged-PHY Protocol is now deprecated so remove the audio driver that is based on it. CC: Vaibhav Agarwal Signed-off-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index ba60430..cf4cf21 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -21,11 +21,7 @@ gb-phy-y := gpbridge.o \ hid.o \ i2c.o \ spi.o \ - usb.o \ - audio.o \ - audio-pcm.o \ - audio-dai.o \ - audio-gb-cmds.o + usb.o # Prefix all modules with gb- gb-vibrator-y := vibrator.o diff --git a/drivers/staging/greybus/audio-dai.c b/drivers/staging/greybus/audio-dai.c deleted file mode 100644 index 9b162bf..0000000 --- a/drivers/staging/greybus/audio-dai.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Greybus audio Digital Audio Interface (DAI) driver - * - * Copyright 2015 Google Inc. - * Copyright 2015 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "greybus.h" -#include "audio.h" - -/* - * This is the greybus cpu dai logic. It really doesn't do much - * other then provide the TRIGGER_START/STOP hooks that start - * and stop the timer sending audio data in the pcm logic. - */ - - -static int gb_dai_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct gb_snd *snd_dev; - - - snd_dev = snd_soc_dai_get_drvdata(rtd->cpu_dai); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - gb_pcm_hrtimer_start(snd_dev); - break; - case SNDRV_PCM_TRIGGER_STOP: - gb_pcm_hrtimer_stop(snd_dev); - break; - default: - return -EINVAL; - } - return 0; -} - -/* - * XXX This is annoying, if we don't have a set_fmt function - * the subsystem returns -ENOTSUPP, which causes applications - * to fail, so add a dummy function here. - */ -static int gb_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) -{ - return 0; -} - -static const struct snd_soc_dai_ops gb_dai_ops = { - .trigger = gb_dai_trigger, - .set_fmt = gb_dai_set_fmt, -}; - -static struct snd_soc_dai_driver gb_cpu_dai = { - .name = "gb-cpu-dai", - .playback = { - .rates = GB_RATES, - .formats = GB_FMTS, - .channels_min = 1, - .channels_max = 2, - }, - .ops = &gb_dai_ops, -}; - -static const struct snd_soc_component_driver gb_soc_component = { - .name = "gb-component", -}; - -static int gb_plat_probe(struct platform_device *pdev) -{ - struct gb_snd *snd_dev; - int ret; - - snd_dev = (struct gb_snd *)pdev->dev.platform_data; - dev_set_drvdata(&pdev->dev, snd_dev); - - ret = snd_soc_register_component(&pdev->dev, &gb_soc_component, - &gb_cpu_dai, 1); - return ret; -} - -static int gb_plat_remove(struct platform_device *pdev) -{ - snd_soc_unregister_component(&pdev->dev); - snd_soc_unregister_platform(&pdev->dev); - return 0; -} - -struct platform_driver gb_audio_plat_driver = { - .driver = { - .name = "gb-dai-audio", - }, - .probe = gb_plat_probe, - .remove = gb_plat_remove, -}; diff --git a/drivers/staging/greybus/audio-gb-cmds.c b/drivers/staging/greybus/audio-gb-cmds.c deleted file mode 100644 index 112aed9..0000000 --- a/drivers/staging/greybus/audio-gb-cmds.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Greybus audio commands - * - * Copyright 2015 Google Inc. - * Copyright 2015 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#include - -#include "greybus.h" -#include "audio.h" - -/*********************************** - * GB I2S helper functions - ***********************************/ -int gb_i2s_mgmt_activate_cport(struct gb_connection *connection, - uint16_t cport) -{ - struct gb_i2s_mgmt_activate_cport_request request; - - memset(&request, 0, sizeof(request)); - request.cport = cpu_to_le16(cport); - - return gb_operation_sync(connection, GB_I2S_MGMT_TYPE_ACTIVATE_CPORT, - &request, sizeof(request), NULL, 0); -} - -int gb_i2s_mgmt_deactivate_cport(struct gb_connection *connection, - uint16_t cport) -{ - struct gb_i2s_mgmt_deactivate_cport_request request; - - memset(&request, 0, sizeof(request)); - request.cport = cpu_to_le16(cport); - - return gb_operation_sync(connection, GB_I2S_MGMT_TYPE_DEACTIVATE_CPORT, - &request, sizeof(request), NULL, 0); -} - -int gb_i2s_mgmt_get_supported_configurations( - struct gb_connection *connection, - struct gb_i2s_mgmt_get_supported_configurations_response *get_cfg, - size_t size) -{ - return gb_operation_sync(connection, - GB_I2S_MGMT_TYPE_GET_SUPPORTED_CONFIGURATIONS, - NULL, 0, get_cfg, size); -} - -int gb_i2s_mgmt_set_configuration(struct gb_connection *connection, - struct gb_i2s_mgmt_set_configuration_request *set_cfg) -{ - return gb_operation_sync(connection, GB_I2S_MGMT_TYPE_SET_CONFIGURATION, - set_cfg, sizeof(*set_cfg), NULL, 0); -} - -int gb_i2s_mgmt_set_samples_per_message( - struct gb_connection *connection, - uint16_t samples_per_message) -{ - struct gb_i2s_mgmt_set_samples_per_message_request request; - - memset(&request, 0, sizeof(request)); - request.samples_per_message = cpu_to_le16(samples_per_message); - - return gb_operation_sync(connection, - GB_I2S_MGMT_TYPE_SET_SAMPLES_PER_MESSAGE, - &request, sizeof(request), NULL, 0); -} - -int gb_i2s_mgmt_get_cfgs(struct gb_snd *snd_dev, - struct gb_connection *connection) -{ - struct gb_i2s_mgmt_get_supported_configurations_response *get_cfg; - size_t size; - int ret; - - size = sizeof(*get_cfg) + - (CONFIG_COUNT_MAX * sizeof(get_cfg->config[0])); - - get_cfg = kzalloc(size, GFP_KERNEL); - if (!get_cfg) - return -ENOMEM; - - ret = gb_i2s_mgmt_get_supported_configurations(connection, get_cfg, - size); - if (ret) { - pr_err("get_supported_config failed: %d\n", ret); - goto err_free_get_cfg; - } - - snd_dev->i2s_configs = get_cfg; - - return 0; - -err_free_get_cfg: - kfree(get_cfg); - return ret; -} - -void gb_i2s_mgmt_free_cfgs(struct gb_snd *snd_dev) -{ - kfree(snd_dev->i2s_configs); - snd_dev->i2s_configs = NULL; -} - -int gb_i2s_mgmt_set_cfg(struct gb_snd *snd_dev, int rate, int chans, - int bytes_per_chan, int is_le) -{ - struct gb_i2s_mgmt_set_configuration_request set_cfg; - struct gb_i2s_mgmt_configuration *cfg; - int i, ret; - u8 byte_order = GB_I2S_MGMT_BYTE_ORDER_NA; - - if (bytes_per_chan > 1) { - if (is_le) - byte_order = GB_I2S_MGMT_BYTE_ORDER_LE; - else - byte_order = GB_I2S_MGMT_BYTE_ORDER_BE; - } - - for (i = 0, cfg = snd_dev->i2s_configs->config; - i < CONFIG_COUNT_MAX; - i++, cfg++) { - if ((cfg->sample_frequency == cpu_to_le32(rate)) && - (cfg->num_channels == chans) && - (cfg->bytes_per_channel == bytes_per_chan) && - (cfg->byte_order & byte_order) && - (cfg->ll_protocol & - cpu_to_le32(GB_I2S_MGMT_PROTOCOL_I2S)) && - (cfg->ll_mclk_role & GB_I2S_MGMT_ROLE_MASTER) && - (cfg->ll_bclk_role & GB_I2S_MGMT_ROLE_MASTER) && - (cfg->ll_wclk_role & GB_I2S_MGMT_ROLE_MASTER) && - (cfg->ll_wclk_polarity & GB_I2S_MGMT_POLARITY_NORMAL) && - (cfg->ll_wclk_change_edge & GB_I2S_MGMT_EDGE_FALLING) && - (cfg->ll_wclk_tx_edge & GB_I2S_MGMT_EDGE_RISING) && - (cfg->ll_wclk_rx_edge & GB_I2S_MGMT_EDGE_FALLING) && - (cfg->ll_data_offset == 1)) - break; - } - - if (i >= CONFIG_COUNT_MAX) { - pr_err("No valid configuration\n"); - return -EINVAL; - } - - memcpy(&set_cfg, cfg, sizeof(set_cfg)); - set_cfg.config.byte_order = byte_order; - set_cfg.config.ll_protocol = cpu_to_le32(GB_I2S_MGMT_PROTOCOL_I2S); - set_cfg.config.ll_mclk_role = GB_I2S_MGMT_ROLE_MASTER; - set_cfg.config.ll_bclk_role = GB_I2S_MGMT_ROLE_MASTER; - set_cfg.config.ll_wclk_role = GB_I2S_MGMT_ROLE_MASTER; - set_cfg.config.ll_wclk_polarity = GB_I2S_MGMT_POLARITY_NORMAL; - set_cfg.config.ll_wclk_change_edge = GB_I2S_MGMT_EDGE_FALLING; - set_cfg.config.ll_wclk_tx_edge = GB_I2S_MGMT_EDGE_RISING; - set_cfg.config.ll_wclk_rx_edge = GB_I2S_MGMT_EDGE_FALLING; - - ret = gb_i2s_mgmt_set_configuration(snd_dev->mgmt_connection, &set_cfg); - if (ret) - pr_err("set_configuration failed: %d\n", ret); - - return ret; -} - -int gb_i2s_send_data(struct gb_connection *connection, - void *req_buf, void *source_addr, - size_t len, int sample_num) -{ - struct gb_i2s_send_data_request *gb_req; - int ret; - - gb_req = req_buf; - gb_req->sample_number = cpu_to_le32(sample_num); - - memcpy((void *)&gb_req->data[0], source_addr, len); - - if (len < MAX_SEND_DATA_LEN) - for (; len < MAX_SEND_DATA_LEN; len++) - gb_req->data[len] = gb_req->data[len - SAMPLE_SIZE]; - - gb_req->size = cpu_to_le32(len); - - ret = gb_operation_sync(connection, GB_I2S_DATA_TYPE_SEND_DATA, - (void *) gb_req, SEND_DATA_BUF_LEN, NULL, 0); - return ret; -} diff --git a/drivers/staging/greybus/audio-pcm.c b/drivers/staging/greybus/audio-pcm.c deleted file mode 100644 index e62152a..0000000 --- a/drivers/staging/greybus/audio-pcm.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - * Greybus audio Pulse Code Modulation (PCM) driver - * - * Copyright 2015 Google Inc. - * Copyright 2015 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "greybus.h" -#include "audio.h" - -/* - * timer/workqueue logic for pushing pcm data. - * - * Since when we are playing audio, we don't get any - * status or feedback from the codec, we have to use a - * hrtimer to trigger sending data to the remote codec. - * However since the hrtimer runs in irq context, so we - * have to schedule a workqueue to actually send the - * greybus data. - */ - -static void gb_pcm_work(struct work_struct *work) -{ - struct gb_snd *snd_dev = container_of(work, struct gb_snd, work); - struct snd_pcm_substream *substream = snd_dev->substream; - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int stride, frames, oldptr; - int period_elapsed, ret; - char *address; - long len; - - if (!snd_dev) - return; - - if (!atomic_read(&snd_dev->running)) { - if (snd_dev->cport_active) { - ret = gb_i2s_mgmt_deactivate_cport( - snd_dev->mgmt_connection, - snd_dev->i2s_tx_connection->intf_cport_id); - if (ret) /* XXX Do what else with failure? */ - pr_err("deactivate_cport failed: %d\n", ret); - - snd_dev->cport_active = false; - snd_dev->send_data_sample_count = 0; - } - - return; - } else if (!snd_dev->cport_active) { - ret = gb_i2s_mgmt_activate_cport(snd_dev->mgmt_connection, - snd_dev->i2s_tx_connection->intf_cport_id); - if (ret) - pr_err("activate_cport failed: %d\n", ret); - - snd_dev->cport_active = true; - } - - address = runtime->dma_area + snd_dev->hwptr_done; - - len = frames_to_bytes(runtime, - runtime->buffer_size) - snd_dev->hwptr_done; - len = min(len, MAX_SEND_DATA_LEN); - gb_i2s_send_data(snd_dev->i2s_tx_connection, snd_dev->send_data_req_buf, - address, len, snd_dev->send_data_sample_count); - - snd_dev->send_data_sample_count += CONFIG_SAMPLES_PER_MSG; - - stride = runtime->frame_bits >> 3; - frames = len/stride; - - snd_pcm_stream_lock(substream); - oldptr = snd_dev->hwptr_done; - snd_dev->hwptr_done += len; - if (snd_dev->hwptr_done >= runtime->buffer_size * stride) - snd_dev->hwptr_done -= runtime->buffer_size * stride; - - frames = (len + (oldptr % stride)) / stride; - - period_elapsed = 0; - snd_dev->transfer_done += frames; - if (snd_dev->transfer_done >= runtime->period_size) { - snd_dev->transfer_done -= runtime->period_size; - period_elapsed = 1; - } - - snd_pcm_stream_unlock(substream); - if (period_elapsed) - snd_pcm_period_elapsed(snd_dev->substream); -} - -static enum hrtimer_restart gb_pcm_timer_function(struct hrtimer *hrtimer) -{ - struct gb_snd *snd_dev = container_of(hrtimer, struct gb_snd, timer); - - if (!atomic_read(&snd_dev->running)) - return HRTIMER_NORESTART; - queue_work(snd_dev->workqueue, &snd_dev->work); - hrtimer_forward_now(hrtimer, ns_to_ktime(CONFIG_PERIOD_NS)); - return HRTIMER_RESTART; -} - -void gb_pcm_hrtimer_start(struct gb_snd *snd_dev) -{ - atomic_set(&snd_dev->running, 1); - queue_work(snd_dev->workqueue, &snd_dev->work); /* Activates CPort */ - hrtimer_start(&snd_dev->timer, ns_to_ktime(CONFIG_PERIOD_NS), - HRTIMER_MODE_REL); -} - -void gb_pcm_hrtimer_stop(struct gb_snd *snd_dev) -{ - atomic_set(&snd_dev->running, 0); - hrtimer_cancel(&snd_dev->timer); - queue_work(snd_dev->workqueue, &snd_dev->work); /* Deactivates CPort */ -} - -static int gb_pcm_hrtimer_init(struct gb_snd *snd_dev) -{ - hrtimer_init(&snd_dev->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - snd_dev->timer.function = gb_pcm_timer_function; - atomic_set(&snd_dev->running, 0); - snd_dev->workqueue = alloc_workqueue("gb-audio", WQ_HIGHPRI, 0); - if (!snd_dev->workqueue) - return -ENOMEM; - INIT_WORK(&snd_dev->work, gb_pcm_work); - return 0; -} - - -/* - * Core gb pcm structure - */ -static struct snd_pcm_hardware gb_plat_pcm_hardware = { - .info = SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID, - .formats = GB_FMTS, - .rates = GB_RATES, - .rate_min = 8000, - .rate_max = GB_SAMPLE_RATE, - .channels_min = 1, - .channels_max = 2, - /* XXX - All the values below are junk */ - .buffer_bytes_max = 64 * 1024, - .period_bytes_min = 32, - .period_bytes_max = 8192, - .periods_min = 2, - .periods_max = 32, -}; - -static snd_pcm_uframes_t gb_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct gb_snd *snd_dev; - - snd_dev = snd_soc_dai_get_drvdata(rtd->cpu_dai); - - return snd_dev->hwptr_done / (substream->runtime->frame_bits >> 3); -} - -static int gb_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct gb_snd *snd_dev; - - snd_dev = snd_soc_dai_get_drvdata(rtd->cpu_dai); - snd_dev->hwptr_done = 0; - snd_dev->transfer_done = 0; - return 0; -} - -static unsigned int rates[] = {GB_SAMPLE_RATE}; -static struct snd_pcm_hw_constraint_list constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, -}; - -static int gb_pcm_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct gb_snd *snd_dev; - unsigned long flags; - int ret; - - snd_dev = snd_soc_dai_get_drvdata(rtd->cpu_dai); - - spin_lock_irqsave(&snd_dev->lock, flags); - runtime->private_data = snd_dev; - snd_dev->substream = substream; - ret = gb_pcm_hrtimer_init(snd_dev); - spin_unlock_irqrestore(&snd_dev->lock, flags); - - if (ret) - return ret; - - snd_soc_set_runtime_hwparams(substream, &gb_plat_pcm_hardware); - - ret = snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - &constraints_rates); - if (ret < 0) - return ret; - - return snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS); -} - -static int gb_pcm_close(struct snd_pcm_substream *substream) -{ - substream->runtime->private_data = NULL; - return 0; -} - -static int gb_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct gb_snd *snd_dev; - int rate, chans, bytes_per_chan, is_le, ret; - - snd_dev = snd_soc_dai_get_drvdata(rtd->cpu_dai); - - rate = params_rate(hw_params); - chans = params_channels(hw_params); - bytes_per_chan = snd_pcm_format_width(params_format(hw_params)) / 8; - is_le = snd_pcm_format_little_endian(params_format(hw_params)); - - ret = gb_i2s_mgmt_set_cfg(snd_dev, rate, chans, bytes_per_chan, is_le); - if (ret) - return ret; - - return snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); -} - -static int gb_pcm_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static struct snd_pcm_ops gb_pcm_ops = { - .open = gb_pcm_open, - .close = gb_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = gb_pcm_hw_params, - .hw_free = gb_pcm_hw_free, - .prepare = gb_pcm_prepare, - .pointer = gb_pcm_pointer, -}; - -static void gb_pcm_free(struct snd_pcm *pcm) -{ - snd_pcm_lib_preallocate_free_for_all(pcm); -} - -static int gb_pcm_new(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_pcm *pcm = rtd->pcm; - - return snd_pcm_lib_preallocate_pages_for_all( - pcm, - SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), - PREALLOC_BUFFER, PREALLOC_BUFFER_MAX); -} - -static struct snd_soc_platform_driver gb_soc_platform = { - .ops = &gb_pcm_ops, - .pcm_new = gb_pcm_new, - .pcm_free = gb_pcm_free, -}; - -static int gb_soc_platform_probe(struct platform_device *pdev) -{ - return snd_soc_register_platform(&pdev->dev, &gb_soc_platform); -} - -static int gb_soc_platform_remove(struct platform_device *pdev) -{ - snd_soc_unregister_platform(&pdev->dev); - return 0; -} - -struct platform_driver gb_audio_pcm_driver = { - .driver = { - .name = "gb-pcm-audio", - .owner = THIS_MODULE, - }, - .probe = gb_soc_platform_probe, - .remove = gb_soc_platform_remove, -}; diff --git a/drivers/staging/greybus/audio.c b/drivers/staging/greybus/audio.c deleted file mode 100644 index 684229c..0000000 --- a/drivers/staging/greybus/audio.c +++ /dev/null @@ -1,470 +0,0 @@ -/* - * Greybus audio driver - * - * Copyright 2015 Google Inc. - * Copyright 2015 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "greybus.h" -#include "audio.h" - - -#define GB_AUDIO_DATA_DRIVER_NAME "gb_audio_data" -#define GB_AUDIO_MGMT_DRIVER_NAME "gb_audio_mgmt" - -#define RT5647_I2C_ADAPTER_NR 6 -#define RT5647_I2C_ADDR 0x1b - -/* - * gb_snd management functions - */ -static DEFINE_SPINLOCK(gb_snd_list_lock); -static LIST_HEAD(gb_snd_list); -static int device_count; - -static struct gb_snd *gb_find_snd(int bundle_id) -{ - struct gb_snd *tmp, *ret = NULL; - unsigned long flags; - - spin_lock_irqsave(&gb_snd_list_lock, flags); - list_for_each_entry(tmp, &gb_snd_list, list) - if (tmp->gb_bundle_id == bundle_id) { - ret = tmp; - break; - } - spin_unlock_irqrestore(&gb_snd_list_lock, flags); - return ret; -} - -static struct gb_snd *gb_get_snd(int bundle_id) -{ - struct gb_snd *snd_dev; - unsigned long flags; - - snd_dev = gb_find_snd(bundle_id); - if (snd_dev) - return snd_dev; - - snd_dev = kzalloc(sizeof(*snd_dev), GFP_KERNEL); - if (!snd_dev) - return NULL; - - spin_lock_init(&snd_dev->lock); - snd_dev->device_count = device_count++; - snd_dev->gb_bundle_id = bundle_id; - spin_lock_irqsave(&gb_snd_list_lock, flags); - list_add(&snd_dev->list, &gb_snd_list); - spin_unlock_irqrestore(&gb_snd_list_lock, flags); - return snd_dev; -} - -static void gb_free_snd(struct gb_snd *snd) -{ - unsigned long flags; - - spin_lock_irqsave(&gb_snd_list_lock, flags); - if (!snd->i2s_tx_connection && - !snd->mgmt_connection) { - list_del(&snd->list); - spin_unlock_irqrestore(&gb_snd_list_lock, flags); - kfree(snd); - } else { - spin_unlock_irqrestore(&gb_snd_list_lock, flags); - } -} - - - - -/* - * This is the ASoC simple card binds the platform codec, - * cpu-dai and codec-dai togheter - */ -struct gb_card_info_object { - struct asoc_simple_card_info card_info; - char codec_name[255]; - char platform_name[255]; - char dai_name[255]; -}; - - -static struct asoc_simple_card_info *setup_card_info(int device_count) -{ - struct gb_card_info_object *obj; - - obj = kzalloc(sizeof(struct gb_card_info_object), GFP_KERNEL); - if (!obj) - return NULL; - - obj->card_info.name = "Greybus Audio Module"; - obj->card_info.card = "gb-card"; - obj->card_info.codec = obj->codec_name; - obj->card_info.platform = obj->platform_name; - obj->card_info.cpu_dai.name = obj->dai_name; -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0) - obj->card_info.cpu_dai.fmt = SND_SOC_DAIFMT_CBM_CFM; -#endif -#if USE_RT5645 - obj->card_info.daifmt = SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_I2S; - sprintf(obj->codec_name, "rt5645.%d-%04x", RT5647_I2C_ADAPTER_NR, - RT5647_I2C_ADDR); - obj->card_info.codec_dai.name = "rt5645-aif1"; -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0) - obj->card_info.codec_dai.fmt = SND_SOC_DAIFMT_CBS_CFS; -#endif - obj->card_info.codec_dai.sysclk = 12288000; -#else - sprintf(obj->codec_name, "spdif-dit"); - obj->card_info.codec_dai.name = "dit-hifi"; -#endif - sprintf(obj->platform_name, "gb-pcm-audio.%i", device_count); - sprintf(obj->dai_name, "gb-dai-audio.%i", device_count); - - return &obj->card_info; -} - -static void free_card_info(struct asoc_simple_card_info *ci) -{ - struct gb_card_info_object *obj; - - obj = container_of(ci, struct gb_card_info_object, card_info); - kfree(obj); -} - - -/* - * XXX this is sort of cruddy but I get warnings if - * we don't have dev.release handler set. - */ -static void default_release(struct device *dev) -{ -} - -/* - * GB connection hooks - */ -static int gb_i2s_transmitter_connection_init(struct gb_connection *connection) -{ - struct gb_snd *snd_dev; - struct platform_device *codec, *dai; - struct asoc_simple_card_info *simple_card; -#if USE_RT5645 - struct i2c_board_info rt5647_info; - struct i2c_adapter *i2c_adap; -#endif - unsigned long flags; - int ret; - - snd_dev = gb_get_snd(connection->bundle->id); - if (!snd_dev) - return -ENOMEM; - - codec = platform_device_register_simple("spdif-dit", -1, NULL, 0); - if (!codec) { - ret = -ENOMEM; - goto out; - } - - dai = platform_device_register_simple("gb-pcm-audio", snd_dev->device_count, NULL, 0); - if (!dai) { - ret = -ENOMEM; - goto out; - } - - simple_card = setup_card_info(snd_dev->device_count); - if (!simple_card) { - ret = -ENOMEM; - goto out; - } - - spin_lock_irqsave(&snd_dev->lock, flags); - snd_dev->card.name = "asoc-simple-card"; - snd_dev->card.id = snd_dev->device_count; - snd_dev->card.dev.release = default_release; /* XXX - suspicious */ - - snd_dev->cpu_dai.name = "gb-dai-audio"; - snd_dev->cpu_dai.id = snd_dev->device_count; - snd_dev->cpu_dai.dev.release = default_release; /* XXX - suspicious */ - - - snd_dev->simple_card_info = simple_card; - snd_dev->card.dev.platform_data = simple_card; - - snd_dev->codec = codec; - snd_dev->i2s_tx_connection = connection; - snd_dev->cpu_dai.dev.platform_data = snd_dev; - snd_dev->i2s_tx_connection->private = snd_dev; - spin_unlock_irqrestore(&snd_dev->lock, flags); - - ret = platform_device_register(&snd_dev->cpu_dai); - if (ret) { - pr_err("cpu_dai platform_device register failed\n"); - goto out_dai; - } - - ret = platform_device_register(&snd_dev->card); - if (ret) { - pr_err("card platform_device register failed\n"); - goto out_card; - } - -#if USE_RT5645 - rt5647_info.addr = RT5647_I2C_ADDR; - strlcpy(rt5647_info.type, "rt5647", I2C_NAME_SIZE); - - i2c_adap = i2c_get_adapter(RT5647_I2C_ADAPTER_NR); - if (!i2c_adap) { - pr_err("codec unavailable\n"); - ret = -ENODEV; - goto out_get_ver; - } - - snd_dev->rt5647 = i2c_new_device(i2c_adap, &rt5647_info); - if (!snd_dev->rt5647) { - pr_err("can't create rt5647 i2c device\n"); - goto out_get_ver; - } -#endif - - return 0; - -#if USE_RT5645 -out_get_ver: - platform_device_unregister(&snd_dev->card); -#endif -out_card: - platform_device_unregister(&snd_dev->cpu_dai); -out_dai: - platform_device_unregister(codec); -out: - gb_free_snd(snd_dev); - return ret; -} - -static void gb_i2s_transmitter_connection_exit(struct gb_connection *connection) -{ - struct gb_snd *snd_dev; - - snd_dev = (struct gb_snd *)connection->private; - -#if USE_RT5645 - i2c_unregister_device(snd_dev->rt5647); -#endif - - platform_device_unregister(&snd_dev->card); - platform_device_unregister(&snd_dev->cpu_dai); - platform_device_unregister(snd_dev->codec); - - free_card_info(snd_dev->simple_card_info); - snd_dev->i2s_tx_connection = NULL; - gb_free_snd(snd_dev); -} - -static int gb_i2s_mgmt_connection_init(struct gb_connection *connection) -{ - struct gb_snd *snd_dev; - unsigned long flags; - int ret; - - snd_dev = gb_get_snd(connection->bundle->id); - if (!snd_dev) - return -ENOMEM; - - spin_lock_irqsave(&snd_dev->lock, flags); - snd_dev->mgmt_connection = connection; - connection->private = snd_dev; - spin_unlock_irqrestore(&snd_dev->lock, flags); - - ret = gb_i2s_mgmt_get_cfgs(snd_dev, connection); - if (ret) { - pr_err("can't get i2s configurations: %d\n", ret); - goto err_free_snd_dev; - } - - ret = gb_i2s_mgmt_set_samples_per_message(snd_dev->mgmt_connection, - CONFIG_SAMPLES_PER_MSG); - if (ret) { - pr_err("set_samples_per_msg failed: %d\n", ret); - goto err_free_i2s_configs; - } - - snd_dev->send_data_req_buf = kzalloc(SEND_DATA_BUF_LEN, GFP_KERNEL); - - if (!snd_dev->send_data_req_buf) { - ret = -ENOMEM; - goto err_free_i2s_configs; - } - - return 0; - -err_free_i2s_configs: - gb_i2s_mgmt_free_cfgs(snd_dev); -err_free_snd_dev: - gb_free_snd(snd_dev); - return ret; -} - -static void gb_i2s_mgmt_connection_exit(struct gb_connection *connection) -{ - struct gb_snd *snd_dev = (struct gb_snd *)connection->private; - - gb_i2s_mgmt_free_cfgs(snd_dev); - - kfree(snd_dev->send_data_req_buf); - snd_dev->send_data_req_buf = NULL; - - snd_dev->mgmt_connection = NULL; - gb_free_snd(snd_dev); -} - -static int gb_i2s_mgmt_report_event_recv(u8 type, struct gb_operation *op) -{ - struct gb_connection *connection = op->connection; - struct gb_i2s_mgmt_report_event_request *req = op->request->payload; - char *event_name; - - if (type != GB_I2S_MGMT_TYPE_REPORT_EVENT) { - dev_err(&connection->bundle->dev, "Invalid request type: %d\n", - type); - return -EINVAL; - } - - if (op->request->payload_size < sizeof(*req)) { - dev_err(&connection->bundle->dev, - "Short request received (%zu < %zu)\n", - op->request->payload_size, sizeof(*req)); - return -EINVAL; - } - - switch (req->event) { - case GB_I2S_MGMT_EVENT_UNSPECIFIED: - event_name = "UNSPECIFIED"; - break; - case GB_I2S_MGMT_EVENT_HALT: - /* XXX Should stop streaming now */ - event_name = "HALT"; - break; - case GB_I2S_MGMT_EVENT_INTERNAL_ERROR: - event_name = "INTERNAL_ERROR"; - break; - case GB_I2S_MGMT_EVENT_PROTOCOL_ERROR: - event_name = "PROTOCOL_ERROR"; - break; - case GB_I2S_MGMT_EVENT_FAILURE: - event_name = "FAILURE"; - break; - case GB_I2S_MGMT_EVENT_OUT_OF_SEQUENCE: - event_name = "OUT_OF_SEQUENCE"; - break; - case GB_I2S_MGMT_EVENT_UNDERRUN: - event_name = "UNDERRUN"; - break; - case GB_I2S_MGMT_EVENT_OVERRUN: - event_name = "OVERRUN"; - break; - case GB_I2S_MGMT_EVENT_CLOCKING: - event_name = "CLOCKING"; - break; - case GB_I2S_MGMT_EVENT_DATA_LEN: - event_name = "DATA_LEN"; - break; - default: - dev_warn(&connection->bundle->dev, - "Unknown I2S Event received: %d\n", req->event); - return -EINVAL; - } - - dev_warn(&connection->bundle->dev, "I2S Event received: %d - '%s'\n", - req->event, event_name); - - return 0; -} - -static struct gb_protocol gb_i2s_receiver_protocol = { - .name = GB_AUDIO_DATA_DRIVER_NAME, - .id = GREYBUS_PROTOCOL_I2S_RECEIVER, - .major = 0, - .minor = 1, - .connection_init = gb_i2s_transmitter_connection_init, - .connection_exit = gb_i2s_transmitter_connection_exit, - .request_recv = NULL, -}; - -static struct gb_protocol gb_i2s_mgmt_protocol = { - .name = GB_AUDIO_MGMT_DRIVER_NAME, - .id = GREYBUS_PROTOCOL_I2S_MGMT, - .major = 0, - .minor = 1, - .connection_init = gb_i2s_mgmt_connection_init, - .connection_exit = gb_i2s_mgmt_connection_exit, - .request_recv = gb_i2s_mgmt_report_event_recv, -}; - - -/* - * This is the basic hook get things initialized and registered w/ gb - */ - -int gb_audio_protocol_init(void) -{ - int err; - - err = gb_protocol_register(&gb_i2s_mgmt_protocol); - if (err) { - pr_err("Can't register i2s mgmt protocol driver: %d\n", -err); - return err; - } - - err = gb_protocol_register(&gb_i2s_receiver_protocol); - if (err) { - pr_err("Can't register Audio protocol driver: %d\n", -err); - goto err_unregister_i2s_mgmt; - } - - err = platform_driver_register(&gb_audio_plat_driver); - if (err) { - pr_err("Can't register platform driver: %d\n", -err); - goto err_unregister_plat; - } - - err = platform_driver_register(&gb_audio_pcm_driver); - if (err) { - pr_err("Can't register pcm driver: %d\n", -err); - goto err_unregister_pcm; - } - - return 0; - -err_unregister_pcm: - platform_driver_unregister(&gb_audio_plat_driver); -err_unregister_plat: - gb_protocol_deregister(&gb_i2s_receiver_protocol); -err_unregister_i2s_mgmt: - gb_protocol_deregister(&gb_i2s_mgmt_protocol); - return err; -} - -void gb_audio_protocol_exit(void) -{ - platform_driver_unregister(&gb_audio_pcm_driver); - platform_driver_unregister(&gb_audio_plat_driver); - gb_protocol_deregister(&gb_i2s_receiver_protocol); - gb_protocol_deregister(&gb_i2s_mgmt_protocol); -} diff --git a/drivers/staging/greybus/audio.h b/drivers/staging/greybus/audio.h deleted file mode 100644 index e497593..0000000 --- a/drivers/staging/greybus/audio.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Greybus audio - * - * Copyright 2015 Google Inc. - * Copyright 2015 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#ifndef __GB_AUDIO_H -#define __GB_AUDIO_H -#include -#include -#include -#include -#include -#include -#include - -#include "greybus.h" - -#define GB_SAMPLE_RATE 48000 -#define GB_RATES SNDRV_PCM_RATE_48000 -#define GB_FMTS SNDRV_PCM_FMTBIT_S16_LE -#define PREALLOC_BUFFER (32 * 1024) -#define PREALLOC_BUFFER_MAX (32 * 1024) - -/* assuming 1 ms samples @ 48KHz */ -#define CONFIG_SAMPLES_PER_MSG 48L -#define CONFIG_PERIOD_NS 1000000 /* send msg every 1ms */ - -#define CONFIG_COUNT_MAX 20 - -/* Switch between dummy spdif and jetson rt5645 codec */ -#define USE_RT5645 0 - -#define SAMPLE_SIZE 4 -#define MAX_SEND_DATA_LEN (CONFIG_SAMPLES_PER_MSG * SAMPLE_SIZE) -#define SEND_DATA_BUF_LEN (sizeof(struct gb_i2s_send_data_request) + \ - MAX_SEND_DATA_LEN) - - -/* - * This is the gb_snd structure which ties everything together - * and fakes DMA interrupts via a timer. - */ -struct gb_snd { - struct platform_device card; - struct platform_device cpu_dai; - struct platform_device *codec; - struct asoc_simple_card_info *simple_card_info; - struct i2c_client *rt5647; - struct gb_connection *mgmt_connection; - struct gb_connection *i2s_tx_connection; - struct gb_connection *i2s_rx_connection; - struct gb_i2s_mgmt_get_supported_configurations_response - *i2s_configs; - char *send_data_req_buf; - long send_data_sample_count; - int gb_bundle_id; - int device_count; - struct snd_pcm_substream *substream; - struct hrtimer timer; - atomic_t running; - bool cport_active; - struct workqueue_struct *workqueue; - struct work_struct work; - int hwptr_done; - int transfer_done; - struct list_head list; - spinlock_t lock; -}; - - -/* - * GB I2S cmd functions - */ -int gb_i2s_mgmt_activate_cport(struct gb_connection *connection, - uint16_t cport); -int gb_i2s_mgmt_deactivate_cport(struct gb_connection *connection, - uint16_t cport); -int gb_i2s_mgmt_get_supported_configurations( - struct gb_connection *connection, - struct gb_i2s_mgmt_get_supported_configurations_response *get_cfg, - size_t size); -int gb_i2s_mgmt_set_configuration(struct gb_connection *connection, - struct gb_i2s_mgmt_set_configuration_request *set_cfg); -int gb_i2s_mgmt_set_samples_per_message(struct gb_connection *connection, - uint16_t samples_per_message); -int gb_i2s_mgmt_get_cfgs(struct gb_snd *snd_dev, - struct gb_connection *connection); -void gb_i2s_mgmt_free_cfgs(struct gb_snd *snd_dev); -int gb_i2s_mgmt_set_cfg(struct gb_snd *snd_dev, int rate, int chans, - int bytes_per_chan, int is_le); -int gb_i2s_send_data(struct gb_connection *connection, void *req_buf, - void *source_addr, size_t len, int sample_num); - - -/* - * GB PCM hooks - */ -void gb_pcm_hrtimer_start(struct gb_snd *snd_dev); -void gb_pcm_hrtimer_stop(struct gb_snd *snd_dev); - - -/* - * Platform drivers - */ -extern struct platform_driver gb_audio_pcm_driver; -extern struct platform_driver gb_audio_plat_driver; - - -#endif /* __GB_AUDIO_H */ diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c index 2324270..404684a 100644 --- a/drivers/staging/greybus/gpbridge.c +++ b/drivers/staging/greybus/gpbridge.c @@ -53,15 +53,9 @@ static int __init gpbridge_init(void) pr_err("error initializing hid protocol\n"); goto error_hid; } - if (gb_audio_protocol_init()) { - pr_err("error initializing audio protocols\n"); - goto error_audio; - } return 0; -error_audio: - gb_hid_protocol_exit(); error_hid: gb_spi_protocol_exit(); error_spi: @@ -83,7 +77,6 @@ module_init(gpbridge_init); static void __exit gpbridge_exit(void) { - gb_audio_protocol_exit(); gb_hid_protocol_exit(); gb_spi_protocol_exit(); gb_i2c_protocol_exit(); diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index 2e0f4d6..ad9f543 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -85,9 +85,6 @@ extern void gb_spi_protocol_exit(void); extern int gb_hid_protocol_init(void); extern void gb_hid_protocol_exit(void); -extern int gb_audio_protocol_init(void); -extern void gb_audio_protocol_exit(void); - /* __protocol: Pointer to struct gb_protocol */ #define gb_protocol_driver(__protocol) \ static int __init protocol_init(void) \ -- cgit v0.10.2 From 357499df455d30290860a23a33b2eb723f9597ac Mon Sep 17 00:00:00 2001 From: Mark Greer Date: Wed, 4 Nov 2015 09:47:22 -0700 Subject: greybus: i2s: Remove deprecated I2S Bridged-PHY Protocol The Greybus I2S Bridged-PHY Protocol is deprecated so remove all support for it from the Greybus code. CC: Vaibhav Agarwal Signed-off-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 687adf2..f29f470 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -32,7 +32,7 @@ enum greybus_protocol { GREYBUS_PROTOCOL_SDIO = 0x07, GREYBUS_PROTOCOL_BATTERY = 0x08, GREYBUS_PROTOCOL_PWM = 0x09, - GREYBUS_PROTOCOL_I2S_MGMT = 0x0a, + /* 0x0a is unused */ GREYBUS_PROTOCOL_SPI = 0x0b, GREYBUS_PROTOCOL_DISPLAY = 0x0c, GREYBUS_PROTOCOL_CAMERA = 0x0d, @@ -40,8 +40,8 @@ enum greybus_protocol { GREYBUS_PROTOCOL_LIGHTS = 0x0f, GREYBUS_PROTOCOL_VIBRATOR = 0x10, GREYBUS_PROTOCOL_LOOPBACK = 0x11, - GREYBUS_PROTOCOL_I2S_RECEIVER = 0x12, - GREYBUS_PROTOCOL_I2S_TRANSMITTER = 0x13, + /* 0x12 is unused */ + /* 0x13 is unused */ GREYBUS_PROTOCOL_SVC = 0x14, GREYBUS_PROTOCOL_FIRMWARE = 0x15, /* ... */ @@ -60,7 +60,7 @@ enum greybus_class_type { GREYBUS_CLASS_SDIO = 0x07, GREYBUS_CLASS_BATTERY = 0x08, GREYBUS_CLASS_PWM = 0x09, - GREYBUS_CLASS_I2S = 0x0a, + /* 0x0a is unused */ GREYBUS_CLASS_SPI = 0x0b, GREYBUS_CLASS_DISPLAY = 0x0c, GREYBUS_CLASS_CAMERA = 0x0d, @@ -68,8 +68,8 @@ enum greybus_class_type { GREYBUS_CLASS_LIGHTS = 0x0f, GREYBUS_CLASS_VIBRATOR = 0x10, GREYBUS_CLASS_LOOPBACK = 0x11, - GREYBUS_CLASS_I2S_RECEIVER = 0x12, - GREYBUS_CLASS_I2S_TRANSMITTER = 0x13, + /* 0x12 is unused */ + /* 0x13 is unused */ GREYBUS_CLASS_SVC = 0x14, GREYBUS_CLASS_FIRMWARE = 0x15, /* ... */ diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 02ba40f..1142b20 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -511,144 +511,6 @@ struct gb_pwm_disable_request { __u8 which; } __packed; -/* I2S */ - -#define GB_I2S_MGMT_TYPE_GET_SUPPORTED_CONFIGURATIONS 0x02 -#define GB_I2S_MGMT_TYPE_SET_CONFIGURATION 0x03 -#define GB_I2S_MGMT_TYPE_SET_SAMPLES_PER_MESSAGE 0x04 -#define GB_I2S_MGMT_TYPE_GET_PROCESSING_DELAY 0x05 -#define GB_I2S_MGMT_TYPE_SET_START_DELAY 0x06 -#define GB_I2S_MGMT_TYPE_ACTIVATE_CPORT 0x07 -#define GB_I2S_MGMT_TYPE_DEACTIVATE_CPORT 0x08 -#define GB_I2S_MGMT_TYPE_REPORT_EVENT 0x09 - -#define GB_I2S_MGMT_BYTE_ORDER_NA BIT(0) -#define GB_I2S_MGMT_BYTE_ORDER_BE BIT(1) -#define GB_I2S_MGMT_BYTE_ORDER_LE BIT(2) - -#define GB_I2S_MGMT_SPATIAL_LOCATION_FL BIT(0) -#define GB_I2S_MGMT_SPATIAL_LOCATION_FR BIT(1) -#define GB_I2S_MGMT_SPATIAL_LOCATION_FC BIT(2) -#define GB_I2S_MGMT_SPATIAL_LOCATION_LFE BIT(3) -#define GB_I2S_MGMT_SPATIAL_LOCATION_BL BIT(4) -#define GB_I2S_MGMT_SPATIAL_LOCATION_BR BIT(5) -#define GB_I2S_MGMT_SPATIAL_LOCATION_FLC BIT(6) -#define GB_I2S_MGMT_SPATIAL_LOCATION_FRC BIT(7) -#define GB_I2S_MGMT_SPATIAL_LOCATION_C BIT(8) /* BC in USB */ -#define GB_I2S_MGMT_SPATIAL_LOCATION_SL BIT(9) -#define GB_I2S_MGMT_SPATIAL_LOCATION_SR BIT(10) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TC BIT(11) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TFL BIT(12) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TFC BIT(13) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TFR BIT(14) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TBL BIT(15) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TBC BIT(16) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TBR BIT(17) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TFLC BIT(18) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TFRC BIT(19) -#define GB_I2S_MGMT_SPATIAL_LOCATION_LLFE BIT(20) -#define GB_I2S_MGMT_SPATIAL_LOCATION_RLFE BIT(21) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TSL BIT(22) -#define GB_I2S_MGMT_SPATIAL_LOCATION_TSR BIT(23) -#define GB_I2S_MGMT_SPATIAL_LOCATION_BC BIT(24) -#define GB_I2S_MGMT_SPATIAL_LOCATION_BLC BIT(25) -#define GB_I2S_MGMT_SPATIAL_LOCATION_BRC BIT(26) -#define GB_I2S_MGMT_SPATIAL_LOCATION_RD BIT(31) - -#define GB_I2S_MGMT_PROTOCOL_PCM BIT(0) -#define GB_I2S_MGMT_PROTOCOL_I2S BIT(1) -#define GB_I2S_MGMT_PROTOCOL_LR_STEREO BIT(2) - -#define GB_I2S_MGMT_ROLE_MASTER BIT(0) -#define GB_I2S_MGMT_ROLE_SLAVE BIT(1) - -#define GB_I2S_MGMT_POLARITY_NORMAL BIT(0) -#define GB_I2S_MGMT_POLARITY_REVERSED BIT(1) - -#define GB_I2S_MGMT_EDGE_RISING BIT(0) -#define GB_I2S_MGMT_EDGE_FALLING BIT(1) - -#define GB_I2S_MGMT_EVENT_UNSPECIFIED 0x1 -#define GB_I2S_MGMT_EVENT_HALT 0x2 -#define GB_I2S_MGMT_EVENT_INTERNAL_ERROR 0x3 -#define GB_I2S_MGMT_EVENT_PROTOCOL_ERROR 0x4 -#define GB_I2S_MGMT_EVENT_FAILURE 0x5 -#define GB_I2S_MGMT_EVENT_OUT_OF_SEQUENCE 0x6 -#define GB_I2S_MGMT_EVENT_UNDERRUN 0x7 -#define GB_I2S_MGMT_EVENT_OVERRUN 0x8 -#define GB_I2S_MGMT_EVENT_CLOCKING 0x9 -#define GB_I2S_MGMT_EVENT_DATA_LEN 0xa - -struct gb_i2s_mgmt_configuration { - __le32 sample_frequency; - __u8 num_channels; - __u8 bytes_per_channel; - __u8 byte_order; - __u8 pad; - __le32 spatial_locations; - __le32 ll_protocol; - __u8 ll_mclk_role; - __u8 ll_bclk_role; - __u8 ll_wclk_role; - __u8 ll_wclk_polarity; - __u8 ll_wclk_change_edge; - __u8 ll_wclk_tx_edge; - __u8 ll_wclk_rx_edge; - __u8 ll_data_offset; -} __packed; - -/* get supported configurations request has no payload */ -struct gb_i2s_mgmt_get_supported_configurations_response { - __u8 config_count; - __u8 pad[3]; - struct gb_i2s_mgmt_configuration config[0]; -} __packed; - -struct gb_i2s_mgmt_set_configuration_request { - struct gb_i2s_mgmt_configuration config; -} __packed; -/* set configuration response has no payload */ - -struct gb_i2s_mgmt_set_samples_per_message_request { - __le16 samples_per_message; -} __packed; -/* set samples per message response has no payload */ - -/* get processing request delay has no payload */ -struct gb_i2s_mgmt_get_processing_delay_response { - __le32 microseconds; -} __packed; - -struct gb_i2s_mgmt_set_start_delay_request { - __le32 microseconds; -} __packed; -/* set start delay response has no payload */ - -struct gb_i2s_mgmt_activate_cport_request { - __le16 cport; -} __packed; -/* activate cport response has no payload */ - -struct gb_i2s_mgmt_deactivate_cport_request { - __le16 cport; -} __packed; -/* deactivate cport response has no payload */ - -struct gb_i2s_mgmt_report_event_request { - __u8 event; -} __packed; -/* report event response has no payload */ - -#define GB_I2S_DATA_TYPE_SEND_DATA 0x02 - -struct gb_i2s_send_data_request { - __le32 sample_number; - __le32 size; - __u8 data[0]; -} __packed; -/* send data has no response at all */ - - /* SPI */ /* Version of the Greybus spi protocol we support */ -- cgit v0.10.2 From a51e8551e298841f26ccf02193caf2b69da2434c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 4 Nov 2015 18:55:12 +0100 Subject: greybus: es2: fix use-after-free at disconnect The interface private data is released as part of host-device removal and must not be accessed afterwards. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 1e786a6..ebf41f7 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -510,6 +510,7 @@ static void ap_disconnect(struct usb_interface *interface) { struct es2_ap_dev *es2; struct usb_device *udev; + int *cport_to_ep; int bulk_in; int i; @@ -548,9 +549,10 @@ static void ap_disconnect(struct usb_interface *interface) usb_set_intfdata(interface, NULL); udev = es2->usb_dev; + cport_to_ep = es2->cport_to_ep; gb_hd_remove(es2->hd); - kfree(es2->cport_to_ep); + kfree(cport_to_ep); usb_put_dev(udev); } -- cgit v0.10.2 From b6d808525aef6703f2bf7662c7ef99f5e7349bb4 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 4 Nov 2015 18:55:13 +0100 Subject: greybus: es2: fix endpoint requirement check The current es2 implementation only checks for no IN or OUT bulk endpoints, but still assumes there are precisely NUM_BULKS of each. Specifically, urbs could be allocated and initialised to default values, which amounts to bulk urbs being submitted to the control endpoint. We should be able to handle any number of endpoints, but for now let's just require NUM_BULKS of each. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index ebf41f7..4bb500f 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -848,8 +848,7 @@ static int ap_probe(struct usb_interface *interface, endpoint->bEndpointAddress); } } - if ((bulk_in == 0) || - (bulk_out == 0)) { + if (bulk_in != NUM_BULKS || bulk_out != NUM_BULKS) { dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n"); goto error; } -- cgit v0.10.2 From 0ce68ce41779c353be780f635234a446ea30c49d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 4 Nov 2015 18:55:14 +0100 Subject: greybus: es2: separate urb allocation and submission Refactor in-urb submission, and make sure to separate allocation and submission. Eventually we'll be submitting the urbs at cport enable rather than at probe, and this is also needed for the driver-model rework. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 4bb500f..1562696 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -209,6 +209,35 @@ static int unmap_cport(struct es2_ap_dev *es2, u16 cport_id) } #endif +static int es2_cport_in_enable(struct es2_ap_dev *es2, + struct es2_cport_in *cport_in) +{ + struct urb *urb; + int ret; + int i; + + for (i = 0; i < NUM_CPORT_IN_URB; ++i) { + urb = cport_in->urb[i]; + + ret = usb_submit_urb(urb, GFP_KERNEL); + if (ret) { + dev_err(&es2->usb_dev->dev, + "failed to submit in-urb: %d\n", ret); + goto err_kill_urbs; + } + } + + return 0; + +err_kill_urbs: + for (--i; i >= 0; --i) { + urb = cport_in->urb[i]; + usb_kill_urb(urb); + } + + return ret; +} + static struct urb *next_free_urb(struct es2_ap_dev *es2, gfp_t gfp_mask) { struct urb *urb = NULL; @@ -853,7 +882,7 @@ static int ap_probe(struct usb_interface *interface, goto error; } - /* Allocate buffers for our cport in messages and start them up */ + /* Allocate buffers for our cport in messages */ for (bulk_in = 0; bulk_in < NUM_BULKS; bulk_in++) { struct es2_cport_in *cport_in = &es2->cport_in[bulk_in]; @@ -875,9 +904,6 @@ static int ap_probe(struct usb_interface *interface, cport_in_callback, hd); cport_in->urb[i] = urb; cport_in->buffer[i] = buffer; - retval = usb_submit_urb(urb, GFP_KERNEL); - if (retval) - goto error; } } @@ -898,6 +924,13 @@ static int ap_probe(struct usb_interface *interface, (S_IWUSR | S_IRUGO), gb_debugfs_get(), es2, &apb_log_enable_fops); + + for (i = 0; i < NUM_BULKS; ++i) { + retval = es2_cport_in_enable(es2, &es2->cport_in[i]); + if (retval) + goto error; + } + return 0; error: ap_disconnect(interface); -- cgit v0.10.2 From 8dfd3fe56467ceabaac39ea884e0dc882c1832cd Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 4 Nov 2015 18:55:15 +0100 Subject: greybus: es1: separate urb allocation and submission Separate in-urb allocation and submission. This is needed for the driver-model rework. Compile-tested only. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 2386087..5724771 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -650,7 +650,7 @@ static int ap_probe(struct usb_interface *interface, goto error; } - /* Allocate buffers for our cport in messages and start them up */ + /* Allocate buffers for our cport in messages */ for (i = 0; i < NUM_CPORT_IN_URB; ++i) { struct urb *urb; u8 *buffer; @@ -668,9 +668,6 @@ static int ap_probe(struct usb_interface *interface, cport_in_callback, hd); es1->cport_in_urb[i] = urb; es1->cport_in_buffer[i] = buffer; - retval = usb_submit_urb(urb, GFP_KERNEL); - if (retval) - goto error; } /* Allocate urbs for our CPort OUT messages */ @@ -689,6 +686,13 @@ static int ap_probe(struct usb_interface *interface, (S_IWUSR | S_IRUGO), gb_debugfs_get(), es1, &apb1_log_enable_fops); + + for (i = 0; i < NUM_CPORT_IN_URB; ++i) { + retval = usb_submit_urb(es1->cport_in_urb[i], GFP_KERNEL); + if (retval) + goto error; + } + return 0; error: ap_disconnect(interface); -- cgit v0.10.2 From f6624ca77cbb4ce799a0642207fdb20e98d32777 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 4 Nov 2015 18:55:16 +0100 Subject: greybus: es2: separate stopping and deallocating urbs Separate stopping and deallocating our in-urbs. This will facilitate implementing proper host-device life-time management. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 1562696..75052af 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -238,6 +238,18 @@ err_kill_urbs: return ret; } +static void es2_cport_in_disable(struct es2_ap_dev *es2, + struct es2_cport_in *cport_in) +{ + struct urb *urb; + int i; + + for (i = 0; i < NUM_CPORT_IN_URB; ++i) { + urb = cport_in->urb[i]; + usb_kill_urb(urb); + } +} + static struct urb *next_free_urb(struct es2_ap_dev *es2, gfp_t gfp_mask) { struct urb *urb = NULL; @@ -547,6 +559,9 @@ static void ap_disconnect(struct usb_interface *interface) if (!es2) return; + for (i = 0; i < NUM_BULKS; ++i) + es2_cport_in_disable(es2, &es2->cport_in[i]); + usb_log_disable(es2); /* Tear down everything! */ @@ -569,7 +584,6 @@ static void ap_disconnect(struct usb_interface *interface) if (!urb) break; - usb_kill_urb(urb); usb_free_urb(urb); kfree(cport_in->buffer[i]); cport_in->buffer[i] = NULL; -- cgit v0.10.2 From 715d7a7280697540f9b6a4d82c3c9d1fa208c48d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 4 Nov 2015 18:55:17 +0100 Subject: greybus: es1: separate stopping and deallocating urbs Separate stopping and deallocating our in-urbs. This will facilitate implementing proper host-device life-time management. Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 5724771..ddca5f9 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -369,6 +369,9 @@ static void ap_disconnect(struct usb_interface *interface) if (!es1) return; + for (i = 0; i < NUM_CPORT_IN_URB; ++i) + usb_kill_urb(es1->cport_in_urb[i]); + usb_log_disable(es1); /* Tear down everything! */ @@ -377,7 +380,6 @@ static void ap_disconnect(struct usb_interface *interface) if (!urb) break; - usb_kill_urb(urb); usb_free_urb(urb); es1->cport_out_urb[i] = NULL; es1->cport_out_urb_busy[i] = false; /* just to be anal */ -- cgit v0.10.2 From 74cd6503e5d4f01146dc18eb28d8fa3976914995 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 4 Nov 2015 18:55:18 +0100 Subject: greybus: es2: fix debugfs dentry leak Fix dentry leak due to failure to remove debugfs file. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 75052af..18cfcd6 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -562,6 +562,7 @@ static void ap_disconnect(struct usb_interface *interface) for (i = 0; i < NUM_BULKS; ++i) es2_cport_in_disable(es2, &es2->cport_in[i]); + debugfs_remove(es2->apb_log_enable_dentry); usb_log_disable(es2); /* Tear down everything! */ -- cgit v0.10.2 From fb7a4ea22b6e68b043165ccff9601665c51af59d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 4 Nov 2015 18:55:19 +0100 Subject: greybus: es1: fix debugfs dentry leak Fix dentry leak due to failure to remove debugfs file. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index ddca5f9..3047769 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -372,6 +372,7 @@ static void ap_disconnect(struct usb_interface *interface) for (i = 0; i < NUM_CPORT_IN_URB; ++i) usb_kill_urb(es1->cport_in_urb[i]); + debugfs_remove(apb1_log_enable_dentry); usb_log_disable(es1); /* Tear down everything! */ -- cgit v0.10.2 From 57bc17ffc566deade99753febcc264c8326f1860 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 4 Nov 2015 18:55:20 +0100 Subject: greybus: es2: add more structure to probe error handling Add more structure to probe error handling rather than use the big hammer and call disconnect directly. This is needed to fix some host-device life-time issues. Note that there was never any need to clear the USB interface data as this will be done by driver core. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 18cfcd6..96ba1a7 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -547,21 +547,13 @@ static int check_urb_status(struct urb *urb) return -EAGAIN; } -static void ap_disconnect(struct usb_interface *interface) +static void es2_destroy(struct es2_ap_dev *es2) { - struct es2_ap_dev *es2; struct usb_device *udev; int *cport_to_ep; int bulk_in; int i; - es2 = usb_get_intfdata(interface); - if (!es2) - return; - - for (i = 0; i < NUM_BULKS; ++i) - es2_cport_in_disable(es2, &es2->cport_in[i]); - debugfs_remove(es2->apb_log_enable_dentry); usb_log_disable(es2); @@ -591,7 +583,6 @@ static void ap_disconnect(struct usb_interface *interface) } } - usb_set_intfdata(interface, NULL); udev = es2->usb_dev; cport_to_ep = es2->cport_to_ep; gb_hd_remove(es2->hd); @@ -600,6 +591,17 @@ static void ap_disconnect(struct usb_interface *interface) usb_put_dev(udev); } +static void ap_disconnect(struct usb_interface *interface) +{ + struct es2_ap_dev *es2 = usb_get_intfdata(interface); + int i; + + for (i = 0; i < NUM_BULKS; ++i) + es2_cport_in_disable(es2, &es2->cport_in[i]); + + es2_destroy(es2); +} + static void cport_in_callback(struct urb *urb) { struct gb_host_device *hd = urb->context; @@ -943,12 +945,16 @@ static int ap_probe(struct usb_interface *interface, for (i = 0; i < NUM_BULKS; ++i) { retval = es2_cport_in_enable(es2, &es2->cport_in[i]); if (retval) - goto error; + goto err_disable_cport_in; } return 0; + +err_disable_cport_in: + for (--i; i >= 0; --i) + es2_cport_in_disable(es2, &es2->cport_in[i]); error: - ap_disconnect(interface); + es2_destroy(es2); return retval; } -- cgit v0.10.2 From b4bd3617ed069a0aae701ed451cb6ec370fbd45f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 4 Nov 2015 18:55:21 +0100 Subject: greybus: es1: add more structure to probe error handling Add more structure to probe error handling rather than use the big hammer and call disconnect directly. This is needed to fix some host-device life-time issues. Note that there was never any need to clear the USB interface data as this will be done by driver core. Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 3047769..858c4aa 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -359,19 +359,11 @@ static int check_urb_status(struct urb *urb) return -EAGAIN; } -static void ap_disconnect(struct usb_interface *interface) +static void es1_destroy(struct es1_ap_dev *es1) { - struct es1_ap_dev *es1; struct usb_device *udev; int i; - es1 = usb_get_intfdata(interface); - if (!es1) - return; - - for (i = 0; i < NUM_CPORT_IN_URB; ++i) - usb_kill_urb(es1->cport_in_urb[i]); - debugfs_remove(apb1_log_enable_dentry); usb_log_disable(es1); @@ -397,13 +389,23 @@ static void ap_disconnect(struct usb_interface *interface) es1->cport_in_buffer[i] = NULL; } - usb_set_intfdata(interface, NULL); udev = es1->usb_dev; gb_hd_remove(es1->hd); usb_put_dev(udev); } +static void ap_disconnect(struct usb_interface *interface) +{ + struct es1_ap_dev *es1 = usb_get_intfdata(interface); + int i; + + for (i = 0; i < NUM_CPORT_IN_URB; ++i) + usb_kill_urb(es1->cport_in_urb[i]); + + es1_destroy(es1); +} + static void cport_in_callback(struct urb *urb) { struct gb_host_device *hd = urb->context; @@ -693,12 +695,16 @@ static int ap_probe(struct usb_interface *interface, for (i = 0; i < NUM_CPORT_IN_URB; ++i) { retval = usb_submit_urb(es1->cport_in_urb[i], GFP_KERNEL); if (retval) - goto error; + goto err_kill_in_urbs; } return 0; + +err_kill_in_urbs: + for (--i; i >= 0; --i) + usb_kill_urb(es1->cport_in_urb[i]); error: - ap_disconnect(interface); + es1_destroy(es1); return retval; } -- cgit v0.10.2 From c1700479845bc36cb48719b2ae341d4df89a73f6 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 4 Nov 2015 18:55:22 +0100 Subject: greybus: hd: fix host-device life time issues Fix host-device life time issues by separating host-device allocation from registration. This is needed both to make sure that all host-device resources are available before registering the device and to prevent such resources from being deallocated while the device is still in use during device removal. This specifically fixes the following warnings during es1 and es2 disconnect: usb 1-1.1: No free CPort OUT urbs, having to dynamically allocate one! Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c index 858c4aa..75253d9 100644 --- a/drivers/staging/greybus/es1.c +++ b/drivers/staging/greybus/es1.c @@ -390,7 +390,7 @@ static void es1_destroy(struct es1_ap_dev *es1) } udev = es1->usb_dev; - gb_hd_remove(es1->hd); + gb_hd_put(es1->hd); usb_put_dev(udev); } @@ -403,6 +403,8 @@ static void ap_disconnect(struct usb_interface *interface) for (i = 0; i < NUM_CPORT_IN_URB; ++i) usb_kill_urb(es1->cport_in_urb[i]); + gb_hd_del(es1->hd); + es1_destroy(es1); } @@ -692,6 +694,10 @@ static int ap_probe(struct usb_interface *interface, gb_debugfs_get(), es1, &apb1_log_enable_fops); + retval = gb_hd_add(hd); + if (retval) + goto error; + for (i = 0; i < NUM_CPORT_IN_URB; ++i) { retval = usb_submit_urb(es1->cport_in_urb[i], GFP_KERNEL); if (retval) @@ -703,6 +709,7 @@ static int ap_probe(struct usb_interface *interface, err_kill_in_urbs: for (--i; i >= 0; --i) usb_kill_urb(es1->cport_in_urb[i]); + gb_hd_del(hd); error: es1_destroy(es1); diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 96ba1a7..aad6451 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -585,7 +585,7 @@ static void es2_destroy(struct es2_ap_dev *es2) udev = es2->usb_dev; cport_to_ep = es2->cport_to_ep; - gb_hd_remove(es2->hd); + gb_hd_put(es2->hd); kfree(cport_to_ep); usb_put_dev(udev); @@ -599,6 +599,8 @@ static void ap_disconnect(struct usb_interface *interface) for (i = 0; i < NUM_BULKS; ++i) es2_cport_in_disable(es2, &es2->cport_in[i]); + gb_hd_del(es2->hd); + es2_destroy(es2); } @@ -942,6 +944,10 @@ static int ap_probe(struct usb_interface *interface, gb_debugfs_get(), es2, &apb_log_enable_fops); + retval = gb_hd_add(hd); + if (retval) + goto error; + for (i = 0; i < NUM_BULKS; ++i) { retval = es2_cport_in_enable(es2, &es2->cport_in[i]); if (retval) @@ -953,6 +959,7 @@ static int ap_probe(struct usb_interface *interface, err_disable_cport_in: for (--i; i >= 0; --i) es2_cport_in_disable(es2, &es2->cport_in[i]); + gb_hd_del(hd); error: es2_destroy(es2); diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index 6f29eb4..b22d547 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -77,6 +77,12 @@ struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, hd->buffer_size_max = buffer_size_max; hd->num_cports = num_cports; + return hd; +} +EXPORT_SYMBOL_GPL(gb_hd_create); + +int gb_hd_add(struct gb_host_device *hd) +{ /* * Initialize AP's SVC protocol connection: * @@ -87,16 +93,14 @@ struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, * time we will create a fully initialized svc-connection, as we need * endo-id and AP's interface id for that. */ - if (!gb_ap_svc_connection_create(hd)) { - kref_put_mutex(&hd->kref, free_hd, &hd_mutex); - return ERR_PTR(-ENOMEM); - } + if (!gb_ap_svc_connection_create(hd)) + return -ENOMEM; - return hd; + return 0; } -EXPORT_SYMBOL_GPL(gb_hd_create); +EXPORT_SYMBOL_GPL(gb_hd_add); -void gb_hd_remove(struct gb_host_device *hd) +void gb_hd_del(struct gb_host_device *hd) { /* * Tear down all interfaces, modules, and the endo that is associated @@ -109,7 +113,11 @@ void gb_hd_remove(struct gb_host_device *hd) /* Is the SVC still using the partially uninitialized connection ? */ if (hd->initial_svc_connection) gb_connection_destroy(hd->initial_svc_connection); +} +EXPORT_SYMBOL_GPL(gb_hd_del); +void gb_hd_put(struct gb_host_device *hd) +{ kref_put_mutex(&hd->kref, free_hd, &hd_mutex); } -EXPORT_SYMBOL_GPL(gb_hd_remove); +EXPORT_SYMBOL_GPL(gb_hd_put); diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h index 91fcccb..6724cfe 100644 --- a/drivers/staging/greybus/hd.h +++ b/drivers/staging/greybus/hd.h @@ -52,6 +52,8 @@ struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, struct device *parent, size_t buffer_size_max, size_t num_cports); -void gb_hd_remove(struct gb_host_device *hd); +int gb_hd_add(struct gb_host_device *hd); +void gb_hd_del(struct gb_host_device *hd); +void gb_hd_put(struct gb_host_device *hd); #endif /* __HD_H */ -- cgit v0.10.2 From a52028626accc2ae26c9ce03ec7bba68146b8456 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 4 Nov 2015 18:55:23 +0100 Subject: greybus: es2: clean up es2 destructor Now that the host-device is deregistered separately from deallocation, we can simplify the cport_to_ep-array deallocation. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index aad6451..c1a6fe4 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -550,7 +550,6 @@ static int check_urb_status(struct urb *urb) static void es2_destroy(struct es2_ap_dev *es2) { struct usb_device *udev; - int *cport_to_ep; int bulk_in; int i; @@ -583,11 +582,11 @@ static void es2_destroy(struct es2_ap_dev *es2) } } + kfree(es2->cport_to_ep); + udev = es2->usb_dev; - cport_to_ep = es2->cport_to_ep; gb_hd_put(es2->hd); - kfree(cport_to_ep); usb_put_dev(udev); } -- cgit v0.10.2 From c9e9de26f912bc0e5bca6a5168e7d5d427d2b2ee Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 4 Nov 2015 20:46:14 -0800 Subject: greybus: hid: hid should not be part of the bridged-phy driver. HID is a stand-alone greybus protocol, not part of the bridged-phy protocols, so make it a stand-alone kernel module. Note, some hard-coded android init script might need to be changed to load the gb-hid.ko kernel module now. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Viresh Kumar diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index cf4cf21..8b28b4b 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -18,7 +18,6 @@ gb-phy-y := gpbridge.o \ uart.o \ pwm.o \ gpio.o \ - hid.o \ i2c.o \ spi.o \ usb.o @@ -29,6 +28,7 @@ gb-battery-y := battery.o gb-loopback-y := loopback.o gb-light-y := light.o gb-raw-y := raw.o +gb-hid-y := hid.o gb-es1-y := es1.o gb-es2-y := es2.o gb-db3-y := db3-platform.o @@ -39,6 +39,7 @@ obj-m += gb-vibrator.o obj-m += gb-battery.o obj-m += gb-loopback.o obj-m += gb-light.o +obj-m += gb-hid.o obj-m += gb-raw.o obj-m += gb-es1.o obj-m += gb-es2.o diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c index 404684a..29f0984 100644 --- a/drivers/staging/greybus/gpbridge.c +++ b/drivers/staging/greybus/gpbridge.c @@ -49,15 +49,9 @@ static int __init gpbridge_init(void) pr_err("error initializing spi protocol\n"); goto error_spi; } - if (gb_hid_protocol_init()) { - pr_err("error initializing hid protocol\n"); - goto error_hid; - } return 0; -error_hid: - gb_spi_protocol_exit(); error_spi: gb_i2c_protocol_exit(); error_i2c: @@ -77,7 +71,6 @@ module_init(gpbridge_init); static void __exit gpbridge_exit(void) { - gb_hid_protocol_exit(); gb_spi_protocol_exit(); gb_i2c_protocol_exit(); gb_usb_protocol_exit(); diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index 3ac9c10..2adcb1c 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -474,4 +474,6 @@ static struct gb_protocol hid_protocol = { .request_recv = gb_hid_irq_handler, }; -gb_builtin_protocol_driver(hid_protocol); +gb_protocol_driver(&hid_protocol); + +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index ad9f543..b1d122c 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -82,9 +82,6 @@ extern void gb_i2c_protocol_exit(void); extern int gb_spi_protocol_init(void); extern void gb_spi_protocol_exit(void); -extern int gb_hid_protocol_init(void); -extern void gb_hid_protocol_exit(void); - /* __protocol: Pointer to struct gb_protocol */ #define gb_protocol_driver(__protocol) \ static int __init protocol_init(void) \ -- cgit v0.10.2 From 0d1d6ee209e1129c584c2b00a48a33ff1fb7312c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 11 Nov 2015 10:07:02 +0100 Subject: greybus: loopback: fix layer violation A bundle (protocol) driver has no business creating sysfs entries for an ancestor device. Move the sysfs entries to the bundle device for now. Signed-off-by: Johan Hovold Reviewed-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index e1b1be0..9a44dcc 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -921,7 +921,7 @@ static int gb_loopback_connection_init(struct gb_connection *connection) struct gb_loopback *gb; int retval; char name[DEBUGFS_NAMELEN]; - struct kobject *kobj = &connection->hd->endo->dev.kobj; + struct kobject *kobj = &connection->bundle->dev.kobj; gb = kzalloc(sizeof(*gb), GFP_KERNEL); if (!gb) @@ -1010,7 +1010,7 @@ out_sysfs: static void gb_loopback_connection_exit(struct gb_connection *connection) { struct gb_loopback *gb = connection->bundle->private; - struct kobject *kobj = &connection->hd->endo->dev.kobj; + struct kobject *kobj = &connection->bundle->dev.kobj; if (!IS_ERR_OR_NULL(gb->task)) kthread_stop(gb->task); -- cgit v0.10.2 From cd414d472637a30104b4908f5f239f3c06d90fe9 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 11 Nov 2015 10:07:03 +0100 Subject: greybus: battery: fix class-device parent Greybus bundle drivers should register their class devices as children to the bundle device that they bind to. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/battery.c b/drivers/staging/greybus/battery.c index 6b354de..e119775 100644 --- a/drivers/staging/greybus/battery.c +++ b/drivers/staging/greybus/battery.c @@ -244,7 +244,7 @@ static int init_and_register(struct gb_connection *connection, gb->bat.num_properties = ARRAY_SIZE(battery_props); gb->bat.get_property = get_property; - return power_supply_register(&connection->bundle->intf->dev, &gb->bat); + return power_supply_register(&connection->bundle->dev, &gb->bat); } #else static int init_and_register(struct gb_connection *connection, @@ -262,7 +262,7 @@ static int init_and_register(struct gb_connection *connection, gb->desc.num_properties = ARRAY_SIZE(battery_props); gb->desc.get_property = get_property; - gb->bat = power_supply_register(&connection->bundle->intf->dev, + gb->bat = power_supply_register(&connection->bundle->dev, &gb->desc, &cfg); if (IS_ERR(gb->bat)) return PTR_ERR(gb->bat); -- cgit v0.10.2 From f865734d3cf58cc9aba3f58962fbca7b97fe47d4 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 11 Nov 2015 10:07:04 +0100 Subject: greybus: light: fix class-device parent Greybus bundle drivers should register their class devices as children to the bundle device that they bind to. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index 664be97..3723a2c 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -724,8 +724,7 @@ static int __gb_lights_flash_led_register(struct gb_channel *channel) goto fail; } - ret = led_classdev_flash_register(&connection->bundle->intf->dev, - fled); + ret = led_classdev_flash_register(&connection->bundle->dev, fled); if (ret < 0) goto fail; @@ -812,8 +811,7 @@ static int __gb_lights_led_register(struct gb_channel *channel) struct led_classdev *cdev = get_channel_cdev(channel); int ret; - ret = led_classdev_register(&connection->bundle->intf->dev, - cdev); + ret = led_classdev_register(&connection->bundle->dev, cdev); if (ret < 0) channel->led = NULL; else -- cgit v0.10.2 From eeb6a6ff597ee47a6ecc652dab769c3137fd1483 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 11 Nov 2015 10:07:05 +0100 Subject: greybus: interface: fix potential use-after-free at remove Fix resources (accessible through sysfs) being released before interface is deregistered. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 275a8c7..e496b16 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -60,6 +60,9 @@ static void gb_interface_release(struct device *dev) { struct gb_interface *intf = to_gb_interface(dev); + kfree(intf->product_string); + kfree(intf->vendor_string); + kfree(intf); } @@ -191,9 +194,6 @@ void gb_interface_remove(struct gb_interface *intf) list_for_each_entry_safe(bundle, next, &intf->bundles, links) gb_bundle_destroy(bundle); - kfree(intf->product_string); - kfree(intf->vendor_string); - module = intf->module; device_unregister(&intf->dev); put_device(&module->dev); -- cgit v0.10.2 From febe25217924983f08a3d729d1a0b96a152ff340 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 11 Nov 2015 10:07:06 +0100 Subject: greybus: interface: fix obsolete comment Fix obsolete comment that was referring to "module" rather than "interface". Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index e496b16..b864f68 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -176,7 +176,7 @@ put_module: } /* - * Tear down a previously set up module. + * Tear down a previously set up interface. */ void gb_interface_remove(struct gb_interface *intf) { -- cgit v0.10.2 From 35a84ba7f94001c11fac0679b20c8d268fbc0b96 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 11 Nov 2015 10:07:07 +0100 Subject: greybus: use decimal notation for interface and cport ids Fix up the few places where hexadecimal rather than decimal notation was used for interface and cport ids. Note that this includes the endo sysfs-attribute for the AP interface id. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c index df4afb2..775dbce 100644 --- a/drivers/staging/greybus/endo.c +++ b/drivers/staging/greybus/endo.c @@ -89,7 +89,7 @@ static ssize_t ap_intf_id_show(struct device *dev, { struct gb_endo *endo = to_gb_endo(dev); - return sprintf(buf, "0x%02x\n", endo->ap_intf_id); + return sprintf(buf, "%u\n", endo->ap_intf_id); } static DEVICE_ATTR_RO(ap_intf_id); diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index b864f68..4c96adc5 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -157,8 +157,7 @@ struct gb_interface *gb_interface_create(struct gb_host_device *hd, retval = device_add(&intf->dev); if (retval) { - pr_err("failed to add interface device for id 0x%02hhx\n", - interface_id); + pr_err("failed to add interface %u\n", interface_id); goto free_intf; } diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index c2633e2..acf08e7 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -268,7 +268,7 @@ void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, ret = gb_operation_sync(connection, GB_SVC_TYPE_CONN_DESTROY, &request, sizeof(request), NULL, 0); if (ret) - pr_err("failed to destroy connection (%hhx:%hx %hhx:%hx) %d\n", + pr_err("failed to destroy connection (%hhu:%hu %hhu:%hu) %d\n", intf1_id, cport1_id, intf2_id, cport2_id, ret); } EXPORT_SYMBOL_GPL(gb_svc_connection_destroy); @@ -300,7 +300,7 @@ static void gb_svc_route_destroy(struct gb_svc *svc, u8 intf1_id, u8 intf2_id) ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_ROUTE_DESTROY, &request, sizeof(request), NULL, 0); if (ret) - pr_err("failed to destroy route (%hhx %hhx) %d\n", + pr_err("failed to destroy route (%hhu %hhu) %d\n", intf1_id, intf2_id, ret); } -- cgit v0.10.2 From f6c6c1388ad3ea9adc0ec2652d2b5ef9ad4ae166 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 11 Nov 2015 10:07:08 +0100 Subject: greybus: svc: use bit-macro for cport flags Use BIT-macro for cport flags. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index acf08e7..6c1a157 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -12,9 +12,9 @@ #include "greybus.h" -#define CPORT_FLAGS_E2EFC (1) -#define CPORT_FLAGS_CSD_N (2) -#define CPORT_FLAGS_CSV_N (4) +#define CPORT_FLAGS_E2EFC BIT(0) +#define CPORT_FLAGS_CSD_N BIT(1) +#define CPORT_FLAGS_CSV_N BIT(2) enum gb_svc_state { GB_SVC_STATE_RESET, -- cgit v0.10.2 From 69166d252536b644f82782840cf31e6d685616dc Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 9 Nov 2015 15:05:03 +0530 Subject: greybus: es2: Send cport-id in wValue field to usb_control_msg() wIndex field has a special meaning, as that can be used by the core to index into the possible USB interfaces. And that specifically broke with gbsim, as it has a single USB interface. Other similar requests (REQUEST_LATENCY_TAG_{EN|DIS}) are already using wValue field for passing cport-id. Fix cport_reset() by sending the cport-id in wValue field instead of wIndex. Signed-off-by: Viresh Kumar Tested-by: Fabien Parent Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index c1a6fe4..a0e2037 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -440,7 +440,7 @@ static int cport_reset(struct gb_host_device *hd, u16 cport_id) retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), REQUEST_RESET_CPORT, USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_INTERFACE, 0, cport_id, + USB_RECIP_INTERFACE, cport_id, 0, NULL, 0, ES2_TIMEOUT); if (retval < 0) { dev_err(&udev->dev, "failed to reset cport %hu: %d\n", cport_id, -- cgit v0.10.2 From 464888410d3499708baf168bc52e13f18d0cf0ae Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Thu, 12 Nov 2015 15:35:59 +0000 Subject: greybus: battery: move battery file to power_supply Rename the battery.c to power_supply.c and update the makefile as the Greybus protocol is being renamed from battery to power_supply. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 8b28b4b..d479a02 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -24,7 +24,7 @@ gb-phy-y := gpbridge.o \ # Prefix all modules with gb- gb-vibrator-y := vibrator.o -gb-battery-y := battery.o +gb-power-supply-y := power_supply.o gb-loopback-y := loopback.o gb-light-y := light.o gb-raw-y := raw.o @@ -36,7 +36,7 @@ gb-db3-y := db3-platform.o obj-m += greybus.o obj-m += gb-phy.o obj-m += gb-vibrator.o -obj-m += gb-battery.o +obj-m += gb-power-supply.o obj-m += gb-loopback.o obj-m += gb-light.o obj-m += gb-hid.o diff --git a/drivers/staging/greybus/battery.c b/drivers/staging/greybus/battery.c deleted file mode 100644 index e119775..0000000 --- a/drivers/staging/greybus/battery.c +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Battery driver for a Greybus module. - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#include -#include -#include -#include -#include "greybus.h" - -struct gb_battery { - /* - * The power supply api changed in 4.1, so handle both the old - * and new apis in the same driver for now, until this is merged - * upstream, when all of these version checks can be removed. - */ -#ifdef DRIVER_OWNS_PSY_STRUCT - struct power_supply bat; -#define to_gb_battery(x) container_of(x, struct gb_battery, bat) -#else - struct power_supply *bat; - struct power_supply_desc desc; -#define to_gb_battery(x) power_supply_get_drvdata(x) -#endif - // FIXME - // we will want to keep the battery stats in here as we will be getting - // updates from the SVC "on the fly" so we don't have to always go ask - // the battery for some information. Hopefully... - struct gb_connection *connection; - -}; - -static int get_tech(struct gb_battery *gb) -{ - struct gb_battery_technology_response tech_response; - u32 technology; - int retval; - - retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_TECHNOLOGY, - NULL, 0, - &tech_response, sizeof(tech_response)); - if (retval) - return retval; - - /* - * Map greybus values to power_supply values. Hopefully these are - * "identical" which should allow gcc to optimize the code away to - * nothing. - */ - technology = le32_to_cpu(tech_response.technology); - switch (technology) { - case GB_BATTERY_TECH_NiMH: - technology = POWER_SUPPLY_TECHNOLOGY_NiMH; - break; - case GB_BATTERY_TECH_LION: - technology = POWER_SUPPLY_TECHNOLOGY_LION; - break; - case GB_BATTERY_TECH_LIPO: - technology = POWER_SUPPLY_TECHNOLOGY_LIPO; - break; - case GB_BATTERY_TECH_LiFe: - technology = POWER_SUPPLY_TECHNOLOGY_LiFe; - break; - case GB_BATTERY_TECH_NiCd: - technology = POWER_SUPPLY_TECHNOLOGY_NiCd; - break; - case GB_BATTERY_TECH_LiMn: - technology = POWER_SUPPLY_TECHNOLOGY_LiMn; - break; - case GB_BATTERY_TECH_UNKNOWN: - default: - technology = POWER_SUPPLY_TECHNOLOGY_UNKNOWN; - break; - } - return technology; -} - -static int get_status(struct gb_battery *gb) -{ - struct gb_battery_status_response status_response; - u16 battery_status; - int retval; - - retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_STATUS, - NULL, 0, - &status_response, sizeof(status_response)); - if (retval) - return retval; - - /* - * Map greybus values to power_supply values. Hopefully these are - * "identical" which should allow gcc to optimize the code away to - * nothing. - */ - battery_status = le16_to_cpu(status_response.battery_status); - switch (battery_status) { - case GB_BATTERY_STATUS_CHARGING: - battery_status = POWER_SUPPLY_STATUS_CHARGING; - break; - case GB_BATTERY_STATUS_DISCHARGING: - battery_status = POWER_SUPPLY_STATUS_DISCHARGING; - break; - case GB_BATTERY_STATUS_NOT_CHARGING: - battery_status = POWER_SUPPLY_STATUS_NOT_CHARGING; - break; - case GB_BATTERY_STATUS_FULL: - battery_status = POWER_SUPPLY_STATUS_FULL; - break; - case GB_BATTERY_STATUS_UNKNOWN: - default: - battery_status = POWER_SUPPLY_STATUS_UNKNOWN; - break; - } - return battery_status; -} - -static int get_max_voltage(struct gb_battery *gb) -{ - struct gb_battery_max_voltage_response volt_response; - u32 max_voltage; - int retval; - - retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_MAX_VOLTAGE, - NULL, 0, - &volt_response, sizeof(volt_response)); - if (retval) - return retval; - - max_voltage = le32_to_cpu(volt_response.max_voltage); - return max_voltage; -} - -static int get_percent_capacity(struct gb_battery *gb) -{ - struct gb_battery_capacity_response capacity_response; - u32 capacity; - int retval; - - retval = gb_operation_sync(gb->connection, - GB_BATTERY_TYPE_PERCENT_CAPACITY, - NULL, 0, &capacity_response, - sizeof(capacity_response)); - if (retval) - return retval; - - capacity = le32_to_cpu(capacity_response.capacity); - return capacity; -} - -static int get_temp(struct gb_battery *gb) -{ - struct gb_battery_temperature_response temp_response; - u32 temperature; - int retval; - - retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_TEMPERATURE, - NULL, 0, - &temp_response, sizeof(temp_response)); - if (retval) - return retval; - - temperature = le32_to_cpu(temp_response.temperature); - return temperature; -} - -static int get_voltage(struct gb_battery *gb) -{ - struct gb_battery_voltage_response voltage_response; - u32 voltage; - int retval; - - retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_VOLTAGE, - NULL, 0, - &voltage_response, sizeof(voltage_response)); - if (retval) - return retval; - - voltage = le32_to_cpu(voltage_response.voltage); - return voltage; -} - -static int get_property(struct power_supply *b, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct gb_battery *gb = to_gb_battery(b); - - switch (psp) { - case POWER_SUPPLY_PROP_TECHNOLOGY: - val->intval = get_tech(gb); - break; - - case POWER_SUPPLY_PROP_STATUS: - val->intval = get_status(gb); - break; - - case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: - val->intval = get_max_voltage(gb); - break; - - case POWER_SUPPLY_PROP_CAPACITY: - val->intval = get_percent_capacity(gb); - break; - - case POWER_SUPPLY_PROP_TEMP: - val->intval = get_temp(gb); - break; - - case POWER_SUPPLY_PROP_VOLTAGE_NOW: - val->intval = get_voltage(gb); - break; - - default: - return -EINVAL; - } - - return (val->intval < 0) ? val->intval : 0; -} - -// FIXME - verify this list, odds are some can be removed and others added. -static enum power_supply_property battery_props[] = { - POWER_SUPPLY_PROP_TECHNOLOGY, - POWER_SUPPLY_PROP_STATUS, - POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, - POWER_SUPPLY_PROP_CAPACITY, - POWER_SUPPLY_PROP_TEMP, - POWER_SUPPLY_PROP_VOLTAGE_NOW, -}; - -#ifdef DRIVER_OWNS_PSY_STRUCT -static int init_and_register(struct gb_connection *connection, - struct gb_battery *gb) -{ - // FIXME - get a better (i.e. unique) name - // FIXME - anything else needs to be set? - gb->bat.name = "gb_battery"; - gb->bat.type = POWER_SUPPLY_TYPE_BATTERY; - gb->bat.properties = battery_props; - gb->bat.num_properties = ARRAY_SIZE(battery_props); - gb->bat.get_property = get_property; - - return power_supply_register(&connection->bundle->dev, &gb->bat); -} -#else -static int init_and_register(struct gb_connection *connection, - struct gb_battery *gb) -{ - struct power_supply_config cfg = {}; - - cfg.drv_data = gb; - - // FIXME - get a better (i.e. unique) name - // FIXME - anything else needs to be set? - gb->desc.name = "gb_battery"; - gb->desc.type = POWER_SUPPLY_TYPE_BATTERY; - gb->desc.properties = battery_props; - gb->desc.num_properties = ARRAY_SIZE(battery_props); - gb->desc.get_property = get_property; - - gb->bat = power_supply_register(&connection->bundle->dev, - &gb->desc, &cfg); - if (IS_ERR(gb->bat)) - return PTR_ERR(gb->bat); - - return 0; -} -#endif - -static int gb_battery_connection_init(struct gb_connection *connection) -{ - struct gb_battery *gb; - int retval; - - gb = kzalloc(sizeof(*gb), GFP_KERNEL); - if (!gb) - return -ENOMEM; - - gb->connection = connection; - connection->private = gb; - - retval = init_and_register(connection, gb); - if (retval) - kfree(gb); - - return retval; -} - -static void gb_battery_connection_exit(struct gb_connection *connection) -{ - struct gb_battery *gb = connection->private; - -#ifdef DRIVER_OWNS_PSY_STRUCT - power_supply_unregister(&gb->bat); -#else - power_supply_unregister(gb->bat); -#endif - kfree(gb); -} - -static struct gb_protocol battery_protocol = { - .name = "battery", - .id = GREYBUS_PROTOCOL_BATTERY, - .major = GB_BATTERY_VERSION_MAJOR, - .minor = GB_BATTERY_VERSION_MINOR, - .connection_init = gb_battery_connection_init, - .connection_exit = gb_battery_connection_exit, - .request_recv = NULL, /* no incoming requests */ -}; - -gb_protocol_driver(&battery_protocol); - -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c new file mode 100644 index 0000000..e119775 --- /dev/null +++ b/drivers/staging/greybus/power_supply.c @@ -0,0 +1,317 @@ +/* + * Battery driver for a Greybus module. + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include "greybus.h" + +struct gb_battery { + /* + * The power supply api changed in 4.1, so handle both the old + * and new apis in the same driver for now, until this is merged + * upstream, when all of these version checks can be removed. + */ +#ifdef DRIVER_OWNS_PSY_STRUCT + struct power_supply bat; +#define to_gb_battery(x) container_of(x, struct gb_battery, bat) +#else + struct power_supply *bat; + struct power_supply_desc desc; +#define to_gb_battery(x) power_supply_get_drvdata(x) +#endif + // FIXME + // we will want to keep the battery stats in here as we will be getting + // updates from the SVC "on the fly" so we don't have to always go ask + // the battery for some information. Hopefully... + struct gb_connection *connection; + +}; + +static int get_tech(struct gb_battery *gb) +{ + struct gb_battery_technology_response tech_response; + u32 technology; + int retval; + + retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_TECHNOLOGY, + NULL, 0, + &tech_response, sizeof(tech_response)); + if (retval) + return retval; + + /* + * Map greybus values to power_supply values. Hopefully these are + * "identical" which should allow gcc to optimize the code away to + * nothing. + */ + technology = le32_to_cpu(tech_response.technology); + switch (technology) { + case GB_BATTERY_TECH_NiMH: + technology = POWER_SUPPLY_TECHNOLOGY_NiMH; + break; + case GB_BATTERY_TECH_LION: + technology = POWER_SUPPLY_TECHNOLOGY_LION; + break; + case GB_BATTERY_TECH_LIPO: + technology = POWER_SUPPLY_TECHNOLOGY_LIPO; + break; + case GB_BATTERY_TECH_LiFe: + technology = POWER_SUPPLY_TECHNOLOGY_LiFe; + break; + case GB_BATTERY_TECH_NiCd: + technology = POWER_SUPPLY_TECHNOLOGY_NiCd; + break; + case GB_BATTERY_TECH_LiMn: + technology = POWER_SUPPLY_TECHNOLOGY_LiMn; + break; + case GB_BATTERY_TECH_UNKNOWN: + default: + technology = POWER_SUPPLY_TECHNOLOGY_UNKNOWN; + break; + } + return technology; +} + +static int get_status(struct gb_battery *gb) +{ + struct gb_battery_status_response status_response; + u16 battery_status; + int retval; + + retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_STATUS, + NULL, 0, + &status_response, sizeof(status_response)); + if (retval) + return retval; + + /* + * Map greybus values to power_supply values. Hopefully these are + * "identical" which should allow gcc to optimize the code away to + * nothing. + */ + battery_status = le16_to_cpu(status_response.battery_status); + switch (battery_status) { + case GB_BATTERY_STATUS_CHARGING: + battery_status = POWER_SUPPLY_STATUS_CHARGING; + break; + case GB_BATTERY_STATUS_DISCHARGING: + battery_status = POWER_SUPPLY_STATUS_DISCHARGING; + break; + case GB_BATTERY_STATUS_NOT_CHARGING: + battery_status = POWER_SUPPLY_STATUS_NOT_CHARGING; + break; + case GB_BATTERY_STATUS_FULL: + battery_status = POWER_SUPPLY_STATUS_FULL; + break; + case GB_BATTERY_STATUS_UNKNOWN: + default: + battery_status = POWER_SUPPLY_STATUS_UNKNOWN; + break; + } + return battery_status; +} + +static int get_max_voltage(struct gb_battery *gb) +{ + struct gb_battery_max_voltage_response volt_response; + u32 max_voltage; + int retval; + + retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_MAX_VOLTAGE, + NULL, 0, + &volt_response, sizeof(volt_response)); + if (retval) + return retval; + + max_voltage = le32_to_cpu(volt_response.max_voltage); + return max_voltage; +} + +static int get_percent_capacity(struct gb_battery *gb) +{ + struct gb_battery_capacity_response capacity_response; + u32 capacity; + int retval; + + retval = gb_operation_sync(gb->connection, + GB_BATTERY_TYPE_PERCENT_CAPACITY, + NULL, 0, &capacity_response, + sizeof(capacity_response)); + if (retval) + return retval; + + capacity = le32_to_cpu(capacity_response.capacity); + return capacity; +} + +static int get_temp(struct gb_battery *gb) +{ + struct gb_battery_temperature_response temp_response; + u32 temperature; + int retval; + + retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_TEMPERATURE, + NULL, 0, + &temp_response, sizeof(temp_response)); + if (retval) + return retval; + + temperature = le32_to_cpu(temp_response.temperature); + return temperature; +} + +static int get_voltage(struct gb_battery *gb) +{ + struct gb_battery_voltage_response voltage_response; + u32 voltage; + int retval; + + retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_VOLTAGE, + NULL, 0, + &voltage_response, sizeof(voltage_response)); + if (retval) + return retval; + + voltage = le32_to_cpu(voltage_response.voltage); + return voltage; +} + +static int get_property(struct power_supply *b, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct gb_battery *gb = to_gb_battery(b); + + switch (psp) { + case POWER_SUPPLY_PROP_TECHNOLOGY: + val->intval = get_tech(gb); + break; + + case POWER_SUPPLY_PROP_STATUS: + val->intval = get_status(gb); + break; + + case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: + val->intval = get_max_voltage(gb); + break; + + case POWER_SUPPLY_PROP_CAPACITY: + val->intval = get_percent_capacity(gb); + break; + + case POWER_SUPPLY_PROP_TEMP: + val->intval = get_temp(gb); + break; + + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + val->intval = get_voltage(gb); + break; + + default: + return -EINVAL; + } + + return (val->intval < 0) ? val->intval : 0; +} + +// FIXME - verify this list, odds are some can be removed and others added. +static enum power_supply_property battery_props[] = { + POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, + POWER_SUPPLY_PROP_CAPACITY, + POWER_SUPPLY_PROP_TEMP, + POWER_SUPPLY_PROP_VOLTAGE_NOW, +}; + +#ifdef DRIVER_OWNS_PSY_STRUCT +static int init_and_register(struct gb_connection *connection, + struct gb_battery *gb) +{ + // FIXME - get a better (i.e. unique) name + // FIXME - anything else needs to be set? + gb->bat.name = "gb_battery"; + gb->bat.type = POWER_SUPPLY_TYPE_BATTERY; + gb->bat.properties = battery_props; + gb->bat.num_properties = ARRAY_SIZE(battery_props); + gb->bat.get_property = get_property; + + return power_supply_register(&connection->bundle->dev, &gb->bat); +} +#else +static int init_and_register(struct gb_connection *connection, + struct gb_battery *gb) +{ + struct power_supply_config cfg = {}; + + cfg.drv_data = gb; + + // FIXME - get a better (i.e. unique) name + // FIXME - anything else needs to be set? + gb->desc.name = "gb_battery"; + gb->desc.type = POWER_SUPPLY_TYPE_BATTERY; + gb->desc.properties = battery_props; + gb->desc.num_properties = ARRAY_SIZE(battery_props); + gb->desc.get_property = get_property; + + gb->bat = power_supply_register(&connection->bundle->dev, + &gb->desc, &cfg); + if (IS_ERR(gb->bat)) + return PTR_ERR(gb->bat); + + return 0; +} +#endif + +static int gb_battery_connection_init(struct gb_connection *connection) +{ + struct gb_battery *gb; + int retval; + + gb = kzalloc(sizeof(*gb), GFP_KERNEL); + if (!gb) + return -ENOMEM; + + gb->connection = connection; + connection->private = gb; + + retval = init_and_register(connection, gb); + if (retval) + kfree(gb); + + return retval; +} + +static void gb_battery_connection_exit(struct gb_connection *connection) +{ + struct gb_battery *gb = connection->private; + +#ifdef DRIVER_OWNS_PSY_STRUCT + power_supply_unregister(&gb->bat); +#else + power_supply_unregister(gb->bat); +#endif + kfree(gb); +} + +static struct gb_protocol battery_protocol = { + .name = "battery", + .id = GREYBUS_PROTOCOL_BATTERY, + .major = GB_BATTERY_VERSION_MAJOR, + .minor = GB_BATTERY_VERSION_MINOR, + .connection_init = gb_battery_connection_init, + .connection_exit = gb_battery_connection_exit, + .request_recv = NULL, /* no incoming requests */ +}; + +gb_protocol_driver(&battery_protocol); + +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 2724be0305bc8def0ad05b226fb9867549b35c16 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Thu, 12 Nov 2015 15:36:00 +0000 Subject: greybus: battery: move implementation to power_supply Rename protocol to POWER_SUPPLY and implementation details from battery to power_supply. Also fix some tabs between define and macro name. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index f29f470..c36c4d1 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -30,7 +30,7 @@ enum greybus_protocol { GREYBUS_PROTOCOL_HID = 0x05, GREYBUS_PROTOCOL_USB = 0x06, GREYBUS_PROTOCOL_SDIO = 0x07, - GREYBUS_PROTOCOL_BATTERY = 0x08, + GREYBUS_PROTOCOL_POWER_SUPPLY = 0x08, GREYBUS_PROTOCOL_PWM = 0x09, /* 0x0a is unused */ GREYBUS_PROTOCOL_SPI = 0x0b, @@ -58,7 +58,7 @@ enum greybus_class_type { GREYBUS_CLASS_HID = 0x05, GREYBUS_CLASS_USB = 0x06, GREYBUS_CLASS_SDIO = 0x07, - GREYBUS_CLASS_BATTERY = 0x08, + GREYBUS_CLASS_POWER_SUPPLY = 0x08, GREYBUS_CLASS_PWM = 0x09, /* 0x0a is unused */ GREYBUS_CLASS_SPI = 0x0b, diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 1142b20..b238040 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -198,60 +198,60 @@ struct gb_firmware_ready_to_boot_request { /* Firmware protocol Ready to boot response has no payload */ -/* BATTERY */ - -/* Version of the Greybus battery protocol we support */ -#define GB_BATTERY_VERSION_MAJOR 0x00 -#define GB_BATTERY_VERSION_MINOR 0x01 - -/* Greybus battery request types */ -#define GB_BATTERY_TYPE_TECHNOLOGY 0x02 -#define GB_BATTERY_TYPE_STATUS 0x03 -#define GB_BATTERY_TYPE_MAX_VOLTAGE 0x04 -#define GB_BATTERY_TYPE_PERCENT_CAPACITY 0x05 -#define GB_BATTERY_TYPE_TEMPERATURE 0x06 -#define GB_BATTERY_TYPE_VOLTAGE 0x07 -#define GB_BATTERY_TYPE_CURRENT 0x08 -#define GB_BATTERY_TYPE_CAPACITY 0x09 // TODO - POWER_SUPPLY_PROP_CURRENT_MAX -#define GB_BATTERY_TYPE_SHUTDOWN_TEMP 0x0a // TODO - POWER_SUPPLY_PROP_TEMP_ALERT_MAX - -/* Should match up with battery types in linux/power_supply.h */ -#define GB_BATTERY_TECH_UNKNOWN 0x0000 -#define GB_BATTERY_TECH_NiMH 0x0001 -#define GB_BATTERY_TECH_LION 0x0002 -#define GB_BATTERY_TECH_LIPO 0x0003 -#define GB_BATTERY_TECH_LiFe 0x0004 -#define GB_BATTERY_TECH_NiCd 0x0005 -#define GB_BATTERY_TECH_LiMn 0x0006 - -struct gb_battery_technology_response { +/* Power Supply */ + +/* Version of the Greybus power supply protocol we support */ +#define GB_POWER_SUPPLY_VERSION_MAJOR 0x00 +#define GB_POWER_SUPPLY_VERSION_MINOR 0x01 + +/* Greybus power supply request types */ +#define GB_POWER_SUPPLY_TYPE_TECHNOLOGY 0x02 +#define GB_POWER_SUPPLY_TYPE_STATUS 0x03 +#define GB_POWER_SUPPLY_TYPE_MAX_VOLTAGE 0x04 +#define GB_POWER_SUPPLY_TYPE_PERCENT_CAPACITY 0x05 +#define GB_POWER_SUPPLY_TYPE_TEMPERATURE 0x06 +#define GB_POWER_SUPPLY_TYPE_VOLTAGE 0x07 +#define GB_POWER_SUPPLY_TYPE_CURRENT 0x08 +#define GB_POWER_SUPPLY_TYPE_CAPACITY 0x09 // TODO - POWER_SUPPLY_PROP_CURRENT_MAX +#define GB_POWER_SUPPLY_TYPE_SHUTDOWN_TEMP 0x0a // TODO - POWER_SUPPLY_PROP_TEMP_ALERT_MAX + +/* Should match up with battery technology types in linux/power_supply.h */ +#define GB_POWER_SUPPLY_TECH_UNKNOWN 0x0000 +#define GB_POWER_SUPPLY_TECH_NiMH 0x0001 +#define GB_POWER_SUPPLY_TECH_LION 0x0002 +#define GB_POWER_SUPPLY_TECH_LIPO 0x0003 +#define GB_POWER_SUPPLY_TECH_LiFe 0x0004 +#define GB_POWER_SUPPLY_TECH_NiCd 0x0005 +#define GB_POWER_SUPPLY_TECH_LiMn 0x0006 + +struct gb_power_supply_technology_response { __le32 technology; } __packed; -/* Should match up with battery status in linux/power_supply.h */ -#define GB_BATTERY_STATUS_UNKNOWN 0x0000 -#define GB_BATTERY_STATUS_CHARGING 0x0001 -#define GB_BATTERY_STATUS_DISCHARGING 0x0002 -#define GB_BATTERY_STATUS_NOT_CHARGING 0x0003 -#define GB_BATTERY_STATUS_FULL 0x0004 +/* Should match up with power supply status in linux/power_supply.h */ +#define GB_POWER_SUPPLY_STATUS_UNKNOWN 0x0000 +#define GB_POWER_SUPPLY_STATUS_CHARGING 0x0001 +#define GB_POWER_SUPPLY_STATUS_DISCHARGING 0x0002 +#define GB_POWER_SUPPLY_STATUS_NOT_CHARGING 0x0003 +#define GB_POWER_SUPPLY_STATUS_FULL 0x0004 -struct gb_battery_status_response { - __le16 battery_status; +struct gb_power_supply_status_response { + __le16 psy_status; } __packed; -struct gb_battery_max_voltage_response { +struct gb_power_supply_max_voltage_response { __le32 max_voltage; } __packed; -struct gb_battery_capacity_response { +struct gb_power_supply_capacity_response { __le32 capacity; } __packed; -struct gb_battery_temperature_response { +struct gb_power_supply_temperature_response { __le32 temperature; } __packed; -struct gb_battery_voltage_response { +struct gb_power_supply_voltage_response { __le32 voltage; } __packed; diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c index e119775..d7797a2 100644 --- a/drivers/staging/greybus/power_supply.c +++ b/drivers/staging/greybus/power_supply.c @@ -1,5 +1,5 @@ /* - * Battery driver for a Greybus module. + * Power Supply driver for a Greybus module. * * Copyright 2014 Google Inc. * Copyright 2014 Linaro Ltd. @@ -13,35 +13,36 @@ #include #include "greybus.h" -struct gb_battery { +struct gb_power_supply { /* * The power supply api changed in 4.1, so handle both the old * and new apis in the same driver for now, until this is merged * upstream, when all of these version checks can be removed. */ #ifdef DRIVER_OWNS_PSY_STRUCT - struct power_supply bat; -#define to_gb_battery(x) container_of(x, struct gb_battery, bat) + struct power_supply psy; +#define to_gb_power_supply(x) container_of(x, struct gb_power_supply, psy) #else - struct power_supply *bat; + struct power_supply *psy; struct power_supply_desc desc; -#define to_gb_battery(x) power_supply_get_drvdata(x) +#define to_gb_power_supply(x) power_supply_get_drvdata(x) #endif // FIXME - // we will want to keep the battery stats in here as we will be getting - // updates from the SVC "on the fly" so we don't have to always go ask - // the battery for some information. Hopefully... + // we will want to keep the power supply stats in here as we will be + // getting updates from the SVC "on the fly" so we don't have to always + // go ask the power supply for some information. Hopefully... struct gb_connection *connection; }; -static int get_tech(struct gb_battery *gb) +static int get_tech(struct gb_power_supply *gb) { - struct gb_battery_technology_response tech_response; + struct gb_power_supply_technology_response tech_response; u32 technology; int retval; - retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_TECHNOLOGY, + retval = gb_operation_sync(gb->connection, + GB_POWER_SUPPLY_TYPE_TECHNOLOGY, NULL, 0, &tech_response, sizeof(tech_response)); if (retval) @@ -54,25 +55,25 @@ static int get_tech(struct gb_battery *gb) */ technology = le32_to_cpu(tech_response.technology); switch (technology) { - case GB_BATTERY_TECH_NiMH: + case GB_POWER_SUPPLY_TECH_NiMH: technology = POWER_SUPPLY_TECHNOLOGY_NiMH; break; - case GB_BATTERY_TECH_LION: + case GB_POWER_SUPPLY_TECH_LION: technology = POWER_SUPPLY_TECHNOLOGY_LION; break; - case GB_BATTERY_TECH_LIPO: + case GB_POWER_SUPPLY_TECH_LIPO: technology = POWER_SUPPLY_TECHNOLOGY_LIPO; break; - case GB_BATTERY_TECH_LiFe: + case GB_POWER_SUPPLY_TECH_LiFe: technology = POWER_SUPPLY_TECHNOLOGY_LiFe; break; - case GB_BATTERY_TECH_NiCd: + case GB_POWER_SUPPLY_TECH_NiCd: technology = POWER_SUPPLY_TECHNOLOGY_NiCd; break; - case GB_BATTERY_TECH_LiMn: + case GB_POWER_SUPPLY_TECH_LiMn: technology = POWER_SUPPLY_TECHNOLOGY_LiMn; break; - case GB_BATTERY_TECH_UNKNOWN: + case GB_POWER_SUPPLY_TECH_UNKNOWN: default: technology = POWER_SUPPLY_TECHNOLOGY_UNKNOWN; break; @@ -80,13 +81,13 @@ static int get_tech(struct gb_battery *gb) return technology; } -static int get_status(struct gb_battery *gb) +static int get_status(struct gb_power_supply *gb) { - struct gb_battery_status_response status_response; - u16 battery_status; + struct gb_power_supply_status_response status_response; + u16 psy_status; int retval; - retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_STATUS, + retval = gb_operation_sync(gb->connection, GB_POWER_SUPPLY_TYPE_STATUS, NULL, 0, &status_response, sizeof(status_response)); if (retval) @@ -97,35 +98,36 @@ static int get_status(struct gb_battery *gb) * "identical" which should allow gcc to optimize the code away to * nothing. */ - battery_status = le16_to_cpu(status_response.battery_status); - switch (battery_status) { - case GB_BATTERY_STATUS_CHARGING: - battery_status = POWER_SUPPLY_STATUS_CHARGING; + psy_status = le16_to_cpu(status_response.psy_status); + switch (psy_status) { + case GB_POWER_SUPPLY_STATUS_CHARGING: + psy_status = POWER_SUPPLY_STATUS_CHARGING; break; - case GB_BATTERY_STATUS_DISCHARGING: - battery_status = POWER_SUPPLY_STATUS_DISCHARGING; + case GB_POWER_SUPPLY_STATUS_DISCHARGING: + psy_status = POWER_SUPPLY_STATUS_DISCHARGING; break; - case GB_BATTERY_STATUS_NOT_CHARGING: - battery_status = POWER_SUPPLY_STATUS_NOT_CHARGING; + case GB_POWER_SUPPLY_STATUS_NOT_CHARGING: + psy_status = POWER_SUPPLY_STATUS_NOT_CHARGING; break; - case GB_BATTERY_STATUS_FULL: - battery_status = POWER_SUPPLY_STATUS_FULL; + case GB_POWER_SUPPLY_STATUS_FULL: + psy_status = POWER_SUPPLY_STATUS_FULL; break; - case GB_BATTERY_STATUS_UNKNOWN: + case GB_POWER_SUPPLY_STATUS_UNKNOWN: default: - battery_status = POWER_SUPPLY_STATUS_UNKNOWN; + psy_status = POWER_SUPPLY_STATUS_UNKNOWN; break; } - return battery_status; + return psy_status; } -static int get_max_voltage(struct gb_battery *gb) +static int get_max_voltage(struct gb_power_supply *gb) { - struct gb_battery_max_voltage_response volt_response; + struct gb_power_supply_max_voltage_response volt_response; u32 max_voltage; int retval; - retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_MAX_VOLTAGE, + retval = gb_operation_sync(gb->connection, + GB_POWER_SUPPLY_TYPE_MAX_VOLTAGE, NULL, 0, &volt_response, sizeof(volt_response)); if (retval) @@ -135,14 +137,14 @@ static int get_max_voltage(struct gb_battery *gb) return max_voltage; } -static int get_percent_capacity(struct gb_battery *gb) +static int get_percent_capacity(struct gb_power_supply *gb) { - struct gb_battery_capacity_response capacity_response; + struct gb_power_supply_capacity_response capacity_response; u32 capacity; int retval; retval = gb_operation_sync(gb->connection, - GB_BATTERY_TYPE_PERCENT_CAPACITY, + GB_POWER_SUPPLY_TYPE_PERCENT_CAPACITY, NULL, 0, &capacity_response, sizeof(capacity_response)); if (retval) @@ -152,13 +154,14 @@ static int get_percent_capacity(struct gb_battery *gb) return capacity; } -static int get_temp(struct gb_battery *gb) +static int get_temp(struct gb_power_supply *gb) { - struct gb_battery_temperature_response temp_response; + struct gb_power_supply_temperature_response temp_response; u32 temperature; int retval; - retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_TEMPERATURE, + retval = gb_operation_sync(gb->connection, + GB_POWER_SUPPLY_TYPE_TEMPERATURE, NULL, 0, &temp_response, sizeof(temp_response)); if (retval) @@ -168,13 +171,13 @@ static int get_temp(struct gb_battery *gb) return temperature; } -static int get_voltage(struct gb_battery *gb) +static int get_voltage(struct gb_power_supply *gb) { - struct gb_battery_voltage_response voltage_response; + struct gb_power_supply_voltage_response voltage_response; u32 voltage; int retval; - retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_VOLTAGE, + retval = gb_operation_sync(gb->connection, GB_POWER_SUPPLY_TYPE_VOLTAGE, NULL, 0, &voltage_response, sizeof(voltage_response)); if (retval) @@ -188,7 +191,7 @@ static int get_property(struct power_supply *b, enum power_supply_property psp, union power_supply_propval *val) { - struct gb_battery *gb = to_gb_battery(b); + struct gb_power_supply *gb = to_gb_power_supply(b); switch (psp) { case POWER_SUPPLY_PROP_TECHNOLOGY: @@ -223,7 +226,7 @@ static int get_property(struct power_supply *b, } // FIXME - verify this list, odds are some can be removed and others added. -static enum power_supply_property battery_props[] = { +static enum power_supply_property psy_props[] = { POWER_SUPPLY_PROP_TECHNOLOGY, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, @@ -238,17 +241,17 @@ static int init_and_register(struct gb_connection *connection, { // FIXME - get a better (i.e. unique) name // FIXME - anything else needs to be set? - gb->bat.name = "gb_battery"; - gb->bat.type = POWER_SUPPLY_TYPE_BATTERY; - gb->bat.properties = battery_props; - gb->bat.num_properties = ARRAY_SIZE(battery_props); - gb->bat.get_property = get_property; + gb->psy.name = "gb_battery"; + gb->psy.type = POWER_SUPPLY_TYPE_BATTERY; + gb->psy.properties = psy_props; + gb->psy.num_properties = ARRAY_SIZE(psy_props); + gb->psy.get_property = get_property; - return power_supply_register(&connection->bundle->dev, &gb->bat); + return power_supply_register(&connection->bundle->dev, &gb->psy); } #else static int init_and_register(struct gb_connection *connection, - struct gb_battery *gb) + struct gb_power_supply *gb) { struct power_supply_config cfg = {}; @@ -258,22 +261,22 @@ static int init_and_register(struct gb_connection *connection, // FIXME - anything else needs to be set? gb->desc.name = "gb_battery"; gb->desc.type = POWER_SUPPLY_TYPE_BATTERY; - gb->desc.properties = battery_props; - gb->desc.num_properties = ARRAY_SIZE(battery_props); + gb->desc.properties = psy_props; + gb->desc.num_properties = ARRAY_SIZE(psy_props); gb->desc.get_property = get_property; - gb->bat = power_supply_register(&connection->bundle->dev, + gb->psy = power_supply_register(&connection->bundle->dev, &gb->desc, &cfg); - if (IS_ERR(gb->bat)) - return PTR_ERR(gb->bat); + if (IS_ERR(gb->psy)) + return PTR_ERR(gb->psy); return 0; } #endif -static int gb_battery_connection_init(struct gb_connection *connection) +static int gb_power_supply_connection_init(struct gb_connection *connection) { - struct gb_battery *gb; + struct gb_power_supply *gb; int retval; gb = kzalloc(sizeof(*gb), GFP_KERNEL); @@ -290,28 +293,28 @@ static int gb_battery_connection_init(struct gb_connection *connection) return retval; } -static void gb_battery_connection_exit(struct gb_connection *connection) +static void gb_power_supply_connection_exit(struct gb_connection *connection) { - struct gb_battery *gb = connection->private; + struct gb_power_supply *gb = connection->private; #ifdef DRIVER_OWNS_PSY_STRUCT - power_supply_unregister(&gb->bat); + power_supply_unregister(&gb->psy); #else - power_supply_unregister(gb->bat); + power_supply_unregister(gb->psy); #endif kfree(gb); } -static struct gb_protocol battery_protocol = { - .name = "battery", - .id = GREYBUS_PROTOCOL_BATTERY, - .major = GB_BATTERY_VERSION_MAJOR, - .minor = GB_BATTERY_VERSION_MINOR, - .connection_init = gb_battery_connection_init, - .connection_exit = gb_battery_connection_exit, +static struct gb_protocol power_supply_protocol = { + .name = "power_supply", + .id = GREYBUS_PROTOCOL_POWER_SUPPLY, + .major = GB_POWER_SUPPLY_VERSION_MAJOR, + .minor = GB_POWER_SUPPLY_VERSION_MINOR, + .connection_init = gb_power_supply_connection_init, + .connection_exit = gb_power_supply_connection_exit, .request_recv = NULL, /* no incoming requests */ }; -gb_protocol_driver(&battery_protocol); +gb_protocol_driver(&power_supply_protocol); MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 783e373a9fead8591e5d22fd12e76a99b234337e Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Thu, 12 Nov 2015 15:36:01 +0000 Subject: greybus: makefile: add power_supply config check Add check for POWER_SUPPLY config option to guarantee that it is enabled. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index d479a02..c3572b3 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -51,7 +51,7 @@ INSTALL_MOD_PATH ?= /.. PWD := $(shell pwd) # kernel config option that shall be enable -CONFIG_OPTIONS_ENABLE := PWM SYSFS SPI USB SND_SOC MMC LEDS_CLASS +CONFIG_OPTIONS_ENABLE := POWER_SUPPLY PWM SYSFS SPI USB SND_SOC MMC LEDS_CLASS # kernel config option that shall be disable CONFIG_OPTIONS_DISABLE := -- cgit v0.10.2 From ffe2e2487a388cf01ec44439346363aa8d654cd4 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Thu, 12 Nov 2015 15:36:02 +0000 Subject: greybus: power_supply: rework and operation changes This is a major rework and changes to the current implementation of the battery protocol. The previous implementation lack the support of a more dynamic handle of power supply properties and updating of status. Also, reflect the actual state of the greybus specification So, with this new approach a set of operations to fetch the battery module configuration and properties is add, new methods to cache and update the values of properties, new operation to set properties if declared writable and an event operation that can be triggered by the module to force an update read on the properties values. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index b238040..9fcbbe4 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -205,17 +205,14 @@ struct gb_firmware_ready_to_boot_request { #define GB_POWER_SUPPLY_VERSION_MINOR 0x01 /* Greybus power supply request types */ -#define GB_POWER_SUPPLY_TYPE_TECHNOLOGY 0x02 -#define GB_POWER_SUPPLY_TYPE_STATUS 0x03 -#define GB_POWER_SUPPLY_TYPE_MAX_VOLTAGE 0x04 -#define GB_POWER_SUPPLY_TYPE_PERCENT_CAPACITY 0x05 -#define GB_POWER_SUPPLY_TYPE_TEMPERATURE 0x06 -#define GB_POWER_SUPPLY_TYPE_VOLTAGE 0x07 -#define GB_POWER_SUPPLY_TYPE_CURRENT 0x08 -#define GB_POWER_SUPPLY_TYPE_CAPACITY 0x09 // TODO - POWER_SUPPLY_PROP_CURRENT_MAX -#define GB_POWER_SUPPLY_TYPE_SHUTDOWN_TEMP 0x0a // TODO - POWER_SUPPLY_PROP_TEMP_ALERT_MAX - -/* Should match up with battery technology types in linux/power_supply.h */ +#define GB_POWER_SUPPLY_TYPE_GET_SUPPLIES 0x02 +#define GB_POWER_SUPPLY_TYPE_GET_DESCRIPTION 0x03 +#define GB_POWER_SUPPLY_TYPE_GET_PROP_DESCRIPTORS 0x04 +#define GB_POWER_SUPPLY_TYPE_GET_PROPERTY 0x05 +#define GB_POWER_SUPPLY_TYPE_SET_PROPERTY 0x06 +#define GB_POWER_SUPPLY_TYPE_EVENT 0x07 + +/* Should match up with battery technologies in linux/power_supply.h */ #define GB_POWER_SUPPLY_TECH_UNKNOWN 0x0000 #define GB_POWER_SUPPLY_TECH_NiMH 0x0001 #define GB_POWER_SUPPLY_TECH_LION 0x0002 @@ -224,35 +221,145 @@ struct gb_firmware_ready_to_boot_request { #define GB_POWER_SUPPLY_TECH_NiCd 0x0005 #define GB_POWER_SUPPLY_TECH_LiMn 0x0006 -struct gb_power_supply_technology_response { - __le32 technology; -} __packed; - -/* Should match up with power supply status in linux/power_supply.h */ -#define GB_POWER_SUPPLY_STATUS_UNKNOWN 0x0000 -#define GB_POWER_SUPPLY_STATUS_CHARGING 0x0001 -#define GB_POWER_SUPPLY_STATUS_DISCHARGING 0x0002 -#define GB_POWER_SUPPLY_STATUS_NOT_CHARGING 0x0003 -#define GB_POWER_SUPPLY_STATUS_FULL 0x0004 - -struct gb_power_supply_status_response { - __le16 psy_status; -} __packed; - -struct gb_power_supply_max_voltage_response { - __le32 max_voltage; -} __packed; - -struct gb_power_supply_capacity_response { - __le32 capacity; -} __packed; - -struct gb_power_supply_temperature_response { - __le32 temperature; -} __packed; - -struct gb_power_supply_voltage_response { - __le32 voltage; +/* Should match up with power supply types in linux/power_supply.h */ +#define GB_POWER_SUPPLY_UNKNOWN_TYPE 0x0000 +#define GB_POWER_SUPPLY_BATTERY_TYPE 0x0001 +#define GB_POWER_SUPPLY_UPS_TYPE 0x0002 +#define GB_POWER_SUPPLY_MAINS_TYPE 0x0003 +#define GB_POWER_SUPPLY_USB_TYPE 0x0004 +#define GB_POWER_SUPPLY_USB_DCP_TYPE 0x0005 +#define GB_POWER_SUPPLY_USB_CDP_TYPE 0x0006 +#define GB_POWER_SUPPLY_USB_ACA_TYPE 0x0007 + +/* Should match up with power supply health in linux/power_supply.h */ +#define GB_POWER_SUPPLY_HEALTH_UNKNOWN 0x0000 +#define GB_POWER_SUPPLY_HEALTH_GOOD 0x0001 +#define GB_POWER_SUPPLY_HEALTH_OVERHEAT 0x0002 +#define GB_POWER_SUPPLY_HEALTH_DEAD 0x0003 +#define GB_POWER_SUPPLY_HEALTH_OVERVOLTAGE 0x0004 +#define GB_POWER_SUPPLY_HEALTH_UNSPEC_FAILURE 0x0005 +#define GB_POWER_SUPPLY_HEALTH_COLD 0x0006 +#define GB_POWER_SUPPLY_HEALTH_WATCHDOG_TIMER_EXPIRE 0x0007 +#define GB_POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE 0x0008 + +/* Should match up with battery status in linux/power_supply.h */ +#define GB_POWER_SUPPLY_STATUS_UNKNOWN 0x0000 +#define GB_POWER_SUPPLY_STATUS_CHARGING 0x0001 +#define GB_POWER_SUPPLY_STATUS_DISCHARGING 0x0002 +#define GB_POWER_SUPPLY_STATUS_NOT_CHARGING 0x0003 +#define GB_POWER_SUPPLY_STATUS_FULL 0x0004 + +struct gb_power_supply_get_supplies_response { + __u8 supplies_count; +} __packed; + +struct gb_power_supply_get_description_request { + __u8 psy_id; +} __packed; + +struct gb_power_supply_get_description_response { + __u8 manufacturer[32]; + __u8 model[32]; + __u8 serial_number[32]; + __le16 type; + __u8 properties_count; +} __packed; + +struct gb_power_supply_props_desc { + __u8 property; +#define GB_POWER_SUPPLY_PROP_STATUS 0x00 +#define GB_POWER_SUPPLY_PROP_CHARGE_TYPE 0x01 +#define GB_POWER_SUPPLY_PROP_HEALTH 0x02 +#define GB_POWER_SUPPLY_PROP_PRESENT 0x03 +#define GB_POWER_SUPPLY_PROP_ONLINE 0x04 +#define GB_POWER_SUPPLY_PROP_AUTHENTIC 0x05 +#define GB_POWER_SUPPLY_PROP_TECHNOLOGY 0x06 +#define GB_POWER_SUPPLY_PROP_CYCLE_COUNT 0x07 +#define GB_POWER_SUPPLY_PROP_VOLTAGE_MAX 0x08 +#define GB_POWER_SUPPLY_PROP_VOLTAGE_MIN 0x09 +#define GB_POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN 0x0A +#define GB_POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN 0x0B +#define GB_POWER_SUPPLY_PROP_VOLTAGE_NOW 0x0C +#define GB_POWER_SUPPLY_PROP_VOLTAGE_AVG 0x0D +#define GB_POWER_SUPPLY_PROP_VOLTAGE_OCV 0x0E +#define GB_POWER_SUPPLY_PROP_VOLTAGE_BOOT 0x0F +#define GB_POWER_SUPPLY_PROP_CURRENT_MAX 0x10 +#define GB_POWER_SUPPLY_PROP_CURRENT_NOW 0x11 +#define GB_POWER_SUPPLY_PROP_CURRENT_AVG 0x12 +#define GB_POWER_SUPPLY_PROP_CURRENT_BOOT 0x13 +#define GB_POWER_SUPPLY_PROP_POWER_NOW 0x14 +#define GB_POWER_SUPPLY_PROP_POWER_AVG 0x15 +#define GB_POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN 0x16 +#define GB_POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN 0x17 +#define GB_POWER_SUPPLY_PROP_CHARGE_FULL 0x18 +#define GB_POWER_SUPPLY_PROP_CHARGE_EMPTY 0x19 +#define GB_POWER_SUPPLY_PROP_CHARGE_NOW 0x1A +#define GB_POWER_SUPPLY_PROP_CHARGE_AVG 0x1B +#define GB_POWER_SUPPLY_PROP_CHARGE_COUNTER 0x1C +#define GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT 0x1D +#define GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX 0x1E +#define GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE 0x1F +#define GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX 0x20 +#define GB_POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT 0x21 +#define GB_POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX 0x22 +#define GB_POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT 0x23 +#define GB_POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN 0x24 +#define GB_POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN 0x25 +#define GB_POWER_SUPPLY_PROP_ENERGY_FULL 0x26 +#define GB_POWER_SUPPLY_PROP_ENERGY_EMPTY 0x27 +#define GB_POWER_SUPPLY_PROP_ENERGY_NOW 0x28 +#define GB_POWER_SUPPLY_PROP_ENERGY_AVG 0x29 +#define GB_POWER_SUPPLY_PROP_CAPACITY 0x2A +#define GB_POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN 0x2B +#define GB_POWER_SUPPLY_PROP_CAPACITY_ALERT_MAX 0x2C +#define GB_POWER_SUPPLY_PROP_CAPACITY_LEVEL 0x2D +#define GB_POWER_SUPPLY_PROP_TEMP 0x2E +#define GB_POWER_SUPPLY_PROP_TEMP_MAX 0x2F +#define GB_POWER_SUPPLY_PROP_TEMP_MIN 0x30 +#define GB_POWER_SUPPLY_PROP_TEMP_ALERT_MIN 0x31 +#define GB_POWER_SUPPLY_PROP_TEMP_ALERT_MAX 0x32 +#define GB_POWER_SUPPLY_PROP_TEMP_AMBIENT 0x33 +#define GB_POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MIN 0x34 +#define GB_POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MAX 0x35 +#define GB_POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW 0x36 +#define GB_POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG 0x37 +#define GB_POWER_SUPPLY_PROP_TIME_TO_FULL_NOW 0x38 +#define GB_POWER_SUPPLY_PROP_TIME_TO_FULL_AVG 0x39 +#define GB_POWER_SUPPLY_PROP_TYPE 0x3A +#define GB_POWER_SUPPLY_PROP_SCOPE 0x3B +#define GB_POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT 0x3C +#define GB_POWER_SUPPLY_PROP_CALIBRATE 0x3D + __u8 is_writeable; +} __packed; + +struct gb_power_supply_get_property_descriptors_request { + __u8 psy_id; +} __packed; + +struct gb_power_supply_get_property_descriptors_response { + __u8 properties_count; + struct gb_power_supply_props_desc props[]; +} __packed; + +struct gb_power_supply_get_property_request { + __u8 psy_id; + __u8 property; +} __packed; + +struct gb_power_supply_get_property_response { + __le32 prop_val; +}; + +struct gb_power_supply_set_property_request { + __u8 psy_id; + __u8 property; + __le32 prop_val; +} __packed; + +struct gb_power_supply_event_request { + __u8 psy_id; + __u8 event; +#define GB_POWER_SUPPLY_UPDATE 0x01 } __packed; diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index f3cb189..d9bf159 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -289,4 +289,11 @@ static inline bool led_sysfs_is_disabled(struct led_classdev *led_cdev) #include #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) +/* + * Power supply get by name need to drop reference after call + */ +#define PSY_HAVE_PUT +#endif + #endif /* __GREYBUS_KERNEL_VER_H */ diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c index d7797a2..4a73816 100644 --- a/drivers/staging/greybus/power_supply.c +++ b/drivers/staging/greybus/power_supply.c @@ -1,308 +1,742 @@ /* * Power Supply driver for a Greybus module. * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. * * Released under the GPLv2 only. */ #include #include -#include #include +#include + #include "greybus.h" +#define PROP_MAX 32 + +struct gb_power_supply_prop { + enum power_supply_property prop; + u32 val; + u32 previous_val; + bool is_writeable; +}; + struct gb_power_supply { - /* - * The power supply api changed in 4.1, so handle both the old - * and new apis in the same driver for now, until this is merged - * upstream, when all of these version checks can be removed. - */ + u8 id; #ifdef DRIVER_OWNS_PSY_STRUCT - struct power_supply psy; + struct power_supply psy; #define to_gb_power_supply(x) container_of(x, struct gb_power_supply, psy) #else - struct power_supply *psy; - struct power_supply_desc desc; + struct power_supply *psy; + struct power_supply_desc desc; #define to_gb_power_supply(x) power_supply_get_drvdata(x) #endif - // FIXME - // we will want to keep the power supply stats in here as we will be - // getting updates from the SVC "on the fly" so we don't have to always - // go ask the power supply for some information. Hopefully... - struct gb_connection *connection; + char name[64]; + struct gb_power_supplies *supplies; + struct delayed_work work; + char *manufacturer; + char *model_name; + char *serial_number; + u8 type; + u8 properties_count; + u8 properties_count_str; + unsigned long last_update; + unsigned int update_interval; + bool changed; + struct gb_power_supply_prop *props; + enum power_supply_property *props_raw; +}; + +struct gb_power_supplies { + struct gb_connection *connection; + u8 supplies_count; + struct gb_power_supply *supply; + struct mutex supplies_lock; +}; + +/* cache time in milliseconds, if cache_time is set to 0 cache is disable */ +static unsigned int cache_time = 1000; +/* + * update interval initial and maximum value, between the two will + * back-off exponential + */ +static unsigned int update_interval_init = 1 * HZ; +static unsigned int update_interval_max = 30 * HZ; + +struct gb_power_supply_changes { + enum power_supply_property prop; + u32 tolerance_change; +}; +static const struct gb_power_supply_changes psy_props_changes[] = { + { .prop = GB_POWER_SUPPLY_PROP_STATUS, + .tolerance_change = 0, + }, + { .prop = GB_POWER_SUPPLY_PROP_TEMP, + .tolerance_change = 500, + }, + { .prop = GB_POWER_SUPPLY_PROP_ONLINE, + .tolerance_change = 0, + }, }; -static int get_tech(struct gb_power_supply *gb) +static struct gb_connection *get_conn_from_psy(struct gb_power_supply *gbpsy) { - struct gb_power_supply_technology_response tech_response; - u32 technology; - int retval; + return gbpsy->supplies->connection; +} - retval = gb_operation_sync(gb->connection, - GB_POWER_SUPPLY_TYPE_TECHNOLOGY, - NULL, 0, - &tech_response, sizeof(tech_response)); - if (retval) - return retval; +static struct gb_power_supply_prop *get_psy_prop(struct gb_power_supply *gbpsy, + enum power_supply_property psp) +{ + int i; - /* - * Map greybus values to power_supply values. Hopefully these are - * "identical" which should allow gcc to optimize the code away to - * nothing. - */ - technology = le32_to_cpu(tech_response.technology); - switch (technology) { - case GB_POWER_SUPPLY_TECH_NiMH: - technology = POWER_SUPPLY_TECHNOLOGY_NiMH; - break; - case GB_POWER_SUPPLY_TECH_LION: - technology = POWER_SUPPLY_TECHNOLOGY_LION; - break; - case GB_POWER_SUPPLY_TECH_LIPO: - technology = POWER_SUPPLY_TECHNOLOGY_LIPO; - break; - case GB_POWER_SUPPLY_TECH_LiFe: - technology = POWER_SUPPLY_TECHNOLOGY_LiFe; - break; - case GB_POWER_SUPPLY_TECH_NiCd: - technology = POWER_SUPPLY_TECHNOLOGY_NiCd; - break; - case GB_POWER_SUPPLY_TECH_LiMn: - technology = POWER_SUPPLY_TECHNOLOGY_LiMn; - break; - case GB_POWER_SUPPLY_TECH_UNKNOWN: - default: - technology = POWER_SUPPLY_TECHNOLOGY_UNKNOWN; - break; + for (i = 0; i < gbpsy->properties_count; i++) + if (gbpsy->props[i].prop == psp) + return &gbpsy->props[i]; + return NULL; +} + +static int is_psy_prop_writeable(struct gb_power_supply *gbpsy, + enum power_supply_property psp) +{ + struct gb_power_supply_prop *prop; + + prop = get_psy_prop(gbpsy, psp); + if (!prop) + return -ENOENT; + return prop->is_writeable ? 1 : 0; +} + +static int is_prop_valint(enum power_supply_property psp) +{ + return ((psp < POWER_SUPPLY_PROP_MODEL_NAME) ? 1 : 0); +} + +static void next_interval(struct gb_power_supply *gbpsy) +{ + if (gbpsy->update_interval == update_interval_max) + return; + + /* do some exponential back-off in the update interval */ + gbpsy->update_interval *= 2; + if (gbpsy->update_interval > update_interval_max) + gbpsy->update_interval = update_interval_max; +} + +#ifdef DRIVER_OWNS_PSY_STRUCT +static void __gb_power_supply_changed(struct gb_power_supply *gbpsy) +{ + power_supply_changed(&gbpsy->psy); +} +#else +static void __gb_power_supply_changed(struct gb_power_supply *gbpsy) +{ + power_supply_changed(gbpsy->psy); +} +#endif + +static void check_changed(struct gb_power_supply *gbpsy, + struct gb_power_supply_prop *prop) +{ + const struct gb_power_supply_changes *psyc; + u32 val = prop->val; + u32 prev_val = prop->previous_val; + int i; + + for (i = 0; i < ARRAY_SIZE(psy_props_changes); i++) { + psyc = &psy_props_changes[i]; + if (prop->prop == psyc->prop) { + if (!psyc->tolerance_change) + gbpsy->changed = true; + else if (val < prev_val && + prev_val - val > psyc->tolerance_change) + gbpsy->changed = true; + else if (val > prev_val && + val - prev_val > psyc->tolerance_change) + gbpsy->changed = true; + break; + } } - return technology; } -static int get_status(struct gb_power_supply *gb) +static int total_props(struct gb_power_supply *gbpsy) { - struct gb_power_supply_status_response status_response; - u16 psy_status; - int retval; + /* this return the intval plus the strval properties */ + return (gbpsy->properties_count + gbpsy->properties_count_str); +} - retval = gb_operation_sync(gb->connection, GB_POWER_SUPPLY_TYPE_STATUS, - NULL, 0, - &status_response, sizeof(status_response)); - if (retval) - return retval; +static void prop_append(struct gb_power_supply *gbpsy, + enum power_supply_property prop) +{ + enum power_supply_property *new_props_raw; + + gbpsy->properties_count_str++; + new_props_raw = krealloc(gbpsy->props_raw, total_props(gbpsy) * + sizeof(enum power_supply_property), + GFP_KERNEL); + if (!new_props_raw) + return; + gbpsy->props_raw = new_props_raw; + gbpsy->props_raw[total_props(gbpsy) - 1] = prop; +} + +static int __gb_power_supply_set_name(char *init_name, char *name, size_t len) +{ + unsigned int i = 0; + int ret = 0; + struct power_supply *psy; + + if (!strlen(init_name)) + init_name = "gb_power_supply"; + strlcpy(name, init_name, len); + + while ((ret < len) && (psy = power_supply_get_by_name(name))) { +#ifdef PSY_HAVE_PUT + power_supply_put(psy); +#endif + ret = snprintf(name, len, "%s_%u", init_name, ++i); + } + if (ret >= len) + return -ENOMEM; + return i; +} + +static void _gb_power_supply_append_props(struct gb_power_supply *gbpsy) +{ + if (strlen(gbpsy->manufacturer)) + prop_append(gbpsy, POWER_SUPPLY_PROP_MANUFACTURER); + if (strlen(gbpsy->model_name)) + prop_append(gbpsy, POWER_SUPPLY_PROP_MODEL_NAME); + if (strlen(gbpsy->serial_number)) + prop_append(gbpsy, POWER_SUPPLY_PROP_SERIAL_NUMBER); +} + +static int gb_power_supply_description_get(struct gb_power_supply *gbpsy) +{ + struct gb_connection *connection = get_conn_from_psy(gbpsy); + struct gb_power_supply_get_description_request req; + struct gb_power_supply_get_description_response resp; + int ret; + + req.psy_id = gbpsy->id; + + ret = gb_operation_sync(connection, + GB_POWER_SUPPLY_TYPE_GET_DESCRIPTION, + &req, sizeof(req), &resp, sizeof(resp)); + if (ret < 0) + return ret; + + gbpsy->manufacturer = kstrndup(resp.manufacturer, PROP_MAX, GFP_KERNEL); + if (!gbpsy->manufacturer) + return -ENOMEM; + gbpsy->model_name = kstrndup(resp.model, PROP_MAX, GFP_KERNEL); + if (!gbpsy->model_name) + return -ENOMEM; + gbpsy->serial_number = kstrndup(resp.serial_number, PROP_MAX, + GFP_KERNEL); + if (!gbpsy->serial_number) + return -ENOMEM; + + gbpsy->type = le16_to_cpu(resp.type); + gbpsy->properties_count = resp.properties_count; + + return 0; +} + +static int gb_power_supply_prop_descriptors_get(struct gb_power_supply *gbpsy) +{ + struct gb_connection *connection = get_conn_from_psy(gbpsy); + struct gb_power_supply_get_property_descriptors_request req; + struct gb_power_supply_get_property_descriptors_response resp; + int ret; + int i; + + if (gbpsy->properties_count == 0) + return 0; + + req.psy_id = gbpsy->id; + + ret = gb_operation_sync(connection, + GB_POWER_SUPPLY_TYPE_GET_PROP_DESCRIPTORS, + &req, sizeof(req), &resp, + sizeof(resp) + gbpsy->properties_count * + sizeof(struct gb_power_supply_props_desc)); + if (ret < 0) + return ret; + + gbpsy->props = kcalloc(gbpsy->properties_count, sizeof(*gbpsy->props), + GFP_KERNEL); + if (!gbpsy->props) + return -ENOMEM; + + gbpsy->props_raw = kzalloc(gbpsy->properties_count * + sizeof(*gbpsy->props_raw), GFP_KERNEL); + if (!gbpsy->props_raw) + return -ENOMEM; + + /* Store available properties */ + for (i = 0; i < gbpsy->properties_count; i++) { + gbpsy->props[i].prop = resp.props[i].property; + gbpsy->props_raw[i] = resp.props[i].property; + if (resp.props[i].is_writeable) + gbpsy->props[i].is_writeable = true; + } /* - * Map greybus values to power_supply values. Hopefully these are - * "identical" which should allow gcc to optimize the code away to - * nothing. + * now append the properties that we already got information in the + * get_description operation. (char * ones) */ - psy_status = le16_to_cpu(status_response.psy_status); - switch (psy_status) { - case GB_POWER_SUPPLY_STATUS_CHARGING: - psy_status = POWER_SUPPLY_STATUS_CHARGING; - break; - case GB_POWER_SUPPLY_STATUS_DISCHARGING: - psy_status = POWER_SUPPLY_STATUS_DISCHARGING; + _gb_power_supply_append_props(gbpsy); + + return 0; +} + +static int __gb_power_supply_property_update(struct gb_power_supply *gbpsy, + enum power_supply_property psp) +{ + struct gb_connection *connection = get_conn_from_psy(gbpsy); + struct gb_power_supply_prop *prop; + struct gb_power_supply_get_property_request req; + struct gb_power_supply_get_property_response resp; + u32 val; + int ret; + + prop = get_psy_prop(gbpsy, psp); + if (!prop) + return -EINVAL; + req.psy_id = gbpsy->id; + req.property = (u8)psp; + + ret = gb_operation_sync(connection, GB_POWER_SUPPLY_TYPE_GET_PROPERTY, + &req, sizeof(req), &resp, sizeof(resp)); + if (ret < 0) + return ret; + + val = le32_to_cpu(resp.prop_val); + if (val == prop->val) + return 0; + + prop->previous_val = prop->val; + prop->val = val; + + check_changed(gbpsy, prop); + + return 0; +} + +static int __gb_power_supply_property_get(struct gb_power_supply *gbpsy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct gb_power_supply_prop *prop; + + prop = get_psy_prop(gbpsy, psp); + if (!prop) + return -EINVAL; + + val->intval = prop->val; + return 0; +} + +static int __gb_power_supply_property_strval_get(struct gb_power_supply *gbpsy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + switch (psp) { + case POWER_SUPPLY_PROP_MODEL_NAME: + val->strval = kstrndup(gbpsy->model_name, PROP_MAX, GFP_KERNEL); break; - case GB_POWER_SUPPLY_STATUS_NOT_CHARGING: - psy_status = POWER_SUPPLY_STATUS_NOT_CHARGING; + case POWER_SUPPLY_PROP_MANUFACTURER: + val->strval = kstrndup(gbpsy->manufacturer, PROP_MAX, + GFP_KERNEL); break; - case GB_POWER_SUPPLY_STATUS_FULL: - psy_status = POWER_SUPPLY_STATUS_FULL; + case POWER_SUPPLY_PROP_SERIAL_NUMBER: + val->strval = kstrndup(gbpsy->serial_number, PROP_MAX, + GFP_KERNEL); break; - case GB_POWER_SUPPLY_STATUS_UNKNOWN: default: - psy_status = POWER_SUPPLY_STATUS_UNKNOWN; break; } - return psy_status; + + return 0; } -static int get_max_voltage(struct gb_power_supply *gb) +static int _gb_power_supply_property_get(struct gb_power_supply *gbpsy, + enum power_supply_property psp, + union power_supply_propval *val) { - struct gb_power_supply_max_voltage_response volt_response; - u32 max_voltage; - int retval; + struct gb_connection *connection = get_conn_from_psy(gbpsy); + int ret; + + /* + * Properties of type const char *, were already fetched on + * get_description operation and should be cached in gb + */ + if (is_prop_valint(psp)) + ret = __gb_power_supply_property_get(gbpsy, psp, val); + else + ret = __gb_power_supply_property_strval_get(gbpsy, psp, val); - retval = gb_operation_sync(gb->connection, - GB_POWER_SUPPLY_TYPE_MAX_VOLTAGE, - NULL, 0, - &volt_response, sizeof(volt_response)); - if (retval) - return retval; + if (ret < 0) + dev_err(&connection->bundle->dev, "get property %u\n", psp); - max_voltage = le32_to_cpu(volt_response.max_voltage); - return max_voltage; + return 0; } -static int get_percent_capacity(struct gb_power_supply *gb) +static int gb_power_supply_status_get(struct gb_power_supply *gbpsy) { - struct gb_power_supply_capacity_response capacity_response; - u32 capacity; - int retval; + int ret = 0; + int i; + + /* check if cache is good enough */ + if (gbpsy->last_update && + time_is_after_jiffies(gbpsy->last_update + + msecs_to_jiffies(cache_time))) + return 0; + + for (i = 0; i < gbpsy->properties_count; i++) { + ret = __gb_power_supply_property_update(gbpsy, + gbpsy->props[i].prop); + if (ret < 0) + break; + } - retval = gb_operation_sync(gb->connection, - GB_POWER_SUPPLY_TYPE_PERCENT_CAPACITY, - NULL, 0, &capacity_response, - sizeof(capacity_response)); - if (retval) - return retval; + if (ret == 0) + gbpsy->last_update = jiffies; - capacity = le32_to_cpu(capacity_response.capacity); - return capacity; + return ret; } -static int get_temp(struct gb_power_supply *gb) +static void gb_power_supply_status_update(struct gb_power_supply *gbpsy) { - struct gb_power_supply_temperature_response temp_response; - u32 temperature; - int retval; + /* check if there a change that need to be reported */ + gb_power_supply_status_get(gbpsy); - retval = gb_operation_sync(gb->connection, - GB_POWER_SUPPLY_TYPE_TEMPERATURE, - NULL, 0, - &temp_response, sizeof(temp_response)); - if (retval) - return retval; + if (!gbpsy->changed) + return; - temperature = le32_to_cpu(temp_response.temperature); - return temperature; + gbpsy->update_interval = update_interval_init; + __gb_power_supply_changed(gbpsy); + gbpsy->changed = false; } -static int get_voltage(struct gb_power_supply *gb) +static void gb_power_supply_work(struct work_struct *work) { - struct gb_power_supply_voltage_response voltage_response; - u32 voltage; - int retval; + struct gb_power_supply *gbpsy = container_of(work, + struct gb_power_supply, + work.work); - retval = gb_operation_sync(gb->connection, GB_POWER_SUPPLY_TYPE_VOLTAGE, - NULL, 0, - &voltage_response, sizeof(voltage_response)); - if (retval) - return retval; + /* + * if the poll interval is not set, disable polling, this is helpful + * specially at unregister time. + */ + if (!gbpsy->update_interval) + return; - voltage = le32_to_cpu(voltage_response.voltage); - return voltage; + gb_power_supply_status_update(gbpsy); + next_interval(gbpsy); + schedule_delayed_work(&gbpsy->work, gbpsy->update_interval); } static int get_property(struct power_supply *b, enum power_supply_property psp, union power_supply_propval *val) { - struct gb_power_supply *gb = to_gb_power_supply(b); + struct gb_power_supply *gbpsy = to_gb_power_supply(b); - switch (psp) { - case POWER_SUPPLY_PROP_TECHNOLOGY: - val->intval = get_tech(gb); - break; + gb_power_supply_status_get(gbpsy); - case POWER_SUPPLY_PROP_STATUS: - val->intval = get_status(gb); - break; + return _gb_power_supply_property_get(gbpsy, psp, val); +} - case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: - val->intval = get_max_voltage(gb); - break; +static int gb_power_supply_property_set(struct gb_power_supply *gbpsy, + enum power_supply_property psp, + int val) +{ + struct gb_connection *connection = get_conn_from_psy(gbpsy); + struct gb_power_supply_prop *prop; + struct gb_power_supply_set_property_request req; + int ret; - case POWER_SUPPLY_PROP_CAPACITY: - val->intval = get_percent_capacity(gb); - break; + prop = get_psy_prop(gbpsy, psp); + if (!prop) + return -EINVAL; + req.psy_id = gbpsy->id; + req.property = (u8)psp; + req.prop_val = cpu_to_le32(val); - case POWER_SUPPLY_PROP_TEMP: - val->intval = get_temp(gb); - break; + ret = gb_operation_sync(connection, GB_POWER_SUPPLY_TYPE_SET_PROPERTY, + &req, sizeof(req), NULL, 0); + if (ret < 0) + goto out; - case POWER_SUPPLY_PROP_VOLTAGE_NOW: - val->intval = get_voltage(gb); - break; + /* cache immediately the new value */ + prop->val = val; - default: - return -EINVAL; - } +out: + return ret; +} - return (val->intval < 0) ? val->intval : 0; +static int set_property(struct power_supply *b, + enum power_supply_property psp, + const union power_supply_propval *val) +{ + struct gb_power_supply *gbpsy = to_gb_power_supply(b); + + return gb_power_supply_property_set(gbpsy, psp, val->intval); +} + +static int property_is_writeable(struct power_supply *b, + enum power_supply_property psp) +{ + struct gb_power_supply *gbpsy = to_gb_power_supply(b); + + return is_psy_prop_writeable(gbpsy, psp); } -// FIXME - verify this list, odds are some can be removed and others added. -static enum power_supply_property psy_props[] = { - POWER_SUPPLY_PROP_TECHNOLOGY, - POWER_SUPPLY_PROP_STATUS, - POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, - POWER_SUPPLY_PROP_CAPACITY, - POWER_SUPPLY_PROP_TEMP, - POWER_SUPPLY_PROP_VOLTAGE_NOW, -}; #ifdef DRIVER_OWNS_PSY_STRUCT -static int init_and_register(struct gb_connection *connection, - struct gb_battery *gb) +static int gb_power_supply_register(struct gb_power_supply *gbpsy) { - // FIXME - get a better (i.e. unique) name - // FIXME - anything else needs to be set? - gb->psy.name = "gb_battery"; - gb->psy.type = POWER_SUPPLY_TYPE_BATTERY; - gb->psy.properties = psy_props; - gb->psy.num_properties = ARRAY_SIZE(psy_props); - gb->psy.get_property = get_property; - - return power_supply_register(&connection->bundle->dev, &gb->psy); + struct gb_connection *connection = get_conn_from_psy(gbpsy); + + gbpsy->psy.name = gbpsy->name; + gbpsy->psy.type = gbpsy->type; + gbpsy->psy.properties = gbpsy->props_raw; + gbpsy->psy.num_properties = total_props(gbpsy); + gbpsy->psy.get_property = get_property; + gbpsy->psy.set_property = set_property; + gbpsy->psy.property_is_writeable = property_is_writeable; + + return power_supply_register(&connection->bundle->dev, + &gbpsy->psy); } #else -static int init_and_register(struct gb_connection *connection, - struct gb_power_supply *gb) +static int gb_power_supply_register(struct gb_power_supply *gbpsy) { + struct gb_connection *connection = get_conn_from_psy(gbpsy); struct power_supply_config cfg = {}; - cfg.drv_data = gb; + cfg.drv_data = gbpsy; - // FIXME - get a better (i.e. unique) name - // FIXME - anything else needs to be set? - gb->desc.name = "gb_battery"; - gb->desc.type = POWER_SUPPLY_TYPE_BATTERY; - gb->desc.properties = psy_props; - gb->desc.num_properties = ARRAY_SIZE(psy_props); - gb->desc.get_property = get_property; + gbpsy->desc.name = gbpsy->name; + gbpsy->desc.type = gbpsy->type; + gbpsy->desc.properties = gbpsy->props_raw; + gbpsy->desc.num_properties = total_props(gbpsy); + gbpsy->desc.get_property = get_property; + gbpsy->desc.set_property = set_property; + gbpsy->desc.property_is_writeable = property_is_writeable; - gb->psy = power_supply_register(&connection->bundle->dev, - &gb->desc, &cfg); - if (IS_ERR(gb->psy)) - return PTR_ERR(gb->psy); + gbpsy->psy = power_supply_register(&connection->bundle->dev, + &gbpsy->desc, &cfg); + if (IS_ERR(gbpsy->psy)) + return PTR_ERR(gbpsy->psy); return 0; } #endif +static void _gb_power_supply_free(struct gb_power_supply *gbpsy) +{ + kfree(gbpsy->serial_number); + kfree(gbpsy->model_name); + kfree(gbpsy->manufacturer); + kfree(gbpsy->props_raw); + kfree(gbpsy->props); + kfree(gbpsy); +} + +static void _gb_power_supply_release(struct gb_power_supply *gbpsy) +{ + if (!gbpsy) + return; + + gbpsy->update_interval = 0; + + cancel_delayed_work_sync(&gbpsy->work); +#ifdef DRIVER_OWNS_PSY_STRUCT + power_supply_unregister(&gbpsy->psy); +#else + power_supply_unregister(gbpsy->psy); +#endif + + _gb_power_supply_free(gbpsy); +} + +static void _gb_power_supplies_release(struct gb_power_supplies *supplies) +{ + int i; + + mutex_lock(&supplies->supplies_lock); + for (i = 0; i < supplies->supplies_count; i++) + _gb_power_supply_release(&supplies->supply[i]); + mutex_unlock(&supplies->supplies_lock); +} + +static int gb_power_supplies_get_count(struct gb_power_supplies *supplies) +{ + struct gb_power_supply_get_supplies_response resp; + int ret; + + ret = gb_operation_sync(supplies->connection, + GB_POWER_SUPPLY_TYPE_GET_SUPPLIES, + NULL, 0, &resp, sizeof(resp)); + if (ret < 0) + return ret; + + if (!resp.supplies_count) + return -EINVAL; + + supplies->supplies_count = resp.supplies_count; + + return ret; +} + +static int gb_power_supply_config(struct gb_power_supplies *supplies, int id) +{ + struct gb_power_supply *gbpsy = &supplies->supply[id]; + int ret; + + gbpsy->supplies = supplies; + gbpsy->id = id; + + ret = gb_power_supply_description_get(gbpsy); + if (ret < 0) + goto out; + + ret = gb_power_supply_prop_descriptors_get(gbpsy); + if (ret < 0) + goto out; + + /* guarantee that we have an unique name, before register */ + ret = __gb_power_supply_set_name(gbpsy->model_name, gbpsy->name, + sizeof(gbpsy->name)); + if (ret < 0) + goto out; + + ret = gb_power_supply_register(gbpsy); + if (ret < 0) + goto out; + + gbpsy->update_interval = update_interval_init; + INIT_DELAYED_WORK(&gbpsy->work, gb_power_supply_work); + schedule_delayed_work(&gbpsy->work, 0); + +out: + return ret; +} + +static int gb_power_supplies_setup(struct gb_power_supplies *supplies) +{ + struct gb_connection *connection = supplies->connection; + int ret; + int i; + + mutex_lock(&supplies->supplies_lock); + + ret = gb_power_supplies_get_count(supplies); + if (ret < 0) + goto out; + + supplies->supply = kzalloc(supplies->supplies_count * + sizeof(struct gb_power_supply), + GFP_KERNEL); + + if (!supplies->supply) + return -ENOMEM; + + for (i = 0; i < supplies->supplies_count; i++) { + ret = gb_power_supply_config(supplies, i); + if (ret < 0) { + dev_err(&connection->bundle->dev, + "Fail to configure supplies devices\n"); + goto out; + } + } +out: + mutex_unlock(&supplies->supplies_lock); + return ret; +} + +static int gb_power_supply_event_recv(u8 type, struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_power_supplies *supplies = connection->private; + struct gb_power_supply *gbpsy; + struct gb_message *request; + struct gb_power_supply_event_request *payload; + u8 psy_id; + u8 event; + int ret = 0; + + if (type != GB_POWER_SUPPLY_TYPE_EVENT) { + dev_err(&connection->bundle->dev, + "Unsupported unsolicited event: %u\n", type); + return -EINVAL; + } + + request = op->request; + + if (request->payload_size < sizeof(*payload)) { + dev_err(&connection->bundle->dev, + "Wrong event size received (%zu < %zu)\n", + request->payload_size, sizeof(*payload)); + return -EINVAL; + } + + payload = request->payload; + psy_id = payload->psy_id; + mutex_lock(&supplies->supplies_lock); + if (psy_id >= supplies->supplies_count || !&supplies->supply[psy_id]) { + dev_err(&connection->bundle->dev, + "Event received for unconfigured power_supply id: %d\n", + psy_id); + ret = -EINVAL; + goto out_unlock; + } + + event = payload->event; + /* + * we will only handle events after setup is done and before release is + * running. For that just check update_interval. + */ + gbpsy = &supplies->supply[psy_id]; + if (gbpsy->update_interval) { + ret = -ESHUTDOWN; + goto out_unlock; + } + + if (event & GB_POWER_SUPPLY_UPDATE) + gb_power_supply_status_update(gbpsy); + +out_unlock: + mutex_unlock(&supplies->supplies_lock); + return ret; +} + static int gb_power_supply_connection_init(struct gb_connection *connection) { - struct gb_power_supply *gb; - int retval; + struct gb_power_supplies *supplies; - gb = kzalloc(sizeof(*gb), GFP_KERNEL); - if (!gb) + supplies = kzalloc(sizeof(*supplies), GFP_KERNEL); + if (!supplies) return -ENOMEM; - gb->connection = connection; - connection->private = gb; + supplies->connection = connection; + connection->private = supplies; - retval = init_and_register(connection, gb); - if (retval) - kfree(gb); + mutex_init(&supplies->supplies_lock); - return retval; + return gb_power_supplies_setup(supplies); } static void gb_power_supply_connection_exit(struct gb_connection *connection) { - struct gb_power_supply *gb = connection->private; + struct gb_power_supplies *supplies = connection->private; -#ifdef DRIVER_OWNS_PSY_STRUCT - power_supply_unregister(&gb->psy); -#else - power_supply_unregister(gb->psy); -#endif - kfree(gb); + _gb_power_supplies_release(supplies); } static struct gb_protocol power_supply_protocol = { @@ -312,7 +746,7 @@ static struct gb_protocol power_supply_protocol = { .minor = GB_POWER_SUPPLY_VERSION_MINOR, .connection_init = gb_power_supply_connection_init, .connection_exit = gb_power_supply_connection_exit, - .request_recv = NULL, /* no incoming requests */ + .request_recv = gb_power_supply_event_recv, }; gb_protocol_driver(&power_supply_protocol); -- cgit v0.10.2 From bf6a61bd2f36245c3d2d62b411cea48f10b7f4dd Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 13 Nov 2015 08:59:49 +0530 Subject: greybus: es2: remove fake vendor/product ids These aren't used anymore, remove them. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index a0e2037..0eb9645 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -22,7 +22,6 @@ #define ES2_GBUF_MSG_SIZE_MAX 2048 static const struct usb_device_id id_table[] = { - { USB_DEVICE(0xffff, 0x0002) }, /* Made up number, delete once firmware is fixed to use real number */ { USB_DEVICE(0x18d1, 0x1eaf) }, { }, }; -- cgit v0.10.2 From e3c25930d90216f7f6e536136a70daee7450604c Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 13 Nov 2015 08:59:50 +0530 Subject: greybus: es1: Remove the (now) unused es1 driver This was used by gbsim earlier, but not anymore. Lets remove it. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index c3572b3..2c1f974 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -29,7 +29,6 @@ gb-loopback-y := loopback.o gb-light-y := light.o gb-raw-y := raw.o gb-hid-y := hid.o -gb-es1-y := es1.o gb-es2-y := es2.o gb-db3-y := db3-platform.o @@ -41,7 +40,6 @@ obj-m += gb-loopback.o obj-m += gb-light.o obj-m += gb-hid.o obj-m += gb-raw.o -obj-m += gb-es1.o obj-m += gb-es2.o obj-m += gb-db3.o diff --git a/drivers/staging/greybus/es1.c b/drivers/staging/greybus/es1.c deleted file mode 100644 index 75253d9..0000000 --- a/drivers/staging/greybus/es1.c +++ /dev/null @@ -1,729 +0,0 @@ -/* - * Greybus "AP" USB driver for "ES1" controller chips - * - * Copyright 2014-2015 Google Inc. - * Copyright 2014-2015 Linaro Ltd. - * - * Released under the GPLv2 only. - */ -#include -#include -#include -#include -#include -#include - -#include "greybus.h" -#include "kernel_ver.h" -#include "connection.h" -#include "greybus_trace.h" - -/* Memory sizes for the buffers sent to/from the ES1 controller */ -#define ES1_GBUF_MSG_SIZE_MAX 2048 - -static const struct usb_device_id id_table[] = { - /* Made up numbers for the SVC USB Bridge in ES1 */ - { USB_DEVICE(0xffff, 0x0001) }, - { }, -}; -MODULE_DEVICE_TABLE(usb, id_table); - -#define APB1_LOG_SIZE SZ_16K -static struct dentry *apb1_log_dentry; -static struct dentry *apb1_log_enable_dentry; -static struct task_struct *apb1_log_task; -static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE); - -/* Number of CPorts supported by es1 */ -#define CPORT_COUNT 256 - -/* - * Number of CPort IN urbs in flight at any point in time. - * Adjust if we are having stalls in the USB buffer due to not enough urbs in - * flight. - */ -#define NUM_CPORT_IN_URB 4 - -/* Number of CPort OUT urbs in flight at any point in time. - * Adjust if we get messages saying we are out of urbs in the system log. - */ -#define NUM_CPORT_OUT_URB 8 - -/* vendor request APB1 log */ -#define REQUEST_LOG 0x02 - -/* vendor request to time the latency of messages on a given cport */ -#define REQUEST_LATENCY_TAG_EN 0x06 -#define REQUEST_LATENCY_TAG_DIS 0x07 - -/** - * es1_ap_dev - ES1 USB Bridge to AP structure - * @usb_dev: pointer to the USB device we are. - * @usb_intf: pointer to the USB interface we are bound to. - * @hd: pointer to our gb_host_device structure - * @cport_in_endpoint: bulk in endpoint for CPort data - * @cport-out_endpoint: bulk out endpoint for CPort data - * @cport_in_urb: array of urbs for the CPort in messages - * @cport_in_buffer: array of buffers for the @cport_in_urb urbs - * @cport_out_urb: array of urbs for the CPort out messages - * @cport_out_urb_busy: array of flags to see if the @cport_out_urb is busy or - * not. - * @cport_out_urb_cancelled: array of flags indicating whether the - * corresponding @cport_out_urb is being cancelled - * @cport_out_urb_lock: locks the @cport_out_urb_busy "list" - */ -struct es1_ap_dev { - struct usb_device *usb_dev; - struct usb_interface *usb_intf; - struct gb_host_device *hd; - - __u8 cport_in_endpoint; - __u8 cport_out_endpoint; - - struct urb *cport_in_urb[NUM_CPORT_IN_URB]; - u8 *cport_in_buffer[NUM_CPORT_IN_URB]; - struct urb *cport_out_urb[NUM_CPORT_OUT_URB]; - bool cport_out_urb_busy[NUM_CPORT_OUT_URB]; - bool cport_out_urb_cancelled[NUM_CPORT_OUT_URB]; - spinlock_t cport_out_urb_lock; -}; - -static inline struct es1_ap_dev *hd_to_es1(struct gb_host_device *hd) -{ - return (struct es1_ap_dev *)&hd->hd_priv; -} - -static void cport_out_callback(struct urb *urb); -static void usb_log_enable(struct es1_ap_dev *es1); -static void usb_log_disable(struct es1_ap_dev *es1); - -#define ES1_TIMEOUT 500 /* 500 ms for the SVC to do something */ - -static struct urb *next_free_urb(struct es1_ap_dev *es1, gfp_t gfp_mask) -{ - struct urb *urb = NULL; - unsigned long flags; - int i; - - spin_lock_irqsave(&es1->cport_out_urb_lock, flags); - - /* Look in our pool of allocated urbs first, as that's the "fastest" */ - for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - if (es1->cport_out_urb_busy[i] == false && - es1->cport_out_urb_cancelled[i] == false) { - es1->cport_out_urb_busy[i] = true; - urb = es1->cport_out_urb[i]; - break; - } - } - spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); - if (urb) - return urb; - - /* - * Crap, pool is empty, complain to the syslog and go allocate one - * dynamically as we have to succeed. - */ - dev_err(&es1->usb_dev->dev, - "No free CPort OUT urbs, having to dynamically allocate one!\n"); - return usb_alloc_urb(0, gfp_mask); -} - -static void free_urb(struct es1_ap_dev *es1, struct urb *urb) -{ - unsigned long flags; - int i; - /* - * See if this was an urb in our pool, if so mark it "free", otherwise - * we need to free it ourselves. - */ - spin_lock_irqsave(&es1->cport_out_urb_lock, flags); - for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - if (urb == es1->cport_out_urb[i]) { - es1->cport_out_urb_busy[i] = false; - urb = NULL; - break; - } - } - spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); - - /* If urb is not NULL, then we need to free this urb */ - usb_free_urb(urb); -} - -/* - * We (ab)use the operation-message header pad bytes to transfer the - * cport id in order to minimise overhead. - */ -static void -gb_message_cport_pack(struct gb_operation_msg_hdr *header, u16 cport_id) -{ - header->pad[0] = cport_id; -} - -/* Clear the pad bytes used for the CPort id */ -static void gb_message_cport_clear(struct gb_operation_msg_hdr *header) -{ - header->pad[0] = 0; -} - -/* Extract the CPort id packed into the header, and clear it */ -static u16 gb_message_cport_unpack(struct gb_operation_msg_hdr *header) -{ - u16 cport_id = header->pad[0]; - - gb_message_cport_clear(header); - - return cport_id; -} - -/* - * Returns zero if the message was successfully queued, or a negative errno - * otherwise. - */ -static int message_send(struct gb_host_device *hd, u16 cport_id, - struct gb_message *message, gfp_t gfp_mask) -{ - struct es1_ap_dev *es1 = hd_to_es1(hd); - struct usb_device *udev = es1->usb_dev; - size_t buffer_size; - int retval; - struct urb *urb; - unsigned long flags; - - /* - * The data actually transferred will include an indication - * of where the data should be sent. Do one last check of - * the target CPort id before filling it in. - */ - if (!cport_id_valid(hd, cport_id)) { - dev_err(&udev->dev, "invalid destination cport 0x%02x\n", - cport_id); - return -EINVAL; - } - - /* Find a free urb */ - urb = next_free_urb(es1, gfp_mask); - if (!urb) - return -ENOMEM; - - spin_lock_irqsave(&es1->cport_out_urb_lock, flags); - message->hcpriv = urb; - spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); - - /* Pack the cport id into the message header */ - gb_message_cport_pack(message->header, cport_id); - - buffer_size = sizeof(*message->header) + message->payload_size; - - usb_fill_bulk_urb(urb, udev, - usb_sndbulkpipe(udev, es1->cport_out_endpoint), - message->buffer, buffer_size, - cport_out_callback, message); - urb->transfer_flags |= URB_ZERO_PACKET; - trace_gb_host_device_send(hd, cport_id, buffer_size); - retval = usb_submit_urb(urb, gfp_mask); - if (retval) { - dev_err(&udev->dev, "failed to submit out-urb: %d\n", retval); - - spin_lock_irqsave(&es1->cport_out_urb_lock, flags); - message->hcpriv = NULL; - spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); - - free_urb(es1, urb); - gb_message_cport_clear(message->header); - - return retval; - } - - return 0; -} - -/* - * Can not be called in atomic context. - */ -static void message_cancel(struct gb_message *message) -{ - struct gb_host_device *hd = message->operation->connection->hd; - struct es1_ap_dev *es1 = hd_to_es1(hd); - struct urb *urb; - int i; - - might_sleep(); - - spin_lock_irq(&es1->cport_out_urb_lock); - urb = message->hcpriv; - - /* Prevent dynamically allocated urb from being deallocated. */ - usb_get_urb(urb); - - /* Prevent pre-allocated urb from being reused. */ - for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - if (urb == es1->cport_out_urb[i]) { - es1->cport_out_urb_cancelled[i] = true; - break; - } - } - spin_unlock_irq(&es1->cport_out_urb_lock); - - usb_kill_urb(urb); - - if (i < NUM_CPORT_OUT_URB) { - spin_lock_irq(&es1->cport_out_urb_lock); - es1->cport_out_urb_cancelled[i] = false; - spin_unlock_irq(&es1->cport_out_urb_lock); - } - - usb_free_urb(urb); -} - -static int latency_tag_enable(struct gb_host_device *hd, u16 cport_id) -{ - int retval; - struct es1_ap_dev *es1 = hd_to_es1(hd); - struct usb_device *udev = es1->usb_dev; - - if (!cport_id_valid(hd, cport_id)) { - dev_err(&udev->dev, "invalid destination cport 0x%02x\n", - cport_id); - return -EINVAL; - } - - retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - REQUEST_LATENCY_TAG_EN, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_INTERFACE, cport_id, 0, NULL, - 0, ES1_TIMEOUT); - - if (retval < 0) - dev_err(&udev->dev, "Cannot enable latency tag for cport %d\n", - cport_id); - return retval; -} - -static int latency_tag_disable(struct gb_host_device *hd, u16 cport_id) -{ - int retval; - struct es1_ap_dev *es1 = hd_to_es1(hd); - struct usb_device *udev = es1->usb_dev; - - if (!cport_id_valid(hd, cport_id)) { - dev_err(&udev->dev, "invalid destination cport 0x%02x\n", - cport_id); - return -EINVAL; - } - - retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - REQUEST_LATENCY_TAG_DIS, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_INTERFACE, cport_id, 0, NULL, - 0, ES1_TIMEOUT); - - if (retval < 0) - dev_err(&udev->dev, "Cannot disable latency tag for cport %d\n", - cport_id); - return retval; -} - -static struct gb_hd_driver es1_driver = { - .hd_priv_size = sizeof(struct es1_ap_dev), - .message_send = message_send, - .message_cancel = message_cancel, - .latency_tag_enable = latency_tag_enable, - .latency_tag_disable = latency_tag_disable, -}; - -/* Common function to report consistent warnings based on URB status */ -static int check_urb_status(struct urb *urb) -{ - struct device *dev = &urb->dev->dev; - int status = urb->status; - - switch (status) { - case 0: - return 0; - - case -EOVERFLOW: - dev_err(dev, "%s: overflow actual length is %d\n", - __func__, urb->actual_length); - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - case -EILSEQ: - case -EPROTO: - /* device is gone, stop sending */ - return status; - } - dev_err(dev, "%s: unknown status %d\n", __func__, status); - - return -EAGAIN; -} - -static void es1_destroy(struct es1_ap_dev *es1) -{ - struct usb_device *udev; - int i; - - debugfs_remove(apb1_log_enable_dentry); - usb_log_disable(es1); - - /* Tear down everything! */ - for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - struct urb *urb = es1->cport_out_urb[i]; - - if (!urb) - break; - usb_free_urb(urb); - es1->cport_out_urb[i] = NULL; - es1->cport_out_urb_busy[i] = false; /* just to be anal */ - } - - for (i = 0; i < NUM_CPORT_IN_URB; ++i) { - struct urb *urb = es1->cport_in_urb[i]; - - if (!urb) - break; - usb_kill_urb(urb); - usb_free_urb(urb); - kfree(es1->cport_in_buffer[i]); - es1->cport_in_buffer[i] = NULL; - } - - udev = es1->usb_dev; - gb_hd_put(es1->hd); - - usb_put_dev(udev); -} - -static void ap_disconnect(struct usb_interface *interface) -{ - struct es1_ap_dev *es1 = usb_get_intfdata(interface); - int i; - - for (i = 0; i < NUM_CPORT_IN_URB; ++i) - usb_kill_urb(es1->cport_in_urb[i]); - - gb_hd_del(es1->hd); - - es1_destroy(es1); -} - -static void cport_in_callback(struct urb *urb) -{ - struct gb_host_device *hd = urb->context; - struct device *dev = &urb->dev->dev; - struct gb_operation_msg_hdr *header; - int status = check_urb_status(urb); - int retval; - u16 cport_id; - - if (status) { - if ((status == -EAGAIN) || (status == -EPROTO)) - goto exit; - dev_err(dev, "urb cport in error %d (dropped)\n", status); - return; - } - - if (urb->actual_length < sizeof(*header)) { - dev_err(dev, "short message received\n"); - goto exit; - } - - /* Extract the CPort id, which is packed in the message header */ - header = urb->transfer_buffer; - cport_id = gb_message_cport_unpack(header); - - if (cport_id_valid(hd, cport_id)) { - trace_gb_host_device_recv(hd, cport_id, urb->actual_length); - greybus_data_rcvd(hd, cport_id, urb->transfer_buffer, - urb->actual_length); - } else { - dev_err(dev, "invalid cport id 0x%02x received\n", cport_id); - } -exit: - /* put our urb back in the request pool */ - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - dev_err(dev, "failed to resubmit in-urb: %d\n", retval); -} - -static void cport_out_callback(struct urb *urb) -{ - struct gb_message *message = urb->context; - struct gb_host_device *hd = message->operation->connection->hd; - struct es1_ap_dev *es1 = hd_to_es1(hd); - int status = check_urb_status(urb); - unsigned long flags; - - gb_message_cport_clear(message->header); - - spin_lock_irqsave(&es1->cport_out_urb_lock, flags); - message->hcpriv = NULL; - spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags); - - /* - * Tell the submitter that the message send (attempt) is - * complete, and report the status. - */ - greybus_message_sent(hd, message, status); - - free_urb(es1, urb); -} - -#define APB1_LOG_MSG_SIZE 64 -static void apb1_log_get(struct es1_ap_dev *es1, char *buf) -{ - int retval; - - /* SVC messages go down our control pipe */ - do { - retval = usb_control_msg(es1->usb_dev, - usb_rcvctrlpipe(es1->usb_dev, 0), - REQUEST_LOG, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - 0x00, 0x00, - buf, - APB1_LOG_MSG_SIZE, - ES1_TIMEOUT); - if (retval > 0) - kfifo_in(&apb1_log_fifo, buf, retval); - } while (retval > 0); -} - -static int apb1_log_poll(void *data) -{ - struct es1_ap_dev *es1 = data; - char *buf; - - buf = kmalloc(APB1_LOG_MSG_SIZE, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - while (!kthread_should_stop()) { - msleep(1000); - apb1_log_get(es1, buf); - } - - kfree(buf); - - return 0; -} - -static ssize_t apb1_log_read(struct file *f, char __user *buf, - size_t count, loff_t *ppos) -{ - ssize_t ret; - size_t copied; - char *tmp_buf; - - if (count > APB1_LOG_SIZE) - count = APB1_LOG_SIZE; - - tmp_buf = kmalloc(count, GFP_KERNEL); - if (!tmp_buf) - return -ENOMEM; - - copied = kfifo_out(&apb1_log_fifo, tmp_buf, count); - ret = simple_read_from_buffer(buf, count, ppos, tmp_buf, copied); - - kfree(tmp_buf); - - return ret; -} - -static const struct file_operations apb1_log_fops = { - .read = apb1_log_read, -}; - -static void usb_log_enable(struct es1_ap_dev *es1) -{ - if (!IS_ERR_OR_NULL(apb1_log_task)) - return; - - /* get log from APB1 */ - apb1_log_task = kthread_run(apb1_log_poll, es1, "apb1_log"); - if (IS_ERR(apb1_log_task)) - return; - apb1_log_dentry = debugfs_create_file("apb1_log", S_IRUGO, - gb_debugfs_get(), NULL, - &apb1_log_fops); -} - -static void usb_log_disable(struct es1_ap_dev *es1) -{ - if (IS_ERR_OR_NULL(apb1_log_task)) - return; - - debugfs_remove(apb1_log_dentry); - apb1_log_dentry = NULL; - - kthread_stop(apb1_log_task); - apb1_log_task = NULL; -} - -static ssize_t apb1_log_enable_read(struct file *f, char __user *buf, - size_t count, loff_t *ppos) -{ - char tmp_buf[3]; - int enable = !IS_ERR_OR_NULL(apb1_log_task); - - sprintf(tmp_buf, "%d\n", enable); - return simple_read_from_buffer(buf, count, ppos, tmp_buf, 3); -} - -static ssize_t apb1_log_enable_write(struct file *f, const char __user *buf, - size_t count, loff_t *ppos) -{ - int enable; - ssize_t retval; - struct es1_ap_dev *es1 = (struct es1_ap_dev *)f->f_inode->i_private; - - retval = kstrtoint_from_user(buf, count, 10, &enable); - if (retval) - return retval; - - if (enable) - usb_log_enable(es1); - else - usb_log_disable(es1); - - return count; -} - -static const struct file_operations apb1_log_enable_fops = { - .read = apb1_log_enable_read, - .write = apb1_log_enable_write, -}; - -/* - * The ES1 USB Bridge device contains 4 endpoints - * 1 Control - usual USB stuff + AP -> SVC messages - * 1 Interrupt IN - SVC -> AP messages - * 1 Bulk IN - CPort data in - * 1 Bulk OUT - CPort data out - */ -static int ap_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct es1_ap_dev *es1; - struct gb_host_device *hd; - struct usb_device *udev; - struct usb_host_interface *iface_desc; - struct usb_endpoint_descriptor *endpoint; - bool bulk_in_found = false; - bool bulk_out_found = false; - int retval = -ENOMEM; - int i; - - /* We need to fit a CPort ID in one byte of a message header */ - BUILD_BUG_ON(CPORT_COUNT > U8_MAX + 1); - - udev = usb_get_dev(interface_to_usbdev(interface)); - - hd = gb_hd_create(&es1_driver, &udev->dev, ES1_GBUF_MSG_SIZE_MAX, - CPORT_COUNT); - if (IS_ERR(hd)) { - usb_put_dev(udev); - return PTR_ERR(hd); - } - - es1 = hd_to_es1(hd); - es1->hd = hd; - es1->usb_intf = interface; - es1->usb_dev = udev; - spin_lock_init(&es1->cport_out_urb_lock); - usb_set_intfdata(interface, es1); - - /* find all 3 of our endpoints */ - iface_desc = interface->cur_altsetting; - for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { - endpoint = &iface_desc->endpoint[i].desc; - - if (usb_endpoint_is_bulk_in(endpoint)) { - es1->cport_in_endpoint = endpoint->bEndpointAddress; - bulk_in_found = true; - } else if (usb_endpoint_is_bulk_out(endpoint)) { - es1->cport_out_endpoint = endpoint->bEndpointAddress; - bulk_out_found = true; - } else { - dev_err(&udev->dev, - "Unknown endpoint type found, address %x\n", - endpoint->bEndpointAddress); - } - } - if ((bulk_in_found == false) || - (bulk_out_found == false)) { - dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n"); - goto error; - } - - /* Allocate buffers for our cport in messages */ - for (i = 0; i < NUM_CPORT_IN_URB; ++i) { - struct urb *urb; - u8 *buffer; - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) - goto error; - buffer = kmalloc(ES1_GBUF_MSG_SIZE_MAX, GFP_KERNEL); - if (!buffer) - goto error; - - usb_fill_bulk_urb(urb, udev, - usb_rcvbulkpipe(udev, es1->cport_in_endpoint), - buffer, ES1_GBUF_MSG_SIZE_MAX, - cport_in_callback, hd); - es1->cport_in_urb[i] = urb; - es1->cport_in_buffer[i] = buffer; - } - - /* Allocate urbs for our CPort OUT messages */ - for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - struct urb *urb; - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) - goto error; - - es1->cport_out_urb[i] = urb; - es1->cport_out_urb_busy[i] = false; /* just to be anal */ - } - - apb1_log_enable_dentry = debugfs_create_file("apb1_log_enable", - (S_IWUSR | S_IRUGO), - gb_debugfs_get(), es1, - &apb1_log_enable_fops); - - retval = gb_hd_add(hd); - if (retval) - goto error; - - for (i = 0; i < NUM_CPORT_IN_URB; ++i) { - retval = usb_submit_urb(es1->cport_in_urb[i], GFP_KERNEL); - if (retval) - goto err_kill_in_urbs; - } - - return 0; - -err_kill_in_urbs: - for (--i; i >= 0; --i) - usb_kill_urb(es1->cport_in_urb[i]); - gb_hd_del(hd); -error: - es1_destroy(es1); - - return retval; -} - -static struct usb_driver es1_ap_driver = { - .name = "es1_ap_driver", - .probe = ap_probe, - .disconnect = ap_disconnect, - .id_table = id_table, -}; - -module_usb_driver(es1_ap_driver); - -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Greg Kroah-Hartman "); diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h index d38f9e0..a39fa39 100644 --- a/drivers/staging/greybus/greybus_trace.h +++ b/drivers/staging/greybus/greybus_trace.h @@ -132,7 +132,7 @@ DECLARE_EVENT_CLASS(gb_host_device, /* * tracepoint name greybus:gb_host_device_send * description tracepoint representing the point data are transmitted - * location es1.c/es2.c:message_send + * location es2.c:message_send */ DEFINE_EVENT(gb_host_device, gb_host_device_send, @@ -145,7 +145,7 @@ DEFINE_EVENT(gb_host_device, gb_host_device_send, /* * tracepoint name greybus:gb_host_device_recv * description tracepoint representing the point data are received - * location es1.c/es2.c:cport_in_callback + * location es2.c:cport_in_callback */ DEFINE_EVENT(gb_host_device, gb_host_device_recv, -- cgit v0.10.2 From 80ee842825d5f40a21b4257dd98b74f2c92e5f02 Mon Sep 17 00:00:00 2001 From: Mark Greer Date: Fri, 13 Nov 2015 14:44:13 -0700 Subject: greybus: audio: Allocate protocol and class values Allocate protocol and class values for the Audio Device Class Protocol. Two values of each type are allocated: one for Audio Management Connections and one for Audio Data Connections. Signed-off-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index c36c4d1..947b71c 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -40,8 +40,8 @@ enum greybus_protocol { GREYBUS_PROTOCOL_LIGHTS = 0x0f, GREYBUS_PROTOCOL_VIBRATOR = 0x10, GREYBUS_PROTOCOL_LOOPBACK = 0x11, - /* 0x12 is unused */ - /* 0x13 is unused */ + GREYBUS_PROTOCOL_AUDIO_MGMT = 0x12, + GREYBUS_PROTOCOL_AUDIO_DATA = 0x13, GREYBUS_PROTOCOL_SVC = 0x14, GREYBUS_PROTOCOL_FIRMWARE = 0x15, /* ... */ @@ -68,8 +68,8 @@ enum greybus_class_type { GREYBUS_CLASS_LIGHTS = 0x0f, GREYBUS_CLASS_VIBRATOR = 0x10, GREYBUS_CLASS_LOOPBACK = 0x11, - /* 0x12 is unused */ - /* 0x13 is unused */ + GREYBUS_CLASS_AUDIO_MGMT = 0x12, + GREYBUS_CLASS_AUDIO_DATA = 0x13, GREYBUS_CLASS_SVC = 0x14, GREYBUS_CLASS_FIRMWARE = 0x15, /* ... */ -- cgit v0.10.2 From 5c864e775dfdecda1ea340af2d3b1c94b4dea63b Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Mon, 16 Nov 2015 19:23:25 +0000 Subject: greybus: manifest: fix bundle descriptor parse The descriptor list is walked in two points, in the bundle parsing and cport parsing, this can make the next descriptor pointer in bundle to be already removed by the cport remove descriptor and become invalid. So, just get the next bundle until there no more left. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 3e61b66..084e07e 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -60,6 +60,18 @@ static void release_manifest_descriptors(struct gb_interface *intf) release_manifest_descriptor(descriptor); } +static struct manifest_desc *get_next_bundle_desc(struct gb_interface *intf) +{ + struct manifest_desc *descriptor; + struct manifest_desc *next; + + list_for_each_entry_safe(descriptor, next, &intf->manifest_descs, links) + if (descriptor->type == GREYBUS_TYPE_BUNDLE) + return descriptor; + + return NULL; +} + /* * Validate the given descriptor. Its reported size must fit within * the number of bytes remaining, and it must have a recognized @@ -282,18 +294,14 @@ exit: static u32 gb_manifest_parse_bundles(struct gb_interface *intf) { struct manifest_desc *desc; - struct manifest_desc *next; struct gb_bundle *bundle; struct gb_bundle *bundle_next; u32 count = 0; u8 bundle_id; - list_for_each_entry_safe(desc, next, &intf->manifest_descs, links) { + while ((desc = get_next_bundle_desc(intf))) { struct greybus_descriptor_bundle *desc_bundle; - if (desc->type != GREYBUS_TYPE_BUNDLE) - continue; - /* Found one. Set up its bundle structure*/ desc_bundle = desc->data; bundle_id = desc_bundle->id; -- cgit v0.10.2 From 9864756be7542d3fe4e18297e0a45b5e2dec2f62 Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Thu, 19 Nov 2015 12:44:46 +0100 Subject: greybus: loopback: fix invalid response size The size of timestamps is not taken into account, which makes the loopback driver in the firmware drop invalid packages. Signed-off-by: Alexandre Bailon Signed-off-by: Bartosz Golaszewski Reviewed-by: Johan Hovold Reviewed-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 9a44dcc..ec68247 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -534,8 +534,8 @@ static int gb_loopback_request_recv(u8 type, struct gb_operation *operation) } if (len) { - if (!gb_operation_response_alloc(operation, len, - GFP_KERNEL)) { + if (!gb_operation_response_alloc(operation, + len + sizeof(*response), GFP_KERNEL)) { dev_err(dev, "error allocating response\n"); return -ENOMEM; } -- cgit v0.10.2 From 81ad6994611706270bc68a8dd951d7c69e2ed175 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Thu, 19 Nov 2015 13:46:43 +0100 Subject: greybus: loopback: allocate a response even for a 0-byte request If payload length of a transfer packet is 0, no response is allocated. Send a well-formed response even in that case. Signed-off-by: Bartosz Golaszewski Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index ec68247..0c38414 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -533,16 +533,16 @@ static int gb_loopback_request_recv(u8 type, struct gb_operation *operation) return -EINVAL; } - if (len) { - if (!gb_operation_response_alloc(operation, - len + sizeof(*response), GFP_KERNEL)) { - dev_err(dev, "error allocating response\n"); - return -ENOMEM; - } - response = operation->response->payload; - response->len = cpu_to_le32(len); - memcpy(response->data, request->data, len); + if (!gb_operation_response_alloc(operation, + len + sizeof(*response), GFP_KERNEL)) { + dev_err(dev, "error allocating response\n"); + return -ENOMEM; } + response = operation->response->payload; + response->len = cpu_to_le32(len); + if (len) + memcpy(response->data, request->data, len); + return 0; default: dev_err(dev, "unsupported request: %hhu\n", type); -- cgit v0.10.2 From 98645a9c69f40e46cdbf8c0c1862b4c2ed470319 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 19 Nov 2015 18:27:59 +0100 Subject: greybus: firmware: fix information leak Add missing sanity checks on get_firmware-request offset and size parameters to fix potential information leaks. This prevents remotely controlled information leaks as the requestor currently controls both the 32-bit firmware-image offset and the amount of data that is returned (up to host-device MTU). Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/firmware.c b/drivers/staging/greybus/firmware.c index b16f133..4e1530f 100644 --- a/drivers/staging/greybus/firmware.c +++ b/drivers/staging/greybus/firmware.c @@ -87,6 +87,7 @@ static int gb_firmware_get_firmware(struct gb_operation *op) { struct gb_connection *connection = op->connection; struct gb_firmware *firmware = connection->private; + const struct firmware *fw = firmware->fw; struct gb_firmware_get_firmware_request *firmware_request = op->request->payload; struct gb_firmware_get_firmware_response *firmware_response; struct device *dev = &connection->bundle->dev; @@ -99,7 +100,7 @@ static int gb_firmware_get_firmware(struct gb_operation *op) return -EINVAL; } - if (!firmware->fw) { + if (!fw) { dev_err(dev, "%s: firmware not available\n", __func__); return -EINVAL; } @@ -107,6 +108,12 @@ static int gb_firmware_get_firmware(struct gb_operation *op) offset = le32_to_cpu(firmware_request->offset); size = le32_to_cpu(firmware_request->size); + if (offset >= fw->size || size > fw->size - offset) { + dev_warn(dev, "bad firmware request (offs = %u, size = %u)\n", + offset, size); + return -EINVAL; + } + if (!gb_operation_response_alloc(op, sizeof(*firmware_response) + size, GFP_KERNEL)) { dev_err(dev, "%s: error allocating response\n", __func__); @@ -114,7 +121,7 @@ static int gb_firmware_get_firmware(struct gb_operation *op) } firmware_response = op->response->payload; - memcpy(firmware_response->data, firmware->fw->data + offset, size); + memcpy(firmware_response->data, fw->data + offset, size); return 0; } -- cgit v0.10.2 From 87f6c976f4104ae5a439ff2d78ea3fe7ce0ac280 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 19 Nov 2015 18:28:00 +0100 Subject: greybus: firmware: break long lines Break lines longer than 80 cols, and clean up an error message while at it. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/firmware.c b/drivers/staging/greybus/firmware.c index 4e1530f..a95be08 100644 --- a/drivers/staging/greybus/firmware.c +++ b/drivers/staging/greybus/firmware.c @@ -88,7 +88,7 @@ static int gb_firmware_get_firmware(struct gb_operation *op) struct gb_connection *connection = op->connection; struct gb_firmware *firmware = connection->private; const struct firmware *fw = firmware->fw; - struct gb_firmware_get_firmware_request *firmware_request = op->request->payload; + struct gb_firmware_get_firmware_request *firmware_request; struct gb_firmware_get_firmware_response *firmware_response; struct device *dev = &connection->bundle->dev; unsigned int offset, size; @@ -105,6 +105,7 @@ static int gb_firmware_get_firmware(struct gb_operation *op) return -EINVAL; } + firmware_request = op->request->payload; offset = le32_to_cpu(firmware_request->offset); size = le32_to_cpu(firmware_request->size); @@ -129,7 +130,7 @@ static int gb_firmware_get_firmware(struct gb_operation *op) static int gb_firmware_ready_to_boot(struct gb_operation *op) { struct gb_connection *connection = op->connection; - struct gb_firmware_ready_to_boot_request *rtb_request = op->request->payload; + struct gb_firmware_ready_to_boot_request *rtb_request; struct device *dev = &connection->bundle->dev; u8 status; @@ -140,6 +141,7 @@ static int gb_firmware_ready_to_boot(struct gb_operation *op) return -EINVAL; } + rtb_request = op->request->payload; status = rtb_request->status; /* Return error if the blob was invalid */ @@ -192,8 +194,10 @@ static int gb_firmware_connection_init(struct gb_connection *connection) */ ret = gb_operation_sync(connection, GB_FIRMWARE_TYPE_AP_READY, NULL, 0, NULL, 0); - if (ret) - dev_err(&connection->bundle->dev, "Failed to send AP READY (%d)\n", ret); + if (ret) { + dev_err(&connection->bundle->dev, + "failed to send AP READY: %d\n", ret); + } return 0; } -- cgit v0.10.2 From 55510843c1630f6067aae4c45ff2929a51f56b4d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 19 Nov 2015 18:28:01 +0100 Subject: greybus: svc: fix missing version-request sanity checks Add missing sanity checks on version-request payload size. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 6c1a157..bd04567 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -310,6 +310,14 @@ static int gb_svc_version_request(struct gb_operation *op) struct gb_protocol_version_request *request; struct gb_protocol_version_response *response; + if (op->request->payload_size < sizeof(*request)) { + pr_err("%d: short version request (%zu < %zu)\n", + connection->intf_cport_id, + op->request->payload_size, + sizeof(*request)); + return -EINVAL; + } + request = op->request->payload; if (request->major > GB_SVC_VERSION_MAJOR) { -- cgit v0.10.2 From 358e9400f41a74467380cef38a6797c1747f7b1a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Sat, 21 Nov 2015 10:51:59 +0100 Subject: greybus: fix bundle-id match macros The matching flags were renamed over a year ago but the so far unused id-macros were never updated. Also rename the GREYBUS_ID_MATCH_DEVICE mask to use the common GREYBUS_ID_MATCH-prefix. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 1b6f56f..4a6b235 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -42,16 +42,16 @@ #define GREYBUS_VERSION_MAJOR 0x00 #define GREYBUS_VERSION_MINOR 0x01 -#define GREYBUS_DEVICE_ID_MATCH_DEVICE \ - (GREYBUS_DEVICE_ID_MATCH_VENDOR | GREYBUS_DEVICE_ID_MATCH_PRODUCT) +#define GREYBUS_ID_MATCH_DEVICE \ + (GREYBUS_ID_MATCH_VENDOR | GREYBUS_ID_MATCH_PRODUCT) #define GREYBUS_DEVICE(v, p) \ - .match_flags = GREYBUS_DEVICE_ID_MATCH_DEVICE, \ + .match_flags = GREYBUS_ID_MATCH_DEVICE, \ .vendor = (v), \ .product = (p), #define GREYBUS_DEVICE_SERIAL(s) \ - .match_flags = GREYBUS_DEVICE_ID_MATCH_SERIAL, \ + .match_flags = GREYBUS_ID_MATCH_SERIAL, \ .serial_number = (s), /* Maximum number of CPorts */ -- cgit v0.10.2 From 9784a591f00134c02d152d6d07c539a136db7c12 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Sat, 21 Nov 2015 10:52:00 +0100 Subject: greybus: remove unique-id matching Remove unique-id matching as it does not make much sense to have a driver match a specific device serial number. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 01745f4..fbc0439 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -79,10 +79,6 @@ static int gb_bundle_match_one_id(struct gb_bundle *bundle, (id->product != bundle->intf->product)) return 0; - if ((id->match_flags & GREYBUS_ID_MATCH_SERIAL) && - (id->unique_id != bundle->intf->unique_id)) - return 0; - if ((id->match_flags & GREYBUS_ID_MATCH_CLASS) && (id->class != bundle->class)) return 0; @@ -97,8 +93,8 @@ gb_bundle_match_id(struct gb_bundle *bundle, if (id == NULL) return NULL; - for (; id->vendor || id->product || id->unique_id || id->class || - id->driver_info; id++) { + for (; id->vendor || id->product || id->class || id->driver_info; + id++) { if (gb_bundle_match_one_id(bundle, id)) return id; } diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 4a6b235..4f8aa31 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -50,10 +50,6 @@ .vendor = (v), \ .product = (p), -#define GREYBUS_DEVICE_SERIAL(s) \ - .match_flags = GREYBUS_ID_MATCH_SERIAL, \ - .serial_number = (s), - /* Maximum number of CPorts */ #define CPORT_ID_MAX 4095 /* UniPro max id is 4095 */ #define CPORT_ID_BAD U16_MAX diff --git a/drivers/staging/greybus/greybus_id.h b/drivers/staging/greybus/greybus_id.h index 8e76d42..68d2e95 100644 --- a/drivers/staging/greybus/greybus_id.h +++ b/drivers/staging/greybus/greybus_id.h @@ -14,7 +14,6 @@ struct greybus_bundle_id { __u16 vendor; __u16 product; __u8 class; - __u64 unique_id; kernel_ulong_t driver_info __aligned(sizeof(kernel_ulong_t)); }; @@ -22,7 +21,6 @@ struct greybus_bundle_id { /* Used to match the greybus_bundle_id */ #define GREYBUS_ID_MATCH_VENDOR BIT(0) #define GREYBUS_ID_MATCH_PRODUCT BIT(1) -#define GREYBUS_ID_MATCH_SERIAL BIT(2) #define GREYBUS_ID_MATCH_CLASS BIT(3) #endif /* __LINUX_GREYBUS_ID_H */ -- cgit v0.10.2 From 8034bd561dac0c6616097394ba9b5eaee3c4fc9c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Sat, 21 Nov 2015 10:52:01 +0100 Subject: greybus: interface: remove unique id Remove the unimplemented interface unique-id. There will eventually be an interface-serial-number attribute provided, but let's not export it or commit to a name for this attribute until we need it. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 22a0c7f..8363f23 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -107,13 +107,6 @@ Contact: Greg Kroah-Hartman Description: Product ID string of a Greybus interface block. -What: /sys/bus/greybus/device/endoE:M:I/unique_id -Date: October 2015 -KernelVersion: 4.XX -Contact: Greg Kroah-Hartman -Description: - Unique ID of a Greybus interface block. - What: /sys/bus/greybus/device/endoE:M:I/vendor Date: October 2015 KernelVersion: 4.XX diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 4c96adc5..b57cc09 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -23,7 +23,6 @@ static DEVICE_ATTR_RO(field) gb_interface_attr(device_id, d); gb_interface_attr(vendor, x); gb_interface_attr(product, x); -gb_interface_attr(unique_id, llX); gb_interface_attr(vendor_string, s); gb_interface_attr(product_string, s); @@ -31,7 +30,6 @@ static struct attribute *interface_attrs[] = { &dev_attr_device_id.attr, &dev_attr_vendor.attr, &dev_attr_product.attr, - &dev_attr_unique_id.attr, &dev_attr_vendor_string.attr, &dev_attr_product_string.attr, NULL, diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 248c991..f0ef4e9 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -26,7 +26,6 @@ struct gb_interface { u16 product; char *vendor_string; char *product_string; - u64 unique_id; /* Information taken from the hotplug event */ u32 unipro_mfg_id; diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 084e07e..4b4dd99 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -396,7 +396,6 @@ static bool gb_manifest_parse_interface(struct gb_interface *intf, // Vendor, Product and Unique id must come via control protocol intf->vendor = 0xffff; intf->product = 0x0001; - intf->unique_id = 0; /* Release the interface descriptor, now that we're done with it */ release_manifest_descriptor(interface_desc); -- cgit v0.10.2 From f65fa47f28f303c84b701dadda6d4f48fb541691 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Sat, 21 Nov 2015 10:52:02 +0100 Subject: greybus: fix vendor and product matching Fix vendor and product matching by matching on the 32-bit Ara vendor and product ids. Remove the "fake" 16-bit vendor and product ids and export the Ara ids using the "vendor" and "product" interface attributes instead. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/firmware.c b/drivers/staging/greybus/firmware.c index a95be08..e99d8d6 100644 --- a/drivers/staging/greybus/firmware.c +++ b/drivers/staging/greybus/firmware.c @@ -41,7 +41,7 @@ static int download_firmware(struct gb_firmware *firmware, u8 stage) snprintf(firmware_name, sizeof(firmware_name), "ara:%08x:%08x:%08x:%08x:%02x.tftf", intf->unipro_mfg_id, intf->unipro_prod_id, - intf->ara_vend_id, intf->ara_prod_id, stage); + intf->vendor, intf->product, stage); return request_firmware(&firmware->fw, firmware_name, &connection->bundle->dev); diff --git a/drivers/staging/greybus/greybus_id.h b/drivers/staging/greybus/greybus_id.h index 68d2e95..c91e7be 100644 --- a/drivers/staging/greybus/greybus_id.h +++ b/drivers/staging/greybus/greybus_id.h @@ -11,8 +11,8 @@ struct greybus_bundle_id { __u16 match_flags; - __u16 vendor; - __u16 product; + __u32 vendor; + __u32 product; __u8 class; kernel_ulong_t driver_info __aligned(sizeof(kernel_ulong_t)); diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index f0ef4e9..28d2bac 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -22,16 +22,14 @@ struct gb_interface { u8 device_id; /* Device id allocated for the interface block by the SVC */ /* Information taken from the manifest descriptor */ - u16 vendor; - u16 product; char *vendor_string; char *product_string; /* Information taken from the hotplug event */ u32 unipro_mfg_id; u32 unipro_prod_id; - u32 ara_vend_id; - u32 ara_prod_id; + u32 vendor; + u32 product; struct gb_module *module; struct gb_host_device *hd; diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 4b4dd99..c80a849 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -392,11 +392,6 @@ static bool gb_manifest_parse_interface(struct gb_interface *intf, if (IS_ERR(intf->product_string)) goto out_free_vendor_string; - // FIXME - // Vendor, Product and Unique id must come via control protocol - intf->vendor = 0xffff; - intf->product = 0x0001; - /* Release the interface descriptor, now that we're done with it */ release_manifest_descriptor(interface_desc); diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index bd04567..1acd0f7 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -460,8 +460,8 @@ static void svc_process_hotplug(struct work_struct *work) intf->unipro_mfg_id = le32_to_cpu(hotplug->data.unipro_mfg_id); intf->unipro_prod_id = le32_to_cpu(hotplug->data.unipro_prod_id); - intf->ara_vend_id = le32_to_cpu(hotplug->data.ara_vend_id); - intf->ara_prod_id = le32_to_cpu(hotplug->data.ara_prod_id); + intf->vendor = le32_to_cpu(hotplug->data.ara_vend_id); + intf->product = le32_to_cpu(hotplug->data.ara_prod_id); /* * Create a device id for the interface: -- cgit v0.10.2 From 700001af960af35e57b701e57bd1595404dca613 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Sat, 21 Nov 2015 10:52:03 +0100 Subject: greybus: move id-matching back to core Move id-matching back to core and the bus code where it belongs. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index fbc0439..4d04f09 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -68,41 +68,6 @@ struct device_type greybus_bundle_type = { .release = gb_bundle_release, }; -static int gb_bundle_match_one_id(struct gb_bundle *bundle, - const struct greybus_bundle_id *id) -{ - if ((id->match_flags & GREYBUS_ID_MATCH_VENDOR) && - (id->vendor != bundle->intf->vendor)) - return 0; - - if ((id->match_flags & GREYBUS_ID_MATCH_PRODUCT) && - (id->product != bundle->intf->product)) - return 0; - - if ((id->match_flags & GREYBUS_ID_MATCH_CLASS) && - (id->class != bundle->class)) - return 0; - - return 1; -} - -const struct greybus_bundle_id * -gb_bundle_match_id(struct gb_bundle *bundle, - const struct greybus_bundle_id *id) -{ - if (id == NULL) - return NULL; - - for (; id->vendor || id->product || id->class || id->driver_info; - id++) { - if (gb_bundle_match_one_id(bundle, id)) - return id; - } - - return NULL; -} - - /* XXX This could be per-host device or per-module */ static DEFINE_SPINLOCK(gb_bundles_lock); diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 4396f90..56250fa 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -29,13 +29,46 @@ int greybus_disabled(void) } EXPORT_SYMBOL_GPL(greybus_disabled); +static int greybus_match_one_id(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) +{ + if ((id->match_flags & GREYBUS_ID_MATCH_VENDOR) && + (id->vendor != bundle->intf->vendor)) + return 0; + + if ((id->match_flags & GREYBUS_ID_MATCH_PRODUCT) && + (id->product != bundle->intf->product)) + return 0; + + if ((id->match_flags & GREYBUS_ID_MATCH_CLASS) && + (id->class != bundle->class)) + return 0; + + return 1; +} + +static const struct greybus_bundle_id * +greybus_match_id(struct gb_bundle *bundle, const struct greybus_bundle_id *id) +{ + if (id == NULL) + return NULL; + + for (; id->vendor || id->product || id->class || id->driver_info; + id++) { + if (greybus_match_one_id(bundle, id)) + return id; + } + + return NULL; +} + static int greybus_module_match(struct device *dev, struct device_driver *drv) { struct greybus_driver *driver = to_greybus_driver(drv); struct gb_bundle *bundle = to_gb_bundle(dev); const struct greybus_bundle_id *id; - id = gb_bundle_match_id(bundle, driver->id_table); + id = greybus_match_id(bundle, driver->id_table); if (id) return 1; /* FIXME - Dynamic ids? */ @@ -97,7 +130,7 @@ static int greybus_probe(struct device *dev) int retval; /* match id */ - id = gb_bundle_match_id(bundle, driver->id_table); + id = greybus_match_id(bundle, driver->id_table); if (!id) return -ENODEV; -- cgit v0.10.2 From 3823c614793131afcfd87ba87bd83012ec52a879 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Sat, 21 Nov 2015 10:52:04 +0100 Subject: greybus: add class matching macro Add matching macro for bundle class. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 4f8aa31..6da4e78 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -50,6 +50,10 @@ .vendor = (v), \ .product = (p), +#define GREYBUS_DEVICE_CLASS(c) \ + .match_flags = GREYBUS_ID_MATCH_CLASS, \ + .class = (c), + /* Maximum number of CPorts */ #define CPORT_ID_MAX 4095 /* UniPro max id is 4095 */ #define CPORT_ID_BAD U16_MAX -- cgit v0.10.2 From d3d2af51f9c2f29a0bf5df278503820004d71e36 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal Date: Mon, 23 Nov 2015 15:57:45 +0530 Subject: greybus: Audio: Add skeleton code for GB virtual codec driver This patch adds gb-codec driver with static information for DAPM widgets, controls & dapm_routes. Including some changes in kernel code(machine driver): - Able to register codec and glue it with existing sound card successfully. - Able to view & modify mixer controls: (volume/mute[left/right][input/output]) - Able to view DAPM widgets registered via /debug interface. - Able to establish DAPM path for playback. Since, FE<->BE path not yet verified with default jetson build, registering GB DAI as normal DAI link to verify GB virtual codec specific DAPM path. Signed-off-by: Vaibhav Agarwal Reviewed-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 2c1f974..40e22ec 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -31,6 +31,7 @@ gb-raw-y := raw.o gb-hid-y := hid.o gb-es2-y := es2.o gb-db3-y := db3-platform.o +gb-audio-codec-y := audio-codec.o obj-m += greybus.o obj-m += gb-phy.o @@ -42,6 +43,7 @@ obj-m += gb-hid.o obj-m += gb-raw.o obj-m += gb-es2.o obj-m += gb-db3.o +obj-m += gb-audio-codec.o KERNELVER ?= $(shell uname -r) KERNELDIR ?= /lib/modules/$(KERNELVER)/build diff --git a/drivers/staging/greybus/audio-codec.c b/drivers/staging/greybus/audio-codec.c new file mode 100644 index 0000000..2bc2309 --- /dev/null +++ b/drivers/staging/greybus/audio-codec.c @@ -0,0 +1,315 @@ +/* + * Greybus audio driver + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ +#include + +#include "audio.h" + +static int gbcodec_event_spk(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + /* Ensure GB speaker is connected */ + + return 0; +} + +static int gbcodec_event_hp(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + /* Ensure GB module supports jack slot */ + + return 0; +} + +static int gbcodec_event_int_mic(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + /* Ensure GB module supports jack slot */ + + return 0; +} + +static const struct snd_kcontrol_new gbcodec_snd_controls[] = { + SOC_DOUBLE("Playback Mute", GBCODEC_MUTE_REG, 0, 1, 1, 1), + SOC_DOUBLE("Capture Mute", GBCODEC_MUTE_REG, 4, 5, 1, 1), + SOC_DOUBLE_R("Playback Volume", GBCODEC_PB_LVOL_REG, + GBCODEC_PB_RVOL_REG, 0, 127, 0), + SOC_DOUBLE_R("Capture Volume", GBCODEC_CAP_LVOL_REG, + GBCODEC_CAP_RVOL_REG, 0, 127, 0), +}; + +static const struct snd_kcontrol_new spk_amp_ctl = + SOC_DAPM_SINGLE("Switch", GBCODEC_CTL_REG, 0, 1, 0); + +static const struct snd_kcontrol_new hp_amp_ctl = + SOC_DAPM_SINGLE("Switch", GBCODEC_CTL_REG, 1, 1, 0); + +static const struct snd_kcontrol_new mic_adc_ctl = + SOC_DAPM_SINGLE("Switch", GBCODEC_CTL_REG, 4, 1, 0); + +/* APB1-GBSPK source */ +static const char * const gbcodec_apb1_src[] = {"Stereo", "Left", "Right"}; + +static const SOC_ENUM_SINGLE_DECL( + gbcodec_apb1_rx_enum, GBCODEC_APB1_MUX_REG, 0, gbcodec_apb1_src); + +static const struct snd_kcontrol_new gbcodec_apb1_rx_mux = + SOC_DAPM_ENUM("APB1 source", gbcodec_apb1_rx_enum); + +static const SOC_ENUM_SINGLE_DECL( + gbcodec_mic_enum, GBCODEC_APB1_MUX_REG, 4, gbcodec_apb1_src); + +static const struct snd_kcontrol_new gbcodec_mic_mux = + SOC_DAPM_ENUM("MIC source", gbcodec_mic_enum); + +static const struct snd_soc_dapm_widget gbcodec_dapm_widgets[] = { + SND_SOC_DAPM_SPK("Spk", gbcodec_event_spk), + SND_SOC_DAPM_SPK("HP", gbcodec_event_hp), + SND_SOC_DAPM_MIC("Int Mic", gbcodec_event_int_mic), + + SND_SOC_DAPM_OUTPUT("SPKOUT"), + SND_SOC_DAPM_OUTPUT("HPOUT"), + + SND_SOC_DAPM_INPUT("MIC"), + SND_SOC_DAPM_INPUT("HSMIC"), + + SND_SOC_DAPM_SWITCH("SPK Amp", SND_SOC_NOPM, 0, 0, &spk_amp_ctl), + SND_SOC_DAPM_SWITCH("HP Amp", SND_SOC_NOPM, 0, 0, &hp_amp_ctl), + SND_SOC_DAPM_SWITCH("MIC ADC", SND_SOC_NOPM, 0, 0, &mic_adc_ctl), + + SND_SOC_DAPM_PGA("SPK DAC", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("HP DAC", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_MIXER("SPK Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("HP Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("APB1_TX Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_MUX("APB1_RX Mux", SND_SOC_NOPM, 0, 0, + &gbcodec_apb1_rx_mux), + SND_SOC_DAPM_MUX("MIC Mux", SND_SOC_NOPM, 0, 0, &gbcodec_mic_mux), + + SND_SOC_DAPM_AIF_IN("APB1RX", "APBridgeA1 Playback", 0, SND_SOC_NOPM, 0, + 0), + SND_SOC_DAPM_AIF_OUT("APB1TX", "APBridgeA1 Capture", 0, SND_SOC_NOPM, 0, + 0), +}; + +static const struct snd_soc_dapm_route gbcodec_dapm_routes[] = { + /* Playback path */ + {"Spk", NULL, "SPKOUT"}, + {"SPKOUT", NULL, "SPK Amp"}, + {"SPK Amp", "Switch", "SPK DAC"}, + {"SPK DAC", NULL, "SPK Mixer"}, + + {"HP", NULL, "HPOUT"}, + {"HPOUT", NULL, "HP Amp"}, + {"HP Amp", "Switch", "HP DAC"}, + {"HP DAC", NULL, "HP Mixer"}, + + {"SPK Mixer", NULL, "APB1_RX Mux"}, + {"HP Mixer", NULL, "APB1_RX Mux"}, + + {"APB1_RX Mux", "Left", "APB1RX"}, + {"APB1_RX Mux", "Right", "APB1RX"}, + {"APB1_RX Mux", "Stereo", "APB1RX"}, + + /* Capture path */ + {"MIC", NULL, "Int Mic"}, + {"MIC", NULL, "MIC Mux"}, + {"MIC Mux", "Left", "MIC ADC"}, + {"MIC Mux", "Right", "MIC ADC"}, + {"MIC Mux", "Stereo", "MIC ADC"}, + {"MIC ADC", "Switch", "APB1_TX Mixer"}, + {"APB1_TX Mixer", NULL, "APB1TX"} +}; + +static int gbcodec_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + return 0; +} + +static void gbcodec_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ +} + +static int gbcodec_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hwparams, + struct snd_soc_dai *dai) +{ + return 0; +} + +static int gbcodec_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + return 0; +} + +static int gbcodec_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + return 0; +} + +static int gbcodec_digital_mute(struct snd_soc_dai *dai, int mute) +{ + return 0; +} + +static struct snd_soc_dai_ops gbcodec_dai_ops = { + .startup = gbcodec_startup, + .shutdown = gbcodec_shutdown, + .hw_params = gbcodec_hw_params, + .prepare = gbcodec_prepare, + .set_fmt = gbcodec_set_dai_fmt, + .digital_mute = gbcodec_digital_mute, +}; + +static struct snd_soc_dai_driver gbcodec_dai = { + .playback = { + .stream_name = "APBridgeA1 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .capture = { + .stream_name = "APBridgeA1 Capture", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .ops = &gbcodec_dai_ops, +}; + +static int gbcodec_probe(struct snd_soc_codec *codec) +{ + struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec); + + gbcodec->codec = codec; + + return 0; +} + +static int gbcodec_remove(struct snd_soc_codec *codec) +{ + /* Empty function for now */ + return 0; +} + +static int gbcodec_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value) +{ + int ret = 0; + struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec); + u8 *gbcodec_reg = gbcodec->reg; + + if (reg == SND_SOC_NOPM) + return 0; + + if (reg >= GBCODEC_REG_COUNT) + return 0; + + gbcodec_reg[reg] = value; + dev_dbg(codec->dev, "reg[%d] = 0x%x\n", reg, value); + + return ret; +} + +static unsigned int gbcodec_read(struct snd_soc_codec *codec, + unsigned int reg) +{ + unsigned int val = 0; + + struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec); + u8 *gbcodec_reg = gbcodec->reg; + + if (reg == SND_SOC_NOPM) + return 0; + + if (reg >= GBCODEC_REG_COUNT) + return 0; + + val = gbcodec_reg[reg]; + dev_dbg(codec->dev, "reg[%d] = 0x%x\n", reg, val); + + return val; +} + +static struct snd_soc_codec_driver soc_codec_dev_gbcodec = { + .probe = gbcodec_probe, + .remove = gbcodec_remove, + + .read = gbcodec_read, + .write = gbcodec_write, + + .reg_cache_size = GBCODEC_REG_COUNT, + .reg_cache_default = gbcodec_reg_defaults, + .reg_word_size = 1, + + .idle_bias_off = true, + + .controls = gbcodec_snd_controls, + .num_controls = ARRAY_SIZE(gbcodec_snd_controls), + .dapm_widgets = gbcodec_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(gbcodec_dapm_widgets), + .dapm_routes = gbcodec_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(gbcodec_dapm_routes), +}; + +static int gbaudio_codec_probe(struct platform_device *pdev) +{ + int ret; + struct gbaudio_codec_info *gbcodec; + char dai_name[NAME_SIZE]; + + gbcodec = devm_kzalloc(&pdev->dev, sizeof(struct gbaudio_codec_info), + GFP_KERNEL); + if (!gbcodec) + return -ENOMEM; + platform_set_drvdata(pdev, gbcodec); + + snprintf(dai_name, NAME_SIZE, "%s.%d", "gbcodec_pcm", pdev->id); + gbcodec_dai.name = dai_name; + + ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_gbcodec, + &gbcodec_dai, 1); + if (!ret) + gbcodec->registered = 1; + + return ret; +} + +static const struct of_device_id gbcodec_of_match[] = { + { .compatible = "greybus,codec", }, + {}, +}; + +static int gbaudio_codec_remove(struct platform_device *pdev) +{ + snd_soc_unregister_codec(&pdev->dev); + + return 0; +} + +static struct platform_driver gbaudio_codec_driver = { + .driver = { + .name = "gbaudio-codec", + .owner = THIS_MODULE, + .of_match_table = gbcodec_of_match, + }, + .probe = gbaudio_codec_probe, + .remove = gbaudio_codec_remove, +}; +module_platform_driver(gbaudio_codec_driver); + +MODULE_DESCRIPTION("Greybus Audio virtual codec driver"); +MODULE_AUTHOR("Vaibhav Agarwal "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:gbaudio-codec"); diff --git a/drivers/staging/greybus/audio.h b/drivers/staging/greybus/audio.h new file mode 100644 index 0000000..5dec00d --- /dev/null +++ b/drivers/staging/greybus/audio.h @@ -0,0 +1,86 @@ +/* + * Greybus audio driver + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#ifndef __LINUX_GBAUDIO_H +#define __LINUX_GBAUDIO_H + +#ifdef __KERNEL__ + +#include + +#define NAME_SIZE 32 + +enum { + APB1_PCM = 0, + APB2_PCM, + NUM_CODEC_DAIS, +}; + +enum gbcodec_reg_index { + GBCODEC_CTL_REG, + GBCODEC_MUTE_REG, + GBCODEC_PB_LVOL_REG, + GBCODEC_PB_RVOL_REG, + GBCODEC_CAP_LVOL_REG, + GBCODEC_CAP_RVOL_REG, + GBCODEC_APB1_MUX_REG, + GBCODEC_APB2_MUX_REG, + GBCODEC_REG_COUNT +}; + +/* bit 0-SPK, 1-HP, 2-DAC, + * 4-MIC, 5-HSMIC, 6-MIC2 + */ +#define GBCODEC_CTL_REG_DEFAULT 0x00 + +/* bit 0,1 - APB1-PB-L/R + * bit 2,3 - APB2-PB-L/R + * bit 4,5 - APB1-Cap-L/R + * bit 6,7 - APB2-Cap-L/R + */ +#define GBCODEC_MUTE_REG_DEFAULT 0x00 + +/* 0-127 steps */ +#define GBCODEC_PB_VOL_REG_DEFAULT 0x00 +#define GBCODEC_CAP_VOL_REG_DEFAULT 0x00 + +/* bit 0,1,2 - PB stereo, left, right + * bit 8,9,10 - Cap stereo, left, right + */ +#define GBCODEC_APB1_MUX_REG_DEFAULT 0x00 +#define GBCODEC_APB2_MUX_REG_DEFAULT 0x00 + +static const u8 gbcodec_reg_defaults[GBCODEC_REG_COUNT] = { + GBCODEC_CTL_REG_DEFAULT, + GBCODEC_MUTE_REG_DEFAULT, + GBCODEC_PB_VOL_REG_DEFAULT, + GBCODEC_PB_VOL_REG_DEFAULT, + GBCODEC_CAP_VOL_REG_DEFAULT, + GBCODEC_CAP_VOL_REG_DEFAULT, + GBCODEC_APB1_MUX_REG_DEFAULT, + GBCODEC_APB2_MUX_REG_DEFAULT, +}; + +struct gbaudio_codec_info { + struct snd_soc_codec *codec; + + bool usable; + u8 reg[GBCODEC_REG_COUNT]; + int registered; + + int num_kcontrols; + int num_dapm_widgets; + int num_dapm_routes; + struct snd_kcontrol_new *kctls; + struct snd_soc_dapm_widget *widgets; + struct snd_soc_dapm_route *routes; + struct mutex lock; +}; + +#endif /* __KERNEL__ */ +#endif /* __LINUX_GBAUDIO_H */ -- cgit v0.10.2 From 39f36c8f9ff6203301a1d7feb7f51d2563abbd3a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Sat, 21 Nov 2015 10:51:58 +0100 Subject: greybus: connection: fix cport-id range Fix cport-id allocation that failed to include the highest port id in the available cport-id range. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 96dabf7..695f148 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -219,7 +219,7 @@ struct gb_connection *gb_connection_create(struct gb_bundle *bundle, { return gb_connection_create_range(bundle->intf->hd, bundle, &bundle->dev, cport_id, protocol_id, - 0, bundle->intf->hd->num_cports - 1); + 0, bundle->intf->hd->num_cports); } /* -- cgit v0.10.2 From bfe2c99c1cd346b06a7d34274b9b826d40ab40a1 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Sun, 22 Nov 2015 10:12:58 +0100 Subject: greybus: hd: fix cport-count check Fix off-by-one error when checking the number of cports a host-device supports. The CPORT_ID_MAX is the largest valid cport id so the maximum number of cports a host-device can use is CPORT_ID_MAX + 1. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index b22d547..3446fec 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -49,7 +49,7 @@ struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, return ERR_PTR(-EINVAL); } - if (num_cports == 0 || num_cports > CPORT_ID_MAX) { + if (num_cports == 0 || num_cports > CPORT_ID_MAX + 1) { dev_err(parent, "Invalid number of CPorts: %zu\n", num_cports); return ERR_PTR(-EINVAL); } -- cgit v0.10.2 From fc25d9068e80659ea2b3a4516c63c523bdafc20b Mon Sep 17 00:00:00 2001 From: Sachin Pandhare Date: Tue, 24 Nov 2015 07:59:10 +0530 Subject: greybus: manifest: simplify descriptor address calculation This patch doesn't change any functionality. It just improves the readability of the code. Current code to get 'descriptors' pointer looks as if we are forcing the pointer type change. To simplify the address calculations, use 'descriptors' member directly from greybus_manifest structure. Signed-off-by: Sachin Pandhare Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index c80a849..41d5157 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -475,7 +475,7 @@ bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size) } /* OK, find all the descriptors */ - desc = (struct greybus_descriptor *)(header + 1); + desc = manifest->descriptors; size -= sizeof(*header); while (size) { int desc_size; -- cgit v0.10.2 From f6f8aeaa35899de2180b93a0efc27a7d5b0c4ec5 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Sun, 22 Nov 2015 10:24:08 +0100 Subject: greybus: Documentation/sysfs: update the example sysfs tree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update the example sysfs-tree layout under Documentation. The new layout reflects changes to the kernel device-model that are needed to eventually be able to handle multiple AP-bridges. The example tree has two AP-bridges, each with its own view of the UniPro network, the bus. . ├── greybus1 │   ├── 1-2 │   │   ├── 1-2.1 │   │   │   ├── class │   │   │   ├── id │   │   │   └── state │   │   ├── 1-2.2 │   │   │   ├── class │   │   │   ├── id │   │   │   └── state │   │   ├── id │   │   ├── product_id │   │   ├── unique_id │   │   └── vendor_id │   ├── 1-4 │   │   ├── 1-4.2 │   │   │   ├── class │   │   │   ├── gpbridge0 │   │   │   │   ├── gpio │   │   │   │   │   └── gpiochip490 │   │   │   │   └── i2c-4 │   │   │   ├── id │   │   │   └── state │   │   ├── id │   │   ├── product_id │   │   ├── unique_id │   │   └── vendor_id │   └── 1-svc │   ├── ap_intf_id │   ├── eject │   ├── endo_id │   └── unique_id └── greybus2 ├── 2-3 │   ├── 2-3.1 │   │   ├── class │   │   ├── id │   │   └── state │   ├── id │   ├── product_id │   ├── unique_id │   └── vendor_id └── 2-svc ├── ap_intf_id ├── eject ├── endo_id └── unique_id Every bus has exactly one svc device (1-svc and 2-svc). For our system, the svc device of each bus will be a representation of the same network-unique SVC device (e.g. endo_id and unique_id will be identical). The first bus has two registered interfaces (1-2 and 1-4), while the second bus has a single interface (2-3). Note that the interface ids (2, 4, and 3) are necessarily unique as these are interfaces on the same network. Interface 1-2 has two bundles (1-2.1 and 1-2.2) and interface 1-4 has a single bundle (1-4.2). The bundle ids are interface-unique and reflect the ids found in each manifest. In the example, bundle 1-4.2 has a gbbridge-device, which is the parent device for a gpiochip device and an i2c bus. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/vendor_id b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/vendor_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/vendor_name b/drivers/staging/greybus/Documentation/sysfs/endo-TYPE/01/01/vendor_name deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/01/01/01/01/gpbridge00/gpio/.gitignore b/drivers/staging/greybus/Documentation/sysfs/endo/01/01/01/01/gpbridge00/gpio/.gitignore deleted file mode 100644 index f935021..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/endo/01/01/01/01/gpbridge00/gpio/.gitignore +++ /dev/null @@ -1 +0,0 @@ -!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/01/01/01/01/gpbridge00/i2c/.gitignore b/drivers/staging/greybus/Documentation/sysfs/endo/01/01/01/01/gpbridge00/i2c/.gitignore deleted file mode 100644 index f935021..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/endo/01/01/01/01/gpbridge00/i2c/.gitignore +++ /dev/null @@ -1 +0,0 @@ -!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/01/01/01/01/gpbridge00/usb/.gitignore b/drivers/staging/greybus/Documentation/sysfs/endo/01/01/01/01/gpbridge00/usb/.gitignore deleted file mode 100644 index f935021..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/endo/01/01/01/01/gpbridge00/usb/.gitignore +++ /dev/null @@ -1 +0,0 @@ -!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/01/01/firmware b/drivers/staging/greybus/Documentation/sysfs/endo/01/01/firmware deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/01/01/manifest b/drivers/staging/greybus/Documentation/sysfs/endo/01/01/manifest deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/01/01/product_id b/drivers/staging/greybus/Documentation/sysfs/endo/01/01/product_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/01/01/product_name b/drivers/staging/greybus/Documentation/sysfs/endo/01/01/product_name deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/01/01/state b/drivers/staging/greybus/Documentation/sysfs/endo/01/01/state deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/01/01/uid b/drivers/staging/greybus/Documentation/sysfs/endo/01/01/uid deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/01/01/version_major b/drivers/staging/greybus/Documentation/sysfs/endo/01/01/version_major deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/01/01/version_minor b/drivers/staging/greybus/Documentation/sysfs/endo/01/01/version_minor deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/01/epm b/drivers/staging/greybus/Documentation/sysfs/endo/01/epm deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/01/power b/drivers/staging/greybus/Documentation/sysfs/endo/01/power deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/01/present b/drivers/staging/greybus/Documentation/sysfs/endo/01/present deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/02/02/.gitignore b/drivers/staging/greybus/Documentation/sysfs/endo/02/02/.gitignore deleted file mode 100644 index f935021..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/endo/02/02/.gitignore +++ /dev/null @@ -1 +0,0 @@ -!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/ap_intf_id b/drivers/staging/greybus/Documentation/sysfs/endo/ap_intf_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/id b/drivers/staging/greybus/Documentation/sysfs/endo/id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/svc/svc/firmware b/drivers/staging/greybus/Documentation/sysfs/endo/svc/svc/firmware deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/svc/svc/serial_number b/drivers/staging/greybus/Documentation/sysfs/endo/svc/svc/serial_number deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/endo/svc/svc/version b/drivers/staging/greybus/Documentation/sysfs/endo/svc/svc/version deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.1/class b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.1/class new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.1/id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.1/id new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.1/id @@ -0,0 +1 @@ +1 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.1/state b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.1/state new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/class b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/class new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/id new file mode 100644 index 0000000..0cfbf08 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/id @@ -0,0 +1 @@ +2 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/state b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/state new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/id new file mode 100644 index 0000000..0cfbf08 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/id @@ -0,0 +1 @@ +2 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/product_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/product_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/unique_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/unique_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/vendor_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/vendor_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/class b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/class new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/gpbridge0/gpio/gpiochip490/.gitignore b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/gpbridge0/gpio/gpiochip490/.gitignore new file mode 100644 index 0000000..f935021 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/gpbridge0/gpio/gpiochip490/.gitignore @@ -0,0 +1 @@ +!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/gpbridge0/i2c-4/.gitignore b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/gpbridge0/i2c-4/.gitignore new file mode 100644 index 0000000..f935021 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/gpbridge0/i2c-4/.gitignore @@ -0,0 +1 @@ +!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/id new file mode 100644 index 0000000..0cfbf08 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/id @@ -0,0 +1 @@ +2 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/state b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/state new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/id new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/id @@ -0,0 +1 @@ +4 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/product_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/product_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/unique_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/unique_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/vendor_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/vendor_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-svc/ap_intf_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-svc/ap_intf_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-svc/eject b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-svc/eject new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-svc/endo_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-svc/endo_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-svc/unique_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-svc/unique_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.1/class b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.1/class new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.1/id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.1/id new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.1/id @@ -0,0 +1 @@ +1 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.1/state b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.1/state new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/id new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/id @@ -0,0 +1 @@ +3 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/product_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/product_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/unique_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/unique_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/vendor_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/vendor_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-svc/ap_intf_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-svc/ap_intf_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-svc/eject b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-svc/eject new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-svc/endo_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-svc/endo_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-svc/unique_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-svc/unique_id new file mode 100644 index 0000000..e69de29 -- cgit v0.10.2 From fda3412566631d7c22edc3da7561f09a6f4dbc96 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:58:55 +0100 Subject: greybus: Documentation/sysfs-bus-greybus: update the bus ABI documentation Update the ABI documentation to match the new device model. Note that the SVC unique_id and version attributes are not yet implemented. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 8363f23..88ed2d8 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -1,13 +1,19 @@ -What: /sys/bus/greybus/device/endoE +What: /sys/bus/greybus/device/greybusN Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: - The "root" endo devices for the Greybus device tree. E - is replaced with a 2 byte number representing the endo, - mostly 0. + The "root" greybus device for the Greybus device tree, or bus, + where N is a dynamically assigned 1-based id. -What: /sys/bus/greybus/device/endoE/id +What: /sys/bus/greybus/device/N-svc/endo_id +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The singleton SVC device of bus N. + +What: /sys/bus/greybus/device/N-svc/endo_id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman @@ -16,112 +22,74 @@ Description: defined by the Endo layout scheme, documented in the ARA Module Developer Kit. -What: /sys/bus/greybus/device/endoE/ap_intf_id +What: /sys/bus/greybus/device/N-svc/ap_intf_id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: The AP interface ID, a 1-byte non-zero integer which - defines the position of the AP module on the Endo. + defines the position of the AP module on the frame. The interface positions are defined in the ARA Module Developer Kit. -What: /sys/bus/greybus/device/endoE/svc/serial_number +What: /sys/bus/greybus/device/N-svc/unique_id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: - The serial number of the SVC device + The unique ID, or serial number, of the SVC device -What: /sys/bus/greybus/device/endoE/svc/version +What: /sys/bus/greybus/device/N-svc/version Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: The version number of the firmware in the SVC device. -What: /sys/bus/greybus/device/endoE:M -Date: October 2015 -KernelVersion: 4.XX -Contact: Greg Kroah-Hartman -Description: - A module slot on the endoE, M is replaced by a 1-byte - number representing the module slot. - -What: /sys/bus/greybus/device/endoE:M/epm -Date: October 2015 -KernelVersion: 4.XX -Contact: Greg Kroah-Hartman -Description: - The EPM (Electropermanent Magnet) control file for - the specific module slot the file is present in. - Writing 1 to it turns it on, writing 0 to it turns it - off. Reading the value returns if it is on or off. - -What: /sys/bus/greybus/device/endoE:M/power_control -Date: October 2015 -KernelVersion: 4.XX -Contact: Greg Kroah-Hartman -Description: - The power control file for the specific module slot that - the file is present in. Writing 1 to it turns power on - to the module, writing 0 to it turns power off to the - module. Reading the value returns if it is on or off. - -What: /sys/bus/greybus/device/endoE:M/present -Date: October 2015 -KernelVersion: 4.XX -Contact: Greg Kroah-Hartman -Description: - The "is a module present in the slot" file for the - specific module slot that the file is present in. - This is read-only, 1 means a module is present, 0 means - no module is present. - -What: /sys/bus/greybus/device/endoE:M:I +What: /sys/bus/greybus/device/N-I Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: - An Interface I on the module slot M on the endoE, I is - replaced by a 1-byte number representing the interface. + An Interface I on the bus N, where I is the 1-byte interface + ID. -What: /sys/bus/greybus/device/endoE:M:I/device_id +What: /sys/bus/greybus/device/N-I/interface_id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: - The device ID of a Greybus interface block. + The ID of a Greybus interface. -What: /sys/bus/greybus/device/endoE:M:I/product +What: /sys/bus/greybus/device/N-I/product_id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: - Product ID of a Greybus interface block. + Product ID of a Greybus interface. -What: /sys/bus/greybus/device/endoE:M:I/product_string +What: /sys/bus/greybus/device/N-I/product_string Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: - Product ID string of a Greybus interface block. + Product ID string of a Greybus interface. -What: /sys/bus/greybus/device/endoE:M:I/vendor +What: /sys/bus/greybus/device/N-I/vendor_id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: - Vendor ID of a Greybus interface block. + Vendor ID of a Greybus interface. -What: /sys/bus/greybus/device/endoE:M:I/vendor_string +What: /sys/bus/greybus/device/N-I/vendor_string Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: Vendor ID string of a Greybus interface block. -What: /sys/bus/greybus/device/endoE:M:I:B +What: /sys/bus/greybus/device/N-I.B Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman @@ -129,14 +97,14 @@ Description: A bundle B on the Interface I, B is replaced by a 1-byte number representing the bundle. -What: /sys/bus/greybus/device/endoE:M:I:B/class +What: /sys/bus/greybus/device/N-I.B/bundle_class Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: The greybus class of the bundle B. -What: /sys/bus/greybus/device/endoE:M:I:B/state +What: /sys/bus/greybus/device/N-I.B/state Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman -- cgit v0.10.2 From 9f59263a8976db0877409d9f9813d7101756a653 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:58:56 +0100 Subject: greybus: interface: rename vendor and product attributes Rename vendor and product attributes vendor_id and product_id. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 56250fa..b3c422a 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -33,11 +33,11 @@ static int greybus_match_one_id(struct gb_bundle *bundle, const struct greybus_bundle_id *id) { if ((id->match_flags & GREYBUS_ID_MATCH_VENDOR) && - (id->vendor != bundle->intf->vendor)) + (id->vendor != bundle->intf->vendor_id)) return 0; if ((id->match_flags & GREYBUS_ID_MATCH_PRODUCT) && - (id->product != bundle->intf->product)) + (id->product != bundle->intf->product_id)) return 0; if ((id->match_flags & GREYBUS_ID_MATCH_CLASS) && diff --git a/drivers/staging/greybus/firmware.c b/drivers/staging/greybus/firmware.c index e99d8d6..e41526b 100644 --- a/drivers/staging/greybus/firmware.c +++ b/drivers/staging/greybus/firmware.c @@ -41,7 +41,7 @@ static int download_firmware(struct gb_firmware *firmware, u8 stage) snprintf(firmware_name, sizeof(firmware_name), "ara:%08x:%08x:%08x:%08x:%02x.tftf", intf->unipro_mfg_id, intf->unipro_prod_id, - intf->vendor, intf->product, stage); + intf->vendor_id, intf->product_id, stage); return request_firmware(&firmware->fw, firmware_name, &connection->bundle->dev); diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index b57cc09..9f4cf4d 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -21,15 +21,15 @@ static ssize_t field##_show(struct device *dev, \ static DEVICE_ATTR_RO(field) gb_interface_attr(device_id, d); -gb_interface_attr(vendor, x); -gb_interface_attr(product, x); +gb_interface_attr(vendor_id, x); +gb_interface_attr(product_id, x); gb_interface_attr(vendor_string, s); gb_interface_attr(product_string, s); static struct attribute *interface_attrs[] = { &dev_attr_device_id.attr, - &dev_attr_vendor.attr, - &dev_attr_product.attr, + &dev_attr_vendor_id.attr, + &dev_attr_product_id.attr, &dev_attr_vendor_string.attr, &dev_attr_product_string.attr, NULL, diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 28d2bac..71493cd 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -28,8 +28,8 @@ struct gb_interface { /* Information taken from the hotplug event */ u32 unipro_mfg_id; u32 unipro_prod_id; - u32 vendor; - u32 product; + u32 vendor_id; + u32 product_id; struct gb_module *module; struct gb_host_device *hd; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 1acd0f7..2e8c444 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -460,8 +460,8 @@ static void svc_process_hotplug(struct work_struct *work) intf->unipro_mfg_id = le32_to_cpu(hotplug->data.unipro_mfg_id); intf->unipro_prod_id = le32_to_cpu(hotplug->data.unipro_prod_id); - intf->vendor = le32_to_cpu(hotplug->data.ara_vend_id); - intf->product = le32_to_cpu(hotplug->data.ara_prod_id); + intf->vendor_id = le32_to_cpu(hotplug->data.ara_vend_id); + intf->product_id = le32_to_cpu(hotplug->data.ara_prod_id); /* * Create a device id for the interface: -- cgit v0.10.2 From 1eca63ae79cc90ae3c8cabe21d5c9c717eb82a3a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:58:57 +0100 Subject: greybus: interface: remove device_id attribute The interface device_id attribute is an implementation detail that does not need to be exported to user space. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 9f4cf4d..4ed782e 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -20,14 +20,12 @@ static ssize_t field##_show(struct device *dev, \ } \ static DEVICE_ATTR_RO(field) -gb_interface_attr(device_id, d); gb_interface_attr(vendor_id, x); gb_interface_attr(product_id, x); gb_interface_attr(vendor_string, s); gb_interface_attr(product_string, s); static struct attribute *interface_attrs[] = { - &dev_attr_device_id.attr, &dev_attr_vendor_id.attr, &dev_attr_product_id.attr, &dev_attr_vendor_string.attr, -- cgit v0.10.2 From 320421a80bdd0f7373dbba0bf01b594e12d57218 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:58:58 +0100 Subject: greybus: interface: add interface_id attribute Add interface_id attribute that user space needs to identify an interface. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 4ed782e..b5d9046 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -20,12 +20,14 @@ static ssize_t field##_show(struct device *dev, \ } \ static DEVICE_ATTR_RO(field) +gb_interface_attr(interface_id, u); gb_interface_attr(vendor_id, x); gb_interface_attr(product_id, x); gb_interface_attr(vendor_string, s); gb_interface_attr(product_string, s); static struct attribute *interface_attrs[] = { + &dev_attr_interface_id.attr, &dev_attr_vendor_id.attr, &dev_attr_product_id.attr, &dev_attr_vendor_string.attr, -- cgit v0.10.2 From 4396c00b73d1ead961f09016aa9c731ea97c44ab Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:58:59 +0100 Subject: greybus: bundle: rename class attribute Rename the bundle class-attribute "bundle_class" for consistency reasons and to make it self documenting. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 4d04f09..7b539e9 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -9,14 +9,14 @@ #include "greybus.h" -static ssize_t class_show(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t bundle_class_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct gb_bundle *bundle = to_gb_bundle(dev); return sprintf(buf, "%d\n", bundle->class); } -static DEVICE_ATTR_RO(class); +static DEVICE_ATTR_RO(bundle_class); static ssize_t state_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -48,7 +48,7 @@ static DEVICE_ATTR_RW(state); static struct attribute *bundle_attrs[] = { - &dev_attr_class.attr, + &dev_attr_bundle_class.attr, &dev_attr_state.attr, NULL, }; -- cgit v0.10.2 From 2b14daba1d6976a078ba8ccdd1f932f2320061a8 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:59:00 +0100 Subject: greybus: bundle: use hexadecimal notation for class attribute Use hexadecimal notation for class-attribute value. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 7b539e9..61c9a6d 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -14,7 +14,7 @@ static ssize_t bundle_class_show(struct device *dev, { struct gb_bundle *bundle = to_gb_bundle(dev); - return sprintf(buf, "%d\n", bundle->class); + return sprintf(buf, "0x%02x\n", bundle->class); } static DEVICE_ATTR_RO(bundle_class); -- cgit v0.10.2 From a97015c9e99d8421b80cdf9652a456f4cd93fc1e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:59:01 +0100 Subject: greybus: bundle: add bundle_id attribute Add a bundle_id attribute for the interface-unique id of a bundle that user space can use for matching. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 88ed2d8..9329a31 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -104,6 +104,13 @@ Contact: Greg Kroah-Hartman Description: The greybus class of the bundle B. +What: /sys/bus/greybus/device/N-I.B/bundle_id +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The interface-unique id of the bundle B. + What: /sys/bus/greybus/device/N-I.B/state Date: October 2015 KernelVersion: 4.XX diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 61c9a6d..f746438 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -18,6 +18,15 @@ static ssize_t bundle_class_show(struct device *dev, } static DEVICE_ATTR_RO(bundle_class); +static ssize_t bundle_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_bundle *bundle = to_gb_bundle(dev); + + return sprintf(buf, "%u\n", bundle->id); +} +static DEVICE_ATTR_RO(bundle_id); + static ssize_t state_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -49,6 +58,7 @@ static DEVICE_ATTR_RW(state); static struct attribute *bundle_attrs[] = { &dev_attr_bundle_class.attr, + &dev_attr_bundle_id.attr, &dev_attr_state.attr, NULL, }; -- cgit v0.10.2 From 2adaefb1458f67b3f71111fcf6a15670ab64101d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:59:02 +0100 Subject: greybus: hd: make host device a device Make the host device a proper device in the kernel device model. Host devices will be our new greybus-bus root devices. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 695f148..c076171 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -55,7 +55,7 @@ void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id, connection = gb_connection_hd_find(hd, cport_id); if (!connection) { - dev_err(hd->parent, + dev_err(&hd->dev, "nonexistent connection (%zu bytes dropped)\n", length); return; } @@ -196,7 +196,7 @@ static int gb_connection_hd_cport_enable(struct gb_connection *connection) ret = hd->driver->cport_enable(hd, connection->hd_cport_id); if (ret) { - dev_err(hd->parent, + dev_err(&hd->dev, "failed to enable host cport: %d\n", ret); return ret; } @@ -502,7 +502,7 @@ int gb_connection_bind_protocol(struct gb_connection *connection) connection->major, connection->minor); if (!protocol) { - dev_warn(connection->hd->parent, + dev_warn(&connection->hd->dev, "protocol 0x%02hhx version %hhu.%hhu not found\n", connection->protocol_id, connection->major, connection->minor); diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index b3c422a..8c8ba02 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -77,6 +77,7 @@ static int greybus_module_match(struct device *dev, struct device_driver *drv) static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) { + struct gb_host_device *hd = NULL; struct gb_module *module = NULL; struct gb_interface *intf = NULL; struct gb_bundle *bundle = NULL; @@ -89,7 +90,9 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) return 0; } - if (is_gb_module(dev)) { + if (is_gb_host_device(dev)) { + hd = to_gb_host_device(dev); + } else if (is_gb_module(dev)) { module = to_gb_module(dev); } else if (is_gb_interface(dev)) { intf = to_gb_interface(dev); @@ -196,6 +199,12 @@ static int __init gb_init(void) goto error_bus; } + retval = gb_hd_init(); + if (retval) { + pr_err("gb_hd_init failed (%d)\n", retval); + goto error_hd; + } + retval = gb_operation_init(); if (retval) { pr_err("gb_operation_init failed (%d)\n", retval); @@ -237,6 +246,8 @@ error_control: error_endo: gb_operation_exit(); error_operation: + gb_hd_exit(); +error_hd: bus_unregister(&greybus_bus_type); error_bus: gb_debugfs_cleanup(); @@ -252,6 +263,7 @@ static void __exit gb_exit(void) gb_control_protocol_exit(); gb_endo_exit(); gb_operation_exit(); + gb_hd_exit(); bus_unregister(&greybus_bus_type); gb_debugfs_cleanup(); tracepoint_synchronize_unregister(); diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c index 775dbce..6fb22fb 100644 --- a/drivers/staging/greybus/endo.c +++ b/drivers/staging/greybus/endo.c @@ -219,7 +219,7 @@ static bool validate_front_ribs(struct gb_host_device *hd, layout->front_ribs = 0x5; break; default: - dev_err(hd->parent, + dev_err(&hd->dev, "%s: Invalid endo front mask 0x%02x, id 0x%04x\n", __func__, front_mask, endo_id); return false; @@ -266,21 +266,21 @@ static bool validate_back_ribs(struct gb_host_device *hd, right_ribs = endo_back_right_ribs(endo_id, max_ribs); if (!single_cross_rib(left_ribs, right_ribs)) { - dev_err(hd->parent, + dev_err(&hd->dev, "%s: More than one spanning rib (left 0x%02x right 0x%02x), id 0x%04x\n", __func__, left_ribs, right_ribs, endo_id); return false; } if (modules_oversized(max_ribs, left_ribs)) { - dev_err(hd->parent, + dev_err(&hd->dev, "%s: Oversized module (left) 0x%02x, id 0x%04x\n", __func__, left_ribs, endo_id); return false; } if (modules_oversized(max_ribs, right_ribs)) { - dev_err(hd->parent, + dev_err(&hd->dev, "%s: Oversized module (Right) 0x%02x, id 0x%04x\n", __func__, right_ribs, endo_id); return false; @@ -306,7 +306,7 @@ static bool validate_back_ribs(struct gb_host_device *hd, * are of different widths. */ if (max_ribs != ENDO_BACK_RIBS_MEDIUM && left_ribs < right_ribs) { - dev_err(hd->parent, "%s: Non-canonical endo id 0x%04x\n", __func__, + dev_err(&hd->dev, "%s: Non-canonical endo id 0x%04x\n", __func__, endo_id); return false; } @@ -334,7 +334,7 @@ static int gb_endo_validate_id(struct gb_host_device *hd, /* Mini Endo type */ layout->max_ribs = ENDO_BACK_RIBS_MINI; } else { - dev_err(hd->parent, "%s: Invalid endo type, id 0x%04x\n", + dev_err(&hd->dev, "%s: Invalid endo type, id 0x%04x\n", __func__, endo_id); return -EINVAL; } @@ -447,11 +447,11 @@ static int gb_endo_register(struct gb_host_device *hd, endo->dev_id = dev_id; - endo->dev.parent = hd->parent; + endo->dev.parent = &hd->dev; endo->dev.bus = &greybus_bus_type; endo->dev.type = &greybus_endo_type; endo->dev.groups = endo_groups; - endo->dev.dma_mask = hd->parent->dma_mask; + endo->dev.dma_mask = hd->dev.dma_mask; device_initialize(&endo->dev); dev_set_name(&endo->dev, "endo%hu", endo->dev_id); @@ -463,7 +463,7 @@ static int gb_endo_register(struct gb_host_device *hd, retval = device_add(&endo->dev); if (retval) { - dev_err(hd->parent, "failed to add endo device of id 0x%04x\n", + dev_err(&hd->dev, "failed to add endo device of id 0x%04x\n", endo->id); put_device(&endo->dev); } diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 6da4e78..8ef3a04 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -104,11 +104,17 @@ struct dentry *gb_debugfs_get(void); extern struct bus_type greybus_bus_type; +extern struct device_type greybus_hd_type; extern struct device_type greybus_endo_type; extern struct device_type greybus_module_type; extern struct device_type greybus_interface_type; extern struct device_type greybus_bundle_type; +static inline int is_gb_host_device(const struct device *dev) +{ + return dev->type == &greybus_hd_type; +} + static inline int is_gb_endo(const struct device *dev) { return dev->type == &greybus_endo_type; diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h index a39fa39..1ca0706 100644 --- a/drivers/staging/greybus/greybus_trace.h +++ b/drivers/staging/greybus/greybus_trace.h @@ -114,13 +114,13 @@ DECLARE_EVENT_CLASS(gb_host_device, TP_ARGS(hd, intf_cport_id, payload_size), TP_STRUCT__entry( - __string(name, dev_name(hd->parent)) + __string(name, dev_name(&hd->dev)) __field(u16, intf_cport_id) __field(size_t, payload_size) ), TP_fast_assign( - __assign_str(name, dev_name(hd->parent)) + __assign_str(name, dev_name(&hd->dev)) __entry->intf_cport_id = intf_cport_id; __entry->payload_size = payload_size; ), diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index 3446fec..88d2f01 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -14,26 +14,30 @@ #include "greybus.h" -static DEFINE_MUTEX(hd_mutex); +static struct ida gb_hd_bus_id_map; -static void free_hd(struct kref *kref) +static void gb_hd_release(struct device *dev) { - struct gb_host_device *hd; - - hd = container_of(kref, struct gb_host_device, kref); + struct gb_host_device *hd = to_gb_host_device(dev); + ida_simple_remove(&gb_hd_bus_id_map, hd->bus_id); ida_destroy(&hd->cport_id_map); kfree(hd); - mutex_unlock(&hd_mutex); } +struct device_type greybus_hd_type = { + .name = "greybus_host_device", + .release = gb_hd_release, +}; + struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, struct device *parent, size_t buffer_size_max, size_t num_cports) { struct gb_host_device *hd; + int ret; /* * Validate that the driver implements all of the callbacks @@ -68,8 +72,21 @@ struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, if (!hd) return ERR_PTR(-ENOMEM); - kref_init(&hd->kref); - hd->parent = parent; + hd->dev.parent = parent; + hd->dev.bus = &greybus_bus_type; + hd->dev.type = &greybus_hd_type; + hd->dev.dma_mask = hd->dev.parent->dma_mask; + device_initialize(&hd->dev); + + ret = ida_simple_get(&gb_hd_bus_id_map, 1, 0, GFP_KERNEL); + if (ret < 0) { + kfree(hd); + return ERR_PTR(ret); + } + + hd->bus_id = ret; + dev_set_name(&hd->dev, "greybus%d", hd->bus_id); + hd->driver = driver; INIT_LIST_HEAD(&hd->interfaces); INIT_LIST_HEAD(&hd->connections); @@ -83,6 +100,12 @@ EXPORT_SYMBOL_GPL(gb_hd_create); int gb_hd_add(struct gb_host_device *hd) { + int ret; + + ret = device_add(&hd->dev); + if (ret) + return ret; + /* * Initialize AP's SVC protocol connection: * @@ -93,8 +116,10 @@ int gb_hd_add(struct gb_host_device *hd) * time we will create a fully initialized svc-connection, as we need * endo-id and AP's interface id for that. */ - if (!gb_ap_svc_connection_create(hd)) + if (!gb_ap_svc_connection_create(hd)) { + device_del(&hd->dev); return -ENOMEM; + } return 0; } @@ -113,11 +138,25 @@ void gb_hd_del(struct gb_host_device *hd) /* Is the SVC still using the partially uninitialized connection ? */ if (hd->initial_svc_connection) gb_connection_destroy(hd->initial_svc_connection); + + device_del(&hd->dev); } EXPORT_SYMBOL_GPL(gb_hd_del); void gb_hd_put(struct gb_host_device *hd) { - kref_put_mutex(&hd->kref, free_hd, &hd_mutex); + put_device(&hd->dev); } EXPORT_SYMBOL_GPL(gb_hd_put); + +int __init gb_hd_init(void) +{ + ida_init(&gb_hd_bus_id_map); + + return 0; +} + +void gb_hd_exit(void) +{ + ida_destroy(&gb_hd_bus_id_map); +} diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h index 6724cfe..6bc9ce3 100644 --- a/drivers/staging/greybus/hd.h +++ b/drivers/staging/greybus/hd.h @@ -26,8 +26,8 @@ struct gb_hd_driver { }; struct gb_host_device { - struct kref kref; - struct device *parent; + struct device dev; + int bus_id; const struct gb_hd_driver *driver; struct list_head interfaces; @@ -47,6 +47,7 @@ struct gb_host_device { /* Private data for the host driver */ unsigned long hd_priv[0] __aligned(sizeof(s64)); }; +#define to_gb_host_device(d) container_of(d, struct gb_host_device, d) struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, struct device *parent, @@ -56,4 +57,7 @@ int gb_hd_add(struct gb_host_device *hd); void gb_hd_del(struct gb_host_device *hd); void gb_hd_put(struct gb_host_device *hd); +int gb_hd_init(void); +void gb_hd_exit(void); + #endif /* __HD_H */ diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index b5d9046..4c99e3e 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -149,7 +149,7 @@ struct gb_interface *gb_interface_create(struct gb_host_device *hd, intf->dev.bus = &greybus_bus_type; intf->dev.type = &greybus_interface_type; intf->dev.groups = interface_groups; - intf->dev.dma_mask = hd->parent->dma_mask; + intf->dev.dma_mask = hd->dev.dma_mask; device_initialize(&intf->dev); dev_set_name(&intf->dev, "%s:%d", dev_name(&module->dev), interface_id); diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 2e8c444..7425c49 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -46,7 +46,7 @@ gb_ap_svc_connection_create(struct gb_host_device *hd) { struct gb_connection *connection; - connection = gb_connection_create_range(hd, NULL, hd->parent, + connection = gb_connection_create_range(hd, NULL, &hd->dev, GB_SVC_CPORT_ID, GREYBUS_PROTOCOL_SVC, GB_SVC_CPORT_ID, -- cgit v0.10.2 From 582b3a13920c71ca6e546598d344dc6027168e64 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:59:03 +0100 Subject: greybus: connection: drop parent parameter from connection create The parent parameter was only used for debug messages and to name the connection workqueue. Use the host-device device for this instead. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index c076171..cca5293 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -106,7 +106,7 @@ int svc_update_connection(struct gb_interface *intf, */ struct gb_connection * gb_connection_create_range(struct gb_host_device *hd, - struct gb_bundle *bundle, struct device *parent, + struct gb_bundle *bundle, u16 cport_id, u8 protocol_id, u32 ida_start, u32 ida_end) { @@ -152,7 +152,7 @@ gb_connection_create_range(struct gb_host_device *hd, INIT_LIST_HEAD(&connection->operations); connection->wq = alloc_workqueue("%s:%d", WQ_UNBOUND, 1, - dev_name(parent), cport_id); + dev_name(&hd->dev), hd_cport_id); if (!connection->wq) goto err_free_connection; @@ -170,7 +170,7 @@ gb_connection_create_range(struct gb_host_device *hd, retval = gb_connection_bind_protocol(connection); if (retval) { - dev_err(parent, "%d: failed to bind protocol: %d\n", + dev_err(&hd->dev, "%d: failed to bind protocol: %d\n", cport_id, retval); gb_connection_destroy(connection); return NULL; @@ -218,7 +218,7 @@ struct gb_connection *gb_connection_create(struct gb_bundle *bundle, u16 cport_id, u8 protocol_id) { return gb_connection_create_range(bundle->intf->hd, bundle, - &bundle->dev, cport_id, protocol_id, + cport_id, protocol_id, 0, bundle->intf->hd->num_cports); } diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 6163082..44ecfbe 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -54,7 +54,7 @@ int svc_update_connection(struct gb_interface *intf, struct gb_connection *gb_connection_create(struct gb_bundle *bundle, u16 cport_id, u8 protocol_id); struct gb_connection *gb_connection_create_range(struct gb_host_device *hd, - struct gb_bundle *bundle, struct device *parent, + struct gb_bundle *bundle, u16 cport_id, u8 protocol_id, u32 ida_start, u32 ida_end); void gb_connection_destroy(struct gb_connection *connection); diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 4c99e3e..1b13d37 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -101,7 +101,7 @@ int gb_create_bundle_connection(struct gb_interface *intf, u8 class) if (!bundle) return -EINVAL; - if (!gb_connection_create_range(bundle->intf->hd, bundle, &bundle->dev, + if (!gb_connection_create_range(bundle->intf->hd, bundle, cport_id, protocol_id, ida_start, ida_end)) return -EINVAL; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 7425c49..7994158 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -46,7 +46,7 @@ gb_ap_svc_connection_create(struct gb_host_device *hd) { struct gb_connection *connection; - connection = gb_connection_create_range(hd, NULL, &hd->dev, + connection = gb_connection_create_range(hd, NULL, GB_SVC_CPORT_ID, GREYBUS_PROTOCOL_SVC, GB_SVC_CPORT_ID, -- cgit v0.10.2 From 8b0df4b2eaf2f741ae44e8f5bad4ecb223f87932 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:59:04 +0100 Subject: greybus: interface: make interfaces children of host devices Make interfaces child devices of host devices. The new interface device name is "-", where bus_id is the dynamically allocated bus id for the host device and intf_id is the svc-allocated interface id. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 1b13d37..5060924 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -124,20 +124,14 @@ int gb_create_bundle_connection(struct gb_interface *intf, u8 class) struct gb_interface *gb_interface_create(struct gb_host_device *hd, u8 interface_id) { - struct gb_module *module; struct gb_interface *intf; int retval; - module = gb_module_find(hd, endo_get_module_id(hd->endo, interface_id)); - if (!module) - return NULL; - intf = kzalloc(sizeof(*intf), GFP_KERNEL); if (!intf) - goto put_module; + return NULL; intf->hd = hd; /* XXX refcount? */ - intf->module = module; intf->interface_id = interface_id; INIT_LIST_HEAD(&intf->bundles); INIT_LIST_HEAD(&intf->manifest_descs); @@ -145,13 +139,13 @@ struct gb_interface *gb_interface_create(struct gb_host_device *hd, /* Invalid device id to start with */ intf->device_id = GB_DEVICE_ID_BAD; - intf->dev.parent = &module->dev; + intf->dev.parent = &hd->dev; intf->dev.bus = &greybus_bus_type; intf->dev.type = &greybus_interface_type; intf->dev.groups = interface_groups; intf->dev.dma_mask = hd->dev.dma_mask; device_initialize(&intf->dev); - dev_set_name(&intf->dev, "%s:%d", dev_name(&module->dev), interface_id); + dev_set_name(&intf->dev, "%d-%d", hd->bus_id, interface_id); retval = device_add(&intf->dev); if (retval) { @@ -167,8 +161,6 @@ struct gb_interface *gb_interface_create(struct gb_host_device *hd, free_intf: put_device(&intf->dev); -put_module: - put_device(&module->dev); return NULL; } @@ -177,7 +169,6 @@ put_module: */ void gb_interface_remove(struct gb_interface *intf) { - struct gb_module *module; struct gb_bundle *bundle; struct gb_bundle *next; @@ -191,9 +182,7 @@ void gb_interface_remove(struct gb_interface *intf) list_for_each_entry_safe(bundle, next, &intf->bundles, links) gb_bundle_destroy(bundle); - module = intf->module; device_unregister(&intf->dev); - put_device(&module->dev); } void gb_interfaces_remove(struct gb_host_device *hd) diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 71493cd..1202062 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -31,7 +31,6 @@ struct gb_interface { u32 vendor_id; u32 product_id; - struct gb_module *module; struct gb_host_device *hd; /* The interface needs to boot over unipro */ diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 0c38414..ededfef 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -878,12 +878,6 @@ static int gb_loopback_bus_id_compare(void *priv, struct list_head *lha, struct gb_connection *ca = a->connection; struct gb_connection *cb = b->connection; - if (ca->bundle->intf->module->module_id < - cb->bundle->intf->module->module_id) - return -1; - if (cb->bundle->intf->module->module_id < - ca->bundle->intf->module->module_id) - return 1; if (ca->bundle->intf->interface_id < cb->bundle->intf->interface_id) return -1; if (cb->bundle->intf->interface_id < ca->bundle->intf->interface_id) -- cgit v0.10.2 From f0172c7043d772ed0d198046cb6142dd91ab2a5a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:59:05 +0100 Subject: greybus: bundle: rename bundle devices Rename bundle devices so that the new device names become "-.", where bus_id is the dynamically allocated host-device bus id and intf_id the svc-allocated interface id. Using a period (.) rather than a colon (:) makes dev-messages easier to read as as those already add a colon after the device name, for example: greybus 1-4.15: failed to connect cport: -22 Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index f746438..3df7d5f 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -148,7 +148,7 @@ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, bundle->dev.type = &greybus_bundle_type; bundle->dev.groups = bundle_groups; device_initialize(&bundle->dev); - dev_set_name(&bundle->dev, "%s:%d", dev_name(&intf->dev), bundle_id); + dev_set_name(&bundle->dev, "%s.%d", dev_name(&intf->dev), bundle_id); retval = device_add(&bundle->dev); if (retval) { -- cgit v0.10.2 From efe6ef76ba97f20302d200368d9f99848350bae1 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:59:06 +0100 Subject: greybus: svc: make svc a device Make the svc object a child device of the host-device device and use driver core to manage its lifetime. The svc device name is "-svc", where bus_id is the dynamically assigned id of the host device. Note that there is exactly one svc-device per host device (bus). Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 7994158..8f4efb3 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -23,6 +23,8 @@ enum gb_svc_state { }; struct gb_svc { + struct device dev; + struct gb_connection *connection; enum gb_svc_state state; struct ida device_id_map; @@ -667,19 +669,42 @@ static int gb_svc_request_recv(u8 type, struct gb_operation *op) } } +static void gb_svc_release(struct device *dev) +{ + struct gb_svc *svc = container_of(dev, struct gb_svc, dev); + + ida_destroy(&svc->device_id_map); + kfree(svc); +} + +struct device_type greybus_svc_type = { + .name = "greybus_svc", + .release = gb_svc_release, +}; + static int gb_svc_connection_init(struct gb_connection *connection) { + struct gb_host_device *hd = connection->hd; struct gb_svc *svc; svc = kzalloc(sizeof(*svc), GFP_KERNEL); if (!svc) return -ENOMEM; - connection->hd->svc = svc; + svc->dev.parent = &hd->dev; + svc->dev.bus = &greybus_bus_type; + svc->dev.type = &greybus_svc_type; + svc->dev.dma_mask = svc->dev.parent->dma_mask; + device_initialize(&svc->dev); + + dev_set_name(&svc->dev, "%d-svc", hd->bus_id); + svc->state = GB_SVC_STATE_RESET; svc->connection = connection; connection->private = svc; + hd->svc = svc; + WARN_ON(connection->hd->initial_svc_connection); connection->hd->initial_svc_connection = connection; @@ -692,10 +717,10 @@ static void gb_svc_connection_exit(struct gb_connection *connection) { struct gb_svc *svc = connection->private; - ida_destroy(&svc->device_id_map); connection->hd->svc = NULL; connection->private = NULL; - kfree(svc); + + put_device(&svc->dev); } static struct gb_protocol svc_protocol = { -- cgit v0.10.2 From 6106e51b742b32954351e6020cdb789bc33bf120 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:59:07 +0100 Subject: greybus: svc: clean up svc initialisation Make sure to initialise the svc device fully before adding it to the host device. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 8f4efb3..5aa21f7 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -699,6 +699,7 @@ static int gb_svc_connection_init(struct gb_connection *connection) dev_set_name(&svc->dev, "%d-svc", hd->bus_id); + ida_init(&svc->device_id_map); svc->state = GB_SVC_STATE_RESET; svc->connection = connection; connection->private = svc; @@ -708,8 +709,6 @@ static int gb_svc_connection_init(struct gb_connection *connection) WARN_ON(connection->hd->initial_svc_connection); connection->hd->initial_svc_connection = connection; - ida_init(&svc->device_id_map); - return 0; } -- cgit v0.10.2 From 88f7b96da75f816ba022190d6076720562cac050 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:59:08 +0100 Subject: greybus: svc: register svc device at hello Register the svc device upon reception of the HELLO request. The SVC HELLO request contains the endo id and AP interface id, which will be exposed from the svc device rather than the endo. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 8c8ba02..d1e26c4 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -81,6 +81,7 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) struct gb_module *module = NULL; struct gb_interface *intf = NULL; struct gb_bundle *bundle = NULL; + struct gb_svc *svc = NULL; if (is_gb_endo(dev)) { /* @@ -99,6 +100,8 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) } else if (is_gb_bundle(dev)) { bundle = to_gb_bundle(dev); intf = bundle->intf; + } else if (is_gb_svc(dev)) { + svc = to_gb_svc(dev); } else { dev_WARN(dev, "uevent for unknown greybus device \"type\"!\n"); return -EINVAL; diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 8ef3a04..fa81733 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -109,6 +109,7 @@ extern struct device_type greybus_endo_type; extern struct device_type greybus_module_type; extern struct device_type greybus_interface_type; extern struct device_type greybus_bundle_type; +extern struct device_type greybus_svc_type; static inline int is_gb_host_device(const struct device *dev) { @@ -135,6 +136,11 @@ static inline int is_gb_bundle(const struct device *dev) return dev->type == &greybus_bundle_type; } +static inline int is_gb_svc(const struct device *dev) +{ + return dev->type == &greybus_svc_type; +} + static inline bool cport_id_valid(struct gb_host_device *hd, u16 cport_id) { return cport_id != CPORT_ID_BAD && cport_id < hd->num_cports; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 5aa21f7..fab5c45 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -16,19 +16,6 @@ #define CPORT_FLAGS_CSD_N BIT(1) #define CPORT_FLAGS_CSV_N BIT(2) -enum gb_svc_state { - GB_SVC_STATE_RESET, - GB_SVC_STATE_PROTOCOL_VERSION, - GB_SVC_STATE_SVC_HELLO, -}; - -struct gb_svc { - struct device dev; - - struct gb_connection *connection; - enum gb_svc_state state; - struct ida device_id_map; -}; struct svc_hotplug { struct work_struct work; @@ -348,6 +335,7 @@ static int gb_svc_version_request(struct gb_operation *op) static int gb_svc_hello(struct gb_operation *op) { struct gb_connection *connection = op->connection; + struct gb_svc *svc = connection->private; struct gb_host_device *hd = connection->hd; struct gb_svc_hello_request *hello_request; struct gb_interface *intf; @@ -370,6 +358,12 @@ static int gb_svc_hello(struct gb_operation *op) endo_id = le16_to_cpu(hello_request->endo_id); interface_id = hello_request->interface_id; + ret = device_add(&svc->dev); + if (ret) { + dev_err(&svc->dev, "failed to register svc device: %d\n", ret); + return ret; + } + /* Setup Endo */ ret = greybus_endo_setup(hd, endo_id, interface_id); if (ret) @@ -671,7 +665,7 @@ static int gb_svc_request_recv(u8 type, struct gb_operation *op) static void gb_svc_release(struct device *dev) { - struct gb_svc *svc = container_of(dev, struct gb_svc, dev); + struct gb_svc *svc = to_gb_svc(dev); ida_destroy(&svc->device_id_map); kfree(svc); @@ -716,6 +710,9 @@ static void gb_svc_connection_exit(struct gb_connection *connection) { struct gb_svc *svc = connection->private; + if (device_is_registered(&svc->dev)) + device_del(&svc->dev); + connection->hd->svc = NULL; connection->private = NULL; diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index d2f406f..c9d8866 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -10,7 +10,20 @@ #ifndef __SVC_H #define __SVC_H -struct gb_svc; +enum gb_svc_state { + GB_SVC_STATE_RESET, + GB_SVC_STATE_PROTOCOL_VERSION, + GB_SVC_STATE_SVC_HELLO, +}; + +struct gb_svc { + struct device dev; + + struct gb_connection *connection; + enum gb_svc_state state; + struct ida device_id_map; +}; +#define to_gb_svc(d) container_of(d, struct gb_svc, d) int gb_svc_intf_reset(struct gb_svc *svc, u8 intf_id); int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, -- cgit v0.10.2 From 66069fb06ce42c1deca543d0620a69508b92ec31 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:59:09 +0100 Subject: greybus: svc: move endo id and ap interface id to svc Move endo_id and AP interface id to the svc device. The endo abstraction is about to be removed, and these attributes are arguable attributes of the svc anyway. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index cca5293..51fc84e 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -268,7 +268,7 @@ gb_connection_svc_connection_create(struct gb_connection *connection) intf = connection->bundle->intf; ret = gb_svc_connection_create(hd->svc, - hd->endo->ap_intf_id, + hd->svc->ap_intf_id, connection->hd_cport_id, intf->interface_id, connection->intf_cport_id, @@ -289,7 +289,7 @@ gb_connection_svc_connection_destroy(struct gb_connection *connection) return; gb_svc_connection_destroy(connection->hd->svc, - connection->hd->endo->ap_intf_id, + connection->hd->svc->ap_intf_id, connection->hd_cport_id, connection->bundle->intf->interface_id, connection->intf_cport_id); diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c index 6fb22fb..cca2a83 100644 --- a/drivers/staging/greybus/endo.c +++ b/drivers/staging/greybus/endo.c @@ -75,36 +75,7 @@ static const struct attribute_group svc_group = { .name = "svc", }; -static ssize_t id_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gb_endo *endo = to_gb_endo(dev); - - return sprintf(buf, "0x%04x\n", endo->id); -} -static DEVICE_ATTR_RO(id); - -static ssize_t ap_intf_id_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gb_endo *endo = to_gb_endo(dev); - - return sprintf(buf, "%u\n", endo->ap_intf_id); -} -static DEVICE_ATTR_RO(ap_intf_id); - -static struct attribute *endo_attrs[] = { - &dev_attr_id.attr, - &dev_attr_ap_intf_id.attr, - NULL, -}; - -static const struct attribute_group endo_group = { - .attrs = endo_attrs, -}; - static const struct attribute_group *endo_groups[] = { - &endo_group, &svc_group, NULL, }; @@ -490,8 +461,6 @@ struct gb_endo *gb_endo_create(struct gb_host_device *hd, u16 endo_id, retval = -EINVAL; goto free_endo; } - endo->id = endo_id; - endo->ap_intf_id = ap_intf_id; /* Register Endo device */ retval = gb_endo_register(hd, endo); diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index fab5c45..c71f41d 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -24,6 +24,31 @@ struct svc_hotplug { }; +static ssize_t endo_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_svc *svc = to_gb_svc(dev); + + return sprintf(buf, "0x%04x\n", svc->endo_id); +} +static DEVICE_ATTR_RO(endo_id); + +static ssize_t ap_intf_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_svc *svc = to_gb_svc(dev); + + return sprintf(buf, "%u\n", svc->ap_intf_id); +} +static DEVICE_ATTR_RO(ap_intf_id); + +static struct attribute *svc_attrs[] = { + &dev_attr_endo_id.attr, + &dev_attr_ap_intf_id.attr, + NULL, +}; +ATTRIBUTE_GROUPS(svc); + /* * AP's SVC cport is required early to get messages from the SVC. This happens * even before the Endo is created and hence any modules or interfaces. @@ -339,8 +364,6 @@ static int gb_svc_hello(struct gb_operation *op) struct gb_host_device *hd = connection->hd; struct gb_svc_hello_request *hello_request; struct gb_interface *intf; - u16 endo_id; - u8 interface_id; int ret; /* @@ -355,8 +378,8 @@ static int gb_svc_hello(struct gb_operation *op) } hello_request = op->request->payload; - endo_id = le16_to_cpu(hello_request->endo_id); - interface_id = hello_request->interface_id; + svc->endo_id = le16_to_cpu(hello_request->endo_id); + svc->ap_intf_id = hello_request->interface_id; ret = device_add(&svc->dev); if (ret) { @@ -365,7 +388,7 @@ static int gb_svc_hello(struct gb_operation *op) } /* Setup Endo */ - ret = greybus_endo_setup(hd, endo_id, interface_id); + ret = greybus_endo_setup(hd, svc->endo_id, svc->ap_intf_id); if (ret) return ret; @@ -373,7 +396,7 @@ static int gb_svc_hello(struct gb_operation *op) * Endo and its modules are ready now, fix AP's partially initialized * svc protocol and its connection. */ - intf = gb_ap_interface_create(hd, connection, interface_id); + intf = gb_ap_interface_create(hd, connection, svc->ap_intf_id); if (!intf) { gb_endo_remove(hd->endo); return ret; @@ -385,7 +408,6 @@ static int gb_svc_hello(struct gb_operation *op) static void svc_intf_remove(struct gb_connection *connection, struct gb_interface *intf) { - struct gb_host_device *hd = connection->hd; struct gb_svc *svc = connection->private; u8 intf_id = intf->interface_id; u8 device_id; @@ -396,7 +418,7 @@ static void svc_intf_remove(struct gb_connection *connection, /* * Destroy the two-way route between the AP and the interface. */ - gb_svc_route_destroy(svc, hd->endo->ap_intf_id, intf_id); + gb_svc_route_destroy(svc, svc->ap_intf_id, intf_id); ida_simple_remove(&svc->device_id_map, device_id); } @@ -486,7 +508,7 @@ static void svc_process_hotplug(struct work_struct *work) /* * Create a two-way route between the AP and the new interface */ - ret = gb_svc_route_create(svc, hd->endo->ap_intf_id, GB_DEVICE_ID_AP, + ret = gb_svc_route_create(svc, svc->ap_intf_id, GB_DEVICE_ID_AP, intf_id, device_id); if (ret) { pr_err("%d: Route create operation failed, interface %hhu device_id %hhu (%d)\n", @@ -504,7 +526,7 @@ static void svc_process_hotplug(struct work_struct *work) goto free_svc_hotplug; destroy_route: - gb_svc_route_destroy(svc, hd->endo->ap_intf_id, intf_id); + gb_svc_route_destroy(svc, svc->ap_intf_id, intf_id); svc_id_free: /* * XXX Should we tell SVC that this id doesn't belong to interface @@ -688,6 +710,7 @@ static int gb_svc_connection_init(struct gb_connection *connection) svc->dev.parent = &hd->dev; svc->dev.bus = &greybus_bus_type; svc->dev.type = &greybus_svc_type; + svc->dev.groups = svc_groups; svc->dev.dma_mask = svc->dev.parent->dma_mask; device_initialize(&svc->dev); diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index c9d8866..e05785f 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -22,6 +22,9 @@ struct gb_svc { struct gb_connection *connection; enum gb_svc_state state; struct ida device_id_map; + + u16 endo_id; + u8 ap_intf_id; }; #define to_gb_svc(d) container_of(d, struct gb_svc, d) -- cgit v0.10.2 From e4048006fd3823760d85057549bf609d3ed2e4c8 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:59:10 +0100 Subject: greybus: interface: kill gb_create_bundle_connection Kill gb_create_bundle_connection, which was only used to create the control bundle and connection, and replace it with a specialised static helper. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 5060924..c4ec256 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -71,40 +71,27 @@ struct device_type greybus_interface_type = { /* * Create kernel structures corresponding to a bundle and connection for - * managing control/svc CPort. + * managing control CPort. */ -int gb_create_bundle_connection(struct gb_interface *intf, u8 class) +static int +gb_interface_create_control_bundle_connection(struct gb_interface *intf) { struct gb_bundle *bundle; - u32 ida_start, ida_end; - u8 bundle_id, protocol_id; - u16 cport_id; - - if (class == GREYBUS_CLASS_CONTROL) { - protocol_id = GREYBUS_PROTOCOL_CONTROL; - bundle_id = GB_CONTROL_BUNDLE_ID; - cport_id = GB_CONTROL_CPORT_ID; - ida_start = 0; - ida_end = intf->hd->num_cports - 1; - } else if (class == GREYBUS_CLASS_SVC) { - protocol_id = GREYBUS_PROTOCOL_SVC; - bundle_id = GB_SVC_BUNDLE_ID; - cport_id = GB_SVC_CPORT_ID; - ida_start = GB_SVC_CPORT_ID; - ida_end = GB_SVC_CPORT_ID + 1; - } else { - WARN_ON(1); - return -EINVAL; - } + struct gb_connection *connection; - bundle = gb_bundle_create(intf, bundle_id, class); - if (!bundle) - return -EINVAL; + bundle = gb_bundle_create(intf, GB_CONTROL_BUNDLE_ID, + GREYBUS_CLASS_CONTROL); + if (!bundle) { + dev_err(&intf->dev, "failed to create control bundle\n"); + return -ENOMEM; + } - if (!gb_connection_create_range(bundle->intf->hd, bundle, - cport_id, protocol_id, ida_start, - ida_end)) - return -EINVAL; + connection = gb_connection_create(bundle, GB_CONTROL_CPORT_ID, + GREYBUS_PROTOCOL_CONTROL); + if (!connection) { + dev_err(&intf->dev, "failed to create control connection\n"); + return -ENOMEM; + } return 0; } @@ -208,11 +195,9 @@ int gb_interface_init(struct gb_interface *intf, u8 device_id) intf->device_id = device_id; /* Establish control CPort connection */ - ret = gb_create_bundle_connection(intf, GREYBUS_CLASS_CONTROL); - if (ret) { - dev_err(&intf->dev, "Failed to create control CPort connection (%d)\n", ret); + ret = gb_interface_create_control_bundle_connection(intf); + if (ret) return ret; - } /* Get manifest size using control protocol on CPort */ size = gb_control_get_manifest_size_operation(intf); diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 1202062..61e9c05 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -61,5 +61,4 @@ int gb_interface_init(struct gb_interface *intf, u8 device_id); void gb_interface_remove(struct gb_interface *intf); void gb_interfaces_remove(struct gb_host_device *hd); -int gb_create_bundle_connection(struct gb_interface *intf, u8 class); #endif /* __INTERFACE_H */ -- cgit v0.10.2 From 2566fae6a5eb29e52502a38fd816c6e994547625 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:59:11 +0100 Subject: greybus: connection: clean up connection-creation interface Clean up the connection-creation interface by clearly separating our two types of connections: static and dynamic. Add two convenience functions for creating static and dynamic connections. A static connection is a pre-setup connection that is defined by a host device and a host-device cport id. Specifically, the remote interface or cport id need not be known. The SVC connection is a static connection. A dynamic connection is defined by a host device and a remote interface and cport id. This is our normal connections where the host-device cport is (generally) allocated dynamically. Note that the new generic interface is marked static, but can be exported later to allow dynamic connections to be created also from fixed host-device cports (e.g. for CSI). Also note that a connection of either type is uniquely identified by its host-device and host-device cport id once created. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 51fc84e..d87a346 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -94,25 +94,32 @@ int svc_update_connection(struct gb_interface *intf, } /* - * Set up a Greybus connection, representing the bidirectional link + * gb_connection_create() - create a Greybus connection + * @hd: host device of the connection + * @hd_cport_id: host-device cport id, or -1 for dynamic allocation + * @intf: remote interface, or NULL for static connections + * @bundle: remote-interface bundle (may be NULL) + * @cport_id: remote-interface cport id, or 0 for static connections + * @protocol_id: protocol id + * + * Create a Greybus connection, representing the bidirectional link * between a CPort on a (local) Greybus host device and a CPort on - * another Greybus module. + * another Greybus interface. * * A connection also maintains the state of operations sent over the * connection. * - * Returns a pointer to the new connection if successful, or a null - * pointer otherwise. + * Return: A pointer to the new connection if successful, or NULL otherwise. */ -struct gb_connection * -gb_connection_create_range(struct gb_host_device *hd, - struct gb_bundle *bundle, - u16 cport_id, u8 protocol_id, u32 ida_start, - u32 ida_end) +static struct gb_connection * +gb_connection_create(struct gb_host_device *hd, int hd_cport_id, + struct gb_interface *intf, + struct gb_bundle *bundle, int cport_id, + u8 protocol_id) { struct gb_connection *connection; struct ida *id_map = &hd->cport_id_map; - int hd_cport_id; + int ida_start, ida_end; int retval; u8 major = 0; u8 minor = 1; @@ -128,6 +135,17 @@ gb_connection_create_range(struct gb_host_device *hd, return NULL; } + if (hd_cport_id < 0) { + ida_start = 0; + ida_end = hd->num_cports; + } else if (hd_cport_id < hd->num_cports) { + ida_start = hd_cport_id; + ida_end = hd_cport_id + 1; + } else { + dev_err(&hd->dev, "cport %d not available\n", hd_cport_id); + return NULL; + } + hd_cport_id = ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL); if (hd_cport_id < 0) return NULL; @@ -139,6 +157,7 @@ gb_connection_create_range(struct gb_host_device *hd, connection->hd_cport_id = hd_cport_id; connection->intf_cport_id = cport_id; connection->hd = hd; + connection->intf = intf; connection->protocol_id = protocol_id; connection->major = major; @@ -186,6 +205,23 @@ err_remove_ida: return NULL; } +struct gb_connection * +gb_connection_create_static(struct gb_host_device *hd, + u16 hd_cport_id, u8 protocol_id) +{ + return gb_connection_create(hd, hd_cport_id, NULL, NULL, 0, + protocol_id); +} + +struct gb_connection * +gb_connection_create_dynamic(struct gb_interface *intf, + struct gb_bundle *bundle, + u16 cport_id, u8 protocol_id) +{ + return gb_connection_create(intf->hd, -1, intf, bundle, cport_id, + protocol_id); +} + static int gb_connection_hd_cport_enable(struct gb_connection *connection) { struct gb_host_device *hd = connection->hd; @@ -214,14 +250,6 @@ static void gb_connection_hd_cport_disable(struct gb_connection *connection) hd->driver->cport_disable(hd, connection->hd_cport_id); } -struct gb_connection *gb_connection_create(struct gb_bundle *bundle, - u16 cport_id, u8 protocol_id) -{ - return gb_connection_create_range(bundle->intf->hd, bundle, - cport_id, protocol_id, - 0, bundle->intf->hd->num_cports); -} - /* * Cancel all active operations on a connection. * diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 44ecfbe..c5499fc 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -23,6 +23,7 @@ enum gb_connection_state { struct gb_connection { struct gb_host_device *hd; + struct gb_interface *intf; struct gb_bundle *bundle; struct kref kref; u16 hd_cport_id; @@ -51,12 +52,12 @@ struct gb_connection { int svc_update_connection(struct gb_interface *intf, struct gb_connection *connection); -struct gb_connection *gb_connection_create(struct gb_bundle *bundle, - u16 cport_id, u8 protocol_id); -struct gb_connection *gb_connection_create_range(struct gb_host_device *hd, - struct gb_bundle *bundle, - u16 cport_id, u8 protocol_id, u32 ida_start, - u32 ida_end); + +struct gb_connection *gb_connection_create_static(struct gb_host_device *hd, + u16 hd_cport_id, u8 protocol_id); +struct gb_connection *gb_connection_create_dynamic(struct gb_interface *intf, + struct gb_bundle *bundle, u16 cport_id, + u8 protocol_id); void gb_connection_destroy(struct gb_connection *connection); void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id, diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index c4ec256..2415187 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -86,7 +86,8 @@ gb_interface_create_control_bundle_connection(struct gb_interface *intf) return -ENOMEM; } - connection = gb_connection_create(bundle, GB_CONTROL_CPORT_ID, + connection = gb_connection_create_dynamic(intf, bundle, + GB_CONTROL_CPORT_ID, GREYBUS_PROTOCOL_CONTROL); if (!connection) { dev_err(&intf->dev, "failed to create control connection\n"); diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 41d5157..9252bf4 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -251,7 +251,8 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) goto print_error_exit; } - if (!gb_connection_create(bundle, cport_id, protocol_id)) + if (!gb_connection_create_dynamic(intf, bundle, cport_id, + protocol_id)) goto exit; release_descriptor: diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index c71f41d..9dd5112 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -60,11 +60,8 @@ gb_ap_svc_connection_create(struct gb_host_device *hd) { struct gb_connection *connection; - connection = gb_connection_create_range(hd, NULL, - GB_SVC_CPORT_ID, - GREYBUS_PROTOCOL_SVC, - GB_SVC_CPORT_ID, - GB_SVC_CPORT_ID + 1); + connection = gb_connection_create_static(hd, GB_SVC_CPORT_ID, + GREYBUS_PROTOCOL_SVC); return connection; } -- cgit v0.10.2 From 0daf17b9e4f74981c7546ad4b4224b8bef85e00e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:59:12 +0100 Subject: greybus: connection: fix potential null-deref on create Make sure that the interface lookup helper can handle static, bundle-less connections without oopsing when creating further connections. Note that the initial svc-connection has always been bundle-less, but did not trigger an oops as a bundle was created for it before further connections were created. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index d87a346..a7b8037 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -20,10 +20,12 @@ gb_connection_intf_find(struct gb_interface *intf, u16 cport_id) struct gb_host_device *hd = intf->hd; struct gb_connection *connection; - list_for_each_entry(connection, &hd->connections, hd_links) - if (connection->bundle->intf == intf && + list_for_each_entry(connection, &hd->connections, hd_links) { + if (connection->intf == intf && connection->intf_cport_id == cport_id) return connection; + } + return NULL; } -- cgit v0.10.2 From 4ec1574ae99872a9d1922fb1e57b8d46df4d0920 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:59:13 +0100 Subject: greybus: connection: kill GB_PROTOCOL_SKIP_SVC_CONNECTION Add helper to determine whether a connection is static, and remove the protocol flag GB_PROTOCOL_SKIP_SVC_CONNECTION. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index a7b8037..3f2fe01 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -289,11 +289,10 @@ static int gb_connection_svc_connection_create(struct gb_connection *connection) { struct gb_host_device *hd = connection->hd; - struct gb_protocol *protocol = connection->protocol; struct gb_interface *intf; int ret; - if (protocol->flags & GB_PROTOCOL_SKIP_SVC_CONNECTION) + if (gb_connection_is_static(connection)) return 0; intf = connection->bundle->intf; @@ -315,7 +314,7 @@ gb_connection_svc_connection_create(struct gb_connection *connection) static void gb_connection_svc_connection_destroy(struct gb_connection *connection) { - if (connection->protocol->flags & GB_PROTOCOL_SKIP_SVC_CONNECTION) + if (gb_connection_is_static(connection)) return; gb_svc_connection_destroy(connection->hd->svc, diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index c5499fc..446ffe1 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -60,6 +60,11 @@ struct gb_connection *gb_connection_create_dynamic(struct gb_interface *intf, u8 protocol_id); void gb_connection_destroy(struct gb_connection *connection); +static inline bool gb_connection_is_static(struct gb_connection *connection) +{ + return !connection->intf; +} + void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id, u8 *data, size_t length); diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index b1d122c..384ddf8 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -18,7 +18,6 @@ struct gb_operation; #define GB_PROTOCOL_SKIP_CONTROL_DISCONNECTED BIT(1) /* Don't sent disconnected requests */ #define GB_PROTOCOL_NO_BUNDLE BIT(2) /* Protocol May have a bundle-less connection */ #define GB_PROTOCOL_SKIP_VERSION BIT(3) /* Don't send get_version() requests */ -#define GB_PROTOCOL_SKIP_SVC_CONNECTION BIT(4) /* Don't send SVC connection requests */ typedef int (*gb_connection_init_t)(struct gb_connection *); typedef void (*gb_connection_exit_t)(struct gb_connection *); diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 9dd5112..3beb3a2 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -750,7 +750,6 @@ static struct gb_protocol svc_protocol = { .flags = GB_PROTOCOL_SKIP_CONTROL_CONNECTED | GB_PROTOCOL_SKIP_CONTROL_DISCONNECTED | GB_PROTOCOL_NO_BUNDLE | - GB_PROTOCOL_SKIP_VERSION | - GB_PROTOCOL_SKIP_SVC_CONNECTION, + GB_PROTOCOL_SKIP_VERSION, }; gb_builtin_protocol_driver(svc_protocol); -- cgit v0.10.2 From 729b260a67e051bcabdd83c8a29fc13c5617cd6b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:59:14 +0100 Subject: greybus: connection: add name field Add a name field to connections that can be used in log messages. A connection always belongs to a host-device (bus) and can be uniquely identified by its host-device cport id, but include remote interface and cport id nonetheless on the following format: /: The remote interface and cport id will be zero for static connections. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 3f2fe01..65d72b8 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -95,6 +95,21 @@ int svc_update_connection(struct gb_interface *intf, return 0; } +static void gb_connection_init_name(struct gb_connection *connection) +{ + u16 hd_cport_id = connection->hd_cport_id; + u16 cport_id = 0; + u8 intf_id = 0; + + if (connection->intf) { + intf_id = connection->intf->interface_id; + cport_id = connection->intf_cport_id; + } + + snprintf(connection->name, sizeof(connection->name), + "%hu/%hhu:%hu", hd_cport_id, intf_id, cport_id); +} + /* * gb_connection_create() - create a Greybus connection * @hd: host device of the connection @@ -179,6 +194,8 @@ gb_connection_create(struct gb_host_device *hd, int hd_cport_id, kref_init(&connection->kref); + gb_connection_init_name(connection); + spin_lock_irq(&gb_connections_lock); list_add(&connection->hd_links, &hd->connections); diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 446ffe1..028f278 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -43,6 +43,7 @@ struct gb_connection { enum gb_connection_state state; struct list_head operations; + char name[16]; struct workqueue_struct *wq; atomic_t op_cycle; -- cgit v0.10.2 From 4c4b50218656d972295b2ecabd3aacb674e2fe11 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:59:15 +0100 Subject: greybus: connection: handle static connections Use host-device device and connection name for log messages rather than assume that all connections have a bundle (e.g. not true for static connections). Note that the "initial" svc connection has never had a bundle. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 65d72b8..0ac3a8e 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -208,8 +208,8 @@ gb_connection_create(struct gb_host_device *hd, int hd_cport_id, retval = gb_connection_bind_protocol(connection); if (retval) { - dev_err(&hd->dev, "%d: failed to bind protocol: %d\n", - cport_id, retval); + dev_err(&hd->dev, "%s: failed to bind protocol: %d\n", + connection->name, retval); gb_connection_destroy(connection); return NULL; } @@ -320,8 +320,9 @@ gb_connection_svc_connection_create(struct gb_connection *connection) connection->intf_cport_id, intf->boot_over_unipro); if (ret) { - dev_err(&connection->bundle->dev, - "failed to create svc connection: %d\n", ret); + dev_err(&connection->hd->dev, + "%s: failed to create svc connection: %d\n", + connection->name, ret); return ret; } @@ -513,8 +514,9 @@ void gb_connection_latency_tag_enable(struct gb_connection *connection) ret = hd->driver->latency_tag_enable(hd, connection->hd_cport_id); if (ret) { - dev_err(&connection->bundle->dev, - "failed to enable latency tag: %d\n", ret); + dev_err(&connection->hd->dev, + "%s: failed to enable latency tag: %d\n", + connection->name, ret); } } EXPORT_SYMBOL_GPL(gb_connection_latency_tag_enable); @@ -529,8 +531,9 @@ void gb_connection_latency_tag_disable(struct gb_connection *connection) ret = hd->driver->latency_tag_disable(hd, connection->hd_cport_id); if (ret) { - dev_err(&connection->bundle->dev, - "failed to disable latency tag: %d\n", ret); + dev_err(&connection->hd->dev, + "%s: failed to disable latency tag: %d\n", + connection->name, ret); } } EXPORT_SYMBOL_GPL(gb_connection_latency_tag_disable); -- cgit v0.10.2 From 25cdd7aa5e67c09d65a5a2a5da5fc01ebf6483fe Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:59:16 +0100 Subject: greybus: operation: handle static connections Use the host-device device and connection name for error messages, as the operation code can not assume that a connection has a bundle. Note that the "initial" svc connection has never had a bundle. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 1643880..01ad08b 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -217,7 +217,8 @@ static void gb_message_cancel(struct gb_message *message) static void gb_operation_request_handle(struct gb_operation *operation) { - struct gb_protocol *protocol = operation->connection->protocol; + struct gb_connection *connection = operation->connection; + struct gb_protocol *protocol = connection->protocol; int status; int ret; @@ -227,18 +228,18 @@ static void gb_operation_request_handle(struct gb_operation *operation) if (protocol->request_recv) { status = protocol->request_recv(operation->type, operation); } else { - dev_err(&operation->connection->bundle->dev, - "unexpected incoming request type 0x%02hhx\n", - operation->type); + dev_err(&connection->hd->dev, + "%s: unexpected incoming request of type 0x%02hhx\n", + connection->name, operation->type); status = -EPROTONOSUPPORT; } ret = gb_operation_response_send(operation, status); if (ret) { - dev_err(&operation->connection->bundle->dev, - "failed to send response %d for type 0x%02hhx: %d\n", - status, operation->type, ret); + dev_err(&connection->hd->dev, + "%s: failed to send response %d for type 0x%02hhx: %d\n", + connection->name, status, operation->type, ret); return; } } @@ -743,7 +744,7 @@ static int gb_operation_response_send(struct gb_operation *operation, /* Record the result */ if (!gb_operation_result_set(operation, errno)) { - dev_err(&connection->bundle->dev, "request result already set\n"); + dev_err(&connection->hd->dev, "request result already set\n"); return -EIO; /* Shouldn't happen */ } @@ -795,9 +796,9 @@ void greybus_message_sent(struct gb_host_device *hd, */ if (message == operation->response) { if (status) { - dev_err(&connection->bundle->dev, - "error sending response type 0x%02hhx: %d\n", - operation->type, status); + dev_err(&connection->hd->dev, + "%s: error sending response 0x%02hhx: %d\n", + connection->name, operation->type, status); } gb_operation_put_active(operation); gb_operation_put(operation); @@ -827,8 +828,9 @@ static void gb_connection_recv_request(struct gb_connection *connection, operation = gb_operation_create_incoming(connection, operation_id, type, data, size); if (!operation) { - dev_err(&connection->bundle->dev, - "can't create incoming operation\n"); + dev_err(&connection->hd->dev, + "%s: can't create incoming operation\n", + connection->name); return; } @@ -865,17 +867,19 @@ static void gb_connection_recv_response(struct gb_connection *connection, operation = gb_operation_find_outgoing(connection, operation_id); if (!operation) { - dev_err(&connection->bundle->dev, - "unexpected response 0x%04hx received\n", operation_id); + dev_err(&connection->hd->dev, + "%s: unexpected response id 0x%04hx received\n", + connection->name, operation_id); return; } message = operation->response; message_size = sizeof(*message->header) + message->payload_size; if (!errno && size != message_size) { - dev_err(&connection->bundle->dev, - "malformed response of type 0x%02hhx received (%zu != %zu)\n", - message->header->type, size, message_size); + dev_err(&connection->hd->dev, + "%s: malformed response 0x%02hhx received (%zu != %zu)\n", + connection->name, message->header->type, size, + message_size); errno = -EMSGSIZE; } trace_gb_message_recv_response(operation->response); @@ -902,17 +906,18 @@ void gb_connection_recv(struct gb_connection *connection, void *data, size_t size) { struct gb_operation_msg_hdr header; - struct device *dev = &connection->bundle->dev; + struct device *dev = &connection->hd->dev; size_t msg_size; u16 operation_id; if (connection->state != GB_CONNECTION_STATE_ENABLED) { - dev_warn(dev, "dropping %zu received bytes\n", size); + dev_warn(dev, "%s: dropping %zu received bytes\n", + connection->name, size); return; } if (size < sizeof(header)) { - dev_err(dev, "short message received\n"); + dev_err(dev, "%s: short message received\n", connection->name); return; } @@ -921,9 +926,9 @@ void gb_connection_recv(struct gb_connection *connection, msg_size = le16_to_cpu(header.size); if (size < msg_size) { dev_err(dev, - "incomplete message 0x%04hx of type 0x%02hhx received (%zu < %zu)\n", - le16_to_cpu(header.operation_id), header.type, size, - msg_size); + "%s: incomplete message 0x%04hx of type 0x%02hhx received (%zu < %zu)\n", + connection->name, le16_to_cpu(header.operation_id), + header.type, size, msg_size); return; /* XXX Should still complete operation */ } @@ -1030,9 +1035,9 @@ int gb_operation_sync_timeout(struct gb_connection *connection, int type, ret = gb_operation_request_send_sync_timeout(operation, timeout); if (ret) { - dev_err(&connection->bundle->dev, - "synchronous operation of type 0x%02hhx failed: %d\n", - type, ret); + dev_err(&connection->hd->dev, + "%s: synchronous operation of type 0x%02hhx failed: %d\n", + connection->name, type, ret); } else { if (response_size) { memcpy(response, operation->response->payload, -- cgit v0.10.2 From 87757e325ab8b5b9e0e90e37de77778a631e6c8c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:59:17 +0100 Subject: greybus: protocol: handle static connections Use host-device device and connection name for log messages, as not all connections have a bundle. Note that the "initial" svc connection has never had a bundle. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index 1790d1a..47b7479 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -165,9 +165,9 @@ int gb_protocol_get_version(struct gb_connection *connection) return retval; if (response.major > connection->protocol->major) { - dev_err(&connection->bundle->dev, - "%d: unsupported major version (%hhu > %hhu)\n", - connection->intf_cport_id, response.major, + dev_err(&connection->hd->dev, + "%s: unsupported major version (%hhu > %hhu)\n", + connection->name, response.major, connection->protocol->major); return -ENOTSUPP; } @@ -175,8 +175,8 @@ int gb_protocol_get_version(struct gb_connection *connection) connection->module_major = response.major; connection->module_minor = response.minor; - dev_dbg(&connection->bundle->dev, - "%d: %s (0x%02hhx) v%hhu.%hhu\n", connection->intf_cport_id, + dev_dbg(&connection->hd->dev, + "%s: %s (0x%02hhx) v%hhu.%hhu\n", connection->name, protocol->name, protocol->id, response.major, response.minor); return 0; -- cgit v0.10.2 From 5ef323846ff7d1c32e4fb2441dfc79b10d6092b3 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:59:18 +0100 Subject: greybus: hd: fix svc-connection handling Create the svc connection when registering the host-device and remove the current svc connection hacks that "upgraded" the svc connection once the endo id and ap interface id was known. Note that the old implementation was partly based on a misunderstanding as it was the remote interface id, rather than the local AP interface id, that used to define a connection (but we also needed the endo_id). The remote interface is no longer needed as static connections, such as the svc connection, are now simply defined by the host-device and host cport id. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 0ac3a8e..7beab74 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -77,24 +77,6 @@ static void gb_connection_kref_release(struct kref *kref) mutex_unlock(&connection_mutex); } -int svc_update_connection(struct gb_interface *intf, - struct gb_connection *connection) -{ - struct gb_bundle *bundle; - - bundle = gb_bundle_create(intf, GB_SVC_BUNDLE_ID, GREYBUS_CLASS_SVC); - if (!bundle) - return -EINVAL; - - connection->bundle = bundle; - - spin_lock_irq(&gb_connections_lock); - list_add(&connection->bundle_links, &bundle->connections); - spin_unlock_irq(&gb_connections_lock); - - return 0; -} - static void gb_connection_init_name(struct gb_connection *connection) { u16 hd_cport_id = connection->hd_cport_id; diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 028f278..8006262 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -51,9 +51,6 @@ struct gb_connection { void *private; }; -int svc_update_connection(struct gb_interface *intf, - struct gb_connection *connection); - struct gb_connection *gb_connection_create_static(struct gb_host_device *hd, u16 hd_cport_id, u8 protocol_id); struct gb_connection *gb_connection_create_dynamic(struct gb_interface *intf, diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index 88d2f01..2ee5d4f 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -98,6 +98,18 @@ struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, } EXPORT_SYMBOL_GPL(gb_hd_create); +static int gb_hd_create_svc_connection(struct gb_host_device *hd) +{ + hd->svc_connection = gb_connection_create_static(hd, GB_SVC_CPORT_ID, + GREYBUS_PROTOCOL_SVC); + if (!hd->svc_connection) { + dev_err(&hd->dev, "failed to create svc connection\n"); + return -ENOMEM; + } + + return 0; +} + int gb_hd_add(struct gb_host_device *hd) { int ret; @@ -106,19 +118,10 @@ int gb_hd_add(struct gb_host_device *hd) if (ret) return ret; - /* - * Initialize AP's SVC protocol connection: - * - * This is required as part of early initialization of the host device - * as we need this connection in order to start any kind of message - * exchange between the AP and the SVC. SVC will start with a - * 'get-version' request followed by a 'svc-hello' message and at that - * time we will create a fully initialized svc-connection, as we need - * endo-id and AP's interface id for that. - */ - if (!gb_ap_svc_connection_create(hd)) { + ret = gb_hd_create_svc_connection(hd); + if (ret) { device_del(&hd->dev); - return -ENOMEM; + return ret; } return 0; @@ -135,9 +138,7 @@ void gb_hd_del(struct gb_host_device *hd) gb_interfaces_remove(hd); gb_endo_remove(hd->endo); - /* Is the SVC still using the partially uninitialized connection ? */ - if (hd->initial_svc_connection) - gb_connection_destroy(hd->initial_svc_connection); + gb_connection_destroy(hd->svc_connection); device_del(&hd->dev); } diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h index 6bc9ce3..72716e0 100644 --- a/drivers/staging/greybus/hd.h +++ b/drivers/staging/greybus/hd.h @@ -41,8 +41,8 @@ struct gb_host_device { size_t buffer_size_max; struct gb_endo *endo; - struct gb_connection *initial_svc_connection; struct gb_svc *svc; + struct gb_connection *svc_connection; /* Private data for the host driver */ unsigned long hd_priv[0] __aligned(sizeof(s64)); diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 3beb3a2..11fa8c9 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -49,51 +49,6 @@ static struct attribute *svc_attrs[] = { }; ATTRIBUTE_GROUPS(svc); -/* - * AP's SVC cport is required early to get messages from the SVC. This happens - * even before the Endo is created and hence any modules or interfaces. - * - * This is a temporary connection, used only at initial bootup. - */ -struct gb_connection * -gb_ap_svc_connection_create(struct gb_host_device *hd) -{ - struct gb_connection *connection; - - connection = gb_connection_create_static(hd, GB_SVC_CPORT_ID, - GREYBUS_PROTOCOL_SVC); - - return connection; -} - -/* - * We know endo-type and AP's interface id now, lets create a proper svc - * connection (and its interface/bundle) now and get rid of the initial - * 'partially' initialized one svc connection. - */ -static struct gb_interface * -gb_ap_interface_create(struct gb_host_device *hd, - struct gb_connection *connection, u8 interface_id) -{ - struct gb_interface *intf; - struct device *dev = &hd->endo->dev; - - intf = gb_interface_create(hd, interface_id); - if (!intf) { - dev_err(dev, "%s: Failed to create interface with id %hhu\n", - __func__, interface_id); - return NULL; - } - - intf->device_id = GB_DEVICE_ID_AP; - svc_update_connection(intf, connection); - - /* Its no longer a partially initialized connection */ - hd->initial_svc_connection = NULL; - - return intf; -} - static int gb_svc_intf_device_id(struct gb_svc *svc, u8 intf_id, u8 device_id) { struct gb_svc_intf_device_id_request request; @@ -360,7 +315,6 @@ static int gb_svc_hello(struct gb_operation *op) struct gb_svc *svc = connection->private; struct gb_host_device *hd = connection->hd; struct gb_svc_hello_request *hello_request; - struct gb_interface *intf; int ret; /* @@ -389,16 +343,6 @@ static int gb_svc_hello(struct gb_operation *op) if (ret) return ret; - /* - * Endo and its modules are ready now, fix AP's partially initialized - * svc protocol and its connection. - */ - intf = gb_ap_interface_create(hd, connection, svc->ap_intf_id); - if (!intf) { - gb_endo_remove(hd->endo); - return ret; - } - return 0; } @@ -720,9 +664,6 @@ static int gb_svc_connection_init(struct gb_connection *connection) hd->svc = svc; - WARN_ON(connection->hd->initial_svc_connection); - connection->hd->initial_svc_connection = connection; - return 0; } diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index e05785f..99be041 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -41,6 +41,4 @@ int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, int gb_svc_protocol_init(void); void gb_svc_protocol_exit(void); -struct gb_connection *gb_ap_svc_connection_create(struct gb_host_device *hd); - #endif /* __SVC_H */ -- cgit v0.10.2 From 684156a9d6eba32db939b11618d3c14d7e92d630 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:59:19 +0100 Subject: greybus: svc: clean up log messages Use dev_err and friends with the svc device for messages. Clean up error messages. Demote a few warnings to warning level. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 11fa8c9..62b67cc 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -7,7 +7,6 @@ * Released under the GPLv2 only. */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include #include "greybus.h" @@ -87,15 +86,15 @@ int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, &request, sizeof(request), &response, sizeof(response)); if (ret) { - pr_err("failed to get DME attribute (%hhu %hx %hu) %d\n", - intf_id, attr, selector, ret); + dev_err(&svc->dev, "failed to get DME attribute (%hhu %hx %hu): %d\n", + intf_id, attr, selector, ret); return ret; } result = le16_to_cpu(response.result_code); if (result) { - pr_err("Unipro error %hu while getting DME attribute (%hhu %hx %hu)\n", - result, intf_id, attr, selector); + dev_err(&svc->dev, "UniPro error while getting DME attribute (%hhu %hx %hu): %hu\n", + intf_id, attr, selector, result); return -EINVAL; } @@ -123,15 +122,15 @@ int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, &request, sizeof(request), &response, sizeof(response)); if (ret) { - pr_err("failed to set DME attribute (%hhu %hx %hu %u) %d\n", - intf_id, attr, selector, value, ret); + dev_err(&svc->dev, "failed to set DME attribute (%hhu %hx %hu %u): %d\n", + intf_id, attr, selector, value, ret); return ret; } result = le16_to_cpu(response.result_code); if (result) { - pr_err("Unipro error %hu while setting DME attribute (%hhu %hx %hu %u)\n", - result, intf_id, attr, selector, value); + dev_err(&svc->dev, "UniPro error while setting DME attribute (%hhu %hx %hu %u): %hu\n", + intf_id, attr, selector, value, result); return -EINVAL; } @@ -233,9 +232,10 @@ void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, ret = gb_operation_sync(connection, GB_SVC_TYPE_CONN_DESTROY, &request, sizeof(request), NULL, 0); - if (ret) - pr_err("failed to destroy connection (%hhu:%hu %hhu:%hu) %d\n", - intf1_id, cport1_id, intf2_id, cport2_id, ret); + if (ret) { + dev_err(&svc->dev, "failed to destroy connection (%hhu:%hu %hhu:%hu): %d\n", + intf1_id, cport1_id, intf2_id, cport2_id, ret); + } } EXPORT_SYMBOL_GPL(gb_svc_connection_destroy); @@ -265,20 +265,21 @@ static void gb_svc_route_destroy(struct gb_svc *svc, u8 intf1_id, u8 intf2_id) ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_ROUTE_DESTROY, &request, sizeof(request), NULL, 0); - if (ret) - pr_err("failed to destroy route (%hhu %hhu) %d\n", - intf1_id, intf2_id, ret); + if (ret) { + dev_err(&svc->dev, "failed to destroy route (%hhu %hhu): %d\n", + intf1_id, intf2_id, ret); + } } static int gb_svc_version_request(struct gb_operation *op) { struct gb_connection *connection = op->connection; + struct gb_svc *svc = connection->private; struct gb_protocol_version_request *request; struct gb_protocol_version_response *response; if (op->request->payload_size < sizeof(*request)) { - pr_err("%d: short version request (%zu < %zu)\n", - connection->intf_cport_id, + dev_err(&svc->dev, "short version request (%zu < %zu)\n", op->request->payload_size, sizeof(*request)); return -EINVAL; @@ -287,20 +288,16 @@ static int gb_svc_version_request(struct gb_operation *op) request = op->request->payload; if (request->major > GB_SVC_VERSION_MAJOR) { - pr_err("%d: unsupported major version (%hhu > %hhu)\n", - connection->intf_cport_id, request->major, - GB_SVC_VERSION_MAJOR); + dev_warn(&svc->dev, "unsupported major version (%hhu > %hhu)\n", + request->major, GB_SVC_VERSION_MAJOR); return -ENOTSUPP; } connection->module_major = request->major; connection->module_minor = request->minor; - if (!gb_operation_response_alloc(op, sizeof(*response), GFP_KERNEL)) { - pr_err("%d: error allocating response\n", - connection->intf_cport_id); + if (!gb_operation_response_alloc(op, sizeof(*response), GFP_KERNEL)) return -ENOMEM; - } response = op->response->payload; response->major = connection->module_major; @@ -322,9 +319,9 @@ static int gb_svc_hello(struct gb_operation *op) * request, use that to create an endo. */ if (op->request->payload_size < sizeof(*hello_request)) { - pr_err("%d: Illegal size of hello request (%zu < %zu)\n", - connection->intf_cport_id, op->request->payload_size, - sizeof(*hello_request)); + dev_warn(&svc->dev, "short hello request (%zu < %zu)\n", + op->request->payload_size, + sizeof(*hello_request)); return -EINVAL; } @@ -401,15 +398,15 @@ static void svc_process_hotplug(struct work_struct *work) * Remove the interface and add it again, and let user know * about this with a print message. */ - pr_info("%d: Removed interface (%hhu) to add it again\n", - connection->intf_cport_id, intf_id); + dev_info(&svc->dev, "removing interface %hhu to add it again\n", + intf_id); svc_intf_remove(connection, intf); } intf = gb_interface_create(hd, intf_id); if (!intf) { - pr_err("%d: Failed to create interface with id %hhu\n", - connection->intf_cport_id, intf_id); + dev_err(&svc->dev, "failed to create interface %hhu\n", + intf_id); goto free_svc_hotplug; } @@ -434,15 +431,15 @@ static void svc_process_hotplug(struct work_struct *work) GB_DEVICE_ID_MODULES_START, 0, GFP_KERNEL); if (device_id < 0) { ret = device_id; - pr_err("%d: Failed to allocate device id for interface with id %hhu (%d)\n", - connection->intf_cport_id, intf_id, ret); + dev_err(&svc->dev, "failed to allocate device id for interface %hhu: %d\n", + intf_id, ret); goto destroy_interface; } ret = gb_svc_intf_device_id(svc, intf_id, device_id); if (ret) { - pr_err("%d: Device id operation failed, interface %hhu device_id %hhu (%d)\n", - connection->intf_cport_id, intf_id, device_id, ret); + dev_err(&svc->dev, "failed to set device id %hhu for interface %hhu: %d\n", + device_id, intf_id, ret); goto ida_put; } @@ -452,15 +449,15 @@ static void svc_process_hotplug(struct work_struct *work) ret = gb_svc_route_create(svc, svc->ap_intf_id, GB_DEVICE_ID_AP, intf_id, device_id); if (ret) { - pr_err("%d: Route create operation failed, interface %hhu device_id %hhu (%d)\n", - connection->intf_cport_id, intf_id, device_id, ret); + dev_err(&svc->dev, "failed to create route to interface %hhu (device id %hhu): %d\n", + intf_id, device_id, ret); goto svc_id_free; } ret = gb_interface_init(intf, device_id); if (ret) { - pr_err("%d: Failed to initialize interface, interface %hhu device_id %hhu (%d)\n", - connection->intf_cport_id, intf_id, device_id, ret); + dev_err(&svc->dev, "failed to initialize interface %hhu (device id %hhu): %d\n", + intf_id, device_id, ret); goto destroy_route; } @@ -492,13 +489,14 @@ free_svc_hotplug: */ static int gb_svc_intf_hotplug_recv(struct gb_operation *op) { + struct gb_svc *svc = op->connection->private; struct gb_message *request = op->request; struct svc_hotplug *svc_hotplug; if (request->payload_size < sizeof(svc_hotplug->data)) { - pr_err("%d: short hotplug request received (%zu < %zu)\n", - op->connection->intf_cport_id, request->payload_size, - sizeof(svc_hotplug->data)); + dev_warn(&svc->dev, "short hotplug request received (%zu < %zu)\n", + request->payload_size, + sizeof(svc_hotplug->data)); return -EINVAL; } @@ -517,6 +515,7 @@ static int gb_svc_intf_hotplug_recv(struct gb_operation *op) static int gb_svc_intf_hot_unplug_recv(struct gb_operation *op) { + struct gb_svc *svc = op->connection->private; struct gb_message *request = op->request; struct gb_svc_intf_hot_unplug_request *hot_unplug = request->payload; struct gb_host_device *hd = op->connection->hd; @@ -524,9 +523,9 @@ static int gb_svc_intf_hot_unplug_recv(struct gb_operation *op) u8 intf_id; if (request->payload_size < sizeof(*hot_unplug)) { - pr_err("connection %d: short hot unplug request received (%zu < %zu)\n", - op->connection->intf_cport_id, request->payload_size, - sizeof(*hot_unplug)); + dev_warn(&svc->dev, "short hot unplug request received (%zu < %zu)\n", + request->payload_size, + sizeof(*hot_unplug)); return -EINVAL; } @@ -534,8 +533,8 @@ static int gb_svc_intf_hot_unplug_recv(struct gb_operation *op) intf = gb_interface_find(hd, intf_id); if (!intf) { - pr_err("connection %d: Couldn't find interface for id %hhu\n", - op->connection->intf_cport_id, intf_id); + dev_warn(&svc->dev, "could not find hot-unplug interface %hhu\n", + intf_id); return -EINVAL; } @@ -546,14 +545,14 @@ static int gb_svc_intf_hot_unplug_recv(struct gb_operation *op) static int gb_svc_intf_reset_recv(struct gb_operation *op) { + struct gb_svc *svc = op->connection->private; struct gb_message *request = op->request; struct gb_svc_intf_reset_request *reset; u8 intf_id; if (request->payload_size < sizeof(*reset)) { - pr_err("connection %d: short reset request received (%zu < %zu)\n", - op->connection->intf_cport_id, request->payload_size, - sizeof(*reset)); + dev_warn(&svc->dev, "short reset request received (%zu < %zu)\n", + request->payload_size, sizeof(*reset)); return -EINVAL; } reset = request->payload; @@ -597,8 +596,8 @@ static int gb_svc_request_recv(u8 type, struct gb_operation *op) } if (ret) { - pr_warn("connection %d: unexpected SVC request 0x%02x received (state %u)\n", - connection->intf_cport_id, type, svc->state); + dev_warn(&svc->dev, "unexpected request 0x%02x received (state %u)\n", + type, svc->state); return ret; } @@ -620,8 +619,7 @@ static int gb_svc_request_recv(u8 type, struct gb_operation *op) case GB_SVC_TYPE_INTF_RESET: return gb_svc_intf_reset_recv(op); default: - pr_err("connection %d: unsupported request: %hhu\n", - connection->intf_cport_id, type); + dev_warn(&svc->dev, "unsupported request 0x%02x\n", type); return -EINVAL; } } -- cgit v0.10.2 From dc3da5db2858c3fb33441988d1b6d56c06e53d7d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:59:20 +0100 Subject: greybus: loopback: remove endo reference Replace reference to "endo0" and generate the raw-latency filename based on the host-device bus id instead. Signed-off-by: Johan Hovold Reviewed-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index ededfef..ef16ca5 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -922,10 +922,11 @@ static int gb_loopback_connection_init(struct gb_connection *connection) return -ENOMEM; gb_loopback_reset_stats(&gb_dev); - /* If this is the first connection - create a module endo0 entry */ + /* If this is the first connection - create a per-bus entry */ mutex_lock(&gb_dev.mutex); if (!gb_dev.count) { - snprintf(name, sizeof(name), "raw_latency_endo0"); + snprintf(name, sizeof(name), "raw_latency_%d", + connection->bundle->intf->hd->bus_id); gb_dev.file = debugfs_create_file(name, S_IFREG | S_IRUGO, gb_dev.root, &gb_dev, &gb_loopback_debugfs_dev_latency_ops); -- cgit v0.10.2 From 0f37860de9a86d25f86ccc95631fa03fa766f31e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:59:21 +0100 Subject: greybus: kill the endo Remove the now unused endo and module code. Note that the never-implemented serial and version attributes of the endo can be implemented as svc attributes if needed. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 40e22ec..cc50482 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -2,8 +2,6 @@ greybus-y := core.o \ debugfs.o \ hd.o \ manifest.o \ - endo.o \ - module.o \ interface.o \ bundle.o \ connection.o \ diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index d1e26c4..9dcb1bf 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -78,23 +78,12 @@ static int greybus_module_match(struct device *dev, struct device_driver *drv) static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) { struct gb_host_device *hd = NULL; - struct gb_module *module = NULL; struct gb_interface *intf = NULL; struct gb_bundle *bundle = NULL; struct gb_svc *svc = NULL; - if (is_gb_endo(dev)) { - /* - * Not much to do for an endo, just fall through, as the - * "default" attributes are good enough for us. - */ - return 0; - } - if (is_gb_host_device(dev)) { hd = to_gb_host_device(dev); - } else if (is_gb_module(dev)) { - module = to_gb_module(dev); } else if (is_gb_interface(dev)) { intf = to_gb_interface(dev); } else if (is_gb_bundle(dev)) { @@ -214,12 +203,6 @@ static int __init gb_init(void) goto error_operation; } - retval = gb_endo_init(); - if (retval) { - pr_err("gb_endo_init failed (%d)\n", retval); - goto error_endo; - } - retval = gb_control_protocol_init(); if (retval) { pr_err("gb_control_protocol_init failed\n"); @@ -245,8 +228,6 @@ error_firmware: error_svc: gb_control_protocol_exit(); error_control: - gb_endo_exit(); -error_endo: gb_operation_exit(); error_operation: gb_hd_exit(); @@ -264,7 +245,6 @@ static void __exit gb_exit(void) gb_firmware_protocol_exit(); gb_svc_protocol_exit(); gb_control_protocol_exit(); - gb_endo_exit(); gb_operation_exit(); gb_hd_exit(); bus_unregister(&greybus_bus_type); diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c deleted file mode 100644 index cca2a83..0000000 --- a/drivers/staging/greybus/endo.c +++ /dev/null @@ -1,520 +0,0 @@ -/* - * Greybus endo code - * - * Copyright 2014-2015 Google Inc. - * Copyright 2014-2015 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#include "greybus.h" - -/* Endo ID (16 bits long) Masks */ -#define ENDO_ID_MASK 0xFFFF -#define ENDO_LARGE_MASK 0x1000 -#define ENDO_MEDIUM_MASK 0x0400 -#define ENDO_MINI_MASK 0x0100 - -#define ENDO_FRONT_MASK(id) ((id) >> 13) -#define ENDO_BACK_SIDE_RIBS_MASK(ribs) ((1 << (ribs)) - 1) - -/* - * endo_is_medium() should be used only if endo isn't large. And endo_is_mini() - * should be used only if endo isn't large or medium. - */ -#define endo_is_large(id) ((id) & ENDO_LARGE_MASK) -#define endo_is_medium(id) ((id) & ENDO_MEDIUM_MASK) -#define endo_is_mini(id) ((id) & ENDO_MINI_MASK) - -#define endo_back_left_ribs(id, ribs) (((id) >> (ribs)) & ENDO_BACK_SIDE_RIBS_MASK(ribs)) -#define endo_back_right_ribs(id, ribs) ((id) & ENDO_BACK_SIDE_RIBS_MASK(ribs)) - -/* - * An Endo has interface block positions on the front and back. - * Each has numeric ID, starting with 1 (interface 0 represents - * the SVC within the Endo itself). The maximum interface ID is the - * also the number of non-SVC interfaces possible on the endo. - * - * Total number of interfaces: - * - Front: 4 - * - Back left: max_ribs + 1 - * - Back right: max_ribs + 1 - */ -#define max_endo_interface_id(endo_layout) \ - (4 + ((endo_layout)->max_ribs + 1) * 2) - -static struct ida greybus_endo_id_map; - -/* endo sysfs attributes */ -static ssize_t serial_number_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gb_endo *endo = to_gb_endo(dev); - - return sprintf(buf, "%s\n", &endo->svc_info.serial_number[0]); -} -static DEVICE_ATTR_RO(serial_number); - -static ssize_t version_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gb_endo *endo = to_gb_endo(dev); - - return sprintf(buf, "%s\n", &endo->svc_info.version[0]); -} -static DEVICE_ATTR_RO(version); - -static struct attribute *svc_attrs[] = { - &dev_attr_serial_number.attr, - &dev_attr_version.attr, - NULL, -}; - -static const struct attribute_group svc_group = { - .attrs = svc_attrs, - .name = "svc", -}; - -static const struct attribute_group *endo_groups[] = { - &svc_group, - NULL, -}; - -static void gb_endo_release(struct device *dev) -{ - struct gb_endo *endo = to_gb_endo(dev); - - ida_simple_remove(&greybus_endo_id_map, endo->dev_id); - kfree(endo); -} - -struct device_type greybus_endo_type = { - .name = "greybus_endo", - .release = gb_endo_release, -}; - - -/* Validate Endo ID */ - -/* - * The maximum module height is 2 units. This means any adjacent pair of bits - * in the left or right mask must have at least one bit set. - */ -static inline bool modules_oversized(unsigned int count, unsigned int mask) -{ - int i; - - for (i = 0; i < count - 1; i++) - if (!(mask & (0x3 << i))) - return true; - - return false; -} - -/* Reverse a number of least significant bits in a value */ -static u8 reverse_bits(unsigned int value, unsigned int bits) -{ - u8 result = 0; - u8 result_mask = 1 << (bits - 1); - u8 value_mask = 1; - - while (value && result_mask) { - if (value & value_mask) { - result |= result_mask; - value ^= value_mask; - } - value_mask <<= 1; - result_mask >>= 1; - } - - return result; -} - -/* - * An Endo can have at most one instance of a single rib spanning its whole - * width. That is, the left and right bit masks representing the rib positions - * must have at most one bit set in both masks. - */ -static bool single_cross_rib(u8 left_ribs, u8 right_ribs) -{ - u8 span_ribs = left_ribs & right_ribs; - - /* Power of 2 ? */ - if (span_ribs & (span_ribs - 1)) - return false; - return true; -} - -/* - * Each Endo size has its own set of front module configurations. For most, the - * resulting rib mask is the same regardless of the Endo size. The mini Endo - * has a few differences though. - * - * Endo front has 4 interface blocks and 3 rib positions. A maximum of 2 ribs - * are allowed to be present for any endo type. - * - * This routine validates front mask and sets 'front_ribs', its 3 least - * significant bits represent front ribs mask, other are 0. The front values - * should be within range (1..6). - * - * front_ribs bitmask: - * - Bit 0: 1st rib location from top, i.e. between interface 1 and 2. - * - Bit 1: 2nd rib location from top, i.e. between interface 2 and 3. - * - Bit 2: 3rd rib location from top, i.e. between interface 3 and 4. - */ -static bool validate_front_ribs(struct gb_host_device *hd, - struct endo_layout *layout, bool mini, - u16 endo_id) -{ - u8 front_mask = ENDO_FRONT_MASK(endo_id); - - /* Verify front endo mask is in valid range, i.e. 1-6 */ - - switch (front_mask) { - case 1: - layout->front_ribs = 0x0; - break; - case 2: - layout->front_ribs = 0x1; - break; - case 3: - layout->front_ribs = 0x4; - break; - case 4: - layout->front_ribs = mini ? 0x2 : 0x3; - break; - case 5: - layout->front_ribs = mini ? 0x2 : 0x6; - break; - case 6: - layout->front_ribs = 0x5; - break; - default: - dev_err(&hd->dev, - "%s: Invalid endo front mask 0x%02x, id 0x%04x\n", - __func__, front_mask, endo_id); - return false; - } - - return true; -} - -/* - * The rear of an endo has a single vertical "spine", and the modules placed on - * the left and right of that spine are separated by ribs. Only one "cross" - * (i.e. rib that spans the entire width) is allowed of the back of the endo; - * all other ribs reach from the spine to the left or right edge. - * - * The width of the module positions on the left and right of the spine are - * determined by the width of the endo (either 1 or 2 "units"). The height of - * the modules is determined by the placement of the ribs (a module can be - * either 1 or 2 units high). - * - * The lower 13 bits of the 16-bit endo id are used to encode back ribs - * information. The large form factor endo uses all of these bits; the medium - * and mini form factors leave some bits unused (such bits shall be ignored, and - * are 0 for the purposes of this endo id definition). - * - * Each defined bit represents a rib position on one or the other side - * of the spine on the back of an endo. If that bit is set (1), it - * means a rib is present in the corresponding location; otherwise - * there is no rib there. - * - * Rotating an endo 180 degrees does not produce a new rib configuration. A - * single endo id represents a specific configuration of ribs without regard to - * its rotational orientation. We define one canonical id to represent a - * particular endo configuration. - */ -static bool validate_back_ribs(struct gb_host_device *hd, - struct endo_layout *layout, u16 endo_id) -{ - u8 max_ribs = layout->max_ribs; - u8 left_ribs; - u8 right_ribs; - - /* Extract the left and right rib masks */ - left_ribs = endo_back_left_ribs(endo_id, max_ribs); - right_ribs = endo_back_right_ribs(endo_id, max_ribs); - - if (!single_cross_rib(left_ribs, right_ribs)) { - dev_err(&hd->dev, - "%s: More than one spanning rib (left 0x%02x right 0x%02x), id 0x%04x\n", - __func__, left_ribs, right_ribs, endo_id); - return false; - } - - if (modules_oversized(max_ribs, left_ribs)) { - dev_err(&hd->dev, - "%s: Oversized module (left) 0x%02x, id 0x%04x\n", - __func__, left_ribs, endo_id); - return false; - } - - if (modules_oversized(max_ribs, right_ribs)) { - dev_err(&hd->dev, - "%s: Oversized module (Right) 0x%02x, id 0x%04x\n", - __func__, right_ribs, endo_id); - return false; - } - - /* - * The Endo numbering scheme represents the left and right rib - * configuration in a way that's convenient for looking for multiple - * spanning ribs. But it doesn't match the normal Endo interface - * numbering scheme (increasing counter-clockwise around the back). - * Reverse the right bit positions so they do match. - */ - right_ribs = reverse_bits(right_ribs, max_ribs); - - /* - * A mini or large Endo rotated 180 degrees is still the same Endo. In - * most cases that allows two distinct values to represent the same - * Endo; we choose one of them to be the canonical one (and the other is - * invalid). The canonical one is identified by higher value of left - * ribs mask. - * - * This doesn't apply to medium Endos, because the left and right sides - * are of different widths. - */ - if (max_ribs != ENDO_BACK_RIBS_MEDIUM && left_ribs < right_ribs) { - dev_err(&hd->dev, "%s: Non-canonical endo id 0x%04x\n", __func__, - endo_id); - return false; - } - - layout->left_ribs = left_ribs; - layout->right_ribs = right_ribs; - return true; -} - -/* - * Validate the endo-id passed from SVC. Error out if its not a valid Endo, - * else return structure representing ribs positions on front and back of Endo. - */ -static int gb_endo_validate_id(struct gb_host_device *hd, - struct endo_layout *layout, u16 endo_id) -{ - /* Validate Endo Size */ - if (endo_is_large(endo_id)) { - /* Large Endo type */ - layout->max_ribs = ENDO_BACK_RIBS_LARGE; - } else if (endo_is_medium(endo_id)) { - /* Medium Endo type */ - layout->max_ribs = ENDO_BACK_RIBS_MEDIUM; - } else if (endo_is_mini(endo_id)) { - /* Mini Endo type */ - layout->max_ribs = ENDO_BACK_RIBS_MINI; - } else { - dev_err(&hd->dev, "%s: Invalid endo type, id 0x%04x\n", - __func__, endo_id); - return -EINVAL; - } - - if (!validate_back_ribs(hd, layout, endo_id)) - return -EINVAL; - - if (!validate_front_ribs(hd, layout, - layout->max_ribs == ENDO_BACK_RIBS_MINI, - endo_id)) - return -EINVAL; - - return 0; -} - -/* - * Look up which module contains the given interface. - * - * A module's ID is the same as its lowest-numbered interface ID. So the module - * ID for a 1x1 module is always the same as its interface ID. - * - * For Endo Back: - * The module ID for an interface on a 1x2 or 2x2 module (which use two - * interface blocks) can be either the interface ID, or one less than the - * interface ID if there is no rib "above" the interface. - * - * For Endo Front: - * There are three rib locations in front and all of them might be unused, i.e. - * a single module is used for all 4 interfaces. We need to check all ribs in - * that case to find module ID. - */ -u8 endo_get_module_id(struct gb_endo *endo, u8 interface_id) -{ - struct endo_layout *layout = &endo->layout; - unsigned int height = layout->max_ribs + 1; - unsigned int iid = interface_id - 1; - unsigned int mask, rib_mask; - - if (!interface_id) - return 0; - - if (iid < height) { /* back left */ - mask = layout->left_ribs; - } else if (iid < 2 * height) { /* back right */ - mask = layout->right_ribs; - iid -= height; - } else { /* front */ - mask = layout->front_ribs; - iid -= 2 * height; - } - - /* - * Find the next rib *above* this interface to determine the lowest - * interface ID in the module. - */ - rib_mask = 1 << iid; - while ((rib_mask >>= 1) != 0 && !(mask & rib_mask)) - --interface_id; - - return interface_id; -} - -/* - * Creates all possible modules for the Endo. - * - * We try to create modules for all possible interface IDs. If a module is - * already created, we skip creating it again with the help of prev_module_id. - */ -static int create_modules(struct gb_endo *endo) -{ - struct gb_module *module; - int prev_module_id = 0; - int interface_id; - int module_id; - int max_id; - - max_id = max_endo_interface_id(&endo->layout); - - /* Find module corresponding to each interface */ - for (interface_id = 1; interface_id <= max_id; interface_id++) { - module_id = endo_get_module_id(endo, interface_id); - - if (WARN_ON(!module_id)) - continue; - - /* Skip already created modules */ - if (module_id == prev_module_id) - continue; - - prev_module_id = module_id; - - /* New module, create it */ - module = gb_module_create(&endo->dev, module_id); - if (!module) - return -EINVAL; - } - - return 0; -} - -static int gb_endo_register(struct gb_host_device *hd, - struct gb_endo *endo) -{ - int dev_id; - int retval; - - dev_id = ida_simple_get(&greybus_endo_id_map, 0, 0, GFP_KERNEL); - if (dev_id < 0) - return dev_id; - - endo->dev_id = dev_id; - - endo->dev.parent = &hd->dev; - endo->dev.bus = &greybus_bus_type; - endo->dev.type = &greybus_endo_type; - endo->dev.groups = endo_groups; - endo->dev.dma_mask = hd->dev.dma_mask; - device_initialize(&endo->dev); - dev_set_name(&endo->dev, "endo%hu", endo->dev_id); - - // FIXME - // Get the version and serial number from the SVC, right now we are - // using "fake" numbers. - strcpy(&endo->svc_info.serial_number[0], "042"); - strcpy(&endo->svc_info.version[0], "0.0"); - - retval = device_add(&endo->dev); - if (retval) { - dev_err(&hd->dev, "failed to add endo device of id 0x%04x\n", - endo->id); - put_device(&endo->dev); - } - - return retval; -} - -struct gb_endo *gb_endo_create(struct gb_host_device *hd, u16 endo_id, - u8 ap_intf_id) -{ - struct gb_endo *endo; - int retval; - - endo = kzalloc(sizeof(*endo), GFP_KERNEL); - if (!endo) - return ERR_PTR(-ENOMEM); - - /* First check if the value supplied is a valid endo id */ - if (gb_endo_validate_id(hd, &endo->layout, endo_id)) { - retval = -EINVAL; - goto free_endo; - } - if (ap_intf_id > max_endo_interface_id(&endo->layout)) { - retval = -EINVAL; - goto free_endo; - } - - /* Register Endo device */ - retval = gb_endo_register(hd, endo); - if (retval) - goto free_endo; - - /* Create modules/interfaces */ - retval = create_modules(endo); - if (retval) { - gb_endo_remove(endo); - return NULL; - } - - return endo; - -free_endo: - kfree(endo); - - return ERR_PTR(retval); -} - -void gb_endo_remove(struct gb_endo *endo) -{ - if (!endo) - return; - - /* remove all modules for this endo */ - gb_module_remove_all(endo); - - device_unregister(&endo->dev); -} - -int greybus_endo_setup(struct gb_host_device *hd, u16 endo_id, - u8 ap_intf_id) -{ - struct gb_endo *endo; - - endo = gb_endo_create(hd, endo_id, ap_intf_id); - if (IS_ERR(endo)) - return PTR_ERR(endo); - hd->endo = endo; - - return 0; -} -EXPORT_SYMBOL_GPL(greybus_endo_setup); - -int __init gb_endo_init(void) -{ - ida_init(&greybus_endo_id_map); - - return 0; -} - -void gb_endo_exit(void) -{ - ida_destroy(&greybus_endo_id_map); -} diff --git a/drivers/staging/greybus/endo.h b/drivers/staging/greybus/endo.h deleted file mode 100644 index 20a8649..0000000 --- a/drivers/staging/greybus/endo.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Greybus endo code - * - * Copyright 2015 Google Inc. - * Copyright 2015 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#ifndef __ENDO_H -#define __ENDO_H - -/* Greybus "public" definitions" */ -struct gb_svc_info { - u8 serial_number[10]; - u8 version[10]; -}; - -/* Max ribs per Endo size */ -#define ENDO_BACK_RIBS_MINI 0x4 -#define ENDO_BACK_RIBS_MEDIUM 0x5 -#define ENDO_BACK_RIBS_LARGE 0x6 - -/** - * struct endo_layout - represents front/back ribs of the endo. - * - * @front_ribs: Mask of present ribs in front. - * @left_ribs: Mask of present ribs in back (left). - * @right_ribs: Mask of present ribs in back (right). - * @max_ribs: Max ribs on endo back, possible values defined above. - */ -struct endo_layout { - u8 front_ribs; - u8 left_ribs; - u8 right_ribs; - u8 max_ribs; -}; - -struct gb_endo { - struct device dev; - struct endo_layout layout; - struct gb_svc_info svc_info; - u16 dev_id; - u16 id; - u8 ap_intf_id; -}; -#define to_gb_endo(d) container_of(d, struct gb_endo, dev) - -/* Greybus "private" definitions */ -struct gb_host_device; - -int gb_endo_init(void); -void gb_endo_exit(void); - -struct gb_endo *gb_endo_create(struct gb_host_device *hd, - u16 endo_id, u8 ap_intf_id); -void gb_endo_remove(struct gb_endo *endo); -int greybus_endo_setup(struct gb_host_device *hd, u16 endo_id, - u8 ap_intf_id); - -u8 endo_get_module_id(struct gb_endo *endo, u8 interface_id); - -#endif /* __ENDO_H */ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index fa81733..405e565 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -26,10 +26,8 @@ #include "greybus_protocols.h" #include "manifest.h" #include "hd.h" -#include "endo.h" #include "svc.h" #include "firmware.h" -#include "module.h" #include "control.h" #include "interface.h" #include "bundle.h" @@ -105,8 +103,6 @@ struct dentry *gb_debugfs_get(void); extern struct bus_type greybus_bus_type; extern struct device_type greybus_hd_type; -extern struct device_type greybus_endo_type; -extern struct device_type greybus_module_type; extern struct device_type greybus_interface_type; extern struct device_type greybus_bundle_type; extern struct device_type greybus_svc_type; @@ -116,16 +112,6 @@ static inline int is_gb_host_device(const struct device *dev) return dev->type == &greybus_hd_type; } -static inline int is_gb_endo(const struct device *dev) -{ - return dev->type == &greybus_endo_type; -} - -static inline int is_gb_module(const struct device *dev) -{ - return dev->type == &greybus_module_type; -} - static inline int is_gb_interface(const struct device *dev) { return dev->type == &greybus_interface_type; diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index 2ee5d4f..b280925 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -130,13 +130,7 @@ EXPORT_SYMBOL_GPL(gb_hd_add); void gb_hd_del(struct gb_host_device *hd) { - /* - * Tear down all interfaces, modules, and the endo that is associated - * with this host controller before freeing the memory associated with - * the host controller. - */ gb_interfaces_remove(hd); - gb_endo_remove(hd->endo); gb_connection_destroy(hd->svc_connection); diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h index 72716e0..5612b48 100644 --- a/drivers/staging/greybus/hd.h +++ b/drivers/staging/greybus/hd.h @@ -40,7 +40,6 @@ struct gb_host_device { /* Host device buffer constraints */ size_t buffer_size_max; - struct gb_endo *endo; struct gb_svc *svc; struct gb_connection *svc_connection; diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c deleted file mode 100644 index e3d7a66..0000000 --- a/drivers/staging/greybus/module.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Greybus module code - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#include "greybus.h" - - -/* module sysfs attributes */ -static ssize_t epm_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - // FIXME - // Implement something here when we have a working control protocol - return sprintf(buf, "1\n"); -} - -static ssize_t epm_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t size) -{ - // FIXME - // Implement something here when we have a working control protocol - return 0; -} -static DEVICE_ATTR_RW(epm); - -static ssize_t power_control_show(struct device *dev, - struct device_attribute *addr, char *buf) -{ - // FIXME - // Implement something here when we have a working control protocol - return sprintf(buf, "1\n"); -} - -static ssize_t power_control_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - // FIXME - // Implement something here when we have a working control protocol - return 0; -} -static DEVICE_ATTR_RW(power_control); - -static ssize_t present_show(struct device *dev, - struct device_attribute *addr, char *buf) -{ - // FIXME - // Implement something here when we have a working control protocol - return sprintf(buf, "1\n"); -} - -static ssize_t present_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t size) -{ - // FIXME - // Implement something here when we have a working control protocol - return 0; -} -static DEVICE_ATTR_RW(present); - -static struct attribute *module_attrs[] = { - &dev_attr_epm.attr, - &dev_attr_power_control.attr, - &dev_attr_present.attr, - NULL, -}; -ATTRIBUTE_GROUPS(module); - -static void gb_module_release(struct device *dev) -{ - struct gb_module *module = to_gb_module(dev); - - kfree(module); -} - -struct device_type greybus_module_type = { - .name = "greybus_module", - .release = gb_module_release, -}; - -struct module_find { - struct gb_endo *endo; - u8 module_id; -}; - -static int module_find(struct device *dev, void *data) -{ - struct gb_module *module; - struct module_find *find = data; - - if (!is_gb_module(dev)) - return 0; - - module = to_gb_module(dev); - if ((module->module_id == find->module_id) && - (module->dev.parent == &find->endo->dev)) - return 1; - - return 0; -} - -/* - * Search the list of modules in the system. If one is found, return it, with - * the reference count incremented. - */ -struct gb_module *gb_module_find(struct gb_host_device *hd, u8 module_id) -{ - struct device *dev; - struct gb_module *module = NULL; - struct module_find find; - - if (!module_id) - return NULL; - - find.module_id = module_id; - find.endo = hd->endo; - - dev = bus_find_device(&greybus_bus_type, NULL, - &find, module_find); - if (dev) - module = to_gb_module(dev); - - return module; -} - -struct gb_module *gb_module_create(struct device *parent, u8 module_id) -{ - struct gb_module *module; - int retval; - - module = kzalloc(sizeof(*module), GFP_KERNEL); - if (!module) - return NULL; - - module->module_id = module_id; - module->dev.parent = parent; - module->dev.bus = &greybus_bus_type; - module->dev.type = &greybus_module_type; - module->dev.groups = module_groups; - module->dev.dma_mask = parent->dma_mask; - device_initialize(&module->dev); - dev_set_name(&module->dev, "%s:%hhu", dev_name(parent), module_id); - - retval = device_add(&module->dev); - if (retval) { - pr_err("failed to add module device for id 0x%02hhx\n", - module_id); - put_device(&module->dev); - return NULL; - } - - return module; -} - -static int module_remove(struct device *dev, void *data) -{ - struct gb_module *module; - struct gb_endo *endo = data; - - if (!is_gb_module(dev)) - return 0; - - module = to_gb_module(dev); - if (module->dev.parent == &endo->dev) - device_unregister(&module->dev); - - return 0; -} - -void gb_module_remove_all(struct gb_endo *endo) -{ - bus_for_each_dev(&greybus_bus_type, NULL, endo, module_remove); -} diff --git a/drivers/staging/greybus/module.h b/drivers/staging/greybus/module.h deleted file mode 100644 index 2b36fe9..0000000 --- a/drivers/staging/greybus/module.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Greybus module code - * - * Copyright 2014 Google Inc. - * - * Released under the GPLv2 only. - */ - -#ifndef __MODULE_H -#define __MODULE_H - -/* Greybus "public" definitions" */ -struct gb_module { - struct device dev; - u8 module_id; /* Physical location within the Endo */ -}; -#define to_gb_module(d) container_of(d, struct gb_module, dev) - -struct gb_host_device; - -/* Greybus "private" definitions */ -struct gb_module *gb_module_find(struct gb_host_device *hd, u8 module_id); -struct gb_module *gb_module_create(struct device *parent, u8 module_id); -void gb_module_remove_all(struct gb_endo *endo); - -#endif /* __MODULE_H */ diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 62b67cc..42cc7e9 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -310,14 +310,9 @@ static int gb_svc_hello(struct gb_operation *op) { struct gb_connection *connection = op->connection; struct gb_svc *svc = connection->private; - struct gb_host_device *hd = connection->hd; struct gb_svc_hello_request *hello_request; int ret; - /* - * SVC sends information about the endo and interface-id on the hello - * request, use that to create an endo. - */ if (op->request->payload_size < sizeof(*hello_request)) { dev_warn(&svc->dev, "short hello request (%zu < %zu)\n", op->request->payload_size, @@ -335,11 +330,6 @@ static int gb_svc_hello(struct gb_operation *op) return ret; } - /* Setup Endo */ - ret = greybus_endo_setup(hd, svc->endo_id, svc->ap_intf_id); - if (ret) - return ret; - return 0; } -- cgit v0.10.2 From 35822c04a5c232a7899d43a74f0d2fca5077b196 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:59:22 +0100 Subject: greybus: connection: handle bundle-less connections in svc helpers The svc connection helper functions should not assume that all dynamic connections will have a bundle. This is needed as the control bundle is going away. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 7beab74..7dde8a11 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -294,7 +294,7 @@ gb_connection_svc_connection_create(struct gb_connection *connection) if (gb_connection_is_static(connection)) return 0; - intf = connection->bundle->intf; + intf = connection->intf; ret = gb_svc_connection_create(hd->svc, hd->svc->ap_intf_id, connection->hd_cport_id, @@ -320,7 +320,7 @@ gb_connection_svc_connection_destroy(struct gb_connection *connection) gb_svc_connection_destroy(connection->hd->svc, connection->hd->svc->ap_intf_id, connection->hd_cport_id, - connection->bundle->intf->interface_id, + connection->intf->interface_id, connection->intf_cport_id); } -- cgit v0.10.2 From 7fa530ad1b2d160ec9e76b3b5a1ac2e302e8f3bf Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:59:23 +0100 Subject: greybus: control: do not assume a control bundle The control bundle is going away so update the code. Also remove defensive WARN_ON which would not just warn if our implementation is broken, but also leak further memory unnecessarily. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index ffc07a4..2cc1917 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -22,9 +22,8 @@ int gb_control_get_manifest_size_operation(struct gb_interface *intf) ret = gb_operation_sync(connection, GB_CONTROL_TYPE_GET_MANIFEST_SIZE, NULL, 0, &response, sizeof(response)); if (ret) { - dev_err(&connection->bundle->dev, - "%s: Manifest size get operation failed (%d)\n", - __func__, ret); + dev_err(&connection->intf->dev, + "failed to get manifest size: %d\n", ret); return ret; } @@ -72,7 +71,7 @@ static int gb_control_connection_init(struct gb_connection *connection) connection->private = control; /* Set interface's control connection */ - connection->bundle->intf->control = control; + connection->intf->control = control; return 0; } @@ -81,10 +80,7 @@ static void gb_control_connection_exit(struct gb_connection *connection) { struct gb_control *control = connection->private; - if (WARN_ON(connection->bundle->intf->control != control)) - return; - - connection->bundle->intf->control = NULL; + connection->intf->control = NULL; kfree(control); } -- cgit v0.10.2 From e1442f6910da337a879e44f32909844986714a4b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:59:24 +0100 Subject: greybus: connection: unconditionally enable connections Remove conditional enabling of connections when binding protocols that served no purpose as a connection either has no bundle or it has an interface with a valid device id. Also remove the now unused GB_PROTOCOL_NO_BUNDLE protocol flag. This is an intermediate step in moving the protocol binding to connection_init, but is also needed as the control bundle is going away. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 7dde8a11..2b07846 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -541,19 +541,11 @@ int gb_connection_bind_protocol(struct gb_connection *connection) } connection->protocol = protocol; - /* - * If we have a valid device_id for the interface block, then we have an - * active device, so bring up the connection at the same time. - */ - if ((!connection->bundle && - protocol->flags & GB_PROTOCOL_NO_BUNDLE) || - connection->bundle->intf->device_id != GB_DEVICE_ID_BAD) { - ret = gb_connection_init(connection); - if (ret) { - gb_protocol_put(protocol); - connection->protocol = NULL; - return ret; - } + ret = gb_connection_init(connection); + if (ret) { + gb_protocol_put(protocol); + connection->protocol = NULL; + return ret; } return 0; diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index 384ddf8..f24281b 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -16,7 +16,6 @@ struct gb_operation; /* Possible flags for protocol drivers */ #define GB_PROTOCOL_SKIP_CONTROL_CONNECTED BIT(0) /* Don't sent connected requests */ #define GB_PROTOCOL_SKIP_CONTROL_DISCONNECTED BIT(1) /* Don't sent disconnected requests */ -#define GB_PROTOCOL_NO_BUNDLE BIT(2) /* Protocol May have a bundle-less connection */ #define GB_PROTOCOL_SKIP_VERSION BIT(3) /* Don't send get_version() requests */ typedef int (*gb_connection_init_t)(struct gb_connection *); diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 42cc7e9..f9ca08b3 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -678,7 +678,6 @@ static struct gb_protocol svc_protocol = { .request_recv = gb_svc_request_recv, .flags = GB_PROTOCOL_SKIP_CONTROL_CONNECTED | GB_PROTOCOL_SKIP_CONTROL_DISCONNECTED | - GB_PROTOCOL_NO_BUNDLE | GB_PROTOCOL_SKIP_VERSION, }; gb_builtin_protocol_driver(svc_protocol); -- cgit v0.10.2 From f2152eb33dec35703176e792da2769e88e5a81d3 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:59:25 +0100 Subject: greybus: manifest: refactor cport-descriptor release Add helper function to release cport-descriptors with a given bundle id. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 9252bf4..4fdb98d 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -60,6 +60,22 @@ static void release_manifest_descriptors(struct gb_interface *intf) release_manifest_descriptor(descriptor); } +static void release_cport_descriptors(struct list_head *head, u8 bundle_id) +{ + struct manifest_desc *desc, *tmp; + struct greybus_descriptor_cport *desc_cport; + + list_for_each_entry_safe(desc, tmp, head, links) { + desc_cport = desc->data; + + if (desc->type != GREYBUS_TYPE_CPORT) + continue; + + if (desc_cport->bundle == bundle_id) + release_manifest_descriptor(desc); + } +} + static struct manifest_desc *get_next_bundle_desc(struct gb_interface *intf) { struct manifest_desc *descriptor; @@ -275,14 +291,7 @@ exit: * Free all cports for this bundle to avoid 'excess descriptors' * warnings. */ - list_for_each_entry_safe(desc, next, &intf->manifest_descs, links) { - struct greybus_descriptor_cport *desc_cport = desc->data; - - if (desc->type != GREYBUS_TYPE_CPORT) - continue; - if (desc_cport->bundle == bundle_id) - release_manifest_descriptor(desc); - } + release_cport_descriptors(&intf->manifest_descs, bundle_id); return 0; /* Error; count should also be 0 */ } -- cgit v0.10.2 From 47091af91e7e872748a17158f1e99833962428b4 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:59:26 +0100 Subject: greybus: interface: drop the control bundle Drop the control bundle and ignore control descriptors when parsing manifests. Every interface has a control connection with a well defined remote CPort 0 and there's no longer any need to create a bundle for it. As the control connection is setup and enabled before parsing the manifest, ignore any legacy descriptors for control cports and bundles in a manifest. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 2415187..9ff7464 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -70,34 +70,6 @@ struct device_type greybus_interface_type = { }; /* - * Create kernel structures corresponding to a bundle and connection for - * managing control CPort. - */ -static int -gb_interface_create_control_bundle_connection(struct gb_interface *intf) -{ - struct gb_bundle *bundle; - struct gb_connection *connection; - - bundle = gb_bundle_create(intf, GB_CONTROL_BUNDLE_ID, - GREYBUS_CLASS_CONTROL); - if (!bundle) { - dev_err(&intf->dev, "failed to create control bundle\n"); - return -ENOMEM; - } - - connection = gb_connection_create_dynamic(intf, bundle, - GB_CONTROL_CPORT_ID, - GREYBUS_PROTOCOL_CONTROL); - if (!connection) { - dev_err(&intf->dev, "failed to create control connection\n"); - return -ENOMEM; - } - - return 0; -} - -/* * A Greybus module represents a user-replaceable component on an Ara * phone. An interface is the physical connection on that module. A * module may have more than one interface. @@ -170,6 +142,9 @@ void gb_interface_remove(struct gb_interface *intf) list_for_each_entry_safe(bundle, next, &intf->bundles, links) gb_bundle_destroy(bundle); + if (intf->control) + gb_connection_destroy(intf->control->connection); + device_unregister(&intf->dev); } @@ -190,15 +165,20 @@ void gb_interfaces_remove(struct gb_host_device *hd) */ int gb_interface_init(struct gb_interface *intf, u8 device_id) { + struct gb_connection *connection; int ret, size; void *manifest; intf->device_id = device_id; /* Establish control CPort connection */ - ret = gb_interface_create_control_bundle_connection(intf); - if (ret) - return ret; + connection = gb_connection_create_dynamic(intf, NULL, + GB_CONTROL_CPORT_ID, + GREYBUS_PROTOCOL_CONTROL); + if (!connection) { + dev_err(&intf->dev, "failed to create control connection\n"); + return -ENOMEM; + } /* Get manifest size using control protocol on CPort */ size = gb_control_get_manifest_size_operation(intf); diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 4fdb98d..ea5ff86 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -254,24 +254,10 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) /* Found one. Set up its function structure */ protocol_id = desc_cport->protocol_id; - /* Validate declarations of the control protocol CPort */ - if (cport_id == GB_CONTROL_CPORT_ID) { - /* This should have protocol set to control protocol*/ - if (protocol_id != GREYBUS_PROTOCOL_CONTROL) - goto print_error_exit; - /* Don't recreate connection for control cport */ - goto release_descriptor; - } - /* Nothing else should have its protocol as control protocol */ - if (protocol_id == GREYBUS_PROTOCOL_CONTROL) { - goto print_error_exit; - } - if (!gb_connection_create_dynamic(intf, bundle, cport_id, protocol_id)) goto exit; -release_descriptor: count++; /* Release the cport descriptor */ @@ -279,12 +265,6 @@ release_descriptor: } return count; -print_error_exit: - /* A control protocol parse error was encountered */ - dev_err(&bundle->dev, - "cport_id, protocol_id 0x%04hx,0x%04hx want 0x%04hx,0x%04hx\n", - cport_id, protocol_id, GB_CONTROL_CPORT_ID, - GREYBUS_PROTOCOL_CONTROL); exit: /* @@ -308,6 +288,7 @@ static u32 gb_manifest_parse_bundles(struct gb_interface *intf) struct gb_bundle *bundle_next; u32 count = 0; u8 bundle_id; + u8 class; while ((desc = get_next_bundle_desc(intf))) { struct greybus_descriptor_bundle *desc_bundle; @@ -315,37 +296,32 @@ static u32 gb_manifest_parse_bundles(struct gb_interface *intf) /* Found one. Set up its bundle structure*/ desc_bundle = desc->data; bundle_id = desc_bundle->id; + class = desc_bundle->class; + + /* Done with this bundle descriptor */ + release_manifest_descriptor(desc); - /* Don't recreate bundle for control cport */ + /* Ignore any legacy control bundles */ if (bundle_id == GB_CONTROL_BUNDLE_ID) { - /* This should have class set to control class */ - if (desc_bundle->class != GREYBUS_CLASS_CONTROL) { - dev_err(&intf->dev, - "bad class 0x%02x for control bundle\n", - desc_bundle->class); - goto cleanup; - } - - bundle = intf->control->connection->bundle; - goto parse_cports; + dev_dbg(&intf->dev, "%s - ignoring control bundle\n", + __func__); + release_cport_descriptors(&intf->manifest_descs, + bundle_id); + continue; } /* Nothing else should have its class set to control class */ - if (desc_bundle->class == GREYBUS_CLASS_CONTROL) { + if (class == GREYBUS_CLASS_CONTROL) { dev_err(&intf->dev, "bundle 0x%02x cannot use control class\n", bundle_id); goto cleanup; } - bundle = gb_bundle_create(intf, bundle_id, desc_bundle->class); + bundle = gb_bundle_create(intf, bundle_id, class); if (!bundle) goto cleanup; -parse_cports: - /* Done with this bundle descriptor */ - release_manifest_descriptor(desc); - /* * Now go set up this bundle's functions and cports. * @@ -362,15 +338,8 @@ parse_cports: * separate entities and don't reject entire interface and its * bundles on failing to initialize a cport. But make sure the * bundle which needs the cport, gets destroyed properly. - * - * The control bundle and its connections are special. The - * entire manifest should be rejected if we failed to initialize - * the control bundle/connections. */ if (!gb_manifest_parse_cports(bundle)) { - if (bundle_id == GB_CONTROL_BUNDLE_ID) - goto cleanup; - gb_bundle_destroy(bundle); continue; } -- cgit v0.10.2 From 32945d6ecc89331f10d715496fd2247f958d471e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 25 Nov 2015 15:06:41 +0100 Subject: greybus: Documentation/sysfs: rename interface and bundle attributes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update the example sysfs-tree layout under Documentation due renamed interface and bundle attributes. The interface and bundle "id" attributes have been renamed "interface_id" and "bundle_id" respectively to make them self describing. For consistency reasons the bundle class attribute is renamed as "bundle_class". . ├── greybus1 │   ├── 1-2 │   │   ├── 1-2.1 │   │   │   ├── bundle_class │   │   │   ├── bundle_id │   │   │   └── state │   │   ├── 1-2.2 │   │   │   ├── bundle_class │   │   │   ├── bundle_id │   │   │   └── state │   │   ├── interface_id │   │   ├── product_id │   │   ├── unique_id │   │   └── vendor_id │   ├── 1-4 │   │   ├── 1-4.2 │   │   │   ├── bundle_class │   │   │   ├── bundle_id │   │   │   ├── gpbridge0 │   │   │   │   ├── gpio │   │   │   │   │   └── gpiochip490 │   │   │   │   └── i2c-4 │   │   │   └── state │   │   ├── interface_id │   │   ├── product_id │   │   ├── unique_id │   │   └── vendor_id │   └── 1-svc │   ├── ap_intf_id │   ├── eject │   ├── endo_id │   └── unique_id └── greybus2 ├── 2-3 │   ├── 2-3.1 │   │   ├── bundle_class │   │   ├── bundle_id │   │   └── state │   ├── interface_id │   ├── product_id │   ├── unique_id │   └── vendor_id └── 2-svc ├── ap_intf_id ├── eject ├── endo_id └── unique_id Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.1/bundle_class b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.1/bundle_class new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.1/bundle_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.1/bundle_id new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.1/bundle_id @@ -0,0 +1 @@ +1 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.1/class b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.1/class deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.1/id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.1/id deleted file mode 100644 index d00491f..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.1/id +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/bundle_class b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/bundle_class new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/bundle_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/bundle_id new file mode 100644 index 0000000..0cfbf08 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/bundle_id @@ -0,0 +1 @@ +2 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/class b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/class deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/id deleted file mode 100644 index 0cfbf08..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/id +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/id deleted file mode 100644 index 0cfbf08..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/id +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/interface_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/interface_id new file mode 100644 index 0000000..0cfbf08 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/interface_id @@ -0,0 +1 @@ +2 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/bundle_class b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/bundle_class new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/bundle_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/bundle_id new file mode 100644 index 0000000..0cfbf08 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/bundle_id @@ -0,0 +1 @@ +2 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/class b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/class deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/id deleted file mode 100644 index 0cfbf08..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/id +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/id deleted file mode 100644 index b8626c4..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/id +++ /dev/null @@ -1 +0,0 @@ -4 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/interface_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/interface_id new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/interface_id @@ -0,0 +1 @@ +4 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.1/bundle_class b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.1/bundle_class new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.1/bundle_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.1/bundle_id new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.1/bundle_id @@ -0,0 +1 @@ +1 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.1/class b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.1/class deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.1/id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.1/id deleted file mode 100644 index d00491f..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.1/id +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/id deleted file mode 100644 index 00750ed..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/id +++ /dev/null @@ -1 +0,0 @@ -3 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/interface_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/interface_id new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/interface_id @@ -0,0 +1 @@ +3 -- cgit v0.10.2 From f1e941a6e4b71a5b94d584277121bd2bee8809b0 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 26 Nov 2015 15:33:46 +0530 Subject: greybus: firmware: Fetch es2 VID/PID to distinguish module vendors The es2 chip doesn't have VID/PID programmed into the hardware and we need to hack that up to distinguish different modules and their firmware packages. This fetches VID/PID (over firmware protocol) for es2 chip only, when VID/PID already sent during hotplug are 0. Since only the bootrom contains a firmware protocol cport, this only affects bootrom's working and not nuttx. Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/firmware.c b/drivers/staging/greybus/firmware.c index e41526b..cd2184c 100644 --- a/drivers/staging/greybus/firmware.c +++ b/drivers/staging/greybus/firmware.c @@ -11,9 +11,14 @@ #include "greybus.h" +#define ES2_UNIPRO_MFG_ID 0x00000126 +#define ES2_UNIPRO_PROD_ID 0x00001000 + struct gb_firmware { struct gb_connection *connection; const struct firmware *fw; + u32 vendor_id; + u32 product_id; }; static void free_firmware(struct gb_firmware *firmware) @@ -22,6 +27,45 @@ static void free_firmware(struct gb_firmware *firmware) firmware->fw = NULL; } +/* + * The es2 chip doesn't have VID/PID programmed into the hardware and we need to + * hack that up to distinguish different modules and their firmware blobs. + * + * This fetches VID/PID (over firmware protocol) for es2 chip only, when VID/PID + * already sent during hotplug are 0. + * + * Otherwise, we keep firmware->vendor_id/product_id same as what's passed + * during hotplug. + */ +static void firmware_es2_fixup_vid_pid(struct gb_firmware *firmware) +{ + struct gb_firmware_get_vid_pid_response response; + struct gb_connection *connection = firmware->connection; + struct gb_interface *intf = connection->bundle->intf; + int ret; + + /* + * Use VID/PID specified at hotplug if: + * - Bridge ASIC chip isn't ES2 + * - Received non-zero Vendor/Product ids + */ + if (intf->unipro_mfg_id != ES2_UNIPRO_MFG_ID || + intf->unipro_prod_id != ES2_UNIPRO_PROD_ID || + intf->vendor_id != 0 || intf->product_id != 0) + return; + + ret = gb_operation_sync(connection, GB_FIRMWARE_TYPE_GET_VID_PID, + NULL, 0, &response, sizeof(response)); + if (ret) { + dev_err(&connection->bundle->dev, + "Firmware get vid/pid operation failed (%d)\n", ret); + return; + } + + firmware->vendor_id = le32_to_cpu(response.vendor_id); + firmware->product_id = le32_to_cpu(response.product_id); +} + /* This returns path of the firmware blob on the disk */ static int download_firmware(struct gb_firmware *firmware, u8 stage) { @@ -41,7 +85,7 @@ static int download_firmware(struct gb_firmware *firmware, u8 stage) snprintf(firmware_name, sizeof(firmware_name), "ara:%08x:%08x:%08x:%08x:%02x.tftf", intf->unipro_mfg_id, intf->unipro_prod_id, - intf->vendor_id, intf->product_id, stage); + firmware->vendor_id, firmware->product_id, stage); return request_firmware(&firmware->fw, firmware_name, &connection->bundle->dev); @@ -183,6 +227,11 @@ static int gb_firmware_connection_init(struct gb_connection *connection) firmware->connection = connection; connection->private = firmware; + firmware->vendor_id = connection->intf->vendor_id; + firmware->product_id = connection->intf->product_id; + + firmware_es2_fixup_vid_pid(firmware); + /* * Module's Bootrom needs a way to know (currently), when to start * sending requests to the AP. The version request is sent before this diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 9fcbbe4..00593b0 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -158,6 +158,7 @@ struct gb_control_disconnected_request { #define GB_FIRMWARE_TYPE_GET_FIRMWARE 0x03 #define GB_FIRMWARE_TYPE_READY_TO_BOOT 0x04 #define GB_FIRMWARE_TYPE_AP_READY 0x05 /* Request with no-payload */ +#define GB_FIRMWARE_TYPE_GET_VID_PID 0x06 /* Request with no-payload */ /* Greybus firmware boot stages */ #define GB_FIRMWARE_BOOT_STAGE_ONE 0x01 /* Reserved for the boot ROM */ @@ -197,6 +198,12 @@ struct gb_firmware_ready_to_boot_request { } __packed; /* Firmware protocol Ready to boot response has no payload */ +/* Firmware protocol get VID/PID request has no payload */ +struct gb_firmware_get_vid_pid_response { + __le32 vendor_id; + __le32 product_id; +} __packed; + /* Power Supply */ -- cgit v0.10.2 From d34a3643fe8d20b4e19779f82dfb29b5e6678a9d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 2 Dec 2015 18:23:26 +0100 Subject: greybus: svc: clean up hotplug/unplug request handlers Clean up hotplug/unplug request handlers somewhat. Also add a debug message to both handlers that includes the interface id. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index f9ca08b3..2c2dd8e 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -480,22 +480,25 @@ free_svc_hotplug: static int gb_svc_intf_hotplug_recv(struct gb_operation *op) { struct gb_svc *svc = op->connection->private; - struct gb_message *request = op->request; + struct gb_svc_intf_hotplug_request *request; struct svc_hotplug *svc_hotplug; - if (request->payload_size < sizeof(svc_hotplug->data)) { + if (op->request->payload_size < sizeof(*request)) { dev_warn(&svc->dev, "short hotplug request received (%zu < %zu)\n", - request->payload_size, - sizeof(svc_hotplug->data)); + op->request->payload_size, sizeof(*request)); return -EINVAL; } + request = op->request->payload; + + dev_dbg(&svc->dev, "%s - id = %u\n", __func__, request->intf_id); + svc_hotplug = kmalloc(sizeof(*svc_hotplug), GFP_KERNEL); if (!svc_hotplug) return -ENOMEM; svc_hotplug->connection = op->connection; - memcpy(&svc_hotplug->data, op->request->payload, sizeof(svc_hotplug->data)); + memcpy(&svc_hotplug->data, request, sizeof(svc_hotplug->data)); INIT_WORK(&svc_hotplug->work, svc_process_hotplug); queue_work(system_unbound_wq, &svc_hotplug->work); @@ -506,20 +509,21 @@ static int gb_svc_intf_hotplug_recv(struct gb_operation *op) static int gb_svc_intf_hot_unplug_recv(struct gb_operation *op) { struct gb_svc *svc = op->connection->private; - struct gb_message *request = op->request; - struct gb_svc_intf_hot_unplug_request *hot_unplug = request->payload; + struct gb_svc_intf_hot_unplug_request *request; struct gb_host_device *hd = op->connection->hd; struct gb_interface *intf; u8 intf_id; - if (request->payload_size < sizeof(*hot_unplug)) { + if (op->request->payload_size < sizeof(*request)) { dev_warn(&svc->dev, "short hot unplug request received (%zu < %zu)\n", - request->payload_size, - sizeof(*hot_unplug)); + op->request->payload_size, sizeof(*request)); return -EINVAL; } - intf_id = hot_unplug->intf_id; + request = op->request->payload; + intf_id = request->intf_id; + + dev_dbg(&svc->dev, "%s - id = %u\n", __func__, intf_id); intf = gb_interface_find(hd, intf_id); if (!intf) { -- cgit v0.10.2 From 24456a09a830dc44ace4d0db8e29d1e367937b58 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 2 Dec 2015 18:23:27 +0100 Subject: greybus: svc: clean up deferred hotplug handler Rename the hotplug request message, and clarify that the message size has already been verified by the primary handler. Also add a debug message that includes the interface id. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 2c2dd8e..476914c 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -359,7 +359,7 @@ static void svc_process_hotplug(struct work_struct *work) { struct svc_hotplug *svc_hotplug = container_of(work, struct svc_hotplug, work); - struct gb_svc_intf_hotplug_request *hotplug = &svc_hotplug->data; + struct gb_svc_intf_hotplug_request *request; struct gb_connection *connection = svc_hotplug->connection; struct gb_svc *svc = connection->private; struct gb_host_device *hd = connection->hd; @@ -367,10 +367,11 @@ static void svc_process_hotplug(struct work_struct *work) u8 intf_id, device_id; int ret; - /* - * Grab the information we need. - */ - intf_id = hotplug->intf_id; + /* The request message size has already been verified. */ + request = &svc_hotplug->data; + intf_id = request->intf_id; + + dev_dbg(&svc->dev, "%s - id = %u\n", __func__, intf_id); intf = gb_interface_find(hd, intf_id); if (intf) { @@ -404,10 +405,10 @@ static void svc_process_hotplug(struct work_struct *work) if (ret) goto destroy_interface; - intf->unipro_mfg_id = le32_to_cpu(hotplug->data.unipro_mfg_id); - intf->unipro_prod_id = le32_to_cpu(hotplug->data.unipro_prod_id); - intf->vendor_id = le32_to_cpu(hotplug->data.ara_vend_id); - intf->product_id = le32_to_cpu(hotplug->data.ara_prod_id); + intf->unipro_mfg_id = le32_to_cpu(request->data.unipro_mfg_id); + intf->unipro_prod_id = le32_to_cpu(request->data.unipro_prod_id); + intf->vendor_id = le32_to_cpu(request->data.ara_vend_id); + intf->product_id = le32_to_cpu(request->data.ara_prod_id); /* * Create a device id for the interface: -- cgit v0.10.2 From b4ee82ece86d21c73213abae77e32abe40136eb4 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 2 Dec 2015 18:23:28 +0100 Subject: greybus: svc: clean up interface-remove helper Pass the svc rather than its connection to the interface remove helper. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 476914c..d974b36 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -333,10 +333,8 @@ static int gb_svc_hello(struct gb_operation *op) return 0; } -static void svc_intf_remove(struct gb_connection *connection, - struct gb_interface *intf) +static void gb_svc_intf_remove(struct gb_svc *svc, struct gb_interface *intf) { - struct gb_svc *svc = connection->private; u8 intf_id = intf->interface_id; u8 device_id; @@ -391,7 +389,7 @@ static void svc_process_hotplug(struct work_struct *work) */ dev_info(&svc->dev, "removing interface %hhu to add it again\n", intf_id); - svc_intf_remove(connection, intf); + gb_svc_intf_remove(svc, intf); } intf = gb_interface_create(hd, intf_id); @@ -533,7 +531,7 @@ static int gb_svc_intf_hot_unplug_recv(struct gb_operation *op) return -EINVAL; } - svc_intf_remove(op->connection, intf); + gb_svc_intf_remove(svc, intf); return 0; } -- cgit v0.10.2 From 9ae4109e5db02d4fae37bbd1399a8157efb583c4 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 2 Dec 2015 18:23:29 +0100 Subject: greybus: svc: generalise deferred request handling Clean up and generalise deferred request handling by simply storing a reference-counted pointer to the operation itself in the work context. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index d974b36..6428052 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -16,10 +16,9 @@ #define CPORT_FLAGS_CSV_N BIT(2) -struct svc_hotplug { +struct gb_svc_deferred_request { struct work_struct work; - struct gb_connection *connection; - struct gb_svc_intf_hotplug_request data; + struct gb_operation *operation; }; @@ -349,16 +348,10 @@ static void gb_svc_intf_remove(struct gb_svc *svc, struct gb_interface *intf) ida_simple_remove(&svc->device_id_map, device_id); } -/* - * 'struct svc_hotplug' should be freed by svc_process_hotplug() before it - * returns, irrespective of success or Failure in bringing up the module. - */ -static void svc_process_hotplug(struct work_struct *work) +static void gb_svc_process_intf_hotplug(struct gb_operation *operation) { - struct svc_hotplug *svc_hotplug = container_of(work, struct svc_hotplug, - work); struct gb_svc_intf_hotplug_request *request; - struct gb_connection *connection = svc_hotplug->connection; + struct gb_connection *connection = operation->connection; struct gb_svc *svc = connection->private; struct gb_host_device *hd = connection->hd; struct gb_interface *intf; @@ -366,7 +359,7 @@ static void svc_process_hotplug(struct work_struct *work) int ret; /* The request message size has already been verified. */ - request = &svc_hotplug->data; + request = operation->request->payload; intf_id = request->intf_id; dev_dbg(&svc->dev, "%s - id = %u\n", __func__, intf_id); @@ -396,7 +389,7 @@ static void svc_process_hotplug(struct work_struct *work) if (!intf) { dev_err(&svc->dev, "failed to create interface %hhu\n", intf_id); - goto free_svc_hotplug; + return; } ret = gb_svc_read_and_clear_module_boot_status(intf); @@ -450,7 +443,7 @@ static void svc_process_hotplug(struct work_struct *work) goto destroy_route; } - goto free_svc_hotplug; + return; destroy_route: gb_svc_route_destroy(svc, svc->ap_intf_id, intf_id); @@ -463,8 +456,48 @@ ida_put: ida_simple_remove(&svc->device_id_map, device_id); destroy_interface: gb_interface_remove(intf); -free_svc_hotplug: - kfree(svc_hotplug); +} + +static void gb_svc_process_deferred_request(struct work_struct *work) +{ + struct gb_svc_deferred_request *dr; + struct gb_operation *operation; + struct gb_svc *svc; + u8 type; + + dr = container_of(work, struct gb_svc_deferred_request, work); + operation = dr->operation; + svc = operation->connection->private; + type = operation->request->header->type; + + switch (type) { + case GB_SVC_TYPE_INTF_HOTPLUG: + gb_svc_process_intf_hotplug(operation); + break; + default: + dev_err(&svc->dev, "bad deferred request type: %02x\n", type); + } + + gb_operation_put(operation); + kfree(dr); +} + +static int gb_svc_queue_deferred_request(struct gb_operation *operation) +{ + struct gb_svc_deferred_request *dr; + + dr = kmalloc(sizeof(*dr), GFP_KERNEL); + if (!dr) + return -ENOMEM; + + gb_operation_get(operation); + + dr->operation = operation; + INIT_WORK(&dr->work, gb_svc_process_deferred_request); + + queue_work(system_unbound_wq, &dr->work); + + return 0; } /* @@ -480,7 +513,6 @@ static int gb_svc_intf_hotplug_recv(struct gb_operation *op) { struct gb_svc *svc = op->connection->private; struct gb_svc_intf_hotplug_request *request; - struct svc_hotplug *svc_hotplug; if (op->request->payload_size < sizeof(*request)) { dev_warn(&svc->dev, "short hotplug request received (%zu < %zu)\n", @@ -492,17 +524,7 @@ static int gb_svc_intf_hotplug_recv(struct gb_operation *op) dev_dbg(&svc->dev, "%s - id = %u\n", __func__, request->intf_id); - svc_hotplug = kmalloc(sizeof(*svc_hotplug), GFP_KERNEL); - if (!svc_hotplug) - return -ENOMEM; - - svc_hotplug->connection = op->connection; - memcpy(&svc_hotplug->data, request, sizeof(svc_hotplug->data)); - - INIT_WORK(&svc_hotplug->work, svc_process_hotplug); - queue_work(system_unbound_wq, &svc_hotplug->work); - - return 0; + return gb_svc_queue_deferred_request(op); } static int gb_svc_intf_hot_unplug_recv(struct gb_operation *op) -- cgit v0.10.2 From 57ccd4b08767bc3c44d3752bddcb6d6cad78830c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 2 Dec 2015 18:23:30 +0100 Subject: greybus: svc: defer processing of hot-unplug requests Defer processing also of hot-unplug events. This is a step towards serialising hot-plug and unplug event processing. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 6428052..34713d6 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -458,6 +458,30 @@ destroy_interface: gb_interface_remove(intf); } +static void gb_svc_process_intf_hot_unplug(struct gb_operation *operation) +{ + struct gb_svc *svc = operation->connection->private; + struct gb_svc_intf_hot_unplug_request *request; + struct gb_host_device *hd = operation->connection->hd; + struct gb_interface *intf; + u8 intf_id; + + /* The request message size has already been verified. */ + request = operation->request->payload; + intf_id = request->intf_id; + + dev_dbg(&svc->dev, "%s - id = %u\n", __func__, intf_id); + + intf = gb_interface_find(hd, intf_id); + if (!intf) { + dev_warn(&svc->dev, "could not find hot-unplug interface %hhu\n", + intf_id); + return; + } + + gb_svc_intf_remove(svc, intf); +} + static void gb_svc_process_deferred_request(struct work_struct *work) { struct gb_svc_deferred_request *dr; @@ -474,6 +498,9 @@ static void gb_svc_process_deferred_request(struct work_struct *work) case GB_SVC_TYPE_INTF_HOTPLUG: gb_svc_process_intf_hotplug(operation); break; + case GB_SVC_TYPE_INTF_HOT_UNPLUG: + gb_svc_process_intf_hot_unplug(operation); + break; default: dev_err(&svc->dev, "bad deferred request type: %02x\n", type); } @@ -531,9 +558,6 @@ static int gb_svc_intf_hot_unplug_recv(struct gb_operation *op) { struct gb_svc *svc = op->connection->private; struct gb_svc_intf_hot_unplug_request *request; - struct gb_host_device *hd = op->connection->hd; - struct gb_interface *intf; - u8 intf_id; if (op->request->payload_size < sizeof(*request)) { dev_warn(&svc->dev, "short hot unplug request received (%zu < %zu)\n", @@ -542,20 +566,10 @@ static int gb_svc_intf_hot_unplug_recv(struct gb_operation *op) } request = op->request->payload; - intf_id = request->intf_id; - - dev_dbg(&svc->dev, "%s - id = %u\n", __func__, intf_id); - intf = gb_interface_find(hd, intf_id); - if (!intf) { - dev_warn(&svc->dev, "could not find hot-unplug interface %hhu\n", - intf_id); - return -EINVAL; - } - - gb_svc_intf_remove(svc, intf); + dev_dbg(&svc->dev, "%s - id = %u\n", __func__, request->intf_id); - return 0; + return gb_svc_queue_deferred_request(op); } static int gb_svc_intf_reset_recv(struct gb_operation *op) -- cgit v0.10.2 From 3e48acac26c8b5321ff5b752c8650e1cf4d04344 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 2 Dec 2015 18:23:31 +0100 Subject: greybus: svc: fix racy hotplug handling Fix racy hotplug handling by serialising all processing of hot-plug and unplug requests using a single-threaded dedicated workqueue. This fixes a reported crash during enumeration when processing multiple events. The current svc implementation does not handle concurrency at all (e.g. no interface list lock or refcounting) so we need to use the big hammer for now. Note that we will eventually want to process events for different interfaces in parallel, but that we'd still need a workqueue in order not to starve other svc requests (e.g. for timesync). Reported-by: Vaibhav Hiremath Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 34713d6..af41e8e4 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -511,6 +511,7 @@ static void gb_svc_process_deferred_request(struct work_struct *work) static int gb_svc_queue_deferred_request(struct gb_operation *operation) { + struct gb_svc *svc = operation->connection->private; struct gb_svc_deferred_request *dr; dr = kmalloc(sizeof(*dr), GFP_KERNEL); @@ -522,7 +523,7 @@ static int gb_svc_queue_deferred_request(struct gb_operation *operation) dr->operation = operation; INIT_WORK(&dr->work, gb_svc_process_deferred_request); - queue_work(system_unbound_wq, &dr->work); + queue_work(svc->wq, &dr->work); return 0; } @@ -532,7 +533,7 @@ static int gb_svc_queue_deferred_request(struct gb_operation *operation) * initialization on the module side. Over that, we may also need to download * the firmware first and flash that on the module. * - * In order to make other hotplug events to not wait for all this to finish, + * In order not to make other svc events wait for all this to finish, * handle most of module hotplug stuff outside of the hotplug callback, with * help of a workqueue. */ @@ -658,6 +659,7 @@ static void gb_svc_release(struct device *dev) struct gb_svc *svc = to_gb_svc(dev); ida_destroy(&svc->device_id_map); + destroy_workqueue(svc->wq); kfree(svc); } @@ -675,6 +677,12 @@ static int gb_svc_connection_init(struct gb_connection *connection) if (!svc) return -ENOMEM; + svc->wq = alloc_workqueue("%s:svc", WQ_UNBOUND, 1, dev_name(&hd->dev)); + if (!svc->wq) { + kfree(svc); + return -ENOMEM; + } + svc->dev.parent = &hd->dev; svc->dev.bus = &greybus_bus_type; svc->dev.type = &greybus_svc_type; diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index 99be041..3acfa07 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -22,6 +22,7 @@ struct gb_svc { struct gb_connection *connection; enum gb_svc_state state; struct ida device_id_map; + struct workqueue_struct *wq; u16 endo_id; u8 ap_intf_id; -- cgit v0.10.2 From b455c84655d5bdfc5157d2100279e3ff2454b596 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Wed, 2 Dec 2015 11:12:27 +0000 Subject: greybus: spi: add rdwr field to transfer descriptor Add read and/or write field to transfer descriptor to make it possible to identify the type of transfer. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 00593b0..23d4cce 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -695,6 +695,9 @@ struct gb_spi_transfer { __le16 delay_usecs; __u8 cs_change; __u8 bits_per_word; + __u8 rdwr; +#define GB_SPI_XFER_READ 0x01 +#define GB_SPI_XFER_WRITE 0x02 } __packed; struct gb_spi_transfer_request { diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index 33e86f9..1b9c973 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -107,13 +107,16 @@ gb_spi_operation_create(struct gb_connection *connection, gb_xfer->delay_usecs = cpu_to_le16(xfer->delay_usecs); gb_xfer->cs_change = xfer->cs_change; gb_xfer->bits_per_word = xfer->bits_per_word; - gb_xfer++; /* Copy tx data */ if (xfer->tx_buf) { memcpy(tx_data, xfer->tx_buf, xfer->len); tx_data += xfer->len; + gb_xfer->rdwr |= GB_SPI_XFER_WRITE; } + if (xfer->rx_buf) + gb_xfer->rdwr |= GB_SPI_XFER_READ; + gb_xfer++; } return operation; -- cgit v0.10.2 From b343f6afd7635c86e1c001f1623e07f218c694db Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Wed, 2 Dec 2015 11:12:28 +0000 Subject: greybus: spi: add master and device config operations Add master and device config operations, one is to merge all the master operations and the device config will allow to fetch and add devices for each chip select. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 23d4cce..e8c4bce 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -651,30 +651,29 @@ struct gb_pwm_disable_request { #define GB_SPI_FLAG_NO_TX BIT(2) /* can't do buffer write */ /* Greybus spi operation types */ -#define GB_SPI_TYPE_MODE 0x02 -#define GB_SPI_TYPE_FLAGS 0x03 -#define GB_SPI_TYPE_BITS_PER_WORD_MASK 0x04 -#define GB_SPI_TYPE_NUM_CHIPSELECT 0x05 -#define GB_SPI_TYPE_TRANSFER 0x06 +#define GB_SPI_TYPE_MASTER_CONFIG 0x02 +#define GB_SPI_TYPE_DEVICE_CONFIG 0x03 +#define GB_SPI_TYPE_TRANSFER 0x04 /* mode request has no payload */ -struct gb_spi_mode_response { +struct gb_spi_master_config_response { + __le32 bits_per_word_mask; + __le32 min_speed_hz; + __le32 max_speed_hz; __le16 mode; -} __packed; - -/* flags request has no payload */ -struct gb_spi_flags_response { __le16 flags; + __le16 num_chipselect; } __packed; -/* bits-per-word request has no payload */ -struct gb_spi_bpw_response { - __le32 bits_per_word_mask; +struct gb_spi_device_config_request { + __le16 chip_select; } __packed; -/* num-chipselects request has no payload */ -struct gb_spi_chipselect_response { - __le16 num_chipselect; +struct gb_spi_device_config_response { + __le16 mode; + __u8 bits_per_word; + __le32 max_speed_hz; + __u8 name[32]; } __packed; /** diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index 1b9c973..8e0e403 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -1,8 +1,8 @@ /* * SPI bridge driver for the Greybus "generic" SPI module. * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. * * Released under the GPLv2 only. */ @@ -17,30 +17,20 @@ struct gb_spi { struct gb_connection *connection; - - /* Modes supported by spi controller */ u16 mode; - /* constraints of the spi controller */ u16 flags; - - /* - * copied from kernel: - * - * A mask indicating which values of bits_per_word are supported by the - * controller. Bit n indicates that a bits_per_word n+1 is suported. If - * set, the SPI core will reject any transfer with an unsupported - * bits_per_word. If not set, this value is simply ignored, and it's up - * to the individual driver to perform any validation. - */ u32 bits_per_word_mask; - - /* - * chipselects will be integral to many controllers; some others might - * use board-specific GPIOs. - */ u16 num_chipselect; + u32 min_speed_hz; + u32 max_speed_hz; + struct spi_device *spi_devices; }; +static struct spi_master *get_master_from_spi(struct gb_spi *spi) +{ + return spi->connection->private; +} + /* Routines to transfer data */ static struct gb_operation * gb_spi_operation_create(struct gb_connection *connection, @@ -181,7 +171,7 @@ static void gb_spi_cleanup(struct spi_device *spi) } -/* Routines to get controller infomation */ +/* Routines to get controller information */ /* * Map Greybus spi mode bits/flags/bpw into Linux ones. @@ -190,103 +180,86 @@ static void gb_spi_cleanup(struct spi_device *spi) #define gb_spi_mode_map(mode) mode #define gb_spi_flags_map(flags) flags -static int gb_spi_mode_operation(struct gb_spi *spi) +static int gb_spi_get_master_config(struct gb_spi *spi) { - struct gb_spi_mode_response response; - u16 mode; + struct gb_spi_master_config_response response; + u16 mode, flags; int ret; - ret = gb_operation_sync(spi->connection, GB_SPI_TYPE_MODE, + ret = gb_operation_sync(spi->connection, GB_SPI_TYPE_MASTER_CONFIG, NULL, 0, &response, sizeof(response)); - if (ret) + if (ret < 0) return ret; mode = le16_to_cpu(response.mode); spi->mode = gb_spi_mode_map(mode); - return 0; -} - -static int gb_spi_flags_operation(struct gb_spi *spi) -{ - struct gb_spi_flags_response response; - u16 flags; - int ret; - - ret = gb_operation_sync(spi->connection, GB_SPI_TYPE_FLAGS, - NULL, 0, &response, sizeof(response)); - if (ret) - return ret; - flags = le16_to_cpu(response.flags); spi->flags = gb_spi_flags_map(flags); - return 0; -} - -static int gb_spi_bpw_operation(struct gb_spi *spi) -{ - struct gb_spi_bpw_response response; - int ret; - - ret = gb_operation_sync(spi->connection, GB_SPI_TYPE_BITS_PER_WORD_MASK, - NULL, 0, &response, sizeof(response)); - if (ret) - return ret; - spi->bits_per_word_mask = le32_to_cpu(response.bits_per_word_mask); + spi->num_chipselect = le16_to_cpu(response.num_chipselect); + + spi->min_speed_hz = le32_to_cpu(response.min_speed_hz); + spi->max_speed_hz = le32_to_cpu(response.max_speed_hz); return 0; } -static int gb_spi_chipselect_operation(struct gb_spi *spi) +static int gb_spi_setup_device(struct gb_spi *spi, uint16_t cs) { - struct gb_spi_chipselect_response response; + struct spi_master *master = get_master_from_spi(spi); + struct gb_spi_device_config_request request; + struct gb_spi_device_config_response response; + struct spi_board_info spi_board = { {0} }; + struct spi_device *spidev = &spi->spi_devices[cs]; int ret; - ret = gb_operation_sync(spi->connection, GB_SPI_TYPE_NUM_CHIPSELECT, - NULL, 0, &response, sizeof(response)); - if (ret) + request.chip_select = cpu_to_le16(cs); + + ret = gb_operation_sync(spi->connection, GB_SPI_TYPE_DEVICE_CONFIG, + &request, sizeof(request), + &response, sizeof(response)); + if (ret < 0) return ret; - spi->num_chipselect = le16_to_cpu(response.num_chipselect); + memcpy(spi_board.modalias, response.name, sizeof(spi_board.modalias)); + spi_board.mode = le16_to_cpu(response.mode); + spi_board.bus_num = master->bus_num; + spi_board.chip_select = cs; + spi_board.max_speed_hz = le32_to_cpu(response.max_speed_hz); + + spidev = spi_new_device(master, &spi_board); + if (!spidev) + ret = -EINVAL; return 0; } -/* - * Initialize the spi device. This includes verifying we can support it (based - * on the protocol version it advertises). If that's OK, we get and cached its - * mode bits & flags. - */ static int gb_spi_init(struct gb_spi *spi) { int ret; - /* mode never changes, just get it once */ - ret = gb_spi_mode_operation(spi); - if (ret) - return ret; - - /* flags never changes, just get it once */ - ret = gb_spi_flags_operation(spi); + /* get master configuration */ + ret = gb_spi_get_master_config(spi); if (ret) return ret; - /* total number of chipselects never changes, just get it once */ - ret = gb_spi_chipselect_operation(spi); - if (ret) - return ret; + spi->spi_devices = kcalloc(spi->num_chipselect, + sizeof(struct spi_device), GFP_KERNEL); + if (!spi->spi_devices) + return -ENOMEM; - /* bits-per-word-mask never changes, just get it once */ - return gb_spi_bpw_operation(spi); + return ret; } + static int gb_spi_connection_init(struct gb_connection *connection) { struct gb_spi *spi; struct spi_master *master; int ret; + int i; /* Allocate master with space for data */ master = spi_alloc_master(&connection->bundle->dev, sizeof(*spi)); @@ -315,8 +288,15 @@ static int gb_spi_connection_init(struct gb_connection *connection) master->transfer_one_message = gb_spi_transfer_one_message; ret = spi_register_master(master); - if (!ret) - return 0; + + /* now, fetch the devices configuration */ + for (i = 0; i < spi->num_chipselect; i++) { + ret = gb_spi_setup_device(spi, i); + if (ret < 0) + break; + } + + return ret; out_err: spi_master_put(master); -- cgit v0.10.2 From 11aa7121edfa4c32b06e9278e6d0e51d197d3560 Mon Sep 17 00:00:00 2001 From: Michael Scott Date: Thu, 3 Dec 2015 12:32:30 -0800 Subject: greybus: build: remove Android makefile There is no standard way of building a kernel from source in Android. Each device/SoC can (and do) implement it in their own way. To that end, let's remove this makefile and let each device define how they want to build the modules. Signed-off-by: Michael Scott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Android.mk b/drivers/staging/greybus/Android.mk deleted file mode 100644 index 74948cd..0000000 --- a/drivers/staging/greybus/Android.mk +++ /dev/null @@ -1,32 +0,0 @@ -.PHONY: build-greybus - -ifneq ($(TARGET_NO_KERNEL), true) -$(PRODUCT_OUT)/ramdisk.img: build-greybus -endif - -GREYBUS_MODULE_OUT_PATH := $(PRODUCT_OUT)/root/lib/modules -GREYBUS_CC_PREFIX := $(shell cd `dirname $(TARGET_TOOLS_PREFIX)` && pwd)/$(shell basename $(TARGET_TOOLS_PREFIX)) - -include $(CLEAR_VARS) -GREYBUS_SRC_PATH := $(ANDROID_BUILD_TOP)/external/greybus/ -LOCAL_PATH := $(GREYBUS_SRC_PATH) -LOCAL_SRC_FILES := greybus.ko -LOCAL_MODULE := $(LOCAL_SRC_FILES) -LOCAL_MODULE_CLASS := EXECUTABLES -LOCAL_MODULE_PATH := $(GREYBUS_MODULE_OUT_PATH) -$(LOCAL_PATH)/$(LOCAL_SRC_FILES): build-greybus -include $(BUILD_PREBUILT) - -KDIRARG := KERNELDIR="${ANDROID_PRODUCT_OUT}/obj/kernel" -ARCHARG := ARCH=$(TARGET_ARCH) -FLAGARG := EXTRA_CFLAGS+=-fno-pic -ARGS := $(KDIRARG) $(ARCHARG) $(FLAGARG) - -build-greybus: $(INSTALLED_KERNEL_TARGET) - make clean -C $(GREYBUS_SRC_PATH) - cd $(GREYBUS_SRC_PATH) &&\ - $(MAKE) -j$(MAKE_JOBS) CROSS_COMPILE=$(GREYBUS_CC_PREFIX) $(ARGS) - mkdir -p $(GREYBUS_MODULE_OUT_PATH) - ko=`find $(GREYBUS_SRC_PATH) -type f -name "*.ko"`;\ - for i in $$ko; do $(GREYBUS_CC_PREFIX)strip --strip-unneeded $$i;\ - mv $$i $(GREYBUS_MODULE_OUT_PATH)/; done; -- cgit v0.10.2 From 31bc2c9bcd3054b90322acf85a53aacbb9e29ee4 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Wed, 2 Dec 2015 11:12:29 +0000 Subject: greybus: spi: fix transfers bigger than greybus payload Add helper functions calculate the tx and rx size possible that fit a greybus payload size and change the operation creation to adjust to that. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index 8e0e403..094d6d8 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -31,6 +31,51 @@ static struct spi_master *get_master_from_spi(struct gb_spi *spi) return spi->connection->private; } +static int tx_header_fit_operation(u32 tx_size, u32 count, size_t data_max) +{ + size_t headers_size; + + data_max -= sizeof(struct gb_spi_transfer_request); + headers_size = (count + 1) * sizeof(struct gb_spi_transfer); + + return tx_size + headers_size > data_max ? 0 : 1; +} + +static size_t calc_rx_xfer_size(u32 rx_size, u32 *tx_xfer_size, u32 len, + size_t data_max) +{ + size_t rx_xfer_size; + + data_max -= sizeof(struct gb_spi_transfer_response); + + if (rx_size + len > data_max) + rx_xfer_size = data_max - rx_size; + else + rx_xfer_size = len; + + /* if this is a write_read, for symmetry read the same as write */ + if (*tx_xfer_size && rx_xfer_size > *tx_xfer_size) + rx_xfer_size = *tx_xfer_size; + if (*tx_xfer_size && rx_xfer_size < *tx_xfer_size) + *tx_xfer_size = rx_xfer_size; + + return rx_xfer_size; +} + +static size_t calc_tx_xfer_size(u32 tx_size, u32 count, size_t len, + size_t data_max) +{ + size_t headers_size; + + data_max -= sizeof(struct gb_spi_transfer_request); + headers_size = (count + 1) * sizeof(struct gb_spi_transfer); + + if (tx_size + headers_size + len > data_max) + return data_max - (tx_size + sizeof(struct gb_spi_transfer)); + + return len; +} + /* Routines to transfer data */ static struct gb_operation * gb_spi_operation_create(struct gb_connection *connection, @@ -41,9 +86,14 @@ gb_spi_operation_create(struct gb_connection *connection, struct spi_transfer *xfer; struct gb_spi_transfer *gb_xfer; struct gb_operation *operation; - u32 tx_size = 0, rx_size = 0, count = 0, request_size; + struct spi_transfer *last_xfer = NULL; + u32 tx_size = 0, rx_size = 0, count = 0, xfer_len = 0, request_size; + u32 tx_xfer_size = 0, rx_xfer_size = 0, last_xfer_size = 0; + size_t data_max; void *tx_data; + data_max = gb_operation_get_payload_size_max(connection); + /* Find number of transfers queued and tx/rx length in the message */ list_for_each_entry(xfer, &msg->transfers, transfer_list) { if (!xfer->tx_buf && !xfer->rx_buf) { @@ -51,21 +101,33 @@ gb_spi_operation_create(struct gb_connection *connection, "bufferless transfer, length %u\n", xfer->len); return NULL; } + last_xfer = xfer; - if (xfer->tx_buf) - tx_size += xfer->len; - if (xfer->rx_buf) - rx_size += xfer->len; + tx_xfer_size = 0; + rx_xfer_size = 0; + + if (xfer->tx_buf) { + if (!tx_header_fit_operation(tx_size, count, data_max)) + break; + tx_xfer_size = calc_tx_xfer_size(tx_size, count, + xfer->len, data_max); + last_xfer_size = tx_xfer_size; + } + + if (xfer->rx_buf) { + rx_xfer_size = calc_rx_xfer_size(rx_size, &tx_xfer_size, + xfer->len, data_max); + last_xfer_size = rx_xfer_size; + } + + tx_size += tx_xfer_size; + rx_size += rx_xfer_size; - *total_len += xfer->len; + *total_len += last_xfer_size; count++; - } - /* Too many transfers ? */ - if (count > (u32)U16_MAX) { - dev_err(&connection->bundle->dev, - "transfer count (%u) too big\n", count); - return NULL; + if (xfer->len != last_xfer_size) + break; } /* @@ -92,20 +154,30 @@ gb_spi_operation_create(struct gb_connection *connection, /* Fill in the transfers array */ list_for_each_entry(xfer, &msg->transfers, transfer_list) { + if (last_xfer && xfer == last_xfer) + xfer_len = last_xfer_size; + else + xfer_len = xfer->len; + gb_xfer->speed_hz = cpu_to_le32(xfer->speed_hz); - gb_xfer->len = cpu_to_le32(xfer->len); + gb_xfer->len = cpu_to_le32(xfer_len); gb_xfer->delay_usecs = cpu_to_le16(xfer->delay_usecs); gb_xfer->cs_change = xfer->cs_change; gb_xfer->bits_per_word = xfer->bits_per_word; /* Copy tx data */ if (xfer->tx_buf) { - memcpy(tx_data, xfer->tx_buf, xfer->len); - tx_data += xfer->len; gb_xfer->rdwr |= GB_SPI_XFER_WRITE; + memcpy(tx_data, xfer->tx_buf, xfer_len); + tx_data += xfer_len; } + if (xfer->rx_buf) gb_xfer->rdwr |= GB_SPI_XFER_READ; + + if (last_xfer && xfer == last_xfer) + break; + gb_xfer++; } -- cgit v0.10.2 From e6420dac3d5d45c60886221afcf31ecaf255d992 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 3 Dec 2015 13:54:57 +0530 Subject: greybus: Documentation: Fix N-svc directory name endo_id was present in place of the directory N-svc, fix it. Fixes: 4f7b1833e78f ("Documentation/sysfs-bus-greybus: update the bus ABI documentation") Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 9329a31..9a6bbc3 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -6,7 +6,7 @@ Description: The "root" greybus device for the Greybus device tree, or bus, where N is a dynamically assigned 1-based id. -What: /sys/bus/greybus/device/N-svc/endo_id +What: /sys/bus/greybus/device/N-svc Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman -- cgit v0.10.2 From 3f85c787b74c26f3816017e64288af907f291462 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Thu, 3 Dec 2015 16:07:47 +0000 Subject: greybus: lights: add v4l2 flash operations We do not implement any of the v4l2 flash operations, as the default ones are ok for now, however the init needs anything define, if not it will return an error. So, just define it and have an error free v4l2 flash init. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index 3723a2c..01dcf18 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -456,6 +456,8 @@ static void gb_lights_led_operations_set(struct gb_channel *channel, #ifdef V4L2_HAVE_FLASH /* V4L2 specific helpers */ +static const struct v4l2_flash_ops v4l2_flash_ops; + static void __gb_lights_channel_v4l2_config(struct led_flash_setting *channel_s, struct led_flash_setting *v4l2_s) { @@ -507,7 +509,7 @@ static int gb_lights_light_v4l2_register(struct gb_light *light) LED_FAULT_LED_OVER_TEMPERATURE; light->v4l2_flash = v4l2_flash_init(dev, NULL, fled, iled, - NULL, sd_cfg); + &v4l2_flash_ops, sd_cfg); if (IS_ERR_OR_NULL(light->v4l2_flash)) { ret = PTR_ERR(light->v4l2_flash); goto out_free; -- cgit v0.10.2 From d644181fe60f4fcfca7e9e9e9b0503993e391e69 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Thu, 3 Dec 2015 16:07:48 +0000 Subject: greybus: lights: avoid channel torch double free When attaching torch to a flash we release the channel torch resources, but afterwards we do it again when releasing all the channels. Just free all the resource at channel release. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index 01dcf18..c49cc7e 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -681,9 +681,6 @@ static int __gb_lights_channel_torch_attach(struct gb_channel *channel, kfree(channel->led->name); channel->led->name = name; - /* free original torch channel resources */ - gb_lights_channel_free(channel_torch); - channel_torch->led = channel->led; return 0; -- cgit v0.10.2 From 1700507d8c1b3578152c8afa8062a66e78e3a4bb Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Thu, 3 Dec 2015 16:07:49 +0000 Subject: greybus: lights: default value for v4l2 flash controls V4l2 flash will return erro ERANGE if val(which is the default value) is not defined. Just set it to the max value reported by the module. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index c49cc7e..153c4f5 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -702,6 +702,7 @@ static int __gb_lights_flash_led_register(struct gb_channel *channel) fset->min = channel->intensity_uA.min; fset->max = channel->intensity_uA.max; fset->step = channel->intensity_uA.step; + fset->val = channel->intensity_uA.max; /* Only the flash mode have the timeout constraints settings */ if (channel->mode & GB_CHANNEL_MODE_FLASH) { @@ -709,6 +710,7 @@ static int __gb_lights_flash_led_register(struct gb_channel *channel) fset->min = channel->timeout_us.min; fset->max = channel->timeout_us.max; fset->step = channel->timeout_us.step; + fset->val = channel->timeout_us.max; } /* -- cgit v0.10.2 From d9fb3754ecf807f6c6bbe63ff2fbd29e00fad131 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 3 Dec 2015 17:29:38 +0000 Subject: greybus: loopback: Relax locking during loopback operations Currently a per-connection mutex is held during calls to gb_operation_send_sync. It is not necessary to hold this lock and later patches supporting multiple-outstanding bi-directional operations need to take the per-connection lock and the gb_dev level lock. Since gb_dev must always be taken before per-connection locks, it is both desirable and safe to drop the lock now. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index ef16ca5..e0be130 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -774,6 +774,8 @@ static int gb_loopback_fn(void *data) mutex_unlock(&gb->mutex); goto sleep; } + mutex_unlock(&gb->mutex); + /* Else operations to perform */ gb->apbridge_latency_ts = 0; gb->gpbridge_latency_ts = 0; @@ -783,7 +785,6 @@ static int gb_loopback_fn(void *data) error = gb_loopback_transfer(gb, size); else if (type == GB_LOOPBACK_TYPE_SINK) error = gb_loopback_sink(gb, size); - mutex_unlock(&gb->mutex); mutex_lock(&gb_dev.mutex); mutex_lock(&gb->mutex); -- cgit v0.10.2 From d6a1a3b5ea08c7828a177b48e6e39943b0fadf3c Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 3 Dec 2015 17:29:39 +0000 Subject: greybus: loopback: Move latency_ts initialization to transfer routine Initializing the bridge specific latency variables is only relevant to the transfer operation, so make it loopback-transfer specific. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index e0be130..7d582cd 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -463,6 +463,9 @@ static int gb_loopback_transfer(struct gb_loopback *gb, u32 len) struct gb_loopback_transfer_response *response; int retval; + gb->apbridge_latency_ts = 0; + gb->gpbridge_latency_ts = 0; + request = kmalloc(len + sizeof(*request), GFP_KERNEL); if (!request) return -ENOMEM; @@ -777,8 +780,6 @@ static int gb_loopback_fn(void *data) mutex_unlock(&gb->mutex); /* Else operations to perform */ - gb->apbridge_latency_ts = 0; - gb->gpbridge_latency_ts = 0; if (type == GB_LOOPBACK_TYPE_PING) error = gb_loopback_ping(gb); else if (type == GB_LOOPBACK_TYPE_TRANSFER) -- cgit v0.10.2 From 9673dcebe472f298ba9781db84c5880d55372cc9 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 3 Dec 2015 17:29:40 +0000 Subject: greybus: loopback: Drop unused timeval variables start and end aren't used and should be dropped. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 7d582cd..c1943f2 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -53,9 +53,6 @@ struct gb_loopback_device { int ms_wait; u32 error; - struct timeval start; - struct timeval end; - /* Overall stats */ struct gb_loopback_stats latency; struct gb_loopback_stats throughput; @@ -577,8 +574,6 @@ static void gb_loopback_reset_stats(struct gb_loopback_device *gb_dev) } /* Reset aggregate stats */ - memset(&gb_dev->start, 0, sizeof(struct timeval)); - memset(&gb_dev->end, 0, sizeof(struct timeval)); memcpy(&gb_dev->latency, &reset, sizeof(struct gb_loopback_stats)); memcpy(&gb_dev->throughput, &reset, sizeof(struct gb_loopback_stats)); memcpy(&gb_dev->requests_per_second, &reset, -- cgit v0.10.2 From 8e1d6c336d74977403b0d7ca81e1e9a098518ff0 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 3 Dec 2015 17:29:41 +0000 Subject: greybus: loopback: drop bus aggregate calculation At some point we had a statement in a Jira work item to pull out 'bus level' data from greybus and to have messages to different interfaces be synchronized with respect to each other. Synchronizing threads with respect to each other is slow and it turns out we can get the same 'bus level' stastics by making the user-space test application smarter. That's great news for the in-kernel code since it means we can cut out a whole lot of code to-do with calculating 'bus level' aggregate data and we can stop forcing threads to hit a rendezvous before sending out another loopback operation. So this patch drops bus level aggregates in favour of doing that in user-space. It subtracts a lot of code and cycles that in practice nobody cares about anyway. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index c1943f2..8524ce1 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -36,29 +36,11 @@ struct gb_loopback_stats { struct gb_loopback_device { struct dentry *root; - struct dentry *file; u32 count; + size_t size_max; - struct kfifo kfifo; struct mutex mutex; struct list_head list; - wait_queue_head_t wq; - - int type; - u32 mask; - u32 size; - u32 iteration_max; - u32 iteration_count; - size_t size_max; - int ms_wait; - u32 error; - - /* Overall stats */ - struct gb_loopback_stats latency; - struct gb_loopback_stats throughput; - struct gb_loopback_stats requests_per_second; - struct gb_loopback_stats apbridge_unipro_latency; - struct gb_loopback_stats gpbridge_firmware_latency; }; static struct gb_loopback_device gb_dev; @@ -72,6 +54,7 @@ struct gb_loopback { struct mutex mutex; struct task_struct *task; struct list_head entry; + wait_queue_head_t wq; /* Per connection stats */ struct gb_loopback_stats latency; @@ -80,10 +63,15 @@ struct gb_loopback { struct gb_loopback_stats apbridge_unipro_latency; struct gb_loopback_stats gpbridge_firmware_latency; - u32 lbid; + int type; + u32 mask; + u32 size; + u32 iteration_max; u32 iteration_count; - u64 elapsed_nsecs; + int ms_wait; u32 error; + u32 lbid; + u64 elapsed_nsecs; u32 apbridge_latency_ts; u32 gpbridge_latency_ts; }; @@ -99,42 +87,34 @@ module_param(kfifo_depth, uint, 0444); #define GB_LOOPBACK_MS_WAIT_MAX 1000 /* interface sysfs attributes */ -#define gb_loopback_ro_attr(field, pfx, conn) \ -static ssize_t field##_##pfx##_show(struct device *dev, \ +#define gb_loopback_ro_attr(field) \ +static ssize_t field##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ struct gb_bundle *bundle; \ struct gb_loopback *gb; \ - if (conn) { \ - bundle = to_gb_bundle(dev); \ - gb = bundle->private; \ - return sprintf(buf, "%u\n", gb->field); \ - } else { \ - return sprintf(buf, "%u\n", gb_dev.field); \ - } \ + bundle = to_gb_bundle(dev); \ + gb = bundle->private; \ + return sprintf(buf, "%u\n", gb->field); \ } \ -static DEVICE_ATTR_RO(field##_##pfx) +static DEVICE_ATTR_RO(field) -#define gb_loopback_ro_stats_attr(name, field, type, pfx, conn) \ -static ssize_t name##_##field##_##pfx##_show(struct device *dev, \ +#define gb_loopback_ro_stats_attr(name, field, type) \ +static ssize_t name##_##field##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ struct gb_bundle *bundle; \ struct gb_loopback *gb; \ - if (conn) { \ - bundle = to_gb_bundle(dev); \ - gb = bundle->private; \ - return sprintf(buf, "%"#type"\n", gb->name.field); \ - } else { \ - return sprintf(buf, "%"#type"\n", gb_dev.name.field); \ - } \ + bundle = to_gb_bundle(dev); \ + gb = bundle->private; \ + return sprintf(buf, "%"#type"\n", gb->name.field); \ } \ -static DEVICE_ATTR_RO(name##_##field##_##pfx) +static DEVICE_ATTR_RO(name##_##field) -#define gb_loopback_ro_avg_attr(name, pfx, conn) \ -static ssize_t name##_avg_##pfx##_show(struct device *dev, \ +#define gb_loopback_ro_avg_attr(name) \ +static ssize_t name##_avg_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ @@ -143,24 +123,20 @@ static ssize_t name##_avg_##pfx##_show(struct device *dev, \ struct gb_loopback *gb; \ u64 avg; \ u32 count, rem; \ - if (conn) { \ - bundle = to_gb_bundle(dev); \ - gb = bundle->private; \ - stats = &gb->name; \ - } else { \ - stats = &gb_dev.name; \ - } \ + bundle = to_gb_bundle(dev); \ + gb = bundle->private; \ + stats = &gb->name; \ count = stats->count ? stats->count : 1; \ avg = stats->sum + count / 2; /* round closest */ \ rem = do_div(avg, count); \ return sprintf(buf, "%llu.%06u\n", avg, 1000000 * rem / count); \ } \ -static DEVICE_ATTR_RO(name##_avg_##pfx) +static DEVICE_ATTR_RO(name##_avg) -#define gb_loopback_stats_attrs(field, pfx, conn) \ - gb_loopback_ro_stats_attr(field, min, u, pfx, conn); \ - gb_loopback_ro_stats_attr(field, max, u, pfx, conn); \ - gb_loopback_ro_avg_attr(field, pfx, conn) +#define gb_loopback_stats_attrs(field) \ + gb_loopback_ro_stats_attr(field, min, u); \ + gb_loopback_ro_stats_attr(field, max, u); \ + gb_loopback_ro_avg_attr(field) #define gb_loopback_attr(field, type) \ static ssize_t field##_show(struct device *dev, \ @@ -178,13 +154,14 @@ static ssize_t field##_store(struct device *dev, \ { \ int ret; \ struct gb_bundle *bundle = to_gb_bundle(dev); \ - mutex_lock(&gb_dev.mutex); \ + struct gb_loopback *gb = bundle->private; \ + mutex_lock(&gb->mutex); \ ret = sscanf(buf, "%"#type, &gb->field); \ if (ret != 1) \ len = -EINVAL; \ else \ - gb_loopback_check_attr(&gb_dev, bundle); \ - mutex_unlock(&gb_dev.mutex); \ + gb_loopback_check_attr(gb, bundle); \ + mutex_unlock(&gb->mutex); \ return len; \ } \ static DEVICE_ATTR_RW(field) @@ -194,7 +171,9 @@ static ssize_t field##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ - return sprintf(buf, "%u\n", gb_dev.field); \ + struct gb_bundle *bundle = to_gb_bundle(dev); \ + struct gb_loopback *gb = bundle->private; \ + return sprintf(buf, "%u\n", gb->field); \ } \ static DEVICE_ATTR_RO(field) @@ -203,7 +182,9 @@ static ssize_t field##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ - return sprintf(buf, "%"#type"\n", gb_dev.field); \ + struct gb_bundle *bundle = to_gb_bundle(dev); \ + struct gb_loopback *gb = bundle->private; \ + return sprintf(buf, "%"#type"\n", gb->field); \ } \ static ssize_t field##_store(struct device *dev, \ struct device_attribute *attr, \ @@ -212,76 +193,63 @@ static ssize_t field##_store(struct device *dev, \ { \ int ret; \ struct gb_bundle *bundle = to_gb_bundle(dev); \ - mutex_lock(&gb_dev.mutex); \ - ret = sscanf(buf, "%"#type, &gb_dev.field); \ + struct gb_loopback *gb = bundle->private; \ + mutex_lock(&gb->mutex); \ + ret = sscanf(buf, "%"#type, &gb->field); \ if (ret != 1) \ len = -EINVAL; \ else \ - gb_loopback_check_attr(&gb_dev, bundle); \ - mutex_unlock(&gb_dev.mutex); \ + gb_loopback_check_attr(gb, bundle); \ + mutex_unlock(&gb->mutex); \ return len; \ } \ static DEVICE_ATTR_RW(field) -static void gb_loopback_reset_stats(struct gb_loopback_device *gb_dev); -static void gb_loopback_check_attr(struct gb_loopback_device *gb_dev, +static void gb_loopback_reset_stats(struct gb_loopback *gb); +static void gb_loopback_check_attr(struct gb_loopback *gb, struct gb_bundle *bundle) { - struct gb_loopback *gb; - - if (gb_dev->ms_wait > GB_LOOPBACK_MS_WAIT_MAX) - gb_dev->ms_wait = GB_LOOPBACK_MS_WAIT_MAX; - if (gb_dev->size > gb_dev->size_max) - gb_dev->size = gb_dev->size_max; - gb_dev->iteration_count = 0; - gb_dev->error = 0; - - list_for_each_entry(gb, &gb_dev->list, entry) { - mutex_lock(&gb->mutex); - gb->iteration_count = 0; - gb->error = 0; - if (kfifo_depth < gb_dev->iteration_max) { - dev_warn(&bundle->dev, - "cannot log bytes %u kfifo_depth %u\n", - gb_dev->iteration_max, kfifo_depth); - } - kfifo_reset_out(&gb->kfifo_lat); - kfifo_reset_out(&gb->kfifo_ts); - mutex_unlock(&gb->mutex); + if (gb->ms_wait > GB_LOOPBACK_MS_WAIT_MAX) + gb->ms_wait = GB_LOOPBACK_MS_WAIT_MAX; + if (gb->size > gb_dev.size_max) + gb->size = gb_dev.size_max; + gb->iteration_count = 0; + gb->error = 0; + + if (kfifo_depth < gb->iteration_max) { + dev_warn(&bundle->dev, + "cannot log bytes %u kfifo_depth %u\n", + gb->iteration_max, kfifo_depth); } + kfifo_reset_out(&gb->kfifo_lat); + kfifo_reset_out(&gb->kfifo_ts); - switch (gb_dev->type) { + switch (gb->type) { case GB_LOOPBACK_TYPE_PING: case GB_LOOPBACK_TYPE_TRANSFER: case GB_LOOPBACK_TYPE_SINK: - kfifo_reset_out(&gb_dev->kfifo); - gb_loopback_reset_stats(gb_dev); - wake_up(&gb_dev->wq); + gb_loopback_reset_stats(gb); + wake_up(&gb->wq); break; default: - gb_dev->type = 0; + gb->type = 0; break; } } /* Time to send and receive one message */ -gb_loopback_stats_attrs(latency, dev, false); -gb_loopback_stats_attrs(latency, con, true); +gb_loopback_stats_attrs(latency); /* Number of requests sent per second on this cport */ -gb_loopback_stats_attrs(requests_per_second, dev, false); -gb_loopback_stats_attrs(requests_per_second, con, true); +gb_loopback_stats_attrs(requests_per_second); /* Quantity of data sent and received on this cport */ -gb_loopback_stats_attrs(throughput, dev, false); -gb_loopback_stats_attrs(throughput, con, true); +gb_loopback_stats_attrs(throughput); /* Latency across the UniPro link from APBridge's perspective */ -gb_loopback_stats_attrs(apbridge_unipro_latency, dev, false); -gb_loopback_stats_attrs(apbridge_unipro_latency, con, true); +gb_loopback_stats_attrs(apbridge_unipro_latency); /* Firmware induced overhead in the GPBridge */ -gb_loopback_stats_attrs(gpbridge_firmware_latency, dev, false); -gb_loopback_stats_attrs(gpbridge_firmware_latency, con, true); +gb_loopback_stats_attrs(gpbridge_firmware_latency); + /* Number of errors encountered during loop */ -gb_loopback_ro_attr(error, dev, false); -gb_loopback_ro_attr(error, con, true); +gb_loopback_ro_attr(error); /* * Type of loopback message to send based on protocol type definitions @@ -303,53 +271,32 @@ gb_dev_loopback_ro_attr(iteration_count, false); /* A bit-mask of destination connecitons to include in the test run */ gb_dev_loopback_rw_attr(mask, u); -static struct attribute *loopback_dev_attrs[] = { - &dev_attr_latency_min_dev.attr, - &dev_attr_latency_max_dev.attr, - &dev_attr_latency_avg_dev.attr, - &dev_attr_requests_per_second_min_dev.attr, - &dev_attr_requests_per_second_max_dev.attr, - &dev_attr_requests_per_second_avg_dev.attr, - &dev_attr_throughput_min_dev.attr, - &dev_attr_throughput_max_dev.attr, - &dev_attr_throughput_avg_dev.attr, - &dev_attr_apbridge_unipro_latency_min_dev.attr, - &dev_attr_apbridge_unipro_latency_max_dev.attr, - &dev_attr_apbridge_unipro_latency_avg_dev.attr, - &dev_attr_gpbridge_firmware_latency_min_dev.attr, - &dev_attr_gpbridge_firmware_latency_max_dev.attr, - &dev_attr_gpbridge_firmware_latency_avg_dev.attr, +static struct attribute *loopback_attrs[] = { + &dev_attr_latency_min.attr, + &dev_attr_latency_max.attr, + &dev_attr_latency_avg.attr, + &dev_attr_requests_per_second_min.attr, + &dev_attr_requests_per_second_max.attr, + &dev_attr_requests_per_second_avg.attr, + &dev_attr_throughput_min.attr, + &dev_attr_throughput_max.attr, + &dev_attr_throughput_avg.attr, + &dev_attr_apbridge_unipro_latency_min.attr, + &dev_attr_apbridge_unipro_latency_max.attr, + &dev_attr_apbridge_unipro_latency_avg.attr, + &dev_attr_gpbridge_firmware_latency_min.attr, + &dev_attr_gpbridge_firmware_latency_max.attr, + &dev_attr_gpbridge_firmware_latency_avg.attr, &dev_attr_type.attr, &dev_attr_size.attr, &dev_attr_ms_wait.attr, &dev_attr_iteration_count.attr, &dev_attr_iteration_max.attr, &dev_attr_mask.attr, - &dev_attr_error_dev.attr, + &dev_attr_error.attr, NULL, }; -ATTRIBUTE_GROUPS(loopback_dev); - -static struct attribute *loopback_con_attrs[] = { - &dev_attr_latency_min_con.attr, - &dev_attr_latency_max_con.attr, - &dev_attr_latency_avg_con.attr, - &dev_attr_requests_per_second_min_con.attr, - &dev_attr_requests_per_second_max_con.attr, - &dev_attr_requests_per_second_avg_con.attr, - &dev_attr_throughput_min_con.attr, - &dev_attr_throughput_max_con.attr, - &dev_attr_throughput_avg_con.attr, - &dev_attr_apbridge_unipro_latency_min_con.attr, - &dev_attr_apbridge_unipro_latency_max_con.attr, - &dev_attr_apbridge_unipro_latency_avg_con.attr, - &dev_attr_gpbridge_firmware_latency_min_con.attr, - &dev_attr_gpbridge_firmware_latency_max_con.attr, - &dev_attr_gpbridge_firmware_latency_avg_con.attr, - &dev_attr_error_con.attr, - NULL, -}; -ATTRIBUTE_GROUPS(loopback_con); +ATTRIBUTE_GROUPS(loopback); static u32 gb_loopback_nsec_to_usec_latency(u64 elapsed_nsecs) { @@ -385,11 +332,6 @@ static void gb_loopback_push_latency_ts(struct gb_loopback *gb, kfifo_in(&gb->kfifo_ts, (unsigned char *)te, sizeof(*te)); } -static int gb_loopback_active(struct gb_loopback *gb) -{ - return (gb_dev.mask == 0 || (gb_dev.mask & gb->lbid)); -} - static int gb_loopback_operation_sync(struct gb_loopback *gb, int type, void *request, int request_size, void *response, int response_size) @@ -550,37 +492,32 @@ static int gb_loopback_request_recv(u8 type, struct gb_operation *operation) } } -static void gb_loopback_reset_stats(struct gb_loopback_device *gb_dev) +static void gb_loopback_reset_stats(struct gb_loopback *gb) { struct gb_loopback_stats reset = { .min = U32_MAX, }; - struct gb_loopback *gb; /* Reset per-connection stats */ - list_for_each_entry(gb, &gb_dev->list, entry) { - mutex_lock(&gb->mutex); - memcpy(&gb->latency, &reset, - sizeof(struct gb_loopback_stats)); - memcpy(&gb->throughput, &reset, - sizeof(struct gb_loopback_stats)); - memcpy(&gb->requests_per_second, &reset, - sizeof(struct gb_loopback_stats)); - memcpy(&gb->apbridge_unipro_latency, &reset, - sizeof(struct gb_loopback_stats)); - memcpy(&gb->gpbridge_firmware_latency, &reset, - sizeof(struct gb_loopback_stats)); - mutex_unlock(&gb->mutex); - } + memcpy(&gb->latency, &reset, + sizeof(struct gb_loopback_stats)); + memcpy(&gb->throughput, &reset, + sizeof(struct gb_loopback_stats)); + memcpy(&gb->requests_per_second, &reset, + sizeof(struct gb_loopback_stats)); + memcpy(&gb->apbridge_unipro_latency, &reset, + sizeof(struct gb_loopback_stats)); + memcpy(&gb->gpbridge_firmware_latency, &reset, + sizeof(struct gb_loopback_stats)); /* Reset aggregate stats */ - memcpy(&gb_dev->latency, &reset, sizeof(struct gb_loopback_stats)); - memcpy(&gb_dev->throughput, &reset, sizeof(struct gb_loopback_stats)); - memcpy(&gb_dev->requests_per_second, &reset, + memcpy(&gb->latency, &reset, sizeof(struct gb_loopback_stats)); + memcpy(&gb->throughput, &reset, sizeof(struct gb_loopback_stats)); + memcpy(&gb->requests_per_second, &reset, sizeof(struct gb_loopback_stats)); - memcpy(&gb_dev->apbridge_unipro_latency, &reset, + memcpy(&gb->apbridge_unipro_latency, &reset, sizeof(struct gb_loopback_stats)); - memcpy(&gb_dev->gpbridge_firmware_latency, &reset, + memcpy(&gb->gpbridge_firmware_latency, &reset, sizeof(struct gb_loopback_stats)); } @@ -599,7 +536,6 @@ static void gb_loopback_requests_update(struct gb_loopback *gb, u32 latency) u32 req = USEC_PER_SEC; do_div(req, latency); - gb_loopback_update_stats(&gb_dev.requests_per_second, req); gb_loopback_update_stats(&gb->requests_per_second, req); } @@ -608,17 +544,17 @@ static void gb_loopback_throughput_update(struct gb_loopback *gb, u32 latency) u32 throughput; u32 aggregate_size = sizeof(struct gb_operation_msg_hdr) * 2; - switch (gb_dev.type) { + switch (gb->type) { case GB_LOOPBACK_TYPE_PING: break; case GB_LOOPBACK_TYPE_SINK: aggregate_size += sizeof(struct gb_loopback_transfer_request) + - gb_dev.size; + gb->size; break; case GB_LOOPBACK_TYPE_TRANSFER: aggregate_size += sizeof(struct gb_loopback_transfer_request) + sizeof(struct gb_loopback_transfer_response) + - gb_dev.size * 2; + gb->size * 2; break; default: return; @@ -628,65 +564,9 @@ static void gb_loopback_throughput_update(struct gb_loopback *gb, u32 latency) throughput = USEC_PER_SEC; do_div(throughput, latency); throughput *= aggregate_size; - gb_loopback_update_stats(&gb_dev.throughput, throughput); gb_loopback_update_stats(&gb->throughput, throughput); } -static int gb_loopback_calculate_aggregate_stats(void) -{ - struct gb_loopback *gb; - struct timeval ts; - struct timeval te; - u64 t1, t2; - u64 ts_min; - u64 te_max; - u64 elapsed_nsecs; - u32 lat; - int i, latched; - int rollover = 0; - - for (i = 0; i < gb_dev.iteration_max; i++) { - latched = 0; - ts_min = 0; - te_max = 0; - list_for_each_entry(gb, &gb_dev.list, entry) { - if (!gb_loopback_active(gb)) - continue; - if (kfifo_out(&gb->kfifo_ts, &ts, sizeof(ts)) < sizeof(ts)) - goto error; - if (kfifo_out(&gb->kfifo_ts, &te, sizeof(te)) < sizeof(te)) - goto error; - t1 = timeval_to_ns(&ts); - t2 = timeval_to_ns(&te); - - /* minimum timestamp is always what we want */ - if (latched == 0 || t1 < ts_min) - ts_min = t1; - - /* maximum timestamp needs to handle rollover */ - if (t2 > t1) { - if (latched == 0 || t2 > te_max) - te_max = t2; - } else { - if (latched == 0 || rollover == 0) - te_max = t2; - if (rollover == 1 && t2 > te_max) - te_max = t2; - rollover = 1; - } - latched = 1; - } - /* Calculate the aggregate timestamp */ - elapsed_nsecs = __gb_loopback_calc_latency(ts_min, te_max); - lat = gb_loopback_nsec_to_usec_latency(elapsed_nsecs); - kfifo_in(&gb_dev.kfifo, (unsigned char *)&lat, sizeof(lat)); - } - return 0; -error: - kfifo_reset_out(&gb_dev.kfifo); - return -ENOMEM; -} - static void gb_loopback_calculate_stats(struct gb_loopback *gb) { u32 lat; @@ -695,7 +575,6 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb) lat = gb_loopback_nsec_to_usec_latency(gb->elapsed_nsecs); /* Log latency stastic */ - gb_loopback_update_stats(&gb_dev.latency, lat); gb_loopback_update_stats(&gb->latency, lat); /* Raw latency log on a per thread basis */ @@ -706,12 +585,8 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb) gb_loopback_requests_update(gb, lat); /* Log the firmware supplied latency values */ - gb_loopback_update_stats(&gb_dev.apbridge_unipro_latency, - gb->apbridge_latency_ts); gb_loopback_update_stats(&gb->apbridge_unipro_latency, gb->apbridge_latency_ts); - gb_loopback_update_stats(&gb_dev.gpbridge_firmware_latency, - gb->gpbridge_latency_ts); gb_loopback_update_stats(&gb->gpbridge_firmware_latency, gb->gpbridge_latency_ts); } @@ -722,56 +597,29 @@ static int gb_loopback_fn(void *data) int ms_wait = 0; int type; u32 size; - u32 low_count; struct gb_loopback *gb = data; - struct gb_loopback *gb_list; while (1) { - if (!gb_dev.type) - wait_event_interruptible(gb_dev.wq, gb_dev.type || + if (!gb->type) + wait_event_interruptible(gb->wq, gb->type || kthread_should_stop()); if (kthread_should_stop()) break; - mutex_lock(&gb_dev.mutex); - if (!gb_loopback_active(gb)) { - ms_wait = 100; - goto unlock_continue; - } - if (gb_dev.iteration_max) { - /* Determine overall lowest count */ - low_count = gb->iteration_count; - list_for_each_entry(gb_list, &gb_dev.list, entry) { - if (!gb_loopback_active(gb_list)) - continue; - if (gb_list->iteration_count < low_count) - low_count = gb_list->iteration_count; - } - /* All threads achieved at least low_count iterations */ - if (gb_dev.iteration_count < low_count) { - gb_dev.iteration_count = low_count; - sysfs_notify(&gb->connection->bundle->dev.kobj, - NULL, "iteration_count"); - } - /* Optionally terminate */ - if (gb_dev.iteration_count == gb_dev.iteration_max) { - gb_loopback_calculate_aggregate_stats(); - gb_dev.type = 0; - goto unlock_continue; - } - } - size = gb_dev.size; - ms_wait = gb_dev.ms_wait; - type = gb_dev.type; - mutex_unlock(&gb_dev.mutex); - mutex_lock(&gb->mutex); - if (gb->iteration_count >= gb_dev.iteration_max) { - /* If this thread finished before siblings then sleep */ - ms_wait = 1; + + sysfs_notify(&gb->connection->bundle->dev.kobj, + NULL, "iteration_count"); + + /* Optionally terminate */ + if (gb->iteration_count == gb->iteration_max) { + gb->type = 0; mutex_unlock(&gb->mutex); - goto sleep; + continue; } + size = gb->size; + ms_wait = gb->ms_wait; + type = gb->type; mutex_unlock(&gb->mutex); /* Else operations to perform */ @@ -782,20 +630,12 @@ static int gb_loopback_fn(void *data) else if (type == GB_LOOPBACK_TYPE_SINK) error = gb_loopback_sink(gb, size); - mutex_lock(&gb_dev.mutex); - mutex_lock(&gb->mutex); - - if (error) { - gb_dev.error++; + if (error) gb->error++; - } + gb_loopback_calculate_stats(gb); gb->iteration_count++; - mutex_unlock(&gb->mutex); -unlock_continue: - mutex_unlock(&gb_dev.mutex); -sleep: if (ms_wait) msleep(ms_wait); } @@ -846,27 +686,6 @@ static const struct file_operations gb_loopback_debugfs_latency_ops = { .release = single_release, }; -static int gb_loopback_dbgfs_dev_latency_show(struct seq_file *s, void *unused) -{ - struct gb_loopback_device *gb_dev = s->private; - - return gb_loopback_dbgfs_latency_show_common(s, &gb_dev->kfifo, - &gb_dev->mutex); -} - -static int gb_loopback_dev_latency_open(struct inode *inode, struct file *file) -{ - return single_open(file, gb_loopback_dbgfs_dev_latency_show, - inode->i_private); -} - -static const struct file_operations gb_loopback_debugfs_dev_latency_ops = { - .open = gb_loopback_dev_latency_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - static int gb_loopback_bus_id_compare(void *priv, struct list_head *lha, struct list_head *lhb) { @@ -912,31 +731,22 @@ static int gb_loopback_connection_init(struct gb_connection *connection) struct gb_loopback *gb; int retval; char name[DEBUGFS_NAMELEN]; - struct kobject *kobj = &connection->bundle->dev.kobj; gb = kzalloc(sizeof(*gb), GFP_KERNEL); if (!gb) return -ENOMEM; - gb_loopback_reset_stats(&gb_dev); - /* If this is the first connection - create a per-bus entry */ + init_waitqueue_head(&gb->wq); + gb_loopback_reset_stats(gb); + mutex_lock(&gb_dev.mutex); if (!gb_dev.count) { - snprintf(name, sizeof(name), "raw_latency_%d", - connection->bundle->intf->hd->bus_id); - gb_dev.file = debugfs_create_file(name, S_IFREG | S_IRUGO, - gb_dev.root, &gb_dev, - &gb_loopback_debugfs_dev_latency_ops); - retval = sysfs_create_groups(kobj, loopback_dev_groups); - if (retval) - goto out_sysfs; - /* Calculate maximum payload */ gb_dev.size_max = gb_operation_get_payload_size_max(connection); if (gb_dev.size_max <= sizeof(struct gb_loopback_transfer_request)) { retval = -EINVAL; - goto out_sysfs_dev; + goto out_sysfs; } gb_dev.size_max -= sizeof(struct gb_loopback_transfer_request); } @@ -949,9 +759,9 @@ static int gb_loopback_connection_init(struct gb_connection *connection) gb->connection = connection; connection->bundle->private = gb; retval = sysfs_create_groups(&connection->bundle->dev.kobj, - loopback_con_groups); + loopback_groups); if (retval) - goto out_sysfs_dev; + goto out_sysfs; /* Allocate kfifo */ if (kfifo_alloc(&gb->kfifo_lat, kfifo_depth * sizeof(u32), @@ -984,15 +794,10 @@ out_kfifo1: out_kfifo0: kfifo_free(&gb->kfifo_lat); out_sysfs_conn: - sysfs_remove_groups(&connection->bundle->dev.kobj, loopback_con_groups); -out_sysfs_dev: - if (!gb_dev.count) { - sysfs_remove_groups(kobj, loopback_dev_groups); - debugfs_remove(gb_dev.file); - } + sysfs_remove_groups(&connection->bundle->dev.kobj, loopback_groups); +out_sysfs: debugfs_remove(gb->file); connection->bundle->private = NULL; -out_sysfs: mutex_unlock(&gb_dev.mutex); kfree(gb); @@ -1002,7 +807,6 @@ out_sysfs: static void gb_loopback_connection_exit(struct gb_connection *connection) { struct gb_loopback *gb = connection->bundle->private; - struct kobject *kobj = &connection->bundle->dev.kobj; if (!IS_ERR_OR_NULL(gb->task)) kthread_stop(gb->task); @@ -1014,12 +818,8 @@ static void gb_loopback_connection_exit(struct gb_connection *connection) kfifo_free(&gb->kfifo_ts); gb_connection_latency_tag_disable(connection); gb_dev.count--; - if (!gb_dev.count) { - sysfs_remove_groups(kobj, loopback_dev_groups); - debugfs_remove(gb_dev.file); - } sysfs_remove_groups(&connection->bundle->dev.kobj, - loopback_con_groups); + loopback_groups); debugfs_remove(gb->file); list_del(&gb->entry); mutex_unlock(&gb_dev.mutex); @@ -1040,21 +840,14 @@ static int loopback_init(void) { int retval; - init_waitqueue_head(&gb_dev.wq); INIT_LIST_HEAD(&gb_dev.list); mutex_init(&gb_dev.mutex); gb_dev.root = debugfs_create_dir("gb_loopback", NULL); - if (kfifo_alloc(&gb_dev.kfifo, kfifo_depth * sizeof(u32), GFP_KERNEL)) { - retval = -ENOMEM; - goto error_debugfs; - } - retval = gb_protocol_register(&loopback_protocol); if (!retval) return retval; -error_debugfs: debugfs_remove_recursive(gb_dev.root); return retval; } @@ -1063,7 +856,6 @@ module_init(loopback_init); static void __exit loopback_exit(void) { debugfs_remove_recursive(gb_dev.root); - kfifo_free(&gb_dev.kfifo); gb_protocol_deregister(&loopback_protocol); } module_exit(loopback_exit); -- cgit v0.10.2 From 1cacb456fd6b5fd99f0274bef2b2d04b5f259392 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 3 Dec 2015 17:29:00 +0100 Subject: greybus: svc: flush workqueue at connection exit Make sure to flush the workqueue from hotplug and hotunplug events when the svc connection is tore down. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index af41e8e4..f65aba6 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -709,6 +709,8 @@ static void gb_svc_connection_exit(struct gb_connection *connection) if (device_is_registered(&svc->dev)) device_del(&svc->dev); + flush_workqueue(svc->wq); + connection->hd->svc = NULL; connection->private = NULL; -- cgit v0.10.2 From f0960d05f5ece96a7b2539e0adb92bfbfc83bf3e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 3 Dec 2015 19:18:02 +0100 Subject: greybus: core: add bus id to uevents Add the bus id to all greybus uevents. This is needed to identify devices that are being removed (e.g. at hot-unplug). Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 9dcb1bf..3d8b7ef 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -77,7 +77,7 @@ static int greybus_module_match(struct device *dev, struct device_driver *drv) static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) { - struct gb_host_device *hd = NULL; + struct gb_host_device *hd; struct gb_interface *intf = NULL; struct gb_bundle *bundle = NULL; struct gb_svc *svc = NULL; @@ -86,16 +86,22 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) hd = to_gb_host_device(dev); } else if (is_gb_interface(dev)) { intf = to_gb_interface(dev); + hd = intf->hd; } else if (is_gb_bundle(dev)) { bundle = to_gb_bundle(dev); intf = bundle->intf; + hd = intf->hd; } else if (is_gb_svc(dev)) { svc = to_gb_svc(dev); + hd = svc->hd; } else { dev_WARN(dev, "uevent for unknown greybus device \"type\"!\n"); return -EINVAL; } + if (add_uevent_var(env, "BUS=%u", hd->bus_id)) + return -ENOMEM; + if (bundle) { // FIXME // add a uevent that can "load" a bundle type @@ -104,10 +110,6 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) return 0; } - // FIXME - // "just" a module, be vague here, nothing binds to a module except - // the greybus core, so there's not much, if anything, we need to - // advertise. return 0; } diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index f65aba6..7037125 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -695,6 +695,7 @@ static int gb_svc_connection_init(struct gb_connection *connection) ida_init(&svc->device_id_map); svc->state = GB_SVC_STATE_RESET; svc->connection = connection; + svc->hd = hd; connection->private = svc; hd->svc = svc; diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index 3acfa07..ca0f71d 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -19,6 +19,7 @@ enum gb_svc_state { struct gb_svc { struct device dev; + struct gb_host_device *hd; struct gb_connection *connection; enum gb_svc_state state; struct ida device_id_map; -- cgit v0.10.2 From c5e6b05ce4a18e7d6b73be0579c0698c8cc31b6c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 3 Dec 2015 19:18:04 +0100 Subject: greybus: core: add interface id to interface and bundle uevents Add the interface id to interface and bundle uevents. This is needed to identify interfaces that are being removed (e.g. at hot-unplug). Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 3d8b7ef..4ec7988 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -102,6 +102,11 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) if (add_uevent_var(env, "BUS=%u", hd->bus_id)) return -ENOMEM; + if (intf) { + if (add_uevent_var(env, "INTERFACE=%u", intf->interface_id)) + return -ENOMEM; + } + if (bundle) { // FIXME // add a uevent that can "load" a bundle type -- cgit v0.10.2 From c29c016f7e41404aa7288aad8088162cac291594 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 4 Dec 2015 10:44:24 +0100 Subject: greybus: core: add bundle id to bundle uevents Add the bundle id to bundle uevents. This is needed to identify bundles that are being removed (e.g. at hot-unplug). Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 4ec7988..209e1cd 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -112,7 +112,9 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) // add a uevent that can "load" a bundle type // This is what we need to bind a driver to so use the info // in gmod here as well - return 0; + + if (add_uevent_var(env, "BUNDLE=%u", bundle->id)) + return -ENOMEM; } return 0; -- cgit v0.10.2 From c5b6df9c8dbe0329e154410e9d39526ab01c0b51 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 4 Dec 2015 21:30:07 +0530 Subject: greybus: Documentation: Arrange entries in alphabetical order The order of entries in sysfs-bus-greybus file doesn't match the order files/directories in sysfs on a real board. More specifically, N-svc comes at last and ap_interface_id comes before endo_id within the svc. Fix that. Reviewed-by: Johan Hovold Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 9a6bbc3..a0363bf 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -6,46 +6,6 @@ Description: The "root" greybus device for the Greybus device tree, or bus, where N is a dynamically assigned 1-based id. -What: /sys/bus/greybus/device/N-svc -Date: October 2015 -KernelVersion: 4.XX -Contact: Greg Kroah-Hartman -Description: - The singleton SVC device of bus N. - -What: /sys/bus/greybus/device/N-svc/endo_id -Date: October 2015 -KernelVersion: 4.XX -Contact: Greg Kroah-Hartman -Description: - The Endo ID, which is a 2-byte hexadecimal value - defined by the Endo layout scheme, documented in - the ARA Module Developer Kit. - -What: /sys/bus/greybus/device/N-svc/ap_intf_id -Date: October 2015 -KernelVersion: 4.XX -Contact: Greg Kroah-Hartman -Description: - The AP interface ID, a 1-byte non-zero integer which - defines the position of the AP module on the frame. - The interface positions are defined in the ARA - Module Developer Kit. - -What: /sys/bus/greybus/device/N-svc/unique_id -Date: October 2015 -KernelVersion: 4.XX -Contact: Greg Kroah-Hartman -Description: - The unique ID, or serial number, of the SVC device - -What: /sys/bus/greybus/device/N-svc/version -Date: October 2015 -KernelVersion: 4.XX -Contact: Greg Kroah-Hartman -Description: - The version number of the firmware in the SVC device. - What: /sys/bus/greybus/device/N-I Date: October 2015 KernelVersion: 4.XX @@ -123,3 +83,43 @@ Description: process watching the file will be woken up, and the new value can be read. It's a "poor-man's IPC", yes, but simplifies the Android userspace code immensely. + +What: /sys/bus/greybus/device/N-svc +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The singleton SVC device of bus N. + +What: /sys/bus/greybus/device/N-svc/ap_intf_id +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The AP interface ID, a 1-byte non-zero integer which + defines the position of the AP module on the frame. + The interface positions are defined in the ARA + Module Developer Kit. + +What: /sys/bus/greybus/device/N-svc/endo_id +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The Endo ID, which is a 2-byte hexadecimal value + defined by the Endo layout scheme, documented in + the ARA Module Developer Kit. + +What: /sys/bus/greybus/device/N-svc/unique_id +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The unique ID, or serial number, of the SVC device + +What: /sys/bus/greybus/device/N-svc/version +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + The version number of the firmware in the SVC device. -- cgit v0.10.2 From 4aac6c5a144921448237d2a2bff50d4fba0b0faf Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 4 Dec 2015 21:30:08 +0530 Subject: greybus: svc: Use -EIO instead of -EINVAL for unipro errors -EIO fits better here, rather than -EINVAL as the arguments to the routine itself are valid, just that we failed while doing unipro transfers. Suggested-by: Johan Hovold Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 7037125..220aed0 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -94,7 +94,7 @@ int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, if (result) { dev_err(&svc->dev, "UniPro error while getting DME attribute (%hhu %hx %hu): %hu\n", intf_id, attr, selector, result); - return -EINVAL; + return -EIO; } if (value) @@ -130,7 +130,7 @@ int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, if (result) { dev_err(&svc->dev, "UniPro error while setting DME attribute (%hhu %hx %hu %u): %hu\n", intf_id, attr, selector, value, result); - return -EINVAL; + return -EIO; } return 0; -- cgit v0.10.2 From 2f3db927cdf7627aa5359ff46c80ab72f7971980 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 4 Dec 2015 21:30:09 +0530 Subject: greybus: don't use %h and %hh for printing short and char variables Because the width of our fields is already known, we can use %0Nx (for hex) to print N bytes and %u (for unsigned decimal), instead of using %h and %hh, which isn't that readable. This patch makes following changes: - s/%hx/%04x - s/%04hx/%04x - s/%hhx/%02x - s/%02hhx/%02x - s/%hhu/%u - s/%hu/%u - s/%x/%02x for u8 value (only at a single place) Suggested-by: Johan Hovold Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 3df7d5f..97a8195 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -128,7 +128,7 @@ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, * the interface bundle list locked here. */ if (gb_bundle_find(intf, bundle_id)) { - pr_err("duplicate bundle id 0x%02hhx\n", bundle_id); + pr_err("duplicate bundle id 0x%02x\n", bundle_id); return NULL; } @@ -152,7 +152,7 @@ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, retval = device_add(&bundle->dev); if (retval) { - pr_err("failed to add bundle device for id 0x%02hhx\n", + pr_err("failed to add bundle device for id 0x%02x\n", bundle_id); put_device(&bundle->dev); return NULL; diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 2b07846..674e9a8 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -89,7 +89,7 @@ static void gb_connection_init_name(struct gb_connection *connection) } snprintf(connection->name, sizeof(connection->name), - "%hu/%hhu:%hu", hd_cport_id, intf_id, cport_id); + "%u/%u:%u", hd_cport_id, intf_id, cport_id); } /* @@ -129,7 +129,7 @@ gb_connection_create(struct gb_host_device *hd, int hd_cport_id, * about holding the connection lock. */ if (bundle && gb_connection_intf_find(bundle->intf, cport_id)) { - dev_err(&bundle->dev, "cport 0x%04hx already connected\n", + dev_err(&bundle->dev, "cport 0x%04x already connected\n", cport_id); return NULL; } @@ -534,7 +534,7 @@ int gb_connection_bind_protocol(struct gb_connection *connection) connection->minor); if (!protocol) { dev_warn(&connection->hd->dev, - "protocol 0x%02hhx version %hhu.%hhu not found\n", + "protocol 0x%02x version %u.%u not found\n", connection->protocol_id, connection->major, connection->minor); return 0; diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 0eb9645..ed22b6c 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -442,7 +442,7 @@ static int cport_reset(struct gb_host_device *hd, u16 cport_id) USB_RECIP_INTERFACE, cport_id, 0, NULL, 0, ES2_TIMEOUT); if (retval < 0) { - dev_err(&udev->dev, "failed to reset cport %hu: %d\n", cport_id, + dev_err(&udev->dev, "failed to reset cport %u: %d\n", cport_id, retval); return retval; } @@ -890,7 +890,7 @@ static int ap_probe(struct usb_interface *interface, endpoint->bEndpointAddress; } else { dev_err(&udev->dev, - "Unknown endpoint type found, address %x\n", + "Unknown endpoint type found, address %02x\n", endpoint->bEndpointAddress); } } diff --git a/drivers/staging/greybus/firmware.c b/drivers/staging/greybus/firmware.c index cd2184c..9d1739d 100644 --- a/drivers/staging/greybus/firmware.c +++ b/drivers/staging/greybus/firmware.c @@ -210,7 +210,7 @@ static int gb_firmware_request_recv(u8 type, struct gb_operation *op) return gb_firmware_ready_to_boot(op); default: dev_err(&op->connection->bundle->dev, - "unsupported request: %hhu\n", type); + "unsupported request: %u\n", type); return -EINVAL; } } diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index 2adcb1c..f45b444 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -411,7 +411,7 @@ static int gb_hid_init(struct gb_hid *ghid) // hid->bus = BUS_GREYBUS; /* Need a bustype for GREYBUS in */ /* Set HID device's name */ - snprintf(hid->name, sizeof(hid->name), "%s %04hX:%04hX", + snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", dev_name(&ghid->connection->bundle->dev), hid->vendor, hid->product); diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 8524ce1..689ebfd 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -487,7 +487,7 @@ static int gb_loopback_request_recv(u8 type, struct gb_operation *operation) return 0; default: - dev_err(dev, "unsupported request: %hhu\n", type); + dev_err(dev, "unsupported request: %u\n", type); return -EINVAL; } } diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index ea5ff86..72400e3 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -140,7 +140,7 @@ static int identify_descriptor(struct gb_interface *intf, break; case GREYBUS_TYPE_INVALID: default: - pr_err("invalid descriptor type (%hhu)\n", desc_header->type); + pr_err("invalid descriptor type (%u)\n", desc_header->type); return -EINVAL; } @@ -440,14 +440,14 @@ bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size) header = &manifest->header; manifest_size = le16_to_cpu(header->size); if (manifest_size != size) { - pr_err("manifest size mismatch (%zu != %hu)\n", + pr_err("manifest size mismatch (%zu != %u)\n", size, manifest_size); return false; } /* Validate major/minor number */ if (header->version_major > GREYBUS_VERSION_MAJOR) { - pr_err("manifest version too new (%hhu.%hhu > %hhu.%hhu)\n", + pr_err("manifest version too new (%u.%u > %u.%u)\n", header->version_major, header->version_minor, GREYBUS_VERSION_MAJOR, GREYBUS_VERSION_MINOR); return false; diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 01ad08b..ae3ada0 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -229,7 +229,7 @@ static void gb_operation_request_handle(struct gb_operation *operation) status = protocol->request_recv(operation->type, operation); } else { dev_err(&connection->hd->dev, - "%s: unexpected incoming request of type 0x%02hhx\n", + "%s: unexpected incoming request of type 0x%02x\n", connection->name, operation->type); status = -EPROTONOSUPPORT; @@ -238,7 +238,7 @@ static void gb_operation_request_handle(struct gb_operation *operation) ret = gb_operation_response_send(operation, status); if (ret) { dev_err(&connection->hd->dev, - "%s: failed to send response %d for type 0x%02hhx: %d\n", + "%s: failed to send response %d for type 0x%02x: %d\n", connection->name, status, operation->type, ret); return; } @@ -797,7 +797,7 @@ void greybus_message_sent(struct gb_host_device *hd, if (message == operation->response) { if (status) { dev_err(&connection->hd->dev, - "%s: error sending response 0x%02hhx: %d\n", + "%s: error sending response 0x%02x: %d\n", connection->name, operation->type, status); } gb_operation_put_active(operation); @@ -868,7 +868,7 @@ static void gb_connection_recv_response(struct gb_connection *connection, operation = gb_operation_find_outgoing(connection, operation_id); if (!operation) { dev_err(&connection->hd->dev, - "%s: unexpected response id 0x%04hx received\n", + "%s: unexpected response id 0x%04x received\n", connection->name, operation_id); return; } @@ -877,7 +877,7 @@ static void gb_connection_recv_response(struct gb_connection *connection, message_size = sizeof(*message->header) + message->payload_size; if (!errno && size != message_size) { dev_err(&connection->hd->dev, - "%s: malformed response 0x%02hhx received (%zu != %zu)\n", + "%s: malformed response 0x%02x received (%zu != %zu)\n", connection->name, message->header->type, size, message_size); errno = -EMSGSIZE; @@ -926,7 +926,7 @@ void gb_connection_recv(struct gb_connection *connection, msg_size = le16_to_cpu(header.size); if (size < msg_size) { dev_err(dev, - "%s: incomplete message 0x%04hx of type 0x%02hhx received (%zu < %zu)\n", + "%s: incomplete message 0x%04x of type 0x%02x received (%zu < %zu)\n", connection->name, le16_to_cpu(header.operation_id), header.type, size, msg_size); return; /* XXX Should still complete operation */ @@ -1036,7 +1036,7 @@ int gb_operation_sync_timeout(struct gb_connection *connection, int type, ret = gb_operation_request_send_sync_timeout(operation, timeout); if (ret) { dev_err(&connection->hd->dev, - "%s: synchronous operation of type 0x%02hhx failed: %d\n", + "%s: synchronous operation of type 0x%02x failed: %d\n", connection->name, type, ret); } else { if (response_size) { diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index 47b7479..aadb793 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -166,7 +166,7 @@ int gb_protocol_get_version(struct gb_connection *connection) if (response.major > connection->protocol->major) { dev_err(&connection->hd->dev, - "%s: unsupported major version (%hhu > %hhu)\n", + "%s: unsupported major version (%u > %u)\n", connection->name, response.major, connection->protocol->major); return -ENOTSUPP; @@ -176,7 +176,7 @@ int gb_protocol_get_version(struct gb_connection *connection) connection->module_minor = response.minor; dev_dbg(&connection->hd->dev, - "%s: %s (0x%02hhx) v%hhu.%hhu\n", connection->name, + "%s: %s (0x%02x) v%u.%u\n", connection->name, protocol->name, protocol->id, response.major, response.minor); return 0; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 220aed0..4514e86 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -85,14 +85,14 @@ int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, &request, sizeof(request), &response, sizeof(response)); if (ret) { - dev_err(&svc->dev, "failed to get DME attribute (%hhu %hx %hu): %d\n", + dev_err(&svc->dev, "failed to get DME attribute (%u %04x %u): %d\n", intf_id, attr, selector, ret); return ret; } result = le16_to_cpu(response.result_code); if (result) { - dev_err(&svc->dev, "UniPro error while getting DME attribute (%hhu %hx %hu): %hu\n", + dev_err(&svc->dev, "UniPro error while getting DME attribute (%u %04x %u): %u\n", intf_id, attr, selector, result); return -EIO; } @@ -121,14 +121,14 @@ int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, &request, sizeof(request), &response, sizeof(response)); if (ret) { - dev_err(&svc->dev, "failed to set DME attribute (%hhu %hx %hu %u): %d\n", + dev_err(&svc->dev, "failed to set DME attribute (%u %04x %u %u): %d\n", intf_id, attr, selector, value, ret); return ret; } result = le16_to_cpu(response.result_code); if (result) { - dev_err(&svc->dev, "UniPro error while setting DME attribute (%hhu %hx %hu %u): %hu\n", + dev_err(&svc->dev, "UniPro error while setting DME attribute (%u %04x %u %u): %u\n", intf_id, attr, selector, value, result); return -EIO; } @@ -232,7 +232,7 @@ void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, ret = gb_operation_sync(connection, GB_SVC_TYPE_CONN_DESTROY, &request, sizeof(request), NULL, 0); if (ret) { - dev_err(&svc->dev, "failed to destroy connection (%hhu:%hu %hhu:%hu): %d\n", + dev_err(&svc->dev, "failed to destroy connection (%u:%u %u:%u): %d\n", intf1_id, cport1_id, intf2_id, cport2_id, ret); } } @@ -265,7 +265,7 @@ static void gb_svc_route_destroy(struct gb_svc *svc, u8 intf1_id, u8 intf2_id) ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_ROUTE_DESTROY, &request, sizeof(request), NULL, 0); if (ret) { - dev_err(&svc->dev, "failed to destroy route (%hhu %hhu): %d\n", + dev_err(&svc->dev, "failed to destroy route (%u %u): %d\n", intf1_id, intf2_id, ret); } } @@ -287,7 +287,7 @@ static int gb_svc_version_request(struct gb_operation *op) request = op->request->payload; if (request->major > GB_SVC_VERSION_MAJOR) { - dev_warn(&svc->dev, "unsupported major version (%hhu > %hhu)\n", + dev_warn(&svc->dev, "unsupported major version (%u > %u)\n", request->major, GB_SVC_VERSION_MAJOR); return -ENOTSUPP; } @@ -380,14 +380,14 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) * Remove the interface and add it again, and let user know * about this with a print message. */ - dev_info(&svc->dev, "removing interface %hhu to add it again\n", + dev_info(&svc->dev, "removing interface %u to add it again\n", intf_id); gb_svc_intf_remove(svc, intf); } intf = gb_interface_create(hd, intf_id); if (!intf) { - dev_err(&svc->dev, "failed to create interface %hhu\n", + dev_err(&svc->dev, "failed to create interface %u\n", intf_id); return; } @@ -413,14 +413,14 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) GB_DEVICE_ID_MODULES_START, 0, GFP_KERNEL); if (device_id < 0) { ret = device_id; - dev_err(&svc->dev, "failed to allocate device id for interface %hhu: %d\n", + dev_err(&svc->dev, "failed to allocate device id for interface %u: %d\n", intf_id, ret); goto destroy_interface; } ret = gb_svc_intf_device_id(svc, intf_id, device_id); if (ret) { - dev_err(&svc->dev, "failed to set device id %hhu for interface %hhu: %d\n", + dev_err(&svc->dev, "failed to set device id %u for interface %u: %d\n", device_id, intf_id, ret); goto ida_put; } @@ -431,14 +431,14 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) ret = gb_svc_route_create(svc, svc->ap_intf_id, GB_DEVICE_ID_AP, intf_id, device_id); if (ret) { - dev_err(&svc->dev, "failed to create route to interface %hhu (device id %hhu): %d\n", + dev_err(&svc->dev, "failed to create route to interface %u (device id %u): %d\n", intf_id, device_id, ret); goto svc_id_free; } ret = gb_interface_init(intf, device_id); if (ret) { - dev_err(&svc->dev, "failed to initialize interface %hhu (device id %hhu): %d\n", + dev_err(&svc->dev, "failed to initialize interface %u (device id %u): %d\n", intf_id, device_id, ret); goto destroy_route; } @@ -474,7 +474,7 @@ static void gb_svc_process_intf_hot_unplug(struct gb_operation *operation) intf = gb_interface_find(hd, intf_id); if (!intf) { - dev_warn(&svc->dev, "could not find hot-unplug interface %hhu\n", + dev_warn(&svc->dev, "could not find hot-unplug interface %u\n", intf_id); return; } -- cgit v0.10.2 From b933fa4a40962c77254405a5274c8927f53b5074 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 4 Dec 2015 21:30:10 +0530 Subject: greybus: Prefix hexadecimal values with 0x while printing them To clearly specify the base for printed values, prefix hexadecimal values with 0x. Suggested-by: Johan Hovold Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index ed22b6c..02cd2f6 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -890,7 +890,7 @@ static int ap_probe(struct usb_interface *interface, endpoint->bEndpointAddress; } else { dev_err(&udev->dev, - "Unknown endpoint type found, address %02x\n", + "Unknown endpoint type found, address 0x%02x\n", endpoint->bEndpointAddress); } } diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index beb3574..da90937 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -398,7 +398,7 @@ static int gb_sdio_command(struct gb_sdio_host *host, struct mmc_command *cmd) cmd_flags = GB_SDIO_RSP_R3_R4; break; default: - dev_err(mmc_dev(host->mmc), "cmd flag invalid %04x\n", + dev_err(mmc_dev(host->mmc), "cmd flag invalid 0x%04x\n", mmc_resp_type(cmd)); ret = -EINVAL; goto out; @@ -418,7 +418,7 @@ static int gb_sdio_command(struct gb_sdio_host *host, struct mmc_command *cmd) cmd_type = GB_SDIO_CMD_ADTC; break; default: - dev_err(mmc_dev(host->mmc), "cmd type invalid %04x\n", + dev_err(mmc_dev(host->mmc), "cmd type invalid 0x%04x\n", mmc_cmd_type(cmd)); ret = -EINVAL; goto out; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 4514e86..5ae64d7 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -85,14 +85,14 @@ int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, &request, sizeof(request), &response, sizeof(response)); if (ret) { - dev_err(&svc->dev, "failed to get DME attribute (%u %04x %u): %d\n", + dev_err(&svc->dev, "failed to get DME attribute (%u 0x%04x %u): %d\n", intf_id, attr, selector, ret); return ret; } result = le16_to_cpu(response.result_code); if (result) { - dev_err(&svc->dev, "UniPro error while getting DME attribute (%u %04x %u): %u\n", + dev_err(&svc->dev, "UniPro error while getting DME attribute (%u 0x%04x %u): %u\n", intf_id, attr, selector, result); return -EIO; } @@ -121,14 +121,14 @@ int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, &request, sizeof(request), &response, sizeof(response)); if (ret) { - dev_err(&svc->dev, "failed to set DME attribute (%u %04x %u %u): %d\n", + dev_err(&svc->dev, "failed to set DME attribute (%u 0x%04x %u %u): %d\n", intf_id, attr, selector, value, ret); return ret; } result = le16_to_cpu(response.result_code); if (result) { - dev_err(&svc->dev, "UniPro error while setting DME attribute (%u %04x %u %u): %u\n", + dev_err(&svc->dev, "UniPro error while setting DME attribute (%u 0x%04x %u %u): %u\n", intf_id, attr, selector, value, result); return -EIO; } @@ -502,7 +502,7 @@ static void gb_svc_process_deferred_request(struct work_struct *work) gb_svc_process_intf_hot_unplug(operation); break; default: - dev_err(&svc->dev, "bad deferred request type: %02x\n", type); + dev_err(&svc->dev, "bad deferred request type: 0x%02x\n", type); } gb_operation_put(operation); diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index ec978a4..1ba8476 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -122,7 +122,7 @@ static int gb_uart_request_recv(u8 type, struct gb_operation *op) break; default: dev_err(&connection->bundle->dev, - "unsupported unsolicited request: %02x\n", type); + "unsupported unsolicited request: 0x%02x\n", type); ret = -EINVAL; } -- cgit v0.10.2 From 2e238d71edadf03bed470cf58514ee10795a806b Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 7 Dec 2015 01:59:05 +0000 Subject: greybus: loopback: Convert cross-thread mutex to spinlock while relaxing connect locks This patch converts the cross-thread mutex used to synchronize threads with respect to each other to a spinlock. This is done to enable taking of locks in the following patches while in atomic context. A small re-order of locking in connection setup/tear-down is done to minimize the amount of time spent in spinlock_irqsave(). Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 689ebfd..b65e3e5 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -39,7 +40,8 @@ struct gb_loopback_device { u32 count; size_t size_max; - struct mutex mutex; + /* We need to take a lock in atomic context */ + spinlock_t lock; struct list_head list; }; @@ -731,6 +733,7 @@ static int gb_loopback_connection_init(struct gb_connection *connection) struct gb_loopback *gb; int retval; char name[DEBUGFS_NAMELEN]; + unsigned long flags; gb = kzalloc(sizeof(*gb), GFP_KERNEL); if (!gb) @@ -739,14 +742,13 @@ static int gb_loopback_connection_init(struct gb_connection *connection) init_waitqueue_head(&gb->wq); gb_loopback_reset_stats(gb); - mutex_lock(&gb_dev.mutex); if (!gb_dev.count) { /* Calculate maximum payload */ gb_dev.size_max = gb_operation_get_payload_size_max(connection); if (gb_dev.size_max <= sizeof(struct gb_loopback_transfer_request)) { retval = -EINVAL; - goto out_sysfs; + goto out_kzalloc; } gb_dev.size_max -= sizeof(struct gb_loopback_transfer_request); } @@ -783,10 +785,12 @@ static int gb_loopback_connection_init(struct gb_connection *connection) goto out_kfifo1; } + spin_lock_irqsave(&gb_dev.lock, flags); gb_loopback_insert_id(gb); - gb_connection_latency_tag_enable(connection); gb_dev.count++; - mutex_unlock(&gb_dev.mutex); + spin_unlock_irqrestore(&gb_dev.lock, flags); + + gb_connection_latency_tag_enable(connection); return 0; out_kfifo1: @@ -798,7 +802,7 @@ out_sysfs_conn: out_sysfs: debugfs_remove(gb->file); connection->bundle->private = NULL; - mutex_unlock(&gb_dev.mutex); +out_kzalloc: kfree(gb); return retval; @@ -807,22 +811,24 @@ out_sysfs: static void gb_loopback_connection_exit(struct gb_connection *connection) { struct gb_loopback *gb = connection->bundle->private; + unsigned long flags; if (!IS_ERR_OR_NULL(gb->task)) kthread_stop(gb->task); - mutex_lock(&gb_dev.mutex); - connection->bundle->private = NULL; kfifo_free(&gb->kfifo_lat); kfifo_free(&gb->kfifo_ts); gb_connection_latency_tag_disable(connection); - gb_dev.count--; sysfs_remove_groups(&connection->bundle->dev.kobj, loopback_groups); debugfs_remove(gb->file); + + spin_lock_irqsave(&gb_dev.lock, flags); + gb_dev.count--; list_del(&gb->entry); - mutex_unlock(&gb_dev.mutex); + spin_unlock_irqrestore(&gb_dev.lock, flags); + kfree(gb); } @@ -841,7 +847,7 @@ static int loopback_init(void) int retval; INIT_LIST_HEAD(&gb_dev.list); - mutex_init(&gb_dev.mutex); + spin_lock_init(&gb_dev.lock); gb_dev.root = debugfs_create_dir("gb_loopback", NULL); retval = gb_protocol_register(&loopback_protocol); -- cgit v0.10.2 From 12927835d21127d7e528b9ed56fc334ac96db985 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 7 Dec 2015 01:59:06 +0000 Subject: greybus: loopback: Add asynchronous bi-directional support A particular ask from the firmware people for some time now has been the ability to drive multiple outstanding bi-directional operations from loopback to loopback Interfaces. This patch implments that change. The approach taken is to make a call to gb_operation_send() and have loopback capture the completion callback itself, with a parallel timer to timeout completion callbacks that take too long. The calling thread will issue each gb_operation_send() as fast as it can within the constraints of thread-safety. In order to support this addition the following new sysfs entries are created on a per-connection basis. - async Zero indicates loopback should use the traditional synchronous model i.e. gb_operation_request_send_sync(). Non-zero indicates loopback should use the new asynchronous model i.e. gb_operation_send() - requests_completed This value indicates the number of requests successfully completed. - requests_timedout This value indicates the number of requests which timed out. - timeout The number of microseconds to give an individual asynchronous request before timing that request out. - timeout_min Read-only attribute informs user-space of the minimum allowed timeout. - timeout_max Read-only attribute informs user-space of the maximum allowed timeout. Note requests_completed + requests_timedout should always equal iteration_max, once iteration_count == iteration_max. Also, at this time we support either synchronous or asynchronous operations in one set of transactions. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index b65e3e5..392f985 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -20,6 +20,7 @@ #include #include #include +#include #include @@ -43,10 +44,24 @@ struct gb_loopback_device { /* We need to take a lock in atomic context */ spinlock_t lock; struct list_head list; + struct list_head list_op_async; + wait_queue_head_t wq; }; static struct gb_loopback_device gb_dev; +struct gb_loopback_async_operation { + struct gb_loopback *gb; + struct gb_operation *operation; + struct timeval ts; + struct timer_list timer; + struct list_head entry; + struct work_struct work; + struct kref kref; + bool pending; + int (*completion)(struct gb_loopback_async_operation *op_async); +}; + struct gb_loopback { struct gb_connection *connection; @@ -66,18 +81,29 @@ struct gb_loopback { struct gb_loopback_stats gpbridge_firmware_latency; int type; + int async; u32 mask; u32 size; u32 iteration_max; u32 iteration_count; int ms_wait; u32 error; + u32 requests_completed; + u32 requests_timedout; + u32 timeout; + u32 jiffy_timeout; + u32 timeout_min; + u32 timeout_max; u32 lbid; u64 elapsed_nsecs; u32 apbridge_latency_ts; u32 gpbridge_latency_ts; }; +/* Min/max values in jiffies */ +#define GB_LOOPBACK_TIMEOUT_MIN 1 +#define GB_LOOPBACK_TIMEOUT_MAX 10000 + #define GB_LOOPBACK_FIFO_DEFAULT 8192 static unsigned kfifo_depth = GB_LOOPBACK_FIFO_DEFAULT; @@ -215,6 +241,8 @@ static void gb_loopback_check_attr(struct gb_loopback *gb, gb->ms_wait = GB_LOOPBACK_MS_WAIT_MAX; if (gb->size > gb_dev.size_max) gb->size = gb_dev.size_max; + gb->requests_timedout = 0; + gb->requests_completed = 0; gb->iteration_count = 0; gb->error = 0; @@ -230,6 +258,11 @@ static void gb_loopback_check_attr(struct gb_loopback *gb, case GB_LOOPBACK_TYPE_PING: case GB_LOOPBACK_TYPE_TRANSFER: case GB_LOOPBACK_TYPE_SINK: + gb->jiffy_timeout = usecs_to_jiffies(gb->timeout); + if (!gb->jiffy_timeout) + gb->jiffy_timeout = GB_LOOPBACK_TIMEOUT_MIN; + else if (gb->jiffy_timeout > GB_LOOPBACK_TIMEOUT_MAX) + gb->jiffy_timeout = GB_LOOPBACK_TIMEOUT_MAX; gb_loopback_reset_stats(gb); wake_up(&gb->wq); break; @@ -252,6 +285,14 @@ gb_loopback_stats_attrs(gpbridge_firmware_latency); /* Number of errors encountered during loop */ gb_loopback_ro_attr(error); +/* Number of requests successfully completed async */ +gb_loopback_ro_attr(requests_completed); +/* Number of requests timed out async */ +gb_loopback_ro_attr(requests_timedout); +/* Timeout minimum in useconds */ +gb_loopback_ro_attr(timeout_min); +/* Timeout minimum in useconds */ +gb_loopback_ro_attr(timeout_max); /* * Type of loopback message to send based on protocol type definitions @@ -270,8 +311,12 @@ gb_dev_loopback_rw_attr(ms_wait, d); gb_dev_loopback_rw_attr(iteration_max, u); /* The current index of the for (i = 0; i < iteration_max; i++) loop */ gb_dev_loopback_ro_attr(iteration_count, false); -/* A bit-mask of destination connecitons to include in the test run */ +/* A bit-mask of destination connections to include in the test run */ gb_dev_loopback_rw_attr(mask, u); +/* A flag to indicate synchronous or asynchronous operations */ +gb_dev_loopback_rw_attr(async, u); +/* Timeout of an individual asynchronous request */ +gb_dev_loopback_rw_attr(timeout, u); static struct attribute *loopback_attrs[] = { &dev_attr_latency_min.attr, @@ -295,11 +340,19 @@ static struct attribute *loopback_attrs[] = { &dev_attr_iteration_count.attr, &dev_attr_iteration_max.attr, &dev_attr_mask.attr, + &dev_attr_async.attr, &dev_attr_error.attr, + &dev_attr_requests_completed.attr, + &dev_attr_requests_timedout.attr, + &dev_attr_timeout.attr, + &dev_attr_timeout_min.attr, + &dev_attr_timeout_max.attr, NULL, }; ATTRIBUTE_GROUPS(loopback); +static void gb_loopback_calculate_stats(struct gb_loopback *gb); + static u32 gb_loopback_nsec_to_usec_latency(u64 elapsed_nsecs) { u32 lat; @@ -381,7 +434,200 @@ error: return ret; } -static int gb_loopback_sink(struct gb_loopback *gb, u32 len) +static void __gb_loopback_async_operation_destroy(struct kref *kref) +{ + struct gb_loopback_async_operation *op_async; + + op_async = container_of(kref, struct gb_loopback_async_operation, kref); + + list_del(&op_async->entry); + if (op_async->operation) + gb_operation_put(op_async->operation); + kfree(op_async); +} + +static void gb_loopback_async_operation_get(struct gb_loopback_async_operation + *op_async) +{ + kref_get(&op_async->kref); +} + +static void gb_loopback_async_operation_put(struct gb_loopback_async_operation + *op_async) +{ + unsigned long flags; + + spin_lock_irqsave(&gb_dev.lock, flags); + kref_put(&op_async->kref, __gb_loopback_async_operation_destroy); + spin_unlock_irqrestore(&gb_dev.lock, flags); +} + +static struct gb_loopback_async_operation * + gb_loopback_operation_find(u16 id) +{ + struct gb_loopback_async_operation *op_async; + bool found = false; + unsigned long flags; + + spin_lock_irqsave(&gb_dev.lock, flags); + list_for_each_entry(op_async, &gb_dev.list_op_async, entry) { + if (op_async->operation->id == id) { + gb_loopback_async_operation_get(op_async); + found = true; + break; + } + } + spin_unlock_irqrestore(&gb_dev.lock, flags); + + return found ? op_async : NULL; +} + +static void gb_loopback_async_operation_callback(struct gb_operation *operation) +{ + struct gb_loopback_async_operation *op_async; + struct gb_loopback *gb; + struct timeval te; + bool err = false; + + do_gettimeofday(&te); + op_async = gb_loopback_operation_find(operation->id); + if (!op_async) + return; + + gb = op_async->gb; + mutex_lock(&gb->mutex); + + if (!op_async->pending || gb_operation_result(operation)) { + err = true; + } else { + if (op_async->completion) + if (op_async->completion(op_async)) + err = true; + } + + if (err) { + gb->error++; + } else { + gb->requests_completed++; + gb_loopback_push_latency_ts(gb, &op_async->ts, &te); + gb->elapsed_nsecs = gb_loopback_calc_latency(&op_async->ts, + &te); + gb_loopback_calculate_stats(gb); + } + + if (op_async->pending) { + gb->iteration_count++; + op_async->pending = false; + del_timer_sync(&op_async->timer); + gb_loopback_async_operation_put(op_async); + } + mutex_unlock(&gb->mutex); + + dev_dbg(&gb->connection->bundle->dev, "complete operation %d\n", + operation->id); + + gb_loopback_async_operation_put(op_async); +} + +static void gb_loopback_async_operation_work(struct work_struct *work) +{ + struct gb_loopback *gb; + struct gb_operation *operation; + struct gb_loopback_async_operation *op_async; + + op_async = container_of(work, struct gb_loopback_async_operation, work); + if (!op_async) + return; + + gb = op_async->gb; + operation = op_async->operation; + + mutex_lock(&gb->mutex); + if (op_async->pending) { + gb->requests_timedout++; + gb->error++; + gb->iteration_count++; + op_async->pending = false; + gb_loopback_async_operation_put(op_async); + } + mutex_unlock(&gb->mutex); + + dev_dbg(&gb->connection->bundle->dev, "timeout operation %d\n", + operation->id); + + gb_operation_cancel(operation, -ETIMEDOUT); + gb_loopback_async_operation_put(op_async); +} + +static void gb_loopback_async_operation_timeout(unsigned long data) +{ + struct gb_loopback_async_operation *op_async; + u16 id = data; + + op_async = gb_loopback_operation_find(id); + if (!op_async) { + pr_err("operation %d not found - time out ?\n", id); + return; + } + schedule_work(&op_async->work); +} + +static int gb_loopback_async_operation(struct gb_loopback *gb, int type, + void *request, int request_size, + int response_size, + void *completion) +{ + struct gb_loopback_async_operation *op_async; + struct gb_operation *operation; + int ret; + unsigned long flags; + + op_async = kzalloc(sizeof(*op_async), GFP_KERNEL); + if (!op_async) + return -ENOMEM; + + INIT_WORK(&op_async->work, gb_loopback_async_operation_work); + init_timer(&op_async->timer); + kref_init(&op_async->kref); + + operation = gb_operation_create(gb->connection, type, request_size, + response_size, GFP_KERNEL); + if (!operation) { + ret = -ENOMEM; + goto error; + } + + if (request_size) + memcpy(operation->request->payload, request, request_size); + + op_async->gb = gb; + op_async->operation = operation; + op_async->completion = completion; + + spin_lock_irqsave(&gb_dev.lock, flags); + list_add_tail(&op_async->entry, &gb_dev.list_op_async); + spin_unlock_irqrestore(&gb_dev.lock, flags); + + do_gettimeofday(&op_async->ts); + op_async->pending = true; + ret = gb_operation_request_send(operation, + gb_loopback_async_operation_callback, + GFP_KERNEL); + if (ret) + goto error; + + op_async->timer.function = gb_loopback_async_operation_timeout; + op_async->timer.expires = jiffies + gb->jiffy_timeout; + op_async->timer.data = (unsigned long)operation->id; + add_timer(&op_async->timer); + + return ret; +error: + gb_loopback_async_operation_put(op_async); + return ret; +} + +static int gb_loopback_sync_sink(struct gb_loopback *gb, u32 len) { struct gb_loopback_transfer_request *request; int retval; @@ -398,7 +644,7 @@ static int gb_loopback_sink(struct gb_loopback *gb, u32 len) return retval; } -static int gb_loopback_transfer(struct gb_loopback *gb, u32 len) +static int gb_loopback_sync_transfer(struct gb_loopback *gb, u32 len) { struct gb_loopback_transfer_request *request; struct gb_loopback_transfer_response *response; @@ -440,12 +686,91 @@ gb_error: return retval; } -static int gb_loopback_ping(struct gb_loopback *gb) +static int gb_loopback_sync_ping(struct gb_loopback *gb) { return gb_loopback_operation_sync(gb, GB_LOOPBACK_TYPE_PING, NULL, 0, NULL, 0); } +static int gb_loopback_async_sink(struct gb_loopback *gb, u32 len) +{ + struct gb_loopback_transfer_request *request; + int retval; + + request = kmalloc(len + sizeof(*request), GFP_KERNEL); + if (!request) + return -ENOMEM; + + request->len = cpu_to_le32(len); + retval = gb_loopback_async_operation(gb, GB_LOOPBACK_TYPE_SINK, + request, len + sizeof(*request), + 0, NULL); + kfree(request); + return retval; +} + +static int gb_loopback_async_transfer_complete( + struct gb_loopback_async_operation *op_async) +{ + struct gb_loopback *gb; + struct gb_operation *operation; + struct gb_loopback_transfer_request *request; + struct gb_loopback_transfer_response *response; + size_t len; + int retval = 0; + + gb = op_async->gb; + operation = op_async->operation; + request = operation->request->payload; + response = operation->response->payload; + len = le32_to_cpu(request->len); + + if (memcmp(request->data, response->data, len)) { + dev_err(&gb->connection->bundle->dev, + "Loopback Data doesn't match operation id %d\n", + operation->id); + retval = -EREMOTEIO; + } else { + gb->apbridge_latency_ts = + (u32)__le32_to_cpu(response->reserved0); + gb->gpbridge_latency_ts = + (u32)__le32_to_cpu(response->reserved1); + } + + return retval; +} + +static int gb_loopback_async_transfer(struct gb_loopback *gb, u32 len) +{ + struct gb_loopback_transfer_request *request; + int retval, response_len; + + request = kmalloc(len + sizeof(*request), GFP_KERNEL); + if (!request) + return -ENOMEM; + + memset(request->data, 0x5A, len); + + request->len = cpu_to_le32(len); + response_len = sizeof(struct gb_loopback_transfer_response); + retval = gb_loopback_async_operation(gb, GB_LOOPBACK_TYPE_TRANSFER, + request, len + sizeof(*request), + len + response_len, + gb_loopback_async_transfer_complete); + if (retval) + goto gb_error; + +gb_error: + kfree(request); + return retval; +} + +static int gb_loopback_async_ping(struct gb_loopback *gb) +{ + return gb_loopback_async_operation(gb, GB_LOOPBACK_TYPE_PING, + NULL, 0, 0, NULL); +} + static int gb_loopback_request_recv(u8 type, struct gb_operation *operation) { struct gb_connection *connection = operation->connection; @@ -512,6 +837,10 @@ static void gb_loopback_reset_stats(struct gb_loopback *gb) memcpy(&gb->gpbridge_firmware_latency, &reset, sizeof(struct gb_loopback_stats)); + /* Set values to report min/max timeout to user-space */ + gb->timeout_min = jiffies_to_usecs(GB_LOOPBACK_TIMEOUT_MIN); + gb->timeout_max = jiffies_to_usecs(GB_LOOPBACK_TIMEOUT_MAX); + /* Reset aggregate stats */ memcpy(&gb->latency, &reset, sizeof(struct gb_loopback_stats)); memcpy(&gb->throughput, &reset, sizeof(struct gb_loopback_stats)); @@ -599,23 +928,25 @@ static int gb_loopback_fn(void *data) int ms_wait = 0; int type; u32 size; + u32 send_count = 0; struct gb_loopback *gb = data; while (1) { if (!gb->type) wait_event_interruptible(gb->wq, gb->type || kthread_should_stop()); + if (kthread_should_stop()) break; mutex_lock(&gb->mutex); - sysfs_notify(&gb->connection->bundle->dev.kobj, NULL, "iteration_count"); /* Optionally terminate */ - if (gb->iteration_count == gb->iteration_max) { + if (send_count == gb->iteration_max) { gb->type = 0; + send_count = 0; mutex_unlock(&gb->mutex); continue; } @@ -625,19 +956,33 @@ static int gb_loopback_fn(void *data) mutex_unlock(&gb->mutex); /* Else operations to perform */ - if (type == GB_LOOPBACK_TYPE_PING) - error = gb_loopback_ping(gb); - else if (type == GB_LOOPBACK_TYPE_TRANSFER) - error = gb_loopback_transfer(gb, size); - else if (type == GB_LOOPBACK_TYPE_SINK) - error = gb_loopback_sink(gb, size); - - if (error) - gb->error++; - - gb_loopback_calculate_stats(gb); - gb->iteration_count++; - + if (gb->async) { + if (type == GB_LOOPBACK_TYPE_PING) { + error = gb_loopback_async_ping(gb); + gb_loopback_calculate_stats(gb); + } else if (type == GB_LOOPBACK_TYPE_TRANSFER) { + error = gb_loopback_async_transfer(gb, size); + } else if (type == GB_LOOPBACK_TYPE_SINK) { + error = gb_loopback_async_sink(gb, size); + } + + if (error) + gb->error++; + } else { + /* We are effectively single threaded here */ + if (type == GB_LOOPBACK_TYPE_PING) + error = gb_loopback_sync_ping(gb); + else if (type == GB_LOOPBACK_TYPE_TRANSFER) + error = gb_loopback_sync_transfer(gb, size); + else if (type == GB_LOOPBACK_TYPE_SINK) + error = gb_loopback_sync_sink(gb, size); + + if (error) + gb->error++; + gb->iteration_count++; + gb_loopback_calculate_stats(gb); + } + send_count++; if (ms_wait) msleep(ms_wait); } @@ -742,6 +1087,10 @@ static int gb_loopback_connection_init(struct gb_connection *connection) init_waitqueue_head(&gb->wq); gb_loopback_reset_stats(gb); + /* Reported values to user-space for min/max timeouts */ + gb->timeout_min = jiffies_to_usecs(GB_LOOPBACK_TIMEOUT_MIN); + gb->timeout_max = jiffies_to_usecs(GB_LOOPBACK_TIMEOUT_MAX); + if (!gb_dev.count) { /* Calculate maximum payload */ gb_dev.size_max = gb_operation_get_payload_size_max(connection); @@ -847,6 +1196,7 @@ static int loopback_init(void) int retval; INIT_LIST_HEAD(&gb_dev.list); + INIT_LIST_HEAD(&gb_dev.list_op_async); spin_lock_init(&gb_dev.lock); gb_dev.root = debugfs_create_dir("gb_loopback", NULL); -- cgit v0.10.2 From b36f04fa9417c58d53b1c54bf868b9da8f73810f Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 7 Dec 2015 01:59:07 +0000 Subject: greybus: loopback: Convert thread delay to microseconds Currently the loopback code allows a delay between operations specified in milliseconds. Having added asynchronous bi-directional support to loopback its obvious that the delay value would be far more useful specified in microseconds than milliseconds. So, this patch makes the necessary conversion. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 392f985..b8297d6 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -86,7 +86,7 @@ struct gb_loopback { u32 size; u32 iteration_max; u32 iteration_count; - int ms_wait; + int us_wait; u32 error; u32 requests_completed; u32 requests_timedout; @@ -112,7 +112,7 @@ module_param(kfifo_depth, uint, 0444); /* Maximum size of any one send data buffer we support */ #define MAX_PACKET_SIZE (PAGE_SIZE * 2) -#define GB_LOOPBACK_MS_WAIT_MAX 1000 +#define GB_LOOPBACK_US_WAIT_MAX 1000000 /* interface sysfs attributes */ #define gb_loopback_ro_attr(field) \ @@ -237,8 +237,8 @@ static void gb_loopback_reset_stats(struct gb_loopback *gb); static void gb_loopback_check_attr(struct gb_loopback *gb, struct gb_bundle *bundle) { - if (gb->ms_wait > GB_LOOPBACK_MS_WAIT_MAX) - gb->ms_wait = GB_LOOPBACK_MS_WAIT_MAX; + if (gb->us_wait > GB_LOOPBACK_US_WAIT_MAX) + gb->us_wait = GB_LOOPBACK_US_WAIT_MAX; if (gb->size > gb_dev.size_max) gb->size = gb_dev.size_max; gb->requests_timedout = 0; @@ -306,7 +306,7 @@ gb_dev_loopback_rw_attr(type, d); /* Size of transfer message payload: 0-4096 bytes */ gb_dev_loopback_rw_attr(size, u); /* Time to wait between two messages: 0-1000 ms */ -gb_dev_loopback_rw_attr(ms_wait, d); +gb_dev_loopback_rw_attr(us_wait, d); /* Maximum iterations for a given operation: 1-(2^32-1), 0 implies infinite */ gb_dev_loopback_rw_attr(iteration_max, u); /* The current index of the for (i = 0; i < iteration_max; i++) loop */ @@ -336,7 +336,7 @@ static struct attribute *loopback_attrs[] = { &dev_attr_gpbridge_firmware_latency_avg.attr, &dev_attr_type.attr, &dev_attr_size.attr, - &dev_attr_ms_wait.attr, + &dev_attr_us_wait.attr, &dev_attr_iteration_count.attr, &dev_attr_iteration_max.attr, &dev_attr_mask.attr, @@ -925,7 +925,7 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb) static int gb_loopback_fn(void *data) { int error = 0; - int ms_wait = 0; + int us_wait = 0; int type; u32 size; u32 send_count = 0; @@ -951,7 +951,7 @@ static int gb_loopback_fn(void *data) continue; } size = gb->size; - ms_wait = gb->ms_wait; + us_wait = gb->us_wait; type = gb->type; mutex_unlock(&gb->mutex); @@ -983,8 +983,8 @@ static int gb_loopback_fn(void *data) gb_loopback_calculate_stats(gb); } send_count++; - if (ms_wait) - msleep(ms_wait); + if (us_wait) + udelay(us_wait); } return 0; } -- cgit v0.10.2 From f42a6891d18a156f41813e3cb924470d1e2ff9ad Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 7 Dec 2015 01:59:08 +0000 Subject: greybus: loopback: Ensure we reset stats once and once only 9445c54c ('greybus/loopback: drop bus aggregate calculation') removed the aggregation of data in-kernel but instead of dropping the reset of aggregate stastics, converted that reset into a second reset of the connection-level stats. While this doesn't result in anything bad it's also definitely a dumb thing to be doing, so, drop it now. Also ensure we reset the bridge-specific tracking variables at least once. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index b8297d6..626a841 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -837,19 +837,9 @@ static void gb_loopback_reset_stats(struct gb_loopback *gb) memcpy(&gb->gpbridge_firmware_latency, &reset, sizeof(struct gb_loopback_stats)); - /* Set values to report min/max timeout to user-space */ - gb->timeout_min = jiffies_to_usecs(GB_LOOPBACK_TIMEOUT_MIN); - gb->timeout_max = jiffies_to_usecs(GB_LOOPBACK_TIMEOUT_MAX); - - /* Reset aggregate stats */ - memcpy(&gb->latency, &reset, sizeof(struct gb_loopback_stats)); - memcpy(&gb->throughput, &reset, sizeof(struct gb_loopback_stats)); - memcpy(&gb->requests_per_second, &reset, - sizeof(struct gb_loopback_stats)); - memcpy(&gb->apbridge_unipro_latency, &reset, - sizeof(struct gb_loopback_stats)); - memcpy(&gb->gpbridge_firmware_latency, &reset, - sizeof(struct gb_loopback_stats)); + /* Should be initialized at least once per transaction set */ + gb->apbridge_latency_ts = 0; + gb->gpbridge_latency_ts = 0; } static void gb_loopback_update_stats(struct gb_loopback_stats *stats, u32 val) -- cgit v0.10.2 From b395754a8e03a3d424a93b2601f6e41a4ad59a05 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 7 Dec 2015 15:05:28 +0100 Subject: greybus: svc: add missing boot-status error message Make sure to print an error message when aborting hotplug processing due to failure to clear the interface boot status. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 5ae64d7..2a8f79e 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -393,8 +393,11 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) } ret = gb_svc_read_and_clear_module_boot_status(intf); - if (ret) + if (ret) { + dev_err(&svc->dev, "failed to clear boot status of interface %u: %d\n", + intf_id, ret); goto destroy_interface; + } intf->unipro_mfg_id = le32_to_cpu(request->data.unipro_mfg_id); intf->unipro_prod_id = le32_to_cpu(request->data.unipro_prod_id); -- cgit v0.10.2 From a2cc7404e18cb75555b14831685a0b227135bc47 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 7 Dec 2015 15:05:29 +0100 Subject: greybus: bundle: remove obsolete function prototype Remove obsolete function prototype that was left after a recent code relocation. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.h b/drivers/staging/greybus/bundle.h index 24ddd44..662c4a6 100644 --- a/drivers/staging/greybus/bundle.h +++ b/drivers/staging/greybus/bundle.h @@ -36,8 +36,4 @@ void gb_bundle_destroy(struct gb_bundle *bundle); struct gb_bundle *gb_bundle_find(struct gb_interface *intf, u8 bundle_id); void gb_bundle_bind_protocols(void); -const struct greybus_bundle_id * - gb_bundle_match_id(struct gb_bundle *bundle, - const struct greybus_bundle_id *id); - #endif /* __BUNDLE_H */ -- cgit v0.10.2 From 2d54e4db4efd244181aa6a2f54f0ec362adc9d4d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 7 Dec 2015 15:05:30 +0100 Subject: greybus: bundle: kill gb_bundle_bind_protocols Remove gb_bundle_bind_protocols() that was used to iterate over all registered bundles and bind protocols to them should a protocol become available post bundle creation. The protocol abstraction as a generic construct is going away in favour of class drivers. Connections will be setup when a class driver is probed, and driver modules can be loaded on-demand by user space based on uevents and modalias. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 97a8195..e538336 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -81,36 +81,6 @@ struct device_type greybus_bundle_type = { /* XXX This could be per-host device or per-module */ static DEFINE_SPINLOCK(gb_bundles_lock); -static int __bundle_bind_protocols(struct device *dev, void *data) -{ - struct gb_bundle *bundle; - struct gb_connection *connection; - - if (!is_gb_bundle(dev)) - return 0; - - bundle = to_gb_bundle(dev); - - list_for_each_entry(connection, &bundle->connections, bundle_links) { - gb_connection_bind_protocol(connection); - } - - return 0; -} - -/* - * Walk all bundles in the system, and see if any connections are not bound to a - * specific prototcol. If they are not, then try to find one for it and bind it - * to it. - * - * This is called after registering a new protocol. - */ -void gb_bundle_bind_protocols(void) -{ - bus_for_each_dev(&greybus_bus_type, NULL, NULL, - __bundle_bind_protocols); -} - /* * Create a gb_bundle structure to represent a discovered * bundle. Returns a pointer to the new bundle or a null diff --git a/drivers/staging/greybus/bundle.h b/drivers/staging/greybus/bundle.h index 662c4a6..70d7b9d 100644 --- a/drivers/staging/greybus/bundle.h +++ b/drivers/staging/greybus/bundle.h @@ -34,6 +34,5 @@ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, void gb_bundle_destroy(struct gb_bundle *bundle); struct gb_bundle *gb_bundle_find(struct gb_interface *intf, u8 bundle_id); -void gb_bundle_bind_protocols(void); #endif /* __BUNDLE_H */ diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 674e9a8..bf28dad 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -11,6 +11,10 @@ #include "greybus.h" + +static int gb_connection_bind_protocol(struct gb_connection *connection); + + static DEFINE_SPINLOCK(gb_connections_lock); /* This is only used at initialization time; no locking is required. */ @@ -520,7 +524,7 @@ void gb_connection_latency_tag_disable(struct gb_connection *connection) } EXPORT_SYMBOL_GPL(gb_connection_latency_tag_disable); -int gb_connection_bind_protocol(struct gb_connection *connection) +static int gb_connection_bind_protocol(struct gb_connection *connection) { struct gb_protocol *protocol; int ret; diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 8006262..77f77bf 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -66,8 +66,6 @@ static inline bool gb_connection_is_static(struct gb_connection *connection) void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id, u8 *data, size_t length); -int gb_connection_bind_protocol(struct gb_connection *connection); - void gb_connection_latency_tag_enable(struct gb_connection *connection); void gb_connection_latency_tag_disable(struct gb_connection *connection); diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index aadb793..d69f648 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -90,12 +90,6 @@ int __gb_protocol_register(struct gb_protocol *protocol, struct module *module) pr_info("Registered %s protocol.\n", protocol->name); - /* - * Go try to bind any unbound connections, as we have a - * new protocol in the system - */ - gb_bundle_bind_protocols(); - return 0; } EXPORT_SYMBOL_GPL(__gb_protocol_register); -- cgit v0.10.2 From 74c831653309872b4a514cb27f456f20a7914173 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 7 Dec 2015 15:05:31 +0100 Subject: greybus: connection: fail on missing protocol Make sure to fail properly when a protocol is missing. This prevents the connection from being created, which is fine as we currently never bind protocols post creation. This is an intermediate step in moving protocol binding to connection_init. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index bf28dad..ae8cb66 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -537,11 +537,11 @@ static int gb_connection_bind_protocol(struct gb_connection *connection) connection->major, connection->minor); if (!protocol) { - dev_warn(&connection->hd->dev, + dev_err(&connection->hd->dev, "protocol 0x%02x version %u.%u not found\n", connection->protocol_id, connection->major, connection->minor); - return 0; + return -EPROTONOSUPPORT; } connection->protocol = protocol; -- cgit v0.10.2 From 30c2de77aedeb0f576356fe152e1e22c4806d239 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 7 Dec 2015 15:05:32 +0100 Subject: greybus: connection: bind protocol at init Bind protocol at connection init. This is an intermediate step in separating connection creation and enabling. Note that the protocol is currently still unbound when the connection is destroyed. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index ae8cb66..3880360 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -13,6 +13,7 @@ static int gb_connection_bind_protocol(struct gb_connection *connection); +static int gb_connection_init(struct gb_connection *connection); static DEFINE_SPINLOCK(gb_connections_lock); @@ -192,9 +193,9 @@ gb_connection_create(struct gb_host_device *hd, int hd_cport_id, spin_unlock_irq(&gb_connections_lock); - retval = gb_connection_bind_protocol(connection); + retval = gb_connection_init(connection); if (retval) { - dev_err(&hd->dev, "%s: failed to bind protocol: %d\n", + dev_err(&hd->dev, "%s: failed to initialize connection: %d\n", connection->name, retval); gb_connection_destroy(connection); return NULL; @@ -396,9 +397,12 @@ static int gb_connection_protocol_get_version(struct gb_connection *connection) static int gb_connection_init(struct gb_connection *connection) { - struct gb_protocol *protocol = connection->protocol; int ret; + ret = gb_connection_bind_protocol(connection); + if (ret) + return ret; + ret = gb_connection_hd_cport_enable(connection); if (ret) return ret; @@ -420,7 +424,7 @@ static int gb_connection_init(struct gb_connection *connection) if (ret) goto err_disconnect; - ret = protocol->connection_init(connection); + ret = connection->protocol->connection_init(connection); if (ret) goto err_disconnect; @@ -527,7 +531,6 @@ EXPORT_SYMBOL_GPL(gb_connection_latency_tag_disable); static int gb_connection_bind_protocol(struct gb_connection *connection) { struct gb_protocol *protocol; - int ret; /* If we already have a protocol bound here, just return */ if (connection->protocol) @@ -545,12 +548,5 @@ static int gb_connection_bind_protocol(struct gb_connection *connection) } connection->protocol = protocol; - ret = gb_connection_init(connection); - if (ret) { - gb_protocol_put(protocol); - connection->protocol = NULL; - return ret; - } - return 0; } -- cgit v0.10.2 From 36173112354a4f5993d464f95b04d41e1eec10a0 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 7 Dec 2015 15:05:33 +0100 Subject: greybus: connection: unbind protocol at exit Unbind protocol at connection exit rather than when the connection is destroyed. Now a protocol is only bound while a connection is enabled. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 3880360..980244a8 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -13,6 +13,7 @@ static int gb_connection_bind_protocol(struct gb_connection *connection); +static void gb_connection_unbind_protocol(struct gb_connection *connection); static int gb_connection_init(struct gb_connection *connection); @@ -405,7 +406,7 @@ static int gb_connection_init(struct gb_connection *connection) ret = gb_connection_hd_cport_enable(connection); if (ret) - return ret; + goto err_unbind_protocol; ret = gb_connection_svc_connection_create(connection); if (ret) @@ -440,15 +441,14 @@ err_svc_destroy: gb_connection_svc_connection_destroy(connection); err_hd_cport_disable: gb_connection_hd_cport_disable(connection); +err_unbind_protocol: + gb_connection_unbind_protocol(connection); return ret; } static void gb_connection_exit(struct gb_connection *connection) { - if (!connection->protocol) - return; - spin_lock_irq(&connection->lock); if (connection->state != GB_CONNECTION_STATE_ENABLED) { spin_unlock_irq(&connection->lock); @@ -463,6 +463,7 @@ static void gb_connection_exit(struct gb_connection *connection) gb_connection_control_disconnected(connection); gb_connection_svc_connection_destroy(connection); gb_connection_hd_cport_disable(connection); + gb_connection_unbind_protocol(connection); } /* @@ -482,10 +483,6 @@ void gb_connection_destroy(struct gb_connection *connection) list_del(&connection->hd_links); spin_unlock_irq(&gb_connections_lock); - if (connection->protocol) - gb_protocol_put(connection->protocol); - connection->protocol = NULL; - id_map = &connection->hd->cport_id_map; ida_simple_remove(id_map, connection->hd_cport_id); connection->hd_cport_id = CPORT_ID_BAD; @@ -532,10 +529,6 @@ static int gb_connection_bind_protocol(struct gb_connection *connection) { struct gb_protocol *protocol; - /* If we already have a protocol bound here, just return */ - if (connection->protocol) - return 0; - protocol = gb_protocol_get(connection->protocol_id, connection->major, connection->minor); @@ -550,3 +543,12 @@ static int gb_connection_bind_protocol(struct gb_connection *connection) return 0; } + +static void gb_connection_unbind_protocol(struct gb_connection *connection) +{ + struct gb_protocol *protocol = connection->protocol; + + gb_protocol_put(protocol); + + connection->protocol = NULL; +} -- cgit v0.10.2 From 0bf1f2441979e290945f4e5af40d76582c61da1e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 7 Dec 2015 15:05:34 +0100 Subject: greybus: connection: separate connection creation and enabling Separate connection creation from enabling. This will ultimately allow connection structures to be created while parsing manifests, but the connections to not be enabled until a driver is bound. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 980244a8..c936502 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -14,7 +14,6 @@ static int gb_connection_bind_protocol(struct gb_connection *connection); static void gb_connection_unbind_protocol(struct gb_connection *connection); -static int gb_connection_init(struct gb_connection *connection); static DEFINE_SPINLOCK(gb_connections_lock); @@ -125,7 +124,6 @@ gb_connection_create(struct gb_host_device *hd, int hd_cport_id, struct gb_connection *connection; struct ida *id_map = &hd->cport_id_map; int ida_start, ida_end; - int retval; u8 major = 0; u8 minor = 1; @@ -194,14 +192,6 @@ gb_connection_create(struct gb_host_device *hd, int hd_cport_id, spin_unlock_irq(&gb_connections_lock); - retval = gb_connection_init(connection); - if (retval) { - dev_err(&hd->dev, "%s: failed to initialize connection: %d\n", - connection->name, retval); - gb_connection_destroy(connection); - return NULL; - } - return connection; err_free_connection: @@ -396,7 +386,7 @@ static int gb_connection_protocol_get_version(struct gb_connection *connection) return 0; } -static int gb_connection_init(struct gb_connection *connection) +int gb_connection_init(struct gb_connection *connection) { int ret; diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 77f77bf..329b705 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -63,6 +63,8 @@ static inline bool gb_connection_is_static(struct gb_connection *connection) return !connection->intf; } +int gb_connection_init(struct gb_connection *connection); + void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id, u8 *data, size_t length); diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index b280925..74569a3 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -124,6 +124,13 @@ int gb_hd_add(struct gb_host_device *hd) return ret; } + ret = gb_connection_init(hd->svc_connection); + if (ret) { + gb_connection_destroy(hd->svc_connection); + device_del(&hd->dev); + return ret; + } + return 0; } EXPORT_SYMBOL_GPL(gb_hd_add); diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 9ff7464..e8eed85 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -180,6 +180,12 @@ int gb_interface_init(struct gb_interface *intf, u8 device_id) return -ENOMEM; } + ret = gb_connection_init(connection); + if (ret) { + gb_connection_destroy(connection); + return ret; + } + /* Get manifest size using control protocol on CPort */ size = gb_control_get_manifest_size_operation(intf); if (size <= 0) { diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 72400e3..2d47050 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -228,6 +228,7 @@ static char *gb_string_get(struct gb_interface *intf, u8 string_id) */ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) { + struct gb_connection *connection; struct gb_interface *intf = bundle->intf; struct manifest_desc *desc; struct manifest_desc *next; @@ -235,6 +236,7 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) u8 protocol_id; u16 cport_id; u32 count = 0; + int ret; /* Set up all cport descriptors associated with this bundle */ list_for_each_entry_safe(desc, next, &intf->manifest_descs, links) { @@ -254,10 +256,18 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) /* Found one. Set up its function structure */ protocol_id = desc_cport->protocol_id; - if (!gb_connection_create_dynamic(intf, bundle, cport_id, - protocol_id)) + connection = gb_connection_create_dynamic(intf, bundle, + cport_id, + protocol_id); + if (!connection) goto exit; + ret = gb_connection_init(connection); + if (ret) { + gb_connection_destroy(connection); + goto exit; + } + count++; /* Release the cport descriptor */ -- cgit v0.10.2 From d4c80bad59dbc69a989ca2c4efbcc0fb772a713b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 7 Dec 2015 15:05:35 +0100 Subject: greybus: hd: initialise device last Initialise the struct device last when creating the host device. After device_initialize(), or rather dev_set_name(), we must use put_device to release the host device. Initialising last will allow for a simpler release callback. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index 74569a3..e38c41c 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -72,20 +72,12 @@ struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, if (!hd) return ERR_PTR(-ENOMEM); - hd->dev.parent = parent; - hd->dev.bus = &greybus_bus_type; - hd->dev.type = &greybus_hd_type; - hd->dev.dma_mask = hd->dev.parent->dma_mask; - device_initialize(&hd->dev); - ret = ida_simple_get(&gb_hd_bus_id_map, 1, 0, GFP_KERNEL); if (ret < 0) { kfree(hd); return ERR_PTR(ret); } - hd->bus_id = ret; - dev_set_name(&hd->dev, "greybus%d", hd->bus_id); hd->driver = driver; INIT_LIST_HEAD(&hd->interfaces); @@ -94,6 +86,13 @@ struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, hd->buffer_size_max = buffer_size_max; hd->num_cports = num_cports; + hd->dev.parent = parent; + hd->dev.bus = &greybus_bus_type; + hd->dev.type = &greybus_hd_type; + hd->dev.dma_mask = hd->dev.parent->dma_mask; + device_initialize(&hd->dev); + dev_set_name(&hd->dev, "greybus%d", hd->bus_id); + return hd; } EXPORT_SYMBOL_GPL(gb_hd_create); -- cgit v0.10.2 From 2c848944c14cf9c74c298b2459cc39dc3c757f25 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 7 Dec 2015 15:05:36 +0100 Subject: greybus: hd: make svc-connection life time coincide with host-device Create the svc-connection as part of the host device, and destroy it in the host-device destructor. The svc-connection is enabled when registering the host device, and disabled when the host device is deregistered. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index c936502..38604e8 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -437,7 +437,7 @@ err_unbind_protocol: return ret; } -static void gb_connection_exit(struct gb_connection *connection) +void gb_connection_exit(struct gb_connection *connection) { spin_lock_irq(&connection->lock); if (connection->state != GB_CONNECTION_STATE_ENABLED) { diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 329b705..b795b44 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -64,6 +64,7 @@ static inline bool gb_connection_is_static(struct gb_connection *connection) } int gb_connection_init(struct gb_connection *connection); +void gb_connection_exit(struct gb_connection *connection); void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id, u8 *data, size_t length); diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index e38c41c..469b31e 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -21,6 +21,8 @@ static void gb_hd_release(struct device *dev) { struct gb_host_device *hd = to_gb_host_device(dev); + if (hd->svc_connection) + gb_connection_destroy(hd->svc_connection); ida_simple_remove(&gb_hd_bus_id_map, hd->bus_id); ida_destroy(&hd->cport_id_map); kfree(hd); @@ -93,21 +95,17 @@ struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, device_initialize(&hd->dev); dev_set_name(&hd->dev, "greybus%d", hd->bus_id); - return hd; -} -EXPORT_SYMBOL_GPL(gb_hd_create); - -static int gb_hd_create_svc_connection(struct gb_host_device *hd) -{ hd->svc_connection = gb_connection_create_static(hd, GB_SVC_CPORT_ID, GREYBUS_PROTOCOL_SVC); if (!hd->svc_connection) { dev_err(&hd->dev, "failed to create svc connection\n"); - return -ENOMEM; + put_device(&hd->dev); + return ERR_PTR(-ENOMEM); } - return 0; + return hd; } +EXPORT_SYMBOL_GPL(gb_hd_create); int gb_hd_add(struct gb_host_device *hd) { @@ -117,15 +115,8 @@ int gb_hd_add(struct gb_host_device *hd) if (ret) return ret; - ret = gb_hd_create_svc_connection(hd); - if (ret) { - device_del(&hd->dev); - return ret; - } - ret = gb_connection_init(hd->svc_connection); if (ret) { - gb_connection_destroy(hd->svc_connection); device_del(&hd->dev); return ret; } @@ -138,7 +129,7 @@ void gb_hd_del(struct gb_host_device *hd) { gb_interfaces_remove(hd); - gb_connection_destroy(hd->svc_connection); + gb_connection_exit(hd->svc_connection); device_del(&hd->dev); } -- cgit v0.10.2 From 7adeaae7132e06cd760b86576b8aefd2f0feb4d1 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 7 Dec 2015 15:05:37 +0100 Subject: greybus: svc: create svc along with host device Create svc device along with host-device and move the svc-connection to the svc structure. The svc connection is enabled when registering the host device, but as the SVC protocol is currently driven by the SVC, we need to defer registration of the svc device to the connection request handler. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index 469b31e..bff6861 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -21,8 +21,8 @@ static void gb_hd_release(struct device *dev) { struct gb_host_device *hd = to_gb_host_device(dev); - if (hd->svc_connection) - gb_connection_destroy(hd->svc_connection); + if (hd->svc) + gb_svc_put(hd->svc); ida_simple_remove(&gb_hd_bus_id_map, hd->bus_id); ida_destroy(&hd->cport_id_map); kfree(hd); @@ -95,10 +95,9 @@ struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, device_initialize(&hd->dev); dev_set_name(&hd->dev, "greybus%d", hd->bus_id); - hd->svc_connection = gb_connection_create_static(hd, GB_SVC_CPORT_ID, - GREYBUS_PROTOCOL_SVC); - if (!hd->svc_connection) { - dev_err(&hd->dev, "failed to create svc connection\n"); + hd->svc = gb_svc_create(hd); + if (!hd->svc) { + dev_err(&hd->dev, "failed to create svc\n"); put_device(&hd->dev); return ERR_PTR(-ENOMEM); } @@ -115,7 +114,7 @@ int gb_hd_add(struct gb_host_device *hd) if (ret) return ret; - ret = gb_connection_init(hd->svc_connection); + ret = gb_svc_add(hd->svc); if (ret) { device_del(&hd->dev); return ret; @@ -129,7 +128,7 @@ void gb_hd_del(struct gb_host_device *hd) { gb_interfaces_remove(hd); - gb_connection_exit(hd->svc_connection); + gb_svc_del(hd->svc); device_del(&hd->dev); } diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h index 5612b48..d828129 100644 --- a/drivers/staging/greybus/hd.h +++ b/drivers/staging/greybus/hd.h @@ -41,8 +41,6 @@ struct gb_host_device { size_t buffer_size_max; struct gb_svc *svc; - struct gb_connection *svc_connection; - /* Private data for the host driver */ unsigned long hd_priv[0] __aligned(sizeof(s64)); }; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 2a8f79e..c013083 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -661,6 +661,8 @@ static void gb_svc_release(struct device *dev) { struct gb_svc *svc = to_gb_svc(dev); + if (svc->connection) + gb_connection_destroy(svc->connection); ida_destroy(&svc->device_id_map); destroy_workqueue(svc->wq); kfree(svc); @@ -671,19 +673,18 @@ struct device_type greybus_svc_type = { .release = gb_svc_release, }; -static int gb_svc_connection_init(struct gb_connection *connection) +struct gb_svc *gb_svc_create(struct gb_host_device *hd) { - struct gb_host_device *hd = connection->hd; struct gb_svc *svc; svc = kzalloc(sizeof(*svc), GFP_KERNEL); if (!svc) - return -ENOMEM; + return NULL; svc->wq = alloc_workqueue("%s:svc", WQ_UNBOUND, 1, dev_name(&hd->dev)); if (!svc->wq) { kfree(svc); - return -ENOMEM; + return NULL; } svc->dev.parent = &hd->dev; @@ -697,30 +698,71 @@ static int gb_svc_connection_init(struct gb_connection *connection) ida_init(&svc->device_id_map); svc->state = GB_SVC_STATE_RESET; - svc->connection = connection; svc->hd = hd; - connection->private = svc; - hd->svc = svc; + svc->connection = gb_connection_create_static(hd, GB_SVC_CPORT_ID, + GREYBUS_PROTOCOL_SVC); + if (!svc->connection) { + dev_err(&svc->dev, "failed to create connection\n"); + put_device(&svc->dev); + return NULL; + } + + svc->connection->private = svc; - return 0; + return svc; } -static void gb_svc_connection_exit(struct gb_connection *connection) +int gb_svc_add(struct gb_svc *svc) { - struct gb_svc *svc = connection->private; + int ret; + /* + * The SVC protocol is currently driven by the SVC, so the SVC device + * is added from the connection request handler when enough + * information has been received. + */ + ret = gb_connection_init(svc->connection); + if (ret) + return ret; + + return 0; +} + +void gb_svc_del(struct gb_svc *svc) +{ + /* + * The SVC device may have been registered from the request handler. + */ if (device_is_registered(&svc->dev)) device_del(&svc->dev); - flush_workqueue(svc->wq); + gb_connection_exit(svc->connection); - connection->hd->svc = NULL; - connection->private = NULL; + flush_workqueue(svc->wq); +} +void gb_svc_put(struct gb_svc *svc) +{ put_device(&svc->dev); } +static int gb_svc_connection_init(struct gb_connection *connection) +{ + struct gb_svc *svc = connection->private; + + dev_dbg(&svc->dev, "%s\n", __func__); + + return 0; +} + +static void gb_svc_connection_exit(struct gb_connection *connection) +{ + struct gb_svc *svc = connection->private; + + dev_dbg(&svc->dev, "%s\n", __func__); +} + static struct gb_protocol svc_protocol = { .name = "svc", .id = GREYBUS_PROTOCOL_SVC, diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index ca0f71d..b7cb7e4 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -30,6 +30,11 @@ struct gb_svc { }; #define to_gb_svc(d) container_of(d, struct gb_svc, d) +struct gb_svc *gb_svc_create(struct gb_host_device *hd); +int gb_svc_add(struct gb_svc *svc); +void gb_svc_del(struct gb_svc *svc); +void gb_svc_put(struct gb_svc *svc); + int gb_svc_intf_reset(struct gb_svc *svc, u8 intf_id); int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id, bool boot_over_unipro); -- cgit v0.10.2 From 100e90000840741b630d1a369119ccb57ea4e49c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 7 Dec 2015 15:05:38 +0100 Subject: greybus: use decimal notation for interfaces, bundles and cports Fix up the last few places where hexadecimal rather than decimal notation was used for interface, bundle and cport ids. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Reviewed-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index e538336..d7975ed 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -98,7 +98,7 @@ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, * the interface bundle list locked here. */ if (gb_bundle_find(intf, bundle_id)) { - pr_err("duplicate bundle id 0x%02x\n", bundle_id); + pr_err("duplicate bundle id %u\n", bundle_id); return NULL; } @@ -122,8 +122,7 @@ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, retval = device_add(&bundle->dev); if (retval) { - pr_err("failed to add bundle device for id 0x%02x\n", - bundle_id); + pr_err("failed to add bundle device for id %u\n", bundle_id); put_device(&bundle->dev); return NULL; } diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 38604e8..5a24dbe 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -133,7 +133,7 @@ gb_connection_create(struct gb_host_device *hd, int hd_cport_id, * about holding the connection lock. */ if (bundle && gb_connection_intf_find(bundle->intf, cport_id)) { - dev_err(&bundle->dev, "cport 0x%04x already connected\n", + dev_err(&bundle->dev, "cport %u already connected\n", cport_id); return NULL; } diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 02cd2f6..b1b6ad3 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -348,8 +348,7 @@ static int message_send(struct gb_host_device *hd, u16 cport_id, * the target CPort id before filling it in. */ if (!cport_id_valid(hd, cport_id)) { - dev_err(&udev->dev, "invalid destination cport 0x%02x\n", - cport_id); + dev_err(&udev->dev, "invalid cport %u\n", cport_id); return -EINVAL; } @@ -470,8 +469,7 @@ static int latency_tag_enable(struct gb_host_device *hd, u16 cport_id) struct usb_device *udev = es2->usb_dev; if (!cport_id_valid(hd, cport_id)) { - dev_err(&udev->dev, "invalid destination cport 0x%02x\n", - cport_id); + dev_err(&udev->dev, "invalid cport %u\n", cport_id); return -EINVAL; } @@ -494,8 +492,7 @@ static int latency_tag_disable(struct gb_host_device *hd, u16 cport_id) struct usb_device *udev = es2->usb_dev; if (!cport_id_valid(hd, cport_id)) { - dev_err(&udev->dev, "invalid destination cport 0x%02x\n", - cport_id); + dev_err(&udev->dev, "invalid cport %u\n", cport_id); return -EINVAL; } @@ -632,7 +629,7 @@ static void cport_in_callback(struct urb *urb) greybus_data_rcvd(hd, cport_id, urb->transfer_buffer, urb->actual_length); } else { - dev_err(dev, "invalid cport id 0x%02x received\n", cport_id); + dev_err(dev, "invalid cport id %u received\n", cport_id); } exit: /* put our urb back in the request pool */ diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h index 1ca0706..96c5151 100644 --- a/drivers/staging/greybus/greybus_trace.h +++ b/drivers/staging/greybus/greybus_trace.h @@ -41,7 +41,7 @@ DECLARE_EVENT_CLASS(gb_message, __entry->payload_size = message->payload_size; ), - TP_printk("greybus:%s op=%04x if_id=%04x hd_id=%04x l=%zu", + TP_printk("greybus:%s op=%04x if_id=%u hd_id=%u l=%zu", __get_str(name), __entry->op_id, __entry->intf_cport_id, __entry->hd_cport_id, __entry->payload_size) ); @@ -125,7 +125,7 @@ DECLARE_EVENT_CLASS(gb_host_device, __entry->payload_size = payload_size; ), - TP_printk("greybus:%s if_id=%04x l=%zu", __get_str(name), + TP_printk("greybus:%s if_id=%u l=%zu", __get_str(name), __entry->intf_cport_id, __entry->payload_size) ); diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 2d47050..8310f19 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -323,7 +323,7 @@ static u32 gb_manifest_parse_bundles(struct gb_interface *intf) /* Nothing else should have its class set to control class */ if (class == GREYBUS_CLASS_CONTROL) { dev_err(&intf->dev, - "bundle 0x%02x cannot use control class\n", + "bundle %u cannot use control class\n", bundle_id); goto cleanup; } -- cgit v0.10.2 From 1e6fb9a1451f01f8ea092e49f27338ef9d3c7811 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 7 Dec 2015 15:05:39 +0100 Subject: greybus: interface: remove defensive WARN_ON Remove defensive WARN_ON testing for a NULL-interface when removing an interface. Every call site has just dereferenced the interface. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index e8eed85..27215cf 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -132,9 +132,6 @@ void gb_interface_remove(struct gb_interface *intf) struct gb_bundle *bundle; struct gb_bundle *next; - if (WARN_ON(!intf)) - return; - spin_lock_irq(&gb_interfaces_lock); list_del(&intf->links); spin_unlock_irq(&gb_interfaces_lock); -- cgit v0.10.2 From 1db1b24304a064b9b4213ba1812450ac054c2c58 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 7 Dec 2015 15:05:40 +0100 Subject: greybus: bundle: kill the bundle lock Kill the bundle lock, which looked like it protected the interface bundle lists but really did not as lock-less manipulations were still made. No locking for the interface bundle list is in fact needed as bundles are created along with the interface, and the list is only used to check for duplicate bundle ids when parsing the manifest and to destroy the bundles when removing the interface itself. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index d7975ed..c2dbd24 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -65,6 +65,19 @@ static struct attribute *bundle_attrs[] = { ATTRIBUTE_GROUPS(bundle); +static struct gb_bundle *gb_bundle_find(struct gb_interface *intf, + u8 bundle_id) +{ + struct gb_bundle *bundle; + + list_for_each_entry(bundle, &intf->bundles, links) { + if (bundle->id == bundle_id) + return bundle; + } + + return NULL; +} + static void gb_bundle_release(struct device *dev) { struct gb_bundle *bundle = to_gb_bundle(dev); @@ -78,9 +91,6 @@ struct device_type greybus_bundle_type = { .release = gb_bundle_release, }; -/* XXX This could be per-host device or per-module */ -static DEFINE_SPINLOCK(gb_bundles_lock); - /* * Create a gb_bundle structure to represent a discovered * bundle. Returns a pointer to the new bundle or a null @@ -127,9 +137,7 @@ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, return NULL; } - spin_lock_irq(&gb_bundles_lock); list_add(&bundle->links, &intf->bundles); - spin_unlock_irq(&gb_bundles_lock); return bundle; } @@ -149,25 +157,10 @@ static void gb_bundle_connections_exit(struct gb_bundle *bundle) */ void gb_bundle_destroy(struct gb_bundle *bundle) { - spin_lock_irq(&gb_bundles_lock); list_del(&bundle->links); - spin_unlock_irq(&gb_bundles_lock); gb_bundle_connections_exit(bundle); device_unregister(&bundle->dev); } -struct gb_bundle *gb_bundle_find(struct gb_interface *intf, u8 bundle_id) -{ - struct gb_bundle *bundle; - spin_lock_irq(&gb_bundles_lock); - list_for_each_entry(bundle, &intf->bundles, links) - if (bundle->id == bundle_id) - goto found; - bundle = NULL; -found: - spin_unlock_irq(&gb_bundles_lock); - - return bundle; -} diff --git a/drivers/staging/greybus/bundle.h b/drivers/staging/greybus/bundle.h index 70d7b9d..eae375c 100644 --- a/drivers/staging/greybus/bundle.h +++ b/drivers/staging/greybus/bundle.h @@ -33,6 +33,4 @@ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, u8 class); void gb_bundle_destroy(struct gb_bundle *bundle); -struct gb_bundle *gb_bundle_find(struct gb_interface *intf, u8 bundle_id); - #endif /* __BUNDLE_H */ -- cgit v0.10.2 From a234792d715345ebcd684196b05ef0f7454a64cb Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 7 Dec 2015 15:05:41 +0100 Subject: greybus: bundle: use dev_err for bundle-creation errors Use dev_err to report duplicate bundle ids when creating a bundle. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index c2dbd24..5d058a9 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -108,7 +108,7 @@ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, * the interface bundle list locked here. */ if (gb_bundle_find(intf, bundle_id)) { - pr_err("duplicate bundle id %u\n", bundle_id); + dev_err(&intf->dev, "duplicate bundle id %u\n", bundle_id); return NULL; } -- cgit v0.10.2 From bdc37354aa933d299c959144487eba777e707b63 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 7 Dec 2015 15:05:42 +0100 Subject: greybus: bundle: separate connection disabling and destruction Separate bundle-connection disabling and destruction, and destroy the connections along with the bundle. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 5d058a9..0f3a00d 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -81,6 +81,13 @@ static struct gb_bundle *gb_bundle_find(struct gb_interface *intf, static void gb_bundle_release(struct device *dev) { struct gb_bundle *bundle = to_gb_bundle(dev); + struct gb_connection *connection; + struct gb_connection *tmp; + + list_for_each_entry_safe(connection, tmp, &bundle->connections, + bundle_links) { + gb_connection_destroy(connection); + } kfree(bundle->state); kfree(bundle); @@ -145,11 +152,9 @@ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, static void gb_bundle_connections_exit(struct gb_bundle *bundle) { struct gb_connection *connection; - struct gb_connection *next; - list_for_each_entry_safe(connection, next, &bundle->connections, - bundle_links) - gb_connection_destroy(connection); + list_for_each_entry(connection, &bundle->connections, bundle_links) + gb_connection_exit(connection); } /* -- cgit v0.10.2 From a7e36d0eac7fe9d8c66547ac4ec660b026ca4691 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 7 Dec 2015 15:05:43 +0100 Subject: greybus: bundle: separate bundle creation and registration Separate bundle creation and registration. Note that the bundle connections still needs to be initialised post registration as protocol drivers create child devices to the bundle. This will ultimately allow connection structures to be created while parsing manifests, but the connections to not be enabled until a driver is bound. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 0f3a00d..fb775ff 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -107,7 +107,6 @@ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, u8 class) { struct gb_bundle *bundle; - int retval; /* * Reject any attempt to reuse a bundle id. We initialize @@ -128,8 +127,6 @@ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, bundle->class = class; INIT_LIST_HEAD(&bundle->connections); - /* Build up the bundle device structures and register it with the - * driver core */ bundle->dev.parent = &intf->dev; bundle->dev.bus = &greybus_bus_type; bundle->dev.type = &greybus_bundle_type; @@ -137,18 +134,24 @@ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, device_initialize(&bundle->dev); dev_set_name(&bundle->dev, "%s.%d", dev_name(&intf->dev), bundle_id); - retval = device_add(&bundle->dev); - if (retval) { - pr_err("failed to add bundle device for id %u\n", bundle_id); - put_device(&bundle->dev); - return NULL; - } - list_add(&bundle->links, &intf->bundles); return bundle; } +int gb_bundle_add(struct gb_bundle *bundle) +{ + int ret; + + ret = device_add(&bundle->dev); + if (ret) { + dev_err(&bundle->dev, "failed to register bundle: %d\n", ret); + return ret; + } + + return 0; +} + static void gb_bundle_connections_exit(struct gb_bundle *bundle) { struct gb_connection *connection; @@ -162,10 +165,12 @@ static void gb_bundle_connections_exit(struct gb_bundle *bundle) */ void gb_bundle_destroy(struct gb_bundle *bundle) { - list_del(&bundle->links); - gb_bundle_connections_exit(bundle); - device_unregister(&bundle->dev); -} + if (device_is_registered(&bundle->dev)) + device_del(&bundle->dev); + list_del(&bundle->links); + + put_device(&bundle->dev); +} diff --git a/drivers/staging/greybus/bundle.h b/drivers/staging/greybus/bundle.h index eae375c..682ec32 100644 --- a/drivers/staging/greybus/bundle.h +++ b/drivers/staging/greybus/bundle.h @@ -31,6 +31,7 @@ struct gb_bundle { /* Greybus "private" definitions" */ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, u8 class); +int gb_bundle_add(struct gb_bundle *bundle); void gb_bundle_destroy(struct gb_bundle *bundle); #endif /* __BUNDLE_H */ diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 8310f19..5120112 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -236,7 +236,6 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) u8 protocol_id; u16 cport_id; u32 count = 0; - int ret; /* Set up all cport descriptors associated with this bundle */ list_for_each_entry_safe(desc, next, &intf->manifest_descs, links) { @@ -262,12 +261,6 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) if (!connection) goto exit; - ret = gb_connection_init(connection); - if (ret) { - gb_connection_destroy(connection); - goto exit; - } - count++; /* Release the cport descriptor */ @@ -293,12 +286,14 @@ exit: */ static u32 gb_manifest_parse_bundles(struct gb_interface *intf) { + struct gb_connection *connection; struct manifest_desc *desc; struct gb_bundle *bundle; struct gb_bundle *bundle_next; u32 count = 0; u8 bundle_id; u8 class; + int ret; while ((desc = get_next_bundle_desc(intf))) { struct greybus_descriptor_bundle *desc_bundle; @@ -354,6 +349,23 @@ static u32 gb_manifest_parse_bundles(struct gb_interface *intf) continue; } + ret = gb_bundle_add(bundle); + if (ret) { + gb_bundle_destroy(bundle); + continue; + } + + list_for_each_entry(connection, &bundle->connections, + bundle_links) { + ret = gb_connection_init(connection); + if (ret) + break; + } + if (ret) { + gb_bundle_destroy(bundle); + continue; + } + count++; } -- cgit v0.10.2 From 708d07a9ea2f32ee3cf4fcbbba8d52c42302b39b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 7 Dec 2015 15:05:44 +0100 Subject: greybus: interface: separate manifest parsing from bundle registration Separate manifest parsing, including bundle and connection creation, from bundle registration. Note that this is also needed to allow the interface to not be registered until the manifest has been parsed. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 27215cf..98a1ba1 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -162,6 +162,7 @@ void gb_interfaces_remove(struct gb_host_device *hd) */ int gb_interface_init(struct gb_interface *intf, u8 device_id) { + struct gb_bundle *bundle, *tmp; struct gb_connection *connection; int ret, size; void *manifest; @@ -215,14 +216,25 @@ int gb_interface_init(struct gb_interface *intf, u8 device_id) goto free_manifest; } - /* - * XXX - * We've successfully parsed the manifest. Now we need to - * allocate CPort Id's for connecting to the CPorts found on - * other modules. For each of these, establish a connection - * between the local and remote CPorts (including - * configuring the switch to allow them to communicate). - */ + /* Register the interface bundles. */ + list_for_each_entry_safe_reverse(bundle, tmp, &intf->bundles, links) { + ret = gb_bundle_add(bundle); + if (ret) { + gb_bundle_destroy(bundle); + continue; + } + + list_for_each_entry(connection, &bundle->connections, + bundle_links) { + ret = gb_connection_init(connection); + if (ret) + break; + } + if (ret) + gb_bundle_destroy(bundle); + } + + ret = 0; free_manifest: kfree(manifest); diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 5120112..357f9c6 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -286,14 +286,12 @@ exit: */ static u32 gb_manifest_parse_bundles(struct gb_interface *intf) { - struct gb_connection *connection; struct manifest_desc *desc; struct gb_bundle *bundle; struct gb_bundle *bundle_next; u32 count = 0; u8 bundle_id; u8 class; - int ret; while ((desc = get_next_bundle_desc(intf))) { struct greybus_descriptor_bundle *desc_bundle; @@ -349,23 +347,6 @@ static u32 gb_manifest_parse_bundles(struct gb_interface *intf) continue; } - ret = gb_bundle_add(bundle); - if (ret) { - gb_bundle_destroy(bundle); - continue; - } - - list_for_each_entry(connection, &bundle->connections, - bundle_links) { - ret = gb_connection_init(connection); - if (ret) - break; - } - if (ret) { - gb_bundle_destroy(bundle); - continue; - } - count++; } -- cgit v0.10.2 From ab66dd786b4b56875baabef7c188cff862231717 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 7 Dec 2015 15:05:45 +0100 Subject: greybus: interface: fix interface-registration race Fix race with user space when registering the interface. The interface was registered before having been fully initialised, something which could lead to user space accessing not-yet-initialised attribute values (e.g. zero vendor and product ids or empty vendor and product strings). Note that this is also needed to be able to let attribute visibility depend on manifest data (e.g. interface unlock). Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 98a1ba1..1c6a8a4 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -85,7 +85,6 @@ struct gb_interface *gb_interface_create(struct gb_host_device *hd, u8 interface_id) { struct gb_interface *intf; - int retval; intf = kzalloc(sizeof(*intf), GFP_KERNEL); if (!intf) @@ -107,21 +106,11 @@ struct gb_interface *gb_interface_create(struct gb_host_device *hd, device_initialize(&intf->dev); dev_set_name(&intf->dev, "%d-%d", hd->bus_id, interface_id); - retval = device_add(&intf->dev); - if (retval) { - pr_err("failed to add interface %u\n", interface_id); - goto free_intf; - } - spin_lock_irq(&gb_interfaces_lock); list_add(&intf->links, &hd->interfaces); spin_unlock_irq(&gb_interfaces_lock); return intf; - -free_intf: - put_device(&intf->dev); - return NULL; } /* @@ -132,17 +121,20 @@ void gb_interface_remove(struct gb_interface *intf) struct gb_bundle *bundle; struct gb_bundle *next; - spin_lock_irq(&gb_interfaces_lock); - list_del(&intf->links); - spin_unlock_irq(&gb_interfaces_lock); - list_for_each_entry_safe(bundle, next, &intf->bundles, links) gb_bundle_destroy(bundle); + if (device_is_registered(&intf->dev)) + device_del(&intf->dev); + if (intf->control) gb_connection_destroy(intf->control->connection); - device_unregister(&intf->dev); + spin_lock_irq(&gb_interfaces_lock); + list_del(&intf->links); + spin_unlock_irq(&gb_interfaces_lock); + + put_device(&intf->dev); } void gb_interfaces_remove(struct gb_host_device *hd) @@ -216,7 +208,13 @@ int gb_interface_init(struct gb_interface *intf, u8 device_id) goto free_manifest; } - /* Register the interface bundles. */ + /* Register the interface and its bundles. */ + ret = device_add(&intf->dev); + if (ret) { + dev_err(&intf->dev, "failed to register interface: %d\n", ret); + goto free_manifest; + } + list_for_each_entry_safe_reverse(bundle, tmp, &intf->bundles, links) { ret = gb_bundle_add(bundle); if (ret) { -- cgit v0.10.2 From 5626e0bf99a065d53a0f9966ee335fb0707bd005 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 7 Dec 2015 15:05:46 +0100 Subject: greybus: interface: clean up error messages Drop redundant __func__ and add missing errno values. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 1c6a8a4..85fcae7 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -179,8 +179,7 @@ int gb_interface_init(struct gb_interface *intf, u8 device_id) /* Get manifest size using control protocol on CPort */ size = gb_control_get_manifest_size_operation(intf); if (size <= 0) { - dev_err(&intf->dev, "%s: Failed to get manifest size (%d)\n", - __func__, size); + dev_err(&intf->dev, "failed to get manifest size: %d\n", size); if (size) return size; else @@ -194,7 +193,7 @@ int gb_interface_init(struct gb_interface *intf, u8 device_id) /* Get manifest using control protocol on CPort */ ret = gb_control_get_manifest_operation(intf, manifest, size); if (ret) { - dev_err(&intf->dev, "%s: Failed to get manifest\n", __func__); + dev_err(&intf->dev, "failed to get manifest: %d\n", ret); goto free_manifest; } @@ -203,7 +202,7 @@ int gb_interface_init(struct gb_interface *intf, u8 device_id) * what's in it. */ if (!gb_manifest_parse(intf, manifest, size)) { - dev_err(&intf->dev, "%s: Failed to parse manifest\n", __func__); + dev_err(&intf->dev, "failed to parse manifest\n"); ret = -EINVAL; goto free_manifest; } -- cgit v0.10.2 From a75fd8ba5c8c263d2d0341123822c769e7d95918 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 8 Dec 2015 19:54:59 +0200 Subject: greybus: es2: Reserve CPorts 16 and 17 CPorts 16 and 17 are reserved for CDSI0 and CDSI1 by the ES2 APB, make sure they won't be allocated dynamically. Signed-off-by: Laurent Pinchart Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index b1b6ad3..86972a9 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -841,6 +841,7 @@ static int ap_probe(struct usb_interface *interface, int retval = -ENOMEM; int i; int num_cports; + int cport_id; udev = usb_get_dev(interface_to_usbdev(interface)); @@ -859,6 +860,14 @@ static int ap_probe(struct usb_interface *interface, return PTR_ERR(hd); } + /* + * CPorts 16 and 17 are reserved for CDSI0 and CDSI1, make sure they + * won't be allocated dynamically. + */ + do { + cport_id = ida_simple_get(&hd->cport_id_map, 16, 18, GFP_KERNEL); + } while (cport_id > 0); + es2 = hd_to_es2(hd); es2->hd = hd; es2->usb_intf = interface; -- cgit v0.10.2 From 50014e0774b25666ebdeb537964527e0b9c95c13 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Thu, 10 Dec 2015 14:24:58 +0000 Subject: greybus: spi: move chipselect to one byte size Fixed in the specification, some values for chipselect count and index were different in size, just fix that for all reference to chipselect and move all to one byte size and remove byte order operations. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index e8c4bce..d3f957f 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -662,11 +662,11 @@ struct gb_spi_master_config_response { __le32 max_speed_hz; __le16 mode; __le16 flags; - __le16 num_chipselect; + __u8 num_chipselect; } __packed; struct gb_spi_device_config_request { - __le16 chip_select; + __u8 chip_select; } __packed; struct gb_spi_device_config_response { diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index 094d6d8..15886a2 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -20,7 +20,7 @@ struct gb_spi { u16 mode; u16 flags; u32 bits_per_word_mask; - u16 num_chipselect; + u8 num_chipselect; u32 min_speed_hz; u32 max_speed_hz; struct spi_device *spi_devices; @@ -270,7 +270,7 @@ static int gb_spi_get_master_config(struct gb_spi *spi) spi->flags = gb_spi_flags_map(flags); spi->bits_per_word_mask = le32_to_cpu(response.bits_per_word_mask); - spi->num_chipselect = le16_to_cpu(response.num_chipselect); + spi->num_chipselect = response.num_chipselect; spi->min_speed_hz = le32_to_cpu(response.min_speed_hz); spi->max_speed_hz = le32_to_cpu(response.max_speed_hz); @@ -278,7 +278,7 @@ static int gb_spi_get_master_config(struct gb_spi *spi) return 0; } -static int gb_spi_setup_device(struct gb_spi *spi, uint16_t cs) +static int gb_spi_setup_device(struct gb_spi *spi, u8 cs) { struct spi_master *master = get_master_from_spi(spi); struct gb_spi_device_config_request request; @@ -287,7 +287,7 @@ static int gb_spi_setup_device(struct gb_spi *spi, uint16_t cs) struct spi_device *spidev = &spi->spi_devices[cs]; int ret; - request.chip_select = cpu_to_le16(cs); + request.chip_select = cs; ret = gb_operation_sync(spi->connection, GB_SPI_TYPE_DEVICE_CONFIG, &request, sizeof(request), @@ -331,7 +331,7 @@ static int gb_spi_connection_init(struct gb_connection *connection) struct gb_spi *spi; struct spi_master *master; int ret; - int i; + u8 i; /* Allocate master with space for data */ master = spi_alloc_master(&connection->bundle->dev, sizeof(*spi)); -- cgit v0.10.2 From 3647a313de367e98840c4dfab491dfbeaf2cf9a4 Mon Sep 17 00:00:00 2001 From: Axel Haslam Date: Tue, 8 Dec 2015 18:26:31 +0100 Subject: greybus: loopback: remove mask attribute The mask attribute is not used on the driver anymore and can be removed. Signed-off-by: Axel Haslam Reviewed-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 626a841..6a5eee3 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -82,7 +82,6 @@ struct gb_loopback { int type; int async; - u32 mask; u32 size; u32 iteration_max; u32 iteration_count; @@ -311,8 +310,6 @@ gb_dev_loopback_rw_attr(us_wait, d); gb_dev_loopback_rw_attr(iteration_max, u); /* The current index of the for (i = 0; i < iteration_max; i++) loop */ gb_dev_loopback_ro_attr(iteration_count, false); -/* A bit-mask of destination connections to include in the test run */ -gb_dev_loopback_rw_attr(mask, u); /* A flag to indicate synchronous or asynchronous operations */ gb_dev_loopback_rw_attr(async, u); /* Timeout of an individual asynchronous request */ @@ -339,7 +336,6 @@ static struct attribute *loopback_attrs[] = { &dev_attr_us_wait.attr, &dev_attr_iteration_count.attr, &dev_attr_iteration_max.attr, - &dev_attr_mask.attr, &dev_attr_async.attr, &dev_attr_error.attr, &dev_attr_requests_completed.attr, -- cgit v0.10.2 From 079fa32ba53a205a745e75b045361beeffdfeaba Mon Sep 17 00:00:00 2001 From: Axel Haslam Date: Fri, 11 Dec 2015 11:49:45 +0100 Subject: greybus: loopback: register a struct device. Instead of having the loopback attributes in the bundle device, Add a struct device to the gb_loopback struct and register it on connection_init, deregister it at connection_exit, and move the loopback attribute group over to the new device. Use device_create_with_groups to create sysfs attributes together with device. Suggested-by: Bryan O'Donoghue Suggested-by: Johan Hovold Signed-off-by: Axel Haslam Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 6a5eee3..6837291 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -71,6 +71,7 @@ struct gb_loopback { struct mutex mutex; struct task_struct *task; struct list_head entry; + struct device *dev; wait_queue_head_t wq; /* Per connection stats */ @@ -82,6 +83,7 @@ struct gb_loopback { int type; int async; + int id; u32 size; u32 iteration_max; u32 iteration_count; @@ -99,6 +101,12 @@ struct gb_loopback { u32 gpbridge_latency_ts; }; +static struct class loopback_class = { + .name = "gb_loopback", + .owner = THIS_MODULE, +}; +static DEFINE_IDA(loopback_ida); + /* Min/max values in jiffies */ #define GB_LOOPBACK_TIMEOUT_MIN 1 #define GB_LOOPBACK_TIMEOUT_MAX 10000 @@ -119,10 +127,7 @@ static ssize_t field##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ - struct gb_bundle *bundle; \ - struct gb_loopback *gb; \ - bundle = to_gb_bundle(dev); \ - gb = bundle->private; \ + struct gb_loopback *gb = dev_get_drvdata(dev); \ return sprintf(buf, "%u\n", gb->field); \ } \ static DEVICE_ATTR_RO(field) @@ -132,10 +137,7 @@ static ssize_t name##_##field##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ - struct gb_bundle *bundle; \ - struct gb_loopback *gb; \ - bundle = to_gb_bundle(dev); \ - gb = bundle->private; \ + struct gb_loopback *gb = dev_get_drvdata(dev); \ return sprintf(buf, "%"#type"\n", gb->name.field); \ } \ static DEVICE_ATTR_RO(name##_##field) @@ -146,12 +148,10 @@ static ssize_t name##_avg_show(struct device *dev, \ char *buf) \ { \ struct gb_loopback_stats *stats; \ - struct gb_bundle *bundle; \ struct gb_loopback *gb; \ u64 avg; \ u32 count, rem; \ - bundle = to_gb_bundle(dev); \ - gb = bundle->private; \ + gb = dev_get_drvdata(dev); \ stats = &gb->name; \ count = stats->count ? stats->count : 1; \ avg = stats->sum + count / 2; /* round closest */ \ @@ -170,8 +170,7 @@ static ssize_t field##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ - struct gb_bundle *bundle = to_gb_bundle(dev); \ - struct gb_loopback *gb = bundle->private; \ + struct gb_loopback *gb = dev_get_drvdata(dev); \ return sprintf(buf, "%"#type"\n", gb->field); \ } \ static ssize_t field##_store(struct device *dev, \ @@ -180,8 +179,7 @@ static ssize_t field##_store(struct device *dev, \ size_t len) \ { \ int ret; \ - struct gb_bundle *bundle = to_gb_bundle(dev); \ - struct gb_loopback *gb = bundle->private; \ + struct gb_loopback *gb = dev_get_drvdata(dev); \ mutex_lock(&gb->mutex); \ ret = sscanf(buf, "%"#type, &gb->field); \ if (ret != 1) \ @@ -198,8 +196,7 @@ static ssize_t field##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ - struct gb_bundle *bundle = to_gb_bundle(dev); \ - struct gb_loopback *gb = bundle->private; \ + struct gb_loopback *gb = dev_get_drvdata(dev); \ return sprintf(buf, "%u\n", gb->field); \ } \ static DEVICE_ATTR_RO(field) @@ -209,8 +206,7 @@ static ssize_t field##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ - struct gb_bundle *bundle = to_gb_bundle(dev); \ - struct gb_loopback *gb = bundle->private; \ + struct gb_loopback *gb = dev_get_drvdata(dev); \ return sprintf(buf, "%"#type"\n", gb->field); \ } \ static ssize_t field##_store(struct device *dev, \ @@ -219,22 +215,20 @@ static ssize_t field##_store(struct device *dev, \ size_t len) \ { \ int ret; \ - struct gb_bundle *bundle = to_gb_bundle(dev); \ - struct gb_loopback *gb = bundle->private; \ + struct gb_loopback *gb = dev_get_drvdata(dev); \ mutex_lock(&gb->mutex); \ ret = sscanf(buf, "%"#type, &gb->field); \ if (ret != 1) \ len = -EINVAL; \ else \ - gb_loopback_check_attr(gb, bundle); \ + gb_loopback_check_attr(gb); \ mutex_unlock(&gb->mutex); \ return len; \ } \ static DEVICE_ATTR_RW(field) static void gb_loopback_reset_stats(struct gb_loopback *gb); -static void gb_loopback_check_attr(struct gb_loopback *gb, - struct gb_bundle *bundle) +static void gb_loopback_check_attr(struct gb_loopback *gb) { if (gb->us_wait > GB_LOOPBACK_US_WAIT_MAX) gb->us_wait = GB_LOOPBACK_US_WAIT_MAX; @@ -246,7 +240,7 @@ static void gb_loopback_check_attr(struct gb_loopback *gb, gb->error = 0; if (kfifo_depth < gb->iteration_max) { - dev_warn(&bundle->dev, + dev_warn(gb->dev, "cannot log bytes %u kfifo_depth %u\n", gb->iteration_max, kfifo_depth); } @@ -1062,6 +1056,7 @@ static void gb_loopback_insert_id(struct gb_loopback *gb) static int gb_loopback_connection_init(struct gb_connection *connection) { struct gb_loopback *gb; + struct device *dev; int retval; char name[DEBUGFS_NAMELEN]; unsigned long flags; @@ -1095,16 +1090,28 @@ static int gb_loopback_connection_init(struct gb_connection *connection) &gb_loopback_debugfs_latency_ops); gb->connection = connection; connection->bundle->private = gb; - retval = sysfs_create_groups(&connection->bundle->dev.kobj, - loopback_groups); - if (retval) - goto out_sysfs; + + gb->id = ida_simple_get(&loopback_ida, 0, 0, GFP_KERNEL); + if (gb->id < 0) { + retval = gb->id; + goto out_ida; + } + + dev = device_create_with_groups(&loopback_class, + &connection->bundle->dev, + MKDEV(0, 0), gb, loopback_groups, + "gb_loopback%d", gb->id); + if (IS_ERR(dev)) { + retval = PTR_ERR(dev); + goto out_dev; + } + gb->dev = dev; /* Allocate kfifo */ if (kfifo_alloc(&gb->kfifo_lat, kfifo_depth * sizeof(u32), GFP_KERNEL)) { retval = -ENOMEM; - goto out_sysfs_conn; + goto out_conn; } if (kfifo_alloc(&gb->kfifo_ts, kfifo_depth * sizeof(struct timeval) * 2, GFP_KERNEL)) { @@ -1132,9 +1139,11 @@ out_kfifo1: kfifo_free(&gb->kfifo_ts); out_kfifo0: kfifo_free(&gb->kfifo_lat); -out_sysfs_conn: - sysfs_remove_groups(&connection->bundle->dev.kobj, loopback_groups); -out_sysfs: +out_conn: + device_unregister(dev); +out_dev: + ida_simple_remove(&loopback_ida, gb->id); +out_ida: debugfs_remove(gb->file); connection->bundle->private = NULL; out_kzalloc: @@ -1155,8 +1164,6 @@ static void gb_loopback_connection_exit(struct gb_connection *connection) kfifo_free(&gb->kfifo_lat); kfifo_free(&gb->kfifo_ts); gb_connection_latency_tag_disable(connection); - sysfs_remove_groups(&connection->bundle->dev.kobj, - loopback_groups); debugfs_remove(gb->file); spin_lock_irqsave(&gb_dev.lock, flags); @@ -1164,6 +1171,9 @@ static void gb_loopback_connection_exit(struct gb_connection *connection) list_del(&gb->entry); spin_unlock_irqrestore(&gb_dev.lock, flags); + device_unregister(gb->dev); + ida_simple_remove(&loopback_ida, gb->id); + kfree(gb); } @@ -1186,10 +1196,19 @@ static int loopback_init(void) spin_lock_init(&gb_dev.lock); gb_dev.root = debugfs_create_dir("gb_loopback", NULL); + retval = class_register(&loopback_class); + if (retval) + goto err; + retval = gb_protocol_register(&loopback_protocol); - if (!retval) - return retval; + if (retval) + goto err_unregister; + + return 0; +err_unregister: + class_unregister(&loopback_class); +err: debugfs_remove_recursive(gb_dev.root); return retval; } @@ -1199,6 +1218,8 @@ static void __exit loopback_exit(void) { debugfs_remove_recursive(gb_dev.root); gb_protocol_deregister(&loopback_protocol); + class_unregister(&loopback_class); + ida_destroy(&loopback_ida); } module_exit(loopback_exit); -- cgit v0.10.2 From 578a0ab8dd02f1de4b3b0e7b227ff78ae54fa4e1 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Fri, 11 Dec 2015 13:46:50 +0000 Subject: greybus: loopback: Drop NULL check on container_of pointer container_of cannot return NULL and the pointer passed to this context uses reference counter bumped inside a spinlock, so the base pointer will be valid at this point. Suggested-by: Johan Hovold Signed-off-by: Bryan O'Donoghue Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 6837291..0828772 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -526,9 +526,6 @@ static void gb_loopback_async_operation_work(struct work_struct *work) struct gb_loopback_async_operation *op_async; op_async = container_of(work, struct gb_loopback_async_operation, work); - if (!op_async) - return; - gb = op_async->gb; operation = op_async->operation; -- cgit v0.10.2 From c7aae4e613ef471f9f785e4b85de4d46d552c86b Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Fri, 11 Dec 2015 13:46:51 +0000 Subject: greybus: loopback: Retrun -ENOMEM if operation allocation fails If operation allocation fails we should return -ENOMEM in the asynchronous operation send routine. If we don't return here then the gb_loopback_async_operation_put() later can dereference a NULL pointer if the previous gb_operation_create() failed. Reported-by: Johan Hovold Signed-off-by: Bryan O'Donoghue Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 0828772..eb6a013 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -580,8 +580,8 @@ static int gb_loopback_async_operation(struct gb_loopback *gb, int type, operation = gb_operation_create(gb->connection, type, request_size, response_size, GFP_KERNEL); if (!operation) { - ret = -ENOMEM; - goto error; + kfree(op_async); + return -ENOMEM; } if (request_size) -- cgit v0.10.2 From 36f241fff4720f205e36bda5900d4ef7b6662bd7 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Fri, 11 Dec 2015 13:46:52 +0000 Subject: greybus: loopback: Wait for all async operations to complete on exit On gb_loopback_connection_exit() we should ensure every issued asynchronous operation completes before exiting connection_exit(). This patch introduces a waitqueue with a counter which represents the number of incomplete asynchronous operations. When the counter reaches zero connection_exit() will complete. At the point which we wait for outstanding operations to complete the connection-specific loopback thread will have ceased to issue new operations. Tested with both synchronous and asynchronous operations. Reviewed-by: Johan Hovold Suggested-by: Johan Hovold Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index eb6a013..4814f94 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -73,6 +74,8 @@ struct gb_loopback { struct list_head entry; struct device *dev; wait_queue_head_t wq; + wait_queue_head_t wq_completion; + atomic_t outstanding_operations; /* Per connection stats */ struct gb_loopback_stats latency; @@ -433,6 +436,8 @@ static void __gb_loopback_async_operation_destroy(struct kref *kref) list_del(&op_async->entry); if (op_async->operation) gb_operation_put(op_async->operation); + atomic_dec(&op_async->gb->outstanding_operations); + wake_up(&op_async->gb->wq_completion); kfree(op_async); } @@ -472,6 +477,12 @@ static struct gb_loopback_async_operation * return found ? op_async : NULL; } +static void gb_loopback_async_wait_all(struct gb_loopback *gb) +{ + wait_event(gb->wq_completion, + !atomic_read(&gb->outstanding_operations)); +} + static void gb_loopback_async_operation_callback(struct gb_operation *operation) { struct gb_loopback_async_operation *op_async; @@ -597,6 +608,7 @@ static int gb_loopback_async_operation(struct gb_loopback *gb, int type, do_gettimeofday(&op_async->ts); op_async->pending = true; + atomic_inc(&gb->outstanding_operations); ret = gb_operation_request_send(operation, gb_loopback_async_operation_callback, GFP_KERNEL); @@ -1063,6 +1075,8 @@ static int gb_loopback_connection_init(struct gb_connection *connection) return -ENOMEM; init_waitqueue_head(&gb->wq); + init_waitqueue_head(&gb->wq_completion); + atomic_set(&gb->outstanding_operations, 0); gb_loopback_reset_stats(gb); /* Reported values to user-space for min/max timeouts */ @@ -1162,6 +1176,7 @@ static void gb_loopback_connection_exit(struct gb_connection *connection) kfifo_free(&gb->kfifo_ts); gb_connection_latency_tag_disable(connection); debugfs_remove(gb->file); + gb_loopback_async_wait_all(gb); spin_lock_irqsave(&gb_dev.lock, flags); gb_dev.count--; -- cgit v0.10.2 From 8e3fba55d379bb67732c878988cf9859bfea2812 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Fri, 11 Dec 2015 13:46:53 +0000 Subject: greybus: loopback: Add asynchronous backoff A specific request from the firmware people is the ability to back-off from sending more asynchronous operations once a specific number of operations are in-flight. This patch adds that ability - with a new sysfs parameter 'outstanding_operations_max' which controls the maximum number of operations that can be outstanding/in-flight at any time. When outstanding_operations_max contains a non-zero value and asynchronous operations are being used - we will back-off until the completion counter is < outstanding_operations_max. Tested in both synchronous and asynchronous mode and with gb_loopback_connection_exit() interrupting in-flight operations. Suggested-by: Johan Hovold Signed-off-by: Bryan O'Donoghue Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 4814f94..c35d227 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -98,6 +98,7 @@ struct gb_loopback { u32 jiffy_timeout; u32 timeout_min; u32 timeout_max; + u32 outstanding_operations_max; u32 lbid; u64 elapsed_nsecs; u32 apbridge_latency_ts; @@ -311,6 +312,8 @@ gb_dev_loopback_ro_attr(iteration_count, false); gb_dev_loopback_rw_attr(async, u); /* Timeout of an individual asynchronous request */ gb_dev_loopback_rw_attr(timeout, u); +/* Maximum number of in-flight operations before back-off */ +gb_dev_loopback_rw_attr(outstanding_operations_max, u); static struct attribute *loopback_attrs[] = { &dev_attr_latency_min.attr, @@ -338,6 +341,7 @@ static struct attribute *loopback_attrs[] = { &dev_attr_requests_completed.attr, &dev_attr_requests_timedout.attr, &dev_attr_timeout.attr, + &dev_attr_outstanding_operations_max.attr, &dev_attr_timeout_min.attr, &dev_attr_timeout_max.attr, NULL, @@ -911,6 +915,16 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb) gb->gpbridge_latency_ts); } +static void gb_loopback_async_wait_to_send(struct gb_loopback *gb) +{ + if (!(gb->async && gb->outstanding_operations_max)) + return; + wait_event_interruptible(gb->wq_completion, + (atomic_read(&gb->outstanding_operations) < + gb->outstanding_operations_max) || + kthread_should_stop()); +} + static int gb_loopback_fn(void *data) { int error = 0; @@ -924,7 +938,11 @@ static int gb_loopback_fn(void *data) if (!gb->type) wait_event_interruptible(gb->wq, gb->type || kthread_should_stop()); + if (kthread_should_stop()) + break; + /* Limit the maximum number of in-flight async operations */ + gb_loopback_async_wait_to_send(gb); if (kthread_should_stop()) break; -- cgit v0.10.2 From e61a2a7114bc9d87d4db2994bbe49a28f8331a3a Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 15 Dec 2015 03:18:05 +0200 Subject: greybus: Add camera protocol definition Define the camera data protocol ID and all the protocol operations data structures. Signed-off-by: Laurent Pinchart Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 947b71c..32602b1 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -35,7 +35,7 @@ enum greybus_protocol { /* 0x0a is unused */ GREYBUS_PROTOCOL_SPI = 0x0b, GREYBUS_PROTOCOL_DISPLAY = 0x0c, - GREYBUS_PROTOCOL_CAMERA = 0x0d, + GREYBUS_PROTOCOL_CAMERA_MGMT = 0x0d, GREYBUS_PROTOCOL_SENSOR = 0x0e, GREYBUS_PROTOCOL_LIGHTS = 0x0f, GREYBUS_PROTOCOL_VIBRATOR = 0x10, @@ -44,6 +44,7 @@ enum greybus_protocol { GREYBUS_PROTOCOL_AUDIO_DATA = 0x13, GREYBUS_PROTOCOL_SVC = 0x14, GREYBUS_PROTOCOL_FIRMWARE = 0x15, + GREYBUS_PROTOCOL_CAMERA_DATA = 0x16, /* ... */ GREYBUS_PROTOCOL_RAW = 0xfe, GREYBUS_PROTOCOL_VENDOR = 0xff, diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index d3f957f..f024acd 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -1100,6 +1100,77 @@ struct gb_sdio_event_request { #define GB_SDIO_WP 0x04 } __packed; +/* Camera */ + +#define GB_CAMERA_VERSION_MAJOR 0x00 +#define GB_CAMERA_VERSION_MINOR 0x01 + +/* Greybus Camera request types */ +#define GB_CAMERA_TYPE_CAPABILITIES 0x02 +#define GB_CAMERA_TYPE_CONFIGURE_STREAMS 0x03 +#define GB_CAMERA_TYPE_CAPTURE 0x04 +#define GB_CAMERA_TYPE_FLUSH 0x05 +#define GB_CAMERA_TYPE_METADATA 0x06 + +#define GB_CAMERA_MAX_STREAMS 4 +#define GB_CAMERA_MAX_SETTINGS_SIZE 8192 + +/* Greybus Camera Configure Streams request payload */ +struct gb_camera_stream_config_request { + __le16 width; + __le16 height; + __le16 format; + __le16 padding; +} __packed; + +struct gb_camera_configure_streams_request { + __le16 num_streams; + __le16 padding; + struct gb_camera_stream_config_request config[0]; +} __packed; + +/* Greybus Camera Configure Streams response payload */ +struct gb_camera_stream_config_response { + __le16 width; + __le16 height; + __le16 format; + __u8 virtual_channel; + __u8 data_type[2]; + __u8 padding[3]; + __le32 max_size; +} __packed; + +struct gb_camera_configure_streams_response { + __le16 num_streams; +#define GB_CAMERA_CONFIGURE_STREAMS_ADJUSTED 0x01 + u8 flags; + u8 padding; + struct gb_camera_stream_config_response config[0]; +} __packed; + +/* Greybus Camera Capture request payload - response has no payload */ +struct gb_camera_capture_request { + __le32 request_id; + u8 streams; + u8 padding; + __le16 num_frames; + u8 settings[0]; +} __packed; + +/* Greybus Camera Flush response payload - request has no payload */ +struct gb_camera_flush_response { + __le32 request_id; +} __packed; + +/* Greybus Camera Metadata request payload - operation has no response */ +struct gb_camera_metadata_request { + __le32 request_id; + __le16 frame_number; + __u8 stream; + __u8 padding; + u8 metadata[0]; +} __packed; + /* Lights */ #define GB_LIGHTS_VERSION_MAJOR 0x00 -- cgit v0.10.2 From 3265edaf0d70433699eece915fcca6509332c0e8 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 15 Dec 2015 03:18:06 +0200 Subject: greybus: Add driver for the camera class protocol Integration with the V4L2 camera drivers isn't available yet, a debugfs interface is exposed instead to call the camera Greybus operations. The debugfs interface will be kept for module testing purpose in order to exercise all the protocol operations with various valid and invalid parameters. Signed-off-by: Laurent Pinchart Signed-off-by: Jacopo Mondi Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index cc50482..e9e1cd0 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -30,6 +30,7 @@ gb-hid-y := hid.o gb-es2-y := es2.o gb-db3-y := db3-platform.o gb-audio-codec-y := audio-codec.o +gb-camera-y := camera.o obj-m += greybus.o obj-m += gb-phy.o @@ -42,6 +43,7 @@ obj-m += gb-raw.o obj-m += gb-es2.o obj-m += gb-db3.o obj-m += gb-audio-codec.o +obj-m += gb-camera.o KERNELVER ?= $(shell uname -r) KERNELDIR ?= /lib/modules/$(KERNELVER)/build diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c new file mode 100644 index 0000000..38b209c --- /dev/null +++ b/drivers/staging/greybus/camera.c @@ -0,0 +1,611 @@ +/* + * Greybus Camera protocol driver. + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "greybus.h" +#include "greybus_protocols.h" + +enum gb_camera_debugs_buffer_id { + GB_CAMERA_DEBUGFS_BUFFER_CAPABILITIES, + GB_CAMERA_DEBUGFS_BUFFER_STREAMS, + GB_CAMERA_DEBUGFS_BUFFER_CAPTURE, + GB_CAMERA_DEBUGFS_BUFFER_FLUSH, + GB_CAMERA_DEBUGFS_BUFFER_MAX, +}; + +struct gb_camera_debugfs_buffer { + char data[PAGE_SIZE]; + size_t length; +}; + +/** + * struct gb_camera - A Greybus Camera Device + * @connection: the greybus connection for camera control + * @data_connected: whether the data connection has been established + * @debugfs: debugfs entries for camera protocol operations testing + */ +struct gb_camera { + struct gb_connection *connection; + bool data_connected; + + struct { + struct dentry *root; + struct gb_camera_debugfs_buffer *buffers; + } debugfs; +}; + +struct gb_camera_stream_config { + unsigned int width; + unsigned int height; + unsigned int format; + unsigned int vc; + unsigned int dt[2]; + unsigned int max_size; +}; + +#define ES2_APB_CDSI0_CPORT 16 +#define ES2_APB_CDSI1_CPORT 17 + +#define GB_CAMERA_MAX_SETTINGS_SIZE 8192 + +#define gcam_dbg(gcam, format...) \ + dev_dbg(&gcam->connection->bundle->dev, format) +#define gcam_info(gcam, format...) \ + dev_info(&gcam->connection->bundle->dev, format) +#define gcam_err(gcam, format...) \ + dev_err(&gcam->connection->bundle->dev, format) + +/* ----------------------------------------------------------------------------- + * Camera Protocol Operations + */ + +static int gb_camera_configure_streams(struct gb_camera *gcam, + unsigned int nstreams, + struct gb_camera_stream_config *streams) +{ + struct gb_camera_configure_streams_request *req; + struct gb_camera_configure_streams_response *resp; + unsigned int i; + size_t req_size; + size_t resp_size; + int ret; + + if (nstreams > GB_CAMERA_MAX_STREAMS) + return -EINVAL; + + req_size = sizeof(*req) + nstreams * sizeof(req->config[0]); + resp_size = sizeof(*resp) + nstreams * sizeof(resp->config[0]); + + req = kmalloc(req_size, GFP_KERNEL); + resp = kmalloc(resp_size, GFP_KERNEL); + if (!req || !resp) { + ret = -ENOMEM; + goto done; + } + + req->num_streams = nstreams; + req->padding = 0; + + for (i = 0; i < nstreams; ++i) { + struct gb_camera_stream_config_request *cfg = &req->config[i]; + + cfg->width = streams[i].width; + cfg->height = streams[i].height; + cfg->format = streams[i].format; + cfg->padding = 0; + } + + ret = gb_operation_sync(gcam->connection, + GB_CAMERA_TYPE_CONFIGURE_STREAMS, + req, req_size, resp, resp_size); + if (ret < 0) + return ret; + + if (resp->num_streams > nstreams) { + gcam_dbg(gcam, "got #streams %u > request %u\n", + resp->num_streams, nstreams); + ret = -EIO; + goto done; + } + + if (resp->padding != 0) { + gcam_dbg(gcam, "response padding != 0"); + ret = -EIO; + goto done; + } + + for (i = 0; i < nstreams; ++i) { + struct gb_camera_stream_config_response *cfg = &resp->config[i]; + + streams[i].width = cfg->width; + streams[i].height = cfg->height; + streams[i].format = cfg->format; + streams[i].vc = cfg->virtual_channel; + streams[i].dt[0] = cfg->data_type[0]; + streams[i].dt[1] = cfg->data_type[1]; + streams[i].max_size = cfg->max_size; + + if (cfg->padding[0] || cfg->padding[1] || cfg->padding[2]) { + gcam_dbg(gcam, "stream #%u padding != 0", i); + ret = -EIO; + goto done; + } + } + + ret = resp->num_streams; + +done: + kfree(req); + kfree(resp); + return ret; +} + +static int gb_camera_capture(struct gb_camera *gcam, u32 request_id, + unsigned int streams, unsigned int num_frames, + size_t settings_size, const void *settings) +{ + struct gb_camera_capture_request *req; + size_t req_size; + + if (settings_size > GB_CAMERA_MAX_SETTINGS_SIZE) + return -EINVAL; + + req_size = sizeof(*req) + settings_size; + req = kmalloc(req_size, GFP_KERNEL); + if (!req) + return -ENOMEM; + + req->request_id = request_id; + req->streams = streams; + req->padding = 0; + req->num_frames = num_frames; + memcpy(req->settings, settings, settings_size); + + return gb_operation_sync(gcam->connection, GB_CAMERA_TYPE_CAPTURE, + req, req_size, NULL, 0); +} + +static int gb_camera_flush(struct gb_camera *gcam, u32 *request_id) +{ + struct gb_camera_flush_response resp; + int ret; + + ret = gb_operation_sync(gcam->connection, GB_CAMERA_TYPE_FLUSH, NULL, 0, + &resp, sizeof(resp)); + if (ret < 0) + return ret; + + if (request_id) + *request_id = resp.request_id; + + return 0; +} + +static int gb_camera_event_recv(u8 type, struct gb_operation *op) +{ + struct gb_camera *gcam = op->connection->private; + struct gb_camera_metadata_request *payload; + struct gb_message *request; + + if (type != GB_CAMERA_TYPE_METADATA) { + gcam_err(gcam, "Unsupported unsolicited event: %u\n", type); + return -EINVAL; + } + + request = op->request; + + if (request->payload_size < sizeof(*payload)) { + gcam_err(gcam, "Wrong event size received (%zu < %zu)\n", + request->payload_size, sizeof(*payload)); + return -EINVAL; + } + + payload = request->payload; + + gcam_dbg(gcam, "received metadata for request %u, frame %u, stream %u\n", + payload->request_id, payload->frame_number, payload->stream); + + return 0; +} + +/* ----------------------------------------------------------------------------- + * DebugFS + */ +static ssize_t gb_camera_debugfs_capabilities(struct gb_camera *gcam, + char *buf, size_t len) +{ + return len; +} + +static ssize_t gb_camera_debugfs_configure_streams(struct gb_camera *gcam, + char *buf, size_t len) +{ + struct gb_camera_debugfs_buffer *buffer = + &gcam->debugfs.buffers[GB_CAMERA_DEBUGFS_BUFFER_STREAMS]; + struct gb_camera_stream_config *streams; + unsigned int nstreams; + const char *sep = ";"; + unsigned int i; + char *token; + int ret; + + /* Retrieve number of streams to configure */ + token = strsep(&buf, sep); + if (token == NULL) + return -EINVAL; + + ret = kstrtouint(token, 10, &nstreams); + if (ret < 0) + return ret; + + if (nstreams > GB_CAMERA_MAX_STREAMS) + return -EINVAL; + + /* For each stream to configure parse width, height and format */ + streams = kzalloc(nstreams * sizeof(*streams), GFP_KERNEL); + if (!streams) + return -ENOMEM; + + for (i = 0; i < nstreams; ++i) { + struct gb_camera_stream_config *stream = &streams[i]; + + /* width */ + token = strsep(&buf, ";"); + if (token == NULL) { + ret = -EINVAL; + goto done; + } + ret = kstrtouint(token, 10, &stream->width); + if (ret < 0) + goto done; + + /* height */ + token = strsep(&buf, ";"); + if (token == NULL) + goto done; + + ret = kstrtouint(token, 10, &stream->height); + if (ret < 0) + goto done; + + /* Image format code */ + token = strsep(&buf, ";"); + if (token == NULL) + goto done; + + ret = kstrtouint(token, 16, &stream->format); + if (ret < 0) + goto done; + } + + ret = gb_camera_configure_streams(gcam, nstreams, streams); + if (ret < 0) + goto done; + + nstreams = ret; + buffer->length = sprintf(buffer->data, "%u;", nstreams); + + for (i = 0; i < nstreams; ++i) { + struct gb_camera_stream_config *stream = &streams[i]; + + buffer->length += sprintf(buffer->data + buffer->length, + "%u;%u;%u;%u;%u;%u;%u;", + stream->width, stream->height, + stream->format, stream->vc, + stream->dt[0], stream->dt[1], + stream->max_size); + } + + ret = len; + +done: + kfree(streams); + return ret; +}; + +static ssize_t gb_camera_debugfs_capture(struct gb_camera *gcam, + char *buf, size_t len) +{ + unsigned int request_id; + unsigned int streams_mask; + unsigned int num_frames; + char *token; + int ret; + + /* Request id */ + token = strsep(&buf, ";"); + if (token == NULL) + return -EINVAL; + ret = kstrtouint(token, 10, &request_id); + if (ret < 0) + return ret; + + /* Stream mask */ + token = strsep(&buf, ";"); + if (token == NULL) + return -EINVAL; + ret = kstrtouint(token, 16, &streams_mask); + if (ret < 0) + return ret; + + /* number of frames */ + token = strsep(&buf, ";"); + if (token == NULL) + return -EINVAL; + ret = kstrtouint(token, 10, &num_frames); + if (ret < 0) + return ret; + + ret = gb_camera_capture(gcam, request_id, streams_mask, num_frames, 0, + NULL); + if (ret < 0) + return ret; + + return len; +} + +static ssize_t gb_camera_debugfs_flush(struct gb_camera *gcam, + char *buf, size_t len) +{ + struct gb_camera_debugfs_buffer *buffer = + &gcam->debugfs.buffers[GB_CAMERA_DEBUGFS_BUFFER_FLUSH]; + unsigned int req_id; + int ret; + + ret = gb_camera_flush(gcam, &req_id); + if (ret < 0) + return ret; + + buffer->length = sprintf(buffer->data, "%u", req_id); + + return len; +} + +struct gb_camera_debugfs_entry { + const char *name; + unsigned int mask; + unsigned int buffer; + ssize_t (*execute)(struct gb_camera *gcam, char *buf, size_t len); +}; + +static const struct gb_camera_debugfs_entry gb_camera_debugfs_entries[] = { + { + .name = "capabilities", + .mask = S_IFREG | S_IRUGO, + .buffer = GB_CAMERA_DEBUGFS_BUFFER_CAPABILITIES, + .execute = gb_camera_debugfs_capabilities, + }, { + .name = "configure_streams", + .mask = S_IFREG | S_IRUGO | S_IWUGO, + .buffer = GB_CAMERA_DEBUGFS_BUFFER_STREAMS, + .execute = gb_camera_debugfs_configure_streams, + }, { + .name = "capture", + .mask = S_IFREG | S_IRUGO | S_IWUGO, + .buffer = GB_CAMERA_DEBUGFS_BUFFER_CAPTURE, + .execute = gb_camera_debugfs_capture, + }, { + .name = "flush", + .mask = S_IFREG | S_IRUGO | S_IWUGO, + .buffer = GB_CAMERA_DEBUGFS_BUFFER_FLUSH, + .execute = gb_camera_debugfs_flush, + }, +}; + +static ssize_t gb_camera_debugfs_read(struct file *file, char __user *buf, + size_t len, loff_t *offset) +{ + const struct gb_camera_debugfs_entry *op = file->private_data; + struct gb_camera *gcam = file->f_inode->i_private; + struct gb_camera_debugfs_buffer *buffer; + ssize_t ret; + + /* For read-only entries the operation is triggered by a read. */ + if (!(op->mask & S_IWUGO)) { + ret = op->execute(gcam, NULL, 0); + if (ret < 0) + return ret; + } + + buffer = &gcam->debugfs.buffers[op->buffer]; + + return simple_read_from_buffer(buf, len, offset, buffer->data, + buffer->length); +} + +static ssize_t gb_camera_debugfs_write(struct file *file, + const char __user *buf, size_t len, + loff_t *offset) +{ + const struct gb_camera_debugfs_entry *op = file->private_data; + struct gb_camera *gcam = file->f_inode->i_private; + ssize_t ret; + char *kbuf; + + if (len > 1024) + return -EINVAL; + + kbuf = kmalloc(len + 1, GFP_KERNEL); + if (kbuf == NULL) + return -ENOMEM; + + if (copy_from_user(kbuf, buf, len)) { + ret = -EFAULT; + goto done; + } + + kbuf[len] = '\0'; + + ret = op->execute(gcam, kbuf, len); + +done: + kfree(kbuf); + return ret; +} + +static int gb_camera_debugfs_open(struct inode *inode, struct file *file) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(gb_camera_debugfs_entries); ++i) { + const struct gb_camera_debugfs_entry *entry = + &gb_camera_debugfs_entries[i]; + + if (!strcmp(file->f_dentry->d_iname, entry->name)) { + file->private_data = (void *)entry; + break; + } + } + + return 0; +} + +static const struct file_operations gb_camera_debugfs_ops = { + .open = gb_camera_debugfs_open, + .read = gb_camera_debugfs_read, + .write = gb_camera_debugfs_write, +}; + +static int gb_camera_debugfs_init(struct gb_camera *gcam) +{ + struct gb_connection *connection = gcam->connection; + char dirname[27]; + unsigned int i; + + /* + * Create root debugfs entry and a file entry for each camera operation. + */ + snprintf(dirname, 27, "camera-%u.%u", connection->intf->interface_id, + connection->bundle->id); + + gcam->debugfs.root = debugfs_create_dir(dirname, gb_debugfs_get()); + if (IS_ERR(gcam->debugfs.root)) { + gcam_err(gcam, "debugfs root create failed (%ld)\n", + PTR_ERR(gcam->debugfs.root)); + return PTR_ERR(gcam->debugfs.root); + } + + gcam->debugfs.buffers = vmalloc(sizeof(*gcam->debugfs.buffers) * + GB_CAMERA_DEBUGFS_BUFFER_MAX); + if (!gcam->debugfs.buffers) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(gb_camera_debugfs_entries); ++i) { + const struct gb_camera_debugfs_entry *entry = + &gb_camera_debugfs_entries[i]; + struct dentry *dentry; + + gcam->debugfs.buffers[i].length = 0; + + dentry = debugfs_create_file(entry->name, entry->mask, + gcam->debugfs.root, gcam, + &gb_camera_debugfs_ops); + if (IS_ERR(dentry)) { + gcam_err(gcam, + "debugfs operation %s create failed (%ld)\n", + entry->name, PTR_ERR(gcam->debugfs.root)); + return PTR_ERR(dentry); + } + } + + return 0; +} + +static void gb_camera_debugfs_cleanup(struct gb_camera *gcam) +{ + if (gcam->debugfs.root) + debugfs_remove_recursive(gcam->debugfs.root); + + vfree(gcam->debugfs.buffers); +} + +/* ----------------------------------------------------------------------------- + * Init & Cleanup + */ + +static void gb_camera_cleanup(struct gb_camera *gcam) +{ + gb_camera_debugfs_cleanup(gcam); + + if (gcam->data_connected) { + struct gb_interface *intf = gcam->connection->intf; + struct gb_svc *svc = gcam->connection->hd->svc; + + gb_svc_connection_destroy(svc, intf->interface_id, + ES2_APB_CDSI0_CPORT, svc->ap_intf_id, + ES2_APB_CDSI1_CPORT); + } + + kfree(gcam); +} + +static int gb_camera_connection_init(struct gb_connection *connection) +{ + struct gb_svc *svc = connection->hd->svc; + struct gb_camera *gcam; + int ret; + + gcam = kzalloc(sizeof(*gcam), GFP_KERNEL); + if (!gcam) + return -ENOMEM; + + gcam->connection = connection; + connection->private = gcam; + + /* + * Create the data connection between camera module CDSI0 and APB CDS1. + * The CPort IDs are hardcoded by the ES2 bridges. + */ + ret = gb_svc_connection_create(svc, connection->intf->interface_id, + ES2_APB_CDSI0_CPORT, svc->ap_intf_id, + ES2_APB_CDSI1_CPORT, false); + if (ret < 0) + goto error; + + gcam->data_connected = true; + + ret = gb_camera_debugfs_init(gcam); + if (ret < 0) + goto error; + + return 0; + +error: + gb_camera_cleanup(gcam); + return ret; +} + +static void gb_camera_connection_exit(struct gb_connection *connection) +{ + struct gb_camera *gcam = connection->private; + + gb_camera_cleanup(gcam); +} + +static struct gb_protocol camera_protocol = { + .name = "camera", + .id = GREYBUS_PROTOCOL_CAMERA_MGMT, + .major = GB_CAMERA_VERSION_MAJOR, + .minor = GB_CAMERA_VERSION_MINOR, + .connection_init = gb_camera_connection_init, + .connection_exit = gb_camera_connection_exit, + .request_recv = gb_camera_event_recv, +}; + +gb_protocol_driver(&camera_protocol); + +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 4dda744c2a26d7ee63ceaf834bfe19ab038e4064 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 14 Dec 2015 18:33:19 -0800 Subject: greybus: Camera: remove f_dentry usage On newer kernels f_dentry is gone, so use f_path.dentry instead. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 38b209c..b7d9384 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -465,7 +465,7 @@ static int gb_camera_debugfs_open(struct inode *inode, struct file *file) const struct gb_camera_debugfs_entry *entry = &gb_camera_debugfs_entries[i]; - if (!strcmp(file->f_dentry->d_iname, entry->name)) { + if (!strcmp(file->f_path.dentry->d_iname, entry->name)) { file->private_data = (void *)entry; break; } -- cgit v0.10.2 From ed972e3a36c3402479f46f6d0218e7ef586d0d3e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 15 Dec 2015 15:51:48 +0100 Subject: greybus: es2: demote dynamic-urb error message Demote error message when needing to dynamically allocate an URB to debug level. This isn't really an error as much as a reminder of how the current es2 implementation works: It uses a fixed number of pre-allocated URBs, but allocates URBs dynamically when enough messages are sent in rapid succession to exhaust the URB pool. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 86972a9..1be4a7c 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -274,7 +274,7 @@ static struct urb *next_free_urb(struct es2_ap_dev *es2, gfp_t gfp_mask) * Crap, pool is empty, complain to the syslog and go allocate one * dynamically as we have to succeed. */ - dev_err(&es2->usb_dev->dev, + dev_dbg(&es2->usb_dev->dev, "No free CPort OUT urbs, having to dynamically allocate one!\n"); return usb_alloc_urb(0, gfp_mask); } -- cgit v0.10.2 From c634650ecc5b3db9ac4f1258387b87ff66386906 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 15 Dec 2015 15:28:56 +0100 Subject: greybus: interface: clean up control-connection handling Clean up control-connection handling by managing it through the control structure and a higher-level control interface. Also make both the control structure and connection lifetimes coincide with that of the interface. The control connection is now only enabled and disabled when the interface is initialised and removed. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index 2cc1917..9c282e4 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -59,31 +59,70 @@ int gb_control_disconnected_operation(struct gb_control *control, u16 cport_id) sizeof(request), NULL, 0); } -static int gb_control_connection_init(struct gb_connection *connection) +struct gb_control *gb_control_create(struct gb_interface *intf) { struct gb_control *control; control = kzalloc(sizeof(*control), GFP_KERNEL); if (!control) - return -ENOMEM; + return NULL; + + control->connection = gb_connection_create_dynamic(intf, NULL, + GB_CONTROL_CPORT_ID, + GREYBUS_PROTOCOL_CONTROL); + if (!control->connection) { + dev_err(&intf->dev, "failed to create control connection\n"); + kfree(control); + return NULL; + } - control->connection = connection; - connection->private = control; + control->connection->private = control; + + return control; +} + +int gb_control_enable(struct gb_control *control) +{ + int ret; - /* Set interface's control connection */ - connection->intf->control = control; + dev_dbg(&control->connection->intf->dev, "%s\n", __func__); + + ret = gb_connection_init(control->connection); + if (ret) { + dev_err(&control->connection->intf->dev, + "failed to enable control connection: %d\n", + ret); + return ret; + } return 0; } -static void gb_control_connection_exit(struct gb_connection *connection) +void gb_control_disable(struct gb_control *control) { - struct gb_control *control = connection->private; + dev_dbg(&control->connection->intf->dev, "%s\n", __func__); - connection->intf->control = NULL; + gb_connection_exit(control->connection); +} + +void gb_control_destroy(struct gb_control *control) +{ + gb_connection_destroy(control->connection); kfree(control); } +static int gb_control_connection_init(struct gb_connection *connection) +{ + dev_dbg(&connection->intf->dev, "%s\n", __func__); + + return 0; +} + +static void gb_control_connection_exit(struct gb_connection *connection) +{ + dev_dbg(&connection->intf->dev, "%s\n", __func__); +} + static struct gb_protocol control_protocol = { .name = "control", .id = GREYBUS_PROTOCOL_CONTROL, diff --git a/drivers/staging/greybus/control.h b/drivers/staging/greybus/control.h index 3248d96..da0fa66 100644 --- a/drivers/staging/greybus/control.h +++ b/drivers/staging/greybus/control.h @@ -14,6 +14,11 @@ struct gb_control { struct gb_connection *connection; }; +struct gb_control *gb_control_create(struct gb_interface *intf); +int gb_control_enable(struct gb_control *control); +void gb_control_disable(struct gb_control *control); +void gb_control_destroy(struct gb_control *control); + int gb_control_connected_operation(struct gb_control *control, u16 cport_id); int gb_control_disconnected_operation(struct gb_control *control, u16 cport_id); int gb_control_get_manifest_size_operation(struct gb_interface *intf); diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 85fcae7..aa30dc2 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -61,6 +61,9 @@ static void gb_interface_release(struct device *dev) kfree(intf->product_string); kfree(intf->vendor_string); + if (intf->control) + gb_control_destroy(intf->control); + kfree(intf); } @@ -106,6 +109,12 @@ struct gb_interface *gb_interface_create(struct gb_host_device *hd, device_initialize(&intf->dev); dev_set_name(&intf->dev, "%d-%d", hd->bus_id, interface_id); + intf->control = gb_control_create(intf); + if (!intf->control) { + put_device(&intf->dev); + return NULL; + } + spin_lock_irq(&gb_interfaces_lock); list_add(&intf->links, &hd->interfaces); spin_unlock_irq(&gb_interfaces_lock); @@ -127,8 +136,7 @@ void gb_interface_remove(struct gb_interface *intf) if (device_is_registered(&intf->dev)) device_del(&intf->dev); - if (intf->control) - gb_connection_destroy(intf->control->connection); + gb_control_disable(intf->control); spin_lock_irq(&gb_interfaces_lock); list_del(&intf->links); @@ -161,20 +169,10 @@ int gb_interface_init(struct gb_interface *intf, u8 device_id) intf->device_id = device_id; - /* Establish control CPort connection */ - connection = gb_connection_create_dynamic(intf, NULL, - GB_CONTROL_CPORT_ID, - GREYBUS_PROTOCOL_CONTROL); - if (!connection) { - dev_err(&intf->dev, "failed to create control connection\n"); - return -ENOMEM; - } - - ret = gb_connection_init(connection); - if (ret) { - gb_connection_destroy(connection); + /* Establish control connection */ + ret = gb_control_enable(intf->control); + if (ret) return ret; - } /* Get manifest size using control protocol on CPort */ size = gb_control_get_manifest_size_operation(intf); -- cgit v0.10.2 From 141af4f05435ac217b9e1fc8260b42e460997fb6 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 15 Dec 2015 15:28:57 +0100 Subject: greybus: interface: fix hot-unplug control-connection timeouts Set an interface disconnected flag when the interface has been hot-unplugged (e.g. forcibly removed or after a reboot), and use it to disable the control connection early when deregistering the interface and its bundles. This avoids a one-second (default) timeout for every enabled connection (e.g. one per bundle) at hot-unplug, something which for the default gpbridge manifest currently amounts to five seconds. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index aa30dc2..ecc64be 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -130,6 +130,9 @@ void gb_interface_remove(struct gb_interface *intf) struct gb_bundle *bundle; struct gb_bundle *next; + if (intf->disconnected) + gb_control_disable(intf->control); + list_for_each_entry_safe(bundle, next, &intf->bundles, links) gb_bundle_destroy(bundle); diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 61e9c05..ca123ce 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -35,6 +35,7 @@ struct gb_interface { /* The interface needs to boot over unipro */ bool boot_over_unipro; + bool disconnected; }; #define to_gb_interface(d) container_of(d, struct gb_interface, dev) diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index c013083..5c4ca79 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -335,9 +335,10 @@ static int gb_svc_hello(struct gb_operation *op) static void gb_svc_intf_remove(struct gb_svc *svc, struct gb_interface *intf) { u8 intf_id = intf->interface_id; - u8 device_id; + u8 device_id = intf->device_id; + + intf->disconnected = true; - device_id = intf->device_id; gb_interface_remove(intf); /* -- cgit v0.10.2 From 5fbd1a0bcb02a2fda30849539dee0b91c4009c42 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Tue, 15 Dec 2015 19:09:54 +0000 Subject: greybus: spi: rename label to undo operation Rename error path label to a more significant name related to the free operation done. Signed-off-by: Rui Miguel Silva Reported-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index 15886a2..41aa0ec 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -346,7 +346,7 @@ static int gb_spi_connection_init(struct gb_connection *connection) ret = gb_spi_init(spi); if (ret) - goto out_err; + goto out_put_master; master->bus_num = -1; /* Allow spi-core to allocate it dynamically */ master->num_chipselect = spi->num_chipselect; @@ -370,7 +370,7 @@ static int gb_spi_connection_init(struct gb_connection *connection) return ret; -out_err: +out_put_master: spi_master_put(master); return ret; -- cgit v0.10.2 From a92a2d46acd0bfb97ba409d9d663c270cb240715 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Tue, 15 Dec 2015 19:09:55 +0000 Subject: greybus: spi: validate spi master register Check for error in registering spi master, even though the current code will fail a little more ahead when trying to register devices in the master. Signed-off-by: Rui Miguel Silva Reported-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index 41aa0ec..6e1146d 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -360,6 +360,8 @@ static int gb_spi_connection_init(struct gb_connection *connection) master->transfer_one_message = gb_spi_transfer_one_message; ret = spi_register_master(master); + if (ret < 0) + goto out_put_master; /* now, fetch the devices configuration */ for (i = 0; i < spi->num_chipselect; i++) { -- cgit v0.10.2 From 4a0c4453e3f99335db3e7786b1a66e3b6cfa0653 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Tue, 15 Dec 2015 19:09:56 +0000 Subject: greybus: spi: unregister master on device add fail When registering devices if any of it fail, just cleanup and release spi master. Signed-off-by: Rui Miguel Silva Reported-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index 6e1146d..e49dc56 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -366,8 +366,12 @@ static int gb_spi_connection_init(struct gb_connection *connection) /* now, fetch the devices configuration */ for (i = 0; i < spi->num_chipselect; i++) { ret = gb_spi_setup_device(spi, i); - if (ret < 0) + if (ret < 0) { + dev_err(&connection->bundle->dev, + "failed to allocated spi device: %d\n", ret); + spi_unregister_master(master); break; + } } return ret; -- cgit v0.10.2 From 65fabd1848f2ddd00a1af5a1eaeb4f95dcb25b77 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Tue, 15 Dec 2015 19:09:57 +0000 Subject: greybus: spi: fix and cleanup spi devices handling Cleanup and remove the spi_devices from the greybus spi handling as they are not needed and they were completely misused. With this the gb_spi_init does not make sense to exist anymore, so just remove it and handle the master config directly from connection init. Signed-off-by: Rui Miguel Silva Reported-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index e49dc56..ad4a1d6 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -23,7 +23,6 @@ struct gb_spi { u8 num_chipselect; u32 min_speed_hz; u32 max_speed_hz; - struct spi_device *spi_devices; }; static struct spi_master *get_master_from_spi(struct gb_spi *spi) @@ -284,7 +283,7 @@ static int gb_spi_setup_device(struct gb_spi *spi, u8 cs) struct gb_spi_device_config_request request; struct gb_spi_device_config_response response; struct spi_board_info spi_board = { {0} }; - struct spi_device *spidev = &spi->spi_devices[cs]; + struct spi_device *spidev; int ret; request.chip_select = cs; @@ -308,24 +307,6 @@ static int gb_spi_setup_device(struct gb_spi *spi, u8 cs) return 0; } -static int gb_spi_init(struct gb_spi *spi) -{ - int ret; - - /* get master configuration */ - ret = gb_spi_get_master_config(spi); - if (ret) - return ret; - - spi->spi_devices = kcalloc(spi->num_chipselect, - sizeof(struct spi_device), GFP_KERNEL); - if (!spi->spi_devices) - return -ENOMEM; - - return ret; -} - - static int gb_spi_connection_init(struct gb_connection *connection) { struct gb_spi *spi; @@ -344,7 +325,8 @@ static int gb_spi_connection_init(struct gb_connection *connection) spi->connection = connection; connection->private = master; - ret = gb_spi_init(spi); + /* get master configuration */ + ret = gb_spi_get_master_config(spi); if (ret) goto out_put_master; -- cgit v0.10.2 From 8e77c83e2a6ea1977de0b6e144b90faf1bd4f418 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Thu, 17 Dec 2015 19:56:23 +0000 Subject: greybus: camera: fix data types of operations In some operations definitions it was introduce some new fields with the wrong data types, u8, instead of __u8. And because of this gbsim build was broken. Fixes: 3a1d7aa15bf6 ("greybus: Add camera protocol definition") Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index f024acd..770a162 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -1143,18 +1143,18 @@ struct gb_camera_stream_config_response { struct gb_camera_configure_streams_response { __le16 num_streams; #define GB_CAMERA_CONFIGURE_STREAMS_ADJUSTED 0x01 - u8 flags; - u8 padding; + __u8 flags; + __u8 padding; struct gb_camera_stream_config_response config[0]; } __packed; /* Greybus Camera Capture request payload - response has no payload */ struct gb_camera_capture_request { __le32 request_id; - u8 streams; - u8 padding; + __u8 streams; + __u8 padding; __le16 num_frames; - u8 settings[0]; + __u8 settings[0]; } __packed; /* Greybus Camera Flush response payload - request has no payload */ @@ -1168,7 +1168,7 @@ struct gb_camera_metadata_request { __le16 frame_number; __u8 stream; __u8 padding; - u8 metadata[0]; + __u8 metadata[0]; } __packed; /* Lights */ -- cgit v0.10.2 From 6b0658f68786110f41cd82558bd97447e4b14203 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 15 Dec 2015 12:46:22 -0800 Subject: greybus: tools: Add tools directory to greybus repo and add loopback Move the loopback test to the greybus main repo, as we will be adding more tests over time and it doesn't need to be burried in the gbsim repo. This moves the latest version from gbsim to this repo and fixes up the Makefile to be a bit more "smart" when building the code. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/.gitignore b/drivers/staging/greybus/.gitignore index 8395773..faf45ee 100644 --- a/drivers/staging/greybus/.gitignore +++ b/drivers/staging/greybus/.gitignore @@ -12,3 +12,4 @@ tags cscope.* ncscope.* *.patch +tools/loopback_test diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index e9e1cd0..7fd1fc3 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -85,7 +85,10 @@ ccflags-y := -Wall # needed for trace events ccflags-y += -I$(src) -all: module +all: module tools + +tools:: + $(MAKE) -C tools KERNELDIR=$(realpath $(KERNELDIR)) module: $(MAKE) -C $(KERNELDIR) M=$(PWD) @@ -97,6 +100,7 @@ clean: rm -f *.o *~ core .depend .*.cmd *.ko *.mod.c rm -f Module.markers Module.symvers modules.order rm -rf .tmp_versions Modules.symvers + $(MAKE) -C tools clean coccicheck: $(MAKE) -C $(KERNELDIR) M=$(PWD) coccicheck diff --git a/drivers/staging/greybus/tools/Android.mk b/drivers/staging/greybus/tools/Android.mk new file mode 100644 index 0000000..fdadbf6 --- /dev/null +++ b/drivers/staging/greybus/tools/Android.mk @@ -0,0 +1,10 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= loopback_test.c +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE := gb_loopback_test + +include $(BUILD_EXECUTABLE) + diff --git a/drivers/staging/greybus/tools/Makefile b/drivers/staging/greybus/tools/Makefile new file mode 100644 index 0000000..852b12b --- /dev/null +++ b/drivers/staging/greybus/tools/Makefile @@ -0,0 +1,31 @@ +ifeq ($(strip $(V)), 1) + Q = +else + Q = @ +endif + +CFLAGS += -std=gnu99 -Wall -Wextra -g \ + -D_GNU_SOURCE \ + -Wno-unused-parameter \ + -Wmaybe-uninitialized \ + -Wredundant-decls \ + -Wcast-align \ + -Wsign-compare \ + -Wno-missing-field-initializers + +CC := $(CROSS_COMPILE)gcc + +TOOLS = loopback_test + +all: $(TOOLS) + +%.o: %.c ../greybus_protocols.h + @echo ' TARGET_CC $@' + $(Q)$(CC) $(CFLAGS) -c $< -o $@ + +loopback_%: loopback_%.o + @echo ' TARGET_LD $@' + $(Q)$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ + +clean:: + rm -f *.o $(TOOLS) diff --git a/drivers/staging/greybus/tools/README.loopback b/drivers/staging/greybus/tools/README.loopback new file mode 100644 index 0000000..845b08d --- /dev/null +++ b/drivers/staging/greybus/tools/README.loopback @@ -0,0 +1,198 @@ + + + 1 - LOOPBACK DRIVER + +The driver implements the main logic of the loopback test and provides +sysfs files to configure the test and retrieve the results. +A user could run a test without the need of the test application given +that he understands the sysfs interface of the loopback driver. + +The loopback kernel driver needs to be loaded and at least one module +with the loopback feature enabled must be present for the sysfs files to be +created and for the loopback test application to be able to run. + +To load the module: +# modprobe gb-loopback + + +When the module is probed, New files are available on the sysfs +directory of the detected loopback device. +(typically under "/sys/bus/graybus/devices"). + +Here is a short summary of the sysfs interface files that should be visible: + +* Loopback Configuration Files: + async - Use asynchronous operations. + iteration_max - Number of tests iterations to perform. + size - payload size of the transfer. + timeout - The number of microseconds to give an individual + asynchronous request before timing out. + us_wait - Time to wait between 2 messages + type - By writing the test type to this file, the test starts. + Valid tests are: + 0 stop the test + 2 - ping + 3 - transfer + 4 - sink + +* Loopback feedback files: + error - number of errors that have occurred. + iteration_count - Number of iterations performed. + requests_completed - Number of requests successfully completed. + requests_timedout - Number of requests that have timed out. + timeout_max - Max allowed timeout + timeout_min - Min allowed timeout. + +* Loopback result files: + apbridge_unipro_latency_avg + apbridge_unipro_latency_max + apbridge_unipro_latency_min + gpbridge_firmware_latency_avg + gpbridge_firmware_latency_max + gpbridge_firmware_latency_min + requests_per_second_avg + requests_per_second_max + requests_per_second_min + latency_avg + latency_max + latency_min + throughput_avg + throughput_max + throughput_min + + + + 2 - LOOPBACK TEST APPLICATION + +The loopback test application manages and formats the results provided by +the loopback kernel module. The purpose of this application +is to: + - Start and manage multiple loopback device tests concurrently. + - Calculate the aggregate results for multiple devices. + - Gather and format test results (csv or human readable). + +The best way to get up to date usage information for the application is +usually to pass the "-h" parameter. +Here is the summary of the available options: + + Mandatory arguments + -t must be one of the test names - sink, transfer or ping + -i iteration count - the number of iterations to run the test over + Optional arguments + -S sysfs location - location for greybus 'endo' entires default /sys/bus/greybus/devices/ + -D debugfs location - location for loopback debugfs entries default /sys/kernel/debug/gb_loopback/ + -s size of data packet to send during test - defaults to zero + -m mask - a bit mask of connections to include example: -m 8 = 4th connection -m 9 = 1st and 4th connection etc + default is zero which means broadcast to all connections + -v verbose output + -d debug output + -r raw data output - when specified the full list of latency values are included in the output CSV + -p porcelain - when specified printout is in a user-friendly non-CSV format. This option suppresses writing to CSV file + -a aggregate - show aggregation of all enabled devies + -l list found loopback devices and exit. + -x Async - Enable async transfers. + -o Timeout - Timeout in microseconds for async operations. + + + + 3 - REAL WORLD EXAMPLE USAGES + + 3.1 - Using the driver sysfs files to run a test on a single device: + +* Run a 1000 transfers of a 100 byte packet. Each transfer is started only +after the previous one finished successfully: + echo 0 > /sys/bus/greybus/devices/1-2.17/type + echo 0 > /sys/bus/greybus/devices/1-2.17/async + echo 2000 > /sys/bus/greybus/devices/1-2.17/us_wait + echo 100 > /sys/bus/greybus/devices/1-2.17/size + echo 1000 > /sys/bus/greybus/devices/1-2.17/iteration_max + echo 0 > /sys/bus/greybus/devices/1-2.17/mask + echo 200000 > /sys/bus/greybus/devices/1-2.17/timeout + echo 3 > /sys/bus/greybus/devices/1-2.17/type + +* Run a 1000 transfers of a 100 byte packet. Transfers are started without +waiting for the previous one to finish: + echo 0 > /sys/bus/greybus/devices/1-2.17/type + echo 3 > /sys/bus/greybus/devices/1-2.17/async + echo 0 > /sys/bus/greybus/devices/1-2.17/us_wait + echo 100 > /sys/bus/greybus/devices/1-2.17/size + echo 1000 > /sys/bus/greybus/devices/1-2.17/iteration_max + echo 0 > /sys/bus/greybus/devices/1-2.17/mask + echo 200000 > /sys/bus/greybus/devices/1-2.17/timeout + echo 3 > /sys/bus/greybus/devices/1-2.17/type + +* Read the results from sysfs: + cat /sys/bus/greybus/devices/1-2.17/requests_per_second_min + cat /sys/bus/greybus/devices/1-2.17/requests_per_second_max + cat /sys/bus/greybus/devices/1-2.17/requests_per_second_avg + + cat /sys/bus/greybus/devices/1-2.17/latency_min + cat /sys/bus/greybus/devices/1-2.17/latency_max + cat /sys/bus/greybus/devices/1-2.17/latency_avg + + cat /sys/bus/greybus/devices/1-2.17/apbridge_unipro_latency_min + cat /sys/bus/greybus/devices/1-2.17/apbridge_unipro_latency_max + cat /sys/bus/greybus/devices/1-2.17/apbridge_unipro_latency_avg + + cat /sys/bus/greybus/devices/1-2.17/gpbridge_firmware_latency_min + cat /sys/bus/greybus/devices/1-2.17/gpbridge_firmware_latency_max + cat /sys/bus/greybus/devices/1-2.17/gpbridge_firmware_latency_avg + + cat /sys/bus/greybus/devices/1-2.17/error + cat /sys/bus/greybus/devices/1-2.17/requests_completed + cat /sys/bus/greybus/devices/1-2.17/requests_timedout + + +3.2 - using the test application: + +* Run a transfer test 10 iterations of size 100 bytes on all available devices + #/loopback_test -t transfer -i 10 -s 100 + 1970-1-1 0:10:7,transfer,1-4.17,100,10,0,443,509,471.700012,66,1963,2256,2124.600098,293,102776,118088,109318.898438,15312,1620,1998,1894.099976,378,56,57,56.799999,1 + 1970-1-1 0:10:7,transfer,1-5.17,100,10,0,399,542,463.399994,143,1845,2505,2175.800049,660,92568,125744,107393.296875,33176,1469,2305,1806.500000,836,56,57,56.799999,1 + + +* Show the aggregate results of both devices. ("-a") + #/loopback_test -t transfer -i 10 -s 100 -a + 1970-1-1 0:10:35,transfer,1-4.17,100,10,0,448,580,494.100006,132,1722,2230,2039.400024,508,103936,134560,114515.703125,30624,1513,1980,1806.900024,467,56,57,57.299999,1 + 1970-1-1 0:10:35,transfer,1-5.17,100,10,0,383,558,478.600006,175,1791,2606,2115.199951,815,88856,129456,110919.703125,40600,1457,2246,1773.599976,789,56,57,57.099998,1 + 1970-1-1 0:10:35,transfer,aggregate,100,10,0,383,580,486.000000,197,1722,2606,2077.000000,884,88856,134560,112717.000000,45704,1457,2246,1789.000000,789,56,57,57.000000,1 + +* Example usage of the mask option to select which devices will + run the test (1st, 2nd, or both devices): + # /loopback_test -t transfer -i 10 -s 100 -m 1 + 1970-1-1 0:11:56,transfer,1-4.17,100,10,0,514,558,544.900024,44,1791,1943,1836.599976,152,119248,129456,126301.296875,10208,1600,1001609,101613.601562,1000009,56,57,56.900002,1 + # /loopback_test -t transfer -i 10 -s 100 -m 2 + 1970-1-1 0:12:0,transfer,1-5.17,100,10,0,468,554,539.000000,86,1804,2134,1859.500000,330,108576,128528,124932.500000,19952,1606,1626,1619.300049,20,56,57,57.400002,1 + # /loopback_test -t transfer -i 10 -s 100 -m 3 + 1970-1-1 0:12:3,transfer,1-4.17,100,10,0,432,510,469.399994,78,1959,2313,2135.800049,354,100224,118320,108785.296875,18096,1610,2024,1893.500000,414,56,57,57.200001,1 + 1970-1-1 0:12:3,transfer,1-5.17,100,10,0,404,542,468.799988,138,1843,2472,2152.500000,629,93728,125744,108646.101562,32016,1504,2247,1853.099976,743,56,57,57.099998,1 + +* Show output in human readable format ("-p") + # /loopback_test -t transfer -i 10 -s 100 -m 3 -p + + 1970-1-1 0:12:37 + test: transfer + path: 1-4.17 + size: 100 + iterations: 10 + errors: 0 + async: Disabled + requests per-sec: min=390, max=547, average=469.299988, jitter=157 + ap-throughput B/s: min=90480 max=126904 average=108762.101562 jitter=36424 + ap-latency usec: min=1826 max=2560 average=2146.000000 jitter=734 + apbridge-latency usec: min=1620 max=1982 average=1882.099976 jitter=362 + gpbridge-latency usec: min=56 max=57 average=57.099998 jitter=1 + + + 1970-1-1 0:12:37 + test: transfer + path: 1-5.17 + size: 100 + iterations: 10 + errors: 0 + async: Disabled + requests per-sec: min=397, max=538, average=461.700012, jitter=141 + ap-throughput B/s: min=92104 max=124816 average=106998.898438 jitter=32712 + ap-latency usec: min=1856 max=2514 average=2185.699951 jitter=658 + apbridge-latency usec: min=1460 max=2296 average=1828.599976 jitter=836 + gpbridge-latency usec: min=56 max=57 average=57.099998 jitter=1 diff --git a/drivers/staging/greybus/tools/lbtest b/drivers/staging/greybus/tools/lbtest new file mode 100755 index 0000000..d7353f1 --- /dev/null +++ b/drivers/staging/greybus/tools/lbtest @@ -0,0 +1,168 @@ +#!/usr/bin/env python + +# Copyright (c) 2015 Google, Inc. +# Copyright (c) 2015 Linaro, Ltd. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# +# 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 HOLDER 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. + +from __future__ import print_function +import csv +import datetime +import sys +import time + +dict = {'ping': '2', 'transfer': '3', 'sink': '4'} +verbose = 1 + +def abort(): + sys.exit(1) + +def usage(): + print('Usage: looptest TEST SIZE ITERATIONS PATH\n\n' + ' Run TEST for a number of ITERATIONS with operation data SIZE bytes\n' + ' TEST may be \'ping\' \'transfer\' or \'sink\'\n' + ' SIZE indicates the size of transfer <= greybus max payload bytes\n' + ' ITERATIONS indicates the number of times to execute TEST at SIZE bytes\n' + ' Note if ITERATIONS is set to zero then this utility will\n' + ' initiate an infinite (non terminating) test and exit\n' + ' without logging any metrics data\n' + ' PATH indicates the sysfs path for the loopback greybus entries e.g.\n' + ' /sys/bus/greybus/devices/endo0:1:1:1:1/\n' + 'Examples:\n' + ' looptest transfer 128 10000\n' + ' looptest ping 0 128\n' + ' looptest sink 2030 32768\n' + .format(sys.argv[0]), file=sys.stderr) + + abort() + +def read_sysfs_int(path): + try: + f = open(path, "r"); + val = f.read(); + f.close() + return int(val) + except IOError as e: + print("I/O error({0}): {1}".format(e.errno, e.strerror)) + print("Invalid path %s" % path) + +def write_sysfs_val(path, val): + try: + f = open(path, "r+") + f.write(val) + f.close() + except IOError as e: + print("I/O error({0}): {1}".format(e.errno, e.strerror)) + print("Invalid path %s" % path) + +def log_csv(test_name, size, iteration_max, sys_pfx): + # file name will test_name_size_iteration_max.csv + # every time the same test with the same parameters is run we will then + # append to the same CSV with datestamp - representing each test dataset + fname = test_name + '_' + size + '_' + str(iteration_max) + '.csv' + + try: + # gather data set + date = str(datetime.datetime.now()) + error = read_sysfs_int(sys_pfx + 'error') + request_min = read_sysfs_int(sys_pfx + 'requests_per_second_min') + request_max = read_sysfs_int(sys_pfx + 'requests_per_second_max') + request_avg = read_sysfs_int(sys_pfx + 'requests_per_second_avg') + latency_min = read_sysfs_int(sys_pfx + 'latency_min') + latency_max = read_sysfs_int(sys_pfx + 'latency_max') + latency_avg = read_sysfs_int(sys_pfx + 'latency_avg') + throughput_min = read_sysfs_int(sys_pfx + 'throughput_min') + throughput_max = read_sysfs_int(sys_pfx + 'throughput_max') + throughput_avg = read_sysfs_int(sys_pfx + 'throughput_avg') + + # derive jitter + request_jitter = request_max - request_min + latency_jitter = latency_max - latency_min + throughput_jitter = throughput_max - throughput_min + + # append data set to file + with open(fname, 'a') as csvf: + row = csv.writer(csvf, delimiter=",", quotechar="'", + quoting=csv.QUOTE_MINIMAL) + row.writerow([date, test_name, size, iteration_max, error, + request_min, request_max, request_avg, request_jitter, + latency_min, latency_max, latency_avg, latency_jitter, + throughput_min, throughput_max, throughput_avg, throughput_jitter]) + except IOError as e: + print("I/O error({0}): {1}".format(e.errno, e.strerror)) + +def loopback_run(test_name, size, iteration_max, sys_pfx): + test_id = dict[test_name] + try: + # Terminate any currently running test + write_sysfs_val(sys_pfx + 'type', '0') + # Set parameter for no wait between messages + write_sysfs_val(sys_pfx + 'ms_wait', '0') + # Set operation size + write_sysfs_val(sys_pfx + 'size', size) + # Set iterations + write_sysfs_val(sys_pfx + 'iteration_max', str(iteration_max)) + # Initiate by setting loopback operation type + write_sysfs_val(sys_pfx + 'type', test_id) + time.sleep(1) + + if iteration_max == 0: + print ("Infinite test initiated CSV won't be logged\n") + return + + previous = 0 + err = 0 + while True: + # get current count bail out if it hasn't changed + iteration_count = read_sysfs_int(sys_pfx + 'iteration_count') + if previous == iteration_count: + err = 1 + break + elif iteration_count == iteration_max: + break + previous = iteration_count + if verbose: + print('%02d%% complete %d of %d ' % + (100 * iteration_count / iteration_max, + iteration_count, iteration_max)) + time.sleep(1) + if err: + print ('\nError executing test\n') + else: + log_csv(test_name, size, iteration_max, sys_pfx) + except ValueError as ve: + print("Error: %s " % format(e.strerror), file=sys.stderr) + abort() + +def main(): + if len(sys.argv) < 5: + usage() + + if sys.argv[1] in dict.keys(): + loopback_run(sys.argv[1], sys.argv[2], int(sys.argv[3]), sys.argv[4]) + else: + usage() +if __name__ == '__main__': + main() diff --git a/drivers/staging/greybus/tools/loopback_test.c b/drivers/staging/greybus/tools/loopback_test.c new file mode 100644 index 0000000..55b3102 --- /dev/null +++ b/drivers/staging/greybus/tools/loopback_test.c @@ -0,0 +1,958 @@ +/* + * Loopback test application + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Provided under the three clause BSD license found in the LICENSE file. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_NUM_DEVICES 50 +#define MAX_SYSFS_PATH 0x200 +#define CSV_MAX_LINE 0x1000 +#define SYSFS_MAX_INT 0x20 +#define MAX_STR_LEN 255 +#define MAX_TIMEOUT_COUNT 5 +#define TIMEOUT_SEC 1 +#define DEFAULT_ASYNC_TIMEOUT 200000 + +struct dict { + char *name; + int type; +}; + +static struct dict dict[] = { + {"ping", 2}, + {"transfer", 3}, + {"sink", 4} +}; + +struct loopback_results { + float latency_avg; + uint32_t latency_max; + uint32_t latency_min; + uint32_t latency_jitter; + + float request_avg; + uint32_t request_max; + uint32_t request_min; + uint32_t request_jitter; + + float throughput_avg; + uint32_t throughput_max; + uint32_t throughput_min; + uint32_t throughput_jitter; + + float apbridge_unipro_latency_avg; + uint32_t apbridge_unipro_latency_max; + uint32_t apbridge_unipro_latency_min; + uint32_t apbridge_unipro_latency_jitter; + + float gpbridge_firmware_latency_avg; + uint32_t gpbridge_firmware_latency_max; + uint32_t gpbridge_firmware_latency_min; + uint32_t gpbridge_firmware_latency_jitter; + + uint32_t error; +}; + +struct loopback_device { + char name[MAX_SYSFS_PATH]; + char sysfs_entry[MAX_SYSFS_PATH]; + char debugfs_entry[MAX_SYSFS_PATH]; + int inotify_wd; + struct loopback_results results; +}; + +struct loopback_test { + int verbose; + int debug; + int raw_data_dump; + int porcelain; + int mask; + int size; + int iteration_max; + int aggregate_output; + int test_id; + int device_count; + int inotify_fd; + int list_devices; + int use_async; + int async_timeout; + int async_outstanding_operations; + int us_wait; + char test_name[MAX_STR_LEN]; + char sysfs_prefix[MAX_SYSFS_PATH]; + char debugfs_prefix[MAX_SYSFS_PATH]; + struct loopback_device devices[MAX_NUM_DEVICES]; + struct loopback_results aggregate_results; +}; +struct loopback_test t; + +/* Helper macros to calculate the aggregate results for all devices */ +static inline int device_enabled(struct loopback_test *t, int dev_idx); + +#define GET_MAX(field) \ +static int get_##field##_aggregate(struct loopback_test *t) \ +{ \ + uint32_t max = 0; \ + int i; \ + for (i = 0; i < t->device_count; i++) { \ + if (!device_enabled(t, i)) \ + continue; \ + if (t->devices[i].results.field > max) \ + max = t->devices[i].results.field; \ + } \ + return max; \ +} \ + +#define GET_MIN(field) \ +static int get_##field##_aggregate(struct loopback_test *t) \ +{ \ + uint32_t min = ~0; \ + int i; \ + for (i = 0; i < t->device_count; i++) { \ + if (!device_enabled(t, i)) \ + continue; \ + if (t->devices[i].results.field < min) \ + min = t->devices[i].results.field; \ + } \ + return min; \ +} \ + +#define GET_AVG(field) \ +static int get_##field##_aggregate(struct loopback_test *t) \ +{ \ + uint32_t val = 0; \ + uint32_t count = 0; \ + int i; \ + for (i = 0; i < t->device_count; i++) { \ + if (!device_enabled(t, i)) \ + continue; \ + count++; \ + val += t->devices[i].results.field; \ + } \ + if (count) \ + val /= count; \ + return val; \ +} \ + +GET_MAX(throughput_max); +GET_MAX(request_max); +GET_MAX(latency_max); +GET_MAX(apbridge_unipro_latency_max); +GET_MAX(gpbridge_firmware_latency_max); +GET_MIN(throughput_min); +GET_MIN(request_min); +GET_MIN(latency_min); +GET_MIN(apbridge_unipro_latency_min); +GET_MIN(gpbridge_firmware_latency_min); +GET_AVG(throughput_avg); +GET_AVG(request_avg); +GET_AVG(latency_avg); +GET_AVG(apbridge_unipro_latency_avg); +GET_AVG(gpbridge_firmware_latency_avg); + +void abort() +{ + _exit(1); +} + +void usage(void) +{ + fprintf(stderr, "Usage: loopback_test TEST [SIZE] ITERATIONS [SYSPATH] [DBGPATH]\n\n" + " Run TEST for a number of ITERATIONS with operation data SIZE bytes\n" + " TEST may be \'ping\' \'transfer\' or \'sink\'\n" + " SIZE indicates the size of transfer <= greybus max payload bytes\n" + " ITERATIONS indicates the number of times to execute TEST at SIZE bytes\n" + " Note if ITERATIONS is set to zero then this utility will\n" + " initiate an infinite (non terminating) test and exit\n" + " without logging any metrics data\n" + " SYSPATH indicates the sysfs path for the loopback greybus entries e.g.\n" + " /sys/bus/greybus/devices\n" + " DBGPATH indicates the debugfs path for the loopback greybus entries e.g.\n" + " /sys/kernel/debug/gb_loopback/\n" + " Mandatory arguments\n" + " -t must be one of the test names - sink, transfer or ping\n" + " -i iteration count - the number of iterations to run the test over\n" + " Optional arguments\n" + " -S sysfs location - location for greybus 'endo' entires default /sys/bus/greybus/devices/\n" + " -D debugfs location - location for loopback debugfs entries default /sys/kernel/debug/gb_loopback/\n" + " -s size of data packet to send during test - defaults to zero\n" + " -m mask - a bit mask of connections to include example: -m 8 = 4th connection -m 9 = 1st and 4th connection etc\n" + " default is zero which means broadcast to all connections\n" + " -v verbose output\n" + " -d debug output\n" + " -r raw data output - when specified the full list of latency values are included in the output CSV\n" + " -p porcelain - when specified printout is in a user-friendly non-CSV format. This option suppresses writing to CSV file\n" + " -a aggregate - show aggregation of all enabled devices\n" + " -l list found loopback devices and exit\n" + " -x Async - Enable async transfers\n" + " -o Async Timeout - Timeout in uSec for async operations\n" + " -c Max number of outstanding operations for async operations\n" + " -w Wait in uSec between operations\n" + "Examples:\n" + " Send 10000 transfers with a packet size of 128 bytes to all active connections\n" + " loopback_test -t transfer -s 128 -i 10000 -S /sys/bus/greybus/devices/ -D /sys/kernel/debug/gb_loopback/\n" + " loopback_test -t transfer -s 128 -i 10000 -m 0\n" + " Send 10000 transfers with a packet size of 128 bytes to connection 1 and 4\n" + " loopback_test -t transfer -s 128 -i 10000 -m 9\n" + " loopback_test -t ping -s 0 128 -i -S /sys/bus/greybus/devices/ -D /sys/kernel/debug/gb_loopback/\n" + " loopback_test -t sink -s 2030 -i 32768 -S /sys/bus/greybus/devices/ -D /sys/kernel/debug/gb_loopback/\n"); + abort(); +} + +static inline int device_enabled(struct loopback_test *t, int dev_idx) +{ + if (!t->mask || (t->mask & (1 << dev_idx))) + return 1; + + return 0; +} + +static void show_loopback_devices(struct loopback_test *t) +{ + int i; + + if (t->device_count == 0) { + printf("No loopback devices.\n"); + return; + } + + for (i = 0; i < t->device_count; i++) + printf("device[%d] = %s\n", i, t->devices[i].name); + +} + +int open_sysfs(const char *sys_pfx, const char *node, int flags) +{ + int fd; + char path[MAX_SYSFS_PATH]; + + snprintf(path, sizeof(path), "%s%s", sys_pfx, node); + fd = open(path, flags); + if (fd < 0) { + fprintf(stderr, "unable to open %s\n", path); + abort(); + } + return fd; +} + +int read_sysfs_int_fd(int fd, const char *sys_pfx, const char *node) +{ + char buf[SYSFS_MAX_INT]; + + if (read(fd, buf, sizeof(buf)) < 0) { + fprintf(stderr, "unable to read from %s%s %s\n", sys_pfx, node, + strerror(errno)); + close(fd); + abort(); + } + return atoi(buf); +} + +float read_sysfs_float_fd(int fd, const char *sys_pfx, const char *node) +{ + char buf[SYSFS_MAX_INT]; + + if (read(fd, buf, sizeof(buf)) < 0) { + + fprintf(stderr, "unable to read from %s%s %s\n", sys_pfx, node, + strerror(errno)); + close(fd); + abort(); + } + return atof(buf); +} + +int read_sysfs_int(const char *sys_pfx, const char *node) +{ + int fd, val; + + fd = open_sysfs(sys_pfx, node, O_RDONLY); + val = read_sysfs_int_fd(fd, sys_pfx, node); + close(fd); + return val; +} + +float read_sysfs_float(const char *sys_pfx, const char *node) +{ + int fd; + float val; + + fd = open_sysfs(sys_pfx, node, O_RDONLY); + val = read_sysfs_float_fd(fd, sys_pfx, node); + close(fd); + return val; +} + +void write_sysfs_val(const char *sys_pfx, const char *node, int val) +{ + int fd, len; + char buf[SYSFS_MAX_INT]; + + fd = open_sysfs(sys_pfx, node, O_RDWR); + len = snprintf(buf, sizeof(buf), "%d", val); + if (write(fd, buf, len) < 0) { + fprintf(stderr, "unable to write to %s%s %s\n", sys_pfx, node, + strerror(errno)); + close(fd); + abort(); + } + close(fd); +} + +static int get_results(struct loopback_test *t) +{ + struct loopback_device *d; + struct loopback_results *r; + int i; + + for (i = 0; i < t->device_count; i++) { + if (!device_enabled(t, i)) + continue; + + d = &t->devices[i]; + r = &d->results; + + r->error = read_sysfs_int(d->sysfs_entry, "error"); + r->request_min = read_sysfs_int(d->sysfs_entry, "requests_per_second_min"); + r->request_max = read_sysfs_int(d->sysfs_entry, "requests_per_second_max"); + r->request_avg = read_sysfs_float(d->sysfs_entry, "requests_per_second_avg"); + + r->latency_min = read_sysfs_int(d->sysfs_entry, "latency_min"); + r->latency_max = read_sysfs_int(d->sysfs_entry, "latency_max"); + r->latency_avg = read_sysfs_float(d->sysfs_entry, "latency_avg"); + + r->throughput_min = read_sysfs_int(d->sysfs_entry, "throughput_min"); + r->throughput_max = read_sysfs_int(d->sysfs_entry, "throughput_max"); + r->throughput_avg = read_sysfs_float(d->sysfs_entry, "throughput_avg"); + + r->apbridge_unipro_latency_min = + read_sysfs_int(d->sysfs_entry, "apbridge_unipro_latency_min"); + r->apbridge_unipro_latency_max = + read_sysfs_int(d->sysfs_entry, "apbridge_unipro_latency_max"); + r->apbridge_unipro_latency_avg = + read_sysfs_float(d->sysfs_entry, "apbridge_unipro_latency_avg"); + + r->gpbridge_firmware_latency_min = + read_sysfs_int(d->sysfs_entry, "gpbridge_firmware_latency_min"); + r->gpbridge_firmware_latency_max = + read_sysfs_int(d->sysfs_entry, "gpbridge_firmware_latency_max"); + r->gpbridge_firmware_latency_avg = + read_sysfs_float(d->sysfs_entry, "gpbridge_firmware_latency_avg"); + + r->request_jitter = r->request_max - r->request_min; + r->latency_jitter = r->latency_max - r->latency_min; + r->throughput_jitter = r->throughput_max - r->throughput_min; + r->apbridge_unipro_latency_jitter = + r->apbridge_unipro_latency_max - r->apbridge_unipro_latency_min; + r->gpbridge_firmware_latency_jitter = + r->gpbridge_firmware_latency_max - r->gpbridge_firmware_latency_min; + + } + + /*calculate the aggregate results of all enabled devices */ + if (t->aggregate_output) { + r = &t->aggregate_results; + + r->request_min = get_request_min_aggregate(t); + r->request_max = get_request_max_aggregate(t); + r->request_avg = get_request_avg_aggregate(t); + + r->latency_min = get_latency_min_aggregate(t); + r->latency_max = get_latency_max_aggregate(t); + r->latency_avg = get_latency_avg_aggregate(t); + + r->throughput_min = get_throughput_min_aggregate(t); + r->throughput_max = get_throughput_max_aggregate(t); + r->throughput_avg = get_throughput_avg_aggregate(t); + + r->apbridge_unipro_latency_min = + get_apbridge_unipro_latency_min_aggregate(t); + r->apbridge_unipro_latency_max = + get_apbridge_unipro_latency_max_aggregate(t); + r->apbridge_unipro_latency_avg = + get_apbridge_unipro_latency_avg_aggregate(t); + + r->gpbridge_firmware_latency_min = + get_gpbridge_firmware_latency_min_aggregate(t); + r->gpbridge_firmware_latency_max = + get_gpbridge_firmware_latency_max_aggregate(t); + r->gpbridge_firmware_latency_avg = + get_gpbridge_firmware_latency_avg_aggregate(t); + + r->request_jitter = r->request_max - r->request_min; + r->latency_jitter = r->latency_max - r->latency_min; + r->throughput_jitter = r->throughput_max - r->throughput_min; + r->apbridge_unipro_latency_jitter = + r->apbridge_unipro_latency_max - r->apbridge_unipro_latency_min; + r->gpbridge_firmware_latency_jitter = + r->gpbridge_firmware_latency_max - r->gpbridge_firmware_latency_min; + + } + + return 0; +} + +void log_csv_error(int len, int err) +{ + fprintf(stderr, "unable to write %d bytes to csv %s\n", len, + strerror(err)); +} + +int format_output(struct loopback_test *t, + struct loopback_results *r, + const char *dev_name, + char *buf, int buf_len, + struct tm *tm) +{ + int len = 0; + + memset(buf, 0x00, buf_len); + len = snprintf(buf, buf_len, "%u-%u-%u %u:%u:%u", + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + + if (t->porcelain) { + len += snprintf(&buf[len], buf_len - len, + "\n test:\t\t\t%s\n path:\t\t\t%s\n size:\t\t\t%u\n iterations:\t\t%u\n errors:\t\t%u\n async:\t\t\t%s\n", + t->test_name, + dev_name, + t->size, + t->iteration_max, + r->error, + t->use_async ? "Enabled" : "Disabled"); + + len += snprintf(&buf[len], buf_len - len, + " requests per-sec:\tmin=%u, max=%u, average=%f, jitter=%u\n", + r->request_min, + r->request_max, + r->request_avg, + r->request_jitter); + + len += snprintf(&buf[len], buf_len - len, + " ap-throughput B/s:\tmin=%u max=%u average=%f jitter=%u\n", + r->throughput_min, + r->throughput_max, + r->throughput_avg, + r->throughput_jitter); + len += snprintf(&buf[len], buf_len - len, + " ap-latency usec:\tmin=%u max=%u average=%f jitter=%u\n", + r->latency_min, + r->latency_max, + r->latency_avg, + r->latency_jitter); + len += snprintf(&buf[len], buf_len - len, + " apbridge-latency usec:\tmin=%u max=%u average=%f jitter=%u\n", + r->apbridge_unipro_latency_min, + r->apbridge_unipro_latency_max, + r->apbridge_unipro_latency_avg, + r->apbridge_unipro_latency_jitter); + + len += snprintf(&buf[len], buf_len - len, + " gpbridge-latency usec:\tmin=%u max=%u average=%f jitter=%u\n", + r->gpbridge_firmware_latency_min, + r->gpbridge_firmware_latency_max, + r->gpbridge_firmware_latency_avg, + r->gpbridge_firmware_latency_jitter); + + } else { + len += snprintf(&buf[len], buf_len- len, ",%s,%s,%u,%u,%u", + t->test_name, dev_name, t->size, t->iteration_max, + r->error); + + len += snprintf(&buf[len], buf_len - len, ",%u,%u,%f,%u", + r->request_min, + r->request_max, + r->request_avg, + r->request_jitter); + + len += snprintf(&buf[len], buf_len - len, ",%u,%u,%f,%u", + r->latency_min, + r->latency_max, + r->latency_avg, + r->latency_jitter); + + len += snprintf(&buf[len], buf_len - len, ",%u,%u,%f,%u", + r->throughput_min, + r->throughput_max, + r->throughput_avg, + r->throughput_jitter); + + len += snprintf(&buf[len], buf_len - len, ",%u,%u,%f,%u", + r->apbridge_unipro_latency_min, + r->apbridge_unipro_latency_max, + r->apbridge_unipro_latency_avg, + r->apbridge_unipro_latency_jitter); + + len += snprintf(&buf[len], buf_len - len, ",%u,%u,%f,%u", + r->gpbridge_firmware_latency_min, + r->gpbridge_firmware_latency_max, + r->gpbridge_firmware_latency_avg, + r->gpbridge_firmware_latency_jitter); + } + + printf("\n%s\n", buf); + + return len; +} + +static int log_results(struct loopback_test *t) +{ + int fd, i, len, ret; + struct tm tm; + time_t local_time; + mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; + char file_name[MAX_SYSFS_PATH]; + char data[CSV_MAX_LINE]; + + local_time = time(NULL); + tm = *localtime(&local_time); + + /* + * file name will test_name_size_iteration_max.csv + * every time the same test with the same parameters is run we will then + * append to the same CSV with datestamp - representing each test + * dataset. + */ + if (!t->porcelain) { + snprintf(file_name, sizeof(file_name), "%s_%d_%d.csv", + t->test_name, t->size, t->iteration_max); + + fd = open(file_name, O_WRONLY | O_CREAT | O_APPEND, mode); + if (fd < 0) { + fprintf(stderr, "unable to open %s for appendation\n", file_name); + abort(); + } + + } + for (i = 0; i < t->device_count; i++) { + if (!device_enabled(t, i)) + continue; + + len = format_output(t, &t->devices[i].results, + t->devices[i].name, + data, sizeof(data), &tm); + if (!t->porcelain) { + ret = write(fd, data, len); + if (ret == -1) + fprintf(stderr, "unable to write %d bytes to csv.\n", len); + } + + } + + + if (t->aggregate_output) { + len = format_output(t, &t->aggregate_results, "aggregate", + data, sizeof(data), &tm); + if (!t->porcelain) { + ret = write(fd, data, len); + if (ret == -1) + fprintf(stderr, "unable to write %d bytes to csv.\n", len); + } + } + + if (!t->porcelain) + close(fd); + + return 0; +} + +int is_loopback_device(const char *path, const char *node) +{ + char file[MAX_SYSFS_PATH]; + + snprintf(file, MAX_SYSFS_PATH, "%s%s/iteration_count", path, node); + if (access(file, F_OK) == 0) + return 1; + return 0; +} + +int find_loopback_devices(struct loopback_test *t) +{ + struct dirent **namelist; + int i, n, ret; + unsigned int dev_id; + struct loopback_device *d; + + n = scandir(t->sysfs_prefix, &namelist, NULL, alphasort); + if (n < 0) { + perror("scandir"); + ret = -ENODEV; + goto baddir; + } + + /* Don't include '.' and '..' */ + if (n <= 2) { + ret = -ENOMEM; + goto done; + } + + for (i = 0; i < n; i++) { + ret = sscanf(namelist[i]->d_name, "gb_loopback%u", &dev_id); + if (ret != 1) + continue; + + if (!is_loopback_device(t->sysfs_prefix, namelist[i]->d_name)) + continue; + + if (t->device_count == MAX_NUM_DEVICES) { + fprintf(stderr, "max number of devices reached!\n"); + break; + } + + d = &t->devices[t->device_count++]; + snprintf(d->name, MAX_STR_LEN, "gb_loopback%u", dev_id); + + snprintf(d->sysfs_entry, MAX_SYSFS_PATH, "%s%s/", + t->sysfs_prefix, d->name); + + snprintf(d->debugfs_entry, MAX_SYSFS_PATH, "%sraw_latency_%s", + t->debugfs_prefix, d->name); + + if (t->debug) + printf("add %s %s\n", d->sysfs_entry, + d->debugfs_entry); + } + + ret = 0; +done: + for (i = 0; i < n; i++) + free(namelist[n]); + free(namelist); +baddir: + return ret; +} + + +static int register_for_notification(struct loopback_test *t) +{ + char buf[MAX_SYSFS_PATH]; + int i; + + t->inotify_fd = inotify_init(); + if (t->inotify_fd < 0) { + fprintf(stderr, "inotify_init fail %s\n", strerror(errno)); + abort(); + } + + for (i = 0; i < t->device_count; i++) { + if (!device_enabled(t, i)) + continue; + + snprintf(buf, sizeof(buf), "%s%s", t->devices[i].sysfs_entry, + "iteration_count"); + + t->devices[i].inotify_wd = inotify_add_watch(t->inotify_fd, + buf, IN_MODIFY); + if (t->devices[i].inotify_wd < 0) { + fprintf(stderr, "inotify_add_watch %s fail %s\n", + buf, strerror(errno)); + close(t->inotify_fd); + abort(); + } + } + + return 0; +} + +static int unregister_for_notification(struct loopback_test *t) +{ + int i; + int ret = 0; + + for (i = 0; i < t->device_count; i++) { + if (!device_enabled(t, i)) + continue; + + ret = inotify_rm_watch(t->inotify_fd, t->devices[i].inotify_wd); + if (ret) { + fprintf(stderr, "inotify_rm_watch error.\n"); + return ret; + } + } + + close(t->inotify_fd); + return 0; +} + +static int is_complete(struct loopback_test *t) +{ + uint32_t iteration_count = 0; + int i; + + for (i = 0; i < t->device_count; i++) { + if (!device_enabled(t, i)) + continue; + + iteration_count = read_sysfs_int(t->devices[i].sysfs_entry, + "iteration_count"); + + /* at least one device did not finish yet */ + if (iteration_count != t->iteration_max) + return 0; + } + + return 1; +} + +static int wait_for_complete(struct loopback_test *t) +{ + int remaining_timeouts = MAX_TIMEOUT_COUNT; + char buf[MAX_SYSFS_PATH]; + struct timeval timeout; + fd_set read_fds; + int ret; + + while (1) { + /* Wait for change */ + timeout.tv_sec = TIMEOUT_SEC; + timeout.tv_usec = 0; + FD_ZERO(&read_fds); + FD_SET(t->inotify_fd, &read_fds); + ret = select(FD_SETSIZE, &read_fds, NULL, NULL, &timeout); + if (ret < 0) { + fprintf(stderr, "Select error.\n"); + return -1; + } + + /* timeout - test may be finished.*/ + if (!FD_ISSET(t->inotify_fd, &read_fds)) { + remaining_timeouts--; + + if (is_complete(t)) + return 0; + + if (!remaining_timeouts) { + fprintf(stderr, "Too many timeouts\n"); + return -1; + } + } else { + /* read to clear the event */ + ret = read(t->inotify_fd, buf, sizeof(buf)); + } + } + + return 0; +} + +static void prepare_devices(struct loopback_test *t) +{ + int i; + + /* Cancel any running tests */ + for (i = 0; i < t->device_count; i++) + write_sysfs_val(t->devices[i].sysfs_entry, "type", 0); + + + for (i = 0; i < t->device_count; i++) { + if (!device_enabled(t, i)) + continue; + + write_sysfs_val(t->devices[i].sysfs_entry, "us_wait", + t->us_wait); + + /* Set operation size */ + write_sysfs_val(t->devices[i].sysfs_entry, "size", t->size); + + /* Set iterations */ + write_sysfs_val(t->devices[i].sysfs_entry, "iteration_max", + t->iteration_max); + + if (t->use_async) { + write_sysfs_val(t->devices[i].sysfs_entry, + "async", 1); + write_sysfs_val(t->devices[i].sysfs_entry, + "timeout", t->async_timeout); + write_sysfs_val(t->devices[i].sysfs_entry, + "outstanding_operations_max", + t->async_outstanding_operations); + } else + write_sysfs_val(t->devices[i].sysfs_entry, + "async", 0); + } +} + +static int start(struct loopback_test *t) +{ + int i; + + /* the test starts by writing test_id to the type file. */ + for (i = 0; i < t->device_count; i++) { + if (!device_enabled(t, i)) + continue; + + write_sysfs_val(t->devices[i].sysfs_entry, "type", t->test_id); + } + + return 0; +} + + +void loopback_run(struct loopback_test *t) +{ + int i; + int ret; + + for (i = 0; i < sizeof(dict) / sizeof(struct dict); i++) { + if (strstr(dict[i].name, t->test_name)) + t->test_id = dict[i].type; + } + if (!t->test_id) { + fprintf(stderr, "invalid test %s\n", t->test_name); + usage(); + return; + } + + prepare_devices(t); + + ret = register_for_notification(t); + if (ret) + goto err; + + start(t); + + sleep(1); + + wait_for_complete(t); + + unregister_for_notification(t); + + get_results(t); + + log_results(t); + + return; + +err: + printf("Error running test\n"); + return; +} + +static int sanity_check(struct loopback_test *t) +{ + int i; + + if (t->device_count == 0) { + fprintf(stderr, "No loopback devices found\n"); + return -1; + } + + for (i = 0; i < MAX_NUM_DEVICES; i++) { + if (!device_enabled(t, i)) + continue; + + if (t->mask && !strcmp(t->devices[i].name, "")) { + fprintf(stderr, "Bad device mask %x\n", (1 << i)); + return -1; + } + + } + + + return 0; +} +int main(int argc, char *argv[]) +{ + int o, ret; + char *sysfs_prefix = "/sys/class/gb_loopback/"; + char *debugfs_prefix = "/sys/kernel/debug/gb_loopback/"; + + memset(&t, 0, sizeof(t)); + + while ((o = getopt(argc, argv, + "t:s:i:S:D:m:v::d::r::p::a::l::x::o:c:w:")) != -1) { + switch (o) { + case 't': + snprintf(t.test_name, MAX_STR_LEN, "%s", optarg); + break; + case 's': + t.size = atoi(optarg); + break; + case 'i': + t.iteration_max = atoi(optarg); + break; + case 'S': + snprintf(t.sysfs_prefix, MAX_SYSFS_PATH, "%s", optarg); + break; + case 'D': + snprintf(t.debugfs_prefix, MAX_SYSFS_PATH, "%s", optarg); + break; + case 'm': + t.mask = atol(optarg); + break; + case 'v': + t.verbose = 1; + break; + case 'd': + t.debug = 1; + break; + case 'r': + t.raw_data_dump = 1; + break; + case 'p': + t.porcelain = 1; + break; + case 'a': + t.aggregate_output = 1; + break; + case 'l': + t.list_devices = 1; + break; + case 'x': + t.use_async = 1; + break; + case 'o': + t.async_timeout = atoi(optarg); + break; + case 'c': + t.async_outstanding_operations = atoi(optarg); + break; + case 'w': + t.us_wait = atoi(optarg); + break; + default: + usage(); + return -EINVAL; + } + } + + if (!strcmp(t.sysfs_prefix, "")) + snprintf(t.sysfs_prefix, MAX_SYSFS_PATH, "%s", sysfs_prefix); + + if (!strcmp(t.debugfs_prefix, "")) + snprintf(t.debugfs_prefix, MAX_SYSFS_PATH, "%s", debugfs_prefix); + + ret = find_loopback_devices(&t); + if (ret) + return ret; + ret = sanity_check(&t); + if (ret) + return ret; + + if (t.list_devices) { + show_loopback_devices(&t); + return 0; + } + + if (t.test_name[0] == '\0' || t.iteration_max == 0) + usage(); + + if (t.async_timeout == 0) + t.async_timeout = DEFAULT_ASYNC_TIMEOUT; + + loopback_run(&t); + + return 0; +} -- cgit v0.10.2 From 6bfff1dcb2766ebef60a288601ff4cccbb1f6e54 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 15 Dec 2015 13:55:05 -0800 Subject: greybus: loopback_test: fix warning about signed/unsigned comparison We read an int, don't treat it as a unsigned value, especially when comparing it to a signed value. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/tools/loopback_test.c b/drivers/staging/greybus/tools/loopback_test.c index 55b3102..5c2a9fc 100644 --- a/drivers/staging/greybus/tools/loopback_test.c +++ b/drivers/staging/greybus/tools/loopback_test.c @@ -689,7 +689,7 @@ static int unregister_for_notification(struct loopback_test *t) static int is_complete(struct loopback_test *t) { - uint32_t iteration_count = 0; + int iteration_count; int i; for (i = 0; i < t->device_count; i++) { -- cgit v0.10.2 From d5bc9607f749a241b2491f8f8b07986ba7655350 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 15 Dec 2015 13:57:22 -0800 Subject: greybus: loopback_test: null terminate the dict structure This lets us test for any number of entries, no need to do an ARRAY_SIZE-type comparison. This fixes a build warning of comparing signed/unsigned values.) Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/tools/loopback_test.c b/drivers/staging/greybus/tools/loopback_test.c index 5c2a9fc..27c733d 100644 --- a/drivers/staging/greybus/tools/loopback_test.c +++ b/drivers/staging/greybus/tools/loopback_test.c @@ -34,7 +34,8 @@ struct dict { static struct dict dict[] = { {"ping", 2}, {"transfer", 3}, - {"sink", 4} + {"sink", 4}, + {NULL,} /* list termination */ }; struct loopback_results { @@ -805,7 +806,7 @@ void loopback_run(struct loopback_test *t) int i; int ret; - for (i = 0; i < sizeof(dict) / sizeof(struct dict); i++) { + for (i = 0; dict[i].name != NULL; i++) { if (strstr(dict[i].name, t->test_name)) t->test_id = dict[i].type; } -- cgit v0.10.2 From 70b3b3e77a87d40ceae6e5f4f6afedbd725fd636 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 17 Dec 2015 22:32:03 -0800 Subject: greybus: tools: don't always build them. This breaks the kernel-only build as it can't find any userspace headers with the cross-compiler, so don't build the tools by "default" unless you ask for them. Reported-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 7fd1fc3..29c4c8b 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -85,7 +85,7 @@ ccflags-y := -Wall # needed for trace events ccflags-y += -I$(src) -all: module tools +all: module tools:: $(MAKE) -C tools KERNELDIR=$(realpath $(KERNELDIR)) -- cgit v0.10.2 From c6622216ffaacc6286189121e63cdaae1b6bcbce Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 18 Dec 2015 21:23:21 +0200 Subject: greybus: camera: Fix endian conversion issues Convert all Greybus operation fields between CPU and protocol endianness. Signed-off-by: Laurent Pinchart Reported-by: Rui Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index b7d9384..545ed63 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -103,9 +103,9 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, for (i = 0; i < nstreams; ++i) { struct gb_camera_stream_config_request *cfg = &req->config[i]; - cfg->width = streams[i].width; - cfg->height = streams[i].height; - cfg->format = streams[i].format; + cfg->width = cpu_to_le16(streams[i].width); + cfg->height = cpu_to_le16(streams[i].height); + cfg->format = cpu_to_le16(streams[i].format); cfg->padding = 0; } @@ -131,13 +131,13 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, for (i = 0; i < nstreams; ++i) { struct gb_camera_stream_config_response *cfg = &resp->config[i]; - streams[i].width = cfg->width; - streams[i].height = cfg->height; - streams[i].format = cfg->format; + streams[i].width = le16_to_cpu(cfg->width); + streams[i].height = le16_to_cpu(cfg->height); + streams[i].format = le16_to_cpu(cfg->format); streams[i].vc = cfg->virtual_channel; streams[i].dt[0] = cfg->data_type[0]; streams[i].dt[1] = cfg->data_type[1]; - streams[i].max_size = cfg->max_size; + streams[i].max_size = le32_to_cpu(cfg->max_size); if (cfg->padding[0] || cfg->padding[1] || cfg->padding[2]) { gcam_dbg(gcam, "stream #%u padding != 0", i); @@ -169,10 +169,10 @@ static int gb_camera_capture(struct gb_camera *gcam, u32 request_id, if (!req) return -ENOMEM; - req->request_id = request_id; + req->request_id = cpu_to_le32(request_id); req->streams = streams; req->padding = 0; - req->num_frames = num_frames; + req->num_frames = cpu_to_le16(num_frames); memcpy(req->settings, settings, settings_size); return gb_operation_sync(gcam->connection, GB_CAMERA_TYPE_CAPTURE, @@ -190,7 +190,7 @@ static int gb_camera_flush(struct gb_camera *gcam, u32 *request_id) return ret; if (request_id) - *request_id = resp.request_id; + *request_id = le32_to_cpu(resp.request_id); return 0; } -- cgit v0.10.2 From 784f87614a633f9cca12c35ebb3cbdb1e80452c6 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 18 Dec 2015 21:23:22 +0200 Subject: greybus: svc: Add support for the link config operation Signed-off-by: Laurent Pinchart Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 770a162..a50823c 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -726,6 +726,7 @@ struct gb_spi_transfer_response { #define GB_SVC_TYPE_DME_PEER_SET 0x0a #define GB_SVC_TYPE_ROUTE_CREATE 0x0b #define GB_SVC_TYPE_ROUTE_DESTROY 0x0c +#define GB_SVC_TYPE_LINK_CONFIG 0x0d /* * SVC version request/response has the same payload as @@ -806,6 +807,20 @@ struct gb_svc_dme_peer_set_response { __le16 result_code; } __packed; +#define GB_SVC_LINK_CONFIG_BURST_PWM 0 +#define GB_SVC_LINK_CONFIG_BURST_HS_A 1 +#define GB_SVC_LINK_CONFIG_BURST_HS_B 2 +#define GB_SVC_LINK_CONFIG_FLAG_AUTO_SLEEP (1 << 0) + +struct gb_svc_link_config_request { + __u8 intf_id; + __u8 burst; + __u8 gear; + __u8 nlanes; + __u8 flags; +} __packed; +/* link config response has no payload */ + /* Attributes for peer get/set operations */ #define DME_ATTR_SELECTOR_INDEX 0 #define DME_ATTR_T_TST_SRC_INCREMENT 0x4083 diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 5c4ca79..ff865b3 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -270,6 +270,24 @@ static void gb_svc_route_destroy(struct gb_svc *svc, u8 intf1_id, u8 intf2_id) } } +/* Creates bi-directional routes between the devices */ +int gb_svc_link_config(struct gb_svc *svc, u8 intf_id, + unsigned int burst, unsigned int gear, + unsigned int nlanes, unsigned int flags) +{ + struct gb_svc_link_config_request request; + + request.intf_id = intf_id; + request.burst = burst; + request.gear = gear; + request.nlanes = nlanes; + request.flags = flags; + + return gb_operation_sync(svc->connection, GB_SVC_TYPE_LINK_CONFIG, + &request, sizeof(request), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_svc_link_config); + static int gb_svc_version_request(struct gb_operation *op) { struct gb_connection *connection = op->connection; diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index b7cb7e4..2306035 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -44,6 +44,9 @@ int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, u32 *value); int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, u32 value); +int gb_svc_link_config(struct gb_svc *svc, u8 intf_id, unsigned int burst, + unsigned int gear, unsigned int nlanes, + unsigned int flags); int gb_svc_protocol_init(void); void gb_svc_protocol_exit(void); -- cgit v0.10.2 From bcc050be962179f8004629b0869db8996eb8596c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 18 Dec 2015 21:23:23 +0200 Subject: greybus: camera: Configure link speed for the data connection Hardcode the speed to HS-G1 for now. Signed-off-by: Laurent Pinchart Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 545ed63..f163689 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -576,6 +576,16 @@ static int gb_camera_connection_init(struct gb_connection *connection) if (ret < 0) goto error; + ret = gb_svc_link_config(svc, connection->intf->interface_id, + GB_SVC_LINK_CONFIG_BURST_HS_A, 1, 1, 0); + if (ret < 0) + goto error; + + ret = gb_svc_link_config(svc, svc->ap_intf_id, + GB_SVC_LINK_CONFIG_BURST_HS_A, 1, 1, 0); + if (ret < 0) + goto error; + gcam->data_connected = true; ret = gb_camera_debugfs_init(gcam); -- cgit v0.10.2 From 8e2b7daa23760e7be642e87b2ea5fea78a18fd79 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 18 Dec 2015 21:23:24 +0200 Subject: greybus: es2: Add support for CSI transmitter configuration Export a function from the es2 driver to configure the CSI transmitter through the corresponding USB vendor control request. Signed-off-by: Laurent Pinchart Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 1be4a7c..334ed06 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -13,6 +13,7 @@ #include #include +#include "es2.h" #include "greybus.h" #include "kernel_ver.h" #include "connection.h" @@ -60,6 +61,9 @@ MODULE_DEVICE_TABLE(usb, id_table); #define REQUEST_LATENCY_TAG_EN 0x06 #define REQUEST_LATENCY_TAG_DIS 0x07 +/* vendor request to control the CSI transmitter */ +#define REQUEST_CSI_TX_CONTROL 0x08 + /* * @endpoint: bulk in endpoint for CPort data * @urb: array of urbs for the CPort in messages @@ -130,6 +134,14 @@ struct cport_to_ep { __u8 endpoint_out; }; +struct es2_ap_csi_config_request { + u8 csi_id; + u8 clock_mode; + u8 num_lanes; + u8 padding; + __le32 bus_freq; +} __attribute__((__packed__)); + static inline struct es2_ap_dev *hd_to_es2(struct gb_host_device *hd) { return (struct es2_ap_dev *)&hd->hd_priv; @@ -208,6 +220,42 @@ static int unmap_cport(struct es2_ap_dev *es2, u16 cport_id) } #endif +int es2_ap_csi_setup(struct gb_host_device *hd, bool start, + struct es2_ap_csi_config *cfg) +{ + struct es2_ap_csi_config_request cfg_req; + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct usb_device *udev = es2->usb_dev; + int retval; + + cfg_req.csi_id = cfg->csi_id; + + if (start) { + cfg_req.clock_mode = cfg->clock_mode; + cfg_req.num_lanes = cfg->num_lanes; + cfg_req.padding = 0; + cfg_req.bus_freq = cfg->bus_freq; + } else { + cfg_req.clock_mode = 0; + cfg_req.num_lanes = 0; + cfg_req.padding = 0; + cfg_req.bus_freq = 0; + } + + retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + REQUEST_CSI_TX_CONTROL, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, 0, 0, &cfg_req, + sizeof(cfg_req), ES2_TIMEOUT); + if (retval < 0) { + dev_err(&udev->dev, "failed to setup csi: %d\n", retval); + return retval; + } + + return 0; +} +EXPORT_SYMBOL_GPL(es2_ap_csi_setup); + static int es2_cport_in_enable(struct es2_ap_dev *es2, struct es2_cport_in *cport_in) { diff --git a/drivers/staging/greybus/es2.h b/drivers/staging/greybus/es2.h new file mode 100644 index 0000000..ea29770 --- /dev/null +++ b/drivers/staging/greybus/es2.h @@ -0,0 +1,27 @@ +/* + * Greybus "AP" USB driver for "ES2" controller chips + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#ifndef __ES2_H +#define __ES2_H + +#include + +struct gb_host_device; + +struct es2_ap_csi_config { + u8 csi_id; + u8 clock_mode; + u8 num_lanes; + u32 bus_freq; +}; + +int es2_ap_csi_setup(struct gb_host_device *hd, bool start, + struct es2_ap_csi_config *cfg); + +#endif /* __ES2_H */ -- cgit v0.10.2 From 142b21fee07e858a85bb1b8091d9803cf9fa13e3 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 18 Dec 2015 21:23:25 +0200 Subject: greybus: camera: Configure the bridge CSI transmitter Start or stop the CSI transmitter when configuring and unconfiguring the streams respectively. The CSI configuration parameters are currently hardcoded. Signed-off-by: Laurent Pinchart Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index f163689..556226a 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -16,6 +16,7 @@ #include #include +#include "es2.h" #include "greybus.h" #include "greybus_protocols.h" @@ -79,6 +80,7 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, { struct gb_camera_configure_streams_request *req; struct gb_camera_configure_streams_response *resp; + struct es2_ap_csi_config csi_cfg; unsigned int i; size_t req_size; size_t resp_size; @@ -146,6 +148,27 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, } } + /* Configure the CSI transmitter. Hardcode the parameters for now. */ + if (nstreams && !(resp->flags & GB_CAMERA_CONFIGURE_STREAMS_ADJUSTED)) { + csi_cfg.csi_id = 1; + csi_cfg.clock_mode = 0; + csi_cfg.num_lanes = 2; + csi_cfg.bus_freq = 250000000; + + ret = es2_ap_csi_setup(gcam->connection->hd, true, &csi_cfg); + } else if (nstreams == 0) { + csi_cfg.csi_id = 1; + csi_cfg.clock_mode = 0; + csi_cfg.num_lanes = 0; + csi_cfg.bus_freq = 0; + + ret = es2_ap_csi_setup(gcam->connection->hd, false, &csi_cfg); + } + + if (ret < 0) + gcam_err(gcam, "failed to %s the CSI transmitter\n", + nstreams ? "start" : "stop"); + ret = resp->num_streams; done: -- cgit v0.10.2 From b1c7d67e886be3baf1b2e1f061d09f758709ba9b Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 19 Dec 2015 08:38:56 +0200 Subject: greybus: camera: Set link power mode to HS-G2 with 2 lanes HS-G1 isn't enough for all camera modules. The gear will need to be computed dynamically, but for now hardcode it to 2 with 2 lanes. Signed-off-by: Laurent Pinchart Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 556226a..592c3ef 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -600,12 +600,12 @@ static int gb_camera_connection_init(struct gb_connection *connection) goto error; ret = gb_svc_link_config(svc, connection->intf->interface_id, - GB_SVC_LINK_CONFIG_BURST_HS_A, 1, 1, 0); + GB_SVC_LINK_CONFIG_BURST_HS_A, 2, 2, 0); if (ret < 0) goto error; ret = gb_svc_link_config(svc, svc->ap_intf_id, - GB_SVC_LINK_CONFIG_BURST_HS_A, 1, 1, 0); + GB_SVC_LINK_CONFIG_BURST_HS_A, 2, 2, 0); if (ret < 0) goto error; -- cgit v0.10.2 From 98ce3b0a71c23f924dd031d41171a96eee7fe313 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 22 Dec 2015 03:00:35 +0200 Subject: greybus: camera: Fix remaining endian conversion issues Convert all Greybus operation fields between CPU and protocol endianness. Signed-off-by: Laurent Pinchart Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 592c3ef..c742fea 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -99,7 +99,7 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, goto done; } - req->num_streams = nstreams; + req->num_streams = cpu_to_le16(nstreams); req->padding = 0; for (i = 0; i < nstreams; ++i) { @@ -117,9 +117,9 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, if (ret < 0) return ret; - if (resp->num_streams > nstreams) { + if (le16_to_cpu(resp->num_streams) > nstreams) { gcam_dbg(gcam, "got #streams %u > request %u\n", - resp->num_streams, nstreams); + le16_to_cpu(resp->num_streams), nstreams); ret = -EIO; goto done; } @@ -169,7 +169,7 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, gcam_err(gcam, "failed to %s the CSI transmitter\n", nstreams ? "start" : "stop"); - ret = resp->num_streams; + ret = le16_to_cpu(resp->num_streams); done: kfree(req); -- cgit v0.10.2 From e715a54f4b3fa7d46802984833dc918e44b608e5 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 22 Dec 2015 03:00:36 +0200 Subject: greybus: es2: Fix endian conversion issues Convert all USB request fields between CPU and protocol endianness. Signed-off-by: Laurent Pinchart Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 334ed06..5a991c0 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -234,7 +234,7 @@ int es2_ap_csi_setup(struct gb_host_device *hd, bool start, cfg_req.clock_mode = cfg->clock_mode; cfg_req.num_lanes = cfg->num_lanes; cfg_req.padding = 0; - cfg_req.bus_freq = cfg->bus_freq; + cfg_req.bus_freq = cpu_to_le32(cfg->bus_freq); } else { cfg_req.clock_mode = 0; cfg_req.num_lanes = 0; -- cgit v0.10.2 From ccb58035915d8e915fbf39c389e95bb11fe9aff3 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 22 Dec 2015 03:00:37 +0200 Subject: greybus: es2: Don't use stack memory as USB request data USB request data must be DMAble memory, allocate it with kzalloc() instead of declaring it as a local variable. Signed-off-by: Laurent Pinchart Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 5a991c0..7b07ab7 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -223,36 +223,33 @@ static int unmap_cport(struct es2_ap_dev *es2, u16 cport_id) int es2_ap_csi_setup(struct gb_host_device *hd, bool start, struct es2_ap_csi_config *cfg) { - struct es2_ap_csi_config_request cfg_req; + struct es2_ap_csi_config_request *cfg_req; struct es2_ap_dev *es2 = hd_to_es2(hd); struct usb_device *udev = es2->usb_dev; int retval; - cfg_req.csi_id = cfg->csi_id; + cfg_req = kzalloc(sizeof(*cfg_req), GFP_KERNEL); + if (!cfg_req) + return -ENOMEM; + + cfg_req->csi_id = cfg->csi_id; if (start) { - cfg_req.clock_mode = cfg->clock_mode; - cfg_req.num_lanes = cfg->num_lanes; - cfg_req.padding = 0; - cfg_req.bus_freq = cpu_to_le32(cfg->bus_freq); - } else { - cfg_req.clock_mode = 0; - cfg_req.num_lanes = 0; - cfg_req.padding = 0; - cfg_req.bus_freq = 0; + cfg_req->clock_mode = cfg->clock_mode; + cfg_req->num_lanes = cfg->num_lanes; + cfg_req->bus_freq = cpu_to_le32(cfg->bus_freq); } retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), REQUEST_CSI_TX_CONTROL, USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_INTERFACE, 0, 0, &cfg_req, - sizeof(cfg_req), ES2_TIMEOUT); - if (retval < 0) { + USB_RECIP_INTERFACE, 0, 0, cfg_req, + sizeof(*cfg_req), ES2_TIMEOUT); + if (retval < 0) dev_err(&udev->dev, "failed to setup csi: %d\n", retval); - return retval; - } - return 0; + kfree(cfg_req); + return retval; } EXPORT_SYMBOL_GPL(es2_ap_csi_setup); -- cgit v0.10.2 From 2c7df74468506f390cd53c0af3457943e8076bd8 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 18 Dec 2015 15:04:27 +0530 Subject: greybus: interface: Prefix hexadecimal values with '0x' In order to clearly specify the base of values printed using sysfs files, prefix hexadecimal values with '0x'. Also force the minimum width (to be printed) for hexadecimal values to their sizes. To make it more readable make the second argument to gb_interface_attr() a proper string. Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index ecc64be..c43992d 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -16,15 +16,15 @@ static ssize_t field##_show(struct device *dev, \ char *buf) \ { \ struct gb_interface *intf = to_gb_interface(dev); \ - return scnprintf(buf, PAGE_SIZE, "%"#type"\n", intf->field); \ + return scnprintf(buf, PAGE_SIZE, type"\n", intf->field); \ } \ static DEVICE_ATTR_RO(field) -gb_interface_attr(interface_id, u); -gb_interface_attr(vendor_id, x); -gb_interface_attr(product_id, x); -gb_interface_attr(vendor_string, s); -gb_interface_attr(product_string, s); +gb_interface_attr(interface_id, "%u"); +gb_interface_attr(vendor_id, "0x%08x"); +gb_interface_attr(product_id, "0x%08x"); +gb_interface_attr(vendor_string, "%s"); +gb_interface_attr(product_string, "%s"); static struct attribute *interface_attrs[] = { &dev_attr_interface_id.attr, -- cgit v0.10.2 From 61a748a30d883996c80cc2a4cda9b1e056c75c1b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 22 Dec 2015 17:55:52 +0100 Subject: greybus: svc: drop copy-pasted function header Drop function header that was copied but never updated or removed when adding gb_svc_link_config. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index ff865b3..24b6cdf 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -270,7 +270,6 @@ static void gb_svc_route_destroy(struct gb_svc *svc, u8 intf1_id, u8 intf2_id) } } -/* Creates bi-directional routes between the devices */ int gb_svc_link_config(struct gb_svc *svc, u8 intf_id, unsigned int burst, unsigned int gear, unsigned int nlanes, unsigned int flags) -- cgit v0.10.2 From a5a7723a0d3762387fc765e69f0ab61fd4d47f00 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 22 Dec 2015 17:55:53 +0100 Subject: greybus: es2: clean up csi-config request Use __packed and __u8 for csi-config request that is going out on the wire. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 7b07ab7..af5d7496 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -135,12 +135,12 @@ struct cport_to_ep { }; struct es2_ap_csi_config_request { - u8 csi_id; - u8 clock_mode; - u8 num_lanes; - u8 padding; + __u8 csi_id; + __u8 clock_mode; + __u8 num_lanes; + __u8 padding; __le32 bus_freq; -} __attribute__((__packed__)); +} __packed; static inline struct es2_ap_dev *hd_to_es2(struct gb_host_device *hd) { -- cgit v0.10.2 From b32a5c5346bdaac0ad6ef12cb444a9ad69d2b24b Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 22 Dec 2015 22:04:33 +0530 Subject: greybus: interface: Prefix DDBL1 attributes with ddbl1_ instead of unipro_ The Device descriptor block Level 1 (DDBL1) attributes are specified by the MIPI standard and prefixing them with 'unipro_' isn't the best thing to do. They should be prefixed with DDBL1 instead. To make it more readable/clear: - rename macros and variable by prefixing them with ddbl1_. - write full names for mfg and prod ids as manufacturer and product ids. - replace mfg (manufacturing) with mfr (manufacturer) Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/firmware.c b/drivers/staging/greybus/firmware.c index 9d1739d..5ec3efd 100644 --- a/drivers/staging/greybus/firmware.c +++ b/drivers/staging/greybus/firmware.c @@ -11,8 +11,8 @@ #include "greybus.h" -#define ES2_UNIPRO_MFG_ID 0x00000126 -#define ES2_UNIPRO_PROD_ID 0x00001000 +#define ES2_DDBL1_MFR_ID 0x00000126 +#define ES2_DDBL1_PROD_ID 0x00001000 struct gb_firmware { struct gb_connection *connection; @@ -49,8 +49,8 @@ static void firmware_es2_fixup_vid_pid(struct gb_firmware *firmware) * - Bridge ASIC chip isn't ES2 * - Received non-zero Vendor/Product ids */ - if (intf->unipro_mfg_id != ES2_UNIPRO_MFG_ID || - intf->unipro_prod_id != ES2_UNIPRO_PROD_ID || + if (intf->ddbl1_manufacturer_id != ES2_DDBL1_MFR_ID || + intf->ddbl1_product_id != ES2_DDBL1_PROD_ID || intf->vendor_id != 0 || intf->product_id != 0) return; @@ -84,7 +84,7 @@ static int download_firmware(struct gb_firmware *firmware, u8 stage) */ snprintf(firmware_name, sizeof(firmware_name), "ara:%08x:%08x:%08x:%08x:%02x.tftf", - intf->unipro_mfg_id, intf->unipro_prod_id, + intf->ddbl1_manufacturer_id, intf->ddbl1_product_id, firmware->vendor_id, firmware->product_id, stage); return request_firmware(&firmware->fw, firmware_name, diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index a50823c..76416b5 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -749,8 +749,8 @@ struct gb_svc_intf_device_id_request { struct gb_svc_intf_hotplug_request { __u8 intf_id; struct { - __le32 unipro_mfg_id; - __le32 unipro_prod_id; + __le32 ddbl1_mfr_id; + __le32 ddbl1_prod_id; __le32 ara_vend_id; __le32 ara_prod_id; } data; diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index ca123ce..d192b74 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -26,8 +26,8 @@ struct gb_interface { char *product_string; /* Information taken from the hotplug event */ - u32 unipro_mfg_id; - u32 unipro_prod_id; + u32 ddbl1_manufacturer_id; + u32 ddbl1_product_id; u32 vendor_id; u32 product_id; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 24b6cdf..864051b 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -417,8 +417,8 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) goto destroy_interface; } - intf->unipro_mfg_id = le32_to_cpu(request->data.unipro_mfg_id); - intf->unipro_prod_id = le32_to_cpu(request->data.unipro_prod_id); + intf->ddbl1_manufacturer_id = le32_to_cpu(request->data.ddbl1_mfr_id); + intf->ddbl1_product_id = le32_to_cpu(request->data.ddbl1_prod_id); intf->vendor_id = le32_to_cpu(request->data.ara_vend_id); intf->product_id = le32_to_cpu(request->data.ara_prod_id); -- cgit v0.10.2 From 0e9403a0fbf704b40ae80c2379b643caed924a5e Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 22 Dec 2015 22:04:34 +0530 Subject: greybus: interface: Expose DDBL1 manufacturing and production id in sysfs These ids are already fetched from the SVC, but were never exposed to sysfs. Userspace may be interested in using these values and hence these must be exposed to it. Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index a0363bf..2cd17c7 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -14,6 +14,22 @@ Description: An Interface I on the bus N, where I is the 1-byte interface ID. +What: /sys/bus/greybus/device/N-I/ddbl1_manufacturer_id +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + Unipro Device Descriptor Block Level 1 manufacturer ID for the + greybus Interface. + +What: /sys/bus/greybus/device/N-I/ddbl1_product_id +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + Unipro Device Descriptor Block Level 1 product ID for the + greybus Interface. + What: /sys/bus/greybus/device/N-I/interface_id Date: October 2015 KernelVersion: 4.XX diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/ddbl1_manufacturer_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/ddbl1_manufacturer_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/ddbl1_product_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/ddbl1_product_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/ddbl1_manufacturer_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/ddbl1_manufacturer_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/ddbl1_product_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/ddbl1_product_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/ddbl1_manufacturer_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/ddbl1_manufacturer_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/ddbl1_product_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/ddbl1_product_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index c43992d..c4b9e14 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -20,6 +20,8 @@ static ssize_t field##_show(struct device *dev, \ } \ static DEVICE_ATTR_RO(field) +gb_interface_attr(ddbl1_manufacturer_id, "0x%08x"); +gb_interface_attr(ddbl1_product_id, "0x%08x"); gb_interface_attr(interface_id, "%u"); gb_interface_attr(vendor_id, "0x%08x"); gb_interface_attr(product_id, "0x%08x"); @@ -27,6 +29,8 @@ gb_interface_attr(vendor_string, "%s"); gb_interface_attr(product_string, "%s"); static struct attribute *interface_attrs[] = { + &dev_attr_ddbl1_manufacturer_id.attr, + &dev_attr_ddbl1_product_id.attr, &dev_attr_interface_id.attr, &dev_attr_vendor_id.attr, &dev_attr_product_id.attr, -- cgit v0.10.2 From 3563ff88e65e544f09569195b07841dd48d60e57 Mon Sep 17 00:00:00 2001 From: Eli Sennesh Date: Tue, 22 Dec 2015 17:26:57 -0500 Subject: greybus: firmware and svc: detect the difference between ES2 and ES3 chips The Greybus SVC code needs to read and clear the module boot status upon hotplug; this requires reading two different attributes depending on whether we're running on ES2 or ES3. On Marti Bolivar's (mbolivar@leaflabs.com) advice, we detect ES2 using the unique ES2_DDBL1_MFR_ID and ES2_DDBL1_PROD_ID for ES2 hardware, and treat all other chips as ES3 appropriately. This patch detects the difference and adds the appropriate definitions for ES3 hardware. Signed-off-by: Eli Sennesh Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/firmware.c b/drivers/staging/greybus/firmware.c index 5ec3efd..c65f294 100644 --- a/drivers/staging/greybus/firmware.c +++ b/drivers/staging/greybus/firmware.c @@ -11,9 +11,6 @@ #include "greybus.h" -#define ES2_DDBL1_MFR_ID 0x00000126 -#define ES2_DDBL1_PROD_ID 0x00001000 - struct gb_firmware { struct gb_connection *connection; const struct firmware *fw; diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 76416b5..53c1dea 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -160,6 +160,10 @@ struct gb_control_disconnected_request { #define GB_FIRMWARE_TYPE_AP_READY 0x05 /* Request with no-payload */ #define GB_FIRMWARE_TYPE_GET_VID_PID 0x06 /* Request with no-payload */ +/* FIXME: remove all ES2-specific identifiers from the kernel */ +#define ES2_DDBL1_MFR_ID 0x00000126 +#define ES2_DDBL1_PROD_ID 0x00001000 + /* Greybus firmware boot stages */ #define GB_FIRMWARE_BOOT_STAGE_ONE 0x01 /* Reserved for the boot ROM */ #define GB_FIRMWARE_BOOT_STAGE_TWO 0x02 /* Firmware package to be loaded by the boot ROM */ @@ -823,14 +827,16 @@ struct gb_svc_link_config_request { /* Attributes for peer get/set operations */ #define DME_ATTR_SELECTOR_INDEX 0 +/* FIXME: remove ES2 support and DME_ATTR_T_TST_SRC_INCREMENT */ #define DME_ATTR_T_TST_SRC_INCREMENT 0x4083 - -/* Return value from TST_SRC_INCREMENT */ -#define DME_TSI_SPI_BOOT_STARTED 0x02 -#define DME_TSI_TRUSTED_SPI_BOOT_FINISHED 0x03 -#define DME_TSI_UNTRUSTED_SPI_BOOT_FINISHED 0x04 -#define DME_TSI_UNIPRO_BOOT_STARTED 0x06 -#define DME_TSI_FALLBACK_UNIPRO_BOOT_STARTED 0x09 +#define DME_ATTR_ES3_INIT_STATUS 0x6101 + +/* Return value from init-status attributes listed above */ +#define DME_DIS_SPI_BOOT_STARTED 0x02 +#define DME_DIS_TRUSTED_SPI_BOOT_FINISHED 0x03 +#define DME_DIS_UNTRUSTED_SPI_BOOT_FINISHED 0x04 +#define DME_DIS_UNIPRO_BOOT_STARTED 0x06 +#define DME_DIS_FALLBACK_UNIPRO_BOOT_STARTED 0x09 struct gb_svc_route_create_request { __u8 intf1_id; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 864051b..3e760e6 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -139,8 +139,8 @@ EXPORT_SYMBOL_GPL(gb_svc_dme_peer_set); /* * T_TstSrcIncrement is written by the module on ES2 as a stand-in for boot - * status attribute. AP needs to read and clear it, after reading a non-zero - * value from it. + * status attribute ES3_INIT_STATUS. AP needs to read and clear it, after + * reading a non-zero value from it. * * FIXME: This is module-hardware dependent and needs to be extended for every * type of module we want to support. @@ -150,10 +150,22 @@ static int gb_svc_read_and_clear_module_boot_status(struct gb_interface *intf) struct gb_host_device *hd = intf->hd; int ret; u32 value; + u16 attr; + u8 init_status; - /* Read and clear boot status in T_TstSrcIncrement */ - ret = gb_svc_dme_peer_get(hd->svc, intf->interface_id, - DME_ATTR_T_TST_SRC_INCREMENT, + /* + * Check if the module is ES2 or ES3, and choose attr number + * appropriately. + * FIXME: Remove ES2 support from the kernel entirely. + */ + if (intf->ddbl1_manufacturer_id == ES2_DDBL1_MFR_ID && + intf->ddbl1_product_id == ES2_DDBL1_PROD_ID) + attr = DME_ATTR_T_TST_SRC_INCREMENT; + else + attr = DME_ATTR_ES3_INIT_STATUS; + + /* Read and clear boot status in ES3_INIT_STATUS */ + ret = gb_svc_dme_peer_get(hd->svc, intf->interface_id, attr, DME_ATTR_SELECTOR_INDEX, &value); if (ret) @@ -169,19 +181,22 @@ static int gb_svc_read_and_clear_module_boot_status(struct gb_interface *intf) } /* - * Check if the module needs to boot from unipro. + * Check if the module needs to boot from UniPro. * For ES2: We need to check lowest 8 bits of 'value'. * For ES3: We need to check highest 8 bits out of 32 of 'value'. - * - * FIXME: Add code to find if we are on ES2 or ES3 to have separate - * checks. + * FIXME: Remove ES2 support from the kernel entirely. */ - if (value == DME_TSI_UNIPRO_BOOT_STARTED || - value == DME_TSI_FALLBACK_UNIPRO_BOOT_STARTED) + if (intf->ddbl1_manufacturer_id == ES2_DDBL1_MFR_ID && + intf->ddbl1_product_id == ES2_DDBL1_PROD_ID) + init_status = value; + else + init_status = value >> 24; + + if (init_status == DME_DIS_UNIPRO_BOOT_STARTED || + init_status == DME_DIS_FALLBACK_UNIPRO_BOOT_STARTED) intf->boot_over_unipro = true; - return gb_svc_dme_peer_set(hd->svc, intf->interface_id, - DME_ATTR_T_TST_SRC_INCREMENT, + return gb_svc_dme_peer_set(hd->svc, intf->interface_id, attr, DME_ATTR_SELECTOR_INDEX, 0); } -- cgit v0.10.2 From 0b8af6a901512a61e687e765c75c8d3ca9867493 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Wed, 16 Dec 2015 16:29:17 +0530 Subject: greybus: db3(arche)-platform: Remove all APB control code Current db3(arche)-platform driver was only handling APB control signals, which is where it all started. But now with completion of DB3/EVT1 bringup we know that platform driver is more than APB control. We have to bring SVC up before APB, as SVC supposed to enable clock to APB's. Note that, in EVT1, AP will have direct control over APB's clock. Then we have dependency between APB and USB HUB, where, APB should be brought up before USB HUB (note that this needs to rootcaused). This patch cleanup the db3(arche)-platform driver to remove all APB control code. The idea here is create another driver for APB control (arche-apb-ctrl.c), which will deal with APB. And this driver will have generic/common platform specific support, currently manages SVC resources. This patch also takes in all the changes from factory branch, discovered during bringup. Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/db3-platform.c b/drivers/staging/greybus/db3-platform.c index 31f27f0..eede56b 100644 --- a/drivers/staging/greybus/db3-platform.c +++ b/drivers/staging/greybus/db3-platform.c @@ -1,5 +1,5 @@ /* - * DB3 Platform driver for AP bridge control interface. + * DB3 Platform driver to enable Unipro link. * * Copyright 2014-2015 Google Inc. * Copyright 2014-2015 Linaro Ltd. @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -23,304 +24,141 @@ #include #include -enum apb_state { - APB_STATE_OFF, - APB_STATE_ACTIVE, - APB_STATE_STANDBY, -}; - -/* - * Control GPIO signals to and from AP <=> AP Bridges - */ -struct apb_ctrl_gpios { - int wake_detect; /* bi-dir, maps to WAKE_MOD and WAKE_FRAME signals */ - int reset; - int boot_ret; - int pwroff; - int wake_in; - int wake_out; - int pwrdn; -}; - -struct apb_ctrl_drvdata { - struct apb_ctrl_gpios ctrl; +struct db3_platform_drvdata { + /* Control GPIO signals to and from AP <=> SVC */ + int svc_reset_gpio; + bool is_reset_act_hi; + int svc_sysboot_gpio; - unsigned int wake_detect_irq; - enum apb_state state; - - struct regulator *vcore; - struct regulator *vio; + unsigned int svc_refclk_req; + struct clk *svc_ref_clk; struct pinctrl *pinctrl; struct pinctrl_state *pin_default; - /* To protect concurrent access of GPIO registers, need protection */ - spinlock_t lock; + int num_apbs; }; -static inline void assert_wake(unsigned int wake_detect) -{ - gpio_set_value(wake_detect, 1); -} - -static inline void deassert_wake(unsigned int wake_detect) -{ - gpio_set_value(wake_detect, 0); -} - -static irqreturn_t apb_ctrl_wake_detect_irq(int irq, void *devid) +static inline void svc_reset_onoff(unsigned int gpio, bool onoff) { - struct apb_ctrl_drvdata *apb_data = devid; - unsigned long flags; - - /* - * TODO: - * Since currently SoC GPIOs are being used we are safe here - * But ideally we should create a workqueue and process the control - * signals, especially when we start using GPIOs over slow - * buses like I2C. - */ - if (!gpio_is_valid(apb_data->ctrl.wake_detect) && - !gpio_is_valid(apb_data->ctrl.reset)) - return IRQ_HANDLED; /* Should it be IRQ_NONE ?? */ - - spin_lock_irqsave(&apb_data->lock, flags); - - if (apb_data->state != APB_STATE_ACTIVE) { - /* Bring bridge out of reset on this event */ - gpio_set_value(apb_data->ctrl.reset, 0); - apb_data->state = APB_STATE_ACTIVE; - } else { - /* - * Assert Wake_OUT signal to APB - * It would resemble WakeDetect module's signal pass-through - */ - /* - * We have to generate the pulse, so we may need to schedule - * workqueue here. - * - * Also, since we are using both rising and falling edge for - * interrupt trigger, we may not need workqueue. Just pass - * through the value to bridge. - * Just read GPIO value and pass it to the bridge - */ - } - - spin_unlock_irqrestore(&apb_data->lock, flags); - - return IRQ_HANDLED; + gpio_set_value(gpio, onoff); } -static void apb_ctrl_cleanup(struct apb_ctrl_drvdata *apb_data) +static void db3_platform_cleanup(struct db3_platform_drvdata *db3_pdata) { - if (apb_data->vcore && regulator_is_enabled(apb_data->vcore) > 0) - regulator_disable(apb_data->vcore); - - if (apb_data->vio && regulator_is_enabled(apb_data->vio) > 0) - regulator_disable(apb_data->vio); - /* As part of exit, put APB back in reset state */ - if (gpio_is_valid(apb_data->ctrl.reset)) - gpio_set_value(apb_data->ctrl.reset, 1); - - /* TODO: May have to send an event to SVC about this exit */ + if (gpio_is_valid(db3_pdata->svc_reset_gpio)) + svc_reset_onoff(db3_pdata->svc_reset_gpio, + db3_pdata->is_reset_act_hi); } -/* - * Note: Please do not modify the below sequence, as it is as per the spec - */ -static int apb_ctrl_init_seq(struct device *dev, - struct apb_ctrl_drvdata *apb_data) +static int db3_platform_probe(struct platform_device *pdev) { + struct db3_platform_drvdata *db3_pdata; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; int ret; - pinctrl_select_state(apb_data->pinctrl, apb_data->pin_default); + db3_pdata = devm_kzalloc(&pdev->dev, sizeof(*db3_pdata), GFP_KERNEL); + if (!db3_pdata) + return -ENOMEM; - /* Hold APB in reset state */ - ret = devm_gpio_request_one(dev, apb_data->ctrl.reset, - GPIOF_OUT_INIT_LOW, "reset"); - if (ret) { - dev_err(dev, "Failed requesting reset gpio %d\n", - apb_data->ctrl.reset); + /* setup svc reset gpio */ + db3_pdata->is_reset_act_hi = of_property_read_bool(np, "svc,reset-active-high"); + db3_pdata->svc_reset_gpio = of_get_named_gpio(np, "svc,reset-gpio", 0); + if (db3_pdata->svc_reset_gpio < 0) { + dev_err(dev, "failed to get reset-gpio\n"); + ret = -ENODEV; return ret; } - - /* Enable power to APB */ - if (apb_data->vcore) { - ret = regulator_enable(apb_data->vcore); - if (ret) { - dev_err(dev, "failed to enable core regulator\n"); - return ret; - } - } - - if (apb_data->vio) { - ret = regulator_enable(apb_data->vio); - if (ret) { - dev_err(dev, "failed to enable IO regulator\n"); - return ret; - } - } - - /* - * We should be safe here to deassert boot retention signal, as - * we are only supporting cold boot as of now. - */ - ret = devm_gpio_request_one(dev, apb_data->ctrl.boot_ret, - GPIOF_OUT_INIT_LOW, "boot retention"); + ret = devm_gpio_request(dev, db3_pdata->svc_reset_gpio, "svc-reset"); if (ret) { - dev_err(dev, "Failed requesting reset gpio %d\n", - apb_data->ctrl.boot_ret); + dev_err(dev, "failed to request svc-reset gpio:%d\n", ret); return ret; } - - ret = devm_gpio_request(dev, apb_data->ctrl.wake_detect, "wake detect"); - if (ret) - dev_err(dev, "Failed requesting wake_detect gpio %d\n", - apb_data->ctrl.wake_detect); - - return ret; -} - -static int apb_ctrl_get_devtree_data(struct device *dev, - struct apb_ctrl_drvdata *apb_data) -{ - struct device_node *np = dev->of_node; - - /* fetch control signals */ - apb_data->ctrl.wake_detect = of_get_named_gpio(np, "wake-detect-gpios", 0); - if (!gpio_is_valid(apb_data->ctrl.wake_detect)) { - dev_err(dev, "failed to get wake detect gpio\n"); - return apb_data->ctrl.wake_detect; - } - - apb_data->ctrl.reset = of_get_named_gpio(np, "reset-gpios", 0); - if (!gpio_is_valid(apb_data->ctrl.reset)) { - dev_err(dev, "failed to get reset gpio\n"); - return apb_data->ctrl.reset; + ret = gpio_direction_output(db3_pdata->svc_reset_gpio, db3_pdata->is_reset_act_hi); + if (ret) { + dev_err(dev, "failed to set svc-reset gpio dir:%d\n", ret); + return ret; } - apb_data->ctrl.boot_ret = of_get_named_gpio(np, "boot-ret-gpios", 0); - if (!gpio_is_valid(apb_data->ctrl.boot_ret)) { - dev_err(dev, "failed to get boot retention gpio\n"); - return apb_data->ctrl.boot_ret; + db3_pdata->svc_sysboot_gpio = of_get_named_gpio(np, "svc,sysboot-gpio", 0); + if (db3_pdata->svc_sysboot_gpio < 0) { + dev_err(dev, "failed to get sysboot gpio\n"); + ret = -ENODEV; + return ret; } - - /* It's not mandatory to support power management interface */ - apb_data->ctrl.pwroff = of_get_named_gpio(np, "pwr-off-gpios", 0); - if (!gpio_is_valid(apb_data->ctrl.pwroff)) - dev_info(dev, "failed to get power off gpio\n"); - - apb_data->ctrl.pwrdn = of_get_named_gpio(np, "pwr-down-gpios", 0); - if (!gpio_is_valid(apb_data->ctrl.pwrdn)) - dev_info(dev, "failed to get power down gpio\n"); - - /* Regulators are optional, as we may have fixed supply coming in */ - apb_data->vcore = devm_regulator_get(dev, "vcore"); - if (IS_ERR_OR_NULL(apb_data->vcore)) { - dev_info(dev, "no core regulator found\n"); - apb_data->vcore = NULL; + ret = devm_gpio_request(dev, db3_pdata->svc_sysboot_gpio, "sysboot0"); + if (ret) { + dev_err(dev, "failed to request sysboot0 gpio:%d\n", ret); + return ret; } - - apb_data->vio = devm_regulator_get(dev, "vio"); - if (IS_ERR_OR_NULL(apb_data->vio)) { - dev_info(dev, "no IO regulator found\n"); - apb_data->vio = NULL; + ret = gpio_direction_output(db3_pdata->svc_sysboot_gpio, 0); + if (ret) { + dev_err(dev, "failed to set svc-reset gpio dir:%d\n", ret); + return ret; } - apb_data->pinctrl = devm_pinctrl_get(dev); - if (IS_ERR(apb_data->pinctrl)) { - dev_err(dev, "could not get pinctrl handle\n"); - return PTR_ERR(apb_data->pinctrl); + /* setup the clock request gpio first */ + db3_pdata->svc_refclk_req = of_get_named_gpio(np, "svc,refclk-req-gpio", 0); + if (db3_pdata->svc_refclk_req < 0) { + dev_err(dev, "failed to get svc clock-req gpio\n"); + return -ENODEV; } - apb_data->pin_default = pinctrl_lookup_state(apb_data->pinctrl, "default"); - if (IS_ERR(apb_data->pin_default)) { - dev_err(dev, "could not get default pin state\n"); - return PTR_ERR(apb_data->pin_default); + ret = devm_gpio_request(dev, db3_pdata->svc_refclk_req, "svc-clk-req"); + if (ret) { + dev_err(dev, "failed to request svc-clk-req gpio: %d\n", ret); + return ret; } - - return 0; -} - -static int apb_ctrl_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct apb_ctrl_drvdata *apb_data; - int ret; - - apb_data = devm_kzalloc(&pdev->dev, sizeof(*apb_data), GFP_KERNEL); - if (!apb_data) - return -ENOMEM; - - ret = apb_ctrl_get_devtree_data(dev, apb_data); + ret = gpio_direction_input(db3_pdata->svc_refclk_req); if (ret) { - dev_err(dev, "failed to get devicetree data %d\n", ret); + dev_err(dev, "failed to set svc-clk-req gpio dir :%d\n", ret); return ret; } - ret = apb_ctrl_init_seq(dev, apb_data); + /* setup refclk2 to follow the pin */ + db3_pdata->svc_ref_clk = devm_clk_get(dev, "svc_ref_clk"); + if (IS_ERR(db3_pdata->svc_ref_clk)) { + ret = PTR_ERR(db3_pdata->svc_ref_clk); + dev_err(dev, "failed to get svc_ref_clk: %d\n", ret); + return ret; + } + ret = clk_prepare_enable(db3_pdata->svc_ref_clk); if (ret) { - dev_err(dev, "failed to set init state of control signal %d\n", - ret); - goto exit; + dev_err(dev, "failed to enable svc_ref_clk: %d\n", ret); + return ret; } - platform_set_drvdata(pdev, apb_data); - - apb_data->state = APB_STATE_OFF; - /* - * Assert AP module detect signal by pulling wake_detect low - */ - deassert_wake(apb_data->ctrl.wake_detect); + platform_set_drvdata(pdev, db3_pdata); - /* - * In order to receive an interrupt, the GPIO must be set to input mode - * - * As per WDM spec, for the cold boot, the wake pulse must be - * >= 5000 usec, but at this stage it is power up sequence, - * so we always treat it as cold boot. - */ - gpio_direction_input(apb_data->ctrl.wake_detect); + db3_pdata->num_apbs = of_get_child_count(np); + dev_dbg(dev, "Number of APB's available - %d\n", db3_pdata->num_apbs); - ret = devm_request_irq(dev, gpio_to_irq(apb_data->ctrl.wake_detect), - apb_ctrl_wake_detect_irq, - IRQF_TRIGGER_RISING, - "wake detect", apb_data); - if (ret) { - dev_err(&pdev->dev, "failed to request wake detect IRQ\n"); - goto exit; - } + /* bring SVC out of reset */ + svc_reset_onoff(db3_pdata->svc_reset_gpio, !db3_pdata->is_reset_act_hi); - /* - * Interrupt handling for WAKE_IN (from bridge) signal is required - * - * Assumption here is, AP already would have woken up and in the - * WAKE_IN/WAKE_FRAME event from bridge, as AP would pass-through event - * to SVC. - * - * Not sure anything else needs to take care here. - */ - dev_info(dev, "Device registered successfully \n"); - return 0; + /* probe all childs here */ + ret = of_platform_populate(np, NULL, NULL, dev); + if (ret) + dev_err(dev, "no child node found\n"); -exit: - apb_ctrl_cleanup(apb_data); + dev_info(dev, "Device registered successfully\n"); return ret; } -static int apb_ctrl_remove(struct platform_device *pdev) +static int db3_platform_remove(struct platform_device *pdev) { - struct apb_ctrl_drvdata *apb_data = platform_get_drvdata(pdev); + struct db3_platform_drvdata *db3_pdata = platform_get_drvdata(pdev); - if (apb_data) - apb_ctrl_cleanup(apb_data); + if (db3_pdata) + db3_platform_cleanup(db3_pdata); platform_set_drvdata(pdev, NULL); return 0; } -static int apb_ctrl_suspend(struct device *dev) +static int db3_platform_suspend(struct device *dev) { /* * If timing profile premits, we may shutdown bridge @@ -334,7 +172,7 @@ static int apb_ctrl_suspend(struct device *dev) return 0; } -static int apb_ctrl_resume(struct device *dev) +static int db3_platform_resume(struct device *dev) { /* * Atleast for ES2 we have to meet the delay requirement between @@ -348,26 +186,26 @@ static int apb_ctrl_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(apb_ctrl_pm_ops, apb_ctrl_suspend, apb_ctrl_resume); +static SIMPLE_DEV_PM_OPS(db3_platform_pm_ops, db3_platform_suspend, db3_platform_resume); -static struct of_device_id apb_ctrl_of_match[] = { - { .compatible = "usbffff,2", }, +static struct of_device_id db3_platform_of_match[] = { + { .compatible = "google,db3-platform", }, /* Use PID/VID of SVC device */ { }, }; -MODULE_DEVICE_TABLE(of, apb_ctrl_of_match); +MODULE_DEVICE_TABLE(of, db3_platform_of_match); -static struct platform_driver apb_ctrl_device_driver = { - .probe = apb_ctrl_probe, - .remove = apb_ctrl_remove, +static struct platform_driver db3_platform_device_driver = { + .probe = db3_platform_probe, + .remove = db3_platform_remove, .driver = { - .name = "unipro-APbridge", - .pm = &apb_ctrl_pm_ops, - .of_match_table = of_match_ptr(apb_ctrl_of_match), + .name = "db3-platform-ctrl", + .pm = &db3_platform_pm_ops, + .of_match_table = of_match_ptr(db3_platform_of_match), } }; -module_platform_driver(apb_ctrl_device_driver); +module_platform_driver(db3_platform_device_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Vaibhav Hiremath "); -MODULE_DESCRIPTION("AP Bridge Control Driver for DB3 platform"); +MODULE_DESCRIPTION("DB3 Platform Driver"); -- cgit v0.10.2 From 7fa60654752bd4fbbe1e35e310a4bc96b6a3dec3 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Wed, 16 Dec 2015 16:29:18 +0530 Subject: greybus: arche-platform: Rename db3-platform to arche-platform With multiple platforms getting rolled into ara, db3 name is confusing. And this driver is applicable to all arche platforms, so make sense to rename it to arche-platform.c. Also rename all internal functions accordingly. Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 29c4c8b..bc4de85 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -28,7 +28,7 @@ gb-light-y := light.o gb-raw-y := raw.o gb-hid-y := hid.o gb-es2-y := es2.o -gb-db3-y := db3-platform.o +gb-arche-y := arche-platform.o gb-audio-codec-y := audio-codec.o gb-camera-y := camera.o @@ -41,7 +41,7 @@ obj-m += gb-light.o obj-m += gb-hid.o obj-m += gb-raw.o obj-m += gb-es2.o -obj-m += gb-db3.o +obj-m += gb-arche.o obj-m += gb-audio-codec.o obj-m += gb-camera.o diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c new file mode 100644 index 0000000..7d90f5d --- /dev/null +++ b/drivers/staging/greybus/arche-platform.c @@ -0,0 +1,216 @@ +/* + * Arche Platform driver to enable Unipro link. + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct arche_platform_drvdata { + /* Control GPIO signals to and from AP <=> SVC */ + int svc_reset_gpio; + bool is_reset_act_hi; + int svc_sysboot_gpio; + + unsigned int svc_refclk_req; + struct clk *svc_ref_clk; + + struct pinctrl *pinctrl; + struct pinctrl_state *pin_default; + + int num_apbs; +}; + +static inline void svc_reset_onoff(unsigned int gpio, bool onoff) +{ + gpio_set_value(gpio, onoff); +} + +static void arche_platform_cleanup(struct arche_platform_drvdata *arche_pdata) +{ + /* As part of exit, put APB back in reset state */ + if (gpio_is_valid(arche_pdata->svc_reset_gpio)) + svc_reset_onoff(arche_pdata->svc_reset_gpio, + arche_pdata->is_reset_act_hi); +} + +static int arche_platform_probe(struct platform_device *pdev) +{ + struct arche_platform_drvdata *arche_pdata; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + int ret; + + arche_pdata = devm_kzalloc(&pdev->dev, sizeof(*arche_pdata), GFP_KERNEL); + if (!arche_pdata) + return -ENOMEM; + + /* setup svc reset gpio */ + arche_pdata->is_reset_act_hi = of_property_read_bool(np, + "svc,reset-active-high"); + arche_pdata->svc_reset_gpio = of_get_named_gpio(np, "svc,reset-gpio", 0); + if (arche_pdata->svc_reset_gpio < 0) { + dev_err(dev, "failed to get reset-gpio\n"); + return -ENODEV; + } + ret = devm_gpio_request(dev, arche_pdata->svc_reset_gpio, "svc-reset"); + if (ret) { + dev_err(dev, "failed to request svc-reset gpio:%d\n", ret); + return ret; + } + ret = gpio_direction_output(arche_pdata->svc_reset_gpio, + arche_pdata->is_reset_act_hi); + if (ret) { + dev_err(dev, "failed to set svc-reset gpio dir:%d\n", ret); + return ret; + } + + arche_pdata->svc_sysboot_gpio = of_get_named_gpio(np, + "svc,sysboot-gpio", 0); + if (arche_pdata->svc_sysboot_gpio < 0) { + dev_err(dev, "failed to get sysboot gpio\n"); + return -ENODEV; + } + ret = devm_gpio_request(dev, arche_pdata->svc_sysboot_gpio, "sysboot0"); + if (ret) { + dev_err(dev, "failed to request sysboot0 gpio:%d\n", ret); + return ret; + } + ret = gpio_direction_output(arche_pdata->svc_sysboot_gpio, 0); + if (ret) { + dev_err(dev, "failed to set svc-reset gpio dir:%d\n", ret); + return ret; + } + + /* setup the clock request gpio first */ + arche_pdata->svc_refclk_req = of_get_named_gpio(np, + "svc,refclk-req-gpio", 0); + if (arche_pdata->svc_refclk_req < 0) { + dev_err(dev, "failed to get svc clock-req gpio\n"); + return -ENODEV; + } + ret = devm_gpio_request(dev, arche_pdata->svc_refclk_req, "svc-clk-req"); + if (ret) { + dev_err(dev, "failed to request svc-clk-req gpio: %d\n", ret); + return ret; + } + ret = gpio_direction_input(arche_pdata->svc_refclk_req); + if (ret) { + dev_err(dev, "failed to set svc-clk-req gpio dir :%d\n", ret); + return ret; + } + + /* setup refclk2 to follow the pin */ + arche_pdata->svc_ref_clk = devm_clk_get(dev, "svc_ref_clk"); + if (IS_ERR(arche_pdata->svc_ref_clk)) { + ret = PTR_ERR(arche_pdata->svc_ref_clk); + dev_err(dev, "failed to get svc_ref_clk: %d\n", ret); + return ret; + } + ret = clk_prepare_enable(arche_pdata->svc_ref_clk); + if (ret) { + dev_err(dev, "failed to enable svc_ref_clk: %d\n", ret); + return ret; + } + + platform_set_drvdata(pdev, arche_pdata); + + /* bring SVC out of reset */ + svc_reset_onoff(arche_pdata->svc_reset_gpio, + !arche_pdata->is_reset_act_hi); + + arche_pdata->num_apbs = of_get_child_count(np); + dev_dbg(dev, "Number of APB's available - %d\n", arche_pdata->num_apbs); + + /* probe all childs here */ + ret = of_platform_populate(np, NULL, NULL, dev); + if (ret) + dev_err(dev, "no child node found\n"); + + dev_info(dev, "Device registered successfully\n"); + return ret; +} + +static int arche_platform_remove(struct platform_device *pdev) +{ + struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev); + + if (arche_pdata) + arche_platform_cleanup(arche_pdata); + + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static int arche_platform_suspend(struct device *dev) +{ + /* + * If timing profile premits, we may shutdown bridge + * completely + * + * TODO: sequence ?? + * + * Also, need to make sure we meet precondition for unipro suspend + * Precondition: Definition ??? + */ + return 0; +} + +static int arche_platform_resume(struct device *dev) +{ + /* + * Atleast for ES2 we have to meet the delay requirement between + * unipro switch and AP bridge init, depending on whether bridge is in + * OFF state or standby state. + * + * Based on whether bridge is in standby or OFF state we may have to + * assert multiple signals. Please refer to WDM spec, for more info. + * + */ + return 0; +} + +static SIMPLE_DEV_PM_OPS(arche_platform_pm_ops, + arche_platform_suspend, + arche_platform_resume); + +static struct of_device_id arche_platform_of_match[] = { + { .compatible = "google,arche-platform", }, /* Use PID/VID of SVC device */ + { }, +}; +MODULE_DEVICE_TABLE(of, arche_platform_of_match); + +static struct platform_driver arche_platform_device_driver = { + .probe = arche_platform_probe, + .remove = arche_platform_remove, + .driver = { + .name = "arche-platform-ctrl", + .pm = &arche_platform_pm_ops, + .of_match_table = of_match_ptr(arche_platform_of_match), + } +}; + +module_platform_driver(arche_platform_device_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Vaibhav Hiremath "); +MODULE_DESCRIPTION("Arche Platform Driver"); diff --git a/drivers/staging/greybus/db3-platform.c b/drivers/staging/greybus/db3-platform.c deleted file mode 100644 index eede56b..0000000 --- a/drivers/staging/greybus/db3-platform.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - * DB3 Platform driver to enable Unipro link. - * - * Copyright 2014-2015 Google Inc. - * Copyright 2014-2015 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct db3_platform_drvdata { - /* Control GPIO signals to and from AP <=> SVC */ - int svc_reset_gpio; - bool is_reset_act_hi; - int svc_sysboot_gpio; - - unsigned int svc_refclk_req; - struct clk *svc_ref_clk; - - struct pinctrl *pinctrl; - struct pinctrl_state *pin_default; - - int num_apbs; -}; - -static inline void svc_reset_onoff(unsigned int gpio, bool onoff) -{ - gpio_set_value(gpio, onoff); -} - -static void db3_platform_cleanup(struct db3_platform_drvdata *db3_pdata) -{ - /* As part of exit, put APB back in reset state */ - if (gpio_is_valid(db3_pdata->svc_reset_gpio)) - svc_reset_onoff(db3_pdata->svc_reset_gpio, - db3_pdata->is_reset_act_hi); -} - -static int db3_platform_probe(struct platform_device *pdev) -{ - struct db3_platform_drvdata *db3_pdata; - struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; - int ret; - - db3_pdata = devm_kzalloc(&pdev->dev, sizeof(*db3_pdata), GFP_KERNEL); - if (!db3_pdata) - return -ENOMEM; - - /* setup svc reset gpio */ - db3_pdata->is_reset_act_hi = of_property_read_bool(np, "svc,reset-active-high"); - db3_pdata->svc_reset_gpio = of_get_named_gpio(np, "svc,reset-gpio", 0); - if (db3_pdata->svc_reset_gpio < 0) { - dev_err(dev, "failed to get reset-gpio\n"); - ret = -ENODEV; - return ret; - } - ret = devm_gpio_request(dev, db3_pdata->svc_reset_gpio, "svc-reset"); - if (ret) { - dev_err(dev, "failed to request svc-reset gpio:%d\n", ret); - return ret; - } - ret = gpio_direction_output(db3_pdata->svc_reset_gpio, db3_pdata->is_reset_act_hi); - if (ret) { - dev_err(dev, "failed to set svc-reset gpio dir:%d\n", ret); - return ret; - } - - db3_pdata->svc_sysboot_gpio = of_get_named_gpio(np, "svc,sysboot-gpio", 0); - if (db3_pdata->svc_sysboot_gpio < 0) { - dev_err(dev, "failed to get sysboot gpio\n"); - ret = -ENODEV; - return ret; - } - ret = devm_gpio_request(dev, db3_pdata->svc_sysboot_gpio, "sysboot0"); - if (ret) { - dev_err(dev, "failed to request sysboot0 gpio:%d\n", ret); - return ret; - } - ret = gpio_direction_output(db3_pdata->svc_sysboot_gpio, 0); - if (ret) { - dev_err(dev, "failed to set svc-reset gpio dir:%d\n", ret); - return ret; - } - - /* setup the clock request gpio first */ - db3_pdata->svc_refclk_req = of_get_named_gpio(np, "svc,refclk-req-gpio", 0); - if (db3_pdata->svc_refclk_req < 0) { - dev_err(dev, "failed to get svc clock-req gpio\n"); - return -ENODEV; - } - ret = devm_gpio_request(dev, db3_pdata->svc_refclk_req, "svc-clk-req"); - if (ret) { - dev_err(dev, "failed to request svc-clk-req gpio: %d\n", ret); - return ret; - } - ret = gpio_direction_input(db3_pdata->svc_refclk_req); - if (ret) { - dev_err(dev, "failed to set svc-clk-req gpio dir :%d\n", ret); - return ret; - } - - /* setup refclk2 to follow the pin */ - db3_pdata->svc_ref_clk = devm_clk_get(dev, "svc_ref_clk"); - if (IS_ERR(db3_pdata->svc_ref_clk)) { - ret = PTR_ERR(db3_pdata->svc_ref_clk); - dev_err(dev, "failed to get svc_ref_clk: %d\n", ret); - return ret; - } - ret = clk_prepare_enable(db3_pdata->svc_ref_clk); - if (ret) { - dev_err(dev, "failed to enable svc_ref_clk: %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, db3_pdata); - - db3_pdata->num_apbs = of_get_child_count(np); - dev_dbg(dev, "Number of APB's available - %d\n", db3_pdata->num_apbs); - - /* bring SVC out of reset */ - svc_reset_onoff(db3_pdata->svc_reset_gpio, !db3_pdata->is_reset_act_hi); - - /* probe all childs here */ - ret = of_platform_populate(np, NULL, NULL, dev); - if (ret) - dev_err(dev, "no child node found\n"); - - dev_info(dev, "Device registered successfully\n"); - return ret; -} - -static int db3_platform_remove(struct platform_device *pdev) -{ - struct db3_platform_drvdata *db3_pdata = platform_get_drvdata(pdev); - - if (db3_pdata) - db3_platform_cleanup(db3_pdata); - - platform_set_drvdata(pdev, NULL); - - return 0; -} - -static int db3_platform_suspend(struct device *dev) -{ - /* - * If timing profile premits, we may shutdown bridge - * completely - * - * TODO: sequence ?? - * - * Also, need to make sure we meet precondition for unipro suspend - * Precondition: Definition ??? - */ - return 0; -} - -static int db3_platform_resume(struct device *dev) -{ - /* - * Atleast for ES2 we have to meet the delay requirement between - * unipro switch and AP bridge init, depending on whether bridge is in - * OFF state or standby state. - * - * Based on whether bridge is in standby or OFF state we may have to - * assert multiple signals. Please refer to WDM spec, for more info. - * - */ - return 0; -} - -static SIMPLE_DEV_PM_OPS(db3_platform_pm_ops, db3_platform_suspend, db3_platform_resume); - -static struct of_device_id db3_platform_of_match[] = { - { .compatible = "google,db3-platform", }, /* Use PID/VID of SVC device */ - { }, -}; -MODULE_DEVICE_TABLE(of, db3_platform_of_match); - -static struct platform_driver db3_platform_device_driver = { - .probe = db3_platform_probe, - .remove = db3_platform_remove, - .driver = { - .name = "db3-platform-ctrl", - .pm = &db3_platform_pm_ops, - .of_match_table = of_match_ptr(db3_platform_of_match), - } -}; - -module_platform_driver(db3_platform_device_driver); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Vaibhav Hiremath "); -MODULE_DESCRIPTION("DB3 Platform Driver"); -- cgit v0.10.2 From 5a78178718b9e50ee60a1129431758125cfa2f6a Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Wed, 16 Dec 2015 16:29:19 +0530 Subject: greybus: arche-apb-ctrl: Add APB control driver It was messy to integrate both SVC, APB (and any other arche platform specific control) into one single driver. Especially due to cross-dependency. AP first needs to bringup SVC, as SVC should enable clock to APB. APB should come up before HUB, as due to some reason HUB wouldn't enumerate APB's is APB comes up later. And on top of that we should have clean picture of hardware description in DT file. So this patch introduces APB control driver. Mostly copied from original arche-platform driver + fixed boot sequence. Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index bc4de85..b0d53f5 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -29,6 +29,7 @@ gb-raw-y := raw.o gb-hid-y := hid.o gb-es2-y := es2.o gb-arche-y := arche-platform.o +gb-arche-apb-ctrl-y := arche-apb-ctrl.o gb-audio-codec-y := audio-codec.o gb-camera-y := camera.o @@ -42,6 +43,7 @@ obj-m += gb-hid.o obj-m += gb-raw.o obj-m += gb-es2.o obj-m += gb-arche.o +obj-m += gb-arche-apb-ctrl.o obj-m += gb-audio-codec.o obj-m += gb-camera.o diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c new file mode 100644 index 0000000..efc1e42 --- /dev/null +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -0,0 +1,400 @@ +/* + * Arche Platform driver to control APB. + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum apb_state { + APB_STATE_OFF, + APB_STATE_ACTIVE, + APB_STATE_STANDBY, +}; + +struct arche_apb_ctrl_drvdata { + /* Control GPIO signals to and from AP <=> AP Bridges */ + int wake_detect_gpio; /* bi-dir,maps to WAKE_MOD & WAKE_FRAME signals */ + int resetn_gpio; + int boot_ret_gpio; + int pwroff_gpio; + int wake_in_gpio; + int wake_out_gpio; + int pwrdn_gpio; + + unsigned int wake_detect_irq; + enum apb_state state; + + struct regulator *vcore; + struct regulator *vio; + + unsigned int clk_en_gpio; + struct clk *clk; + + struct pinctrl *pinctrl; + struct pinctrl_state *pin_default; + + /* To protect concurrent access of GPIO registers, need protection */ + spinlock_t lock; +}; + +/* + * Note that these low level api's are active high + */ +static inline void assert_gpio(unsigned int gpio) +{ + gpio_set_value(gpio, 1); + msleep(500); +} + +static inline void deassert_gpio(unsigned int gpio) +{ + gpio_set_value(gpio, 0); +} + +static irqreturn_t apb_ctrl_wake_detect_irq(int irq, void *devid) +{ + struct arche_apb_ctrl_drvdata *apb = devid; + unsigned long flags; + + /* + * TODO: + * Since currently SoC GPIOs are being used we are safe here + * But ideally we should create a workqueue and process the control + * signals, especially when we start using GPIOs over slow + * buses like I2C. + */ + if (!gpio_is_valid(apb->wake_detect_gpio) && + !gpio_is_valid(apb->resetn_gpio)) + return IRQ_HANDLED; /* Should it be IRQ_NONE ?? */ + + spin_lock_irqsave(&apb->lock, flags); + + if (apb->state != APB_STATE_ACTIVE) { + /* Bring bridge out of reset on this event */ + gpio_set_value(apb->resetn_gpio, 1); + apb->state = APB_STATE_ACTIVE; + } else { + /* + * Assert Wake_OUT signal to APB + * It would resemble WakeDetect module's signal pass-through + */ + /* + * We have to generate the pulse, so we may need to schedule + * workqueue here. + * + * Also, since we are using both rising and falling edge for + * interrupt trigger, we may not need workqueue. Just pass + * through the value to bridge. + * Just read GPIO value and pass it to the bridge + */ + } + + spin_unlock_irqrestore(&apb->lock, flags); + + return IRQ_HANDLED; +} + +/* + * Note: Please do not modify the below sequence, as it is as per the spec + */ +static int apb_ctrl_init_seq(struct platform_device *pdev, + struct arche_apb_ctrl_drvdata *apb) +{ + struct device *dev = &pdev->dev; + int ret; + + /* On DB3 clock was not mandatory */ + if (gpio_is_valid(apb->clk_en_gpio)) { + ret = devm_gpio_request(dev, apb->clk_en_gpio, "apb_clk_en"); + if (ret) + dev_err(dev, "Failed requesting APB clock en gpio %d\n", + apb->clk_en_gpio); + ret = gpio_direction_output(apb->clk_en_gpio, 1); + if (ret) + dev_err(dev, "failed to set APB clock en gpio dir:%d\n", ret); + } + /* Hold APB in reset state */ + ret = devm_gpio_request(dev, apb->resetn_gpio, "apb-reset"); + if (ret) { + dev_err(dev, "Failed requesting reset gpio %d\n", + apb->resetn_gpio); + return ret; + } + ret = gpio_direction_output(apb->resetn_gpio, 0); + if (ret) { + dev_err(dev, "failed to set reset gpio dir:%d\n", ret); + return ret; + } + + ret = devm_gpio_request(dev, apb->pwroff_gpio, "pwroff_n"); + if (ret) { + dev_err(dev, "Failed requesting pwroff_n gpio %d\n", + apb->pwroff_gpio); + return ret; + } + ret = gpio_direction_input(apb->pwroff_gpio); + if (ret) { + dev_err(dev, "failed to set pwroff gpio dir:%d\n", ret); + return ret; + } + + /* Enable power to APB */ + if (apb->vcore) { + ret = regulator_enable(apb->vcore); + if (ret) { + dev_err(dev, "failed to enable core regulator\n"); + return ret; + } + } + if (apb->vio) { + ret = regulator_enable(apb->vio); + if (ret) { + dev_err(dev, "failed to enable IO regulator\n"); + return ret; + } + } + + ret = devm_gpio_request_one(dev, apb->boot_ret_gpio, + GPIOF_OUT_INIT_LOW, "boot retention"); + if (ret) { + dev_err(dev, "Failed requesting bootret gpio %d\n", + apb->boot_ret_gpio); + return ret; + } + gpio_set_value(apb->boot_ret_gpio, 0); + udelay(50); + + ret = devm_gpio_request(dev, apb->wake_detect_gpio, "wake detect"); + if (ret) + dev_err(dev, "Failed requesting wake_detect gpio %d\n", + apb->wake_detect_gpio); + + return ret; +} + +static int apb_ctrl_get_devtree_data(struct platform_device *pdev, + struct arche_apb_ctrl_drvdata *apb) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + + apb->wake_detect_gpio = of_get_named_gpio(np, "wake-detect-gpios", 0); + if (!gpio_is_valid(apb->wake_detect_gpio)) { + dev_err(dev, "failed to get wake detect gpio\n"); + return apb->wake_detect_gpio; + } + + apb->resetn_gpio = of_get_named_gpio(np, "reset-gpios", 0); + if (!gpio_is_valid(apb->resetn_gpio)) { + dev_err(dev, "failed to get reset gpio\n"); + return apb->resetn_gpio; + } + + apb->boot_ret_gpio = of_get_named_gpio(np, "boot-ret-gpios", 0); + if (!gpio_is_valid(apb->boot_ret_gpio)) { + dev_err(dev, "failed to get boot retention gpio\n"); + return apb->boot_ret_gpio; + } + + /* It's not mandatory to support power management interface */ + apb->pwroff_gpio = of_get_named_gpio(np, "pwr-off-gpios", 0); + if (!gpio_is_valid(apb->pwroff_gpio)) { + dev_info(dev, "failed to get power off gpio\n"); + return apb->pwroff_gpio; + } + + /* Do not make clock mandatory as of now (for DB3) */ + apb->clk_en_gpio = of_get_named_gpio(np, "clock-en-gpio", 0); + if (!gpio_is_valid(apb->clk_en_gpio)) + dev_err(dev, "failed to get clock en gpio\n"); + + apb->pwrdn_gpio = of_get_named_gpio(np, "pwr-down-gpios", 0); + if (!gpio_is_valid(apb->pwrdn_gpio)) + dev_info(dev, "failed to get power down gpio\n"); + + /* Regulators are optional, as we may have fixed supply coming in */ + apb->vcore = devm_regulator_get(dev, "vcore"); + if (IS_ERR_OR_NULL(apb->vcore)) { + dev_info(dev, "no core regulator found\n"); + apb->vcore = NULL; + } + + apb->vio = devm_regulator_get(dev, "vio"); + if (IS_ERR_OR_NULL(apb->vio)) { + dev_info(dev, "no IO regulator found\n"); + apb->vio = NULL; + } + + apb->pinctrl = devm_pinctrl_get(&pdev->dev); + if (IS_ERR(apb->pinctrl)) { + dev_err(&pdev->dev, "could not get pinctrl handle\n"); + return PTR_ERR(apb->pinctrl); + } + apb->pin_default = pinctrl_lookup_state(apb->pinctrl, "default"); + if (IS_ERR(apb->pin_default)) { + dev_err(&pdev->dev, "could not get default pin state\n"); + return PTR_ERR(apb->pin_default); + } + + return 0; +} + +static void apb_ctrl_cleanup(struct arche_apb_ctrl_drvdata *apb) +{ + unsigned long flags; + + if (apb->vcore && regulator_is_enabled(apb->vcore) > 0) + regulator_disable(apb->vcore); + + if (apb->vio && regulator_is_enabled(apb->vio) > 0) + regulator_disable(apb->vio); + + spin_lock_irqsave(&apb->lock, flags); + /* As part of exit, put APB back in reset state */ + if (gpio_is_valid(apb->resetn_gpio)) + gpio_set_value(apb->resetn_gpio, 0); + + apb->state = APB_STATE_OFF; + spin_unlock_irqrestore(&apb->lock, flags); + + /* TODO: May have to send an event to SVC about this exit */ +} + +static int arche_apb_ctrl_probe(struct platform_device *pdev) +{ + int ret; + struct arche_apb_ctrl_drvdata *apb; + struct device *dev = &pdev->dev; + + apb = devm_kzalloc(&pdev->dev, sizeof(*apb), GFP_KERNEL); + if (!apb) + return -ENOMEM; + + ret = apb_ctrl_get_devtree_data(pdev, apb); + if (ret) { + dev_err(dev, "failed to get apb devicetree data %d\n", ret); + return ret; + } + + ret = apb_ctrl_init_seq(pdev, apb); + if (ret) { + dev_err(dev, "failed to set init state of control signal %d\n", + ret); + goto exit; + } + + spin_lock_init(&apb->lock); + + apb->state = APB_STATE_OFF; + /* + * Assert AP module detect signal by pulling wake_detect low + */ + assert_gpio(apb->wake_detect_gpio); + + /* + * In order to receive an interrupt, the GPIO must be set to input mode + */ + gpio_direction_input(apb->wake_detect_gpio); + + ret = devm_request_irq(dev, gpio_to_irq(apb->wake_detect_gpio), + apb_ctrl_wake_detect_irq, IRQF_TRIGGER_FALLING, + "wake detect", apb); + if (ret) { + dev_err(dev, "failed to request wake detect IRQ\n"); + goto exit; + } + + platform_set_drvdata(pdev, apb); + + dev_info(&pdev->dev, "Device registered successfully\n"); + return 0; + +exit: + apb_ctrl_cleanup(apb); + return ret; +} + +static int arche_apb_ctrl_remove(struct platform_device *pdev) +{ + struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); + + if (apb) + apb_ctrl_cleanup(apb); + + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static int arche_apb_ctrl_suspend(struct device *dev) +{ + /* + * If timing profile premits, we may shutdown bridge + * completely + * + * TODO: sequence ?? + * + * Also, need to make sure we meet precondition for unipro suspend + * Precondition: Definition ??? + */ + return 0; +} + +static int arche_apb_ctrl_resume(struct device *dev) +{ + /* + * Atleast for ES2 we have to meet the delay requirement between + * unipro switch and AP bridge init, depending on whether bridge is in + * OFF state or standby state. + * + * Based on whether bridge is in standby or OFF state we may have to + * assert multiple signals. Please refer to WDM spec, for more info. + * + */ + return 0; +} + +static SIMPLE_DEV_PM_OPS(arche_apb_ctrl_pm_ops, + arche_apb_ctrl_suspend, + arche_apb_ctrl_resume); + +static struct of_device_id arche_apb_ctrl_of_match[] = { + { .compatible = "usbffff,2", }, + { }, +}; +MODULE_DEVICE_TABLE(of, arche_apb_ctrl_of_match); + +static struct platform_driver arche_apb_ctrl_device_driver = { + .probe = arche_apb_ctrl_probe, + .remove = arche_apb_ctrl_remove, + .driver = { + .name = "arche-apb-ctrl", + .pm = &arche_apb_ctrl_pm_ops, + .of_match_table = of_match_ptr(arche_apb_ctrl_of_match), + } +}; + +module_platform_driver(arche_apb_ctrl_device_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Vaibhav Hiremath "); +MODULE_DESCRIPTION("Arche APB control Driver"); -- cgit v0.10.2 From 166f0aed325f7bcb7c1ee8c2665d5cb05d36d931 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Wed, 16 Dec 2015 16:29:20 +0530 Subject: greybus: arche-apb-ctrl: Assert reset to APB at the end of probe Until we have proper handshake mechanism implemented with SVC assert reset to APB at the end of probe. We are safe here to do that, as SVC always enables clock to APB's currently. And also from EVT1 perspective, we should be good, as clock control signals are now moved to AP. Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index efc1e42..68f8d3c 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -325,6 +325,8 @@ static int arche_apb_ctrl_probe(struct platform_device *pdev) platform_set_drvdata(pdev, apb); + assert_gpio(apb->resetn_gpio); + dev_info(&pdev->dev, "Device registered successfully\n"); return 0; -- cgit v0.10.2 From 5b22521c895111ca191c82a6573214f995c47709 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 16 Dec 2015 16:29:29 +0530 Subject: greybus: control: Use Macro's instead of direct values for major/minor We already have macro's defined for this, use them. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index 9c282e4..09ff797 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -126,8 +126,8 @@ static void gb_control_connection_exit(struct gb_connection *connection) static struct gb_protocol control_protocol = { .name = "control", .id = GREYBUS_PROTOCOL_CONTROL, - .major = 0, - .minor = 1, + .major = GB_CONTROL_VERSION_MAJOR, + .minor = GB_CONTROL_VERSION_MINOR, .connection_init = gb_control_connection_init, .connection_exit = gb_control_connection_exit, .flags = GB_PROTOCOL_SKIP_CONTROL_CONNECTED | -- cgit v0.10.2 From 72e53aed1d077166b63537b2b08dc89af60d6c9a Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Wed, 23 Dec 2015 16:48:59 +0000 Subject: greybus: svc: Change GB_SVC_TYPE_LINK_CONFIG to 0x10 The greybus specification reserves SVC type 0x0d-0x0f for timesync. 53124d73 ('svc: Add support for the link config operation') allocated the next available type 0x0d which conflicts with the specification. Change the type to 0x10 to ensure kernel and specification agree. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 53c1dea..773e1ab 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -730,7 +730,7 @@ struct gb_spi_transfer_response { #define GB_SVC_TYPE_DME_PEER_SET 0x0a #define GB_SVC_TYPE_ROUTE_CREATE 0x0b #define GB_SVC_TYPE_ROUTE_DESTROY 0x0c -#define GB_SVC_TYPE_LINK_CONFIG 0x0d +#define GB_SVC_TYPE_LINK_CONFIG 0x10 /* * SVC version request/response has the same payload as -- cgit v0.10.2 From 63d742b68abd09977dfa9f488e5494ec65485ef0 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 23 Dec 2015 09:07:42 +0530 Subject: greybus: svc: Set interface's hotplug attributes before using them gb_svc_read_and_clear_module_boot_status() relies on the values of ddbl1_manufacturer_id and ddbl1_product_id to distinguish between ES2 and ES3 chips, but those values are set for the interface structure only after gb_svc_read_and_clear_module_boot_status() is called. This makes ES2 module to fail with following errors: greybus 1-2: Module not ready yet greybus 1-svc: failed to clear boot status of interface 2: -19 Fix this by setting these values before calling gb_svc_read_and_clear_module_boot_status(). Fixes: 51f1dc421b1f ("firmware and svc: detect the difference between ES2 and ES3 chips") Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 3e760e6..4178699 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -425,6 +425,11 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) return; } + intf->ddbl1_manufacturer_id = le32_to_cpu(request->data.ddbl1_mfr_id); + intf->ddbl1_product_id = le32_to_cpu(request->data.ddbl1_prod_id); + intf->vendor_id = le32_to_cpu(request->data.ara_vend_id); + intf->product_id = le32_to_cpu(request->data.ara_prod_id); + ret = gb_svc_read_and_clear_module_boot_status(intf); if (ret) { dev_err(&svc->dev, "failed to clear boot status of interface %u: %d\n", @@ -432,11 +437,6 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) goto destroy_interface; } - intf->ddbl1_manufacturer_id = le32_to_cpu(request->data.ddbl1_mfr_id); - intf->ddbl1_product_id = le32_to_cpu(request->data.ddbl1_prod_id); - intf->vendor_id = le32_to_cpu(request->data.ara_vend_id); - intf->product_id = le32_to_cpu(request->data.ara_prod_id); - /* * Create a device id for the interface: * - device id 0 (GB_DEVICE_ID_SVC) belongs to the SVC -- cgit v0.10.2 From 57c6bcc635626e24fff3546bb072b4ba4163872b Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 28 Dec 2015 11:59:00 +0530 Subject: greybus: interface: Receive serial-number on hotplug event Two exactly same modules can be uniquely identified using module's serial-number. This patch updates the interface hotplug event to also receive the serial-number of the module. Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 2cd17c7..0d16d76 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -37,6 +37,14 @@ Contact: Greg Kroah-Hartman Description: The ID of a Greybus interface. +What: /sys/bus/greybus/device/N-I/serial_number +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + Serial Number of the Greybus interface, represented by a 64 bit + hexadecimal number. + What: /sys/bus/greybus/device/N-I/product_id Date: October 2015 KernelVersion: 4.XX diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/serial_number b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/serial_number new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/serial_number b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/serial_number new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/serial_number b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/serial_number new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 773e1ab..f66f4d7 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -757,6 +757,7 @@ struct gb_svc_intf_hotplug_request { __le32 ddbl1_prod_id; __le32 ara_vend_id; __le32 ara_prod_id; + __le64 serial_number; } data; } __packed; /* hotplug response has no payload */ diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index c4b9e14..69eb788 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -27,6 +27,7 @@ gb_interface_attr(vendor_id, "0x%08x"); gb_interface_attr(product_id, "0x%08x"); gb_interface_attr(vendor_string, "%s"); gb_interface_attr(product_string, "%s"); +gb_interface_attr(serial_number, "0x%016llx"); static struct attribute *interface_attrs[] = { &dev_attr_ddbl1_manufacturer_id.attr, @@ -36,6 +37,7 @@ static struct attribute *interface_attrs[] = { &dev_attr_product_id.attr, &dev_attr_vendor_string.attr, &dev_attr_product_string.attr, + &dev_attr_serial_number.attr, NULL, }; ATTRIBUTE_GROUPS(interface); diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index d192b74..a1a1f9f 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -30,6 +30,7 @@ struct gb_interface { u32 ddbl1_product_id; u32 vendor_id; u32 product_id; + u64 serial_number; struct gb_host_device *hd; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 4178699..fe7bd28 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -429,6 +429,7 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) intf->ddbl1_product_id = le32_to_cpu(request->data.ddbl1_prod_id); intf->vendor_id = le32_to_cpu(request->data.ara_vend_id); intf->product_id = le32_to_cpu(request->data.ara_prod_id); + intf->serial_number = le64_to_cpu(request->data.serial_number); ret = gb_svc_read_and_clear_module_boot_status(intf); if (ret) { -- cgit v0.10.2 From d39bf704acbd254576e3fc880ec13e6cd09e88c7 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 28 Dec 2015 11:59:01 +0530 Subject: greybus: interface: Fetch and expose version of interface's firmware The version of the currently running firmware on the module is useful for userspace as it can be used to find if an update is available or not. This patch fetches interface's version with a new control operation and exposes the same in userspace. Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 0d16d76..9ce36dd 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -73,6 +73,14 @@ Contact: Greg Kroah-Hartman Description: Vendor ID string of a Greybus interface block. +What: /sys/bus/greybus/device/N-I/version +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + Interface version represented as <16 bit major number>.<16 bit + minor number>. + What: /sys/bus/greybus/device/N-I.B Date: October 2015 KernelVersion: 4.XX diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index 09ff797..4d65dbf 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -59,6 +59,35 @@ int gb_control_disconnected_operation(struct gb_control *control, u16 cport_id) sizeof(request), NULL, 0); } +int gb_control_get_interface_version_operation(struct gb_interface *intf) +{ + struct gb_control_interface_version_response response; + struct gb_connection *connection = intf->control->connection; + int ret; + + /* The ES3 bootrom fails to boot if this request it sent to it */ + if (intf->boot_over_unipro) + return 0; + + ret = gb_operation_sync(connection, GB_CONTROL_TYPE_INTERFACE_VERSION, + NULL, 0, &response, sizeof(response)); + if (ret) { + dev_err(&connection->intf->dev, + "failed to get interface version: %d\n", ret); + /* + * FIXME: Return success until the time we bump version of + * control protocol. The interface-version is already set to + * 0.0, so no need to update that. + */ + return 0; + } + + intf->version_major = le16_to_cpu(response.major); + intf->version_minor = le16_to_cpu(response.minor); + + return 0; +} + struct gb_control *gb_control_create(struct gb_interface *intf) { struct gb_control *control; diff --git a/drivers/staging/greybus/control.h b/drivers/staging/greybus/control.h index da0fa66..7cb3dd2 100644 --- a/drivers/staging/greybus/control.h +++ b/drivers/staging/greybus/control.h @@ -24,6 +24,7 @@ int gb_control_disconnected_operation(struct gb_control *control, u16 cport_id); int gb_control_get_manifest_size_operation(struct gb_interface *intf); int gb_control_get_manifest_operation(struct gb_interface *intf, void *manifest, size_t size); +int gb_control_get_interface_version_operation(struct gb_interface *intf); int gb_control_protocol_init(void); void gb_control_protocol_exit(void); diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index f66f4d7..a0bddaa 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -125,6 +125,7 @@ struct gb_protocol_version_response { #define GB_CONTROL_TYPE_GET_MANIFEST 0x04 #define GB_CONTROL_TYPE_CONNECTED 0x05 #define GB_CONTROL_TYPE_DISCONNECTED 0x06 +#define GB_CONTROL_TYPE_INTERFACE_VERSION 0x0a /* Control protocol manifest get size request has no payload*/ struct gb_control_get_manifest_size_response { @@ -146,6 +147,12 @@ struct gb_control_disconnected_request { } __packed; /* Control protocol [dis]connected response has no payload */ +/* Control protocol interface version request has no payload */ +struct gb_control_interface_version_response { + __le16 major; + __le16 minor; +} __packed; + /* Firmware Protocol */ diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 69eb788..edac238 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -29,6 +29,16 @@ gb_interface_attr(vendor_string, "%s"); gb_interface_attr(product_string, "%s"); gb_interface_attr(serial_number, "0x%016llx"); +static ssize_t version_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct gb_interface *intf = to_gb_interface(dev); + + return scnprintf(buf, PAGE_SIZE, "%u.%u\n", intf->version_major, + intf->version_minor); +} +static DEVICE_ATTR_RO(version); + static struct attribute *interface_attrs[] = { &dev_attr_ddbl1_manufacturer_id.attr, &dev_attr_ddbl1_product_id.attr, @@ -38,6 +48,7 @@ static struct attribute *interface_attrs[] = { &dev_attr_vendor_string.attr, &dev_attr_product_string.attr, &dev_attr_serial_number.attr, + &dev_attr_version.attr, NULL, }; ATTRIBUTE_GROUPS(interface); @@ -214,6 +225,10 @@ int gb_interface_init(struct gb_interface *intf, u8 device_id) goto free_manifest; } + ret = gb_control_get_interface_version_operation(intf); + if (ret) + goto free_manifest; + /* Register the interface and its bundles. */ ret = device_add(&intf->dev); if (ret) { diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index a1a1f9f..4168a57 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -32,6 +32,9 @@ struct gb_interface { u32 product_id; u64 serial_number; + u16 version_major; + u16 version_minor; + struct gb_host_device *hd; /* The interface needs to boot over unipro */ -- cgit v0.10.2 From 12c8b0dcc884cc7f1f925cd1ed08cf8cdc95e7ef Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 30 Dec 2015 11:08:00 +0100 Subject: greybus: camera: fix memory leak in configure-streams error path Fix memory leak in configure-streams error path by making sure to release the operation buffers before returning. Signed-off-by: Johan Hovold Reviewed-by: Laurent Pinchart Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index c742fea..8b2eedd 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -115,7 +115,7 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, GB_CAMERA_TYPE_CONFIGURE_STREAMS, req, req_size, resp, resp_size); if (ret < 0) - return ret; + goto done; if (le16_to_cpu(resp->num_streams) > nstreams) { gcam_dbg(gcam, "got #streams %u > request %u\n", -- cgit v0.10.2 From b9f71bc854105148f38d0c2336ed7c9b50a97800 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 30 Dec 2015 11:08:01 +0100 Subject: greybus: camera: fix memory leak in capture-request handler Fix memory leak in capture-request handler by making sure to release the operation request buffer after sending the request. Signed-off-by: Johan Hovold Reviewed-by: Laurent Pinchart Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 8b2eedd..ec7d4a0 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -183,6 +183,7 @@ static int gb_camera_capture(struct gb_camera *gcam, u32 request_id, { struct gb_camera_capture_request *req; size_t req_size; + int ret; if (settings_size > GB_CAMERA_MAX_SETTINGS_SIZE) return -EINVAL; @@ -198,8 +199,12 @@ static int gb_camera_capture(struct gb_camera *gcam, u32 request_id, req->num_frames = cpu_to_le16(num_frames); memcpy(req->settings, settings, settings_size); - return gb_operation_sync(gcam->connection, GB_CAMERA_TYPE_CAPTURE, + ret = gb_operation_sync(gcam->connection, GB_CAMERA_TYPE_CAPTURE, req, req_size, NULL, 0); + + kfree(req); + + return ret; } static int gb_camera_flush(struct gb_camera *gcam, u32 *request_id) -- cgit v0.10.2 From 41c23958557d9b37755768849ee39b99a9826a9c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 30 Dec 2015 11:23:51 +0100 Subject: greybus: camera: destroy data connection on link-config errors Make sure to tear down the data connection also on failure to configure the link by setting the data_connected flag immediately after creating the connection. Signed-off-by: Johan Hovold Reviewed-by: Laurent Pinchart Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index ec7d4a0..b181ac4 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -604,6 +604,8 @@ static int gb_camera_connection_init(struct gb_connection *connection) if (ret < 0) goto error; + gcam->data_connected = true; + ret = gb_svc_link_config(svc, connection->intf->interface_id, GB_SVC_LINK_CONFIG_BURST_HS_A, 2, 2, 0); if (ret < 0) @@ -614,8 +616,6 @@ static int gb_camera_connection_init(struct gb_connection *connection) if (ret < 0) goto error; - gcam->data_connected = true; - ret = gb_camera_debugfs_init(gcam); if (ret < 0) goto error; -- cgit v0.10.2 From bc142bbb4ceba0891db6bf36cfb7be13c9a2dd72 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Mon, 28 Dec 2015 20:06:32 +0530 Subject: greybus: arche_platform: Remove child's platform device as part of _remove() fn It seems we need to delete platform_dev of all childs explicitly, in _remove() fn callback of parent driver. There were some discussions about having of_platform_unpopulate(), but it never made it to mainline. https://lkml.org/lkml/2013/7/19/615 There are some drivers which are removing platform_dev explicitly, as done in this patch. Note that, without this, multiple insmod-rmmod won't work, as I see driver probe gets invoked twice and leads to failure of probe. Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 7d90f5d..697180d 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -149,10 +149,21 @@ static int arche_platform_probe(struct platform_device *pdev) return ret; } +static int arche_remove_child(struct device *dev, void *unused) +{ + struct platform_device *pdev = to_platform_device(dev); + + platform_device_unregister(pdev); + + return 0; +} + static int arche_platform_remove(struct platform_device *pdev) { struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev); + device_for_each_child(&pdev->dev, NULL, arche_remove_child); + if (arche_pdata) arche_platform_cleanup(arche_pdata); -- cgit v0.10.2 From 1e5dd1f8279a8a934b9df7adec47b944fe6b10f4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 30 Dec 2015 13:38:33 -0800 Subject: greybus: arche-platform: merge arche-apb-ctrl and arche-platform No need to have two separate arche platform drivers, that's just crazy, so merge them both together to be only one kernel module. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Vaibhav Hiremath Tested-by: Vaibhav Hiremath diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index b0d53f5..011e87c 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -28,8 +28,7 @@ gb-light-y := light.o gb-raw-y := raw.o gb-hid-y := hid.o gb-es2-y := es2.o -gb-arche-y := arche-platform.o -gb-arche-apb-ctrl-y := arche-apb-ctrl.o +gb-arche-y := arche-platform.o arche-apb-ctrl.o gb-audio-codec-y := audio-codec.o gb-camera-y := camera.o @@ -43,7 +42,6 @@ obj-m += gb-hid.o obj-m += gb-raw.o obj-m += gb-es2.o obj-m += gb-arche.o -obj-m += gb-arche-apb-ctrl.o obj-m += gb-audio-codec.o obj-m += gb-camera.o diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index 68f8d3c..f02b8ad 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -23,6 +23,7 @@ #include #include #include +#include "arche_platform.h" enum apb_state { APB_STATE_OFF, @@ -279,7 +280,7 @@ static void apb_ctrl_cleanup(struct arche_apb_ctrl_drvdata *apb) /* TODO: May have to send an event to SVC about this exit */ } -static int arche_apb_ctrl_probe(struct platform_device *pdev) +int arche_apb_ctrl_probe(struct platform_device *pdev) { int ret; struct arche_apb_ctrl_drvdata *apb; @@ -335,7 +336,7 @@ exit: return ret; } -static int arche_apb_ctrl_remove(struct platform_device *pdev) +int arche_apb_ctrl_remove(struct platform_device *pdev) { struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); @@ -375,28 +376,8 @@ static int arche_apb_ctrl_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(arche_apb_ctrl_pm_ops, - arche_apb_ctrl_suspend, - arche_apb_ctrl_resume); +SIMPLE_DEV_PM_OPS(arche_apb_ctrl_pm_ops, + arche_apb_ctrl_suspend, + arche_apb_ctrl_resume); -static struct of_device_id arche_apb_ctrl_of_match[] = { - { .compatible = "usbffff,2", }, - { }, -}; -MODULE_DEVICE_TABLE(of, arche_apb_ctrl_of_match); - -static struct platform_driver arche_apb_ctrl_device_driver = { - .probe = arche_apb_ctrl_probe, - .remove = arche_apb_ctrl_remove, - .driver = { - .name = "arche-apb-ctrl", - .pm = &arche_apb_ctrl_pm_ops, - .of_match_table = of_match_ptr(arche_apb_ctrl_of_match), - } -}; - -module_platform_driver(arche_apb_ctrl_device_driver); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Vaibhav Hiremath "); -MODULE_DESCRIPTION("Arche APB control Driver"); diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 697180d..5069952 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -23,6 +23,7 @@ #include #include #include +#include "arche_platform.h" struct arche_platform_drvdata { /* Control GPIO signals to and from AP <=> SVC */ @@ -208,7 +209,18 @@ static struct of_device_id arche_platform_of_match[] = { { .compatible = "google,arche-platform", }, /* Use PID/VID of SVC device */ { }, }; -MODULE_DEVICE_TABLE(of, arche_platform_of_match); + +static struct of_device_id arche_apb_ctrl_of_match[] = { + { .compatible = "usbffff,2", }, + { }, +}; + +static struct of_device_id arche_combined_id[] = { + { .compatible = "google,arche-platform", }, /* Use PID/VID of SVC device */ + { .compatible = "usbffff,2", }, + { }, +}; +MODULE_DEVICE_TABLE(of, arche_combined_id); static struct platform_driver arche_platform_device_driver = { .probe = arche_platform_probe, @@ -216,11 +228,42 @@ static struct platform_driver arche_platform_device_driver = { .driver = { .name = "arche-platform-ctrl", .pm = &arche_platform_pm_ops, - .of_match_table = of_match_ptr(arche_platform_of_match), + .of_match_table = arche_platform_of_match, } }; -module_platform_driver(arche_platform_device_driver); +static struct platform_driver arche_apb_ctrl_device_driver = { + .probe = arche_apb_ctrl_probe, + .remove = arche_apb_ctrl_remove, + .driver = { + .name = "arche-apb-ctrl", + .pm = &arche_apb_ctrl_pm_ops, + .of_match_table = arche_apb_ctrl_of_match, + } +}; + +static int __init arche_init(void) +{ + int retval; + + retval = platform_driver_register(&arche_platform_device_driver); + if (retval) + return retval; + + retval = platform_driver_register(&arche_apb_ctrl_device_driver); + if (retval) + platform_driver_unregister(&arche_platform_device_driver); + + return retval; +} +module_init(arche_init); + +static void __exit arche_exit(void) +{ + platform_driver_unregister(&arche_apb_ctrl_device_driver); + platform_driver_unregister(&arche_platform_device_driver); +} +module_exit(arche_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Vaibhav Hiremath "); diff --git a/drivers/staging/greybus/arche_platform.h b/drivers/staging/greybus/arche_platform.h new file mode 100644 index 0000000..22a968a --- /dev/null +++ b/drivers/staging/greybus/arche_platform.h @@ -0,0 +1,17 @@ +/* + * Arche Platform driver to enable Unipro link. + * + * Copyright 2015-2016 Google Inc. + * Copyright 2015-2016 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#ifndef __ARCHE_PLATFORM_H +#define __ARCHE_PLATFORM_H + +int arche_apb_ctrl_probe(struct platform_device *pdev); +int arche_apb_ctrl_remove(struct platform_device *pdev); +extern const struct dev_pm_ops arche_apb_ctrl_pm_ops; + +#endif /* __ARCHE_PLATFORM_H */ -- cgit v0.10.2 From 1f67ee5c04c9690c4c99fc4d31f4add46ea7be73 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 31 Dec 2015 04:20:56 +0200 Subject: greybus: camera: Raise the CSI-2 bandwidth Use 4 lanes at 960MHz to support camera modules requiring higher bandwidths until we implement support for dynamic bandwidth calculation. Signed-off-by: Laurent Pinchart Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index b181ac4..7be7cfc 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -152,8 +152,8 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, if (nstreams && !(resp->flags & GB_CAMERA_CONFIGURE_STREAMS_ADJUSTED)) { csi_cfg.csi_id = 1; csi_cfg.clock_mode = 0; - csi_cfg.num_lanes = 2; - csi_cfg.bus_freq = 250000000; + csi_cfg.num_lanes = 4; + csi_cfg.bus_freq = 960000000; ret = es2_ap_csi_setup(gcam->connection->hd, true, &csi_cfg); } else if (nstreams == 0) { -- cgit v0.10.2 From 6da86df3a4aa6dfbb9af350df4a908a7a9254be0 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Wed, 6 Jan 2016 11:31:20 +0530 Subject: greybus: arche-platform: Export gpio (reset & sys_boot) to user In order to allow user to flash the firmware to, SVC: user need to assert the reset first, set sysboot pin and deassert reset. And then issue a flashing command. And APB: User need to assert the reset first, and then issue flashing command. So this patch exports the gpio's to user. Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index f02b8ad..8046e1e 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -71,6 +71,17 @@ static inline void deassert_gpio(unsigned int gpio) gpio_set_value(gpio, 0); } +/* Export gpio's to user space */ +static void export_gpios(struct arche_apb_ctrl_drvdata *apb) +{ + gpio_export(apb->resetn_gpio, false); +} + +static void unexport_gpios(struct arche_apb_ctrl_drvdata *apb) +{ + gpio_unexport(apb->resetn_gpio); +} + static irqreturn_t apb_ctrl_wake_detect_irq(int irq, void *devid) { struct arche_apb_ctrl_drvdata *apb = devid; @@ -328,6 +339,8 @@ int arche_apb_ctrl_probe(struct platform_device *pdev) assert_gpio(apb->resetn_gpio); + export_gpios(apb); + dev_info(&pdev->dev, "Device registered successfully\n"); return 0; @@ -344,6 +357,7 @@ int arche_apb_ctrl_remove(struct platform_device *pdev) apb_ctrl_cleanup(apb); platform_set_drvdata(pdev, NULL); + unexport_gpios(apb); return 0; } diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 5069952..e6fe015 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -45,6 +45,19 @@ static inline void svc_reset_onoff(unsigned int gpio, bool onoff) gpio_set_value(gpio, onoff); } +/* Export gpio's to user space */ +static void export_gpios(struct arche_platform_drvdata *arche_pdata) +{ + gpio_export(arche_pdata->svc_reset_gpio, false); + gpio_export(arche_pdata->svc_sysboot_gpio, false); +} + +static void unexport_gpios(struct arche_platform_drvdata *arche_pdata) +{ + gpio_unexport(arche_pdata->svc_reset_gpio); + gpio_unexport(arche_pdata->svc_sysboot_gpio); +} + static void arche_platform_cleanup(struct arche_platform_drvdata *arche_pdata) { /* As part of exit, put APB back in reset state */ @@ -141,6 +154,8 @@ static int arche_platform_probe(struct platform_device *pdev) arche_pdata->num_apbs = of_get_child_count(np); dev_dbg(dev, "Number of APB's available - %d\n", arche_pdata->num_apbs); + export_gpios(arche_pdata); + /* probe all childs here */ ret = of_platform_populate(np, NULL, NULL, dev); if (ret) @@ -169,6 +184,7 @@ static int arche_platform_remove(struct platform_device *pdev) arche_platform_cleanup(arche_pdata); platform_set_drvdata(pdev, NULL); + unexport_gpios(arche_pdata); return 0; } -- cgit v0.10.2 From ae0bf3a62805fa80c8277dd293d9d9d9b8b4c7c0 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Wed, 6 Jan 2016 23:46:45 +0530 Subject: greybus: arche-apb-ctrl: Set wake_detect gpio to low initially This patch enables handshaking of AP and SVC using wake_detect gpio (WD_8A and WD_8B). Note that WAKE_DETECT polarity is active-high, so in order to enable handshaking between AP <=> SVC, we need to set wake_detect gpio to low initially, so that driver can send WAKE_DET signal (active-high) to SVC and then SVC can send back WAKE_MOD signal (active-low). And on reception of WAKE_MOD signal, driver would bring respective APB out of reset. WD_8A => APB1 WD_8B => APB2 Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index 8046e1e..d3db7fb 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -195,7 +195,8 @@ static int apb_ctrl_init_seq(struct platform_device *pdev, gpio_set_value(apb->boot_ret_gpio, 0); udelay(50); - ret = devm_gpio_request(dev, apb->wake_detect_gpio, "wake detect"); + ret = devm_gpio_request_one(dev, apb->wake_detect_gpio, + GPIOF_INIT_LOW, "wake detect"); if (ret) dev_err(dev, "Failed requesting wake_detect gpio %d\n", apb->wake_detect_gpio); -- cgit v0.10.2 From e49268cc336eceb0653a03c4a0f9eb53eadf4d64 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Wed, 6 Jan 2016 23:46:46 +0530 Subject: greybus: arche-apb-ctrl: Do not bring APB out of reset in probe With addition of handshaking between AP <=> SVC, driver brings out APB out of reset only on reception of WAKE_MOD signal from SVC. So remove the deassertion from probe. Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index d3db7fb..701cd56 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -338,8 +338,6 @@ int arche_apb_ctrl_probe(struct platform_device *pdev) platform_set_drvdata(pdev, apb); - assert_gpio(apb->resetn_gpio); - export_gpios(apb); dev_info(&pdev->dev, "Device registered successfully\n"); -- cgit v0.10.2 From aab4a1a3684a46b423af23e4bdc9afe1b28dc389 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 6 Jan 2016 16:16:46 +0200 Subject: greybus: svc: Replace link config hack with standard operation The link config operation was a hack only designed to fulfill the camera driver's needs. Now that a standard operation is defined for the same purpose, implement it and remove the hack. Signed-off-by: Laurent Pinchart Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 7be7cfc..4e96e1f 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -606,13 +606,21 @@ static int gb_camera_connection_init(struct gb_connection *connection) gcam->data_connected = true; - ret = gb_svc_link_config(svc, connection->intf->interface_id, - GB_SVC_LINK_CONFIG_BURST_HS_A, 2, 2, 0); + ret = gb_svc_intf_set_power_mode(svc, connection->intf->interface_id, + GB_SVC_UNIPRO_HS_SERIES_A, + GB_SVC_UNIPRO_FAST_MODE, 2, 2, + GB_SVC_UNIPRO_FAST_MODE, 2, 2, + GB_SVC_PWRM_RXTERMINATION | + GB_SVC_PWRM_TXTERMINATION, 0); if (ret < 0) goto error; - ret = gb_svc_link_config(svc, svc->ap_intf_id, - GB_SVC_LINK_CONFIG_BURST_HS_A, 2, 2, 0); + ret = gb_svc_intf_set_power_mode(svc, svc->ap_intf_id, + GB_SVC_UNIPRO_HS_SERIES_A, + GB_SVC_UNIPRO_FAST_MODE, 2, 2, + GB_SVC_UNIPRO_FAST_MODE, 2, 2, + GB_SVC_PWRM_RXTERMINATION | + GB_SVC_PWRM_TXTERMINATION, 0); if (ret < 0) goto error; diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index a0bddaa..72e753c 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -737,7 +737,7 @@ struct gb_spi_transfer_response { #define GB_SVC_TYPE_DME_PEER_SET 0x0a #define GB_SVC_TYPE_ROUTE_CREATE 0x0b #define GB_SVC_TYPE_ROUTE_DESTROY 0x0c -#define GB_SVC_TYPE_LINK_CONFIG 0x10 +#define GB_SVC_TYPE_INTF_SET_PWRM 0x10 /* * SVC version request/response has the same payload as @@ -819,20 +819,6 @@ struct gb_svc_dme_peer_set_response { __le16 result_code; } __packed; -#define GB_SVC_LINK_CONFIG_BURST_PWM 0 -#define GB_SVC_LINK_CONFIG_BURST_HS_A 1 -#define GB_SVC_LINK_CONFIG_BURST_HS_B 2 -#define GB_SVC_LINK_CONFIG_FLAG_AUTO_SLEEP (1 << 0) - -struct gb_svc_link_config_request { - __u8 intf_id; - __u8 burst; - __u8 gear; - __u8 nlanes; - __u8 flags; -} __packed; -/* link config response has no payload */ - /* Attributes for peer get/set operations */ #define DME_ATTR_SELECTOR_INDEX 0 /* FIXME: remove ES2 support and DME_ATTR_T_TST_SRC_INCREMENT */ @@ -860,6 +846,40 @@ struct gb_svc_route_destroy_request { } __packed; /* route destroy response has no payload */ +#define GB_SVC_UNIPRO_FAST_MODE 0x01 +#define GB_SVC_UNIPRO_SLOW_MODE 0x02 +#define GB_SVC_UNIPRO_FAST_AUTO_MODE 0x04 +#define GB_SVC_UNIPRO_SLOW_AUTO_MODE 0x05 +#define GB_SVC_UNIPRO_MODE_UNCHANGED 0x07 +#define GB_SVC_UNIPRO_HIBERNATE_MODE 0x11 +#define GB_SVC_UNIPRO_OFF_MODE 0x12 + +#define GB_SVC_PWRM_RXTERMINATION 0x01 +#define GB_SVC_PWRM_TXTERMINATION 0x02 +#define GB_SVC_PWRM_LINE_RESET 0x04 +#define GB_SVC_PWRM_SCRAMBLING 0x20 + +#define GB_SVC_PWRM_QUIRK_HSSER 0x00000001 + +#define GB_SVC_UNIPRO_HS_SERIES_A 0x01 +#define GB_SVC_UNIPRO_HS_SERIES_B 0x02 + +struct gb_svc_intf_set_pwrm_request { + __u8 intf_id; + __u8 hs_series; + __u8 tx_mode; + __u8 tx_gear; + __u8 tx_nlanes; + __u8 rx_mode; + __u8 rx_gear; + __u8 rx_nlanes; + __u8 flags; + __le32 quirks; +} __packed; + +struct gb_svc_intf_set_pwrm_response { + __le16 result_code; +} __packed; /* RAW */ diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index fe7bd28..c4c3bb5 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -285,22 +285,35 @@ static void gb_svc_route_destroy(struct gb_svc *svc, u8 intf1_id, u8 intf2_id) } } -int gb_svc_link_config(struct gb_svc *svc, u8 intf_id, - unsigned int burst, unsigned int gear, - unsigned int nlanes, unsigned int flags) +int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series, + u8 tx_mode, u8 tx_gear, u8 tx_nlanes, + u8 rx_mode, u8 rx_gear, u8 rx_nlanes, + u8 flags, u32 quirks) { - struct gb_svc_link_config_request request; + struct gb_svc_intf_set_pwrm_request request; + struct gb_svc_intf_set_pwrm_response response; + int ret; request.intf_id = intf_id; - request.burst = burst; - request.gear = gear; - request.nlanes = nlanes; + request.hs_series = hs_series; + request.tx_mode = tx_mode; + request.tx_gear = tx_gear; + request.tx_nlanes = tx_nlanes; + request.rx_mode = rx_mode; + request.rx_gear = rx_gear; + request.rx_nlanes = rx_nlanes; request.flags = flags; + request.quirks = cpu_to_le32(quirks); - return gb_operation_sync(svc->connection, GB_SVC_TYPE_LINK_CONFIG, - &request, sizeof(request), NULL, 0); + ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_INTF_SET_PWRM, + &request, sizeof(request), + &response, sizeof(response)); + if (ret < 0) + return ret; + + return le16_to_cpu(response.result_code); } -EXPORT_SYMBOL_GPL(gb_svc_link_config); +EXPORT_SYMBOL_GPL(gb_svc_intf_set_power_mode); static int gb_svc_version_request(struct gb_operation *op) { diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index 2306035..0ebbed9 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -44,9 +44,10 @@ int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, u32 *value); int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, u32 value); -int gb_svc_link_config(struct gb_svc *svc, u8 intf_id, unsigned int burst, - unsigned int gear, unsigned int nlanes, - unsigned int flags); +int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series, + u8 tx_mode, u8 tx_gear, u8 tx_nlanes, + u8 rx_mode, u8 rx_gear, u8 rx_nlanes, + u8 flags, u32 quirks); int gb_svc_protocol_init(void); void gb_svc_protocol_exit(void); -- cgit v0.10.2 From b787d413e0d99ae74e21cdab600ea3c5b0886ec2 Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Fri, 8 Jan 2016 18:13:20 +0200 Subject: greybus: camera: Add support for flags to stream_configure Add support for the flags field of the stream configure request that was recently added to the camera protocol and update the debugfs arguments parsing accordingly. The stream configure response layout is also updated to the latest protocol specification. Signed-off-by: Jacopo Mondi Signed-off-by: Laurent Pinchart Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 4e96e1f..06ea529 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -76,6 +76,7 @@ struct gb_camera_stream_config { static int gb_camera_configure_streams(struct gb_camera *gcam, unsigned int nstreams, + unsigned int flags, struct gb_camera_stream_config *streams) { struct gb_camera_configure_streams_request *req; @@ -99,7 +100,8 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, goto done; } - req->num_streams = cpu_to_le16(nstreams); + req->num_streams = nstreams; + req->flags = flags; req->padding = 0; for (i = 0; i < nstreams; ++i) { @@ -117,9 +119,9 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, if (ret < 0) goto done; - if (le16_to_cpu(resp->num_streams) > nstreams) { + if (resp->num_streams > nstreams) { gcam_dbg(gcam, "got #streams %u > request %u\n", - le16_to_cpu(resp->num_streams), nstreams); + resp->num_streams, nstreams); ret = -EIO; goto done; } @@ -169,7 +171,7 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, gcam_err(gcam, "failed to %s the CSI transmitter\n", nstreams ? "start" : "stop"); - ret = le16_to_cpu(resp->num_streams); + ret = resp->num_streams; done: kfree(req); @@ -266,13 +268,13 @@ static ssize_t gb_camera_debugfs_configure_streams(struct gb_camera *gcam, &gcam->debugfs.buffers[GB_CAMERA_DEBUGFS_BUFFER_STREAMS]; struct gb_camera_stream_config *streams; unsigned int nstreams; - const char *sep = ";"; + unsigned int flags; unsigned int i; char *token; int ret; /* Retrieve number of streams to configure */ - token = strsep(&buf, sep); + token = strsep(&buf, ";"); if (token == NULL) return -EINVAL; @@ -283,6 +285,14 @@ static ssize_t gb_camera_debugfs_configure_streams(struct gb_camera *gcam, if (nstreams > GB_CAMERA_MAX_STREAMS) return -EINVAL; + token = strsep(&buf, ";"); + if (token == NULL) + return -EINVAL; + + ret = kstrtouint(token, 10, &flags); + if (ret < 0) + return ret; + /* For each stream to configure parse width, height and format */ streams = kzalloc(nstreams * sizeof(*streams), GFP_KERNEL); if (!streams) @@ -320,7 +330,7 @@ static ssize_t gb_camera_debugfs_configure_streams(struct gb_camera *gcam, goto done; } - ret = gb_camera_configure_streams(gcam, nstreams, streams); + ret = gb_camera_configure_streams(gcam, nstreams, flags, streams); if (ret < 0) goto done; diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 72e753c..67f260b 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -1173,7 +1173,9 @@ struct gb_camera_stream_config_request { } __packed; struct gb_camera_configure_streams_request { - __le16 num_streams; + __u8 num_streams; + __u8 flags; +#define GB_CAMERA_CONFIGURE_STREAMS_TEST_ONLY 0x01 __le16 padding; struct gb_camera_stream_config_request config[0]; } __packed; @@ -1190,10 +1192,10 @@ struct gb_camera_stream_config_response { } __packed; struct gb_camera_configure_streams_response { - __le16 num_streams; -#define GB_CAMERA_CONFIGURE_STREAMS_ADJUSTED 0x01 + __u8 num_streams; __u8 flags; - __u8 padding; +#define GB_CAMERA_CONFIGURE_STREAMS_ADJUSTED 0x01 + __le16 padding; struct gb_camera_stream_config_response config[0]; } __packed; -- cgit v0.10.2 From 13da9e11e9b781e54fc5db6b65bdcdf6dd96022d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 8 Jan 2016 20:13:43 +0100 Subject: greybus: core: add drvdata accessors Add greybus driver-data accessors. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 405e565..2767946 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -72,6 +72,16 @@ struct greybus_driver { }; #define to_greybus_driver(d) container_of(d, struct greybus_driver, driver) +static inline void greybus_set_drvdata(struct gb_bundle *bundle, void *data) +{ + dev_set_drvdata(&bundle->dev, data); +} + +static inline void *greybus_get_drvdata(struct gb_bundle *bundle) +{ + return dev_get_drvdata(&bundle->dev); +} + /* Don't call these directly, use the module_greybus_driver() macro instead */ int greybus_register_driver(struct greybus_driver *driver, struct module *module, const char *mod_name); -- cgit v0.10.2 From 3c48d1b8a5a9571c9107fc7f2b5aea31d458fd18 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 8 Jan 2016 20:13:42 +0100 Subject: greybus: core: fix greybus driver registration Add missing bus type to driver structure when registering a greybus driver. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 209e1cd..c56c0c4 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -162,6 +162,7 @@ int greybus_register_driver(struct greybus_driver *driver, struct module *owner, if (greybus_disabled()) return -ENODEV; + driver->driver.bus = &greybus_bus_type; driver->driver.name = driver->name; driver->driver.probe = greybus_probe; driver->driver.remove = greybus_remove; -- cgit v0.10.2 From b77f9328f2d629220389d44febf7ab6b48848050 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 8 Jan 2016 20:13:41 +0100 Subject: greybus: core: fix greybus device matching The bus code should only match bundle devices for now, and must not assume all greybus devices are bundles. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index c56c0c4..6b31155 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -65,9 +65,14 @@ greybus_match_id(struct gb_bundle *bundle, const struct greybus_bundle_id *id) static int greybus_module_match(struct device *dev, struct device_driver *drv) { struct greybus_driver *driver = to_greybus_driver(drv); - struct gb_bundle *bundle = to_gb_bundle(dev); + struct gb_bundle *bundle; const struct greybus_bundle_id *id; + if (!is_gb_bundle(dev)) + return 0; + + bundle = to_gb_bundle(dev); + id = greybus_match_id(bundle, driver->id_table); if (id) return 1; -- cgit v0.10.2 From 4e6e3f5cff2dc72c05c8a8fb4539189ac9141133 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 8 Jan 2016 20:13:40 +0100 Subject: greybus: connection: fix version-request error handling Use the host device and connection name when logging errors as the version-request helper must not assume that all connection have a bundle. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 5a24dbe..b356ee0 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -378,8 +378,9 @@ static int gb_connection_protocol_get_version(struct gb_connection *connection) ret = gb_protocol_get_version(connection); if (ret) { - dev_err(&connection->bundle->dev, - "failed to get protocol version: %d\n", ret); + dev_err(&connection->hd->dev, + "%s: failed to get protocol version: %d\n", + connection->name, ret); return ret; } -- cgit v0.10.2 From fc41c2da44c510a919f68e2486aeb456f90a50a4 Mon Sep 17 00:00:00 2001 From: Eli Sennesh Date: Fri, 8 Jan 2016 14:11:29 -0500 Subject: greybus: firmware/bootrom: debug output from bootrom protocol The bootrom protocol issues no dynamic debugging messages when it functions successfully. Use dev_dbg() to fix that by issuing kernel logs when firmware download works. Signed-off-by: Eli Sennesh Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/firmware.c b/drivers/staging/greybus/firmware.c index c65f294..b65787c 100644 --- a/drivers/staging/greybus/firmware.c +++ b/drivers/staging/greybus/firmware.c @@ -61,6 +61,9 @@ static void firmware_es2_fixup_vid_pid(struct gb_firmware *firmware) firmware->vendor_id = le32_to_cpu(response.vendor_id); firmware->product_id = le32_to_cpu(response.product_id); + + dev_dbg(&connection->bundle->dev, "Firmware got vid (0x%x)/pid (0x%x)\n", + firmware->vendor_id, firmware->product_id); } /* This returns path of the firmware blob on the disk */ @@ -69,6 +72,7 @@ static int download_firmware(struct gb_firmware *firmware, u8 stage) struct gb_connection *connection = firmware->connection; struct gb_interface *intf = connection->bundle->intf; char firmware_name[48]; + int rc; /* Already have a firmware, free it */ if (firmware->fw) @@ -84,8 +88,11 @@ static int download_firmware(struct gb_firmware *firmware, u8 stage) intf->ddbl1_manufacturer_id, intf->ddbl1_product_id, firmware->vendor_id, firmware->product_id, stage); - return request_firmware(&firmware->fw, firmware_name, - &connection->bundle->dev); + rc = request_firmware(&firmware->fw, firmware_name, + &connection->bundle->dev); + dev_dbg(&connection->bundle->dev, "Searched for TFTF %s: %d\n", + firmware_name, rc); + return rc; } static int gb_firmware_size_request(struct gb_operation *op) @@ -121,6 +128,8 @@ static int gb_firmware_size_request(struct gb_operation *op) size_response = op->response->payload; size_response->size = cpu_to_le32(firmware->fw->size); + dev_dbg(dev, "%s: firmware size %d bytes\n", __func__, size_response->size); + return 0; } @@ -165,6 +174,9 @@ static int gb_firmware_get_firmware(struct gb_operation *op) firmware_response = op->response->payload; memcpy(firmware_response->data, fw->data + offset, size); + dev_dbg(dev, "responding with firmware (offs = %u, size = %u)\n", offset, + size); + return 0; } @@ -192,6 +204,7 @@ static int gb_firmware_ready_to_boot(struct gb_operation *op) /* * XXX Should we return error for insecure firmware? */ + dev_dbg(dev, "ready to boot: 0x%x, 0\n", status); return 0; } @@ -245,6 +258,8 @@ static int gb_firmware_connection_init(struct gb_connection *connection) "failed to send AP READY: %d\n", ret); } + dev_dbg(&connection->bundle->dev, "%s: AP_READY sent\n", __func__); + return 0; } @@ -258,6 +273,8 @@ static void gb_firmware_connection_exit(struct gb_connection *connection) connection->private = NULL; kfree(firmware); + + dev_dbg(&connection->bundle->dev, "%s\n", __func__); } static struct gb_protocol firmware_protocol = { -- cgit v0.10.2 From 73658f2a285dd8b53160355e619fcb59db3bb98a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 11 Jan 2016 11:29:03 +0530 Subject: greybus: arche-platform: arche_pdata is guaranteed to be valid arche_pdata is guaranteed to be valid in arche_platform_remove(). Signed-off-by: Viresh Kumar Reviewed-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index e6fe015..259473c 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -179,10 +179,7 @@ static int arche_platform_remove(struct platform_device *pdev) struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev); device_for_each_child(&pdev->dev, NULL, arche_remove_child); - - if (arche_pdata) - arche_platform_cleanup(arche_pdata); - + arche_platform_cleanup(arche_pdata); platform_set_drvdata(pdev, NULL); unexport_gpios(arche_pdata); -- cgit v0.10.2 From 8adf71d1b43aa1c449d22dd8e6f6c29957872a7f Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 11 Jan 2016 11:29:04 +0530 Subject: greybus: arche-platform: Export GPIOs after populating APBs Populating APBs operation can potentially fail and it would be better if we export the GPIOs towards then end of the routine, so that we don't need to unexport them on error cases. Signed-off-by: Viresh Kumar Reviewed-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 259473c..93d90b2 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -154,13 +154,13 @@ static int arche_platform_probe(struct platform_device *pdev) arche_pdata->num_apbs = of_get_child_count(np); dev_dbg(dev, "Number of APB's available - %d\n", arche_pdata->num_apbs); - export_gpios(arche_pdata); - /* probe all childs here */ ret = of_platform_populate(np, NULL, NULL, dev); if (ret) dev_err(dev, "no child node found\n"); + export_gpios(arche_pdata); + dev_info(dev, "Device registered successfully\n"); return ret; } -- cgit v0.10.2 From 72a8c24b6dcae46c4e8c37c1b1d1adb6e6b8a72f Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 11 Jan 2016 11:29:05 +0530 Subject: greybus: arche-platform: Put APB in reset if of_platform_populate() fails The current implementation around of_platform_populate() is not so great. On error, we first print an error message, followed by a success message and finally we return an error. And over that we don't undo what we did initially. This patch puts the APB back into reset and create a separate error path to make things clear. Signed-off-by: Viresh Kumar Reviewed-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 93d90b2..67bbd71 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -156,13 +156,16 @@ static int arche_platform_probe(struct platform_device *pdev) /* probe all childs here */ ret = of_platform_populate(np, NULL, NULL, dev); - if (ret) + if (ret) { + arche_platform_cleanup(arche_pdata); dev_err(dev, "no child node found\n"); + return ret; + } export_gpios(arche_pdata); dev_info(dev, "Device registered successfully\n"); - return ret; + return 0; } static int arche_remove_child(struct device *dev, void *unused) -- cgit v0.10.2 From 140741ec6384435b1a0f89042a2a6dac8e2eebd2 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 11 Jan 2016 11:29:06 +0530 Subject: greybus: arche-platform: svc_reset_gpio can't be invalid in arche_platform_cleanup() svc_reset_gpio is guaranteed to be valid in arche_platform_cleanup. Drop the useless check. Signed-off-by: Viresh Kumar Reviewed-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 67bbd71..93ecd8c 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -61,9 +61,8 @@ static void unexport_gpios(struct arche_platform_drvdata *arche_pdata) static void arche_platform_cleanup(struct arche_platform_drvdata *arche_pdata) { /* As part of exit, put APB back in reset state */ - if (gpio_is_valid(arche_pdata->svc_reset_gpio)) - svc_reset_onoff(arche_pdata->svc_reset_gpio, - arche_pdata->is_reset_act_hi); + svc_reset_onoff(arche_pdata->svc_reset_gpio, + arche_pdata->is_reset_act_hi); } static int arche_platform_probe(struct platform_device *pdev) -- cgit v0.10.2 From f1f251b59b6db97c42d7d746727072cb37604494 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 11 Jan 2016 11:29:07 +0530 Subject: greybus: arche-platform: propagate errors returned by gpiolib Propagate errors returned by of_get_named_gpio() instead of sending -ENODEV. Signed-off-by: Viresh Kumar Reviewed-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 93ecd8c..52c79ae 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -82,7 +82,7 @@ static int arche_platform_probe(struct platform_device *pdev) arche_pdata->svc_reset_gpio = of_get_named_gpio(np, "svc,reset-gpio", 0); if (arche_pdata->svc_reset_gpio < 0) { dev_err(dev, "failed to get reset-gpio\n"); - return -ENODEV; + return arche_pdata->svc_reset_gpio; } ret = devm_gpio_request(dev, arche_pdata->svc_reset_gpio, "svc-reset"); if (ret) { @@ -100,7 +100,7 @@ static int arche_platform_probe(struct platform_device *pdev) "svc,sysboot-gpio", 0); if (arche_pdata->svc_sysboot_gpio < 0) { dev_err(dev, "failed to get sysboot gpio\n"); - return -ENODEV; + return arche_pdata->svc_sysboot_gpio; } ret = devm_gpio_request(dev, arche_pdata->svc_sysboot_gpio, "sysboot0"); if (ret) { @@ -118,7 +118,7 @@ static int arche_platform_probe(struct platform_device *pdev) "svc,refclk-req-gpio", 0); if (arche_pdata->svc_refclk_req < 0) { dev_err(dev, "failed to get svc clock-req gpio\n"); - return -ENODEV; + return arche_pdata->svc_refclk_req; } ret = devm_gpio_request(dev, arche_pdata->svc_refclk_req, "svc-clk-req"); if (ret) { -- cgit v0.10.2 From 3b538c399c3273ec268f7c641c8ce35c1235763a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 11 Jan 2016 11:29:08 +0530 Subject: greybus: arche-apb: Spelling and whitespace fixes - s/premits/permits - Remove blank lines at the end of the file Signed-off-by: Viresh Kumar Reviewed-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index 701cd56..4fe2d11 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -364,7 +364,7 @@ int arche_apb_ctrl_remove(struct platform_device *pdev) static int arche_apb_ctrl_suspend(struct device *dev) { /* - * If timing profile premits, we may shutdown bridge + * If timing profile permits, we may shutdown bridge * completely * * TODO: sequence ?? @@ -392,5 +392,3 @@ static int arche_apb_ctrl_resume(struct device *dev) SIMPLE_DEV_PM_OPS(arche_apb_ctrl_pm_ops, arche_apb_ctrl_suspend, arche_apb_ctrl_resume); - - -- cgit v0.10.2 From 977ff250755f4ae01ef50e98d792fabebb199c34 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 11 Jan 2016 11:29:09 +0530 Subject: greybus: arche-apb: platform data 'apb' is guaranteed to be valid Platform data 'apb' is guaranteed to be valid in arche_apb_ctrl_remove() and so no need to check it. Signed-off-by: Viresh Kumar Reviewed-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index 4fe2d11..3d71093 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -352,9 +352,7 @@ int arche_apb_ctrl_remove(struct platform_device *pdev) { struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); - if (apb) - apb_ctrl_cleanup(apb); - + apb_ctrl_cleanup(apb); platform_set_drvdata(pdev, NULL); unexport_gpios(apb); -- cgit v0.10.2 From 7541c1a1c6b0e5531545c400e27b8aee2ba71610 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 11 Jan 2016 11:29:10 +0530 Subject: greybus: arche-apb: Replace gpio_is_valid() with gpio < 0 checks There can be no invalid values in the DTS. The actual pin numbers are assigned by gpiolib when the gpio controller is registered. And so a simple 'gpio < 0' is enough instead of gpio_is_valid() which also checks for 'gpio < ARCH_NR_GPIOS'. This will make the usage of of_get_named_gpio() similar with how it is done in arche-platform driver. Signed-off-by: Viresh Kumar Reviewed-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index 3d71093..b06bb34 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -211,37 +211,37 @@ static int apb_ctrl_get_devtree_data(struct platform_device *pdev, struct device_node *np = dev->of_node; apb->wake_detect_gpio = of_get_named_gpio(np, "wake-detect-gpios", 0); - if (!gpio_is_valid(apb->wake_detect_gpio)) { + if (apb->wake_detect_gpio < 0) { dev_err(dev, "failed to get wake detect gpio\n"); return apb->wake_detect_gpio; } apb->resetn_gpio = of_get_named_gpio(np, "reset-gpios", 0); - if (!gpio_is_valid(apb->resetn_gpio)) { + if (apb->resetn_gpio < 0) { dev_err(dev, "failed to get reset gpio\n"); return apb->resetn_gpio; } apb->boot_ret_gpio = of_get_named_gpio(np, "boot-ret-gpios", 0); - if (!gpio_is_valid(apb->boot_ret_gpio)) { + if (apb->boot_ret_gpio < 0) { dev_err(dev, "failed to get boot retention gpio\n"); return apb->boot_ret_gpio; } /* It's not mandatory to support power management interface */ apb->pwroff_gpio = of_get_named_gpio(np, "pwr-off-gpios", 0); - if (!gpio_is_valid(apb->pwroff_gpio)) { + if (apb->pwroff_gpio < 0) { dev_info(dev, "failed to get power off gpio\n"); return apb->pwroff_gpio; } /* Do not make clock mandatory as of now (for DB3) */ apb->clk_en_gpio = of_get_named_gpio(np, "clock-en-gpio", 0); - if (!gpio_is_valid(apb->clk_en_gpio)) + if (apb->clk_en_gpio < 0) dev_err(dev, "failed to get clock en gpio\n"); apb->pwrdn_gpio = of_get_named_gpio(np, "pwr-down-gpios", 0); - if (!gpio_is_valid(apb->pwrdn_gpio)) + if (apb->pwrdn_gpio < 0) dev_info(dev, "failed to get power down gpio\n"); /* Regulators are optional, as we may have fixed supply coming in */ -- cgit v0.10.2 From bd62fa5e1067bd5a3c8421ae3de0021a67223e22 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 11 Jan 2016 11:29:11 +0530 Subject: greybus: arche-apb: devm_regulator_get() doesn't return NULL And so we don't need to check for it. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index b06bb34..1ae2c06 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -246,13 +246,13 @@ static int apb_ctrl_get_devtree_data(struct platform_device *pdev, /* Regulators are optional, as we may have fixed supply coming in */ apb->vcore = devm_regulator_get(dev, "vcore"); - if (IS_ERR_OR_NULL(apb->vcore)) { + if (IS_ERR(apb->vcore)) { dev_info(dev, "no core regulator found\n"); apb->vcore = NULL; } apb->vio = devm_regulator_get(dev, "vio"); - if (IS_ERR_OR_NULL(apb->vio)) { + if (IS_ERR(apb->vio)) { dev_info(dev, "no IO regulator found\n"); apb->vio = NULL; } -- cgit v0.10.2 From dcf77c397918178af09b72f63145eed3fde788ba Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 11 Jan 2016 11:29:12 +0530 Subject: greybus: arche-apb: NULL is a valid regulator Since NULL could in theory be a valid regulator we ought to check for IS_ERR() rather than for NULL. In practice this is unlikely to be an issue but it's better for neatness. Signed-off-by: Viresh Kumar Reviewed-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index 1ae2c06..acdeb71 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -170,14 +170,14 @@ static int apb_ctrl_init_seq(struct platform_device *pdev, } /* Enable power to APB */ - if (apb->vcore) { + if (!IS_ERR(apb->vcore)) { ret = regulator_enable(apb->vcore); if (ret) { dev_err(dev, "failed to enable core regulator\n"); return ret; } } - if (apb->vio) { + if (!IS_ERR(apb->vio)) { ret = regulator_enable(apb->vio); if (ret) { dev_err(dev, "failed to enable IO regulator\n"); @@ -246,16 +246,12 @@ static int apb_ctrl_get_devtree_data(struct platform_device *pdev, /* Regulators are optional, as we may have fixed supply coming in */ apb->vcore = devm_regulator_get(dev, "vcore"); - if (IS_ERR(apb->vcore)) { + if (IS_ERR(apb->vcore)) dev_info(dev, "no core regulator found\n"); - apb->vcore = NULL; - } apb->vio = devm_regulator_get(dev, "vio"); - if (IS_ERR(apb->vio)) { + if (IS_ERR(apb->vio)) dev_info(dev, "no IO regulator found\n"); - apb->vio = NULL; - } apb->pinctrl = devm_pinctrl_get(&pdev->dev); if (IS_ERR(apb->pinctrl)) { @@ -275,10 +271,10 @@ static void apb_ctrl_cleanup(struct arche_apb_ctrl_drvdata *apb) { unsigned long flags; - if (apb->vcore && regulator_is_enabled(apb->vcore) > 0) + if (!IS_ERR(apb->vcore) && regulator_is_enabled(apb->vcore) > 0) regulator_disable(apb->vcore); - if (apb->vio && regulator_is_enabled(apb->vio) > 0) + if (!IS_ERR(apb->vio) && regulator_is_enabled(apb->vio) > 0) regulator_disable(apb->vio); spin_lock_irqsave(&apb->lock, flags); -- cgit v0.10.2 From db0cff554a612715701a04143df595cc87737d55 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 11 Jan 2016 11:29:13 +0530 Subject: greybus: arche-apb: Properly use dev_err/info/warn Use dev_err for errors after which we need to abort the currently running routine and dev_warn for resource allocation failure, with which we can continue to work. Signed-off-by: Viresh Kumar Reviewed-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index acdeb71..8582a48 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -138,11 +138,11 @@ static int apb_ctrl_init_seq(struct platform_device *pdev, if (gpio_is_valid(apb->clk_en_gpio)) { ret = devm_gpio_request(dev, apb->clk_en_gpio, "apb_clk_en"); if (ret) - dev_err(dev, "Failed requesting APB clock en gpio %d\n", + dev_warn(dev, "Failed requesting APB clock en gpio %d\n", apb->clk_en_gpio); ret = gpio_direction_output(apb->clk_en_gpio, 1); if (ret) - dev_err(dev, "failed to set APB clock en gpio dir:%d\n", ret); + dev_warn(dev, "failed to set APB clock en gpio dir:%d\n", ret); } /* Hold APB in reset state */ ret = devm_gpio_request(dev, apb->resetn_gpio, "apb-reset"); @@ -231,27 +231,27 @@ static int apb_ctrl_get_devtree_data(struct platform_device *pdev, /* It's not mandatory to support power management interface */ apb->pwroff_gpio = of_get_named_gpio(np, "pwr-off-gpios", 0); if (apb->pwroff_gpio < 0) { - dev_info(dev, "failed to get power off gpio\n"); + dev_err(dev, "failed to get power off gpio\n"); return apb->pwroff_gpio; } /* Do not make clock mandatory as of now (for DB3) */ apb->clk_en_gpio = of_get_named_gpio(np, "clock-en-gpio", 0); if (apb->clk_en_gpio < 0) - dev_err(dev, "failed to get clock en gpio\n"); + dev_warn(dev, "failed to get clock en gpio\n"); apb->pwrdn_gpio = of_get_named_gpio(np, "pwr-down-gpios", 0); if (apb->pwrdn_gpio < 0) - dev_info(dev, "failed to get power down gpio\n"); + dev_warn(dev, "failed to get power down gpio\n"); /* Regulators are optional, as we may have fixed supply coming in */ apb->vcore = devm_regulator_get(dev, "vcore"); if (IS_ERR(apb->vcore)) - dev_info(dev, "no core regulator found\n"); + dev_warn(dev, "no core regulator found\n"); apb->vio = devm_regulator_get(dev, "vio"); if (IS_ERR(apb->vio)) - dev_info(dev, "no IO regulator found\n"); + dev_warn(dev, "no IO regulator found\n"); apb->pinctrl = devm_pinctrl_get(&pdev->dev); if (IS_ERR(apb->pinctrl)) { -- cgit v0.10.2 From a7a794ec540c442999598cf16605ba7962aa3861 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 11 Jan 2016 11:29:14 +0530 Subject: greybus: arche-apb: Don't use gpio after failing to request it If devm_gpio_request() returns an error, we shouldn't try to set the direction of the same gpio. Signed-off-by: Viresh Kumar Reviewed-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index 8582a48..f83230d 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -137,12 +137,15 @@ static int apb_ctrl_init_seq(struct platform_device *pdev, /* On DB3 clock was not mandatory */ if (gpio_is_valid(apb->clk_en_gpio)) { ret = devm_gpio_request(dev, apb->clk_en_gpio, "apb_clk_en"); - if (ret) + if (ret) { dev_warn(dev, "Failed requesting APB clock en gpio %d\n", - apb->clk_en_gpio); - ret = gpio_direction_output(apb->clk_en_gpio, 1); - if (ret) - dev_warn(dev, "failed to set APB clock en gpio dir:%d\n", ret); + apb->clk_en_gpio); + } else { + ret = gpio_direction_output(apb->clk_en_gpio, 1); + if (ret) + dev_warn(dev, "failed to set APB clock en gpio dir:%d\n", + ret); + } } /* Hold APB in reset state */ ret = devm_gpio_request(dev, apb->resetn_gpio, "apb-reset"); -- cgit v0.10.2 From d258432fb2fbf1a5a4910dbc31aba99d04801268 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 11 Jan 2016 11:29:15 +0530 Subject: greybus: arche-apb: Do cleanup within apb_ctrl_init_seq() for error cases Relying on apb_ctrl_cleanup() to do the cleanup for errors that occurred within apb_ctrl_init_seq() isn't a very clean idea. Handle that separately within apb_ctrl_init_seq(). This will clean apb_ctrl_cleanup() in later patches. Signed-off-by: Viresh Kumar Reviewed-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index f83230d..859d22e 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -184,7 +184,7 @@ static int apb_ctrl_init_seq(struct platform_device *pdev, ret = regulator_enable(apb->vio); if (ret) { dev_err(dev, "failed to enable IO regulator\n"); - return ret; + goto out_vcore_disable; } } @@ -193,16 +193,27 @@ static int apb_ctrl_init_seq(struct platform_device *pdev, if (ret) { dev_err(dev, "Failed requesting bootret gpio %d\n", apb->boot_ret_gpio); - return ret; + goto out_vio_disable; } gpio_set_value(apb->boot_ret_gpio, 0); udelay(50); ret = devm_gpio_request_one(dev, apb->wake_detect_gpio, GPIOF_INIT_LOW, "wake detect"); - if (ret) + if (ret) { dev_err(dev, "Failed requesting wake_detect gpio %d\n", apb->wake_detect_gpio); + goto out_vio_disable; + } + + return 0; + +out_vio_disable: + if (!IS_ERR(apb->vio)) + regulator_disable(apb->vio); +out_vcore_disable: + if (!IS_ERR(apb->vcore)) + regulator_disable(apb->vcore); return ret; } @@ -311,7 +322,7 @@ int arche_apb_ctrl_probe(struct platform_device *pdev) if (ret) { dev_err(dev, "failed to set init state of control signal %d\n", ret); - goto exit; + return ret; } spin_lock_init(&apb->lock); @@ -332,7 +343,8 @@ int arche_apb_ctrl_probe(struct platform_device *pdev) "wake detect", apb); if (ret) { dev_err(dev, "failed to request wake detect IRQ\n"); - goto exit; + apb_ctrl_cleanup(apb); + return ret; } platform_set_drvdata(pdev, apb); @@ -341,10 +353,6 @@ int arche_apb_ctrl_probe(struct platform_device *pdev) dev_info(&pdev->dev, "Device registered successfully\n"); return 0; - -exit: - apb_ctrl_cleanup(apb); - return ret; } int arche_apb_ctrl_remove(struct platform_device *pdev) -- cgit v0.10.2 From 40989cf3c1e3c114d3558ad4d7513344ed612ac2 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 11 Jan 2016 11:29:16 +0530 Subject: greybus: arche-apb: Drop unnecessary checks wake_detect_gpio and resetn_gpio are guaranteed to be valid in apb_ctrl_cleanup() and irq-handler, no need to check for their validity. Signed-off-by: Viresh Kumar Reviewed-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index 859d22e..04c4467 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -94,10 +94,6 @@ static irqreturn_t apb_ctrl_wake_detect_irq(int irq, void *devid) * signals, especially when we start using GPIOs over slow * buses like I2C. */ - if (!gpio_is_valid(apb->wake_detect_gpio) && - !gpio_is_valid(apb->resetn_gpio)) - return IRQ_HANDLED; /* Should it be IRQ_NONE ?? */ - spin_lock_irqsave(&apb->lock, flags); if (apb->state != APB_STATE_ACTIVE) { @@ -293,9 +289,7 @@ static void apb_ctrl_cleanup(struct arche_apb_ctrl_drvdata *apb) spin_lock_irqsave(&apb->lock, flags); /* As part of exit, put APB back in reset state */ - if (gpio_is_valid(apb->resetn_gpio)) - gpio_set_value(apb->resetn_gpio, 0); - + gpio_set_value(apb->resetn_gpio, 0); apb->state = APB_STATE_OFF; spin_unlock_irqrestore(&apb->lock, flags); -- cgit v0.10.2 From 3b858df01fe936bbd329ecf13c3a3d81486f1f16 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 11 Jan 2016 11:29:17 +0530 Subject: greybus: arche: Remove unwanted headers and rearrange others This removes few unwanted headers related to irq, interrupt, regulator, spinlock, etc. Also arrange the rest in alphabetical order to make it more readable. Signed-off-by: Viresh Kumar Reviewed-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index 04c4467..afdaeca 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -7,22 +7,18 @@ * Released under the GPLv2 only. */ -#include -#include -#include -#include -#include -#include +#include #include -#include #include -#include -#include +#include #include #include -#include -#include +#include #include +#include +#include +#include +#include #include "arche_platform.h" enum apb_state { diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 52c79ae..94e6f5d 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -7,22 +7,15 @@ * Released under the GPLv2 only. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include +#include +#include +#include #include -#include -#include -#include +#include #include +#include +#include #include "arche_platform.h" struct arche_platform_drvdata { -- cgit v0.10.2 From 33036178bf04a06ad7e87513c76d7075959088e8 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Mon, 11 Jan 2016 17:41:22 +0530 Subject: greybus: arche-apb-ctrl: Remove wake_detect gpio and related code With TIME_SYNC functionality, assignment of wake/detect pin will change, WD_8A => to bring APB's out of reset WD_8B => TIME_SYNC operation So in order to support this, we can no longer keep wake_detect gpio in apb-ctrl driver. So remove it. In the subsequent patches, wake_detect support will be added to parent SVC driver (arche-platform) who is responsible for SVC control. Note that, this patch also removes ISR related code. The APB state still is maintained, for future use. Signed-off-by: Vaibhav Hiremath Tested-by: Michael Scott Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index afdaeca..5b9a3ed 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -29,7 +29,6 @@ enum apb_state { struct arche_apb_ctrl_drvdata { /* Control GPIO signals to and from AP <=> AP Bridges */ - int wake_detect_gpio; /* bi-dir,maps to WAKE_MOD & WAKE_FRAME signals */ int resetn_gpio; int boot_ret_gpio; int pwroff_gpio; @@ -37,7 +36,6 @@ struct arche_apb_ctrl_drvdata { int wake_out_gpio; int pwrdn_gpio; - unsigned int wake_detect_irq; enum apb_state state; struct regulator *vcore; @@ -48,9 +46,6 @@ struct arche_apb_ctrl_drvdata { struct pinctrl *pinctrl; struct pinctrl_state *pin_default; - - /* To protect concurrent access of GPIO registers, need protection */ - spinlock_t lock; }; /* @@ -78,45 +73,6 @@ static void unexport_gpios(struct arche_apb_ctrl_drvdata *apb) gpio_unexport(apb->resetn_gpio); } -static irqreturn_t apb_ctrl_wake_detect_irq(int irq, void *devid) -{ - struct arche_apb_ctrl_drvdata *apb = devid; - unsigned long flags; - - /* - * TODO: - * Since currently SoC GPIOs are being used we are safe here - * But ideally we should create a workqueue and process the control - * signals, especially when we start using GPIOs over slow - * buses like I2C. - */ - spin_lock_irqsave(&apb->lock, flags); - - if (apb->state != APB_STATE_ACTIVE) { - /* Bring bridge out of reset on this event */ - gpio_set_value(apb->resetn_gpio, 1); - apb->state = APB_STATE_ACTIVE; - } else { - /* - * Assert Wake_OUT signal to APB - * It would resemble WakeDetect module's signal pass-through - */ - /* - * We have to generate the pulse, so we may need to schedule - * workqueue here. - * - * Also, since we are using both rising and falling edge for - * interrupt trigger, we may not need workqueue. Just pass - * through the value to bridge. - * Just read GPIO value and pass it to the bridge - */ - } - - spin_unlock_irqrestore(&apb->lock, flags); - - return IRQ_HANDLED; -} - /* * Note: Please do not modify the below sequence, as it is as per the spec */ @@ -190,14 +146,6 @@ static int apb_ctrl_init_seq(struct platform_device *pdev, gpio_set_value(apb->boot_ret_gpio, 0); udelay(50); - ret = devm_gpio_request_one(dev, apb->wake_detect_gpio, - GPIOF_INIT_LOW, "wake detect"); - if (ret) { - dev_err(dev, "Failed requesting wake_detect gpio %d\n", - apb->wake_detect_gpio); - goto out_vio_disable; - } - return 0; out_vio_disable: @@ -216,12 +164,6 @@ static int apb_ctrl_get_devtree_data(struct platform_device *pdev, struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; - apb->wake_detect_gpio = of_get_named_gpio(np, "wake-detect-gpios", 0); - if (apb->wake_detect_gpio < 0) { - dev_err(dev, "failed to get wake detect gpio\n"); - return apb->wake_detect_gpio; - } - apb->resetn_gpio = of_get_named_gpio(np, "reset-gpios", 0); if (apb->resetn_gpio < 0) { dev_err(dev, "failed to get reset gpio\n"); @@ -275,19 +217,15 @@ static int apb_ctrl_get_devtree_data(struct platform_device *pdev, static void apb_ctrl_cleanup(struct arche_apb_ctrl_drvdata *apb) { - unsigned long flags; - if (!IS_ERR(apb->vcore) && regulator_is_enabled(apb->vcore) > 0) regulator_disable(apb->vcore); if (!IS_ERR(apb->vio) && regulator_is_enabled(apb->vio) > 0) regulator_disable(apb->vio); - spin_lock_irqsave(&apb->lock, flags); /* As part of exit, put APB back in reset state */ gpio_set_value(apb->resetn_gpio, 0); apb->state = APB_STATE_OFF; - spin_unlock_irqrestore(&apb->lock, flags); /* TODO: May have to send an event to SVC about this exit */ } @@ -315,27 +253,8 @@ int arche_apb_ctrl_probe(struct platform_device *pdev) return ret; } - spin_lock_init(&apb->lock); - apb->state = APB_STATE_OFF; - /* - * Assert AP module detect signal by pulling wake_detect low - */ - assert_gpio(apb->wake_detect_gpio); - /* - * In order to receive an interrupt, the GPIO must be set to input mode - */ - gpio_direction_input(apb->wake_detect_gpio); - - ret = devm_request_irq(dev, gpio_to_irq(apb->wake_detect_gpio), - apb_ctrl_wake_detect_irq, IRQF_TRIGGER_FALLING, - "wake detect", apb); - if (ret) { - dev_err(dev, "failed to request wake detect IRQ\n"); - apb_ctrl_cleanup(apb); - return ret; - } platform_set_drvdata(pdev, apb); -- cgit v0.10.2 From f1e9cbd5a097aa6ec62f261bdf44879bbaefb72a Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Mon, 11 Jan 2016 17:41:23 +0530 Subject: greybus: arche-apb-ctrl: deassert reset at the end of probe Now the complete handshaking between AP<=>SVC would be offloaded to parent driver (arche-platform) who is responsible for SVC control, so the apb-ctrl driver can just simply bring APB's out of reset during probe itself. Along with deasserting reset, this patch renames the local fn to exclusively use it for reset purpose. Note that, driver is exporting reset gpio to user, so user can still flash FW from prompt. Signed-off-by: Vaibhav Hiremath Tested-by: Michael Scott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index 5b9a3ed..65b1e9a 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -51,13 +51,13 @@ struct arche_apb_ctrl_drvdata { /* * Note that these low level api's are active high */ -static inline void assert_gpio(unsigned int gpio) +static inline void deassert_reset(unsigned int gpio) { gpio_set_value(gpio, 1); msleep(500); } -static inline void deassert_gpio(unsigned int gpio) +static inline void assert_reset(unsigned int gpio) { gpio_set_value(gpio, 0); } @@ -224,7 +224,7 @@ static void apb_ctrl_cleanup(struct arche_apb_ctrl_drvdata *apb) regulator_disable(apb->vio); /* As part of exit, put APB back in reset state */ - gpio_set_value(apb->resetn_gpio, 0); + assert_reset(apb->resetn_gpio); apb->state = APB_STATE_OFF; /* TODO: May have to send an event to SVC about this exit */ @@ -253,8 +253,9 @@ int arche_apb_ctrl_probe(struct platform_device *pdev) return ret; } - apb->state = APB_STATE_OFF; - + /* deassert reset to APB : Active-low signal */ + deassert_reset(apb->resetn_gpio); + apb->state = APB_STATE_ACTIVE; platform_set_drvdata(pdev, apb); -- cgit v0.10.2 From a463fc1533c9ea2edc99306b31c74f472c62d690 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Mon, 11 Jan 2016 17:41:24 +0530 Subject: greybus: arche-platform: Add wake/detect support along with handshaking with AP Add wake_detect support to arche-platform driver which is responsible for SVC control. This patch also adds code for handshaking between AP <=> SVC. The sequence is, 1. AP boots To keep compatibility between DB3 and EVT platform, SVC will be help in reset and AP driver would release it at appropriate time. wake/detect pin (WD8A) = Low reset (SVC/APB1/APB2) = Asserted (as per polarity) 2. AP Driver gets inserted 2.1. AP will deassert reset to SVC (following power on sequence) 2.2. SVC allows 360 milliseconds to elapse after switch boots to work around bug described in ENG-330. 2.3. AP asserts wake/detect pin (WD8A = HIGH) 3. SVC detects assertion of wake/detect pin, and sends "wake out" signal to AP 4. AP receives "wake out" signal, takes AP Bridges through their power on reset sequence as defined in the bridge ASIC reference manuals 5. AP takes USB3613 through its power on reset sequence 6. AP should enumerates AP Bridges Note: ISR has been deliberately removed (not merged) as we are still not sure how it will be used, in runtime usage context. Driver as such doesn't do anything for runtime assert-n-deassert of reset to SVC/APB's, it just simply offloads it to user by exporting required gpio's. The exported gpio's are required for FW flashing from user space. When it comes to usersace manipulated control sequence, user has to manage. Signed-off-by: Vaibhav Hiremath Tested-by: Michael Scott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 94e6f5d..d12fa0e 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -8,6 +8,7 @@ */ #include +#include #include #include #include @@ -23,6 +24,7 @@ struct arche_platform_drvdata { int svc_reset_gpio; bool is_reset_act_hi; int svc_sysboot_gpio; + int wake_detect_gpio; /* bi-dir,maps to WAKE_MOD & WAKE_FRAME signals */ unsigned int svc_refclk_req; struct clk *svc_ref_clk; @@ -31,6 +33,9 @@ struct arche_platform_drvdata { struct pinctrl_state *pin_default; int num_apbs; + + struct delayed_work delayed_work; + struct device *dev; }; static inline void svc_reset_onoff(unsigned int gpio, bool onoff) @@ -38,6 +43,52 @@ static inline void svc_reset_onoff(unsigned int gpio, bool onoff) gpio_set_value(gpio, onoff); } +/** + * svc_delayed_work - Time to give SVC to boot. + */ +static void svc_delayed_work(struct work_struct *work) +{ + struct arche_platform_drvdata *arche_pdata = + container_of(work, struct arche_platform_drvdata, delayed_work.work); + struct device *dev = arche_pdata->dev; + struct device_node *np = dev->of_node; + int timeout = 10; + int ret; + + /* + * 1. SVC and AP boot independently, with AP<-->SVC wake/detect pin + * deasserted (LOW in this case) + * 2.1. SVC allows 360 milliseconds to elapse after switch boots to work + * around bug described in ENG-330. + * 2.2. AP asserts wake/detect pin (HIGH) (this can proceed in parallel with 2.1) + * 3. SVC detects assertion of wake/detect pin, and sends "wake out" signal to AP + * 4. AP receives "wake out" signal, takes AP Bridges through their power + * on reset sequence as defined in the bridge ASIC reference manuals + * 5. AP takes USB3613 through its power on reset sequence + * 6. AP enumerates AP Bridges + */ + gpio_set_value(arche_pdata->wake_detect_gpio, 1); + gpio_direction_input(arche_pdata->wake_detect_gpio); + do { + /* Read the wake_detect GPIO, for WAKE_OUT event from SVC */ + if (gpio_get_value(arche_pdata->wake_detect_gpio) == 0) + break; + + msleep(500); + } while(timeout--); + + if (timeout >= 0) { + ret = of_platform_populate(np, NULL, NULL, dev); + if (!ret) + /* Should we set wake_detect gpio to output again? */ + return; + } + + /* FIXME: We may want to limit retries here */ + gpio_direction_output(arche_pdata->wake_detect_gpio, 0); + schedule_delayed_work(&arche_pdata->delayed_work, msecs_to_jiffies(2000)); +} + /* Export gpio's to user space */ static void export_gpios(struct arche_platform_drvdata *arche_pdata) { @@ -146,18 +197,32 @@ static int arche_platform_probe(struct platform_device *pdev) arche_pdata->num_apbs = of_get_child_count(np); dev_dbg(dev, "Number of APB's available - %d\n", arche_pdata->num_apbs); - /* probe all childs here */ - ret = of_platform_populate(np, NULL, NULL, dev); + arche_pdata->wake_detect_gpio = of_get_named_gpio(np, "svc,wake-detect-gpio", 0); + if (arche_pdata->wake_detect_gpio < 0) { + dev_err(dev, "failed to get wake detect gpio\n"); + ret = arche_pdata->wake_detect_gpio; + goto exit; + } + + ret = devm_gpio_request(dev, arche_pdata->wake_detect_gpio, "wake detect"); if (ret) { - arche_platform_cleanup(arche_pdata); - dev_err(dev, "no child node found\n"); - return ret; + dev_err(dev, "Failed requesting wake_detect gpio %d\n", + arche_pdata->wake_detect_gpio); + goto exit; } + arche_pdata->dev = &pdev->dev; + INIT_DELAYED_WORK(&arche_pdata->delayed_work, svc_delayed_work); + schedule_delayed_work(&arche_pdata->delayed_work, msecs_to_jiffies(2000)); + export_gpios(arche_pdata); dev_info(dev, "Device registered successfully\n"); return 0; + +exit: + arche_platform_cleanup(arche_pdata); + return ret; } static int arche_remove_child(struct device *dev, void *unused) -- cgit v0.10.2 From e0d91ff127cf68e6369cfccd51af18b07bf462e3 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 7 Jan 2016 12:28:29 +0100 Subject: greybus: power_supply: fix lock imbalance in init error path Make sure to release the supplies_lock before returning on errors in gb_power_supplies_setup(). Signed-off-by: Johan Hovold Reviewed-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c index 4a73816..1f3884b 100644 --- a/drivers/staging/greybus/power_supply.c +++ b/drivers/staging/greybus/power_supply.c @@ -644,8 +644,10 @@ static int gb_power_supplies_setup(struct gb_power_supplies *supplies) sizeof(struct gb_power_supply), GFP_KERNEL); - if (!supplies->supply) - return -ENOMEM; + if (!supplies->supply) { + ret = -ENOMEM; + goto out; + } for (i = 0; i < supplies->supplies_count; i++) { ret = gb_power_supply_config(supplies, i); -- cgit v0.10.2 From 7ccac20d59ca45a2efea93a24a99d57022ff8911 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Fri, 8 Jan 2016 13:53:42 +0000 Subject: greybus: power_supply: do not release failed supply alloc If allocation of memory for each supply fail, we should get out of release any individual supply. Signed-off-by: Rui Miguel Silva Reported-by: Johan Hovold Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c index 1f3884b..1ce57f6 100644 --- a/drivers/staging/greybus/power_supply.c +++ b/drivers/staging/greybus/power_supply.c @@ -569,6 +569,9 @@ static void _gb_power_supplies_release(struct gb_power_supplies *supplies) { int i; + if (!supplies->supply) + return; + mutex_lock(&supplies->supplies_lock); for (i = 0; i < supplies->supplies_count; i++) _gb_power_supply_release(&supplies->supply[i]); -- cgit v0.10.2 From ff85f723ca362986dc984217433cbdd133fc03d6 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Fri, 8 Jan 2016 13:53:43 +0000 Subject: greybus: power_supply: fix unregister on error path If setup fail the release for each supply needs to know the status at unregister time. So, add the field to the structure, update it at setup time and use it at release. Signed-off-by: Rui Miguel Silva Reported-by: Johan Hovold Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c index 1ce57f6..764d2f6 100644 --- a/drivers/staging/greybus/power_supply.c +++ b/drivers/staging/greybus/power_supply.c @@ -25,6 +25,7 @@ struct gb_power_supply_prop { struct gb_power_supply { u8 id; + bool registered; #ifdef DRIVER_OWNS_PSY_STRUCT struct power_supply psy; #define to_gb_power_supply(x) container_of(x, struct gb_power_supply, psy) @@ -557,9 +558,11 @@ static void _gb_power_supply_release(struct gb_power_supply *gbpsy) cancel_delayed_work_sync(&gbpsy->work); #ifdef DRIVER_OWNS_PSY_STRUCT - power_supply_unregister(&gbpsy->psy); + if (gbpsy->registered) + power_supply_unregister(&gbpsy->psy); #else - power_supply_unregister(gbpsy->psy); + if (gbpsy->registered) + power_supply_unregister(gbpsy->psy); #endif _gb_power_supply_free(gbpsy); @@ -628,6 +631,9 @@ static int gb_power_supply_config(struct gb_power_supplies *supplies, int id) schedule_delayed_work(&gbpsy->work, 0); out: + /* if everything went fine just mark it for release code to know */ + if (ret == 0) + gbpsy->registered = true; return ret; } -- cgit v0.10.2 From 23f25ba6edd4121eb70baf3df12f5592bee8a1e9 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Fri, 8 Jan 2016 13:53:44 +0000 Subject: greybus: power_supply: free supplies at release After freeing each individual power_supply, free the top controller, if not it will leak memory at each module insert/remove. Signed-off-by: Rui Miguel Silva Reported-by: Johan Hovold Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c index 764d2f6..7d1848b 100644 --- a/drivers/staging/greybus/power_supply.c +++ b/drivers/staging/greybus/power_supply.c @@ -579,6 +579,7 @@ static void _gb_power_supplies_release(struct gb_power_supplies *supplies) for (i = 0; i < supplies->supplies_count; i++) _gb_power_supply_release(&supplies->supply[i]); mutex_unlock(&supplies->supplies_lock); + kfree(supplies); } static int gb_power_supplies_get_count(struct gb_power_supplies *supplies) -- cgit v0.10.2 From d9eafd58e3e365d71cd7d477a1c5675db1931027 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Fri, 8 Jan 2016 13:53:45 +0000 Subject: greybus: power_supply: fix error path at supplies setup If something goes wrong at setup time for the supplies, we need to release all the resources allocated already. Call the supplies release function which will handle the correct teardown of the supplies. Signed-off-by: Rui Miguel Silva Reported-by: Johan Hovold Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c index 7d1848b..28548a2 100644 --- a/drivers/staging/greybus/power_supply.c +++ b/drivers/staging/greybus/power_supply.c @@ -731,6 +731,7 @@ out_unlock: static int gb_power_supply_connection_init(struct gb_connection *connection) { struct gb_power_supplies *supplies; + int ret; supplies = kzalloc(sizeof(*supplies), GFP_KERNEL); if (!supplies) @@ -741,7 +742,11 @@ static int gb_power_supply_connection_init(struct gb_connection *connection) mutex_init(&supplies->supplies_lock); - return gb_power_supplies_setup(supplies); + ret = gb_power_supplies_setup(supplies); + if (ret < 0) + _gb_power_supplies_release(supplies); + + return ret; } static void gb_power_supply_connection_exit(struct gb_connection *connection) -- cgit v0.10.2 From f921fb139bd5ee008ec993c76b8a89a535fd11e9 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Fri, 8 Jan 2016 13:53:46 +0000 Subject: greybus: power_supply: fix leak getting string properties When fetching string properties, memory was being allocated and leaked when it was not necessary to do so. Signed-off-by: Rui Miguel Silva Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c index 28548a2..3c9bb12 100644 --- a/drivers/staging/greybus/power_supply.c +++ b/drivers/staging/greybus/power_supply.c @@ -347,15 +347,13 @@ static int __gb_power_supply_property_strval_get(struct gb_power_supply *gbpsy, { switch (psp) { case POWER_SUPPLY_PROP_MODEL_NAME: - val->strval = kstrndup(gbpsy->model_name, PROP_MAX, GFP_KERNEL); + val->strval = gbpsy->model_name; break; case POWER_SUPPLY_PROP_MANUFACTURER: - val->strval = kstrndup(gbpsy->manufacturer, PROP_MAX, - GFP_KERNEL); + val->strval = gbpsy->manufacturer; break; case POWER_SUPPLY_PROP_SERIAL_NUMBER: - val->strval = kstrndup(gbpsy->serial_number, PROP_MAX, - GFP_KERNEL); + val->strval = gbpsy->serial_number; break; default: break; -- cgit v0.10.2 From accad1ba7d62543ab3bcf08813726ea87d237bb6 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Fri, 8 Jan 2016 13:53:47 +0000 Subject: greybus: power_supply: fix use after free of power supply Individual power supply were being freed and checked using the wrong pointers and at the wrong place, which would make several issues, like used after free and so on. Fix it by freeing all allocated memory after release individual power supply. Signed-off-by: Rui Miguel Silva Reported-by: Johan Hovold Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c index 3c9bb12..d985e13 100644 --- a/drivers/staging/greybus/power_supply.c +++ b/drivers/staging/greybus/power_supply.c @@ -544,13 +544,10 @@ static void _gb_power_supply_free(struct gb_power_supply *gbpsy) kfree(gbpsy->manufacturer); kfree(gbpsy->props_raw); kfree(gbpsy->props); - kfree(gbpsy); } static void _gb_power_supply_release(struct gb_power_supply *gbpsy) { - if (!gbpsy) - return; gbpsy->update_interval = 0; @@ -576,6 +573,7 @@ static void _gb_power_supplies_release(struct gb_power_supplies *supplies) mutex_lock(&supplies->supplies_lock); for (i = 0; i < supplies->supplies_count; i++) _gb_power_supply_release(&supplies->supply[i]); + kfree(supplies->supply); mutex_unlock(&supplies->supplies_lock); kfree(supplies); } -- cgit v0.10.2 From ed4596e9b19104ccc1e87bde8fcadee3a473c101 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 22 Dec 2015 18:21:51 -0800 Subject: greybus: host: provide "generic" apbridge output calls Provide a new function, gb_hd_output() to send data to the apbridge. This is useful for the camera and audio drivers that need to do this type of messaging. The camera driver is converted to use this new function, the audio driver can use it when it gets merged later. Signed-off-by: Greg Kroah-Hartman Tested-by: Mark Greer Reviewed-by: Johan Hovold diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 06ea529..ac9ade3 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -16,7 +16,6 @@ #include #include -#include "es2.h" #include "greybus.h" #include "greybus_protocols.h" @@ -74,6 +73,17 @@ struct gb_camera_stream_config { * Camera Protocol Operations */ +/* vendor request to control the CSI transmitter */ +#define REQUEST_CSI_TX_CONTROL 0x08 + +struct ap_csi_config_request { + __u8 csi_id; + __u8 clock_mode; + __u8 num_lanes; + __u8 padding; + __le32 bus_freq; +} __packed; + static int gb_camera_configure_streams(struct gb_camera *gcam, unsigned int nstreams, unsigned int flags, @@ -81,7 +91,7 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, { struct gb_camera_configure_streams_request *req; struct gb_camera_configure_streams_response *resp; - struct es2_ap_csi_config csi_cfg; + struct ap_csi_config_request csi_cfg; unsigned int i; size_t req_size; size_t resp_size; @@ -150,21 +160,22 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, } } + memset(&csi_cfg, 0, sizeof(csi_cfg)); + /* Configure the CSI transmitter. Hardcode the parameters for now. */ if (nstreams && !(resp->flags & GB_CAMERA_CONFIGURE_STREAMS_ADJUSTED)) { csi_cfg.csi_id = 1; csi_cfg.clock_mode = 0; csi_cfg.num_lanes = 4; - csi_cfg.bus_freq = 960000000; - - ret = es2_ap_csi_setup(gcam->connection->hd, true, &csi_cfg); + csi_cfg.bus_freq = cpu_to_le32(960000000); + ret = gb_hd_output(gcam->connection->hd, &csi_cfg, + sizeof(csi_cfg), REQUEST_CSI_TX_CONTROL, + false); } else if (nstreams == 0) { csi_cfg.csi_id = 1; - csi_cfg.clock_mode = 0; - csi_cfg.num_lanes = 0; - csi_cfg.bus_freq = 0; - - ret = es2_ap_csi_setup(gcam->connection->hd, false, &csi_cfg); + ret = gb_hd_output(gcam->connection->hd, &csi_cfg, + sizeof(csi_cfg), REQUEST_CSI_TX_CONTROL, + false); } if (ret < 0) diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index af5d7496..1b5487f 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -13,7 +13,6 @@ #include #include -#include "es2.h" #include "greybus.h" #include "kernel_ver.h" #include "connection.h" @@ -134,14 +133,6 @@ struct cport_to_ep { __u8 endpoint_out; }; -struct es2_ap_csi_config_request { - __u8 csi_id; - __u8 clock_mode; - __u8 num_lanes; - __u8 padding; - __le32 bus_freq; -} __packed; - static inline struct es2_ap_dev *hd_to_es2(struct gb_host_device *hd) { return (struct es2_ap_dev *)&hd->hd_priv; @@ -220,38 +211,87 @@ static int unmap_cport(struct es2_ap_dev *es2, u16 cport_id) } #endif -int es2_ap_csi_setup(struct gb_host_device *hd, bool start, - struct es2_ap_csi_config *cfg) +static int output_sync(struct es2_ap_dev *es2, void *req, u16 size, u8 cmd) { - struct es2_ap_csi_config_request *cfg_req; - struct es2_ap_dev *es2 = hd_to_es2(hd); struct usb_device *udev = es2->usb_dev; + u8 *data; int retval; - cfg_req = kzalloc(sizeof(*cfg_req), GFP_KERNEL); - if (!cfg_req) + data = kmalloc(size, GFP_KERNEL); + if (!data) return -ENOMEM; - - cfg_req->csi_id = cfg->csi_id; - - if (start) { - cfg_req->clock_mode = cfg->clock_mode; - cfg_req->num_lanes = cfg->num_lanes; - cfg_req->bus_freq = cpu_to_le32(cfg->bus_freq); - } + memcpy(data, req, size); retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - REQUEST_CSI_TX_CONTROL, + cmd, USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_INTERFACE, 0, 0, cfg_req, - sizeof(*cfg_req), ES2_TIMEOUT); + USB_RECIP_INTERFACE, + 0, 0, data, size, ES2_TIMEOUT); if (retval < 0) - dev_err(&udev->dev, "failed to setup csi: %d\n", retval); + dev_err(&udev->dev, "%s: return error %d\n", __func__, retval); + else + retval = 0; - kfree(cfg_req); + kfree(data); return retval; } -EXPORT_SYMBOL_GPL(es2_ap_csi_setup); + +static void ap_urb_complete(struct urb *urb) +{ + struct usb_ctrlrequest *dr = urb->context; + + kfree(dr); + usb_free_urb(urb); +} + +static int output_async(struct es2_ap_dev *es2, void *req, u16 size, u8 cmd) +{ + struct usb_device *udev = es2->usb_dev; + struct urb *urb; + struct usb_ctrlrequest *dr; + u8 *buf; + int retval; + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!urb) + return -ENOMEM; + + dr = kmalloc(sizeof(*dr) + size, GFP_ATOMIC); + if (!dr) { + usb_free_urb(urb); + return -ENOMEM; + } + + buf = (u8 *)dr + sizeof(*dr); + memcpy(buf, req, size); + + dr->bRequest = cmd; + dr->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE; + dr->wValue = 0; + dr->wIndex = 0; + dr->wLength = cpu_to_le16(size); + + usb_fill_control_urb(urb, udev, usb_sndctrlpipe(udev, 0), + (unsigned char *)dr, buf, size, + ap_urb_complete, dr); + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) { + usb_free_urb(urb); + kfree(dr); + } + return retval; +} + +static int output(struct gb_host_device *hd, void *req, u16 size, u8 cmd, + bool async) +{ + struct es2_ap_dev *es2 = hd_to_es2(hd); + + if (async) + return output_async(es2, req, size, cmd); + + return output_sync(es2, req, size, cmd); +} static int es2_cport_in_enable(struct es2_ap_dev *es2, struct es2_cport_in *cport_in) @@ -560,6 +600,7 @@ static struct gb_hd_driver es2_driver = { .cport_enable = cport_enable, .latency_tag_enable = latency_tag_enable, .latency_tag_disable = latency_tag_disable, + .output = output, }; /* Common function to report consistent warnings based on URB status */ diff --git a/drivers/staging/greybus/es2.h b/drivers/staging/greybus/es2.h deleted file mode 100644 index ea29770..0000000 --- a/drivers/staging/greybus/es2.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Greybus "AP" USB driver for "ES2" controller chips - * - * Copyright 2015 Google Inc. - * Copyright 2015 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#ifndef __ES2_H -#define __ES2_H - -#include - -struct gb_host_device; - -struct es2_ap_csi_config { - u8 csi_id; - u8 clock_mode; - u8 num_lanes; - u32 bus_freq; -}; - -int es2_ap_csi_setup(struct gb_host_device *hd, bool start, - struct es2_ap_csi_config *cfg); - -#endif /* __ES2_H */ diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index bff6861..b11a636 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -17,6 +17,15 @@ static struct ida gb_hd_bus_id_map; +int gb_hd_output(struct gb_host_device *hd, void *req, u16 size, u8 cmd, + bool async) +{ + if (!hd || !hd->driver || !hd->driver->output) + return -EINVAL; + return hd->driver->output(hd, req, size, cmd, async); +} +EXPORT_SYMBOL_GPL(gb_hd_output); + static void gb_hd_release(struct device *dev) { struct gb_host_device *hd = to_gb_host_device(dev); diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h index d828129..e11359b 100644 --- a/drivers/staging/greybus/hd.h +++ b/drivers/staging/greybus/hd.h @@ -23,6 +23,8 @@ struct gb_hd_driver { void (*message_cancel)(struct gb_message *message); int (*latency_tag_enable)(struct gb_host_device *hd, u16 cport_id); int (*latency_tag_disable)(struct gb_host_device *hd, u16 cport_id); + int (*output)(struct gb_host_device *hd, void *req, u16 size, u8 cmd, + bool async); }; struct gb_host_device { @@ -53,6 +55,8 @@ struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, int gb_hd_add(struct gb_host_device *hd); void gb_hd_del(struct gb_host_device *hd); void gb_hd_put(struct gb_host_device *hd); +int gb_hd_output(struct gb_host_device *hd, void *req, u16 size, u8 cmd, + bool in_irq); int gb_hd_init(void); void gb_hd_exit(void); -- cgit v0.10.2 From e5273381041fc75215fb50661db39d2f8ed5544e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 31 Dec 2015 11:14:33 -0800 Subject: greybus: APBridge: move APBridge request protocol to a common .h file This moves all of the APBridge request protocol commands that are currently used to a common .h file for everyone to be able to use them in the future, where needed. Signed-off-by: Greg Kroah-Hartman Tested-by: Mark Greer Reviewed-by: Johan Hovold diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index ac9ade3..783a435 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -73,9 +73,6 @@ struct gb_camera_stream_config { * Camera Protocol Operations */ -/* vendor request to control the CSI transmitter */ -#define REQUEST_CSI_TX_CONTROL 0x08 - struct ap_csi_config_request { __u8 csi_id; __u8 clock_mode; @@ -169,13 +166,13 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, csi_cfg.num_lanes = 4; csi_cfg.bus_freq = cpu_to_le32(960000000); ret = gb_hd_output(gcam->connection->hd, &csi_cfg, - sizeof(csi_cfg), REQUEST_CSI_TX_CONTROL, - false); + sizeof(csi_cfg), + GB_APB_REQUEST_CSI_TX_CONTROL, false); } else if (nstreams == 0) { csi_cfg.csi_id = 1; ret = gb_hd_output(gcam->connection->hd, &csi_cfg, - sizeof(csi_cfg), REQUEST_CSI_TX_CONTROL, - false); + sizeof(csi_cfg), + GB_APB_REQUEST_CSI_TX_CONTROL, false); } if (ret < 0) diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 1b5487f..e39bd58 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -44,25 +44,6 @@ MODULE_DEVICE_TABLE(usb, id_table); */ #define NUM_CPORT_OUT_URB (8 * NUM_BULKS) -/* vendor request APB1 log */ -#define REQUEST_LOG 0x02 - -/* vendor request to map a cport to bulk in and bulk out endpoints */ -#define REQUEST_EP_MAPPING 0x03 - -/* vendor request to get the number of cports available */ -#define REQUEST_CPORT_COUNT 0x04 - -/* vendor request to reset a cport state */ -#define REQUEST_RESET_CPORT 0x05 - -/* vendor request to time the latency of messages on a given cport */ -#define REQUEST_LATENCY_TAG_EN 0x06 -#define REQUEST_LATENCY_TAG_DIS 0x07 - -/* vendor request to control the CSI transmitter */ -#define REQUEST_CSI_TX_CONTROL 0x08 - /* * @endpoint: bulk in endpoint for CPort data * @urb: array of urbs for the CPort in messages @@ -191,7 +172,7 @@ static int map_cport_to_ep(struct es2_ap_dev *es2, retval = usb_control_msg(es2->usb_dev, usb_sndctrlpipe(es2->usb_dev, 0), - REQUEST_EP_MAPPING, + GB_APB_REQUEST_EP_MAPPING, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0x00, 0x00, (char *)cport_to_ep, @@ -521,7 +502,7 @@ static int cport_reset(struct gb_host_device *hd, u16 cport_id) int retval; retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - REQUEST_RESET_CPORT, + GB_APB_REQUEST_RESET_CPORT, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, cport_id, 0, NULL, 0, ES2_TIMEOUT); @@ -559,7 +540,7 @@ static int latency_tag_enable(struct gb_host_device *hd, u16 cport_id) } retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - REQUEST_LATENCY_TAG_EN, + GB_APB_REQUEST_LATENCY_TAG_EN, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, cport_id, 0, NULL, 0, ES2_TIMEOUT); @@ -582,7 +563,7 @@ static int latency_tag_disable(struct gb_host_device *hd, u16 cport_id) } retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - REQUEST_LATENCY_TAG_DIS, + GB_APB_REQUEST_LATENCY_TAG_DIS, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, cport_id, 0, NULL, 0, ES2_TIMEOUT); @@ -756,7 +737,7 @@ static void apb_log_get(struct es2_ap_dev *es2, char *buf) do { retval = usb_control_msg(es2->usb_dev, usb_rcvctrlpipe(es2->usb_dev, 0), - REQUEST_LOG, + GB_APB_REQUEST_LOG, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0x00, 0x00, buf, @@ -885,7 +866,7 @@ static int apb_get_cport_count(struct usb_device *udev) return -ENOMEM; retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - REQUEST_CPORT_COUNT, + GB_APB_REQUEST_CPORT_COUNT, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0, 0, cport_count, sizeof(*cport_count), ES2_TIMEOUT); diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 67f260b..dfa3d29 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -154,6 +154,28 @@ struct gb_control_interface_version_response { } __packed; +/* APBridge protocol */ + +/* request APB1 log */ +#define GB_APB_REQUEST_LOG 0x02 + +/* request to map a cport to bulk in and bulk out endpoints */ +#define GB_APB_REQUEST_EP_MAPPING 0x03 + +/* request to get the number of cports available */ +#define GB_APB_REQUEST_CPORT_COUNT 0x04 + +/* request to reset a cport state */ +#define GB_APB_REQUEST_RESET_CPORT 0x05 + +/* request to time the latency of messages on a given cport */ +#define GB_APB_REQUEST_LATENCY_TAG_EN 0x06 +#define GB_APB_REQUEST_LATENCY_TAG_DIS 0x07 + +/* request to control the CSI transmitter */ +#define GB_APB_REQUEST_CSI_TX_CONTROL 0x08 + + /* Firmware Protocol */ /* Version of the Greybus firmware protocol we support */ -- cgit v0.10.2 From adb57cff54dd4418f4d5b17f03a976dfdc670226 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Tue, 12 Jan 2016 14:38:21 +0000 Subject: greybus: power_supply: fix check for configured supply The correct check for if the power supply is ready to receive event is wrong and it should check for the registered flag. Signed-off-by: Rui Miguel Silva Reported-by: Johan Hovold Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c index d985e13..2dc193a 100644 --- a/drivers/staging/greybus/power_supply.c +++ b/drivers/staging/greybus/power_supply.c @@ -697,7 +697,8 @@ static int gb_power_supply_event_recv(u8 type, struct gb_operation *op) payload = request->payload; psy_id = payload->psy_id; mutex_lock(&supplies->supplies_lock); - if (psy_id >= supplies->supplies_count || !&supplies->supply[psy_id]) { + if (psy_id >= supplies->supplies_count || + !supplies->supply[psy_id].registered) { dev_err(&connection->bundle->dev, "Event received for unconfigured power_supply id: %d\n", psy_id); -- cgit v0.10.2 From c5d55fb3596db4064491e7e5db6df8bf8f046078 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Mon, 11 Jan 2016 13:46:31 +0000 Subject: greybus: svc: add interface eject operation Add a new svc operation which will be used to send a request to eject a given interface. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman Reviewed-by: Jeffrey Carlyle diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index dfa3d29..2ffe07c 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -760,6 +760,7 @@ struct gb_spi_transfer_response { #define GB_SVC_TYPE_ROUTE_CREATE 0x0b #define GB_SVC_TYPE_ROUTE_DESTROY 0x0c #define GB_SVC_TYPE_INTF_SET_PWRM 0x10 +#define GB_SVC_TYPE_INTF_EJECT 0x11 /* * SVC version request/response has the same payload as @@ -801,6 +802,12 @@ struct gb_svc_intf_reset_request { } __packed; /* interface reset response has no payload */ +#define GB_SVC_EJECT_TIME 9000 +struct gb_svc_intf_eject_request { + __u8 intf_id; +} __packed; +/* interface eject response has no payload */ + struct gb_svc_conn_create_request { __u8 intf1_id; __le16 cport1_id; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index c4c3bb5..ef10b67 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -69,6 +69,23 @@ int gb_svc_intf_reset(struct gb_svc *svc, u8 intf_id) } EXPORT_SYMBOL_GPL(gb_svc_intf_reset); +int gb_svc_intf_eject(struct gb_svc *svc, u8 intf_id) +{ + struct gb_svc_intf_eject_request request; + + request.intf_id = intf_id; + + /* + * The pulse width for module release in svc is long so we need to + * increase the timeout so the operation will not return to soon. + */ + return gb_operation_sync_timeout(svc->connection, + GB_SVC_TYPE_INTF_EJECT, &request, + sizeof(request), NULL, 0, + GB_SVC_EJECT_TIME); +} +EXPORT_SYMBOL_GPL(gb_svc_intf_eject); + int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, u32 *value) { diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index 0ebbed9..8567615 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -40,6 +40,7 @@ int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id, bool boot_over_unipro); void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id); +int gb_svc_intf_eject(struct gb_svc *svc, u8 intf_id); int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, u32 *value); int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, -- cgit v0.10.2 From 2c92bd5235ac72aa659150ebac309dd4f1c01079 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Mon, 11 Jan 2016 13:46:33 +0000 Subject: greybus: svc: add intf_eject attribute Add a new write-only svc attribute to send an eject request to the svc giving the interface number. So, doing: echo 3 > /sys/bus/greybus/devices/1-svc/intf_eject will force eject the module on interface 3 (module slot 1 on EVT1). This can take some seconds as the pulse width for module release is large. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman Reviewed-by: Jeffrey Carlyle diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 9ce36dd..1550b7f 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -142,6 +142,14 @@ Description: defined by the Endo layout scheme, documented in the ARA Module Developer Kit. +What: /sys/bus/greybus/device/N-svc/intf_eject +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + Write the number of the interface that you wish to + forcibly eject from the system. + What: /sys/bus/greybus/device/N-svc/unique_id Date: October 2015 KernelVersion: 4.XX diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index ef10b67..be62d30 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -40,9 +40,38 @@ static ssize_t ap_intf_id_show(struct device *dev, } static DEVICE_ATTR_RO(ap_intf_id); + +// FIXME +// This is a hack, we need to do this "right" and clean the interface up +// properly, not just forcibly yank the thing out of the system and hope for the +// best. But for now, people want their modules to come out without having to +// throw the thing to the ground or get out a screwdriver. +static ssize_t intf_eject_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t len) +{ + struct gb_svc *svc = to_gb_svc(dev); + unsigned short intf_id; + int ret; + + ret = kstrtou16(buf, 10, &intf_id); + if (ret < 0) + return ret; + + dev_warn(dev, "Forcibly trying to eject interface %d\n", intf_id); + + ret = gb_svc_intf_eject(svc, intf_id); + if (ret < 0) + return ret; + + return len; +} +static DEVICE_ATTR_WO(intf_eject); + static struct attribute *svc_attrs[] = { &dev_attr_endo_id.attr, &dev_attr_ap_intf_id.attr, + &dev_attr_intf_eject.attr, NULL, }; ATTRIBUTE_GROUPS(svc); -- cgit v0.10.2 From 4d0bee11253ba98c4a9c9ebb6df19c3185fe1fd8 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 8 Jan 2016 20:13:45 +0100 Subject: greybus: connection: fix connection-state handling Set connection state to ENABLE before sending the control connected message, and set state DISABLE after sending the control disconnected event. Remove the now unused ERROR connection state. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index b356ee0..1cb3314 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -403,15 +403,14 @@ int gb_connection_init(struct gb_connection *connection) if (ret) goto err_hd_cport_disable; - ret = gb_connection_control_connected(connection); - if (ret) - goto err_svc_destroy; - - /* Need to enable the connection to initialize it */ spin_lock_irq(&connection->lock); connection->state = GB_CONNECTION_STATE_ENABLED; spin_unlock_irq(&connection->lock); + ret = gb_connection_control_connected(connection); + if (ret) + goto err_svc_destroy; + ret = gb_connection_protocol_get_version(connection); if (ret) goto err_disconnect; @@ -423,11 +422,11 @@ int gb_connection_init(struct gb_connection *connection) return 0; err_disconnect: + gb_connection_control_disconnected(connection); + spin_lock_irq(&connection->lock); - connection->state = GB_CONNECTION_STATE_ERROR; + connection->state = GB_CONNECTION_STATE_DISABLED; spin_unlock_irq(&connection->lock); - - gb_connection_control_disconnected(connection); err_svc_destroy: gb_connection_svc_connection_destroy(connection); err_hd_cport_disable: @@ -451,7 +450,13 @@ void gb_connection_exit(struct gb_connection *connection) gb_connection_cancel_operations(connection, -ESHUTDOWN); connection->protocol->connection_exit(connection); + gb_connection_control_disconnected(connection); + + spin_lock_irq(&connection->lock); + connection->state = GB_CONNECTION_STATE_DISABLED; + spin_unlock_irq(&connection->lock); + gb_connection_svc_connection_destroy(connection); gb_connection_hd_cport_disable(connection); gb_connection_unbind_protocol(connection); diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index b795b44..ef31c8d 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -17,8 +17,7 @@ enum gb_connection_state { GB_CONNECTION_STATE_INVALID = 0, GB_CONNECTION_STATE_DISABLED = 1, GB_CONNECTION_STATE_ENABLED = 2, - GB_CONNECTION_STATE_ERROR = 3, - GB_CONNECTION_STATE_DESTROYING = 4, + GB_CONNECTION_STATE_DESTROYING = 3, }; struct gb_connection { -- cgit v0.10.2 From 3ea6a81568f5902ff59ada61b073d8d4a6df5fbf Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 8 Jan 2016 20:13:46 +0100 Subject: greybus: connection: refactor connection enable and disable Refactor connection enable and disable. This is a step towards removing the legacy-protocol handling from core. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 1cb3314..6295d28 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -387,17 +387,13 @@ static int gb_connection_protocol_get_version(struct gb_connection *connection) return 0; } -int gb_connection_init(struct gb_connection *connection) +int gb_connection_enable(struct gb_connection *connection) { int ret; - ret = gb_connection_bind_protocol(connection); - if (ret) - return ret; - ret = gb_connection_hd_cport_enable(connection); if (ret) - goto err_unbind_protocol; + return ret; ret = gb_connection_svc_connection_create(connection); if (ret) @@ -411,26 +407,58 @@ int gb_connection_init(struct gb_connection *connection) if (ret) goto err_svc_destroy; - ret = gb_connection_protocol_get_version(connection); - if (ret) - goto err_disconnect; + return 0; - ret = connection->protocol->connection_init(connection); - if (ret) - goto err_disconnect; +err_svc_destroy: + spin_lock_irq(&connection->lock); + connection->state = GB_CONNECTION_STATE_DISABLED; + spin_unlock_irq(&connection->lock); - return 0; + gb_connection_svc_connection_destroy(connection); +err_hd_cport_disable: + gb_connection_hd_cport_disable(connection); + + return ret; +} +EXPORT_SYMBOL_GPL(gb_connection_enable); -err_disconnect: +void gb_connection_disable(struct gb_connection *connection) +{ gb_connection_control_disconnected(connection); spin_lock_irq(&connection->lock); connection->state = GB_CONNECTION_STATE_DISABLED; spin_unlock_irq(&connection->lock); -err_svc_destroy: + gb_connection_svc_connection_destroy(connection); -err_hd_cport_disable: gb_connection_hd_cport_disable(connection); +} +EXPORT_SYMBOL_GPL(gb_connection_disable); + +int gb_connection_init(struct gb_connection *connection) +{ + int ret; + + ret = gb_connection_bind_protocol(connection); + if (ret) + return ret; + + ret = gb_connection_enable(connection); + if (ret) + goto err_unbind_protocol; + + ret = gb_connection_protocol_get_version(connection); + if (ret) + goto err_disable; + + ret = connection->protocol->connection_init(connection); + if (ret) + goto err_disable; + + return 0; + +err_disable: + gb_connection_disable(connection); err_unbind_protocol: gb_connection_unbind_protocol(connection); @@ -448,17 +476,10 @@ void gb_connection_exit(struct gb_connection *connection) spin_unlock_irq(&connection->lock); gb_connection_cancel_operations(connection, -ESHUTDOWN); - connection->protocol->connection_exit(connection); - gb_connection_control_disconnected(connection); + gb_connection_disable(connection); - spin_lock_irq(&connection->lock); - connection->state = GB_CONNECTION_STATE_DISABLED; - spin_unlock_irq(&connection->lock); - - gb_connection_svc_connection_destroy(connection); - gb_connection_hd_cport_disable(connection); gb_connection_unbind_protocol(connection); } -- cgit v0.10.2 From 14006ab2f53df868f3835ab0706b5ef94c90708f Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Wed, 13 Jan 2016 14:39:55 +0000 Subject: greybus: makefile: add requirement for CONFIG_INPUT To support key events coming from the svc (ara key) it is needed to add the input core as an required config option. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 011e87c..d45a641 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -51,7 +51,7 @@ INSTALL_MOD_PATH ?= /.. PWD := $(shell pwd) # kernel config option that shall be enable -CONFIG_OPTIONS_ENABLE := POWER_SUPPLY PWM SYSFS SPI USB SND_SOC MMC LEDS_CLASS +CONFIG_OPTIONS_ENABLE := POWER_SUPPLY PWM SYSFS SPI USB SND_SOC MMC LEDS_CLASS INPUT # kernel config option that shall be disable CONFIG_OPTIONS_DISABLE := -- cgit v0.10.2 From de141314498b3e52cec7a0e5100e4dd278bde4c7 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 11 Jan 2016 19:24:54 -0800 Subject: greybus: uevent: add GREYBUS_ID to uevent This adds the GREYBUS_ID environment variable to all interface uevents to let userspace know the vendor/product id of the module interface that has been added or removed from the system. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Viresh Kumar diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 6b31155..0e2f99d 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -110,6 +110,10 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) if (intf) { if (add_uevent_var(env, "INTERFACE=%u", intf->interface_id)) return -ENOMEM; + if (add_uevent_var(env, "GREYBUS_ID=%04x/%04x", + (u16)(intf->vendor_id & 0xffff), + (u16)(intf->product_id & 0xffff))) + return -ENOMEM; } if (bundle) { -- cgit v0.10.2 From b827e1137ca9b495f10f3215ed6dd6ff738f0c81 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Tue, 12 Jan 2016 14:35:48 +0000 Subject: greybus: kernel_ver: add handle for lights in 4.5 In v4.5 the LED API is changed related to the set brightness operations, set_sync is removed and the workqueue handling is now done by leds core, so no need for individual drivers to have one. This will be done by removing the SET_SYNC macro and add a new SET_BLOCKING. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index d9bf159..1f8d6a1 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -267,6 +267,15 @@ static inline size_t sg_pcopy_from_buffer(struct scatterlist *sgl, #include #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0) +/* + * New change in LED api, the set_sync operation was renamed to set_blocking and + * the workqueue is now handle by core. So, only one set operation is need. + */ +#undef LED_HAVE_SET_SYNC +#define LED_HAVE_SET_BLOCKING +#endif + #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0) /* * From this version upper it was introduced the possibility to disable led -- cgit v0.10.2 From 9c06c6a2b9ec4cfa78a4cf5ab123bfca0285e083 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Tue, 12 Jan 2016 14:35:49 +0000 Subject: greybus: lights: remove sync operation and work queue In kernel v4.5 there is a change in LED api, which remove the need for individual work queue and rename the set_sync operation to set_blocking. This patch add the handling of this case and avoid compilation failure for this kernel versions. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index 153c4f5..3488bbd 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -30,7 +30,9 @@ struct gb_channel { struct attribute **attrs; struct attribute_group *attr_group; const struct attribute_group **attr_groups; +#ifndef LED_HAVE_SET_BLOCKING struct work_struct work_brightness_set; +#endif struct led_classdev *led; #ifdef LED_HAVE_FLASH struct led_classdev_flash fled; @@ -381,6 +383,7 @@ static int __gb_lights_brightness_set(struct gb_channel *channel) return ret; } +#ifndef LED_HAVE_SET_BLOCKING static void gb_brightness_set_work(struct work_struct *work) { struct gb_channel *channel = container_of(work, struct gb_channel, @@ -412,6 +415,17 @@ static void gb_brightness_set(struct led_classdev *cdev, cdev->brightness = value; schedule_work(&channel->work_brightness_set); } +#else /* LED_HAVE_SET_BLOCKING */ +static int gb_brightness_set(struct led_classdev *cdev, + enum led_brightness value) +{ + struct gb_channel *channel = get_channel_from_cdev(cdev); + + channel->led->brightness = value; + + return __gb_lights_brightness_set(channel); +} +#endif static enum led_brightness gb_brightness_get(struct led_classdev *cdev) @@ -443,12 +457,17 @@ static int gb_blink_set(struct led_classdev *cdev, unsigned long *delay_on, static void gb_lights_led_operations_set(struct gb_channel *channel, struct led_classdev *cdev) { - cdev->brightness_set = gb_brightness_set; cdev->brightness_get = gb_brightness_get; #ifdef LED_HAVE_SET_SYNC cdev->brightness_set_sync = gb_brightness_set_sync; #endif +#ifdef LED_HAVE_SET_BLOCKING + cdev->brightness_set_blocking = gb_brightness_set; +#endif +#ifndef LED_HAVE_SET_BLOCKING + cdev->brightness_set = gb_brightness_set; INIT_WORK(&channel->work_brightness_set, gb_brightness_set_work); +#endif if (channel->flags & GB_LIGHT_CHANNEL_BLINK) cdev->blink_set = gb_blink_set; @@ -986,8 +1005,10 @@ static int gb_lights_light_config(struct gb_lights *glights, u8 id) static void gb_lights_channel_free(struct gb_channel *channel) { +#ifndef LED_HAVE_SET_BLOCKING if (&channel->work_brightness_set) flush_work(&channel->work_brightness_set); +#endif kfree(channel->attrs); kfree(channel->attr_group); kfree(channel->attr_groups); -- cgit v0.10.2 From fc0ddf5adbc2636365b1f8c3c21cd3adf0a8c252 Mon Sep 17 00:00:00 2001 From: Gjorgji Rosikopulos Date: Wed, 13 Jan 2016 21:52:37 +0200 Subject: greybus: camera: HACK: Export GB camera interface Gb camera need to communicate with HOST driver. as temporary solution there will be shared header between gb camera HOST camera. Both need to be in sync since gb drivers are compiled out of the kernel tree. Gb camera register camera operation functions when is created. Currently unregister is not supported. Signed-off-by: Gjorgji Rosikopulos Acked-by: Laurent Pinchart Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gb-camera.h b/drivers/staging/greybus/gb-camera.h new file mode 100644 index 0000000..a182474 --- /dev/null +++ b/drivers/staging/greybus/gb-camera.h @@ -0,0 +1,37 @@ +/* + * Greybus Camera protocol driver. + * + * Copyright 2015 Google Inc. + * + * Released under the GPLv2 only. + */ +#ifndef __GB_CAMERA_H +#define __GB_CAMERA_H + +#include + +struct gb_camera_stream { + unsigned int width; + unsigned int height; + enum v4l2_mbus_pixelcode pixel_code; + unsigned int vc; + unsigned int dt[2]; + unsigned int max_size; +}; + +struct gb_camera_ops { + ssize_t (*capabilities)(void *priv, char *buf, size_t len); + int (*configure_streams)(void *priv, unsigned int nstreams, + struct gb_camera_stream *streams); + int (*capture)(void *priv, u32 request_id, + unsigned int streams, unsigned int num_frames, + size_t settings_size, const void *settings); + int (*flush)(void *priv, u32 *request_id); +}; + +#define gb_camera_call(f, p, op, args...) \ + (((f)->op) ? (f)->op(p, ##args) : -ENOIOCTLCMD) + +int gb_camera_register(struct gb_camera_ops *ops, void *priv); + +#endif /* __GB_CAMERA_H */ -- cgit v0.10.2 From 3a8dba4e57d11965fa8f649753dc1507dd8331eb Mon Sep 17 00:00:00 2001 From: Gjorgji Rosikopulos Date: Wed, 13 Jan 2016 21:52:38 +0200 Subject: greybus: camera: HACK: Register gb camera to the HOST camera This change implements gb camera interface and register gb camera to the HOST driver. This implementation need to be reworked after the demo. Tested with db3 with two camera modules. Signed-off-by: Gjorgji Rosikopulos Acked-by: Laurent Pinchart Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 783a435..a69797b 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -16,6 +16,7 @@ #include #include +#include "gb-camera.h" #include "greybus.h" #include "greybus_protocols.h" @@ -57,6 +58,31 @@ struct gb_camera_stream_config { unsigned int max_size; }; +struct gb_camera_fmt_map { + enum v4l2_mbus_pixelcode mbus_code; + unsigned int gb_format; +}; + +/* GB format to media code map */ +static const struct gb_camera_fmt_map mbus_to_gbus_format[] = { + { + .mbus_code = V4L2_MBUS_FMT_UYVY8_1X16, + .gb_format = 0x01, + }, + { + .mbus_code = V4L2_MBUS_FMT_YUYV8_1_5X8, + .gb_format = 0x16, + }, + { + .mbus_code = V4L2_MBUS_FMT_YVYU8_1_5X8, + .gb_format = 0x17, + }, + { + .mbus_code = V4L2_MBUS_FMT_JPEG_1X8, + .gb_format = 0x40, + } +}; + #define ES2_APB_CDSI0_CPORT 16 #define ES2_APB_CDSI1_CPORT 17 @@ -261,6 +287,97 @@ static int gb_camera_event_recv(u8 type, struct gb_operation *op) } /* ----------------------------------------------------------------------------- + * Interface with HOST ara camera. + */ +static unsigned int gb_camera_mbus_to_gb(enum v4l2_mbus_pixelcode mbus_code) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(mbus_to_gbus_format); i++) { + if (mbus_to_gbus_format[i].mbus_code == mbus_code) + return mbus_to_gbus_format[i].gb_format; + } + return mbus_to_gbus_format[0].gb_format; +} + +static enum v4l2_mbus_pixelcode gb_camera_gb_to_mbus(u16 gb_fmt) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(mbus_to_gbus_format); i++) { + if (mbus_to_gbus_format[i].gb_format == gb_fmt) + return mbus_to_gbus_format[i].mbus_code; + } + return mbus_to_gbus_format[0].mbus_code; +} + +static int gb_camera_op_configure_streams(void *priv, unsigned int nstreams, + struct gb_camera_stream *streams) +{ + struct gb_camera *gcam = priv; + struct gb_camera_stream_config *gb_streams; + unsigned int i; + int ret; + + if (nstreams > GB_CAMERA_MAX_STREAMS) + return -EINVAL; + + gb_streams = kzalloc(nstreams * sizeof(*gb_streams), GFP_KERNEL); + if (!gb_streams) + return -ENOMEM; + + for (i = 0; i < nstreams; i++) { + gb_streams[i].width = streams[i].width; + gb_streams[i].height = streams[i].height; + gb_streams[i].format = + gb_camera_mbus_to_gb(streams[i].pixel_code); + } + + ret = gb_camera_configure_streams(gcam, nstreams, 0, gb_streams); + if (ret < 0) + goto done; + + for (i = 0; i < nstreams; i++) { + streams[i].width = gb_streams[i].width; + streams[i].height = gb_streams[i].height; + streams[i].vc = gb_streams[i].vc; + streams[i].dt[0] = gb_streams[i].dt[0]; + streams[i].dt[1] = gb_streams[i].dt[1]; + streams[i].max_size = gb_streams[i].max_size; + streams[i].pixel_code = + gb_camera_gb_to_mbus(gb_streams[i].format); + } + +done: + kfree(gb_streams); + return ret; +} + +static int gb_camera_op_capture(void *priv, u32 request_id, + unsigned int streams, unsigned int num_frames, + size_t settings_size, const void *settings) +{ + return gb_camera_capture(priv, request_id, streams, num_frames, + settings_size, settings); +} + +static int gb_camera_op_flush(void *priv, u32 *request_id) +{ + return gb_camera_flush(priv, request_id); +} + +struct gb_camera_ops gb_cam_ops = { + .configure_streams = gb_camera_op_configure_streams, + .capture = gb_camera_op_capture, + .flush = gb_camera_op_flush, +}; + +static int gb_camera_register_intf_ops(struct gb_camera *gcam) +{ + return gb_camera_register(&gb_cam_ops, gcam); +} + +/* ----------------------------------------------------------------------------- * DebugFS */ static ssize_t gb_camera_debugfs_capabilities(struct gb_camera *gcam, @@ -646,6 +763,10 @@ static int gb_camera_connection_init(struct gb_connection *connection) if (ret < 0) goto error; + ret = gb_camera_register_intf_ops(gcam); + if (ret < 0) + goto error; + return 0; error: -- cgit v0.10.2 From aa187d33129ba102756600aa27f6e7992a6c814a Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Thu, 14 Jan 2016 02:06:47 +0530 Subject: greybus: arche-apb-ctrl: Enable the clocks after regulator enable It makes more sense to enable the clock after power is enabled to the device, so move clock enable code after regulator_enable and setting up BOOT_RET pin. Signed-off-by: Vaibhav Hiremath Tested-by: Michael Scott Reviewed-by: Laurent Pinchart Tested-by: Laurent Pinchart Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index 65b1e9a..d073543 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -82,19 +82,6 @@ static int apb_ctrl_init_seq(struct platform_device *pdev, struct device *dev = &pdev->dev; int ret; - /* On DB3 clock was not mandatory */ - if (gpio_is_valid(apb->clk_en_gpio)) { - ret = devm_gpio_request(dev, apb->clk_en_gpio, "apb_clk_en"); - if (ret) { - dev_warn(dev, "Failed requesting APB clock en gpio %d\n", - apb->clk_en_gpio); - } else { - ret = gpio_direction_output(apb->clk_en_gpio, 1); - if (ret) - dev_warn(dev, "failed to set APB clock en gpio dir:%d\n", - ret); - } - } /* Hold APB in reset state */ ret = devm_gpio_request(dev, apb->resetn_gpio, "apb-reset"); if (ret) { @@ -128,6 +115,7 @@ static int apb_ctrl_init_seq(struct platform_device *pdev, return ret; } } + if (!IS_ERR(apb->vio)) { ret = regulator_enable(apb->vio); if (ret) { @@ -144,7 +132,22 @@ static int apb_ctrl_init_seq(struct platform_device *pdev, goto out_vio_disable; } gpio_set_value(apb->boot_ret_gpio, 0); - udelay(50); + + /* On DB3 clock was not mandatory */ + if (gpio_is_valid(apb->clk_en_gpio)) { + ret = devm_gpio_request(dev, apb->clk_en_gpio, "apb_clk_en"); + if (ret) { + dev_warn(dev, "Failed requesting APB clock en gpio %d\n", + apb->clk_en_gpio); + } else { + ret = gpio_direction_output(apb->clk_en_gpio, 1); + if (ret) + dev_warn(dev, "failed to set APB clock en gpio dir:%d\n", + ret); + } + } + + usleep_range(100, 200); return 0; -- cgit v0.10.2 From fd8f9e12e2a3bb945959cd294768b265fb97480b Mon Sep 17 00:00:00 2001 From: Mark Greer Date: Wed, 13 Jan 2016 14:07:44 -0700 Subject: greybus: audio: Use underscore in file name For consistency with most other files in the Greybus repository, change 'audio-codec.c' to use an underscore instead of a hyphen in its name. Signed-off-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index d45a641..fb0e023 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -29,7 +29,7 @@ gb-raw-y := raw.o gb-hid-y := hid.o gb-es2-y := es2.o gb-arche-y := arche-platform.o arche-apb-ctrl.o -gb-audio-codec-y := audio-codec.o +gb-audio-codec-y := audio_codec.o gb-camera-y := camera.o obj-m += greybus.o diff --git a/drivers/staging/greybus/audio-codec.c b/drivers/staging/greybus/audio-codec.c deleted file mode 100644 index 2bc2309..0000000 --- a/drivers/staging/greybus/audio-codec.c +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Greybus audio driver - * Copyright 2015 Google Inc. - * Copyright 2015 Linaro Ltd. - * - * Released under the GPLv2 only. - */ -#include - -#include "audio.h" - -static int gbcodec_event_spk(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - /* Ensure GB speaker is connected */ - - return 0; -} - -static int gbcodec_event_hp(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - /* Ensure GB module supports jack slot */ - - return 0; -} - -static int gbcodec_event_int_mic(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - /* Ensure GB module supports jack slot */ - - return 0; -} - -static const struct snd_kcontrol_new gbcodec_snd_controls[] = { - SOC_DOUBLE("Playback Mute", GBCODEC_MUTE_REG, 0, 1, 1, 1), - SOC_DOUBLE("Capture Mute", GBCODEC_MUTE_REG, 4, 5, 1, 1), - SOC_DOUBLE_R("Playback Volume", GBCODEC_PB_LVOL_REG, - GBCODEC_PB_RVOL_REG, 0, 127, 0), - SOC_DOUBLE_R("Capture Volume", GBCODEC_CAP_LVOL_REG, - GBCODEC_CAP_RVOL_REG, 0, 127, 0), -}; - -static const struct snd_kcontrol_new spk_amp_ctl = - SOC_DAPM_SINGLE("Switch", GBCODEC_CTL_REG, 0, 1, 0); - -static const struct snd_kcontrol_new hp_amp_ctl = - SOC_DAPM_SINGLE("Switch", GBCODEC_CTL_REG, 1, 1, 0); - -static const struct snd_kcontrol_new mic_adc_ctl = - SOC_DAPM_SINGLE("Switch", GBCODEC_CTL_REG, 4, 1, 0); - -/* APB1-GBSPK source */ -static const char * const gbcodec_apb1_src[] = {"Stereo", "Left", "Right"}; - -static const SOC_ENUM_SINGLE_DECL( - gbcodec_apb1_rx_enum, GBCODEC_APB1_MUX_REG, 0, gbcodec_apb1_src); - -static const struct snd_kcontrol_new gbcodec_apb1_rx_mux = - SOC_DAPM_ENUM("APB1 source", gbcodec_apb1_rx_enum); - -static const SOC_ENUM_SINGLE_DECL( - gbcodec_mic_enum, GBCODEC_APB1_MUX_REG, 4, gbcodec_apb1_src); - -static const struct snd_kcontrol_new gbcodec_mic_mux = - SOC_DAPM_ENUM("MIC source", gbcodec_mic_enum); - -static const struct snd_soc_dapm_widget gbcodec_dapm_widgets[] = { - SND_SOC_DAPM_SPK("Spk", gbcodec_event_spk), - SND_SOC_DAPM_SPK("HP", gbcodec_event_hp), - SND_SOC_DAPM_MIC("Int Mic", gbcodec_event_int_mic), - - SND_SOC_DAPM_OUTPUT("SPKOUT"), - SND_SOC_DAPM_OUTPUT("HPOUT"), - - SND_SOC_DAPM_INPUT("MIC"), - SND_SOC_DAPM_INPUT("HSMIC"), - - SND_SOC_DAPM_SWITCH("SPK Amp", SND_SOC_NOPM, 0, 0, &spk_amp_ctl), - SND_SOC_DAPM_SWITCH("HP Amp", SND_SOC_NOPM, 0, 0, &hp_amp_ctl), - SND_SOC_DAPM_SWITCH("MIC ADC", SND_SOC_NOPM, 0, 0, &mic_adc_ctl), - - SND_SOC_DAPM_PGA("SPK DAC", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("HP DAC", SND_SOC_NOPM, 0, 0, NULL, 0), - - SND_SOC_DAPM_MIXER("SPK Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_MIXER("HP Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_MIXER("APB1_TX Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), - - SND_SOC_DAPM_MUX("APB1_RX Mux", SND_SOC_NOPM, 0, 0, - &gbcodec_apb1_rx_mux), - SND_SOC_DAPM_MUX("MIC Mux", SND_SOC_NOPM, 0, 0, &gbcodec_mic_mux), - - SND_SOC_DAPM_AIF_IN("APB1RX", "APBridgeA1 Playback", 0, SND_SOC_NOPM, 0, - 0), - SND_SOC_DAPM_AIF_OUT("APB1TX", "APBridgeA1 Capture", 0, SND_SOC_NOPM, 0, - 0), -}; - -static const struct snd_soc_dapm_route gbcodec_dapm_routes[] = { - /* Playback path */ - {"Spk", NULL, "SPKOUT"}, - {"SPKOUT", NULL, "SPK Amp"}, - {"SPK Amp", "Switch", "SPK DAC"}, - {"SPK DAC", NULL, "SPK Mixer"}, - - {"HP", NULL, "HPOUT"}, - {"HPOUT", NULL, "HP Amp"}, - {"HP Amp", "Switch", "HP DAC"}, - {"HP DAC", NULL, "HP Mixer"}, - - {"SPK Mixer", NULL, "APB1_RX Mux"}, - {"HP Mixer", NULL, "APB1_RX Mux"}, - - {"APB1_RX Mux", "Left", "APB1RX"}, - {"APB1_RX Mux", "Right", "APB1RX"}, - {"APB1_RX Mux", "Stereo", "APB1RX"}, - - /* Capture path */ - {"MIC", NULL, "Int Mic"}, - {"MIC", NULL, "MIC Mux"}, - {"MIC Mux", "Left", "MIC ADC"}, - {"MIC Mux", "Right", "MIC ADC"}, - {"MIC Mux", "Stereo", "MIC ADC"}, - {"MIC ADC", "Switch", "APB1_TX Mixer"}, - {"APB1_TX Mixer", NULL, "APB1TX"} -}; - -static int gbcodec_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - return 0; -} - -static void gbcodec_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ -} - -static int gbcodec_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hwparams, - struct snd_soc_dai *dai) -{ - return 0; -} - -static int gbcodec_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - return 0; -} - -static int gbcodec_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) -{ - return 0; -} - -static int gbcodec_digital_mute(struct snd_soc_dai *dai, int mute) -{ - return 0; -} - -static struct snd_soc_dai_ops gbcodec_dai_ops = { - .startup = gbcodec_startup, - .shutdown = gbcodec_shutdown, - .hw_params = gbcodec_hw_params, - .prepare = gbcodec_prepare, - .set_fmt = gbcodec_set_dai_fmt, - .digital_mute = gbcodec_digital_mute, -}; - -static struct snd_soc_dai_driver gbcodec_dai = { - .playback = { - .stream_name = "APBridgeA1 Playback", - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .capture = { - .stream_name = "APBridgeA1 Capture", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .ops = &gbcodec_dai_ops, -}; - -static int gbcodec_probe(struct snd_soc_codec *codec) -{ - struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec); - - gbcodec->codec = codec; - - return 0; -} - -static int gbcodec_remove(struct snd_soc_codec *codec) -{ - /* Empty function for now */ - return 0; -} - -static int gbcodec_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - int ret = 0; - struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec); - u8 *gbcodec_reg = gbcodec->reg; - - if (reg == SND_SOC_NOPM) - return 0; - - if (reg >= GBCODEC_REG_COUNT) - return 0; - - gbcodec_reg[reg] = value; - dev_dbg(codec->dev, "reg[%d] = 0x%x\n", reg, value); - - return ret; -} - -static unsigned int gbcodec_read(struct snd_soc_codec *codec, - unsigned int reg) -{ - unsigned int val = 0; - - struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec); - u8 *gbcodec_reg = gbcodec->reg; - - if (reg == SND_SOC_NOPM) - return 0; - - if (reg >= GBCODEC_REG_COUNT) - return 0; - - val = gbcodec_reg[reg]; - dev_dbg(codec->dev, "reg[%d] = 0x%x\n", reg, val); - - return val; -} - -static struct snd_soc_codec_driver soc_codec_dev_gbcodec = { - .probe = gbcodec_probe, - .remove = gbcodec_remove, - - .read = gbcodec_read, - .write = gbcodec_write, - - .reg_cache_size = GBCODEC_REG_COUNT, - .reg_cache_default = gbcodec_reg_defaults, - .reg_word_size = 1, - - .idle_bias_off = true, - - .controls = gbcodec_snd_controls, - .num_controls = ARRAY_SIZE(gbcodec_snd_controls), - .dapm_widgets = gbcodec_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(gbcodec_dapm_widgets), - .dapm_routes = gbcodec_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(gbcodec_dapm_routes), -}; - -static int gbaudio_codec_probe(struct platform_device *pdev) -{ - int ret; - struct gbaudio_codec_info *gbcodec; - char dai_name[NAME_SIZE]; - - gbcodec = devm_kzalloc(&pdev->dev, sizeof(struct gbaudio_codec_info), - GFP_KERNEL); - if (!gbcodec) - return -ENOMEM; - platform_set_drvdata(pdev, gbcodec); - - snprintf(dai_name, NAME_SIZE, "%s.%d", "gbcodec_pcm", pdev->id); - gbcodec_dai.name = dai_name; - - ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_gbcodec, - &gbcodec_dai, 1); - if (!ret) - gbcodec->registered = 1; - - return ret; -} - -static const struct of_device_id gbcodec_of_match[] = { - { .compatible = "greybus,codec", }, - {}, -}; - -static int gbaudio_codec_remove(struct platform_device *pdev) -{ - snd_soc_unregister_codec(&pdev->dev); - - return 0; -} - -static struct platform_driver gbaudio_codec_driver = { - .driver = { - .name = "gbaudio-codec", - .owner = THIS_MODULE, - .of_match_table = gbcodec_of_match, - }, - .probe = gbaudio_codec_probe, - .remove = gbaudio_codec_remove, -}; -module_platform_driver(gbaudio_codec_driver); - -MODULE_DESCRIPTION("Greybus Audio virtual codec driver"); -MODULE_AUTHOR("Vaibhav Agarwal "); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:gbaudio-codec"); diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c new file mode 100644 index 0000000..2bc2309 --- /dev/null +++ b/drivers/staging/greybus/audio_codec.c @@ -0,0 +1,315 @@ +/* + * Greybus audio driver + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ +#include + +#include "audio.h" + +static int gbcodec_event_spk(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + /* Ensure GB speaker is connected */ + + return 0; +} + +static int gbcodec_event_hp(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + /* Ensure GB module supports jack slot */ + + return 0; +} + +static int gbcodec_event_int_mic(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + /* Ensure GB module supports jack slot */ + + return 0; +} + +static const struct snd_kcontrol_new gbcodec_snd_controls[] = { + SOC_DOUBLE("Playback Mute", GBCODEC_MUTE_REG, 0, 1, 1, 1), + SOC_DOUBLE("Capture Mute", GBCODEC_MUTE_REG, 4, 5, 1, 1), + SOC_DOUBLE_R("Playback Volume", GBCODEC_PB_LVOL_REG, + GBCODEC_PB_RVOL_REG, 0, 127, 0), + SOC_DOUBLE_R("Capture Volume", GBCODEC_CAP_LVOL_REG, + GBCODEC_CAP_RVOL_REG, 0, 127, 0), +}; + +static const struct snd_kcontrol_new spk_amp_ctl = + SOC_DAPM_SINGLE("Switch", GBCODEC_CTL_REG, 0, 1, 0); + +static const struct snd_kcontrol_new hp_amp_ctl = + SOC_DAPM_SINGLE("Switch", GBCODEC_CTL_REG, 1, 1, 0); + +static const struct snd_kcontrol_new mic_adc_ctl = + SOC_DAPM_SINGLE("Switch", GBCODEC_CTL_REG, 4, 1, 0); + +/* APB1-GBSPK source */ +static const char * const gbcodec_apb1_src[] = {"Stereo", "Left", "Right"}; + +static const SOC_ENUM_SINGLE_DECL( + gbcodec_apb1_rx_enum, GBCODEC_APB1_MUX_REG, 0, gbcodec_apb1_src); + +static const struct snd_kcontrol_new gbcodec_apb1_rx_mux = + SOC_DAPM_ENUM("APB1 source", gbcodec_apb1_rx_enum); + +static const SOC_ENUM_SINGLE_DECL( + gbcodec_mic_enum, GBCODEC_APB1_MUX_REG, 4, gbcodec_apb1_src); + +static const struct snd_kcontrol_new gbcodec_mic_mux = + SOC_DAPM_ENUM("MIC source", gbcodec_mic_enum); + +static const struct snd_soc_dapm_widget gbcodec_dapm_widgets[] = { + SND_SOC_DAPM_SPK("Spk", gbcodec_event_spk), + SND_SOC_DAPM_SPK("HP", gbcodec_event_hp), + SND_SOC_DAPM_MIC("Int Mic", gbcodec_event_int_mic), + + SND_SOC_DAPM_OUTPUT("SPKOUT"), + SND_SOC_DAPM_OUTPUT("HPOUT"), + + SND_SOC_DAPM_INPUT("MIC"), + SND_SOC_DAPM_INPUT("HSMIC"), + + SND_SOC_DAPM_SWITCH("SPK Amp", SND_SOC_NOPM, 0, 0, &spk_amp_ctl), + SND_SOC_DAPM_SWITCH("HP Amp", SND_SOC_NOPM, 0, 0, &hp_amp_ctl), + SND_SOC_DAPM_SWITCH("MIC ADC", SND_SOC_NOPM, 0, 0, &mic_adc_ctl), + + SND_SOC_DAPM_PGA("SPK DAC", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("HP DAC", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_MIXER("SPK Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("HP Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("APB1_TX Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_MUX("APB1_RX Mux", SND_SOC_NOPM, 0, 0, + &gbcodec_apb1_rx_mux), + SND_SOC_DAPM_MUX("MIC Mux", SND_SOC_NOPM, 0, 0, &gbcodec_mic_mux), + + SND_SOC_DAPM_AIF_IN("APB1RX", "APBridgeA1 Playback", 0, SND_SOC_NOPM, 0, + 0), + SND_SOC_DAPM_AIF_OUT("APB1TX", "APBridgeA1 Capture", 0, SND_SOC_NOPM, 0, + 0), +}; + +static const struct snd_soc_dapm_route gbcodec_dapm_routes[] = { + /* Playback path */ + {"Spk", NULL, "SPKOUT"}, + {"SPKOUT", NULL, "SPK Amp"}, + {"SPK Amp", "Switch", "SPK DAC"}, + {"SPK DAC", NULL, "SPK Mixer"}, + + {"HP", NULL, "HPOUT"}, + {"HPOUT", NULL, "HP Amp"}, + {"HP Amp", "Switch", "HP DAC"}, + {"HP DAC", NULL, "HP Mixer"}, + + {"SPK Mixer", NULL, "APB1_RX Mux"}, + {"HP Mixer", NULL, "APB1_RX Mux"}, + + {"APB1_RX Mux", "Left", "APB1RX"}, + {"APB1_RX Mux", "Right", "APB1RX"}, + {"APB1_RX Mux", "Stereo", "APB1RX"}, + + /* Capture path */ + {"MIC", NULL, "Int Mic"}, + {"MIC", NULL, "MIC Mux"}, + {"MIC Mux", "Left", "MIC ADC"}, + {"MIC Mux", "Right", "MIC ADC"}, + {"MIC Mux", "Stereo", "MIC ADC"}, + {"MIC ADC", "Switch", "APB1_TX Mixer"}, + {"APB1_TX Mixer", NULL, "APB1TX"} +}; + +static int gbcodec_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + return 0; +} + +static void gbcodec_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ +} + +static int gbcodec_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hwparams, + struct snd_soc_dai *dai) +{ + return 0; +} + +static int gbcodec_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + return 0; +} + +static int gbcodec_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + return 0; +} + +static int gbcodec_digital_mute(struct snd_soc_dai *dai, int mute) +{ + return 0; +} + +static struct snd_soc_dai_ops gbcodec_dai_ops = { + .startup = gbcodec_startup, + .shutdown = gbcodec_shutdown, + .hw_params = gbcodec_hw_params, + .prepare = gbcodec_prepare, + .set_fmt = gbcodec_set_dai_fmt, + .digital_mute = gbcodec_digital_mute, +}; + +static struct snd_soc_dai_driver gbcodec_dai = { + .playback = { + .stream_name = "APBridgeA1 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .capture = { + .stream_name = "APBridgeA1 Capture", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .ops = &gbcodec_dai_ops, +}; + +static int gbcodec_probe(struct snd_soc_codec *codec) +{ + struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec); + + gbcodec->codec = codec; + + return 0; +} + +static int gbcodec_remove(struct snd_soc_codec *codec) +{ + /* Empty function for now */ + return 0; +} + +static int gbcodec_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value) +{ + int ret = 0; + struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec); + u8 *gbcodec_reg = gbcodec->reg; + + if (reg == SND_SOC_NOPM) + return 0; + + if (reg >= GBCODEC_REG_COUNT) + return 0; + + gbcodec_reg[reg] = value; + dev_dbg(codec->dev, "reg[%d] = 0x%x\n", reg, value); + + return ret; +} + +static unsigned int gbcodec_read(struct snd_soc_codec *codec, + unsigned int reg) +{ + unsigned int val = 0; + + struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec); + u8 *gbcodec_reg = gbcodec->reg; + + if (reg == SND_SOC_NOPM) + return 0; + + if (reg >= GBCODEC_REG_COUNT) + return 0; + + val = gbcodec_reg[reg]; + dev_dbg(codec->dev, "reg[%d] = 0x%x\n", reg, val); + + return val; +} + +static struct snd_soc_codec_driver soc_codec_dev_gbcodec = { + .probe = gbcodec_probe, + .remove = gbcodec_remove, + + .read = gbcodec_read, + .write = gbcodec_write, + + .reg_cache_size = GBCODEC_REG_COUNT, + .reg_cache_default = gbcodec_reg_defaults, + .reg_word_size = 1, + + .idle_bias_off = true, + + .controls = gbcodec_snd_controls, + .num_controls = ARRAY_SIZE(gbcodec_snd_controls), + .dapm_widgets = gbcodec_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(gbcodec_dapm_widgets), + .dapm_routes = gbcodec_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(gbcodec_dapm_routes), +}; + +static int gbaudio_codec_probe(struct platform_device *pdev) +{ + int ret; + struct gbaudio_codec_info *gbcodec; + char dai_name[NAME_SIZE]; + + gbcodec = devm_kzalloc(&pdev->dev, sizeof(struct gbaudio_codec_info), + GFP_KERNEL); + if (!gbcodec) + return -ENOMEM; + platform_set_drvdata(pdev, gbcodec); + + snprintf(dai_name, NAME_SIZE, "%s.%d", "gbcodec_pcm", pdev->id); + gbcodec_dai.name = dai_name; + + ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_gbcodec, + &gbcodec_dai, 1); + if (!ret) + gbcodec->registered = 1; + + return ret; +} + +static const struct of_device_id gbcodec_of_match[] = { + { .compatible = "greybus,codec", }, + {}, +}; + +static int gbaudio_codec_remove(struct platform_device *pdev) +{ + snd_soc_unregister_codec(&pdev->dev); + + return 0; +} + +static struct platform_driver gbaudio_codec_driver = { + .driver = { + .name = "gbaudio-codec", + .owner = THIS_MODULE, + .of_match_table = gbcodec_of_match, + }, + .probe = gbaudio_codec_probe, + .remove = gbaudio_codec_remove, +}; +module_platform_driver(gbaudio_codec_driver); + +MODULE_DESCRIPTION("Greybus Audio virtual codec driver"); +MODULE_AUTHOR("Vaibhav Agarwal "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:gbaudio-codec"); -- cgit v0.10.2 From ba4144afdebf96a3c27c9a03e0c671cf85cc55e9 Mon Sep 17 00:00:00 2001 From: Mark Greer Date: Wed, 13 Jan 2016 14:07:45 -0700 Subject: greybus: audio: Add Audio Device Class Protocol definitions Add the macros and structures for the Greybus Audio Device Class Protocol. Signed-off-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 2ffe07c..1277b74 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -1425,5 +1425,372 @@ struct gb_lights_get_flash_fault_response { #define GB_LIGHTS_FLASH_FAULT_LED_OVER_TEMPERATURE 0x00000080 } __packed; +/* Audio */ + +/* Version of the Greybus audio protocol we support */ +#define GB_AUDIO_VERSION_MAJOR 0x00 +#define GB_AUDIO_VERSION_MINOR 0x01 + +#define GB_AUDIO_TYPE_PROTOCOL_VERSION 0x01 +#define GB_AUDIO_TYPE_GET_TOPOLOGY_SIZE 0x02 +#define GB_AUDIO_TYPE_GET_TOPOLOGY 0x03 +#define GB_AUDIO_TYPE_GET_CONTROL 0x04 +#define GB_AUDIO_TYPE_SET_CONTROL 0x05 +#define GB_AUDIO_TYPE_ENABLE_WIDGET 0x06 +#define GB_AUDIO_TYPE_DISABLE_WIDGET 0x07 +#define GB_AUDIO_TYPE_GET_PCM 0x08 +#define GB_AUDIO_TYPE_SET_PCM 0x09 +#define GB_AUDIO_TYPE_SET_TX_DATA_SIZE 0x0a +#define GB_AUDIO_TYPE_GET_TX_DELAY 0x0b +#define GB_AUDIO_TYPE_ACTIVATE_TX 0x0c +#define GB_AUDIO_TYPE_DEACTIVATE_TX 0x0d +#define GB_AUDIO_TYPE_SET_RX_DATA_SIZE 0x0e +#define GB_AUDIO_TYPE_GET_RX_DELAY 0x0f +#define GB_AUDIO_TYPE_ACTIVATE_RX 0x10 +#define GB_AUDIO_TYPE_DEACTIVATE_RX 0x11 +#define GB_AUDIO_TYPE_JACK_EVENT 0x12 +#define GB_AUDIO_TYPE_BUTTON_EVENT 0x13 +#define GB_AUDIO_TYPE_STREAMING_EVENT 0x14 +#define GB_AUDIO_TYPE_SEND_DATA 0x15 + +/* Module must be able to buffer 10ms of audio data, minimum */ +#define GB_AUDIO_SAMPLE_BUFFER_MIN_US 10000 + +#define GB_AUDIO_PCM_NAME_MAX 32 +#define AUDIO_DAI_NAME_MAX 32 +#define AUDIO_CONTROL_NAME_MAX 32 +#define AUDIO_CTL_ELEM_NAME_MAX 44 +#define AUDIO_ENUM_NAME_MAX 64 +#define AUDIO_WIDGET_NAME_MAX 32 + +/* See SNDRV_PCM_FMTBIT_* in Linux source */ +#define GB_AUDIO_PCM_FMT_S8 BIT(0) +#define GB_AUDIO_PCM_FMT_U8 BIT(1) +#define GB_AUDIO_PCM_FMT_S16_LE BIT(2) +#define GB_AUDIO_PCM_FMT_S16_BE BIT(3) +#define GB_AUDIO_PCM_FMT_U16_LE BIT(4) +#define GB_AUDIO_PCM_FMT_U16_BE BIT(5) +#define GB_AUDIO_PCM_FMT_S24_LE BIT(6) +#define GB_AUDIO_PCM_FMT_S24_BE BIT(7) +#define GB_AUDIO_PCM_FMT_U24_LE BIT(8) +#define GB_AUDIO_PCM_FMT_U24_BE BIT(9) +#define GB_AUDIO_PCM_FMT_S32_LE BIT(10) +#define GB_AUDIO_PCM_FMT_S32_BE BIT(11) +#define GB_AUDIO_PCM_FMT_U32_LE BIT(12) +#define GB_AUDIO_PCM_FMT_U32_BE BIT(13) + +/* See SNDRV_PCM_RATE_* in Linux source */ +#define GB_AUDIO_PCM_RATE_5512 BIT(0) +#define GB_AUDIO_PCM_RATE_8000 BIT(1) +#define GB_AUDIO_PCM_RATE_11025 BIT(2) +#define GB_AUDIO_PCM_RATE_16000 BIT(3) +#define GB_AUDIO_PCM_RATE_22050 BIT(4) +#define GB_AUDIO_PCM_RATE_32000 BIT(5) +#define GB_AUDIO_PCM_RATE_44100 BIT(6) +#define GB_AUDIO_PCM_RATE_48000 BIT(7) +#define GB_AUDIO_PCM_RATE_64000 BIT(8) +#define GB_AUDIO_PCM_RATE_88200 BIT(9) +#define GB_AUDIO_PCM_RATE_96000 BIT(10) +#define GB_AUDIO_PCM_RATE_176400 BIT(11) +#define GB_AUDIO_PCM_RATE_192000 BIT(12) + +#define GB_AUDIO_STREAM_TYPE_CAPTURE 0x1 +#define GB_AUDIO_STREAM_TYPE_PLAYBACK 0x2 + +#define GB_AUDIO_CTL_ELEM_ACCESS_READ BIT(0) +#define GB_AUDIO_CTL_ELEM_ACCESS_WRITE BIT(1) + +/* See SNDRV_CTL_ELEM_TYPE_* in Linux source */ +#define GB_AUDIO_CTL_ELEM_TYPE_BOOLEAN 0x01 +#define GB_AUDIO_CTL_ELEM_TYPE_INTEGER 0x02 +#define GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED 0x03 +#define GB_AUDIO_CTL_ELEM_TYPE_INTEGER64 0x06 + +/* See SNDRV_CTL_ELEM_IFACE_* in Linux source */ +#define GB_AUDIO_CTL_ELEM_IFACE_CARD 0x00 +#define GB_AUDIO_CTL_ELEM_IFACE_HWDEP 0x01 +#define GB_AUDIO_CTL_ELEM_IFACE_MIXER 0x02 +#define GB_AUDIO_CTL_ELEM_IFACE_PCM 0x03 +#define GB_AUDIO_CTL_ELEM_IFACE_RAWMIDI 0x04 +#define GB_AUDIO_CTL_ELEM_IFACE_TIMER 0x05 +#define GB_AUDIO_CTL_ELEM_IFACE_SEQUENCER 0x06 + +/* SNDRV_CTL_ELEM_ACCESS_* in Linux source */ +#define GB_AUDIO_ACCESS_READ BIT(0) +#define GB_AUDIO_ACCESS_WRITE BIT(1) +#define GB_AUDIO_ACCESS_VOLATILE BIT(2) +#define GB_AUDIO_ACCESS_TIMESTAMP BIT(3) +#define GB_AUDIO_ACCESS_TLV_READ BIT(4) +#define GB_AUDIO_ACCESS_TLV_WRITE BIT(5) +#define GB_AUDIO_ACCESS_TLV_COMMAND BIT(6) +#define GB_AUDIO_ACCESS_INACTIVE BIT(7) +#define GB_AUDIO_ACCESS_LOCK BIT(8) +#define GB_AUDIO_ACCESS_OWNER BIT(9) + +/* enum snd_soc_dapm_type */ +#define GB_AUDIO_WIDGET_TYPE_INPUT 0x0 +#define GB_AUDIO_WIDGET_TYPE_OUTPUT 0x1 +#define GB_AUDIO_WIDGET_TYPE_MUX 0x2 +#define GB_AUDIO_WIDGET_TYPE_VIRT_MUX 0x3 +#define GB_AUDIO_WIDGET_TYPE_VALUE_MUX 0x4 +#define GB_AUDIO_WIDGET_TYPE_MIXER 0x5 +#define GB_AUDIO_WIDGET_TYPE_MIXER_NAMED_CTL 0x6 +#define GB_AUDIO_WIDGET_TYPE_PGA 0x7 +#define GB_AUDIO_WIDGET_TYPE_OUT_DRV 0x8 +#define GB_AUDIO_WIDGET_TYPE_ADC 0x9 +#define GB_AUDIO_WIDGET_TYPE_DAC 0xa +#define GB_AUDIO_WIDGET_TYPE_MICBIAS 0xb +#define GB_AUDIO_WIDGET_TYPE_MIC 0xc +#define GB_AUDIO_WIDGET_TYPE_HP 0xd +#define GB_AUDIO_WIDGET_TYPE_SPK 0xe +#define GB_AUDIO_WIDGET_TYPE_LINE 0xf +#define GB_AUDIO_WIDGET_TYPE_SWITCH 0x10 +#define GB_AUDIO_WIDGET_TYPE_VMID 0x11 +#define GB_AUDIO_WIDGET_TYPE_PRE 0x12 +#define GB_AUDIO_WIDGET_TYPE_POST 0x13 +#define GB_AUDIO_WIDGET_TYPE_SUPPLY 0x14 +#define GB_AUDIO_WIDGET_TYPE_REGULATOR_SUPPLY 0x15 +#define GB_AUDIO_WIDGET_TYPE_CLOCK_SUPPLY 0x16 +#define GB_AUDIO_WIDGET_TYPE_AIF_IN 0x17 +#define GB_AUDIO_WIDGET_TYPE_AIF_OUT 0x18 +#define GB_AUDIO_WIDGET_TYPE_SIGGEN 0x19 +#define GB_AUDIO_WIDGET_TYPE_DAI_IN 0x1a +#define GB_AUDIO_WIDGET_TYPE_DAI_OUT 0x1b +#define GB_AUDIO_WIDGET_TYPE_DAI_LINK 0x1c + +#define GB_AUDIO_WIDGET_STATE_DISABLED 0x01 +#define GB_AUDIO_WIDGET_STATE_ENAABLED 0x02 + +#define GB_AUDIO_JACK_EVENT_INSERTION 0x1 +#define GB_AUDIO_JACK_EVENT_REMOVAL 0x2 + +#define GB_AUDIO_BUTTON_EVENT_PRESS 0x1 +#define GB_AUDIO_BUTTON_EVENT_RELEASE 0x2 + +#define GB_AUDIO_STREAMING_EVENT_UNSPECIFIED 0x1 +#define GB_AUDIO_STREAMING_EVENT_HALT 0x2 +#define GB_AUDIO_STREAMING_EVENT_INTERNAL_ERROR 0x3 +#define GB_AUDIO_STREAMING_EVENT_PROTOCOL_ERROR 0x4 +#define GB_AUDIO_STREAMING_EVENT_FAILURE 0x5 +#define GB_AUDIO_STREAMING_EVENT_UNDERRUN 0x6 +#define GB_AUDIO_STREAMING_EVENT_OVERRUN 0x7 +#define GB_AUDIO_STREAMING_EVENT_CLOCKING 0x8 +#define GB_AUDIO_STREAMING_EVENT_DATA_LEN 0x9 + +#define GB_AUDIO_INVALID_INDEX 0xff + +struct gb_audio_pcm { + __u8 stream_name[GB_AUDIO_PCM_NAME_MAX]; + __le32 formats; /* GB_AUDIO_PCM_FMT_* */ + __le32 rates; /* GB_AUDIO_PCM_RATE_* */ + __u8 chan_min; + __u8 chan_max; + __u8 sig_bits; /* number of bits of content */ +} __packed; + +struct gb_audio_dai { + __u8 name[AUDIO_DAI_NAME_MAX]; + __le16 data_cport; + struct gb_audio_pcm capture; + struct gb_audio_pcm playback; +} __packed; + +struct gb_audio_integer { + __le32 min; + __le32 max; + __le32 step; +} __packed; + +struct gb_audio_integer64 { + __le64 min; + __le64 max; + __le64 step; +} __packed; + +struct gb_audio_enumerated { + __le32 items; + __le16 names_length; + __u8 names[0]; +} __packed; + +struct gb_audio_ctl_elem_info { /* See snd_ctl_elem_info in Linux source */ + __u8 type; /* GB_AUDIO_CTL_ELEM_TYPE_* */ + __le16 dimen[4]; + union { + struct gb_audio_integer integer; + struct gb_audio_integer64 integer64; + struct gb_audio_enumerated enumerated; + } value; +} __packed; + +struct gb_audio_ctl_elem_value { /* See snd_ctl_elem_value in Linux source */ + __le64 timestamp; /* XXX needed? */ + union { + __le32 integer_value[2]; /* consider CTL_DOUBLE_xxx */ + __le64 integer64_value[2]; + __le32 enumerated_item[2]; + } value; +} __packed; + +struct gb_audio_control { + __u8 name[AUDIO_CONTROL_NAME_MAX]; + __u8 id; /* 0-63 */ + __u8 iface; /* GB_AUDIO_IFACE_* */ + __le16 data_cport; + __le32 access; /* GB_AUDIO_ACCESS_* */ + __u8 count; /* count of same elements */ + __u8 count_values; /* count of values, max=2 for CTL_DOUBLE_xxx */ + struct gb_audio_ctl_elem_info info; +} __packed; + +struct gb_audio_widget { + __u8 name[AUDIO_WIDGET_NAME_MAX]; + __u8 sname[AUDIO_WIDGET_NAME_MAX]; + __u8 id; + __u8 type; /* GB_AUDIO_WIDGET_TYPE_* */ + __u8 state; /* GB_AUDIO_WIDGET_STATE_* */ + __u8 ncontrols; + struct gb_audio_control ctl[0]; /* 'ncontrols' entries */ +} __packed; + +struct gb_audio_route { + __u8 source_id; /* widget id */ + __u8 destination_id; /* widget id */ + __u8 control_id; /* 0-63 */ + __u8 index; /* Selection within the control */ +} __packed; + +struct gb_audio_topology { + __u8 num_dais; + __u8 num_controls; + __u8 num_widgets; + __u8 num_routes; + __u32 size_dais; + __u32 size_controls; + __u32 size_widgets; + __u32 size_routes; + /* + * struct gb_audio_dai dai[num_dais]; + * struct gb_audio_control controls[num_controls]; + * struct gb_audio_widget widgets[num_widgets]; + * struct gb_audio_route routes[num_routes]; + */ + __u8 data[0]; +} __packed; + +struct gb_audio_get_topology_size_response { + __le16 size; +} __packed; + +struct gb_audio_get_topology_response { + struct gb_audio_topology topology; +} __packed; + +struct gb_audio_get_control_request { + __u8 control_id; + __u8 index; +} __packed; + +struct gb_audio_get_control_response { + struct gb_audio_ctl_elem_value value; +} __packed; + +struct gb_audio_set_control_request { + __u8 control_id; + __u8 index; + struct gb_audio_ctl_elem_value value; +} __packed; + +struct gb_audio_enable_widget_request { + __u8 widget_id; +} __packed; + +struct gb_audio_disable_widget_request { + __u8 widget_id; +} __packed; + +struct gb_audio_get_pcm_request { + __le16 data_cport; +} __packed; + +struct gb_audio_get_pcm_response { + __le32 format; + __le32 rate; + __u8 channels; + __u8 sig_bits; +} __packed; + +struct gb_audio_set_pcm_request { + __le16 data_cport; + __le32 format; + __le32 rate; + __u8 channels; + __u8 sig_bits; +} __packed; + +struct gb_audio_set_tx_data_size_request { + __le16 data_cport; + __le16 size; +} __packed; + +struct gb_audio_get_tx_delay_request { + __le16 data_cport; +} __packed; + +struct gb_audio_get_tx_delay_response { + __le32 delay; +} __packed; + +struct gb_audio_activate_tx_request { + __le16 data_cport; +} __packed; + +struct gb_audio_deactivate_tx_request { + __le16 data_cport; +} __packed; + +struct gb_audio_set_rx_data_size_request { + __le16 data_cport; + __le16 size; +} __packed; + +struct gb_audio_get_rx_delay_request { + __le16 data_cport; +} __packed; + +struct gb_audio_get_rx_delay_response { + __le32 delay; +} __packed; + +struct gb_audio_activate_rx_request { + __le16 data_cport; +} __packed; + +struct gb_audio_deactivate_rx_request { + __le16 data_cport; +} __packed; + +struct gb_audio_jack_event_request { + __u8 widget_id; + __u8 widget_type; + __u8 event; +} __packed; + +struct gb_audio_button_event_request { + __u8 widget_id; + __u8 button_id; + __u8 event; +} __packed; + +struct gb_audio_streaming_event_request { + __le16 data_cport; + __u8 event; +} __packed; + +struct gb_audio_send_data_request { + __le64 timestamp; + __u8 data[0]; +} __packed; + #endif /* __GREYBUS_PROTOCOLS_H */ -- cgit v0.10.2 From 184992e305f1de3a3d5fa446da3a2bc76be7c54a Mon Sep 17 00:00:00 2001 From: Mark Greer Date: Wed, 13 Jan 2016 14:07:46 -0700 Subject: greybus: audio: Add Greybus Audio Device Class Protocol helper routines Add helper routines to make communicating with audio modules easier. Signed-off-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index fb0e023..3010f16 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -30,6 +30,7 @@ gb-hid-y := hid.o gb-es2-y := es2.o gb-arche-y := arche-platform.o arche-apb-ctrl.o gb-audio-codec-y := audio_codec.o +gb-audio-gb-y := audio_gb.o gb-camera-y := camera.o obj-m += greybus.o @@ -44,6 +45,7 @@ obj-m += gb-es2.o obj-m += gb-arche.o obj-m += gb-audio-codec.o obj-m += gb-camera.o +obj-m += gb-audio-gb.o KERNELVER ?= $(shell uname -r) KERNELDIR ?= /lib/modules/$(KERNELVER)/build diff --git a/drivers/staging/greybus/audio.h b/drivers/staging/greybus/audio.h index 5dec00d..c8f798e 100644 --- a/drivers/staging/greybus/audio.h +++ b/drivers/staging/greybus/audio.h @@ -13,6 +13,9 @@ #include +#include "greybus.h" +#include "greybus_protocols.h" + #define NAME_SIZE 32 enum { @@ -82,5 +85,42 @@ struct gbaudio_codec_info { struct mutex lock; }; +extern int gb_audio_gb_get_topology(struct gb_connection *connection, + struct gb_audio_topology **topology); +extern int gb_audio_gb_get_control(struct gb_connection *connection, + uint8_t control_id, uint8_t index, + struct gb_audio_ctl_elem_value *value); +extern int gb_audio_gb_set_control(struct gb_connection *connection, + uint8_t control_id, uint8_t index, + struct gb_audio_ctl_elem_value *value); +extern int gb_audio_gb_enable_widget(struct gb_connection *connection, + uint8_t widget_id); +extern int gb_audio_gb_disable_widget(struct gb_connection *connection, + uint8_t widget_id); +extern int gb_audio_gb_get_pcm(struct gb_connection *connection, + uint16_t data_cport, uint32_t *format, + uint32_t *rate, uint8_t *channels, + uint8_t *sig_bits); +extern int gb_audio_gb_set_pcm(struct gb_connection *connection, + uint16_t data_cport, uint32_t format, + uint32_t rate, uint8_t channels, + uint8_t sig_bits); +extern int gb_audio_gb_set_tx_data_size(struct gb_connection *connection, + uint16_t data_cport, uint16_t size); +extern int gb_audio_gb_get_tx_delay(struct gb_connection *connection, + uint16_t data_cport, uint32_t *delay); +extern int gb_audio_gb_activate_tx(struct gb_connection *connection, + uint16_t data_cport); +extern int gb_audio_gb_deactivate_tx(struct gb_connection *connection, + uint16_t data_cport); +extern int gb_audio_gb_set_rx_data_size(struct gb_connection *connection, + uint16_t data_cport, uint16_t size); +extern int gb_audio_gb_get_rx_delay(struct gb_connection *connection, + uint16_t data_cport, uint32_t *delay); +extern int gb_audio_gb_activate_rx(struct gb_connection *connection, + uint16_t data_cport); +extern int gb_audio_gb_deactivate_rx(struct gb_connection *connection, + uint16_t data_cport); + #endif /* __KERNEL__ */ #endif /* __LINUX_GBAUDIO_H */ diff --git a/drivers/staging/greybus/audio_gb.c b/drivers/staging/greybus/audio_gb.c new file mode 100644 index 0000000..08bfdeb --- /dev/null +++ b/drivers/staging/greybus/audio_gb.c @@ -0,0 +1,267 @@ +/* + * Greybus Audio Device Class Protocol helpers + * + * Copyright 2015-2016 Google Inc. + * + * Released under the GPLv2 only. + */ + +#include "greybus.h" +#include "greybus_protocols.h" +#include "operation.h" + +/* TODO: Split into separate calls */ +int gb_audio_gb_get_topology(struct gb_connection *connection, + struct gb_audio_topology **topology) +{ + struct gb_audio_get_topology_size_response size_resp; + struct gb_audio_topology *topo; + uint16_t size; + int ret; + + ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_TOPOLOGY_SIZE, + NULL, 0, &size_resp, sizeof(size_resp)); + if (ret) + return ret; + + size = le16_to_cpu(size_resp.size); + if (size < sizeof(*topo)) + return -ENODATA; + + topo = kzalloc(size, GFP_KERNEL); + if (!topo) + return -ENOMEM; + + ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_TOPOLOGY, NULL, 0, + topo, size); + if (ret) { + kfree(topo); + return ret; + } + + *topology = topo; + + return 0; +} +EXPORT_SYMBOL_GPL(gb_audio_gb_get_topology); + +int gb_audio_gb_get_control(struct gb_connection *connection, + uint8_t control_id, uint8_t index, + struct gb_audio_ctl_elem_value *value) +{ + struct gb_audio_get_control_request req; + struct gb_audio_get_control_response resp; + int ret; + + req.control_id = control_id; + req.index = index; + + ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_CONTROL, + &req, sizeof(req), &resp, sizeof(resp)); + if (ret) + return ret; + + memcpy(value, &resp.value, sizeof(*value)); + + return 0; +} +EXPORT_SYMBOL_GPL(gb_audio_gb_get_control); + +int gb_audio_gb_set_control(struct gb_connection *connection, + uint8_t control_id, uint8_t index, + struct gb_audio_ctl_elem_value *value) +{ + struct gb_audio_set_control_request req; + + req.control_id = control_id; + req.index = index; + memcpy(&req.value, value, sizeof(req.value)); + + return gb_operation_sync(connection, GB_AUDIO_TYPE_SET_CONTROL, + &req, sizeof(req), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_audio_gb_set_control); + +int gb_audio_gb_enable_widget(struct gb_connection *connection, + uint8_t widget_id) +{ + struct gb_audio_enable_widget_request req; + + req.widget_id = widget_id; + + return gb_operation_sync(connection, GB_AUDIO_TYPE_ENABLE_WIDGET, + &req, sizeof(req), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_audio_gb_enable_widget); + +int gb_audio_gb_disable_widget(struct gb_connection *connection, + uint8_t widget_id) +{ + struct gb_audio_disable_widget_request req; + + req.widget_id = widget_id; + + return gb_operation_sync(connection, GB_AUDIO_TYPE_DISABLE_WIDGET, + &req, sizeof(req), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_audio_gb_disable_widget); + +int gb_audio_gb_get_pcm(struct gb_connection *connection, uint16_t data_cport, + uint32_t *format, uint32_t *rate, uint8_t *channels, + uint8_t *sig_bits) +{ + struct gb_audio_get_pcm_request req; + struct gb_audio_get_pcm_response resp; + int ret; + + req.data_cport = cpu_to_le16(data_cport); + + ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_PCM, + &req, sizeof(req), &resp, sizeof(resp)); + if (ret) + return ret; + + *format = le32_to_cpu(resp.format); + *rate = le32_to_cpu(resp.rate); + *channels = resp.channels; + *sig_bits = resp.sig_bits; + + return 0; +} +EXPORT_SYMBOL_GPL(gb_audio_gb_get_pcm); + +int gb_audio_gb_set_pcm(struct gb_connection *connection, uint16_t data_cport, + uint32_t format, uint32_t rate, uint8_t channels, + uint8_t sig_bits) +{ + struct gb_audio_set_pcm_request req; + + req.data_cport = cpu_to_le16(data_cport); + req.format = cpu_to_le32(format); + req.rate = cpu_to_le32(rate); + req.channels = channels; + req.sig_bits = sig_bits; + + return gb_operation_sync(connection, GB_AUDIO_TYPE_SET_PCM, + &req, sizeof(req), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_audio_gb_set_pcm); + +int gb_audio_gb_set_tx_data_size(struct gb_connection *connection, + uint16_t data_cport, uint16_t size) +{ + struct gb_audio_set_tx_data_size_request req; + + req.data_cport = cpu_to_le16(data_cport); + req.size = cpu_to_le16(size); + + return gb_operation_sync(connection, GB_AUDIO_TYPE_SET_TX_DATA_SIZE, + &req, sizeof(req), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_audio_gb_set_tx_data_size); + +int gb_audio_gb_get_tx_delay(struct gb_connection *connection, + uint16_t data_cport, uint32_t *delay) +{ + struct gb_audio_get_tx_delay_request req; + struct gb_audio_get_tx_delay_response resp; + int ret; + + req.data_cport = cpu_to_le16(data_cport); + + ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_TX_DELAY, + &req, sizeof(req), &resp, sizeof(resp)); + if (ret) + return ret; + + *delay = le32_to_cpu(resp.delay); + + return 0; +} +EXPORT_SYMBOL_GPL(gb_audio_gb_get_tx_delay); + +int gb_audio_gb_activate_tx(struct gb_connection *connection, + uint16_t data_cport) +{ + struct gb_audio_activate_tx_request req; + + req.data_cport = cpu_to_le16(data_cport); + + return gb_operation_sync(connection, GB_AUDIO_TYPE_ACTIVATE_TX, + &req, sizeof(req), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_audio_gb_activate_tx); + +int gb_audio_gb_deactivate_tx(struct gb_connection *connection, + uint16_t data_cport) +{ + struct gb_audio_deactivate_tx_request req; + + req.data_cport = cpu_to_le16(data_cport); + + return gb_operation_sync(connection, GB_AUDIO_TYPE_DEACTIVATE_TX, + &req, sizeof(req), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_audio_gb_deactivate_tx); + +int gb_audio_gb_set_rx_data_size(struct gb_connection *connection, + uint16_t data_cport, uint16_t size) +{ + struct gb_audio_set_rx_data_size_request req; + + req.data_cport = cpu_to_le16(data_cport); + req.size = cpu_to_le16(size); + + return gb_operation_sync(connection, GB_AUDIO_TYPE_SET_RX_DATA_SIZE, + &req, sizeof(req), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_audio_gb_set_rx_data_size); + +int gb_audio_gb_get_rx_delay(struct gb_connection *connection, + uint16_t data_cport, uint32_t *delay) +{ + struct gb_audio_get_rx_delay_request req; + struct gb_audio_get_rx_delay_response resp; + int ret; + + req.data_cport = cpu_to_le16(data_cport); + + ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_RX_DELAY, + &req, sizeof(req), &resp, sizeof(resp)); + if (ret) + return ret; + + *delay = le32_to_cpu(resp.delay); + + return 0; +} +EXPORT_SYMBOL_GPL(gb_audio_gb_get_rx_delay); + +int gb_audio_gb_activate_rx(struct gb_connection *connection, + uint16_t data_cport) +{ + struct gb_audio_activate_rx_request req; + + req.data_cport = cpu_to_le16(data_cport); + + return gb_operation_sync(connection, GB_AUDIO_TYPE_ACTIVATE_RX, + &req, sizeof(req), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_audio_gb_activate_rx); + +int gb_audio_gb_deactivate_rx(struct gb_connection *connection, + uint16_t data_cport) +{ + struct gb_audio_deactivate_rx_request req; + + req.data_cport = cpu_to_le16(data_cport); + + return gb_operation_sync(connection, GB_AUDIO_TYPE_DEACTIVATE_RX, + &req, sizeof(req), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_audio_gb_deactivate_rx); + +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("greybus:audio-gb"); +MODULE_DESCRIPTION("Greybus Audio Device Class Protocol library"); +MODULE_AUTHOR("Mark Greer "); -- cgit v0.10.2 From 4dbf5056405ad3c0ead370f0f3254c17b81b1e04 Mon Sep 17 00:00:00 2001 From: Mark Greer Date: Wed, 13 Jan 2016 14:07:47 -0700 Subject: greybus: audio: Add direct audio streaming control for APBridgeA The latest audio architecture does not stream audio data over the USB link between the AP and APBridgeA. Instead, audio data is streamed directly over the I2S link between the two. To support the Greybus audio driver in setting up the I2S port and controling packeting/depacketizing of audio data to/from Greybus audio messages, define a set of commands and their parameters. These commands and parameters will be placed into a request and sent over the USB control channel to APBridgeA. A corresponding driver on APBridgeA will receive and process the requests. Signed-off-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 3010f16..e2ae24b 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -31,6 +31,7 @@ gb-es2-y := es2.o gb-arche-y := arche-platform.o arche-apb-ctrl.o gb-audio-codec-y := audio_codec.o gb-audio-gb-y := audio_gb.o +gb-audio-apbridgea-y := audio_apbridgea.o gb-camera-y := camera.o obj-m += greybus.o @@ -46,6 +47,7 @@ obj-m += gb-arche.o obj-m += gb-audio-codec.o obj-m += gb-camera.o obj-m += gb-audio-gb.o +obj-m += gb-audio-apbridgea.o KERNELVER ?= $(shell uname -r) KERNELDIR ?= /lib/modules/$(KERNELVER)/build diff --git a/drivers/staging/greybus/audio.h b/drivers/staging/greybus/audio.h index c8f798e..fca60af 100644 --- a/drivers/staging/greybus/audio.h +++ b/drivers/staging/greybus/audio.h @@ -121,6 +121,29 @@ extern int gb_audio_gb_activate_rx(struct gb_connection *connection, uint16_t data_cport); extern int gb_audio_gb_deactivate_rx(struct gb_connection *connection, uint16_t data_cport); +extern int gb_audio_apbridgea_set_config(struct gb_connection *connection, + __u16 i2s_port, __u32 format, + __u32 rate, __u32 mclk_freq); +extern int gb_audio_apbridgea_register_cport(struct gb_connection *connection, + __u16 i2s_port, __u16 cportid); +extern int gb_audio_apbridgea_unregister_cport(struct gb_connection *connection, + __u16 i2s_port, __u16 cportid); +extern int gb_audio_apbridgea_set_tx_data_size(struct gb_connection *connection, + __u16 i2s_port, __u16 size); +extern int gb_audio_apbridgea_get_tx_delay(struct gb_connection *connection, + __u16 i2s_port, __u32 *delay); +extern int gb_audio_apbridgea_start_tx(struct gb_connection *connection, + __u16 i2s_port, __u64 timestamp); +extern int gb_audio_apbridgea_stop_tx(struct gb_connection *connection, + __u16 i2s_port); +extern int gb_audio_apbridgea_set_rx_data_size(struct gb_connection *connection, + __u16 i2s_port, __u16 size); +extern int gb_audio_apbridgea_get_rx_delay(struct gb_connection *connection, + __u16 i2s_port, __u32 *delay); +extern int gb_audio_apbridgea_start_rx(struct gb_connection *connection, + __u16 i2s_port); +extern int gb_audio_apbridgea_stop_rx(struct gb_connection *connection, + __u16 i2s_port); #endif /* __KERNEL__ */ #endif /* __LINUX_GBAUDIO_H */ diff --git a/drivers/staging/greybus/audio_apbridgea.c b/drivers/staging/greybus/audio_apbridgea.c new file mode 100644 index 0000000..20238e6 --- /dev/null +++ b/drivers/staging/greybus/audio_apbridgea.c @@ -0,0 +1,156 @@ +/* + * Greybus Audio Device Class Protocol helpers + * + * Copyright 2015-2016 Google Inc. + * + * Released under the GPLv2 only. + */ + +#include "greybus.h" +#include "greybus_protocols.h" +#include "audio_apbridgea.h" + +int gb_audio_apbridgea_set_config(struct gb_connection *connection, + __u16 i2s_port, __u32 format, __u32 rate, + __u32 mclk_freq) +{ + struct audio_apbridgea_set_config_request req; + + req.hdr.type = AUDIO_APBRIDGEA_TYPE_SET_CONFIG; + req.hdr.i2s_port = cpu_to_le16(i2s_port); + req.format = cpu_to_le32(format); + req.rate = cpu_to_le32(rate); + req.mclk_freq = cpu_to_le32(mclk_freq); + + return gb_hd_output(connection->hd, &req, sizeof(req), + GB_APB_REQUEST_AUDIO_CONTROL, true); +} +EXPORT_SYMBOL_GPL(gb_audio_apbridgea_set_config); + +int gb_audio_apbridgea_register_cport(struct gb_connection *connection, + __u16 i2s_port, __u16 cportid) +{ + struct audio_apbridgea_register_cport_request req; + + req.hdr.type = AUDIO_APBRIDGEA_TYPE_REGISTER_CPORT; + req.hdr.i2s_port = cpu_to_le16(i2s_port); + req.cport = cpu_to_le16(cportid); + + return gb_hd_output(connection->hd, &req, sizeof(req), + GB_APB_REQUEST_AUDIO_CONTROL, true); +} +EXPORT_SYMBOL_GPL(gb_audio_apbridgea_register_cport); + +int gb_audio_apbridgea_unregister_cport(struct gb_connection *connection, + __u16 i2s_port, __u16 cportid) +{ + struct audio_apbridgea_unregister_cport_request req; + + req.hdr.type = AUDIO_APBRIDGEA_TYPE_UNREGISTER_CPORT; + req.hdr.i2s_port = cpu_to_le16(i2s_port); + req.cport = cpu_to_le16(cportid); + + return gb_hd_output(connection->hd, &req, sizeof(req), + GB_APB_REQUEST_AUDIO_CONTROL, true); +} +EXPORT_SYMBOL_GPL(gb_audio_apbridgea_unregister_cport); + +int gb_audio_apbridgea_set_tx_data_size(struct gb_connection *connection, + __u16 i2s_port, __u16 size) +{ + struct audio_apbridgea_set_tx_data_size_request req; + + req.hdr.type = AUDIO_APBRIDGEA_TYPE_SET_TX_DATA_SIZE; + req.hdr.i2s_port = cpu_to_le16(i2s_port); + req.size = cpu_to_le16(size); + + return gb_hd_output(connection->hd, &req, sizeof(req), + GB_APB_REQUEST_AUDIO_CONTROL, true); +} +EXPORT_SYMBOL_GPL(gb_audio_apbridgea_set_tx_data_size); + +int gb_audio_apbridgea_get_tx_delay(struct gb_connection *connection, + __u16 i2s_port, __u32 *delay) +{ + /* TODO: implement */ + return -ENOSYS; +} +EXPORT_SYMBOL_GPL(gb_audio_apbridgea_get_tx_delay); + +int gb_audio_apbridgea_start_tx(struct gb_connection *connection, + __u16 i2s_port, __u64 timestamp) +{ + struct audio_apbridgea_start_tx_request req; + + req.hdr.type = AUDIO_APBRIDGEA_TYPE_START_TX; + req.hdr.i2s_port = cpu_to_le16(i2s_port); + req.timestamp = cpu_to_le64(timestamp); + + return gb_hd_output(connection->hd, &req, sizeof(req), + GB_APB_REQUEST_AUDIO_CONTROL, true); +} +EXPORT_SYMBOL_GPL(gb_audio_apbridgea_start_tx); + +int gb_audio_apbridgea_stop_tx(struct gb_connection *connection, __u16 i2s_port) +{ + struct audio_apbridgea_stop_tx_request req; + + req.hdr.type = AUDIO_APBRIDGEA_TYPE_STOP_TX; + req.hdr.i2s_port = cpu_to_le16(i2s_port); + + return gb_hd_output(connection->hd, &req, sizeof(req), + GB_APB_REQUEST_AUDIO_CONTROL, true); +} +EXPORT_SYMBOL_GPL(gb_audio_apbridgea_stop_tx); + +int gb_audio_apbridgea_set_rx_data_size(struct gb_connection *connection, + __u16 i2s_port, __u16 size) +{ + struct audio_apbridgea_set_rx_data_size_request req; + + req.hdr.type = AUDIO_APBRIDGEA_TYPE_SET_RX_DATA_SIZE; + req.hdr.i2s_port = cpu_to_le16(i2s_port); + req.size = cpu_to_le16(size); + + return gb_hd_output(connection->hd, &req, sizeof(req), + GB_APB_REQUEST_AUDIO_CONTROL, true); +} +EXPORT_SYMBOL_GPL(gb_audio_apbridgea_set_rx_data_size); + +int gb_audio_apbridgea_get_rx_delay(struct gb_connection *connection, + __u16 i2s_port, __u32 *delay) +{ + /* TODO: implement */ + return -ENOSYS; +} +EXPORT_SYMBOL_GPL(gb_audio_apbridgea_get_rx_delay); + +int gb_audio_apbridgea_start_rx(struct gb_connection *connection, + __u16 i2s_port) +{ + struct audio_apbridgea_start_rx_request req; + + req.hdr.type = AUDIO_APBRIDGEA_TYPE_START_RX; + req.hdr.i2s_port = cpu_to_le16(i2s_port); + + return gb_hd_output(connection->hd, &req, sizeof(req), + GB_APB_REQUEST_AUDIO_CONTROL, true); +} +EXPORT_SYMBOL_GPL(gb_audio_apbridgea_start_rx); + +int gb_audio_apbridgea_stop_rx(struct gb_connection *connection, __u16 i2s_port) +{ + struct audio_apbridgea_stop_rx_request req; + + req.hdr.type = AUDIO_APBRIDGEA_TYPE_STOP_RX; + req.hdr.i2s_port = cpu_to_le16(i2s_port); + + return gb_hd_output(connection->hd, &req, sizeof(req), + GB_APB_REQUEST_AUDIO_CONTROL, true); +} +EXPORT_SYMBOL_GPL(gb_audio_apbridgea_stop_rx); + +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("greybus:audio-apbridgea"); +MODULE_DESCRIPTION("Greybus Special APBridgeA Audio Protocol library"); +MODULE_AUTHOR("Mark Greer "); diff --git a/drivers/staging/greybus/audio_apbridgea.h b/drivers/staging/greybus/audio_apbridgea.h new file mode 100644 index 0000000..d1d56b7 --- /dev/null +++ b/drivers/staging/greybus/audio_apbridgea.h @@ -0,0 +1,149 @@ +/** + * Copyright (c) 2015-2016 Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 HOLDER 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. + */ +/* + * This is a special protocol for configuring communication over the + * I2S bus between the DSP on the MSM8994 and APBridgeA. Therefore, + * we can predefine several low-level attributes of the communication + * because we know that they are supported. In particular, the following + * assumptions are made: + * - there are two channels (i.e., stereo) + * - the low-level protocol is I2S as defined by Philips/NXP + * - the DSP on the MSM8994 is the clock master for MCLK, BCLK, and WCLK + * - WCLK changes on the falling edge of BCLK + * - WCLK low for left channel; high for right channel + * - TX data is sent on the falling edge of BCLK + * - RX data is received/latched on the rising edge of BCLK + */ + +#ifndef __AUDIO_APBRIDGEA_H +#define __AUDIO_APBRIDGEA_H + +#define AUDIO_APBRIDGEA_TYPE_SET_CONFIG 0x01 +#define AUDIO_APBRIDGEA_TYPE_REGISTER_CPORT 0x02 +#define AUDIO_APBRIDGEA_TYPE_UNREGISTER_CPORT 0x03 +#define AUDIO_APBRIDGEA_TYPE_SET_TX_DATA_SIZE 0x04 +#define AUDIO_APBRIDGEA_TYPE_GET_TX_DELAY 0x05 +#define AUDIO_APBRIDGEA_TYPE_START_TX 0x06 +#define AUDIO_APBRIDGEA_TYPE_STOP_TX 0x07 +#define AUDIO_APBRIDGEA_TYPE_SET_RX_DATA_SIZE 0x08 +#define AUDIO_APBRIDGEA_TYPE_GET_RX_DELAY 0x09 +#define AUDIO_APBRIDGEA_TYPE_START_RX 0x0a +#define AUDIO_APBRIDGEA_TYPE_STOP_RX 0x0b + +#define AUDIO_APBRIDGEA_PCM_FMT_8 BIT(0) +#define AUDIO_APBRIDGEA_PCM_FMT_16 BIT(1) +#define AUDIO_APBRIDGEA_PCM_FMT_24 BIT(2) +#define AUDIO_APBRIDGEA_PCM_FMT_32 BIT(3) +#define AUDIO_APBRIDGEA_PCM_FMT_64 BIT(4) + +#define AUDIO_APBRIDGEA_PCM_RATE_5512 BIT(0) +#define AUDIO_APBRIDGEA_PCM_RATE_8000 BIT(1) +#define AUDIO_APBRIDGEA_PCM_RATE_11025 BIT(2) +#define AUDIO_APBRIDGEA_PCM_RATE_16000 BIT(3) +#define AUDIO_APBRIDGEA_PCM_RATE_22050 BIT(4) +#define AUDIO_APBRIDGEA_PCM_RATE_32000 BIT(5) +#define AUDIO_APBRIDGEA_PCM_RATE_44100 BIT(6) +#define AUDIO_APBRIDGEA_PCM_RATE_48000 BIT(7) +#define AUDIO_APBRIDGEA_PCM_RATE_64000 BIT(8) +#define AUDIO_APBRIDGEA_PCM_RATE_88200 BIT(9) +#define AUDIO_APBRIDGEA_PCM_RATE_96000 BIT(10) +#define AUDIO_APBRIDGEA_PCM_RATE_176400 BIT(11) +#define AUDIO_APBRIDGEA_PCM_RATE_192000 BIT(12) + +/* The I2S port is passed in the 'index' parameter of the USB request */ +/* The CPort is passed in the 'value' parameter of the USB request */ + +struct audio_apbridgea_hdr { + __u8 type; + __le16 i2s_port; + __u8 data[0]; +} __packed; + +struct audio_apbridgea_set_config_request { + struct audio_apbridgea_hdr hdr; + __le32 format; /* AUDIO_APBRIDGEA_PCM_FMT_* */ + __le32 rate; /* AUDIO_APBRIDGEA_PCM_RATE_* */ + __le32 mclk_freq; /* XXX Remove? */ +} __packed; + +struct audio_apbridgea_register_cport_request { + struct audio_apbridgea_hdr hdr; + __le16 cport; +} __packed; + +struct audio_apbridgea_unregister_cport_request { + struct audio_apbridgea_hdr hdr; + __le16 cport; +} __packed; + +struct audio_apbridgea_set_tx_data_size_request { + struct audio_apbridgea_hdr hdr; + __le16 size; +} __packed; + +struct audio_apbridgea_get_tx_delay_request { + struct audio_apbridgea_hdr hdr; +} __packed; + +struct audio_apbridgea_get_tx_delay_response { + struct audio_apbridgea_hdr hdr; + __le16 delay; +} __packed; + +struct audio_apbridgea_start_tx_request { + struct audio_apbridgea_hdr hdr; + __le64 timestamp; +} __packed; + +struct audio_apbridgea_stop_tx_request { + struct audio_apbridgea_hdr hdr; +} __packed; + +struct audio_apbridgea_set_rx_data_size_request { + struct audio_apbridgea_hdr hdr; + __le16 size; +} __packed; + +struct audio_apbridgea_get_rx_delay_request { + struct audio_apbridgea_hdr hdr; +} __packed; + +struct audio_apbridgea_get_rx_delay_response { + struct audio_apbridgea_hdr hdr; + __le16 delay; +} __packed; + +struct audio_apbridgea_start_rx_request { + struct audio_apbridgea_hdr hdr; +} __packed; + +struct audio_apbridgea_stop_rx_request { + struct audio_apbridgea_hdr hdr; +} __packed; + +#endif /*__AUDIO_APBRIDGEA_H */ diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 1277b74..55e99b7 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -175,6 +175,9 @@ struct gb_control_interface_version_response { /* request to control the CSI transmitter */ #define GB_APB_REQUEST_CSI_TX_CONTROL 0x08 +/* request to control the CSI transmitter */ +#define GB_APB_REQUEST_AUDIO_CONTROL 0x09 + /* Firmware Protocol */ -- cgit v0.10.2 From 8db00736d365b75d6af5dfd4a2673a1453fff4b7 Mon Sep 17 00:00:00 2001 From: Svetlin Ankov Date: Wed, 13 Jan 2016 14:07:48 -0700 Subject: greybus: audio: Add Audio Manager This is a simple module that keeps a list of connected GB audio modules. Whenever a device is attached, an appropriate uevent is sent to userspace: UDEV [4941.803215] add /kernel/gb_audio_manager/0 (gb_audio_manager) ACTION=add CPORT=99 DEVICES=0x10 DEVPATH=/kernel/gb_audio_manager/0 NAME=naim PID=64 SEQNUM=1828 SLOT=2 SUBSYSTEM=gb_audio_manager USEC_INITIALIZED=802416 VID=128 And whenever removed: UDEV [4941.836588] remove /kernel/gb_audio_manager/0 (gb_audio_manager) ACTION=remove DEVPATH=/kernel/gb_audio_manager/0 SEQNUM=1833 SUBSYSTEM=gb_audio_manager USEC_INITIALIZED=835681 The API consists of functions for adding, removing and inspecting added device module descriptions (struct gb_audio_module): int gb_audio_manager_add(struct gb_audio_module_descriptor *desc); int gb_audio_manager_remove(int id); int gb_audio_manager_remove_all(void); struct gb_audio_module* gb_audio_manager_get_module(int id); void gb_audio_manager_put_module(struct gb_audio_module *module); int gb_audio_manager_dump_module(int id); void gb_audio_manager_dump_all(void); Devices can be inspected through sysfs in /sys/kernel/gb_audio_manager/{id}/* If GB_AUDIO_MANAGER_SYSFS is exported as 'true', managing devices can be done via the SYSFS as well. For instance: echo name=naim slot=2 vid=128 pid=64 cport=99 devices=0x10 > /sys/kernel/gb_audio_manager/add echo all > /sys/kernel/gb_audio_manager/dump echo 2 > /sys/kernel/gb_audio_manager/dump echo 2 > /sys/kernel/gb_audio_manager/remove Signed-off-by: Svetlin Ankov Signed-off-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index e2ae24b..4ebdc6b 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -32,6 +32,8 @@ gb-arche-y := arche-platform.o arche-apb-ctrl.o gb-audio-codec-y := audio_codec.o gb-audio-gb-y := audio_gb.o gb-audio-apbridgea-y := audio_apbridgea.o +gb-audio-manager-y += audio_manager.o +gb-audio-manager-y += audio_manager_module.o gb-camera-y := camera.o obj-m += greybus.o @@ -48,6 +50,7 @@ obj-m += gb-audio-codec.o obj-m += gb-camera.o obj-m += gb-audio-gb.o obj-m += gb-audio-apbridgea.o +obj-m += gb-audio-manager.o KERNELVER ?= $(shell uname -r) KERNELDIR ?= /lib/modules/$(KERNELVER)/build @@ -89,6 +92,12 @@ ccflags-y := -Wall # needed for trace events ccflags-y += -I$(src) +GB_AUDIO_MANAGER_SYSFS ?= true +ifeq ($(GB_AUDIO_MANAGER_SYSFS),true) +gb-audio-manager-y += audio_manager_sysfs.o +ccflags-y += -DGB_AUDIO_MANAGER_SYSFS +endif + all: module tools:: diff --git a/drivers/staging/greybus/audio_manager.c b/drivers/staging/greybus/audio_manager.c new file mode 100644 index 0000000..1176763 --- /dev/null +++ b/drivers/staging/greybus/audio_manager.c @@ -0,0 +1,184 @@ +/* + * Greybus operations + * + * Copyright 2015-2016 Google Inc. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include +#include +#include + +#include "audio_manager.h" +#include "audio_manager_private.h" + +static struct kset *manager_kset; + +static LIST_HEAD(modules_list); +static DEFINE_RWLOCK(modules_lock); + +static int current_module_id; + +/* helpers */ +static struct gb_audio_manager_module *gb_audio_manager_get_locked(int id) +{ + struct gb_audio_manager_module *module; + + if (id < 0) + return NULL; + + list_for_each_entry(module, &modules_list, list) { + if (module->id == id) + return module; + } + + return NULL; +} + +/* public API */ +int gb_audio_manager_add(struct gb_audio_manager_module_descriptor *desc) +{ + struct gb_audio_manager_module *module; + unsigned long flags; + int err; + + err = gb_audio_manager_module_create(&module, manager_kset, + current_module_id++, desc); + if (err) + return err; + + /* Add it to the list */ + write_lock_irqsave(&modules_lock, flags); + list_add_tail(&module->list, &modules_list); + write_unlock_irqrestore(&modules_lock, flags); + + return module->id; +} +EXPORT_SYMBOL_GPL(gb_audio_manager_add); + +int gb_audio_manager_remove(int id) +{ + struct gb_audio_manager_module *module; + unsigned long flags; + + write_lock_irqsave(&modules_lock, flags); + + module = gb_audio_manager_get_locked(id); + if (!module) { + write_unlock_irqrestore(&modules_lock, flags); + return -EINVAL; + } + + list_del(&module->list); + kobject_put(&module->kobj); + write_unlock_irqrestore(&modules_lock, flags); + return 0; +} +EXPORT_SYMBOL_GPL(gb_audio_manager_remove); + +void gb_audio_manager_remove_all(void) +{ + struct gb_audio_manager_module *module, *next; + int is_empty = 1; + unsigned long flags; + + write_lock_irqsave(&modules_lock, flags); + + list_for_each_entry_safe(module, next, &modules_list, list) { + list_del(&module->list); + kobject_put(&module->kobj); + } + + is_empty = list_empty(&modules_list); + + write_unlock_irqrestore(&modules_lock, flags); + + if (!is_empty) + pr_warn("Not all nodes were deleted\n"); +} +EXPORT_SYMBOL_GPL(gb_audio_manager_remove_all); + +struct gb_audio_manager_module *gb_audio_manager_get_module(int id) +{ + struct gb_audio_manager_module *module; + unsigned long flags; + + read_lock_irqsave(&modules_lock, flags); + module = gb_audio_manager_get_locked(id); + kobject_get(&module->kobj); + read_unlock_irqrestore(&modules_lock, flags); + return module; +} +EXPORT_SYMBOL_GPL(gb_audio_manager_get_module); + +void gb_audio_manager_put_module(struct gb_audio_manager_module *module) +{ + kobject_put(&module->kobj); +} +EXPORT_SYMBOL_GPL(gb_audio_manager_put_module); + +int gb_audio_manager_dump_module(int id) +{ + struct gb_audio_manager_module *module; + unsigned long flags; + + read_lock_irqsave(&modules_lock, flags); + module = gb_audio_manager_get_locked(id); + read_unlock_irqrestore(&modules_lock, flags); + + if (!module) + return -EINVAL; + + gb_audio_manager_module_dump(module); + return 0; +} +EXPORT_SYMBOL_GPL(gb_audio_manager_dump_module); + +void gb_audio_manager_dump_all(void) +{ + struct gb_audio_manager_module *module; + int count = 0; + unsigned long flags; + + read_lock_irqsave(&modules_lock, flags); + list_for_each_entry(module, &modules_list, list) { + gb_audio_manager_module_dump(module); + count++; + } + read_unlock_irqrestore(&modules_lock, flags); + + pr_info("Number of connected modules: %d\n", count); +} +EXPORT_SYMBOL_GPL(gb_audio_manager_dump_all); + +/* + * module init/deinit + */ +static int __init manager_init(void) +{ + manager_kset = kset_create_and_add(GB_AUDIO_MANAGER_NAME, NULL, + kernel_kobj); + if (!manager_kset) + return -ENOMEM; + +#ifdef GB_AUDIO_MANAGER_SYSFS + gb_audio_manager_sysfs_init(&manager_kset->kobj); +#endif + + return 0; +} + +static void __exit manager_exit(void) +{ + gb_audio_manager_remove_all(); + kset_unregister(manager_kset); +} + +module_init(manager_init); +module_exit(manager_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Svetlin Ankov "); diff --git a/drivers/staging/greybus/audio_manager.h b/drivers/staging/greybus/audio_manager.h new file mode 100644 index 0000000..9ca7ac09 --- /dev/null +++ b/drivers/staging/greybus/audio_manager.h @@ -0,0 +1,82 @@ +/* + * Greybus operations + * + * Copyright 2015-2016 Google Inc. + * + * Released under the GPLv2 only. + */ + +#ifndef _GB_AUDIO_MANAGER_H_ +#define _GB_AUDIO_MANAGER_H_ + +#include +#include + +#define GB_AUDIO_MANAGER_NAME "gb_audio_manager" +#define GB_AUDIO_MANAGER_MODULE_NAME_LEN 64 +#define GB_AUDIO_MANAGER_MODULE_NAME_LEN_SSCANF "63" + +struct gb_audio_manager_module_descriptor { + char name[GB_AUDIO_MANAGER_MODULE_NAME_LEN]; + int slot; + int vid; + int pid; + int cport; + unsigned int devices; +}; + +struct gb_audio_manager_module { + struct kobject kobj; + struct list_head list; + int id; + struct gb_audio_manager_module_descriptor desc; +}; + +/* + * Creates a new gb_audio_manager_module_descriptor, using the specified + * descriptor. + * + * Returns a negative result on error, or the id of the newly created module. + * + */ +int gb_audio_manager_add(struct gb_audio_manager_module_descriptor *desc); + +/* + * Removes a connected gb_audio_manager_module_descriptor for the specified ID. + * + * Returns zero on success, or a negative value on error. + */ +int gb_audio_manager_remove(int id); + +/* + * Removes all connected gb_audio_modules + * + * Returns zero on success, or a negative value on error. + */ +void gb_audio_manager_remove_all(void); + +/* + * Retrieves a gb_audio_manager_module_descriptor for the specified id. + * Returns the gb_audio_manager_module_descriptor structure, + * or NULL if there is no module with the specified ID. + */ +struct gb_audio_manager_module *gb_audio_manager_get_module(int id); + +/* + * Decreases the refcount of the module, obtained by the get function. + * Modules are removed via gb_audio_manager_remove + */ +void gb_audio_manager_put_module(struct gb_audio_manager_module *module); + +/* + * Dumps the module for the specified id + * Return 0 on success + */ +int gb_audio_manager_dump_module(int id); + +/* + * Dumps all connected modules + */ +void gb_audio_manager_dump_all(void); + +#endif /* _GB_AUDIO_MANAGER_H_ */ diff --git a/drivers/staging/greybus/audio_manager_module.c b/drivers/staging/greybus/audio_manager_module.c new file mode 100644 index 0000000..e5cffa3 --- /dev/null +++ b/drivers/staging/greybus/audio_manager_module.c @@ -0,0 +1,240 @@ +/* + * Greybus operations + * + * Copyright 2015-2016 Google Inc. + * + * Released under the GPLv2 only. + */ + +#include + +#include "audio_manager.h" +#include "audio_manager_private.h" + +#define to_gb_audio_module_attr(x) \ + container_of(x, struct gb_audio_manager_module_attribute, attr) +#define to_gb_audio_module(x) \ + container_of(x, struct gb_audio_manager_module, kobj) + +struct gb_audio_manager_module_attribute { + struct attribute attr; + ssize_t (*show)(struct gb_audio_manager_module *module, + struct gb_audio_manager_module_attribute *attr, + char *buf); + ssize_t (*store)(struct gb_audio_manager_module *module, + struct gb_audio_manager_module_attribute *attr, + const char *buf, size_t count); +}; + +static ssize_t gb_audio_module_attr_show( + struct kobject *kobj, struct attribute *attr, char *buf) +{ + struct gb_audio_manager_module_attribute *attribute; + struct gb_audio_manager_module *module; + + attribute = to_gb_audio_module_attr(attr); + module = to_gb_audio_module(kobj); + + if (!attribute->show) + return -EIO; + + return attribute->show(module, attribute, buf); +} + +static ssize_t gb_audio_module_attr_store(struct kobject *kobj, + struct attribute *attr, + const char *buf, size_t len) +{ + struct gb_audio_manager_module_attribute *attribute; + struct gb_audio_manager_module *module; + + attribute = to_gb_audio_module_attr(attr); + module = to_gb_audio_module(kobj); + + if (!attribute->store) + return -EIO; + + return attribute->store(module, attribute, buf, len); +} + +static const struct sysfs_ops gb_audio_module_sysfs_ops = { + .show = gb_audio_module_attr_show, + .store = gb_audio_module_attr_store, +}; + +static void gb_audio_module_release(struct kobject *kobj) +{ + struct gb_audio_manager_module *module = to_gb_audio_module(kobj); + + pr_info("Destroying audio module #%d\n", module->id); + /* TODO -> delete from list */ + kfree(module); +} + +static ssize_t gb_audio_module_name_show( + struct gb_audio_manager_module *module, + struct gb_audio_manager_module_attribute *attr, char *buf) +{ + return sprintf(buf, "%s", module->desc.name); +} + +static struct gb_audio_manager_module_attribute gb_audio_module_name_attribute = + __ATTR(name, 0664, gb_audio_module_name_show, NULL); + +static ssize_t gb_audio_module_slot_show( + struct gb_audio_manager_module *module, + struct gb_audio_manager_module_attribute *attr, char *buf) +{ + return sprintf(buf, "%d", module->desc.slot); +} + +static struct gb_audio_manager_module_attribute gb_audio_module_slot_attribute = + __ATTR(slot, 0664, gb_audio_module_slot_show, NULL); + +static ssize_t gb_audio_module_vid_show( + struct gb_audio_manager_module *module, + struct gb_audio_manager_module_attribute *attr, char *buf) +{ + return sprintf(buf, "%d", module->desc.vid); +} + +static struct gb_audio_manager_module_attribute gb_audio_module_vid_attribute = + __ATTR(vid, 0664, gb_audio_module_vid_show, NULL); + +static ssize_t gb_audio_module_pid_show( + struct gb_audio_manager_module *module, + struct gb_audio_manager_module_attribute *attr, char *buf) +{ + return sprintf(buf, "%d", module->desc.pid); +} + +static struct gb_audio_manager_module_attribute gb_audio_module_pid_attribute = + __ATTR(pid, 0664, gb_audio_module_pid_show, NULL); + +static ssize_t gb_audio_module_cport_show( + struct gb_audio_manager_module *module, + struct gb_audio_manager_module_attribute *attr, char *buf) +{ + return sprintf(buf, "%d", module->desc.cport); +} + +static struct gb_audio_manager_module_attribute + gb_audio_module_cport_attribute = + __ATTR(cport, 0664, gb_audio_module_cport_show, NULL); + +static ssize_t gb_audio_module_devices_show( + struct gb_audio_manager_module *module, + struct gb_audio_manager_module_attribute *attr, char *buf) +{ + return sprintf(buf, "0x%X", module->desc.devices); +} + +static struct gb_audio_manager_module_attribute + gb_audio_module_devices_attribute = + __ATTR(devices, 0664, gb_audio_module_devices_show, NULL); + +static struct attribute *gb_audio_module_default_attrs[] = { + &gb_audio_module_name_attribute.attr, + &gb_audio_module_slot_attribute.attr, + &gb_audio_module_vid_attribute.attr, + &gb_audio_module_pid_attribute.attr, + &gb_audio_module_cport_attribute.attr, + &gb_audio_module_devices_attribute.attr, + NULL, /* need to NULL terminate the list of attributes */ +}; + +static struct kobj_type gb_audio_module_type = { + .sysfs_ops = &gb_audio_module_sysfs_ops, + .release = gb_audio_module_release, + .default_attrs = gb_audio_module_default_attrs, +}; + +static void send_add_uevent(struct gb_audio_manager_module *module) +{ + char name_string[128]; + char slot_string[64]; + char vid_string[64]; + char pid_string[64]; + char cport_string[64]; + char devices_string[64]; + + char *envp[] = { + name_string, + slot_string, + vid_string, + pid_string, + cport_string, + devices_string, + NULL + }; + + snprintf(name_string, 128, "NAME=%s", module->desc.name); + snprintf(slot_string, 64, "SLOT=%d", module->desc.slot); + snprintf(vid_string, 64, "VID=%d", module->desc.vid); + snprintf(pid_string, 64, "PID=%d", module->desc.pid); + snprintf(cport_string, 64, "CPORT=%d", module->desc.cport); + snprintf(devices_string, 64, "DEVICES=0x%X", module->desc.devices); + + kobject_uevent_env(&module->kobj, KOBJ_ADD, envp); +} + +int gb_audio_manager_module_create( + struct gb_audio_manager_module **module, + struct kset *manager_kset, + int id, struct gb_audio_manager_module_descriptor *desc) +{ + int err; + struct gb_audio_manager_module *m; + + m = kzalloc(sizeof(*m), GFP_ATOMIC); + if (!m) + return -ENOMEM; + + /* Initialize the node */ + INIT_LIST_HEAD(&m->list); + + /* Set the module id */ + m->id = id; + + /* Copy the provided descriptor */ + memcpy(&m->desc, desc, sizeof(*desc)); + + /* set the kset */ + m->kobj.kset = manager_kset; + + /* + * Initialize and add the kobject to the kernel. All the default files + * will be created here. As we have already specified a kset for this + * kobject, we don't have to set a parent for the kobject, the kobject + * will be placed beneath that kset automatically. + */ + err = kobject_init_and_add(&m->kobj, &gb_audio_module_type, NULL, "%d", + id); + if (err) { + pr_err("failed initializing kobject for audio module #%d\n", + id); + kobject_put(&m->kobj); + return err; + } + + /* + * Notify the object was created + */ + send_add_uevent(m); + + *module = m; + pr_info("Created audio module #%d\n", id); + return 0; +} + +void gb_audio_manager_module_dump(struct gb_audio_manager_module *module) +{ + pr_info("audio module #%d name=%s slot=%d vid=%d pid=%d cport=%d devices=0x%X\n", + module->id, + module->desc.name, + module->desc.slot, + module->desc.vid, + module->desc.pid, + module->desc.cport, + module->desc.devices); +} diff --git a/drivers/staging/greybus/audio_manager_private.h b/drivers/staging/greybus/audio_manager_private.h new file mode 100644 index 0000000..079ce95 --- /dev/null +++ b/drivers/staging/greybus/audio_manager_private.h @@ -0,0 +1,28 @@ +/* + * Greybus operations + * + * Copyright 2015-2016 Google Inc. + * + * Released under the GPLv2 only. + */ + +#ifndef _GB_AUDIO_MANAGER_PRIVATE_H_ +#define _GB_AUDIO_MANAGER_PRIVATE_H_ + +#include + +#include "audio_manager.h" + +int gb_audio_manager_module_create( + struct gb_audio_manager_module **module, + struct kset *manager_kset, + int id, struct gb_audio_manager_module_descriptor *desc); + +/* module destroyed via kobject_put */ + +void gb_audio_manager_module_dump(struct gb_audio_manager_module *module); + +/* sysfs control */ +void gb_audio_manager_sysfs_init(struct kobject *kobj); + +#endif /* _GB_AUDIO_MANAGER_PRIVATE_H_ */ diff --git a/drivers/staging/greybus/audio_manager_sysfs.c b/drivers/staging/greybus/audio_manager_sysfs.c new file mode 100644 index 0000000..c713f5f --- /dev/null +++ b/drivers/staging/greybus/audio_manager_sysfs.c @@ -0,0 +1,101 @@ +/* + * Greybus operations + * + * Copyright 2015-2016 Google Inc. + * + * Released under the GPLv2 only. + */ + +#include +#include + +#include "audio_manager.h" +#include "audio_manager_private.h" + +static ssize_t manager_sysfs_add_store( + struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) +{ + struct gb_audio_manager_module_descriptor desc = { {0} }; + + int num = sscanf(buf, + "name=%" GB_AUDIO_MANAGER_MODULE_NAME_LEN_SSCANF "s " + "slot=%d vid=%d pid=%d cport=%d devices=0x%X", + desc.name, &desc.slot, &desc.vid, &desc.pid, + &desc.cport, &desc.devices); + + if (num != 6) + return -EINVAL; + + num = gb_audio_manager_add(&desc); + if (num < 0) + return -EINVAL; + + return count; +} + +static struct kobj_attribute manager_add_attribute = + __ATTR(add, 0664, NULL, manager_sysfs_add_store); + +static ssize_t manager_sysfs_remove_store( + struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) +{ + int id; + + int num = sscanf(buf, "%d", &id); + + if (num != 1) + return -EINVAL; + + num = gb_audio_manager_remove(id); + if (num) + return num; + + return count; +} + +static struct kobj_attribute manager_remove_attribute = + __ATTR(remove, 0664, NULL, manager_sysfs_remove_store); + +static ssize_t manager_sysfs_dump_store( + struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) +{ + int id; + + int num = sscanf(buf, "%d", &id); + + if (num == 1) { + num = gb_audio_manager_dump_module(id); + if (num) + return num; + } else if (!strncmp("all", buf, 3)) + gb_audio_manager_dump_all(); + else + return -EINVAL; + + return count; +} + +static struct kobj_attribute manager_dump_attribute = + __ATTR(dump, 0664, NULL, manager_sysfs_dump_store); + +static void manager_sysfs_init_attribute( + struct kobject *kobj, struct kobj_attribute *kattr) +{ + int err; + + err = sysfs_create_file(kobj, &kattr->attr); + if (err) { + pr_warn("creating the sysfs entry for %s failed: %d\n", + kattr->attr.name, err); + } +} + +void gb_audio_manager_sysfs_init(struct kobject *kobj) +{ + manager_sysfs_init_attribute(kobj, &manager_add_attribute); + manager_sysfs_init_attribute(kobj, &manager_remove_attribute); + manager_sysfs_init_attribute(kobj, &manager_dump_attribute); +} -- cgit v0.10.2 From 7885342cc2727e2e9acae1597ebc88bedfea8464 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal Date: Wed, 13 Jan 2016 14:07:49 -0700 Subject: greybus: audio: Build audio module conditionally Added CONFIG_XXX flag check before compiling audio module. Once we add dynamic DAI link registration from audio driver, this check wil be required to avoid compilation failures with other kernel revisions. Also, renamed header file to better align with .c file name. Signed-off-by: Vaibhav Agarwal Signed-off-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 4ebdc6b..6759d684 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -47,6 +47,9 @@ obj-m += gb-raw.o obj-m += gb-es2.o obj-m += gb-arche.o obj-m += gb-audio-codec.o +ifeq ($(CONFIG_SND_SOC_DYNAMIC_DAILINK),y) + obj-m += gb-audio-codec.o +endif obj-m += gb-camera.o obj-m += gb-audio-gb.o obj-m += gb-audio-apbridgea.o diff --git a/drivers/staging/greybus/audio.h b/drivers/staging/greybus/audio.h deleted file mode 100644 index fca60af..0000000 --- a/drivers/staging/greybus/audio.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Greybus audio driver - * Copyright 2015 Google Inc. - * Copyright 2015 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#ifndef __LINUX_GBAUDIO_H -#define __LINUX_GBAUDIO_H - -#ifdef __KERNEL__ - -#include - -#include "greybus.h" -#include "greybus_protocols.h" - -#define NAME_SIZE 32 - -enum { - APB1_PCM = 0, - APB2_PCM, - NUM_CODEC_DAIS, -}; - -enum gbcodec_reg_index { - GBCODEC_CTL_REG, - GBCODEC_MUTE_REG, - GBCODEC_PB_LVOL_REG, - GBCODEC_PB_RVOL_REG, - GBCODEC_CAP_LVOL_REG, - GBCODEC_CAP_RVOL_REG, - GBCODEC_APB1_MUX_REG, - GBCODEC_APB2_MUX_REG, - GBCODEC_REG_COUNT -}; - -/* bit 0-SPK, 1-HP, 2-DAC, - * 4-MIC, 5-HSMIC, 6-MIC2 - */ -#define GBCODEC_CTL_REG_DEFAULT 0x00 - -/* bit 0,1 - APB1-PB-L/R - * bit 2,3 - APB2-PB-L/R - * bit 4,5 - APB1-Cap-L/R - * bit 6,7 - APB2-Cap-L/R - */ -#define GBCODEC_MUTE_REG_DEFAULT 0x00 - -/* 0-127 steps */ -#define GBCODEC_PB_VOL_REG_DEFAULT 0x00 -#define GBCODEC_CAP_VOL_REG_DEFAULT 0x00 - -/* bit 0,1,2 - PB stereo, left, right - * bit 8,9,10 - Cap stereo, left, right - */ -#define GBCODEC_APB1_MUX_REG_DEFAULT 0x00 -#define GBCODEC_APB2_MUX_REG_DEFAULT 0x00 - -static const u8 gbcodec_reg_defaults[GBCODEC_REG_COUNT] = { - GBCODEC_CTL_REG_DEFAULT, - GBCODEC_MUTE_REG_DEFAULT, - GBCODEC_PB_VOL_REG_DEFAULT, - GBCODEC_PB_VOL_REG_DEFAULT, - GBCODEC_CAP_VOL_REG_DEFAULT, - GBCODEC_CAP_VOL_REG_DEFAULT, - GBCODEC_APB1_MUX_REG_DEFAULT, - GBCODEC_APB2_MUX_REG_DEFAULT, -}; - -struct gbaudio_codec_info { - struct snd_soc_codec *codec; - - bool usable; - u8 reg[GBCODEC_REG_COUNT]; - int registered; - - int num_kcontrols; - int num_dapm_widgets; - int num_dapm_routes; - struct snd_kcontrol_new *kctls; - struct snd_soc_dapm_widget *widgets; - struct snd_soc_dapm_route *routes; - struct mutex lock; -}; - -extern int gb_audio_gb_get_topology(struct gb_connection *connection, - struct gb_audio_topology **topology); -extern int gb_audio_gb_get_control(struct gb_connection *connection, - uint8_t control_id, uint8_t index, - struct gb_audio_ctl_elem_value *value); -extern int gb_audio_gb_set_control(struct gb_connection *connection, - uint8_t control_id, uint8_t index, - struct gb_audio_ctl_elem_value *value); -extern int gb_audio_gb_enable_widget(struct gb_connection *connection, - uint8_t widget_id); -extern int gb_audio_gb_disable_widget(struct gb_connection *connection, - uint8_t widget_id); -extern int gb_audio_gb_get_pcm(struct gb_connection *connection, - uint16_t data_cport, uint32_t *format, - uint32_t *rate, uint8_t *channels, - uint8_t *sig_bits); -extern int gb_audio_gb_set_pcm(struct gb_connection *connection, - uint16_t data_cport, uint32_t format, - uint32_t rate, uint8_t channels, - uint8_t sig_bits); -extern int gb_audio_gb_set_tx_data_size(struct gb_connection *connection, - uint16_t data_cport, uint16_t size); -extern int gb_audio_gb_get_tx_delay(struct gb_connection *connection, - uint16_t data_cport, uint32_t *delay); -extern int gb_audio_gb_activate_tx(struct gb_connection *connection, - uint16_t data_cport); -extern int gb_audio_gb_deactivate_tx(struct gb_connection *connection, - uint16_t data_cport); -extern int gb_audio_gb_set_rx_data_size(struct gb_connection *connection, - uint16_t data_cport, uint16_t size); -extern int gb_audio_gb_get_rx_delay(struct gb_connection *connection, - uint16_t data_cport, uint32_t *delay); -extern int gb_audio_gb_activate_rx(struct gb_connection *connection, - uint16_t data_cport); -extern int gb_audio_gb_deactivate_rx(struct gb_connection *connection, - uint16_t data_cport); -extern int gb_audio_apbridgea_set_config(struct gb_connection *connection, - __u16 i2s_port, __u32 format, - __u32 rate, __u32 mclk_freq); -extern int gb_audio_apbridgea_register_cport(struct gb_connection *connection, - __u16 i2s_port, __u16 cportid); -extern int gb_audio_apbridgea_unregister_cport(struct gb_connection *connection, - __u16 i2s_port, __u16 cportid); -extern int gb_audio_apbridgea_set_tx_data_size(struct gb_connection *connection, - __u16 i2s_port, __u16 size); -extern int gb_audio_apbridgea_get_tx_delay(struct gb_connection *connection, - __u16 i2s_port, __u32 *delay); -extern int gb_audio_apbridgea_start_tx(struct gb_connection *connection, - __u16 i2s_port, __u64 timestamp); -extern int gb_audio_apbridgea_stop_tx(struct gb_connection *connection, - __u16 i2s_port); -extern int gb_audio_apbridgea_set_rx_data_size(struct gb_connection *connection, - __u16 i2s_port, __u16 size); -extern int gb_audio_apbridgea_get_rx_delay(struct gb_connection *connection, - __u16 i2s_port, __u32 *delay); -extern int gb_audio_apbridgea_start_rx(struct gb_connection *connection, - __u16 i2s_port); -extern int gb_audio_apbridgea_stop_rx(struct gb_connection *connection, - __u16 i2s_port); - -#endif /* __KERNEL__ */ -#endif /* __LINUX_GBAUDIO_H */ diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 2bc2309..826604a 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -7,7 +7,7 @@ */ #include -#include "audio.h" +#include "audio_codec.h" static int gbcodec_event_spk(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h new file mode 100644 index 0000000..f8597b3 --- /dev/null +++ b/drivers/staging/greybus/audio_codec.h @@ -0,0 +1,146 @@ +/* + * Greybus audio driver + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#ifndef __LINUX_GBAUDIO_CODEC_H +#define __LINUX_GBAUDIO_CODEC_H + +#include + +#include "greybus.h" +#include "greybus_protocols.h" + +#define NAME_SIZE 32 + +enum { + APB1_PCM = 0, + APB2_PCM, + NUM_CODEC_DAIS, +}; + +enum gbcodec_reg_index { + GBCODEC_CTL_REG, + GBCODEC_MUTE_REG, + GBCODEC_PB_LVOL_REG, + GBCODEC_PB_RVOL_REG, + GBCODEC_CAP_LVOL_REG, + GBCODEC_CAP_RVOL_REG, + GBCODEC_APB1_MUX_REG, + GBCODEC_APB2_MUX_REG, + GBCODEC_REG_COUNT +}; + +/* bit 0-SPK, 1-HP, 2-DAC, + * 4-MIC, 5-HSMIC, 6-MIC2 + */ +#define GBCODEC_CTL_REG_DEFAULT 0x00 + +/* bit 0,1 - APB1-PB-L/R + * bit 2,3 - APB2-PB-L/R + * bit 4,5 - APB1-Cap-L/R + * bit 6,7 - APB2-Cap-L/R + */ +#define GBCODEC_MUTE_REG_DEFAULT 0x00 + +/* 0-127 steps */ +#define GBCODEC_PB_VOL_REG_DEFAULT 0x00 +#define GBCODEC_CAP_VOL_REG_DEFAULT 0x00 + +/* bit 0,1,2 - PB stereo, left, right + * bit 8,9,10 - Cap stereo, left, right + */ +#define GBCODEC_APB1_MUX_REG_DEFAULT 0x00 +#define GBCODEC_APB2_MUX_REG_DEFAULT 0x00 + +static const u8 gbcodec_reg_defaults[GBCODEC_REG_COUNT] = { + GBCODEC_CTL_REG_DEFAULT, + GBCODEC_MUTE_REG_DEFAULT, + GBCODEC_PB_VOL_REG_DEFAULT, + GBCODEC_PB_VOL_REG_DEFAULT, + GBCODEC_CAP_VOL_REG_DEFAULT, + GBCODEC_CAP_VOL_REG_DEFAULT, + GBCODEC_APB1_MUX_REG_DEFAULT, + GBCODEC_APB2_MUX_REG_DEFAULT, +}; + +struct gbaudio_codec_info { + struct snd_soc_codec *codec; + + bool usable; + u8 reg[GBCODEC_REG_COUNT]; + int registered; + + int num_kcontrols; + int num_dapm_widgets; + int num_dapm_routes; + struct snd_kcontrol_new *kctls; + struct snd_soc_dapm_widget *widgets; + struct snd_soc_dapm_route *routes; + struct mutex lock; +}; + +extern int gb_audio_gb_get_topology(struct gb_connection *connection, + struct gb_audio_topology **topology); +extern int gb_audio_gb_get_control(struct gb_connection *connection, + uint8_t control_id, uint8_t index, + struct gb_audio_ctl_elem_value *value); +extern int gb_audio_gb_set_control(struct gb_connection *connection, + uint8_t control_id, uint8_t index, + struct gb_audio_ctl_elem_value *value); +extern int gb_audio_gb_enable_widget(struct gb_connection *connection, + uint8_t widget_id); +extern int gb_audio_gb_disable_widget(struct gb_connection *connection, + uint8_t widget_id); +extern int gb_audio_gb_get_pcm(struct gb_connection *connection, + uint16_t data_cport, uint32_t *format, + uint32_t *rate, uint8_t *channels, + uint8_t *sig_bits); +extern int gb_audio_gb_set_pcm(struct gb_connection *connection, + uint16_t data_cport, uint32_t format, + uint32_t rate, uint8_t channels, + uint8_t sig_bits); +extern int gb_audio_gb_set_tx_data_size(struct gb_connection *connection, + uint16_t data_cport, uint16_t size); +extern int gb_audio_gb_get_tx_delay(struct gb_connection *connection, + uint16_t data_cport, uint32_t *delay); +extern int gb_audio_gb_activate_tx(struct gb_connection *connection, + uint16_t data_cport); +extern int gb_audio_gb_deactivate_tx(struct gb_connection *connection, + uint16_t data_cport); +extern int gb_audio_gb_set_rx_data_size(struct gb_connection *connection, + uint16_t data_cport, uint16_t size); +extern int gb_audio_gb_get_rx_delay(struct gb_connection *connection, + uint16_t data_cport, uint32_t *delay); +extern int gb_audio_gb_activate_rx(struct gb_connection *connection, + uint16_t data_cport); +extern int gb_audio_gb_deactivate_rx(struct gb_connection *connection, + uint16_t data_cport); +extern int gb_audio_apbridgea_set_config(struct gb_connection *connection, + __u16 i2s_port, __u32 format, + __u32 rate, __u32 mclk_freq); +extern int gb_audio_apbridgea_register_cport(struct gb_connection *connection, + __u16 i2s_port, __u16 cportid); +extern int gb_audio_apbridgea_unregister_cport(struct gb_connection *connection, + __u16 i2s_port, __u16 cportid); +extern int gb_audio_apbridgea_set_tx_data_size(struct gb_connection *connection, + __u16 i2s_port, __u16 size); +extern int gb_audio_apbridgea_get_tx_delay(struct gb_connection *connection, + __u16 i2s_port, __u32 *delay); +extern int gb_audio_apbridgea_start_tx(struct gb_connection *connection, + __u16 i2s_port, __u64 timestamp); +extern int gb_audio_apbridgea_stop_tx(struct gb_connection *connection, + __u16 i2s_port); +extern int gb_audio_apbridgea_set_rx_data_size(struct gb_connection *connection, + __u16 i2s_port, __u16 size); +extern int gb_audio_apbridgea_get_rx_delay(struct gb_connection *connection, + __u16 i2s_port, __u32 *delay); +extern int gb_audio_apbridgea_start_rx(struct gb_connection *connection, + __u16 i2s_port); +extern int gb_audio_apbridgea_stop_rx(struct gb_connection *connection, + __u16 i2s_port); + +#endif /* __LINUX_GBAUDIO_CODEC_H */ -- cgit v0.10.2 From 86a685dd453547431794a5c332a9ed742916c9d4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 13 Jan 2016 16:18:36 -0800 Subject: greybus: Makefile: fix up build test for gb-audio-codec.ko We really only want to build the module if the config is set, not all the time like the current code does. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 6759d684..9364897 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -46,7 +46,6 @@ obj-m += gb-hid.o obj-m += gb-raw.o obj-m += gb-es2.o obj-m += gb-arche.o -obj-m += gb-audio-codec.o ifeq ($(CONFIG_SND_SOC_DYNAMIC_DAILINK),y) obj-m += gb-audio-codec.o endif -- cgit v0.10.2 From 2a70e49f9183d72287e84ac4d6a4080e3f2a6475 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal Date: Wed, 13 Jan 2016 14:07:50 -0700 Subject: greybus: audio: Use greybus connection device for codec registration Use GB Audio mgmt, data protocol ids to register codec module with GB protocol. And in response to mgmt->connection_init(), register GB codec driver with ASoC. Now, using msm8994 machine to register DAI link dynamically on codec insertion. ToDos: - snd_soc_register_codec() uses driver->name to identify device id. However, for GB device, .driver{} is not yet populated by GB core. Thus, defining dummy structure within codec driver. This should come from GB core itself. Even existing .driver{} may cause problem in case of multiple modules inserted or inserted at a different slot. - Fix logic for gbcodec->dais & gbcodec->dailinks. Current implementation contains some hard coded data with assumption of count=1. - Evaluate definition of 'gbaudio_dailink.be_id' in case of multiple DAI links. Signed-off-by: Vaibhav Agarwal Signed-off-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 826604a..fd94042 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -5,10 +5,20 @@ * * Released under the GPLv2 only. */ +#include #include +#include +#include +#include #include "audio_codec.h" +#define GB_AUDIO_MGMT_DRIVER_NAME "gb_audio_mgmt" +#define GB_AUDIO_DATA_DRIVER_NAME "gb_audio_data" + +static DEFINE_MUTEX(gb_codec_list_lock); +static LIST_HEAD(gb_codec_list); + static int gbcodec_event_spk(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { @@ -190,10 +200,7 @@ static struct snd_soc_dai_driver gbcodec_dai = { static int gbcodec_probe(struct snd_soc_codec *codec) { - struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec); - - gbcodec->codec = codec; - + /* Empty function for now */ return 0; } @@ -263,53 +270,412 @@ static struct snd_soc_codec_driver soc_codec_dev_gbcodec = { .num_dapm_routes = ARRAY_SIZE(gbcodec_dapm_routes), }; -static int gbaudio_codec_probe(struct platform_device *pdev) +/* + * GB codec DAI link related + */ +static struct snd_soc_dai_link gbaudio_dailink = { + .name = "PRI_MI2S_RX", + .stream_name = "Primary MI2S Playback", + .platform_name = "msm-pcm-routing", + .cpu_dai_name = "msm-dai-q6-mi2s.0", + .no_pcm = 1, + .be_id = 34, +}; + +static void gbaudio_remove_dailinks(struct gbaudio_codec_info *gbcodec) +{ + int i; + + for (i = 0; i < gbcodec->num_dai_links; i++) { + dev_dbg(gbcodec->dev, "Remove %s: DAI link\n", + gbcodec->dailink_name[i]); + devm_kfree(gbcodec->dev, gbcodec->dailink_name[i]); + gbcodec->dailink_name[i] = NULL; + } + gbcodec->num_dai_links = 0; +} + +static int gbaudio_add_dailinks(struct gbaudio_codec_info *gbcodec) +{ + int ret, i; + char *dai_link_name; + struct snd_soc_dai_link *dai; + struct device *dev = gbcodec->dev; + + dai = &gbaudio_dailink; + dai->codec_name = gbcodec->name; + + /* FIXME + * allocate memory for DAI links based on count. + * currently num_dai_links=1, so using static struct + */ + gbcodec->num_dai_links = 1; + + for (i = 0; i < gbcodec->num_dai_links; i++) { + gbcodec->dailink_name[i] = dai_link_name = + devm_kzalloc(dev, NAME_SIZE, GFP_KERNEL); + snprintf(dai_link_name, NAME_SIZE, "GB %d.%d PRI_MI2S_RX", + gbcodec->dev_id, i); + dai->name = dai_link_name; + dai->codec_dai_name = gbcodec->dais[i].name; + } + + ret = msm8994_add_dailink("msm8994-tomtom-mtp-snd-card", dai, 1); + if (ret) { + dev_err(dev, "%d:Error while adding DAI link\n", ret); + goto err_dai_link; + } + + return ret; + +err_dai_link: + gbcodec->num_dai_links = i; + gbaudio_remove_dailinks(gbcodec); + return ret; +} + +/* + * gb_snd management functions + */ +static struct gbaudio_codec_info *gbaudio_find_codec(struct device *dev, + int dev_id) +{ + struct gbaudio_codec_info *tmp, *ret; + + mutex_lock(&gb_codec_list_lock); + list_for_each_entry_safe(ret, tmp, &gb_codec_list, list) { + dev_dbg(dev, "%d:device found\n", ret->dev_id); + if (ret->dev_id == dev_id) { + mutex_unlock(&gb_codec_list_lock); + return ret; + } + } + mutex_unlock(&gb_codec_list_lock); + return NULL; +} + +static struct gbaudio_codec_info *gbaudio_get_codec(struct device *dev, + int dev_id) +{ + struct gbaudio_codec_info *gbcodec; + + gbcodec = gbaudio_find_codec(dev, dev_id); + if (gbcodec) + return gbcodec; + + gbcodec = devm_kzalloc(dev, sizeof(*gbcodec), GFP_KERNEL); + if (!gbcodec) + return NULL; + + mutex_init(&gbcodec->lock); + INIT_LIST_HEAD(&gbcodec->dai_list); + gbcodec->dev_id = dev_id; + dev_set_drvdata(dev, gbcodec); + gbcodec->dev = dev; + strlcpy(gbcodec->name, dev_name(dev), NAME_SIZE); + + mutex_lock(&gb_codec_list_lock); + list_add(&gbcodec->list, &gb_codec_list); + mutex_unlock(&gb_codec_list_lock); + dev_dbg(dev, "%d:%s Added to codec list\n", gbcodec->dev_id, + gbcodec->name); + + return gbcodec; +} + +static void gbaudio_free_codec(struct device *dev, + struct gbaudio_codec_info *gbcodec) +{ + mutex_lock(&gb_codec_list_lock); + if (!gbcodec->mgmt_connection && + list_empty(&gbcodec->dai_list)) { + list_del(&gbcodec->list); + mutex_unlock(&gb_codec_list_lock); + dev_set_drvdata(dev, NULL); + devm_kfree(dev, gbcodec); + } else { + mutex_unlock(&gb_codec_list_lock); + } +} + +/* + * This is the basic hook get things initialized and registered w/ gb + */ + +/* + * GB codec module driver ops + */ +struct device_driver gb_codec_driver = { + .name = "1-8", + .owner = THIS_MODULE, +}; + +static int gbaudio_codec_probe(struct gb_connection *connection) { int ret; struct gbaudio_codec_info *gbcodec; - char dai_name[NAME_SIZE]; + struct device *dev = &connection->bundle->dev; + int dev_id = connection->bundle->id; - gbcodec = devm_kzalloc(&pdev->dev, sizeof(struct gbaudio_codec_info), - GFP_KERNEL); + dev_dbg(dev, "Add device:%d:%s\n", dev_id, dev_name(dev)); + /* get gbcodec data */ + gbcodec = gbaudio_get_codec(dev, dev_id); if (!gbcodec) return -ENOMEM; - platform_set_drvdata(pdev, gbcodec); - snprintf(dai_name, NAME_SIZE, "%s.%d", "gbcodec_pcm", pdev->id); - gbcodec_dai.name = dai_name; + gbcodec->mgmt_connection = connection; + + /* update DAI info */ + gbcodec->dais = &gbcodec_dai; + /* FIXME */ + dev->driver = &gb_codec_driver; + + /* register codec */ + ret = snd_soc_register_codec(dev, &soc_codec_dev_gbcodec, + gbcodec->dais, 1); + if (ret) { + dev_err(dev, "%d:Failed to register codec\n", ret); + goto base_error; + } + + /* update DAI links in response to this codec */ + ret = gbaudio_add_dailinks(gbcodec); + if (ret) { + dev_err(dev, "%d: Failed to add DAI links\n", ret); + goto codec_reg_error; + } + + /* set registered flag */ + mutex_lock(&gbcodec->lock); + gbcodec->codec_registered = 1; - ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_gbcodec, - &gbcodec_dai, 1); - if (!ret) - gbcodec->registered = 1; + mutex_unlock(&gbcodec->lock); return ret; + +codec_reg_error: + snd_soc_unregister_codec(dev); +base_error: + dev->driver = NULL; + gbcodec->mgmt_connection = NULL; + return ret; } -static const struct of_device_id gbcodec_of_match[] = { - { .compatible = "greybus,codec", }, - {}, +static void gbaudio_codec_remove(struct gb_connection *connection) +{ + struct gbaudio_codec_info *gbcodec; + struct device *dev = &connection->bundle->dev; + int dev_id = connection->bundle->id; + + dev_dbg(dev, "Remove device:%d:%s\n", dev_id, dev_name(dev)); + + /* get gbcodec data */ + gbcodec = gbaudio_find_codec(dev, dev_id); + if (!gbcodec) + return; + + msm8994_remove_dailink("msm8994-tomtom-mtp-snd-card", &gbaudio_dailink, + 1); + gbaudio_remove_dailinks(gbcodec); + + snd_soc_unregister_codec(dev); + dev->driver = NULL; + gbcodec->mgmt_connection = NULL; + mutex_lock(&gbcodec->lock); + gbcodec->codec_registered = 0; + mutex_unlock(&gbcodec->lock); + gbaudio_free_codec(dev, gbcodec); +} + +static int gbaudio_codec_report_event_recv(u8 type, struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_audio_streaming_event_request *req = op->request->payload; + + dev_warn(&connection->bundle->dev, + "Audio Event received: cport: %u, event: %u\n", + req->data_cport, req->event); + + return 0; +} + +static struct gb_protocol gb_audio_mgmt_protocol = { + .name = GB_AUDIO_MGMT_DRIVER_NAME, + .id = GREYBUS_PROTOCOL_AUDIO_MGMT, + .major = 0, + .minor = 1, + .connection_init = gbaudio_codec_probe, + .connection_exit = gbaudio_codec_remove, + .request_recv = gbaudio_codec_report_event_recv, }; -static int gbaudio_codec_remove(struct platform_device *pdev) +static struct gbaudio_dai *gbaudio_allocate_dai(struct gbaudio_codec_info *gb, + int data_cport, + struct gb_connection *connection, + const char *name) +{ + struct gbaudio_dai *dai; + + mutex_lock(&gb->lock); + dai = devm_kzalloc(gb->dev, sizeof(*dai), GFP_KERNEL); + if (!dai) { + dev_err(gb->dev, "%s:DAI Malloc failure\n", name); + mutex_unlock(&gb->lock); + return NULL; + } + + dai->data_cport = data_cport; + dai->connection = connection; + + /* update name */ + if (name) + strlcpy(dai->name, name, NAME_SIZE); + list_add(&dai->list, &gb->dai_list); + dev_dbg(gb->dev, "%d:%s: DAI added\n", data_cport, dai->name); + mutex_unlock(&gb->lock); + + return dai; +} + +struct gbaudio_dai *gbaudio_add_dai(struct gbaudio_codec_info *gbcodec, + int data_cport, + struct gb_connection *connection, + const char *name) +{ + struct gbaudio_dai *dai, *_dai; + + /* FIXME need to take care for multiple DAIs */ + mutex_lock(&gbcodec->lock); + if (list_empty(&gbcodec->dai_list)) { + mutex_unlock(&gbcodec->lock); + return gbaudio_allocate_dai(gbcodec, data_cport, connection, + name); + } + + list_for_each_entry_safe(dai, _dai, &gbcodec->dai_list, list) { + if (dai->data_cport == data_cport) { + if (connection) + dai->connection = connection; + + if (name) + strlcpy(dai->name, name, NAME_SIZE); + dev_dbg(gbcodec->dev, "%d:%s: DAI updated\n", + data_cport, dai->name); + mutex_unlock(&gbcodec->lock); + return dai; + } + } + + dev_err(gbcodec->dev, "%s:DAI not found\n", name); + mutex_unlock(&gbcodec->lock); + return NULL; +} + +static int gbaudio_dai_probe(struct gb_connection *connection) { - snd_soc_unregister_codec(&pdev->dev); + struct gbaudio_dai *dai; + struct device *dev = &connection->bundle->dev; + int dev_id = connection->bundle->id; + struct gbaudio_codec_info *gbcodec = dev_get_drvdata(dev); + + dev_dbg(dev, "Add DAI device:%d:%s\n", dev_id, dev_name(dev)); + + /* get gbcodec data */ + gbcodec = gbaudio_get_codec(dev, dev_id); + if (!gbcodec) + return -ENOMEM; + + /* add/update dai_list*/ + dai = gbaudio_add_dai(gbcodec, connection->intf_cport_id, connection, + NULL); + if (!dai) + return -ENOMEM; + + /* update dai_added count */ + mutex_lock(&gbcodec->lock); + gbcodec->dai_added++; + mutex_unlock(&gbcodec->lock); return 0; } -static struct platform_driver gbaudio_codec_driver = { - .driver = { - .name = "gbaudio-codec", - .owner = THIS_MODULE, - .of_match_table = gbcodec_of_match, - }, - .probe = gbaudio_codec_probe, - .remove = gbaudio_codec_remove, +static void gbaudio_dai_remove(struct gb_connection *connection) +{ + struct device *dev = &connection->bundle->dev; + int dev_id = connection->bundle->id; + struct gbaudio_codec_info *gbcodec; + + dev_dbg(dev, "Remove DAI device:%d:%s\n", dev_id, dev_name(dev)); + + /* get gbcodec data */ + gbcodec = gbaudio_find_codec(dev, dev_id); + if (!gbcodec) + return; + + /* inform uevent to above layers */ + mutex_lock(&gbcodec->lock); + /* update dai_added count */ + gbcodec->dai_added--; + mutex_unlock(&gbcodec->lock); + + gbaudio_free_codec(dev, gbcodec); +} + +static int gbaudio_dai_report_event_recv(u8 type, struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + + dev_warn(&connection->bundle->dev, "Audio Event received\n"); + + return 0; +} + +static struct gb_protocol gb_audio_data_protocol = { + .name = GB_AUDIO_DATA_DRIVER_NAME, + .id = GREYBUS_PROTOCOL_AUDIO_DATA, + .major = 0, + .minor = 1, + .connection_init = gbaudio_dai_probe, + .connection_exit = gbaudio_dai_remove, + .request_recv = gbaudio_dai_report_event_recv, }; -module_platform_driver(gbaudio_codec_driver); -MODULE_DESCRIPTION("Greybus Audio virtual codec driver"); +/* + * This is the basic hook get things initialized and registered w/ gb + */ + +static int __init gb_audio_protocol_init(void) +{ + int err; + + err = gb_protocol_register(&gb_audio_mgmt_protocol); + if (err) { + pr_err("Can't register i2s mgmt protocol driver: %d\n", -err); + return err; + } + + err = gb_protocol_register(&gb_audio_data_protocol); + if (err) { + pr_err("Can't register Audio protocol driver: %d\n", -err); + goto err_unregister_audio_mgmt; + } + + return 0; + +err_unregister_audio_mgmt: + gb_protocol_deregister(&gb_audio_mgmt_protocol); + return err; +} +module_init(gb_audio_protocol_init); + +static void __exit gb_audio_protocol_exit(void) +{ + gb_protocol_deregister(&gb_audio_data_protocol); + gb_protocol_deregister(&gb_audio_mgmt_protocol); +} +module_exit(gb_audio_protocol_exit); + +MODULE_DESCRIPTION("Greybus Audio codec driver"); MODULE_AUTHOR("Vaibhav Agarwal "); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:gbaudio-codec"); diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index f8597b3..39bd995 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -15,6 +15,7 @@ #include "greybus_protocols.h" #define NAME_SIZE 32 +#define MAX_DAIS 2 /* APB1, APB2 */ enum { APB1_PCM = 0, @@ -67,24 +68,54 @@ static const u8 gbcodec_reg_defaults[GBCODEC_REG_COUNT] = { GBCODEC_APB2_MUX_REG_DEFAULT, }; +struct gbaudio_dai { + __le16 data_cport; + char name[NAME_SIZE]; + struct gb_connection *connection; + struct list_head list; +}; + struct gbaudio_codec_info { + /* module info */ + int dev_id; /* check if it should be bundle_id/hd_cport_id */ + int vid; + int pid; + int slot; + int type; + int dai_added; + int codec_registered; + char vstr[NAME_SIZE]; + char pstr[NAME_SIZE]; + struct list_head list; + char name[NAME_SIZE]; + + /* soc related data */ struct snd_soc_codec *codec; - - bool usable; + struct device *dev; u8 reg[GBCODEC_REG_COUNT]; - int registered; + /* dai_link related */ + char card_name[NAME_SIZE]; + char *dailink_name[MAX_DAIS]; + int num_dai_links; + + /* topology related */ + struct gb_connection *mgmt_connection; + int num_dais; int num_kcontrols; int num_dapm_widgets; int num_dapm_routes; struct snd_kcontrol_new *kctls; struct snd_soc_dapm_widget *widgets; struct snd_soc_dapm_route *routes; + struct snd_soc_dai_driver *dais; + + /* lists */ + struct list_head dai_list; struct mutex lock; }; -extern int gb_audio_gb_get_topology(struct gb_connection *connection, - struct gb_audio_topology **topology); +/* protocol related */ extern int gb_audio_gb_get_control(struct gb_connection *connection, uint8_t control_id, uint8_t index, struct gb_audio_ctl_elem_value *value); -- cgit v0.10.2 From 6339d2322c47f4b8ebabf9daf0130328ed72648b Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal Date: Wed, 13 Jan 2016 14:07:51 -0700 Subject: greybus: audio: Add topology parser for GB codec For each GB codec module inserted, DAPM widgets, kcontrols, routes and DAIs can be fetched through greybus in a binary chunk and parsed locally to create & populate DAPM graph for the specific module. It is required by each codec module to populate a minimum set of kcontrols with fixed names to support basic audio usecase. To support advanced features of codec module, the same can be polpulated with existing topology parser. However, to use them for different usecase separate mechanism (may be via MSP) is required to inform userspace about their configuration value & enable/disable sequence. ToDos: Currently, support for enumerated kcontrol/dapm control is hardcoded. Need to add complete logic within the parser. Signed-off-by: Vaibhav Agarwal Signed-off-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 9364897..b1272cb 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -29,7 +29,7 @@ gb-raw-y := raw.o gb-hid-y := hid.o gb-es2-y := es2.o gb-arche-y := arche-platform.o arche-apb-ctrl.o -gb-audio-codec-y := audio_codec.o +gb-audio-codec-y := audio_codec.o audio_topology.o gb-audio-gb-y := audio_gb.o gb-audio-apbridgea-y := audio_apbridgea.o gb-audio-manager-y += audio_manager.o diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index fd94042..239a9b6 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -19,124 +19,6 @@ static DEFINE_MUTEX(gb_codec_list_lock); static LIST_HEAD(gb_codec_list); -static int gbcodec_event_spk(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - /* Ensure GB speaker is connected */ - - return 0; -} - -static int gbcodec_event_hp(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - /* Ensure GB module supports jack slot */ - - return 0; -} - -static int gbcodec_event_int_mic(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - /* Ensure GB module supports jack slot */ - - return 0; -} - -static const struct snd_kcontrol_new gbcodec_snd_controls[] = { - SOC_DOUBLE("Playback Mute", GBCODEC_MUTE_REG, 0, 1, 1, 1), - SOC_DOUBLE("Capture Mute", GBCODEC_MUTE_REG, 4, 5, 1, 1), - SOC_DOUBLE_R("Playback Volume", GBCODEC_PB_LVOL_REG, - GBCODEC_PB_RVOL_REG, 0, 127, 0), - SOC_DOUBLE_R("Capture Volume", GBCODEC_CAP_LVOL_REG, - GBCODEC_CAP_RVOL_REG, 0, 127, 0), -}; - -static const struct snd_kcontrol_new spk_amp_ctl = - SOC_DAPM_SINGLE("Switch", GBCODEC_CTL_REG, 0, 1, 0); - -static const struct snd_kcontrol_new hp_amp_ctl = - SOC_DAPM_SINGLE("Switch", GBCODEC_CTL_REG, 1, 1, 0); - -static const struct snd_kcontrol_new mic_adc_ctl = - SOC_DAPM_SINGLE("Switch", GBCODEC_CTL_REG, 4, 1, 0); - -/* APB1-GBSPK source */ -static const char * const gbcodec_apb1_src[] = {"Stereo", "Left", "Right"}; - -static const SOC_ENUM_SINGLE_DECL( - gbcodec_apb1_rx_enum, GBCODEC_APB1_MUX_REG, 0, gbcodec_apb1_src); - -static const struct snd_kcontrol_new gbcodec_apb1_rx_mux = - SOC_DAPM_ENUM("APB1 source", gbcodec_apb1_rx_enum); - -static const SOC_ENUM_SINGLE_DECL( - gbcodec_mic_enum, GBCODEC_APB1_MUX_REG, 4, gbcodec_apb1_src); - -static const struct snd_kcontrol_new gbcodec_mic_mux = - SOC_DAPM_ENUM("MIC source", gbcodec_mic_enum); - -static const struct snd_soc_dapm_widget gbcodec_dapm_widgets[] = { - SND_SOC_DAPM_SPK("Spk", gbcodec_event_spk), - SND_SOC_DAPM_SPK("HP", gbcodec_event_hp), - SND_SOC_DAPM_MIC("Int Mic", gbcodec_event_int_mic), - - SND_SOC_DAPM_OUTPUT("SPKOUT"), - SND_SOC_DAPM_OUTPUT("HPOUT"), - - SND_SOC_DAPM_INPUT("MIC"), - SND_SOC_DAPM_INPUT("HSMIC"), - - SND_SOC_DAPM_SWITCH("SPK Amp", SND_SOC_NOPM, 0, 0, &spk_amp_ctl), - SND_SOC_DAPM_SWITCH("HP Amp", SND_SOC_NOPM, 0, 0, &hp_amp_ctl), - SND_SOC_DAPM_SWITCH("MIC ADC", SND_SOC_NOPM, 0, 0, &mic_adc_ctl), - - SND_SOC_DAPM_PGA("SPK DAC", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("HP DAC", SND_SOC_NOPM, 0, 0, NULL, 0), - - SND_SOC_DAPM_MIXER("SPK Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_MIXER("HP Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_MIXER("APB1_TX Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), - - SND_SOC_DAPM_MUX("APB1_RX Mux", SND_SOC_NOPM, 0, 0, - &gbcodec_apb1_rx_mux), - SND_SOC_DAPM_MUX("MIC Mux", SND_SOC_NOPM, 0, 0, &gbcodec_mic_mux), - - SND_SOC_DAPM_AIF_IN("APB1RX", "APBridgeA1 Playback", 0, SND_SOC_NOPM, 0, - 0), - SND_SOC_DAPM_AIF_OUT("APB1TX", "APBridgeA1 Capture", 0, SND_SOC_NOPM, 0, - 0), -}; - -static const struct snd_soc_dapm_route gbcodec_dapm_routes[] = { - /* Playback path */ - {"Spk", NULL, "SPKOUT"}, - {"SPKOUT", NULL, "SPK Amp"}, - {"SPK Amp", "Switch", "SPK DAC"}, - {"SPK DAC", NULL, "SPK Mixer"}, - - {"HP", NULL, "HPOUT"}, - {"HPOUT", NULL, "HP Amp"}, - {"HP Amp", "Switch", "HP DAC"}, - {"HP DAC", NULL, "HP Mixer"}, - - {"SPK Mixer", NULL, "APB1_RX Mux"}, - {"HP Mixer", NULL, "APB1_RX Mux"}, - - {"APB1_RX Mux", "Left", "APB1RX"}, - {"APB1_RX Mux", "Right", "APB1RX"}, - {"APB1_RX Mux", "Stereo", "APB1RX"}, - - /* Capture path */ - {"MIC", NULL, "Int Mic"}, - {"MIC", NULL, "MIC Mux"}, - {"MIC Mux", "Left", "MIC ADC"}, - {"MIC Mux", "Right", "MIC ADC"}, - {"MIC Mux", "Stereo", "MIC ADC"}, - {"MIC ADC", "Switch", "APB1_TX Mixer"}, - {"APB1_TX Mixer", NULL, "APB1TX"} -}; - static int gbcodec_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { @@ -180,24 +62,9 @@ static struct snd_soc_dai_ops gbcodec_dai_ops = { .digital_mute = gbcodec_digital_mute, }; -static struct snd_soc_dai_driver gbcodec_dai = { - .playback = { - .stream_name = "APBridgeA1 Playback", - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .capture = { - .stream_name = "APBridgeA1 Capture", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .ops = &gbcodec_dai_ops, -}; - +/* + * codec driver ops + */ static int gbcodec_probe(struct snd_soc_codec *codec) { /* Empty function for now */ @@ -261,13 +128,6 @@ static struct snd_soc_codec_driver soc_codec_dev_gbcodec = { .reg_word_size = 1, .idle_bias_off = true, - - .controls = gbcodec_snd_controls, - .num_controls = ARRAY_SIZE(gbcodec_snd_controls), - .dapm_widgets = gbcodec_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(gbcodec_dapm_widgets), - .dapm_routes = gbcodec_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(gbcodec_dapm_routes), }; /* @@ -369,6 +229,9 @@ static struct gbaudio_codec_info *gbaudio_get_codec(struct device *dev, mutex_init(&gbcodec->lock); INIT_LIST_HEAD(&gbcodec->dai_list); + INIT_LIST_HEAD(&gbcodec->widget_list); + INIT_LIST_HEAD(&gbcodec->codec_ctl_list); + INIT_LIST_HEAD(&gbcodec->widget_ctl_list); gbcodec->dev_id = dev_id; dev_set_drvdata(dev, gbcodec); gbcodec->dev = dev; @@ -412,8 +275,9 @@ struct device_driver gb_codec_driver = { static int gbaudio_codec_probe(struct gb_connection *connection) { - int ret; + int ret, i; struct gbaudio_codec_info *gbcodec; + struct gb_audio_topology *topology; struct device *dev = &connection->bundle->dev; int dev_id = connection->bundle->id; @@ -425,8 +289,35 @@ static int gbaudio_codec_probe(struct gb_connection *connection) gbcodec->mgmt_connection = connection; + /* fetch topology data */ + ret = gb_audio_gb_get_topology(connection, &topology); + if (ret) { + dev_err(gbcodec->dev, + "%d:Error while fetching topology\n", ret); + goto base_error; + } + + /* process topology data */ + ret = gbaudio_tplg_parse_data(gbcodec, topology); + if (ret) { + dev_err(dev, "%d:Error while parsing topology data\n", + ret); + goto topology_error; + } + gbcodec->topology = topology; + + /* update codec info */ + soc_codec_dev_gbcodec.controls = gbcodec->kctls; + soc_codec_dev_gbcodec.num_controls = gbcodec->num_kcontrols; + soc_codec_dev_gbcodec.dapm_widgets = gbcodec->widgets; + soc_codec_dev_gbcodec.num_dapm_widgets = gbcodec->num_dapm_widgets; + soc_codec_dev_gbcodec.dapm_routes = gbcodec->routes; + soc_codec_dev_gbcodec.num_dapm_routes = gbcodec->num_dapm_routes; + /* update DAI info */ - gbcodec->dais = &gbcodec_dai; + for (i = 0; i < gbcodec->num_dais; i++) + gbcodec->dais[i].ops = &gbcodec_dai_ops; + /* FIXME */ dev->driver = &gb_codec_driver; @@ -435,7 +326,7 @@ static int gbaudio_codec_probe(struct gb_connection *connection) gbcodec->dais, 1); if (ret) { dev_err(dev, "%d:Failed to register codec\n", ret); - goto base_error; + goto parse_error; } /* update DAI links in response to this codec */ @@ -455,8 +346,13 @@ static int gbaudio_codec_probe(struct gb_connection *connection) codec_reg_error: snd_soc_unregister_codec(dev); -base_error: dev->driver = NULL; +parse_error: + gbaudio_tplg_release(gbcodec); + gbcodec->topology = NULL; +topology_error: + kfree(topology); +base_error: gbcodec->mgmt_connection = NULL; return ret; } @@ -480,6 +376,8 @@ static void gbaudio_codec_remove(struct gb_connection *connection) snd_soc_unregister_codec(dev); dev->driver = NULL; + gbaudio_tplg_release(gbcodec); + kfree(gbcodec->topology); gbcodec->mgmt_connection = NULL; mutex_lock(&gbcodec->lock); gbcodec->codec_registered = 0; @@ -509,68 +407,6 @@ static struct gb_protocol gb_audio_mgmt_protocol = { .request_recv = gbaudio_codec_report_event_recv, }; -static struct gbaudio_dai *gbaudio_allocate_dai(struct gbaudio_codec_info *gb, - int data_cport, - struct gb_connection *connection, - const char *name) -{ - struct gbaudio_dai *dai; - - mutex_lock(&gb->lock); - dai = devm_kzalloc(gb->dev, sizeof(*dai), GFP_KERNEL); - if (!dai) { - dev_err(gb->dev, "%s:DAI Malloc failure\n", name); - mutex_unlock(&gb->lock); - return NULL; - } - - dai->data_cport = data_cport; - dai->connection = connection; - - /* update name */ - if (name) - strlcpy(dai->name, name, NAME_SIZE); - list_add(&dai->list, &gb->dai_list); - dev_dbg(gb->dev, "%d:%s: DAI added\n", data_cport, dai->name); - mutex_unlock(&gb->lock); - - return dai; -} - -struct gbaudio_dai *gbaudio_add_dai(struct gbaudio_codec_info *gbcodec, - int data_cport, - struct gb_connection *connection, - const char *name) -{ - struct gbaudio_dai *dai, *_dai; - - /* FIXME need to take care for multiple DAIs */ - mutex_lock(&gbcodec->lock); - if (list_empty(&gbcodec->dai_list)) { - mutex_unlock(&gbcodec->lock); - return gbaudio_allocate_dai(gbcodec, data_cport, connection, - name); - } - - list_for_each_entry_safe(dai, _dai, &gbcodec->dai_list, list) { - if (dai->data_cport == data_cport) { - if (connection) - dai->connection = connection; - - if (name) - strlcpy(dai->name, name, NAME_SIZE); - dev_dbg(gbcodec->dev, "%d:%s: DAI updated\n", - data_cport, dai->name); - mutex_unlock(&gbcodec->lock); - return dai; - } - } - - dev_err(gbcodec->dev, "%s:DAI not found\n", name); - mutex_unlock(&gbcodec->lock); - return NULL; -} - static int gbaudio_dai_probe(struct gb_connection *connection) { struct gbaudio_dai *dai; diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index 39bd995..5051e06 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -68,6 +68,19 @@ static const u8 gbcodec_reg_defaults[GBCODEC_REG_COUNT] = { GBCODEC_APB2_MUX_REG_DEFAULT, }; +struct gbaudio_widget { + __u8 id; + const char *name; + struct list_head list; +}; + +struct gbaudio_control { + __u8 id; + char *name; + const char * const *texts; + struct list_head list; +}; + struct gbaudio_dai { __le16 data_cport; char name[NAME_SIZE]; @@ -87,6 +100,7 @@ struct gbaudio_codec_info { char vstr[NAME_SIZE]; char pstr[NAME_SIZE]; struct list_head list; + struct gb_audio_topology *topology; char name[NAME_SIZE]; /* soc related data */ @@ -105,6 +119,10 @@ struct gbaudio_codec_info { int num_kcontrols; int num_dapm_widgets; int num_dapm_routes; + unsigned long dai_offset; + unsigned long widget_offset; + unsigned long control_offset; + unsigned long route_offset; struct snd_kcontrol_new *kctls; struct snd_soc_dapm_widget *widgets; struct snd_soc_dapm_route *routes; @@ -112,10 +130,23 @@ struct gbaudio_codec_info { /* lists */ struct list_head dai_list; + struct list_head widget_list; + struct list_head codec_ctl_list; + struct list_head widget_ctl_list; struct mutex lock; }; +struct gbaudio_dai *gbaudio_add_dai(struct gbaudio_codec_info *gbcodec, + int data_cport, + struct gb_connection *connection, + const char *name); +int gbaudio_tplg_parse_data(struct gbaudio_codec_info *gbcodec, + struct gb_audio_topology *tplg_data); +void gbaudio_tplg_release(struct gbaudio_codec_info *gbcodec); + /* protocol related */ +extern int gb_audio_gb_get_topology(struct gb_connection *connection, + struct gb_audio_topology **topology); extern int gb_audio_gb_get_control(struct gb_connection *connection, uint8_t control_id, uint8_t index, struct gb_audio_ctl_elem_value *value); diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c new file mode 100644 index 0000000..8840a9c --- /dev/null +++ b/drivers/staging/greybus/audio_topology.c @@ -0,0 +1,1114 @@ +/* + * Greybus audio driver + * Copyright 2015-2016 Google Inc. + * Copyright 2015-2016 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include "audio_codec.h" +#include "greybus_protocols.h" + +#define GBAUDIO_INVALID_ID 0xFF + +/* mixer control */ +struct gb_mixer_control { + int min, max; + unsigned int reg, rreg, shift, rshift, invert; +}; + +struct gbaudio_ctl_pvt { + unsigned int ctl_id; + unsigned int data_cport; + unsigned int access; + unsigned int vcount; + struct gb_audio_ctl_elem_info *info; +}; + +static const char *gbaudio_map_controlid(struct gbaudio_codec_info *gbcodec, + __u8 control_id, __u8 index) +{ + struct gbaudio_control *control; + + if (control_id == GBAUDIO_INVALID_ID) + return NULL; + + list_for_each_entry(control, &gbcodec->codec_ctl_list, list) { + if (control->id == control_id) { + if (index == GBAUDIO_INVALID_ID) + return control->name; + return control->texts[index]; + } + } + list_for_each_entry(control, &gbcodec->widget_ctl_list, list) { + if (control->id == control_id) { + if (index == GBAUDIO_INVALID_ID) + return control->name; + return control->texts[index]; + } + } + return NULL; +} + +static int gbaudio_map_widgetname(struct gbaudio_codec_info *gbcodec, + const char *name) +{ + struct gbaudio_widget *widget; + char widget_name[NAME_SIZE]; + char prefix_name[NAME_SIZE]; + + snprintf(prefix_name, NAME_SIZE, "GB %d ", gbcodec->dev_id); + if (strncmp(name, prefix_name, strlen(prefix_name))) + return -EINVAL; + + strlcpy(widget_name, name+strlen(prefix_name), NAME_SIZE); + dev_dbg(gbcodec->dev, "widget_name:%s, truncated widget_name:%s\n", + name, widget_name); + + list_for_each_entry(widget, &gbcodec->widget_list, list) { + if (!strncmp(widget->name, widget_name, NAME_SIZE)) + return widget->id; + } + return -EINVAL; +} + +static const char *gbaudio_map_widgetid(struct gbaudio_codec_info *gbcodec, + __u8 widget_id) +{ + struct gbaudio_widget *widget; + + list_for_each_entry(widget, &gbcodec->widget_list, list) { + if (widget->id == widget_id) + return widget->name; + } + return NULL; +} + +static int gbcodec_mixer_ctl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + unsigned int max; + const char *name; + struct gbaudio_ctl_pvt *data; + struct gb_audio_ctl_elem_info *info; + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec); + + data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; + info = (struct gb_audio_ctl_elem_info *)data->info; + + if (!info) { + dev_err(gbcodec->dev, "NULL info for %s\n", uinfo->id.name); + return -EINVAL; + } + + /* update uinfo */ + uinfo->access = data->access; + uinfo->count = data->vcount; + uinfo->type = (snd_ctl_elem_type_t)info->type; + + switch (info->type) { + case GB_AUDIO_CTL_ELEM_TYPE_BOOLEAN: + case GB_AUDIO_CTL_ELEM_TYPE_INTEGER: + uinfo->value.integer.min = info->value.integer.min; + uinfo->value.integer.max = info->value.integer.max; + break; + case GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED: + max = info->value.enumerated.items; + uinfo->value.enumerated.items = max; + if (uinfo->value.enumerated.item > max - 1) + uinfo->value.enumerated.item = max - 1; + name = gbaudio_map_controlid(gbcodec, data->ctl_id, + uinfo->value.enumerated.item); + strlcpy(uinfo->value.enumerated.name, name, NAME_SIZE); + break; + default: + dev_err(codec->dev, "Invalid type: %d for %s:kcontrol\n", + info->type, kcontrol->id.name); + break; + } + return 0; +} + +static int gbcodec_mixer_ctl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret; + struct gb_audio_ctl_elem_info *info; + struct gbaudio_ctl_pvt *data; + struct gb_audio_ctl_elem_value gbvalue; + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + + data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; + info = (struct gb_audio_ctl_elem_info *)data->info; + + ret = gb_audio_gb_get_control(gb->mgmt_connection, data->ctl_id, + GB_AUDIO_INVALID_INDEX, &gbvalue); + if (ret) { + dev_err(codec->dev, "%d:Error in %s for %s\n", ret, __func__, + kcontrol->id.name); + return ret; + } + + /* update ucontrol */ + switch (info->type) { + case GB_AUDIO_CTL_ELEM_TYPE_BOOLEAN: + case GB_AUDIO_CTL_ELEM_TYPE_INTEGER: + ucontrol->value.integer.value[0] = + gbvalue.value.integer_value[0]; + if (data->vcount == 2) + ucontrol->value.integer.value[1] = + gbvalue.value.integer_value[1]; + break; + case GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED: + ucontrol->value.enumerated.item[0] = + gbvalue.value.enumerated_item[0]; + if (data->vcount == 2) + ucontrol->value.enumerated.item[1] = + gbvalue.value.enumerated_item[1]; + break; + default: + dev_err(codec->dev, "Invalid type: %d for %s:kcontrol\n", + info->type, kcontrol->id.name); + ret = -EINVAL; + break; + } + return ret; +} + +static int gbcodec_mixer_ctl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret = 0; + struct gb_audio_ctl_elem_info *info; + struct gbaudio_ctl_pvt *data; + struct gb_audio_ctl_elem_value gbvalue; + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + + data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; + info = (struct gb_audio_ctl_elem_info *)data->info; + + /* update ucontrol */ + switch (info->type) { + case GB_AUDIO_CTL_ELEM_TYPE_BOOLEAN: + case GB_AUDIO_CTL_ELEM_TYPE_INTEGER: + gbvalue.value.integer_value[0] = + ucontrol->value.integer.value[0]; + if (data->vcount == 2) + gbvalue.value.integer_value[1] = + ucontrol->value.integer.value[1]; + break; + case GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED: + gbvalue.value.enumerated_item[0] = + ucontrol->value.enumerated.item[0]; + if (data->vcount == 2) + gbvalue.value.enumerated_item[1] = + ucontrol->value.enumerated.item[1]; + break; + default: + dev_err(codec->dev, "Invalid type: %d for %s:kcontrol\n", + info->type, kcontrol->id.name); + ret = -EINVAL; + break; + } + + if (ret) + return ret; + + ret = gb_audio_gb_set_control(gb->mgmt_connection, data->ctl_id, + GB_AUDIO_INVALID_INDEX, &gbvalue); + if (ret) { + dev_err(codec->dev, "%d:Error in %s for %s\n", ret, __func__, + kcontrol->id.name); + } + + return ret; +} + +#define SOC_MIXER_GB(xname, kcount, data) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ + .count = kcount, .info = gbcodec_mixer_ctl_info, \ + .get = gbcodec_mixer_ctl_get, .put = gbcodec_mixer_ctl_put, \ + .private_value = (unsigned long)data } + +/* + * although below callback functions seems redundant to above functions. + * same are kept to allow provision for different handling in case + * of DAPM related sequencing, etc. + */ +static int gbcodec_mixer_dapm_ctl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + int platform_max, platform_min; + struct gbaudio_ctl_pvt *data; + struct gb_audio_ctl_elem_info *info; + + data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; + info = (struct gb_audio_ctl_elem_info *)data->info; + + /* update uinfo */ + platform_max = info->value.integer.max; + platform_min = info->value.integer.min; + + if (platform_max == 1 && + !strnstr(kcontrol->id.name, " Volume", NAME_SIZE)) + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + else + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + + uinfo->count = data->vcount; + uinfo->value.integer.min = 0; + if (info->value.integer.min < 0 && + (uinfo->type == SNDRV_CTL_ELEM_TYPE_INTEGER)) + uinfo->value.integer.max = platform_max - platform_min; + else + uinfo->value.integer.max = platform_max; + + return 0; +} + +static int gbcodec_mixer_dapm_ctl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret; + struct gb_audio_ctl_elem_info *info; + struct gbaudio_ctl_pvt *data; + struct gb_audio_ctl_elem_value gbvalue; + struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); + struct snd_soc_dapm_widget *widget = wlist->widgets[0]; + struct snd_soc_codec *codec = widget->codec; + struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + + data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; + info = (struct gb_audio_ctl_elem_info *)data->info; + + if (data->vcount == 2) + dev_warn(widget->dapm->dev, + "GB: Control '%s' is stereo, which is not supported\n", + kcontrol->id.name); + + ret = gb_audio_gb_get_control(gb->mgmt_connection, data->ctl_id, + GB_AUDIO_INVALID_INDEX, &gbvalue); + if (ret) { + dev_err(codec->dev, "%d:Error in %s for %s\n", ret, __func__, + kcontrol->id.name); + return ret; + } + /* update ucontrol */ + ucontrol->value.integer.value[0] = gbvalue.value.integer_value[0]; + + return ret; +} + +static int gbcodec_mixer_dapm_ctl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret, wi, max, connect; + unsigned int mask, val; + struct gb_audio_ctl_elem_info *info; + struct gbaudio_ctl_pvt *data; + struct gb_audio_ctl_elem_value gbvalue; + struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); + struct snd_soc_dapm_widget *widget = wlist->widgets[0]; + struct snd_soc_codec *codec = widget->codec; + struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + + data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; + info = (struct gb_audio_ctl_elem_info *)data->info; + + if (data->vcount == 2) + dev_warn(widget->dapm->dev, + "GB: Control '%s' is stereo, which is not supported\n", + kcontrol->id.name); + + max = info->value.integer.max; + mask = (1 << fls(max)) - 1; + val = (ucontrol->value.integer.value[0] & mask); + connect = !!val; + + /* update ucontrol */ + if (gbvalue.value.integer_value[0] != val) { + for (wi = 0; wi < wlist->num_widgets; wi++) { + widget = wlist->widgets[wi]; + + widget->value = val; + widget->dapm->update = NULL; + snd_soc_dapm_mixer_update_power(widget, kcontrol, + connect); + } + gbvalue.value.integer_value[0] = + ucontrol->value.integer.value[0]; + ret = gb_audio_gb_set_control(gb->mgmt_connection, + data->ctl_id, + GB_AUDIO_INVALID_INDEX, &gbvalue); + if (ret) { + dev_err(codec->dev, + "%d:Error in %s for %s\n", ret, __func__, + kcontrol->id.name); + } + } + + return ret; +} + +#define SOC_DAPM_MIXER_GB(xname, kcount, data) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ + .count = kcount, .info = gbcodec_mixer_dapm_ctl_info, \ + .get = gbcodec_mixer_dapm_ctl_get, .put = gbcodec_mixer_dapm_ctl_put, \ + .private_value = (unsigned long)data} + +static int gbcodec_event_spk(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + /* Ensure GB speaker is connected */ + + return 0; +} + +static int gbcodec_event_hp(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + /* Ensure GB module supports jack slot */ + + return 0; +} + +static int gbcodec_event_int_mic(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + /* Ensure GB module supports jack slot */ + + return 0; +} + +static int gbaudio_validate_kcontrol_count(struct gb_audio_widget *w) +{ + int ret = 0; + + switch (w->type) { + case snd_soc_dapm_spk: + case snd_soc_dapm_hp: + case snd_soc_dapm_mic: + case snd_soc_dapm_output: + case snd_soc_dapm_input: + if (w->ncontrols) + ret = -EINVAL; + break; + case snd_soc_dapm_switch: + case snd_soc_dapm_mux: + if (w->ncontrols != 1) + ret = -EINVAL; + break; + default: + break; + } + + return ret; +} + +static int gbaudio_tplg_create_kcontrol(struct gbaudio_codec_info *gb, + struct snd_kcontrol_new *kctl, + struct gb_audio_control *ctl) +{ + struct gbaudio_ctl_pvt *ctldata; + + switch (ctl->iface) { + case SNDRV_CTL_ELEM_IFACE_MIXER: + ctldata = devm_kzalloc(gb->dev, sizeof(struct gbaudio_ctl_pvt), + GFP_KERNEL); + if (!ctldata) + return -ENOMEM; + ctldata->ctl_id = ctl->id; + ctldata->data_cport = ctl->data_cport; + ctldata->access = ctl->access; + ctldata->vcount = ctl->count_values; + ctldata->info = &ctl->info; + *kctl = (struct snd_kcontrol_new) + SOC_MIXER_GB(ctl->name, ctl->count, ctldata); + ctldata = NULL; + break; + default: + return -EINVAL; + } + + dev_dbg(gb->dev, "%s:%d control created\n", ctl->name, ctl->id); + return 0; +} + +static const char * const gbtexts[] = {"Stereo", "Left", "Right"}; + +static const SOC_ENUM_SINGLE_DECL( + gbcodec_apb1_rx_enum, GBCODEC_APB1_MUX_REG, 0, gbtexts); + +static const SOC_ENUM_SINGLE_DECL( + gbcodec_mic_enum, GBCODEC_APB1_MUX_REG, 4, gbtexts); + +static int gbaudio_tplg_create_enum_ctl(struct gbaudio_codec_info *gb, + struct snd_kcontrol_new *kctl, + struct gb_audio_control *ctl) +{ + switch (ctl->id) { + case 8: + *kctl = (struct snd_kcontrol_new) + SOC_DAPM_ENUM(ctl->name, gbcodec_apb1_rx_enum); + break; + case 9: + *kctl = (struct snd_kcontrol_new) + SOC_DAPM_ENUM(ctl->name, gbcodec_mic_enum); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int gbaudio_tplg_create_mixer_ctl(struct gbaudio_codec_info *gb, + struct snd_kcontrol_new *kctl, + struct gb_audio_control *ctl) +{ + struct gbaudio_ctl_pvt *ctldata; + + ctldata = devm_kzalloc(gb->dev, sizeof(struct gbaudio_ctl_pvt), + GFP_KERNEL); + if (!ctldata) + return -ENOMEM; + ctldata->ctl_id = ctl->id; + ctldata->data_cport = ctl->data_cport; + ctldata->access = ctl->access; + ctldata->vcount = ctl->count_values; + ctldata->info = &ctl->info; + *kctl = (struct snd_kcontrol_new) + SOC_DAPM_MIXER_GB(ctl->name, ctl->count, ctldata); + + return 0; +} + +static int gbaudio_tplg_create_wcontrol(struct gbaudio_codec_info *gb, + struct snd_kcontrol_new *kctl, + struct gb_audio_control *ctl) +{ + int ret; + + switch (ctl->iface) { + case 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); + break; + default: + ret = gbaudio_tplg_create_mixer_ctl(gb, kctl, ctl); + break; + } + break; + default: + return -EINVAL; + + } + + dev_dbg(gb->dev, "%s:%d DAPM control created, ret:%d\n", ctl->name, + ctl->id, ret); + return ret; +} + +static int gbaudio_widget_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + int wid; + int ret; + struct snd_soc_codec *codec = w->codec; + struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec); + + dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event); + + /* map name to widget id */ + wid = gbaudio_map_widgetname(gbcodec, w->name); + if (wid < 0) { + dev_err(codec->dev, "Invalid widget name:%s\n", w->name); + return -EINVAL; + } + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + ret = gb_audio_gb_enable_widget(gbcodec->mgmt_connection, wid); + break; + case SND_SOC_DAPM_POST_PMD: + ret = gb_audio_gb_disable_widget(gbcodec->mgmt_connection, wid); + break; + } + if (ret) + dev_err(codec->dev, "%d: widget, event:%d failed:%d\n", wid, + event, ret); + return ret; +} + +static int gbaudio_tplg_create_widget(struct gbaudio_codec_info *gbcodec, + struct snd_soc_dapm_widget *dw, + struct gb_audio_widget *w) +{ + int i, ret; + struct snd_kcontrol_new *widget_kctls; + struct gb_audio_control *curr; + struct gbaudio_control *control, *_control; + size_t size; + + ret = gbaudio_validate_kcontrol_count(w); + if (ret) { + dev_err(gbcodec->dev, "Inavlid kcontrol count=%d for %s\n", + w->ncontrols, w->name); + return ret; + } + + /* allocate memory for kcontrol */ + if (w->ncontrols) { + size = sizeof(struct snd_kcontrol_new) * w->ncontrols; + widget_kctls = devm_kzalloc(gbcodec->dev, size, GFP_KERNEL); + if (!widget_kctls) + return -ENOMEM; + } + + /* create relevant kcontrols */ + for (i = 0; i < w->ncontrols; i++) { + curr = &w->ctl[i]; + ret = gbaudio_tplg_create_wcontrol(gbcodec, &widget_kctls[i], + curr); + if (ret) { + dev_err(gbcodec->dev, + "%s:%d type widget_ctl not supported\n", + curr->name, curr->iface); + goto error; + } + control = devm_kzalloc(gbcodec->dev, + sizeof(struct gbaudio_control), + GFP_KERNEL); + if (!control) { + ret = -ENOMEM; + goto error; + } + control->id = curr->id; + control->name = curr->name; + if (curr->info.type == GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED) + control->texts = (const char * const *) + curr->info.value.enumerated.names; + list_add(&control->list, &gbcodec->widget_ctl_list); + dev_dbg(gbcodec->dev, "%s: control of type %d created\n", + widget_kctls[i].name, widget_kctls[i].iface); + } + + switch (w->type) { + case snd_soc_dapm_spk: + *dw = (struct snd_soc_dapm_widget) + SND_SOC_DAPM_SPK(w->name, gbcodec_event_spk); + break; + case snd_soc_dapm_hp: + *dw = (struct snd_soc_dapm_widget) + SND_SOC_DAPM_HP(w->name, gbcodec_event_hp); + break; + case snd_soc_dapm_mic: + *dw = (struct snd_soc_dapm_widget) + SND_SOC_DAPM_MIC(w->name, gbcodec_event_int_mic); + break; + case snd_soc_dapm_output: + *dw = (struct snd_soc_dapm_widget)SND_SOC_DAPM_OUTPUT(w->name); + break; + case snd_soc_dapm_input: + *dw = (struct snd_soc_dapm_widget)SND_SOC_DAPM_INPUT(w->name); + break; + case snd_soc_dapm_switch: + *dw = (struct snd_soc_dapm_widget) + SND_SOC_DAPM_SWITCH_E(w->name, SND_SOC_NOPM, 0, 0, + widget_kctls, gbaudio_widget_event, + SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD); + break; + case snd_soc_dapm_pga: + *dw = (struct snd_soc_dapm_widget) + SND_SOC_DAPM_PGA_E(w->name, SND_SOC_NOPM, 0, 0, NULL, 0, + gbaudio_widget_event, + SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD); + break; + case snd_soc_dapm_mixer: + *dw = (struct snd_soc_dapm_widget) + SND_SOC_DAPM_MIXER_E(w->name, SND_SOC_NOPM, 0, 0, NULL, + 0, gbaudio_widget_event, + SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD); + break; + case snd_soc_dapm_mux: + *dw = (struct snd_soc_dapm_widget) + SND_SOC_DAPM_MUX_E(w->name, SND_SOC_NOPM, 0, 0, + widget_kctls, gbaudio_widget_event, + SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD); + break; + case snd_soc_dapm_aif_in: + *dw = (struct snd_soc_dapm_widget) + SND_SOC_DAPM_AIF_IN_E(w->name, w->sname, 0, + SND_SOC_NOPM, + 0, 0, gbaudio_widget_event, + SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD); + break; + case snd_soc_dapm_aif_out: + *dw = (struct snd_soc_dapm_widget) + SND_SOC_DAPM_AIF_OUT_E(w->name, w->sname, 0, + SND_SOC_NOPM, + 0, 0, gbaudio_widget_event, + SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD); + break; + default: + ret = -EINVAL; + goto error; + } + + dev_dbg(gbcodec->dev, "%s: widget of type %d created\n", dw->name, + dw->id); + return 0; +error: + list_for_each_entry_safe(control, _control, &gbcodec->widget_ctl_list, + list) { + list_del(&control->list); + devm_kfree(gbcodec->dev, control); + } + return ret; +} + +static int gbaudio_tplg_create_dai(struct gbaudio_codec_info *gbcodec, + struct snd_soc_dai_driver *gb_dai, + struct gb_audio_dai *dai) +{ + /* + * do not update name here, + * append dev_id before assigning it here + */ + + gb_dai->playback.stream_name = dai->playback.stream_name; + gb_dai->playback.channels_min = dai->playback.chan_min; + gb_dai->playback.channels_max = dai->playback.chan_max; + gb_dai->playback.formats = dai->playback.formats; + gb_dai->playback.rates = dai->playback.rates; + gb_dai->playback.sig_bits = dai->playback.sig_bits; + + gb_dai->capture.stream_name = dai->capture.stream_name; + gb_dai->capture.channels_min = dai->capture.chan_min; + gb_dai->capture.channels_max = dai->capture.chan_max; + gb_dai->capture.formats = dai->capture.formats; + gb_dai->capture.rates = dai->capture.rates; + gb_dai->capture.sig_bits = dai->capture.sig_bits; + + return 0; +} + +static int gbaudio_tplg_process_kcontrols(struct gbaudio_codec_info *gbcodec, + struct gb_audio_control *controls) +{ + int i, ret; + struct snd_kcontrol_new *dapm_kctls; + struct gb_audio_control *curr; + struct gbaudio_control *control, *_control; + size_t size; + + size = sizeof(struct snd_kcontrol_new) * gbcodec->num_kcontrols; + dapm_kctls = devm_kzalloc(gbcodec->dev, size, GFP_KERNEL); + if (!dapm_kctls) + return -ENOMEM; + + curr = controls; + for (i = 0; i < gbcodec->num_kcontrols; i++) { + ret = gbaudio_tplg_create_kcontrol(gbcodec, &dapm_kctls[i], + curr); + if (ret) { + dev_err(gbcodec->dev, "%s:%d type not supported\n", + curr->name, curr->iface); + goto error; + } + control = devm_kzalloc(gbcodec->dev, sizeof(struct + gbaudio_control), + GFP_KERNEL); + if (!control) { + ret = -ENOMEM; + goto error; + } + control->id = curr->id; + control->name = curr->name; + if (curr->info.type == GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED) + control->texts = (const char * const *) + curr->info.value.enumerated.names; + list_add(&control->list, &gbcodec->codec_ctl_list); + dev_dbg(gbcodec->dev, "%d:%s created of type %d\n", curr->id, + curr->name, curr->info.type); + curr++; + } + gbcodec->kctls = dapm_kctls; + + return 0; +error: + list_for_each_entry_safe(control, _control, &gbcodec->codec_ctl_list, + list) { + list_del(&control->list); + devm_kfree(gbcodec->dev, control); + } + devm_kfree(gbcodec->dev, dapm_kctls); + return ret; +} + +static int gbaudio_tplg_process_widgets(struct gbaudio_codec_info *gbcodec, + struct gb_audio_widget *widgets) +{ + int i, ret, ncontrols; + struct snd_soc_dapm_widget *dapm_widgets; + struct gb_audio_widget *curr; + struct gbaudio_widget *widget, *_widget; + size_t size; + + size = sizeof(struct snd_soc_dapm_widget) * gbcodec->num_dapm_widgets; + dapm_widgets = devm_kzalloc(gbcodec->dev, size, GFP_KERNEL); + if (!dapm_widgets) + return -ENOMEM; + + curr = widgets; + for (i = 0; i < gbcodec->num_dapm_widgets; i++) { + ret = gbaudio_tplg_create_widget(gbcodec, &dapm_widgets[i], + curr); + if (ret) { + dev_err(gbcodec->dev, "%s:%d type not supported\n", + curr->name, curr->type); + goto error; + } + widget = devm_kzalloc(gbcodec->dev, sizeof(struct + gbaudio_widget), + GFP_KERNEL); + if (!widget) { + ret = -ENOMEM; + goto error; + } + widget->id = curr->id; + widget->name = curr->name; + list_add(&widget->list, &gbcodec->widget_list); + ncontrols = curr->ncontrols; + curr++; + curr += ncontrols * sizeof(struct gb_audio_control); + } + gbcodec->widgets = dapm_widgets; + + return 0; + +error: + list_for_each_entry_safe(widget, _widget, &gbcodec->widget_list, + list) { + list_del(&widget->list); + devm_kfree(gbcodec->dev, widget); + } + devm_kfree(gbcodec->dev, dapm_widgets); + return ret; +} + +static int gbaudio_tplg_process_dais(struct gbaudio_codec_info *gbcodec, + struct gb_audio_dai *dais) +{ + int i, ret; + struct snd_soc_dai_driver *gb_dais; + struct gb_audio_dai *curr; + struct gbaudio_dai *dai, *_dai; + size_t size; + char dai_name[NAME_SIZE]; + + size = sizeof(struct snd_soc_dai_driver) * gbcodec->num_dais; + gb_dais = devm_kzalloc(gbcodec->dev, size, GFP_KERNEL); + if (!gb_dais) + return -ENOMEM; + + curr = dais; + for (i = 0; i < gbcodec->num_dais; i++) { + ret = gbaudio_tplg_create_dai(gbcodec, &gb_dais[i], curr); + if (ret) { + dev_err(gbcodec->dev, "%s failed to create\n", + curr->name); + goto error; + } + /* append dev_id to dai_name */ + snprintf(dai_name, NAME_SIZE, "%s.%d", curr->name, + gbcodec->dev_id); + dai = gbaudio_add_dai(gbcodec, curr->data_cport, NULL, + dai_name); + if (!dai) + goto error; + dev_err(gbcodec->dev, "%s:DAI added\n", dai->name); + gb_dais[i].name = dai->name; + curr++; + } + gbcodec->dais = gb_dais; + + return 0; + +error: + list_for_each_entry_safe(dai, _dai, &gbcodec->dai_list, list) { + list_del(&dai->list); + devm_kfree(gbcodec->dev, dai); + } + devm_kfree(gbcodec->dev, gb_dais); + return ret; +} + +static int gbaudio_tplg_process_routes(struct gbaudio_codec_info *gbcodec, + struct gb_audio_route *routes) +{ + int i, ret; + struct snd_soc_dapm_route *dapm_routes; + struct gb_audio_route *curr; + size_t size; + + size = sizeof(struct snd_soc_dapm_route) * gbcodec->num_dapm_routes; + dapm_routes = devm_kzalloc(gbcodec->dev, size, GFP_KERNEL); + if (!dapm_routes) + return -ENOMEM; + + + gbcodec->routes = dapm_routes; + curr = routes; + + for (i = 0; i < gbcodec->num_dapm_routes; i++) { + dapm_routes->sink = + gbaudio_map_widgetid(gbcodec, curr->destination_id); + if (!dapm_routes->sink) { + dev_err(gbcodec->dev, "%d:%d:%d:%d - Invalid sink\n", + curr->source_id, curr->destination_id, + curr->control_id, curr->index); + ret = -EINVAL; + goto error; + } + dapm_routes->source = + gbaudio_map_widgetid(gbcodec, curr->source_id); + if (!dapm_routes->source) { + dev_err(gbcodec->dev, "%d:%d:%d:%d - Invalid source\n", + curr->source_id, curr->destination_id, + curr->control_id, curr->index); + ret = -EINVAL; + goto error; + } + dapm_routes->control = + gbaudio_map_controlid(gbcodec, + curr->control_id, + curr->index); + if ((curr->control_id != GBAUDIO_INVALID_ID) && + !dapm_routes->control) { + dev_err(gbcodec->dev, "%d:%d:%d:%d - Invalid control\n", + curr->source_id, curr->destination_id, + curr->control_id, curr->index); + ret = -EINVAL; + goto error; + } + dev_dbg(gbcodec->dev, "Route {%s, %s, %s}\n", dapm_routes->sink, + (dapm_routes->control) ? dapm_routes->control:"NULL", + dapm_routes->source); + dapm_routes++; + curr++; + } + + return 0; + +error: + devm_kfree(gbcodec->dev, dapm_routes); + return ret; +} + +static int gbaudio_tplg_process_header(struct gbaudio_codec_info *gbcodec, + struct gb_audio_topology *tplg_data) +{ + /* fetch no. of kcontrols, widgets & routes */ + gbcodec->num_dais = tplg_data->num_dais; + gbcodec->num_kcontrols = tplg_data->num_controls; + gbcodec->num_dapm_widgets = tplg_data->num_widgets; + gbcodec->num_dapm_routes = tplg_data->num_routes; + + /* update block offset */ + gbcodec->dai_offset = (unsigned long)&tplg_data->data; + gbcodec->control_offset = gbcodec->dai_offset + tplg_data->size_dais; + gbcodec->widget_offset = gbcodec->control_offset + + tplg_data->size_controls; + gbcodec->route_offset = gbcodec->widget_offset + + tplg_data->size_widgets; + + dev_dbg(gbcodec->dev, "DAI offset is 0x%lx\n", gbcodec->dai_offset); + dev_dbg(gbcodec->dev, "control offset is %lx\n", + gbcodec->control_offset); + dev_dbg(gbcodec->dev, "widget offset is %lx\n", gbcodec->widget_offset); + dev_dbg(gbcodec->dev, "route offset is %lx\n", gbcodec->route_offset); + + return 0; +} + +static struct gbaudio_dai *gbaudio_allocate_dai(struct gbaudio_codec_info *gb, + int data_cport, + struct gb_connection *connection, + const char *name) +{ + struct gbaudio_dai *dai; + + mutex_lock(&gb->lock); + dai = devm_kzalloc(gb->dev, sizeof(*dai), GFP_KERNEL); + if (!dai) { + dev_err(gb->dev, "%s:DAI Malloc failure\n", name); + mutex_unlock(&gb->lock); + return NULL; + } + + dai->data_cport = data_cport; + dai->connection = connection; + + /* update name */ + if (name) + strlcpy(dai->name, name, NAME_SIZE); + list_add(&dai->list, &gb->dai_list); + dev_dbg(gb->dev, "%d:%s: DAI added\n", data_cport, dai->name); + mutex_unlock(&gb->lock); + + return dai; +} + +struct gbaudio_dai *gbaudio_add_dai(struct gbaudio_codec_info *gbcodec, + int data_cport, + struct gb_connection *connection, + const char *name) +{ + struct gbaudio_dai *dai, *_dai; + + /* FIXME need to take care for multiple DAIs */ + mutex_lock(&gbcodec->lock); + if (list_empty(&gbcodec->dai_list)) { + mutex_unlock(&gbcodec->lock); + return gbaudio_allocate_dai(gbcodec, data_cport, connection, + name); + } + + list_for_each_entry_safe(dai, _dai, &gbcodec->dai_list, list) { + if (dai->data_cport == data_cport) { + if (connection) + dai->connection = connection; + + if (name) + strlcpy(dai->name, name, NAME_SIZE); + dev_dbg(gbcodec->dev, "%d:%s: DAI updated\n", + data_cport, dai->name); + mutex_unlock(&gbcodec->lock); + return dai; + } + } + + dev_err(gbcodec->dev, "%s:DAI not found\n", name); + mutex_unlock(&gbcodec->lock); + return NULL; +} + +int gbaudio_tplg_parse_data(struct gbaudio_codec_info *gbcodec, + struct gb_audio_topology *tplg_data) +{ + int ret; + struct gb_audio_dai *dais; + struct gb_audio_control *controls; + struct gb_audio_widget *widgets; + struct gb_audio_route *routes; + + if (!tplg_data) + return -EINVAL; + + ret = gbaudio_tplg_process_header(gbcodec, tplg_data); + if (ret) { + dev_err(gbcodec->dev, "%d: Error in parsing topology header\n", + ret); + return ret; + } + + /* process control */ + controls = (struct gb_audio_control *)gbcodec->control_offset; + ret = gbaudio_tplg_process_kcontrols(gbcodec, controls); + if (ret) { + dev_err(gbcodec->dev, + "%d: Error in parsing controls data\n", ret); + return ret; + } + dev_err(gbcodec->dev, "Control parsing finished\n"); + + /* process DAI */ + dais = (struct gb_audio_dai *)gbcodec->dai_offset; + ret = gbaudio_tplg_process_dais(gbcodec, dais); + if (ret) { + dev_err(gbcodec->dev, + "%d: Error in parsing DAIs data\n", ret); + return ret; + } + dev_err(gbcodec->dev, "DAI parsing finished\n"); + + /* process widgets */ + widgets = (struct gb_audio_widget *)gbcodec->widget_offset; + ret = gbaudio_tplg_process_widgets(gbcodec, widgets); + if (ret) { + dev_err(gbcodec->dev, + "%d: Error in parsing widgets data\n", ret); + return ret; + } + dev_err(gbcodec->dev, "Widget parsing finished\n"); + + /* process route */ + routes = (struct gb_audio_route *)gbcodec->route_offset; + ret = gbaudio_tplg_process_routes(gbcodec, routes); + if (ret) { + dev_err(gbcodec->dev, + "%d: Error in parsing routes data\n", ret); + return ret; + } + dev_err(gbcodec->dev, "Route parsing finished\n"); + + return ret; +} + +void gbaudio_tplg_release(struct gbaudio_codec_info *gbcodec) +{ + struct gbaudio_dai *dai, *_dai; + struct gbaudio_control *control, *_control; + struct gbaudio_widget *widget, *_widget; + + if (!gbcodec->topology) + return; + + /* release kcontrols */ + list_for_each_entry_safe(control, _control, &gbcodec->codec_ctl_list, + list) { + list_del(&control->list); + devm_kfree(gbcodec->dev, control); + } + if (gbcodec->kctls) + devm_kfree(gbcodec->dev, gbcodec->kctls); + + /* release widget controls */ + list_for_each_entry_safe(control, _control, &gbcodec->widget_ctl_list, + list) { + list_del(&control->list); + devm_kfree(gbcodec->dev, control); + } + + /* release widgets */ + list_for_each_entry_safe(widget, _widget, &gbcodec->widget_list, + list) { + list_del(&widget->list); + devm_kfree(gbcodec->dev, widget); + } + if (gbcodec->widgets) + devm_kfree(gbcodec->dev, gbcodec->widgets); + + /* release routes */ + if (gbcodec->routes) + devm_kfree(gbcodec->dev, gbcodec->routes); + + /* release DAIs */ + mutex_lock(&gbcodec->lock); + list_for_each_entry_safe(dai, _dai, &gbcodec->dai_list, list) { + list_del(&dai->list); + devm_kfree(gbcodec->dev, dai); + } + mutex_unlock(&gbcodec->lock); +} -- cgit v0.10.2 From b7f0088df7369bafc5029be7c0085961904086fc Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal Date: Wed, 13 Jan 2016 14:07:52 -0700 Subject: greybus: audio: Add GB Audio class protocol functionality in GB codec DAI ops GB Audio class driver provides APIs to configure GB codec module. This patch adds relevant operations in DAI ops callback functions to configure codec module as per DAPM sequence triggered. Signed-off-by: Vaibhav Agarwal Signed-off-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 239a9b6..a03caa0 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -12,6 +12,7 @@ #include #include "audio_codec.h" +#include "audio_apbridgea.h" #define GB_AUDIO_MGMT_DRIVER_NAME "gb_audio_mgmt" #define GB_AUDIO_DATA_DRIVER_NAME "gb_audio_data" @@ -19,28 +20,325 @@ static DEFINE_MUTEX(gb_codec_list_lock); static LIST_HEAD(gb_codec_list); +/* + * codec DAI ops + */ static int gbcodec_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - return 0; + int ret, found; + __u16 i2s_port, cportid; + + struct gbaudio_dai *gb_dai; + struct gbaudio_codec_info *gb = + (struct gbaudio_codec_info *)dev_get_drvdata(dai->dev); + + /* find the dai */ + found = 0; + list_for_each_entry(gb_dai, &gb->dai_list, list) { + if (!strncmp(gb_dai->name, dai->name, NAME_SIZE)) { + found = 1; + break; + } + } + + if (!found) { + dev_err(dai->dev, "%s: DAI not registered\n", dai->name); + return -EINVAL; + } + + /* register cport */ + i2s_port = 0; /* fixed for now */ + cportid = gb_dai->connection->hd_cport_id; + ret = gb_audio_apbridgea_register_cport(gb_dai->connection, i2s_port, + cportid); + dev_dbg(dai->dev, "Register %s:%d DAI, ret:%d\n", dai->name, cportid, + ret); + + return ret; } static void gbcodec_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { + int ret, found; + __u16 i2s_port, cportid; + + struct gbaudio_dai *gb_dai; + struct gbaudio_codec_info *gb = + (struct gbaudio_codec_info *)dev_get_drvdata(dai->dev); + + /* find the dai */ + found = 0; + list_for_each_entry(gb_dai, &gb->dai_list, list) { + if (!strncmp(gb_dai->name, dai->name, NAME_SIZE)) { + found = 1; + break; + } + } + + if (!found) { + dev_err(dai->dev, "%s: DAI not registered\n", dai->name); + return; + } + + /* deactivate rx/tx */ + cportid = gb_dai->connection->intf_cport_id; + + switch (substream->stream) { + case SNDRV_PCM_STREAM_CAPTURE: + ret = gb_audio_gb_deactivate_rx(gb->mgmt_connection, cportid); + break; + case SNDRV_PCM_STREAM_PLAYBACK: + ret = gb_audio_gb_deactivate_tx(gb->mgmt_connection, cportid); + break; + default: + dev_err(dai->dev, "Invalid stream type during shutdown\n"); + return; + } + + if (ret) + dev_err(dai->dev, "%d:Error during deactivate\n", ret); + + /* un register cport */ + i2s_port = 0; /* fixed for now */ + ret = gb_audio_apbridgea_unregister_cport(gb_dai->connection, i2s_port, + gb_dai->connection->hd_cport_id); + + dev_dbg(dai->dev, "Unregister %s:%d DAI, ret:%d\n", dai->name, + gb_dai->connection->hd_cport_id, ret); + + return; } static int gbcodec_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hwparams, struct snd_soc_dai *dai) { - return 0; + int ret, found; + uint8_t sig_bits, channels; + uint32_t format, rate; + uint16_t data_cport; + struct gbaudio_dai *gb_dai; + struct gbaudio_codec_info *gb = + (struct gbaudio_codec_info *)dev_get_drvdata(dai->dev); + + /* find the dai */ + found = 0; + list_for_each_entry(gb_dai, &gb->dai_list, list) { + if (!strncmp(gb_dai->name, dai->name, NAME_SIZE)) { + found = 1; + break; + } + } + + if (!found) { + dev_err(dai->dev, "%s: DAI not registered\n", dai->name); + return -EINVAL; + } + + /* + * assuming, currently only 48000 Hz, 16BIT_LE, stereo + * is supported, validate params before configuring codec + */ + if (params_channels(hwparams) != 2) { + dev_err(dai->dev, "Invalid channel count:%d\n", + params_channels(hwparams)); + return -EINVAL; + } + channels = params_channels(hwparams); + + if (params_rate(hwparams) != 48000) { + dev_err(dai->dev, "Invalid sampling rate:%d\n", + params_rate(hwparams)); + return -EINVAL; + } + rate = GB_AUDIO_PCM_RATE_48000; + + if (params_format(hwparams) != SNDRV_PCM_FORMAT_S16_LE) { + dev_err(dai->dev, "Invalid format:%d\n", + params_format(hwparams)); + return -EINVAL; + } + format = GB_AUDIO_PCM_FMT_S16_LE; + + data_cport = gb_dai->connection->intf_cport_id; + /* XXX check impact of sig_bit + * it should not change ideally + */ + + dev_dbg(dai->dev, "cport:%d, rate:%d, channel %d, format %d, sig_bits:%d\n", + data_cport, rate, channels, format, sig_bits); + ret = gb_audio_gb_set_pcm(gb->mgmt_connection, data_cport, format, + rate, channels, sig_bits); + if (ret) { + dev_err(dai->dev, "%d: Error during set_pcm\n", ret); + return ret; + } + + /* + * XXX need to check if + * set config is always required + * check for mclk_freq as well + */ + ret = gb_audio_apbridgea_set_config(gb_dai->connection, 0, + AUDIO_APBRIDGEA_PCM_FMT_16, + AUDIO_APBRIDGEA_PCM_RATE_48000, + 6144000); + if (ret) + dev_err(dai->dev, "%d: Error during set_config\n", ret); + + return ret; } static int gbcodec_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - return 0; + int ret, found; + uint16_t data_cport; + struct gbaudio_dai *gb_dai; + struct gbaudio_codec_info *gb = + (struct gbaudio_codec_info *)dev_get_drvdata(dai->dev); + + /* find the dai */ + found = 0; + list_for_each_entry(gb_dai, &gb->dai_list, list) { + if (!strncmp(gb_dai->name, dai->name, NAME_SIZE)) { + found = 1; + break; + } + } + + if (!found) { + dev_err(dai->dev, "%s: DAI not registered\n", dai->name); + return -EINVAL; + } + + /* deactivate rx/tx */ + data_cport = gb_dai->connection->intf_cport_id; + + switch (substream->stream) { + case SNDRV_PCM_STREAM_CAPTURE: + ret = gb_audio_gb_set_rx_data_size(gb->mgmt_connection, + data_cport, 192); + if (ret) { + dev_err(dai->dev, + "%d:Error during set_rx_data_size, cport:%d\n", + ret, data_cport); + return ret; + } + ret = gb_audio_apbridgea_set_rx_data_size(gb_dai->connection, 0, + 192); + if (ret) { + dev_err(dai->dev, + "%d:Error during apbridgea_set_rx_data_size\n", + ret); + return ret; + } + ret = gb_audio_gb_activate_rx(gb->mgmt_connection, data_cport); + break; + case SNDRV_PCM_STREAM_PLAYBACK: + ret = gb_audio_gb_set_tx_data_size(gb->mgmt_connection, + data_cport, 192); + if (ret) { + dev_err(dai->dev, + "%d:Error during module set_tx_data_size, cport:%d\n", + ret, data_cport); + return ret; + } + ret = gb_audio_apbridgea_set_tx_data_size(gb_dai->connection, 0, + 192); + if (ret) { + dev_err(dai->dev, + "%d:Error during apbridgea set_tx_data_size, cport\n", + ret); + return ret; + } + ret = gb_audio_gb_activate_tx(gb->mgmt_connection, data_cport); + break; + default: + dev_err(dai->dev, "Invalid stream type %d during prepare\n", + substream->stream); + return -EINVAL; + } + + if (ret) + dev_err(dai->dev, "%d: Error during activate stream\n", ret); + + return ret; +} + +static int gbcodec_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + int ret, found; + int tx, rx, start, stop; + struct gbaudio_dai *gb_dai; + struct gbaudio_codec_info *gb = + (struct gbaudio_codec_info *)dev_get_drvdata(dai->dev); + + /* find the dai */ + found = 0; + list_for_each_entry(gb_dai, &gb->dai_list, list) { + if (!strncmp(gb_dai->name, dai->name, NAME_SIZE)) { + found = 1; + break; + } + } + + if (!found) { + dev_err(dai->dev, "%s: DAI not registered\n", dai->name); + return -EINVAL; + } + + tx = rx = start = stop = 0; + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + start = 1; + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + stop = 1; + break; + default: + dev_err(dai->dev, "Invalid tigger cmd:%d\n", cmd); + return -EINVAL; + } + + switch (substream->stream) { + case SNDRV_PCM_STREAM_CAPTURE: + rx = 1; + break; + case SNDRV_PCM_STREAM_PLAYBACK: + tx = 1; + break; + default: + dev_err(dai->dev, "Invalid stream type:%d\n", + substream->stream); + return -EINVAL; + } + + if (start && tx) + ret = gb_audio_apbridgea_start_tx(gb_dai->connection, 0, 0); + + else if (start && rx) + ret = gb_audio_apbridgea_start_rx(gb_dai->connection, 0); + + else if (stop && tx) + ret = gb_audio_apbridgea_stop_tx(gb_dai->connection, 0); + + else if (stop && rx) + ret = gb_audio_apbridgea_stop_rx(gb_dai->connection, 0); + + else + ret = -EINVAL; + + if (ret) + dev_err(dai->dev, "%d:Error during %s stream\n", ret, + start ? "Start" : "Stop"); + + return ret; } static int gbcodec_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) @@ -57,6 +355,7 @@ static struct snd_soc_dai_ops gbcodec_dai_ops = { .startup = gbcodec_startup, .shutdown = gbcodec_shutdown, .hw_params = gbcodec_hw_params, + .trigger = gbcodec_trigger, .prepare = gbcodec_prepare, .set_fmt = gbcodec_set_dai_fmt, .digital_mute = gbcodec_digital_mute, -- cgit v0.10.2 From 17247da52ee8694429e089f452dd14f4dbda9f06 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal Date: Wed, 13 Jan 2016 14:07:53 -0700 Subject: greybus: audio: Report uevent on GB codec module insertion/removal GB-Audio-manager module is currently used to report uevent to above layer in response to any codec module inserted or removed. Signed-off-by: Vaibhav Agarwal Signed-off-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index a03caa0..93906c8 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -13,6 +13,7 @@ #include "audio_codec.h" #include "audio_apbridgea.h" +#include "audio_manager.h" #define GB_AUDIO_MGMT_DRIVER_NAME "gb_audio_mgmt" #define GB_AUDIO_DATA_DRIVER_NAME "gb_audio_data" @@ -577,6 +578,7 @@ static int gbaudio_codec_probe(struct gb_connection *connection) int ret, i; struct gbaudio_codec_info *gbcodec; struct gb_audio_topology *topology; + struct gb_audio_manager_module_descriptor desc; struct device *dev = &connection->bundle->dev; int dev_id = connection->bundle->id; @@ -639,6 +641,21 @@ static int gbaudio_codec_probe(struct gb_connection *connection) mutex_lock(&gbcodec->lock); gbcodec->codec_registered = 1; + /* inform above layer for uevent */ + if (!gbcodec->set_uevent && + (gbcodec->dai_added == gbcodec->num_dais)) { + dev_dbg(dev, "Inform set_event:%d to above layer\n", 1); + /* prepare for the audio manager */ + strlcpy(desc.name, gbcodec->name, + GB_AUDIO_MANAGER_MODULE_NAME_LEN); /* todo */ + desc.slot = 1; /* todo */ + desc.vid = 2; /* todo */ + desc.pid = 3; /* todo */ + desc.cport = gbcodec->dev_id; + desc.devices = 0x2; /* todo */ + gbcodec->manager_id = gb_audio_manager_add(&desc); + gbcodec->set_uevent = 1; + } mutex_unlock(&gbcodec->lock); return ret; @@ -669,6 +686,16 @@ static void gbaudio_codec_remove(struct gb_connection *connection) if (!gbcodec) return; + /* inform uevent to above layers */ + mutex_lock(&gbcodec->lock); + if (gbcodec->set_uevent) { + /* notify the audio manager */ + dev_dbg(dev, "Inform set_event:%d to above layer\n", 0); + gb_audio_manager_remove(gbcodec->manager_id); + gbcodec->set_uevent = 0; + } + mutex_unlock(&gbcodec->lock); + msm8994_remove_dailink("msm8994-tomtom-mtp-snd-card", &gbaudio_dailink, 1); gbaudio_remove_dailinks(gbcodec); @@ -712,6 +739,7 @@ static int gbaudio_dai_probe(struct gb_connection *connection) struct device *dev = &connection->bundle->dev; int dev_id = connection->bundle->id; struct gbaudio_codec_info *gbcodec = dev_get_drvdata(dev); + struct gb_audio_manager_module_descriptor desc; dev_dbg(dev, "Add DAI device:%d:%s\n", dev_id, dev_name(dev)); @@ -729,6 +757,22 @@ static int gbaudio_dai_probe(struct gb_connection *connection) /* update dai_added count */ mutex_lock(&gbcodec->lock); gbcodec->dai_added++; + + /* inform above layer for uevent */ + if (!gbcodec->set_uevent && gbcodec->codec_registered && + (gbcodec->dai_added == gbcodec->num_dais)) { + /* prepare for the audio manager */ + dev_dbg(dev, "Inform set_event:%d to above layer\n", 1); + strlcpy(desc.name, gbcodec->name, + GB_AUDIO_MANAGER_MODULE_NAME_LEN); /* todo */ + desc.slot = 1; /* todo */ + desc.vid = 2; /* todo */ + desc.pid = 3; /* todo */ + desc.cport = gbcodec->dev_id; + desc.devices = 0x2; /* todo */ + gbcodec->manager_id = gb_audio_manager_add(&desc); + gbcodec->set_uevent = 1; + } mutex_unlock(&gbcodec->lock); return 0; @@ -749,6 +793,12 @@ static void gbaudio_dai_remove(struct gb_connection *connection) /* inform uevent to above layers */ mutex_lock(&gbcodec->lock); + if (gbcodec->set_uevent) { + /* notify the audio manager */ + dev_dbg(dev, "Inform set_event:%d to above layer\n", 0); + gb_audio_manager_remove(gbcodec->manager_id); + gbcodec->set_uevent = 0; + } /* update dai_added count */ gbcodec->dai_added--; mutex_unlock(&gbcodec->lock); diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index 5051e06..fcf3a06 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -97,10 +97,13 @@ struct gbaudio_codec_info { int type; int dai_added; int codec_registered; + int set_uevent; char vstr[NAME_SIZE]; char pstr[NAME_SIZE]; struct list_head list; struct gb_audio_topology *topology; + /* need to share this info to above user space */ + int manager_id; char name[NAME_SIZE]; /* soc related data */ -- cgit v0.10.2 From 538ecb5a05049fcd23043ed5c97e42c379e5ccb0 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal Date: Wed, 13 Jan 2016 14:07:54 -0700 Subject: greybus: audio: cleanup unnecessary dev_err messages Replace unnecessary dev_err msg with dev_dbg. Same were added during development to trace topology parser progress. Signed-off-by: Vaibhav Agarwal Signed-off-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index 8840a9c..b18574e 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -837,7 +837,7 @@ static int gbaudio_tplg_process_dais(struct gbaudio_codec_info *gbcodec, dai_name); if (!dai) goto error; - dev_err(gbcodec->dev, "%s:DAI added\n", dai->name); + dev_dbg(gbcodec->dev, "%s:DAI added\n", dai->name); gb_dais[i].name = dai->name; curr++; } @@ -1031,7 +1031,7 @@ int gbaudio_tplg_parse_data(struct gbaudio_codec_info *gbcodec, "%d: Error in parsing controls data\n", ret); return ret; } - dev_err(gbcodec->dev, "Control parsing finished\n"); + dev_dbg(gbcodec->dev, "Control parsing finished\n"); /* process DAI */ dais = (struct gb_audio_dai *)gbcodec->dai_offset; @@ -1041,7 +1041,7 @@ int gbaudio_tplg_parse_data(struct gbaudio_codec_info *gbcodec, "%d: Error in parsing DAIs data\n", ret); return ret; } - dev_err(gbcodec->dev, "DAI parsing finished\n"); + dev_dbg(gbcodec->dev, "DAI parsing finished\n"); /* process widgets */ widgets = (struct gb_audio_widget *)gbcodec->widget_offset; @@ -1051,7 +1051,7 @@ int gbaudio_tplg_parse_data(struct gbaudio_codec_info *gbcodec, "%d: Error in parsing widgets data\n", ret); return ret; } - dev_err(gbcodec->dev, "Widget parsing finished\n"); + dev_dbg(gbcodec->dev, "Widget parsing finished\n"); /* process route */ routes = (struct gb_audio_route *)gbcodec->route_offset; @@ -1061,7 +1061,7 @@ int gbaudio_tplg_parse_data(struct gbaudio_codec_info *gbcodec, "%d: Error in parsing routes data\n", ret); return ret; } - dev_err(gbcodec->dev, "Route parsing finished\n"); + dev_dbg(gbcodec->dev, "Route parsing finished\n"); return ret; } -- cgit v0.10.2 From 25de3491f11064845a45606fa5828a200ecf8c53 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal Date: Wed, 13 Jan 2016 14:07:55 -0700 Subject: greybus: audio: Cleanup GB protocol connections in case of abrupt codec removal We need to clean up GB protocl connections, otherwise successive codec insertions fails repeatedly. NOTE: As per suggestion, since codec is already removed, one should not trigger any GB command. It'll cause a delay of atleast TIMEOUT value. HOwever, failing to cleanup GB protocol, causes successive module insertion to fail Signed-off-by: Vaibhav Agarwal Signed-off-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 93906c8..2b4fcbe 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -56,6 +56,9 @@ static int gbcodec_startup(struct snd_pcm_substream *substream, dev_dbg(dai->dev, "Register %s:%d DAI, ret:%d\n", dai->name, cportid, ret); + if (!ret) + atomic_inc(&gb->users); + return ret; } @@ -83,6 +86,8 @@ static void gbcodec_shutdown(struct snd_pcm_substream *substream, return; } + atomic_dec(&gb->users); + /* deactivate rx/tx */ cportid = gb_dai->connection->intf_cport_id; @@ -428,6 +433,7 @@ static struct snd_soc_codec_driver soc_codec_dev_gbcodec = { .reg_word_size = 1, .idle_bias_off = true, + .ignore_pmdown_time = 1, }; /* @@ -573,6 +579,50 @@ struct device_driver gb_codec_driver = { .owner = THIS_MODULE, }; +/* XXX + * since BE DAI path is not yet properly closed from above layer, + * dsp dai.mi2s_dai_data.status_mask is still set to STATUS_PORT_STARTED + * this causes immediate playback/capture to fail in case relevant mixer + * control is not turned OFF + * user need to try once again after failure to recover DSP state. + */ +static void gb_audio_cleanup(struct gbaudio_codec_info *gb) +{ + int cportid, ret; + struct gbaudio_dai *gb_dai; + struct gb_connection *connection; + struct device *dev = gb->dev; + + list_for_each_entry(gb_dai, &gb->dai_list, list) { + /* + * In case of BE dailink, need to deactivate APBridge + * manually + */ + if (gbaudio_dailink.no_pcm && atomic_read(&gb->users)) { + connection = gb_dai->connection; + /* PB active */ + ret = gb_audio_apbridgea_stop_tx(connection, 0); + if (ret) + dev_info(dev, "%d:Failed during APBridge stop_tx\n", + ret); + cportid = connection->intf_cport_id; + ret = gb_audio_gb_deactivate_tx(gb->mgmt_connection, + cportid); + if (ret) + dev_info(dev, + "%d:Failed during deactivate_tx\n", + ret); + cportid = connection->hd_cport_id; + ret = gb_audio_apbridgea_unregister_cport(connection, 0, + cportid); + if (ret) + dev_info(dev, "%d:Failed during unregister cport\n", + ret); + atomic_dec(&gb->users); + } + } +} + static int gbaudio_codec_probe(struct gb_connection *connection) { int ret, i; @@ -641,6 +691,9 @@ static int gbaudio_codec_probe(struct gb_connection *connection) mutex_lock(&gbcodec->lock); gbcodec->codec_registered = 1; + /* codec cleanup related */ + atomic_set(&gbcodec->users, 0); + /* inform above layer for uevent */ if (!gbcodec->set_uevent && (gbcodec->dai_added == gbcodec->num_dais)) { @@ -696,6 +749,11 @@ static void gbaudio_codec_remove(struct gb_connection *connection) } mutex_unlock(&gbcodec->lock); + if (atomic_read(&gbcodec->users)) { + dev_err(dev, "Cleanup Error: BE stream not yet closed\n"); + gb_audio_cleanup(gbcodec); + } + msm8994_remove_dailink("msm8994-tomtom-mtp-snd-card", &gbaudio_dailink, 1); gbaudio_remove_dailinks(gbcodec); diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index fcf3a06..0b587ef 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -131,6 +131,9 @@ struct gbaudio_codec_info { struct snd_soc_dapm_route *routes; struct snd_soc_dai_driver *dais; + /* codec users */ + atomic_t users; + /* lists */ struct list_head dai_list; struct list_head widget_list; -- cgit v0.10.2 From 83ec628386aee5e14fe1be3e27e84124dfa7b165 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal Date: Wed, 13 Jan 2016 14:07:56 -0700 Subject: greybus: audio: Enable codec module detection on different slots driver_name associated with dev_name was hard coded earlier. This limits, audio codec module to be detected on Port#5 only. Now, driver_name is generated dynamically based on dev_name. This enables codec module detection on any 1x2 slot. Also, Update dev_id based on slot number, instead of bundle->id. bundle->id is not unique for multiple modules added, thus now using slot number for unique identification. Signed-off-by: Vaibhav Agarwal Signed-off-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 2b4fcbe..79f2baf 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -575,7 +575,6 @@ static void gbaudio_free_codec(struct device *dev, * GB codec module driver ops */ struct device_driver gb_codec_driver = { - .name = "1-8", .owner = THIS_MODULE, }; @@ -626,11 +625,12 @@ static void gb_audio_cleanup(struct gbaudio_codec_info *gb) static int gbaudio_codec_probe(struct gb_connection *connection) { int ret, i; + char *driver_name; struct gbaudio_codec_info *gbcodec; struct gb_audio_topology *topology; struct gb_audio_manager_module_descriptor desc; struct device *dev = &connection->bundle->dev; - int dev_id = connection->bundle->id; + int dev_id = connection->intf->interface_id; dev_dbg(dev, "Add device:%d:%s\n", dev_id, dev_name(dev)); /* get gbcodec data */ @@ -670,6 +670,10 @@ static int gbaudio_codec_probe(struct gb_connection *connection) gbcodec->dais[i].ops = &gbcodec_dai_ops; /* FIXME */ + driver_name = devm_kzalloc(dev, NAME_SIZE, GFP_KERNEL); + strlcpy(driver_name, gbcodec->name, NAME_SIZE); + gb_codec_driver.name = strsep(&driver_name, "."); + dev_dbg(dev, "driver.name:%s\n", gb_codec_driver.name); dev->driver = &gb_codec_driver; /* register codec */ @@ -730,7 +734,7 @@ static void gbaudio_codec_remove(struct gb_connection *connection) { struct gbaudio_codec_info *gbcodec; struct device *dev = &connection->bundle->dev; - int dev_id = connection->bundle->id; + int dev_id = connection->intf->interface_id; dev_dbg(dev, "Remove device:%d:%s\n", dev_id, dev_name(dev)); @@ -795,7 +799,7 @@ static int gbaudio_dai_probe(struct gb_connection *connection) { struct gbaudio_dai *dai; struct device *dev = &connection->bundle->dev; - int dev_id = connection->bundle->id; + int dev_id = connection->intf->interface_id; struct gbaudio_codec_info *gbcodec = dev_get_drvdata(dev); struct gb_audio_manager_module_descriptor desc; @@ -839,7 +843,7 @@ static int gbaudio_dai_probe(struct gb_connection *connection) static void gbaudio_dai_remove(struct gb_connection *connection) { struct device *dev = &connection->bundle->dev; - int dev_id = connection->bundle->id; + int dev_id = connection->intf->interface_id; struct gbaudio_codec_info *gbcodec; dev_dbg(dev, "Remove DAI device:%d:%s\n", dev_id, dev_name(dev)); -- cgit v0.10.2 From 4068487ce3dba22bdc7bf34e7327b474494430b5 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 15 Jan 2016 01:33:55 +0200 Subject: greybus: camera: Return the result flags from the configure_streams response And return the response num_streams field through a pointer variable instead of using the return value of the function as both an error code and a positive number of streams, it makes the API more consistent. Signed-off-by: Laurent Pinchart Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index a69797b..deb55da 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -108,13 +108,14 @@ struct ap_csi_config_request { } __packed; static int gb_camera_configure_streams(struct gb_camera *gcam, - unsigned int nstreams, - unsigned int flags, + unsigned int *num_streams, + unsigned int *flags, struct gb_camera_stream_config *streams) { struct gb_camera_configure_streams_request *req; struct gb_camera_configure_streams_response *resp; struct ap_csi_config_request csi_cfg; + unsigned int nstreams = *num_streams; unsigned int i; size_t req_size; size_t resp_size; @@ -134,7 +135,7 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, } req->num_streams = nstreams; - req->flags = flags; + req->flags = *flags; req->padding = 0; for (i = 0; i < nstreams; ++i) { @@ -165,6 +166,8 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, goto done; } + *flags = resp->flags; + for (i = 0; i < nstreams; ++i) { struct gb_camera_stream_config_response *cfg = &resp->config[i]; @@ -205,7 +208,8 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, gcam_err(gcam, "failed to %s the CSI transmitter\n", nstreams ? "start" : "stop"); - ret = resp->num_streams; + *num_streams = resp->num_streams; + ret = 0; done: kfree(req); @@ -316,6 +320,7 @@ static int gb_camera_op_configure_streams(void *priv, unsigned int nstreams, { struct gb_camera *gcam = priv; struct gb_camera_stream_config *gb_streams; + unsigned int flags = 0; unsigned int i; int ret; @@ -333,7 +338,7 @@ static int gb_camera_op_configure_streams(void *priv, unsigned int nstreams, gb_camera_mbus_to_gb(streams[i].pixel_code); } - ret = gb_camera_configure_streams(gcam, nstreams, 0, gb_streams); + ret = gb_camera_configure_streams(gcam, &nstreams, &flags, gb_streams); if (ret < 0) goto done; @@ -455,12 +460,11 @@ static ssize_t gb_camera_debugfs_configure_streams(struct gb_camera *gcam, goto done; } - ret = gb_camera_configure_streams(gcam, nstreams, flags, streams); + ret = gb_camera_configure_streams(gcam, &nstreams, &flags, streams); if (ret < 0) goto done; - nstreams = ret; - buffer->length = sprintf(buffer->data, "%u;", nstreams); + buffer->length = sprintf(buffer->data, "%u;%u;", nstreams, flags); for (i = 0; i < nstreams; ++i) { struct gb_camera_stream_config *stream = &streams[i]; -- cgit v0.10.2 From 11ca550c226b87c4bf457580a817e4529c7aca62 Mon Sep 17 00:00:00 2001 From: Gjorgji Rosikopulos Date: Fri, 15 Jan 2016 21:34:56 +0200 Subject: greybus: camera: Fix backword compatibility in configure streams Configure streams ret code should be number of streams in gb operation exported to HOST camera. Until gb operation is migrated to new interface return number of streams in ret code. Signed-off-by: Gjorgji Rosikopulos Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index deb55da..8b21433 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -352,6 +352,8 @@ static int gb_camera_op_configure_streams(void *priv, unsigned int nstreams, streams[i].pixel_code = gb_camera_gb_to_mbus(gb_streams[i].format); } + /* For backward compatibility return number of streams in ret code */ + ret = nstreams; done: kfree(gb_streams); -- cgit v0.10.2 From b55d9431d62d6ce762d4b50ec93bbb81dce783c6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 15 Jan 2016 14:41:02 -0800 Subject: greybus: Revert "camera: Fix backword compatibility in configure streams" This reverts commit 48cc91e52dba9abad4c9b56f911994c65071bfc4 as the caller should be changed instead. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 8b21433..deb55da 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -352,8 +352,6 @@ static int gb_camera_op_configure_streams(void *priv, unsigned int nstreams, streams[i].pixel_code = gb_camera_gb_to_mbus(gb_streams[i].format); } - /* For backward compatibility return number of streams in ret code */ - ret = nstreams; done: kfree(gb_streams); -- cgit v0.10.2 From b29906af20cf74bda2ec702626a26dc4501866ef Mon Sep 17 00:00:00 2001 From: Michael Scott Date: Fri, 15 Jan 2016 14:03:17 -0800 Subject: greybus: firmware: replace colons with underscore in firmware file request Due to some issues with handling colons in Android (and possibly future exposure to other problems) we should remove the colons from the firmware file request. Replacing them with underscores. Specifically, we copy firmware into the Android build using a line similar to this: PRODUCT_COPY_FILES += \ source-repo/ara:00000126:00001000:00000001:00000001:02.tftf:system/etc/firmware/ara:00000126:00001000:00000001:00000001:02.tftf There is a colon delimiter between the source and destination in the PRODUCT_COPY_FILES format. The greybus naming logic breaks the parsing routine and generates an Android build break. Signed-off-by: Michael Scott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/firmware.c b/drivers/staging/greybus/firmware.c index b65787c..11d605b 100644 --- a/drivers/staging/greybus/firmware.c +++ b/drivers/staging/greybus/firmware.c @@ -84,7 +84,7 @@ static int download_firmware(struct gb_firmware *firmware, u8 stage) * XXX Name it properly.. */ snprintf(firmware_name, sizeof(firmware_name), - "ara:%08x:%08x:%08x:%08x:%02x.tftf", + "ara_%08x_%08x_%08x_%08x_%02x.tftf", intf->ddbl1_manufacturer_id, intf->ddbl1_product_id, firmware->vendor_id, firmware->product_id, stage); -- cgit v0.10.2 From 24ac4fa490bf105c202b843280eb67b2327c337f Mon Sep 17 00:00:00 2001 From: Gjorgji Rosikopulos Date: Sun, 17 Jan 2016 19:52:20 +0200 Subject: greybus: camera: Add support for configure streams flag in gb interface Update gb interface and export flags needed for latest protocol version. Number of streams also can be changed based on operation result. Caller sets input flags, end fucntion return output flags Input flags supported: - GB_CAMERA_IN_FLAG_TEST - Need to be set when operation is not actually applied. Output flags supported: - GB_CAMERA_OUT_FLAG_ADJUSTED - This is result of the operation if this flag is set, result is adjusted and operation need to be repeat. Signed-off-by: Gjorgji Rosikopulos Acked-by: Laurent Pinchart Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gb-camera.h b/drivers/staging/greybus/gb-camera.h index a182474..50af057 100644 --- a/drivers/staging/greybus/gb-camera.h +++ b/drivers/staging/greybus/gb-camera.h @@ -10,6 +10,11 @@ #include +/* Input flags need to be set from the caller */ +#define GB_CAMERA_IN_FLAG_TEST (1 << 0) +/* Output flags returned */ +#define GB_CAMERA_OUT_FLAG_ADJUSTED (1 << 0) + struct gb_camera_stream { unsigned int width; unsigned int height; @@ -21,8 +26,8 @@ struct gb_camera_stream { struct gb_camera_ops { ssize_t (*capabilities)(void *priv, char *buf, size_t len); - int (*configure_streams)(void *priv, unsigned int nstreams, - struct gb_camera_stream *streams); + int (*configure_streams)(void *priv, unsigned int *nstreams, + unsigned int *flags, struct gb_camera_stream *streams); int (*capture)(void *priv, u32 request_id, unsigned int streams, unsigned int num_frames, size_t settings_size, const void *settings); -- cgit v0.10.2 From 5b0327103ff0f5498af008cb7189770c1a33b67b Mon Sep 17 00:00:00 2001 From: Gjorgji Rosikopulos Date: Sun, 17 Jan 2016 19:52:21 +0200 Subject: greybus: camera: Update configure stream based on new interface Interface has been changed. return code will not return number of configured streams but just error code. Number of streams is passed as pointer and if operation result is changed number of streams will be updated. Flags are also used for information regarding configure stream operation result. Signed-off-by: Gjorgji Rosikopulos Acked-by: Laurent Pinchart Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index deb55da..6f14848 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -315,34 +315,47 @@ static enum v4l2_mbus_pixelcode gb_camera_gb_to_mbus(u16 gb_fmt) return mbus_to_gbus_format[0].mbus_code; } -static int gb_camera_op_configure_streams(void *priv, unsigned int nstreams, - struct gb_camera_stream *streams) +static int gb_camera_op_configure_streams(void *priv, unsigned int *nstreams, + unsigned int *flags, struct gb_camera_stream *streams) { struct gb_camera *gcam = priv; struct gb_camera_stream_config *gb_streams; - unsigned int flags = 0; + unsigned int gb_flags = 0; + unsigned int gb_nstreams = *nstreams; unsigned int i; int ret; - if (nstreams > GB_CAMERA_MAX_STREAMS) + if (gb_nstreams > GB_CAMERA_MAX_STREAMS) return -EINVAL; - gb_streams = kzalloc(nstreams * sizeof(*gb_streams), GFP_KERNEL); + gb_streams = kzalloc(gb_nstreams * sizeof(*gb_streams), GFP_KERNEL); if (!gb_streams) return -ENOMEM; - for (i = 0; i < nstreams; i++) { + for (i = 0; i < gb_nstreams; i++) { gb_streams[i].width = streams[i].width; gb_streams[i].height = streams[i].height; gb_streams[i].format = gb_camera_mbus_to_gb(streams[i].pixel_code); } - ret = gb_camera_configure_streams(gcam, &nstreams, &flags, gb_streams); + if (*flags & GB_CAMERA_IN_FLAG_TEST) + gb_flags |= GB_CAMERA_CONFIGURE_STREAMS_TEST_ONLY; + + ret = gb_camera_configure_streams(gcam, &gb_nstreams, + &gb_flags, gb_streams); if (ret < 0) goto done; + if (gb_nstreams > *nstreams) { + ret = -EINVAL; + goto done; + } + + *flags = 0; + if (gb_flags & GB_CAMERA_CONFIGURE_STREAMS_ADJUSTED) + *flags |= GB_CAMERA_OUT_FLAG_ADJUSTED; - for (i = 0; i < nstreams; i++) { + for (i = 0; i < gb_nstreams; i++) { streams[i].width = gb_streams[i].width; streams[i].height = gb_streams[i].height; streams[i].vc = gb_streams[i].vc; @@ -352,6 +365,7 @@ static int gb_camera_op_configure_streams(void *priv, unsigned int nstreams, streams[i].pixel_code = gb_camera_gb_to_mbus(gb_streams[i].format); } + *nstreams = gb_nstreams; done: kfree(gb_streams); -- cgit v0.10.2 From 5dda7e5a484295f24ecfcba6b64da6d37dccb912 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:50:59 +0100 Subject: greybus: legacy: add legacy-protocol bundle driver Add the first Greybus bundle driver that will be used when transitioning from legacy Greybus protocols to bundle drivers. The legacy-protocol driver initially binds to all current bundle classes. In order to avoid having to update current module-loading scripts, keep this driver internal to greybus core at least until modalias support is added. Note that this prevents unloading any protocol drivers without first tearing down the host device due to a circular module dependency. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index b1272cb..1e24509 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -9,7 +9,8 @@ greybus-y := core.o \ control.o \ svc.o \ firmware.o \ - operation.o + operation.o \ + legacy.o gb-phy-y := gpbridge.o \ sdio.o \ diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index fb775ff..ec52bde 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -152,21 +152,11 @@ int gb_bundle_add(struct gb_bundle *bundle) return 0; } -static void gb_bundle_connections_exit(struct gb_bundle *bundle) -{ - struct gb_connection *connection; - - list_for_each_entry(connection, &bundle->connections, bundle_links) - gb_connection_exit(connection); -} - /* * Tear down a previously set up bundle. */ void gb_bundle_destroy(struct gb_bundle *bundle) { - gb_bundle_connections_exit(bundle); - if (device_is_registered(&bundle->dev)) device_del(&bundle->dev); diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 6295d28..21e6eb5 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -464,6 +464,7 @@ err_unbind_protocol: return ret; } +EXPORT_SYMBOL_GPL(gb_connection_init); void gb_connection_exit(struct gb_connection *connection) { @@ -482,6 +483,7 @@ void gb_connection_exit(struct gb_connection *connection) gb_connection_unbind_protocol(connection); } +EXPORT_SYMBOL_GPL(gb_connection_exit); /* * Tear down a previously set up connection. diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 0e2f99d..28f48d7 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -12,6 +12,7 @@ #define CREATE_TRACE_POINTS #include "greybus.h" #include "greybus_trace.h" +#include "legacy.h" EXPORT_TRACEPOINT_SYMBOL_GPL(gb_host_device_send); EXPORT_TRACEPOINT_SYMBOL_GPL(gb_host_device_recv); @@ -240,8 +241,16 @@ static int __init gb_init(void) goto error_firmware; } + retval = gb_legacy_init(); + if (retval) { + pr_err("gb_legacy_init failed\n"); + goto error_legacy; + } + return 0; /* Success */ +error_legacy: + gb_firmware_protocol_exit(); error_firmware: gb_svc_protocol_exit(); error_svc: @@ -261,6 +270,7 @@ module_init(gb_init); static void __exit gb_exit(void) { + gb_legacy_exit(); gb_firmware_protocol_exit(); gb_svc_protocol_exit(); gb_control_protocol_exit(); diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index edac238..c345350 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -183,7 +183,6 @@ void gb_interfaces_remove(struct gb_host_device *hd) int gb_interface_init(struct gb_interface *intf, u8 device_id) { struct gb_bundle *bundle, *tmp; - struct gb_connection *connection; int ret, size; void *manifest; @@ -242,15 +241,6 @@ int gb_interface_init(struct gb_interface *intf, u8 device_id) gb_bundle_destroy(bundle); continue; } - - list_for_each_entry(connection, &bundle->connections, - bundle_links) { - ret = gb_connection_init(connection); - if (ret) - break; - } - if (ret) - gb_bundle_destroy(bundle); } ret = 0; diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c new file mode 100644 index 0000000..26a7d1a --- /dev/null +++ b/drivers/staging/greybus/legacy.c @@ -0,0 +1,95 @@ +/* + * Greybus legacy-protocol driver + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include "greybus.h" +#include "legacy.h" + +static int legacy_probe(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) +{ + struct gb_connection *connection; + int ret; + + dev_dbg(&bundle->dev, "%s - bundle class = 0x%02x\n", __func__, + bundle->class); + + list_for_each_entry(connection, &bundle->connections, bundle_links) { + dev_dbg(&bundle->dev, "enabling connection %s\n", + connection->name); + + ret = gb_connection_init(connection); + if (ret) + goto err_connections_disable; + } + + return 0; + +err_connections_disable: + list_for_each_entry_reverse(connection, &bundle->connections, + bundle_links) { + gb_connection_exit(connection); + } + + return ret; +} + +static void legacy_disconnect(struct gb_bundle *bundle) +{ + struct gb_connection *connection; + + dev_dbg(&bundle->dev, "%s - bundle class = 0x%02x\n", __func__, + bundle->class); + + list_for_each_entry_reverse(connection, &bundle->connections, + bundle_links) { + gb_connection_exit(connection); + } +} + +static const struct greybus_bundle_id legacy_id_table[] = { + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_GPIO) }, + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_I2C) }, + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_UART) }, + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_HID) }, + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_USB) }, + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SDIO) }, + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_POWER_SUPPLY) }, + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_PWM) }, + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SPI) }, + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_DISPLAY) }, + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_CAMERA) }, + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SENSOR) }, + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_LIGHTS) }, + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_VIBRATOR) }, + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_LOOPBACK) }, + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_AUDIO_MGMT) }, + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_AUDIO_DATA) }, + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SVC) }, + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_FIRMWARE) }, + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_RAW) }, + { } +}; +MODULE_DEVICE_TABLE(greybus, legacy_id_table); + +static struct greybus_driver legacy_driver = { + .name = "legacy", + .probe = legacy_probe, + .disconnect = legacy_disconnect, + .id_table = legacy_id_table, +}; + +int gb_legacy_init(void) +{ + return greybus_register(&legacy_driver); +} + +void gb_legacy_exit(void) +{ + greybus_deregister(&legacy_driver); +} diff --git a/drivers/staging/greybus/legacy.h b/drivers/staging/greybus/legacy.h new file mode 100644 index 0000000..2177f6a --- /dev/null +++ b/drivers/staging/greybus/legacy.h @@ -0,0 +1,16 @@ +/* + * Greybus legacy-protocol driver + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#ifndef __LEGACY_H +#define __LEGACY_H + +int gb_legacy_init(void); +void gb_legacy_exit(void); + +#endif /* __LEGACY_H */ -- cgit v0.10.2 From 6d3d95042e6b3bede0199bad0d08f71b4f7735fb Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:51:00 +0100 Subject: greybus: connection: rename legacy init and exit functions Rename legacy connection init and exit functions. This is a step towards removing the legacy-protocol handling from core. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 21e6eb5..d0e3f91 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -435,7 +435,7 @@ void gb_connection_disable(struct gb_connection *connection) } EXPORT_SYMBOL_GPL(gb_connection_disable); -int gb_connection_init(struct gb_connection *connection) +int gb_connection_legacy_init(struct gb_connection *connection) { int ret; @@ -464,9 +464,9 @@ err_unbind_protocol: return ret; } -EXPORT_SYMBOL_GPL(gb_connection_init); +EXPORT_SYMBOL_GPL(gb_connection_legacy_init); -void gb_connection_exit(struct gb_connection *connection) +void gb_connection_legacy_exit(struct gb_connection *connection) { spin_lock_irq(&connection->lock); if (connection->state != GB_CONNECTION_STATE_ENABLED) { @@ -483,7 +483,7 @@ void gb_connection_exit(struct gb_connection *connection) gb_connection_unbind_protocol(connection); } -EXPORT_SYMBOL_GPL(gb_connection_exit); +EXPORT_SYMBOL_GPL(gb_connection_legacy_exit); /* * Tear down a previously set up connection. @@ -495,7 +495,7 @@ void gb_connection_destroy(struct gb_connection *connection) if (WARN_ON(!connection)) return; - gb_connection_exit(connection); + gb_connection_legacy_exit(connection); spin_lock_irq(&gb_connections_lock); list_del(&connection->bundle_links); diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index ef31c8d..b0a67f2 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -62,8 +62,11 @@ static inline bool gb_connection_is_static(struct gb_connection *connection) return !connection->intf; } -int gb_connection_init(struct gb_connection *connection); -void gb_connection_exit(struct gb_connection *connection); +int gb_connection_enable(struct gb_connection *connection); +void gb_connection_disable(struct gb_connection *connection); + +int gb_connection_legacy_init(struct gb_connection *connection); +void gb_connection_legacy_exit(struct gb_connection *connection); void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id, u8 *data, size_t length); diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index 4d65dbf..1c4994b 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -116,7 +116,7 @@ int gb_control_enable(struct gb_control *control) dev_dbg(&control->connection->intf->dev, "%s\n", __func__); - ret = gb_connection_init(control->connection); + ret = gb_connection_legacy_init(control->connection); if (ret) { dev_err(&control->connection->intf->dev, "failed to enable control connection: %d\n", @@ -131,7 +131,7 @@ void gb_control_disable(struct gb_control *control) { dev_dbg(&control->connection->intf->dev, "%s\n", __func__); - gb_connection_exit(control->connection); + gb_connection_legacy_exit(control->connection); } void gb_control_destroy(struct gb_control *control) diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index 26a7d1a..e8d9cb9 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -23,7 +23,7 @@ static int legacy_probe(struct gb_bundle *bundle, dev_dbg(&bundle->dev, "enabling connection %s\n", connection->name); - ret = gb_connection_init(connection); + ret = gb_connection_legacy_init(connection); if (ret) goto err_connections_disable; } @@ -33,7 +33,7 @@ static int legacy_probe(struct gb_bundle *bundle, err_connections_disable: list_for_each_entry_reverse(connection, &bundle->connections, bundle_links) { - gb_connection_exit(connection); + gb_connection_legacy_exit(connection); } return ret; @@ -48,7 +48,7 @@ static void legacy_disconnect(struct gb_bundle *bundle) list_for_each_entry_reverse(connection, &bundle->connections, bundle_links) { - gb_connection_exit(connection); + gb_connection_legacy_exit(connection); } } diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index be62d30..0bbcdda 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -815,7 +815,7 @@ int gb_svc_add(struct gb_svc *svc) * is added from the connection request handler when enough * information has been received. */ - ret = gb_connection_init(svc->connection); + ret = gb_connection_legacy_init(svc->connection); if (ret) return ret; @@ -830,7 +830,7 @@ void gb_svc_del(struct gb_svc *svc) if (device_is_registered(&svc->dev)) device_del(&svc->dev); - gb_connection_exit(svc->connection); + gb_connection_legacy_exit(svc->connection); flush_workqueue(svc->wq); } -- cgit v0.10.2 From 1cbfab3804b185ce2744b5b8064d06ca19491e36 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:51:01 +0100 Subject: greybus: connection: remove disable from destructor Remove implicit disable of legacy connections from the destructor. This is a step towards removing the legacy-protocol handling from core. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index d0e3f91..29a8193 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -495,8 +495,6 @@ void gb_connection_destroy(struct gb_connection *connection) if (WARN_ON(!connection)) return; - gb_connection_legacy_exit(connection); - spin_lock_irq(&gb_connections_lock); list_del(&connection->bundle_links); list_del(&connection->hd_links); -- cgit v0.10.2 From bfa9a5e2d07937a7620d55ff6eb55b480bc13100 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:51:02 +0100 Subject: greybus: connection: add per-connection request handlers Add a connection request-handler field to struct gb_connection that is set when the connection is enabled. This is a step towards removing the legacy protocol abstraction from core, and will also be used to implement unidirectional connection states (e.g. only outgoing operations are allowed). Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 29a8193..3d7a9ca 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -387,7 +387,8 @@ static int gb_connection_protocol_get_version(struct gb_connection *connection) return 0; } -int gb_connection_enable(struct gb_connection *connection) +int gb_connection_enable(struct gb_connection *connection, + gb_request_handler_t handler) { int ret; @@ -400,6 +401,7 @@ int gb_connection_enable(struct gb_connection *connection) goto err_hd_cport_disable; spin_lock_irq(&connection->lock); + connection->handler = handler; connection->state = GB_CONNECTION_STATE_ENABLED; spin_unlock_irq(&connection->lock); @@ -435,15 +437,28 @@ void gb_connection_disable(struct gb_connection *connection) } EXPORT_SYMBOL_GPL(gb_connection_disable); +static int gb_legacy_request_handler(struct gb_operation *operation) +{ + struct gb_protocol *protocol = operation->connection->protocol; + + return protocol->request_recv(operation->type, operation); +} + int gb_connection_legacy_init(struct gb_connection *connection) { + gb_request_handler_t handler; int ret; ret = gb_connection_bind_protocol(connection); if (ret) return ret; - ret = gb_connection_enable(connection); + if (connection->protocol->request_recv) + handler = gb_legacy_request_handler; + else + handler = NULL; + + ret = gb_connection_enable(connection, handler); if (ret) goto err_unbind_protocol; diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index b0a67f2..ec0e469 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -20,6 +20,10 @@ enum gb_connection_state { GB_CONNECTION_STATE_DESTROYING = 3, }; +struct gb_operation; + +typedef int (*gb_request_handler_t)(struct gb_operation *); + struct gb_connection { struct gb_host_device *hd; struct gb_interface *intf; @@ -31,6 +35,8 @@ struct gb_connection { struct list_head hd_links; struct list_head bundle_links; + gb_request_handler_t handler; + struct gb_protocol *protocol; u8 protocol_id; u8 major; @@ -62,7 +68,8 @@ static inline bool gb_connection_is_static(struct gb_connection *connection) return !connection->intf; } -int gb_connection_enable(struct gb_connection *connection); +int gb_connection_enable(struct gb_connection *connection, + gb_request_handler_t handler); void gb_connection_disable(struct gb_connection *connection); int gb_connection_legacy_init(struct gb_connection *connection); diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index ae3ada0..4dc79cb 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -218,15 +218,11 @@ static void gb_message_cancel(struct gb_message *message) static void gb_operation_request_handle(struct gb_operation *operation) { struct gb_connection *connection = operation->connection; - struct gb_protocol *protocol = connection->protocol; int status; int ret; - if (!protocol) - return; - - if (protocol->request_recv) { - status = protocol->request_recv(operation->type, operation); + if (connection->handler) { + status = connection->handler(operation); } else { dev_err(&connection->hd->dev, "%s: unexpected incoming request of type 0x%02x\n", -- cgit v0.10.2 From 81fba24969c0ca427a8cd3d31bea10749f15b737 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:51:03 +0100 Subject: greybus: connection: always cancel operations on connection disable Always cancel all operations on connection disable and remove the now unused DESTROYING state. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 3d7a9ca..0fd7c05 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -426,12 +426,17 @@ EXPORT_SYMBOL_GPL(gb_connection_enable); void gb_connection_disable(struct gb_connection *connection) { + if (connection->state == GB_CONNECTION_STATE_DISABLED) + return; + gb_connection_control_disconnected(connection); spin_lock_irq(&connection->lock); connection->state = GB_CONNECTION_STATE_DISABLED; spin_unlock_irq(&connection->lock); + gb_connection_cancel_operations(connection, -ESHUTDOWN); + gb_connection_svc_connection_destroy(connection); gb_connection_hd_cport_disable(connection); } @@ -483,19 +488,13 @@ EXPORT_SYMBOL_GPL(gb_connection_legacy_init); void gb_connection_legacy_exit(struct gb_connection *connection) { - spin_lock_irq(&connection->lock); - if (connection->state != GB_CONNECTION_STATE_ENABLED) { - spin_unlock_irq(&connection->lock); + if (connection->state == GB_CONNECTION_STATE_DISABLED) return; - } - connection->state = GB_CONNECTION_STATE_DESTROYING; - spin_unlock_irq(&connection->lock); - - gb_connection_cancel_operations(connection, -ESHUTDOWN); - connection->protocol->connection_exit(connection); gb_connection_disable(connection); + connection->protocol->connection_exit(connection); + gb_connection_unbind_protocol(connection); } EXPORT_SYMBOL_GPL(gb_connection_legacy_exit); diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index ec0e469..b774b9c 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -17,7 +17,6 @@ enum gb_connection_state { GB_CONNECTION_STATE_INVALID = 0, GB_CONNECTION_STATE_DISABLED = 1, GB_CONNECTION_STATE_ENABLED = 2, - GB_CONNECTION_STATE_DESTROYING = 3, }; struct gb_operation; -- cgit v0.10.2 From 520c6eae991299720bcc0668326fb1e3a4bba3ba Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:51:04 +0100 Subject: greybus: connection: clean up operation cancellation on disable Move helper to cancel active operations above gb_connection_enable and simplify locking. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 0fd7c05..f782e8b 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -248,35 +248,6 @@ static void gb_connection_hd_cport_disable(struct gb_connection *connection) } /* - * Cancel all active operations on a connection. - * - * Should only be called during connection tear down. - */ -static void gb_connection_cancel_operations(struct gb_connection *connection, - int errno) -{ - struct gb_operation *operation; - - spin_lock_irq(&connection->lock); - while (!list_empty(&connection->operations)) { - operation = list_last_entry(&connection->operations, - struct gb_operation, links); - gb_operation_get(operation); - spin_unlock_irq(&connection->lock); - - if (gb_operation_is_incoming(operation)) - gb_operation_cancel_incoming(operation, errno); - else - gb_operation_cancel(operation, errno); - - gb_operation_put(operation); - - spin_lock_irq(&connection->lock); - } - spin_unlock_irq(&connection->lock); -} - -/* * Request the SVC to create a connection from AP's cport to interface's * cport. */ @@ -387,6 +358,33 @@ static int gb_connection_protocol_get_version(struct gb_connection *connection) return 0; } +/* + * Cancel all active operations on a connection. + * + * Locking: Called with connection lock held and state set to DISABLED. + */ +static void gb_connection_cancel_operations(struct gb_connection *connection, + int errno) +{ + struct gb_operation *operation; + + while (!list_empty(&connection->operations)) { + operation = list_last_entry(&connection->operations, + struct gb_operation, links); + gb_operation_get(operation); + spin_unlock_irq(&connection->lock); + + if (gb_operation_is_incoming(operation)) + gb_operation_cancel_incoming(operation, errno); + else + gb_operation_cancel(operation, errno); + + gb_operation_put(operation); + + spin_lock_irq(&connection->lock); + } +} + int gb_connection_enable(struct gb_connection *connection, gb_request_handler_t handler) { @@ -433,9 +431,8 @@ void gb_connection_disable(struct gb_connection *connection) spin_lock_irq(&connection->lock); connection->state = GB_CONNECTION_STATE_DISABLED; - spin_unlock_irq(&connection->lock); - gb_connection_cancel_operations(connection, -ESHUTDOWN); + spin_unlock_irq(&connection->lock); gb_connection_svc_connection_destroy(connection); gb_connection_hd_cport_disable(connection); -- cgit v0.10.2 From 192bee4b1a7adbf16d12721c77d6268c76428323 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:51:05 +0100 Subject: greybus: connection: disable operations on enable errors Make sure to cancel all (incoming) operations when failing to enable a connection. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index f782e8b..0159fbd 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -412,6 +412,7 @@ int gb_connection_enable(struct gb_connection *connection, err_svc_destroy: spin_lock_irq(&connection->lock); connection->state = GB_CONNECTION_STATE_DISABLED; + gb_connection_cancel_operations(connection, -ESHUTDOWN); spin_unlock_irq(&connection->lock); gb_connection_svc_connection_destroy(connection); -- cgit v0.10.2 From 23268785b288c25ab5ee2ec523982546b5353880 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:51:06 +0100 Subject: greybus: connection: make connection enable/disable thread safe Add connection mutex to protect connection enabling and disabling. This is needed to eventually allow drivers to manage the state of their connections during operation (i.e. post probe and pre disconnect). Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 0159fbd..56588f3 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -170,6 +170,7 @@ gb_connection_create(struct gb_host_device *hd, int hd_cport_id, connection->state = GB_CONNECTION_STATE_DISABLED; atomic_set(&connection->op_cycle, 0); + mutex_init(&connection->mutex); spin_lock_init(&connection->lock); INIT_LIST_HEAD(&connection->operations); @@ -390,9 +391,14 @@ int gb_connection_enable(struct gb_connection *connection, { int ret; + mutex_lock(&connection->mutex); + + if (connection->state == GB_CONNECTION_STATE_ENABLED) + goto out_unlock; + ret = gb_connection_hd_cport_enable(connection); if (ret) - return ret; + goto err_unlock; ret = gb_connection_svc_connection_create(connection); if (ret) @@ -407,6 +413,9 @@ int gb_connection_enable(struct gb_connection *connection, if (ret) goto err_svc_destroy; +out_unlock: + mutex_unlock(&connection->mutex); + return 0; err_svc_destroy: @@ -418,6 +427,8 @@ err_svc_destroy: gb_connection_svc_connection_destroy(connection); err_hd_cport_disable: gb_connection_hd_cport_disable(connection); +err_unlock: + mutex_unlock(&connection->mutex); return ret; } @@ -425,8 +436,10 @@ EXPORT_SYMBOL_GPL(gb_connection_enable); void gb_connection_disable(struct gb_connection *connection) { + mutex_lock(&connection->mutex); + if (connection->state == GB_CONNECTION_STATE_DISABLED) - return; + goto out_unlock; gb_connection_control_disconnected(connection); @@ -437,6 +450,9 @@ void gb_connection_disable(struct gb_connection *connection) gb_connection_svc_connection_destroy(connection); gb_connection_hd_cport_disable(connection); + +out_unlock: + mutex_unlock(&connection->mutex); } EXPORT_SYMBOL_GPL(gb_connection_disable); diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index b774b9c..e7c6feb 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -43,6 +43,7 @@ struct gb_connection { u8 module_major; u8 module_minor; + struct mutex mutex; spinlock_t lock; enum gb_connection_state state; struct list_head operations; -- cgit v0.10.2 From 570dfa7c55a76258b03a2d93f9db12dacc2ad3c6 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:51:07 +0100 Subject: greybus: connection: add unidirectional enabled state Add a new connection state ENABLED_TX in which only outgoing operations are allowed. This allows drivers to query the device during probe before allocating their state containers without having to worry about racing incoming requests. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 56588f3..8ae099d 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -396,6 +396,18 @@ int gb_connection_enable(struct gb_connection *connection, if (connection->state == GB_CONNECTION_STATE_ENABLED) goto out_unlock; + if (connection->state == GB_CONNECTION_STATE_ENABLED_TX) { + if (!handler) + goto out_unlock; + + spin_lock_irq(&connection->lock); + connection->handler = handler; + connection->state = GB_CONNECTION_STATE_ENABLED; + spin_unlock_irq(&connection->lock); + + goto out_unlock; + } + ret = gb_connection_hd_cport_enable(connection); if (ret) goto err_unlock; @@ -406,7 +418,10 @@ int gb_connection_enable(struct gb_connection *connection, spin_lock_irq(&connection->lock); connection->handler = handler; - connection->state = GB_CONNECTION_STATE_ENABLED; + if (handler) + connection->state = GB_CONNECTION_STATE_ENABLED; + else + connection->state = GB_CONNECTION_STATE_ENABLED_TX; spin_unlock_irq(&connection->lock); ret = gb_connection_control_connected(connection); @@ -422,6 +437,7 @@ err_svc_destroy: spin_lock_irq(&connection->lock); connection->state = GB_CONNECTION_STATE_DISABLED; gb_connection_cancel_operations(connection, -ESHUTDOWN); + connection->handler = NULL; spin_unlock_irq(&connection->lock); gb_connection_svc_connection_destroy(connection); @@ -446,6 +462,7 @@ void gb_connection_disable(struct gb_connection *connection) spin_lock_irq(&connection->lock); connection->state = GB_CONNECTION_STATE_DISABLED; gb_connection_cancel_operations(connection, -ESHUTDOWN); + connection->handler = NULL; spin_unlock_irq(&connection->lock); gb_connection_svc_connection_destroy(connection); diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index e7c6feb..ab2556d 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -16,7 +16,8 @@ enum gb_connection_state { GB_CONNECTION_STATE_INVALID = 0, GB_CONNECTION_STATE_DISABLED = 1, - GB_CONNECTION_STATE_ENABLED = 2, + GB_CONNECTION_STATE_ENABLED_TX = 2, + GB_CONNECTION_STATE_ENABLED = 3, }; struct gb_operation; @@ -70,6 +71,10 @@ static inline bool gb_connection_is_static(struct gb_connection *connection) int gb_connection_enable(struct gb_connection *connection, gb_request_handler_t handler); +static inline int gb_connection_enable_tx(struct gb_connection *connection) +{ + return gb_connection_enable(connection, NULL); +} void gb_connection_disable(struct gb_connection *connection); int gb_connection_legacy_init(struct gb_connection *connection); diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 4dc79cb..d6b3d1f 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -47,7 +47,9 @@ static int gb_operation_get_active(struct gb_operation *operation) spin_lock_irqsave(&connection->lock, flags); - if (connection->state != GB_CONNECTION_STATE_ENABLED) { + if (connection->state != GB_CONNECTION_STATE_ENABLED && + connection->state != GB_CONNECTION_STATE_ENABLED_TX && + !gb_operation_is_incoming(operation)) { spin_unlock_irqrestore(&connection->lock, flags); return -ENOTCONN; } @@ -906,7 +908,8 @@ void gb_connection_recv(struct gb_connection *connection, size_t msg_size; u16 operation_id; - if (connection->state != GB_CONNECTION_STATE_ENABLED) { + if (connection->state != GB_CONNECTION_STATE_ENABLED && + connection->state != GB_CONNECTION_STATE_ENABLED_TX) { dev_warn(dev, "%s: dropping %zu received bytes\n", connection->name, size); return; -- cgit v0.10.2 From beb6b7fede005ae351619b30a8940a04e797b9b2 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:51:08 +0100 Subject: greybus: connection: add helper to disable incoming operations Add helper to disable and flush incoming operations. This is intended to be used by core to flush any incoming requests before calling driver disconnect, but could potentially later be exported for driver use as well. Note that we currently flush all incoming operation and allow the request handlers to run, but cancel any responses sent. This may need to be refined later. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 8ae099d..c3207c8 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -386,6 +386,42 @@ static void gb_connection_cancel_operations(struct gb_connection *connection, } } +/* + * Cancel all active incoming operations on a connection. + * + * Locking: Called with connection lock held and state set to ENABLED_TX. + */ +static void +gb_connection_flush_incoming_operations(struct gb_connection *connection, + int errno) +{ + struct gb_operation *operation; + bool incoming; + + while (!list_empty(&connection->operations)) { + incoming = false; + list_for_each_entry(operation, &connection->operations, + links) { + if (gb_operation_is_incoming(operation)) { + gb_operation_get(operation); + incoming = true; + break; + } + } + + if (!incoming) + break; + + spin_unlock_irq(&connection->lock); + + /* FIXME: flush, not cancel? */ + gb_operation_cancel_incoming(operation, errno); + gb_operation_put(operation); + + spin_lock_irq(&connection->lock); + } +} + int gb_connection_enable(struct gb_connection *connection, gb_request_handler_t handler) { @@ -450,6 +486,24 @@ err_unlock: } EXPORT_SYMBOL_GPL(gb_connection_enable); +void gb_connection_disable_rx(struct gb_connection *connection) +{ + mutex_lock(&connection->mutex); + + spin_lock_irq(&connection->lock); + if (connection->state != GB_CONNECTION_STATE_ENABLED) { + spin_unlock_irq(&connection->lock); + goto out_unlock; + } + connection->state = GB_CONNECTION_STATE_ENABLED_TX; + gb_connection_flush_incoming_operations(connection, -ESHUTDOWN); + connection->handler = NULL; + spin_unlock_irq(&connection->lock); + +out_unlock: + mutex_unlock(&connection->mutex); +} + void gb_connection_disable(struct gb_connection *connection) { mutex_lock(&connection->mutex); diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index ab2556d..8813f54 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -75,6 +75,7 @@ static inline int gb_connection_enable_tx(struct gb_connection *connection) { return gb_connection_enable(connection, NULL); } +void gb_connection_disable_rx(struct gb_connection *connection); void gb_connection_disable(struct gb_connection *connection); int gb_connection_legacy_init(struct gb_connection *connection); -- cgit v0.10.2 From fa8369c130098da3276bafec425822aa74971905 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:51:09 +0100 Subject: greybus: core: disable incoming operations pre disconnect Disable and flush incoming operations before calling driver disconnect. Bundle drivers are still responsible for disabling their connections in their disconnect callback. Note that specifically the legacy protocols must have incoming operations disabled when their connection_exit callback is called as that is where their state is deallocated. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 28f48d7..cf06c9f 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -159,6 +159,10 @@ static int greybus_remove(struct device *dev) { struct greybus_driver *driver = to_greybus_driver(dev->driver); struct gb_bundle *bundle = to_gb_bundle(dev); + struct gb_connection *connection; + + list_for_each_entry(connection, &bundle->connections, bundle_links) + gb_connection_disable_rx(connection); driver->disconnect(bundle); return 0; -- cgit v0.10.2 From 02a54dd18f1eb831f4bf02ac763a4e9d805e1ba3 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:51:10 +0100 Subject: greybus: core: add defensive connection disable post disconnect Bundle drivers *must* disable their connections in the disconnect callback, but add a defensive test and warn about buggy drivers nonetheless. Note that bundle drivers would generally release their state containers in disconnect so a failure stop I/O could potentially lead to use-after-free bugs in any late operation completion callbacks. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index cf06c9f..493f392 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -165,6 +165,13 @@ static int greybus_remove(struct device *dev) gb_connection_disable_rx(connection); driver->disconnect(bundle); + + /* Catch buggy drivers that fail to disable their connections. */ + list_for_each_entry(connection, &bundle->connections, bundle_links) { + if (WARN_ON(connection->state != GB_CONNECTION_STATE_DISABLED)) + gb_connection_disable(connection); + } + return 0; } -- cgit v0.10.2 From 3e1b8c753d982bd4a63b0896a4ea68888f47502e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:51:11 +0100 Subject: greybus: firmware: remove skip-disconnected flag Remove the legacy protocol flag that was used to suppress sending the control disconnected operation. Instead rely on the fact that no control operations will be sent by core to an interface that has been removed (e.g. after having received a new hotplug event after the bootrom has jumped to the new image). Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/firmware.c b/drivers/staging/greybus/firmware.c index 11d605b..408c7e2 100644 --- a/drivers/staging/greybus/firmware.c +++ b/drivers/staging/greybus/firmware.c @@ -285,6 +285,5 @@ static struct gb_protocol firmware_protocol = { .connection_init = gb_firmware_connection_init, .connection_exit = gb_firmware_connection_exit, .request_recv = gb_firmware_request_recv, - .flags = GB_PROTOCOL_SKIP_CONTROL_DISCONNECTED, }; gb_builtin_protocol_driver(firmware_protocol); -- cgit v0.10.2 From bc3be1705c17e05c4d423a67a49a9f316d235bf4 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:51:12 +0100 Subject: greybus: connection: remove skip-connected legacy protocol flags Remove the legacy protocol flags that were used to suppress the connected and disconnected events. Instead send the connected and disconnected event for all bundle connections and explicitly exclude static connections and control connections. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index c3207c8..3f644ca 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -295,15 +295,17 @@ gb_connection_svc_connection_destroy(struct gb_connection *connection) /* Inform Interface about active CPorts */ static int gb_connection_control_connected(struct gb_connection *connection) { - struct gb_protocol *protocol = connection->protocol; struct gb_control *control; u16 cport_id = connection->intf_cport_id; int ret; - if (protocol->flags & GB_PROTOCOL_SKIP_CONTROL_CONNECTED) + if (gb_connection_is_static(connection)) return 0; - control = connection->bundle->intf->control; + control = connection->intf->control; + + if (connection == control->connection) + return 0; ret = gb_control_connected_operation(control, cport_id); if (ret) { @@ -319,15 +321,17 @@ static int gb_connection_control_connected(struct gb_connection *connection) static void gb_connection_control_disconnected(struct gb_connection *connection) { - struct gb_protocol *protocol = connection->protocol; struct gb_control *control; u16 cport_id = connection->intf_cport_id; int ret; - if (protocol->flags & GB_PROTOCOL_SKIP_CONTROL_DISCONNECTED) + if (gb_connection_is_static(connection)) return; - control = connection->bundle->intf->control; + control = connection->intf->control; + + if (connection == control->connection) + return; ret = gb_control_disconnected_operation(control, cport_id); if (ret) { diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index 1c4994b..12a9eca 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -159,7 +159,5 @@ static struct gb_protocol control_protocol = { .minor = GB_CONTROL_VERSION_MINOR, .connection_init = gb_control_connection_init, .connection_exit = gb_control_connection_exit, - .flags = GB_PROTOCOL_SKIP_CONTROL_CONNECTED | - GB_PROTOCOL_SKIP_CONTROL_DISCONNECTED, }; gb_builtin_protocol_driver(control_protocol); diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index f24281b..1f25c13 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -14,8 +14,6 @@ struct gb_connection; struct gb_operation; /* Possible flags for protocol drivers */ -#define GB_PROTOCOL_SKIP_CONTROL_CONNECTED BIT(0) /* Don't sent connected requests */ -#define GB_PROTOCOL_SKIP_CONTROL_DISCONNECTED BIT(1) /* Don't sent disconnected requests */ #define GB_PROTOCOL_SKIP_VERSION BIT(3) /* Don't send get_version() requests */ typedef int (*gb_connection_init_t)(struct gb_connection *); diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 0bbcdda..245cf4d 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -864,8 +864,6 @@ static struct gb_protocol svc_protocol = { .connection_init = gb_svc_connection_init, .connection_exit = gb_svc_connection_exit, .request_recv = gb_svc_request_recv, - .flags = GB_PROTOCOL_SKIP_CONTROL_CONNECTED | - GB_PROTOCOL_SKIP_CONTROL_DISCONNECTED | - GB_PROTOCOL_SKIP_VERSION, + .flags = GB_PROTOCOL_SKIP_VERSION, }; gb_builtin_protocol_driver(svc_protocol); -- cgit v0.10.2 From 6bd6e148930b6f6dff7a6d664b37ba76d6d2c75e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:51:13 +0100 Subject: greybus: greybus_protocols: remove control-protocol version Remove control-protocol version from the exported protocol definitions as it is an implementation detail that makes no sense to export. Currently gbsim uses the kernel's control-protocol version definitions directly instead of reporting the version of the protocol it actually implements. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index 12a9eca..d79807c 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -12,6 +12,11 @@ #include #include "greybus.h" +/* Highest control-protocol version supported */ +#define GB_CONTROL_VERSION_MAJOR 0 +#define GB_CONTROL_VERSION_MINOR 1 + + /* Get Manifest's size from the interface */ int gb_control_get_manifest_size_operation(struct gb_interface *intf) { diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 55e99b7..c563e74 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -115,10 +115,6 @@ struct gb_protocol_version_response { /* Control Protocol */ -/* Version of the Greybus control protocol we support */ -#define GB_CONTROL_VERSION_MAJOR 0x00 -#define GB_CONTROL_VERSION_MINOR 0x01 - /* Greybus control request types */ #define GB_CONTROL_TYPE_PROBE_AP 0x02 #define GB_CONTROL_TYPE_GET_MANIFEST_SIZE 0x03 -- cgit v0.10.2 From e217ae762bccb0ba0109887cefec3e20e5549a48 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:51:14 +0100 Subject: greybus: control: drop legacy-protocol dependency Drop dependency on the legacy protocol abstraction. Instead implement the protocol-specific version request directly, and use the new interface for managing the control connection. Note that the version request is being removed from most protocols, but we need to keep the current request for the control protocol as-is indefinitely to maintain backwards compatibility (e.g. with the ES2/ES3 bootrom). Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index d79807c..3077940 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -17,6 +17,43 @@ #define GB_CONTROL_VERSION_MINOR 1 +int gb_control_get_version(struct gb_control *control) +{ + struct gb_interface *intf = control->connection->intf; + struct gb_control_version_request request; + struct gb_control_version_response response; + int ret; + + request.major = GB_CONTROL_VERSION_MAJOR; + request.minor = GB_CONTROL_VERSION_MINOR; + + ret = gb_operation_sync(control->connection, + GB_CONTROL_TYPE_VERSION, + &request, sizeof(request), &response, + sizeof(response)); + if (ret) { + dev_err(&intf->dev, + "failed to get control-protocol version: %d\n", + ret); + return ret; + } + + if (response.major > request.major) { + dev_err(&intf->dev, + "unsupported major control-protocol version (%u > %u)\n", + response.major, request.major); + return -ENOTSUPP; + } + + control->protocol_major = response.major; + control->protocol_minor = response.minor; + + dev_dbg(&intf->dev, "%s - %u.%u\n", __func__, response.major, + response.minor); + + return 0; +} + /* Get Manifest's size from the interface */ int gb_control_get_manifest_size_operation(struct gb_interface *intf) { @@ -121,7 +158,7 @@ int gb_control_enable(struct gb_control *control) dev_dbg(&control->connection->intf->dev, "%s\n", __func__); - ret = gb_connection_legacy_init(control->connection); + ret = gb_connection_enable_tx(control->connection); if (ret) { dev_err(&control->connection->intf->dev, "failed to enable control connection: %d\n", @@ -129,14 +166,23 @@ int gb_control_enable(struct gb_control *control) return ret; } + ret = gb_control_get_version(control); + if (ret) + goto err_disable_connection; + return 0; + +err_disable_connection: + gb_connection_disable(control->connection); + + return ret; } void gb_control_disable(struct gb_control *control) { dev_dbg(&control->connection->intf->dev, "%s\n", __func__); - gb_connection_legacy_exit(control->connection); + gb_connection_disable(control->connection); } void gb_control_destroy(struct gb_control *control) @@ -144,25 +190,3 @@ void gb_control_destroy(struct gb_control *control) gb_connection_destroy(control->connection); kfree(control); } - -static int gb_control_connection_init(struct gb_connection *connection) -{ - dev_dbg(&connection->intf->dev, "%s\n", __func__); - - return 0; -} - -static void gb_control_connection_exit(struct gb_connection *connection) -{ - dev_dbg(&connection->intf->dev, "%s\n", __func__); -} - -static struct gb_protocol control_protocol = { - .name = "control", - .id = GREYBUS_PROTOCOL_CONTROL, - .major = GB_CONTROL_VERSION_MAJOR, - .minor = GB_CONTROL_VERSION_MINOR, - .connection_init = gb_control_connection_init, - .connection_exit = gb_control_connection_exit, -}; -gb_builtin_protocol_driver(control_protocol); diff --git a/drivers/staging/greybus/control.h b/drivers/staging/greybus/control.h index 7cb3dd2..dd0a2d7 100644 --- a/drivers/staging/greybus/control.h +++ b/drivers/staging/greybus/control.h @@ -12,6 +12,9 @@ struct gb_control { struct gb_connection *connection; + + u8 protocol_major; + u8 protocol_minor; }; struct gb_control *gb_control_create(struct gb_interface *intf); @@ -26,6 +29,4 @@ int gb_control_get_manifest_operation(struct gb_interface *intf, void *manifest, size_t size); int gb_control_get_interface_version_operation(struct gb_interface *intf); -int gb_control_protocol_init(void); -void gb_control_protocol_exit(void); #endif /* __CONTROL_H */ diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 493f392..6674b27 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -234,12 +234,6 @@ static int __init gb_init(void) goto error_operation; } - retval = gb_control_protocol_init(); - if (retval) { - pr_err("gb_control_protocol_init failed\n"); - goto error_control; - } - retval = gb_svc_protocol_init(); if (retval) { pr_err("gb_svc_protocol_init failed\n"); @@ -265,8 +259,6 @@ error_legacy: error_firmware: gb_svc_protocol_exit(); error_svc: - gb_control_protocol_exit(); -error_control: gb_operation_exit(); error_operation: gb_hd_exit(); @@ -284,7 +276,6 @@ static void __exit gb_exit(void) gb_legacy_exit(); gb_firmware_protocol_exit(); gb_svc_protocol_exit(); - gb_control_protocol_exit(); gb_operation_exit(); gb_hd_exit(); bus_unregister(&greybus_bus_type); diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index c563e74..abbb214 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -116,6 +116,7 @@ struct gb_protocol_version_response { /* Control Protocol */ /* Greybus control request types */ +#define GB_CONTROL_TYPE_VERSION 0x01 #define GB_CONTROL_TYPE_PROBE_AP 0x02 #define GB_CONTROL_TYPE_GET_MANIFEST_SIZE 0x03 #define GB_CONTROL_TYPE_GET_MANIFEST 0x04 @@ -123,6 +124,16 @@ struct gb_protocol_version_response { #define GB_CONTROL_TYPE_DISCONNECTED 0x06 #define GB_CONTROL_TYPE_INTERFACE_VERSION 0x0a +struct gb_control_version_request { + __u8 major; + __u8 minor; +} __packed; + +struct gb_control_version_response { + __u8 major; + __u8 minor; +} __packed; + /* Control protocol manifest get size request has no payload*/ struct gb_control_get_manifest_size_response { __le16 size; -- cgit v0.10.2 From 84427943d2da5f55d5cc83d83ba2a75c2079d1dd Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:51:15 +0100 Subject: greybus: svc: drop legacy-protocol dependency Drop dependency on the legacy protocol abstraction. Remove the now unused and last legacy-protocol flag GB_PROTOCOL_SKIP_VERSION along with the protocol-flag feature. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 3f644ca..3339ef9 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -341,17 +341,12 @@ gb_connection_control_disconnected(struct gb_connection *connection) } /* - * Request protocol version supported by the module. We don't need to do - * this for SVC as that is initiated by the SVC. + * Request protocol version supported by the module. */ static int gb_connection_protocol_get_version(struct gb_connection *connection) { - struct gb_protocol *protocol = connection->protocol; int ret; - if (protocol->flags & GB_PROTOCOL_SKIP_VERSION) - return 0; - ret = gb_protocol_get_version(connection); if (ret) { dev_err(&connection->hd->dev, diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 6674b27..a72191f 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -234,12 +234,6 @@ static int __init gb_init(void) goto error_operation; } - retval = gb_svc_protocol_init(); - if (retval) { - pr_err("gb_svc_protocol_init failed\n"); - goto error_svc; - } - retval = gb_firmware_protocol_init(); if (retval) { pr_err("gb_firmware_protocol_init failed\n"); @@ -257,8 +251,6 @@ static int __init gb_init(void) error_legacy: gb_firmware_protocol_exit(); error_firmware: - gb_svc_protocol_exit(); -error_svc: gb_operation_exit(); error_operation: gb_hd_exit(); @@ -275,7 +267,6 @@ static void __exit gb_exit(void) { gb_legacy_exit(); gb_firmware_protocol_exit(); - gb_svc_protocol_exit(); gb_operation_exit(); gb_hd_exit(); bus_unregister(&greybus_bus_type); diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index 1f25c13..26c59ef 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -13,9 +13,6 @@ struct gb_connection; struct gb_operation; -/* Possible flags for protocol drivers */ -#define GB_PROTOCOL_SKIP_VERSION BIT(3) /* Don't send get_version() requests */ - typedef int (*gb_connection_init_t)(struct gb_connection *); typedef void (*gb_connection_exit_t)(struct gb_connection *); typedef int (*gb_request_recv_t)(u8, struct gb_operation *); @@ -30,7 +27,6 @@ struct gb_protocol { u8 major; u8 minor; u8 count; - unsigned long flags; struct list_head links; /* global list */ diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 245cf4d..fcdee90 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -690,10 +690,11 @@ static int gb_svc_intf_reset_recv(struct gb_operation *op) return 0; } -static int gb_svc_request_recv(u8 type, struct gb_operation *op) +static int gb_svc_request_handler(struct gb_operation *op) { struct gb_connection *connection = op->connection; struct gb_svc *svc = connection->private; + u8 type = op->type; int ret = 0; /* @@ -815,7 +816,7 @@ int gb_svc_add(struct gb_svc *svc) * is added from the connection request handler when enough * information has been received. */ - ret = gb_connection_legacy_init(svc->connection); + ret = gb_connection_enable(svc->connection, gb_svc_request_handler); if (ret) return ret; @@ -830,7 +831,7 @@ void gb_svc_del(struct gb_svc *svc) if (device_is_registered(&svc->dev)) device_del(&svc->dev); - gb_connection_legacy_exit(svc->connection); + gb_connection_disable(svc->connection); flush_workqueue(svc->wq); } @@ -839,31 +840,3 @@ void gb_svc_put(struct gb_svc *svc) { put_device(&svc->dev); } - -static int gb_svc_connection_init(struct gb_connection *connection) -{ - struct gb_svc *svc = connection->private; - - dev_dbg(&svc->dev, "%s\n", __func__); - - return 0; -} - -static void gb_svc_connection_exit(struct gb_connection *connection) -{ - struct gb_svc *svc = connection->private; - - dev_dbg(&svc->dev, "%s\n", __func__); -} - -static struct gb_protocol svc_protocol = { - .name = "svc", - .id = GREYBUS_PROTOCOL_SVC, - .major = GB_SVC_VERSION_MAJOR, - .minor = GB_SVC_VERSION_MINOR, - .connection_init = gb_svc_connection_init, - .connection_exit = gb_svc_connection_exit, - .request_recv = gb_svc_request_recv, - .flags = GB_PROTOCOL_SKIP_VERSION, -}; -gb_builtin_protocol_driver(svc_protocol); -- cgit v0.10.2 From 50dfb87865790bf8ef86a1c6898cde4e0df212fd Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:51:16 +0100 Subject: greybus: connection: move legacy-protocol handling to legacy driver Move legacy protocol and connection handling to the legacy driver. Rename the former global functions using a common legacy_ prefix. Note that all legacy protocols suffer from a connection initialisation race in that the protocol-specific initialisation, which includes allocation of protocol-specific state containers, can not happen until *after* the connection has been enabled. This is a major flaw in the original design that we can now finally address by converting the legacy protocol drivers into proper bundle (class) drivers. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 3339ef9..7a967be 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -12,10 +12,6 @@ #include "greybus.h" -static int gb_connection_bind_protocol(struct gb_connection *connection); -static void gb_connection_unbind_protocol(struct gb_connection *connection); - - static DEFINE_SPINLOCK(gb_connections_lock); /* This is only used at initialization time; no locking is required. */ @@ -341,24 +337,6 @@ gb_connection_control_disconnected(struct gb_connection *connection) } /* - * Request protocol version supported by the module. - */ -static int gb_connection_protocol_get_version(struct gb_connection *connection) -{ - int ret; - - ret = gb_protocol_get_version(connection); - if (ret) { - dev_err(&connection->hd->dev, - "%s: failed to get protocol version: %d\n", - connection->name, ret); - return ret; - } - - return 0; -} - -/* * Cancel all active operations on a connection. * * Locking: Called with connection lock held and state set to DISABLED. @@ -526,63 +504,6 @@ out_unlock: } EXPORT_SYMBOL_GPL(gb_connection_disable); -static int gb_legacy_request_handler(struct gb_operation *operation) -{ - struct gb_protocol *protocol = operation->connection->protocol; - - return protocol->request_recv(operation->type, operation); -} - -int gb_connection_legacy_init(struct gb_connection *connection) -{ - gb_request_handler_t handler; - int ret; - - ret = gb_connection_bind_protocol(connection); - if (ret) - return ret; - - if (connection->protocol->request_recv) - handler = gb_legacy_request_handler; - else - handler = NULL; - - ret = gb_connection_enable(connection, handler); - if (ret) - goto err_unbind_protocol; - - ret = gb_connection_protocol_get_version(connection); - if (ret) - goto err_disable; - - ret = connection->protocol->connection_init(connection); - if (ret) - goto err_disable; - - return 0; - -err_disable: - gb_connection_disable(connection); -err_unbind_protocol: - gb_connection_unbind_protocol(connection); - - return ret; -} -EXPORT_SYMBOL_GPL(gb_connection_legacy_init); - -void gb_connection_legacy_exit(struct gb_connection *connection) -{ - if (connection->state == GB_CONNECTION_STATE_DISABLED) - return; - - gb_connection_disable(connection); - - connection->protocol->connection_exit(connection); - - gb_connection_unbind_protocol(connection); -} -EXPORT_SYMBOL_GPL(gb_connection_legacy_exit); - /* * Tear down a previously set up connection. */ @@ -639,31 +560,3 @@ void gb_connection_latency_tag_disable(struct gb_connection *connection) } } EXPORT_SYMBOL_GPL(gb_connection_latency_tag_disable); - -static int gb_connection_bind_protocol(struct gb_connection *connection) -{ - struct gb_protocol *protocol; - - protocol = gb_protocol_get(connection->protocol_id, - connection->major, - connection->minor); - if (!protocol) { - dev_err(&connection->hd->dev, - "protocol 0x%02x version %u.%u not found\n", - connection->protocol_id, - connection->major, connection->minor); - return -EPROTONOSUPPORT; - } - connection->protocol = protocol; - - return 0; -} - -static void gb_connection_unbind_protocol(struct gb_connection *connection) -{ - struct gb_protocol *protocol = connection->protocol; - - gb_protocol_put(protocol); - - connection->protocol = NULL; -} diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 8813f54..33deeb6 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -78,9 +78,6 @@ static inline int gb_connection_enable_tx(struct gb_connection *connection) void gb_connection_disable_rx(struct gb_connection *connection); void gb_connection_disable(struct gb_connection *connection); -int gb_connection_legacy_init(struct gb_connection *connection); -void gb_connection_legacy_exit(struct gb_connection *connection); - void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id, u8 *data, size_t length); diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index e8d9cb9..fd847f4 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -9,6 +9,106 @@ #include "greybus.h" #include "legacy.h" +#include "protocol.h" + + +static int legacy_connection_get_version(struct gb_connection *connection) +{ + int ret; + + ret = gb_protocol_get_version(connection); + if (ret) { + dev_err(&connection->hd->dev, + "%s: failed to get protocol version: %d\n", + connection->name, ret); + return ret; + } + + return 0; +} + +static int legacy_connection_bind_protocol(struct gb_connection *connection) +{ + struct gb_protocol *protocol; + + protocol = gb_protocol_get(connection->protocol_id, + connection->major, + connection->minor); + if (!protocol) { + dev_err(&connection->hd->dev, + "protocol 0x%02x version %u.%u not found\n", + connection->protocol_id, + connection->major, connection->minor); + return -EPROTONOSUPPORT; + } + connection->protocol = protocol; + + return 0; +} + +static void legacy_connection_unbind_protocol(struct gb_connection *connection) +{ + struct gb_protocol *protocol = connection->protocol; + + gb_protocol_put(protocol); + + connection->protocol = NULL; +} + +static int legacy_request_handler(struct gb_operation *operation) +{ + struct gb_protocol *protocol = operation->connection->protocol; + + return protocol->request_recv(operation->type, operation); +} + +static int legacy_connection_init(struct gb_connection *connection) +{ + gb_request_handler_t handler; + int ret; + + ret = legacy_connection_bind_protocol(connection); + if (ret) + return ret; + + if (connection->protocol->request_recv) + handler = legacy_request_handler; + else + handler = NULL; + + ret = gb_connection_enable(connection, handler); + if (ret) + goto err_unbind_protocol; + + ret = legacy_connection_get_version(connection); + if (ret) + goto err_disable; + + ret = connection->protocol->connection_init(connection); + if (ret) + goto err_disable; + + return 0; + +err_disable: + gb_connection_disable(connection); +err_unbind_protocol: + legacy_connection_unbind_protocol(connection); + + return ret; +} + +static void legacy_connection_exit(struct gb_connection *connection) +{ + if (connection->state == GB_CONNECTION_STATE_DISABLED) + return; + + gb_connection_disable(connection); + + connection->protocol->connection_exit(connection); + + legacy_connection_unbind_protocol(connection); +} static int legacy_probe(struct gb_bundle *bundle, const struct greybus_bundle_id *id) @@ -23,7 +123,7 @@ static int legacy_probe(struct gb_bundle *bundle, dev_dbg(&bundle->dev, "enabling connection %s\n", connection->name); - ret = gb_connection_legacy_init(connection); + ret = legacy_connection_init(connection); if (ret) goto err_connections_disable; } @@ -33,7 +133,7 @@ static int legacy_probe(struct gb_bundle *bundle, err_connections_disable: list_for_each_entry_reverse(connection, &bundle->connections, bundle_links) { - gb_connection_legacy_exit(connection); + legacy_connection_exit(connection); } return ret; @@ -48,7 +148,7 @@ static void legacy_disconnect(struct gb_bundle *bundle) list_for_each_entry_reverse(connection, &bundle->connections, bundle_links) { - gb_connection_legacy_exit(connection); + legacy_connection_exit(connection); } } diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c index d69f648..057ab60 100644 --- a/drivers/staging/greybus/protocol.c +++ b/drivers/staging/greybus/protocol.c @@ -141,6 +141,7 @@ struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor) return protocol; } +EXPORT_SYMBOL_GPL(gb_protocol_get); int gb_protocol_get_version(struct gb_connection *connection) { @@ -197,3 +198,4 @@ void gb_protocol_put(struct gb_protocol *protocol) out: spin_unlock_irq(&gb_protocols_lock); } +EXPORT_SYMBOL_GPL(gb_protocol_put); -- cgit v0.10.2 From 01547770e6fc283ce74944415fc069d287de082a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:51:17 +0100 Subject: greybus: legacy: use protocol pointer to determine state Use the protocol pointer to determine the legacy connection state. This is needed to allow core disable connections when an interface has been hot-unplugged without the legacy protocols leaking its resources. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index fd847f4..a2c0b9b 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -100,7 +100,7 @@ err_unbind_protocol: static void legacy_connection_exit(struct gb_connection *connection) { - if (connection->state == GB_CONNECTION_STATE_DISABLED) + if (!connection->protocol) return; gb_connection_disable(connection); -- cgit v0.10.2 From 47a2e6769e8194da5570eaed7fc43f5abec18809 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:51:18 +0100 Subject: greybus: core: disable bundle connections on hot-unplug Disable bundle connections in core before calling driver disconnect in case the interface is already gone. This avoids unnecessary timeouts on hot-unplug when a driver does I/O in its disconnect callback. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index a72191f..522d059 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -161,8 +161,12 @@ static int greybus_remove(struct device *dev) struct gb_bundle *bundle = to_gb_bundle(dev); struct gb_connection *connection; - list_for_each_entry(connection, &bundle->connections, bundle_links) - gb_connection_disable_rx(connection); + list_for_each_entry(connection, &bundle->connections, bundle_links) { + if (bundle->intf->disconnected) + gb_connection_disable(connection); + else + gb_connection_disable_rx(connection); + } driver->disconnect(bundle); -- cgit v0.10.2 From 357de006573f0dbbd5e214dd3f2fe808157ec530 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:51:19 +0100 Subject: greybus: svc: store protocol version Store the "negotiated" protocol version to use in the svc state struct instead of the connection struct. The generic concept of a connection version is going away in favour of bundle-class versions. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index fcdee90..bc64f48 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -383,15 +383,15 @@ static int gb_svc_version_request(struct gb_operation *op) return -ENOTSUPP; } - connection->module_major = request->major; - connection->module_minor = request->minor; + svc->protocol_major = request->major; + svc->protocol_minor = request->minor; if (!gb_operation_response_alloc(op, sizeof(*response), GFP_KERNEL)) return -ENOMEM; response = op->response->payload; - response->major = connection->module_major; - response->minor = connection->module_minor; + response->major = svc->protocol_major; + response->minor = svc->protocol_minor; return 0; } diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index 8567615..4abc5ef 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -27,6 +27,9 @@ struct gb_svc { u16 endo_id; u8 ap_intf_id; + + u8 protocol_major; + u8 protocol_minor; }; #define to_gb_svc(d) container_of(d, struct gb_svc, d) -- cgit v0.10.2 From 96a9b9b0eb2c5b9626bdad02c057fb22f133fc86 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:51:20 +0100 Subject: greybus: connection: remove broken protocol-version handling Remove the broken legacy protocol-version handling from core and move it to the legacy driver instead. Note that version handling has always been broken as legacy protocols were looked up and bound to connections before the connections were enabled and version negotiation could take place (over that very connection). Document that in the legacy driver as well. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 7a967be..ebd038e 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -120,8 +120,6 @@ gb_connection_create(struct gb_host_device *hd, int hd_cport_id, struct gb_connection *connection; struct ida *id_map = &hd->cport_id_map; int ida_start, ida_end; - u8 major = 0; - u8 minor = 1; /* * If a manifest tries to reuse a cport, reject it. We @@ -159,8 +157,6 @@ gb_connection_create(struct gb_host_device *hd, int hd_cport_id, connection->intf = intf; connection->protocol_id = protocol_id; - connection->major = major; - connection->minor = minor; connection->bundle = bundle; connection->state = GB_CONNECTION_STATE_DISABLED; diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 33deeb6..66f37b2 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -39,8 +39,6 @@ struct gb_connection { struct gb_protocol *protocol; u8 protocol_id; - u8 major; - u8 minor; u8 module_major; u8 module_minor; diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index a2c0b9b..1864823 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -30,15 +30,25 @@ static int legacy_connection_get_version(struct gb_connection *connection) static int legacy_connection_bind_protocol(struct gb_connection *connection) { struct gb_protocol *protocol; + u8 major, minor; + + /* + * The legacy protocols have always been looked up using a hard-coded + * version of 0.1, despite (or perhaps rather, due to) the fact that + * module version negotiation could not take place until after the + * protocol was bound. + */ + major = 0; + minor = 1; protocol = gb_protocol_get(connection->protocol_id, - connection->major, - connection->minor); + major, + minor); if (!protocol) { dev_err(&connection->hd->dev, "protocol 0x%02x version %u.%u not found\n", connection->protocol_id, - connection->major, connection->minor); + major, minor); return -EPROTONOSUPPORT; } connection->protocol = protocol; -- cgit v0.10.2 From b807aa7aa51129b1754e7d17f6a2e30e3c6f7a4b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:51:21 +0100 Subject: greybus: control: add bundle-version operation Add bundle-version operation to fetch the version of the bundle class. Retrieve the bundle version of all bundles when initialising the interface in case the control-protocol version is greater than 0.1. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.h b/drivers/staging/greybus/bundle.h index 682ec32..837682d 100644 --- a/drivers/staging/greybus/bundle.h +++ b/drivers/staging/greybus/bundle.h @@ -16,8 +16,12 @@ struct gb_bundle { struct device dev; struct gb_interface *intf; + u8 id; u8 class; + u8 class_major; + u8 class_minor; + struct list_head connections; u8 *state; diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index 3077940..0e50fd4 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -54,6 +54,54 @@ int gb_control_get_version(struct gb_control *control) return 0; } +static int gb_control_get_bundle_version(struct gb_control *control, + struct gb_bundle *bundle) +{ + struct gb_interface *intf = control->connection->intf; + struct gb_control_bundle_version_request request; + struct gb_control_bundle_version_response response; + int ret; + + request.bundle_id = bundle->id; + + ret = gb_operation_sync(control->connection, + GB_CONTROL_TYPE_BUNDLE_VERSION, + &request, sizeof(request), + &response, sizeof(response)); + if (ret) { + dev_err(&intf->dev, + "failed to get bundle %u class version: %d\n", + bundle->id, ret); + return ret; + } + + bundle->class_major = response.major; + bundle->class_minor = response.minor; + + dev_dbg(&intf->dev, "%s - %u: %u.%u\n", __func__, bundle->id, + response.major, response.minor); + + return 0; +} + +int gb_control_get_bundle_versions(struct gb_control *control) +{ + struct gb_interface *intf = control->connection->intf; + struct gb_bundle *bundle; + int ret; + + if (!control->has_bundle_version) + return 0; + + list_for_each_entry(bundle, &intf->bundles, links) { + ret = gb_control_get_bundle_version(control, bundle); + if (ret) + return ret; + } + + return 0; +} + /* Get Manifest's size from the interface */ int gb_control_get_manifest_size_operation(struct gb_interface *intf) { @@ -170,6 +218,9 @@ int gb_control_enable(struct gb_control *control) if (ret) goto err_disable_connection; + if (control->protocol_major > 0 || control->protocol_minor > 1) + control->has_bundle_version = true; + return 0; err_disable_connection: diff --git a/drivers/staging/greybus/control.h b/drivers/staging/greybus/control.h index dd0a2d7..d31e7c6 100644 --- a/drivers/staging/greybus/control.h +++ b/drivers/staging/greybus/control.h @@ -15,6 +15,8 @@ struct gb_control { u8 protocol_major; u8 protocol_minor; + + bool has_bundle_version; }; struct gb_control *gb_control_create(struct gb_interface *intf); @@ -22,6 +24,7 @@ int gb_control_enable(struct gb_control *control); void gb_control_disable(struct gb_control *control); void gb_control_destroy(struct gb_control *control); +int gb_control_get_bundle_versions(struct gb_control *control); int gb_control_connected_operation(struct gb_control *control, u16 cport_id); int gb_control_disconnected_operation(struct gb_control *control, u16 cport_id); int gb_control_get_manifest_size_operation(struct gb_interface *intf); diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index abbb214..84fb6ab 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -123,6 +123,7 @@ struct gb_protocol_version_response { #define GB_CONTROL_TYPE_CONNECTED 0x05 #define GB_CONTROL_TYPE_DISCONNECTED 0x06 #define GB_CONTROL_TYPE_INTERFACE_VERSION 0x0a +#define GB_CONTROL_TYPE_BUNDLE_VERSION 0x0b struct gb_control_version_request { __u8 major; @@ -134,6 +135,15 @@ struct gb_control_version_response { __u8 minor; } __packed; +struct gb_control_bundle_version_request { + __u8 bundle_id; +} __packed; + +struct gb_control_bundle_version_response { + __u8 major; + __u8 minor; +} __packed; + /* Control protocol manifest get size request has no payload*/ struct gb_control_get_manifest_size_response { __le16 size; diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index c345350..9c05d81 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -228,6 +228,10 @@ int gb_interface_init(struct gb_interface *intf, u8 device_id) if (ret) goto free_manifest; + ret = gb_control_get_bundle_versions(intf->control); + if (ret) + goto free_manifest; + /* Register the interface and its bundles. */ ret = device_add(&intf->dev); if (ret) { -- cgit v0.10.2 From 2edbf5ffbf5ef8b92518e57687e96a7d34ddd3c4 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:51:22 +0100 Subject: greybus: connection: remove WARN_ON from destroy Remove WARN_ON from connection destroy testing for a NULL-connection when destroying a connection. This will allow for simpler driver code when releasing driver-managed connections. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index ebd038e..d1508e2 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -507,7 +507,7 @@ void gb_connection_destroy(struct gb_connection *connection) { struct ida *id_map; - if (WARN_ON(!connection)) + if (!connection) return; spin_lock_irq(&gb_connections_lock); -- cgit v0.10.2 From c3681f6c92df6c4ec834fc8e3fa1905e73952630 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:51:23 +0100 Subject: greybus: connection: destroy workqueue at unregister Destroy the work queue when the connection is destroyed/deregistered instead of when the last reference is dropped. The work queue is not needed once the connection has been deregistered, and no operations will ever be added to it again (handled by checking connection->state) even if the connection object may not be deallocated until the final reference is dropped. The work-queue name is set based on the host-device name and host-device cport id, something which guarantees a unique name. This would no longer be true if the work queue was not destroyed at connection deregistration as a new connection could then be created for that very same host cport. This is not necessarily a problem unless some work queue features are used that require unique work-queue names, but let's try to be well behaved. Also update an obsolete comment and make explicit that a connection must be disabled before being destroyed. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index d1508e2..1d7c21e 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -73,7 +73,7 @@ static void gb_connection_kref_release(struct kref *kref) struct gb_connection *connection; connection = container_of(kref, struct gb_connection, kref); - destroy_workqueue(connection->wq); + kfree(connection); mutex_unlock(&connection_mutex); } @@ -500,9 +500,7 @@ out_unlock: } EXPORT_SYMBOL_GPL(gb_connection_disable); -/* - * Tear down a previously set up connection. - */ +/* Caller must have disabled the connection before destroying it. */ void gb_connection_destroy(struct gb_connection *connection) { struct ida *id_map; @@ -515,6 +513,8 @@ void gb_connection_destroy(struct gb_connection *connection) list_del(&connection->hd_links); spin_unlock_irq(&gb_connections_lock); + destroy_workqueue(connection->wq); + id_map = &connection->hd->cport_id_map; ida_simple_remove(id_map, connection->hd_cport_id); connection->hd_cport_id = CPORT_ID_BAD; -- cgit v0.10.2 From c6d64a19cdb39680460ab9f153e33843aa8c825c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:51:24 +0100 Subject: greybus: connection: drop the connection_mutex Drop the useless connection_mutex that did not, and can not be used to prevent connection lookup races in atomic context and therefore serves no purpose. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 1d7c21e..bfd2c0d 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -66,8 +66,6 @@ void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id, } EXPORT_SYMBOL_GPL(greybus_data_rcvd); -static DEFINE_MUTEX(connection_mutex); - static void gb_connection_kref_release(struct kref *kref) { struct gb_connection *connection; @@ -75,7 +73,6 @@ static void gb_connection_kref_release(struct kref *kref) connection = container_of(kref, struct gb_connection, kref); kfree(connection); - mutex_unlock(&connection_mutex); } static void gb_connection_init_name(struct gb_connection *connection) @@ -519,8 +516,7 @@ void gb_connection_destroy(struct gb_connection *connection) ida_simple_remove(id_map, connection->hd_cport_id); connection->hd_cport_id = CPORT_ID_BAD; - kref_put_mutex(&connection->kref, gb_connection_kref_release, - &connection_mutex); + kref_put(&connection->kref, gb_connection_kref_release); } void gb_connection_latency_tag_enable(struct gb_connection *connection) -- cgit v0.10.2 From 0e46fab7dd5afbb4db97d9520812c57e9301bfc2 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:51:25 +0100 Subject: greybus: connection: fix lookup race Fix longstanding race that could lead to a connection being destroyed while processing an incoming message due to missing reference counting when looking up the connection. Add helpers to manipulate the connection kref. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index bfd2c0d..d215c5c 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -12,6 +12,9 @@ #include "greybus.h" +static void gb_connection_kref_release(struct kref *kref); + + static DEFINE_SPINLOCK(gb_connections_lock); /* This is only used at initialization time; no locking is required. */ @@ -30,6 +33,19 @@ gb_connection_intf_find(struct gb_interface *intf, u16 cport_id) return NULL; } +static void gb_connection_get(struct gb_connection *connection) +{ + kref_get(&connection->kref); +} + +static void gb_connection_put(struct gb_connection *connection) +{ + kref_put(&connection->kref, gb_connection_kref_release); +} + +/* + * Returns a reference-counted pointer to the connection if found. + */ static struct gb_connection * gb_connection_hd_find(struct gb_host_device *hd, u16 cport_id) { @@ -38,8 +54,10 @@ gb_connection_hd_find(struct gb_host_device *hd, u16 cport_id) spin_lock_irqsave(&gb_connections_lock, flags); list_for_each_entry(connection, &hd->connections, hd_links) - if (connection->hd_cport_id == cport_id) + if (connection->hd_cport_id == cport_id) { + gb_connection_get(connection); goto found; + } connection = NULL; found: spin_unlock_irqrestore(&gb_connections_lock, flags); @@ -63,6 +81,7 @@ void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id, return; } gb_connection_recv(connection, data, length); + gb_connection_put(connection); } EXPORT_SYMBOL_GPL(greybus_data_rcvd); @@ -516,7 +535,7 @@ void gb_connection_destroy(struct gb_connection *connection) ida_simple_remove(id_map, connection->hd_cport_id); connection->hd_cport_id = CPORT_ID_BAD; - kref_put(&connection->kref, gb_connection_kref_release); + gb_connection_put(connection); } void gb_connection_latency_tag_enable(struct gb_connection *connection) -- cgit v0.10.2 From 210b508e45f00fd81c1ba35c979836d8ffea3980 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:51:26 +0100 Subject: greybus: connection: serialise connection creation Serialise connection creation against concurrent creation and destruction using a global mutex. This is needed to prevent two drivers from attempting to create a connection to the same interface CPort and to cope with a racing connection destroy when moving to driver managed connections. Note that the locking can not (easily) be made more fine-grained as not all connections have an interface, but these are not hot paths anyway. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index d215c5c..de44775 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -16,6 +16,8 @@ static void gb_connection_kref_release(struct kref *kref); static DEFINE_SPINLOCK(gb_connections_lock); +static DEFINE_MUTEX(gb_connection_mutex); + /* This is only used at initialization time; no locking is required. */ static struct gb_connection * @@ -125,6 +127,9 @@ static void gb_connection_init_name(struct gb_connection *connection) * A connection also maintains the state of operations sent over the * connection. * + * Serialised against concurrent create and destroy using the + * gb_connection_mutex. + * * Return: A pointer to the new connection if successful, or NULL otherwise. */ static struct gb_connection * @@ -159,9 +164,11 @@ gb_connection_create(struct gb_host_device *hd, int hd_cport_id, return NULL; } + mutex_lock(&gb_connection_mutex); + hd_cport_id = ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL); if (hd_cport_id < 0) - return NULL; + goto err_unlock; connection = kzalloc(sizeof(*connection), GFP_KERNEL); if (!connection) @@ -201,12 +208,16 @@ gb_connection_create(struct gb_host_device *hd, int hd_cport_id, spin_unlock_irq(&gb_connections_lock); + mutex_unlock(&gb_connection_mutex); + return connection; err_free_connection: kfree(connection); err_remove_ida: ida_simple_remove(id_map, hd_cport_id); +err_unlock: + mutex_unlock(&gb_connection_mutex); return NULL; } @@ -524,6 +535,8 @@ void gb_connection_destroy(struct gb_connection *connection) if (!connection) return; + mutex_lock(&gb_connection_mutex); + spin_lock_irq(&gb_connections_lock); list_del(&connection->bundle_links); list_del(&connection->hd_links); @@ -535,6 +548,8 @@ void gb_connection_destroy(struct gb_connection *connection) ida_simple_remove(id_map, connection->hd_cport_id); connection->hd_cport_id = CPORT_ID_BAD; + mutex_unlock(&gb_connection_mutex); + gb_connection_put(connection); } -- cgit v0.10.2 From b53e0c9e8dceb170b054f186200b2fe3fb3718f2 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:51:27 +0100 Subject: greybus: connection: make cport lookup thread-safe Use the gb_connection_mutex when making sure a remote CPort is available. This is needed when moving to driver-managed connections that can be created and destroyed at any time. Also check for duplicate bundle-less connections. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index de44775..88c8a3f 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -19,7 +19,7 @@ static DEFINE_SPINLOCK(gb_connections_lock); static DEFINE_MUTEX(gb_connection_mutex); -/* This is only used at initialization time; no locking is required. */ +/* Caller holds gb_connection_mutex. */ static struct gb_connection * gb_connection_intf_find(struct gb_interface *intf, u16 cport_id) { @@ -142,17 +142,6 @@ gb_connection_create(struct gb_host_device *hd, int hd_cport_id, struct ida *id_map = &hd->cport_id_map; int ida_start, ida_end; - /* - * If a manifest tries to reuse a cport, reject it. We - * initialize connections serially so we don't need to worry - * about holding the connection lock. - */ - if (bundle && gb_connection_intf_find(bundle->intf, cport_id)) { - dev_err(&bundle->dev, "cport %u already connected\n", - cport_id); - return NULL; - } - if (hd_cport_id < 0) { ida_start = 0; ida_end = hd->num_cports; @@ -166,6 +155,11 @@ gb_connection_create(struct gb_host_device *hd, int hd_cport_id, mutex_lock(&gb_connection_mutex); + if (intf && gb_connection_intf_find(intf, cport_id)) { + dev_err(&intf->dev, "cport %u already in use\n", cport_id); + goto err_unlock; + } + hd_cport_id = ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL); if (hd_cport_id < 0) goto err_unlock; -- cgit v0.10.2 From 7d81bafa4ca477a4d364dd229bbbeffb1fa7af4e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:51:28 +0100 Subject: greybus: legacy: add private driver data Allocate private data structure at probe and release at disconnect. The private data will be used to track the connections managed by the driver, but for now only holds a count of the number of cports the bundle has. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index 1864823..1e878be 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -12,6 +12,11 @@ #include "protocol.h" +struct legacy_data { + size_t num_cports; +}; + + static int legacy_connection_get_version(struct gb_connection *connection) { int ret; @@ -123,11 +128,23 @@ static void legacy_connection_exit(struct gb_connection *connection) static int legacy_probe(struct gb_bundle *bundle, const struct greybus_bundle_id *id) { + struct legacy_data *data; struct gb_connection *connection; int ret; - dev_dbg(&bundle->dev, "%s - bundle class = 0x%02x\n", __func__, - bundle->class); + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->num_cports = 0; + list_for_each_entry(connection, &bundle->connections, bundle_links) + data->num_cports++; + + dev_dbg(&bundle->dev, + "%s - bundle class = 0x%02x, num_cports = %zu\n", + __func__, bundle->class, data->num_cports); + + greybus_set_drvdata(bundle, data); list_for_each_entry(connection, &bundle->connections, bundle_links) { dev_dbg(&bundle->dev, "enabling connection %s\n", @@ -145,12 +162,14 @@ err_connections_disable: bundle_links) { legacy_connection_exit(connection); } + kfree(data); return ret; } static void legacy_disconnect(struct gb_bundle *bundle) { + struct legacy_data *data = greybus_get_drvdata(bundle); struct gb_connection *connection; dev_dbg(&bundle->dev, "%s - bundle class = 0x%02x\n", __func__, @@ -160,6 +179,8 @@ static void legacy_disconnect(struct gb_bundle *bundle) bundle_links) { legacy_connection_exit(connection); } + + kfree(data); } static const struct greybus_bundle_id legacy_id_table[] = { -- cgit v0.10.2 From 4b874134284b1dbb340f063fe0cf5141ffd416b1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 20 Jan 2016 14:41:40 -0800 Subject: greybus: audio_codec: Don't be tricky with the driver model With the recent changes by Johan to the driver model of the greybus code, the audio_codec no longer should need to provide a "dummy" driver when registering the codec. In fact, having it there causes the greybus core to crash when inserting the module. Removing it all fixes the crash. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 79f2baf..5c02b65 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -571,13 +571,6 @@ static void gbaudio_free_codec(struct device *dev, * This is the basic hook get things initialized and registered w/ gb */ -/* - * GB codec module driver ops - */ -struct device_driver gb_codec_driver = { - .owner = THIS_MODULE, -}; - /* XXX * since BE DAI path is not yet properly closed from above layer, * dsp dai.mi2s_dai_data.status_mask is still set to STATUS_PORT_STARTED @@ -625,7 +618,6 @@ static void gb_audio_cleanup(struct gbaudio_codec_info *gb) static int gbaudio_codec_probe(struct gb_connection *connection) { int ret, i; - char *driver_name; struct gbaudio_codec_info *gbcodec; struct gb_audio_topology *topology; struct gb_audio_manager_module_descriptor desc; @@ -669,13 +661,6 @@ static int gbaudio_codec_probe(struct gb_connection *connection) for (i = 0; i < gbcodec->num_dais; i++) gbcodec->dais[i].ops = &gbcodec_dai_ops; - /* FIXME */ - driver_name = devm_kzalloc(dev, NAME_SIZE, GFP_KERNEL); - strlcpy(driver_name, gbcodec->name, NAME_SIZE); - gb_codec_driver.name = strsep(&driver_name, "."); - dev_dbg(dev, "driver.name:%s\n", gb_codec_driver.name); - dev->driver = &gb_codec_driver; - /* register codec */ ret = snd_soc_register_codec(dev, &soc_codec_dev_gbcodec, gbcodec->dais, 1); -- cgit v0.10.2 From ebe99d61815fea0ecece5ddb530b28339f8d5ed3 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Thu, 21 Jan 2016 01:42:17 +0000 Subject: greybus: svc: add key event handling Add a new input device associated with the SVC to handle key events. This new events are transfer over a new greybus svc operation which is unidirectional. It was selected the KEY_A for representing the KEY_ARA_BUTTON key code. Signed-off-by: Rui Miguel Silva Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 84fb6ab..2a48d95 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -781,6 +781,7 @@ struct gb_spi_transfer_response { #define GB_SVC_TYPE_ROUTE_DESTROY 0x0c #define GB_SVC_TYPE_INTF_SET_PWRM 0x10 #define GB_SVC_TYPE_INTF_EJECT 0x11 +#define GB_SVC_TYPE_KEY_EVENT 0x12 /* * SVC version request/response has the same payload as @@ -930,6 +931,15 @@ struct gb_svc_intf_set_pwrm_response { __le16 result_code; } __packed; +struct gb_svc_key_event_request { + __le16 key_code; +#define GB_KEYCODE_ARA 0x00 + + __u8 key_event; +#define GB_SVC_KEY_RELEASED 0x00 +#define GB_SVC_KEY_PRESSED 0x01 +} __packed; + /* RAW */ /* Version of the Greybus raw protocol we support */ diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index bc64f48..ad04a95 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -7,6 +7,7 @@ * Released under the GPLv2 only. */ +#include #include #include "greybus.h" @@ -15,6 +16,7 @@ #define CPORT_FLAGS_CSD_N BIT(1) #define CPORT_FLAGS_CSV_N BIT(2) +#define SVC_KEY_ARA_BUTTON KEY_A struct gb_svc_deferred_request { struct work_struct work; @@ -420,6 +422,13 @@ static int gb_svc_hello(struct gb_operation *op) return ret; } + ret = input_register_device(svc->input); + if (ret) { + dev_err(&svc->dev, "failed to register input: %d\n", ret); + device_del(&svc->dev); + return ret; + } + return 0; } @@ -690,6 +699,53 @@ static int gb_svc_intf_reset_recv(struct gb_operation *op) return 0; } +static int gb_svc_key_code_map(struct gb_svc *svc, u16 key_code, u16 *code) +{ + switch (key_code) { + case GB_KEYCODE_ARA: + *code = SVC_KEY_ARA_BUTTON; + break; + default: + dev_warn(&svc->dev, "unknown keycode received: %u\n", key_code); + return -EINVAL; + } + + return 0; +} + +static int gb_svc_key_event_recv(struct gb_operation *op) +{ + struct gb_svc *svc = op->connection->private; + struct gb_message *request = op->request; + struct gb_svc_key_event_request *key; + u16 code; + u8 event; + int ret; + + if (request->payload_size < sizeof(*key)) { + dev_warn(&svc->dev, "short key request received (%zu < %zu)\n", + request->payload_size, sizeof(*key)); + return -EINVAL; + } + + key = request->payload; + + ret = gb_svc_key_code_map(svc, le16_to_cpu(key->key_code), &code); + if (ret < 0) + return ret; + + event = key->key_event; + if ((event != GB_SVC_KEY_PRESSED) && (event != GB_SVC_KEY_RELEASED)) { + dev_warn(&svc->dev, "unknown key event received: %u\n", event); + return -EINVAL; + } + + input_report_key(svc->input, code, (event == GB_SVC_KEY_PRESSED)); + input_sync(svc->input); + + return 0; +} + static int gb_svc_request_handler(struct gb_operation *op) { struct gb_connection *connection = op->connection; @@ -745,12 +801,42 @@ static int gb_svc_request_handler(struct gb_operation *op) return gb_svc_intf_hot_unplug_recv(op); case GB_SVC_TYPE_INTF_RESET: return gb_svc_intf_reset_recv(op); + case GB_SVC_TYPE_KEY_EVENT: + return gb_svc_key_event_recv(op); default: dev_warn(&svc->dev, "unsupported request 0x%02x\n", type); return -EINVAL; } } +static struct input_dev *gb_svc_input_create(struct gb_svc *svc) +{ + struct input_dev *input_dev; + + input_dev = input_allocate_device(); + if (!input_dev) + return ERR_PTR(-ENOMEM); + + input_dev->name = dev_name(&svc->dev); + svc->input_phys = kasprintf(GFP_KERNEL, "greybus-%s/input0", + input_dev->name); + if (!svc->input_phys) + goto err_free_input; + + input_dev->phys = svc->input_phys; + input_dev->dev.parent = &svc->dev; + + input_set_drvdata(input_dev, svc); + + input_set_capability(input_dev, EV_KEY, SVC_KEY_ARA_BUTTON); + + return input_dev; + +err_free_input: + input_free_device(svc->input); + return ERR_PTR(-ENOMEM); +} + static void gb_svc_release(struct device *dev) { struct gb_svc *svc = to_gb_svc(dev); @@ -759,6 +845,7 @@ static void gb_svc_release(struct device *dev) gb_connection_destroy(svc->connection); ida_destroy(&svc->device_id_map); destroy_workqueue(svc->wq); + kfree(svc->input_phys); kfree(svc); } @@ -794,17 +881,29 @@ struct gb_svc *gb_svc_create(struct gb_host_device *hd) svc->state = GB_SVC_STATE_RESET; svc->hd = hd; + svc->input = gb_svc_input_create(svc); + if (IS_ERR(svc->input)) { + dev_err(&svc->dev, "failed to create input device: %ld\n", + PTR_ERR(svc->input)); + goto err_put_device; + } + svc->connection = gb_connection_create_static(hd, GB_SVC_CPORT_ID, GREYBUS_PROTOCOL_SVC); if (!svc->connection) { dev_err(&svc->dev, "failed to create connection\n"); - put_device(&svc->dev); - return NULL; + goto err_free_input; } svc->connection->private = svc; return svc; + +err_free_input: + input_free_device(svc->input); +err_put_device: + put_device(&svc->dev); + return NULL; } int gb_svc_add(struct gb_svc *svc) @@ -825,13 +924,16 @@ int gb_svc_add(struct gb_svc *svc) void gb_svc_del(struct gb_svc *svc) { + gb_connection_disable(svc->connection); + /* - * The SVC device may have been registered from the request handler. + * The SVC device and input device may have been registered + * from the request handler. */ - if (device_is_registered(&svc->dev)) + if (device_is_registered(&svc->dev)) { + input_unregister_device(svc->input); device_del(&svc->dev); - - gb_connection_disable(svc->connection); + } flush_workqueue(svc->wq); } diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index 4abc5ef..f079b4d 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -30,6 +30,9 @@ struct gb_svc { u8 protocol_major; u8 protocol_minor; + + struct input_dev *input; + char *input_phys; }; #define to_gb_svc(d) container_of(d, struct gb_svc, d) -- cgit v0.10.2 From eb8fafdfb9fce95b7d4f4bc9d34a46863176d7f8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 20 Jan 2016 09:27:05 -0800 Subject: greybus: firmware: log the name of the firmware being requested People are getting confused as to what the firmware file name is for their module, so log it to make it easier to find modules with "blank" vid/pid values and let people know what to name their firmware files. Because we are now logging this, turn the debug message after the firmware request into an error message if something fails. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Michael Scott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/firmware.c b/drivers/staging/greybus/firmware.c index 408c7e2..6d8fd0e 100644 --- a/drivers/staging/greybus/firmware.c +++ b/drivers/staging/greybus/firmware.c @@ -88,10 +88,19 @@ static int download_firmware(struct gb_firmware *firmware, u8 stage) intf->ddbl1_manufacturer_id, intf->ddbl1_product_id, firmware->vendor_id, firmware->product_id, stage); + // FIXME: + // Turn to dev_dbg later after everyone has valid bootloaders with good + // ids, but leave this as dev_info for now to make it easier to track + // down "empty" vid/pid modules. + dev_info(&connection->bundle->dev, "Firmware file '%s' requested\n", + firmware_name); + rc = request_firmware(&firmware->fw, firmware_name, &connection->bundle->dev); - dev_dbg(&connection->bundle->dev, "Searched for TFTF %s: %d\n", - firmware_name, rc); + if (rc) + dev_err(&connection->bundle->dev, + "Firware request for %s has failed : %d", + firmware_name, rc); return rc; } -- cgit v0.10.2 From 55ec09e898adb43cf69ebd8839e3d5656a0e7345 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 19 Jan 2016 23:30:42 -0800 Subject: greybus: svc: add ping command This implements the SVC "ping" command. It's tiny and simple, but we need something like this in order for us to "know" if all is working well. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 2a48d95..3f51fb5 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -782,6 +782,7 @@ struct gb_spi_transfer_response { #define GB_SVC_TYPE_INTF_SET_PWRM 0x10 #define GB_SVC_TYPE_INTF_EJECT 0x11 #define GB_SVC_TYPE_KEY_EVENT 0x12 +#define GB_SVC_TYPE_PING 0x13 /* * SVC version request/response has the same payload as diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index ad04a95..8c675d3 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -363,6 +363,13 @@ int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series, } EXPORT_SYMBOL_GPL(gb_svc_intf_set_power_mode); +int gb_svc_ping(struct gb_svc *svc) +{ + return gb_operation_sync(svc->connection, GB_SVC_TYPE_PING, + NULL, 0, NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_svc_ping); + static int gb_svc_version_request(struct gb_operation *op) { struct gb_connection *connection = op->connection; diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index f079b4d..f3e8479 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -55,6 +55,7 @@ int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series, u8 tx_mode, u8 tx_gear, u8 tx_nlanes, u8 rx_mode, u8 rx_gear, u8 rx_nlanes, u8 flags, u32 quirks); +int gb_svc_ping(struct gb_svc *svc); int gb_svc_protocol_init(void); void gb_svc_protocol_exit(void); -- cgit v0.10.2 From 6ce4cc278deca9849bd54783294be7edbe24bac0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 21 Jan 2016 18:13:41 -0800 Subject: greybus: add bundle class to the bundle uevent When bundles are added and then removed, we have a race where we go to read the sysfs file, but it is now for a different bundle than the uevent was originally for. So add the bundle class to the uevent so we "know" what the correct bundle class was. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 522d059..1bb685b 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -125,6 +125,8 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) if (add_uevent_var(env, "BUNDLE=%u", bundle->id)) return -ENOMEM; + if (add_uevent_var(env, "BUNDLE_CLASS=%02x", bundle->class)) + return -ENOMEM; } return 0; -- cgit v0.10.2 From 98fdf5a037f0789f1ea6e22431a4a4cc7c41829d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Jan 2016 17:34:09 +0100 Subject: greybus: core: defer connection creation to driver probe Defer connection creation to bundle driver probe instead of creating them when initialising the interface and parsing the manifest. Store copies of the CPorts descriptors in the bundle for the drivers to use, and update the legacy driver. This is needed for drivers that need more control over host-device resource management, for example, when a protocol needs to use a dedicated host CPort for traffic offloading (e.g. camera data). This also avoids allocating host CPorts for bundles that are not bound to a driver or for remote CPorts that a driver does not need. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index ec52bde..1714482 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -81,15 +81,9 @@ static struct gb_bundle *gb_bundle_find(struct gb_interface *intf, static void gb_bundle_release(struct device *dev) { struct gb_bundle *bundle = to_gb_bundle(dev); - struct gb_connection *connection; - struct gb_connection *tmp; - - list_for_each_entry_safe(connection, tmp, &bundle->connections, - bundle_links) { - gb_connection_destroy(connection); - } kfree(bundle->state); + kfree(bundle->cport_desc); kfree(bundle); } diff --git a/drivers/staging/greybus/bundle.h b/drivers/staging/greybus/bundle.h index 837682d..48fb3fd 100644 --- a/drivers/staging/greybus/bundle.h +++ b/drivers/staging/greybus/bundle.h @@ -22,6 +22,9 @@ struct gb_bundle { u8 class_major; u8 class_minor; + size_t num_cports; + struct greybus_descriptor_cport *cport_desc; + struct list_head connections; u8 *state; diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 88c8a3f..c92af6e 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -232,6 +232,7 @@ gb_connection_create_dynamic(struct gb_interface *intf, return gb_connection_create(intf->hd, -1, intf, bundle, cport_id, protocol_id); } +EXPORT_SYMBOL_GPL(gb_connection_create_dynamic); static int gb_connection_hd_cport_enable(struct gb_connection *connection) { @@ -546,6 +547,7 @@ void gb_connection_destroy(struct gb_connection *connection) gb_connection_put(connection); } +EXPORT_SYMBOL_GPL(gb_connection_destroy); void gb_connection_latency_tag_enable(struct gb_connection *connection) { diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 1bb685b..b9303c0 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -151,8 +151,14 @@ static int greybus_probe(struct device *dev) return -ENODEV; retval = driver->probe(bundle, id); - if (retval) + if (retval) { + /* + * Catch buggy drivers that fail to destroy their connections. + */ + WARN_ON(!list_empty(&bundle->connections)); + return retval; + } return 0; } @@ -172,11 +178,8 @@ static int greybus_remove(struct device *dev) driver->disconnect(bundle); - /* Catch buggy drivers that fail to disable their connections. */ - list_for_each_entry(connection, &bundle->connections, bundle_links) { - if (WARN_ON(connection->state != GB_CONNECTION_STATE_DISABLED)) - gb_connection_disable(connection); - } + /* Catch buggy drivers that fail to destroy their connections. */ + WARN_ON(!list_empty(&bundle->connections)); return 0; } diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index 1e878be..0f3dc86 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -14,6 +14,7 @@ struct legacy_data { size_t num_cports; + struct gb_connection **connections; }; @@ -128,25 +129,44 @@ static void legacy_connection_exit(struct gb_connection *connection) static int legacy_probe(struct gb_bundle *bundle, const struct greybus_bundle_id *id) { + struct greybus_descriptor_cport *cport_desc; struct legacy_data *data; struct gb_connection *connection; - int ret; + int i; + int ret = -ENOMEM; + + dev_dbg(&bundle->dev, + "%s - bundle class = 0x%02x, num_cports = %zu\n", + __func__, bundle->class, bundle->num_cports); data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; - data->num_cports = 0; - list_for_each_entry(connection, &bundle->connections, bundle_links) - data->num_cports++; + data->num_cports = bundle->num_cports; + data->connections = kcalloc(data->num_cports, + sizeof(*data->connections), + GFP_KERNEL); + if (!data->connections) + goto err_free_data; - dev_dbg(&bundle->dev, - "%s - bundle class = 0x%02x, num_cports = %zu\n", - __func__, bundle->class, data->num_cports); + for (i = 0; i < data->num_cports; ++i) { + cport_desc = &bundle->cport_desc[i]; + + connection = gb_connection_create_dynamic(bundle->intf, + bundle, + le16_to_cpu(cport_desc->id), + cport_desc->protocol_id); + if (!connection) + goto err_connections_destroy; + + data->connections[i] = connection; + } greybus_set_drvdata(bundle, data); - list_for_each_entry(connection, &bundle->connections, bundle_links) { + for (i = 0; i < data->num_cports; ++i) { + connection = data->connections[i]; dev_dbg(&bundle->dev, "enabling connection %s\n", connection->name); @@ -158,10 +178,13 @@ static int legacy_probe(struct gb_bundle *bundle, return 0; err_connections_disable: - list_for_each_entry_reverse(connection, &bundle->connections, - bundle_links) { - legacy_connection_exit(connection); - } + for (--i; i >= 0; --i) + legacy_connection_exit(data->connections[i]); +err_connections_destroy: + for (i = 0; i < data->num_cports; ++i) + gb_connection_destroy(data->connections[i]); + kfree(data->connections); +err_free_data: kfree(data); return ret; @@ -170,16 +193,17 @@ err_connections_disable: static void legacy_disconnect(struct gb_bundle *bundle) { struct legacy_data *data = greybus_get_drvdata(bundle); - struct gb_connection *connection; + int i; dev_dbg(&bundle->dev, "%s - bundle class = 0x%02x\n", __func__, bundle->class); - list_for_each_entry_reverse(connection, &bundle->connections, - bundle_links) { - legacy_connection_exit(connection); + for (i = 0; i < data->num_cports; ++i) { + legacy_connection_exit(data->connections[i]); + gb_connection_destroy(data->connections[i]); } + kfree(data->connections); kfree(data); } diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 357f9c6..64c60c2 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -228,19 +228,18 @@ static char *gb_string_get(struct gb_interface *intf, u8 string_id) */ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) { - struct gb_connection *connection; struct gb_interface *intf = bundle->intf; + struct greybus_descriptor_cport *desc_cport; struct manifest_desc *desc; struct manifest_desc *next; + LIST_HEAD(list); u8 bundle_id = bundle->id; - u8 protocol_id; u16 cport_id; u32 count = 0; + int i; /* Set up all cport descriptors associated with this bundle */ list_for_each_entry_safe(desc, next, &intf->manifest_descs, links) { - struct greybus_descriptor_cport *desc_cport; - if (desc->type != GREYBUS_TYPE_CPORT) continue; @@ -252,16 +251,26 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) if (cport_id > CPORT_ID_MAX) goto exit; - /* Found one. Set up its function structure */ - protocol_id = desc_cport->protocol_id; + /* Found one, move it to our temporary list. */ + list_move(&desc->links, &list); + count++; + } - connection = gb_connection_create_dynamic(intf, bundle, - cport_id, - protocol_id); - if (!connection) - goto exit; + if (!count) + return 0; - count++; + bundle->cport_desc = kcalloc(count, sizeof(*bundle->cport_desc), + GFP_KERNEL); + if (!bundle->cport_desc) + goto exit; + + bundle->num_cports = count; + + i = 0; + list_for_each_entry_safe(desc, next, &list, links) { + desc_cport = desc->data; + memcpy(&bundle->cport_desc[i++], desc_cport, + sizeof(*desc_cport)); /* Release the cport descriptor */ release_manifest_descriptor(desc); @@ -269,7 +278,7 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) return count; exit: - + release_cport_descriptors(&list, bundle_id); /* * Free all cports for this bundle to avoid 'excess descriptors' * warnings. -- cgit v0.10.2 From d6fba3dbb04dac64cf7fa6d33ea7fce81ecf862c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Jan 2016 17:34:10 +0100 Subject: greybus: manifest: check for duplicate CPort descriptors when parsing Now that connection creation has been separated from interface initialisation, we should explicitly check for duplicate CPort descriptors when parsing the manifest. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 64c60c2..5ca36c9 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -230,8 +230,7 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) { struct gb_interface *intf = bundle->intf; struct greybus_descriptor_cport *desc_cport; - struct manifest_desc *desc; - struct manifest_desc *next; + struct manifest_desc *desc, *next, *tmp; LIST_HEAD(list); u8 bundle_id = bundle->id; u16 cport_id; @@ -251,7 +250,19 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) if (cport_id > CPORT_ID_MAX) goto exit; - /* Found one, move it to our temporary list. */ + /* + * Found one, move it to our temporary list after checking for + * duplicates. + */ + list_for_each_entry(tmp, &list, links) { + desc_cport = tmp->data; + if (cport_id == desc_cport->id) { + dev_err(&bundle->dev, + "duplicate CPort %u found\n", + cport_id); + goto exit; + } + } list_move(&desc->links, &list); count++; } -- cgit v0.10.2 From bafe3f67908c68a0b1fdc527c79cd7d9106abd85 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Jan 2016 17:34:11 +0100 Subject: greybus: connection: drop protocol parameter from static interface Drop legacy protocol parameter from static connection interface. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index c92af6e..9b8112b 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -217,11 +217,9 @@ err_unlock: } struct gb_connection * -gb_connection_create_static(struct gb_host_device *hd, - u16 hd_cport_id, u8 protocol_id) +gb_connection_create_static(struct gb_host_device *hd, u16 hd_cport_id) { - return gb_connection_create(hd, hd_cport_id, NULL, NULL, 0, - protocol_id); + return gb_connection_create(hd, hd_cport_id, NULL, NULL, 0, 0); } struct gb_connection * diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 66f37b2..562bd2b4 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -56,7 +56,7 @@ struct gb_connection { }; struct gb_connection *gb_connection_create_static(struct gb_host_device *hd, - u16 hd_cport_id, u8 protocol_id); + u16 hd_cport_id); struct gb_connection *gb_connection_create_dynamic(struct gb_interface *intf, struct gb_bundle *bundle, u16 cport_id, u8 protocol_id); diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 8c675d3..472997e 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -895,8 +895,7 @@ struct gb_svc *gb_svc_create(struct gb_host_device *hd) goto err_put_device; } - svc->connection = gb_connection_create_static(hd, GB_SVC_CPORT_ID, - GREYBUS_PROTOCOL_SVC); + svc->connection = gb_connection_create_static(hd, GB_SVC_CPORT_ID); if (!svc->connection) { dev_err(&svc->dev, "failed to create connection\n"); goto err_free_input; -- cgit v0.10.2 From 59507e2612379356d93de0bd1d6e0f9a36dca0da Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Jan 2016 17:34:12 +0100 Subject: greybus: connection: add helper to create control connections Add dedicated helper to create control connections. This will allow us to simplify the generic (dynamic) interface. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 9b8112b..f81f053 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -223,6 +223,12 @@ gb_connection_create_static(struct gb_host_device *hd, u16 hd_cport_id) } struct gb_connection * +gb_connection_create_control(struct gb_interface *intf) +{ + return gb_connection_create(intf->hd, -1, intf, NULL, 0, 0); +} + +struct gb_connection * gb_connection_create_dynamic(struct gb_interface *intf, struct gb_bundle *bundle, u16 cport_id, u8 protocol_id) diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 562bd2b4..cd4a093 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -57,6 +57,7 @@ struct gb_connection { struct gb_connection *gb_connection_create_static(struct gb_host_device *hd, u16 hd_cport_id); +struct gb_connection *gb_connection_create_control(struct gb_interface *intf); struct gb_connection *gb_connection_create_dynamic(struct gb_interface *intf, struct gb_bundle *bundle, u16 cport_id, u8 protocol_id); diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index 0e50fd4..a766ec8 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -186,9 +186,7 @@ struct gb_control *gb_control_create(struct gb_interface *intf) if (!control) return NULL; - control->connection = gb_connection_create_dynamic(intf, NULL, - GB_CONTROL_CPORT_ID, - GREYBUS_PROTOCOL_CONTROL); + control->connection = gb_connection_create_control(intf); if (!control->connection) { dev_err(&intf->dev, "failed to create control connection\n"); kfree(control); -- cgit v0.10.2 From e4c16f8b034047096187a9a9b49035ff5dbc8478 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Jan 2016 17:34:13 +0100 Subject: greybus: connection: drop the legacy protocol-id parameter The protocol-id parameter is only used by the legacy driver so remove it from the generic interface and move it to the legacy driver until it can be removed completely. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index f81f053..8c7f2ea 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -118,7 +118,6 @@ static void gb_connection_init_name(struct gb_connection *connection) * @intf: remote interface, or NULL for static connections * @bundle: remote-interface bundle (may be NULL) * @cport_id: remote-interface cport id, or 0 for static connections - * @protocol_id: protocol id * * Create a Greybus connection, representing the bidirectional link * between a CPort on a (local) Greybus host device and a CPort on @@ -135,8 +134,7 @@ static void gb_connection_init_name(struct gb_connection *connection) static struct gb_connection * gb_connection_create(struct gb_host_device *hd, int hd_cport_id, struct gb_interface *intf, - struct gb_bundle *bundle, int cport_id, - u8 protocol_id) + struct gb_bundle *bundle, int cport_id) { struct gb_connection *connection; struct ida *id_map = &hd->cport_id_map; @@ -173,8 +171,6 @@ gb_connection_create(struct gb_host_device *hd, int hd_cport_id, connection->hd = hd; connection->intf = intf; - connection->protocol_id = protocol_id; - connection->bundle = bundle; connection->state = GB_CONNECTION_STATE_DISABLED; @@ -219,22 +215,21 @@ err_unlock: struct gb_connection * gb_connection_create_static(struct gb_host_device *hd, u16 hd_cport_id) { - return gb_connection_create(hd, hd_cport_id, NULL, NULL, 0, 0); + return gb_connection_create(hd, hd_cport_id, NULL, NULL, 0); } struct gb_connection * gb_connection_create_control(struct gb_interface *intf) { - return gb_connection_create(intf->hd, -1, intf, NULL, 0, 0); + return gb_connection_create(intf->hd, -1, intf, NULL, 0); } struct gb_connection * gb_connection_create_dynamic(struct gb_interface *intf, struct gb_bundle *bundle, - u16 cport_id, u8 protocol_id) + u16 cport_id) { - return gb_connection_create(intf->hd, -1, intf, bundle, cport_id, - protocol_id); + return gb_connection_create(intf->hd, -1, intf, bundle, cport_id); } EXPORT_SYMBOL_GPL(gb_connection_create_dynamic); diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index cd4a093..442bd49 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -59,8 +59,7 @@ struct gb_connection *gb_connection_create_static(struct gb_host_device *hd, u16 hd_cport_id); struct gb_connection *gb_connection_create_control(struct gb_interface *intf); struct gb_connection *gb_connection_create_dynamic(struct gb_interface *intf, - struct gb_bundle *bundle, u16 cport_id, - u8 protocol_id); + struct gb_bundle *bundle, u16 cport_id); void gb_connection_destroy(struct gb_connection *connection); static inline bool gb_connection_is_static(struct gb_connection *connection) diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index 0f3dc86..c34764f 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -155,11 +155,12 @@ static int legacy_probe(struct gb_bundle *bundle, connection = gb_connection_create_dynamic(bundle->intf, bundle, - le16_to_cpu(cport_desc->id), - cport_desc->protocol_id); + le16_to_cpu(cport_desc->id)); if (!connection) goto err_connections_destroy; + connection->protocol_id = cport_desc->protocol_id; + data->connections[i] = connection; } -- cgit v0.10.2 From 8cff6c6473db471d7da9dd6dfbfcebdc4d617aa8 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Jan 2016 17:34:14 +0100 Subject: greybus: connection: simplify connection-creation interface Simplify the exported generic interface for creating dynamic connections. Since all driver connections will have a bundle we can drop the redundant interface parameter. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 8c7f2ea..227bfe8 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -225,10 +225,10 @@ gb_connection_create_control(struct gb_interface *intf) } struct gb_connection * -gb_connection_create_dynamic(struct gb_interface *intf, - struct gb_bundle *bundle, - u16 cport_id) +gb_connection_create_dynamic(struct gb_bundle *bundle, u16 cport_id) { + struct gb_interface *intf = bundle->intf; + return gb_connection_create(intf->hd, -1, intf, bundle, cport_id); } EXPORT_SYMBOL_GPL(gb_connection_create_dynamic); diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 442bd49..863109c 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -58,8 +58,8 @@ struct gb_connection { struct gb_connection *gb_connection_create_static(struct gb_host_device *hd, u16 hd_cport_id); struct gb_connection *gb_connection_create_control(struct gb_interface *intf); -struct gb_connection *gb_connection_create_dynamic(struct gb_interface *intf, - struct gb_bundle *bundle, u16 cport_id); +struct gb_connection *gb_connection_create_dynamic(struct gb_bundle *bundle, + u16 cport_id); void gb_connection_destroy(struct gb_connection *connection); static inline bool gb_connection_is_static(struct gb_connection *connection) diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index c34764f..86ab7b7 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -153,8 +153,7 @@ static int legacy_probe(struct gb_bundle *bundle, for (i = 0; i < data->num_cports; ++i) { cport_desc = &bundle->cport_desc[i]; - connection = gb_connection_create_dynamic(bundle->intf, - bundle, + connection = gb_connection_create_dynamic(bundle, le16_to_cpu(cport_desc->id)); if (!connection) goto err_connections_destroy; -- cgit v0.10.2 From 96c2af5c6bf7dda9498fdcea57fde1bdc677236a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Jan 2016 17:34:15 +0100 Subject: greybus: connection: rename connection-create interface Drop the _dynamic suffix from the exported interface that drivers use to create connections. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 227bfe8..5d0edbe 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -112,7 +112,7 @@ static void gb_connection_init_name(struct gb_connection *connection) } /* - * gb_connection_create() - create a Greybus connection + * _gb_connection_create() - create a Greybus connection * @hd: host device of the connection * @hd_cport_id: host-device cport id, or -1 for dynamic allocation * @intf: remote interface, or NULL for static connections @@ -132,7 +132,7 @@ static void gb_connection_init_name(struct gb_connection *connection) * Return: A pointer to the new connection if successful, or NULL otherwise. */ static struct gb_connection * -gb_connection_create(struct gb_host_device *hd, int hd_cport_id, +_gb_connection_create(struct gb_host_device *hd, int hd_cport_id, struct gb_interface *intf, struct gb_bundle *bundle, int cport_id) { @@ -215,23 +215,23 @@ err_unlock: struct gb_connection * gb_connection_create_static(struct gb_host_device *hd, u16 hd_cport_id) { - return gb_connection_create(hd, hd_cport_id, NULL, NULL, 0); + return _gb_connection_create(hd, hd_cport_id, NULL, NULL, 0); } struct gb_connection * gb_connection_create_control(struct gb_interface *intf) { - return gb_connection_create(intf->hd, -1, intf, NULL, 0); + return _gb_connection_create(intf->hd, -1, intf, NULL, 0); } struct gb_connection * -gb_connection_create_dynamic(struct gb_bundle *bundle, u16 cport_id) +gb_connection_create(struct gb_bundle *bundle, u16 cport_id) { struct gb_interface *intf = bundle->intf; - return gb_connection_create(intf->hd, -1, intf, bundle, cport_id); + return _gb_connection_create(intf->hd, -1, intf, bundle, cport_id); } -EXPORT_SYMBOL_GPL(gb_connection_create_dynamic); +EXPORT_SYMBOL_GPL(gb_connection_create); static int gb_connection_hd_cport_enable(struct gb_connection *connection) { diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 863109c..0e78f10 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -58,7 +58,7 @@ struct gb_connection { struct gb_connection *gb_connection_create_static(struct gb_host_device *hd, u16 hd_cport_id); struct gb_connection *gb_connection_create_control(struct gb_interface *intf); -struct gb_connection *gb_connection_create_dynamic(struct gb_bundle *bundle, +struct gb_connection *gb_connection_create(struct gb_bundle *bundle, u16 cport_id); void gb_connection_destroy(struct gb_connection *connection); diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index 86ab7b7..fb0a82e 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -153,7 +153,7 @@ static int legacy_probe(struct gb_bundle *bundle, for (i = 0; i < data->num_cports; ++i) { cport_desc = &bundle->cport_desc[i]; - connection = gb_connection_create_dynamic(bundle, + connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id)); if (!connection) goto err_connections_destroy; -- cgit v0.10.2 From 24e094d687a23878024589a854ce66a070b769cc Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Jan 2016 17:34:16 +0100 Subject: greybus: connection: return error-valued pointer on creation errors Return an ERR_PTR on errors when creating connections. This allows driver probe to fail with a more informative error message as not all connection creation errors are due to memory exhaustion. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 5d0edbe..99efe31 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -129,7 +129,8 @@ static void gb_connection_init_name(struct gb_connection *connection) * Serialised against concurrent create and destroy using the * gb_connection_mutex. * - * Return: A pointer to the new connection if successful, or NULL otherwise. + * Return: A pointer to the new connection if successful, or an ERR_PTR + * otherwise. */ static struct gb_connection * _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, @@ -139,6 +140,7 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, struct gb_connection *connection; struct ida *id_map = &hd->cport_id_map; int ida_start, ida_end; + int ret; if (hd_cport_id < 0) { ida_start = 0; @@ -148,23 +150,27 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, ida_end = hd_cport_id + 1; } else { dev_err(&hd->dev, "cport %d not available\n", hd_cport_id); - return NULL; + return ERR_PTR(-EINVAL); } mutex_lock(&gb_connection_mutex); if (intf && gb_connection_intf_find(intf, cport_id)) { dev_err(&intf->dev, "cport %u already in use\n", cport_id); + ret = -EBUSY; goto err_unlock; } - hd_cport_id = ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL); - if (hd_cport_id < 0) + ret = ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL); + if (ret < 0) goto err_unlock; + hd_cport_id = ret; connection = kzalloc(sizeof(*connection), GFP_KERNEL); - if (!connection) + if (!connection) { + ret = -ENOMEM; goto err_remove_ida; + } connection->hd_cport_id = hd_cport_id; connection->intf_cport_id = cport_id; @@ -181,8 +187,10 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, connection->wq = alloc_workqueue("%s:%d", WQ_UNBOUND, 1, dev_name(&hd->dev), hd_cport_id); - if (!connection->wq) + if (!connection->wq) { + ret = -ENOMEM; goto err_free_connection; + } kref_init(&connection->kref); @@ -209,7 +217,7 @@ err_remove_ida: err_unlock: mutex_unlock(&gb_connection_mutex); - return NULL; + return ERR_PTR(ret); } struct gb_connection * diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index a766ec8..fb0bb1c 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -187,8 +187,10 @@ struct gb_control *gb_control_create(struct gb_interface *intf) return NULL; control->connection = gb_connection_create_control(intf); - if (!control->connection) { - dev_err(&intf->dev, "failed to create control connection\n"); + if (IS_ERR(control->connection)) { + dev_err(&intf->dev, + "failed to create control connection: %ld\n", + PTR_ERR(control->connection)); kfree(control); return NULL; } diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index fb0a82e..fc19b8b 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -133,7 +133,7 @@ static int legacy_probe(struct gb_bundle *bundle, struct legacy_data *data; struct gb_connection *connection; int i; - int ret = -ENOMEM; + int ret; dev_dbg(&bundle->dev, "%s - bundle class = 0x%02x, num_cports = %zu\n", @@ -147,16 +147,20 @@ static int legacy_probe(struct gb_bundle *bundle, data->connections = kcalloc(data->num_cports, sizeof(*data->connections), GFP_KERNEL); - if (!data->connections) + if (!data->connections) { + ret = -ENOMEM; goto err_free_data; + } for (i = 0; i < data->num_cports; ++i) { cport_desc = &bundle->cport_desc[i]; connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id)); - if (!connection) + if (IS_ERR(connection)) { + ret = PTR_ERR(connection); goto err_connections_destroy; + } connection->protocol_id = cport_desc->protocol_id; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 472997e..845f82d 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -896,8 +896,9 @@ struct gb_svc *gb_svc_create(struct gb_host_device *hd) } svc->connection = gb_connection_create_static(hd, GB_SVC_CPORT_ID); - if (!svc->connection) { - dev_err(&svc->dev, "failed to create connection\n"); + if (IS_ERR(svc->connection)) { + dev_err(&svc->dev, "failed to create connection: %ld\n", + PTR_ERR(svc->connection)); goto err_free_input; } -- cgit v0.10.2 From 431b3ebb3d9e0c25081006fc7a1f97621dca6192 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Jan 2016 17:34:17 +0100 Subject: greybus: legacy: refactor legacy-connection handling Add wrapper structure for legacy connections and add helpers to create and destroy legacy connections. This is a step in removing legacy connection fields from the core structures. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index fc19b8b..37c4212 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -12,9 +12,13 @@ #include "protocol.h" +struct legacy_connection { + struct gb_connection *connection; +}; + struct legacy_data { size_t num_cports; - struct gb_connection **connections; + struct legacy_connection *connections; }; @@ -78,12 +82,16 @@ static int legacy_request_handler(struct gb_operation *operation) return protocol->request_recv(operation->type, operation); } -static int legacy_connection_init(struct gb_connection *connection) +static int legacy_connection_init(struct legacy_connection *lc) { + struct gb_connection *connection = lc->connection; gb_request_handler_t handler; int ret; - ret = legacy_connection_bind_protocol(connection); + dev_dbg(&connection->bundle->dev, "%s - %s\n", __func__, + connection->name); + + ret = legacy_connection_bind_protocol(lc->connection); if (ret) return ret; @@ -114,8 +122,10 @@ err_unbind_protocol: return ret; } -static void legacy_connection_exit(struct gb_connection *connection) +static void legacy_connection_exit(struct legacy_connection *lc) { + struct gb_connection *connection = lc->connection; + if (!connection->protocol) return; @@ -126,12 +136,33 @@ static void legacy_connection_exit(struct gb_connection *connection) legacy_connection_unbind_protocol(connection); } +static int legacy_connection_create(struct legacy_connection *lc, + struct gb_bundle *bundle, + struct greybus_descriptor_cport *desc) +{ + struct gb_connection *connection; + + connection = gb_connection_create(bundle, le16_to_cpu(desc->id)); + if (IS_ERR(connection)) + return PTR_ERR(connection); + + lc->connection = connection; + lc->connection->protocol_id = desc->protocol_id; + + return 0; +} + +static void legacy_connection_destroy(struct legacy_connection *lc) +{ + gb_connection_destroy(lc->connection); +} + static int legacy_probe(struct gb_bundle *bundle, const struct greybus_bundle_id *id) { struct greybus_descriptor_cport *cport_desc; struct legacy_data *data; - struct gb_connection *connection; + struct legacy_connection *lc; int i; int ret; @@ -154,27 +185,19 @@ static int legacy_probe(struct gb_bundle *bundle, for (i = 0; i < data->num_cports; ++i) { cport_desc = &bundle->cport_desc[i]; + lc = &data->connections[i]; - connection = gb_connection_create(bundle, - le16_to_cpu(cport_desc->id)); - if (IS_ERR(connection)) { - ret = PTR_ERR(connection); + ret = legacy_connection_create(lc, bundle, cport_desc); + if (ret) goto err_connections_destroy; - } - - connection->protocol_id = cport_desc->protocol_id; - - data->connections[i] = connection; } greybus_set_drvdata(bundle, data); for (i = 0; i < data->num_cports; ++i) { - connection = data->connections[i]; - dev_dbg(&bundle->dev, "enabling connection %s\n", - connection->name); + lc = &data->connections[i]; - ret = legacy_connection_init(connection); + ret = legacy_connection_init(lc); if (ret) goto err_connections_disable; } @@ -183,10 +206,10 @@ static int legacy_probe(struct gb_bundle *bundle, err_connections_disable: for (--i; i >= 0; --i) - legacy_connection_exit(data->connections[i]); + legacy_connection_exit(&data->connections[i]); err_connections_destroy: for (i = 0; i < data->num_cports; ++i) - gb_connection_destroy(data->connections[i]); + legacy_connection_destroy(&data->connections[i]); kfree(data->connections); err_free_data: kfree(data); @@ -203,8 +226,8 @@ static void legacy_disconnect(struct gb_bundle *bundle) bundle->class); for (i = 0; i < data->num_cports; ++i) { - legacy_connection_exit(data->connections[i]); - gb_connection_destroy(data->connections[i]); + legacy_connection_exit(&data->connections[i]); + legacy_connection_destroy(&data->connections[i]); } kfree(data->connections); -- cgit v0.10.2 From 8278fae5d727b02af2fb7e1ac518c63569096c9f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Jan 2016 17:34:18 +0100 Subject: greybus: legacy: add initialized flag Add initialized flag and use instead of the connection protocol pointer to determine when the legacy connection has been initialised. This is a step in moving legacy connection binding to connection-creation time. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index 37c4212..c7f59e4 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -14,6 +14,7 @@ struct legacy_connection { struct gb_connection *connection; + bool initialized; }; struct legacy_data { @@ -112,6 +113,8 @@ static int legacy_connection_init(struct legacy_connection *lc) if (ret) goto err_disable; + lc->initialized = true; + return 0; err_disable: @@ -126,7 +129,7 @@ static void legacy_connection_exit(struct legacy_connection *lc) { struct gb_connection *connection = lc->connection; - if (!connection->protocol) + if (!lc->initialized) return; gb_connection_disable(connection); @@ -134,6 +137,8 @@ static void legacy_connection_exit(struct legacy_connection *lc) connection->protocol->connection_exit(connection); legacy_connection_unbind_protocol(connection); + + lc->initialized = false; } static int legacy_connection_create(struct legacy_connection *lc, -- cgit v0.10.2 From 63cf52f79b4c9f73657285031427ca748d11ce86 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Jan 2016 17:34:19 +0100 Subject: greybus: connection: remove legacy protocol id from core Remove legacy protocol-id field that is only used by the legacy-protocol driver from the connection structure. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 0e78f10..8e5284a 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -38,7 +38,6 @@ struct gb_connection { gb_request_handler_t handler; struct gb_protocol *protocol; - u8 protocol_id; u8 module_major; u8 module_minor; diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index c7f59e4..340d8b5 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -15,6 +15,7 @@ struct legacy_connection { struct gb_connection *connection; bool initialized; + u8 protocol_id; }; struct legacy_data { @@ -38,8 +39,9 @@ static int legacy_connection_get_version(struct gb_connection *connection) return 0; } -static int legacy_connection_bind_protocol(struct gb_connection *connection) +static int legacy_connection_bind_protocol(struct legacy_connection *lc) { + struct gb_connection *connection = lc->connection; struct gb_protocol *protocol; u8 major, minor; @@ -52,14 +54,11 @@ static int legacy_connection_bind_protocol(struct gb_connection *connection) major = 0; minor = 1; - protocol = gb_protocol_get(connection->protocol_id, - major, - minor); + protocol = gb_protocol_get(lc->protocol_id, major, minor); if (!protocol) { dev_err(&connection->hd->dev, "protocol 0x%02x version %u.%u not found\n", - connection->protocol_id, - major, minor); + lc->protocol_id, major, minor); return -EPROTONOSUPPORT; } connection->protocol = protocol; @@ -92,7 +91,7 @@ static int legacy_connection_init(struct legacy_connection *lc) dev_dbg(&connection->bundle->dev, "%s - %s\n", __func__, connection->name); - ret = legacy_connection_bind_protocol(lc->connection); + ret = legacy_connection_bind_protocol(lc); if (ret) return ret; @@ -152,7 +151,7 @@ static int legacy_connection_create(struct legacy_connection *lc, return PTR_ERR(connection); lc->connection = connection; - lc->connection->protocol_id = desc->protocol_id; + lc->protocol_id = desc->protocol_id; return 0; } -- cgit v0.10.2 From 2399032d7262f2a5dc1f22380d23b17971ed22e4 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Jan 2016 17:34:20 +0100 Subject: greybus: legacy: look up protocol at connection creation Look up legacy protocol at connection create instead of at init. Note that we can now look up the protocol before even creating the actual connection. This is needed to be able to set a connection request handler when creating the connection rather than when enabling it. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index 340d8b5..4f3476c 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -15,7 +15,7 @@ struct legacy_connection { struct gb_connection *connection; bool initialized; - u8 protocol_id; + struct gb_protocol *protocol; }; struct legacy_data { @@ -39,42 +39,6 @@ static int legacy_connection_get_version(struct gb_connection *connection) return 0; } -static int legacy_connection_bind_protocol(struct legacy_connection *lc) -{ - struct gb_connection *connection = lc->connection; - struct gb_protocol *protocol; - u8 major, minor; - - /* - * The legacy protocols have always been looked up using a hard-coded - * version of 0.1, despite (or perhaps rather, due to) the fact that - * module version negotiation could not take place until after the - * protocol was bound. - */ - major = 0; - minor = 1; - - protocol = gb_protocol_get(lc->protocol_id, major, minor); - if (!protocol) { - dev_err(&connection->hd->dev, - "protocol 0x%02x version %u.%u not found\n", - lc->protocol_id, major, minor); - return -EPROTONOSUPPORT; - } - connection->protocol = protocol; - - return 0; -} - -static void legacy_connection_unbind_protocol(struct gb_connection *connection) -{ - struct gb_protocol *protocol = connection->protocol; - - gb_protocol_put(protocol); - - connection->protocol = NULL; -} - static int legacy_request_handler(struct gb_operation *operation) { struct gb_protocol *protocol = operation->connection->protocol; @@ -91,10 +55,6 @@ static int legacy_connection_init(struct legacy_connection *lc) dev_dbg(&connection->bundle->dev, "%s - %s\n", __func__, connection->name); - ret = legacy_connection_bind_protocol(lc); - if (ret) - return ret; - if (connection->protocol->request_recv) handler = legacy_request_handler; else @@ -102,7 +62,7 @@ static int legacy_connection_init(struct legacy_connection *lc) ret = gb_connection_enable(connection, handler); if (ret) - goto err_unbind_protocol; + return ret; ret = legacy_connection_get_version(connection); if (ret) @@ -118,8 +78,6 @@ static int legacy_connection_init(struct legacy_connection *lc) err_disable: gb_connection_disable(connection); -err_unbind_protocol: - legacy_connection_unbind_protocol(connection); return ret; } @@ -135,8 +93,6 @@ static void legacy_connection_exit(struct legacy_connection *lc) connection->protocol->connection_exit(connection); - legacy_connection_unbind_protocol(connection); - lc->initialized = false; } @@ -145,20 +101,57 @@ static int legacy_connection_create(struct legacy_connection *lc, struct greybus_descriptor_cport *desc) { struct gb_connection *connection; + struct gb_protocol *protocol; + u8 major, minor; + int ret; + + /* + * The legacy protocols have always been looked up using a hard-coded + * version of 0.1, despite (or perhaps rather, due to) the fact that + * module version negotiation could not take place until after the + * protocol was bound. + */ + major = 0; + minor = 1; + + protocol = gb_protocol_get(desc->protocol_id, major, minor); + if (!protocol) { + dev_err(&bundle->dev, + "protocol 0x%02x version %u.%u not found\n", + desc->protocol_id, major, minor); + return -EPROTONOSUPPORT; + } connection = gb_connection_create(bundle, le16_to_cpu(desc->id)); - if (IS_ERR(connection)) - return PTR_ERR(connection); + if (IS_ERR(connection)) { + ret = PTR_ERR(connection); + goto err_protocol_put; + } + + /* + * NOTE: We need to keep a pointer to the protocol in the actual + * connection structure for now. + */ + connection->protocol = protocol; lc->connection = connection; - lc->protocol_id = desc->protocol_id; + lc->protocol = protocol; return 0; + +err_protocol_put: + gb_protocol_put(protocol); + + return ret; } static void legacy_connection_destroy(struct legacy_connection *lc) { + lc->connection->protocol = NULL; + gb_connection_destroy(lc->connection); + + gb_protocol_put(lc->protocol); } static int legacy_probe(struct gb_bundle *bundle, -- cgit v0.10.2 From f7ee081e3151e187e7478eb8941f61744f125201 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Jan 2016 17:34:21 +0100 Subject: greybus: connection: set request handlers at creation Set the connection request handler at creation rather than when enabling the connection. This is possible now that connections are created by the drivers that use them rather than by core at manifest parsing time. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 99efe31..77c2f67 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -118,6 +118,7 @@ static void gb_connection_init_name(struct gb_connection *connection) * @intf: remote interface, or NULL for static connections * @bundle: remote-interface bundle (may be NULL) * @cport_id: remote-interface cport id, or 0 for static connections + * @handler: request handler (may be NULL) * * Create a Greybus connection, representing the bidirectional link * between a CPort on a (local) Greybus host device and a CPort on @@ -135,7 +136,8 @@ static void gb_connection_init_name(struct gb_connection *connection) static struct gb_connection * _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, struct gb_interface *intf, - struct gb_bundle *bundle, int cport_id) + struct gb_bundle *bundle, int cport_id, + gb_request_handler_t handler) { struct gb_connection *connection; struct ida *id_map = &hd->cport_id_map; @@ -176,8 +178,8 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, connection->intf_cport_id = cport_id; connection->hd = hd; connection->intf = intf; - connection->bundle = bundle; + connection->handler = handler; connection->state = GB_CONNECTION_STATE_DISABLED; atomic_set(&connection->op_cycle, 0); @@ -221,23 +223,26 @@ err_unlock: } struct gb_connection * -gb_connection_create_static(struct gb_host_device *hd, u16 hd_cport_id) +gb_connection_create_static(struct gb_host_device *hd, u16 hd_cport_id, + gb_request_handler_t handler) { - return _gb_connection_create(hd, hd_cport_id, NULL, NULL, 0); + return _gb_connection_create(hd, hd_cport_id, NULL, NULL, 0, handler); } struct gb_connection * gb_connection_create_control(struct gb_interface *intf) { - return _gb_connection_create(intf->hd, -1, intf, NULL, 0); + return _gb_connection_create(intf->hd, -1, intf, NULL, 0, NULL); } struct gb_connection * -gb_connection_create(struct gb_bundle *bundle, u16 cport_id) +gb_connection_create(struct gb_bundle *bundle, u16 cport_id, + gb_request_handler_t handler) { struct gb_interface *intf = bundle->intf; - return _gb_connection_create(intf->hd, -1, intf, bundle, cport_id); + return _gb_connection_create(intf->hd, -1, intf, bundle, cport_id, + handler); } EXPORT_SYMBOL_GPL(gb_connection_create); @@ -424,39 +429,42 @@ gb_connection_flush_incoming_operations(struct gb_connection *connection, } } -int gb_connection_enable(struct gb_connection *connection, - gb_request_handler_t handler) +/* + * _gb_connection_enable() - enable a connection + * @connection: connection to enable + * @rx: whether to enable incoming requests + * + * Connection-enable helper for DISABLED->ENABLED, DISABLED->ENABLED_TX, and + * ENABLED_TX->ENABLED state transitions. + * + * Locking: Caller holds connection->mutex. + */ +static int _gb_connection_enable(struct gb_connection *connection, bool rx) { int ret; - mutex_lock(&connection->mutex); - - if (connection->state == GB_CONNECTION_STATE_ENABLED) - goto out_unlock; - + /* Handle ENABLED_TX -> ENABLED transitions. */ if (connection->state == GB_CONNECTION_STATE_ENABLED_TX) { - if (!handler) - goto out_unlock; + if (!(connection->handler && rx)) + return 0; spin_lock_irq(&connection->lock); - connection->handler = handler; connection->state = GB_CONNECTION_STATE_ENABLED; spin_unlock_irq(&connection->lock); - goto out_unlock; + return 0; } ret = gb_connection_hd_cport_enable(connection); if (ret) - goto err_unlock; + return ret; ret = gb_connection_svc_connection_create(connection); if (ret) goto err_hd_cport_disable; spin_lock_irq(&connection->lock); - connection->handler = handler; - if (handler) + if (connection->handler && rx) connection->state = GB_CONNECTION_STATE_ENABLED; else connection->state = GB_CONNECTION_STATE_ENABLED_TX; @@ -466,28 +474,60 @@ int gb_connection_enable(struct gb_connection *connection, if (ret) goto err_svc_destroy; -out_unlock: - mutex_unlock(&connection->mutex); - return 0; err_svc_destroy: spin_lock_irq(&connection->lock); connection->state = GB_CONNECTION_STATE_DISABLED; gb_connection_cancel_operations(connection, -ESHUTDOWN); - connection->handler = NULL; spin_unlock_irq(&connection->lock); gb_connection_svc_connection_destroy(connection); err_hd_cport_disable: gb_connection_hd_cport_disable(connection); -err_unlock: + + return ret; +} + +int gb_connection_enable(struct gb_connection *connection) +{ + int ret = 0; + + mutex_lock(&connection->mutex); + + if (connection->state == GB_CONNECTION_STATE_ENABLED) + goto out_unlock; + + ret = _gb_connection_enable(connection, true); +out_unlock: mutex_unlock(&connection->mutex); return ret; } EXPORT_SYMBOL_GPL(gb_connection_enable); +int gb_connection_enable_tx(struct gb_connection *connection) +{ + int ret = 0; + + mutex_lock(&connection->mutex); + + if (connection->state == GB_CONNECTION_STATE_ENABLED) { + ret = -EINVAL; + goto out_unlock; + } + + if (connection->state == GB_CONNECTION_STATE_ENABLED_TX) + goto out_unlock; + + ret = _gb_connection_enable(connection, false); +out_unlock: + mutex_unlock(&connection->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(gb_connection_enable_tx); + void gb_connection_disable_rx(struct gb_connection *connection) { mutex_lock(&connection->mutex); @@ -499,7 +539,6 @@ void gb_connection_disable_rx(struct gb_connection *connection) } connection->state = GB_CONNECTION_STATE_ENABLED_TX; gb_connection_flush_incoming_operations(connection, -ESHUTDOWN); - connection->handler = NULL; spin_unlock_irq(&connection->lock); out_unlock: @@ -518,7 +557,6 @@ void gb_connection_disable(struct gb_connection *connection) spin_lock_irq(&connection->lock); connection->state = GB_CONNECTION_STATE_DISABLED; gb_connection_cancel_operations(connection, -ESHUTDOWN); - connection->handler = NULL; spin_unlock_irq(&connection->lock); gb_connection_svc_connection_destroy(connection); diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 8e5284a..24b7d6f 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -55,10 +55,10 @@ struct gb_connection { }; struct gb_connection *gb_connection_create_static(struct gb_host_device *hd, - u16 hd_cport_id); + u16 hd_cport_id, gb_request_handler_t handler); struct gb_connection *gb_connection_create_control(struct gb_interface *intf); struct gb_connection *gb_connection_create(struct gb_bundle *bundle, - u16 cport_id); + u16 cport_id, gb_request_handler_t handler); void gb_connection_destroy(struct gb_connection *connection); static inline bool gb_connection_is_static(struct gb_connection *connection) @@ -66,12 +66,8 @@ static inline bool gb_connection_is_static(struct gb_connection *connection) return !connection->intf; } -int gb_connection_enable(struct gb_connection *connection, - gb_request_handler_t handler); -static inline int gb_connection_enable_tx(struct gb_connection *connection) -{ - return gb_connection_enable(connection, NULL); -} +int gb_connection_enable(struct gb_connection *connection); +int gb_connection_enable_tx(struct gb_connection *connection); void gb_connection_disable_rx(struct gb_connection *connection); void gb_connection_disable(struct gb_connection *connection); diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index 4f3476c..18f1a2b 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -49,18 +49,12 @@ static int legacy_request_handler(struct gb_operation *operation) static int legacy_connection_init(struct legacy_connection *lc) { struct gb_connection *connection = lc->connection; - gb_request_handler_t handler; int ret; dev_dbg(&connection->bundle->dev, "%s - %s\n", __func__, connection->name); - if (connection->protocol->request_recv) - handler = legacy_request_handler; - else - handler = NULL; - - ret = gb_connection_enable(connection, handler); + ret = gb_connection_enable(connection); if (ret) return ret; @@ -102,6 +96,7 @@ static int legacy_connection_create(struct legacy_connection *lc, { struct gb_connection *connection; struct gb_protocol *protocol; + gb_request_handler_t handler; u8 major, minor; int ret; @@ -122,7 +117,13 @@ static int legacy_connection_create(struct legacy_connection *lc, return -EPROTONOSUPPORT; } - connection = gb_connection_create(bundle, le16_to_cpu(desc->id)); + if (protocol->request_recv) + handler = legacy_request_handler; + else + handler = NULL; + + connection = gb_connection_create(bundle, le16_to_cpu(desc->id), + handler); if (IS_ERR(connection)) { ret = PTR_ERR(connection); goto err_protocol_put; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 845f82d..feadb62 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -895,7 +895,8 @@ struct gb_svc *gb_svc_create(struct gb_host_device *hd) goto err_put_device; } - svc->connection = gb_connection_create_static(hd, GB_SVC_CPORT_ID); + svc->connection = gb_connection_create_static(hd, GB_SVC_CPORT_ID, + gb_svc_request_handler); if (IS_ERR(svc->connection)) { dev_err(&svc->dev, "failed to create connection: %ld\n", PTR_ERR(svc->connection)); @@ -922,7 +923,7 @@ int gb_svc_add(struct gb_svc *svc) * is added from the connection request handler when enough * information has been received. */ - ret = gb_connection_enable(svc->connection, gb_svc_request_handler); + ret = gb_connection_enable(svc->connection); if (ret) return ret; -- cgit v0.10.2 From 5dd8cc5370dbf68f17ed9443be6bcc54afbef204 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Jan 2016 17:34:22 +0100 Subject: greybus: hid: clean up init error paths Separate success and error paths more clearly. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index f45b444..51657b0 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -431,7 +431,7 @@ static int gb_hid_connection_init(struct gb_connection *connection) hid = hid_allocate_device(); if (IS_ERR(hid)) { ret = PTR_ERR(hid); - goto free_ghid; + goto err_free_ghid; } connection->private = ghid; @@ -440,17 +440,19 @@ static int gb_hid_connection_init(struct gb_connection *connection) ret = gb_hid_init(ghid); if (ret) - goto destroy_hid; + goto err_destroy_hid; ret = hid_add_device(hid); - if (!ret) - return 0; + if (ret) { + hid_err(hid, "can't add hid device: %d\n", ret); + goto err_destroy_hid; + } - hid_err(hid, "can't add hid device: %d\n", ret); + return 0; -destroy_hid: +err_destroy_hid: hid_destroy_device(hid); -free_ghid: +err_free_ghid: kfree(ghid); return ret; -- cgit v0.10.2 From 4324282d90cb02e041753240780c516f9cfe5b10 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Jan 2016 17:34:23 +0100 Subject: greybus: hid: convert to bundle driver Convert the legacy HID protocol driver to a bundle driver. This also fixes a potential crash should a (malicious) module have sent an early request before the private data had been initialised. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index 51657b0..4db337c 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -97,13 +97,13 @@ static int gb_hid_set_report(struct gb_hid *ghid, u8 report_type, u8 report_id, return ret; } -static int gb_hid_irq_handler(u8 type, struct gb_operation *op) +static int gb_hid_request_handler(struct gb_operation *op) { struct gb_connection *connection = op->connection; struct gb_hid *ghid = connection->private; struct gb_hid_input_report_request *request = op->request->payload; - if (type != GB_HID_TYPE_IRQ_EVENT) { + if (op->type != GB_HID_TYPE_IRQ_EVENT) { dev_err(&connection->bundle->dev, "unsupported unsolicited request\n"); return -EINVAL; @@ -418,64 +418,96 @@ static int gb_hid_init(struct gb_hid *ghid) return 0; } -static int gb_hid_connection_init(struct gb_connection *connection) +static int gb_hid_probe(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) { + struct greybus_descriptor_cport *cport_desc; + struct gb_connection *connection; struct hid_device *hid; struct gb_hid *ghid; int ret; + if (bundle->num_cports != 1) + return -ENODEV; + + cport_desc = &bundle->cport_desc[0]; + if (cport_desc->protocol_id != GREYBUS_PROTOCOL_HID) + return -ENODEV; + ghid = kzalloc(sizeof(*ghid), GFP_KERNEL); if (!ghid) return -ENOMEM; - hid = hid_allocate_device(); - if (IS_ERR(hid)) { - ret = PTR_ERR(hid); + connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id), + gb_hid_request_handler); + if (IS_ERR(connection)) { + ret = PTR_ERR(connection); goto err_free_ghid; } connection->private = ghid; ghid->connection = connection; + + hid = hid_allocate_device(); + if (IS_ERR(hid)) { + ret = PTR_ERR(hid); + goto err_connection_destroy; + } + ghid->hid = hid; - ret = gb_hid_init(ghid); + greybus_set_drvdata(bundle, ghid); + + ret = gb_connection_enable(connection); if (ret) goto err_destroy_hid; + ret = gb_hid_init(ghid); + if (ret) + goto err_connection_disable; + ret = hid_add_device(hid); if (ret) { hid_err(hid, "can't add hid device: %d\n", ret); - goto err_destroy_hid; + goto err_connection_disable; } return 0; +err_connection_disable: + gb_connection_disable(connection); err_destroy_hid: hid_destroy_device(hid); +err_connection_destroy: + gb_connection_destroy(connection); err_free_ghid: kfree(ghid); return ret; } -static void gb_hid_connection_exit(struct gb_connection *connection) +static void gb_hid_disconnect(struct gb_bundle *bundle) { - struct gb_hid *ghid = connection->private; + struct gb_hid *ghid = greybus_get_drvdata(bundle); + gb_connection_disable(ghid->connection); hid_destroy_device(ghid->hid); + gb_connection_destroy(ghid->connection); kfree(ghid); } -static struct gb_protocol hid_protocol = { - .name = "hid", - .id = GREYBUS_PROTOCOL_HID, - .major = GB_HID_VERSION_MAJOR, - .minor = GB_HID_VERSION_MINOR, - .connection_init = gb_hid_connection_init, - .connection_exit = gb_hid_connection_exit, - .request_recv = gb_hid_irq_handler, +static const struct greybus_bundle_id gb_hid_id_table[] = { + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_HID) }, + { } }; +MODULE_DEVICE_TABLE(greybus, gb_hid_id_table); -gb_protocol_driver(&hid_protocol); +static struct greybus_driver gb_hid_driver = { + .name = "hid", + .probe = gb_hid_probe, + .disconnect = gb_hid_disconnect, + .id_table = gb_hid_id_table, +}; +module_greybus_driver(gb_hid_driver); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index 18f1a2b..5cfbd23 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -236,7 +236,6 @@ static const struct greybus_bundle_id legacy_id_table[] = { { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_GPIO) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_I2C) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_UART) }, - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_HID) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_USB) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SDIO) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_POWER_SUPPLY) }, -- cgit v0.10.2 From e0deb079edc9bd403acdb1ecada0879786cc0fe3 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Jan 2016 17:34:24 +0100 Subject: greybus: vibrator: convert to bundle driver Convert the legacy vibrator protocol driver to a bundle driver. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index 5cfbd23..4a45a94 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -245,7 +245,6 @@ static const struct greybus_bundle_id legacy_id_table[] = { { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_CAMERA) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SENSOR) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_LIGHTS) }, - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_VIBRATOR) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_LOOPBACK) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_AUDIO_MGMT) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_AUDIO_DATA) }, diff --git a/drivers/staging/greybus/vibrator.c b/drivers/staging/greybus/vibrator.c index 04737c8..8c0df99 100644 --- a/drivers/staging/greybus/vibrator.c +++ b/drivers/staging/greybus/vibrator.c @@ -88,19 +88,42 @@ static struct class vibrator_class = { static DEFINE_IDA(minors); -static int gb_vibrator_connection_init(struct gb_connection *connection) +static int gb_vibrator_probe(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) { + struct greybus_descriptor_cport *cport_desc; + struct gb_connection *connection; struct gb_vibrator_device *vib; struct device *dev; int retval; + if (bundle->num_cports != 1) + return -ENODEV; + + cport_desc = &bundle->cport_desc[0]; + if (cport_desc->protocol_id != GREYBUS_PROTOCOL_VIBRATOR) + return -ENODEV; + vib = kzalloc(sizeof(*vib), GFP_KERNEL); if (!vib) return -ENOMEM; - vib->connection = connection; + connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id), + NULL); + if (IS_ERR(connection)) { + retval = PTR_ERR(connection); + goto err_free_vib; + } connection->private = vib; + vib->connection = connection; + + greybus_set_drvdata(bundle, vib); + + retval = gb_connection_enable(connection); + if (retval) + goto err_connection_destroy; + /* * For now we create a device in sysfs for the vibrator, but odds are * there is a "real" device somewhere in the kernel for this, but I @@ -109,9 +132,9 @@ static int gb_vibrator_connection_init(struct gb_connection *connection) vib->minor = ida_simple_get(&minors, 0, 0, GFP_KERNEL); if (vib->minor < 0) { retval = vib->minor; - goto error; + goto err_connection_disable; } - dev = device_create(&vibrator_class, &connection->bundle->dev, + dev = device_create(&vibrator_class, &bundle->dev, MKDEV(0, 0), vib, "vibrator%d", vib->minor); if (IS_ERR(dev)) { retval = -EINVAL; @@ -136,34 +159,44 @@ static int gb_vibrator_connection_init(struct gb_connection *connection) err_ida_remove: ida_simple_remove(&minors, vib->minor); -error: +err_connection_disable: + gb_connection_disable(connection); +err_connection_destroy: + gb_connection_destroy(connection); +err_free_vib: kfree(vib); + return retval; } -static void gb_vibrator_connection_exit(struct gb_connection *connection) +static void gb_vibrator_disconnect(struct gb_bundle *bundle) { - struct gb_vibrator_device *vib = connection->private; + struct gb_vibrator_device *vib = greybus_get_drvdata(bundle); #if LINUX_VERSION_CODE <= KERNEL_VERSION(3,11,0) sysfs_remove_group(&vib->dev->kobj, vibrator_groups[0]); #endif device_unregister(vib->dev); ida_simple_remove(&minors, vib->minor); + gb_connection_disable(vib->connection); + gb_connection_destroy(vib->connection); kfree(vib); } -static struct gb_protocol vibrator_protocol = { - .name = "vibrator", - .id = GREYBUS_PROTOCOL_VIBRATOR, - .major = GB_VIBRATOR_VERSION_MAJOR, - .minor = GB_VIBRATOR_VERSION_MINOR, - .connection_init = gb_vibrator_connection_init, - .connection_exit = gb_vibrator_connection_exit, - .request_recv = NULL, /* no incoming requests */ +static const struct greybus_bundle_id gb_vibrator_id_table[] = { + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_VIBRATOR) }, + { } +}; +MODULE_DEVICE_TABLE(greybus, gb_vibrator_id_table); + +static struct greybus_driver gb_vibrator_driver = { + .name = "vibrator", + .probe = gb_vibrator_probe, + .disconnect = gb_vibrator_disconnect, + .id_table = gb_vibrator_id_table, }; -static __init int protocol_init(void) +static __init int gb_vibrator_init(void) { int retval; @@ -171,7 +204,7 @@ static __init int protocol_init(void) if (retval) return retval; - retval = gb_protocol_register(&vibrator_protocol); + retval = greybus_register(&gb_vibrator_driver); if (retval) goto err_class_unregister; @@ -182,14 +215,14 @@ err_class_unregister: return retval; } -module_init(protocol_init); +module_init(gb_vibrator_init); -static __exit void protocol_exit(void) +static __exit void gb_vibrator_exit(void) { - gb_protocol_deregister(&vibrator_protocol); + greybus_deregister(&gb_vibrator_driver); class_unregister(&vibrator_class); ida_destroy(&minors); } -module_exit(protocol_exit); +module_exit(gb_vibrator_exit); MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 8eff5109616f4fb1784aa311b7544ef29b8deae9 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Jan 2016 17:34:26 +0100 Subject: greybus: firmware: abort if AP_READY fails Abort if the AP_READY request fails. Also update the comment suggesting that this operation was a temporary one. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/firmware.c b/drivers/staging/greybus/firmware.c index 6d8fd0e..ee239a9 100644 --- a/drivers/staging/greybus/firmware.c +++ b/drivers/staging/greybus/firmware.c @@ -251,25 +251,23 @@ static int gb_firmware_connection_init(struct gb_connection *connection) firmware_es2_fixup_vid_pid(firmware); - /* - * Module's Bootrom needs a way to know (currently), when to start - * sending requests to the AP. The version request is sent before this - * routine is called, and if the module sends the request right after - * receiving version request, the connection->private field will be - * NULL. - * - * Fix this TEMPORARILY by sending an AP_READY request. - */ + /* Tell bootrom we're ready. */ ret = gb_operation_sync(connection, GB_FIRMWARE_TYPE_AP_READY, NULL, 0, NULL, 0); if (ret) { dev_err(&connection->bundle->dev, "failed to send AP READY: %d\n", ret); + goto err_free_firmware; } dev_dbg(&connection->bundle->dev, "%s: AP_READY sent\n", __func__); return 0; + +err_free_firmware: + kfree(firmware); + + return ret; } static void gb_firmware_connection_exit(struct gb_connection *connection) -- cgit v0.10.2 From a547deb5105b583138e74e882b1e2aae1f76dc9c Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal Date: Thu, 21 Jan 2016 22:33:13 +0530 Subject: greybus: audio_codec: update codec_name as per driver->name Originally, driver->name was not poluated from GB and thus manually set from audio_codec driver as a hack. This is no more required. Another patch already removes that hack. Now, with new driver->name as "legacy." codec is registered with different name. So, during DAI link registration as well it needs modification. Signed-off-by: Vaibhav Agarwal Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 5c02b65..1f39c9c 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -541,7 +541,8 @@ static struct gbaudio_codec_info *gbaudio_get_codec(struct device *dev, gbcodec->dev_id = dev_id; dev_set_drvdata(dev, gbcodec); gbcodec->dev = dev; - strlcpy(gbcodec->name, dev_name(dev), NAME_SIZE); + snprintf(gbcodec->name, NAME_SIZE, "%s.%s", dev->driver->name, + dev_name(dev)); mutex_lock(&gb_codec_list_lock); list_add(&gbcodec->list, &gb_codec_list); -- cgit v0.10.2 From fd7c28ebf03d7c5c293ac07fd178640582c8c137 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 22 Jan 2016 14:42:34 -0800 Subject: greybus: lsgb: add lsgb shell script Horrid hack, but a start at making it easier for people to see what is currently connected without having to deal with poking around in sysfs directly. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/lsgb b/drivers/staging/greybus/lsgb new file mode 100755 index 0000000..4fb30d2 --- /dev/null +++ b/drivers/staging/greybus/lsgb @@ -0,0 +1,149 @@ +#!/bin/sh +# +# 'ls greybus' +# +# Copyright 2016 Google Inc. +# All rights reserved. +# +############################################################################### +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# +# 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 HOLDER 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. +############################################################################### + +# Horrid hack to just make it easier than poking around directly in sysfs +# Don't rely on any of these fields to be stable, the layout is going to +# change a lot over time. +# + +print_interface() { + local devname=$1 + local iid=`cat interface_id` + local vid=`cat vendor_id` + local pid=`cat product_id` + local version=`cat version` + local serial=`cat serial_number` + local vs=`cat vendor_string` + local ps=`cat product_string` + printf "Interface: %s %s:%s ver:%s \"%s\" \"%s\"\n"\ + ${iid} ${vid} ${pid} ${version} "${vs}" "${ps}" +} + +print_bundle() { + local devname=$1 + local id=`cat bundle_id` + local class=`cat bundle_class` + local class_type="unknown" + case ${class} in + "0x01" ) class_type="SVC" + ;; + "0x02" ) class_type="GPIO" + ;; + "0x03" ) class_type="I2C" + ;; + "0x04" ) class_type="UART" + ;; + "0x05" ) class_type="HID" + ;; + "0x06" ) class_type="USB" + ;; + "0x07" ) class_type="SDIO" + ;; + "0x08" ) class_type="Power Supply" + ;; + "0x09" ) class_type="PWM" + ;; + "0x0a" ) class_type="unknown" + ;; + "0x0b" ) class_type="SPI" + ;; + "0x0c" ) class_type="Display" + ;; + "0x0d" ) class_type="Camera" + ;; + "0x0e" ) class_type="Sensoe" + ;; + "0x0f" ) class_type="Lights" + ;; + "0x10" ) class_type="Vibrator" + ;; + "0x11" ) class_type="Loopback" + ;; + "0x12" ) class_type="Audio Management" + ;; + "0x13" ) class_type="Audio Data" + ;; + "0x14" ) class_type="SVC" + ;; + "0x15" ) class_type="Firmware" + ;; + "0xfe" ) class_type="Raw" + ;; + "0xff" ) class_type="Vendor" + ;; + esac + printf " Bundle: %s %s (%s)\n" ${id} ${class_type} ${class} +} + +print_svc() { + local devname=$1 + printf " SVC: ${devname}\n" +} + +print_host_device() { + local devname=$1 + printf " Host: ${devname}\n" +} + +print_unknown() { + local devname=$1 + + printf "Unknown device type: ${devname}\n" +} + + +print_device() { + local dev=$1 + + [ -d $dev ] || return + cd $dev + + local devname=`basename ${dev}` + local devtype=`cat uevent | grep DEVTYPE | cut -f 2 -d '='` + case ${devtype} in + greybus_interface ) print_interface ${devname} + ;; + greybus_bundle ) print_bundle ${devname} + ;; + greybus_svc ) print_svc ${devname} + ;; + greybus_host_device ) print_host_device ${devname} + ;; + * ) print_unknown ${devname} + ;; + esac +} + +for device in /sys/bus/greybus/devices/* +do + print_device $device +done -- cgit v0.10.2 From f3e6c0971af62c81d0a9f0b408ae0e97248e2976 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 22 Jan 2016 16:16:08 +0530 Subject: greybus: svc: Expose and retain VID/PID received from bootrom for ES2 ES2 chips doesn't have efuses for storing module's vendor_id and product_id and so we have hacked bootrom earlier using firmware protocol, so that VID/PID can be received for fetching firmware packages. Another requirement is to expose them to sysfs, so that modules can be identified properly. That can be easily solved by updating interface's VID/PID, when fetched using firmware protocol and later reusing them while the module switches its identity from bootrom to firmware. Do that only if the module is ES2 and the VID/PID sent during hotplug are both 0. Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/firmware.c b/drivers/staging/greybus/firmware.c index ee239a9..3789510 100644 --- a/drivers/staging/greybus/firmware.c +++ b/drivers/staging/greybus/firmware.c @@ -14,8 +14,6 @@ struct gb_firmware { struct gb_connection *connection; const struct firmware *fw; - u32 vendor_id; - u32 product_id; }; static void free_firmware(struct gb_firmware *firmware) @@ -31,7 +29,7 @@ static void free_firmware(struct gb_firmware *firmware) * This fetches VID/PID (over firmware protocol) for es2 chip only, when VID/PID * already sent during hotplug are 0. * - * Otherwise, we keep firmware->vendor_id/product_id same as what's passed + * Otherwise, we keep intf->vendor_id/product_id same as what's passed * during hotplug. */ static void firmware_es2_fixup_vid_pid(struct gb_firmware *firmware) @@ -59,11 +57,18 @@ static void firmware_es2_fixup_vid_pid(struct gb_firmware *firmware) return; } - firmware->vendor_id = le32_to_cpu(response.vendor_id); - firmware->product_id = le32_to_cpu(response.product_id); + /* + * NOTE: This is hacked, so that the same values of VID/PID can be used + * by next firmware level as well. The uevent for bootrom will still + * have VID/PID as 0, though after this point the sysfs files will start + * showing the updated values. But yeah, that's a bit racy as the same + * sysfs files would be showing 0 before this point. + */ + intf->vendor_id = le32_to_cpu(response.vendor_id); + intf->product_id = le32_to_cpu(response.product_id); dev_dbg(&connection->bundle->dev, "Firmware got vid (0x%x)/pid (0x%x)\n", - firmware->vendor_id, firmware->product_id); + intf->vendor_id, intf->product_id); } /* This returns path of the firmware blob on the disk */ @@ -86,7 +91,7 @@ static int download_firmware(struct gb_firmware *firmware, u8 stage) snprintf(firmware_name, sizeof(firmware_name), "ara_%08x_%08x_%08x_%08x_%02x.tftf", intf->ddbl1_manufacturer_id, intf->ddbl1_product_id, - firmware->vendor_id, firmware->product_id, stage); + intf->vendor_id, intf->product_id, stage); // FIXME: // Turn to dev_dbg later after everyone has valid bootloaders with good @@ -246,9 +251,6 @@ static int gb_firmware_connection_init(struct gb_connection *connection) firmware->connection = connection; connection->private = firmware; - firmware->vendor_id = connection->intf->vendor_id; - firmware->product_id = connection->intf->product_id; - firmware_es2_fixup_vid_pid(firmware); /* Tell bootrom we're ready. */ diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index feadb62..85eb7ea 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -464,6 +464,8 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) struct gb_host_device *hd = connection->hd; struct gb_interface *intf; u8 intf_id, device_id; + u32 vendor_id = 0; + u32 product_id = 0; int ret; /* The request message size has already been verified. */ @@ -475,6 +477,14 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) intf = gb_interface_find(hd, intf_id); if (intf) { /* + * For ES2, we need to maintain the same vendor/product ids we + * got from bootrom, otherwise userspace can't distinguish + * between modules. + */ + vendor_id = intf->vendor_id; + product_id = intf->product_id; + + /* * We have received a hotplug request for an interface that * already exists. * @@ -506,6 +516,20 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) intf->product_id = le32_to_cpu(request->data.ara_prod_id); intf->serial_number = le64_to_cpu(request->data.serial_number); + /* + * Use VID/PID specified at hotplug if: + * - Bridge ASIC chip isn't ES2 + * - Received non-zero Vendor/Product ids + * + * Otherwise, use the ids we received from bootrom. + */ + if (intf->ddbl1_manufacturer_id == ES2_DDBL1_MFR_ID && + intf->ddbl1_product_id == ES2_DDBL1_PROD_ID && + intf->vendor_id == 0 && intf->product_id == 0) { + intf->vendor_id = vendor_id; + intf->product_id = product_id; + } + ret = gb_svc_read_and_clear_module_boot_status(intf); if (ret) { dev_err(&svc->dev, "failed to clear boot status of interface %u: %d\n", -- cgit v0.10.2 From 7c154711a6705bbc3036d8f64944e8882fe3fd84 Mon Sep 17 00:00:00 2001 From: Gjorgji Rosikopulos Date: Fri, 22 Jan 2016 17:59:44 +0200 Subject: greybus: camera: add semiplanar and planar formats This change adds missing planar and semiplanar formats from gb specification. Mbus to Gb format map: V4L2_MBUS_FMT_NV12_1x8 -> 0x12 V4L2_MBUS_FMT_NV21_1x8 -> 0x13 V4L2_MBUS_FMT_YV12_1x8 -> 0x16 V4L2_MBUS_FMT_YU12_1x8 -> 0x17 Change depends on: "media: add new mediabus format enums for ara camera" Signed-off-by: Gjorgji Rosikopulos Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 6f14848..bcef392 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -70,11 +70,19 @@ static const struct gb_camera_fmt_map mbus_to_gbus_format[] = { .gb_format = 0x01, }, { - .mbus_code = V4L2_MBUS_FMT_YUYV8_1_5X8, + .mbus_code = V4L2_MBUS_FMT_NV12_1x8, + .gb_format = 0x12, + }, + { + .mbus_code = V4L2_MBUS_FMT_NV21_1x8, + .gb_format = 0x13, + }, + { + .mbus_code = V4L2_MBUS_FMT_YU12_1x8, .gb_format = 0x16, }, { - .mbus_code = V4L2_MBUS_FMT_YVYU8_1_5X8, + .mbus_code = V4L2_MBUS_FMT_YV12_1x8, .gb_format = 0x17, }, { -- cgit v0.10.2 From 0f65fb1ea268a7268ab97a92d172d26d960a5d92 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 22 Jan 2016 18:26:23 -0800 Subject: greybus: lsgb: Minor tweaks Make it executable on an Android system Change layout to be show heirachy a bit better. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/lsgb b/drivers/staging/greybus/lsgb index 4fb30d2..2d84169 100755 --- a/drivers/staging/greybus/lsgb +++ b/drivers/staging/greybus/lsgb @@ -1,4 +1,4 @@ -#!/bin/sh +#!/system/bin/sh # # 'ls greybus' # @@ -44,8 +44,8 @@ print_interface() { local serial=`cat serial_number` local vs=`cat vendor_string` local ps=`cat product_string` - printf "Interface: %s %s:%s ver:%s \"%s\" \"%s\"\n"\ - ${iid} ${vid} ${pid} ${version} "${vs}" "${ps}" + printf " Intf %02d %s:%s %s %s v%s\n" \ + ${iid} ${vid} ${pid} "${vs}" "${ps}" ${version} } print_bundle() { @@ -101,17 +101,19 @@ print_bundle() { "0xff" ) class_type="Vendor" ;; esac - printf " Bundle: %s %s (%s)\n" ${id} ${class_type} ${class} + printf " Bundle %02d Class %s (%s)\n" ${id} ${class} ${class_type} } print_svc() { local devname=$1 - printf " SVC: ${devname}\n" + local bus=`cat uevent | grep BUS | cut -f 2 -d '='` + printf " SVC %02d\n" ${bus} } print_host_device() { local devname=$1 - printf " Host: ${devname}\n" + local bus=`cat uevent | grep BUS | cut -f 2 -d '='` + printf "Bus %02d\n" ${bus} } print_unknown() { -- cgit v0.10.2 From ed7279ae31b0a0a97e832bdd0eb6edb31ec2736f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 20 Jan 2016 22:51:49 -0800 Subject: greybus: svc: add a "watchdog" to check the network health Now that we have a svc ping command, let's add a watchdog to call it every so often (1 second at the moment.) If it finds something went wrong, post a stern message to the kernel log and call: start unipro_reset to reset the whole greybus hardware subsystem. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 1e24509..1e45416 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -8,6 +8,7 @@ greybus-y := core.o \ protocol.o \ control.o \ svc.o \ + svc_watchdog.o \ firmware.o \ operation.o \ legacy.o diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 85eb7ea..fc57470 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -436,6 +436,13 @@ static int gb_svc_hello(struct gb_operation *op) return ret; } + ret = gb_svc_watchdog_create(svc); + if (ret) { + dev_err(&svc->dev, "failed to create watchdog: %d\n", ret); + input_unregister_device(svc->input); + device_del(&svc->dev); + } + return 0; } @@ -963,6 +970,7 @@ void gb_svc_del(struct gb_svc *svc) * from the request handler. */ if (device_is_registered(&svc->dev)) { + gb_svc_watchdog_destroy(svc); input_unregister_device(svc->input); device_del(&svc->dev); } diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index f3e8479..0f81e97 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -16,6 +16,8 @@ enum gb_svc_state { GB_SVC_STATE_SVC_HELLO, }; +struct gb_svc_watchdog; + struct gb_svc { struct device dev; @@ -33,6 +35,7 @@ struct gb_svc { struct input_dev *input; char *input_phys; + struct gb_svc_watchdog *watchdog; }; #define to_gb_svc(d) container_of(d, struct gb_svc, d) @@ -56,6 +59,8 @@ int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series, u8 rx_mode, u8 rx_gear, u8 rx_nlanes, u8 flags, u32 quirks); int gb_svc_ping(struct gb_svc *svc); +int gb_svc_watchdog_create(struct gb_svc *svc); +void gb_svc_watchdog_destroy(struct gb_svc *svc); int gb_svc_protocol_init(void); void gb_svc_protocol_exit(void); diff --git a/drivers/staging/greybus/svc_watchdog.c b/drivers/staging/greybus/svc_watchdog.c new file mode 100644 index 0000000..edb73ef --- /dev/null +++ b/drivers/staging/greybus/svc_watchdog.c @@ -0,0 +1,109 @@ +/* + * SVC Greybus "watchdog" driver. + * + * Copyright 2016 Google Inc. + * + * Released under the GPLv2 only. + */ + +#include +#include +#include "greybus.h" + +#define SVC_WATCHDOG_PERIOD (2*HZ) + +struct gb_svc_watchdog { + struct delayed_work work; + struct gb_svc *svc; + bool finished; +}; + +static struct delayed_work reset_work; + +static void greybus_reset(struct work_struct *work) +{ + static char start_path[256] = "/system/bin/start"; + static char *envp[] = { + "HOME=/", + "PATH=/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin", + NULL, + }; + static char *argv[] = { + start_path, + "unipro_reset", + NULL, + }; + + printk(KERN_ERR "svc_watchdog: calling \"%s %s\" to reset greybus network!\n", + argv[0], argv[1]); + call_usermodehelper(start_path, argv, envp, UMH_WAIT_EXEC); +} + +static void do_work(struct work_struct *work) +{ + struct gb_svc_watchdog *watchdog; + struct gb_svc *svc; + int retval; + + watchdog = container_of(work, struct gb_svc_watchdog, work.work); + svc = watchdog->svc; + + dev_dbg(&svc->dev, "%s: ping.\n", __func__); + retval = gb_svc_ping(svc); + if (retval) { + /* + * Something went really wrong, let's warn userspace and then + * pull the plug and reset the whole greybus network. + * We need to do this outside of this workqueue as we will be + * tearing down the svc device itself. So queue up + * yet-another-callback to do that. + */ + dev_err(&svc->dev, + "SVC ping has returned %d, something is wrong!!!\n", + retval); + dev_err(&svc->dev, "Resetting the greybus network, watch out!!!\n"); + + INIT_DELAYED_WORK(&reset_work, greybus_reset); + queue_delayed_work(system_wq, &reset_work, HZ/2); + return; + } + + /* resubmit our work to happen again, if we are still "alive" */ + if (!watchdog->finished) + queue_delayed_work(system_wq, &watchdog->work, + SVC_WATCHDOG_PERIOD); +} + +int gb_svc_watchdog_create(struct gb_svc *svc) +{ + struct gb_svc_watchdog *watchdog; + + if (svc->watchdog) + return 0; + + watchdog = kmalloc(sizeof(*watchdog), GFP_KERNEL); + if (!watchdog) + return -ENOMEM; + + watchdog->finished = false; + watchdog->svc = svc; + INIT_DELAYED_WORK(&watchdog->work, do_work); + svc->watchdog = watchdog; + + queue_delayed_work(system_wq, &watchdog->work, + SVC_WATCHDOG_PERIOD); + return 0; +} + +void gb_svc_watchdog_destroy(struct gb_svc *svc) +{ + struct gb_svc_watchdog *watchdog = svc->watchdog; + + if (!watchdog) + return; + + watchdog->finished = true; + cancel_delayed_work_sync(&watchdog->work); + svc->watchdog = NULL; + kfree(watchdog); +} -- cgit v0.10.2 From 539d6e11d266bceb597bc416060f9f2888bbd89f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 23 Jan 2016 17:36:00 -0800 Subject: greybus: svc: return proper error code on watchdog create error When the watchdog is not created properly, we need to propagate the error for this and not just return success. Reported-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index fc57470..9df3c7a 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -441,6 +441,7 @@ static int gb_svc_hello(struct gb_operation *op) dev_err(&svc->dev, "failed to create watchdog: %d\n", ret); input_unregister_device(svc->input); device_del(&svc->dev); + return ret; } return 0; -- cgit v0.10.2 From 4fbf69c71cdd3248745fd842481e946d1685f13c Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Sat, 23 Jan 2016 19:44:46 -0800 Subject: greybus: camera: Stream config change unipro speed Unipro network speed was increased at camera initialization time and never slowed down. This unnecessary drains power during the entire time camera module is plugged in. Increasing/decreasing unipro link speed before issuing stream configuration request to camera module prevents this from happening. Signed-off-by: Jacopo Mondi Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index bcef392..c735908 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -120,9 +120,12 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, unsigned int *flags, struct gb_camera_stream_config *streams) { + struct gb_interface *intf = gcam->connection->intf; + struct gb_svc *svc = gcam->connection->hd->svc; struct gb_camera_configure_streams_request *req; struct gb_camera_configure_streams_response *resp; struct ap_csi_config_request csi_cfg; + unsigned int nstreams = *num_streams; unsigned int i; size_t req_size; @@ -142,6 +145,57 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, goto done; } + /* + * Setup unipro link speed before actually issuing configuration + * to the camera module, to assure unipro network speed is set + * before CSI interfaces gets configured + */ + if (nstreams) { + ret = gb_svc_intf_set_power_mode(svc, intf->interface_id, + GB_SVC_UNIPRO_HS_SERIES_A, + GB_SVC_UNIPRO_FAST_MODE, 2, 2, + GB_SVC_UNIPRO_FAST_MODE, 2, 2, + GB_SVC_PWRM_RXTERMINATION | + GB_SVC_PWRM_TXTERMINATION, 0); + if (ret < 0) + goto done; + + ret = gb_svc_intf_set_power_mode(svc, svc->ap_intf_id, + GB_SVC_UNIPRO_HS_SERIES_A, + GB_SVC_UNIPRO_FAST_MODE, 2, 2, + GB_SVC_UNIPRO_FAST_MODE, 2, 2, + GB_SVC_PWRM_RXTERMINATION | + GB_SVC_PWRM_TXTERMINATION, 0); + if (ret < 0) + goto done; + } else { + ret = gb_svc_intf_set_power_mode(svc, intf->interface_id, + GB_SVC_UNIPRO_HS_SERIES_A, + GB_SVC_UNIPRO_SLOW_AUTO_MODE, + 1, 2, + GB_SVC_UNIPRO_SLOW_AUTO_MODE, + 1, 2, + 0, 0); + if (ret < 0) { + gcam_err(gcam, "can't take camera link to PWM-G1 auto: %d\n", + ret); + goto done; + } + + ret = gb_svc_intf_set_power_mode(svc, svc->ap_intf_id, + GB_SVC_UNIPRO_HS_SERIES_A, + GB_SVC_UNIPRO_SLOW_AUTO_MODE, + 1, 2, + GB_SVC_UNIPRO_SLOW_AUTO_MODE, + 1, 2, + 0, 0); + if (ret < 0) { + gcam_err(gcam, "can't take AP link to PWM-G1 auto: %d\n", + ret); + goto done; + } + } + req->num_streams = nstreams; req->flags = *flags; req->padding = 0; @@ -159,19 +213,19 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, GB_CAMERA_TYPE_CONFIGURE_STREAMS, req, req_size, resp, resp_size); if (ret < 0) - goto done; + goto set_unipro_slow_mode; if (resp->num_streams > nstreams) { gcam_dbg(gcam, "got #streams %u > request %u\n", resp->num_streams, nstreams); ret = -EIO; - goto done; + goto set_unipro_slow_mode; } if (resp->padding != 0) { gcam_dbg(gcam, "response padding != 0"); ret = -EIO; - goto done; + goto set_unipro_slow_mode; } *flags = resp->flags; @@ -190,7 +244,7 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, if (cfg->padding[0] || cfg->padding[1] || cfg->padding[2]) { gcam_dbg(gcam, "stream #%u padding != 0", i); ret = -EIO; - goto done; + goto set_unipro_slow_mode; } } @@ -219,6 +273,36 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, *num_streams = resp->num_streams; ret = 0; + kfree(req); + kfree(resp); + return ret; + +set_unipro_slow_mode: + ret = gb_svc_intf_set_power_mode(svc, intf->interface_id, + GB_SVC_UNIPRO_HS_SERIES_A, + GB_SVC_UNIPRO_SLOW_AUTO_MODE, + 1, 2, + GB_SVC_UNIPRO_SLOW_AUTO_MODE, + 1, 2, + 0, 0); + if (ret < 0) { + gcam_err(gcam, "can't take camera link to PWM-G1 auto: %d\n", + ret); + goto done; + } + + gb_svc_intf_set_power_mode(svc, svc->ap_intf_id, + GB_SVC_UNIPRO_HS_SERIES_A, + GB_SVC_UNIPRO_SLOW_AUTO_MODE, + 1, 2, + GB_SVC_UNIPRO_SLOW_AUTO_MODE, + 1, 2, + 0, 0); + if (ret < 0) + gcam_err(gcam, "can't take AP link to PWM-G1 auto: %d\n", + ret); + + done: kfree(req); kfree(resp); @@ -767,24 +851,6 @@ static int gb_camera_connection_init(struct gb_connection *connection) gcam->data_connected = true; - ret = gb_svc_intf_set_power_mode(svc, connection->intf->interface_id, - GB_SVC_UNIPRO_HS_SERIES_A, - GB_SVC_UNIPRO_FAST_MODE, 2, 2, - GB_SVC_UNIPRO_FAST_MODE, 2, 2, - GB_SVC_PWRM_RXTERMINATION | - GB_SVC_PWRM_TXTERMINATION, 0); - if (ret < 0) - goto error; - - ret = gb_svc_intf_set_power_mode(svc, svc->ap_intf_id, - GB_SVC_UNIPRO_HS_SERIES_A, - GB_SVC_UNIPRO_FAST_MODE, 2, 2, - GB_SVC_UNIPRO_FAST_MODE, 2, 2, - GB_SVC_PWRM_RXTERMINATION | - GB_SVC_PWRM_TXTERMINATION, 0); - if (ret < 0) - goto error; - ret = gb_camera_debugfs_init(gcam); if (ret < 0) goto error; -- cgit v0.10.2 From d8b16338df9bcef1fa0a047bd3e8d2e922dc5bb8 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Tue, 26 Jan 2016 07:23:29 +0530 Subject: greybus: arche-platform: Disable clock as part of driver remove As part of driver remove (cleanup) function, disable the clock for both SVC, APB1 & APB2. Testing Done: Tested on EVT1 platform with Connect=>disconnect=>connect iteration, almost close to 100 iterations have passed (demo branch). And also tested with kernel-only build. Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index d073543..f2bad8d 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -220,6 +220,10 @@ static int apb_ctrl_get_devtree_data(struct platform_device *pdev, static void apb_ctrl_cleanup(struct arche_apb_ctrl_drvdata *apb) { + /* disable the clock */ + if (gpio_is_valid(apb->clk_en_gpio)) + gpio_set_value(apb->clk_en_gpio, 0); + if (!IS_ERR(apb->vcore) && regulator_is_enabled(apb->vcore) > 0) regulator_disable(apb->vcore); diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index d12fa0e..b5596ec 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -104,6 +104,7 @@ static void unexport_gpios(struct arche_platform_drvdata *arche_pdata) static void arche_platform_cleanup(struct arche_platform_drvdata *arche_pdata) { + clk_disable_unprepare(arche_pdata->svc_ref_clk); /* As part of exit, put APB back in reset state */ svc_reset_onoff(arche_pdata->svc_reset_gpio, arche_pdata->is_reset_act_hi); -- cgit v0.10.2 From 839ac5b989fbfcc260d23ea4be9e3c8840e1c4e1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 26 Jan 2016 08:57:50 -0800 Subject: greybus: svc: double the ping delay timeout Sometimes the ping response comes back _right_ after we timed out, as the svc got its act together and squeaked out the ack, yet we miss it and reset the whole bus. Double the delay to hopefully give the svc a little more of a chance to fix itself. Odds are, it's still in trouble, but we can just hold off resetting it for a bit more... Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 9df3c7a..b9e5b85 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -365,8 +365,9 @@ EXPORT_SYMBOL_GPL(gb_svc_intf_set_power_mode); int gb_svc_ping(struct gb_svc *svc) { - return gb_operation_sync(svc->connection, GB_SVC_TYPE_PING, - NULL, 0, NULL, 0); + return gb_operation_sync_timeout(svc->connection, GB_SVC_TYPE_PING, + NULL, 0, NULL, 0, + GB_OPERATION_TIMEOUT_DEFAULT * 2); } EXPORT_SYMBOL_GPL(gb_svc_ping); -- cgit v0.10.2 From 7030f9246b55b7c186bd4bd8217162874fe29002 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 25 Jan 2016 20:13:15 -0800 Subject: greybus: camera: only build module against msm kernel The camera driver currently does not build against anything other than the msm kernel, due to cross-dependancies, so enable that here so that we can build against other kernels without failing the build. Signed-off-by: Greg Kroah-Hartman Tested-by: Marti Bolivar Acked-by: Laurent Pinchart Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 1e45416..870a7bb 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -51,7 +51,9 @@ obj-m += gb-arche.o ifeq ($(CONFIG_SND_SOC_DYNAMIC_DAILINK),y) obj-m += gb-audio-codec.o endif -obj-m += gb-camera.o +ifeq ($(CONFIG_ARCH_MSM8994),y) + obj-m += gb-camera.o +endif obj-m += gb-audio-gb.o obj-m += gb-audio-apbridgea.o obj-m += gb-audio-manager.o -- cgit v0.10.2 From d562853d3ecc31806412635adcc590b33621b0c0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 26 Jan 2016 15:17:08 -0800 Subject: greybus: svc watchdog: allow it to be enabled/disabled from userspace Sometimes you want to disable the SVC watchdog without having to patch your kernel, so provide a sysfs file to do this. This can let us do power measurements, and let the firmware developers not go crazy worrying that the kernel is going to reset their chips with no notice. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 1550b7f..4493605 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -163,3 +163,11 @@ KernelVersion: 4.XX Contact: Greg Kroah-Hartman Description: The version number of the firmware in the SVC device. + +What: /sys/bus/greybus/device/N-svc/watchdog +Date: October 2016 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + If the SVC watchdog is enabled or not. Writing 0 to this + file will disable the watchdog, writing 1 will enable it. diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index b9e5b85..eeb251e 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -70,10 +70,42 @@ static ssize_t intf_eject_store(struct device *dev, } static DEVICE_ATTR_WO(intf_eject); +static ssize_t watchdog_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct gb_svc *svc = to_gb_svc(dev); + + return sprintf(buf, "%s\n", + gb_svc_watchdog_enabled(svc) ? "enabled" : "disabled"); +} + +static ssize_t watchdog_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t len) +{ + struct gb_svc *svc = to_gb_svc(dev); + int retval; + bool user_request; + + retval = strtobool(buf, &user_request); + if (retval) + return retval; + + if (user_request) + retval = gb_svc_watchdog_enable(svc); + else + retval = gb_svc_watchdog_disable(svc); + if (retval) + return retval; + return len; +} +static DEVICE_ATTR_RW(watchdog); + static struct attribute *svc_attrs[] = { &dev_attr_endo_id.attr, &dev_attr_ap_intf_id.attr, &dev_attr_intf_eject.attr, + &dev_attr_watchdog.attr, NULL, }; ATTRIBUTE_GROUPS(svc); diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index 0f81e97..b9fb93e 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -61,6 +61,9 @@ int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series, int gb_svc_ping(struct gb_svc *svc); int gb_svc_watchdog_create(struct gb_svc *svc); void gb_svc_watchdog_destroy(struct gb_svc *svc); +bool gb_svc_watchdog_enabled(struct gb_svc *svc); +int gb_svc_watchdog_enable(struct gb_svc *svc); +int gb_svc_watchdog_disable(struct gb_svc *svc); int gb_svc_protocol_init(void); void gb_svc_protocol_exit(void); diff --git a/drivers/staging/greybus/svc_watchdog.c b/drivers/staging/greybus/svc_watchdog.c index edb73ef..9bd68f4 100644 --- a/drivers/staging/greybus/svc_watchdog.c +++ b/drivers/staging/greybus/svc_watchdog.c @@ -15,7 +15,7 @@ struct gb_svc_watchdog { struct delayed_work work; struct gb_svc *svc; - bool finished; + bool enabled; }; static struct delayed_work reset_work; @@ -65,11 +65,16 @@ static void do_work(struct work_struct *work) INIT_DELAYED_WORK(&reset_work, greybus_reset); queue_delayed_work(system_wq, &reset_work, HZ/2); - return; + + /* + * Disable ourselves, we don't want to trip again unless + * userspace wants us to. + */ + watchdog->enabled = false; } /* resubmit our work to happen again, if we are still "alive" */ - if (!watchdog->finished) + if (watchdog->enabled) queue_delayed_work(system_wq, &watchdog->work, SVC_WATCHDOG_PERIOD); } @@ -85,14 +90,12 @@ int gb_svc_watchdog_create(struct gb_svc *svc) if (!watchdog) return -ENOMEM; - watchdog->finished = false; + watchdog->enabled = false; watchdog->svc = svc; INIT_DELAYED_WORK(&watchdog->work, do_work); svc->watchdog = watchdog; - queue_delayed_work(system_wq, &watchdog->work, - SVC_WATCHDOG_PERIOD); - return 0; + return gb_svc_watchdog_enable(svc); } void gb_svc_watchdog_destroy(struct gb_svc *svc) @@ -102,8 +105,47 @@ void gb_svc_watchdog_destroy(struct gb_svc *svc) if (!watchdog) return; - watchdog->finished = true; - cancel_delayed_work_sync(&watchdog->work); + gb_svc_watchdog_disable(svc); svc->watchdog = NULL; kfree(watchdog); } + +bool gb_svc_watchdog_enabled(struct gb_svc *svc) +{ + if (!svc || !svc->watchdog) + return false; + return svc->watchdog->enabled; +} + +int gb_svc_watchdog_enable(struct gb_svc *svc) +{ + struct gb_svc_watchdog *watchdog; + + if (!svc->watchdog) + return -ENODEV; + + watchdog = svc->watchdog; + if (watchdog->enabled) + return 0; + + watchdog->enabled = true; + queue_delayed_work(system_wq, &watchdog->work, + SVC_WATCHDOG_PERIOD); + return 0; +} + +int gb_svc_watchdog_disable(struct gb_svc *svc) +{ + struct gb_svc_watchdog *watchdog; + + if (!svc->watchdog) + return -ENODEV; + + watchdog = svc->watchdog; + if (!watchdog->enabled) + return 0; + + watchdog->enabled = false; + cancel_delayed_work_sync(&watchdog->work); + return 0; +} -- cgit v0.10.2 From 5bee760890aff6dfef8b50c5e4167e9cd003ee7b Mon Sep 17 00:00:00 2001 From: Axel Haslam Date: Tue, 26 Jan 2016 21:26:02 +0100 Subject: greybus: loopback_test: make output to csv file a parameter option Its useful to get a CSV output on stdout for test frameworks to read and parse the results. However, a csv file is not always needed. Add the -z option to create/append a csv file only when the user asks for it. Signed-off-by: Axel Haslam Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/tools/loopback_test.c b/drivers/staging/greybus/tools/loopback_test.c index 27c733d..e8d35bd 100644 --- a/drivers/staging/greybus/tools/loopback_test.c +++ b/drivers/staging/greybus/tools/loopback_test.c @@ -92,6 +92,7 @@ struct loopback_test { int async_timeout; int async_outstanding_operations; int us_wait; + int file_output; char test_name[MAX_STR_LEN]; char sysfs_prefix[MAX_SYSFS_PATH]; char debugfs_prefix[MAX_SYSFS_PATH]; @@ -202,6 +203,7 @@ void usage(void) " -o Async Timeout - Timeout in uSec for async operations\n" " -c Max number of outstanding operations for async operations\n" " -w Wait in uSec between operations\n" + " -z Enable output to a CSV file (incompatible with -p)\n" "Examples:\n" " Send 10000 transfers with a packet size of 128 bytes to all active connections\n" " loopback_test -t transfer -s 128 -i 10000 -S /sys/bus/greybus/devices/ -D /sys/kernel/debug/gb_loopback/\n" @@ -527,7 +529,7 @@ static int log_results(struct loopback_test *t) * append to the same CSV with datestamp - representing each test * dataset. */ - if (!t->porcelain) { + if (t->file_output && !t->porcelain) { snprintf(file_name, sizeof(file_name), "%s_%d_%d.csv", t->test_name, t->size, t->iteration_max); @@ -545,7 +547,7 @@ static int log_results(struct loopback_test *t) len = format_output(t, &t->devices[i].results, t->devices[i].name, data, sizeof(data), &tm); - if (!t->porcelain) { + if (t->file_output && !t->porcelain) { ret = write(fd, data, len); if (ret == -1) fprintf(stderr, "unable to write %d bytes to csv.\n", len); @@ -557,14 +559,14 @@ static int log_results(struct loopback_test *t) if (t->aggregate_output) { len = format_output(t, &t->aggregate_results, "aggregate", data, sizeof(data), &tm); - if (!t->porcelain) { + if (t->file_output && !t->porcelain) { ret = write(fd, data, len); if (ret == -1) fprintf(stderr, "unable to write %d bytes to csv.\n", len); } } - if (!t->porcelain) + if (t->file_output && !t->porcelain) close(fd); return 0; @@ -923,6 +925,8 @@ int main(int argc, char *argv[]) case 'w': t.us_wait = atoi(optarg); break; + case 'z': + t.file_output = 1; default: usage(); return -EINVAL; -- cgit v0.10.2 From 6e304f5963ce2136cf8fda2acfb87cfe942d2e71 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 27 Jan 2016 13:17:52 +0100 Subject: greybus: legacy: fix a null pointer dereference When gb_protocol_get() fails in legacy_connection_create(), we end up bailing-out before assigning lc->connection and lc->protocol. Calling legacy_connection_destroy() in that case results in a null pointer dereference. Check if lc->connection is not null before freeing it. Signed-off-by: Bartosz Golaszewski Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index 4a45a94..838c70f 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -148,6 +148,9 @@ err_protocol_put: static void legacy_connection_destroy(struct legacy_connection *lc) { + if (!lc->connection) + return; + lc->connection->protocol = NULL; gb_connection_destroy(lc->connection); -- cgit v0.10.2 From 2df6396160b019d992241e2db8a6d5a15f654e69 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 27 Jan 2016 11:16:57 +0530 Subject: greybus: audio_codec: Free gccodec on codec probe failure We aren't freeing the codec, that we allocated before failing to probe the connection. Free it. Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 1f39c9c..a7ccaaa 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -713,6 +713,7 @@ topology_error: kfree(topology); base_error: gbcodec->mgmt_connection = NULL; + gbaudio_free_codec(dev, gbcodec); return ret; } -- cgit v0.10.2 From 4b27be1223b048322398e04fcebef7f85c0dac0d Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 27 Jan 2016 11:16:58 +0530 Subject: greybus: audio_codec: Free gccodec on dia probe failure We aren't freeing the codec, that we allocated before failing to probe the connection. Free it. Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index a7ccaaa..5fef495 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -789,6 +789,7 @@ static int gbaudio_dai_probe(struct gb_connection *connection) int dev_id = connection->intf->interface_id; struct gbaudio_codec_info *gbcodec = dev_get_drvdata(dev); struct gb_audio_manager_module_descriptor desc; + int ret; dev_dbg(dev, "Add DAI device:%d:%s\n", dev_id, dev_name(dev)); @@ -800,8 +801,10 @@ static int gbaudio_dai_probe(struct gb_connection *connection) /* add/update dai_list*/ dai = gbaudio_add_dai(gbcodec, connection->intf_cport_id, connection, NULL); - if (!dai) - return -ENOMEM; + if (!dai) { + ret = -ENOMEM; + goto err_free_codec; + } /* update dai_added count */ mutex_lock(&gbcodec->lock); @@ -825,6 +828,10 @@ static int gbaudio_dai_probe(struct gb_connection *connection) mutex_unlock(&gbcodec->lock); return 0; + +err_free_codec: + gbaudio_free_codec(dev, gbcodec); + return ret; } static void gbaudio_dai_remove(struct gb_connection *connection) -- cgit v0.10.2 From 35e28794dcddf2eab1d53b9f3bf5a0eeee82e3c9 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 27 Jan 2016 16:57:48 +0530 Subject: greybus: audio_codec: convert to bundle driver Convert the legacy audio management and data protocol drivers to a bundle driver. The Audio bundle driver can support a single management and any number of data cports, and so we expect multiple data cports to be present for the bundle during initialization. Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 5fef495..b2feba8 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -15,9 +15,6 @@ #include "audio_apbridgea.h" #include "audio_manager.h" -#define GB_AUDIO_MGMT_DRIVER_NAME "gb_audio_mgmt" -#define GB_AUDIO_DATA_DRIVER_NAME "gb_audio_data" - static DEFINE_MUTEX(gb_codec_list_lock); static LIST_HEAD(gb_codec_list); @@ -31,8 +28,8 @@ static int gbcodec_startup(struct snd_pcm_substream *substream, __u16 i2s_port, cportid; struct gbaudio_dai *gb_dai; - struct gbaudio_codec_info *gb = - (struct gbaudio_codec_info *)dev_get_drvdata(dai->dev); + struct gb_audio *audio = dev_get_drvdata(dai->dev); + struct gbaudio_codec_info *gb = audio->gbcodec; /* find the dai */ found = 0; @@ -69,8 +66,8 @@ static void gbcodec_shutdown(struct snd_pcm_substream *substream, __u16 i2s_port, cportid; struct gbaudio_dai *gb_dai; - struct gbaudio_codec_info *gb = - (struct gbaudio_codec_info *)dev_get_drvdata(dai->dev); + struct gb_audio *audio = dev_get_drvdata(dai->dev); + struct gbaudio_codec_info *gb = audio->gbcodec; /* find the dai */ found = 0; @@ -126,8 +123,8 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream, uint32_t format, rate; uint16_t data_cport; struct gbaudio_dai *gb_dai; - struct gbaudio_codec_info *gb = - (struct gbaudio_codec_info *)dev_get_drvdata(dai->dev); + struct gb_audio *audio = dev_get_drvdata(dai->dev); + struct gbaudio_codec_info *gb = audio->gbcodec; /* find the dai */ found = 0; @@ -203,8 +200,8 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream, int ret, found; uint16_t data_cport; struct gbaudio_dai *gb_dai; - struct gbaudio_codec_info *gb = - (struct gbaudio_codec_info *)dev_get_drvdata(dai->dev); + struct gb_audio *audio = dev_get_drvdata(dai->dev); + struct gbaudio_codec_info *gb = audio->gbcodec; /* find the dai */ found = 0; @@ -280,8 +277,8 @@ static int gbcodec_trigger(struct snd_pcm_substream *substream, int cmd, int ret, found; int tx, rx, start, stop; struct gbaudio_dai *gb_dai; - struct gbaudio_codec_info *gb = - (struct gbaudio_codec_info *)dev_get_drvdata(dai->dev); + struct gb_audio *audio = dev_get_drvdata(dai->dev); + struct gbaudio_codec_info *gb = audio->gbcodec; /* find the dai */ found = 0; @@ -386,7 +383,8 @@ static int gbcodec_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int value) { int ret = 0; - struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec); + struct gb_audio *audio = snd_soc_codec_get_drvdata(codec); + struct gbaudio_codec_info *gbcodec = audio->gbcodec; u8 *gbcodec_reg = gbcodec->reg; if (reg == SND_SOC_NOPM) @@ -406,7 +404,8 @@ static unsigned int gbcodec_read(struct snd_soc_codec *codec, { unsigned int val = 0; - struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec); + struct gb_audio *audio = snd_soc_codec_get_drvdata(codec); + struct gbaudio_codec_info *gbcodec = audio->gbcodec; u8 *gbcodec_reg = gbcodec->reg; if (reg == SND_SOC_NOPM) @@ -524,6 +523,7 @@ static struct gbaudio_codec_info *gbaudio_get_codec(struct device *dev, int dev_id) { struct gbaudio_codec_info *gbcodec; + struct gb_audio *audio = dev_get_drvdata(dev); gbcodec = gbaudio_find_codec(dev, dev_id); if (gbcodec) @@ -539,7 +539,7 @@ static struct gbaudio_codec_info *gbaudio_get_codec(struct device *dev, INIT_LIST_HEAD(&gbcodec->codec_ctl_list); INIT_LIST_HEAD(&gbcodec->widget_ctl_list); gbcodec->dev_id = dev_id; - dev_set_drvdata(dev, gbcodec); + audio->gbcodec = gbcodec; gbcodec->dev = dev; snprintf(gbcodec->name, NAME_SIZE, "%s.%s", dev->driver->name, dev_name(dev)); @@ -556,12 +556,14 @@ static struct gbaudio_codec_info *gbaudio_get_codec(struct device *dev, static void gbaudio_free_codec(struct device *dev, struct gbaudio_codec_info *gbcodec) { + struct gb_audio *audio = dev_get_drvdata(dev); + mutex_lock(&gb_codec_list_lock); if (!gbcodec->mgmt_connection && list_empty(&gbcodec->dai_list)) { list_del(&gbcodec->list); mutex_unlock(&gb_codec_list_lock); - dev_set_drvdata(dev, NULL); + audio->gbcodec = NULL; devm_kfree(dev, gbcodec); } else { mutex_unlock(&gb_codec_list_lock); @@ -633,12 +635,16 @@ static int gbaudio_codec_probe(struct gb_connection *connection) gbcodec->mgmt_connection = connection; + ret = gb_connection_enable(connection); + if (ret) + goto base_error; + /* fetch topology data */ ret = gb_audio_gb_get_topology(connection, &topology); if (ret) { dev_err(gbcodec->dev, "%d:Error while fetching topology\n", ret); - goto base_error; + goto err_connection_disable; } /* process topology data */ @@ -711,6 +717,8 @@ parse_error: gbcodec->topology = NULL; topology_error: kfree(topology); +err_connection_disable: + gb_connection_disable(connection); base_error: gbcodec->mgmt_connection = NULL; gbaudio_free_codec(dev, gbcodec); @@ -753,6 +761,7 @@ static void gbaudio_codec_remove(struct gb_connection *connection) dev->driver = NULL; gbaudio_tplg_release(gbcodec); kfree(gbcodec->topology); + gb_connection_disable(connection); gbcodec->mgmt_connection = NULL; mutex_lock(&gbcodec->lock); gbcodec->codec_registered = 0; @@ -760,7 +769,7 @@ static void gbaudio_codec_remove(struct gb_connection *connection) gbaudio_free_codec(dev, gbcodec); } -static int gbaudio_codec_report_event_recv(u8 type, struct gb_operation *op) +static int gbaudio_codec_request_handler(struct gb_operation *op) { struct gb_connection *connection = op->connection; struct gb_audio_streaming_event_request *req = op->request->payload; @@ -772,22 +781,12 @@ static int gbaudio_codec_report_event_recv(u8 type, struct gb_operation *op) return 0; } -static struct gb_protocol gb_audio_mgmt_protocol = { - .name = GB_AUDIO_MGMT_DRIVER_NAME, - .id = GREYBUS_PROTOCOL_AUDIO_MGMT, - .major = 0, - .minor = 1, - .connection_init = gbaudio_codec_probe, - .connection_exit = gbaudio_codec_remove, - .request_recv = gbaudio_codec_report_event_recv, -}; - static int gbaudio_dai_probe(struct gb_connection *connection) { struct gbaudio_dai *dai; struct device *dev = &connection->bundle->dev; int dev_id = connection->intf->interface_id; - struct gbaudio_codec_info *gbcodec = dev_get_drvdata(dev); + struct gbaudio_codec_info *gbcodec; struct gb_audio_manager_module_descriptor desc; int ret; @@ -798,12 +797,16 @@ static int gbaudio_dai_probe(struct gb_connection *connection) if (!gbcodec) return -ENOMEM; + ret = gb_connection_enable(connection); + if (ret) + goto err_free_codec; + /* add/update dai_list*/ dai = gbaudio_add_dai(gbcodec, connection->intf_cport_id, connection, NULL); if (!dai) { ret = -ENOMEM; - goto err_free_codec; + goto err_connection_disable; } /* update dai_added count */ @@ -829,6 +832,8 @@ static int gbaudio_dai_probe(struct gb_connection *connection) return 0; +err_connection_disable: + gb_connection_disable(connection); err_free_codec: gbaudio_free_codec(dev, gbcodec); return ret; @@ -859,10 +864,11 @@ static void gbaudio_dai_remove(struct gb_connection *connection) gbcodec->dai_added--; mutex_unlock(&gbcodec->lock); + gb_connection_disable(connection); gbaudio_free_codec(dev, gbcodec); } -static int gbaudio_dai_report_event_recv(u8 type, struct gb_operation *op) +static int gbaudio_dai_request_handler(struct gb_operation *op) { struct gb_connection *connection = op->connection; @@ -871,50 +877,165 @@ static int gbaudio_dai_report_event_recv(u8 type, struct gb_operation *op) return 0; } -static struct gb_protocol gb_audio_data_protocol = { - .name = GB_AUDIO_DATA_DRIVER_NAME, - .id = GREYBUS_PROTOCOL_AUDIO_DATA, - .major = 0, - .minor = 1, - .connection_init = gbaudio_dai_probe, - .connection_exit = gbaudio_dai_remove, - .request_recv = gbaudio_dai_report_event_recv, -}; +static int gb_audio_add_mgmt_connection(struct gb_audio *audio, + struct greybus_descriptor_cport *cport_desc, + struct gb_bundle *bundle) +{ + struct gb_connection *connection; -/* - * This is the basic hook get things initialized and registered w/ gb - */ + /* Management Cport */ + if (audio->mgmt_connection) { + dev_err(&bundle->dev, + "Can't have multiple Management connections\n"); + return -ENODEV; + } + + connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id), + gbaudio_codec_request_handler); + if (IS_ERR(connection)) + return PTR_ERR(connection); + + connection->private = audio; + audio->mgmt_connection = connection; + + return 0; +} + +static int gb_audio_add_data_connection(struct gb_audio *audio, + struct greybus_descriptor_cport *cport_desc, + struct gb_bundle *bundle, int index) +{ + struct gb_connection *connection; + + connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id), + gbaudio_dai_request_handler); + if (IS_ERR(connection)) + return PTR_ERR(connection); + + connection->private = audio; + audio->data_connection[index] = connection; + + return 0; +} -static int __init gb_audio_protocol_init(void) +static int gb_audio_probe(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) { - int err; + struct greybus_descriptor_cport *cport_desc; + struct gb_audio *audio; + int ret, i; + int count = bundle->num_cports - 1; + + /* There should be at least one Management and one Data cport */ + if (bundle->num_cports < 2) + return -ENODEV; - err = gb_protocol_register(&gb_audio_mgmt_protocol); - if (err) { - pr_err("Can't register i2s mgmt protocol driver: %d\n", -err); - return err; + /* + * There can be only one Management connection and any number of data + * connections. + */ + audio = kzalloc(sizeof(*audio) + + count * sizeof(*audio->data_connection), GFP_KERNEL); + if (!audio) + return -ENOMEM; + + audio->num_data_connections = count; + greybus_set_drvdata(bundle, audio); + + /* Create all connections */ + for (count = 0, i = 0; i < bundle->num_cports; i++) { + cport_desc = &bundle->cport_desc[i]; + + switch (cport_desc->protocol_id) { + case GREYBUS_PROTOCOL_AUDIO_MGMT: + ret = gb_audio_add_mgmt_connection(audio, cport_desc, + bundle); + if (ret) + goto destroy_connections; + break; + case GREYBUS_PROTOCOL_AUDIO_DATA: + ret = gb_audio_add_data_connection(audio, cport_desc, + bundle, count); + if (ret) + goto destroy_connections; + + count++; + break; + default: + dev_err(&bundle->dev, "Unsupported protocol: 0x%02x\n", + cport_desc->protocol_id); + ret = -ENODEV; + goto destroy_connections; + } } - err = gb_protocol_register(&gb_audio_data_protocol); - if (err) { - pr_err("Can't register Audio protocol driver: %d\n", -err); - goto err_unregister_audio_mgmt; + /* There must be a management cport */ + if (!audio->mgmt_connection) { + ret = -EINVAL; + dev_err(&bundle->dev, "Missing management connection\n"); + goto destroy_connections; + } + + /* Initialize management connection */ + ret = gbaudio_codec_probe(audio->mgmt_connection); + if (ret) + goto destroy_connections; + + /* Initialize data connections */ + for (i = 0; i < audio->num_data_connections; i++) { + ret = gbaudio_dai_probe(audio->data_connection[i]); + if (ret) + goto remove_dai; } return 0; -err_unregister_audio_mgmt: - gb_protocol_deregister(&gb_audio_mgmt_protocol); - return err; +remove_dai: + while (i--) + gbaudio_dai_remove(audio->data_connection[i]); + + gbaudio_codec_remove(audio->mgmt_connection); +destroy_connections: + while (count--) + gb_connection_destroy(audio->data_connection[count]); + + if (audio->mgmt_connection) + gb_connection_destroy(audio->mgmt_connection); + + kfree(audio); + + return ret; } -module_init(gb_audio_protocol_init); -static void __exit gb_audio_protocol_exit(void) +static void gb_audio_disconnect(struct gb_bundle *bundle) { - gb_protocol_deregister(&gb_audio_data_protocol); - gb_protocol_deregister(&gb_audio_mgmt_protocol); + struct gb_audio *audio = greybus_get_drvdata(bundle); + int i; + + for (i = audio->num_data_connections - 1; i >= 0; i--) { + gbaudio_dai_remove(audio->data_connection[i]); + gb_connection_destroy(audio->data_connection[i]); + } + + gbaudio_codec_remove(audio->mgmt_connection); + gb_connection_destroy(audio->mgmt_connection); + + kfree(audio); } -module_exit(gb_audio_protocol_exit); + +static const struct greybus_bundle_id gb_audio_id_table[] = { + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_AUDIO_MGMT) }, + { } +}; +MODULE_DEVICE_TABLE(greybus, gb_audio_id_table); + +static struct greybus_driver gb_audio_driver = { + .name = "gb-audio", + .probe = gb_audio_probe, + .disconnect = gb_audio_disconnect, + .id_table = gb_audio_id_table, +}; +module_greybus_driver(gb_audio_driver); MODULE_DESCRIPTION("Greybus Audio codec driver"); MODULE_AUTHOR("Vaibhav Agarwal "); diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index 0b587ef..bba48a5 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -142,6 +142,13 @@ struct gbaudio_codec_info { struct mutex lock; }; +struct gb_audio { + struct gb_connection *mgmt_connection; + size_t num_data_connections; + struct gbaudio_codec_info *gbcodec; + struct gb_connection *data_connection[0]; +}; + struct gbaudio_dai *gbaudio_add_dai(struct gbaudio_codec_info *gbcodec, int data_cport, struct gb_connection *connection, diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index b18574e..90d2148 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -92,7 +92,8 @@ static int gbcodec_mixer_ctl_info(struct snd_kcontrol *kcontrol, struct gbaudio_ctl_pvt *data; struct gb_audio_ctl_elem_info *info; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec); + struct gb_audio *audio = snd_soc_codec_get_drvdata(codec); + struct gbaudio_codec_info *gbcodec = audio->gbcodec; data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; info = (struct gb_audio_ctl_elem_info *)data->info; @@ -138,7 +139,8 @@ static int gbcodec_mixer_ctl_get(struct snd_kcontrol *kcontrol, struct gbaudio_ctl_pvt *data; struct gb_audio_ctl_elem_value gbvalue; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + struct gb_audio *audio = snd_soc_codec_get_drvdata(codec); + struct gbaudio_codec_info *gb = audio->gbcodec; data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; info = (struct gb_audio_ctl_elem_info *)data->info; @@ -185,7 +187,8 @@ static int gbcodec_mixer_ctl_put(struct snd_kcontrol *kcontrol, struct gbaudio_ctl_pvt *data; struct gb_audio_ctl_elem_value gbvalue; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + struct gb_audio *audio = snd_soc_codec_get_drvdata(codec); + struct gbaudio_codec_info *gb = audio->gbcodec; data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; info = (struct gb_audio_ctl_elem_info *)data->info; @@ -279,7 +282,8 @@ static int gbcodec_mixer_dapm_ctl_get(struct snd_kcontrol *kcontrol, struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); struct snd_soc_dapm_widget *widget = wlist->widgets[0]; struct snd_soc_codec *codec = widget->codec; - struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + struct gb_audio *audio = snd_soc_codec_get_drvdata(codec); + struct gbaudio_codec_info *gb = audio->gbcodec; data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; info = (struct gb_audio_ctl_elem_info *)data->info; @@ -313,7 +317,8 @@ static int gbcodec_mixer_dapm_ctl_put(struct snd_kcontrol *kcontrol, struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); struct snd_soc_dapm_widget *widget = wlist->widgets[0]; struct snd_soc_codec *codec = widget->codec; - struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + struct gb_audio *audio = snd_soc_codec_get_drvdata(codec); + struct gbaudio_codec_info *gb = audio->gbcodec; data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; info = (struct gb_audio_ctl_elem_info *)data->info; @@ -519,7 +524,8 @@ static int gbaudio_widget_event(struct snd_soc_dapm_widget *w, int wid; int ret; struct snd_soc_codec *codec = w->codec; - struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec); + struct gb_audio *audio = snd_soc_codec_get_drvdata(codec); + struct gbaudio_codec_info *gbcodec = audio->gbcodec; dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event); diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index 838c70f..677a949 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -249,8 +249,6 @@ static const struct greybus_bundle_id legacy_id_table[] = { { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SENSOR) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_LIGHTS) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_LOOPBACK) }, - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_AUDIO_MGMT) }, - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_AUDIO_DATA) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SVC) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_FIRMWARE) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_RAW) }, -- cgit v0.10.2 From 3b710ec06e00ce041606678b25f9c82e95fde813 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 27 Jan 2016 11:17:00 +0530 Subject: greybus: audio: Rename Audio class and remove the unused one There should be a single class macro for Audio and two protocol macros. Rename class with value 0x12 as GREYBUS_CLASS_AUDIO and remove the other unused class GREYBUS_CLASS_AUDIO_DATA. Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index b2feba8..b43b543 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -1024,7 +1024,7 @@ static void gb_audio_disconnect(struct gb_bundle *bundle) } static const struct greybus_bundle_id gb_audio_id_table[] = { - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_AUDIO_MGMT) }, + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_AUDIO) }, { } }; MODULE_DEVICE_TABLE(greybus, gb_audio_id_table); diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 32602b1..76649a6 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -69,8 +69,8 @@ enum greybus_class_type { GREYBUS_CLASS_LIGHTS = 0x0f, GREYBUS_CLASS_VIBRATOR = 0x10, GREYBUS_CLASS_LOOPBACK = 0x11, - GREYBUS_CLASS_AUDIO_MGMT = 0x12, - GREYBUS_CLASS_AUDIO_DATA = 0x13, + GREYBUS_CLASS_AUDIO = 0x12, + /* 0x13 is unused */ GREYBUS_CLASS_SVC = 0x14, GREYBUS_CLASS_FIRMWARE = 0x15, /* ... */ -- cgit v0.10.2 From 24988d3a253303be63c460071dd99bd4674c0880 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 28 Jan 2016 12:43:29 +0100 Subject: greybus: hd: fix host-device-removal race Make sure to tear down the svc and flush any on-going hotplug processing before removing the remaining interfaces. This fixes crashes due to host-device removal racing with svc hotplug/unplug processing (e.g. at "UniPro restart"). Testing Done: Verified that this fixes crashes reproducible on SDB when unloading the host-device driver module while generating hotplug/unplug events. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index b11a636..d1aab29 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -135,9 +135,12 @@ EXPORT_SYMBOL_GPL(gb_hd_add); void gb_hd_del(struct gb_host_device *hd) { - gb_interfaces_remove(hd); - + /* + * Tear down the svc and flush any on-going hotplug processing before + * removing the remaining interfaces. + */ gb_svc_del(hd->svc); + gb_interfaces_remove(hd); device_del(&hd->dev); } -- cgit v0.10.2 From 057aad29f9dec26d49671c6744d070edb8594174 Mon Sep 17 00:00:00 2001 From: Michael Scott Date: Wed, 27 Jan 2016 16:40:58 -0800 Subject: greybus: arche-platform: ensure wake-detect pin is deasserted During DB3.5 bringup, it was noted that wake_detect signal was not properly generating SVC edge IRQ. To ensure signal goes from low to high correctly, let's bring signal low (regardless of default pin state). Testing Done: - Used for DB3.5/EVT1.5 hardware during bringup - Regression tested on DB3.1+ES2, DB3.1+ES3 Signed-off-by: Michael Scott Reviewed-by: Vaibhav Hiremath Tested-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index b5596ec..4e49be8 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -211,6 +211,8 @@ static int arche_platform_probe(struct platform_device *pdev) arche_pdata->wake_detect_gpio); goto exit; } + /* deassert wake detect */ + gpio_direction_output(arche_pdata->wake_detect_gpio, 0); arche_pdata->dev = &pdev->dev; INIT_DELAYED_WORK(&arche_pdata->delayed_work, svc_delayed_work); -- cgit v0.10.2 From 9e1aef82af47edd1697449ca8be5fd3c1c58b9bb Mon Sep 17 00:00:00 2001 From: Michael Scott Date: Wed, 27 Jan 2016 16:40:59 -0800 Subject: greybus: arche-platform: bring SVC out of reset later in probe Move SVC deassert reset to after wake-detect pin has been pulled low in probe. Otherwise, SVC may trigger WAKE_OUT based on a default high signal. Testing Done: - Used for DB3.5/EVT1.5 hardware during bringup - Regression tested on DB3.1+ES2, DB3.1+ES3 Signed-off-by: Michael Scott Reviewed-by: Vaibhav Hiremath Tested-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 4e49be8..b6fb90e 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -191,10 +191,6 @@ static int arche_platform_probe(struct platform_device *pdev) platform_set_drvdata(pdev, arche_pdata); - /* bring SVC out of reset */ - svc_reset_onoff(arche_pdata->svc_reset_gpio, - !arche_pdata->is_reset_act_hi); - arche_pdata->num_apbs = of_get_child_count(np); dev_dbg(dev, "Number of APB's available - %d\n", arche_pdata->num_apbs); @@ -214,6 +210,10 @@ static int arche_platform_probe(struct platform_device *pdev) /* deassert wake detect */ gpio_direction_output(arche_pdata->wake_detect_gpio, 0); + /* bring SVC out of reset */ + svc_reset_onoff(arche_pdata->svc_reset_gpio, + !arche_pdata->is_reset_act_hi); + arche_pdata->dev = &pdev->dev; INIT_DELAYED_WORK(&arche_pdata->delayed_work, svc_delayed_work); schedule_delayed_work(&arche_pdata->delayed_work, msecs_to_jiffies(2000)); -- cgit v0.10.2 From 1e83ee3321447679eb327fed90f366ef18411778 Mon Sep 17 00:00:00 2001 From: Michael Scott Date: Wed, 27 Jan 2016 16:41:00 -0800 Subject: greybus: arche-platform: assert wake-detect to complete WAKE_OUT event After SVC generates WAKE_OUT (pulling wake-detect pin low) and APB is brought out of reset, we need to assert wake-detect again to complete SVC WAKE_OUT logic. Testing Done: - Used for DB3.5/EVT1.5 hardware during bringup - Regression tested on DB3.1+ES2, DB3.1+ES3 Signed-off-by: Michael Scott Reviewed-by: Vaibhav Hiremath Tested-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index b6fb90e..f18cec6 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -79,9 +79,11 @@ static void svc_delayed_work(struct work_struct *work) if (timeout >= 0) { ret = of_platform_populate(np, NULL, NULL, dev); - if (!ret) - /* Should we set wake_detect gpio to output again? */ + if (!ret) { + /* re-assert wake_detect to confirm SVC WAKE_OUT */ + gpio_direction_output(arche_pdata->wake_detect_gpio, 1); return; + } } /* FIXME: We may want to limit retries here */ -- cgit v0.10.2 From a3043d9e717ace89a34352e57d88c70584f9c768 Mon Sep 17 00:00:00 2001 From: Michael Scott Date: Wed, 27 Jan 2016 16:41:01 -0800 Subject: greybus: arche-platform: reduce wait between WAKE_OUT checks SVC WAKE_OUT loop is estimated 400ms during which wake_detect line is pulled low for AP detection. On AP side we have 500ms delay between checks. To avoid timing issues, reduce delay between checks and raise total # of checks so that overall time for sequence is the same. Testing Done: - Used for DB3.5/EVT1.5 hardware during bringup - Regression tested on DB3.1+ES2, DB3.1+ES3 Signed-off-by: Michael Scott Reviewed-by: Vaibhav Hiremath Tested-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index f18cec6..65c8f71 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -52,7 +52,7 @@ static void svc_delayed_work(struct work_struct *work) container_of(work, struct arche_platform_drvdata, delayed_work.work); struct device *dev = arche_pdata->dev; struct device_node *np = dev->of_node; - int timeout = 10; + int timeout = 50; int ret; /* @@ -74,7 +74,7 @@ static void svc_delayed_work(struct work_struct *work) if (gpio_get_value(arche_pdata->wake_detect_gpio) == 0) break; - msleep(500); + msleep(100); } while(timeout--); if (timeout >= 0) { -- cgit v0.10.2 From c760442e1cafef30de20ea5b64074d70efa6eec2 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 29 Jan 2016 15:42:30 +0100 Subject: greybus: legacy: remove unimplemented classes from id table Remove the unimplemented display, sensor, and svc classes from the device-id table. As Viresh noted the SVC protocol is special and having an SVC class doesn't really make sense at all. Either way, the SVC protocol is already implemented by core. Testing Done: Compiled Reported-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index 677a949..900521a 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -244,12 +244,9 @@ static const struct greybus_bundle_id legacy_id_table[] = { { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_POWER_SUPPLY) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_PWM) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SPI) }, - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_DISPLAY) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_CAMERA) }, - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SENSOR) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_LIGHTS) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_LOOPBACK) }, - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SVC) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_FIRMWARE) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_RAW) }, { } -- cgit v0.10.2 From 8ec589b9796eebfa266d2b047ee2318541814e28 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 29 Jan 2016 15:42:31 +0100 Subject: greybus: firmware: convert to bundle driver Convert the legacy firmware protocol driver to a bundle driver. This also fixes a potential crash should a (malicious) module have sent an early request before the private data had been initialised. Note that the firmware protocol needs to support the version request indefinitely since it has been burnt into ROM. In order to avoid having to update current module-loading scripts, keep this driver internal to greybus core at least until modalias support is added. Note that there is no MODULE_DEVICE_TABLE defined for firmware as we cannot have two greybus tables in one module on ancient 3.10 kernels and that the legacy driver is currently also internal to core. This needs be added once the driver can be built as a module. Testing Done: Tested on DB3. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index b9303c0..2fb9574 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -10,6 +10,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define CREATE_TRACE_POINTS +#include "firmware.h" #include "greybus.h" #include "greybus_trace.h" #include "legacy.h" @@ -243,9 +244,9 @@ static int __init gb_init(void) goto error_operation; } - retval = gb_firmware_protocol_init(); + retval = gb_firmware_init(); if (retval) { - pr_err("gb_firmware_protocol_init failed\n"); + pr_err("gb_firmware_init failed\n"); goto error_firmware; } @@ -258,7 +259,7 @@ static int __init gb_init(void) return 0; /* Success */ error_legacy: - gb_firmware_protocol_exit(); + gb_firmware_exit(); error_firmware: gb_operation_exit(); error_operation: @@ -275,7 +276,7 @@ module_init(gb_init); static void __exit gb_exit(void) { gb_legacy_exit(); - gb_firmware_protocol_exit(); + gb_firmware_exit(); gb_operation_exit(); gb_hd_exit(); bus_unregister(&greybus_bus_type); diff --git a/drivers/staging/greybus/firmware.c b/drivers/staging/greybus/firmware.c index 3789510..17ce573 100644 --- a/drivers/staging/greybus/firmware.c +++ b/drivers/staging/greybus/firmware.c @@ -9,11 +9,15 @@ #include +#include "firmware.h" #include "greybus.h" + struct gb_firmware { struct gb_connection *connection; const struct firmware *fw; + u8 protocol_major; + u8 protocol_minor; }; static void free_firmware(struct gb_firmware *firmware) @@ -223,8 +227,10 @@ static int gb_firmware_ready_to_boot(struct gb_operation *op) return 0; } -static int gb_firmware_request_recv(u8 type, struct gb_operation *op) +static int gb_firmware_request_handler(struct gb_operation *op) { + u8 type = op->type; + switch (type) { case GB_FIRMWARE_TYPE_FIRMWARE_SIZE: return gb_firmware_size_request(op); @@ -239,60 +245,147 @@ static int gb_firmware_request_recv(u8 type, struct gb_operation *op) } } -static int gb_firmware_connection_init(struct gb_connection *connection) +static int gb_firmware_get_version(struct gb_firmware *firmware) { + struct gb_bundle *bundle = firmware->connection->bundle; + struct gb_firmware_version_request request; + struct gb_firmware_version_response response; + int ret; + + request.major = GB_FIRMWARE_VERSION_MAJOR; + request.minor = GB_FIRMWARE_VERSION_MINOR; + + ret = gb_operation_sync(firmware->connection, + GB_FIRMWARE_TYPE_VERSION, + &request, sizeof(request), &response, + sizeof(response)); + if (ret) { + dev_err(&bundle->dev, + "failed to get protocol version: %d\n", + ret); + return ret; + } + + if (response.major > request.major) { + dev_err(&bundle->dev, + "unsupported major protocol version (%u > %u)\n", + response.major, request.major); + return -ENOTSUPP; + } + + firmware->protocol_major = response.major; + firmware->protocol_minor = response.minor; + + dev_dbg(&bundle->dev, "%s - %u.%u\n", __func__, response.major, + response.minor); + + return 0; +} + +static int gb_firmware_probe(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) +{ + struct greybus_descriptor_cport *cport_desc; + struct gb_connection *connection; struct gb_firmware *firmware; int ret; + if (bundle->num_cports != 1) + return -ENODEV; + + cport_desc = &bundle->cport_desc[0]; + if (cport_desc->protocol_id != GREYBUS_PROTOCOL_FIRMWARE) + return -ENODEV; + firmware = kzalloc(sizeof(*firmware), GFP_KERNEL); if (!firmware) return -ENOMEM; - firmware->connection = connection; + connection = gb_connection_create(bundle, + le16_to_cpu(cport_desc->id), + gb_firmware_request_handler); + if (IS_ERR(connection)) { + ret = PTR_ERR(connection); + goto err_free_firmware; + } + connection->private = firmware; + firmware->connection = connection; + + greybus_set_drvdata(bundle, firmware); + + ret = gb_connection_enable_tx(connection); + if (ret) + goto err_connection_destroy; + + ret = gb_firmware_get_version(firmware); + if (ret) + goto err_connection_disable; + firmware_es2_fixup_vid_pid(firmware); + ret = gb_connection_enable(connection); + if (ret) + goto err_connection_disable; + /* Tell bootrom we're ready. */ ret = gb_operation_sync(connection, GB_FIRMWARE_TYPE_AP_READY, NULL, 0, NULL, 0); if (ret) { dev_err(&connection->bundle->dev, "failed to send AP READY: %d\n", ret); - goto err_free_firmware; + goto err_connection_disable; } - dev_dbg(&connection->bundle->dev, "%s: AP_READY sent\n", __func__); + dev_dbg(&bundle->dev, "AP_READY sent\n"); return 0; +err_connection_disable: + gb_connection_disable(connection); +err_connection_destroy: + gb_connection_destroy(connection); err_free_firmware: kfree(firmware); return ret; } -static void gb_firmware_connection_exit(struct gb_connection *connection) +static void gb_firmware_disconnect(struct gb_bundle *bundle) { - struct gb_firmware *firmware = connection->private; + struct gb_firmware *firmware = greybus_get_drvdata(bundle); + + dev_dbg(&bundle->dev, "%s\n", __func__); + + gb_connection_disable(firmware->connection); /* Release firmware */ if (firmware->fw) free_firmware(firmware); - connection->private = NULL; + gb_connection_destroy(firmware->connection); kfree(firmware); - - dev_dbg(&connection->bundle->dev, "%s\n", __func__); } -static struct gb_protocol firmware_protocol = { - .name = "firmware", - .id = GREYBUS_PROTOCOL_FIRMWARE, - .major = GB_FIRMWARE_VERSION_MAJOR, - .minor = GB_FIRMWARE_VERSION_MINOR, - .connection_init = gb_firmware_connection_init, - .connection_exit = gb_firmware_connection_exit, - .request_recv = gb_firmware_request_recv, +static const struct greybus_bundle_id gb_firmware_id_table[] = { + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_FIRMWARE) }, + { } }; -gb_builtin_protocol_driver(firmware_protocol); + +static struct greybus_driver gb_firmware_driver = { + .name = "firmware", + .probe = gb_firmware_probe, + .disconnect = gb_firmware_disconnect, + .id_table = gb_firmware_id_table, +}; + +int gb_firmware_init(void) +{ + return greybus_register(&gb_firmware_driver); +} + +void gb_firmware_exit(void) +{ + greybus_deregister(&gb_firmware_driver); +} diff --git a/drivers/staging/greybus/firmware.h b/drivers/staging/greybus/firmware.h index 548d297..f25744c 100644 --- a/drivers/staging/greybus/firmware.h +++ b/drivers/staging/greybus/firmware.h @@ -10,7 +10,7 @@ #ifndef __FIRMWARE_H #define __FIRMWARE_H -int gb_firmware_protocol_init(void); -void gb_firmware_protocol_exit(void); +int gb_firmware_init(void); +void gb_firmware_exit(void); #endif /* __FIRMWARE_H */ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 2767946..2fc79fa 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -27,7 +27,6 @@ #include "manifest.h" #include "hd.h" #include "svc.h" -#include "firmware.h" #include "control.h" #include "interface.h" #include "bundle.h" diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 3f51fb5..89db932 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -203,6 +203,7 @@ struct gb_control_interface_version_response { #define GB_FIRMWARE_VERSION_MINOR 0x01 /* Greybus firmware request types */ +#define GB_FIRMWARE_TYPE_VERSION 0x01 #define GB_FIRMWARE_TYPE_FIRMWARE_SIZE 0x02 #define GB_FIRMWARE_TYPE_GET_FIRMWARE 0x03 #define GB_FIRMWARE_TYPE_READY_TO_BOOT 0x04 @@ -226,6 +227,16 @@ struct gb_control_interface_version_response { /* Max firmware data fetch size in bytes */ #define GB_FIRMWARE_FETCH_MAX 2000 +struct gb_firmware_version_request { + __u8 major; + __u8 minor; +} __packed; + +struct gb_firmware_version_response { + __u8 major; + __u8 minor; +} __packed; + /* Firmware protocol firmware size request/response */ struct gb_firmware_size_request { __u8 stage; diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index 900521a..057029d 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -247,7 +247,6 @@ static const struct greybus_bundle_id legacy_id_table[] = { { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_CAMERA) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_LIGHTS) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_LOOPBACK) }, - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_FIRMWARE) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_RAW) }, { } }; -- cgit v0.10.2 From 3f830562deade2ab6163f07ee6829158cc070ee4 Mon Sep 17 00:00:00 2001 From: Axel Haslam Date: Fri, 29 Jan 2016 11:34:19 +0100 Subject: greybus: loopback_test: Decrease the max number of devices Its unrealistic to expect 50 loopback devices, and the mask parameter can hold up to "int" anyways so decrease to max number of devices to sane value. Signed-off-by: Axel Haslam Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/tools/loopback_test.c b/drivers/staging/greybus/tools/loopback_test.c index e8d35bd..6178354 100644 --- a/drivers/staging/greybus/tools/loopback_test.c +++ b/drivers/staging/greybus/tools/loopback_test.c @@ -17,7 +17,7 @@ #include #include -#define MAX_NUM_DEVICES 50 +#define MAX_NUM_DEVICES 10 #define MAX_SYSFS_PATH 0x200 #define CSV_MAX_LINE 0x1000 #define SYSFS_MAX_INT 0x20 -- cgit v0.10.2 From 3c5de59473f88aeb12420f142d42801d4d389759 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 25 Jan 2016 16:52:17 -0800 Subject: greybus: audio_manager: use an 'ida' for the module id Every time we hotplug an audio module, we get a new audio module id. We should recycle them instead of just constantly incrementing the number so we don't see things like: [178016.832580] Created audio module #6124 in the kernel logs. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio_manager.c b/drivers/staging/greybus/audio_manager.c index 1176763..05af441 100644 --- a/drivers/staging/greybus/audio_manager.c +++ b/drivers/staging/greybus/audio_manager.c @@ -19,8 +19,7 @@ static struct kset *manager_kset; static LIST_HEAD(modules_list); static DEFINE_RWLOCK(modules_lock); - -static int current_module_id; +static DEFINE_IDA(module_id); /* helpers */ static struct gb_audio_manager_module *gb_audio_manager_get_locked(int id) @@ -43,12 +42,16 @@ int gb_audio_manager_add(struct gb_audio_manager_module_descriptor *desc) { struct gb_audio_manager_module *module; unsigned long flags; + int id; int err; + id = ida_simple_get(&module_id, 0, 0, GFP_KERNEL); err = gb_audio_manager_module_create(&module, manager_kset, - current_module_id++, desc); - if (err) + id, desc); + if (err) { + ida_simple_remove(&module_id, id); return err; + } /* Add it to the list */ write_lock_irqsave(&modules_lock, flags); @@ -72,6 +75,7 @@ int gb_audio_manager_remove(int id) return -EINVAL; } + ida_simple_remove(&module_id, module->id); list_del(&module->list); kobject_put(&module->kobj); write_unlock_irqrestore(&modules_lock, flags); @@ -175,6 +179,7 @@ static void __exit manager_exit(void) { gb_audio_manager_remove_all(); kset_unregister(manager_kset); + ida_destroy(&module_id); } module_init(manager_init); -- cgit v0.10.2 From 1045451f8abbfe3628af9bc1ce53da4d57723626 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 28 Jan 2016 15:50:47 +0530 Subject: greybus: audio: Fix sparse warnings greybus/audio_apbridgea.c:13:5: warning: symbol 'gb_audio_apbridgea_set_config' was not declared. Should it be static? greybus/audio_apbridgea.c:30:5: warning: symbol 'gb_audio_apbridgea_register_cport' was not declared. Should it be static? greybus/audio_apbridgea.c:44:5: warning: symbol 'gb_audio_apbridgea_unregister_cport' was not declared. Should it be static? greybus/audio_apbridgea.c:58:5: warning: symbol 'gb_audio_apbridgea_set_tx_data_size' was not declared. Should it be static? greybus/audio_apbridgea.c:72:5: warning: symbol 'gb_audio_apbridgea_get_tx_delay' was not declared. Should it be static? greybus/audio_apbridgea.c:80:5: warning: symbol 'gb_audio_apbridgea_start_tx' was not declared. Should it be static? greybus/audio_apbridgea.c:94:5: warning: symbol 'gb_audio_apbridgea_stop_tx' was not declared. Should it be static? greybus/audio_apbridgea.c:106:5: warning: symbol 'gb_audio_apbridgea_set_rx_data_size' was not declared. Should it be static? greybus/audio_apbridgea.c:120:5: warning: symbol 'gb_audio_apbridgea_get_rx_delay' was not declared. Should it be static? greybus/audio_apbridgea.c:128:5: warning: symbol 'gb_audio_apbridgea_start_rx' was not declared. Should it be static? greybus/audio_apbridgea.c:141:5: warning: symbol 'gb_audio_apbridgea_stop_rx' was not declared. Should it be static? greybus/audio_gb.c:14:5: warning: symbol 'gb_audio_gb_get_topology' was not declared. Should it be static? greybus/audio_gb.c:48:5: warning: symbol 'gb_audio_gb_get_control' was not declared. Should it be static? greybus/audio_gb.c:70:5: warning: symbol 'gb_audio_gb_set_control' was not declared. Should it be static? greybus/audio_gb.c:85:5: warning: symbol 'gb_audio_gb_enable_widget' was not declared. Should it be static? greybus/audio_gb.c:97:5: warning: symbol 'gb_audio_gb_disable_widget' was not declared. Should it be static? greybus/audio_gb.c:109:5: warning: symbol 'gb_audio_gb_get_pcm' was not declared. Should it be static? greybus/audio_gb.c:133:5: warning: symbol 'gb_audio_gb_set_pcm' was not declared. Should it be static? greybus/audio_gb.c:150:5: warning: symbol 'gb_audio_gb_set_tx_data_size' was not declared. Should it be static? greybus/audio_gb.c:163:5: warning: symbol 'gb_audio_gb_get_tx_delay' was not declared. Should it be static? greybus/audio_gb.c:183:5: warning: symbol 'gb_audio_gb_activate_tx' was not declared. Should it be static? greybus/audio_gb.c:195:5: warning: symbol 'gb_audio_gb_deactivate_tx' was not declared. Should it be static? greybus/audio_gb.c:207:5: warning: symbol 'gb_audio_gb_set_rx_data_size' was not declared. Should it be static? greybus/audio_gb.c:220:5: warning: symbol 'gb_audio_gb_get_rx_delay' was not declared. Should it be static? greybus/audio_gb.c:240:5: warning: symbol 'gb_audio_gb_activate_rx' was not declared. Should it be static? greybus/audio_gb.c:252:5: warning: symbol 'gb_audio_gb_deactivate_rx' was not declared. Should it be static? Fix them by including the header that declares the exported routines. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio_apbridgea.c b/drivers/staging/greybus/audio_apbridgea.c index 20238e6..75c8c3c 100644 --- a/drivers/staging/greybus/audio_apbridgea.c +++ b/drivers/staging/greybus/audio_apbridgea.c @@ -9,6 +9,7 @@ #include "greybus.h" #include "greybus_protocols.h" #include "audio_apbridgea.h" +#include "audio_codec.h" int gb_audio_apbridgea_set_config(struct gb_connection *connection, __u16 i2s_port, __u32 format, __u32 rate, diff --git a/drivers/staging/greybus/audio_gb.c b/drivers/staging/greybus/audio_gb.c index 08bfdeb..167683d 100644 --- a/drivers/staging/greybus/audio_gb.c +++ b/drivers/staging/greybus/audio_gb.c @@ -9,6 +9,7 @@ #include "greybus.h" #include "greybus_protocols.h" #include "operation.h" +#include "audio_codec.h" /* TODO: Split into separate calls */ int gb_audio_gb_get_topology(struct gb_connection *connection, -- cgit v0.10.2 From ee9627bce7561f772345a329e783149893cfbb55 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 28 Jan 2016 15:50:49 +0530 Subject: greybus: control: Fix sparse warnings gb_control_get_version() is not used outside of the file and must be marked as static. Following sparse warnings are reported today: greybus/control.c:20:5: warning: symbol 'gb_control_get_version' was not declared. Should it be static? Fix it by marking gb_control_get_version() 'static'. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index fb0bb1c..ba2754a 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -17,7 +17,7 @@ #define GB_CONTROL_VERSION_MINOR 1 -int gb_control_get_version(struct gb_control *control) +static int gb_control_get_version(struct gb_control *control) { struct gb_interface *intf = control->connection->intf; struct gb_control_version_request request; -- cgit v0.10.2 From 68ba0a01ccc3e0aff3687ac2704c01a3849d5345 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 2 Feb 2016 21:35:12 -0800 Subject: greybus: lsgb: remove it, it's in the gb-utils repo lsgb does not need to be in this repo, it gets installed as part of gb-utils now. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/lsgb b/drivers/staging/greybus/lsgb deleted file mode 100755 index 2d84169..0000000 --- a/drivers/staging/greybus/lsgb +++ /dev/null @@ -1,151 +0,0 @@ -#!/system/bin/sh -# -# 'ls greybus' -# -# Copyright 2016 Google Inc. -# All rights reserved. -# -############################################################################### -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# 1. Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# 3. Neither the name of the copyright holder nor the names of its -# contributors may be used to endorse or promote products derived from this -# software without specific prior written permission. -# -# 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 HOLDER 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. -############################################################################### - -# Horrid hack to just make it easier than poking around directly in sysfs -# Don't rely on any of these fields to be stable, the layout is going to -# change a lot over time. -# - -print_interface() { - local devname=$1 - local iid=`cat interface_id` - local vid=`cat vendor_id` - local pid=`cat product_id` - local version=`cat version` - local serial=`cat serial_number` - local vs=`cat vendor_string` - local ps=`cat product_string` - printf " Intf %02d %s:%s %s %s v%s\n" \ - ${iid} ${vid} ${pid} "${vs}" "${ps}" ${version} -} - -print_bundle() { - local devname=$1 - local id=`cat bundle_id` - local class=`cat bundle_class` - local class_type="unknown" - case ${class} in - "0x01" ) class_type="SVC" - ;; - "0x02" ) class_type="GPIO" - ;; - "0x03" ) class_type="I2C" - ;; - "0x04" ) class_type="UART" - ;; - "0x05" ) class_type="HID" - ;; - "0x06" ) class_type="USB" - ;; - "0x07" ) class_type="SDIO" - ;; - "0x08" ) class_type="Power Supply" - ;; - "0x09" ) class_type="PWM" - ;; - "0x0a" ) class_type="unknown" - ;; - "0x0b" ) class_type="SPI" - ;; - "0x0c" ) class_type="Display" - ;; - "0x0d" ) class_type="Camera" - ;; - "0x0e" ) class_type="Sensoe" - ;; - "0x0f" ) class_type="Lights" - ;; - "0x10" ) class_type="Vibrator" - ;; - "0x11" ) class_type="Loopback" - ;; - "0x12" ) class_type="Audio Management" - ;; - "0x13" ) class_type="Audio Data" - ;; - "0x14" ) class_type="SVC" - ;; - "0x15" ) class_type="Firmware" - ;; - "0xfe" ) class_type="Raw" - ;; - "0xff" ) class_type="Vendor" - ;; - esac - printf " Bundle %02d Class %s (%s)\n" ${id} ${class} ${class_type} -} - -print_svc() { - local devname=$1 - local bus=`cat uevent | grep BUS | cut -f 2 -d '='` - printf " SVC %02d\n" ${bus} -} - -print_host_device() { - local devname=$1 - local bus=`cat uevent | grep BUS | cut -f 2 -d '='` - printf "Bus %02d\n" ${bus} -} - -print_unknown() { - local devname=$1 - - printf "Unknown device type: ${devname}\n" -} - - -print_device() { - local dev=$1 - - [ -d $dev ] || return - cd $dev - - local devname=`basename ${dev}` - local devtype=`cat uevent | grep DEVTYPE | cut -f 2 -d '='` - case ${devtype} in - greybus_interface ) print_interface ${devname} - ;; - greybus_bundle ) print_bundle ${devname} - ;; - greybus_svc ) print_svc ${devname} - ;; - greybus_host_device ) print_host_device ${devname} - ;; - * ) print_unknown ${devname} - ;; - esac -} - -for device in /sys/bus/greybus/devices/* -do - print_device $device -done -- cgit v0.10.2 From 127c1fbd55939642365f26efd3121562629ec1b1 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 28 Jan 2016 15:50:48 +0530 Subject: greybus: connection: Fix sparse warnings around locking The callers ensures that connection->lock is taken before calling few routines, but that isn't enough for sparse as it sees an unexpected unlock. greybus/connection.c:380:29: warning: context imbalance in 'gb_connection_cancel_operations' - unexpected unlock Fix that adding __must_lock() attribute to the function declaration. This also adds the attribute for gb_connection_flush_incoming_operations(), which isn't showing any sparse warnings with the current state of code, but with minor rearrangements of the code. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 77c2f67..4f5e2ad 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -373,6 +373,7 @@ gb_connection_control_disconnected(struct gb_connection *connection) */ static void gb_connection_cancel_operations(struct gb_connection *connection, int errno) + __must_hold(&connection->lock) { struct gb_operation *operation; @@ -401,6 +402,7 @@ static void gb_connection_cancel_operations(struct gb_connection *connection, static void gb_connection_flush_incoming_operations(struct gb_connection *connection, int errno) + __must_hold(&connection->lock) { struct gb_operation *operation; bool incoming; -- cgit v0.10.2 From 796fad441cb248c1eac88bfb3a5929bb1a10fabb Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal Date: Thu, 28 Jan 2016 21:15:39 +0530 Subject: greybus: audio: codec driver cleanup audio codec driver is now moved to bundle driver approach. This resolved many race conditions related to audio mgmt & data connection init/exit sequence. Thus, a lot of helper functions can now be safely removed. Signed-off-by: Vaibhav Agarwal Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index b43b543..ad28c10 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -18,30 +18,38 @@ static DEFINE_MUTEX(gb_codec_list_lock); static LIST_HEAD(gb_codec_list); +struct gbaudio_dai *gbaudio_find_dai(struct gbaudio_codec_info *gbcodec, + int data_cport, const char *name) +{ + struct gbaudio_dai *dai; + + list_for_each_entry(dai, &gbcodec->dai_list, list) { + if (name && !strncmp(dai->name, name, NAME_SIZE)) + return dai; + if ((data_cport != -1) && (dai->data_cport == data_cport)) + return dai; + } + return NULL; +} + /* * codec DAI ops */ static int gbcodec_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - int ret, found; + int ret; __u16 i2s_port, cportid; struct gbaudio_dai *gb_dai; - struct gb_audio *audio = dev_get_drvdata(dai->dev); - struct gbaudio_codec_info *gb = audio->gbcodec; + struct gbaudio_codec_info *gb = dev_get_drvdata(dai->dev); /* find the dai */ - found = 0; - list_for_each_entry(gb_dai, &gb->dai_list, list) { - if (!strncmp(gb_dai->name, dai->name, NAME_SIZE)) { - found = 1; - break; - } - } - - if (!found) { + mutex_lock(&gb->lock); + gb_dai = gbaudio_find_dai(gb, -1, dai->name); + if (!gb_dai) { dev_err(dai->dev, "%s: DAI not registered\n", dai->name); + mutex_unlock(&gb->lock); return -EINVAL; } @@ -54,7 +62,8 @@ static int gbcodec_startup(struct snd_pcm_substream *substream, ret); if (!ret) - atomic_inc(&gb->users); + atomic_inc(&gb_dai->users); + mutex_unlock(&gb->lock); return ret; } @@ -62,28 +71,21 @@ static int gbcodec_startup(struct snd_pcm_substream *substream, static void gbcodec_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - int ret, found; + int ret; __u16 i2s_port, cportid; struct gbaudio_dai *gb_dai; - struct gb_audio *audio = dev_get_drvdata(dai->dev); - struct gbaudio_codec_info *gb = audio->gbcodec; + struct gbaudio_codec_info *gb = dev_get_drvdata(dai->dev); /* find the dai */ - found = 0; - list_for_each_entry(gb_dai, &gb->dai_list, list) { - if (!strncmp(gb_dai->name, dai->name, NAME_SIZE)) { - found = 1; - break; - } - } - - if (!found) { + mutex_lock(&gb->lock); + gb_dai = gbaudio_find_dai(gb, -1, dai->name); + if (!gb_dai) { dev_err(dai->dev, "%s: DAI not registered\n", dai->name); - return; + goto func_exit; } - atomic_dec(&gb->users); + atomic_dec(&gb_dai->users); /* deactivate rx/tx */ cportid = gb_dai->connection->intf_cport_id; @@ -97,7 +99,7 @@ static void gbcodec_shutdown(struct snd_pcm_substream *substream, break; default: dev_err(dai->dev, "Invalid stream type during shutdown\n"); - return; + goto func_exit; } if (ret) @@ -110,6 +112,8 @@ static void gbcodec_shutdown(struct snd_pcm_substream *substream, dev_dbg(dai->dev, "Unregister %s:%d DAI, ret:%d\n", dai->name, gb_dai->connection->hd_cport_id, ret); +func_exit: + mutex_unlock(&gb->lock); return; } @@ -118,26 +122,20 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hwparams, struct snd_soc_dai *dai) { - int ret, found; + int ret; uint8_t sig_bits, channels; uint32_t format, rate; uint16_t data_cport; struct gbaudio_dai *gb_dai; - struct gb_audio *audio = dev_get_drvdata(dai->dev); - struct gbaudio_codec_info *gb = audio->gbcodec; + struct gbaudio_codec_info *gb = dev_get_drvdata(dai->dev); /* find the dai */ - found = 0; - list_for_each_entry(gb_dai, &gb->dai_list, list) { - if (!strncmp(gb_dai->name, dai->name, NAME_SIZE)) { - found = 1; - break; - } - } - - if (!found) { + mutex_lock(&gb->lock); + gb_dai = gbaudio_find_dai(gb, -1, dai->name); + if (!gb_dai) { dev_err(dai->dev, "%s: DAI not registered\n", dai->name); - return -EINVAL; + ret = -EINVAL; + goto func_exit; } /* @@ -147,21 +145,24 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream, if (params_channels(hwparams) != 2) { dev_err(dai->dev, "Invalid channel count:%d\n", params_channels(hwparams)); - return -EINVAL; + ret = -EINVAL; + goto func_exit; } channels = params_channels(hwparams); if (params_rate(hwparams) != 48000) { dev_err(dai->dev, "Invalid sampling rate:%d\n", params_rate(hwparams)); - return -EINVAL; + ret = -EINVAL; + goto func_exit; } rate = GB_AUDIO_PCM_RATE_48000; if (params_format(hwparams) != SNDRV_PCM_FORMAT_S16_LE) { dev_err(dai->dev, "Invalid format:%d\n", params_format(hwparams)); - return -EINVAL; + ret = -EINVAL; + goto func_exit; } format = GB_AUDIO_PCM_FMT_S16_LE; @@ -176,7 +177,7 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream, rate, channels, sig_bits); if (ret) { dev_err(dai->dev, "%d: Error during set_pcm\n", ret); - return ret; + goto func_exit; } /* @@ -190,31 +191,26 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream, 6144000); if (ret) dev_err(dai->dev, "%d: Error during set_config\n", ret); - +func_exit: + mutex_unlock(&gb->lock); return ret; } static int gbcodec_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - int ret, found; + int ret; uint16_t data_cport; struct gbaudio_dai *gb_dai; - struct gb_audio *audio = dev_get_drvdata(dai->dev); - struct gbaudio_codec_info *gb = audio->gbcodec; + struct gbaudio_codec_info *gb = dev_get_drvdata(dai->dev); /* find the dai */ - found = 0; - list_for_each_entry(gb_dai, &gb->dai_list, list) { - if (!strncmp(gb_dai->name, dai->name, NAME_SIZE)) { - found = 1; - break; - } - } - - if (!found) { + mutex_lock(&gb->lock); + gb_dai = gbaudio_find_dai(gb, -1, dai->name); + if (!gb_dai) { dev_err(dai->dev, "%s: DAI not registered\n", dai->name); - return -EINVAL; + ret = -EINVAL; + goto func_exit; } /* deactivate rx/tx */ @@ -228,7 +224,7 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream, dev_err(dai->dev, "%d:Error during set_rx_data_size, cport:%d\n", ret, data_cport); - return ret; + goto func_exit; } ret = gb_audio_apbridgea_set_rx_data_size(gb_dai->connection, 0, 192); @@ -236,7 +232,7 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream, dev_err(dai->dev, "%d:Error during apbridgea_set_rx_data_size\n", ret); - return ret; + goto func_exit; } ret = gb_audio_gb_activate_rx(gb->mgmt_connection, data_cport); break; @@ -247,7 +243,7 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream, dev_err(dai->dev, "%d:Error during module set_tx_data_size, cport:%d\n", ret, data_cport); - return ret; + goto func_exit; } ret = gb_audio_apbridgea_set_tx_data_size(gb_dai->connection, 0, 192); @@ -255,43 +251,40 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream, dev_err(dai->dev, "%d:Error during apbridgea set_tx_data_size, cport\n", ret); - return ret; + goto func_exit; } ret = gb_audio_gb_activate_tx(gb->mgmt_connection, data_cport); break; default: dev_err(dai->dev, "Invalid stream type %d during prepare\n", substream->stream); - return -EINVAL; + ret = -EINVAL; + goto func_exit; } if (ret) dev_err(dai->dev, "%d: Error during activate stream\n", ret); +func_exit: + mutex_unlock(&gb->lock); return ret; } static int gbcodec_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - int ret, found; + int ret; int tx, rx, start, stop; struct gbaudio_dai *gb_dai; - struct gb_audio *audio = dev_get_drvdata(dai->dev); - struct gbaudio_codec_info *gb = audio->gbcodec; + struct gbaudio_codec_info *gb = dev_get_drvdata(dai->dev); /* find the dai */ - found = 0; - list_for_each_entry(gb_dai, &gb->dai_list, list) { - if (!strncmp(gb_dai->name, dai->name, NAME_SIZE)) { - found = 1; - break; - } - } - - if (!found) { + mutex_lock(&gb->lock); + gb_dai = gbaudio_find_dai(gb, -1, dai->name); + if (!gb_dai) { dev_err(dai->dev, "%s: DAI not registered\n", dai->name); - return -EINVAL; + ret = -EINVAL; + goto func_exit; } tx = rx = start = stop = 0; @@ -306,7 +299,8 @@ static int gbcodec_trigger(struct snd_pcm_substream *substream, int cmd, break; default: dev_err(dai->dev, "Invalid tigger cmd:%d\n", cmd); - return -EINVAL; + ret = -EINVAL; + goto func_exit; } switch (substream->stream) { @@ -319,7 +313,8 @@ static int gbcodec_trigger(struct snd_pcm_substream *substream, int cmd, default: dev_err(dai->dev, "Invalid stream type:%d\n", substream->stream); - return -EINVAL; + ret = -EINVAL; + goto func_exit; } if (start && tx) @@ -341,6 +336,8 @@ static int gbcodec_trigger(struct snd_pcm_substream *substream, int cmd, dev_err(dai->dev, "%d:Error during %s stream\n", ret, start ? "Start" : "Stop"); +func_exit: + mutex_unlock(&gb->lock); return ret; } @@ -383,8 +380,7 @@ static int gbcodec_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int value) { int ret = 0; - struct gb_audio *audio = snd_soc_codec_get_drvdata(codec); - struct gbaudio_codec_info *gbcodec = audio->gbcodec; + struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec); u8 *gbcodec_reg = gbcodec->reg; if (reg == SND_SOC_NOPM) @@ -404,8 +400,7 @@ static unsigned int gbcodec_read(struct snd_soc_codec *codec, { unsigned int val = 0; - struct gb_audio *audio = snd_soc_codec_get_drvdata(codec); - struct gbaudio_codec_info *gbcodec = audio->gbcodec; + struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec); u8 *gbcodec_reg = gbcodec->reg; if (reg == SND_SOC_NOPM) @@ -447,28 +442,15 @@ static struct snd_soc_dai_link gbaudio_dailink = { .be_id = 34, }; -static void gbaudio_remove_dailinks(struct gbaudio_codec_info *gbcodec) -{ - int i; - - for (i = 0; i < gbcodec->num_dai_links; i++) { - dev_dbg(gbcodec->dev, "Remove %s: DAI link\n", - gbcodec->dailink_name[i]); - devm_kfree(gbcodec->dev, gbcodec->dailink_name[i]); - gbcodec->dailink_name[i] = NULL; - } - gbcodec->num_dai_links = 0; -} - static int gbaudio_add_dailinks(struct gbaudio_codec_info *gbcodec) { int ret, i; char *dai_link_name; - struct snd_soc_dai_link *dai; + struct snd_soc_dai_link *dailink; struct device *dev = gbcodec->dev; - dai = &gbaudio_dailink; - dai->codec_name = gbcodec->name; + dailink = &gbaudio_dailink; + dailink->codec_name = gbcodec->name; /* FIXME * allocate memory for DAI links based on count. @@ -481,98 +463,20 @@ static int gbaudio_add_dailinks(struct gbaudio_codec_info *gbcodec) devm_kzalloc(dev, NAME_SIZE, GFP_KERNEL); snprintf(dai_link_name, NAME_SIZE, "GB %d.%d PRI_MI2S_RX", gbcodec->dev_id, i); - dai->name = dai_link_name; - dai->codec_dai_name = gbcodec->dais[i].name; + dailink->name = dai_link_name; + dailink->codec_dai_name = gbcodec->dais[i].name; } - ret = msm8994_add_dailink("msm8994-tomtom-mtp-snd-card", dai, 1); - if (ret) { + ret = msm8994_add_dailink("msm8994-tomtom-mtp-snd-card", dailink, 1); + if (ret) dev_err(dev, "%d:Error while adding DAI link\n", ret); - goto err_dai_link; - } return ret; - -err_dai_link: - gbcodec->num_dai_links = i; - gbaudio_remove_dailinks(gbcodec); - return ret; } /* * gb_snd management functions */ -static struct gbaudio_codec_info *gbaudio_find_codec(struct device *dev, - int dev_id) -{ - struct gbaudio_codec_info *tmp, *ret; - - mutex_lock(&gb_codec_list_lock); - list_for_each_entry_safe(ret, tmp, &gb_codec_list, list) { - dev_dbg(dev, "%d:device found\n", ret->dev_id); - if (ret->dev_id == dev_id) { - mutex_unlock(&gb_codec_list_lock); - return ret; - } - } - mutex_unlock(&gb_codec_list_lock); - return NULL; -} - -static struct gbaudio_codec_info *gbaudio_get_codec(struct device *dev, - int dev_id) -{ - struct gbaudio_codec_info *gbcodec; - struct gb_audio *audio = dev_get_drvdata(dev); - - gbcodec = gbaudio_find_codec(dev, dev_id); - if (gbcodec) - return gbcodec; - - gbcodec = devm_kzalloc(dev, sizeof(*gbcodec), GFP_KERNEL); - if (!gbcodec) - return NULL; - - mutex_init(&gbcodec->lock); - INIT_LIST_HEAD(&gbcodec->dai_list); - INIT_LIST_HEAD(&gbcodec->widget_list); - INIT_LIST_HEAD(&gbcodec->codec_ctl_list); - INIT_LIST_HEAD(&gbcodec->widget_ctl_list); - gbcodec->dev_id = dev_id; - audio->gbcodec = gbcodec; - gbcodec->dev = dev; - snprintf(gbcodec->name, NAME_SIZE, "%s.%s", dev->driver->name, - dev_name(dev)); - - mutex_lock(&gb_codec_list_lock); - list_add(&gbcodec->list, &gb_codec_list); - mutex_unlock(&gb_codec_list_lock); - dev_dbg(dev, "%d:%s Added to codec list\n", gbcodec->dev_id, - gbcodec->name); - - return gbcodec; -} - -static void gbaudio_free_codec(struct device *dev, - struct gbaudio_codec_info *gbcodec) -{ - struct gb_audio *audio = dev_get_drvdata(dev); - - mutex_lock(&gb_codec_list_lock); - if (!gbcodec->mgmt_connection && - list_empty(&gbcodec->dai_list)) { - list_del(&gbcodec->list); - mutex_unlock(&gb_codec_list_lock); - audio->gbcodec = NULL; - devm_kfree(dev, gbcodec); - } else { - mutex_unlock(&gb_codec_list_lock); - } -} - -/* - * This is the basic hook get things initialized and registered w/ gb - */ /* XXX * since BE DAI path is not yet properly closed from above layer, @@ -593,7 +497,7 @@ static void gb_audio_cleanup(struct gbaudio_codec_info *gb) * In case of BE dailink, need to deactivate APBridge * manually */ - if (gbaudio_dailink.no_pcm && atomic_read(&gb->users)) { + if (atomic_read(&gb_dai->users)) { connection = gb_dai->connection; /* PB active */ ret = gb_audio_apbridgea_stop_tx(connection, 0); @@ -613,38 +517,34 @@ static void gb_audio_cleanup(struct gbaudio_codec_info *gb) if (ret) dev_info(dev, "%d:Failed during unregister cport\n", ret); - atomic_dec(&gb->users); + atomic_dec(&gb_dai->users); } } } -static int gbaudio_codec_probe(struct gb_connection *connection) +static int gbaudio_register_codec(struct gbaudio_codec_info *gbcodec) { int ret, i; - struct gbaudio_codec_info *gbcodec; + struct device *dev = gbcodec->dev; + struct gb_connection *connection = gbcodec->mgmt_connection; + /* + * FIXME: malloc for topology happens via audio_gb driver + * should be done within codec driver itself + */ struct gb_audio_topology *topology; - struct gb_audio_manager_module_descriptor desc; - struct device *dev = &connection->bundle->dev; - int dev_id = connection->intf->interface_id; - - dev_dbg(dev, "Add device:%d:%s\n", dev_id, dev_name(dev)); - /* get gbcodec data */ - gbcodec = gbaudio_get_codec(dev, dev_id); - if (!gbcodec) - return -ENOMEM; - - gbcodec->mgmt_connection = connection; ret = gb_connection_enable(connection); - if (ret) - goto base_error; + if (ret) { + dev_err(dev, "%d: Error while enabling mgmt connection\n", ret); + return ret; + } + gbcodec->dev_id = connection->intf->interface_id; /* fetch topology data */ ret = gb_audio_gb_get_topology(connection, &topology); if (ret) { - dev_err(gbcodec->dev, - "%d:Error while fetching topology\n", ret); - goto err_connection_disable; + dev_err(dev, "%d:Error while fetching topology\n", ret); + goto tplg_fetch_err; } /* process topology data */ @@ -652,7 +552,7 @@ static int gbaudio_codec_probe(struct gb_connection *connection) if (ret) { dev_err(dev, "%d:Error while parsing topology data\n", ret); - goto topology_error; + goto tplg_parse_err; } gbcodec->topology = topology; @@ -673,100 +573,39 @@ static int gbaudio_codec_probe(struct gb_connection *connection) gbcodec->dais, 1); if (ret) { dev_err(dev, "%d:Failed to register codec\n", ret); - goto parse_error; + goto codec_reg_err; } /* update DAI links in response to this codec */ ret = gbaudio_add_dailinks(gbcodec); if (ret) { dev_err(dev, "%d: Failed to add DAI links\n", ret); - goto codec_reg_error; + goto add_dailink_err; } - /* set registered flag */ - mutex_lock(&gbcodec->lock); - gbcodec->codec_registered = 1; - - /* codec cleanup related */ - atomic_set(&gbcodec->users, 0); - - /* inform above layer for uevent */ - if (!gbcodec->set_uevent && - (gbcodec->dai_added == gbcodec->num_dais)) { - dev_dbg(dev, "Inform set_event:%d to above layer\n", 1); - /* prepare for the audio manager */ - strlcpy(desc.name, gbcodec->name, - GB_AUDIO_MANAGER_MODULE_NAME_LEN); /* todo */ - desc.slot = 1; /* todo */ - desc.vid = 2; /* todo */ - desc.pid = 3; /* todo */ - desc.cport = gbcodec->dev_id; - desc.devices = 0x2; /* todo */ - gbcodec->manager_id = gb_audio_manager_add(&desc); - gbcodec->set_uevent = 1; - } - mutex_unlock(&gbcodec->lock); - - return ret; + return 0; -codec_reg_error: +add_dailink_err: snd_soc_unregister_codec(dev); - dev->driver = NULL; -parse_error: +codec_reg_err: gbaudio_tplg_release(gbcodec); gbcodec->topology = NULL; -topology_error: +tplg_parse_err: kfree(topology); -err_connection_disable: - gb_connection_disable(connection); -base_error: - gbcodec->mgmt_connection = NULL; - gbaudio_free_codec(dev, gbcodec); +tplg_fetch_err: + gb_connection_disable(gbcodec->mgmt_connection); return ret; } -static void gbaudio_codec_remove(struct gb_connection *connection) +static void gbaudio_unregister_codec(struct gbaudio_codec_info *gbcodec) { - struct gbaudio_codec_info *gbcodec; - struct device *dev = &connection->bundle->dev; - int dev_id = connection->intf->interface_id; - - dev_dbg(dev, "Remove device:%d:%s\n", dev_id, dev_name(dev)); - - /* get gbcodec data */ - gbcodec = gbaudio_find_codec(dev, dev_id); - if (!gbcodec) - return; - - /* inform uevent to above layers */ - mutex_lock(&gbcodec->lock); - if (gbcodec->set_uevent) { - /* notify the audio manager */ - dev_dbg(dev, "Inform set_event:%d to above layer\n", 0); - gb_audio_manager_remove(gbcodec->manager_id); - gbcodec->set_uevent = 0; - } - mutex_unlock(&gbcodec->lock); - - if (atomic_read(&gbcodec->users)) { - dev_err(dev, "Cleanup Error: BE stream not yet closed\n"); - gb_audio_cleanup(gbcodec); - } - + gb_audio_cleanup(gbcodec); msm8994_remove_dailink("msm8994-tomtom-mtp-snd-card", &gbaudio_dailink, 1); - gbaudio_remove_dailinks(gbcodec); - - snd_soc_unregister_codec(dev); - dev->driver = NULL; + snd_soc_unregister_codec(gbcodec->dev); gbaudio_tplg_release(gbcodec); kfree(gbcodec->topology); - gb_connection_disable(connection); - gbcodec->mgmt_connection = NULL; - mutex_lock(&gbcodec->lock); - gbcodec->codec_registered = 0; - mutex_unlock(&gbcodec->lock); - gbaudio_free_codec(dev, gbcodec); + gb_connection_disable(gbcodec->mgmt_connection); } static int gbaudio_codec_request_handler(struct gb_operation *op) @@ -781,93 +620,6 @@ static int gbaudio_codec_request_handler(struct gb_operation *op) return 0; } -static int gbaudio_dai_probe(struct gb_connection *connection) -{ - struct gbaudio_dai *dai; - struct device *dev = &connection->bundle->dev; - int dev_id = connection->intf->interface_id; - struct gbaudio_codec_info *gbcodec; - struct gb_audio_manager_module_descriptor desc; - int ret; - - dev_dbg(dev, "Add DAI device:%d:%s\n", dev_id, dev_name(dev)); - - /* get gbcodec data */ - gbcodec = gbaudio_get_codec(dev, dev_id); - if (!gbcodec) - return -ENOMEM; - - ret = gb_connection_enable(connection); - if (ret) - goto err_free_codec; - - /* add/update dai_list*/ - dai = gbaudio_add_dai(gbcodec, connection->intf_cport_id, connection, - NULL); - if (!dai) { - ret = -ENOMEM; - goto err_connection_disable; - } - - /* update dai_added count */ - mutex_lock(&gbcodec->lock); - gbcodec->dai_added++; - - /* inform above layer for uevent */ - if (!gbcodec->set_uevent && gbcodec->codec_registered && - (gbcodec->dai_added == gbcodec->num_dais)) { - /* prepare for the audio manager */ - dev_dbg(dev, "Inform set_event:%d to above layer\n", 1); - strlcpy(desc.name, gbcodec->name, - GB_AUDIO_MANAGER_MODULE_NAME_LEN); /* todo */ - desc.slot = 1; /* todo */ - desc.vid = 2; /* todo */ - desc.pid = 3; /* todo */ - desc.cport = gbcodec->dev_id; - desc.devices = 0x2; /* todo */ - gbcodec->manager_id = gb_audio_manager_add(&desc); - gbcodec->set_uevent = 1; - } - mutex_unlock(&gbcodec->lock); - - return 0; - -err_connection_disable: - gb_connection_disable(connection); -err_free_codec: - gbaudio_free_codec(dev, gbcodec); - return ret; -} - -static void gbaudio_dai_remove(struct gb_connection *connection) -{ - struct device *dev = &connection->bundle->dev; - int dev_id = connection->intf->interface_id; - struct gbaudio_codec_info *gbcodec; - - dev_dbg(dev, "Remove DAI device:%d:%s\n", dev_id, dev_name(dev)); - - /* get gbcodec data */ - gbcodec = gbaudio_find_codec(dev, dev_id); - if (!gbcodec) - return; - - /* inform uevent to above layers */ - mutex_lock(&gbcodec->lock); - if (gbcodec->set_uevent) { - /* notify the audio manager */ - dev_dbg(dev, "Inform set_event:%d to above layer\n", 0); - gb_audio_manager_remove(gbcodec->manager_id); - gbcodec->set_uevent = 0; - } - /* update dai_added count */ - gbcodec->dai_added--; - mutex_unlock(&gbcodec->lock); - - gb_connection_disable(connection); - gbaudio_free_codec(dev, gbcodec); -} - static int gbaudio_dai_request_handler(struct gb_operation *op) { struct gb_connection *connection = op->connection; @@ -877,14 +629,14 @@ static int gbaudio_dai_request_handler(struct gb_operation *op) return 0; } -static int gb_audio_add_mgmt_connection(struct gb_audio *audio, +static int gb_audio_add_mgmt_connection(struct gbaudio_codec_info *gbcodec, struct greybus_descriptor_cport *cport_desc, struct gb_bundle *bundle) { struct gb_connection *connection; /* Management Cport */ - if (audio->mgmt_connection) { + if (gbcodec->mgmt_connection) { dev_err(&bundle->dev, "Can't have multiple Management connections\n"); return -ENODEV; @@ -895,74 +647,99 @@ static int gb_audio_add_mgmt_connection(struct gb_audio *audio, if (IS_ERR(connection)) return PTR_ERR(connection); - connection->private = audio; - audio->mgmt_connection = connection; + connection->private = gbcodec; + gbcodec->mgmt_connection = connection; return 0; } -static int gb_audio_add_data_connection(struct gb_audio *audio, +static int gb_audio_add_data_connection(struct gbaudio_codec_info *gbcodec, struct greybus_descriptor_cport *cport_desc, - struct gb_bundle *bundle, int index) + struct gb_bundle *bundle) { struct gb_connection *connection; + struct gbaudio_dai *dai; + + dai = devm_kzalloc(gbcodec->dev, sizeof(*dai), GFP_KERNEL); + if (!dai) { + dev_err(gbcodec->dev, "DAI Malloc failure\n"); + return -ENOMEM; + } connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id), gbaudio_dai_request_handler); - if (IS_ERR(connection)) + if (IS_ERR(connection)) { + devm_kfree(gbcodec->dev, dai); return PTR_ERR(connection); + } - connection->private = audio; - audio->data_connection[index] = connection; + connection->private = gbcodec; + atomic_set(&dai->users, 0); + dai->data_cport = connection->intf_cport_id; + dai->connection = connection; + list_add(&dai->list, &gbcodec->dai_list); return 0; } +/* + * This is the basic hook get things initialized and registered w/ gb + */ static int gb_audio_probe(struct gb_bundle *bundle, const struct greybus_bundle_id *id) { + struct device *dev = &bundle->dev; + struct gbaudio_codec_info *gbcodec; struct greybus_descriptor_cport *cport_desc; - struct gb_audio *audio; + struct gb_audio_manager_module_descriptor desc; + struct gbaudio_dai *dai, *_dai; int ret, i; - int count = bundle->num_cports - 1; /* There should be at least one Management and one Data cport */ if (bundle->num_cports < 2) return -ENODEV; + mutex_lock(&gb_codec_list_lock); /* * There can be only one Management connection and any number of data * connections. */ - audio = kzalloc(sizeof(*audio) + - count * sizeof(*audio->data_connection), GFP_KERNEL); - if (!audio) + gbcodec = devm_kzalloc(dev, sizeof(*gbcodec), GFP_KERNEL); + if (!gbcodec) { + mutex_unlock(&gb_codec_list_lock); return -ENOMEM; + } - audio->num_data_connections = count; - greybus_set_drvdata(bundle, audio); + gbcodec->num_data_connections = bundle->num_cports - 1; + mutex_init(&gbcodec->lock); + INIT_LIST_HEAD(&gbcodec->dai_list); + INIT_LIST_HEAD(&gbcodec->widget_list); + INIT_LIST_HEAD(&gbcodec->codec_ctl_list); + INIT_LIST_HEAD(&gbcodec->widget_ctl_list); + gbcodec->dev = dev; + snprintf(gbcodec->name, NAME_SIZE, "%s.%s", dev->driver->name, + dev_name(dev)); + greybus_set_drvdata(bundle, gbcodec); /* Create all connections */ - for (count = 0, i = 0; i < bundle->num_cports; i++) { + for (i = 0; i < bundle->num_cports; i++) { cport_desc = &bundle->cport_desc[i]; switch (cport_desc->protocol_id) { case GREYBUS_PROTOCOL_AUDIO_MGMT: - ret = gb_audio_add_mgmt_connection(audio, cport_desc, + ret = gb_audio_add_mgmt_connection(gbcodec, cport_desc, bundle); if (ret) goto destroy_connections; break; case GREYBUS_PROTOCOL_AUDIO_DATA: - ret = gb_audio_add_data_connection(audio, cport_desc, - bundle, count); + ret = gb_audio_add_data_connection(gbcodec, cport_desc, + bundle); if (ret) goto destroy_connections; - - count++; break; default: - dev_err(&bundle->dev, "Unsupported protocol: 0x%02x\n", + dev_err(dev, "Unsupported protocol: 0x%02x\n", cport_desc->protocol_id); ret = -ENODEV; goto destroy_connections; @@ -970,57 +747,88 @@ static int gb_audio_probe(struct gb_bundle *bundle, } /* There must be a management cport */ - if (!audio->mgmt_connection) { + if (!gbcodec->mgmt_connection) { ret = -EINVAL; - dev_err(&bundle->dev, "Missing management connection\n"); + dev_err(dev, "Missing management connection\n"); goto destroy_connections; } /* Initialize management connection */ - ret = gbaudio_codec_probe(audio->mgmt_connection); + ret = gbaudio_register_codec(gbcodec); if (ret) goto destroy_connections; /* Initialize data connections */ - for (i = 0; i < audio->num_data_connections; i++) { - ret = gbaudio_dai_probe(audio->data_connection[i]); + list_for_each_entry(dai, &gbcodec->dai_list, list) { + ret = gb_connection_enable(dai->connection); if (ret) goto remove_dai; } + /* inform above layer for uevent */ + dev_dbg(dev, "Inform set_event:%d to above layer\n", 1); + /* prepare for the audio manager */ + strlcpy(desc.name, gbcodec->name, GB_AUDIO_MANAGER_MODULE_NAME_LEN); + desc.slot = 1; /* todo */ + desc.vid = 2; /* todo */ + desc.pid = 3; /* todo */ + desc.cport = gbcodec->dev_id; + desc.devices = 0x2; /* todo */ + gbcodec->manager_id = gb_audio_manager_add(&desc); + + list_add(&gbcodec->list, &gb_codec_list); + dev_dbg(dev, "Add GB Audio device:%s\n", gbcodec->name); + mutex_unlock(&gb_codec_list_lock); + return 0; remove_dai: - while (i--) - gbaudio_dai_remove(audio->data_connection[i]); + list_for_each_entry_safe(dai, _dai, &gbcodec->dai_list, list) + gb_connection_disable(dai->connection); - gbaudio_codec_remove(audio->mgmt_connection); + gbaudio_unregister_codec(gbcodec); destroy_connections: - while (count--) - gb_connection_destroy(audio->data_connection[count]); + list_for_each_entry_safe(dai, _dai, &gbcodec->dai_list, list) { + gb_connection_destroy(dai->connection); + list_del(&dai->list); + devm_kfree(dev, dai); + } - if (audio->mgmt_connection) - gb_connection_destroy(audio->mgmt_connection); + if (gbcodec->mgmt_connection) + gb_connection_destroy(gbcodec->mgmt_connection); - kfree(audio); + devm_kfree(dev, gbcodec); + mutex_unlock(&gb_codec_list_lock); return ret; } static void gb_audio_disconnect(struct gb_bundle *bundle) { - struct gb_audio *audio = greybus_get_drvdata(bundle); - int i; + struct gbaudio_codec_info *gbcodec = greybus_get_drvdata(bundle); + struct gbaudio_dai *dai, *_dai; - for (i = audio->num_data_connections - 1; i >= 0; i--) { - gbaudio_dai_remove(audio->data_connection[i]); - gb_connection_destroy(audio->data_connection[i]); - } + mutex_lock(&gb_codec_list_lock); + list_del(&gbcodec->list); + /* inform uevent to above layers */ + gb_audio_manager_remove(gbcodec->manager_id); - gbaudio_codec_remove(audio->mgmt_connection); - gb_connection_destroy(audio->mgmt_connection); + mutex_lock(&gbcodec->lock); + list_for_each_entry_safe(dai, _dai, &gbcodec->dai_list, list) + gb_connection_disable(dai->connection); + gbaudio_unregister_codec(gbcodec); - kfree(audio); + list_for_each_entry_safe(dai, _dai, &gbcodec->dai_list, list) { + gb_connection_destroy(dai->connection); + list_del(&dai->list); + devm_kfree(gbcodec->dev, dai); + } + gb_connection_destroy(gbcodec->mgmt_connection); + gbcodec->mgmt_connection = NULL; + mutex_unlock(&gbcodec->lock); + + devm_kfree(&bundle->dev, gbcodec); + mutex_unlock(&gb_codec_list_lock); } static const struct greybus_bundle_id gb_audio_id_table[] = { diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index bba48a5..5611091 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -84,6 +84,8 @@ struct gbaudio_control { struct gbaudio_dai { __le16 data_cport; char name[NAME_SIZE]; + /* DAI users */ + atomic_t users; struct gb_connection *connection; struct list_head list; }; @@ -116,8 +118,9 @@ struct gbaudio_codec_info { char *dailink_name[MAX_DAIS]; int num_dai_links; - /* topology related */ struct gb_connection *mgmt_connection; + size_t num_data_connections; + /* topology related */ int num_dais; int num_kcontrols; int num_dapm_widgets; @@ -131,9 +134,6 @@ struct gbaudio_codec_info { struct snd_soc_dapm_route *routes; struct snd_soc_dai_driver *dais; - /* codec users */ - atomic_t users; - /* lists */ struct list_head dai_list; struct list_head widget_list; @@ -142,17 +142,8 @@ struct gbaudio_codec_info { struct mutex lock; }; -struct gb_audio { - struct gb_connection *mgmt_connection; - size_t num_data_connections; - struct gbaudio_codec_info *gbcodec; - struct gb_connection *data_connection[0]; -}; - -struct gbaudio_dai *gbaudio_add_dai(struct gbaudio_codec_info *gbcodec, - int data_cport, - struct gb_connection *connection, - const char *name); +struct gbaudio_dai *gbaudio_find_dai(struct gbaudio_codec_info *gbcodec, + int data_cport, const char *name); int gbaudio_tplg_parse_data(struct gbaudio_codec_info *gbcodec, struct gb_audio_topology *tplg_data); void gbaudio_tplg_release(struct gbaudio_codec_info *gbcodec); diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index 90d2148..5fab393 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -92,8 +92,7 @@ static int gbcodec_mixer_ctl_info(struct snd_kcontrol *kcontrol, struct gbaudio_ctl_pvt *data; struct gb_audio_ctl_elem_info *info; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct gb_audio *audio = snd_soc_codec_get_drvdata(codec); - struct gbaudio_codec_info *gbcodec = audio->gbcodec; + struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec); data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; info = (struct gb_audio_ctl_elem_info *)data->info; @@ -139,8 +138,7 @@ static int gbcodec_mixer_ctl_get(struct snd_kcontrol *kcontrol, struct gbaudio_ctl_pvt *data; struct gb_audio_ctl_elem_value gbvalue; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct gb_audio *audio = snd_soc_codec_get_drvdata(codec); - struct gbaudio_codec_info *gb = audio->gbcodec; + struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; info = (struct gb_audio_ctl_elem_info *)data->info; @@ -187,8 +185,7 @@ static int gbcodec_mixer_ctl_put(struct snd_kcontrol *kcontrol, struct gbaudio_ctl_pvt *data; struct gb_audio_ctl_elem_value gbvalue; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct gb_audio *audio = snd_soc_codec_get_drvdata(codec); - struct gbaudio_codec_info *gb = audio->gbcodec; + struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; info = (struct gb_audio_ctl_elem_info *)data->info; @@ -282,8 +279,7 @@ static int gbcodec_mixer_dapm_ctl_get(struct snd_kcontrol *kcontrol, struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); struct snd_soc_dapm_widget *widget = wlist->widgets[0]; struct snd_soc_codec *codec = widget->codec; - struct gb_audio *audio = snd_soc_codec_get_drvdata(codec); - struct gbaudio_codec_info *gb = audio->gbcodec; + struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; info = (struct gb_audio_ctl_elem_info *)data->info; @@ -317,8 +313,7 @@ static int gbcodec_mixer_dapm_ctl_put(struct snd_kcontrol *kcontrol, struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); struct snd_soc_dapm_widget *widget = wlist->widgets[0]; struct snd_soc_codec *codec = widget->codec; - struct gb_audio *audio = snd_soc_codec_get_drvdata(codec); - struct gbaudio_codec_info *gb = audio->gbcodec; + struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; info = (struct gb_audio_ctl_elem_info *)data->info; @@ -524,8 +519,7 @@ static int gbaudio_widget_event(struct snd_soc_dapm_widget *w, int wid; int ret; struct snd_soc_codec *codec = w->codec; - struct gb_audio *audio = snd_soc_codec_get_drvdata(codec); - struct gbaudio_codec_info *gbcodec = audio->gbcodec; + struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec); dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event); @@ -819,9 +813,9 @@ static int gbaudio_tplg_process_dais(struct gbaudio_codec_info *gbcodec, int i, ret; struct snd_soc_dai_driver *gb_dais; struct gb_audio_dai *curr; - struct gbaudio_dai *dai, *_dai; size_t size; char dai_name[NAME_SIZE]; + struct gbaudio_dai *dai; size = sizeof(struct snd_soc_dai_driver) * gbcodec->num_dais; gb_dais = devm_kzalloc(gbcodec->dev, size, GFP_KERNEL); @@ -839,10 +833,10 @@ static int gbaudio_tplg_process_dais(struct gbaudio_codec_info *gbcodec, /* append dev_id to dai_name */ snprintf(dai_name, NAME_SIZE, "%s.%d", curr->name, gbcodec->dev_id); - dai = gbaudio_add_dai(gbcodec, curr->data_cport, NULL, - dai_name); + dai = gbaudio_find_dai(gbcodec, curr->data_cport, NULL); if (!dai) goto error; + strlcpy(dai->name, dai_name, NAME_SIZE); dev_dbg(gbcodec->dev, "%s:DAI added\n", dai->name); gb_dais[i].name = dai->name; curr++; @@ -852,10 +846,6 @@ static int gbaudio_tplg_process_dais(struct gbaudio_codec_info *gbcodec, return 0; error: - list_for_each_entry_safe(dai, _dai, &gbcodec->dai_list, list) { - list_del(&dai->list); - devm_kfree(gbcodec->dev, dai); - } devm_kfree(gbcodec->dev, gb_dais); return ret; } @@ -948,68 +938,6 @@ static int gbaudio_tplg_process_header(struct gbaudio_codec_info *gbcodec, return 0; } -static struct gbaudio_dai *gbaudio_allocate_dai(struct gbaudio_codec_info *gb, - int data_cport, - struct gb_connection *connection, - const char *name) -{ - struct gbaudio_dai *dai; - - mutex_lock(&gb->lock); - dai = devm_kzalloc(gb->dev, sizeof(*dai), GFP_KERNEL); - if (!dai) { - dev_err(gb->dev, "%s:DAI Malloc failure\n", name); - mutex_unlock(&gb->lock); - return NULL; - } - - dai->data_cport = data_cport; - dai->connection = connection; - - /* update name */ - if (name) - strlcpy(dai->name, name, NAME_SIZE); - list_add(&dai->list, &gb->dai_list); - dev_dbg(gb->dev, "%d:%s: DAI added\n", data_cport, dai->name); - mutex_unlock(&gb->lock); - - return dai; -} - -struct gbaudio_dai *gbaudio_add_dai(struct gbaudio_codec_info *gbcodec, - int data_cport, - struct gb_connection *connection, - const char *name) -{ - struct gbaudio_dai *dai, *_dai; - - /* FIXME need to take care for multiple DAIs */ - mutex_lock(&gbcodec->lock); - if (list_empty(&gbcodec->dai_list)) { - mutex_unlock(&gbcodec->lock); - return gbaudio_allocate_dai(gbcodec, data_cport, connection, - name); - } - - list_for_each_entry_safe(dai, _dai, &gbcodec->dai_list, list) { - if (dai->data_cport == data_cport) { - if (connection) - dai->connection = connection; - - if (name) - strlcpy(dai->name, name, NAME_SIZE); - dev_dbg(gbcodec->dev, "%d:%s: DAI updated\n", - data_cport, dai->name); - mutex_unlock(&gbcodec->lock); - return dai; - } - } - - dev_err(gbcodec->dev, "%s:DAI not found\n", name); - mutex_unlock(&gbcodec->lock); - return NULL; -} - int gbaudio_tplg_parse_data(struct gbaudio_codec_info *gbcodec, struct gb_audio_topology *tplg_data) { @@ -1074,7 +1002,6 @@ int gbaudio_tplg_parse_data(struct gbaudio_codec_info *gbcodec, void gbaudio_tplg_release(struct gbaudio_codec_info *gbcodec) { - struct gbaudio_dai *dai, *_dai; struct gbaudio_control *control, *_control; struct gbaudio_widget *widget, *_widget; @@ -1109,12 +1036,4 @@ void gbaudio_tplg_release(struct gbaudio_codec_info *gbcodec) /* release routes */ if (gbcodec->routes) devm_kfree(gbcodec->dev, gbcodec->routes); - - /* release DAIs */ - mutex_lock(&gbcodec->lock); - list_for_each_entry_safe(dai, _dai, &gbcodec->dai_list, list) { - list_del(&dai->list); - devm_kfree(gbcodec->dev, dai); - } - mutex_unlock(&gbcodec->lock); } -- cgit v0.10.2 From 3994e0b139c709047cdeb44b6c28cfb39f89f3f2 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal Date: Thu, 28 Jan 2016 21:15:40 +0530 Subject: greybus: audio: use variable 'is_connected' to maintain module state there is race condition between _disconnect() request & stop_trigger() in case of abrupt module removal. And sometimes this can lead to deadlock while acquiring codec_info->lock. To avoid such situation, atomic variable is used to maintain codec connected state. During dai operations (trigger, shutdown, etc.), 'is_connected' variable is validated to avoid unnecessary lock acquire in case module already removed. Signed-off-by: Vaibhav Agarwal Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index ad28c10..c05ab4f 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -44,6 +44,9 @@ static int gbcodec_startup(struct snd_pcm_substream *substream, struct gbaudio_dai *gb_dai; struct gbaudio_codec_info *gb = dev_get_drvdata(dai->dev); + if (!atomic_read(&gb->is_connected)) + return -ENODEV; + /* find the dai */ mutex_lock(&gb->lock); gb_dai = gbaudio_find_dai(gb, -1, dai->name); @@ -77,6 +80,9 @@ static void gbcodec_shutdown(struct snd_pcm_substream *substream, struct gbaudio_dai *gb_dai; struct gbaudio_codec_info *gb = dev_get_drvdata(dai->dev); + if (!atomic_read(&gb->is_connected)) + return; + /* find the dai */ mutex_lock(&gb->lock); gb_dai = gbaudio_find_dai(gb, -1, dai->name); @@ -129,6 +135,9 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream, struct gbaudio_dai *gb_dai; struct gbaudio_codec_info *gb = dev_get_drvdata(dai->dev); + if (!atomic_read(&gb->is_connected)) + return -ENODEV; + /* find the dai */ mutex_lock(&gb->lock); gb_dai = gbaudio_find_dai(gb, -1, dai->name); @@ -204,6 +213,9 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream, struct gbaudio_dai *gb_dai; struct gbaudio_codec_info *gb = dev_get_drvdata(dai->dev); + if (!atomic_read(&gb->is_connected)) + return -ENODEV; + /* find the dai */ mutex_lock(&gb->lock); gb_dai = gbaudio_find_dai(gb, -1, dai->name); @@ -278,6 +290,9 @@ static int gbcodec_trigger(struct snd_pcm_substream *substream, int cmd, struct gbaudio_dai *gb_dai; struct gbaudio_codec_info *gb = dev_get_drvdata(dai->dev); + if (!atomic_read(&gb->is_connected)) + return -ENODEV; + /* find the dai */ mutex_lock(&gb->lock); gb_dai = gbaudio_find_dai(gb, -1, dai->name); @@ -776,6 +791,7 @@ static int gb_audio_probe(struct gb_bundle *bundle, desc.devices = 0x2; /* todo */ gbcodec->manager_id = gb_audio_manager_add(&desc); + atomic_set(&gbcodec->is_connected, 1); list_add(&gbcodec->list, &gb_codec_list); dev_dbg(dev, "Add GB Audio device:%s\n", gbcodec->name); mutex_unlock(&gb_codec_list_lock); @@ -809,6 +825,7 @@ static void gb_audio_disconnect(struct gb_bundle *bundle) struct gbaudio_dai *dai, *_dai; mutex_lock(&gb_codec_list_lock); + atomic_set(&gbcodec->is_connected, 0); list_del(&gbcodec->list); /* inform uevent to above layers */ gb_audio_manager_remove(gbcodec->manager_id); diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index 5611091..4c19bd8 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -108,6 +108,15 @@ struct gbaudio_codec_info { int manager_id; char name[NAME_SIZE]; + /* + * there can be a rece condition between gb_audio_disconnect() + * and dai->trigger from above ASoC layer. + * To avoid any deadlock over codec_info->lock, atomic variable + * is used. + */ + atomic_t is_connected; + struct mutex lock; + /* soc related data */ struct snd_soc_codec *codec; struct device *dev; @@ -139,7 +148,6 @@ struct gbaudio_codec_info { struct list_head widget_list; struct list_head codec_ctl_list; struct list_head widget_ctl_list; - struct mutex lock; }; struct gbaudio_dai *gbaudio_find_dai(struct gbaudio_codec_info *gbcodec, diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index 5fab393..1651c14 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -140,6 +140,9 @@ static int gbcodec_mixer_ctl_get(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + if (!atomic_read(&gb->is_connected)) + return -ENODEV; + data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; info = (struct gb_audio_ctl_elem_info *)data->info; @@ -187,6 +190,9 @@ static int gbcodec_mixer_ctl_put(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + if (!atomic_read(&gb->is_connected)) + return -ENODEV; + data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; info = (struct gb_audio_ctl_elem_info *)data->info; @@ -281,6 +287,9 @@ static int gbcodec_mixer_dapm_ctl_get(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = widget->codec; struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + if (!atomic_read(&gb->is_connected)) + return -ENODEV; + data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; info = (struct gb_audio_ctl_elem_info *)data->info; @@ -315,6 +324,9 @@ static int gbcodec_mixer_dapm_ctl_put(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = widget->codec; struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + if (!atomic_read(&gb->is_connected)) + return -ENODEV; + data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; info = (struct gb_audio_ctl_elem_info *)data->info; -- cgit v0.10.2 From ec413566e819ad19be929ab38d2b5911cbf096c2 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 3 Feb 2016 12:53:40 +0100 Subject: greybus: audio_manager: add missing header There's a definition missing in audio_manager causing the kernel build to fail: CC [M] ./greybus/audio_manager.o ./greybus/audio_manager.c:22:8: warning: type defaults to 'int' in declaration of 'DEFINE_IDA' [-Wimplicit-int] error, forbidden warning: audio_manager.c:22 ./kernel/scripts/Makefile.build:308: recipe for target './greybus/audio_manager.o' failed Including linux/idr.h fixes the issue. Signed-off-by: Bartosz Golaszewski Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio_manager.c b/drivers/staging/greybus/audio_manager.c index 05af441..bc5be49 100644 --- a/drivers/staging/greybus/audio_manager.c +++ b/drivers/staging/greybus/audio_manager.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "audio_manager.h" #include "audio_manager_private.h" -- cgit v0.10.2 From d1a9c0560a4ffc05c31a042dff380ddf1ea721b0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 2 Feb 2016 21:31:19 -0800 Subject: greybus: fix sparse warning in manifest.c The cport id field is a le16, so treat it as such when comparing it to something else. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 5ca36c9..4e3c4ca 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -256,7 +256,7 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) */ list_for_each_entry(tmp, &list, links) { desc_cport = tmp->data; - if (cport_id == desc_cport->id) { + if (cport_id == le16_to_cpu(desc_cport->id)) { dev_err(&bundle->dev, "duplicate CPort %u found\n", cport_id); -- cgit v0.10.2 From 6084653541ac5fb619c4338e6fa6a9d5d4a51713 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Fri, 5 Feb 2016 01:10:56 +0530 Subject: greybus: arche-apb-ctrl: Remove extra delay in APB reset With synchronization between SVC <=> AP over wake/detect line to bring APB's out of reset, we do not need any extra delays now. So remove it. Testing Done: Tested for 10 iterations on EVT1 Signed-off-by: Vaibhav Hiremath Reviewed-by: Michael Scott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index f2bad8d..4e5ce37 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -54,7 +54,6 @@ struct arche_apb_ctrl_drvdata { static inline void deassert_reset(unsigned int gpio) { gpio_set_value(gpio, 1); - msleep(500); } static inline void assert_reset(unsigned int gpio) -- cgit v0.10.2 From f121d79d8acb0852f42b42b111967a3ef265362b Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Fri, 5 Feb 2016 09:35:32 +0100 Subject: greybus: camera: Reset link speed on failed config Improve the management of unipro power mode changes in response to a configure_stream operation. When sending a "test only" request to camera module, do not change power mode to HS-G2 as no frame will be actually transmitted. When receiveing an "adjusted" configuration response, reset power mode to PWM-G1. Signed-off-by: Jacopo Mondi Reviewed-by: Gjorgji Rosikopulos Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index c735908..90eef23 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -150,7 +150,7 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, * to the camera module, to assure unipro network speed is set * before CSI interfaces gets configured */ - if (nstreams) { + if (nstreams && !(*flags & GB_CAMERA_CONFIGURE_STREAMS_TEST_ONLY)) { ret = gb_svc_intf_set_power_mode(svc, intf->interface_id, GB_SVC_UNIPRO_HS_SERIES_A, GB_SVC_UNIPRO_FAST_MODE, 2, 2, @@ -168,7 +168,7 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, GB_SVC_PWRM_TXTERMINATION, 0); if (ret < 0) goto done; - } else { + } else if (nstreams == 0) { ret = gb_svc_intf_set_power_mode(svc, intf->interface_id, GB_SVC_UNIPRO_HS_SERIES_A, GB_SVC_UNIPRO_SLOW_AUTO_MODE, @@ -228,8 +228,6 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, goto set_unipro_slow_mode; } - *flags = resp->flags; - for (i = 0; i < nstreams; ++i) { struct gb_camera_stream_config_response *cfg = &resp->config[i]; @@ -248,10 +246,16 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, } } + if (nstreams && resp->flags & GB_CAMERA_CONFIGURE_STREAMS_ADJUSTED) { + *flags = resp->flags; + *num_streams = resp->num_streams; + goto set_unipro_slow_mode; + } + memset(&csi_cfg, 0, sizeof(csi_cfg)); /* Configure the CSI transmitter. Hardcode the parameters for now. */ - if (nstreams && !(resp->flags & GB_CAMERA_CONFIGURE_STREAMS_ADJUSTED)) { + if (nstreams) { csi_cfg.csi_id = 1; csi_cfg.clock_mode = 0; csi_cfg.num_lanes = 4; @@ -259,7 +263,7 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, ret = gb_hd_output(gcam->connection->hd, &csi_cfg, sizeof(csi_cfg), GB_APB_REQUEST_CSI_TX_CONTROL, false); - } else if (nstreams == 0) { + } else { csi_cfg.csi_id = 1; ret = gb_hd_output(gcam->connection->hd, &csi_cfg, sizeof(csi_cfg), @@ -270,6 +274,7 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, gcam_err(gcam, "failed to %s the CSI transmitter\n", nstreams ? "start" : "stop"); + *flags = resp->flags; *num_streams = resp->num_streams; ret = 0; -- cgit v0.10.2 From db81b76970a2e9f3ffa1ca66e7761f9f4b84efc6 Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Fri, 5 Feb 2016 09:35:33 +0100 Subject: greybus: camera: Add missing return value Add missing return value assignement when changing unipro power mode to PWM-G1. Signed-off-by: Jacopo Mondi Reviewed-by: Gjorgji Rosikopulos Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 90eef23..3f31a2f 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -296,7 +296,7 @@ set_unipro_slow_mode: goto done; } - gb_svc_intf_set_power_mode(svc, svc->ap_intf_id, + ret = gb_svc_intf_set_power_mode(svc, svc->ap_intf_id, GB_SVC_UNIPRO_HS_SERIES_A, GB_SVC_UNIPRO_SLOW_AUTO_MODE, 1, 2, @@ -307,7 +307,6 @@ set_unipro_slow_mode: gcam_err(gcam, "can't take AP link to PWM-G1 auto: %d\n", ret); - done: kfree(req); kfree(resp); -- cgit v0.10.2 From 9d15134d067ecb52bf02136234fbd1d09e1706d8 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Thu, 4 Feb 2016 14:00:36 +0000 Subject: greybus: power_supply: rework get descriptors Rework the get property descriptors function to fix a memory handling error for the response structure. This could corrupt the stack and throw nonalignment PC or SP error: Internal error: SP or PC abort: 8a000000 1 PREEMPT SMP Modules linked in: gb_power_supply(O) gb_arche(O) gb_camera(O) gb_es2(O) gb_vibrator(O) gb_raw(O) g] CPU: 3 PID: 51 Comm: kworker/u16:2 Tainted: G W O 3.10.73-g8a6af60-00118-g599a5c1 #1 Workqueue: greybus1:svc gb_svc_connection_destroy [greybus] task: ffffffc0ba249580 ti: ffffffc0ba294000 task.ti: ffffffc0ba294000 PC is at gb_power_supply_connection_init+0x81/0x1dc [gb_power_supply] LR is at gb_power_supply_connection_init+0x81/0x1dc [gb_power_supply] pc : [] lr : [] pstate: 80000145 sp : ffffffc0ba297a00 x29: 32002e002a001100 x28: ffffffc042cb2c80 To fix this, allocate firstly the operation and handle request and response using operation payload. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c index 2dc193a..37bea9c 100644 --- a/drivers/staging/greybus/power_supply.c +++ b/drivers/staging/greybus/power_supply.c @@ -249,39 +249,53 @@ static int gb_power_supply_description_get(struct gb_power_supply *gbpsy) static int gb_power_supply_prop_descriptors_get(struct gb_power_supply *gbpsy) { struct gb_connection *connection = get_conn_from_psy(gbpsy); - struct gb_power_supply_get_property_descriptors_request req; - struct gb_power_supply_get_property_descriptors_response resp; + struct gb_power_supply_get_property_descriptors_request *req; + struct gb_power_supply_get_property_descriptors_response *resp; + struct gb_operation *op; + u8 props_count = gbpsy->properties_count; int ret; int i; - if (gbpsy->properties_count == 0) + if (props_count == 0) return 0; - req.psy_id = gbpsy->id; + op = gb_operation_create(connection, + GB_POWER_SUPPLY_TYPE_GET_PROP_DESCRIPTORS, + sizeof(req), sizeof(*resp) + props_count * + sizeof(struct gb_power_supply_props_desc), + GFP_KERNEL); + if (!op) + return -ENOMEM; - ret = gb_operation_sync(connection, - GB_POWER_SUPPLY_TYPE_GET_PROP_DESCRIPTORS, - &req, sizeof(req), &resp, - sizeof(resp) + gbpsy->properties_count * - sizeof(struct gb_power_supply_props_desc)); + req = op->request->payload; + req->psy_id = gbpsy->id; + + ret = gb_operation_request_send_sync(op); if (ret < 0) - return ret; + goto out_put_operation; + + resp = op->response->payload; gbpsy->props = kcalloc(gbpsy->properties_count, sizeof(*gbpsy->props), GFP_KERNEL); - if (!gbpsy->props) - return -ENOMEM; + if (!gbpsy->props) { + ret = -ENOMEM; + goto out_put_operation; + } + + gbpsy->props_raw = kcalloc(gbpsy->properties_count, + sizeof(*gbpsy->props_raw), GFP_KERNEL); + if (!gbpsy->props_raw) { + ret = -ENOMEM; + goto out_put_operation; + } - gbpsy->props_raw = kzalloc(gbpsy->properties_count * - sizeof(*gbpsy->props_raw), GFP_KERNEL); - if (!gbpsy->props_raw) - return -ENOMEM; /* Store available properties */ for (i = 0; i < gbpsy->properties_count; i++) { - gbpsy->props[i].prop = resp.props[i].property; - gbpsy->props_raw[i] = resp.props[i].property; - if (resp.props[i].is_writeable) + gbpsy->props[i].prop = resp->props[i].property; + gbpsy->props_raw[i] = resp->props[i].property; + if (resp->props[i].is_writeable) gbpsy->props[i].is_writeable = true; } @@ -291,7 +305,10 @@ static int gb_power_supply_prop_descriptors_get(struct gb_power_supply *gbpsy) */ _gb_power_supply_append_props(gbpsy); - return 0; +out_put_operation: + gb_operation_put(op); + + return ret; } static int __gb_power_supply_property_update(struct gb_power_supply *gbpsy, -- cgit v0.10.2 From 9d4bb6c9183f1283158bbb00ebf65ec4cf18ee33 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Fri, 5 Feb 2016 13:50:37 +0000 Subject: greybus: uart: fix double free of tty port When inserting and removing a module with a UART protocol defined a double free of the tty_port would happen and that would generate a lot of kernel oops in different places related to memory corruption. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 1ba8476..46cce8c 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -701,7 +701,6 @@ static void gb_uart_connection_exit(struct gb_connection *connection) /* FIXME - free transmit / receive buffers */ - tty_port_put(&gb_tty->port); tty_port_destroy(&gb_tty->port); kfree(gb_tty->buffer); kfree(gb_tty); -- cgit v0.10.2 From 0273038df61349868d368dd9254eb629425a3378 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Tue, 2 Feb 2016 14:23:16 +0000 Subject: greybus: spi: add device_type field to device config Add device_type field in device config operation to get the type of device and try to expose less the kernel internal over greybus. This include the spidev, spi-nor will fetch the correct nor id over jede and a modalias that will have the previous behavior (name will set the driver to be loaded). As at it, fix a trivial error path and return immediately. Tested: using gbsim and confirming that a spidev and mtd device were created. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 89db932..cd64ac8 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -737,6 +737,10 @@ struct gb_spi_device_config_response { __le16 mode; __u8 bits_per_word; __le32 max_speed_hz; + __u8 device_type; +#define GB_SPI_SPI_DEV 0x00 +#define GB_SPI_SPI_NOR 0x01 +#define GB_SPI_SPI_MODALIAS 0x02 __u8 name[32]; } __packed; diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index 1f8d6a1..18bf8df 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -305,4 +305,12 @@ static inline bool led_sysfs_is_disabled(struct led_classdev *led_cdev) #define PSY_HAVE_PUT #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) +#define SPI_DEV_MODALIAS "spidev" +#define SPI_NOR_MODALIAS "spi-nor" +#else +#define SPI_DEV_MODALIAS "spidev" +#define SPI_NOR_MODALIAS "m25p80" +#endif + #endif /* __GREYBUS_KERNEL_VER_H */ diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index ad4a1d6..c00492c 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -285,6 +285,7 @@ static int gb_spi_setup_device(struct gb_spi *spi, u8 cs) struct spi_board_info spi_board = { {0} }; struct spi_device *spidev; int ret; + u8 dev_type; request.chip_select = cs; @@ -294,7 +295,20 @@ static int gb_spi_setup_device(struct gb_spi *spi, u8 cs) if (ret < 0) return ret; - memcpy(spi_board.modalias, response.name, sizeof(spi_board.modalias)); + dev_type = response.device_type; + + if (dev_type == GB_SPI_SPI_DEV) + strlcpy(spi_board.modalias, SPI_DEV_MODALIAS, + sizeof(spi_board.modalias)); + else if (dev_type == GB_SPI_SPI_NOR) + strlcpy(spi_board.modalias, SPI_NOR_MODALIAS, + sizeof(spi_board.modalias)); + else if (dev_type == GB_SPI_SPI_MODALIAS) + memcpy(spi_board.modalias, response.name, + sizeof(spi_board.modalias)); + else + return -EINVAL; + spi_board.mode = le16_to_cpu(response.mode); spi_board.bus_num = master->bus_num; spi_board.chip_select = cs; @@ -302,7 +316,7 @@ static int gb_spi_setup_device(struct gb_spi *spi, u8 cs) spidev = spi_new_device(master, &spi_board); if (!spidev) - ret = -EINVAL; + return -EINVAL; return 0; } -- cgit v0.10.2 From f6d6f5bd29f76721d7ac5c64426a1f45203c622a Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Tue, 9 Feb 2016 22:09:16 +0530 Subject: greybus: Revert "arche-apb-ctrl: Remove extra delay in APB reset" We are seeing failures on DB3.1 board, and Axel root-caused it to this commit, so revert it as of now. This reverts commit 942627227684c187b727ba5fb581bc2d886b6708. Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index 4e5ce37..f2bad8d 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -54,6 +54,7 @@ struct arche_apb_ctrl_drvdata { static inline void deassert_reset(unsigned int gpio) { gpio_set_value(gpio, 1); + msleep(500); } static inline void assert_reset(unsigned int gpio) -- cgit v0.10.2 From d5a265648aa830383bc2c3e750ffe1bea0cd4309 Mon Sep 17 00:00:00 2001 From: Michael Scott Date: Mon, 8 Feb 2016 17:08:46 -0800 Subject: greybus: interface: clear upper 16-bits of version_id and product_id Current userspace looks through the sysfs interface entries for matching vendor_id and product_id any time an interface is opened by module developers. The upper 16-bits of ES3 vendor_id and product_id contain a reverse mask of the lower 16-bits. This additional information is never used and should be removed so that every consumer of these sysfs entries doesn't have to perform the same bit clearing logic. Signed-off-by: Michael Scott Reviewed-by: Alex Elder Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 9c05d81..6c815db 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -23,12 +23,33 @@ static DEVICE_ATTR_RO(field) gb_interface_attr(ddbl1_manufacturer_id, "0x%08x"); gb_interface_attr(ddbl1_product_id, "0x%08x"); gb_interface_attr(interface_id, "%u"); -gb_interface_attr(vendor_id, "0x%08x"); -gb_interface_attr(product_id, "0x%08x"); gb_interface_attr(vendor_string, "%s"); gb_interface_attr(product_string, "%s"); gb_interface_attr(serial_number, "0x%016llx"); +static ssize_t vendor_id_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct gb_interface *intf = to_gb_interface(dev); + + /* clear the upper 16-bits to keep userspace "simple" */ + return scnprintf(buf, PAGE_SIZE, "0x%04x\n", + (0x0000FFFF & intf->vendor_id)); +} +static DEVICE_ATTR_RO(vendor_id); + +static ssize_t product_id_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct gb_interface *intf = to_gb_interface(dev); + + /* clear the upper 16-bits to keep userspace "simple" */ + return scnprintf(buf, PAGE_SIZE, "0x%04x\n", + (0x0000FFFF & intf->product_id)); +} +static DEVICE_ATTR_RO(product_id); + static ssize_t version_show(struct device *dev, struct device_attribute *attr, char *buf) { -- cgit v0.10.2 From a0b5542df26b6d2fccb611c05ea1cb266456b60c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 11 Feb 2016 13:52:46 +0100 Subject: greybus: manifest: add interface-device prefix to messages Use dev_err and friends so that we can tell which interface (and module) a manifest-parsing error messages was for. Testing Done: Tested on DB3.5 with the generic bridge firmware on APB2. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 4e3c4ca..74e3be9 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -7,8 +7,6 @@ * Released under the GPLv2 only. */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include "greybus.h" static const char *get_descriptor_type_string(u8 type) @@ -107,14 +105,15 @@ static int identify_descriptor(struct gb_interface *intf, size_t expected_size; if (size < sizeof(*desc_header)) { - pr_err("manifest too small (%zu < %zu)\n", + dev_err(&intf->dev, "manifest too small (%zu < %zu)\n", size, sizeof(*desc_header)); return -EINVAL; /* Must at least have header */ } desc_size = le16_to_cpu(desc_header->size); if (desc_size > size) { - pr_err("descriptor too big (%zu > %zu)\n", desc_size, size); + dev_err(&intf->dev, "descriptor too big (%zu > %zu)\n", + desc_size, size); return -EINVAL; } @@ -140,22 +139,23 @@ static int identify_descriptor(struct gb_interface *intf, break; case GREYBUS_TYPE_INVALID: default: - pr_err("invalid descriptor type (%u)\n", desc_header->type); + dev_err(&intf->dev, "invalid descriptor type (%u)\n", + desc_header->type); return -EINVAL; } if (desc_size < expected_size) { - pr_err("%s descriptor too small (%zu < %zu)\n", - get_descriptor_type_string(desc_header->type), - desc_size, expected_size); + dev_err(&intf->dev, "%s descriptor too small (%zu < %zu)\n", + get_descriptor_type_string(desc_header->type), + desc_size, expected_size); return -EINVAL; } /* Descriptor bigger than what we expect */ if (desc_size > expected_size) { - pr_warn("%s descriptor size mismatch (want %zu got %zu)\n", - get_descriptor_type_string(desc_header->type), - expected_size, desc_size); + dev_warn(&intf->dev, "%s descriptor size mismatch (want %zu got %zu)\n", + get_descriptor_type_string(desc_header->type), + expected_size, desc_size); } descriptor = kzalloc(sizeof(*descriptor), GFP_KERNEL); @@ -454,7 +454,8 @@ bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size) /* we have to have at _least_ the manifest header */ if (size < sizeof(*header)) { - pr_err("short manifest (%zu < %zu)\n", size, sizeof(*header)); + dev_err(&intf->dev, "short manifest (%zu < %zu)\n", + size, sizeof(*header)); return false; } @@ -463,16 +464,16 @@ bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size) header = &manifest->header; manifest_size = le16_to_cpu(header->size); if (manifest_size != size) { - pr_err("manifest size mismatch (%zu != %u)\n", - size, manifest_size); + dev_err(&intf->dev, "manifest size mismatch (%zu != %u)\n", + size, manifest_size); return false; } /* Validate major/minor number */ if (header->version_major > GREYBUS_VERSION_MAJOR) { - pr_err("manifest version too new (%u.%u > %u.%u)\n", - header->version_major, header->version_minor, - GREYBUS_VERSION_MAJOR, GREYBUS_VERSION_MINOR); + dev_err(&intf->dev, "manifest version too new (%u.%u > %u.%u)\n", + header->version_major, header->version_minor, + GREYBUS_VERSION_MAJOR, GREYBUS_VERSION_MINOR); return false; } @@ -498,8 +499,8 @@ bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size) interface_desc = descriptor; } if (found != 1) { - pr_err("manifest must have 1 interface descriptor (%u found)\n", - found); + dev_err(&intf->dev, "manifest must have 1 interface descriptor (%u found)\n", + found); result = false; goto out; } @@ -512,7 +513,7 @@ bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size) * don't know what newer format manifests might leave. */ if (result && !list_empty(&intf->manifest_descs)) - pr_info("excess descriptors in interface manifest\n"); + dev_info(&intf->dev, "excess descriptors in interface manifest\n"); out: release_manifest_descriptors(intf); -- cgit v0.10.2 From b427572ebff3abba436a9ae45db73c78fa3ddcf8 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 11 Feb 2016 13:52:47 +0100 Subject: greybus: core: add device prefix to error messages Use dev_err and dev_warn where appropriate and remove now unused pr_fmt defines. Testing Done: Tested on DB3.5 with the generic bridge firmware on APB2. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/debugfs.c b/drivers/staging/greybus/debugfs.c index 725565d..a9d4d3d 100644 --- a/drivers/staging/greybus/debugfs.c +++ b/drivers/staging/greybus/debugfs.c @@ -7,8 +7,6 @@ * Released under the GPLv2 only. */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include #include "greybus.h" diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index d1aab29..147a92d 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -7,8 +7,6 @@ * Released under the GPLv2 only. */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include #include @@ -55,7 +53,7 @@ struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, * so that we don't have to every time we make them. */ if ((!driver->message_send) || (!driver->message_cancel)) { - pr_err("Must implement all gb_hd_driver callbacks!\n"); + dev_err(parent, "mandatory hd-callbacks missing\n"); return ERR_PTR(-EINVAL); } diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index d6b3d1f..bd79f81 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -327,7 +327,7 @@ gb_operation_message_alloc(struct gb_host_device *hd, u8 type, size_t message_size = payload_size + sizeof(*header); if (message_size > hd->buffer_size_max) { - pr_warn("requested message size too big (%zu > %zu)\n", + dev_warn(&hd->dev, "requested message size too big (%zu > %zu)\n", message_size, hd->buffer_size_max); return NULL; } -- cgit v0.10.2 From 6d6fb2549f23d5d7d3494574b49e35df8e737645 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 11 Feb 2016 13:52:48 +0100 Subject: greybus: i2c: add bundle-device prefix to error messages Replace all pr_err with dev_err so we can tell what device (and driver) a message was for. Testing Done: Compiled Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c index 5a5af36..ec74e87 100644 --- a/drivers/staging/greybus/i2c.c +++ b/drivers/staging/greybus/i2c.c @@ -52,6 +52,7 @@ static int gb_i2c_functionality_operation(struct gb_i2c_device *gb_i2c_dev) static int gb_i2c_timeout_operation(struct gb_i2c_device *gb_i2c_dev, u16 msec) { + struct device *dev = &gb_i2c_dev->connection->bundle->dev; struct gb_i2c_timeout_request request; int ret; @@ -59,7 +60,7 @@ static int gb_i2c_timeout_operation(struct gb_i2c_device *gb_i2c_dev, u16 msec) ret = gb_operation_sync(gb_i2c_dev->connection, GB_I2C_TYPE_TIMEOUT, &request, sizeof(request), NULL, 0); if (ret) - pr_err("timeout operation failed (%d)\n", ret); + dev_err(dev, "timeout operation failed (%d)\n", ret); else gb_i2c_dev->timeout_msec = msec; @@ -69,6 +70,7 @@ static int gb_i2c_timeout_operation(struct gb_i2c_device *gb_i2c_dev, u16 msec) static int gb_i2c_retries_operation(struct gb_i2c_device *gb_i2c_dev, u8 retries) { + struct device *dev = &gb_i2c_dev->connection->bundle->dev; struct gb_i2c_retries_request request; int ret; @@ -76,7 +78,7 @@ static int gb_i2c_retries_operation(struct gb_i2c_device *gb_i2c_dev, ret = gb_operation_sync(gb_i2c_dev->connection, GB_I2C_TYPE_RETRIES, &request, sizeof(request), NULL, 0); if (ret) - pr_err("retries operation failed (%d)\n", ret); + dev_err(dev, "retries operation failed (%d)\n", ret); else gb_i2c_dev->retries = retries; @@ -201,6 +203,7 @@ static int gb_i2c_transfer_operation(struct gb_i2c_device *gb_i2c_dev, struct i2c_msg *msgs, u32 msg_count) { struct gb_connection *connection = gb_i2c_dev->connection; + struct device *dev = &connection->bundle->dev; struct gb_operation *operation; int ret; @@ -216,7 +219,7 @@ static int gb_i2c_transfer_operation(struct gb_i2c_device *gb_i2c_dev, gb_i2c_decode_response(msgs, msg_count, response); ret = msg_count; } else if (!gb_i2c_expected_transfer_error(ret)) { - pr_err("transfer operation failed (%d)\n", ret); + dev_err(dev, "transfer operation failed (%d)\n", ret); } gb_operation_put(operation); -- cgit v0.10.2 From 8923c5b59ffd18b8a31b18dd02332fdfe801f7c9 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 11 Feb 2016 13:52:49 +0100 Subject: greybus: loopback: add missing pr_fmt Add missing pr_fmt so we can at least tell what module the sole remaining pr_err was from. Testing Done: Tested on DB3.5 with the generic bridge firmware on APB2. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index c35d227..3f32dee 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -6,6 +6,9 @@ * * Released under the GPLv2 only. */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include -- cgit v0.10.2 From 5ef545fb8c22ab605f764ea467859572797dbc09 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 11 Feb 2016 13:52:50 +0100 Subject: greybus: spi: add bundle-device prefix to error messages Replace all pr_err with dev_err so we can tell what device (and driver) a message was for. Testing Done: Compiled Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index c00492c..7689af0 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -218,7 +218,8 @@ static int gb_spi_transfer_one_message(struct spi_master *master, if (response) gb_spi_decode_response(msg, response); } else { - pr_err("transfer operation failed (%d)\n", ret); + dev_err(&connection->bundle->dev, + "transfer operation failed: %d\n", ret); } gb_operation_put(operation); -- cgit v0.10.2 From 8d46ec49819599d33ee5cffd43b19bf21f9472b8 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 10 Feb 2016 12:31:03 +0100 Subject: greybus: bundle: remove private data field Remove the private data field from the bundle structure as it is no longer needed. Bundle drivers can use the driver data field in the bundle device. Update the only current user to use the connection private data until it has been converted to a bundle driver. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.h b/drivers/staging/greybus/bundle.h index 48fb3fd..18b125e8 100644 --- a/drivers/staging/greybus/bundle.h +++ b/drivers/staging/greybus/bundle.h @@ -29,7 +29,6 @@ struct gb_bundle { u8 *state; struct list_head links; /* interface->bundles */ - void *private; }; #define to_gb_bundle(d) container_of(d, struct gb_bundle, dev) diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 3f32dee..66b3fca 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -1121,7 +1121,7 @@ static int gb_loopback_connection_init(struct gb_connection *connection) gb->file = debugfs_create_file(name, S_IFREG | S_IRUGO, gb_dev.root, gb, &gb_loopback_debugfs_latency_ops); gb->connection = connection; - connection->bundle->private = gb; + connection->private = gb; gb->id = ida_simple_get(&loopback_ida, 0, 0, GFP_KERNEL); if (gb->id < 0) { @@ -1177,7 +1177,6 @@ out_dev: ida_simple_remove(&loopback_ida, gb->id); out_ida: debugfs_remove(gb->file); - connection->bundle->private = NULL; out_kzalloc: kfree(gb); @@ -1186,13 +1185,12 @@ out_kzalloc: static void gb_loopback_connection_exit(struct gb_connection *connection) { - struct gb_loopback *gb = connection->bundle->private; + struct gb_loopback *gb = connection->private; unsigned long flags; if (!IS_ERR_OR_NULL(gb->task)) kthread_stop(gb->task); - connection->bundle->private = NULL; kfifo_free(&gb->kfifo_lat); kfifo_free(&gb->kfifo_ts); gb_connection_latency_tag_disable(connection); -- cgit v0.10.2 From 397d34152423d2ddbff3e48495ef988cbb07776b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 10 Feb 2016 11:08:29 +0100 Subject: greybus: raw: fix memory leak on disconnect Make sure the class device is freed as well as deregistered on disconnect. Also deregister the class device before character device as the former depends on the latter. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/raw.c b/drivers/staging/greybus/raw.c index fa5025d..a6e7959 100644 --- a/drivers/staging/greybus/raw.c +++ b/drivers/staging/greybus/raw.c @@ -203,9 +203,9 @@ static void gb_raw_connection_exit(struct gb_connection *connection) struct raw_data *temp; // FIXME - handle removing a connection when the char device node is open. + device_destroy(raw_class, raw->dev); cdev_del(&raw->cdev); ida_simple_remove(&minors, MINOR(raw->dev)); - device_del(raw->device); mutex_lock(&raw->list_lock); list_for_each_entry_safe(raw_data, temp, &raw->list, entry) { list_del(&raw_data->entry); -- cgit v0.10.2 From a821adb47d28e22f96716b0ab8c4a8d5f7d3dadb Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sat, 13 Feb 2016 02:04:02 +0530 Subject: greybus: arche-platform: make apb_state common to both platform drivers Make 'enum apb_state' common to both platform drivers, so that both drivers can make use of same state and user will have unified control configuration across devices (SVC, APB1 and APB2) Testing Done: Tested on EVT1.2 and DB3.5 platform. Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index f2bad8d..42267fa 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -21,11 +21,6 @@ #include #include "arche_platform.h" -enum apb_state { - APB_STATE_OFF, - APB_STATE_ACTIVE, - APB_STATE_STANDBY, -}; struct arche_apb_ctrl_drvdata { /* Control GPIO signals to and from AP <=> AP Bridges */ @@ -36,7 +31,7 @@ struct arche_apb_ctrl_drvdata { int wake_out_gpio; int pwrdn_gpio; - enum apb_state state; + enum arche_platform_state state; struct regulator *vcore; struct regulator *vio; @@ -232,7 +227,7 @@ static void apb_ctrl_cleanup(struct arche_apb_ctrl_drvdata *apb) /* As part of exit, put APB back in reset state */ assert_reset(apb->resetn_gpio); - apb->state = APB_STATE_OFF; + apb->state = ARCHE_PLATFORM_STATE_OFF; /* TODO: May have to send an event to SVC about this exit */ } @@ -262,7 +257,7 @@ int arche_apb_ctrl_probe(struct platform_device *pdev) /* deassert reset to APB : Active-low signal */ deassert_reset(apb->resetn_gpio); - apb->state = APB_STATE_ACTIVE; + apb->state = ARCHE_PLATFORM_STATE_ACTIVE; platform_set_drvdata(pdev, apb); diff --git a/drivers/staging/greybus/arche_platform.h b/drivers/staging/greybus/arche_platform.h index 22a968a..33c4bb8 100644 --- a/drivers/staging/greybus/arche_platform.h +++ b/drivers/staging/greybus/arche_platform.h @@ -10,6 +10,12 @@ #ifndef __ARCHE_PLATFORM_H #define __ARCHE_PLATFORM_H +enum arche_platform_state { + ARCHE_PLATFORM_STATE_OFF, + ARCHE_PLATFORM_STATE_ACTIVE, + ARCHE_PLATFORM_STATE_STANDBY, +}; + int arche_apb_ctrl_probe(struct platform_device *pdev); int arche_apb_ctrl_remove(struct platform_device *pdev); extern const struct dev_pm_ops arche_apb_ctrl_pm_ops; -- cgit v0.10.2 From 758ca99de9961036675048e1487713e801b184db Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sat, 13 Feb 2016 02:04:03 +0530 Subject: greybus: arche-platform: Introduce coldboot_seq fn This is preparation for support for different operational states (defined by arche_platform_state) in the driver, to enable user/developer to dynamically configure the state. arche_platform_coldboot_seq() fn will be responsible for rebooting SVC device. Testing Done: Tested on EVT1.2 and DB3.5 platform Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 65c8f71..f367430 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -104,6 +104,32 @@ static void unexport_gpios(struct arche_platform_drvdata *arche_pdata) gpio_unexport(arche_pdata->svc_sysboot_gpio); } +static int arche_platform_coldboot_seq(struct arche_platform_drvdata *arche_pdata) +{ + int ret; + + dev_info(arche_pdata->dev, "Booting from cold boot state\n"); + + svc_reset_onoff(arche_pdata->svc_reset_gpio, + arche_pdata->is_reset_act_hi); + + gpio_set_value(arche_pdata->svc_sysboot_gpio, 0); + usleep_range(100, 200); + + ret = clk_prepare_enable(arche_pdata->svc_ref_clk); + if (ret) { + dev_err(arche_pdata->dev, "failed to enable svc_ref_clk: %d\n", + ret); + return ret; + } + + /* bring SVC out of reset */ + svc_reset_onoff(arche_pdata->svc_reset_gpio, + !arche_pdata->is_reset_act_hi); + + return 0; +} + static void arche_platform_cleanup(struct arche_platform_drvdata *arche_pdata) { clk_disable_unprepare(arche_pdata->svc_ref_clk); @@ -185,11 +211,6 @@ static int arche_platform_probe(struct platform_device *pdev) dev_err(dev, "failed to get svc_ref_clk: %d\n", ret); return ret; } - ret = clk_prepare_enable(arche_pdata->svc_ref_clk); - if (ret) { - dev_err(dev, "failed to enable svc_ref_clk: %d\n", ret); - return ret; - } platform_set_drvdata(pdev, arche_pdata); @@ -200,34 +221,32 @@ static int arche_platform_probe(struct platform_device *pdev) if (arche_pdata->wake_detect_gpio < 0) { dev_err(dev, "failed to get wake detect gpio\n"); ret = arche_pdata->wake_detect_gpio; - goto exit; + return ret; } ret = devm_gpio_request(dev, arche_pdata->wake_detect_gpio, "wake detect"); if (ret) { dev_err(dev, "Failed requesting wake_detect gpio %d\n", arche_pdata->wake_detect_gpio); - goto exit; + return ret; } /* deassert wake detect */ gpio_direction_output(arche_pdata->wake_detect_gpio, 0); - /* bring SVC out of reset */ - svc_reset_onoff(arche_pdata->svc_reset_gpio, - !arche_pdata->is_reset_act_hi); - arche_pdata->dev = &pdev->dev; INIT_DELAYED_WORK(&arche_pdata->delayed_work, svc_delayed_work); schedule_delayed_work(&arche_pdata->delayed_work, msecs_to_jiffies(2000)); + ret = arche_platform_coldboot_seq(arche_pdata); + if (ret) { + dev_err(dev, "Failed to cold boot svc %d\n", ret); + return ret; + } + export_gpios(arche_pdata); dev_info(dev, "Device registered successfully\n"); return 0; - -exit: - arche_platform_cleanup(arche_pdata); - return ret; } static int arche_remove_child(struct device *dev, void *unused) -- cgit v0.10.2 From 49e6e04bb44e4f3bf2c6d3c2c096257da2cb54ff Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sat, 13 Feb 2016 01:15:11 +0530 Subject: greybus: arche-platform: Cancel delayed_work in driver remove fn This is a bug fix, where as part of cleanup, delayed work was not canceled in driver remove function. So fix it. Testing Done: Tested on EVT1.2 and DB3.5 platform. Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index f367430..3b7974d 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -262,6 +262,7 @@ static int arche_platform_remove(struct platform_device *pdev) { struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev); + cancel_delayed_work_sync(&arche_pdata->delayed_work); device_for_each_child(&pdev->dev, NULL, arche_remove_child); arche_platform_cleanup(arche_pdata); platform_set_drvdata(pdev, NULL); -- cgit v0.10.2 From 5993e2bfd848538b1f3e8e3de6412f76e600c69f Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sat, 13 Feb 2016 02:04:04 +0530 Subject: greybus: arche-platform: Rename cleanup fn to poweroff_seq In sync with operational states, rename arche_platform_cleanup() fn to arche_platform_poweroff_seq() fn. Testing Done: Tested on EVT1.2 and DB3.5 platform. Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 3b7974d..48ab1eb 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -130,7 +130,7 @@ static int arche_platform_coldboot_seq(struct arche_platform_drvdata *arche_pdat return 0; } -static void arche_platform_cleanup(struct arche_platform_drvdata *arche_pdata) +static void arche_platform_poweroff_seq(struct arche_platform_drvdata *arche_pdata) { clk_disable_unprepare(arche_pdata->svc_ref_clk); /* As part of exit, put APB back in reset state */ @@ -264,7 +264,7 @@ static int arche_platform_remove(struct platform_device *pdev) cancel_delayed_work_sync(&arche_pdata->delayed_work); device_for_each_child(&pdev->dev, NULL, arche_remove_child); - arche_platform_cleanup(arche_pdata); + arche_platform_poweroff_seq(arche_pdata); platform_set_drvdata(pdev, NULL); unexport_gpios(arche_pdata); -- cgit v0.10.2 From e74d04a5810233a95cb7a556165817d378b89e44 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sat, 13 Feb 2016 02:04:05 +0530 Subject: greybus: arche-platform: Add state variable to driver data This is preparation for operational state support. So in order to provide operational state transitions, driver needs to maintain state. So add 'enum arche_platform_state' variable to 'struct arche_platform_drvdata' Testing Done: Tested on EVT1.2 and DB3.5 platform. Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 48ab1eb..1336fc4 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -26,6 +26,8 @@ struct arche_platform_drvdata { int svc_sysboot_gpio; int wake_detect_gpio; /* bi-dir,maps to WAKE_MOD & WAKE_FRAME signals */ + enum arche_platform_state state; + unsigned int svc_refclk_req; struct clk *svc_ref_clk; @@ -127,6 +129,8 @@ static int arche_platform_coldboot_seq(struct arche_platform_drvdata *arche_pdat svc_reset_onoff(arche_pdata->svc_reset_gpio, !arche_pdata->is_reset_act_hi); + arche_pdata->state = ARCHE_PLATFORM_STATE_ACTIVE; + return 0; } @@ -136,6 +140,8 @@ static void arche_platform_poweroff_seq(struct arche_platform_drvdata *arche_pda /* As part of exit, put APB back in reset state */ svc_reset_onoff(arche_pdata->svc_reset_gpio, arche_pdata->is_reset_act_hi); + + arche_pdata->state = ARCHE_PLATFORM_STATE_OFF; } static int arche_platform_probe(struct platform_device *pdev) @@ -168,6 +174,7 @@ static int arche_platform_probe(struct platform_device *pdev) dev_err(dev, "failed to set svc-reset gpio dir:%d\n", ret); return ret; } + arche_pdata->state = ARCHE_PLATFORM_STATE_OFF; arche_pdata->svc_sysboot_gpio = of_get_named_gpio(np, "svc,sysboot-gpio", 0); -- cgit v0.10.2 From b4c95fca6a9dd8ac2242a451e53781d5313b8c1d Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sat, 13 Feb 2016 02:04:06 +0530 Subject: greybus: arche-platform: Pull wake/detect low in poweroff When SVC goes down, make sure that wake/detect is also pulled low. Note that this is not the criteria for SVC poweroff, but it is required to have right state on wake/detect line before powering off. And on next boot, the boot-sequence code would take care of handshaking with SVC. Tested-on: Tested on EVT1.2 and DB3.5 platform. Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 1336fc4..b2f3919 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -136,6 +136,10 @@ static int arche_platform_coldboot_seq(struct arche_platform_drvdata *arche_pdat static void arche_platform_poweroff_seq(struct arche_platform_drvdata *arche_pdata) { + /* Send disconnect/detach event to SVC */ + gpio_set_value(arche_pdata->wake_detect_gpio, 0); + usleep_range(100, 200); + clk_disable_unprepare(arche_pdata->svc_ref_clk); /* As part of exit, put APB back in reset state */ svc_reset_onoff(arche_pdata->svc_reset_gpio, -- cgit v0.10.2 From 2923c58eb5acb019e6781dc05662b896e14339f6 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sat, 13 Feb 2016 02:04:07 +0530 Subject: greybus: arche_platform: Add sysfs to allow user to change state This patch introduces sysfs interface for the user space to enable operational state change of the driver. Currently, driver supports, 'off', 'active' and 'standby' Note that, driver doesn't do anything for standby state as of today. To see the current state # cat /sys/devices/arche_platform.*/state And to change the state # echo [off/active/standby] > /sys/devices/arche_platform.*/state Testing Done: Tested on EVT1.2 and DB3.5 platform. Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index b2f3919..1dd2b08 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -148,6 +148,55 @@ static void arche_platform_poweroff_seq(struct arche_platform_drvdata *arche_pda arche_pdata->state = ARCHE_PLATFORM_STATE_OFF; } +static ssize_t state_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct platform_device *pdev = to_platform_device(dev); + struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev); + int ret = 0; + + if (sysfs_streq(buf, "off")) { + if (arche_pdata->state == ARCHE_PLATFORM_STATE_OFF) + return count; + + arche_platform_poweroff_seq(arche_pdata); + } else if (sysfs_streq(buf, "active")) { + if (arche_pdata->state == ARCHE_PLATFORM_STATE_ACTIVE) + return count; + + ret = arche_platform_coldboot_seq(arche_pdata); + } else if (sysfs_streq(buf, "standby")) { + if (arche_pdata->state == ARCHE_PLATFORM_STATE_STANDBY) + return count; + + dev_warn(arche_pdata->dev, "standby state not supported\n"); + } else { + dev_err(arche_pdata->dev, "unknown state\n"); + ret = -EINVAL; + } + + return ret ? ret : count; +} + +static ssize_t state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct arche_platform_drvdata *arche_pdata = dev_get_drvdata(dev); + + switch (arche_pdata->state) { + case ARCHE_PLATFORM_STATE_OFF: + return sprintf(buf, "off\n"); + case ARCHE_PLATFORM_STATE_ACTIVE: + return sprintf(buf, "active\n"); + case ARCHE_PLATFORM_STATE_STANDBY: + return sprintf(buf, "standby\n"); + default: + return sprintf(buf, "unknown state\n"); + } +} + +static DEVICE_ATTR_RW(state); + static int arche_platform_probe(struct platform_device *pdev) { struct arche_platform_drvdata *arche_pdata; @@ -248,6 +297,12 @@ static int arche_platform_probe(struct platform_device *pdev) INIT_DELAYED_WORK(&arche_pdata->delayed_work, svc_delayed_work); schedule_delayed_work(&arche_pdata->delayed_work, msecs_to_jiffies(2000)); + ret = device_create_file(dev, &dev_attr_state); + if (ret) { + dev_err(dev, "failed to create state file in sysfs\n"); + return ret; + } + ret = arche_platform_coldboot_seq(arche_pdata); if (ret) { dev_err(dev, "Failed to cold boot svc %d\n", ret); @@ -273,6 +328,7 @@ static int arche_platform_remove(struct platform_device *pdev) { struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev); + device_remove_file(&pdev->dev, &dev_attr_state); cancel_delayed_work_sync(&arche_pdata->delayed_work); device_for_each_child(&pdev->dev, NULL, arche_remove_child); arche_platform_poweroff_seq(arche_pdata); -- cgit v0.10.2 From 7691fed20e7301bd89b04d38f88262c83279817a Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sat, 13 Feb 2016 02:04:08 +0530 Subject: greybus: arche-platform: Introduce FW_FLASHING state Introduce FW_FLASHING state to arche-platform driver, to enable user space to flash/upgrade SVC firmware. Command to enter into flashing state: # echo fw_flashing > /sys/devices/arche_platform.*/state Testing Done: Tested on EVT1.2 and DB3.5 platform. Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 1dd2b08..3e6432f 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -134,6 +134,23 @@ static int arche_platform_coldboot_seq(struct arche_platform_drvdata *arche_pdat return 0; } +static void arche_platform_fw_flashing_seq(struct arche_platform_drvdata *arche_pdata) +{ + dev_info(arche_pdata->dev, "Switching to FW flashing state\n"); + + svc_reset_onoff(arche_pdata->svc_reset_gpio, + arche_pdata->is_reset_act_hi); + + gpio_set_value(arche_pdata->svc_sysboot_gpio, 1); + + usleep_range(100, 200); + svc_reset_onoff(arche_pdata->svc_reset_gpio, + !arche_pdata->is_reset_act_hi); + + arche_pdata->state = ARCHE_PLATFORM_STATE_FW_FLASHING; + +} + static void arche_platform_poweroff_seq(struct arche_platform_drvdata *arche_pdata) { /* Send disconnect/detach event to SVC */ @@ -170,6 +187,14 @@ static ssize_t state_store(struct device *dev, return count; dev_warn(arche_pdata->dev, "standby state not supported\n"); + } else if (sysfs_streq(buf, "fw_flashing")) { + if (arche_pdata->state == ARCHE_PLATFORM_STATE_FW_FLASHING) + return count; + + /* First we want to make sure we power off everything + * and then enter FW flashing state */ + arche_platform_poweroff_seq(arche_pdata); + arche_platform_fw_flashing_seq(arche_pdata); } else { dev_err(arche_pdata->dev, "unknown state\n"); ret = -EINVAL; @@ -190,6 +215,8 @@ static ssize_t state_show(struct device *dev, return sprintf(buf, "active\n"); case ARCHE_PLATFORM_STATE_STANDBY: return sprintf(buf, "standby\n"); + case ARCHE_PLATFORM_STATE_FW_FLASHING: + return sprintf(buf, "fw_flashing\n"); default: return sprintf(buf, "unknown state\n"); } diff --git a/drivers/staging/greybus/arche_platform.h b/drivers/staging/greybus/arche_platform.h index 33c4bb8..27deeb7 100644 --- a/drivers/staging/greybus/arche_platform.h +++ b/drivers/staging/greybus/arche_platform.h @@ -14,6 +14,7 @@ enum arche_platform_state { ARCHE_PLATFORM_STATE_OFF, ARCHE_PLATFORM_STATE_ACTIVE, ARCHE_PLATFORM_STATE_STANDBY, + ARCHE_PLATFORM_STATE_FW_FLASHING, }; int arche_apb_ctrl_probe(struct platform_device *pdev); -- cgit v0.10.2 From 6ceed512e68ea8a82cc320630e24656f03c50424 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sat, 13 Feb 2016 02:04:09 +0530 Subject: greybus: arche-apb-ctrl: Re-arrange init sequence In order to allow APB2 disable by default on boot/init, and also provide interface to user to enable it later on, re-arrange the init_seq fn. The idea here is, the apb_ctrl_init_seq() fn will be renamed to apb_ctrl_coldboot_seq(), and should not try to claim any resources. All the resource claim should happen in apb_ctrl_get_devtree_data() fn. And also uses devm_gpio_request_one() fn wherever possible. Testing Done: Tested on EVT1.2 and DB3.5 platform. Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index 42267fa..7720153 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -78,29 +78,7 @@ static int apb_ctrl_init_seq(struct platform_device *pdev, int ret; /* Hold APB in reset state */ - ret = devm_gpio_request(dev, apb->resetn_gpio, "apb-reset"); - if (ret) { - dev_err(dev, "Failed requesting reset gpio %d\n", - apb->resetn_gpio); - return ret; - } - ret = gpio_direction_output(apb->resetn_gpio, 0); - if (ret) { - dev_err(dev, "failed to set reset gpio dir:%d\n", ret); - return ret; - } - - ret = devm_gpio_request(dev, apb->pwroff_gpio, "pwroff_n"); - if (ret) { - dev_err(dev, "Failed requesting pwroff_n gpio %d\n", - apb->pwroff_gpio); - return ret; - } - ret = gpio_direction_input(apb->pwroff_gpio); - if (ret) { - dev_err(dev, "failed to set pwroff gpio dir:%d\n", ret); - return ret; - } + assert_reset(apb->resetn_gpio); /* Enable power to APB */ if (!IS_ERR(apb->vcore)) { @@ -115,45 +93,24 @@ static int apb_ctrl_init_seq(struct platform_device *pdev, ret = regulator_enable(apb->vio); if (ret) { dev_err(dev, "failed to enable IO regulator\n"); - goto out_vcore_disable; + return ret; } } - ret = devm_gpio_request_one(dev, apb->boot_ret_gpio, - GPIOF_OUT_INIT_LOW, "boot retention"); - if (ret) { - dev_err(dev, "Failed requesting bootret gpio %d\n", - apb->boot_ret_gpio); - goto out_vio_disable; - } gpio_set_value(apb->boot_ret_gpio, 0); /* On DB3 clock was not mandatory */ - if (gpio_is_valid(apb->clk_en_gpio)) { - ret = devm_gpio_request(dev, apb->clk_en_gpio, "apb_clk_en"); - if (ret) { - dev_warn(dev, "Failed requesting APB clock en gpio %d\n", - apb->clk_en_gpio); - } else { - ret = gpio_direction_output(apb->clk_en_gpio, 1); - if (ret) - dev_warn(dev, "failed to set APB clock en gpio dir:%d\n", - ret); - } - } + if (gpio_is_valid(apb->clk_en_gpio)) + gpio_set_value(apb->clk_en_gpio, 1); usleep_range(100, 200); - return 0; + /* deassert reset to APB : Active-low signal */ + deassert_reset(apb->resetn_gpio); -out_vio_disable: - if (!IS_ERR(apb->vio)) - regulator_disable(apb->vio); -out_vcore_disable: - if (!IS_ERR(apb->vcore)) - regulator_disable(apb->vcore); + apb->state = ARCHE_PLATFORM_STATE_ACTIVE; - return ret; + return 0; } static int apb_ctrl_get_devtree_data(struct platform_device *pdev, @@ -161,18 +118,33 @@ static int apb_ctrl_get_devtree_data(struct platform_device *pdev, { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; + int ret; apb->resetn_gpio = of_get_named_gpio(np, "reset-gpios", 0); if (apb->resetn_gpio < 0) { dev_err(dev, "failed to get reset gpio\n"); return apb->resetn_gpio; } + ret = devm_gpio_request_one(dev, apb->resetn_gpio, + GPIOF_OUT_INIT_LOW, "apb-reset"); + if (ret) { + dev_err(dev, "Failed requesting reset gpio %d\n", + apb->resetn_gpio); + return ret; + } apb->boot_ret_gpio = of_get_named_gpio(np, "boot-ret-gpios", 0); if (apb->boot_ret_gpio < 0) { dev_err(dev, "failed to get boot retention gpio\n"); return apb->boot_ret_gpio; } + ret = devm_gpio_request_one(dev, apb->boot_ret_gpio, + GPIOF_OUT_INIT_LOW, "boot retention"); + if (ret) { + dev_err(dev, "Failed requesting bootret gpio %d\n", + apb->boot_ret_gpio); + return ret; + } /* It's not mandatory to support power management interface */ apb->pwroff_gpio = of_get_named_gpio(np, "pwr-off-gpios", 0); @@ -180,11 +152,27 @@ static int apb_ctrl_get_devtree_data(struct platform_device *pdev, dev_err(dev, "failed to get power off gpio\n"); return apb->pwroff_gpio; } + ret = devm_gpio_request_one(dev, apb->pwroff_gpio, + GPIOF_IN, "pwroff_n"); + if (ret) { + dev_err(dev, "Failed requesting pwroff_n gpio %d\n", + apb->pwroff_gpio); + return ret; + } /* Do not make clock mandatory as of now (for DB3) */ apb->clk_en_gpio = of_get_named_gpio(np, "clock-en-gpio", 0); - if (apb->clk_en_gpio < 0) + if (apb->clk_en_gpio < 0) { dev_warn(dev, "failed to get clock en gpio\n"); + } else if (gpio_is_valid(apb->clk_en_gpio)) { + ret = devm_gpio_request_one(dev, apb->clk_en_gpio, + GPIOF_OUT_INIT_LOW, "apb_clk_en"); + if (ret) { + dev_warn(dev, "Failed requesting APB clock en gpio %d\n", + apb->clk_en_gpio); + return ret; + } + } apb->pwrdn_gpio = of_get_named_gpio(np, "pwr-down-gpios", 0); if (apb->pwrdn_gpio < 0) @@ -255,10 +243,6 @@ int arche_apb_ctrl_probe(struct platform_device *pdev) return ret; } - /* deassert reset to APB : Active-low signal */ - deassert_reset(apb->resetn_gpio); - apb->state = ARCHE_PLATFORM_STATE_ACTIVE; - platform_set_drvdata(pdev, apb); export_gpios(apb); -- cgit v0.10.2 From 5667ab17999a16c2bb1a5cdcaf183d8710aeb717 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sat, 13 Feb 2016 02:04:10 +0530 Subject: greybus: arche-apb-ctrl: Rename init_seq and cleanup fn apb_ctrl_coldboot_seq() and apb_ctrl_poweroff_seq() is appropriate name as per spec and implementation, so rename it. Also move apb_ctrl_poweroff_seq() fn above, to group it with other _seq functions. Testing Done: Tested on EVT1.2 and DB3.5 platform. Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index 7720153..9b7d61f 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -71,7 +71,7 @@ static void unexport_gpios(struct arche_apb_ctrl_drvdata *apb) /* * Note: Please do not modify the below sequence, as it is as per the spec */ -static int apb_ctrl_init_seq(struct platform_device *pdev, +static int apb_ctrl_coldboot_seq(struct platform_device *pdev, struct arche_apb_ctrl_drvdata *apb) { struct device *dev = &pdev->dev; @@ -113,6 +113,25 @@ static int apb_ctrl_init_seq(struct platform_device *pdev, return 0; } +static void apb_ctrl_poweroff_seq(struct arche_apb_ctrl_drvdata *apb) +{ + /* disable the clock */ + if (gpio_is_valid(apb->clk_en_gpio)) + gpio_set_value(apb->clk_en_gpio, 0); + + if (!IS_ERR(apb->vcore) && regulator_is_enabled(apb->vcore) > 0) + regulator_disable(apb->vcore); + + if (!IS_ERR(apb->vio) && regulator_is_enabled(apb->vio) > 0) + regulator_disable(apb->vio); + + /* As part of exit, put APB back in reset state */ + assert_reset(apb->resetn_gpio); + apb->state = ARCHE_PLATFORM_STATE_OFF; + + /* TODO: May have to send an event to SVC about this exit */ +} + static int apb_ctrl_get_devtree_data(struct platform_device *pdev, struct arche_apb_ctrl_drvdata *apb) { @@ -201,25 +220,6 @@ static int apb_ctrl_get_devtree_data(struct platform_device *pdev, return 0; } -static void apb_ctrl_cleanup(struct arche_apb_ctrl_drvdata *apb) -{ - /* disable the clock */ - if (gpio_is_valid(apb->clk_en_gpio)) - gpio_set_value(apb->clk_en_gpio, 0); - - if (!IS_ERR(apb->vcore) && regulator_is_enabled(apb->vcore) > 0) - regulator_disable(apb->vcore); - - if (!IS_ERR(apb->vio) && regulator_is_enabled(apb->vio) > 0) - regulator_disable(apb->vio); - - /* As part of exit, put APB back in reset state */ - assert_reset(apb->resetn_gpio); - apb->state = ARCHE_PLATFORM_STATE_OFF; - - /* TODO: May have to send an event to SVC about this exit */ -} - int arche_apb_ctrl_probe(struct platform_device *pdev) { int ret; @@ -236,7 +236,7 @@ int arche_apb_ctrl_probe(struct platform_device *pdev) return ret; } - ret = apb_ctrl_init_seq(pdev, apb); + ret = apb_ctrl_coldboot_seq(pdev, apb); if (ret) { dev_err(dev, "failed to set init state of control signal %d\n", ret); @@ -255,7 +255,7 @@ int arche_apb_ctrl_remove(struct platform_device *pdev) { struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); - apb_ctrl_cleanup(apb); + apb_ctrl_poweroff_seq(apb); platform_set_drvdata(pdev, NULL); unexport_gpios(apb); -- cgit v0.10.2 From f2222a41db55f89bfafad03bd04ffdfb317b2edb Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sat, 13 Feb 2016 02:04:11 +0530 Subject: greybus: arche-apb-ctrl: Set default state value to OFF Explicitly set default apb->state value to ARCHE_PLATFORM_STATE_OFF in probe() fn. Testing Done: Tested on EVT1.2 and DB3.5 platform Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index 9b7d61f..1d3c112 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -236,6 +236,9 @@ int arche_apb_ctrl_probe(struct platform_device *pdev) return ret; } + /* Initially set APB to OFF state */ + apb->state = ARCHE_PLATFORM_STATE_OFF; + ret = apb_ctrl_coldboot_seq(pdev, apb); if (ret) { dev_err(dev, "failed to set init state of control signal %d\n", -- cgit v0.10.2 From 6961e0466575608639e91ddbcc62d9385d45a198 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sat, 13 Feb 2016 02:04:12 +0530 Subject: greybus: arche-apb-ctrl: Pass only platform_device to _seq fns Pass only pointer to platform_device to _seq fns and fetch handle to arche_apb_ctrl_drvdata from platform_device. This is preparation for support for dynamic switching between operational states for the device, where these functions will be called from parent driver. Testing Done: Tested on EVT1.2 and DB3.5 platform. Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index 1d3c112..8f6f096 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -71,10 +71,10 @@ static void unexport_gpios(struct arche_apb_ctrl_drvdata *apb) /* * Note: Please do not modify the below sequence, as it is as per the spec */ -static int apb_ctrl_coldboot_seq(struct platform_device *pdev, - struct arche_apb_ctrl_drvdata *apb) +static int apb_ctrl_coldboot_seq(struct platform_device *pdev) { struct device *dev = &pdev->dev; + struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); int ret; /* Hold APB in reset state */ @@ -113,8 +113,10 @@ static int apb_ctrl_coldboot_seq(struct platform_device *pdev, return 0; } -static void apb_ctrl_poweroff_seq(struct arche_apb_ctrl_drvdata *apb) +static void apb_ctrl_poweroff_seq(struct platform_device *pdev) { + struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); + /* disable the clock */ if (gpio_is_valid(apb->clk_en_gpio)) gpio_set_value(apb->clk_en_gpio, 0); @@ -239,15 +241,16 @@ int arche_apb_ctrl_probe(struct platform_device *pdev) /* Initially set APB to OFF state */ apb->state = ARCHE_PLATFORM_STATE_OFF; - ret = apb_ctrl_coldboot_seq(pdev, apb); + platform_set_drvdata(pdev, apb); + + ret = apb_ctrl_coldboot_seq(pdev); if (ret) { dev_err(dev, "failed to set init state of control signal %d\n", ret); + platform_set_drvdata(pdev, NULL); return ret; } - platform_set_drvdata(pdev, apb); - export_gpios(apb); dev_info(&pdev->dev, "Device registered successfully\n"); @@ -258,7 +261,7 @@ int arche_apb_ctrl_remove(struct platform_device *pdev) { struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); - apb_ctrl_poweroff_seq(apb); + apb_ctrl_poweroff_seq(pdev); platform_set_drvdata(pdev, NULL); unexport_gpios(apb); -- cgit v0.10.2 From 33d76291073dd9408055a23cd96a23c375944377 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sat, 13 Feb 2016 02:04:13 +0530 Subject: greybus: arche-apb-ctrl: Add sysfs to allow user to change state This patch introduces sysfs interface for the user space to enable state change of the driver. Driver supports below operational states, - off - active - standby - fw_flashing To see the current state i # cat /sys/devices/arche_platform.*/apb*/state And to change the state # echo [off/active/standby/fw_flashing] > /sys/devices/arche_platform.*/apb*/state Testing Done: Tested on EVT1.2 and DB3.5 platform Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index 8f6f096..e4fd34d 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -113,6 +113,52 @@ static int apb_ctrl_coldboot_seq(struct platform_device *pdev) return 0; } +static int apb_ctrl_fw_flashing_seq(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); + int ret; + + ret = regulator_enable(apb->vcore); + if (ret) { + dev_err(dev, "failed to enable core regulator\n"); + return ret; + } + + ret = regulator_enable(apb->vio); + if (ret) { + dev_err(dev, "failed to enable IO regulator\n"); + return ret; + } + + /* for flashing device should be in reset state */ + assert_reset(apb->resetn_gpio); + apb->state = ARCHE_PLATFORM_STATE_FW_FLASHING; + + return 0; +} + +static int apb_ctrl_standby_boot_seq(struct platform_device *pdev) +{ + struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); + + /* If it is in OFF state, then we do not want to change the state */ + if (apb->state == ARCHE_PLATFORM_STATE_OFF) + return 0; + + /* + * As per WDM spec, do nothing + * + * Pasted from WDM spec, + * - A falling edge on POWEROFF_L is detected (a) + * - WDM enters standby mode, but no output signals are changed + * */ + + /* TODO: POWEROFF_L is input to WDM module */ + apb->state = ARCHE_PLATFORM_STATE_STANDBY; + return 0; +} + static void apb_ctrl_poweroff_seq(struct platform_device *pdev) { struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); @@ -134,6 +180,66 @@ static void apb_ctrl_poweroff_seq(struct platform_device *pdev) /* TODO: May have to send an event to SVC about this exit */ } +static ssize_t state_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct platform_device *pdev = to_platform_device(dev); + struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); + int ret = 0; + + if (sysfs_streq(buf, "off")) { + if (apb->state == ARCHE_PLATFORM_STATE_OFF) + return count; + + apb_ctrl_poweroff_seq(pdev); + } else if (sysfs_streq(buf, "active")) { + if (apb->state == ARCHE_PLATFORM_STATE_ACTIVE) + return count; + + apb_ctrl_poweroff_seq(pdev); + ret = apb_ctrl_coldboot_seq(pdev); + } else if (sysfs_streq(buf, "standby")) { + if (apb->state == ARCHE_PLATFORM_STATE_STANDBY) + return count; + + ret = apb_ctrl_standby_boot_seq(pdev); + } else if (sysfs_streq(buf, "fw_flashing")) { + if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING) + return count; + + /* First we want to make sure we power off everything + * and then enter FW flashing state */ + apb_ctrl_poweroff_seq(pdev); + ret = apb_ctrl_fw_flashing_seq(pdev); + } else { + dev_err(dev, "unknown state\n"); + ret = -EINVAL; + } + + return ret ? ret : count; +} + +static ssize_t state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct arche_apb_ctrl_drvdata *apb = dev_get_drvdata(dev); + + switch (apb->state) { + case ARCHE_PLATFORM_STATE_OFF: + return sprintf(buf, "off\n"); + case ARCHE_PLATFORM_STATE_ACTIVE: + return sprintf(buf, "active\n"); + case ARCHE_PLATFORM_STATE_STANDBY: + return sprintf(buf, "standby\n"); + case ARCHE_PLATFORM_STATE_FW_FLASHING: + return sprintf(buf, "fw_flashing\n"); + default: + return sprintf(buf, "unknown state\n"); + } +} + +static DEVICE_ATTR_RW(state); + static int apb_ctrl_get_devtree_data(struct platform_device *pdev, struct arche_apb_ctrl_drvdata *apb) { @@ -243,10 +349,18 @@ int arche_apb_ctrl_probe(struct platform_device *pdev) platform_set_drvdata(pdev, apb); + /* Create sysfs interface to allow user to change state dynamically */ + ret = device_create_file(dev, &dev_attr_state); + if (ret) { + dev_err(dev, "failed to create state file in sysfs\n"); + return ret; + } + ret = apb_ctrl_coldboot_seq(pdev); if (ret) { dev_err(dev, "failed to set init state of control signal %d\n", ret); + device_remove_file(dev, &dev_attr_state); platform_set_drvdata(pdev, NULL); return ret; } @@ -261,6 +375,7 @@ int arche_apb_ctrl_remove(struct platform_device *pdev) { struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); + device_remove_file(&pdev->dev, &dev_attr_state); apb_ctrl_poweroff_seq(pdev); platform_set_drvdata(pdev, NULL); unexport_gpios(apb); -- cgit v0.10.2 From af3aae10f16f05acba27294bc1ae234f3cb61a61 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sat, 13 Feb 2016 02:04:14 +0530 Subject: greybus: arche-apb-ctrl: Introduce ara,init-disable property for APB New DT property "ara,init-disable" will allow user to disable APB1 or APB2 during boot and enable it only when needed through command prompt via sysfs interface. - To disable APB2 during boot, specify "ara,init-disable" property in respective APB node. - How to check the state # cat /sys/devices/arche_platform.*/apb*/state It should be 'off', if 'ara,init-disable' enabled in DT. - During runtime if user/developer desired to enable APB2 (strictly and only for development purpose) then respective APB can be enabled through, # echo active > /sys/devices/arche_platform.*/apb*/state Note: - If APB device is in 'off,disabled' state, then no state transitions are permitted. - User/developer must first activate APB device # echo active > /sys/devices/arche_platform.*/apb*/state This will clear the 'init-disable' flag and allow state transition from here onwards. Note that, 'off,disabled' is only indicative state and is only applicable during init/boot. Testing Done: Tested on EVT1.2 and DB3.5 platform Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index e4fd34d..04ba836 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -32,6 +32,7 @@ struct arche_apb_ctrl_drvdata { int pwrdn_gpio; enum arche_platform_state state; + bool init_disabled; struct regulator *vcore; struct regulator *vio; @@ -77,6 +78,9 @@ static int apb_ctrl_coldboot_seq(struct platform_device *pdev) struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); int ret; + if (apb->init_disabled) + return 0; + /* Hold APB in reset state */ assert_reset(apb->resetn_gpio); @@ -119,6 +123,9 @@ static int apb_ctrl_fw_flashing_seq(struct platform_device *pdev) struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); int ret; + if (apb->init_disabled) + return 0; + ret = regulator_enable(apb->vcore); if (ret) { dev_err(dev, "failed to enable core regulator\n"); @@ -142,6 +149,9 @@ static int apb_ctrl_standby_boot_seq(struct platform_device *pdev) { struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); + if (apb->init_disabled) + return 0; + /* If it is in OFF state, then we do not want to change the state */ if (apb->state == ARCHE_PLATFORM_STATE_OFF) return 0; @@ -163,6 +173,9 @@ static void apb_ctrl_poweroff_seq(struct platform_device *pdev) { struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); + if (apb->init_disabled) + return; + /* disable the clock */ if (gpio_is_valid(apb->clk_en_gpio)) gpio_set_value(apb->clk_en_gpio, 0); @@ -186,6 +199,7 @@ static ssize_t state_store(struct device *dev, struct platform_device *pdev = to_platform_device(dev); struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); int ret = 0; + bool is_disabled; if (sysfs_streq(buf, "off")) { if (apb->state == ARCHE_PLATFORM_STATE_OFF) @@ -197,7 +211,11 @@ static ssize_t state_store(struct device *dev, return count; apb_ctrl_poweroff_seq(pdev); + is_disabled = apb->init_disabled; + apb->init_disabled = false; ret = apb_ctrl_coldboot_seq(pdev); + if (ret) + apb->init_disabled = is_disabled; } else if (sysfs_streq(buf, "standby")) { if (apb->state == ARCHE_PLATFORM_STATE_STANDBY) return count; @@ -226,7 +244,8 @@ static ssize_t state_show(struct device *dev, switch (apb->state) { case ARCHE_PLATFORM_STATE_OFF: - return sprintf(buf, "off\n"); + return sprintf(buf, "off%s\n", + apb->init_disabled ? ",disabled" : ""); case ARCHE_PLATFORM_STATE_ACTIVE: return sprintf(buf, "active\n"); case ARCHE_PLATFORM_STATE_STANDBY: @@ -346,6 +365,9 @@ int arche_apb_ctrl_probe(struct platform_device *pdev) /* Initially set APB to OFF state */ apb->state = ARCHE_PLATFORM_STATE_OFF; + /* Check whether device needs to be enabled on boot */ + if (of_property_read_bool(pdev->dev.of_node, "ara,init-disable")) + apb->init_disabled = true; platform_set_drvdata(pdev, apb); -- cgit v0.10.2 From 80a057aa6c170403261f8d1d2ce435d3668848f6 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sat, 13 Feb 2016 02:04:15 +0530 Subject: greybus: arche-apb-ctrl: Rename internal operational state fns This is preparation for enabling export set of operational fns to parent driver. So it is important to differentiate internal ops function against externally accessed (from parent). Testing Done: Tested on EVT1.2 and DB3.5 platform. Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index 04ba836..50d27a6 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -72,7 +72,7 @@ static void unexport_gpios(struct arche_apb_ctrl_drvdata *apb) /* * Note: Please do not modify the below sequence, as it is as per the spec */ -static int apb_ctrl_coldboot_seq(struct platform_device *pdev) +static int coldboot_seq(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); @@ -117,7 +117,7 @@ static int apb_ctrl_coldboot_seq(struct platform_device *pdev) return 0; } -static int apb_ctrl_fw_flashing_seq(struct platform_device *pdev) +static int fw_flashing_seq(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); @@ -145,7 +145,7 @@ static int apb_ctrl_fw_flashing_seq(struct platform_device *pdev) return 0; } -static int apb_ctrl_standby_boot_seq(struct platform_device *pdev) +static int standby_boot_seq(struct platform_device *pdev) { struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); @@ -169,7 +169,7 @@ static int apb_ctrl_standby_boot_seq(struct platform_device *pdev) return 0; } -static void apb_ctrl_poweroff_seq(struct platform_device *pdev) +static void poweroff_seq(struct platform_device *pdev) { struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); @@ -205,30 +205,30 @@ static ssize_t state_store(struct device *dev, if (apb->state == ARCHE_PLATFORM_STATE_OFF) return count; - apb_ctrl_poweroff_seq(pdev); + poweroff_seq(pdev); } else if (sysfs_streq(buf, "active")) { if (apb->state == ARCHE_PLATFORM_STATE_ACTIVE) return count; - apb_ctrl_poweroff_seq(pdev); + poweroff_seq(pdev); is_disabled = apb->init_disabled; apb->init_disabled = false; - ret = apb_ctrl_coldboot_seq(pdev); + ret = coldboot_seq(pdev); if (ret) apb->init_disabled = is_disabled; } else if (sysfs_streq(buf, "standby")) { if (apb->state == ARCHE_PLATFORM_STATE_STANDBY) return count; - ret = apb_ctrl_standby_boot_seq(pdev); + ret = standby_boot_seq(pdev); } else if (sysfs_streq(buf, "fw_flashing")) { if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING) return count; /* First we want to make sure we power off everything * and then enter FW flashing state */ - apb_ctrl_poweroff_seq(pdev); - ret = apb_ctrl_fw_flashing_seq(pdev); + poweroff_seq(pdev); + ret = fw_flashing_seq(pdev); } else { dev_err(dev, "unknown state\n"); ret = -EINVAL; @@ -378,7 +378,7 @@ int arche_apb_ctrl_probe(struct platform_device *pdev) return ret; } - ret = apb_ctrl_coldboot_seq(pdev); + ret = coldboot_seq(pdev); if (ret) { dev_err(dev, "failed to set init state of control signal %d\n", ret); @@ -398,7 +398,7 @@ int arche_apb_ctrl_remove(struct platform_device *pdev) struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); device_remove_file(&pdev->dev, &dev_attr_state); - apb_ctrl_poweroff_seq(pdev); + poweroff_seq(pdev); platform_set_drvdata(pdev, NULL); unexport_gpios(apb); -- cgit v0.10.2 From 65fd5a5018c8c5b7ddf14dffa75474b3a9040851 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sat, 13 Feb 2016 02:04:16 +0530 Subject: greybus: arche-apb-ctrl: Export operational fns from driver In order to use single wake/detect line for both APB's we need to have access to APB operational functions to parent/SVC driver. So export coldboot, standby_boot, fw_flashing and poweroff operation functions from the driver. Testing Done: Tested on EVT1.2 and DB3.5 platform Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index 50d27a6..e1df998 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -193,6 +193,26 @@ static void poweroff_seq(struct platform_device *pdev) /* TODO: May have to send an event to SVC about this exit */ } +int apb_ctrl_coldboot(struct device *dev) +{ + return coldboot_seq(to_platform_device(dev)); +} + +int apb_ctrl_fw_flashing(struct device *dev) +{ + return fw_flashing_seq(to_platform_device(dev)); +} + +int apb_ctrl_standby_boot(struct device *dev) +{ + return standby_boot_seq(to_platform_device(dev)); +} + +void apb_ctrl_poweroff(struct device *dev) +{ + poweroff_seq(to_platform_device(dev)); +} + static ssize_t state_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { diff --git a/drivers/staging/greybus/arche_platform.h b/drivers/staging/greybus/arche_platform.h index 27deeb7..700c548 100644 --- a/drivers/staging/greybus/arche_platform.h +++ b/drivers/staging/greybus/arche_platform.h @@ -17,8 +17,17 @@ enum arche_platform_state { ARCHE_PLATFORM_STATE_FW_FLASHING, }; + int arche_apb_ctrl_probe(struct platform_device *pdev); int arche_apb_ctrl_remove(struct platform_device *pdev); + +/* Operational states for the APB device */ +int apb_ctrl_coldboot(struct device *dev); +int apb_ctrl_fw_flashing(struct device *dev); +int apb_ctrl_standby_boot(struct device *dev); +void apb_ctrl_poweroff(struct device *dev); + + extern const struct dev_pm_ops arche_apb_ctrl_pm_ops; #endif /* __ARCHE_PLATFORM_H */ -- cgit v0.10.2 From fd60ac585607979e37b64ecec8afb898f9ad6a85 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sat, 13 Feb 2016 02:04:17 +0530 Subject: greybus: arche-platform: Fix boot, poweroff and fw_flashing seq with APBs Now SVC driver has an access to APBs operational functions (coldboot, standby_boot, fw_flashing and poweroff), SVC driver can control APB's as per below rules, - If SVC goes down (poweroff state), it will also power off APBs and vice a versa for all operational states. - On boot, SVC will probe/populate APB device, but will not coldboot it. APBs will coldboot only after handshaking with SVC over wake/detect line. Note that, both APBs share same wake/detect line. So from user/developer perspective, it is highly recommended that they should use arche-platform interfaces, instead of individual apb interface, # echo [off/active/standby/fw_flashing] > /sys/devices/arche_platform.*/state Note: 'standby' mode is not supported as of now. Testing Done: Testd on EVT1.2 and DB3.5 platform. Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 3e6432f..037e142 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -45,6 +45,37 @@ static inline void svc_reset_onoff(unsigned int gpio, bool onoff) gpio_set_value(gpio, onoff); } +static int apb_cold_boot(struct device *dev, void *data) +{ + int ret; + + ret = apb_ctrl_coldboot(dev); + if (ret) + dev_warn(dev, "failed to coldboot\n"); + + /*Child nodes are independent, so do not exit coldboot operation */ + return 0; +} + +static int apb_fw_flashing_state(struct device *dev, void *data) +{ + int ret; + + ret = apb_ctrl_fw_flashing(dev); + if (ret) + dev_warn(dev, "failed to switch to fw flashing state\n"); + + /*Child nodes are independent, so do not exit coldboot operation */ + return 0; +} + +static int apb_poweroff(struct device *dev, void *data) +{ + apb_ctrl_poweroff(dev); + + return 0; +} + /** * svc_delayed_work - Time to give SVC to boot. */ @@ -52,10 +83,7 @@ static void svc_delayed_work(struct work_struct *work) { struct arche_platform_drvdata *arche_pdata = container_of(work, struct arche_platform_drvdata, delayed_work.work); - struct device *dev = arche_pdata->dev; - struct device_node *np = dev->of_node; int timeout = 50; - int ret; /* * 1. SVC and AP boot independently, with AP<-->SVC wake/detect pin @@ -79,18 +107,20 @@ static void svc_delayed_work(struct work_struct *work) msleep(100); } while(timeout--); - if (timeout >= 0) { - ret = of_platform_populate(np, NULL, NULL, dev); - if (!ret) { - /* re-assert wake_detect to confirm SVC WAKE_OUT */ - gpio_direction_output(arche_pdata->wake_detect_gpio, 1); - return; - } + if (timeout < 0) { + /* FIXME: We may want to limit retries here */ + dev_warn(arche_pdata->dev, + "Timed out on wake/detect, rescheduling handshake\n"); + gpio_direction_output(arche_pdata->wake_detect_gpio, 0); + schedule_delayed_work(&arche_pdata->delayed_work, msecs_to_jiffies(2000)); + return; } - /* FIXME: We may want to limit retries here */ - gpio_direction_output(arche_pdata->wake_detect_gpio, 0); - schedule_delayed_work(&arche_pdata->delayed_work, msecs_to_jiffies(2000)); + /* Bring APB out of reset: cold boot sequence */ + device_for_each_child(arche_pdata->dev, NULL, apb_cold_boot); + + /* re-assert wake_detect to confirm SVC WAKE_OUT */ + gpio_direction_output(arche_pdata->wake_detect_gpio, 1); } /* Export gpio's to user space */ @@ -176,12 +206,17 @@ static ssize_t state_store(struct device *dev, if (arche_pdata->state == ARCHE_PLATFORM_STATE_OFF) return count; + /* If SVC goes down, bring down APB's as well */ + device_for_each_child(arche_pdata->dev, NULL, apb_poweroff); + arche_platform_poweroff_seq(arche_pdata); } else if (sysfs_streq(buf, "active")) { if (arche_pdata->state == ARCHE_PLATFORM_STATE_ACTIVE) return count; ret = arche_platform_coldboot_seq(arche_pdata); + /* Give enough time for SVC to boot and then handshake with SVC */ + schedule_delayed_work(&arche_pdata->delayed_work, msecs_to_jiffies(2000)); } else if (sysfs_streq(buf, "standby")) { if (arche_pdata->state == ARCHE_PLATFORM_STATE_STANDBY) return count; @@ -193,8 +228,13 @@ static ssize_t state_store(struct device *dev, /* First we want to make sure we power off everything * and then enter FW flashing state */ + device_for_each_child(arche_pdata->dev, NULL, apb_poweroff); + arche_platform_poweroff_seq(arche_pdata); + arche_platform_fw_flashing_seq(arche_pdata); + + device_for_each_child(arche_pdata->dev, NULL, apb_fw_flashing_state); } else { dev_err(arche_pdata->dev, "unknown state\n"); ret = -EINVAL; @@ -321,8 +361,6 @@ static int arche_platform_probe(struct platform_device *pdev) gpio_direction_output(arche_pdata->wake_detect_gpio, 0); arche_pdata->dev = &pdev->dev; - INIT_DELAYED_WORK(&arche_pdata->delayed_work, svc_delayed_work); - schedule_delayed_work(&arche_pdata->delayed_work, msecs_to_jiffies(2000)); ret = device_create_file(dev, &dev_attr_state); if (ret) { @@ -336,6 +374,15 @@ static int arche_platform_probe(struct platform_device *pdev) return ret; } + ret = of_platform_populate(np, NULL, NULL, dev); + if (ret) { + dev_err(dev, "failed to populate child nodes %d\n", ret); + return ret; + } + + INIT_DELAYED_WORK(&arche_pdata->delayed_work, svc_delayed_work); + schedule_delayed_work(&arche_pdata->delayed_work, msecs_to_jiffies(2000)); + export_gpios(arche_pdata); dev_info(dev, "Device registered successfully\n"); -- cgit v0.10.2 From b03249390806c48921e1a538673276ebfcb645b7 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sat, 13 Feb 2016 02:04:18 +0530 Subject: greybus: arche-platform: Do not export any gpios With addition of operational state in driver, user/developer can switch to FW flashing state through sysfs. So no need to export any gpios to userspace now. Testing Done: Tested on EVT1.2 and DB3.5 platform Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 037e142..1fd806f 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -123,19 +123,6 @@ static void svc_delayed_work(struct work_struct *work) gpio_direction_output(arche_pdata->wake_detect_gpio, 1); } -/* Export gpio's to user space */ -static void export_gpios(struct arche_platform_drvdata *arche_pdata) -{ - gpio_export(arche_pdata->svc_reset_gpio, false); - gpio_export(arche_pdata->svc_sysboot_gpio, false); -} - -static void unexport_gpios(struct arche_platform_drvdata *arche_pdata) -{ - gpio_unexport(arche_pdata->svc_reset_gpio); - gpio_unexport(arche_pdata->svc_sysboot_gpio); -} - static int arche_platform_coldboot_seq(struct arche_platform_drvdata *arche_pdata) { int ret; @@ -383,8 +370,6 @@ static int arche_platform_probe(struct platform_device *pdev) INIT_DELAYED_WORK(&arche_pdata->delayed_work, svc_delayed_work); schedule_delayed_work(&arche_pdata->delayed_work, msecs_to_jiffies(2000)); - export_gpios(arche_pdata); - dev_info(dev, "Device registered successfully\n"); return 0; } @@ -407,7 +392,6 @@ static int arche_platform_remove(struct platform_device *pdev) device_for_each_child(&pdev->dev, NULL, arche_remove_child); arche_platform_poweroff_seq(arche_pdata); platform_set_drvdata(pdev, NULL); - unexport_gpios(arche_pdata); return 0; } -- cgit v0.10.2 From bc8eadd46c05280f7ddcf2ab7cf97d1cd15a578c Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sat, 13 Feb 2016 02:04:19 +0530 Subject: greybus: arche-apb-ctrl: Do not export any gpios With addition of operational state in driver, user/developer can switch to FW flashing state through sysfs. So no need to export any gpios to userspace now. Testing Done: Tested on EVT1.2 and DB3.5 platform Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index e1df998..b888da3 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -58,17 +58,6 @@ static inline void assert_reset(unsigned int gpio) gpio_set_value(gpio, 0); } -/* Export gpio's to user space */ -static void export_gpios(struct arche_apb_ctrl_drvdata *apb) -{ - gpio_export(apb->resetn_gpio, false); -} - -static void unexport_gpios(struct arche_apb_ctrl_drvdata *apb) -{ - gpio_unexport(apb->resetn_gpio); -} - /* * Note: Please do not modify the below sequence, as it is as per the spec */ @@ -407,20 +396,15 @@ int arche_apb_ctrl_probe(struct platform_device *pdev) return ret; } - export_gpios(apb); - dev_info(&pdev->dev, "Device registered successfully\n"); return 0; } int arche_apb_ctrl_remove(struct platform_device *pdev) { - struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); - device_remove_file(&pdev->dev, &dev_attr_state); poweroff_seq(pdev); platform_set_drvdata(pdev, NULL); - unexport_gpios(apb); return 0; } -- cgit v0.10.2 From ad4d3f95c9a25590da8b2b71dbbad838b80bf7dc Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sat, 13 Feb 2016 02:04:20 +0530 Subject: greybus: arche-platform: Control usb3613 from arche-platform USB3613 hub driver exports control function, which allows caller to switch the mode of operation of hub device. As we know that, we have dependency between HUB3613 and APB's where, HUB supposed to enter into HUB only after APB's brought out of reset. Until now, we had all userspace driver sequences to control this, but now since we are moving all resource management strictly to the driver, it makes sense (even though it looks hacky) to enable control of hub3613 from arche-platform driver. Note that, there is another discussion where, the hub.connect IO pin may get interfaced with MSM gpio, at that time, we can get rid of this hack and replace it with gpio control. Testing Done: Tested on EVT1.2 and DB3.5 platform. Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 1fd806f..591cf9d 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -19,6 +19,8 @@ #include #include "arche_platform.h" +#include + struct arche_platform_drvdata { /* Control GPIO signals to and from AP <=> SVC */ int svc_reset_gpio; @@ -121,6 +123,10 @@ static void svc_delayed_work(struct work_struct *work) /* re-assert wake_detect to confirm SVC WAKE_OUT */ gpio_direction_output(arche_pdata->wake_detect_gpio, 1); + + /* Enable HUB3613 into HUB mode. */ + if (usb3613_hub_mode_ctrl(true)) + dev_warn(arche_pdata->dev, "failed to control hub device\n"); } static int arche_platform_coldboot_seq(struct arche_platform_drvdata *arche_pdata) @@ -197,6 +203,11 @@ static ssize_t state_store(struct device *dev, device_for_each_child(arche_pdata->dev, NULL, apb_poweroff); arche_platform_poweroff_seq(arche_pdata); + + ret = usb3613_hub_mode_ctrl(false); + if (ret) + dev_warn(arche_pdata->dev, "failed to control hub device\n"); + /* TODO: Should we do anything more here ?? */ } else if (sysfs_streq(buf, "active")) { if (arche_pdata->state == ARCHE_PLATFORM_STATE_ACTIVE) return count; @@ -219,6 +230,11 @@ static ssize_t state_store(struct device *dev, arche_platform_poweroff_seq(arche_pdata); + ret = usb3613_hub_mode_ctrl(false); + if (ret) + dev_warn(arche_pdata->dev, "failed to control hub device\n"); + /* TODO: Should we do anything more here ?? */ + arche_platform_fw_flashing_seq(arche_pdata); device_for_each_child(arche_pdata->dev, NULL, apb_fw_flashing_state); @@ -393,6 +409,9 @@ static int arche_platform_remove(struct platform_device *pdev) arche_platform_poweroff_seq(arche_pdata); platform_set_drvdata(pdev, NULL); + if (usb3613_hub_mode_ctrl(false)) + dev_warn(arche_pdata->dev, "failed to control hub device\n"); + /* TODO: Should we do anything more here ?? */ return 0; } -- cgit v0.10.2 From 7d0493d191abc0bb20c0746fe687b7e8ba8a696a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 15 Feb 2016 13:58:21 -0800 Subject: greybus: only build arche platform driver if usb3613 is enabled The build is broken if you try to build the arche platform driver without the usb3163 driver enabled at the same time, so specify that dependency in the greybus Makefile. Testing done: built inside and outside of the build system against many different kernel versions. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Michael Scott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 870a7bb..6e276d8 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -47,7 +47,9 @@ obj-m += gb-light.o obj-m += gb-hid.o obj-m += gb-raw.o obj-m += gb-es2.o -obj-m += gb-arche.o +ifeq ($(CONFIG_USB_HSIC_USB3613),y) + obj-m += gb-arche.o +endif ifeq ($(CONFIG_SND_SOC_DYNAMIC_DAILINK),y) obj-m += gb-audio-codec.o endif -- cgit v0.10.2 From c463593c3dbc8d4dcb132538b0116256fa0cc455 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 12 Feb 2016 16:08:26 +0530 Subject: greybus: raw: Use consistent label names in connection_init() Some of the labels are named based on what they are going to undo, while others are based on where we failed in connection_init(). Follow only the first type of naming. Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/raw.c b/drivers/staging/greybus/raw.c index a6e7959..d2e0281 100644 --- a/drivers/staging/greybus/raw.c +++ b/drivers/staging/greybus/raw.c @@ -174,21 +174,21 @@ static int gb_raw_connection_init(struct gb_connection *connection) cdev_init(&raw->cdev, &raw_fops); retval = cdev_add(&raw->cdev, raw->dev, 1); if (retval) - goto error_cdev; + goto error_remove_ida; raw->device = device_create(raw_class, &connection->bundle->dev, raw->dev, raw, "gb!raw%d", minor); if (IS_ERR(raw->device)) { retval = PTR_ERR(raw->device); - goto error_device; + goto error_del_cdev; } return 0; -error_device: +error_del_cdev: cdev_del(&raw->cdev); -error_cdev: +error_remove_ida: ida_simple_remove(&minors, minor); error_free: -- cgit v0.10.2 From 2554eda5756a37118ab310bd02de78491303ab5f Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 12 Feb 2016 16:08:27 +0530 Subject: greybus: raw: Don't use (possibly) uninitialized raw->device in gb_raw_receive() If an incoming request comes on the connection, before the driver has allocated its raw->device in gb_raw_connection_init(), then it might result in a crash while printing error messages. Fix that by using bundle->dev for printing error messages. Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/raw.c b/drivers/staging/greybus/raw.c index d2e0281..ed17ba3 100644 --- a/drivers/staging/greybus/raw.c +++ b/drivers/staging/greybus/raw.c @@ -57,17 +57,17 @@ static DEFINE_IDA(minors); static int receive_data(struct gb_raw *raw, u32 len, u8 *data) { struct raw_data *raw_data; + struct device *dev = &raw->connection->bundle->dev; int retval = 0; if (len > MAX_PACKET_SIZE) { - dev_err(raw->device, "Too big of a data packet, rejected\n"); + dev_err(dev, "Too big of a data packet, rejected\n"); return -EINVAL; } mutex_lock(&raw->list_lock); if ((raw->list_data + len) > MAX_DATA_SIZE) { - dev_err(raw->device, - "Too much data in receive buffer, now dropping packets\n"); + dev_err(dev, "Too much data in receive buffer, now dropping packets\n"); retval = -EINVAL; goto exit; } @@ -91,32 +91,31 @@ exit: static int gb_raw_receive(u8 type, struct gb_operation *op) { struct gb_connection *connection = op->connection; + struct device *dev = &connection->bundle->dev; struct gb_raw *raw = connection->private; struct gb_raw_send_request *receive; u32 len; if (type != GB_RAW_TYPE_SEND) { - dev_err(raw->device, "unknown request type %d\n", type); + dev_err(dev, "unknown request type %d\n", type); return -EINVAL; } /* Verify size of payload */ if (op->request->payload_size < sizeof(*receive)) { - dev_err(raw->device, "raw receive request too small (%zu < %zu)\n", + dev_err(dev, "raw receive request too small (%zu < %zu)\n", op->request->payload_size, sizeof(*receive)); return -EINVAL; } receive = op->request->payload; len = le32_to_cpu(receive->len); if (len != (int)(op->request->payload_size - sizeof(__le32))) { - dev_err(raw->device, - "raw receive request wrong size %d vs %d\n", - len, + dev_err(dev, "raw receive request wrong size %d vs %d\n", len, (int)(op->request->payload_size - sizeof(__le32))); return -EINVAL; } if (len == 0) { - dev_err(raw->device, "raw receive request of 0 bytes?\n"); + dev_err(dev, "raw receive request of 0 bytes?\n"); return -EINVAL; } -- cgit v0.10.2 From 512cc327625651260b2ba885b63cf2cf14ff54d1 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 15 Feb 2016 10:47:27 +0530 Subject: greybus: raw: convert to bundle driver Convert the legacy raw protocol driver to a bundle driver. This also fixes a potential crash should a (malicious) module have sent an early request before the private data had been initialised. Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index 057029d..23ea458 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -247,7 +247,6 @@ static const struct greybus_bundle_id legacy_id_table[] = { { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_CAMERA) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_LIGHTS) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_LOOPBACK) }, - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_RAW) }, { } }; MODULE_DEVICE_TABLE(greybus, legacy_id_table); diff --git a/drivers/staging/greybus/raw.c b/drivers/staging/greybus/raw.c index ed17ba3..338139e 100644 --- a/drivers/staging/greybus/raw.c +++ b/drivers/staging/greybus/raw.c @@ -88,16 +88,16 @@ exit: return retval; } -static int gb_raw_receive(u8 type, struct gb_operation *op) +static int gb_raw_request_handler(struct gb_operation *op) { struct gb_connection *connection = op->connection; struct device *dev = &connection->bundle->dev; - struct gb_raw *raw = connection->private; + struct gb_raw *raw = greybus_get_drvdata(connection->bundle); struct gb_raw_send_request *receive; u32 len; - if (type != GB_RAW_TYPE_SEND) { - dev_err(dev, "unknown request type %d\n", type); + if (op->type != GB_RAW_TYPE_SEND) { + dev_err(dev, "unknown request type %d\n", op->type); return -EINVAL; } @@ -147,34 +147,56 @@ static int gb_raw_send(struct gb_raw *raw, u32 len, const char __user *data) return retval; } -static int gb_raw_connection_init(struct gb_connection *connection) +static int gb_raw_probe(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) { + struct greybus_descriptor_cport *cport_desc; + struct gb_connection *connection; struct gb_raw *raw; int retval; int minor; + if (bundle->num_cports != 1) + return -ENODEV; + + cport_desc = &bundle->cport_desc[0]; + if (cport_desc->protocol_id != GREYBUS_PROTOCOL_RAW) + return -ENODEV; + raw = kzalloc(sizeof(*raw), GFP_KERNEL); if (!raw) return -ENOMEM; - raw->connection = connection; - connection->private = raw; + connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id), + gb_raw_request_handler); + if (IS_ERR(connection)) { + retval = PTR_ERR(connection); + goto error_free; + } INIT_LIST_HEAD(&raw->list); mutex_init(&raw->list_lock); + raw->connection = connection; + greybus_set_drvdata(bundle, raw); + minor = ida_simple_get(&minors, 0, 0, GFP_KERNEL); if (minor < 0) { retval = minor; - goto error_free; + goto error_connection_destroy; } raw->dev = MKDEV(raw_major, minor); cdev_init(&raw->cdev, &raw_fops); - retval = cdev_add(&raw->cdev, raw->dev, 1); + + retval = gb_connection_enable(connection); if (retval) goto error_remove_ida; + retval = cdev_add(&raw->cdev, raw->dev, 1); + if (retval) + goto error_connection_disable; + raw->device = device_create(raw_class, &connection->bundle->dev, raw->dev, raw, "gb!raw%d", minor); if (IS_ERR(raw->device)) { @@ -187,24 +209,34 @@ static int gb_raw_connection_init(struct gb_connection *connection) error_del_cdev: cdev_del(&raw->cdev); +error_connection_disable: + gb_connection_disable(connection); + error_remove_ida: ida_simple_remove(&minors, minor); +error_connection_destroy: + gb_connection_destroy(connection); + error_free: kfree(raw); return retval; } -static void gb_raw_connection_exit(struct gb_connection *connection) +static void gb_raw_disconnect(struct gb_bundle *bundle) { - struct gb_raw *raw = connection->private; + struct gb_raw *raw = greybus_get_drvdata(bundle); + struct gb_connection *connection = raw->connection; struct raw_data *raw_data; struct raw_data *temp; // FIXME - handle removing a connection when the char device node is open. device_destroy(raw_class, raw->dev); cdev_del(&raw->cdev); + gb_connection_disable(connection); ida_simple_remove(&minors, MINOR(raw->dev)); + gb_connection_destroy(connection); + mutex_lock(&raw->list_lock); list_for_each_entry_safe(raw_data, temp, &raw->list, entry) { list_del(&raw_data->entry); @@ -215,16 +247,6 @@ static void gb_raw_connection_exit(struct gb_connection *connection) kfree(raw); } -static struct gb_protocol raw_protocol = { - .name = "raw", - .id = GREYBUS_PROTOCOL_RAW, - .major = GB_RAW_VERSION_MAJOR, - .minor = GB_RAW_VERSION_MINOR, - .connection_init = gb_raw_connection_init, - .connection_exit = gb_raw_connection_exit, - .request_recv = gb_raw_receive, -}; - /* * Character device node interfaces. * @@ -302,6 +324,19 @@ static const struct file_operations raw_fops = { .llseek = noop_llseek, }; +static const struct greybus_bundle_id gb_raw_id_table[] = { + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_RAW) }, + { } +}; +MODULE_DEVICE_TABLE(greybus, gb_raw_id_table); + +static struct greybus_driver gb_raw_driver = { + .name = "raw", + .probe = gb_raw_probe, + .disconnect = gb_raw_disconnect, + .id_table = gb_raw_id_table, +}; + static int raw_init(void) { dev_t dev; @@ -317,10 +352,9 @@ static int raw_init(void) if (retval < 0) goto error_chrdev; - raw_major = MAJOR(dev); - retval = gb_protocol_register(&raw_protocol); + retval = greybus_register(&gb_raw_driver); if (retval) goto error_gb; @@ -337,7 +371,7 @@ module_init(raw_init); static void __exit raw_exit(void) { - gb_protocol_deregister(&raw_protocol); + greybus_deregister(&gb_raw_driver); unregister_chrdev_region(MKDEV(raw_major, 0), NUM_MINORS); class_destroy(raw_class); ida_destroy(&minors); -- cgit v0.10.2 From e82a11dcbd37f0b5596d08636859b372713d4460 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 12 Feb 2016 16:08:29 +0530 Subject: greybus: loopback: convert to bundle driver Convert the legacy loopback protocol driver to a bundle driver. Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index 23ea458..63597f7 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -246,7 +246,6 @@ static const struct greybus_bundle_id legacy_id_table[] = { { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SPI) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_CAMERA) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_LIGHTS) }, - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_LOOPBACK) }, { } }; MODULE_DEVICE_TABLE(greybus, legacy_id_table); diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 66b3fca..f3ae2e9 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -777,7 +777,7 @@ static int gb_loopback_async_ping(struct gb_loopback *gb) NULL, 0, 0, NULL); } -static int gb_loopback_request_recv(u8 type, struct gb_operation *operation) +static int gb_loopback_request_handler(struct gb_operation *operation) { struct gb_connection *connection = operation->connection; struct gb_loopback_transfer_request *request; @@ -786,7 +786,7 @@ static int gb_loopback_request_recv(u8 type, struct gb_operation *operation) size_t len; /* By convention, the AP initiates the version operation */ - switch (type) { + switch (operation->type) { case GB_REQUEST_TYPE_PROTOCOL_VERSION: dev_err(dev, "module-initiated version operation\n"); return -EINVAL; @@ -820,7 +820,7 @@ static int gb_loopback_request_recv(u8 type, struct gb_operation *operation) return 0; default: - dev_err(dev, "unsupported request: %u\n", type); + dev_err(dev, "unsupported request: %u\n", operation->type); return -EINVAL; } } @@ -1083,18 +1083,38 @@ static void gb_loopback_insert_id(struct gb_loopback *gb) #define DEBUGFS_NAMELEN 32 -static int gb_loopback_connection_init(struct gb_connection *connection) +static int gb_loopback_probe(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) { + struct greybus_descriptor_cport *cport_desc; + struct gb_connection *connection; struct gb_loopback *gb; struct device *dev; int retval; char name[DEBUGFS_NAMELEN]; unsigned long flags; + if (bundle->num_cports != 1) + return -ENODEV; + + cport_desc = &bundle->cport_desc[0]; + if (cport_desc->protocol_id != GREYBUS_PROTOCOL_LOOPBACK) + return -ENODEV; + gb = kzalloc(sizeof(*gb), GFP_KERNEL); if (!gb) return -ENOMEM; + connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id), + gb_loopback_request_handler); + if (IS_ERR(connection)) { + retval = PTR_ERR(connection); + goto out_kzalloc; + } + + gb->connection = connection; + greybus_set_drvdata(bundle, gb); + init_waitqueue_head(&gb->wq); init_waitqueue_head(&gb->wq_completion); atomic_set(&gb->outstanding_operations, 0); @@ -1110,7 +1130,7 @@ static int gb_loopback_connection_init(struct gb_connection *connection) if (gb_dev.size_max <= sizeof(struct gb_loopback_transfer_request)) { retval = -EINVAL; - goto out_kzalloc; + goto out_connection_destroy; } gb_dev.size_max -= sizeof(struct gb_loopback_transfer_request); } @@ -1120,22 +1140,24 @@ static int gb_loopback_connection_init(struct gb_connection *connection) dev_name(&connection->bundle->dev)); gb->file = debugfs_create_file(name, S_IFREG | S_IRUGO, gb_dev.root, gb, &gb_loopback_debugfs_latency_ops); - gb->connection = connection; - connection->private = gb; gb->id = ida_simple_get(&loopback_ida, 0, 0, GFP_KERNEL); if (gb->id < 0) { retval = gb->id; - goto out_ida; + goto out_debugfs_remove; } + retval = gb_connection_enable(connection); + if (retval) + goto out_ida_remove; + dev = device_create_with_groups(&loopback_class, &connection->bundle->dev, MKDEV(0, 0), gb, loopback_groups, "gb_loopback%d", gb->id); if (IS_ERR(dev)) { retval = PTR_ERR(dev); - goto out_dev; + goto out_connection_disable; } gb->dev = dev; @@ -1173,28 +1195,40 @@ out_kfifo0: kfifo_free(&gb->kfifo_lat); out_conn: device_unregister(dev); -out_dev: +out_connection_disable: + gb_connection_disable(connection); +out_ida_remove: ida_simple_remove(&loopback_ida, gb->id); -out_ida: +out_debugfs_remove: debugfs_remove(gb->file); +out_connection_destroy: + gb_connection_destroy(connection); out_kzalloc: kfree(gb); return retval; } -static void gb_loopback_connection_exit(struct gb_connection *connection) +static void gb_loopback_disconnect(struct gb_bundle *bundle) { - struct gb_loopback *gb = connection->private; + struct gb_loopback *gb = greybus_get_drvdata(bundle); unsigned long flags; + gb_connection_disable(gb->connection); + if (!IS_ERR_OR_NULL(gb->task)) kthread_stop(gb->task); kfifo_free(&gb->kfifo_lat); kfifo_free(&gb->kfifo_ts); - gb_connection_latency_tag_disable(connection); + gb_connection_latency_tag_disable(gb->connection); debugfs_remove(gb->file); + + /* + * FIXME: gb_loopback_async_wait_all() is redundant now, as connection + * is disabled at the beginning and so we can't have any more + * incoming/outgoing requests. + */ gb_loopback_async_wait_all(gb); spin_lock_irqsave(&gb_dev.lock, flags); @@ -1205,17 +1239,21 @@ static void gb_loopback_connection_exit(struct gb_connection *connection) device_unregister(gb->dev); ida_simple_remove(&loopback_ida, gb->id); + gb_connection_destroy(gb->connection); kfree(gb); } -static struct gb_protocol loopback_protocol = { - .name = "loopback", - .id = GREYBUS_PROTOCOL_LOOPBACK, - .major = GB_LOOPBACK_VERSION_MAJOR, - .minor = GB_LOOPBACK_VERSION_MINOR, - .connection_init = gb_loopback_connection_init, - .connection_exit = gb_loopback_connection_exit, - .request_recv = gb_loopback_request_recv, +static const struct greybus_bundle_id gb_loopback_id_table[] = { + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_LOOPBACK) }, + { } +}; +MODULE_DEVICE_TABLE(greybus, gb_loopback_id_table); + +static struct greybus_driver gb_loopback_driver = { + .name = "loopback", + .probe = gb_loopback_probe, + .disconnect = gb_loopback_disconnect, + .id_table = gb_loopback_id_table, }; static int loopback_init(void) @@ -1231,7 +1269,7 @@ static int loopback_init(void) if (retval) goto err; - retval = gb_protocol_register(&loopback_protocol); + retval = greybus_register(&gb_loopback_driver); if (retval) goto err_unregister; @@ -1248,7 +1286,7 @@ module_init(loopback_init); static void __exit loopback_exit(void) { debugfs_remove_recursive(gb_dev.root); - gb_protocol_deregister(&loopback_protocol); + greybus_deregister(&gb_loopback_driver); class_unregister(&loopback_class); ida_destroy(&loopback_ida); } -- cgit v0.10.2 From 6ce0eed783bd6b507fb029323d30d0e9a9d38da2 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 12 Feb 2016 16:08:30 +0530 Subject: greybus: lights: Break light setup into two parts This breaks the light setup routine into two parts, the first one allocates all the necessary resources and the second on registers lights to the required frameworks. This is required to enable only TX on the connection, until we have allocated all the resources, otherwise the request handler might get called for partially initialized structures. Signed-off-by: Viresh Kumar Reviewed-by: Rui Miguel Silva Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index 3488bbd..c1ad6b1 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -983,6 +983,14 @@ static int gb_lights_light_config(struct gb_lights *glights, u8 id) return ret; } + return 0; +} + +static int gb_lights_light_register(struct gb_light *light) +{ + int ret; + int i; + /* * Then, if everything went ok in getting configurations, we register * the classdev, flash classdev and v4l2 subsystem, if a flash device is @@ -1089,7 +1097,7 @@ static int gb_lights_get_count(struct gb_lights *glights) return 0; } -static int gb_lights_setup(struct gb_lights *glights) +static int gb_lights_create_all(struct gb_lights *glights) { struct gb_connection *connection = glights->connection; int ret; @@ -1121,11 +1129,32 @@ out: return ret; } +static int gb_lights_register_all(struct gb_lights *glights) +{ + struct gb_connection *connection = glights->connection; + int ret = 0; + int i; + + mutex_lock(&glights->lights_lock); + for (i = 0; i < glights->lights_count; i++) { + ret = gb_lights_light_register(&glights->lights[i]); + if (ret < 0) { + dev_err(&connection->bundle->dev, + "Fail to enable lights device\n"); + break; + } + } + + mutex_unlock(&glights->lights_lock); + return ret; +} + static int gb_lights_event_recv(u8 type, struct gb_operation *op) { struct gb_connection *connection = op->connection; struct device *dev = &connection->bundle->dev; struct gb_lights *glights = connection->private; + struct gb_light *light; struct gb_message *request; struct gb_lights_event_request *payload; int ret = 0; @@ -1157,11 +1186,15 @@ static int gb_lights_event_recv(u8 type, struct gb_operation *op) event = payload->event; if (event & GB_LIGHTS_LIGHT_CONFIG) { + light = &glights->lights[light_id]; + mutex_lock(&glights->lights_lock); - gb_lights_light_release(&glights->lights[light_id]); + gb_lights_light_release(light); ret = gb_lights_light_config(glights, light_id); + if (!ret) + ret = gb_lights_light_register(light); if (ret < 0) - gb_lights_light_release(&glights->lights[light_id]); + gb_lights_light_release(light); mutex_unlock(&glights->lights_lock); } @@ -1186,7 +1219,12 @@ static int gb_lights_connection_init(struct gb_connection *connection) * Setup all the lights devices over this connection, if anything goes * wrong tear down all lights */ - ret = gb_lights_setup(glights); + ret = gb_lights_create_all(glights); + if (ret < 0) + goto out; + + /* Enable & register lights */ + ret = gb_lights_register_all(glights); if (ret < 0) goto out; -- cgit v0.10.2 From 69564dfeacf0728b60e3b2c85b357bc63213116c Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 12 Feb 2016 16:08:31 +0530 Subject: greybus: lights: convert to bundle driver Convert the legacy lights protocol driver to a bundle driver. This also fixes a potential crash should a (malicious) module have sent an early request before the private data had been initialised. Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index 63597f7..2188de9 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -245,7 +245,6 @@ static const struct greybus_bundle_id legacy_id_table[] = { { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_PWM) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SPI) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_CAMERA) }, - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_LIGHTS) }, { } }; MODULE_DEVICE_TABLE(greybus, legacy_id_table); diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index c1ad6b1..70fcade 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -1149,7 +1149,7 @@ static int gb_lights_register_all(struct gb_lights *glights) return ret; } -static int gb_lights_event_recv(u8 type, struct gb_operation *op) +static int gb_lights_request_handler(struct gb_operation *op) { struct gb_connection *connection = op->connection; struct device *dev = &connection->bundle->dev; @@ -1161,8 +1161,8 @@ static int gb_lights_event_recv(u8 type, struct gb_operation *op) u8 light_id; u8 event; - if (type != GB_LIGHTS_TYPE_EVENT) { - dev_err(dev, "Unsupported unsolicited event: %u\n", type); + if (op->type != GB_LIGHTS_TYPE_EVENT) { + dev_err(dev, "Unsupported unsolicited event: %u\n", op->type); return -EINVAL; } @@ -1201,57 +1201,95 @@ static int gb_lights_event_recv(u8 type, struct gb_operation *op) return ret; } -static int gb_lights_connection_init(struct gb_connection *connection) +static int gb_lights_probe(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) { + struct greybus_descriptor_cport *cport_desc; + struct gb_connection *connection; struct gb_lights *glights; int ret; + if (bundle->num_cports != 1) + return -ENODEV; + + cport_desc = &bundle->cport_desc[0]; + if (cport_desc->protocol_id != GREYBUS_PROTOCOL_LIGHTS) + return -ENODEV; + glights = kzalloc(sizeof(*glights), GFP_KERNEL); if (!glights) return -ENOMEM; + connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id), + gb_lights_request_handler); + if (IS_ERR(connection)) { + ret = PTR_ERR(connection); + goto out; + } + glights->connection = connection; connection->private = glights; mutex_init(&glights->lights_lock); + greybus_set_drvdata(bundle, glights); + + /* We aren't ready to receive an incoming request yet */ + ret = gb_connection_enable_tx(connection); + if (ret) + goto error_connection_destroy; + /* * Setup all the lights devices over this connection, if anything goes * wrong tear down all lights */ ret = gb_lights_create_all(glights); if (ret < 0) - goto out; + goto error_connection_disable; + + /* We are ready to receive an incoming request now, enable RX as well */ + ret = gb_connection_enable(connection); + if (ret) + goto error_connection_disable; /* Enable & register lights */ ret = gb_lights_register_all(glights); if (ret < 0) - goto out; + goto error_connection_disable; return 0; +error_connection_disable: + gb_connection_disable(connection); +error_connection_destroy: + gb_connection_destroy(connection); out: gb_lights_release(glights); return ret; } -static void gb_lights_connection_exit(struct gb_connection *connection) +static void gb_lights_disconnect(struct gb_bundle *bundle) { - struct gb_lights *glights = connection->private; + struct gb_lights *glights = greybus_get_drvdata(bundle); + + gb_connection_disable(glights->connection); + gb_connection_destroy(glights->connection); gb_lights_release(glights); } -static struct gb_protocol lights_protocol = { - .name = "lights", - .id = GREYBUS_PROTOCOL_LIGHTS, - .major = GB_LIGHTS_VERSION_MAJOR, - .minor = GB_LIGHTS_VERSION_MINOR, - .connection_init = gb_lights_connection_init, - .connection_exit = gb_lights_connection_exit, - .request_recv = gb_lights_event_recv, +static const struct greybus_bundle_id gb_lights_id_table[] = { + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_LIGHTS) }, + { } }; +MODULE_DEVICE_TABLE(greybus, gb_lights_id_table); -gb_protocol_driver(&lights_protocol); +static struct greybus_driver gb_lights_driver = { + .name = "lights", + .probe = gb_lights_probe, + .disconnect = gb_lights_disconnect, + .id_table = gb_lights_id_table, +}; +module_greybus_driver(gb_lights_driver); MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 7e9fba8df7606bcace9d22394f59c2047dd55091 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 12 Feb 2016 16:08:32 +0530 Subject: greybus: power_supply: Break supply setup into two parts This breaks the power supply setup routine into two parts, the first one allocates all the necessary resources and the second on registers supplies to the required frameworks. This is required to enable only TX on the connection, until we have allocated all the resources, otherwise the request handler might get called for partially initialized structures. Signed-off-by: Viresh Kumar Reviewed-by: Rui Miguel Silva Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c index 37bea9c..c50b30d 100644 --- a/drivers/staging/greybus/power_supply.c +++ b/drivers/staging/greybus/power_supply.c @@ -624,31 +624,33 @@ static int gb_power_supply_config(struct gb_power_supplies *supplies, int id) ret = gb_power_supply_description_get(gbpsy); if (ret < 0) - goto out; + return ret; ret = gb_power_supply_prop_descriptors_get(gbpsy); if (ret < 0) - goto out; + return ret; /* guarantee that we have an unique name, before register */ - ret = __gb_power_supply_set_name(gbpsy->model_name, gbpsy->name, - sizeof(gbpsy->name)); - if (ret < 0) - goto out; + return __gb_power_supply_set_name(gbpsy->model_name, gbpsy->name, + sizeof(gbpsy->name)); +} + +static int gb_power_supply_enable(struct gb_power_supply *gbpsy) +{ + int ret; ret = gb_power_supply_register(gbpsy); if (ret < 0) - goto out; + return ret; gbpsy->update_interval = update_interval_init; INIT_DELAYED_WORK(&gbpsy->work, gb_power_supply_work); schedule_delayed_work(&gbpsy->work, 0); -out: - /* if everything went fine just mark it for release code to know */ - if (ret == 0) - gbpsy->registered = true; - return ret; + /* everything went fine, mark it for release code to know */ + gbpsy->registered = true; + + return 0; } static int gb_power_supplies_setup(struct gb_power_supplies *supplies) @@ -685,6 +687,27 @@ out: return ret; } +static int gb_power_supplies_register(struct gb_power_supplies *supplies) +{ + struct gb_connection *connection = supplies->connection; + int ret = 0; + int i; + + mutex_lock(&supplies->supplies_lock); + + for (i = 0; i < supplies->supplies_count; i++) { + ret = gb_power_supply_enable(&supplies->supply[i]); + if (ret < 0) { + dev_err(&connection->bundle->dev, + "Fail to enable supplies devices\n"); + break; + } + } + + mutex_unlock(&supplies->supplies_lock); + return ret; +} + static int gb_power_supply_event_recv(u8 type, struct gb_operation *op) { struct gb_connection *connection = op->connection; @@ -758,8 +781,16 @@ static int gb_power_supply_connection_init(struct gb_connection *connection) ret = gb_power_supplies_setup(supplies); if (ret < 0) - _gb_power_supplies_release(supplies); + goto out; + + ret = gb_power_supplies_register(supplies); + if (ret < 0) + goto out; + + return 0; +out: + _gb_power_supplies_release(supplies); return ret; } -- cgit v0.10.2 From 68b1309be689ec4e93d2b48e09ccaaa8abf5b0b6 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 12 Feb 2016 16:08:33 +0530 Subject: greybus: power_supply: convert to bundle driver Convert the legacy power_supply protocol driver to a bundle driver. This also fixes a potential crash should a (malicious) module have sent an early request before the private data had been initialised. Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index 2188de9..58b2779 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -241,7 +241,6 @@ static const struct greybus_bundle_id legacy_id_table[] = { { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_UART) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_USB) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SDIO) }, - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_POWER_SUPPLY) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_PWM) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SPI) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_CAMERA) }, diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c index c50b30d..0467537 100644 --- a/drivers/staging/greybus/power_supply.c +++ b/drivers/staging/greybus/power_supply.c @@ -708,7 +708,7 @@ static int gb_power_supplies_register(struct gb_power_supplies *supplies) return ret; } -static int gb_power_supply_event_recv(u8 type, struct gb_operation *op) +static int gb_supplies_request_handler(struct gb_operation *op) { struct gb_connection *connection = op->connection; struct gb_power_supplies *supplies = connection->private; @@ -719,9 +719,9 @@ static int gb_power_supply_event_recv(u8 type, struct gb_operation *op) u8 event; int ret = 0; - if (type != GB_POWER_SUPPLY_TYPE_EVENT) { + if (op->type != GB_POWER_SUPPLY_TYPE_EVENT) { dev_err(&connection->bundle->dev, - "Unsupported unsolicited event: %u\n", type); + "Unsupported unsolicited event: %u\n", op->type); return -EINVAL; } @@ -765,52 +765,90 @@ out_unlock: return ret; } -static int gb_power_supply_connection_init(struct gb_connection *connection) +static int gb_power_supply_probe(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) { + struct greybus_descriptor_cport *cport_desc; + struct gb_connection *connection; struct gb_power_supplies *supplies; int ret; + if (bundle->num_cports != 1) + return -ENODEV; + + cport_desc = &bundle->cport_desc[0]; + if (cport_desc->protocol_id != GREYBUS_PROTOCOL_POWER_SUPPLY) + return -ENODEV; + supplies = kzalloc(sizeof(*supplies), GFP_KERNEL); if (!supplies) return -ENOMEM; + connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id), + gb_supplies_request_handler); + if (IS_ERR(connection)) { + ret = PTR_ERR(connection); + goto out; + } + supplies->connection = connection; connection->private = supplies; mutex_init(&supplies->supplies_lock); + greybus_set_drvdata(bundle, supplies); + + /* We aren't ready to receive an incoming request yet */ + ret = gb_connection_enable_tx(connection); + if (ret) + goto error_connection_destroy; + ret = gb_power_supplies_setup(supplies); if (ret < 0) - goto out; + goto error_connection_disable; + + /* We are ready to receive an incoming request now, enable RX as well */ + ret = gb_connection_enable(connection); + if (ret) + goto error_connection_disable; ret = gb_power_supplies_register(supplies); if (ret < 0) - goto out; + goto error_connection_disable; return 0; +error_connection_disable: + gb_connection_disable(connection); +error_connection_destroy: + gb_connection_destroy(connection); out: _gb_power_supplies_release(supplies); return ret; } -static void gb_power_supply_connection_exit(struct gb_connection *connection) +static void gb_power_supply_disconnect(struct gb_bundle *bundle) { - struct gb_power_supplies *supplies = connection->private; + struct gb_power_supplies *supplies = greybus_get_drvdata(bundle); + + gb_connection_disable(supplies->connection); + gb_connection_destroy(supplies->connection); _gb_power_supplies_release(supplies); } -static struct gb_protocol power_supply_protocol = { - .name = "power_supply", - .id = GREYBUS_PROTOCOL_POWER_SUPPLY, - .major = GB_POWER_SUPPLY_VERSION_MAJOR, - .minor = GB_POWER_SUPPLY_VERSION_MINOR, - .connection_init = gb_power_supply_connection_init, - .connection_exit = gb_power_supply_connection_exit, - .request_recv = gb_power_supply_event_recv, +static const struct greybus_bundle_id gb_power_supply_id_table[] = { + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_POWER_SUPPLY) }, + { } }; +MODULE_DEVICE_TABLE(greybus, gb_power_supply_id_table); -gb_protocol_driver(&power_supply_protocol); +static struct greybus_driver gb_power_supply_driver = { + .name = "power_supply", + .probe = gb_power_supply_probe, + .disconnect = gb_power_supply_disconnect, + .id_table = gb_power_supply_id_table, +}; +module_greybus_driver(gb_power_supply_driver); MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From c161c0fc2f18ab8c299d6cb716d6264427e38867 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 14 Feb 2016 02:33:04 +0200 Subject: greybus: camera: Factorize link power mode configuration code into a function Avoid duplicating the same code block multiple times. Signed-off-by: Laurent Pinchart Tested-by: Jacopo Mondi Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 3f31a2f..8383770 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -107,6 +107,54 @@ static const struct gb_camera_fmt_map mbus_to_gbus_format[] = { * Camera Protocol Operations */ +static int gb_camera_set_intf_power_mode(struct gb_camera *gcam, u8 intf_id, + bool hs) +{ + struct gb_svc *svc = gcam->connection->hd->svc; + int ret; + + if (hs) + ret = gb_svc_intf_set_power_mode(svc, intf_id, + GB_SVC_UNIPRO_HS_SERIES_A, + GB_SVC_UNIPRO_FAST_MODE, 2, 2, + GB_SVC_UNIPRO_FAST_MODE, 2, 2, + GB_SVC_PWRM_RXTERMINATION | + GB_SVC_PWRM_TXTERMINATION, 0); + else + ret = gb_svc_intf_set_power_mode(svc, intf_id, + GB_SVC_UNIPRO_HS_SERIES_A, + GB_SVC_UNIPRO_SLOW_AUTO_MODE, + 1, 2, + GB_SVC_UNIPRO_SLOW_AUTO_MODE, + 1, 2, + 0, 0); + + return ret; +} + +static int gb_camera_set_power_mode(struct gb_camera *gcam, bool hs) +{ + struct gb_interface *intf = gcam->connection->intf; + struct gb_svc *svc = gcam->connection->hd->svc; + int ret; + + ret = gb_camera_set_intf_power_mode(gcam, intf->interface_id, hs); + if (ret < 0) { + gcam_err(gcam, "failed to set module interface to %s (%d)\n", + hs ? "HS" : "PWM", ret); + return ret; + } + + ret = gb_camera_set_intf_power_mode(gcam, svc->ap_intf_id, hs); + if (ret < 0) { + gcam_err(gcam, "failed to set AP interface to %s (%d)\n", + hs ? "HS" : "PWM", ret); + return ret; + } + + return 0; +} + struct ap_csi_config_request { __u8 csi_id; __u8 clock_mode; @@ -120,8 +168,6 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, unsigned int *flags, struct gb_camera_stream_config *streams) { - struct gb_interface *intf = gcam->connection->intf; - struct gb_svc *svc = gcam->connection->hd->svc; struct gb_camera_configure_streams_request *req; struct gb_camera_configure_streams_response *resp; struct ap_csi_config_request csi_cfg; @@ -151,49 +197,13 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, * before CSI interfaces gets configured */ if (nstreams && !(*flags & GB_CAMERA_CONFIGURE_STREAMS_TEST_ONLY)) { - ret = gb_svc_intf_set_power_mode(svc, intf->interface_id, - GB_SVC_UNIPRO_HS_SERIES_A, - GB_SVC_UNIPRO_FAST_MODE, 2, 2, - GB_SVC_UNIPRO_FAST_MODE, 2, 2, - GB_SVC_PWRM_RXTERMINATION | - GB_SVC_PWRM_TXTERMINATION, 0); - if (ret < 0) - goto done; - - ret = gb_svc_intf_set_power_mode(svc, svc->ap_intf_id, - GB_SVC_UNIPRO_HS_SERIES_A, - GB_SVC_UNIPRO_FAST_MODE, 2, 2, - GB_SVC_UNIPRO_FAST_MODE, 2, 2, - GB_SVC_PWRM_RXTERMINATION | - GB_SVC_PWRM_TXTERMINATION, 0); + ret = gb_camera_set_power_mode(gcam, true); if (ret < 0) goto done; } else if (nstreams == 0) { - ret = gb_svc_intf_set_power_mode(svc, intf->interface_id, - GB_SVC_UNIPRO_HS_SERIES_A, - GB_SVC_UNIPRO_SLOW_AUTO_MODE, - 1, 2, - GB_SVC_UNIPRO_SLOW_AUTO_MODE, - 1, 2, - 0, 0); - if (ret < 0) { - gcam_err(gcam, "can't take camera link to PWM-G1 auto: %d\n", - ret); - goto done; - } - - ret = gb_svc_intf_set_power_mode(svc, svc->ap_intf_id, - GB_SVC_UNIPRO_HS_SERIES_A, - GB_SVC_UNIPRO_SLOW_AUTO_MODE, - 1, 2, - GB_SVC_UNIPRO_SLOW_AUTO_MODE, - 1, 2, - 0, 0); - if (ret < 0) { - gcam_err(gcam, "can't take AP link to PWM-G1 auto: %d\n", - ret); + ret = gb_camera_set_power_mode(gcam, false); + if (ret < 0) goto done; - } } req->num_streams = nstreams; @@ -283,29 +293,7 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, return ret; set_unipro_slow_mode: - ret = gb_svc_intf_set_power_mode(svc, intf->interface_id, - GB_SVC_UNIPRO_HS_SERIES_A, - GB_SVC_UNIPRO_SLOW_AUTO_MODE, - 1, 2, - GB_SVC_UNIPRO_SLOW_AUTO_MODE, - 1, 2, - 0, 0); - if (ret < 0) { - gcam_err(gcam, "can't take camera link to PWM-G1 auto: %d\n", - ret); - goto done; - } - - ret = gb_svc_intf_set_power_mode(svc, svc->ap_intf_id, - GB_SVC_UNIPRO_HS_SERIES_A, - GB_SVC_UNIPRO_SLOW_AUTO_MODE, - 1, 2, - GB_SVC_UNIPRO_SLOW_AUTO_MODE, - 1, 2, - 0, 0); - if (ret < 0) - gcam_err(gcam, "can't take AP link to PWM-G1 auto: %d\n", - ret); + ret = gb_camera_set_power_mode(gcam, false); done: kfree(req); -- cgit v0.10.2 From b573b0e65616c1ae5c5dd2c14fd62d3ded3d5466 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 14 Feb 2016 02:33:05 +0200 Subject: greybus: camera: Clean up when AP link power mode configuration failed Restore the module link power mode to the previous state in that case. Signed-off-by: Laurent Pinchart Reviewed-by: Gjorgji Rosikopulos Tested-by: Jacopo Mondi Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 8383770..25dbf69 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -147,6 +147,7 @@ static int gb_camera_set_power_mode(struct gb_camera *gcam, bool hs) ret = gb_camera_set_intf_power_mode(gcam, svc->ap_intf_id, hs); if (ret < 0) { + gb_camera_set_intf_power_mode(gcam, intf->interface_id, !hs); gcam_err(gcam, "failed to set AP interface to %s (%d)\n", hs ? "HS" : "PWM", ret); return ret; -- cgit v0.10.2 From 66c3607076e7e801ab20077dc2d0ed45693eea10 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 14 Feb 2016 02:33:06 +0200 Subject: greybus: camera: Set power mode after configuring streams There's no need to set the power mode before configuring streams, doing it after simplifies code. Signed-off-by: Laurent Pinchart Reviewed-by: Gjorgji Rosikopulos Tested-by: Jacopo Mondi Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 25dbf69..7eef6ec 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -192,21 +192,6 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, goto done; } - /* - * Setup unipro link speed before actually issuing configuration - * to the camera module, to assure unipro network speed is set - * before CSI interfaces gets configured - */ - if (nstreams && !(*flags & GB_CAMERA_CONFIGURE_STREAMS_TEST_ONLY)) { - ret = gb_camera_set_power_mode(gcam, true); - if (ret < 0) - goto done; - } else if (nstreams == 0) { - ret = gb_camera_set_power_mode(gcam, false); - if (ret < 0) - goto done; - } - req->num_streams = nstreams; req->flags = *flags; req->padding = 0; @@ -224,19 +209,19 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, GB_CAMERA_TYPE_CONFIGURE_STREAMS, req, req_size, resp, resp_size); if (ret < 0) - goto set_unipro_slow_mode; + goto done; if (resp->num_streams > nstreams) { gcam_dbg(gcam, "got #streams %u > request %u\n", resp->num_streams, nstreams); ret = -EIO; - goto set_unipro_slow_mode; + goto done; } if (resp->padding != 0) { gcam_dbg(gcam, "response padding != 0"); ret = -EIO; - goto set_unipro_slow_mode; + goto done; } for (i = 0; i < nstreams; ++i) { @@ -253,14 +238,25 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, if (cfg->padding[0] || cfg->padding[1] || cfg->padding[2]) { gcam_dbg(gcam, "stream #%u padding != 0", i); ret = -EIO; - goto set_unipro_slow_mode; + goto done; } } if (nstreams && resp->flags & GB_CAMERA_CONFIGURE_STREAMS_ADJUSTED) { *flags = resp->flags; *num_streams = resp->num_streams; - goto set_unipro_slow_mode; + goto done; + } + + /* Setup unipro link speed. */ + if (nstreams && !(*flags & GB_CAMERA_CONFIGURE_STREAMS_TEST_ONLY)) { + ret = gb_camera_set_power_mode(gcam, true); + if (ret < 0) + goto done; + } else if (nstreams == 0) { + ret = gb_camera_set_power_mode(gcam, false); + if (ret < 0) + goto done; } memset(&csi_cfg, 0, sizeof(csi_cfg)); @@ -289,13 +285,6 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, *num_streams = resp->num_streams; ret = 0; - kfree(req); - kfree(resp); - return ret; - -set_unipro_slow_mode: - ret = gb_camera_set_power_mode(gcam, false); - done: kfree(req); kfree(resp); -- cgit v0.10.2 From 640924d2172da9b6f8a0c9372c3ea3b83f68e2f8 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 14 Feb 2016 02:33:07 +0200 Subject: greybus: camera: Don't configure CSI TX in test only mode When the GB_CAMERA_CONFIGURE_STREAMS_TEST_ONLY flag is set by the caller the configure streams operation should only test the requested settings without modifying the hardware state. This applies for both the module, the UniPro links power modes and the AP bridge settings. Return early when the flag is set to avoid modifying the AP bridge CSI TX settings. Signed-off-by: Laurent Pinchart Reviewed-by: Gjorgji Rosikopulos Tested-by: Jacopo Mondi Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 7eef6ec..bb8bc17 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -242,26 +242,21 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, } } - if (nstreams && resp->flags & GB_CAMERA_CONFIGURE_STREAMS_ADJUSTED) { + if ((resp->flags & GB_CAMERA_CONFIGURE_STREAMS_ADJUSTED) || + (*flags & GB_CAMERA_CONFIGURE_STREAMS_TEST_ONLY)) { *flags = resp->flags; *num_streams = resp->num_streams; goto done; } /* Setup unipro link speed. */ - if (nstreams && !(*flags & GB_CAMERA_CONFIGURE_STREAMS_TEST_ONLY)) { - ret = gb_camera_set_power_mode(gcam, true); - if (ret < 0) - goto done; - } else if (nstreams == 0) { - ret = gb_camera_set_power_mode(gcam, false); - if (ret < 0) - goto done; - } + ret = gb_camera_set_power_mode(gcam, nstreams != 0); + if (ret < 0) + goto done; + /* Configure the CSI transmitter. Hardcode the parameters for now. */ memset(&csi_cfg, 0, sizeof(csi_cfg)); - /* Configure the CSI transmitter. Hardcode the parameters for now. */ if (nstreams) { csi_cfg.csi_id = 1; csi_cfg.clock_mode = 0; -- cgit v0.10.2 From 4a7908cb71875991cabb2194c1c6b05cb97187ae Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 12 Feb 2016 21:48:03 +0530 Subject: greybus: manifest: Parse cports (within a bundle) in the order from manifest blob The order in which cports (of a bundle) are present in the manifest blob is important for gbsim, as it allocates hd_cport_id's for them sequentially. For example, if there are two cports (1 and 2, in order 1->2) present in a bundle in the manifest blob, then gbsim allocates hd_cport_id X and X+1 for them. This is done on the assumption that kernel will do the same. Though it shouldn't have had any such assumptions since the beginning. But with a recent patch that sequence is changed, and it broke the assumption gbsim had. While parsing the manifest blob, the cports within a bundle are now moved to another list using list_move() and then they are picked one by one from the HEAD of the list. list_move() first deletes the node and then adds it to HEAD as it uses list_add() and not list_add_tail(). And that reverses the order in which the cports were present in the original list. And because of this, the messages destined for cport 1 are delivered to cport 2 and the ones for cport 2 are delivered to cport 1. In order to get gbsim working with greybus, keep the cport list in the order in which they were present in manifest, by replacing list_move() with list_move_tail(). Its a trivial patch and shouldn't have any side effects on the working of greybus with nuttx. Signed-off-by: Viresh Kumar Reviewed-by: Alex Elder Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 74e3be9..070afc6 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -263,7 +263,7 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) goto exit; } } - list_move(&desc->links, &list); + list_move_tail(&desc->links, &list); count++; } -- cgit v0.10.2 From ee97e24ac63510c5836ac71ce88c9f61e265ee84 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Wed, 17 Feb 2016 01:27:52 +0530 Subject: greybus: arche-apb-ctrl: Do not coldboot APBs in probe Since parent driver (SVC) is controlling APBs directly, we do not need to bringup APBs in its own probe. Testing Done: Tested on EVT1.2. Signed-off-by: Vaibhav Hiremath Reviewed-by: Michael Scott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index b888da3..3086306 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -387,15 +387,6 @@ int arche_apb_ctrl_probe(struct platform_device *pdev) return ret; } - ret = coldboot_seq(pdev); - if (ret) { - dev_err(dev, "failed to set init state of control signal %d\n", - ret); - device_remove_file(dev, &dev_attr_state); - platform_set_drvdata(pdev, NULL); - return ret; - } - dev_info(&pdev->dev, "Device registered successfully\n"); return 0; } -- cgit v0.10.2 From b59281ac077414d879e66798f8e44eb976967814 Mon Sep 17 00:00:00 2001 From: Axel Haslam Date: Wed, 10 Feb 2016 14:19:29 +0100 Subject: greybus: loopback: Add reserved fields to transfer request All loopback transfer operations should have an identical header format in order to facilitate bandwidth and data movement analysis. Suggested-by: Bryan O'Donoghue Signed-off-by: Axel Haslam Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index cd64ac8..6b19292 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -1053,8 +1053,14 @@ struct gb_uart_serial_state_request { #define GB_LOOPBACK_TYPE_TRANSFER 0x03 #define GB_LOOPBACK_TYPE_SINK 0x04 +/* + * Loopback request/response header format should be identical + * to simplify bandwidth and data movement analysis. + */ struct gb_loopback_transfer_request { __le32 len; + __le32 reserved0; + __le32 reserved1; __u8 data[0]; } __packed; -- cgit v0.10.2 From 478ce7203c2cf3f241f11587717336a60d391269 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 17 Feb 2016 19:30:40 +0100 Subject: greybus: es2: fix cport-count error handling Make sure to check for short transfers when retrieving the bridge cport count. Also clear the request buffer when allocating it. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index e39bd58..5ade51e 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -861,7 +861,7 @@ static int apb_get_cport_count(struct usb_device *udev) int retval; __le16 *cport_count; - cport_count = kmalloc(sizeof(*cport_count), GFP_KERNEL); + cport_count = kzalloc(sizeof(*cport_count), GFP_KERNEL); if (!cport_count) return -ENOMEM; @@ -870,9 +870,13 @@ static int apb_get_cport_count(struct usb_device *udev) USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0, 0, cport_count, sizeof(*cport_count), ES2_TIMEOUT); - if (retval < 0) { + if (retval != sizeof(*cport_count)) { dev_err(&udev->dev, "Cannot retrieve CPort count: %d\n", retval); + + if (retval >= 0) + retval = -EIO; + goto out; } -- cgit v0.10.2 From c53b0b27d57cc1dff50080c911b48b2af7728dc4 Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Wed, 17 Feb 2016 18:21:06 +0100 Subject: greybus: gb_loopback: Fix throughput calculations Throughput and requests per second calculations are broken for asynchronous request. Instead of calculate the throughput for each iteration, calculate it once at the end of the test. Signed-off-by: Alexandre Bailon Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index f3ae2e9..c022edb 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -81,6 +81,7 @@ struct gb_loopback { atomic_t outstanding_operations; /* Per connection stats */ + struct timeval ts; struct gb_loopback_stats latency; struct gb_loopback_stats throughput; struct gb_loopback_stats requests_per_second; @@ -520,7 +521,6 @@ static void gb_loopback_async_operation_callback(struct gb_operation *operation) gb_loopback_push_latency_ts(gb, &op_async->ts, &te); gb->elapsed_nsecs = gb_loopback_calc_latency(&op_async->ts, &te); - gb_loopback_calculate_stats(gb); } if (op_async->pending) { @@ -529,6 +529,7 @@ static void gb_loopback_async_operation_callback(struct gb_operation *operation) del_timer_sync(&op_async->timer); gb_loopback_async_operation_put(op_async); } + gb_loopback_calculate_stats(gb); mutex_unlock(&gb->mutex); dev_dbg(&gb->connection->bundle->dev, "complete operation %d\n", @@ -846,6 +847,7 @@ static void gb_loopback_reset_stats(struct gb_loopback *gb) /* Should be initialized at least once per transaction set */ gb->apbridge_latency_ts = 0; gb->gpbridge_latency_ts = 0; + memset(&gb->ts, 0, sizeof(struct timeval)); } static void gb_loopback_update_stats(struct gb_loopback_stats *stats, u32 val) @@ -860,15 +862,15 @@ static void gb_loopback_update_stats(struct gb_loopback_stats *stats, u32 val) static void gb_loopback_requests_update(struct gb_loopback *gb, u32 latency) { - u32 req = USEC_PER_SEC; + u64 req = gb->requests_completed * USEC_PER_SEC; do_div(req, latency); - gb_loopback_update_stats(&gb->requests_per_second, req); + gb_loopback_update_stats(&gb->requests_per_second, (u32)req); } static void gb_loopback_throughput_update(struct gb_loopback *gb, u32 latency) { - u32 throughput; + u64 throughput; u32 aggregate_size = sizeof(struct gb_operation_msg_hdr) * 2; switch (gb->type) { @@ -887,14 +889,13 @@ static void gb_loopback_throughput_update(struct gb_loopback *gb, u32 latency) return; } - /* Calculate bytes per second */ - throughput = USEC_PER_SEC; + aggregate_size *= gb->requests_completed; + throughput = aggregate_size * USEC_PER_SEC; do_div(throughput, latency); - throughput *= aggregate_size; - gb_loopback_update_stats(&gb->throughput, throughput); + gb_loopback_update_stats(&gb->throughput, (u32)throughput); } -static void gb_loopback_calculate_stats(struct gb_loopback *gb) +static void gb_loopback_calculate_latency_stats(struct gb_loopback *gb) { u32 lat; @@ -907,10 +908,6 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb) /* Raw latency log on a per thread basis */ kfifo_in(&gb->kfifo_lat, (unsigned char *)&lat, sizeof(lat)); - /* Log throughput and requests using latency as benchmark */ - gb_loopback_throughput_update(gb, lat); - gb_loopback_requests_update(gb, lat); - /* Log the firmware supplied latency values */ gb_loopback_update_stats(&gb->apbridge_unipro_latency, gb->apbridge_latency_ts); @@ -918,6 +915,27 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb) gb->gpbridge_latency_ts); } +static void gb_loopback_calculate_stats(struct gb_loopback *gb) +{ + u64 nlat; + u32 lat; + struct timeval te; + + gb_loopback_calculate_latency_stats(gb); + + if (gb->iteration_count == gb->iteration_max) { + do_gettimeofday(&te); + nlat = gb_loopback_calc_latency(&gb->ts, &te); + lat = gb_loopback_nsec_to_usec_latency(nlat); + + gb_loopback_throughput_update(gb, lat); + gb_loopback_requests_update(gb, lat); + + memset(&gb->ts, 0, sizeof(struct timeval)); + gb->type = 0; + } +} + static void gb_loopback_async_wait_to_send(struct gb_loopback *gb) { if (!(gb->async && gb->outstanding_operations_max)) @@ -955,8 +973,10 @@ static int gb_loopback_fn(void *data) /* Optionally terminate */ if (send_count == gb->iteration_max) { - gb->type = 0; - send_count = 0; + if (!gb->async) + send_count = 0; + else if (gb->iteration_count == gb->iteration_max) + send_count = 0; mutex_unlock(&gb->mutex); continue; } @@ -965,10 +985,15 @@ static int gb_loopback_fn(void *data) type = gb->type; mutex_unlock(&gb->mutex); + if (gb->ts.tv_usec == 0 && gb->ts.tv_sec == 0) + do_gettimeofday(&gb->ts); + /* Else operations to perform */ if (gb->async) { if (type == GB_LOOPBACK_TYPE_PING) { error = gb_loopback_async_ping(gb); + if (!error) + gb->requests_completed++; gb_loopback_calculate_stats(gb); } else if (type == GB_LOOPBACK_TYPE_TRANSFER) { error = gb_loopback_async_transfer(gb, size); @@ -989,6 +1014,8 @@ static int gb_loopback_fn(void *data) if (error) gb->error++; + else + gb->requests_completed++; gb->iteration_count++; gb_loopback_calculate_stats(gb); } -- cgit v0.10.2 From 492331435465977407e43865c19e34918cd90a66 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Wed, 17 Feb 2016 14:32:51 +0000 Subject: greybus: lights: remove unnecessary checks We do not need to check for channels and lights as they can never be NULL as a big memory array elements. Signed-off-by: Rui Miguel Silva Reported-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index 70fcade..6c5b999 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -1026,9 +1026,6 @@ static void gb_lights_channel_free(struct gb_channel *channel) static void gb_lights_channel_release(struct gb_channel *channel) { - if (!channel) - return; - channel->releasing = true; gb_lights_channel_unregister(channel); @@ -1041,8 +1038,6 @@ static void gb_lights_light_release(struct gb_light *light) int i; int count; - if (!light) - return; count = light->channels_count; -- cgit v0.10.2 From 137f717942c9cff82484ee90647881d9c524178f Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Wed, 17 Feb 2016 14:32:52 +0000 Subject: greybus: lights: remove has_flash on failure If register to v4l2 fails just mark the light as not having flash so in release we do not try to unregister. Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index 6c5b999..4c46d14 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -1004,8 +1004,10 @@ static int gb_lights_light_register(struct gb_light *light) if (light->has_flash) { ret = gb_lights_light_v4l2_register(light); - if (ret < 0) + if (ret < 0) { + light->has_flash = false; return ret; + } } return 0; -- cgit v0.10.2 From c6ad27a98ce5f9718c7235cf02de2055897f56d5 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Wed, 17 Feb 2016 14:32:53 +0000 Subject: greybus: lights: fix check for configured lights The validation for a complete configured light is wrong and it is reworked to make sure that only when the light is ready, will handle request events. Signed-off-by: Rui Miguel Silva Reported-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index 4c46d14..17877f7 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -55,6 +55,7 @@ struct gb_light { u8 channels_count; struct gb_channel *channels; bool has_flash; + bool ready; #ifdef V4L2_HAVE_FLASH struct v4l2_flash *v4l2_flash; #endif @@ -1002,6 +1003,8 @@ static int gb_lights_light_register(struct gb_light *light) return ret; } + light->ready = true; + if (light->has_flash) { ret = gb_lights_light_v4l2_register(light); if (ret < 0) { @@ -1040,6 +1043,7 @@ static void gb_lights_light_release(struct gb_light *light) int i; int count; + light->ready = false; count = light->channels_count; @@ -1174,7 +1178,8 @@ static int gb_lights_request_handler(struct gb_operation *op) payload = request->payload; light_id = payload->light_id; - if (light_id >= glights->lights_count || !&glights->lights[light_id]) { + if (light_id >= glights->lights_count || !glights->lights || + !glights->lights[light_id].ready) { dev_err(dev, "Event received for unconfigured light id: %d\n", light_id); return -EINVAL; -- cgit v0.10.2 From b19df7b9950cd8c1212dcc775dffcdaace391db3 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal Date: Tue, 16 Feb 2016 00:27:27 +0530 Subject: greybus: audio: Enable support for multiple codec modules Update params, sequence in response to changes in msm8994 helper APIs Signed-off-by: Vaibhav Agarwal Reviewed-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index c05ab4f..cabe289 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -430,65 +430,6 @@ static unsigned int gbcodec_read(struct snd_soc_codec *codec, return val; } -static struct snd_soc_codec_driver soc_codec_dev_gbcodec = { - .probe = gbcodec_probe, - .remove = gbcodec_remove, - - .read = gbcodec_read, - .write = gbcodec_write, - - .reg_cache_size = GBCODEC_REG_COUNT, - .reg_cache_default = gbcodec_reg_defaults, - .reg_word_size = 1, - - .idle_bias_off = true, - .ignore_pmdown_time = 1, -}; - -/* - * GB codec DAI link related - */ -static struct snd_soc_dai_link gbaudio_dailink = { - .name = "PRI_MI2S_RX", - .stream_name = "Primary MI2S Playback", - .platform_name = "msm-pcm-routing", - .cpu_dai_name = "msm-dai-q6-mi2s.0", - .no_pcm = 1, - .be_id = 34, -}; - -static int gbaudio_add_dailinks(struct gbaudio_codec_info *gbcodec) -{ - int ret, i; - char *dai_link_name; - struct snd_soc_dai_link *dailink; - struct device *dev = gbcodec->dev; - - dailink = &gbaudio_dailink; - dailink->codec_name = gbcodec->name; - - /* FIXME - * allocate memory for DAI links based on count. - * currently num_dai_links=1, so using static struct - */ - gbcodec->num_dai_links = 1; - - for (i = 0; i < gbcodec->num_dai_links; i++) { - gbcodec->dailink_name[i] = dai_link_name = - devm_kzalloc(dev, NAME_SIZE, GFP_KERNEL); - snprintf(dai_link_name, NAME_SIZE, "GB %d.%d PRI_MI2S_RX", - gbcodec->dev_id, i); - dailink->name = dai_link_name; - dailink->codec_dai_name = gbcodec->dais[i].name; - } - - ret = msm8994_add_dailink("msm8994-tomtom-mtp-snd-card", dailink, 1); - if (ret) - dev_err(dev, "%d:Error while adding DAI link\n", ret); - - return ret; -} - /* * gb_snd management functions */ @@ -542,12 +483,21 @@ static int gbaudio_register_codec(struct gbaudio_codec_info *gbcodec) int ret, i; struct device *dev = gbcodec->dev; struct gb_connection *connection = gbcodec->mgmt_connection; + struct snd_soc_codec_driver *soc_codec_dev_gbcodec; /* * FIXME: malloc for topology happens via audio_gb driver * should be done within codec driver itself */ struct gb_audio_topology *topology; + soc_codec_dev_gbcodec = devm_kzalloc(gbcodec->dev, + sizeof(*soc_codec_dev_gbcodec), + GFP_KERNEL); + if (!soc_codec_dev_gbcodec) { + dev_err(gbcodec->dev, "Malloc failed for codec_driver\n"); + return -ENOMEM; + } + ret = gb_connection_enable(connection); if (ret) { dev_err(dev, "%d: Error while enabling mgmt connection\n", ret); @@ -572,19 +522,32 @@ static int gbaudio_register_codec(struct gbaudio_codec_info *gbcodec) gbcodec->topology = topology; /* update codec info */ - soc_codec_dev_gbcodec.controls = gbcodec->kctls; - soc_codec_dev_gbcodec.num_controls = gbcodec->num_kcontrols; - soc_codec_dev_gbcodec.dapm_widgets = gbcodec->widgets; - soc_codec_dev_gbcodec.num_dapm_widgets = gbcodec->num_dapm_widgets; - soc_codec_dev_gbcodec.dapm_routes = gbcodec->routes; - soc_codec_dev_gbcodec.num_dapm_routes = gbcodec->num_dapm_routes; + soc_codec_dev_gbcodec->probe = gbcodec_probe, + soc_codec_dev_gbcodec->remove = gbcodec_remove, + + soc_codec_dev_gbcodec->read = gbcodec_read, + soc_codec_dev_gbcodec->write = gbcodec_write, + + soc_codec_dev_gbcodec->reg_cache_size = GBCODEC_REG_COUNT, + soc_codec_dev_gbcodec->reg_cache_default = gbcodec_reg_defaults, + soc_codec_dev_gbcodec->reg_word_size = 1, + + soc_codec_dev_gbcodec->idle_bias_off = true, + soc_codec_dev_gbcodec->ignore_pmdown_time = 1, + + soc_codec_dev_gbcodec->controls = gbcodec->kctls; + soc_codec_dev_gbcodec->num_controls = gbcodec->num_kcontrols; + soc_codec_dev_gbcodec->dapm_widgets = gbcodec->widgets; + soc_codec_dev_gbcodec->num_dapm_widgets = gbcodec->num_dapm_widgets; + soc_codec_dev_gbcodec->dapm_routes = gbcodec->routes; + soc_codec_dev_gbcodec->num_dapm_routes = gbcodec->num_dapm_routes; /* update DAI info */ for (i = 0; i < gbcodec->num_dais; i++) gbcodec->dais[i].ops = &gbcodec_dai_ops; /* register codec */ - ret = snd_soc_register_codec(dev, &soc_codec_dev_gbcodec, + ret = snd_soc_register_codec(dev, soc_codec_dev_gbcodec, gbcodec->dais, 1); if (ret) { dev_err(dev, "%d:Failed to register codec\n", ret); @@ -592,11 +555,13 @@ static int gbaudio_register_codec(struct gbaudio_codec_info *gbcodec) } /* update DAI links in response to this codec */ - ret = gbaudio_add_dailinks(gbcodec); + ret = msm8994_add_dailink("msm8994-tomtom-mtp-snd-card", gbcodec->name, + gbcodec->dais[0].name, 1); if (ret) { dev_err(dev, "%d: Failed to add DAI links\n", ret); goto add_dailink_err; } + gbcodec->num_dai_links = 1; return 0; @@ -615,8 +580,8 @@ tplg_fetch_err: static void gbaudio_unregister_codec(struct gbaudio_codec_info *gbcodec) { gb_audio_cleanup(gbcodec); - msm8994_remove_dailink("msm8994-tomtom-mtp-snd-card", &gbaudio_dailink, - 1); + msm8994_remove_dailink("msm8994-tomtom-mtp-snd-card", gbcodec->name, + gbcodec->dais[0].name, 1); snd_soc_unregister_codec(gbcodec->dev); gbaudio_tplg_release(gbcodec); kfree(gbcodec->topology); @@ -792,7 +757,7 @@ static int gb_audio_probe(struct gb_bundle *bundle, gbcodec->manager_id = gb_audio_manager_add(&desc); atomic_set(&gbcodec->is_connected, 1); - list_add(&gbcodec->list, &gb_codec_list); + list_add_tail(&gbcodec->list, &gb_codec_list); dev_dbg(dev, "Add GB Audio device:%s\n", gbcodec->name); mutex_unlock(&gb_codec_list_lock); @@ -826,7 +791,6 @@ static void gb_audio_disconnect(struct gb_bundle *bundle) mutex_lock(&gb_codec_list_lock); atomic_set(&gbcodec->is_connected, 0); - list_del(&gbcodec->list); /* inform uevent to above layers */ gb_audio_manager_remove(gbcodec->manager_id); @@ -842,6 +806,7 @@ static void gb_audio_disconnect(struct gb_bundle *bundle) } gb_connection_destroy(gbcodec->mgmt_connection); gbcodec->mgmt_connection = NULL; + list_del(&gbcodec->list); mutex_unlock(&gbcodec->lock); devm_kfree(&bundle->dev, gbcodec); -- cgit v0.10.2 From 29386f058a758f5ef6e8a522101fcbfd0ef07a19 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal Date: Tue, 16 Feb 2016 00:27:28 +0530 Subject: greybus: audio: schedule workqueue to perform codec cleanup on module removal In response to codec module removal, user space is reported about the event. In response to this, ALSA layer will update DAPM route and cleanup DAPM states. As a fallback mechanism, kernel can cleanup the DAPM state for codec module. But, this would cause immediate playback (first trial) to fail, since DSP is still in inconsistent state. To avoid such situation, a workqueue is scheduled for codec cleanup with timeout=50ms. Thus, normally it is expected from above layers to update routes and perform cleanup. However, fallback mechanism still holds good after 50ms. Signed-off-by: Vaibhav Agarwal Reviewed-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index cabe289..25b1042 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -80,11 +80,7 @@ static void gbcodec_shutdown(struct snd_pcm_substream *substream, struct gbaudio_dai *gb_dai; struct gbaudio_codec_info *gb = dev_get_drvdata(dai->dev); - if (!atomic_read(&gb->is_connected)) - return; - /* find the dai */ - mutex_lock(&gb->lock); gb_dai = gbaudio_find_dai(gb, -1, dai->name); if (!gb_dai) { dev_err(dai->dev, "%s: DAI not registered\n", dai->name); @@ -93,6 +89,13 @@ static void gbcodec_shutdown(struct snd_pcm_substream *substream, atomic_dec(&gb_dai->users); + if (!atomic_read(&gb->is_connected)) { + if (!atomic_read(&gb_dai->users)) + wake_up_interruptible(&gb_dai->wait_queue); + return; + } + + mutex_lock(&gb->lock); /* deactivate rx/tx */ cportid = gb_dai->connection->intf_cport_id; @@ -121,6 +124,11 @@ static void gbcodec_shutdown(struct snd_pcm_substream *substream, func_exit: mutex_unlock(&gb->lock); + /* + if (!atomic_read(&gb_dai->users)) + wake_up_interruptible(&gb_dai->wait_queue); + */ + return; } @@ -290,8 +298,11 @@ static int gbcodec_trigger(struct snd_pcm_substream *substream, int cmd, struct gbaudio_dai *gb_dai; struct gbaudio_codec_info *gb = dev_get_drvdata(dai->dev); - if (!atomic_read(&gb->is_connected)) + if (!atomic_read(&gb->is_connected)) { + if (cmd == SNDRV_PCM_TRIGGER_STOP) + return 0; return -ENODEV; + } /* find the dai */ mutex_lock(&gb->lock); @@ -443,9 +454,10 @@ static unsigned int gbcodec_read(struct snd_soc_codec *codec, */ static void gb_audio_cleanup(struct gbaudio_codec_info *gb) { - int cportid, ret; + int cportid, ret, timeout_result; struct gbaudio_dai *gb_dai; struct gb_connection *connection; + long timeout = msecs_to_jiffies(50); /* 50ms */ struct device *dev = gb->dev; list_for_each_entry(gb_dai, &gb->dai_list, list) { @@ -454,6 +466,16 @@ static void gb_audio_cleanup(struct gbaudio_codec_info *gb) * manually */ if (atomic_read(&gb_dai->users)) { + /* schedule a wait event */ + timeout_result = + wait_event_interruptible_timeout( + gb_dai->wait_queue, + !atomic_read(&gb_dai->users), + timeout); + if (!timeout_result) + dev_warn(dev, "%s:DAI still in use.\n", + gb_dai->name); + connection = gb_dai->connection; /* PB active */ ret = gb_audio_apbridgea_stop_tx(connection, 0); @@ -473,7 +495,6 @@ static void gb_audio_cleanup(struct gbaudio_codec_info *gb) if (ret) dev_info(dev, "%d:Failed during unregister cport\n", ret); - atomic_dec(&gb_dai->users); } } } @@ -655,6 +676,7 @@ static int gb_audio_add_data_connection(struct gbaudio_codec_info *gbcodec, connection->private = gbcodec; atomic_set(&dai->users, 0); + init_waitqueue_head(&dai->wait_queue); dai->data_cport = connection->intf_cport_id; dai->connection = connection; list_add(&dai->list, &gbcodec->dai_list); diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index 4c19bd8..fc60c36 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -88,6 +88,7 @@ struct gbaudio_dai { atomic_t users; struct gb_connection *connection; struct list_head list; + wait_queue_head_t wait_queue; }; struct gbaudio_codec_info { -- cgit v0.10.2 From b07868bda2fb61b784dc260dd075d84ac994d599 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal Date: Tue, 16 Feb 2016 22:16:33 +0530 Subject: greybus: audio: return success for stop trigger if device removed In case GB codec module is already removed, no action is required at the HW level. Thus, report SUCCESS to above layer. Reporting error to above layer will cause repeated trials and won't allow to update DPCM connections. Signed-off-by: Vaibhav Agarwal Reviewed-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 25b1042..d820116 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -362,6 +362,10 @@ static int gbcodec_trigger(struct snd_pcm_substream *substream, int cmd, dev_err(dai->dev, "%d:Error during %s stream\n", ret, start ? "Start" : "Stop"); + /* in case device removed, return 0 for stop trigger */ + if (stop && (ret == -ENODEV)) + ret = 0; + func_exit: mutex_unlock(&gb->lock); return ret; -- cgit v0.10.2 From 2422d36696f36ea92f17bb34a129a74f9b173891 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 17 Feb 2016 16:30:38 -0800 Subject: greybus: Revert "gb_loopback: Fix throughput calculations" This reverts commit 9b9b046af237f5674c2f7ca991dc62332b2d4041 Bryan wants more feedback first. Reported-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index c022edb..f3ae2e9 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -81,7 +81,6 @@ struct gb_loopback { atomic_t outstanding_operations; /* Per connection stats */ - struct timeval ts; struct gb_loopback_stats latency; struct gb_loopback_stats throughput; struct gb_loopback_stats requests_per_second; @@ -521,6 +520,7 @@ static void gb_loopback_async_operation_callback(struct gb_operation *operation) gb_loopback_push_latency_ts(gb, &op_async->ts, &te); gb->elapsed_nsecs = gb_loopback_calc_latency(&op_async->ts, &te); + gb_loopback_calculate_stats(gb); } if (op_async->pending) { @@ -529,7 +529,6 @@ static void gb_loopback_async_operation_callback(struct gb_operation *operation) del_timer_sync(&op_async->timer); gb_loopback_async_operation_put(op_async); } - gb_loopback_calculate_stats(gb); mutex_unlock(&gb->mutex); dev_dbg(&gb->connection->bundle->dev, "complete operation %d\n", @@ -847,7 +846,6 @@ static void gb_loopback_reset_stats(struct gb_loopback *gb) /* Should be initialized at least once per transaction set */ gb->apbridge_latency_ts = 0; gb->gpbridge_latency_ts = 0; - memset(&gb->ts, 0, sizeof(struct timeval)); } static void gb_loopback_update_stats(struct gb_loopback_stats *stats, u32 val) @@ -862,15 +860,15 @@ static void gb_loopback_update_stats(struct gb_loopback_stats *stats, u32 val) static void gb_loopback_requests_update(struct gb_loopback *gb, u32 latency) { - u64 req = gb->requests_completed * USEC_PER_SEC; + u32 req = USEC_PER_SEC; do_div(req, latency); - gb_loopback_update_stats(&gb->requests_per_second, (u32)req); + gb_loopback_update_stats(&gb->requests_per_second, req); } static void gb_loopback_throughput_update(struct gb_loopback *gb, u32 latency) { - u64 throughput; + u32 throughput; u32 aggregate_size = sizeof(struct gb_operation_msg_hdr) * 2; switch (gb->type) { @@ -889,13 +887,14 @@ static void gb_loopback_throughput_update(struct gb_loopback *gb, u32 latency) return; } - aggregate_size *= gb->requests_completed; - throughput = aggregate_size * USEC_PER_SEC; + /* Calculate bytes per second */ + throughput = USEC_PER_SEC; do_div(throughput, latency); - gb_loopback_update_stats(&gb->throughput, (u32)throughput); + throughput *= aggregate_size; + gb_loopback_update_stats(&gb->throughput, throughput); } -static void gb_loopback_calculate_latency_stats(struct gb_loopback *gb) +static void gb_loopback_calculate_stats(struct gb_loopback *gb) { u32 lat; @@ -908,6 +907,10 @@ static void gb_loopback_calculate_latency_stats(struct gb_loopback *gb) /* Raw latency log on a per thread basis */ kfifo_in(&gb->kfifo_lat, (unsigned char *)&lat, sizeof(lat)); + /* Log throughput and requests using latency as benchmark */ + gb_loopback_throughput_update(gb, lat); + gb_loopback_requests_update(gb, lat); + /* Log the firmware supplied latency values */ gb_loopback_update_stats(&gb->apbridge_unipro_latency, gb->apbridge_latency_ts); @@ -915,27 +918,6 @@ static void gb_loopback_calculate_latency_stats(struct gb_loopback *gb) gb->gpbridge_latency_ts); } -static void gb_loopback_calculate_stats(struct gb_loopback *gb) -{ - u64 nlat; - u32 lat; - struct timeval te; - - gb_loopback_calculate_latency_stats(gb); - - if (gb->iteration_count == gb->iteration_max) { - do_gettimeofday(&te); - nlat = gb_loopback_calc_latency(&gb->ts, &te); - lat = gb_loopback_nsec_to_usec_latency(nlat); - - gb_loopback_throughput_update(gb, lat); - gb_loopback_requests_update(gb, lat); - - memset(&gb->ts, 0, sizeof(struct timeval)); - gb->type = 0; - } -} - static void gb_loopback_async_wait_to_send(struct gb_loopback *gb) { if (!(gb->async && gb->outstanding_operations_max)) @@ -973,10 +955,8 @@ static int gb_loopback_fn(void *data) /* Optionally terminate */ if (send_count == gb->iteration_max) { - if (!gb->async) - send_count = 0; - else if (gb->iteration_count == gb->iteration_max) - send_count = 0; + gb->type = 0; + send_count = 0; mutex_unlock(&gb->mutex); continue; } @@ -985,15 +965,10 @@ static int gb_loopback_fn(void *data) type = gb->type; mutex_unlock(&gb->mutex); - if (gb->ts.tv_usec == 0 && gb->ts.tv_sec == 0) - do_gettimeofday(&gb->ts); - /* Else operations to perform */ if (gb->async) { if (type == GB_LOOPBACK_TYPE_PING) { error = gb_loopback_async_ping(gb); - if (!error) - gb->requests_completed++; gb_loopback_calculate_stats(gb); } else if (type == GB_LOOPBACK_TYPE_TRANSFER) { error = gb_loopback_async_transfer(gb, size); @@ -1014,8 +989,6 @@ static int gb_loopback_fn(void *data) if (error) gb->error++; - else - gb->requests_completed++; gb->iteration_count++; gb_loopback_calculate_stats(gb); } -- cgit v0.10.2 From 907d1e16ffe4ea50a9bdf1c644fd48ce6a126e4f Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 19 Feb 2016 15:57:46 +0530 Subject: greybus: interface: Add print messages on interface initialization/removal It might be of interest (to developers at least) to know when an interface is getting created or removed from the system. Interface creation message can further contain basic information about the interface, like its vid/pid and mfg/prod ids. Now, the interface is created by gb_interface_create(), which doesn't register the intf->dev to the kernel and so the print message is rather added to gb_interface_init() where we register the device with the kernel. A similar message is added to gb_interface_remove() only when the interface was earlier initialized. And this is how the output looks on real insertion/removal of the module: greybus 1-1: Interface added: VID=0x00000001, PID=0x00000001 greybus 1-1: DDBL1 Manufacturer=0x00000001, Product=0x00000001 ... greybus 1-1: Interface removed Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 6c815db..5e49bc8 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -174,8 +174,10 @@ void gb_interface_remove(struct gb_interface *intf) list_for_each_entry_safe(bundle, next, &intf->bundles, links) gb_bundle_destroy(bundle); - if (device_is_registered(&intf->dev)) + if (device_is_registered(&intf->dev)) { device_del(&intf->dev); + dev_info(&intf->dev, "Interface removed\n"); + } gb_control_disable(intf->control); @@ -260,6 +262,11 @@ int gb_interface_init(struct gb_interface *intf, u8 device_id) goto free_manifest; } + dev_info(&intf->dev, "Interface added: VID=0x%08x, PID=0x%08x\n", + intf->vendor_id, intf->product_id); + dev_info(&intf->dev, "DDBL1 Manufacturer=0x%08x, Product=0x%08x\n", + intf->ddbl1_manufacturer_id, intf->ddbl1_product_id); + list_for_each_entry_safe_reverse(bundle, tmp, &intf->bundles, links) { ret = gb_bundle_add(bundle); if (ret) { -- cgit v0.10.2 From 737df280a73b9e9d3d24cd8e81637b0496f06dde Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 22 Feb 2016 18:50:53 +0100 Subject: greybus: Documentation: remove svc unique_id attribute Remove unimplemented svc unique_id attribute from the documentation. This attribute made more sense when we thought we'd have an AP-module, unlike now when the AP and SVC are both part of the same frame. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 4493605..17b1a29 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -150,13 +150,6 @@ Description: Write the number of the interface that you wish to forcibly eject from the system. -What: /sys/bus/greybus/device/N-svc/unique_id -Date: October 2015 -KernelVersion: 4.XX -Contact: Greg Kroah-Hartman -Description: - The unique ID, or serial number, of the SVC device - What: /sys/bus/greybus/device/N-svc/version Date: October 2015 KernelVersion: 4.XX diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-svc/unique_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-svc/unique_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-svc/unique_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-svc/unique_id deleted file mode 100644 index e69de29..0000000 -- cgit v0.10.2 From 7f29aded453e0392391b831c196583c274ec2cfd Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 22 Feb 2016 18:14:46 -0800 Subject: greybus: uart: properly calculate max buffer size We forgot to count the size of the uart send data message header when calculating the maximum size of the buffer that the uart driver could send in one chunk. This fixes the math and makes the variable a size_t to match the return value of the call to gb_operation_get_payload_size_max(); Reported-by: Axel Haslam Signed-off-by: Greg Kroah-Hartman Tested-by: Axel Haslam Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 46cce8c..52cc9d5 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -43,7 +43,7 @@ struct gb_tty_line_coding { struct gb_tty { struct tty_port port; void *buffer; - u32 buffer_payload_max; + size_t buffer_payload_max; struct gb_connection *connection; u16 cport_id; unsigned int minor; @@ -608,11 +608,8 @@ static int gb_uart_connection_init(struct gb_connection *connection) } gb_tty->buffer_payload_max = - gb_operation_get_payload_size_max(connection); - if (!gb_tty->buffer_payload_max) { - retval = -EINVAL; - goto error_payload; - } + gb_operation_get_payload_size_max(connection) - + sizeof(struct gb_uart_send_data_request); gb_tty->buffer = kzalloc(gb_tty->buffer_payload_max, GFP_KERNEL); if (!gb_tty->buffer) { -- cgit v0.10.2 From 446091c999388f9365e8d206f70b0c1a860212a0 Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Tue, 23 Feb 2016 11:22:48 +0100 Subject: greybus: camera: Add CSI configuration parameters Add CSI configuration parameters to the configure_stream operation response. Currently, only the total number of lines in a second is used to configure the the AP-Bridge CSI transmitter, all other parameters (number of CSI data lanes, and CSI bus clock frequency) are kept hard-coded for two reasons: 1) We need to configure the CSI receiver on AP side accordingly to these settings, before sending them to APB1 CSI transmitter. 2) We cannot use the camera module provided parameters as-is, but use those information to compute the required bandwidth on the CSI bus, and configure the # of CSI data lanes, and the CSI bus clock speed in a way that satisfies that bandwidth requirement. Signed-off-by: Jacopo Mondi Acked-by: Laurent Pinchart Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index bb8bc17..3f205cb 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -162,6 +162,7 @@ struct ap_csi_config_request { __u8 num_lanes; __u8 padding; __le32 bus_freq; + __le32 lines_per_second; } __packed; static int gb_camera_configure_streams(struct gb_camera *gcam, @@ -254,7 +255,14 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, if (ret < 0) goto done; - /* Configure the CSI transmitter. Hardcode the parameters for now. */ + /* + * Configure the APB1 CSI transmitter using the lines count reported by + * the camera module, but with hard-coded bus frequency and lanes number. + * + * TODO: use the clocking and size informations reported by camera module + * to compute the required CSI bandwidth, and configure the CSI receiver + * on AP side, and the CSI transmitter on APB1 side accordingly. + */ memset(&csi_cfg, 0, sizeof(csi_cfg)); if (nstreams) { @@ -262,6 +270,7 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, csi_cfg.clock_mode = 0; csi_cfg.num_lanes = 4; csi_cfg.bus_freq = cpu_to_le32(960000000); + csi_cfg.lines_per_second = resp->lines_per_second; ret = gb_hd_output(gcam->connection->hd, &csi_cfg, sizeof(csi_cfg), GB_APB_REQUEST_CSI_TX_CONTROL, false); diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 6b19292..1a90dc2 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -1276,7 +1276,10 @@ struct gb_camera_configure_streams_response { __u8 num_streams; __u8 flags; #define GB_CAMERA_CONFIGURE_STREAMS_ADJUSTED 0x01 - __le16 padding; + __u8 num_lanes; + __u8 padding; + __le32 bus_freq; + __le32 lines_per_second; struct gb_camera_stream_config_response config[0]; } __packed; -- cgit v0.10.2 From 27e18d8c6967f554b374a713c6bd21bcc985389b Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Tue, 23 Feb 2016 11:22:49 +0100 Subject: greybus: camera: Rename clock_mode to flags Rename the 'clock_mode' parameter to a more generic 'flags' in the csi bus configuration structure. Define flags value for continuous clock mode. Signed-off-by: Jacopo Mondi Acked-by: Laurent Pinchart Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 3f205cb..444e218 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -158,7 +158,8 @@ static int gb_camera_set_power_mode(struct gb_camera *gcam, bool hs) struct ap_csi_config_request { __u8 csi_id; - __u8 clock_mode; + __u8 flags; +#define GB_CAMERA_CSI_FLAG_CLOCK_CONTINUOUS 0x01 __u8 num_lanes; __u8 padding; __le32 bus_freq; @@ -267,7 +268,7 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, if (nstreams) { csi_cfg.csi_id = 1; - csi_cfg.clock_mode = 0; + csi_cfg.flags = 0; csi_cfg.num_lanes = 4; csi_cfg.bus_freq = cpu_to_le32(960000000); csi_cfg.lines_per_second = resp->lines_per_second; -- cgit v0.10.2 From 599159b6877e665b086d6e3092203c651b8a3952 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Mon, 22 Feb 2016 17:27:24 +0530 Subject: greybus: arche-platform: Return immediately if in same state from state change fns Have a check inside all individual operational state change functions to check whether device is in same state, and if yes, then return immediately. Testing Done: Tested on DB3.5 platform Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 591cf9d..2dc11fd 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -133,6 +133,9 @@ static int arche_platform_coldboot_seq(struct arche_platform_drvdata *arche_pdat { int ret; + if (arche_pdata->state == ARCHE_PLATFORM_STATE_ACTIVE) + return 0; + dev_info(arche_pdata->dev, "Booting from cold boot state\n"); svc_reset_onoff(arche_pdata->svc_reset_gpio, @@ -159,6 +162,9 @@ static int arche_platform_coldboot_seq(struct arche_platform_drvdata *arche_pdat static void arche_platform_fw_flashing_seq(struct arche_platform_drvdata *arche_pdata) { + if (arche_pdata->state == ARCHE_PLATFORM_STATE_FW_FLASHING) + return; + dev_info(arche_pdata->dev, "Switching to FW flashing state\n"); svc_reset_onoff(arche_pdata->svc_reset_gpio, @@ -176,6 +182,9 @@ static void arche_platform_fw_flashing_seq(struct arche_platform_drvdata *arche_ static void arche_platform_poweroff_seq(struct arche_platform_drvdata *arche_pdata) { + if (arche_pdata->state == ARCHE_PLATFORM_STATE_OFF) + return; + /* Send disconnect/detach event to SVC */ gpio_set_value(arche_pdata->wake_detect_gpio, 0); usleep_range(100, 200); -- cgit v0.10.2 From 25847ee7c9517f91323f9139713ebdc94c865a2e Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Mon, 22 Feb 2016 17:27:25 +0530 Subject: greybus: arche-platform: Avoid doing same thing again in poweroff fn If user switches from fw_flashing => off mode, then we do not need to do same things again, for example, clk_disable and wake/detect event, as while switching to fw_flashing, driver makes sure that device goes to off state and then brings back in fw_flashing state. Testing Done: Tested on DB3.5 platform. Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 2dc11fd..efeafb3 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -185,11 +185,15 @@ static void arche_platform_poweroff_seq(struct arche_platform_drvdata *arche_pda if (arche_pdata->state == ARCHE_PLATFORM_STATE_OFF) return; - /* Send disconnect/detach event to SVC */ - gpio_set_value(arche_pdata->wake_detect_gpio, 0); - usleep_range(100, 200); + /* If in fw_flashing mode, then no need to repeate things again */ + if (arche_pdata->state != ARCHE_PLATFORM_STATE_FW_FLASHING) { + /* Send disconnect/detach event to SVC */ + gpio_set_value(arche_pdata->wake_detect_gpio, 0); + usleep_range(100, 200); + + clk_disable_unprepare(arche_pdata->svc_ref_clk); + } - clk_disable_unprepare(arche_pdata->svc_ref_clk); /* As part of exit, put APB back in reset state */ svc_reset_onoff(arche_pdata->svc_reset_gpio, arche_pdata->is_reset_act_hi); -- cgit v0.10.2 From c5e7cbaf3ab8842278a9162dfaf04464ce21f0e4 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Mon, 22 Feb 2016 17:27:26 +0530 Subject: greybus: arche-apb-ctrl: Return immediately if in same state from state change fns Have a check inside all individual operational state change functions to check whether device is in same state, and if yes, then return immediately. Testing Done: Tested on DB3.5 platform. Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index 3086306..c2f0776 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -67,7 +67,8 @@ static int coldboot_seq(struct platform_device *pdev) struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); int ret; - if (apb->init_disabled) + if (apb->init_disabled || + apb->state == ARCHE_PLATFORM_STATE_ACTIVE) return 0; /* Hold APB in reset state */ @@ -112,7 +113,8 @@ static int fw_flashing_seq(struct platform_device *pdev) struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); int ret; - if (apb->init_disabled) + if (apb->init_disabled || + apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING) return 0; ret = regulator_enable(apb->vcore); @@ -141,8 +143,9 @@ static int standby_boot_seq(struct platform_device *pdev) if (apb->init_disabled) return 0; - /* If it is in OFF state, then we do not want to change the state */ - if (apb->state == ARCHE_PLATFORM_STATE_OFF) + /* Even if it is in OFF state, then we do not want to change the state */ + if (apb->state == ARCHE_PLATFORM_STATE_STANDBY || + apb->state == ARCHE_PLATFORM_STATE_OFF) return 0; /* @@ -162,7 +165,7 @@ static void poweroff_seq(struct platform_device *pdev) { struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); - if (apb->init_disabled) + if (apb->init_disabled || apb->state == ARCHE_PLATFORM_STATE_OFF) return; /* disable the clock */ -- cgit v0.10.2 From 9ed5e1ba33d12dfcc693c87779f39b91c16c15b9 Mon Sep 17 00:00:00 2001 From: Fabien Parent Date: Tue, 23 Feb 2016 18:46:08 +0100 Subject: greybus: connection: add api to {en,dis}able unipro fct flow In order to support mailbox-free control cport init on the bridges the AP must be able to enable/disable the flow of unipro fct tokens. Add a new API that will enable or disable on APBA the flow of fct tokens. Reviewed-by: Johan Hovold Signed-off-by: Fabien Parent Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 4f5e2ad..4ae7153 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -274,6 +274,34 @@ static void gb_connection_hd_cport_disable(struct gb_connection *connection) hd->driver->cport_disable(hd, connection->hd_cport_id); } +static int gb_connection_hd_fct_flow_enable(struct gb_connection *connection) +{ + struct gb_host_device *hd = connection->hd; + int ret; + + if (!hd->driver->fct_flow_enable) + return 0; + + ret = hd->driver->fct_flow_enable(hd, connection->hd_cport_id); + if (ret) { + dev_err(&hd->dev, "%s: failed to enable FCT flow: %d\n", + connection->name, ret); + return ret; + } + + return 0; +} + +static void gb_connection_hd_fct_flow_disable(struct gb_connection *connection) +{ + struct gb_host_device *hd = connection->hd; + + if (!hd->driver->fct_flow_disable) + return; + + hd->driver->fct_flow_disable(hd, connection->hd_cport_id); +} + /* * Request the SVC to create a connection from AP's cport to interface's * cport. diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h index e11359b..eaddfc9 100644 --- a/drivers/staging/greybus/hd.h +++ b/drivers/staging/greybus/hd.h @@ -25,6 +25,8 @@ struct gb_hd_driver { int (*latency_tag_disable)(struct gb_host_device *hd, u16 cport_id); int (*output)(struct gb_host_device *hd, void *req, u16 size, u8 cmd, bool async); + int (*fct_flow_enable)(struct gb_host_device *hd, u16 cport_id); + int (*fct_flow_disable)(struct gb_host_device *hd, u16 cport_id); }; struct gb_host_device { -- cgit v0.10.2 From 48a173030545472e4d0aa1b432b389ef59bf5cf0 Mon Sep 17 00:00:00 2001 From: Fabien Parent Date: Tue, 23 Feb 2016 18:46:09 +0100 Subject: greybus: apba: add fct flow usb control requests Add control requests to enable/disable the flow of unipro FCT tokens Reviewed-by: Johan Hovold Signed-off-by: Fabien Parent Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 1a90dc2..f283912 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -195,6 +195,9 @@ struct gb_control_interface_version_response { /* request to control the CSI transmitter */ #define GB_APB_REQUEST_AUDIO_CONTROL 0x09 +/* vendor requests to enable/disable FCT tokens flow */ +#define GB_APB_REQUEST_FCT_FLOW_EN 0x0b +#define GB_APB_REQUEST_FCT_FLOW_DIS 0x0c /* Firmware Protocol */ -- cgit v0.10.2 From e70055b3fb62c7ff1c23d8d2076e4c5b4caf39a1 Mon Sep 17 00:00:00 2001 From: Fabien Parent Date: Tue, 23 Feb 2016 18:46:10 +0100 Subject: greybus: es2: implement the fct flow control requests Implement the control requests enabling/disabling the flow of FCT on APBA. Reviewed-by: Johan Hovold Signed-off-by: Fabien Parent Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 5ade51e..e920563 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -574,6 +574,41 @@ static int latency_tag_disable(struct gb_host_device *hd, u16 cport_id) return retval; } +static int fct_flow_enable(struct gb_host_device *hd, u16 cport_id) +{ + int retval; + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct usb_device *udev = es2->usb_dev; + + retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + GB_APB_REQUEST_FCT_FLOW_EN, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, cport_id, 0, NULL, + 0, ES2_TIMEOUT); + if (retval < 0) + dev_err(&udev->dev, "Cannot enable FCT flow for cport %u: %d\n", + cport_id, retval); + return retval; +} + +static int fct_flow_disable(struct gb_host_device *hd, u16 cport_id) +{ + int retval; + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct usb_device *udev = es2->usb_dev; + + retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + GB_APB_REQUEST_FCT_FLOW_DIS, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, cport_id, 0, NULL, + 0, ES2_TIMEOUT); + if (retval < 0) + dev_err(&udev->dev, + "Cannot disable FCT flow for cport %u: %d\n", + cport_id, retval); + return retval; +} + static struct gb_hd_driver es2_driver = { .hd_priv_size = sizeof(struct es2_ap_dev), .message_send = message_send, @@ -582,6 +617,8 @@ static struct gb_hd_driver es2_driver = { .latency_tag_enable = latency_tag_enable, .latency_tag_disable = latency_tag_disable, .output = output, + .fct_flow_enable = fct_flow_enable, + .fct_flow_disable = fct_flow_disable, }; /* Common function to report consistent warnings based on URB status */ -- cgit v0.10.2 From 71f6c3231c1dce6980f97b7bc7ed7ac32faac550 Mon Sep 17 00:00:00 2001 From: Fabien Parent Date: Tue, 23 Feb 2016 18:46:11 +0100 Subject: greybus: connection: {en,dis}able fct flow in connection management The AP must enable the FCT flow of APBA once it has received the response from the AP that the connection between APBA and a module has been setted up. Disable the flow of FCT tokens when destroying connections. Signed-off-by: Fabien Parent Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 4ae7153..34e26dc 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -314,7 +314,7 @@ gb_connection_svc_connection_create(struct gb_connection *connection) int ret; if (gb_connection_is_static(connection)) - return 0; + return gb_connection_hd_fct_flow_enable(connection); intf = connection->intf; ret = gb_svc_connection_create(hd->svc, @@ -330,12 +330,23 @@ gb_connection_svc_connection_create(struct gb_connection *connection) return ret; } + ret = gb_connection_hd_fct_flow_enable(connection); + if (ret) { + gb_svc_connection_destroy(hd->svc, hd->svc->ap_intf_id, + connection->hd_cport_id, + intf->interface_id, + connection->intf_cport_id); + return ret; + } + return 0; } static void gb_connection_svc_connection_destroy(struct gb_connection *connection) { + gb_connection_hd_fct_flow_disable(connection); + if (gb_connection_is_static(connection)) return; -- cgit v0.10.2 From 066f950c65c206c1a1a2f72f2c80134177ea3999 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 24 Feb 2016 16:11:49 +0100 Subject: greybus: uart: add max-payload sanity check Let's be well behaved and add a sanity check on the maximum greybus payload size to avoid underflow on the calculated buffer size. Reviewed-by: Rui Miguel Silva Signed-off-by: Johan Hovold Reviewed-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 52cc9d5..60617cb 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -587,6 +587,7 @@ static void gb_tty_exit(void); static int gb_uart_connection_init(struct gb_connection *connection) { + size_t max_payload; struct gb_tty *gb_tty; struct device *tty_dev; int retval; @@ -607,8 +608,13 @@ static int gb_uart_connection_init(struct gb_connection *connection) goto error_alloc; } - gb_tty->buffer_payload_max = - gb_operation_get_payload_size_max(connection) - + max_payload = gb_operation_get_payload_size_max(connection); + if (max_payload < sizeof(struct gb_uart_send_data_request)) { + retval = -EINVAL; + goto error_payload; + } + + gb_tty->buffer_payload_max = max_payload - sizeof(struct gb_uart_send_data_request); gb_tty->buffer = kzalloc(gb_tty->buffer_payload_max, GFP_KERNEL); -- cgit v0.10.2 From cb7f00ba5f581ca2f0848dd2ed77f1b9d793c648 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 24 Feb 2016 16:11:50 +0100 Subject: greybus: uart: add missing serial-state sanity check Add dedicated serial-state request handler and add the missing sanity check on the incoming request. Reviewed-by: Rui Miguel Silva Signed-off-by: Johan Hovold Reviewed-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 60617cb..c09a76b 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -103,13 +103,32 @@ static int gb_uart_receive_data(struct gb_tty *gb_tty, return 0; } -static int gb_uart_request_recv(u8 type, struct gb_operation *op) +static int gb_uart_serial_state_handler(struct gb_operation *op) { struct gb_connection *connection = op->connection; struct gb_tty *gb_tty = connection->private; struct gb_message *request = op->request; struct gb_uart_serial_state_request *serial_state; - int ret = 0; + + if (request->payload_size < sizeof(*serial_state)) { + dev_err(&connection->bundle->dev, + "short serial-state event received (%zu < %zu)\n", + request->payload_size, sizeof(*serial_state)); + return -EINVAL; + } + + serial_state = request->payload; + gb_tty->ctrlin = serial_state->control; + + return 0; +} + +static int gb_uart_request_recv(u8 type, struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_tty *gb_tty = connection->private; + struct gb_message *request = op->request; + int ret; switch (type) { case GB_UART_TYPE_RECEIVE_DATA: @@ -117,8 +136,7 @@ static int gb_uart_request_recv(u8 type, struct gb_operation *op) request->payload); break; case GB_UART_TYPE_SERIAL_STATE: - serial_state = request->payload; - gb_tty->ctrlin = serial_state->control; + ret = gb_uart_serial_state_handler(op); break; default: dev_err(&connection->bundle->dev, -- cgit v0.10.2 From c5f338c4a040d7d6eefc560f3ee5cdb6ede03b74 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 24 Feb 2016 16:11:51 +0100 Subject: greybus: uart: fix incomplete receive-data sanity checks Fix incomplete receive-data sanity checks. The payload size was never verified before parsing the uart header and neither was the uart-header data size verified against the actual payload size, something which could lead to information leaks when passing data beyond the payload buffer to the tty layer. Also remove the incorrect check against the maximum (tx-buffer) payload size. Reviewed-by: Rui Miguel Silva Signed-off-by: Johan Hovold Reviewed-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index c09a76b..0685cdc 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -65,18 +65,36 @@ static DEFINE_IDR(tty_minors); static DEFINE_MUTEX(table_lock); static atomic_t reference_count = ATOMIC_INIT(0); -static int gb_uart_receive_data(struct gb_tty *gb_tty, - struct gb_connection *connection, - struct gb_uart_recv_data_request *receive_data) +static int gb_uart_receive_data_handler(struct gb_operation *op) { + struct gb_connection *connection = op->connection; + struct gb_tty *gb_tty = connection->private; struct tty_port *port = &gb_tty->port; + struct gb_message *request = op->request; + struct gb_uart_recv_data_request *receive_data; u16 recv_data_size; int count; unsigned long tty_flags = TTY_NORMAL; - count = gb_tty->buffer_payload_max - sizeof(*receive_data); + if (request->payload_size < sizeof(*receive_data)) { + dev_err(&connection->bundle->dev, + "short receive-data request received (%zu < %zu)\n", + request->payload_size, sizeof(*receive_data)); + return -EINVAL; + } + + receive_data = op->request->payload; recv_data_size = le16_to_cpu(receive_data->size); - if (!recv_data_size || recv_data_size > count) + + if (recv_data_size != request->payload_size - sizeof(*receive_data)) { + dev_err(&connection->bundle->dev, + "malformed receive-data request received (%u != %zu)\n", + recv_data_size, + request->payload_size - sizeof(*receive_data)); + return -EINVAL; + } + + if (!recv_data_size) return -EINVAL; if (receive_data->flags) { @@ -126,14 +144,11 @@ static int gb_uart_serial_state_handler(struct gb_operation *op) static int gb_uart_request_recv(u8 type, struct gb_operation *op) { struct gb_connection *connection = op->connection; - struct gb_tty *gb_tty = connection->private; - struct gb_message *request = op->request; int ret; switch (type) { case GB_UART_TYPE_RECEIVE_DATA: - ret = gb_uart_receive_data(gb_tty, connection, - request->payload); + ret = gb_uart_receive_data_handler(op); break; case GB_UART_TYPE_SERIAL_STATE: ret = gb_uart_serial_state_handler(op); -- cgit v0.10.2 From 6743a6fd963aba000b128fd0b5c420a8f4b0dcde Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Thu, 25 Feb 2016 02:27:36 +0530 Subject: greybus: arche-platform: Fix exit path in probe fn If SVC coldboot fails or if of_platform_populate() fn fails, then state of device needs to be reverted. Importantly, if of_platform_populate() fails, then poweroff the SVC. Testing Done: Tested on DB3.5 platform. Signed-off-by: Vaibhav Hiremath Reviewed-by: Michael Scott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index efeafb3..c99a375 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -387,13 +387,13 @@ static int arche_platform_probe(struct platform_device *pdev) ret = arche_platform_coldboot_seq(arche_pdata); if (ret) { dev_err(dev, "Failed to cold boot svc %d\n", ret); - return ret; + goto err_coldboot; } ret = of_platform_populate(np, NULL, NULL, dev); if (ret) { dev_err(dev, "failed to populate child nodes %d\n", ret); - return ret; + goto err_populate; } INIT_DELAYED_WORK(&arche_pdata->delayed_work, svc_delayed_work); @@ -401,6 +401,12 @@ static int arche_platform_probe(struct platform_device *pdev) dev_info(dev, "Device registered successfully\n"); return 0; + +err_populate: + arche_platform_poweroff_seq(arche_pdata); +err_coldboot: + device_remove_file(&pdev->dev, &dev_attr_state); + return ret; } static int arche_remove_child(struct device *dev, void *unused) -- cgit v0.10.2 From 7a6396d9ce81564b09d91586b29fdd02e6814c28 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 23 Feb 2016 22:51:23 -0800 Subject: greybus: gpio: use bundle device for error messages Use the bundle device directly in gpio error messages instead of the gpio device, as they are the same pointer. This will make future gpio api changes much easier to handle. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 5830dc9..ec375c0 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -77,6 +77,7 @@ static int gb_gpio_activate_operation(struct gb_gpio_controller *ggc, u8 which) static void gb_gpio_deactivate_operation(struct gb_gpio_controller *ggc, u8 which) { + struct device *dev = &ggc->connection->bundle->dev; struct gb_gpio_deactivate_request request; int ret; @@ -84,8 +85,7 @@ static void gb_gpio_deactivate_operation(struct gb_gpio_controller *ggc, ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_DEACTIVATE, &request, sizeof(request), NULL, 0); if (ret) { - dev_err(ggc->chip.dev, "failed to deactivate gpio %u\n", - which); + dev_err(dev, "failed to deactivate gpio %u\n", which); return; } @@ -95,6 +95,7 @@ static void gb_gpio_deactivate_operation(struct gb_gpio_controller *ggc, static int gb_gpio_get_direction_operation(struct gb_gpio_controller *ggc, u8 which) { + struct device *dev = &ggc->connection->bundle->dev; struct gb_gpio_get_direction_request request; struct gb_gpio_get_direction_response response; int ret; @@ -109,8 +110,7 @@ static int gb_gpio_get_direction_operation(struct gb_gpio_controller *ggc, direction = response.direction; if (direction && direction != 1) { - dev_warn(ggc->chip.dev, - "gpio %u direction was %u (should be 0 or 1)\n", + dev_warn(dev, "gpio %u direction was %u (should be 0 or 1)\n", which, direction); } ggc->lines[which].direction = direction ? 1 : 0; @@ -149,6 +149,7 @@ static int gb_gpio_direction_out_operation(struct gb_gpio_controller *ggc, static int gb_gpio_get_value_operation(struct gb_gpio_controller *ggc, u8 which) { + struct device *dev = &ggc->connection->bundle->dev; struct gb_gpio_get_value_request request; struct gb_gpio_get_value_response response; int ret; @@ -159,15 +160,13 @@ static int gb_gpio_get_value_operation(struct gb_gpio_controller *ggc, &request, sizeof(request), &response, sizeof(response)); if (ret) { - dev_err(ggc->chip.dev, "failed to get value of gpio %u\n", - which); + dev_err(dev, "failed to get value of gpio %u\n", which); return ret; } value = response.value; if (value && value != 1) { - dev_warn(ggc->chip.dev, - "gpio %u value was %u (should be 0 or 1)\n", + dev_warn(dev, "gpio %u value was %u (should be 0 or 1)\n", which, value); } ggc->lines[which].value = value ? 1 : 0; @@ -177,12 +176,13 @@ static int gb_gpio_get_value_operation(struct gb_gpio_controller *ggc, static void gb_gpio_set_value_operation(struct gb_gpio_controller *ggc, u8 which, bool value_high) { + struct device *dev = &ggc->connection->bundle->dev; struct gb_gpio_set_value_request request; int ret; if (ggc->lines[which].direction == 1) { - dev_warn(ggc->chip.dev, - "refusing to set value of input gpio %u\n", which); + dev_warn(dev, "refusing to set value of input gpio %u\n", + which); return; } @@ -191,8 +191,7 @@ static void gb_gpio_set_value_operation(struct gb_gpio_controller *ggc, ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_SET_VALUE, &request, sizeof(request), NULL, 0); if (ret) { - dev_err(ggc->chip.dev, "failed to set value of gpio %u\n", - which); + dev_err(dev, "failed to set value of gpio %u\n", which); return; } @@ -216,6 +215,7 @@ static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *ggc, static void _gb_gpio_irq_mask(struct gb_gpio_controller *ggc, u8 hwirq) { + struct device *dev = &ggc->connection->bundle->dev; struct gb_gpio_irq_mask_request request; int ret; @@ -224,11 +224,12 @@ static void _gb_gpio_irq_mask(struct gb_gpio_controller *ggc, u8 hwirq) GB_GPIO_TYPE_IRQ_MASK, &request, sizeof(request), NULL, 0); if (ret) - dev_err(ggc->chip.dev, "failed to mask irq: %d\n", ret); + dev_err(dev, "failed to mask irq: %d\n", ret); } static void _gb_gpio_irq_unmask(struct gb_gpio_controller *ggc, u8 hwirq) { + struct device *dev = &ggc->connection->bundle->dev; struct gb_gpio_irq_unmask_request request; int ret; @@ -237,12 +238,13 @@ static void _gb_gpio_irq_unmask(struct gb_gpio_controller *ggc, u8 hwirq) GB_GPIO_TYPE_IRQ_UNMASK, &request, sizeof(request), NULL, 0); if (ret) - dev_err(ggc->chip.dev, "failed to unmask irq: %d\n", ret); + dev_err(dev, "failed to unmask irq: %d\n", ret); } static void _gb_gpio_irq_set_type(struct gb_gpio_controller *ggc, u8 hwirq, u8 type) { + struct device *dev = &ggc->connection->bundle->dev; struct gb_gpio_irq_type_request request; int ret; @@ -253,7 +255,7 @@ static void _gb_gpio_irq_set_type(struct gb_gpio_controller *ggc, GB_GPIO_TYPE_IRQ_TYPE, &request, sizeof(request), NULL, 0); if (ret) - dev_err(ggc->chip.dev, "failed to set irq type: %d\n", ret); + dev_err(dev, "failed to set irq type: %d\n", ret); } static void gb_gpio_irq_mask(struct irq_data *d) @@ -281,6 +283,7 @@ static int gb_gpio_irq_set_type(struct irq_data *d, unsigned int type) struct gpio_chip *chip = irq_data_to_gpio_chip(d); struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); struct gb_gpio_line *line = &ggc->lines[d->hwirq]; + struct device *dev = &ggc->connection->bundle->dev; u8 irq_type; switch (type) { @@ -303,7 +306,7 @@ static int gb_gpio_irq_set_type(struct irq_data *d, unsigned int type) irq_type = GB_GPIO_IRQ_TYPE_LEVEL_HIGH; break; default: - dev_err(chip->dev, "unsupported irq type: %u\n", type); + dev_err(dev, "unsupported irq type: %u\n", type); return -EINVAL; } @@ -346,6 +349,7 @@ static void gb_gpio_irq_bus_sync_unlock(struct irq_data *d) static int gb_gpio_request_recv(u8 type, struct gb_operation *op) { struct gb_connection *connection = op->connection; + struct device *dev = &connection->bundle->dev; struct gb_gpio_controller *ggc = connection->private; struct gb_message *request; struct gb_gpio_irq_event_request *event; @@ -353,33 +357,32 @@ static int gb_gpio_request_recv(u8 type, struct gb_operation *op) struct irq_desc *desc; if (type != GB_GPIO_TYPE_IRQ_EVENT) { - dev_err(&connection->bundle->dev, - "unsupported unsolicited request: %u\n", type); + dev_err(dev, "unsupported unsolicited request: %u\n", type); return -EINVAL; } request = op->request; if (request->payload_size < sizeof(*event)) { - dev_err(ggc->chip.dev, "short event received (%zu < %zu)\n", + dev_err(dev, "short event received (%zu < %zu)\n", request->payload_size, sizeof(*event)); return -EINVAL; } event = request->payload; if (event->which > ggc->line_max) { - dev_err(ggc->chip.dev, "invalid hw irq: %d\n", event->which); + dev_err(dev, "invalid hw irq: %d\n", event->which); return -EINVAL; } irq = irq_find_mapping(ggc->irqdomain, event->which); if (!irq) { - dev_err(ggc->chip.dev, "failed to find IRQ\n"); + dev_err(dev, "failed to find IRQ\n"); return -EINVAL; } desc = irq_to_desc(irq); if (!desc) { - dev_err(ggc->chip.dev, "failed to look up irq\n"); + dev_err(dev, "failed to look up irq\n"); return -EINVAL; } -- cgit v0.10.2 From bb80c76448b2463a1ecfe622df4f7b3c5fb39cdf Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 23 Feb 2016 22:51:45 -0800 Subject: greybus: gpio: handle api changes for 4.5 kernel release In kernel version 4.5, struct gpio_chip renamed the field 'dev' to 'parent' so handle this properly. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index ec375c0..e7dd994 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -651,7 +651,11 @@ static int gb_gpio_connection_init(struct gb_connection *connection) gpio = &ggc->chip; gpio->label = "greybus_gpio"; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0) + gpio->parent = &connection->bundle->dev; +#else gpio->dev = &connection->bundle->dev; +#endif gpio->owner = THIS_MODULE; gpio->request = gb_gpio_request; -- cgit v0.10.2 From 8886c44f87cbee41fd4ac1cfdf1ef6a7cb4583f5 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 22 Feb 2016 18:50:54 +0100 Subject: greybus: Documentation/sysfs: add module devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce module devices and rename interface and bundle devices. Greybus module devices correspond to physical modules and have one or more interfaces. Modules have an id that is identical to the id of their primary interface, which in turn is the interface with lowest numbered id. The module name is constructed from the bus and module id: - Interfaces and bundles are consequently renamed as -. and -.. respectively. As before, interface ids (and therefore in a sense now also module ids) correspond to physical interface positions on the frame. Modules have the following attributes: eject module_id num_interfaces where module_id is the id of the module and num_interface the number of interfaces the module has. Note that the interface ids of a module's interfaces are expected to be , , ..., . Writing a non-zero argument to eject cleanly shuts down and unregisters all of the module interfaces before ejecting the module. The example sysfs tree now looks as follows with the second bus (APBridgeA) left out: greybus1/ ├── 1-2 │   ├── 1-2.2 │   │   ├── 1-2.2.1 │   │   │   ├── bundle_class │   │   │   ├── bundle_id │   │   │   └── state │   │   ├── 1-2.2.2 │   │   │   ├── bundle_class │   │   │   ├── bundle_id │   │   │   └── state │   │   ├── ddbl1_manufacturer_id │   │   ├── ddbl1_product_id │   │   ├── interface_id │   │   ├── product_id │   │   ├── serial_number │   │   ├── unique_id │   │   └── vendor_id │   ├── eject │   ├── module_id │   └── num_interfaces ├── 1-4 │   ├── 1-4.4 │   │   ├── 1-4.4.2 │   │   │   ├── bundle_class │   │   │   ├── bundle_id │   │   │   ├── gpbridge0 │   │   │   │   ├── gpio │   │   │   │   │   └── gpiochip490 │   │   │   │   └── i2c-4 │   │   │   └── state │   │   ├── ddbl1_manufacturer_id │   │   ├── ddbl1_product_id │   │   ├── interface_id │   │   ├── product_id │   │   ├── serial_number │   │   ├── unique_id │   │   └── vendor_id │   ├── eject │   ├── module_id │   └── num_interfaces └── 1-svc ├── ap_intf_id ├── eject └── endo_id where greybus1 is a bus; 1-svc the svc; 1-2, and 1-4 are modules; 1-2.2 and 1-4.4 are (primary) interfaces; and 1-2.2.1, 1-2.2.2, and 1-4.4.2 are bundles. Note that the svc eject attribute may eventually be renamed force_eject. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.1/bundle_class b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.1/bundle_class deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.1/bundle_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.1/bundle_id deleted file mode 100644 index d00491f..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.1/bundle_id +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.1/state b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.1/state deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.1/bundle_class b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.1/bundle_class new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.1/bundle_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.1/bundle_id new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.1/bundle_id @@ -0,0 +1 @@ +1 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.1/state b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.1/state new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.2/bundle_class b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.2/bundle_class new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.2/bundle_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.2/bundle_id new file mode 100644 index 0000000..0cfbf08 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.2/bundle_id @@ -0,0 +1 @@ +2 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.2/state b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.2/state new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/bundle_class b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/bundle_class deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/bundle_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/bundle_id deleted file mode 100644 index 0cfbf08..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/bundle_id +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/ddbl1_manufacturer_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/ddbl1_manufacturer_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/ddbl1_product_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/ddbl1_product_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/interface_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/interface_id new file mode 100644 index 0000000..0cfbf08 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/interface_id @@ -0,0 +1 @@ +2 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/product_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/product_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/serial_number b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/serial_number new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/state b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/state deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/unique_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/unique_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/vendor_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/vendor_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/ddbl1_manufacturer_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/ddbl1_manufacturer_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/ddbl1_product_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/ddbl1_product_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/eject b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/eject new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/interface_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/interface_id deleted file mode 100644 index 0cfbf08..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/interface_id +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/module_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/module_id new file mode 100644 index 0000000..0cfbf08 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/module_id @@ -0,0 +1 @@ +2 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/num_interfaces b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/num_interfaces new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/num_interfaces @@ -0,0 +1 @@ +1 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/product_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/product_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/serial_number b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/serial_number deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/unique_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/unique_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/vendor_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/vendor_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/bundle_class b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/bundle_class deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/bundle_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/bundle_id deleted file mode 100644 index 0cfbf08..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/bundle_id +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/gpbridge0/gpio/gpiochip490/.gitignore b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/gpbridge0/gpio/gpiochip490/.gitignore deleted file mode 100644 index f935021..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/gpbridge0/gpio/gpiochip490/.gitignore +++ /dev/null @@ -1 +0,0 @@ -!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/gpbridge0/i2c-4/.gitignore b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/gpbridge0/i2c-4/.gitignore deleted file mode 100644 index f935021..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/gpbridge0/i2c-4/.gitignore +++ /dev/null @@ -1 +0,0 @@ -!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/state b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.2/state deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/1-4.4.2/bundle_class b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/1-4.4.2/bundle_class new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/1-4.4.2/bundle_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/1-4.4.2/bundle_id new file mode 100644 index 0000000..0cfbf08 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/1-4.4.2/bundle_id @@ -0,0 +1 @@ +2 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/1-4.4.2/gpbridge0/gpio/gpiochip490/.gitignore b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/1-4.4.2/gpbridge0/gpio/gpiochip490/.gitignore new file mode 100644 index 0000000..f935021 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/1-4.4.2/gpbridge0/gpio/gpiochip490/.gitignore @@ -0,0 +1 @@ +!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/1-4.4.2/gpbridge0/i2c-4/.gitignore b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/1-4.4.2/gpbridge0/i2c-4/.gitignore new file mode 100644 index 0000000..f935021 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/1-4.4.2/gpbridge0/i2c-4/.gitignore @@ -0,0 +1 @@ +!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/1-4.4.2/state b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/1-4.4.2/state new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/ddbl1_manufacturer_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/ddbl1_manufacturer_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/ddbl1_product_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/ddbl1_product_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/interface_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/interface_id new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/interface_id @@ -0,0 +1 @@ +4 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/product_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/product_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/serial_number b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/serial_number new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/unique_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/unique_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/vendor_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/vendor_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/ddbl1_manufacturer_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/ddbl1_manufacturer_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/ddbl1_product_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/ddbl1_product_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/eject b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/eject new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/interface_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/interface_id deleted file mode 100644 index b8626c4..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/interface_id +++ /dev/null @@ -1 +0,0 @@ -4 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/module_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/module_id new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/module_id @@ -0,0 +1 @@ +4 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/num_interfaces b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/num_interfaces new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/num_interfaces @@ -0,0 +1 @@ +1 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/product_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/product_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/serial_number b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/serial_number deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/unique_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/unique_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/vendor_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/vendor_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.1/bundle_class b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.1/bundle_class deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.1/bundle_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.1/bundle_id deleted file mode 100644 index d00491f..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.1/bundle_id +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.1/state b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.1/state deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.1/bundle_class b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.1/bundle_class new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.1/bundle_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.1/bundle_id new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.1/bundle_id @@ -0,0 +1 @@ +1 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.1/state b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.1/state new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/ddbl1_manufacturer_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/ddbl1_manufacturer_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/ddbl1_product_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/ddbl1_product_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/interface_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/interface_id new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/interface_id @@ -0,0 +1 @@ +3 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/product_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/product_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/serial_number b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/serial_number new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/unique_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/unique_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/vendor_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/vendor_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/ddbl1_manufacturer_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/ddbl1_manufacturer_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/ddbl1_product_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/ddbl1_product_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/eject b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/eject new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/interface_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/interface_id deleted file mode 100644 index 00750ed..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/interface_id +++ /dev/null @@ -1 +0,0 @@ -3 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/module_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/module_id new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/module_id @@ -0,0 +1 @@ +3 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/num_interfaces b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/num_interfaces new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/num_interfaces @@ -0,0 +1 @@ +1 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/product_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/product_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/serial_number b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/serial_number deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/unique_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/unique_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/vendor_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/vendor_id deleted file mode 100644 index e69de29..0000000 -- cgit v0.10.2 From bd93d2a819c5e6081920f5dc775fc3361dbca5f7 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 22 Feb 2016 18:50:55 +0100 Subject: greybus: Documentation/sysfs: move module 1-4 to position 5 Move example module 1-4 to position 5, effectively renaming it 1-5. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/1-4.4.2/bundle_class b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/1-4.4.2/bundle_class deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/1-4.4.2/bundle_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/1-4.4.2/bundle_id deleted file mode 100644 index 0cfbf08..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/1-4.4.2/bundle_id +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/1-4.4.2/gpbridge0/gpio/gpiochip490/.gitignore b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/1-4.4.2/gpbridge0/gpio/gpiochip490/.gitignore deleted file mode 100644 index f935021..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/1-4.4.2/gpbridge0/gpio/gpiochip490/.gitignore +++ /dev/null @@ -1 +0,0 @@ -!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/1-4.4.2/gpbridge0/i2c-4/.gitignore b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/1-4.4.2/gpbridge0/i2c-4/.gitignore deleted file mode 100644 index f935021..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/1-4.4.2/gpbridge0/i2c-4/.gitignore +++ /dev/null @@ -1 +0,0 @@ -!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/1-4.4.2/state b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/1-4.4.2/state deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/ddbl1_manufacturer_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/ddbl1_manufacturer_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/ddbl1_product_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/ddbl1_product_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/interface_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/interface_id deleted file mode 100644 index b8626c4..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/interface_id +++ /dev/null @@ -1 +0,0 @@ -4 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/product_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/product_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/serial_number b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/serial_number deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/unique_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/unique_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/vendor_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/1-4.4/vendor_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/eject b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/eject deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/module_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/module_id deleted file mode 100644 index b8626c4..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/module_id +++ /dev/null @@ -1 +0,0 @@ -4 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/num_interfaces b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/num_interfaces deleted file mode 100644 index d00491f..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-4/num_interfaces +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/bundle_class b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/bundle_class new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/bundle_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/bundle_id new file mode 100644 index 0000000..0cfbf08 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/bundle_id @@ -0,0 +1 @@ +2 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gpbridge0/gpio/gpiochip490/.gitignore b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gpbridge0/gpio/gpiochip490/.gitignore new file mode 100644 index 0000000..f935021 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gpbridge0/gpio/gpiochip490/.gitignore @@ -0,0 +1 @@ +!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gpbridge0/i2c-4/.gitignore b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gpbridge0/i2c-4/.gitignore new file mode 100644 index 0000000..f935021 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gpbridge0/i2c-4/.gitignore @@ -0,0 +1 @@ +!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/state b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/state new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/ddbl1_manufacturer_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/ddbl1_manufacturer_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/ddbl1_product_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/ddbl1_product_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/interface_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/interface_id new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/interface_id @@ -0,0 +1 @@ +5 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/product_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/product_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/serial_number b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/serial_number new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/unique_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/unique_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/vendor_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/vendor_id new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/eject b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/eject new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/module_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/module_id new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/module_id @@ -0,0 +1 @@ +5 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/num_interfaces b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/num_interfaces new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/num_interfaces @@ -0,0 +1 @@ +1 -- cgit v0.10.2 From c8733c513df38d5e5b3a19fe54be0f5821bfda2a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 22 Feb 2016 18:50:56 +0100 Subject: greybus: Documentation/sysfs: make 1-5 a 2x2 module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make example module 1-5 a 2x2 module by adding a second, dummy interface. This is both an example of how a 2x2 module would be represented and also suggests what a dummy interface may look like. A 2x2 module has two child interface devices and a num_interfaces value of two. In this example, the secondary interface 1-5.6, is a dummy interface and therefore lacks the normal identifying attributes (e.g. UniPro DDBL1 and Ara ids). We may eventually add an interface_type attribute to facilitate distinguishing various interface types (there may be more than two). In the following tree, the bundle attributes and child devices have been left out: greybus1/ ├── 1-2 │   ├── 1-2.2 │   │   ├── 1-2.2.1 │   │   ├── 1-2.2.2 │   │   ├── ddbl1_manufacturer_id │   │   ├── ddbl1_product_id │   │   ├── interface_id │   │   ├── product_id │   │   ├── serial_number │   │   ├── unique_id │   │   └── vendor_id │   ├── eject │   ├── module_id │   └── num_interfaces ├── 1-5 │   ├── 1-5.5 │   │   ├── 1-5.5.2 │   │   ├── ddbl1_manufacturer_id │   │   ├── ddbl1_product_id │   │   ├── interface_id │   │   ├── product_id │   │   ├── serial_number │   │   ├── unique_id │   │   └── vendor_id │   ├── 1-5.6 │   │   └── interface_id │   ├── eject │   ├── module_id │   └── num_interfaces └── 1-svc In this example there are two modules: 1-2 is a 1x2 module with one interface, and 1-5 is a 2x2 module with two interfaces of which the second (1-5.6) is a dummy interface. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.6/interface_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.6/interface_id new file mode 100644 index 0000000..1e8b314 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.6/interface_id @@ -0,0 +1 @@ +6 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/num_interfaces b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/num_interfaces index d00491f..0cfbf08 100644 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/num_interfaces +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/num_interfaces @@ -1 +1 @@ -1 +2 -- cgit v0.10.2 From 037a4028be8d6551dc226fc48c0c16063774e649 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Thu, 25 Feb 2016 04:37:33 +0530 Subject: greybus: arche-apb-ctrl: Remove extra delay in APB reset With synchronization between SVC <=> AP over wake/detect line to bring APB's out of reset, we do not need any extra delays now. So remove it. Testing Done: Tested for DB3.5 and EVT1.2 platform. Signed-off-by: Vaibhav Hiremath Reviewed-by: Michael Scott Tested-by: Michael Scott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index c2f0776..55806bd 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -50,7 +50,6 @@ struct arche_apb_ctrl_drvdata { static inline void deassert_reset(unsigned int gpio) { gpio_set_value(gpio, 1); - msleep(500); } static inline void assert_reset(unsigned int gpio) -- cgit v0.10.2 From db5a3bca56584c0ae62dbe0b280333c75a813b0a Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Thu, 25 Feb 2016 04:37:34 +0530 Subject: greybus: arche-platform: Convert delayed work to do only hub3613 configuration This is preparation of interrupt handling support, where APB coldboot and wake/detect handling will be handled as response to wake/detect interrupt. Due to slower I2C write operations in HUB configuration, it is important to separate HUB configuration, and probably delay it after APB is cold booted. Note that delayed work will be scheduled from interrupt handler, in following patches. To satisfy build (and bisect), remove apb_cold_boot() fn, which will be added back in the patch where it gets used again. Testing Done: Tested on DB3.5 platform. Signed-off-by: Vaibhav Hiremath Reviewed-by: Michael Scott Tested-by: Michael Scott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index c99a375..50991a6 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -47,18 +47,6 @@ static inline void svc_reset_onoff(unsigned int gpio, bool onoff) gpio_set_value(gpio, onoff); } -static int apb_cold_boot(struct device *dev, void *data) -{ - int ret; - - ret = apb_ctrl_coldboot(dev); - if (ret) - dev_warn(dev, "failed to coldboot\n"); - - /*Child nodes are independent, so do not exit coldboot operation */ - return 0; -} - static int apb_fw_flashing_state(struct device *dev, void *data) { int ret; @@ -79,50 +67,17 @@ static int apb_poweroff(struct device *dev, void *data) } /** - * svc_delayed_work - Time to give SVC to boot. + * hub_conf_delayed_work - Configures USB3613 device to HUB mode + * + * The idea here is to split the APB coldboot operation with slow HUB configuration, + * so that driver response to wake/detect event can be met. + * So expectation is, once code reaches here, means initial unipro linkup + * between APB<->Switch was successful, so now just take it to AP. */ -static void svc_delayed_work(struct work_struct *work) +static void hub_conf_delayed_work(struct work_struct *work) { struct arche_platform_drvdata *arche_pdata = container_of(work, struct arche_platform_drvdata, delayed_work.work); - int timeout = 50; - - /* - * 1. SVC and AP boot independently, with AP<-->SVC wake/detect pin - * deasserted (LOW in this case) - * 2.1. SVC allows 360 milliseconds to elapse after switch boots to work - * around bug described in ENG-330. - * 2.2. AP asserts wake/detect pin (HIGH) (this can proceed in parallel with 2.1) - * 3. SVC detects assertion of wake/detect pin, and sends "wake out" signal to AP - * 4. AP receives "wake out" signal, takes AP Bridges through their power - * on reset sequence as defined in the bridge ASIC reference manuals - * 5. AP takes USB3613 through its power on reset sequence - * 6. AP enumerates AP Bridges - */ - gpio_set_value(arche_pdata->wake_detect_gpio, 1); - gpio_direction_input(arche_pdata->wake_detect_gpio); - do { - /* Read the wake_detect GPIO, for WAKE_OUT event from SVC */ - if (gpio_get_value(arche_pdata->wake_detect_gpio) == 0) - break; - - msleep(100); - } while(timeout--); - - if (timeout < 0) { - /* FIXME: We may want to limit retries here */ - dev_warn(arche_pdata->dev, - "Timed out on wake/detect, rescheduling handshake\n"); - gpio_direction_output(arche_pdata->wake_detect_gpio, 0); - schedule_delayed_work(&arche_pdata->delayed_work, msecs_to_jiffies(2000)); - return; - } - - /* Bring APB out of reset: cold boot sequence */ - device_for_each_child(arche_pdata->dev, NULL, apb_cold_boot); - - /* re-assert wake_detect to confirm SVC WAKE_OUT */ - gpio_direction_output(arche_pdata->wake_detect_gpio, 1); /* Enable HUB3613 into HUB mode. */ if (usb3613_hub_mode_ctrl(true)) @@ -226,8 +181,6 @@ static ssize_t state_store(struct device *dev, return count; ret = arche_platform_coldboot_seq(arche_pdata); - /* Give enough time for SVC to boot and then handshake with SVC */ - schedule_delayed_work(&arche_pdata->delayed_work, msecs_to_jiffies(2000)); } else if (sysfs_streq(buf, "standby")) { if (arche_pdata->state == ARCHE_PLATFORM_STATE_STANDBY) return count; @@ -396,8 +349,7 @@ static int arche_platform_probe(struct platform_device *pdev) goto err_populate; } - INIT_DELAYED_WORK(&arche_pdata->delayed_work, svc_delayed_work); - schedule_delayed_work(&arche_pdata->delayed_work, msecs_to_jiffies(2000)); + INIT_DELAYED_WORK(&arche_pdata->delayed_work, hub_conf_delayed_work); dev_info(dev, "Device registered successfully\n"); return 0; -- cgit v0.10.2 From 685353c12ea33e99d1daba5b3721b9033cdbdb87 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Thu, 25 Feb 2016 04:37:35 +0530 Subject: greybus: arche-platform: Add wake detect state based on functionality If driver needs to process wake/detect events from SVC, by enabling interrupt support on wake/detect event, it becomes easier to maintain state of wake/detect line based on functionality. Testing Done: Tested on DB3.5 platform. Signed-off-by: Vaibhav Hiremath Reviewed-by: Michael Scott Tested-by: Michael Scott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 50991a6..dcc3844 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -21,6 +21,15 @@ #include +enum svc_wakedetect_state { + WD_STATE_IDLE, /* Default state = pulled high/low */ + WD_STATE_BOOT_INIT, /* WD = falling edge (low) */ + WD_STATE_COLDBOOT_TRIG, /* WD = rising edge (high), > 30msec */ + WD_STATE_STANDBYBOOT_TRIG, /* As of now not used ?? */ + WD_STATE_COLDBOOT_START, /* Cold boot process started */ + WD_STATE_STANDBYBOOT_START, /* Not used */ +}; + struct arche_platform_drvdata { /* Control GPIO signals to and from AP <=> SVC */ int svc_reset_gpio; @@ -39,6 +48,8 @@ struct arche_platform_drvdata { int num_apbs; struct delayed_work delayed_work; + enum svc_wakedetect_state wake_detect_state; + struct device *dev; }; @@ -145,6 +156,7 @@ static void arche_platform_poweroff_seq(struct arche_platform_drvdata *arche_pda /* Send disconnect/detach event to SVC */ gpio_set_value(arche_pdata->wake_detect_gpio, 0); usleep_range(100, 200); + arche_pdata->wake_detect_state = WD_STATE_IDLE; clk_disable_unprepare(arche_pdata->svc_ref_clk); } @@ -328,6 +340,7 @@ static int arche_platform_probe(struct platform_device *pdev) } /* deassert wake detect */ gpio_direction_output(arche_pdata->wake_detect_gpio, 0); + arche_pdata->wake_detect_state = WD_STATE_IDLE; arche_pdata->dev = &pdev->dev; -- cgit v0.10.2 From f760bbfb5c10952739fd0d39869cdd6a43844037 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Thu, 25 Feb 2016 04:37:36 +0530 Subject: greybus: arche-platform: Enable interrupt support on wake/detect line This patch enabled interrupt support on events received over wake/detect line. The driver follows below state machine, Default: wake/detect line is high (WD_STATE_IDLE) On Falling edge: SVC initiates boot (either cold/standby). On ES3, > 30msec = coldboot, else standby boot. Driver moves to WD_STATE_BOOT_INIT On rising edge (> 30msec): SVC expects APB to coldboot Driver wakes irq thread which kicks off APB coldboot (WD_STATE_COLDBOOT_TRIG) On rising edge (< 30msec): Driver ignores it, do nothing. After coldboot of APB, HUB configuration work is scheduled after 2 sec, allowing enough time for APB<->SVC/Switch to linkup (in multiple iterations) Testing Done: Tested on DB3.5 platform. Signed-off-by: Vaibhav Hiremath Reviewed-by: Michael Scott Tested-by: Michael Scott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index dcc3844..83db892 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -17,10 +17,15 @@ #include #include #include +#include +#include +#include #include "arche_platform.h" #include +#define WD_COLDBOOT_PULSE_WIDTH_MS 30 + enum svc_wakedetect_state { WD_STATE_IDLE, /* Default state = pulled high/low */ WD_STATE_BOOT_INIT, /* WD = falling edge (low) */ @@ -49,6 +54,9 @@ struct arche_platform_drvdata { struct delayed_work delayed_work; enum svc_wakedetect_state wake_detect_state; + int wake_detect_irq; + spinlock_t lock; + unsigned long wake_detect_start; struct device *dev; }; @@ -58,6 +66,18 @@ static inline void svc_reset_onoff(unsigned int gpio, bool onoff) gpio_set_value(gpio, onoff); } +static int apb_cold_boot(struct device *dev, void *data) +{ + int ret; + + ret = apb_ctrl_coldboot(dev); + if (ret) + dev_warn(dev, "failed to coldboot\n"); + + /*Child nodes are independent, so do not exit coldboot operation */ + return 0; +} + static int apb_fw_flashing_state(struct device *dev, void *data) { int ret; @@ -95,6 +115,86 @@ static void hub_conf_delayed_work(struct work_struct *work) dev_warn(arche_pdata->dev, "failed to control hub device\n"); } +static irqreturn_t arche_platform_wd_irq_thread(int irq, void *devid) +{ + struct arche_platform_drvdata *arche_pdata = devid; + unsigned long flags; + + spin_lock_irqsave(&arche_pdata->lock, flags); + if (arche_pdata->wake_detect_state != WD_STATE_COLDBOOT_TRIG) { + /* Something is wrong */ + spin_unlock_irqrestore(&arche_pdata->lock, flags); + return IRQ_HANDLED; + } + + arche_pdata->wake_detect_state = WD_STATE_COLDBOOT_START; + spin_unlock_irqrestore(&arche_pdata->lock, flags); + + /* Bring APB out of reset: cold boot sequence */ + device_for_each_child(arche_pdata->dev, NULL, apb_cold_boot); + + spin_lock_irqsave(&arche_pdata->lock, flags); + /* USB HUB configuration */ + schedule_delayed_work(&arche_pdata->delayed_work, msecs_to_jiffies(2000)); + arche_pdata->wake_detect_state = WD_STATE_IDLE; + spin_unlock_irqrestore(&arche_pdata->lock, flags); + + return IRQ_HANDLED; +} + +static irqreturn_t arche_platform_wd_irq(int irq, void *devid) +{ + struct arche_platform_drvdata *arche_pdata = devid; + unsigned long flags; + + spin_lock_irqsave(&arche_pdata->lock, flags); + + if (gpio_get_value(arche_pdata->wake_detect_gpio)) { + /* wake/detect rising */ + + /* + * If wake/detect line goes high after low, within less than + * 30msec, then standby boot sequence is initiated, which is not + * supported/implemented as of now. So ignore it. + */ + if (arche_pdata->wake_detect_state == WD_STATE_BOOT_INIT) { + if (time_before(jiffies, + arche_pdata->wake_detect_start + + msecs_to_jiffies(WD_COLDBOOT_PULSE_WIDTH_MS))) { + /* No harm with cancellation, even if not pending */ + cancel_delayed_work(&arche_pdata->delayed_work); + arche_pdata->wake_detect_state = WD_STATE_IDLE; + } else { + /* Check we are not in middle of irq thread already */ + if (arche_pdata->wake_detect_state != + WD_STATE_COLDBOOT_START) { + arche_pdata->wake_detect_state = + WD_STATE_COLDBOOT_TRIG; + spin_unlock_irqrestore(&arche_pdata->lock, flags); + return IRQ_WAKE_THREAD; + } + } + } + } else { + /* wake/detect falling */ + if (arche_pdata->wake_detect_state == WD_STATE_IDLE) { + arche_pdata->wake_detect_start = jiffies; + /* No harm with cancellation even if it is not pending*/ + cancel_delayed_work(&arche_pdata->delayed_work); + /* + * In the begining, when wake/detect goes low (first time), we assume + * it is meant for coldboot and set the flag. If wake/detect line stays low + * beyond 30msec, then it is coldboot else fallback to standby boot. + */ + arche_pdata->wake_detect_state = WD_STATE_BOOT_INIT; + } + } + + spin_unlock_irqrestore(&arche_pdata->lock, flags); + + return IRQ_HANDLED; +} + static int arche_platform_coldboot_seq(struct arche_platform_drvdata *arche_pdata) { int ret; @@ -148,6 +248,8 @@ static void arche_platform_fw_flashing_seq(struct arche_platform_drvdata *arche_ static void arche_platform_poweroff_seq(struct arche_platform_drvdata *arche_pdata) { + unsigned long flags; + if (arche_pdata->state == ARCHE_PLATFORM_STATE_OFF) return; @@ -156,7 +258,9 @@ static void arche_platform_poweroff_seq(struct arche_platform_drvdata *arche_pda /* Send disconnect/detach event to SVC */ gpio_set_value(arche_pdata->wake_detect_gpio, 0); usleep_range(100, 200); + spin_lock_irqsave(&arche_pdata->lock, flags); arche_pdata->wake_detect_state = WD_STATE_IDLE; + spin_unlock_irqrestore(&arche_pdata->lock, flags); clk_disable_unprepare(arche_pdata->svc_ref_clk); } @@ -344,6 +448,22 @@ static int arche_platform_probe(struct platform_device *pdev) arche_pdata->dev = &pdev->dev; + spin_lock_init(&arche_pdata->lock); + arche_pdata->wake_detect_irq = + gpio_to_irq(arche_pdata->wake_detect_gpio); + + ret = devm_request_threaded_irq(dev, arche_pdata->wake_detect_irq, + arche_platform_wd_irq, + arche_platform_wd_irq_thread, + IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT, + dev_name(dev), arche_pdata); + if (ret) { + dev_err(dev, "failed to request wake detect IRQ %d\n", ret); + return ret; + } + /* Enable it only after sending wake/detect event */ + disable_irq(arche_pdata->wake_detect_irq); + ret = device_create_file(dev, &dev_attr_state); if (ret) { dev_err(dev, "failed to create state file in sysfs\n"); -- cgit v0.10.2 From 16fe18ca9ef0a3d806d33121a3a653138a1a6854 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Thu, 25 Feb 2016 04:37:37 +0530 Subject: greybus: arche-platform: Assert wake/detect after SVC reset without delay Since now driver supports interrupt based mechanism to read events from SVC over wake/detect line, no need to delay wake/detect assertion. We can assert wake/detect after SVC reset deassertion, so during boot itself SVC will start sending wake_out pulses. Testing Done: Tested on DB3.5 platform. Signed-off-by: Vaibhav Hiremath Reviewed-by: Michael Scott Tested-by: Michael Scott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 83db892..87526b2b 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -115,6 +115,16 @@ static void hub_conf_delayed_work(struct work_struct *work) dev_warn(arche_pdata->dev, "failed to control hub device\n"); } +static void assert_wakedetect(struct arche_platform_drvdata *arche_pdata) +{ + /* Assert wake/detect = Detect event from AP */ + gpio_direction_output(arche_pdata->wake_detect_gpio, 1); + + /* Enable interrupt here, to read event back from SVC */ + gpio_direction_input(arche_pdata->wake_detect_gpio); + enable_irq(arche_pdata->wake_detect_irq); +} + static irqreturn_t arche_platform_wd_irq_thread(int irq, void *devid) { struct arche_platform_drvdata *arche_pdata = devid; @@ -297,6 +307,8 @@ static ssize_t state_store(struct device *dev, return count; ret = arche_platform_coldboot_seq(arche_pdata); + + assert_wakedetect(arche_pdata); } else if (sysfs_streq(buf, "standby")) { if (arche_pdata->state == ARCHE_PLATFORM_STATE_STANDBY) return count; @@ -482,6 +494,7 @@ static int arche_platform_probe(struct platform_device *pdev) goto err_populate; } + assert_wakedetect(arche_pdata); INIT_DELAYED_WORK(&arche_pdata->delayed_work, hub_conf_delayed_work); dev_info(dev, "Device registered successfully\n"); -- cgit v0.10.2 From 0786212d6c1514545f33554b7403ea10d8061eb7 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Thu, 25 Feb 2016 04:37:38 +0530 Subject: greybus: arche-platform: Set direction of wake/detect gpio in poweroff fn With support of interrupt based mechanism, gpio is not longer set to output mode, so gpio_set_value won't work. So use gpio_direction_output() fn in poweroff(), while setting value on wake/detect line. Testing Done: Tested on DB3.5 platform. Signed-off-by: Vaibhav Hiremath Reviewed-by: Michael Scott Tested-by: Michael Scott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 87526b2b..5b393ec 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -266,7 +266,7 @@ static void arche_platform_poweroff_seq(struct arche_platform_drvdata *arche_pda /* If in fw_flashing mode, then no need to repeate things again */ if (arche_pdata->state != ARCHE_PLATFORM_STATE_FW_FLASHING) { /* Send disconnect/detach event to SVC */ - gpio_set_value(arche_pdata->wake_detect_gpio, 0); + gpio_direction_output(arche_pdata->wake_detect_gpio, 0); usleep_range(100, 200); spin_lock_irqsave(&arche_pdata->lock, flags); arche_pdata->wake_detect_state = WD_STATE_IDLE; -- cgit v0.10.2 From d2320b2dbf95216e9aedf69345862f934ae55138 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Thu, 25 Feb 2016 04:37:39 +0530 Subject: greybus: arche-platform: Disable wake/detect interrupt in poweroff In poweroff() fn, we are shutting down SVC, so disable interrupt as well. Testing Done: Tested on DB3.5 platform. Signed-off-by: Vaibhav Hiremath Reviewed-by: Michael Scott Tested-by: Michael Scott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 5b393ec..21a8438 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -265,6 +265,7 @@ static void arche_platform_poweroff_seq(struct arche_platform_drvdata *arche_pda /* If in fw_flashing mode, then no need to repeate things again */ if (arche_pdata->state != ARCHE_PLATFORM_STATE_FW_FLASHING) { + disable_irq(arche_pdata->wake_detect_irq); /* Send disconnect/detach event to SVC */ gpio_direction_output(arche_pdata->wake_detect_gpio, 0); usleep_range(100, 200); -- cgit v0.10.2 From 34804efb0c25d189bd9aa6e495a3bf5d778a0299 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Feb 2016 14:40:23 +0100 Subject: greybus: operation: add temporary pointer to response handler As a preparatory clean up, add a temporary variable to point to the response message header. Reviewed-by: Laurent Pinchart Tested-by: Laurent Pinchart Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index bd79f81..9de548d 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -858,6 +858,7 @@ static void gb_connection_recv_request(struct gb_connection *connection, static void gb_connection_recv_response(struct gb_connection *connection, u16 operation_id, u8 result, void *data, size_t size) { + struct gb_operation_msg_hdr *header; struct gb_operation *operation; struct gb_message *message; int errno = gb_operation_status_map(result); @@ -872,11 +873,12 @@ static void gb_connection_recv_response(struct gb_connection *connection, } message = operation->response; - message_size = sizeof(*message->header) + message->payload_size; + header = message->header; + message_size = sizeof(*header) + message->payload_size; if (!errno && size != message_size) { dev_err(&connection->hd->dev, "%s: malformed response 0x%02x received (%zu != %zu)\n", - connection->name, message->header->type, size, + connection->name, header->type, size, message_size); errno = -EMSGSIZE; } @@ -884,11 +886,11 @@ static void gb_connection_recv_response(struct gb_connection *connection, /* We must ignore the payload if a bad status is returned */ if (errno) - size = sizeof(*message->header); + size = sizeof(*header); /* The rest will be handled in work queue context */ if (gb_operation_result_set(operation, errno)) { - memcpy(message->header, data, size); + memcpy(header, data, size); queue_work(gb_operation_completion_wq, &operation->work); } -- cgit v0.10.2 From 7e43e337a524eb5ceab2cda9bbf882c35074bcc2 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Feb 2016 14:40:24 +0100 Subject: greybus: operation: add support for short responses Add support for operations with short responses. So far we have assumed that the initiator of an operation always knows the exact size of the expected response. This is however not always the case and we've worked around this limitation in a couple of places by, for example, first requesting the size of a resource before fetching the actual data. To avoid such workarounds and simplify our protocols, add a short-response flag that can be set when allocating an operation. When this flag is set on an operation, core will accept a response that is shorter than the size of the (pre-allocated) response payload buffer. For now, we update the response-message payload_size field to reflect the actual length of the response received. Reviewed-by: Laurent Pinchart Tested-by: Laurent Pinchart Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 9de548d..5818d7c 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -530,20 +530,25 @@ err_cache: * invalid operation type for all protocols, and this is enforced * here. */ -struct gb_operation *gb_operation_create(struct gb_connection *connection, - u8 type, size_t request_size, - size_t response_size, - gfp_t gfp) +struct gb_operation * +gb_operation_create_flags(struct gb_connection *connection, + u8 type, size_t request_size, + size_t response_size, unsigned long flags, + gfp_t gfp) { if (WARN_ON_ONCE(type == GB_OPERATION_TYPE_INVALID)) return NULL; if (WARN_ON_ONCE(type & GB_MESSAGE_TYPE_RESPONSE)) type &= ~GB_MESSAGE_TYPE_RESPONSE; + if (WARN_ON_ONCE(flags & ~GB_OPERATION_FLAG_USER_MASK)) + flags &= GB_OPERATION_FLAG_USER_MASK; + return gb_operation_create_common(connection, type, - request_size, response_size, 0, gfp); + request_size, response_size, + flags, gfp); } -EXPORT_SYMBOL_GPL(gb_operation_create); +EXPORT_SYMBOL_GPL(gb_operation_create_flags); size_t gb_operation_get_payload_size_max(struct gb_connection *connection) { @@ -875,12 +880,22 @@ static void gb_connection_recv_response(struct gb_connection *connection, message = operation->response; header = message->header; message_size = sizeof(*header) + message->payload_size; - if (!errno && size != message_size) { + if (!errno && size > message_size) { dev_err(&connection->hd->dev, - "%s: malformed response 0x%02x received (%zu != %zu)\n", - connection->name, header->type, size, - message_size); + "%s: malformed response 0x%02x received (%zu > %zu)\n", + connection->name, header->type, + size, message_size); errno = -EMSGSIZE; + } else if (!errno && size < message_size) { + if (gb_operation_short_response_allowed(operation)) { + message->payload_size = size - sizeof(*header); + } else { + dev_err(&connection->hd->dev, + "%s: short response 0x%02x received (%zu < %zu)\n", + connection->name, header->type, + size, message_size); + errno = -EMSGSIZE; + } } trace_gb_message_recv_response(operation->response); diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index c3f7ce7..38e5303 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -65,6 +65,9 @@ struct gb_message { #define GB_OPERATION_FLAG_INCOMING BIT(0) #define GB_OPERATION_FLAG_UNIDIRECTIONAL BIT(1) +#define GB_OPERATION_FLAG_SHORT_RESPONSE BIT(2) + +#define GB_OPERATION_FLAG_USER_MASK GB_OPERATION_FLAG_SHORT_RESPONSE /* * A Greybus operation is a remote procedure call performed over a @@ -119,16 +122,33 @@ gb_operation_is_unidirectional(struct gb_operation *operation) return operation->flags & GB_OPERATION_FLAG_UNIDIRECTIONAL; } +static inline bool +gb_operation_short_response_allowed(struct gb_operation *operation) +{ + return operation->flags & GB_OPERATION_FLAG_SHORT_RESPONSE; +} + void gb_connection_recv(struct gb_connection *connection, void *data, size_t size); int gb_operation_result(struct gb_operation *operation); size_t gb_operation_get_payload_size_max(struct gb_connection *connection); -struct gb_operation *gb_operation_create(struct gb_connection *connection, - u8 type, size_t request_size, - size_t response_size, - gfp_t gfp); +struct gb_operation * +gb_operation_create_flags(struct gb_connection *connection, + u8 type, size_t request_size, + size_t response_size, unsigned long flags, + gfp_t gfp); + +static inline struct gb_operation * +gb_operation_create(struct gb_connection *connection, + u8 type, size_t request_size, + size_t response_size, gfp_t gfp) +{ + return gb_operation_create_flags(connection, type, request_size, + response_size, 0, gfp); +} + void gb_operation_get(struct gb_operation *operation); void gb_operation_put(struct gb_operation *operation); -- cgit v0.10.2 From ff788de0b41b960d7b4a650e167cfcc0d3f63644 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Thu, 25 Feb 2016 16:45:44 +0530 Subject: greybus: arche-platform: Make sure APB power cycles on coldboot On first wake/detect pulse, everything works fine, as APB would be in poweroff state initially. But on subsequent wake/detect pulses, where APB is already in active state, internal function just returns doing nothing, as it finds that device is already in active state. So the solution would be to make sure that, whenever execution reaches to coldboot, make sure we power cycle it. Power off first, before powering on. Interrupt handler takes care of ignoring < 30msec pulses, so we should be safe here to power cycle APB. Testing Done: Testd on DB3.5 platform. Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 21a8438..f44c343 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -140,6 +140,8 @@ static irqreturn_t arche_platform_wd_irq_thread(int irq, void *devid) arche_pdata->wake_detect_state = WD_STATE_COLDBOOT_START; spin_unlock_irqrestore(&arche_pdata->lock, flags); + /* It should complete power cycle, so first make sure it is poweroff */ + device_for_each_child(arche_pdata->dev, NULL, apb_poweroff); /* Bring APB out of reset: cold boot sequence */ device_for_each_child(arche_pdata->dev, NULL, apb_cold_boot); -- cgit v0.10.2 From e915ce48bae606b79150a4d799a30037604a93ed Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Thu, 25 Feb 2016 16:45:45 +0530 Subject: greybus: arche-platform: Disable HUB3613 only in APB poweroff fn HUB3613 configuration, either disable (Standby mode) or enable (HUB mode) is related to APB. So it makes perfect sense to put both of them together in one function. HUB3613 enable happens only at one place, in hub_conf_delayed_work() fn, but disable is initiated from multiple places. Move all calls to usb3613_hub_mode_ctrl(false) to apb_poweroff(). Testing Done: Tested on DB3.5 platform. Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index f44c343..64dd8a1 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -94,6 +94,10 @@ static int apb_poweroff(struct device *dev, void *data) { apb_ctrl_poweroff(dev); + /* Enable HUB3613 into HUB mode. */ + if (usb3613_hub_mode_ctrl(false)) + dev_warn(dev, "failed to control hub device\n"); + return 0; } @@ -142,6 +146,7 @@ static irqreturn_t arche_platform_wd_irq_thread(int irq, void *devid) /* It should complete power cycle, so first make sure it is poweroff */ device_for_each_child(arche_pdata->dev, NULL, apb_poweroff); + /* Bring APB out of reset: cold boot sequence */ device_for_each_child(arche_pdata->dev, NULL, apb_cold_boot); @@ -301,10 +306,6 @@ static ssize_t state_store(struct device *dev, arche_platform_poweroff_seq(arche_pdata); - ret = usb3613_hub_mode_ctrl(false); - if (ret) - dev_warn(arche_pdata->dev, "failed to control hub device\n"); - /* TODO: Should we do anything more here ?? */ } else if (sysfs_streq(buf, "active")) { if (arche_pdata->state == ARCHE_PLATFORM_STATE_ACTIVE) return count; @@ -327,11 +328,6 @@ static ssize_t state_store(struct device *dev, arche_platform_poweroff_seq(arche_pdata); - ret = usb3613_hub_mode_ctrl(false); - if (ret) - dev_warn(arche_pdata->dev, "failed to control hub device\n"); - /* TODO: Should we do anything more here ?? */ - arche_platform_fw_flashing_seq(arche_pdata); device_for_each_child(arche_pdata->dev, NULL, apb_fw_flashing_state); -- cgit v0.10.2 From bf9deb29e2b3c5dbc97ce559325f4faa0bad5022 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Thu, 25 Feb 2016 18:05:09 +0000 Subject: greybus: lights: remove unnecessary check lights can never be NULL at that point since lights_count must be different than zero, and we need only to validate the light_id. Reported-by: Johan Hovold Signed-off-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index 17877f7..47d4ac4 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -1178,7 +1178,7 @@ static int gb_lights_request_handler(struct gb_operation *op) payload = request->payload; light_id = payload->light_id; - if (light_id >= glights->lights_count || !glights->lights || + if (light_id >= glights->lights_count || !glights->lights[light_id].ready) { dev_err(dev, "Event received for unconfigured light id: %d\n", light_id); -- cgit v0.10.2 From d97bbf3ed6211c01bd7df77d405dee2e9846cd68 Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Thu, 25 Feb 2016 18:19:13 +0100 Subject: greybus: loopback: Fix calculations error for ping transfers For the async ping transfer, statistics are counted twice, once after the after the gb_loopback_async_operation() and once in the callback. Only keep the one in the callback. Signed-off-by: Alexandre Bailon Reported-by: Johan Hovold Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index f3ae2e9..b40c95e 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -969,7 +969,6 @@ static int gb_loopback_fn(void *data) if (gb->async) { if (type == GB_LOOPBACK_TYPE_PING) { error = gb_loopback_async_ping(gb); - gb_loopback_calculate_stats(gb); } else if (type == GB_LOOPBACK_TYPE_TRANSFER) { error = gb_loopback_async_transfer(gb, size); } else if (type == GB_LOOPBACK_TYPE_SINK) { -- cgit v0.10.2 From d9048d8c96bfe2d18cdf7205b3de97aa344283a7 Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Thu, 25 Feb 2016 18:19:14 +0100 Subject: greybus: loopback: Fix incoherency in calculations in the case of error Currently, in case the case of error, statistics are updated for asynchronous but not for an asynchronous operation. Do not update the statistics in the case of error. Signed-off-by: Alexandre Bailon Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index b40c95e..a1f878b 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -398,10 +398,8 @@ static int gb_loopback_operation_sync(struct gb_loopback *gb, int type, do_gettimeofday(&ts); operation = gb_operation_create(gb->connection, type, request_size, response_size, GFP_KERNEL); - if (!operation) { - ret = -ENOMEM; - goto error; - } + if (!operation) + return -ENOMEM; if (request_size) memcpy(operation->request->payload, request, request_size); @@ -410,6 +408,7 @@ static int gb_loopback_operation_sync(struct gb_loopback *gb, int type, if (ret) { dev_err(&gb->connection->bundle->dev, "synchronous operation failed: %d\n", ret); + goto out_put_operation; } else { if (response_size == operation->response->payload_size) { memcpy(response, operation->response->payload, @@ -419,18 +418,20 @@ static int gb_loopback_operation_sync(struct gb_loopback *gb, int type, "response size %zu expected %d\n", operation->response->payload_size, response_size); + ret = -EINVAL; + goto out_put_operation; } } - gb_operation_put(operation); - -error: do_gettimeofday(&te); /* Calculate the total time the message took */ gb_loopback_push_latency_ts(gb, &ts, &te); gb->elapsed_nsecs = gb_loopback_calc_latency(&ts, &te); +out_put_operation: + gb_operation_put(operation); + return ret; } @@ -988,8 +989,9 @@ static int gb_loopback_fn(void *data) if (error) gb->error++; + else + gb_loopback_calculate_stats(gb); gb->iteration_count++; - gb_loopback_calculate_stats(gb); } send_count++; if (us_wait) -- cgit v0.10.2 From ab81bb9c68d9fb899b79fa622fedf294e66fa53d Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Thu, 25 Feb 2016 18:19:15 +0100 Subject: greybus: loopback: Fix throughput calculations Throughput and requests per second calculations are broken for asynchronous request. Instead of calculate the throughput for each iteration, calculate it once at the end of the test. In addition, update every seconds the min and the max for throughput and requests per second. Signed-off-by: Alexandre Bailon Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index a1f878b..85d3e35 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -81,6 +81,7 @@ struct gb_loopback { atomic_t outstanding_operations; /* Per connection stats */ + struct timeval ts; struct gb_loopback_stats latency; struct gb_loopback_stats throughput; struct gb_loopback_stats requests_per_second; @@ -351,7 +352,7 @@ static struct attribute *loopback_attrs[] = { }; ATTRIBUTE_GROUPS(loopback); -static void gb_loopback_calculate_stats(struct gb_loopback *gb); +static void gb_loopback_calculate_stats(struct gb_loopback *gb, bool error); static u32 gb_loopback_nsec_to_usec_latency(u64 elapsed_nsecs) { @@ -517,11 +518,9 @@ static void gb_loopback_async_operation_callback(struct gb_operation *operation) if (err) { gb->error++; } else { - gb->requests_completed++; gb_loopback_push_latency_ts(gb, &op_async->ts, &te); gb->elapsed_nsecs = gb_loopback_calc_latency(&op_async->ts, &te); - gb_loopback_calculate_stats(gb); } if (op_async->pending) { @@ -529,6 +528,7 @@ static void gb_loopback_async_operation_callback(struct gb_operation *operation) op_async->pending = false; del_timer_sync(&op_async->timer); gb_loopback_async_operation_put(op_async); + gb_loopback_calculate_stats(gb, err); } mutex_unlock(&gb->mutex); @@ -555,6 +555,7 @@ static void gb_loopback_async_operation_work(struct work_struct *work) gb->iteration_count++; op_async->pending = false; gb_loopback_async_operation_put(op_async); + gb_loopback_calculate_stats(gb, true); } mutex_unlock(&gb->mutex); @@ -847,6 +848,7 @@ static void gb_loopback_reset_stats(struct gb_loopback *gb) /* Should be initialized at least once per transaction set */ gb->apbridge_latency_ts = 0; gb->gpbridge_latency_ts = 0; + memset(&gb->ts, 0, sizeof(struct timeval)); } static void gb_loopback_update_stats(struct gb_loopback_stats *stats, u32 val) @@ -859,18 +861,29 @@ static void gb_loopback_update_stats(struct gb_loopback_stats *stats, u32 val) stats->count++; } +static void gb_loopback_update_stats_window(struct gb_loopback_stats *stats, + u64 val, u32 count) +{ + stats->sum += val; + stats->count += count; + + do_div(val, count); + if (stats->min > val) + stats->min = val; + if (stats->max < val) + stats->max = val; +} + static void gb_loopback_requests_update(struct gb_loopback *gb, u32 latency) { - u32 req = USEC_PER_SEC; + u64 req = gb->requests_completed * USEC_PER_SEC; - do_div(req, latency); - gb_loopback_update_stats(&gb->requests_per_second, req); + gb_loopback_update_stats_window(&gb->requests_per_second, req, latency); } static void gb_loopback_throughput_update(struct gb_loopback *gb, u32 latency) { - u32 throughput; - u32 aggregate_size = sizeof(struct gb_operation_msg_hdr) * 2; + u64 aggregate_size = sizeof(struct gb_operation_msg_hdr) * 2; switch (gb->type) { case GB_LOOPBACK_TYPE_PING: @@ -888,14 +901,13 @@ static void gb_loopback_throughput_update(struct gb_loopback *gb, u32 latency) return; } - /* Calculate bytes per second */ - throughput = USEC_PER_SEC; - do_div(throughput, latency); - throughput *= aggregate_size; - gb_loopback_update_stats(&gb->throughput, throughput); + aggregate_size *= gb->requests_completed; + aggregate_size *= USEC_PER_SEC; + gb_loopback_update_stats_window(&gb->throughput, aggregate_size, + latency); } -static void gb_loopback_calculate_stats(struct gb_loopback *gb) +static void gb_loopback_calculate_latency_stats(struct gb_loopback *gb) { u32 lat; @@ -908,10 +920,6 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb) /* Raw latency log on a per thread basis */ kfifo_in(&gb->kfifo_lat, (unsigned char *)&lat, sizeof(lat)); - /* Log throughput and requests using latency as benchmark */ - gb_loopback_throughput_update(gb, lat); - gb_loopback_requests_update(gb, lat); - /* Log the firmware supplied latency values */ gb_loopback_update_stats(&gb->apbridge_unipro_latency, gb->apbridge_latency_ts); @@ -919,6 +927,32 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb) gb->gpbridge_latency_ts); } +static void gb_loopback_calculate_stats(struct gb_loopback *gb, bool error) +{ + u64 nlat; + u32 lat; + struct timeval te; + + if (!error) { + gb->requests_completed++; + gb_loopback_calculate_latency_stats(gb); + } + + do_gettimeofday(&te); + nlat = gb_loopback_calc_latency(&gb->ts, &te); + if (nlat >= NSEC_PER_SEC || gb->iteration_count == gb->iteration_max) { + lat = gb_loopback_nsec_to_usec_latency(nlat); + + gb_loopback_throughput_update(gb, lat); + gb_loopback_requests_update(gb, lat); + + if (gb->iteration_count != gb->iteration_max) { + gb->ts = te; + gb->requests_completed = 0; + } + } +} + static void gb_loopback_async_wait_to_send(struct gb_loopback *gb) { if (!(gb->async && gb->outstanding_operations_max)) @@ -956,14 +990,18 @@ static int gb_loopback_fn(void *data) /* Optionally terminate */ if (send_count == gb->iteration_max) { - gb->type = 0; - send_count = 0; + if (gb->iteration_count == gb->iteration_max) { + gb->type = 0; + send_count = 0; + } mutex_unlock(&gb->mutex); continue; } size = gb->size; us_wait = gb->us_wait; type = gb->type; + if (gb->ts.tv_usec == 0 && gb->ts.tv_sec == 0) + do_gettimeofday(&gb->ts); mutex_unlock(&gb->mutex); /* Else operations to perform */ @@ -989,9 +1027,8 @@ static int gb_loopback_fn(void *data) if (error) gb->error++; - else - gb_loopback_calculate_stats(gb); gb->iteration_count++; + gb_loopback_calculate_stats(gb, !!error); } send_count++; if (us_wait) -- cgit v0.10.2 From fb37f137b78f186275b15e8ce1e5a26b51a6e6ad Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Thu, 25 Feb 2016 18:19:16 +0100 Subject: greybus: loopback: Fix averaging Currently, we are adding 0.5 to the average to round the average. But we are using the remainder to calculate the decimal, so we do not need to round the average. In addition, use a u64 type for the remainder to avoid overflow that might happen when stats->sum value is too big, usually for requests per seconds and the throughput. Signed-off-by: Alexandre Bailon Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 85d3e35..9f0da57 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -157,14 +157,15 @@ static ssize_t name##_avg_show(struct device *dev, \ { \ struct gb_loopback_stats *stats; \ struct gb_loopback *gb; \ - u64 avg; \ - u32 count, rem; \ + u64 avg, rem; \ + u32 count; \ gb = dev_get_drvdata(dev); \ stats = &gb->name; \ count = stats->count ? stats->count : 1; \ - avg = stats->sum + count / 2; /* round closest */ \ + avg = stats->sum; \ rem = do_div(avg, count); \ - return sprintf(buf, "%llu.%06u\n", avg, 1000000 * rem / count); \ + rem = 1000000 * rem / count; \ + return sprintf(buf, "%llu.%06u\n", avg, (u32)rem); \ } \ static DEVICE_ATTR_RO(name##_avg) -- cgit v0.10.2 From 611924dd72594200ac55957b4e68b0a65bab143b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 26 Feb 2016 21:54:38 -0800 Subject: greybus: expose full 32 bits of vid/pid to userspace Now that userspace is ready for all 32 bits of the vid/pid, take off our mask and send the full values. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 2fb9574..ca7469e 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -112,9 +112,8 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) if (intf) { if (add_uevent_var(env, "INTERFACE=%u", intf->interface_id)) return -ENOMEM; - if (add_uevent_var(env, "GREYBUS_ID=%04x/%04x", - (u16)(intf->vendor_id & 0xffff), - (u16)(intf->product_id & 0xffff))) + if (add_uevent_var(env, "GREYBUS_ID=%08x/%08x", + intf->vendor_id, intf->product_id)) return -ENOMEM; } diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 5e49bc8..2f3966f 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -23,33 +23,12 @@ static DEVICE_ATTR_RO(field) gb_interface_attr(ddbl1_manufacturer_id, "0x%08x"); gb_interface_attr(ddbl1_product_id, "0x%08x"); gb_interface_attr(interface_id, "%u"); +gb_interface_attr(vendor_id, "0x%08x"); +gb_interface_attr(product_id, "0x%08x"); gb_interface_attr(vendor_string, "%s"); gb_interface_attr(product_string, "%s"); gb_interface_attr(serial_number, "0x%016llx"); -static ssize_t vendor_id_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct gb_interface *intf = to_gb_interface(dev); - - /* clear the upper 16-bits to keep userspace "simple" */ - return scnprintf(buf, PAGE_SIZE, "0x%04x\n", - (0x0000FFFF & intf->vendor_id)); -} -static DEVICE_ATTR_RO(vendor_id); - -static ssize_t product_id_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct gb_interface *intf = to_gb_interface(dev); - - /* clear the upper 16-bits to keep userspace "simple" */ - return scnprintf(buf, PAGE_SIZE, "0x%04x\n", - (0x0000FFFF & intf->product_id)); -} -static DEVICE_ATTR_RO(product_id); - static ssize_t version_show(struct device *dev, struct device_attribute *attr, char *buf) { -- cgit v0.10.2 From 4a8e519902e73c833fb57f69bc194c2274dcdc30 Mon Sep 17 00:00:00 2001 From: Mark Greer Date: Fri, 26 Feb 2016 17:04:36 -0700 Subject: greybus: audio: Register CPorts for specific directions Currently, it is assumed that all audio data CPorts registered on APB1 are used for transmitting audio data. That may not always be true like when a microphone is connected but no speakers. Also, the current special protocol lacks a way to tell APB1 whether the CPort being registered is for transmitting, receiving, or both. Fix by adding a 'direction' field to the register and unregister CPort requests and define bits indicating which direction (or both) audio data will go on that CPort. Signed-off-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio_apbridgea.c b/drivers/staging/greybus/audio_apbridgea.c index 75c8c3c..bed087d 100644 --- a/drivers/staging/greybus/audio_apbridgea.c +++ b/drivers/staging/greybus/audio_apbridgea.c @@ -29,13 +29,15 @@ int gb_audio_apbridgea_set_config(struct gb_connection *connection, EXPORT_SYMBOL_GPL(gb_audio_apbridgea_set_config); int gb_audio_apbridgea_register_cport(struct gb_connection *connection, - __u16 i2s_port, __u16 cportid) + __u16 i2s_port, __u16 cportid, + __u8 direction) { struct audio_apbridgea_register_cport_request req; req.hdr.type = AUDIO_APBRIDGEA_TYPE_REGISTER_CPORT; req.hdr.i2s_port = cpu_to_le16(i2s_port); req.cport = cpu_to_le16(cportid); + req.direction = direction; return gb_hd_output(connection->hd, &req, sizeof(req), GB_APB_REQUEST_AUDIO_CONTROL, true); @@ -43,13 +45,15 @@ int gb_audio_apbridgea_register_cport(struct gb_connection *connection, EXPORT_SYMBOL_GPL(gb_audio_apbridgea_register_cport); int gb_audio_apbridgea_unregister_cport(struct gb_connection *connection, - __u16 i2s_port, __u16 cportid) + __u16 i2s_port, __u16 cportid, + __u8 direction) { struct audio_apbridgea_unregister_cport_request req; req.hdr.type = AUDIO_APBRIDGEA_TYPE_UNREGISTER_CPORT; req.hdr.i2s_port = cpu_to_le16(i2s_port); req.cport = cpu_to_le16(cportid); + req.direction = direction; return gb_hd_output(connection->hd, &req, sizeof(req), GB_APB_REQUEST_AUDIO_CONTROL, true); diff --git a/drivers/staging/greybus/audio_apbridgea.h b/drivers/staging/greybus/audio_apbridgea.h index d1d56b7..c543e39 100644 --- a/drivers/staging/greybus/audio_apbridgea.h +++ b/drivers/staging/greybus/audio_apbridgea.h @@ -75,6 +75,9 @@ #define AUDIO_APBRIDGEA_PCM_RATE_176400 BIT(11) #define AUDIO_APBRIDGEA_PCM_RATE_192000 BIT(12) +#define AUDIO_APBRIDGEA_DIRECTION_TX BIT(0) +#define AUDIO_APBRIDGEA_DIRECTION_RX BIT(1) + /* The I2S port is passed in the 'index' parameter of the USB request */ /* The CPort is passed in the 'value' parameter of the USB request */ @@ -94,11 +97,13 @@ struct audio_apbridgea_set_config_request { struct audio_apbridgea_register_cport_request { struct audio_apbridgea_hdr hdr; __le16 cport; + __u8 direction; } __packed; struct audio_apbridgea_unregister_cport_request { struct audio_apbridgea_hdr hdr; __le16 cport; + __u8 direction; } __packed; struct audio_apbridgea_set_tx_data_size_request { diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index d820116..5e29694 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -60,7 +60,8 @@ static int gbcodec_startup(struct snd_pcm_substream *substream, i2s_port = 0; /* fixed for now */ cportid = gb_dai->connection->hd_cport_id; ret = gb_audio_apbridgea_register_cport(gb_dai->connection, i2s_port, - cportid); + cportid, + AUDIO_APBRIDGEA_DIRECTION_TX); dev_dbg(dai->dev, "Register %s:%d DAI, ret:%d\n", dai->name, cportid, ret); @@ -117,7 +118,8 @@ static void gbcodec_shutdown(struct snd_pcm_substream *substream, /* un register cport */ i2s_port = 0; /* fixed for now */ ret = gb_audio_apbridgea_unregister_cport(gb_dai->connection, i2s_port, - gb_dai->connection->hd_cport_id); + gb_dai->connection->hd_cport_id, + AUDIO_APBRIDGEA_DIRECTION_TX); dev_dbg(dai->dev, "Unregister %s:%d DAI, ret:%d\n", dai->name, gb_dai->connection->hd_cport_id, ret); @@ -495,7 +497,8 @@ static void gb_audio_cleanup(struct gbaudio_codec_info *gb) ret); cportid = connection->hd_cport_id; ret = gb_audio_apbridgea_unregister_cport(connection, 0, - cportid); + cportid, + AUDIO_APBRIDGEA_DIRECTION_TX); if (ret) dev_info(dev, "%d:Failed during unregister cport\n", ret); diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index fc60c36..0631203 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -198,9 +198,11 @@ extern int gb_audio_apbridgea_set_config(struct gb_connection *connection, __u16 i2s_port, __u32 format, __u32 rate, __u32 mclk_freq); extern int gb_audio_apbridgea_register_cport(struct gb_connection *connection, - __u16 i2s_port, __u16 cportid); + __u16 i2s_port, __u16 cportid, + __u8 direction); extern int gb_audio_apbridgea_unregister_cport(struct gb_connection *connection, - __u16 i2s_port, __u16 cportid); + __u16 i2s_port, __u16 cportid, + __u8 direction); extern int gb_audio_apbridgea_set_tx_data_size(struct gb_connection *connection, __u16 i2s_port, __u16 size); extern int gb_audio_apbridgea_get_tx_delay(struct gb_connection *connection, -- cgit v0.10.2 From b22b7104d5930ed4aae2c8494b8f95f20a85d66b Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 29 Feb 2016 12:19:50 +0530 Subject: greybus: hid: Don't disable connection-tx before destroying hid-device hid_destroy_device() can potentially call callbacks defined in struct hid_ll_driver, which may initiate few greybus operations. And so connection (tx) should be kept enabled until the hid-device isn't destroyed. Reported-by: Jiss Kuruvila Reported-by: Laurent Pinchart Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index 4db337c..601ee6f 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -490,8 +490,8 @@ static void gb_hid_disconnect(struct gb_bundle *bundle) { struct gb_hid *ghid = greybus_get_drvdata(bundle); - gb_connection_disable(ghid->connection); hid_destroy_device(ghid->hid); + gb_connection_disable(ghid->connection); gb_connection_destroy(ghid->connection); kfree(ghid); } -- cgit v0.10.2 From 9b22f155beb4e5a71f86710034b478ec43af9c43 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 26 Feb 2016 16:44:19 +0530 Subject: greybus: hid: Replace WARN_ON() with dev_err() WARN_ON() is a bit harsh here, as we just failed to power-off the HID device while it is getting removed. Replace it with dev_err(). Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index 601ee6f..6ef151f 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -345,6 +345,7 @@ static int gb_hid_open(struct hid_device *hid) static void gb_hid_close(struct hid_device *hid) { struct gb_hid *ghid = hid->driver_data; + int ret; /* * Protecting hid->open to make sure we don't restart data acquistion @@ -355,7 +356,10 @@ static void gb_hid_close(struct hid_device *hid) clear_bit(GB_HID_STARTED, &ghid->flags); /* Save some power */ - WARN_ON(gb_hid_set_power(ghid, GB_HID_TYPE_PWR_OFF)); + ret = gb_hid_set_power(ghid, GB_HID_TYPE_PWR_OFF); + if (ret) + dev_err(&ghid->connection->bundle->dev, + "failed to power off (%d)\n", ret); } mutex_unlock(&gb_hid_open_mutex); } -- cgit v0.10.2 From 39c2787b120a6e69e065b255d4db97ee60d73bf8 Mon Sep 17 00:00:00 2001 From: Axel Haslam Date: Fri, 26 Feb 2016 11:39:48 +0100 Subject: greybus: Notify user space only when the test finished. Currently, user space is notified for every message sent, but this is not really needed and does not work in the async case where all messages are sent from the start. Instead, notify userspace only when all the transfers are complete. This allows userspace to wait in a poll loop and wakeup only when the test is finished. Also, don't use the bundle kobj to send the notification it is the loopback device that contains the loopback attributes. Signed-off-by: Axel Haslam Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 9f0da57..9014c2b 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -986,14 +986,14 @@ static int gb_loopback_fn(void *data) break; mutex_lock(&gb->mutex); - sysfs_notify(&gb->connection->bundle->dev.kobj, - NULL, "iteration_count"); /* Optionally terminate */ if (send_count == gb->iteration_max) { if (gb->iteration_count == gb->iteration_max) { gb->type = 0; send_count = 0; + sysfs_notify(&gb->dev->kobj, NULL, + "iteration_count"); } mutex_unlock(&gb->mutex); continue; -- cgit v0.10.2 From 9250c0ee2626d371753027b1b5ede697676de6d1 Mon Sep 17 00:00:00 2001 From: Axel Haslam Date: Fri, 26 Feb 2016 11:39:49 +0100 Subject: greybus: Loopback_test: use poll instead of inotify Inotify does not handle sysfs events, so use poll instead. The loopback kernel driver will send a notification when the test is complete. So, open a poll file descriptor for every enabled device, and after starting the test, wait for an event from each device. After all events are received, read the total number of iterations and make sure the test is complete. Also, add missing stdint header which was included in inotify. Signed-off-by: Axel Haslam Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/tools/loopback_test.c b/drivers/staging/greybus/tools/loopback_test.c index 6178354..0abe623 100644 --- a/drivers/staging/greybus/tools/loopback_test.c +++ b/drivers/staging/greybus/tools/loopback_test.c @@ -11,7 +11,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -22,8 +23,7 @@ #define CSV_MAX_LINE 0x1000 #define SYSFS_MAX_INT 0x20 #define MAX_STR_LEN 255 -#define MAX_TIMEOUT_COUNT 5 -#define TIMEOUT_SEC 1 +#define DEFAULT_POLL_TIMEOUT_SEC 30 #define DEFAULT_ASYNC_TIMEOUT 200000 struct dict { @@ -71,7 +71,6 @@ struct loopback_device { char name[MAX_SYSFS_PATH]; char sysfs_entry[MAX_SYSFS_PATH]; char debugfs_entry[MAX_SYSFS_PATH]; - int inotify_wd; struct loopback_results results; }; @@ -86,19 +85,22 @@ struct loopback_test { int aggregate_output; int test_id; int device_count; - int inotify_fd; int list_devices; int use_async; int async_timeout; + int poll_timeout; int async_outstanding_operations; int us_wait; int file_output; + int poll_count; char test_name[MAX_STR_LEN]; char sysfs_prefix[MAX_SYSFS_PATH]; char debugfs_prefix[MAX_SYSFS_PATH]; struct loopback_device devices[MAX_NUM_DEVICES]; struct loopback_results aggregate_results; + struct pollfd fds[MAX_NUM_DEVICES]; }; + struct loopback_test t; /* Helper macros to calculate the aggregate results for all devices */ @@ -201,6 +203,7 @@ void usage(void) " -l list found loopback devices and exit\n" " -x Async - Enable async transfers\n" " -o Async Timeout - Timeout in uSec for async operations\n" + " -O Poll loop time out in seconds(max time a test is expected to last, default: 30sec)\n" " -c Max number of outstanding operations for async operations\n" " -w Wait in uSec between operations\n" " -z Enable output to a CSV file (incompatible with -p)\n" @@ -638,58 +641,51 @@ baddir: return ret; } - -static int register_for_notification(struct loopback_test *t) +static int open_poll_files(struct loopback_test *t) { - char buf[MAX_SYSFS_PATH]; + struct loopback_device *dev; + char buf[MAX_STR_LEN]; + char dummy; + int fds_idx = 0; int i; - t->inotify_fd = inotify_init(); - if (t->inotify_fd < 0) { - fprintf(stderr, "inotify_init fail %s\n", strerror(errno)); - abort(); - } - for (i = 0; i < t->device_count; i++) { + dev = &t->devices[i]; + if (!device_enabled(t, i)) continue; - snprintf(buf, sizeof(buf), "%s%s", t->devices[i].sysfs_entry, - "iteration_count"); - - t->devices[i].inotify_wd = inotify_add_watch(t->inotify_fd, - buf, IN_MODIFY); - if (t->devices[i].inotify_wd < 0) { - fprintf(stderr, "inotify_add_watch %s fail %s\n", - buf, strerror(errno)); - close(t->inotify_fd); - abort(); + snprintf(buf, sizeof(buf), "%s%s", dev->sysfs_entry, "iteration_count"); + t->fds[fds_idx].fd = open(buf, O_RDONLY); + if (t->fds[fds_idx].fd < 0) { + fprintf(stderr, "Error opening poll file!\n"); + goto err; } + read(t->fds[fds_idx].fd, &dummy, 1); + t->fds[fds_idx].events = POLLERR|POLLPRI; + t->fds[fds_idx].revents = 0; + fds_idx++; } + t->poll_count = fds_idx; + return 0; + +err: + for (i = 0; i < fds_idx; i++) + close(t->fds[fds_idx].fd); + + return -1; } -static int unregister_for_notification(struct loopback_test *t) +static int close_poll_files(struct loopback_test *t) { int i; - int ret = 0; - - for (i = 0; i < t->device_count; i++) { - if (!device_enabled(t, i)) - continue; - - ret = inotify_rm_watch(t->inotify_fd, t->devices[i].inotify_wd); - if (ret) { - fprintf(stderr, "inotify_rm_watch error.\n"); - return ret; - } - } + for (i = 0; i < t->poll_count; i++) + close(t->fds[i].fd); - close(t->inotify_fd); return 0; } - static int is_complete(struct loopback_test *t) { int iteration_count; @@ -712,39 +708,38 @@ static int is_complete(struct loopback_test *t) static int wait_for_complete(struct loopback_test *t) { - int remaining_timeouts = MAX_TIMEOUT_COUNT; - char buf[MAX_SYSFS_PATH]; - struct timeval timeout; - fd_set read_fds; + int number_of_events = 0; + char dummy; int ret; + int i; while (1) { - /* Wait for change */ - timeout.tv_sec = TIMEOUT_SEC; - timeout.tv_usec = 0; - FD_ZERO(&read_fds); - FD_SET(t->inotify_fd, &read_fds); - ret = select(FD_SETSIZE, &read_fds, NULL, NULL, &timeout); - if (ret < 0) { - fprintf(stderr, "Select error.\n"); + ret = poll(t->fds, t->poll_count, DEFAULT_POLL_TIMEOUT_SEC * 1000); + if (ret == 0) { + fprintf(stderr, "Poll timmed out!\n"); return -1; } - /* timeout - test may be finished.*/ - if (!FD_ISSET(t->inotify_fd, &read_fds)) { - remaining_timeouts--; - - if (is_complete(t)) - return 0; + if (ret < 0) { + fprintf(stderr, "Poll Error!\n"); + return -1; + } - if (!remaining_timeouts) { - fprintf(stderr, "Too many timeouts\n"); - return -1; + for (i = 0; i < t->poll_count; i++) { + if (t->fds[i].revents & POLLPRI) { + /* Dummy read to clear the event */ + read(t->fds[i].fd, &dummy, 1); + number_of_events++; } - } else { - /* read to clear the event */ - ret = read(t->inotify_fd, buf, sizeof(buf)); } + + if (number_of_events == t->poll_count) + break; + } + + if (!is_complete(t)) { + fprintf(stderr, "Iteration count did not finish!\n"); + return -1; } return 0; @@ -820,17 +815,17 @@ void loopback_run(struct loopback_test *t) prepare_devices(t); - ret = register_for_notification(t); + ret = open_poll_files(t); if (ret) goto err; start(t); - sleep(1); - - wait_for_complete(t); + ret = wait_for_complete(t); + close_poll_files(t); + if (ret) + goto err; - unregister_for_notification(t); get_results(t); @@ -875,7 +870,7 @@ int main(int argc, char *argv[]) memset(&t, 0, sizeof(t)); while ((o = getopt(argc, argv, - "t:s:i:S:D:m:v::d::r::p::a::l::x::o:c:w:")) != -1) { + "t:s:i:S:D:m:v::d::r::p::a::l::x::o:c:w:O:")) != -1) { switch (o) { case 't': snprintf(t.test_name, MAX_STR_LEN, "%s", optarg); @@ -919,6 +914,9 @@ int main(int argc, char *argv[]) case 'o': t.async_timeout = atoi(optarg); break; + case 'O': + t.poll_timeout = atoi(optarg); + break; case 'c': t.async_outstanding_operations = atoi(optarg); break; @@ -957,6 +955,9 @@ int main(int argc, char *argv[]) if (t.async_timeout == 0) t.async_timeout = DEFAULT_ASYNC_TIMEOUT; + if (t.poll_timeout == 0) + t.poll_timeout = DEFAULT_POLL_TIMEOUT_SEC; + loopback_run(&t); return 0; -- cgit v0.10.2 From 5bbe14b7acc2a00f51b23812ffc596577d94e80b Mon Sep 17 00:00:00 2001 From: Mark Greer Date: Mon, 29 Feb 2016 15:31:02 -0700 Subject: greybus: audio: Split start and stop APBridgeA requests Provide finer-grained control of the audio streaming on APB1 by splitting the transmit/receive start and stop requests into prepare, start, stop, and shutdown. CC: Vaibhav Agarwal Signed-off-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio_apbridgea.c b/drivers/staging/greybus/audio_apbridgea.c index bed087d..a6e089d 100644 --- a/drivers/staging/greybus/audio_apbridgea.c +++ b/drivers/staging/greybus/audio_apbridgea.c @@ -82,6 +82,19 @@ int gb_audio_apbridgea_get_tx_delay(struct gb_connection *connection, } EXPORT_SYMBOL_GPL(gb_audio_apbridgea_get_tx_delay); +int gb_audio_apbridgea_prepare_tx(struct gb_connection *connection, + __u16 i2s_port) +{ + struct audio_apbridgea_prepare_tx_request req; + + req.hdr.type = AUDIO_APBRIDGEA_TYPE_PREPARE_TX; + req.hdr.i2s_port = cpu_to_le16(i2s_port); + + return gb_hd_output(connection->hd, &req, sizeof(req), + GB_APB_REQUEST_AUDIO_CONTROL, true); +} +EXPORT_SYMBOL_GPL(gb_audio_apbridgea_prepare_tx); + int gb_audio_apbridgea_start_tx(struct gb_connection *connection, __u16 i2s_port, __u64 timestamp) { @@ -108,6 +121,19 @@ int gb_audio_apbridgea_stop_tx(struct gb_connection *connection, __u16 i2s_port) } EXPORT_SYMBOL_GPL(gb_audio_apbridgea_stop_tx); +int gb_audio_apbridgea_shutdown_tx(struct gb_connection *connection, + __u16 i2s_port) +{ + struct audio_apbridgea_shutdown_tx_request req; + + req.hdr.type = AUDIO_APBRIDGEA_TYPE_SHUTDOWN_TX; + req.hdr.i2s_port = cpu_to_le16(i2s_port); + + return gb_hd_output(connection->hd, &req, sizeof(req), + GB_APB_REQUEST_AUDIO_CONTROL, true); +} +EXPORT_SYMBOL_GPL(gb_audio_apbridgea_shutdown_tx); + int gb_audio_apbridgea_set_rx_data_size(struct gb_connection *connection, __u16 i2s_port, __u16 size) { @@ -130,6 +156,19 @@ int gb_audio_apbridgea_get_rx_delay(struct gb_connection *connection, } EXPORT_SYMBOL_GPL(gb_audio_apbridgea_get_rx_delay); +int gb_audio_apbridgea_prepare_rx(struct gb_connection *connection, + __u16 i2s_port) +{ + struct audio_apbridgea_prepare_rx_request req; + + req.hdr.type = AUDIO_APBRIDGEA_TYPE_PREPARE_RX; + req.hdr.i2s_port = cpu_to_le16(i2s_port); + + return gb_hd_output(connection->hd, &req, sizeof(req), + GB_APB_REQUEST_AUDIO_CONTROL, true); +} +EXPORT_SYMBOL_GPL(gb_audio_apbridgea_prepare_rx); + int gb_audio_apbridgea_start_rx(struct gb_connection *connection, __u16 i2s_port) { @@ -155,6 +194,19 @@ int gb_audio_apbridgea_stop_rx(struct gb_connection *connection, __u16 i2s_port) } EXPORT_SYMBOL_GPL(gb_audio_apbridgea_stop_rx); +int gb_audio_apbridgea_shutdown_rx(struct gb_connection *connection, + __u16 i2s_port) +{ + struct audio_apbridgea_shutdown_rx_request req; + + req.hdr.type = AUDIO_APBRIDGEA_TYPE_SHUTDOWN_RX; + req.hdr.i2s_port = cpu_to_le16(i2s_port); + + return gb_hd_output(connection->hd, &req, sizeof(req), + GB_APB_REQUEST_AUDIO_CONTROL, true); +} +EXPORT_SYMBOL_GPL(gb_audio_apbridgea_shutdown_rx); + MODULE_LICENSE("GPL v2"); MODULE_ALIAS("greybus:audio-apbridgea"); MODULE_DESCRIPTION("Greybus Special APBridgeA Audio Protocol library"); diff --git a/drivers/staging/greybus/audio_apbridgea.h b/drivers/staging/greybus/audio_apbridgea.h index c543e39..a48f815 100644 --- a/drivers/staging/greybus/audio_apbridgea.h +++ b/drivers/staging/greybus/audio_apbridgea.h @@ -48,12 +48,16 @@ #define AUDIO_APBRIDGEA_TYPE_UNREGISTER_CPORT 0x03 #define AUDIO_APBRIDGEA_TYPE_SET_TX_DATA_SIZE 0x04 #define AUDIO_APBRIDGEA_TYPE_GET_TX_DELAY 0x05 -#define AUDIO_APBRIDGEA_TYPE_START_TX 0x06 -#define AUDIO_APBRIDGEA_TYPE_STOP_TX 0x07 -#define AUDIO_APBRIDGEA_TYPE_SET_RX_DATA_SIZE 0x08 -#define AUDIO_APBRIDGEA_TYPE_GET_RX_DELAY 0x09 -#define AUDIO_APBRIDGEA_TYPE_START_RX 0x0a -#define AUDIO_APBRIDGEA_TYPE_STOP_RX 0x0b +#define AUDIO_APBRIDGEA_TYPE_PREPARE_TX 0x06 +#define AUDIO_APBRIDGEA_TYPE_START_TX 0x07 +#define AUDIO_APBRIDGEA_TYPE_STOP_TX 0x08 +#define AUDIO_APBRIDGEA_TYPE_SHUTDOWN_TX 0x09 +#define AUDIO_APBRIDGEA_TYPE_SET_RX_DATA_SIZE 0x0a +#define AUDIO_APBRIDGEA_TYPE_GET_RX_DELAY 0x0b +#define AUDIO_APBRIDGEA_TYPE_PREPARE_RX 0x0c +#define AUDIO_APBRIDGEA_TYPE_START_RX 0x0d +#define AUDIO_APBRIDGEA_TYPE_STOP_RX 0x0e +#define AUDIO_APBRIDGEA_TYPE_SHUTDOWN_RX 0x0f #define AUDIO_APBRIDGEA_PCM_FMT_8 BIT(0) #define AUDIO_APBRIDGEA_PCM_FMT_16 BIT(1) @@ -120,6 +124,10 @@ struct audio_apbridgea_get_tx_delay_response { __le16 delay; } __packed; +struct audio_apbridgea_prepare_tx_request { + struct audio_apbridgea_hdr hdr; +} __packed; + struct audio_apbridgea_start_tx_request { struct audio_apbridgea_hdr hdr; __le64 timestamp; @@ -129,6 +137,10 @@ struct audio_apbridgea_stop_tx_request { struct audio_apbridgea_hdr hdr; } __packed; +struct audio_apbridgea_shutdown_tx_request { + struct audio_apbridgea_hdr hdr; +} __packed; + struct audio_apbridgea_set_rx_data_size_request { struct audio_apbridgea_hdr hdr; __le16 size; @@ -143,6 +155,10 @@ struct audio_apbridgea_get_rx_delay_response { __le16 delay; } __packed; +struct audio_apbridgea_prepare_rx_request { + struct audio_apbridgea_hdr hdr; +} __packed; + struct audio_apbridgea_start_rx_request { struct audio_apbridgea_hdr hdr; } __packed; @@ -151,4 +167,8 @@ struct audio_apbridgea_stop_rx_request { struct audio_apbridgea_hdr hdr; } __packed; +struct audio_apbridgea_shutdown_rx_request { + struct audio_apbridgea_hdr hdr; +} __packed; + #endif /*__AUDIO_APBRIDGEA_H */ diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 5e29694..d7cae77 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -345,17 +345,33 @@ static int gbcodec_trigger(struct snd_pcm_substream *substream, int cmd, goto func_exit; } - if (start && tx) - ret = gb_audio_apbridgea_start_tx(gb_dai->connection, 0, 0); + if (start && tx) { + ret = gb_audio_apbridgea_prepare_tx(gb_dai->connection, 0); + if (!ret) + ret = gb_audio_apbridgea_start_tx(gb_dai->connection, 0, + 0); + } - else if (start && rx) - ret = gb_audio_apbridgea_start_rx(gb_dai->connection, 0); + else if (start && rx) { + ret = gb_audio_apbridgea_prepare_rx(gb_dai->connection, 0); + if (!ret) + ret = gb_audio_apbridgea_start_rx(gb_dai->connection, + 0); + } - else if (stop && tx) + else if (stop && tx) { ret = gb_audio_apbridgea_stop_tx(gb_dai->connection, 0); + if (!ret) + ret = gb_audio_apbridgea_shutdown_tx(gb_dai->connection, + 0); + } - else if (stop && rx) + else if (stop && rx) { ret = gb_audio_apbridgea_stop_rx(gb_dai->connection, 0); + if (!ret) + ret = gb_audio_apbridgea_shutdown_rx(gb_dai->connection, + 0); + } else ret = -EINVAL; @@ -488,6 +504,10 @@ static void gb_audio_cleanup(struct gbaudio_codec_info *gb) if (ret) dev_info(dev, "%d:Failed during APBridge stop_tx\n", ret); + ret = gb_audio_apbridgea_shutdown_tx(connection, 0); + if (ret) + dev_info(dev, "%d:Failed during APBridge shutdown_tx\n", + ret); cportid = connection->intf_cport_id; ret = gb_audio_gb_deactivate_tx(gb->mgmt_connection, cportid); diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index 0631203..9197adc 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -207,17 +207,25 @@ extern int gb_audio_apbridgea_set_tx_data_size(struct gb_connection *connection, __u16 i2s_port, __u16 size); extern int gb_audio_apbridgea_get_tx_delay(struct gb_connection *connection, __u16 i2s_port, __u32 *delay); +extern int gb_audio_apbridgea_prepare_tx(struct gb_connection *connection, + __u16 i2s_port); extern int gb_audio_apbridgea_start_tx(struct gb_connection *connection, __u16 i2s_port, __u64 timestamp); extern int gb_audio_apbridgea_stop_tx(struct gb_connection *connection, __u16 i2s_port); +extern int gb_audio_apbridgea_shutdown_tx(struct gb_connection *connection, + __u16 i2s_port); extern int gb_audio_apbridgea_set_rx_data_size(struct gb_connection *connection, __u16 i2s_port, __u16 size); extern int gb_audio_apbridgea_get_rx_delay(struct gb_connection *connection, __u16 i2s_port, __u32 *delay); +extern int gb_audio_apbridgea_prepare_rx(struct gb_connection *connection, + __u16 i2s_port); extern int gb_audio_apbridgea_start_rx(struct gb_connection *connection, __u16 i2s_port); extern int gb_audio_apbridgea_stop_rx(struct gb_connection *connection, __u16 i2s_port); +extern int gb_audio_apbridgea_shutdown_rx(struct gb_connection *connection, + __u16 i2s_port); #endif /* __LINUX_GBAUDIO_CODEC_H */ -- cgit v0.10.2 From 41993cd54fdc5c774cc4881e18a21e3e4a2544cd Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 3 Mar 2016 15:29:39 +0100 Subject: greybus: loopback: fix double error count Make sure not count errors during asynchronous tests twice (first in the timeout handler then again in the completion handler) to avoid obviously broken error stats such as: $ loopback_test -i 1000 -t transfer -p -o 200000 -c 64 -x -s 2000 1970-1-1 1:3:35 test: transfer path: gb_loopback0 size: 2000 iterations: 1000 errors: 1998 async: Enabled requests per-sec: min=0, max=0, average=0.310556, jitter=0 ap-throughput B/s: min=0 max=4026 average=1254.647461 jitter=4026 ap-latency usec: min=12803 max=12803 average=12803.000000 jitter=0 apbridge-latency usec: min=89 max=89 average=89.000000 jitter=0 gpbridge-latency usec: min=294 max=294 average=294.000000 jitter=0 where we supposedly have more errors than iterations (operations initiated). Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 9014c2b..ba6e12a 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -516,15 +516,15 @@ static void gb_loopback_async_operation_callback(struct gb_operation *operation) err = true; } - if (err) { - gb->error++; - } else { + if (!err) { gb_loopback_push_latency_ts(gb, &op_async->ts, &te); gb->elapsed_nsecs = gb_loopback_calc_latency(&op_async->ts, &te); } if (op_async->pending) { + if (err) + gb->error++; gb->iteration_count++; op_async->pending = false; del_timer_sync(&op_async->timer); -- cgit v0.10.2 From c7733b6167750a42da81133189e9cca33ce7584f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 2 Mar 2016 18:00:51 +0100 Subject: greybus: raw: use hexadecimal notation for request types Use hexadecimal notation for request types in log messages. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/raw.c b/drivers/staging/greybus/raw.c index 338139e..729d258 100644 --- a/drivers/staging/greybus/raw.c +++ b/drivers/staging/greybus/raw.c @@ -97,7 +97,7 @@ static int gb_raw_request_handler(struct gb_operation *op) u32 len; if (op->type != GB_RAW_TYPE_SEND) { - dev_err(dev, "unknown request type %d\n", op->type); + dev_err(dev, "unknown request type 0x%02x\n", op->type); return -EINVAL; } -- cgit v0.10.2 From e494b580ea23a98f2f3b3507157c2d573240486c Mon Sep 17 00:00:00 2001 From: Michael Mogenson Date: Thu, 3 Mar 2016 16:23:11 -0500 Subject: greybus: remove gb_i2c_timeout_operation Set timeout operation was removed from the Greybus specification. Remove gb_i2c_timeout_operation and all other no longer necessary code bits from the Greybus kernel code. Signed-off-by: Michael Mogenson Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index f283912..f1b5cf6 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -495,23 +495,16 @@ struct gb_hid_input_report_request { /* Greybus i2c request types */ #define GB_I2C_TYPE_FUNCTIONALITY 0x02 -#define GB_I2C_TYPE_TIMEOUT 0x03 #define GB_I2C_TYPE_RETRIES 0x04 #define GB_I2C_TYPE_TRANSFER 0x05 #define GB_I2C_RETRIES_DEFAULT 3 -#define GB_I2C_TIMEOUT_DEFAULT 1000 /* milliseconds */ /* functionality request has no payload */ struct gb_i2c_functionality_response { __le32 functionality; } __packed; -struct gb_i2c_timeout_request { - __le16 msec; -} __packed; -/* timeout response has no payload */ - struct gb_i2c_retries_request { __u8 retries; } __packed; diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c index ec74e87..d9d483d 100644 --- a/drivers/staging/greybus/i2c.c +++ b/drivers/staging/greybus/i2c.c @@ -18,7 +18,6 @@ struct gb_i2c_device { struct gb_connection *connection; u32 functionality; - u16 timeout_msec; u8 retries; struct i2c_adapter adapter; @@ -50,23 +49,6 @@ static int gb_i2c_functionality_operation(struct gb_i2c_device *gb_i2c_dev) return 0; } -static int gb_i2c_timeout_operation(struct gb_i2c_device *gb_i2c_dev, u16 msec) -{ - struct device *dev = &gb_i2c_dev->connection->bundle->dev; - struct gb_i2c_timeout_request request; - int ret; - - request.msec = cpu_to_le16(msec); - ret = gb_operation_sync(gb_i2c_dev->connection, GB_I2C_TYPE_TIMEOUT, - &request, sizeof(request), NULL, 0); - if (ret) - dev_err(dev, "timeout operation failed (%d)\n", ret); - else - gb_i2c_dev->timeout_msec = msec; - - return ret; -} - static int gb_i2c_retries_operation(struct gb_i2c_device *gb_i2c_dev, u8 retries) { @@ -267,8 +249,8 @@ static const struct i2c_algorithm gb_i2c_algorithm = { /* * Do initial setup of the i2c device. This includes verifying we * can support it (based on the protocol version it advertises). - * If that's OK, we get and cached its functionality bits, and - * set up the retry count and timeout. + * If that's OK, we get and cached its functionality bits and + * set up the retry count. * * Note: gb_i2c_dev->connection is assumed to have been valid. */ @@ -281,12 +263,8 @@ static int gb_i2c_device_setup(struct gb_i2c_device *gb_i2c_dev) if (ret) return ret; - /* Set up our default retry count and timeout */ - ret = gb_i2c_retries_operation(gb_i2c_dev, GB_I2C_RETRIES_DEFAULT); - if (ret) - return ret; - - return gb_i2c_timeout_operation(gb_i2c_dev, GB_I2C_TIMEOUT_DEFAULT); + /* Set up our default retry count */ + return gb_i2c_retries_operation(gb_i2c_dev, GB_I2C_RETRIES_DEFAULT); } static int gb_i2c_connection_init(struct gb_connection *connection) @@ -312,7 +290,6 @@ static int gb_i2c_connection_init(struct gb_connection *connection) adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; adapter->algo = &gb_i2c_algorithm; /* adapter->algo_data = what? */ - adapter->timeout = gb_i2c_dev->timeout_msec * HZ / 1000; adapter->retries = gb_i2c_dev->retries; adapter->dev.parent = &connection->bundle->dev; -- cgit v0.10.2 From 3522a09fa7df45b49c27997b419a20d9dcff8919 Mon Sep 17 00:00:00 2001 From: Michael Mogenson Date: Thu, 3 Mar 2016 16:23:12 -0500 Subject: greybus: remove gb_i2c_retries_operation Set retries operation was removed from the Greybus specification. Remove gb_i2c_retries_operation and all other no longer necessary code bits from the Greybus kernel code. Signed-off-by: Michael Mogenson Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index f1b5cf6..b60c7dc 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -495,21 +495,13 @@ struct gb_hid_input_report_request { /* Greybus i2c request types */ #define GB_I2C_TYPE_FUNCTIONALITY 0x02 -#define GB_I2C_TYPE_RETRIES 0x04 #define GB_I2C_TYPE_TRANSFER 0x05 -#define GB_I2C_RETRIES_DEFAULT 3 - /* functionality request has no payload */ struct gb_i2c_functionality_response { __le32 functionality; } __packed; -struct gb_i2c_retries_request { - __u8 retries; -} __packed; -/* retries response has no payload */ - /* * Outgoing data immediately follows the op count and ops array. * The data for each write (master -> slave) op in the array is sent diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c index d9d483d..cb68b45 100644 --- a/drivers/staging/greybus/i2c.c +++ b/drivers/staging/greybus/i2c.c @@ -18,7 +18,6 @@ struct gb_i2c_device { struct gb_connection *connection; u32 functionality; - u8 retries; struct i2c_adapter adapter; }; @@ -49,25 +48,6 @@ static int gb_i2c_functionality_operation(struct gb_i2c_device *gb_i2c_dev) return 0; } -static int gb_i2c_retries_operation(struct gb_i2c_device *gb_i2c_dev, - u8 retries) -{ - struct device *dev = &gb_i2c_dev->connection->bundle->dev; - struct gb_i2c_retries_request request; - int ret; - - request.retries = retries; - ret = gb_operation_sync(gb_i2c_dev->connection, GB_I2C_TYPE_RETRIES, - &request, sizeof(request), NULL, 0); - if (ret) - dev_err(dev, "retries operation failed (%d)\n", ret); - else - gb_i2c_dev->retries = retries; - - return ret; -} - - /* * Map Linux i2c_msg flags into Greybus i2c transfer op flags. */ @@ -249,22 +229,14 @@ static const struct i2c_algorithm gb_i2c_algorithm = { /* * Do initial setup of the i2c device. This includes verifying we * can support it (based on the protocol version it advertises). - * If that's OK, we get and cached its functionality bits and - * set up the retry count. + * If that's OK, we get and cached its functionality bits. * * Note: gb_i2c_dev->connection is assumed to have been valid. */ static int gb_i2c_device_setup(struct gb_i2c_device *gb_i2c_dev) { - int ret; - /* Assume the functionality never changes, just get it once */ - ret = gb_i2c_functionality_operation(gb_i2c_dev); - if (ret) - return ret; - - /* Set up our default retry count */ - return gb_i2c_retries_operation(gb_i2c_dev, GB_I2C_RETRIES_DEFAULT); + return gb_i2c_functionality_operation(gb_i2c_dev); } static int gb_i2c_connection_init(struct gb_connection *connection) @@ -290,7 +262,6 @@ static int gb_i2c_connection_init(struct gb_connection *connection) adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; adapter->algo = &gb_i2c_algorithm; /* adapter->algo_data = what? */ - adapter->retries = gb_i2c_dev->retries; adapter->dev.parent = &connection->bundle->dev; snprintf(adapter->name, sizeof(adapter->name), "Greybus i2c adapter"); -- cgit v0.10.2 From c7b07265046b5db56778dc8c2cfc9056413ec5ba Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 28 Feb 2016 14:42:54 -0800 Subject: greybus: gpbridge.h: move protocol init/exit prototypes Create gpbridge.h for the gpbridge-specific function prototypes, the rest of the greybus drivers don't care about them. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Viresh Kumar Reviewed-by: Johan Hovold diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c index 29f0984..c82ded1 100644 --- a/drivers/staging/greybus/gpbridge.c +++ b/drivers/staging/greybus/gpbridge.c @@ -17,7 +17,7 @@ #include #include "greybus.h" - +#include "gpbridge.h" static int __init gpbridge_init(void) { diff --git a/drivers/staging/greybus/gpbridge.h b/drivers/staging/greybus/gpbridge.h new file mode 100644 index 0000000..50ee87b --- /dev/null +++ b/drivers/staging/greybus/gpbridge.h @@ -0,0 +1,34 @@ +/* + * Greybus GPBridge phy driver + * + * Copyright 2016 Google Inc. + * + * Released under the GPLv2 only. + */ + +#ifndef __GPBRIDGE_H +#define __GPBRIDGE_H + +extern int gb_gpio_protocol_init(void); +extern void gb_gpio_protocol_exit(void); + +extern int gb_pwm_protocol_init(void); +extern void gb_pwm_protocol_exit(void); + +extern int gb_uart_protocol_init(void); +extern void gb_uart_protocol_exit(void); + +extern int gb_sdio_protocol_init(void); +extern void gb_sdio_protocol_exit(void); + +extern int gb_usb_protocol_init(void); +extern void gb_usb_protocol_exit(void); + +extern int gb_i2c_protocol_init(void); +extern void gb_i2c_protocol_exit(void); + +extern int gb_spi_protocol_init(void); +extern void gb_spi_protocol_exit(void); + +#endif /* __GPBRIDGE_H */ + diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index e7dd994..7b2cb5d 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -16,6 +16,7 @@ #include #include "greybus.h" +#include "gpbridge.h" struct gb_gpio_line { /* The following has to be an array of line_max entries */ diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c index cb68b45..4b96f69 100644 --- a/drivers/staging/greybus/i2c.c +++ b/drivers/staging/greybus/i2c.c @@ -13,6 +13,7 @@ #include #include "greybus.h" +#include "gpbridge.h" struct gb_i2c_device { struct gb_connection *connection; diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h index 26c59ef..38fe14c 100644 --- a/drivers/staging/greybus/protocol.h +++ b/drivers/staging/greybus/protocol.h @@ -48,32 +48,6 @@ int gb_protocol_get_version(struct gb_connection *connection); void gb_protocol_put(struct gb_protocol *protocol); -/* - * These are defined in their respective protocol source files. - * Declared here for now. They could be added via modules, or maybe - * just use initcalls (which level?). - */ -extern int gb_gpio_protocol_init(void); -extern void gb_gpio_protocol_exit(void); - -extern int gb_pwm_protocol_init(void); -extern void gb_pwm_protocol_exit(void); - -extern int gb_uart_protocol_init(void); -extern void gb_uart_protocol_exit(void); - -extern int gb_sdio_protocol_init(void); -extern void gb_sdio_protocol_exit(void); - -extern int gb_usb_protocol_init(void); -extern void gb_usb_protocol_exit(void); - -extern int gb_i2c_protocol_init(void); -extern void gb_i2c_protocol_exit(void); - -extern int gb_spi_protocol_init(void); -extern void gb_spi_protocol_exit(void); - /* __protocol: Pointer to struct gb_protocol */ #define gb_protocol_driver(__protocol) \ static int __init protocol_init(void) \ diff --git a/drivers/staging/greybus/pwm.c b/drivers/staging/greybus/pwm.c index c3a3a9d..018d5c2 100644 --- a/drivers/staging/greybus/pwm.c +++ b/drivers/staging/greybus/pwm.c @@ -13,6 +13,7 @@ #include #include "greybus.h" +#include "gpbridge.h" struct gb_pwm_chip { struct gb_connection *connection; diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index da90937..9a20f0e 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -15,6 +15,7 @@ #include #include "greybus.h" +#include "gpbridge.h" struct gb_sdio_host { struct gb_connection *connection; diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index 7689af0..3571453 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -14,6 +14,7 @@ #include #include "greybus.h" +#include "gpbridge.h" struct gb_spi { struct gb_connection *connection; diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 0685cdc..d169c55 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -29,6 +29,7 @@ #include #include "greybus.h" +#include "gpbridge.h" #define GB_NUM_MINORS 16 /* 16 is is more than enough */ #define GB_NAME "ttyGB" diff --git a/drivers/staging/greybus/usb.c b/drivers/staging/greybus/usb.c index 6647868..0cfc00f 100644 --- a/drivers/staging/greybus/usb.c +++ b/drivers/staging/greybus/usb.c @@ -14,6 +14,7 @@ #include #include "greybus.h" +#include "gpbridge.h" /* Version of the Greybus USB protocol we support */ #define GB_USB_VERSION_MAJOR 0x00 -- cgit v0.10.2 From d6fefbe19327f4137360d7ab8af78f1d4d9b909e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 28 Feb 2016 14:13:27 -0800 Subject: greybus: manifest: reserve the Bridged PHY class This reserves the bridged phy class number to be used later on. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Viresh Kumar Reviewed-by: Johan Hovold diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c index c82ded1..9be936c 100644 --- a/drivers/staging/greybus/gpbridge.c +++ b/drivers/staging/greybus/gpbridge.c @@ -81,4 +81,16 @@ static void __exit gpbridge_exit(void) } module_exit(gpbridge_exit); +/* + * One large list of all classes we support in the gpbridge.ko module. + * + * Due to limitations in older kernels, the different phy .c files can not + * contain their own MODULE_DEVICE_TABLE(), so put them all here for now. + */ +static const struct greybus_bundle_id bridged_phy_id_table[] = { + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_BRIDGED_PHY) }, + { }, +}; +MODULE_DEVICE_TABLE(greybus, bridged_phy_id_table); + MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 76649a6..b9504c7 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -61,7 +61,7 @@ enum greybus_class_type { GREYBUS_CLASS_SDIO = 0x07, GREYBUS_CLASS_POWER_SUPPLY = 0x08, GREYBUS_CLASS_PWM = 0x09, - /* 0x0a is unused */ + GREYBUS_CLASS_BRIDGED_PHY = 0x0a, GREYBUS_CLASS_SPI = 0x0b, GREYBUS_CLASS_DISPLAY = 0x0c, GREYBUS_CLASS_CAMERA = 0x0d, -- cgit v0.10.2 From 177d4a4d34bc81e220cc2ef4056df3da25ad6994 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Wed, 2 Mar 2016 16:51:08 +0000 Subject: greybus: timesync: Add Control and SVC TimeSync command/response data definitions This patch adds the protocol command/response definitions for the SVC and Control protocols to the greybus_protocols definition header consistent with the greybus-spec. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index b60c7dc..c0a7863 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -170,6 +170,20 @@ struct gb_control_interface_version_response { __le16 minor; } __packed; +#define GB_TIMESYNC_MAX_STROBES 0x04 + +struct gb_control_timesync_enable_request { + __u8 count; + __u64 frame_time; + __u32 strobe_delay; + __u32 refclk; +} __packed; +/* timesync enable response has no payload */ + +struct gb_control_timesync_authoritative_request { + __u64 frame_time[GB_TIMESYNC_MAX_STROBES]; +} __packed; +/* timesync authoritative response has no payload */ /* APBridge protocol */ @@ -900,6 +914,20 @@ struct gb_svc_route_destroy_request { } __packed; /* route destroy response has no payload */ +struct gb_svc_timesync_enable_request { + __u8 count; + __u64 frame_time; + __u32 strobe_delay; + __u32 strobe_mask; + __u32 refclk; +} __packed; +/* timesync enable response has no payload */ + +/* timesync authoritative request has no payload */ +struct gb_svc_timesync_authoritative_response { + __u64 frame_time[GB_TIMESYNC_MAX_STROBES]; +}; + #define GB_SVC_UNIPRO_FAST_MODE 0x01 #define GB_SVC_UNIPRO_SLOW_MODE 0x02 #define GB_SVC_UNIPRO_FAST_AUTO_MODE 0x04 -- cgit v0.10.2 From 0bd39ca4898fb554bcba28c82f425cc6c88180b9 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Wed, 2 Mar 2016 16:51:09 +0000 Subject: greybus: timesync: Add Control and SVC protocol TimeSync operation definitions This patch adds the protocol command extenions for SVC and Control protocols to the greybus_protocols definition header consistent with the greybus-spec. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index c0a7863..8fd91f1 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -122,6 +122,9 @@ struct gb_protocol_version_response { #define GB_CONTROL_TYPE_GET_MANIFEST 0x04 #define GB_CONTROL_TYPE_CONNECTED 0x05 #define GB_CONTROL_TYPE_DISCONNECTED 0x06 +#define GB_CONTROL_TYPE_TIMESYNC_ENABLE 0x07 +#define GB_CONTROL_TYPE_TIMESYNC_DISABLE 0x08 +#define GB_CONTROL_TYPE_TIMESYNC_AUTHORITATIVE 0x09 #define GB_CONTROL_TYPE_INTERFACE_VERSION 0x0a #define GB_CONTROL_TYPE_BUNDLE_VERSION 0x0b @@ -785,21 +788,24 @@ struct gb_spi_transfer_response { #define GB_SVC_VERSION_MINOR 0x01 /* Greybus SVC request types */ -#define GB_SVC_TYPE_SVC_HELLO 0x02 -#define GB_SVC_TYPE_INTF_DEVICE_ID 0x03 -#define GB_SVC_TYPE_INTF_HOTPLUG 0x04 -#define GB_SVC_TYPE_INTF_HOT_UNPLUG 0x05 -#define GB_SVC_TYPE_INTF_RESET 0x06 -#define GB_SVC_TYPE_CONN_CREATE 0x07 -#define GB_SVC_TYPE_CONN_DESTROY 0x08 -#define GB_SVC_TYPE_DME_PEER_GET 0x09 -#define GB_SVC_TYPE_DME_PEER_SET 0x0a -#define GB_SVC_TYPE_ROUTE_CREATE 0x0b -#define GB_SVC_TYPE_ROUTE_DESTROY 0x0c -#define GB_SVC_TYPE_INTF_SET_PWRM 0x10 -#define GB_SVC_TYPE_INTF_EJECT 0x11 -#define GB_SVC_TYPE_KEY_EVENT 0x12 -#define GB_SVC_TYPE_PING 0x13 +#define GB_SVC_TYPE_SVC_HELLO 0x02 +#define GB_SVC_TYPE_INTF_DEVICE_ID 0x03 +#define GB_SVC_TYPE_INTF_HOTPLUG 0x04 +#define GB_SVC_TYPE_INTF_HOT_UNPLUG 0x05 +#define GB_SVC_TYPE_INTF_RESET 0x06 +#define GB_SVC_TYPE_CONN_CREATE 0x07 +#define GB_SVC_TYPE_CONN_DESTROY 0x08 +#define GB_SVC_TYPE_DME_PEER_GET 0x09 +#define GB_SVC_TYPE_DME_PEER_SET 0x0a +#define GB_SVC_TYPE_ROUTE_CREATE 0x0b +#define GB_SVC_TYPE_ROUTE_DESTROY 0x0c +#define GB_SVC_TYPE_TIMESYNC_ENABLE 0x0d +#define GB_SVC_TYPE_TIMESYNC_DISABLE 0x0e +#define GB_SVC_TYPE_TIMESYNC_AUTHORITATIVE 0x0f +#define GB_SVC_TYPE_INTF_SET_PWRM 0x10 +#define GB_SVC_TYPE_INTF_EJECT 0x11 +#define GB_SVC_TYPE_KEY_EVENT 0x12 +#define GB_SVC_TYPE_PING 0x13 /* * SVC version request/response has the same payload as -- cgit v0.10.2 From 8fd9466b8c324bc87c5db58a46c33731d1ea50bf Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Wed, 2 Mar 2016 16:51:10 +0000 Subject: greybus: control: Add TimeSync control commands Simple addition of the TimeSync commands defined in the specification. Note for the case of timesync_authoritative we're passing the request structure directly so as not to have to pass eight parameters into the function. Adds: - control.c::timesync_enable(u8 count, u64 frame_time, u32 strobe_delay, u32 refclk) Informs an Interface to expect count TimeSync strobe pulses with strobe_delay milliseconds delay between each strobe. Once enabled an Interface may not enter a low-power mode which will result in the reference timer used to track time switching off. - control.c::timesync_disable(void) Commands an Interface to immediately halt TimeSync logic. This will allow an Interface to transition into low-power modes where the reference time being used for TimeSync may switch off. - control.c::timesync_authoritative(u64 *frame_time, u8 count) Used by the AP Module to inform an Interface of the authoritative TimeSync clock-master time at each strobe pulse. Down-stream clock slaves shall adjust their local frame-time appropriately based on the diseminated authoritative frame-time. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index ba2754a..bac412ef 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -241,3 +241,39 @@ void gb_control_destroy(struct gb_control *control) gb_connection_destroy(control->connection); kfree(control); } + +int gb_control_timesync_enable(struct gb_control *control, u8 count, + u64 frame_time, u32 strobe_delay, u32 refclk) +{ + struct gb_control_timesync_enable_request request; + + request.count = count; + request.frame_time = cpu_to_le64(frame_time); + request.strobe_delay = cpu_to_le32(strobe_delay); + request.refclk = cpu_to_le32(refclk); + return gb_operation_sync(control->connection, + GB_CONTROL_TYPE_TIMESYNC_ENABLE, &request, + sizeof(request), NULL, 0); +} + +int gb_control_timesync_disable(struct gb_control *control) +{ + return gb_operation_sync(control->connection, + GB_CONTROL_TYPE_TIMESYNC_DISABLE, NULL, 0, + NULL, 0); +} + +int gb_control_timesync_authoritative(struct gb_control *control, + u64 *frame_time, u8 count) +{ + struct gb_control_timesync_authoritative_request request; + int i; + + for (i = 0; i < GB_TIMESYNC_MAX_STROBES; i++) + request.frame_time[i] = frame_time[i]; + + return gb_operation_sync(control->connection, + GB_CONTROL_TYPE_TIMESYNC_AUTHORITATIVE, + &request, sizeof(request), + NULL, 0); +} diff --git a/drivers/staging/greybus/control.h b/drivers/staging/greybus/control.h index d31e7c6..949f1a3 100644 --- a/drivers/staging/greybus/control.h +++ b/drivers/staging/greybus/control.h @@ -31,5 +31,10 @@ int gb_control_get_manifest_size_operation(struct gb_interface *intf); int gb_control_get_manifest_operation(struct gb_interface *intf, void *manifest, size_t size); int gb_control_get_interface_version_operation(struct gb_interface *intf); +int gb_control_timesync_enable(struct gb_control *control, u8 count, + u64 frame_time, u32 strobe_delay, u32 refclk); +int gb_control_timesync_disable(struct gb_control *control); +int gb_control_timesync_authoritative(struct gb_control *control, + u64 *frame_time, u8 count); #endif /* __CONTROL_H */ -- cgit v0.10.2 From cb033188d8a783be55d03017954b8e7453799a5d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 3 Mar 2016 13:34:36 +0100 Subject: greybus: connection: add connection-flag interface Add interface for associating a flag bitmask with a connection when creating it. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 34e26dc..eaceafc 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -119,6 +119,7 @@ static void gb_connection_init_name(struct gb_connection *connection) * @bundle: remote-interface bundle (may be NULL) * @cport_id: remote-interface cport id, or 0 for static connections * @handler: request handler (may be NULL) + * @flags: connection flags * * Create a Greybus connection, representing the bidirectional link * between a CPort on a (local) Greybus host device and a CPort on @@ -137,7 +138,8 @@ static struct gb_connection * _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, struct gb_interface *intf, struct gb_bundle *bundle, int cport_id, - gb_request_handler_t handler) + gb_request_handler_t handler, + unsigned long flags) { struct gb_connection *connection; struct ida *id_map = &hd->cport_id_map; @@ -180,6 +182,7 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, connection->intf = intf; connection->bundle = bundle; connection->handler = handler; + connection->flags = flags; connection->state = GB_CONNECTION_STATE_DISABLED; atomic_set(&connection->op_cycle, 0); @@ -226,13 +229,14 @@ struct gb_connection * gb_connection_create_static(struct gb_host_device *hd, u16 hd_cport_id, gb_request_handler_t handler) { - return _gb_connection_create(hd, hd_cport_id, NULL, NULL, 0, handler); + return _gb_connection_create(hd, hd_cport_id, NULL, NULL, 0, handler, + 0); } struct gb_connection * gb_connection_create_control(struct gb_interface *intf) { - return _gb_connection_create(intf->hd, -1, intf, NULL, 0, NULL); + return _gb_connection_create(intf->hd, -1, intf, NULL, 0, NULL, 0); } struct gb_connection * @@ -242,10 +246,22 @@ gb_connection_create(struct gb_bundle *bundle, u16 cport_id, struct gb_interface *intf = bundle->intf; return _gb_connection_create(intf->hd, -1, intf, bundle, cport_id, - handler); + handler, 0); } EXPORT_SYMBOL_GPL(gb_connection_create); +struct gb_connection * +gb_connection_create_flags(struct gb_bundle *bundle, u16 cport_id, + gb_request_handler_t handler, + unsigned long flags) +{ + struct gb_interface *intf = bundle->intf; + + return _gb_connection_create(intf->hd, -1, intf, bundle, cport_id, + handler, flags); +} +EXPORT_SYMBOL_GPL(gb_connection_create_flags); + static int gb_connection_hd_cport_enable(struct gb_connection *connection) { struct gb_host_device *hd = connection->hd; diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 24b7d6f..d5ac145 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -36,6 +36,7 @@ struct gb_connection { struct list_head bundle_links; gb_request_handler_t handler; + unsigned long flags; struct gb_protocol *protocol; u8 module_major; @@ -59,6 +60,9 @@ struct gb_connection *gb_connection_create_static(struct gb_host_device *hd, struct gb_connection *gb_connection_create_control(struct gb_interface *intf); struct gb_connection *gb_connection_create(struct gb_bundle *bundle, u16 cport_id, gb_request_handler_t handler); +struct gb_connection * gb_connection_create_flags(struct gb_bundle *bundle, + u16 cport_id, gb_request_handler_t handler, + unsigned long flags); void gb_connection_destroy(struct gb_connection *connection); static inline bool gb_connection_is_static(struct gb_connection *connection) -- cgit v0.10.2 From 34145b608d4198d7c89bfeffded6bc71012b6d79 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 3 Mar 2016 13:34:37 +0100 Subject: greybus: svc: clean up CPortFlags handling Clean up CPortFlags handling and explicitly disable CSD when E2EFC is enabled (CSD_n is ignored when E2EFC is set). Note that the bootrom requires E2EFC, CSD, and CSV to all be disabled. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index eeb251e..65c6d8e 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -291,21 +291,14 @@ int gb_svc_connection_create(struct gb_svc *svc, request.cport1_id = cpu_to_le16(cport1_id); request.intf2_id = intf2_id; request.cport2_id = cpu_to_le16(cport2_id); - /* - * XXX: fix connections paramaters to TC0 and all CPort flags - * for now. - */ - request.tc = 0; + request.tc = 0; /* TC0 */ - /* - * We need to skip setting E2EFC and other flags to the connection - * create request, for all cports, on an interface that need to boot - * over unipro, i.e. interfaces required to download firmware. - */ + /* The ES2/ES3 bootrom requires E2EFC, CSD and CSV to be disabled. */ + request.flags = CPORT_FLAGS_CSV_N; if (boot_over_unipro) - request.flags = CPORT_FLAGS_CSV_N | CPORT_FLAGS_CSD_N; + request.flags |= CPORT_FLAGS_CSD_N; else - request.flags = CPORT_FLAGS_CSV_N | CPORT_FLAGS_E2EFC; + request.flags |= CPORT_FLAGS_CSD_N | CPORT_FLAGS_E2EFC; return gb_operation_sync(svc->connection, GB_SVC_TYPE_CONN_CREATE, &request, sizeof(request), NULL, 0); -- cgit v0.10.2 From 27f25c17ad7fa2b24a24a4e617077dec20a026ce Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 3 Mar 2016 13:34:38 +0100 Subject: greybus: connection: generalise CPortFlags handling Generalise the svc connection-create helper to accept a cport-flags argument and handle the flags in the connection code instead. Note that the camera driver currently manages its data connection directly. We keep E2EFC enabled for now even though it will soon need to be disabled due to some pending firmware updates. Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 444e218..3ca585f 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -817,6 +817,7 @@ static int gb_camera_connection_init(struct gb_connection *connection) { struct gb_svc *svc = connection->hd->svc; struct gb_camera *gcam; + u8 cport_flags; int ret; gcam = kzalloc(sizeof(*gcam), GFP_KERNEL); @@ -830,9 +831,12 @@ static int gb_camera_connection_init(struct gb_connection *connection) * Create the data connection between camera module CDSI0 and APB CDS1. * The CPort IDs are hardcoded by the ES2 bridges. */ + /* FIXME: remove E2EFC */ + cport_flags = GB_SVC_CPORT_FLAG_E2EFC | GB_SVC_CPORT_FLAG_CSD_N | + GB_SVC_CPORT_FLAG_CSV_N; ret = gb_svc_connection_create(svc, connection->intf->interface_id, ES2_APB_CDSI0_CPORT, svc->ap_intf_id, - ES2_APB_CDSI1_CPORT, false); + ES2_APB_CDSI1_CPORT, cport_flags); if (ret < 0) goto error; diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index eaceafc..01d31f6 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -327,18 +327,29 @@ gb_connection_svc_connection_create(struct gb_connection *connection) { struct gb_host_device *hd = connection->hd; struct gb_interface *intf; + u8 cport_flags; int ret; if (gb_connection_is_static(connection)) return gb_connection_hd_fct_flow_enable(connection); intf = connection->intf; + + /* The ES2/ES3 bootrom requires E2EFC, CSD and CSV to be disabled. */ + cport_flags = GB_SVC_CPORT_FLAG_CSV_N; + if (intf->boot_over_unipro) { + cport_flags |= GB_SVC_CPORT_FLAG_CSD_N; + } else { + cport_flags |= GB_SVC_CPORT_FLAG_CSD_N | + GB_SVC_CPORT_FLAG_E2EFC; + } + ret = gb_svc_connection_create(hd->svc, hd->svc->ap_intf_id, connection->hd_cport_id, intf->interface_id, connection->intf_cport_id, - intf->boot_over_unipro); + cport_flags); if (ret) { dev_err(&connection->hd->dev, "%s: failed to create svc connection: %d\n", diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 65c6d8e..69c37d4 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -12,10 +12,6 @@ #include "greybus.h" -#define CPORT_FLAGS_E2EFC BIT(0) -#define CPORT_FLAGS_CSD_N BIT(1) -#define CPORT_FLAGS_CSV_N BIT(2) - #define SVC_KEY_ARA_BUTTON KEY_A struct gb_svc_deferred_request { @@ -283,7 +279,7 @@ static int gb_svc_read_and_clear_module_boot_status(struct gb_interface *intf) int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id, - bool boot_over_unipro) + u8 cport_flags) { struct gb_svc_conn_create_request request; @@ -292,13 +288,7 @@ int gb_svc_connection_create(struct gb_svc *svc, request.intf2_id = intf2_id; request.cport2_id = cpu_to_le16(cport2_id); request.tc = 0; /* TC0 */ - - /* The ES2/ES3 bootrom requires E2EFC, CSD and CSV to be disabled. */ - request.flags = CPORT_FLAGS_CSV_N; - if (boot_over_unipro) - request.flags |= CPORT_FLAGS_CSD_N; - else - request.flags |= CPORT_FLAGS_CSD_N | CPORT_FLAGS_E2EFC; + request.flags = cport_flags; return gb_operation_sync(svc->connection, GB_SVC_TYPE_CONN_CREATE, &request, sizeof(request), NULL, 0); diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index b9fb93e..0436f49 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -10,6 +10,10 @@ #ifndef __SVC_H #define __SVC_H +#define GB_SVC_CPORT_FLAG_E2EFC BIT(0) +#define GB_SVC_CPORT_FLAG_CSD_N BIT(1) +#define GB_SVC_CPORT_FLAG_CSV_N BIT(2) + enum gb_svc_state { GB_SVC_STATE_RESET, GB_SVC_STATE_PROTOCOL_VERSION, @@ -46,7 +50,7 @@ void gb_svc_put(struct gb_svc *svc); int gb_svc_intf_reset(struct gb_svc *svc, u8 intf_id); int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, - u8 intf2_id, u16 cport2_id, bool boot_over_unipro); + u8 intf2_id, u16 cport2_id, u8 cport_flags); void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id); int gb_svc_intf_eject(struct gb_svc *svc, u8 intf_id); -- cgit v0.10.2 From 64a6d1388432704c9205fee04be8e6df45fc563b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 3 Mar 2016 13:34:39 +0100 Subject: greybus: connection: add CSD connection flag Add CSD connection flag that can be specified when allocating a connection to enable Controlled Segment Dropping in favour of E2EFC which is enabled by default. Note that most connections are expected to have E2EFC enabled. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 01d31f6..96a8aa3 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -339,7 +339,7 @@ gb_connection_svc_connection_create(struct gb_connection *connection) cport_flags = GB_SVC_CPORT_FLAG_CSV_N; if (intf->boot_over_unipro) { cport_flags |= GB_SVC_CPORT_FLAG_CSD_N; - } else { + } else if (gb_connection_e2efc_enabled(connection)) { cport_flags |= GB_SVC_CPORT_FLAG_CSD_N | GB_SVC_CPORT_FLAG_E2EFC; } diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index d5ac145..6197d45 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -13,6 +13,8 @@ #include #include +#define GB_CONNECTION_FLAG_CSD BIT(0) + enum gb_connection_state { GB_CONNECTION_STATE_INVALID = 0, GB_CONNECTION_STATE_DISABLED = 1, @@ -81,4 +83,9 @@ void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id, void gb_connection_latency_tag_enable(struct gb_connection *connection); void gb_connection_latency_tag_disable(struct gb_connection *connection); +static inline bool gb_connection_e2efc_enabled(struct gb_connection *connection) +{ + return !(connection->flags & GB_CONNECTION_FLAG_CSD); +} + #endif /* __CONNECTION_H */ -- cgit v0.10.2 From aa2a5459aa167814f847afb05c262c1f29dc9c6a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 3 Mar 2016 13:34:40 +0100 Subject: greybus: hd: rename CPort-features callbacks Rename the CPort-features callbacks, that are not just used to enable FCT flow, to the more descriptive cport_features_enable/disable. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 96a8aa3..64fa20a 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -290,17 +290,18 @@ static void gb_connection_hd_cport_disable(struct gb_connection *connection) hd->driver->cport_disable(hd, connection->hd_cport_id); } -static int gb_connection_hd_fct_flow_enable(struct gb_connection *connection) +static int +gb_connection_hd_cport_features_enable(struct gb_connection *connection) { struct gb_host_device *hd = connection->hd; int ret; - if (!hd->driver->fct_flow_enable) + if (!hd->driver->cport_features_enable) return 0; - ret = hd->driver->fct_flow_enable(hd, connection->hd_cport_id); + ret = hd->driver->cport_features_enable(hd, connection->hd_cport_id); if (ret) { - dev_err(&hd->dev, "%s: failed to enable FCT flow: %d\n", + dev_err(&hd->dev, "%s: failed to enable CPort features: %d\n", connection->name, ret); return ret; } @@ -308,14 +309,15 @@ static int gb_connection_hd_fct_flow_enable(struct gb_connection *connection) return 0; } -static void gb_connection_hd_fct_flow_disable(struct gb_connection *connection) +static void +gb_connection_hd_cport_features_disable(struct gb_connection *connection) { struct gb_host_device *hd = connection->hd; - if (!hd->driver->fct_flow_disable) + if (!hd->driver->cport_features_disable) return; - hd->driver->fct_flow_disable(hd, connection->hd_cport_id); + hd->driver->cport_features_disable(hd, connection->hd_cport_id); } /* @@ -331,7 +333,7 @@ gb_connection_svc_connection_create(struct gb_connection *connection) int ret; if (gb_connection_is_static(connection)) - return gb_connection_hd_fct_flow_enable(connection); + return gb_connection_hd_cport_features_enable(connection); intf = connection->intf; @@ -357,7 +359,7 @@ gb_connection_svc_connection_create(struct gb_connection *connection) return ret; } - ret = gb_connection_hd_fct_flow_enable(connection); + ret = gb_connection_hd_cport_features_enable(connection); if (ret) { gb_svc_connection_destroy(hd->svc, hd->svc->ap_intf_id, connection->hd_cport_id, @@ -372,7 +374,7 @@ gb_connection_svc_connection_create(struct gb_connection *connection) static void gb_connection_svc_connection_destroy(struct gb_connection *connection) { - gb_connection_hd_fct_flow_disable(connection); + gb_connection_hd_cport_features_disable(connection); if (gb_connection_is_static(connection)) return; diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index e920563..239adf7 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -574,37 +574,37 @@ static int latency_tag_disable(struct gb_host_device *hd, u16 cport_id) return retval; } -static int fct_flow_enable(struct gb_host_device *hd, u16 cport_id) +static int cport_features_enable(struct gb_host_device *hd, u16 cport_id) { int retval; struct es2_ap_dev *es2 = hd_to_es2(hd); struct usb_device *udev = es2->usb_dev; retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - GB_APB_REQUEST_FCT_FLOW_EN, + GB_APB_REQUEST_CPORT_FEAT_EN, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, cport_id, 0, NULL, 0, ES2_TIMEOUT); if (retval < 0) - dev_err(&udev->dev, "Cannot enable FCT flow for cport %u: %d\n", + dev_err(&udev->dev, "Cannot enable CPort features for cport %u: %d\n", cport_id, retval); return retval; } -static int fct_flow_disable(struct gb_host_device *hd, u16 cport_id) +static int cport_features_disable(struct gb_host_device *hd, u16 cport_id) { int retval; struct es2_ap_dev *es2 = hd_to_es2(hd); struct usb_device *udev = es2->usb_dev; retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - GB_APB_REQUEST_FCT_FLOW_DIS, + GB_APB_REQUEST_CPORT_FEAT_DIS, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, cport_id, 0, NULL, 0, ES2_TIMEOUT); if (retval < 0) dev_err(&udev->dev, - "Cannot disable FCT flow for cport %u: %d\n", + "Cannot disable CPort features for cport %u: %d\n", cport_id, retval); return retval; } @@ -617,8 +617,8 @@ static struct gb_hd_driver es2_driver = { .latency_tag_enable = latency_tag_enable, .latency_tag_disable = latency_tag_disable, .output = output, - .fct_flow_enable = fct_flow_enable, - .fct_flow_disable = fct_flow_disable, + .cport_features_enable = cport_features_enable, + .cport_features_disable = cport_features_disable, }; /* Common function to report consistent warnings based on URB status */ diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 8fd91f1..27acbdd 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -212,9 +212,9 @@ struct gb_control_timesync_authoritative_request { /* request to control the CSI transmitter */ #define GB_APB_REQUEST_AUDIO_CONTROL 0x09 -/* vendor requests to enable/disable FCT tokens flow */ -#define GB_APB_REQUEST_FCT_FLOW_EN 0x0b -#define GB_APB_REQUEST_FCT_FLOW_DIS 0x0c +/* vendor requests to enable/disable CPort features */ +#define GB_APB_REQUEST_CPORT_FEAT_EN 0x0b +#define GB_APB_REQUEST_CPORT_FEAT_DIS 0x0c /* Firmware Protocol */ diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h index eaddfc9..fe6c086 100644 --- a/drivers/staging/greybus/hd.h +++ b/drivers/staging/greybus/hd.h @@ -25,8 +25,8 @@ struct gb_hd_driver { int (*latency_tag_disable)(struct gb_host_device *hd, u16 cport_id); int (*output)(struct gb_host_device *hd, void *req, u16 size, u8 cmd, bool async); - int (*fct_flow_enable)(struct gb_host_device *hd, u16 cport_id); - int (*fct_flow_disable)(struct gb_host_device *hd, u16 cport_id); + int (*cport_features_enable)(struct gb_host_device *hd, u16 cport_id); + int (*cport_features_disable)(struct gb_host_device *hd, u16 cport_id); }; struct gb_host_device { -- cgit v0.10.2 From 53f965065a5eb067621e4734fee9719942976a86 Mon Sep 17 00:00:00 2001 From: Fabien Parent Date: Fri, 4 Mar 2016 17:32:20 +0100 Subject: greybus: camera: disable E2EFC on CSI connection Following Toshiba's recommendation we shouldn't use E2EFC on a CSI connection. Disable E2EFC on the CSI connection. Signed-off-by: Fabien Parent Acked-by: Laurent Pinchart Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 3ca585f..d499ffd 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -831,9 +831,7 @@ static int gb_camera_connection_init(struct gb_connection *connection) * Create the data connection between camera module CDSI0 and APB CDS1. * The CPort IDs are hardcoded by the ES2 bridges. */ - /* FIXME: remove E2EFC */ - cport_flags = GB_SVC_CPORT_FLAG_E2EFC | GB_SVC_CPORT_FLAG_CSD_N | - GB_SVC_CPORT_FLAG_CSV_N; + cport_flags = GB_SVC_CPORT_FLAG_CSD_N | GB_SVC_CPORT_FLAG_CSV_N; ret = gb_svc_connection_create(svc, connection->intf->interface_id, ES2_APB_CDSI0_CPORT, svc->ap_intf_id, ES2_APB_CDSI1_CPORT, cport_flags); -- cgit v0.10.2 From 9fa3a9b8cb7e04b600166049424d01b428a251ad Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 4 Mar 2016 18:40:02 -0800 Subject: greybus: properly annotate struct gb_control_timesync_enable_request A patch from created struct gb_control_timesync_enable_request, but forgot to properly annotate that the fields are little-endian. The code is correct in treating them this way, so there isn't a bug, but sparse complains. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 27acbdd..524c649 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -177,9 +177,9 @@ struct gb_control_interface_version_response { struct gb_control_timesync_enable_request { __u8 count; - __u64 frame_time; - __u32 strobe_delay; - __u32 refclk; + __le64 frame_time; + __le32 strobe_delay; + __le32 refclk; } __packed; /* timesync enable response has no payload */ -- cgit v0.10.2 From 7fe9301422444a1fca71bb8c4c0673fb44eb0f2d Mon Sep 17 00:00:00 2001 From: David Lin Date: Mon, 7 Mar 2016 21:52:54 -0800 Subject: greybus: arche-platform: fix incorrect gpio variable type GPIO number obtained from of_get_named_gpio() should be signed to allow error handling. Testing Done: Built & booted on EVT1.5 Signed-off-by: David Lin Reviewed-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index 55806bd..3a092a5 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -37,7 +37,7 @@ struct arche_apb_ctrl_drvdata { struct regulator *vcore; struct regulator *vio; - unsigned int clk_en_gpio; + int clk_en_gpio; struct clk *clk; struct pinctrl *pinctrl; diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 64dd8a1..3293661 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -44,7 +44,7 @@ struct arche_platform_drvdata { enum arche_platform_state state; - unsigned int svc_refclk_req; + int svc_refclk_req; struct clk *svc_ref_clk; struct pinctrl *pinctrl; -- cgit v0.10.2 From 4b82dd7be3d3ea62c634bda6bd01666912bc7e79 Mon Sep 17 00:00:00 2001 From: Axel Haslam Date: Tue, 8 Mar 2016 10:03:40 +0100 Subject: greybus: loopback_test: Use timeout argument Patch "c3b0a32 Loopback_test: use poll instead of inotify" added a optional argument for the user to specify a timeout value, but did not use this parameter in the actual poll function. The default of 30 seconds is always used. Fix this by actually using the the poll_timeout parameter so the user can run long tests. Signed-off-by: Axel Haslam Reviewed-by: Patrick Titiano Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/tools/loopback_test.c b/drivers/staging/greybus/tools/loopback_test.c index 0abe623..ab40bcf 100644 --- a/drivers/staging/greybus/tools/loopback_test.c +++ b/drivers/staging/greybus/tools/loopback_test.c @@ -714,7 +714,7 @@ static int wait_for_complete(struct loopback_test *t) int i; while (1) { - ret = poll(t->fds, t->poll_count, DEFAULT_POLL_TIMEOUT_SEC * 1000); + ret = poll(t->fds, t->poll_count, t->poll_timeout * 1000); if (ret == 0) { fprintf(stderr, "Poll timmed out!\n"); return -1; -- cgit v0.10.2 From 9230e298cf49761abbf5893125fc20ad286cff5b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 8 Mar 2016 16:50:43 +0100 Subject: greybus: greybus_manifest: remove unused AP class and protocol Mark the AP Bundle-class and protocol ids as unused. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Reviewed-by: Jeffrey Carlyle Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index b9504c7..86ebc0a 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -23,7 +23,7 @@ enum greybus_descriptor_type { enum greybus_protocol { GREYBUS_PROTOCOL_CONTROL = 0x00, - GREYBUS_PROTOCOL_AP = 0x01, + /* 0x01 is unused */ GREYBUS_PROTOCOL_GPIO = 0x02, GREYBUS_PROTOCOL_I2C = 0x03, GREYBUS_PROTOCOL_UART = 0x04, @@ -52,7 +52,7 @@ enum greybus_protocol { enum greybus_class_type { GREYBUS_CLASS_CONTROL = 0x00, - GREYBUS_CLASS_AP = 0x01, + /* 0x01 is unused */ GREYBUS_CLASS_GPIO = 0x02, GREYBUS_CLASS_I2C = 0x03, GREYBUS_CLASS_UART = 0x04, -- cgit v0.10.2 From a23aa56452a8c705c7da62e9eda4c2fafd837829 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 9 Mar 2016 16:13:55 +0100 Subject: greybus: greybus_manifest: remove unused SVC class Mark the SVC Bundle-class id as unused. Signed-off-by: Johan Hovold Reviewed-by: Jeffrey Carlyle Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 86ebc0a..12b6e74 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -71,7 +71,7 @@ enum greybus_class_type { GREYBUS_CLASS_LOOPBACK = 0x11, GREYBUS_CLASS_AUDIO = 0x12, /* 0x13 is unused */ - GREYBUS_CLASS_SVC = 0x14, + /* 0x14 is unused */ GREYBUS_CLASS_FIRMWARE = 0x15, /* ... */ GREYBUS_CLASS_RAW = 0xfe, -- cgit v0.10.2 From 89ec14ceaedf887fb666f09e1b768afdc32cb291 Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Tue, 8 Mar 2016 16:37:36 +0100 Subject: greybus: loopback: Fix warning on 32-bit build gb_loopback_ro_avg_attr() is using "/" to divide two 64-bit integer, causing a reference to __aeabi_uldivmod() that is not availalbe on 32-bit. Instead, use do_div(). Signed-off-by: Alexandre Bailon Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index ba6e12a..75bff56 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -164,7 +164,8 @@ static ssize_t name##_avg_show(struct device *dev, \ count = stats->count ? stats->count : 1; \ avg = stats->sum; \ rem = do_div(avg, count); \ - rem = 1000000 * rem / count; \ + rem *= 1000000; \ + do_div(rem, count); \ return sprintf(buf, "%llu.%06u\n", avg, (u32)rem); \ } \ static DEVICE_ATTR_RO(name##_avg) -- cgit v0.10.2 From 58a527afff2b27bc912dbb7111d3f23d4f28105b Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Tue, 8 Mar 2016 16:37:37 +0100 Subject: greybus: loopback: round closest the sixth decimal The original round was removed becaused it was rounding the integer whereas we had decimals. Round the sixth decimal. Signed-off-by: Alexandre Bailon Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 75bff56..9f1cd9d 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -162,7 +162,7 @@ static ssize_t name##_avg_show(struct device *dev, \ gb = dev_get_drvdata(dev); \ stats = &gb->name; \ count = stats->count ? stats->count : 1; \ - avg = stats->sum; \ + avg = stats->sum + count / 2000000; /* round closest */ \ rem = do_div(avg, count); \ rem *= 1000000; \ do_div(rem, count); \ -- cgit v0.10.2 From 01480ba336982d49e2208636e38c0a80b732eba8 Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Tue, 8 Mar 2016 17:40:16 +0100 Subject: greybus: loopback: Fix broken synchonous test loopback driver use the send_count variable to know the test progress. The test may be stopped or change but this variable is never cleaned. Such situation may break the next run. Signed-off-by: Alexandre Bailon Reviewed-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 9f1cd9d..6c62706 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -107,6 +107,8 @@ struct gb_loopback { u64 elapsed_nsecs; u32 apbridge_latency_ts; u32 gpbridge_latency_ts; + + u32 send_count; }; static struct class loopback_class = { @@ -247,6 +249,7 @@ static void gb_loopback_check_attr(struct gb_loopback *gb) gb->requests_timedout = 0; gb->requests_completed = 0; gb->iteration_count = 0; + gb->send_count = 0; gb->error = 0; if (kfifo_depth < gb->iteration_max) { @@ -971,7 +974,7 @@ static int gb_loopback_fn(void *data) int us_wait = 0; int type; u32 size; - u32 send_count = 0; + struct gb_loopback *gb = data; while (1) { @@ -989,10 +992,10 @@ static int gb_loopback_fn(void *data) mutex_lock(&gb->mutex); /* Optionally terminate */ - if (send_count == gb->iteration_max) { + if (gb->send_count == gb->iteration_max) { if (gb->iteration_count == gb->iteration_max) { gb->type = 0; - send_count = 0; + gb->send_count = 0; sysfs_notify(&gb->dev->kobj, NULL, "iteration_count"); } @@ -1032,7 +1035,7 @@ static int gb_loopback_fn(void *data) gb->iteration_count++; gb_loopback_calculate_stats(gb, !!error); } - send_count++; + gb->send_count++; if (us_wait) udelay(us_wait); } -- cgit v0.10.2 From 83a124e2c57afee205284f8d5263252a4b8bbfac Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 9 Mar 2016 12:20:31 +0100 Subject: greybus: interface: remove unused function prototype Remove unused gb_interface_destroy() prototype. Signed-off-by: Johan Hovold Reviewed-by: Jeffrey Carlyle Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 4168a57..6a19880 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -61,7 +61,6 @@ struct gb_interface *gb_interface_find(struct gb_host_device *hd, struct gb_interface *gb_interface_create(struct gb_host_device *hd, u8 interface_id); -void gb_interface_destroy(struct gb_interface *intf); int gb_interface_init(struct gb_interface *intf, u8 device_id); void gb_interface_remove(struct gb_interface *intf); void gb_interfaces_remove(struct gb_host_device *hd); -- cgit v0.10.2 From 52bbd5b3a04816cdd65605c53dd033d3d987cfee Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 9 Mar 2016 12:20:32 +0100 Subject: greybus: interface: remove unused drvdata helpers Remove the unused interface drvdata helpers along with some dubious comments about public and private definitions. Greybus drivers bind to bundles and should be using the greybus_set_drvdata and greybus_get_drvdata helpers. Signed-off-by: Johan Hovold Reviewed-by: Jeffrey Carlyle Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 6a19880..ebc51fc 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -10,7 +10,6 @@ #ifndef __INTERFACE_H #define __INTERFACE_H -/* Greybus "public" definitions" */ struct gb_interface { struct device dev; struct gb_control *control; @@ -43,19 +42,6 @@ struct gb_interface { }; #define to_gb_interface(d) container_of(d, struct gb_interface, dev) -static inline void gb_interface_set_drvdata(struct gb_interface *intf, - void *data) -{ - dev_set_drvdata(&intf->dev, data); -} - -static inline void *gb_interface_get_drvdata(struct gb_interface *intf) -{ - return dev_get_drvdata(&intf->dev); -} - -/* Greybus "private" definitions */ - struct gb_interface *gb_interface_find(struct gb_host_device *hd, u8 interface_id); -- cgit v0.10.2 From 60269b958ea127a46be9caf0deff931384c4dd2f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 9 Mar 2016 12:20:33 +0100 Subject: greybus: interface: add comment about early control-connection disable Add comment about why the control connection is disabled early when the interface is already gone. Signed-off-by: Johan Hovold Reviewed-by: Jeffrey Carlyle Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 2f3966f..5c5c422 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -147,6 +147,10 @@ void gb_interface_remove(struct gb_interface *intf) struct gb_bundle *bundle; struct gb_bundle *next; + /* + * Disable the control-connection early to avoid operation timeouts + * when the interface is already gone. + */ if (intf->disconnected) gb_control_disable(intf->control); -- cgit v0.10.2 From bb2533a9742f19bfe6b87b64d54e846674e467d1 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 9 Mar 2016 12:20:34 +0100 Subject: greybus: svc: refactor interface-route creation Add interface-route-create helper to allocate an interface device id and setup the route. Signed-off-by: Johan Hovold Reviewed-by: Jeffrey Carlyle Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 5c5c422..63dd285 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -186,14 +186,12 @@ void gb_interfaces_remove(struct gb_host_device *hd) * Finally initialize all the bundles to set routes via SVC and initialize all * connections. */ -int gb_interface_init(struct gb_interface *intf, u8 device_id) +int gb_interface_init(struct gb_interface *intf) { struct gb_bundle *bundle, *tmp; int ret, size; void *manifest; - intf->device_id = device_id; - /* Establish control connection */ ret = gb_control_enable(intf->control); if (ret) diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index ebc51fc..8d48cfa 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -47,7 +47,7 @@ struct gb_interface *gb_interface_find(struct gb_host_device *hd, struct gb_interface *gb_interface_create(struct gb_host_device *hd, u8 interface_id); -int gb_interface_init(struct gb_interface *intf, u8 device_id); +int gb_interface_init(struct gb_interface *intf); void gb_interface_remove(struct gb_interface *intf); void gb_interfaces_remove(struct gb_host_device *hd); diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 69c37d4..4ed108b 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -463,6 +463,61 @@ static int gb_svc_hello(struct gb_operation *op) return 0; } +static int gb_svc_interface_route_create(struct gb_svc *svc, + struct gb_interface *intf) +{ + u8 intf_id = intf->interface_id; + u8 device_id; + int ret; + + /* + * Create a device id for the interface: + * - device id 0 (GB_DEVICE_ID_SVC) belongs to the SVC + * - device id 1 (GB_DEVICE_ID_AP) belongs to the AP + * + * XXX Do we need to allocate device ID for SVC or the AP here? And what + * XXX about an AP with multiple interface blocks? + */ + ret = ida_simple_get(&svc->device_id_map, + GB_DEVICE_ID_MODULES_START, 0, GFP_KERNEL); + if (ret < 0) { + dev_err(&svc->dev, "failed to allocate device id for interface %u: %d\n", + intf_id, ret); + return ret; + } + device_id = ret; + + ret = gb_svc_intf_device_id(svc, intf_id, device_id); + if (ret) { + dev_err(&svc->dev, "failed to set device id %u for interface %u: %d\n", + device_id, intf_id, ret); + goto err_ida_remove; + } + + /* Create a two-way route between the AP and the new interface. */ + ret = gb_svc_route_create(svc, svc->ap_intf_id, GB_DEVICE_ID_AP, + intf_id, device_id); + if (ret) { + dev_err(&svc->dev, "failed to create route to interface %u (device id %u): %d\n", + intf_id, device_id, ret); + goto err_svc_id_free; + } + + intf->device_id = device_id; + + return 0; + +err_svc_id_free: + /* + * XXX Should we tell SVC that this id doesn't belong to interface + * XXX anymore. + */ +err_ida_remove: + ida_simple_remove(&svc->device_id_map, device_id); + + return ret; +} + static void gb_svc_intf_remove(struct gb_svc *svc, struct gb_interface *intf) { u8 intf_id = intf->interface_id; @@ -487,7 +542,7 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) struct gb_svc *svc = connection->private; struct gb_host_device *hd = connection->hd; struct gb_interface *intf; - u8 intf_id, device_id; + u8 intf_id; u32 vendor_id = 0; u32 product_id = 0; int ret; @@ -561,45 +616,14 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) goto destroy_interface; } - /* - * Create a device id for the interface: - * - device id 0 (GB_DEVICE_ID_SVC) belongs to the SVC - * - device id 1 (GB_DEVICE_ID_AP) belongs to the AP - * - * XXX Do we need to allocate device ID for SVC or the AP here? And what - * XXX about an AP with multiple interface blocks? - */ - device_id = ida_simple_get(&svc->device_id_map, - GB_DEVICE_ID_MODULES_START, 0, GFP_KERNEL); - if (device_id < 0) { - ret = device_id; - dev_err(&svc->dev, "failed to allocate device id for interface %u: %d\n", - intf_id, ret); + ret = gb_svc_interface_route_create(svc, intf); + if (ret) goto destroy_interface; - } - - ret = gb_svc_intf_device_id(svc, intf_id, device_id); - if (ret) { - dev_err(&svc->dev, "failed to set device id %u for interface %u: %d\n", - device_id, intf_id, ret); - goto ida_put; - } - /* - * Create a two-way route between the AP and the new interface - */ - ret = gb_svc_route_create(svc, svc->ap_intf_id, GB_DEVICE_ID_AP, - intf_id, device_id); + ret = gb_interface_init(intf); if (ret) { - dev_err(&svc->dev, "failed to create route to interface %u (device id %u): %d\n", - intf_id, device_id, ret); - goto svc_id_free; - } - - ret = gb_interface_init(intf, device_id); - if (ret) { - dev_err(&svc->dev, "failed to initialize interface %u (device id %u): %d\n", - intf_id, device_id, ret); + dev_err(&svc->dev, "failed to initialize interface %u: %d\n", + intf_id, ret); goto destroy_route; } @@ -607,13 +631,7 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) destroy_route: gb_svc_route_destroy(svc, svc->ap_intf_id, intf_id); -svc_id_free: - /* - * XXX Should we tell SVC that this id doesn't belong to interface - * XXX anymore. - */ -ida_put: - ida_simple_remove(&svc->device_id_map, device_id); + ida_simple_remove(&svc->device_id_map, intf->device_id); destroy_interface: gb_interface_remove(intf); } -- cgit v0.10.2 From 39495a2bea4d523c4d36f28f3739caa8d3a404c4 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 9 Mar 2016 12:20:35 +0100 Subject: greybus: svc: refactor interface-route destruction Add interface-route-destroy helper to tear down the route and release the interface device id. Note that we currently need to grab a reference to the interface to prevent it from being deallocated before tearing down the route. Signed-off-by: Johan Hovold Reviewed-by: Jeffrey Carlyle Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 4ed108b..efa418a19 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -518,21 +518,23 @@ err_ida_remove: return ret; } -static void gb_svc_intf_remove(struct gb_svc *svc, struct gb_interface *intf) +static void gb_svc_interface_route_destroy(struct gb_svc *svc, + struct gb_interface *intf) { - u8 intf_id = intf->interface_id; - u8 device_id = intf->device_id; + gb_svc_route_destroy(svc, svc->ap_intf_id, intf->interface_id); + ida_simple_remove(&svc->device_id_map, intf->device_id); +} +static void gb_svc_intf_remove(struct gb_svc *svc, struct gb_interface *intf) +{ intf->disconnected = true; - gb_interface_remove(intf); + get_device(&intf->dev); - /* - * Destroy the two-way route between the AP and the interface. - */ - gb_svc_route_destroy(svc, svc->ap_intf_id, intf_id); + gb_interface_remove(intf); + gb_svc_interface_route_destroy(svc, intf); - ida_simple_remove(&svc->device_id_map, device_id); + put_device(&intf->dev); } static void gb_svc_process_intf_hotplug(struct gb_operation *operation) @@ -630,8 +632,7 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) return; destroy_route: - gb_svc_route_destroy(svc, svc->ap_intf_id, intf_id); - ida_simple_remove(&svc->device_id_map, intf->device_id); + gb_svc_interface_route_destroy(svc, intf); destroy_interface: gb_interface_remove(intf); } -- cgit v0.10.2 From 7a137fb290df63f24242fc4996decd0b339ba3b1 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 9 Mar 2016 12:20:36 +0100 Subject: greybus: interface: separate initialisation and registration Separate interface initialisation from registration of the interface and its bundles. This is a step towards registering also interfaces that failed to initialise (e.g. a dummy interface). Signed-off-by: Johan Hovold Reviewed-by: Jeffrey Carlyle Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 63dd285..a32e564 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -179,16 +179,12 @@ void gb_interfaces_remove(struct gb_host_device *hd) gb_interface_remove(intf); } -/** - * gb_interface_init - * - * Create connection for control CPort and then request/parse manifest. - * Finally initialize all the bundles to set routes via SVC and initialize all - * connections. +/* + * Intialise an interface by enabling the control connection and fetching the + * manifest and other information over it. */ int gb_interface_init(struct gb_interface *intf) { - struct gb_bundle *bundle, *tmp; int ret, size; void *manifest; @@ -236,11 +232,22 @@ int gb_interface_init(struct gb_interface *intf) if (ret) goto free_manifest; - /* Register the interface and its bundles. */ +free_manifest: + kfree(manifest); + + return ret; +} + +/* Register an interface and its bundles. */ +int gb_interface_add(struct gb_interface *intf) +{ + struct gb_bundle *bundle, *tmp; + int ret; + ret = device_add(&intf->dev); if (ret) { dev_err(&intf->dev, "failed to register interface: %d\n", ret); - goto free_manifest; + return ret; } dev_info(&intf->dev, "Interface added: VID=0x%08x, PID=0x%08x\n", @@ -256,9 +263,5 @@ int gb_interface_init(struct gb_interface *intf) } } - ret = 0; - -free_manifest: - kfree(manifest); - return ret; + return 0; } diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 8d48cfa..5238804 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -48,6 +48,7 @@ struct gb_interface *gb_interface_find(struct gb_host_device *hd, struct gb_interface *gb_interface_create(struct gb_host_device *hd, u8 interface_id); int gb_interface_init(struct gb_interface *intf); +int gb_interface_add(struct gb_interface *intf); void gb_interface_remove(struct gb_interface *intf); void gb_interfaces_remove(struct gb_host_device *hd); diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index efa418a19..0a6c039 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -629,6 +629,10 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) goto destroy_route; } + ret = gb_interface_add(intf); + if (ret) + goto destroy_route; + return; destroy_route: -- cgit v0.10.2 From a77660a75a3f79c71064dc6848a2975731ca5c00 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 9 Mar 2016 12:20:37 +0100 Subject: greybus: interface: free bundles on initialisation errors Immediately free any created bundle structures on interface initialisation errors. Signed-off-by: Johan Hovold Reviewed-by: Jeffrey Carlyle Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index a32e564..fe4efe1 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -185,6 +185,7 @@ void gb_interfaces_remove(struct gb_host_device *hd) */ int gb_interface_init(struct gb_interface *intf) { + struct gb_bundle *bundle, *tmp; int ret, size; void *manifest; @@ -211,7 +212,7 @@ int gb_interface_init(struct gb_interface *intf) ret = gb_control_get_manifest_operation(intf, manifest, size); if (ret) { dev_err(&intf->dev, "failed to get manifest: %d\n", ret); - goto free_manifest; + goto err_free_manifest; } /* @@ -221,18 +222,25 @@ int gb_interface_init(struct gb_interface *intf) if (!gb_manifest_parse(intf, manifest, size)) { dev_err(&intf->dev, "failed to parse manifest\n"); ret = -EINVAL; - goto free_manifest; + goto err_destroy_bundles; } ret = gb_control_get_interface_version_operation(intf); if (ret) - goto free_manifest; + goto err_destroy_bundles; ret = gb_control_get_bundle_versions(intf->control); if (ret) - goto free_manifest; + goto err_destroy_bundles; + + kfree(manifest); -free_manifest: + return 0; + +err_destroy_bundles: + list_for_each_entry_safe(bundle, tmp, &intf->bundles, links) + gb_bundle_destroy(bundle); +err_free_manifest: kfree(manifest); return ret; -- cgit v0.10.2 From 986d6911083150a15b723b33f9aaaf5744b84a84 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 9 Mar 2016 12:20:38 +0100 Subject: greybus: svc: always register interfaces at hotplug Always register interfaces at hotplug regardless of whether initialisation succeeded or not. Even if a module failed to initialise we want it to have a representation while it is physically present. Note that the vendor and product-string attribute will read as "(null)" for now on an interface that failed (early) initialisation. Also note that the switch route is kept until the interface is finally removed also on initialisation errors. Signed-off-by: Johan Hovold Reviewed-by: Jeffrey Carlyle Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 0a6c039..572ed0e 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -521,8 +521,12 @@ err_ida_remove: static void gb_svc_interface_route_destroy(struct gb_svc *svc, struct gb_interface *intf) { + if (intf->device_id == GB_DEVICE_ID_BAD) + return; + gb_svc_route_destroy(svc, svc->ap_intf_id, intf->interface_id); ida_simple_remove(&svc->device_id_map, intf->device_id); + intf->device_id = GB_DEVICE_ID_BAD; } static void gb_svc_intf_remove(struct gb_svc *svc, struct gb_interface *intf) @@ -615,30 +619,22 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) if (ret) { dev_err(&svc->dev, "failed to clear boot status of interface %u: %d\n", intf_id, ret); - goto destroy_interface; + goto out_interface_add; } ret = gb_svc_interface_route_create(svc, intf); if (ret) - goto destroy_interface; + goto out_interface_add; ret = gb_interface_init(intf); if (ret) { dev_err(&svc->dev, "failed to initialize interface %u: %d\n", intf_id, ret); - goto destroy_route; + goto out_interface_add; } - ret = gb_interface_add(intf); - if (ret) - goto destroy_route; - - return; - -destroy_route: - gb_svc_interface_route_destroy(svc, intf); -destroy_interface: - gb_interface_remove(intf); +out_interface_add: + gb_interface_add(intf); } static void gb_svc_process_intf_hot_unplug(struct gb_operation *operation) -- cgit v0.10.2 From 11548c8327000302cfaaf7bcac02a3ccf14c2db1 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 9 Mar 2016 12:20:39 +0100 Subject: greybus: interface: disable control connection on initialisation errors Disable the control connection immediately on any errors during interface initialisation as there's no need to keep it around for an interface in an error state. Signed-off-by: Johan Hovold Reviewed-by: Jeffrey Carlyle Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index fe4efe1..2654fa8 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -198,15 +198,20 @@ int gb_interface_init(struct gb_interface *intf) size = gb_control_get_manifest_size_operation(intf); if (size <= 0) { dev_err(&intf->dev, "failed to get manifest size: %d\n", size); + if (size) - return size; + ret = size; else - return -EINVAL; + ret = -EINVAL; + + goto err_disable_control; } manifest = kmalloc(size, GFP_KERNEL); - if (!manifest) - return -ENOMEM; + if (!manifest) { + ret = -ENOMEM; + goto err_disable_control; + } /* Get manifest using control protocol on CPort */ ret = gb_control_get_manifest_operation(intf, manifest, size); @@ -242,6 +247,8 @@ err_destroy_bundles: gb_bundle_destroy(bundle); err_free_manifest: kfree(manifest); +err_disable_control: + gb_control_disable(intf->control); return ret; } -- cgit v0.10.2 From 64acb6611f3c17251347870e73ddc106fed807cb Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 9 Mar 2016 12:20:40 +0100 Subject: greybus: interface: remove useless spinlock Remove useless global interface spinlock that appeared to protect the host-device interface list, but really did not as we are doing lock-less look-ups by relying on the single-threaded SVC workqueue. Document the locking assumptions. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 2654fa8..4671f40 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -54,9 +54,6 @@ static struct attribute *interface_attrs[] = { ATTRIBUTE_GROUPS(interface); -/* XXX This could be per-host device */ -static DEFINE_SPINLOCK(gb_interfaces_lock); - // FIXME, odds are you don't want to call this function, rework the caller to // not need it please. struct gb_interface *gb_interface_find(struct gb_host_device *hd, @@ -100,6 +97,9 @@ struct device_type greybus_interface_type = { * * Returns a pointer to the new interfce or a null pointer if a * failure occurs due to memory exhaustion. + * + * Locking: Caller ensures serialisation with gb_interface_remove and + * gb_interface_find. */ struct gb_interface *gb_interface_create(struct gb_host_device *hd, u8 interface_id) @@ -132,9 +132,7 @@ struct gb_interface *gb_interface_create(struct gb_host_device *hd, return NULL; } - spin_lock_irq(&gb_interfaces_lock); list_add(&intf->links, &hd->interfaces); - spin_unlock_irq(&gb_interfaces_lock); return intf; } @@ -164,9 +162,7 @@ void gb_interface_remove(struct gb_interface *intf) gb_control_disable(intf->control); - spin_lock_irq(&gb_interfaces_lock); list_del(&intf->links); - spin_unlock_irq(&gb_interfaces_lock); put_device(&intf->dev); } -- cgit v0.10.2 From 66d674cfafb2be4002265e6081a1580d0ea461f7 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 9 Mar 2016 12:20:41 +0100 Subject: greybus: interface: move interface-removal helper Move helper to remove all interfaces of a host-device to the svc code and call it when removing the svc device as this needs to be coordinated with flushing the SVC work queue. Signed-off-by: Johan Hovold Reviewed-by: Jeffrey Carlyle Reviewed-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index 147a92d..2c13860 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -138,7 +138,6 @@ void gb_hd_del(struct gb_host_device *hd) * removing the remaining interfaces. */ gb_svc_del(hd->svc); - gb_interfaces_remove(hd); device_del(&hd->dev); } diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 4671f40..ebf0081 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -167,14 +167,6 @@ void gb_interface_remove(struct gb_interface *intf) put_device(&intf->dev); } -void gb_interfaces_remove(struct gb_host_device *hd) -{ - struct gb_interface *intf, *temp; - - list_for_each_entry_safe(intf, temp, &hd->interfaces, links) - gb_interface_remove(intf); -} - /* * Intialise an interface by enabling the control connection and fetching the * manifest and other information over it. diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 5238804..7fc7d29 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -50,6 +50,5 @@ struct gb_interface *gb_interface_create(struct gb_host_device *hd, int gb_interface_init(struct gb_interface *intf); int gb_interface_add(struct gb_interface *intf); void gb_interface_remove(struct gb_interface *intf); -void gb_interfaces_remove(struct gb_host_device *hd); #endif /* __INTERFACE_H */ diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 572ed0e..446cb25 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -997,6 +997,14 @@ int gb_svc_add(struct gb_svc *svc) return 0; } +static void gb_svc_remove_interfaces(struct gb_svc *svc) +{ + struct gb_interface *intf, *tmp; + + list_for_each_entry_safe(intf, tmp, &svc->hd->interfaces, links) + gb_interface_remove(intf); +} + void gb_svc_del(struct gb_svc *svc) { gb_connection_disable(svc->connection); @@ -1012,6 +1020,8 @@ void gb_svc_del(struct gb_svc *svc) } flush_workqueue(svc->wq); + + gb_svc_remove_interfaces(svc); } void gb_svc_put(struct gb_svc *svc) -- cgit v0.10.2 From 35580af0bd620056506ed51fff024fc4ade66f67 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 9 Mar 2016 12:20:42 +0100 Subject: greybus: interface: rename initialisation function Rename the interface-initialisation function gb_interface_enable(), which is more descriptive. Signed-off-by: Johan Hovold Reviewed-by: Viresh Kumar Reviewed-by: Jeffrey Carlyle Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index ebf0081..072e7c5 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -168,10 +168,10 @@ void gb_interface_remove(struct gb_interface *intf) } /* - * Intialise an interface by enabling the control connection and fetching the + * Enable an interface by enabling its control connection and fetching the * manifest and other information over it. */ -int gb_interface_init(struct gb_interface *intf) +int gb_interface_enable(struct gb_interface *intf) { struct gb_bundle *bundle, *tmp; int ret, size; diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 7fc7d29..4b69e9e 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -47,7 +47,7 @@ struct gb_interface *gb_interface_find(struct gb_host_device *hd, struct gb_interface *gb_interface_create(struct gb_host_device *hd, u8 interface_id); -int gb_interface_init(struct gb_interface *intf); +int gb_interface_enable(struct gb_interface *intf); int gb_interface_add(struct gb_interface *intf); void gb_interface_remove(struct gb_interface *intf); diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 446cb25..631a769 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -626,9 +626,9 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) if (ret) goto out_interface_add; - ret = gb_interface_init(intf); + ret = gb_interface_enable(intf); if (ret) { - dev_err(&svc->dev, "failed to initialize interface %u: %d\n", + dev_err(&svc->dev, "failed to enable interface %u: %d\n", intf_id, ret); goto out_interface_add; } -- cgit v0.10.2 From 629c0d007de962bb4edca7b959cebebb29746e90 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 9 Mar 2016 12:20:43 +0100 Subject: greybus: interface: separate disabling from removal Separate interface disable from interface removal. Disabling an interface means tearing down its control connection and destroying (i.e. deregistering and releasing) its bundles, while removing it means deregistering and releasing the interface itself. This is needed to implement controlled module removal, where the module interfaces are disabled before being physically ejected. Signed-off-by: Johan Hovold Reviewed-by: Jeffrey Carlyle Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 072e7c5..44226c4 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -138,36 +138,6 @@ struct gb_interface *gb_interface_create(struct gb_host_device *hd, } /* - * Tear down a previously set up interface. - */ -void gb_interface_remove(struct gb_interface *intf) -{ - struct gb_bundle *bundle; - struct gb_bundle *next; - - /* - * Disable the control-connection early to avoid operation timeouts - * when the interface is already gone. - */ - if (intf->disconnected) - gb_control_disable(intf->control); - - list_for_each_entry_safe(bundle, next, &intf->bundles, links) - gb_bundle_destroy(bundle); - - if (device_is_registered(&intf->dev)) { - device_del(&intf->dev); - dev_info(&intf->dev, "Interface removed\n"); - } - - gb_control_disable(intf->control); - - list_del(&intf->links); - - put_device(&intf->dev); -} - -/* * Enable an interface by enabling its control connection and fetching the * manifest and other information over it. */ @@ -241,6 +211,25 @@ err_disable_control: return ret; } +/* Disable an interface and destroy its bundles. */ +void gb_interface_disable(struct gb_interface *intf) +{ + struct gb_bundle *bundle; + struct gb_bundle *next; + + /* + * Disable the control-connection early to avoid operation timeouts + * when the interface is already gone. + */ + if (intf->disconnected) + gb_control_disable(intf->control); + + list_for_each_entry_safe(bundle, next, &intf->bundles, links) + gb_bundle_destroy(bundle); + + gb_control_disable(intf->control); +} + /* Register an interface and its bundles. */ int gb_interface_add(struct gb_interface *intf) { @@ -268,3 +257,16 @@ int gb_interface_add(struct gb_interface *intf) return 0; } + +/* Deregister an interface and drop its reference. */ +void gb_interface_remove(struct gb_interface *intf) +{ + if (device_is_registered(&intf->dev)) { + device_del(&intf->dev); + dev_info(&intf->dev, "Interface removed\n"); + } + + list_del(&intf->links); + + put_device(&intf->dev); +} diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 4b69e9e..d4c55ab 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -48,6 +48,7 @@ struct gb_interface *gb_interface_find(struct gb_host_device *hd, struct gb_interface *gb_interface_create(struct gb_host_device *hd, u8 interface_id); int gb_interface_enable(struct gb_interface *intf); +void gb_interface_disable(struct gb_interface *intf); int gb_interface_add(struct gb_interface *intf); void gb_interface_remove(struct gb_interface *intf); diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 631a769..480a071 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -533,12 +533,9 @@ static void gb_svc_intf_remove(struct gb_svc *svc, struct gb_interface *intf) { intf->disconnected = true; - get_device(&intf->dev); - - gb_interface_remove(intf); + gb_interface_disable(intf); gb_svc_interface_route_destroy(svc, intf); - - put_device(&intf->dev); + gb_interface_remove(intf); } static void gb_svc_process_intf_hotplug(struct gb_operation *operation) @@ -1001,8 +998,10 @@ static void gb_svc_remove_interfaces(struct gb_svc *svc) { struct gb_interface *intf, *tmp; - list_for_each_entry_safe(intf, tmp, &svc->hd->interfaces, links) + list_for_each_entry_safe(intf, tmp, &svc->hd->interfaces, links) { + gb_interface_disable(intf); gb_interface_remove(intf); + } } void gb_svc_del(struct gb_svc *svc) -- cgit v0.10.2 From c80514a39a407caa5565450063ac1af42381636a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 9 Mar 2016 12:20:44 +0100 Subject: greybus: svc: unexport eject helper Do no export the interface-eject helper, which is only supposed to be used by core. Signed-off-by: Johan Hovold Reviewed-by: Jeffrey Carlyle Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 480a071..71b3879 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -143,7 +143,6 @@ int gb_svc_intf_eject(struct gb_svc *svc, u8 intf_id) sizeof(request), NULL, 0, GB_SVC_EJECT_TIME); } -EXPORT_SYMBOL_GPL(gb_svc_intf_eject); int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, u32 *value) -- cgit v0.10.2 From e676ccd7134ae9e73d2f82446cef011a12f30e9b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 9 Mar 2016 12:20:45 +0100 Subject: greybus: svc: print an error message on failed eject attempts Print an error message when the SVC fails to eject an interface. Signed-off-by: Johan Hovold Reviewed-by: Jeffrey Carlyle Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 71b3879..b9ef770 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -131,6 +131,7 @@ EXPORT_SYMBOL_GPL(gb_svc_intf_reset); int gb_svc_intf_eject(struct gb_svc *svc, u8 intf_id) { struct gb_svc_intf_eject_request request; + int ret; request.intf_id = intf_id; @@ -138,10 +139,16 @@ int gb_svc_intf_eject(struct gb_svc *svc, u8 intf_id) * The pulse width for module release in svc is long so we need to * increase the timeout so the operation will not return to soon. */ - return gb_operation_sync_timeout(svc->connection, - GB_SVC_TYPE_INTF_EJECT, &request, - sizeof(request), NULL, 0, - GB_SVC_EJECT_TIME); + ret = gb_operation_sync_timeout(svc->connection, + GB_SVC_TYPE_INTF_EJECT, &request, + sizeof(request), NULL, 0, + GB_SVC_EJECT_TIME); + if (ret) { + dev_err(&svc->dev, "failed to eject interface %u\n", intf_id); + return ret; + } + + return 0; } int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, -- cgit v0.10.2 From d18da86b51c135100e297a9833bcdc586e68a84b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 9 Mar 2016 12:20:46 +0100 Subject: greybus: greybus_protocols: remove svc-eject timeout define The SVC eject timeout is implementation specific and does not belong in the protocol header so move it to the svc module. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 524c649..9c628cc 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -847,7 +847,6 @@ struct gb_svc_intf_reset_request { } __packed; /* interface reset response has no payload */ -#define GB_SVC_EJECT_TIME 9000 struct gb_svc_intf_eject_request { __u8 intf_id; } __packed; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index b9ef770..ae1911c 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -14,6 +14,8 @@ #define SVC_KEY_ARA_BUTTON KEY_A +#define SVC_INTF_EJECT_TIMEOUT 9000 + struct gb_svc_deferred_request { struct work_struct work; struct gb_operation *operation; @@ -142,7 +144,7 @@ int gb_svc_intf_eject(struct gb_svc *svc, u8 intf_id) ret = gb_operation_sync_timeout(svc->connection, GB_SVC_TYPE_INTF_EJECT, &request, sizeof(request), NULL, 0, - GB_SVC_EJECT_TIME); + SVC_INTF_EJECT_TIMEOUT); if (ret) { dev_err(&svc->dev, "failed to eject interface %u\n", intf_id); return ret; -- cgit v0.10.2 From 1dc8d3d7c568d9a80fa20570a764da57677f1050 Mon Sep 17 00:00:00 2001 From: Alexandre Bailon Date: Fri, 11 Mar 2016 17:23:37 +0100 Subject: greybus: loopback: Fix broken loopback min values Currently, when a loopback test completely fail, loopback will return 4294967295 for every min value. Return 0 instead of 4294967295 in such case. Signed-off-by: Alexandre Bailon Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 6c62706..9b732a8 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -148,6 +148,9 @@ static ssize_t name##_##field##_show(struct device *dev, \ char *buf) \ { \ struct gb_loopback *gb = dev_get_drvdata(dev); \ + /* Report 0 for min and max if no transfer successed */ \ + if (!gb->requests_completed) \ + return sprintf(buf, "0\n"); \ return sprintf(buf, "%"#type"\n", gb->name.field); \ } \ static DEVICE_ATTR_RO(name##_##field) -- cgit v0.10.2 From fece9c87cb80aceec7dd0205a77c37ff7ba831fe Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Wed, 16 Mar 2016 11:29:59 +0000 Subject: greybus: Ensure gb->mutex is held when adding timer Currently in loopback on the async path we issue an operation and then add a timer to time-out that operation should it fail to complete. Looking at a backtrace given in its feasible op_async->pending can be true and del_timer() can run before add_timer() has run. In the callback handler we already hold gb->mutex. This patch fixes that potential race by ensuring we hold gb->mutex both when we are adding and when we are removing the relevant timer. Signed-off-by: Bryan O'Donoghue Reported-and-tested-by: Axel Haslam Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 9b732a8..5e009e1 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -626,6 +626,7 @@ static int gb_loopback_async_operation(struct gb_loopback *gb, int type, do_gettimeofday(&op_async->ts); op_async->pending = true; atomic_inc(&gb->outstanding_operations); + mutex_lock(&gb->mutex); ret = gb_operation_request_send(operation, gb_loopback_async_operation_callback, GFP_KERNEL); @@ -637,9 +638,11 @@ static int gb_loopback_async_operation(struct gb_loopback *gb, int type, op_async->timer.data = (unsigned long)operation->id; add_timer(&op_async->timer); - return ret; + goto done; error: gb_loopback_async_operation_put(op_async); +done: + mutex_unlock(&gb->mutex); return ret; } -- cgit v0.10.2 From 3b90040de82a43ee0538d36b32c9fa4cbbab59c6 Mon Sep 17 00:00:00 2001 From: Axel Haslam Date: Fri, 11 Mar 2016 13:19:30 +0100 Subject: greybus: loopback_test: handle SIGINT signal Adding a default timeout may not be representative of every usecase for gb_loopback. Also, tests may continue to run on the driver in case of a timeout. To avoid adding a default timeout, handle SIGINT so that when the user presses ctrl-c the test are stoped. The user can still specify a timeout value with the -O option. Signed-off-by: Axel Haslam Reviewed-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/tools/loopback_test.c b/drivers/staging/greybus/tools/loopback_test.c index ab40bcf..d8ff1bc 100644 --- a/drivers/staging/greybus/tools/loopback_test.c +++ b/drivers/staging/greybus/tools/loopback_test.c @@ -17,13 +17,13 @@ #include #include #include +#include #define MAX_NUM_DEVICES 10 #define MAX_SYSFS_PATH 0x200 #define CSV_MAX_LINE 0x1000 #define SYSFS_MAX_INT 0x20 #define MAX_STR_LEN 255 -#define DEFAULT_POLL_TIMEOUT_SEC 30 #define DEFAULT_ASYNC_TIMEOUT 200000 struct dict { @@ -88,7 +88,6 @@ struct loopback_test { int list_devices; int use_async; int async_timeout; - int poll_timeout; int async_outstanding_operations; int us_wait; int file_output; @@ -96,6 +95,7 @@ struct loopback_test { char test_name[MAX_STR_LEN]; char sysfs_prefix[MAX_SYSFS_PATH]; char debugfs_prefix[MAX_SYSFS_PATH]; + struct timespec poll_timeout; struct loopback_device devices[MAX_NUM_DEVICES]; struct loopback_results aggregate_results; struct pollfd fds[MAX_NUM_DEVICES]; @@ -706,22 +706,51 @@ static int is_complete(struct loopback_test *t) return 1; } +static void stop_tests(struct loopback_test *t) +{ + int i; + + for (i = 0; i < t->device_count; i++) { + if (!device_enabled(t, i)) + continue; + write_sysfs_val(t->devices[i].sysfs_entry, "type", 0); + } +} + +static void handler(int sig) { /* do nothing */ } + static int wait_for_complete(struct loopback_test *t) { int number_of_events = 0; char dummy; int ret; int i; + struct timespec *ts = NULL; + struct sigaction sa; + sigset_t mask_old, mask; + + sigemptyset(&mask); + sigemptyset(&mask_old); + sigaddset(&mask, SIGINT); + sigprocmask(SIG_BLOCK, &mask, &mask_old); + + sa.sa_handler = handler; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + if (sigaction(SIGINT, &sa, NULL) == -1) { + fprintf(stderr, "sigaction error\n"); + return -1; + } + + if (t->poll_timeout.tv_sec != 0) + ts = &t->poll_timeout; while (1) { - ret = poll(t->fds, t->poll_count, t->poll_timeout * 1000); - if (ret == 0) { - fprintf(stderr, "Poll timmed out!\n"); - return -1; - } - if (ret < 0) { - fprintf(stderr, "Poll Error!\n"); + ret = ppoll(t->fds, t->poll_count, ts, &mask_old); + if (ret <= 0) { + stop_tests(t); + fprintf(stderr, "Poll exit with errno %d\n", errno); return -1; } @@ -861,6 +890,7 @@ static int sanity_check(struct loopback_test *t) return 0; } + int main(int argc, char *argv[]) { int o, ret; @@ -915,7 +945,7 @@ int main(int argc, char *argv[]) t.async_timeout = atoi(optarg); break; case 'O': - t.poll_timeout = atoi(optarg); + t.poll_timeout.tv_sec = atoi(optarg); break; case 'c': t.async_outstanding_operations = atoi(optarg); @@ -955,9 +985,6 @@ int main(int argc, char *argv[]) if (t.async_timeout == 0) t.async_timeout = DEFAULT_ASYNC_TIMEOUT; - if (t.poll_timeout == 0) - t.poll_timeout = DEFAULT_POLL_TIMEOUT_SEC; - loopback_run(&t); return 0; -- cgit v0.10.2 From f8811c7630912617d1bc0e0b18e3221fec26f9cf Mon Sep 17 00:00:00 2001 From: Sandeep Patil Date: Tue, 15 Mar 2016 12:28:38 -0700 Subject: greybus: power_supply: reverse version check for new psy API Reversing the kernel version check for new power supply APIs will easily allow us to use older kernels with backported power supply APIs by defining "CORE_OWNS_PSY_STRUCT" in power supply core header Testing Done: - Build tested with arche kernel with backported power supply APIs - Build tested also with current arche kernel to make sure we build with 3.10 kernels Signed-off-by: Sandeep Patil Reviewed-by: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index 18bf8df..f5e62ed 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -17,9 +17,9 @@ #include #include -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) /* Commit: 297d716 power_supply: Change ownership from driver to core */ -#define DRIVER_OWNS_PSY_STRUCT +#define CORE_OWNS_PSY_STRUCT #endif #ifndef __ATTR_WO diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c index 0467537..ec8fb1b 100644 --- a/drivers/staging/greybus/power_supply.c +++ b/drivers/staging/greybus/power_supply.c @@ -26,7 +26,7 @@ struct gb_power_supply_prop { struct gb_power_supply { u8 id; bool registered; -#ifdef DRIVER_OWNS_PSY_STRUCT +#ifndef CORE_OWNS_PSY_STRUCT struct power_supply psy; #define to_gb_power_supply(x) container_of(x, struct gb_power_supply, psy) #else @@ -126,7 +126,7 @@ static void next_interval(struct gb_power_supply *gbpsy) gbpsy->update_interval = update_interval_max; } -#ifdef DRIVER_OWNS_PSY_STRUCT +#ifndef CORE_OWNS_PSY_STRUCT static void __gb_power_supply_changed(struct gb_power_supply *gbpsy) { power_supply_changed(&gbpsy->psy); @@ -513,7 +513,7 @@ static int property_is_writeable(struct power_supply *b, } -#ifdef DRIVER_OWNS_PSY_STRUCT +#ifndef CORE_OWNS_PSY_STRUCT static int gb_power_supply_register(struct gb_power_supply *gbpsy) { struct gb_connection *connection = get_conn_from_psy(gbpsy); @@ -569,7 +569,7 @@ static void _gb_power_supply_release(struct gb_power_supply *gbpsy) gbpsy->update_interval = 0; cancel_delayed_work_sync(&gbpsy->work); -#ifdef DRIVER_OWNS_PSY_STRUCT +#ifndef CORE_OWNS_PSY_STRUCT if (gbpsy->registered) power_supply_unregister(&gbpsy->psy); #else -- cgit v0.10.2 From 48b15a9b119d945933bfed6204d51e071d35328b Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 17 Mar 2016 11:02:02 +0100 Subject: greybus: camera: Implement the capabilities operation The operation queries the camera module for its capabilities. The debugfs interface just prints a hex dump of the binary message. Signed-off-by: Laurent Pinchart Signed-off-by: Jacopo Mondi Reviewed-by: Gjorgji Rosikopulos Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index d499ffd..6042c68 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -156,6 +156,33 @@ static int gb_camera_set_power_mode(struct gb_camera *gcam, bool hs) return 0; } +static int gb_camera_capabilities(struct gb_camera *gcam, + u8 *capabilities, size_t *size) +{ + struct gb_operation *op; + int ret; + + op = gb_operation_create_flags(gcam->connection, + GB_CAMERA_TYPE_CAPABILITIES, 0, *size, + GB_OPERATION_FLAG_SHORT_RESPONSE, + GFP_KERNEL); + if (!op) + return -ENOMEM; + + ret = gb_operation_request_send_sync(op); + if (ret) { + gcam_err(gcam, "failed to retrieve capabilities: %d\n", ret); + goto done; + } + + memcpy(capabilities, op->response->payload, op->response->payload_size); + *size = op->response->payload_size; + +done: + gb_operation_put(op); + return ret; +} + struct ap_csi_config_request { __u8 csi_id; __u8 flags; @@ -478,10 +505,41 @@ static int gb_camera_register_intf_ops(struct gb_camera *gcam) /* ----------------------------------------------------------------------------- * DebugFS */ + static ssize_t gb_camera_debugfs_capabilities(struct gb_camera *gcam, char *buf, size_t len) { - return len; + struct gb_camera_debugfs_buffer *buffer = + &gcam->debugfs.buffers[GB_CAMERA_DEBUGFS_BUFFER_CAPABILITIES]; + size_t size = 1024; + unsigned int i; + u8 *caps; + int ret; + + caps = kmalloc(size, GFP_KERNEL); + if (!caps) + return -ENOMEM; + + ret = gb_camera_capabilities(gcam, caps, &size); + if (ret < 0) + goto done; + + /* + * hex_dump_to_buffer() doesn't return the number of bytes dumped prior + * to v4.0, we need our own implementation :-( + */ + buffer->length = 0; + + for (i = 0; i < size; i += 16) { + unsigned int nbytes = min_t(unsigned int, size - i, 16); + + buffer->length += sprintf(buffer->data + buffer->length, + "%*ph\n", nbytes, caps + i); + } + +done: + kfree(caps); + return ret; } static ssize_t gb_camera_debugfs_configure_streams(struct gb_camera *gcam, -- cgit v0.10.2 From a883b0eb434c6ad0237b559b1b5c8cee89ef6350 Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Thu, 17 Mar 2016 11:02:03 +0100 Subject: greybus: camera: Register capabilities operation Register the greybus camera driver capabilities operation to the ara_camera subdevice Signed-off-by: Jacopo Mondi Reviewed-by: Gjorgji Rosikopulos Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 6042c68..e862659 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -421,6 +421,19 @@ static enum v4l2_mbus_pixelcode gb_camera_gb_to_mbus(u16 gb_fmt) return mbus_to_gbus_format[0].mbus_code; } +static ssize_t gb_camera_op_capabilities(void *priv, char *data, size_t len) +{ + struct gb_camera *gcam = priv; + size_t capabilities_len = len; + int ret; + + ret = gb_camera_capabilities(gcam, data, &capabilities_len); + if (ret) + return ret; + + return capabilities_len; +} + static int gb_camera_op_configure_streams(void *priv, unsigned int *nstreams, unsigned int *flags, struct gb_camera_stream *streams) { @@ -492,6 +505,7 @@ static int gb_camera_op_flush(void *priv, u32 *request_id) } struct gb_camera_ops gb_cam_ops = { + .capabilities = gb_camera_op_capabilities, .configure_streams = gb_camera_op_configure_streams, .capture = gb_camera_op_capture, .flush = gb_camera_op_flush, -- cgit v0.10.2 From c3d77f71308e38ef98909c317c57d906f4d51cb9 Mon Sep 17 00:00:00 2001 From: Gjorgji Rosikopulos Date: Mon, 14 Mar 2016 18:44:53 +0200 Subject: greybus: camera: Improve module registration mechanism Registering more then one module at same time was not possible with previous implementation. Also unregistering of the module was missing leading to many instability issues when camera module is ejected when camera is still active. Signed-off-by: Gjorgji Rosikopulos Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index e862659..722f2b4 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -38,6 +38,7 @@ struct gb_camera_debugfs_buffer { * @connection: the greybus connection for camera control * @data_connected: whether the data connection has been established * @debugfs: debugfs entries for camera protocol operations testing + * @module: Greybus camera module registered to HOST processor. */ struct gb_camera { struct gb_connection *connection; @@ -47,6 +48,8 @@ struct gb_camera { struct dentry *root; struct gb_camera_debugfs_buffer *buffers; } debugfs; + + struct gb_camera_module module; }; struct gb_camera_stream_config { @@ -504,16 +507,20 @@ static int gb_camera_op_flush(void *priv, u32 *request_id) return gb_camera_flush(priv, request_id); } -struct gb_camera_ops gb_cam_ops = { - .capabilities = gb_camera_op_capabilities, - .configure_streams = gb_camera_op_configure_streams, - .capture = gb_camera_op_capture, - .flush = gb_camera_op_flush, -}; - static int gb_camera_register_intf_ops(struct gb_camera *gcam) { - return gb_camera_register(&gb_cam_ops, gcam); + gcam->module.priv = gcam; + gcam->module.ops.capabilities = gb_camera_op_capabilities; + gcam->module.ops.configure_streams = gb_camera_op_configure_streams; + gcam->module.ops.capture = gb_camera_op_capture; + gcam->module.ops.flush = gb_camera_op_flush; + + return gb_camera_register(&gcam->module); +} + +static int gb_camera_unregister_intf_ops(struct gb_camera *gcam) +{ + return gb_camera_unregister(&gcam->module); } /* ----------------------------------------------------------------------------- @@ -931,6 +938,8 @@ static void gb_camera_connection_exit(struct gb_connection *connection) { struct gb_camera *gcam = connection->private; + gb_camera_unregister_intf_ops(gcam); + gb_camera_cleanup(gcam); } diff --git a/drivers/staging/greybus/gb-camera.h b/drivers/staging/greybus/gb-camera.h index 50af057..0a48a16 100644 --- a/drivers/staging/greybus/gb-camera.h +++ b/drivers/staging/greybus/gb-camera.h @@ -34,9 +34,18 @@ struct gb_camera_ops { int (*flush)(void *priv, u32 *request_id); }; -#define gb_camera_call(f, p, op, args...) \ - (((f)->op) ? (f)->op(p, ##args) : -ENOIOCTLCMD) +struct gb_camera_module { + void *priv; + struct gb_camera_ops ops; -int gb_camera_register(struct gb_camera_ops *ops, void *priv); + struct list_head list; /* Global list */ +}; + +#define gb_camera_call(f, op, args...) \ + ((!(f) ? -ENODEV : ((f)->ops.op) ? \ + (f)->ops.op((f)->priv, ##args) : -ENOIOCTLCMD)) + +int gb_camera_register(struct gb_camera_module *module); +int gb_camera_unregister(struct gb_camera_module *module); #endif /* __GB_CAMERA_H */ -- cgit v0.10.2 From 309520ec93f7190c0c3d22d613825a0835a8600f Mon Sep 17 00:00:00 2001 From: Mark Greer Date: Thu, 17 Mar 2016 10:32:37 -0700 Subject: greybus: audio: Use CSD instead of E2EFC for audio data connections There is no reason to use end-to-end flow control for Greybus audio data connections so disable it and enable Controlled Segment Dropping (CSD). Testing Done: Played music using audio modules on an EVT1.5. CC: Vaibhav Agarwal CC: Johan Hovold Signed-off-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index d7cae77..025dd53 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -694,8 +694,10 @@ static int gb_audio_add_data_connection(struct gbaudio_codec_info *gbcodec, return -ENOMEM; } - connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id), - gbaudio_dai_request_handler); + connection = gb_connection_create_flags(bundle, + le16_to_cpu(cport_desc->id), + gbaudio_dai_request_handler, + GB_CONNECTION_FLAG_CSD); if (IS_ERR(connection)) { devm_kfree(gbcodec->dev, dai); return PTR_ERR(connection); -- cgit v0.10.2 From 30b442b385c199b3f8e1df26fd6f0c07b61b32a2 Mon Sep 17 00:00:00 2001 From: David Lin Date: Fri, 18 Mar 2016 18:30:50 -0700 Subject: greybus: greybus_trace: Fix broken greybus ftrace Enabling greybus ftrace event causes null pointer access due to that gb_message to SVC has no Bundle. Fix it by handling this in the trace header. Testing Done: $ echo 1 > /d/tracing/event/greybus/enable [002] ...1 54.504426: gb_message_send: greybus:1-svc op=0023 if_id=0 hd_id=0 l=0 [002] ...1 54.504461: gb_host_device_send: greybus:greybus1 if_id=0 l=8 Signed-off-by: David Lin Reviewed-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h index 96c5151..6f3e101 100644 --- a/drivers/staging/greybus/greybus_trace.h +++ b/drivers/staging/greybus/greybus_trace.h @@ -17,6 +17,11 @@ struct gb_message; struct gb_host_device; +#define gb_bundle_name(message) \ + (message->operation->connection->bundle ? \ + dev_name(&message->operation->connection->bundle->dev) : \ + dev_name(&message->operation->connection->hd->svc->dev)) + DECLARE_EVENT_CLASS(gb_message, TP_PROTO(struct gb_message *message), @@ -24,7 +29,7 @@ DECLARE_EVENT_CLASS(gb_message, TP_ARGS(message), TP_STRUCT__entry( - __string(name, dev_name(&message->operation->connection->bundle->dev)) + __string(name, gb_bundle_name(message)) __field(u16, op_id) __field(u16, intf_cport_id) __field(u16, hd_cport_id) @@ -32,7 +37,7 @@ DECLARE_EVENT_CLASS(gb_message, ), TP_fast_assign( - __assign_str(name, dev_name(&message->operation->connection->bundle->dev)) + __assign_str(name, gb_bundle_name(message)) __entry->op_id = message->operation->id; __entry->intf_cport_id = message->operation->connection->intf_cport_id; -- cgit v0.10.2 From 418f3dab841f85e24beb6e30858cafce5cf1f87c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 22 Mar 2016 14:30:16 -0400 Subject: greybus: connection: add functions to get/set private data Add gb_connection_get_data() and gb_connection_set_data() to get and set the private data of a connection, instead of "open coding" it everywhere. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 6197d45..443d27b 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -88,4 +88,15 @@ static inline bool gb_connection_e2efc_enabled(struct gb_connection *connection) return !(connection->flags & GB_CONNECTION_FLAG_CSD); } +static inline void *gb_connection_get_data(struct gb_connection *connection) +{ + return connection->private; +} + +static inline void gb_connection_set_data(struct gb_connection *connection, + void *data) +{ + connection->private = data; +} + #endif /* __CONNECTION_H */ -- cgit v0.10.2 From 0ec306324423444d3ee0222708ef9de7f5586b93 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 22 Mar 2016 14:30:35 -0400 Subject: greybus: convert drivers to use connection->private set/get This converts all drivers to use the gb_connection_get_data() and gb_connection_set_data() functions to make it a bit more explicit as to what is going on. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 025dd53..30b381a 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -675,7 +675,7 @@ static int gb_audio_add_mgmt_connection(struct gbaudio_codec_info *gbcodec, if (IS_ERR(connection)) return PTR_ERR(connection); - connection->private = gbcodec; + gb_connection_set_data(connection, gbcodec); gbcodec->mgmt_connection = connection; return 0; @@ -703,7 +703,7 @@ static int gb_audio_add_data_connection(struct gbaudio_codec_info *gbcodec, return PTR_ERR(connection); } - connection->private = gbcodec; + gb_connection_set_data(connection, gbcodec); atomic_set(&dai->users, 0); init_waitqueue_head(&dai->wait_queue); dai->data_cport = connection->intf_cport_id; diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 722f2b4..a871b0f 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -374,7 +374,7 @@ static int gb_camera_flush(struct gb_camera *gcam, u32 *request_id) static int gb_camera_event_recv(u8 type, struct gb_operation *op) { - struct gb_camera *gcam = op->connection->private; + struct gb_camera *gcam = gb_connection_get_data(op->connection); struct gb_camera_metadata_request *payload; struct gb_message *request; @@ -904,7 +904,7 @@ static int gb_camera_connection_init(struct gb_connection *connection) return -ENOMEM; gcam->connection = connection; - connection->private = gcam; + gb_connection_set_data(connection, gcam); /* * Create the data connection between camera module CDSI0 and APB CDS1. @@ -936,7 +936,7 @@ error: static void gb_camera_connection_exit(struct gb_connection *connection) { - struct gb_camera *gcam = connection->private; + struct gb_camera *gcam = gb_connection_get_data(connection); gb_camera_unregister_intf_ops(gcam); diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index bac412ef..83be255 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -195,7 +195,7 @@ struct gb_control *gb_control_create(struct gb_interface *intf) return NULL; } - control->connection->private = control; + gb_connection_set_data(control->connection, control); return control; } diff --git a/drivers/staging/greybus/firmware.c b/drivers/staging/greybus/firmware.c index 17ce573..b1188b2 100644 --- a/drivers/staging/greybus/firmware.c +++ b/drivers/staging/greybus/firmware.c @@ -115,11 +115,10 @@ static int download_firmware(struct gb_firmware *firmware, u8 stage) static int gb_firmware_size_request(struct gb_operation *op) { - struct gb_connection *connection = op->connection; - struct gb_firmware *firmware = connection->private; + struct gb_firmware *firmware = gb_connection_get_data(op->connection); struct gb_firmware_size_request *size_request = op->request->payload; struct gb_firmware_size_response *size_response; - struct device *dev = &connection->bundle->dev; + struct device *dev = &op->connection->bundle->dev; int ret; if (op->request->payload_size != sizeof(*size_request)) { @@ -153,12 +152,11 @@ static int gb_firmware_size_request(struct gb_operation *op) static int gb_firmware_get_firmware(struct gb_operation *op) { - struct gb_connection *connection = op->connection; - struct gb_firmware *firmware = connection->private; + struct gb_firmware *firmware = gb_connection_get_data(op->connection); const struct firmware *fw = firmware->fw; struct gb_firmware_get_firmware_request *firmware_request; struct gb_firmware_get_firmware_response *firmware_response; - struct device *dev = &connection->bundle->dev; + struct device *dev = &op->connection->bundle->dev; unsigned int offset, size; if (op->request->payload_size != sizeof(*firmware_request)) { @@ -309,7 +307,7 @@ static int gb_firmware_probe(struct gb_bundle *bundle, goto err_free_firmware; } - connection->private = firmware; + gb_connection_set_data(connection, firmware); firmware->connection = connection; diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 7b2cb5d..440ff44c 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -351,7 +351,7 @@ static int gb_gpio_request_recv(u8 type, struct gb_operation *op) { struct gb_connection *connection = op->connection; struct device *dev = &connection->bundle->dev; - struct gb_gpio_controller *ggc = connection->private; + struct gb_gpio_controller *ggc = gb_connection_get_data(connection); struct gb_message *request; struct gb_gpio_irq_event_request *event; int irq; @@ -633,7 +633,7 @@ static int gb_gpio_connection_init(struct gb_connection *connection) if (!ggc) return -ENOMEM; ggc->connection = connection; - connection->private = ggc; + gb_connection_set_data(connection, ggc); ret = gb_gpio_controller_setup(ggc); if (ret) @@ -700,7 +700,7 @@ err_free_controller: static void gb_gpio_connection_exit(struct gb_connection *connection) { - struct gb_gpio_controller *ggc = connection->private; + struct gb_gpio_controller *ggc = gb_connection_get_data(connection); if (!ggc) return; diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index 6ef151f..fd4a7e0 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -100,7 +100,7 @@ static int gb_hid_set_report(struct gb_hid *ghid, u8 report_type, u8 report_id, static int gb_hid_request_handler(struct gb_operation *op) { struct gb_connection *connection = op->connection; - struct gb_hid *ghid = connection->private; + struct gb_hid *ghid = gb_connection_get_data(connection); struct gb_hid_input_report_request *request = op->request->payload; if (op->type != GB_HID_TYPE_IRQ_EVENT) { @@ -449,7 +449,7 @@ static int gb_hid_probe(struct gb_bundle *bundle, goto err_free_ghid; } - connection->private = ghid; + gb_connection_set_data(connection, ghid); ghid->connection = connection; hid = hid_allocate_device(); diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c index 4b96f69..73b8581 100644 --- a/drivers/staging/greybus/i2c.c +++ b/drivers/staging/greybus/i2c.c @@ -251,7 +251,7 @@ static int gb_i2c_connection_init(struct gb_connection *connection) return -ENOMEM; gb_i2c_dev->connection = connection; /* refcount? */ - connection->private = gb_i2c_dev; + gb_connection_set_data(connection, gb_i2c_dev); ret = gb_i2c_device_setup(gb_i2c_dev); if (ret) @@ -282,7 +282,7 @@ out_err: static void gb_i2c_connection_exit(struct gb_connection *connection) { - struct gb_i2c_device *gb_i2c_dev = connection->private; + struct gb_i2c_device *gb_i2c_dev = gb_connection_get_data(connection); i2c_del_adapter(&gb_i2c_dev->adapter); /* kref_put(gb_i2c_dev->connection) */ diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index 47d4ac4..8b71ed3 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -1154,7 +1154,7 @@ static int gb_lights_request_handler(struct gb_operation *op) { struct gb_connection *connection = op->connection; struct device *dev = &connection->bundle->dev; - struct gb_lights *glights = connection->private; + struct gb_lights *glights = gb_connection_get_data(connection); struct gb_light *light; struct gb_message *request; struct gb_lights_event_request *payload; @@ -1230,7 +1230,7 @@ static int gb_lights_probe(struct gb_bundle *bundle, } glights->connection = connection; - connection->private = glights; + gb_connection_set_data(connection, glights); mutex_init(&glights->lights_lock); diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c index ec8fb1b..9cae396 100644 --- a/drivers/staging/greybus/power_supply.c +++ b/drivers/staging/greybus/power_supply.c @@ -711,7 +711,7 @@ static int gb_power_supplies_register(struct gb_power_supplies *supplies) static int gb_supplies_request_handler(struct gb_operation *op) { struct gb_connection *connection = op->connection; - struct gb_power_supplies *supplies = connection->private; + struct gb_power_supplies *supplies = gb_connection_get_data(connection); struct gb_power_supply *gbpsy; struct gb_message *request; struct gb_power_supply_event_request *payload; @@ -792,7 +792,7 @@ static int gb_power_supply_probe(struct gb_bundle *bundle, } supplies->connection = connection; - connection->private = supplies; + gb_connection_set_data(connection, supplies); mutex_init(&supplies->supplies_lock); diff --git a/drivers/staging/greybus/pwm.c b/drivers/staging/greybus/pwm.c index 018d5c2..176301a 100644 --- a/drivers/staging/greybus/pwm.c +++ b/drivers/staging/greybus/pwm.c @@ -188,7 +188,7 @@ static int gb_pwm_connection_init(struct gb_connection *connection) if (!pwmc) return -ENOMEM; pwmc->connection = connection; - connection->private = pwmc; + gb_connection_set_data(connection, pwmc); /* Query number of pwms present */ ret = gb_pwm_count_operation(pwmc); @@ -218,8 +218,7 @@ out_err: static void gb_pwm_connection_exit(struct gb_connection *connection) { - struct gb_pwm_chip *pwmc = connection->private; - + struct gb_pwm_chip *pwmc = gb_connection_get_data(connection); if (!pwmc) return; diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index 9a20f0e..d4cbcb9 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -201,15 +201,14 @@ static int _gb_sdio_process_events(struct gb_sdio_host *host, u8 event) static int gb_sdio_event_recv(u8 type, struct gb_operation *op) { - struct gb_connection *connection = op->connection; - struct gb_sdio_host *host = connection->private; + struct gb_sdio_host *host = gb_connection_get_data(op->connection); struct gb_message *request; struct gb_sdio_event_request *payload; int ret = 0; u8 event; if (type != GB_SDIO_TYPE_EVENT) { - dev_err(&connection->bundle->dev, + dev_err(mmc_dev(host->mmc), "unsupported unsolicited event: %u\n", type); return -EINVAL; } @@ -723,7 +722,7 @@ static int gb_sdio_connection_init(struct gb_connection *connection) host->removed = true; host->connection = connection; - connection->private = host; + gb_connection_set_data(connection, host); ret = gb_sdio_get_caps(host); if (ret < 0) @@ -767,7 +766,7 @@ free_work: free_buffer: kfree(host->xfer_buffer); free_mmc: - connection->private = NULL; + gb_connection_set_data(connection, NULL); mmc_free_host(mmc); return ret; @@ -776,7 +775,7 @@ free_mmc: static void gb_sdio_connection_exit(struct gb_connection *connection) { struct mmc_host *mmc; - struct gb_sdio_host *host = connection->private; + struct gb_sdio_host *host = gb_connection_get_data(connection); if (!host) return; @@ -784,7 +783,7 @@ static void gb_sdio_connection_exit(struct gb_connection *connection) mutex_lock(&host->lock); host->removed = true; mmc = host->mmc; - connection->private = NULL; + gb_connection_set_data(connection, NULL); mutex_unlock(&host->lock); flush_workqueue(host->mrq_workqueue); diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index 3571453..12e8cd8 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -28,7 +28,7 @@ struct gb_spi { static struct spi_master *get_master_from_spi(struct gb_spi *spi) { - return spi->connection->private; + return gb_connection_get_data(spi->connection); } static int tx_header_fit_operation(u32 tx_size, u32 count, size_t data_max) @@ -339,7 +339,7 @@ static int gb_spi_connection_init(struct gb_connection *connection) spi = spi_master_get_devdata(master); spi->connection = connection; - connection->private = master; + gb_connection_set_data(connection, master); /* get master configuration */ ret = gb_spi_get_master_config(spi); @@ -382,7 +382,7 @@ out_put_master: static void gb_spi_connection_exit(struct gb_connection *connection) { - struct spi_master *master = connection->private; + struct spi_master *master = gb_connection_get_data(connection); spi_unregister_master(master); } diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index ae1911c..6a8da0d 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -397,7 +397,7 @@ EXPORT_SYMBOL_GPL(gb_svc_ping); static int gb_svc_version_request(struct gb_operation *op) { struct gb_connection *connection = op->connection; - struct gb_svc *svc = connection->private; + struct gb_svc *svc = gb_connection_get_data(connection); struct gb_protocol_version_request *request; struct gb_protocol_version_response *response; @@ -432,7 +432,7 @@ static int gb_svc_version_request(struct gb_operation *op) static int gb_svc_hello(struct gb_operation *op) { struct gb_connection *connection = op->connection; - struct gb_svc *svc = connection->private; + struct gb_svc *svc = gb_connection_get_data(connection); struct gb_svc_hello_request *hello_request; int ret; @@ -550,7 +550,7 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) { struct gb_svc_intf_hotplug_request *request; struct gb_connection *connection = operation->connection; - struct gb_svc *svc = connection->private; + struct gb_svc *svc = gb_connection_get_data(connection); struct gb_host_device *hd = connection->hd; struct gb_interface *intf; u8 intf_id; @@ -644,7 +644,7 @@ out_interface_add: static void gb_svc_process_intf_hot_unplug(struct gb_operation *operation) { - struct gb_svc *svc = operation->connection->private; + struct gb_svc *svc = gb_connection_get_data(operation->connection); struct gb_svc_intf_hot_unplug_request *request; struct gb_host_device *hd = operation->connection->hd; struct gb_interface *intf; @@ -675,7 +675,7 @@ static void gb_svc_process_deferred_request(struct work_struct *work) dr = container_of(work, struct gb_svc_deferred_request, work); operation = dr->operation; - svc = operation->connection->private; + svc = gb_connection_get_data(operation->connection); type = operation->request->header->type; switch (type) { @@ -695,7 +695,7 @@ static void gb_svc_process_deferred_request(struct work_struct *work) static int gb_svc_queue_deferred_request(struct gb_operation *operation) { - struct gb_svc *svc = operation->connection->private; + struct gb_svc *svc = gb_connection_get_data(operation->connection); struct gb_svc_deferred_request *dr; dr = kmalloc(sizeof(*dr), GFP_KERNEL); @@ -723,7 +723,7 @@ static int gb_svc_queue_deferred_request(struct gb_operation *operation) */ static int gb_svc_intf_hotplug_recv(struct gb_operation *op) { - struct gb_svc *svc = op->connection->private; + struct gb_svc *svc = gb_connection_get_data(op->connection); struct gb_svc_intf_hotplug_request *request; if (op->request->payload_size < sizeof(*request)) { @@ -741,7 +741,7 @@ static int gb_svc_intf_hotplug_recv(struct gb_operation *op) static int gb_svc_intf_hot_unplug_recv(struct gb_operation *op) { - struct gb_svc *svc = op->connection->private; + struct gb_svc *svc = gb_connection_get_data(op->connection); struct gb_svc_intf_hot_unplug_request *request; if (op->request->payload_size < sizeof(*request)) { @@ -759,7 +759,7 @@ static int gb_svc_intf_hot_unplug_recv(struct gb_operation *op) static int gb_svc_intf_reset_recv(struct gb_operation *op) { - struct gb_svc *svc = op->connection->private; + struct gb_svc *svc = gb_connection_get_data(op->connection); struct gb_message *request = op->request; struct gb_svc_intf_reset_request *reset; u8 intf_id; @@ -794,7 +794,7 @@ static int gb_svc_key_code_map(struct gb_svc *svc, u16 key_code, u16 *code) static int gb_svc_key_event_recv(struct gb_operation *op) { - struct gb_svc *svc = op->connection->private; + struct gb_svc *svc = gb_connection_get_data(op->connection); struct gb_message *request = op->request; struct gb_svc_key_event_request *key; u16 code; @@ -828,7 +828,7 @@ static int gb_svc_key_event_recv(struct gb_operation *op) static int gb_svc_request_handler(struct gb_operation *op) { struct gb_connection *connection = op->connection; - struct gb_svc *svc = connection->private; + struct gb_svc *svc = gb_connection_get_data(connection); u8 type = op->type; int ret = 0; @@ -975,7 +975,7 @@ struct gb_svc *gb_svc_create(struct gb_host_device *hd) goto err_free_input; } - svc->connection->private = svc; + gb_connection_set_data(svc->connection, svc); return svc; diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index d169c55..c580fe0 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -69,7 +69,7 @@ static atomic_t reference_count = ATOMIC_INIT(0); static int gb_uart_receive_data_handler(struct gb_operation *op) { struct gb_connection *connection = op->connection; - struct gb_tty *gb_tty = connection->private; + struct gb_tty *gb_tty = gb_connection_get_data(connection); struct tty_port *port = &gb_tty->port; struct gb_message *request = op->request; struct gb_uart_recv_data_request *receive_data; @@ -125,7 +125,7 @@ static int gb_uart_receive_data_handler(struct gb_operation *op) static int gb_uart_serial_state_handler(struct gb_operation *op) { struct gb_connection *connection = op->connection; - struct gb_tty *gb_tty = connection->private; + struct gb_tty *gb_tty = gb_connection_get_data(connection); struct gb_message *request = op->request; struct gb_uart_serial_state_request *serial_state; @@ -658,7 +658,7 @@ static int gb_uart_connection_init(struct gb_connection *connection) } gb_tty->connection = connection; - connection->private = gb_tty; + gb_connection_set_data(connection, gb_tty); minor = alloc_minor(gb_tty); if (minor < 0) { @@ -702,7 +702,7 @@ error: tty_port_destroy(&gb_tty->port); release_minor(gb_tty); error_minor: - connection->private = NULL; + gb_connection_set_data(connection, NULL); kfree(gb_tty->buffer); error_payload: kfree(gb_tty); @@ -714,7 +714,7 @@ error_alloc: static void gb_uart_connection_exit(struct gb_connection *connection) { - struct gb_tty *gb_tty = connection->private; + struct gb_tty *gb_tty = gb_connection_get_data(connection); struct tty_struct *tty; if (!gb_tty) @@ -724,7 +724,7 @@ static void gb_uart_connection_exit(struct gb_connection *connection) gb_tty->disconnected = true; wake_up_all(&gb_tty->wioctl); - connection->private = NULL; + gb_connection_set_data(connection, NULL); mutex_unlock(&gb_tty->mutex); tty = tty_port_tty_get(&gb_tty->port); diff --git a/drivers/staging/greybus/usb.c b/drivers/staging/greybus/usb.c index 0cfc00f..25a6c7e 100644 --- a/drivers/staging/greybus/usb.c +++ b/drivers/staging/greybus/usb.c @@ -176,7 +176,7 @@ static int gb_usb_connection_init(struct gb_connection *connection) gb_usb_dev = to_gb_usb_device(hcd); gb_usb_dev->connection = connection; - connection->private = gb_usb_dev; + gb_connection_set_data(connection, gb_usb_dev); hcd->has_tt = 1; @@ -206,7 +206,7 @@ err_put_hcd: static void gb_usb_connection_exit(struct gb_connection *connection) { - struct gb_usb_device *gb_usb_dev = connection->private; + struct gb_usb_device *gb_usb_dev = gb_connection_get_data(connection); struct usb_hcd *hcd = gb_usb_device_to_hcd(gb_usb_dev); usb_remove_hcd(hcd); diff --git a/drivers/staging/greybus/vibrator.c b/drivers/staging/greybus/vibrator.c index 8c0df99..5afcb27 100644 --- a/drivers/staging/greybus/vibrator.c +++ b/drivers/staging/greybus/vibrator.c @@ -114,7 +114,7 @@ static int gb_vibrator_probe(struct gb_bundle *bundle, retval = PTR_ERR(connection); goto err_free_vib; } - connection->private = vib; + gb_connection_set_data(connection, vib); vib->connection = connection; -- cgit v0.10.2 From 6dd67645f22cfeb55a32e9a08c92deb297d06935 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal Date: Tue, 29 Mar 2016 23:31:41 +0530 Subject: greybus: audio: Use single codec driver registration We have single I2S port via APB1 for communication with all audio modules. Thus, we should register single codec driver and manage all individual audio modules internally within this driver. Signed-off-by: Vaibhav Agarwal Reviewed-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 30b381a..ab24ec8 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -1,7 +1,7 @@ /* - * Greybus audio driver - * Copyright 2015 Google Inc. - * Copyright 2015 Linaro Ltd. + * audio codec driver + * Copyright 2016 Google Inc. + * Copyright 2016 Linaro Ltd. * * Released under the GPLv2 only. */ @@ -9,128 +9,382 @@ #include #include #include -#include #include "audio_codec.h" #include "audio_apbridgea.h" #include "audio_manager.h" -static DEFINE_MUTEX(gb_codec_list_lock); -static LIST_HEAD(gb_codec_list); +static struct gbaudio_codec_info *gbcodec; -struct gbaudio_dai *gbaudio_find_dai(struct gbaudio_codec_info *gbcodec, - int data_cport, const char *name) +struct gbaudio_data_connection *find_data(struct gbaudio_module_info *module, + const char *name) { - struct gbaudio_dai *dai; + struct gbaudio_data_connection *data; - list_for_each_entry(dai, &gbcodec->dai_list, list) { - if (name && !strncmp(dai->name, name, NAME_SIZE)) - return dai; - if ((data_cport != -1) && (dai->data_cport == data_cport)) - return dai; + list_for_each_entry(data, &module->data_list, list) { + if (name && !strncmp(data->name, name, NAME_SIZE)) + return data; } return NULL; } -/* - * codec DAI ops - */ -static int gbcodec_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) +static int find_stream(const char *name) { - int ret; - __u16 i2s_port, cportid; + int stream = 0; + + if (strnstr(name, "SPK Amp", NAME_SIZE)) + stream |= GB_PLAYBACK; + + return stream; +} + +static int gbaudio_module_disable(struct gbaudio_codec_info *codec, + struct gbaudio_module_info *module, + int dir) +{ + int ret = 0; + uint16_t data_cport, cportid, i2s_port; + int codec_state, module_state; + struct gbaudio_data_connection *data; + const char *dai_name; + + mutex_lock(&codec->lock); + + codec_state = codec->stream[dir].state; + if (codec_state == GBAUDIO_CODEC_SHUTDOWN) { + mutex_unlock(&codec->lock); + return 0; + } + + dai_name = codec->stream[dir].dai_name; - struct gbaudio_dai *gb_dai; - struct gbaudio_codec_info *gb = dev_get_drvdata(dai->dev); + mutex_lock(&module->lock); + module_state = module->ctrlstate[dir]; + if (module_state == GBAUDIO_CODEC_SHUTDOWN) { + dev_dbg(codec->dev, "%s: module already configured\n", + module->name); + goto func_exit; + } - if (!atomic_read(&gb->is_connected)) + /* find the dai */ + data = find_data(module, dai_name); + if (!data) { + dev_err(codec->dev, "%s:%s DATA connection missing\n", + dai_name, module->name); + mutex_unlock(&module->lock); + mutex_unlock(&codec->lock); return -ENODEV; + } + if (codec_state > GBAUDIO_CODEC_HWPARAMS) { + data_cport = data->connection->intf_cport_id; + ret = gb_audio_gb_deactivate_tx(module->mgmt_connection, + data_cport); + if (ret) { + dev_err(codec->dev, "deactivate_tx for %s failed:%d\n", + module->name, ret); + goto func_exit; + } + dev_dbg(codec->dev, "Dynamic deactivate %s:%d DAI\n", dai_name, + data_cport); + } + if (codec_state > GBAUDIO_CODEC_SHUTDOWN) { + cportid = data->connection->hd_cport_id; + ret = gb_audio_apbridgea_unregister_cport(data->connection, + i2s_port, cportid, + AUDIO_APBRIDGEA_DIRECTION_TX); + if (ret) { + dev_err(codec->dev, "unregister_cport for %s failed:%d\n", + module->name, ret); + goto func_exit; + } + dev_dbg(codec->dev, "Dynamic Unregister %s:%d DAI\n", dai_name, + cportid); + } + module->ctrlstate[dir] = GBAUDIO_CODEC_SHUTDOWN; + +func_exit: + mutex_unlock(&module->lock); + mutex_unlock(&codec->lock); + return ret; +} + +static int gbaudio_module_enable(struct gbaudio_codec_info *codec, + struct gbaudio_module_info *module, int dir) +{ + int ret = 0; + __u16 i2s_port, cportid; + int codec_state, module_state; + uint16_t data_cport; + uint8_t sig_bits, channels; + uint32_t format, rate; + struct gbaudio_data_connection *data; + const char *dai_name; + + mutex_lock(&codec->lock); + + codec_state = codec->stream[dir].state; + if (codec_state == GBAUDIO_CODEC_SHUTDOWN) { + mutex_unlock(&codec->lock); + return 0; + } + + dai_name = codec->stream[dir].dai_name; + format = codec->stream[dir].format; + channels = codec->stream[dir].channels; + rate = codec->stream[dir].rate; + sig_bits = codec->stream[dir].sig_bits; + + mutex_lock(&module->lock); + module_state = module->ctrlstate[dir]; + if (module_state == codec_state) { + dev_dbg(codec->dev, "%s: module already configured\n", + module->name); + goto func_exit; + } /* find the dai */ - mutex_lock(&gb->lock); - gb_dai = gbaudio_find_dai(gb, -1, dai->name); - if (!gb_dai) { - dev_err(dai->dev, "%s: DAI not registered\n", dai->name); - mutex_unlock(&gb->lock); - return -EINVAL; + data = find_data(module, dai_name); + if (!data) { + dev_err(codec->dev, "%s:%s DATA connection missing\n", + dai_name, module->name); + mutex_unlock(&module->lock); + mutex_unlock(&codec->lock); + return -ENODEV; } /* register cport */ - i2s_port = 0; /* fixed for now */ - cportid = gb_dai->connection->hd_cport_id; - ret = gb_audio_apbridgea_register_cport(gb_dai->connection, i2s_port, - cportid, + if (module_state < codec_state) { + i2s_port = 0; /* fixed for now */ + cportid = data->connection->hd_cport_id; + ret = gb_audio_apbridgea_register_cport(data->connection, + i2s_port, cportid, AUDIO_APBRIDGEA_DIRECTION_TX); - dev_dbg(dai->dev, "Register %s:%d DAI, ret:%d\n", dai->name, cportid, - ret); + if (ret) { + dev_err(codec->dev, "reg_cport for %s\n", module->name); + goto func_exit; + } + module_state = GBAUDIO_CODEC_STARTUP; + dev_dbg(codec->dev, "Dynamic Register %s:%d DAI\n", dai_name, + cportid); + } + + /* hw_params */ + if (module_state < codec_state) { + data_cport = data->connection->intf_cport_id; + ret = gb_audio_gb_set_pcm(module->mgmt_connection, data_cport, + format, rate, channels, sig_bits); + if (ret) { + dev_err(codec->dev, "set_pcm for %s\n", module->name); + goto func_exit; + } + module_state = GBAUDIO_CODEC_HWPARAMS; + dev_dbg(codec->dev, "Dynamic hw_params %s:%d DAI\n", dai_name, + data_cport); + } - if (!ret) - atomic_inc(&gb_dai->users); - mutex_unlock(&gb->lock); + /* prepare */ + if (module_state < codec_state) { + data_cport = data->connection->intf_cport_id; + ret = gb_audio_gb_set_tx_data_size(module->mgmt_connection, + data_cport, 192); + if (ret) { + dev_err(codec->dev, "set_tx_data_size for %s\n", + module->name); + goto func_exit; + } + ret = gb_audio_gb_activate_tx(module->mgmt_connection, + data_cport); + if (ret) { + dev_err(codec->dev, "activate_tx for %s\n", + module->name); + goto func_exit; + } + module_state = GBAUDIO_CODEC_PREPARE; + dev_dbg(codec->dev, "Dynamic prepare %s:%d DAI\n", dai_name, + data_cport); + } +func_exit: + module->ctrlstate[dir] = module_state; + mutex_unlock(&module->lock); + mutex_unlock(&codec->lock); return ret; } -static void gbcodec_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) +int gbaudio_module_update(struct gbaudio_codec_info *codec, + const char *w_name, + struct gbaudio_module_info *module, int enable) { - int ret; - __u16 i2s_port, cportid; + int stream, ret = 0; + int pb_state; - struct gbaudio_dai *gb_dai; - struct gbaudio_codec_info *gb = dev_get_drvdata(dai->dev); + dev_dbg(module->dev, "Module update %s sequence\n", + enable ? "Enable":"Disable"); - /* find the dai */ - gb_dai = gbaudio_find_dai(gb, -1, dai->name); - if (!gb_dai) { - dev_err(dai->dev, "%s: DAI not registered\n", dai->name); - goto func_exit; + stream = find_stream(w_name); + if (!stream) { + dev_dbg(codec->dev, "No action required for %s\n", w_name); + return 0; } - atomic_dec(&gb_dai->users); + /* check if playback active */ + pb_state = codec->stream[SNDRV_PCM_STREAM_PLAYBACK].state; + if ((stream & GB_PLAYBACK) && (pb_state > GBAUDIO_CODEC_SHUTDOWN)) { + if (enable) + ret = gbaudio_module_enable(codec, module, + SNDRV_PCM_STREAM_PLAYBACK); + else + ret = gbaudio_module_disable(codec, module, + SNDRV_PCM_STREAM_PLAYBACK); + } - if (!atomic_read(&gb->is_connected)) { - if (!atomic_read(&gb_dai->users)) - wake_up_interruptible(&gb_dai->wait_queue); - return; + /* TBD + * check if capture active + * cap_state = codec->stream[SNDRV_PCM_STREAM_CAPTURE].state; + * if ((stream & GB_CAPTURE) && (cap_state > GBAUDIO_CODEC_SHUTDOWN)) + * + */ + + return ret; +} +EXPORT_SYMBOL(gbaudio_module_update); + +/* + * codec DAI ops + */ +static int gbcodec_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + int ret = 0; + __u16 i2s_port, cportid; + int state; + struct gbaudio_data_connection *data; + struct gbaudio_module_info *module; + struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev); + + mutex_lock(&codec->lock); + + if (list_empty(&codec->module_list)) { + dev_err(codec->dev, "No codec module available\n"); + mutex_unlock(&codec->lock); + return -ENODEV; } - mutex_lock(&gb->lock); - /* deactivate rx/tx */ - cportid = gb_dai->connection->intf_cport_id; + state = codec->stream[substream->stream].state; + list_for_each_entry(module, &codec->module_list, list) { + mutex_lock(&module->lock); + if (!module->is_connected) { + mutex_unlock(&module->lock); + continue; + } - switch (substream->stream) { - case SNDRV_PCM_STREAM_CAPTURE: - ret = gb_audio_gb_deactivate_rx(gb->mgmt_connection, cportid); - break; - case SNDRV_PCM_STREAM_PLAYBACK: - ret = gb_audio_gb_deactivate_tx(gb->mgmt_connection, cportid); - break; - default: - dev_err(dai->dev, "Invalid stream type during shutdown\n"); - goto func_exit; + /* find the dai */ + data = find_data(module, dai->name); + if (!data) { + dev_err(dai->dev, "%s:%s DATA connection missing\n", + dai->name, module->name); + mutex_unlock(&module->lock); + continue; + } + + /* register cport */ + i2s_port = 0; /* fixed for now */ + cportid = data->connection->hd_cport_id; + ret = gb_audio_apbridgea_register_cport(data->connection, + i2s_port, cportid, + AUDIO_APBRIDGEA_DIRECTION_TX); + dev_dbg(dai->dev, "Register %s:%d DAI, ret:%d\n", dai->name, + cportid, ret); + state = GBAUDIO_CODEC_STARTUP; + module->ctrlstate[substream->stream] = state; + dev_dbg(dai->dev, "%s: state:%d\n", module->name, state); + mutex_unlock(&module->lock); } + codec->stream[substream->stream].state = state; + codec->stream[substream->stream].dai_name = dai->name; + mutex_unlock(&codec->lock); - if (ret) - dev_err(dai->dev, "%d:Error during deactivate\n", ret); + return ret; +} - /* un register cport */ - i2s_port = 0; /* fixed for now */ - ret = gb_audio_apbridgea_unregister_cport(gb_dai->connection, i2s_port, - gb_dai->connection->hd_cport_id, - AUDIO_APBRIDGEA_DIRECTION_TX); +static void gbcodec_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + int ret; + __u16 i2s_port, cportid; + int state, module_state; + struct gbaudio_module_info *module; + struct gbaudio_data_connection *data; + struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev); - dev_dbg(dai->dev, "Unregister %s:%d DAI, ret:%d\n", dai->name, - gb_dai->connection->hd_cport_id, ret); -func_exit: - mutex_unlock(&gb->lock); + mutex_lock(&codec->lock); - /* - if (!atomic_read(&gb_dai->users)) - wake_up_interruptible(&gb_dai->wait_queue); - */ + if (list_empty(&codec->module_list)) { + dev_err(codec->dev, "No codec module available\n"); + mutex_unlock(&codec->lock); + return; + } + + state = codec->stream[substream->stream].state; + list_for_each_entry(module, &codec->module_list, list) { + mutex_lock(&module->lock); + if (!module->is_connected) { + dev_err(dai->dev, "%s:%s module not connected\n", + __func__, module->name); + mutex_unlock(&module->lock); + continue; + } + module_state = module->ctrlstate[substream->stream]; + if (module_state == GBAUDIO_CODEC_SHUTDOWN) { + dev_dbg(codec->dev, "%s: module already configured\n", + module->name); + mutex_unlock(&module->lock); + continue; + } + + /* find the dai */ + data = find_data(module, dai->name); + if (!data) { + dev_err(dai->dev, "%s:%s DATA connection missing\n", + dai->name, module->name); + mutex_unlock(&module->lock); + continue; + } + /* deactivate */ + cportid = data->connection->intf_cport_id; + switch (substream->stream) { + case SNDRV_PCM_STREAM_CAPTURE: + ret = gb_audio_gb_deactivate_rx(module->mgmt_connection, + cportid); + /* unregister cport */ + i2s_port = 0; /* fixed for now */ + cportid = data->connection->hd_cport_id; + ret = gb_audio_apbridgea_unregister_cport( + data->connection, i2s_port, cportid, + AUDIO_APBRIDGEA_DIRECTION_RX); + break; + case SNDRV_PCM_STREAM_PLAYBACK: + ret = gb_audio_gb_deactivate_tx(module->mgmt_connection, + cportid); + /* unregister cport */ + i2s_port = 0; /* fixed for now */ + cportid = data->connection->hd_cport_id; + ret = gb_audio_apbridgea_unregister_cport( + data->connection, i2s_port, cportid, + AUDIO_APBRIDGEA_DIRECTION_TX); + break; + } + dev_dbg(dai->dev, "Unregister %s:%d DAI, ret:%d\n", dai->name, + cportid, ret); + state = GBAUDIO_CODEC_SHUTDOWN; + module->ctrlstate[substream->stream] = state; + dev_dbg(dai->dev, "%s: state:%d\n", module->name, state); + mutex_unlock(&module->lock); + } + codec->stream[substream->stream].state = state; + codec->stream[substream->stream].dai_name = NULL; + mutex_unlock(&codec->lock); return; } @@ -142,19 +396,17 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream, uint8_t sig_bits, channels; uint32_t format, rate; uint16_t data_cport; - struct gbaudio_dai *gb_dai; - struct gbaudio_codec_info *gb = dev_get_drvdata(dai->dev); + struct gbaudio_module_info *module; + struct gbaudio_data_connection *data; + int state; + struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev); - if (!atomic_read(&gb->is_connected)) - return -ENODEV; + mutex_lock(&codec->lock); - /* find the dai */ - mutex_lock(&gb->lock); - gb_dai = gbaudio_find_dai(gb, -1, dai->name); - if (!gb_dai) { - dev_err(dai->dev, "%s: DAI not registered\n", dai->name); - ret = -EINVAL; - goto func_exit; + if (list_empty(&codec->module_list)) { + dev_err(codec->dev, "No codec module available\n"); + mutex_unlock(&codec->lock); + return -ENODEV; } /* @@ -164,54 +416,86 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream, if (params_channels(hwparams) != 2) { dev_err(dai->dev, "Invalid channel count:%d\n", params_channels(hwparams)); - ret = -EINVAL; - goto func_exit; + mutex_unlock(&codec->lock); + return -EINVAL; } channels = params_channels(hwparams); if (params_rate(hwparams) != 48000) { dev_err(dai->dev, "Invalid sampling rate:%d\n", params_rate(hwparams)); - ret = -EINVAL; - goto func_exit; + mutex_unlock(&codec->lock); + return -EINVAL; } rate = GB_AUDIO_PCM_RATE_48000; if (params_format(hwparams) != SNDRV_PCM_FORMAT_S16_LE) { dev_err(dai->dev, "Invalid format:%d\n", params_format(hwparams)); - ret = -EINVAL; - goto func_exit; + mutex_unlock(&codec->lock); + return -EINVAL; } format = GB_AUDIO_PCM_FMT_S16_LE; - data_cport = gb_dai->connection->intf_cport_id; - /* XXX check impact of sig_bit - * it should not change ideally - */ + state = codec->stream[substream->stream].state; + list_for_each_entry(module, &codec->module_list, list) { + mutex_lock(&module->lock); + if (!module->is_connected) { + dev_err(dai->dev, "%s:%s module not connected\n", + __func__, module->name); + ret = -ENODEV; + mutex_unlock(&module->lock); + continue; + } - dev_dbg(dai->dev, "cport:%d, rate:%d, channel %d, format %d, sig_bits:%d\n", - data_cport, rate, channels, format, sig_bits); - ret = gb_audio_gb_set_pcm(gb->mgmt_connection, data_cport, format, - rate, channels, sig_bits); - if (ret) { - dev_err(dai->dev, "%d: Error during set_pcm\n", ret); - goto func_exit; + /* find the data connection */ + data = find_data(module, dai->name); + if (!data) { + dev_err(dai->dev, "%s:%s DATA connection missing\n", + dai->name, module->name); + mutex_unlock(&module->lock); + continue; + } + + data_cport = data->connection->intf_cport_id; + /* XXX check impact of sig_bit + * it should not change ideally + */ + dev_dbg(dai->dev, + "cport:%d, rate:%d, channel %d, format %d, sig_bits:%d\n", + data_cport, rate, channels, format, sig_bits); + ret = gb_audio_gb_set_pcm(module->mgmt_connection, data_cport, + format, rate, channels, sig_bits); + if (ret) { + dev_err(dai->dev, "%d: Error during set_pcm\n", ret); + mutex_unlock(&module->lock); + goto func_exit; + } + if (state < GBAUDIO_CODEC_HWPARAMS) { + ret = gb_audio_apbridgea_set_config(data->connection, 0, + AUDIO_APBRIDGEA_PCM_FMT_16, + AUDIO_APBRIDGEA_PCM_RATE_48000, + 6144000); + if (ret) { + dev_err(dai->dev, + "%d: Error during set_config\n", ret); + mutex_unlock(&module->lock); + goto func_exit; + } + } + state = GBAUDIO_CODEC_HWPARAMS; + module->ctrlstate[substream->stream] = state; + dev_dbg(dai->dev, "%s: state:%d\n", module->name, state); + mutex_unlock(&module->lock); } + codec->stream[substream->stream].state = state; + codec->stream[substream->stream].format = format; + codec->stream[substream->stream].rate = rate; + codec->stream[substream->stream].channels = channels; + codec->stream[substream->stream].sig_bits = sig_bits; - /* - * XXX need to check if - * set config is always required - * check for mclk_freq as well - */ - ret = gb_audio_apbridgea_set_config(gb_dai->connection, 0, - AUDIO_APBRIDGEA_PCM_FMT_16, - AUDIO_APBRIDGEA_PCM_RATE_48000, - 6144000); - if (ret) - dev_err(dai->dev, "%d: Error during set_config\n", ret); func_exit: - mutex_unlock(&gb->lock); + mutex_unlock(&codec->lock); return ret; } @@ -220,76 +504,110 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream, { int ret; uint16_t data_cport; - struct gbaudio_dai *gb_dai; - struct gbaudio_codec_info *gb = dev_get_drvdata(dai->dev); + struct gbaudio_data_connection *data; + struct gbaudio_module_info *module; + int state; + struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev); - if (!atomic_read(&gb->is_connected)) - return -ENODEV; + mutex_lock(&codec->lock); - /* find the dai */ - mutex_lock(&gb->lock); - gb_dai = gbaudio_find_dai(gb, -1, dai->name); - if (!gb_dai) { - dev_err(dai->dev, "%s: DAI not registered\n", dai->name); - ret = -EINVAL; - goto func_exit; + if (list_empty(&codec->module_list)) { + dev_err(codec->dev, "No codec module available\n"); + mutex_unlock(&codec->lock); + return -ENODEV; } - /* deactivate rx/tx */ - data_cport = gb_dai->connection->intf_cport_id; + state = codec->stream[substream->stream].state; + list_for_each_entry(module, &codec->module_list, list) { + mutex_lock(&module->lock); + if (!module->is_connected) { + mutex_unlock(&module->lock); + continue; + } - switch (substream->stream) { - case SNDRV_PCM_STREAM_CAPTURE: - ret = gb_audio_gb_set_rx_data_size(gb->mgmt_connection, - data_cport, 192); - if (ret) { - dev_err(dai->dev, - "%d:Error during set_rx_data_size, cport:%d\n", - ret, data_cport); - goto func_exit; + /* find the dai */ + data = find_data(module, dai->name); + if (!data) { + dev_err(dai->dev, "%s:%s DATA connection missing\n", + dai->name, module->name); + mutex_unlock(&module->lock); + continue; } - ret = gb_audio_apbridgea_set_rx_data_size(gb_dai->connection, 0, - 192); - if (ret) { - dev_err(dai->dev, + /* deactivate rx/tx */ + data_cport = data->connection->intf_cport_id; + + switch (substream->stream) { + case SNDRV_PCM_STREAM_CAPTURE: + ret = gb_audio_gb_set_rx_data_size( + module->mgmt_connection, + data_cport, 192); + if (ret) { + dev_err(dai->dev, + "%d:Error during set_rx_data_size, cport:%d\n", + ret, data_cport); + mutex_unlock(&module->lock); + goto func_exit; + } + if (state < GBAUDIO_CODEC_PREPARE) { + ret = gb_audio_apbridgea_set_rx_data_size( + data->connection, 0, + 192); + if (ret) { + dev_err(dai->dev, "%d:Error during apbridgea_set_rx_data_size\n", ret); - goto func_exit; - } - ret = gb_audio_gb_activate_rx(gb->mgmt_connection, data_cport); - break; - case SNDRV_PCM_STREAM_PLAYBACK: - ret = gb_audio_gb_set_tx_data_size(gb->mgmt_connection, - data_cport, 192); - if (ret) { - dev_err(dai->dev, - "%d:Error during module set_tx_data_size, cport:%d\n", - ret, data_cport); - goto func_exit; - } - ret = gb_audio_apbridgea_set_tx_data_size(gb_dai->connection, 0, - 192); - if (ret) { - dev_err(dai->dev, - "%d:Error during apbridgea set_tx_data_size, cport\n", - ret); - goto func_exit; + mutex_unlock(&module->lock); + goto func_exit; + } + } + ret = gb_audio_gb_activate_rx(module->mgmt_connection, + data_cport); + if (ret) + dev_err(dai->dev, + "%s:Error during activate stream,%d\n", + module->name, ret); + break; + case SNDRV_PCM_STREAM_PLAYBACK: + ret = gb_audio_gb_set_tx_data_size( + module->mgmt_connection, + data_cport, 192); + if (ret) { + dev_err(dai->dev, + "%d:Error during module set_tx_data_size, cport:%d\n", + ret, data_cport); + mutex_unlock(&module->lock); + goto func_exit; + } + if (state < GBAUDIO_CODEC_PREPARE) { + ret = gb_audio_apbridgea_set_tx_data_size( + data->connection, 0, + 192); + if (ret) { + dev_err(dai->dev, + "%d:Error during apbridgea set_tx_data_size, cport\n", + ret); + mutex_unlock(&module->lock); + goto func_exit; + } + } + ret = gb_audio_gb_activate_tx(module->mgmt_connection, + data_cport); + if (ret) + dev_err(dai->dev, + "%s:Error during activate stream,%d\n", + module->name, ret); + break; } - ret = gb_audio_gb_activate_tx(gb->mgmt_connection, data_cport); - break; - default: - dev_err(dai->dev, "Invalid stream type %d during prepare\n", - substream->stream); - ret = -EINVAL; - goto func_exit; + state = GBAUDIO_CODEC_PREPARE; + module->ctrlstate[substream->stream] = state; + dev_dbg(dai->dev, "%s: state:%d\n", module->name, state); + mutex_unlock(&module->lock); } - - if (ret) - dev_err(dai->dev, "%d: Error during activate stream\n", ret); + codec->stream[substream->stream].state = state; func_exit: - mutex_unlock(&gb->lock); - return ret; + mutex_unlock(&codec->lock); + return 0; } static int gbcodec_trigger(struct snd_pcm_substream *substream, int cmd, @@ -297,24 +615,19 @@ static int gbcodec_trigger(struct snd_pcm_substream *substream, int cmd, { int ret; int tx, rx, start, stop; - struct gbaudio_dai *gb_dai; - struct gbaudio_codec_info *gb = dev_get_drvdata(dai->dev); - - if (!atomic_read(&gb->is_connected)) { + struct gbaudio_data_connection *data; + struct gbaudio_module_info *module; + struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev); + + mutex_lock(&codec->lock); + if (list_empty(&codec->module_list)) { + dev_err(codec->dev, "No codec module available\n"); + mutex_unlock(&codec->lock); if (cmd == SNDRV_PCM_TRIGGER_STOP) return 0; return -ENODEV; } - /* find the dai */ - mutex_lock(&gb->lock); - gb_dai = gbaudio_find_dai(gb, -1, dai->name); - if (!gb_dai) { - dev_err(dai->dev, "%s: DAI not registered\n", dai->name); - ret = -EINVAL; - goto func_exit; - } - tx = rx = start = stop = 0; switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -345,47 +658,60 @@ static int gbcodec_trigger(struct snd_pcm_substream *substream, int cmd, goto func_exit; } + list_for_each_entry(module, &codec->module_list, list) { + mutex_lock(&module->lock); + if (!module->is_connected) { + mutex_unlock(&module->lock); + continue; + } + + /* find the dai */ + data = find_data(module, dai->name); + if (data) + break; + } + if (!data) { + dev_err(dai->dev, "%s:%s DATA connection missing\n", + dai->name, module->name); + ret = -ENODEV; + mutex_unlock(&module->lock); + goto func_exit; + } if (start && tx) { - ret = gb_audio_apbridgea_prepare_tx(gb_dai->connection, 0); + ret = gb_audio_apbridgea_prepare_tx(data->connection, + 0); if (!ret) - ret = gb_audio_apbridgea_start_tx(gb_dai->connection, 0, - 0); - } - - else if (start && rx) { - ret = gb_audio_apbridgea_prepare_rx(gb_dai->connection, 0); + ret = gb_audio_apbridgea_start_tx(data->connection, + 0, 0); + codec->stream[substream->stream].state = GBAUDIO_CODEC_START; + } else if (start && rx) { + ret = gb_audio_apbridgea_prepare_rx(data->connection, + 0); if (!ret) - ret = gb_audio_apbridgea_start_rx(gb_dai->connection, + ret = gb_audio_apbridgea_start_rx(data->connection, 0); - } - - else if (stop && tx) { - ret = gb_audio_apbridgea_stop_tx(gb_dai->connection, 0); + codec->stream[substream->stream].state = GBAUDIO_CODEC_START; + } else if (stop && tx) { + ret = gb_audio_apbridgea_stop_tx(data->connection, 0); if (!ret) - ret = gb_audio_apbridgea_shutdown_tx(gb_dai->connection, + ret = gb_audio_apbridgea_shutdown_tx(data->connection, 0); - } - - else if (stop && rx) { - ret = gb_audio_apbridgea_stop_rx(gb_dai->connection, 0); + codec->stream[substream->stream].state = GBAUDIO_CODEC_STOP; + } else if (stop && rx) { + ret = gb_audio_apbridgea_stop_rx(data->connection, 0); if (!ret) - ret = gb_audio_apbridgea_shutdown_rx(gb_dai->connection, + ret = gb_audio_apbridgea_shutdown_rx(data->connection, 0); - } - - else + codec->stream[substream->stream].state = GBAUDIO_CODEC_STOP; + } else ret = -EINVAL; - if (ret) - dev_err(dai->dev, "%d:Error during %s stream\n", ret, - start ? "Start" : "Stop"); - - /* in case device removed, return 0 for stop trigger */ - if (stop && (ret == -ENODEV)) - ret = 0; + dev_err(dai->dev, "%s:Error during %s stream:%d\n", + module->name, start ? "Start" : "Stop", ret); + mutex_unlock(&module->lock); func_exit: - mutex_unlock(&gb->lock); + mutex_unlock(&codec->lock); return ret; } @@ -409,476 +735,325 @@ static struct snd_soc_dai_ops gbcodec_dai_ops = { .digital_mute = gbcodec_digital_mute, }; -/* - * codec driver ops - */ -static int gbcodec_probe(struct snd_soc_codec *codec) +int gbaudio_register_module(struct gbaudio_module_info *module) { - /* Empty function for now */ - return 0; -} + int ret; + struct snd_soc_codec *codec; -static int gbcodec_remove(struct snd_soc_codec *codec) -{ - /* Empty function for now */ - return 0; -} + if (!gbcodec) { + dev_err(module->dev, "GB Codec not yet probed\n"); + return -EAGAIN; + } -static int gbcodec_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - int ret = 0; - struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec); - u8 *gbcodec_reg = gbcodec->reg; + codec = gbcodec->codec; + mutex_lock(&gbcodec->lock); - if (reg == SND_SOC_NOPM) - return 0; + if (module->num_dais) { + dev_err(gbcodec->dev, + "%d:DAIs not supported via gbcodec driver\n", + module->num_dais); + mutex_unlock(&gbcodec->lock); + return -EINVAL; + } - if (reg >= GBCODEC_REG_COUNT) - return 0; + if (module->dapm_widgets) + snd_soc_dapm_new_controls(&codec->dapm, module->dapm_widgets, + module->num_dapm_widgets); + if (module->controls) + snd_soc_add_codec_controls(codec, module->controls, + module->num_controls); + if (module->dapm_routes) + snd_soc_dapm_add_routes(&codec->dapm, module->dapm_routes, + module->num_dapm_routes); + + /* card already instantiated, create widgets here only */ + if (codec->card->instantiated) { + ret = snd_soc_dapm_new_widgets(&codec->dapm); + if (!ret) + snd_soc_dapm_link_dai_widgets_component(codec->card, + &codec->dapm); + } - gbcodec_reg[reg] = value; - dev_dbg(codec->dev, "reg[%d] = 0x%x\n", reg, value); + list_add(&module->list, &gbcodec->module_list); + dev_dbg(codec->dev, "Registered %s module\n", module->name); - return ret; + mutex_unlock(&gbcodec->lock); + return 0; } +EXPORT_SYMBOL(gbaudio_register_module); -static unsigned int gbcodec_read(struct snd_soc_codec *codec, - unsigned int reg) +void gbaudio_codec_cleanup(struct gbaudio_module_info *module) { - unsigned int val = 0; - - struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec); - u8 *gbcodec_reg = gbcodec->reg; - - if (reg == SND_SOC_NOPM) - return 0; - - if (reg >= GBCODEC_REG_COUNT) - return 0; - - val = gbcodec_reg[reg]; - dev_dbg(codec->dev, "reg[%d] = 0x%x\n", reg, val); - - return val; -} + struct gbaudio_data_connection *data; + int pb_state = gbcodec->stream[0].state; + int cap_state = gbcodec->stream[1].state; + int ret; + uint16_t i2s_port, cportid; -/* - * gb_snd management functions - */ + /* locks already acquired */ + if (!pb_state && !cap_state) + return; -/* XXX - * since BE DAI path is not yet properly closed from above layer, - * dsp dai.mi2s_dai_data.status_mask is still set to STATUS_PORT_STARTED - * this causes immediate playback/capture to fail in case relevant mixer - * control is not turned OFF - * user need to try once again after failure to recover DSP state. - */ -static void gb_audio_cleanup(struct gbaudio_codec_info *gb) -{ - int cportid, ret, timeout_result; - struct gbaudio_dai *gb_dai; - struct gb_connection *connection; - long timeout = msecs_to_jiffies(50); /* 50ms */ - struct device *dev = gb->dev; - - list_for_each_entry(gb_dai, &gb->dai_list, list) { - /* - * In case of BE dailink, need to deactivate APBridge - * manually - */ - if (atomic_read(&gb_dai->users)) { - /* schedule a wait event */ - timeout_result = - wait_event_interruptible_timeout( - gb_dai->wait_queue, - !atomic_read(&gb_dai->users), - timeout); - if (!timeout_result) - dev_warn(dev, "%s:DAI still in use.\n", - gb_dai->name); - - connection = gb_dai->connection; - /* PB active */ - ret = gb_audio_apbridgea_stop_tx(connection, 0); - if (ret) - dev_info(dev, "%d:Failed during APBridge stop_tx\n", - ret); - ret = gb_audio_apbridgea_shutdown_tx(connection, 0); - if (ret) - dev_info(dev, "%d:Failed during APBridge shutdown_tx\n", - ret); - cportid = connection->intf_cport_id; - ret = gb_audio_gb_deactivate_tx(gb->mgmt_connection, - cportid); - if (ret) - dev_info(dev, - "%d:Failed during deactivate_tx\n", - ret); - cportid = connection->hd_cport_id; - ret = gb_audio_apbridgea_unregister_cport(connection, 0, - cportid, + if (pb_state == GBAUDIO_CODEC_START) { + /* cleanup PB path, only APBridge specific */ + data = find_data(module, gbcodec->stream[0].dai_name); + if (!data) { + dev_err(gbcodec->dev, "%s: Missing data pointer\n", + __func__); + return; + } + ret = gb_audio_apbridgea_stop_tx(data->connection, 0); + if (ret) + return; + ret = gb_audio_apbridgea_shutdown_tx(data->connection, 0); + if (ret) + return; + i2s_port = 0; /* fixed for now */ + cportid = data->connection->hd_cport_id; + ret = gb_audio_apbridgea_unregister_cport(data->connection, + i2s_port, cportid, AUDIO_APBRIDGEA_DIRECTION_TX); - if (ret) - dev_info(dev, "%d:Failed during unregister cport\n", - ret); + gbcodec->stream[0].state = GBAUDIO_CODEC_SHUTDOWN; + } + + if (cap_state == GBAUDIO_CODEC_START) { + /* cleanup CAP path, only APBridge specific */ + data = find_data(module, gbcodec->stream[1].dai_name); + if (!data) { + dev_err(gbcodec->dev, "%s: Missing data pointer\n", + __func__); + return; } + ret = gb_audio_apbridgea_stop_rx(data->connection, 0); + if (ret) + return; + ret = gb_audio_apbridgea_shutdown_rx(data->connection, 0); + if (ret) + return; + i2s_port = 0; /* fixed for now */ + cportid = data->connection->hd_cport_id; + ret = gb_audio_apbridgea_unregister_cport(data->connection, + i2s_port, cportid, + AUDIO_APBRIDGEA_DIRECTION_RX); + gbcodec->stream[1].state = GBAUDIO_CODEC_SHUTDOWN; } } -static int gbaudio_register_codec(struct gbaudio_codec_info *gbcodec) +void gbaudio_unregister_module(struct gbaudio_module_info *module) { - int ret, i; - struct device *dev = gbcodec->dev; - struct gb_connection *connection = gbcodec->mgmt_connection; - struct snd_soc_codec_driver *soc_codec_dev_gbcodec; - /* - * FIXME: malloc for topology happens via audio_gb driver - * should be done within codec driver itself - */ - struct gb_audio_topology *topology; + struct snd_soc_codec *codec = gbcodec->codec; + struct snd_card *card = codec->card->snd_card; - soc_codec_dev_gbcodec = devm_kzalloc(gbcodec->dev, - sizeof(*soc_codec_dev_gbcodec), - GFP_KERNEL); - if (!soc_codec_dev_gbcodec) { - dev_err(gbcodec->dev, "Malloc failed for codec_driver\n"); - return -ENOMEM; - } + dev_dbg(codec->dev, "Unregister %s module\n", module->name); - ret = gb_connection_enable(connection); - if (ret) { - dev_err(dev, "%d: Error while enabling mgmt connection\n", ret); - return ret; - } + /* complete widget processing, if ongoing */ + snd_soc_dapm_sync(&codec->dapm); - gbcodec->dev_id = connection->intf->interface_id; - /* fetch topology data */ - ret = gb_audio_gb_get_topology(connection, &topology); - if (ret) { - dev_err(dev, "%d:Error while fetching topology\n", ret); - goto tplg_fetch_err; - } + down_write(&card->controls_rwsem); + mutex_lock(&gbcodec->lock); + dev_dbg(codec->dev, "Process Unregister %s module\n", module->name); + mutex_lock(&module->lock); - /* process topology data */ - ret = gbaudio_tplg_parse_data(gbcodec, topology); - if (ret) { - dev_err(dev, "%d:Error while parsing topology data\n", - ret); - goto tplg_parse_err; + if (list_is_last(&module->list, &gbcodec->module_list)) { + dev_dbg(codec->dev, "Last module removed, cleanup APBridge\n"); + gbaudio_codec_cleanup(module); } - gbcodec->topology = topology; - - /* update codec info */ - soc_codec_dev_gbcodec->probe = gbcodec_probe, - soc_codec_dev_gbcodec->remove = gbcodec_remove, - - soc_codec_dev_gbcodec->read = gbcodec_read, - soc_codec_dev_gbcodec->write = gbcodec_write, - - soc_codec_dev_gbcodec->reg_cache_size = GBCODEC_REG_COUNT, - soc_codec_dev_gbcodec->reg_cache_default = gbcodec_reg_defaults, - soc_codec_dev_gbcodec->reg_word_size = 1, - soc_codec_dev_gbcodec->idle_bias_off = true, - soc_codec_dev_gbcodec->ignore_pmdown_time = 1, - - soc_codec_dev_gbcodec->controls = gbcodec->kctls; - soc_codec_dev_gbcodec->num_controls = gbcodec->num_kcontrols; - soc_codec_dev_gbcodec->dapm_widgets = gbcodec->widgets; - soc_codec_dev_gbcodec->num_dapm_widgets = gbcodec->num_dapm_widgets; - soc_codec_dev_gbcodec->dapm_routes = gbcodec->routes; - soc_codec_dev_gbcodec->num_dapm_routes = gbcodec->num_dapm_routes; - - /* update DAI info */ - for (i = 0; i < gbcodec->num_dais; i++) - gbcodec->dais[i].ops = &gbcodec_dai_ops; - - /* register codec */ - ret = snd_soc_register_codec(dev, soc_codec_dev_gbcodec, - gbcodec->dais, 1); - if (ret) { - dev_err(dev, "%d:Failed to register codec\n", ret); - goto codec_reg_err; + module->is_connected = 0; + if (module->dapm_routes) { + dev_dbg(codec->dev, "Removing %d routes\n", + module->num_dapm_routes); + snd_soc_dapm_del_routes(&codec->dapm, module->dapm_routes, + module->num_dapm_routes); } - - /* update DAI links in response to this codec */ - ret = msm8994_add_dailink("msm8994-tomtom-mtp-snd-card", gbcodec->name, - gbcodec->dais[0].name, 1); - if (ret) { - dev_err(dev, "%d: Failed to add DAI links\n", ret); - goto add_dailink_err; + if (module->controls) { + dev_dbg(codec->dev, "Removing %d controls\n", + module->num_controls); + soc_remove_codec_controls(codec, module->controls, + module->num_controls); + } + if (module->dapm_widgets) { + dev_dbg(codec->dev, "Removing %d widgets\n", + module->num_dapm_widgets); + snd_soc_dapm_free_controls(&codec->dapm, module->dapm_widgets, + module->num_dapm_widgets); } - gbcodec->num_dai_links = 1; - return 0; + mutex_unlock(&module->lock); -add_dailink_err: - snd_soc_unregister_codec(dev); -codec_reg_err: - gbaudio_tplg_release(gbcodec); - gbcodec->topology = NULL; -tplg_parse_err: - kfree(topology); -tplg_fetch_err: - gb_connection_disable(gbcodec->mgmt_connection); - return ret; -} + list_del(&module->list); + dev_dbg(codec->dev, "Unregistered %s module\n", module->name); -static void gbaudio_unregister_codec(struct gbaudio_codec_info *gbcodec) -{ - gb_audio_cleanup(gbcodec); - msm8994_remove_dailink("msm8994-tomtom-mtp-snd-card", gbcodec->name, - gbcodec->dais[0].name, 1); - snd_soc_unregister_codec(gbcodec->dev); - gbaudio_tplg_release(gbcodec); - kfree(gbcodec->topology); - gb_connection_disable(gbcodec->mgmt_connection); + mutex_unlock(&gbcodec->lock); + up_write(&card->controls_rwsem); } +EXPORT_SYMBOL(gbaudio_unregister_module); -static int gbaudio_codec_request_handler(struct gb_operation *op) +/* + * codec driver ops + */ +static int gbcodec_probe(struct snd_soc_codec *codec) { - struct gb_connection *connection = op->connection; - struct gb_audio_streaming_event_request *req = op->request->payload; + struct gbaudio_codec_info *info; + + info = devm_kzalloc(codec->dev, sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; - dev_warn(&connection->bundle->dev, - "Audio Event received: cport: %u, event: %u\n", - req->data_cport, req->event); + info->dev = codec->dev; + INIT_LIST_HEAD(&info->module_list); + mutex_init(&info->lock); + info->codec = codec; + snd_soc_codec_set_drvdata(codec, info); + gbcodec = info; + /* Empty function for now */ return 0; } -static int gbaudio_dai_request_handler(struct gb_operation *op) +static int gbcodec_remove(struct snd_soc_codec *codec) { - struct gb_connection *connection = op->connection; - - dev_warn(&connection->bundle->dev, "Audio Event received\n"); - + /* Empty function for now */ return 0; } -static int gb_audio_add_mgmt_connection(struct gbaudio_codec_info *gbcodec, - struct greybus_descriptor_cport *cport_desc, - struct gb_bundle *bundle) +static u8 gbcodec_reg[GBCODEC_REG_COUNT] = { + [GBCODEC_CTL_REG] = GBCODEC_CTL_REG_DEFAULT, + [GBCODEC_MUTE_REG] = GBCODEC_MUTE_REG_DEFAULT, + [GBCODEC_PB_LVOL_REG] = GBCODEC_PB_VOL_REG_DEFAULT, + [GBCODEC_PB_RVOL_REG] = GBCODEC_PB_VOL_REG_DEFAULT, + [GBCODEC_CAP_LVOL_REG] = GBCODEC_CAP_VOL_REG_DEFAULT, + [GBCODEC_CAP_RVOL_REG] = GBCODEC_CAP_VOL_REG_DEFAULT, + [GBCODEC_APB1_MUX_REG] = GBCODEC_APB1_MUX_REG_DEFAULT, + [GBCODEC_APB2_MUX_REG] = GBCODEC_APB2_MUX_REG_DEFAULT, +}; + +static int gbcodec_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value) { - struct gb_connection *connection; + int ret = 0; - /* Management Cport */ - if (gbcodec->mgmt_connection) { - dev_err(&bundle->dev, - "Can't have multiple Management connections\n"); - return -ENODEV; - } + if (reg == SND_SOC_NOPM) + return 0; - connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id), - gbaudio_codec_request_handler); - if (IS_ERR(connection)) - return PTR_ERR(connection); + BUG_ON(reg >= GBCODEC_REG_COUNT); + return 0; - gb_connection_set_data(connection, gbcodec); - gbcodec->mgmt_connection = connection; + gbcodec_reg[reg] = value; + dev_dbg(codec->dev, "reg[%d] = 0x%x\n", reg, value); - return 0; + return ret; } -static int gb_audio_add_data_connection(struct gbaudio_codec_info *gbcodec, - struct greybus_descriptor_cport *cport_desc, - struct gb_bundle *bundle) +static unsigned int gbcodec_read(struct snd_soc_codec *codec, + unsigned int reg) { - struct gb_connection *connection; - struct gbaudio_dai *dai; + unsigned int val = 0; - dai = devm_kzalloc(gbcodec->dev, sizeof(*dai), GFP_KERNEL); - if (!dai) { - dev_err(gbcodec->dev, "DAI Malloc failure\n"); - return -ENOMEM; - } + if (reg == SND_SOC_NOPM) + return 0; - connection = gb_connection_create_flags(bundle, - le16_to_cpu(cport_desc->id), - gbaudio_dai_request_handler, - GB_CONNECTION_FLAG_CSD); - if (IS_ERR(connection)) { - devm_kfree(gbcodec->dev, dai); - return PTR_ERR(connection); - } + BUG_ON(reg >= GBCODEC_REG_COUNT); - gb_connection_set_data(connection, gbcodec); - atomic_set(&dai->users, 0); - init_waitqueue_head(&dai->wait_queue); - dai->data_cport = connection->intf_cport_id; - dai->connection = connection; - list_add(&dai->list, &gbcodec->dai_list); + val = gbcodec_reg[reg]; + dev_dbg(codec->dev, "reg[%d] = 0x%x\n", reg, val); - return 0; + return val; } -/* - * This is the basic hook get things initialized and registered w/ gb - */ -static int gb_audio_probe(struct gb_bundle *bundle, - const struct greybus_bundle_id *id) -{ - struct device *dev = &bundle->dev; - struct gbaudio_codec_info *gbcodec; - struct greybus_descriptor_cport *cport_desc; - struct gb_audio_manager_module_descriptor desc; - struct gbaudio_dai *dai, *_dai; - int ret, i; - - /* There should be at least one Management and one Data cport */ - if (bundle->num_cports < 2) - return -ENODEV; +static struct snd_soc_dai_driver gbaudio_dai[] = { + { + .name = "greybus-apb1", + .id = 0, + .playback = { + .stream_name = "GB Audio Playback", + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FORMAT_S16_LE, + .rate_max = 48000, + .rate_min = 48000, + .channels_min = 1, + .channels_max = 2, + }, + .capture = { + .stream_name = "GB Audio Capture", + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FORMAT_S16_LE, + .rate_max = 48000, + .rate_min = 48000, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &gbcodec_dai_ops, + }, +}; - mutex_lock(&gb_codec_list_lock); - /* - * There can be only one Management connection and any number of data - * connections. - */ - gbcodec = devm_kzalloc(dev, sizeof(*gbcodec), GFP_KERNEL); - if (!gbcodec) { - mutex_unlock(&gb_codec_list_lock); - return -ENOMEM; - } +static struct snd_soc_codec_driver soc_codec_dev_gbaudio = { + .probe = gbcodec_probe, + .remove = gbcodec_remove, - gbcodec->num_data_connections = bundle->num_cports - 1; - mutex_init(&gbcodec->lock); - INIT_LIST_HEAD(&gbcodec->dai_list); - INIT_LIST_HEAD(&gbcodec->widget_list); - INIT_LIST_HEAD(&gbcodec->codec_ctl_list); - INIT_LIST_HEAD(&gbcodec->widget_ctl_list); - gbcodec->dev = dev; - snprintf(gbcodec->name, NAME_SIZE, "%s.%s", dev->driver->name, - dev_name(dev)); - greybus_set_drvdata(bundle, gbcodec); - - /* Create all connections */ - for (i = 0; i < bundle->num_cports; i++) { - cport_desc = &bundle->cport_desc[i]; - - switch (cport_desc->protocol_id) { - case GREYBUS_PROTOCOL_AUDIO_MGMT: - ret = gb_audio_add_mgmt_connection(gbcodec, cport_desc, - bundle); - if (ret) - goto destroy_connections; - break; - case GREYBUS_PROTOCOL_AUDIO_DATA: - ret = gb_audio_add_data_connection(gbcodec, cport_desc, - bundle); - if (ret) - goto destroy_connections; - break; - default: - dev_err(dev, "Unsupported protocol: 0x%02x\n", - cport_desc->protocol_id); - ret = -ENODEV; - goto destroy_connections; - } - } + .read = gbcodec_read, + .write = gbcodec_write, - /* There must be a management cport */ - if (!gbcodec->mgmt_connection) { - ret = -EINVAL; - dev_err(dev, "Missing management connection\n"); - goto destroy_connections; - } + .reg_cache_size = GBCODEC_REG_COUNT, + .reg_cache_default = gbcodec_reg_defaults, + .reg_word_size = 1, - /* Initialize management connection */ - ret = gbaudio_register_codec(gbcodec); - if (ret) - goto destroy_connections; - - /* Initialize data connections */ - list_for_each_entry(dai, &gbcodec->dai_list, list) { - ret = gb_connection_enable(dai->connection); - if (ret) - goto remove_dai; - } - - /* inform above layer for uevent */ - dev_dbg(dev, "Inform set_event:%d to above layer\n", 1); - /* prepare for the audio manager */ - strlcpy(desc.name, gbcodec->name, GB_AUDIO_MANAGER_MODULE_NAME_LEN); - desc.slot = 1; /* todo */ - desc.vid = 2; /* todo */ - desc.pid = 3; /* todo */ - desc.cport = gbcodec->dev_id; - desc.devices = 0x2; /* todo */ - gbcodec->manager_id = gb_audio_manager_add(&desc); + .idle_bias_off = true, + .ignore_pmdown_time = 1, +}; - atomic_set(&gbcodec->is_connected, 1); - list_add_tail(&gbcodec->list, &gb_codec_list); - dev_dbg(dev, "Add GB Audio device:%s\n", gbcodec->name); - mutex_unlock(&gb_codec_list_lock); +#ifdef CONFIG_PM +static int gbaudio_codec_suspend(struct device *dev) +{ + dev_dbg(dev, "%s: suspend\n", __func__); return 0; - -remove_dai: - list_for_each_entry_safe(dai, _dai, &gbcodec->dai_list, list) - gb_connection_disable(dai->connection); - - gbaudio_unregister_codec(gbcodec); -destroy_connections: - list_for_each_entry_safe(dai, _dai, &gbcodec->dai_list, list) { - gb_connection_destroy(dai->connection); - list_del(&dai->list); - devm_kfree(dev, dai); - } - - if (gbcodec->mgmt_connection) - gb_connection_destroy(gbcodec->mgmt_connection); - - devm_kfree(dev, gbcodec); - mutex_unlock(&gb_codec_list_lock); - - return ret; } -static void gb_audio_disconnect(struct gb_bundle *bundle) +static int gbaudio_codec_resume(struct device *dev) { - struct gbaudio_codec_info *gbcodec = greybus_get_drvdata(bundle); - struct gbaudio_dai *dai, *_dai; + dev_dbg(dev, "%s: resume\n", __func__); + return 0; +} - mutex_lock(&gb_codec_list_lock); - atomic_set(&gbcodec->is_connected, 0); - /* inform uevent to above layers */ - gb_audio_manager_remove(gbcodec->manager_id); +static const struct dev_pm_ops gbaudio_codec_pm_ops = { + .suspend = gbaudio_codec_suspend, + .resume = gbaudio_codec_resume, +}; +#endif - mutex_lock(&gbcodec->lock); - list_for_each_entry_safe(dai, _dai, &gbcodec->dai_list, list) - gb_connection_disable(dai->connection); - gbaudio_unregister_codec(gbcodec); - - list_for_each_entry_safe(dai, _dai, &gbcodec->dai_list, list) { - gb_connection_destroy(dai->connection); - list_del(&dai->list); - devm_kfree(gbcodec->dev, dai); - } - gb_connection_destroy(gbcodec->mgmt_connection); - gbcodec->mgmt_connection = NULL; - list_del(&gbcodec->list); - mutex_unlock(&gbcodec->lock); +static int gbaudio_codec_probe(struct platform_device *pdev) +{ + return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_gbaudio, + gbaudio_dai, ARRAY_SIZE(gbaudio_dai)); +} - devm_kfree(&bundle->dev, gbcodec); - mutex_unlock(&gb_codec_list_lock); +static int gbaudio_codec_remove(struct platform_device *pdev) +{ + snd_soc_unregister_codec(&pdev->dev); + return 0; } -static const struct greybus_bundle_id gb_audio_id_table[] = { - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_AUDIO) }, - { } +static const struct of_device_id greybus_asoc_machine_of_match[] = { + { .compatible = "qcom,ara-codec", }, + {}, }; -MODULE_DEVICE_TABLE(greybus, gb_audio_id_table); -static struct greybus_driver gb_audio_driver = { - .name = "gb-audio", - .probe = gb_audio_probe, - .disconnect = gb_audio_disconnect, - .id_table = gb_audio_id_table, +static struct platform_driver gbaudio_codec_driver = { + .driver = { + .name = "gb-codec", + .owner = THIS_MODULE, +#ifdef CONFIG_PM + .pm = &gbaudio_codec_pm_ops, +#endif + .of_match_table = greybus_asoc_machine_of_match, + }, + .probe = gbaudio_codec_probe, + .remove = gbaudio_codec_remove, }; -module_greybus_driver(gb_audio_driver); +module_platform_driver(gbaudio_codec_driver); -MODULE_DESCRIPTION("Greybus Audio codec driver"); +MODULE_DESCRIPTION("Greybus codec driver"); MODULE_AUTHOR("Vaibhav Agarwal "); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:gbaudio-codec"); diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index 9197adc..a2697dd 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -68,6 +68,31 @@ static const u8 gbcodec_reg_defaults[GBCODEC_REG_COUNT] = { GBCODEC_APB2_MUX_REG_DEFAULT, }; +enum gbaudio_codec_state { + GBAUDIO_CODEC_SHUTDOWN = 0, + GBAUDIO_CODEC_STARTUP, + GBAUDIO_CODEC_HWPARAMS, + GBAUDIO_CODEC_PREPARE, + GBAUDIO_CODEC_START, + GBAUDIO_CODEC_STOP, +}; + +struct gbaudio_stream { + const char *dai_name; + int state; + uint8_t sig_bits, channels; + uint32_t format, rate; +}; + +struct gbaudio_codec_info { + struct device *dev; + struct snd_soc_codec *codec; + struct list_head module_list; + struct gbaudio_stream stream[2]; /* PB/CAP */ + struct mutex lock; + u8 reg[GBCODEC_REG_COUNT]; +}; + struct gbaudio_widget { __u8 id; const char *name; @@ -81,81 +106,80 @@ struct gbaudio_control { struct list_head list; }; -struct gbaudio_dai { +struct gbaudio_data_connection { __le16 data_cport; + int cport_configured; char name[NAME_SIZE]; - /* DAI users */ - atomic_t users; struct gb_connection *connection; struct list_head list; - wait_queue_head_t wait_queue; }; -struct gbaudio_codec_info { +/* stream direction */ +#define GB_PLAYBACK BIT(0) +#define GB_CAPTURE BIT(1) + +enum gbaudio_module_state { + GBAUDIO_MODULE_OFF = 0, + GBAUDIO_MODULE_ON, +}; + +struct gbaudio_module_info { /* module info */ + struct device *dev; int dev_id; /* check if it should be bundle_id/hd_cport_id */ int vid; int pid; int slot; int type; - int dai_added; - int codec_registered; int set_uevent; char vstr[NAME_SIZE]; char pstr[NAME_SIZE]; struct list_head list; - struct gb_audio_topology *topology; /* need to share this info to above user space */ int manager_id; char name[NAME_SIZE]; - /* - * there can be a rece condition between gb_audio_disconnect() - * and dai->trigger from above ASoC layer. - * To avoid any deadlock over codec_info->lock, atomic variable - * is used. - */ - atomic_t is_connected; + /* used by codec_ops */ struct mutex lock; + int is_connected; + int ctrlstate[2]; /* PB/CAP */ - /* soc related data */ - struct snd_soc_codec *codec; - struct device *dev; - u8 reg[GBCODEC_REG_COUNT]; - - /* dai_link related */ - char card_name[NAME_SIZE]; - char *dailink_name[MAX_DAIS]; - int num_dai_links; - + /* connection info */ struct gb_connection *mgmt_connection; size_t num_data_connections; + struct list_head data_list; + /* topology related */ int num_dais; - int num_kcontrols; + int num_controls; int num_dapm_widgets; int num_dapm_routes; unsigned long dai_offset; unsigned long widget_offset; unsigned long control_offset; unsigned long route_offset; - struct snd_kcontrol_new *kctls; - struct snd_soc_dapm_widget *widgets; - struct snd_soc_dapm_route *routes; + struct snd_kcontrol_new *controls; + struct snd_soc_dapm_widget *dapm_widgets; + struct snd_soc_dapm_route *dapm_routes; struct snd_soc_dai_driver *dais; - /* lists */ - struct list_head dai_list; struct list_head widget_list; - struct list_head codec_ctl_list; + struct list_head ctl_list; struct list_head widget_ctl_list; + + struct gb_audio_topology *topology; }; -struct gbaudio_dai *gbaudio_find_dai(struct gbaudio_codec_info *gbcodec, - int data_cport, const char *name); -int gbaudio_tplg_parse_data(struct gbaudio_codec_info *gbcodec, +int gbaudio_tplg_parse_data(struct gbaudio_module_info *module, struct gb_audio_topology *tplg_data); -void gbaudio_tplg_release(struct gbaudio_codec_info *gbcodec); +void gbaudio_tplg_release(struct gbaudio_module_info *module); + +int gbaudio_module_update(struct gbaudio_codec_info *codec, + const char *w_name, + struct gbaudio_module_info *module, + int enable); +int gbaudio_register_module(struct gbaudio_module_info *module); +void gbaudio_unregister_module(struct gbaudio_module_info *module); /* protocol related */ extern int gb_audio_gb_get_topology(struct gb_connection *connection, diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index 1651c14..4901348 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -25,7 +25,32 @@ struct gbaudio_ctl_pvt { struct gb_audio_ctl_elem_info *info; }; -static const char *gbaudio_map_controlid(struct gbaudio_codec_info *gbcodec, +static struct gbaudio_module_info *find_gb_module( + struct gbaudio_codec_info *codec, + char const *name) +{ + int dev_id, ret; + char begin[NAME_SIZE]; + struct gbaudio_module_info *module; + + if (!name) + return NULL; + + ret = sscanf(name, "%s %d", begin, &dev_id); + dev_dbg(codec->dev, "%s:Find module#%d\n", __func__, dev_id); + + mutex_lock(&codec->lock); + list_for_each_entry(module, &codec->module_list, list) { + if (module->dev_id == dev_id) { + mutex_unlock(&codec->lock); + return module; + } + } + mutex_unlock(&codec->lock); + return NULL; +} + +static const char *gbaudio_map_controlid(struct gbaudio_module_info *module, __u8 control_id, __u8 index) { struct gbaudio_control *control; @@ -33,14 +58,14 @@ static const char *gbaudio_map_controlid(struct gbaudio_codec_info *gbcodec, if (control_id == GBAUDIO_INVALID_ID) return NULL; - list_for_each_entry(control, &gbcodec->codec_ctl_list, list) { + list_for_each_entry(control, &module->ctl_list, list) { if (control->id == control_id) { if (index == GBAUDIO_INVALID_ID) return control->name; return control->texts[index]; } } - list_for_each_entry(control, &gbcodec->widget_ctl_list, list) { + list_for_each_entry(control, &module->widget_ctl_list, list) { if (control->id == control_id) { if (index == GBAUDIO_INVALID_ID) return control->name; @@ -50,34 +75,23 @@ static const char *gbaudio_map_controlid(struct gbaudio_codec_info *gbcodec, return NULL; } -static int gbaudio_map_widgetname(struct gbaudio_codec_info *gbcodec, +static int gbaudio_map_widgetname(struct gbaudio_module_info *module, const char *name) { struct gbaudio_widget *widget; - char widget_name[NAME_SIZE]; - char prefix_name[NAME_SIZE]; - - snprintf(prefix_name, NAME_SIZE, "GB %d ", gbcodec->dev_id); - if (strncmp(name, prefix_name, strlen(prefix_name))) - return -EINVAL; - - strlcpy(widget_name, name+strlen(prefix_name), NAME_SIZE); - dev_dbg(gbcodec->dev, "widget_name:%s, truncated widget_name:%s\n", - name, widget_name); - - list_for_each_entry(widget, &gbcodec->widget_list, list) { - if (!strncmp(widget->name, widget_name, NAME_SIZE)) + list_for_each_entry(widget, &module->widget_list, list) { + if (!strncmp(widget->name, name, NAME_SIZE)) return widget->id; } return -EINVAL; } -static const char *gbaudio_map_widgetid(struct gbaudio_codec_info *gbcodec, +static const char *gbaudio_map_widgetid(struct gbaudio_module_info *module, __u8 widget_id) { struct gbaudio_widget *widget; - list_for_each_entry(widget, &gbcodec->widget_list, list) { + list_for_each_entry(widget, &module->widget_list, list) { if (widget->id == widget_id) return widget->name; } @@ -91,14 +105,16 @@ static int gbcodec_mixer_ctl_info(struct snd_kcontrol *kcontrol, const char *name; struct gbaudio_ctl_pvt *data; struct gb_audio_ctl_elem_info *info; + struct gbaudio_module_info *module; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec); + dev_dbg(codec->dev, "Entered %s:%s\n", __func__, kcontrol->id.name); data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; info = (struct gb_audio_ctl_elem_info *)data->info; if (!info) { - dev_err(gbcodec->dev, "NULL info for %s\n", uinfo->id.name); + dev_err(module->dev, "NULL info for %s\n", uinfo->id.name); return -EINVAL; } @@ -118,7 +134,10 @@ static int gbcodec_mixer_ctl_info(struct snd_kcontrol *kcontrol, uinfo->value.enumerated.items = max; if (uinfo->value.enumerated.item > max - 1) uinfo->value.enumerated.item = max - 1; - name = gbaudio_map_controlid(gbcodec, data->ctl_id, + module = find_gb_module(gbcodec, kcontrol->id.name); + if (!module) + return -EINVAL; + name = gbaudio_map_controlid(module, data->ctl_id, uinfo->value.enumerated.item); strlcpy(uinfo->value.enumerated.name, name, NAME_SIZE); break; @@ -137,16 +156,19 @@ static int gbcodec_mixer_ctl_get(struct snd_kcontrol *kcontrol, struct gb_audio_ctl_elem_info *info; struct gbaudio_ctl_pvt *data; struct gb_audio_ctl_elem_value gbvalue; + struct gbaudio_module_info *module; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); - if (!atomic_read(&gb->is_connected)) - return -ENODEV; + dev_dbg(codec->dev, "Entered %s:%s\n", __func__, kcontrol->id.name); + module = find_gb_module(gb, kcontrol->id.name); + if (!module) + return -EINVAL; data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; info = (struct gb_audio_ctl_elem_info *)data->info; - ret = gb_audio_gb_get_control(gb->mgmt_connection, data->ctl_id, + ret = gb_audio_gb_get_control(module->mgmt_connection, data->ctl_id, GB_AUDIO_INVALID_INDEX, &gbvalue); if (ret) { dev_err(codec->dev, "%d:Error in %s for %s\n", ret, __func__, @@ -187,11 +209,14 @@ static int gbcodec_mixer_ctl_put(struct snd_kcontrol *kcontrol, struct gb_audio_ctl_elem_info *info; struct gbaudio_ctl_pvt *data; struct gb_audio_ctl_elem_value gbvalue; + struct gbaudio_module_info *module; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); - if (!atomic_read(&gb->is_connected)) - return -ENODEV; + dev_dbg(codec->dev, "Entered %s:%s\n", __func__, kcontrol->id.name); + module = find_gb_module(gb, kcontrol->id.name); + if (!module) + return -EINVAL; data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; info = (struct gb_audio_ctl_elem_info *)data->info; @@ -223,7 +248,7 @@ static int gbcodec_mixer_ctl_put(struct snd_kcontrol *kcontrol, if (ret) return ret; - ret = gb_audio_gb_set_control(gb->mgmt_connection, data->ctl_id, + ret = gb_audio_gb_set_control(module->mgmt_connection, data->ctl_id, GB_AUDIO_INVALID_INDEX, &gbvalue); if (ret) { dev_err(codec->dev, "%d:Error in %s for %s\n", ret, __func__, @@ -250,7 +275,11 @@ static int gbcodec_mixer_dapm_ctl_info(struct snd_kcontrol *kcontrol, int platform_max, platform_min; struct gbaudio_ctl_pvt *data; struct gb_audio_ctl_elem_info *info; + struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); + struct snd_soc_dapm_widget *widget = wlist->widgets[0]; + struct snd_soc_codec *codec = widget->codec; + dev_dbg(codec->dev, "Entered %s:%s\n", __func__, kcontrol->id.name); data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; info = (struct gb_audio_ctl_elem_info *)data->info; @@ -282,13 +311,16 @@ static int gbcodec_mixer_dapm_ctl_get(struct snd_kcontrol *kcontrol, struct gb_audio_ctl_elem_info *info; struct gbaudio_ctl_pvt *data; struct gb_audio_ctl_elem_value gbvalue; + struct gbaudio_module_info *module; struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); struct snd_soc_dapm_widget *widget = wlist->widgets[0]; struct snd_soc_codec *codec = widget->codec; struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); - if (!atomic_read(&gb->is_connected)) - return -ENODEV; + dev_dbg(codec->dev, "Entered %s:%s\n", __func__, kcontrol->id.name); + module = find_gb_module(gb, kcontrol->id.name); + if (!module) + return -EINVAL; data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; info = (struct gb_audio_ctl_elem_info *)data->info; @@ -298,7 +330,7 @@ static int gbcodec_mixer_dapm_ctl_get(struct snd_kcontrol *kcontrol, "GB: Control '%s' is stereo, which is not supported\n", kcontrol->id.name); - ret = gb_audio_gb_get_control(gb->mgmt_connection, data->ctl_id, + ret = gb_audio_gb_get_control(module->mgmt_connection, data->ctl_id, GB_AUDIO_INVALID_INDEX, &gbvalue); if (ret) { dev_err(codec->dev, "%d:Error in %s for %s\n", ret, __func__, @@ -319,13 +351,16 @@ static int gbcodec_mixer_dapm_ctl_put(struct snd_kcontrol *kcontrol, struct gb_audio_ctl_elem_info *info; struct gbaudio_ctl_pvt *data; struct gb_audio_ctl_elem_value gbvalue; + struct gbaudio_module_info *module; struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); struct snd_soc_dapm_widget *widget = wlist->widgets[0]; struct snd_soc_codec *codec = widget->codec; struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); - if (!atomic_read(&gb->is_connected)) - return -ENODEV; + dev_dbg(codec->dev, "Entered %s:%s\n", __func__, kcontrol->id.name); + module = find_gb_module(gb, kcontrol->id.name); + if (!module) + return -EINVAL; data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; info = (struct gb_audio_ctl_elem_info *)data->info; @@ -352,7 +387,7 @@ static int gbcodec_mixer_dapm_ctl_put(struct snd_kcontrol *kcontrol, } gbvalue.value.integer_value[0] = ucontrol->value.integer.value[0]; - ret = gb_audio_gb_set_control(gb->mgmt_connection, + ret = gb_audio_gb_set_control(module->mgmt_connection, data->ctl_id, GB_AUDIO_INVALID_INDEX, &gbvalue); if (ret) { @@ -420,7 +455,7 @@ static int gbaudio_validate_kcontrol_count(struct gb_audio_widget *w) return ret; } -static int gbaudio_tplg_create_kcontrol(struct gbaudio_codec_info *gb, +static int gbaudio_tplg_create_kcontrol(struct gbaudio_module_info *gb, struct snd_kcontrol_new *kctl, struct gb_audio_control *ctl) { @@ -452,23 +487,23 @@ static int gbaudio_tplg_create_kcontrol(struct gbaudio_codec_info *gb, static const char * const gbtexts[] = {"Stereo", "Left", "Right"}; static const SOC_ENUM_SINGLE_DECL( - gbcodec_apb1_rx_enum, GBCODEC_APB1_MUX_REG, 0, gbtexts); + module_apb1_rx_enum, GBCODEC_APB1_MUX_REG, 0, gbtexts); static const SOC_ENUM_SINGLE_DECL( - gbcodec_mic_enum, GBCODEC_APB1_MUX_REG, 4, gbtexts); + module_mic_enum, GBCODEC_APB1_MUX_REG, 4, gbtexts); -static int gbaudio_tplg_create_enum_ctl(struct gbaudio_codec_info *gb, +static int gbaudio_tplg_create_enum_ctl(struct gbaudio_module_info *gb, struct snd_kcontrol_new *kctl, struct gb_audio_control *ctl) { switch (ctl->id) { case 8: *kctl = (struct snd_kcontrol_new) - SOC_DAPM_ENUM(ctl->name, gbcodec_apb1_rx_enum); + SOC_DAPM_ENUM(ctl->name, module_apb1_rx_enum); break; case 9: *kctl = (struct snd_kcontrol_new) - SOC_DAPM_ENUM(ctl->name, gbcodec_mic_enum); + SOC_DAPM_ENUM(ctl->name, module_mic_enum); break; default: return -EINVAL; @@ -477,7 +512,7 @@ static int gbaudio_tplg_create_enum_ctl(struct gbaudio_codec_info *gb, return 0; } -static int gbaudio_tplg_create_mixer_ctl(struct gbaudio_codec_info *gb, +static int gbaudio_tplg_create_mixer_ctl(struct gbaudio_module_info *gb, struct snd_kcontrol_new *kctl, struct gb_audio_control *ctl) { @@ -498,7 +533,7 @@ static int gbaudio_tplg_create_mixer_ctl(struct gbaudio_codec_info *gb, return 0; } -static int gbaudio_tplg_create_wcontrol(struct gbaudio_codec_info *gb, +static int gbaudio_tplg_create_wcontrol(struct gbaudio_module_info *gb, struct snd_kcontrol_new *kctl, struct gb_audio_control *ctl) { @@ -532,11 +567,17 @@ static int gbaudio_widget_event(struct snd_soc_dapm_widget *w, int ret; struct snd_soc_codec *codec = w->codec; struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec); + struct gbaudio_module_info *module; dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event); + /* Find relevant module */ + module = find_gb_module(gbcodec, w->name); + if (!module) + return -EINVAL; + /* map name to widget id */ - wid = gbaudio_map_widgetname(gbcodec, w->name); + wid = gbaudio_map_widgetname(module, w->name); if (wid < 0) { dev_err(codec->dev, "Invalid widget name:%s\n", w->name); return -EINVAL; @@ -544,10 +585,16 @@ static int gbaudio_widget_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: - ret = gb_audio_gb_enable_widget(gbcodec->mgmt_connection, wid); + ret = gb_audio_gb_enable_widget(module->mgmt_connection, wid); + if (!ret) + ret = gbaudio_module_update(gbcodec, w->name, module, + 1); break; case SND_SOC_DAPM_POST_PMD: - ret = gb_audio_gb_disable_widget(gbcodec->mgmt_connection, wid); + ret = gb_audio_gb_disable_widget(module->mgmt_connection, wid); + if (!ret) + ret = gbaudio_module_update(gbcodec, w->name, module, + 0); break; } if (ret) @@ -556,7 +603,7 @@ static int gbaudio_widget_event(struct snd_soc_dapm_widget *w, return ret; } -static int gbaudio_tplg_create_widget(struct gbaudio_codec_info *gbcodec, +static int gbaudio_tplg_create_widget(struct gbaudio_module_info *module, struct snd_soc_dapm_widget *dw, struct gb_audio_widget *w) { @@ -565,10 +612,11 @@ static int gbaudio_tplg_create_widget(struct gbaudio_codec_info *gbcodec, struct gb_audio_control *curr; struct gbaudio_control *control, *_control; size_t size; + char temp_name[NAME_SIZE]; ret = gbaudio_validate_kcontrol_count(w); if (ret) { - dev_err(gbcodec->dev, "Inavlid kcontrol count=%d for %s\n", + dev_err(module->dev, "Inavlid kcontrol count=%d for %s\n", w->ncontrols, w->name); return ret; } @@ -576,7 +624,7 @@ static int gbaudio_tplg_create_widget(struct gbaudio_codec_info *gbcodec, /* allocate memory for kcontrol */ if (w->ncontrols) { size = sizeof(struct snd_kcontrol_new) * w->ncontrols; - widget_kctls = devm_kzalloc(gbcodec->dev, size, GFP_KERNEL); + widget_kctls = devm_kzalloc(module->dev, size, GFP_KERNEL); if (!widget_kctls) return -ENOMEM; } @@ -584,15 +632,15 @@ static int gbaudio_tplg_create_widget(struct gbaudio_codec_info *gbcodec, /* create relevant kcontrols */ for (i = 0; i < w->ncontrols; i++) { curr = &w->ctl[i]; - ret = gbaudio_tplg_create_wcontrol(gbcodec, &widget_kctls[i], + ret = gbaudio_tplg_create_wcontrol(module, &widget_kctls[i], curr); if (ret) { - dev_err(gbcodec->dev, + dev_err(module->dev, "%s:%d type widget_ctl not supported\n", curr->name, curr->iface); goto error; } - control = devm_kzalloc(gbcodec->dev, + control = devm_kzalloc(module->dev, sizeof(struct gbaudio_control), GFP_KERNEL); if (!control) { @@ -604,11 +652,15 @@ static int gbaudio_tplg_create_widget(struct gbaudio_codec_info *gbcodec, if (curr->info.type == GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED) control->texts = (const char * const *) curr->info.value.enumerated.names; - list_add(&control->list, &gbcodec->widget_ctl_list); - dev_dbg(gbcodec->dev, "%s: control of type %d created\n", + list_add(&control->list, &module->widget_ctl_list); + dev_dbg(module->dev, "%s: control of type %d created\n", widget_kctls[i].name, widget_kctls[i].iface); } + /* Prefix dev_id to widget control_name */ + strlcpy(temp_name, w->name, NAME_SIZE); + snprintf(w->name, NAME_SIZE, "GB %d %s", module->dev_id, temp_name); + switch (w->type) { case snd_soc_dapm_spk: *dw = (struct snd_soc_dapm_widget) @@ -677,45 +729,19 @@ static int gbaudio_tplg_create_widget(struct gbaudio_codec_info *gbcodec, goto error; } - dev_dbg(gbcodec->dev, "%s: widget of type %d created\n", dw->name, + dev_dbg(module->dev, "%s: widget of type %d created\n", dw->name, dw->id); return 0; error: - list_for_each_entry_safe(control, _control, &gbcodec->widget_ctl_list, + list_for_each_entry_safe(control, _control, &module->widget_ctl_list, list) { list_del(&control->list); - devm_kfree(gbcodec->dev, control); + devm_kfree(module->dev, control); } return ret; } -static int gbaudio_tplg_create_dai(struct gbaudio_codec_info *gbcodec, - struct snd_soc_dai_driver *gb_dai, - struct gb_audio_dai *dai) -{ - /* - * do not update name here, - * append dev_id before assigning it here - */ - - gb_dai->playback.stream_name = dai->playback.stream_name; - gb_dai->playback.channels_min = dai->playback.chan_min; - gb_dai->playback.channels_max = dai->playback.chan_max; - gb_dai->playback.formats = dai->playback.formats; - gb_dai->playback.rates = dai->playback.rates; - gb_dai->playback.sig_bits = dai->playback.sig_bits; - - gb_dai->capture.stream_name = dai->capture.stream_name; - gb_dai->capture.channels_min = dai->capture.chan_min; - gb_dai->capture.channels_max = dai->capture.chan_max; - gb_dai->capture.formats = dai->capture.formats; - gb_dai->capture.rates = dai->capture.rates; - gb_dai->capture.sig_bits = dai->capture.sig_bits; - - return 0; -} - -static int gbaudio_tplg_process_kcontrols(struct gbaudio_codec_info *gbcodec, +static int gbaudio_tplg_process_kcontrols(struct gbaudio_module_info *module, struct gb_audio_control *controls) { int i, ret; @@ -723,22 +749,23 @@ static int gbaudio_tplg_process_kcontrols(struct gbaudio_codec_info *gbcodec, struct gb_audio_control *curr; struct gbaudio_control *control, *_control; size_t size; + char temp_name[NAME_SIZE]; - size = sizeof(struct snd_kcontrol_new) * gbcodec->num_kcontrols; - dapm_kctls = devm_kzalloc(gbcodec->dev, size, GFP_KERNEL); + size = sizeof(struct snd_kcontrol_new) * module->num_controls; + dapm_kctls = devm_kzalloc(module->dev, size, GFP_KERNEL); if (!dapm_kctls) return -ENOMEM; curr = controls; - for (i = 0; i < gbcodec->num_kcontrols; i++) { - ret = gbaudio_tplg_create_kcontrol(gbcodec, &dapm_kctls[i], + for (i = 0; i < module->num_controls; i++) { + ret = gbaudio_tplg_create_kcontrol(module, &dapm_kctls[i], curr); if (ret) { - dev_err(gbcodec->dev, "%s:%d type not supported\n", + dev_err(module->dev, "%s:%d type not supported\n", curr->name, curr->iface); goto error; } - control = devm_kzalloc(gbcodec->dev, sizeof(struct + control = devm_kzalloc(module->dev, sizeof(struct gbaudio_control), GFP_KERNEL); if (!control) { @@ -746,29 +773,33 @@ static int gbaudio_tplg_process_kcontrols(struct gbaudio_codec_info *gbcodec, goto error; } control->id = curr->id; + /* Prefix dev_id to widget_name */ + strlcpy(temp_name, curr->name, NAME_SIZE); + snprintf(curr->name, NAME_SIZE, "GB %d %s", module->dev_id, + temp_name); control->name = curr->name; if (curr->info.type == GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED) control->texts = (const char * const *) curr->info.value.enumerated.names; - list_add(&control->list, &gbcodec->codec_ctl_list); - dev_dbg(gbcodec->dev, "%d:%s created of type %d\n", curr->id, + list_add(&control->list, &module->ctl_list); + dev_dbg(module->dev, "%d:%s created of type %d\n", curr->id, curr->name, curr->info.type); curr++; } - gbcodec->kctls = dapm_kctls; + module->controls = dapm_kctls; return 0; error: - list_for_each_entry_safe(control, _control, &gbcodec->codec_ctl_list, + list_for_each_entry_safe(control, _control, &module->ctl_list, list) { list_del(&control->list); - devm_kfree(gbcodec->dev, control); + devm_kfree(module->dev, control); } - devm_kfree(gbcodec->dev, dapm_kctls); + devm_kfree(module->dev, dapm_kctls); return ret; } -static int gbaudio_tplg_process_widgets(struct gbaudio_codec_info *gbcodec, +static int gbaudio_tplg_process_widgets(struct gbaudio_module_info *module, struct gb_audio_widget *widgets) { int i, ret, ncontrols; @@ -777,21 +808,21 @@ static int gbaudio_tplg_process_widgets(struct gbaudio_codec_info *gbcodec, struct gbaudio_widget *widget, *_widget; size_t size; - size = sizeof(struct snd_soc_dapm_widget) * gbcodec->num_dapm_widgets; - dapm_widgets = devm_kzalloc(gbcodec->dev, size, GFP_KERNEL); + size = sizeof(struct snd_soc_dapm_widget) * module->num_dapm_widgets; + dapm_widgets = devm_kzalloc(module->dev, size, GFP_KERNEL); if (!dapm_widgets) return -ENOMEM; curr = widgets; - for (i = 0; i < gbcodec->num_dapm_widgets; i++) { - ret = gbaudio_tplg_create_widget(gbcodec, &dapm_widgets[i], + for (i = 0; i < module->num_dapm_widgets; i++) { + ret = gbaudio_tplg_create_widget(module, &dapm_widgets[i], curr); if (ret) { - dev_err(gbcodec->dev, "%s:%d type not supported\n", + dev_err(module->dev, "%s:%d type not supported\n", curr->name, curr->type); goto error; } - widget = devm_kzalloc(gbcodec->dev, sizeof(struct + widget = devm_kzalloc(module->dev, sizeof(struct gbaudio_widget), GFP_KERNEL); if (!widget) { @@ -800,69 +831,26 @@ static int gbaudio_tplg_process_widgets(struct gbaudio_codec_info *gbcodec, } widget->id = curr->id; widget->name = curr->name; - list_add(&widget->list, &gbcodec->widget_list); + list_add(&widget->list, &module->widget_list); ncontrols = curr->ncontrols; curr++; curr += ncontrols * sizeof(struct gb_audio_control); } - gbcodec->widgets = dapm_widgets; + module->dapm_widgets = dapm_widgets; return 0; error: - list_for_each_entry_safe(widget, _widget, &gbcodec->widget_list, + list_for_each_entry_safe(widget, _widget, &module->widget_list, list) { list_del(&widget->list); - devm_kfree(gbcodec->dev, widget); - } - devm_kfree(gbcodec->dev, dapm_widgets); - return ret; -} - -static int gbaudio_tplg_process_dais(struct gbaudio_codec_info *gbcodec, - struct gb_audio_dai *dais) -{ - int i, ret; - struct snd_soc_dai_driver *gb_dais; - struct gb_audio_dai *curr; - size_t size; - char dai_name[NAME_SIZE]; - struct gbaudio_dai *dai; - - size = sizeof(struct snd_soc_dai_driver) * gbcodec->num_dais; - gb_dais = devm_kzalloc(gbcodec->dev, size, GFP_KERNEL); - if (!gb_dais) - return -ENOMEM; - - curr = dais; - for (i = 0; i < gbcodec->num_dais; i++) { - ret = gbaudio_tplg_create_dai(gbcodec, &gb_dais[i], curr); - if (ret) { - dev_err(gbcodec->dev, "%s failed to create\n", - curr->name); - goto error; - } - /* append dev_id to dai_name */ - snprintf(dai_name, NAME_SIZE, "%s.%d", curr->name, - gbcodec->dev_id); - dai = gbaudio_find_dai(gbcodec, curr->data_cport, NULL); - if (!dai) - goto error; - strlcpy(dai->name, dai_name, NAME_SIZE); - dev_dbg(gbcodec->dev, "%s:DAI added\n", dai->name); - gb_dais[i].name = dai->name; - curr++; + devm_kfree(module->dev, widget); } - gbcodec->dais = gb_dais; - - return 0; - -error: - devm_kfree(gbcodec->dev, gb_dais); + devm_kfree(module->dev, dapm_widgets); return ret; } -static int gbaudio_tplg_process_routes(struct gbaudio_codec_info *gbcodec, +static int gbaudio_tplg_process_routes(struct gbaudio_module_info *module, struct gb_audio_route *routes) { int i, ret; @@ -870,47 +858,47 @@ static int gbaudio_tplg_process_routes(struct gbaudio_codec_info *gbcodec, struct gb_audio_route *curr; size_t size; - size = sizeof(struct snd_soc_dapm_route) * gbcodec->num_dapm_routes; - dapm_routes = devm_kzalloc(gbcodec->dev, size, GFP_KERNEL); + size = sizeof(struct snd_soc_dapm_route) * module->num_dapm_routes; + dapm_routes = devm_kzalloc(module->dev, size, GFP_KERNEL); if (!dapm_routes) return -ENOMEM; - gbcodec->routes = dapm_routes; + module->dapm_routes = dapm_routes; curr = routes; - for (i = 0; i < gbcodec->num_dapm_routes; i++) { + for (i = 0; i < module->num_dapm_routes; i++) { dapm_routes->sink = - gbaudio_map_widgetid(gbcodec, curr->destination_id); + gbaudio_map_widgetid(module, curr->destination_id); if (!dapm_routes->sink) { - dev_err(gbcodec->dev, "%d:%d:%d:%d - Invalid sink\n", + dev_err(module->dev, "%d:%d:%d:%d - Invalid sink\n", curr->source_id, curr->destination_id, curr->control_id, curr->index); ret = -EINVAL; goto error; } dapm_routes->source = - gbaudio_map_widgetid(gbcodec, curr->source_id); + gbaudio_map_widgetid(module, curr->source_id); if (!dapm_routes->source) { - dev_err(gbcodec->dev, "%d:%d:%d:%d - Invalid source\n", + dev_err(module->dev, "%d:%d:%d:%d - Invalid source\n", curr->source_id, curr->destination_id, curr->control_id, curr->index); ret = -EINVAL; goto error; } dapm_routes->control = - gbaudio_map_controlid(gbcodec, + gbaudio_map_controlid(module, curr->control_id, curr->index); if ((curr->control_id != GBAUDIO_INVALID_ID) && !dapm_routes->control) { - dev_err(gbcodec->dev, "%d:%d:%d:%d - Invalid control\n", + dev_err(module->dev, "%d:%d:%d:%d - Invalid control\n", curr->source_id, curr->destination_id, curr->control_id, curr->index); ret = -EINVAL; goto error; } - dev_dbg(gbcodec->dev, "Route {%s, %s, %s}\n", dapm_routes->sink, + dev_dbg(module->dev, "Route {%s, %s, %s}\n", dapm_routes->sink, (dapm_routes->control) ? dapm_routes->control:"NULL", dapm_routes->source); dapm_routes++; @@ -920,41 +908,39 @@ static int gbaudio_tplg_process_routes(struct gbaudio_codec_info *gbcodec, return 0; error: - devm_kfree(gbcodec->dev, dapm_routes); + devm_kfree(module->dev, dapm_routes); return ret; } -static int gbaudio_tplg_process_header(struct gbaudio_codec_info *gbcodec, +static int gbaudio_tplg_process_header(struct gbaudio_module_info *module, struct gb_audio_topology *tplg_data) { /* fetch no. of kcontrols, widgets & routes */ - gbcodec->num_dais = tplg_data->num_dais; - gbcodec->num_kcontrols = tplg_data->num_controls; - gbcodec->num_dapm_widgets = tplg_data->num_widgets; - gbcodec->num_dapm_routes = tplg_data->num_routes; + module->num_controls = tplg_data->num_controls; + module->num_dapm_widgets = tplg_data->num_widgets; + module->num_dapm_routes = tplg_data->num_routes; /* update block offset */ - gbcodec->dai_offset = (unsigned long)&tplg_data->data; - gbcodec->control_offset = gbcodec->dai_offset + tplg_data->size_dais; - gbcodec->widget_offset = gbcodec->control_offset + + module->dai_offset = (unsigned long)&tplg_data->data; + module->control_offset = module->dai_offset + tplg_data->size_dais; + module->widget_offset = module->control_offset + tplg_data->size_controls; - gbcodec->route_offset = gbcodec->widget_offset + + module->route_offset = module->widget_offset + tplg_data->size_widgets; - dev_dbg(gbcodec->dev, "DAI offset is 0x%lx\n", gbcodec->dai_offset); - dev_dbg(gbcodec->dev, "control offset is %lx\n", - gbcodec->control_offset); - dev_dbg(gbcodec->dev, "widget offset is %lx\n", gbcodec->widget_offset); - dev_dbg(gbcodec->dev, "route offset is %lx\n", gbcodec->route_offset); + dev_dbg(module->dev, "DAI offset is 0x%lx\n", module->dai_offset); + dev_dbg(module->dev, "control offset is %lx\n", + module->control_offset); + dev_dbg(module->dev, "widget offset is %lx\n", module->widget_offset); + dev_dbg(module->dev, "route offset is %lx\n", module->route_offset); return 0; } -int gbaudio_tplg_parse_data(struct gbaudio_codec_info *gbcodec, +int gbaudio_tplg_parse_data(struct gbaudio_module_info *module, struct gb_audio_topology *tplg_data) { int ret; - struct gb_audio_dai *dais; struct gb_audio_control *controls; struct gb_audio_widget *widgets; struct gb_audio_route *routes; @@ -962,90 +948,80 @@ int gbaudio_tplg_parse_data(struct gbaudio_codec_info *gbcodec, if (!tplg_data) return -EINVAL; - ret = gbaudio_tplg_process_header(gbcodec, tplg_data); + ret = gbaudio_tplg_process_header(module, tplg_data); if (ret) { - dev_err(gbcodec->dev, "%d: Error in parsing topology header\n", + dev_err(module->dev, "%d: Error in parsing topology header\n", ret); return ret; } /* process control */ - controls = (struct gb_audio_control *)gbcodec->control_offset; - ret = gbaudio_tplg_process_kcontrols(gbcodec, controls); + controls = (struct gb_audio_control *)module->control_offset; + ret = gbaudio_tplg_process_kcontrols(module, controls); if (ret) { - dev_err(gbcodec->dev, + dev_err(module->dev, "%d: Error in parsing controls data\n", ret); return ret; } - dev_dbg(gbcodec->dev, "Control parsing finished\n"); - - /* process DAI */ - dais = (struct gb_audio_dai *)gbcodec->dai_offset; - ret = gbaudio_tplg_process_dais(gbcodec, dais); - if (ret) { - dev_err(gbcodec->dev, - "%d: Error in parsing DAIs data\n", ret); - return ret; - } - dev_dbg(gbcodec->dev, "DAI parsing finished\n"); + dev_dbg(module->dev, "Control parsing finished\n"); /* process widgets */ - widgets = (struct gb_audio_widget *)gbcodec->widget_offset; - ret = gbaudio_tplg_process_widgets(gbcodec, widgets); + widgets = (struct gb_audio_widget *)module->widget_offset; + ret = gbaudio_tplg_process_widgets(module, widgets); if (ret) { - dev_err(gbcodec->dev, + dev_err(module->dev, "%d: Error in parsing widgets data\n", ret); return ret; } - dev_dbg(gbcodec->dev, "Widget parsing finished\n"); + dev_dbg(module->dev, "Widget parsing finished\n"); /* process route */ - routes = (struct gb_audio_route *)gbcodec->route_offset; - ret = gbaudio_tplg_process_routes(gbcodec, routes); + routes = (struct gb_audio_route *)module->route_offset; + ret = gbaudio_tplg_process_routes(module, routes); if (ret) { - dev_err(gbcodec->dev, + dev_err(module->dev, "%d: Error in parsing routes data\n", ret); return ret; } - dev_dbg(gbcodec->dev, "Route parsing finished\n"); + dev_dbg(module->dev, "Route parsing finished\n"); return ret; } -void gbaudio_tplg_release(struct gbaudio_codec_info *gbcodec) +void gbaudio_tplg_release(struct gbaudio_module_info *module) { struct gbaudio_control *control, *_control; struct gbaudio_widget *widget, *_widget; - if (!gbcodec->topology) + if (!module->topology) return; /* release kcontrols */ - list_for_each_entry_safe(control, _control, &gbcodec->codec_ctl_list, + list_for_each_entry_safe(control, _control, &module->ctl_list, list) { list_del(&control->list); - devm_kfree(gbcodec->dev, control); + devm_kfree(module->dev, control); } - if (gbcodec->kctls) - devm_kfree(gbcodec->dev, gbcodec->kctls); + if (module->controls) + devm_kfree(module->dev, module->controls); /* release widget controls */ - list_for_each_entry_safe(control, _control, &gbcodec->widget_ctl_list, + list_for_each_entry_safe(control, _control, &module->widget_ctl_list, list) { list_del(&control->list); - devm_kfree(gbcodec->dev, control); + devm_kfree(module->dev, control); } /* release widgets */ - list_for_each_entry_safe(widget, _widget, &gbcodec->widget_list, + list_for_each_entry_safe(widget, _widget, &module->widget_list, list) { list_del(&widget->list); - devm_kfree(gbcodec->dev, widget); + devm_kfree(module->dev, widget); } - if (gbcodec->widgets) - devm_kfree(gbcodec->dev, gbcodec->widgets); + if (module->dapm_widgets) + devm_kfree(module->dev, module->dapm_widgets); /* release routes */ - if (gbcodec->routes) - devm_kfree(gbcodec->dev, gbcodec->routes); + if (module->dapm_routes) + devm_kfree(module->dev, module->dapm_routes); } -- cgit v0.10.2 From 5793227cb037e4fddf1dc869b0e0abcc22646f6b Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal Date: Tue, 29 Mar 2016 23:31:42 +0530 Subject: greybus: audio: Add module specific driver Use seperate driver to process GB Audio modules plugged-in. It'll use helper function register_module to attach itself to gbaudio-codec driver. Signed-off-by: Vaibhav Agarwal Reviewed-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 6e276d8..ec92891 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -31,7 +31,8 @@ gb-raw-y := raw.o gb-hid-y := hid.o gb-es2-y := es2.o gb-arche-y := arche-platform.o arche-apb-ctrl.o -gb-audio-codec-y := audio_codec.o audio_topology.o +gb-audio-module-y := audio_module.o audio_topology.o +gb-audio-codec-y := audio_codec.o gb-audio-gb-y := audio_gb.o gb-audio-apbridgea-y := audio_apbridgea.o gb-audio-manager-y += audio_manager.o @@ -52,6 +53,7 @@ ifeq ($(CONFIG_USB_HSIC_USB3613),y) endif ifeq ($(CONFIG_SND_SOC_DYNAMIC_DAILINK),y) obj-m += gb-audio-codec.o +obj-m += gb-audio-module.o endif ifeq ($(CONFIG_ARCH_MSM8994),y) obj-m += gb-camera.o diff --git a/drivers/staging/greybus/audio_module.c b/drivers/staging/greybus/audio_module.c new file mode 100644 index 0000000..94fdadc --- /dev/null +++ b/drivers/staging/greybus/audio_module.c @@ -0,0 +1,309 @@ +/* + * Greybus audio driver + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + * + * Released under the GPLv2 only. + */ +#include +#include +#include +#include +#include + +#include "audio_codec.h" +#include "audio_apbridgea.h" +#include "audio_manager.h" + +static DEFINE_MUTEX(gb_codec_list_lock); +static LIST_HEAD(gb_codec_list); + +/* + * gb_snd management functions + */ + +static int gbaudio_codec_request_handler(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_audio_streaming_event_request *req = op->request->payload; + + dev_warn(&connection->bundle->dev, + "Audio Event received: cport: %u, event: %u\n", + req->data_cport, req->event); + + return 0; +} + +static int gbaudio_data_connection_request_handler(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + + dev_warn(&connection->bundle->dev, "Audio Event received\n"); + + return 0; +} + +static int gb_audio_add_mgmt_connection(struct gbaudio_module_info *gbmodule, + struct greybus_descriptor_cport *cport_desc, + struct gb_bundle *bundle) +{ + struct gb_connection *connection; + + /* Management Cport */ + if (gbmodule->mgmt_connection) { + dev_err(&bundle->dev, + "Can't have multiple Management connections\n"); + return -ENODEV; + } + + connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id), + gbaudio_codec_request_handler); + if (IS_ERR(connection)) + return PTR_ERR(connection); + + connection->private = gbmodule; + gbmodule->mgmt_connection = connection; + + return 0; +} + +static int gb_audio_add_data_connection(struct gbaudio_module_info *gbmodule, + struct greybus_descriptor_cport *cport_desc, + struct gb_bundle *bundle) +{ + struct gb_connection *connection; + struct gbaudio_data_connection *dai; + + dai = devm_kzalloc(gbmodule->dev, sizeof(*dai), GFP_KERNEL); + if (!dai) { + dev_err(gbmodule->dev, "DAI Malloc failure\n"); + return -ENOMEM; + } + + connection = gb_connection_create_flags(bundle, + le16_to_cpu(cport_desc->id), + gbaudio_data_connection_request_handler, + GB_CONNECTION_FLAG_CSD); + if (IS_ERR(connection)) { + devm_kfree(gbmodule->dev, dai); + return PTR_ERR(connection); + } + + connection->private = gbmodule; + /* dai->name should be same as codec->dai_name */ + strlcpy(dai->name, "greybus-apb1", NAME_SIZE); + dai->data_cport = connection->intf_cport_id; + dai->connection = connection; + list_add(&dai->list, &gbmodule->data_list); + + return 0; +} + +/* + * This is the basic hook get things initialized and registered w/ gb + */ + +static int gb_audio_probe(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) +{ + struct device *dev = &bundle->dev; + struct gbaudio_module_info *gbmodule; + struct greybus_descriptor_cport *cport_desc; + struct gb_audio_manager_module_descriptor desc; + struct gbaudio_data_connection *dai, *_dai; + int ret, i; + struct gb_audio_topology *topology; + + + /* There should be at least one Management and one Data cport */ + if (bundle->num_cports < 2) + return -ENODEV; + + mutex_lock(&gb_codec_list_lock); + /* + * There can be only one Management connection and any number of data + * connections. + */ + gbmodule = devm_kzalloc(dev, sizeof(*gbmodule), GFP_KERNEL); + if (!gbmodule) { + mutex_unlock(&gb_codec_list_lock); + return -ENOMEM; + } + + gbmodule->num_data_connections = bundle->num_cports - 1; + mutex_init(&gbmodule->lock); + INIT_LIST_HEAD(&gbmodule->data_list); + INIT_LIST_HEAD(&gbmodule->widget_list); + INIT_LIST_HEAD(&gbmodule->ctl_list); + INIT_LIST_HEAD(&gbmodule->widget_ctl_list); + gbmodule->dev = dev; + snprintf(gbmodule->name, NAME_SIZE, "%s.%s", dev->driver->name, + dev_name(dev)); + greybus_set_drvdata(bundle, gbmodule); + + /* Create all connections */ + for (i = 0; i < bundle->num_cports; i++) { + cport_desc = &bundle->cport_desc[i]; + + switch (cport_desc->protocol_id) { + case GREYBUS_PROTOCOL_AUDIO_MGMT: + ret = gb_audio_add_mgmt_connection(gbmodule, cport_desc, + bundle); + if (ret) + goto destroy_connections; + break; + case GREYBUS_PROTOCOL_AUDIO_DATA: + ret = gb_audio_add_data_connection(gbmodule, cport_desc, + bundle); + if (ret) + goto destroy_connections; + break; + default: + dev_err(dev, "Unsupported protocol: 0x%02x\n", + cport_desc->protocol_id); + ret = -ENODEV; + goto destroy_connections; + } + } + + /* There must be a management cport */ + if (!gbmodule->mgmt_connection) { + ret = -EINVAL; + dev_err(dev, "Missing management connection\n"); + goto destroy_connections; + } + + /* Initialize management connection */ + ret = gb_connection_enable(gbmodule->mgmt_connection); + if (ret) { + dev_err(dev, "%d: Error while enabling mgmt connection\n", ret); + goto destroy_connections; + } + gbmodule->dev_id = gbmodule->mgmt_connection->intf->interface_id; + + /* + * FIXME: malloc for topology happens via audio_gb driver + * should be done within codec driver itself + */ + ret = gb_audio_gb_get_topology(gbmodule->mgmt_connection, &topology); + if (ret) { + dev_err(dev, "%d:Error while fetching topology\n", ret); + goto disable_connection; + } + + /* process topology data */ + ret = gbaudio_tplg_parse_data(gbmodule, topology); + if (ret) { + dev_err(dev, "%d:Error while parsing topology data\n", + ret); + goto free_topology; + } + gbmodule->topology = topology; + + /* register module with gbcodec */ + ret = gbaudio_register_module(gbmodule); + if (ret) + goto release_topology; + + /* Initialize data connections */ + list_for_each_entry(dai, &gbmodule->data_list, list) { + ret = gb_connection_enable(dai->connection); + if (ret) + goto disable_data_connection; + } + gbmodule->is_connected = 1; + + /* inform above layer for uevent */ + dev_dbg(dev, "Inform set_event:%d to above layer\n", 1); + /* prepare for the audio manager */ + strlcpy(desc.name, gbmodule->name, GB_AUDIO_MANAGER_MODULE_NAME_LEN); + desc.slot = 1; /* todo */ + desc.vid = 2; /* todo */ + desc.pid = 3; /* todo */ + desc.cport = gbmodule->dev_id; + desc.devices = 0x2; /* todo */ + gbmodule->manager_id = gb_audio_manager_add(&desc); + + dev_dbg(dev, "Add GB Audio device:%s\n", gbmodule->name); + mutex_unlock(&gb_codec_list_lock); + + return 0; + +disable_data_connection: + list_for_each_entry_safe(dai, _dai, &gbmodule->data_list, list) + gb_connection_disable(dai->connection); + gbaudio_unregister_module(gbmodule); + +release_topology: + gbaudio_tplg_release(gbmodule); + gbmodule->topology = NULL; + +free_topology: + kfree(topology); + +disable_connection: + gb_connection_disable(gbmodule->mgmt_connection); + +destroy_connections: + list_for_each_entry_safe(dai, _dai, &gbmodule->data_list, list) { + gb_connection_destroy(dai->connection); + list_del(&dai->list); + devm_kfree(dev, dai); + } + + if (gbmodule->mgmt_connection) + gb_connection_destroy(gbmodule->mgmt_connection); + + devm_kfree(dev, gbmodule); + mutex_unlock(&gb_codec_list_lock); + + return ret; +} + +static void gb_audio_disconnect(struct gb_bundle *bundle) +{ + struct gbaudio_module_info *gbmodule = greybus_get_drvdata(bundle); + struct gbaudio_data_connection *dai, *_dai; + + mutex_lock(&gb_codec_list_lock); + + gbaudio_unregister_module(gbmodule); + + /* inform uevent to above layers */ + gb_audio_manager_remove(gbmodule->manager_id); + + gbaudio_tplg_release(gbmodule); + gbmodule->topology = NULL; + kfree(gbmodule->topology); + gb_connection_disable(gbmodule->mgmt_connection); + list_for_each_entry_safe(dai, _dai, &gbmodule->data_list, list) { + gb_connection_disable(dai->connection); + gb_connection_destroy(dai->connection); + list_del(&dai->list); + devm_kfree(gbmodule->dev, dai); + } + gb_connection_destroy(gbmodule->mgmt_connection); + gbmodule->mgmt_connection = NULL; + + devm_kfree(&bundle->dev, gbmodule); + mutex_unlock(&gb_codec_list_lock); +} + +static const struct greybus_bundle_id gb_audio_id_table[] = { + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_AUDIO) }, + { } +}; +MODULE_DEVICE_TABLE(greybus, gb_audio_id_table); + +static struct greybus_driver gb_audio_driver = { + .name = "gb-audio", + .probe = gb_audio_probe, + .disconnect = gb_audio_disconnect, + .id_table = gb_audio_id_table, +}; +module_greybus_driver(gb_audio_driver); + +MODULE_DESCRIPTION("Greybus Audio module driver"); +MODULE_AUTHOR("Vaibhav Agarwal "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:gbaudio-module"); -- cgit v0.10.2 From d764212f73cf270f10b041d8e26a8eb1ee7d4909 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal Date: Tue, 29 Mar 2016 23:31:43 +0530 Subject: greybus: audio: fix to resolve multiple audio module playback issue Cleanup APBridge sequence only in case of last module plugged-out. For other modules, unregister cportid is sufficient. Signed-off-by: Vaibhav Agarwal Reviewed-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index ab24ec8..803bab2 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -794,6 +794,7 @@ void gbaudio_codec_cleanup(struct gbaudio_module_info *module) if (!pb_state && !cap_state) return; + dev_dbg(gbcodec->dev, "%s: removed, cleanup APBridge\n", module->name); if (pb_state == GBAUDIO_CODEC_START) { /* cleanup PB path, only APBridge specific */ data = find_data(module, gbcodec->stream[0].dai_name); @@ -802,12 +803,16 @@ void gbaudio_codec_cleanup(struct gbaudio_module_info *module) __func__); return; } - ret = gb_audio_apbridgea_stop_tx(data->connection, 0); - if (ret) - return; - ret = gb_audio_apbridgea_shutdown_tx(data->connection, 0); - if (ret) - return; + + if (list_is_singular(&gbcodec->module_list)) { + ret = gb_audio_apbridgea_stop_tx(data->connection, 0); + if (ret) + return; + ret = gb_audio_apbridgea_shutdown_tx(data->connection, + 0); + if (ret) + return; + } i2s_port = 0; /* fixed for now */ cportid = data->connection->hd_cport_id; ret = gb_audio_apbridgea_unregister_cport(data->connection, @@ -824,12 +829,15 @@ void gbaudio_codec_cleanup(struct gbaudio_module_info *module) __func__); return; } - ret = gb_audio_apbridgea_stop_rx(data->connection, 0); - if (ret) - return; - ret = gb_audio_apbridgea_shutdown_rx(data->connection, 0); - if (ret) - return; + if (list_is_singular(&gbcodec->module_list)) { + ret = gb_audio_apbridgea_stop_rx(data->connection, 0); + if (ret) + return; + ret = gb_audio_apbridgea_shutdown_rx(data->connection, + 0); + if (ret) + return; + } i2s_port = 0; /* fixed for now */ cportid = data->connection->hd_cport_id; ret = gb_audio_apbridgea_unregister_cport(data->connection, @@ -854,10 +862,7 @@ void gbaudio_unregister_module(struct gbaudio_module_info *module) dev_dbg(codec->dev, "Process Unregister %s module\n", module->name); mutex_lock(&module->lock); - if (list_is_last(&module->list, &gbcodec->module_list)) { - dev_dbg(codec->dev, "Last module removed, cleanup APBridge\n"); - gbaudio_codec_cleanup(module); - } + gbaudio_codec_cleanup(module); module->is_connected = 0; if (module->dapm_routes) { -- cgit v0.10.2 From b77e3e5658921537df925c03fd358c4818be6f52 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 30 Mar 2016 16:53:17 -0400 Subject: greybus: core: fix two container-of macros Fix two greybus container-of macros that used the pointer name for the member. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h index fe6c086..b481dd0 100644 --- a/drivers/staging/greybus/hd.h +++ b/drivers/staging/greybus/hd.h @@ -48,7 +48,7 @@ struct gb_host_device { /* Private data for the host driver */ unsigned long hd_priv[0] __aligned(sizeof(s64)); }; -#define to_gb_host_device(d) container_of(d, struct gb_host_device, d) +#define to_gb_host_device(d) container_of(d, struct gb_host_device, dev) struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, struct device *parent, diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index 0436f49..2f23bc0 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -41,7 +41,7 @@ struct gb_svc { char *input_phys; struct gb_svc_watchdog *watchdog; }; -#define to_gb_svc(d) container_of(d, struct gb_svc, d) +#define to_gb_svc(d) container_of(d, struct gb_svc, dev) struct gb_svc *gb_svc_create(struct gb_host_device *hd); int gb_svc_add(struct gb_svc *svc); -- cgit v0.10.2 From 1b4c4e98eb9dcf0dbe4d940c4485e81de64b0325 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 29 Mar 2016 18:55:56 -0400 Subject: greybus: greybus_protocols: align DME-attribute values Align the DME-attribute values in the protocol header. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 9c628cc..863bcb9 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -893,9 +893,9 @@ struct gb_svc_dme_peer_set_response { } __packed; /* Attributes for peer get/set operations */ -#define DME_ATTR_SELECTOR_INDEX 0 +#define DME_ATTR_SELECTOR_INDEX 0 /* FIXME: remove ES2 support and DME_ATTR_T_TST_SRC_INCREMENT */ -#define DME_ATTR_T_TST_SRC_INCREMENT 0x4083 +#define DME_ATTR_T_TST_SRC_INCREMENT 0x4083 #define DME_ATTR_ES3_INIT_STATUS 0x6101 /* Return value from init-status attributes listed above */ -- cgit v0.10.2 From b5eebbf6a1f15273ce100ea14c9339d26c44e546 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 29 Mar 2016 18:55:57 -0400 Subject: greybus: svc: remove bogus interface-reset helper Remove unused, bogus interface-reset helper. The interface-reset operation is initiated by the SVC, not the AP. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 6a8da0d..ca1d482 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -119,17 +119,6 @@ static int gb_svc_intf_device_id(struct gb_svc *svc, u8 intf_id, u8 device_id) &request, sizeof(request), NULL, 0); } -int gb_svc_intf_reset(struct gb_svc *svc, u8 intf_id) -{ - struct gb_svc_intf_reset_request request; - - request.intf_id = intf_id; - - return gb_operation_sync(svc->connection, GB_SVC_TYPE_INTF_RESET, - &request, sizeof(request), NULL, 0); -} -EXPORT_SYMBOL_GPL(gb_svc_intf_reset); - int gb_svc_intf_eject(struct gb_svc *svc, u8 intf_id) { struct gb_svc_intf_eject_request request; diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index 2f23bc0..519d2f3 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -48,7 +48,6 @@ int gb_svc_add(struct gb_svc *svc); void gb_svc_del(struct gb_svc *svc); void gb_svc_put(struct gb_svc *svc); -int gb_svc_intf_reset(struct gb_svc *svc, u8 intf_id); int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id, u8 cport_flags); void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, -- cgit v0.10.2 From 601df8ff3ad2f88bdece80e71986b462da9c9b2e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 29 Mar 2016 18:55:58 -0400 Subject: greybus: greybus_protocols: remove bogus comment about svc bundle The SVC connection is special and does not belong to neither an interface or a bundle. Remove the unused SVC bundle-id define. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 863bcb9..31e772a 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -59,11 +59,6 @@ #define GB_DEVICE_ID_AP 1 #define GB_DEVICE_ID_MODULES_START 2 -/* - * Bundle/cport for control/svc cport: The same bundle/cport is shared by both - * CONTROL and SVC protocols for communication between AP and SVC. - */ -#define GB_SVC_BUNDLE_ID 0 #define GB_SVC_CPORT_ID 0 #define GB_CONTROL_BUNDLE_ID 0 #define GB_CONTROL_CPORT_ID 0 -- cgit v0.10.2 From 9ba486e3198eab8cd254c5089cc9f56b1d5b8d4c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 29 Mar 2016 18:55:59 -0400 Subject: greybus: svc: indent CPort flag defines properly Use tabs to indent CPort-flag values. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index 519d2f3..904b2dd 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -10,9 +10,9 @@ #ifndef __SVC_H #define __SVC_H -#define GB_SVC_CPORT_FLAG_E2EFC BIT(0) -#define GB_SVC_CPORT_FLAG_CSD_N BIT(1) -#define GB_SVC_CPORT_FLAG_CSV_N BIT(2) +#define GB_SVC_CPORT_FLAG_E2EFC BIT(0) +#define GB_SVC_CPORT_FLAG_CSD_N BIT(1) +#define GB_SVC_CPORT_FLAG_CSV_N BIT(2) enum gb_svc_state { GB_SVC_STATE_RESET, -- cgit v0.10.2 From c2d80906fbe529ee4b1963bf83d84e53e02e44c2 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 29 Mar 2016 18:56:00 -0400 Subject: greybus: interface: move boot-status clearing to interface enable Reading and clearing the boot status of an interface is an interface operation and belongs in the interface code. As part of the reworked interface boot sequence, we also want to do this when enabling (enumerating) a Greybus interface. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 44226c4..deb5b26 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -9,6 +9,69 @@ #include "greybus.h" + +/* + * T_TstSrcIncrement is written by the module on ES2 as a stand-in for boot + * status attribute ES3_INIT_STATUS. AP needs to read and clear it, after + * reading a non-zero value from it. + * + * FIXME: This is module-hardware dependent and needs to be extended for every + * type of module we want to support. + */ +static int gb_interface_read_and_clear_boot_status(struct gb_interface *intf) +{ + struct gb_host_device *hd = intf->hd; + int ret; + u32 value; + u16 attr; + u8 init_status; + + /* + * Check if the module is ES2 or ES3, and choose attr number + * appropriately. + * FIXME: Remove ES2 support from the kernel entirely. + */ + if (intf->ddbl1_manufacturer_id == ES2_DDBL1_MFR_ID && + intf->ddbl1_product_id == ES2_DDBL1_PROD_ID) + attr = DME_ATTR_T_TST_SRC_INCREMENT; + else + attr = DME_ATTR_ES3_INIT_STATUS; + + /* Read and clear boot status in ES3_INIT_STATUS */ + ret = gb_svc_dme_peer_get(hd->svc, intf->interface_id, attr, + DME_ATTR_SELECTOR_INDEX, &value); + if (ret) + return ret; + + /* + * A nonzero boot status indicates the module has finished + * booting. Clear it. + */ + if (!value) { + dev_err(&intf->dev, "Module not ready yet\n"); + return -ENODEV; + } + + /* + * Check if the module needs to boot from UniPro. + * For ES2: We need to check lowest 8 bits of 'value'. + * For ES3: We need to check highest 8 bits out of 32 of 'value'. + * FIXME: Remove ES2 support from the kernel entirely. + */ + if (intf->ddbl1_manufacturer_id == ES2_DDBL1_MFR_ID && + intf->ddbl1_product_id == ES2_DDBL1_PROD_ID) + init_status = value; + else + init_status = value >> 24; + + if (init_status == DME_DIS_UNIPRO_BOOT_STARTED || + init_status == DME_DIS_FALLBACK_UNIPRO_BOOT_STARTED) + intf->boot_over_unipro = true; + + return gb_svc_dme_peer_set(hd->svc, intf->interface_id, attr, + DME_ATTR_SELECTOR_INDEX, 0); +} + /* interface sysfs attributes */ #define gb_interface_attr(field, type) \ static ssize_t field##_show(struct device *dev, \ @@ -147,6 +210,12 @@ int gb_interface_enable(struct gb_interface *intf) int ret, size; void *manifest; + ret = gb_interface_read_and_clear_boot_status(intf); + if (ret) { + dev_err(&intf->dev, "failed to clear boot status: %d\n", ret); + return ret; + } + /* Establish control connection */ ret = gb_control_enable(intf->control); if (ret) diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index ca1d482..ca2f34e 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -210,69 +210,6 @@ int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, } EXPORT_SYMBOL_GPL(gb_svc_dme_peer_set); -/* - * T_TstSrcIncrement is written by the module on ES2 as a stand-in for boot - * status attribute ES3_INIT_STATUS. AP needs to read and clear it, after - * reading a non-zero value from it. - * - * FIXME: This is module-hardware dependent and needs to be extended for every - * type of module we want to support. - */ -static int gb_svc_read_and_clear_module_boot_status(struct gb_interface *intf) -{ - struct gb_host_device *hd = intf->hd; - int ret; - u32 value; - u16 attr; - u8 init_status; - - /* - * Check if the module is ES2 or ES3, and choose attr number - * appropriately. - * FIXME: Remove ES2 support from the kernel entirely. - */ - if (intf->ddbl1_manufacturer_id == ES2_DDBL1_MFR_ID && - intf->ddbl1_product_id == ES2_DDBL1_PROD_ID) - attr = DME_ATTR_T_TST_SRC_INCREMENT; - else - attr = DME_ATTR_ES3_INIT_STATUS; - - /* Read and clear boot status in ES3_INIT_STATUS */ - ret = gb_svc_dme_peer_get(hd->svc, intf->interface_id, attr, - DME_ATTR_SELECTOR_INDEX, &value); - - if (ret) - return ret; - - /* - * A nonzero boot status indicates the module has finished - * booting. Clear it. - */ - if (!value) { - dev_err(&intf->dev, "Module not ready yet\n"); - return -ENODEV; - } - - /* - * Check if the module needs to boot from UniPro. - * For ES2: We need to check lowest 8 bits of 'value'. - * For ES3: We need to check highest 8 bits out of 32 of 'value'. - * FIXME: Remove ES2 support from the kernel entirely. - */ - if (intf->ddbl1_manufacturer_id == ES2_DDBL1_MFR_ID && - intf->ddbl1_product_id == ES2_DDBL1_PROD_ID) - init_status = value; - else - init_status = value >> 24; - - if (init_status == DME_DIS_UNIPRO_BOOT_STARTED || - init_status == DME_DIS_FALLBACK_UNIPRO_BOOT_STARTED) - intf->boot_over_unipro = true; - - return gb_svc_dme_peer_set(hd->svc, intf->interface_id, attr, - DME_ATTR_SELECTOR_INDEX, 0); -} - int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id, @@ -609,13 +546,6 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) intf->product_id = product_id; } - ret = gb_svc_read_and_clear_module_boot_status(intf); - if (ret) { - dev_err(&svc->dev, "failed to clear boot status of interface %u: %d\n", - intf_id, ret); - goto out_interface_add; - } - ret = gb_svc_interface_route_create(svc, intf); if (ret) goto out_interface_add; -- cgit v0.10.2 From e12811eff7f9948d6cce661eef4a5910d747f194 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 29 Mar 2016 18:56:01 -0400 Subject: greybus: interface: fix es2 boot-status mask The ES2 boot status is stored in the least significant byte. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index deb5b26..3b18f61 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -60,7 +60,7 @@ static int gb_interface_read_and_clear_boot_status(struct gb_interface *intf) */ if (intf->ddbl1_manufacturer_id == ES2_DDBL1_MFR_ID && intf->ddbl1_product_id == ES2_DDBL1_PROD_ID) - init_status = value; + init_status = value & 0xff; else init_status = value >> 24; -- cgit v0.10.2 From 133e366bbee53c76596df5da4bf6b32d0d9cb364 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 29 Mar 2016 18:56:02 -0400 Subject: greybus: interface: clean up and rename init-status helper Clean up and rename the interface-init-status helper. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 3b18f61..569403c 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -11,55 +11,58 @@ /* - * T_TstSrcIncrement is written by the module on ES2 as a stand-in for boot - * status attribute ES3_INIT_STATUS. AP needs to read and clear it, after - * reading a non-zero value from it. + * T_TstSrcIncrement is written by the module on ES2 as a stand-in for the + * init-status attribute ES3_INIT_STATUS. The AP needs to read and clear it + * after reading a non-zero value from it. * * FIXME: This is module-hardware dependent and needs to be extended for every * type of module we want to support. */ -static int gb_interface_read_and_clear_boot_status(struct gb_interface *intf) +static int gb_interface_read_and_clear_init_status(struct gb_interface *intf) { struct gb_host_device *hd = intf->hd; int ret; u32 value; u16 attr; u8 init_status; + bool es2_bridge; + + es2_bridge = intf->ddbl1_manufacturer_id == ES2_DDBL1_MFR_ID && + intf->ddbl1_product_id == ES2_DDBL1_PROD_ID; /* - * Check if the module is ES2 or ES3, and choose attr number - * appropriately. - * FIXME: Remove ES2 support from the kernel entirely. + * ES2 bridges use T_TstSrcIncrement for the init status. + * + * FIXME: Remove ES2 support */ - if (intf->ddbl1_manufacturer_id == ES2_DDBL1_MFR_ID && - intf->ddbl1_product_id == ES2_DDBL1_PROD_ID) + if (es2_bridge) attr = DME_ATTR_T_TST_SRC_INCREMENT; else attr = DME_ATTR_ES3_INIT_STATUS; - /* Read and clear boot status in ES3_INIT_STATUS */ ret = gb_svc_dme_peer_get(hd->svc, intf->interface_id, attr, DME_ATTR_SELECTOR_INDEX, &value); if (ret) return ret; /* - * A nonzero boot status indicates the module has finished - * booting. Clear it. + * A nonzero init status indicates the module has finished + * initializing. */ if (!value) { - dev_err(&intf->dev, "Module not ready yet\n"); + dev_err(&intf->dev, "invalid init status\n"); return -ENODEV; } /* - * Check if the module needs to boot from UniPro. + * Check if the interface needs to boot over UniPro. + * * For ES2: We need to check lowest 8 bits of 'value'. * For ES3: We need to check highest 8 bits out of 32 of 'value'. - * FIXME: Remove ES2 support from the kernel entirely. + * + * FIXME: Remove ES2 support */ - if (intf->ddbl1_manufacturer_id == ES2_DDBL1_MFR_ID && - intf->ddbl1_product_id == ES2_DDBL1_PROD_ID) + if (es2_bridge) init_status = value & 0xff; else init_status = value >> 24; @@ -68,6 +71,7 @@ static int gb_interface_read_and_clear_boot_status(struct gb_interface *intf) init_status == DME_DIS_FALLBACK_UNIPRO_BOOT_STARTED) intf->boot_over_unipro = true; + /* Clear the init status. */ return gb_svc_dme_peer_set(hd->svc, intf->interface_id, attr, DME_ATTR_SELECTOR_INDEX, 0); } @@ -210,9 +214,9 @@ int gb_interface_enable(struct gb_interface *intf) int ret, size; void *manifest; - ret = gb_interface_read_and_clear_boot_status(intf); + ret = gb_interface_read_and_clear_init_status(intf); if (ret) { - dev_err(&intf->dev, "failed to clear boot status: %d\n", ret); + dev_err(&intf->dev, "failed to clear init status: %d\n", ret); return ret; } -- cgit v0.10.2 From ec199ccdd2a3c215f5088052377f08a5855f560e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 29 Mar 2016 18:56:03 -0400 Subject: greybus: interface: clean up ES3-bootroom-quirk handling Clean up handling of the ES3-bootrom quirks by adding an interface quirk-flags field that is set appropriately when we detect that the ES3 bootrom is running. Note that we need to reserve the DME_DIS_UNIPRO_BOOT_STARTED and DME_DIS_FALLBACK_UNIPRO_BOOT_STARTED status values for the ES3 bootrom, which does not support any CPort features (unlike later boot stages). Add a BOOTROM infix to the defines to make this more clear. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 64fa20a..1880f8f 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -337,9 +337,12 @@ gb_connection_svc_connection_create(struct gb_connection *connection) intf = connection->intf; - /* The ES2/ES3 bootrom requires E2EFC, CSD and CSV to be disabled. */ + /* + * Enable either E2EFC or CSD, unless the interface does not support + * any CPort features. + */ cport_flags = GB_SVC_CPORT_FLAG_CSV_N; - if (intf->boot_over_unipro) { + if (intf->quirks & GB_INTERFACE_QUIRK_NO_CPORT_FEATURES) { cport_flags |= GB_SVC_CPORT_FLAG_CSD_N; } else if (gb_connection_e2efc_enabled(connection)) { cport_flags |= GB_SVC_CPORT_FLAG_CSD_N | diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index 83be255..8475f15 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -155,8 +155,7 @@ int gb_control_get_interface_version_operation(struct gb_interface *intf) struct gb_connection *connection = intf->control->connection; int ret; - /* The ES3 bootrom fails to boot if this request it sent to it */ - if (intf->boot_over_unipro) + if (intf->quirks & GB_INTERFACE_QUIRK_NO_INTERFACE_VERSION) return 0; ret = gb_operation_sync(connection, GB_CONTROL_TYPE_INTERFACE_VERSION, diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 31e772a..8370cfe 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -894,11 +894,11 @@ struct gb_svc_dme_peer_set_response { #define DME_ATTR_ES3_INIT_STATUS 0x6101 /* Return value from init-status attributes listed above */ -#define DME_DIS_SPI_BOOT_STARTED 0x02 -#define DME_DIS_TRUSTED_SPI_BOOT_FINISHED 0x03 -#define DME_DIS_UNTRUSTED_SPI_BOOT_FINISHED 0x04 -#define DME_DIS_UNIPRO_BOOT_STARTED 0x06 -#define DME_DIS_FALLBACK_UNIPRO_BOOT_STARTED 0x09 +#define DME_DIS_SPI_BOOT_STARTED 0x02 +#define DME_DIS_TRUSTED_SPI_BOOT_FINISHED 0x03 +#define DME_DIS_UNTRUSTED_SPI_BOOT_FINISHED 0x04 +#define DME_DIS_BOOTROM_UNIPRO_BOOT_STARTED 0x06 +#define DME_DIS_BOOTROM_FALLBACK_UNIPRO_BOOT_STARTED 0x09 struct gb_svc_route_create_request { __u8 intf1_id; diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 569403c..a13b221 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -55,7 +55,7 @@ static int gb_interface_read_and_clear_init_status(struct gb_interface *intf) } /* - * Check if the interface needs to boot over UniPro. + * Extract the init status. * * For ES2: We need to check lowest 8 bits of 'value'. * For ES3: We need to check highest 8 bits out of 32 of 'value'. @@ -67,9 +67,18 @@ static int gb_interface_read_and_clear_init_status(struct gb_interface *intf) else init_status = value >> 24; - if (init_status == DME_DIS_UNIPRO_BOOT_STARTED || - init_status == DME_DIS_FALLBACK_UNIPRO_BOOT_STARTED) - intf->boot_over_unipro = true; + /* + * Check if the interface is executing the quirky ES3 bootrom that + * requires E2EFC, CSD and CSV to be disabled and that does not + * support the interface-version request. + */ + switch (init_status) { + case DME_DIS_BOOTROM_UNIPRO_BOOT_STARTED: + case DME_DIS_BOOTROM_FALLBACK_UNIPRO_BOOT_STARTED: + intf->quirks |= GB_INTERFACE_QUIRK_NO_CPORT_FEATURES; + intf->quirks |= GB_INTERFACE_QUIRK_NO_INTERFACE_VERSION; + break; + } /* Clear the init status. */ return gb_svc_dme_peer_set(hd->svc, intf->interface_id, attr, diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index d4c55ab..96caabc 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -10,6 +10,9 @@ #ifndef __INTERFACE_H #define __INTERFACE_H +#define GB_INTERFACE_QUIRK_NO_CPORT_FEATURES BIT(0) +#define GB_INTERFACE_QUIRK_NO_INTERFACE_VERSION BIT(1) + struct gb_interface { struct device dev; struct gb_control *control; @@ -36,8 +39,8 @@ struct gb_interface { struct gb_host_device *hd; - /* The interface needs to boot over unipro */ - bool boot_over_unipro; + unsigned long quirks; + bool disconnected; }; #define to_gb_interface(d) container_of(d, struct gb_interface, dev) -- cgit v0.10.2 From 4d5f6218886e5d363cf41af5c5a51045f2722e50 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 29 Mar 2016 18:56:04 -0400 Subject: greybus: interface: move route creation to interface activation Creating and destroying a route to an interface is arguably an interface operation and belongs with the interface code. Add new interface_activate and interface_deactivate helpers that will be used to activate and deactivate an interface in the new interface boot sequence. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index a13b221..48f64fb 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -10,6 +10,71 @@ #include "greybus.h" +static int gb_interface_route_create(struct gb_interface *intf) +{ + struct gb_svc *svc = intf->hd->svc; + u8 intf_id = intf->interface_id; + u8 device_id; + int ret; + + /* + * Create a device id for the interface: + * - device id 0 (GB_DEVICE_ID_SVC) belongs to the SVC + * - device id 1 (GB_DEVICE_ID_AP) belongs to the AP + * + * XXX Do we need to allocate device ID for SVC or the AP here? And what + * XXX about an AP with multiple interface blocks? + */ + ret = ida_simple_get(&svc->device_id_map, + GB_DEVICE_ID_MODULES_START, 0, GFP_KERNEL); + if (ret < 0) { + dev_err(&intf->dev, "failed to allocate device id: %d\n", ret); + return ret; + } + device_id = ret; + + ret = gb_svc_intf_device_id(svc, intf_id, device_id); + if (ret) { + dev_err(&intf->dev, "failed to set device id %u: %d\n", + device_id, ret); + goto err_ida_remove; + } + + /* Create a two-way route between the AP and the new interface. */ + ret = gb_svc_route_create(svc, svc->ap_intf_id, GB_DEVICE_ID_AP, + intf_id, device_id); + if (ret) { + dev_err(&intf->dev, "failed to create route: %d\n", ret); + goto err_svc_id_free; + } + + intf->device_id = device_id; + + return 0; + +err_svc_id_free: + /* + * XXX Should we tell SVC that this id doesn't belong to interface + * XXX anymore. + */ +err_ida_remove: + ida_simple_remove(&svc->device_id_map, device_id); + + return ret; +} + +static void gb_interface_route_destroy(struct gb_interface *intf) +{ + struct gb_svc *svc = intf->hd->svc; + + if (intf->device_id == GB_DEVICE_ID_BAD) + return; + + gb_svc_route_destroy(svc, svc->ap_intf_id, intf->interface_id); + ida_simple_remove(&svc->device_id_map, intf->device_id); + intf->device_id = GB_DEVICE_ID_BAD; +} + /* * T_TstSrcIncrement is written by the module on ES2 as a stand-in for the * init-status attribute ES3_INIT_STATUS. The AP needs to read and clear it @@ -213,6 +278,22 @@ struct gb_interface *gb_interface_create(struct gb_host_device *hd, return intf; } +int gb_interface_activate(struct gb_interface *intf) +{ + int ret; + + ret = gb_interface_route_create(intf); + if (ret) + return ret; + + return 0; +} + +void gb_interface_deactivate(struct gb_interface *intf) +{ + gb_interface_route_destroy(intf); +} + /* * Enable an interface by enabling its control connection and fetching the * manifest and other information over it. diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 96caabc..5dfaea5 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -50,6 +50,8 @@ struct gb_interface *gb_interface_find(struct gb_host_device *hd, struct gb_interface *gb_interface_create(struct gb_host_device *hd, u8 interface_id); +int gb_interface_activate(struct gb_interface *intf); +void gb_interface_deactivate(struct gb_interface *intf); int gb_interface_enable(struct gb_interface *intf); void gb_interface_disable(struct gb_interface *intf); int gb_interface_add(struct gb_interface *intf); diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index ca2f34e..5c517d7 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -108,7 +108,7 @@ static struct attribute *svc_attrs[] = { }; ATTRIBUTE_GROUPS(svc); -static int gb_svc_intf_device_id(struct gb_svc *svc, u8 intf_id, u8 device_id) +int gb_svc_intf_device_id(struct gb_svc *svc, u8 intf_id, u8 device_id) { struct gb_svc_intf_device_id_request request; @@ -251,7 +251,7 @@ void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, EXPORT_SYMBOL_GPL(gb_svc_connection_destroy); /* Creates bi-directional routes between the devices */ -static int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, +int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, u8 intf2_id, u8 dev2_id) { struct gb_svc_route_create_request request; @@ -266,7 +266,7 @@ static int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, } /* Destroys bi-directional routes between the devices */ -static void gb_svc_route_destroy(struct gb_svc *svc, u8 intf1_id, u8 intf2_id) +void gb_svc_route_destroy(struct gb_svc *svc, u8 intf1_id, u8 intf2_id) { struct gb_svc_route_destroy_request request; int ret; @@ -397,78 +397,12 @@ static int gb_svc_hello(struct gb_operation *op) return 0; } -static int gb_svc_interface_route_create(struct gb_svc *svc, - struct gb_interface *intf) -{ - u8 intf_id = intf->interface_id; - u8 device_id; - int ret; - - /* - * Create a device id for the interface: - * - device id 0 (GB_DEVICE_ID_SVC) belongs to the SVC - * - device id 1 (GB_DEVICE_ID_AP) belongs to the AP - * - * XXX Do we need to allocate device ID for SVC or the AP here? And what - * XXX about an AP with multiple interface blocks? - */ - ret = ida_simple_get(&svc->device_id_map, - GB_DEVICE_ID_MODULES_START, 0, GFP_KERNEL); - if (ret < 0) { - dev_err(&svc->dev, "failed to allocate device id for interface %u: %d\n", - intf_id, ret); - return ret; - } - device_id = ret; - - ret = gb_svc_intf_device_id(svc, intf_id, device_id); - if (ret) { - dev_err(&svc->dev, "failed to set device id %u for interface %u: %d\n", - device_id, intf_id, ret); - goto err_ida_remove; - } - - /* Create a two-way route between the AP and the new interface. */ - ret = gb_svc_route_create(svc, svc->ap_intf_id, GB_DEVICE_ID_AP, - intf_id, device_id); - if (ret) { - dev_err(&svc->dev, "failed to create route to interface %u (device id %u): %d\n", - intf_id, device_id, ret); - goto err_svc_id_free; - } - - intf->device_id = device_id; - - return 0; - -err_svc_id_free: - /* - * XXX Should we tell SVC that this id doesn't belong to interface - * XXX anymore. - */ -err_ida_remove: - ida_simple_remove(&svc->device_id_map, device_id); - - return ret; -} - -static void gb_svc_interface_route_destroy(struct gb_svc *svc, - struct gb_interface *intf) -{ - if (intf->device_id == GB_DEVICE_ID_BAD) - return; - - gb_svc_route_destroy(svc, svc->ap_intf_id, intf->interface_id); - ida_simple_remove(&svc->device_id_map, intf->device_id); - intf->device_id = GB_DEVICE_ID_BAD; -} - static void gb_svc_intf_remove(struct gb_svc *svc, struct gb_interface *intf) { intf->disconnected = true; gb_interface_disable(intf); - gb_svc_interface_route_destroy(svc, intf); + gb_interface_deactivate(intf); gb_interface_remove(intf); } @@ -546,9 +480,12 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) intf->product_id = product_id; } - ret = gb_svc_interface_route_create(svc, intf); - if (ret) + ret = gb_interface_activate(intf); + if (ret) { + dev_err(&svc->dev, "failed to activate interface %u: %d\n", + intf_id, ret); goto out_interface_add; + } ret = gb_interface_enable(intf); if (ret) { diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index 904b2dd..8950baf 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -48,6 +48,10 @@ int gb_svc_add(struct gb_svc *svc); void gb_svc_del(struct gb_svc *svc); void gb_svc_put(struct gb_svc *svc); +int gb_svc_intf_device_id(struct gb_svc *svc, u8 intf_id, u8 device_id); +int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, + u8 intf2_id, u8 dev2_id); +void gb_svc_route_destroy(struct gb_svc *svc, u8 intf1_id, u8 intf2_id); int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id, u8 cport_flags); void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, -- cgit v0.10.2 From 984c9d38ae370993f28b36c8be9923b1de39f5e7 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 29 Mar 2016 18:56:05 -0400 Subject: greybus: interface: deactivate interface on enumeration failure Deactivate an interface immediately on enumeration failure. Note that an interface is always registered. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 5c517d7..96d3d55 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -484,17 +484,23 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) if (ret) { dev_err(&svc->dev, "failed to activate interface %u: %d\n", intf_id, ret); - goto out_interface_add; + goto err_interface_add; } ret = gb_interface_enable(intf); if (ret) { dev_err(&svc->dev, "failed to enable interface %u: %d\n", intf_id, ret); - goto out_interface_add; + goto err_interface_deactivate; } -out_interface_add: + gb_interface_add(intf); + + return; + +err_interface_deactivate: + gb_interface_deactivate(intf); +err_interface_add: gb_interface_add(intf); } -- cgit v0.10.2 From e9f2f688d1a9434f615eec7180f14f0c52941bb9 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 29 Mar 2016 18:56:06 -0400 Subject: greybus: interface: clean up device-id handling Clean up the device id-handling and make sure we never allocate invalid device ids due to a missing upper bound. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/bundle.h b/drivers/staging/greybus/bundle.h index 18b125e8..2dc61ab 100644 --- a/drivers/staging/greybus/bundle.h +++ b/drivers/staging/greybus/bundle.h @@ -32,8 +32,6 @@ struct gb_bundle { }; #define to_gb_bundle(d) container_of(d, struct gb_bundle, dev) -#define GB_DEVICE_ID_BAD 0xff - /* Greybus "private" definitions" */ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, u8 class); diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 8370cfe..2e126e6 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -54,10 +54,11 @@ /* Fixed IDs for control/svc protocols */ -/* Device ID of SVC and AP */ -#define GB_DEVICE_ID_SVC 0 -#define GB_DEVICE_ID_AP 1 -#define GB_DEVICE_ID_MODULES_START 2 +/* SVC switch-port device ids */ +#define GB_SVC_DEVICE_ID_SVC 0 +#define GB_SVC_DEVICE_ID_AP 1 +#define GB_SVC_DEVICE_ID_MIN 2 +#define GB_SVC_DEVICE_ID_MAX 31 #define GB_SVC_CPORT_ID 0 #define GB_CONTROL_BUNDLE_ID 0 diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 48f64fb..7e7bcda 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -10,6 +10,9 @@ #include "greybus.h" +#define GB_INTERFACE_DEVICE_ID_BAD 0xff + + static int gb_interface_route_create(struct gb_interface *intf) { struct gb_svc *svc = intf->hd->svc; @@ -17,16 +20,10 @@ static int gb_interface_route_create(struct gb_interface *intf) u8 device_id; int ret; - /* - * Create a device id for the interface: - * - device id 0 (GB_DEVICE_ID_SVC) belongs to the SVC - * - device id 1 (GB_DEVICE_ID_AP) belongs to the AP - * - * XXX Do we need to allocate device ID for SVC or the AP here? And what - * XXX about an AP with multiple interface blocks? - */ + /* Allocate an interface device id. */ ret = ida_simple_get(&svc->device_id_map, - GB_DEVICE_ID_MODULES_START, 0, GFP_KERNEL); + GB_SVC_DEVICE_ID_MIN, GB_SVC_DEVICE_ID_MAX + 1, + GFP_KERNEL); if (ret < 0) { dev_err(&intf->dev, "failed to allocate device id: %d\n", ret); return ret; @@ -40,8 +37,8 @@ static int gb_interface_route_create(struct gb_interface *intf) goto err_ida_remove; } - /* Create a two-way route between the AP and the new interface. */ - ret = gb_svc_route_create(svc, svc->ap_intf_id, GB_DEVICE_ID_AP, + /* FIXME: Hard-coded AP device id. */ + ret = gb_svc_route_create(svc, svc->ap_intf_id, GB_SVC_DEVICE_ID_AP, intf_id, device_id); if (ret) { dev_err(&intf->dev, "failed to create route: %d\n", ret); @@ -67,12 +64,12 @@ static void gb_interface_route_destroy(struct gb_interface *intf) { struct gb_svc *svc = intf->hd->svc; - if (intf->device_id == GB_DEVICE_ID_BAD) + if (intf->device_id == GB_INTERFACE_DEVICE_ID_BAD) return; gb_svc_route_destroy(svc, svc->ap_intf_id, intf->interface_id); ida_simple_remove(&svc->device_id_map, intf->device_id); - intf->device_id = GB_DEVICE_ID_BAD; + intf->device_id = GB_INTERFACE_DEVICE_ID_BAD; } /* @@ -257,7 +254,7 @@ struct gb_interface *gb_interface_create(struct gb_host_device *hd, INIT_LIST_HEAD(&intf->manifest_descs); /* Invalid device id to start with */ - intf->device_id = GB_DEVICE_ID_BAD; + intf->device_id = GB_INTERFACE_DEVICE_ID_BAD; intf->dev.parent = &hd->dev; intf->dev.bus = &greybus_bus_type; diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 5dfaea5..8b6fcfe 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -21,7 +21,7 @@ struct gb_interface { struct list_head links; /* gb_host_device->interfaces */ struct list_head manifest_descs; u8 interface_id; /* Physical location within the Endo */ - u8 device_id; /* Device id allocated for the interface block by the SVC */ + u8 device_id; /* Information taken from the manifest descriptor */ char *vendor_string; -- cgit v0.10.2 From af1471e7a903c18e98adf49fc9e2e444915b48c8 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 29 Mar 2016 18:56:07 -0400 Subject: greybus: greybus_protocols: rename NULL DME selector index Add NULL suffix to the don't-care DME selector index. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 2e126e6..0a7427e 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -889,7 +889,7 @@ struct gb_svc_dme_peer_set_response { } __packed; /* Attributes for peer get/set operations */ -#define DME_ATTR_SELECTOR_INDEX 0 +#define DME_ATTR_SELECTOR_INDEX_NULL 0 /* FIXME: remove ES2 support and DME_ATTR_T_TST_SRC_INCREMENT */ #define DME_ATTR_T_TST_SRC_INCREMENT 0x4083 #define DME_ATTR_ES3_INIT_STATUS 0x6101 diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 7e7bcda..823debb 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -103,7 +103,7 @@ static int gb_interface_read_and_clear_init_status(struct gb_interface *intf) attr = DME_ATTR_ES3_INIT_STATUS; ret = gb_svc_dme_peer_get(hd->svc, intf->interface_id, attr, - DME_ATTR_SELECTOR_INDEX, &value); + DME_ATTR_SELECTOR_INDEX_NULL, &value); if (ret) return ret; @@ -144,7 +144,7 @@ static int gb_interface_read_and_clear_init_status(struct gb_interface *intf) /* Clear the init status. */ return gb_svc_dme_peer_set(hd->svc, intf->interface_id, attr, - DME_ATTR_SELECTOR_INDEX, 0); + DME_ATTR_SELECTOR_INDEX_NULL, 0); } /* interface sysfs attributes */ -- cgit v0.10.2 From 153ff7e76ddb2fd5ab3d790c0139154dfd5464f1 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 29 Mar 2016 18:56:08 -0400 Subject: greybus: interface: read DME attributes at activation Read the DDBL1 and Ara DME attributes when activating an interface. These values are currently provided by the SVC in the intf_hotplug request, which is about to go away. Note that there are currently no standard Ara VID and PID attributes and that Toshiba uses attributes from the reserved space in ES3. For now, we therefore refuse to enumerate any non-Toshiba bridges. Also note that the Ara serial number is currently not supported. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 823debb..c7793a9 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -12,6 +12,74 @@ #define GB_INTERFACE_DEVICE_ID_BAD 0xff +/* DME attributes */ +#define DME_DDBL1_MANUFACTURERID 0x5003 +#define DME_DDBL1_PRODUCTID 0x5004 + +#define DME_TOSHIBA_ARA_VID 0x6000 +#define DME_TOSHIBA_ARA_PID 0x6001 + +/* DDBL1 Manufacturer and Product ids */ +#define TOSHIBA_DMID 0x0126 +#define TOSHIBA_ES2_BRIDGE_DPID 0x1000 +#define TOSHIBA_ES3_APBRIDGE_DPID 0x1001 +#define TOSHIBA_ES3_GPBRIDGE_DPID 0x1002 + + +static int gb_interface_dme_attr_get(struct gb_interface *intf, + u16 attr, u32 *val) +{ + return gb_svc_dme_peer_get(intf->hd->svc, intf->interface_id, + attr, DME_ATTR_SELECTOR_INDEX_NULL, + val); +} + +static int gb_interface_read_ara_dme(struct gb_interface *intf) +{ + int ret; + + /* + * Unless this is a Toshiba bridge, bail out until we have defined + * standard Ara attributes. + */ + if (intf->ddbl1_manufacturer_id != TOSHIBA_DMID) { + dev_err(&intf->dev, "unknown manufacturer %08x\n", + intf->ddbl1_manufacturer_id); + return -ENODEV; + } + + ret = gb_interface_dme_attr_get(intf, DME_TOSHIBA_ARA_VID, + &intf->vendor_id); + if (ret) + return ret; + + ret = gb_interface_dme_attr_get(intf, DME_TOSHIBA_ARA_PID, + &intf->product_id); + if (ret) + return ret; + + /* FIXME: serial number not implemented */ + intf->serial_number = 0; + + return 0; +} + +static int gb_interface_read_dme(struct gb_interface *intf) +{ + int ret; + + ret = gb_interface_dme_attr_get(intf, DME_DDBL1_MANUFACTURERID, + &intf->ddbl1_manufacturer_id); + if (ret) + return ret; + + ret = gb_interface_dme_attr_get(intf, DME_DDBL1_PRODUCTID, + &intf->ddbl1_product_id); + if (ret) + return ret; + + return gb_interface_read_ara_dme(intf); +} static int gb_interface_route_create(struct gb_interface *intf) { @@ -279,6 +347,10 @@ int gb_interface_activate(struct gb_interface *intf) { int ret; + ret = gb_interface_read_dme(intf); + if (ret) + return ret; + ret = gb_interface_route_create(intf); if (ret) return ret; diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 8b6fcfe..1a6ce5c 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -27,7 +27,6 @@ struct gb_interface { char *vendor_string; char *product_string; - /* Information taken from the hotplug event */ u32 ddbl1_manufacturer_id; u32 ddbl1_product_id; u32 vendor_id; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 96d3d55..0659815 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -460,11 +460,12 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) return; } - intf->ddbl1_manufacturer_id = le32_to_cpu(request->data.ddbl1_mfr_id); - intf->ddbl1_product_id = le32_to_cpu(request->data.ddbl1_prod_id); - intf->vendor_id = le32_to_cpu(request->data.ara_vend_id); - intf->product_id = le32_to_cpu(request->data.ara_prod_id); - intf->serial_number = le64_to_cpu(request->data.serial_number); + ret = gb_interface_activate(intf); + if (ret) { + dev_err(&svc->dev, "failed to activate interface %u: %d\n", + intf_id, ret); + goto err_interface_add; + } /* * Use VID/PID specified at hotplug if: @@ -480,13 +481,6 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) intf->product_id = product_id; } - ret = gb_interface_activate(intf); - if (ret) { - dev_err(&svc->dev, "failed to activate interface %u: %d\n", - intf_id, ret); - goto err_interface_add; - } - ret = gb_interface_enable(intf); if (ret) { dev_err(&svc->dev, "failed to enable interface %u: %d\n", -- cgit v0.10.2 From 7d7acc06a0febf9f08649df52aa267b8f74b0de9 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 29 Mar 2016 18:56:09 -0400 Subject: greybus: interface: add ES2 init-status quirk flag Add ES2 init-status quirk flag instead of checking MID/PID directly. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index c7793a9..767bf87 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -78,6 +78,11 @@ static int gb_interface_read_dme(struct gb_interface *intf) if (ret) return ret; + if (intf->ddbl1_manufacturer_id == TOSHIBA_DMID && + intf->ddbl1_product_id == TOSHIBA_ES2_BRIDGE_DPID) { + intf->quirks |= GB_INTERFACE_QUIRK_NO_INIT_STATUS; + } + return gb_interface_read_ara_dme(intf); } @@ -155,17 +160,13 @@ static int gb_interface_read_and_clear_init_status(struct gb_interface *intf) u32 value; u16 attr; u8 init_status; - bool es2_bridge; - - es2_bridge = intf->ddbl1_manufacturer_id == ES2_DDBL1_MFR_ID && - intf->ddbl1_product_id == ES2_DDBL1_PROD_ID; /* * ES2 bridges use T_TstSrcIncrement for the init status. * * FIXME: Remove ES2 support */ - if (es2_bridge) + if (intf->quirks & GB_INTERFACE_QUIRK_NO_INIT_STATUS) attr = DME_ATTR_T_TST_SRC_INCREMENT; else attr = DME_ATTR_ES3_INIT_STATUS; @@ -192,7 +193,7 @@ static int gb_interface_read_and_clear_init_status(struct gb_interface *intf) * * FIXME: Remove ES2 support */ - if (es2_bridge) + if (intf->quirks & GB_INTERFACE_QUIRK_NO_INIT_STATUS) init_status = value & 0xff; else init_status = value >> 24; diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 1a6ce5c..94eb36e 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -12,6 +12,7 @@ #define GB_INTERFACE_QUIRK_NO_CPORT_FEATURES BIT(0) #define GB_INTERFACE_QUIRK_NO_INTERFACE_VERSION BIT(1) +#define GB_INTERFACE_QUIRK_NO_INIT_STATUS BIT(2) struct gb_interface { struct device dev; -- cgit v0.10.2 From ac72cfbe6937f00c1fb334001c89ea26254ef430 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 29 Mar 2016 18:56:10 -0400 Subject: greybus: interface: clean up ES2 VID/PID hack Clean up the ES2 VID/PID hack using a new quirk flag. Note that the hack is now used if and only if the interface is a Toshiba ES2 bridge (and not if the attributes read zero). Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/firmware.c b/drivers/staging/greybus/firmware.c index b1188b2..b1e373c 100644 --- a/drivers/staging/greybus/firmware.c +++ b/drivers/staging/greybus/firmware.c @@ -43,14 +43,7 @@ static void firmware_es2_fixup_vid_pid(struct gb_firmware *firmware) struct gb_interface *intf = connection->bundle->intf; int ret; - /* - * Use VID/PID specified at hotplug if: - * - Bridge ASIC chip isn't ES2 - * - Received non-zero Vendor/Product ids - */ - if (intf->ddbl1_manufacturer_id != ES2_DDBL1_MFR_ID || - intf->ddbl1_product_id != ES2_DDBL1_PROD_ID || - intf->vendor_id != 0 || intf->product_id != 0) + if (!(intf->quirks & GB_INTERFACE_QUIRK_NO_ARA_IDS)) return; ret = gb_operation_sync(connection, GB_FIRMWARE_TYPE_GET_VID_PID, diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 0a7427e..bb7b01f 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -226,10 +226,6 @@ struct gb_control_timesync_authoritative_request { #define GB_FIRMWARE_TYPE_AP_READY 0x05 /* Request with no-payload */ #define GB_FIRMWARE_TYPE_GET_VID_PID 0x06 /* Request with no-payload */ -/* FIXME: remove all ES2-specific identifiers from the kernel */ -#define ES2_DDBL1_MFR_ID 0x00000126 -#define ES2_DDBL1_PROD_ID 0x00001000 - /* Greybus firmware boot stages */ #define GB_FIRMWARE_BOOT_STAGE_ONE 0x01 /* Reserved for the boot ROM */ #define GB_FIRMWARE_BOOT_STAGE_TWO 0x02 /* Firmware package to be loaded by the boot ROM */ diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 767bf87..bf29831 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -80,6 +80,7 @@ static int gb_interface_read_dme(struct gb_interface *intf) if (intf->ddbl1_manufacturer_id == TOSHIBA_DMID && intf->ddbl1_product_id == TOSHIBA_ES2_BRIDGE_DPID) { + intf->quirks |= GB_INTERFACE_QUIRK_NO_ARA_IDS; intf->quirks |= GB_INTERFACE_QUIRK_NO_INIT_STATUS; } diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 94eb36e..15c687f 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -13,6 +13,7 @@ #define GB_INTERFACE_QUIRK_NO_CPORT_FEATURES BIT(0) #define GB_INTERFACE_QUIRK_NO_INTERFACE_VERSION BIT(1) #define GB_INTERFACE_QUIRK_NO_INIT_STATUS BIT(2) +#define GB_INTERFACE_QUIRK_NO_ARA_IDS BIT(3) struct gb_interface { struct device dev; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 0659815..a19e575 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -426,11 +426,7 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) intf = gb_interface_find(hd, intf_id); if (intf) { - /* - * For ES2, we need to maintain the same vendor/product ids we - * got from bootrom, otherwise userspace can't distinguish - * between modules. - */ + /* HACK: Save Ara VID/PID for ES2 hack below */ vendor_id = intf->vendor_id; product_id = intf->product_id; @@ -468,15 +464,11 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) } /* - * Use VID/PID specified at hotplug if: - * - Bridge ASIC chip isn't ES2 - * - Received non-zero Vendor/Product ids + * HACK: Use Ara VID/PID from earlier boot stage. * - * Otherwise, use the ids we received from bootrom. + * FIXME: remove quirk with ES2 support */ - if (intf->ddbl1_manufacturer_id == ES2_DDBL1_MFR_ID && - intf->ddbl1_product_id == ES2_DDBL1_PROD_ID && - intf->vendor_id == 0 && intf->product_id == 0) { + if (intf->quirks & GB_INTERFACE_QUIRK_NO_ARA_IDS) { intf->vendor_id = vendor_id; intf->product_id = product_id; } -- cgit v0.10.2 From 50ad4163a54cb373012b330d078e4ad17b6e6c95 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 29 Mar 2016 18:56:11 -0400 Subject: greybus: interface: clean up DME attribute handling Move all DME defines to the interface code and rename them using common prefixes (e.g. DME_T and DME_TOSHIBA). The DDB L1 attributes are defined by MIPI and the Ara attributes are currently Toshiba specific so move them all out of the Greybus protocol header. Also rename the Greybus init-status values using a GB_INIT prefix. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index bb7b01f..06888e0 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -884,18 +884,12 @@ struct gb_svc_dme_peer_set_response { __le16 result_code; } __packed; -/* Attributes for peer get/set operations */ -#define DME_ATTR_SELECTOR_INDEX_NULL 0 -/* FIXME: remove ES2 support and DME_ATTR_T_TST_SRC_INCREMENT */ -#define DME_ATTR_T_TST_SRC_INCREMENT 0x4083 -#define DME_ATTR_ES3_INIT_STATUS 0x6101 - -/* Return value from init-status attributes listed above */ -#define DME_DIS_SPI_BOOT_STARTED 0x02 -#define DME_DIS_TRUSTED_SPI_BOOT_FINISHED 0x03 -#define DME_DIS_UNTRUSTED_SPI_BOOT_FINISHED 0x04 -#define DME_DIS_BOOTROM_UNIPRO_BOOT_STARTED 0x06 -#define DME_DIS_BOOTROM_FALLBACK_UNIPRO_BOOT_STARTED 0x09 +/* Greybus init-status values, currently retrieved using DME peer gets. */ +#define GB_INIT_SPI_BOOT_STARTED 0x02 +#define GB_INIT_TRUSTED_SPI_BOOT_FINISHED 0x03 +#define GB_INIT_UNTRUSTED_SPI_BOOT_FINISHED 0x04 +#define GB_INIT_BOOTROM_UNIPRO_BOOT_STARTED 0x06 +#define GB_INIT_BOOTROM_FALLBACK_UNIPRO_BOOT_STARTED 0x09 struct gb_svc_route_create_request { __u8 intf1_id; diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index bf29831..d0542e5 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -12,12 +12,19 @@ #define GB_INTERFACE_DEVICE_ID_BAD 0xff +/* Don't-care selector index */ +#define DME_SELECTOR_INDEX_NULL 0 + /* DME attributes */ +/* FIXME: remove ES2 support and DME_T_TST_SRC_INCREMENT */ +#define DME_T_TST_SRC_INCREMENT 0x4083 + #define DME_DDBL1_MANUFACTURERID 0x5003 #define DME_DDBL1_PRODUCTID 0x5004 #define DME_TOSHIBA_ARA_VID 0x6000 #define DME_TOSHIBA_ARA_PID 0x6001 +#define DME_TOSHIBA_ARA_INIT_STATUS 0x6101 /* DDBL1 Manufacturer and Product ids */ #define TOSHIBA_DMID 0x0126 @@ -30,8 +37,7 @@ static int gb_interface_dme_attr_get(struct gb_interface *intf, u16 attr, u32 *val) { return gb_svc_dme_peer_get(intf->hd->svc, intf->interface_id, - attr, DME_ATTR_SELECTOR_INDEX_NULL, - val); + attr, DME_SELECTOR_INDEX_NULL, val); } static int gb_interface_read_ara_dme(struct gb_interface *intf) @@ -148,8 +154,8 @@ static void gb_interface_route_destroy(struct gb_interface *intf) /* * T_TstSrcIncrement is written by the module on ES2 as a stand-in for the - * init-status attribute ES3_INIT_STATUS. The AP needs to read and clear it - * after reading a non-zero value from it. + * init-status attribute DME_TOSHIBA_INIT_STATUS. The AP needs to read and + * clear it after reading a non-zero value from it. * * FIXME: This is module-hardware dependent and needs to be extended for every * type of module we want to support. @@ -168,12 +174,12 @@ static int gb_interface_read_and_clear_init_status(struct gb_interface *intf) * FIXME: Remove ES2 support */ if (intf->quirks & GB_INTERFACE_QUIRK_NO_INIT_STATUS) - attr = DME_ATTR_T_TST_SRC_INCREMENT; + attr = DME_T_TST_SRC_INCREMENT; else - attr = DME_ATTR_ES3_INIT_STATUS; + attr = DME_TOSHIBA_ARA_INIT_STATUS; ret = gb_svc_dme_peer_get(hd->svc, intf->interface_id, attr, - DME_ATTR_SELECTOR_INDEX_NULL, &value); + DME_SELECTOR_INDEX_NULL, &value); if (ret) return ret; @@ -205,8 +211,8 @@ static int gb_interface_read_and_clear_init_status(struct gb_interface *intf) * support the interface-version request. */ switch (init_status) { - case DME_DIS_BOOTROM_UNIPRO_BOOT_STARTED: - case DME_DIS_BOOTROM_FALLBACK_UNIPRO_BOOT_STARTED: + case GB_INIT_BOOTROM_UNIPRO_BOOT_STARTED: + case GB_INIT_BOOTROM_FALLBACK_UNIPRO_BOOT_STARTED: intf->quirks |= GB_INTERFACE_QUIRK_NO_CPORT_FEATURES; intf->quirks |= GB_INTERFACE_QUIRK_NO_INTERFACE_VERSION; break; @@ -214,7 +220,7 @@ static int gb_interface_read_and_clear_init_status(struct gb_interface *intf) /* Clear the init status. */ return gb_svc_dme_peer_set(hd->svc, intf->interface_id, attr, - DME_ATTR_SELECTOR_INDEX_NULL, 0); + DME_SELECTOR_INDEX_NULL, 0); } /* interface sysfs attributes */ -- cgit v0.10.2 From a7be84613acc4f732f3aa9ab28da7e2e3a6bab0b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 29 Mar 2016 18:56:12 -0400 Subject: greybus: interface: add Ara serial-number support Add support for reading the Ara serial-number attributes. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index d0542e5..27dbd79 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -24,6 +24,8 @@ #define DME_TOSHIBA_ARA_VID 0x6000 #define DME_TOSHIBA_ARA_PID 0x6001 +#define DME_TOSHIBA_ARA_SN0 0x6002 +#define DME_TOSHIBA_ARA_SN1 0x6003 #define DME_TOSHIBA_ARA_INIT_STATUS 0x6101 /* DDBL1 Manufacturer and Product ids */ @@ -42,6 +44,7 @@ static int gb_interface_dme_attr_get(struct gb_interface *intf, static int gb_interface_read_ara_dme(struct gb_interface *intf) { + u32 sn0, sn1; int ret; /* @@ -64,8 +67,15 @@ static int gb_interface_read_ara_dme(struct gb_interface *intf) if (ret) return ret; - /* FIXME: serial number not implemented */ - intf->serial_number = 0; + ret = gb_interface_dme_attr_get(intf, DME_TOSHIBA_ARA_SN0, &sn0); + if (ret) + return ret; + + ret = gb_interface_dme_attr_get(intf, DME_TOSHIBA_ARA_SN1, &sn1); + if (ret) + return ret; + + intf->serial_number = (u64)sn1 << 32 | sn0; return 0; } -- cgit v0.10.2 From 1472ec67f734d9707d4758fddd4787113fe0b0b2 Mon Sep 17 00:00:00 2001 From: Gjorgji Rosikopulos Date: Thu, 31 Mar 2016 14:12:45 +0300 Subject: greybus: camera: Use pointer for gb camera module ops No need to duplicate module ops on every registration. NOTE: Change should be along merged with: "msm: camera: Change gb_camera_module ops to pointer" Signed-off-by: Gjorgji Rosikopulos Reviewed-by: Laurent Pinchart Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index a871b0f..2de91d5 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -498,23 +498,30 @@ static int gb_camera_op_capture(void *priv, u32 request_id, unsigned int streams, unsigned int num_frames, size_t settings_size, const void *settings) { - return gb_camera_capture(priv, request_id, streams, num_frames, + struct gb_camera *gcam = priv; + + return gb_camera_capture(gcam, request_id, streams, num_frames, settings_size, settings); } static int gb_camera_op_flush(void *priv, u32 *request_id) { - return gb_camera_flush(priv, request_id); + struct gb_camera *gcam = priv; + + return gb_camera_flush(gcam, request_id); } +static const struct gb_camera_ops gb_cam_ops = { + .capabilities = gb_camera_op_capabilities, + .configure_streams = gb_camera_op_configure_streams, + .capture = gb_camera_op_capture, + .flush = gb_camera_op_flush, +}; + static int gb_camera_register_intf_ops(struct gb_camera *gcam) { gcam->module.priv = gcam; - gcam->module.ops.capabilities = gb_camera_op_capabilities; - gcam->module.ops.configure_streams = gb_camera_op_configure_streams; - gcam->module.ops.capture = gb_camera_op_capture; - gcam->module.ops.flush = gb_camera_op_flush; - + gcam->module.ops = &gb_cam_ops; return gb_camera_register(&gcam->module); } diff --git a/drivers/staging/greybus/gb-camera.h b/drivers/staging/greybus/gb-camera.h index 0a48a16..273b4fa 100644 --- a/drivers/staging/greybus/gb-camera.h +++ b/drivers/staging/greybus/gb-camera.h @@ -36,14 +36,14 @@ struct gb_camera_ops { struct gb_camera_module { void *priv; - struct gb_camera_ops ops; + const struct gb_camera_ops *ops; struct list_head list; /* Global list */ }; #define gb_camera_call(f, op, args...) \ - ((!(f) ? -ENODEV : ((f)->ops.op) ? \ - (f)->ops.op((f)->priv, ##args) : -ENOIOCTLCMD)) + (!(f) ? -ENODEV : (((f)->ops->op) ? \ + (f)->ops->op((f)->priv, ##args) : -ENOIOCTLCMD)) int gb_camera_register(struct gb_camera_module *module); int gb_camera_unregister(struct gb_camera_module *module); -- cgit v0.10.2 From 6da549ec851117293a07e64f97170f7dc9d55578 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal Date: Tue, 29 Mar 2016 16:32:35 +0530 Subject: greybus: audio: Fix widget pointer update during control parsing widget pointer was incorrectly modfied while parsing kcontrol Signed-off-by: Vaibhav Agarwal Reviewed-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index 4901348..9e36fb2 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -834,7 +834,7 @@ static int gbaudio_tplg_process_widgets(struct gbaudio_module_info *module, list_add(&widget->list, &module->widget_list); ncontrols = curr->ncontrols; curr++; - curr += ncontrols * sizeof(struct gb_audio_control); + curr = (void *)curr + ncontrols*sizeof(struct gb_audio_control); } module->dapm_widgets = dapm_widgets; -- cgit v0.10.2 From 64a7e2cceb75ccabaec713944a95511605751b29 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal Date: Tue, 29 Mar 2016 16:32:36 +0530 Subject: greybus: audio: Added jack support to audio module Register jack with ASoC sound card in case audio module populates it via codec FW. Currently, only a single jack with 4 buttons can be registered for each module. Signed-off-by: Vaibhav Agarwal Reviewed-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 803bab2..66a9548 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "audio_codec.h" #include "audio_apbridgea.h" @@ -735,10 +736,80 @@ static struct snd_soc_dai_ops gbcodec_dai_ops = { .digital_mute = gbcodec_digital_mute, }; +static int gbaudio_init_jack(struct gbaudio_module_info *module, + struct snd_soc_codec *codec) +{ + int ret; + + if (!module->num_jacks) + return 0; + + /* register jack(s) in case any */ + if (module->num_jacks > 1) { + dev_err(module->dev, "Currently supports max=1 jack\n"); + return -EINVAL; + } + + snprintf(module->jack_name, NAME_SIZE, "GB %d Headset Jack", + module->dev_id); + ret = snd_soc_jack_new(codec, module->jack_name, GBCODEC_JACK_MASK, + &module->headset_jack); + if (ret) { + dev_err(module->dev, "Failed to create new jack\n"); + return ret; + } + + snprintf(module->button_name, NAME_SIZE, "GB %d Button Jack", + module->dev_id); + ret = snd_soc_jack_new(codec, module->button_name, + GBCODEC_JACK_BUTTON_MASK, &module->button_jack); + if (ret) { + dev_err(module->dev, "Failed to create button jack\n"); + return ret; + } + + ret = snd_jack_set_key(module->button_jack.jack, SND_JACK_BTN_0, + KEY_MEDIA); + if (ret) { + dev_err(module->dev, "Failed to set BTN_0\n"); + return ret; + } + + ret = snd_jack_set_key(module->button_jack.jack, SND_JACK_BTN_1, + KEY_VOICECOMMAND); + if (ret) { + dev_err(module->dev, "Failed to set BTN_1\n"); + return ret; + } + + ret = snd_jack_set_key(module->button_jack.jack, SND_JACK_BTN_2, + KEY_VOLUMEUP); + if (ret) { + dev_err(module->dev, "Failed to set BTN_2\n"); + return ret; + } + + ret = snd_jack_set_key(module->button_jack.jack, SND_JACK_BTN_3, + KEY_VOLUMEDOWN); + if (ret) { + dev_err(module->dev, "Failed to set BTN_0\n"); + return ret; + } + + /* FIXME + * verify if this is really required + set_bit(INPUT_PROP_NO_DUMMY_RELEASE, + module->button_jack.jack->input_dev->propbit); + */ + + return 0; +} + int gbaudio_register_module(struct gbaudio_module_info *module) { int ret; struct snd_soc_codec *codec; + struct snd_soc_jack *jack = NULL; if (!gbcodec) { dev_err(module->dev, "GB Codec not yet probed\n"); @@ -756,6 +827,12 @@ int gbaudio_register_module(struct gbaudio_module_info *module) return -EINVAL; } + ret = gbaudio_init_jack(module, codec); + if (ret) { + mutex_unlock(&gbcodec->lock); + return ret; + } + if (module->dapm_widgets) snd_soc_dapm_new_controls(&codec->dapm, module->dapm_widgets, module->num_dapm_widgets); @@ -774,6 +851,15 @@ int gbaudio_register_module(struct gbaudio_module_info *module) &codec->dapm); } +#ifdef CONFIG_SND_JACK + /* register jack devices for this module from codec->jack_list */ + list_for_each_entry(jack, &codec->jack_list, list) { + if ((jack == &module->headset_jack) + || (jack == &module->button_jack)) + snd_device_register(codec->card->snd_card, jack->jack); + } +#endif + list_add(&module->list, &gbcodec->module_list); dev_dbg(codec->dev, "Registered %s module\n", module->name); @@ -851,6 +937,7 @@ void gbaudio_unregister_module(struct gbaudio_module_info *module) { struct snd_soc_codec *codec = gbcodec->codec; struct snd_card *card = codec->card->snd_card; + struct snd_soc_jack *jack, *next_j; dev_dbg(codec->dev, "Unregister %s module\n", module->name); @@ -862,6 +949,17 @@ void gbaudio_unregister_module(struct gbaudio_module_info *module) dev_dbg(codec->dev, "Process Unregister %s module\n", module->name); mutex_lock(&module->lock); +#ifdef CONFIG_SND_JACK + /* free jack devices for this module from codec->jack_list */ + list_for_each_entry_safe(jack, next_j, &codec->jack_list, list) { + if ((jack == &module->headset_jack) + || (jack == &module->button_jack)) { + snd_device_free(codec->card->snd_card, jack->jack); + list_del(&jack->list); + } + } +#endif + gbaudio_codec_cleanup(module); module->is_connected = 0; diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index a2697dd..165b359 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -10,6 +10,7 @@ #define __LINUX_GBAUDIO_CODEC_H #include +#include #include "greybus.h" #include "greybus_protocols.h" @@ -57,6 +58,11 @@ enum gbcodec_reg_index { #define GBCODEC_APB1_MUX_REG_DEFAULT 0x00 #define GBCODEC_APB2_MUX_REG_DEFAULT 0x00 +#define GBCODEC_JACK_MASK (SND_JACK_HEADSET | SND_JACK_LINEOUT | \ + SND_JACK_LINEIN | SND_JACK_UNSUPPORTED) +#define GBCODEC_JACK_BUTTON_MASK (SND_JACK_BTN_0 | SND_JACK_BTN_1 | \ + SND_JACK_BTN_2 | SND_JACK_BTN_3) + static const u8 gbcodec_reg_defaults[GBCODEC_REG_COUNT] = { GBCODEC_CTL_REG_DEFAULT, GBCODEC_MUTE_REG_DEFAULT, @@ -139,6 +145,15 @@ struct gbaudio_module_info { int manager_id; char name[NAME_SIZE]; + /* jack related */ + char jack_name[NAME_SIZE]; + char button_name[NAME_SIZE]; + int num_jacks; + int jack_type; + int button_status; + struct snd_soc_jack headset_jack; + struct snd_soc_jack button_jack; + /* used by codec_ops */ struct mutex lock; int is_connected; diff --git a/drivers/staging/greybus/audio_module.c b/drivers/staging/greybus/audio_module.c index 94fdadc..9039aa6 100644 --- a/drivers/staging/greybus/audio_module.c +++ b/drivers/staging/greybus/audio_module.c @@ -22,18 +22,150 @@ static LIST_HEAD(gb_codec_list); * gb_snd management functions */ -static int gbaudio_codec_request_handler(struct gb_operation *op) +static int gbaudio_request_jack(struct gbaudio_module_info *module, + struct gb_audio_jack_event_request *req) { - struct gb_connection *connection = op->connection; - struct gb_audio_streaming_event_request *req = op->request->payload; + int report, button_status; + + dev_warn(module->dev, "Jack Event received: type: %u, event: %u\n", + req->widget_type, req->event); + + mutex_lock(&module->lock); + if (req->event == GB_AUDIO_JACK_EVENT_REMOVAL) { + module->jack_type = 0; + button_status = module->button_status; + module->button_status = 0; + mutex_unlock(&module->lock); + if (button_status) + snd_soc_jack_report(&module->button_jack, 0, + GBCODEC_JACK_BUTTON_MASK); + snd_soc_jack_report(&module->headset_jack, 0, + GBCODEC_JACK_MASK); + return 0; + } + + report &= ~GBCODEC_JACK_MASK; + /* currently supports Headphone, Headset & Lineout only */ + if (req->widget_type && GB_AUDIO_WIDGET_TYPE_HP) + report |= SND_JACK_HEADPHONE & GBCODEC_JACK_MASK; + + if (req->widget_type && GB_AUDIO_WIDGET_TYPE_MIC) + report = SND_JACK_MICROPHONE & GBCODEC_JACK_MASK; + + if (req->widget_type && GB_AUDIO_WIDGET_TYPE_LINE) + report = (report & GBCODEC_JACK_MASK) | + SND_JACK_LINEOUT | SND_JACK_LINEIN; + + if (module->jack_type) + dev_warn(module->dev, "Modifying jack from %d to %d\n", + module->jack_type, report); + + module->jack_type = report; + mutex_unlock(&module->lock); + snd_soc_jack_report(&module->headset_jack, report, GBCODEC_JACK_MASK); + + return 0; +} + +static int gbaudio_request_button(struct gbaudio_module_info *module, + struct gb_audio_button_event_request *req) +{ + int soc_button_id, report; + + dev_warn(module->dev, "Button Event received: id: %u, event: %u\n", + req->button_id, req->event); + + /* currently supports 4 buttons only */ + mutex_lock(&module->lock); + if (!module->jack_type) { + dev_err(module->dev, "Jack not present. Bogus event!!\n"); + mutex_unlock(&module->lock); + return -EINVAL; + } + + report = module->button_status & GBCODEC_JACK_BUTTON_MASK; + + switch (req->button_id) { + case 1: + soc_button_id = SND_JACK_BTN_0; + break; + + case 2: + soc_button_id = SND_JACK_BTN_1; + break; - dev_warn(&connection->bundle->dev, - "Audio Event received: cport: %u, event: %u\n", + case 3: + soc_button_id = SND_JACK_BTN_2; + break; + + case 4: + soc_button_id = SND_JACK_BTN_3; + break; + default: + dev_err(module->dev, "Invalid button request received\n"); + return -EINVAL; + } + + if (req->event == GB_AUDIO_BUTTON_EVENT_PRESS) + report = report | soc_button_id; + else + report = report & ~soc_button_id; + + module->button_status = report; + + mutex_unlock(&module->lock); + + snd_soc_jack_report(&module->button_jack, report, + GBCODEC_JACK_BUTTON_MASK); + + return 0; +} + +static int gbaudio_request_stream(struct gbaudio_module_info *module, + struct gb_audio_streaming_event_request *req) +{ + dev_warn(module->dev, "Audio Event received: cport: %u, event: %u\n", req->data_cport, req->event); return 0; } +static int gbaudio_codec_request_handler(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gbaudio_module_info *module = + greybus_get_drvdata(connection->bundle); + struct gb_operation_msg_hdr *header = op->request->header; + struct gb_audio_streaming_event_request *stream_req; + struct gb_audio_jack_event_request *jack_req; + struct gb_audio_button_event_request *button_req; + int ret; + + switch (header->type) { + case GB_AUDIO_TYPE_STREAMING_EVENT: + stream_req = op->request->payload; + ret = gbaudio_request_stream(module, stream_req); + break; + + case GB_AUDIO_TYPE_JACK_EVENT: + jack_req = op->request->payload; + ret = gbaudio_request_jack(module, jack_req); + break; + + case GB_AUDIO_TYPE_BUTTON_EVENT: + button_req = op->request->payload; + ret = gbaudio_request_button(module, button_req); + break; + + default: + dev_err(&connection->bundle->dev, + "Invalid Audio Event received\n"); + return -EINVAL; + } + + return ret; +} + static int gbaudio_data_connection_request_handler(struct gb_operation *op) { struct gb_connection *connection = op->connection; diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index 9e36fb2..79161c1 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -669,6 +669,7 @@ static int gbaudio_tplg_create_widget(struct gbaudio_module_info *module, case snd_soc_dapm_hp: *dw = (struct snd_soc_dapm_widget) SND_SOC_DAPM_HP(w->name, gbcodec_event_hp); + module->num_jacks++; break; case snd_soc_dapm_mic: *dw = (struct snd_soc_dapm_widget) -- cgit v0.10.2 From 094c4302c11889683af54525221ca68f64c1a358 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal Date: Tue, 29 Mar 2016 16:32:37 +0530 Subject: greybus: audio: Add I2S_RX path related settings Capture path related settings during startup, perpare & hwparams were earlier missing. Signed-off-by: Vaibhav Agarwal Reviewed-by: Mark Greer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 66a9548..2c6142d 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -72,16 +72,27 @@ static int gbaudio_module_disable(struct gbaudio_codec_info *codec, if (!data) { dev_err(codec->dev, "%s:%s DATA connection missing\n", dai_name, module->name); - mutex_unlock(&module->lock); - mutex_unlock(&codec->lock); - return -ENODEV; + ret = -ENODEV; + goto func_exit; } if (codec_state > GBAUDIO_CODEC_HWPARAMS) { data_cport = data->connection->intf_cport_id; - ret = gb_audio_gb_deactivate_tx(module->mgmt_connection, + switch(dir) { + case SNDRV_PCM_STREAM_CAPTURE: + ret = gb_audio_gb_deactivate_rx( + module->mgmt_connection, + data_cport); + break; + case SNDRV_PCM_STREAM_PLAYBACK: + ret = gb_audio_gb_deactivate_tx( + module->mgmt_connection, data_cport); + break; + default: + ret = -EINVAL; + } if (ret) { - dev_err(codec->dev, "deactivate_tx for %s failed:%d\n", + dev_err(codec->dev, "deactivate for %s failed:%d\n", module->name, ret); goto func_exit; } @@ -90,9 +101,22 @@ static int gbaudio_module_disable(struct gbaudio_codec_info *codec, } if (codec_state > GBAUDIO_CODEC_SHUTDOWN) { cportid = data->connection->hd_cport_id; - ret = gb_audio_apbridgea_unregister_cport(data->connection, + switch(dir) { + case SNDRV_PCM_STREAM_CAPTURE: + ret = gb_audio_apbridgea_unregister_cport( + data->connection, + i2s_port, cportid, + AUDIO_APBRIDGEA_DIRECTION_RX); + break; + case SNDRV_PCM_STREAM_PLAYBACK: + ret = gb_audio_apbridgea_unregister_cport( + data->connection, i2s_port, cportid, AUDIO_APBRIDGEA_DIRECTION_TX); + break; + default: + ret = -EINVAL; + } if (ret) { dev_err(codec->dev, "unregister_cport for %s failed:%d\n", module->name, ret); @@ -148,18 +172,30 @@ static int gbaudio_module_enable(struct gbaudio_codec_info *codec, if (!data) { dev_err(codec->dev, "%s:%s DATA connection missing\n", dai_name, module->name); - mutex_unlock(&module->lock); - mutex_unlock(&codec->lock); - return -ENODEV; + ret = -ENODEV; + goto func_exit; } /* register cport */ if (module_state < codec_state) { i2s_port = 0; /* fixed for now */ cportid = data->connection->hd_cport_id; - ret = gb_audio_apbridgea_register_cport(data->connection, + switch(dir) { + case SNDRV_PCM_STREAM_CAPTURE: + ret = gb_audio_apbridgea_register_cport( + data->connection, + i2s_port, cportid, + AUDIO_APBRIDGEA_DIRECTION_RX); + break; + case SNDRV_PCM_STREAM_PLAYBACK: + ret = gb_audio_apbridgea_register_cport( + data->connection, i2s_port, cportid, AUDIO_APBRIDGEA_DIRECTION_TX); + break; + default: + ret = -EINVAL; + } if (ret) { dev_err(codec->dev, "reg_cport for %s\n", module->name); goto func_exit; @@ -186,18 +222,46 @@ static int gbaudio_module_enable(struct gbaudio_codec_info *codec, /* prepare */ if (module_state < codec_state) { data_cport = data->connection->intf_cport_id; - ret = gb_audio_gb_set_tx_data_size(module->mgmt_connection, - data_cport, 192); - if (ret) { - dev_err(codec->dev, "set_tx_data_size for %s\n", - module->name); - goto func_exit; - } - ret = gb_audio_gb_activate_tx(module->mgmt_connection, - data_cport); - if (ret) { - dev_err(codec->dev, "activate_tx for %s\n", - module->name); + switch(dir) { + case SNDRV_PCM_STREAM_CAPTURE: + ret = gb_audio_gb_set_rx_data_size( + module->mgmt_connection, + data_cport, 192); + if (ret) { + dev_err(codec->dev, + "set_rx_data_size for %s\n", + module->name); + goto func_exit; + } + ret = gb_audio_gb_activate_rx(module->mgmt_connection, + data_cport); + if (ret) { + dev_err(codec->dev, "activate_rx for %s\n", + module->name); + goto func_exit; + } + break; + case SNDRV_PCM_STREAM_PLAYBACK: + ret = gb_audio_gb_set_tx_data_size( + module->mgmt_connection, + data_cport, 192); + if (ret) { + dev_err(codec->dev, + "set_tx_data_size for %s\n", + module->name); + goto func_exit; + } + ret = gb_audio_gb_activate_tx(module->mgmt_connection, + data_cport); + if (ret) { + dev_err(codec->dev, "activate_tx for %s\n", + module->name); + goto func_exit; + } + break; + default: + dev_err(codec->dev, "Inavlid stream direction\n"); + ret = -EINVAL; goto func_exit; } module_state = GBAUDIO_CODEC_PREPARE; @@ -217,7 +281,7 @@ int gbaudio_module_update(struct gbaudio_codec_info *codec, struct gbaudio_module_info *module, int enable) { int stream, ret = 0; - int pb_state; + int pb_state, cap_state; dev_dbg(module->dev, "Module update %s sequence\n", enable ? "Enable":"Disable"); @@ -239,12 +303,16 @@ int gbaudio_module_update(struct gbaudio_codec_info *codec, SNDRV_PCM_STREAM_PLAYBACK); } - /* TBD - * check if capture active - * cap_state = codec->stream[SNDRV_PCM_STREAM_CAPTURE].state; - * if ((stream & GB_CAPTURE) && (cap_state > GBAUDIO_CODEC_SHUTDOWN)) - * - */ + /* check if capture active */ + cap_state = codec->stream[SNDRV_PCM_STREAM_CAPTURE].state; + if ((stream & GB_CAPTURE) && (cap_state > GBAUDIO_CODEC_SHUTDOWN)) { + if (enable) + ret = gbaudio_module_enable(codec, module, + SNDRV_PCM_STREAM_CAPTURE); + else + ret = gbaudio_module_disable(codec, module, + SNDRV_PCM_STREAM_CAPTURE); + } return ret; } @@ -291,9 +359,25 @@ static int gbcodec_startup(struct snd_pcm_substream *substream, /* register cport */ i2s_port = 0; /* fixed for now */ cportid = data->connection->hd_cport_id; - ret = gb_audio_apbridgea_register_cport(data->connection, + switch (substream->stream) { + case SNDRV_PCM_STREAM_CAPTURE: + ret = gb_audio_apbridgea_register_cport( + data->connection, + i2s_port, cportid, + AUDIO_APBRIDGEA_DIRECTION_RX); + break; + case SNDRV_PCM_STREAM_PLAYBACK: + ret = gb_audio_apbridgea_register_cport( + data->connection, i2s_port, cportid, AUDIO_APBRIDGEA_DIRECTION_TX); + break; + default: + dev_err(dai->dev, "Inavlid stream\n"); + mutex_unlock(&module->lock); + mutex_unlock(&codec->lock); + return -EINVAL; + } dev_dbg(dai->dev, "Register %s:%d DAI, ret:%d\n", dai->name, cportid, ret); state = GBAUDIO_CODEC_STARTUP; -- cgit v0.10.2 From a4d11cee6fe9591a78ac82c8b91cf6592d0ba8cf Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 31 Mar 2016 22:26:39 -0700 Subject: greybus: trivial: add checkpatch.pl to the tree For those who are stuck using old kernel trees, let's include the latest version of checkpatch.pl into our tree to help prevent coding style mistakes from creeping in. Also add spelling.txt to catch spelling errors in comments. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/greybus/checkpatch.pl b/drivers/staging/greybus/checkpatch.pl new file mode 100755 index 0000000..d574d13 --- /dev/null +++ b/drivers/staging/greybus/checkpatch.pl @@ -0,0 +1,5993 @@ +#!/usr/bin/perl -w +# (c) 2001, Dave Jones. (the file handling bit) +# (c) 2005, Joel Schopp (the ugly bit) +# (c) 2007,2008, Andy Whitcroft (new conditions, test suite) +# (c) 2008-2010 Andy Whitcroft +# Licensed under the terms of the GNU GPL License version 2 + +use strict; +use POSIX; +use File::Basename; +use Cwd 'abs_path'; +use Term::ANSIColor qw(:constants); + +my $P = $0; +my $D = dirname(abs_path($P)); + +my $V = '0.32'; + +use Getopt::Long qw(:config no_auto_abbrev); + +my $quiet = 0; +my $tree = 1; +my $chk_signoff = 1; +my $chk_patch = 1; +my $tst_only; +my $emacs = 0; +my $terse = 0; +my $showfile = 0; +my $file = 0; +my $check = 0; +my $check_orig = 0; +my $summary = 1; +my $mailback = 0; +my $summary_file = 0; +my $show_types = 0; +my $fix = 0; +my $fix_inplace = 0; +my $root; +my %debug; +my %camelcase = (); +my %use_type = (); +my @use = (); +my %ignore_type = (); +my @ignore = (); +my $help = 0; +my $configuration_file = ".checkpatch.conf"; +my $max_line_length = 80; +my $ignore_perl_version = 0; +my $minimum_perl_version = 5.10.0; +my $min_conf_desc_length = 4; +my $spelling_file = "$D/spelling.txt"; +my $codespell = 0; +my $codespellfile = "/usr/share/codespell/dictionary.txt"; +my $color = 1; + +sub help { + my ($exitcode) = @_; + + print << "EOM"; +Usage: $P [OPTION]... [FILE]... +Version: $V + +Options: + -q, --quiet quiet + --no-tree run without a kernel tree + --no-signoff do not check for 'Signed-off-by' line + --patch treat FILE as patchfile (default) + --emacs emacs compile window format + --terse one line per report + --showfile emit diffed file position, not input file position + -f, --file treat FILE as regular source file + --subjective, --strict enable more subjective tests + --types TYPE(,TYPE2...) show only these comma separated message types + --ignore TYPE(,TYPE2...) ignore various comma separated message types + --max-line-length=n set the maximum line length, if exceeded, warn + --min-conf-desc-length=n set the min description length, if shorter, warn + --show-types show the message "types" in the output + --root=PATH PATH to the kernel tree root + --no-summary suppress the per-file summary + --mailback only produce a report in case of warnings/errors + --summary-file include the filename in summary + --debug KEY=[0|1] turn on/off debugging of KEY, where KEY is one of + 'values', 'possible', 'type', and 'attr' (default + is all off) + --test-only=WORD report only warnings/errors containing WORD + literally + --fix EXPERIMENTAL - may create horrible results + If correctable single-line errors exist, create + ".EXPERIMENTAL-checkpatch-fixes" + with potential errors corrected to the preferred + checkpatch style + --fix-inplace EXPERIMENTAL - may create horrible results + Is the same as --fix, but overwrites the input + file. It's your fault if there's no backup or git + --ignore-perl-version override checking of perl version. expect + runtime errors. + --codespell Use the codespell dictionary for spelling/typos + (default:/usr/share/codespell/dictionary.txt) + --codespellfile Use this codespell dictionary + --color Use colors when output is STDOUT (default: on) + -h, --help, --version display this help and exit + +When FILE is - read standard input. +EOM + + exit($exitcode); +} + +my $conf = which_conf($configuration_file); +if (-f $conf) { + my @conf_args; + open(my $conffile, '<', "$conf") + or warn "$P: Can't find a readable $configuration_file file $!\n"; + + while (<$conffile>) { + my $line = $_; + + $line =~ s/\s*\n?$//g; + $line =~ s/^\s*//g; + $line =~ s/\s+/ /g; + + next if ($line =~ m/^\s*#/); + next if ($line =~ m/^\s*$/); + + my @words = split(" ", $line); + foreach my $word (@words) { + last if ($word =~ m/^#/); + push (@conf_args, $word); + } + } + close($conffile); + unshift(@ARGV, @conf_args) if @conf_args; +} + +GetOptions( + 'q|quiet+' => \$quiet, + 'tree!' => \$tree, + 'signoff!' => \$chk_signoff, + 'patch!' => \$chk_patch, + 'emacs!' => \$emacs, + 'terse!' => \$terse, + 'showfile!' => \$showfile, + 'f|file!' => \$file, + 'subjective!' => \$check, + 'strict!' => \$check, + 'ignore=s' => \@ignore, + 'types=s' => \@use, + 'show-types!' => \$show_types, + 'max-line-length=i' => \$max_line_length, + 'min-conf-desc-length=i' => \$min_conf_desc_length, + 'root=s' => \$root, + 'summary!' => \$summary, + 'mailback!' => \$mailback, + 'summary-file!' => \$summary_file, + 'fix!' => \$fix, + 'fix-inplace!' => \$fix_inplace, + 'ignore-perl-version!' => \$ignore_perl_version, + 'debug=s' => \%debug, + 'test-only=s' => \$tst_only, + 'codespell!' => \$codespell, + 'codespellfile=s' => \$codespellfile, + 'color!' => \$color, + 'h|help' => \$help, + 'version' => \$help +) or help(1); + +help(0) if ($help); + +$fix = 1 if ($fix_inplace); +$check_orig = $check; + +my $exit = 0; + +if ($^V && $^V lt $minimum_perl_version) { + printf "$P: requires at least perl version %vd\n", $minimum_perl_version; + if (!$ignore_perl_version) { + exit(1); + } +} + +if ($#ARGV < 0) { + print "$P: no input files\n"; + exit(1); +} + +sub hash_save_array_words { + my ($hashRef, $arrayRef) = @_; + + my @array = split(/,/, join(',', @$arrayRef)); + foreach my $word (@array) { + $word =~ s/\s*\n?$//g; + $word =~ s/^\s*//g; + $word =~ s/\s+/ /g; + $word =~ tr/[a-z]/[A-Z]/; + + next if ($word =~ m/^\s*#/); + next if ($word =~ m/^\s*$/); + + $hashRef->{$word}++; + } +} + +sub hash_show_words { + my ($hashRef, $prefix) = @_; + + if (keys %$hashRef) { + print "\nNOTE: $prefix message types:"; + foreach my $word (sort keys %$hashRef) { + print " $word"; + } + print "\n"; + } +} + +hash_save_array_words(\%ignore_type, \@ignore); +hash_save_array_words(\%use_type, \@use); + +my $dbg_values = 0; +my $dbg_possible = 0; +my $dbg_type = 0; +my $dbg_attr = 0; +for my $key (keys %debug) { + ## no critic + eval "\${dbg_$key} = '$debug{$key}';"; + die "$@" if ($@); +} + +my $rpt_cleaners = 0; + +if ($terse) { + $emacs = 1; + $quiet++; +} + +if ($tree) { + if (defined $root) { + if (!top_of_kernel_tree($root)) { + die "$P: $root: --root does not point at a valid tree\n"; + } + } else { + if (top_of_kernel_tree('.')) { + $root = '.'; + } elsif ($0 =~ m@(.*)/scripts/[^/]*$@ && + top_of_kernel_tree($1)) { + $root = $1; + } + } + + if (!defined $root) { + print "Must be run from the top-level dir. of a kernel tree\n"; + exit(2); + } +} + +my $emitted_corrupt = 0; + +our $Ident = qr{ + [A-Za-z_][A-Za-z\d_]* + (?:\s*\#\#\s*[A-Za-z_][A-Za-z\d_]*)* + }x; +our $Storage = qr{extern|static|asmlinkage}; +our $Sparse = qr{ + __user| + __kernel| + __force| + __iomem| + __pmem| + __must_check| + __init_refok| + __kprobes| + __ref| + __rcu| + __private + }x; +our $InitAttributePrefix = qr{__(?:mem|cpu|dev|net_|)}; +our $InitAttributeData = qr{$InitAttributePrefix(?:initdata\b)}; +our $InitAttributeConst = qr{$InitAttributePrefix(?:initconst\b)}; +our $InitAttributeInit = qr{$InitAttributePrefix(?:init\b)}; +our $InitAttribute = qr{$InitAttributeData|$InitAttributeConst|$InitAttributeInit}; + +# Notes to $Attribute: +# We need \b after 'init' otherwise 'initconst' will cause a false positive in a check +our $Attribute = qr{ + const| + __percpu| + __nocast| + __safe| + __bitwise__| + __packed__| + __packed2__| + __naked| + __maybe_unused| + __always_unused| + __noreturn| + __used| + __cold| + __pure| + __noclone| + __deprecated| + __read_mostly| + __kprobes| + $InitAttribute| + ____cacheline_aligned| + ____cacheline_aligned_in_smp| + ____cacheline_internodealigned_in_smp| + __weak + }x; +our $Modifier; +our $Inline = qr{inline|__always_inline|noinline|__inline|__inline__}; +our $Member = qr{->$Ident|\.$Ident|\[[^]]*\]}; +our $Lval = qr{$Ident(?:$Member)*}; + +our $Int_type = qr{(?i)llu|ull|ll|lu|ul|l|u}; +our $Binary = qr{(?i)0b[01]+$Int_type?}; +our $Hex = qr{(?i)0x[0-9a-f]+$Int_type?}; +our $Int = qr{[0-9]+$Int_type?}; +our $Octal = qr{0[0-7]+$Int_type?}; +our $String = qr{"[X\t]*"}; +our $Float_hex = qr{(?i)0x[0-9a-f]+p-?[0-9]+[fl]?}; +our $Float_dec = qr{(?i)(?:[0-9]+\.[0-9]*|[0-9]*\.[0-9]+)(?:e-?[0-9]+)?[fl]?}; +our $Float_int = qr{(?i)[0-9]+e-?[0-9]+[fl]?}; +our $Float = qr{$Float_hex|$Float_dec|$Float_int}; +our $Constant = qr{$Float|$Binary|$Octal|$Hex|$Int}; +our $Assignment = qr{\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=}; +our $Compare = qr{<=|>=|==|!=|<|(?}; +our $Arithmetic = qr{\+|-|\*|\/|%}; +our $Operators = qr{ + <=|>=|==|!=| + =>|->|<<|>>|<|>|!|~| + &&|\|\||,|\^|\+\+|--|&|\||$Arithmetic + }x; + +our $c90_Keywords = qr{do|for|while|if|else|return|goto|continue|switch|default|case|break}x; + +our $BasicType; +our $NonptrType; +our $NonptrTypeMisordered; +our $NonptrTypeWithAttr; +our $Type; +our $TypeMisordered; +our $Declare; +our $DeclareMisordered; + +our $NON_ASCII_UTF8 = qr{ + [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte + | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs + | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte + | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates + | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 + | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 + | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 +}x; + +our $UTF8 = qr{ + [\x09\x0A\x0D\x20-\x7E] # ASCII + | $NON_ASCII_UTF8 +}x; + +our $typeC99Typedefs = qr{(?:__)?(?:[us]_?)?int_?(?:8|16|32|64)_t}; +our $typeOtherOSTypedefs = qr{(?x: + u_(?:char|short|int|long) | # bsd + u(?:nchar|short|int|long) # sysv +)}; +our $typeKernelTypedefs = qr{(?x: + (?:__)?(?:u|s|be|le)(?:8|16|32|64)| + atomic_t +)}; +our $typeTypedefs = qr{(?x: + $typeC99Typedefs\b| + $typeOtherOSTypedefs\b| + $typeKernelTypedefs\b +)}; + +our $zero_initializer = qr{(?:(?:0[xX])?0+$Int_type?|NULL|false)\b}; + +our $logFunctions = qr{(?x: + printk(?:_ratelimited|_once|)| + (?:[a-z0-9]+_){1,2}(?:printk|emerg|alert|crit|err|warning|warn|notice|info|debug|dbg|vdbg|devel|cont|WARN)(?:_ratelimited|_once|)| + WARN(?:_RATELIMIT|_ONCE|)| + panic| + MODULE_[A-Z_]+| + seq_vprintf|seq_printf|seq_puts +)}; + +our $signature_tags = qr{(?xi: + Signed-off-by:| + Acked-by:| + Tested-by:| + Reviewed-by:| + Reported-by:| + Suggested-by:| + To:| + Cc: +)}; + +our @typeListMisordered = ( + qr{char\s+(?:un)?signed}, + qr{int\s+(?:(?:un)?signed\s+)?short\s}, + qr{int\s+short(?:\s+(?:un)?signed)}, + qr{short\s+int(?:\s+(?:un)?signed)}, + qr{(?:un)?signed\s+int\s+short}, + qr{short\s+(?:un)?signed}, + qr{long\s+int\s+(?:un)?signed}, + qr{int\s+long\s+(?:un)?signed}, + qr{long\s+(?:un)?signed\s+int}, + qr{int\s+(?:un)?signed\s+long}, + qr{int\s+(?:un)?signed}, + qr{int\s+long\s+long\s+(?:un)?signed}, + qr{long\s+long\s+int\s+(?:un)?signed}, + qr{long\s+long\s+(?:un)?signed\s+int}, + qr{long\s+long\s+(?:un)?signed}, + qr{long\s+(?:un)?signed}, +); + +our @typeList = ( + qr{void}, + qr{(?:(?:un)?signed\s+)?char}, + qr{(?:(?:un)?signed\s+)?short\s+int}, + qr{(?:(?:un)?signed\s+)?short}, + qr{(?:(?:un)?signed\s+)?int}, + qr{(?:(?:un)?signed\s+)?long\s+int}, + qr{(?:(?:un)?signed\s+)?long\s+long\s+int}, + qr{(?:(?:un)?signed\s+)?long\s+long}, + qr{(?:(?:un)?signed\s+)?long}, + qr{(?:un)?signed}, + qr{float}, + qr{double}, + qr{bool}, + qr{struct\s+$Ident}, + qr{union\s+$Ident}, + qr{enum\s+$Ident}, + qr{${Ident}_t}, + qr{${Ident}_handler}, + qr{${Ident}_handler_fn}, + @typeListMisordered, +); + +our $C90_int_types = qr{(?x: + long\s+long\s+int\s+(?:un)?signed| + long\s+long\s+(?:un)?signed\s+int| + long\s+long\s+(?:un)?signed| + (?:(?:un)?signed\s+)?long\s+long\s+int| + (?:(?:un)?signed\s+)?long\s+long| + int\s+long\s+long\s+(?:un)?signed| + int\s+(?:(?:un)?signed\s+)?long\s+long| + + long\s+int\s+(?:un)?signed| + long\s+(?:un)?signed\s+int| + long\s+(?:un)?signed| + (?:(?:un)?signed\s+)?long\s+int| + (?:(?:un)?signed\s+)?long| + int\s+long\s+(?:un)?signed| + int\s+(?:(?:un)?signed\s+)?long| + + int\s+(?:un)?signed| + (?:(?:un)?signed\s+)?int +)}; + +our @typeListFile = (); +our @typeListWithAttr = ( + @typeList, + qr{struct\s+$InitAttribute\s+$Ident}, + qr{union\s+$InitAttribute\s+$Ident}, +); + +our @modifierList = ( + qr{fastcall}, +); +our @modifierListFile = (); + +our @mode_permission_funcs = ( + ["module_param", 3], + ["module_param_(?:array|named|string)", 4], + ["module_param_array_named", 5], + ["debugfs_create_(?:file|u8|u16|u32|u64|x8|x16|x32|x64|size_t|atomic_t|bool|blob|regset32|u32_array)", 2], + ["proc_create(?:_data|)", 2], + ["(?:CLASS|DEVICE|SENSOR)_ATTR", 2], +); + +#Create a search pattern for all these functions to speed up a loop below +our $mode_perms_search = ""; +foreach my $entry (@mode_permission_funcs) { + $mode_perms_search .= '|' if ($mode_perms_search ne ""); + $mode_perms_search .= $entry->[0]; +} + +our $mode_perms_world_writable = qr{ + S_IWUGO | + S_IWOTH | + S_IRWXUGO | + S_IALLUGO | + 0[0-7][0-7][2367] +}x; + +our $allowed_asm_includes = qr{(?x: + irq| + memory| + time| + reboot +)}; +# memory.h: ARM has a custom one + +# Load common spelling mistakes and build regular expression list. +my $misspellings; +my %spelling_fix; + +if (open(my $spelling, '<', $spelling_file)) { + while (<$spelling>) { + my $line = $_; + + $line =~ s/\s*\n?$//g; + $line =~ s/^\s*//g; + + next if ($line =~ m/^\s*#/); + next if ($line =~ m/^\s*$/); + + my ($suspect, $fix) = split(/\|\|/, $line); + + $spelling_fix{$suspect} = $fix; + } + close($spelling); +} else { + warn "No typos will be found - file '$spelling_file': $!\n"; +} + +if ($codespell) { + if (open(my $spelling, '<', $codespellfile)) { + while (<$spelling>) { + my $line = $_; + + $line =~ s/\s*\n?$//g; + $line =~ s/^\s*//g; + + next if ($line =~ m/^\s*#/); + next if ($line =~ m/^\s*$/); + next if ($line =~ m/, disabled/i); + + $line =~ s/,.*$//; + + my ($suspect, $fix) = split(/->/, $line); + + $spelling_fix{$suspect} = $fix; + } + close($spelling); + } else { + warn "No codespell typos will be found - file '$codespellfile': $!\n"; + } +} + +$misspellings = join("|", sort keys %spelling_fix) if keys %spelling_fix; + +sub build_types { + my $mods = "(?x: \n" . join("|\n ", (@modifierList, @modifierListFile)) . "\n)"; + my $all = "(?x: \n" . join("|\n ", (@typeList, @typeListFile)) . "\n)"; + my $Misordered = "(?x: \n" . join("|\n ", @typeListMisordered) . "\n)"; + my $allWithAttr = "(?x: \n" . join("|\n ", @typeListWithAttr) . "\n)"; + $Modifier = qr{(?:$Attribute|$Sparse|$mods)}; + $BasicType = qr{ + (?:$typeTypedefs\b)| + (?:${all}\b) + }x; + $NonptrType = qr{ + (?:$Modifier\s+|const\s+)* + (?: + (?:typeof|__typeof__)\s*\([^\)]*\)| + (?:$typeTypedefs\b)| + (?:${all}\b) + ) + (?:\s+$Modifier|\s+const)* + }x; + $NonptrTypeMisordered = qr{ + (?:$Modifier\s+|const\s+)* + (?: + (?:${Misordered}\b) + ) + (?:\s+$Modifier|\s+const)* + }x; + $NonptrTypeWithAttr = qr{ + (?:$Modifier\s+|const\s+)* + (?: + (?:typeof|__typeof__)\s*\([^\)]*\)| + (?:$typeTypedefs\b)| + (?:${allWithAttr}\b) + ) + (?:\s+$Modifier|\s+const)* + }x; + $Type = qr{ + $NonptrType + (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+)? + (?:\s+$Inline|\s+$Modifier)* + }x; + $TypeMisordered = qr{ + $NonptrTypeMisordered + (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+)? + (?:\s+$Inline|\s+$Modifier)* + }x; + $Declare = qr{(?:$Storage\s+(?:$Inline\s+)?)?$Type}; + $DeclareMisordered = qr{(?:$Storage\s+(?:$Inline\s+)?)?$TypeMisordered}; +} +build_types(); + +our $Typecast = qr{\s*(\(\s*$NonptrType\s*\)){0,1}\s*}; + +# Using $balanced_parens, $LvalOrFunc, or $FuncArg +# requires at least perl version v5.10.0 +# Any use must be runtime checked with $^V + +our $balanced_parens = qr/(\((?:[^\(\)]++|(?-1))*\))/; +our $LvalOrFunc = qr{((?:[\&\*]\s*)?$Lval)\s*($balanced_parens{0,1})\s*}; +our $FuncArg = qr{$Typecast{0,1}($LvalOrFunc|$Constant|$String)}; + +our $declaration_macros = qr{(?x: + (?:$Storage\s+)?(?:[A-Z_][A-Z0-9]*_){0,2}(?:DEFINE|DECLARE)(?:_[A-Z0-9]+){1,6}\s*\(| + (?:$Storage\s+)?LIST_HEAD\s*\(| + (?:$Storage\s+)?${Type}\s+uninitialized_var\s*\( +)}; + +sub deparenthesize { + my ($string) = @_; + return "" if (!defined($string)); + + while ($string =~ /^\s*\(.*\)\s*$/) { + $string =~ s@^\s*\(\s*@@; + $string =~ s@\s*\)\s*$@@; + } + + $string =~ s@\s+@ @g; + + return $string; +} + +sub seed_camelcase_file { + my ($file) = @_; + + return if (!(-f $file)); + + local $/; + + open(my $include_file, '<', "$file") + or warn "$P: Can't read '$file' $!\n"; + my $text = <$include_file>; + close($include_file); + + my @lines = split('\n', $text); + + foreach my $line (@lines) { + next if ($line !~ /(?:[A-Z][a-z]|[a-z][A-Z])/); + if ($line =~ /^[ \t]*(?:#[ \t]*define|typedef\s+$Type)\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)/) { + $camelcase{$1} = 1; + } elsif ($line =~ /^\s*$Declare\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)\s*[\(\[,;]/) { + $camelcase{$1} = 1; + } elsif ($line =~ /^\s*(?:union|struct|enum)\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)\s*[;\{]/) { + $camelcase{$1} = 1; + } + } +} + +my $camelcase_seeded = 0; +sub seed_camelcase_includes { + return if ($camelcase_seeded); + + my $files; + my $camelcase_cache = ""; + my @include_files = (); + + $camelcase_seeded = 1; + + if (-e ".git") { + my $git_last_include_commit = `git log --no-merges --pretty=format:"%h%n" -1 -- include`; + chomp $git_last_include_commit; + $camelcase_cache = ".checkpatch-camelcase.git.$git_last_include_commit"; + } else { + my $last_mod_date = 0; + $files = `find $root/include -name "*.h"`; + @include_files = split('\n', $files); + foreach my $file (@include_files) { + my $date = POSIX::strftime("%Y%m%d%H%M", + localtime((stat $file)[9])); + $last_mod_date = $date if ($last_mod_date < $date); + } + $camelcase_cache = ".checkpatch-camelcase.date.$last_mod_date"; + } + + if ($camelcase_cache ne "" && -f $camelcase_cache) { + open(my $camelcase_file, '<', "$camelcase_cache") + or warn "$P: Can't read '$camelcase_cache' $!\n"; + while (<$camelcase_file>) { + chomp; + $camelcase{$_} = 1; + } + close($camelcase_file); + + return; + } + + if (-e ".git") { + $files = `git ls-files "include/*.h"`; + @include_files = split('\n', $files); + } + + foreach my $file (@include_files) { + seed_camelcase_file($file); + } + + if ($camelcase_cache ne "") { + unlink glob ".checkpatch-camelcase.*"; + open(my $camelcase_file, '>', "$camelcase_cache") + or warn "$P: Can't write '$camelcase_cache' $!\n"; + foreach (sort { lc($a) cmp lc($b) } keys(%camelcase)) { + print $camelcase_file ("$_\n"); + } + close($camelcase_file); + } +} + +sub git_commit_info { + my ($commit, $id, $desc) = @_; + + return ($id, $desc) if ((which("git") eq "") || !(-e ".git")); + + my $output = `git log --no-color --format='%H %s' -1 $commit 2>&1`; + $output =~ s/^\s*//gm; + my @lines = split("\n", $output); + + return ($id, $desc) if ($#lines < 0); + + if ($lines[0] =~ /^error: short SHA1 $commit is ambiguous\./) { +# Maybe one day convert this block of bash into something that returns +# all matching commit ids, but it's very slow... +# +# echo "checking commits $1..." +# git rev-list --remotes | grep -i "^$1" | +# while read line ; do +# git log --format='%H %s' -1 $line | +# echo "commit $(cut -c 1-12,41-)" +# done + } elsif ($lines[0] =~ /^fatal: ambiguous argument '$commit': unknown revision or path not in the working tree\./) { + } else { + $id = substr($lines[0], 0, 12); + $desc = substr($lines[0], 41); + } + + return ($id, $desc); +} + +$chk_signoff = 0 if ($file); + +my @rawlines = (); +my @lines = (); +my @fixed = (); +my @fixed_inserted = (); +my @fixed_deleted = (); +my $fixlinenr = -1; + +my $vname; +for my $filename (@ARGV) { + my $FILE; + if ($file) { + open($FILE, '-|', "diff -u /dev/null $filename") || + die "$P: $filename: diff failed - $!\n"; + } elsif ($filename eq '-') { + open($FILE, '<&STDIN'); + } else { + open($FILE, '<', "$filename") || + die "$P: $filename: open failed - $!\n"; + } + if ($filename eq '-') { + $vname = 'Your patch'; + } else { + $vname = $filename; + } + while (<$FILE>) { + chomp; + push(@rawlines, $_); + } + close($FILE); + + if ($#ARGV > 0 && $quiet == 0) { + print '-' x length($vname) . "\n"; + print "$vname\n"; + print '-' x length($vname) . "\n"; + } + + if (!process($filename)) { + $exit = 1; + } + @rawlines = (); + @lines = (); + @fixed = (); + @fixed_inserted = (); + @fixed_deleted = (); + $fixlinenr = -1; + @modifierListFile = (); + @typeListFile = (); + build_types(); +} + +if (!$quiet) { + hash_show_words(\%use_type, "Used"); + hash_show_words(\%ignore_type, "Ignored"); + + if ($^V lt 5.10.0) { + print << "EOM" + +NOTE: perl $^V is not modern enough to detect all possible issues. + An upgrade to at least perl v5.10.0 is suggested. +EOM + } + if ($exit) { + print << "EOM" + +NOTE: If any of the errors are false positives, please report + them to the maintainer, see CHECKPATCH in MAINTAINERS. +EOM + } +} + +exit($exit); + +sub top_of_kernel_tree { + my ($root) = @_; + + my @tree_check = ( + "COPYING", "CREDITS", "Kbuild", "MAINTAINERS", "Makefile", + "README", "Documentation", "arch", "include", "drivers", + "fs", "init", "ipc", "kernel", "lib", "scripts", + ); + + foreach my $check (@tree_check) { + if (! -e $root . '/' . $check) { + return 0; + } + } + return 1; +} + +sub parse_email { + my ($formatted_email) = @_; + + my $name = ""; + my $address = ""; + my $comment = ""; + + if ($formatted_email =~ /^(.*)<(\S+\@\S+)>(.*)$/) { + $name = $1; + $address = $2; + $comment = $3 if defined $3; + } elsif ($formatted_email =~ /^\s*<(\S+\@\S+)>(.*)$/) { + $address = $1; + $comment = $2 if defined $2; + } elsif ($formatted_email =~ /(\S+\@\S+)(.*)$/) { + $address = $1; + $comment = $2 if defined $2; + $formatted_email =~ s/$address.*$//; + $name = $formatted_email; + $name = trim($name); + $name =~ s/^\"|\"$//g; + # If there's a name left after stripping spaces and + # leading quotes, and the address doesn't have both + # leading and trailing angle brackets, the address + # is invalid. ie: + # "joe smith joe@smith.com" bad + # "joe smith ]+>$/) { + $name = ""; + $address = ""; + $comment = ""; + } + } + + $name = trim($name); + $name =~ s/^\"|\"$//g; + $address = trim($address); + $address =~ s/^\<|\>$//g; + + if ($name =~ /[^\w \-]/i) { ##has "must quote" chars + $name =~ s/(?"; + } + + return $formatted_email; +} + +sub which { + my ($bin) = @_; + + foreach my $path (split(/:/, $ENV{PATH})) { + if (-e "$path/$bin") { + return "$path/$bin"; + } + } + + return ""; +} + +sub which_conf { + my ($conf) = @_; + + foreach my $path (split(/:/, ".:$ENV{HOME}:.scripts")) { + if (-e "$path/$conf") { + return "$path/$conf"; + } + } + + return ""; +} + +sub expand_tabs { + my ($str) = @_; + + my $res = ''; + my $n = 0; + for my $c (split(//, $str)) { + if ($c eq "\t") { + $res .= ' '; + $n++; + for (; ($n % 8) != 0; $n++) { + $res .= ' '; + } + next; + } + $res .= $c; + $n++; + } + + return $res; +} +sub copy_spacing { + (my $res = shift) =~ tr/\t/ /c; + return $res; +} + +sub line_stats { + my ($line) = @_; + + # Drop the diff line leader and expand tabs + $line =~ s/^.//; + $line = expand_tabs($line); + + # Pick the indent from the front of the line. + my ($white) = ($line =~ /^(\s*)/); + + return (length($line), length($white)); +} + +my $sanitise_quote = ''; + +sub sanitise_line_reset { + my ($in_comment) = @_; + + if ($in_comment) { + $sanitise_quote = '*/'; + } else { + $sanitise_quote = ''; + } +} +sub sanitise_line { + my ($line) = @_; + + my $res = ''; + my $l = ''; + + my $qlen = 0; + my $off = 0; + my $c; + + # Always copy over the diff marker. + $res = substr($line, 0, 1); + + for ($off = 1; $off < length($line); $off++) { + $c = substr($line, $off, 1); + + # Comments we are wacking completly including the begin + # and end, all to $;. + if ($sanitise_quote eq '' && substr($line, $off, 2) eq '/*') { + $sanitise_quote = '*/'; + + substr($res, $off, 2, "$;$;"); + $off++; + next; + } + if ($sanitise_quote eq '*/' && substr($line, $off, 2) eq '*/') { + $sanitise_quote = ''; + substr($res, $off, 2, "$;$;"); + $off++; + next; + } + if ($sanitise_quote eq '' && substr($line, $off, 2) eq '//') { + $sanitise_quote = '//'; + + substr($res, $off, 2, $sanitise_quote); + $off++; + next; + } + + # A \ in a string means ignore the next character. + if (($sanitise_quote eq "'" || $sanitise_quote eq '"') && + $c eq "\\") { + substr($res, $off, 2, 'XX'); + $off++; + next; + } + # Regular quotes. + if ($c eq "'" || $c eq '"') { + if ($sanitise_quote eq '') { + $sanitise_quote = $c; + + substr($res, $off, 1, $c); + next; + } elsif ($sanitise_quote eq $c) { + $sanitise_quote = ''; + } + } + + #print "c<$c> SQ<$sanitise_quote>\n"; + if ($off != 0 && $sanitise_quote eq '*/' && $c ne "\t") { + substr($res, $off, 1, $;); + } elsif ($off != 0 && $sanitise_quote eq '//' && $c ne "\t") { + substr($res, $off, 1, $;); + } elsif ($off != 0 && $sanitise_quote && $c ne "\t") { + substr($res, $off, 1, 'X'); + } else { + substr($res, $off, 1, $c); + } + } + + if ($sanitise_quote eq '//') { + $sanitise_quote = ''; + } + + # The pathname on a #include may be surrounded by '<' and '>'. + if ($res =~ /^.\s*\#\s*include\s+\<(.*)\>/) { + my $clean = 'X' x length($1); + $res =~ s@\<.*\>@<$clean>@; + + # The whole of a #error is a string. + } elsif ($res =~ /^.\s*\#\s*(?:error|warning)\s+(.*)\b/) { + my $clean = 'X' x length($1); + $res =~ s@(\#\s*(?:error|warning)\s+).*@$1$clean@; + } + + return $res; +} + +sub get_quoted_string { + my ($line, $rawline) = @_; + + return "" if ($line !~ m/($String)/g); + return substr($rawline, $-[0], $+[0] - $-[0]); +} + +sub ctx_statement_block { + my ($linenr, $remain, $off) = @_; + my $line = $linenr - 1; + my $blk = ''; + my $soff = $off; + my $coff = $off - 1; + my $coff_set = 0; + + my $loff = 0; + + my $type = ''; + my $level = 0; + my @stack = (); + my $p; + my $c; + my $len = 0; + + my $remainder; + while (1) { + @stack = (['', 0]) if ($#stack == -1); + + #warn "CSB: blk<$blk> remain<$remain>\n"; + # If we are about to drop off the end, pull in more + # context. + if ($off >= $len) { + for (; $remain > 0; $line++) { + last if (!defined $lines[$line]); + next if ($lines[$line] =~ /^-/); + $remain--; + $loff = $len; + $blk .= $lines[$line] . "\n"; + $len = length($blk); + $line++; + last; + } + # Bail if there is no further context. + #warn "CSB: blk<$blk> off<$off> len<$len>\n"; + if ($off >= $len) { + last; + } + if ($level == 0 && substr($blk, $off) =~ /^.\s*#\s*define/) { + $level++; + $type = '#'; + } + } + $p = $c; + $c = substr($blk, $off, 1); + $remainder = substr($blk, $off); + + #warn "CSB: c<$c> type<$type> level<$level> remainder<$remainder> coff_set<$coff_set>\n"; + + # Handle nested #if/#else. + if ($remainder =~ /^#\s*(?:ifndef|ifdef|if)\s/) { + push(@stack, [ $type, $level ]); + } elsif ($remainder =~ /^#\s*(?:else|elif)\b/) { + ($type, $level) = @{$stack[$#stack - 1]}; + } elsif ($remainder =~ /^#\s*endif\b/) { + ($type, $level) = @{pop(@stack)}; + } + + # Statement ends at the ';' or a close '}' at the + # outermost level. + if ($level == 0 && $c eq ';') { + last; + } + + # An else is really a conditional as long as its not else if + if ($level == 0 && $coff_set == 0 && + (!defined($p) || $p =~ /(?:\s|\}|\+)/) && + $remainder =~ /^(else)(?:\s|{)/ && + $remainder !~ /^else\s+if\b/) { + $coff = $off + length($1) - 1; + $coff_set = 1; + #warn "CSB: mark coff<$coff> soff<$soff> 1<$1>\n"; + #warn "[" . substr($blk, $soff, $coff - $soff + 1) . "]\n"; + } + + if (($type eq '' || $type eq '(') && $c eq '(') { + $level++; + $type = '('; + } + if ($type eq '(' && $c eq ')') { + $level--; + $type = ($level != 0)? '(' : ''; + + if ($level == 0 && $coff < $soff) { + $coff = $off; + $coff_set = 1; + #warn "CSB: mark coff<$coff>\n"; + } + } + if (($type eq '' || $type eq '{') && $c eq '{') { + $level++; + $type = '{'; + } + if ($type eq '{' && $c eq '}') { + $level--; + $type = ($level != 0)? '{' : ''; + + if ($level == 0) { + if (substr($blk, $off + 1, 1) eq ';') { + $off++; + } + last; + } + } + # Preprocessor commands end at the newline unless escaped. + if ($type eq '#' && $c eq "\n" && $p ne "\\") { + $level--; + $type = ''; + $off++; + last; + } + $off++; + } + # We are truly at the end, so shuffle to the next line. + if ($off == $len) { + $loff = $len + 1; + $line++; + $remain--; + } + + my $statement = substr($blk, $soff, $off - $soff + 1); + my $condition = substr($blk, $soff, $coff - $soff + 1); + + #warn "STATEMENT<$statement>\n"; + #warn "CONDITION<$condition>\n"; + + #print "coff<$coff> soff<$off> loff<$loff>\n"; + + return ($statement, $condition, + $line, $remain + 1, $off - $loff + 1, $level); +} + +sub statement_lines { + my ($stmt) = @_; + + # Strip the diff line prefixes and rip blank lines at start and end. + $stmt =~ s/(^|\n)./$1/g; + $stmt =~ s/^\s*//; + $stmt =~ s/\s*$//; + + my @stmt_lines = ($stmt =~ /\n/g); + + return $#stmt_lines + 2; +} + +sub statement_rawlines { + my ($stmt) = @_; + + my @stmt_lines = ($stmt =~ /\n/g); + + return $#stmt_lines + 2; +} + +sub statement_block_size { + my ($stmt) = @_; + + $stmt =~ s/(^|\n)./$1/g; + $stmt =~ s/^\s*{//; + $stmt =~ s/}\s*$//; + $stmt =~ s/^\s*//; + $stmt =~ s/\s*$//; + + my @stmt_lines = ($stmt =~ /\n/g); + my @stmt_statements = ($stmt =~ /;/g); + + my $stmt_lines = $#stmt_lines + 2; + my $stmt_statements = $#stmt_statements + 1; + + if ($stmt_lines > $stmt_statements) { + return $stmt_lines; + } else { + return $stmt_statements; + } +} + +sub ctx_statement_full { + my ($linenr, $remain, $off) = @_; + my ($statement, $condition, $level); + + my (@chunks); + + # Grab the first conditional/block pair. + ($statement, $condition, $linenr, $remain, $off, $level) = + ctx_statement_block($linenr, $remain, $off); + #print "F: c<$condition> s<$statement> remain<$remain>\n"; + push(@chunks, [ $condition, $statement ]); + if (!($remain > 0 && $condition =~ /^\s*(?:\n[+-])?\s*(?:if|else|do)\b/s)) { + return ($level, $linenr, @chunks); + } + + # Pull in the following conditional/block pairs and see if they + # could continue the statement. + for (;;) { + ($statement, $condition, $linenr, $remain, $off, $level) = + ctx_statement_block($linenr, $remain, $off); + #print "C: c<$condition> s<$statement> remain<$remain>\n"; + last if (!($remain > 0 && $condition =~ /^(?:\s*\n[+-])*\s*(?:else|do)\b/s)); + #print "C: push\n"; + push(@chunks, [ $condition, $statement ]); + } + + return ($level, $linenr, @chunks); +} + +sub ctx_block_get { + my ($linenr, $remain, $outer, $open, $close, $off) = @_; + my $line; + my $start = $linenr - 1; + my $blk = ''; + my @o; + my @c; + my @res = (); + + my $level = 0; + my @stack = ($level); + for ($line = $start; $remain > 0; $line++) { + next if ($rawlines[$line] =~ /^-/); + $remain--; + + $blk .= $rawlines[$line]; + + # Handle nested #if/#else. + if ($lines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) { + push(@stack, $level); + } elsif ($lines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) { + $level = $stack[$#stack - 1]; + } elsif ($lines[$line] =~ /^.\s*#\s*endif\b/) { + $level = pop(@stack); + } + + foreach my $c (split(//, $lines[$line])) { + ##print "C<$c>L<$level><$open$close>O<$off>\n"; + if ($off > 0) { + $off--; + next; + } + + if ($c eq $close && $level > 0) { + $level--; + last if ($level == 0); + } elsif ($c eq $open) { + $level++; + } + } + + if (!$outer || $level <= 1) { + push(@res, $rawlines[$line]); + } + + last if ($level == 0); + } + + return ($level, @res); +} +sub ctx_block_outer { + my ($linenr, $remain) = @_; + + my ($level, @r) = ctx_block_get($linenr, $remain, 1, '{', '}', 0); + return @r; +} +sub ctx_block { + my ($linenr, $remain) = @_; + + my ($level, @r) = ctx_block_get($linenr, $remain, 0, '{', '}', 0); + return @r; +} +sub ctx_statement { + my ($linenr, $remain, $off) = @_; + + my ($level, @r) = ctx_block_get($linenr, $remain, 0, '(', ')', $off); + return @r; +} +sub ctx_block_level { + my ($linenr, $remain) = @_; + + return ctx_block_get($linenr, $remain, 0, '{', '}', 0); +} +sub ctx_statement_level { + my ($linenr, $remain, $off) = @_; + + return ctx_block_get($linenr, $remain, 0, '(', ')', $off); +} + +sub ctx_locate_comment { + my ($first_line, $end_line) = @_; + + # Catch a comment on the end of the line itself. + my ($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*(?:\\\s*)?$@); + return $current_comment if (defined $current_comment); + + # Look through the context and try and figure out if there is a + # comment. + my $in_comment = 0; + $current_comment = ''; + for (my $linenr = $first_line; $linenr < $end_line; $linenr++) { + my $line = $rawlines[$linenr - 1]; + #warn " $line\n"; + if ($linenr == $first_line and $line =~ m@^.\s*\*@) { + $in_comment = 1; + } + if ($line =~ m@/\*@) { + $in_comment = 1; + } + if (!$in_comment && $current_comment ne '') { + $current_comment = ''; + } + $current_comment .= $line . "\n" if ($in_comment); + if ($line =~ m@\*/@) { + $in_comment = 0; + } + } + + chomp($current_comment); + return($current_comment); +} +sub ctx_has_comment { + my ($first_line, $end_line) = @_; + my $cmt = ctx_locate_comment($first_line, $end_line); + + ##print "LINE: $rawlines[$end_line - 1 ]\n"; + ##print "CMMT: $cmt\n"; + + return ($cmt ne ''); +} + +sub raw_line { + my ($linenr, $cnt) = @_; + + my $offset = $linenr - 1; + $cnt++; + + my $line; + while ($cnt) { + $line = $rawlines[$offset++]; + next if (defined($line) && $line =~ /^-/); + $cnt--; + } + + return $line; +} + +sub cat_vet { + my ($vet) = @_; + my ($res, $coded); + + $res = ''; + while ($vet =~ /([^[:cntrl:]]*)([[:cntrl:]]|$)/g) { + $res .= $1; + if ($2 ne '') { + $coded = sprintf("^%c", unpack('C', $2) + 64); + $res .= $coded; + } + } + $res =~ s/$/\$/; + + return $res; +} + +my $av_preprocessor = 0; +my $av_pending; +my @av_paren_type; +my $av_pend_colon; + +sub annotate_reset { + $av_preprocessor = 0; + $av_pending = '_'; + @av_paren_type = ('E'); + $av_pend_colon = 'O'; +} + +sub annotate_values { + my ($stream, $type) = @_; + + my $res; + my $var = '_' x length($stream); + my $cur = $stream; + + print "$stream\n" if ($dbg_values > 1); + + while (length($cur)) { + @av_paren_type = ('E') if ($#av_paren_type < 0); + print " <" . join('', @av_paren_type) . + "> <$type> <$av_pending>" if ($dbg_values > 1); + if ($cur =~ /^(\s+)/o) { + print "WS($1)\n" if ($dbg_values > 1); + if ($1 =~ /\n/ && $av_preprocessor) { + $type = pop(@av_paren_type); + $av_preprocessor = 0; + } + + } elsif ($cur =~ /^(\(\s*$Type\s*)\)/ && $av_pending eq '_') { + print "CAST($1)\n" if ($dbg_values > 1); + push(@av_paren_type, $type); + $type = 'c'; + + } elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\(|\s*$)/) { + print "DECLARE($1)\n" if ($dbg_values > 1); + $type = 'T'; + + } elsif ($cur =~ /^($Modifier)\s*/) { + print "MODIFIER($1)\n" if ($dbg_values > 1); + $type = 'T'; + + } elsif ($cur =~ /^(\#\s*define\s*$Ident)(\(?)/o) { + print "DEFINE($1,$2)\n" if ($dbg_values > 1); + $av_preprocessor = 1; + push(@av_paren_type, $type); + if ($2 ne '') { + $av_pending = 'N'; + } + $type = 'E'; + + } elsif ($cur =~ /^(\#\s*(?:undef\s*$Ident|include\b))/o) { + print "UNDEF($1)\n" if ($dbg_values > 1); + $av_preprocessor = 1; + push(@av_paren_type, $type); + + } elsif ($cur =~ /^(\#\s*(?:ifdef|ifndef|if))/o) { + print "PRE_START($1)\n" if ($dbg_values > 1); + $av_preprocessor = 1; + + push(@av_paren_type, $type); + push(@av_paren_type, $type); + $type = 'E'; + + } elsif ($cur =~ /^(\#\s*(?:else|elif))/o) { + print "PRE_RESTART($1)\n" if ($dbg_values > 1); + $av_preprocessor = 1; + + push(@av_paren_type, $av_paren_type[$#av_paren_type]); + + $type = 'E'; + + } elsif ($cur =~ /^(\#\s*(?:endif))/o) { + print "PRE_END($1)\n" if ($dbg_values > 1); + + $av_preprocessor = 1; + + # Assume all arms of the conditional end as this + # one does, and continue as if the #endif was not here. + pop(@av_paren_type); + push(@av_paren_type, $type); + $type = 'E'; + + } elsif ($cur =~ /^(\\\n)/o) { + print "PRECONT($1)\n" if ($dbg_values > 1); + + } elsif ($cur =~ /^(__attribute__)\s*\(?/o) { + print "ATTR($1)\n" if ($dbg_values > 1); + $av_pending = $type; + $type = 'N'; + + } elsif ($cur =~ /^(sizeof)\s*(\()?/o) { + print "SIZEOF($1)\n" if ($dbg_values > 1); + if (defined $2) { + $av_pending = 'V'; + } + $type = 'N'; + + } elsif ($cur =~ /^(if|while|for)\b/o) { + print "COND($1)\n" if ($dbg_values > 1); + $av_pending = 'E'; + $type = 'N'; + + } elsif ($cur =~/^(case)/o) { + print "CASE($1)\n" if ($dbg_values > 1); + $av_pend_colon = 'C'; + $type = 'N'; + + } elsif ($cur =~/^(return|else|goto|typeof|__typeof__)\b/o) { + print "KEYWORD($1)\n" if ($dbg_values > 1); + $type = 'N'; + + } elsif ($cur =~ /^(\()/o) { + print "PAREN('$1')\n" if ($dbg_values > 1); + push(@av_paren_type, $av_pending); + $av_pending = '_'; + $type = 'N'; + + } elsif ($cur =~ /^(\))/o) { + my $new_type = pop(@av_paren_type); + if ($new_type ne '_') { + $type = $new_type; + print "PAREN('$1') -> $type\n" + if ($dbg_values > 1); + } else { + print "PAREN('$1')\n" if ($dbg_values > 1); + } + + } elsif ($cur =~ /^($Ident)\s*\(/o) { + print "FUNC($1)\n" if ($dbg_values > 1); + $type = 'V'; + $av_pending = 'V'; + + } elsif ($cur =~ /^($Ident\s*):(?:\s*\d+\s*(,|=|;))?/) { + if (defined $2 && $type eq 'C' || $type eq 'T') { + $av_pend_colon = 'B'; + } elsif ($type eq 'E') { + $av_pend_colon = 'L'; + } + print "IDENT_COLON($1,$type>$av_pend_colon)\n" if ($dbg_values > 1); + $type = 'V'; + + } elsif ($cur =~ /^($Ident|$Constant)/o) { + print "IDENT($1)\n" if ($dbg_values > 1); + $type = 'V'; + + } elsif ($cur =~ /^($Assignment)/o) { + print "ASSIGN($1)\n" if ($dbg_values > 1); + $type = 'N'; + + } elsif ($cur =~/^(;|{|})/) { + print "END($1)\n" if ($dbg_values > 1); + $type = 'E'; + $av_pend_colon = 'O'; + + } elsif ($cur =~/^(,)/) { + print "COMMA($1)\n" if ($dbg_values > 1); + $type = 'C'; + + } elsif ($cur =~ /^(\?)/o) { + print "QUESTION($1)\n" if ($dbg_values > 1); + $type = 'N'; + + } elsif ($cur =~ /^(:)/o) { + print "COLON($1,$av_pend_colon)\n" if ($dbg_values > 1); + + substr($var, length($res), 1, $av_pend_colon); + if ($av_pend_colon eq 'C' || $av_pend_colon eq 'L') { + $type = 'E'; + } else { + $type = 'N'; + } + $av_pend_colon = 'O'; + + } elsif ($cur =~ /^(\[)/o) { + print "CLOSE($1)\n" if ($dbg_values > 1); + $type = 'N'; + + } elsif ($cur =~ /^(-(?![->])|\+(?!\+)|\*|\&\&|\&)/o) { + my $variant; + + print "OPV($1)\n" if ($dbg_values > 1); + if ($type eq 'V') { + $variant = 'B'; + } else { + $variant = 'U'; + } + + substr($var, length($res), 1, $variant); + $type = 'N'; + + } elsif ($cur =~ /^($Operators)/o) { + print "OP($1)\n" if ($dbg_values > 1); + if ($1 ne '++' && $1 ne '--') { + $type = 'N'; + } + + } elsif ($cur =~ /(^.)/o) { + print "C($1)\n" if ($dbg_values > 1); + } + if (defined $1) { + $cur = substr($cur, length($1)); + $res .= $type x length($1); + } + } + + return ($res, $var); +} + +sub possible { + my ($possible, $line) = @_; + my $notPermitted = qr{(?: + ^(?: + $Modifier| + $Storage| + $Type| + DEFINE_\S+ + )$| + ^(?: + goto| + return| + case| + else| + asm|__asm__| + do| + \#| + \#\#| + )(?:\s|$)| + ^(?:typedef|struct|enum)\b + )}x; + warn "CHECK<$possible> ($line)\n" if ($dbg_possible > 2); + if ($possible !~ $notPermitted) { + # Check for modifiers. + $possible =~ s/\s*$Storage\s*//g; + $possible =~ s/\s*$Sparse\s*//g; + if ($possible =~ /^\s*$/) { + + } elsif ($possible =~ /\s/) { + $possible =~ s/\s*$Type\s*//g; + for my $modifier (split(' ', $possible)) { + if ($modifier !~ $notPermitted) { + warn "MODIFIER: $modifier ($possible) ($line)\n" if ($dbg_possible); + push(@modifierListFile, $modifier); + } + } + + } else { + warn "POSSIBLE: $possible ($line)\n" if ($dbg_possible); + push(@typeListFile, $possible); + } + build_types(); + } else { + warn "NOTPOSS: $possible ($line)\n" if ($dbg_possible > 1); + } +} + +my $prefix = ''; + +sub show_type { + my ($type) = @_; + + return defined $use_type{$type} if (scalar keys %use_type > 0); + + return !defined $ignore_type{$type}; +} + +sub report { + my ($level, $type, $msg) = @_; + + if (!show_type($type) || + (defined $tst_only && $msg !~ /\Q$tst_only\E/)) { + return 0; + } + my $output = ''; + if (-t STDOUT && $color) { + if ($level eq 'ERROR') { + $output .= RED; + } elsif ($level eq 'WARNING') { + $output .= YELLOW; + } else { + $output .= GREEN; + } + } + $output .= $prefix . $level . ':'; + if ($show_types) { + $output .= BLUE if (-t STDOUT && $color); + $output .= "$type:"; + } + $output .= RESET if (-t STDOUT && $color); + $output .= ' ' . $msg . "\n"; + + if ($showfile) { + my @lines = split("\n", $output, -1); + splice(@lines, 1, 1); + $output = join("\n", @lines); + } + $output = (split('\n', $output))[0] . "\n" if ($terse); + + push(our @report, $output); + + return 1; +} + +sub report_dump { + our @report; +} + +sub fixup_current_range { + my ($lineRef, $offset, $length) = @_; + + if ($$lineRef =~ /^\@\@ -\d+,\d+ \+(\d+),(\d+) \@\@/) { + my $o = $1; + my $l = $2; + my $no = $o + $offset; + my $nl = $l + $length; + $$lineRef =~ s/\+$o,$l \@\@/\+$no,$nl \@\@/; + } +} + +sub fix_inserted_deleted_lines { + my ($linesRef, $insertedRef, $deletedRef) = @_; + + my $range_last_linenr = 0; + my $delta_offset = 0; + + my $old_linenr = 0; + my $new_linenr = 0; + + my $next_insert = 0; + my $next_delete = 0; + + my @lines = (); + + my $inserted = @{$insertedRef}[$next_insert++]; + my $deleted = @{$deletedRef}[$next_delete++]; + + foreach my $old_line (@{$linesRef}) { + my $save_line = 1; + my $line = $old_line; #don't modify the array + if ($line =~ /^(?:\+\+\+|\-\-\-)\s+\S+/) { #new filename + $delta_offset = 0; + } elsif ($line =~ /^\@\@ -\d+,\d+ \+\d+,\d+ \@\@/) { #new hunk + $range_last_linenr = $new_linenr; + fixup_current_range(\$line, $delta_offset, 0); + } + + while (defined($deleted) && ${$deleted}{'LINENR'} == $old_linenr) { + $deleted = @{$deletedRef}[$next_delete++]; + $save_line = 0; + fixup_current_range(\$lines[$range_last_linenr], $delta_offset--, -1); + } + + while (defined($inserted) && ${$inserted}{'LINENR'} == $old_linenr) { + push(@lines, ${$inserted}{'LINE'}); + $inserted = @{$insertedRef}[$next_insert++]; + $new_linenr++; + fixup_current_range(\$lines[$range_last_linenr], $delta_offset++, 1); + } + + if ($save_line) { + push(@lines, $line); + $new_linenr++; + } + + $old_linenr++; + } + + return @lines; +} + +sub fix_insert_line { + my ($linenr, $line) = @_; + + my $inserted = { + LINENR => $linenr, + LINE => $line, + }; + push(@fixed_inserted, $inserted); +} + +sub fix_delete_line { + my ($linenr, $line) = @_; + + my $deleted = { + LINENR => $linenr, + LINE => $line, + }; + + push(@fixed_deleted, $deleted); +} + +sub ERROR { + my ($type, $msg) = @_; + + if (report("ERROR", $type, $msg)) { + our $clean = 0; + our $cnt_error++; + return 1; + } + return 0; +} +sub WARN { + my ($type, $msg) = @_; + + if (report("WARNING", $type, $msg)) { + our $clean = 0; + our $cnt_warn++; + return 1; + } + return 0; +} +sub CHK { + my ($type, $msg) = @_; + + if ($check && report("CHECK", $type, $msg)) { + our $clean = 0; + our $cnt_chk++; + return 1; + } + return 0; +} + +sub check_absolute_file { + my ($absolute, $herecurr) = @_; + my $file = $absolute; + + ##print "absolute<$absolute>\n"; + + # See if any suffix of this path is a path within the tree. + while ($file =~ s@^[^/]*/@@) { + if (-f "$root/$file") { + ##print "file<$file>\n"; + last; + } + } + if (! -f _) { + return 0; + } + + # It is, so see if the prefix is acceptable. + my $prefix = $absolute; + substr($prefix, -length($file)) = ''; + + ##print "prefix<$prefix>\n"; + if ($prefix ne ".../") { + WARN("USE_RELATIVE_PATH", + "use relative pathname instead of absolute in changelog text\n" . $herecurr); + } +} + +sub trim { + my ($string) = @_; + + $string =~ s/^\s+|\s+$//g; + + return $string; +} + +sub ltrim { + my ($string) = @_; + + $string =~ s/^\s+//; + + return $string; +} + +sub rtrim { + my ($string) = @_; + + $string =~ s/\s+$//; + + return $string; +} + +sub string_find_replace { + my ($string, $find, $replace) = @_; + + $string =~ s/$find/$replace/g; + + return $string; +} + +sub tabify { + my ($leading) = @_; + + my $source_indent = 8; + my $max_spaces_before_tab = $source_indent - 1; + my $spaces_to_tab = " " x $source_indent; + + #convert leading spaces to tabs + 1 while $leading =~ s@^([\t]*)$spaces_to_tab@$1\t@g; + #Remove spaces before a tab + 1 while $leading =~ s@^([\t]*)( {1,$max_spaces_before_tab})\t@$1\t@g; + + return "$leading"; +} + +sub pos_last_openparen { + my ($line) = @_; + + my $pos = 0; + + my $opens = $line =~ tr/\(/\(/; + my $closes = $line =~ tr/\)/\)/; + + my $last_openparen = 0; + + if (($opens == 0) || ($closes >= $opens)) { + return -1; + } + + my $len = length($line); + + for ($pos = 0; $pos < $len; $pos++) { + my $string = substr($line, $pos); + if ($string =~ /^($FuncArg|$balanced_parens)/) { + $pos += length($1) - 1; + } elsif (substr($line, $pos, 1) eq '(') { + $last_openparen = $pos; + } elsif (index($string, '(') == -1) { + last; + } + } + + return length(expand_tabs(substr($line, 0, $last_openparen))) + 1; +} + +sub process { + my $filename = shift; + + my $linenr=0; + my $prevline=""; + my $prevrawline=""; + my $stashline=""; + my $stashrawline=""; + + my $length; + my $indent; + my $previndent=0; + my $stashindent=0; + + our $clean = 1; + my $signoff = 0; + my $is_patch = 0; + my $in_header_lines = $file ? 0 : 1; + my $in_commit_log = 0; #Scanning lines before patch + my $commit_log_possible_stack_dump = 0; + my $commit_log_long_line = 0; + my $commit_log_has_diff = 0; + my $reported_maintainer_file = 0; + my $non_utf8_charset = 0; + + my $last_blank_line = 0; + my $last_coalesced_string_linenr = -1; + + our @report = (); + our $cnt_lines = 0; + our $cnt_error = 0; + our $cnt_warn = 0; + our $cnt_chk = 0; + + # Trace the real file/line as we go. + my $realfile = ''; + my $realline = 0; + my $realcnt = 0; + my $here = ''; + my $in_comment = 0; + my $comment_edge = 0; + my $first_line = 0; + my $p1_prefix = ''; + + my $prev_values = 'E'; + + # suppression flags + my %suppress_ifbraces; + my %suppress_whiletrailers; + my %suppress_export; + my $suppress_statement = 0; + + my %signatures = (); + + # Pre-scan the patch sanitizing the lines. + # Pre-scan the patch looking for any __setup documentation. + # + my @setup_docs = (); + my $setup_docs = 0; + + my $camelcase_file_seeded = 0; + + sanitise_line_reset(); + my $line; + foreach my $rawline (@rawlines) { + $linenr++; + $line = $rawline; + + push(@fixed, $rawline) if ($fix); + + if ($rawline=~/^\+\+\+\s+(\S+)/) { + $setup_docs = 0; + if ($1 =~ m@Documentation/kernel-parameters.txt$@) { + $setup_docs = 1; + } + #next; + } + if ($rawline=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) { + $realline=$1-1; + if (defined $2) { + $realcnt=$3+1; + } else { + $realcnt=1+1; + } + $in_comment = 0; + + # Guestimate if this is a continuing comment. Run + # the context looking for a comment "edge". If this + # edge is a close comment then we must be in a comment + # at context start. + my $edge; + my $cnt = $realcnt; + for (my $ln = $linenr + 1; $cnt > 0; $ln++) { + next if (defined $rawlines[$ln - 1] && + $rawlines[$ln - 1] =~ /^-/); + $cnt--; + #print "RAW<$rawlines[$ln - 1]>\n"; + last if (!defined $rawlines[$ln - 1]); + if ($rawlines[$ln - 1] =~ m@(/\*|\*/)@ && + $rawlines[$ln - 1] !~ m@"[^"]*(?:/\*|\*/)[^"]*"@) { + ($edge) = $1; + last; + } + } + if (defined $edge && $edge eq '*/') { + $in_comment = 1; + } + + # Guestimate if this is a continuing comment. If this + # is the start of a diff block and this line starts + # ' *' then it is very likely a comment. + if (!defined $edge && + $rawlines[$linenr] =~ m@^.\s*(?:\*\*+| \*)(?:\s|$)@) + { + $in_comment = 1; + } + + ##print "COMMENT:$in_comment edge<$edge> $rawline\n"; + sanitise_line_reset($in_comment); + + } elsif ($realcnt && $rawline =~ /^(?:\+| |$)/) { + # Standardise the strings and chars within the input to + # simplify matching -- only bother with positive lines. + $line = sanitise_line($rawline); + } + push(@lines, $line); + + if ($realcnt > 1) { + $realcnt-- if ($line =~ /^(?:\+| |$)/); + } else { + $realcnt = 0; + } + + #print "==>$rawline\n"; + #print "-->$line\n"; + + if ($setup_docs && $line =~ /^\+/) { + push(@setup_docs, $line); + } + } + + $prefix = ''; + + $realcnt = 0; + $linenr = 0; + $fixlinenr = -1; + foreach my $line (@lines) { + $linenr++; + $fixlinenr++; + my $sline = $line; #copy of $line + $sline =~ s/$;/ /g; #with comments as spaces + + my $rawline = $rawlines[$linenr - 1]; + +#extract the line range in the file after the patch is applied + if (!$in_commit_log && + $line =~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) { + $is_patch = 1; + $first_line = $linenr + 1; + $realline=$1-1; + if (defined $2) { + $realcnt=$3+1; + } else { + $realcnt=1+1; + } + annotate_reset(); + $prev_values = 'E'; + + %suppress_ifbraces = (); + %suppress_whiletrailers = (); + %suppress_export = (); + $suppress_statement = 0; + next; + +# track the line number as we move through the hunk, note that +# new versions of GNU diff omit the leading space on completely +# blank context lines so we need to count that too. + } elsif ($line =~ /^( |\+|$)/) { + $realline++; + $realcnt-- if ($realcnt != 0); + + # Measure the line length and indent. + ($length, $indent) = line_stats($rawline); + + # Track the previous line. + ($prevline, $stashline) = ($stashline, $line); + ($previndent, $stashindent) = ($stashindent, $indent); + ($prevrawline, $stashrawline) = ($stashrawline, $rawline); + + #warn "line<$line>\n"; + + } elsif ($realcnt == 1) { + $realcnt--; + } + + my $hunk_line = ($realcnt != 0); + + $here = "#$linenr: " if (!$file); + $here = "#$realline: " if ($file); + + my $found_file = 0; + # extract the filename as it passes + if ($line =~ /^diff --git.*?(\S+)$/) { + $realfile = $1; + $realfile =~ s@^([^/]*)/@@ if (!$file); + $in_commit_log = 0; + $found_file = 1; + } elsif ($line =~ /^\+\+\+\s+(\S+)/) { + $realfile = $1; + $realfile =~ s@^([^/]*)/@@ if (!$file); + $in_commit_log = 0; + + $p1_prefix = $1; + if (!$file && $tree && $p1_prefix ne '' && + -e "$root/$p1_prefix") { + WARN("PATCH_PREFIX", + "patch prefix '$p1_prefix' exists, appears to be a -p0 patch\n"); + } + + if ($realfile =~ m@^include/asm/@) { + ERROR("MODIFIED_INCLUDE_ASM", + "do not modify files in include/asm, change architecture specific files in include/asm-\n" . "$here$rawline\n"); + } + $found_file = 1; + } + +#make up the handle for any error we report on this line + if ($showfile) { + $prefix = "$realfile:$realline: " + } elsif ($emacs) { + if ($file) { + $prefix = "$filename:$realline: "; + } else { + $prefix = "$filename:$linenr: "; + } + } + + if ($found_file) { + if ($realfile =~ m@^(?:drivers/net/|net/|drivers/staging/)@) { + $check = 1; + } else { + $check = $check_orig; + } + next; + } + + $here .= "FILE: $realfile:$realline:" if ($realcnt != 0); + + my $hereline = "$here\n$rawline\n"; + my $herecurr = "$here\n$rawline\n"; + my $hereprev = "$here\n$prevrawline\n$rawline\n"; + + $cnt_lines++ if ($realcnt != 0); + +# Check if the commit log has what seems like a diff which can confuse patch + if ($in_commit_log && !$commit_log_has_diff && + (($line =~ m@^\s+diff\b.*a/[\w/]+@ && + $line =~ m@^\s+diff\b.*a/([\w/]+)\s+b/$1\b@) || + $line =~ m@^\s*(?:\-\-\-\s+a/|\+\+\+\s+b/)@ || + $line =~ m/^\s*\@\@ \-\d+,\d+ \+\d+,\d+ \@\@/)) { + ERROR("DIFF_IN_COMMIT_MSG", + "Avoid using diff content in the commit message - patch(1) might not work\n" . $herecurr); + $commit_log_has_diff = 1; + } + +# Check for incorrect file permissions + if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) { + my $permhere = $here . "FILE: $realfile\n"; + if ($realfile !~ m@scripts/@ && + $realfile !~ /\.(py|pl|awk|sh)$/) { + ERROR("EXECUTE_PERMISSIONS", + "do not set execute permissions for source files\n" . $permhere); + } + } + +# Check the patch for a signoff: + if ($line =~ /^\s*signed-off-by:/i) { + $signoff++; + $in_commit_log = 0; + } + +# Check if MAINTAINERS is being updated. If so, there's probably no need to +# emit the "does MAINTAINERS need updating?" message on file add/move/delete + if ($line =~ /^\s*MAINTAINERS\s*\|/) { + $reported_maintainer_file = 1; + } + +# Check signature styles + if (!$in_header_lines && + $line =~ /^(\s*)([a-z0-9_-]+by:|$signature_tags)(\s*)(.*)/i) { + my $space_before = $1; + my $sign_off = $2; + my $space_after = $3; + my $email = $4; + my $ucfirst_sign_off = ucfirst(lc($sign_off)); + + if ($sign_off !~ /$signature_tags/) { + WARN("BAD_SIGN_OFF", + "Non-standard signature: $sign_off\n" . $herecurr); + } + if (defined $space_before && $space_before ne "") { + if (WARN("BAD_SIGN_OFF", + "Do not use whitespace before $ucfirst_sign_off\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] = + "$ucfirst_sign_off $email"; + } + } + if ($sign_off =~ /-by:$/i && $sign_off ne $ucfirst_sign_off) { + if (WARN("BAD_SIGN_OFF", + "'$ucfirst_sign_off' is the preferred signature form\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] = + "$ucfirst_sign_off $email"; + } + + } + if (!defined $space_after || $space_after ne " ") { + if (WARN("BAD_SIGN_OFF", + "Use a single space after $ucfirst_sign_off\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] = + "$ucfirst_sign_off $email"; + } + } + + my ($email_name, $email_address, $comment) = parse_email($email); + my $suggested_email = format_email(($email_name, $email_address)); + if ($suggested_email eq "") { + ERROR("BAD_SIGN_OFF", + "Unrecognized email address: '$email'\n" . $herecurr); + } else { + my $dequoted = $suggested_email; + $dequoted =~ s/^"//; + $dequoted =~ s/" $comment" ne $email && + "$suggested_email$comment" ne $email) { + WARN("BAD_SIGN_OFF", + "email address '$email' might be better as '$suggested_email$comment'\n" . $herecurr); + } + } + +# Check for duplicate signatures + my $sig_nospace = $line; + $sig_nospace =~ s/\s//g; + $sig_nospace = lc($sig_nospace); + if (defined $signatures{$sig_nospace}) { + WARN("BAD_SIGN_OFF", + "Duplicate signature\n" . $herecurr); + } else { + $signatures{$sig_nospace} = 1; + } + } + +# Check email subject for common tools that don't need to be mentioned + if ($in_header_lines && + $line =~ /^Subject:.*\b(?:checkpatch|sparse|smatch)\b[^:]/i) { + WARN("EMAIL_SUBJECT", + "A patch subject line should describe the change not the tool that found it\n" . $herecurr); + } + +# Check for old stable address + if ($line =~ /^\s*cc:\s*.*?.*$/i) { + ERROR("STABLE_ADDRESS", + "The 'stable' address should be 'stable\@vger.kernel.org'\n" . $herecurr); + } + +# Check for unwanted Gerrit info + if ($in_commit_log && $line =~ /^\s*change-id:/i) { + ERROR("GERRIT_CHANGE_ID", + "Remove Gerrit Change-Id's before submitting upstream.\n" . $herecurr); + } + +# Check if the commit log is in a possible stack dump + if ($in_commit_log && !$commit_log_possible_stack_dump && + ($line =~ /^\s*(?:WARNING:|BUG:)/ || + $line =~ /^\s*\[\s*\d+\.\d{6,6}\s*\]/ || + # timestamp + $line =~ /^\s*\[\<[0-9a-fA-F]{8,}\>\]/)) { + # stack dump address + $commit_log_possible_stack_dump = 1; + } + +# Check for line lengths > 75 in commit log, warn once + if ($in_commit_log && !$commit_log_long_line && + length($line) > 75 && + !($line =~ /^\s*[a-zA-Z0-9_\/\.]+\s+\|\s+\d+/ || + # file delta changes + $line =~ /^\s*(?:[\w\.\-]+\/)++[\w\.\-]+:/ || + # filename then : + $line =~ /^\s*(?:Fixes:|Link:)/i || + # A Fixes: or Link: line + $commit_log_possible_stack_dump)) { + WARN("COMMIT_LOG_LONG_LINE", + "Possible unwrapped commit description (prefer a maximum 75 chars per line)\n" . $herecurr); + $commit_log_long_line = 1; + } + +# Reset possible stack dump if a blank line is found + if ($in_commit_log && $commit_log_possible_stack_dump && + $line =~ /^\s*$/) { + $commit_log_possible_stack_dump = 0; + } + +# Check for git id commit length and improperly formed commit descriptions + if ($in_commit_log && !$commit_log_possible_stack_dump && + ($line =~ /\bcommit\s+[0-9a-f]{5,}\b/i || + ($line =~ /\b[0-9a-f]{12,40}\b/i && + $line !~ /[\<\[][0-9a-f]{12,40}[\>\]]/i && + $line !~ /\bfixes:\s*[0-9a-f]{12,40}/i))) { + my $init_char = "c"; + my $orig_commit = ""; + my $short = 1; + my $long = 0; + my $case = 1; + my $space = 1; + my $hasdesc = 0; + my $hasparens = 0; + my $id = '0123456789ab'; + my $orig_desc = "commit description"; + my $description = ""; + + if ($line =~ /\b(c)ommit\s+([0-9a-f]{5,})\b/i) { + $init_char = $1; + $orig_commit = lc($2); + } elsif ($line =~ /\b([0-9a-f]{12,40})\b/i) { + $orig_commit = lc($1); + } + + $short = 0 if ($line =~ /\bcommit\s+[0-9a-f]{12,40}/i); + $long = 1 if ($line =~ /\bcommit\s+[0-9a-f]{41,}/i); + $space = 0 if ($line =~ /\bcommit [0-9a-f]/i); + $case = 0 if ($line =~ /\b[Cc]ommit\s+[0-9a-f]{5,40}[^A-F]/); + if ($line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("([^"]+)"\)/i) { + $orig_desc = $1; + $hasparens = 1; + } elsif ($line =~ /\bcommit\s+[0-9a-f]{5,}\s*$/i && + defined $rawlines[$linenr] && + $rawlines[$linenr] =~ /^\s*\("([^"]+)"\)/) { + $orig_desc = $1; + $hasparens = 1; + } elsif ($line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("[^"]+$/i && + defined $rawlines[$linenr] && + $rawlines[$linenr] =~ /^\s*[^"]+"\)/) { + $line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("([^"]+)$/i; + $orig_desc = $1; + $rawlines[$linenr] =~ /^\s*([^"]+)"\)/; + $orig_desc .= " " . $1; + $hasparens = 1; + } + + ($id, $description) = git_commit_info($orig_commit, + $id, $orig_desc); + + if ($short || $long || $space || $case || ($orig_desc ne $description) || !$hasparens) { + ERROR("GIT_COMMIT_ID", + "Please use git commit description style 'commit <12+ chars of sha1> (\"\")' - ie: '${init_char}ommit $id (\"$description\")'\n" . $herecurr); + } + } + +# Check for added, moved or deleted files + if (!$reported_maintainer_file && !$in_commit_log && + ($line =~ /^(?:new|deleted) file mode\s*\d+\s*$/ || + $line =~ /^rename (?:from|to) [\w\/\.\-]+\s*$/ || + ($line =~ /\{\s*([\w\/\.\-]*)\s*\=\>\s*([\w\/\.\-]*)\s*\}/ && + (defined($1) || defined($2))))) { + $reported_maintainer_file = 1; + WARN("FILE_PATH_CHANGES", + "added, moved or deleted file(s), does MAINTAINERS need updating?\n" . $herecurr); + } + +# Check for wrappage within a valid hunk of the file + if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) { + ERROR("CORRUPTED_PATCH", + "patch seems to be corrupt (line wrapped?)\n" . + $herecurr) if (!$emitted_corrupt++); + } + +# Check for absolute kernel paths. + if ($tree) { + while ($line =~ m{(?:^|\s)(/\S*)}g) { + my $file = $1; + + if ($file =~ m{^(.*?)(?::\d+)+:?$} && + check_absolute_file($1, $herecurr)) { + # + } else { + check_absolute_file($file, $herecurr); + } + } + } + +# UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php + if (($realfile =~ /^$/ || $line =~ /^\+/) && + $rawline !~ m/^$UTF8*$/) { + my ($utf8_prefix) = ($rawline =~ /^($UTF8*)/); + + my $blank = copy_spacing($rawline); + my $ptr = substr($blank, 0, length($utf8_prefix)) . "^"; + my $hereptr = "$hereline$ptr\n"; + + CHK("INVALID_UTF8", + "Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $hereptr); + } + +# Check if it's the start of a commit log +# (not a header line and we haven't seen the patch filename) + if ($in_header_lines && $realfile =~ /^$/ && + !($rawline =~ /^\s+\S/ || + $rawline =~ /^(commit\b|from\b|[\w-]+:).*$/i)) { + $in_header_lines = 0; + $in_commit_log = 1; + } + +# Check if there is UTF-8 in a commit log when a mail header has explicitly +# declined it, i.e defined some charset where it is missing. + if ($in_header_lines && + $rawline =~ /^Content-Type:.+charset="(.+)".*$/ && + $1 !~ /utf-8/i) { + $non_utf8_charset = 1; + } + + if ($in_commit_log && $non_utf8_charset && $realfile =~ /^$/ && + $rawline =~ /$NON_ASCII_UTF8/) { + WARN("UTF8_BEFORE_PATCH", + "8-bit UTF-8 used in possible commit log\n" . $herecurr); + } + +# Check for various typo / spelling mistakes + if (defined($misspellings) && + ($in_commit_log || $line =~ /^(?:\+|Subject:)/i)) { + while ($rawline =~ /(?:^|[^a-z@])($misspellings)(?:\b|$|[^a-z@])/gi) { + my $typo = $1; + my $typo_fix = $spelling_fix{lc($typo)}; + $typo_fix = ucfirst($typo_fix) if ($typo =~ /^[A-Z]/); + $typo_fix = uc($typo_fix) if ($typo =~ /^[A-Z]+$/); + my $msg_type = \&WARN; + $msg_type = \&CHK if ($file); + if (&{$msg_type}("TYPO_SPELLING", + "'$typo' may be misspelled - perhaps '$typo_fix'?\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/(^|[^A-Za-z@])($typo)($|[^A-Za-z@])/$1$typo_fix$3/; + } + } + } + +# ignore non-hunk lines and lines being removed + next if (!$hunk_line || $line =~ /^-/); + +#trailing whitespace + if ($line =~ /^\+.*\015/) { + my $herevet = "$here\n" . cat_vet($rawline) . "\n"; + if (ERROR("DOS_LINE_ENDINGS", + "DOS line endings\n" . $herevet) && + $fix) { + $fixed[$fixlinenr] =~ s/[\s\015]+$//; + } + } elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) { + my $herevet = "$here\n" . cat_vet($rawline) . "\n"; + if (ERROR("TRAILING_WHITESPACE", + "trailing whitespace\n" . $herevet) && + $fix) { + $fixed[$fixlinenr] =~ s/\s+$//; + } + + $rpt_cleaners = 1; + } + +# Check for FSF mailing addresses. + if ($rawline =~ /\bwrite to the Free/i || + $rawline =~ /\b59\s+Temple\s+Pl/i || + $rawline =~ /\b51\s+Franklin\s+St/i) { + my $herevet = "$here\n" . cat_vet($rawline) . "\n"; + my $msg_type = \&ERROR; + $msg_type = \&CHK if ($file); + &{$msg_type}("FSF_MAILING_ADDRESS", + "Do not include the paragraph about writing to the Free Software Foundation's mailing address from the sample GPL notice. The FSF has changed addresses in the past, and may do so again. Linux already includes a copy of the GPL.\n" . $herevet) + } + +# check for Kconfig help text having a real description +# Only applies when adding the entry originally, after that we do not have +# sufficient context to determine whether it is indeed long enough. + if ($realfile =~ /Kconfig/ && + $line =~ /^\+\s*config\s+/) { + my $length = 0; + my $cnt = $realcnt; + my $ln = $linenr + 1; + my $f; + my $is_start = 0; + my $is_end = 0; + for (; $cnt > 0 && defined $lines[$ln - 1]; $ln++) { + $f = $lines[$ln - 1]; + $cnt-- if ($lines[$ln - 1] !~ /^-/); + $is_end = $lines[$ln - 1] =~ /^\+/; + + next if ($f =~ /^-/); + last if (!$file && $f =~ /^\@\@/); + + if ($lines[$ln - 1] =~ /^\+\s*(?:bool|tristate)\s*\"/) { + $is_start = 1; + } elsif ($lines[$ln - 1] =~ /^\+\s*(?:---)?help(?:---)?$/) { + $length = -1; + } + + $f =~ s/^.//; + $f =~ s/#.*//; + $f =~ s/^\s+//; + next if ($f =~ /^$/); + if ($f =~ /^\s*config\s/) { + $is_end = 1; + last; + } + $length++; + } + if ($is_start && $is_end && $length < $min_conf_desc_length) { + WARN("CONFIG_DESCRIPTION", + "please write a paragraph that describes the config symbol fully\n" . $herecurr); + } + #print "is_start<$is_start> is_end<$is_end> length<$length>\n"; + } + +# discourage the addition of CONFIG_EXPERIMENTAL in Kconfig. + if ($realfile =~ /Kconfig/ && + $line =~ /.\s*depends on\s+.*\bEXPERIMENTAL\b/) { + WARN("CONFIG_EXPERIMENTAL", + "Use of CONFIG_EXPERIMENTAL is deprecated. For alternatives, see https://lkml.org/lkml/2012/10/23/580\n"); + } + +# discourage the use of boolean for type definition attributes of Kconfig options + if ($realfile =~ /Kconfig/ && + $line =~ /^\+\s*\bboolean\b/) { + WARN("CONFIG_TYPE_BOOLEAN", + "Use of boolean is deprecated, please use bool instead.\n" . $herecurr); + } + + if (($realfile =~ /Makefile.*/ || $realfile =~ /Kbuild.*/) && + ($line =~ /\+(EXTRA_[A-Z]+FLAGS).*/)) { + my $flag = $1; + my $replacement = { + 'EXTRA_AFLAGS' => 'asflags-y', + 'EXTRA_CFLAGS' => 'ccflags-y', + 'EXTRA_CPPFLAGS' => 'cppflags-y', + 'EXTRA_LDFLAGS' => 'ldflags-y', + }; + + WARN("DEPRECATED_VARIABLE", + "Use of $flag is deprecated, please use \`$replacement->{$flag} instead.\n" . $herecurr) if ($replacement->{$flag}); + } + +# check for DT compatible documentation + if (defined $root && + (($realfile =~ /\.dtsi?$/ && $line =~ /^\+\s*compatible\s*=\s*\"/) || + ($realfile =~ /\.[ch]$/ && $line =~ /^\+.*\.compatible\s*=\s*\"/))) { + + my @compats = $rawline =~ /\"([a-zA-Z0-9\-\,\.\+_]+)\"/g; + + my $dt_path = $root . "/Documentation/devicetree/bindings/"; + my $vp_file = $dt_path . "vendor-prefixes.txt"; + + foreach my $compat (@compats) { + my $compat2 = $compat; + $compat2 =~ s/\,[a-zA-Z0-9]*\-/\,<\.\*>\-/; + my $compat3 = $compat; + $compat3 =~ s/\,([a-z]*)[0-9]*\-/\,$1<\.\*>\-/; + `grep -Erq "$compat|$compat2|$compat3" $dt_path`; + if ( $? >> 8 ) { + WARN("UNDOCUMENTED_DT_STRING", + "DT compatible string \"$compat\" appears un-documented -- check $dt_path\n" . $herecurr); + } + + next if $compat !~ /^([a-zA-Z0-9\-]+)\,/; + my $vendor = $1; + `grep -Eq "^$vendor\\b" $vp_file`; + if ( $? >> 8 ) { + WARN("UNDOCUMENTED_DT_STRING", + "DT compatible string vendor \"$vendor\" appears un-documented -- check $vp_file\n" . $herecurr); + } + } + } + +# check we are in a valid source file if not then ignore this hunk + next if ($realfile !~ /\.(h|c|s|S|pl|sh|dtsi|dts)$/); + +# line length limit (with some exclusions) +# +# There are a few types of lines that may extend beyond $max_line_length: +# logging functions like pr_info that end in a string +# lines with a single string +# #defines that are a single string +# +# There are 3 different line length message types: +# LONG_LINE_COMMENT a comment starts before but extends beyond $max_linelength +# LONG_LINE_STRING a string starts before but extends beyond $max_line_length +# LONG_LINE all other lines longer than $max_line_length +# +# if LONG_LINE is ignored, the other 2 types are also ignored +# + + if ($line =~ /^\+/ && $length > $max_line_length) { + my $msg_type = "LONG_LINE"; + + # Check the allowed long line types first + + # logging functions that end in a string that starts + # before $max_line_length + if ($line =~ /^\+\s*$logFunctions\s*\(\s*(?:(?:KERN_\S+\s*|[^"]*))?($String\s*(?:|,|\)\s*;)\s*)$/ && + length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) { + $msg_type = ""; + + # lines with only strings (w/ possible termination) + # #defines with only strings + } elsif ($line =~ /^\+\s*$String\s*(?:\s*|,|\)\s*;)\s*$/ || + $line =~ /^\+\s*#\s*define\s+\w+\s+$String$/) { + $msg_type = ""; + + # Otherwise set the alternate message types + + # a comment starts before $max_line_length + } elsif ($line =~ /($;[\s$;]*)$/ && + length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) { + $msg_type = "LONG_LINE_COMMENT" + + # a quoted string starts before $max_line_length + } elsif ($sline =~ /\s*($String(?:\s*(?:\\|,\s*|\)\s*;\s*))?)$/ && + length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) { + $msg_type = "LONG_LINE_STRING" + } + + if ($msg_type ne "" && + (show_type("LONG_LINE") || show_type($msg_type))) { + WARN($msg_type, + "line over $max_line_length characters\n" . $herecurr); + } + } + +# check for adding lines without a newline. + if ($line =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ No newline at end of file/) { + WARN("MISSING_EOF_NEWLINE", + "adding a line without newline at end of file\n" . $herecurr); + } + +# Blackfin: use hi/lo macros + if ($realfile =~ m@arch/blackfin/.*\.S$@) { + if ($line =~ /\.[lL][[:space:]]*=.*&[[:space:]]*0x[fF][fF][fF][fF]/) { + my $herevet = "$here\n" . cat_vet($line) . "\n"; + ERROR("LO_MACRO", + "use the LO() macro, not (... & 0xFFFF)\n" . $herevet); + } + if ($line =~ /\.[hH][[:space:]]*=.*>>[[:space:]]*16/) { + my $herevet = "$here\n" . cat_vet($line) . "\n"; + ERROR("HI_MACRO", + "use the HI() macro, not (... >> 16)\n" . $herevet); + } + } + +# check we are in a valid source file C or perl if not then ignore this hunk + next if ($realfile !~ /\.(h|c|pl|dtsi|dts)$/); + +# at the beginning of a line any tabs must come first and anything +# more than 8 must use tabs. + if ($rawline =~ /^\+\s* \t\s*\S/ || + $rawline =~ /^\+\s* \s*/) { + my $herevet = "$here\n" . cat_vet($rawline) . "\n"; + $rpt_cleaners = 1; + if (ERROR("CODE_INDENT", + "code indent should use tabs where possible\n" . $herevet) && + $fix) { + $fixed[$fixlinenr] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e; + } + } + +# check for space before tabs. + if ($rawline =~ /^\+/ && $rawline =~ / \t/) { + my $herevet = "$here\n" . cat_vet($rawline) . "\n"; + if (WARN("SPACE_BEFORE_TAB", + "please, no space before tabs\n" . $herevet) && + $fix) { + while ($fixed[$fixlinenr] =~ + s/(^\+.*) {8,8}\t/$1\t\t/) {} + while ($fixed[$fixlinenr] =~ + s/(^\+.*) +\t/$1\t/) {} + } + } + +# check for && or || at the start of a line + if ($rawline =~ /^\+\s*(&&|\|\|)/) { + CHK("LOGICAL_CONTINUATIONS", + "Logical continuations should be on the previous line\n" . $hereprev); + } + +# check multi-line statement indentation matches previous line + if ($^V && $^V ge 5.10.0 && + $prevline =~ /^\+([ \t]*)((?:$c90_Keywords(?:\s+if)\s*)|(?:$Declare\s*)?(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*|$Ident\s*=\s*$Ident\s*)\(.*(\&\&|\|\||,)\s*$/) { + $prevline =~ /^\+(\t*)(.*)$/; + my $oldindent = $1; + my $rest = $2; + + my $pos = pos_last_openparen($rest); + if ($pos >= 0) { + $line =~ /^(\+| )([ \t]*)/; + my $newindent = $2; + + my $goodtabindent = $oldindent . + "\t" x ($pos / 8) . + " " x ($pos % 8); + my $goodspaceindent = $oldindent . " " x $pos; + + if ($newindent ne $goodtabindent && + $newindent ne $goodspaceindent) { + + if (CHK("PARENTHESIS_ALIGNMENT", + "Alignment should match open parenthesis\n" . $hereprev) && + $fix && $line =~ /^\+/) { + $fixed[$fixlinenr] =~ + s/^\+[ \t]*/\+$goodtabindent/; + } + } + } + } + +# check for space after cast like "(int) foo" or "(struct foo) bar" +# avoid checking a few false positives: +# "sizeof(<type>)" or "__alignof__(<type>)" +# function pointer declarations like "(*foo)(int) = bar;" +# structure definitions like "(struct foo) { 0 };" +# multiline macros that define functions +# known attributes or the __attribute__ keyword + if ($line =~ /^\+(.*)\(\s*$Type\s*\)([ \t]++)((?![={]|\\$|$Attribute|__attribute__))/ && + (!defined($1) || $1 !~ /\b(?:sizeof|__alignof__)\s*$/)) { + if (CHK("SPACING", + "No space is necessary after a cast\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ + s/(\(\s*$Type\s*\))[ \t]+/$1/; + } + } + +# Block comment styles +# Networking with an initial /* + if ($realfile =~ m@^(drivers/net/|net/)@ && + $prevrawline =~ /^\+[ \t]*\/\*[ \t]*$/ && + $rawline =~ /^\+[ \t]*\*/ && + $realline > 2) { + WARN("NETWORKING_BLOCK_COMMENT_STYLE", + "networking block comments don't use an empty /* line, use /* Comment...\n" . $hereprev); + } + +# Block comments use * on subsequent lines + if ($prevline =~ /$;[ \t]*$/ && #ends in comment + $prevrawline =~ /^\+.*?\/\*/ && #starting /* + $prevrawline !~ /\*\/[ \t]*$/ && #no trailing */ + $rawline =~ /^\+/ && #line is new + $rawline !~ /^\+[ \t]*\*/) { #no leading * + WARN("BLOCK_COMMENT_STYLE", + "Block comments use * on subsequent lines\n" . $hereprev); + } + +# Block comments use */ on trailing lines + if ($rawline !~ m@^\+[ \t]*\*/[ \t]*$@ && #trailing */ + $rawline !~ m@^\+.*/\*.*\*/[ \t]*$@ && #inline /*...*/ + $rawline !~ m@^\+.*\*{2,}/[ \t]*$@ && #trailing **/ + $rawline =~ m@^\+[ \t]*.+\*\/[ \t]*$@) { #non blank */ + WARN("BLOCK_COMMENT_STYLE", + "Block comments use a trailing */ on a separate line\n" . $herecurr); + } + +# check for missing blank lines after struct/union declarations +# with exceptions for various attributes and macros + if ($prevline =~ /^[\+ ]};?\s*$/ && + $line =~ /^\+/ && + !($line =~ /^\+\s*$/ || + $line =~ /^\+\s*EXPORT_SYMBOL/ || + $line =~ /^\+\s*MODULE_/i || + $line =~ /^\+\s*\#\s*(?:end|elif|else)/ || + $line =~ /^\+[a-z_]*init/ || + $line =~ /^\+\s*(?:static\s+)?[A-Z_]*ATTR/ || + $line =~ /^\+\s*DECLARE/ || + $line =~ /^\+\s*__setup/)) { + if (CHK("LINE_SPACING", + "Please use a blank line after function/struct/union/enum declarations\n" . $hereprev) && + $fix) { + fix_insert_line($fixlinenr, "\+"); + } + } + +# check for multiple consecutive blank lines + if ($prevline =~ /^[\+ ]\s*$/ && + $line =~ /^\+\s*$/ && + $last_blank_line != ($linenr - 1)) { + if (CHK("LINE_SPACING", + "Please don't use multiple blank lines\n" . $hereprev) && + $fix) { + fix_delete_line($fixlinenr, $rawline); + } + + $last_blank_line = $linenr; + } + +# check for missing blank lines after declarations + if ($sline =~ /^\+\s+\S/ && #Not at char 1 + # actual declarations + ($prevline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ || + # function pointer declarations + $prevline =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ || + # foo bar; where foo is some local typedef or #define + $prevline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ || + # known declaration macros + $prevline =~ /^\+\s+$declaration_macros/) && + # for "else if" which can look like "$Ident $Ident" + !($prevline =~ /^\+\s+$c90_Keywords\b/ || + # other possible extensions of declaration lines + $prevline =~ /(?:$Compare|$Assignment|$Operators)\s*$/ || + # not starting a section or a macro "\" extended line + $prevline =~ /(?:\{\s*|\\)$/) && + # looks like a declaration + !($sline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ || + # function pointer declarations + $sline =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ || + # foo bar; where foo is some local typedef or #define + $sline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ || + # known declaration macros + $sline =~ /^\+\s+$declaration_macros/ || + # start of struct or union or enum + $sline =~ /^\+\s+(?:union|struct|enum|typedef)\b/ || + # start or end of block or continuation of declaration + $sline =~ /^\+\s+(?:$|[\{\}\.\#\"\?\:\(\[])/ || + # bitfield continuation + $sline =~ /^\+\s+$Ident\s*:\s*\d+\s*[,;]/ || + # other possible extensions of declaration lines + $sline =~ /^\+\s+\(?\s*(?:$Compare|$Assignment|$Operators)/) && + # indentation of previous and current line are the same + (($prevline =~ /\+(\s+)\S/) && $sline =~ /^\+$1\S/)) { + if (WARN("LINE_SPACING", + "Missing a blank line after declarations\n" . $hereprev) && + $fix) { + fix_insert_line($fixlinenr, "\+"); + } + } + +# check for spaces at the beginning of a line. +# Exceptions: +# 1) within comments +# 2) indented preprocessor commands +# 3) hanging labels + if ($rawline =~ /^\+ / && $line !~ /^\+ *(?:$;|#|$Ident:)/) { + my $herevet = "$here\n" . cat_vet($rawline) . "\n"; + if (WARN("LEADING_SPACE", + "please, no spaces at the start of a line\n" . $herevet) && + $fix) { + $fixed[$fixlinenr] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e; + } + } + +# check we are in a valid C source file if not then ignore this hunk + next if ($realfile !~ /\.(h|c)$/); + +# check indentation of any line with a bare else +# (but not if it is a multiple line "if (foo) return bar; else return baz;") +# if the previous line is a break or return and is indented 1 tab more... + if ($sline =~ /^\+([\t]+)(?:}[ \t]*)?else(?:[ \t]*{)?\s*$/) { + my $tabs = length($1) + 1; + if ($prevline =~ /^\+\t{$tabs,$tabs}break\b/ || + ($prevline =~ /^\+\t{$tabs,$tabs}return\b/ && + defined $lines[$linenr] && + $lines[$linenr] !~ /^[ \+]\t{$tabs,$tabs}return/)) { + WARN("UNNECESSARY_ELSE", + "else is not generally useful after a break or return\n" . $hereprev); + } + } + +# check indentation of a line with a break; +# if the previous line is a goto or return and is indented the same # of tabs + if ($sline =~ /^\+([\t]+)break\s*;\s*$/) { + my $tabs = $1; + if ($prevline =~ /^\+$tabs(?:goto|return)\b/) { + WARN("UNNECESSARY_BREAK", + "break is not useful after a goto or return\n" . $hereprev); + } + } + +# discourage the addition of CONFIG_EXPERIMENTAL in #if(def). + if ($line =~ /^\+\s*\#\s*if.*\bCONFIG_EXPERIMENTAL\b/) { + WARN("CONFIG_EXPERIMENTAL", + "Use of CONFIG_EXPERIMENTAL is deprecated. For alternatives, see https://lkml.org/lkml/2012/10/23/580\n"); + } + +# check for RCS/CVS revision markers + if ($rawline =~ /^\+.*\$(Revision|Log|Id)(?:\$|)/) { + WARN("CVS_KEYWORD", + "CVS style keyword markers, these will _not_ be updated\n". $herecurr); + } + +# Blackfin: don't use __builtin_bfin_[cs]sync + if ($line =~ /__builtin_bfin_csync/) { + my $herevet = "$here\n" . cat_vet($line) . "\n"; + ERROR("CSYNC", + "use the CSYNC() macro in asm/blackfin.h\n" . $herevet); + } + if ($line =~ /__builtin_bfin_ssync/) { + my $herevet = "$here\n" . cat_vet($line) . "\n"; + ERROR("SSYNC", + "use the SSYNC() macro in asm/blackfin.h\n" . $herevet); + } + +# check for old HOTPLUG __dev<foo> section markings + if ($line =~ /\b(__dev(init|exit)(data|const|))\b/) { + WARN("HOTPLUG_SECTION", + "Using $1 is unnecessary\n" . $herecurr); + } + +# Check for potential 'bare' types + my ($stat, $cond, $line_nr_next, $remain_next, $off_next, + $realline_next); +#print "LINE<$line>\n"; + if ($linenr >= $suppress_statement && + $realcnt && $sline =~ /.\s*\S/) { + ($stat, $cond, $line_nr_next, $remain_next, $off_next) = + ctx_statement_block($linenr, $realcnt, 0); + $stat =~ s/\n./\n /g; + $cond =~ s/\n./\n /g; + +#print "linenr<$linenr> <$stat>\n"; + # If this statement has no statement boundaries within + # it there is no point in retrying a statement scan + # until we hit end of it. + my $frag = $stat; $frag =~ s/;+\s*$//; + if ($frag !~ /(?:{|;)/) { +#print "skip<$line_nr_next>\n"; + $suppress_statement = $line_nr_next; + } + + # Find the real next line. + $realline_next = $line_nr_next; + if (defined $realline_next && + (!defined $lines[$realline_next - 1] || + substr($lines[$realline_next - 1], $off_next) =~ /^\s*$/)) { + $realline_next++; + } + + my $s = $stat; + $s =~ s/{.*$//s; + + # Ignore goto labels. + if ($s =~ /$Ident:\*$/s) { + + # Ignore functions being called + } elsif ($s =~ /^.\s*$Ident\s*\(/s) { + + } elsif ($s =~ /^.\s*else\b/s) { + + # declarations always start with types + } elsif ($prev_values eq 'E' && $s =~ /^.\s*(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?((?:\s*$Ident)+?)\b(?:\s+$Sparse)?\s*\**\s*(?:$Ident|\(\*[^\)]*\))(?:\s*$Modifier)?\s*(?:;|=|,|\()/s) { + my $type = $1; + $type =~ s/\s+/ /g; + possible($type, "A:" . $s); + + # definitions in global scope can only start with types + } elsif ($s =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b\s*(?!:)/s) { + possible($1, "B:" . $s); + } + + # any (foo ... *) is a pointer cast, and foo is a type + while ($s =~ /\(($Ident)(?:\s+$Sparse)*[\s\*]+\s*\)/sg) { + possible($1, "C:" . $s); + } + + # Check for any sort of function declaration. + # int foo(something bar, other baz); + # void (*store_gdt)(x86_descr_ptr *); + if ($prev_values eq 'E' && $s =~ /^(.(?:typedef\s*)?(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*(?:\b$Ident|\(\*\s*$Ident\))\s*)\(/s) { + my ($name_len) = length($1); + + my $ctx = $s; + substr($ctx, 0, $name_len + 1, ''); + $ctx =~ s/\)[^\)]*$//; + + for my $arg (split(/\s*,\s*/, $ctx)) { + if ($arg =~ /^(?:const\s+)?($Ident)(?:\s+$Sparse)*\s*\**\s*(:?\b$Ident)?$/s || $arg =~ /^($Ident)$/s) { + + possible($1, "D:" . $s); + } + } + } + + } + +# +# Checks which may be anchored in the context. +# + +# Check for switch () and associated case and default +# statements should be at the same indent. + if ($line=~/\bswitch\s*\(.*\)/) { + my $err = ''; + my $sep = ''; + my @ctx = ctx_block_outer($linenr, $realcnt); + shift(@ctx); + for my $ctx (@ctx) { + my ($clen, $cindent) = line_stats($ctx); + if ($ctx =~ /^\+\s*(case\s+|default:)/ && + $indent != $cindent) { + $err .= "$sep$ctx\n"; + $sep = ''; + } else { + $sep = "[...]\n"; + } + } + if ($err ne '') { + ERROR("SWITCH_CASE_INDENT_LEVEL", + "switch and case should be at the same indent\n$hereline$err"); + } + } + +# if/while/etc brace do not go on next line, unless defining a do while loop, +# or if that brace on the next line is for something else + if ($line =~ /(.*)\b((?:if|while|for|switch|(?:[a-z_]+|)for_each[a-z_]+)\s*\(|do\b|else\b)/ && $line !~ /^.\s*\#/) { + my $pre_ctx = "$1$2"; + + my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0); + + if ($line =~ /^\+\t{6,}/) { + WARN("DEEP_INDENTATION", + "Too many leading tabs - consider code refactoring\n" . $herecurr); + } + + my $ctx_cnt = $realcnt - $#ctx - 1; + my $ctx = join("\n", @ctx); + + my $ctx_ln = $linenr; + my $ctx_skip = $realcnt; + + while ($ctx_skip > $ctx_cnt || ($ctx_skip == $ctx_cnt && + defined $lines[$ctx_ln - 1] && + $lines[$ctx_ln - 1] =~ /^-/)) { + ##print "SKIP<$ctx_skip> CNT<$ctx_cnt>\n"; + $ctx_skip-- if (!defined $lines[$ctx_ln - 1] || $lines[$ctx_ln - 1] !~ /^-/); + $ctx_ln++; + } + + #print "realcnt<$realcnt> ctx_cnt<$ctx_cnt>\n"; + #print "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n"; + + if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln - 1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) { + ERROR("OPEN_BRACE", + "that open brace { should be on the previous line\n" . + "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n"); + } + if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ && + $ctx =~ /\)\s*\;\s*$/ && + defined $lines[$ctx_ln - 1]) + { + my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]); + if ($nindent > $indent) { + WARN("TRAILING_SEMICOLON", + "trailing semicolon indicates no statements, indent implies otherwise\n" . + "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n"); + } + } + } + +# Check relative indent for conditionals and blocks. + if ($line =~ /\b(?:(?:if|while|for|(?:[a-z_]+|)for_each[a-z_]+)\s*\(|do\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) { + ($stat, $cond, $line_nr_next, $remain_next, $off_next) = + ctx_statement_block($linenr, $realcnt, 0) + if (!defined $stat); + my ($s, $c) = ($stat, $cond); + + substr($s, 0, length($c), ''); + + # remove inline comments + $s =~ s/$;/ /g; + $c =~ s/$;/ /g; + + # Find out how long the conditional actually is. + my @newlines = ($c =~ /\n/gs); + my $cond_lines = 1 + $#newlines; + + # Make sure we remove the line prefixes as we have + # none on the first line, and are going to readd them + # where necessary. + $s =~ s/\n./\n/gs; + while ($s =~ /\n\s+\\\n/) { + $cond_lines += $s =~ s/\n\s+\\\n/\n/g; + } + + # We want to check the first line inside the block + # starting at the end of the conditional, so remove: + # 1) any blank line termination + # 2) any opening brace { on end of the line + # 3) any do (...) { + my $continuation = 0; + my $check = 0; + $s =~ s/^.*\bdo\b//; + $s =~ s/^\s*{//; + if ($s =~ s/^\s*\\//) { + $continuation = 1; + } + if ($s =~ s/^\s*?\n//) { + $check = 1; + $cond_lines++; + } + + # Also ignore a loop construct at the end of a + # preprocessor statement. + if (($prevline =~ /^.\s*#\s*define\s/ || + $prevline =~ /\\\s*$/) && $continuation == 0) { + $check = 0; + } + + my $cond_ptr = -1; + $continuation = 0; + while ($cond_ptr != $cond_lines) { + $cond_ptr = $cond_lines; + + # If we see an #else/#elif then the code + # is not linear. + if ($s =~ /^\s*\#\s*(?:else|elif)/) { + $check = 0; + } + + # Ignore: + # 1) blank lines, they should be at 0, + # 2) preprocessor lines, and + # 3) labels. + if ($continuation || + $s =~ /^\s*?\n/ || + $s =~ /^\s*#\s*?/ || + $s =~ /^\s*$Ident\s*:/) { + $continuation = ($s =~ /^.*?\\\n/) ? 1 : 0; + if ($s =~ s/^.*?\n//) { + $cond_lines++; + } + } + } + + my (undef, $sindent) = line_stats("+" . $s); + my $stat_real = raw_line($linenr, $cond_lines); + + # Check if either of these lines are modified, else + # this is not this patch's fault. + if (!defined($stat_real) || + $stat !~ /^\+/ && $stat_real !~ /^\+/) { + $check = 0; + } + if (defined($stat_real) && $cond_lines > 1) { + $stat_real = "[...]\n$stat_real"; + } + + #print "line<$line> prevline<$prevline> indent<$indent> sindent<$sindent> check<$check> continuation<$continuation> s<$s> cond_lines<$cond_lines> stat_real<$stat_real> stat<$stat>\n"; + + if ($check && $s ne '' && + (($sindent % 8) != 0 || + ($sindent < $indent) || + ($sindent > $indent + 8))) { + WARN("SUSPECT_CODE_INDENT", + "suspect code indent for conditional statements ($indent, $sindent)\n" . $herecurr . "$stat_real\n"); + } + } + + # Track the 'values' across context and added lines. + my $opline = $line; $opline =~ s/^./ /; + my ($curr_values, $curr_vars) = + annotate_values($opline . "\n", $prev_values); + $curr_values = $prev_values . $curr_values; + if ($dbg_values) { + my $outline = $opline; $outline =~ s/\t/ /g; + print "$linenr > .$outline\n"; + print "$linenr > $curr_values\n"; + print "$linenr > $curr_vars\n"; + } + $prev_values = substr($curr_values, -1); + +#ignore lines not being added + next if ($line =~ /^[^\+]/); + +# check for declarations of signed or unsigned without int + while ($line =~ m{($Declare)\s*(?!char\b|short\b|int\b|long\b)\s*($Ident)?\s*[=,;\[\)\(]}g) { + my $type = $1; + my $var = $2; + $var = "" if (!defined $var); + if ($type =~ /^(?:(?:$Storage|$Inline|$Attribute)\s+)*((?:un)?signed)((?:\s*\*)*)\s*$/) { + my $sign = $1; + my $pointer = $2; + + $pointer = "" if (!defined $pointer); + + if (WARN("UNSPECIFIED_INT", + "Prefer '" . trim($sign) . " int" . rtrim($pointer) . "' to bare use of '$sign" . rtrim($pointer) . "'\n" . $herecurr) && + $fix) { + my $decl = trim($sign) . " int "; + my $comp_pointer = $pointer; + $comp_pointer =~ s/\s//g; + $decl .= $comp_pointer; + $decl = rtrim($decl) if ($var eq ""); + $fixed[$fixlinenr] =~ s@\b$sign\s*\Q$pointer\E\s*$var\b@$decl$var@; + } + } + } + +# TEST: allow direct testing of the type matcher. + if ($dbg_type) { + if ($line =~ /^.\s*$Declare\s*$/) { + ERROR("TEST_TYPE", + "TEST: is type\n" . $herecurr); + } elsif ($dbg_type > 1 && $line =~ /^.+($Declare)/) { + ERROR("TEST_NOT_TYPE", + "TEST: is not type ($1 is)\n". $herecurr); + } + next; + } +# TEST: allow direct testing of the attribute matcher. + if ($dbg_attr) { + if ($line =~ /^.\s*$Modifier\s*$/) { + ERROR("TEST_ATTR", + "TEST: is attr\n" . $herecurr); + } elsif ($dbg_attr > 1 && $line =~ /^.+($Modifier)/) { + ERROR("TEST_NOT_ATTR", + "TEST: is not attr ($1 is)\n". $herecurr); + } + next; + } + +# check for initialisation to aggregates open brace on the next line + if ($line =~ /^.\s*{/ && + $prevline =~ /(?:^|[^=])=\s*$/) { + if (ERROR("OPEN_BRACE", + "that open brace { should be on the previous line\n" . $hereprev) && + $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { + fix_delete_line($fixlinenr - 1, $prevrawline); + fix_delete_line($fixlinenr, $rawline); + my $fixedline = $prevrawline; + $fixedline =~ s/\s*=\s*$/ = {/; + fix_insert_line($fixlinenr, $fixedline); + $fixedline = $line; + $fixedline =~ s/^(.\s*){\s*/$1/; + fix_insert_line($fixlinenr, $fixedline); + } + } + +# +# Checks which are anchored on the added line. +# + +# check for malformed paths in #include statements (uses RAW line) + if ($rawline =~ m{^.\s*\#\s*include\s+[<"](.*)[">]}) { + my $path = $1; + if ($path =~ m{//}) { + ERROR("MALFORMED_INCLUDE", + "malformed #include filename\n" . $herecurr); + } + if ($path =~ "^uapi/" && $realfile =~ m@\binclude/uapi/@) { + ERROR("UAPI_INCLUDE", + "No #include in ...include/uapi/... should use a uapi/ path prefix\n" . $herecurr); + } + } + +# no C99 // comments + if ($line =~ m{//}) { + if (ERROR("C99_COMMENTS", + "do not use C99 // comments\n" . $herecurr) && + $fix) { + my $line = $fixed[$fixlinenr]; + if ($line =~ /\/\/(.*)$/) { + my $comment = trim($1); + $fixed[$fixlinenr] =~ s@\/\/(.*)$@/\* $comment \*/@; + } + } + } + # Remove C99 comments. + $line =~ s@//.*@@; + $opline =~ s@//.*@@; + +# EXPORT_SYMBOL should immediately follow the thing it is exporting, consider +# the whole statement. +#print "APW <$lines[$realline_next - 1]>\n"; + if (defined $realline_next && + exists $lines[$realline_next - 1] && + !defined $suppress_export{$realline_next} && + ($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/ || + $lines[$realline_next - 1] =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) { + # Handle definitions which produce identifiers with + # a prefix: + # XXX(foo); + # EXPORT_SYMBOL(something_foo); + my $name = $1; + if ($stat =~ /^(?:.\s*}\s*\n)?.([A-Z_]+)\s*\(\s*($Ident)/ && + $name =~ /^${Ident}_$2/) { +#print "FOO C name<$name>\n"; + $suppress_export{$realline_next} = 1; + + } elsif ($stat !~ /(?: + \n.}\s*$| + ^.DEFINE_$Ident\(\Q$name\E\)| + ^.DECLARE_$Ident\(\Q$name\E\)| + ^.LIST_HEAD\(\Q$name\E\)| + ^.(?:$Storage\s+)?$Type\s*\(\s*\*\s*\Q$name\E\s*\)\s*\(| + \b\Q$name\E(?:\s+$Attribute)*\s*(?:;|=|\[|\() + )/x) { +#print "FOO A<$lines[$realline_next - 1]> stat<$stat> name<$name>\n"; + $suppress_export{$realline_next} = 2; + } else { + $suppress_export{$realline_next} = 1; + } + } + if (!defined $suppress_export{$linenr} && + $prevline =~ /^.\s*$/ && + ($line =~ /EXPORT_SYMBOL.*\((.*)\)/ || + $line =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) { +#print "FOO B <$lines[$linenr - 1]>\n"; + $suppress_export{$linenr} = 2; + } + if (defined $suppress_export{$linenr} && + $suppress_export{$linenr} == 2) { + WARN("EXPORT_SYMBOL", + "EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr); + } + +# check for global initialisers. + if ($line =~ /^\+$Type\s*$Ident(?:\s+$Modifier)*\s*=\s*($zero_initializer)\s*;/) { + if (ERROR("GLOBAL_INITIALISERS", + "do not initialise globals to $1\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/(^.$Type\s*$Ident(?:\s+$Modifier)*)\s*=\s*$zero_initializer\s*;/$1;/; + } + } +# check for static initialisers. + if ($line =~ /^\+.*\bstatic\s.*=\s*($zero_initializer)\s*;/) { + if (ERROR("INITIALISED_STATIC", + "do not initialise statics to $1\n" . + $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/(\bstatic\s.*?)\s*=\s*$zero_initializer\s*;/$1;/; + } + } + +# check for misordered declarations of char/short/int/long with signed/unsigned + while ($sline =~ m{(\b$TypeMisordered\b)}g) { + my $tmp = trim($1); + WARN("MISORDERED_TYPE", + "type '$tmp' should be specified in [[un]signed] [short|int|long|long long] order\n" . $herecurr); + } + +# check for static const char * arrays. + if ($line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/) { + WARN("STATIC_CONST_CHAR_ARRAY", + "static const char * array should probably be static const char * const\n" . + $herecurr); + } + +# check for static char foo[] = "bar" declarations. + if ($line =~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=\s*"/) { + WARN("STATIC_CONST_CHAR_ARRAY", + "static char array declaration should probably be static const char\n" . + $herecurr); + } + +# check for const <foo> const where <foo> is not a pointer or array type + if ($sline =~ /\bconst\s+($BasicType)\s+const\b/) { + my $found = $1; + if ($sline =~ /\bconst\s+\Q$found\E\s+const\b\s*\*/) { + WARN("CONST_CONST", + "'const $found const *' should probably be 'const $found * const'\n" . $herecurr); + } elsif ($sline !~ /\bconst\s+\Q$found\E\s+const\s+\w+\s*\[/) { + WARN("CONST_CONST", + "'const $found const' should probably be 'const $found'\n" . $herecurr); + } + } + +# check for non-global char *foo[] = {"bar", ...} declarations. + if ($line =~ /^.\s+(?:static\s+|const\s+)?char\s+\*\s*\w+\s*\[\s*\]\s*=\s*\{/) { + WARN("STATIC_CONST_CHAR_ARRAY", + "char * array declaration might be better as static const\n" . + $herecurr); + } + +# check for sizeof(foo)/sizeof(foo[0]) that could be ARRAY_SIZE(foo) + if ($line =~ m@\bsizeof\s*\(\s*($Lval)\s*\)@) { + my $array = $1; + if ($line =~ m@\b(sizeof\s*\(\s*\Q$array\E\s*\)\s*/\s*sizeof\s*\(\s*\Q$array\E\s*\[\s*0\s*\]\s*\))@) { + my $array_div = $1; + if (WARN("ARRAY_SIZE", + "Prefer ARRAY_SIZE($array)\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\Q$array_div\E/ARRAY_SIZE($array)/; + } + } + } + +# check for function declarations without arguments like "int foo()" + if ($line =~ /(\b$Type\s+$Ident)\s*\(\s*\)/) { + if (ERROR("FUNCTION_WITHOUT_ARGS", + "Bad function definition - $1() should probably be $1(void)\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/(\b($Type)\s+($Ident))\s*\(\s*\)/$2 $3(void)/; + } + } + +# check for uses of DEFINE_PCI_DEVICE_TABLE + if ($line =~ /\bDEFINE_PCI_DEVICE_TABLE\s*\(\s*(\w+)\s*\)\s*=/) { + if (WARN("DEFINE_PCI_DEVICE_TABLE", + "Prefer struct pci_device_id over deprecated DEFINE_PCI_DEVICE_TABLE\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\b(?:static\s+|)DEFINE_PCI_DEVICE_TABLE\s*\(\s*(\w+)\s*\)\s*=\s*/static const struct pci_device_id $1\[\] = /; + } + } + +# check for new typedefs, only function parameters and sparse annotations +# make sense. + if ($line =~ /\btypedef\s/ && + $line !~ /\btypedef\s+$Type\s*\(\s*\*?$Ident\s*\)\s*\(/ && + $line !~ /\btypedef\s+$Type\s+$Ident\s*\(/ && + $line !~ /\b$typeTypedefs\b/ && + $line !~ /\b__bitwise(?:__|)\b/) { + WARN("NEW_TYPEDEFS", + "do not add new typedefs\n" . $herecurr); + } + +# * goes on variable not on type + # (char*[ const]) + while ($line =~ m{(\($NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)\))}g) { + #print "AA<$1>\n"; + my ($ident, $from, $to) = ($1, $2, $2); + + # Should start with a space. + $to =~ s/^(\S)/ $1/; + # Should not end with a space. + $to =~ s/\s+$//; + # '*'s should not have spaces between. + while ($to =~ s/\*\s+\*/\*\*/) { + } + +## print "1: from<$from> to<$to> ident<$ident>\n"; + if ($from ne $to) { + if (ERROR("POINTER_LOCATION", + "\"(foo$from)\" should be \"(foo$to)\"\n" . $herecurr) && + $fix) { + my $sub_from = $ident; + my $sub_to = $ident; + $sub_to =~ s/\Q$from\E/$to/; + $fixed[$fixlinenr] =~ + s@\Q$sub_from\E@$sub_to@; + } + } + } + while ($line =~ m{(\b$NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)($Ident))}g) { + #print "BB<$1>\n"; + my ($match, $from, $to, $ident) = ($1, $2, $2, $3); + + # Should start with a space. + $to =~ s/^(\S)/ $1/; + # Should not end with a space. + $to =~ s/\s+$//; + # '*'s should not have spaces between. + while ($to =~ s/\*\s+\*/\*\*/) { + } + # Modifiers should have spaces. + $to =~ s/(\b$Modifier$)/$1 /; + +## print "2: from<$from> to<$to> ident<$ident>\n"; + if ($from ne $to && $ident !~ /^$Modifier$/) { + if (ERROR("POINTER_LOCATION", + "\"foo${from}bar\" should be \"foo${to}bar\"\n" . $herecurr) && + $fix) { + + my $sub_from = $match; + my $sub_to = $match; + $sub_to =~ s/\Q$from\E/$to/; + $fixed[$fixlinenr] =~ + s@\Q$sub_from\E@$sub_to@; + } + } + } + +# avoid BUG() or BUG_ON() + if ($line =~ /\b(?:BUG|BUG_ON)\b/) { + my $msg_type = \&WARN; + $msg_type = \&CHK if ($file); + &{$msg_type}("AVOID_BUG", + "Avoid crashing the kernel - try using WARN_ON & recovery code rather than BUG() or BUG_ON()\n" . $herecurr); + } + +# avoid LINUX_VERSION_CODE + if ($line =~ /\bLINUX_VERSION_CODE\b/) { + WARN("LINUX_VERSION_CODE", + "LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged\n" . $herecurr); + } + +# check for uses of printk_ratelimit + if ($line =~ /\bprintk_ratelimit\s*\(/) { + WARN("PRINTK_RATELIMITED", + "Prefer printk_ratelimited or pr_<level>_ratelimited to printk_ratelimit\n" . $herecurr); + } + +# printk should use KERN_* levels. Note that follow on printk's on the +# same line do not need a level, so we use the current block context +# to try and find and validate the current printk. In summary the current +# printk includes all preceding printk's which have no newline on the end. +# we assume the first bad printk is the one to report. + if ($line =~ /\bprintk\((?!KERN_)\s*"/) { + my $ok = 0; + for (my $ln = $linenr - 1; $ln >= $first_line; $ln--) { + #print "CHECK<$lines[$ln - 1]\n"; + # we have a preceding printk if it ends + # with "\n" ignore it, else it is to blame + if ($lines[$ln - 1] =~ m{\bprintk\(}) { + if ($rawlines[$ln - 1] !~ m{\\n"}) { + $ok = 1; + } + last; + } + } + if ($ok == 0) { + WARN("PRINTK_WITHOUT_KERN_LEVEL", + "printk() should include KERN_ facility level\n" . $herecurr); + } + } + + if ($line =~ /\bprintk\s*\(\s*KERN_([A-Z]+)/) { + my $orig = $1; + my $level = lc($orig); + $level = "warn" if ($level eq "warning"); + my $level2 = $level; + $level2 = "dbg" if ($level eq "debug"); + WARN("PREFER_PR_LEVEL", + "Prefer [subsystem eg: netdev]_$level2([subsystem]dev, ... then dev_$level2(dev, ... then pr_$level(... to printk(KERN_$orig ...\n" . $herecurr); + } + + if ($line =~ /\bpr_warning\s*\(/) { + if (WARN("PREFER_PR_LEVEL", + "Prefer pr_warn(... to pr_warning(...\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ + s/\bpr_warning\b/pr_warn/; + } + } + + if ($line =~ /\bdev_printk\s*\(\s*KERN_([A-Z]+)/) { + my $orig = $1; + my $level = lc($orig); + $level = "warn" if ($level eq "warning"); + $level = "dbg" if ($level eq "debug"); + WARN("PREFER_DEV_LEVEL", + "Prefer dev_$level(... to dev_printk(KERN_$orig, ...\n" . $herecurr); + } + +# ENOSYS means "bad syscall nr" and nothing else. This will have a small +# number of false positives, but assembly files are not checked, so at +# least the arch entry code will not trigger this warning. + if ($line =~ /\bENOSYS\b/) { + WARN("ENOSYS", + "ENOSYS means 'invalid syscall nr' and nothing else\n" . $herecurr); + } + +# function brace can't be on same line, except for #defines of do while, +# or if closed on same line + if (($line=~/$Type\s*$Ident\(.*\).*\s*{/) and + !($line=~/\#\s*define.*do\s\{/) and !($line=~/}/)) { + if (ERROR("OPEN_BRACE", + "open brace '{' following function declarations go on the next line\n" . $herecurr) && + $fix) { + fix_delete_line($fixlinenr, $rawline); + my $fixed_line = $rawline; + $fixed_line =~ /(^..*$Type\s*$Ident\(.*\)\s*){(.*)$/; + my $line1 = $1; + my $line2 = $2; + fix_insert_line($fixlinenr, ltrim($line1)); + fix_insert_line($fixlinenr, "\+{"); + if ($line2 !~ /^\s*$/) { + fix_insert_line($fixlinenr, "\+\t" . trim($line2)); + } + } + } + +# open braces for enum, union and struct go on the same line. + if ($line =~ /^.\s*{/ && + $prevline =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?\s*$/) { + if (ERROR("OPEN_BRACE", + "open brace '{' following $1 go on the same line\n" . $hereprev) && + $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { + fix_delete_line($fixlinenr - 1, $prevrawline); + fix_delete_line($fixlinenr, $rawline); + my $fixedline = rtrim($prevrawline) . " {"; + fix_insert_line($fixlinenr, $fixedline); + $fixedline = $rawline; + $fixedline =~ s/^(.\s*){\s*/$1\t/; + if ($fixedline !~ /^\+\s*$/) { + fix_insert_line($fixlinenr, $fixedline); + } + } + } + +# missing space after union, struct or enum definition + if ($line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident){1,2}[=\{]/) { + if (WARN("SPACING", + "missing space after $1 definition\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ + s/^(.\s*(?:typedef\s+)?(?:enum|union|struct)(?:\s+$Ident){1,2})([=\{])/$1 $2/; + } + } + +# Function pointer declarations +# check spacing between type, funcptr, and args +# canonical declaration is "type (*funcptr)(args...)" + if ($line =~ /^.\s*($Declare)\((\s*)\*(\s*)($Ident)(\s*)\)(\s*)\(/) { + my $declare = $1; + my $pre_pointer_space = $2; + my $post_pointer_space = $3; + my $funcname = $4; + my $post_funcname_space = $5; + my $pre_args_space = $6; + +# the $Declare variable will capture all spaces after the type +# so check it for a missing trailing missing space but pointer return types +# don't need a space so don't warn for those. + my $post_declare_space = ""; + if ($declare =~ /(\s+)$/) { + $post_declare_space = $1; + $declare = rtrim($declare); + } + if ($declare !~ /\*$/ && $post_declare_space =~ /^$/) { + WARN("SPACING", + "missing space after return type\n" . $herecurr); + $post_declare_space = " "; + } + +# unnecessary space "type (*funcptr)(args...)" +# This test is not currently implemented because these declarations are +# equivalent to +# int foo(int bar, ...) +# and this is form shouldn't/doesn't generate a checkpatch warning. +# +# elsif ($declare =~ /\s{2,}$/) { +# WARN("SPACING", +# "Multiple spaces after return type\n" . $herecurr); +# } + +# unnecessary space "type ( *funcptr)(args...)" + if (defined $pre_pointer_space && + $pre_pointer_space =~ /^\s/) { + WARN("SPACING", + "Unnecessary space after function pointer open parenthesis\n" . $herecurr); + } + +# unnecessary space "type (* funcptr)(args...)" + if (defined $post_pointer_space && + $post_pointer_space =~ /^\s/) { + WARN("SPACING", + "Unnecessary space before function pointer name\n" . $herecurr); + } + +# unnecessary space "type (*funcptr )(args...)" + if (defined $post_funcname_space && + $post_funcname_space =~ /^\s/) { + WARN("SPACING", + "Unnecessary space after function pointer name\n" . $herecurr); + } + +# unnecessary space "type (*funcptr) (args...)" + if (defined $pre_args_space && + $pre_args_space =~ /^\s/) { + WARN("SPACING", + "Unnecessary space before function pointer arguments\n" . $herecurr); + } + + if (show_type("SPACING") && $fix) { + $fixed[$fixlinenr] =~ + s/^(.\s*)$Declare\s*\(\s*\*\s*$Ident\s*\)\s*\(/$1 . $declare . $post_declare_space . '(*' . $funcname . ')('/ex; + } + } + +# check for spacing round square brackets; allowed: +# 1. with a type on the left -- int [] a; +# 2. at the beginning of a line for slice initialisers -- [0...10] = 5, +# 3. inside a curly brace -- = { [0...10] = 5 } + while ($line =~ /(.*?\s)\[/g) { + my ($where, $prefix) = ($-[1], $1); + if ($prefix !~ /$Type\s+$/ && + ($where != 0 || $prefix !~ /^.\s+$/) && + $prefix !~ /[{,]\s+$/) { + if (ERROR("BRACKET_SPACE", + "space prohibited before open square bracket '['\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ + s/^(\+.*?)\s+\[/$1\[/; + } + } + } + +# check for spaces between functions and their parentheses. + while ($line =~ /($Ident)\s+\(/g) { + my $name = $1; + my $ctx_before = substr($line, 0, $-[1]); + my $ctx = "$ctx_before$name"; + + # Ignore those directives where spaces _are_ permitted. + if ($name =~ /^(?: + if|for|while|switch|return|case| + volatile|__volatile__| + __attribute__|format|__extension__| + asm|__asm__)$/x) + { + # cpp #define statements have non-optional spaces, ie + # if there is a space between the name and the open + # parenthesis it is simply not a parameter group. + } elsif ($ctx_before =~ /^.\s*\#\s*define\s*$/) { + + # cpp #elif statement condition may start with a ( + } elsif ($ctx =~ /^.\s*\#\s*elif\s*$/) { + + # If this whole things ends with a type its most + # likely a typedef for a function. + } elsif ($ctx =~ /$Type$/) { + + } else { + if (WARN("SPACING", + "space prohibited between function name and open parenthesis '('\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ + s/\b$name\s+\(/$name\(/; + } + } + } + +# Check operator spacing. + if (!($line=~/\#\s*include/)) { + my $fixed_line = ""; + my $line_fixed = 0; + + my $ops = qr{ + <<=|>>=|<=|>=|==|!=| + \+=|-=|\*=|\/=|%=|\^=|\|=|&=| + =>|->|<<|>>|<|>|=|!|~| + &&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%| + \?:|\?|: + }x; + my @elements = split(/($ops|;)/, $opline); + +## print("element count: <" . $#elements . ">\n"); +## foreach my $el (@elements) { +## print("el: <$el>\n"); +## } + + my @fix_elements = (); + my $off = 0; + + foreach my $el (@elements) { + push(@fix_elements, substr($rawline, $off, length($el))); + $off += length($el); + } + + $off = 0; + + my $blank = copy_spacing($opline); + my $last_after = -1; + + for (my $n = 0; $n < $#elements; $n += 2) { + + my $good = $fix_elements[$n] . $fix_elements[$n + 1]; + +## print("n: <$n> good: <$good>\n"); + + $off += length($elements[$n]); + + # Pick up the preceding and succeeding characters. + my $ca = substr($opline, 0, $off); + my $cc = ''; + if (length($opline) >= ($off + length($elements[$n + 1]))) { + $cc = substr($opline, $off + length($elements[$n + 1])); + } + my $cb = "$ca$;$cc"; + + my $a = ''; + $a = 'V' if ($elements[$n] ne ''); + $a = 'W' if ($elements[$n] =~ /\s$/); + $a = 'C' if ($elements[$n] =~ /$;$/); + $a = 'B' if ($elements[$n] =~ /(\[|\()$/); + $a = 'O' if ($elements[$n] eq ''); + $a = 'E' if ($ca =~ /^\s*$/); + + my $op = $elements[$n + 1]; + + my $c = ''; + if (defined $elements[$n + 2]) { + $c = 'V' if ($elements[$n + 2] ne ''); + $c = 'W' if ($elements[$n + 2] =~ /^\s/); + $c = 'C' if ($elements[$n + 2] =~ /^$;/); + $c = 'B' if ($elements[$n + 2] =~ /^(\)|\]|;)/); + $c = 'O' if ($elements[$n + 2] eq ''); + $c = 'E' if ($elements[$n + 2] =~ /^\s*\\$/); + } else { + $c = 'E'; + } + + my $ctx = "${a}x${c}"; + + my $at = "(ctx:$ctx)"; + + my $ptr = substr($blank, 0, $off) . "^"; + my $hereptr = "$hereline$ptr\n"; + + # Pull out the value of this operator. + my $op_type = substr($curr_values, $off + 1, 1); + + # Get the full operator variant. + my $opv = $op . substr($curr_vars, $off, 1); + + # Ignore operators passed as parameters. + if ($op_type ne 'V' && + $ca =~ /\s$/ && $cc =~ /^\s*[,\)]/) { + +# # Ignore comments +# } elsif ($op =~ /^$;+$/) { + + # ; should have either the end of line or a space or \ after it + } elsif ($op eq ';') { + if ($ctx !~ /.x[WEBC]/ && + $cc !~ /^\\/ && $cc !~ /^;/) { + if (ERROR("SPACING", + "space required after that '$op' $at\n" . $hereptr)) { + $good = $fix_elements[$n] . trim($fix_elements[$n + 1]) . " "; + $line_fixed = 1; + } + } + + # // is a comment + } elsif ($op eq '//') { + + # : when part of a bitfield + } elsif ($opv eq ':B') { + # skip the bitfield test for now + + # No spaces for: + # -> + } elsif ($op eq '->') { + if ($ctx =~ /Wx.|.xW/) { + if (ERROR("SPACING", + "spaces prohibited around that '$op' $at\n" . $hereptr)) { + $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); + if (defined $fix_elements[$n + 2]) { + $fix_elements[$n + 2] =~ s/^\s+//; + } + $line_fixed = 1; + } + } + + # , must not have a space before and must have a space on the right. + } elsif ($op eq ',') { + my $rtrim_before = 0; + my $space_after = 0; + if ($ctx =~ /Wx./) { + if (ERROR("SPACING", + "space prohibited before that '$op' $at\n" . $hereptr)) { + $line_fixed = 1; + $rtrim_before = 1; + } + } + if ($ctx !~ /.x[WEC]/ && $cc !~ /^}/) { + if (ERROR("SPACING", + "space required after that '$op' $at\n" . $hereptr)) { + $line_fixed = 1; + $last_after = $n; + $space_after = 1; + } + } + if ($rtrim_before || $space_after) { + if ($rtrim_before) { + $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); + } else { + $good = $fix_elements[$n] . trim($fix_elements[$n + 1]); + } + if ($space_after) { + $good .= " "; + } + } + + # '*' as part of a type definition -- reported already. + } elsif ($opv eq '*_') { + #warn "'*' is part of type\n"; + + # unary operators should have a space before and + # none after. May be left adjacent to another + # unary operator, or a cast + } elsif ($op eq '!' || $op eq '~' || + $opv eq '*U' || $opv eq '-U' || + $opv eq '&U' || $opv eq '&&U') { + if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) { + if (ERROR("SPACING", + "space required before that '$op' $at\n" . $hereptr)) { + if ($n != $last_after + 2) { + $good = $fix_elements[$n] . " " . ltrim($fix_elements[$n + 1]); + $line_fixed = 1; + } + } + } + if ($op eq '*' && $cc =~/\s*$Modifier\b/) { + # A unary '*' may be const + + } elsif ($ctx =~ /.xW/) { + if (ERROR("SPACING", + "space prohibited after that '$op' $at\n" . $hereptr)) { + $good = $fix_elements[$n] . rtrim($fix_elements[$n + 1]); + if (defined $fix_elements[$n + 2]) { + $fix_elements[$n + 2] =~ s/^\s+//; + } + $line_fixed = 1; + } + } + + # unary ++ and unary -- are allowed no space on one side. + } elsif ($op eq '++' or $op eq '--') { + if ($ctx !~ /[WEOBC]x[^W]/ && $ctx !~ /[^W]x[WOBEC]/) { + if (ERROR("SPACING", + "space required one side of that '$op' $at\n" . $hereptr)) { + $good = $fix_elements[$n] . trim($fix_elements[$n + 1]) . " "; + $line_fixed = 1; + } + } + if ($ctx =~ /Wx[BE]/ || + ($ctx =~ /Wx./ && $cc =~ /^;/)) { + if (ERROR("SPACING", + "space prohibited before that '$op' $at\n" . $hereptr)) { + $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); + $line_fixed = 1; + } + } + if ($ctx =~ /ExW/) { + if (ERROR("SPACING", + "space prohibited after that '$op' $at\n" . $hereptr)) { + $good = $fix_elements[$n] . trim($fix_elements[$n + 1]); + if (defined $fix_elements[$n + 2]) { + $fix_elements[$n + 2] =~ s/^\s+//; + } + $line_fixed = 1; + } + } + + # << and >> may either have or not have spaces both sides + } elsif ($op eq '<<' or $op eq '>>' or + $op eq '&' or $op eq '^' or $op eq '|' or + $op eq '+' or $op eq '-' or + $op eq '*' or $op eq '/' or + $op eq '%') + { + if ($check) { + if (defined $fix_elements[$n + 2] && $ctx !~ /[EW]x[EW]/) { + if (CHK("SPACING", + "spaces preferred around that '$op' $at\n" . $hereptr)) { + $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " "; + $fix_elements[$n + 2] =~ s/^\s+//; + $line_fixed = 1; + } + } elsif (!defined $fix_elements[$n + 2] && $ctx !~ /Wx[OE]/) { + if (CHK("SPACING", + "space preferred before that '$op' $at\n" . $hereptr)) { + $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]); + $line_fixed = 1; + } + } + } elsif ($ctx =~ /Wx[^WCE]|[^WCE]xW/) { + if (ERROR("SPACING", + "need consistent spacing around '$op' $at\n" . $hereptr)) { + $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " "; + if (defined $fix_elements[$n + 2]) { + $fix_elements[$n + 2] =~ s/^\s+//; + } + $line_fixed = 1; + } + } + + # A colon needs no spaces before when it is + # terminating a case value or a label. + } elsif ($opv eq ':C' || $opv eq ':L') { + if ($ctx =~ /Wx./) { + if (ERROR("SPACING", + "space prohibited before that '$op' $at\n" . $hereptr)) { + $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); + $line_fixed = 1; + } + } + + # All the others need spaces both sides. + } elsif ($ctx !~ /[EWC]x[CWE]/) { + my $ok = 0; + + # Ignore email addresses <foo@bar> + if (($op eq '<' && + $cc =~ /^\S+\@\S+>/) || + ($op eq '>' && + $ca =~ /<\S+\@\S+$/)) + { + $ok = 1; + } + + # for asm volatile statements + # ignore a colon with another + # colon immediately before or after + if (($op eq ':') && + ($ca =~ /:$/ || $cc =~ /^:/)) { + $ok = 1; + } + + # messages are ERROR, but ?: are CHK + if ($ok == 0) { + my $msg_type = \&ERROR; + $msg_type = \&CHK if (($op eq '?:' || $op eq '?' || $op eq ':') && $ctx =~ /VxV/); + + if (&{$msg_type}("SPACING", + "spaces required around that '$op' $at\n" . $hereptr)) { + $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " "; + if (defined $fix_elements[$n + 2]) { + $fix_elements[$n + 2] =~ s/^\s+//; + } + $line_fixed = 1; + } + } + } + $off += length($elements[$n + 1]); + +## print("n: <$n> GOOD: <$good>\n"); + + $fixed_line = $fixed_line . $good; + } + + if (($#elements % 2) == 0) { + $fixed_line = $fixed_line . $fix_elements[$#elements]; + } + + if ($fix && $line_fixed && $fixed_line ne $fixed[$fixlinenr]) { + $fixed[$fixlinenr] = $fixed_line; + } + + + } + +# check for whitespace before a non-naked semicolon + if ($line =~ /^\+.*\S\s+;\s*$/) { + if (WARN("SPACING", + "space prohibited before semicolon\n" . $herecurr) && + $fix) { + 1 while $fixed[$fixlinenr] =~ + s/^(\+.*\S)\s+;/$1;/; + } + } + +# check for multiple assignments + if ($line =~ /^.\s*$Lval\s*=\s*$Lval\s*=(?!=)/) { + CHK("MULTIPLE_ASSIGNMENTS", + "multiple assignments should be avoided\n" . $herecurr); + } + +## # check for multiple declarations, allowing for a function declaration +## # continuation. +## if ($line =~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Ident.*/ && +## $line !~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Type\s*$Ident.*/) { +## +## # Remove any bracketed sections to ensure we do not +## # falsly report the parameters of functions. +## my $ln = $line; +## while ($ln =~ s/\([^\(\)]*\)//g) { +## } +## if ($ln =~ /,/) { +## WARN("MULTIPLE_DECLARATION", +## "declaring multiple variables together should be avoided\n" . $herecurr); +## } +## } + +#need space before brace following if, while, etc + if (($line =~ /\(.*\)\{/ && $line !~ /\($Type\)\{/) || + $line =~ /do\{/) { + if (ERROR("SPACING", + "space required before the open brace '{'\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/^(\+.*(?:do|\))){/$1 {/; + } + } + +## # check for blank lines before declarations +## if ($line =~ /^.\t+$Type\s+$Ident(?:\s*=.*)?;/ && +## $prevrawline =~ /^.\s*$/) { +## WARN("SPACING", +## "No blank lines before declarations\n" . $hereprev); +## } +## + +# closing brace should have a space following it when it has anything +# on the line + if ($line =~ /}(?!(?:,|;|\)))\S/) { + if (ERROR("SPACING", + "space required after that close brace '}'\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ + s/}((?!(?:,|;|\)))\S)/} $1/; + } + } + +# check spacing on square brackets + if ($line =~ /\[\s/ && $line !~ /\[\s*$/) { + if (ERROR("SPACING", + "space prohibited after that open square bracket '['\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ + s/\[\s+/\[/; + } + } + if ($line =~ /\s\]/) { + if (ERROR("SPACING", + "space prohibited before that close square bracket ']'\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ + s/\s+\]/\]/; + } + } + +# check spacing on parentheses + if ($line =~ /\(\s/ && $line !~ /\(\s*(?:\\)?$/ && + $line !~ /for\s*\(\s+;/) { + if (ERROR("SPACING", + "space prohibited after that open parenthesis '('\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ + s/\(\s+/\(/; + } + } + if ($line =~ /(\s+)\)/ && $line !~ /^.\s*\)/ && + $line !~ /for\s*\(.*;\s+\)/ && + $line !~ /:\s+\)/) { + if (ERROR("SPACING", + "space prohibited before that close parenthesis ')'\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ + s/\s+\)/\)/; + } + } + +# check unnecessary parentheses around addressof/dereference single $Lvals +# ie: &(foo->bar) should be &foo->bar and *(foo->bar) should be *foo->bar + + while ($line =~ /(?:[^&]&\s*|\*)\(\s*($Ident\s*(?:$Member\s*)+)\s*\)/g) { + my $var = $1; + if (CHK("UNNECESSARY_PARENTHESES", + "Unnecessary parentheses around $var\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\(\s*\Q$var\E\s*\)/$var/; + } + } + +# check for unnecessary parentheses around function pointer uses +# ie: (foo->bar)(); should be foo->bar(); +# but not "if (foo->bar) (" to avoid some false positives + if ($line =~ /(\bif\s*|)(\(\s*$Ident\s*(?:$Member\s*)+\))[ \t]*\(/ && $1 !~ /^if/) { + my $var = $2; + if (CHK("UNNECESSARY_PARENTHESES", + "Unnecessary parentheses around function pointer $var\n" . $herecurr) && + $fix) { + my $var2 = deparenthesize($var); + $var2 =~ s/\s//g; + $fixed[$fixlinenr] =~ s/\Q$var\E/$var2/; + } + } + +#goto labels aren't indented, allow a single space however + if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and + !($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) { + if (WARN("INDENTED_LABEL", + "labels should not be indented\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ + s/^(.)\s+/$1/; + } + } + +# return is not a function + if (defined($stat) && $stat =~ /^.\s*return(\s*)\(/s) { + my $spacing = $1; + if ($^V && $^V ge 5.10.0 && + $stat =~ /^.\s*return\s*($balanced_parens)\s*;\s*$/) { + my $value = $1; + $value = deparenthesize($value); + if ($value =~ m/^\s*$FuncArg\s*(?:\?|$)/) { + ERROR("RETURN_PARENTHESES", + "return is not a function, parentheses are not required\n" . $herecurr); + } + } elsif ($spacing !~ /\s+/) { + ERROR("SPACING", + "space required before the open parenthesis '('\n" . $herecurr); + } + } + +# unnecessary return in a void function +# at end-of-function, with the previous line a single leading tab, then return; +# and the line before that not a goto label target like "out:" + if ($sline =~ /^[ \+]}\s*$/ && + $prevline =~ /^\+\treturn\s*;\s*$/ && + $linenr >= 3 && + $lines[$linenr - 3] =~ /^[ +]/ && + $lines[$linenr - 3] !~ /^[ +]\s*$Ident\s*:/) { + WARN("RETURN_VOID", + "void function return statements are not generally useful\n" . $hereprev); + } + +# if statements using unnecessary parentheses - ie: if ((foo == bar)) + if ($^V && $^V ge 5.10.0 && + $line =~ /\bif\s*((?:\(\s*){2,})/) { + my $openparens = $1; + my $count = $openparens =~ tr@\(@\(@; + my $msg = ""; + if ($line =~ /\bif\s*(?:\(\s*){$count,$count}$LvalOrFunc\s*($Compare)\s*$LvalOrFunc(?:\s*\)){$count,$count}/) { + my $comp = $4; #Not $1 because of $LvalOrFunc + $msg = " - maybe == should be = ?" if ($comp eq "=="); + WARN("UNNECESSARY_PARENTHESES", + "Unnecessary parentheses$msg\n" . $herecurr); + } + } + +# comparisons with a constant or upper case identifier on the left +# avoid cases like "foo + BAR < baz" +# only fix matches surrounded by parentheses to avoid incorrect +# conversions like "FOO < baz() + 5" being "misfixed" to "baz() > FOO + 5" + if ($^V && $^V ge 5.10.0 && + $line =~ /^\+(.*)\b($Constant|[A-Z_][A-Z0-9_]*)\s*($Compare)\s*($LvalOrFunc)/) { + my $lead = $1; + my $const = $2; + my $comp = $3; + my $to = $4; + my $newcomp = $comp; + if ($lead !~ /$Operators\s*$/ && + $to !~ /^(?:Constant|[A-Z_][A-Z0-9_]*)$/ && + WARN("CONSTANT_COMPARISON", + "Comparisons should place the constant on the right side of the test\n" . $herecurr) && + $fix) { + if ($comp eq "<") { + $newcomp = ">"; + } elsif ($comp eq "<=") { + $newcomp = ">="; + } elsif ($comp eq ">") { + $newcomp = "<"; + } elsif ($comp eq ">=") { + $newcomp = "<="; + } + $fixed[$fixlinenr] =~ s/\(\s*\Q$const\E\s*$Compare\s*\Q$to\E\s*\)/($to $newcomp $const)/; + } + } + +# Return of what appears to be an errno should normally be negative + if ($sline =~ /\breturn(?:\s*\(+\s*|\s+)(E[A-Z]+)(?:\s*\)+\s*|\s*)[;:,]/) { + my $name = $1; + if ($name ne 'EOF' && $name ne 'ERROR') { + WARN("USE_NEGATIVE_ERRNO", + "return of an errno should typically be negative (ie: return -$1)\n" . $herecurr); + } + } + +# Need a space before open parenthesis after if, while etc + if ($line =~ /\b(if|while|for|switch)\(/) { + if (ERROR("SPACING", + "space required before the open parenthesis '('\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ + s/\b(if|while|for|switch)\(/$1 \(/; + } + } + +# Check for illegal assignment in if conditional -- and check for trailing +# statements after the conditional. + if ($line =~ /do\s*(?!{)/) { + ($stat, $cond, $line_nr_next, $remain_next, $off_next) = + ctx_statement_block($linenr, $realcnt, 0) + if (!defined $stat); + my ($stat_next) = ctx_statement_block($line_nr_next, + $remain_next, $off_next); + $stat_next =~ s/\n./\n /g; + ##print "stat<$stat> stat_next<$stat_next>\n"; + + if ($stat_next =~ /^\s*while\b/) { + # If the statement carries leading newlines, + # then count those as offsets. + my ($whitespace) = + ($stat_next =~ /^((?:\s*\n[+-])*\s*)/s); + my $offset = + statement_rawlines($whitespace) - 1; + + $suppress_whiletrailers{$line_nr_next + + $offset} = 1; + } + } + if (!defined $suppress_whiletrailers{$linenr} && + defined($stat) && defined($cond) && + $line =~ /\b(?:if|while|for)\s*\(/ && $line !~ /^.\s*#/) { + my ($s, $c) = ($stat, $cond); + + if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/s) { + ERROR("ASSIGN_IN_IF", + "do not use assignment in if condition\n" . $herecurr); + } + + # Find out what is on the end of the line after the + # conditional. + substr($s, 0, length($c), ''); + $s =~ s/\n.*//g; + $s =~ s/$;//g; # Remove any comments + if (length($c) && $s !~ /^\s*{?\s*\\*\s*$/ && + $c !~ /}\s*while\s*/) + { + # Find out how long the conditional actually is. + my @newlines = ($c =~ /\n/gs); + my $cond_lines = 1 + $#newlines; + my $stat_real = ''; + + $stat_real = raw_line($linenr, $cond_lines) + . "\n" if ($cond_lines); + if (defined($stat_real) && $cond_lines > 1) { + $stat_real = "[...]\n$stat_real"; + } + + ERROR("TRAILING_STATEMENTS", + "trailing statements should be on next line\n" . $herecurr . $stat_real); + } + } + +# Check for bitwise tests written as boolean + if ($line =~ / + (?: + (?:\[|\(|\&\&|\|\|) + \s*0[xX][0-9]+\s* + (?:\&\&|\|\|) + | + (?:\&\&|\|\|) + \s*0[xX][0-9]+\s* + (?:\&\&|\|\||\)|\]) + )/x) + { + WARN("HEXADECIMAL_BOOLEAN_TEST", + "boolean test with hexadecimal, perhaps just 1 \& or \|?\n" . $herecurr); + } + +# if and else should not have general statements after it + if ($line =~ /^.\s*(?:}\s*)?else\b(.*)/) { + my $s = $1; + $s =~ s/$;//g; # Remove any comments + if ($s !~ /^\s*(?:\sif|(?:{|)\s*\\?\s*$)/) { + ERROR("TRAILING_STATEMENTS", + "trailing statements should be on next line\n" . $herecurr); + } + } +# if should not continue a brace + if ($line =~ /}\s*if\b/) { + ERROR("TRAILING_STATEMENTS", + "trailing statements should be on next line (or did you mean 'else if'?)\n" . + $herecurr); + } +# case and default should not have general statements after them + if ($line =~ /^.\s*(?:case\s*.*|default\s*):/g && + $line !~ /\G(?: + (?:\s*$;*)(?:\s*{)?(?:\s*$;*)(?:\s*\\)?\s*$| + \s*return\s+ + )/xg) + { + ERROR("TRAILING_STATEMENTS", + "trailing statements should be on next line\n" . $herecurr); + } + + # Check for }<nl>else {, these must be at the same + # indent level to be relevant to each other. + if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ && + $previndent == $indent) { + if (ERROR("ELSE_AFTER_BRACE", + "else should follow close brace '}'\n" . $hereprev) && + $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { + fix_delete_line($fixlinenr - 1, $prevrawline); + fix_delete_line($fixlinenr, $rawline); + my $fixedline = $prevrawline; + $fixedline =~ s/}\s*$//; + if ($fixedline !~ /^\+\s*$/) { + fix_insert_line($fixlinenr, $fixedline); + } + $fixedline = $rawline; + $fixedline =~ s/^(.\s*)else/$1} else/; + fix_insert_line($fixlinenr, $fixedline); + } + } + + if ($prevline=~/}\s*$/ and $line=~/^.\s*while\s*/ && + $previndent == $indent) { + my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0); + + # Find out what is on the end of the line after the + # conditional. + substr($s, 0, length($c), ''); + $s =~ s/\n.*//g; + + if ($s =~ /^\s*;/) { + if (ERROR("WHILE_AFTER_BRACE", + "while should follow close brace '}'\n" . $hereprev) && + $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { + fix_delete_line($fixlinenr - 1, $prevrawline); + fix_delete_line($fixlinenr, $rawline); + my $fixedline = $prevrawline; + my $trailing = $rawline; + $trailing =~ s/^\+//; + $trailing = trim($trailing); + $fixedline =~ s/}\s*$/} $trailing/; + fix_insert_line($fixlinenr, $fixedline); + } + } + } + +#Specific variable tests + while ($line =~ m{($Constant|$Lval)}g) { + my $var = $1; + +#gcc binary extension + if ($var =~ /^$Binary$/) { + if (WARN("GCC_BINARY_CONSTANT", + "Avoid gcc v4.3+ binary constant extension: <$var>\n" . $herecurr) && + $fix) { + my $hexval = sprintf("0x%x", oct($var)); + $fixed[$fixlinenr] =~ + s/\b$var\b/$hexval/; + } + } + +#CamelCase + if ($var !~ /^$Constant$/ && + $var =~ /[A-Z][a-z]|[a-z][A-Z]/ && +#Ignore Page<foo> variants + $var !~ /^(?:Clear|Set|TestClear|TestSet|)Page[A-Z]/ && +#Ignore SI style variants like nS, mV and dB (ie: max_uV, regulator_min_uA_show) + $var !~ /^(?:[a-z_]*?)_?[a-z][A-Z](?:_[a-z_]+)?$/ && +#Ignore some three character SI units explicitly, like MiB and KHz + $var !~ /^(?:[a-z_]*?)_?(?:[KMGT]iB|[KMGT]?Hz)(?:_[a-z_]+)?$/) { + while ($var =~ m{($Ident)}g) { + my $word = $1; + next if ($word !~ /[A-Z][a-z]|[a-z][A-Z]/); + if ($check) { + seed_camelcase_includes(); + if (!$file && !$camelcase_file_seeded) { + seed_camelcase_file($realfile); + $camelcase_file_seeded = 1; + } + } + if (!defined $camelcase{$word}) { + $camelcase{$word} = 1; + CHK("CAMELCASE", + "Avoid CamelCase: <$word>\n" . $herecurr); + } + } + } + } + +#no spaces allowed after \ in define + if ($line =~ /\#\s*define.*\\\s+$/) { + if (WARN("WHITESPACE_AFTER_LINE_CONTINUATION", + "Whitespace after \\ makes next lines useless\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\s+$//; + } + } + +# warn if <asm/foo.h> is #included and <linux/foo.h> is available and includes +# itself <asm/foo.h> (uses RAW line) + if ($tree && $rawline =~ m{^.\s*\#\s*include\s*\<asm\/(.*)\.h\>}) { + my $file = "$1.h"; + my $checkfile = "include/linux/$file"; + if (-f "$root/$checkfile" && + $realfile ne $checkfile && + $1 !~ /$allowed_asm_includes/) + { + my $asminclude = `grep -Ec "#include\\s+<asm/$file>" $root/$checkfile`; + if ($asminclude > 0) { + if ($realfile =~ m{^arch/}) { + CHK("ARCH_INCLUDE_LINUX", + "Consider using #include <linux/$file> instead of <asm/$file>\n" . $herecurr); + } else { + WARN("INCLUDE_LINUX", + "Use #include <linux/$file> instead of <asm/$file>\n" . $herecurr); + } + } + } + } + +# multi-statement macros should be enclosed in a do while loop, grab the +# first statement and ensure its the whole macro if its not enclosed +# in a known good container + if ($realfile !~ m@/vmlinux.lds.h$@ && + $line =~ /^.\s*\#\s*define\s*$Ident(\()?/) { + my $ln = $linenr; + my $cnt = $realcnt; + my ($off, $dstat, $dcond, $rest); + my $ctx = ''; + my $has_flow_statement = 0; + my $has_arg_concat = 0; + ($dstat, $dcond, $ln, $cnt, $off) = + ctx_statement_block($linenr, $realcnt, 0); + $ctx = $dstat; + #print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n"; + #print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n"; + + $has_flow_statement = 1 if ($ctx =~ /\b(goto|return)\b/); + $has_arg_concat = 1 if ($ctx =~ /\#\#/ && $ctx !~ /\#\#\s*(?:__VA_ARGS__|args)\b/); + + $dstat =~ s/^.\s*\#\s*define\s+$Ident(?:\([^\)]*\))?\s*//; + $dstat =~ s/$;//g; + $dstat =~ s/\\\n.//g; + $dstat =~ s/^\s*//s; + $dstat =~ s/\s*$//s; + + # Flatten any parentheses and braces + while ($dstat =~ s/\([^\(\)]*\)/1/ || + $dstat =~ s/\{[^\{\}]*\}/1/ || + $dstat =~ s/.\[[^\[\]]*\]/1/) + { + } + + # Flatten any obvious string concatentation. + while ($dstat =~ s/($String)\s*$Ident/$1/ || + $dstat =~ s/$Ident\s*($String)/$1/) + { + } + + # Make asm volatile uses seem like a generic function + $dstat =~ s/\b_*asm_*\s+_*volatile_*\b/asm_volatile/g; + + my $exceptions = qr{ + $Declare| + module_param_named| + MODULE_PARM_DESC| + DECLARE_PER_CPU| + DEFINE_PER_CPU| + __typeof__\(| + union| + struct| + \.$Ident\s*=\s*| + ^\"|\"$| + ^\[ + }x; + #print "REST<$rest> dstat<$dstat> ctx<$ctx>\n"; + if ($dstat ne '' && + $dstat !~ /^(?:$Ident|-?$Constant),$/ && # 10, // foo(), + $dstat !~ /^(?:$Ident|-?$Constant);$/ && # foo(); + $dstat !~ /^[!~-]?(?:$Lval|$Constant)$/ && # 10 // foo() // !foo // ~foo // -foo // foo->bar // foo.bar->baz + $dstat !~ /^'X'$/ && $dstat !~ /^'XX'$/ && # character constants + $dstat !~ /$exceptions/ && + $dstat !~ /^\.$Ident\s*=/ && # .foo = + $dstat !~ /^(?:\#\s*$Ident|\#\s*$Constant)\s*$/ && # stringification #foo + $dstat !~ /^do\s*$Constant\s*while\s*$Constant;?$/ && # do {...} while (...); // do {...} while (...) + $dstat !~ /^for\s*$Constant$/ && # for (...) + $dstat !~ /^for\s*$Constant\s+(?:$Ident|-?$Constant)$/ && # for (...) bar() + $dstat !~ /^do\s*{/ && # do {... + $dstat !~ /^\(\{/ && # ({... + $ctx !~ /^.\s*#\s*define\s+TRACE_(?:SYSTEM|INCLUDE_FILE|INCLUDE_PATH)\b/) + { + $ctx =~ s/\n*$//; + my $herectx = $here . "\n"; + my $cnt = statement_rawlines($ctx); + + for (my $n = 0; $n < $cnt; $n++) { + $herectx .= raw_line($linenr, $n) . "\n"; + } + + if ($dstat =~ /;/) { + ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE", + "Macros with multiple statements should be enclosed in a do - while loop\n" . "$herectx"); + } else { + ERROR("COMPLEX_MACRO", + "Macros with complex values should be enclosed in parentheses\n" . "$herectx"); + } + } + +# check for macros with flow control, but without ## concatenation +# ## concatenation is commonly a macro that defines a function so ignore those + if ($has_flow_statement && !$has_arg_concat) { + my $herectx = $here . "\n"; + my $cnt = statement_rawlines($ctx); + + for (my $n = 0; $n < $cnt; $n++) { + $herectx .= raw_line($linenr, $n) . "\n"; + } + WARN("MACRO_WITH_FLOW_CONTROL", + "Macros with flow control statements should be avoided\n" . "$herectx"); + } + +# check for line continuations outside of #defines, preprocessor #, and asm + + } else { + if ($prevline !~ /^..*\\$/ && + $line !~ /^\+\s*\#.*\\$/ && # preprocessor + $line !~ /^\+.*\b(__asm__|asm)\b.*\\$/ && # asm + $line =~ /^\+.*\\$/) { + WARN("LINE_CONTINUATIONS", + "Avoid unnecessary line continuations\n" . $herecurr); + } + } + +# do {} while (0) macro tests: +# single-statement macros do not need to be enclosed in do while (0) loop, +# macro should not end with a semicolon + if ($^V && $^V ge 5.10.0 && + $realfile !~ m@/vmlinux.lds.h$@ && + $line =~ /^.\s*\#\s*define\s+$Ident(\()?/) { + my $ln = $linenr; + my $cnt = $realcnt; + my ($off, $dstat, $dcond, $rest); + my $ctx = ''; + ($dstat, $dcond, $ln, $cnt, $off) = + ctx_statement_block($linenr, $realcnt, 0); + $ctx = $dstat; + + $dstat =~ s/\\\n.//g; + $dstat =~ s/$;/ /g; + + if ($dstat =~ /^\+\s*#\s*define\s+$Ident\s*${balanced_parens}\s*do\s*{(.*)\s*}\s*while\s*\(\s*0\s*\)\s*([;\s]*)\s*$/) { + my $stmts = $2; + my $semis = $3; + + $ctx =~ s/\n*$//; + my $cnt = statement_rawlines($ctx); + my $herectx = $here . "\n"; + + for (my $n = 0; $n < $cnt; $n++) { + $herectx .= raw_line($linenr, $n) . "\n"; + } + + if (($stmts =~ tr/;/;/) == 1 && + $stmts !~ /^\s*(if|while|for|switch)\b/) { + WARN("SINGLE_STATEMENT_DO_WHILE_MACRO", + "Single statement macros should not use a do {} while (0) loop\n" . "$herectx"); + } + if (defined $semis && $semis ne "") { + WARN("DO_WHILE_MACRO_WITH_TRAILING_SEMICOLON", + "do {} while (0) macros should not be semicolon terminated\n" . "$herectx"); + } + } elsif ($dstat =~ /^\+\s*#\s*define\s+$Ident.*;\s*$/) { + $ctx =~ s/\n*$//; + my $cnt = statement_rawlines($ctx); + my $herectx = $here . "\n"; + + for (my $n = 0; $n < $cnt; $n++) { + $herectx .= raw_line($linenr, $n) . "\n"; + } + + WARN("TRAILING_SEMICOLON", + "macros should not use a trailing semicolon\n" . "$herectx"); + } + } + +# make sure symbols are always wrapped with VMLINUX_SYMBOL() ... +# all assignments may have only one of the following with an assignment: +# . +# ALIGN(...) +# VMLINUX_SYMBOL(...) + if ($realfile eq 'vmlinux.lds.h' && $line =~ /(?:(?:^|\s)$Ident\s*=|=\s*$Ident(?:\s|$))/) { + WARN("MISSING_VMLINUX_SYMBOL", + "vmlinux.lds.h needs VMLINUX_SYMBOL() around C-visible symbols\n" . $herecurr); + } + +# check for redundant bracing round if etc + if ($line =~ /(^.*)\bif\b/ && $1 !~ /else\s*$/) { + my ($level, $endln, @chunks) = + ctx_statement_full($linenr, $realcnt, 1); + #print "chunks<$#chunks> linenr<$linenr> endln<$endln> level<$level>\n"; + #print "APW: <<$chunks[1][0]>><<$chunks[1][1]>>\n"; + if ($#chunks > 0 && $level == 0) { + my @allowed = (); + my $allow = 0; + my $seen = 0; + my $herectx = $here . "\n"; + my $ln = $linenr - 1; + for my $chunk (@chunks) { + my ($cond, $block) = @{$chunk}; + + # If the condition carries leading newlines, then count those as offsets. + my ($whitespace) = ($cond =~ /^((?:\s*\n[+-])*\s*)/s); + my $offset = statement_rawlines($whitespace) - 1; + + $allowed[$allow] = 0; + #print "COND<$cond> whitespace<$whitespace> offset<$offset>\n"; + + # We have looked at and allowed this specific line. + $suppress_ifbraces{$ln + $offset} = 1; + + $herectx .= "$rawlines[$ln + $offset]\n[...]\n"; + $ln += statement_rawlines($block) - 1; + + substr($block, 0, length($cond), ''); + + $seen++ if ($block =~ /^\s*{/); + + #print "cond<$cond> block<$block> allowed<$allowed[$allow]>\n"; + if (statement_lines($cond) > 1) { + #print "APW: ALLOWED: cond<$cond>\n"; + $allowed[$allow] = 1; + } + if ($block =~/\b(?:if|for|while)\b/) { + #print "APW: ALLOWED: block<$block>\n"; + $allowed[$allow] = 1; + } + if (statement_block_size($block) > 1) { + #print "APW: ALLOWED: lines block<$block>\n"; + $allowed[$allow] = 1; + } + $allow++; + } + if ($seen) { + my $sum_allowed = 0; + foreach (@allowed) { + $sum_allowed += $_; + } + if ($sum_allowed == 0) { + WARN("BRACES", + "braces {} are not necessary for any arm of this statement\n" . $herectx); + } elsif ($sum_allowed != $allow && + $seen != $allow) { + CHK("BRACES", + "braces {} should be used on all arms of this statement\n" . $herectx); + } + } + } + } + if (!defined $suppress_ifbraces{$linenr - 1} && + $line =~ /\b(if|while|for|else)\b/) { + my $allowed = 0; + + # Check the pre-context. + if (substr($line, 0, $-[0]) =~ /(\}\s*)$/) { + #print "APW: ALLOWED: pre<$1>\n"; + $allowed = 1; + } + + my ($level, $endln, @chunks) = + ctx_statement_full($linenr, $realcnt, $-[0]); + + # Check the condition. + my ($cond, $block) = @{$chunks[0]}; + #print "CHECKING<$linenr> cond<$cond> block<$block>\n"; + if (defined $cond) { + substr($block, 0, length($cond), ''); + } + if (statement_lines($cond) > 1) { + #print "APW: ALLOWED: cond<$cond>\n"; + $allowed = 1; + } + if ($block =~/\b(?:if|for|while)\b/) { + #print "APW: ALLOWED: block<$block>\n"; + $allowed = 1; + } + if (statement_block_size($block) > 1) { + #print "APW: ALLOWED: lines block<$block>\n"; + $allowed = 1; + } + # Check the post-context. + if (defined $chunks[1]) { + my ($cond, $block) = @{$chunks[1]}; + if (defined $cond) { + substr($block, 0, length($cond), ''); + } + if ($block =~ /^\s*\{/) { + #print "APW: ALLOWED: chunk-1 block<$block>\n"; + $allowed = 1; + } + } + if ($level == 0 && $block =~ /^\s*\{/ && !$allowed) { + my $herectx = $here . "\n"; + my $cnt = statement_rawlines($block); + + for (my $n = 0; $n < $cnt; $n++) { + $herectx .= raw_line($linenr, $n) . "\n"; + } + + WARN("BRACES", + "braces {} are not necessary for single statement blocks\n" . $herectx); + } + } + +# check for unnecessary blank lines around braces + if (($line =~ /^.\s*}\s*$/ && $prevrawline =~ /^.\s*$/)) { + if (CHK("BRACES", + "Blank lines aren't necessary before a close brace '}'\n" . $hereprev) && + $fix && $prevrawline =~ /^\+/) { + fix_delete_line($fixlinenr - 1, $prevrawline); + } + } + if (($rawline =~ /^.\s*$/ && $prevline =~ /^..*{\s*$/)) { + if (CHK("BRACES", + "Blank lines aren't necessary after an open brace '{'\n" . $hereprev) && + $fix) { + fix_delete_line($fixlinenr, $rawline); + } + } + +# no volatiles please + my $asm_volatile = qr{\b(__asm__|asm)\s+(__volatile__|volatile)\b}; + if ($line =~ /\bvolatile\b/ && $line !~ /$asm_volatile/) { + WARN("VOLATILE", + "Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n" . $herecurr); + } + +# Check for user-visible strings broken across lines, which breaks the ability +# to grep for the string. Make exceptions when the previous string ends in a +# newline (multiple lines in one string constant) or '\t', '\r', ';', or '{' +# (common in inline assembly) or is a octal \123 or hexadecimal \xaf value + if ($line =~ /^\+\s*$String/ && + $prevline =~ /"\s*$/ && + $prevrawline !~ /(?:\\(?:[ntr]|[0-7]{1,3}|x[0-9a-fA-F]{1,2})|;\s*|\{\s*)"\s*$/) { + if (WARN("SPLIT_STRING", + "quoted string split across lines\n" . $hereprev) && + $fix && + $prevrawline =~ /^\+.*"\s*$/ && + $last_coalesced_string_linenr != $linenr - 1) { + my $extracted_string = get_quoted_string($line, $rawline); + my $comma_close = ""; + if ($rawline =~ /\Q$extracted_string\E(\s*\)\s*;\s*$|\s*,\s*)/) { + $comma_close = $1; + } + + fix_delete_line($fixlinenr - 1, $prevrawline); + fix_delete_line($fixlinenr, $rawline); + my $fixedline = $prevrawline; + $fixedline =~ s/"\s*$//; + $fixedline .= substr($extracted_string, 1) . trim($comma_close); + fix_insert_line($fixlinenr - 1, $fixedline); + $fixedline = $rawline; + $fixedline =~ s/\Q$extracted_string\E\Q$comma_close\E//; + if ($fixedline !~ /\+\s*$/) { + fix_insert_line($fixlinenr, $fixedline); + } + $last_coalesced_string_linenr = $linenr; + } + } + +# check for missing a space in a string concatenation + if ($prevrawline =~ /[^\\]\w"$/ && $rawline =~ /^\+[\t ]+"\w/) { + WARN('MISSING_SPACE', + "break quoted strings at a space character\n" . $hereprev); + } + +# check for spaces before a quoted newline + if ($rawline =~ /^.*\".*\s\\n/) { + if (WARN("QUOTED_WHITESPACE_BEFORE_NEWLINE", + "unnecessary whitespace before a quoted newline\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/^(\+.*\".*)\s+\\n/$1\\n/; + } + + } + +# concatenated string without spaces between elements + if ($line =~ /$String[A-Z_]/ || $line =~ /[A-Za-z0-9_]$String/) { + CHK("CONCATENATED_STRING", + "Concatenated strings should use spaces between elements\n" . $herecurr); + } + +# uncoalesced string fragments + if ($line =~ /$String\s*"/) { + WARN("STRING_FRAGMENTS", + "Consecutive strings are generally better as a single string\n" . $herecurr); + } + +# check for %L{u,d,i} and 0x%[udi] in strings + my $string; + while ($line =~ /(?:^|")([X\t]*)(?:"|$)/g) { + $string = substr($rawline, $-[1], $+[1] - $-[1]); + $string =~ s/%%/__/g; + if ($string =~ /(?<!%)%[\*\d\.\$]*L[udi]/) { + WARN("PRINTF_L", + "\%Ld/%Lu are not-standard C, use %lld/%llu\n" . $herecurr); + last; + } + if ($string =~ /0x%[\*\d\.\$\Llzth]*[udi]/) { + ERROR("PRINTF_0xDECIMAL", + "Prefixing 0x with decimal output is defective\n" . $herecurr); + } + } + +# check for line continuations in quoted strings with odd counts of " + if ($rawline =~ /\\$/ && $rawline =~ tr/"/"/ % 2) { + WARN("LINE_CONTINUATIONS", + "Avoid line continuations in quoted strings\n" . $herecurr); + } + +# warn about #if 0 + if ($line =~ /^.\s*\#\s*if\s+0\b/) { + CHK("REDUNDANT_CODE", + "if this code is redundant consider removing it\n" . + $herecurr); + } + +# check for needless "if (<foo>) fn(<foo>)" uses + if ($prevline =~ /\bif\s*\(\s*($Lval)\s*\)/) { + my $tested = quotemeta($1); + my $expr = '\s*\(\s*' . $tested . '\s*\)\s*;'; + if ($line =~ /\b(kfree|usb_free_urb|debugfs_remove(?:_recursive)?|(?:kmem_cache|mempool|dma_pool)_destroy)$expr/) { + my $func = $1; + if (WARN('NEEDLESS_IF', + "$func(NULL) is safe and this check is probably not required\n" . $hereprev) && + $fix) { + my $do_fix = 1; + my $leading_tabs = ""; + my $new_leading_tabs = ""; + if ($lines[$linenr - 2] =~ /^\+(\t*)if\s*\(\s*$tested\s*\)\s*$/) { + $leading_tabs = $1; + } else { + $do_fix = 0; + } + if ($lines[$linenr - 1] =~ /^\+(\t+)$func\s*\(\s*$tested\s*\)\s*;\s*$/) { + $new_leading_tabs = $1; + if (length($leading_tabs) + 1 ne length($new_leading_tabs)) { + $do_fix = 0; + } + } else { + $do_fix = 0; + } + if ($do_fix) { + fix_delete_line($fixlinenr - 1, $prevrawline); + $fixed[$fixlinenr] =~ s/^\+$new_leading_tabs/\+$leading_tabs/; + } + } + } + } + +# check for unnecessary "Out of Memory" messages + if ($line =~ /^\+.*\b$logFunctions\s*\(/ && + $prevline =~ /^[ \+]\s*if\s*\(\s*(\!\s*|NULL\s*==\s*)?($Lval)(\s*==\s*NULL\s*)?\s*\)/ && + (defined $1 || defined $3) && + $linenr > 3) { + my $testval = $2; + my $testline = $lines[$linenr - 3]; + + my ($s, $c) = ctx_statement_block($linenr - 3, $realcnt, 0); +# print("line: <$line>\nprevline: <$prevline>\ns: <$s>\nc: <$c>\n\n\n"); + + if ($c =~ /(?:^|\n)[ \+]\s*(?:$Type\s*)?\Q$testval\E\s*=\s*(?:\([^\)]*\)\s*)?\s*(?:devm_)?(?:[kv][czm]alloc(?:_node|_array)?\b|kstrdup|(?:dev_)?alloc_skb)/) { + WARN("OOM_MESSAGE", + "Possible unnecessary 'out of memory' message\n" . $hereprev); + } + } + +# check for logging functions with KERN_<LEVEL> + if ($line !~ /printk(?:_ratelimited|_once)?\s*\(/ && + $line =~ /\b$logFunctions\s*\(.*\b(KERN_[A-Z]+)\b/) { + my $level = $1; + if (WARN("UNNECESSARY_KERN_LEVEL", + "Possible unnecessary $level\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\s*$level\s*//; + } + } + +# check for mask then right shift without a parentheses + if ($^V && $^V ge 5.10.0 && + $line =~ /$LvalOrFunc\s*\&\s*($LvalOrFunc)\s*>>/ && + $4 !~ /^\&/) { # $LvalOrFunc may be &foo, ignore if so + WARN("MASK_THEN_SHIFT", + "Possible precedence defect with mask then right shift - may need parentheses\n" . $herecurr); + } + +# check for pointer comparisons to NULL + if ($^V && $^V ge 5.10.0) { + while ($line =~ /\b$LvalOrFunc\s*(==|\!=)\s*NULL\b/g) { + my $val = $1; + my $equal = "!"; + $equal = "" if ($4 eq "!="); + if (CHK("COMPARISON_TO_NULL", + "Comparison to NULL could be written \"${equal}${val}\"\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\b\Q$val\E\s*(?:==|\!=)\s*NULL\b/$equal$val/; + } + } + } + +# check for bad placement of section $InitAttribute (e.g.: __initdata) + if ($line =~ /(\b$InitAttribute\b)/) { + my $attr = $1; + if ($line =~ /^\+\s*static\s+(?:const\s+)?(?:$attr\s+)?($NonptrTypeWithAttr)\s+(?:$attr\s+)?($Ident(?:\[[^]]*\])?)\s*[=;]/) { + my $ptr = $1; + my $var = $2; + if ((($ptr =~ /\b(union|struct)\s+$attr\b/ && + ERROR("MISPLACED_INIT", + "$attr should be placed after $var\n" . $herecurr)) || + ($ptr !~ /\b(union|struct)\s+$attr\b/ && + WARN("MISPLACED_INIT", + "$attr should be placed after $var\n" . $herecurr))) && + $fix) { + $fixed[$fixlinenr] =~ s/(\bstatic\s+(?:const\s+)?)(?:$attr\s+)?($NonptrTypeWithAttr)\s+(?:$attr\s+)?($Ident(?:\[[^]]*\])?)\s*([=;])\s*/"$1" . trim(string_find_replace($2, "\\s*$attr\\s*", " ")) . " " . trim(string_find_replace($3, "\\s*$attr\\s*", "")) . " $attr" . ("$4" eq ";" ? ";" : " = ")/e; + } + } + } + +# check for $InitAttributeData (ie: __initdata) with const + if ($line =~ /\bconst\b/ && $line =~ /($InitAttributeData)/) { + my $attr = $1; + $attr =~ /($InitAttributePrefix)(.*)/; + my $attr_prefix = $1; + my $attr_type = $2; + if (ERROR("INIT_ATTRIBUTE", + "Use of const init definition must use ${attr_prefix}initconst\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ + s/$InitAttributeData/${attr_prefix}initconst/; + } + } + +# check for $InitAttributeConst (ie: __initconst) without const + if ($line !~ /\bconst\b/ && $line =~ /($InitAttributeConst)/) { + my $attr = $1; + if (ERROR("INIT_ATTRIBUTE", + "Use of $attr requires a separate use of const\n" . $herecurr) && + $fix) { + my $lead = $fixed[$fixlinenr] =~ + /(^\+\s*(?:static\s+))/; + $lead = rtrim($1); + $lead = "$lead " if ($lead !~ /^\+$/); + $lead = "${lead}const "; + $fixed[$fixlinenr] =~ s/(^\+\s*(?:static\s+))/$lead/; + } + } + +# check for __read_mostly with const non-pointer (should just be const) + if ($line =~ /\b__read_mostly\b/ && + $line =~ /($Type)\s*$Ident/ && $1 !~ /\*\s*$/ && $1 =~ /\bconst\b/) { + if (ERROR("CONST_READ_MOSTLY", + "Invalid use of __read_mostly with const type\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\s+__read_mostly\b//; + } + } + +# don't use __constant_<foo> functions outside of include/uapi/ + if ($realfile !~ m@^include/uapi/@ && + $line =~ /(__constant_(?:htons|ntohs|[bl]e(?:16|32|64)_to_cpu|cpu_to_[bl]e(?:16|32|64)))\s*\(/) { + my $constant_func = $1; + my $func = $constant_func; + $func =~ s/^__constant_//; + if (WARN("CONSTANT_CONVERSION", + "$constant_func should be $func\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\b$constant_func\b/$func/g; + } + } + +# prefer usleep_range over udelay + if ($line =~ /\budelay\s*\(\s*(\d+)\s*\)/) { + my $delay = $1; + # ignore udelay's < 10, however + if (! ($delay < 10) ) { + CHK("USLEEP_RANGE", + "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt\n" . $herecurr); + } + if ($delay > 2000) { + WARN("LONG_UDELAY", + "long udelay - prefer mdelay; see arch/arm/include/asm/delay.h\n" . $herecurr); + } + } + +# warn about unexpectedly long msleep's + if ($line =~ /\bmsleep\s*\((\d+)\);/) { + if ($1 < 20) { + WARN("MSLEEP", + "msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt\n" . $herecurr); + } + } + +# check for comparisons of jiffies + if ($line =~ /\bjiffies\s*$Compare|$Compare\s*jiffies\b/) { + WARN("JIFFIES_COMPARISON", + "Comparing jiffies is almost always wrong; prefer time_after, time_before and friends\n" . $herecurr); + } + +# check for comparisons of get_jiffies_64() + if ($line =~ /\bget_jiffies_64\s*\(\s*\)\s*$Compare|$Compare\s*get_jiffies_64\s*\(\s*\)/) { + WARN("JIFFIES_COMPARISON", + "Comparing get_jiffies_64() is almost always wrong; prefer time_after64, time_before64 and friends\n" . $herecurr); + } + +# warn about #ifdefs in C files +# if ($line =~ /^.\s*\#\s*if(|n)def/ && ($realfile =~ /\.c$/)) { +# print "#ifdef in C files should be avoided\n"; +# print "$herecurr"; +# $clean = 0; +# } + +# warn about spacing in #ifdefs + if ($line =~ /^.\s*\#\s*(ifdef|ifndef|elif)\s\s+/) { + if (ERROR("SPACING", + "exactly one space required after that #$1\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ + s/^(.\s*\#\s*(ifdef|ifndef|elif))\s{2,}/$1 /; + } + + } + +# check for spinlock_t definitions without a comment. + if ($line =~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/ || + $line =~ /^.\s*(DEFINE_MUTEX)\s*\(/) { + my $which = $1; + if (!ctx_has_comment($first_line, $linenr)) { + CHK("UNCOMMENTED_DEFINITION", + "$1 definition without comment\n" . $herecurr); + } + } +# check for memory barriers without a comment. + + my $barriers = qr{ + mb| + rmb| + wmb| + read_barrier_depends + }x; + my $barrier_stems = qr{ + mb__before_atomic| + mb__after_atomic| + store_release| + load_acquire| + store_mb| + (?:$barriers) + }x; + my $all_barriers = qr{ + (?:$barriers)| + smp_(?:$barrier_stems)| + virt_(?:$barrier_stems) + }x; + + if ($line =~ /\b(?:$all_barriers)\s*\(/) { + if (!ctx_has_comment($first_line, $linenr)) { + WARN("MEMORY_BARRIER", + "memory barrier without comment\n" . $herecurr); + } + } + + my $underscore_smp_barriers = qr{__smp_(?:$barrier_stems)}x; + + if ($realfile !~ m@^include/asm-generic/@ && + $realfile !~ m@/barrier\.h$@ && + $line =~ m/\b(?:$underscore_smp_barriers)\s*\(/ && + $line !~ m/^.\s*\#\s*define\s+(?:$underscore_smp_barriers)\s*\(/) { + WARN("MEMORY_BARRIER", + "__smp memory barriers shouldn't be used outside barrier.h and asm-generic\n" . $herecurr); + } + +# check for waitqueue_active without a comment. + if ($line =~ /\bwaitqueue_active\s*\(/) { + if (!ctx_has_comment($first_line, $linenr)) { + WARN("WAITQUEUE_ACTIVE", + "waitqueue_active without comment\n" . $herecurr); + } + } + +# Check for expedited grace periods that interrupt non-idle non-nohz +# online CPUs. These expedited can therefore degrade real-time response +# if used carelessly, and should be avoided where not absolutely +# needed. It is always OK to use synchronize_rcu_expedited() and +# synchronize_sched_expedited() at boot time (before real-time applications +# start) and in error situations where real-time response is compromised in +# any case. Note that synchronize_srcu_expedited() does -not- interrupt +# other CPUs, so don't warn on uses of synchronize_srcu_expedited(). +# Of course, nothing comes for free, and srcu_read_lock() and +# srcu_read_unlock() do contain full memory barriers in payment for +# synchronize_srcu_expedited() non-interruption properties. + if ($line =~ /\b(synchronize_rcu_expedited|synchronize_sched_expedited)\(/) { + WARN("EXPEDITED_RCU_GRACE_PERIOD", + "expedited RCU grace periods should be avoided where they can degrade real-time response\n" . $herecurr); + + } + +# check of hardware specific defines + if ($line =~ m@^.\s*\#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@ && $realfile !~ m@include/asm-@) { + CHK("ARCH_DEFINES", + "architecture specific defines should be avoided\n" . $herecurr); + } + +# Check that the storage class is at the beginning of a declaration + if ($line =~ /\b$Storage\b/ && $line !~ /^.\s*$Storage\b/) { + WARN("STORAGE_CLASS", + "storage class should be at the beginning of the declaration\n" . $herecurr) + } + +# check the location of the inline attribute, that it is between +# storage class and type. + if ($line =~ /\b$Type\s+$Inline\b/ || + $line =~ /\b$Inline\s+$Storage\b/) { + ERROR("INLINE_LOCATION", + "inline keyword should sit between storage class and type\n" . $herecurr); + } + +# Check for __inline__ and __inline, prefer inline + if ($realfile !~ m@\binclude/uapi/@ && + $line =~ /\b(__inline__|__inline)\b/) { + if (WARN("INLINE", + "plain inline is preferred over $1\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\b(__inline__|__inline)\b/inline/; + + } + } + +# Check for __attribute__ packed, prefer __packed + if ($realfile !~ m@\binclude/uapi/@ && + $line =~ /\b__attribute__\s*\(\s*\(.*\bpacked\b/) { + WARN("PREFER_PACKED", + "__packed is preferred over __attribute__((packed))\n" . $herecurr); + } + +# Check for __attribute__ aligned, prefer __aligned + if ($realfile !~ m@\binclude/uapi/@ && + $line =~ /\b__attribute__\s*\(\s*\(.*aligned/) { + WARN("PREFER_ALIGNED", + "__aligned(size) is preferred over __attribute__((aligned(size)))\n" . $herecurr); + } + +# Check for __attribute__ format(printf, prefer __printf + if ($realfile !~ m@\binclude/uapi/@ && + $line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf/) { + if (WARN("PREFER_PRINTF", + "__printf(string-index, first-to-check) is preferred over __attribute__((format(printf, string-index, first-to-check)))\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf\s*,\s*(.*)\)\s*\)\s*\)/"__printf(" . trim($1) . ")"/ex; + + } + } + +# Check for __attribute__ format(scanf, prefer __scanf + if ($realfile !~ m@\binclude/uapi/@ && + $line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\b/) { + if (WARN("PREFER_SCANF", + "__scanf(string-index, first-to-check) is preferred over __attribute__((format(scanf, string-index, first-to-check)))\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\s*,\s*(.*)\)\s*\)\s*\)/"__scanf(" . trim($1) . ")"/ex; + } + } + +# Check for __attribute__ weak, or __weak declarations (may have link issues) + if ($^V && $^V ge 5.10.0 && + $line =~ /(?:$Declare|$DeclareMisordered)\s*$Ident\s*$balanced_parens\s*(?:$Attribute)?\s*;/ && + ($line =~ /\b__attribute__\s*\(\s*\(.*\bweak\b/ || + $line =~ /\b__weak\b/)) { + ERROR("WEAK_DECLARATION", + "Using weak declarations can have unintended link defects\n" . $herecurr); + } + +# check for c99 types like uint8_t used outside of uapi/ + if ($realfile !~ m@\binclude/uapi/@ && + $line =~ /\b($Declare)\s*$Ident\s*[=;,\[]/) { + my $type = $1; + if ($type =~ /\b($typeC99Typedefs)\b/) { + $type = $1; + my $kernel_type = 'u'; + $kernel_type = 's' if ($type =~ /^_*[si]/); + $type =~ /(\d+)/; + $kernel_type .= $1; + if (CHK("PREFER_KERNEL_TYPES", + "Prefer kernel type '$kernel_type' over '$type'\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\b$type\b/$kernel_type/; + } + } + } + +# check for cast of C90 native int or longer types constants + if ($line =~ /(\(\s*$C90_int_types\s*\)\s*)($Constant)\b/) { + my $cast = $1; + my $const = $2; + if (WARN("TYPECAST_INT_CONSTANT", + "Unnecessary typecast of c90 int constant\n" . $herecurr) && + $fix) { + my $suffix = ""; + my $newconst = $const; + $newconst =~ s/${Int_type}$//; + $suffix .= 'U' if ($cast =~ /\bunsigned\b/); + if ($cast =~ /\blong\s+long\b/) { + $suffix .= 'LL'; + } elsif ($cast =~ /\blong\b/) { + $suffix .= 'L'; + } + $fixed[$fixlinenr] =~ s/\Q$cast\E$const\b/$newconst$suffix/; + } + } + +# check for sizeof(&) + if ($line =~ /\bsizeof\s*\(\s*\&/) { + WARN("SIZEOF_ADDRESS", + "sizeof(& should be avoided\n" . $herecurr); + } + +# check for sizeof without parenthesis + if ($line =~ /\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/) { + if (WARN("SIZEOF_PARENTHESIS", + "sizeof $1 should be sizeof($1)\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/"sizeof(" . trim($1) . ")"/ex; + } + } + +# check for struct spinlock declarations + if ($line =~ /^.\s*\bstruct\s+spinlock\s+\w+\s*;/) { + WARN("USE_SPINLOCK_T", + "struct spinlock should be spinlock_t\n" . $herecurr); + } + +# check for seq_printf uses that could be seq_puts + if ($sline =~ /\bseq_printf\s*\(.*"\s*\)\s*;\s*$/) { + my $fmt = get_quoted_string($line, $rawline); + $fmt =~ s/%%//g; + if ($fmt !~ /%/) { + if (WARN("PREFER_SEQ_PUTS", + "Prefer seq_puts to seq_printf\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\bseq_printf\b/seq_puts/; + } + } + } + +# Check for misused memsets + if ($^V && $^V ge 5.10.0 && + defined $stat && + $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*$FuncArg\s*\)/) { + + my $ms_addr = $2; + my $ms_val = $7; + my $ms_size = $12; + + if ($ms_size =~ /^(0x|)0$/i) { + ERROR("MEMSET", + "memset to 0's uses 0 as the 2nd argument, not the 3rd\n" . "$here\n$stat\n"); + } elsif ($ms_size =~ /^(0x|)1$/i) { + WARN("MEMSET", + "single byte memset is suspicious. Swapped 2nd/3rd argument?\n" . "$here\n$stat\n"); + } + } + +# Check for memcpy(foo, bar, ETH_ALEN) that could be ether_addr_copy(foo, bar) + if ($^V && $^V ge 5.10.0 && + defined $stat && + $stat =~ /^\+(?:.*?)\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) { + if (WARN("PREFER_ETHER_ADDR_COPY", + "Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2)\n" . "$here\n$stat\n") && + $fix) { + $fixed[$fixlinenr] =~ s/\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/ether_addr_copy($2, $7)/; + } + } + +# Check for memcmp(foo, bar, ETH_ALEN) that could be ether_addr_equal*(foo, bar) + if ($^V && $^V ge 5.10.0 && + defined $stat && + $stat =~ /^\+(?:.*?)\bmemcmp\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) { + WARN("PREFER_ETHER_ADDR_EQUAL", + "Prefer ether_addr_equal() or ether_addr_equal_unaligned() over memcmp()\n" . "$here\n$stat\n") + } + +# check for memset(foo, 0x0, ETH_ALEN) that could be eth_zero_addr +# check for memset(foo, 0xFF, ETH_ALEN) that could be eth_broadcast_addr + if ($^V && $^V ge 5.10.0 && + defined $stat && + $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) { + + my $ms_val = $7; + + if ($ms_val =~ /^(?:0x|)0+$/i) { + if (WARN("PREFER_ETH_ZERO_ADDR", + "Prefer eth_zero_addr over memset()\n" . "$here\n$stat\n") && + $fix) { + $fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_zero_addr($2)/; + } + } elsif ($ms_val =~ /^(?:0xff|255)$/i) { + if (WARN("PREFER_ETH_BROADCAST_ADDR", + "Prefer eth_broadcast_addr() over memset()\n" . "$here\n$stat\n") && + $fix) { + $fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_broadcast_addr($2)/; + } + } + } + +# typecasts on min/max could be min_t/max_t + if ($^V && $^V ge 5.10.0 && + defined $stat && + $stat =~ /^\+(?:.*?)\b(min|max)\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\)/) { + if (defined $2 || defined $7) { + my $call = $1; + my $cast1 = deparenthesize($2); + my $arg1 = $3; + my $cast2 = deparenthesize($7); + my $arg2 = $8; + my $cast; + + if ($cast1 ne "" && $cast2 ne "" && $cast1 ne $cast2) { + $cast = "$cast1 or $cast2"; + } elsif ($cast1 ne "") { + $cast = $cast1; + } else { + $cast = $cast2; + } + WARN("MINMAX", + "$call() should probably be ${call}_t($cast, $arg1, $arg2)\n" . "$here\n$stat\n"); + } + } + +# check usleep_range arguments + if ($^V && $^V ge 5.10.0 && + defined $stat && + $stat =~ /^\+(?:.*?)\busleep_range\s*\(\s*($FuncArg)\s*,\s*($FuncArg)\s*\)/) { + my $min = $1; + my $max = $7; + if ($min eq $max) { + WARN("USLEEP_RANGE", + "usleep_range should not use min == max args; see Documentation/timers/timers-howto.txt\n" . "$here\n$stat\n"); + } elsif ($min =~ /^\d+$/ && $max =~ /^\d+$/ && + $min > $max) { + WARN("USLEEP_RANGE", + "usleep_range args reversed, use min then max; see Documentation/timers/timers-howto.txt\n" . "$here\n$stat\n"); + } + } + +# check for naked sscanf + if ($^V && $^V ge 5.10.0 && + defined $stat && + $line =~ /\bsscanf\b/ && + ($stat !~ /$Ident\s*=\s*sscanf\s*$balanced_parens/ && + $stat !~ /\bsscanf\s*$balanced_parens\s*(?:$Compare)/ && + $stat !~ /(?:$Compare)\s*\bsscanf\s*$balanced_parens/)) { + my $lc = $stat =~ tr@\n@@; + $lc = $lc + $linenr; + my $stat_real = raw_line($linenr, 0); + for (my $count = $linenr + 1; $count <= $lc; $count++) { + $stat_real = $stat_real . "\n" . raw_line($count, 0); + } + WARN("NAKED_SSCANF", + "unchecked sscanf return value\n" . "$here\n$stat_real\n"); + } + +# check for simple sscanf that should be kstrto<foo> + if ($^V && $^V ge 5.10.0 && + defined $stat && + $line =~ /\bsscanf\b/) { + my $lc = $stat =~ tr@\n@@; + $lc = $lc + $linenr; + my $stat_real = raw_line($linenr, 0); + for (my $count = $linenr + 1; $count <= $lc; $count++) { + $stat_real = $stat_real . "\n" . raw_line($count, 0); + } + if ($stat_real =~ /\bsscanf\b\s*\(\s*$FuncArg\s*,\s*("[^"]+")/) { + my $format = $6; + my $count = $format =~ tr@%@%@; + if ($count == 1 && + $format =~ /^"\%(?i:ll[udxi]|[udxi]ll|ll|[hl]h?[udxi]|[udxi][hl]h?|[hl]h?|[udxi])"$/) { + WARN("SSCANF_TO_KSTRTO", + "Prefer kstrto<type> to single variable sscanf\n" . "$here\n$stat_real\n"); + } + } + } + +# check for new externs in .h files. + if ($realfile =~ /\.h$/ && + $line =~ /^\+\s*(extern\s+)$Type\s*$Ident\s*\(/s) { + if (CHK("AVOID_EXTERNS", + "extern prototypes should be avoided in .h files\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/(.*)\bextern\b\s*(.*)/$1$2/; + } + } + +# check for new externs in .c files. + if ($realfile =~ /\.c$/ && defined $stat && + $stat =~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s) + { + my $function_name = $1; + my $paren_space = $2; + + my $s = $stat; + if (defined $cond) { + substr($s, 0, length($cond), ''); + } + if ($s =~ /^\s*;/ && + $function_name ne 'uninitialized_var') + { + WARN("AVOID_EXTERNS", + "externs should be avoided in .c files\n" . $herecurr); + } + + if ($paren_space =~ /\n/) { + WARN("FUNCTION_ARGUMENTS", + "arguments for function declarations should follow identifier\n" . $herecurr); + } + + } elsif ($realfile =~ /\.c$/ && defined $stat && + $stat =~ /^.\s*extern\s+/) + { + WARN("AVOID_EXTERNS", + "externs should be avoided in .c files\n" . $herecurr); + } + +# checks for new __setup's + if ($rawline =~ /\b__setup\("([^"]*)"/) { + my $name = $1; + + if (!grep(/$name/, @setup_docs)) { + CHK("UNDOCUMENTED_SETUP", + "__setup appears un-documented -- check Documentation/kernel-parameters.txt\n" . $herecurr); + } + } + +# check for pointless casting of kmalloc return + if ($line =~ /\*\s*\)\s*[kv][czm]alloc(_node){0,1}\b/) { + WARN("UNNECESSARY_CASTS", + "unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $herecurr); + } + +# alloc style +# p = alloc(sizeof(struct foo), ...) should be p = alloc(sizeof(*p), ...) + if ($^V && $^V ge 5.10.0 && + $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*([kv][mz]alloc(?:_node)?)\s*\(\s*(sizeof\s*\(\s*struct\s+$Lval\s*\))/) { + CHK("ALLOC_SIZEOF_STRUCT", + "Prefer $3(sizeof(*$1)...) over $3($4...)\n" . $herecurr); + } + +# check for k[mz]alloc with multiplies that could be kmalloc_array/kcalloc + if ($^V && $^V ge 5.10.0 && + $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) { + my $oldfunc = $3; + my $a1 = $4; + my $a2 = $10; + my $newfunc = "kmalloc_array"; + $newfunc = "kcalloc" if ($oldfunc eq "kzalloc"); + my $r1 = $a1; + my $r2 = $a2; + if ($a1 =~ /^sizeof\s*\S/) { + $r1 = $a2; + $r2 = $a1; + } + if ($r1 !~ /^sizeof\b/ && $r2 =~ /^sizeof\s*\S/ && + !($r1 =~ /^$Constant$/ || $r1 =~ /^[A-Z_][A-Z0-9_]*$/)) { + if (WARN("ALLOC_WITH_MULTIPLY", + "Prefer $newfunc over $oldfunc with multiply\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . trim($r1) . ', ' . trim($r2)/e; + + } + } + } + +# check for krealloc arg reuse + if ($^V && $^V ge 5.10.0 && + $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*krealloc\s*\(\s*\1\s*,/) { + WARN("KREALLOC_ARG_REUSE", + "Reusing the krealloc arg is almost always a bug\n" . $herecurr); + } + +# check for alloc argument mismatch + if ($line =~ /\b(kcalloc|kmalloc_array)\s*\(\s*sizeof\b/) { + WARN("ALLOC_ARRAY_ARGS", + "$1 uses number as first arg, sizeof is generally wrong\n" . $herecurr); + } + +# check for multiple semicolons + if ($line =~ /;\s*;\s*$/) { + if (WARN("ONE_SEMICOLON", + "Statements terminations use 1 semicolon\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/(\s*;\s*){2,}$/;/g; + } + } + +# check for #defines like: 1 << <digit> that could be BIT(digit) + if ($line =~ /#\s*define\s+\w+\s+\(?\s*1\s*([ulUL]*)\s*\<\<\s*(?:\d+|$Ident)\s*\)?/) { + my $ull = ""; + $ull = "_ULL" if (defined($1) && $1 =~ /ll/i); + if (CHK("BIT_MACRO", + "Prefer using the BIT$ull macro\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\(?\s*1\s*[ulUL]*\s*<<\s*(\d+|$Ident)\s*\)?/BIT${ull}($1)/; + } + } + +# check for case / default statements not preceded by break/fallthrough/switch + if ($line =~ /^.\s*(?:case\s+(?:$Ident|$Constant)\s*|default):/) { + my $has_break = 0; + my $has_statement = 0; + my $count = 0; + my $prevline = $linenr; + while ($prevline > 1 && ($file || $count < 3) && !$has_break) { + $prevline--; + my $rline = $rawlines[$prevline - 1]; + my $fline = $lines[$prevline - 1]; + last if ($fline =~ /^\@\@/); + next if ($fline =~ /^\-/); + next if ($fline =~ /^.(?:\s*(?:case\s+(?:$Ident|$Constant)[\s$;]*|default):[\s$;]*)*$/); + $has_break = 1 if ($rline =~ /fall[\s_-]*(through|thru)/i); + next if ($fline =~ /^.[\s$;]*$/); + $has_statement = 1; + $count++; + $has_break = 1 if ($fline =~ /\bswitch\b|\b(?:break\s*;[\s$;]*$|return\b|goto\b|continue\b)/); + } + if (!$has_break && $has_statement) { + WARN("MISSING_BREAK", + "Possible switch case/default not preceeded by break or fallthrough comment\n" . $herecurr); + } + } + +# check for switch/default statements without a break; + if ($^V && $^V ge 5.10.0 && + defined $stat && + $stat =~ /^\+[$;\s]*(?:case[$;\s]+\w+[$;\s]*:[$;\s]*|)*[$;\s]*\bdefault[$;\s]*:[$;\s]*;/g) { + my $ctx = ''; + my $herectx = $here . "\n"; + my $cnt = statement_rawlines($stat); + for (my $n = 0; $n < $cnt; $n++) { + $herectx .= raw_line($linenr, $n) . "\n"; + } + WARN("DEFAULT_NO_BREAK", + "switch default: should use break\n" . $herectx); + } + +# check for gcc specific __FUNCTION__ + if ($line =~ /\b__FUNCTION__\b/) { + if (WARN("USE_FUNC", + "__func__ should be used instead of gcc specific __FUNCTION__\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\b__FUNCTION__\b/__func__/g; + } + } + +# check for uses of __DATE__, __TIME__, __TIMESTAMP__ + while ($line =~ /\b(__(?:DATE|TIME|TIMESTAMP)__)\b/g) { + ERROR("DATE_TIME", + "Use of the '$1' macro makes the build non-deterministic\n" . $herecurr); + } + +# check for use of yield() + if ($line =~ /\byield\s*\(\s*\)/) { + WARN("YIELD", + "Using yield() is generally wrong. See yield() kernel-doc (sched/core.c)\n" . $herecurr); + } + +# check for comparisons against true and false + if ($line =~ /\+\s*(.*?)\b(true|false|$Lval)\s*(==|\!=)\s*(true|false|$Lval)\b(.*)$/i) { + my $lead = $1; + my $arg = $2; + my $test = $3; + my $otype = $4; + my $trail = $5; + my $op = "!"; + + ($arg, $otype) = ($otype, $arg) if ($arg =~ /^(?:true|false)$/i); + + my $type = lc($otype); + if ($type =~ /^(?:true|false)$/) { + if (("$test" eq "==" && "$type" eq "true") || + ("$test" eq "!=" && "$type" eq "false")) { + $op = ""; + } + + CHK("BOOL_COMPARISON", + "Using comparison to $otype is error prone\n" . $herecurr); + +## maybe suggesting a correct construct would better +## "Using comparison to $otype is error prone. Perhaps use '${lead}${op}${arg}${trail}'\n" . $herecurr); + + } + } + +# check for semaphores initialized locked + if ($line =~ /^.\s*sema_init.+,\W?0\W?\)/) { + WARN("CONSIDER_COMPLETION", + "consider using a completion\n" . $herecurr); + } + +# recommend kstrto* over simple_strto* and strict_strto* + if ($line =~ /\b((simple|strict)_(strto(l|ll|ul|ull)))\s*\(/) { + WARN("CONSIDER_KSTRTO", + "$1 is obsolete, use k$3 instead\n" . $herecurr); + } + +# check for __initcall(), use device_initcall() explicitly or more appropriate function please + if ($line =~ /^.\s*__initcall\s*\(/) { + WARN("USE_DEVICE_INITCALL", + "please use device_initcall() or more appropriate function instead of __initcall() (see include/linux/init.h)\n" . $herecurr); + } + +# check for various structs that are normally const (ops, kgdb, device_tree) + my $const_structs = qr{ + acpi_dock_ops| + address_space_operations| + backlight_ops| + block_device_operations| + dentry_operations| + dev_pm_ops| + dma_map_ops| + extent_io_ops| + file_lock_operations| + file_operations| + hv_ops| + ide_dma_ops| + intel_dvo_dev_ops| + item_operations| + iwl_ops| + kgdb_arch| + kgdb_io| + kset_uevent_ops| + lock_manager_operations| + microcode_ops| + mtrr_ops| + neigh_ops| + nlmsvc_binding| + of_device_id| + pci_raw_ops| + pipe_buf_operations| + platform_hibernation_ops| + platform_suspend_ops| + proto_ops| + rpc_pipe_ops| + seq_operations| + snd_ac97_build_ops| + soc_pcmcia_socket_ops| + stacktrace_ops| + sysfs_ops| + tty_operations| + uart_ops| + usb_mon_operations| + wd_ops}x; + if ($line !~ /\bconst\b/ && + $line =~ /\bstruct\s+($const_structs)\b/) { + WARN("CONST_STRUCT", + "struct $1 should normally be const\n" . + $herecurr); + } + +# use of NR_CPUS is usually wrong +# ignore definitions of NR_CPUS and usage to define arrays as likely right + if ($line =~ /\bNR_CPUS\b/ && + $line !~ /^.\s*\s*#\s*if\b.*\bNR_CPUS\b/ && + $line !~ /^.\s*\s*#\s*define\b.*\bNR_CPUS\b/ && + $line !~ /^.\s*$Declare\s.*\[[^\]]*NR_CPUS[^\]]*\]/ && + $line !~ /\[[^\]]*\.\.\.[^\]]*NR_CPUS[^\]]*\]/ && + $line !~ /\[[^\]]*NR_CPUS[^\]]*\.\.\.[^\]]*\]/) + { + WARN("NR_CPUS", + "usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc\n" . $herecurr); + } + +# Use of __ARCH_HAS_<FOO> or ARCH_HAVE_<BAR> is wrong. + if ($line =~ /\+\s*#\s*define\s+((?:__)?ARCH_(?:HAS|HAVE)\w*)\b/) { + ERROR("DEFINE_ARCH_HAS", + "#define of '$1' is wrong - use Kconfig variables or standard guards instead\n" . $herecurr); + } + +# likely/unlikely comparisons similar to "(likely(foo) > 0)" + if ($^V && $^V ge 5.10.0 && + $line =~ /\b((?:un)?likely)\s*\(\s*$FuncArg\s*\)\s*$Compare/) { + WARN("LIKELY_MISUSE", + "Using $1 should generally have parentheses around the comparison\n" . $herecurr); + } + +# whine mightly about in_atomic + if ($line =~ /\bin_atomic\s*\(/) { + if ($realfile =~ m@^drivers/@) { + ERROR("IN_ATOMIC", + "do not use in_atomic in drivers\n" . $herecurr); + } elsif ($realfile !~ m@^kernel/@) { + WARN("IN_ATOMIC", + "use of in_atomic() is incorrect outside core kernel code\n" . $herecurr); + } + } + +# check for lockdep_set_novalidate_class + if ($line =~ /^.\s*lockdep_set_novalidate_class\s*\(/ || + $line =~ /__lockdep_no_validate__\s*\)/ ) { + if ($realfile !~ m@^kernel/lockdep@ && + $realfile !~ m@^include/linux/lockdep@ && + $realfile !~ m@^drivers/base/core@) { + ERROR("LOCKDEP", + "lockdep_no_validate class is reserved for device->mutex.\n" . $herecurr); + } + } + + if ($line =~ /debugfs_create_\w+.*\b$mode_perms_world_writable\b/ || + $line =~ /DEVICE_ATTR.*\b$mode_perms_world_writable\b/) { + WARN("EXPORTED_WORLD_WRITABLE", + "Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr); + } + +# Mode permission misuses where it seems decimal should be octal +# This uses a shortcut match to avoid unnecessary uses of a slow foreach loop + if ($^V && $^V ge 5.10.0 && + $line =~ /$mode_perms_search/) { + foreach my $entry (@mode_permission_funcs) { + my $func = $entry->[0]; + my $arg_pos = $entry->[1]; + + my $skip_args = ""; + if ($arg_pos > 1) { + $arg_pos--; + $skip_args = "(?:\\s*$FuncArg\\s*,\\s*){$arg_pos,$arg_pos}"; + } + my $test = "\\b$func\\s*\\(${skip_args}([\\d]+)\\s*[,\\)]"; + if ($line =~ /$test/) { + my $val = $1; + $val = $6 if ($skip_args ne ""); + + if ($val !~ /^0$/ && + (($val =~ /^$Int$/ && $val !~ /^$Octal$/) || + length($val) ne 4)) { + ERROR("NON_OCTAL_PERMISSIONS", + "Use 4 digit octal (0777) not decimal permissions\n" . $herecurr); + } elsif ($val =~ /^$Octal$/ && (oct($val) & 02)) { + ERROR("EXPORTED_WORLD_WRITABLE", + "Exporting writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr); + } + } + } + } + +# validate content of MODULE_LICENSE against list from include/linux/module.h + if ($line =~ /\bMODULE_LICENSE\s*\(\s*($String)\s*\)/) { + my $extracted_string = get_quoted_string($line, $rawline); + my $valid_licenses = qr{ + GPL| + GPL\ v2| + GPL\ and\ additional\ rights| + Dual\ BSD/GPL| + Dual\ MIT/GPL| + Dual\ MPL/GPL| + Proprietary + }x; + if ($extracted_string !~ /^"(?:$valid_licenses)"$/x) { + WARN("MODULE_LICENSE", + "unknown module license " . $extracted_string . "\n" . $herecurr); + } + } + } + + # If we have no input at all, then there is nothing to report on + # so just keep quiet. + if ($#rawlines == -1) { + exit(0); + } + + # In mailback mode only produce a report in the negative, for + # things that appear to be patches. + if ($mailback && ($clean == 1 || !$is_patch)) { + exit(0); + } + + # This is not a patch, and we are are in 'no-patch' mode so + # just keep quiet. + if (!$chk_patch && !$is_patch) { + exit(0); + } + + if (!$is_patch && $file !~ /cover-letter\.patch$/) { + ERROR("NOT_UNIFIED_DIFF", + "Does not appear to be a unified-diff format patch\n"); + } + if ($is_patch && $filename ne '-' && $chk_signoff && $signoff == 0) { + ERROR("MISSING_SIGN_OFF", + "Missing Signed-off-by: line(s)\n"); + } + + print report_dump(); + if ($summary && !($clean == 1 && $quiet == 1)) { + print "$filename " if ($summary_file); + print "total: $cnt_error errors, $cnt_warn warnings, " . + (($check)? "$cnt_chk checks, " : "") . + "$cnt_lines lines checked\n"; + } + + if ($quiet == 0) { + # If there were whitespace errors which cleanpatch can fix + # then suggest that. + if ($rpt_cleaners) { + $rpt_cleaners = 0; + print << "EOM" + +NOTE: Whitespace errors detected. + You may wish to use scripts/cleanpatch or scripts/cleanfile +EOM + } + } + + if ($clean == 0 && $fix && + ("@rawlines" ne "@fixed" || + $#fixed_inserted >= 0 || $#fixed_deleted >= 0)) { + my $newfile = $filename; + $newfile .= ".EXPERIMENTAL-checkpatch-fixes" if (!$fix_inplace); + my $linecount = 0; + my $f; + + @fixed = fix_inserted_deleted_lines(\@fixed, \@fixed_inserted, \@fixed_deleted); + + open($f, '>', $newfile) + or die "$P: Can't open $newfile for write\n"; + foreach my $fixed_line (@fixed) { + $linecount++; + if ($file) { + if ($linecount > 3) { + $fixed_line =~ s/^\+//; + print $f $fixed_line . "\n"; + } + } else { + print $f $fixed_line . "\n"; + } + } + close($f); + + if (!$quiet) { + print << "EOM"; + +Wrote EXPERIMENTAL --fix correction(s) to '$newfile' + +Do _NOT_ trust the results written to this file. +Do _NOT_ submit these changes without inspecting them for correctness. + +This EXPERIMENTAL file is simply a convenience to help rewrite patches. +No warranties, expressed or implied... +EOM + } + } + + if ($quiet == 0) { + print "\n"; + if ($clean == 1) { + print "$vname has no obvious style problems and is ready for submission.\n"; + } else { + print "$vname has style problems, please review.\n"; + } + } + return $clean; +} diff --git a/drivers/staging/greybus/spelling.txt b/drivers/staging/greybus/spelling.txt new file mode 100644 index 0000000..946caf3 --- /dev/null +++ b/drivers/staging/greybus/spelling.txt @@ -0,0 +1,1072 @@ +# Originally from Debian's Lintian tool. Various false positives have been +# removed, and various additions have been made as they've been discovered +# in the kernel source. +# +# License: GPLv2 +# +# The format of each line is: +# mistake||correction +# +abandonning||abandoning +abigious||ambiguous +abitrate||arbitrate +abov||above +abreviated||abbreviated +absense||absence +absolut||absolute +absoulte||absolute +acccess||access +acceleratoin||acceleration +accelleration||acceleration +accesing||accessing +accesnt||accent +accessable||accessible +accesss||access +accidentaly||accidentally +accidentually||accidentally +accoding||according +accomodate||accommodate +accomodates||accommodates +accordign||according +accoring||according +accout||account +accquire||acquire +accquired||acquired +accross||across +acessable||accessible +acess||access +achitecture||architecture +acient||ancient +acitions||actions +acitve||active +acknowldegement||acknowldegement +acknowledgement||acknowledgment +ackowledge||acknowledge +ackowledged||acknowledged +acording||according +activete||activate +acumulating||accumulating +adapater||adapter +addional||additional +additionaly||additionally +addres||address +addreses||addresses +addresss||address +aditional||additional +aditionally||additionally +aditionaly||additionally +adminstrative||administrative +adress||address +adresses||addresses +adviced||advised +afecting||affecting +agaist||against +albumns||albums +alegorical||allegorical +algorith||algorithm +algorithmical||algorithmically +algoritm||algorithm +algoritms||algorithms +algorrithm||algorithm +algorritm||algorithm +allign||align +allocatrd||allocated +allocte||allocate +allpication||application +alocate||allocate +alogirhtms||algorithms +alogrithm||algorithm +alot||a lot +alow||allow +alows||allows +altough||although +alue||value +ambigious||ambiguous +amoung||among +amout||amount +analysator||analyzer +ang||and +anniversery||anniversary +annoucement||announcement +anomolies||anomalies +anomoly||anomaly +anway||anyway +aplication||application +appearence||appearance +applicaion||application +appliction||application +applictions||applications +appplications||applications +appropiate||appropriate +appropriatly||appropriately +approriate||appropriate +approriately||appropriately +apropriate||appropriate +aquainted||acquainted +aquired||acquired +aquisition||acquisition +arbitary||arbitrary +architechture||architecture +arguement||argument +arguements||arguments +aritmetic||arithmetic +arne't||aren't +arraival||arrival +artifical||artificial +artillary||artillery +asign||assign +assertation||assertion +assiged||assigned +assigment||assignment +assigments||assignments +assistent||assistant +assocation||association +associcated||associated +assotiated||associated +assum||assume +assumtpion||assumption +asuming||assuming +asycronous||asynchronous +asynchnous||asynchronous +atomatically||automatically +atomicly||atomically +attachement||attachment +attched||attached +attemps||attempts +attruibutes||attributes +authentification||authentication +automaticaly||automatically +automaticly||automatically +automatize||automate +automatized||automated +automatizes||automates +autonymous||autonomous +auxillary||auxiliary +auxilliary||auxiliary +avaiable||available +avaible||available +availabe||available +availabled||available +availablity||availability +availale||available +availavility||availability +availble||available +availiable||available +avalable||available +avaliable||available +aysnc||async +backgroud||background +backword||backward +backwords||backwards +bahavior||behavior +bakup||backup +baloon||balloon +baloons||balloons +bandwith||bandwidth +batery||battery +beacuse||because +becasue||because +becomming||becoming +becuase||because +beeing||being +befor||before +begining||beginning +beter||better +betweeen||between +bianries||binaries +bitmast||bitmask +boardcast||broadcast +borad||board +boundry||boundary +brievely||briefly +broadcat||broadcast +cacluated||calculated +caculation||calculation +calender||calendar +calle||called +calucate||calculate +calulate||calculate +cancelation||cancellation +capabilites||capabilities +capabitilies||capabilities +capatibilities||capabilities +carefuly||carefully +cariage||carriage +catagory||category +cehck||check +challange||challenge +challanges||challenges +chanell||channel +changable||changeable +channle||channel +channnel||channel +charachter||character +charachters||characters +charactor||character +charater||character +charaters||characters +charcter||character +chcek||check +chck||check +checksuming||checksumming +childern||children +childs||children +chiled||child +chked||checked +chnage||change +chnages||changes +chnnel||channel +choosen||chosen +chouse||chose +circumvernt||circumvent +claread||cleared +clared||cleared +closeing||closing +clustred||clustered +collapsable||collapsible +colorfull||colorful +comand||command +comit||commit +commerical||commercial +comming||coming +comminucation||communication +commited||committed +commiting||committing +committ||commit +commoditiy||commodity +compability||compatibility +compaibility||compatibility +compatability||compatibility +compatable||compatible +compatibiliy||compatibility +compatibilty||compatibility +compatiblity||compatibility +competion||completion +compilant||compliant +compleatly||completely +completly||completely +complient||compliant +componnents||components +compres||compress +compresion||compression +comression||compression +comunication||communication +conbination||combination +conditionaly||conditionally +conected||connected +configuratoin||configuration +configuraton||configuration +configuretion||configuration +conider||consider +conjuction||conjunction +connectinos||connections +connnection||connection +connnections||connections +consistancy||consistency +consistant||consistent +containes||contains +containts||contains +contaisn||contains +contant||contact +contence||contents +continous||continuous +continously||continuously +continueing||continuing +contraints||constraints +controled||controlled +controler||controller +controll||control +contruction||construction +contry||country +convertion||conversion +convertor||converter +convienient||convenient +convinient||convenient +corected||corrected +correponding||corresponding +correponds||corresponds +correspoding||corresponding +cotrol||control +couter||counter +coutner||counter +cryptocraphic||cryptographic +cunter||counter +curently||currently +dafault||default +deafult||default +deamon||daemon +decompres||decompress +decription||description +defailt||default +defferred||deferred +definate||definite +definately||definitely +defintion||definition +defintions||definitions +defualt||default +defult||default +deivce||device +delared||declared +delare||declare +delares||declares +delaring||declaring +delemiter||delimiter +dependancies||dependencies +dependancy||dependency +dependant||dependent +depreacted||deprecated +depreacte||deprecate +desactivate||deactivate +desciptors||descriptors +descripton||description +descrition||description +descritptor||descriptor +desctiptor||descriptor +desriptor||descriptor +desriptors||descriptors +destory||destroy +destoryed||destroyed +destorys||destroys +destroied||destroyed +detabase||database +develope||develop +developement||development +developped||developed +developpement||development +developper||developer +developpment||development +deveolpment||development +devided||divided +deviece||device +diable||disable +dictionnary||dictionary +didnt||didn't +diferent||different +differrence||difference +difinition||definition +diplay||display +direectly||directly +disapear||disappear +disapeared||disappeared +disappared||disappeared +disconnet||disconnect +discontinous||discontinuous +dispertion||dispersion +dissapears||disappears +distiction||distinction +docuentation||documentation +documantation||documentation +documentaion||documentation +documment||document +doesnt||doesn't +dorp||drop +dosen||doesn +downlad||download +downlads||downloads +druing||during +dynmaic||dynamic +easilly||easily +ecspecially||especially +edditable||editable +editting||editing +efficently||efficiently +ehther||ether +eigth||eight +eletronic||electronic +enabledi||enabled +enchanced||enhanced +encorporating||incorporating +encrupted||encrypted +encrypiton||encryption +endianess||endianness +enhaced||enhanced +enlightnment||enlightenment +enocded||encoded +enterily||entirely +enviroiment||environment +enviroment||environment +environement||environment +environent||environment +eqivalent||equivalent +equiped||equipped +equivelant||equivalent +equivilant||equivalent +eror||error +estbalishment||establishment +etsablishment||establishment +etsbalishment||establishment +excecutable||executable +exceded||exceeded +excellant||excellent +existance||existence +existant||existent +exixt||exist +exlcude||exclude +exlcusive||exclusive +exmaple||example +expecially||especially +explicite||explicit +explicitely||explicitly +explict||explicit +explictly||explicitly +expresion||expression +exprimental||experimental +extened||extended +extensability||extensibility +extention||extension +extracter||extractor +faild||failed +faill||fail +failue||failure +failuer||failure +faireness||fairness +faliure||failure +familar||familiar +fatser||faster +feauture||feature +feautures||features +fetaure||feature +fetaures||features +fileystem||filesystem +finanize||finalize +findn||find +finilizes||finalizes +finsih||finish +flusing||flushing +folloing||following +followign||following +follwing||following +forseeable||foreseeable +forse||force +fortan||fortran +forwardig||forwarding +framwork||framework +frequncy||frequency +frome||from +fucntion||function +fuction||function +fuctions||functions +funcion||function +functionallity||functionality +functionaly||functionally +functionnality||functionality +functonality||functionality +funtion||function +funtions||functions +furthur||further +futhermore||furthermore +futrue||future +gaurenteed||guaranteed +generiously||generously +genric||generic +globel||global +grabing||grabbing +grahical||graphical +grahpical||graphical +grapic||graphic +guage||gauge +guarenteed||guaranteed +guarentee||guarantee +halfs||halves +hander||handler +handfull||handful +hanled||handled +happend||happened +harware||hardware +heirarchically||hierarchically +helpfull||helpful +hierachy||hierarchy +hierarchie||hierarchy +howver||however +hsould||should +hypter||hyper +identidier||identifier +imblance||imbalance +immeadiately||immediately +immedaite||immediate +immediatelly||immediately +immediatly||immediately +immidiate||immediate +impelentation||implementation +impementated||implemented +implemantation||implementation +implemenation||implementation +implementaiton||implementation +implementated||implemented +implemention||implementation +implemetation||implementation +implemntation||implementation +implentation||implementation +implmentation||implementation +implmenting||implementing +incomming||incoming +incompatabilities||incompatibilities +incompatable||incompatible +inconsistant||inconsistent +increas||increase +incrment||increment +indendation||indentation +indended||intended +independant||independent +independantly||independently +independed||independent +indiate||indicate +inexpect||inexpected +infomation||information +informatiom||information +informations||information +informtion||information +infromation||information +ingore||ignore +inital||initial +initalised||initialized +initalise||initialize +initalize||initialize +initation||initiation +initators||initiators +initializiation||initialization +initialzed||initialized +initilization||initialization +initilize||initialize +inofficial||unofficial +insititute||institute +instal||install +inteface||interface +integreated||integrated +integrety||integrity +integrey||integrity +intendet||intended +intented||intended +interanl||internal +interchangable||interchangeable +interferring||interfering +interger||integer +intermittant||intermittent +internel||internal +interoprability||interoperability +interrface||interface +interrrupt||interrupt +interrup||interrupt +interrups||interrupts +interruptted||interrupted +interupted||interrupted +interupt||interrupt +intial||initial +intialized||initialized +intialize||initialize +intregral||integral +intrrupt||interrupt +intuative||intuitive +invaid||invalid +invalde||invald +invalide||invalid +invididual||individual +invokation||invocation +invokations||invocations +irrelevent||irrelevant +isnt||isn't +isssue||issue +itslef||itself +jave||java +jeffies||jiffies +juse||just +jus||just +kown||known +langage||language +langauage||language +langauge||language +langugage||language +lauch||launch +layed||laid +leightweight||lightweight +lengh||length +lenght||length +lenth||length +lesstiff||lesstif +libaries||libraries +libary||library +librairies||libraries +libraris||libraries +licenceing||licencing +loggging||logging +loggin||login +logile||logfile +loosing||losing +losted||lost +machinary||machinery +maintainance||maintenance +maintainence||maintenance +maintan||maintain +makeing||making +malplaced||misplaced +malplace||misplace +managable||manageable +managment||management +mangement||management +manoeuvering||maneuvering +mappping||mapping +mathimatical||mathematical +mathimatic||mathematic +mathimatics||mathematics +maxium||maximum +mechamism||mechanism +meetign||meeting +ment||meant +mergable||mergeable +mesage||message +messags||messages +messgaes||messages +messsage||message +messsages||messages +microprocesspr||microprocessor +milliseonds||milliseconds +minumum||minimum +miscelleneous||miscellaneous +misformed||malformed +mispelled||misspelled +mispelt||misspelt +miximum||maximum +mmnemonic||mnemonic +mnay||many +modeled||modelled +modulues||modules +monochorome||monochrome +monochromo||monochrome +monocrome||monochrome +mopdule||module +mroe||more +mulitplied||multiplied +multidimensionnal||multidimensional +multple||multiple +mumber||number +muticast||multicast +mutiple||multiple +mutli||multi +nams||names +navagating||navigating +nead||need +neccecary||necessary +neccesary||necessary +neccessary||necessary +necesary||necessary +negaive||negative +negoitation||negotiation +negotation||negotiation +nerver||never +nescessary||necessary +nessessary||necessary +noticable||noticeable +notications||notifications +notifed||notified +numebr||number +numner||number +obtaion||obtain +occassionally||occasionally +occationally||occasionally +occurance||occurrence +occurances||occurrences +occured||occurred +occurence||occurrence +occure||occurred +occuring||occurring +offet||offset +omitt||omit +ommiting||omitting +ommitted||omitted +onself||oneself +ony||only +operatione||operation +opertaions||operations +optionnal||optional +optmizations||optimizations +orientatied||orientated +orientied||oriented +otherise||otherwise +ouput||output +overaall||overall +overhread||overhead +overlaping||overlapping +overriden||overridden +overun||overrun +pacakge||package +pachage||package +packacge||package +packege||package +packge||package +packtes||packets +pakage||package +pallette||palette +paln||plan +paramameters||parameters +paramater||parameter +parametes||parameters +parametised||parametrised +paramter||parameter +paramters||parameters +particuarly||particularly +particularily||particularly +pased||passed +passin||passing +pathes||paths +pecularities||peculiarities +peformance||performance +peice||piece +pendantic||pedantic +peprocessor||preprocessor +perfoming||performing +permissons||permissions +peroid||period +persistance||persistence +persistant||persistent +platfrom||platform +plattform||platform +pleaes||please +ploting||plotting +plugable||pluggable +poinnter||pointer +poiter||pointer +posible||possible +positon||position +possibilites||possibilities +powerfull||powerful +preceeded||preceded +preceeding||preceding +preceed||precede +precendence||precedence +precission||precision +preemptable||preemptible +prefered||preferred +prefferably||preferably +premption||preemption +prepaired||prepared +pressre||pressure +primative||primitive +princliple||principle +priorty||priority +privilaged||privileged +privilage||privilege +priviledge||privilege +priviledges||privileges +probaly||probably +procceed||proceed +proccesors||processors +procesed||processed +proces||process +processessing||processing +processess||processes +processpr||processor +processsed||processed +processsing||processing +procteted||protected +prodecure||procedure +progams||programs +progess||progress +programers||programmers +programm||program +programms||programs +progresss||progress +promiscous||promiscuous +promps||prompts +pronnounced||pronounced +prononciation||pronunciation +pronouce||pronounce +pronunce||pronounce +propery||property +propigate||propagate +propigation||propagation +propogate||propagate +prosess||process +protable||portable +protcol||protocol +protecion||protection +protocoll||protocol +psudo||pseudo +psuedo||pseudo +psychadelic||psychedelic +pwoer||power +quering||querying +raoming||roaming +reasearcher||researcher +reasearchers||researchers +reasearch||research +recepient||recipient +receving||receiving +recieved||received +recieve||receive +reciever||receiver +recieves||receives +recogniced||recognised +recognizeable||recognizable +recommanded||recommended +recyle||recycle +redircet||redirect +redirectrion||redirection +refcounf||refcount +refence||reference +refered||referred +referenace||reference +refering||referring +refernces||references +refernnce||reference +refrence||reference +registerd||registered +registeresd||registered +registes||registers +registraration||registration +regster||register +regualar||regular +reguator||regulator +regulamentations||regulations +reigstration||registration +releated||related +relevent||relevant +remoote||remote +remore||remote +removeable||removable +repectively||respectively +replacable||replaceable +replacments||replacements +replys||replies +reponse||response +representaion||representation +reqeust||request +requiere||require +requirment||requirement +requred||required +requried||required +requst||request +reseting||resetting +resizeable||resizable +resouces||resources +resoures||resources +responce||response +ressizes||resizes +ressource||resource +ressources||resources +retransmited||retransmitted +retreived||retrieved +retreive||retrieve +retrive||retrieve +retuned||returned +reudce||reduce +reuest||request +reuqest||request +reutnred||returned +rmeoved||removed +rmeove||remove +rmeoves||removes +rountine||routine +routins||routines +rquest||request +runing||running +runned||ran +runnning||running +runtine||runtime +sacrifying||sacrificing +safly||safely +safty||safety +savable||saveable +scaned||scanned +scaning||scanning +scarch||search +seach||search +searchs||searches +secquence||sequence +secund||second +segement||segment +senarios||scenarios +sentivite||sensitive +separatly||separately +sepcify||specify +sepc||spec +seperated||separated +seperately||separately +seperate||separate +seperatly||separately +seperator||separator +sepperate||separate +sequece||sequence +sequencial||sequential +serveral||several +setts||sets +settting||setting +shotdown||shutdown +shoud||should +shouldnt||shouldn't +shoule||should +shrinked||shrunk +siginificantly||significantly +signabl||signal +similary||similarly +similiar||similar +simlar||similar +simliar||similar +simpified||simplified +singaled||signaled +singal||signal +singed||signed +sleeped||slept +softwares||software +speach||speech +specfic||specific +speciefied||specified +specifc||specific +specifed||specified +specificatin||specification +specificaton||specification +specifing||specifying +specifiying||specifying +speficied||specified +speicify||specify +speling||spelling +spinlcok||spinlock +spinock||spinlock +splitted||split +spreaded||spread +sructure||structure +stablilization||stabilization +staically||statically +staion||station +standardss||standards +standartization||standardization +standart||standard +staticly||statically +stoped||stopped +stoppped||stopped +straming||streaming +struc||struct +structres||structures +stuct||struct +stucture||structure +sturcture||structure +subdirectoires||subdirectories +suble||subtle +substract||subtract +succesfully||successfully +succesful||successful +successfull||successful +sucessfully||successfully +sucess||success +superflous||superfluous +superseeded||superseded +suplied||supplied +suported||supported +suport||support +suppored||supported +supportin||supporting +suppoted||supported +suppported||supported +suppport||support +supress||suppress +surpresses||suppresses +susbsystem||subsystem +suspicously||suspiciously +swaping||swapping +switchs||switches +symetric||symmetric +synax||syntax +synchonized||synchronized +syncronize||synchronize +syncronizing||synchronizing +syncronus||synchronous +syste||system +sytem||system +sythesis||synthesis +taht||that +targetted||targeted +targetting||targeting +teh||the +temorary||temporary +temproarily||temporarily +thier||their +threds||threads +threshhold||threshold +throught||through +thses||these +tiggered||triggered +tipically||typically +tmis||this +torerable||tolerable +tramsmitted||transmitted +tramsmit||transmit +tranfer||transfer +transciever||transceiver +transferd||transferrd +transfered||transferred +transfering||transferring +transision||transition +transmittd||transmitted +transormed||transformed +trasmission||transmission +treshold||threshold +trigerring||triggering +trun||turn +ture||true +tyep||type +udpate||update +uesd||used +unconditionaly||unconditionally +underun||underrun +unecessary||unnecessary +unexecpted||unexpected +unexpectd||unexpected +unexpeted||unexpected +unfortunatelly||unfortunately +unifiy||unify +unintialized||uninitialized +unknonw||unknown +unknow||unknown +unkown||unknown +unneedingly||unnecessarily +unresgister||unregister +unsinged||unsigned +unstabel||unstable +unsuccessfull||unsuccessful +unsuported||unsupported +untill||until +unuseful||useless +upate||update +usefule||useful +usefull||useful +usege||usage +usera||users +usualy||usually +utilites||utilities +utillities||utilities +utilties||utilities +utiltity||utility +utitity||utility +utitlty||utility +vaid||valid +vaild||valid +valide||valid +variantions||variations +varient||variant +vaule||value +verbse||verbose +verisons||versions +verison||version +verson||version +vicefersa||vice-versa +virtal||virtual +virtaul||virtual +virtiual||virtual +visiters||visitors +vitual||virtual +wating||waiting +wether||whether +whataver||whatever +whcih||which +whenver||whenever +wheter||whether +whe||when +wierd||weird +wiil||will +wirte||write +withing||within +wnat||want +workarould||workaround +writeing||writing +writting||writing +zombe||zombie +zomebie||zombie -- cgit v0.10.2 From d9984cf0f24860bc3a9d3c8f48d90a148827c5c6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Thu, 31 Mar 2016 22:35:24 -0700 Subject: greybus: scripts: create subdir for checkpatch and spelling.txt They belong in a subdir. Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/checkpatch.pl b/drivers/staging/greybus/checkpatch.pl deleted file mode 100755 index d574d13..0000000 --- a/drivers/staging/greybus/checkpatch.pl +++ /dev/null @@ -1,5993 +0,0 @@ -#!/usr/bin/perl -w -# (c) 2001, Dave Jones. (the file handling bit) -# (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit) -# (c) 2007,2008, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite) -# (c) 2008-2010 Andy Whitcroft <apw@canonical.com> -# Licensed under the terms of the GNU GPL License version 2 - -use strict; -use POSIX; -use File::Basename; -use Cwd 'abs_path'; -use Term::ANSIColor qw(:constants); - -my $P = $0; -my $D = dirname(abs_path($P)); - -my $V = '0.32'; - -use Getopt::Long qw(:config no_auto_abbrev); - -my $quiet = 0; -my $tree = 1; -my $chk_signoff = 1; -my $chk_patch = 1; -my $tst_only; -my $emacs = 0; -my $terse = 0; -my $showfile = 0; -my $file = 0; -my $check = 0; -my $check_orig = 0; -my $summary = 1; -my $mailback = 0; -my $summary_file = 0; -my $show_types = 0; -my $fix = 0; -my $fix_inplace = 0; -my $root; -my %debug; -my %camelcase = (); -my %use_type = (); -my @use = (); -my %ignore_type = (); -my @ignore = (); -my $help = 0; -my $configuration_file = ".checkpatch.conf"; -my $max_line_length = 80; -my $ignore_perl_version = 0; -my $minimum_perl_version = 5.10.0; -my $min_conf_desc_length = 4; -my $spelling_file = "$D/spelling.txt"; -my $codespell = 0; -my $codespellfile = "/usr/share/codespell/dictionary.txt"; -my $color = 1; - -sub help { - my ($exitcode) = @_; - - print << "EOM"; -Usage: $P [OPTION]... [FILE]... -Version: $V - -Options: - -q, --quiet quiet - --no-tree run without a kernel tree - --no-signoff do not check for 'Signed-off-by' line - --patch treat FILE as patchfile (default) - --emacs emacs compile window format - --terse one line per report - --showfile emit diffed file position, not input file position - -f, --file treat FILE as regular source file - --subjective, --strict enable more subjective tests - --types TYPE(,TYPE2...) show only these comma separated message types - --ignore TYPE(,TYPE2...) ignore various comma separated message types - --max-line-length=n set the maximum line length, if exceeded, warn - --min-conf-desc-length=n set the min description length, if shorter, warn - --show-types show the message "types" in the output - --root=PATH PATH to the kernel tree root - --no-summary suppress the per-file summary - --mailback only produce a report in case of warnings/errors - --summary-file include the filename in summary - --debug KEY=[0|1] turn on/off debugging of KEY, where KEY is one of - 'values', 'possible', 'type', and 'attr' (default - is all off) - --test-only=WORD report only warnings/errors containing WORD - literally - --fix EXPERIMENTAL - may create horrible results - If correctable single-line errors exist, create - "<inputfile>.EXPERIMENTAL-checkpatch-fixes" - with potential errors corrected to the preferred - checkpatch style - --fix-inplace EXPERIMENTAL - may create horrible results - Is the same as --fix, but overwrites the input - file. It's your fault if there's no backup or git - --ignore-perl-version override checking of perl version. expect - runtime errors. - --codespell Use the codespell dictionary for spelling/typos - (default:/usr/share/codespell/dictionary.txt) - --codespellfile Use this codespell dictionary - --color Use colors when output is STDOUT (default: on) - -h, --help, --version display this help and exit - -When FILE is - read standard input. -EOM - - exit($exitcode); -} - -my $conf = which_conf($configuration_file); -if (-f $conf) { - my @conf_args; - open(my $conffile, '<', "$conf") - or warn "$P: Can't find a readable $configuration_file file $!\n"; - - while (<$conffile>) { - my $line = $_; - - $line =~ s/\s*\n?$//g; - $line =~ s/^\s*//g; - $line =~ s/\s+/ /g; - - next if ($line =~ m/^\s*#/); - next if ($line =~ m/^\s*$/); - - my @words = split(" ", $line); - foreach my $word (@words) { - last if ($word =~ m/^#/); - push (@conf_args, $word); - } - } - close($conffile); - unshift(@ARGV, @conf_args) if @conf_args; -} - -GetOptions( - 'q|quiet+' => \$quiet, - 'tree!' => \$tree, - 'signoff!' => \$chk_signoff, - 'patch!' => \$chk_patch, - 'emacs!' => \$emacs, - 'terse!' => \$terse, - 'showfile!' => \$showfile, - 'f|file!' => \$file, - 'subjective!' => \$check, - 'strict!' => \$check, - 'ignore=s' => \@ignore, - 'types=s' => \@use, - 'show-types!' => \$show_types, - 'max-line-length=i' => \$max_line_length, - 'min-conf-desc-length=i' => \$min_conf_desc_length, - 'root=s' => \$root, - 'summary!' => \$summary, - 'mailback!' => \$mailback, - 'summary-file!' => \$summary_file, - 'fix!' => \$fix, - 'fix-inplace!' => \$fix_inplace, - 'ignore-perl-version!' => \$ignore_perl_version, - 'debug=s' => \%debug, - 'test-only=s' => \$tst_only, - 'codespell!' => \$codespell, - 'codespellfile=s' => \$codespellfile, - 'color!' => \$color, - 'h|help' => \$help, - 'version' => \$help -) or help(1); - -help(0) if ($help); - -$fix = 1 if ($fix_inplace); -$check_orig = $check; - -my $exit = 0; - -if ($^V && $^V lt $minimum_perl_version) { - printf "$P: requires at least perl version %vd\n", $minimum_perl_version; - if (!$ignore_perl_version) { - exit(1); - } -} - -if ($#ARGV < 0) { - print "$P: no input files\n"; - exit(1); -} - -sub hash_save_array_words { - my ($hashRef, $arrayRef) = @_; - - my @array = split(/,/, join(',', @$arrayRef)); - foreach my $word (@array) { - $word =~ s/\s*\n?$//g; - $word =~ s/^\s*//g; - $word =~ s/\s+/ /g; - $word =~ tr/[a-z]/[A-Z]/; - - next if ($word =~ m/^\s*#/); - next if ($word =~ m/^\s*$/); - - $hashRef->{$word}++; - } -} - -sub hash_show_words { - my ($hashRef, $prefix) = @_; - - if (keys %$hashRef) { - print "\nNOTE: $prefix message types:"; - foreach my $word (sort keys %$hashRef) { - print " $word"; - } - print "\n"; - } -} - -hash_save_array_words(\%ignore_type, \@ignore); -hash_save_array_words(\%use_type, \@use); - -my $dbg_values = 0; -my $dbg_possible = 0; -my $dbg_type = 0; -my $dbg_attr = 0; -for my $key (keys %debug) { - ## no critic - eval "\${dbg_$key} = '$debug{$key}';"; - die "$@" if ($@); -} - -my $rpt_cleaners = 0; - -if ($terse) { - $emacs = 1; - $quiet++; -} - -if ($tree) { - if (defined $root) { - if (!top_of_kernel_tree($root)) { - die "$P: $root: --root does not point at a valid tree\n"; - } - } else { - if (top_of_kernel_tree('.')) { - $root = '.'; - } elsif ($0 =~ m@(.*)/scripts/[^/]*$@ && - top_of_kernel_tree($1)) { - $root = $1; - } - } - - if (!defined $root) { - print "Must be run from the top-level dir. of a kernel tree\n"; - exit(2); - } -} - -my $emitted_corrupt = 0; - -our $Ident = qr{ - [A-Za-z_][A-Za-z\d_]* - (?:\s*\#\#\s*[A-Za-z_][A-Za-z\d_]*)* - }x; -our $Storage = qr{extern|static|asmlinkage}; -our $Sparse = qr{ - __user| - __kernel| - __force| - __iomem| - __pmem| - __must_check| - __init_refok| - __kprobes| - __ref| - __rcu| - __private - }x; -our $InitAttributePrefix = qr{__(?:mem|cpu|dev|net_|)}; -our $InitAttributeData = qr{$InitAttributePrefix(?:initdata\b)}; -our $InitAttributeConst = qr{$InitAttributePrefix(?:initconst\b)}; -our $InitAttributeInit = qr{$InitAttributePrefix(?:init\b)}; -our $InitAttribute = qr{$InitAttributeData|$InitAttributeConst|$InitAttributeInit}; - -# Notes to $Attribute: -# We need \b after 'init' otherwise 'initconst' will cause a false positive in a check -our $Attribute = qr{ - const| - __percpu| - __nocast| - __safe| - __bitwise__| - __packed__| - __packed2__| - __naked| - __maybe_unused| - __always_unused| - __noreturn| - __used| - __cold| - __pure| - __noclone| - __deprecated| - __read_mostly| - __kprobes| - $InitAttribute| - ____cacheline_aligned| - ____cacheline_aligned_in_smp| - ____cacheline_internodealigned_in_smp| - __weak - }x; -our $Modifier; -our $Inline = qr{inline|__always_inline|noinline|__inline|__inline__}; -our $Member = qr{->$Ident|\.$Ident|\[[^]]*\]}; -our $Lval = qr{$Ident(?:$Member)*}; - -our $Int_type = qr{(?i)llu|ull|ll|lu|ul|l|u}; -our $Binary = qr{(?i)0b[01]+$Int_type?}; -our $Hex = qr{(?i)0x[0-9a-f]+$Int_type?}; -our $Int = qr{[0-9]+$Int_type?}; -our $Octal = qr{0[0-7]+$Int_type?}; -our $String = qr{"[X\t]*"}; -our $Float_hex = qr{(?i)0x[0-9a-f]+p-?[0-9]+[fl]?}; -our $Float_dec = qr{(?i)(?:[0-9]+\.[0-9]*|[0-9]*\.[0-9]+)(?:e-?[0-9]+)?[fl]?}; -our $Float_int = qr{(?i)[0-9]+e-?[0-9]+[fl]?}; -our $Float = qr{$Float_hex|$Float_dec|$Float_int}; -our $Constant = qr{$Float|$Binary|$Octal|$Hex|$Int}; -our $Assignment = qr{\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=}; -our $Compare = qr{<=|>=|==|!=|<|(?<!-)>}; -our $Arithmetic = qr{\+|-|\*|\/|%}; -our $Operators = qr{ - <=|>=|==|!=| - =>|->|<<|>>|<|>|!|~| - &&|\|\||,|\^|\+\+|--|&|\||$Arithmetic - }x; - -our $c90_Keywords = qr{do|for|while|if|else|return|goto|continue|switch|default|case|break}x; - -our $BasicType; -our $NonptrType; -our $NonptrTypeMisordered; -our $NonptrTypeWithAttr; -our $Type; -our $TypeMisordered; -our $Declare; -our $DeclareMisordered; - -our $NON_ASCII_UTF8 = qr{ - [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte - | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs - | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte - | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates - | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 - | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 - | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 -}x; - -our $UTF8 = qr{ - [\x09\x0A\x0D\x20-\x7E] # ASCII - | $NON_ASCII_UTF8 -}x; - -our $typeC99Typedefs = qr{(?:__)?(?:[us]_?)?int_?(?:8|16|32|64)_t}; -our $typeOtherOSTypedefs = qr{(?x: - u_(?:char|short|int|long) | # bsd - u(?:nchar|short|int|long) # sysv -)}; -our $typeKernelTypedefs = qr{(?x: - (?:__)?(?:u|s|be|le)(?:8|16|32|64)| - atomic_t -)}; -our $typeTypedefs = qr{(?x: - $typeC99Typedefs\b| - $typeOtherOSTypedefs\b| - $typeKernelTypedefs\b -)}; - -our $zero_initializer = qr{(?:(?:0[xX])?0+$Int_type?|NULL|false)\b}; - -our $logFunctions = qr{(?x: - printk(?:_ratelimited|_once|)| - (?:[a-z0-9]+_){1,2}(?:printk|emerg|alert|crit|err|warning|warn|notice|info|debug|dbg|vdbg|devel|cont|WARN)(?:_ratelimited|_once|)| - WARN(?:_RATELIMIT|_ONCE|)| - panic| - MODULE_[A-Z_]+| - seq_vprintf|seq_printf|seq_puts -)}; - -our $signature_tags = qr{(?xi: - Signed-off-by:| - Acked-by:| - Tested-by:| - Reviewed-by:| - Reported-by:| - Suggested-by:| - To:| - Cc: -)}; - -our @typeListMisordered = ( - qr{char\s+(?:un)?signed}, - qr{int\s+(?:(?:un)?signed\s+)?short\s}, - qr{int\s+short(?:\s+(?:un)?signed)}, - qr{short\s+int(?:\s+(?:un)?signed)}, - qr{(?:un)?signed\s+int\s+short}, - qr{short\s+(?:un)?signed}, - qr{long\s+int\s+(?:un)?signed}, - qr{int\s+long\s+(?:un)?signed}, - qr{long\s+(?:un)?signed\s+int}, - qr{int\s+(?:un)?signed\s+long}, - qr{int\s+(?:un)?signed}, - qr{int\s+long\s+long\s+(?:un)?signed}, - qr{long\s+long\s+int\s+(?:un)?signed}, - qr{long\s+long\s+(?:un)?signed\s+int}, - qr{long\s+long\s+(?:un)?signed}, - qr{long\s+(?:un)?signed}, -); - -our @typeList = ( - qr{void}, - qr{(?:(?:un)?signed\s+)?char}, - qr{(?:(?:un)?signed\s+)?short\s+int}, - qr{(?:(?:un)?signed\s+)?short}, - qr{(?:(?:un)?signed\s+)?int}, - qr{(?:(?:un)?signed\s+)?long\s+int}, - qr{(?:(?:un)?signed\s+)?long\s+long\s+int}, - qr{(?:(?:un)?signed\s+)?long\s+long}, - qr{(?:(?:un)?signed\s+)?long}, - qr{(?:un)?signed}, - qr{float}, - qr{double}, - qr{bool}, - qr{struct\s+$Ident}, - qr{union\s+$Ident}, - qr{enum\s+$Ident}, - qr{${Ident}_t}, - qr{${Ident}_handler}, - qr{${Ident}_handler_fn}, - @typeListMisordered, -); - -our $C90_int_types = qr{(?x: - long\s+long\s+int\s+(?:un)?signed| - long\s+long\s+(?:un)?signed\s+int| - long\s+long\s+(?:un)?signed| - (?:(?:un)?signed\s+)?long\s+long\s+int| - (?:(?:un)?signed\s+)?long\s+long| - int\s+long\s+long\s+(?:un)?signed| - int\s+(?:(?:un)?signed\s+)?long\s+long| - - long\s+int\s+(?:un)?signed| - long\s+(?:un)?signed\s+int| - long\s+(?:un)?signed| - (?:(?:un)?signed\s+)?long\s+int| - (?:(?:un)?signed\s+)?long| - int\s+long\s+(?:un)?signed| - int\s+(?:(?:un)?signed\s+)?long| - - int\s+(?:un)?signed| - (?:(?:un)?signed\s+)?int -)}; - -our @typeListFile = (); -our @typeListWithAttr = ( - @typeList, - qr{struct\s+$InitAttribute\s+$Ident}, - qr{union\s+$InitAttribute\s+$Ident}, -); - -our @modifierList = ( - qr{fastcall}, -); -our @modifierListFile = (); - -our @mode_permission_funcs = ( - ["module_param", 3], - ["module_param_(?:array|named|string)", 4], - ["module_param_array_named", 5], - ["debugfs_create_(?:file|u8|u16|u32|u64|x8|x16|x32|x64|size_t|atomic_t|bool|blob|regset32|u32_array)", 2], - ["proc_create(?:_data|)", 2], - ["(?:CLASS|DEVICE|SENSOR)_ATTR", 2], -); - -#Create a search pattern for all these functions to speed up a loop below -our $mode_perms_search = ""; -foreach my $entry (@mode_permission_funcs) { - $mode_perms_search .= '|' if ($mode_perms_search ne ""); - $mode_perms_search .= $entry->[0]; -} - -our $mode_perms_world_writable = qr{ - S_IWUGO | - S_IWOTH | - S_IRWXUGO | - S_IALLUGO | - 0[0-7][0-7][2367] -}x; - -our $allowed_asm_includes = qr{(?x: - irq| - memory| - time| - reboot -)}; -# memory.h: ARM has a custom one - -# Load common spelling mistakes and build regular expression list. -my $misspellings; -my %spelling_fix; - -if (open(my $spelling, '<', $spelling_file)) { - while (<$spelling>) { - my $line = $_; - - $line =~ s/\s*\n?$//g; - $line =~ s/^\s*//g; - - next if ($line =~ m/^\s*#/); - next if ($line =~ m/^\s*$/); - - my ($suspect, $fix) = split(/\|\|/, $line); - - $spelling_fix{$suspect} = $fix; - } - close($spelling); -} else { - warn "No typos will be found - file '$spelling_file': $!\n"; -} - -if ($codespell) { - if (open(my $spelling, '<', $codespellfile)) { - while (<$spelling>) { - my $line = $_; - - $line =~ s/\s*\n?$//g; - $line =~ s/^\s*//g; - - next if ($line =~ m/^\s*#/); - next if ($line =~ m/^\s*$/); - next if ($line =~ m/, disabled/i); - - $line =~ s/,.*$//; - - my ($suspect, $fix) = split(/->/, $line); - - $spelling_fix{$suspect} = $fix; - } - close($spelling); - } else { - warn "No codespell typos will be found - file '$codespellfile': $!\n"; - } -} - -$misspellings = join("|", sort keys %spelling_fix) if keys %spelling_fix; - -sub build_types { - my $mods = "(?x: \n" . join("|\n ", (@modifierList, @modifierListFile)) . "\n)"; - my $all = "(?x: \n" . join("|\n ", (@typeList, @typeListFile)) . "\n)"; - my $Misordered = "(?x: \n" . join("|\n ", @typeListMisordered) . "\n)"; - my $allWithAttr = "(?x: \n" . join("|\n ", @typeListWithAttr) . "\n)"; - $Modifier = qr{(?:$Attribute|$Sparse|$mods)}; - $BasicType = qr{ - (?:$typeTypedefs\b)| - (?:${all}\b) - }x; - $NonptrType = qr{ - (?:$Modifier\s+|const\s+)* - (?: - (?:typeof|__typeof__)\s*\([^\)]*\)| - (?:$typeTypedefs\b)| - (?:${all}\b) - ) - (?:\s+$Modifier|\s+const)* - }x; - $NonptrTypeMisordered = qr{ - (?:$Modifier\s+|const\s+)* - (?: - (?:${Misordered}\b) - ) - (?:\s+$Modifier|\s+const)* - }x; - $NonptrTypeWithAttr = qr{ - (?:$Modifier\s+|const\s+)* - (?: - (?:typeof|__typeof__)\s*\([^\)]*\)| - (?:$typeTypedefs\b)| - (?:${allWithAttr}\b) - ) - (?:\s+$Modifier|\s+const)* - }x; - $Type = qr{ - $NonptrType - (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+)? - (?:\s+$Inline|\s+$Modifier)* - }x; - $TypeMisordered = qr{ - $NonptrTypeMisordered - (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+)? - (?:\s+$Inline|\s+$Modifier)* - }x; - $Declare = qr{(?:$Storage\s+(?:$Inline\s+)?)?$Type}; - $DeclareMisordered = qr{(?:$Storage\s+(?:$Inline\s+)?)?$TypeMisordered}; -} -build_types(); - -our $Typecast = qr{\s*(\(\s*$NonptrType\s*\)){0,1}\s*}; - -# Using $balanced_parens, $LvalOrFunc, or $FuncArg -# requires at least perl version v5.10.0 -# Any use must be runtime checked with $^V - -our $balanced_parens = qr/(\((?:[^\(\)]++|(?-1))*\))/; -our $LvalOrFunc = qr{((?:[\&\*]\s*)?$Lval)\s*($balanced_parens{0,1})\s*}; -our $FuncArg = qr{$Typecast{0,1}($LvalOrFunc|$Constant|$String)}; - -our $declaration_macros = qr{(?x: - (?:$Storage\s+)?(?:[A-Z_][A-Z0-9]*_){0,2}(?:DEFINE|DECLARE)(?:_[A-Z0-9]+){1,6}\s*\(| - (?:$Storage\s+)?LIST_HEAD\s*\(| - (?:$Storage\s+)?${Type}\s+uninitialized_var\s*\( -)}; - -sub deparenthesize { - my ($string) = @_; - return "" if (!defined($string)); - - while ($string =~ /^\s*\(.*\)\s*$/) { - $string =~ s@^\s*\(\s*@@; - $string =~ s@\s*\)\s*$@@; - } - - $string =~ s@\s+@ @g; - - return $string; -} - -sub seed_camelcase_file { - my ($file) = @_; - - return if (!(-f $file)); - - local $/; - - open(my $include_file, '<', "$file") - or warn "$P: Can't read '$file' $!\n"; - my $text = <$include_file>; - close($include_file); - - my @lines = split('\n', $text); - - foreach my $line (@lines) { - next if ($line !~ /(?:[A-Z][a-z]|[a-z][A-Z])/); - if ($line =~ /^[ \t]*(?:#[ \t]*define|typedef\s+$Type)\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)/) { - $camelcase{$1} = 1; - } elsif ($line =~ /^\s*$Declare\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)\s*[\(\[,;]/) { - $camelcase{$1} = 1; - } elsif ($line =~ /^\s*(?:union|struct|enum)\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)\s*[;\{]/) { - $camelcase{$1} = 1; - } - } -} - -my $camelcase_seeded = 0; -sub seed_camelcase_includes { - return if ($camelcase_seeded); - - my $files; - my $camelcase_cache = ""; - my @include_files = (); - - $camelcase_seeded = 1; - - if (-e ".git") { - my $git_last_include_commit = `git log --no-merges --pretty=format:"%h%n" -1 -- include`; - chomp $git_last_include_commit; - $camelcase_cache = ".checkpatch-camelcase.git.$git_last_include_commit"; - } else { - my $last_mod_date = 0; - $files = `find $root/include -name "*.h"`; - @include_files = split('\n', $files); - foreach my $file (@include_files) { - my $date = POSIX::strftime("%Y%m%d%H%M", - localtime((stat $file)[9])); - $last_mod_date = $date if ($last_mod_date < $date); - } - $camelcase_cache = ".checkpatch-camelcase.date.$last_mod_date"; - } - - if ($camelcase_cache ne "" && -f $camelcase_cache) { - open(my $camelcase_file, '<', "$camelcase_cache") - or warn "$P: Can't read '$camelcase_cache' $!\n"; - while (<$camelcase_file>) { - chomp; - $camelcase{$_} = 1; - } - close($camelcase_file); - - return; - } - - if (-e ".git") { - $files = `git ls-files "include/*.h"`; - @include_files = split('\n', $files); - } - - foreach my $file (@include_files) { - seed_camelcase_file($file); - } - - if ($camelcase_cache ne "") { - unlink glob ".checkpatch-camelcase.*"; - open(my $camelcase_file, '>', "$camelcase_cache") - or warn "$P: Can't write '$camelcase_cache' $!\n"; - foreach (sort { lc($a) cmp lc($b) } keys(%camelcase)) { - print $camelcase_file ("$_\n"); - } - close($camelcase_file); - } -} - -sub git_commit_info { - my ($commit, $id, $desc) = @_; - - return ($id, $desc) if ((which("git") eq "") || !(-e ".git")); - - my $output = `git log --no-color --format='%H %s' -1 $commit 2>&1`; - $output =~ s/^\s*//gm; - my @lines = split("\n", $output); - - return ($id, $desc) if ($#lines < 0); - - if ($lines[0] =~ /^error: short SHA1 $commit is ambiguous\./) { -# Maybe one day convert this block of bash into something that returns -# all matching commit ids, but it's very slow... -# -# echo "checking commits $1..." -# git rev-list --remotes | grep -i "^$1" | -# while read line ; do -# git log --format='%H %s' -1 $line | -# echo "commit $(cut -c 1-12,41-)" -# done - } elsif ($lines[0] =~ /^fatal: ambiguous argument '$commit': unknown revision or path not in the working tree\./) { - } else { - $id = substr($lines[0], 0, 12); - $desc = substr($lines[0], 41); - } - - return ($id, $desc); -} - -$chk_signoff = 0 if ($file); - -my @rawlines = (); -my @lines = (); -my @fixed = (); -my @fixed_inserted = (); -my @fixed_deleted = (); -my $fixlinenr = -1; - -my $vname; -for my $filename (@ARGV) { - my $FILE; - if ($file) { - open($FILE, '-|', "diff -u /dev/null $filename") || - die "$P: $filename: diff failed - $!\n"; - } elsif ($filename eq '-') { - open($FILE, '<&STDIN'); - } else { - open($FILE, '<', "$filename") || - die "$P: $filename: open failed - $!\n"; - } - if ($filename eq '-') { - $vname = 'Your patch'; - } else { - $vname = $filename; - } - while (<$FILE>) { - chomp; - push(@rawlines, $_); - } - close($FILE); - - if ($#ARGV > 0 && $quiet == 0) { - print '-' x length($vname) . "\n"; - print "$vname\n"; - print '-' x length($vname) . "\n"; - } - - if (!process($filename)) { - $exit = 1; - } - @rawlines = (); - @lines = (); - @fixed = (); - @fixed_inserted = (); - @fixed_deleted = (); - $fixlinenr = -1; - @modifierListFile = (); - @typeListFile = (); - build_types(); -} - -if (!$quiet) { - hash_show_words(\%use_type, "Used"); - hash_show_words(\%ignore_type, "Ignored"); - - if ($^V lt 5.10.0) { - print << "EOM" - -NOTE: perl $^V is not modern enough to detect all possible issues. - An upgrade to at least perl v5.10.0 is suggested. -EOM - } - if ($exit) { - print << "EOM" - -NOTE: If any of the errors are false positives, please report - them to the maintainer, see CHECKPATCH in MAINTAINERS. -EOM - } -} - -exit($exit); - -sub top_of_kernel_tree { - my ($root) = @_; - - my @tree_check = ( - "COPYING", "CREDITS", "Kbuild", "MAINTAINERS", "Makefile", - "README", "Documentation", "arch", "include", "drivers", - "fs", "init", "ipc", "kernel", "lib", "scripts", - ); - - foreach my $check (@tree_check) { - if (! -e $root . '/' . $check) { - return 0; - } - } - return 1; -} - -sub parse_email { - my ($formatted_email) = @_; - - my $name = ""; - my $address = ""; - my $comment = ""; - - if ($formatted_email =~ /^(.*)<(\S+\@\S+)>(.*)$/) { - $name = $1; - $address = $2; - $comment = $3 if defined $3; - } elsif ($formatted_email =~ /^\s*<(\S+\@\S+)>(.*)$/) { - $address = $1; - $comment = $2 if defined $2; - } elsif ($formatted_email =~ /(\S+\@\S+)(.*)$/) { - $address = $1; - $comment = $2 if defined $2; - $formatted_email =~ s/$address.*$//; - $name = $formatted_email; - $name = trim($name); - $name =~ s/^\"|\"$//g; - # If there's a name left after stripping spaces and - # leading quotes, and the address doesn't have both - # leading and trailing angle brackets, the address - # is invalid. ie: - # "joe smith joe@smith.com" bad - # "joe smith <joe@smith.com" bad - if ($name ne "" && $address !~ /^<[^>]+>$/) { - $name = ""; - $address = ""; - $comment = ""; - } - } - - $name = trim($name); - $name =~ s/^\"|\"$//g; - $address = trim($address); - $address =~ s/^\<|\>$//g; - - if ($name =~ /[^\w \-]/i) { ##has "must quote" chars - $name =~ s/(?<!\\)"/\\"/g; ##escape quotes - $name = "\"$name\""; - } - - return ($name, $address, $comment); -} - -sub format_email { - my ($name, $address) = @_; - - my $formatted_email; - - $name = trim($name); - $name =~ s/^\"|\"$//g; - $address = trim($address); - - if ($name =~ /[^\w \-]/i) { ##has "must quote" chars - $name =~ s/(?<!\\)"/\\"/g; ##escape quotes - $name = "\"$name\""; - } - - if ("$name" eq "") { - $formatted_email = "$address"; - } else { - $formatted_email = "$name <$address>"; - } - - return $formatted_email; -} - -sub which { - my ($bin) = @_; - - foreach my $path (split(/:/, $ENV{PATH})) { - if (-e "$path/$bin") { - return "$path/$bin"; - } - } - - return ""; -} - -sub which_conf { - my ($conf) = @_; - - foreach my $path (split(/:/, ".:$ENV{HOME}:.scripts")) { - if (-e "$path/$conf") { - return "$path/$conf"; - } - } - - return ""; -} - -sub expand_tabs { - my ($str) = @_; - - my $res = ''; - my $n = 0; - for my $c (split(//, $str)) { - if ($c eq "\t") { - $res .= ' '; - $n++; - for (; ($n % 8) != 0; $n++) { - $res .= ' '; - } - next; - } - $res .= $c; - $n++; - } - - return $res; -} -sub copy_spacing { - (my $res = shift) =~ tr/\t/ /c; - return $res; -} - -sub line_stats { - my ($line) = @_; - - # Drop the diff line leader and expand tabs - $line =~ s/^.//; - $line = expand_tabs($line); - - # Pick the indent from the front of the line. - my ($white) = ($line =~ /^(\s*)/); - - return (length($line), length($white)); -} - -my $sanitise_quote = ''; - -sub sanitise_line_reset { - my ($in_comment) = @_; - - if ($in_comment) { - $sanitise_quote = '*/'; - } else { - $sanitise_quote = ''; - } -} -sub sanitise_line { - my ($line) = @_; - - my $res = ''; - my $l = ''; - - my $qlen = 0; - my $off = 0; - my $c; - - # Always copy over the diff marker. - $res = substr($line, 0, 1); - - for ($off = 1; $off < length($line); $off++) { - $c = substr($line, $off, 1); - - # Comments we are wacking completly including the begin - # and end, all to $;. - if ($sanitise_quote eq '' && substr($line, $off, 2) eq '/*') { - $sanitise_quote = '*/'; - - substr($res, $off, 2, "$;$;"); - $off++; - next; - } - if ($sanitise_quote eq '*/' && substr($line, $off, 2) eq '*/') { - $sanitise_quote = ''; - substr($res, $off, 2, "$;$;"); - $off++; - next; - } - if ($sanitise_quote eq '' && substr($line, $off, 2) eq '//') { - $sanitise_quote = '//'; - - substr($res, $off, 2, $sanitise_quote); - $off++; - next; - } - - # A \ in a string means ignore the next character. - if (($sanitise_quote eq "'" || $sanitise_quote eq '"') && - $c eq "\\") { - substr($res, $off, 2, 'XX'); - $off++; - next; - } - # Regular quotes. - if ($c eq "'" || $c eq '"') { - if ($sanitise_quote eq '') { - $sanitise_quote = $c; - - substr($res, $off, 1, $c); - next; - } elsif ($sanitise_quote eq $c) { - $sanitise_quote = ''; - } - } - - #print "c<$c> SQ<$sanitise_quote>\n"; - if ($off != 0 && $sanitise_quote eq '*/' && $c ne "\t") { - substr($res, $off, 1, $;); - } elsif ($off != 0 && $sanitise_quote eq '//' && $c ne "\t") { - substr($res, $off, 1, $;); - } elsif ($off != 0 && $sanitise_quote && $c ne "\t") { - substr($res, $off, 1, 'X'); - } else { - substr($res, $off, 1, $c); - } - } - - if ($sanitise_quote eq '//') { - $sanitise_quote = ''; - } - - # The pathname on a #include may be surrounded by '<' and '>'. - if ($res =~ /^.\s*\#\s*include\s+\<(.*)\>/) { - my $clean = 'X' x length($1); - $res =~ s@\<.*\>@<$clean>@; - - # The whole of a #error is a string. - } elsif ($res =~ /^.\s*\#\s*(?:error|warning)\s+(.*)\b/) { - my $clean = 'X' x length($1); - $res =~ s@(\#\s*(?:error|warning)\s+).*@$1$clean@; - } - - return $res; -} - -sub get_quoted_string { - my ($line, $rawline) = @_; - - return "" if ($line !~ m/($String)/g); - return substr($rawline, $-[0], $+[0] - $-[0]); -} - -sub ctx_statement_block { - my ($linenr, $remain, $off) = @_; - my $line = $linenr - 1; - my $blk = ''; - my $soff = $off; - my $coff = $off - 1; - my $coff_set = 0; - - my $loff = 0; - - my $type = ''; - my $level = 0; - my @stack = (); - my $p; - my $c; - my $len = 0; - - my $remainder; - while (1) { - @stack = (['', 0]) if ($#stack == -1); - - #warn "CSB: blk<$blk> remain<$remain>\n"; - # If we are about to drop off the end, pull in more - # context. - if ($off >= $len) { - for (; $remain > 0; $line++) { - last if (!defined $lines[$line]); - next if ($lines[$line] =~ /^-/); - $remain--; - $loff = $len; - $blk .= $lines[$line] . "\n"; - $len = length($blk); - $line++; - last; - } - # Bail if there is no further context. - #warn "CSB: blk<$blk> off<$off> len<$len>\n"; - if ($off >= $len) { - last; - } - if ($level == 0 && substr($blk, $off) =~ /^.\s*#\s*define/) { - $level++; - $type = '#'; - } - } - $p = $c; - $c = substr($blk, $off, 1); - $remainder = substr($blk, $off); - - #warn "CSB: c<$c> type<$type> level<$level> remainder<$remainder> coff_set<$coff_set>\n"; - - # Handle nested #if/#else. - if ($remainder =~ /^#\s*(?:ifndef|ifdef|if)\s/) { - push(@stack, [ $type, $level ]); - } elsif ($remainder =~ /^#\s*(?:else|elif)\b/) { - ($type, $level) = @{$stack[$#stack - 1]}; - } elsif ($remainder =~ /^#\s*endif\b/) { - ($type, $level) = @{pop(@stack)}; - } - - # Statement ends at the ';' or a close '}' at the - # outermost level. - if ($level == 0 && $c eq ';') { - last; - } - - # An else is really a conditional as long as its not else if - if ($level == 0 && $coff_set == 0 && - (!defined($p) || $p =~ /(?:\s|\}|\+)/) && - $remainder =~ /^(else)(?:\s|{)/ && - $remainder !~ /^else\s+if\b/) { - $coff = $off + length($1) - 1; - $coff_set = 1; - #warn "CSB: mark coff<$coff> soff<$soff> 1<$1>\n"; - #warn "[" . substr($blk, $soff, $coff - $soff + 1) . "]\n"; - } - - if (($type eq '' || $type eq '(') && $c eq '(') { - $level++; - $type = '('; - } - if ($type eq '(' && $c eq ')') { - $level--; - $type = ($level != 0)? '(' : ''; - - if ($level == 0 && $coff < $soff) { - $coff = $off; - $coff_set = 1; - #warn "CSB: mark coff<$coff>\n"; - } - } - if (($type eq '' || $type eq '{') && $c eq '{') { - $level++; - $type = '{'; - } - if ($type eq '{' && $c eq '}') { - $level--; - $type = ($level != 0)? '{' : ''; - - if ($level == 0) { - if (substr($blk, $off + 1, 1) eq ';') { - $off++; - } - last; - } - } - # Preprocessor commands end at the newline unless escaped. - if ($type eq '#' && $c eq "\n" && $p ne "\\") { - $level--; - $type = ''; - $off++; - last; - } - $off++; - } - # We are truly at the end, so shuffle to the next line. - if ($off == $len) { - $loff = $len + 1; - $line++; - $remain--; - } - - my $statement = substr($blk, $soff, $off - $soff + 1); - my $condition = substr($blk, $soff, $coff - $soff + 1); - - #warn "STATEMENT<$statement>\n"; - #warn "CONDITION<$condition>\n"; - - #print "coff<$coff> soff<$off> loff<$loff>\n"; - - return ($statement, $condition, - $line, $remain + 1, $off - $loff + 1, $level); -} - -sub statement_lines { - my ($stmt) = @_; - - # Strip the diff line prefixes and rip blank lines at start and end. - $stmt =~ s/(^|\n)./$1/g; - $stmt =~ s/^\s*//; - $stmt =~ s/\s*$//; - - my @stmt_lines = ($stmt =~ /\n/g); - - return $#stmt_lines + 2; -} - -sub statement_rawlines { - my ($stmt) = @_; - - my @stmt_lines = ($stmt =~ /\n/g); - - return $#stmt_lines + 2; -} - -sub statement_block_size { - my ($stmt) = @_; - - $stmt =~ s/(^|\n)./$1/g; - $stmt =~ s/^\s*{//; - $stmt =~ s/}\s*$//; - $stmt =~ s/^\s*//; - $stmt =~ s/\s*$//; - - my @stmt_lines = ($stmt =~ /\n/g); - my @stmt_statements = ($stmt =~ /;/g); - - my $stmt_lines = $#stmt_lines + 2; - my $stmt_statements = $#stmt_statements + 1; - - if ($stmt_lines > $stmt_statements) { - return $stmt_lines; - } else { - return $stmt_statements; - } -} - -sub ctx_statement_full { - my ($linenr, $remain, $off) = @_; - my ($statement, $condition, $level); - - my (@chunks); - - # Grab the first conditional/block pair. - ($statement, $condition, $linenr, $remain, $off, $level) = - ctx_statement_block($linenr, $remain, $off); - #print "F: c<$condition> s<$statement> remain<$remain>\n"; - push(@chunks, [ $condition, $statement ]); - if (!($remain > 0 && $condition =~ /^\s*(?:\n[+-])?\s*(?:if|else|do)\b/s)) { - return ($level, $linenr, @chunks); - } - - # Pull in the following conditional/block pairs and see if they - # could continue the statement. - for (;;) { - ($statement, $condition, $linenr, $remain, $off, $level) = - ctx_statement_block($linenr, $remain, $off); - #print "C: c<$condition> s<$statement> remain<$remain>\n"; - last if (!($remain > 0 && $condition =~ /^(?:\s*\n[+-])*\s*(?:else|do)\b/s)); - #print "C: push\n"; - push(@chunks, [ $condition, $statement ]); - } - - return ($level, $linenr, @chunks); -} - -sub ctx_block_get { - my ($linenr, $remain, $outer, $open, $close, $off) = @_; - my $line; - my $start = $linenr - 1; - my $blk = ''; - my @o; - my @c; - my @res = (); - - my $level = 0; - my @stack = ($level); - for ($line = $start; $remain > 0; $line++) { - next if ($rawlines[$line] =~ /^-/); - $remain--; - - $blk .= $rawlines[$line]; - - # Handle nested #if/#else. - if ($lines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) { - push(@stack, $level); - } elsif ($lines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) { - $level = $stack[$#stack - 1]; - } elsif ($lines[$line] =~ /^.\s*#\s*endif\b/) { - $level = pop(@stack); - } - - foreach my $c (split(//, $lines[$line])) { - ##print "C<$c>L<$level><$open$close>O<$off>\n"; - if ($off > 0) { - $off--; - next; - } - - if ($c eq $close && $level > 0) { - $level--; - last if ($level == 0); - } elsif ($c eq $open) { - $level++; - } - } - - if (!$outer || $level <= 1) { - push(@res, $rawlines[$line]); - } - - last if ($level == 0); - } - - return ($level, @res); -} -sub ctx_block_outer { - my ($linenr, $remain) = @_; - - my ($level, @r) = ctx_block_get($linenr, $remain, 1, '{', '}', 0); - return @r; -} -sub ctx_block { - my ($linenr, $remain) = @_; - - my ($level, @r) = ctx_block_get($linenr, $remain, 0, '{', '}', 0); - return @r; -} -sub ctx_statement { - my ($linenr, $remain, $off) = @_; - - my ($level, @r) = ctx_block_get($linenr, $remain, 0, '(', ')', $off); - return @r; -} -sub ctx_block_level { - my ($linenr, $remain) = @_; - - return ctx_block_get($linenr, $remain, 0, '{', '}', 0); -} -sub ctx_statement_level { - my ($linenr, $remain, $off) = @_; - - return ctx_block_get($linenr, $remain, 0, '(', ')', $off); -} - -sub ctx_locate_comment { - my ($first_line, $end_line) = @_; - - # Catch a comment on the end of the line itself. - my ($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*(?:\\\s*)?$@); - return $current_comment if (defined $current_comment); - - # Look through the context and try and figure out if there is a - # comment. - my $in_comment = 0; - $current_comment = ''; - for (my $linenr = $first_line; $linenr < $end_line; $linenr++) { - my $line = $rawlines[$linenr - 1]; - #warn " $line\n"; - if ($linenr == $first_line and $line =~ m@^.\s*\*@) { - $in_comment = 1; - } - if ($line =~ m@/\*@) { - $in_comment = 1; - } - if (!$in_comment && $current_comment ne '') { - $current_comment = ''; - } - $current_comment .= $line . "\n" if ($in_comment); - if ($line =~ m@\*/@) { - $in_comment = 0; - } - } - - chomp($current_comment); - return($current_comment); -} -sub ctx_has_comment { - my ($first_line, $end_line) = @_; - my $cmt = ctx_locate_comment($first_line, $end_line); - - ##print "LINE: $rawlines[$end_line - 1 ]\n"; - ##print "CMMT: $cmt\n"; - - return ($cmt ne ''); -} - -sub raw_line { - my ($linenr, $cnt) = @_; - - my $offset = $linenr - 1; - $cnt++; - - my $line; - while ($cnt) { - $line = $rawlines[$offset++]; - next if (defined($line) && $line =~ /^-/); - $cnt--; - } - - return $line; -} - -sub cat_vet { - my ($vet) = @_; - my ($res, $coded); - - $res = ''; - while ($vet =~ /([^[:cntrl:]]*)([[:cntrl:]]|$)/g) { - $res .= $1; - if ($2 ne '') { - $coded = sprintf("^%c", unpack('C', $2) + 64); - $res .= $coded; - } - } - $res =~ s/$/\$/; - - return $res; -} - -my $av_preprocessor = 0; -my $av_pending; -my @av_paren_type; -my $av_pend_colon; - -sub annotate_reset { - $av_preprocessor = 0; - $av_pending = '_'; - @av_paren_type = ('E'); - $av_pend_colon = 'O'; -} - -sub annotate_values { - my ($stream, $type) = @_; - - my $res; - my $var = '_' x length($stream); - my $cur = $stream; - - print "$stream\n" if ($dbg_values > 1); - - while (length($cur)) { - @av_paren_type = ('E') if ($#av_paren_type < 0); - print " <" . join('', @av_paren_type) . - "> <$type> <$av_pending>" if ($dbg_values > 1); - if ($cur =~ /^(\s+)/o) { - print "WS($1)\n" if ($dbg_values > 1); - if ($1 =~ /\n/ && $av_preprocessor) { - $type = pop(@av_paren_type); - $av_preprocessor = 0; - } - - } elsif ($cur =~ /^(\(\s*$Type\s*)\)/ && $av_pending eq '_') { - print "CAST($1)\n" if ($dbg_values > 1); - push(@av_paren_type, $type); - $type = 'c'; - - } elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\(|\s*$)/) { - print "DECLARE($1)\n" if ($dbg_values > 1); - $type = 'T'; - - } elsif ($cur =~ /^($Modifier)\s*/) { - print "MODIFIER($1)\n" if ($dbg_values > 1); - $type = 'T'; - - } elsif ($cur =~ /^(\#\s*define\s*$Ident)(\(?)/o) { - print "DEFINE($1,$2)\n" if ($dbg_values > 1); - $av_preprocessor = 1; - push(@av_paren_type, $type); - if ($2 ne '') { - $av_pending = 'N'; - } - $type = 'E'; - - } elsif ($cur =~ /^(\#\s*(?:undef\s*$Ident|include\b))/o) { - print "UNDEF($1)\n" if ($dbg_values > 1); - $av_preprocessor = 1; - push(@av_paren_type, $type); - - } elsif ($cur =~ /^(\#\s*(?:ifdef|ifndef|if))/o) { - print "PRE_START($1)\n" if ($dbg_values > 1); - $av_preprocessor = 1; - - push(@av_paren_type, $type); - push(@av_paren_type, $type); - $type = 'E'; - - } elsif ($cur =~ /^(\#\s*(?:else|elif))/o) { - print "PRE_RESTART($1)\n" if ($dbg_values > 1); - $av_preprocessor = 1; - - push(@av_paren_type, $av_paren_type[$#av_paren_type]); - - $type = 'E'; - - } elsif ($cur =~ /^(\#\s*(?:endif))/o) { - print "PRE_END($1)\n" if ($dbg_values > 1); - - $av_preprocessor = 1; - - # Assume all arms of the conditional end as this - # one does, and continue as if the #endif was not here. - pop(@av_paren_type); - push(@av_paren_type, $type); - $type = 'E'; - - } elsif ($cur =~ /^(\\\n)/o) { - print "PRECONT($1)\n" if ($dbg_values > 1); - - } elsif ($cur =~ /^(__attribute__)\s*\(?/o) { - print "ATTR($1)\n" if ($dbg_values > 1); - $av_pending = $type; - $type = 'N'; - - } elsif ($cur =~ /^(sizeof)\s*(\()?/o) { - print "SIZEOF($1)\n" if ($dbg_values > 1); - if (defined $2) { - $av_pending = 'V'; - } - $type = 'N'; - - } elsif ($cur =~ /^(if|while|for)\b/o) { - print "COND($1)\n" if ($dbg_values > 1); - $av_pending = 'E'; - $type = 'N'; - - } elsif ($cur =~/^(case)/o) { - print "CASE($1)\n" if ($dbg_values > 1); - $av_pend_colon = 'C'; - $type = 'N'; - - } elsif ($cur =~/^(return|else|goto|typeof|__typeof__)\b/o) { - print "KEYWORD($1)\n" if ($dbg_values > 1); - $type = 'N'; - - } elsif ($cur =~ /^(\()/o) { - print "PAREN('$1')\n" if ($dbg_values > 1); - push(@av_paren_type, $av_pending); - $av_pending = '_'; - $type = 'N'; - - } elsif ($cur =~ /^(\))/o) { - my $new_type = pop(@av_paren_type); - if ($new_type ne '_') { - $type = $new_type; - print "PAREN('$1') -> $type\n" - if ($dbg_values > 1); - } else { - print "PAREN('$1')\n" if ($dbg_values > 1); - } - - } elsif ($cur =~ /^($Ident)\s*\(/o) { - print "FUNC($1)\n" if ($dbg_values > 1); - $type = 'V'; - $av_pending = 'V'; - - } elsif ($cur =~ /^($Ident\s*):(?:\s*\d+\s*(,|=|;))?/) { - if (defined $2 && $type eq 'C' || $type eq 'T') { - $av_pend_colon = 'B'; - } elsif ($type eq 'E') { - $av_pend_colon = 'L'; - } - print "IDENT_COLON($1,$type>$av_pend_colon)\n" if ($dbg_values > 1); - $type = 'V'; - - } elsif ($cur =~ /^($Ident|$Constant)/o) { - print "IDENT($1)\n" if ($dbg_values > 1); - $type = 'V'; - - } elsif ($cur =~ /^($Assignment)/o) { - print "ASSIGN($1)\n" if ($dbg_values > 1); - $type = 'N'; - - } elsif ($cur =~/^(;|{|})/) { - print "END($1)\n" if ($dbg_values > 1); - $type = 'E'; - $av_pend_colon = 'O'; - - } elsif ($cur =~/^(,)/) { - print "COMMA($1)\n" if ($dbg_values > 1); - $type = 'C'; - - } elsif ($cur =~ /^(\?)/o) { - print "QUESTION($1)\n" if ($dbg_values > 1); - $type = 'N'; - - } elsif ($cur =~ /^(:)/o) { - print "COLON($1,$av_pend_colon)\n" if ($dbg_values > 1); - - substr($var, length($res), 1, $av_pend_colon); - if ($av_pend_colon eq 'C' || $av_pend_colon eq 'L') { - $type = 'E'; - } else { - $type = 'N'; - } - $av_pend_colon = 'O'; - - } elsif ($cur =~ /^(\[)/o) { - print "CLOSE($1)\n" if ($dbg_values > 1); - $type = 'N'; - - } elsif ($cur =~ /^(-(?![->])|\+(?!\+)|\*|\&\&|\&)/o) { - my $variant; - - print "OPV($1)\n" if ($dbg_values > 1); - if ($type eq 'V') { - $variant = 'B'; - } else { - $variant = 'U'; - } - - substr($var, length($res), 1, $variant); - $type = 'N'; - - } elsif ($cur =~ /^($Operators)/o) { - print "OP($1)\n" if ($dbg_values > 1); - if ($1 ne '++' && $1 ne '--') { - $type = 'N'; - } - - } elsif ($cur =~ /(^.)/o) { - print "C($1)\n" if ($dbg_values > 1); - } - if (defined $1) { - $cur = substr($cur, length($1)); - $res .= $type x length($1); - } - } - - return ($res, $var); -} - -sub possible { - my ($possible, $line) = @_; - my $notPermitted = qr{(?: - ^(?: - $Modifier| - $Storage| - $Type| - DEFINE_\S+ - )$| - ^(?: - goto| - return| - case| - else| - asm|__asm__| - do| - \#| - \#\#| - )(?:\s|$)| - ^(?:typedef|struct|enum)\b - )}x; - warn "CHECK<$possible> ($line)\n" if ($dbg_possible > 2); - if ($possible !~ $notPermitted) { - # Check for modifiers. - $possible =~ s/\s*$Storage\s*//g; - $possible =~ s/\s*$Sparse\s*//g; - if ($possible =~ /^\s*$/) { - - } elsif ($possible =~ /\s/) { - $possible =~ s/\s*$Type\s*//g; - for my $modifier (split(' ', $possible)) { - if ($modifier !~ $notPermitted) { - warn "MODIFIER: $modifier ($possible) ($line)\n" if ($dbg_possible); - push(@modifierListFile, $modifier); - } - } - - } else { - warn "POSSIBLE: $possible ($line)\n" if ($dbg_possible); - push(@typeListFile, $possible); - } - build_types(); - } else { - warn "NOTPOSS: $possible ($line)\n" if ($dbg_possible > 1); - } -} - -my $prefix = ''; - -sub show_type { - my ($type) = @_; - - return defined $use_type{$type} if (scalar keys %use_type > 0); - - return !defined $ignore_type{$type}; -} - -sub report { - my ($level, $type, $msg) = @_; - - if (!show_type($type) || - (defined $tst_only && $msg !~ /\Q$tst_only\E/)) { - return 0; - } - my $output = ''; - if (-t STDOUT && $color) { - if ($level eq 'ERROR') { - $output .= RED; - } elsif ($level eq 'WARNING') { - $output .= YELLOW; - } else { - $output .= GREEN; - } - } - $output .= $prefix . $level . ':'; - if ($show_types) { - $output .= BLUE if (-t STDOUT && $color); - $output .= "$type:"; - } - $output .= RESET if (-t STDOUT && $color); - $output .= ' ' . $msg . "\n"; - - if ($showfile) { - my @lines = split("\n", $output, -1); - splice(@lines, 1, 1); - $output = join("\n", @lines); - } - $output = (split('\n', $output))[0] . "\n" if ($terse); - - push(our @report, $output); - - return 1; -} - -sub report_dump { - our @report; -} - -sub fixup_current_range { - my ($lineRef, $offset, $length) = @_; - - if ($$lineRef =~ /^\@\@ -\d+,\d+ \+(\d+),(\d+) \@\@/) { - my $o = $1; - my $l = $2; - my $no = $o + $offset; - my $nl = $l + $length; - $$lineRef =~ s/\+$o,$l \@\@/\+$no,$nl \@\@/; - } -} - -sub fix_inserted_deleted_lines { - my ($linesRef, $insertedRef, $deletedRef) = @_; - - my $range_last_linenr = 0; - my $delta_offset = 0; - - my $old_linenr = 0; - my $new_linenr = 0; - - my $next_insert = 0; - my $next_delete = 0; - - my @lines = (); - - my $inserted = @{$insertedRef}[$next_insert++]; - my $deleted = @{$deletedRef}[$next_delete++]; - - foreach my $old_line (@{$linesRef}) { - my $save_line = 1; - my $line = $old_line; #don't modify the array - if ($line =~ /^(?:\+\+\+|\-\-\-)\s+\S+/) { #new filename - $delta_offset = 0; - } elsif ($line =~ /^\@\@ -\d+,\d+ \+\d+,\d+ \@\@/) { #new hunk - $range_last_linenr = $new_linenr; - fixup_current_range(\$line, $delta_offset, 0); - } - - while (defined($deleted) && ${$deleted}{'LINENR'} == $old_linenr) { - $deleted = @{$deletedRef}[$next_delete++]; - $save_line = 0; - fixup_current_range(\$lines[$range_last_linenr], $delta_offset--, -1); - } - - while (defined($inserted) && ${$inserted}{'LINENR'} == $old_linenr) { - push(@lines, ${$inserted}{'LINE'}); - $inserted = @{$insertedRef}[$next_insert++]; - $new_linenr++; - fixup_current_range(\$lines[$range_last_linenr], $delta_offset++, 1); - } - - if ($save_line) { - push(@lines, $line); - $new_linenr++; - } - - $old_linenr++; - } - - return @lines; -} - -sub fix_insert_line { - my ($linenr, $line) = @_; - - my $inserted = { - LINENR => $linenr, - LINE => $line, - }; - push(@fixed_inserted, $inserted); -} - -sub fix_delete_line { - my ($linenr, $line) = @_; - - my $deleted = { - LINENR => $linenr, - LINE => $line, - }; - - push(@fixed_deleted, $deleted); -} - -sub ERROR { - my ($type, $msg) = @_; - - if (report("ERROR", $type, $msg)) { - our $clean = 0; - our $cnt_error++; - return 1; - } - return 0; -} -sub WARN { - my ($type, $msg) = @_; - - if (report("WARNING", $type, $msg)) { - our $clean = 0; - our $cnt_warn++; - return 1; - } - return 0; -} -sub CHK { - my ($type, $msg) = @_; - - if ($check && report("CHECK", $type, $msg)) { - our $clean = 0; - our $cnt_chk++; - return 1; - } - return 0; -} - -sub check_absolute_file { - my ($absolute, $herecurr) = @_; - my $file = $absolute; - - ##print "absolute<$absolute>\n"; - - # See if any suffix of this path is a path within the tree. - while ($file =~ s@^[^/]*/@@) { - if (-f "$root/$file") { - ##print "file<$file>\n"; - last; - } - } - if (! -f _) { - return 0; - } - - # It is, so see if the prefix is acceptable. - my $prefix = $absolute; - substr($prefix, -length($file)) = ''; - - ##print "prefix<$prefix>\n"; - if ($prefix ne ".../") { - WARN("USE_RELATIVE_PATH", - "use relative pathname instead of absolute in changelog text\n" . $herecurr); - } -} - -sub trim { - my ($string) = @_; - - $string =~ s/^\s+|\s+$//g; - - return $string; -} - -sub ltrim { - my ($string) = @_; - - $string =~ s/^\s+//; - - return $string; -} - -sub rtrim { - my ($string) = @_; - - $string =~ s/\s+$//; - - return $string; -} - -sub string_find_replace { - my ($string, $find, $replace) = @_; - - $string =~ s/$find/$replace/g; - - return $string; -} - -sub tabify { - my ($leading) = @_; - - my $source_indent = 8; - my $max_spaces_before_tab = $source_indent - 1; - my $spaces_to_tab = " " x $source_indent; - - #convert leading spaces to tabs - 1 while $leading =~ s@^([\t]*)$spaces_to_tab@$1\t@g; - #Remove spaces before a tab - 1 while $leading =~ s@^([\t]*)( {1,$max_spaces_before_tab})\t@$1\t@g; - - return "$leading"; -} - -sub pos_last_openparen { - my ($line) = @_; - - my $pos = 0; - - my $opens = $line =~ tr/\(/\(/; - my $closes = $line =~ tr/\)/\)/; - - my $last_openparen = 0; - - if (($opens == 0) || ($closes >= $opens)) { - return -1; - } - - my $len = length($line); - - for ($pos = 0; $pos < $len; $pos++) { - my $string = substr($line, $pos); - if ($string =~ /^($FuncArg|$balanced_parens)/) { - $pos += length($1) - 1; - } elsif (substr($line, $pos, 1) eq '(') { - $last_openparen = $pos; - } elsif (index($string, '(') == -1) { - last; - } - } - - return length(expand_tabs(substr($line, 0, $last_openparen))) + 1; -} - -sub process { - my $filename = shift; - - my $linenr=0; - my $prevline=""; - my $prevrawline=""; - my $stashline=""; - my $stashrawline=""; - - my $length; - my $indent; - my $previndent=0; - my $stashindent=0; - - our $clean = 1; - my $signoff = 0; - my $is_patch = 0; - my $in_header_lines = $file ? 0 : 1; - my $in_commit_log = 0; #Scanning lines before patch - my $commit_log_possible_stack_dump = 0; - my $commit_log_long_line = 0; - my $commit_log_has_diff = 0; - my $reported_maintainer_file = 0; - my $non_utf8_charset = 0; - - my $last_blank_line = 0; - my $last_coalesced_string_linenr = -1; - - our @report = (); - our $cnt_lines = 0; - our $cnt_error = 0; - our $cnt_warn = 0; - our $cnt_chk = 0; - - # Trace the real file/line as we go. - my $realfile = ''; - my $realline = 0; - my $realcnt = 0; - my $here = ''; - my $in_comment = 0; - my $comment_edge = 0; - my $first_line = 0; - my $p1_prefix = ''; - - my $prev_values = 'E'; - - # suppression flags - my %suppress_ifbraces; - my %suppress_whiletrailers; - my %suppress_export; - my $suppress_statement = 0; - - my %signatures = (); - - # Pre-scan the patch sanitizing the lines. - # Pre-scan the patch looking for any __setup documentation. - # - my @setup_docs = (); - my $setup_docs = 0; - - my $camelcase_file_seeded = 0; - - sanitise_line_reset(); - my $line; - foreach my $rawline (@rawlines) { - $linenr++; - $line = $rawline; - - push(@fixed, $rawline) if ($fix); - - if ($rawline=~/^\+\+\+\s+(\S+)/) { - $setup_docs = 0; - if ($1 =~ m@Documentation/kernel-parameters.txt$@) { - $setup_docs = 1; - } - #next; - } - if ($rawline=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) { - $realline=$1-1; - if (defined $2) { - $realcnt=$3+1; - } else { - $realcnt=1+1; - } - $in_comment = 0; - - # Guestimate if this is a continuing comment. Run - # the context looking for a comment "edge". If this - # edge is a close comment then we must be in a comment - # at context start. - my $edge; - my $cnt = $realcnt; - for (my $ln = $linenr + 1; $cnt > 0; $ln++) { - next if (defined $rawlines[$ln - 1] && - $rawlines[$ln - 1] =~ /^-/); - $cnt--; - #print "RAW<$rawlines[$ln - 1]>\n"; - last if (!defined $rawlines[$ln - 1]); - if ($rawlines[$ln - 1] =~ m@(/\*|\*/)@ && - $rawlines[$ln - 1] !~ m@"[^"]*(?:/\*|\*/)[^"]*"@) { - ($edge) = $1; - last; - } - } - if (defined $edge && $edge eq '*/') { - $in_comment = 1; - } - - # Guestimate if this is a continuing comment. If this - # is the start of a diff block and this line starts - # ' *' then it is very likely a comment. - if (!defined $edge && - $rawlines[$linenr] =~ m@^.\s*(?:\*\*+| \*)(?:\s|$)@) - { - $in_comment = 1; - } - - ##print "COMMENT:$in_comment edge<$edge> $rawline\n"; - sanitise_line_reset($in_comment); - - } elsif ($realcnt && $rawline =~ /^(?:\+| |$)/) { - # Standardise the strings and chars within the input to - # simplify matching -- only bother with positive lines. - $line = sanitise_line($rawline); - } - push(@lines, $line); - - if ($realcnt > 1) { - $realcnt-- if ($line =~ /^(?:\+| |$)/); - } else { - $realcnt = 0; - } - - #print "==>$rawline\n"; - #print "-->$line\n"; - - if ($setup_docs && $line =~ /^\+/) { - push(@setup_docs, $line); - } - } - - $prefix = ''; - - $realcnt = 0; - $linenr = 0; - $fixlinenr = -1; - foreach my $line (@lines) { - $linenr++; - $fixlinenr++; - my $sline = $line; #copy of $line - $sline =~ s/$;/ /g; #with comments as spaces - - my $rawline = $rawlines[$linenr - 1]; - -#extract the line range in the file after the patch is applied - if (!$in_commit_log && - $line =~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) { - $is_patch = 1; - $first_line = $linenr + 1; - $realline=$1-1; - if (defined $2) { - $realcnt=$3+1; - } else { - $realcnt=1+1; - } - annotate_reset(); - $prev_values = 'E'; - - %suppress_ifbraces = (); - %suppress_whiletrailers = (); - %suppress_export = (); - $suppress_statement = 0; - next; - -# track the line number as we move through the hunk, note that -# new versions of GNU diff omit the leading space on completely -# blank context lines so we need to count that too. - } elsif ($line =~ /^( |\+|$)/) { - $realline++; - $realcnt-- if ($realcnt != 0); - - # Measure the line length and indent. - ($length, $indent) = line_stats($rawline); - - # Track the previous line. - ($prevline, $stashline) = ($stashline, $line); - ($previndent, $stashindent) = ($stashindent, $indent); - ($prevrawline, $stashrawline) = ($stashrawline, $rawline); - - #warn "line<$line>\n"; - - } elsif ($realcnt == 1) { - $realcnt--; - } - - my $hunk_line = ($realcnt != 0); - - $here = "#$linenr: " if (!$file); - $here = "#$realline: " if ($file); - - my $found_file = 0; - # extract the filename as it passes - if ($line =~ /^diff --git.*?(\S+)$/) { - $realfile = $1; - $realfile =~ s@^([^/]*)/@@ if (!$file); - $in_commit_log = 0; - $found_file = 1; - } elsif ($line =~ /^\+\+\+\s+(\S+)/) { - $realfile = $1; - $realfile =~ s@^([^/]*)/@@ if (!$file); - $in_commit_log = 0; - - $p1_prefix = $1; - if (!$file && $tree && $p1_prefix ne '' && - -e "$root/$p1_prefix") { - WARN("PATCH_PREFIX", - "patch prefix '$p1_prefix' exists, appears to be a -p0 patch\n"); - } - - if ($realfile =~ m@^include/asm/@) { - ERROR("MODIFIED_INCLUDE_ASM", - "do not modify files in include/asm, change architecture specific files in include/asm-<architecture>\n" . "$here$rawline\n"); - } - $found_file = 1; - } - -#make up the handle for any error we report on this line - if ($showfile) { - $prefix = "$realfile:$realline: " - } elsif ($emacs) { - if ($file) { - $prefix = "$filename:$realline: "; - } else { - $prefix = "$filename:$linenr: "; - } - } - - if ($found_file) { - if ($realfile =~ m@^(?:drivers/net/|net/|drivers/staging/)@) { - $check = 1; - } else { - $check = $check_orig; - } - next; - } - - $here .= "FILE: $realfile:$realline:" if ($realcnt != 0); - - my $hereline = "$here\n$rawline\n"; - my $herecurr = "$here\n$rawline\n"; - my $hereprev = "$here\n$prevrawline\n$rawline\n"; - - $cnt_lines++ if ($realcnt != 0); - -# Check if the commit log has what seems like a diff which can confuse patch - if ($in_commit_log && !$commit_log_has_diff && - (($line =~ m@^\s+diff\b.*a/[\w/]+@ && - $line =~ m@^\s+diff\b.*a/([\w/]+)\s+b/$1\b@) || - $line =~ m@^\s*(?:\-\-\-\s+a/|\+\+\+\s+b/)@ || - $line =~ m/^\s*\@\@ \-\d+,\d+ \+\d+,\d+ \@\@/)) { - ERROR("DIFF_IN_COMMIT_MSG", - "Avoid using diff content in the commit message - patch(1) might not work\n" . $herecurr); - $commit_log_has_diff = 1; - } - -# Check for incorrect file permissions - if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) { - my $permhere = $here . "FILE: $realfile\n"; - if ($realfile !~ m@scripts/@ && - $realfile !~ /\.(py|pl|awk|sh)$/) { - ERROR("EXECUTE_PERMISSIONS", - "do not set execute permissions for source files\n" . $permhere); - } - } - -# Check the patch for a signoff: - if ($line =~ /^\s*signed-off-by:/i) { - $signoff++; - $in_commit_log = 0; - } - -# Check if MAINTAINERS is being updated. If so, there's probably no need to -# emit the "does MAINTAINERS need updating?" message on file add/move/delete - if ($line =~ /^\s*MAINTAINERS\s*\|/) { - $reported_maintainer_file = 1; - } - -# Check signature styles - if (!$in_header_lines && - $line =~ /^(\s*)([a-z0-9_-]+by:|$signature_tags)(\s*)(.*)/i) { - my $space_before = $1; - my $sign_off = $2; - my $space_after = $3; - my $email = $4; - my $ucfirst_sign_off = ucfirst(lc($sign_off)); - - if ($sign_off !~ /$signature_tags/) { - WARN("BAD_SIGN_OFF", - "Non-standard signature: $sign_off\n" . $herecurr); - } - if (defined $space_before && $space_before ne "") { - if (WARN("BAD_SIGN_OFF", - "Do not use whitespace before $ucfirst_sign_off\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] = - "$ucfirst_sign_off $email"; - } - } - if ($sign_off =~ /-by:$/i && $sign_off ne $ucfirst_sign_off) { - if (WARN("BAD_SIGN_OFF", - "'$ucfirst_sign_off' is the preferred signature form\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] = - "$ucfirst_sign_off $email"; - } - - } - if (!defined $space_after || $space_after ne " ") { - if (WARN("BAD_SIGN_OFF", - "Use a single space after $ucfirst_sign_off\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] = - "$ucfirst_sign_off $email"; - } - } - - my ($email_name, $email_address, $comment) = parse_email($email); - my $suggested_email = format_email(($email_name, $email_address)); - if ($suggested_email eq "") { - ERROR("BAD_SIGN_OFF", - "Unrecognized email address: '$email'\n" . $herecurr); - } else { - my $dequoted = $suggested_email; - $dequoted =~ s/^"//; - $dequoted =~ s/" </ </; - # Don't force email to have quotes - # Allow just an angle bracketed address - if ("$dequoted$comment" ne $email && - "<$email_address>$comment" ne $email && - "$suggested_email$comment" ne $email) { - WARN("BAD_SIGN_OFF", - "email address '$email' might be better as '$suggested_email$comment'\n" . $herecurr); - } - } - -# Check for duplicate signatures - my $sig_nospace = $line; - $sig_nospace =~ s/\s//g; - $sig_nospace = lc($sig_nospace); - if (defined $signatures{$sig_nospace}) { - WARN("BAD_SIGN_OFF", - "Duplicate signature\n" . $herecurr); - } else { - $signatures{$sig_nospace} = 1; - } - } - -# Check email subject for common tools that don't need to be mentioned - if ($in_header_lines && - $line =~ /^Subject:.*\b(?:checkpatch|sparse|smatch)\b[^:]/i) { - WARN("EMAIL_SUBJECT", - "A patch subject line should describe the change not the tool that found it\n" . $herecurr); - } - -# Check for old stable address - if ($line =~ /^\s*cc:\s*.*<?\bstable\@kernel\.org\b>?.*$/i) { - ERROR("STABLE_ADDRESS", - "The 'stable' address should be 'stable\@vger.kernel.org'\n" . $herecurr); - } - -# Check for unwanted Gerrit info - if ($in_commit_log && $line =~ /^\s*change-id:/i) { - ERROR("GERRIT_CHANGE_ID", - "Remove Gerrit Change-Id's before submitting upstream.\n" . $herecurr); - } - -# Check if the commit log is in a possible stack dump - if ($in_commit_log && !$commit_log_possible_stack_dump && - ($line =~ /^\s*(?:WARNING:|BUG:)/ || - $line =~ /^\s*\[\s*\d+\.\d{6,6}\s*\]/ || - # timestamp - $line =~ /^\s*\[\<[0-9a-fA-F]{8,}\>\]/)) { - # stack dump address - $commit_log_possible_stack_dump = 1; - } - -# Check for line lengths > 75 in commit log, warn once - if ($in_commit_log && !$commit_log_long_line && - length($line) > 75 && - !($line =~ /^\s*[a-zA-Z0-9_\/\.]+\s+\|\s+\d+/ || - # file delta changes - $line =~ /^\s*(?:[\w\.\-]+\/)++[\w\.\-]+:/ || - # filename then : - $line =~ /^\s*(?:Fixes:|Link:)/i || - # A Fixes: or Link: line - $commit_log_possible_stack_dump)) { - WARN("COMMIT_LOG_LONG_LINE", - "Possible unwrapped commit description (prefer a maximum 75 chars per line)\n" . $herecurr); - $commit_log_long_line = 1; - } - -# Reset possible stack dump if a blank line is found - if ($in_commit_log && $commit_log_possible_stack_dump && - $line =~ /^\s*$/) { - $commit_log_possible_stack_dump = 0; - } - -# Check for git id commit length and improperly formed commit descriptions - if ($in_commit_log && !$commit_log_possible_stack_dump && - ($line =~ /\bcommit\s+[0-9a-f]{5,}\b/i || - ($line =~ /\b[0-9a-f]{12,40}\b/i && - $line !~ /[\<\[][0-9a-f]{12,40}[\>\]]/i && - $line !~ /\bfixes:\s*[0-9a-f]{12,40}/i))) { - my $init_char = "c"; - my $orig_commit = ""; - my $short = 1; - my $long = 0; - my $case = 1; - my $space = 1; - my $hasdesc = 0; - my $hasparens = 0; - my $id = '0123456789ab'; - my $orig_desc = "commit description"; - my $description = ""; - - if ($line =~ /\b(c)ommit\s+([0-9a-f]{5,})\b/i) { - $init_char = $1; - $orig_commit = lc($2); - } elsif ($line =~ /\b([0-9a-f]{12,40})\b/i) { - $orig_commit = lc($1); - } - - $short = 0 if ($line =~ /\bcommit\s+[0-9a-f]{12,40}/i); - $long = 1 if ($line =~ /\bcommit\s+[0-9a-f]{41,}/i); - $space = 0 if ($line =~ /\bcommit [0-9a-f]/i); - $case = 0 if ($line =~ /\b[Cc]ommit\s+[0-9a-f]{5,40}[^A-F]/); - if ($line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("([^"]+)"\)/i) { - $orig_desc = $1; - $hasparens = 1; - } elsif ($line =~ /\bcommit\s+[0-9a-f]{5,}\s*$/i && - defined $rawlines[$linenr] && - $rawlines[$linenr] =~ /^\s*\("([^"]+)"\)/) { - $orig_desc = $1; - $hasparens = 1; - } elsif ($line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("[^"]+$/i && - defined $rawlines[$linenr] && - $rawlines[$linenr] =~ /^\s*[^"]+"\)/) { - $line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("([^"]+)$/i; - $orig_desc = $1; - $rawlines[$linenr] =~ /^\s*([^"]+)"\)/; - $orig_desc .= " " . $1; - $hasparens = 1; - } - - ($id, $description) = git_commit_info($orig_commit, - $id, $orig_desc); - - if ($short || $long || $space || $case || ($orig_desc ne $description) || !$hasparens) { - ERROR("GIT_COMMIT_ID", - "Please use git commit description style 'commit <12+ chars of sha1> (\"<title line>\")' - ie: '${init_char}ommit $id (\"$description\")'\n" . $herecurr); - } - } - -# Check for added, moved or deleted files - if (!$reported_maintainer_file && !$in_commit_log && - ($line =~ /^(?:new|deleted) file mode\s*\d+\s*$/ || - $line =~ /^rename (?:from|to) [\w\/\.\-]+\s*$/ || - ($line =~ /\{\s*([\w\/\.\-]*)\s*\=\>\s*([\w\/\.\-]*)\s*\}/ && - (defined($1) || defined($2))))) { - $reported_maintainer_file = 1; - WARN("FILE_PATH_CHANGES", - "added, moved or deleted file(s), does MAINTAINERS need updating?\n" . $herecurr); - } - -# Check for wrappage within a valid hunk of the file - if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) { - ERROR("CORRUPTED_PATCH", - "patch seems to be corrupt (line wrapped?)\n" . - $herecurr) if (!$emitted_corrupt++); - } - -# Check for absolute kernel paths. - if ($tree) { - while ($line =~ m{(?:^|\s)(/\S*)}g) { - my $file = $1; - - if ($file =~ m{^(.*?)(?::\d+)+:?$} && - check_absolute_file($1, $herecurr)) { - # - } else { - check_absolute_file($file, $herecurr); - } - } - } - -# UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php - if (($realfile =~ /^$/ || $line =~ /^\+/) && - $rawline !~ m/^$UTF8*$/) { - my ($utf8_prefix) = ($rawline =~ /^($UTF8*)/); - - my $blank = copy_spacing($rawline); - my $ptr = substr($blank, 0, length($utf8_prefix)) . "^"; - my $hereptr = "$hereline$ptr\n"; - - CHK("INVALID_UTF8", - "Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $hereptr); - } - -# Check if it's the start of a commit log -# (not a header line and we haven't seen the patch filename) - if ($in_header_lines && $realfile =~ /^$/ && - !($rawline =~ /^\s+\S/ || - $rawline =~ /^(commit\b|from\b|[\w-]+:).*$/i)) { - $in_header_lines = 0; - $in_commit_log = 1; - } - -# Check if there is UTF-8 in a commit log when a mail header has explicitly -# declined it, i.e defined some charset where it is missing. - if ($in_header_lines && - $rawline =~ /^Content-Type:.+charset="(.+)".*$/ && - $1 !~ /utf-8/i) { - $non_utf8_charset = 1; - } - - if ($in_commit_log && $non_utf8_charset && $realfile =~ /^$/ && - $rawline =~ /$NON_ASCII_UTF8/) { - WARN("UTF8_BEFORE_PATCH", - "8-bit UTF-8 used in possible commit log\n" . $herecurr); - } - -# Check for various typo / spelling mistakes - if (defined($misspellings) && - ($in_commit_log || $line =~ /^(?:\+|Subject:)/i)) { - while ($rawline =~ /(?:^|[^a-z@])($misspellings)(?:\b|$|[^a-z@])/gi) { - my $typo = $1; - my $typo_fix = $spelling_fix{lc($typo)}; - $typo_fix = ucfirst($typo_fix) if ($typo =~ /^[A-Z]/); - $typo_fix = uc($typo_fix) if ($typo =~ /^[A-Z]+$/); - my $msg_type = \&WARN; - $msg_type = \&CHK if ($file); - if (&{$msg_type}("TYPO_SPELLING", - "'$typo' may be misspelled - perhaps '$typo_fix'?\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/(^|[^A-Za-z@])($typo)($|[^A-Za-z@])/$1$typo_fix$3/; - } - } - } - -# ignore non-hunk lines and lines being removed - next if (!$hunk_line || $line =~ /^-/); - -#trailing whitespace - if ($line =~ /^\+.*\015/) { - my $herevet = "$here\n" . cat_vet($rawline) . "\n"; - if (ERROR("DOS_LINE_ENDINGS", - "DOS line endings\n" . $herevet) && - $fix) { - $fixed[$fixlinenr] =~ s/[\s\015]+$//; - } - } elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) { - my $herevet = "$here\n" . cat_vet($rawline) . "\n"; - if (ERROR("TRAILING_WHITESPACE", - "trailing whitespace\n" . $herevet) && - $fix) { - $fixed[$fixlinenr] =~ s/\s+$//; - } - - $rpt_cleaners = 1; - } - -# Check for FSF mailing addresses. - if ($rawline =~ /\bwrite to the Free/i || - $rawline =~ /\b59\s+Temple\s+Pl/i || - $rawline =~ /\b51\s+Franklin\s+St/i) { - my $herevet = "$here\n" . cat_vet($rawline) . "\n"; - my $msg_type = \&ERROR; - $msg_type = \&CHK if ($file); - &{$msg_type}("FSF_MAILING_ADDRESS", - "Do not include the paragraph about writing to the Free Software Foundation's mailing address from the sample GPL notice. The FSF has changed addresses in the past, and may do so again. Linux already includes a copy of the GPL.\n" . $herevet) - } - -# check for Kconfig help text having a real description -# Only applies when adding the entry originally, after that we do not have -# sufficient context to determine whether it is indeed long enough. - if ($realfile =~ /Kconfig/ && - $line =~ /^\+\s*config\s+/) { - my $length = 0; - my $cnt = $realcnt; - my $ln = $linenr + 1; - my $f; - my $is_start = 0; - my $is_end = 0; - for (; $cnt > 0 && defined $lines[$ln - 1]; $ln++) { - $f = $lines[$ln - 1]; - $cnt-- if ($lines[$ln - 1] !~ /^-/); - $is_end = $lines[$ln - 1] =~ /^\+/; - - next if ($f =~ /^-/); - last if (!$file && $f =~ /^\@\@/); - - if ($lines[$ln - 1] =~ /^\+\s*(?:bool|tristate)\s*\"/) { - $is_start = 1; - } elsif ($lines[$ln - 1] =~ /^\+\s*(?:---)?help(?:---)?$/) { - $length = -1; - } - - $f =~ s/^.//; - $f =~ s/#.*//; - $f =~ s/^\s+//; - next if ($f =~ /^$/); - if ($f =~ /^\s*config\s/) { - $is_end = 1; - last; - } - $length++; - } - if ($is_start && $is_end && $length < $min_conf_desc_length) { - WARN("CONFIG_DESCRIPTION", - "please write a paragraph that describes the config symbol fully\n" . $herecurr); - } - #print "is_start<$is_start> is_end<$is_end> length<$length>\n"; - } - -# discourage the addition of CONFIG_EXPERIMENTAL in Kconfig. - if ($realfile =~ /Kconfig/ && - $line =~ /.\s*depends on\s+.*\bEXPERIMENTAL\b/) { - WARN("CONFIG_EXPERIMENTAL", - "Use of CONFIG_EXPERIMENTAL is deprecated. For alternatives, see https://lkml.org/lkml/2012/10/23/580\n"); - } - -# discourage the use of boolean for type definition attributes of Kconfig options - if ($realfile =~ /Kconfig/ && - $line =~ /^\+\s*\bboolean\b/) { - WARN("CONFIG_TYPE_BOOLEAN", - "Use of boolean is deprecated, please use bool instead.\n" . $herecurr); - } - - if (($realfile =~ /Makefile.*/ || $realfile =~ /Kbuild.*/) && - ($line =~ /\+(EXTRA_[A-Z]+FLAGS).*/)) { - my $flag = $1; - my $replacement = { - 'EXTRA_AFLAGS' => 'asflags-y', - 'EXTRA_CFLAGS' => 'ccflags-y', - 'EXTRA_CPPFLAGS' => 'cppflags-y', - 'EXTRA_LDFLAGS' => 'ldflags-y', - }; - - WARN("DEPRECATED_VARIABLE", - "Use of $flag is deprecated, please use \`$replacement->{$flag} instead.\n" . $herecurr) if ($replacement->{$flag}); - } - -# check for DT compatible documentation - if (defined $root && - (($realfile =~ /\.dtsi?$/ && $line =~ /^\+\s*compatible\s*=\s*\"/) || - ($realfile =~ /\.[ch]$/ && $line =~ /^\+.*\.compatible\s*=\s*\"/))) { - - my @compats = $rawline =~ /\"([a-zA-Z0-9\-\,\.\+_]+)\"/g; - - my $dt_path = $root . "/Documentation/devicetree/bindings/"; - my $vp_file = $dt_path . "vendor-prefixes.txt"; - - foreach my $compat (@compats) { - my $compat2 = $compat; - $compat2 =~ s/\,[a-zA-Z0-9]*\-/\,<\.\*>\-/; - my $compat3 = $compat; - $compat3 =~ s/\,([a-z]*)[0-9]*\-/\,$1<\.\*>\-/; - `grep -Erq "$compat|$compat2|$compat3" $dt_path`; - if ( $? >> 8 ) { - WARN("UNDOCUMENTED_DT_STRING", - "DT compatible string \"$compat\" appears un-documented -- check $dt_path\n" . $herecurr); - } - - next if $compat !~ /^([a-zA-Z0-9\-]+)\,/; - my $vendor = $1; - `grep -Eq "^$vendor\\b" $vp_file`; - if ( $? >> 8 ) { - WARN("UNDOCUMENTED_DT_STRING", - "DT compatible string vendor \"$vendor\" appears un-documented -- check $vp_file\n" . $herecurr); - } - } - } - -# check we are in a valid source file if not then ignore this hunk - next if ($realfile !~ /\.(h|c|s|S|pl|sh|dtsi|dts)$/); - -# line length limit (with some exclusions) -# -# There are a few types of lines that may extend beyond $max_line_length: -# logging functions like pr_info that end in a string -# lines with a single string -# #defines that are a single string -# -# There are 3 different line length message types: -# LONG_LINE_COMMENT a comment starts before but extends beyond $max_linelength -# LONG_LINE_STRING a string starts before but extends beyond $max_line_length -# LONG_LINE all other lines longer than $max_line_length -# -# if LONG_LINE is ignored, the other 2 types are also ignored -# - - if ($line =~ /^\+/ && $length > $max_line_length) { - my $msg_type = "LONG_LINE"; - - # Check the allowed long line types first - - # logging functions that end in a string that starts - # before $max_line_length - if ($line =~ /^\+\s*$logFunctions\s*\(\s*(?:(?:KERN_\S+\s*|[^"]*))?($String\s*(?:|,|\)\s*;)\s*)$/ && - length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) { - $msg_type = ""; - - # lines with only strings (w/ possible termination) - # #defines with only strings - } elsif ($line =~ /^\+\s*$String\s*(?:\s*|,|\)\s*;)\s*$/ || - $line =~ /^\+\s*#\s*define\s+\w+\s+$String$/) { - $msg_type = ""; - - # Otherwise set the alternate message types - - # a comment starts before $max_line_length - } elsif ($line =~ /($;[\s$;]*)$/ && - length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) { - $msg_type = "LONG_LINE_COMMENT" - - # a quoted string starts before $max_line_length - } elsif ($sline =~ /\s*($String(?:\s*(?:\\|,\s*|\)\s*;\s*))?)$/ && - length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) { - $msg_type = "LONG_LINE_STRING" - } - - if ($msg_type ne "" && - (show_type("LONG_LINE") || show_type($msg_type))) { - WARN($msg_type, - "line over $max_line_length characters\n" . $herecurr); - } - } - -# check for adding lines without a newline. - if ($line =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ No newline at end of file/) { - WARN("MISSING_EOF_NEWLINE", - "adding a line without newline at end of file\n" . $herecurr); - } - -# Blackfin: use hi/lo macros - if ($realfile =~ m@arch/blackfin/.*\.S$@) { - if ($line =~ /\.[lL][[:space:]]*=.*&[[:space:]]*0x[fF][fF][fF][fF]/) { - my $herevet = "$here\n" . cat_vet($line) . "\n"; - ERROR("LO_MACRO", - "use the LO() macro, not (... & 0xFFFF)\n" . $herevet); - } - if ($line =~ /\.[hH][[:space:]]*=.*>>[[:space:]]*16/) { - my $herevet = "$here\n" . cat_vet($line) . "\n"; - ERROR("HI_MACRO", - "use the HI() macro, not (... >> 16)\n" . $herevet); - } - } - -# check we are in a valid source file C or perl if not then ignore this hunk - next if ($realfile !~ /\.(h|c|pl|dtsi|dts)$/); - -# at the beginning of a line any tabs must come first and anything -# more than 8 must use tabs. - if ($rawline =~ /^\+\s* \t\s*\S/ || - $rawline =~ /^\+\s* \s*/) { - my $herevet = "$here\n" . cat_vet($rawline) . "\n"; - $rpt_cleaners = 1; - if (ERROR("CODE_INDENT", - "code indent should use tabs where possible\n" . $herevet) && - $fix) { - $fixed[$fixlinenr] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e; - } - } - -# check for space before tabs. - if ($rawline =~ /^\+/ && $rawline =~ / \t/) { - my $herevet = "$here\n" . cat_vet($rawline) . "\n"; - if (WARN("SPACE_BEFORE_TAB", - "please, no space before tabs\n" . $herevet) && - $fix) { - while ($fixed[$fixlinenr] =~ - s/(^\+.*) {8,8}\t/$1\t\t/) {} - while ($fixed[$fixlinenr] =~ - s/(^\+.*) +\t/$1\t/) {} - } - } - -# check for && or || at the start of a line - if ($rawline =~ /^\+\s*(&&|\|\|)/) { - CHK("LOGICAL_CONTINUATIONS", - "Logical continuations should be on the previous line\n" . $hereprev); - } - -# check multi-line statement indentation matches previous line - if ($^V && $^V ge 5.10.0 && - $prevline =~ /^\+([ \t]*)((?:$c90_Keywords(?:\s+if)\s*)|(?:$Declare\s*)?(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*|$Ident\s*=\s*$Ident\s*)\(.*(\&\&|\|\||,)\s*$/) { - $prevline =~ /^\+(\t*)(.*)$/; - my $oldindent = $1; - my $rest = $2; - - my $pos = pos_last_openparen($rest); - if ($pos >= 0) { - $line =~ /^(\+| )([ \t]*)/; - my $newindent = $2; - - my $goodtabindent = $oldindent . - "\t" x ($pos / 8) . - " " x ($pos % 8); - my $goodspaceindent = $oldindent . " " x $pos; - - if ($newindent ne $goodtabindent && - $newindent ne $goodspaceindent) { - - if (CHK("PARENTHESIS_ALIGNMENT", - "Alignment should match open parenthesis\n" . $hereprev) && - $fix && $line =~ /^\+/) { - $fixed[$fixlinenr] =~ - s/^\+[ \t]*/\+$goodtabindent/; - } - } - } - } - -# check for space after cast like "(int) foo" or "(struct foo) bar" -# avoid checking a few false positives: -# "sizeof(<type>)" or "__alignof__(<type>)" -# function pointer declarations like "(*foo)(int) = bar;" -# structure definitions like "(struct foo) { 0 };" -# multiline macros that define functions -# known attributes or the __attribute__ keyword - if ($line =~ /^\+(.*)\(\s*$Type\s*\)([ \t]++)((?![={]|\\$|$Attribute|__attribute__))/ && - (!defined($1) || $1 !~ /\b(?:sizeof|__alignof__)\s*$/)) { - if (CHK("SPACING", - "No space is necessary after a cast\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/(\(\s*$Type\s*\))[ \t]+/$1/; - } - } - -# Block comment styles -# Networking with an initial /* - if ($realfile =~ m@^(drivers/net/|net/)@ && - $prevrawline =~ /^\+[ \t]*\/\*[ \t]*$/ && - $rawline =~ /^\+[ \t]*\*/ && - $realline > 2) { - WARN("NETWORKING_BLOCK_COMMENT_STYLE", - "networking block comments don't use an empty /* line, use /* Comment...\n" . $hereprev); - } - -# Block comments use * on subsequent lines - if ($prevline =~ /$;[ \t]*$/ && #ends in comment - $prevrawline =~ /^\+.*?\/\*/ && #starting /* - $prevrawline !~ /\*\/[ \t]*$/ && #no trailing */ - $rawline =~ /^\+/ && #line is new - $rawline !~ /^\+[ \t]*\*/) { #no leading * - WARN("BLOCK_COMMENT_STYLE", - "Block comments use * on subsequent lines\n" . $hereprev); - } - -# Block comments use */ on trailing lines - if ($rawline !~ m@^\+[ \t]*\*/[ \t]*$@ && #trailing */ - $rawline !~ m@^\+.*/\*.*\*/[ \t]*$@ && #inline /*...*/ - $rawline !~ m@^\+.*\*{2,}/[ \t]*$@ && #trailing **/ - $rawline =~ m@^\+[ \t]*.+\*\/[ \t]*$@) { #non blank */ - WARN("BLOCK_COMMENT_STYLE", - "Block comments use a trailing */ on a separate line\n" . $herecurr); - } - -# check for missing blank lines after struct/union declarations -# with exceptions for various attributes and macros - if ($prevline =~ /^[\+ ]};?\s*$/ && - $line =~ /^\+/ && - !($line =~ /^\+\s*$/ || - $line =~ /^\+\s*EXPORT_SYMBOL/ || - $line =~ /^\+\s*MODULE_/i || - $line =~ /^\+\s*\#\s*(?:end|elif|else)/ || - $line =~ /^\+[a-z_]*init/ || - $line =~ /^\+\s*(?:static\s+)?[A-Z_]*ATTR/ || - $line =~ /^\+\s*DECLARE/ || - $line =~ /^\+\s*__setup/)) { - if (CHK("LINE_SPACING", - "Please use a blank line after function/struct/union/enum declarations\n" . $hereprev) && - $fix) { - fix_insert_line($fixlinenr, "\+"); - } - } - -# check for multiple consecutive blank lines - if ($prevline =~ /^[\+ ]\s*$/ && - $line =~ /^\+\s*$/ && - $last_blank_line != ($linenr - 1)) { - if (CHK("LINE_SPACING", - "Please don't use multiple blank lines\n" . $hereprev) && - $fix) { - fix_delete_line($fixlinenr, $rawline); - } - - $last_blank_line = $linenr; - } - -# check for missing blank lines after declarations - if ($sline =~ /^\+\s+\S/ && #Not at char 1 - # actual declarations - ($prevline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ || - # function pointer declarations - $prevline =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ || - # foo bar; where foo is some local typedef or #define - $prevline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ || - # known declaration macros - $prevline =~ /^\+\s+$declaration_macros/) && - # for "else if" which can look like "$Ident $Ident" - !($prevline =~ /^\+\s+$c90_Keywords\b/ || - # other possible extensions of declaration lines - $prevline =~ /(?:$Compare|$Assignment|$Operators)\s*$/ || - # not starting a section or a macro "\" extended line - $prevline =~ /(?:\{\s*|\\)$/) && - # looks like a declaration - !($sline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ || - # function pointer declarations - $sline =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ || - # foo bar; where foo is some local typedef or #define - $sline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ || - # known declaration macros - $sline =~ /^\+\s+$declaration_macros/ || - # start of struct or union or enum - $sline =~ /^\+\s+(?:union|struct|enum|typedef)\b/ || - # start or end of block or continuation of declaration - $sline =~ /^\+\s+(?:$|[\{\}\.\#\"\?\:\(\[])/ || - # bitfield continuation - $sline =~ /^\+\s+$Ident\s*:\s*\d+\s*[,;]/ || - # other possible extensions of declaration lines - $sline =~ /^\+\s+\(?\s*(?:$Compare|$Assignment|$Operators)/) && - # indentation of previous and current line are the same - (($prevline =~ /\+(\s+)\S/) && $sline =~ /^\+$1\S/)) { - if (WARN("LINE_SPACING", - "Missing a blank line after declarations\n" . $hereprev) && - $fix) { - fix_insert_line($fixlinenr, "\+"); - } - } - -# check for spaces at the beginning of a line. -# Exceptions: -# 1) within comments -# 2) indented preprocessor commands -# 3) hanging labels - if ($rawline =~ /^\+ / && $line !~ /^\+ *(?:$;|#|$Ident:)/) { - my $herevet = "$here\n" . cat_vet($rawline) . "\n"; - if (WARN("LEADING_SPACE", - "please, no spaces at the start of a line\n" . $herevet) && - $fix) { - $fixed[$fixlinenr] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e; - } - } - -# check we are in a valid C source file if not then ignore this hunk - next if ($realfile !~ /\.(h|c)$/); - -# check indentation of any line with a bare else -# (but not if it is a multiple line "if (foo) return bar; else return baz;") -# if the previous line is a break or return and is indented 1 tab more... - if ($sline =~ /^\+([\t]+)(?:}[ \t]*)?else(?:[ \t]*{)?\s*$/) { - my $tabs = length($1) + 1; - if ($prevline =~ /^\+\t{$tabs,$tabs}break\b/ || - ($prevline =~ /^\+\t{$tabs,$tabs}return\b/ && - defined $lines[$linenr] && - $lines[$linenr] !~ /^[ \+]\t{$tabs,$tabs}return/)) { - WARN("UNNECESSARY_ELSE", - "else is not generally useful after a break or return\n" . $hereprev); - } - } - -# check indentation of a line with a break; -# if the previous line is a goto or return and is indented the same # of tabs - if ($sline =~ /^\+([\t]+)break\s*;\s*$/) { - my $tabs = $1; - if ($prevline =~ /^\+$tabs(?:goto|return)\b/) { - WARN("UNNECESSARY_BREAK", - "break is not useful after a goto or return\n" . $hereprev); - } - } - -# discourage the addition of CONFIG_EXPERIMENTAL in #if(def). - if ($line =~ /^\+\s*\#\s*if.*\bCONFIG_EXPERIMENTAL\b/) { - WARN("CONFIG_EXPERIMENTAL", - "Use of CONFIG_EXPERIMENTAL is deprecated. For alternatives, see https://lkml.org/lkml/2012/10/23/580\n"); - } - -# check for RCS/CVS revision markers - if ($rawline =~ /^\+.*\$(Revision|Log|Id)(?:\$|)/) { - WARN("CVS_KEYWORD", - "CVS style keyword markers, these will _not_ be updated\n". $herecurr); - } - -# Blackfin: don't use __builtin_bfin_[cs]sync - if ($line =~ /__builtin_bfin_csync/) { - my $herevet = "$here\n" . cat_vet($line) . "\n"; - ERROR("CSYNC", - "use the CSYNC() macro in asm/blackfin.h\n" . $herevet); - } - if ($line =~ /__builtin_bfin_ssync/) { - my $herevet = "$here\n" . cat_vet($line) . "\n"; - ERROR("SSYNC", - "use the SSYNC() macro in asm/blackfin.h\n" . $herevet); - } - -# check for old HOTPLUG __dev<foo> section markings - if ($line =~ /\b(__dev(init|exit)(data|const|))\b/) { - WARN("HOTPLUG_SECTION", - "Using $1 is unnecessary\n" . $herecurr); - } - -# Check for potential 'bare' types - my ($stat, $cond, $line_nr_next, $remain_next, $off_next, - $realline_next); -#print "LINE<$line>\n"; - if ($linenr >= $suppress_statement && - $realcnt && $sline =~ /.\s*\S/) { - ($stat, $cond, $line_nr_next, $remain_next, $off_next) = - ctx_statement_block($linenr, $realcnt, 0); - $stat =~ s/\n./\n /g; - $cond =~ s/\n./\n /g; - -#print "linenr<$linenr> <$stat>\n"; - # If this statement has no statement boundaries within - # it there is no point in retrying a statement scan - # until we hit end of it. - my $frag = $stat; $frag =~ s/;+\s*$//; - if ($frag !~ /(?:{|;)/) { -#print "skip<$line_nr_next>\n"; - $suppress_statement = $line_nr_next; - } - - # Find the real next line. - $realline_next = $line_nr_next; - if (defined $realline_next && - (!defined $lines[$realline_next - 1] || - substr($lines[$realline_next - 1], $off_next) =~ /^\s*$/)) { - $realline_next++; - } - - my $s = $stat; - $s =~ s/{.*$//s; - - # Ignore goto labels. - if ($s =~ /$Ident:\*$/s) { - - # Ignore functions being called - } elsif ($s =~ /^.\s*$Ident\s*\(/s) { - - } elsif ($s =~ /^.\s*else\b/s) { - - # declarations always start with types - } elsif ($prev_values eq 'E' && $s =~ /^.\s*(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?((?:\s*$Ident)+?)\b(?:\s+$Sparse)?\s*\**\s*(?:$Ident|\(\*[^\)]*\))(?:\s*$Modifier)?\s*(?:;|=|,|\()/s) { - my $type = $1; - $type =~ s/\s+/ /g; - possible($type, "A:" . $s); - - # definitions in global scope can only start with types - } elsif ($s =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b\s*(?!:)/s) { - possible($1, "B:" . $s); - } - - # any (foo ... *) is a pointer cast, and foo is a type - while ($s =~ /\(($Ident)(?:\s+$Sparse)*[\s\*]+\s*\)/sg) { - possible($1, "C:" . $s); - } - - # Check for any sort of function declaration. - # int foo(something bar, other baz); - # void (*store_gdt)(x86_descr_ptr *); - if ($prev_values eq 'E' && $s =~ /^(.(?:typedef\s*)?(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*(?:\b$Ident|\(\*\s*$Ident\))\s*)\(/s) { - my ($name_len) = length($1); - - my $ctx = $s; - substr($ctx, 0, $name_len + 1, ''); - $ctx =~ s/\)[^\)]*$//; - - for my $arg (split(/\s*,\s*/, $ctx)) { - if ($arg =~ /^(?:const\s+)?($Ident)(?:\s+$Sparse)*\s*\**\s*(:?\b$Ident)?$/s || $arg =~ /^($Ident)$/s) { - - possible($1, "D:" . $s); - } - } - } - - } - -# -# Checks which may be anchored in the context. -# - -# Check for switch () and associated case and default -# statements should be at the same indent. - if ($line=~/\bswitch\s*\(.*\)/) { - my $err = ''; - my $sep = ''; - my @ctx = ctx_block_outer($linenr, $realcnt); - shift(@ctx); - for my $ctx (@ctx) { - my ($clen, $cindent) = line_stats($ctx); - if ($ctx =~ /^\+\s*(case\s+|default:)/ && - $indent != $cindent) { - $err .= "$sep$ctx\n"; - $sep = ''; - } else { - $sep = "[...]\n"; - } - } - if ($err ne '') { - ERROR("SWITCH_CASE_INDENT_LEVEL", - "switch and case should be at the same indent\n$hereline$err"); - } - } - -# if/while/etc brace do not go on next line, unless defining a do while loop, -# or if that brace on the next line is for something else - if ($line =~ /(.*)\b((?:if|while|for|switch|(?:[a-z_]+|)for_each[a-z_]+)\s*\(|do\b|else\b)/ && $line !~ /^.\s*\#/) { - my $pre_ctx = "$1$2"; - - my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0); - - if ($line =~ /^\+\t{6,}/) { - WARN("DEEP_INDENTATION", - "Too many leading tabs - consider code refactoring\n" . $herecurr); - } - - my $ctx_cnt = $realcnt - $#ctx - 1; - my $ctx = join("\n", @ctx); - - my $ctx_ln = $linenr; - my $ctx_skip = $realcnt; - - while ($ctx_skip > $ctx_cnt || ($ctx_skip == $ctx_cnt && - defined $lines[$ctx_ln - 1] && - $lines[$ctx_ln - 1] =~ /^-/)) { - ##print "SKIP<$ctx_skip> CNT<$ctx_cnt>\n"; - $ctx_skip-- if (!defined $lines[$ctx_ln - 1] || $lines[$ctx_ln - 1] !~ /^-/); - $ctx_ln++; - } - - #print "realcnt<$realcnt> ctx_cnt<$ctx_cnt>\n"; - #print "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n"; - - if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln - 1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) { - ERROR("OPEN_BRACE", - "that open brace { should be on the previous line\n" . - "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n"); - } - if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ && - $ctx =~ /\)\s*\;\s*$/ && - defined $lines[$ctx_ln - 1]) - { - my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]); - if ($nindent > $indent) { - WARN("TRAILING_SEMICOLON", - "trailing semicolon indicates no statements, indent implies otherwise\n" . - "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n"); - } - } - } - -# Check relative indent for conditionals and blocks. - if ($line =~ /\b(?:(?:if|while|for|(?:[a-z_]+|)for_each[a-z_]+)\s*\(|do\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) { - ($stat, $cond, $line_nr_next, $remain_next, $off_next) = - ctx_statement_block($linenr, $realcnt, 0) - if (!defined $stat); - my ($s, $c) = ($stat, $cond); - - substr($s, 0, length($c), ''); - - # remove inline comments - $s =~ s/$;/ /g; - $c =~ s/$;/ /g; - - # Find out how long the conditional actually is. - my @newlines = ($c =~ /\n/gs); - my $cond_lines = 1 + $#newlines; - - # Make sure we remove the line prefixes as we have - # none on the first line, and are going to readd them - # where necessary. - $s =~ s/\n./\n/gs; - while ($s =~ /\n\s+\\\n/) { - $cond_lines += $s =~ s/\n\s+\\\n/\n/g; - } - - # We want to check the first line inside the block - # starting at the end of the conditional, so remove: - # 1) any blank line termination - # 2) any opening brace { on end of the line - # 3) any do (...) { - my $continuation = 0; - my $check = 0; - $s =~ s/^.*\bdo\b//; - $s =~ s/^\s*{//; - if ($s =~ s/^\s*\\//) { - $continuation = 1; - } - if ($s =~ s/^\s*?\n//) { - $check = 1; - $cond_lines++; - } - - # Also ignore a loop construct at the end of a - # preprocessor statement. - if (($prevline =~ /^.\s*#\s*define\s/ || - $prevline =~ /\\\s*$/) && $continuation == 0) { - $check = 0; - } - - my $cond_ptr = -1; - $continuation = 0; - while ($cond_ptr != $cond_lines) { - $cond_ptr = $cond_lines; - - # If we see an #else/#elif then the code - # is not linear. - if ($s =~ /^\s*\#\s*(?:else|elif)/) { - $check = 0; - } - - # Ignore: - # 1) blank lines, they should be at 0, - # 2) preprocessor lines, and - # 3) labels. - if ($continuation || - $s =~ /^\s*?\n/ || - $s =~ /^\s*#\s*?/ || - $s =~ /^\s*$Ident\s*:/) { - $continuation = ($s =~ /^.*?\\\n/) ? 1 : 0; - if ($s =~ s/^.*?\n//) { - $cond_lines++; - } - } - } - - my (undef, $sindent) = line_stats("+" . $s); - my $stat_real = raw_line($linenr, $cond_lines); - - # Check if either of these lines are modified, else - # this is not this patch's fault. - if (!defined($stat_real) || - $stat !~ /^\+/ && $stat_real !~ /^\+/) { - $check = 0; - } - if (defined($stat_real) && $cond_lines > 1) { - $stat_real = "[...]\n$stat_real"; - } - - #print "line<$line> prevline<$prevline> indent<$indent> sindent<$sindent> check<$check> continuation<$continuation> s<$s> cond_lines<$cond_lines> stat_real<$stat_real> stat<$stat>\n"; - - if ($check && $s ne '' && - (($sindent % 8) != 0 || - ($sindent < $indent) || - ($sindent > $indent + 8))) { - WARN("SUSPECT_CODE_INDENT", - "suspect code indent for conditional statements ($indent, $sindent)\n" . $herecurr . "$stat_real\n"); - } - } - - # Track the 'values' across context and added lines. - my $opline = $line; $opline =~ s/^./ /; - my ($curr_values, $curr_vars) = - annotate_values($opline . "\n", $prev_values); - $curr_values = $prev_values . $curr_values; - if ($dbg_values) { - my $outline = $opline; $outline =~ s/\t/ /g; - print "$linenr > .$outline\n"; - print "$linenr > $curr_values\n"; - print "$linenr > $curr_vars\n"; - } - $prev_values = substr($curr_values, -1); - -#ignore lines not being added - next if ($line =~ /^[^\+]/); - -# check for declarations of signed or unsigned without int - while ($line =~ m{($Declare)\s*(?!char\b|short\b|int\b|long\b)\s*($Ident)?\s*[=,;\[\)\(]}g) { - my $type = $1; - my $var = $2; - $var = "" if (!defined $var); - if ($type =~ /^(?:(?:$Storage|$Inline|$Attribute)\s+)*((?:un)?signed)((?:\s*\*)*)\s*$/) { - my $sign = $1; - my $pointer = $2; - - $pointer = "" if (!defined $pointer); - - if (WARN("UNSPECIFIED_INT", - "Prefer '" . trim($sign) . " int" . rtrim($pointer) . "' to bare use of '$sign" . rtrim($pointer) . "'\n" . $herecurr) && - $fix) { - my $decl = trim($sign) . " int "; - my $comp_pointer = $pointer; - $comp_pointer =~ s/\s//g; - $decl .= $comp_pointer; - $decl = rtrim($decl) if ($var eq ""); - $fixed[$fixlinenr] =~ s@\b$sign\s*\Q$pointer\E\s*$var\b@$decl$var@; - } - } - } - -# TEST: allow direct testing of the type matcher. - if ($dbg_type) { - if ($line =~ /^.\s*$Declare\s*$/) { - ERROR("TEST_TYPE", - "TEST: is type\n" . $herecurr); - } elsif ($dbg_type > 1 && $line =~ /^.+($Declare)/) { - ERROR("TEST_NOT_TYPE", - "TEST: is not type ($1 is)\n". $herecurr); - } - next; - } -# TEST: allow direct testing of the attribute matcher. - if ($dbg_attr) { - if ($line =~ /^.\s*$Modifier\s*$/) { - ERROR("TEST_ATTR", - "TEST: is attr\n" . $herecurr); - } elsif ($dbg_attr > 1 && $line =~ /^.+($Modifier)/) { - ERROR("TEST_NOT_ATTR", - "TEST: is not attr ($1 is)\n". $herecurr); - } - next; - } - -# check for initialisation to aggregates open brace on the next line - if ($line =~ /^.\s*{/ && - $prevline =~ /(?:^|[^=])=\s*$/) { - if (ERROR("OPEN_BRACE", - "that open brace { should be on the previous line\n" . $hereprev) && - $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { - fix_delete_line($fixlinenr - 1, $prevrawline); - fix_delete_line($fixlinenr, $rawline); - my $fixedline = $prevrawline; - $fixedline =~ s/\s*=\s*$/ = {/; - fix_insert_line($fixlinenr, $fixedline); - $fixedline = $line; - $fixedline =~ s/^(.\s*){\s*/$1/; - fix_insert_line($fixlinenr, $fixedline); - } - } - -# -# Checks which are anchored on the added line. -# - -# check for malformed paths in #include statements (uses RAW line) - if ($rawline =~ m{^.\s*\#\s*include\s+[<"](.*)[">]}) { - my $path = $1; - if ($path =~ m{//}) { - ERROR("MALFORMED_INCLUDE", - "malformed #include filename\n" . $herecurr); - } - if ($path =~ "^uapi/" && $realfile =~ m@\binclude/uapi/@) { - ERROR("UAPI_INCLUDE", - "No #include in ...include/uapi/... should use a uapi/ path prefix\n" . $herecurr); - } - } - -# no C99 // comments - if ($line =~ m{//}) { - if (ERROR("C99_COMMENTS", - "do not use C99 // comments\n" . $herecurr) && - $fix) { - my $line = $fixed[$fixlinenr]; - if ($line =~ /\/\/(.*)$/) { - my $comment = trim($1); - $fixed[$fixlinenr] =~ s@\/\/(.*)$@/\* $comment \*/@; - } - } - } - # Remove C99 comments. - $line =~ s@//.*@@; - $opline =~ s@//.*@@; - -# EXPORT_SYMBOL should immediately follow the thing it is exporting, consider -# the whole statement. -#print "APW <$lines[$realline_next - 1]>\n"; - if (defined $realline_next && - exists $lines[$realline_next - 1] && - !defined $suppress_export{$realline_next} && - ($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/ || - $lines[$realline_next - 1] =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) { - # Handle definitions which produce identifiers with - # a prefix: - # XXX(foo); - # EXPORT_SYMBOL(something_foo); - my $name = $1; - if ($stat =~ /^(?:.\s*}\s*\n)?.([A-Z_]+)\s*\(\s*($Ident)/ && - $name =~ /^${Ident}_$2/) { -#print "FOO C name<$name>\n"; - $suppress_export{$realline_next} = 1; - - } elsif ($stat !~ /(?: - \n.}\s*$| - ^.DEFINE_$Ident\(\Q$name\E\)| - ^.DECLARE_$Ident\(\Q$name\E\)| - ^.LIST_HEAD\(\Q$name\E\)| - ^.(?:$Storage\s+)?$Type\s*\(\s*\*\s*\Q$name\E\s*\)\s*\(| - \b\Q$name\E(?:\s+$Attribute)*\s*(?:;|=|\[|\() - )/x) { -#print "FOO A<$lines[$realline_next - 1]> stat<$stat> name<$name>\n"; - $suppress_export{$realline_next} = 2; - } else { - $suppress_export{$realline_next} = 1; - } - } - if (!defined $suppress_export{$linenr} && - $prevline =~ /^.\s*$/ && - ($line =~ /EXPORT_SYMBOL.*\((.*)\)/ || - $line =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) { -#print "FOO B <$lines[$linenr - 1]>\n"; - $suppress_export{$linenr} = 2; - } - if (defined $suppress_export{$linenr} && - $suppress_export{$linenr} == 2) { - WARN("EXPORT_SYMBOL", - "EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr); - } - -# check for global initialisers. - if ($line =~ /^\+$Type\s*$Ident(?:\s+$Modifier)*\s*=\s*($zero_initializer)\s*;/) { - if (ERROR("GLOBAL_INITIALISERS", - "do not initialise globals to $1\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/(^.$Type\s*$Ident(?:\s+$Modifier)*)\s*=\s*$zero_initializer\s*;/$1;/; - } - } -# check for static initialisers. - if ($line =~ /^\+.*\bstatic\s.*=\s*($zero_initializer)\s*;/) { - if (ERROR("INITIALISED_STATIC", - "do not initialise statics to $1\n" . - $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/(\bstatic\s.*?)\s*=\s*$zero_initializer\s*;/$1;/; - } - } - -# check for misordered declarations of char/short/int/long with signed/unsigned - while ($sline =~ m{(\b$TypeMisordered\b)}g) { - my $tmp = trim($1); - WARN("MISORDERED_TYPE", - "type '$tmp' should be specified in [[un]signed] [short|int|long|long long] order\n" . $herecurr); - } - -# check for static const char * arrays. - if ($line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/) { - WARN("STATIC_CONST_CHAR_ARRAY", - "static const char * array should probably be static const char * const\n" . - $herecurr); - } - -# check for static char foo[] = "bar" declarations. - if ($line =~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=\s*"/) { - WARN("STATIC_CONST_CHAR_ARRAY", - "static char array declaration should probably be static const char\n" . - $herecurr); - } - -# check for const <foo> const where <foo> is not a pointer or array type - if ($sline =~ /\bconst\s+($BasicType)\s+const\b/) { - my $found = $1; - if ($sline =~ /\bconst\s+\Q$found\E\s+const\b\s*\*/) { - WARN("CONST_CONST", - "'const $found const *' should probably be 'const $found * const'\n" . $herecurr); - } elsif ($sline !~ /\bconst\s+\Q$found\E\s+const\s+\w+\s*\[/) { - WARN("CONST_CONST", - "'const $found const' should probably be 'const $found'\n" . $herecurr); - } - } - -# check for non-global char *foo[] = {"bar", ...} declarations. - if ($line =~ /^.\s+(?:static\s+|const\s+)?char\s+\*\s*\w+\s*\[\s*\]\s*=\s*\{/) { - WARN("STATIC_CONST_CHAR_ARRAY", - "char * array declaration might be better as static const\n" . - $herecurr); - } - -# check for sizeof(foo)/sizeof(foo[0]) that could be ARRAY_SIZE(foo) - if ($line =~ m@\bsizeof\s*\(\s*($Lval)\s*\)@) { - my $array = $1; - if ($line =~ m@\b(sizeof\s*\(\s*\Q$array\E\s*\)\s*/\s*sizeof\s*\(\s*\Q$array\E\s*\[\s*0\s*\]\s*\))@) { - my $array_div = $1; - if (WARN("ARRAY_SIZE", - "Prefer ARRAY_SIZE($array)\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\Q$array_div\E/ARRAY_SIZE($array)/; - } - } - } - -# check for function declarations without arguments like "int foo()" - if ($line =~ /(\b$Type\s+$Ident)\s*\(\s*\)/) { - if (ERROR("FUNCTION_WITHOUT_ARGS", - "Bad function definition - $1() should probably be $1(void)\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/(\b($Type)\s+($Ident))\s*\(\s*\)/$2 $3(void)/; - } - } - -# check for uses of DEFINE_PCI_DEVICE_TABLE - if ($line =~ /\bDEFINE_PCI_DEVICE_TABLE\s*\(\s*(\w+)\s*\)\s*=/) { - if (WARN("DEFINE_PCI_DEVICE_TABLE", - "Prefer struct pci_device_id over deprecated DEFINE_PCI_DEVICE_TABLE\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b(?:static\s+|)DEFINE_PCI_DEVICE_TABLE\s*\(\s*(\w+)\s*\)\s*=\s*/static const struct pci_device_id $1\[\] = /; - } - } - -# check for new typedefs, only function parameters and sparse annotations -# make sense. - if ($line =~ /\btypedef\s/ && - $line !~ /\btypedef\s+$Type\s*\(\s*\*?$Ident\s*\)\s*\(/ && - $line !~ /\btypedef\s+$Type\s+$Ident\s*\(/ && - $line !~ /\b$typeTypedefs\b/ && - $line !~ /\b__bitwise(?:__|)\b/) { - WARN("NEW_TYPEDEFS", - "do not add new typedefs\n" . $herecurr); - } - -# * goes on variable not on type - # (char*[ const]) - while ($line =~ m{(\($NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)\))}g) { - #print "AA<$1>\n"; - my ($ident, $from, $to) = ($1, $2, $2); - - # Should start with a space. - $to =~ s/^(\S)/ $1/; - # Should not end with a space. - $to =~ s/\s+$//; - # '*'s should not have spaces between. - while ($to =~ s/\*\s+\*/\*\*/) { - } - -## print "1: from<$from> to<$to> ident<$ident>\n"; - if ($from ne $to) { - if (ERROR("POINTER_LOCATION", - "\"(foo$from)\" should be \"(foo$to)\"\n" . $herecurr) && - $fix) { - my $sub_from = $ident; - my $sub_to = $ident; - $sub_to =~ s/\Q$from\E/$to/; - $fixed[$fixlinenr] =~ - s@\Q$sub_from\E@$sub_to@; - } - } - } - while ($line =~ m{(\b$NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)($Ident))}g) { - #print "BB<$1>\n"; - my ($match, $from, $to, $ident) = ($1, $2, $2, $3); - - # Should start with a space. - $to =~ s/^(\S)/ $1/; - # Should not end with a space. - $to =~ s/\s+$//; - # '*'s should not have spaces between. - while ($to =~ s/\*\s+\*/\*\*/) { - } - # Modifiers should have spaces. - $to =~ s/(\b$Modifier$)/$1 /; - -## print "2: from<$from> to<$to> ident<$ident>\n"; - if ($from ne $to && $ident !~ /^$Modifier$/) { - if (ERROR("POINTER_LOCATION", - "\"foo${from}bar\" should be \"foo${to}bar\"\n" . $herecurr) && - $fix) { - - my $sub_from = $match; - my $sub_to = $match; - $sub_to =~ s/\Q$from\E/$to/; - $fixed[$fixlinenr] =~ - s@\Q$sub_from\E@$sub_to@; - } - } - } - -# avoid BUG() or BUG_ON() - if ($line =~ /\b(?:BUG|BUG_ON)\b/) { - my $msg_type = \&WARN; - $msg_type = \&CHK if ($file); - &{$msg_type}("AVOID_BUG", - "Avoid crashing the kernel - try using WARN_ON & recovery code rather than BUG() or BUG_ON()\n" . $herecurr); - } - -# avoid LINUX_VERSION_CODE - if ($line =~ /\bLINUX_VERSION_CODE\b/) { - WARN("LINUX_VERSION_CODE", - "LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged\n" . $herecurr); - } - -# check for uses of printk_ratelimit - if ($line =~ /\bprintk_ratelimit\s*\(/) { - WARN("PRINTK_RATELIMITED", - "Prefer printk_ratelimited or pr_<level>_ratelimited to printk_ratelimit\n" . $herecurr); - } - -# printk should use KERN_* levels. Note that follow on printk's on the -# same line do not need a level, so we use the current block context -# to try and find and validate the current printk. In summary the current -# printk includes all preceding printk's which have no newline on the end. -# we assume the first bad printk is the one to report. - if ($line =~ /\bprintk\((?!KERN_)\s*"/) { - my $ok = 0; - for (my $ln = $linenr - 1; $ln >= $first_line; $ln--) { - #print "CHECK<$lines[$ln - 1]\n"; - # we have a preceding printk if it ends - # with "\n" ignore it, else it is to blame - if ($lines[$ln - 1] =~ m{\bprintk\(}) { - if ($rawlines[$ln - 1] !~ m{\\n"}) { - $ok = 1; - } - last; - } - } - if ($ok == 0) { - WARN("PRINTK_WITHOUT_KERN_LEVEL", - "printk() should include KERN_ facility level\n" . $herecurr); - } - } - - if ($line =~ /\bprintk\s*\(\s*KERN_([A-Z]+)/) { - my $orig = $1; - my $level = lc($orig); - $level = "warn" if ($level eq "warning"); - my $level2 = $level; - $level2 = "dbg" if ($level eq "debug"); - WARN("PREFER_PR_LEVEL", - "Prefer [subsystem eg: netdev]_$level2([subsystem]dev, ... then dev_$level2(dev, ... then pr_$level(... to printk(KERN_$orig ...\n" . $herecurr); - } - - if ($line =~ /\bpr_warning\s*\(/) { - if (WARN("PREFER_PR_LEVEL", - "Prefer pr_warn(... to pr_warning(...\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/\bpr_warning\b/pr_warn/; - } - } - - if ($line =~ /\bdev_printk\s*\(\s*KERN_([A-Z]+)/) { - my $orig = $1; - my $level = lc($orig); - $level = "warn" if ($level eq "warning"); - $level = "dbg" if ($level eq "debug"); - WARN("PREFER_DEV_LEVEL", - "Prefer dev_$level(... to dev_printk(KERN_$orig, ...\n" . $herecurr); - } - -# ENOSYS means "bad syscall nr" and nothing else. This will have a small -# number of false positives, but assembly files are not checked, so at -# least the arch entry code will not trigger this warning. - if ($line =~ /\bENOSYS\b/) { - WARN("ENOSYS", - "ENOSYS means 'invalid syscall nr' and nothing else\n" . $herecurr); - } - -# function brace can't be on same line, except for #defines of do while, -# or if closed on same line - if (($line=~/$Type\s*$Ident\(.*\).*\s*{/) and - !($line=~/\#\s*define.*do\s\{/) and !($line=~/}/)) { - if (ERROR("OPEN_BRACE", - "open brace '{' following function declarations go on the next line\n" . $herecurr) && - $fix) { - fix_delete_line($fixlinenr, $rawline); - my $fixed_line = $rawline; - $fixed_line =~ /(^..*$Type\s*$Ident\(.*\)\s*){(.*)$/; - my $line1 = $1; - my $line2 = $2; - fix_insert_line($fixlinenr, ltrim($line1)); - fix_insert_line($fixlinenr, "\+{"); - if ($line2 !~ /^\s*$/) { - fix_insert_line($fixlinenr, "\+\t" . trim($line2)); - } - } - } - -# open braces for enum, union and struct go on the same line. - if ($line =~ /^.\s*{/ && - $prevline =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?\s*$/) { - if (ERROR("OPEN_BRACE", - "open brace '{' following $1 go on the same line\n" . $hereprev) && - $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { - fix_delete_line($fixlinenr - 1, $prevrawline); - fix_delete_line($fixlinenr, $rawline); - my $fixedline = rtrim($prevrawline) . " {"; - fix_insert_line($fixlinenr, $fixedline); - $fixedline = $rawline; - $fixedline =~ s/^(.\s*){\s*/$1\t/; - if ($fixedline !~ /^\+\s*$/) { - fix_insert_line($fixlinenr, $fixedline); - } - } - } - -# missing space after union, struct or enum definition - if ($line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident){1,2}[=\{]/) { - if (WARN("SPACING", - "missing space after $1 definition\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/^(.\s*(?:typedef\s+)?(?:enum|union|struct)(?:\s+$Ident){1,2})([=\{])/$1 $2/; - } - } - -# Function pointer declarations -# check spacing between type, funcptr, and args -# canonical declaration is "type (*funcptr)(args...)" - if ($line =~ /^.\s*($Declare)\((\s*)\*(\s*)($Ident)(\s*)\)(\s*)\(/) { - my $declare = $1; - my $pre_pointer_space = $2; - my $post_pointer_space = $3; - my $funcname = $4; - my $post_funcname_space = $5; - my $pre_args_space = $6; - -# the $Declare variable will capture all spaces after the type -# so check it for a missing trailing missing space but pointer return types -# don't need a space so don't warn for those. - my $post_declare_space = ""; - if ($declare =~ /(\s+)$/) { - $post_declare_space = $1; - $declare = rtrim($declare); - } - if ($declare !~ /\*$/ && $post_declare_space =~ /^$/) { - WARN("SPACING", - "missing space after return type\n" . $herecurr); - $post_declare_space = " "; - } - -# unnecessary space "type (*funcptr)(args...)" -# This test is not currently implemented because these declarations are -# equivalent to -# int foo(int bar, ...) -# and this is form shouldn't/doesn't generate a checkpatch warning. -# -# elsif ($declare =~ /\s{2,}$/) { -# WARN("SPACING", -# "Multiple spaces after return type\n" . $herecurr); -# } - -# unnecessary space "type ( *funcptr)(args...)" - if (defined $pre_pointer_space && - $pre_pointer_space =~ /^\s/) { - WARN("SPACING", - "Unnecessary space after function pointer open parenthesis\n" . $herecurr); - } - -# unnecessary space "type (* funcptr)(args...)" - if (defined $post_pointer_space && - $post_pointer_space =~ /^\s/) { - WARN("SPACING", - "Unnecessary space before function pointer name\n" . $herecurr); - } - -# unnecessary space "type (*funcptr )(args...)" - if (defined $post_funcname_space && - $post_funcname_space =~ /^\s/) { - WARN("SPACING", - "Unnecessary space after function pointer name\n" . $herecurr); - } - -# unnecessary space "type (*funcptr) (args...)" - if (defined $pre_args_space && - $pre_args_space =~ /^\s/) { - WARN("SPACING", - "Unnecessary space before function pointer arguments\n" . $herecurr); - } - - if (show_type("SPACING") && $fix) { - $fixed[$fixlinenr] =~ - s/^(.\s*)$Declare\s*\(\s*\*\s*$Ident\s*\)\s*\(/$1 . $declare . $post_declare_space . '(*' . $funcname . ')('/ex; - } - } - -# check for spacing round square brackets; allowed: -# 1. with a type on the left -- int [] a; -# 2. at the beginning of a line for slice initialisers -- [0...10] = 5, -# 3. inside a curly brace -- = { [0...10] = 5 } - while ($line =~ /(.*?\s)\[/g) { - my ($where, $prefix) = ($-[1], $1); - if ($prefix !~ /$Type\s+$/ && - ($where != 0 || $prefix !~ /^.\s+$/) && - $prefix !~ /[{,]\s+$/) { - if (ERROR("BRACKET_SPACE", - "space prohibited before open square bracket '['\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/^(\+.*?)\s+\[/$1\[/; - } - } - } - -# check for spaces between functions and their parentheses. - while ($line =~ /($Ident)\s+\(/g) { - my $name = $1; - my $ctx_before = substr($line, 0, $-[1]); - my $ctx = "$ctx_before$name"; - - # Ignore those directives where spaces _are_ permitted. - if ($name =~ /^(?: - if|for|while|switch|return|case| - volatile|__volatile__| - __attribute__|format|__extension__| - asm|__asm__)$/x) - { - # cpp #define statements have non-optional spaces, ie - # if there is a space between the name and the open - # parenthesis it is simply not a parameter group. - } elsif ($ctx_before =~ /^.\s*\#\s*define\s*$/) { - - # cpp #elif statement condition may start with a ( - } elsif ($ctx =~ /^.\s*\#\s*elif\s*$/) { - - # If this whole things ends with a type its most - # likely a typedef for a function. - } elsif ($ctx =~ /$Type$/) { - - } else { - if (WARN("SPACING", - "space prohibited between function name and open parenthesis '('\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/\b$name\s+\(/$name\(/; - } - } - } - -# Check operator spacing. - if (!($line=~/\#\s*include/)) { - my $fixed_line = ""; - my $line_fixed = 0; - - my $ops = qr{ - <<=|>>=|<=|>=|==|!=| - \+=|-=|\*=|\/=|%=|\^=|\|=|&=| - =>|->|<<|>>|<|>|=|!|~| - &&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%| - \?:|\?|: - }x; - my @elements = split(/($ops|;)/, $opline); - -## print("element count: <" . $#elements . ">\n"); -## foreach my $el (@elements) { -## print("el: <$el>\n"); -## } - - my @fix_elements = (); - my $off = 0; - - foreach my $el (@elements) { - push(@fix_elements, substr($rawline, $off, length($el))); - $off += length($el); - } - - $off = 0; - - my $blank = copy_spacing($opline); - my $last_after = -1; - - for (my $n = 0; $n < $#elements; $n += 2) { - - my $good = $fix_elements[$n] . $fix_elements[$n + 1]; - -## print("n: <$n> good: <$good>\n"); - - $off += length($elements[$n]); - - # Pick up the preceding and succeeding characters. - my $ca = substr($opline, 0, $off); - my $cc = ''; - if (length($opline) >= ($off + length($elements[$n + 1]))) { - $cc = substr($opline, $off + length($elements[$n + 1])); - } - my $cb = "$ca$;$cc"; - - my $a = ''; - $a = 'V' if ($elements[$n] ne ''); - $a = 'W' if ($elements[$n] =~ /\s$/); - $a = 'C' if ($elements[$n] =~ /$;$/); - $a = 'B' if ($elements[$n] =~ /(\[|\()$/); - $a = 'O' if ($elements[$n] eq ''); - $a = 'E' if ($ca =~ /^\s*$/); - - my $op = $elements[$n + 1]; - - my $c = ''; - if (defined $elements[$n + 2]) { - $c = 'V' if ($elements[$n + 2] ne ''); - $c = 'W' if ($elements[$n + 2] =~ /^\s/); - $c = 'C' if ($elements[$n + 2] =~ /^$;/); - $c = 'B' if ($elements[$n + 2] =~ /^(\)|\]|;)/); - $c = 'O' if ($elements[$n + 2] eq ''); - $c = 'E' if ($elements[$n + 2] =~ /^\s*\\$/); - } else { - $c = 'E'; - } - - my $ctx = "${a}x${c}"; - - my $at = "(ctx:$ctx)"; - - my $ptr = substr($blank, 0, $off) . "^"; - my $hereptr = "$hereline$ptr\n"; - - # Pull out the value of this operator. - my $op_type = substr($curr_values, $off + 1, 1); - - # Get the full operator variant. - my $opv = $op . substr($curr_vars, $off, 1); - - # Ignore operators passed as parameters. - if ($op_type ne 'V' && - $ca =~ /\s$/ && $cc =~ /^\s*[,\)]/) { - -# # Ignore comments -# } elsif ($op =~ /^$;+$/) { - - # ; should have either the end of line or a space or \ after it - } elsif ($op eq ';') { - if ($ctx !~ /.x[WEBC]/ && - $cc !~ /^\\/ && $cc !~ /^;/) { - if (ERROR("SPACING", - "space required after that '$op' $at\n" . $hereptr)) { - $good = $fix_elements[$n] . trim($fix_elements[$n + 1]) . " "; - $line_fixed = 1; - } - } - - # // is a comment - } elsif ($op eq '//') { - - # : when part of a bitfield - } elsif ($opv eq ':B') { - # skip the bitfield test for now - - # No spaces for: - # -> - } elsif ($op eq '->') { - if ($ctx =~ /Wx.|.xW/) { - if (ERROR("SPACING", - "spaces prohibited around that '$op' $at\n" . $hereptr)) { - $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); - if (defined $fix_elements[$n + 2]) { - $fix_elements[$n + 2] =~ s/^\s+//; - } - $line_fixed = 1; - } - } - - # , must not have a space before and must have a space on the right. - } elsif ($op eq ',') { - my $rtrim_before = 0; - my $space_after = 0; - if ($ctx =~ /Wx./) { - if (ERROR("SPACING", - "space prohibited before that '$op' $at\n" . $hereptr)) { - $line_fixed = 1; - $rtrim_before = 1; - } - } - if ($ctx !~ /.x[WEC]/ && $cc !~ /^}/) { - if (ERROR("SPACING", - "space required after that '$op' $at\n" . $hereptr)) { - $line_fixed = 1; - $last_after = $n; - $space_after = 1; - } - } - if ($rtrim_before || $space_after) { - if ($rtrim_before) { - $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); - } else { - $good = $fix_elements[$n] . trim($fix_elements[$n + 1]); - } - if ($space_after) { - $good .= " "; - } - } - - # '*' as part of a type definition -- reported already. - } elsif ($opv eq '*_') { - #warn "'*' is part of type\n"; - - # unary operators should have a space before and - # none after. May be left adjacent to another - # unary operator, or a cast - } elsif ($op eq '!' || $op eq '~' || - $opv eq '*U' || $opv eq '-U' || - $opv eq '&U' || $opv eq '&&U') { - if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) { - if (ERROR("SPACING", - "space required before that '$op' $at\n" . $hereptr)) { - if ($n != $last_after + 2) { - $good = $fix_elements[$n] . " " . ltrim($fix_elements[$n + 1]); - $line_fixed = 1; - } - } - } - if ($op eq '*' && $cc =~/\s*$Modifier\b/) { - # A unary '*' may be const - - } elsif ($ctx =~ /.xW/) { - if (ERROR("SPACING", - "space prohibited after that '$op' $at\n" . $hereptr)) { - $good = $fix_elements[$n] . rtrim($fix_elements[$n + 1]); - if (defined $fix_elements[$n + 2]) { - $fix_elements[$n + 2] =~ s/^\s+//; - } - $line_fixed = 1; - } - } - - # unary ++ and unary -- are allowed no space on one side. - } elsif ($op eq '++' or $op eq '--') { - if ($ctx !~ /[WEOBC]x[^W]/ && $ctx !~ /[^W]x[WOBEC]/) { - if (ERROR("SPACING", - "space required one side of that '$op' $at\n" . $hereptr)) { - $good = $fix_elements[$n] . trim($fix_elements[$n + 1]) . " "; - $line_fixed = 1; - } - } - if ($ctx =~ /Wx[BE]/ || - ($ctx =~ /Wx./ && $cc =~ /^;/)) { - if (ERROR("SPACING", - "space prohibited before that '$op' $at\n" . $hereptr)) { - $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); - $line_fixed = 1; - } - } - if ($ctx =~ /ExW/) { - if (ERROR("SPACING", - "space prohibited after that '$op' $at\n" . $hereptr)) { - $good = $fix_elements[$n] . trim($fix_elements[$n + 1]); - if (defined $fix_elements[$n + 2]) { - $fix_elements[$n + 2] =~ s/^\s+//; - } - $line_fixed = 1; - } - } - - # << and >> may either have or not have spaces both sides - } elsif ($op eq '<<' or $op eq '>>' or - $op eq '&' or $op eq '^' or $op eq '|' or - $op eq '+' or $op eq '-' or - $op eq '*' or $op eq '/' or - $op eq '%') - { - if ($check) { - if (defined $fix_elements[$n + 2] && $ctx !~ /[EW]x[EW]/) { - if (CHK("SPACING", - "spaces preferred around that '$op' $at\n" . $hereptr)) { - $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " "; - $fix_elements[$n + 2] =~ s/^\s+//; - $line_fixed = 1; - } - } elsif (!defined $fix_elements[$n + 2] && $ctx !~ /Wx[OE]/) { - if (CHK("SPACING", - "space preferred before that '$op' $at\n" . $hereptr)) { - $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]); - $line_fixed = 1; - } - } - } elsif ($ctx =~ /Wx[^WCE]|[^WCE]xW/) { - if (ERROR("SPACING", - "need consistent spacing around '$op' $at\n" . $hereptr)) { - $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " "; - if (defined $fix_elements[$n + 2]) { - $fix_elements[$n + 2] =~ s/^\s+//; - } - $line_fixed = 1; - } - } - - # A colon needs no spaces before when it is - # terminating a case value or a label. - } elsif ($opv eq ':C' || $opv eq ':L') { - if ($ctx =~ /Wx./) { - if (ERROR("SPACING", - "space prohibited before that '$op' $at\n" . $hereptr)) { - $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); - $line_fixed = 1; - } - } - - # All the others need spaces both sides. - } elsif ($ctx !~ /[EWC]x[CWE]/) { - my $ok = 0; - - # Ignore email addresses <foo@bar> - if (($op eq '<' && - $cc =~ /^\S+\@\S+>/) || - ($op eq '>' && - $ca =~ /<\S+\@\S+$/)) - { - $ok = 1; - } - - # for asm volatile statements - # ignore a colon with another - # colon immediately before or after - if (($op eq ':') && - ($ca =~ /:$/ || $cc =~ /^:/)) { - $ok = 1; - } - - # messages are ERROR, but ?: are CHK - if ($ok == 0) { - my $msg_type = \&ERROR; - $msg_type = \&CHK if (($op eq '?:' || $op eq '?' || $op eq ':') && $ctx =~ /VxV/); - - if (&{$msg_type}("SPACING", - "spaces required around that '$op' $at\n" . $hereptr)) { - $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " "; - if (defined $fix_elements[$n + 2]) { - $fix_elements[$n + 2] =~ s/^\s+//; - } - $line_fixed = 1; - } - } - } - $off += length($elements[$n + 1]); - -## print("n: <$n> GOOD: <$good>\n"); - - $fixed_line = $fixed_line . $good; - } - - if (($#elements % 2) == 0) { - $fixed_line = $fixed_line . $fix_elements[$#elements]; - } - - if ($fix && $line_fixed && $fixed_line ne $fixed[$fixlinenr]) { - $fixed[$fixlinenr] = $fixed_line; - } - - - } - -# check for whitespace before a non-naked semicolon - if ($line =~ /^\+.*\S\s+;\s*$/) { - if (WARN("SPACING", - "space prohibited before semicolon\n" . $herecurr) && - $fix) { - 1 while $fixed[$fixlinenr] =~ - s/^(\+.*\S)\s+;/$1;/; - } - } - -# check for multiple assignments - if ($line =~ /^.\s*$Lval\s*=\s*$Lval\s*=(?!=)/) { - CHK("MULTIPLE_ASSIGNMENTS", - "multiple assignments should be avoided\n" . $herecurr); - } - -## # check for multiple declarations, allowing for a function declaration -## # continuation. -## if ($line =~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Ident.*/ && -## $line !~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Type\s*$Ident.*/) { -## -## # Remove any bracketed sections to ensure we do not -## # falsly report the parameters of functions. -## my $ln = $line; -## while ($ln =~ s/\([^\(\)]*\)//g) { -## } -## if ($ln =~ /,/) { -## WARN("MULTIPLE_DECLARATION", -## "declaring multiple variables together should be avoided\n" . $herecurr); -## } -## } - -#need space before brace following if, while, etc - if (($line =~ /\(.*\)\{/ && $line !~ /\($Type\)\{/) || - $line =~ /do\{/) { - if (ERROR("SPACING", - "space required before the open brace '{'\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/^(\+.*(?:do|\))){/$1 {/; - } - } - -## # check for blank lines before declarations -## if ($line =~ /^.\t+$Type\s+$Ident(?:\s*=.*)?;/ && -## $prevrawline =~ /^.\s*$/) { -## WARN("SPACING", -## "No blank lines before declarations\n" . $hereprev); -## } -## - -# closing brace should have a space following it when it has anything -# on the line - if ($line =~ /}(?!(?:,|;|\)))\S/) { - if (ERROR("SPACING", - "space required after that close brace '}'\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/}((?!(?:,|;|\)))\S)/} $1/; - } - } - -# check spacing on square brackets - if ($line =~ /\[\s/ && $line !~ /\[\s*$/) { - if (ERROR("SPACING", - "space prohibited after that open square bracket '['\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/\[\s+/\[/; - } - } - if ($line =~ /\s\]/) { - if (ERROR("SPACING", - "space prohibited before that close square bracket ']'\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/\s+\]/\]/; - } - } - -# check spacing on parentheses - if ($line =~ /\(\s/ && $line !~ /\(\s*(?:\\)?$/ && - $line !~ /for\s*\(\s+;/) { - if (ERROR("SPACING", - "space prohibited after that open parenthesis '('\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/\(\s+/\(/; - } - } - if ($line =~ /(\s+)\)/ && $line !~ /^.\s*\)/ && - $line !~ /for\s*\(.*;\s+\)/ && - $line !~ /:\s+\)/) { - if (ERROR("SPACING", - "space prohibited before that close parenthesis ')'\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/\s+\)/\)/; - } - } - -# check unnecessary parentheses around addressof/dereference single $Lvals -# ie: &(foo->bar) should be &foo->bar and *(foo->bar) should be *foo->bar - - while ($line =~ /(?:[^&]&\s*|\*)\(\s*($Ident\s*(?:$Member\s*)+)\s*\)/g) { - my $var = $1; - if (CHK("UNNECESSARY_PARENTHESES", - "Unnecessary parentheses around $var\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\(\s*\Q$var\E\s*\)/$var/; - } - } - -# check for unnecessary parentheses around function pointer uses -# ie: (foo->bar)(); should be foo->bar(); -# but not "if (foo->bar) (" to avoid some false positives - if ($line =~ /(\bif\s*|)(\(\s*$Ident\s*(?:$Member\s*)+\))[ \t]*\(/ && $1 !~ /^if/) { - my $var = $2; - if (CHK("UNNECESSARY_PARENTHESES", - "Unnecessary parentheses around function pointer $var\n" . $herecurr) && - $fix) { - my $var2 = deparenthesize($var); - $var2 =~ s/\s//g; - $fixed[$fixlinenr] =~ s/\Q$var\E/$var2/; - } - } - -#goto labels aren't indented, allow a single space however - if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and - !($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) { - if (WARN("INDENTED_LABEL", - "labels should not be indented\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/^(.)\s+/$1/; - } - } - -# return is not a function - if (defined($stat) && $stat =~ /^.\s*return(\s*)\(/s) { - my $spacing = $1; - if ($^V && $^V ge 5.10.0 && - $stat =~ /^.\s*return\s*($balanced_parens)\s*;\s*$/) { - my $value = $1; - $value = deparenthesize($value); - if ($value =~ m/^\s*$FuncArg\s*(?:\?|$)/) { - ERROR("RETURN_PARENTHESES", - "return is not a function, parentheses are not required\n" . $herecurr); - } - } elsif ($spacing !~ /\s+/) { - ERROR("SPACING", - "space required before the open parenthesis '('\n" . $herecurr); - } - } - -# unnecessary return in a void function -# at end-of-function, with the previous line a single leading tab, then return; -# and the line before that not a goto label target like "out:" - if ($sline =~ /^[ \+]}\s*$/ && - $prevline =~ /^\+\treturn\s*;\s*$/ && - $linenr >= 3 && - $lines[$linenr - 3] =~ /^[ +]/ && - $lines[$linenr - 3] !~ /^[ +]\s*$Ident\s*:/) { - WARN("RETURN_VOID", - "void function return statements are not generally useful\n" . $hereprev); - } - -# if statements using unnecessary parentheses - ie: if ((foo == bar)) - if ($^V && $^V ge 5.10.0 && - $line =~ /\bif\s*((?:\(\s*){2,})/) { - my $openparens = $1; - my $count = $openparens =~ tr@\(@\(@; - my $msg = ""; - if ($line =~ /\bif\s*(?:\(\s*){$count,$count}$LvalOrFunc\s*($Compare)\s*$LvalOrFunc(?:\s*\)){$count,$count}/) { - my $comp = $4; #Not $1 because of $LvalOrFunc - $msg = " - maybe == should be = ?" if ($comp eq "=="); - WARN("UNNECESSARY_PARENTHESES", - "Unnecessary parentheses$msg\n" . $herecurr); - } - } - -# comparisons with a constant or upper case identifier on the left -# avoid cases like "foo + BAR < baz" -# only fix matches surrounded by parentheses to avoid incorrect -# conversions like "FOO < baz() + 5" being "misfixed" to "baz() > FOO + 5" - if ($^V && $^V ge 5.10.0 && - $line =~ /^\+(.*)\b($Constant|[A-Z_][A-Z0-9_]*)\s*($Compare)\s*($LvalOrFunc)/) { - my $lead = $1; - my $const = $2; - my $comp = $3; - my $to = $4; - my $newcomp = $comp; - if ($lead !~ /$Operators\s*$/ && - $to !~ /^(?:Constant|[A-Z_][A-Z0-9_]*)$/ && - WARN("CONSTANT_COMPARISON", - "Comparisons should place the constant on the right side of the test\n" . $herecurr) && - $fix) { - if ($comp eq "<") { - $newcomp = ">"; - } elsif ($comp eq "<=") { - $newcomp = ">="; - } elsif ($comp eq ">") { - $newcomp = "<"; - } elsif ($comp eq ">=") { - $newcomp = "<="; - } - $fixed[$fixlinenr] =~ s/\(\s*\Q$const\E\s*$Compare\s*\Q$to\E\s*\)/($to $newcomp $const)/; - } - } - -# Return of what appears to be an errno should normally be negative - if ($sline =~ /\breturn(?:\s*\(+\s*|\s+)(E[A-Z]+)(?:\s*\)+\s*|\s*)[;:,]/) { - my $name = $1; - if ($name ne 'EOF' && $name ne 'ERROR') { - WARN("USE_NEGATIVE_ERRNO", - "return of an errno should typically be negative (ie: return -$1)\n" . $herecurr); - } - } - -# Need a space before open parenthesis after if, while etc - if ($line =~ /\b(if|while|for|switch)\(/) { - if (ERROR("SPACING", - "space required before the open parenthesis '('\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/\b(if|while|for|switch)\(/$1 \(/; - } - } - -# Check for illegal assignment in if conditional -- and check for trailing -# statements after the conditional. - if ($line =~ /do\s*(?!{)/) { - ($stat, $cond, $line_nr_next, $remain_next, $off_next) = - ctx_statement_block($linenr, $realcnt, 0) - if (!defined $stat); - my ($stat_next) = ctx_statement_block($line_nr_next, - $remain_next, $off_next); - $stat_next =~ s/\n./\n /g; - ##print "stat<$stat> stat_next<$stat_next>\n"; - - if ($stat_next =~ /^\s*while\b/) { - # If the statement carries leading newlines, - # then count those as offsets. - my ($whitespace) = - ($stat_next =~ /^((?:\s*\n[+-])*\s*)/s); - my $offset = - statement_rawlines($whitespace) - 1; - - $suppress_whiletrailers{$line_nr_next + - $offset} = 1; - } - } - if (!defined $suppress_whiletrailers{$linenr} && - defined($stat) && defined($cond) && - $line =~ /\b(?:if|while|for)\s*\(/ && $line !~ /^.\s*#/) { - my ($s, $c) = ($stat, $cond); - - if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/s) { - ERROR("ASSIGN_IN_IF", - "do not use assignment in if condition\n" . $herecurr); - } - - # Find out what is on the end of the line after the - # conditional. - substr($s, 0, length($c), ''); - $s =~ s/\n.*//g; - $s =~ s/$;//g; # Remove any comments - if (length($c) && $s !~ /^\s*{?\s*\\*\s*$/ && - $c !~ /}\s*while\s*/) - { - # Find out how long the conditional actually is. - my @newlines = ($c =~ /\n/gs); - my $cond_lines = 1 + $#newlines; - my $stat_real = ''; - - $stat_real = raw_line($linenr, $cond_lines) - . "\n" if ($cond_lines); - if (defined($stat_real) && $cond_lines > 1) { - $stat_real = "[...]\n$stat_real"; - } - - ERROR("TRAILING_STATEMENTS", - "trailing statements should be on next line\n" . $herecurr . $stat_real); - } - } - -# Check for bitwise tests written as boolean - if ($line =~ / - (?: - (?:\[|\(|\&\&|\|\|) - \s*0[xX][0-9]+\s* - (?:\&\&|\|\|) - | - (?:\&\&|\|\|) - \s*0[xX][0-9]+\s* - (?:\&\&|\|\||\)|\]) - )/x) - { - WARN("HEXADECIMAL_BOOLEAN_TEST", - "boolean test with hexadecimal, perhaps just 1 \& or \|?\n" . $herecurr); - } - -# if and else should not have general statements after it - if ($line =~ /^.\s*(?:}\s*)?else\b(.*)/) { - my $s = $1; - $s =~ s/$;//g; # Remove any comments - if ($s !~ /^\s*(?:\sif|(?:{|)\s*\\?\s*$)/) { - ERROR("TRAILING_STATEMENTS", - "trailing statements should be on next line\n" . $herecurr); - } - } -# if should not continue a brace - if ($line =~ /}\s*if\b/) { - ERROR("TRAILING_STATEMENTS", - "trailing statements should be on next line (or did you mean 'else if'?)\n" . - $herecurr); - } -# case and default should not have general statements after them - if ($line =~ /^.\s*(?:case\s*.*|default\s*):/g && - $line !~ /\G(?: - (?:\s*$;*)(?:\s*{)?(?:\s*$;*)(?:\s*\\)?\s*$| - \s*return\s+ - )/xg) - { - ERROR("TRAILING_STATEMENTS", - "trailing statements should be on next line\n" . $herecurr); - } - - # Check for }<nl>else {, these must be at the same - # indent level to be relevant to each other. - if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ && - $previndent == $indent) { - if (ERROR("ELSE_AFTER_BRACE", - "else should follow close brace '}'\n" . $hereprev) && - $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { - fix_delete_line($fixlinenr - 1, $prevrawline); - fix_delete_line($fixlinenr, $rawline); - my $fixedline = $prevrawline; - $fixedline =~ s/}\s*$//; - if ($fixedline !~ /^\+\s*$/) { - fix_insert_line($fixlinenr, $fixedline); - } - $fixedline = $rawline; - $fixedline =~ s/^(.\s*)else/$1} else/; - fix_insert_line($fixlinenr, $fixedline); - } - } - - if ($prevline=~/}\s*$/ and $line=~/^.\s*while\s*/ && - $previndent == $indent) { - my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0); - - # Find out what is on the end of the line after the - # conditional. - substr($s, 0, length($c), ''); - $s =~ s/\n.*//g; - - if ($s =~ /^\s*;/) { - if (ERROR("WHILE_AFTER_BRACE", - "while should follow close brace '}'\n" . $hereprev) && - $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { - fix_delete_line($fixlinenr - 1, $prevrawline); - fix_delete_line($fixlinenr, $rawline); - my $fixedline = $prevrawline; - my $trailing = $rawline; - $trailing =~ s/^\+//; - $trailing = trim($trailing); - $fixedline =~ s/}\s*$/} $trailing/; - fix_insert_line($fixlinenr, $fixedline); - } - } - } - -#Specific variable tests - while ($line =~ m{($Constant|$Lval)}g) { - my $var = $1; - -#gcc binary extension - if ($var =~ /^$Binary$/) { - if (WARN("GCC_BINARY_CONSTANT", - "Avoid gcc v4.3+ binary constant extension: <$var>\n" . $herecurr) && - $fix) { - my $hexval = sprintf("0x%x", oct($var)); - $fixed[$fixlinenr] =~ - s/\b$var\b/$hexval/; - } - } - -#CamelCase - if ($var !~ /^$Constant$/ && - $var =~ /[A-Z][a-z]|[a-z][A-Z]/ && -#Ignore Page<foo> variants - $var !~ /^(?:Clear|Set|TestClear|TestSet|)Page[A-Z]/ && -#Ignore SI style variants like nS, mV and dB (ie: max_uV, regulator_min_uA_show) - $var !~ /^(?:[a-z_]*?)_?[a-z][A-Z](?:_[a-z_]+)?$/ && -#Ignore some three character SI units explicitly, like MiB and KHz - $var !~ /^(?:[a-z_]*?)_?(?:[KMGT]iB|[KMGT]?Hz)(?:_[a-z_]+)?$/) { - while ($var =~ m{($Ident)}g) { - my $word = $1; - next if ($word !~ /[A-Z][a-z]|[a-z][A-Z]/); - if ($check) { - seed_camelcase_includes(); - if (!$file && !$camelcase_file_seeded) { - seed_camelcase_file($realfile); - $camelcase_file_seeded = 1; - } - } - if (!defined $camelcase{$word}) { - $camelcase{$word} = 1; - CHK("CAMELCASE", - "Avoid CamelCase: <$word>\n" . $herecurr); - } - } - } - } - -#no spaces allowed after \ in define - if ($line =~ /\#\s*define.*\\\s+$/) { - if (WARN("WHITESPACE_AFTER_LINE_CONTINUATION", - "Whitespace after \\ makes next lines useless\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\s+$//; - } - } - -# warn if <asm/foo.h> is #included and <linux/foo.h> is available and includes -# itself <asm/foo.h> (uses RAW line) - if ($tree && $rawline =~ m{^.\s*\#\s*include\s*\<asm\/(.*)\.h\>}) { - my $file = "$1.h"; - my $checkfile = "include/linux/$file"; - if (-f "$root/$checkfile" && - $realfile ne $checkfile && - $1 !~ /$allowed_asm_includes/) - { - my $asminclude = `grep -Ec "#include\\s+<asm/$file>" $root/$checkfile`; - if ($asminclude > 0) { - if ($realfile =~ m{^arch/}) { - CHK("ARCH_INCLUDE_LINUX", - "Consider using #include <linux/$file> instead of <asm/$file>\n" . $herecurr); - } else { - WARN("INCLUDE_LINUX", - "Use #include <linux/$file> instead of <asm/$file>\n" . $herecurr); - } - } - } - } - -# multi-statement macros should be enclosed in a do while loop, grab the -# first statement and ensure its the whole macro if its not enclosed -# in a known good container - if ($realfile !~ m@/vmlinux.lds.h$@ && - $line =~ /^.\s*\#\s*define\s*$Ident(\()?/) { - my $ln = $linenr; - my $cnt = $realcnt; - my ($off, $dstat, $dcond, $rest); - my $ctx = ''; - my $has_flow_statement = 0; - my $has_arg_concat = 0; - ($dstat, $dcond, $ln, $cnt, $off) = - ctx_statement_block($linenr, $realcnt, 0); - $ctx = $dstat; - #print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n"; - #print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n"; - - $has_flow_statement = 1 if ($ctx =~ /\b(goto|return)\b/); - $has_arg_concat = 1 if ($ctx =~ /\#\#/ && $ctx !~ /\#\#\s*(?:__VA_ARGS__|args)\b/); - - $dstat =~ s/^.\s*\#\s*define\s+$Ident(?:\([^\)]*\))?\s*//; - $dstat =~ s/$;//g; - $dstat =~ s/\\\n.//g; - $dstat =~ s/^\s*//s; - $dstat =~ s/\s*$//s; - - # Flatten any parentheses and braces - while ($dstat =~ s/\([^\(\)]*\)/1/ || - $dstat =~ s/\{[^\{\}]*\}/1/ || - $dstat =~ s/.\[[^\[\]]*\]/1/) - { - } - - # Flatten any obvious string concatentation. - while ($dstat =~ s/($String)\s*$Ident/$1/ || - $dstat =~ s/$Ident\s*($String)/$1/) - { - } - - # Make asm volatile uses seem like a generic function - $dstat =~ s/\b_*asm_*\s+_*volatile_*\b/asm_volatile/g; - - my $exceptions = qr{ - $Declare| - module_param_named| - MODULE_PARM_DESC| - DECLARE_PER_CPU| - DEFINE_PER_CPU| - __typeof__\(| - union| - struct| - \.$Ident\s*=\s*| - ^\"|\"$| - ^\[ - }x; - #print "REST<$rest> dstat<$dstat> ctx<$ctx>\n"; - if ($dstat ne '' && - $dstat !~ /^(?:$Ident|-?$Constant),$/ && # 10, // foo(), - $dstat !~ /^(?:$Ident|-?$Constant);$/ && # foo(); - $dstat !~ /^[!~-]?(?:$Lval|$Constant)$/ && # 10 // foo() // !foo // ~foo // -foo // foo->bar // foo.bar->baz - $dstat !~ /^'X'$/ && $dstat !~ /^'XX'$/ && # character constants - $dstat !~ /$exceptions/ && - $dstat !~ /^\.$Ident\s*=/ && # .foo = - $dstat !~ /^(?:\#\s*$Ident|\#\s*$Constant)\s*$/ && # stringification #foo - $dstat !~ /^do\s*$Constant\s*while\s*$Constant;?$/ && # do {...} while (...); // do {...} while (...) - $dstat !~ /^for\s*$Constant$/ && # for (...) - $dstat !~ /^for\s*$Constant\s+(?:$Ident|-?$Constant)$/ && # for (...) bar() - $dstat !~ /^do\s*{/ && # do {... - $dstat !~ /^\(\{/ && # ({... - $ctx !~ /^.\s*#\s*define\s+TRACE_(?:SYSTEM|INCLUDE_FILE|INCLUDE_PATH)\b/) - { - $ctx =~ s/\n*$//; - my $herectx = $here . "\n"; - my $cnt = statement_rawlines($ctx); - - for (my $n = 0; $n < $cnt; $n++) { - $herectx .= raw_line($linenr, $n) . "\n"; - } - - if ($dstat =~ /;/) { - ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE", - "Macros with multiple statements should be enclosed in a do - while loop\n" . "$herectx"); - } else { - ERROR("COMPLEX_MACRO", - "Macros with complex values should be enclosed in parentheses\n" . "$herectx"); - } - } - -# check for macros with flow control, but without ## concatenation -# ## concatenation is commonly a macro that defines a function so ignore those - if ($has_flow_statement && !$has_arg_concat) { - my $herectx = $here . "\n"; - my $cnt = statement_rawlines($ctx); - - for (my $n = 0; $n < $cnt; $n++) { - $herectx .= raw_line($linenr, $n) . "\n"; - } - WARN("MACRO_WITH_FLOW_CONTROL", - "Macros with flow control statements should be avoided\n" . "$herectx"); - } - -# check for line continuations outside of #defines, preprocessor #, and asm - - } else { - if ($prevline !~ /^..*\\$/ && - $line !~ /^\+\s*\#.*\\$/ && # preprocessor - $line !~ /^\+.*\b(__asm__|asm)\b.*\\$/ && # asm - $line =~ /^\+.*\\$/) { - WARN("LINE_CONTINUATIONS", - "Avoid unnecessary line continuations\n" . $herecurr); - } - } - -# do {} while (0) macro tests: -# single-statement macros do not need to be enclosed in do while (0) loop, -# macro should not end with a semicolon - if ($^V && $^V ge 5.10.0 && - $realfile !~ m@/vmlinux.lds.h$@ && - $line =~ /^.\s*\#\s*define\s+$Ident(\()?/) { - my $ln = $linenr; - my $cnt = $realcnt; - my ($off, $dstat, $dcond, $rest); - my $ctx = ''; - ($dstat, $dcond, $ln, $cnt, $off) = - ctx_statement_block($linenr, $realcnt, 0); - $ctx = $dstat; - - $dstat =~ s/\\\n.//g; - $dstat =~ s/$;/ /g; - - if ($dstat =~ /^\+\s*#\s*define\s+$Ident\s*${balanced_parens}\s*do\s*{(.*)\s*}\s*while\s*\(\s*0\s*\)\s*([;\s]*)\s*$/) { - my $stmts = $2; - my $semis = $3; - - $ctx =~ s/\n*$//; - my $cnt = statement_rawlines($ctx); - my $herectx = $here . "\n"; - - for (my $n = 0; $n < $cnt; $n++) { - $herectx .= raw_line($linenr, $n) . "\n"; - } - - if (($stmts =~ tr/;/;/) == 1 && - $stmts !~ /^\s*(if|while|for|switch)\b/) { - WARN("SINGLE_STATEMENT_DO_WHILE_MACRO", - "Single statement macros should not use a do {} while (0) loop\n" . "$herectx"); - } - if (defined $semis && $semis ne "") { - WARN("DO_WHILE_MACRO_WITH_TRAILING_SEMICOLON", - "do {} while (0) macros should not be semicolon terminated\n" . "$herectx"); - } - } elsif ($dstat =~ /^\+\s*#\s*define\s+$Ident.*;\s*$/) { - $ctx =~ s/\n*$//; - my $cnt = statement_rawlines($ctx); - my $herectx = $here . "\n"; - - for (my $n = 0; $n < $cnt; $n++) { - $herectx .= raw_line($linenr, $n) . "\n"; - } - - WARN("TRAILING_SEMICOLON", - "macros should not use a trailing semicolon\n" . "$herectx"); - } - } - -# make sure symbols are always wrapped with VMLINUX_SYMBOL() ... -# all assignments may have only one of the following with an assignment: -# . -# ALIGN(...) -# VMLINUX_SYMBOL(...) - if ($realfile eq 'vmlinux.lds.h' && $line =~ /(?:(?:^|\s)$Ident\s*=|=\s*$Ident(?:\s|$))/) { - WARN("MISSING_VMLINUX_SYMBOL", - "vmlinux.lds.h needs VMLINUX_SYMBOL() around C-visible symbols\n" . $herecurr); - } - -# check for redundant bracing round if etc - if ($line =~ /(^.*)\bif\b/ && $1 !~ /else\s*$/) { - my ($level, $endln, @chunks) = - ctx_statement_full($linenr, $realcnt, 1); - #print "chunks<$#chunks> linenr<$linenr> endln<$endln> level<$level>\n"; - #print "APW: <<$chunks[1][0]>><<$chunks[1][1]>>\n"; - if ($#chunks > 0 && $level == 0) { - my @allowed = (); - my $allow = 0; - my $seen = 0; - my $herectx = $here . "\n"; - my $ln = $linenr - 1; - for my $chunk (@chunks) { - my ($cond, $block) = @{$chunk}; - - # If the condition carries leading newlines, then count those as offsets. - my ($whitespace) = ($cond =~ /^((?:\s*\n[+-])*\s*)/s); - my $offset = statement_rawlines($whitespace) - 1; - - $allowed[$allow] = 0; - #print "COND<$cond> whitespace<$whitespace> offset<$offset>\n"; - - # We have looked at and allowed this specific line. - $suppress_ifbraces{$ln + $offset} = 1; - - $herectx .= "$rawlines[$ln + $offset]\n[...]\n"; - $ln += statement_rawlines($block) - 1; - - substr($block, 0, length($cond), ''); - - $seen++ if ($block =~ /^\s*{/); - - #print "cond<$cond> block<$block> allowed<$allowed[$allow]>\n"; - if (statement_lines($cond) > 1) { - #print "APW: ALLOWED: cond<$cond>\n"; - $allowed[$allow] = 1; - } - if ($block =~/\b(?:if|for|while)\b/) { - #print "APW: ALLOWED: block<$block>\n"; - $allowed[$allow] = 1; - } - if (statement_block_size($block) > 1) { - #print "APW: ALLOWED: lines block<$block>\n"; - $allowed[$allow] = 1; - } - $allow++; - } - if ($seen) { - my $sum_allowed = 0; - foreach (@allowed) { - $sum_allowed += $_; - } - if ($sum_allowed == 0) { - WARN("BRACES", - "braces {} are not necessary for any arm of this statement\n" . $herectx); - } elsif ($sum_allowed != $allow && - $seen != $allow) { - CHK("BRACES", - "braces {} should be used on all arms of this statement\n" . $herectx); - } - } - } - } - if (!defined $suppress_ifbraces{$linenr - 1} && - $line =~ /\b(if|while|for|else)\b/) { - my $allowed = 0; - - # Check the pre-context. - if (substr($line, 0, $-[0]) =~ /(\}\s*)$/) { - #print "APW: ALLOWED: pre<$1>\n"; - $allowed = 1; - } - - my ($level, $endln, @chunks) = - ctx_statement_full($linenr, $realcnt, $-[0]); - - # Check the condition. - my ($cond, $block) = @{$chunks[0]}; - #print "CHECKING<$linenr> cond<$cond> block<$block>\n"; - if (defined $cond) { - substr($block, 0, length($cond), ''); - } - if (statement_lines($cond) > 1) { - #print "APW: ALLOWED: cond<$cond>\n"; - $allowed = 1; - } - if ($block =~/\b(?:if|for|while)\b/) { - #print "APW: ALLOWED: block<$block>\n"; - $allowed = 1; - } - if (statement_block_size($block) > 1) { - #print "APW: ALLOWED: lines block<$block>\n"; - $allowed = 1; - } - # Check the post-context. - if (defined $chunks[1]) { - my ($cond, $block) = @{$chunks[1]}; - if (defined $cond) { - substr($block, 0, length($cond), ''); - } - if ($block =~ /^\s*\{/) { - #print "APW: ALLOWED: chunk-1 block<$block>\n"; - $allowed = 1; - } - } - if ($level == 0 && $block =~ /^\s*\{/ && !$allowed) { - my $herectx = $here . "\n"; - my $cnt = statement_rawlines($block); - - for (my $n = 0; $n < $cnt; $n++) { - $herectx .= raw_line($linenr, $n) . "\n"; - } - - WARN("BRACES", - "braces {} are not necessary for single statement blocks\n" . $herectx); - } - } - -# check for unnecessary blank lines around braces - if (($line =~ /^.\s*}\s*$/ && $prevrawline =~ /^.\s*$/)) { - if (CHK("BRACES", - "Blank lines aren't necessary before a close brace '}'\n" . $hereprev) && - $fix && $prevrawline =~ /^\+/) { - fix_delete_line($fixlinenr - 1, $prevrawline); - } - } - if (($rawline =~ /^.\s*$/ && $prevline =~ /^..*{\s*$/)) { - if (CHK("BRACES", - "Blank lines aren't necessary after an open brace '{'\n" . $hereprev) && - $fix) { - fix_delete_line($fixlinenr, $rawline); - } - } - -# no volatiles please - my $asm_volatile = qr{\b(__asm__|asm)\s+(__volatile__|volatile)\b}; - if ($line =~ /\bvolatile\b/ && $line !~ /$asm_volatile/) { - WARN("VOLATILE", - "Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n" . $herecurr); - } - -# Check for user-visible strings broken across lines, which breaks the ability -# to grep for the string. Make exceptions when the previous string ends in a -# newline (multiple lines in one string constant) or '\t', '\r', ';', or '{' -# (common in inline assembly) or is a octal \123 or hexadecimal \xaf value - if ($line =~ /^\+\s*$String/ && - $prevline =~ /"\s*$/ && - $prevrawline !~ /(?:\\(?:[ntr]|[0-7]{1,3}|x[0-9a-fA-F]{1,2})|;\s*|\{\s*)"\s*$/) { - if (WARN("SPLIT_STRING", - "quoted string split across lines\n" . $hereprev) && - $fix && - $prevrawline =~ /^\+.*"\s*$/ && - $last_coalesced_string_linenr != $linenr - 1) { - my $extracted_string = get_quoted_string($line, $rawline); - my $comma_close = ""; - if ($rawline =~ /\Q$extracted_string\E(\s*\)\s*;\s*$|\s*,\s*)/) { - $comma_close = $1; - } - - fix_delete_line($fixlinenr - 1, $prevrawline); - fix_delete_line($fixlinenr, $rawline); - my $fixedline = $prevrawline; - $fixedline =~ s/"\s*$//; - $fixedline .= substr($extracted_string, 1) . trim($comma_close); - fix_insert_line($fixlinenr - 1, $fixedline); - $fixedline = $rawline; - $fixedline =~ s/\Q$extracted_string\E\Q$comma_close\E//; - if ($fixedline !~ /\+\s*$/) { - fix_insert_line($fixlinenr, $fixedline); - } - $last_coalesced_string_linenr = $linenr; - } - } - -# check for missing a space in a string concatenation - if ($prevrawline =~ /[^\\]\w"$/ && $rawline =~ /^\+[\t ]+"\w/) { - WARN('MISSING_SPACE', - "break quoted strings at a space character\n" . $hereprev); - } - -# check for spaces before a quoted newline - if ($rawline =~ /^.*\".*\s\\n/) { - if (WARN("QUOTED_WHITESPACE_BEFORE_NEWLINE", - "unnecessary whitespace before a quoted newline\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/^(\+.*\".*)\s+\\n/$1\\n/; - } - - } - -# concatenated string without spaces between elements - if ($line =~ /$String[A-Z_]/ || $line =~ /[A-Za-z0-9_]$String/) { - CHK("CONCATENATED_STRING", - "Concatenated strings should use spaces between elements\n" . $herecurr); - } - -# uncoalesced string fragments - if ($line =~ /$String\s*"/) { - WARN("STRING_FRAGMENTS", - "Consecutive strings are generally better as a single string\n" . $herecurr); - } - -# check for %L{u,d,i} and 0x%[udi] in strings - my $string; - while ($line =~ /(?:^|")([X\t]*)(?:"|$)/g) { - $string = substr($rawline, $-[1], $+[1] - $-[1]); - $string =~ s/%%/__/g; - if ($string =~ /(?<!%)%[\*\d\.\$]*L[udi]/) { - WARN("PRINTF_L", - "\%Ld/%Lu are not-standard C, use %lld/%llu\n" . $herecurr); - last; - } - if ($string =~ /0x%[\*\d\.\$\Llzth]*[udi]/) { - ERROR("PRINTF_0xDECIMAL", - "Prefixing 0x with decimal output is defective\n" . $herecurr); - } - } - -# check for line continuations in quoted strings with odd counts of " - if ($rawline =~ /\\$/ && $rawline =~ tr/"/"/ % 2) { - WARN("LINE_CONTINUATIONS", - "Avoid line continuations in quoted strings\n" . $herecurr); - } - -# warn about #if 0 - if ($line =~ /^.\s*\#\s*if\s+0\b/) { - CHK("REDUNDANT_CODE", - "if this code is redundant consider removing it\n" . - $herecurr); - } - -# check for needless "if (<foo>) fn(<foo>)" uses - if ($prevline =~ /\bif\s*\(\s*($Lval)\s*\)/) { - my $tested = quotemeta($1); - my $expr = '\s*\(\s*' . $tested . '\s*\)\s*;'; - if ($line =~ /\b(kfree|usb_free_urb|debugfs_remove(?:_recursive)?|(?:kmem_cache|mempool|dma_pool)_destroy)$expr/) { - my $func = $1; - if (WARN('NEEDLESS_IF', - "$func(NULL) is safe and this check is probably not required\n" . $hereprev) && - $fix) { - my $do_fix = 1; - my $leading_tabs = ""; - my $new_leading_tabs = ""; - if ($lines[$linenr - 2] =~ /^\+(\t*)if\s*\(\s*$tested\s*\)\s*$/) { - $leading_tabs = $1; - } else { - $do_fix = 0; - } - if ($lines[$linenr - 1] =~ /^\+(\t+)$func\s*\(\s*$tested\s*\)\s*;\s*$/) { - $new_leading_tabs = $1; - if (length($leading_tabs) + 1 ne length($new_leading_tabs)) { - $do_fix = 0; - } - } else { - $do_fix = 0; - } - if ($do_fix) { - fix_delete_line($fixlinenr - 1, $prevrawline); - $fixed[$fixlinenr] =~ s/^\+$new_leading_tabs/\+$leading_tabs/; - } - } - } - } - -# check for unnecessary "Out of Memory" messages - if ($line =~ /^\+.*\b$logFunctions\s*\(/ && - $prevline =~ /^[ \+]\s*if\s*\(\s*(\!\s*|NULL\s*==\s*)?($Lval)(\s*==\s*NULL\s*)?\s*\)/ && - (defined $1 || defined $3) && - $linenr > 3) { - my $testval = $2; - my $testline = $lines[$linenr - 3]; - - my ($s, $c) = ctx_statement_block($linenr - 3, $realcnt, 0); -# print("line: <$line>\nprevline: <$prevline>\ns: <$s>\nc: <$c>\n\n\n"); - - if ($c =~ /(?:^|\n)[ \+]\s*(?:$Type\s*)?\Q$testval\E\s*=\s*(?:\([^\)]*\)\s*)?\s*(?:devm_)?(?:[kv][czm]alloc(?:_node|_array)?\b|kstrdup|(?:dev_)?alloc_skb)/) { - WARN("OOM_MESSAGE", - "Possible unnecessary 'out of memory' message\n" . $hereprev); - } - } - -# check for logging functions with KERN_<LEVEL> - if ($line !~ /printk(?:_ratelimited|_once)?\s*\(/ && - $line =~ /\b$logFunctions\s*\(.*\b(KERN_[A-Z]+)\b/) { - my $level = $1; - if (WARN("UNNECESSARY_KERN_LEVEL", - "Possible unnecessary $level\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\s*$level\s*//; - } - } - -# check for mask then right shift without a parentheses - if ($^V && $^V ge 5.10.0 && - $line =~ /$LvalOrFunc\s*\&\s*($LvalOrFunc)\s*>>/ && - $4 !~ /^\&/) { # $LvalOrFunc may be &foo, ignore if so - WARN("MASK_THEN_SHIFT", - "Possible precedence defect with mask then right shift - may need parentheses\n" . $herecurr); - } - -# check for pointer comparisons to NULL - if ($^V && $^V ge 5.10.0) { - while ($line =~ /\b$LvalOrFunc\s*(==|\!=)\s*NULL\b/g) { - my $val = $1; - my $equal = "!"; - $equal = "" if ($4 eq "!="); - if (CHK("COMPARISON_TO_NULL", - "Comparison to NULL could be written \"${equal}${val}\"\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b\Q$val\E\s*(?:==|\!=)\s*NULL\b/$equal$val/; - } - } - } - -# check for bad placement of section $InitAttribute (e.g.: __initdata) - if ($line =~ /(\b$InitAttribute\b)/) { - my $attr = $1; - if ($line =~ /^\+\s*static\s+(?:const\s+)?(?:$attr\s+)?($NonptrTypeWithAttr)\s+(?:$attr\s+)?($Ident(?:\[[^]]*\])?)\s*[=;]/) { - my $ptr = $1; - my $var = $2; - if ((($ptr =~ /\b(union|struct)\s+$attr\b/ && - ERROR("MISPLACED_INIT", - "$attr should be placed after $var\n" . $herecurr)) || - ($ptr !~ /\b(union|struct)\s+$attr\b/ && - WARN("MISPLACED_INIT", - "$attr should be placed after $var\n" . $herecurr))) && - $fix) { - $fixed[$fixlinenr] =~ s/(\bstatic\s+(?:const\s+)?)(?:$attr\s+)?($NonptrTypeWithAttr)\s+(?:$attr\s+)?($Ident(?:\[[^]]*\])?)\s*([=;])\s*/"$1" . trim(string_find_replace($2, "\\s*$attr\\s*", " ")) . " " . trim(string_find_replace($3, "\\s*$attr\\s*", "")) . " $attr" . ("$4" eq ";" ? ";" : " = ")/e; - } - } - } - -# check for $InitAttributeData (ie: __initdata) with const - if ($line =~ /\bconst\b/ && $line =~ /($InitAttributeData)/) { - my $attr = $1; - $attr =~ /($InitAttributePrefix)(.*)/; - my $attr_prefix = $1; - my $attr_type = $2; - if (ERROR("INIT_ATTRIBUTE", - "Use of const init definition must use ${attr_prefix}initconst\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/$InitAttributeData/${attr_prefix}initconst/; - } - } - -# check for $InitAttributeConst (ie: __initconst) without const - if ($line !~ /\bconst\b/ && $line =~ /($InitAttributeConst)/) { - my $attr = $1; - if (ERROR("INIT_ATTRIBUTE", - "Use of $attr requires a separate use of const\n" . $herecurr) && - $fix) { - my $lead = $fixed[$fixlinenr] =~ - /(^\+\s*(?:static\s+))/; - $lead = rtrim($1); - $lead = "$lead " if ($lead !~ /^\+$/); - $lead = "${lead}const "; - $fixed[$fixlinenr] =~ s/(^\+\s*(?:static\s+))/$lead/; - } - } - -# check for __read_mostly with const non-pointer (should just be const) - if ($line =~ /\b__read_mostly\b/ && - $line =~ /($Type)\s*$Ident/ && $1 !~ /\*\s*$/ && $1 =~ /\bconst\b/) { - if (ERROR("CONST_READ_MOSTLY", - "Invalid use of __read_mostly with const type\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\s+__read_mostly\b//; - } - } - -# don't use __constant_<foo> functions outside of include/uapi/ - if ($realfile !~ m@^include/uapi/@ && - $line =~ /(__constant_(?:htons|ntohs|[bl]e(?:16|32|64)_to_cpu|cpu_to_[bl]e(?:16|32|64)))\s*\(/) { - my $constant_func = $1; - my $func = $constant_func; - $func =~ s/^__constant_//; - if (WARN("CONSTANT_CONVERSION", - "$constant_func should be $func\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b$constant_func\b/$func/g; - } - } - -# prefer usleep_range over udelay - if ($line =~ /\budelay\s*\(\s*(\d+)\s*\)/) { - my $delay = $1; - # ignore udelay's < 10, however - if (! ($delay < 10) ) { - CHK("USLEEP_RANGE", - "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt\n" . $herecurr); - } - if ($delay > 2000) { - WARN("LONG_UDELAY", - "long udelay - prefer mdelay; see arch/arm/include/asm/delay.h\n" . $herecurr); - } - } - -# warn about unexpectedly long msleep's - if ($line =~ /\bmsleep\s*\((\d+)\);/) { - if ($1 < 20) { - WARN("MSLEEP", - "msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt\n" . $herecurr); - } - } - -# check for comparisons of jiffies - if ($line =~ /\bjiffies\s*$Compare|$Compare\s*jiffies\b/) { - WARN("JIFFIES_COMPARISON", - "Comparing jiffies is almost always wrong; prefer time_after, time_before and friends\n" . $herecurr); - } - -# check for comparisons of get_jiffies_64() - if ($line =~ /\bget_jiffies_64\s*\(\s*\)\s*$Compare|$Compare\s*get_jiffies_64\s*\(\s*\)/) { - WARN("JIFFIES_COMPARISON", - "Comparing get_jiffies_64() is almost always wrong; prefer time_after64, time_before64 and friends\n" . $herecurr); - } - -# warn about #ifdefs in C files -# if ($line =~ /^.\s*\#\s*if(|n)def/ && ($realfile =~ /\.c$/)) { -# print "#ifdef in C files should be avoided\n"; -# print "$herecurr"; -# $clean = 0; -# } - -# warn about spacing in #ifdefs - if ($line =~ /^.\s*\#\s*(ifdef|ifndef|elif)\s\s+/) { - if (ERROR("SPACING", - "exactly one space required after that #$1\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/^(.\s*\#\s*(ifdef|ifndef|elif))\s{2,}/$1 /; - } - - } - -# check for spinlock_t definitions without a comment. - if ($line =~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/ || - $line =~ /^.\s*(DEFINE_MUTEX)\s*\(/) { - my $which = $1; - if (!ctx_has_comment($first_line, $linenr)) { - CHK("UNCOMMENTED_DEFINITION", - "$1 definition without comment\n" . $herecurr); - } - } -# check for memory barriers without a comment. - - my $barriers = qr{ - mb| - rmb| - wmb| - read_barrier_depends - }x; - my $barrier_stems = qr{ - mb__before_atomic| - mb__after_atomic| - store_release| - load_acquire| - store_mb| - (?:$barriers) - }x; - my $all_barriers = qr{ - (?:$barriers)| - smp_(?:$barrier_stems)| - virt_(?:$barrier_stems) - }x; - - if ($line =~ /\b(?:$all_barriers)\s*\(/) { - if (!ctx_has_comment($first_line, $linenr)) { - WARN("MEMORY_BARRIER", - "memory barrier without comment\n" . $herecurr); - } - } - - my $underscore_smp_barriers = qr{__smp_(?:$barrier_stems)}x; - - if ($realfile !~ m@^include/asm-generic/@ && - $realfile !~ m@/barrier\.h$@ && - $line =~ m/\b(?:$underscore_smp_barriers)\s*\(/ && - $line !~ m/^.\s*\#\s*define\s+(?:$underscore_smp_barriers)\s*\(/) { - WARN("MEMORY_BARRIER", - "__smp memory barriers shouldn't be used outside barrier.h and asm-generic\n" . $herecurr); - } - -# check for waitqueue_active without a comment. - if ($line =~ /\bwaitqueue_active\s*\(/) { - if (!ctx_has_comment($first_line, $linenr)) { - WARN("WAITQUEUE_ACTIVE", - "waitqueue_active without comment\n" . $herecurr); - } - } - -# Check for expedited grace periods that interrupt non-idle non-nohz -# online CPUs. These expedited can therefore degrade real-time response -# if used carelessly, and should be avoided where not absolutely -# needed. It is always OK to use synchronize_rcu_expedited() and -# synchronize_sched_expedited() at boot time (before real-time applications -# start) and in error situations where real-time response is compromised in -# any case. Note that synchronize_srcu_expedited() does -not- interrupt -# other CPUs, so don't warn on uses of synchronize_srcu_expedited(). -# Of course, nothing comes for free, and srcu_read_lock() and -# srcu_read_unlock() do contain full memory barriers in payment for -# synchronize_srcu_expedited() non-interruption properties. - if ($line =~ /\b(synchronize_rcu_expedited|synchronize_sched_expedited)\(/) { - WARN("EXPEDITED_RCU_GRACE_PERIOD", - "expedited RCU grace periods should be avoided where they can degrade real-time response\n" . $herecurr); - - } - -# check of hardware specific defines - if ($line =~ m@^.\s*\#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@ && $realfile !~ m@include/asm-@) { - CHK("ARCH_DEFINES", - "architecture specific defines should be avoided\n" . $herecurr); - } - -# Check that the storage class is at the beginning of a declaration - if ($line =~ /\b$Storage\b/ && $line !~ /^.\s*$Storage\b/) { - WARN("STORAGE_CLASS", - "storage class should be at the beginning of the declaration\n" . $herecurr) - } - -# check the location of the inline attribute, that it is between -# storage class and type. - if ($line =~ /\b$Type\s+$Inline\b/ || - $line =~ /\b$Inline\s+$Storage\b/) { - ERROR("INLINE_LOCATION", - "inline keyword should sit between storage class and type\n" . $herecurr); - } - -# Check for __inline__ and __inline, prefer inline - if ($realfile !~ m@\binclude/uapi/@ && - $line =~ /\b(__inline__|__inline)\b/) { - if (WARN("INLINE", - "plain inline is preferred over $1\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b(__inline__|__inline)\b/inline/; - - } - } - -# Check for __attribute__ packed, prefer __packed - if ($realfile !~ m@\binclude/uapi/@ && - $line =~ /\b__attribute__\s*\(\s*\(.*\bpacked\b/) { - WARN("PREFER_PACKED", - "__packed is preferred over __attribute__((packed))\n" . $herecurr); - } - -# Check for __attribute__ aligned, prefer __aligned - if ($realfile !~ m@\binclude/uapi/@ && - $line =~ /\b__attribute__\s*\(\s*\(.*aligned/) { - WARN("PREFER_ALIGNED", - "__aligned(size) is preferred over __attribute__((aligned(size)))\n" . $herecurr); - } - -# Check for __attribute__ format(printf, prefer __printf - if ($realfile !~ m@\binclude/uapi/@ && - $line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf/) { - if (WARN("PREFER_PRINTF", - "__printf(string-index, first-to-check) is preferred over __attribute__((format(printf, string-index, first-to-check)))\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf\s*,\s*(.*)\)\s*\)\s*\)/"__printf(" . trim($1) . ")"/ex; - - } - } - -# Check for __attribute__ format(scanf, prefer __scanf - if ($realfile !~ m@\binclude/uapi/@ && - $line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\b/) { - if (WARN("PREFER_SCANF", - "__scanf(string-index, first-to-check) is preferred over __attribute__((format(scanf, string-index, first-to-check)))\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\s*,\s*(.*)\)\s*\)\s*\)/"__scanf(" . trim($1) . ")"/ex; - } - } - -# Check for __attribute__ weak, or __weak declarations (may have link issues) - if ($^V && $^V ge 5.10.0 && - $line =~ /(?:$Declare|$DeclareMisordered)\s*$Ident\s*$balanced_parens\s*(?:$Attribute)?\s*;/ && - ($line =~ /\b__attribute__\s*\(\s*\(.*\bweak\b/ || - $line =~ /\b__weak\b/)) { - ERROR("WEAK_DECLARATION", - "Using weak declarations can have unintended link defects\n" . $herecurr); - } - -# check for c99 types like uint8_t used outside of uapi/ - if ($realfile !~ m@\binclude/uapi/@ && - $line =~ /\b($Declare)\s*$Ident\s*[=;,\[]/) { - my $type = $1; - if ($type =~ /\b($typeC99Typedefs)\b/) { - $type = $1; - my $kernel_type = 'u'; - $kernel_type = 's' if ($type =~ /^_*[si]/); - $type =~ /(\d+)/; - $kernel_type .= $1; - if (CHK("PREFER_KERNEL_TYPES", - "Prefer kernel type '$kernel_type' over '$type'\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b$type\b/$kernel_type/; - } - } - } - -# check for cast of C90 native int or longer types constants - if ($line =~ /(\(\s*$C90_int_types\s*\)\s*)($Constant)\b/) { - my $cast = $1; - my $const = $2; - if (WARN("TYPECAST_INT_CONSTANT", - "Unnecessary typecast of c90 int constant\n" . $herecurr) && - $fix) { - my $suffix = ""; - my $newconst = $const; - $newconst =~ s/${Int_type}$//; - $suffix .= 'U' if ($cast =~ /\bunsigned\b/); - if ($cast =~ /\blong\s+long\b/) { - $suffix .= 'LL'; - } elsif ($cast =~ /\blong\b/) { - $suffix .= 'L'; - } - $fixed[$fixlinenr] =~ s/\Q$cast\E$const\b/$newconst$suffix/; - } - } - -# check for sizeof(&) - if ($line =~ /\bsizeof\s*\(\s*\&/) { - WARN("SIZEOF_ADDRESS", - "sizeof(& should be avoided\n" . $herecurr); - } - -# check for sizeof without parenthesis - if ($line =~ /\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/) { - if (WARN("SIZEOF_PARENTHESIS", - "sizeof $1 should be sizeof($1)\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/"sizeof(" . trim($1) . ")"/ex; - } - } - -# check for struct spinlock declarations - if ($line =~ /^.\s*\bstruct\s+spinlock\s+\w+\s*;/) { - WARN("USE_SPINLOCK_T", - "struct spinlock should be spinlock_t\n" . $herecurr); - } - -# check for seq_printf uses that could be seq_puts - if ($sline =~ /\bseq_printf\s*\(.*"\s*\)\s*;\s*$/) { - my $fmt = get_quoted_string($line, $rawline); - $fmt =~ s/%%//g; - if ($fmt !~ /%/) { - if (WARN("PREFER_SEQ_PUTS", - "Prefer seq_puts to seq_printf\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\bseq_printf\b/seq_puts/; - } - } - } - -# Check for misused memsets - if ($^V && $^V ge 5.10.0 && - defined $stat && - $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*$FuncArg\s*\)/) { - - my $ms_addr = $2; - my $ms_val = $7; - my $ms_size = $12; - - if ($ms_size =~ /^(0x|)0$/i) { - ERROR("MEMSET", - "memset to 0's uses 0 as the 2nd argument, not the 3rd\n" . "$here\n$stat\n"); - } elsif ($ms_size =~ /^(0x|)1$/i) { - WARN("MEMSET", - "single byte memset is suspicious. Swapped 2nd/3rd argument?\n" . "$here\n$stat\n"); - } - } - -# Check for memcpy(foo, bar, ETH_ALEN) that could be ether_addr_copy(foo, bar) - if ($^V && $^V ge 5.10.0 && - defined $stat && - $stat =~ /^\+(?:.*?)\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) { - if (WARN("PREFER_ETHER_ADDR_COPY", - "Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2)\n" . "$here\n$stat\n") && - $fix) { - $fixed[$fixlinenr] =~ s/\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/ether_addr_copy($2, $7)/; - } - } - -# Check for memcmp(foo, bar, ETH_ALEN) that could be ether_addr_equal*(foo, bar) - if ($^V && $^V ge 5.10.0 && - defined $stat && - $stat =~ /^\+(?:.*?)\bmemcmp\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) { - WARN("PREFER_ETHER_ADDR_EQUAL", - "Prefer ether_addr_equal() or ether_addr_equal_unaligned() over memcmp()\n" . "$here\n$stat\n") - } - -# check for memset(foo, 0x0, ETH_ALEN) that could be eth_zero_addr -# check for memset(foo, 0xFF, ETH_ALEN) that could be eth_broadcast_addr - if ($^V && $^V ge 5.10.0 && - defined $stat && - $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) { - - my $ms_val = $7; - - if ($ms_val =~ /^(?:0x|)0+$/i) { - if (WARN("PREFER_ETH_ZERO_ADDR", - "Prefer eth_zero_addr over memset()\n" . "$here\n$stat\n") && - $fix) { - $fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_zero_addr($2)/; - } - } elsif ($ms_val =~ /^(?:0xff|255)$/i) { - if (WARN("PREFER_ETH_BROADCAST_ADDR", - "Prefer eth_broadcast_addr() over memset()\n" . "$here\n$stat\n") && - $fix) { - $fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_broadcast_addr($2)/; - } - } - } - -# typecasts on min/max could be min_t/max_t - if ($^V && $^V ge 5.10.0 && - defined $stat && - $stat =~ /^\+(?:.*?)\b(min|max)\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\)/) { - if (defined $2 || defined $7) { - my $call = $1; - my $cast1 = deparenthesize($2); - my $arg1 = $3; - my $cast2 = deparenthesize($7); - my $arg2 = $8; - my $cast; - - if ($cast1 ne "" && $cast2 ne "" && $cast1 ne $cast2) { - $cast = "$cast1 or $cast2"; - } elsif ($cast1 ne "") { - $cast = $cast1; - } else { - $cast = $cast2; - } - WARN("MINMAX", - "$call() should probably be ${call}_t($cast, $arg1, $arg2)\n" . "$here\n$stat\n"); - } - } - -# check usleep_range arguments - if ($^V && $^V ge 5.10.0 && - defined $stat && - $stat =~ /^\+(?:.*?)\busleep_range\s*\(\s*($FuncArg)\s*,\s*($FuncArg)\s*\)/) { - my $min = $1; - my $max = $7; - if ($min eq $max) { - WARN("USLEEP_RANGE", - "usleep_range should not use min == max args; see Documentation/timers/timers-howto.txt\n" . "$here\n$stat\n"); - } elsif ($min =~ /^\d+$/ && $max =~ /^\d+$/ && - $min > $max) { - WARN("USLEEP_RANGE", - "usleep_range args reversed, use min then max; see Documentation/timers/timers-howto.txt\n" . "$here\n$stat\n"); - } - } - -# check for naked sscanf - if ($^V && $^V ge 5.10.0 && - defined $stat && - $line =~ /\bsscanf\b/ && - ($stat !~ /$Ident\s*=\s*sscanf\s*$balanced_parens/ && - $stat !~ /\bsscanf\s*$balanced_parens\s*(?:$Compare)/ && - $stat !~ /(?:$Compare)\s*\bsscanf\s*$balanced_parens/)) { - my $lc = $stat =~ tr@\n@@; - $lc = $lc + $linenr; - my $stat_real = raw_line($linenr, 0); - for (my $count = $linenr + 1; $count <= $lc; $count++) { - $stat_real = $stat_real . "\n" . raw_line($count, 0); - } - WARN("NAKED_SSCANF", - "unchecked sscanf return value\n" . "$here\n$stat_real\n"); - } - -# check for simple sscanf that should be kstrto<foo> - if ($^V && $^V ge 5.10.0 && - defined $stat && - $line =~ /\bsscanf\b/) { - my $lc = $stat =~ tr@\n@@; - $lc = $lc + $linenr; - my $stat_real = raw_line($linenr, 0); - for (my $count = $linenr + 1; $count <= $lc; $count++) { - $stat_real = $stat_real . "\n" . raw_line($count, 0); - } - if ($stat_real =~ /\bsscanf\b\s*\(\s*$FuncArg\s*,\s*("[^"]+")/) { - my $format = $6; - my $count = $format =~ tr@%@%@; - if ($count == 1 && - $format =~ /^"\%(?i:ll[udxi]|[udxi]ll|ll|[hl]h?[udxi]|[udxi][hl]h?|[hl]h?|[udxi])"$/) { - WARN("SSCANF_TO_KSTRTO", - "Prefer kstrto<type> to single variable sscanf\n" . "$here\n$stat_real\n"); - } - } - } - -# check for new externs in .h files. - if ($realfile =~ /\.h$/ && - $line =~ /^\+\s*(extern\s+)$Type\s*$Ident\s*\(/s) { - if (CHK("AVOID_EXTERNS", - "extern prototypes should be avoided in .h files\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/(.*)\bextern\b\s*(.*)/$1$2/; - } - } - -# check for new externs in .c files. - if ($realfile =~ /\.c$/ && defined $stat && - $stat =~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s) - { - my $function_name = $1; - my $paren_space = $2; - - my $s = $stat; - if (defined $cond) { - substr($s, 0, length($cond), ''); - } - if ($s =~ /^\s*;/ && - $function_name ne 'uninitialized_var') - { - WARN("AVOID_EXTERNS", - "externs should be avoided in .c files\n" . $herecurr); - } - - if ($paren_space =~ /\n/) { - WARN("FUNCTION_ARGUMENTS", - "arguments for function declarations should follow identifier\n" . $herecurr); - } - - } elsif ($realfile =~ /\.c$/ && defined $stat && - $stat =~ /^.\s*extern\s+/) - { - WARN("AVOID_EXTERNS", - "externs should be avoided in .c files\n" . $herecurr); - } - -# checks for new __setup's - if ($rawline =~ /\b__setup\("([^"]*)"/) { - my $name = $1; - - if (!grep(/$name/, @setup_docs)) { - CHK("UNDOCUMENTED_SETUP", - "__setup appears un-documented -- check Documentation/kernel-parameters.txt\n" . $herecurr); - } - } - -# check for pointless casting of kmalloc return - if ($line =~ /\*\s*\)\s*[kv][czm]alloc(_node){0,1}\b/) { - WARN("UNNECESSARY_CASTS", - "unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $herecurr); - } - -# alloc style -# p = alloc(sizeof(struct foo), ...) should be p = alloc(sizeof(*p), ...) - if ($^V && $^V ge 5.10.0 && - $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*([kv][mz]alloc(?:_node)?)\s*\(\s*(sizeof\s*\(\s*struct\s+$Lval\s*\))/) { - CHK("ALLOC_SIZEOF_STRUCT", - "Prefer $3(sizeof(*$1)...) over $3($4...)\n" . $herecurr); - } - -# check for k[mz]alloc with multiplies that could be kmalloc_array/kcalloc - if ($^V && $^V ge 5.10.0 && - $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) { - my $oldfunc = $3; - my $a1 = $4; - my $a2 = $10; - my $newfunc = "kmalloc_array"; - $newfunc = "kcalloc" if ($oldfunc eq "kzalloc"); - my $r1 = $a1; - my $r2 = $a2; - if ($a1 =~ /^sizeof\s*\S/) { - $r1 = $a2; - $r2 = $a1; - } - if ($r1 !~ /^sizeof\b/ && $r2 =~ /^sizeof\s*\S/ && - !($r1 =~ /^$Constant$/ || $r1 =~ /^[A-Z_][A-Z0-9_]*$/)) { - if (WARN("ALLOC_WITH_MULTIPLY", - "Prefer $newfunc over $oldfunc with multiply\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . trim($r1) . ', ' . trim($r2)/e; - - } - } - } - -# check for krealloc arg reuse - if ($^V && $^V ge 5.10.0 && - $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*krealloc\s*\(\s*\1\s*,/) { - WARN("KREALLOC_ARG_REUSE", - "Reusing the krealloc arg is almost always a bug\n" . $herecurr); - } - -# check for alloc argument mismatch - if ($line =~ /\b(kcalloc|kmalloc_array)\s*\(\s*sizeof\b/) { - WARN("ALLOC_ARRAY_ARGS", - "$1 uses number as first arg, sizeof is generally wrong\n" . $herecurr); - } - -# check for multiple semicolons - if ($line =~ /;\s*;\s*$/) { - if (WARN("ONE_SEMICOLON", - "Statements terminations use 1 semicolon\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/(\s*;\s*){2,}$/;/g; - } - } - -# check for #defines like: 1 << <digit> that could be BIT(digit) - if ($line =~ /#\s*define\s+\w+\s+\(?\s*1\s*([ulUL]*)\s*\<\<\s*(?:\d+|$Ident)\s*\)?/) { - my $ull = ""; - $ull = "_ULL" if (defined($1) && $1 =~ /ll/i); - if (CHK("BIT_MACRO", - "Prefer using the BIT$ull macro\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\(?\s*1\s*[ulUL]*\s*<<\s*(\d+|$Ident)\s*\)?/BIT${ull}($1)/; - } - } - -# check for case / default statements not preceded by break/fallthrough/switch - if ($line =~ /^.\s*(?:case\s+(?:$Ident|$Constant)\s*|default):/) { - my $has_break = 0; - my $has_statement = 0; - my $count = 0; - my $prevline = $linenr; - while ($prevline > 1 && ($file || $count < 3) && !$has_break) { - $prevline--; - my $rline = $rawlines[$prevline - 1]; - my $fline = $lines[$prevline - 1]; - last if ($fline =~ /^\@\@/); - next if ($fline =~ /^\-/); - next if ($fline =~ /^.(?:\s*(?:case\s+(?:$Ident|$Constant)[\s$;]*|default):[\s$;]*)*$/); - $has_break = 1 if ($rline =~ /fall[\s_-]*(through|thru)/i); - next if ($fline =~ /^.[\s$;]*$/); - $has_statement = 1; - $count++; - $has_break = 1 if ($fline =~ /\bswitch\b|\b(?:break\s*;[\s$;]*$|return\b|goto\b|continue\b)/); - } - if (!$has_break && $has_statement) { - WARN("MISSING_BREAK", - "Possible switch case/default not preceeded by break or fallthrough comment\n" . $herecurr); - } - } - -# check for switch/default statements without a break; - if ($^V && $^V ge 5.10.0 && - defined $stat && - $stat =~ /^\+[$;\s]*(?:case[$;\s]+\w+[$;\s]*:[$;\s]*|)*[$;\s]*\bdefault[$;\s]*:[$;\s]*;/g) { - my $ctx = ''; - my $herectx = $here . "\n"; - my $cnt = statement_rawlines($stat); - for (my $n = 0; $n < $cnt; $n++) { - $herectx .= raw_line($linenr, $n) . "\n"; - } - WARN("DEFAULT_NO_BREAK", - "switch default: should use break\n" . $herectx); - } - -# check for gcc specific __FUNCTION__ - if ($line =~ /\b__FUNCTION__\b/) { - if (WARN("USE_FUNC", - "__func__ should be used instead of gcc specific __FUNCTION__\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b__FUNCTION__\b/__func__/g; - } - } - -# check for uses of __DATE__, __TIME__, __TIMESTAMP__ - while ($line =~ /\b(__(?:DATE|TIME|TIMESTAMP)__)\b/g) { - ERROR("DATE_TIME", - "Use of the '$1' macro makes the build non-deterministic\n" . $herecurr); - } - -# check for use of yield() - if ($line =~ /\byield\s*\(\s*\)/) { - WARN("YIELD", - "Using yield() is generally wrong. See yield() kernel-doc (sched/core.c)\n" . $herecurr); - } - -# check for comparisons against true and false - if ($line =~ /\+\s*(.*?)\b(true|false|$Lval)\s*(==|\!=)\s*(true|false|$Lval)\b(.*)$/i) { - my $lead = $1; - my $arg = $2; - my $test = $3; - my $otype = $4; - my $trail = $5; - my $op = "!"; - - ($arg, $otype) = ($otype, $arg) if ($arg =~ /^(?:true|false)$/i); - - my $type = lc($otype); - if ($type =~ /^(?:true|false)$/) { - if (("$test" eq "==" && "$type" eq "true") || - ("$test" eq "!=" && "$type" eq "false")) { - $op = ""; - } - - CHK("BOOL_COMPARISON", - "Using comparison to $otype is error prone\n" . $herecurr); - -## maybe suggesting a correct construct would better -## "Using comparison to $otype is error prone. Perhaps use '${lead}${op}${arg}${trail}'\n" . $herecurr); - - } - } - -# check for semaphores initialized locked - if ($line =~ /^.\s*sema_init.+,\W?0\W?\)/) { - WARN("CONSIDER_COMPLETION", - "consider using a completion\n" . $herecurr); - } - -# recommend kstrto* over simple_strto* and strict_strto* - if ($line =~ /\b((simple|strict)_(strto(l|ll|ul|ull)))\s*\(/) { - WARN("CONSIDER_KSTRTO", - "$1 is obsolete, use k$3 instead\n" . $herecurr); - } - -# check for __initcall(), use device_initcall() explicitly or more appropriate function please - if ($line =~ /^.\s*__initcall\s*\(/) { - WARN("USE_DEVICE_INITCALL", - "please use device_initcall() or more appropriate function instead of __initcall() (see include/linux/init.h)\n" . $herecurr); - } - -# check for various structs that are normally const (ops, kgdb, device_tree) - my $const_structs = qr{ - acpi_dock_ops| - address_space_operations| - backlight_ops| - block_device_operations| - dentry_operations| - dev_pm_ops| - dma_map_ops| - extent_io_ops| - file_lock_operations| - file_operations| - hv_ops| - ide_dma_ops| - intel_dvo_dev_ops| - item_operations| - iwl_ops| - kgdb_arch| - kgdb_io| - kset_uevent_ops| - lock_manager_operations| - microcode_ops| - mtrr_ops| - neigh_ops| - nlmsvc_binding| - of_device_id| - pci_raw_ops| - pipe_buf_operations| - platform_hibernation_ops| - platform_suspend_ops| - proto_ops| - rpc_pipe_ops| - seq_operations| - snd_ac97_build_ops| - soc_pcmcia_socket_ops| - stacktrace_ops| - sysfs_ops| - tty_operations| - uart_ops| - usb_mon_operations| - wd_ops}x; - if ($line !~ /\bconst\b/ && - $line =~ /\bstruct\s+($const_structs)\b/) { - WARN("CONST_STRUCT", - "struct $1 should normally be const\n" . - $herecurr); - } - -# use of NR_CPUS is usually wrong -# ignore definitions of NR_CPUS and usage to define arrays as likely right - if ($line =~ /\bNR_CPUS\b/ && - $line !~ /^.\s*\s*#\s*if\b.*\bNR_CPUS\b/ && - $line !~ /^.\s*\s*#\s*define\b.*\bNR_CPUS\b/ && - $line !~ /^.\s*$Declare\s.*\[[^\]]*NR_CPUS[^\]]*\]/ && - $line !~ /\[[^\]]*\.\.\.[^\]]*NR_CPUS[^\]]*\]/ && - $line !~ /\[[^\]]*NR_CPUS[^\]]*\.\.\.[^\]]*\]/) - { - WARN("NR_CPUS", - "usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc\n" . $herecurr); - } - -# Use of __ARCH_HAS_<FOO> or ARCH_HAVE_<BAR> is wrong. - if ($line =~ /\+\s*#\s*define\s+((?:__)?ARCH_(?:HAS|HAVE)\w*)\b/) { - ERROR("DEFINE_ARCH_HAS", - "#define of '$1' is wrong - use Kconfig variables or standard guards instead\n" . $herecurr); - } - -# likely/unlikely comparisons similar to "(likely(foo) > 0)" - if ($^V && $^V ge 5.10.0 && - $line =~ /\b((?:un)?likely)\s*\(\s*$FuncArg\s*\)\s*$Compare/) { - WARN("LIKELY_MISUSE", - "Using $1 should generally have parentheses around the comparison\n" . $herecurr); - } - -# whine mightly about in_atomic - if ($line =~ /\bin_atomic\s*\(/) { - if ($realfile =~ m@^drivers/@) { - ERROR("IN_ATOMIC", - "do not use in_atomic in drivers\n" . $herecurr); - } elsif ($realfile !~ m@^kernel/@) { - WARN("IN_ATOMIC", - "use of in_atomic() is incorrect outside core kernel code\n" . $herecurr); - } - } - -# check for lockdep_set_novalidate_class - if ($line =~ /^.\s*lockdep_set_novalidate_class\s*\(/ || - $line =~ /__lockdep_no_validate__\s*\)/ ) { - if ($realfile !~ m@^kernel/lockdep@ && - $realfile !~ m@^include/linux/lockdep@ && - $realfile !~ m@^drivers/base/core@) { - ERROR("LOCKDEP", - "lockdep_no_validate class is reserved for device->mutex.\n" . $herecurr); - } - } - - if ($line =~ /debugfs_create_\w+.*\b$mode_perms_world_writable\b/ || - $line =~ /DEVICE_ATTR.*\b$mode_perms_world_writable\b/) { - WARN("EXPORTED_WORLD_WRITABLE", - "Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr); - } - -# Mode permission misuses where it seems decimal should be octal -# This uses a shortcut match to avoid unnecessary uses of a slow foreach loop - if ($^V && $^V ge 5.10.0 && - $line =~ /$mode_perms_search/) { - foreach my $entry (@mode_permission_funcs) { - my $func = $entry->[0]; - my $arg_pos = $entry->[1]; - - my $skip_args = ""; - if ($arg_pos > 1) { - $arg_pos--; - $skip_args = "(?:\\s*$FuncArg\\s*,\\s*){$arg_pos,$arg_pos}"; - } - my $test = "\\b$func\\s*\\(${skip_args}([\\d]+)\\s*[,\\)]"; - if ($line =~ /$test/) { - my $val = $1; - $val = $6 if ($skip_args ne ""); - - if ($val !~ /^0$/ && - (($val =~ /^$Int$/ && $val !~ /^$Octal$/) || - length($val) ne 4)) { - ERROR("NON_OCTAL_PERMISSIONS", - "Use 4 digit octal (0777) not decimal permissions\n" . $herecurr); - } elsif ($val =~ /^$Octal$/ && (oct($val) & 02)) { - ERROR("EXPORTED_WORLD_WRITABLE", - "Exporting writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr); - } - } - } - } - -# validate content of MODULE_LICENSE against list from include/linux/module.h - if ($line =~ /\bMODULE_LICENSE\s*\(\s*($String)\s*\)/) { - my $extracted_string = get_quoted_string($line, $rawline); - my $valid_licenses = qr{ - GPL| - GPL\ v2| - GPL\ and\ additional\ rights| - Dual\ BSD/GPL| - Dual\ MIT/GPL| - Dual\ MPL/GPL| - Proprietary - }x; - if ($extracted_string !~ /^"(?:$valid_licenses)"$/x) { - WARN("MODULE_LICENSE", - "unknown module license " . $extracted_string . "\n" . $herecurr); - } - } - } - - # If we have no input at all, then there is nothing to report on - # so just keep quiet. - if ($#rawlines == -1) { - exit(0); - } - - # In mailback mode only produce a report in the negative, for - # things that appear to be patches. - if ($mailback && ($clean == 1 || !$is_patch)) { - exit(0); - } - - # This is not a patch, and we are are in 'no-patch' mode so - # just keep quiet. - if (!$chk_patch && !$is_patch) { - exit(0); - } - - if (!$is_patch && $file !~ /cover-letter\.patch$/) { - ERROR("NOT_UNIFIED_DIFF", - "Does not appear to be a unified-diff format patch\n"); - } - if ($is_patch && $filename ne '-' && $chk_signoff && $signoff == 0) { - ERROR("MISSING_SIGN_OFF", - "Missing Signed-off-by: line(s)\n"); - } - - print report_dump(); - if ($summary && !($clean == 1 && $quiet == 1)) { - print "$filename " if ($summary_file); - print "total: $cnt_error errors, $cnt_warn warnings, " . - (($check)? "$cnt_chk checks, " : "") . - "$cnt_lines lines checked\n"; - } - - if ($quiet == 0) { - # If there were whitespace errors which cleanpatch can fix - # then suggest that. - if ($rpt_cleaners) { - $rpt_cleaners = 0; - print << "EOM" - -NOTE: Whitespace errors detected. - You may wish to use scripts/cleanpatch or scripts/cleanfile -EOM - } - } - - if ($clean == 0 && $fix && - ("@rawlines" ne "@fixed" || - $#fixed_inserted >= 0 || $#fixed_deleted >= 0)) { - my $newfile = $filename; - $newfile .= ".EXPERIMENTAL-checkpatch-fixes" if (!$fix_inplace); - my $linecount = 0; - my $f; - - @fixed = fix_inserted_deleted_lines(\@fixed, \@fixed_inserted, \@fixed_deleted); - - open($f, '>', $newfile) - or die "$P: Can't open $newfile for write\n"; - foreach my $fixed_line (@fixed) { - $linecount++; - if ($file) { - if ($linecount > 3) { - $fixed_line =~ s/^\+//; - print $f $fixed_line . "\n"; - } - } else { - print $f $fixed_line . "\n"; - } - } - close($f); - - if (!$quiet) { - print << "EOM"; - -Wrote EXPERIMENTAL --fix correction(s) to '$newfile' - -Do _NOT_ trust the results written to this file. -Do _NOT_ submit these changes without inspecting them for correctness. - -This EXPERIMENTAL file is simply a convenience to help rewrite patches. -No warranties, expressed or implied... -EOM - } - } - - if ($quiet == 0) { - print "\n"; - if ($clean == 1) { - print "$vname has no obvious style problems and is ready for submission.\n"; - } else { - print "$vname has style problems, please review.\n"; - } - } - return $clean; -} diff --git a/drivers/staging/greybus/scripts/checkpatch.pl b/drivers/staging/greybus/scripts/checkpatch.pl new file mode 100755 index 0000000..d574d13 --- /dev/null +++ b/drivers/staging/greybus/scripts/checkpatch.pl @@ -0,0 +1,5993 @@ +#!/usr/bin/perl -w +# (c) 2001, Dave Jones. (the file handling bit) +# (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit) +# (c) 2007,2008, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite) +# (c) 2008-2010 Andy Whitcroft <apw@canonical.com> +# Licensed under the terms of the GNU GPL License version 2 + +use strict; +use POSIX; +use File::Basename; +use Cwd 'abs_path'; +use Term::ANSIColor qw(:constants); + +my $P = $0; +my $D = dirname(abs_path($P)); + +my $V = '0.32'; + +use Getopt::Long qw(:config no_auto_abbrev); + +my $quiet = 0; +my $tree = 1; +my $chk_signoff = 1; +my $chk_patch = 1; +my $tst_only; +my $emacs = 0; +my $terse = 0; +my $showfile = 0; +my $file = 0; +my $check = 0; +my $check_orig = 0; +my $summary = 1; +my $mailback = 0; +my $summary_file = 0; +my $show_types = 0; +my $fix = 0; +my $fix_inplace = 0; +my $root; +my %debug; +my %camelcase = (); +my %use_type = (); +my @use = (); +my %ignore_type = (); +my @ignore = (); +my $help = 0; +my $configuration_file = ".checkpatch.conf"; +my $max_line_length = 80; +my $ignore_perl_version = 0; +my $minimum_perl_version = 5.10.0; +my $min_conf_desc_length = 4; +my $spelling_file = "$D/spelling.txt"; +my $codespell = 0; +my $codespellfile = "/usr/share/codespell/dictionary.txt"; +my $color = 1; + +sub help { + my ($exitcode) = @_; + + print << "EOM"; +Usage: $P [OPTION]... [FILE]... +Version: $V + +Options: + -q, --quiet quiet + --no-tree run without a kernel tree + --no-signoff do not check for 'Signed-off-by' line + --patch treat FILE as patchfile (default) + --emacs emacs compile window format + --terse one line per report + --showfile emit diffed file position, not input file position + -f, --file treat FILE as regular source file + --subjective, --strict enable more subjective tests + --types TYPE(,TYPE2...) show only these comma separated message types + --ignore TYPE(,TYPE2...) ignore various comma separated message types + --max-line-length=n set the maximum line length, if exceeded, warn + --min-conf-desc-length=n set the min description length, if shorter, warn + --show-types show the message "types" in the output + --root=PATH PATH to the kernel tree root + --no-summary suppress the per-file summary + --mailback only produce a report in case of warnings/errors + --summary-file include the filename in summary + --debug KEY=[0|1] turn on/off debugging of KEY, where KEY is one of + 'values', 'possible', 'type', and 'attr' (default + is all off) + --test-only=WORD report only warnings/errors containing WORD + literally + --fix EXPERIMENTAL - may create horrible results + If correctable single-line errors exist, create + "<inputfile>.EXPERIMENTAL-checkpatch-fixes" + with potential errors corrected to the preferred + checkpatch style + --fix-inplace EXPERIMENTAL - may create horrible results + Is the same as --fix, but overwrites the input + file. It's your fault if there's no backup or git + --ignore-perl-version override checking of perl version. expect + runtime errors. + --codespell Use the codespell dictionary for spelling/typos + (default:/usr/share/codespell/dictionary.txt) + --codespellfile Use this codespell dictionary + --color Use colors when output is STDOUT (default: on) + -h, --help, --version display this help and exit + +When FILE is - read standard input. +EOM + + exit($exitcode); +} + +my $conf = which_conf($configuration_file); +if (-f $conf) { + my @conf_args; + open(my $conffile, '<', "$conf") + or warn "$P: Can't find a readable $configuration_file file $!\n"; + + while (<$conffile>) { + my $line = $_; + + $line =~ s/\s*\n?$//g; + $line =~ s/^\s*//g; + $line =~ s/\s+/ /g; + + next if ($line =~ m/^\s*#/); + next if ($line =~ m/^\s*$/); + + my @words = split(" ", $line); + foreach my $word (@words) { + last if ($word =~ m/^#/); + push (@conf_args, $word); + } + } + close($conffile); + unshift(@ARGV, @conf_args) if @conf_args; +} + +GetOptions( + 'q|quiet+' => \$quiet, + 'tree!' => \$tree, + 'signoff!' => \$chk_signoff, + 'patch!' => \$chk_patch, + 'emacs!' => \$emacs, + 'terse!' => \$terse, + 'showfile!' => \$showfile, + 'f|file!' => \$file, + 'subjective!' => \$check, + 'strict!' => \$check, + 'ignore=s' => \@ignore, + 'types=s' => \@use, + 'show-types!' => \$show_types, + 'max-line-length=i' => \$max_line_length, + 'min-conf-desc-length=i' => \$min_conf_desc_length, + 'root=s' => \$root, + 'summary!' => \$summary, + 'mailback!' => \$mailback, + 'summary-file!' => \$summary_file, + 'fix!' => \$fix, + 'fix-inplace!' => \$fix_inplace, + 'ignore-perl-version!' => \$ignore_perl_version, + 'debug=s' => \%debug, + 'test-only=s' => \$tst_only, + 'codespell!' => \$codespell, + 'codespellfile=s' => \$codespellfile, + 'color!' => \$color, + 'h|help' => \$help, + 'version' => \$help +) or help(1); + +help(0) if ($help); + +$fix = 1 if ($fix_inplace); +$check_orig = $check; + +my $exit = 0; + +if ($^V && $^V lt $minimum_perl_version) { + printf "$P: requires at least perl version %vd\n", $minimum_perl_version; + if (!$ignore_perl_version) { + exit(1); + } +} + +if ($#ARGV < 0) { + print "$P: no input files\n"; + exit(1); +} + +sub hash_save_array_words { + my ($hashRef, $arrayRef) = @_; + + my @array = split(/,/, join(',', @$arrayRef)); + foreach my $word (@array) { + $word =~ s/\s*\n?$//g; + $word =~ s/^\s*//g; + $word =~ s/\s+/ /g; + $word =~ tr/[a-z]/[A-Z]/; + + next if ($word =~ m/^\s*#/); + next if ($word =~ m/^\s*$/); + + $hashRef->{$word}++; + } +} + +sub hash_show_words { + my ($hashRef, $prefix) = @_; + + if (keys %$hashRef) { + print "\nNOTE: $prefix message types:"; + foreach my $word (sort keys %$hashRef) { + print " $word"; + } + print "\n"; + } +} + +hash_save_array_words(\%ignore_type, \@ignore); +hash_save_array_words(\%use_type, \@use); + +my $dbg_values = 0; +my $dbg_possible = 0; +my $dbg_type = 0; +my $dbg_attr = 0; +for my $key (keys %debug) { + ## no critic + eval "\${dbg_$key} = '$debug{$key}';"; + die "$@" if ($@); +} + +my $rpt_cleaners = 0; + +if ($terse) { + $emacs = 1; + $quiet++; +} + +if ($tree) { + if (defined $root) { + if (!top_of_kernel_tree($root)) { + die "$P: $root: --root does not point at a valid tree\n"; + } + } else { + if (top_of_kernel_tree('.')) { + $root = '.'; + } elsif ($0 =~ m@(.*)/scripts/[^/]*$@ && + top_of_kernel_tree($1)) { + $root = $1; + } + } + + if (!defined $root) { + print "Must be run from the top-level dir. of a kernel tree\n"; + exit(2); + } +} + +my $emitted_corrupt = 0; + +our $Ident = qr{ + [A-Za-z_][A-Za-z\d_]* + (?:\s*\#\#\s*[A-Za-z_][A-Za-z\d_]*)* + }x; +our $Storage = qr{extern|static|asmlinkage}; +our $Sparse = qr{ + __user| + __kernel| + __force| + __iomem| + __pmem| + __must_check| + __init_refok| + __kprobes| + __ref| + __rcu| + __private + }x; +our $InitAttributePrefix = qr{__(?:mem|cpu|dev|net_|)}; +our $InitAttributeData = qr{$InitAttributePrefix(?:initdata\b)}; +our $InitAttributeConst = qr{$InitAttributePrefix(?:initconst\b)}; +our $InitAttributeInit = qr{$InitAttributePrefix(?:init\b)}; +our $InitAttribute = qr{$InitAttributeData|$InitAttributeConst|$InitAttributeInit}; + +# Notes to $Attribute: +# We need \b after 'init' otherwise 'initconst' will cause a false positive in a check +our $Attribute = qr{ + const| + __percpu| + __nocast| + __safe| + __bitwise__| + __packed__| + __packed2__| + __naked| + __maybe_unused| + __always_unused| + __noreturn| + __used| + __cold| + __pure| + __noclone| + __deprecated| + __read_mostly| + __kprobes| + $InitAttribute| + ____cacheline_aligned| + ____cacheline_aligned_in_smp| + ____cacheline_internodealigned_in_smp| + __weak + }x; +our $Modifier; +our $Inline = qr{inline|__always_inline|noinline|__inline|__inline__}; +our $Member = qr{->$Ident|\.$Ident|\[[^]]*\]}; +our $Lval = qr{$Ident(?:$Member)*}; + +our $Int_type = qr{(?i)llu|ull|ll|lu|ul|l|u}; +our $Binary = qr{(?i)0b[01]+$Int_type?}; +our $Hex = qr{(?i)0x[0-9a-f]+$Int_type?}; +our $Int = qr{[0-9]+$Int_type?}; +our $Octal = qr{0[0-7]+$Int_type?}; +our $String = qr{"[X\t]*"}; +our $Float_hex = qr{(?i)0x[0-9a-f]+p-?[0-9]+[fl]?}; +our $Float_dec = qr{(?i)(?:[0-9]+\.[0-9]*|[0-9]*\.[0-9]+)(?:e-?[0-9]+)?[fl]?}; +our $Float_int = qr{(?i)[0-9]+e-?[0-9]+[fl]?}; +our $Float = qr{$Float_hex|$Float_dec|$Float_int}; +our $Constant = qr{$Float|$Binary|$Octal|$Hex|$Int}; +our $Assignment = qr{\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=}; +our $Compare = qr{<=|>=|==|!=|<|(?<!-)>}; +our $Arithmetic = qr{\+|-|\*|\/|%}; +our $Operators = qr{ + <=|>=|==|!=| + =>|->|<<|>>|<|>|!|~| + &&|\|\||,|\^|\+\+|--|&|\||$Arithmetic + }x; + +our $c90_Keywords = qr{do|for|while|if|else|return|goto|continue|switch|default|case|break}x; + +our $BasicType; +our $NonptrType; +our $NonptrTypeMisordered; +our $NonptrTypeWithAttr; +our $Type; +our $TypeMisordered; +our $Declare; +our $DeclareMisordered; + +our $NON_ASCII_UTF8 = qr{ + [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte + | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs + | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte + | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates + | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 + | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 + | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 +}x; + +our $UTF8 = qr{ + [\x09\x0A\x0D\x20-\x7E] # ASCII + | $NON_ASCII_UTF8 +}x; + +our $typeC99Typedefs = qr{(?:__)?(?:[us]_?)?int_?(?:8|16|32|64)_t}; +our $typeOtherOSTypedefs = qr{(?x: + u_(?:char|short|int|long) | # bsd + u(?:nchar|short|int|long) # sysv +)}; +our $typeKernelTypedefs = qr{(?x: + (?:__)?(?:u|s|be|le)(?:8|16|32|64)| + atomic_t +)}; +our $typeTypedefs = qr{(?x: + $typeC99Typedefs\b| + $typeOtherOSTypedefs\b| + $typeKernelTypedefs\b +)}; + +our $zero_initializer = qr{(?:(?:0[xX])?0+$Int_type?|NULL|false)\b}; + +our $logFunctions = qr{(?x: + printk(?:_ratelimited|_once|)| + (?:[a-z0-9]+_){1,2}(?:printk|emerg|alert|crit|err|warning|warn|notice|info|debug|dbg|vdbg|devel|cont|WARN)(?:_ratelimited|_once|)| + WARN(?:_RATELIMIT|_ONCE|)| + panic| + MODULE_[A-Z_]+| + seq_vprintf|seq_printf|seq_puts +)}; + +our $signature_tags = qr{(?xi: + Signed-off-by:| + Acked-by:| + Tested-by:| + Reviewed-by:| + Reported-by:| + Suggested-by:| + To:| + Cc: +)}; + +our @typeListMisordered = ( + qr{char\s+(?:un)?signed}, + qr{int\s+(?:(?:un)?signed\s+)?short\s}, + qr{int\s+short(?:\s+(?:un)?signed)}, + qr{short\s+int(?:\s+(?:un)?signed)}, + qr{(?:un)?signed\s+int\s+short}, + qr{short\s+(?:un)?signed}, + qr{long\s+int\s+(?:un)?signed}, + qr{int\s+long\s+(?:un)?signed}, + qr{long\s+(?:un)?signed\s+int}, + qr{int\s+(?:un)?signed\s+long}, + qr{int\s+(?:un)?signed}, + qr{int\s+long\s+long\s+(?:un)?signed}, + qr{long\s+long\s+int\s+(?:un)?signed}, + qr{long\s+long\s+(?:un)?signed\s+int}, + qr{long\s+long\s+(?:un)?signed}, + qr{long\s+(?:un)?signed}, +); + +our @typeList = ( + qr{void}, + qr{(?:(?:un)?signed\s+)?char}, + qr{(?:(?:un)?signed\s+)?short\s+int}, + qr{(?:(?:un)?signed\s+)?short}, + qr{(?:(?:un)?signed\s+)?int}, + qr{(?:(?:un)?signed\s+)?long\s+int}, + qr{(?:(?:un)?signed\s+)?long\s+long\s+int}, + qr{(?:(?:un)?signed\s+)?long\s+long}, + qr{(?:(?:un)?signed\s+)?long}, + qr{(?:un)?signed}, + qr{float}, + qr{double}, + qr{bool}, + qr{struct\s+$Ident}, + qr{union\s+$Ident}, + qr{enum\s+$Ident}, + qr{${Ident}_t}, + qr{${Ident}_handler}, + qr{${Ident}_handler_fn}, + @typeListMisordered, +); + +our $C90_int_types = qr{(?x: + long\s+long\s+int\s+(?:un)?signed| + long\s+long\s+(?:un)?signed\s+int| + long\s+long\s+(?:un)?signed| + (?:(?:un)?signed\s+)?long\s+long\s+int| + (?:(?:un)?signed\s+)?long\s+long| + int\s+long\s+long\s+(?:un)?signed| + int\s+(?:(?:un)?signed\s+)?long\s+long| + + long\s+int\s+(?:un)?signed| + long\s+(?:un)?signed\s+int| + long\s+(?:un)?signed| + (?:(?:un)?signed\s+)?long\s+int| + (?:(?:un)?signed\s+)?long| + int\s+long\s+(?:un)?signed| + int\s+(?:(?:un)?signed\s+)?long| + + int\s+(?:un)?signed| + (?:(?:un)?signed\s+)?int +)}; + +our @typeListFile = (); +our @typeListWithAttr = ( + @typeList, + qr{struct\s+$InitAttribute\s+$Ident}, + qr{union\s+$InitAttribute\s+$Ident}, +); + +our @modifierList = ( + qr{fastcall}, +); +our @modifierListFile = (); + +our @mode_permission_funcs = ( + ["module_param", 3], + ["module_param_(?:array|named|string)", 4], + ["module_param_array_named", 5], + ["debugfs_create_(?:file|u8|u16|u32|u64|x8|x16|x32|x64|size_t|atomic_t|bool|blob|regset32|u32_array)", 2], + ["proc_create(?:_data|)", 2], + ["(?:CLASS|DEVICE|SENSOR)_ATTR", 2], +); + +#Create a search pattern for all these functions to speed up a loop below +our $mode_perms_search = ""; +foreach my $entry (@mode_permission_funcs) { + $mode_perms_search .= '|' if ($mode_perms_search ne ""); + $mode_perms_search .= $entry->[0]; +} + +our $mode_perms_world_writable = qr{ + S_IWUGO | + S_IWOTH | + S_IRWXUGO | + S_IALLUGO | + 0[0-7][0-7][2367] +}x; + +our $allowed_asm_includes = qr{(?x: + irq| + memory| + time| + reboot +)}; +# memory.h: ARM has a custom one + +# Load common spelling mistakes and build regular expression list. +my $misspellings; +my %spelling_fix; + +if (open(my $spelling, '<', $spelling_file)) { + while (<$spelling>) { + my $line = $_; + + $line =~ s/\s*\n?$//g; + $line =~ s/^\s*//g; + + next if ($line =~ m/^\s*#/); + next if ($line =~ m/^\s*$/); + + my ($suspect, $fix) = split(/\|\|/, $line); + + $spelling_fix{$suspect} = $fix; + } + close($spelling); +} else { + warn "No typos will be found - file '$spelling_file': $!\n"; +} + +if ($codespell) { + if (open(my $spelling, '<', $codespellfile)) { + while (<$spelling>) { + my $line = $_; + + $line =~ s/\s*\n?$//g; + $line =~ s/^\s*//g; + + next if ($line =~ m/^\s*#/); + next if ($line =~ m/^\s*$/); + next if ($line =~ m/, disabled/i); + + $line =~ s/,.*$//; + + my ($suspect, $fix) = split(/->/, $line); + + $spelling_fix{$suspect} = $fix; + } + close($spelling); + } else { + warn "No codespell typos will be found - file '$codespellfile': $!\n"; + } +} + +$misspellings = join("|", sort keys %spelling_fix) if keys %spelling_fix; + +sub build_types { + my $mods = "(?x: \n" . join("|\n ", (@modifierList, @modifierListFile)) . "\n)"; + my $all = "(?x: \n" . join("|\n ", (@typeList, @typeListFile)) . "\n)"; + my $Misordered = "(?x: \n" . join("|\n ", @typeListMisordered) . "\n)"; + my $allWithAttr = "(?x: \n" . join("|\n ", @typeListWithAttr) . "\n)"; + $Modifier = qr{(?:$Attribute|$Sparse|$mods)}; + $BasicType = qr{ + (?:$typeTypedefs\b)| + (?:${all}\b) + }x; + $NonptrType = qr{ + (?:$Modifier\s+|const\s+)* + (?: + (?:typeof|__typeof__)\s*\([^\)]*\)| + (?:$typeTypedefs\b)| + (?:${all}\b) + ) + (?:\s+$Modifier|\s+const)* + }x; + $NonptrTypeMisordered = qr{ + (?:$Modifier\s+|const\s+)* + (?: + (?:${Misordered}\b) + ) + (?:\s+$Modifier|\s+const)* + }x; + $NonptrTypeWithAttr = qr{ + (?:$Modifier\s+|const\s+)* + (?: + (?:typeof|__typeof__)\s*\([^\)]*\)| + (?:$typeTypedefs\b)| + (?:${allWithAttr}\b) + ) + (?:\s+$Modifier|\s+const)* + }x; + $Type = qr{ + $NonptrType + (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+)? + (?:\s+$Inline|\s+$Modifier)* + }x; + $TypeMisordered = qr{ + $NonptrTypeMisordered + (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+)? + (?:\s+$Inline|\s+$Modifier)* + }x; + $Declare = qr{(?:$Storage\s+(?:$Inline\s+)?)?$Type}; + $DeclareMisordered = qr{(?:$Storage\s+(?:$Inline\s+)?)?$TypeMisordered}; +} +build_types(); + +our $Typecast = qr{\s*(\(\s*$NonptrType\s*\)){0,1}\s*}; + +# Using $balanced_parens, $LvalOrFunc, or $FuncArg +# requires at least perl version v5.10.0 +# Any use must be runtime checked with $^V + +our $balanced_parens = qr/(\((?:[^\(\)]++|(?-1))*\))/; +our $LvalOrFunc = qr{((?:[\&\*]\s*)?$Lval)\s*($balanced_parens{0,1})\s*}; +our $FuncArg = qr{$Typecast{0,1}($LvalOrFunc|$Constant|$String)}; + +our $declaration_macros = qr{(?x: + (?:$Storage\s+)?(?:[A-Z_][A-Z0-9]*_){0,2}(?:DEFINE|DECLARE)(?:_[A-Z0-9]+){1,6}\s*\(| + (?:$Storage\s+)?LIST_HEAD\s*\(| + (?:$Storage\s+)?${Type}\s+uninitialized_var\s*\( +)}; + +sub deparenthesize { + my ($string) = @_; + return "" if (!defined($string)); + + while ($string =~ /^\s*\(.*\)\s*$/) { + $string =~ s@^\s*\(\s*@@; + $string =~ s@\s*\)\s*$@@; + } + + $string =~ s@\s+@ @g; + + return $string; +} + +sub seed_camelcase_file { + my ($file) = @_; + + return if (!(-f $file)); + + local $/; + + open(my $include_file, '<', "$file") + or warn "$P: Can't read '$file' $!\n"; + my $text = <$include_file>; + close($include_file); + + my @lines = split('\n', $text); + + foreach my $line (@lines) { + next if ($line !~ /(?:[A-Z][a-z]|[a-z][A-Z])/); + if ($line =~ /^[ \t]*(?:#[ \t]*define|typedef\s+$Type)\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)/) { + $camelcase{$1} = 1; + } elsif ($line =~ /^\s*$Declare\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)\s*[\(\[,;]/) { + $camelcase{$1} = 1; + } elsif ($line =~ /^\s*(?:union|struct|enum)\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)\s*[;\{]/) { + $camelcase{$1} = 1; + } + } +} + +my $camelcase_seeded = 0; +sub seed_camelcase_includes { + return if ($camelcase_seeded); + + my $files; + my $camelcase_cache = ""; + my @include_files = (); + + $camelcase_seeded = 1; + + if (-e ".git") { + my $git_last_include_commit = `git log --no-merges --pretty=format:"%h%n" -1 -- include`; + chomp $git_last_include_commit; + $camelcase_cache = ".checkpatch-camelcase.git.$git_last_include_commit"; + } else { + my $last_mod_date = 0; + $files = `find $root/include -name "*.h"`; + @include_files = split('\n', $files); + foreach my $file (@include_files) { + my $date = POSIX::strftime("%Y%m%d%H%M", + localtime((stat $file)[9])); + $last_mod_date = $date if ($last_mod_date < $date); + } + $camelcase_cache = ".checkpatch-camelcase.date.$last_mod_date"; + } + + if ($camelcase_cache ne "" && -f $camelcase_cache) { + open(my $camelcase_file, '<', "$camelcase_cache") + or warn "$P: Can't read '$camelcase_cache' $!\n"; + while (<$camelcase_file>) { + chomp; + $camelcase{$_} = 1; + } + close($camelcase_file); + + return; + } + + if (-e ".git") { + $files = `git ls-files "include/*.h"`; + @include_files = split('\n', $files); + } + + foreach my $file (@include_files) { + seed_camelcase_file($file); + } + + if ($camelcase_cache ne "") { + unlink glob ".checkpatch-camelcase.*"; + open(my $camelcase_file, '>', "$camelcase_cache") + or warn "$P: Can't write '$camelcase_cache' $!\n"; + foreach (sort { lc($a) cmp lc($b) } keys(%camelcase)) { + print $camelcase_file ("$_\n"); + } + close($camelcase_file); + } +} + +sub git_commit_info { + my ($commit, $id, $desc) = @_; + + return ($id, $desc) if ((which("git") eq "") || !(-e ".git")); + + my $output = `git log --no-color --format='%H %s' -1 $commit 2>&1`; + $output =~ s/^\s*//gm; + my @lines = split("\n", $output); + + return ($id, $desc) if ($#lines < 0); + + if ($lines[0] =~ /^error: short SHA1 $commit is ambiguous\./) { +# Maybe one day convert this block of bash into something that returns +# all matching commit ids, but it's very slow... +# +# echo "checking commits $1..." +# git rev-list --remotes | grep -i "^$1" | +# while read line ; do +# git log --format='%H %s' -1 $line | +# echo "commit $(cut -c 1-12,41-)" +# done + } elsif ($lines[0] =~ /^fatal: ambiguous argument '$commit': unknown revision or path not in the working tree\./) { + } else { + $id = substr($lines[0], 0, 12); + $desc = substr($lines[0], 41); + } + + return ($id, $desc); +} + +$chk_signoff = 0 if ($file); + +my @rawlines = (); +my @lines = (); +my @fixed = (); +my @fixed_inserted = (); +my @fixed_deleted = (); +my $fixlinenr = -1; + +my $vname; +for my $filename (@ARGV) { + my $FILE; + if ($file) { + open($FILE, '-|', "diff -u /dev/null $filename") || + die "$P: $filename: diff failed - $!\n"; + } elsif ($filename eq '-') { + open($FILE, '<&STDIN'); + } else { + open($FILE, '<', "$filename") || + die "$P: $filename: open failed - $!\n"; + } + if ($filename eq '-') { + $vname = 'Your patch'; + } else { + $vname = $filename; + } + while (<$FILE>) { + chomp; + push(@rawlines, $_); + } + close($FILE); + + if ($#ARGV > 0 && $quiet == 0) { + print '-' x length($vname) . "\n"; + print "$vname\n"; + print '-' x length($vname) . "\n"; + } + + if (!process($filename)) { + $exit = 1; + } + @rawlines = (); + @lines = (); + @fixed = (); + @fixed_inserted = (); + @fixed_deleted = (); + $fixlinenr = -1; + @modifierListFile = (); + @typeListFile = (); + build_types(); +} + +if (!$quiet) { + hash_show_words(\%use_type, "Used"); + hash_show_words(\%ignore_type, "Ignored"); + + if ($^V lt 5.10.0) { + print << "EOM" + +NOTE: perl $^V is not modern enough to detect all possible issues. + An upgrade to at least perl v5.10.0 is suggested. +EOM + } + if ($exit) { + print << "EOM" + +NOTE: If any of the errors are false positives, please report + them to the maintainer, see CHECKPATCH in MAINTAINERS. +EOM + } +} + +exit($exit); + +sub top_of_kernel_tree { + my ($root) = @_; + + my @tree_check = ( + "COPYING", "CREDITS", "Kbuild", "MAINTAINERS", "Makefile", + "README", "Documentation", "arch", "include", "drivers", + "fs", "init", "ipc", "kernel", "lib", "scripts", + ); + + foreach my $check (@tree_check) { + if (! -e $root . '/' . $check) { + return 0; + } + } + return 1; +} + +sub parse_email { + my ($formatted_email) = @_; + + my $name = ""; + my $address = ""; + my $comment = ""; + + if ($formatted_email =~ /^(.*)<(\S+\@\S+)>(.*)$/) { + $name = $1; + $address = $2; + $comment = $3 if defined $3; + } elsif ($formatted_email =~ /^\s*<(\S+\@\S+)>(.*)$/) { + $address = $1; + $comment = $2 if defined $2; + } elsif ($formatted_email =~ /(\S+\@\S+)(.*)$/) { + $address = $1; + $comment = $2 if defined $2; + $formatted_email =~ s/$address.*$//; + $name = $formatted_email; + $name = trim($name); + $name =~ s/^\"|\"$//g; + # If there's a name left after stripping spaces and + # leading quotes, and the address doesn't have both + # leading and trailing angle brackets, the address + # is invalid. ie: + # "joe smith joe@smith.com" bad + # "joe smith <joe@smith.com" bad + if ($name ne "" && $address !~ /^<[^>]+>$/) { + $name = ""; + $address = ""; + $comment = ""; + } + } + + $name = trim($name); + $name =~ s/^\"|\"$//g; + $address = trim($address); + $address =~ s/^\<|\>$//g; + + if ($name =~ /[^\w \-]/i) { ##has "must quote" chars + $name =~ s/(?<!\\)"/\\"/g; ##escape quotes + $name = "\"$name\""; + } + + return ($name, $address, $comment); +} + +sub format_email { + my ($name, $address) = @_; + + my $formatted_email; + + $name = trim($name); + $name =~ s/^\"|\"$//g; + $address = trim($address); + + if ($name =~ /[^\w \-]/i) { ##has "must quote" chars + $name =~ s/(?<!\\)"/\\"/g; ##escape quotes + $name = "\"$name\""; + } + + if ("$name" eq "") { + $formatted_email = "$address"; + } else { + $formatted_email = "$name <$address>"; + } + + return $formatted_email; +} + +sub which { + my ($bin) = @_; + + foreach my $path (split(/:/, $ENV{PATH})) { + if (-e "$path/$bin") { + return "$path/$bin"; + } + } + + return ""; +} + +sub which_conf { + my ($conf) = @_; + + foreach my $path (split(/:/, ".:$ENV{HOME}:.scripts")) { + if (-e "$path/$conf") { + return "$path/$conf"; + } + } + + return ""; +} + +sub expand_tabs { + my ($str) = @_; + + my $res = ''; + my $n = 0; + for my $c (split(//, $str)) { + if ($c eq "\t") { + $res .= ' '; + $n++; + for (; ($n % 8) != 0; $n++) { + $res .= ' '; + } + next; + } + $res .= $c; + $n++; + } + + return $res; +} +sub copy_spacing { + (my $res = shift) =~ tr/\t/ /c; + return $res; +} + +sub line_stats { + my ($line) = @_; + + # Drop the diff line leader and expand tabs + $line =~ s/^.//; + $line = expand_tabs($line); + + # Pick the indent from the front of the line. + my ($white) = ($line =~ /^(\s*)/); + + return (length($line), length($white)); +} + +my $sanitise_quote = ''; + +sub sanitise_line_reset { + my ($in_comment) = @_; + + if ($in_comment) { + $sanitise_quote = '*/'; + } else { + $sanitise_quote = ''; + } +} +sub sanitise_line { + my ($line) = @_; + + my $res = ''; + my $l = ''; + + my $qlen = 0; + my $off = 0; + my $c; + + # Always copy over the diff marker. + $res = substr($line, 0, 1); + + for ($off = 1; $off < length($line); $off++) { + $c = substr($line, $off, 1); + + # Comments we are wacking completly including the begin + # and end, all to $;. + if ($sanitise_quote eq '' && substr($line, $off, 2) eq '/*') { + $sanitise_quote = '*/'; + + substr($res, $off, 2, "$;$;"); + $off++; + next; + } + if ($sanitise_quote eq '*/' && substr($line, $off, 2) eq '*/') { + $sanitise_quote = ''; + substr($res, $off, 2, "$;$;"); + $off++; + next; + } + if ($sanitise_quote eq '' && substr($line, $off, 2) eq '//') { + $sanitise_quote = '//'; + + substr($res, $off, 2, $sanitise_quote); + $off++; + next; + } + + # A \ in a string means ignore the next character. + if (($sanitise_quote eq "'" || $sanitise_quote eq '"') && + $c eq "\\") { + substr($res, $off, 2, 'XX'); + $off++; + next; + } + # Regular quotes. + if ($c eq "'" || $c eq '"') { + if ($sanitise_quote eq '') { + $sanitise_quote = $c; + + substr($res, $off, 1, $c); + next; + } elsif ($sanitise_quote eq $c) { + $sanitise_quote = ''; + } + } + + #print "c<$c> SQ<$sanitise_quote>\n"; + if ($off != 0 && $sanitise_quote eq '*/' && $c ne "\t") { + substr($res, $off, 1, $;); + } elsif ($off != 0 && $sanitise_quote eq '//' && $c ne "\t") { + substr($res, $off, 1, $;); + } elsif ($off != 0 && $sanitise_quote && $c ne "\t") { + substr($res, $off, 1, 'X'); + } else { + substr($res, $off, 1, $c); + } + } + + if ($sanitise_quote eq '//') { + $sanitise_quote = ''; + } + + # The pathname on a #include may be surrounded by '<' and '>'. + if ($res =~ /^.\s*\#\s*include\s+\<(.*)\>/) { + my $clean = 'X' x length($1); + $res =~ s@\<.*\>@<$clean>@; + + # The whole of a #error is a string. + } elsif ($res =~ /^.\s*\#\s*(?:error|warning)\s+(.*)\b/) { + my $clean = 'X' x length($1); + $res =~ s@(\#\s*(?:error|warning)\s+).*@$1$clean@; + } + + return $res; +} + +sub get_quoted_string { + my ($line, $rawline) = @_; + + return "" if ($line !~ m/($String)/g); + return substr($rawline, $-[0], $+[0] - $-[0]); +} + +sub ctx_statement_block { + my ($linenr, $remain, $off) = @_; + my $line = $linenr - 1; + my $blk = ''; + my $soff = $off; + my $coff = $off - 1; + my $coff_set = 0; + + my $loff = 0; + + my $type = ''; + my $level = 0; + my @stack = (); + my $p; + my $c; + my $len = 0; + + my $remainder; + while (1) { + @stack = (['', 0]) if ($#stack == -1); + + #warn "CSB: blk<$blk> remain<$remain>\n"; + # If we are about to drop off the end, pull in more + # context. + if ($off >= $len) { + for (; $remain > 0; $line++) { + last if (!defined $lines[$line]); + next if ($lines[$line] =~ /^-/); + $remain--; + $loff = $len; + $blk .= $lines[$line] . "\n"; + $len = length($blk); + $line++; + last; + } + # Bail if there is no further context. + #warn "CSB: blk<$blk> off<$off> len<$len>\n"; + if ($off >= $len) { + last; + } + if ($level == 0 && substr($blk, $off) =~ /^.\s*#\s*define/) { + $level++; + $type = '#'; + } + } + $p = $c; + $c = substr($blk, $off, 1); + $remainder = substr($blk, $off); + + #warn "CSB: c<$c> type<$type> level<$level> remainder<$remainder> coff_set<$coff_set>\n"; + + # Handle nested #if/#else. + if ($remainder =~ /^#\s*(?:ifndef|ifdef|if)\s/) { + push(@stack, [ $type, $level ]); + } elsif ($remainder =~ /^#\s*(?:else|elif)\b/) { + ($type, $level) = @{$stack[$#stack - 1]}; + } elsif ($remainder =~ /^#\s*endif\b/) { + ($type, $level) = @{pop(@stack)}; + } + + # Statement ends at the ';' or a close '}' at the + # outermost level. + if ($level == 0 && $c eq ';') { + last; + } + + # An else is really a conditional as long as its not else if + if ($level == 0 && $coff_set == 0 && + (!defined($p) || $p =~ /(?:\s|\}|\+)/) && + $remainder =~ /^(else)(?:\s|{)/ && + $remainder !~ /^else\s+if\b/) { + $coff = $off + length($1) - 1; + $coff_set = 1; + #warn "CSB: mark coff<$coff> soff<$soff> 1<$1>\n"; + #warn "[" . substr($blk, $soff, $coff - $soff + 1) . "]\n"; + } + + if (($type eq '' || $type eq '(') && $c eq '(') { + $level++; + $type = '('; + } + if ($type eq '(' && $c eq ')') { + $level--; + $type = ($level != 0)? '(' : ''; + + if ($level == 0 && $coff < $soff) { + $coff = $off; + $coff_set = 1; + #warn "CSB: mark coff<$coff>\n"; + } + } + if (($type eq '' || $type eq '{') && $c eq '{') { + $level++; + $type = '{'; + } + if ($type eq '{' && $c eq '}') { + $level--; + $type = ($level != 0)? '{' : ''; + + if ($level == 0) { + if (substr($blk, $off + 1, 1) eq ';') { + $off++; + } + last; + } + } + # Preprocessor commands end at the newline unless escaped. + if ($type eq '#' && $c eq "\n" && $p ne "\\") { + $level--; + $type = ''; + $off++; + last; + } + $off++; + } + # We are truly at the end, so shuffle to the next line. + if ($off == $len) { + $loff = $len + 1; + $line++; + $remain--; + } + + my $statement = substr($blk, $soff, $off - $soff + 1); + my $condition = substr($blk, $soff, $coff - $soff + 1); + + #warn "STATEMENT<$statement>\n"; + #warn "CONDITION<$condition>\n"; + + #print "coff<$coff> soff<$off> loff<$loff>\n"; + + return ($statement, $condition, + $line, $remain + 1, $off - $loff + 1, $level); +} + +sub statement_lines { + my ($stmt) = @_; + + # Strip the diff line prefixes and rip blank lines at start and end. + $stmt =~ s/(^|\n)./$1/g; + $stmt =~ s/^\s*//; + $stmt =~ s/\s*$//; + + my @stmt_lines = ($stmt =~ /\n/g); + + return $#stmt_lines + 2; +} + +sub statement_rawlines { + my ($stmt) = @_; + + my @stmt_lines = ($stmt =~ /\n/g); + + return $#stmt_lines + 2; +} + +sub statement_block_size { + my ($stmt) = @_; + + $stmt =~ s/(^|\n)./$1/g; + $stmt =~ s/^\s*{//; + $stmt =~ s/}\s*$//; + $stmt =~ s/^\s*//; + $stmt =~ s/\s*$//; + + my @stmt_lines = ($stmt =~ /\n/g); + my @stmt_statements = ($stmt =~ /;/g); + + my $stmt_lines = $#stmt_lines + 2; + my $stmt_statements = $#stmt_statements + 1; + + if ($stmt_lines > $stmt_statements) { + return $stmt_lines; + } else { + return $stmt_statements; + } +} + +sub ctx_statement_full { + my ($linenr, $remain, $off) = @_; + my ($statement, $condition, $level); + + my (@chunks); + + # Grab the first conditional/block pair. + ($statement, $condition, $linenr, $remain, $off, $level) = + ctx_statement_block($linenr, $remain, $off); + #print "F: c<$condition> s<$statement> remain<$remain>\n"; + push(@chunks, [ $condition, $statement ]); + if (!($remain > 0 && $condition =~ /^\s*(?:\n[+-])?\s*(?:if|else|do)\b/s)) { + return ($level, $linenr, @chunks); + } + + # Pull in the following conditional/block pairs and see if they + # could continue the statement. + for (;;) { + ($statement, $condition, $linenr, $remain, $off, $level) = + ctx_statement_block($linenr, $remain, $off); + #print "C: c<$condition> s<$statement> remain<$remain>\n"; + last if (!($remain > 0 && $condition =~ /^(?:\s*\n[+-])*\s*(?:else|do)\b/s)); + #print "C: push\n"; + push(@chunks, [ $condition, $statement ]); + } + + return ($level, $linenr, @chunks); +} + +sub ctx_block_get { + my ($linenr, $remain, $outer, $open, $close, $off) = @_; + my $line; + my $start = $linenr - 1; + my $blk = ''; + my @o; + my @c; + my @res = (); + + my $level = 0; + my @stack = ($level); + for ($line = $start; $remain > 0; $line++) { + next if ($rawlines[$line] =~ /^-/); + $remain--; + + $blk .= $rawlines[$line]; + + # Handle nested #if/#else. + if ($lines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) { + push(@stack, $level); + } elsif ($lines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) { + $level = $stack[$#stack - 1]; + } elsif ($lines[$line] =~ /^.\s*#\s*endif\b/) { + $level = pop(@stack); + } + + foreach my $c (split(//, $lines[$line])) { + ##print "C<$c>L<$level><$open$close>O<$off>\n"; + if ($off > 0) { + $off--; + next; + } + + if ($c eq $close && $level > 0) { + $level--; + last if ($level == 0); + } elsif ($c eq $open) { + $level++; + } + } + + if (!$outer || $level <= 1) { + push(@res, $rawlines[$line]); + } + + last if ($level == 0); + } + + return ($level, @res); +} +sub ctx_block_outer { + my ($linenr, $remain) = @_; + + my ($level, @r) = ctx_block_get($linenr, $remain, 1, '{', '}', 0); + return @r; +} +sub ctx_block { + my ($linenr, $remain) = @_; + + my ($level, @r) = ctx_block_get($linenr, $remain, 0, '{', '}', 0); + return @r; +} +sub ctx_statement { + my ($linenr, $remain, $off) = @_; + + my ($level, @r) = ctx_block_get($linenr, $remain, 0, '(', ')', $off); + return @r; +} +sub ctx_block_level { + my ($linenr, $remain) = @_; + + return ctx_block_get($linenr, $remain, 0, '{', '}', 0); +} +sub ctx_statement_level { + my ($linenr, $remain, $off) = @_; + + return ctx_block_get($linenr, $remain, 0, '(', ')', $off); +} + +sub ctx_locate_comment { + my ($first_line, $end_line) = @_; + + # Catch a comment on the end of the line itself. + my ($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*(?:\\\s*)?$@); + return $current_comment if (defined $current_comment); + + # Look through the context and try and figure out if there is a + # comment. + my $in_comment = 0; + $current_comment = ''; + for (my $linenr = $first_line; $linenr < $end_line; $linenr++) { + my $line = $rawlines[$linenr - 1]; + #warn " $line\n"; + if ($linenr == $first_line and $line =~ m@^.\s*\*@) { + $in_comment = 1; + } + if ($line =~ m@/\*@) { + $in_comment = 1; + } + if (!$in_comment && $current_comment ne '') { + $current_comment = ''; + } + $current_comment .= $line . "\n" if ($in_comment); + if ($line =~ m@\*/@) { + $in_comment = 0; + } + } + + chomp($current_comment); + return($current_comment); +} +sub ctx_has_comment { + my ($first_line, $end_line) = @_; + my $cmt = ctx_locate_comment($first_line, $end_line); + + ##print "LINE: $rawlines[$end_line - 1 ]\n"; + ##print "CMMT: $cmt\n"; + + return ($cmt ne ''); +} + +sub raw_line { + my ($linenr, $cnt) = @_; + + my $offset = $linenr - 1; + $cnt++; + + my $line; + while ($cnt) { + $line = $rawlines[$offset++]; + next if (defined($line) && $line =~ /^-/); + $cnt--; + } + + return $line; +} + +sub cat_vet { + my ($vet) = @_; + my ($res, $coded); + + $res = ''; + while ($vet =~ /([^[:cntrl:]]*)([[:cntrl:]]|$)/g) { + $res .= $1; + if ($2 ne '') { + $coded = sprintf("^%c", unpack('C', $2) + 64); + $res .= $coded; + } + } + $res =~ s/$/\$/; + + return $res; +} + +my $av_preprocessor = 0; +my $av_pending; +my @av_paren_type; +my $av_pend_colon; + +sub annotate_reset { + $av_preprocessor = 0; + $av_pending = '_'; + @av_paren_type = ('E'); + $av_pend_colon = 'O'; +} + +sub annotate_values { + my ($stream, $type) = @_; + + my $res; + my $var = '_' x length($stream); + my $cur = $stream; + + print "$stream\n" if ($dbg_values > 1); + + while (length($cur)) { + @av_paren_type = ('E') if ($#av_paren_type < 0); + print " <" . join('', @av_paren_type) . + "> <$type> <$av_pending>" if ($dbg_values > 1); + if ($cur =~ /^(\s+)/o) { + print "WS($1)\n" if ($dbg_values > 1); + if ($1 =~ /\n/ && $av_preprocessor) { + $type = pop(@av_paren_type); + $av_preprocessor = 0; + } + + } elsif ($cur =~ /^(\(\s*$Type\s*)\)/ && $av_pending eq '_') { + print "CAST($1)\n" if ($dbg_values > 1); + push(@av_paren_type, $type); + $type = 'c'; + + } elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\(|\s*$)/) { + print "DECLARE($1)\n" if ($dbg_values > 1); + $type = 'T'; + + } elsif ($cur =~ /^($Modifier)\s*/) { + print "MODIFIER($1)\n" if ($dbg_values > 1); + $type = 'T'; + + } elsif ($cur =~ /^(\#\s*define\s*$Ident)(\(?)/o) { + print "DEFINE($1,$2)\n" if ($dbg_values > 1); + $av_preprocessor = 1; + push(@av_paren_type, $type); + if ($2 ne '') { + $av_pending = 'N'; + } + $type = 'E'; + + } elsif ($cur =~ /^(\#\s*(?:undef\s*$Ident|include\b))/o) { + print "UNDEF($1)\n" if ($dbg_values > 1); + $av_preprocessor = 1; + push(@av_paren_type, $type); + + } elsif ($cur =~ /^(\#\s*(?:ifdef|ifndef|if))/o) { + print "PRE_START($1)\n" if ($dbg_values > 1); + $av_preprocessor = 1; + + push(@av_paren_type, $type); + push(@av_paren_type, $type); + $type = 'E'; + + } elsif ($cur =~ /^(\#\s*(?:else|elif))/o) { + print "PRE_RESTART($1)\n" if ($dbg_values > 1); + $av_preprocessor = 1; + + push(@av_paren_type, $av_paren_type[$#av_paren_type]); + + $type = 'E'; + + } elsif ($cur =~ /^(\#\s*(?:endif))/o) { + print "PRE_END($1)\n" if ($dbg_values > 1); + + $av_preprocessor = 1; + + # Assume all arms of the conditional end as this + # one does, and continue as if the #endif was not here. + pop(@av_paren_type); + push(@av_paren_type, $type); + $type = 'E'; + + } elsif ($cur =~ /^(\\\n)/o) { + print "PRECONT($1)\n" if ($dbg_values > 1); + + } elsif ($cur =~ /^(__attribute__)\s*\(?/o) { + print "ATTR($1)\n" if ($dbg_values > 1); + $av_pending = $type; + $type = 'N'; + + } elsif ($cur =~ /^(sizeof)\s*(\()?/o) { + print "SIZEOF($1)\n" if ($dbg_values > 1); + if (defined $2) { + $av_pending = 'V'; + } + $type = 'N'; + + } elsif ($cur =~ /^(if|while|for)\b/o) { + print "COND($1)\n" if ($dbg_values > 1); + $av_pending = 'E'; + $type = 'N'; + + } elsif ($cur =~/^(case)/o) { + print "CASE($1)\n" if ($dbg_values > 1); + $av_pend_colon = 'C'; + $type = 'N'; + + } elsif ($cur =~/^(return|else|goto|typeof|__typeof__)\b/o) { + print "KEYWORD($1)\n" if ($dbg_values > 1); + $type = 'N'; + + } elsif ($cur =~ /^(\()/o) { + print "PAREN('$1')\n" if ($dbg_values > 1); + push(@av_paren_type, $av_pending); + $av_pending = '_'; + $type = 'N'; + + } elsif ($cur =~ /^(\))/o) { + my $new_type = pop(@av_paren_type); + if ($new_type ne '_') { + $type = $new_type; + print "PAREN('$1') -> $type\n" + if ($dbg_values > 1); + } else { + print "PAREN('$1')\n" if ($dbg_values > 1); + } + + } elsif ($cur =~ /^($Ident)\s*\(/o) { + print "FUNC($1)\n" if ($dbg_values > 1); + $type = 'V'; + $av_pending = 'V'; + + } elsif ($cur =~ /^($Ident\s*):(?:\s*\d+\s*(,|=|;))?/) { + if (defined $2 && $type eq 'C' || $type eq 'T') { + $av_pend_colon = 'B'; + } elsif ($type eq 'E') { + $av_pend_colon = 'L'; + } + print "IDENT_COLON($1,$type>$av_pend_colon)\n" if ($dbg_values > 1); + $type = 'V'; + + } elsif ($cur =~ /^($Ident|$Constant)/o) { + print "IDENT($1)\n" if ($dbg_values > 1); + $type = 'V'; + + } elsif ($cur =~ /^($Assignment)/o) { + print "ASSIGN($1)\n" if ($dbg_values > 1); + $type = 'N'; + + } elsif ($cur =~/^(;|{|})/) { + print "END($1)\n" if ($dbg_values > 1); + $type = 'E'; + $av_pend_colon = 'O'; + + } elsif ($cur =~/^(,)/) { + print "COMMA($1)\n" if ($dbg_values > 1); + $type = 'C'; + + } elsif ($cur =~ /^(\?)/o) { + print "QUESTION($1)\n" if ($dbg_values > 1); + $type = 'N'; + + } elsif ($cur =~ /^(:)/o) { + print "COLON($1,$av_pend_colon)\n" if ($dbg_values > 1); + + substr($var, length($res), 1, $av_pend_colon); + if ($av_pend_colon eq 'C' || $av_pend_colon eq 'L') { + $type = 'E'; + } else { + $type = 'N'; + } + $av_pend_colon = 'O'; + + } elsif ($cur =~ /^(\[)/o) { + print "CLOSE($1)\n" if ($dbg_values > 1); + $type = 'N'; + + } elsif ($cur =~ /^(-(?![->])|\+(?!\+)|\*|\&\&|\&)/o) { + my $variant; + + print "OPV($1)\n" if ($dbg_values > 1); + if ($type eq 'V') { + $variant = 'B'; + } else { + $variant = 'U'; + } + + substr($var, length($res), 1, $variant); + $type = 'N'; + + } elsif ($cur =~ /^($Operators)/o) { + print "OP($1)\n" if ($dbg_values > 1); + if ($1 ne '++' && $1 ne '--') { + $type = 'N'; + } + + } elsif ($cur =~ /(^.)/o) { + print "C($1)\n" if ($dbg_values > 1); + } + if (defined $1) { + $cur = substr($cur, length($1)); + $res .= $type x length($1); + } + } + + return ($res, $var); +} + +sub possible { + my ($possible, $line) = @_; + my $notPermitted = qr{(?: + ^(?: + $Modifier| + $Storage| + $Type| + DEFINE_\S+ + )$| + ^(?: + goto| + return| + case| + else| + asm|__asm__| + do| + \#| + \#\#| + )(?:\s|$)| + ^(?:typedef|struct|enum)\b + )}x; + warn "CHECK<$possible> ($line)\n" if ($dbg_possible > 2); + if ($possible !~ $notPermitted) { + # Check for modifiers. + $possible =~ s/\s*$Storage\s*//g; + $possible =~ s/\s*$Sparse\s*//g; + if ($possible =~ /^\s*$/) { + + } elsif ($possible =~ /\s/) { + $possible =~ s/\s*$Type\s*//g; + for my $modifier (split(' ', $possible)) { + if ($modifier !~ $notPermitted) { + warn "MODIFIER: $modifier ($possible) ($line)\n" if ($dbg_possible); + push(@modifierListFile, $modifier); + } + } + + } else { + warn "POSSIBLE: $possible ($line)\n" if ($dbg_possible); + push(@typeListFile, $possible); + } + build_types(); + } else { + warn "NOTPOSS: $possible ($line)\n" if ($dbg_possible > 1); + } +} + +my $prefix = ''; + +sub show_type { + my ($type) = @_; + + return defined $use_type{$type} if (scalar keys %use_type > 0); + + return !defined $ignore_type{$type}; +} + +sub report { + my ($level, $type, $msg) = @_; + + if (!show_type($type) || + (defined $tst_only && $msg !~ /\Q$tst_only\E/)) { + return 0; + } + my $output = ''; + if (-t STDOUT && $color) { + if ($level eq 'ERROR') { + $output .= RED; + } elsif ($level eq 'WARNING') { + $output .= YELLOW; + } else { + $output .= GREEN; + } + } + $output .= $prefix . $level . ':'; + if ($show_types) { + $output .= BLUE if (-t STDOUT && $color); + $output .= "$type:"; + } + $output .= RESET if (-t STDOUT && $color); + $output .= ' ' . $msg . "\n"; + + if ($showfile) { + my @lines = split("\n", $output, -1); + splice(@lines, 1, 1); + $output = join("\n", @lines); + } + $output = (split('\n', $output))[0] . "\n" if ($terse); + + push(our @report, $output); + + return 1; +} + +sub report_dump { + our @report; +} + +sub fixup_current_range { + my ($lineRef, $offset, $length) = @_; + + if ($$lineRef =~ /^\@\@ -\d+,\d+ \+(\d+),(\d+) \@\@/) { + my $o = $1; + my $l = $2; + my $no = $o + $offset; + my $nl = $l + $length; + $$lineRef =~ s/\+$o,$l \@\@/\+$no,$nl \@\@/; + } +} + +sub fix_inserted_deleted_lines { + my ($linesRef, $insertedRef, $deletedRef) = @_; + + my $range_last_linenr = 0; + my $delta_offset = 0; + + my $old_linenr = 0; + my $new_linenr = 0; + + my $next_insert = 0; + my $next_delete = 0; + + my @lines = (); + + my $inserted = @{$insertedRef}[$next_insert++]; + my $deleted = @{$deletedRef}[$next_delete++]; + + foreach my $old_line (@{$linesRef}) { + my $save_line = 1; + my $line = $old_line; #don't modify the array + if ($line =~ /^(?:\+\+\+|\-\-\-)\s+\S+/) { #new filename + $delta_offset = 0; + } elsif ($line =~ /^\@\@ -\d+,\d+ \+\d+,\d+ \@\@/) { #new hunk + $range_last_linenr = $new_linenr; + fixup_current_range(\$line, $delta_offset, 0); + } + + while (defined($deleted) && ${$deleted}{'LINENR'} == $old_linenr) { + $deleted = @{$deletedRef}[$next_delete++]; + $save_line = 0; + fixup_current_range(\$lines[$range_last_linenr], $delta_offset--, -1); + } + + while (defined($inserted) && ${$inserted}{'LINENR'} == $old_linenr) { + push(@lines, ${$inserted}{'LINE'}); + $inserted = @{$insertedRef}[$next_insert++]; + $new_linenr++; + fixup_current_range(\$lines[$range_last_linenr], $delta_offset++, 1); + } + + if ($save_line) { + push(@lines, $line); + $new_linenr++; + } + + $old_linenr++; + } + + return @lines; +} + +sub fix_insert_line { + my ($linenr, $line) = @_; + + my $inserted = { + LINENR => $linenr, + LINE => $line, + }; + push(@fixed_inserted, $inserted); +} + +sub fix_delete_line { + my ($linenr, $line) = @_; + + my $deleted = { + LINENR => $linenr, + LINE => $line, + }; + + push(@fixed_deleted, $deleted); +} + +sub ERROR { + my ($type, $msg) = @_; + + if (report("ERROR", $type, $msg)) { + our $clean = 0; + our $cnt_error++; + return 1; + } + return 0; +} +sub WARN { + my ($type, $msg) = @_; + + if (report("WARNING", $type, $msg)) { + our $clean = 0; + our $cnt_warn++; + return 1; + } + return 0; +} +sub CHK { + my ($type, $msg) = @_; + + if ($check && report("CHECK", $type, $msg)) { + our $clean = 0; + our $cnt_chk++; + return 1; + } + return 0; +} + +sub check_absolute_file { + my ($absolute, $herecurr) = @_; + my $file = $absolute; + + ##print "absolute<$absolute>\n"; + + # See if any suffix of this path is a path within the tree. + while ($file =~ s@^[^/]*/@@) { + if (-f "$root/$file") { + ##print "file<$file>\n"; + last; + } + } + if (! -f _) { + return 0; + } + + # It is, so see if the prefix is acceptable. + my $prefix = $absolute; + substr($prefix, -length($file)) = ''; + + ##print "prefix<$prefix>\n"; + if ($prefix ne ".../") { + WARN("USE_RELATIVE_PATH", + "use relative pathname instead of absolute in changelog text\n" . $herecurr); + } +} + +sub trim { + my ($string) = @_; + + $string =~ s/^\s+|\s+$//g; + + return $string; +} + +sub ltrim { + my ($string) = @_; + + $string =~ s/^\s+//; + + return $string; +} + +sub rtrim { + my ($string) = @_; + + $string =~ s/\s+$//; + + return $string; +} + +sub string_find_replace { + my ($string, $find, $replace) = @_; + + $string =~ s/$find/$replace/g; + + return $string; +} + +sub tabify { + my ($leading) = @_; + + my $source_indent = 8; + my $max_spaces_before_tab = $source_indent - 1; + my $spaces_to_tab = " " x $source_indent; + + #convert leading spaces to tabs + 1 while $leading =~ s@^([\t]*)$spaces_to_tab@$1\t@g; + #Remove spaces before a tab + 1 while $leading =~ s@^([\t]*)( {1,$max_spaces_before_tab})\t@$1\t@g; + + return "$leading"; +} + +sub pos_last_openparen { + my ($line) = @_; + + my $pos = 0; + + my $opens = $line =~ tr/\(/\(/; + my $closes = $line =~ tr/\)/\)/; + + my $last_openparen = 0; + + if (($opens == 0) || ($closes >= $opens)) { + return -1; + } + + my $len = length($line); + + for ($pos = 0; $pos < $len; $pos++) { + my $string = substr($line, $pos); + if ($string =~ /^($FuncArg|$balanced_parens)/) { + $pos += length($1) - 1; + } elsif (substr($line, $pos, 1) eq '(') { + $last_openparen = $pos; + } elsif (index($string, '(') == -1) { + last; + } + } + + return length(expand_tabs(substr($line, 0, $last_openparen))) + 1; +} + +sub process { + my $filename = shift; + + my $linenr=0; + my $prevline=""; + my $prevrawline=""; + my $stashline=""; + my $stashrawline=""; + + my $length; + my $indent; + my $previndent=0; + my $stashindent=0; + + our $clean = 1; + my $signoff = 0; + my $is_patch = 0; + my $in_header_lines = $file ? 0 : 1; + my $in_commit_log = 0; #Scanning lines before patch + my $commit_log_possible_stack_dump = 0; + my $commit_log_long_line = 0; + my $commit_log_has_diff = 0; + my $reported_maintainer_file = 0; + my $non_utf8_charset = 0; + + my $last_blank_line = 0; + my $last_coalesced_string_linenr = -1; + + our @report = (); + our $cnt_lines = 0; + our $cnt_error = 0; + our $cnt_warn = 0; + our $cnt_chk = 0; + + # Trace the real file/line as we go. + my $realfile = ''; + my $realline = 0; + my $realcnt = 0; + my $here = ''; + my $in_comment = 0; + my $comment_edge = 0; + my $first_line = 0; + my $p1_prefix = ''; + + my $prev_values = 'E'; + + # suppression flags + my %suppress_ifbraces; + my %suppress_whiletrailers; + my %suppress_export; + my $suppress_statement = 0; + + my %signatures = (); + + # Pre-scan the patch sanitizing the lines. + # Pre-scan the patch looking for any __setup documentation. + # + my @setup_docs = (); + my $setup_docs = 0; + + my $camelcase_file_seeded = 0; + + sanitise_line_reset(); + my $line; + foreach my $rawline (@rawlines) { + $linenr++; + $line = $rawline; + + push(@fixed, $rawline) if ($fix); + + if ($rawline=~/^\+\+\+\s+(\S+)/) { + $setup_docs = 0; + if ($1 =~ m@Documentation/kernel-parameters.txt$@) { + $setup_docs = 1; + } + #next; + } + if ($rawline=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) { + $realline=$1-1; + if (defined $2) { + $realcnt=$3+1; + } else { + $realcnt=1+1; + } + $in_comment = 0; + + # Guestimate if this is a continuing comment. Run + # the context looking for a comment "edge". If this + # edge is a close comment then we must be in a comment + # at context start. + my $edge; + my $cnt = $realcnt; + for (my $ln = $linenr + 1; $cnt > 0; $ln++) { + next if (defined $rawlines[$ln - 1] && + $rawlines[$ln - 1] =~ /^-/); + $cnt--; + #print "RAW<$rawlines[$ln - 1]>\n"; + last if (!defined $rawlines[$ln - 1]); + if ($rawlines[$ln - 1] =~ m@(/\*|\*/)@ && + $rawlines[$ln - 1] !~ m@"[^"]*(?:/\*|\*/)[^"]*"@) { + ($edge) = $1; + last; + } + } + if (defined $edge && $edge eq '*/') { + $in_comment = 1; + } + + # Guestimate if this is a continuing comment. If this + # is the start of a diff block and this line starts + # ' *' then it is very likely a comment. + if (!defined $edge && + $rawlines[$linenr] =~ m@^.\s*(?:\*\*+| \*)(?:\s|$)@) + { + $in_comment = 1; + } + + ##print "COMMENT:$in_comment edge<$edge> $rawline\n"; + sanitise_line_reset($in_comment); + + } elsif ($realcnt && $rawline =~ /^(?:\+| |$)/) { + # Standardise the strings and chars within the input to + # simplify matching -- only bother with positive lines. + $line = sanitise_line($rawline); + } + push(@lines, $line); + + if ($realcnt > 1) { + $realcnt-- if ($line =~ /^(?:\+| |$)/); + } else { + $realcnt = 0; + } + + #print "==>$rawline\n"; + #print "-->$line\n"; + + if ($setup_docs && $line =~ /^\+/) { + push(@setup_docs, $line); + } + } + + $prefix = ''; + + $realcnt = 0; + $linenr = 0; + $fixlinenr = -1; + foreach my $line (@lines) { + $linenr++; + $fixlinenr++; + my $sline = $line; #copy of $line + $sline =~ s/$;/ /g; #with comments as spaces + + my $rawline = $rawlines[$linenr - 1]; + +#extract the line range in the file after the patch is applied + if (!$in_commit_log && + $line =~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) { + $is_patch = 1; + $first_line = $linenr + 1; + $realline=$1-1; + if (defined $2) { + $realcnt=$3+1; + } else { + $realcnt=1+1; + } + annotate_reset(); + $prev_values = 'E'; + + %suppress_ifbraces = (); + %suppress_whiletrailers = (); + %suppress_export = (); + $suppress_statement = 0; + next; + +# track the line number as we move through the hunk, note that +# new versions of GNU diff omit the leading space on completely +# blank context lines so we need to count that too. + } elsif ($line =~ /^( |\+|$)/) { + $realline++; + $realcnt-- if ($realcnt != 0); + + # Measure the line length and indent. + ($length, $indent) = line_stats($rawline); + + # Track the previous line. + ($prevline, $stashline) = ($stashline, $line); + ($previndent, $stashindent) = ($stashindent, $indent); + ($prevrawline, $stashrawline) = ($stashrawline, $rawline); + + #warn "line<$line>\n"; + + } elsif ($realcnt == 1) { + $realcnt--; + } + + my $hunk_line = ($realcnt != 0); + + $here = "#$linenr: " if (!$file); + $here = "#$realline: " if ($file); + + my $found_file = 0; + # extract the filename as it passes + if ($line =~ /^diff --git.*?(\S+)$/) { + $realfile = $1; + $realfile =~ s@^([^/]*)/@@ if (!$file); + $in_commit_log = 0; + $found_file = 1; + } elsif ($line =~ /^\+\+\+\s+(\S+)/) { + $realfile = $1; + $realfile =~ s@^([^/]*)/@@ if (!$file); + $in_commit_log = 0; + + $p1_prefix = $1; + if (!$file && $tree && $p1_prefix ne '' && + -e "$root/$p1_prefix") { + WARN("PATCH_PREFIX", + "patch prefix '$p1_prefix' exists, appears to be a -p0 patch\n"); + } + + if ($realfile =~ m@^include/asm/@) { + ERROR("MODIFIED_INCLUDE_ASM", + "do not modify files in include/asm, change architecture specific files in include/asm-<architecture>\n" . "$here$rawline\n"); + } + $found_file = 1; + } + +#make up the handle for any error we report on this line + if ($showfile) { + $prefix = "$realfile:$realline: " + } elsif ($emacs) { + if ($file) { + $prefix = "$filename:$realline: "; + } else { + $prefix = "$filename:$linenr: "; + } + } + + if ($found_file) { + if ($realfile =~ m@^(?:drivers/net/|net/|drivers/staging/)@) { + $check = 1; + } else { + $check = $check_orig; + } + next; + } + + $here .= "FILE: $realfile:$realline:" if ($realcnt != 0); + + my $hereline = "$here\n$rawline\n"; + my $herecurr = "$here\n$rawline\n"; + my $hereprev = "$here\n$prevrawline\n$rawline\n"; + + $cnt_lines++ if ($realcnt != 0); + +# Check if the commit log has what seems like a diff which can confuse patch + if ($in_commit_log && !$commit_log_has_diff && + (($line =~ m@^\s+diff\b.*a/[\w/]+@ && + $line =~ m@^\s+diff\b.*a/([\w/]+)\s+b/$1\b@) || + $line =~ m@^\s*(?:\-\-\-\s+a/|\+\+\+\s+b/)@ || + $line =~ m/^\s*\@\@ \-\d+,\d+ \+\d+,\d+ \@\@/)) { + ERROR("DIFF_IN_COMMIT_MSG", + "Avoid using diff content in the commit message - patch(1) might not work\n" . $herecurr); + $commit_log_has_diff = 1; + } + +# Check for incorrect file permissions + if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) { + my $permhere = $here . "FILE: $realfile\n"; + if ($realfile !~ m@scripts/@ && + $realfile !~ /\.(py|pl|awk|sh)$/) { + ERROR("EXECUTE_PERMISSIONS", + "do not set execute permissions for source files\n" . $permhere); + } + } + +# Check the patch for a signoff: + if ($line =~ /^\s*signed-off-by:/i) { + $signoff++; + $in_commit_log = 0; + } + +# Check if MAINTAINERS is being updated. If so, there's probably no need to +# emit the "does MAINTAINERS need updating?" message on file add/move/delete + if ($line =~ /^\s*MAINTAINERS\s*\|/) { + $reported_maintainer_file = 1; + } + +# Check signature styles + if (!$in_header_lines && + $line =~ /^(\s*)([a-z0-9_-]+by:|$signature_tags)(\s*)(.*)/i) { + my $space_before = $1; + my $sign_off = $2; + my $space_after = $3; + my $email = $4; + my $ucfirst_sign_off = ucfirst(lc($sign_off)); + + if ($sign_off !~ /$signature_tags/) { + WARN("BAD_SIGN_OFF", + "Non-standard signature: $sign_off\n" . $herecurr); + } + if (defined $space_before && $space_before ne "") { + if (WARN("BAD_SIGN_OFF", + "Do not use whitespace before $ucfirst_sign_off\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] = + "$ucfirst_sign_off $email"; + } + } + if ($sign_off =~ /-by:$/i && $sign_off ne $ucfirst_sign_off) { + if (WARN("BAD_SIGN_OFF", + "'$ucfirst_sign_off' is the preferred signature form\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] = + "$ucfirst_sign_off $email"; + } + + } + if (!defined $space_after || $space_after ne " ") { + if (WARN("BAD_SIGN_OFF", + "Use a single space after $ucfirst_sign_off\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] = + "$ucfirst_sign_off $email"; + } + } + + my ($email_name, $email_address, $comment) = parse_email($email); + my $suggested_email = format_email(($email_name, $email_address)); + if ($suggested_email eq "") { + ERROR("BAD_SIGN_OFF", + "Unrecognized email address: '$email'\n" . $herecurr); + } else { + my $dequoted = $suggested_email; + $dequoted =~ s/^"//; + $dequoted =~ s/" </ </; + # Don't force email to have quotes + # Allow just an angle bracketed address + if ("$dequoted$comment" ne $email && + "<$email_address>$comment" ne $email && + "$suggested_email$comment" ne $email) { + WARN("BAD_SIGN_OFF", + "email address '$email' might be better as '$suggested_email$comment'\n" . $herecurr); + } + } + +# Check for duplicate signatures + my $sig_nospace = $line; + $sig_nospace =~ s/\s//g; + $sig_nospace = lc($sig_nospace); + if (defined $signatures{$sig_nospace}) { + WARN("BAD_SIGN_OFF", + "Duplicate signature\n" . $herecurr); + } else { + $signatures{$sig_nospace} = 1; + } + } + +# Check email subject for common tools that don't need to be mentioned + if ($in_header_lines && + $line =~ /^Subject:.*\b(?:checkpatch|sparse|smatch)\b[^:]/i) { + WARN("EMAIL_SUBJECT", + "A patch subject line should describe the change not the tool that found it\n" . $herecurr); + } + +# Check for old stable address + if ($line =~ /^\s*cc:\s*.*<?\bstable\@kernel\.org\b>?.*$/i) { + ERROR("STABLE_ADDRESS", + "The 'stable' address should be 'stable\@vger.kernel.org'\n" . $herecurr); + } + +# Check for unwanted Gerrit info + if ($in_commit_log && $line =~ /^\s*change-id:/i) { + ERROR("GERRIT_CHANGE_ID", + "Remove Gerrit Change-Id's before submitting upstream.\n" . $herecurr); + } + +# Check if the commit log is in a possible stack dump + if ($in_commit_log && !$commit_log_possible_stack_dump && + ($line =~ /^\s*(?:WARNING:|BUG:)/ || + $line =~ /^\s*\[\s*\d+\.\d{6,6}\s*\]/ || + # timestamp + $line =~ /^\s*\[\<[0-9a-fA-F]{8,}\>\]/)) { + # stack dump address + $commit_log_possible_stack_dump = 1; + } + +# Check for line lengths > 75 in commit log, warn once + if ($in_commit_log && !$commit_log_long_line && + length($line) > 75 && + !($line =~ /^\s*[a-zA-Z0-9_\/\.]+\s+\|\s+\d+/ || + # file delta changes + $line =~ /^\s*(?:[\w\.\-]+\/)++[\w\.\-]+:/ || + # filename then : + $line =~ /^\s*(?:Fixes:|Link:)/i || + # A Fixes: or Link: line + $commit_log_possible_stack_dump)) { + WARN("COMMIT_LOG_LONG_LINE", + "Possible unwrapped commit description (prefer a maximum 75 chars per line)\n" . $herecurr); + $commit_log_long_line = 1; + } + +# Reset possible stack dump if a blank line is found + if ($in_commit_log && $commit_log_possible_stack_dump && + $line =~ /^\s*$/) { + $commit_log_possible_stack_dump = 0; + } + +# Check for git id commit length and improperly formed commit descriptions + if ($in_commit_log && !$commit_log_possible_stack_dump && + ($line =~ /\bcommit\s+[0-9a-f]{5,}\b/i || + ($line =~ /\b[0-9a-f]{12,40}\b/i && + $line !~ /[\<\[][0-9a-f]{12,40}[\>\]]/i && + $line !~ /\bfixes:\s*[0-9a-f]{12,40}/i))) { + my $init_char = "c"; + my $orig_commit = ""; + my $short = 1; + my $long = 0; + my $case = 1; + my $space = 1; + my $hasdesc = 0; + my $hasparens = 0; + my $id = '0123456789ab'; + my $orig_desc = "commit description"; + my $description = ""; + + if ($line =~ /\b(c)ommit\s+([0-9a-f]{5,})\b/i) { + $init_char = $1; + $orig_commit = lc($2); + } elsif ($line =~ /\b([0-9a-f]{12,40})\b/i) { + $orig_commit = lc($1); + } + + $short = 0 if ($line =~ /\bcommit\s+[0-9a-f]{12,40}/i); + $long = 1 if ($line =~ /\bcommit\s+[0-9a-f]{41,}/i); + $space = 0 if ($line =~ /\bcommit [0-9a-f]/i); + $case = 0 if ($line =~ /\b[Cc]ommit\s+[0-9a-f]{5,40}[^A-F]/); + if ($line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("([^"]+)"\)/i) { + $orig_desc = $1; + $hasparens = 1; + } elsif ($line =~ /\bcommit\s+[0-9a-f]{5,}\s*$/i && + defined $rawlines[$linenr] && + $rawlines[$linenr] =~ /^\s*\("([^"]+)"\)/) { + $orig_desc = $1; + $hasparens = 1; + } elsif ($line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("[^"]+$/i && + defined $rawlines[$linenr] && + $rawlines[$linenr] =~ /^\s*[^"]+"\)/) { + $line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("([^"]+)$/i; + $orig_desc = $1; + $rawlines[$linenr] =~ /^\s*([^"]+)"\)/; + $orig_desc .= " " . $1; + $hasparens = 1; + } + + ($id, $description) = git_commit_info($orig_commit, + $id, $orig_desc); + + if ($short || $long || $space || $case || ($orig_desc ne $description) || !$hasparens) { + ERROR("GIT_COMMIT_ID", + "Please use git commit description style 'commit <12+ chars of sha1> (\"<title line>\")' - ie: '${init_char}ommit $id (\"$description\")'\n" . $herecurr); + } + } + +# Check for added, moved or deleted files + if (!$reported_maintainer_file && !$in_commit_log && + ($line =~ /^(?:new|deleted) file mode\s*\d+\s*$/ || + $line =~ /^rename (?:from|to) [\w\/\.\-]+\s*$/ || + ($line =~ /\{\s*([\w\/\.\-]*)\s*\=\>\s*([\w\/\.\-]*)\s*\}/ && + (defined($1) || defined($2))))) { + $reported_maintainer_file = 1; + WARN("FILE_PATH_CHANGES", + "added, moved or deleted file(s), does MAINTAINERS need updating?\n" . $herecurr); + } + +# Check for wrappage within a valid hunk of the file + if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) { + ERROR("CORRUPTED_PATCH", + "patch seems to be corrupt (line wrapped?)\n" . + $herecurr) if (!$emitted_corrupt++); + } + +# Check for absolute kernel paths. + if ($tree) { + while ($line =~ m{(?:^|\s)(/\S*)}g) { + my $file = $1; + + if ($file =~ m{^(.*?)(?::\d+)+:?$} && + check_absolute_file($1, $herecurr)) { + # + } else { + check_absolute_file($file, $herecurr); + } + } + } + +# UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php + if (($realfile =~ /^$/ || $line =~ /^\+/) && + $rawline !~ m/^$UTF8*$/) { + my ($utf8_prefix) = ($rawline =~ /^($UTF8*)/); + + my $blank = copy_spacing($rawline); + my $ptr = substr($blank, 0, length($utf8_prefix)) . "^"; + my $hereptr = "$hereline$ptr\n"; + + CHK("INVALID_UTF8", + "Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $hereptr); + } + +# Check if it's the start of a commit log +# (not a header line and we haven't seen the patch filename) + if ($in_header_lines && $realfile =~ /^$/ && + !($rawline =~ /^\s+\S/ || + $rawline =~ /^(commit\b|from\b|[\w-]+:).*$/i)) { + $in_header_lines = 0; + $in_commit_log = 1; + } + +# Check if there is UTF-8 in a commit log when a mail header has explicitly +# declined it, i.e defined some charset where it is missing. + if ($in_header_lines && + $rawline =~ /^Content-Type:.+charset="(.+)".*$/ && + $1 !~ /utf-8/i) { + $non_utf8_charset = 1; + } + + if ($in_commit_log && $non_utf8_charset && $realfile =~ /^$/ && + $rawline =~ /$NON_ASCII_UTF8/) { + WARN("UTF8_BEFORE_PATCH", + "8-bit UTF-8 used in possible commit log\n" . $herecurr); + } + +# Check for various typo / spelling mistakes + if (defined($misspellings) && + ($in_commit_log || $line =~ /^(?:\+|Subject:)/i)) { + while ($rawline =~ /(?:^|[^a-z@])($misspellings)(?:\b|$|[^a-z@])/gi) { + my $typo = $1; + my $typo_fix = $spelling_fix{lc($typo)}; + $typo_fix = ucfirst($typo_fix) if ($typo =~ /^[A-Z]/); + $typo_fix = uc($typo_fix) if ($typo =~ /^[A-Z]+$/); + my $msg_type = \&WARN; + $msg_type = \&CHK if ($file); + if (&{$msg_type}("TYPO_SPELLING", + "'$typo' may be misspelled - perhaps '$typo_fix'?\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/(^|[^A-Za-z@])($typo)($|[^A-Za-z@])/$1$typo_fix$3/; + } + } + } + +# ignore non-hunk lines and lines being removed + next if (!$hunk_line || $line =~ /^-/); + +#trailing whitespace + if ($line =~ /^\+.*\015/) { + my $herevet = "$here\n" . cat_vet($rawline) . "\n"; + if (ERROR("DOS_LINE_ENDINGS", + "DOS line endings\n" . $herevet) && + $fix) { + $fixed[$fixlinenr] =~ s/[\s\015]+$//; + } + } elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) { + my $herevet = "$here\n" . cat_vet($rawline) . "\n"; + if (ERROR("TRAILING_WHITESPACE", + "trailing whitespace\n" . $herevet) && + $fix) { + $fixed[$fixlinenr] =~ s/\s+$//; + } + + $rpt_cleaners = 1; + } + +# Check for FSF mailing addresses. + if ($rawline =~ /\bwrite to the Free/i || + $rawline =~ /\b59\s+Temple\s+Pl/i || + $rawline =~ /\b51\s+Franklin\s+St/i) { + my $herevet = "$here\n" . cat_vet($rawline) . "\n"; + my $msg_type = \&ERROR; + $msg_type = \&CHK if ($file); + &{$msg_type}("FSF_MAILING_ADDRESS", + "Do not include the paragraph about writing to the Free Software Foundation's mailing address from the sample GPL notice. The FSF has changed addresses in the past, and may do so again. Linux already includes a copy of the GPL.\n" . $herevet) + } + +# check for Kconfig help text having a real description +# Only applies when adding the entry originally, after that we do not have +# sufficient context to determine whether it is indeed long enough. + if ($realfile =~ /Kconfig/ && + $line =~ /^\+\s*config\s+/) { + my $length = 0; + my $cnt = $realcnt; + my $ln = $linenr + 1; + my $f; + my $is_start = 0; + my $is_end = 0; + for (; $cnt > 0 && defined $lines[$ln - 1]; $ln++) { + $f = $lines[$ln - 1]; + $cnt-- if ($lines[$ln - 1] !~ /^-/); + $is_end = $lines[$ln - 1] =~ /^\+/; + + next if ($f =~ /^-/); + last if (!$file && $f =~ /^\@\@/); + + if ($lines[$ln - 1] =~ /^\+\s*(?:bool|tristate)\s*\"/) { + $is_start = 1; + } elsif ($lines[$ln - 1] =~ /^\+\s*(?:---)?help(?:---)?$/) { + $length = -1; + } + + $f =~ s/^.//; + $f =~ s/#.*//; + $f =~ s/^\s+//; + next if ($f =~ /^$/); + if ($f =~ /^\s*config\s/) { + $is_end = 1; + last; + } + $length++; + } + if ($is_start && $is_end && $length < $min_conf_desc_length) { + WARN("CONFIG_DESCRIPTION", + "please write a paragraph that describes the config symbol fully\n" . $herecurr); + } + #print "is_start<$is_start> is_end<$is_end> length<$length>\n"; + } + +# discourage the addition of CONFIG_EXPERIMENTAL in Kconfig. + if ($realfile =~ /Kconfig/ && + $line =~ /.\s*depends on\s+.*\bEXPERIMENTAL\b/) { + WARN("CONFIG_EXPERIMENTAL", + "Use of CONFIG_EXPERIMENTAL is deprecated. For alternatives, see https://lkml.org/lkml/2012/10/23/580\n"); + } + +# discourage the use of boolean for type definition attributes of Kconfig options + if ($realfile =~ /Kconfig/ && + $line =~ /^\+\s*\bboolean\b/) { + WARN("CONFIG_TYPE_BOOLEAN", + "Use of boolean is deprecated, please use bool instead.\n" . $herecurr); + } + + if (($realfile =~ /Makefile.*/ || $realfile =~ /Kbuild.*/) && + ($line =~ /\+(EXTRA_[A-Z]+FLAGS).*/)) { + my $flag = $1; + my $replacement = { + 'EXTRA_AFLAGS' => 'asflags-y', + 'EXTRA_CFLAGS' => 'ccflags-y', + 'EXTRA_CPPFLAGS' => 'cppflags-y', + 'EXTRA_LDFLAGS' => 'ldflags-y', + }; + + WARN("DEPRECATED_VARIABLE", + "Use of $flag is deprecated, please use \`$replacement->{$flag} instead.\n" . $herecurr) if ($replacement->{$flag}); + } + +# check for DT compatible documentation + if (defined $root && + (($realfile =~ /\.dtsi?$/ && $line =~ /^\+\s*compatible\s*=\s*\"/) || + ($realfile =~ /\.[ch]$/ && $line =~ /^\+.*\.compatible\s*=\s*\"/))) { + + my @compats = $rawline =~ /\"([a-zA-Z0-9\-\,\.\+_]+)\"/g; + + my $dt_path = $root . "/Documentation/devicetree/bindings/"; + my $vp_file = $dt_path . "vendor-prefixes.txt"; + + foreach my $compat (@compats) { + my $compat2 = $compat; + $compat2 =~ s/\,[a-zA-Z0-9]*\-/\,<\.\*>\-/; + my $compat3 = $compat; + $compat3 =~ s/\,([a-z]*)[0-9]*\-/\,$1<\.\*>\-/; + `grep -Erq "$compat|$compat2|$compat3" $dt_path`; + if ( $? >> 8 ) { + WARN("UNDOCUMENTED_DT_STRING", + "DT compatible string \"$compat\" appears un-documented -- check $dt_path\n" . $herecurr); + } + + next if $compat !~ /^([a-zA-Z0-9\-]+)\,/; + my $vendor = $1; + `grep -Eq "^$vendor\\b" $vp_file`; + if ( $? >> 8 ) { + WARN("UNDOCUMENTED_DT_STRING", + "DT compatible string vendor \"$vendor\" appears un-documented -- check $vp_file\n" . $herecurr); + } + } + } + +# check we are in a valid source file if not then ignore this hunk + next if ($realfile !~ /\.(h|c|s|S|pl|sh|dtsi|dts)$/); + +# line length limit (with some exclusions) +# +# There are a few types of lines that may extend beyond $max_line_length: +# logging functions like pr_info that end in a string +# lines with a single string +# #defines that are a single string +# +# There are 3 different line length message types: +# LONG_LINE_COMMENT a comment starts before but extends beyond $max_linelength +# LONG_LINE_STRING a string starts before but extends beyond $max_line_length +# LONG_LINE all other lines longer than $max_line_length +# +# if LONG_LINE is ignored, the other 2 types are also ignored +# + + if ($line =~ /^\+/ && $length > $max_line_length) { + my $msg_type = "LONG_LINE"; + + # Check the allowed long line types first + + # logging functions that end in a string that starts + # before $max_line_length + if ($line =~ /^\+\s*$logFunctions\s*\(\s*(?:(?:KERN_\S+\s*|[^"]*))?($String\s*(?:|,|\)\s*;)\s*)$/ && + length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) { + $msg_type = ""; + + # lines with only strings (w/ possible termination) + # #defines with only strings + } elsif ($line =~ /^\+\s*$String\s*(?:\s*|,|\)\s*;)\s*$/ || + $line =~ /^\+\s*#\s*define\s+\w+\s+$String$/) { + $msg_type = ""; + + # Otherwise set the alternate message types + + # a comment starts before $max_line_length + } elsif ($line =~ /($;[\s$;]*)$/ && + length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) { + $msg_type = "LONG_LINE_COMMENT" + + # a quoted string starts before $max_line_length + } elsif ($sline =~ /\s*($String(?:\s*(?:\\|,\s*|\)\s*;\s*))?)$/ && + length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) { + $msg_type = "LONG_LINE_STRING" + } + + if ($msg_type ne "" && + (show_type("LONG_LINE") || show_type($msg_type))) { + WARN($msg_type, + "line over $max_line_length characters\n" . $herecurr); + } + } + +# check for adding lines without a newline. + if ($line =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ No newline at end of file/) { + WARN("MISSING_EOF_NEWLINE", + "adding a line without newline at end of file\n" . $herecurr); + } + +# Blackfin: use hi/lo macros + if ($realfile =~ m@arch/blackfin/.*\.S$@) { + if ($line =~ /\.[lL][[:space:]]*=.*&[[:space:]]*0x[fF][fF][fF][fF]/) { + my $herevet = "$here\n" . cat_vet($line) . "\n"; + ERROR("LO_MACRO", + "use the LO() macro, not (... & 0xFFFF)\n" . $herevet); + } + if ($line =~ /\.[hH][[:space:]]*=.*>>[[:space:]]*16/) { + my $herevet = "$here\n" . cat_vet($line) . "\n"; + ERROR("HI_MACRO", + "use the HI() macro, not (... >> 16)\n" . $herevet); + } + } + +# check we are in a valid source file C or perl if not then ignore this hunk + next if ($realfile !~ /\.(h|c|pl|dtsi|dts)$/); + +# at the beginning of a line any tabs must come first and anything +# more than 8 must use tabs. + if ($rawline =~ /^\+\s* \t\s*\S/ || + $rawline =~ /^\+\s* \s*/) { + my $herevet = "$here\n" . cat_vet($rawline) . "\n"; + $rpt_cleaners = 1; + if (ERROR("CODE_INDENT", + "code indent should use tabs where possible\n" . $herevet) && + $fix) { + $fixed[$fixlinenr] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e; + } + } + +# check for space before tabs. + if ($rawline =~ /^\+/ && $rawline =~ / \t/) { + my $herevet = "$here\n" . cat_vet($rawline) . "\n"; + if (WARN("SPACE_BEFORE_TAB", + "please, no space before tabs\n" . $herevet) && + $fix) { + while ($fixed[$fixlinenr] =~ + s/(^\+.*) {8,8}\t/$1\t\t/) {} + while ($fixed[$fixlinenr] =~ + s/(^\+.*) +\t/$1\t/) {} + } + } + +# check for && or || at the start of a line + if ($rawline =~ /^\+\s*(&&|\|\|)/) { + CHK("LOGICAL_CONTINUATIONS", + "Logical continuations should be on the previous line\n" . $hereprev); + } + +# check multi-line statement indentation matches previous line + if ($^V && $^V ge 5.10.0 && + $prevline =~ /^\+([ \t]*)((?:$c90_Keywords(?:\s+if)\s*)|(?:$Declare\s*)?(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*|$Ident\s*=\s*$Ident\s*)\(.*(\&\&|\|\||,)\s*$/) { + $prevline =~ /^\+(\t*)(.*)$/; + my $oldindent = $1; + my $rest = $2; + + my $pos = pos_last_openparen($rest); + if ($pos >= 0) { + $line =~ /^(\+| )([ \t]*)/; + my $newindent = $2; + + my $goodtabindent = $oldindent . + "\t" x ($pos / 8) . + " " x ($pos % 8); + my $goodspaceindent = $oldindent . " " x $pos; + + if ($newindent ne $goodtabindent && + $newindent ne $goodspaceindent) { + + if (CHK("PARENTHESIS_ALIGNMENT", + "Alignment should match open parenthesis\n" . $hereprev) && + $fix && $line =~ /^\+/) { + $fixed[$fixlinenr] =~ + s/^\+[ \t]*/\+$goodtabindent/; + } + } + } + } + +# check for space after cast like "(int) foo" or "(struct foo) bar" +# avoid checking a few false positives: +# "sizeof(<type>)" or "__alignof__(<type>)" +# function pointer declarations like "(*foo)(int) = bar;" +# structure definitions like "(struct foo) { 0 };" +# multiline macros that define functions +# known attributes or the __attribute__ keyword + if ($line =~ /^\+(.*)\(\s*$Type\s*\)([ \t]++)((?![={]|\\$|$Attribute|__attribute__))/ && + (!defined($1) || $1 !~ /\b(?:sizeof|__alignof__)\s*$/)) { + if (CHK("SPACING", + "No space is necessary after a cast\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ + s/(\(\s*$Type\s*\))[ \t]+/$1/; + } + } + +# Block comment styles +# Networking with an initial /* + if ($realfile =~ m@^(drivers/net/|net/)@ && + $prevrawline =~ /^\+[ \t]*\/\*[ \t]*$/ && + $rawline =~ /^\+[ \t]*\*/ && + $realline > 2) { + WARN("NETWORKING_BLOCK_COMMENT_STYLE", + "networking block comments don't use an empty /* line, use /* Comment...\n" . $hereprev); + } + +# Block comments use * on subsequent lines + if ($prevline =~ /$;[ \t]*$/ && #ends in comment + $prevrawline =~ /^\+.*?\/\*/ && #starting /* + $prevrawline !~ /\*\/[ \t]*$/ && #no trailing */ + $rawline =~ /^\+/ && #line is new + $rawline !~ /^\+[ \t]*\*/) { #no leading * + WARN("BLOCK_COMMENT_STYLE", + "Block comments use * on subsequent lines\n" . $hereprev); + } + +# Block comments use */ on trailing lines + if ($rawline !~ m@^\+[ \t]*\*/[ \t]*$@ && #trailing */ + $rawline !~ m@^\+.*/\*.*\*/[ \t]*$@ && #inline /*...*/ + $rawline !~ m@^\+.*\*{2,}/[ \t]*$@ && #trailing **/ + $rawline =~ m@^\+[ \t]*.+\*\/[ \t]*$@) { #non blank */ + WARN("BLOCK_COMMENT_STYLE", + "Block comments use a trailing */ on a separate line\n" . $herecurr); + } + +# check for missing blank lines after struct/union declarations +# with exceptions for various attributes and macros + if ($prevline =~ /^[\+ ]};?\s*$/ && + $line =~ /^\+/ && + !($line =~ /^\+\s*$/ || + $line =~ /^\+\s*EXPORT_SYMBOL/ || + $line =~ /^\+\s*MODULE_/i || + $line =~ /^\+\s*\#\s*(?:end|elif|else)/ || + $line =~ /^\+[a-z_]*init/ || + $line =~ /^\+\s*(?:static\s+)?[A-Z_]*ATTR/ || + $line =~ /^\+\s*DECLARE/ || + $line =~ /^\+\s*__setup/)) { + if (CHK("LINE_SPACING", + "Please use a blank line after function/struct/union/enum declarations\n" . $hereprev) && + $fix) { + fix_insert_line($fixlinenr, "\+"); + } + } + +# check for multiple consecutive blank lines + if ($prevline =~ /^[\+ ]\s*$/ && + $line =~ /^\+\s*$/ && + $last_blank_line != ($linenr - 1)) { + if (CHK("LINE_SPACING", + "Please don't use multiple blank lines\n" . $hereprev) && + $fix) { + fix_delete_line($fixlinenr, $rawline); + } + + $last_blank_line = $linenr; + } + +# check for missing blank lines after declarations + if ($sline =~ /^\+\s+\S/ && #Not at char 1 + # actual declarations + ($prevline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ || + # function pointer declarations + $prevline =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ || + # foo bar; where foo is some local typedef or #define + $prevline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ || + # known declaration macros + $prevline =~ /^\+\s+$declaration_macros/) && + # for "else if" which can look like "$Ident $Ident" + !($prevline =~ /^\+\s+$c90_Keywords\b/ || + # other possible extensions of declaration lines + $prevline =~ /(?:$Compare|$Assignment|$Operators)\s*$/ || + # not starting a section or a macro "\" extended line + $prevline =~ /(?:\{\s*|\\)$/) && + # looks like a declaration + !($sline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ || + # function pointer declarations + $sline =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ || + # foo bar; where foo is some local typedef or #define + $sline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ || + # known declaration macros + $sline =~ /^\+\s+$declaration_macros/ || + # start of struct or union or enum + $sline =~ /^\+\s+(?:union|struct|enum|typedef)\b/ || + # start or end of block or continuation of declaration + $sline =~ /^\+\s+(?:$|[\{\}\.\#\"\?\:\(\[])/ || + # bitfield continuation + $sline =~ /^\+\s+$Ident\s*:\s*\d+\s*[,;]/ || + # other possible extensions of declaration lines + $sline =~ /^\+\s+\(?\s*(?:$Compare|$Assignment|$Operators)/) && + # indentation of previous and current line are the same + (($prevline =~ /\+(\s+)\S/) && $sline =~ /^\+$1\S/)) { + if (WARN("LINE_SPACING", + "Missing a blank line after declarations\n" . $hereprev) && + $fix) { + fix_insert_line($fixlinenr, "\+"); + } + } + +# check for spaces at the beginning of a line. +# Exceptions: +# 1) within comments +# 2) indented preprocessor commands +# 3) hanging labels + if ($rawline =~ /^\+ / && $line !~ /^\+ *(?:$;|#|$Ident:)/) { + my $herevet = "$here\n" . cat_vet($rawline) . "\n"; + if (WARN("LEADING_SPACE", + "please, no spaces at the start of a line\n" . $herevet) && + $fix) { + $fixed[$fixlinenr] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e; + } + } + +# check we are in a valid C source file if not then ignore this hunk + next if ($realfile !~ /\.(h|c)$/); + +# check indentation of any line with a bare else +# (but not if it is a multiple line "if (foo) return bar; else return baz;") +# if the previous line is a break or return and is indented 1 tab more... + if ($sline =~ /^\+([\t]+)(?:}[ \t]*)?else(?:[ \t]*{)?\s*$/) { + my $tabs = length($1) + 1; + if ($prevline =~ /^\+\t{$tabs,$tabs}break\b/ || + ($prevline =~ /^\+\t{$tabs,$tabs}return\b/ && + defined $lines[$linenr] && + $lines[$linenr] !~ /^[ \+]\t{$tabs,$tabs}return/)) { + WARN("UNNECESSARY_ELSE", + "else is not generally useful after a break or return\n" . $hereprev); + } + } + +# check indentation of a line with a break; +# if the previous line is a goto or return and is indented the same # of tabs + if ($sline =~ /^\+([\t]+)break\s*;\s*$/) { + my $tabs = $1; + if ($prevline =~ /^\+$tabs(?:goto|return)\b/) { + WARN("UNNECESSARY_BREAK", + "break is not useful after a goto or return\n" . $hereprev); + } + } + +# discourage the addition of CONFIG_EXPERIMENTAL in #if(def). + if ($line =~ /^\+\s*\#\s*if.*\bCONFIG_EXPERIMENTAL\b/) { + WARN("CONFIG_EXPERIMENTAL", + "Use of CONFIG_EXPERIMENTAL is deprecated. For alternatives, see https://lkml.org/lkml/2012/10/23/580\n"); + } + +# check for RCS/CVS revision markers + if ($rawline =~ /^\+.*\$(Revision|Log|Id)(?:\$|)/) { + WARN("CVS_KEYWORD", + "CVS style keyword markers, these will _not_ be updated\n". $herecurr); + } + +# Blackfin: don't use __builtin_bfin_[cs]sync + if ($line =~ /__builtin_bfin_csync/) { + my $herevet = "$here\n" . cat_vet($line) . "\n"; + ERROR("CSYNC", + "use the CSYNC() macro in asm/blackfin.h\n" . $herevet); + } + if ($line =~ /__builtin_bfin_ssync/) { + my $herevet = "$here\n" . cat_vet($line) . "\n"; + ERROR("SSYNC", + "use the SSYNC() macro in asm/blackfin.h\n" . $herevet); + } + +# check for old HOTPLUG __dev<foo> section markings + if ($line =~ /\b(__dev(init|exit)(data|const|))\b/) { + WARN("HOTPLUG_SECTION", + "Using $1 is unnecessary\n" . $herecurr); + } + +# Check for potential 'bare' types + my ($stat, $cond, $line_nr_next, $remain_next, $off_next, + $realline_next); +#print "LINE<$line>\n"; + if ($linenr >= $suppress_statement && + $realcnt && $sline =~ /.\s*\S/) { + ($stat, $cond, $line_nr_next, $remain_next, $off_next) = + ctx_statement_block($linenr, $realcnt, 0); + $stat =~ s/\n./\n /g; + $cond =~ s/\n./\n /g; + +#print "linenr<$linenr> <$stat>\n"; + # If this statement has no statement boundaries within + # it there is no point in retrying a statement scan + # until we hit end of it. + my $frag = $stat; $frag =~ s/;+\s*$//; + if ($frag !~ /(?:{|;)/) { +#print "skip<$line_nr_next>\n"; + $suppress_statement = $line_nr_next; + } + + # Find the real next line. + $realline_next = $line_nr_next; + if (defined $realline_next && + (!defined $lines[$realline_next - 1] || + substr($lines[$realline_next - 1], $off_next) =~ /^\s*$/)) { + $realline_next++; + } + + my $s = $stat; + $s =~ s/{.*$//s; + + # Ignore goto labels. + if ($s =~ /$Ident:\*$/s) { + + # Ignore functions being called + } elsif ($s =~ /^.\s*$Ident\s*\(/s) { + + } elsif ($s =~ /^.\s*else\b/s) { + + # declarations always start with types + } elsif ($prev_values eq 'E' && $s =~ /^.\s*(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?((?:\s*$Ident)+?)\b(?:\s+$Sparse)?\s*\**\s*(?:$Ident|\(\*[^\)]*\))(?:\s*$Modifier)?\s*(?:;|=|,|\()/s) { + my $type = $1; + $type =~ s/\s+/ /g; + possible($type, "A:" . $s); + + # definitions in global scope can only start with types + } elsif ($s =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b\s*(?!:)/s) { + possible($1, "B:" . $s); + } + + # any (foo ... *) is a pointer cast, and foo is a type + while ($s =~ /\(($Ident)(?:\s+$Sparse)*[\s\*]+\s*\)/sg) { + possible($1, "C:" . $s); + } + + # Check for any sort of function declaration. + # int foo(something bar, other baz); + # void (*store_gdt)(x86_descr_ptr *); + if ($prev_values eq 'E' && $s =~ /^(.(?:typedef\s*)?(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*(?:\b$Ident|\(\*\s*$Ident\))\s*)\(/s) { + my ($name_len) = length($1); + + my $ctx = $s; + substr($ctx, 0, $name_len + 1, ''); + $ctx =~ s/\)[^\)]*$//; + + for my $arg (split(/\s*,\s*/, $ctx)) { + if ($arg =~ /^(?:const\s+)?($Ident)(?:\s+$Sparse)*\s*\**\s*(:?\b$Ident)?$/s || $arg =~ /^($Ident)$/s) { + + possible($1, "D:" . $s); + } + } + } + + } + +# +# Checks which may be anchored in the context. +# + +# Check for switch () and associated case and default +# statements should be at the same indent. + if ($line=~/\bswitch\s*\(.*\)/) { + my $err = ''; + my $sep = ''; + my @ctx = ctx_block_outer($linenr, $realcnt); + shift(@ctx); + for my $ctx (@ctx) { + my ($clen, $cindent) = line_stats($ctx); + if ($ctx =~ /^\+\s*(case\s+|default:)/ && + $indent != $cindent) { + $err .= "$sep$ctx\n"; + $sep = ''; + } else { + $sep = "[...]\n"; + } + } + if ($err ne '') { + ERROR("SWITCH_CASE_INDENT_LEVEL", + "switch and case should be at the same indent\n$hereline$err"); + } + } + +# if/while/etc brace do not go on next line, unless defining a do while loop, +# or if that brace on the next line is for something else + if ($line =~ /(.*)\b((?:if|while|for|switch|(?:[a-z_]+|)for_each[a-z_]+)\s*\(|do\b|else\b)/ && $line !~ /^.\s*\#/) { + my $pre_ctx = "$1$2"; + + my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0); + + if ($line =~ /^\+\t{6,}/) { + WARN("DEEP_INDENTATION", + "Too many leading tabs - consider code refactoring\n" . $herecurr); + } + + my $ctx_cnt = $realcnt - $#ctx - 1; + my $ctx = join("\n", @ctx); + + my $ctx_ln = $linenr; + my $ctx_skip = $realcnt; + + while ($ctx_skip > $ctx_cnt || ($ctx_skip == $ctx_cnt && + defined $lines[$ctx_ln - 1] && + $lines[$ctx_ln - 1] =~ /^-/)) { + ##print "SKIP<$ctx_skip> CNT<$ctx_cnt>\n"; + $ctx_skip-- if (!defined $lines[$ctx_ln - 1] || $lines[$ctx_ln - 1] !~ /^-/); + $ctx_ln++; + } + + #print "realcnt<$realcnt> ctx_cnt<$ctx_cnt>\n"; + #print "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n"; + + if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln - 1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) { + ERROR("OPEN_BRACE", + "that open brace { should be on the previous line\n" . + "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n"); + } + if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ && + $ctx =~ /\)\s*\;\s*$/ && + defined $lines[$ctx_ln - 1]) + { + my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]); + if ($nindent > $indent) { + WARN("TRAILING_SEMICOLON", + "trailing semicolon indicates no statements, indent implies otherwise\n" . + "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n"); + } + } + } + +# Check relative indent for conditionals and blocks. + if ($line =~ /\b(?:(?:if|while|for|(?:[a-z_]+|)for_each[a-z_]+)\s*\(|do\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) { + ($stat, $cond, $line_nr_next, $remain_next, $off_next) = + ctx_statement_block($linenr, $realcnt, 0) + if (!defined $stat); + my ($s, $c) = ($stat, $cond); + + substr($s, 0, length($c), ''); + + # remove inline comments + $s =~ s/$;/ /g; + $c =~ s/$;/ /g; + + # Find out how long the conditional actually is. + my @newlines = ($c =~ /\n/gs); + my $cond_lines = 1 + $#newlines; + + # Make sure we remove the line prefixes as we have + # none on the first line, and are going to readd them + # where necessary. + $s =~ s/\n./\n/gs; + while ($s =~ /\n\s+\\\n/) { + $cond_lines += $s =~ s/\n\s+\\\n/\n/g; + } + + # We want to check the first line inside the block + # starting at the end of the conditional, so remove: + # 1) any blank line termination + # 2) any opening brace { on end of the line + # 3) any do (...) { + my $continuation = 0; + my $check = 0; + $s =~ s/^.*\bdo\b//; + $s =~ s/^\s*{//; + if ($s =~ s/^\s*\\//) { + $continuation = 1; + } + if ($s =~ s/^\s*?\n//) { + $check = 1; + $cond_lines++; + } + + # Also ignore a loop construct at the end of a + # preprocessor statement. + if (($prevline =~ /^.\s*#\s*define\s/ || + $prevline =~ /\\\s*$/) && $continuation == 0) { + $check = 0; + } + + my $cond_ptr = -1; + $continuation = 0; + while ($cond_ptr != $cond_lines) { + $cond_ptr = $cond_lines; + + # If we see an #else/#elif then the code + # is not linear. + if ($s =~ /^\s*\#\s*(?:else|elif)/) { + $check = 0; + } + + # Ignore: + # 1) blank lines, they should be at 0, + # 2) preprocessor lines, and + # 3) labels. + if ($continuation || + $s =~ /^\s*?\n/ || + $s =~ /^\s*#\s*?/ || + $s =~ /^\s*$Ident\s*:/) { + $continuation = ($s =~ /^.*?\\\n/) ? 1 : 0; + if ($s =~ s/^.*?\n//) { + $cond_lines++; + } + } + } + + my (undef, $sindent) = line_stats("+" . $s); + my $stat_real = raw_line($linenr, $cond_lines); + + # Check if either of these lines are modified, else + # this is not this patch's fault. + if (!defined($stat_real) || + $stat !~ /^\+/ && $stat_real !~ /^\+/) { + $check = 0; + } + if (defined($stat_real) && $cond_lines > 1) { + $stat_real = "[...]\n$stat_real"; + } + + #print "line<$line> prevline<$prevline> indent<$indent> sindent<$sindent> check<$check> continuation<$continuation> s<$s> cond_lines<$cond_lines> stat_real<$stat_real> stat<$stat>\n"; + + if ($check && $s ne '' && + (($sindent % 8) != 0 || + ($sindent < $indent) || + ($sindent > $indent + 8))) { + WARN("SUSPECT_CODE_INDENT", + "suspect code indent for conditional statements ($indent, $sindent)\n" . $herecurr . "$stat_real\n"); + } + } + + # Track the 'values' across context and added lines. + my $opline = $line; $opline =~ s/^./ /; + my ($curr_values, $curr_vars) = + annotate_values($opline . "\n", $prev_values); + $curr_values = $prev_values . $curr_values; + if ($dbg_values) { + my $outline = $opline; $outline =~ s/\t/ /g; + print "$linenr > .$outline\n"; + print "$linenr > $curr_values\n"; + print "$linenr > $curr_vars\n"; + } + $prev_values = substr($curr_values, -1); + +#ignore lines not being added + next if ($line =~ /^[^\+]/); + +# check for declarations of signed or unsigned without int + while ($line =~ m{($Declare)\s*(?!char\b|short\b|int\b|long\b)\s*($Ident)?\s*[=,;\[\)\(]}g) { + my $type = $1; + my $var = $2; + $var = "" if (!defined $var); + if ($type =~ /^(?:(?:$Storage|$Inline|$Attribute)\s+)*((?:un)?signed)((?:\s*\*)*)\s*$/) { + my $sign = $1; + my $pointer = $2; + + $pointer = "" if (!defined $pointer); + + if (WARN("UNSPECIFIED_INT", + "Prefer '" . trim($sign) . " int" . rtrim($pointer) . "' to bare use of '$sign" . rtrim($pointer) . "'\n" . $herecurr) && + $fix) { + my $decl = trim($sign) . " int "; + my $comp_pointer = $pointer; + $comp_pointer =~ s/\s//g; + $decl .= $comp_pointer; + $decl = rtrim($decl) if ($var eq ""); + $fixed[$fixlinenr] =~ s@\b$sign\s*\Q$pointer\E\s*$var\b@$decl$var@; + } + } + } + +# TEST: allow direct testing of the type matcher. + if ($dbg_type) { + if ($line =~ /^.\s*$Declare\s*$/) { + ERROR("TEST_TYPE", + "TEST: is type\n" . $herecurr); + } elsif ($dbg_type > 1 && $line =~ /^.+($Declare)/) { + ERROR("TEST_NOT_TYPE", + "TEST: is not type ($1 is)\n". $herecurr); + } + next; + } +# TEST: allow direct testing of the attribute matcher. + if ($dbg_attr) { + if ($line =~ /^.\s*$Modifier\s*$/) { + ERROR("TEST_ATTR", + "TEST: is attr\n" . $herecurr); + } elsif ($dbg_attr > 1 && $line =~ /^.+($Modifier)/) { + ERROR("TEST_NOT_ATTR", + "TEST: is not attr ($1 is)\n". $herecurr); + } + next; + } + +# check for initialisation to aggregates open brace on the next line + if ($line =~ /^.\s*{/ && + $prevline =~ /(?:^|[^=])=\s*$/) { + if (ERROR("OPEN_BRACE", + "that open brace { should be on the previous line\n" . $hereprev) && + $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { + fix_delete_line($fixlinenr - 1, $prevrawline); + fix_delete_line($fixlinenr, $rawline); + my $fixedline = $prevrawline; + $fixedline =~ s/\s*=\s*$/ = {/; + fix_insert_line($fixlinenr, $fixedline); + $fixedline = $line; + $fixedline =~ s/^(.\s*){\s*/$1/; + fix_insert_line($fixlinenr, $fixedline); + } + } + +# +# Checks which are anchored on the added line. +# + +# check for malformed paths in #include statements (uses RAW line) + if ($rawline =~ m{^.\s*\#\s*include\s+[<"](.*)[">]}) { + my $path = $1; + if ($path =~ m{//}) { + ERROR("MALFORMED_INCLUDE", + "malformed #include filename\n" . $herecurr); + } + if ($path =~ "^uapi/" && $realfile =~ m@\binclude/uapi/@) { + ERROR("UAPI_INCLUDE", + "No #include in ...include/uapi/... should use a uapi/ path prefix\n" . $herecurr); + } + } + +# no C99 // comments + if ($line =~ m{//}) { + if (ERROR("C99_COMMENTS", + "do not use C99 // comments\n" . $herecurr) && + $fix) { + my $line = $fixed[$fixlinenr]; + if ($line =~ /\/\/(.*)$/) { + my $comment = trim($1); + $fixed[$fixlinenr] =~ s@\/\/(.*)$@/\* $comment \*/@; + } + } + } + # Remove C99 comments. + $line =~ s@//.*@@; + $opline =~ s@//.*@@; + +# EXPORT_SYMBOL should immediately follow the thing it is exporting, consider +# the whole statement. +#print "APW <$lines[$realline_next - 1]>\n"; + if (defined $realline_next && + exists $lines[$realline_next - 1] && + !defined $suppress_export{$realline_next} && + ($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/ || + $lines[$realline_next - 1] =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) { + # Handle definitions which produce identifiers with + # a prefix: + # XXX(foo); + # EXPORT_SYMBOL(something_foo); + my $name = $1; + if ($stat =~ /^(?:.\s*}\s*\n)?.([A-Z_]+)\s*\(\s*($Ident)/ && + $name =~ /^${Ident}_$2/) { +#print "FOO C name<$name>\n"; + $suppress_export{$realline_next} = 1; + + } elsif ($stat !~ /(?: + \n.}\s*$| + ^.DEFINE_$Ident\(\Q$name\E\)| + ^.DECLARE_$Ident\(\Q$name\E\)| + ^.LIST_HEAD\(\Q$name\E\)| + ^.(?:$Storage\s+)?$Type\s*\(\s*\*\s*\Q$name\E\s*\)\s*\(| + \b\Q$name\E(?:\s+$Attribute)*\s*(?:;|=|\[|\() + )/x) { +#print "FOO A<$lines[$realline_next - 1]> stat<$stat> name<$name>\n"; + $suppress_export{$realline_next} = 2; + } else { + $suppress_export{$realline_next} = 1; + } + } + if (!defined $suppress_export{$linenr} && + $prevline =~ /^.\s*$/ && + ($line =~ /EXPORT_SYMBOL.*\((.*)\)/ || + $line =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) { +#print "FOO B <$lines[$linenr - 1]>\n"; + $suppress_export{$linenr} = 2; + } + if (defined $suppress_export{$linenr} && + $suppress_export{$linenr} == 2) { + WARN("EXPORT_SYMBOL", + "EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr); + } + +# check for global initialisers. + if ($line =~ /^\+$Type\s*$Ident(?:\s+$Modifier)*\s*=\s*($zero_initializer)\s*;/) { + if (ERROR("GLOBAL_INITIALISERS", + "do not initialise globals to $1\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/(^.$Type\s*$Ident(?:\s+$Modifier)*)\s*=\s*$zero_initializer\s*;/$1;/; + } + } +# check for static initialisers. + if ($line =~ /^\+.*\bstatic\s.*=\s*($zero_initializer)\s*;/) { + if (ERROR("INITIALISED_STATIC", + "do not initialise statics to $1\n" . + $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/(\bstatic\s.*?)\s*=\s*$zero_initializer\s*;/$1;/; + } + } + +# check for misordered declarations of char/short/int/long with signed/unsigned + while ($sline =~ m{(\b$TypeMisordered\b)}g) { + my $tmp = trim($1); + WARN("MISORDERED_TYPE", + "type '$tmp' should be specified in [[un]signed] [short|int|long|long long] order\n" . $herecurr); + } + +# check for static const char * arrays. + if ($line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/) { + WARN("STATIC_CONST_CHAR_ARRAY", + "static const char * array should probably be static const char * const\n" . + $herecurr); + } + +# check for static char foo[] = "bar" declarations. + if ($line =~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=\s*"/) { + WARN("STATIC_CONST_CHAR_ARRAY", + "static char array declaration should probably be static const char\n" . + $herecurr); + } + +# check for const <foo> const where <foo> is not a pointer or array type + if ($sline =~ /\bconst\s+($BasicType)\s+const\b/) { + my $found = $1; + if ($sline =~ /\bconst\s+\Q$found\E\s+const\b\s*\*/) { + WARN("CONST_CONST", + "'const $found const *' should probably be 'const $found * const'\n" . $herecurr); + } elsif ($sline !~ /\bconst\s+\Q$found\E\s+const\s+\w+\s*\[/) { + WARN("CONST_CONST", + "'const $found const' should probably be 'const $found'\n" . $herecurr); + } + } + +# check for non-global char *foo[] = {"bar", ...} declarations. + if ($line =~ /^.\s+(?:static\s+|const\s+)?char\s+\*\s*\w+\s*\[\s*\]\s*=\s*\{/) { + WARN("STATIC_CONST_CHAR_ARRAY", + "char * array declaration might be better as static const\n" . + $herecurr); + } + +# check for sizeof(foo)/sizeof(foo[0]) that could be ARRAY_SIZE(foo) + if ($line =~ m@\bsizeof\s*\(\s*($Lval)\s*\)@) { + my $array = $1; + if ($line =~ m@\b(sizeof\s*\(\s*\Q$array\E\s*\)\s*/\s*sizeof\s*\(\s*\Q$array\E\s*\[\s*0\s*\]\s*\))@) { + my $array_div = $1; + if (WARN("ARRAY_SIZE", + "Prefer ARRAY_SIZE($array)\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\Q$array_div\E/ARRAY_SIZE($array)/; + } + } + } + +# check for function declarations without arguments like "int foo()" + if ($line =~ /(\b$Type\s+$Ident)\s*\(\s*\)/) { + if (ERROR("FUNCTION_WITHOUT_ARGS", + "Bad function definition - $1() should probably be $1(void)\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/(\b($Type)\s+($Ident))\s*\(\s*\)/$2 $3(void)/; + } + } + +# check for uses of DEFINE_PCI_DEVICE_TABLE + if ($line =~ /\bDEFINE_PCI_DEVICE_TABLE\s*\(\s*(\w+)\s*\)\s*=/) { + if (WARN("DEFINE_PCI_DEVICE_TABLE", + "Prefer struct pci_device_id over deprecated DEFINE_PCI_DEVICE_TABLE\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\b(?:static\s+|)DEFINE_PCI_DEVICE_TABLE\s*\(\s*(\w+)\s*\)\s*=\s*/static const struct pci_device_id $1\[\] = /; + } + } + +# check for new typedefs, only function parameters and sparse annotations +# make sense. + if ($line =~ /\btypedef\s/ && + $line !~ /\btypedef\s+$Type\s*\(\s*\*?$Ident\s*\)\s*\(/ && + $line !~ /\btypedef\s+$Type\s+$Ident\s*\(/ && + $line !~ /\b$typeTypedefs\b/ && + $line !~ /\b__bitwise(?:__|)\b/) { + WARN("NEW_TYPEDEFS", + "do not add new typedefs\n" . $herecurr); + } + +# * goes on variable not on type + # (char*[ const]) + while ($line =~ m{(\($NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)\))}g) { + #print "AA<$1>\n"; + my ($ident, $from, $to) = ($1, $2, $2); + + # Should start with a space. + $to =~ s/^(\S)/ $1/; + # Should not end with a space. + $to =~ s/\s+$//; + # '*'s should not have spaces between. + while ($to =~ s/\*\s+\*/\*\*/) { + } + +## print "1: from<$from> to<$to> ident<$ident>\n"; + if ($from ne $to) { + if (ERROR("POINTER_LOCATION", + "\"(foo$from)\" should be \"(foo$to)\"\n" . $herecurr) && + $fix) { + my $sub_from = $ident; + my $sub_to = $ident; + $sub_to =~ s/\Q$from\E/$to/; + $fixed[$fixlinenr] =~ + s@\Q$sub_from\E@$sub_to@; + } + } + } + while ($line =~ m{(\b$NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)($Ident))}g) { + #print "BB<$1>\n"; + my ($match, $from, $to, $ident) = ($1, $2, $2, $3); + + # Should start with a space. + $to =~ s/^(\S)/ $1/; + # Should not end with a space. + $to =~ s/\s+$//; + # '*'s should not have spaces between. + while ($to =~ s/\*\s+\*/\*\*/) { + } + # Modifiers should have spaces. + $to =~ s/(\b$Modifier$)/$1 /; + +## print "2: from<$from> to<$to> ident<$ident>\n"; + if ($from ne $to && $ident !~ /^$Modifier$/) { + if (ERROR("POINTER_LOCATION", + "\"foo${from}bar\" should be \"foo${to}bar\"\n" . $herecurr) && + $fix) { + + my $sub_from = $match; + my $sub_to = $match; + $sub_to =~ s/\Q$from\E/$to/; + $fixed[$fixlinenr] =~ + s@\Q$sub_from\E@$sub_to@; + } + } + } + +# avoid BUG() or BUG_ON() + if ($line =~ /\b(?:BUG|BUG_ON)\b/) { + my $msg_type = \&WARN; + $msg_type = \&CHK if ($file); + &{$msg_type}("AVOID_BUG", + "Avoid crashing the kernel - try using WARN_ON & recovery code rather than BUG() or BUG_ON()\n" . $herecurr); + } + +# avoid LINUX_VERSION_CODE + if ($line =~ /\bLINUX_VERSION_CODE\b/) { + WARN("LINUX_VERSION_CODE", + "LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged\n" . $herecurr); + } + +# check for uses of printk_ratelimit + if ($line =~ /\bprintk_ratelimit\s*\(/) { + WARN("PRINTK_RATELIMITED", + "Prefer printk_ratelimited or pr_<level>_ratelimited to printk_ratelimit\n" . $herecurr); + } + +# printk should use KERN_* levels. Note that follow on printk's on the +# same line do not need a level, so we use the current block context +# to try and find and validate the current printk. In summary the current +# printk includes all preceding printk's which have no newline on the end. +# we assume the first bad printk is the one to report. + if ($line =~ /\bprintk\((?!KERN_)\s*"/) { + my $ok = 0; + for (my $ln = $linenr - 1; $ln >= $first_line; $ln--) { + #print "CHECK<$lines[$ln - 1]\n"; + # we have a preceding printk if it ends + # with "\n" ignore it, else it is to blame + if ($lines[$ln - 1] =~ m{\bprintk\(}) { + if ($rawlines[$ln - 1] !~ m{\\n"}) { + $ok = 1; + } + last; + } + } + if ($ok == 0) { + WARN("PRINTK_WITHOUT_KERN_LEVEL", + "printk() should include KERN_ facility level\n" . $herecurr); + } + } + + if ($line =~ /\bprintk\s*\(\s*KERN_([A-Z]+)/) { + my $orig = $1; + my $level = lc($orig); + $level = "warn" if ($level eq "warning"); + my $level2 = $level; + $level2 = "dbg" if ($level eq "debug"); + WARN("PREFER_PR_LEVEL", + "Prefer [subsystem eg: netdev]_$level2([subsystem]dev, ... then dev_$level2(dev, ... then pr_$level(... to printk(KERN_$orig ...\n" . $herecurr); + } + + if ($line =~ /\bpr_warning\s*\(/) { + if (WARN("PREFER_PR_LEVEL", + "Prefer pr_warn(... to pr_warning(...\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ + s/\bpr_warning\b/pr_warn/; + } + } + + if ($line =~ /\bdev_printk\s*\(\s*KERN_([A-Z]+)/) { + my $orig = $1; + my $level = lc($orig); + $level = "warn" if ($level eq "warning"); + $level = "dbg" if ($level eq "debug"); + WARN("PREFER_DEV_LEVEL", + "Prefer dev_$level(... to dev_printk(KERN_$orig, ...\n" . $herecurr); + } + +# ENOSYS means "bad syscall nr" and nothing else. This will have a small +# number of false positives, but assembly files are not checked, so at +# least the arch entry code will not trigger this warning. + if ($line =~ /\bENOSYS\b/) { + WARN("ENOSYS", + "ENOSYS means 'invalid syscall nr' and nothing else\n" . $herecurr); + } + +# function brace can't be on same line, except for #defines of do while, +# or if closed on same line + if (($line=~/$Type\s*$Ident\(.*\).*\s*{/) and + !($line=~/\#\s*define.*do\s\{/) and !($line=~/}/)) { + if (ERROR("OPEN_BRACE", + "open brace '{' following function declarations go on the next line\n" . $herecurr) && + $fix) { + fix_delete_line($fixlinenr, $rawline); + my $fixed_line = $rawline; + $fixed_line =~ /(^..*$Type\s*$Ident\(.*\)\s*){(.*)$/; + my $line1 = $1; + my $line2 = $2; + fix_insert_line($fixlinenr, ltrim($line1)); + fix_insert_line($fixlinenr, "\+{"); + if ($line2 !~ /^\s*$/) { + fix_insert_line($fixlinenr, "\+\t" . trim($line2)); + } + } + } + +# open braces for enum, union and struct go on the same line. + if ($line =~ /^.\s*{/ && + $prevline =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?\s*$/) { + if (ERROR("OPEN_BRACE", + "open brace '{' following $1 go on the same line\n" . $hereprev) && + $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { + fix_delete_line($fixlinenr - 1, $prevrawline); + fix_delete_line($fixlinenr, $rawline); + my $fixedline = rtrim($prevrawline) . " {"; + fix_insert_line($fixlinenr, $fixedline); + $fixedline = $rawline; + $fixedline =~ s/^(.\s*){\s*/$1\t/; + if ($fixedline !~ /^\+\s*$/) { + fix_insert_line($fixlinenr, $fixedline); + } + } + } + +# missing space after union, struct or enum definition + if ($line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident){1,2}[=\{]/) { + if (WARN("SPACING", + "missing space after $1 definition\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ + s/^(.\s*(?:typedef\s+)?(?:enum|union|struct)(?:\s+$Ident){1,2})([=\{])/$1 $2/; + } + } + +# Function pointer declarations +# check spacing between type, funcptr, and args +# canonical declaration is "type (*funcptr)(args...)" + if ($line =~ /^.\s*($Declare)\((\s*)\*(\s*)($Ident)(\s*)\)(\s*)\(/) { + my $declare = $1; + my $pre_pointer_space = $2; + my $post_pointer_space = $3; + my $funcname = $4; + my $post_funcname_space = $5; + my $pre_args_space = $6; + +# the $Declare variable will capture all spaces after the type +# so check it for a missing trailing missing space but pointer return types +# don't need a space so don't warn for those. + my $post_declare_space = ""; + if ($declare =~ /(\s+)$/) { + $post_declare_space = $1; + $declare = rtrim($declare); + } + if ($declare !~ /\*$/ && $post_declare_space =~ /^$/) { + WARN("SPACING", + "missing space after return type\n" . $herecurr); + $post_declare_space = " "; + } + +# unnecessary space "type (*funcptr)(args...)" +# This test is not currently implemented because these declarations are +# equivalent to +# int foo(int bar, ...) +# and this is form shouldn't/doesn't generate a checkpatch warning. +# +# elsif ($declare =~ /\s{2,}$/) { +# WARN("SPACING", +# "Multiple spaces after return type\n" . $herecurr); +# } + +# unnecessary space "type ( *funcptr)(args...)" + if (defined $pre_pointer_space && + $pre_pointer_space =~ /^\s/) { + WARN("SPACING", + "Unnecessary space after function pointer open parenthesis\n" . $herecurr); + } + +# unnecessary space "type (* funcptr)(args...)" + if (defined $post_pointer_space && + $post_pointer_space =~ /^\s/) { + WARN("SPACING", + "Unnecessary space before function pointer name\n" . $herecurr); + } + +# unnecessary space "type (*funcptr )(args...)" + if (defined $post_funcname_space && + $post_funcname_space =~ /^\s/) { + WARN("SPACING", + "Unnecessary space after function pointer name\n" . $herecurr); + } + +# unnecessary space "type (*funcptr) (args...)" + if (defined $pre_args_space && + $pre_args_space =~ /^\s/) { + WARN("SPACING", + "Unnecessary space before function pointer arguments\n" . $herecurr); + } + + if (show_type("SPACING") && $fix) { + $fixed[$fixlinenr] =~ + s/^(.\s*)$Declare\s*\(\s*\*\s*$Ident\s*\)\s*\(/$1 . $declare . $post_declare_space . '(*' . $funcname . ')('/ex; + } + } + +# check for spacing round square brackets; allowed: +# 1. with a type on the left -- int [] a; +# 2. at the beginning of a line for slice initialisers -- [0...10] = 5, +# 3. inside a curly brace -- = { [0...10] = 5 } + while ($line =~ /(.*?\s)\[/g) { + my ($where, $prefix) = ($-[1], $1); + if ($prefix !~ /$Type\s+$/ && + ($where != 0 || $prefix !~ /^.\s+$/) && + $prefix !~ /[{,]\s+$/) { + if (ERROR("BRACKET_SPACE", + "space prohibited before open square bracket '['\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ + s/^(\+.*?)\s+\[/$1\[/; + } + } + } + +# check for spaces between functions and their parentheses. + while ($line =~ /($Ident)\s+\(/g) { + my $name = $1; + my $ctx_before = substr($line, 0, $-[1]); + my $ctx = "$ctx_before$name"; + + # Ignore those directives where spaces _are_ permitted. + if ($name =~ /^(?: + if|for|while|switch|return|case| + volatile|__volatile__| + __attribute__|format|__extension__| + asm|__asm__)$/x) + { + # cpp #define statements have non-optional spaces, ie + # if there is a space between the name and the open + # parenthesis it is simply not a parameter group. + } elsif ($ctx_before =~ /^.\s*\#\s*define\s*$/) { + + # cpp #elif statement condition may start with a ( + } elsif ($ctx =~ /^.\s*\#\s*elif\s*$/) { + + # If this whole things ends with a type its most + # likely a typedef for a function. + } elsif ($ctx =~ /$Type$/) { + + } else { + if (WARN("SPACING", + "space prohibited between function name and open parenthesis '('\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ + s/\b$name\s+\(/$name\(/; + } + } + } + +# Check operator spacing. + if (!($line=~/\#\s*include/)) { + my $fixed_line = ""; + my $line_fixed = 0; + + my $ops = qr{ + <<=|>>=|<=|>=|==|!=| + \+=|-=|\*=|\/=|%=|\^=|\|=|&=| + =>|->|<<|>>|<|>|=|!|~| + &&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%| + \?:|\?|: + }x; + my @elements = split(/($ops|;)/, $opline); + +## print("element count: <" . $#elements . ">\n"); +## foreach my $el (@elements) { +## print("el: <$el>\n"); +## } + + my @fix_elements = (); + my $off = 0; + + foreach my $el (@elements) { + push(@fix_elements, substr($rawline, $off, length($el))); + $off += length($el); + } + + $off = 0; + + my $blank = copy_spacing($opline); + my $last_after = -1; + + for (my $n = 0; $n < $#elements; $n += 2) { + + my $good = $fix_elements[$n] . $fix_elements[$n + 1]; + +## print("n: <$n> good: <$good>\n"); + + $off += length($elements[$n]); + + # Pick up the preceding and succeeding characters. + my $ca = substr($opline, 0, $off); + my $cc = ''; + if (length($opline) >= ($off + length($elements[$n + 1]))) { + $cc = substr($opline, $off + length($elements[$n + 1])); + } + my $cb = "$ca$;$cc"; + + my $a = ''; + $a = 'V' if ($elements[$n] ne ''); + $a = 'W' if ($elements[$n] =~ /\s$/); + $a = 'C' if ($elements[$n] =~ /$;$/); + $a = 'B' if ($elements[$n] =~ /(\[|\()$/); + $a = 'O' if ($elements[$n] eq ''); + $a = 'E' if ($ca =~ /^\s*$/); + + my $op = $elements[$n + 1]; + + my $c = ''; + if (defined $elements[$n + 2]) { + $c = 'V' if ($elements[$n + 2] ne ''); + $c = 'W' if ($elements[$n + 2] =~ /^\s/); + $c = 'C' if ($elements[$n + 2] =~ /^$;/); + $c = 'B' if ($elements[$n + 2] =~ /^(\)|\]|;)/); + $c = 'O' if ($elements[$n + 2] eq ''); + $c = 'E' if ($elements[$n + 2] =~ /^\s*\\$/); + } else { + $c = 'E'; + } + + my $ctx = "${a}x${c}"; + + my $at = "(ctx:$ctx)"; + + my $ptr = substr($blank, 0, $off) . "^"; + my $hereptr = "$hereline$ptr\n"; + + # Pull out the value of this operator. + my $op_type = substr($curr_values, $off + 1, 1); + + # Get the full operator variant. + my $opv = $op . substr($curr_vars, $off, 1); + + # Ignore operators passed as parameters. + if ($op_type ne 'V' && + $ca =~ /\s$/ && $cc =~ /^\s*[,\)]/) { + +# # Ignore comments +# } elsif ($op =~ /^$;+$/) { + + # ; should have either the end of line or a space or \ after it + } elsif ($op eq ';') { + if ($ctx !~ /.x[WEBC]/ && + $cc !~ /^\\/ && $cc !~ /^;/) { + if (ERROR("SPACING", + "space required after that '$op' $at\n" . $hereptr)) { + $good = $fix_elements[$n] . trim($fix_elements[$n + 1]) . " "; + $line_fixed = 1; + } + } + + # // is a comment + } elsif ($op eq '//') { + + # : when part of a bitfield + } elsif ($opv eq ':B') { + # skip the bitfield test for now + + # No spaces for: + # -> + } elsif ($op eq '->') { + if ($ctx =~ /Wx.|.xW/) { + if (ERROR("SPACING", + "spaces prohibited around that '$op' $at\n" . $hereptr)) { + $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); + if (defined $fix_elements[$n + 2]) { + $fix_elements[$n + 2] =~ s/^\s+//; + } + $line_fixed = 1; + } + } + + # , must not have a space before and must have a space on the right. + } elsif ($op eq ',') { + my $rtrim_before = 0; + my $space_after = 0; + if ($ctx =~ /Wx./) { + if (ERROR("SPACING", + "space prohibited before that '$op' $at\n" . $hereptr)) { + $line_fixed = 1; + $rtrim_before = 1; + } + } + if ($ctx !~ /.x[WEC]/ && $cc !~ /^}/) { + if (ERROR("SPACING", + "space required after that '$op' $at\n" . $hereptr)) { + $line_fixed = 1; + $last_after = $n; + $space_after = 1; + } + } + if ($rtrim_before || $space_after) { + if ($rtrim_before) { + $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); + } else { + $good = $fix_elements[$n] . trim($fix_elements[$n + 1]); + } + if ($space_after) { + $good .= " "; + } + } + + # '*' as part of a type definition -- reported already. + } elsif ($opv eq '*_') { + #warn "'*' is part of type\n"; + + # unary operators should have a space before and + # none after. May be left adjacent to another + # unary operator, or a cast + } elsif ($op eq '!' || $op eq '~' || + $opv eq '*U' || $opv eq '-U' || + $opv eq '&U' || $opv eq '&&U') { + if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) { + if (ERROR("SPACING", + "space required before that '$op' $at\n" . $hereptr)) { + if ($n != $last_after + 2) { + $good = $fix_elements[$n] . " " . ltrim($fix_elements[$n + 1]); + $line_fixed = 1; + } + } + } + if ($op eq '*' && $cc =~/\s*$Modifier\b/) { + # A unary '*' may be const + + } elsif ($ctx =~ /.xW/) { + if (ERROR("SPACING", + "space prohibited after that '$op' $at\n" . $hereptr)) { + $good = $fix_elements[$n] . rtrim($fix_elements[$n + 1]); + if (defined $fix_elements[$n + 2]) { + $fix_elements[$n + 2] =~ s/^\s+//; + } + $line_fixed = 1; + } + } + + # unary ++ and unary -- are allowed no space on one side. + } elsif ($op eq '++' or $op eq '--') { + if ($ctx !~ /[WEOBC]x[^W]/ && $ctx !~ /[^W]x[WOBEC]/) { + if (ERROR("SPACING", + "space required one side of that '$op' $at\n" . $hereptr)) { + $good = $fix_elements[$n] . trim($fix_elements[$n + 1]) . " "; + $line_fixed = 1; + } + } + if ($ctx =~ /Wx[BE]/ || + ($ctx =~ /Wx./ && $cc =~ /^;/)) { + if (ERROR("SPACING", + "space prohibited before that '$op' $at\n" . $hereptr)) { + $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); + $line_fixed = 1; + } + } + if ($ctx =~ /ExW/) { + if (ERROR("SPACING", + "space prohibited after that '$op' $at\n" . $hereptr)) { + $good = $fix_elements[$n] . trim($fix_elements[$n + 1]); + if (defined $fix_elements[$n + 2]) { + $fix_elements[$n + 2] =~ s/^\s+//; + } + $line_fixed = 1; + } + } + + # << and >> may either have or not have spaces both sides + } elsif ($op eq '<<' or $op eq '>>' or + $op eq '&' or $op eq '^' or $op eq '|' or + $op eq '+' or $op eq '-' or + $op eq '*' or $op eq '/' or + $op eq '%') + { + if ($check) { + if (defined $fix_elements[$n + 2] && $ctx !~ /[EW]x[EW]/) { + if (CHK("SPACING", + "spaces preferred around that '$op' $at\n" . $hereptr)) { + $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " "; + $fix_elements[$n + 2] =~ s/^\s+//; + $line_fixed = 1; + } + } elsif (!defined $fix_elements[$n + 2] && $ctx !~ /Wx[OE]/) { + if (CHK("SPACING", + "space preferred before that '$op' $at\n" . $hereptr)) { + $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]); + $line_fixed = 1; + } + } + } elsif ($ctx =~ /Wx[^WCE]|[^WCE]xW/) { + if (ERROR("SPACING", + "need consistent spacing around '$op' $at\n" . $hereptr)) { + $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " "; + if (defined $fix_elements[$n + 2]) { + $fix_elements[$n + 2] =~ s/^\s+//; + } + $line_fixed = 1; + } + } + + # A colon needs no spaces before when it is + # terminating a case value or a label. + } elsif ($opv eq ':C' || $opv eq ':L') { + if ($ctx =~ /Wx./) { + if (ERROR("SPACING", + "space prohibited before that '$op' $at\n" . $hereptr)) { + $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); + $line_fixed = 1; + } + } + + # All the others need spaces both sides. + } elsif ($ctx !~ /[EWC]x[CWE]/) { + my $ok = 0; + + # Ignore email addresses <foo@bar> + if (($op eq '<' && + $cc =~ /^\S+\@\S+>/) || + ($op eq '>' && + $ca =~ /<\S+\@\S+$/)) + { + $ok = 1; + } + + # for asm volatile statements + # ignore a colon with another + # colon immediately before or after + if (($op eq ':') && + ($ca =~ /:$/ || $cc =~ /^:/)) { + $ok = 1; + } + + # messages are ERROR, but ?: are CHK + if ($ok == 0) { + my $msg_type = \&ERROR; + $msg_type = \&CHK if (($op eq '?:' || $op eq '?' || $op eq ':') && $ctx =~ /VxV/); + + if (&{$msg_type}("SPACING", + "spaces required around that '$op' $at\n" . $hereptr)) { + $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " "; + if (defined $fix_elements[$n + 2]) { + $fix_elements[$n + 2] =~ s/^\s+//; + } + $line_fixed = 1; + } + } + } + $off += length($elements[$n + 1]); + +## print("n: <$n> GOOD: <$good>\n"); + + $fixed_line = $fixed_line . $good; + } + + if (($#elements % 2) == 0) { + $fixed_line = $fixed_line . $fix_elements[$#elements]; + } + + if ($fix && $line_fixed && $fixed_line ne $fixed[$fixlinenr]) { + $fixed[$fixlinenr] = $fixed_line; + } + + + } + +# check for whitespace before a non-naked semicolon + if ($line =~ /^\+.*\S\s+;\s*$/) { + if (WARN("SPACING", + "space prohibited before semicolon\n" . $herecurr) && + $fix) { + 1 while $fixed[$fixlinenr] =~ + s/^(\+.*\S)\s+;/$1;/; + } + } + +# check for multiple assignments + if ($line =~ /^.\s*$Lval\s*=\s*$Lval\s*=(?!=)/) { + CHK("MULTIPLE_ASSIGNMENTS", + "multiple assignments should be avoided\n" . $herecurr); + } + +## # check for multiple declarations, allowing for a function declaration +## # continuation. +## if ($line =~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Ident.*/ && +## $line !~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Type\s*$Ident.*/) { +## +## # Remove any bracketed sections to ensure we do not +## # falsly report the parameters of functions. +## my $ln = $line; +## while ($ln =~ s/\([^\(\)]*\)//g) { +## } +## if ($ln =~ /,/) { +## WARN("MULTIPLE_DECLARATION", +## "declaring multiple variables together should be avoided\n" . $herecurr); +## } +## } + +#need space before brace following if, while, etc + if (($line =~ /\(.*\)\{/ && $line !~ /\($Type\)\{/) || + $line =~ /do\{/) { + if (ERROR("SPACING", + "space required before the open brace '{'\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/^(\+.*(?:do|\))){/$1 {/; + } + } + +## # check for blank lines before declarations +## if ($line =~ /^.\t+$Type\s+$Ident(?:\s*=.*)?;/ && +## $prevrawline =~ /^.\s*$/) { +## WARN("SPACING", +## "No blank lines before declarations\n" . $hereprev); +## } +## + +# closing brace should have a space following it when it has anything +# on the line + if ($line =~ /}(?!(?:,|;|\)))\S/) { + if (ERROR("SPACING", + "space required after that close brace '}'\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ + s/}((?!(?:,|;|\)))\S)/} $1/; + } + } + +# check spacing on square brackets + if ($line =~ /\[\s/ && $line !~ /\[\s*$/) { + if (ERROR("SPACING", + "space prohibited after that open square bracket '['\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ + s/\[\s+/\[/; + } + } + if ($line =~ /\s\]/) { + if (ERROR("SPACING", + "space prohibited before that close square bracket ']'\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ + s/\s+\]/\]/; + } + } + +# check spacing on parentheses + if ($line =~ /\(\s/ && $line !~ /\(\s*(?:\\)?$/ && + $line !~ /for\s*\(\s+;/) { + if (ERROR("SPACING", + "space prohibited after that open parenthesis '('\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ + s/\(\s+/\(/; + } + } + if ($line =~ /(\s+)\)/ && $line !~ /^.\s*\)/ && + $line !~ /for\s*\(.*;\s+\)/ && + $line !~ /:\s+\)/) { + if (ERROR("SPACING", + "space prohibited before that close parenthesis ')'\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ + s/\s+\)/\)/; + } + } + +# check unnecessary parentheses around addressof/dereference single $Lvals +# ie: &(foo->bar) should be &foo->bar and *(foo->bar) should be *foo->bar + + while ($line =~ /(?:[^&]&\s*|\*)\(\s*($Ident\s*(?:$Member\s*)+)\s*\)/g) { + my $var = $1; + if (CHK("UNNECESSARY_PARENTHESES", + "Unnecessary parentheses around $var\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\(\s*\Q$var\E\s*\)/$var/; + } + } + +# check for unnecessary parentheses around function pointer uses +# ie: (foo->bar)(); should be foo->bar(); +# but not "if (foo->bar) (" to avoid some false positives + if ($line =~ /(\bif\s*|)(\(\s*$Ident\s*(?:$Member\s*)+\))[ \t]*\(/ && $1 !~ /^if/) { + my $var = $2; + if (CHK("UNNECESSARY_PARENTHESES", + "Unnecessary parentheses around function pointer $var\n" . $herecurr) && + $fix) { + my $var2 = deparenthesize($var); + $var2 =~ s/\s//g; + $fixed[$fixlinenr] =~ s/\Q$var\E/$var2/; + } + } + +#goto labels aren't indented, allow a single space however + if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and + !($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) { + if (WARN("INDENTED_LABEL", + "labels should not be indented\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ + s/^(.)\s+/$1/; + } + } + +# return is not a function + if (defined($stat) && $stat =~ /^.\s*return(\s*)\(/s) { + my $spacing = $1; + if ($^V && $^V ge 5.10.0 && + $stat =~ /^.\s*return\s*($balanced_parens)\s*;\s*$/) { + my $value = $1; + $value = deparenthesize($value); + if ($value =~ m/^\s*$FuncArg\s*(?:\?|$)/) { + ERROR("RETURN_PARENTHESES", + "return is not a function, parentheses are not required\n" . $herecurr); + } + } elsif ($spacing !~ /\s+/) { + ERROR("SPACING", + "space required before the open parenthesis '('\n" . $herecurr); + } + } + +# unnecessary return in a void function +# at end-of-function, with the previous line a single leading tab, then return; +# and the line before that not a goto label target like "out:" + if ($sline =~ /^[ \+]}\s*$/ && + $prevline =~ /^\+\treturn\s*;\s*$/ && + $linenr >= 3 && + $lines[$linenr - 3] =~ /^[ +]/ && + $lines[$linenr - 3] !~ /^[ +]\s*$Ident\s*:/) { + WARN("RETURN_VOID", + "void function return statements are not generally useful\n" . $hereprev); + } + +# if statements using unnecessary parentheses - ie: if ((foo == bar)) + if ($^V && $^V ge 5.10.0 && + $line =~ /\bif\s*((?:\(\s*){2,})/) { + my $openparens = $1; + my $count = $openparens =~ tr@\(@\(@; + my $msg = ""; + if ($line =~ /\bif\s*(?:\(\s*){$count,$count}$LvalOrFunc\s*($Compare)\s*$LvalOrFunc(?:\s*\)){$count,$count}/) { + my $comp = $4; #Not $1 because of $LvalOrFunc + $msg = " - maybe == should be = ?" if ($comp eq "=="); + WARN("UNNECESSARY_PARENTHESES", + "Unnecessary parentheses$msg\n" . $herecurr); + } + } + +# comparisons with a constant or upper case identifier on the left +# avoid cases like "foo + BAR < baz" +# only fix matches surrounded by parentheses to avoid incorrect +# conversions like "FOO < baz() + 5" being "misfixed" to "baz() > FOO + 5" + if ($^V && $^V ge 5.10.0 && + $line =~ /^\+(.*)\b($Constant|[A-Z_][A-Z0-9_]*)\s*($Compare)\s*($LvalOrFunc)/) { + my $lead = $1; + my $const = $2; + my $comp = $3; + my $to = $4; + my $newcomp = $comp; + if ($lead !~ /$Operators\s*$/ && + $to !~ /^(?:Constant|[A-Z_][A-Z0-9_]*)$/ && + WARN("CONSTANT_COMPARISON", + "Comparisons should place the constant on the right side of the test\n" . $herecurr) && + $fix) { + if ($comp eq "<") { + $newcomp = ">"; + } elsif ($comp eq "<=") { + $newcomp = ">="; + } elsif ($comp eq ">") { + $newcomp = "<"; + } elsif ($comp eq ">=") { + $newcomp = "<="; + } + $fixed[$fixlinenr] =~ s/\(\s*\Q$const\E\s*$Compare\s*\Q$to\E\s*\)/($to $newcomp $const)/; + } + } + +# Return of what appears to be an errno should normally be negative + if ($sline =~ /\breturn(?:\s*\(+\s*|\s+)(E[A-Z]+)(?:\s*\)+\s*|\s*)[;:,]/) { + my $name = $1; + if ($name ne 'EOF' && $name ne 'ERROR') { + WARN("USE_NEGATIVE_ERRNO", + "return of an errno should typically be negative (ie: return -$1)\n" . $herecurr); + } + } + +# Need a space before open parenthesis after if, while etc + if ($line =~ /\b(if|while|for|switch)\(/) { + if (ERROR("SPACING", + "space required before the open parenthesis '('\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ + s/\b(if|while|for|switch)\(/$1 \(/; + } + } + +# Check for illegal assignment in if conditional -- and check for trailing +# statements after the conditional. + if ($line =~ /do\s*(?!{)/) { + ($stat, $cond, $line_nr_next, $remain_next, $off_next) = + ctx_statement_block($linenr, $realcnt, 0) + if (!defined $stat); + my ($stat_next) = ctx_statement_block($line_nr_next, + $remain_next, $off_next); + $stat_next =~ s/\n./\n /g; + ##print "stat<$stat> stat_next<$stat_next>\n"; + + if ($stat_next =~ /^\s*while\b/) { + # If the statement carries leading newlines, + # then count those as offsets. + my ($whitespace) = + ($stat_next =~ /^((?:\s*\n[+-])*\s*)/s); + my $offset = + statement_rawlines($whitespace) - 1; + + $suppress_whiletrailers{$line_nr_next + + $offset} = 1; + } + } + if (!defined $suppress_whiletrailers{$linenr} && + defined($stat) && defined($cond) && + $line =~ /\b(?:if|while|for)\s*\(/ && $line !~ /^.\s*#/) { + my ($s, $c) = ($stat, $cond); + + if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/s) { + ERROR("ASSIGN_IN_IF", + "do not use assignment in if condition\n" . $herecurr); + } + + # Find out what is on the end of the line after the + # conditional. + substr($s, 0, length($c), ''); + $s =~ s/\n.*//g; + $s =~ s/$;//g; # Remove any comments + if (length($c) && $s !~ /^\s*{?\s*\\*\s*$/ && + $c !~ /}\s*while\s*/) + { + # Find out how long the conditional actually is. + my @newlines = ($c =~ /\n/gs); + my $cond_lines = 1 + $#newlines; + my $stat_real = ''; + + $stat_real = raw_line($linenr, $cond_lines) + . "\n" if ($cond_lines); + if (defined($stat_real) && $cond_lines > 1) { + $stat_real = "[...]\n$stat_real"; + } + + ERROR("TRAILING_STATEMENTS", + "trailing statements should be on next line\n" . $herecurr . $stat_real); + } + } + +# Check for bitwise tests written as boolean + if ($line =~ / + (?: + (?:\[|\(|\&\&|\|\|) + \s*0[xX][0-9]+\s* + (?:\&\&|\|\|) + | + (?:\&\&|\|\|) + \s*0[xX][0-9]+\s* + (?:\&\&|\|\||\)|\]) + )/x) + { + WARN("HEXADECIMAL_BOOLEAN_TEST", + "boolean test with hexadecimal, perhaps just 1 \& or \|?\n" . $herecurr); + } + +# if and else should not have general statements after it + if ($line =~ /^.\s*(?:}\s*)?else\b(.*)/) { + my $s = $1; + $s =~ s/$;//g; # Remove any comments + if ($s !~ /^\s*(?:\sif|(?:{|)\s*\\?\s*$)/) { + ERROR("TRAILING_STATEMENTS", + "trailing statements should be on next line\n" . $herecurr); + } + } +# if should not continue a brace + if ($line =~ /}\s*if\b/) { + ERROR("TRAILING_STATEMENTS", + "trailing statements should be on next line (or did you mean 'else if'?)\n" . + $herecurr); + } +# case and default should not have general statements after them + if ($line =~ /^.\s*(?:case\s*.*|default\s*):/g && + $line !~ /\G(?: + (?:\s*$;*)(?:\s*{)?(?:\s*$;*)(?:\s*\\)?\s*$| + \s*return\s+ + )/xg) + { + ERROR("TRAILING_STATEMENTS", + "trailing statements should be on next line\n" . $herecurr); + } + + # Check for }<nl>else {, these must be at the same + # indent level to be relevant to each other. + if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ && + $previndent == $indent) { + if (ERROR("ELSE_AFTER_BRACE", + "else should follow close brace '}'\n" . $hereprev) && + $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { + fix_delete_line($fixlinenr - 1, $prevrawline); + fix_delete_line($fixlinenr, $rawline); + my $fixedline = $prevrawline; + $fixedline =~ s/}\s*$//; + if ($fixedline !~ /^\+\s*$/) { + fix_insert_line($fixlinenr, $fixedline); + } + $fixedline = $rawline; + $fixedline =~ s/^(.\s*)else/$1} else/; + fix_insert_line($fixlinenr, $fixedline); + } + } + + if ($prevline=~/}\s*$/ and $line=~/^.\s*while\s*/ && + $previndent == $indent) { + my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0); + + # Find out what is on the end of the line after the + # conditional. + substr($s, 0, length($c), ''); + $s =~ s/\n.*//g; + + if ($s =~ /^\s*;/) { + if (ERROR("WHILE_AFTER_BRACE", + "while should follow close brace '}'\n" . $hereprev) && + $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { + fix_delete_line($fixlinenr - 1, $prevrawline); + fix_delete_line($fixlinenr, $rawline); + my $fixedline = $prevrawline; + my $trailing = $rawline; + $trailing =~ s/^\+//; + $trailing = trim($trailing); + $fixedline =~ s/}\s*$/} $trailing/; + fix_insert_line($fixlinenr, $fixedline); + } + } + } + +#Specific variable tests + while ($line =~ m{($Constant|$Lval)}g) { + my $var = $1; + +#gcc binary extension + if ($var =~ /^$Binary$/) { + if (WARN("GCC_BINARY_CONSTANT", + "Avoid gcc v4.3+ binary constant extension: <$var>\n" . $herecurr) && + $fix) { + my $hexval = sprintf("0x%x", oct($var)); + $fixed[$fixlinenr] =~ + s/\b$var\b/$hexval/; + } + } + +#CamelCase + if ($var !~ /^$Constant$/ && + $var =~ /[A-Z][a-z]|[a-z][A-Z]/ && +#Ignore Page<foo> variants + $var !~ /^(?:Clear|Set|TestClear|TestSet|)Page[A-Z]/ && +#Ignore SI style variants like nS, mV and dB (ie: max_uV, regulator_min_uA_show) + $var !~ /^(?:[a-z_]*?)_?[a-z][A-Z](?:_[a-z_]+)?$/ && +#Ignore some three character SI units explicitly, like MiB and KHz + $var !~ /^(?:[a-z_]*?)_?(?:[KMGT]iB|[KMGT]?Hz)(?:_[a-z_]+)?$/) { + while ($var =~ m{($Ident)}g) { + my $word = $1; + next if ($word !~ /[A-Z][a-z]|[a-z][A-Z]/); + if ($check) { + seed_camelcase_includes(); + if (!$file && !$camelcase_file_seeded) { + seed_camelcase_file($realfile); + $camelcase_file_seeded = 1; + } + } + if (!defined $camelcase{$word}) { + $camelcase{$word} = 1; + CHK("CAMELCASE", + "Avoid CamelCase: <$word>\n" . $herecurr); + } + } + } + } + +#no spaces allowed after \ in define + if ($line =~ /\#\s*define.*\\\s+$/) { + if (WARN("WHITESPACE_AFTER_LINE_CONTINUATION", + "Whitespace after \\ makes next lines useless\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\s+$//; + } + } + +# warn if <asm/foo.h> is #included and <linux/foo.h> is available and includes +# itself <asm/foo.h> (uses RAW line) + if ($tree && $rawline =~ m{^.\s*\#\s*include\s*\<asm\/(.*)\.h\>}) { + my $file = "$1.h"; + my $checkfile = "include/linux/$file"; + if (-f "$root/$checkfile" && + $realfile ne $checkfile && + $1 !~ /$allowed_asm_includes/) + { + my $asminclude = `grep -Ec "#include\\s+<asm/$file>" $root/$checkfile`; + if ($asminclude > 0) { + if ($realfile =~ m{^arch/}) { + CHK("ARCH_INCLUDE_LINUX", + "Consider using #include <linux/$file> instead of <asm/$file>\n" . $herecurr); + } else { + WARN("INCLUDE_LINUX", + "Use #include <linux/$file> instead of <asm/$file>\n" . $herecurr); + } + } + } + } + +# multi-statement macros should be enclosed in a do while loop, grab the +# first statement and ensure its the whole macro if its not enclosed +# in a known good container + if ($realfile !~ m@/vmlinux.lds.h$@ && + $line =~ /^.\s*\#\s*define\s*$Ident(\()?/) { + my $ln = $linenr; + my $cnt = $realcnt; + my ($off, $dstat, $dcond, $rest); + my $ctx = ''; + my $has_flow_statement = 0; + my $has_arg_concat = 0; + ($dstat, $dcond, $ln, $cnt, $off) = + ctx_statement_block($linenr, $realcnt, 0); + $ctx = $dstat; + #print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n"; + #print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n"; + + $has_flow_statement = 1 if ($ctx =~ /\b(goto|return)\b/); + $has_arg_concat = 1 if ($ctx =~ /\#\#/ && $ctx !~ /\#\#\s*(?:__VA_ARGS__|args)\b/); + + $dstat =~ s/^.\s*\#\s*define\s+$Ident(?:\([^\)]*\))?\s*//; + $dstat =~ s/$;//g; + $dstat =~ s/\\\n.//g; + $dstat =~ s/^\s*//s; + $dstat =~ s/\s*$//s; + + # Flatten any parentheses and braces + while ($dstat =~ s/\([^\(\)]*\)/1/ || + $dstat =~ s/\{[^\{\}]*\}/1/ || + $dstat =~ s/.\[[^\[\]]*\]/1/) + { + } + + # Flatten any obvious string concatentation. + while ($dstat =~ s/($String)\s*$Ident/$1/ || + $dstat =~ s/$Ident\s*($String)/$1/) + { + } + + # Make asm volatile uses seem like a generic function + $dstat =~ s/\b_*asm_*\s+_*volatile_*\b/asm_volatile/g; + + my $exceptions = qr{ + $Declare| + module_param_named| + MODULE_PARM_DESC| + DECLARE_PER_CPU| + DEFINE_PER_CPU| + __typeof__\(| + union| + struct| + \.$Ident\s*=\s*| + ^\"|\"$| + ^\[ + }x; + #print "REST<$rest> dstat<$dstat> ctx<$ctx>\n"; + if ($dstat ne '' && + $dstat !~ /^(?:$Ident|-?$Constant),$/ && # 10, // foo(), + $dstat !~ /^(?:$Ident|-?$Constant);$/ && # foo(); + $dstat !~ /^[!~-]?(?:$Lval|$Constant)$/ && # 10 // foo() // !foo // ~foo // -foo // foo->bar // foo.bar->baz + $dstat !~ /^'X'$/ && $dstat !~ /^'XX'$/ && # character constants + $dstat !~ /$exceptions/ && + $dstat !~ /^\.$Ident\s*=/ && # .foo = + $dstat !~ /^(?:\#\s*$Ident|\#\s*$Constant)\s*$/ && # stringification #foo + $dstat !~ /^do\s*$Constant\s*while\s*$Constant;?$/ && # do {...} while (...); // do {...} while (...) + $dstat !~ /^for\s*$Constant$/ && # for (...) + $dstat !~ /^for\s*$Constant\s+(?:$Ident|-?$Constant)$/ && # for (...) bar() + $dstat !~ /^do\s*{/ && # do {... + $dstat !~ /^\(\{/ && # ({... + $ctx !~ /^.\s*#\s*define\s+TRACE_(?:SYSTEM|INCLUDE_FILE|INCLUDE_PATH)\b/) + { + $ctx =~ s/\n*$//; + my $herectx = $here . "\n"; + my $cnt = statement_rawlines($ctx); + + for (my $n = 0; $n < $cnt; $n++) { + $herectx .= raw_line($linenr, $n) . "\n"; + } + + if ($dstat =~ /;/) { + ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE", + "Macros with multiple statements should be enclosed in a do - while loop\n" . "$herectx"); + } else { + ERROR("COMPLEX_MACRO", + "Macros with complex values should be enclosed in parentheses\n" . "$herectx"); + } + } + +# check for macros with flow control, but without ## concatenation +# ## concatenation is commonly a macro that defines a function so ignore those + if ($has_flow_statement && !$has_arg_concat) { + my $herectx = $here . "\n"; + my $cnt = statement_rawlines($ctx); + + for (my $n = 0; $n < $cnt; $n++) { + $herectx .= raw_line($linenr, $n) . "\n"; + } + WARN("MACRO_WITH_FLOW_CONTROL", + "Macros with flow control statements should be avoided\n" . "$herectx"); + } + +# check for line continuations outside of #defines, preprocessor #, and asm + + } else { + if ($prevline !~ /^..*\\$/ && + $line !~ /^\+\s*\#.*\\$/ && # preprocessor + $line !~ /^\+.*\b(__asm__|asm)\b.*\\$/ && # asm + $line =~ /^\+.*\\$/) { + WARN("LINE_CONTINUATIONS", + "Avoid unnecessary line continuations\n" . $herecurr); + } + } + +# do {} while (0) macro tests: +# single-statement macros do not need to be enclosed in do while (0) loop, +# macro should not end with a semicolon + if ($^V && $^V ge 5.10.0 && + $realfile !~ m@/vmlinux.lds.h$@ && + $line =~ /^.\s*\#\s*define\s+$Ident(\()?/) { + my $ln = $linenr; + my $cnt = $realcnt; + my ($off, $dstat, $dcond, $rest); + my $ctx = ''; + ($dstat, $dcond, $ln, $cnt, $off) = + ctx_statement_block($linenr, $realcnt, 0); + $ctx = $dstat; + + $dstat =~ s/\\\n.//g; + $dstat =~ s/$;/ /g; + + if ($dstat =~ /^\+\s*#\s*define\s+$Ident\s*${balanced_parens}\s*do\s*{(.*)\s*}\s*while\s*\(\s*0\s*\)\s*([;\s]*)\s*$/) { + my $stmts = $2; + my $semis = $3; + + $ctx =~ s/\n*$//; + my $cnt = statement_rawlines($ctx); + my $herectx = $here . "\n"; + + for (my $n = 0; $n < $cnt; $n++) { + $herectx .= raw_line($linenr, $n) . "\n"; + } + + if (($stmts =~ tr/;/;/) == 1 && + $stmts !~ /^\s*(if|while|for|switch)\b/) { + WARN("SINGLE_STATEMENT_DO_WHILE_MACRO", + "Single statement macros should not use a do {} while (0) loop\n" . "$herectx"); + } + if (defined $semis && $semis ne "") { + WARN("DO_WHILE_MACRO_WITH_TRAILING_SEMICOLON", + "do {} while (0) macros should not be semicolon terminated\n" . "$herectx"); + } + } elsif ($dstat =~ /^\+\s*#\s*define\s+$Ident.*;\s*$/) { + $ctx =~ s/\n*$//; + my $cnt = statement_rawlines($ctx); + my $herectx = $here . "\n"; + + for (my $n = 0; $n < $cnt; $n++) { + $herectx .= raw_line($linenr, $n) . "\n"; + } + + WARN("TRAILING_SEMICOLON", + "macros should not use a trailing semicolon\n" . "$herectx"); + } + } + +# make sure symbols are always wrapped with VMLINUX_SYMBOL() ... +# all assignments may have only one of the following with an assignment: +# . +# ALIGN(...) +# VMLINUX_SYMBOL(...) + if ($realfile eq 'vmlinux.lds.h' && $line =~ /(?:(?:^|\s)$Ident\s*=|=\s*$Ident(?:\s|$))/) { + WARN("MISSING_VMLINUX_SYMBOL", + "vmlinux.lds.h needs VMLINUX_SYMBOL() around C-visible symbols\n" . $herecurr); + } + +# check for redundant bracing round if etc + if ($line =~ /(^.*)\bif\b/ && $1 !~ /else\s*$/) { + my ($level, $endln, @chunks) = + ctx_statement_full($linenr, $realcnt, 1); + #print "chunks<$#chunks> linenr<$linenr> endln<$endln> level<$level>\n"; + #print "APW: <<$chunks[1][0]>><<$chunks[1][1]>>\n"; + if ($#chunks > 0 && $level == 0) { + my @allowed = (); + my $allow = 0; + my $seen = 0; + my $herectx = $here . "\n"; + my $ln = $linenr - 1; + for my $chunk (@chunks) { + my ($cond, $block) = @{$chunk}; + + # If the condition carries leading newlines, then count those as offsets. + my ($whitespace) = ($cond =~ /^((?:\s*\n[+-])*\s*)/s); + my $offset = statement_rawlines($whitespace) - 1; + + $allowed[$allow] = 0; + #print "COND<$cond> whitespace<$whitespace> offset<$offset>\n"; + + # We have looked at and allowed this specific line. + $suppress_ifbraces{$ln + $offset} = 1; + + $herectx .= "$rawlines[$ln + $offset]\n[...]\n"; + $ln += statement_rawlines($block) - 1; + + substr($block, 0, length($cond), ''); + + $seen++ if ($block =~ /^\s*{/); + + #print "cond<$cond> block<$block> allowed<$allowed[$allow]>\n"; + if (statement_lines($cond) > 1) { + #print "APW: ALLOWED: cond<$cond>\n"; + $allowed[$allow] = 1; + } + if ($block =~/\b(?:if|for|while)\b/) { + #print "APW: ALLOWED: block<$block>\n"; + $allowed[$allow] = 1; + } + if (statement_block_size($block) > 1) { + #print "APW: ALLOWED: lines block<$block>\n"; + $allowed[$allow] = 1; + } + $allow++; + } + if ($seen) { + my $sum_allowed = 0; + foreach (@allowed) { + $sum_allowed += $_; + } + if ($sum_allowed == 0) { + WARN("BRACES", + "braces {} are not necessary for any arm of this statement\n" . $herectx); + } elsif ($sum_allowed != $allow && + $seen != $allow) { + CHK("BRACES", + "braces {} should be used on all arms of this statement\n" . $herectx); + } + } + } + } + if (!defined $suppress_ifbraces{$linenr - 1} && + $line =~ /\b(if|while|for|else)\b/) { + my $allowed = 0; + + # Check the pre-context. + if (substr($line, 0, $-[0]) =~ /(\}\s*)$/) { + #print "APW: ALLOWED: pre<$1>\n"; + $allowed = 1; + } + + my ($level, $endln, @chunks) = + ctx_statement_full($linenr, $realcnt, $-[0]); + + # Check the condition. + my ($cond, $block) = @{$chunks[0]}; + #print "CHECKING<$linenr> cond<$cond> block<$block>\n"; + if (defined $cond) { + substr($block, 0, length($cond), ''); + } + if (statement_lines($cond) > 1) { + #print "APW: ALLOWED: cond<$cond>\n"; + $allowed = 1; + } + if ($block =~/\b(?:if|for|while)\b/) { + #print "APW: ALLOWED: block<$block>\n"; + $allowed = 1; + } + if (statement_block_size($block) > 1) { + #print "APW: ALLOWED: lines block<$block>\n"; + $allowed = 1; + } + # Check the post-context. + if (defined $chunks[1]) { + my ($cond, $block) = @{$chunks[1]}; + if (defined $cond) { + substr($block, 0, length($cond), ''); + } + if ($block =~ /^\s*\{/) { + #print "APW: ALLOWED: chunk-1 block<$block>\n"; + $allowed = 1; + } + } + if ($level == 0 && $block =~ /^\s*\{/ && !$allowed) { + my $herectx = $here . "\n"; + my $cnt = statement_rawlines($block); + + for (my $n = 0; $n < $cnt; $n++) { + $herectx .= raw_line($linenr, $n) . "\n"; + } + + WARN("BRACES", + "braces {} are not necessary for single statement blocks\n" . $herectx); + } + } + +# check for unnecessary blank lines around braces + if (($line =~ /^.\s*}\s*$/ && $prevrawline =~ /^.\s*$/)) { + if (CHK("BRACES", + "Blank lines aren't necessary before a close brace '}'\n" . $hereprev) && + $fix && $prevrawline =~ /^\+/) { + fix_delete_line($fixlinenr - 1, $prevrawline); + } + } + if (($rawline =~ /^.\s*$/ && $prevline =~ /^..*{\s*$/)) { + if (CHK("BRACES", + "Blank lines aren't necessary after an open brace '{'\n" . $hereprev) && + $fix) { + fix_delete_line($fixlinenr, $rawline); + } + } + +# no volatiles please + my $asm_volatile = qr{\b(__asm__|asm)\s+(__volatile__|volatile)\b}; + if ($line =~ /\bvolatile\b/ && $line !~ /$asm_volatile/) { + WARN("VOLATILE", + "Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n" . $herecurr); + } + +# Check for user-visible strings broken across lines, which breaks the ability +# to grep for the string. Make exceptions when the previous string ends in a +# newline (multiple lines in one string constant) or '\t', '\r', ';', or '{' +# (common in inline assembly) or is a octal \123 or hexadecimal \xaf value + if ($line =~ /^\+\s*$String/ && + $prevline =~ /"\s*$/ && + $prevrawline !~ /(?:\\(?:[ntr]|[0-7]{1,3}|x[0-9a-fA-F]{1,2})|;\s*|\{\s*)"\s*$/) { + if (WARN("SPLIT_STRING", + "quoted string split across lines\n" . $hereprev) && + $fix && + $prevrawline =~ /^\+.*"\s*$/ && + $last_coalesced_string_linenr != $linenr - 1) { + my $extracted_string = get_quoted_string($line, $rawline); + my $comma_close = ""; + if ($rawline =~ /\Q$extracted_string\E(\s*\)\s*;\s*$|\s*,\s*)/) { + $comma_close = $1; + } + + fix_delete_line($fixlinenr - 1, $prevrawline); + fix_delete_line($fixlinenr, $rawline); + my $fixedline = $prevrawline; + $fixedline =~ s/"\s*$//; + $fixedline .= substr($extracted_string, 1) . trim($comma_close); + fix_insert_line($fixlinenr - 1, $fixedline); + $fixedline = $rawline; + $fixedline =~ s/\Q$extracted_string\E\Q$comma_close\E//; + if ($fixedline !~ /\+\s*$/) { + fix_insert_line($fixlinenr, $fixedline); + } + $last_coalesced_string_linenr = $linenr; + } + } + +# check for missing a space in a string concatenation + if ($prevrawline =~ /[^\\]\w"$/ && $rawline =~ /^\+[\t ]+"\w/) { + WARN('MISSING_SPACE', + "break quoted strings at a space character\n" . $hereprev); + } + +# check for spaces before a quoted newline + if ($rawline =~ /^.*\".*\s\\n/) { + if (WARN("QUOTED_WHITESPACE_BEFORE_NEWLINE", + "unnecessary whitespace before a quoted newline\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/^(\+.*\".*)\s+\\n/$1\\n/; + } + + } + +# concatenated string without spaces between elements + if ($line =~ /$String[A-Z_]/ || $line =~ /[A-Za-z0-9_]$String/) { + CHK("CONCATENATED_STRING", + "Concatenated strings should use spaces between elements\n" . $herecurr); + } + +# uncoalesced string fragments + if ($line =~ /$String\s*"/) { + WARN("STRING_FRAGMENTS", + "Consecutive strings are generally better as a single string\n" . $herecurr); + } + +# check for %L{u,d,i} and 0x%[udi] in strings + my $string; + while ($line =~ /(?:^|")([X\t]*)(?:"|$)/g) { + $string = substr($rawline, $-[1], $+[1] - $-[1]); + $string =~ s/%%/__/g; + if ($string =~ /(?<!%)%[\*\d\.\$]*L[udi]/) { + WARN("PRINTF_L", + "\%Ld/%Lu are not-standard C, use %lld/%llu\n" . $herecurr); + last; + } + if ($string =~ /0x%[\*\d\.\$\Llzth]*[udi]/) { + ERROR("PRINTF_0xDECIMAL", + "Prefixing 0x with decimal output is defective\n" . $herecurr); + } + } + +# check for line continuations in quoted strings with odd counts of " + if ($rawline =~ /\\$/ && $rawline =~ tr/"/"/ % 2) { + WARN("LINE_CONTINUATIONS", + "Avoid line continuations in quoted strings\n" . $herecurr); + } + +# warn about #if 0 + if ($line =~ /^.\s*\#\s*if\s+0\b/) { + CHK("REDUNDANT_CODE", + "if this code is redundant consider removing it\n" . + $herecurr); + } + +# check for needless "if (<foo>) fn(<foo>)" uses + if ($prevline =~ /\bif\s*\(\s*($Lval)\s*\)/) { + my $tested = quotemeta($1); + my $expr = '\s*\(\s*' . $tested . '\s*\)\s*;'; + if ($line =~ /\b(kfree|usb_free_urb|debugfs_remove(?:_recursive)?|(?:kmem_cache|mempool|dma_pool)_destroy)$expr/) { + my $func = $1; + if (WARN('NEEDLESS_IF', + "$func(NULL) is safe and this check is probably not required\n" . $hereprev) && + $fix) { + my $do_fix = 1; + my $leading_tabs = ""; + my $new_leading_tabs = ""; + if ($lines[$linenr - 2] =~ /^\+(\t*)if\s*\(\s*$tested\s*\)\s*$/) { + $leading_tabs = $1; + } else { + $do_fix = 0; + } + if ($lines[$linenr - 1] =~ /^\+(\t+)$func\s*\(\s*$tested\s*\)\s*;\s*$/) { + $new_leading_tabs = $1; + if (length($leading_tabs) + 1 ne length($new_leading_tabs)) { + $do_fix = 0; + } + } else { + $do_fix = 0; + } + if ($do_fix) { + fix_delete_line($fixlinenr - 1, $prevrawline); + $fixed[$fixlinenr] =~ s/^\+$new_leading_tabs/\+$leading_tabs/; + } + } + } + } + +# check for unnecessary "Out of Memory" messages + if ($line =~ /^\+.*\b$logFunctions\s*\(/ && + $prevline =~ /^[ \+]\s*if\s*\(\s*(\!\s*|NULL\s*==\s*)?($Lval)(\s*==\s*NULL\s*)?\s*\)/ && + (defined $1 || defined $3) && + $linenr > 3) { + my $testval = $2; + my $testline = $lines[$linenr - 3]; + + my ($s, $c) = ctx_statement_block($linenr - 3, $realcnt, 0); +# print("line: <$line>\nprevline: <$prevline>\ns: <$s>\nc: <$c>\n\n\n"); + + if ($c =~ /(?:^|\n)[ \+]\s*(?:$Type\s*)?\Q$testval\E\s*=\s*(?:\([^\)]*\)\s*)?\s*(?:devm_)?(?:[kv][czm]alloc(?:_node|_array)?\b|kstrdup|(?:dev_)?alloc_skb)/) { + WARN("OOM_MESSAGE", + "Possible unnecessary 'out of memory' message\n" . $hereprev); + } + } + +# check for logging functions with KERN_<LEVEL> + if ($line !~ /printk(?:_ratelimited|_once)?\s*\(/ && + $line =~ /\b$logFunctions\s*\(.*\b(KERN_[A-Z]+)\b/) { + my $level = $1; + if (WARN("UNNECESSARY_KERN_LEVEL", + "Possible unnecessary $level\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\s*$level\s*//; + } + } + +# check for mask then right shift without a parentheses + if ($^V && $^V ge 5.10.0 && + $line =~ /$LvalOrFunc\s*\&\s*($LvalOrFunc)\s*>>/ && + $4 !~ /^\&/) { # $LvalOrFunc may be &foo, ignore if so + WARN("MASK_THEN_SHIFT", + "Possible precedence defect with mask then right shift - may need parentheses\n" . $herecurr); + } + +# check for pointer comparisons to NULL + if ($^V && $^V ge 5.10.0) { + while ($line =~ /\b$LvalOrFunc\s*(==|\!=)\s*NULL\b/g) { + my $val = $1; + my $equal = "!"; + $equal = "" if ($4 eq "!="); + if (CHK("COMPARISON_TO_NULL", + "Comparison to NULL could be written \"${equal}${val}\"\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\b\Q$val\E\s*(?:==|\!=)\s*NULL\b/$equal$val/; + } + } + } + +# check for bad placement of section $InitAttribute (e.g.: __initdata) + if ($line =~ /(\b$InitAttribute\b)/) { + my $attr = $1; + if ($line =~ /^\+\s*static\s+(?:const\s+)?(?:$attr\s+)?($NonptrTypeWithAttr)\s+(?:$attr\s+)?($Ident(?:\[[^]]*\])?)\s*[=;]/) { + my $ptr = $1; + my $var = $2; + if ((($ptr =~ /\b(union|struct)\s+$attr\b/ && + ERROR("MISPLACED_INIT", + "$attr should be placed after $var\n" . $herecurr)) || + ($ptr !~ /\b(union|struct)\s+$attr\b/ && + WARN("MISPLACED_INIT", + "$attr should be placed after $var\n" . $herecurr))) && + $fix) { + $fixed[$fixlinenr] =~ s/(\bstatic\s+(?:const\s+)?)(?:$attr\s+)?($NonptrTypeWithAttr)\s+(?:$attr\s+)?($Ident(?:\[[^]]*\])?)\s*([=;])\s*/"$1" . trim(string_find_replace($2, "\\s*$attr\\s*", " ")) . " " . trim(string_find_replace($3, "\\s*$attr\\s*", "")) . " $attr" . ("$4" eq ";" ? ";" : " = ")/e; + } + } + } + +# check for $InitAttributeData (ie: __initdata) with const + if ($line =~ /\bconst\b/ && $line =~ /($InitAttributeData)/) { + my $attr = $1; + $attr =~ /($InitAttributePrefix)(.*)/; + my $attr_prefix = $1; + my $attr_type = $2; + if (ERROR("INIT_ATTRIBUTE", + "Use of const init definition must use ${attr_prefix}initconst\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ + s/$InitAttributeData/${attr_prefix}initconst/; + } + } + +# check for $InitAttributeConst (ie: __initconst) without const + if ($line !~ /\bconst\b/ && $line =~ /($InitAttributeConst)/) { + my $attr = $1; + if (ERROR("INIT_ATTRIBUTE", + "Use of $attr requires a separate use of const\n" . $herecurr) && + $fix) { + my $lead = $fixed[$fixlinenr] =~ + /(^\+\s*(?:static\s+))/; + $lead = rtrim($1); + $lead = "$lead " if ($lead !~ /^\+$/); + $lead = "${lead}const "; + $fixed[$fixlinenr] =~ s/(^\+\s*(?:static\s+))/$lead/; + } + } + +# check for __read_mostly with const non-pointer (should just be const) + if ($line =~ /\b__read_mostly\b/ && + $line =~ /($Type)\s*$Ident/ && $1 !~ /\*\s*$/ && $1 =~ /\bconst\b/) { + if (ERROR("CONST_READ_MOSTLY", + "Invalid use of __read_mostly with const type\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\s+__read_mostly\b//; + } + } + +# don't use __constant_<foo> functions outside of include/uapi/ + if ($realfile !~ m@^include/uapi/@ && + $line =~ /(__constant_(?:htons|ntohs|[bl]e(?:16|32|64)_to_cpu|cpu_to_[bl]e(?:16|32|64)))\s*\(/) { + my $constant_func = $1; + my $func = $constant_func; + $func =~ s/^__constant_//; + if (WARN("CONSTANT_CONVERSION", + "$constant_func should be $func\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\b$constant_func\b/$func/g; + } + } + +# prefer usleep_range over udelay + if ($line =~ /\budelay\s*\(\s*(\d+)\s*\)/) { + my $delay = $1; + # ignore udelay's < 10, however + if (! ($delay < 10) ) { + CHK("USLEEP_RANGE", + "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt\n" . $herecurr); + } + if ($delay > 2000) { + WARN("LONG_UDELAY", + "long udelay - prefer mdelay; see arch/arm/include/asm/delay.h\n" . $herecurr); + } + } + +# warn about unexpectedly long msleep's + if ($line =~ /\bmsleep\s*\((\d+)\);/) { + if ($1 < 20) { + WARN("MSLEEP", + "msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt\n" . $herecurr); + } + } + +# check for comparisons of jiffies + if ($line =~ /\bjiffies\s*$Compare|$Compare\s*jiffies\b/) { + WARN("JIFFIES_COMPARISON", + "Comparing jiffies is almost always wrong; prefer time_after, time_before and friends\n" . $herecurr); + } + +# check for comparisons of get_jiffies_64() + if ($line =~ /\bget_jiffies_64\s*\(\s*\)\s*$Compare|$Compare\s*get_jiffies_64\s*\(\s*\)/) { + WARN("JIFFIES_COMPARISON", + "Comparing get_jiffies_64() is almost always wrong; prefer time_after64, time_before64 and friends\n" . $herecurr); + } + +# warn about #ifdefs in C files +# if ($line =~ /^.\s*\#\s*if(|n)def/ && ($realfile =~ /\.c$/)) { +# print "#ifdef in C files should be avoided\n"; +# print "$herecurr"; +# $clean = 0; +# } + +# warn about spacing in #ifdefs + if ($line =~ /^.\s*\#\s*(ifdef|ifndef|elif)\s\s+/) { + if (ERROR("SPACING", + "exactly one space required after that #$1\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ + s/^(.\s*\#\s*(ifdef|ifndef|elif))\s{2,}/$1 /; + } + + } + +# check for spinlock_t definitions without a comment. + if ($line =~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/ || + $line =~ /^.\s*(DEFINE_MUTEX)\s*\(/) { + my $which = $1; + if (!ctx_has_comment($first_line, $linenr)) { + CHK("UNCOMMENTED_DEFINITION", + "$1 definition without comment\n" . $herecurr); + } + } +# check for memory barriers without a comment. + + my $barriers = qr{ + mb| + rmb| + wmb| + read_barrier_depends + }x; + my $barrier_stems = qr{ + mb__before_atomic| + mb__after_atomic| + store_release| + load_acquire| + store_mb| + (?:$barriers) + }x; + my $all_barriers = qr{ + (?:$barriers)| + smp_(?:$barrier_stems)| + virt_(?:$barrier_stems) + }x; + + if ($line =~ /\b(?:$all_barriers)\s*\(/) { + if (!ctx_has_comment($first_line, $linenr)) { + WARN("MEMORY_BARRIER", + "memory barrier without comment\n" . $herecurr); + } + } + + my $underscore_smp_barriers = qr{__smp_(?:$barrier_stems)}x; + + if ($realfile !~ m@^include/asm-generic/@ && + $realfile !~ m@/barrier\.h$@ && + $line =~ m/\b(?:$underscore_smp_barriers)\s*\(/ && + $line !~ m/^.\s*\#\s*define\s+(?:$underscore_smp_barriers)\s*\(/) { + WARN("MEMORY_BARRIER", + "__smp memory barriers shouldn't be used outside barrier.h and asm-generic\n" . $herecurr); + } + +# check for waitqueue_active without a comment. + if ($line =~ /\bwaitqueue_active\s*\(/) { + if (!ctx_has_comment($first_line, $linenr)) { + WARN("WAITQUEUE_ACTIVE", + "waitqueue_active without comment\n" . $herecurr); + } + } + +# Check for expedited grace periods that interrupt non-idle non-nohz +# online CPUs. These expedited can therefore degrade real-time response +# if used carelessly, and should be avoided where not absolutely +# needed. It is always OK to use synchronize_rcu_expedited() and +# synchronize_sched_expedited() at boot time (before real-time applications +# start) and in error situations where real-time response is compromised in +# any case. Note that synchronize_srcu_expedited() does -not- interrupt +# other CPUs, so don't warn on uses of synchronize_srcu_expedited(). +# Of course, nothing comes for free, and srcu_read_lock() and +# srcu_read_unlock() do contain full memory barriers in payment for +# synchronize_srcu_expedited() non-interruption properties. + if ($line =~ /\b(synchronize_rcu_expedited|synchronize_sched_expedited)\(/) { + WARN("EXPEDITED_RCU_GRACE_PERIOD", + "expedited RCU grace periods should be avoided where they can degrade real-time response\n" . $herecurr); + + } + +# check of hardware specific defines + if ($line =~ m@^.\s*\#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@ && $realfile !~ m@include/asm-@) { + CHK("ARCH_DEFINES", + "architecture specific defines should be avoided\n" . $herecurr); + } + +# Check that the storage class is at the beginning of a declaration + if ($line =~ /\b$Storage\b/ && $line !~ /^.\s*$Storage\b/) { + WARN("STORAGE_CLASS", + "storage class should be at the beginning of the declaration\n" . $herecurr) + } + +# check the location of the inline attribute, that it is between +# storage class and type. + if ($line =~ /\b$Type\s+$Inline\b/ || + $line =~ /\b$Inline\s+$Storage\b/) { + ERROR("INLINE_LOCATION", + "inline keyword should sit between storage class and type\n" . $herecurr); + } + +# Check for __inline__ and __inline, prefer inline + if ($realfile !~ m@\binclude/uapi/@ && + $line =~ /\b(__inline__|__inline)\b/) { + if (WARN("INLINE", + "plain inline is preferred over $1\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\b(__inline__|__inline)\b/inline/; + + } + } + +# Check for __attribute__ packed, prefer __packed + if ($realfile !~ m@\binclude/uapi/@ && + $line =~ /\b__attribute__\s*\(\s*\(.*\bpacked\b/) { + WARN("PREFER_PACKED", + "__packed is preferred over __attribute__((packed))\n" . $herecurr); + } + +# Check for __attribute__ aligned, prefer __aligned + if ($realfile !~ m@\binclude/uapi/@ && + $line =~ /\b__attribute__\s*\(\s*\(.*aligned/) { + WARN("PREFER_ALIGNED", + "__aligned(size) is preferred over __attribute__((aligned(size)))\n" . $herecurr); + } + +# Check for __attribute__ format(printf, prefer __printf + if ($realfile !~ m@\binclude/uapi/@ && + $line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf/) { + if (WARN("PREFER_PRINTF", + "__printf(string-index, first-to-check) is preferred over __attribute__((format(printf, string-index, first-to-check)))\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf\s*,\s*(.*)\)\s*\)\s*\)/"__printf(" . trim($1) . ")"/ex; + + } + } + +# Check for __attribute__ format(scanf, prefer __scanf + if ($realfile !~ m@\binclude/uapi/@ && + $line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\b/) { + if (WARN("PREFER_SCANF", + "__scanf(string-index, first-to-check) is preferred over __attribute__((format(scanf, string-index, first-to-check)))\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\s*,\s*(.*)\)\s*\)\s*\)/"__scanf(" . trim($1) . ")"/ex; + } + } + +# Check for __attribute__ weak, or __weak declarations (may have link issues) + if ($^V && $^V ge 5.10.0 && + $line =~ /(?:$Declare|$DeclareMisordered)\s*$Ident\s*$balanced_parens\s*(?:$Attribute)?\s*;/ && + ($line =~ /\b__attribute__\s*\(\s*\(.*\bweak\b/ || + $line =~ /\b__weak\b/)) { + ERROR("WEAK_DECLARATION", + "Using weak declarations can have unintended link defects\n" . $herecurr); + } + +# check for c99 types like uint8_t used outside of uapi/ + if ($realfile !~ m@\binclude/uapi/@ && + $line =~ /\b($Declare)\s*$Ident\s*[=;,\[]/) { + my $type = $1; + if ($type =~ /\b($typeC99Typedefs)\b/) { + $type = $1; + my $kernel_type = 'u'; + $kernel_type = 's' if ($type =~ /^_*[si]/); + $type =~ /(\d+)/; + $kernel_type .= $1; + if (CHK("PREFER_KERNEL_TYPES", + "Prefer kernel type '$kernel_type' over '$type'\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\b$type\b/$kernel_type/; + } + } + } + +# check for cast of C90 native int or longer types constants + if ($line =~ /(\(\s*$C90_int_types\s*\)\s*)($Constant)\b/) { + my $cast = $1; + my $const = $2; + if (WARN("TYPECAST_INT_CONSTANT", + "Unnecessary typecast of c90 int constant\n" . $herecurr) && + $fix) { + my $suffix = ""; + my $newconst = $const; + $newconst =~ s/${Int_type}$//; + $suffix .= 'U' if ($cast =~ /\bunsigned\b/); + if ($cast =~ /\blong\s+long\b/) { + $suffix .= 'LL'; + } elsif ($cast =~ /\blong\b/) { + $suffix .= 'L'; + } + $fixed[$fixlinenr] =~ s/\Q$cast\E$const\b/$newconst$suffix/; + } + } + +# check for sizeof(&) + if ($line =~ /\bsizeof\s*\(\s*\&/) { + WARN("SIZEOF_ADDRESS", + "sizeof(& should be avoided\n" . $herecurr); + } + +# check for sizeof without parenthesis + if ($line =~ /\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/) { + if (WARN("SIZEOF_PARENTHESIS", + "sizeof $1 should be sizeof($1)\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/"sizeof(" . trim($1) . ")"/ex; + } + } + +# check for struct spinlock declarations + if ($line =~ /^.\s*\bstruct\s+spinlock\s+\w+\s*;/) { + WARN("USE_SPINLOCK_T", + "struct spinlock should be spinlock_t\n" . $herecurr); + } + +# check for seq_printf uses that could be seq_puts + if ($sline =~ /\bseq_printf\s*\(.*"\s*\)\s*;\s*$/) { + my $fmt = get_quoted_string($line, $rawline); + $fmt =~ s/%%//g; + if ($fmt !~ /%/) { + if (WARN("PREFER_SEQ_PUTS", + "Prefer seq_puts to seq_printf\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\bseq_printf\b/seq_puts/; + } + } + } + +# Check for misused memsets + if ($^V && $^V ge 5.10.0 && + defined $stat && + $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*$FuncArg\s*\)/) { + + my $ms_addr = $2; + my $ms_val = $7; + my $ms_size = $12; + + if ($ms_size =~ /^(0x|)0$/i) { + ERROR("MEMSET", + "memset to 0's uses 0 as the 2nd argument, not the 3rd\n" . "$here\n$stat\n"); + } elsif ($ms_size =~ /^(0x|)1$/i) { + WARN("MEMSET", + "single byte memset is suspicious. Swapped 2nd/3rd argument?\n" . "$here\n$stat\n"); + } + } + +# Check for memcpy(foo, bar, ETH_ALEN) that could be ether_addr_copy(foo, bar) + if ($^V && $^V ge 5.10.0 && + defined $stat && + $stat =~ /^\+(?:.*?)\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) { + if (WARN("PREFER_ETHER_ADDR_COPY", + "Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2)\n" . "$here\n$stat\n") && + $fix) { + $fixed[$fixlinenr] =~ s/\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/ether_addr_copy($2, $7)/; + } + } + +# Check for memcmp(foo, bar, ETH_ALEN) that could be ether_addr_equal*(foo, bar) + if ($^V && $^V ge 5.10.0 && + defined $stat && + $stat =~ /^\+(?:.*?)\bmemcmp\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) { + WARN("PREFER_ETHER_ADDR_EQUAL", + "Prefer ether_addr_equal() or ether_addr_equal_unaligned() over memcmp()\n" . "$here\n$stat\n") + } + +# check for memset(foo, 0x0, ETH_ALEN) that could be eth_zero_addr +# check for memset(foo, 0xFF, ETH_ALEN) that could be eth_broadcast_addr + if ($^V && $^V ge 5.10.0 && + defined $stat && + $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) { + + my $ms_val = $7; + + if ($ms_val =~ /^(?:0x|)0+$/i) { + if (WARN("PREFER_ETH_ZERO_ADDR", + "Prefer eth_zero_addr over memset()\n" . "$here\n$stat\n") && + $fix) { + $fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_zero_addr($2)/; + } + } elsif ($ms_val =~ /^(?:0xff|255)$/i) { + if (WARN("PREFER_ETH_BROADCAST_ADDR", + "Prefer eth_broadcast_addr() over memset()\n" . "$here\n$stat\n") && + $fix) { + $fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_broadcast_addr($2)/; + } + } + } + +# typecasts on min/max could be min_t/max_t + if ($^V && $^V ge 5.10.0 && + defined $stat && + $stat =~ /^\+(?:.*?)\b(min|max)\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\)/) { + if (defined $2 || defined $7) { + my $call = $1; + my $cast1 = deparenthesize($2); + my $arg1 = $3; + my $cast2 = deparenthesize($7); + my $arg2 = $8; + my $cast; + + if ($cast1 ne "" && $cast2 ne "" && $cast1 ne $cast2) { + $cast = "$cast1 or $cast2"; + } elsif ($cast1 ne "") { + $cast = $cast1; + } else { + $cast = $cast2; + } + WARN("MINMAX", + "$call() should probably be ${call}_t($cast, $arg1, $arg2)\n" . "$here\n$stat\n"); + } + } + +# check usleep_range arguments + if ($^V && $^V ge 5.10.0 && + defined $stat && + $stat =~ /^\+(?:.*?)\busleep_range\s*\(\s*($FuncArg)\s*,\s*($FuncArg)\s*\)/) { + my $min = $1; + my $max = $7; + if ($min eq $max) { + WARN("USLEEP_RANGE", + "usleep_range should not use min == max args; see Documentation/timers/timers-howto.txt\n" . "$here\n$stat\n"); + } elsif ($min =~ /^\d+$/ && $max =~ /^\d+$/ && + $min > $max) { + WARN("USLEEP_RANGE", + "usleep_range args reversed, use min then max; see Documentation/timers/timers-howto.txt\n" . "$here\n$stat\n"); + } + } + +# check for naked sscanf + if ($^V && $^V ge 5.10.0 && + defined $stat && + $line =~ /\bsscanf\b/ && + ($stat !~ /$Ident\s*=\s*sscanf\s*$balanced_parens/ && + $stat !~ /\bsscanf\s*$balanced_parens\s*(?:$Compare)/ && + $stat !~ /(?:$Compare)\s*\bsscanf\s*$balanced_parens/)) { + my $lc = $stat =~ tr@\n@@; + $lc = $lc + $linenr; + my $stat_real = raw_line($linenr, 0); + for (my $count = $linenr + 1; $count <= $lc; $count++) { + $stat_real = $stat_real . "\n" . raw_line($count, 0); + } + WARN("NAKED_SSCANF", + "unchecked sscanf return value\n" . "$here\n$stat_real\n"); + } + +# check for simple sscanf that should be kstrto<foo> + if ($^V && $^V ge 5.10.0 && + defined $stat && + $line =~ /\bsscanf\b/) { + my $lc = $stat =~ tr@\n@@; + $lc = $lc + $linenr; + my $stat_real = raw_line($linenr, 0); + for (my $count = $linenr + 1; $count <= $lc; $count++) { + $stat_real = $stat_real . "\n" . raw_line($count, 0); + } + if ($stat_real =~ /\bsscanf\b\s*\(\s*$FuncArg\s*,\s*("[^"]+")/) { + my $format = $6; + my $count = $format =~ tr@%@%@; + if ($count == 1 && + $format =~ /^"\%(?i:ll[udxi]|[udxi]ll|ll|[hl]h?[udxi]|[udxi][hl]h?|[hl]h?|[udxi])"$/) { + WARN("SSCANF_TO_KSTRTO", + "Prefer kstrto<type> to single variable sscanf\n" . "$here\n$stat_real\n"); + } + } + } + +# check for new externs in .h files. + if ($realfile =~ /\.h$/ && + $line =~ /^\+\s*(extern\s+)$Type\s*$Ident\s*\(/s) { + if (CHK("AVOID_EXTERNS", + "extern prototypes should be avoided in .h files\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/(.*)\bextern\b\s*(.*)/$1$2/; + } + } + +# check for new externs in .c files. + if ($realfile =~ /\.c$/ && defined $stat && + $stat =~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s) + { + my $function_name = $1; + my $paren_space = $2; + + my $s = $stat; + if (defined $cond) { + substr($s, 0, length($cond), ''); + } + if ($s =~ /^\s*;/ && + $function_name ne 'uninitialized_var') + { + WARN("AVOID_EXTERNS", + "externs should be avoided in .c files\n" . $herecurr); + } + + if ($paren_space =~ /\n/) { + WARN("FUNCTION_ARGUMENTS", + "arguments for function declarations should follow identifier\n" . $herecurr); + } + + } elsif ($realfile =~ /\.c$/ && defined $stat && + $stat =~ /^.\s*extern\s+/) + { + WARN("AVOID_EXTERNS", + "externs should be avoided in .c files\n" . $herecurr); + } + +# checks for new __setup's + if ($rawline =~ /\b__setup\("([^"]*)"/) { + my $name = $1; + + if (!grep(/$name/, @setup_docs)) { + CHK("UNDOCUMENTED_SETUP", + "__setup appears un-documented -- check Documentation/kernel-parameters.txt\n" . $herecurr); + } + } + +# check for pointless casting of kmalloc return + if ($line =~ /\*\s*\)\s*[kv][czm]alloc(_node){0,1}\b/) { + WARN("UNNECESSARY_CASTS", + "unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $herecurr); + } + +# alloc style +# p = alloc(sizeof(struct foo), ...) should be p = alloc(sizeof(*p), ...) + if ($^V && $^V ge 5.10.0 && + $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*([kv][mz]alloc(?:_node)?)\s*\(\s*(sizeof\s*\(\s*struct\s+$Lval\s*\))/) { + CHK("ALLOC_SIZEOF_STRUCT", + "Prefer $3(sizeof(*$1)...) over $3($4...)\n" . $herecurr); + } + +# check for k[mz]alloc with multiplies that could be kmalloc_array/kcalloc + if ($^V && $^V ge 5.10.0 && + $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) { + my $oldfunc = $3; + my $a1 = $4; + my $a2 = $10; + my $newfunc = "kmalloc_array"; + $newfunc = "kcalloc" if ($oldfunc eq "kzalloc"); + my $r1 = $a1; + my $r2 = $a2; + if ($a1 =~ /^sizeof\s*\S/) { + $r1 = $a2; + $r2 = $a1; + } + if ($r1 !~ /^sizeof\b/ && $r2 =~ /^sizeof\s*\S/ && + !($r1 =~ /^$Constant$/ || $r1 =~ /^[A-Z_][A-Z0-9_]*$/)) { + if (WARN("ALLOC_WITH_MULTIPLY", + "Prefer $newfunc over $oldfunc with multiply\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . trim($r1) . ', ' . trim($r2)/e; + + } + } + } + +# check for krealloc arg reuse + if ($^V && $^V ge 5.10.0 && + $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*krealloc\s*\(\s*\1\s*,/) { + WARN("KREALLOC_ARG_REUSE", + "Reusing the krealloc arg is almost always a bug\n" . $herecurr); + } + +# check for alloc argument mismatch + if ($line =~ /\b(kcalloc|kmalloc_array)\s*\(\s*sizeof\b/) { + WARN("ALLOC_ARRAY_ARGS", + "$1 uses number as first arg, sizeof is generally wrong\n" . $herecurr); + } + +# check for multiple semicolons + if ($line =~ /;\s*;\s*$/) { + if (WARN("ONE_SEMICOLON", + "Statements terminations use 1 semicolon\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/(\s*;\s*){2,}$/;/g; + } + } + +# check for #defines like: 1 << <digit> that could be BIT(digit) + if ($line =~ /#\s*define\s+\w+\s+\(?\s*1\s*([ulUL]*)\s*\<\<\s*(?:\d+|$Ident)\s*\)?/) { + my $ull = ""; + $ull = "_ULL" if (defined($1) && $1 =~ /ll/i); + if (CHK("BIT_MACRO", + "Prefer using the BIT$ull macro\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\(?\s*1\s*[ulUL]*\s*<<\s*(\d+|$Ident)\s*\)?/BIT${ull}($1)/; + } + } + +# check for case / default statements not preceded by break/fallthrough/switch + if ($line =~ /^.\s*(?:case\s+(?:$Ident|$Constant)\s*|default):/) { + my $has_break = 0; + my $has_statement = 0; + my $count = 0; + my $prevline = $linenr; + while ($prevline > 1 && ($file || $count < 3) && !$has_break) { + $prevline--; + my $rline = $rawlines[$prevline - 1]; + my $fline = $lines[$prevline - 1]; + last if ($fline =~ /^\@\@/); + next if ($fline =~ /^\-/); + next if ($fline =~ /^.(?:\s*(?:case\s+(?:$Ident|$Constant)[\s$;]*|default):[\s$;]*)*$/); + $has_break = 1 if ($rline =~ /fall[\s_-]*(through|thru)/i); + next if ($fline =~ /^.[\s$;]*$/); + $has_statement = 1; + $count++; + $has_break = 1 if ($fline =~ /\bswitch\b|\b(?:break\s*;[\s$;]*$|return\b|goto\b|continue\b)/); + } + if (!$has_break && $has_statement) { + WARN("MISSING_BREAK", + "Possible switch case/default not preceeded by break or fallthrough comment\n" . $herecurr); + } + } + +# check for switch/default statements without a break; + if ($^V && $^V ge 5.10.0 && + defined $stat && + $stat =~ /^\+[$;\s]*(?:case[$;\s]+\w+[$;\s]*:[$;\s]*|)*[$;\s]*\bdefault[$;\s]*:[$;\s]*;/g) { + my $ctx = ''; + my $herectx = $here . "\n"; + my $cnt = statement_rawlines($stat); + for (my $n = 0; $n < $cnt; $n++) { + $herectx .= raw_line($linenr, $n) . "\n"; + } + WARN("DEFAULT_NO_BREAK", + "switch default: should use break\n" . $herectx); + } + +# check for gcc specific __FUNCTION__ + if ($line =~ /\b__FUNCTION__\b/) { + if (WARN("USE_FUNC", + "__func__ should be used instead of gcc specific __FUNCTION__\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\b__FUNCTION__\b/__func__/g; + } + } + +# check for uses of __DATE__, __TIME__, __TIMESTAMP__ + while ($line =~ /\b(__(?:DATE|TIME|TIMESTAMP)__)\b/g) { + ERROR("DATE_TIME", + "Use of the '$1' macro makes the build non-deterministic\n" . $herecurr); + } + +# check for use of yield() + if ($line =~ /\byield\s*\(\s*\)/) { + WARN("YIELD", + "Using yield() is generally wrong. See yield() kernel-doc (sched/core.c)\n" . $herecurr); + } + +# check for comparisons against true and false + if ($line =~ /\+\s*(.*?)\b(true|false|$Lval)\s*(==|\!=)\s*(true|false|$Lval)\b(.*)$/i) { + my $lead = $1; + my $arg = $2; + my $test = $3; + my $otype = $4; + my $trail = $5; + my $op = "!"; + + ($arg, $otype) = ($otype, $arg) if ($arg =~ /^(?:true|false)$/i); + + my $type = lc($otype); + if ($type =~ /^(?:true|false)$/) { + if (("$test" eq "==" && "$type" eq "true") || + ("$test" eq "!=" && "$type" eq "false")) { + $op = ""; + } + + CHK("BOOL_COMPARISON", + "Using comparison to $otype is error prone\n" . $herecurr); + +## maybe suggesting a correct construct would better +## "Using comparison to $otype is error prone. Perhaps use '${lead}${op}${arg}${trail}'\n" . $herecurr); + + } + } + +# check for semaphores initialized locked + if ($line =~ /^.\s*sema_init.+,\W?0\W?\)/) { + WARN("CONSIDER_COMPLETION", + "consider using a completion\n" . $herecurr); + } + +# recommend kstrto* over simple_strto* and strict_strto* + if ($line =~ /\b((simple|strict)_(strto(l|ll|ul|ull)))\s*\(/) { + WARN("CONSIDER_KSTRTO", + "$1 is obsolete, use k$3 instead\n" . $herecurr); + } + +# check for __initcall(), use device_initcall() explicitly or more appropriate function please + if ($line =~ /^.\s*__initcall\s*\(/) { + WARN("USE_DEVICE_INITCALL", + "please use device_initcall() or more appropriate function instead of __initcall() (see include/linux/init.h)\n" . $herecurr); + } + +# check for various structs that are normally const (ops, kgdb, device_tree) + my $const_structs = qr{ + acpi_dock_ops| + address_space_operations| + backlight_ops| + block_device_operations| + dentry_operations| + dev_pm_ops| + dma_map_ops| + extent_io_ops| + file_lock_operations| + file_operations| + hv_ops| + ide_dma_ops| + intel_dvo_dev_ops| + item_operations| + iwl_ops| + kgdb_arch| + kgdb_io| + kset_uevent_ops| + lock_manager_operations| + microcode_ops| + mtrr_ops| + neigh_ops| + nlmsvc_binding| + of_device_id| + pci_raw_ops| + pipe_buf_operations| + platform_hibernation_ops| + platform_suspend_ops| + proto_ops| + rpc_pipe_ops| + seq_operations| + snd_ac97_build_ops| + soc_pcmcia_socket_ops| + stacktrace_ops| + sysfs_ops| + tty_operations| + uart_ops| + usb_mon_operations| + wd_ops}x; + if ($line !~ /\bconst\b/ && + $line =~ /\bstruct\s+($const_structs)\b/) { + WARN("CONST_STRUCT", + "struct $1 should normally be const\n" . + $herecurr); + } + +# use of NR_CPUS is usually wrong +# ignore definitions of NR_CPUS and usage to define arrays as likely right + if ($line =~ /\bNR_CPUS\b/ && + $line !~ /^.\s*\s*#\s*if\b.*\bNR_CPUS\b/ && + $line !~ /^.\s*\s*#\s*define\b.*\bNR_CPUS\b/ && + $line !~ /^.\s*$Declare\s.*\[[^\]]*NR_CPUS[^\]]*\]/ && + $line !~ /\[[^\]]*\.\.\.[^\]]*NR_CPUS[^\]]*\]/ && + $line !~ /\[[^\]]*NR_CPUS[^\]]*\.\.\.[^\]]*\]/) + { + WARN("NR_CPUS", + "usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc\n" . $herecurr); + } + +# Use of __ARCH_HAS_<FOO> or ARCH_HAVE_<BAR> is wrong. + if ($line =~ /\+\s*#\s*define\s+((?:__)?ARCH_(?:HAS|HAVE)\w*)\b/) { + ERROR("DEFINE_ARCH_HAS", + "#define of '$1' is wrong - use Kconfig variables or standard guards instead\n" . $herecurr); + } + +# likely/unlikely comparisons similar to "(likely(foo) > 0)" + if ($^V && $^V ge 5.10.0 && + $line =~ /\b((?:un)?likely)\s*\(\s*$FuncArg\s*\)\s*$Compare/) { + WARN("LIKELY_MISUSE", + "Using $1 should generally have parentheses around the comparison\n" . $herecurr); + } + +# whine mightly about in_atomic + if ($line =~ /\bin_atomic\s*\(/) { + if ($realfile =~ m@^drivers/@) { + ERROR("IN_ATOMIC", + "do not use in_atomic in drivers\n" . $herecurr); + } elsif ($realfile !~ m@^kernel/@) { + WARN("IN_ATOMIC", + "use of in_atomic() is incorrect outside core kernel code\n" . $herecurr); + } + } + +# check for lockdep_set_novalidate_class + if ($line =~ /^.\s*lockdep_set_novalidate_class\s*\(/ || + $line =~ /__lockdep_no_validate__\s*\)/ ) { + if ($realfile !~ m@^kernel/lockdep@ && + $realfile !~ m@^include/linux/lockdep@ && + $realfile !~ m@^drivers/base/core@) { + ERROR("LOCKDEP", + "lockdep_no_validate class is reserved for device->mutex.\n" . $herecurr); + } + } + + if ($line =~ /debugfs_create_\w+.*\b$mode_perms_world_writable\b/ || + $line =~ /DEVICE_ATTR.*\b$mode_perms_world_writable\b/) { + WARN("EXPORTED_WORLD_WRITABLE", + "Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr); + } + +# Mode permission misuses where it seems decimal should be octal +# This uses a shortcut match to avoid unnecessary uses of a slow foreach loop + if ($^V && $^V ge 5.10.0 && + $line =~ /$mode_perms_search/) { + foreach my $entry (@mode_permission_funcs) { + my $func = $entry->[0]; + my $arg_pos = $entry->[1]; + + my $skip_args = ""; + if ($arg_pos > 1) { + $arg_pos--; + $skip_args = "(?:\\s*$FuncArg\\s*,\\s*){$arg_pos,$arg_pos}"; + } + my $test = "\\b$func\\s*\\(${skip_args}([\\d]+)\\s*[,\\)]"; + if ($line =~ /$test/) { + my $val = $1; + $val = $6 if ($skip_args ne ""); + + if ($val !~ /^0$/ && + (($val =~ /^$Int$/ && $val !~ /^$Octal$/) || + length($val) ne 4)) { + ERROR("NON_OCTAL_PERMISSIONS", + "Use 4 digit octal (0777) not decimal permissions\n" . $herecurr); + } elsif ($val =~ /^$Octal$/ && (oct($val) & 02)) { + ERROR("EXPORTED_WORLD_WRITABLE", + "Exporting writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr); + } + } + } + } + +# validate content of MODULE_LICENSE against list from include/linux/module.h + if ($line =~ /\bMODULE_LICENSE\s*\(\s*($String)\s*\)/) { + my $extracted_string = get_quoted_string($line, $rawline); + my $valid_licenses = qr{ + GPL| + GPL\ v2| + GPL\ and\ additional\ rights| + Dual\ BSD/GPL| + Dual\ MIT/GPL| + Dual\ MPL/GPL| + Proprietary + }x; + if ($extracted_string !~ /^"(?:$valid_licenses)"$/x) { + WARN("MODULE_LICENSE", + "unknown module license " . $extracted_string . "\n" . $herecurr); + } + } + } + + # If we have no input at all, then there is nothing to report on + # so just keep quiet. + if ($#rawlines == -1) { + exit(0); + } + + # In mailback mode only produce a report in the negative, for + # things that appear to be patches. + if ($mailback && ($clean == 1 || !$is_patch)) { + exit(0); + } + + # This is not a patch, and we are are in 'no-patch' mode so + # just keep quiet. + if (!$chk_patch && !$is_patch) { + exit(0); + } + + if (!$is_patch && $file !~ /cover-letter\.patch$/) { + ERROR("NOT_UNIFIED_DIFF", + "Does not appear to be a unified-diff format patch\n"); + } + if ($is_patch && $filename ne '-' && $chk_signoff && $signoff == 0) { + ERROR("MISSING_SIGN_OFF", + "Missing Signed-off-by: line(s)\n"); + } + + print report_dump(); + if ($summary && !($clean == 1 && $quiet == 1)) { + print "$filename " if ($summary_file); + print "total: $cnt_error errors, $cnt_warn warnings, " . + (($check)? "$cnt_chk checks, " : "") . + "$cnt_lines lines checked\n"; + } + + if ($quiet == 0) { + # If there were whitespace errors which cleanpatch can fix + # then suggest that. + if ($rpt_cleaners) { + $rpt_cleaners = 0; + print << "EOM" + +NOTE: Whitespace errors detected. + You may wish to use scripts/cleanpatch or scripts/cleanfile +EOM + } + } + + if ($clean == 0 && $fix && + ("@rawlines" ne "@fixed" || + $#fixed_inserted >= 0 || $#fixed_deleted >= 0)) { + my $newfile = $filename; + $newfile .= ".EXPERIMENTAL-checkpatch-fixes" if (!$fix_inplace); + my $linecount = 0; + my $f; + + @fixed = fix_inserted_deleted_lines(\@fixed, \@fixed_inserted, \@fixed_deleted); + + open($f, '>', $newfile) + or die "$P: Can't open $newfile for write\n"; + foreach my $fixed_line (@fixed) { + $linecount++; + if ($file) { + if ($linecount > 3) { + $fixed_line =~ s/^\+//; + print $f $fixed_line . "\n"; + } + } else { + print $f $fixed_line . "\n"; + } + } + close($f); + + if (!$quiet) { + print << "EOM"; + +Wrote EXPERIMENTAL --fix correction(s) to '$newfile' + +Do _NOT_ trust the results written to this file. +Do _NOT_ submit these changes without inspecting them for correctness. + +This EXPERIMENTAL file is simply a convenience to help rewrite patches. +No warranties, expressed or implied... +EOM + } + } + + if ($quiet == 0) { + print "\n"; + if ($clean == 1) { + print "$vname has no obvious style problems and is ready for submission.\n"; + } else { + print "$vname has style problems, please review.\n"; + } + } + return $clean; +} diff --git a/drivers/staging/greybus/scripts/spelling.txt b/drivers/staging/greybus/scripts/spelling.txt new file mode 100644 index 0000000..946caf3 --- /dev/null +++ b/drivers/staging/greybus/scripts/spelling.txt @@ -0,0 +1,1072 @@ +# Originally from Debian's Lintian tool. Various false positives have been +# removed, and various additions have been made as they've been discovered +# in the kernel source. +# +# License: GPLv2 +# +# The format of each line is: +# mistake||correction +# +abandonning||abandoning +abigious||ambiguous +abitrate||arbitrate +abov||above +abreviated||abbreviated +absense||absence +absolut||absolute +absoulte||absolute +acccess||access +acceleratoin||acceleration +accelleration||acceleration +accesing||accessing +accesnt||accent +accessable||accessible +accesss||access +accidentaly||accidentally +accidentually||accidentally +accoding||according +accomodate||accommodate +accomodates||accommodates +accordign||according +accoring||according +accout||account +accquire||acquire +accquired||acquired +accross||across +acessable||accessible +acess||access +achitecture||architecture +acient||ancient +acitions||actions +acitve||active +acknowldegement||acknowldegement +acknowledgement||acknowledgment +ackowledge||acknowledge +ackowledged||acknowledged +acording||according +activete||activate +acumulating||accumulating +adapater||adapter +addional||additional +additionaly||additionally +addres||address +addreses||addresses +addresss||address +aditional||additional +aditionally||additionally +aditionaly||additionally +adminstrative||administrative +adress||address +adresses||addresses +adviced||advised +afecting||affecting +agaist||against +albumns||albums +alegorical||allegorical +algorith||algorithm +algorithmical||algorithmically +algoritm||algorithm +algoritms||algorithms +algorrithm||algorithm +algorritm||algorithm +allign||align +allocatrd||allocated +allocte||allocate +allpication||application +alocate||allocate +alogirhtms||algorithms +alogrithm||algorithm +alot||a lot +alow||allow +alows||allows +altough||although +alue||value +ambigious||ambiguous +amoung||among +amout||amount +analysator||analyzer +ang||and +anniversery||anniversary +annoucement||announcement +anomolies||anomalies +anomoly||anomaly +anway||anyway +aplication||application +appearence||appearance +applicaion||application +appliction||application +applictions||applications +appplications||applications +appropiate||appropriate +appropriatly||appropriately +approriate||appropriate +approriately||appropriately +apropriate||appropriate +aquainted||acquainted +aquired||acquired +aquisition||acquisition +arbitary||arbitrary +architechture||architecture +arguement||argument +arguements||arguments +aritmetic||arithmetic +arne't||aren't +arraival||arrival +artifical||artificial +artillary||artillery +asign||assign +assertation||assertion +assiged||assigned +assigment||assignment +assigments||assignments +assistent||assistant +assocation||association +associcated||associated +assotiated||associated +assum||assume +assumtpion||assumption +asuming||assuming +asycronous||asynchronous +asynchnous||asynchronous +atomatically||automatically +atomicly||atomically +attachement||attachment +attched||attached +attemps||attempts +attruibutes||attributes +authentification||authentication +automaticaly||automatically +automaticly||automatically +automatize||automate +automatized||automated +automatizes||automates +autonymous||autonomous +auxillary||auxiliary +auxilliary||auxiliary +avaiable||available +avaible||available +availabe||available +availabled||available +availablity||availability +availale||available +availavility||availability +availble||available +availiable||available +avalable||available +avaliable||available +aysnc||async +backgroud||background +backword||backward +backwords||backwards +bahavior||behavior +bakup||backup +baloon||balloon +baloons||balloons +bandwith||bandwidth +batery||battery +beacuse||because +becasue||because +becomming||becoming +becuase||because +beeing||being +befor||before +begining||beginning +beter||better +betweeen||between +bianries||binaries +bitmast||bitmask +boardcast||broadcast +borad||board +boundry||boundary +brievely||briefly +broadcat||broadcast +cacluated||calculated +caculation||calculation +calender||calendar +calle||called +calucate||calculate +calulate||calculate +cancelation||cancellation +capabilites||capabilities +capabitilies||capabilities +capatibilities||capabilities +carefuly||carefully +cariage||carriage +catagory||category +cehck||check +challange||challenge +challanges||challenges +chanell||channel +changable||changeable +channle||channel +channnel||channel +charachter||character +charachters||characters +charactor||character +charater||character +charaters||characters +charcter||character +chcek||check +chck||check +checksuming||checksumming +childern||children +childs||children +chiled||child +chked||checked +chnage||change +chnages||changes +chnnel||channel +choosen||chosen +chouse||chose +circumvernt||circumvent +claread||cleared +clared||cleared +closeing||closing +clustred||clustered +collapsable||collapsible +colorfull||colorful +comand||command +comit||commit +commerical||commercial +comming||coming +comminucation||communication +commited||committed +commiting||committing +committ||commit +commoditiy||commodity +compability||compatibility +compaibility||compatibility +compatability||compatibility +compatable||compatible +compatibiliy||compatibility +compatibilty||compatibility +compatiblity||compatibility +competion||completion +compilant||compliant +compleatly||completely +completly||completely +complient||compliant +componnents||components +compres||compress +compresion||compression +comression||compression +comunication||communication +conbination||combination +conditionaly||conditionally +conected||connected +configuratoin||configuration +configuraton||configuration +configuretion||configuration +conider||consider +conjuction||conjunction +connectinos||connections +connnection||connection +connnections||connections +consistancy||consistency +consistant||consistent +containes||contains +containts||contains +contaisn||contains +contant||contact +contence||contents +continous||continuous +continously||continuously +continueing||continuing +contraints||constraints +controled||controlled +controler||controller +controll||control +contruction||construction +contry||country +convertion||conversion +convertor||converter +convienient||convenient +convinient||convenient +corected||corrected +correponding||corresponding +correponds||corresponds +correspoding||corresponding +cotrol||control +couter||counter +coutner||counter +cryptocraphic||cryptographic +cunter||counter +curently||currently +dafault||default +deafult||default +deamon||daemon +decompres||decompress +decription||description +defailt||default +defferred||deferred +definate||definite +definately||definitely +defintion||definition +defintions||definitions +defualt||default +defult||default +deivce||device +delared||declared +delare||declare +delares||declares +delaring||declaring +delemiter||delimiter +dependancies||dependencies +dependancy||dependency +dependant||dependent +depreacted||deprecated +depreacte||deprecate +desactivate||deactivate +desciptors||descriptors +descripton||description +descrition||description +descritptor||descriptor +desctiptor||descriptor +desriptor||descriptor +desriptors||descriptors +destory||destroy +destoryed||destroyed +destorys||destroys +destroied||destroyed +detabase||database +develope||develop +developement||development +developped||developed +developpement||development +developper||developer +developpment||development +deveolpment||development +devided||divided +deviece||device +diable||disable +dictionnary||dictionary +didnt||didn't +diferent||different +differrence||difference +difinition||definition +diplay||display +direectly||directly +disapear||disappear +disapeared||disappeared +disappared||disappeared +disconnet||disconnect +discontinous||discontinuous +dispertion||dispersion +dissapears||disappears +distiction||distinction +docuentation||documentation +documantation||documentation +documentaion||documentation +documment||document +doesnt||doesn't +dorp||drop +dosen||doesn +downlad||download +downlads||downloads +druing||during +dynmaic||dynamic +easilly||easily +ecspecially||especially +edditable||editable +editting||editing +efficently||efficiently +ehther||ether +eigth||eight +eletronic||electronic +enabledi||enabled +enchanced||enhanced +encorporating||incorporating +encrupted||encrypted +encrypiton||encryption +endianess||endianness +enhaced||enhanced +enlightnment||enlightenment +enocded||encoded +enterily||entirely +enviroiment||environment +enviroment||environment +environement||environment +environent||environment +eqivalent||equivalent +equiped||equipped +equivelant||equivalent +equivilant||equivalent +eror||error +estbalishment||establishment +etsablishment||establishment +etsbalishment||establishment +excecutable||executable +exceded||exceeded +excellant||excellent +existance||existence +existant||existent +exixt||exist +exlcude||exclude +exlcusive||exclusive +exmaple||example +expecially||especially +explicite||explicit +explicitely||explicitly +explict||explicit +explictly||explicitly +expresion||expression +exprimental||experimental +extened||extended +extensability||extensibility +extention||extension +extracter||extractor +faild||failed +faill||fail +failue||failure +failuer||failure +faireness||fairness +faliure||failure +familar||familiar +fatser||faster +feauture||feature +feautures||features +fetaure||feature +fetaures||features +fileystem||filesystem +finanize||finalize +findn||find +finilizes||finalizes +finsih||finish +flusing||flushing +folloing||following +followign||following +follwing||following +forseeable||foreseeable +forse||force +fortan||fortran +forwardig||forwarding +framwork||framework +frequncy||frequency +frome||from +fucntion||function +fuction||function +fuctions||functions +funcion||function +functionallity||functionality +functionaly||functionally +functionnality||functionality +functonality||functionality +funtion||function +funtions||functions +furthur||further +futhermore||furthermore +futrue||future +gaurenteed||guaranteed +generiously||generously +genric||generic +globel||global +grabing||grabbing +grahical||graphical +grahpical||graphical +grapic||graphic +guage||gauge +guarenteed||guaranteed +guarentee||guarantee +halfs||halves +hander||handler +handfull||handful +hanled||handled +happend||happened +harware||hardware +heirarchically||hierarchically +helpfull||helpful +hierachy||hierarchy +hierarchie||hierarchy +howver||however +hsould||should +hypter||hyper +identidier||identifier +imblance||imbalance +immeadiately||immediately +immedaite||immediate +immediatelly||immediately +immediatly||immediately +immidiate||immediate +impelentation||implementation +impementated||implemented +implemantation||implementation +implemenation||implementation +implementaiton||implementation +implementated||implemented +implemention||implementation +implemetation||implementation +implemntation||implementation +implentation||implementation +implmentation||implementation +implmenting||implementing +incomming||incoming +incompatabilities||incompatibilities +incompatable||incompatible +inconsistant||inconsistent +increas||increase +incrment||increment +indendation||indentation +indended||intended +independant||independent +independantly||independently +independed||independent +indiate||indicate +inexpect||inexpected +infomation||information +informatiom||information +informations||information +informtion||information +infromation||information +ingore||ignore +inital||initial +initalised||initialized +initalise||initialize +initalize||initialize +initation||initiation +initators||initiators +initializiation||initialization +initialzed||initialized +initilization||initialization +initilize||initialize +inofficial||unofficial +insititute||institute +instal||install +inteface||interface +integreated||integrated +integrety||integrity +integrey||integrity +intendet||intended +intented||intended +interanl||internal +interchangable||interchangeable +interferring||interfering +interger||integer +intermittant||intermittent +internel||internal +interoprability||interoperability +interrface||interface +interrrupt||interrupt +interrup||interrupt +interrups||interrupts +interruptted||interrupted +interupted||interrupted +interupt||interrupt +intial||initial +intialized||initialized +intialize||initialize +intregral||integral +intrrupt||interrupt +intuative||intuitive +invaid||invalid +invalde||invald +invalide||invalid +invididual||individual +invokation||invocation +invokations||invocations +irrelevent||irrelevant +isnt||isn't +isssue||issue +itslef||itself +jave||java +jeffies||jiffies +juse||just +jus||just +kown||known +langage||language +langauage||language +langauge||language +langugage||language +lauch||launch +layed||laid +leightweight||lightweight +lengh||length +lenght||length +lenth||length +lesstiff||lesstif +libaries||libraries +libary||library +librairies||libraries +libraris||libraries +licenceing||licencing +loggging||logging +loggin||login +logile||logfile +loosing||losing +losted||lost +machinary||machinery +maintainance||maintenance +maintainence||maintenance +maintan||maintain +makeing||making +malplaced||misplaced +malplace||misplace +managable||manageable +managment||management +mangement||management +manoeuvering||maneuvering +mappping||mapping +mathimatical||mathematical +mathimatic||mathematic +mathimatics||mathematics +maxium||maximum +mechamism||mechanism +meetign||meeting +ment||meant +mergable||mergeable +mesage||message +messags||messages +messgaes||messages +messsage||message +messsages||messages +microprocesspr||microprocessor +milliseonds||milliseconds +minumum||minimum +miscelleneous||miscellaneous +misformed||malformed +mispelled||misspelled +mispelt||misspelt +miximum||maximum +mmnemonic||mnemonic +mnay||many +modeled||modelled +modulues||modules +monochorome||monochrome +monochromo||monochrome +monocrome||monochrome +mopdule||module +mroe||more +mulitplied||multiplied +multidimensionnal||multidimensional +multple||multiple +mumber||number +muticast||multicast +mutiple||multiple +mutli||multi +nams||names +navagating||navigating +nead||need +neccecary||necessary +neccesary||necessary +neccessary||necessary +necesary||necessary +negaive||negative +negoitation||negotiation +negotation||negotiation +nerver||never +nescessary||necessary +nessessary||necessary +noticable||noticeable +notications||notifications +notifed||notified +numebr||number +numner||number +obtaion||obtain +occassionally||occasionally +occationally||occasionally +occurance||occurrence +occurances||occurrences +occured||occurred +occurence||occurrence +occure||occurred +occuring||occurring +offet||offset +omitt||omit +ommiting||omitting +ommitted||omitted +onself||oneself +ony||only +operatione||operation +opertaions||operations +optionnal||optional +optmizations||optimizations +orientatied||orientated +orientied||oriented +otherise||otherwise +ouput||output +overaall||overall +overhread||overhead +overlaping||overlapping +overriden||overridden +overun||overrun +pacakge||package +pachage||package +packacge||package +packege||package +packge||package +packtes||packets +pakage||package +pallette||palette +paln||plan +paramameters||parameters +paramater||parameter +parametes||parameters +parametised||parametrised +paramter||parameter +paramters||parameters +particuarly||particularly +particularily||particularly +pased||passed +passin||passing +pathes||paths +pecularities||peculiarities +peformance||performance +peice||piece +pendantic||pedantic +peprocessor||preprocessor +perfoming||performing +permissons||permissions +peroid||period +persistance||persistence +persistant||persistent +platfrom||platform +plattform||platform +pleaes||please +ploting||plotting +plugable||pluggable +poinnter||pointer +poiter||pointer +posible||possible +positon||position +possibilites||possibilities +powerfull||powerful +preceeded||preceded +preceeding||preceding +preceed||precede +precendence||precedence +precission||precision +preemptable||preemptible +prefered||preferred +prefferably||preferably +premption||preemption +prepaired||prepared +pressre||pressure +primative||primitive +princliple||principle +priorty||priority +privilaged||privileged +privilage||privilege +priviledge||privilege +priviledges||privileges +probaly||probably +procceed||proceed +proccesors||processors +procesed||processed +proces||process +processessing||processing +processess||processes +processpr||processor +processsed||processed +processsing||processing +procteted||protected +prodecure||procedure +progams||programs +progess||progress +programers||programmers +programm||program +programms||programs +progresss||progress +promiscous||promiscuous +promps||prompts +pronnounced||pronounced +prononciation||pronunciation +pronouce||pronounce +pronunce||pronounce +propery||property +propigate||propagate +propigation||propagation +propogate||propagate +prosess||process +protable||portable +protcol||protocol +protecion||protection +protocoll||protocol +psudo||pseudo +psuedo||pseudo +psychadelic||psychedelic +pwoer||power +quering||querying +raoming||roaming +reasearcher||researcher +reasearchers||researchers +reasearch||research +recepient||recipient +receving||receiving +recieved||received +recieve||receive +reciever||receiver +recieves||receives +recogniced||recognised +recognizeable||recognizable +recommanded||recommended +recyle||recycle +redircet||redirect +redirectrion||redirection +refcounf||refcount +refence||reference +refered||referred +referenace||reference +refering||referring +refernces||references +refernnce||reference +refrence||reference +registerd||registered +registeresd||registered +registes||registers +registraration||registration +regster||register +regualar||regular +reguator||regulator +regulamentations||regulations +reigstration||registration +releated||related +relevent||relevant +remoote||remote +remore||remote +removeable||removable +repectively||respectively +replacable||replaceable +replacments||replacements +replys||replies +reponse||response +representaion||representation +reqeust||request +requiere||require +requirment||requirement +requred||required +requried||required +requst||request +reseting||resetting +resizeable||resizable +resouces||resources +resoures||resources +responce||response +ressizes||resizes +ressource||resource +ressources||resources +retransmited||retransmitted +retreived||retrieved +retreive||retrieve +retrive||retrieve +retuned||returned +reudce||reduce +reuest||request +reuqest||request +reutnred||returned +rmeoved||removed +rmeove||remove +rmeoves||removes +rountine||routine +routins||routines +rquest||request +runing||running +runned||ran +runnning||running +runtine||runtime +sacrifying||sacrificing +safly||safely +safty||safety +savable||saveable +scaned||scanned +scaning||scanning +scarch||search +seach||search +searchs||searches +secquence||sequence +secund||second +segement||segment +senarios||scenarios +sentivite||sensitive +separatly||separately +sepcify||specify +sepc||spec +seperated||separated +seperately||separately +seperate||separate +seperatly||separately +seperator||separator +sepperate||separate +sequece||sequence +sequencial||sequential +serveral||several +setts||sets +settting||setting +shotdown||shutdown +shoud||should +shouldnt||shouldn't +shoule||should +shrinked||shrunk +siginificantly||significantly +signabl||signal +similary||similarly +similiar||similar +simlar||similar +simliar||similar +simpified||simplified +singaled||signaled +singal||signal +singed||signed +sleeped||slept +softwares||software +speach||speech +specfic||specific +speciefied||specified +specifc||specific +specifed||specified +specificatin||specification +specificaton||specification +specifing||specifying +specifiying||specifying +speficied||specified +speicify||specify +speling||spelling +spinlcok||spinlock +spinock||spinlock +splitted||split +spreaded||spread +sructure||structure +stablilization||stabilization +staically||statically +staion||station +standardss||standards +standartization||standardization +standart||standard +staticly||statically +stoped||stopped +stoppped||stopped +straming||streaming +struc||struct +structres||structures +stuct||struct +stucture||structure +sturcture||structure +subdirectoires||subdirectories +suble||subtle +substract||subtract +succesfully||successfully +succesful||successful +successfull||successful +sucessfully||successfully +sucess||success +superflous||superfluous +superseeded||superseded +suplied||supplied +suported||supported +suport||support +suppored||supported +supportin||supporting +suppoted||supported +suppported||supported +suppport||support +supress||suppress +surpresses||suppresses +susbsystem||subsystem +suspicously||suspiciously +swaping||swapping +switchs||switches +symetric||symmetric +synax||syntax +synchonized||synchronized +syncronize||synchronize +syncronizing||synchronizing +syncronus||synchronous +syste||system +sytem||system +sythesis||synthesis +taht||that +targetted||targeted +targetting||targeting +teh||the +temorary||temporary +temproarily||temporarily +thier||their +threds||threads +threshhold||threshold +throught||through +thses||these +tiggered||triggered +tipically||typically +tmis||this +torerable||tolerable +tramsmitted||transmitted +tramsmit||transmit +tranfer||transfer +transciever||transceiver +transferd||transferrd +transfered||transferred +transfering||transferring +transision||transition +transmittd||transmitted +transormed||transformed +trasmission||transmission +treshold||threshold +trigerring||triggering +trun||turn +ture||true +tyep||type +udpate||update +uesd||used +unconditionaly||unconditionally +underun||underrun +unecessary||unnecessary +unexecpted||unexpected +unexpectd||unexpected +unexpeted||unexpected +unfortunatelly||unfortunately +unifiy||unify +unintialized||uninitialized +unknonw||unknown +unknow||unknown +unkown||unknown +unneedingly||unnecessarily +unresgister||unregister +unsinged||unsigned +unstabel||unstable +unsuccessfull||unsuccessful +unsuported||unsupported +untill||until +unuseful||useless +upate||update +usefule||useful +usefull||useful +usege||usage +usera||users +usualy||usually +utilites||utilities +utillities||utilities +utilties||utilities +utiltity||utility +utitity||utility +utitlty||utility +vaid||valid +vaild||valid +valide||valid +variantions||variations +varient||variant +vaule||value +verbse||verbose +verisons||versions +verison||version +verson||version +vicefersa||vice-versa +virtal||virtual +virtaul||virtual +virtiual||virtual +visiters||visitors +vitual||virtual +wating||waiting +wether||whether +whataver||whatever +whcih||which +whenver||whenever +wheter||whether +whe||when +wierd||weird +wiil||will +wirte||write +withing||within +wnat||want +workarould||workaround +writeing||writing +writting||writing +zombe||zombie +zomebie||zombie diff --git a/drivers/staging/greybus/spelling.txt b/drivers/staging/greybus/spelling.txt deleted file mode 100644 index 946caf3..0000000 --- a/drivers/staging/greybus/spelling.txt +++ /dev/null @@ -1,1072 +0,0 @@ -# Originally from Debian's Lintian tool. Various false positives have been -# removed, and various additions have been made as they've been discovered -# in the kernel source. -# -# License: GPLv2 -# -# The format of each line is: -# mistake||correction -# -abandonning||abandoning -abigious||ambiguous -abitrate||arbitrate -abov||above -abreviated||abbreviated -absense||absence -absolut||absolute -absoulte||absolute -acccess||access -acceleratoin||acceleration -accelleration||acceleration -accesing||accessing -accesnt||accent -accessable||accessible -accesss||access -accidentaly||accidentally -accidentually||accidentally -accoding||according -accomodate||accommodate -accomodates||accommodates -accordign||according -accoring||according -accout||account -accquire||acquire -accquired||acquired -accross||across -acessable||accessible -acess||access -achitecture||architecture -acient||ancient -acitions||actions -acitve||active -acknowldegement||acknowldegement -acknowledgement||acknowledgment -ackowledge||acknowledge -ackowledged||acknowledged -acording||according -activete||activate -acumulating||accumulating -adapater||adapter -addional||additional -additionaly||additionally -addres||address -addreses||addresses -addresss||address -aditional||additional -aditionally||additionally -aditionaly||additionally -adminstrative||administrative -adress||address -adresses||addresses -adviced||advised -afecting||affecting -agaist||against -albumns||albums -alegorical||allegorical -algorith||algorithm -algorithmical||algorithmically -algoritm||algorithm -algoritms||algorithms -algorrithm||algorithm -algorritm||algorithm -allign||align -allocatrd||allocated -allocte||allocate -allpication||application -alocate||allocate -alogirhtms||algorithms -alogrithm||algorithm -alot||a lot -alow||allow -alows||allows -altough||although -alue||value -ambigious||ambiguous -amoung||among -amout||amount -analysator||analyzer -ang||and -anniversery||anniversary -annoucement||announcement -anomolies||anomalies -anomoly||anomaly -anway||anyway -aplication||application -appearence||appearance -applicaion||application -appliction||application -applictions||applications -appplications||applications -appropiate||appropriate -appropriatly||appropriately -approriate||appropriate -approriately||appropriately -apropriate||appropriate -aquainted||acquainted -aquired||acquired -aquisition||acquisition -arbitary||arbitrary -architechture||architecture -arguement||argument -arguements||arguments -aritmetic||arithmetic -arne't||aren't -arraival||arrival -artifical||artificial -artillary||artillery -asign||assign -assertation||assertion -assiged||assigned -assigment||assignment -assigments||assignments -assistent||assistant -assocation||association -associcated||associated -assotiated||associated -assum||assume -assumtpion||assumption -asuming||assuming -asycronous||asynchronous -asynchnous||asynchronous -atomatically||automatically -atomicly||atomically -attachement||attachment -attched||attached -attemps||attempts -attruibutes||attributes -authentification||authentication -automaticaly||automatically -automaticly||automatically -automatize||automate -automatized||automated -automatizes||automates -autonymous||autonomous -auxillary||auxiliary -auxilliary||auxiliary -avaiable||available -avaible||available -availabe||available -availabled||available -availablity||availability -availale||available -availavility||availability -availble||available -availiable||available -avalable||available -avaliable||available -aysnc||async -backgroud||background -backword||backward -backwords||backwards -bahavior||behavior -bakup||backup -baloon||balloon -baloons||balloons -bandwith||bandwidth -batery||battery -beacuse||because -becasue||because -becomming||becoming -becuase||because -beeing||being -befor||before -begining||beginning -beter||better -betweeen||between -bianries||binaries -bitmast||bitmask -boardcast||broadcast -borad||board -boundry||boundary -brievely||briefly -broadcat||broadcast -cacluated||calculated -caculation||calculation -calender||calendar -calle||called -calucate||calculate -calulate||calculate -cancelation||cancellation -capabilites||capabilities -capabitilies||capabilities -capatibilities||capabilities -carefuly||carefully -cariage||carriage -catagory||category -cehck||check -challange||challenge -challanges||challenges -chanell||channel -changable||changeable -channle||channel -channnel||channel -charachter||character -charachters||characters -charactor||character -charater||character -charaters||characters -charcter||character -chcek||check -chck||check -checksuming||checksumming -childern||children -childs||children -chiled||child -chked||checked -chnage||change -chnages||changes -chnnel||channel -choosen||chosen -chouse||chose -circumvernt||circumvent -claread||cleared -clared||cleared -closeing||closing -clustred||clustered -collapsable||collapsible -colorfull||colorful -comand||command -comit||commit -commerical||commercial -comming||coming -comminucation||communication -commited||committed -commiting||committing -committ||commit -commoditiy||commodity -compability||compatibility -compaibility||compatibility -compatability||compatibility -compatable||compatible -compatibiliy||compatibility -compatibilty||compatibility -compatiblity||compatibility -competion||completion -compilant||compliant -compleatly||completely -completly||completely -complient||compliant -componnents||components -compres||compress -compresion||compression -comression||compression -comunication||communication -conbination||combination -conditionaly||conditionally -conected||connected -configuratoin||configuration -configuraton||configuration -configuretion||configuration -conider||consider -conjuction||conjunction -connectinos||connections -connnection||connection -connnections||connections -consistancy||consistency -consistant||consistent -containes||contains -containts||contains -contaisn||contains -contant||contact -contence||contents -continous||continuous -continously||continuously -continueing||continuing -contraints||constraints -controled||controlled -controler||controller -controll||control -contruction||construction -contry||country -convertion||conversion -convertor||converter -convienient||convenient -convinient||convenient -corected||corrected -correponding||corresponding -correponds||corresponds -correspoding||corresponding -cotrol||control -couter||counter -coutner||counter -cryptocraphic||cryptographic -cunter||counter -curently||currently -dafault||default -deafult||default -deamon||daemon -decompres||decompress -decription||description -defailt||default -defferred||deferred -definate||definite -definately||definitely -defintion||definition -defintions||definitions -defualt||default -defult||default -deivce||device -delared||declared -delare||declare -delares||declares -delaring||declaring -delemiter||delimiter -dependancies||dependencies -dependancy||dependency -dependant||dependent -depreacted||deprecated -depreacte||deprecate -desactivate||deactivate -desciptors||descriptors -descripton||description -descrition||description -descritptor||descriptor -desctiptor||descriptor -desriptor||descriptor -desriptors||descriptors -destory||destroy -destoryed||destroyed -destorys||destroys -destroied||destroyed -detabase||database -develope||develop -developement||development -developped||developed -developpement||development -developper||developer -developpment||development -deveolpment||development -devided||divided -deviece||device -diable||disable -dictionnary||dictionary -didnt||didn't -diferent||different -differrence||difference -difinition||definition -diplay||display -direectly||directly -disapear||disappear -disapeared||disappeared -disappared||disappeared -disconnet||disconnect -discontinous||discontinuous -dispertion||dispersion -dissapears||disappears -distiction||distinction -docuentation||documentation -documantation||documentation -documentaion||documentation -documment||document -doesnt||doesn't -dorp||drop -dosen||doesn -downlad||download -downlads||downloads -druing||during -dynmaic||dynamic -easilly||easily -ecspecially||especially -edditable||editable -editting||editing -efficently||efficiently -ehther||ether -eigth||eight -eletronic||electronic -enabledi||enabled -enchanced||enhanced -encorporating||incorporating -encrupted||encrypted -encrypiton||encryption -endianess||endianness -enhaced||enhanced -enlightnment||enlightenment -enocded||encoded -enterily||entirely -enviroiment||environment -enviroment||environment -environement||environment -environent||environment -eqivalent||equivalent -equiped||equipped -equivelant||equivalent -equivilant||equivalent -eror||error -estbalishment||establishment -etsablishment||establishment -etsbalishment||establishment -excecutable||executable -exceded||exceeded -excellant||excellent -existance||existence -existant||existent -exixt||exist -exlcude||exclude -exlcusive||exclusive -exmaple||example -expecially||especially -explicite||explicit -explicitely||explicitly -explict||explicit -explictly||explicitly -expresion||expression -exprimental||experimental -extened||extended -extensability||extensibility -extention||extension -extracter||extractor -faild||failed -faill||fail -failue||failure -failuer||failure -faireness||fairness -faliure||failure -familar||familiar -fatser||faster -feauture||feature -feautures||features -fetaure||feature -fetaures||features -fileystem||filesystem -finanize||finalize -findn||find -finilizes||finalizes -finsih||finish -flusing||flushing -folloing||following -followign||following -follwing||following -forseeable||foreseeable -forse||force -fortan||fortran -forwardig||forwarding -framwork||framework -frequncy||frequency -frome||from -fucntion||function -fuction||function -fuctions||functions -funcion||function -functionallity||functionality -functionaly||functionally -functionnality||functionality -functonality||functionality -funtion||function -funtions||functions -furthur||further -futhermore||furthermore -futrue||future -gaurenteed||guaranteed -generiously||generously -genric||generic -globel||global -grabing||grabbing -grahical||graphical -grahpical||graphical -grapic||graphic -guage||gauge -guarenteed||guaranteed -guarentee||guarantee -halfs||halves -hander||handler -handfull||handful -hanled||handled -happend||happened -harware||hardware -heirarchically||hierarchically -helpfull||helpful -hierachy||hierarchy -hierarchie||hierarchy -howver||however -hsould||should -hypter||hyper -identidier||identifier -imblance||imbalance -immeadiately||immediately -immedaite||immediate -immediatelly||immediately -immediatly||immediately -immidiate||immediate -impelentation||implementation -impementated||implemented -implemantation||implementation -implemenation||implementation -implementaiton||implementation -implementated||implemented -implemention||implementation -implemetation||implementation -implemntation||implementation -implentation||implementation -implmentation||implementation -implmenting||implementing -incomming||incoming -incompatabilities||incompatibilities -incompatable||incompatible -inconsistant||inconsistent -increas||increase -incrment||increment -indendation||indentation -indended||intended -independant||independent -independantly||independently -independed||independent -indiate||indicate -inexpect||inexpected -infomation||information -informatiom||information -informations||information -informtion||information -infromation||information -ingore||ignore -inital||initial -initalised||initialized -initalise||initialize -initalize||initialize -initation||initiation -initators||initiators -initializiation||initialization -initialzed||initialized -initilization||initialization -initilize||initialize -inofficial||unofficial -insititute||institute -instal||install -inteface||interface -integreated||integrated -integrety||integrity -integrey||integrity -intendet||intended -intented||intended -interanl||internal -interchangable||interchangeable -interferring||interfering -interger||integer -intermittant||intermittent -internel||internal -interoprability||interoperability -interrface||interface -interrrupt||interrupt -interrup||interrupt -interrups||interrupts -interruptted||interrupted -interupted||interrupted -interupt||interrupt -intial||initial -intialized||initialized -intialize||initialize -intregral||integral -intrrupt||interrupt -intuative||intuitive -invaid||invalid -invalde||invald -invalide||invalid -invididual||individual -invokation||invocation -invokations||invocations -irrelevent||irrelevant -isnt||isn't -isssue||issue -itslef||itself -jave||java -jeffies||jiffies -juse||just -jus||just -kown||known -langage||language -langauage||language -langauge||language -langugage||language -lauch||launch -layed||laid -leightweight||lightweight -lengh||length -lenght||length -lenth||length -lesstiff||lesstif -libaries||libraries -libary||library -librairies||libraries -libraris||libraries -licenceing||licencing -loggging||logging -loggin||login -logile||logfile -loosing||losing -losted||lost -machinary||machinery -maintainance||maintenance -maintainence||maintenance -maintan||maintain -makeing||making -malplaced||misplaced -malplace||misplace -managable||manageable -managment||management -mangement||management -manoeuvering||maneuvering -mappping||mapping -mathimatical||mathematical -mathimatic||mathematic -mathimatics||mathematics -maxium||maximum -mechamism||mechanism -meetign||meeting -ment||meant -mergable||mergeable -mesage||message -messags||messages -messgaes||messages -messsage||message -messsages||messages -microprocesspr||microprocessor -milliseonds||milliseconds -minumum||minimum -miscelleneous||miscellaneous -misformed||malformed -mispelled||misspelled -mispelt||misspelt -miximum||maximum -mmnemonic||mnemonic -mnay||many -modeled||modelled -modulues||modules -monochorome||monochrome -monochromo||monochrome -monocrome||monochrome -mopdule||module -mroe||more -mulitplied||multiplied -multidimensionnal||multidimensional -multple||multiple -mumber||number -muticast||multicast -mutiple||multiple -mutli||multi -nams||names -navagating||navigating -nead||need -neccecary||necessary -neccesary||necessary -neccessary||necessary -necesary||necessary -negaive||negative -negoitation||negotiation -negotation||negotiation -nerver||never -nescessary||necessary -nessessary||necessary -noticable||noticeable -notications||notifications -notifed||notified -numebr||number -numner||number -obtaion||obtain -occassionally||occasionally -occationally||occasionally -occurance||occurrence -occurances||occurrences -occured||occurred -occurence||occurrence -occure||occurred -occuring||occurring -offet||offset -omitt||omit -ommiting||omitting -ommitted||omitted -onself||oneself -ony||only -operatione||operation -opertaions||operations -optionnal||optional -optmizations||optimizations -orientatied||orientated -orientied||oriented -otherise||otherwise -ouput||output -overaall||overall -overhread||overhead -overlaping||overlapping -overriden||overridden -overun||overrun -pacakge||package -pachage||package -packacge||package -packege||package -packge||package -packtes||packets -pakage||package -pallette||palette -paln||plan -paramameters||parameters -paramater||parameter -parametes||parameters -parametised||parametrised -paramter||parameter -paramters||parameters -particuarly||particularly -particularily||particularly -pased||passed -passin||passing -pathes||paths -pecularities||peculiarities -peformance||performance -peice||piece -pendantic||pedantic -peprocessor||preprocessor -perfoming||performing -permissons||permissions -peroid||period -persistance||persistence -persistant||persistent -platfrom||platform -plattform||platform -pleaes||please -ploting||plotting -plugable||pluggable -poinnter||pointer -poiter||pointer -posible||possible -positon||position -possibilites||possibilities -powerfull||powerful -preceeded||preceded -preceeding||preceding -preceed||precede -precendence||precedence -precission||precision -preemptable||preemptible -prefered||preferred -prefferably||preferably -premption||preemption -prepaired||prepared -pressre||pressure -primative||primitive -princliple||principle -priorty||priority -privilaged||privileged -privilage||privilege -priviledge||privilege -priviledges||privileges -probaly||probably -procceed||proceed -proccesors||processors -procesed||processed -proces||process -processessing||processing -processess||processes -processpr||processor -processsed||processed -processsing||processing -procteted||protected -prodecure||procedure -progams||programs -progess||progress -programers||programmers -programm||program -programms||programs -progresss||progress -promiscous||promiscuous -promps||prompts -pronnounced||pronounced -prononciation||pronunciation -pronouce||pronounce -pronunce||pronounce -propery||property -propigate||propagate -propigation||propagation -propogate||propagate -prosess||process -protable||portable -protcol||protocol -protecion||protection -protocoll||protocol -psudo||pseudo -psuedo||pseudo -psychadelic||psychedelic -pwoer||power -quering||querying -raoming||roaming -reasearcher||researcher -reasearchers||researchers -reasearch||research -recepient||recipient -receving||receiving -recieved||received -recieve||receive -reciever||receiver -recieves||receives -recogniced||recognised -recognizeable||recognizable -recommanded||recommended -recyle||recycle -redircet||redirect -redirectrion||redirection -refcounf||refcount -refence||reference -refered||referred -referenace||reference -refering||referring -refernces||references -refernnce||reference -refrence||reference -registerd||registered -registeresd||registered -registes||registers -registraration||registration -regster||register -regualar||regular -reguator||regulator -regulamentations||regulations -reigstration||registration -releated||related -relevent||relevant -remoote||remote -remore||remote -removeable||removable -repectively||respectively -replacable||replaceable -replacments||replacements -replys||replies -reponse||response -representaion||representation -reqeust||request -requiere||require -requirment||requirement -requred||required -requried||required -requst||request -reseting||resetting -resizeable||resizable -resouces||resources -resoures||resources -responce||response -ressizes||resizes -ressource||resource -ressources||resources -retransmited||retransmitted -retreived||retrieved -retreive||retrieve -retrive||retrieve -retuned||returned -reudce||reduce -reuest||request -reuqest||request -reutnred||returned -rmeoved||removed -rmeove||remove -rmeoves||removes -rountine||routine -routins||routines -rquest||request -runing||running -runned||ran -runnning||running -runtine||runtime -sacrifying||sacrificing -safly||safely -safty||safety -savable||saveable -scaned||scanned -scaning||scanning -scarch||search -seach||search -searchs||searches -secquence||sequence -secund||second -segement||segment -senarios||scenarios -sentivite||sensitive -separatly||separately -sepcify||specify -sepc||spec -seperated||separated -seperately||separately -seperate||separate -seperatly||separately -seperator||separator -sepperate||separate -sequece||sequence -sequencial||sequential -serveral||several -setts||sets -settting||setting -shotdown||shutdown -shoud||should -shouldnt||shouldn't -shoule||should -shrinked||shrunk -siginificantly||significantly -signabl||signal -similary||similarly -similiar||similar -simlar||similar -simliar||similar -simpified||simplified -singaled||signaled -singal||signal -singed||signed -sleeped||slept -softwares||software -speach||speech -specfic||specific -speciefied||specified -specifc||specific -specifed||specified -specificatin||specification -specificaton||specification -specifing||specifying -specifiying||specifying -speficied||specified -speicify||specify -speling||spelling -spinlcok||spinlock -spinock||spinlock -splitted||split -spreaded||spread -sructure||structure -stablilization||stabilization -staically||statically -staion||station -standardss||standards -standartization||standardization -standart||standard -staticly||statically -stoped||stopped -stoppped||stopped -straming||streaming -struc||struct -structres||structures -stuct||struct -stucture||structure -sturcture||structure -subdirectoires||subdirectories -suble||subtle -substract||subtract -succesfully||successfully -succesful||successful -successfull||successful -sucessfully||successfully -sucess||success -superflous||superfluous -superseeded||superseded -suplied||supplied -suported||supported -suport||support -suppored||supported -supportin||supporting -suppoted||supported -suppported||supported -suppport||support -supress||suppress -surpresses||suppresses -susbsystem||subsystem -suspicously||suspiciously -swaping||swapping -switchs||switches -symetric||symmetric -synax||syntax -synchonized||synchronized -syncronize||synchronize -syncronizing||synchronizing -syncronus||synchronous -syste||system -sytem||system -sythesis||synthesis -taht||that -targetted||targeted -targetting||targeting -teh||the -temorary||temporary -temproarily||temporarily -thier||their -threds||threads -threshhold||threshold -throught||through -thses||these -tiggered||triggered -tipically||typically -tmis||this -torerable||tolerable -tramsmitted||transmitted -tramsmit||transmit -tranfer||transfer -transciever||transceiver -transferd||transferrd -transfered||transferred -transfering||transferring -transision||transition -transmittd||transmitted -transormed||transformed -trasmission||transmission -treshold||threshold -trigerring||triggering -trun||turn -ture||true -tyep||type -udpate||update -uesd||used -unconditionaly||unconditionally -underun||underrun -unecessary||unnecessary -unexecpted||unexpected -unexpectd||unexpected -unexpeted||unexpected -unfortunatelly||unfortunately -unifiy||unify -unintialized||uninitialized -unknonw||unknown -unknow||unknown -unkown||unknown -unneedingly||unnecessarily -unresgister||unregister -unsinged||unsigned -unstabel||unstable -unsuccessfull||unsuccessful -unsuported||unsupported -untill||until -unuseful||useless -upate||update -usefule||useful -usefull||useful -usege||usage -usera||users -usualy||usually -utilites||utilities -utillities||utilities -utilties||utilities -utiltity||utility -utitity||utility -utitlty||utility -vaid||valid -vaild||valid -valide||valid -variantions||variations -varient||variant -vaule||value -verbse||verbose -verisons||versions -verison||version -verson||version -vicefersa||vice-versa -virtal||virtual -virtaul||virtual -virtiual||virtual -visiters||visitors -vitual||virtual -wating||waiting -wether||whether -whataver||whatever -whcih||which -whenver||whenever -wheter||whether -whe||when -wierd||weird -wiil||will -wirte||write -withing||within -wnat||want -workarould||workaround -writeing||writing -writting||writing -zombe||zombie -zomebie||zombie -- cgit v0.10.2 From 88a3011e91f7c557798301d47f830320580795cf Mon Sep 17 00:00:00 2001 From: Georgi Dobrev <dobrev_georgi@projectara.com> Date: Thu, 24 Mar 2016 13:37:21 +0200 Subject: greybus: Added a sysfs entry to power down the SVC Added a sysfs entry called pwr_off. When a "1" is passed to it, it sends a GB_SVC_TYPE_PWR_DOWN command to the SVC, powering it down along with the switch and INA231 chips. Testing Done: Tested on EVT1_5, works. Signed-off-by: Georgi Dobrev <dobrev_georgi@projectara.com> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 06888e0..a160e73 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -798,6 +798,7 @@ struct gb_spi_transfer_response { #define GB_SVC_TYPE_INTF_EJECT 0x11 #define GB_SVC_TYPE_KEY_EVENT 0x12 #define GB_SVC_TYPE_PING 0x13 +#define GB_SVC_TYPE_PWR_DOWN 0x1d /* * SVC version request/response has the same payload as diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index a19e575..f96c645 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -99,11 +99,31 @@ static ssize_t watchdog_store(struct device *dev, } static DEVICE_ATTR_RW(watchdog); +static ssize_t pwr_off_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t len) +{ + struct gb_svc *svc = to_gb_svc(dev); + int retval; + bool user_request; + + retval = strtobool(buf, &user_request); + if (retval) { + return retval; + } + if (user_request) { + retval = gb_svc_pwr_off(svc); + } + return len; +} +static DEVICE_ATTR_WO(pwr_off); + static struct attribute *svc_attrs[] = { &dev_attr_endo_id.attr, &dev_attr_ap_intf_id.attr, &dev_attr_intf_eject.attr, &dev_attr_watchdog.attr, + &dev_attr_pwr_off.attr, NULL, }; ATTRIBUTE_GROUPS(svc); @@ -320,6 +340,14 @@ int gb_svc_ping(struct gb_svc *svc) } EXPORT_SYMBOL_GPL(gb_svc_ping); +int gb_svc_pwr_off(struct gb_svc *svc) +{ + return gb_operation_sync_timeout(svc->connection, GB_SVC_TYPE_PWR_DOWN, + NULL, 0, NULL, 0, + GB_OPERATION_TIMEOUT_DEFAULT * 2); +} +EXPORT_SYMBOL_GPL(gb_svc_pwr_off); + static int gb_svc_version_request(struct gb_operation *op) { struct gb_connection *connection = op->connection; diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index 8950baf..09d8688 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -71,6 +71,7 @@ void gb_svc_watchdog_destroy(struct gb_svc *svc); bool gb_svc_watchdog_enabled(struct gb_svc *svc); int gb_svc_watchdog_enable(struct gb_svc *svc); int gb_svc_watchdog_disable(struct gb_svc *svc); +int gb_svc_pwr_off(struct gb_svc *svc); int gb_svc_protocol_init(void); void gb_svc_protocol_exit(void); -- cgit v0.10.2 From f053f44c9f7f85dd2bab589930d5f3171bb1eaf7 Mon Sep 17 00:00:00 2001 From: Akash Choudhari <akashtc@google.com> Date: Fri, 1 Apr 2016 20:10:01 -0700 Subject: greybus: Revert "Added a sysfs entry to power down the SVC" This reverts commit a1d8f2c3856804ed26157104bb203edf4c882a6c. diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index a160e73..06888e0 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -798,7 +798,6 @@ struct gb_spi_transfer_response { #define GB_SVC_TYPE_INTF_EJECT 0x11 #define GB_SVC_TYPE_KEY_EVENT 0x12 #define GB_SVC_TYPE_PING 0x13 -#define GB_SVC_TYPE_PWR_DOWN 0x1d /* * SVC version request/response has the same payload as diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index f96c645..a19e575 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -99,31 +99,11 @@ static ssize_t watchdog_store(struct device *dev, } static DEVICE_ATTR_RW(watchdog); -static ssize_t pwr_off_store(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t len) -{ - struct gb_svc *svc = to_gb_svc(dev); - int retval; - bool user_request; - - retval = strtobool(buf, &user_request); - if (retval) { - return retval; - } - if (user_request) { - retval = gb_svc_pwr_off(svc); - } - return len; -} -static DEVICE_ATTR_WO(pwr_off); - static struct attribute *svc_attrs[] = { &dev_attr_endo_id.attr, &dev_attr_ap_intf_id.attr, &dev_attr_intf_eject.attr, &dev_attr_watchdog.attr, - &dev_attr_pwr_off.attr, NULL, }; ATTRIBUTE_GROUPS(svc); @@ -340,14 +320,6 @@ int gb_svc_ping(struct gb_svc *svc) } EXPORT_SYMBOL_GPL(gb_svc_ping); -int gb_svc_pwr_off(struct gb_svc *svc) -{ - return gb_operation_sync_timeout(svc->connection, GB_SVC_TYPE_PWR_DOWN, - NULL, 0, NULL, 0, - GB_OPERATION_TIMEOUT_DEFAULT * 2); -} -EXPORT_SYMBOL_GPL(gb_svc_pwr_off); - static int gb_svc_version_request(struct gb_operation *op) { struct gb_connection *connection = op->connection; diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index 09d8688..8950baf 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -71,7 +71,6 @@ void gb_svc_watchdog_destroy(struct gb_svc *svc); bool gb_svc_watchdog_enabled(struct gb_svc *svc); int gb_svc_watchdog_enable(struct gb_svc *svc); int gb_svc_watchdog_disable(struct gb_svc *svc); -int gb_svc_pwr_off(struct gb_svc *svc); int gb_svc_protocol_init(void); void gb_svc_protocol_exit(void); -- cgit v0.10.2 From 0c35631bce4d0bece5a8e823b7f9ef115c712c4f Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Fri, 1 Apr 2016 11:15:42 +0530 Subject: greybus: checkpatch.pl: Mark --no-tree as default option Don't know why, but checkpatch checks if we are running it from top of a kernel tree or not, but then it also provides an option to suppress the warning using --no-tree. Instead of forcing everyone to use this every time, lets make this behavior default. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/scripts/checkpatch.pl b/drivers/staging/greybus/scripts/checkpatch.pl index d574d13..9930b73 100755 --- a/drivers/staging/greybus/scripts/checkpatch.pl +++ b/drivers/staging/greybus/scripts/checkpatch.pl @@ -19,7 +19,7 @@ my $V = '0.32'; use Getopt::Long qw(:config no_auto_abbrev); my $quiet = 0; -my $tree = 1; +my $tree = 0; my $chk_signoff = 1; my $chk_patch = 1; my $tst_only; -- cgit v0.10.2 From 5a53e02eaf223c42c6ca8d9664c1191ea7c2b106 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Sun, 3 Apr 2016 12:18:35 +0530 Subject: greybus: firmware: Rename to bootrom protocol Align with Greybus specifications and rename Firmware Protocol driver as Bootrom Protocol driver. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index ec92891..65259ea 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -9,7 +9,7 @@ greybus-y := core.o \ control.o \ svc.o \ svc_watchdog.o \ - firmware.o \ + bootrom.o \ operation.o \ legacy.o diff --git a/drivers/staging/greybus/bootrom.c b/drivers/staging/greybus/bootrom.c new file mode 100644 index 0000000..3cbe9fe --- /dev/null +++ b/drivers/staging/greybus/bootrom.c @@ -0,0 +1,382 @@ +/* + * BOOTROM Greybus driver. + * + * Copyright 2016 Google Inc. + * Copyright 2016 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include <linux/firmware.h> + +#include "bootrom.h" +#include "greybus.h" + + +struct gb_bootrom { + struct gb_connection *connection; + const struct firmware *fw; + u8 protocol_major; + u8 protocol_minor; +}; + +static void free_firmware(struct gb_bootrom *bootrom) +{ + release_firmware(bootrom->fw); + bootrom->fw = NULL; +} + +/* + * The es2 chip doesn't have VID/PID programmed into the hardware and we need to + * hack that up to distinguish different modules and their firmware blobs. + * + * This fetches VID/PID (over bootrom protocol) for es2 chip only, when VID/PID + * already sent during hotplug are 0. + * + * Otherwise, we keep intf->vendor_id/product_id same as what's passed + * during hotplug. + */ +static void bootrom_es2_fixup_vid_pid(struct gb_bootrom *bootrom) +{ + struct gb_bootrom_get_vid_pid_response response; + struct gb_connection *connection = bootrom->connection; + struct gb_interface *intf = connection->bundle->intf; + int ret; + + if (!(intf->quirks & GB_INTERFACE_QUIRK_NO_ARA_IDS)) + return; + + ret = gb_operation_sync(connection, GB_BOOTROM_TYPE_GET_VID_PID, + NULL, 0, &response, sizeof(response)); + if (ret) { + dev_err(&connection->bundle->dev, + "Bootrom get vid/pid operation failed (%d)\n", ret); + return; + } + + /* + * NOTE: This is hacked, so that the same values of VID/PID can be used + * by next firmware level as well. The uevent for bootrom will still + * have VID/PID as 0, though after this point the sysfs files will start + * showing the updated values. But yeah, that's a bit racy as the same + * sysfs files would be showing 0 before this point. + */ + intf->vendor_id = le32_to_cpu(response.vendor_id); + intf->product_id = le32_to_cpu(response.product_id); + + dev_dbg(&connection->bundle->dev, "Bootrom got vid (0x%x)/pid (0x%x)\n", + intf->vendor_id, intf->product_id); +} + +/* This returns path of the firmware blob on the disk */ +static int download_firmware(struct gb_bootrom *bootrom, u8 stage) +{ + struct gb_connection *connection = bootrom->connection; + struct gb_interface *intf = connection->bundle->intf; + char firmware_name[48]; + int rc; + + /* Already have a firmware, free it */ + if (bootrom->fw) + free_firmware(bootrom); + + /* + * Create firmware name + * + * XXX Name it properly.. + */ + snprintf(firmware_name, sizeof(firmware_name), + "ara_%08x_%08x_%08x_%08x_%02x.tftf", + intf->ddbl1_manufacturer_id, intf->ddbl1_product_id, + intf->vendor_id, intf->product_id, stage); + + // FIXME: + // Turn to dev_dbg later after everyone has valid bootloaders with good + // ids, but leave this as dev_info for now to make it easier to track + // down "empty" vid/pid modules. + dev_info(&connection->bundle->dev, "Firmware file '%s' requested\n", + firmware_name); + + rc = request_firmware(&bootrom->fw, firmware_name, + &connection->bundle->dev); + if (rc) + dev_err(&connection->bundle->dev, + "Firware request for %s has failed : %d", + firmware_name, rc); + return rc; +} + +static int gb_bootrom_firmware_size_request(struct gb_operation *op) +{ + struct gb_bootrom *bootrom = gb_connection_get_data(op->connection); + struct gb_bootrom_firmware_size_request *size_request = op->request->payload; + struct gb_bootrom_firmware_size_response *size_response; + struct device *dev = &op->connection->bundle->dev; + int ret; + + if (op->request->payload_size != sizeof(*size_request)) { + dev_err(dev, "%s: illegal size of firmware size request (%zu != %zu)\n", + __func__, op->request->payload_size, + sizeof(*size_request)); + return -EINVAL; + } + + ret = download_firmware(bootrom, size_request->stage); + if (ret) { + dev_err(dev, "%s: failed to download firmware (%d)\n", __func__, + ret); + return ret; + } + + if (!gb_operation_response_alloc(op, sizeof(*size_response), + GFP_KERNEL)) { + dev_err(dev, "%s: error allocating response\n", __func__); + free_firmware(bootrom); + return -ENOMEM; + } + + size_response = op->response->payload; + size_response->size = cpu_to_le32(bootrom->fw->size); + + dev_dbg(dev, "%s: firmware size %d bytes\n", __func__, size_response->size); + + return 0; +} + +static int gb_bootrom_get_firmware(struct gb_operation *op) +{ + struct gb_bootrom *bootrom = gb_connection_get_data(op->connection); + const struct firmware *fw = bootrom->fw; + struct gb_bootrom_get_firmware_request *firmware_request; + struct gb_bootrom_get_firmware_response *firmware_response; + struct device *dev = &op->connection->bundle->dev; + unsigned int offset, size; + + if (op->request->payload_size != sizeof(*firmware_request)) { + dev_err(dev, "%s: Illegal size of get firmware request (%zu %zu)\n", + __func__, op->request->payload_size, + sizeof(*firmware_request)); + return -EINVAL; + } + + if (!fw) { + dev_err(dev, "%s: firmware not available\n", __func__); + return -EINVAL; + } + + firmware_request = op->request->payload; + offset = le32_to_cpu(firmware_request->offset); + size = le32_to_cpu(firmware_request->size); + + if (offset >= fw->size || size > fw->size - offset) { + dev_warn(dev, "bad firmware request (offs = %u, size = %u)\n", + offset, size); + return -EINVAL; + } + + if (!gb_operation_response_alloc(op, sizeof(*firmware_response) + size, + GFP_KERNEL)) { + dev_err(dev, "%s: error allocating response\n", __func__); + return -ENOMEM; + } + + firmware_response = op->response->payload; + memcpy(firmware_response->data, fw->data + offset, size); + + dev_dbg(dev, "responding with firmware (offs = %u, size = %u)\n", offset, + size); + + return 0; +} + +static int gb_bootrom_ready_to_boot(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_bootrom_ready_to_boot_request *rtb_request; + struct device *dev = &connection->bundle->dev; + u8 status; + + if (op->request->payload_size != sizeof(*rtb_request)) { + dev_err(dev, "%s: Illegal size of ready to boot request (%zu %zu)\n", + __func__, op->request->payload_size, + sizeof(*rtb_request)); + return -EINVAL; + } + + rtb_request = op->request->payload; + status = rtb_request->status; + + /* Return error if the blob was invalid */ + if (status == GB_BOOTROM_BOOT_STATUS_INVALID) + return -EINVAL; + + /* + * XXX Should we return error for insecure firmware? + */ + dev_dbg(dev, "ready to boot: 0x%x, 0\n", status); + + return 0; +} + +static int gb_bootrom_request_handler(struct gb_operation *op) +{ + u8 type = op->type; + + switch (type) { + case GB_BOOTROM_TYPE_FIRMWARE_SIZE: + return gb_bootrom_firmware_size_request(op); + case GB_BOOTROM_TYPE_GET_FIRMWARE: + return gb_bootrom_get_firmware(op); + case GB_BOOTROM_TYPE_READY_TO_BOOT: + return gb_bootrom_ready_to_boot(op); + default: + dev_err(&op->connection->bundle->dev, + "unsupported request: %u\n", type); + return -EINVAL; + } +} + +static int gb_bootrom_get_version(struct gb_bootrom *bootrom) +{ + struct gb_bundle *bundle = bootrom->connection->bundle; + struct gb_bootrom_version_request request; + struct gb_bootrom_version_response response; + int ret; + + request.major = GB_BOOTROM_VERSION_MAJOR; + request.minor = GB_BOOTROM_VERSION_MINOR; + + ret = gb_operation_sync(bootrom->connection, + GB_BOOTROM_TYPE_VERSION, + &request, sizeof(request), &response, + sizeof(response)); + if (ret) { + dev_err(&bundle->dev, + "failed to get protocol version: %d\n", + ret); + return ret; + } + + if (response.major > request.major) { + dev_err(&bundle->dev, + "unsupported major protocol version (%u > %u)\n", + response.major, request.major); + return -ENOTSUPP; + } + + bootrom->protocol_major = response.major; + bootrom->protocol_minor = response.minor; + + dev_dbg(&bundle->dev, "%s - %u.%u\n", __func__, response.major, + response.minor); + + return 0; +} + +static int gb_bootrom_probe(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) +{ + struct greybus_descriptor_cport *cport_desc; + struct gb_connection *connection; + struct gb_bootrom *bootrom; + int ret; + + if (bundle->num_cports != 1) + return -ENODEV; + + cport_desc = &bundle->cport_desc[0]; + if (cport_desc->protocol_id != GREYBUS_PROTOCOL_BOOTROM) + return -ENODEV; + + bootrom = kzalloc(sizeof(*bootrom), GFP_KERNEL); + if (!bootrom) + return -ENOMEM; + + connection = gb_connection_create(bundle, + le16_to_cpu(cport_desc->id), + gb_bootrom_request_handler); + if (IS_ERR(connection)) { + ret = PTR_ERR(connection); + goto err_free_bootrom; + } + + gb_connection_set_data(connection, bootrom); + + bootrom->connection = connection; + + greybus_set_drvdata(bundle, bootrom); + + ret = gb_connection_enable_tx(connection); + if (ret) + goto err_connection_destroy; + + ret = gb_bootrom_get_version(bootrom); + if (ret) + goto err_connection_disable; + + bootrom_es2_fixup_vid_pid(bootrom); + + ret = gb_connection_enable(connection); + if (ret) + goto err_connection_disable; + + /* Tell bootrom we're ready. */ + ret = gb_operation_sync(connection, GB_BOOTROM_TYPE_AP_READY, NULL, 0, + NULL, 0); + if (ret) { + dev_err(&connection->bundle->dev, + "failed to send AP READY: %d\n", ret); + goto err_connection_disable; + } + + dev_dbg(&bundle->dev, "AP_READY sent\n"); + + return 0; + +err_connection_disable: + gb_connection_disable(connection); +err_connection_destroy: + gb_connection_destroy(connection); +err_free_bootrom: + kfree(bootrom); + + return ret; +} + +static void gb_bootrom_disconnect(struct gb_bundle *bundle) +{ + struct gb_bootrom *bootrom = greybus_get_drvdata(bundle); + + dev_dbg(&bundle->dev, "%s\n", __func__); + + gb_connection_disable(bootrom->connection); + + /* Release firmware */ + if (bootrom->fw) + free_firmware(bootrom); + + gb_connection_destroy(bootrom->connection); + kfree(bootrom); +} + +static const struct greybus_bundle_id gb_bootrom_id_table[] = { + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_BOOTROM) }, + { } +}; + +static struct greybus_driver gb_bootrom_driver = { + .name = "bootrom", + .probe = gb_bootrom_probe, + .disconnect = gb_bootrom_disconnect, + .id_table = gb_bootrom_id_table, +}; + +int gb_bootrom_init(void) +{ + return greybus_register(&gb_bootrom_driver); +} + +void gb_bootrom_exit(void) +{ + greybus_deregister(&gb_bootrom_driver); +} diff --git a/drivers/staging/greybus/bootrom.h b/drivers/staging/greybus/bootrom.h new file mode 100644 index 0000000..fd2d193 --- /dev/null +++ b/drivers/staging/greybus/bootrom.h @@ -0,0 +1,16 @@ +/* + * Greybus bootrom code + * + * Copyright 2016 Google Inc. + * Copyright 2016 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#ifndef __BOOTROM_H +#define __BOOTROM_H + +int gb_bootrom_init(void); +void gb_bootrom_exit(void); + +#endif /* __BOOTROM_H */ diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index ca7469e..d868066 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -10,7 +10,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define CREATE_TRACE_POINTS -#include "firmware.h" +#include "bootrom.h" #include "greybus.h" #include "greybus_trace.h" #include "legacy.h" @@ -243,10 +243,10 @@ static int __init gb_init(void) goto error_operation; } - retval = gb_firmware_init(); + retval = gb_bootrom_init(); if (retval) { - pr_err("gb_firmware_init failed\n"); - goto error_firmware; + pr_err("gb_bootrom_init failed\n"); + goto error_bootrom; } retval = gb_legacy_init(); @@ -258,8 +258,8 @@ static int __init gb_init(void) return 0; /* Success */ error_legacy: - gb_firmware_exit(); -error_firmware: + gb_bootrom_exit(); +error_bootrom: gb_operation_exit(); error_operation: gb_hd_exit(); @@ -275,7 +275,7 @@ module_init(gb_init); static void __exit gb_exit(void) { gb_legacy_exit(); - gb_firmware_exit(); + gb_bootrom_exit(); gb_operation_exit(); gb_hd_exit(); bus_unregister(&greybus_bus_type); diff --git a/drivers/staging/greybus/firmware.c b/drivers/staging/greybus/firmware.c deleted file mode 100644 index b1e373c..0000000 --- a/drivers/staging/greybus/firmware.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * FIRMWARE Greybus driver. - * - * Copyright 2015 Google Inc. - * Copyright 2015 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#include <linux/firmware.h> - -#include "firmware.h" -#include "greybus.h" - - -struct gb_firmware { - struct gb_connection *connection; - const struct firmware *fw; - u8 protocol_major; - u8 protocol_minor; -}; - -static void free_firmware(struct gb_firmware *firmware) -{ - release_firmware(firmware->fw); - firmware->fw = NULL; -} - -/* - * The es2 chip doesn't have VID/PID programmed into the hardware and we need to - * hack that up to distinguish different modules and their firmware blobs. - * - * This fetches VID/PID (over firmware protocol) for es2 chip only, when VID/PID - * already sent during hotplug are 0. - * - * Otherwise, we keep intf->vendor_id/product_id same as what's passed - * during hotplug. - */ -static void firmware_es2_fixup_vid_pid(struct gb_firmware *firmware) -{ - struct gb_firmware_get_vid_pid_response response; - struct gb_connection *connection = firmware->connection; - struct gb_interface *intf = connection->bundle->intf; - int ret; - - if (!(intf->quirks & GB_INTERFACE_QUIRK_NO_ARA_IDS)) - return; - - ret = gb_operation_sync(connection, GB_FIRMWARE_TYPE_GET_VID_PID, - NULL, 0, &response, sizeof(response)); - if (ret) { - dev_err(&connection->bundle->dev, - "Firmware get vid/pid operation failed (%d)\n", ret); - return; - } - - /* - * NOTE: This is hacked, so that the same values of VID/PID can be used - * by next firmware level as well. The uevent for bootrom will still - * have VID/PID as 0, though after this point the sysfs files will start - * showing the updated values. But yeah, that's a bit racy as the same - * sysfs files would be showing 0 before this point. - */ - intf->vendor_id = le32_to_cpu(response.vendor_id); - intf->product_id = le32_to_cpu(response.product_id); - - dev_dbg(&connection->bundle->dev, "Firmware got vid (0x%x)/pid (0x%x)\n", - intf->vendor_id, intf->product_id); -} - -/* This returns path of the firmware blob on the disk */ -static int download_firmware(struct gb_firmware *firmware, u8 stage) -{ - struct gb_connection *connection = firmware->connection; - struct gb_interface *intf = connection->bundle->intf; - char firmware_name[48]; - int rc; - - /* Already have a firmware, free it */ - if (firmware->fw) - free_firmware(firmware); - - /* - * Create firmware name - * - * XXX Name it properly.. - */ - snprintf(firmware_name, sizeof(firmware_name), - "ara_%08x_%08x_%08x_%08x_%02x.tftf", - intf->ddbl1_manufacturer_id, intf->ddbl1_product_id, - intf->vendor_id, intf->product_id, stage); - - // FIXME: - // Turn to dev_dbg later after everyone has valid bootloaders with good - // ids, but leave this as dev_info for now to make it easier to track - // down "empty" vid/pid modules. - dev_info(&connection->bundle->dev, "Firmware file '%s' requested\n", - firmware_name); - - rc = request_firmware(&firmware->fw, firmware_name, - &connection->bundle->dev); - if (rc) - dev_err(&connection->bundle->dev, - "Firware request for %s has failed : %d", - firmware_name, rc); - return rc; -} - -static int gb_firmware_size_request(struct gb_operation *op) -{ - struct gb_firmware *firmware = gb_connection_get_data(op->connection); - struct gb_firmware_size_request *size_request = op->request->payload; - struct gb_firmware_size_response *size_response; - struct device *dev = &op->connection->bundle->dev; - int ret; - - if (op->request->payload_size != sizeof(*size_request)) { - dev_err(dev, "%s: illegal size of firmware size request (%zu != %zu)\n", - __func__, op->request->payload_size, - sizeof(*size_request)); - return -EINVAL; - } - - ret = download_firmware(firmware, size_request->stage); - if (ret) { - dev_err(dev, "%s: failed to download firmware (%d)\n", __func__, - ret); - return ret; - } - - if (!gb_operation_response_alloc(op, sizeof(*size_response), - GFP_KERNEL)) { - dev_err(dev, "%s: error allocating response\n", __func__); - free_firmware(firmware); - return -ENOMEM; - } - - size_response = op->response->payload; - size_response->size = cpu_to_le32(firmware->fw->size); - - dev_dbg(dev, "%s: firmware size %d bytes\n", __func__, size_response->size); - - return 0; -} - -static int gb_firmware_get_firmware(struct gb_operation *op) -{ - struct gb_firmware *firmware = gb_connection_get_data(op->connection); - const struct firmware *fw = firmware->fw; - struct gb_firmware_get_firmware_request *firmware_request; - struct gb_firmware_get_firmware_response *firmware_response; - struct device *dev = &op->connection->bundle->dev; - unsigned int offset, size; - - if (op->request->payload_size != sizeof(*firmware_request)) { - dev_err(dev, "%s: Illegal size of get firmware request (%zu %zu)\n", - __func__, op->request->payload_size, - sizeof(*firmware_request)); - return -EINVAL; - } - - if (!fw) { - dev_err(dev, "%s: firmware not available\n", __func__); - return -EINVAL; - } - - firmware_request = op->request->payload; - offset = le32_to_cpu(firmware_request->offset); - size = le32_to_cpu(firmware_request->size); - - if (offset >= fw->size || size > fw->size - offset) { - dev_warn(dev, "bad firmware request (offs = %u, size = %u)\n", - offset, size); - return -EINVAL; - } - - if (!gb_operation_response_alloc(op, sizeof(*firmware_response) + size, - GFP_KERNEL)) { - dev_err(dev, "%s: error allocating response\n", __func__); - return -ENOMEM; - } - - firmware_response = op->response->payload; - memcpy(firmware_response->data, fw->data + offset, size); - - dev_dbg(dev, "responding with firmware (offs = %u, size = %u)\n", offset, - size); - - return 0; -} - -static int gb_firmware_ready_to_boot(struct gb_operation *op) -{ - struct gb_connection *connection = op->connection; - struct gb_firmware_ready_to_boot_request *rtb_request; - struct device *dev = &connection->bundle->dev; - u8 status; - - if (op->request->payload_size != sizeof(*rtb_request)) { - dev_err(dev, "%s: Illegal size of ready to boot request (%zu %zu)\n", - __func__, op->request->payload_size, - sizeof(*rtb_request)); - return -EINVAL; - } - - rtb_request = op->request->payload; - status = rtb_request->status; - - /* Return error if the blob was invalid */ - if (status == GB_FIRMWARE_BOOT_STATUS_INVALID) - return -EINVAL; - - /* - * XXX Should we return error for insecure firmware? - */ - dev_dbg(dev, "ready to boot: 0x%x, 0\n", status); - - return 0; -} - -static int gb_firmware_request_handler(struct gb_operation *op) -{ - u8 type = op->type; - - switch (type) { - case GB_FIRMWARE_TYPE_FIRMWARE_SIZE: - return gb_firmware_size_request(op); - case GB_FIRMWARE_TYPE_GET_FIRMWARE: - return gb_firmware_get_firmware(op); - case GB_FIRMWARE_TYPE_READY_TO_BOOT: - return gb_firmware_ready_to_boot(op); - default: - dev_err(&op->connection->bundle->dev, - "unsupported request: %u\n", type); - return -EINVAL; - } -} - -static int gb_firmware_get_version(struct gb_firmware *firmware) -{ - struct gb_bundle *bundle = firmware->connection->bundle; - struct gb_firmware_version_request request; - struct gb_firmware_version_response response; - int ret; - - request.major = GB_FIRMWARE_VERSION_MAJOR; - request.minor = GB_FIRMWARE_VERSION_MINOR; - - ret = gb_operation_sync(firmware->connection, - GB_FIRMWARE_TYPE_VERSION, - &request, sizeof(request), &response, - sizeof(response)); - if (ret) { - dev_err(&bundle->dev, - "failed to get protocol version: %d\n", - ret); - return ret; - } - - if (response.major > request.major) { - dev_err(&bundle->dev, - "unsupported major protocol version (%u > %u)\n", - response.major, request.major); - return -ENOTSUPP; - } - - firmware->protocol_major = response.major; - firmware->protocol_minor = response.minor; - - dev_dbg(&bundle->dev, "%s - %u.%u\n", __func__, response.major, - response.minor); - - return 0; -} - -static int gb_firmware_probe(struct gb_bundle *bundle, - const struct greybus_bundle_id *id) -{ - struct greybus_descriptor_cport *cport_desc; - struct gb_connection *connection; - struct gb_firmware *firmware; - int ret; - - if (bundle->num_cports != 1) - return -ENODEV; - - cport_desc = &bundle->cport_desc[0]; - if (cport_desc->protocol_id != GREYBUS_PROTOCOL_FIRMWARE) - return -ENODEV; - - firmware = kzalloc(sizeof(*firmware), GFP_KERNEL); - if (!firmware) - return -ENOMEM; - - connection = gb_connection_create(bundle, - le16_to_cpu(cport_desc->id), - gb_firmware_request_handler); - if (IS_ERR(connection)) { - ret = PTR_ERR(connection); - goto err_free_firmware; - } - - gb_connection_set_data(connection, firmware); - - firmware->connection = connection; - - greybus_set_drvdata(bundle, firmware); - - ret = gb_connection_enable_tx(connection); - if (ret) - goto err_connection_destroy; - - ret = gb_firmware_get_version(firmware); - if (ret) - goto err_connection_disable; - - firmware_es2_fixup_vid_pid(firmware); - - ret = gb_connection_enable(connection); - if (ret) - goto err_connection_disable; - - /* Tell bootrom we're ready. */ - ret = gb_operation_sync(connection, GB_FIRMWARE_TYPE_AP_READY, NULL, 0, - NULL, 0); - if (ret) { - dev_err(&connection->bundle->dev, - "failed to send AP READY: %d\n", ret); - goto err_connection_disable; - } - - dev_dbg(&bundle->dev, "AP_READY sent\n"); - - return 0; - -err_connection_disable: - gb_connection_disable(connection); -err_connection_destroy: - gb_connection_destroy(connection); -err_free_firmware: - kfree(firmware); - - return ret; -} - -static void gb_firmware_disconnect(struct gb_bundle *bundle) -{ - struct gb_firmware *firmware = greybus_get_drvdata(bundle); - - dev_dbg(&bundle->dev, "%s\n", __func__); - - gb_connection_disable(firmware->connection); - - /* Release firmware */ - if (firmware->fw) - free_firmware(firmware); - - gb_connection_destroy(firmware->connection); - kfree(firmware); -} - -static const struct greybus_bundle_id gb_firmware_id_table[] = { - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_FIRMWARE) }, - { } -}; - -static struct greybus_driver gb_firmware_driver = { - .name = "firmware", - .probe = gb_firmware_probe, - .disconnect = gb_firmware_disconnect, - .id_table = gb_firmware_id_table, -}; - -int gb_firmware_init(void) -{ - return greybus_register(&gb_firmware_driver); -} - -void gb_firmware_exit(void) -{ - greybus_deregister(&gb_firmware_driver); -} diff --git a/drivers/staging/greybus/firmware.h b/drivers/staging/greybus/firmware.h deleted file mode 100644 index f25744c..0000000 --- a/drivers/staging/greybus/firmware.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Greybus firmware code - * - * Copyright 2015 Google Inc. - * Copyright 2015 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#ifndef __FIRMWARE_H -#define __FIRMWARE_H - -int gb_firmware_init(void); -void gb_firmware_exit(void); - -#endif /* __FIRMWARE_H */ diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 12b6e74..460fced 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -43,7 +43,7 @@ enum greybus_protocol { GREYBUS_PROTOCOL_AUDIO_MGMT = 0x12, GREYBUS_PROTOCOL_AUDIO_DATA = 0x13, GREYBUS_PROTOCOL_SVC = 0x14, - GREYBUS_PROTOCOL_FIRMWARE = 0x15, + GREYBUS_PROTOCOL_BOOTROM = 0x15, GREYBUS_PROTOCOL_CAMERA_DATA = 0x16, /* ... */ GREYBUS_PROTOCOL_RAW = 0xfe, @@ -72,7 +72,7 @@ enum greybus_class_type { GREYBUS_CLASS_AUDIO = 0x12, /* 0x13 is unused */ /* 0x14 is unused */ - GREYBUS_CLASS_FIRMWARE = 0x15, + GREYBUS_CLASS_BOOTROM = 0x15, /* ... */ GREYBUS_CLASS_RAW = 0xfe, GREYBUS_CLASS_VENDOR = 0xff, diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 06888e0..959ff1b 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -212,70 +212,70 @@ struct gb_control_timesync_authoritative_request { #define GB_APB_REQUEST_CPORT_FEAT_EN 0x0b #define GB_APB_REQUEST_CPORT_FEAT_DIS 0x0c -/* Firmware Protocol */ - -/* Version of the Greybus firmware protocol we support */ -#define GB_FIRMWARE_VERSION_MAJOR 0x00 -#define GB_FIRMWARE_VERSION_MINOR 0x01 - -/* Greybus firmware request types */ -#define GB_FIRMWARE_TYPE_VERSION 0x01 -#define GB_FIRMWARE_TYPE_FIRMWARE_SIZE 0x02 -#define GB_FIRMWARE_TYPE_GET_FIRMWARE 0x03 -#define GB_FIRMWARE_TYPE_READY_TO_BOOT 0x04 -#define GB_FIRMWARE_TYPE_AP_READY 0x05 /* Request with no-payload */ -#define GB_FIRMWARE_TYPE_GET_VID_PID 0x06 /* Request with no-payload */ - -/* Greybus firmware boot stages */ -#define GB_FIRMWARE_BOOT_STAGE_ONE 0x01 /* Reserved for the boot ROM */ -#define GB_FIRMWARE_BOOT_STAGE_TWO 0x02 /* Firmware package to be loaded by the boot ROM */ -#define GB_FIRMWARE_BOOT_STAGE_THREE 0x03 /* Module personality package loaded by Stage 2 firmware */ - -/* Greybus firmware ready to boot status */ -#define GB_FIRMWARE_BOOT_STATUS_INVALID 0x00 /* Firmware blob could not be validated */ -#define GB_FIRMWARE_BOOT_STATUS_INSECURE 0x01 /* Firmware blob is valid but insecure */ -#define GB_FIRMWARE_BOOT_STATUS_SECURE 0x02 /* Firmware blob is valid and secure */ - -/* Max firmware data fetch size in bytes */ -#define GB_FIRMWARE_FETCH_MAX 2000 - -struct gb_firmware_version_request { +/* Bootrom Protocol */ + +/* Version of the Greybus bootrom protocol we support */ +#define GB_BOOTROM_VERSION_MAJOR 0x00 +#define GB_BOOTROM_VERSION_MINOR 0x01 + +/* Greybus bootrom request types */ +#define GB_BOOTROM_TYPE_VERSION 0x01 +#define GB_BOOTROM_TYPE_FIRMWARE_SIZE 0x02 +#define GB_BOOTROM_TYPE_GET_FIRMWARE 0x03 +#define GB_BOOTROM_TYPE_READY_TO_BOOT 0x04 +#define GB_BOOTROM_TYPE_AP_READY 0x05 /* Request with no-payload */ +#define GB_BOOTROM_TYPE_GET_VID_PID 0x06 /* Request with no-payload */ + +/* Greybus bootrom boot stages */ +#define GB_BOOTROM_BOOT_STAGE_ONE 0x01 /* Reserved for the boot ROM */ +#define GB_BOOTROM_BOOT_STAGE_TWO 0x02 /* Bootrom package to be loaded by the boot ROM */ +#define GB_BOOTROM_BOOT_STAGE_THREE 0x03 /* Module personality package loaded by Stage 2 firmware */ + +/* Greybus bootrom ready to boot status */ +#define GB_BOOTROM_BOOT_STATUS_INVALID 0x00 /* Firmware blob could not be validated */ +#define GB_BOOTROM_BOOT_STATUS_INSECURE 0x01 /* Firmware blob is valid but insecure */ +#define GB_BOOTROM_BOOT_STATUS_SECURE 0x02 /* Firmware blob is valid and secure */ + +/* Max bootrom data fetch size in bytes */ +#define GB_BOOTROM_FETCH_MAX 2000 + +struct gb_bootrom_version_request { __u8 major; __u8 minor; } __packed; -struct gb_firmware_version_response { +struct gb_bootrom_version_response { __u8 major; __u8 minor; } __packed; -/* Firmware protocol firmware size request/response */ -struct gb_firmware_size_request { +/* Bootrom protocol firmware size request/response */ +struct gb_bootrom_firmware_size_request { __u8 stage; } __packed; -struct gb_firmware_size_response { +struct gb_bootrom_firmware_size_response { __le32 size; } __packed; -/* Firmware protocol get firmware request/response */ -struct gb_firmware_get_firmware_request { +/* Bootrom protocol get firmware request/response */ +struct gb_bootrom_get_firmware_request { __le32 offset; __le32 size; } __packed; -struct gb_firmware_get_firmware_response { +struct gb_bootrom_get_firmware_response { __u8 data[0]; } __packed; -/* Firmware protocol Ready to boot request */ -struct gb_firmware_ready_to_boot_request { +/* Bootrom protocol Ready to boot request */ +struct gb_bootrom_ready_to_boot_request { __u8 status; } __packed; -/* Firmware protocol Ready to boot response has no payload */ +/* Bootrom protocol Ready to boot response has no payload */ -/* Firmware protocol get VID/PID request has no payload */ -struct gb_firmware_get_vid_pid_response { +/* Bootrom protocol get VID/PID request has no payload */ +struct gb_bootrom_get_vid_pid_response { __le32 vendor_id; __le32 product_id; } __packed; -- cgit v0.10.2 From dc5cc72cc6c219868ad5b87b26c79ac778444210 Mon Sep 17 00:00:00 2001 From: Gjorgji Rosikopulos <grosikopulos@mm-sol.com> Date: Fri, 1 Apr 2016 17:32:43 +0300 Subject: greybus: camera: Add metadata format Add support for greybus metadata format. Greybus metadata format id is 0x41. Signed-off-by: Gjorgji Rosikopulos <grosikopulos@mm-sol.com> Acked-by: Laurent Pinchart <laurent.pinchart@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 2de91d5..6db89ef 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -91,6 +91,10 @@ static const struct gb_camera_fmt_map mbus_to_gbus_format[] = { { .mbus_code = V4L2_MBUS_FMT_JPEG_1X8, .gb_format = 0x40, + }, + { + .mbus_code = V4L2_MBUS_FMT_ARA_METADATA_1X8, + .gb_format = 0x41, } }; -- cgit v0.10.2 From a9234bfd6cec4420b5bef29d77dce1f9cb0543e2 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Wed, 30 Mar 2016 13:23:55 +0530 Subject: greybus: audio_manager: Split device type into i/p & o/p devices Currently, single field is used to report device type say SPK, MIC, HS, HP, etc. However above HAL expects separate fields for input & ouput device types. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_manager.h b/drivers/staging/greybus/audio_manager.h index 9ca7ac09..c4ca097 100644 --- a/drivers/staging/greybus/audio_manager.h +++ b/drivers/staging/greybus/audio_manager.h @@ -22,7 +22,8 @@ struct gb_audio_manager_module_descriptor { int vid; int pid; int cport; - unsigned int devices; + unsigned int ip_devices; + unsigned int op_devices; }; struct gb_audio_manager_module { diff --git a/drivers/staging/greybus/audio_manager_module.c b/drivers/staging/greybus/audio_manager_module.c index e5cffa3..a10e96a 100644 --- a/drivers/staging/greybus/audio_manager_module.c +++ b/drivers/staging/greybus/audio_manager_module.c @@ -122,16 +122,27 @@ static struct gb_audio_manager_module_attribute gb_audio_module_cport_attribute = __ATTR(cport, 0664, gb_audio_module_cport_show, NULL); -static ssize_t gb_audio_module_devices_show( +static ssize_t gb_audio_module_ip_devices_show( struct gb_audio_manager_module *module, struct gb_audio_manager_module_attribute *attr, char *buf) { - return sprintf(buf, "0x%X", module->desc.devices); + return sprintf(buf, "0x%X", module->desc.ip_devices); } static struct gb_audio_manager_module_attribute - gb_audio_module_devices_attribute = - __ATTR(devices, 0664, gb_audio_module_devices_show, NULL); + gb_audio_module_ip_devices_attribute = + __ATTR(ip_devices, 0664, gb_audio_module_ip_devices_show, NULL); + +static ssize_t gb_audio_module_op_devices_show( + struct gb_audio_manager_module *module, + struct gb_audio_manager_module_attribute *attr, char *buf) +{ + return sprintf(buf, "0x%X", module->desc.op_devices); +} + +static struct gb_audio_manager_module_attribute + gb_audio_module_op_devices_attribute = + __ATTR(op_devices, 0664, gb_audio_module_op_devices_show, NULL); static struct attribute *gb_audio_module_default_attrs[] = { &gb_audio_module_name_attribute.attr, @@ -139,7 +150,8 @@ static struct attribute *gb_audio_module_default_attrs[] = { &gb_audio_module_vid_attribute.attr, &gb_audio_module_pid_attribute.attr, &gb_audio_module_cport_attribute.attr, - &gb_audio_module_devices_attribute.attr, + &gb_audio_module_ip_devices_attribute.attr, + &gb_audio_module_op_devices_attribute.attr, NULL, /* need to NULL terminate the list of attributes */ }; @@ -156,7 +168,8 @@ static void send_add_uevent(struct gb_audio_manager_module *module) char vid_string[64]; char pid_string[64]; char cport_string[64]; - char devices_string[64]; + char ip_devices_string[64]; + char op_devices_string[64]; char *envp[] = { name_string, @@ -164,7 +177,8 @@ static void send_add_uevent(struct gb_audio_manager_module *module) vid_string, pid_string, cport_string, - devices_string, + ip_devices_string, + op_devices_string, NULL }; @@ -173,7 +187,10 @@ static void send_add_uevent(struct gb_audio_manager_module *module) snprintf(vid_string, 64, "VID=%d", module->desc.vid); snprintf(pid_string, 64, "PID=%d", module->desc.pid); snprintf(cport_string, 64, "CPORT=%d", module->desc.cport); - snprintf(devices_string, 64, "DEVICES=0x%X", module->desc.devices); + snprintf(ip_devices_string, 64, "I/P DEVICES=0x%X", + module->desc.ip_devices); + snprintf(op_devices_string, 64, "O/P DEVICES=0x%X", + module->desc.op_devices); kobject_uevent_env(&module->kobj, KOBJ_ADD, envp); } @@ -229,12 +246,13 @@ int gb_audio_manager_module_create( void gb_audio_manager_module_dump(struct gb_audio_manager_module *module) { - pr_info("audio module #%d name=%s slot=%d vid=%d pid=%d cport=%d devices=0x%X\n", + pr_info("audio module #%d name=%s slot=%d vid=%d pid=%d cport=%d i/p devices=0x%X o/p devices=0x%X\n", module->id, module->desc.name, module->desc.slot, module->desc.vid, module->desc.pid, module->desc.cport, - module->desc.devices); + module->desc.ip_devices, + module->desc.op_devices); } diff --git a/drivers/staging/greybus/audio_manager_sysfs.c b/drivers/staging/greybus/audio_manager_sysfs.c index c713f5f..d8bf859 100644 --- a/drivers/staging/greybus/audio_manager_sysfs.c +++ b/drivers/staging/greybus/audio_manager_sysfs.c @@ -20,11 +20,12 @@ static ssize_t manager_sysfs_add_store( int num = sscanf(buf, "name=%" GB_AUDIO_MANAGER_MODULE_NAME_LEN_SSCANF "s " - "slot=%d vid=%d pid=%d cport=%d devices=0x%X", + "slot=%d vid=%d pid=%d cport=%d i/p devices=0x%X" + "o/p devices=0x%X", desc.name, &desc.slot, &desc.vid, &desc.pid, - &desc.cport, &desc.devices); + &desc.cport, &desc.ip_devices, &desc.op_devices); - if (num != 6) + if (num != 7) return -EINVAL; num = gb_audio_manager_add(&desc); diff --git a/drivers/staging/greybus/audio_module.c b/drivers/staging/greybus/audio_module.c index 9039aa6..a7f961f 100644 --- a/drivers/staging/greybus/audio_module.c +++ b/drivers/staging/greybus/audio_module.c @@ -353,7 +353,8 @@ static int gb_audio_probe(struct gb_bundle *bundle, desc.vid = 2; /* todo */ desc.pid = 3; /* todo */ desc.cport = gbmodule->dev_id; - desc.devices = 0x2; /* todo */ + desc.op_devices = 0x2; /* todo */ + desc.ip_devices = 0x0; /* todo */ gbmodule->manager_id = gb_audio_manager_add(&desc); dev_dbg(dev, "Add GB Audio device:%s\n", gbmodule->name); -- cgit v0.10.2 From 89de9a06213240b9266f9f368a867cf90d0024bf Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Wed, 30 Mar 2016 13:23:56 +0530 Subject: greybus: audio: Update device type based on widget types Device type info shared to above HAL is currently hard coded to SPK only. Actual device type is identifed while parsing widget types from topology FW shared by codec module. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index 165b359..6182b20 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -36,6 +36,21 @@ enum gbcodec_reg_index { GBCODEC_REG_COUNT }; +/* device_type should be same as defined in audio.h (Android media layer) */ +enum { + GBAUDIO_DEVICE_NONE = 0x0, + /* reserved bits */ + GBAUDIO_DEVICE_BIT_IN = 0x80000000, + GBAUDIO_DEVICE_BIT_DEFAULT = 0x40000000, + /* output devices */ + GBAUDIO_DEVICE_OUT_SPEAKER = 0x2, + GBAUDIO_DEVICE_OUT_WIRED_HEADSET = 0x4, + GBAUDIO_DEVICE_OUT_WIRED_HEADPHONE = 0x8, + /* input devices */ + GBAUDIO_DEVICE_IN_BUILTIN_MIC = GBAUDIO_DEVICE_BIT_IN | 0x4, + GBAUDIO_DEVICE_IN_WIRED_HEADSET = GBAUDIO_DEVICE_BIT_IN | 0x10, +}; + /* bit 0-SPK, 1-HP, 2-DAC, * 4-MIC, 5-HSMIC, 6-MIC2 */ @@ -144,6 +159,8 @@ struct gbaudio_module_info { /* need to share this info to above user space */ int manager_id; char name[NAME_SIZE]; + unsigned int ip_devices; + unsigned int op_devices; /* jack related */ char jack_name[NAME_SIZE]; diff --git a/drivers/staging/greybus/audio_module.c b/drivers/staging/greybus/audio_module.c index a7f961f..dd43b6d 100644 --- a/drivers/staging/greybus/audio_module.c +++ b/drivers/staging/greybus/audio_module.c @@ -353,8 +353,8 @@ static int gb_audio_probe(struct gb_bundle *bundle, desc.vid = 2; /* todo */ desc.pid = 3; /* todo */ desc.cport = gbmodule->dev_id; - desc.op_devices = 0x2; /* todo */ - desc.ip_devices = 0x0; /* todo */ + desc.op_devices = gbmodule->op_devices; + desc.ip_devices = gbmodule->ip_devices; gbmodule->manager_id = gb_audio_manager_add(&desc); dev_dbg(dev, "Add GB Audio device:%s\n", gbmodule->name); diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index 79161c1..e423e6d 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -665,15 +665,20 @@ static int gbaudio_tplg_create_widget(struct gbaudio_module_info *module, case snd_soc_dapm_spk: *dw = (struct snd_soc_dapm_widget) SND_SOC_DAPM_SPK(w->name, gbcodec_event_spk); + module->op_devices |= GBAUDIO_DEVICE_OUT_SPEAKER; break; case snd_soc_dapm_hp: *dw = (struct snd_soc_dapm_widget) SND_SOC_DAPM_HP(w->name, gbcodec_event_hp); module->num_jacks++; + module->op_devices |= (GBAUDIO_DEVICE_OUT_WIRED_HEADSET + | GBAUDIO_DEVICE_OUT_WIRED_HEADPHONE); + module->ip_devices |= GBAUDIO_DEVICE_IN_WIRED_HEADSET; break; case snd_soc_dapm_mic: *dw = (struct snd_soc_dapm_widget) SND_SOC_DAPM_MIC(w->name, gbcodec_event_int_mic); + module->ip_devices |= GBAUDIO_DEVICE_IN_BUILTIN_MIC; break; case snd_soc_dapm_output: *dw = (struct snd_soc_dapm_widget)SND_SOC_DAPM_OUTPUT(w->name); -- cgit v0.10.2 From ddb10c8acc8554ffb68bdb6d80d0e277e124cb2b Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Thu, 7 Apr 2016 20:15:30 -0700 Subject: greybus: svc: add Interface power measurements support This change implements the AP Power Monitor functions for obtaining current/voltage/power on a specific rail of an Interface. Testing Done: $ cat /sys/bus/greybus/devices/1-3/current_now 103 $ cat /sys/bus/greybus/devices/1-3/power_now 303 $ cat /sys/bus/greybus/devices/1-3/voltage_now 203 Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Bartosz Golaszewski <bgolaszewski@baylibre.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 17b1a29..281b05c 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -164,3 +164,24 @@ Contact: Greg Kroah-Hartman <greg@kroah.com> Description: If the SVC watchdog is enabled or not. Writing 0 to this file will disable the watchdog, writing 1 will enable it. + +What: /sys/bus/greybus/device/N-I/voltage_now +Date: March 2016 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman <greg@kroah.com> +Description: + Voltage measurement of the interface in microvolts (uV) + +What: /sys/bus/greybus/device/N-I/current_now +Date: March 2016 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman <greg@kroah.com> +Description: + Current measurement of the interface in microamps (uA) + +What: /sys/bus/greybus/device/N-I/power_now +Date: March 2016 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman <greg@kroah.com> +Description: + Power measurement of the interface in microwatts (uW) diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 959ff1b..e3ef3c9 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -798,6 +798,10 @@ struct gb_spi_transfer_response { #define GB_SVC_TYPE_INTF_EJECT 0x11 #define GB_SVC_TYPE_KEY_EVENT 0x12 #define GB_SVC_TYPE_PING 0x13 +#define GB_SVC_TYPE_PWRMON_RAIL_COUNT_GET 0x14 +#define GB_SVC_TYPE_PWRMON_RAIL_NAMES_GET 0x15 +#define GB_SVC_TYPE_PWRMON_SAMPLE_GET 0x16 +#define GB_SVC_TYPE_PWRMON_INTF_SAMPLE_GET 0x17 /* * SVC version request/response has the same payload as @@ -963,6 +967,25 @@ struct gb_svc_key_event_request { #define GB_SVC_KEY_PRESSED 0x01 } __packed; +#define GB_SVC_PWRMON_TYPE_CURR 0x01 +#define GB_SVC_PWRMON_TYPE_VOL 0x02 +#define GB_SVC_PWRMON_TYPE_PWR 0x03 + +#define GB_SVC_PWRMON_GET_SAMPLE_OK 0x00 +#define GB_SVC_PWRMON_GET_SAMPLE_INVAL 0x01 +#define GB_SVC_PWRMON_GET_SAMPLE_NOSUPP 0x02 +#define GB_SVC_PWRMON_GET_SAMPLE_HWERR 0x03 + +struct gb_svc_pwrmon_intf_sample_get_request { + __u8 intf_id; + __u8 measurement_type; +} __packed; + +struct gb_svc_pwrmon_intf_sample_get_response { + __u8 result; + __le32 measurement; +} __packed; + /* RAW */ /* Version of the Greybus raw protocol we support */ diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 27dbd79..a4bee41f 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -263,6 +263,63 @@ static ssize_t version_show(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR_RO(version); +static ssize_t voltage_now_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_interface *intf = to_gb_interface(dev); + int ret; + u32 measurement; + + ret = gb_svc_pwrmon_intf_sample_get(intf->hd->svc, intf->interface_id, + GB_SVC_PWRMON_TYPE_VOL, + &measurement); + if (ret) { + dev_err(&intf->dev, "failed to get voltage sample (%d)\n", ret); + return ret; + } + + return sprintf(buf, "%u\n", measurement); +} +static DEVICE_ATTR_RO(voltage_now); + +static ssize_t current_now_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_interface *intf = to_gb_interface(dev); + int ret; + u32 measurement; + + ret = gb_svc_pwrmon_intf_sample_get(intf->hd->svc, intf->interface_id, + GB_SVC_PWRMON_TYPE_CURR, + &measurement); + if (ret) { + dev_err(&intf->dev, "failed to get current sample (%d)\n", ret); + return ret; + } + + return sprintf(buf, "%u\n", measurement); +} +static DEVICE_ATTR_RO(current_now); + +static ssize_t power_now_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_interface *intf = to_gb_interface(dev); + int ret; + u32 measurement; + + ret = gb_svc_pwrmon_intf_sample_get(intf->hd->svc, intf->interface_id, + GB_SVC_PWRMON_TYPE_PWR, + &measurement); + if (ret) { + dev_err(&intf->dev, "failed to get power sample (%d)\n", ret); + return ret; + } + + return sprintf(buf, "%u\n", measurement); +} +static DEVICE_ATTR_RO(power_now); + static struct attribute *interface_attrs[] = { &dev_attr_ddbl1_manufacturer_id.attr, &dev_attr_ddbl1_product_id.attr, @@ -273,6 +330,9 @@ static struct attribute *interface_attrs[] = { &dev_attr_product_string.attr, &dev_attr_serial_number.attr, &dev_attr_version.attr, + &dev_attr_voltage_now.attr, + &dev_attr_current_now.attr, + &dev_attr_power_now.attr, NULL, }; ATTRIBUTE_GROUPS(interface); diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index a19e575..b79d817 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -99,6 +99,44 @@ static ssize_t watchdog_store(struct device *dev, } static DEVICE_ATTR_RW(watchdog); +int gb_svc_pwrmon_intf_sample_get(struct gb_svc *svc, u8 intf_id, + u8 measurement_type, u32 *value) +{ + struct gb_svc_pwrmon_intf_sample_get_request request; + struct gb_svc_pwrmon_intf_sample_get_response response; + int ret; + + request.intf_id = intf_id; + request.measurement_type = measurement_type; + + ret = gb_operation_sync(svc->connection, + GB_SVC_TYPE_PWRMON_INTF_SAMPLE_GET, + &request, sizeof(request), + &response, sizeof(response)); + if (ret) { + dev_err(&svc->dev, "failed to get intf sample (%d)\n", ret); + return ret; + } + + if (response.result) { + dev_err(&svc->dev, + "UniPro error while getting intf power sample (%d %d): %d\n", + intf_id, measurement_type, response.result); + switch (response.result) { + case GB_SVC_PWRMON_GET_SAMPLE_INVAL: + return -EINVAL; + case GB_SVC_PWRMON_GET_SAMPLE_NOSUPP: + return -ENOSYS; + default: + return -EIO; + } + } + + *value = le32_to_cpu(response.measurement); + + return 0; +} + static struct attribute *svc_attrs[] = { &dev_attr_endo_id.attr, &dev_attr_ap_intf_id.attr, diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index 8950baf..08f8e37 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -48,6 +48,8 @@ int gb_svc_add(struct gb_svc *svc); void gb_svc_del(struct gb_svc *svc); void gb_svc_put(struct gb_svc *svc); +int gb_svc_pwrmon_intf_sample_get(struct gb_svc *svc, u8 intf_id, + u8 measurement_type, u32 *value); int gb_svc_intf_device_id(struct gb_svc *svc, u8 intf_id, u8 device_id); int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, u8 intf2_id, u8 dev2_id); -- cgit v0.10.2 From b4905038965fb986d8496e47cc52a08428408ae5 Mon Sep 17 00:00:00 2001 From: Evgeniy Borisov <borisov_evgeniy@projectara.com> Date: Wed, 6 Apr 2016 15:22:45 +0300 Subject: greybus: camera-gb: Extend the configure streams interface Extending the configure streams interface with CSI params. Getting CSI frequency data form configure streams response. * num_lanes - Number of CSI data lanes * clk_freq - CSI clock frequency in Hz * lines_per_second - Total number of lines in a second of transmission (blanking included) From the AP side we need to know for the CSI speed configuration. This information is needed for dynamically bandwidth calculations. NOTE: Change should be along merged with corresponding interface change in kernel: "camera: Extend the configure streams interface with CSI params" Signed-off-by: Evgeniy Borisov <eborisov@mm-sol.com> Reviewed-by: Gjorgji Rosikopulos <grosikopulos@mm-sol.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 6db89ef..d3ee5b7 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -203,7 +203,8 @@ struct ap_csi_config_request { static int gb_camera_configure_streams(struct gb_camera *gcam, unsigned int *num_streams, unsigned int *flags, - struct gb_camera_stream_config *streams) + struct gb_camera_stream_config *streams, + struct gb_camera_csi_params *csi_params) { struct gb_camera_configure_streams_request *req; struct gb_camera_configure_streams_response *resp; @@ -309,6 +310,12 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, ret = gb_hd_output(gcam->connection->hd, &csi_cfg, sizeof(csi_cfg), GB_APB_REQUEST_CSI_TX_CONTROL, false); + if (csi_params) { + csi_params->num_lanes = csi_cfg.num_lanes; + /* Transmitting two bits per cycle. (DDR clock) */ + csi_params->clk_freq = csi_cfg.bus_freq / 2; + csi_params->lines_per_second = csi_cfg.lines_per_second; + } } else { csi_cfg.csi_id = 1; ret = gb_hd_output(gcam->connection->hd, &csi_cfg, @@ -442,7 +449,8 @@ static ssize_t gb_camera_op_capabilities(void *priv, char *data, size_t len) } static int gb_camera_op_configure_streams(void *priv, unsigned int *nstreams, - unsigned int *flags, struct gb_camera_stream *streams) + unsigned int *flags, struct gb_camera_stream *streams, + struct gb_camera_csi_params *csi_params) { struct gb_camera *gcam = priv; struct gb_camera_stream_config *gb_streams; @@ -469,7 +477,7 @@ static int gb_camera_op_configure_streams(void *priv, unsigned int *nstreams, gb_flags |= GB_CAMERA_CONFIGURE_STREAMS_TEST_ONLY; ret = gb_camera_configure_streams(gcam, &gb_nstreams, - &gb_flags, gb_streams); + &gb_flags, gb_streams, csi_params); if (ret < 0) goto done; if (gb_nstreams > *nstreams) { @@ -643,7 +651,8 @@ static ssize_t gb_camera_debugfs_configure_streams(struct gb_camera *gcam, goto done; } - ret = gb_camera_configure_streams(gcam, &nstreams, &flags, streams); + ret = gb_camera_configure_streams(gcam, &nstreams, &flags, streams, + NULL); if (ret < 0) goto done; diff --git a/drivers/staging/greybus/gb-camera.h b/drivers/staging/greybus/gb-camera.h index 273b4fa..cc9c012 100644 --- a/drivers/staging/greybus/gb-camera.h +++ b/drivers/staging/greybus/gb-camera.h @@ -24,10 +24,24 @@ struct gb_camera_stream { unsigned int max_size; }; +/** + * struct gb_camera_csi_params - CSI configuration parameters + * @num_lanes: number of CSI data lanes + * @clk_freq: CSI clock frequency in Hz + * @lines_per_second: total number of lines in a second of transmission + * (blanking included) + */ +struct gb_camera_csi_params { + unsigned int num_lanes; + unsigned int clk_freq; + unsigned int lines_per_second; +}; + struct gb_camera_ops { ssize_t (*capabilities)(void *priv, char *buf, size_t len); int (*configure_streams)(void *priv, unsigned int *nstreams, - unsigned int *flags, struct gb_camera_stream *streams); + unsigned int *flags, struct gb_camera_stream *streams, + struct gb_camera_csi_params *csi_params); int (*capture)(void *priv, u32 request_id, unsigned int streams, unsigned int num_frames, size_t settings_size, const void *settings); -- cgit v0.10.2 From a7ddda1f5aa47779071dd4c6f3a5e65c0086e49f Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Date: Tue, 12 Apr 2016 17:18:47 +0530 Subject: greybus: arche-platfrom: Get rid of 2sec delay in USB3613 configuration Earlier during boot sequence implementation, we had seen race between USb3613 and APB boot, and since APB boot time is ~2sec, we delayed USb3613 configuration for 2sec after APB deassertion of reset. This obviously won't work in the case of suspend/resume, where we would like to put APB into OFF state and coldboot in resume. With the latest FW changes, we do not see any race issue. I have done regression testing (> 50 iteration of reboot + unipro link up and down) without any issues. So lets get rid of the 2sec delay with this patch. Testing Done: Tested on EVT 1.5 platform. Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Tested-by: David Lin <dtwlin@google.com> Reviewed-by: David Lin <dtwlin@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 3293661..48cdb0f 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -52,7 +52,6 @@ struct arche_platform_drvdata { int num_apbs; - struct delayed_work delayed_work; enum svc_wakedetect_state wake_detect_state; int wake_detect_irq; spinlock_t lock; @@ -101,24 +100,6 @@ static int apb_poweroff(struct device *dev, void *data) return 0; } -/** - * hub_conf_delayed_work - Configures USB3613 device to HUB mode - * - * The idea here is to split the APB coldboot operation with slow HUB configuration, - * so that driver response to wake/detect event can be met. - * So expectation is, once code reaches here, means initial unipro linkup - * between APB<->Switch was successful, so now just take it to AP. - */ -static void hub_conf_delayed_work(struct work_struct *work) -{ - struct arche_platform_drvdata *arche_pdata = - container_of(work, struct arche_platform_drvdata, delayed_work.work); - - /* Enable HUB3613 into HUB mode. */ - if (usb3613_hub_mode_ctrl(true)) - dev_warn(arche_pdata->dev, "failed to control hub device\n"); -} - static void assert_wakedetect(struct arche_platform_drvdata *arche_pdata) { /* Assert wake/detect = Detect event from AP */ @@ -150,9 +131,11 @@ static irqreturn_t arche_platform_wd_irq_thread(int irq, void *devid) /* Bring APB out of reset: cold boot sequence */ device_for_each_child(arche_pdata->dev, NULL, apb_cold_boot); + /* Enable HUB3613 into HUB mode. */ + if (usb3613_hub_mode_ctrl(true)) + dev_warn(arche_pdata->dev, "failed to control hub device\n"); + spin_lock_irqsave(&arche_pdata->lock, flags); - /* USB HUB configuration */ - schedule_delayed_work(&arche_pdata->delayed_work, msecs_to_jiffies(2000)); arche_pdata->wake_detect_state = WD_STATE_IDLE; spin_unlock_irqrestore(&arche_pdata->lock, flags); @@ -178,8 +161,6 @@ static irqreturn_t arche_platform_wd_irq(int irq, void *devid) if (time_before(jiffies, arche_pdata->wake_detect_start + msecs_to_jiffies(WD_COLDBOOT_PULSE_WIDTH_MS))) { - /* No harm with cancellation, even if not pending */ - cancel_delayed_work(&arche_pdata->delayed_work); arche_pdata->wake_detect_state = WD_STATE_IDLE; } else { /* Check we are not in middle of irq thread already */ @@ -196,8 +177,6 @@ static irqreturn_t arche_platform_wd_irq(int irq, void *devid) /* wake/detect falling */ if (arche_pdata->wake_detect_state == WD_STATE_IDLE) { arche_pdata->wake_detect_start = jiffies; - /* No harm with cancellation even if it is not pending*/ - cancel_delayed_work(&arche_pdata->delayed_work); /* * In the begining, when wake/detect goes low (first time), we assume * it is meant for coldboot and set the flag. If wake/detect line stays low @@ -494,7 +473,6 @@ static int arche_platform_probe(struct platform_device *pdev) } assert_wakedetect(arche_pdata); - INIT_DELAYED_WORK(&arche_pdata->delayed_work, hub_conf_delayed_work); dev_info(dev, "Device registered successfully\n"); return 0; @@ -520,7 +498,6 @@ static int arche_platform_remove(struct platform_device *pdev) struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev); device_remove_file(&pdev->dev, &dev_attr_state); - cancel_delayed_work_sync(&arche_pdata->delayed_work); device_for_each_child(&pdev->dev, NULL, arche_remove_child); arche_platform_poweroff_seq(arche_pdata); platform_set_drvdata(pdev, NULL); -- cgit v0.10.2 From 777471a445242e34c790b5b80d031a013933fd05 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Tue, 12 Apr 2016 17:15:11 +0100 Subject: greybus: Fixup __u64, __u32 to __le64, __le32 in timesync declarations A number of data in TimeSync command structures are declared __u64/__u32 instead of __le64/__le32, I forgot to put this through an x86_64 compile before presentation for merge and as a result didn't catch this error. This patch fixes. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index 8475f15..91a7fca 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -269,7 +269,7 @@ int gb_control_timesync_authoritative(struct gb_control *control, int i; for (i = 0; i < GB_TIMESYNC_MAX_STROBES; i++) - request.frame_time[i] = frame_time[i]; + request.frame_time[i] = cpu_to_le64(frame_time[i]); return gb_operation_sync(control->connection, GB_CONTROL_TYPE_TIMESYNC_AUTHORITATIVE, diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index e3ef3c9..e0c0493 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -180,7 +180,7 @@ struct gb_control_timesync_enable_request { /* timesync enable response has no payload */ struct gb_control_timesync_authoritative_request { - __u64 frame_time[GB_TIMESYNC_MAX_STROBES]; + __le64 frame_time[GB_TIMESYNC_MAX_STROBES]; } __packed; /* timesync authoritative response has no payload */ @@ -911,16 +911,16 @@ struct gb_svc_route_destroy_request { struct gb_svc_timesync_enable_request { __u8 count; - __u64 frame_time; - __u32 strobe_delay; - __u32 strobe_mask; - __u32 refclk; + __le64 frame_time; + __le32 strobe_delay; + __le32 strobe_mask; + __le32 refclk; } __packed; /* timesync enable response has no payload */ /* timesync authoritative request has no payload */ struct gb_svc_timesync_authoritative_response { - __u64 frame_time[GB_TIMESYNC_MAX_STROBES]; + __le64 frame_time[GB_TIMESYNC_MAX_STROBES]; }; #define GB_SVC_UNIPRO_FAST_MODE 0x01 -- cgit v0.10.2 From 9160b7c7652a80f48250bbdc151fa0af3ccf024f Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Sat, 16 Apr 2016 01:15:15 +0530 Subject: greybus: arche-platform: Power-off unipro subsystem upon suspend Switch off APBs/SVC/Switch in the suspend call notifier. Note that this is an interim solution to enable fishfooding. Testing done: - Passed QA sanity test on EVT1.5 - Suspend current measured at ~70mW Signed-off-by: David Lin <dtwlin@google.com> Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> [vaibhav.hiremath@linaro.org: Updated commit description] Tested-by: Sandeep Patil <sspatil@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 48cdb0f..3ff4f69 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -19,6 +19,7 @@ #include <linux/pm.h> #include <linux/interrupt.h> #include <linux/irq.h> +#include <linux/suspend.h> #include <linux/time.h> #include "arche_platform.h" @@ -56,6 +57,7 @@ struct arche_platform_drvdata { int wake_detect_irq; spinlock_t lock; unsigned long wake_detect_start; + struct notifier_block pm_notifier; struct device *dev; }; @@ -339,6 +341,31 @@ static ssize_t state_show(struct device *dev, static DEVICE_ATTR_RW(state); +static int arche_platform_pm_notifier(struct notifier_block *notifier, + unsigned long pm_event, void *unused) +{ + struct arche_platform_drvdata *arche_pdata = + container_of(notifier, struct arche_platform_drvdata, + pm_notifier); + + switch (pm_event) { + case PM_SUSPEND_PREPARE: + if (arche_pdata->state != ARCHE_PLATFORM_STATE_ACTIVE) + return NOTIFY_STOP; + device_for_each_child(arche_pdata->dev, NULL, apb_poweroff); + arche_platform_poweroff_seq(arche_pdata); + break; + case PM_POST_SUSPEND: + arche_platform_coldboot_seq(arche_pdata); + assert_wakedetect(arche_pdata); + break; + default: + break; + } + + return NOTIFY_DONE; +} + static int arche_platform_probe(struct platform_device *pdev) { struct arche_platform_drvdata *arche_pdata; @@ -474,6 +501,13 @@ static int arche_platform_probe(struct platform_device *pdev) assert_wakedetect(arche_pdata); + arche_pdata->pm_notifier.notifier_call = arche_platform_pm_notifier; + ret = register_pm_notifier(&arche_pdata->pm_notifier); + if (ret) { + dev_err(dev, "failed to register pm notifier %d\n", ret); + goto err_populate; + } + dev_info(dev, "Device registered successfully\n"); return 0; @@ -497,6 +531,7 @@ static int arche_platform_remove(struct platform_device *pdev) { struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev); + unregister_pm_notifier(&arche_pdata->pm_notifier); device_remove_file(&pdev->dev, &dev_attr_state); device_for_each_child(&pdev->dev, NULL, arche_remove_child); arche_platform_poweroff_seq(arche_pdata); -- cgit v0.10.2 From 192c70dcf6c6f8c39a108f9ba56e916808f23cca Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Sat, 16 Apr 2016 01:15:16 +0530 Subject: greybus: svc watchdog: Disable watchdog upon entering suspend SVC watchdog should be disabled when device is entering suspend mode. Testing done: - Sanity tested on EVT1.5 - Check no SVC ping during the suspend process - Check SVC watchdog is back on pinging once device is resumed Signed-off-by: David Lin <dtwlin@google.com> Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> [vaibhav.hiremath@linaro.org: Removed unwanted check in notifier callback and Updated commit description] Tested-by: Sandeep Patil <sspatil@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/svc_watchdog.c b/drivers/staging/greybus/svc_watchdog.c index 9bd68f4..6cd3bac 100644 --- a/drivers/staging/greybus/svc_watchdog.c +++ b/drivers/staging/greybus/svc_watchdog.c @@ -7,6 +7,7 @@ */ #include <linux/delay.h> +#include <linux/suspend.h> #include <linux/workqueue.h> #include "greybus.h" @@ -16,10 +17,31 @@ struct gb_svc_watchdog { struct delayed_work work; struct gb_svc *svc; bool enabled; + struct notifier_block pm_notifier; }; static struct delayed_work reset_work; +static int svc_watchdog_pm_notifier(struct notifier_block *notifier, + unsigned long pm_event, void *unused) +{ + struct gb_svc_watchdog *watchdog = + container_of(notifier, struct gb_svc_watchdog, pm_notifier); + + switch (pm_event) { + case PM_SUSPEND_PREPARE: + gb_svc_watchdog_disable(watchdog->svc); + break; + case PM_POST_SUSPEND: + gb_svc_watchdog_enable(watchdog->svc); + break; + default: + break; + } + + return NOTIFY_DONE; +} + static void greybus_reset(struct work_struct *work) { static char start_path[256] = "/system/bin/start"; @@ -82,6 +104,7 @@ static void do_work(struct work_struct *work) int gb_svc_watchdog_create(struct gb_svc *svc) { struct gb_svc_watchdog *watchdog; + int retval; if (svc->watchdog) return 0; @@ -95,7 +118,27 @@ int gb_svc_watchdog_create(struct gb_svc *svc) INIT_DELAYED_WORK(&watchdog->work, do_work); svc->watchdog = watchdog; - return gb_svc_watchdog_enable(svc); + watchdog->pm_notifier.notifier_call = svc_watchdog_pm_notifier; + retval = register_pm_notifier(&watchdog->pm_notifier); + if (retval) { + dev_err(&svc->dev, "error registering pm notifier(%d)\n", + retval); + goto svc_watchdog_create_err; + } + + retval = gb_svc_watchdog_enable(svc); + if (retval) { + dev_err(&svc->dev, "error enabling watchdog (%d)\n", retval); + unregister_pm_notifier(&watchdog->pm_notifier); + goto svc_watchdog_create_err; + } + return retval; + +svc_watchdog_create_err: + svc->watchdog = NULL; + kfree(watchdog); + + return retval; } void gb_svc_watchdog_destroy(struct gb_svc *svc) @@ -105,6 +148,7 @@ void gb_svc_watchdog_destroy(struct gb_svc *svc) if (!watchdog) return; + unregister_pm_notifier(&watchdog->pm_notifier); gb_svc_watchdog_disable(svc); svc->watchdog = NULL; kfree(watchdog); -- cgit v0.10.2 From 0928b2e4401cebd7fd2b8aebc41be60dbe4c2ef3 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva <rui.silva@linaro.org> Date: Wed, 20 Apr 2016 14:40:22 +0100 Subject: greybus: spi: fix message transfer over greybus The actual implementation of transfer_one_message have problems with some cases in the possible transfer options. We try to maximize the number of spi transfers in one greybus operation and need to save state until the full message is dispatch over greybus. Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org> Tested-by: Philip Yang <philipy@bsquare.com> Tested-by: Axel Haslam <ahaslam@baylibre.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index 12e8cd8..0bae7f1 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -18,6 +18,11 @@ struct gb_spi { struct gb_connection *connection; + struct spi_transfer *first_xfer; + struct spi_transfer *last_xfer; + u32 rx_xfer_offset; + u32 tx_xfer_offset; + u32 last_xfer_size; u16 mode; u16 flags; u32 bits_per_word_mask; @@ -26,6 +31,13 @@ struct gb_spi { u32 max_speed_hz; }; +#define GB_SPI_STATE_MSG_DONE ((void *)0) +#define GB_SPI_STATE_MSG_IDLE ((void *)1) +#define GB_SPI_STATE_MSG_RUNNING ((void *)2) +#define GB_SPI_STATE_OP_READY ((void *)3) +#define GB_SPI_STATE_OP_DONE ((void *)4) +#define GB_SPI_STATE_MSG_ERROR ((void *)-1) + static struct spi_master *get_master_from_spi(struct gb_spi *spi) { return gb_connection_get_data(spi->connection); @@ -76,58 +88,120 @@ static size_t calc_tx_xfer_size(u32 tx_size, u32 count, size_t len, return len; } +static void clean_xfer_state(struct gb_spi *spi) +{ + spi->first_xfer = NULL; + spi->last_xfer = NULL; + spi->rx_xfer_offset = 0; + spi->tx_xfer_offset = 0; + spi->last_xfer_size = 0; +} + +static int setup_next_xfer(struct gb_spi *spi, struct spi_message *msg) +{ + struct spi_transfer *last_xfer = spi->last_xfer; + + if (msg->state != GB_SPI_STATE_OP_DONE) + return 0; + + /* + * if we transferred all content of the last transfer, reset values and + * check if this was the last transfer in the message + */ + if ((spi->tx_xfer_offset + spi->last_xfer_size == last_xfer->len) || + (spi->rx_xfer_offset + spi->last_xfer_size == last_xfer->len)) { + spi->tx_xfer_offset = 0; + spi->rx_xfer_offset = 0; + if (last_xfer == list_last_entry(&msg->transfers, + struct spi_transfer, + transfer_list)) + msg->state = GB_SPI_STATE_MSG_DONE; + else + spi->first_xfer = list_next_entry(last_xfer, + transfer_list); + return 0; + } + + spi->first_xfer = last_xfer; + if (last_xfer->tx_buf) + spi->tx_xfer_offset += spi->last_xfer_size; + + if (last_xfer->rx_buf) + spi->rx_xfer_offset += spi->last_xfer_size; + + return 0; +} + +static struct spi_transfer *get_next_xfer(struct spi_transfer *xfer, + struct spi_message *msg) +{ + if (xfer == list_last_entry(&msg->transfers, struct spi_transfer, + transfer_list)) + return NULL; + + return list_next_entry(xfer, transfer_list); +} + /* Routines to transfer data */ static struct gb_operation * -gb_spi_operation_create(struct gb_connection *connection, - struct spi_message *msg, u32 *total_len) +gb_spi_operation_create(struct gb_spi *spi, struct gb_connection *connection, + struct spi_message *msg) { struct gb_spi_transfer_request *request; struct spi_device *dev = msg->spi; struct spi_transfer *xfer; struct gb_spi_transfer *gb_xfer; struct gb_operation *operation; - struct spi_transfer *last_xfer = NULL; u32 tx_size = 0, rx_size = 0, count = 0, xfer_len = 0, request_size; - u32 tx_xfer_size = 0, rx_xfer_size = 0, last_xfer_size = 0; + u32 tx_xfer_size = 0, rx_xfer_size = 0, len; + u32 total_len = 0; size_t data_max; void *tx_data; data_max = gb_operation_get_payload_size_max(connection); + xfer = spi->first_xfer; /* Find number of transfers queued and tx/rx length in the message */ - list_for_each_entry(xfer, &msg->transfers, transfer_list) { + + while (msg->state != GB_SPI_STATE_OP_READY) { + msg->state = GB_SPI_STATE_MSG_RUNNING; + spi->last_xfer = xfer; + if (!xfer->tx_buf && !xfer->rx_buf) { dev_err(&connection->bundle->dev, "bufferless transfer, length %u\n", xfer->len); + msg->state = GB_SPI_STATE_MSG_ERROR; return NULL; } - last_xfer = xfer; tx_xfer_size = 0; rx_xfer_size = 0; if (xfer->tx_buf) { + len = xfer->len - spi->tx_xfer_offset; if (!tx_header_fit_operation(tx_size, count, data_max)) break; tx_xfer_size = calc_tx_xfer_size(tx_size, count, - xfer->len, data_max); - last_xfer_size = tx_xfer_size; + len, data_max); + spi->last_xfer_size = tx_xfer_size; } if (xfer->rx_buf) { + len = xfer->len - spi->rx_xfer_offset; rx_xfer_size = calc_rx_xfer_size(rx_size, &tx_xfer_size, - xfer->len, data_max); - last_xfer_size = rx_xfer_size; + len, data_max); + spi->last_xfer_size = rx_xfer_size; } tx_size += tx_xfer_size; rx_size += rx_xfer_size; - *total_len += last_xfer_size; + total_len += spi->last_xfer_size; count++; - if (xfer->len != last_xfer_size) - break; + xfer = get_next_xfer(xfer, msg); + if (!xfer || total_len >= data_max) + msg->state = GB_SPI_STATE_OP_READY; } /* @@ -153,9 +227,10 @@ gb_spi_operation_create(struct gb_connection *connection, tx_data = gb_xfer + count; /* place tx data after last gb_xfer */ /* Fill in the transfers array */ - list_for_each_entry(xfer, &msg->transfers, transfer_list) { - if (last_xfer && xfer == last_xfer) - xfer_len = last_xfer_size; + xfer = spi->first_xfer; + while (msg->state != GB_SPI_STATE_OP_DONE) { + if (xfer == spi->last_xfer) + xfer_len = spi->last_xfer_size; else xfer_len = xfer->len; @@ -168,34 +243,54 @@ gb_spi_operation_create(struct gb_connection *connection, /* Copy tx data */ if (xfer->tx_buf) { gb_xfer->rdwr |= GB_SPI_XFER_WRITE; - memcpy(tx_data, xfer->tx_buf, xfer_len); + memcpy(tx_data, xfer->tx_buf + spi->tx_xfer_offset, + xfer_len); tx_data += xfer_len; } if (xfer->rx_buf) gb_xfer->rdwr |= GB_SPI_XFER_READ; - if (last_xfer && xfer == last_xfer) - break; + if (xfer == spi->last_xfer) { + msg->state = GB_SPI_STATE_OP_DONE; + continue; + } gb_xfer++; + xfer = get_next_xfer(xfer, msg); } + msg->actual_length += total_len; + return operation; } -static void gb_spi_decode_response(struct spi_message *msg, +static void gb_spi_decode_response(struct gb_spi *spi, struct spi_message *msg, struct gb_spi_transfer_response *response) { - struct spi_transfer *xfer; + struct spi_transfer *xfer = spi->first_xfer; void *rx_data = response->data; + u32 xfer_len; - list_for_each_entry(xfer, &msg->transfers, transfer_list) { + while (xfer) { /* Copy rx data */ if (xfer->rx_buf) { - memcpy(xfer->rx_buf, rx_data, xfer->len); - rx_data += xfer->len; + if (xfer == spi->first_xfer) + xfer_len = xfer->len - spi->rx_xfer_offset; + else if (xfer == spi->last_xfer) + xfer_len = spi->last_xfer_size; + else + xfer_len = xfer->len; + + memcpy(xfer->rx_buf + spi->rx_xfer_offset, rx_data, + xfer_len); + rx_data += xfer_len; } + + if (xfer == spi->last_xfer) + break; + + xfer = list_next_entry(xfer, transfer_list); } } @@ -206,27 +301,45 @@ static int gb_spi_transfer_one_message(struct spi_master *master, struct gb_connection *connection = spi->connection; struct gb_spi_transfer_response *response; struct gb_operation *operation; - u32 len = 0; - int ret; + int ret = 0; + + spi->first_xfer = list_first_entry_or_null(&msg->transfers, + struct spi_transfer, + transfer_list); + if (!spi->first_xfer) { + ret = -ENOMEM; + goto out; + } - operation = gb_spi_operation_create(connection, msg, &len); - if (!operation) - return -ENOMEM; + msg->state = GB_SPI_STATE_MSG_IDLE; + + while (msg->state != GB_SPI_STATE_MSG_DONE && + msg->state != GB_SPI_STATE_MSG_ERROR) { + operation = gb_spi_operation_create(spi, connection, msg); + if (!operation) { + msg->state = GB_SPI_STATE_MSG_ERROR; + ret = -EINVAL; + continue; + } - ret = gb_operation_request_send_sync(operation); - if (!ret) { - response = operation->response->payload; - if (response) - gb_spi_decode_response(msg, response); - } else { - dev_err(&connection->bundle->dev, + ret = gb_operation_request_send_sync(operation); + if (!ret) { + response = operation->response->payload; + if (response) + gb_spi_decode_response(spi, msg, response); + } else { + dev_err(&connection->bundle->dev, "transfer operation failed: %d\n", ret); - } + msg->state = GB_SPI_STATE_MSG_ERROR; + } - gb_operation_put(operation); + gb_operation_put(operation); + setup_next_xfer(spi, msg); + } - msg->actual_length = len; - msg->status = 0; +out: + msg->status = ret; + clean_xfer_state(spi); spi_finalize_current_message(master); return ret; -- cgit v0.10.2 From d1d67714a4ece3c1438c9d7def324ee0424e7cbd Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva <rui.silva@linaro.org> Date: Wed, 20 Apr 2016 14:40:23 +0100 Subject: greybus: spi: use timeout request send operation When transfer speed is too slow (less than 17Khz) the operation can take longer than the default greybus timeout. Because of this we need to use the request_send_sync_timeout and calculate the correct timeout for each operation. Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org> Tested-by: Philip Yang <philipy@bsquare.com> Tested-by: Axel Haslam <ahaslam@baylibre.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index 0bae7f1..ce706ed 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -23,6 +23,7 @@ struct gb_spi { u32 rx_xfer_offset; u32 tx_xfer_offset; u32 last_xfer_size; + unsigned int op_timeout; u16 mode; u16 flags; u32 bits_per_word_mask; @@ -38,6 +39,8 @@ struct gb_spi { #define GB_SPI_STATE_OP_DONE ((void *)4) #define GB_SPI_STATE_MSG_ERROR ((void *)-1) +#define XFER_TIMEOUT_TOLERANCE 200 + static struct spi_master *get_master_from_spi(struct gb_spi *spi) { return gb_connection_get_data(spi->connection); @@ -95,6 +98,7 @@ static void clean_xfer_state(struct gb_spi *spi) spi->rx_xfer_offset = 0; spi->tx_xfer_offset = 0; spi->last_xfer_size = 0; + spi->op_timeout = 0; } static int setup_next_xfer(struct gb_spi *spi, struct spi_message *msg) @@ -112,6 +116,7 @@ static int setup_next_xfer(struct gb_spi *spi, struct spi_message *msg) (spi->rx_xfer_offset + spi->last_xfer_size == last_xfer->len)) { spi->tx_xfer_offset = 0; spi->rx_xfer_offset = 0; + spi->op_timeout = 0; if (last_xfer == list_last_entry(&msg->transfers, struct spi_transfer, transfer_list)) @@ -155,6 +160,7 @@ gb_spi_operation_create(struct gb_spi *spi, struct gb_connection *connection, u32 tx_size = 0, rx_size = 0, count = 0, xfer_len = 0, request_size; u32 tx_xfer_size = 0, rx_xfer_size = 0, len; u32 total_len = 0; + unsigned int xfer_timeout; size_t data_max; void *tx_data; @@ -234,6 +240,13 @@ gb_spi_operation_create(struct gb_spi *spi, struct gb_connection *connection, else xfer_len = xfer->len; + /* make sure we do not timeout in a slow transfer */ + xfer_timeout = xfer_len * 8 * MSEC_PER_SEC / xfer->speed_hz; + xfer_timeout += GB_OPERATION_TIMEOUT_DEFAULT; + + if (xfer_timeout > spi->op_timeout) + spi->op_timeout = xfer_timeout; + gb_xfer->speed_hz = cpu_to_le32(xfer->speed_hz); gb_xfer->len = cpu_to_le32(xfer_len); gb_xfer->delay_usecs = cpu_to_le16(xfer->delay_usecs); @@ -322,7 +335,8 @@ static int gb_spi_transfer_one_message(struct spi_master *master, continue; } - ret = gb_operation_request_send_sync(operation); + ret = gb_operation_request_send_sync_timeout(operation, + spi->op_timeout); if (!ret) { response = operation->response->payload; if (response) -- cgit v0.10.2 From 7d963cbe8302d16d2171ecc729782f0d2e7cfbe7 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 13 Apr 2016 19:18:55 +0200 Subject: greybus: manifest: fix illegal free in error path The manifest-parsing code could end up leaving the interface vendor_string set to an error pointer that we'd eventually try to free when destroying the interface. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 070afc6..cca4592 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -384,15 +384,18 @@ static bool gb_manifest_parse_interface(struct gb_interface *intf, struct manifest_desc *interface_desc) { struct greybus_descriptor_interface *desc_intf = interface_desc->data; + char *str; /* Handle the strings first--they can fail */ - intf->vendor_string = gb_string_get(intf, desc_intf->vendor_stringid); - if (IS_ERR(intf->vendor_string)) + str = gb_string_get(intf, desc_intf->vendor_stringid); + if (IS_ERR(str)) return false; + intf->vendor_string = str; - intf->product_string = gb_string_get(intf, desc_intf->product_stringid); - if (IS_ERR(intf->product_string)) + str = gb_string_get(intf, desc_intf->product_stringid); + if (IS_ERR(str)) goto out_free_vendor_string; + intf->product_string = str; /* Release the interface descriptor, now that we're done with it */ release_manifest_descriptor(interface_desc); -- cgit v0.10.2 From aba2fc626e02d493a816bd9e89d338509ca5accc Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 13 Apr 2016 19:18:56 +0200 Subject: greybus: Documentation: move the interface power attributes Move the interface power attributes after the other interface attributes to keep the attributes grouped by device type. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 281b05c..d8bf30e 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -81,6 +81,27 @@ Description: Interface version represented as <16 bit major number>.<16 bit minor number>. +What: /sys/bus/greybus/device/N-I/voltage_now +Date: March 2016 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman <greg@kroah.com> +Description: + Voltage measurement of the interface in microvolts (uV) + +What: /sys/bus/greybus/device/N-I/current_now +Date: March 2016 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman <greg@kroah.com> +Description: + Current measurement of the interface in microamps (uA) + +What: /sys/bus/greybus/device/N-I/power_now +Date: March 2016 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman <greg@kroah.com> +Description: + Power measurement of the interface in microwatts (uW) + What: /sys/bus/greybus/device/N-I.B Date: October 2015 KernelVersion: 4.XX @@ -164,24 +185,3 @@ Contact: Greg Kroah-Hartman <greg@kroah.com> Description: If the SVC watchdog is enabled or not. Writing 0 to this file will disable the watchdog, writing 1 will enable it. - -What: /sys/bus/greybus/device/N-I/voltage_now -Date: March 2016 -KernelVersion: 4.XX -Contact: Greg Kroah-Hartman <greg@kroah.com> -Description: - Voltage measurement of the interface in microvolts (uV) - -What: /sys/bus/greybus/device/N-I/current_now -Date: March 2016 -KernelVersion: 4.XX -Contact: Greg Kroah-Hartman <greg@kroah.com> -Description: - Current measurement of the interface in microamps (uA) - -What: /sys/bus/greybus/device/N-I/power_now -Date: March 2016 -KernelVersion: 4.XX -Contact: Greg Kroah-Hartman <greg@kroah.com> -Description: - Power measurement of the interface in microwatts (uW) -- cgit v0.10.2 From 78b609b14c432d9ce9a994b31b6d18ae3fd41288 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 13 Apr 2016 19:18:57 +0200 Subject: greybus: Documentation/sysfs: remove interface unique_id attribute Remove the interface unique_id attribute, which there is currently no plan to ever implement. Note that the Ara serial numbers are already exposed through the serial_number attribute. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/unique_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/unique_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/unique_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/unique_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/unique_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/unique_id deleted file mode 100644 index e69de29..0000000 -- cgit v0.10.2 From 9e5e6fa6bf66503f4eb48601f3d7b58c8a5f2b0a Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 13 Apr 2016 19:18:58 +0200 Subject: greybus: Documentation/sysfs: rename the svc eject attribute The svc eject attribute was added as an interim solution and is still used to implement a form of forced ejection. This will soon be superseded by the module eject attribute, which will provide an interface for clean eject. We may keep the forced-eject mechanism around indefinitely, albeit possibly with a different name (e.g. forced_intf_eject). Either way, update the example tree to reflect the actual name, intf_eject, which currently used for this svc attribute. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-svc/eject b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-svc/eject deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-svc/intf_eject b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-svc/intf_eject new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-svc/eject b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-svc/eject deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-svc/intf_eject b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-svc/intf_eject new file mode 100644 index 0000000..e69de29 -- cgit v0.10.2 From 078ef067bca6725ab71c0c8d58112ae66097062f Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 13 Apr 2016 19:18:59 +0200 Subject: greybus: Documentation/sysfs: add example control devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add control devices to the example sysfs tree. Control devices are named <bus_id>-<module_id>.<intf_id>.ctrl and expose attributes that are specific to the greybus interface type. Specifically, dummy interfaces do not have a control device. Currently, only the vendor and product strings extracted from the manifest are exported. A subtree of the example tree now looks as follows: greybus1/ ├── 1-5 │   ├── 1-5.5 │   │   ├── 1-5.5.2 │   │   │   ├── bundle_class │   │   │   ├── bundle_id │   │   │   └── state │   │   ├── 1-5.5.ctrl │   │   │   ├── product_string │   │   │   └── vendor_string │   │   ├── ddbl1_manufacturer_id │   │   ├── ddbl1_product_id │   │   ├── interface_id │   │   ├── product_id │   │   ├── serial_number │   │   └── vendor_id │   ├── 1-5.6 │   │   └── interface_id │   ├── eject │   ├── module_id │   └── num_interfaces └── 1-svc Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.ctrl/product_string b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.ctrl/product_string new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.ctrl/vendor_string b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.ctrl/vendor_string new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.ctrl/product_string b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.ctrl/product_string new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.ctrl/vendor_string b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.ctrl/vendor_string new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.ctrl/product_string b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.ctrl/product_string new file mode 100644 index 0000000..e69de29 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.ctrl/vendor_string b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.ctrl/vendor_string new file mode 100644 index 0000000..e69de29 -- cgit v0.10.2 From a530a8be395ff2df384ca729013890f3f040cf99 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 13 Apr 2016 19:19:00 +0200 Subject: greybus: interface: disable interface on registration failures Disable and deactivate an interface immediately on registration failures. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index b79d817..5a16ad3 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -518,7 +518,12 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) goto err_interface_deactivate; } - gb_interface_add(intf); + ret = gb_interface_add(intf); + if (ret) { + gb_interface_disable(intf); + gb_interface_deactivate(intf); + return; + } return; -- cgit v0.10.2 From 1ed8cdef405806c246b62a1ba926e0251fdaa531 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 13 Apr 2016 19:19:01 +0200 Subject: greybus: control: move timesync-operation functions Move the timesync-operation functions above the control-object management functions, which is where all other operation implementations reside. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index 91a7fca..3c1f664 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -177,6 +177,42 @@ int gb_control_get_interface_version_operation(struct gb_interface *intf) return 0; } +int gb_control_timesync_enable(struct gb_control *control, u8 count, + u64 frame_time, u32 strobe_delay, u32 refclk) +{ + struct gb_control_timesync_enable_request request; + + request.count = count; + request.frame_time = cpu_to_le64(frame_time); + request.strobe_delay = cpu_to_le32(strobe_delay); + request.refclk = cpu_to_le32(refclk); + return gb_operation_sync(control->connection, + GB_CONTROL_TYPE_TIMESYNC_ENABLE, &request, + sizeof(request), NULL, 0); +} + +int gb_control_timesync_disable(struct gb_control *control) +{ + return gb_operation_sync(control->connection, + GB_CONTROL_TYPE_TIMESYNC_DISABLE, NULL, 0, + NULL, 0); +} + +int gb_control_timesync_authoritative(struct gb_control *control, + u64 *frame_time, u8 count) +{ + struct gb_control_timesync_authoritative_request request; + int i; + + for (i = 0; i < GB_TIMESYNC_MAX_STROBES; i++) + request.frame_time[i] = cpu_to_le64(frame_time[i]); + + return gb_operation_sync(control->connection, + GB_CONTROL_TYPE_TIMESYNC_AUTHORITATIVE, + &request, sizeof(request), + NULL, 0); +} + struct gb_control *gb_control_create(struct gb_interface *intf) { struct gb_control *control; @@ -240,39 +276,3 @@ void gb_control_destroy(struct gb_control *control) gb_connection_destroy(control->connection); kfree(control); } - -int gb_control_timesync_enable(struct gb_control *control, u8 count, - u64 frame_time, u32 strobe_delay, u32 refclk) -{ - struct gb_control_timesync_enable_request request; - - request.count = count; - request.frame_time = cpu_to_le64(frame_time); - request.strobe_delay = cpu_to_le32(strobe_delay); - request.refclk = cpu_to_le32(refclk); - return gb_operation_sync(control->connection, - GB_CONTROL_TYPE_TIMESYNC_ENABLE, &request, - sizeof(request), NULL, 0); -} - -int gb_control_timesync_disable(struct gb_control *control) -{ - return gb_operation_sync(control->connection, - GB_CONTROL_TYPE_TIMESYNC_DISABLE, NULL, 0, - NULL, 0); -} - -int gb_control_timesync_authoritative(struct gb_control *control, - u64 *frame_time, u8 count) -{ - struct gb_control_timesync_authoritative_request request; - int i; - - for (i = 0; i < GB_TIMESYNC_MAX_STROBES; i++) - request.frame_time[i] = cpu_to_le64(frame_time[i]); - - return gb_operation_sync(control->connection, - GB_CONTROL_TYPE_TIMESYNC_AUTHORITATIVE, - &request, sizeof(request), - NULL, 0); -} -- cgit v0.10.2 From a6e5b014b8fe0bd4cb1e1ca0380320a200605742 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 13 Apr 2016 19:19:02 +0200 Subject: greybus: core: make the control object be a device Make the control object be a greybus device. The control device will be used to expose attributes specific to greybus-type interfaces. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index 3c1f664..c303bb2 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -213,6 +213,20 @@ int gb_control_timesync_authoritative(struct gb_control *control, NULL, 0); } +static void gb_control_release(struct device *dev) +{ + struct gb_control *control = to_gb_control(dev); + + gb_connection_destroy(control->connection); + + kfree(control); +} + +struct device_type greybus_control_type = { + .name = "greybus_control", + .release = gb_control_release, +}; + struct gb_control *gb_control_create(struct gb_interface *intf) { struct gb_control *control; @@ -221,6 +235,8 @@ struct gb_control *gb_control_create(struct gb_interface *intf) if (!control) return NULL; + control->intf = intf; + control->connection = gb_connection_create_control(intf); if (IS_ERR(control->connection)) { dev_err(&intf->dev, @@ -230,6 +246,13 @@ struct gb_control *gb_control_create(struct gb_interface *intf) return NULL; } + control->dev.parent = &intf->dev; + control->dev.bus = &greybus_bus_type; + control->dev.type = &greybus_control_type; + control->dev.dma_mask = intf->dev.dma_mask; + device_initialize(&control->dev); + dev_set_name(&control->dev, "%s.ctrl", dev_name(&intf->dev)); + gb_connection_set_data(control->connection, control); return control; @@ -271,8 +294,7 @@ void gb_control_disable(struct gb_control *control) gb_connection_disable(control->connection); } -void gb_control_destroy(struct gb_control *control) +void gb_control_put(struct gb_control *control) { - gb_connection_destroy(control->connection); - kfree(control); + put_device(&control->dev); } diff --git a/drivers/staging/greybus/control.h b/drivers/staging/greybus/control.h index 949f1a3..697f901 100644 --- a/drivers/staging/greybus/control.h +++ b/drivers/staging/greybus/control.h @@ -11,18 +11,22 @@ #define __CONTROL_H struct gb_control { - struct gb_connection *connection; + struct device dev; + struct gb_interface *intf; + + struct gb_connection *connection; u8 protocol_major; u8 protocol_minor; bool has_bundle_version; }; +#define to_gb_control(d) container_of(d, struct gb_control, dev) struct gb_control *gb_control_create(struct gb_interface *intf); int gb_control_enable(struct gb_control *control); void gb_control_disable(struct gb_control *control); -void gb_control_destroy(struct gb_control *control); +void gb_control_put(struct gb_control *control); int gb_control_get_bundle_versions(struct gb_control *control); int gb_control_connected_operation(struct gb_control *control, u16 cport_id); diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index d868066..9f143e5 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -86,6 +86,7 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) { struct gb_host_device *hd; struct gb_interface *intf = NULL; + struct gb_control *control = NULL; struct gb_bundle *bundle = NULL; struct gb_svc *svc = NULL; @@ -94,6 +95,10 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) } else if (is_gb_interface(dev)) { intf = to_gb_interface(dev); hd = intf->hd; + } else if (is_gb_control(dev)) { + control = to_gb_control(dev); + intf = control->intf; + hd = intf->hd; } else if (is_gb_bundle(dev)) { bundle = to_gb_bundle(dev); intf = bundle->intf; diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 2fc79fa..4ab5f60 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -113,6 +113,7 @@ extern struct bus_type greybus_bus_type; extern struct device_type greybus_hd_type; extern struct device_type greybus_interface_type; +extern struct device_type greybus_control_type; extern struct device_type greybus_bundle_type; extern struct device_type greybus_svc_type; @@ -126,6 +127,11 @@ static inline int is_gb_interface(const struct device *dev) return dev->type == &greybus_interface_type; } +static inline int is_gb_control(const struct device *dev) +{ + return dev->type == &greybus_control_type; +} + static inline int is_gb_bundle(const struct device *dev) { return dev->type == &greybus_bundle_type; diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index a4bee41f..56a3207 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -360,7 +360,7 @@ static void gb_interface_release(struct device *dev) kfree(intf->vendor_string); if (intf->control) - gb_control_destroy(intf->control); + gb_control_put(intf->control); kfree(intf); } -- cgit v0.10.2 From 7326e07b588cace823a36d4a563838b051b8b8a5 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 13 Apr 2016 19:19:03 +0200 Subject: greybus: interface: register control device at hotplug Make sure to register also the control device along with any bundles when registering an interface. Note that we currently ignore failures to register the control device just as we do for bundle devices. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index c303bb2..6063619 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -294,6 +294,27 @@ void gb_control_disable(struct gb_control *control) gb_connection_disable(control->connection); } +int gb_control_add(struct gb_control *control) +{ + int ret; + + ret = device_add(&control->dev); + if (ret) { + dev_err(&control->dev, + "failed to register control device: %d\n", + ret); + return ret; + } + + return 0; +} + +void gb_control_del(struct gb_control *control) +{ + if (device_is_registered(&control->dev)) + device_del(&control->dev); +} + void gb_control_put(struct gb_control *control) { put_device(&control->dev); diff --git a/drivers/staging/greybus/control.h b/drivers/staging/greybus/control.h index 697f901..102e937 100644 --- a/drivers/staging/greybus/control.h +++ b/drivers/staging/greybus/control.h @@ -26,6 +26,8 @@ struct gb_control { struct gb_control *gb_control_create(struct gb_interface *intf); int gb_control_enable(struct gb_control *control); void gb_control_disable(struct gb_control *control); +int gb_control_add(struct gb_control *control); +void gb_control_del(struct gb_control *control); void gb_control_put(struct gb_control *control); int gb_control_get_bundle_versions(struct gb_control *control); diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 56a3207..e0e0873 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -537,6 +537,7 @@ void gb_interface_disable(struct gb_interface *intf) list_for_each_entry_safe(bundle, next, &intf->bundles, links) gb_bundle_destroy(bundle); + gb_control_del(intf->control); gb_control_disable(intf->control); } @@ -557,6 +558,9 @@ int gb_interface_add(struct gb_interface *intf) dev_info(&intf->dev, "DDBL1 Manufacturer=0x%08x, Product=0x%08x\n", intf->ddbl1_manufacturer_id, intf->ddbl1_product_id); + /* NOTE: ignoring errors for now */ + gb_control_add(intf->control); + list_for_each_entry_safe_reverse(bundle, tmp, &intf->bundles, links) { ret = gb_bundle_add(bundle); if (ret) { -- cgit v0.10.2 From 7c8eb12dbb4c1b43ce705a8ba1a5c9c1191e75d8 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 13 Apr 2016 19:19:04 +0200 Subject: greybus: interface: move vendor and product strings to control device The control device is an abstraction of the control connection over which a greybus manifest is retrieved. As interfaces switch modes (e.g. after boot-over-unipro) they expose new manifests, which can contain different vendor and product strings. Eventually control devices will be deregistered and recreated after an interface mode switch, while the interface itself remains registered. Note that only interfaces of type greybus will have control devices. Specifically, dummy interfaces will not. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index d8bf30e..4831efb 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -52,13 +52,6 @@ Contact: Greg Kroah-Hartman <greg@kroah.com> Description: Product ID of a Greybus interface. -What: /sys/bus/greybus/device/N-I/product_string -Date: October 2015 -KernelVersion: 4.XX -Contact: Greg Kroah-Hartman <greg@kroah.com> -Description: - Product ID string of a Greybus interface. - What: /sys/bus/greybus/device/N-I/vendor_id Date: October 2015 KernelVersion: 4.XX @@ -66,13 +59,6 @@ Contact: Greg Kroah-Hartman <greg@kroah.com> Description: Vendor ID of a Greybus interface. -What: /sys/bus/greybus/device/N-I/vendor_string -Date: October 2015 -KernelVersion: 4.XX -Contact: Greg Kroah-Hartman <greg@kroah.com> -Description: - Vendor ID string of a Greybus interface block. - What: /sys/bus/greybus/device/N-I/version Date: October 2015 KernelVersion: 4.XX @@ -110,6 +96,20 @@ Description: A bundle B on the Interface I, B is replaced by a 1-byte number representing the bundle. +What: /sys/bus/greybus/device/N-I.ctrl/product_string +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman <greg@kroah.com> +Description: + Product ID string of a Greybus interface. + +What: /sys/bus/greybus/device/N-I.ctrl/vendor_string +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman <greg@kroah.com> +Description: + Vendor ID string of a Greybus interface. + What: /sys/bus/greybus/device/N-I.B/bundle_class Date: October 2015 KernelVersion: 4.XX diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index 6063619..58a3d60 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -213,12 +213,40 @@ int gb_control_timesync_authoritative(struct gb_control *control, NULL, 0); } +static ssize_t vendor_string_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_control *control = to_gb_control(dev); + + return scnprintf(buf, PAGE_SIZE, "%s\n", control->vendor_string); +} +static DEVICE_ATTR_RO(vendor_string); + +static ssize_t product_string_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_control *control = to_gb_control(dev); + + return scnprintf(buf, PAGE_SIZE, "%s\n", control->product_string); +} +static DEVICE_ATTR_RO(product_string); + +static struct attribute *control_attrs[] = { + &dev_attr_vendor_string.attr, + &dev_attr_product_string.attr, + NULL, +}; +ATTRIBUTE_GROUPS(control); + static void gb_control_release(struct device *dev) { struct gb_control *control = to_gb_control(dev); gb_connection_destroy(control->connection); + kfree(control->vendor_string); + kfree(control->product_string); + kfree(control); } @@ -249,6 +277,7 @@ struct gb_control *gb_control_create(struct gb_interface *intf) control->dev.parent = &intf->dev; control->dev.bus = &greybus_bus_type; control->dev.type = &greybus_control_type; + control->dev.groups = control_groups; control->dev.dma_mask = intf->dev.dma_mask; device_initialize(&control->dev); dev_set_name(&control->dev, "%s.ctrl", dev_name(&intf->dev)); diff --git a/drivers/staging/greybus/control.h b/drivers/staging/greybus/control.h index 102e937..56fa259 100644 --- a/drivers/staging/greybus/control.h +++ b/drivers/staging/greybus/control.h @@ -20,6 +20,9 @@ struct gb_control { u8 protocol_minor; bool has_bundle_version; + + char *vendor_string; + char *product_string; }; #define to_gb_control(d) container_of(d, struct gb_control, dev) diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index e0e0873..ed56f2d 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -249,8 +249,6 @@ gb_interface_attr(ddbl1_product_id, "0x%08x"); gb_interface_attr(interface_id, "%u"); gb_interface_attr(vendor_id, "0x%08x"); gb_interface_attr(product_id, "0x%08x"); -gb_interface_attr(vendor_string, "%s"); -gb_interface_attr(product_string, "%s"); gb_interface_attr(serial_number, "0x%016llx"); static ssize_t version_show(struct device *dev, struct device_attribute *attr, @@ -326,8 +324,6 @@ static struct attribute *interface_attrs[] = { &dev_attr_interface_id.attr, &dev_attr_vendor_id.attr, &dev_attr_product_id.attr, - &dev_attr_vendor_string.attr, - &dev_attr_product_string.attr, &dev_attr_serial_number.attr, &dev_attr_version.attr, &dev_attr_voltage_now.attr, @@ -356,9 +352,6 @@ static void gb_interface_release(struct device *dev) { struct gb_interface *intf = to_gb_interface(dev); - kfree(intf->product_string); - kfree(intf->vendor_string); - if (intf->control) gb_control_put(intf->control); diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 15c687f..567b6c8 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -25,10 +25,6 @@ struct gb_interface { u8 interface_id; /* Physical location within the Endo */ u8 device_id; - /* Information taken from the manifest descriptor */ - char *vendor_string; - char *product_string; - u32 ddbl1_manufacturer_id; u32 ddbl1_product_id; u32 vendor_id; diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index cca4592..886c5fb 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -384,18 +384,19 @@ static bool gb_manifest_parse_interface(struct gb_interface *intf, struct manifest_desc *interface_desc) { struct greybus_descriptor_interface *desc_intf = interface_desc->data; + struct gb_control *control = intf->control; char *str; /* Handle the strings first--they can fail */ str = gb_string_get(intf, desc_intf->vendor_stringid); if (IS_ERR(str)) return false; - intf->vendor_string = str; + control->vendor_string = str; str = gb_string_get(intf, desc_intf->product_stringid); if (IS_ERR(str)) goto out_free_vendor_string; - intf->product_string = str; + control->product_string = str; /* Release the interface descriptor, now that we're done with it */ release_manifest_descriptor(interface_desc); @@ -408,11 +409,11 @@ static bool gb_manifest_parse_interface(struct gb_interface *intf, return true; out_err: - kfree(intf->product_string); - intf->product_string = NULL; + kfree(control->product_string); + control->product_string = NULL; out_free_vendor_string: - kfree(intf->vendor_string); - intf->vendor_string = NULL; + kfree(control->vendor_string); + control->vendor_string = NULL; return false; } -- cgit v0.10.2 From b6147e4fb13e926878dbef9adae429faf8d8c2dd Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 13 Apr 2016 19:19:05 +0200 Subject: greybus: control: return error pointer when failing to create control device Return an error pointer when failing to create a control device. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index 58a3d60..20aa366 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -257,23 +257,26 @@ struct device_type greybus_control_type = { struct gb_control *gb_control_create(struct gb_interface *intf) { + struct gb_connection *connection; struct gb_control *control; control = kzalloc(sizeof(*control), GFP_KERNEL); if (!control) - return NULL; + return ERR_PTR(-ENOMEM); control->intf = intf; - control->connection = gb_connection_create_control(intf); - if (IS_ERR(control->connection)) { + connection = gb_connection_create_control(intf); + if (IS_ERR(connection)) { dev_err(&intf->dev, "failed to create control connection: %ld\n", - PTR_ERR(control->connection)); + PTR_ERR(connection)); kfree(control); - return NULL; + return ERR_CAST(connection); } + control->connection = connection; + control->dev.parent = &intf->dev; control->dev.bus = &greybus_bus_type; control->dev.type = &greybus_control_type; diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index ed56f2d..f627112 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -381,6 +381,7 @@ struct device_type greybus_interface_type = { struct gb_interface *gb_interface_create(struct gb_host_device *hd, u8 interface_id) { + struct gb_control *control; struct gb_interface *intf; intf = kzalloc(sizeof(*intf), GFP_KERNEL); @@ -403,11 +404,12 @@ struct gb_interface *gb_interface_create(struct gb_host_device *hd, device_initialize(&intf->dev); dev_set_name(&intf->dev, "%d-%d", hd->bus_id, interface_id); - intf->control = gb_control_create(intf); - if (!intf->control) { + control = gb_control_create(intf); + if (IS_ERR(control)) { put_device(&intf->dev); return NULL; } + intf->control = control; list_add(&intf->links, &hd->interfaces); -- cgit v0.10.2 From 49605839bcd644016e2ec3b1534104e2cb3ce984 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 13 Apr 2016 19:19:06 +0200 Subject: greybus: interface: reduce control-device lifetime Make the control-device lifetime coincide with when the interface is enabled (enumerated). This is needed to be able register a new control device after a mode switch. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index f627112..5c87fbc 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -352,9 +352,6 @@ static void gb_interface_release(struct device *dev) { struct gb_interface *intf = to_gb_interface(dev); - if (intf->control) - gb_control_put(intf->control); - kfree(intf); } @@ -381,7 +378,6 @@ struct device_type greybus_interface_type = { struct gb_interface *gb_interface_create(struct gb_host_device *hd, u8 interface_id) { - struct gb_control *control; struct gb_interface *intf; intf = kzalloc(sizeof(*intf), GFP_KERNEL); @@ -404,13 +400,6 @@ struct gb_interface *gb_interface_create(struct gb_host_device *hd, device_initialize(&intf->dev); dev_set_name(&intf->dev, "%d-%d", hd->bus_id, interface_id); - control = gb_control_create(intf); - if (IS_ERR(control)) { - put_device(&intf->dev); - return NULL; - } - intf->control = control; - list_add(&intf->links, &hd->interfaces); return intf; @@ -442,6 +431,7 @@ void gb_interface_deactivate(struct gb_interface *intf) */ int gb_interface_enable(struct gb_interface *intf) { + struct gb_control *control; struct gb_bundle *bundle, *tmp; int ret, size; void *manifest; @@ -453,9 +443,17 @@ int gb_interface_enable(struct gb_interface *intf) } /* Establish control connection */ + control = gb_control_create(intf); + if (IS_ERR(control)) { + dev_err(&intf->dev, "failed to create control device: %lu\n", + PTR_ERR(control)); + return PTR_ERR(control); + } + intf->control = control; + ret = gb_control_enable(intf->control); if (ret) - return ret; + goto err_put_control; /* Get manifest size using control protocol on CPort */ size = gb_control_get_manifest_size_operation(intf); @@ -503,6 +501,8 @@ int gb_interface_enable(struct gb_interface *intf) kfree(manifest); + intf->enabled = true; + return 0; err_destroy_bundles: @@ -512,6 +512,9 @@ err_free_manifest: kfree(manifest); err_disable_control: gb_control_disable(intf->control); +err_put_control: + gb_control_put(intf->control); + intf->control = NULL; return ret; } @@ -522,6 +525,9 @@ void gb_interface_disable(struct gb_interface *intf) struct gb_bundle *bundle; struct gb_bundle *next; + if (!intf->enabled) + return; + /* * Disable the control-connection early to avoid operation timeouts * when the interface is already gone. @@ -534,6 +540,10 @@ void gb_interface_disable(struct gb_interface *intf) gb_control_del(intf->control); gb_control_disable(intf->control); + gb_control_put(intf->control); + intf->control = NULL; + + intf->enabled = false; } /* Register an interface and its bundles. */ diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 567b6c8..63ba696 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -39,6 +39,7 @@ struct gb_interface { unsigned long quirks; bool disconnected; + bool enabled; }; #define to_gb_interface(d) container_of(d, struct gb_interface, dev) -- cgit v0.10.2 From 87a4c819a545e41eacab0de1e250173963dacbf8 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 13 Apr 2016 19:19:07 +0200 Subject: greybus: svc: make sure to deactivate all interfaces on disconnect Make sure to deactivate all interfaces when the svc is going away. This is needed to eventually be able to do controlled teardown of the unipro network. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 5a16ad3..25978e7 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -899,6 +899,7 @@ static void gb_svc_remove_interfaces(struct gb_svc *svc) list_for_each_entry_safe(intf, tmp, &svc->hd->interfaces, links) { gb_interface_disable(intf); + gb_interface_deactivate(intf); gb_interface_remove(intf); } } -- cgit v0.10.2 From 96fb6c340b4abb295ae5c7e904befef33a1d0325 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 13 Apr 2016 19:19:08 +0200 Subject: greybus: svc: keep interfaces registered during mode switch Keep a detected interface registered until it is physically removed. Specifically, do not re-register an interface that is switching mode. Note that this also allows us to get rid of some nasty hacks from core. The Ara VID/PID bootrom hack for ES2 will continue to work, but is now mostly confined to the bootrom driver. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 5c87fbc..89fe901 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -426,8 +426,9 @@ void gb_interface_deactivate(struct gb_interface *intf) } /* - * Enable an interface by enabling its control connection and fetching the - * manifest and other information over it. + * Enable an interface by enabling its control connection, fetching the + * manifest and other information over it, and finally registering its child + * devices. */ int gb_interface_enable(struct gb_interface *intf) { @@ -499,6 +500,19 @@ int gb_interface_enable(struct gb_interface *intf) if (ret) goto err_destroy_bundles; + /* Register the control device and any bundles */ + ret = gb_control_add(intf->control); + if (ret) + goto err_destroy_bundles; + + list_for_each_entry_safe_reverse(bundle, tmp, &intf->bundles, links) { + ret = gb_bundle_add(bundle); + if (ret) { + gb_bundle_destroy(bundle); + continue; + } + } + kfree(manifest); intf->enabled = true; @@ -546,10 +560,9 @@ void gb_interface_disable(struct gb_interface *intf) intf->enabled = false; } -/* Register an interface and its bundles. */ +/* Register an interface. */ int gb_interface_add(struct gb_interface *intf) { - struct gb_bundle *bundle, *tmp; int ret; ret = device_add(&intf->dev); @@ -563,17 +576,6 @@ int gb_interface_add(struct gb_interface *intf) dev_info(&intf->dev, "DDBL1 Manufacturer=0x%08x, Product=0x%08x\n", intf->ddbl1_manufacturer_id, intf->ddbl1_product_id); - /* NOTE: ignoring errors for now */ - gb_control_add(intf->control); - - list_for_each_entry_safe_reverse(bundle, tmp, &intf->bundles, links) { - ret = gb_bundle_add(bundle); - if (ret) { - gb_bundle_destroy(bundle); - continue; - } - } - return 0; } diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 25978e7..a9ef16e 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -452,8 +452,6 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) struct gb_host_device *hd = connection->hd; struct gb_interface *intf; u8 intf_id; - u32 vendor_id = 0; - u32 product_id = 0; int ret; /* The request message size has already been verified. */ @@ -464,27 +462,15 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) intf = gb_interface_find(hd, intf_id); if (intf) { - /* HACK: Save Ara VID/PID for ES2 hack below */ - vendor_id = intf->vendor_id; - product_id = intf->product_id; - - /* - * We have received a hotplug request for an interface that - * already exists. - * - * This can happen in cases like: - * - bootrom loading the firmware image and booting into that, - * which only generates a hotplug event. i.e. no hot-unplug - * event. - * - Or the firmware on the module crashed and sent hotplug - * request again to the SVC, which got propagated to AP. - * - * Remove the interface and add it again, and let user know - * about this with a print message. - */ - dev_info(&svc->dev, "removing interface %u to add it again\n", + dev_info(&svc->dev, "mode switch detected on interface %u\n", intf_id); - gb_svc_intf_remove(svc, intf); + + /* Mark as disconnected to prevent I/O during disable. */ + intf->disconnected = true; + gb_interface_disable(intf); + intf->disconnected = false; + + goto enable_interface; } intf = gb_interface_create(hd, intf_id); @@ -498,19 +484,15 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) if (ret) { dev_err(&svc->dev, "failed to activate interface %u: %d\n", intf_id, ret); - goto err_interface_add; + gb_interface_add(intf); + return; } - /* - * HACK: Use Ara VID/PID from earlier boot stage. - * - * FIXME: remove quirk with ES2 support - */ - if (intf->quirks & GB_INTERFACE_QUIRK_NO_ARA_IDS) { - intf->vendor_id = vendor_id; - intf->product_id = product_id; - } + ret = gb_interface_add(intf); + if (ret) + goto err_interface_deactivate; +enable_interface: ret = gb_interface_enable(intf); if (ret) { dev_err(&svc->dev, "failed to enable interface %u: %d\n", @@ -518,19 +500,10 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) goto err_interface_deactivate; } - ret = gb_interface_add(intf); - if (ret) { - gb_interface_disable(intf); - gb_interface_deactivate(intf); - return; - } - return; err_interface_deactivate: gb_interface_deactivate(intf); -err_interface_add: - gb_interface_add(intf); } static void gb_svc_process_intf_hot_unplug(struct gb_operation *operation) -- cgit v0.10.2 From 41d514020f4844905f349cd51476d03db254317a Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 13 Apr 2016 19:19:09 +0200 Subject: greybus: svc: remove interface-remove helper Remove unnecessary interface-remove helper. Also add comment about why the disconnected flag is set. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index a9ef16e..516a452 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -435,15 +435,6 @@ static int gb_svc_hello(struct gb_operation *op) return 0; } -static void gb_svc_intf_remove(struct gb_svc *svc, struct gb_interface *intf) -{ - intf->disconnected = true; - - gb_interface_disable(intf); - gb_interface_deactivate(intf); - gb_interface_remove(intf); -} - static void gb_svc_process_intf_hotplug(struct gb_operation *operation) { struct gb_svc_intf_hotplug_request *request; @@ -527,7 +518,12 @@ static void gb_svc_process_intf_hot_unplug(struct gb_operation *operation) return; } - gb_svc_intf_remove(svc, intf); + /* Mark as disconnected to prevent I/O during disable. */ + intf->disconnected = true; + + gb_interface_disable(intf); + gb_interface_deactivate(intf); + gb_interface_remove(intf); } static void gb_svc_process_deferred_request(struct work_struct *work) -- cgit v0.10.2 From b4b1b7eda9fe0d5a399d9095b2e8d5657726538c Mon Sep 17 00:00:00 2001 From: Axel Haslam <ahaslam@baylibre.com> Date: Wed, 20 Apr 2016 20:47:20 +0200 Subject: greybus: uart: Update line coding settings only when needed The check for line coding changed should use memcmp and not memcpy. Testing done: trivial Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Axel Haslam <ahaslam@baylibre.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index c580fe0..be71891 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -383,7 +383,7 @@ static void gb_tty_set_termios(struct tty_struct *tty, send_control(gb_tty, newctrl); } - if (memcpy(&gb_tty->line_coding, &newline, sizeof(newline))) { + if (memcmp(&gb_tty->line_coding, &newline, sizeof(newline))) { memcpy(&gb_tty->line_coding, &newline, sizeof(newline)); send_line_coding(gb_tty); } -- cgit v0.10.2 From 05a849191f964cf684777fed9ac471d59f2f18ef Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Mon, 18 Apr 2016 13:11:31 -0700 Subject: greybus: es2: Fix apb_log null pointer exception Read on apb_log causes null pointer exception due to the missing es2 device pointer passing to the debugfs. Testing done: - Enable apb_log and cat it Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 239adf7..9e06efb 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -842,7 +842,7 @@ static void usb_log_enable(struct es2_ap_dev *es2) return; /* XXX We will need to rename this per APB */ es2->apb_log_dentry = debugfs_create_file("apb_log", S_IRUGO, - gb_debugfs_get(), NULL, + gb_debugfs_get(), es2, &apb_log_fops); } -- cgit v0.10.2 From 9504677c9a9ef4123e4bc9fb8f6903b92453ea6f Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Wed, 20 Apr 2016 16:55:08 -0700 Subject: greybus: svc: add AP power measurements debugfs support This change adds the AP Power Monitor functions to read out all the rails power information monitored by the SVC. Testing Done: - $ cat /d/greybus/1-svc/pwrmon/*/* and validate the output with the svc stub power monitor functions - $ tree /d/greybus/1-svc/pwrmon | | | |---pwrmon | | | | |---DUMMY_RAIL_1 | | | | | |---current_now | | | | | |---power_now | | | | | |---voltage_now | | | | |---DUMMY_RAIL_2 | | | | | |---current_now | | | | | |---power_now | | | | | |---voltage_now | | | | |---DUMMY_RAIL_3 | | | | | |---current_now | | | | | |---power_now | | | | | |---voltage_now | | | | |---DUMMY_RAIL_4 | | | | | |---current_now | | | | | |---power_now | | | | | |---voltage_now Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index e0c0493..82798cf 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -967,6 +967,18 @@ struct gb_svc_key_event_request { #define GB_SVC_KEY_PRESSED 0x01 } __packed; +#define GB_SVC_PWRMON_MAX_RAIL_COUNT 254 + +struct gb_svc_pwrmon_rail_count_get_response { + __u8 rail_count; +} __packed; + +#define GB_SVC_PWRMON_RAIL_NAME_BUFSIZE 32 + +struct gb_svc_pwrmon_rail_names_get_response { + __u8 name[0][GB_SVC_PWRMON_RAIL_NAME_BUFSIZE]; +} __packed; + #define GB_SVC_PWRMON_TYPE_CURR 0x01 #define GB_SVC_PWRMON_TYPE_VOL 0x02 #define GB_SVC_PWRMON_TYPE_PWR 0x03 @@ -976,6 +988,16 @@ struct gb_svc_key_event_request { #define GB_SVC_PWRMON_GET_SAMPLE_NOSUPP 0x02 #define GB_SVC_PWRMON_GET_SAMPLE_HWERR 0x03 +struct gb_svc_pwrmon_sample_get_request { + __u8 rail_id; + __u8 measurement_type; +} __packed; + +struct gb_svc_pwrmon_sample_get_response { + __u8 result; + __le32 measurement; +} __packed; + struct gb_svc_pwrmon_intf_sample_get_request { __u8 intf_id; __u8 measurement_type; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 516a452..1791dcc 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -7,6 +7,7 @@ * Released under the GPLv2 only. */ +#include <linux/debugfs.h> #include <linux/input.h> #include <linux/workqueue.h> @@ -99,6 +100,78 @@ static ssize_t watchdog_store(struct device *dev, } static DEVICE_ATTR_RW(watchdog); +static int gb_svc_pwrmon_rail_count_get(struct gb_svc *svc, u8 *value) +{ + struct gb_svc_pwrmon_rail_count_get_response response; + int ret; + + ret = gb_operation_sync(svc->connection, + GB_SVC_TYPE_PWRMON_RAIL_COUNT_GET, NULL, 0, + &response, sizeof(response)); + if (ret) { + dev_err(&svc->dev, "failed to get rail count (%d)\n", ret); + return ret; + } + + *value = response.rail_count; + + return 0; +} + +static int gb_svc_pwrmon_rail_names_get(struct gb_svc *svc, + struct gb_svc_pwrmon_rail_names_get_response *response, + size_t bufsize) +{ + int ret; + + ret = gb_operation_sync(svc->connection, + GB_SVC_TYPE_PWRMON_RAIL_NAMES_GET, NULL, 0, + response, bufsize); + if (ret) { + dev_err(&svc->dev, "failed to get rail names (%d)\n", ret); + return ret; + } + + return 0; +} + +static int gb_svc_pwrmon_sample_get(struct gb_svc *svc, u8 rail_id, + u8 measurement_type, u32 *value) +{ + struct gb_svc_pwrmon_sample_get_request request; + struct gb_svc_pwrmon_sample_get_response response; + int ret; + + request.rail_id = rail_id; + request.measurement_type = measurement_type; + + ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_PWRMON_SAMPLE_GET, + &request, sizeof(request), + &response, sizeof(response)); + if (ret) { + dev_err(&svc->dev, "failed to get rail sample (%d)\n", ret); + return ret; + } + + if (response.result) { + dev_err(&svc->dev, + "UniPro error while getting rail power sample (%d %d): %d\n", + rail_id, measurement_type, response.result); + switch (response.result) { + case GB_SVC_PWRMON_GET_SAMPLE_INVAL: + return -EINVAL; + case GB_SVC_PWRMON_GET_SAMPLE_NOSUPP: + return -ENOSYS; + default: + return -EIO; + } + } + + *value = le32_to_cpu(response.measurement); + + return 0; +} + int gb_svc_pwrmon_intf_sample_get(struct gb_svc *svc, u8 intf_id, u8 measurement_type, u32 *value) { @@ -393,6 +466,161 @@ static int gb_svc_version_request(struct gb_operation *op) return 0; } +static ssize_t pwr_debugfs_voltage_read(struct file *file, char __user *buf, + size_t len, loff_t *offset) +{ + struct svc_debugfs_pwrmon_rail *pwrmon_rails = file->f_inode->i_private; + struct gb_svc *svc = pwrmon_rails->svc; + int ret, desc; + u32 value; + char buff[16]; + + ret = gb_svc_pwrmon_sample_get(svc, pwrmon_rails->id, + GB_SVC_PWRMON_TYPE_VOL, &value); + if (ret) { + dev_err(&svc->dev, + "failed to get voltage sample ret=%d id=%d\n", + ret, pwrmon_rails->id); + return ret; + } + + desc = scnprintf(buff, sizeof(buff), "%u\n", value); + + return simple_read_from_buffer(buf, len, offset, buff, desc); +} + +static ssize_t pwr_debugfs_current_read(struct file *file, char __user *buf, + size_t len, loff_t *offset) +{ + struct svc_debugfs_pwrmon_rail *pwrmon_rails = file->f_inode->i_private; + struct gb_svc *svc = pwrmon_rails->svc; + int ret, desc; + u32 value; + char buff[16]; + + ret = gb_svc_pwrmon_sample_get(svc, pwrmon_rails->id, + GB_SVC_PWRMON_TYPE_CURR, &value); + if (ret) { + dev_err(&svc->dev, + "failed to get current sample ret=%d id=%d\n", + ret, pwrmon_rails->id); + return ret; + } + + desc = scnprintf(buff, sizeof(buff), "%u\n", value); + + return simple_read_from_buffer(buf, len, offset, buff, desc); +} + +static ssize_t pwr_debugfs_power_read(struct file *file, char __user *buf, + size_t len, loff_t *offset) +{ + struct svc_debugfs_pwrmon_rail *pwrmon_rails = file->f_inode->i_private; + struct gb_svc *svc = pwrmon_rails->svc; + int ret, desc; + u32 value; + char buff[16]; + + ret = gb_svc_pwrmon_sample_get(svc, pwrmon_rails->id, + GB_SVC_PWRMON_TYPE_PWR, &value); + if (ret) { + dev_err(&svc->dev, "failed to get power sample ret=%d id=%d\n", + ret, pwrmon_rails->id); + return ret; + } + + desc = scnprintf(buff, sizeof(buff), "%u\n", value); + + return simple_read_from_buffer(buf, len, offset, buff, desc); +} + +static const struct file_operations pwrmon_debugfs_voltage_fops = { + .read = pwr_debugfs_voltage_read, +}; + +static const struct file_operations pwrmon_debugfs_current_fops = { + .read = pwr_debugfs_current_read, +}; + +static const struct file_operations pwrmon_debugfs_power_fops = { + .read = pwr_debugfs_power_read, +}; + +static void svc_pwrmon_debugfs_init(struct gb_svc *svc) +{ + int i; + size_t bufsize; + struct dentry *dent; + + dent = debugfs_create_dir("pwrmon", svc->debugfs_dentry); + if (IS_ERR_OR_NULL(dent)) + return; + + if (gb_svc_pwrmon_rail_count_get(svc, &svc->rail_count)) + goto err_pwrmon_debugfs; + + if (!svc->rail_count || svc->rail_count > GB_SVC_PWRMON_MAX_RAIL_COUNT) + goto err_pwrmon_debugfs; + + bufsize = GB_SVC_PWRMON_RAIL_NAME_BUFSIZE * svc->rail_count; + + svc->rail_names = kzalloc(bufsize, GFP_KERNEL); + if (!svc->rail_names) + goto err_pwrmon_debugfs; + + svc->pwrmon_rails = kcalloc(svc->rail_count, sizeof(*svc->pwrmon_rails), + GFP_KERNEL); + if (!svc->pwrmon_rails) + goto err_pwrmon_debugfs_free; + + if (gb_svc_pwrmon_rail_names_get(svc, svc->rail_names, bufsize)) + goto err_pwrmon_debugfs_free; + + for (i = 0; i < svc->rail_count; i++) { + struct dentry *dir; + struct svc_debugfs_pwrmon_rail *rail = &svc->pwrmon_rails[i]; + char fname[GB_SVC_PWRMON_RAIL_NAME_BUFSIZE]; + + snprintf(fname, sizeof(fname), "%s", + (char *)&svc->rail_names->name[i]); + + rail->id = i; + rail->svc = svc; + + dir = debugfs_create_dir(fname, dent); + debugfs_create_file("voltage_now", S_IRUGO, dir, rail, + &pwrmon_debugfs_voltage_fops); + debugfs_create_file("current_now", S_IRUGO, dir, rail, + &pwrmon_debugfs_current_fops); + debugfs_create_file("power_now", S_IRUGO, dir, rail, + &pwrmon_debugfs_power_fops); + }; + return; + +err_pwrmon_debugfs_free: + kfree(svc->rail_names); + svc->rail_names = NULL; + + kfree(svc->pwrmon_rails); + svc->pwrmon_rails = NULL; + +err_pwrmon_debugfs: + debugfs_remove(dent); +} + +static void svc_debugfs_init(struct gb_svc *svc) +{ + svc->debugfs_dentry = debugfs_create_dir(dev_name(&svc->dev), + gb_debugfs_get()); + svc_pwrmon_debugfs_init(svc); +} + +static void svc_debugfs_exit(struct gb_svc *svc) +{ + debugfs_remove_recursive(svc->debugfs_dentry); + kfree(svc->rail_names); +} + static int gb_svc_hello(struct gb_operation *op) { struct gb_connection *connection = op->connection; @@ -432,6 +660,8 @@ static int gb_svc_hello(struct gb_operation *op) return ret; } + svc_debugfs_init(svc); + return 0; } @@ -882,6 +1112,7 @@ void gb_svc_del(struct gb_svc *svc) * from the request handler. */ if (device_is_registered(&svc->dev)) { + svc_debugfs_exit(svc); gb_svc_watchdog_destroy(svc); input_unregister_device(svc->input); device_del(&svc->dev); diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index 08f8e37..72bc716 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -22,6 +22,11 @@ enum gb_svc_state { struct gb_svc_watchdog; +struct svc_debugfs_pwrmon_rail { + u8 id; + struct gb_svc *svc; +}; + struct gb_svc { struct device dev; @@ -40,6 +45,11 @@ struct gb_svc { struct input_dev *input; char *input_phys; struct gb_svc_watchdog *watchdog; + + struct dentry *debugfs_dentry; + struct svc_debugfs_pwrmon_rail *pwrmon_rails; + struct gb_svc_pwrmon_rail_names_get_response *rail_names; + u8 rail_count; }; #define to_gb_svc(d) container_of(d, struct gb_svc, dev) -- cgit v0.10.2 From 698bdcbf87f3c8a2f998058d58f4baa8ab8e192a Mon Sep 17 00:00:00 2001 From: Evgeniy Borisov <borisov_evgeniy@projectara.com> Date: Mon, 18 Apr 2016 16:27:36 +0300 Subject: greybus: camera-gb: Remove hardcode for CSI TX number of lanes The number of CSI TX lanes is hardcoded to 4. Removing this and start using value from configure stream response. NOTE: The patch depends on the CSI init change: "Use GB CSI params to init camera sub-devs" Signed-off-by: Evgeniy Borisov <eborisov@mm-sol.com> Reviewed-by: Gjorgji Rosikopulos <grosikopulos@mm-sol.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index d3ee5b7..956fbf0 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -304,7 +304,7 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, if (nstreams) { csi_cfg.csi_id = 1; csi_cfg.flags = 0; - csi_cfg.num_lanes = 4; + csi_cfg.num_lanes = resp->num_lanes; csi_cfg.bus_freq = cpu_to_le32(960000000); csi_cfg.lines_per_second = resp->lines_per_second; ret = gb_hd_output(gcam->connection->hd, &csi_cfg, -- cgit v0.10.2 From de86e251f87fbc22efc935911f570c97f9b95cac Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 21 Apr 2016 08:13:01 +0530 Subject: greybus: bootrom: fix typo s/Firware/Firmware Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/bootrom.c b/drivers/staging/greybus/bootrom.c index 3cbe9fe..cf750be 100644 --- a/drivers/staging/greybus/bootrom.c +++ b/drivers/staging/greybus/bootrom.c @@ -101,7 +101,7 @@ static int download_firmware(struct gb_bootrom *bootrom, u8 stage) &connection->bundle->dev); if (rc) dev_err(&connection->bundle->dev, - "Firware request for %s has failed : %d", + "Firmware request for %s has failed : %d", firmware_name, rc); return rc; } -- cgit v0.10.2 From 36460e8a895d1f7209c5a0d7c6a87b2ecc68cc4c Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 21 Apr 2016 08:11:57 +0530 Subject: greybus: audio-codec: Staticize few routines to fix build warnings This fixes below warnings .. greybus/audio_codec.c:20:32: warning: symbol 'find_data' was not declared. Should it be static? greybus/audio_codec.c:955:6: warning: symbol 'gbaudio_codec_cleanup' was not declared. Should it be static? Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 2c6142d..ba3bd36 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -17,8 +17,8 @@ static struct gbaudio_codec_info *gbcodec; -struct gbaudio_data_connection *find_data(struct gbaudio_module_info *module, - const char *name) +static struct gbaudio_data_connection * +find_data(struct gbaudio_module_info *module, const char *name) { struct gbaudio_data_connection *data; @@ -952,7 +952,7 @@ int gbaudio_register_module(struct gbaudio_module_info *module) } EXPORT_SYMBOL(gbaudio_register_module); -void gbaudio_codec_cleanup(struct gbaudio_module_info *module) +static void gbaudio_codec_cleanup(struct gbaudio_module_info *module) { struct gbaudio_data_connection *data; int pb_state = gbcodec->stream[0].state; -- cgit v0.10.2 From a0f997bd5db42eb21d42f04d10cbe03f3fc4fa91 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 21 Apr 2016 11:31:13 +0530 Subject: greybus: es2: Allow proper release of greybus host device The usb core disables the Interface prior to calling ->disconnect() for the usb driver. That disallows the es2 driver to remove the greybus host device and every entity below it in a clean way, as the greybus core may want to do few operations over the usb connection before getting removed. And so we see bunch of errors while we remove the es2 module, like: "urb cport in error -108 (dropped)" The usb core has a special per-driver flag, 'soft_unbind', for such usb drivers. If this flag is set by a driver, the usb core doesn't disable the Interface prior to calling ->disconnect(). Set that flag for es2. Tested by removing the gb-es2.ko module on both EVT1.5 and qemu with gbsim. The interface isn't disabled by the core and the driver is still able initiate greybus operations over the Interface. This can be properly tested only after the next patch which removes the greybus host device before disabling the urbs. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 9e06efb..0cc9fe6 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -1083,6 +1083,7 @@ static struct usb_driver es2_ap_driver = { .probe = ap_probe, .disconnect = ap_disconnect, .id_table = id_table, + .soft_unbind = 1, }; module_usb_driver(es2_ap_driver); -- cgit v0.10.2 From ecdd3a2d59321ebd46c595dbadf24f50364a052a Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 21 Apr 2016 11:31:14 +0530 Subject: greybus: es2: disable cport-in after remove greybus host device This allows greybus to do operations before being removed. Tested by removing the gb-es2.ko module on both EVT1.5 and qemu with gbsim. The driver removes the greybus host device successfully before disabling the urbs. The errors are still coming ("urb cport in error -2 (dropped)"), but with an error value -2 (ENOENT) instead of -108. And that happens while the urbs are disabled, not while doing greybus operations. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Acked-by: David Lin <dtwlin@google.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 0cc9fe6..8138bc2 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -695,11 +695,11 @@ static void ap_disconnect(struct usb_interface *interface) struct es2_ap_dev *es2 = usb_get_intfdata(interface); int i; + gb_hd_del(es2->hd); + for (i = 0; i < NUM_BULKS; ++i) es2_cport_in_disable(es2, &es2->cport_in[i]); - gb_hd_del(es2->hd); - es2_destroy(es2); } -- cgit v0.10.2 From 62de6e0a7262edebc4debd99585b19dc10d2741d Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 21 Apr 2016 11:31:15 +0530 Subject: greybus: es2: don't protest when getting -ENOENT/ESHUTDOWN USB errors -ENOENT or -ESHUTDOWN happens when the urbs are being killed from ->disconnect() callback. Don't complain to userspace about this, as the user will see this on es2 module removal. Tested by removing the gb-es2.ko module on both EVT1.5 and qemu with gbsim. The driver doesn't throw anymore errors like: "urb cport in error -2 (dropped)". Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Tested-by: David Lin <dtwlin@google.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 8138bc2..0a29708 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -715,6 +715,11 @@ static void cport_in_callback(struct urb *urb) if (status) { if ((status == -EAGAIN) || (status == -EPROTO)) goto exit; + + /* The urb is being unlinked */ + if (status == -ENOENT || status == -ESHUTDOWN) + return; + dev_err(dev, "urb cport in error %d (dropped)\n", status); return; } -- cgit v0.10.2 From 2437f1c6b582d1d676c08b6069859c11266c69da Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 21 Apr 2016 11:31:16 +0530 Subject: greybus: es2: move ap_disconnect() below ap_probe() This makes it more readable, as the functions are present in this order in the structure as well. Also keeping these two makes more sense. Tested by removing the gb-es2.ko module on both EVT1.5 and qemu with gbsim. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 0a29708..1cef13d 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -690,19 +690,6 @@ static void es2_destroy(struct es2_ap_dev *es2) usb_put_dev(udev); } -static void ap_disconnect(struct usb_interface *interface) -{ - struct es2_ap_dev *es2 = usb_get_intfdata(interface); - int i; - - gb_hd_del(es2->hd); - - for (i = 0; i < NUM_BULKS; ++i) - es2_cport_in_disable(es2, &es2->cport_in[i]); - - es2_destroy(es2); -} - static void cport_in_callback(struct urb *urb) { struct gb_host_device *hd = urb->context; @@ -1083,6 +1070,19 @@ error: return retval; } +static void ap_disconnect(struct usb_interface *interface) +{ + struct es2_ap_dev *es2 = usb_get_intfdata(interface); + int i; + + gb_hd_del(es2->hd); + + for (i = 0; i < NUM_BULKS; ++i) + es2_cport_in_disable(es2, &es2->cport_in[i]); + + es2_destroy(es2); +} + static struct usb_driver es2_ap_driver = { .name = "es2_ap_driver", .probe = ap_probe, -- cgit v0.10.2 From 89f2df438b20f2176fcc8fc92201a708f0d3659b Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Thu, 21 Apr 2016 11:43:36 +0200 Subject: greybus: svc: keep error messages uniform All SVC error messages, except for a few recently added ones, place the errno last after a colon (:). Let's at least try to be consistent within the svc code. Note that this format also allows for more concise messages without risk for ambiguity. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 1791dcc..ff89da6 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -109,7 +109,7 @@ static int gb_svc_pwrmon_rail_count_get(struct gb_svc *svc, u8 *value) GB_SVC_TYPE_PWRMON_RAIL_COUNT_GET, NULL, 0, &response, sizeof(response)); if (ret) { - dev_err(&svc->dev, "failed to get rail count (%d)\n", ret); + dev_err(&svc->dev, "failed to get rail count: %d\n", ret); return ret; } @@ -128,7 +128,7 @@ static int gb_svc_pwrmon_rail_names_get(struct gb_svc *svc, GB_SVC_TYPE_PWRMON_RAIL_NAMES_GET, NULL, 0, response, bufsize); if (ret) { - dev_err(&svc->dev, "failed to get rail names (%d)\n", ret); + dev_err(&svc->dev, "failed to get rail names: %d\n", ret); return ret; } @@ -149,7 +149,7 @@ static int gb_svc_pwrmon_sample_get(struct gb_svc *svc, u8 rail_id, &request, sizeof(request), &response, sizeof(response)); if (ret) { - dev_err(&svc->dev, "failed to get rail sample (%d)\n", ret); + dev_err(&svc->dev, "failed to get rail sample: %d\n", ret); return ret; } @@ -187,7 +187,7 @@ int gb_svc_pwrmon_intf_sample_get(struct gb_svc *svc, u8 intf_id, &request, sizeof(request), &response, sizeof(response)); if (ret) { - dev_err(&svc->dev, "failed to get intf sample (%d)\n", ret); + dev_err(&svc->dev, "failed to get intf sample: %d\n", ret); return ret; } @@ -479,8 +479,8 @@ static ssize_t pwr_debugfs_voltage_read(struct file *file, char __user *buf, GB_SVC_PWRMON_TYPE_VOL, &value); if (ret) { dev_err(&svc->dev, - "failed to get voltage sample ret=%d id=%d\n", - ret, pwrmon_rails->id); + "failed to get voltage sample %u: %d\n", + pwrmon_rails->id, ret); return ret; } @@ -502,8 +502,8 @@ static ssize_t pwr_debugfs_current_read(struct file *file, char __user *buf, GB_SVC_PWRMON_TYPE_CURR, &value); if (ret) { dev_err(&svc->dev, - "failed to get current sample ret=%d id=%d\n", - ret, pwrmon_rails->id); + "failed to get current sample %u: %d\n", + pwrmon_rails->id, ret); return ret; } @@ -524,8 +524,8 @@ static ssize_t pwr_debugfs_power_read(struct file *file, char __user *buf, ret = gb_svc_pwrmon_sample_get(svc, pwrmon_rails->id, GB_SVC_PWRMON_TYPE_PWR, &value); if (ret) { - dev_err(&svc->dev, "failed to get power sample ret=%d id=%d\n", - ret, pwrmon_rails->id); + dev_err(&svc->dev, "failed to get power sample %u: %d\n", + pwrmon_rails->id, ret); return ret; } -- cgit v0.10.2 From 5b35ef95ef9b71406db3fe860b8ce8206b6576c7 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Thu, 21 Apr 2016 11:43:37 +0200 Subject: greybus: svc: fix pwrmon return value Errno -ENOSYS is reserved for missing syscalls, replace it with ENOMSG. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index ff89da6..1cf60898 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -161,7 +161,7 @@ static int gb_svc_pwrmon_sample_get(struct gb_svc *svc, u8 rail_id, case GB_SVC_PWRMON_GET_SAMPLE_INVAL: return -EINVAL; case GB_SVC_PWRMON_GET_SAMPLE_NOSUPP: - return -ENOSYS; + return -ENOMSG; default: return -EIO; } -- cgit v0.10.2 From f35fdb2fbdc9435b723775b6aa561590413131c6 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Thu, 21 Apr 2016 11:43:38 +0200 Subject: greybus: svc: fix function-parameter indentation We really shouldn't be passing response structures around this way, but since we now are, let's at least make sure not to break the 80 col limit. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 1cf60898..d285361 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -119,8 +119,8 @@ static int gb_svc_pwrmon_rail_count_get(struct gb_svc *svc, u8 *value) } static int gb_svc_pwrmon_rail_names_get(struct gb_svc *svc, - struct gb_svc_pwrmon_rail_names_get_response *response, - size_t bufsize) + struct gb_svc_pwrmon_rail_names_get_response *response, + size_t bufsize) { int ret; -- cgit v0.10.2 From f2bf63a365425fa7df56c4e1dbe5a6bb29680324 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Fri, 22 Apr 2016 11:13:19 -0700 Subject: greybus: audio: acquire wakelock during active playback use pm_stay_awake & pm_relax to avoid suspend sequence during active playback testing Done: Music Playback ongoing $ cat /sys/devices/soc.0/qcom,ara-codec.82/power/wakeup_active 1 Music Playback stopped $ cat /sys/devices/soc.0/qcom,ara-codec.82/power/wakeup_active 0 Tested-by: David Lin <dtwlin@google.com> Reviewed-by: David Lin <dtwlin@google.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Akash Choudhari <akashtc@google.com> Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index ba3bd36..9ed35c4 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -7,6 +7,7 @@ */ #include <linux/kernel.h> #include <linux/module.h> +#include <linux/pm_runtime.h> #include <sound/soc.h> #include <sound/pcm_params.h> #include <uapi/linux/input.h> @@ -388,6 +389,8 @@ static int gbcodec_startup(struct snd_pcm_substream *substream, codec->stream[substream->stream].state = state; codec->stream[substream->stream].dai_name = dai->name; mutex_unlock(&codec->lock); + /* to prevent suspend in case of active audio */ + pm_stay_awake(dai->dev); return ret; } @@ -470,6 +473,7 @@ static void gbcodec_shutdown(struct snd_pcm_substream *substream, codec->stream[substream->stream].state = state; codec->stream[substream->stream].dai_name = NULL; mutex_unlock(&codec->lock); + pm_relax(dai->dev); return; } @@ -1094,7 +1098,7 @@ static int gbcodec_probe(struct snd_soc_codec *codec) snd_soc_codec_set_drvdata(codec, info); gbcodec = info; - /* Empty function for now */ + device_init_wakeup(codec->dev, 1); return 0; } -- cgit v0.10.2 From 7b62b61c752a4700ecf11d63a7ec40aeb3cee66c Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Wed, 20 Apr 2016 11:48:37 +0530 Subject: greybus: arche-ctrl: Don't expose driver internals to arche-platform driver We have chosen the *ugly* way of registering two platform drivers from the module_init() of only one of them, so that we can avoid having two separate modules for them. But we should still be doing this in a sane way. There is no need to expose internals of arche-ctrl to arche-platform, like PM-ops, probe, resume, id-table, etc. Just expose an init and a exit callback. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index 3a092a5..a9d78a8 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -358,7 +358,7 @@ static int apb_ctrl_get_devtree_data(struct platform_device *pdev, return 0; } -int arche_apb_ctrl_probe(struct platform_device *pdev) +static int arche_apb_ctrl_probe(struct platform_device *pdev) { int ret; struct arche_apb_ctrl_drvdata *apb; @@ -393,7 +393,7 @@ int arche_apb_ctrl_probe(struct platform_device *pdev) return 0; } -int arche_apb_ctrl_remove(struct platform_device *pdev) +static int arche_apb_ctrl_remove(struct platform_device *pdev) { device_remove_file(&pdev->dev, &dev_attr_state); poweroff_seq(pdev); @@ -430,6 +430,30 @@ static int arche_apb_ctrl_resume(struct device *dev) return 0; } -SIMPLE_DEV_PM_OPS(arche_apb_ctrl_pm_ops, - arche_apb_ctrl_suspend, - arche_apb_ctrl_resume); +static SIMPLE_DEV_PM_OPS(arche_apb_ctrl_pm_ops, arche_apb_ctrl_suspend, + arche_apb_ctrl_resume); + +static struct of_device_id arche_apb_ctrl_of_match[] = { + { .compatible = "usbffff,2", }, + { }, +}; + +static struct platform_driver arche_apb_ctrl_device_driver = { + .probe = arche_apb_ctrl_probe, + .remove = arche_apb_ctrl_remove, + .driver = { + .name = "arche-apb-ctrl", + .pm = &arche_apb_ctrl_pm_ops, + .of_match_table = arche_apb_ctrl_of_match, + } +}; + +int __init arche_apb_init(void) +{ + return platform_driver_register(&arche_apb_ctrl_device_driver); +} + +void __exit arche_apb_exit(void) +{ + platform_driver_unregister(&arche_apb_ctrl_device_driver); +} diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 3ff4f69..d1083cf 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -580,11 +580,6 @@ static struct of_device_id arche_platform_of_match[] = { { }, }; -static struct of_device_id arche_apb_ctrl_of_match[] = { - { .compatible = "usbffff,2", }, - { }, -}; - static struct of_device_id arche_combined_id[] = { { .compatible = "google,arche-platform", }, /* Use PID/VID of SVC device */ { .compatible = "usbffff,2", }, @@ -602,16 +597,6 @@ static struct platform_driver arche_platform_device_driver = { } }; -static struct platform_driver arche_apb_ctrl_device_driver = { - .probe = arche_apb_ctrl_probe, - .remove = arche_apb_ctrl_remove, - .driver = { - .name = "arche-apb-ctrl", - .pm = &arche_apb_ctrl_pm_ops, - .of_match_table = arche_apb_ctrl_of_match, - } -}; - static int __init arche_init(void) { int retval; @@ -620,7 +605,7 @@ static int __init arche_init(void) if (retval) return retval; - retval = platform_driver_register(&arche_apb_ctrl_device_driver); + retval = arche_apb_init(); if (retval) platform_driver_unregister(&arche_platform_device_driver); @@ -630,7 +615,7 @@ module_init(arche_init); static void __exit arche_exit(void) { - platform_driver_unregister(&arche_apb_ctrl_device_driver); + arche_apb_exit(); platform_driver_unregister(&arche_platform_device_driver); } module_exit(arche_exit); diff --git a/drivers/staging/greybus/arche_platform.h b/drivers/staging/greybus/arche_platform.h index 700c548..69b627b 100644 --- a/drivers/staging/greybus/arche_platform.h +++ b/drivers/staging/greybus/arche_platform.h @@ -18,8 +18,8 @@ enum arche_platform_state { }; -int arche_apb_ctrl_probe(struct platform_device *pdev); -int arche_apb_ctrl_remove(struct platform_device *pdev); +int __init arche_apb_init(void); +void __exit arche_apb_exit(void); /* Operational states for the APB device */ int apb_ctrl_coldboot(struct device *dev); @@ -27,7 +27,4 @@ int apb_ctrl_fw_flashing(struct device *dev); int apb_ctrl_standby_boot(struct device *dev); void apb_ctrl_poweroff(struct device *dev); - -extern const struct dev_pm_ops arche_apb_ctrl_pm_ops; - #endif /* __ARCHE_PLATFORM_H */ -- cgit v0.10.2 From d7ed7cbfe695d0a77613b305bed0483a1c9569ca Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Mon, 25 Apr 2016 17:18:17 +0530 Subject: greybus: audio: acquire wakelock during active playback This change was missed while merging original patch commit-id: 53c765c33f4a69c31027ec012e717d303bd4feca Thus submitting it again. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 9ed35c4..20feea1 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -410,6 +410,7 @@ static void gbcodec_shutdown(struct snd_pcm_substream *substream, if (list_empty(&codec->module_list)) { dev_err(codec->dev, "No codec module available\n"); mutex_unlock(&codec->lock); + pm_relax(dai->dev); return; } -- cgit v0.10.2 From 12185197eac3355c7c7c7bce0e81b0c65baa3010 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Sat, 23 Apr 2016 18:47:20 +0200 Subject: greybus: svc: use a common prefix for debugfs functions Use the common gb_svc functions also for the recently added svc functions. Having a common prefix clearly signals where the code resides, something which improves readability and helps during debugging (e.g. stack traces). Note that all functions in svc.c except for these three use the common prefix with the exception of the pwr_debugfs callbacks (that still use *a* common prefix) and the attribute accessors (than can not have a common prefix due to some macro magic). Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index d285361..f9829f1 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -546,7 +546,7 @@ static const struct file_operations pwrmon_debugfs_power_fops = { .read = pwr_debugfs_power_read, }; -static void svc_pwrmon_debugfs_init(struct gb_svc *svc) +static void gb_svc_pwrmon_debugfs_init(struct gb_svc *svc) { int i; size_t bufsize; @@ -608,14 +608,14 @@ err_pwrmon_debugfs: debugfs_remove(dent); } -static void svc_debugfs_init(struct gb_svc *svc) +static void gb_svc_debugfs_init(struct gb_svc *svc) { svc->debugfs_dentry = debugfs_create_dir(dev_name(&svc->dev), gb_debugfs_get()); - svc_pwrmon_debugfs_init(svc); + gb_svc_pwrmon_debugfs_init(svc); } -static void svc_debugfs_exit(struct gb_svc *svc) +static void gb_svc_debugfs_exit(struct gb_svc *svc) { debugfs_remove_recursive(svc->debugfs_dentry); kfree(svc->rail_names); @@ -660,7 +660,7 @@ static int gb_svc_hello(struct gb_operation *op) return ret; } - svc_debugfs_init(svc); + gb_svc_debugfs_init(svc); return 0; } @@ -1112,7 +1112,7 @@ void gb_svc_del(struct gb_svc *svc) * from the request handler. */ if (device_is_registered(&svc->dev)) { - svc_debugfs_exit(svc); + gb_svc_debugfs_exit(svc); gb_svc_watchdog_destroy(svc); input_unregister_device(svc->input); device_del(&svc->dev); -- cgit v0.10.2 From 4ff80a59ac3bbdacaf93598eed396677f29c4673 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Sat, 23 Apr 2016 18:47:21 +0200 Subject: greybus: Documentation/sysfs: add entry for control device Add an entry for the recently added interface control device. Also move the bundle-device entry below the control-device entries. Reported-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 4831efb..89b15b0 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -88,13 +88,13 @@ Contact: Greg Kroah-Hartman <greg@kroah.com> Description: Power measurement of the interface in microwatts (uW) -What: /sys/bus/greybus/device/N-I.B +What: /sys/bus/greybus/device/N-I.ctrl Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> Description: - A bundle B on the Interface I, B is replaced by a 1-byte - number representing the bundle. + Abstract control device for interface I that represents the + current mode of an enumerated Greybus interface. What: /sys/bus/greybus/device/N-I.ctrl/product_string Date: October 2015 @@ -110,6 +110,14 @@ Contact: Greg Kroah-Hartman <greg@kroah.com> Description: Vendor ID string of a Greybus interface. +What: /sys/bus/greybus/device/N-I.B +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman <greg@kroah.com> +Description: + A bundle B on the Interface I, B is replaced by a 1-byte + number representing the bundle. + What: /sys/bus/greybus/device/N-I.B/bundle_class Date: October 2015 KernelVersion: 4.XX -- cgit v0.10.2 From deba0c03e9c12e2053ad5241c2fd59276439f2cd Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Sat, 23 Apr 2016 18:47:22 +0200 Subject: greybus: Documentation/sysfs: sort entries alphabetically The attribute entries have been kept mostly sorted within each device type. Let's move the three more-recently added interface attributes that were not. Suggested-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 89b15b0..cf6d3ee 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -14,6 +14,13 @@ Description: An Interface I on the bus N, where I is the 1-byte interface ID. +What: /sys/bus/greybus/device/N-I/current_now +Date: March 2016 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman <greg@kroah.com> +Description: + Current measurement of the interface in microamps (uA) + What: /sys/bus/greybus/device/N-I/ddbl1_manufacturer_id Date: October 2015 KernelVersion: 4.XX @@ -37,13 +44,12 @@ Contact: Greg Kroah-Hartman <greg@kroah.com> Description: The ID of a Greybus interface. -What: /sys/bus/greybus/device/N-I/serial_number -Date: October 2015 +What: /sys/bus/greybus/device/N-I/power_now +Date: March 2016 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> Description: - Serial Number of the Greybus interface, represented by a 64 bit - hexadecimal number. + Power measurement of the interface in microwatts (uW) What: /sys/bus/greybus/device/N-I/product_id Date: October 2015 @@ -52,6 +58,14 @@ Contact: Greg Kroah-Hartman <greg@kroah.com> Description: Product ID of a Greybus interface. +What: /sys/bus/greybus/device/N-I/serial_number +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman <greg@kroah.com> +Description: + Serial Number of the Greybus interface, represented by a 64 bit + hexadecimal number. + What: /sys/bus/greybus/device/N-I/vendor_id Date: October 2015 KernelVersion: 4.XX @@ -74,20 +88,6 @@ Contact: Greg Kroah-Hartman <greg@kroah.com> Description: Voltage measurement of the interface in microvolts (uV) -What: /sys/bus/greybus/device/N-I/current_now -Date: March 2016 -KernelVersion: 4.XX -Contact: Greg Kroah-Hartman <greg@kroah.com> -Description: - Current measurement of the interface in microamps (uA) - -What: /sys/bus/greybus/device/N-I/power_now -Date: March 2016 -KernelVersion: 4.XX -Contact: Greg Kroah-Hartman <greg@kroah.com> -Description: - Power measurement of the interface in microwatts (uW) - What: /sys/bus/greybus/device/N-I.ctrl Date: October 2015 KernelVersion: 4.XX -- cgit v0.10.2 From 844fcbfeb6491d95b7e19b4705f9eb576a210536 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Sat, 23 Apr 2016 18:47:23 +0200 Subject: greybus: svc: refactor interface re-enable Add interface re-enable helper that is used during mode switch to disable and re-enable (enumerate) an interface. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index f9829f1..cde59d0 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -665,6 +665,24 @@ static int gb_svc_hello(struct gb_operation *op) return 0; } +static void gb_svc_intf_reenable(struct gb_svc *svc, struct gb_interface *intf) +{ + int ret; + + /* Mark as disconnected to prevent I/O during disable. */ + intf->disconnected = true; + gb_interface_disable(intf); + intf->disconnected = false; + + ret = gb_interface_enable(intf); + if (ret) { + dev_err(&svc->dev, "failed to enable interface %u: %d\n", + intf->interface_id, ret); + + gb_interface_deactivate(intf); + } +} + static void gb_svc_process_intf_hotplug(struct gb_operation *operation) { struct gb_svc_intf_hotplug_request *request; @@ -686,12 +704,7 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) dev_info(&svc->dev, "mode switch detected on interface %u\n", intf_id); - /* Mark as disconnected to prevent I/O during disable. */ - intf->disconnected = true; - gb_interface_disable(intf); - intf->disconnected = false; - - goto enable_interface; + return gb_svc_intf_reenable(svc, intf); } intf = gb_interface_create(hd, intf_id); @@ -713,7 +726,6 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) if (ret) goto err_interface_deactivate; -enable_interface: ret = gb_interface_enable(intf); if (ret) { dev_err(&svc->dev, "failed to enable interface %u: %d\n", -- cgit v0.10.2 From b15d97d77017dc168c74c5e9aacfe14ff74dcbe9 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Sat, 23 Apr 2016 18:47:24 +0200 Subject: greybus: core: add module abstraction Add Greybus module abstraction that will be used to implement controlled module removal (eject) and represent module geometry. Greybus module devices correspond to physical modules and have one or more interfaces. Modules have an id that is identical to the id of their primary interface, which in turn is the interface with lowest numbered id. The module name is constructed from the bus and module id: <bus_id>-<module_id> Interfaces, bundles, and control devices are consequently renamed as <bus_id>-<module_id>.<interface_id> <bus_id>-<module_id>.<interface_id>.<bundle_id> <bus_id>-<module_id>.<interface_id>.ctrl As before, interface ids (and therefore in a sense now also module ids) correspond to physical interface positions on the frame. Modules have the following attributes: module_id num_interfaces where module_id is the id of the module and num_interface the number of interfaces the module has. Note that until SVC module-size detection has been implemented, all interfaces are considered to be part of 1x2 modules. Specifically, the two interfaces of a 2x2 module will be presented as two 1x2 modules for now. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index cf6d3ee..41ffc40 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -6,22 +6,45 @@ Description: The "root" greybus device for the Greybus device tree, or bus, where N is a dynamically assigned 1-based id. -What: /sys/bus/greybus/device/N-I +What: /sys/bus/greybus/device/N-M +Date: March 2016 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman <greg@kroah.com> +Description: + A Module M on the bus N, where M is the 1-byte interface + ID of the module's primary interface. + +What: /sys/bus/greybus/device/N-M/module_id +Date: March 2016 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman <greg@kroah.com> +Description: + The ID of a Greybus module, corresponding to the ID of its + primary interface. + +What: /sys/bus/greybus/device/N-M/num_interfaces +Date: March 2016 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman <greg@kroah.com> +Description: + The number of interfaces of a module. + +What: /sys/bus/greybus/device/N-M.I Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> Description: - An Interface I on the bus N, where I is the 1-byte interface - ID. + An Interface I on the bus N and module N-M, where I is the + 1-byte interface ID. -What: /sys/bus/greybus/device/N-I/current_now +What: /sys/bus/greybus/device/N-M.I/current_now Date: March 2016 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> Description: Current measurement of the interface in microamps (uA) -What: /sys/bus/greybus/device/N-I/ddbl1_manufacturer_id +What: /sys/bus/greybus/device/N-M.I/ddbl1_manufacturer_id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> @@ -29,7 +52,7 @@ Description: Unipro Device Descriptor Block Level 1 manufacturer ID for the greybus Interface. -What: /sys/bus/greybus/device/N-I/ddbl1_product_id +What: /sys/bus/greybus/device/N-M.I/ddbl1_product_id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> @@ -37,28 +60,28 @@ Description: Unipro Device Descriptor Block Level 1 product ID for the greybus Interface. -What: /sys/bus/greybus/device/N-I/interface_id +What: /sys/bus/greybus/device/N-M.I/interface_id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> Description: The ID of a Greybus interface. -What: /sys/bus/greybus/device/N-I/power_now +What: /sys/bus/greybus/device/N-M.I/power_now Date: March 2016 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> Description: Power measurement of the interface in microwatts (uW) -What: /sys/bus/greybus/device/N-I/product_id +What: /sys/bus/greybus/device/N-M.I/product_id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> Description: Product ID of a Greybus interface. -What: /sys/bus/greybus/device/N-I/serial_number +What: /sys/bus/greybus/device/N-M.I/serial_number Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> @@ -66,14 +89,14 @@ Description: Serial Number of the Greybus interface, represented by a 64 bit hexadecimal number. -What: /sys/bus/greybus/device/N-I/vendor_id +What: /sys/bus/greybus/device/N-M.I/vendor_id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> Description: Vendor ID of a Greybus interface. -What: /sys/bus/greybus/device/N-I/version +What: /sys/bus/greybus/device/N-M.I/version Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> @@ -81,14 +104,14 @@ Description: Interface version represented as <16 bit major number>.<16 bit minor number>. -What: /sys/bus/greybus/device/N-I/voltage_now +What: /sys/bus/greybus/device/N-M.I/voltage_now Date: March 2016 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> Description: Voltage measurement of the interface in microvolts (uV) -What: /sys/bus/greybus/device/N-I.ctrl +What: /sys/bus/greybus/device/N-M.I.ctrl Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> @@ -96,21 +119,21 @@ Description: Abstract control device for interface I that represents the current mode of an enumerated Greybus interface. -What: /sys/bus/greybus/device/N-I.ctrl/product_string +What: /sys/bus/greybus/device/N-M.I.ctrl/product_string Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> Description: Product ID string of a Greybus interface. -What: /sys/bus/greybus/device/N-I.ctrl/vendor_string +What: /sys/bus/greybus/device/N-M.I.ctrl/vendor_string Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> Description: Vendor ID string of a Greybus interface. -What: /sys/bus/greybus/device/N-I.B +What: /sys/bus/greybus/device/N-M.I.B Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> @@ -118,21 +141,21 @@ Description: A bundle B on the Interface I, B is replaced by a 1-byte number representing the bundle. -What: /sys/bus/greybus/device/N-I.B/bundle_class +What: /sys/bus/greybus/device/N-M.I.B/bundle_class Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> Description: The greybus class of the bundle B. -What: /sys/bus/greybus/device/N-I.B/bundle_id +What: /sys/bus/greybus/device/N-M.I.B/bundle_id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> Description: The interface-unique id of the bundle B. -What: /sys/bus/greybus/device/N-I.B/state +What: /sys/bus/greybus/device/N-M.I.B/state Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 65259ea..8ec6074 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -2,6 +2,7 @@ greybus-y := core.o \ debugfs.o \ hd.o \ manifest.o \ + module.o \ interface.o \ bundle.o \ connection.o \ diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 9f143e5..70a66e2 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -85,6 +85,7 @@ static int greybus_module_match(struct device *dev, struct device_driver *drv) static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) { struct gb_host_device *hd; + struct gb_module *module = NULL; struct gb_interface *intf = NULL; struct gb_control *control = NULL; struct gb_bundle *bundle = NULL; @@ -92,8 +93,12 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) if (is_gb_host_device(dev)) { hd = to_gb_host_device(dev); + } else if (is_gb_module(dev)) { + module = to_gb_module(dev); + hd = module->hd; } else if (is_gb_interface(dev)) { intf = to_gb_interface(dev); + module = intf->module; hd = intf->hd; } else if (is_gb_control(dev)) { control = to_gb_control(dev); @@ -102,6 +107,7 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) } else if (is_gb_bundle(dev)) { bundle = to_gb_bundle(dev); intf = bundle->intf; + module = intf->module; hd = intf->hd; } else if (is_gb_svc(dev)) { svc = to_gb_svc(dev); @@ -114,6 +120,11 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) if (add_uevent_var(env, "BUS=%u", hd->bus_id)) return -ENOMEM; + if (module) { + if (add_uevent_var(env, "MODULE=%u", module->module_id)) + return -ENOMEM; + } + if (intf) { if (add_uevent_var(env, "INTERFACE=%u", intf->interface_id)) return -ENOMEM; diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 4ab5f60..f5447e7 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -28,6 +28,7 @@ #include "hd.h" #include "svc.h" #include "control.h" +#include "module.h" #include "interface.h" #include "bundle.h" #include "connection.h" @@ -112,6 +113,7 @@ struct dentry *gb_debugfs_get(void); extern struct bus_type greybus_bus_type; extern struct device_type greybus_hd_type; +extern struct device_type greybus_module_type; extern struct device_type greybus_interface_type; extern struct device_type greybus_control_type; extern struct device_type greybus_bundle_type; @@ -122,6 +124,11 @@ static inline int is_gb_host_device(const struct device *dev) return dev->type == &greybus_hd_type; } +static inline int is_gb_module(const struct device *dev) +{ + return dev->type == &greybus_module_type; +} + static inline int is_gb_interface(const struct device *dev) { return dev->type == &greybus_interface_type; diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index 2c13860..762cc03 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -89,7 +89,7 @@ struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, hd->bus_id = ret; hd->driver = driver; - INIT_LIST_HEAD(&hd->interfaces); + INIT_LIST_HEAD(&hd->modules); INIT_LIST_HEAD(&hd->connections); ida_init(&hd->cport_id_map); hd->buffer_size_max = buffer_size_max; diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h index b481dd0..ff71936 100644 --- a/drivers/staging/greybus/hd.h +++ b/drivers/staging/greybus/hd.h @@ -34,7 +34,7 @@ struct gb_host_device { int bus_id; const struct gb_hd_driver *driver; - struct list_head interfaces; + struct list_head modules; struct list_head connections; struct ida cport_id_map; diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 89fe901..d51c563 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -333,21 +333,6 @@ static struct attribute *interface_attrs[] = { }; ATTRIBUTE_GROUPS(interface); - -// FIXME, odds are you don't want to call this function, rework the caller to -// not need it please. -struct gb_interface *gb_interface_find(struct gb_host_device *hd, - u8 interface_id) -{ - struct gb_interface *intf; - - list_for_each_entry(intf, &hd->interfaces, links) - if (intf->interface_id == interface_id) - return intf; - - return NULL; -} - static void gb_interface_release(struct device *dev) { struct gb_interface *intf = to_gb_interface(dev); @@ -371,13 +356,11 @@ struct device_type greybus_interface_type = { * * Returns a pointer to the new interfce or a null pointer if a * failure occurs due to memory exhaustion. - * - * Locking: Caller ensures serialisation with gb_interface_remove and - * gb_interface_find. */ -struct gb_interface *gb_interface_create(struct gb_host_device *hd, +struct gb_interface *gb_interface_create(struct gb_module *module, u8 interface_id) { + struct gb_host_device *hd = module->hd; struct gb_interface *intf; intf = kzalloc(sizeof(*intf), GFP_KERNEL); @@ -385,6 +368,7 @@ struct gb_interface *gb_interface_create(struct gb_host_device *hd, return NULL; intf->hd = hd; /* XXX refcount? */ + intf->module = module; intf->interface_id = interface_id; INIT_LIST_HEAD(&intf->bundles); INIT_LIST_HEAD(&intf->manifest_descs); @@ -392,15 +376,14 @@ struct gb_interface *gb_interface_create(struct gb_host_device *hd, /* Invalid device id to start with */ intf->device_id = GB_INTERFACE_DEVICE_ID_BAD; - intf->dev.parent = &hd->dev; + intf->dev.parent = &module->dev; intf->dev.bus = &greybus_bus_type; intf->dev.type = &greybus_interface_type; intf->dev.groups = interface_groups; - intf->dev.dma_mask = hd->dev.dma_mask; + intf->dev.dma_mask = module->dev.dma_mask; device_initialize(&intf->dev); - dev_set_name(&intf->dev, "%d-%d", hd->bus_id, interface_id); - - list_add(&intf->links, &hd->interfaces); + dev_set_name(&intf->dev, "%s.%u", dev_name(&module->dev), + interface_id); return intf; } @@ -579,15 +562,16 @@ int gb_interface_add(struct gb_interface *intf) return 0; } -/* Deregister an interface and drop its reference. */ -void gb_interface_remove(struct gb_interface *intf) +/* Deregister an interface. */ +void gb_interface_del(struct gb_interface *intf) { if (device_is_registered(&intf->dev)) { device_del(&intf->dev); dev_info(&intf->dev, "Interface removed\n"); } +} - list_del(&intf->links); - +void gb_interface_put(struct gb_interface *intf) +{ put_device(&intf->dev); } diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 63ba696..9185c7f 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -20,7 +20,7 @@ struct gb_interface { struct gb_control *control; struct list_head bundles; - struct list_head links; /* gb_host_device->interfaces */ + struct list_head module_node; struct list_head manifest_descs; u8 interface_id; /* Physical location within the Endo */ u8 device_id; @@ -35,6 +35,7 @@ struct gb_interface { u16 version_minor; struct gb_host_device *hd; + struct gb_module *module; unsigned long quirks; @@ -46,13 +47,14 @@ struct gb_interface { struct gb_interface *gb_interface_find(struct gb_host_device *hd, u8 interface_id); -struct gb_interface *gb_interface_create(struct gb_host_device *hd, +struct gb_interface *gb_interface_create(struct gb_module *module, u8 interface_id); int gb_interface_activate(struct gb_interface *intf); void gb_interface_deactivate(struct gb_interface *intf); int gb_interface_enable(struct gb_interface *intf); void gb_interface_disable(struct gb_interface *intf); int gb_interface_add(struct gb_interface *intf); -void gb_interface_remove(struct gb_interface *intf); +void gb_interface_del(struct gb_interface *intf); +void gb_interface_put(struct gb_interface *intf); #endif /* __INTERFACE_H */ diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c new file mode 100644 index 0000000..5c498e0 --- /dev/null +++ b/drivers/staging/greybus/module.c @@ -0,0 +1,178 @@ +/* + * Greybus Module code + * + * Copyright 2016 Google Inc. + * Copyright 2016 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include "greybus.h" + + +static ssize_t module_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_module *module = to_gb_module(dev); + + return sprintf(buf, "%u\n", module->module_id); +} +static DEVICE_ATTR_RO(module_id); + +static ssize_t num_interfaces_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_module *module = to_gb_module(dev); + + return sprintf(buf, "%zu\n", module->num_interfaces); +} +static DEVICE_ATTR_RO(num_interfaces); + +static struct attribute *module_attrs[] = { + &dev_attr_module_id.attr, + &dev_attr_num_interfaces.attr, + NULL, +}; +ATTRIBUTE_GROUPS(module); + +static void gb_module_release(struct device *dev) +{ + struct gb_module *module = to_gb_module(dev); + + kfree(module); +} + +struct device_type greybus_module_type = { + .name = "greybus_module", + .release = gb_module_release, +}; + +struct gb_module *gb_module_create(struct gb_host_device *hd, u8 module_id, + size_t num_interfaces) +{ + struct gb_interface *intf; + struct gb_module *module; + int i; + + module = kzalloc(sizeof(*module) + num_interfaces * sizeof(intf), + GFP_KERNEL); + if (!module) + return NULL; + + module->hd = hd; + module->module_id = module_id; + module->num_interfaces = num_interfaces; + + module->dev.parent = &hd->dev; + module->dev.bus = &greybus_bus_type; + module->dev.type = &greybus_module_type; + module->dev.groups = module_groups; + module->dev.dma_mask = hd->dev.dma_mask; + device_initialize(&module->dev); + dev_set_name(&module->dev, "%d-%u", hd->bus_id, module_id); + + for (i = 0; i < num_interfaces; ++i) { + intf = gb_interface_create(module, module_id + i); + if (!intf) { + dev_err(&module->dev, "failed to create interface %u\n", + module_id + i); + goto err_put_interfaces; + } + module->interfaces[i] = intf; + } + + return module; + +err_put_interfaces: + for (--i; i > 0; --i) + gb_interface_put(module->interfaces[i]); + + put_device(&module->dev); + + return NULL; +} + +/* + * Register and enable an interface after first attempting to activate it. + */ +static void gb_module_register_interface(struct gb_interface *intf) +{ + struct gb_module *module = intf->module; + u8 intf_id = intf->interface_id; + int ret; + + ret = gb_interface_activate(intf); + if (ret) { + dev_err(&module->dev, "failed to activate interface %u: %d\n", + intf_id, ret); + gb_interface_add(intf); + return; + } + + ret = gb_interface_add(intf); + if (ret) + goto err_interface_deactivate; + + ret = gb_interface_enable(intf); + if (ret) { + dev_err(&module->dev, "failed to enable interface %u: %d\n", + intf_id, ret); + goto err_interface_deactivate; + } + + return; + +err_interface_deactivate: + gb_interface_deactivate(intf); +} + +static void gb_module_deregister_interface(struct gb_interface *intf) +{ + /* Mark as disconnected to prevent I/O during disable. */ + if (intf->module->disconnected) + intf->disconnected = true; + + gb_interface_disable(intf); + gb_interface_deactivate(intf); + + gb_interface_del(intf); +} + +/* Register a module and its interfaces. */ +int gb_module_add(struct gb_module *module) +{ + size_t i; + int ret; + + ret = device_add(&module->dev); + if (ret) { + dev_err(&module->dev, "failed to register module: %d\n", ret); + return ret; + } + + for (i = 0; i < module->num_interfaces; ++i) + gb_module_register_interface(module->interfaces[i]); + + return 0; +} + +/* Deregister a module and its interfaces. */ +void gb_module_del(struct gb_module *module) +{ + size_t i; + + for (i = 0; i < module->num_interfaces; ++i) + gb_module_deregister_interface(module->interfaces[i]); + + device_del(&module->dev); +} + +void gb_module_put(struct gb_module *module) +{ + size_t i; + + for (i = 0; i < module->num_interfaces; ++i) + gb_interface_put(module->interfaces[i]); + + put_device(&module->dev); +} diff --git a/drivers/staging/greybus/module.h b/drivers/staging/greybus/module.h new file mode 100644 index 0000000..88a97ce --- /dev/null +++ b/drivers/staging/greybus/module.h @@ -0,0 +1,34 @@ +/* + * Greybus Module code + * + * Copyright 2016 Google Inc. + * Copyright 2016 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#ifndef __MODULE_H +#define __MODULE_H + +struct gb_module { + struct device dev; + struct gb_host_device *hd; + + struct list_head hd_node; + + u8 module_id; + size_t num_interfaces; + + bool disconnected; + + struct gb_interface *interfaces[0]; +}; +#define to_gb_module(d) container_of(d, struct gb_module, dev) + +struct gb_module *gb_module_create(struct gb_host_device *hd, u8 module_id, + size_t num_interfaces); +int gb_module_add(struct gb_module *module); +void gb_module_del(struct gb_module *module); +void gb_module_put(struct gb_module *module); + +#endif /* __MODULE_H */ diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index cde59d0..9401695 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -665,6 +665,19 @@ static int gb_svc_hello(struct gb_operation *op) return 0; } +static struct gb_module *gb_svc_module_lookup(struct gb_svc *svc, u8 module_id) +{ + struct gb_host_device *hd = svc->hd; + struct gb_module *module; + + list_for_each_entry(module, &hd->modules, hd_node) { + if (module->module_id == module_id) + return module; + } + + return NULL; +} + static void gb_svc_intf_reenable(struct gb_svc *svc, struct gb_interface *intf) { int ret; @@ -689,7 +702,7 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) struct gb_connection *connection = operation->connection; struct gb_svc *svc = gb_connection_get_data(connection); struct gb_host_device *hd = connection->hd; - struct gb_interface *intf; + struct gb_module *module; u8 intf_id; int ret; @@ -699,52 +712,35 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) dev_dbg(&svc->dev, "%s - id = %u\n", __func__, intf_id); - intf = gb_interface_find(hd, intf_id); - if (intf) { + /* All modules are considered 1x2 for now */ + module = gb_svc_module_lookup(svc, intf_id); + if (module) { dev_info(&svc->dev, "mode switch detected on interface %u\n", intf_id); - return gb_svc_intf_reenable(svc, intf); + return gb_svc_intf_reenable(svc, module->interfaces[0]); } - intf = gb_interface_create(hd, intf_id); - if (!intf) { - dev_err(&svc->dev, "failed to create interface %u\n", - intf_id); + module = gb_module_create(hd, intf_id, 1); + if (!module) { + dev_err(&svc->dev, "failed to create module\n"); return; } - ret = gb_interface_activate(intf); + ret = gb_module_add(module); if (ret) { - dev_err(&svc->dev, "failed to activate interface %u: %d\n", - intf_id, ret); - gb_interface_add(intf); + gb_module_put(module); return; } - ret = gb_interface_add(intf); - if (ret) - goto err_interface_deactivate; - - ret = gb_interface_enable(intf); - if (ret) { - dev_err(&svc->dev, "failed to enable interface %u: %d\n", - intf_id, ret); - goto err_interface_deactivate; - } - - return; - -err_interface_deactivate: - gb_interface_deactivate(intf); + list_add(&module->hd_node, &hd->modules); } static void gb_svc_process_intf_hot_unplug(struct gb_operation *operation) { struct gb_svc *svc = gb_connection_get_data(operation->connection); struct gb_svc_intf_hot_unplug_request *request; - struct gb_host_device *hd = operation->connection->hd; - struct gb_interface *intf; + struct gb_module *module; u8 intf_id; /* The request message size has already been verified. */ @@ -753,19 +749,19 @@ static void gb_svc_process_intf_hot_unplug(struct gb_operation *operation) dev_dbg(&svc->dev, "%s - id = %u\n", __func__, intf_id); - intf = gb_interface_find(hd, intf_id); - if (!intf) { + /* All modules are considered 1x2 for now */ + module = gb_svc_module_lookup(svc, intf_id); + if (!module) { dev_warn(&svc->dev, "could not find hot-unplug interface %u\n", intf_id); return; } - /* Mark as disconnected to prevent I/O during disable. */ - intf->disconnected = true; + module->disconnected = true; - gb_interface_disable(intf); - gb_interface_deactivate(intf); - gb_interface_remove(intf); + gb_module_del(module); + list_del(&module->hd_node); + gb_module_put(module); } static void gb_svc_process_deferred_request(struct work_struct *work) @@ -1104,14 +1100,15 @@ int gb_svc_add(struct gb_svc *svc) return 0; } -static void gb_svc_remove_interfaces(struct gb_svc *svc) +static void gb_svc_remove_modules(struct gb_svc *svc) { - struct gb_interface *intf, *tmp; + struct gb_host_device *hd = svc->hd; + struct gb_module *module, *tmp; - list_for_each_entry_safe(intf, tmp, &svc->hd->interfaces, links) { - gb_interface_disable(intf); - gb_interface_deactivate(intf); - gb_interface_remove(intf); + list_for_each_entry_safe(module, tmp, &hd->modules, hd_node) { + gb_module_del(module); + list_del(&module->hd_node); + gb_module_put(module); } } @@ -1132,7 +1129,7 @@ void gb_svc_del(struct gb_svc *svc) flush_workqueue(svc->wq); - gb_svc_remove_interfaces(svc); + gb_svc_remove_modules(svc); } void gb_svc_put(struct gb_svc *svc) -- cgit v0.10.2 From 36602a2981c85de7b0b8600eb12cbad3d80eacd9 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Sat, 23 Apr 2016 18:47:25 +0200 Subject: greybus: module: implement controlled module removal Implement controlled module removal through a new module attribute "eject". When a non-zero argument is written to the attribute, all interfaces of the module are disabled (e.g. bundles are deregistered) and deactivated (e.g. powered off) before instructing the SVC to physically eject the module. Note that the module device is not deregistered until the SVC has reported the physical removal of all of its interfaces. A new interface mutex is added to enforce interface state-change serialisation. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 41ffc40..a18ee7e 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -14,6 +14,14 @@ Description: A Module M on the bus N, where M is the 1-byte interface ID of the module's primary interface. +What: /sys/bus/greybus/device/N-M/eject +Date: March 2016 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman <greg@kroah.com> +Description: + Writing a non-zero argument to this attibute disables the + module's interfaces before physically ejecting it. + What: /sys/bus/greybus/device/N-M/module_id Date: March 2016 KernelVersion: 4.XX diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index d51c563..2553312 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -372,6 +372,7 @@ struct gb_interface *gb_interface_create(struct gb_module *module, intf->interface_id = interface_id; INIT_LIST_HEAD(&intf->bundles); INIT_LIST_HEAD(&intf->manifest_descs); + mutex_init(&intf->mutex); /* Invalid device id to start with */ intf->device_id = GB_INTERFACE_DEVICE_ID_BAD; @@ -388,10 +389,18 @@ struct gb_interface *gb_interface_create(struct gb_module *module, return intf; } +/* + * Activate an interface. + * + * Locking: Caller holds the interface mutex. + */ int gb_interface_activate(struct gb_interface *intf) { int ret; + if (intf->ejected) + return -ENODEV; + ret = gb_interface_read_dme(intf); if (ret) return ret; @@ -403,6 +412,11 @@ int gb_interface_activate(struct gb_interface *intf) return 0; } +/* + * Deactivate an interface. + * + * Locking: Caller holds the interface mutex. + */ void gb_interface_deactivate(struct gb_interface *intf) { gb_interface_route_destroy(intf); @@ -412,6 +426,8 @@ void gb_interface_deactivate(struct gb_interface *intf) * Enable an interface by enabling its control connection, fetching the * manifest and other information over it, and finally registering its child * devices. + * + * Locking: Caller holds the interface mutex. */ int gb_interface_enable(struct gb_interface *intf) { @@ -516,7 +532,11 @@ err_put_control: return ret; } -/* Disable an interface and destroy its bundles. */ +/* + * Disable an interface and destroy its bundles. + * + * Locking: Caller holds the interface mutex. + */ void gb_interface_disable(struct gb_interface *intf) { struct gb_bundle *bundle; diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 9185c7f..61399e7 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -39,7 +39,10 @@ struct gb_interface { unsigned long quirks; + struct mutex mutex; + bool disconnected; + bool ejected; bool enabled; }; #define to_gb_interface(d) container_of(d, struct gb_interface, dev) diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index 5c498e0..5077253 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -10,6 +10,43 @@ #include "greybus.h" +static ssize_t eject_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct gb_module *module = to_gb_module(dev); + struct gb_interface *intf; + size_t i; + long val; + int ret; + + ret = kstrtol(buf, 0, &val); + if (ret) + return ret; + + if (!val) + return len; + + for (i = 0; i < module->num_interfaces; ++i) { + intf = module->interfaces[i]; + + mutex_lock(&intf->mutex); + /* Set flag to prevent concurrent activation. */ + intf->ejected = true; + gb_interface_disable(intf); + gb_interface_deactivate(intf); + mutex_unlock(&intf->mutex); + } + + /* Tell the SVC to eject the primary interface. */ + ret = gb_svc_intf_eject(module->hd->svc, module->module_id); + if (ret) + return ret; + + return len; +} +static DEVICE_ATTR_WO(eject); + static ssize_t module_id_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -29,6 +66,7 @@ static ssize_t num_interfaces_show(struct device *dev, static DEVICE_ATTR_RO(num_interfaces); static struct attribute *module_attrs[] = { + &dev_attr_eject.attr, &dev_attr_module_id.attr, &dev_attr_num_interfaces.attr, NULL, @@ -101,12 +139,14 @@ static void gb_module_register_interface(struct gb_interface *intf) u8 intf_id = intf->interface_id; int ret; + mutex_lock(&intf->mutex); + ret = gb_interface_activate(intf); if (ret) { dev_err(&module->dev, "failed to activate interface %u: %d\n", intf_id, ret); gb_interface_add(intf); - return; + goto err_unlock; } ret = gb_interface_add(intf); @@ -120,10 +160,14 @@ static void gb_module_register_interface(struct gb_interface *intf) goto err_interface_deactivate; } + mutex_unlock(&intf->mutex); + return; err_interface_deactivate: gb_interface_deactivate(intf); +err_unlock: + mutex_unlock(&intf->mutex); } static void gb_module_deregister_interface(struct gb_interface *intf) @@ -132,8 +176,10 @@ static void gb_module_deregister_interface(struct gb_interface *intf) if (intf->module->disconnected) intf->disconnected = true; + mutex_lock(&intf->mutex); gb_interface_disable(intf); gb_interface_deactivate(intf); + mutex_unlock(&intf->mutex); gb_interface_del(intf); } diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 9401695..96b3027 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -682,6 +682,8 @@ static void gb_svc_intf_reenable(struct gb_svc *svc, struct gb_interface *intf) { int ret; + mutex_lock(&intf->mutex); + /* Mark as disconnected to prevent I/O during disable. */ intf->disconnected = true; gb_interface_disable(intf); @@ -694,6 +696,8 @@ static void gb_svc_intf_reenable(struct gb_svc *svc, struct gb_interface *intf) gb_interface_deactivate(intf); } + + mutex_unlock(&intf->mutex); } static void gb_svc_process_intf_hotplug(struct gb_operation *operation) -- cgit v0.10.2 From 1e1565e5fee47362baee92506749d80167a1456e Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Sat, 23 Apr 2016 18:47:26 +0200 Subject: greybus: interface: add active state flag Add active state flag to avoid deactivating an interface which is already off. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 2553312..e0c38f1 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -409,6 +409,8 @@ int gb_interface_activate(struct gb_interface *intf) if (ret) return ret; + intf->active = true; + return 0; } @@ -419,7 +421,12 @@ int gb_interface_activate(struct gb_interface *intf) */ void gb_interface_deactivate(struct gb_interface *intf) { + if (!intf->active) + return; + gb_interface_route_destroy(intf); + + intf->active = false; } /* diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 61399e7..c9c1c92 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -43,6 +43,7 @@ struct gb_interface { bool disconnected; bool ejected; + bool active; bool enabled; }; #define to_gb_interface(d) container_of(d, struct gb_interface, dev) -- cgit v0.10.2 From 017482b28decd5b72da2c6c661249e512e6665a8 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Sat, 23 Apr 2016 18:47:27 +0200 Subject: greybus: svc: add stub functions for v_sys, refclk and unipro Add stub functions for v_sys, refclk and unipro resource management. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 96b3027..cac9789 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -253,6 +253,27 @@ int gb_svc_intf_eject(struct gb_svc *svc, u8 intf_id) return 0; } +int gb_svc_intf_vsys_set(struct gb_svc *svc, u8 intf_id, bool enable) +{ + /* FIXME: implement */ + + return 0; +} + +int gb_svc_intf_refclk_set(struct gb_svc *svc, u8 intf_id, bool enable) +{ + /* FIXME: implement */ + + return 0; +} + +int gb_svc_intf_unipro_set(struct gb_svc *svc, u8 intf_id, bool enable) +{ + /* FIXME: implement */ + + return 0; +} + int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, u32 *value) { diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index 72bc716..055948c 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -69,6 +69,9 @@ int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id); int gb_svc_intf_eject(struct gb_svc *svc, u8 intf_id); +int gb_svc_intf_vsys_set(struct gb_svc *svc, u8 intf_id, bool enable); +int gb_svc_intf_refclk_set(struct gb_svc *svc, u8 intf_id, bool enable); +int gb_svc_intf_unipro_set(struct gb_svc *svc, u8 intf_id, bool enable); int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, u32 *value); int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, -- cgit v0.10.2 From 1e8e22b5cb462e9c4da9c988b3355565cdef1d34 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Sat, 23 Apr 2016 18:47:28 +0200 Subject: greybus: svc: add stub interface-activate function Add message structures (based on the current spec) for the SVC Interface Activate operation, and a stub function that always return the Greybus interface type. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 82798cf..9ef8797 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -802,6 +802,7 @@ struct gb_spi_transfer_response { #define GB_SVC_TYPE_PWRMON_RAIL_NAMES_GET 0x15 #define GB_SVC_TYPE_PWRMON_SAMPLE_GET 0x16 #define GB_SVC_TYPE_PWRMON_INTF_SAMPLE_GET 0x17 +#define GB_SVC_TYPE_INTF_ACTIVATE 0x27 /* * SVC version request/response has the same payload as @@ -1008,6 +1009,19 @@ struct gb_svc_pwrmon_intf_sample_get_response { __le32 measurement; } __packed; +struct gb_svc_intf_activate_request { + __u8 intf_id; +} __packed; + +#define GB_SVC_INTF_TYPE_UNKNOWN 0x00 +#define GB_SVC_INTF_TYPE_DUMMY 0x01 +#define GB_SVC_INTF_TYPE_UNIPRO 0x02 +#define GB_SVC_INTF_TYPE_GREYBUS 0x03 + +struct gb_svc_intf_activate_response { + __u8 intf_type; +} __packed; + /* RAW */ /* Version of the Greybus raw protocol we support */ diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index cac9789..1b37019 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -274,6 +274,15 @@ int gb_svc_intf_unipro_set(struct gb_svc *svc, u8 intf_id, bool enable) return 0; } +int gb_svc_intf_activate(struct gb_svc *svc, u8 intf_id, u8 *intf_type) +{ + /* FIXME: implement */ + + *intf_type = GB_SVC_INTF_TYPE_GREYBUS; + + return 0; +} + int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, u32 *value) { diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index 055948c..5460611 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -72,6 +72,7 @@ int gb_svc_intf_eject(struct gb_svc *svc, u8 intf_id); int gb_svc_intf_vsys_set(struct gb_svc *svc, u8 intf_id, bool enable); int gb_svc_intf_refclk_set(struct gb_svc *svc, u8 intf_id, bool enable); int gb_svc_intf_unipro_set(struct gb_svc *svc, u8 intf_id, bool enable); +int gb_svc_intf_activate(struct gb_svc *svc, u8 intf_id, u8 *intf_type); int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, u32 *value); int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, -- cgit v0.10.2 From ec562f28a7de6a4a4c3f790e5cfb5e61e97419b5 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Sat, 23 Apr 2016 18:47:29 +0200 Subject: greybus: interface: implement interface activation and power down Implement the interface activation and power-down sequences. Note that all the required SVC operations have not yet been implemented so some stub functions are used for now. Support for hibernating the UniPro link depends on future power-management work so a stub function is used also for this. Interface type handling will be refined later. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index e0c38f1..f6c058a 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -389,6 +389,95 @@ struct gb_interface *gb_interface_create(struct gb_module *module, return intf; } +static int gb_interface_vsys_set(struct gb_interface *intf, bool enable) +{ + struct gb_svc *svc = intf->hd->svc; + int ret; + + dev_dbg(&intf->dev, "%s - %d\n", __func__, enable); + + ret = gb_svc_intf_vsys_set(svc, intf->interface_id, enable); + if (ret) { + dev_err(&intf->dev, "failed to enable v_sys: %d\n", ret); + return ret; + } + + return 0; +} + +static int gb_interface_refclk_set(struct gb_interface *intf, bool enable) +{ + struct gb_svc *svc = intf->hd->svc; + int ret; + + dev_dbg(&intf->dev, "%s - %d\n", __func__, enable); + + ret = gb_svc_intf_refclk_set(svc, intf->interface_id, enable); + if (ret) { + dev_err(&intf->dev, "failed to enable refclk: %d\n", ret); + return ret; + } + + return 0; +} + +static int gb_interface_unipro_set(struct gb_interface *intf, bool enable) +{ + struct gb_svc *svc = intf->hd->svc; + int ret; + + dev_dbg(&intf->dev, "%s - %d\n", __func__, enable); + + ret = gb_svc_intf_unipro_set(svc, intf->interface_id, enable); + if (ret) { + dev_err(&intf->dev, "failed to enable UniPro: %d\n", ret); + return ret; + } + + return 0; +} + +static int gb_interface_activate_operation(struct gb_interface *intf) +{ + struct gb_svc *svc = intf->hd->svc; + u8 type; + int ret; + + dev_dbg(&intf->dev, "%s\n", __func__); + + ret = gb_svc_intf_activate(svc, intf->interface_id, &type); + if (ret) { + dev_err(&intf->dev, "failed to activate: %d\n", ret); + return ret; + } + + switch (type) { + case GB_SVC_INTF_TYPE_DUMMY: + dev_info(&intf->dev, "dummy interface detected\n"); + /* FIXME: handle as an error for now */ + return -ENODEV; + case GB_SVC_INTF_TYPE_UNIPRO: + dev_err(&intf->dev, "interface type UniPro not supported\n"); + return -ENODEV; + case GB_SVC_INTF_TYPE_GREYBUS: + break; + default: + dev_err(&intf->dev, "unknown interface type: %u\n", type); + return -ENODEV; + } + + return 0; +} + +static int gb_interface_hibernate_link(struct gb_interface *intf) +{ + dev_dbg(&intf->dev, "%s\n", __func__); + + /* FIXME: implement */ + + return 0; +} + /* * Activate an interface. * @@ -401,17 +490,44 @@ int gb_interface_activate(struct gb_interface *intf) if (intf->ejected) return -ENODEV; - ret = gb_interface_read_dme(intf); + ret = gb_interface_vsys_set(intf, true); if (ret) return ret; + ret = gb_interface_refclk_set(intf, true); + if (ret) + goto err_vsys_disable; + + ret = gb_interface_unipro_set(intf, true); + if (ret) + goto err_refclk_disable; + + ret = gb_interface_activate_operation(intf); + if (ret) + goto err_unipro_disable; + + ret = gb_interface_read_dme(intf); + if (ret) + goto err_hibernate_link; + ret = gb_interface_route_create(intf); if (ret) - return ret; + goto err_hibernate_link; intf->active = true; return 0; + +err_hibernate_link: + gb_interface_hibernate_link(intf); +err_unipro_disable: + gb_interface_unipro_set(intf, false); +err_refclk_disable: + gb_interface_refclk_set(intf, false); +err_vsys_disable: + gb_interface_vsys_set(intf, false); + + return ret; } /* @@ -425,6 +541,10 @@ void gb_interface_deactivate(struct gb_interface *intf) return; gb_interface_route_destroy(intf); + gb_interface_hibernate_link(intf); + gb_interface_unipro_set(intf, false); + gb_interface_refclk_set(intf, false); + gb_interface_vsys_set(intf, false); intf->active = false; } -- cgit v0.10.2 From 22bb9380d620b9632fb47220133ee6ab3fd36f22 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Sat, 23 Apr 2016 18:47:30 +0200 Subject: greybus: svc: implement module inserted and removed operations Implement the new module inserted and removed operations. The SVC sends these after detecting a module insertion or removal, and in the former case after having determined the module geometry (i.e. position and size). Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 9ef8797..ece8c64 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -802,6 +802,8 @@ struct gb_spi_transfer_response { #define GB_SVC_TYPE_PWRMON_RAIL_NAMES_GET 0x15 #define GB_SVC_TYPE_PWRMON_SAMPLE_GET 0x16 #define GB_SVC_TYPE_PWRMON_INTF_SAMPLE_GET 0x17 +#define GB_SVC_TYPE_MODULE_INSERTED 0x1f +#define GB_SVC_TYPE_MODULE_REMOVED 0x20 #define GB_SVC_TYPE_INTF_ACTIVATE 0x27 /* @@ -1009,6 +1011,20 @@ struct gb_svc_pwrmon_intf_sample_get_response { __le32 measurement; } __packed; +#define GB_SVC_MODULE_INSERTED_FLAG_NO_PRIMARY 0x0001 + +struct gb_svc_module_inserted_request { + __u8 primary_intf_id; + __u8 intf_count; + __le16 flags; +} __packed; +/* module_inserted response has no payload */ + +struct gb_svc_module_removed_request { + __u8 primary_intf_id; +} __packed; +/* module_removed response has no payload */ + struct gb_svc_intf_activate_request { __u8 intf_id; } __packed; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 1b37019..9d90014 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -798,6 +798,82 @@ static void gb_svc_process_intf_hot_unplug(struct gb_operation *operation) gb_module_put(module); } +static void gb_svc_process_module_inserted(struct gb_operation *operation) +{ + struct gb_svc_module_inserted_request *request; + struct gb_connection *connection = operation->connection; + struct gb_svc *svc = gb_connection_get_data(connection); + struct gb_host_device *hd = svc->hd; + struct gb_module *module; + size_t num_interfaces; + u8 module_id; + u16 flags; + int ret; + + /* The request message size has already been verified. */ + request = operation->request->payload; + module_id = request->primary_intf_id; + num_interfaces = request->intf_count; + flags = le16_to_cpu(request->flags); + + dev_dbg(&svc->dev, "%s - id = %u, num_interfaces = %zu, flags = 0x%04x\n", + __func__, module_id, num_interfaces, flags); + + if (flags & GB_SVC_MODULE_INSERTED_FLAG_NO_PRIMARY) { + dev_warn(&svc->dev, "no primary interface detected on module %u\n", + module_id); + } + + module = gb_svc_module_lookup(svc, module_id); + if (module) { + dev_warn(&svc->dev, "unexpected module-inserted event %u\n", + module_id); + return; + } + + module = gb_module_create(hd, module_id, num_interfaces); + if (!module) { + dev_err(&svc->dev, "failed to create module\n"); + return; + } + + ret = gb_module_add(module); + if (ret) { + gb_module_put(module); + return; + } + + list_add(&module->hd_node, &hd->modules); +} + +static void gb_svc_process_module_removed(struct gb_operation *operation) +{ + struct gb_svc_module_removed_request *request; + struct gb_connection *connection = operation->connection; + struct gb_svc *svc = gb_connection_get_data(connection); + struct gb_module *module; + u8 module_id; + + /* The request message size has already been verified. */ + request = operation->request->payload; + module_id = request->primary_intf_id; + + dev_dbg(&svc->dev, "%s - id = %u\n", __func__, module_id); + + module = gb_svc_module_lookup(svc, module_id); + if (!module) { + dev_warn(&svc->dev, "unexpected module-removed event %u\n", + module_id); + return; + } + + module->disconnected = true; + + gb_module_del(module); + list_del(&module->hd_node); + gb_module_put(module); +} + static void gb_svc_process_deferred_request(struct work_struct *work) { struct gb_svc_deferred_request *dr; @@ -817,6 +893,12 @@ static void gb_svc_process_deferred_request(struct work_struct *work) case GB_SVC_TYPE_INTF_HOT_UNPLUG: gb_svc_process_intf_hot_unplug(operation); break; + case GB_SVC_TYPE_MODULE_INSERTED: + gb_svc_process_module_inserted(operation); + break; + case GB_SVC_TYPE_MODULE_REMOVED: + gb_svc_process_module_removed(operation); + break; default: dev_err(&svc->dev, "bad deferred request type: 0x%02x\n", type); } @@ -957,6 +1039,44 @@ static int gb_svc_key_event_recv(struct gb_operation *op) return 0; } +static int gb_svc_module_inserted_recv(struct gb_operation *op) +{ + struct gb_svc *svc = gb_connection_get_data(op->connection); + struct gb_svc_module_inserted_request *request; + + if (op->request->payload_size < sizeof(*request)) { + dev_warn(&svc->dev, "short module-inserted request received (%zu < %zu)\n", + op->request->payload_size, sizeof(*request)); + return -EINVAL; + } + + request = op->request->payload; + + dev_dbg(&svc->dev, "%s - id = %u\n", __func__, + request->primary_intf_id); + + return gb_svc_queue_deferred_request(op); +} + +static int gb_svc_module_removed_recv(struct gb_operation *op) +{ + struct gb_svc *svc = gb_connection_get_data(op->connection); + struct gb_svc_module_removed_request *request; + + if (op->request->payload_size < sizeof(*request)) { + dev_warn(&svc->dev, "short module-removed request received (%zu < %zu)\n", + op->request->payload_size, sizeof(*request)); + return -EINVAL; + } + + request = op->request->payload; + + dev_dbg(&svc->dev, "%s - id = %u\n", __func__, + request->primary_intf_id); + + return gb_svc_queue_deferred_request(op); +} + static int gb_svc_request_handler(struct gb_operation *op) { struct gb_connection *connection = op->connection; @@ -1014,6 +1134,10 @@ static int gb_svc_request_handler(struct gb_operation *op) return gb_svc_intf_reset_recv(op); case GB_SVC_TYPE_KEY_EVENT: return gb_svc_key_event_recv(op); + case GB_SVC_TYPE_MODULE_INSERTED: + return gb_svc_module_inserted_recv(op); + case GB_SVC_TYPE_MODULE_REMOVED: + return gb_svc_module_removed_recv(op); default: dev_warn(&svc->dev, "unsupported request 0x%02x\n", type); return -EINVAL; -- cgit v0.10.2 From b482b0d6f099e282c7499b5b1a3a69747bf4fa8b Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Sat, 23 Apr 2016 18:47:31 +0200 Subject: greybus: svc: implement interface mailbox event Implement the new interface mailbox-event operation. The event is sent by the SVC under certain conditions when an interface updates its mailbox value. Specifically, this event will be used to implement the new mode-switch functionality. Upon reception the AP verifies that the interface is known and that the mailbox has the expected MAILBOX_GREYBUS value. If so, the interface is disabled before being re-enabled (re-enumerated). Note that during mode-switch, the interface will typically already be in a disabled state when the mailbox is written (with the ES3 bootrom being the notable exception). Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index ece8c64..bf3c132 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -805,6 +805,7 @@ struct gb_spi_transfer_response { #define GB_SVC_TYPE_MODULE_INSERTED 0x1f #define GB_SVC_TYPE_MODULE_REMOVED 0x20 #define GB_SVC_TYPE_INTF_ACTIVATE 0x27 +#define GB_SVC_TYPE_INTF_MAILBOX_EVENT 0x29 /* * SVC version request/response has the same payload as @@ -1038,6 +1039,18 @@ struct gb_svc_intf_activate_response { __u8 intf_type; } __packed; +#define GB_SVC_INTF_MAILBOX_NONE 0x00 +#define GB_SVC_INTF_MAILBOX_AP 0x01 +#define GB_SVC_INTF_MAILBOX_GREYBUS 0x02 + +struct gb_svc_intf_mailbox_event_request { + __u8 intf_id; + __le16 result_code; + __le32 mailbox; +} __packed; +/* intf_mailbox_event response has no payload */ + + /* RAW */ /* Version of the Greybus raw protocol we support */ diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 9d90014..0a49698 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -695,6 +695,27 @@ static int gb_svc_hello(struct gb_operation *op) return 0; } +static struct gb_interface *gb_svc_interface_lookup(struct gb_svc *svc, + u8 intf_id) +{ + struct gb_host_device *hd = svc->hd; + struct gb_module *module; + size_t num_interfaces; + u8 module_id; + + list_for_each_entry(module, &hd->modules, hd_node) { + module_id = module->module_id; + num_interfaces = module->num_interfaces; + + if (intf_id >= module_id && + intf_id < module_id + num_interfaces) { + return module->interfaces[intf_id - module_id]; + } + } + + return NULL; +} + static struct gb_module *gb_svc_module_lookup(struct gb_svc *svc, u8 module_id) { struct gb_host_device *hd = svc->hd; @@ -874,6 +895,58 @@ static void gb_svc_process_module_removed(struct gb_operation *operation) gb_module_put(module); } +static void gb_svc_process_intf_mailbox_event(struct gb_operation *operation) +{ + struct gb_svc_intf_mailbox_event_request *request; + struct gb_connection *connection = operation->connection; + struct gb_svc *svc = gb_connection_get_data(connection); + struct gb_interface *intf; + u8 intf_id; + u16 result_code; + u32 mailbox; + + /* The request message size has already been verified. */ + request = operation->request->payload; + intf_id = request->intf_id; + result_code = le16_to_cpu(request->result_code); + mailbox = le32_to_cpu(request->mailbox); + + dev_dbg(&svc->dev, "%s - id = %u, result = 0x%04x, mailbox = 0x%08x\n", + __func__, intf_id, result_code, mailbox); + + intf = gb_svc_interface_lookup(svc, intf_id); + if (!intf) { + dev_warn(&svc->dev, "unexpected mailbox event %u\n", intf_id); + return; + } + + if (result_code) { + dev_warn(&svc->dev, + "mailbox event %u with UniPro error: 0x%04x\n", + intf_id, result_code); + goto err_disable_interface; + } + + if (mailbox != GB_SVC_INTF_MAILBOX_GREYBUS) { + dev_warn(&svc->dev, + "mailbox event %u with unexected value: 0x%08x\n", + intf_id, mailbox); + goto err_disable_interface; + } + + dev_info(&svc->dev, "mode switch detected on interface %u\n", intf_id); + + gb_svc_intf_reenable(svc, intf); + + return; + +err_disable_interface: + mutex_lock(&intf->mutex); + gb_interface_disable(intf); + gb_interface_deactivate(intf); + mutex_unlock(&intf->mutex); +} + static void gb_svc_process_deferred_request(struct work_struct *work) { struct gb_svc_deferred_request *dr; @@ -899,6 +972,9 @@ static void gb_svc_process_deferred_request(struct work_struct *work) case GB_SVC_TYPE_MODULE_REMOVED: gb_svc_process_module_removed(operation); break; + case GB_SVC_TYPE_INTF_MAILBOX_EVENT: + gb_svc_process_intf_mailbox_event(operation); + break; default: dev_err(&svc->dev, "bad deferred request type: 0x%02x\n", type); } @@ -1077,6 +1153,24 @@ static int gb_svc_module_removed_recv(struct gb_operation *op) return gb_svc_queue_deferred_request(op); } +static int gb_svc_intf_mailbox_event_recv(struct gb_operation *op) +{ + struct gb_svc *svc = gb_connection_get_data(op->connection); + struct gb_svc_intf_mailbox_event_request *request; + + if (op->request->payload_size < sizeof(*request)) { + dev_warn(&svc->dev, "short mailbox request received (%zu < %zu)\n", + op->request->payload_size, sizeof(*request)); + return -EINVAL; + } + + request = op->request->payload; + + dev_dbg(&svc->dev, "%s - id = %u\n", __func__, request->intf_id); + + return gb_svc_queue_deferred_request(op); +} + static int gb_svc_request_handler(struct gb_operation *op) { struct gb_connection *connection = op->connection; @@ -1138,6 +1232,8 @@ static int gb_svc_request_handler(struct gb_operation *op) return gb_svc_module_inserted_recv(op); case GB_SVC_TYPE_MODULE_REMOVED: return gb_svc_module_removed_recv(op); + case GB_SVC_TYPE_INTF_MAILBOX_EVENT: + return gb_svc_intf_mailbox_event_recv(op); default: dev_warn(&svc->dev, "unsupported request 0x%02x\n", type); return -EINVAL; -- cgit v0.10.2 From 3fd747a63e836baab1739bab7f18d9227a083312 Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Fri, 22 Apr 2016 19:03:42 -0700 Subject: greybus: svc: clean up gb_svc struct for pwrmon The power rail names and counts are unnecessarily stored in the gb_svc structure once the SVC created, this causes waste of memory usage. This patch removes rail names and rail counts storage from th gb_svc structure. Testing Done: - Validated the readings from /d/greybus/1-svc/pwrmon/* Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 0a49698..b30b227 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -581,38 +581,40 @@ static void gb_svc_pwrmon_debugfs_init(struct gb_svc *svc) int i; size_t bufsize; struct dentry *dent; + struct gb_svc_pwrmon_rail_names_get_response *rail_names; + u8 rail_count; dent = debugfs_create_dir("pwrmon", svc->debugfs_dentry); if (IS_ERR_OR_NULL(dent)) return; - if (gb_svc_pwrmon_rail_count_get(svc, &svc->rail_count)) + if (gb_svc_pwrmon_rail_count_get(svc, &rail_count)) goto err_pwrmon_debugfs; - if (!svc->rail_count || svc->rail_count > GB_SVC_PWRMON_MAX_RAIL_COUNT) + if (!rail_count || rail_count > GB_SVC_PWRMON_MAX_RAIL_COUNT) goto err_pwrmon_debugfs; - bufsize = GB_SVC_PWRMON_RAIL_NAME_BUFSIZE * svc->rail_count; + bufsize = GB_SVC_PWRMON_RAIL_NAME_BUFSIZE * rail_count; - svc->rail_names = kzalloc(bufsize, GFP_KERNEL); - if (!svc->rail_names) + rail_names = kzalloc(bufsize, GFP_KERNEL); + if (!rail_names) goto err_pwrmon_debugfs; - svc->pwrmon_rails = kcalloc(svc->rail_count, sizeof(*svc->pwrmon_rails), + svc->pwrmon_rails = kcalloc(rail_count, sizeof(*svc->pwrmon_rails), GFP_KERNEL); if (!svc->pwrmon_rails) goto err_pwrmon_debugfs_free; - if (gb_svc_pwrmon_rail_names_get(svc, svc->rail_names, bufsize)) + if (gb_svc_pwrmon_rail_names_get(svc, rail_names, bufsize)) goto err_pwrmon_debugfs_free; - for (i = 0; i < svc->rail_count; i++) { + for (i = 0; i < rail_count; i++) { struct dentry *dir; struct svc_debugfs_pwrmon_rail *rail = &svc->pwrmon_rails[i]; char fname[GB_SVC_PWRMON_RAIL_NAME_BUFSIZE]; snprintf(fname, sizeof(fname), "%s", - (char *)&svc->rail_names->name[i]); + (char *)&rail_names->name[i]); rail->id = i; rail->svc = svc; @@ -625,12 +627,12 @@ static void gb_svc_pwrmon_debugfs_init(struct gb_svc *svc) debugfs_create_file("power_now", S_IRUGO, dir, rail, &pwrmon_debugfs_power_fops); }; + + kfree(rail_names); return; err_pwrmon_debugfs_free: - kfree(svc->rail_names); - svc->rail_names = NULL; - + kfree(rail_names); kfree(svc->pwrmon_rails); svc->pwrmon_rails = NULL; @@ -648,7 +650,6 @@ static void gb_svc_debugfs_init(struct gb_svc *svc) static void gb_svc_debugfs_exit(struct gb_svc *svc) { debugfs_remove_recursive(svc->debugfs_dentry); - kfree(svc->rail_names); } static int gb_svc_hello(struct gb_operation *op) diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index 5460611..7268db6 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -48,8 +48,6 @@ struct gb_svc { struct dentry *debugfs_dentry; struct svc_debugfs_pwrmon_rail *pwrmon_rails; - struct gb_svc_pwrmon_rail_names_get_response *rail_names; - u8 rail_count; }; #define to_gb_svc(d) container_of(d, struct gb_svc, dev) -- cgit v0.10.2 From 9983ea6b766aa701707e50c4b767ca892ee9ba7d Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Fri, 22 Apr 2016 19:03:43 -0700 Subject: greybus: svc: free pwrmon_rails memory upon exit For every time SVC instance is created, memories for storing the rail IDs are allocated, however, they are not freed when the SVC is destroyed. This patch fixes the memory leak by freeing the memory when debugfs for SVC is no longer needed. Testing Done: - Check pwrmon debugfs after turning on and off SVC Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index b30b227..78fe4dc 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -650,6 +650,8 @@ static void gb_svc_debugfs_init(struct gb_svc *svc) static void gb_svc_debugfs_exit(struct gb_svc *svc) { debugfs_remove_recursive(svc->debugfs_dentry); + kfree(svc->pwrmon_rails); + svc->pwrmon_rails = NULL; } static int gb_svc_hello(struct gb_operation *op) -- cgit v0.10.2 From dc0f0285f80558e800411d583de71358a581dfae Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 25 Apr 2016 21:50:36 +0530 Subject: greybus: Bundle: Initialize dma_mask for bundle device We missed this only for bundle device, fix it. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 1714482..1810b62 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -125,6 +125,7 @@ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, bundle->dev.bus = &greybus_bus_type; bundle->dev.type = &greybus_bundle_type; bundle->dev.groups = bundle_groups; + bundle->dev.dma_mask = intf->dev.dma_mask; device_initialize(&bundle->dev); dev_set_name(&bundle->dev, "%s.%d", dev_name(&intf->dev), bundle_id); -- cgit v0.10.2 From 2b8c2b51000e3d056f9aa27a64b93feabddf77a4 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Thu, 21 Apr 2016 22:14:02 +0530 Subject: greybus: audio: Changes in response to ASoC cleanup Update Makefile in response to SND_SOC_DYNAMIC_DAILINK cflag removal. Update files for msm-dynamic-dailink.h header file removal. Update in response to API name changes. Also, acquire sound card controls_rwsem before adding kcontrols to avoid deadlock. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 8ec6074..5bdcccc 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -52,11 +52,9 @@ obj-m += gb-es2.o ifeq ($(CONFIG_USB_HSIC_USB3613),y) obj-m += gb-arche.o endif -ifeq ($(CONFIG_SND_SOC_DYNAMIC_DAILINK),y) - obj-m += gb-audio-codec.o -obj-m += gb-audio-module.o -endif ifeq ($(CONFIG_ARCH_MSM8994),y) + obj-m += gb-audio-codec.o + obj-m += gb-audio-module.o obj-m += gb-camera.o endif obj-m += gb-audio-gb.o diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 20feea1..a2b81ba 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -898,6 +898,7 @@ int gbaudio_register_module(struct gbaudio_module_info *module) { int ret; struct snd_soc_codec *codec; + struct snd_card *card; struct snd_soc_jack *jack = NULL; if (!gbcodec) { @@ -906,6 +907,9 @@ int gbaudio_register_module(struct gbaudio_module_info *module) } codec = gbcodec->codec; + card = codec->card->snd_card; + + down_write(&card->controls_rwsem); mutex_lock(&gbcodec->lock); if (module->num_dais) { @@ -913,12 +917,14 @@ int gbaudio_register_module(struct gbaudio_module_info *module) "%d:DAIs not supported via gbcodec driver\n", module->num_dais); mutex_unlock(&gbcodec->lock); + up_write(&card->controls_rwsem); return -EINVAL; } ret = gbaudio_init_jack(module, codec); if (ret) { mutex_unlock(&gbcodec->lock); + up_write(&card->controls_rwsem); return ret; } @@ -936,7 +942,7 @@ int gbaudio_register_module(struct gbaudio_module_info *module) if (codec->card->instantiated) { ret = snd_soc_dapm_new_widgets(&codec->dapm); if (!ret) - snd_soc_dapm_link_dai_widgets_component(codec->card, + snd_soc_dapm_link_component_dai_widgets(codec->card, &codec->dapm); } @@ -953,6 +959,7 @@ int gbaudio_register_module(struct gbaudio_module_info *module) dev_dbg(codec->dev, "Registered %s module\n", module->name); mutex_unlock(&gbcodec->lock); + up_write(&card->controls_rwsem); return 0; } EXPORT_SYMBOL(gbaudio_register_module); @@ -1061,7 +1068,7 @@ void gbaudio_unregister_module(struct gbaudio_module_info *module) if (module->controls) { dev_dbg(codec->dev, "Removing %d controls\n", module->num_controls); - soc_remove_codec_controls(codec, module->controls, + snd_soc_remove_codec_controls(codec, module->controls, module->num_controls); } if (module->dapm_widgets) { diff --git a/drivers/staging/greybus/audio_module.c b/drivers/staging/greybus/audio_module.c index dd43b6d..bdc5ec5 100644 --- a/drivers/staging/greybus/audio_module.c +++ b/drivers/staging/greybus/audio_module.c @@ -9,7 +9,6 @@ #include <linux/module.h> #include <sound/soc.h> #include <sound/pcm_params.h> -#include <sound/msm-dynamic-dailink.h> #include "audio_codec.h" #include "audio_apbridgea.h" -- cgit v0.10.2 From 54e9070b24def1dfaf07e78fee6ea18f7ff57bcc Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Sat, 23 Apr 2016 20:04:05 +0530 Subject: greybus: audio: Reorder gb_deactivate sequence to avoid protocol error gb_activate_tx/rx is triggered from _prepare() & gb_deactivate from shutdown(). This may cause protocol error in case shutdown executes without _prepare due to some hw_params failure. Also, reorganise _prepare & _shutdown calls to make it more readable & cleaner. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index a2b81ba..7a9abbf 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -395,12 +395,88 @@ static int gbcodec_startup(struct snd_pcm_substream *substream, return ret; } +static int gbmodule_shutdown_tx(struct gbaudio_module_info *module, + struct gbaudio_data_connection *data, + int codec_state, struct device *dev) +{ + int ret, module_state; + __u16 i2s_port, cportid; + + module_state = module->ctrlstate[0]; + if (module_state == GBAUDIO_CODEC_SHUTDOWN) { + dev_dbg(dev, "%s: module already configured\n", + module->name); + return 0; + } + + if (codec_state == GBAUDIO_CODEC_STOP) { + ret = gb_audio_apbridgea_shutdown_tx(data->connection, 0); + if (ret) + return ret; + } + + /* deactivate */ + cportid = data->connection->intf_cport_id; + if (module_state >= GBAUDIO_CODEC_PREPARE) { + ret = gb_audio_gb_deactivate_tx(module->mgmt_connection, + cportid); + if (ret) + return ret; + } + + /* unregister cport */ + i2s_port = 0; /* fixed for now */ + cportid = data->connection->hd_cport_id; + ret = gb_audio_apbridgea_unregister_cport(data->connection, i2s_port, + cportid, + AUDIO_APBRIDGEA_DIRECTION_TX); + + return ret; +} + +static int gbmodule_shutdown_rx(struct gbaudio_module_info *module, + struct gbaudio_data_connection *data, + int codec_state, struct device *dev) +{ + int ret, module_state; + __u16 i2s_port, cportid; + + module_state = module->ctrlstate[1]; + if (module_state == GBAUDIO_CODEC_SHUTDOWN) { + dev_dbg(dev, "%s: module already configured\n", + module->name); + return 0; + } + + if (codec_state == GBAUDIO_CODEC_STOP) { + ret = gb_audio_apbridgea_shutdown_rx(data->connection, 0); + if (ret) + return ret; + } + + /* deactivate */ + cportid = data->connection->intf_cport_id; + if (module_state >= GBAUDIO_CODEC_PREPARE) { + ret = gb_audio_gb_deactivate_rx(module->mgmt_connection, + cportid); + if (ret) + return ret; + } + + /* unregister cport */ + i2s_port = 0; /* fixed for now */ + cportid = data->connection->hd_cport_id; + ret = gb_audio_apbridgea_unregister_cport(data->connection, i2s_port, + cportid, + AUDIO_APBRIDGEA_DIRECTION_RX); + + return ret; +} + static void gbcodec_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - int ret; - __u16 i2s_port, cportid; - int state, module_state; + int ret, state; struct gbaudio_module_info *module; struct gbaudio_data_connection *data; struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev); @@ -423,14 +499,6 @@ static void gbcodec_shutdown(struct snd_pcm_substream *substream, mutex_unlock(&module->lock); continue; } - module_state = module->ctrlstate[substream->stream]; - if (module_state == GBAUDIO_CODEC_SHUTDOWN) { - dev_dbg(codec->dev, "%s: module already configured\n", - module->name); - mutex_unlock(&module->lock); - continue; - } - /* find the dai */ data = find_data(module, dai->name); if (!data) { @@ -440,32 +508,18 @@ static void gbcodec_shutdown(struct snd_pcm_substream *substream, continue; } - /* deactivate */ - cportid = data->connection->intf_cport_id; switch (substream->stream) { - case SNDRV_PCM_STREAM_CAPTURE: - ret = gb_audio_gb_deactivate_rx(module->mgmt_connection, - cportid); - /* unregister cport */ - i2s_port = 0; /* fixed for now */ - cportid = data->connection->hd_cport_id; - ret = gb_audio_apbridgea_unregister_cport( - data->connection, i2s_port, cportid, - AUDIO_APBRIDGEA_DIRECTION_RX); - break; case SNDRV_PCM_STREAM_PLAYBACK: - ret = gb_audio_gb_deactivate_tx(module->mgmt_connection, - cportid); - /* unregister cport */ - i2s_port = 0; /* fixed for now */ - cportid = data->connection->hd_cport_id; - ret = gb_audio_apbridgea_unregister_cport( - data->connection, i2s_port, cportid, - AUDIO_APBRIDGEA_DIRECTION_TX); + ret = gbmodule_shutdown_tx(module, data, state, + dai->dev); + break; + case SNDRV_PCM_STREAM_CAPTURE: + ret = gbmodule_shutdown_rx(module, data, state, + dai->dev); break; } - dev_dbg(dai->dev, "Unregister %s:%d DAI, ret:%d\n", dai->name, - cportid, ret); + dev_dbg(dai->dev, "Unregister %s DAI, ret:%d\n", dai->name, + ret); state = GBAUDIO_CODEC_SHUTDOWN; module->ctrlstate[substream->stream] = state; dev_dbg(dai->dev, "%s: state:%d\n", module->name, state); @@ -589,14 +643,82 @@ func_exit: return ret; } +static int gbmodule_prepare_tx(struct gbaudio_module_info *module, + struct gbaudio_data_connection *data, + int codec_state, struct device *dev) +{ + int ret; + uint16_t data_cport; + + data_cport = data->connection->intf_cport_id; + ret = gb_audio_gb_set_tx_data_size(module->mgmt_connection, data_cport, + 192); + if (ret) { + dev_err(dev, "%d:Error during set_tx_data_size, cport:%d\n", + ret, data_cport); + return ret; + } + if (codec_state < GBAUDIO_CODEC_PREPARE) { + ret = gb_audio_apbridgea_set_tx_data_size(data->connection, 0, + 192); + if (ret) { + dev_err(dev, + "%d:Error during apbridgea set_tx_data_size, cport\n", + ret); + return ret; + } + } + ret = gb_audio_gb_activate_tx(module->mgmt_connection, + data_cport); + if (ret) + dev_err(dev, "%s:Error during activate stream,%d\n", + module->name, ret); + + return ret; +} + +static int gbmodule_prepare_rx(struct gbaudio_module_info *module, + struct gbaudio_data_connection *data, + int codec_state, struct device *dev) +{ + int ret; + uint16_t data_cport; + + data_cport = data->connection->intf_cport_id; + + ret = gb_audio_gb_set_rx_data_size(module->mgmt_connection, data_cport, + 192); + if (ret) { + dev_err(dev, "%d:Error during set_rx_data_size, cport:%d\n", + ret, data_cport); + return ret; + } + if (codec_state < GBAUDIO_CODEC_PREPARE) { + ret = gb_audio_apbridgea_set_rx_data_size(data->connection, 0, + 192); + if (ret) { + dev_err(dev, + "%d:Error during apbridgea_set_rx_data_size\n", + ret); + return ret; + } + } + ret = gb_audio_gb_activate_rx(module->mgmt_connection, + data_cport); + if (ret) + dev_err(dev, "%s:Error during activate stream,%d\n", + module->name, ret); + + return ret; +} + static int gbcodec_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { int ret; - uint16_t data_cport; - struct gbaudio_data_connection *data; struct gbaudio_module_info *module; int state; + struct gbaudio_data_connection *data; struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev); mutex_lock(&codec->lock); @@ -623,71 +745,24 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream, mutex_unlock(&module->lock); continue; } - /* deactivate rx/tx */ - data_cport = data->connection->intf_cport_id; switch (substream->stream) { - case SNDRV_PCM_STREAM_CAPTURE: - ret = gb_audio_gb_set_rx_data_size( - module->mgmt_connection, - data_cport, 192); - if (ret) { - dev_err(dai->dev, - "%d:Error during set_rx_data_size, cport:%d\n", - ret, data_cport); - mutex_unlock(&module->lock); - goto func_exit; - } - if (state < GBAUDIO_CODEC_PREPARE) { - ret = gb_audio_apbridgea_set_rx_data_size( - data->connection, 0, - 192); - if (ret) { - dev_err(dai->dev, - "%d:Error during apbridgea_set_rx_data_size\n", - ret); - mutex_unlock(&module->lock); - goto func_exit; - } - } - ret = gb_audio_gb_activate_rx(module->mgmt_connection, - data_cport); - if (ret) - dev_err(dai->dev, - "%s:Error during activate stream,%d\n", - module->name, ret); - break; case SNDRV_PCM_STREAM_PLAYBACK: - ret = gb_audio_gb_set_tx_data_size( - module->mgmt_connection, - data_cport, 192); - if (ret) { - dev_err(dai->dev, - "%d:Error during module set_tx_data_size, cport:%d\n", - ret, data_cport); - mutex_unlock(&module->lock); - goto func_exit; - } - if (state < GBAUDIO_CODEC_PREPARE) { - ret = gb_audio_apbridgea_set_tx_data_size( - data->connection, 0, - 192); - if (ret) { - dev_err(dai->dev, - "%d:Error during apbridgea set_tx_data_size, cport\n", - ret); - mutex_unlock(&module->lock); - goto func_exit; - } - } - ret = gb_audio_gb_activate_tx(module->mgmt_connection, - data_cport); - if (ret) - dev_err(dai->dev, - "%s:Error during activate stream,%d\n", - module->name, ret); + ret = gbmodule_prepare_tx(module, data, state, + dai->dev); + break; + case SNDRV_PCM_STREAM_CAPTURE: + ret = gbmodule_prepare_rx(module, data, state, + dai->dev); break; } + if (ret == -ENODEV) + continue; + if (ret) { + mutex_unlock(&module->lock); + goto func_exit; + } + state = GBAUDIO_CODEC_PREPARE; module->ctrlstate[substream->stream] = state; dev_dbg(dai->dev, "%s: state:%d\n", module->name, state); @@ -697,7 +772,7 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream, func_exit: mutex_unlock(&codec->lock); - return 0; + return ret; } static int gbcodec_trigger(struct snd_pcm_substream *substream, int cmd, -- cgit v0.10.2 From 475f498bcedb15634ca041b4eea2c58622558e03 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Wed, 13 Apr 2016 09:53:38 +0530 Subject: greybus: audio: Rename widget_type to jack_attrubute This fields actually populates jack attribute. Thus, renamed to reflect the real purpose. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index bf3c132..713b569 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -1922,7 +1922,7 @@ struct gb_audio_deactivate_rx_request { struct gb_audio_jack_event_request { __u8 widget_id; - __u8 widget_type; + __u8 jack_attribute; __u8 event; } __packed; -- cgit v0.10.2 From 05ab5f0daa524915176d170f3873b97ad10d7c43 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Wed, 13 Apr 2016 09:53:39 +0530 Subject: greybus: audio: Identify jack type based on attributes reported Originally, idea was to use widget_type to identify jack_type. However, suggestive way is to identify jack based on jack attributes. Changes already exists in codec FW to report jack attributes. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_module.c b/drivers/staging/greybus/audio_module.c index bdc5ec5..05bda48 100644 --- a/drivers/staging/greybus/audio_module.c +++ b/drivers/staging/greybus/audio_module.c @@ -27,7 +27,7 @@ static int gbaudio_request_jack(struct gbaudio_module_info *module, int report, button_status; dev_warn(module->dev, "Jack Event received: type: %u, event: %u\n", - req->widget_type, req->event); + req->jack_attribute, req->event); mutex_lock(&module->lock); if (req->event == GB_AUDIO_JACK_EVENT_REMOVAL) { @@ -43,18 +43,9 @@ static int gbaudio_request_jack(struct gbaudio_module_info *module, return 0; } - report &= ~GBCODEC_JACK_MASK; /* currently supports Headphone, Headset & Lineout only */ - if (req->widget_type && GB_AUDIO_WIDGET_TYPE_HP) - report |= SND_JACK_HEADPHONE & GBCODEC_JACK_MASK; - - if (req->widget_type && GB_AUDIO_WIDGET_TYPE_MIC) - report = SND_JACK_MICROPHONE & GBCODEC_JACK_MASK; - - if (req->widget_type && GB_AUDIO_WIDGET_TYPE_LINE) - report = (report & GBCODEC_JACK_MASK) | - SND_JACK_LINEOUT | SND_JACK_LINEIN; - + report &= ~GBCODEC_JACK_MASK; + report |= req->jack_attribute & GBCODEC_JACK_MASK; if (module->jack_type) dev_warn(module->dev, "Modifying jack from %d to %d\n", module->jack_type, report); -- cgit v0.10.2 From 9e04fb7b1627ad55b63c4e0927f696ecb1a2563a Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Tue, 26 Apr 2016 10:20:49 +0530 Subject: greybus: firmware: Add firmware management bundle driver All firmware packages on the Modules or Interfaces are now managed by a special Firmware Management Protocol. The Interface Manifest shall at least contain the Firmware Management Bundle and a Firmware Management Protocol CPort within it. The bundle may contain additional CPorts based on the extra functionality required to manage firmware packages. For example, this is how the Firmware Management Bundle of the Interface Manifest may look like: ; Firmware Management Bundle (Bundle 1): [bundle-descriptor 1] class = 0x16 ; (Mandatory) Firmware Management Protocol on CPort 1 [cport-descriptor 1] bundle = 1 protocol = 0x18 ; (Optional) Firmware Download Protocol on CPort 2 [cport-descriptor 2] bundle = 1 protocol = 0x17 ; (Optional) SPI protocol on CPort 3 [cport-descriptor 3] bundle = 1 protocol = 0x0b ; (Optional) Component Authentication Protocol (CAP) on CPort 4 [cport-descriptor 4] bundle = 1 protocol = 0xXX //TBD This patch adds the basic firmware-management bundle driver, which just creates a firmware-management connection. Support for individual protocols will be added separately. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 5bdcccc..1a120d9 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -39,6 +39,7 @@ gb-audio-apbridgea-y := audio_apbridgea.o gb-audio-manager-y += audio_manager.o gb-audio-manager-y += audio_manager_module.o gb-camera-y := camera.o +gb-firmware-y := fw-core.o obj-m += greybus.o obj-m += gb-phy.o @@ -60,6 +61,7 @@ endif obj-m += gb-audio-gb.o obj-m += gb-audio-apbridgea.o obj-m += gb-audio-manager.o +obj-m += gb-firmware.o KERNELVER ?= $(shell uname -r) KERNELDIR ?= /lib/modules/$(KERNELVER)/build diff --git a/drivers/staging/greybus/fw-core.c b/drivers/staging/greybus/fw-core.c new file mode 100644 index 0000000..4720d59 --- /dev/null +++ b/drivers/staging/greybus/fw-core.c @@ -0,0 +1,123 @@ +/* + * Greybus Firmware Core Bundle Driver. + * + * Copyright 2016 Google Inc. + * Copyright 2016 Linaro Ltd. + * + * Released under the GPLv2 only. + */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/firmware.h> +#include "greybus.h" + +struct gb_fw_core { + struct gb_connection *mgmt_connection; +}; + +static int gb_fw_core_probe(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) +{ + struct greybus_descriptor_cport *cport_desc; + struct gb_connection *connection; + struct gb_fw_core *fw_core; + int ret, i; + u16 cport_id; + u8 protocol_id; + + fw_core = kzalloc(sizeof(*fw_core), GFP_KERNEL); + if (!fw_core) + return -ENOMEM; + + /* Parse CPorts and create connections */ + for (i = 0; i < bundle->num_cports; i++) { + cport_desc = &bundle->cport_desc[i]; + cport_id = le16_to_cpu(cport_desc->id); + protocol_id = cport_desc->protocol_id; + + switch (protocol_id) { + case GREYBUS_PROTOCOL_FW_MANAGEMENT: + /* Disallow multiple Firmware Management CPorts */ + if (fw_core->mgmt_connection) { + dev_err(&bundle->dev, + "multiple management CPorts found\n"); + ret = -EINVAL; + goto err_destroy_connections; + } + + connection = gb_connection_create(bundle, cport_id, + NULL); + if (IS_ERR(connection)) { + ret = PTR_ERR(connection); + dev_err(&bundle->dev, + "failed to create management connection (%d)\n", + ret); + goto err_free_fw_core; + } + + fw_core->mgmt_connection = connection; + break; + default: + dev_err(&bundle->dev, "invalid protocol id (0x%02x)\n", + protocol_id); + ret = -EINVAL; + goto err_free_fw_core; + } + } + + /* Firmware Management connection is mandatory */ + if (!fw_core->mgmt_connection) { + dev_err(&bundle->dev, "missing management connection\n"); + ret = -ENODEV; + goto err_free_fw_core; + } + + greybus_set_drvdata(bundle, fw_core); + + return 0; + +err_destroy_connections: + gb_connection_destroy(fw_core->mgmt_connection); +err_free_fw_core: + kfree(fw_core); + + return ret; +} + +static void gb_fw_core_disconnect(struct gb_bundle *bundle) +{ + struct gb_fw_core *fw_core = greybus_get_drvdata(bundle); + + gb_connection_destroy(fw_core->mgmt_connection); + + kfree(fw_core); +} + +static const struct greybus_bundle_id gb_fw_core_id_table[] = { + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_FW_MANAGEMENT) }, + { } +}; + +static struct greybus_driver gb_fw_core_driver = { + .name = "gb-firmware", + .probe = gb_fw_core_probe, + .disconnect = gb_fw_core_disconnect, + .id_table = gb_fw_core_id_table, +}; + +static int fw_core_init(void) +{ + return greybus_register(&gb_fw_core_driver); +} +module_init(fw_core_init); + +static void __exit fw_core_exit(void) +{ + greybus_deregister(&gb_fw_core_driver); +} +module_exit(fw_core_exit); + +MODULE_ALIAS("greybus:firmware"); +MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>"); +MODULE_DESCRIPTION("Greybus Firmware Bundle Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 460fced..5d00f7d 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -45,6 +45,8 @@ enum greybus_protocol { GREYBUS_PROTOCOL_SVC = 0x14, GREYBUS_PROTOCOL_BOOTROM = 0x15, GREYBUS_PROTOCOL_CAMERA_DATA = 0x16, + GREYBUS_PROTOCOL_FW_DOWNLOAD = 0x17, + GREYBUS_PROTOCOL_FW_MANAGEMENT = 0x18, /* ... */ GREYBUS_PROTOCOL_RAW = 0xfe, GREYBUS_PROTOCOL_VENDOR = 0xff, @@ -73,6 +75,7 @@ enum greybus_class_type { /* 0x13 is unused */ /* 0x14 is unused */ GREYBUS_CLASS_BOOTROM = 0x15, + GREYBUS_CLASS_FW_MANAGEMENT = 0x16, /* ... */ GREYBUS_CLASS_RAW = 0xfe, GREYBUS_CLASS_VENDOR = 0xff, -- cgit v0.10.2 From 6ddbed576606a454353638dbbbcc2f66f0fc712d Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Thu, 28 Apr 2016 16:19:39 +0200 Subject: greybus: interface: fix broken UniPro flow control A recent commit inadvertently disabled E2EFC on all interface connections, due to a failure to clear the ES3 bootrom quirk flags during mode switch. Testing Done: Verified that the CPort flags are again set to 0x7 for non-bootrom interface connections. Fixes: 5b638080e94e ("svc: keep interfaces registered during mode switch") Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index f6c058a..b5ad1ac 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -226,6 +226,9 @@ static int gb_interface_read_and_clear_init_status(struct gb_interface *intf) intf->quirks |= GB_INTERFACE_QUIRK_NO_CPORT_FEATURES; intf->quirks |= GB_INTERFACE_QUIRK_NO_INTERFACE_VERSION; break; + default: + intf->quirks &= ~GB_INTERFACE_QUIRK_NO_CPORT_FEATURES; + intf->quirks &= ~GB_INTERFACE_QUIRK_NO_INTERFACE_VERSION; } /* Clear the init status. */ -- cgit v0.10.2 From fbbd2b7c0876550b20c6ac0ee2df90ecc262712c Mon Sep 17 00:00:00 2001 From: Sandeep Patil <sspatil@google.com> Date: Fri, 29 Apr 2016 07:13:23 -0700 Subject: greybus: hd: add bus_id attribute The greybus host device id can only be read by parsing the uevent if one wants to identify a specific host device 'or' bus. This is 'lsgb' uses today. This change adds a bus_id attribute so libraries can identify multiple host devices 'or' bus if they exist. Testing Done: Tested on Arche, 'cat /sys/bus/greybus/devices/greysbus1/bus_id' Signed-off-by: Sandeep Patil <sspatil@google.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index 762cc03..2863472 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -24,6 +24,21 @@ int gb_hd_output(struct gb_host_device *hd, void *req, u16 size, u8 cmd, } EXPORT_SYMBOL_GPL(gb_hd_output); +static ssize_t bus_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_host_device *hd = to_gb_host_device(dev); + + return sprintf(buf, "%d\n", hd->bus_id); +} +static DEVICE_ATTR_RO(bus_id); + +static struct attribute *bus_attrs[] = { + &dev_attr_bus_id.attr, + NULL +}; +ATTRIBUTE_GROUPS(bus); + static void gb_hd_release(struct device *dev) { struct gb_host_device *hd = to_gb_host_device(dev); @@ -98,6 +113,7 @@ struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, hd->dev.parent = parent; hd->dev.bus = &greybus_bus_type; hd->dev.type = &greybus_hd_type; + hd->dev.groups = bus_groups; hd->dev.dma_mask = hd->dev.parent->dma_mask; device_initialize(&hd->dev); dev_set_name(&hd->dev, "greybus%d", hd->bus_id); -- cgit v0.10.2 From dc9e9cf450fb22ad8d4836bc2879ad3428a1b4eb Mon Sep 17 00:00:00 2001 From: Sandeep Patil <sspatil@google.com> Date: Fri, 29 Apr 2016 07:13:24 -0700 Subject: greybus: Documentation/sysfs: add entry for host device bus_id Add description for greybus host device bus_id attribute Signed-off-by: Sandeep Patil <sspatil@google.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index a18ee7e..044ede6 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -6,6 +6,13 @@ Description: The "root" greybus device for the Greybus device tree, or bus, where N is a dynamically assigned 1-based id. +What: /sys/bus/greybus/devices/greybusN/bus_id +Date: April 2016 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman <greg@kroah.com> +Description: + The ID of the "root" greybus device, or bus. + What: /sys/bus/greybus/device/N-M Date: March 2016 KernelVersion: 4.XX diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/bus_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/bus_id new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/bus_id @@ -0,0 +1 @@ +1 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/bus_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/bus_id new file mode 100644 index 0000000..0cfbf08 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus2/bus_id @@ -0,0 +1 @@ +2 -- cgit v0.10.2 From 16ba59cedf070a28dfd84d4f3713a9494f50fe4a Mon Sep 17 00:00:00 2001 From: Sandeep Patil <sspatil@google.com> Date: Fri, 29 Apr 2016 07:13:25 -0700 Subject: greybus: Documentation/sysfs: fix sysfs paths correct sysfs paths typo. (s/device/devices). Signed-off-by: Sandeep Patil <sspatil@google.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 044ede6..0e1c2a3 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -1,4 +1,4 @@ -What: /sys/bus/greybus/device/greybusN +What: /sys/bus/greybus/devices/greybusN Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> @@ -13,7 +13,7 @@ Contact: Greg Kroah-Hartman <greg@kroah.com> Description: The ID of the "root" greybus device, or bus. -What: /sys/bus/greybus/device/N-M +What: /sys/bus/greybus/devices/N-M Date: March 2016 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> @@ -21,7 +21,7 @@ Description: A Module M on the bus N, where M is the 1-byte interface ID of the module's primary interface. -What: /sys/bus/greybus/device/N-M/eject +What: /sys/bus/greybus/devices/N-M/eject Date: March 2016 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> @@ -29,7 +29,7 @@ Description: Writing a non-zero argument to this attibute disables the module's interfaces before physically ejecting it. -What: /sys/bus/greybus/device/N-M/module_id +What: /sys/bus/greybus/devices/N-M/module_id Date: March 2016 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> @@ -37,14 +37,14 @@ Description: The ID of a Greybus module, corresponding to the ID of its primary interface. -What: /sys/bus/greybus/device/N-M/num_interfaces +What: /sys/bus/greybus/devices/N-M/num_interfaces Date: March 2016 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> Description: The number of interfaces of a module. -What: /sys/bus/greybus/device/N-M.I +What: /sys/bus/greybus/devices/N-M.I Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> @@ -52,14 +52,14 @@ Description: An Interface I on the bus N and module N-M, where I is the 1-byte interface ID. -What: /sys/bus/greybus/device/N-M.I/current_now +What: /sys/bus/greybus/devices/N-M.I/current_now Date: March 2016 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> Description: Current measurement of the interface in microamps (uA) -What: /sys/bus/greybus/device/N-M.I/ddbl1_manufacturer_id +What: /sys/bus/greybus/devices/N-M.I/ddbl1_manufacturer_id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> @@ -67,7 +67,7 @@ Description: Unipro Device Descriptor Block Level 1 manufacturer ID for the greybus Interface. -What: /sys/bus/greybus/device/N-M.I/ddbl1_product_id +What: /sys/bus/greybus/devices/N-M.I/ddbl1_product_id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> @@ -75,28 +75,28 @@ Description: Unipro Device Descriptor Block Level 1 product ID for the greybus Interface. -What: /sys/bus/greybus/device/N-M.I/interface_id +What: /sys/bus/greybus/devices/N-M.I/interface_id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> Description: The ID of a Greybus interface. -What: /sys/bus/greybus/device/N-M.I/power_now +What: /sys/bus/greybus/devices/N-M.I/power_now Date: March 2016 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> Description: Power measurement of the interface in microwatts (uW) -What: /sys/bus/greybus/device/N-M.I/product_id +What: /sys/bus/greybus/devices/N-M.I/product_id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> Description: Product ID of a Greybus interface. -What: /sys/bus/greybus/device/N-M.I/serial_number +What: /sys/bus/greybus/devices/N-M.I/serial_number Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> @@ -104,14 +104,14 @@ Description: Serial Number of the Greybus interface, represented by a 64 bit hexadecimal number. -What: /sys/bus/greybus/device/N-M.I/vendor_id +What: /sys/bus/greybus/devices/N-M.I/vendor_id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> Description: Vendor ID of a Greybus interface. -What: /sys/bus/greybus/device/N-M.I/version +What: /sys/bus/greybus/devices/N-M.I/version Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> @@ -119,14 +119,14 @@ Description: Interface version represented as <16 bit major number>.<16 bit minor number>. -What: /sys/bus/greybus/device/N-M.I/voltage_now +What: /sys/bus/greybus/devices/N-M.I/voltage_now Date: March 2016 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> Description: Voltage measurement of the interface in microvolts (uV) -What: /sys/bus/greybus/device/N-M.I.ctrl +What: /sys/bus/greybus/devices/N-M.I.ctrl Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> @@ -134,21 +134,21 @@ Description: Abstract control device for interface I that represents the current mode of an enumerated Greybus interface. -What: /sys/bus/greybus/device/N-M.I.ctrl/product_string +What: /sys/bus/greybus/devices/N-M.I.ctrl/product_string Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> Description: Product ID string of a Greybus interface. -What: /sys/bus/greybus/device/N-M.I.ctrl/vendor_string +What: /sys/bus/greybus/devices/N-M.I.ctrl/vendor_string Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> Description: Vendor ID string of a Greybus interface. -What: /sys/bus/greybus/device/N-M.I.B +What: /sys/bus/greybus/devices/N-M.I.B Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> @@ -156,21 +156,21 @@ Description: A bundle B on the Interface I, B is replaced by a 1-byte number representing the bundle. -What: /sys/bus/greybus/device/N-M.I.B/bundle_class +What: /sys/bus/greybus/devices/N-M.I.B/bundle_class Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> Description: The greybus class of the bundle B. -What: /sys/bus/greybus/device/N-M.I.B/bundle_id +What: /sys/bus/greybus/devices/N-M.I.B/bundle_id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> Description: The interface-unique id of the bundle B. -What: /sys/bus/greybus/device/N-M.I.B/state +What: /sys/bus/greybus/devices/N-M.I.B/state Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> @@ -183,14 +183,14 @@ Description: value can be read. It's a "poor-man's IPC", yes, but simplifies the Android userspace code immensely. -What: /sys/bus/greybus/device/N-svc +What: /sys/bus/greybus/devices/N-svc Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> Description: The singleton SVC device of bus N. -What: /sys/bus/greybus/device/N-svc/ap_intf_id +What: /sys/bus/greybus/devices/N-svc/ap_intf_id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> @@ -200,7 +200,7 @@ Description: The interface positions are defined in the ARA Module Developer Kit. -What: /sys/bus/greybus/device/N-svc/endo_id +What: /sys/bus/greybus/devices/N-svc/endo_id Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> @@ -209,7 +209,7 @@ Description: defined by the Endo layout scheme, documented in the ARA Module Developer Kit. -What: /sys/bus/greybus/device/N-svc/intf_eject +What: /sys/bus/greybus/devices/N-svc/intf_eject Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> @@ -217,14 +217,14 @@ Description: Write the number of the interface that you wish to forcibly eject from the system. -What: /sys/bus/greybus/device/N-svc/version +What: /sys/bus/greybus/devices/N-svc/version Date: October 2015 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> Description: The version number of the firmware in the SVC device. -What: /sys/bus/greybus/device/N-svc/watchdog +What: /sys/bus/greybus/devices/N-svc/watchdog Date: October 2016 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> -- cgit v0.10.2 From cca69fabeb715777c612f4223c91a2eca8f99c3a Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 29 Apr 2016 17:08:29 +0200 Subject: greybus: interface: remove unused prototype Remove unused function prototype that was left after a recent change. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index c9c1c92..7a0366d 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -48,9 +48,6 @@ struct gb_interface { }; #define to_gb_interface(d) container_of(d, struct gb_interface, dev) -struct gb_interface *gb_interface_find(struct gb_host_device *hd, - u8 interface_id); - struct gb_interface *gb_interface_create(struct gb_module *module, u8 interface_id); int gb_interface_activate(struct gb_interface *intf); -- cgit v0.10.2 From 410abddb0389aa1e456f980b336eb20948ccce51 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 29 Apr 2016 17:08:30 +0200 Subject: greybus: fix outdated kernel-doc comment Update the function name, which has gained a timeout suffix. Also fix the kernel-doc formatting. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 5818d7c..5af6535 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -1006,7 +1006,7 @@ void gb_operation_cancel_incoming(struct gb_operation *operation, int errno) } /** - * gb_operation_sync: implement a "simple" synchronous gb operation. + * gb_operation_sync_timeout() - implement a "simple" synchronous operation * @connection: the Greybus connection to send this to * @type: the type of operation to send * @request: pointer to a memory buffer to copy the request from -- cgit v0.10.2 From 613c15e86b7ac30cb3e3f16e13ee367845a941b2 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 29 Apr 2016 17:08:31 +0200 Subject: greybus: operation: update gb_operation_request_send() documentation Fix and update gb_operation_request_send() documentation and add kernel-doc formatting. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 5af6535..bb89955 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -627,13 +627,20 @@ static void gb_operation_sync_callback(struct gb_operation *operation) complete(&operation->completion); } -/* - * Send an operation request message. The caller has filled in any payload so - * the request message is ready to go. The callback function supplied will be - * called when the response message has arrived indicating the operation is - * complete. In that case, the callback function is responsible for fetching - * the result of the operation using gb_operation_result() if desired, and - * dropping the initial reference to the operation. +/** + * gb_operation_request_send() - send an operation request message + * @operation: the operation to initiate + * @callback: the operation completion callback + * @gfp: the memory flags to use for any allocations + * + * The caller has filled in any payload so the request message is ready to go. + * The callback function supplied will be called when the response message has + * arrived, or the operation is cancelled, indicating that the operation is + * complete. The callback function can fetch the result of the operation using + * gb_operation_result() if desired. + * + * Return: 0 if the request was successfully queued in the host-driver queues, + * or a negative errno. */ int gb_operation_request_send(struct gb_operation *operation, gb_operation_callback callback, -- cgit v0.10.2 From 3e2ee2c1e50541b611087be9e2e55b8f77477cf6 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 29 Apr 2016 17:08:32 +0200 Subject: greybus: operation: add support for initiating unidirectional operations Add support for initiating unidirectional operations, that is, sending requests that do not require responses. Note that we already handle incoming unidirectional operations. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index bb89955..9fb7993 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -635,9 +635,10 @@ static void gb_operation_sync_callback(struct gb_operation *operation) * * The caller has filled in any payload so the request message is ready to go. * The callback function supplied will be called when the response message has - * arrived, or the operation is cancelled, indicating that the operation is - * complete. The callback function can fetch the result of the operation using - * gb_operation_result() if desired. + * arrived, a unidirectional request has been sent, or the operation is + * cancelled, indicating that the operation is complete. The callback function + * can fetch the result of the operation using gb_operation_result() if + * desired. * * Return: 0 if the request was successfully queued in the host-driver queues, * or a negative errno. @@ -653,6 +654,7 @@ int gb_operation_request_send(struct gb_operation *operation, if (!callback) return -EINVAL; + /* * Record the callback function, which is executed in * non-atomic (workqueue) context when the final result @@ -662,10 +664,15 @@ int gb_operation_request_send(struct gb_operation *operation, /* * Assign the operation's id, and store it in the request header. - * Zero is a reserved operation id. + * Zero is a reserved operation id for unidirectional operations. */ - cycle = (unsigned int)atomic_inc_return(&connection->op_cycle); - operation->id = (u16)(cycle % U16_MAX + 1); + if (gb_operation_is_unidirectional(operation)) { + operation->id = 0; + } else { + cycle = (unsigned int)atomic_inc_return(&connection->op_cycle); + operation->id = (u16)(cycle % U16_MAX + 1); + } + header = operation->request->header; header->operation_id = cpu_to_le16(operation->id); @@ -799,10 +806,11 @@ void greybus_message_sent(struct gb_host_device *hd, * reference to the operation. If an error occurred, report * it. * - * For requests, if there's no error, there's nothing more - * to do until the response arrives. If an error occurred - * attempting to send it, record that as the result of - * the operation and schedule its completion. + * For requests, if there's no error and the operation in not + * unidirectional, there's nothing more to do until the response + * arrives. If an error occurred attempting to send it, or if the + * operation is unidrectional, record the result of the operation and + * schedule its completion. */ if (message == operation->response) { if (status) { @@ -810,9 +818,10 @@ void greybus_message_sent(struct gb_host_device *hd, "%s: error sending response 0x%02x: %d\n", connection->name, operation->type, status); } + gb_operation_put_active(operation); gb_operation_put(operation); - } else if (status) { + } else if (status || gb_operation_is_unidirectional(operation)) { if (gb_operation_result_set(operation, status)) { queue_work(gb_operation_completion_wq, &operation->work); @@ -876,6 +885,13 @@ static void gb_connection_recv_response(struct gb_connection *connection, int errno = gb_operation_status_map(result); size_t message_size; + if (!operation_id) { + dev_err(&connection->hd->dev, + "%s: invalid response id 0 received\n", + connection->name); + return; + } + operation = gb_operation_find_outgoing(connection, operation_id); if (!operation) { dev_err(&connection->hd->dev, diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 38e5303..c88efe1 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -67,7 +67,8 @@ struct gb_message { #define GB_OPERATION_FLAG_UNIDIRECTIONAL BIT(1) #define GB_OPERATION_FLAG_SHORT_RESPONSE BIT(2) -#define GB_OPERATION_FLAG_USER_MASK GB_OPERATION_FLAG_SHORT_RESPONSE +#define GB_OPERATION_FLAG_USER_MASK (GB_OPERATION_FLAG_SHORT_RESPONSE | \ + GB_OPERATION_FLAG_UNIDIRECTIONAL) /* * A Greybus operation is a remote procedure call performed over a -- cgit v0.10.2 From 5fdc027d5441aecb94ce44de0402bdec3a731de8 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 29 Apr 2016 17:08:33 +0200 Subject: greybus: operation: add helper functions for unidirectional operations Add helper functions for initiating unidirectional operations and waiting for them to have been acknowledged as sent by the host device. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 9fb7993..fcae747 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -1090,6 +1090,53 @@ int gb_operation_sync_timeout(struct gb_connection *connection, int type, } EXPORT_SYMBOL_GPL(gb_operation_sync_timeout); +/** + * gb_operation_unidirectional_timeout() - initiate a unidirectional operation + * @connection: connection to use + * @type: type of operation to send + * @request: memory buffer to copy the request from + * @request_size: size of @request + * @timeout: send timeout in milliseconds + * + * Initiate a unidirectional operation by sending a request message and + * waiting for it to be acknowledged as sent by the host device. + * + * Note that successful send of a unidirectional operation does not imply that + * the request as actually reached the remote end of the connection. + */ +int gb_operation_unidirectional_timeout(struct gb_connection *connection, + int type, void *request, int request_size, + unsigned int timeout) +{ + struct gb_operation *operation; + int ret; + + if (request_size && !request) + return -EINVAL; + + operation = gb_operation_create_flags(connection, type, + request_size, 0, + GB_OPERATION_FLAG_UNIDIRECTIONAL, + GFP_KERNEL); + if (!operation) + return -ENOMEM; + + if (request_size) + memcpy(operation->request->payload, request, request_size); + + ret = gb_operation_request_send_sync_timeout(operation, timeout); + if (ret) { + dev_err(&connection->hd->dev, + "%s: unidirectional operation of type 0x%02x failed: %d\n", + connection->name, type, ret); + } + + gb_operation_put(operation); + + return ret; +} +EXPORT_SYMBOL_GPL(gb_operation_unidirectional_timeout); + int __init gb_operation_init(void) { gb_message_cache = kmem_cache_create("gb_message_cache", diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index c88efe1..8ef8f51 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -178,6 +178,9 @@ int gb_operation_sync_timeout(struct gb_connection *connection, int type, void *request, int request_size, void *response, int response_size, unsigned int timeout); +int gb_operation_unidirectional_timeout(struct gb_connection *connection, + int type, void *request, int request_size, + unsigned int timeout); static inline int gb_operation_sync(struct gb_connection *connection, int type, void *request, int request_size, @@ -188,6 +191,13 @@ static inline int gb_operation_sync(struct gb_connection *connection, int type, GB_OPERATION_TIMEOUT_DEFAULT); } +static inline int gb_operation_unidirectional(struct gb_connection *connection, + int type, void *request, int request_size) +{ + return gb_operation_unidirectional_timeout(connection, type, + request, request_size, GB_OPERATION_TIMEOUT_DEFAULT); +} + int gb_operation_init(void); void gb_operation_exit(void); -- cgit v0.10.2 From 1c3aead12ea4df73b7ae552aa4f4e83bc1f0baa6 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 29 Apr 2016 17:08:34 +0200 Subject: greybus: control: implement mode-switch operation Implement the unidirectional mode-switch operation. This operation will be used in the implementation of the new generic mode-switch functionality. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index 20aa366..1b28899 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -149,6 +149,13 @@ int gb_control_disconnected_operation(struct gb_control *control, u16 cport_id) sizeof(request), NULL, 0); } +int gb_control_mode_switch_operation(struct gb_control *control) +{ + return gb_operation_unidirectional(control->connection, + GB_CONTROL_TYPE_MODE_SWITCH, + NULL, 0); +} + int gb_control_get_interface_version_operation(struct gb_interface *intf) { struct gb_control_interface_version_response response; diff --git a/drivers/staging/greybus/control.h b/drivers/staging/greybus/control.h index 56fa259..f108bcc 100644 --- a/drivers/staging/greybus/control.h +++ b/drivers/staging/greybus/control.h @@ -36,6 +36,7 @@ void gb_control_put(struct gb_control *control); int gb_control_get_bundle_versions(struct gb_control *control); int gb_control_connected_operation(struct gb_control *control, u16 cport_id); int gb_control_disconnected_operation(struct gb_control *control, u16 cport_id); +int gb_control_mode_switch_operation(struct gb_control *control); int gb_control_get_manifest_size_operation(struct gb_interface *intf); int gb_control_get_manifest_operation(struct gb_interface *intf, void *manifest, size_t size); diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 713b569..c074402 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -123,6 +123,7 @@ struct gb_protocol_version_response { #define GB_CONTROL_TYPE_TIMESYNC_AUTHORITATIVE 0x09 #define GB_CONTROL_TYPE_INTERFACE_VERSION 0x0a #define GB_CONTROL_TYPE_BUNDLE_VERSION 0x0b +#define GB_CONTROL_TYPE_MODE_SWITCH 0x0e struct gb_control_version_request { __u8 major; -- cgit v0.10.2 From b1f8bfea65183b4575e3dde64641f7340a3dfa38 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 29 Apr 2016 17:08:35 +0200 Subject: greybus: loopback: remove unsupported version request Remove the unsupported version request from the loopback-driver request handler. Unsupported requests are already handled and logged using the default case. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 5e009e1..ccb2799 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -800,9 +800,6 @@ static int gb_loopback_request_handler(struct gb_operation *operation) /* By convention, the AP initiates the version operation */ switch (operation->type) { - case GB_REQUEST_TYPE_PROTOCOL_VERSION: - dev_err(dev, "module-initiated version operation\n"); - return -EINVAL; case GB_LOOPBACK_TYPE_PING: case GB_LOOPBACK_TYPE_SINK: return 0; -- cgit v0.10.2 From a2cf2e594626ce8c1e6944f6a44a7d481b84b82d Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 29 Apr 2016 17:08:36 +0200 Subject: greybus: svc: define the version request Define the SVC version request, which need not need to stay the same as the legacy version request. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index c074402..07988fb 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -781,6 +781,7 @@ struct gb_spi_transfer_response { #define GB_SVC_VERSION_MINOR 0x01 /* Greybus SVC request types */ +#define GB_SVC_TYPE_PROTOCOL_VERSION 0x01 #define GB_SVC_TYPE_SVC_HELLO 0x02 #define GB_SVC_TYPE_INTF_DEVICE_ID 0x03 #define GB_SVC_TYPE_INTF_HOTPLUG 0x04 @@ -808,10 +809,15 @@ struct gb_spi_transfer_response { #define GB_SVC_TYPE_INTF_ACTIVATE 0x27 #define GB_SVC_TYPE_INTF_MAILBOX_EVENT 0x29 -/* - * SVC version request/response has the same payload as - * gb_protocol_version_request/response. - */ +struct gb_svc_version_request { + __u8 major; + __u8 minor; +} __packed; + +struct gb_svc_version_response { + __u8 major; + __u8 minor; +} __packed; /* SVC protocol hello request */ struct gb_svc_hello_request { diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 78fe4dc..577e680 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -465,8 +465,8 @@ static int gb_svc_version_request(struct gb_operation *op) { struct gb_connection *connection = op->connection; struct gb_svc *svc = gb_connection_get_data(connection); - struct gb_protocol_version_request *request; - struct gb_protocol_version_response *response; + struct gb_svc_version_request *request; + struct gb_svc_version_response *response; if (op->request->payload_size < sizeof(*request)) { dev_err(&svc->dev, "short version request (%zu < %zu)\n", @@ -1192,7 +1192,7 @@ static int gb_svc_request_handler(struct gb_operation *op) * need to protect 'state' for any races. */ switch (type) { - case GB_REQUEST_TYPE_PROTOCOL_VERSION: + case GB_SVC_TYPE_PROTOCOL_VERSION: if (svc->state != GB_SVC_STATE_RESET) ret = -EINVAL; break; @@ -1213,7 +1213,7 @@ static int gb_svc_request_handler(struct gb_operation *op) } switch (type) { - case GB_REQUEST_TYPE_PROTOCOL_VERSION: + case GB_SVC_TYPE_PROTOCOL_VERSION: ret = gb_svc_version_request(op); if (!ret) svc->state = GB_SVC_STATE_PROTOCOL_VERSION; -- cgit v0.10.2 From 7adb32b429ce38bae39e277ae2cc37c93770104f Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 29 Apr 2016 17:08:37 +0200 Subject: greybus: operation: fix definition of the invalid type The invalid request type has been redefined as 0x7f. Also remove the redundant redefinition of the invalid type from the operation header. Note that operation type 0x00 has been repurposed for the new generic ping operation, which will be used to implement proper connection tear down. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 07988fb..f1e8b34 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -95,9 +95,9 @@ struct gb_operation_msg_hdr { } __packed; -/* Generic request numbers supported by all modules */ -#define GB_REQUEST_TYPE_INVALID 0x00 +/* Generic request types */ #define GB_REQUEST_TYPE_PROTOCOL_VERSION 0x01 +#define GB_REQUEST_TYPE_INVALID 0x7f struct gb_protocol_version_request { __u8 major; diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index fcae747..e7e9b0e 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -282,10 +282,10 @@ static void gb_operation_message_init(struct gb_host_device *hd, /* * The type supplied for incoming message buffers will be - * 0x00. Such buffers will be overwritten by arriving data - * so there's no need to initialize the message header. + * GB_REQUEST_TYPE_INVALID. Such buffers will be overwritten by + * arriving data so there's no need to initialize the message header. */ - if (type != GB_OPERATION_TYPE_INVALID) { + if (type != GB_REQUEST_TYPE_INVALID) { u16 message_size = (u16)(sizeof(*header) + payload_size); /* @@ -536,7 +536,7 @@ gb_operation_create_flags(struct gb_connection *connection, size_t response_size, unsigned long flags, gfp_t gfp) { - if (WARN_ON_ONCE(type == GB_OPERATION_TYPE_INVALID)) + if (WARN_ON_ONCE(type == GB_REQUEST_TYPE_INVALID)) return NULL; if (WARN_ON_ONCE(type & GB_MESSAGE_TYPE_RESPONSE)) type &= ~GB_MESSAGE_TYPE_RESPONSE; @@ -573,7 +573,9 @@ gb_operation_create_incoming(struct gb_connection *connection, u16 id, flags |= GB_OPERATION_FLAG_UNIDIRECTIONAL; operation = gb_operation_create_common(connection, type, - request_size, 0, flags, GFP_ATOMIC); + request_size, + GB_REQUEST_TYPE_INVALID, + flags, GFP_ATOMIC); if (!operation) return NULL; diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 8ef8f51..117d7df 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -18,12 +18,6 @@ struct gb_operation; #define GB_OPERATION_TIMEOUT_DEFAULT 1000 /* milliseconds */ /* - * No protocol may define an operation that has numeric value 0x00. - * It is reserved as an explicitly invalid value. - */ -#define GB_OPERATION_TYPE_INVALID ((u8)0x00) - -/* * The top bit of the type in an operation message header indicates * whether the message is a request (bit clear) or response (bit set) */ -- cgit v0.10.2 From cca22207673896262443c72f19b049552d65f88e Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 28 Apr 2016 10:06:38 +0530 Subject: greybus: firmware: Add firmware-download protocol driver This patch adds Firmware Download Protocol support to firmware core, which allows an Interface to download a firmware package over Unipro. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Jun Li <li_jun@projectara.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 1a120d9..43c0c99 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -39,7 +39,7 @@ gb-audio-apbridgea-y := audio_apbridgea.o gb-audio-manager-y += audio_manager.o gb-audio-manager-y += audio_manager_module.o gb-camera-y := camera.o -gb-firmware-y := fw-core.o +gb-firmware-y := fw-core.o fw-download.o obj-m += greybus.o obj-m += gb-phy.o diff --git a/drivers/staging/greybus/firmware.h b/drivers/staging/greybus/firmware.h new file mode 100644 index 0000000..c5736d5 --- /dev/null +++ b/drivers/staging/greybus/firmware.h @@ -0,0 +1,20 @@ +/* + * Greybus Firmware Management Header + * + * Copyright 2016 Google Inc. + * Copyright 2016 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#ifndef __FIRMWARE_H +#define __FIRMWARE_H + +#include "greybus.h" + +/* Firmware Download Protocol specific functions */ +int gb_fw_download_request_handler(struct gb_operation *op); +int gb_fw_download_connection_init(struct gb_connection *connection); +void gb_fw_download_connection_exit(struct gb_connection *connection); + +#endif /* __FIRMWARE_H */ diff --git a/drivers/staging/greybus/fw-core.c b/drivers/staging/greybus/fw-core.c index 4720d59..a686527 100644 --- a/drivers/staging/greybus/fw-core.c +++ b/drivers/staging/greybus/fw-core.c @@ -9,9 +9,11 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/firmware.h> +#include "firmware.h" #include "greybus.h" struct gb_fw_core { + struct gb_connection *download_connection; struct gb_connection *mgmt_connection; }; @@ -52,11 +54,30 @@ static int gb_fw_core_probe(struct gb_bundle *bundle, dev_err(&bundle->dev, "failed to create management connection (%d)\n", ret); - goto err_free_fw_core; + goto err_destroy_connections; } fw_core->mgmt_connection = connection; break; + case GREYBUS_PROTOCOL_FW_DOWNLOAD: + /* Disallow multiple Firmware Download CPorts */ + if (fw_core->download_connection) { + dev_err(&bundle->dev, + "multiple download CPorts found\n"); + ret = -EINVAL; + goto err_destroy_connections; + } + + connection = gb_connection_create(bundle, cport_id, + gb_fw_download_request_handler); + if (IS_ERR(connection)) { + dev_err(&bundle->dev, "failed to create download connection (%ld)\n", + PTR_ERR(connection)); + } else { + fw_core->download_connection = connection; + } + + break; default: dev_err(&bundle->dev, "invalid protocol id (0x%02x)\n", protocol_id); @@ -69,7 +90,16 @@ static int gb_fw_core_probe(struct gb_bundle *bundle, if (!fw_core->mgmt_connection) { dev_err(&bundle->dev, "missing management connection\n"); ret = -ENODEV; - goto err_free_fw_core; + goto err_destroy_connections; + } + + ret = gb_fw_download_connection_init(fw_core->download_connection); + if (ret) { + /* We may still be able to work with the Interface */ + dev_err(&bundle->dev, "failed to initialize firmware download connection, disable it (%d)\n", + ret); + gb_connection_destroy(fw_core->download_connection); + fw_core->download_connection = NULL; } greybus_set_drvdata(bundle, fw_core); @@ -77,6 +107,7 @@ static int gb_fw_core_probe(struct gb_bundle *bundle, return 0; err_destroy_connections: + gb_connection_destroy(fw_core->download_connection); gb_connection_destroy(fw_core->mgmt_connection); err_free_fw_core: kfree(fw_core); @@ -88,6 +119,8 @@ static void gb_fw_core_disconnect(struct gb_bundle *bundle) { struct gb_fw_core *fw_core = greybus_get_drvdata(bundle); + gb_fw_download_connection_exit(fw_core->download_connection); + gb_connection_destroy(fw_core->download_connection); gb_connection_destroy(fw_core->mgmt_connection); kfree(fw_core); diff --git a/drivers/staging/greybus/fw-download.c b/drivers/staging/greybus/fw-download.c new file mode 100644 index 0000000..836b02b --- /dev/null +++ b/drivers/staging/greybus/fw-download.c @@ -0,0 +1,299 @@ +/* + * Greybus Firmware Download Protocol Driver. + * + * Copyright 2016 Google Inc. + * Copyright 2016 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include <linux/firmware.h> +#include "firmware.h" +#include "greybus.h" + +struct fw_request { + u8 firmware_id; + char name[56]; /* ara_%08x_%08x_%08x_%08x_%s.tftf */ + const struct firmware *fw; + struct list_head node; +}; + +struct fw_download { + struct device *parent; + struct gb_connection *connection; + struct list_head fw_requests; + struct ida id_map; +}; + +static struct fw_request *match_firmware(struct fw_download *fw_download, + u8 firmware_id) +{ + struct fw_request *fw_req; + + list_for_each_entry(fw_req, &fw_download->fw_requests, node) { + if (fw_req->firmware_id == firmware_id) + return fw_req; + } + + return NULL; +} + +static void free_firmware(struct fw_download *fw_download, + struct fw_request *fw_req) +{ + list_del(&fw_req->node); + release_firmware(fw_req->fw); + ida_simple_remove(&fw_download->id_map, fw_req->firmware_id); + kfree(fw_req); +} + +/* This returns path of the firmware blob on the disk */ +static struct fw_request *find_firmware(struct fw_download *fw_download, + const char *tag) +{ + struct gb_interface *intf = fw_download->connection->bundle->intf; + struct fw_request *fw_req; + int ret; + + fw_req = kzalloc(sizeof(*fw_req), GFP_KERNEL); + if (!fw_req) + return ERR_PTR(-ENOMEM); + + /* Allocate ids from 1 to 255 (u8-max), 0 is an invalid id */ + ret = ida_simple_get(&fw_download->id_map, 1, 256, GFP_KERNEL); + if (ret < 0) { + dev_err(fw_download->parent, + "failed to allocate firmware id (%d)\n", ret); + goto err_free_req; + } + fw_req->firmware_id = ret; + + snprintf(fw_req->name, sizeof(fw_req->name), + "ara_%08x_%08x_%08x_%08x_%s.tftf", + intf->ddbl1_manufacturer_id, intf->ddbl1_product_id, + intf->vendor_id, intf->product_id, tag); + + dev_info(fw_download->parent, "Requested firmware package '%s'\n", + fw_req->name); + + ret = request_firmware(&fw_req->fw, fw_req->name, fw_download->parent); + if (ret) { + dev_err(fw_download->parent, + "firmware request failed for %s (%d)\n", fw_req->name, + ret); + goto err_free_id; + } + + list_add(&fw_req->node, &fw_download->fw_requests); + + return fw_req; + +err_free_id: + ida_simple_remove(&fw_download->id_map, fw_req->firmware_id); +err_free_req: + kfree(fw_req); + + return ERR_PTR(ret); +} + +static int fw_download_find_firmware(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct fw_download *fw_download = gb_connection_get_data(connection); + struct gb_fw_download_find_firmware_request *request; + struct gb_fw_download_find_firmware_response *response; + struct fw_request *fw_req; + const char *tag; + + if (op->request->payload_size != sizeof(*request)) { + dev_err(fw_download->parent, + "illegal size of find firmware request (%zu != %zu)\n", + op->request->payload_size, sizeof(*request)); + return -EINVAL; + } + + request = op->request->payload; + tag = (const char *)(request->firmware_tag); + + /* firmware_tag should be null-terminated */ + if (strnlen(tag, GB_FIRMWARE_TAG_MAX_LEN) == GB_FIRMWARE_TAG_MAX_LEN) { + dev_err(fw_download->parent, + "firmware-tag is not null-terminated\n"); + return -EINVAL; + } + + fw_req = find_firmware(fw_download, request->firmware_tag); + if (IS_ERR(fw_req)) + return PTR_ERR(fw_req); + + if (!gb_operation_response_alloc(op, sizeof(*response), GFP_KERNEL)) { + dev_err(fw_download->parent, "error allocating response\n"); + free_firmware(fw_download, fw_req); + return -ENOMEM; + } + + response = op->response->payload; + response->firmware_id = fw_req->firmware_id; + response->size = cpu_to_le32(fw_req->fw->size); + + dev_dbg(fw_download->parent, + "firmware size is %zu bytes\n", fw_req->fw->size); + + return 0; +} + +static int fw_download_fetch_firmware(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct fw_download *fw_download = gb_connection_get_data(connection); + struct gb_fw_download_fetch_firmware_request *request; + struct gb_fw_download_fetch_firmware_response *response; + struct fw_request *fw_req; + const struct firmware *fw; + unsigned int offset, size; + u8 firmware_id; + + if (op->request->payload_size != sizeof(*request)) { + dev_err(fw_download->parent, + "Illegal size of fetch firmware request (%zu %zu)\n", + op->request->payload_size, sizeof(*request)); + return -EINVAL; + } + + request = op->request->payload; + offset = le32_to_cpu(request->offset); + size = le32_to_cpu(request->size); + firmware_id = request->firmware_id; + + fw_req = match_firmware(fw_download, firmware_id); + if (!fw_req) { + dev_err(fw_download->parent, + "firmware not available for id: %02u\n", firmware_id); + return -EINVAL; + } + + fw = fw_req->fw; + + if (offset >= fw->size || size > fw->size - offset) { + dev_err(fw_download->parent, + "bad fetch firmware request (offs = %u, size = %u)\n", + offset, size); + return -EINVAL; + } + + if (!gb_operation_response_alloc(op, sizeof(*response) + size, + GFP_KERNEL)) { + dev_err(fw_download->parent, + "error allocating fetch firmware response\n"); + return -ENOMEM; + } + + response = op->response->payload; + memcpy(response->data, fw->data + offset, size); + + dev_dbg(fw_download->parent, + "responding with firmware (offs = %u, size = %u)\n", offset, + size); + + return 0; +} + +static int fw_download_release_firmware(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct fw_download *fw_download = gb_connection_get_data(connection); + struct gb_fw_download_release_firmware_request *request; + struct fw_request *fw_req; + u8 firmware_id; + + if (op->request->payload_size != sizeof(*request)) { + dev_err(fw_download->parent, + "Illegal size of release firmware request (%zu %zu)\n", + op->request->payload_size, sizeof(*request)); + return -EINVAL; + } + + request = op->request->payload; + firmware_id = request->firmware_id; + + fw_req = match_firmware(fw_download, firmware_id); + if (!fw_req) { + dev_err(fw_download->parent, + "firmware not available for id: %02u\n", firmware_id); + return -EINVAL; + } + + free_firmware(fw_download, fw_req); + + dev_dbg(fw_download->parent, "release firmware\n"); + + return 0; +} + +int gb_fw_download_request_handler(struct gb_operation *op) +{ + u8 type = op->type; + + switch (type) { + case GB_FW_DOWNLOAD_TYPE_FIND_FIRMWARE: + return fw_download_find_firmware(op); + case GB_FW_DOWNLOAD_TYPE_FETCH_FIRMWARE: + return fw_download_fetch_firmware(op); + case GB_FW_DOWNLOAD_TYPE_RELEASE_FIRMWARE: + return fw_download_release_firmware(op); + default: + dev_err(&op->connection->bundle->dev, + "unsupported request: %u\n", type); + return -EINVAL; + } +} + +int gb_fw_download_connection_init(struct gb_connection *connection) +{ + struct fw_download *fw_download; + int ret; + + if (!connection) + return 0; + + fw_download = kzalloc(sizeof(*fw_download), GFP_KERNEL); + if (!fw_download) + return -ENOMEM; + + fw_download->parent = &connection->bundle->dev; + INIT_LIST_HEAD(&fw_download->fw_requests); + ida_init(&fw_download->id_map); + gb_connection_set_data(connection, fw_download); + fw_download->connection = connection; + + ret = gb_connection_enable(connection); + if (ret) + goto err_destroy_id_map; + + return 0; + +err_destroy_id_map: + ida_destroy(&fw_download->id_map); + kfree(fw_download); + + return ret; +} + +void gb_fw_download_connection_exit(struct gb_connection *connection) +{ + struct fw_download *fw_download; + struct fw_request *fw_req, *tmp; + + if (!connection) + return; + + fw_download = gb_connection_get_data(connection); + gb_connection_disable(fw_download->connection); + + /* Release pending firmware packages */ + list_for_each_entry_safe(fw_req, tmp, &fw_download->fw_requests, node) + free_firmware(fw_download, fw_req); + + ida_destroy(&fw_download->id_map); + kfree(fw_download); +} diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index f1e8b34..b73acc0 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -213,6 +213,43 @@ struct gb_control_timesync_authoritative_request { #define GB_APB_REQUEST_CPORT_FEAT_EN 0x0b #define GB_APB_REQUEST_CPORT_FEAT_DIS 0x0c +/* Firmware Download Protocol */ + +/* Request Types */ +#define GB_FW_DOWNLOAD_TYPE_FIND_FIRMWARE 0x01 +#define GB_FW_DOWNLOAD_TYPE_FETCH_FIRMWARE 0x02 +#define GB_FW_DOWNLOAD_TYPE_RELEASE_FIRMWARE 0x03 + +#define GB_FIRMWARE_TAG_MAX_LEN 10 + +/* firmware download find firmware request/response */ +struct gb_fw_download_find_firmware_request { + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_LEN]; +} __packed; + +struct gb_fw_download_find_firmware_response { + __u8 firmware_id; + __le32 size; +} __packed; + +/* firmware download fetch firmware request/response */ +struct gb_fw_download_fetch_firmware_request { + __u8 firmware_id; + __le32 offset; + __le32 size; +} __packed; + +struct gb_fw_download_fetch_firmware_response { + __u8 data[0]; +} __packed; + +/* firmware download release firmware request */ +struct gb_fw_download_release_firmware_request { + __u8 firmware_id; +} __packed; +/* firmware download release firmware response has no payload */ + + /* Bootrom Protocol */ /* Version of the Greybus bootrom protocol we support */ -- cgit v0.10.2 From 7557d0481bdeed86780c073e591df0330ec88a9e Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 2 May 2016 10:51:49 +0530 Subject: greybus: fw-download: Create a macro for length of firmware file's name Create a macro representing the length of the firmware file's name and use that instead of using magic number in the code. Suggested-by: Greg Kroah-Hartman <gregkh@google.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/fw-download.c b/drivers/staging/greybus/fw-download.c index 836b02b..e60abde 100644 --- a/drivers/staging/greybus/fw-download.c +++ b/drivers/staging/greybus/fw-download.c @@ -11,9 +11,12 @@ #include "firmware.h" #include "greybus.h" +/* Length of the string in format: ara_%08x_%08x_%08x_%08x_%s.tftf */ +#define FW_NAME_LEN 56 + struct fw_request { u8 firmware_id; - char name[56]; /* ara_%08x_%08x_%08x_%08x_%s.tftf */ + char name[FW_NAME_LEN]; const struct firmware *fw; struct list_head node; }; -- cgit v0.10.2 From 84e0e38744c5d814650e4acec34cea585d04cc96 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Wed, 4 May 2016 16:29:19 +0530 Subject: greybus: audio:gb_manager: Use proper locking around kobject_xxx read/write_lock_irqsave mechanism was used to protect modules list & kobject_xxx() in gb_audio_manager. Since kobject_xxx calls can sleep spin_lock variants can't be used there. So use rw_sem for protecting modules_list. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_manager.c b/drivers/staging/greybus/audio_manager.c index bc5be49..619bdee 100644 --- a/drivers/staging/greybus/audio_manager.c +++ b/drivers/staging/greybus/audio_manager.c @@ -19,7 +19,7 @@ static struct kset *manager_kset; static LIST_HEAD(modules_list); -static DEFINE_RWLOCK(modules_lock); +static DECLARE_RWSEM(modules_rwsem); static DEFINE_IDA(module_id); /* helpers */ @@ -42,7 +42,6 @@ static struct gb_audio_manager_module *gb_audio_manager_get_locked(int id) int gb_audio_manager_add(struct gb_audio_manager_module_descriptor *desc) { struct gb_audio_manager_module *module; - unsigned long flags; int id; int err; @@ -55,9 +54,9 @@ int gb_audio_manager_add(struct gb_audio_manager_module_descriptor *desc) } /* Add it to the list */ - write_lock_irqsave(&modules_lock, flags); + down_write(&modules_rwsem); list_add_tail(&module->list, &modules_list); - write_unlock_irqrestore(&modules_lock, flags); + up_write(&modules_rwsem); return module->id; } @@ -66,20 +65,18 @@ EXPORT_SYMBOL_GPL(gb_audio_manager_add); int gb_audio_manager_remove(int id) { struct gb_audio_manager_module *module; - unsigned long flags; - write_lock_irqsave(&modules_lock, flags); + down_write(&modules_rwsem); module = gb_audio_manager_get_locked(id); if (!module) { - write_unlock_irqrestore(&modules_lock, flags); + up_write(&modules_rwsem); return -EINVAL; } - - ida_simple_remove(&module_id, module->id); list_del(&module->list); kobject_put(&module->kobj); - write_unlock_irqrestore(&modules_lock, flags); + up_write(&modules_rwsem); + ida_simple_remove(&module_id, module->id); return 0; } EXPORT_SYMBOL_GPL(gb_audio_manager_remove); @@ -88,9 +85,8 @@ void gb_audio_manager_remove_all(void) { struct gb_audio_manager_module *module, *next; int is_empty = 1; - unsigned long flags; - write_lock_irqsave(&modules_lock, flags); + down_write(&modules_rwsem); list_for_each_entry_safe(module, next, &modules_list, list) { list_del(&module->list); @@ -99,7 +95,7 @@ void gb_audio_manager_remove_all(void) is_empty = list_empty(&modules_list); - write_unlock_irqrestore(&modules_lock, flags); + up_write(&modules_rwsem); if (!is_empty) pr_warn("Not all nodes were deleted\n"); @@ -109,12 +105,11 @@ EXPORT_SYMBOL_GPL(gb_audio_manager_remove_all); struct gb_audio_manager_module *gb_audio_manager_get_module(int id) { struct gb_audio_manager_module *module; - unsigned long flags; - read_lock_irqsave(&modules_lock, flags); + down_read(&modules_rwsem); module = gb_audio_manager_get_locked(id); kobject_get(&module->kobj); - read_unlock_irqrestore(&modules_lock, flags); + up_read(&modules_rwsem); return module; } EXPORT_SYMBOL_GPL(gb_audio_manager_get_module); @@ -128,11 +123,10 @@ EXPORT_SYMBOL_GPL(gb_audio_manager_put_module); int gb_audio_manager_dump_module(int id) { struct gb_audio_manager_module *module; - unsigned long flags; - read_lock_irqsave(&modules_lock, flags); + down_read(&modules_rwsem); module = gb_audio_manager_get_locked(id); - read_unlock_irqrestore(&modules_lock, flags); + up_read(&modules_rwsem); if (!module) return -EINVAL; @@ -146,14 +140,13 @@ void gb_audio_manager_dump_all(void) { struct gb_audio_manager_module *module; int count = 0; - unsigned long flags; - read_lock_irqsave(&modules_lock, flags); + down_read(&modules_rwsem); list_for_each_entry(module, &modules_list, list) { gb_audio_manager_module_dump(module); count++; } - read_unlock_irqrestore(&modules_lock, flags); + up_read(&modules_rwsem); pr_info("Number of connected modules: %d\n", count); } -- cgit v0.10.2 From e6ab7a154c5dbfc0ad08bf1570efea22f2c7ee6c Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Wed, 4 May 2016 16:29:20 +0530 Subject: greybus: audio: Cleanup GB Audio bundle driver. Remove unnecessary lock & list maintained in GB audio bundle driver Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_module.c b/drivers/staging/greybus/audio_module.c index 05bda48..1e29901 100644 --- a/drivers/staging/greybus/audio_module.c +++ b/drivers/staging/greybus/audio_module.c @@ -14,9 +14,6 @@ #include "audio_apbridgea.h" #include "audio_manager.h" -static DEFINE_MUTEX(gb_codec_list_lock); -static LIST_HEAD(gb_codec_list); - /* * gb_snd management functions */ @@ -241,16 +238,13 @@ static int gb_audio_probe(struct gb_bundle *bundle, if (bundle->num_cports < 2) return -ENODEV; - mutex_lock(&gb_codec_list_lock); /* * There can be only one Management connection and any number of data * connections. */ gbmodule = devm_kzalloc(dev, sizeof(*gbmodule), GFP_KERNEL); - if (!gbmodule) { - mutex_unlock(&gb_codec_list_lock); + if (!gbmodule) return -ENOMEM; - } gbmodule->num_data_connections = bundle->num_cports - 1; mutex_init(&gbmodule->lock); @@ -348,7 +342,6 @@ static int gb_audio_probe(struct gb_bundle *bundle, gbmodule->manager_id = gb_audio_manager_add(&desc); dev_dbg(dev, "Add GB Audio device:%s\n", gbmodule->name); - mutex_unlock(&gb_codec_list_lock); return 0; @@ -378,7 +371,6 @@ destroy_connections: gb_connection_destroy(gbmodule->mgmt_connection); devm_kfree(dev, gbmodule); - mutex_unlock(&gb_codec_list_lock); return ret; } @@ -388,8 +380,6 @@ static void gb_audio_disconnect(struct gb_bundle *bundle) struct gbaudio_module_info *gbmodule = greybus_get_drvdata(bundle); struct gbaudio_data_connection *dai, *_dai; - mutex_lock(&gb_codec_list_lock); - gbaudio_unregister_module(gbmodule); /* inform uevent to above layers */ @@ -409,7 +399,6 @@ static void gb_audio_disconnect(struct gb_bundle *bundle) gbmodule->mgmt_connection = NULL; devm_kfree(&bundle->dev, gbmodule); - mutex_unlock(&gb_codec_list_lock); } static const struct greybus_bundle_id gb_audio_id_table[] = { -- cgit v0.10.2 From 852859ab8186e7a492fdec5db5ef219bf625c21a Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Wed, 4 May 2016 16:29:21 +0530 Subject: greybus: audio: Remove redundant lock protection & is_connected field Each module maintains connected status & a lock to protect it. Using codec->lock we can safely serialize ASoC specific callbacks (in response to mixer_ctl update or dai_ops) and gb module disconnect. Thus is_connected field can be removed. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 7a9abbf..c50720e 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -60,7 +60,6 @@ static int gbaudio_module_disable(struct gbaudio_codec_info *codec, dai_name = codec->stream[dir].dai_name; - mutex_lock(&module->lock); module_state = module->ctrlstate[dir]; if (module_state == GBAUDIO_CODEC_SHUTDOWN) { dev_dbg(codec->dev, "%s: module already configured\n", @@ -129,7 +128,6 @@ static int gbaudio_module_disable(struct gbaudio_codec_info *codec, module->ctrlstate[dir] = GBAUDIO_CODEC_SHUTDOWN; func_exit: - mutex_unlock(&module->lock); mutex_unlock(&codec->lock); return ret; } @@ -160,7 +158,6 @@ static int gbaudio_module_enable(struct gbaudio_codec_info *codec, rate = codec->stream[dir].rate; sig_bits = codec->stream[dir].sig_bits; - mutex_lock(&module->lock); module_state = module->ctrlstate[dir]; if (module_state == codec_state) { dev_dbg(codec->dev, "%s: module already configured\n", @@ -272,7 +269,6 @@ static int gbaudio_module_enable(struct gbaudio_codec_info *codec, func_exit: module->ctrlstate[dir] = module_state; - mutex_unlock(&module->lock); mutex_unlock(&codec->lock); return ret; } @@ -342,18 +338,11 @@ static int gbcodec_startup(struct snd_pcm_substream *substream, state = codec->stream[substream->stream].state; list_for_each_entry(module, &codec->module_list, list) { - mutex_lock(&module->lock); - if (!module->is_connected) { - mutex_unlock(&module->lock); - continue; - } - /* find the dai */ data = find_data(module, dai->name); if (!data) { dev_err(dai->dev, "%s:%s DATA connection missing\n", dai->name, module->name); - mutex_unlock(&module->lock); continue; } @@ -375,7 +364,6 @@ static int gbcodec_startup(struct snd_pcm_substream *substream, break; default: dev_err(dai->dev, "Inavlid stream\n"); - mutex_unlock(&module->lock); mutex_unlock(&codec->lock); return -EINVAL; } @@ -384,7 +372,6 @@ static int gbcodec_startup(struct snd_pcm_substream *substream, state = GBAUDIO_CODEC_STARTUP; module->ctrlstate[substream->stream] = state; dev_dbg(dai->dev, "%s: state:%d\n", module->name, state); - mutex_unlock(&module->lock); } codec->stream[substream->stream].state = state; codec->stream[substream->stream].dai_name = dai->name; @@ -492,19 +479,11 @@ static void gbcodec_shutdown(struct snd_pcm_substream *substream, state = codec->stream[substream->stream].state; list_for_each_entry(module, &codec->module_list, list) { - mutex_lock(&module->lock); - if (!module->is_connected) { - dev_err(dai->dev, "%s:%s module not connected\n", - __func__, module->name); - mutex_unlock(&module->lock); - continue; - } /* find the dai */ data = find_data(module, dai->name); if (!data) { dev_err(dai->dev, "%s:%s DATA connection missing\n", dai->name, module->name); - mutex_unlock(&module->lock); continue; } @@ -523,7 +502,6 @@ static void gbcodec_shutdown(struct snd_pcm_substream *substream, state = GBAUDIO_CODEC_SHUTDOWN; module->ctrlstate[substream->stream] = state; dev_dbg(dai->dev, "%s: state:%d\n", module->name, state); - mutex_unlock(&module->lock); } codec->stream[substream->stream].state = state; codec->stream[substream->stream].dai_name = NULL; @@ -583,21 +561,11 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream, state = codec->stream[substream->stream].state; list_for_each_entry(module, &codec->module_list, list) { - mutex_lock(&module->lock); - if (!module->is_connected) { - dev_err(dai->dev, "%s:%s module not connected\n", - __func__, module->name); - ret = -ENODEV; - mutex_unlock(&module->lock); - continue; - } - /* find the data connection */ data = find_data(module, dai->name); if (!data) { dev_err(dai->dev, "%s:%s DATA connection missing\n", dai->name, module->name); - mutex_unlock(&module->lock); continue; } @@ -612,7 +580,6 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream, format, rate, channels, sig_bits); if (ret) { dev_err(dai->dev, "%d: Error during set_pcm\n", ret); - mutex_unlock(&module->lock); goto func_exit; } if (state < GBAUDIO_CODEC_HWPARAMS) { @@ -623,14 +590,12 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream, if (ret) { dev_err(dai->dev, "%d: Error during set_config\n", ret); - mutex_unlock(&module->lock); goto func_exit; } } state = GBAUDIO_CODEC_HWPARAMS; module->ctrlstate[substream->stream] = state; dev_dbg(dai->dev, "%s: state:%d\n", module->name, state); - mutex_unlock(&module->lock); } codec->stream[substream->stream].state = state; codec->stream[substream->stream].format = format; @@ -731,18 +696,11 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream, state = codec->stream[substream->stream].state; list_for_each_entry(module, &codec->module_list, list) { - mutex_lock(&module->lock); - if (!module->is_connected) { - mutex_unlock(&module->lock); - continue; - } - /* find the dai */ data = find_data(module, dai->name); if (!data) { dev_err(dai->dev, "%s:%s DATA connection missing\n", dai->name, module->name); - mutex_unlock(&module->lock); continue; } @@ -759,14 +717,12 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream, if (ret == -ENODEV) continue; if (ret) { - mutex_unlock(&module->lock); goto func_exit; } state = GBAUDIO_CODEC_PREPARE; module->ctrlstate[substream->stream] = state; dev_dbg(dai->dev, "%s: state:%d\n", module->name, state); - mutex_unlock(&module->lock); } codec->stream[substream->stream].state = state; @@ -824,12 +780,6 @@ static int gbcodec_trigger(struct snd_pcm_substream *substream, int cmd, } list_for_each_entry(module, &codec->module_list, list) { - mutex_lock(&module->lock); - if (!module->is_connected) { - mutex_unlock(&module->lock); - continue; - } - /* find the dai */ data = find_data(module, dai->name); if (data) @@ -839,7 +789,6 @@ static int gbcodec_trigger(struct snd_pcm_substream *substream, int cmd, dev_err(dai->dev, "%s:%s DATA connection missing\n", dai->name, module->name); ret = -ENODEV; - mutex_unlock(&module->lock); goto func_exit; } if (start && tx) { @@ -873,7 +822,6 @@ static int gbcodec_trigger(struct snd_pcm_substream *substream, int cmd, if (ret) dev_err(dai->dev, "%s:Error during %s stream:%d\n", module->name, start ? "Start" : "Stop", ret); - mutex_unlock(&module->lock); func_exit: mutex_unlock(&codec->lock); @@ -1118,7 +1066,6 @@ void gbaudio_unregister_module(struct gbaudio_module_info *module) down_write(&card->controls_rwsem); mutex_lock(&gbcodec->lock); dev_dbg(codec->dev, "Process Unregister %s module\n", module->name); - mutex_lock(&module->lock); #ifdef CONFIG_SND_JACK /* free jack devices for this module from codec->jack_list */ @@ -1133,7 +1080,6 @@ void gbaudio_unregister_module(struct gbaudio_module_info *module) gbaudio_codec_cleanup(module); - module->is_connected = 0; if (module->dapm_routes) { dev_dbg(codec->dev, "Removing %d routes\n", module->num_dapm_routes); @@ -1153,8 +1099,6 @@ void gbaudio_unregister_module(struct gbaudio_module_info *module) module->num_dapm_widgets); } - mutex_unlock(&module->lock); - list_del(&module->list); dev_dbg(codec->dev, "Unregistered %s module\n", module->name); diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index 6182b20..5a19467 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -172,8 +172,6 @@ struct gbaudio_module_info { struct snd_soc_jack button_jack; /* used by codec_ops */ - struct mutex lock; - int is_connected; int ctrlstate[2]; /* PB/CAP */ /* connection info */ diff --git a/drivers/staging/greybus/audio_module.c b/drivers/staging/greybus/audio_module.c index 1e29901..3b76371 100644 --- a/drivers/staging/greybus/audio_module.c +++ b/drivers/staging/greybus/audio_module.c @@ -26,12 +26,10 @@ static int gbaudio_request_jack(struct gbaudio_module_info *module, dev_warn(module->dev, "Jack Event received: type: %u, event: %u\n", req->jack_attribute, req->event); - mutex_lock(&module->lock); if (req->event == GB_AUDIO_JACK_EVENT_REMOVAL) { module->jack_type = 0; button_status = module->button_status; module->button_status = 0; - mutex_unlock(&module->lock); if (button_status) snd_soc_jack_report(&module->button_jack, 0, GBCODEC_JACK_BUTTON_MASK); @@ -48,7 +46,6 @@ static int gbaudio_request_jack(struct gbaudio_module_info *module, module->jack_type, report); module->jack_type = report; - mutex_unlock(&module->lock); snd_soc_jack_report(&module->headset_jack, report, GBCODEC_JACK_MASK); return 0; @@ -63,10 +60,8 @@ static int gbaudio_request_button(struct gbaudio_module_info *module, req->button_id, req->event); /* currently supports 4 buttons only */ - mutex_lock(&module->lock); if (!module->jack_type) { dev_err(module->dev, "Jack not present. Bogus event!!\n"); - mutex_unlock(&module->lock); return -EINVAL; } @@ -100,8 +95,6 @@ static int gbaudio_request_button(struct gbaudio_module_info *module, module->button_status = report; - mutex_unlock(&module->lock); - snd_soc_jack_report(&module->button_jack, report, GBCODEC_JACK_BUTTON_MASK); @@ -247,7 +240,6 @@ static int gb_audio_probe(struct gb_bundle *bundle, return -ENOMEM; gbmodule->num_data_connections = bundle->num_cports - 1; - mutex_init(&gbmodule->lock); INIT_LIST_HEAD(&gbmodule->data_list); INIT_LIST_HEAD(&gbmodule->widget_list); INIT_LIST_HEAD(&gbmodule->ctl_list); @@ -327,7 +319,6 @@ static int gb_audio_probe(struct gb_bundle *bundle, if (ret) goto disable_data_connection; } - gbmodule->is_connected = 1; /* inform above layer for uevent */ dev_dbg(dev, "Inform set_event:%d to above layer\n", 1); -- cgit v0.10.2 From bb9986ef6b311fb3f4de2150bd050c1d9e1d9d65 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Wed, 4 May 2016 16:29:22 +0530 Subject: greybus: audio: Reorganize sequence in GB audio bundle & codec driver Modify sequence of register_module & unregister_module in bundle driver. This would affect the uevent generated for above user space. Accordingly, we need to modify snd_soc_xxx sequence in register_module() in codec driver. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index c50720e..dbcff21 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -963,27 +963,27 @@ int gbaudio_register_module(struct gbaudio_module_info *module) /* card already instantiated, create widgets here only */ if (codec->card->instantiated) { - ret = snd_soc_dapm_new_widgets(&codec->dapm); - if (!ret) - snd_soc_dapm_link_component_dai_widgets(codec->card, - &codec->dapm); - } - + snd_soc_dapm_link_component_dai_widgets(codec->card, + &codec->dapm); #ifdef CONFIG_SND_JACK - /* register jack devices for this module from codec->jack_list */ - list_for_each_entry(jack, &codec->jack_list, list) { - if ((jack == &module->headset_jack) - || (jack == &module->button_jack)) - snd_device_register(codec->card->snd_card, jack->jack); - } + /* register jack devices for this module from codec->jack_list */ + list_for_each_entry(jack, &codec->jack_list, list) { + if ((jack == &module->headset_jack) + || (jack == &module->button_jack)) + snd_device_register(codec->card->snd_card, + jack->jack); + } #endif + } list_add(&module->list, &gbcodec->module_list); + if (codec->card->instantiated) + ret = snd_soc_dapm_new_widgets(&codec->dapm); dev_dbg(codec->dev, "Registered %s module\n", module->name); mutex_unlock(&gbcodec->lock); up_write(&card->controls_rwsem); - return 0; + return ret; } EXPORT_SYMBOL(gbaudio_register_module); @@ -1060,11 +1060,10 @@ void gbaudio_unregister_module(struct gbaudio_module_info *module) dev_dbg(codec->dev, "Unregister %s module\n", module->name); - /* complete widget processing, if ongoing */ - snd_soc_dapm_sync(&codec->dapm); - down_write(&card->controls_rwsem); mutex_lock(&gbcodec->lock); + gbaudio_codec_cleanup(module); + list_del(&module->list); dev_dbg(codec->dev, "Process Unregister %s module\n", module->name); #ifdef CONFIG_SND_JACK @@ -1078,8 +1077,6 @@ void gbaudio_unregister_module(struct gbaudio_module_info *module) } #endif - gbaudio_codec_cleanup(module); - if (module->dapm_routes) { dev_dbg(codec->dev, "Removing %d routes\n", module->num_dapm_routes); @@ -1099,7 +1096,6 @@ void gbaudio_unregister_module(struct gbaudio_module_info *module) module->num_dapm_widgets); } - list_del(&module->list); dev_dbg(codec->dev, "Unregistered %s module\n", module->name); mutex_unlock(&gbcodec->lock); diff --git a/drivers/staging/greybus/audio_module.c b/drivers/staging/greybus/audio_module.c index 3b76371..27e5ff1 100644 --- a/drivers/staging/greybus/audio_module.c +++ b/drivers/staging/greybus/audio_module.c @@ -308,18 +308,22 @@ static int gb_audio_probe(struct gb_bundle *bundle, } gbmodule->topology = topology; - /* register module with gbcodec */ - ret = gbaudio_register_module(gbmodule); - if (ret) - goto release_topology; - /* Initialize data connections */ list_for_each_entry(dai, &gbmodule->data_list, list) { ret = gb_connection_enable(dai->connection); - if (ret) + if (ret) { + dev_err(dev, + "%d:Error while enabling %d:data connection\n", + ret, dai->data_cport); goto disable_data_connection; + } } + /* register module with gbcodec */ + ret = gbaudio_register_module(gbmodule); + if (ret) + goto disable_data_connection; + /* inform above layer for uevent */ dev_dbg(dev, "Inform set_event:%d to above layer\n", 1); /* prepare for the audio manager */ @@ -339,9 +343,6 @@ static int gb_audio_probe(struct gb_bundle *bundle, disable_data_connection: list_for_each_entry_safe(dai, _dai, &gbmodule->data_list, list) gb_connection_disable(dai->connection); - gbaudio_unregister_module(gbmodule); - -release_topology: gbaudio_tplg_release(gbmodule); gbmodule->topology = NULL; @@ -371,11 +372,11 @@ static void gb_audio_disconnect(struct gb_bundle *bundle) struct gbaudio_module_info *gbmodule = greybus_get_drvdata(bundle); struct gbaudio_data_connection *dai, *_dai; - gbaudio_unregister_module(gbmodule); /* inform uevent to above layers */ gb_audio_manager_remove(gbmodule->manager_id); + gbaudio_unregister_module(gbmodule); gbaudio_tplg_release(gbmodule); gbmodule->topology = NULL; kfree(gbmodule->topology); -- cgit v0.10.2 From c188fdc8176a8cb18b5d81cccac590311251208e Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Wed, 4 May 2016 16:29:23 +0530 Subject: greybus: audio: Reduce codec->lock granularity Earlier codec->lock protects almost complete register/unregister module function. This can be reduced to specific operations. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index dbcff21..23dde70 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -933,20 +933,17 @@ int gbaudio_register_module(struct gbaudio_module_info *module) card = codec->card->snd_card; down_write(&card->controls_rwsem); - mutex_lock(&gbcodec->lock); if (module->num_dais) { dev_err(gbcodec->dev, "%d:DAIs not supported via gbcodec driver\n", module->num_dais); - mutex_unlock(&gbcodec->lock); up_write(&card->controls_rwsem); return -EINVAL; } ret = gbaudio_init_jack(module, codec); if (ret) { - mutex_unlock(&gbcodec->lock); up_write(&card->controls_rwsem); return ret; } @@ -976,12 +973,14 @@ int gbaudio_register_module(struct gbaudio_module_info *module) #endif } + mutex_lock(&gbcodec->lock); list_add(&module->list, &gbcodec->module_list); + mutex_unlock(&gbcodec->lock); + if (codec->card->instantiated) ret = snd_soc_dapm_new_widgets(&codec->dapm); dev_dbg(codec->dev, "Registered %s module\n", module->name); - mutex_unlock(&gbcodec->lock); up_write(&card->controls_rwsem); return ret; } @@ -1065,6 +1064,7 @@ void gbaudio_unregister_module(struct gbaudio_module_info *module) gbaudio_codec_cleanup(module); list_del(&module->list); dev_dbg(codec->dev, "Process Unregister %s module\n", module->name); + mutex_unlock(&gbcodec->lock); #ifdef CONFIG_SND_JACK /* free jack devices for this module from codec->jack_list */ @@ -1098,7 +1098,6 @@ void gbaudio_unregister_module(struct gbaudio_module_info *module) dev_dbg(codec->dev, "Unregistered %s module\n", module->name); - mutex_unlock(&gbcodec->lock); up_write(&card->controls_rwsem); } EXPORT_SYMBOL(gbaudio_unregister_module); -- cgit v0.10.2 From 0634874a584e8bd875a83850c656e5adefc53bde Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Wed, 4 May 2016 16:29:24 +0530 Subject: greybus: audio: Use standard API to set connections' private data Use standard API greybus_set_drvdata() while setting private data pointers for mgmt & data connection. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_module.c b/drivers/staging/greybus/audio_module.c index 27e5ff1..d2dd5b8 100644 --- a/drivers/staging/greybus/audio_module.c +++ b/drivers/staging/greybus/audio_module.c @@ -173,7 +173,7 @@ static int gb_audio_add_mgmt_connection(struct gbaudio_module_info *gbmodule, if (IS_ERR(connection)) return PTR_ERR(connection); - connection->private = gbmodule; + greybus_set_drvdata(bundle, gbmodule); gbmodule->mgmt_connection = connection; return 0; @@ -201,7 +201,7 @@ static int gb_audio_add_data_connection(struct gbaudio_module_info *gbmodule, return PTR_ERR(connection); } - connection->private = gbmodule; + greybus_set_drvdata(bundle, gbmodule); /* dai->name should be same as codec->dai_name */ strlcpy(dai->name, "greybus-apb1", NAME_SIZE); dai->data_cport = connection->intf_cport_id; -- cgit v0.10.2 From c81b1ec7853d083981b6edd1d7397d94b88dd597 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Tue, 3 May 2016 16:13:12 +0530 Subject: greybus: bootrom: Implement timeouts to detect Module failures Its possible that the Module may fail to download the next stage firmware, or to jump into it and boot into the new personality. We have already seen examples of both of these cases on EVT 1.5. This patch implements timeouts in the bootrom bundle driver, which now expects the next request from the Module to be received at the AP within 1 second of the previous request/response. The time interval can be increased later if required. The timeouts are added between: - AP_READY and FIRMWARE_SIZE operations - FIRMWARE_SIZE and GET_FIRMWARE operations - Two GET_FIRMWARE operations - GET_FIRMWARE and READY_TO_BOOT operations - READY_TO_BOOT operation and the call to the ->disconnect() event of the bootrom bundle (once the new hotplug request is received). The timeout for the last case is kept at 5 seconds right now (random value), as it may take a bit longer. Because 'bootrom->fw' can be accessed simultaneously (from timeout handler and incoming requests) and one of them can potentially free the '->fw' structure, a mutex is also added to take care of such races while accessing 'bootrom->fw' structure. Also note that the '!bootrom->fw' check is moved to free_firmware() routine. Tested on EVT 1.5, by faking errors on certain requests, so that the bootrom doesn't send any more requests. Normal case is working just fine for audio and GP modules. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/bootrom.c b/drivers/staging/greybus/bootrom.c index cf750be..baada45 100644 --- a/drivers/staging/greybus/bootrom.c +++ b/drivers/staging/greybus/bootrom.c @@ -8,24 +8,48 @@ */ #include <linux/firmware.h> +#include <linux/jiffies.h> +#include <linux/mutex.h> +#include <linux/timer.h> #include "bootrom.h" #include "greybus.h" +/* Timeout, in jiffies, within which the next request must be received */ +#define NEXT_REQ_TIMEOUT_J msecs_to_jiffies(1000) struct gb_bootrom { struct gb_connection *connection; const struct firmware *fw; u8 protocol_major; u8 protocol_minor; + struct timer_list timer; + struct mutex mutex; /* Protects bootrom->fw */ }; static void free_firmware(struct gb_bootrom *bootrom) { + if (!bootrom->fw) + return; + release_firmware(bootrom->fw); bootrom->fw = NULL; } +static void gb_bootrom_timedout(unsigned long data) +{ + struct gb_bootrom *bootrom = (struct gb_bootrom *)data; + struct device *dev = &bootrom->connection->bundle->dev; + + dev_err(dev, "Timed out waiting for request from the Module\n"); + + mutex_lock(&bootrom->mutex); + free_firmware(bootrom); + mutex_unlock(&bootrom->mutex); + + /* TODO: Power-off Module ? */ +} + /* * The es2 chip doesn't have VID/PID programmed into the hardware and we need to * hack that up to distinguish different modules and their firmware blobs. @@ -77,8 +101,7 @@ static int download_firmware(struct gb_bootrom *bootrom, u8 stage) int rc; /* Already have a firmware, free it */ - if (bootrom->fw) - free_firmware(bootrom); + free_firmware(bootrom); /* * Create firmware name @@ -114,25 +137,32 @@ static int gb_bootrom_firmware_size_request(struct gb_operation *op) struct device *dev = &op->connection->bundle->dev; int ret; + /* Disable timeouts */ + del_timer_sync(&bootrom->timer); + if (op->request->payload_size != sizeof(*size_request)) { dev_err(dev, "%s: illegal size of firmware size request (%zu != %zu)\n", __func__, op->request->payload_size, sizeof(*size_request)); - return -EINVAL; + ret = -EINVAL; + goto mod_timer; } + mutex_lock(&bootrom->mutex); + ret = download_firmware(bootrom, size_request->stage); if (ret) { dev_err(dev, "%s: failed to download firmware (%d)\n", __func__, ret); - return ret; + goto unlock; } if (!gb_operation_response_alloc(op, sizeof(*size_response), GFP_KERNEL)) { dev_err(dev, "%s: error allocating response\n", __func__); free_firmware(bootrom); - return -ENOMEM; + ret = -ENOMEM; + goto unlock; } size_response = op->response->payload; @@ -140,28 +170,44 @@ static int gb_bootrom_firmware_size_request(struct gb_operation *op) dev_dbg(dev, "%s: firmware size %d bytes\n", __func__, size_response->size); - return 0; +unlock: + mutex_unlock(&bootrom->mutex); + +mod_timer: + /* Refresh timeout */ + mod_timer(&bootrom->timer, jiffies + NEXT_REQ_TIMEOUT_J); + + return ret; } static int gb_bootrom_get_firmware(struct gb_operation *op) { struct gb_bootrom *bootrom = gb_connection_get_data(op->connection); - const struct firmware *fw = bootrom->fw; + const struct firmware *fw; struct gb_bootrom_get_firmware_request *firmware_request; struct gb_bootrom_get_firmware_response *firmware_response; struct device *dev = &op->connection->bundle->dev; unsigned int offset, size; + int ret = 0; + + /* Disable timeouts */ + del_timer_sync(&bootrom->timer); if (op->request->payload_size != sizeof(*firmware_request)) { dev_err(dev, "%s: Illegal size of get firmware request (%zu %zu)\n", __func__, op->request->payload_size, sizeof(*firmware_request)); - return -EINVAL; + ret = -EINVAL; + goto mod_timer; } + mutex_lock(&bootrom->mutex); + + fw = bootrom->fw; if (!fw) { dev_err(dev, "%s: firmware not available\n", __func__); - return -EINVAL; + ret = -EINVAL; + goto unlock; } firmware_request = op->request->payload; @@ -171,13 +217,15 @@ static int gb_bootrom_get_firmware(struct gb_operation *op) if (offset >= fw->size || size > fw->size - offset) { dev_warn(dev, "bad firmware request (offs = %u, size = %u)\n", offset, size); - return -EINVAL; + ret = -EINVAL; + goto unlock; } if (!gb_operation_response_alloc(op, sizeof(*firmware_response) + size, GFP_KERNEL)) { dev_err(dev, "%s: error allocating response\n", __func__); - return -ENOMEM; + ret = -ENOMEM; + goto unlock; } firmware_response = op->response->payload; @@ -186,36 +234,59 @@ static int gb_bootrom_get_firmware(struct gb_operation *op) dev_dbg(dev, "responding with firmware (offs = %u, size = %u)\n", offset, size); - return 0; +unlock: + mutex_unlock(&bootrom->mutex); + +mod_timer: + /* Refresh timeout */ + mod_timer(&bootrom->timer, jiffies + NEXT_REQ_TIMEOUT_J); + + return ret; } static int gb_bootrom_ready_to_boot(struct gb_operation *op) { struct gb_connection *connection = op->connection; + struct gb_bootrom *bootrom = gb_connection_get_data(connection); struct gb_bootrom_ready_to_boot_request *rtb_request; struct device *dev = &connection->bundle->dev; u8 status; + int ret = 0; + + /* Disable timeouts */ + del_timer_sync(&bootrom->timer); if (op->request->payload_size != sizeof(*rtb_request)) { dev_err(dev, "%s: Illegal size of ready to boot request (%zu %zu)\n", __func__, op->request->payload_size, sizeof(*rtb_request)); - return -EINVAL; + ret = -EINVAL; + goto mod_timer; } rtb_request = op->request->payload; status = rtb_request->status; /* Return error if the blob was invalid */ - if (status == GB_BOOTROM_BOOT_STATUS_INVALID) - return -EINVAL; + if (status == GB_BOOTROM_BOOT_STATUS_INVALID) { + ret = -EINVAL; + goto mod_timer; + } /* * XXX Should we return error for insecure firmware? */ dev_dbg(dev, "ready to boot: 0x%x, 0\n", status); - return 0; +mod_timer: + /* + * Refresh timeout, the Interface shall load the new personality and + * send a new hotplug request, which shall get rid of the bootrom + * connection. As that can take some time, increase the timeout a bit. + */ + mod_timer(&bootrom->timer, jiffies + 5 * NEXT_REQ_TIMEOUT_J); + + return ret; } static int gb_bootrom_request_handler(struct gb_operation *op) @@ -304,6 +375,11 @@ static int gb_bootrom_probe(struct gb_bundle *bundle, bootrom->connection = connection; + mutex_init(&bootrom->mutex); + init_timer(&bootrom->timer); + bootrom->timer.function = gb_bootrom_timedout; + bootrom->timer.data = (unsigned long)bootrom; + greybus_set_drvdata(bundle, bootrom); ret = gb_connection_enable_tx(connection); @@ -329,6 +405,9 @@ static int gb_bootrom_probe(struct gb_bundle *bundle, goto err_connection_disable; } + /* Refresh timeout */ + mod_timer(&bootrom->timer, jiffies + NEXT_REQ_TIMEOUT_J); + dev_dbg(&bundle->dev, "AP_READY sent\n"); return 0; @@ -351,9 +430,16 @@ static void gb_bootrom_disconnect(struct gb_bundle *bundle) gb_connection_disable(bootrom->connection); - /* Release firmware */ - if (bootrom->fw) - free_firmware(bootrom); + /* Disable timeouts */ + del_timer_sync(&bootrom->timer); + + /* + * Release firmware: + * + * As the connection and the timer are already disabled, we don't need + * to lock access to bootrom->fw here. + */ + free_firmware(bootrom); gb_connection_destroy(bootrom->connection); kfree(bootrom); -- cgit v0.10.2 From 3e29bcf4b148b8983dcb30faec0b59f681eabe9e Mon Sep 17 00:00:00 2001 From: Sandeep Patil <sspatil@google.com> Date: Wed, 4 May 2016 16:21:29 -0700 Subject: greybus: core: add MODULE uevent var for all control devices The new ctrl device under interface is missing a MODULE uevent var, add it. Testing Done: cat 'uevent' from ctrl device. $ cat 1-3.3.ctrl/uevent DEVTYPE=greybus_control BUS=1 MODULE=3 INTERFACE=3 GREYBUS_ID=fffe0001/ffee0011 Signed-off-by: Sandeep Patil <sspatil@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 70a66e2..3fdc405 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -103,6 +103,7 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) } else if (is_gb_control(dev)) { control = to_gb_control(dev); intf = control->intf; + module = intf->module; hd = intf->hd; } else if (is_gb_bundle(dev)) { bundle = to_gb_bundle(dev); -- cgit v0.10.2 From ee2f2074fdb20d4939c943d0372f3751d833dedf Mon Sep 17 00:00:00 2001 From: Mitchell Tasman <tasman@leaflabs.com> Date: Wed, 4 May 2016 17:30:23 -0400 Subject: greybus: svc: reconfig APBridgeA-Switch link to handle required load SW-4894, SW-4389, and share a common root cause, namely that the power-on reset configuration of the APBridgeA-Switch link of PWM Gear 1, 1 Lane, Slow Auto, is insufficient to handle some required traffic loads, such as 3 audio streams plus boot-over-UniPro or 4 audio streams. The correct long-term solution is to implement a UniPro Power Mode Manager as in that considers the demands placed on the network, and adjusts power modes accordingly. The present commit implements a short-term, brute-force hack to allow continued system testing: - Upon receiving an SVC HELLO request, schedule deferred work to reconfigure the APB1-Switch link to PWM G2, 1 lane, Slow Auto - When the Camera driver transitions a White Camera module from active to inactive, return the APB1-Switch link to PWM G2, 1 lane, Slow Auto The Camera driver already steps up the APBridgeA-Camera link speed while a camera module is active, which affords sufficient margin for simultaneous audio and hotplug activity, and the Camera driver already steps down the link speed thereafter: the change made by the present patch is simply to tweak the stepped-down power mode to match the new baseline configuration. Signed-off-by: Mitchell Tasman <tasman@leaflabs.com> Tested-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 956fbf0..ba76f56 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -131,9 +131,9 @@ static int gb_camera_set_intf_power_mode(struct gb_camera *gcam, u8 intf_id, ret = gb_svc_intf_set_power_mode(svc, intf_id, GB_SVC_UNIPRO_HS_SERIES_A, GB_SVC_UNIPRO_SLOW_AUTO_MODE, - 1, 2, + 2, 1, GB_SVC_UNIPRO_SLOW_AUTO_MODE, - 1, 2, + 2, 1, 0, 0); return ret; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 577e680..f3ee94e 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -23,6 +23,8 @@ struct gb_svc_deferred_request { }; +static int gb_svc_queue_deferred_request(struct gb_operation *operation); + static ssize_t endo_id_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -695,7 +697,7 @@ static int gb_svc_hello(struct gb_operation *op) gb_svc_debugfs_init(svc); - return 0; + return gb_svc_queue_deferred_request(op); } static struct gb_interface *gb_svc_interface_lookup(struct gb_svc *svc, @@ -754,6 +756,35 @@ static void gb_svc_intf_reenable(struct gb_svc *svc, struct gb_interface *intf) mutex_unlock(&intf->mutex); } +static void gb_svc_process_hello_deferred(struct gb_operation *operation) +{ + struct gb_connection *connection = operation->connection; + struct gb_svc *svc = gb_connection_get_data(connection); + int ret; + + /* + * XXX This is a hack/work-around to reconfigure the APBridgeA-Switch + * link to PWM G2, 1 Lane, Slow Auto, so that it has sufficient + * bandwidth for 3 audio streams plus boot-over-UniPro of a hot-plugged + * module. + * + * The code should be removed once SW-2217, Heuristic for UniPro + * Power Mode Changes is resolved. + */ + ret = gb_svc_intf_set_power_mode(svc, svc->ap_intf_id, + GB_SVC_UNIPRO_HS_SERIES_A, + GB_SVC_UNIPRO_SLOW_AUTO_MODE, + 2, 1, + GB_SVC_UNIPRO_SLOW_AUTO_MODE, + 2, 1, + 0, 0); + + if (ret) + dev_warn(&svc->dev, + "power mode change failed on AP to switch link: %d\n", + ret); +} + static void gb_svc_process_intf_hotplug(struct gb_operation *operation) { struct gb_svc_intf_hotplug_request *request; @@ -963,6 +994,9 @@ static void gb_svc_process_deferred_request(struct work_struct *work) type = operation->request->header->type; switch (type) { + case GB_SVC_TYPE_SVC_HELLO: + gb_svc_process_hello_deferred(operation); + break; case GB_SVC_TYPE_INTF_HOTPLUG: gb_svc_process_intf_hotplug(operation); break; -- cgit v0.10.2 From c77f85bbc91acafeafd4143a23a225fe81c7e294 Mon Sep 17 00:00:00 2001 From: Dinko Mironov <dmironov@mm-sol.com> Date: Thu, 5 May 2016 19:58:22 +0300 Subject: greybus: audio: Fix incorrect counting of 'ida' Function gb_audio_manager_remove_all() to remove all audio modules, doesn't control correctly 'ida' counting. Signed-off-by: Dinko Mironov <dmironov@mm-sol.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_manager.c b/drivers/staging/greybus/audio_manager.c index 619bdee..9def014 100644 --- a/drivers/staging/greybus/audio_manager.c +++ b/drivers/staging/greybus/audio_manager.c @@ -91,6 +91,7 @@ void gb_audio_manager_remove_all(void) list_for_each_entry_safe(module, next, &modules_list, list) { list_del(&module->list); kobject_put(&module->kobj); + ida_simple_remove(&module_id, module->id); } is_empty = list_empty(&modules_list); -- cgit v0.10.2 From 0decdd55b38ac8276a1039654e529120f65ee366 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 5 May 2016 08:49:58 +0530 Subject: greybus: Revert "interface: Fetch and expose version of interface's firmware" This reverts commit b957ade7b3e4ab8c149c53346dbf02e977b7f3a7. The interface version is now managed as part of the firmware-management protocol. This operation is already removed from the greybus specifications. Drop interface version support from greybus. Tested with gbsim (sysfs file not available after this patch). Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Acked-by: Sandeep Patil <sspatil@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 0e1c2a3..3740173 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -111,14 +111,6 @@ Contact: Greg Kroah-Hartman <greg@kroah.com> Description: Vendor ID of a Greybus interface. -What: /sys/bus/greybus/devices/N-M.I/version -Date: October 2015 -KernelVersion: 4.XX -Contact: Greg Kroah-Hartman <greg@kroah.com> -Description: - Interface version represented as <16 bit major number>.<16 bit - minor number>. - What: /sys/bus/greybus/devices/N-M.I/voltage_now Date: March 2016 KernelVersion: 4.XX diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index 1b28899..13c68f3 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -156,34 +156,6 @@ int gb_control_mode_switch_operation(struct gb_control *control) NULL, 0); } -int gb_control_get_interface_version_operation(struct gb_interface *intf) -{ - struct gb_control_interface_version_response response; - struct gb_connection *connection = intf->control->connection; - int ret; - - if (intf->quirks & GB_INTERFACE_QUIRK_NO_INTERFACE_VERSION) - return 0; - - ret = gb_operation_sync(connection, GB_CONTROL_TYPE_INTERFACE_VERSION, - NULL, 0, &response, sizeof(response)); - if (ret) { - dev_err(&connection->intf->dev, - "failed to get interface version: %d\n", ret); - /* - * FIXME: Return success until the time we bump version of - * control protocol. The interface-version is already set to - * 0.0, so no need to update that. - */ - return 0; - } - - intf->version_major = le16_to_cpu(response.major); - intf->version_minor = le16_to_cpu(response.minor); - - return 0; -} - int gb_control_timesync_enable(struct gb_control *control, u8 count, u64 frame_time, u32 strobe_delay, u32 refclk) { diff --git a/drivers/staging/greybus/control.h b/drivers/staging/greybus/control.h index f108bcc..773cdde 100644 --- a/drivers/staging/greybus/control.h +++ b/drivers/staging/greybus/control.h @@ -40,7 +40,6 @@ int gb_control_mode_switch_operation(struct gb_control *control); int gb_control_get_manifest_size_operation(struct gb_interface *intf); int gb_control_get_manifest_operation(struct gb_interface *intf, void *manifest, size_t size); -int gb_control_get_interface_version_operation(struct gb_interface *intf); int gb_control_timesync_enable(struct gb_control *control, u8 count, u64 frame_time, u32 strobe_delay, u32 refclk); int gb_control_timesync_disable(struct gb_control *control); diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index b73acc0..5f5b928 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -121,7 +121,7 @@ struct gb_protocol_version_response { #define GB_CONTROL_TYPE_TIMESYNC_ENABLE 0x07 #define GB_CONTROL_TYPE_TIMESYNC_DISABLE 0x08 #define GB_CONTROL_TYPE_TIMESYNC_AUTHORITATIVE 0x09 -#define GB_CONTROL_TYPE_INTERFACE_VERSION 0x0a +/* Unused 0x0a */ #define GB_CONTROL_TYPE_BUNDLE_VERSION 0x0b #define GB_CONTROL_TYPE_MODE_SWITCH 0x0e @@ -164,12 +164,6 @@ struct gb_control_disconnected_request { } __packed; /* Control protocol [dis]connected response has no payload */ -/* Control protocol interface version request has no payload */ -struct gb_control_interface_version_response { - __le16 major; - __le16 minor; -} __packed; - #define GB_TIMESYNC_MAX_STROBES 0x04 struct gb_control_timesync_enable_request { diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index b5ad1ac..aed45bc 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -254,16 +254,6 @@ gb_interface_attr(vendor_id, "0x%08x"); gb_interface_attr(product_id, "0x%08x"); gb_interface_attr(serial_number, "0x%016llx"); -static ssize_t version_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct gb_interface *intf = to_gb_interface(dev); - - return scnprintf(buf, PAGE_SIZE, "%u.%u\n", intf->version_major, - intf->version_minor); -} -static DEVICE_ATTR_RO(version); - static ssize_t voltage_now_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -328,7 +318,6 @@ static struct attribute *interface_attrs[] = { &dev_attr_vendor_id.attr, &dev_attr_product_id.attr, &dev_attr_serial_number.attr, - &dev_attr_version.attr, &dev_attr_voltage_now.attr, &dev_attr_current_now.attr, &dev_attr_power_now.attr, @@ -621,10 +610,6 @@ int gb_interface_enable(struct gb_interface *intf) goto err_destroy_bundles; } - ret = gb_control_get_interface_version_operation(intf); - if (ret) - goto err_destroy_bundles; - ret = gb_control_get_bundle_versions(intf->control); if (ret) goto err_destroy_bundles; diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 7a0366d..7a2162a 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -31,9 +31,6 @@ struct gb_interface { u32 product_id; u64 serial_number; - u16 version_major; - u16 version_minor; - struct gb_host_device *hd; struct gb_module *module; -- cgit v0.10.2 From 1d5f9ef9ef8de94331ce5ab31d4b05324885ce6c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Thu, 5 May 2016 14:32:27 +0530 Subject: greybus: gpbridge: implement gpbridge "bus" logic This creates a gpbridge "bus" that will be used to create devices that are the bridged phy devices that correspond to the protocols being implemented. Testing Done: Tested on gbsim. Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> [vaibhav.hiremath@linaro.org: 1.Changed code to retain init/exit fns of drivers. 2.Exit path fix. 3. Fixed review comments] Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Tested-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c index 9be936c..5a12b34 100644 --- a/drivers/staging/greybus/gpbridge.c +++ b/drivers/staging/greybus/gpbridge.c @@ -19,8 +19,266 @@ #include "greybus.h" #include "gpbridge.h" +struct gpbridge_host { + struct gb_bundle *bundle; + struct list_head devices; +}; + +static DEFINE_IDA(gpbridge_id); + +static void gpbdev_release(struct device *dev) +{ + struct gpbridge_device *gpbdev = to_gpbridge_dev(dev); + + ida_simple_remove(&gpbridge_id, gpbdev->id); + kfree(gpbdev); +} + +static int gpbdev_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + /* FIXME add something here, userspace will care about these... */ + return 0; +} + +static const struct gpbridge_device_id * +gpbdev_match_cport(struct greybus_descriptor_cport *cport_desc, + const struct gpbridge_device_id *id) +{ + if (!id) + return NULL; + + for (; id->protocol_id; id++) + if (id->protocol_id == cport_desc->protocol_id) + return id; + + return NULL; +} + +static const struct gpbridge_device_id *gpbdev_match_id(struct gb_bundle *bundle, + const struct gpbridge_device_id *id_table) +{ + const struct gpbridge_device_id *id; + int i; + + if (!id_table || !bundle || bundle->num_cports == 0) + return NULL; + + for (i = 0; i < bundle->num_cports; i++) { + id = gpbdev_match_cport(&bundle->cport_desc[i], id_table); + if (id) + return id; + } + + return NULL; +} + +static int gpbdev_match(struct device *dev, struct device_driver *drv) +{ + struct gpbridge_driver *gpbdrv = to_gpbridge_driver(drv); + struct gpbridge_device *gpbdev = to_gpbridge_dev(dev); + const struct gpbridge_device_id *id; + + id = gpbdev_match_id(gpbdev->bundle, gpbdrv->id_table); + if (id) + return 1; + + return 0; +} + +static int gpbdev_probe(struct device *dev) +{ + struct gpbridge_driver *gpbdrv = to_gpbridge_driver(dev->driver); + struct gpbridge_device *gpbdev = to_gpbridge_dev(dev); + const struct gpbridge_device_id *id; + + id = gpbdev_match_id(gpbdev->bundle, gpbdrv->id_table); + if (!id) + return -ENODEV; + + return gpbdrv->probe(gpbdev, id); +} + +static int gpbdev_remove(struct device *dev) +{ + struct gpbridge_driver *gpbdrv = to_gpbridge_driver(dev->driver); + struct gpbridge_device *gpbdev = to_gpbridge_dev(dev); + + gpbdrv->remove(gpbdev); + return 0; +} + +static struct bus_type gpbridge_bus_type = { + .name = "gpbridge", + .match = gpbdev_match, + .probe = gpbdev_probe, + .remove = gpbdev_remove, + .uevent = gpbdev_uevent, +}; + +int gb_gpbridge_register_driver(struct gpbridge_driver *driver, + struct module *owner, const char *mod_name) +{ + int retval; + + if (greybus_disabled()) + return -ENODEV; + + driver->driver.bus = &gpbridge_bus_type; + driver->driver.name = driver->name; + driver->driver.owner = owner; + driver->driver.mod_name = mod_name; + + retval = driver_register(&driver->driver); + if (retval) + return retval; + + pr_info("registered new driver %s\n", driver->name); + return 0; +} + +void gb_gpbridge_deregister_driver(struct gpbridge_driver *driver) +{ + driver_unregister(&driver->driver); +} + +int gb_gpbridge_get_version(struct gb_connection *connection) +{ + struct gb_protocol_version_request request; + struct gb_protocol_version_response response; + int retval; + + request.major = 1; + request.minor = 0; + + retval = gb_operation_sync(connection, GB_REQUEST_TYPE_PROTOCOL_VERSION, + &request, sizeof(request), &response, + sizeof(response)); + if (retval) + return retval; + + /* FIXME - do proper version negotiation here someday... */ + + connection->module_major = response.major; + connection->module_minor = response.minor; + + dev_dbg(&connection->hd->dev, "%s: v%u.%u\n", connection->name, + response.major, response.minor); + + return 0; +} + +static struct gpbridge_device *gb_gpbridge_create_dev(struct gb_bundle *bundle, + struct greybus_descriptor_cport *cport_desc) +{ + struct gpbridge_device *gpbdev; + int retval; + int id; + + id = ida_simple_get(&gpbridge_id, 0, 0, GFP_KERNEL); + if (id < 0) + return ERR_PTR(id); + + gpbdev = kzalloc(sizeof(*gpbdev), GFP_KERNEL); + if (!gpbdev) { + ida_simple_remove(&gpbridge_id, id); + return ERR_PTR(-ENOMEM); + } + + gpbdev->id = id; + gpbdev->bundle = bundle; + gpbdev->cport_desc = cport_desc; + gpbdev->dev.parent = &bundle->dev; + gpbdev->dev.bus = &gpbridge_bus_type; + gpbdev->dev.release = gpbdev_release; + gpbdev->dev.groups = NULL; + gpbdev->dev.dma_mask = bundle->dev.dma_mask; + dev_set_name(&gpbdev->dev, "gpb%d", id); + + retval = device_register(&gpbdev->dev); + if (retval) { + put_device(&gpbdev->dev); + return ERR_PTR(retval); + } + + return gpbdev; +} + +static void gb_gpbridge_disconnect(struct gb_bundle *bundle) +{ + struct gpbridge_host *gpb_host = greybus_get_drvdata(bundle); + struct gpbridge_device *gpbdev, *temp; + + list_for_each_entry_safe(gpbdev, temp, &gpb_host->devices, list) { + list_del(&gpbdev->list); + device_unregister(&gpbdev->dev); + } + + kfree(gpb_host); +} + +static int gb_gpbridge_probe(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) +{ + struct gpbridge_host *gpb_host; + struct gpbridge_device *gpbdev; + int i; + + if (bundle->num_cports == 0) + return -ENODEV; + + gpb_host = kzalloc(sizeof(*gpb_host), GFP_KERNEL); + if (!gpb_host) + return -ENOMEM; + + gpb_host->bundle = bundle; + INIT_LIST_HEAD(&gpb_host->devices); + greybus_set_drvdata(bundle, gpb_host); + + /* + * Create a bunch of children devices, one per cport, and bind the + * bridged phy drivers to them. + */ + for (i = 0; i < bundle->num_cports; ++i) { + gpbdev = gb_gpbridge_create_dev(bundle, &bundle->cport_desc[i]); + if (IS_ERR(gpbdev)) { + gb_gpbridge_disconnect(bundle); + return PTR_ERR(gpbdev); + } + list_add(&gpbdev->list, &gpb_host->devices); + } + + return 0; +} + +static const struct greybus_bundle_id gb_gpbridge_id_table[] = { + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_BRIDGED_PHY) }, + { }, +}; +MODULE_DEVICE_TABLE(greybus, gb_gpbridge_id_table); + +static struct greybus_driver gb_gpbridge_driver = { + .name = "gpbridge", + .probe = gb_gpbridge_probe, + .disconnect = gb_gpbridge_disconnect, + .id_table = gb_gpbridge_id_table, +}; + static int __init gpbridge_init(void) { + int retval; + + retval = bus_register(&gpbridge_bus_type); + if (retval) { + pr_err("gpbridge bus register failed (%d)\n", retval); + return retval; + } + + retval = greybus_register(&gb_gpbridge_driver); + if (retval) { + pr_err("error registering greybus driver\n"); + goto error_gpbridge; + } + if (gb_gpio_protocol_init()) { pr_err("error initializing gpio protocol\n"); goto error_gpio; @@ -65,6 +323,10 @@ error_uart: error_pwm: gb_gpio_protocol_exit(); error_gpio: + greybus_deregister(&gb_gpbridge_driver); +error_gpbridge: + bus_unregister(&gpbridge_bus_type); + ida_destroy(&gpbridge_id); return -EPROTO; } module_init(gpbridge_init); @@ -78,19 +340,11 @@ static void __exit gpbridge_exit(void) gb_uart_protocol_exit(); gb_pwm_protocol_exit(); gb_gpio_protocol_exit(); + + greybus_deregister(&gb_gpbridge_driver); + bus_unregister(&gpbridge_bus_type); + ida_destroy(&gpbridge_id); } module_exit(gpbridge_exit); -/* - * One large list of all classes we support in the gpbridge.ko module. - * - * Due to limitations in older kernels, the different phy .c files can not - * contain their own MODULE_DEVICE_TABLE(), so put them all here for now. - */ -static const struct greybus_bundle_id bridged_phy_id_table[] = { - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_BRIDGED_PHY) }, - { }, -}; -MODULE_DEVICE_TABLE(greybus, bridged_phy_id_table); - MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/gpbridge.h b/drivers/staging/greybus/gpbridge.h index 50ee87b..431cb7b 100644 --- a/drivers/staging/greybus/gpbridge.h +++ b/drivers/staging/greybus/gpbridge.h @@ -9,6 +9,53 @@ #ifndef __GPBRIDGE_H #define __GPBRIDGE_H +struct gpbridge_device { + u32 id; + struct greybus_descriptor_cport *cport_desc; + struct gb_bundle *bundle; + struct list_head list; + struct device dev; +}; +#define to_gpbridge_dev(d) container_of(d, struct gpbridge_device, dev) + +static inline void *gb_gpbridge_get_data(struct gpbridge_device *gdev) +{ + return dev_get_drvdata(&gdev->dev); +} + +static inline void gb_gpbridge_set_data(struct gpbridge_device *gdev, void *data) +{ + dev_set_drvdata(&gdev->dev, data); +} + +struct gpbridge_device_id { + __u8 protocol_id; +}; + +#define GPBRIDGE_PROTOCOL(p) \ + .protocol_id = (p), + +struct gpbridge_driver { + const char *name; + int (*probe)(struct gpbridge_device *, + const struct gpbridge_device_id *id); + void (*remove)(struct gpbridge_device *); + const struct gpbridge_device_id *id_table; + + struct device_driver driver; +}; +#define to_gpbridge_driver(d) container_of(d, struct gpbridge_driver, driver) + +int gb_gpbridge_get_version(struct gb_connection *connection); +int gb_gpbridge_register_driver(struct gpbridge_driver *driver, + struct module *owner, const char *mod_name); +void gb_gpbridge_deregister_driver(struct gpbridge_driver *driver); + +#define gb_gpbridge_register(driver) \ + gb_gpbridge_register_driver(driver, THIS_MODULE, KBUILD_MODNAME) +#define gb_gpbridge_deregister(driver) \ + gb_gpbridge_deregister_driver(driver) + extern int gb_gpio_protocol_init(void); extern void gb_gpio_protocol_exit(void); -- cgit v0.10.2 From ac4cbc575153fe8044d1e7d7742889ab0850913a Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Date: Thu, 5 May 2016 14:32:28 +0530 Subject: greybus: gpbridge: Add gpbridge driver init/exit helper macros In order to help bridged-phy drivers to define init()/exit() functions, define helper macro in gpbridge.h file. Testing Done: Tested on gbsim. Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Tested-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/gpbridge.h b/drivers/staging/greybus/gpbridge.h index 431cb7b..aa2cdc0 100644 --- a/drivers/staging/greybus/gpbridge.h +++ b/drivers/staging/greybus/gpbridge.h @@ -56,6 +56,16 @@ void gb_gpbridge_deregister_driver(struct gpbridge_driver *driver); #define gb_gpbridge_deregister(driver) \ gb_gpbridge_deregister_driver(driver) +#define gb_gpbridge_builtin_driver(__driver) \ + int __init gb_##__driver##_init(void) \ +{ \ + return gb_gpbridge_register(&__driver); \ +} \ +void gb_##__driver##_exit(void) \ +{ \ + gb_gpbridge_deregister(&__driver); \ +} + extern int gb_gpio_protocol_init(void); extern void gb_gpio_protocol_exit(void); -- cgit v0.10.2 From 6d58e7144473f46c245792380c8fc1c7e928147e Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Date: Thu, 5 May 2016 14:32:29 +0530 Subject: greybus: connection: export gb_connection_disable_rx() fn gb_connection_disable_rx() fn is required to be used by other modules (e.g. bridged-phy drivers) and so export it. Testing Done: Tested on gbsim. Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Tested-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 1880f8f..1564db8 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -617,6 +617,7 @@ void gb_connection_disable_rx(struct gb_connection *connection) out_unlock: mutex_unlock(&connection->mutex); } +EXPORT_SYMBOL_GPL(gb_connection_disable_rx); void gb_connection_disable(struct gb_connection *connection) { -- cgit v0.10.2 From 7dbe1f497b445ead3a6c5f0895d002960a2b07f2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Thu, 5 May 2016 14:32:30 +0530 Subject: greybus: UART: convert to a gpbridge driver This converts the UART driver to be a gpbridge driver, moving it away from the "legacy" interface. Testing Done: Tested on gbsim. Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> [vaibhav.hiremath@linaro.org: 1.Changed code to retain init/exit fns of drivers. 2.Exit path fix. 3. Fixed review comments] Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Tested-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c index 5a12b34..2a23a30 100644 --- a/drivers/staging/greybus/gpbridge.c +++ b/drivers/staging/greybus/gpbridge.c @@ -252,6 +252,7 @@ static int gb_gpbridge_probe(struct gb_bundle *bundle, static const struct greybus_bundle_id gb_gpbridge_id_table[] = { { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_BRIDGED_PHY) }, + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_UART) }, { }, }; MODULE_DEVICE_TABLE(greybus, gb_gpbridge_id_table); @@ -287,8 +288,8 @@ static int __init gpbridge_init(void) pr_err("error initializing pwm protocol\n"); goto error_pwm; } - if (gb_uart_protocol_init()) { - pr_err("error initializing uart protocol\n"); + if (gb_uart_driver_init()) { + pr_err("error initializing uart driver\n"); goto error_uart; } if (gb_sdio_protocol_init()) { @@ -317,7 +318,7 @@ error_i2c: error_usb: gb_sdio_protocol_exit(); error_sdio: - gb_uart_protocol_exit(); + gb_uart_driver_exit(); error_uart: gb_pwm_protocol_exit(); error_pwm: @@ -337,7 +338,7 @@ static void __exit gpbridge_exit(void) gb_i2c_protocol_exit(); gb_usb_protocol_exit(); gb_sdio_protocol_exit(); - gb_uart_protocol_exit(); + gb_uart_driver_exit(); gb_pwm_protocol_exit(); gb_gpio_protocol_exit(); diff --git a/drivers/staging/greybus/gpbridge.h b/drivers/staging/greybus/gpbridge.h index aa2cdc0..fb17f02 100644 --- a/drivers/staging/greybus/gpbridge.h +++ b/drivers/staging/greybus/gpbridge.h @@ -72,8 +72,8 @@ extern void gb_gpio_protocol_exit(void); extern int gb_pwm_protocol_init(void); extern void gb_pwm_protocol_exit(void); -extern int gb_uart_protocol_init(void); -extern void gb_uart_protocol_exit(void); +extern int gb_uart_driver_init(void); +extern void gb_uart_driver_exit(void); extern int gb_sdio_protocol_init(void); extern void gb_sdio_protocol_exit(void); diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index 58b2779..f391a5d 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -238,7 +238,6 @@ static void legacy_disconnect(struct gb_bundle *bundle) static const struct greybus_bundle_id legacy_id_table[] = { { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_GPIO) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_I2C) }, - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_UART) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_USB) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SDIO) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_PWM) }, diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index be71891..eb83c04 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -42,6 +42,7 @@ struct gb_tty_line_coding { }; struct gb_tty { + struct gpbridge_device *gpbdev; struct tty_port port; void *buffer; size_t buffer_payload_max; @@ -78,7 +79,7 @@ static int gb_uart_receive_data_handler(struct gb_operation *op) unsigned long tty_flags = TTY_NORMAL; if (request->payload_size < sizeof(*receive_data)) { - dev_err(&connection->bundle->dev, + dev_err(&gb_tty->gpbdev->dev, "short receive-data request received (%zu < %zu)\n", request->payload_size, sizeof(*receive_data)); return -EINVAL; @@ -88,7 +89,7 @@ static int gb_uart_receive_data_handler(struct gb_operation *op) recv_data_size = le16_to_cpu(receive_data->size); if (recv_data_size != request->payload_size - sizeof(*receive_data)) { - dev_err(&connection->bundle->dev, + dev_err(&gb_tty->gpbdev->dev, "malformed receive-data request received (%u != %zu)\n", recv_data_size, request->payload_size - sizeof(*receive_data)); @@ -113,7 +114,7 @@ static int gb_uart_receive_data_handler(struct gb_operation *op) count = tty_insert_flip_string_fixed_flag(port, receive_data->data, tty_flags, recv_data_size); if (count != recv_data_size) { - dev_err(&connection->bundle->dev, + dev_err(&gb_tty->gpbdev->dev, "UART: RX 0x%08x bytes only wrote 0x%08x\n", recv_data_size, count); } @@ -130,7 +131,7 @@ static int gb_uart_serial_state_handler(struct gb_operation *op) struct gb_uart_serial_state_request *serial_state; if (request->payload_size < sizeof(*serial_state)) { - dev_err(&connection->bundle->dev, + dev_err(&gb_tty->gpbdev->dev, "short serial-state event received (%zu < %zu)\n", request->payload_size, sizeof(*serial_state)); return -EINVAL; @@ -142,9 +143,11 @@ static int gb_uart_serial_state_handler(struct gb_operation *op) return 0; } -static int gb_uart_request_recv(u8 type, struct gb_operation *op) +static int gb_uart_request_handler(struct gb_operation *op) { struct gb_connection *connection = op->connection; + struct gb_tty *gb_tty = gb_connection_get_data(connection); + int type = op->type; int ret; switch (type) { @@ -155,7 +158,7 @@ static int gb_uart_request_recv(u8 type, struct gb_operation *op) ret = gb_uart_serial_state_handler(op); break; default: - dev_err(&connection->bundle->dev, + dev_err(&gb_tty->gpbdev->dev, "unsupported unsolicited request: 0x%02x\n", type); ret = -EINVAL; } @@ -209,7 +212,7 @@ static int send_break(struct gb_tty *gb_tty, u8 state) struct gb_uart_set_break_request request; if ((state != 0) && (state != 1)) { - dev_err(&gb_tty->connection->bundle->dev, + dev_err(&gb_tty->gpbdev->dev, "invalid break state of %d\n", state); return -EINVAL; } @@ -619,8 +622,10 @@ static struct tty_port_operations null_ops = { }; static int gb_tty_init(void); static void gb_tty_exit(void); -static int gb_uart_connection_init(struct gb_connection *connection) +static int gb_uart_probe(struct gpbridge_device *gpbdev, + const struct gpbridge_device_id *id) { + struct gb_connection *connection; size_t max_payload; struct gb_tty *gb_tty; struct device *tty_dev; @@ -639,13 +644,21 @@ static int gb_uart_connection_init(struct gb_connection *connection) gb_tty = kzalloc(sizeof(*gb_tty), GFP_KERNEL); if (!gb_tty) { retval = -ENOMEM; - goto error_alloc; + goto exit_tty; + } + + connection = gb_connection_create(gpbdev->bundle, + le16_to_cpu(gpbdev->cport_desc->id), + gb_uart_request_handler); + if (IS_ERR(connection)) { + retval = PTR_ERR(connection); + goto exit_tty_free; } max_payload = gb_operation_get_payload_size_max(connection); if (max_payload < sizeof(struct gb_uart_send_data_request)) { retval = -EINVAL; - goto error_payload; + goto exit_connection_destroy; } gb_tty->buffer_payload_max = max_payload - @@ -654,22 +667,19 @@ static int gb_uart_connection_init(struct gb_connection *connection) gb_tty->buffer = kzalloc(gb_tty->buffer_payload_max, GFP_KERNEL); if (!gb_tty->buffer) { retval = -ENOMEM; - goto error_payload; + goto exit_connection_destroy; } - gb_tty->connection = connection; - gb_connection_set_data(connection, gb_tty); - minor = alloc_minor(gb_tty); if (minor < 0) { if (minor == -ENOSPC) { dev_err(&connection->bundle->dev, "no more free minor numbers\n"); retval = -ENODEV; - goto error_minor; + } else { + retval = minor; } - retval = minor; - goto error_minor; + goto exit_buf_free; } gb_tty->minor = minor; @@ -681,6 +691,19 @@ static int gb_uart_connection_init(struct gb_connection *connection) tty_port_init(&gb_tty->port); gb_tty->port.ops = &null_ops; + gb_tty->connection = connection; + gb_tty->gpbdev = gpbdev; + gb_connection_set_data(connection, gb_tty); + gb_gpbridge_set_data(gpbdev, gb_tty); + + retval = gb_connection_enable_tx(connection); + if (retval) + goto exit_release_minor; + + retval = gb_gpbridge_get_version(connection); + if (retval) + goto exit_connection_disable; + send_control(gb_tty, gb_tty->ctrlout); /* initialize the uart to be 9600n81 */ @@ -690,41 +713,47 @@ static int gb_uart_connection_init(struct gb_connection *connection) gb_tty->line_coding.data_bits = 8; send_line_coding(gb_tty); + retval = gb_connection_enable(connection); + if (retval) + goto exit_connection_disable; + tty_dev = tty_port_register_device(&gb_tty->port, gb_tty_driver, minor, - &connection->bundle->dev); + &gpbdev->dev); if (IS_ERR(tty_dev)) { retval = PTR_ERR(tty_dev); - goto error; + goto exit_connection_disable; } + return 0; -error: - tty_port_destroy(&gb_tty->port); + +exit_connection_disable: + gb_connection_disable(connection); +exit_release_minor: release_minor(gb_tty); -error_minor: - gb_connection_set_data(connection, NULL); +exit_buf_free: kfree(gb_tty->buffer); -error_payload: +exit_connection_destroy: + gb_connection_destroy(connection); +exit_tty_free: kfree(gb_tty); -error_alloc: +exit_tty: if (atomic_dec_return(&reference_count) == 0) gb_tty_exit(); + return retval; } -static void gb_uart_connection_exit(struct gb_connection *connection) +static void gb_uart_remove(struct gpbridge_device *gpbdev) { - struct gb_tty *gb_tty = gb_connection_get_data(connection); + struct gb_tty *gb_tty = gb_gpbridge_get_data(gpbdev); + struct gb_connection *connection = gb_tty->connection; struct tty_struct *tty; - if (!gb_tty) - return; - mutex_lock(&gb_tty->mutex); gb_tty->disconnected = true; wake_up_all(&gb_tty->wioctl); - gb_connection_set_data(connection, NULL); mutex_unlock(&gb_tty->mutex); tty = tty_port_tty_get(&gb_tty->port); @@ -732,13 +761,15 @@ static void gb_uart_connection_exit(struct gb_connection *connection) tty_vhangup(tty); tty_kref_put(tty); } - /* FIXME - stop all traffic */ + gb_connection_disable_rx(connection); tty_unregister_device(gb_tty_driver, gb_tty->minor); /* FIXME - free transmit / receive buffers */ + gb_connection_disable(connection); tty_port_destroy(&gb_tty->port); + gb_connection_destroy(connection); kfree(gb_tty->buffer); kfree(gb_tty); @@ -790,14 +821,15 @@ static void gb_tty_exit(void) idr_destroy(&tty_minors); } -static struct gb_protocol uart_protocol = { - .name = "uart", - .id = GREYBUS_PROTOCOL_UART, - .major = GB_UART_VERSION_MAJOR, - .minor = GB_UART_VERSION_MINOR, - .connection_init = gb_uart_connection_init, - .connection_exit = gb_uart_connection_exit, - .request_recv = gb_uart_request_recv, +static const struct gpbridge_device_id gb_uart_id_table[] = { + { GPBRIDGE_PROTOCOL(GREYBUS_PROTOCOL_UART) }, + { }, }; -gb_builtin_protocol_driver(uart_protocol); +static struct gpbridge_driver uart_driver = { + .name = "uart", + .probe = gb_uart_probe, + .remove = gb_uart_remove, + .id_table = gb_uart_id_table, +}; +gb_gpbridge_builtin_driver(uart_driver); -- cgit v0.10.2 From 320549086d1e985c09fd6635075ab45a3421038e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Thu, 5 May 2016 14:32:31 +0530 Subject: greybus: PWM: convert to a gpbridge driver This converts the PWM driver to be a gpbridge driver, moving it away from the "legacy" interface. Testing Done: Tested on gbsim. Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> [vaibhav.hiremath@linaro.org: 1.Changed code to retain init/exit fns of drivers. 2.Exit path fix. 3. Fixed review comments] Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Tested-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c index 2a23a30..a446749 100644 --- a/drivers/staging/greybus/gpbridge.c +++ b/drivers/staging/greybus/gpbridge.c @@ -252,6 +252,7 @@ static int gb_gpbridge_probe(struct gb_bundle *bundle, static const struct greybus_bundle_id gb_gpbridge_id_table[] = { { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_BRIDGED_PHY) }, + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_PWM) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_UART) }, { }, }; @@ -284,8 +285,8 @@ static int __init gpbridge_init(void) pr_err("error initializing gpio protocol\n"); goto error_gpio; } - if (gb_pwm_protocol_init()) { - pr_err("error initializing pwm protocol\n"); + if (gb_pwm_driver_init()) { + pr_err("error initializing pwm driver\n"); goto error_pwm; } if (gb_uart_driver_init()) { @@ -320,7 +321,7 @@ error_usb: error_sdio: gb_uart_driver_exit(); error_uart: - gb_pwm_protocol_exit(); + gb_pwm_driver_exit(); error_pwm: gb_gpio_protocol_exit(); error_gpio: @@ -339,7 +340,7 @@ static void __exit gpbridge_exit(void) gb_usb_protocol_exit(); gb_sdio_protocol_exit(); gb_uart_driver_exit(); - gb_pwm_protocol_exit(); + gb_pwm_driver_exit(); gb_gpio_protocol_exit(); greybus_deregister(&gb_gpbridge_driver); diff --git a/drivers/staging/greybus/gpbridge.h b/drivers/staging/greybus/gpbridge.h index fb17f02..8681bd3 100644 --- a/drivers/staging/greybus/gpbridge.h +++ b/drivers/staging/greybus/gpbridge.h @@ -69,8 +69,8 @@ void gb_##__driver##_exit(void) \ extern int gb_gpio_protocol_init(void); extern void gb_gpio_protocol_exit(void); -extern int gb_pwm_protocol_init(void); -extern void gb_pwm_protocol_exit(void); +extern int gb_pwm_driver_init(void); +extern void gb_pwm_driver_exit(void); extern int gb_uart_driver_init(void); extern void gb_uart_driver_exit(void); diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index f391a5d..f9bcdde 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -240,7 +240,6 @@ static const struct greybus_bundle_id legacy_id_table[] = { { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_I2C) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_USB) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SDIO) }, - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_PWM) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SPI) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_CAMERA) }, { } diff --git a/drivers/staging/greybus/pwm.c b/drivers/staging/greybus/pwm.c index 176301a..b11e77d 100644 --- a/drivers/staging/greybus/pwm.c +++ b/drivers/staging/greybus/pwm.c @@ -178,8 +178,10 @@ static const struct pwm_ops gb_pwm_ops = { .owner = THIS_MODULE, }; -static int gb_pwm_connection_init(struct gb_connection *connection) +static int gb_pwm_probe(struct gpbridge_device *gpbdev, + const struct gpbridge_device_id *id) { + struct gb_connection *connection; struct gb_pwm_chip *pwmc; struct pwm_chip *pwm; int ret; @@ -187,17 +189,35 @@ static int gb_pwm_connection_init(struct gb_connection *connection) pwmc = kzalloc(sizeof(*pwmc), GFP_KERNEL); if (!pwmc) return -ENOMEM; + + connection = gb_connection_create(gpbdev->bundle, + le16_to_cpu(gpbdev->cport_desc->id), + NULL); + if (IS_ERR(connection)) { + ret = PTR_ERR(connection); + goto exit_pwmc_free; + } + pwmc->connection = connection; gb_connection_set_data(connection, pwmc); + gb_gpbridge_set_data(gpbdev, pwmc); + + ret = gb_connection_enable(connection); + if (ret) + goto exit_connection_destroy; + + ret = gb_gpbridge_get_version(connection); + if (ret) + goto exit_connection_disable; /* Query number of pwms present */ ret = gb_pwm_count_operation(pwmc); if (ret) - goto out_err; + goto exit_connection_disable; pwm = &pwmc->chip; - pwm->dev = &connection->bundle->dev; + pwm->dev = &gpbdev->dev; pwm->ops = &gb_pwm_ops; pwm->base = -1; /* Allocate base dynamically */ pwm->npwm = pwmc->pwm_max + 1; @@ -205,36 +225,42 @@ static int gb_pwm_connection_init(struct gb_connection *connection) ret = pwmchip_add(pwm); if (ret) { - dev_err(&connection->bundle->dev, + dev_err(&gpbdev->dev, "failed to register PWM: %d\n", ret); - goto out_err; + goto exit_connection_disable; } return 0; -out_err: + +exit_connection_disable: + gb_connection_disable(connection); +exit_connection_destroy: + gb_connection_destroy(connection); +exit_pwmc_free: kfree(pwmc); return ret; } -static void gb_pwm_connection_exit(struct gb_connection *connection) +static void gb_pwm_remove(struct gpbridge_device *gpbdev) { - struct gb_pwm_chip *pwmc = gb_connection_get_data(connection); - if (!pwmc) - return; + struct gb_pwm_chip *pwmc = gb_gpbridge_get_data(gpbdev); + struct gb_connection *connection = pwmc->connection; pwmchip_remove(&pwmc->chip); - /* kref_put(pwmc->connection) */ + gb_connection_disable(connection); + gb_connection_destroy(connection); kfree(pwmc); } -static struct gb_protocol pwm_protocol = { - .name = "pwm", - .id = GREYBUS_PROTOCOL_PWM, - .major = GB_PWM_VERSION_MAJOR, - .minor = GB_PWM_VERSION_MINOR, - .connection_init = gb_pwm_connection_init, - .connection_exit = gb_pwm_connection_exit, - .request_recv = NULL, /* no incoming requests */ +static const struct gpbridge_device_id gb_pwm_id_table[] = { + { GPBRIDGE_PROTOCOL(GREYBUS_PROTOCOL_PWM) }, + { }, }; -gb_builtin_protocol_driver(pwm_protocol); +static struct gpbridge_driver pwm_driver = { + .name = "pwm", + .probe = gb_pwm_probe, + .remove = gb_pwm_remove, + .id_table = gb_pwm_id_table, +}; +gb_gpbridge_builtin_driver(pwm_driver); -- cgit v0.10.2 From cf1d8bee59aa995fcc6514be7a67e9575bbe5498 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Thu, 5 May 2016 14:32:32 +0530 Subject: greybus: I2C: convert to a gpbridge driver This converts the I2C driver to be a gpbridge driver, moving it away from the "legacy" interface. Testing Done: Tested on gbsim. Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> [vaibhav.hiremath@linaro.org: 1.Changed code to retain init/exit fns of drivers. 2.Exit path fix. 3. Fixed review comments] Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Tested-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c index a446749..e3c11cb 100644 --- a/drivers/staging/greybus/gpbridge.c +++ b/drivers/staging/greybus/gpbridge.c @@ -252,6 +252,7 @@ static int gb_gpbridge_probe(struct gb_bundle *bundle, static const struct greybus_bundle_id gb_gpbridge_id_table[] = { { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_BRIDGED_PHY) }, + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_I2C) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_PWM) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_UART) }, { }, @@ -301,8 +302,8 @@ static int __init gpbridge_init(void) pr_err("error initializing usb protocol\n"); goto error_usb; } - if (gb_i2c_protocol_init()) { - pr_err("error initializing i2c protocol\n"); + if (gb_i2c_driver_init()) { + pr_err("error initializing i2c driver\n"); goto error_i2c; } if (gb_spi_protocol_init()) { @@ -313,7 +314,7 @@ static int __init gpbridge_init(void) return 0; error_spi: - gb_i2c_protocol_exit(); + gb_i2c_driver_exit(); error_i2c: gb_usb_protocol_exit(); error_usb: @@ -336,7 +337,7 @@ module_init(gpbridge_init); static void __exit gpbridge_exit(void) { gb_spi_protocol_exit(); - gb_i2c_protocol_exit(); + gb_i2c_driver_exit(); gb_usb_protocol_exit(); gb_sdio_protocol_exit(); gb_uart_driver_exit(); diff --git a/drivers/staging/greybus/gpbridge.h b/drivers/staging/greybus/gpbridge.h index 8681bd3..a64e9cb 100644 --- a/drivers/staging/greybus/gpbridge.h +++ b/drivers/staging/greybus/gpbridge.h @@ -81,8 +81,8 @@ extern void gb_sdio_protocol_exit(void); extern int gb_usb_protocol_init(void); extern void gb_usb_protocol_exit(void); -extern int gb_i2c_protocol_init(void); -extern void gb_i2c_protocol_exit(void); +extern int gb_i2c_driver_init(void); +extern void gb_i2c_driver_exit(void); extern int gb_spi_protocol_init(void); extern void gb_spi_protocol_exit(void); diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c index 73b8581..b49e8b4 100644 --- a/drivers/staging/greybus/i2c.c +++ b/drivers/staging/greybus/i2c.c @@ -17,6 +17,7 @@ struct gb_i2c_device { struct gb_connection *connection; + struct gpbridge_device *gpbdev; u32 functionality; @@ -71,6 +72,7 @@ static struct gb_operation * gb_i2c_operation_create(struct gb_connection *connection, struct i2c_msg *msgs, u32 msg_count) { + struct gb_i2c_device *gb_i2c_dev = gb_connection_get_data(connection); struct gb_i2c_transfer_request *request; struct gb_operation *operation; struct gb_i2c_transfer_op *op; @@ -83,7 +85,7 @@ gb_i2c_operation_create(struct gb_connection *connection, u32 i; if (msg_count > (u32)U16_MAX) { - dev_err(&connection->bundle->dev, "msg_count (%u) too big\n", + dev_err(&gb_i2c_dev->gpbdev->dev, "msg_count (%u) too big\n", msg_count); return NULL; } @@ -166,7 +168,7 @@ static int gb_i2c_transfer_operation(struct gb_i2c_device *gb_i2c_dev, struct i2c_msg *msgs, u32 msg_count) { struct gb_connection *connection = gb_i2c_dev->connection; - struct device *dev = &connection->bundle->dev; + struct device *dev = &gb_i2c_dev->gpbdev->dev; struct gb_operation *operation; int ret; @@ -240,8 +242,10 @@ static int gb_i2c_device_setup(struct gb_i2c_device *gb_i2c_dev) return gb_i2c_functionality_operation(gb_i2c_dev); } -static int gb_i2c_connection_init(struct gb_connection *connection) +static int gb_i2c_probe(struct gpbridge_device *gpbdev, + const struct gpbridge_device_id *id) { + struct gb_connection *connection; struct gb_i2c_device *gb_i2c_dev; struct i2c_adapter *adapter; int ret; @@ -250,12 +254,30 @@ static int gb_i2c_connection_init(struct gb_connection *connection) if (!gb_i2c_dev) return -ENOMEM; - gb_i2c_dev->connection = connection; /* refcount? */ + connection = gb_connection_create(gpbdev->bundle, + le16_to_cpu(gpbdev->cport_desc->id), + NULL); + if (IS_ERR(connection)) { + ret = PTR_ERR(connection); + goto exit_i2cdev_free; + } + + gb_i2c_dev->connection = connection; gb_connection_set_data(connection, gb_i2c_dev); + gb_i2c_dev->gpbdev = gpbdev; + gb_gpbridge_set_data(gpbdev, gb_i2c_dev); + + ret = gb_connection_enable(connection); + if (ret) + goto exit_connection_destroy; + + ret = gb_gpbridge_get_version(connection); + if (ret) + goto exit_connection_disable; ret = gb_i2c_device_setup(gb_i2c_dev); if (ret) - goto out_err; + goto exit_connection_disable; /* Looks good; up our i2c adapter */ adapter = &gb_i2c_dev->adapter; @@ -264,39 +286,46 @@ static int gb_i2c_connection_init(struct gb_connection *connection) adapter->algo = &gb_i2c_algorithm; /* adapter->algo_data = what? */ - adapter->dev.parent = &connection->bundle->dev; + adapter->dev.parent = &gpbdev->dev; snprintf(adapter->name, sizeof(adapter->name), "Greybus i2c adapter"); i2c_set_adapdata(adapter, gb_i2c_dev); ret = i2c_add_adapter(adapter); if (ret) - goto out_err; + goto exit_connection_disable; return 0; -out_err: - /* kref_put(gb_i2c_dev->connection) */ + +exit_connection_disable: + gb_connection_disable(connection); +exit_connection_destroy: + gb_connection_destroy(connection); +exit_i2cdev_free: kfree(gb_i2c_dev); return ret; } -static void gb_i2c_connection_exit(struct gb_connection *connection) +static void gb_i2c_remove(struct gpbridge_device *gpbdev) { - struct gb_i2c_device *gb_i2c_dev = gb_connection_get_data(connection); + struct gb_i2c_device *gb_i2c_dev = gb_gpbridge_get_data(gpbdev); + struct gb_connection *connection = gb_i2c_dev->connection; i2c_del_adapter(&gb_i2c_dev->adapter); - /* kref_put(gb_i2c_dev->connection) */ + gb_connection_disable(connection); + gb_connection_destroy(connection); kfree(gb_i2c_dev); } -static struct gb_protocol i2c_protocol = { - .name = "i2c", - .id = GREYBUS_PROTOCOL_I2C, - .major = GB_I2C_VERSION_MAJOR, - .minor = GB_I2C_VERSION_MINOR, - .connection_init = gb_i2c_connection_init, - .connection_exit = gb_i2c_connection_exit, - .request_recv = NULL, /* no incoming requests */ +static const struct gpbridge_device_id gb_i2c_id_table[] = { + { GPBRIDGE_PROTOCOL(GREYBUS_PROTOCOL_I2C) }, + { }, }; -gb_builtin_protocol_driver(i2c_protocol); +static struct gpbridge_driver i2c_driver = { + .name = "i2c", + .probe = gb_i2c_probe, + .remove = gb_i2c_remove, + .id_table = gb_i2c_id_table, +}; +gb_gpbridge_builtin_driver(i2c_driver); diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index f9bcdde..f734646 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -237,7 +237,6 @@ static void legacy_disconnect(struct gb_bundle *bundle) static const struct greybus_bundle_id legacy_id_table[] = { { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_GPIO) }, - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_I2C) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_USB) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SDIO) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SPI) }, -- cgit v0.10.2 From 315bea0e9605a2f506606bdb2a531149a022394d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Thu, 5 May 2016 14:32:33 +0530 Subject: greybus: GPIO: convert to a gpbridge driver This converts the GPIO driver to be a gpbridge driver, moving it away from the "legacy" interface. Testing Done: Tested on gbsim. Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> [vaibhav.hiremath@linaro.org: 1.Changed code to retain init/exit fns of drivers. 2.Exit path fix. 3. Fixed review comments] Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Tested-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c index e3c11cb..a65ab16 100644 --- a/drivers/staging/greybus/gpbridge.c +++ b/drivers/staging/greybus/gpbridge.c @@ -252,6 +252,7 @@ static int gb_gpbridge_probe(struct gb_bundle *bundle, static const struct greybus_bundle_id gb_gpbridge_id_table[] = { { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_BRIDGED_PHY) }, + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_GPIO) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_I2C) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_PWM) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_UART) }, @@ -282,8 +283,8 @@ static int __init gpbridge_init(void) goto error_gpbridge; } - if (gb_gpio_protocol_init()) { - pr_err("error initializing gpio protocol\n"); + if (gb_gpio_driver_init()) { + pr_err("error initializing gpio driver\n"); goto error_gpio; } if (gb_pwm_driver_init()) { @@ -324,7 +325,7 @@ error_sdio: error_uart: gb_pwm_driver_exit(); error_pwm: - gb_gpio_protocol_exit(); + gb_gpio_driver_exit(); error_gpio: greybus_deregister(&gb_gpbridge_driver); error_gpbridge: @@ -342,7 +343,7 @@ static void __exit gpbridge_exit(void) gb_sdio_protocol_exit(); gb_uart_driver_exit(); gb_pwm_driver_exit(); - gb_gpio_protocol_exit(); + gb_gpio_driver_exit(); greybus_deregister(&gb_gpbridge_driver); bus_unregister(&gpbridge_bus_type); diff --git a/drivers/staging/greybus/gpbridge.h b/drivers/staging/greybus/gpbridge.h index a64e9cb..f5161c5 100644 --- a/drivers/staging/greybus/gpbridge.h +++ b/drivers/staging/greybus/gpbridge.h @@ -66,8 +66,8 @@ void gb_##__driver##_exit(void) \ gb_gpbridge_deregister(&__driver); \ } -extern int gb_gpio_protocol_init(void); -extern void gb_gpio_protocol_exit(void); +extern int gb_gpio_driver_init(void); +extern void gb_gpio_driver_exit(void); extern int gb_pwm_driver_init(void); extern void gb_pwm_driver_exit(void); diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 440ff44c..4f0695b 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -33,6 +33,7 @@ struct gb_gpio_line { }; struct gb_gpio_controller { + struct gpbridge_device *gpbdev; struct gb_connection *connection; u8 line_max; /* max line number */ struct gb_gpio_line *lines; @@ -78,7 +79,7 @@ static int gb_gpio_activate_operation(struct gb_gpio_controller *ggc, u8 which) static void gb_gpio_deactivate_operation(struct gb_gpio_controller *ggc, u8 which) { - struct device *dev = &ggc->connection->bundle->dev; + struct device *dev = &ggc->gpbdev->dev; struct gb_gpio_deactivate_request request; int ret; @@ -96,7 +97,7 @@ static void gb_gpio_deactivate_operation(struct gb_gpio_controller *ggc, static int gb_gpio_get_direction_operation(struct gb_gpio_controller *ggc, u8 which) { - struct device *dev = &ggc->connection->bundle->dev; + struct device *dev = &ggc->gpbdev->dev; struct gb_gpio_get_direction_request request; struct gb_gpio_get_direction_response response; int ret; @@ -150,7 +151,7 @@ static int gb_gpio_direction_out_operation(struct gb_gpio_controller *ggc, static int gb_gpio_get_value_operation(struct gb_gpio_controller *ggc, u8 which) { - struct device *dev = &ggc->connection->bundle->dev; + struct device *dev = &ggc->gpbdev->dev; struct gb_gpio_get_value_request request; struct gb_gpio_get_value_response response; int ret; @@ -177,7 +178,7 @@ static int gb_gpio_get_value_operation(struct gb_gpio_controller *ggc, static void gb_gpio_set_value_operation(struct gb_gpio_controller *ggc, u8 which, bool value_high) { - struct device *dev = &ggc->connection->bundle->dev; + struct device *dev = &ggc->gpbdev->dev; struct gb_gpio_set_value_request request; int ret; @@ -216,7 +217,7 @@ static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *ggc, static void _gb_gpio_irq_mask(struct gb_gpio_controller *ggc, u8 hwirq) { - struct device *dev = &ggc->connection->bundle->dev; + struct device *dev = &ggc->gpbdev->dev; struct gb_gpio_irq_mask_request request; int ret; @@ -230,7 +231,7 @@ static void _gb_gpio_irq_mask(struct gb_gpio_controller *ggc, u8 hwirq) static void _gb_gpio_irq_unmask(struct gb_gpio_controller *ggc, u8 hwirq) { - struct device *dev = &ggc->connection->bundle->dev; + struct device *dev = &ggc->gpbdev->dev; struct gb_gpio_irq_unmask_request request; int ret; @@ -245,7 +246,7 @@ static void _gb_gpio_irq_unmask(struct gb_gpio_controller *ggc, u8 hwirq) static void _gb_gpio_irq_set_type(struct gb_gpio_controller *ggc, u8 hwirq, u8 type) { - struct device *dev = &ggc->connection->bundle->dev; + struct device *dev = &ggc->gpbdev->dev; struct gb_gpio_irq_type_request request; int ret; @@ -284,7 +285,7 @@ static int gb_gpio_irq_set_type(struct irq_data *d, unsigned int type) struct gpio_chip *chip = irq_data_to_gpio_chip(d); struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); struct gb_gpio_line *line = &ggc->lines[d->hwirq]; - struct device *dev = &ggc->connection->bundle->dev; + struct device *dev = &ggc->gpbdev->dev; u8 irq_type; switch (type) { @@ -347,13 +348,14 @@ static void gb_gpio_irq_bus_sync_unlock(struct irq_data *d) mutex_unlock(&ggc->irq_lock); } -static int gb_gpio_request_recv(u8 type, struct gb_operation *op) +static int gb_gpio_request_handler(struct gb_operation *op) { struct gb_connection *connection = op->connection; - struct device *dev = &connection->bundle->dev; struct gb_gpio_controller *ggc = gb_connection_get_data(connection); + struct device *dev = &ggc->gpbdev->dev; struct gb_message *request; struct gb_gpio_irq_event_request *event; + u8 type = op->type; int irq; struct irq_desc *desc; @@ -622,8 +624,10 @@ static int gb_gpio_to_irq(struct gpio_chip *chip, unsigned offset) return irq_find_mapping(ggc->irqdomain, offset); } -static int gb_gpio_connection_init(struct gb_connection *connection) +static int gb_gpio_probe(struct gpbridge_device *gpbdev, + const struct gpbridge_device_id *id) { + struct gb_connection *connection; struct gb_gpio_controller *ggc; struct gpio_chip *gpio; struct irq_chip *irqc; @@ -632,12 +636,31 @@ static int gb_gpio_connection_init(struct gb_connection *connection) ggc = kzalloc(sizeof(*ggc), GFP_KERNEL); if (!ggc) return -ENOMEM; + + connection = gb_connection_create(gpbdev->bundle, + le16_to_cpu(gpbdev->cport_desc->id), + gb_gpio_request_handler); + if (IS_ERR(connection)) { + ret = PTR_ERR(connection); + goto exit_ggc_free; + } + ggc->connection = connection; gb_connection_set_data(connection, ggc); + ggc->gpbdev = gpbdev; + gb_gpbridge_set_data(gpbdev, ggc); + + ret = gb_connection_enable_tx(connection); + if (ret) + goto exit_connection_destroy; + + ret = gb_gpbridge_get_version(connection); + if (ret) + goto exit_connection_disable; ret = gb_gpio_controller_setup(ggc); if (ret) - goto err_free_controller; + goto exit_connection_disable; irqc = &ggc->irqc; irqc->irq_mask = gb_gpio_irq_mask; @@ -653,9 +676,9 @@ static int gb_gpio_connection_init(struct gb_connection *connection) gpio->label = "greybus_gpio"; #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0) - gpio->parent = &connection->bundle->dev; + gpio->parent = &gpbdev->dev; #else - gpio->dev = &connection->bundle->dev; + gpio->dev = &gpbdev->dev; #endif gpio->owner = THIS_MODULE; @@ -672,11 +695,15 @@ static int gb_gpio_connection_init(struct gb_connection *connection) gpio->ngpio = ggc->line_max + 1; gpio->can_sleep = true; + ret = gb_connection_enable(connection); + if (ret) + goto exit_line_free; + ret = gpiochip_add(gpio); if (ret) { dev_err(&connection->bundle->dev, "failed to add gpio chip: %d\n", ret); - goto err_free_lines; + goto exit_line_free; } ret = gb_gpio_irqchip_add(gpio, irqc, 0, @@ -684,42 +711,47 @@ static int gb_gpio_connection_init(struct gb_connection *connection) if (ret) { dev_err(&connection->bundle->dev, "failed to add irq chip: %d\n", ret); - goto irqchip_err; + goto exit_gpiochip_remove; } return 0; -irqchip_err: +exit_gpiochip_remove: gb_gpiochip_remove(gpio); -err_free_lines: +exit_line_free: kfree(ggc->lines); -err_free_controller: +exit_connection_disable: + gb_connection_disable(connection); +exit_connection_destroy: + gb_connection_destroy(connection); +exit_ggc_free: kfree(ggc); return ret; } -static void gb_gpio_connection_exit(struct gb_connection *connection) +static void gb_gpio_remove(struct gpbridge_device *gpbdev) { - struct gb_gpio_controller *ggc = gb_connection_get_data(connection); - - if (!ggc) - return; + struct gb_gpio_controller *ggc = gb_gpbridge_get_data(gpbdev); + struct gb_connection *connection = ggc->connection; + gb_connection_disable_rx(connection); gb_gpio_irqchip_remove(ggc); gb_gpiochip_remove(&ggc->chip); - /* kref_put(ggc->connection) */ + gb_connection_disable(connection); + gb_connection_destroy(connection); kfree(ggc->lines); kfree(ggc); } -static struct gb_protocol gpio_protocol = { - .name = "gpio", - .id = GREYBUS_PROTOCOL_GPIO, - .major = GB_GPIO_VERSION_MAJOR, - .minor = GB_GPIO_VERSION_MINOR, - .connection_init = gb_gpio_connection_init, - .connection_exit = gb_gpio_connection_exit, - .request_recv = gb_gpio_request_recv, +static const struct gpbridge_device_id gb_gpio_id_table[] = { + { GPBRIDGE_PROTOCOL(GREYBUS_PROTOCOL_GPIO) }, + { }, }; -gb_builtin_protocol_driver(gpio_protocol); +static struct gpbridge_driver gpio_driver = { + .name = "gpio", + .probe = gb_gpio_probe, + .remove = gb_gpio_remove, + .id_table = gb_gpio_id_table, +}; +gb_gpbridge_builtin_driver(gpio_driver); diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index f734646..ee122ad 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -236,7 +236,6 @@ static void legacy_disconnect(struct gb_bundle *bundle) } static const struct greybus_bundle_id legacy_id_table[] = { - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_GPIO) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_USB) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SDIO) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SPI) }, -- cgit v0.10.2 From dcd2086aa87e274e2f2f96eae449a27548637dd9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Thu, 5 May 2016 14:32:34 +0530 Subject: greybus: SDIO: convert to a gpbridge driver This converts the SDIO driver to be a gpbridge driver, moving it away from the "legacy" interface. Testing Done: Tested on gbsim. Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> [vaibhav.hiremath@linaro.org: 1.Changed code to retain init/exit fns of drivers. 2.Exit path fix. 3. Fixed review comments] Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Tested-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c index a65ab16..d228e27 100644 --- a/drivers/staging/greybus/gpbridge.c +++ b/drivers/staging/greybus/gpbridge.c @@ -255,6 +255,7 @@ static const struct greybus_bundle_id gb_gpbridge_id_table[] = { { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_GPIO) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_I2C) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_PWM) }, + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SDIO) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_UART) }, { }, }; @@ -295,8 +296,8 @@ static int __init gpbridge_init(void) pr_err("error initializing uart driver\n"); goto error_uart; } - if (gb_sdio_protocol_init()) { - pr_err("error initializing sdio protocol\n"); + if (gb_sdio_driver_init()) { + pr_err("error initializing sdio driver\n"); goto error_sdio; } if (gb_usb_protocol_init()) { @@ -319,7 +320,7 @@ error_spi: error_i2c: gb_usb_protocol_exit(); error_usb: - gb_sdio_protocol_exit(); + gb_sdio_driver_exit(); error_sdio: gb_uart_driver_exit(); error_uart: @@ -340,7 +341,7 @@ static void __exit gpbridge_exit(void) gb_spi_protocol_exit(); gb_i2c_driver_exit(); gb_usb_protocol_exit(); - gb_sdio_protocol_exit(); + gb_sdio_driver_exit(); gb_uart_driver_exit(); gb_pwm_driver_exit(); gb_gpio_driver_exit(); diff --git a/drivers/staging/greybus/gpbridge.h b/drivers/staging/greybus/gpbridge.h index f5161c5..3f1d19e 100644 --- a/drivers/staging/greybus/gpbridge.h +++ b/drivers/staging/greybus/gpbridge.h @@ -75,8 +75,8 @@ extern void gb_pwm_driver_exit(void); extern int gb_uart_driver_init(void); extern void gb_uart_driver_exit(void); -extern int gb_sdio_protocol_init(void); -extern void gb_sdio_protocol_exit(void); +extern int gb_sdio_driver_init(void); +extern void gb_sdio_driver_exit(void); extern int gb_usb_protocol_init(void); extern void gb_usb_protocol_exit(void); diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index ee122ad..d94282d 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -237,7 +237,6 @@ static void legacy_disconnect(struct gb_bundle *bundle) static const struct greybus_bundle_id legacy_id_table[] = { { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_USB) }, - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SDIO) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SPI) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_CAMERA) }, { } diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index d4cbcb9..8ee4d4c 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -19,6 +19,7 @@ struct gb_sdio_host { struct gb_connection *connection; + struct gpbridge_device *gpbdev; struct mmc_host *mmc; struct mmc_request *mrq; struct mutex lock; /* lock for this host */ @@ -199,11 +200,12 @@ static int _gb_sdio_process_events(struct gb_sdio_host *host, u8 event) return 0; } -static int gb_sdio_event_recv(u8 type, struct gb_operation *op) +static int gb_sdio_request_handler(struct gb_operation *op) { struct gb_sdio_host *host = gb_connection_get_data(op->connection); struct gb_message *request; struct gb_sdio_event_request *payload; + u8 type = op->type; int ret = 0; u8 event; @@ -706,27 +708,47 @@ static const struct mmc_host_ops gb_sdio_ops = { .get_cd = gb_mmc_get_cd, }; -static int gb_sdio_connection_init(struct gb_connection *connection) +static int gb_sdio_probe(struct gpbridge_device *gpbdev, + const struct gpbridge_device_id *id) { + struct gb_connection *connection; struct mmc_host *mmc; struct gb_sdio_host *host; size_t max_buffer; int ret = 0; - mmc = mmc_alloc_host(sizeof(*host), &connection->bundle->dev); + mmc = mmc_alloc_host(sizeof(*host), &gpbdev->dev); if (!mmc) return -ENOMEM; + connection = gb_connection_create(gpbdev->bundle, + le16_to_cpu(gpbdev->cport_desc->id), + gb_sdio_request_handler); + if (IS_ERR(connection)) { + ret = PTR_ERR(connection); + goto exit_mmc_free; + } + host = mmc_priv(mmc); host->mmc = mmc; host->removed = true; host->connection = connection; gb_connection_set_data(connection, host); + host->gpbdev = gpbdev; + gb_gpbridge_set_data(gpbdev, host); + + ret = gb_connection_enable_tx(connection); + if (ret) + goto exit_connection_destroy; + + ret = gb_gpbridge_get_version(connection); + if (ret) + goto exit_connection_disable; ret = gb_sdio_get_caps(host); if (ret < 0) - goto free_mmc; + goto exit_connection_disable; mmc->ops = &gb_sdio_ops; @@ -740,45 +762,50 @@ static int gb_sdio_connection_init(struct gb_connection *connection) host->xfer_buffer = kzalloc(max_buffer, GFP_KERNEL); if (!host->xfer_buffer) { ret = -ENOMEM; - goto free_mmc; + goto exit_connection_disable; } mutex_init(&host->lock); spin_lock_init(&host->xfer); host->mrq_workqueue = alloc_workqueue("mmc-%s", 0, 1, - dev_name(&connection->bundle->dev)); + dev_name(&gpbdev->dev)); if (!host->mrq_workqueue) { ret = -ENOMEM; - goto free_buffer; + goto exit_buf_free; } INIT_WORK(&host->mrqwork, gb_sdio_mrq_work); + ret = gb_connection_enable(connection); + if (ret) + goto exit_wq_destroy; + ret = mmc_add_host(mmc); if (ret < 0) - goto free_work; + goto exit_wq_destroy; host->removed = false; ret = _gb_sdio_process_events(host, host->queued_events); host->queued_events = 0; return ret; -free_work: +exit_wq_destroy: destroy_workqueue(host->mrq_workqueue); -free_buffer: +exit_buf_free: kfree(host->xfer_buffer); -free_mmc: - gb_connection_set_data(connection, NULL); +exit_connection_disable: + gb_connection_disable(connection); +exit_connection_destroy: + gb_connection_destroy(connection); +exit_mmc_free: mmc_free_host(mmc); return ret; } -static void gb_sdio_connection_exit(struct gb_connection *connection) +static void gb_sdio_remove(struct gpbridge_device *gpbdev) { + struct gb_sdio_host *host = gb_gpbridge_get_data(gpbdev); + struct gb_connection *connection = host->connection; struct mmc_host *mmc; - struct gb_sdio_host *host = gb_connection_get_data(connection); - - if (!host) - return; mutex_lock(&host->lock); host->removed = true; @@ -788,19 +815,23 @@ static void gb_sdio_connection_exit(struct gb_connection *connection) flush_workqueue(host->mrq_workqueue); destroy_workqueue(host->mrq_workqueue); + gb_connection_disable_rx(connection); mmc_remove_host(mmc); + gb_connection_disable(connection); + gb_connection_destroy(connection); kfree(host->xfer_buffer); mmc_free_host(mmc); } -static struct gb_protocol sdio_protocol = { - .name = "sdio", - .id = GREYBUS_PROTOCOL_SDIO, - .major = GB_SDIO_VERSION_MAJOR, - .minor = GB_SDIO_VERSION_MINOR, - .connection_init = gb_sdio_connection_init, - .connection_exit = gb_sdio_connection_exit, - .request_recv = gb_sdio_event_recv, +static const struct gpbridge_device_id gb_sdio_id_table[] = { + { GPBRIDGE_PROTOCOL(GREYBUS_PROTOCOL_SDIO) }, + { }, }; -gb_builtin_protocol_driver(sdio_protocol); +static struct gpbridge_driver sdio_driver = { + .name = "sdio", + .probe = gb_sdio_probe, + .remove = gb_sdio_remove, + .id_table = gb_sdio_id_table, +}; +gb_gpbridge_builtin_driver(sdio_driver); -- cgit v0.10.2 From ba3e67001b42626dec862410310d30db586074d5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Thu, 5 May 2016 14:32:35 +0530 Subject: greybus: SPI: convert to a gpbridge driver This converts the SPI driver to be a gpbridge driver, moving it away from the "legacy" interface. Testing Done: Tested on gbsim. Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> [vaibhav.hiremath@linaro.org: 1.Changed code to retain init/exit fns of drivers. 2.Exit path fix. 3. Fixed review comments] Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Tested-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c index d228e27..1dc6c8f 100644 --- a/drivers/staging/greybus/gpbridge.c +++ b/drivers/staging/greybus/gpbridge.c @@ -256,6 +256,7 @@ static const struct greybus_bundle_id gb_gpbridge_id_table[] = { { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_I2C) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_PWM) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SDIO) }, + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SPI) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_UART) }, { }, }; @@ -308,8 +309,8 @@ static int __init gpbridge_init(void) pr_err("error initializing i2c driver\n"); goto error_i2c; } - if (gb_spi_protocol_init()) { - pr_err("error initializing spi protocol\n"); + if (gb_spi_driver_init()) { + pr_err("error initializing spi driver\n"); goto error_spi; } @@ -338,7 +339,7 @@ module_init(gpbridge_init); static void __exit gpbridge_exit(void) { - gb_spi_protocol_exit(); + gb_spi_driver_exit(); gb_i2c_driver_exit(); gb_usb_protocol_exit(); gb_sdio_driver_exit(); diff --git a/drivers/staging/greybus/gpbridge.h b/drivers/staging/greybus/gpbridge.h index 3f1d19e..ab39003 100644 --- a/drivers/staging/greybus/gpbridge.h +++ b/drivers/staging/greybus/gpbridge.h @@ -84,8 +84,8 @@ extern void gb_usb_protocol_exit(void); extern int gb_i2c_driver_init(void); extern void gb_i2c_driver_exit(void); -extern int gb_spi_protocol_init(void); -extern void gb_spi_protocol_exit(void); +extern int gb_spi_driver_init(void); +extern void gb_spi_driver_exit(void); #endif /* __GPBRIDGE_H */ diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index d94282d..95d1eda 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -237,7 +237,6 @@ static void legacy_disconnect(struct gb_bundle *bundle) static const struct greybus_bundle_id legacy_id_table[] = { { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_USB) }, - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SPI) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_CAMERA) }, { } }; diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index ce706ed..dc811b1 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -18,6 +18,7 @@ struct gb_spi { struct gb_connection *connection; + struct gpbridge_device *gpbdev; struct spi_transfer *first_xfer; struct spi_transfer *last_xfer; u32 rx_xfer_offset; @@ -174,7 +175,7 @@ gb_spi_operation_create(struct gb_spi *spi, struct gb_connection *connection, spi->last_xfer = xfer; if (!xfer->tx_buf && !xfer->rx_buf) { - dev_err(&connection->bundle->dev, + dev_err(&spi->gpbdev->dev, "bufferless transfer, length %u\n", xfer->len); msg->state = GB_SPI_STATE_MSG_ERROR; return NULL; @@ -342,7 +343,7 @@ static int gb_spi_transfer_one_message(struct spi_master *master, if (response) gb_spi_decode_response(spi, msg, response); } else { - dev_err(&connection->bundle->dev, + dev_err(&spi->gpbdev->dev, "transfer operation failed: %d\n", ret); msg->state = GB_SPI_STATE_MSG_ERROR; } @@ -450,28 +451,48 @@ static int gb_spi_setup_device(struct gb_spi *spi, u8 cs) return 0; } -static int gb_spi_connection_init(struct gb_connection *connection) +static int gb_spi_probe(struct gpbridge_device *gpbdev, + const struct gpbridge_device_id *id) { + struct gb_connection *connection; struct gb_spi *spi; struct spi_master *master; int ret; u8 i; /* Allocate master with space for data */ - master = spi_alloc_master(&connection->bundle->dev, sizeof(*spi)); + master = spi_alloc_master(&gpbdev->dev, sizeof(*spi)); if (!master) { - dev_err(&connection->bundle->dev, "cannot alloc SPI master\n"); + dev_err(&gpbdev->dev, "cannot alloc SPI master\n"); return -ENOMEM; } + connection = gb_connection_create(gpbdev->bundle, + le16_to_cpu(gpbdev->cport_desc->id), + NULL); + if (IS_ERR(connection)) { + ret = PTR_ERR(connection); + goto exit_spi_put; + } + spi = spi_master_get_devdata(master); spi->connection = connection; gb_connection_set_data(connection, master); + spi->gpbdev = gpbdev; + gb_gpbridge_set_data(gpbdev, master); + + ret = gb_connection_enable(connection); + if (ret) + goto exit_connection_destroy; + + ret = gb_gpbridge_get_version(connection); + if (ret) + goto exit_connection_disable; /* get master configuration */ ret = gb_spi_get_master_config(spi); if (ret) - goto out_put_master; + goto exit_connection_disable; master->bus_num = -1; /* Allow spi-core to allocate it dynamically */ master->num_chipselect = spi->num_chipselect; @@ -486,42 +507,54 @@ static int gb_spi_connection_init(struct gb_connection *connection) ret = spi_register_master(master); if (ret < 0) - goto out_put_master; + goto exit_connection_disable; /* now, fetch the devices configuration */ for (i = 0; i < spi->num_chipselect; i++) { ret = gb_spi_setup_device(spi, i); if (ret < 0) { - dev_err(&connection->bundle->dev, - "failed to allocated spi device: %d\n", ret); - spi_unregister_master(master); - break; + dev_err(&gpbdev->dev, + "failed to allocate spi device %d: %d\n", + i, ret); + goto exit_spi_unregister; } } return ret; -out_put_master: +exit_spi_unregister: + spi_unregister_master(master); +exit_connection_disable: + gb_connection_disable(connection); +exit_connection_destroy: + gb_connection_destroy(connection); +exit_spi_put: spi_master_put(master); return ret; } -static void gb_spi_connection_exit(struct gb_connection *connection) +static void gb_spi_remove(struct gpbridge_device *gpbdev) { - struct spi_master *master = gb_connection_get_data(connection); + struct spi_master *master = gb_gpbridge_get_data(gpbdev); + struct gb_spi *spi = spi_master_get_devdata(master); + struct gb_connection *connection = spi->connection; spi_unregister_master(master); + gb_connection_disable(connection); + gb_connection_destroy(connection); + spi_master_put(master); } -static struct gb_protocol spi_protocol = { - .name = "spi", - .id = GREYBUS_PROTOCOL_SPI, - .major = GB_SPI_VERSION_MAJOR, - .minor = GB_SPI_VERSION_MINOR, - .connection_init = gb_spi_connection_init, - .connection_exit = gb_spi_connection_exit, - .request_recv = NULL, +static const struct gpbridge_device_id gb_spi_id_table[] = { + { GPBRIDGE_PROTOCOL(GREYBUS_PROTOCOL_SPI) }, + { }, }; -gb_builtin_protocol_driver(spi_protocol); +static struct gpbridge_driver spi_driver = { + .name = "spi", + .probe = gb_spi_probe, + .remove = gb_spi_remove, + .id_table = gb_spi_id_table, +}; +gb_gpbridge_builtin_driver(spi_driver); -- cgit v0.10.2 From 4dda7e96cfc6474d88682547180a9e42687c5a6e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Thu, 5 May 2016 14:32:36 +0530 Subject: greybus: USB: convert to a gpbridge driver This converts the USB driver to be a gpbridge driver, moving it away from the "legacy" interface. It's not like this code even does anything at the moment, how much trouble could we cause with this change? :) Testing Done: Tested on gbsim. Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> [vaibhav.hiremath@linaro.org: 1.Changed code to retain init/exit fns of drivers. 2.Exit path fix. 3. Fixed review comments] Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Tested-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c index 1dc6c8f..993cfac 100644 --- a/drivers/staging/greybus/gpbridge.c +++ b/drivers/staging/greybus/gpbridge.c @@ -258,6 +258,7 @@ static const struct greybus_bundle_id gb_gpbridge_id_table[] = { { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SDIO) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SPI) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_UART) }, + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_USB) }, { }, }; MODULE_DEVICE_TABLE(greybus, gb_gpbridge_id_table); @@ -301,8 +302,8 @@ static int __init gpbridge_init(void) pr_err("error initializing sdio driver\n"); goto error_sdio; } - if (gb_usb_protocol_init()) { - pr_err("error initializing usb protocol\n"); + if (gb_usb_driver_init()) { + pr_err("error initializing usb driver\n"); goto error_usb; } if (gb_i2c_driver_init()) { @@ -319,7 +320,7 @@ static int __init gpbridge_init(void) error_spi: gb_i2c_driver_exit(); error_i2c: - gb_usb_protocol_exit(); + gb_usb_driver_exit(); error_usb: gb_sdio_driver_exit(); error_sdio: @@ -333,7 +334,7 @@ error_gpio: error_gpbridge: bus_unregister(&gpbridge_bus_type); ida_destroy(&gpbridge_id); - return -EPROTO; + return retval; } module_init(gpbridge_init); @@ -341,7 +342,7 @@ static void __exit gpbridge_exit(void) { gb_spi_driver_exit(); gb_i2c_driver_exit(); - gb_usb_protocol_exit(); + gb_usb_driver_exit(); gb_sdio_driver_exit(); gb_uart_driver_exit(); gb_pwm_driver_exit(); diff --git a/drivers/staging/greybus/gpbridge.h b/drivers/staging/greybus/gpbridge.h index ab39003..1af20d8 100644 --- a/drivers/staging/greybus/gpbridge.h +++ b/drivers/staging/greybus/gpbridge.h @@ -78,8 +78,8 @@ extern void gb_uart_driver_exit(void); extern int gb_sdio_driver_init(void); extern void gb_sdio_driver_exit(void); -extern int gb_usb_protocol_init(void); -extern void gb_usb_protocol_exit(void); +extern int gb_usb_driver_init(void); +extern void gb_usb_driver_exit(void); extern int gb_i2c_driver_init(void); extern void gb_i2c_driver_exit(void); diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index 95d1eda..06bd85c 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -236,7 +236,6 @@ static void legacy_disconnect(struct gb_bundle *bundle) } static const struct greybus_bundle_id legacy_id_table[] = { - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_USB) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_CAMERA) }, { } }; diff --git a/drivers/staging/greybus/usb.c b/drivers/staging/greybus/usb.c index 25a6c7e..2b4789b 100644 --- a/drivers/staging/greybus/usb.c +++ b/drivers/staging/greybus/usb.c @@ -38,6 +38,7 @@ struct gb_usb_hub_control_response { struct gb_usb_device { struct gb_connection *connection; + struct gpbridge_device *gpbdev; }; static inline struct gb_usb_device *to_gb_usb_device(struct usb_hcd *hcd) @@ -58,8 +59,7 @@ static void hcd_stop(struct usb_hcd *hcd) ret = gb_operation_sync(dev->connection, GB_USB_TYPE_HCD_STOP, NULL, 0, NULL, 0); if (ret) - dev_err(&dev->connection->bundle->dev, - "HCD stop failed '%d'\n", ret); + dev_err(&dev->gpbdev->dev, "HCD stop failed '%d'\n", ret); } static int hcd_start(struct usb_hcd *hcd) @@ -71,8 +71,7 @@ static int hcd_start(struct usb_hcd *hcd) ret = gb_operation_sync(dev->connection, GB_USB_TYPE_HCD_START, NULL, 0, NULL, 0); if (ret) { - dev_err(&dev->connection->bundle->dev, - "HCD start failed '%d'\n", ret); + dev_err(&dev->gpbdev->dev, "HCD start failed '%d'\n", ret); return ret; } @@ -162,24 +161,43 @@ static struct hc_driver usb_gb_hc_driver = { .hub_control = hub_control, }; -static int gb_usb_connection_init(struct gb_connection *connection) +static int gb_usb_probe(struct gpbridge_device *gpbdev, + const struct gpbridge_device_id *id) { - struct device *dev = &connection->bundle->dev; + struct gb_connection *connection; + struct device *dev = &gpbdev->dev; struct gb_usb_device *gb_usb_dev; struct usb_hcd *hcd; - int retval; hcd = usb_create_hcd(&usb_gb_hc_driver, dev, dev_name(dev)); if (!hcd) return -ENOMEM; + connection = gb_connection_create(gpbdev->bundle, + le16_to_cpu(gpbdev->cport_desc->id), + NULL); + if (IS_ERR(connection)) { + retval = PTR_ERR(connection); + goto exit_usb_put; + } + gb_usb_dev = to_gb_usb_device(hcd); gb_usb_dev->connection = connection; gb_connection_set_data(connection, gb_usb_dev); + gb_usb_dev->gpbdev = gpbdev; + gb_gpbridge_set_data(gpbdev, gb_usb_dev); hcd->has_tt = 1; + retval = gb_connection_enable(connection); + if (retval) + goto exit_connection_destroy; + + retval = gb_gpbridge_get_version(connection); + if (retval) + goto exit_connection_disable; + /* * FIXME: The USB bridged-PHY protocol driver depends on changes to * USB core which are not yet upstream. @@ -189,38 +207,46 @@ static int gb_usb_connection_init(struct gb_connection *connection) if (1) { dev_warn(dev, "USB protocol disabled\n"); retval = -EPROTONOSUPPORT; - goto err_put_hcd; + goto exit_connection_disable; } retval = usb_add_hcd(hcd, 0, 0); if (retval) - goto err_put_hcd; + goto exit_connection_disable; return 0; -err_put_hcd: +exit_connection_disable: + gb_connection_disable(connection); +exit_connection_destroy: + gb_connection_destroy(connection); +exit_usb_put: usb_put_hcd(hcd); return retval; } -static void gb_usb_connection_exit(struct gb_connection *connection) +static void gb_usb_remove(struct gpbridge_device *gpbdev) { - struct gb_usb_device *gb_usb_dev = gb_connection_get_data(connection); + struct gb_usb_device *gb_usb_dev = gb_gpbridge_get_data(gpbdev); + struct gb_connection *connection = gb_usb_dev->connection; struct usb_hcd *hcd = gb_usb_device_to_hcd(gb_usb_dev); usb_remove_hcd(hcd); + gb_connection_disable(connection); + gb_connection_destroy(connection); usb_put_hcd(hcd); } -static struct gb_protocol usb_protocol = { - .name = "usb", - .id = GREYBUS_PROTOCOL_USB, - .major = GB_USB_VERSION_MAJOR, - .minor = GB_USB_VERSION_MINOR, - .connection_init = gb_usb_connection_init, - .connection_exit = gb_usb_connection_exit, - .request_recv = NULL, /* FIXME we have requests!!! */ +static const struct gpbridge_device_id gb_usb_id_table[] = { + { GPBRIDGE_PROTOCOL(GREYBUS_PROTOCOL_USB) }, + { }, }; -gb_builtin_protocol_driver(usb_protocol); +static struct gpbridge_driver usb_driver = { + .name = "usb", + .probe = gb_usb_probe, + .remove = gb_usb_remove, + .id_table = gb_usb_id_table, +}; +gb_gpbridge_builtin_driver(usb_driver); -- cgit v0.10.2 From ceadf9def1329c856fe94ca8aecc9ff7866e827b Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Date: Thu, 5 May 2016 14:32:37 +0530 Subject: greybus: Documentation: Add sysfs information about bridged-phy device Update the documentation (sysfs-bus-greybus) for recent conversion of bridged-phy drivers to real drivers. Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Tested-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 3740173..8605d70 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -162,6 +162,14 @@ Contact: Greg Kroah-Hartman <greg@kroah.com> Description: The interface-unique id of the bundle B. +What: /sys/bus/greybus/devices/N-M.I.B/gpbX +Date: April 2016 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman <greg@kroah.com> +Description: + The General Purpose Bridged PHY device of the bundle B, + where X is a dynamically assigned 0-based id. + What: /sys/bus/greybus/devices/N-M.I.B/state Date: October 2015 KernelVersion: 4.XX -- cgit v0.10.2 From 73d292d8381d9c384796c876ba752ccd18a09d1f Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 5 May 2016 14:32:38 +0530 Subject: greybus: uart: Kill reference_count hack This was done long back and was probably the best bet then, but it looks really bad to have it this way now. Kill the hack and implement proper driver init()/exit() routines to do the same thing. Tested using gbsim by hotplugging uart manifest and removing it later. Also tried removing the gb-phy module to test the exit path properly. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index eb83c04..0d8fcb5 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -65,7 +65,6 @@ struct gb_tty { static struct tty_driver *gb_tty_driver; static DEFINE_IDR(tty_minors); static DEFINE_MUTEX(table_lock); -static atomic_t reference_count = ATOMIC_INIT(0); static int gb_uart_receive_data_handler(struct gb_operation *op) { @@ -553,6 +552,7 @@ static int wait_serial_change(struct gb_tty *gb_tty, unsigned long arg) } while (!retval); return retval; + } static int get_serial_usage(struct gb_tty *gb_tty, @@ -619,9 +619,6 @@ static const struct tty_operations gb_ops = { static struct tty_port_operations null_ops = { }; -static int gb_tty_init(void); -static void gb_tty_exit(void); - static int gb_uart_probe(struct gpbridge_device *gpbdev, const struct gpbridge_device_id *id) { @@ -632,20 +629,9 @@ static int gb_uart_probe(struct gpbridge_device *gpbdev, int retval; int minor; - /* First time here, initialize the tty structures */ - if (atomic_inc_return(&reference_count) == 1) { - retval = gb_tty_init(); - if (retval) { - atomic_dec(&reference_count); - return retval; - } - } - gb_tty = kzalloc(sizeof(*gb_tty), GFP_KERNEL); - if (!gb_tty) { - retval = -ENOMEM; - goto exit_tty; - } + if (!gb_tty) + return -ENOMEM; connection = gb_connection_create(gpbdev->bundle, le16_to_cpu(gpbdev->cport_desc->id), @@ -737,9 +723,6 @@ exit_connection_destroy: gb_connection_destroy(connection); exit_tty_free: kfree(gb_tty); -exit_tty: - if (atomic_dec_return(&reference_count) == 0) - gb_tty_exit(); return retval; } @@ -772,10 +755,6 @@ static void gb_uart_remove(struct gpbridge_device *gpbdev) gb_connection_destroy(connection); kfree(gb_tty->buffer); kfree(gb_tty); - - /* If last device is gone, tear down the tty structures */ - if (atomic_dec_return(&reference_count) == 0) - gb_tty_exit(); } static int gb_tty_init(void) @@ -832,4 +811,26 @@ static struct gpbridge_driver uart_driver = { .remove = gb_uart_remove, .id_table = gb_uart_id_table, }; -gb_gpbridge_builtin_driver(uart_driver); + +int gb_uart_driver_init(void) +{ + int ret; + + ret = gb_tty_init(); + if (ret) + return ret; + + ret = gb_gpbridge_register(&uart_driver); + if (ret) { + gb_tty_exit(); + return ret; + } + + return 0; +} + +void gb_uart_driver_exit(void) +{ + gb_gpbridge_deregister(&uart_driver); + gb_tty_exit(); +} -- cgit v0.10.2 From 5015d5cff9ff0aabbe744522f3c5b5a945a649ef Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Thu, 5 May 2016 15:34:54 +0100 Subject: greybus: greybus_trace.h: Fix dodgy indentation We should use tabs not spaces when indenting multi-line macros and ensure that the relevant '\' characters are aligned to each-other. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Reviewed-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h index 6f3e101..849cfa0 100644 --- a/drivers/staging/greybus/greybus_trace.h +++ b/drivers/staging/greybus/greybus_trace.h @@ -17,9 +17,9 @@ struct gb_message; struct gb_host_device; -#define gb_bundle_name(message) \ - (message->operation->connection->bundle ? \ - dev_name(&message->operation->connection->bundle->dev) : \ +#define gb_bundle_name(message) \ + (message->operation->connection->bundle ? \ + dev_name(&message->operation->connection->bundle->dev) : \ dev_name(&message->operation->connection->hd->svc->dev)) DECLARE_EVENT_CLASS(gb_message, -- cgit v0.10.2 From 596e4a1933e4f6f2b19d5c05884d35cb91e3cf58 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Thu, 5 May 2016 15:34:55 +0100 Subject: greybus: greybus_protocols.h Add SVC_TIMESYNC_WAKE_PINS_ACQUIRE/RELEASE Its necessary to establish an initial state on the wake-detect lines before enabling timesync on APB/GPB in order to ensure all GPIO edge-transitions are correctly interpreted by the receiving processor. This patch adds the operations defined in the Greybus specification to greybus_protocols.h, this involves adding the SVC_TIMESYNC_WAKE_PINS_ACQUIRE and SVC_TIMESYNC_WAKE_PINS_RELEASE commands and moving the 'strobe_mask' parameter from 'struct gb_svc_timesync_enable_request' to 'struct gb_svc_timesync_wd_pins_acquire_request' since the communication of the strobe_mask will be communicated before preparing any of the bridges to receive the TimeSync pulses. A separate patch to the greybus specification describes the transition between the wake sub-state and the timesync sub-state. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Reviewed-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Reviewed-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 5f5b928..d5a63d3 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -835,6 +835,8 @@ struct gb_spi_transfer_response { #define GB_SVC_TYPE_PWRMON_RAIL_NAMES_GET 0x15 #define GB_SVC_TYPE_PWRMON_SAMPLE_GET 0x16 #define GB_SVC_TYPE_PWRMON_INTF_SAMPLE_GET 0x17 +#define GB_SVC_TYPE_TIMESYNC_WAKE_PINS_ACQUIRE 0x18 +#define GB_SVC_TYPE_TIMESYNC_WAKE_PINS_RELEASE 0x19 #define GB_SVC_TYPE_MODULE_INSERTED 0x1f #define GB_SVC_TYPE_MODULE_REMOVED 0x20 #define GB_SVC_TYPE_INTF_ACTIVATE 0x27 @@ -955,7 +957,6 @@ struct gb_svc_timesync_enable_request { __u8 count; __le64 frame_time; __le32 strobe_delay; - __le32 strobe_mask; __le32 refclk; } __packed; /* timesync enable response has no payload */ @@ -965,6 +966,15 @@ struct gb_svc_timesync_authoritative_response { __le64 frame_time[GB_TIMESYNC_MAX_STROBES]; }; +struct gb_svc_timesync_wake_pins_acquire_request { + __le32 strobe_mask; +}; + +/* timesync wake pins acquire response has no payload */ + +/* timesync wake pins release request has no payload */ +/* timesync wake pins release response has no payload */ + #define GB_SVC_UNIPRO_FAST_MODE 0x01 #define GB_SVC_UNIPRO_SLOW_MODE 0x02 #define GB_SVC_UNIPRO_FAST_AUTO_MODE 0x04 -- cgit v0.10.2 From 521d0d538036267fcc1bfab9f2f6e550250caf72 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Thu, 5 May 2016 15:34:56 +0100 Subject: greybus: greybus_protocols.h Add SVC_TIMESYNC_PING In order to verify TimeSync functionality we require a TimeSync-ping operation where the AP can command the SVC to initiate a single strobe of downstream TimeSync slaves, and report the FrameTime at the strobe. Ping will only be valid after the system has transitioned to a TIMESYNC_ACTIVE state. In the active state each TimeSync slave will graph a single incoming SVC strobe as a ping and will store its frame time. The AP will then gather each last-event FrameTime for presentation to user-space in the AP and/or further automation based on the reported FrameTimes at the SVC ping. This patch adds the SVC ping command definition to greybus_protocols.h. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Reviewed-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index d5a63d3..9b21a35 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -837,6 +837,7 @@ struct gb_spi_transfer_response { #define GB_SVC_TYPE_PWRMON_INTF_SAMPLE_GET 0x17 #define GB_SVC_TYPE_TIMESYNC_WAKE_PINS_ACQUIRE 0x18 #define GB_SVC_TYPE_TIMESYNC_WAKE_PINS_RELEASE 0x19 +#define GB_SVC_TYPE_TIMESYNC_PING 0x1a #define GB_SVC_TYPE_MODULE_INSERTED 0x1f #define GB_SVC_TYPE_MODULE_REMOVED 0x20 #define GB_SVC_TYPE_INTF_ACTIVATE 0x27 @@ -975,6 +976,11 @@ struct gb_svc_timesync_wake_pins_acquire_request { /* timesync wake pins release request has no payload */ /* timesync wake pins release response has no payload */ +/* timesync svc ping request has no payload */ +struct gb_svc_timesync_ping_response { + __le64 frame_time; +} __packed; + #define GB_SVC_UNIPRO_FAST_MODE 0x01 #define GB_SVC_UNIPRO_SLOW_MODE 0x02 #define GB_SVC_UNIPRO_FAST_AUTO_MODE 0x04 -- cgit v0.10.2 From 6c1ca56d85377498bec760064c02e33f4678a2dd Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Date: Thu, 5 May 2016 15:34:57 +0100 Subject: greybus: arche-platform: Rename spinlock variable lock => wake_detect_lock With addition of exported function, required for TIMESYNC operation, we need more locking mechanism for driver state, so to avoid confusion rename existing spinlock variable to its appropriate name. Testing Done: Tested on DB3.5 platform. Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Reviewed-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index d1083cf..9a11717 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -55,7 +55,7 @@ struct arche_platform_drvdata { enum svc_wakedetect_state wake_detect_state; int wake_detect_irq; - spinlock_t lock; + spinlock_t wake_lock; /* Protect wake_detect_state */ unsigned long wake_detect_start; struct notifier_block pm_notifier; @@ -117,15 +117,15 @@ static irqreturn_t arche_platform_wd_irq_thread(int irq, void *devid) struct arche_platform_drvdata *arche_pdata = devid; unsigned long flags; - spin_lock_irqsave(&arche_pdata->lock, flags); + spin_lock_irqsave(&arche_pdata->wake_lock, flags); if (arche_pdata->wake_detect_state != WD_STATE_COLDBOOT_TRIG) { /* Something is wrong */ - spin_unlock_irqrestore(&arche_pdata->lock, flags); + spin_unlock_irqrestore(&arche_pdata->wake_lock, flags); return IRQ_HANDLED; } arche_pdata->wake_detect_state = WD_STATE_COLDBOOT_START; - spin_unlock_irqrestore(&arche_pdata->lock, flags); + spin_unlock_irqrestore(&arche_pdata->wake_lock, flags); /* It should complete power cycle, so first make sure it is poweroff */ device_for_each_child(arche_pdata->dev, NULL, apb_poweroff); @@ -137,9 +137,9 @@ static irqreturn_t arche_platform_wd_irq_thread(int irq, void *devid) if (usb3613_hub_mode_ctrl(true)) dev_warn(arche_pdata->dev, "failed to control hub device\n"); - spin_lock_irqsave(&arche_pdata->lock, flags); + spin_lock_irqsave(&arche_pdata->wake_lock, flags); arche_pdata->wake_detect_state = WD_STATE_IDLE; - spin_unlock_irqrestore(&arche_pdata->lock, flags); + spin_unlock_irqrestore(&arche_pdata->wake_lock, flags); return IRQ_HANDLED; } @@ -149,7 +149,7 @@ static irqreturn_t arche_platform_wd_irq(int irq, void *devid) struct arche_platform_drvdata *arche_pdata = devid; unsigned long flags; - spin_lock_irqsave(&arche_pdata->lock, flags); + spin_lock_irqsave(&arche_pdata->wake_lock, flags); if (gpio_get_value(arche_pdata->wake_detect_gpio)) { /* wake/detect rising */ @@ -170,7 +170,9 @@ static irqreturn_t arche_platform_wd_irq(int irq, void *devid) WD_STATE_COLDBOOT_START) { arche_pdata->wake_detect_state = WD_STATE_COLDBOOT_TRIG; - spin_unlock_irqrestore(&arche_pdata->lock, flags); + spin_unlock_irqrestore( + &arche_pdata->wake_lock, + flags); return IRQ_WAKE_THREAD; } } @@ -188,7 +190,7 @@ static irqreturn_t arche_platform_wd_irq(int irq, void *devid) } } - spin_unlock_irqrestore(&arche_pdata->lock, flags); + spin_unlock_irqrestore(&arche_pdata->wake_lock, flags); return IRQ_HANDLED; } @@ -257,9 +259,9 @@ static void arche_platform_poweroff_seq(struct arche_platform_drvdata *arche_pda /* Send disconnect/detach event to SVC */ gpio_direction_output(arche_pdata->wake_detect_gpio, 0); usleep_range(100, 200); - spin_lock_irqsave(&arche_pdata->lock, flags); + spin_lock_irqsave(&arche_pdata->wake_lock, flags); arche_pdata->wake_detect_state = WD_STATE_IDLE; - spin_unlock_irqrestore(&arche_pdata->lock, flags); + spin_unlock_irqrestore(&arche_pdata->wake_lock, flags); clk_disable_unprepare(arche_pdata->svc_ref_clk); } @@ -465,7 +467,7 @@ static int arche_platform_probe(struct platform_device *pdev) arche_pdata->dev = &pdev->dev; - spin_lock_init(&arche_pdata->lock); + spin_lock_init(&arche_pdata->wake_lock); arche_pdata->wake_detect_irq = gpio_to_irq(arche_pdata->wake_detect_gpio); -- cgit v0.10.2 From 886aba558b9e63c7025cabfaff8ca17f9fc02985 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Date: Thu, 5 May 2016 15:34:58 +0100 Subject: greybus: arche-platform: Export fn to allow timesync driver to change the state With the addition of the timesync driver and looking at the hardware interfaces we have, its clear we need to add a new arche-platform state. This patch adds ARCHE_PLATFORM_STATE_TIME_SYNC to the arche-platform driver to facilitate transition to the TIME_SYNC state if-and-only-if the arche-platform driver is in the ACTIVE state. This is mainly needed as wake/detect lines are shared between TIMESYNC operation and basic control functionality of APBs. So during TIMESYNC we want to make sure that the events on wake/detect lines are ignored by the arche-platform APB reset logic. This patch adds one exported function, which can be invoked from timesync driver code, allowing, switching between ARCHE_PLATFORM_STATE_TIME_SYNC <=> ARCHE_PLATFORM_STATE_ACTIVE states. [ bryan.odonoghue@linaro.org: Added mutex, massaged commit text ] Reviewed-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Suggested-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 9a11717..4eceec3 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -55,13 +55,97 @@ struct arche_platform_drvdata { enum svc_wakedetect_state wake_detect_state; int wake_detect_irq; - spinlock_t wake_lock; /* Protect wake_detect_state */ + spinlock_t wake_lock; /* Protect wake_detect_state */ + struct mutex platform_state_mutex; /* Protect state */ unsigned long wake_detect_start; struct notifier_block pm_notifier; struct device *dev; }; +/* + * arche_platform_change_state: Change the operational state + * + * This exported function allows external drivers to change the state + * of the arche-platform driver. + * Note that this function only supports transitions between two states + * with limited functionality. + * + * - ARCHE_PLATFORM_STATE_TIME_SYNC: + * Once set, allows timesync operations between SVC <=> AP and makes + * sure that arche-platform driver ignores any subsequent events/pulses + * from SVC over wake/detect. + * + * - ARCHE_PLATFORM_STATE_ACTIVE: + * Puts back driver to active state, where any pulse from SVC on wake/detect + * line would trigger either cold/standby boot. + * Note: Transition request from this function does not trigger cold/standby + * boot. It just puts back driver book keeping variable back to ACTIVE + * state and restores the interrupt. + * + * Returns -ENODEV if device not found, -EAGAIN if the driver cannot currently + * satisfy the requested state-transition or -EINVAL for all other + * state-transition requests. + */ +int arche_platform_change_state(enum arche_platform_state state) +{ + struct arche_platform_drvdata *arche_pdata; + struct platform_device *pdev; + struct device_node *np; + int ret = -EAGAIN; + unsigned long flags; + + np = of_find_compatible_node(NULL, NULL, "google,arche-platform"); + if (!np) { + pr_err("google,arche-platform device node not found\n"); + return -ENODEV; + } + + pdev = of_find_device_by_node(np); + if (!pdev) { + pr_err("arche-platform device not found\n"); + return -ENODEV; + } + + arche_pdata = platform_get_drvdata(pdev); + + mutex_lock(&arche_pdata->platform_state_mutex); + spin_lock_irqsave(&arche_pdata->wake_lock, flags); + if (arche_pdata->wake_detect_state != WD_STATE_IDLE) { + dev_err(arche_pdata->dev, + "driver busy with wake/detect line ops\n"); + goto exit; + } + + if (arche_pdata->state == state) { + ret = 0; + goto exit; + } + + if (arche_pdata->state == ARCHE_PLATFORM_STATE_OFF || + arche_pdata->state == ARCHE_PLATFORM_STATE_STANDBY || + arche_pdata->state == ARCHE_PLATFORM_STATE_FW_FLASHING) { + dev_err(arche_pdata->dev, "busy, request to retry later\n"); + goto exit; + } + + if (state == ARCHE_PLATFORM_STATE_TIME_SYNC) { + disable_irq(arche_pdata->wake_detect_irq); + arche_pdata->state = ARCHE_PLATFORM_STATE_TIME_SYNC; + } else if (state == ARCHE_PLATFORM_STATE_ACTIVE) { + arche_pdata->state = ARCHE_PLATFORM_STATE_ACTIVE; + enable_irq(arche_pdata->wake_detect_irq); + } else { + dev_err(arche_pdata->dev, "invalid state transition request\n"); + } +exit: + spin_unlock_irqrestore(&arche_pdata->wake_lock, flags); + mutex_unlock(&arche_pdata->platform_state_mutex); + of_node_put(np); + return ret; +} +EXPORT_SYMBOL_GPL(arche_platform_change_state); + static inline void svc_reset_onoff(unsigned int gpio, bool onoff) { gpio_set_value(gpio, onoff); @@ -195,6 +279,9 @@ static irqreturn_t arche_platform_wd_irq(int irq, void *devid) return IRQ_HANDLED; } +/* + * Requires arche_pdata->platform_state_mutex to be held + */ static int arche_platform_coldboot_seq(struct arche_platform_drvdata *arche_pdata) { int ret; @@ -226,6 +313,9 @@ static int arche_platform_coldboot_seq(struct arche_platform_drvdata *arche_pdat return 0; } +/* + * Requires arche_pdata->platform_state_mutex to be held + */ static void arche_platform_fw_flashing_seq(struct arche_platform_drvdata *arche_pdata) { if (arche_pdata->state == ARCHE_PLATFORM_STATE_FW_FLASHING) @@ -246,6 +336,9 @@ static void arche_platform_fw_flashing_seq(struct arche_platform_drvdata *arche_ } +/* + * Requires arche_pdata->platform_state_mutex to be held + */ static void arche_platform_poweroff_seq(struct arche_platform_drvdata *arche_pdata) { unsigned long flags; @@ -280,9 +373,11 @@ static ssize_t state_store(struct device *dev, struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev); int ret = 0; + mutex_lock(&arche_pdata->platform_state_mutex); + if (sysfs_streq(buf, "off")) { if (arche_pdata->state == ARCHE_PLATFORM_STATE_OFF) - return count; + goto exit; /* If SVC goes down, bring down APB's as well */ device_for_each_child(arche_pdata->dev, NULL, apb_poweroff); @@ -291,19 +386,19 @@ static ssize_t state_store(struct device *dev, } else if (sysfs_streq(buf, "active")) { if (arche_pdata->state == ARCHE_PLATFORM_STATE_ACTIVE) - return count; + goto exit; ret = arche_platform_coldboot_seq(arche_pdata); assert_wakedetect(arche_pdata); } else if (sysfs_streq(buf, "standby")) { if (arche_pdata->state == ARCHE_PLATFORM_STATE_STANDBY) - return count; + goto exit; dev_warn(arche_pdata->dev, "standby state not supported\n"); } else if (sysfs_streq(buf, "fw_flashing")) { if (arche_pdata->state == ARCHE_PLATFORM_STATE_FW_FLASHING) - return count; + goto exit; /* First we want to make sure we power off everything * and then enter FW flashing state */ @@ -319,6 +414,8 @@ static ssize_t state_store(struct device *dev, ret = -EINVAL; } +exit: + mutex_unlock(&arche_pdata->platform_state_mutex); return ret ? ret : count; } @@ -336,6 +433,8 @@ static ssize_t state_show(struct device *dev, return sprintf(buf, "standby\n"); case ARCHE_PLATFORM_STATE_FW_FLASHING: return sprintf(buf, "fw_flashing\n"); + case ARCHE_PLATFORM_STATE_TIME_SYNC: + return sprintf(buf, "time_sync\n"); default: return sprintf(buf, "unknown state\n"); } @@ -349,11 +448,15 @@ static int arche_platform_pm_notifier(struct notifier_block *notifier, struct arche_platform_drvdata *arche_pdata = container_of(notifier, struct arche_platform_drvdata, pm_notifier); + int ret = NOTIFY_DONE; + mutex_lock(&arche_pdata->platform_state_mutex); switch (pm_event) { case PM_SUSPEND_PREPARE: - if (arche_pdata->state != ARCHE_PLATFORM_STATE_ACTIVE) - return NOTIFY_STOP; + if (arche_pdata->state != ARCHE_PLATFORM_STATE_ACTIVE) { + ret = NOTIFY_STOP; + break; + } device_for_each_child(arche_pdata->dev, NULL, apb_poweroff); arche_platform_poweroff_seq(arche_pdata); break; @@ -364,8 +467,9 @@ static int arche_platform_pm_notifier(struct notifier_block *notifier, default: break; } + mutex_unlock(&arche_pdata->platform_state_mutex); - return NOTIFY_DONE; + return ret; } static int arche_platform_probe(struct platform_device *pdev) @@ -468,6 +572,7 @@ static int arche_platform_probe(struct platform_device *pdev) arche_pdata->dev = &pdev->dev; spin_lock_init(&arche_pdata->wake_lock); + mutex_init(&arche_pdata->platform_state_mutex); arche_pdata->wake_detect_irq = gpio_to_irq(arche_pdata->wake_detect_gpio); @@ -489,6 +594,7 @@ static int arche_platform_probe(struct platform_device *pdev) return ret; } + mutex_lock(&arche_pdata->platform_state_mutex); ret = arche_platform_coldboot_seq(arche_pdata); if (ret) { dev_err(dev, "Failed to cold boot svc %d\n", ret); @@ -505,6 +611,8 @@ static int arche_platform_probe(struct platform_device *pdev) arche_pdata->pm_notifier.notifier_call = arche_platform_pm_notifier; ret = register_pm_notifier(&arche_pdata->pm_notifier); + mutex_unlock(&arche_pdata->platform_state_mutex); + if (ret) { dev_err(dev, "failed to register pm notifier %d\n", ret); goto err_populate; @@ -516,6 +624,7 @@ static int arche_platform_probe(struct platform_device *pdev) err_populate: arche_platform_poweroff_seq(arche_pdata); err_coldboot: + mutex_unlock(&arche_pdata->platform_state_mutex); device_remove_file(&pdev->dev, &dev_attr_state); return ret; } diff --git a/drivers/staging/greybus/arche_platform.h b/drivers/staging/greybus/arche_platform.h index 69b627b..0f2d292 100644 --- a/drivers/staging/greybus/arche_platform.h +++ b/drivers/staging/greybus/arche_platform.h @@ -15,8 +15,10 @@ enum arche_platform_state { ARCHE_PLATFORM_STATE_ACTIVE, ARCHE_PLATFORM_STATE_STANDBY, ARCHE_PLATFORM_STATE_FW_FLASHING, + ARCHE_PLATFORM_STATE_TIME_SYNC, }; +int arche_platform_change_state(enum arche_platform_state state); int __init arche_apb_init(void); void __exit arche_apb_exit(void); -- cgit v0.10.2 From c4058b7926a44387b1d2480be0f209edb74e7f1c Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Thu, 5 May 2016 15:34:59 +0100 Subject: greybus: arche-platform: Rework platform/wd-line state transition logic This patch simplifies and improves the readability of the internal state transition logic of arche platform driver state transition logic by: 1. Making a dedicated function to state-transition the platform code. 2. Condense the decision to swtich states down to a single switch statement instead of four separate if/else clauses. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Suggested-by: Alex Elder <elder@linaro.org> Reviewed-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 4eceec3..83d823c 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -63,6 +63,13 @@ struct arche_platform_drvdata { struct device *dev; }; +/* Requires calling context to hold arche_pdata->spinlock */ +static void arche_platform_set_state(struct arche_platform_drvdata *arche_pdata, + enum arche_platform_state state) +{ + arche_pdata->state = state; +} + /* * arche_platform_change_state: Change the operational state * @@ -122,22 +129,26 @@ int arche_platform_change_state(enum arche_platform_state state) goto exit; } - if (arche_pdata->state == ARCHE_PLATFORM_STATE_OFF || - arche_pdata->state == ARCHE_PLATFORM_STATE_STANDBY || - arche_pdata->state == ARCHE_PLATFORM_STATE_FW_FLASHING) { - dev_err(arche_pdata->dev, "busy, request to retry later\n"); - goto exit; - } - - if (state == ARCHE_PLATFORM_STATE_TIME_SYNC) { + switch (state) { + case ARCHE_PLATFORM_STATE_TIME_SYNC: disable_irq(arche_pdata->wake_detect_irq); - arche_pdata->state = ARCHE_PLATFORM_STATE_TIME_SYNC; - } else if (state == ARCHE_PLATFORM_STATE_ACTIVE) { - arche_pdata->state = ARCHE_PLATFORM_STATE_ACTIVE; + break; + case ARCHE_PLATFORM_STATE_ACTIVE: enable_irq(arche_pdata->wake_detect_irq); - } else { - dev_err(arche_pdata->dev, "invalid state transition request\n"); + break; + case ARCHE_PLATFORM_STATE_OFF: + case ARCHE_PLATFORM_STATE_STANDBY: + case ARCHE_PLATFORM_STATE_FW_FLASHING: + dev_err(arche_pdata->dev, "busy, request to retry later\n"); + goto exit; + default: + ret = -EINVAL; + dev_err(arche_pdata->dev, + "invalid state transition request\n"); + goto exit; } + arche_platform_set_state(arche_pdata, state); + ret = 0; exit: spin_unlock_irqrestore(&arche_pdata->wake_lock, flags); mutex_unlock(&arche_pdata->platform_state_mutex); @@ -146,6 +157,14 @@ exit: } EXPORT_SYMBOL_GPL(arche_platform_change_state); +/* Requires arche_pdata->wake_lock is held by calling context */ +static void arche_platform_set_wake_detect_state( + struct arche_platform_drvdata *arche_pdata, + enum svc_wakedetect_state state) +{ + arche_pdata->wake_detect_state = state; +} + static inline void svc_reset_onoff(unsigned int gpio, bool onoff) { gpio_set_value(gpio, onoff); @@ -208,7 +227,8 @@ static irqreturn_t arche_platform_wd_irq_thread(int irq, void *devid) return IRQ_HANDLED; } - arche_pdata->wake_detect_state = WD_STATE_COLDBOOT_START; + arche_platform_set_wake_detect_state(arche_pdata, + WD_STATE_COLDBOOT_START); spin_unlock_irqrestore(&arche_pdata->wake_lock, flags); /* It should complete power cycle, so first make sure it is poweroff */ @@ -222,7 +242,7 @@ static irqreturn_t arche_platform_wd_irq_thread(int irq, void *devid) dev_warn(arche_pdata->dev, "failed to control hub device\n"); spin_lock_irqsave(&arche_pdata->wake_lock, flags); - arche_pdata->wake_detect_state = WD_STATE_IDLE; + arche_platform_set_wake_detect_state(arche_pdata, WD_STATE_IDLE); spin_unlock_irqrestore(&arche_pdata->wake_lock, flags); return IRQ_HANDLED; @@ -247,13 +267,14 @@ static irqreturn_t arche_platform_wd_irq(int irq, void *devid) if (time_before(jiffies, arche_pdata->wake_detect_start + msecs_to_jiffies(WD_COLDBOOT_PULSE_WIDTH_MS))) { - arche_pdata->wake_detect_state = WD_STATE_IDLE; + arche_platform_set_wake_detect_state(arche_pdata, + WD_STATE_IDLE); } else { /* Check we are not in middle of irq thread already */ if (arche_pdata->wake_detect_state != WD_STATE_COLDBOOT_START) { - arche_pdata->wake_detect_state = - WD_STATE_COLDBOOT_TRIG; + arche_platform_set_wake_detect_state(arche_pdata, + WD_STATE_COLDBOOT_TRIG); spin_unlock_irqrestore( &arche_pdata->wake_lock, flags); @@ -270,7 +291,8 @@ static irqreturn_t arche_platform_wd_irq(int irq, void *devid) * it is meant for coldboot and set the flag. If wake/detect line stays low * beyond 30msec, then it is coldboot else fallback to standby boot. */ - arche_pdata->wake_detect_state = WD_STATE_BOOT_INIT; + arche_platform_set_wake_detect_state(arche_pdata, + WD_STATE_BOOT_INIT); } } @@ -308,7 +330,7 @@ static int arche_platform_coldboot_seq(struct arche_platform_drvdata *arche_pdat svc_reset_onoff(arche_pdata->svc_reset_gpio, !arche_pdata->is_reset_act_hi); - arche_pdata->state = ARCHE_PLATFORM_STATE_ACTIVE; + arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_ACTIVE); return 0; } @@ -332,7 +354,7 @@ static void arche_platform_fw_flashing_seq(struct arche_platform_drvdata *arche_ svc_reset_onoff(arche_pdata->svc_reset_gpio, !arche_pdata->is_reset_act_hi); - arche_pdata->state = ARCHE_PLATFORM_STATE_FW_FLASHING; + arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_FW_FLASHING); } @@ -353,7 +375,8 @@ static void arche_platform_poweroff_seq(struct arche_platform_drvdata *arche_pda gpio_direction_output(arche_pdata->wake_detect_gpio, 0); usleep_range(100, 200); spin_lock_irqsave(&arche_pdata->wake_lock, flags); - arche_pdata->wake_detect_state = WD_STATE_IDLE; + arche_platform_set_wake_detect_state(arche_pdata, + WD_STATE_IDLE); spin_unlock_irqrestore(&arche_pdata->wake_lock, flags); clk_disable_unprepare(arche_pdata->svc_ref_clk); @@ -363,7 +386,7 @@ static void arche_platform_poweroff_seq(struct arche_platform_drvdata *arche_pda svc_reset_onoff(arche_pdata->svc_reset_gpio, arche_pdata->is_reset_act_hi); - arche_pdata->state = ARCHE_PLATFORM_STATE_OFF; + arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_OFF); } static ssize_t state_store(struct device *dev, @@ -502,7 +525,7 @@ static int arche_platform_probe(struct platform_device *pdev) dev_err(dev, "failed to set svc-reset gpio dir:%d\n", ret); return ret; } - arche_pdata->state = ARCHE_PLATFORM_STATE_OFF; + arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_OFF); arche_pdata->svc_sysboot_gpio = of_get_named_gpio(np, "svc,sysboot-gpio", 0); @@ -567,7 +590,7 @@ static int arche_platform_probe(struct platform_device *pdev) } /* deassert wake detect */ gpio_direction_output(arche_pdata->wake_detect_gpio, 0); - arche_pdata->wake_detect_state = WD_STATE_IDLE; + arche_platform_set_wake_detect_state(arche_pdata, WD_STATE_IDLE); arche_pdata->dev = &pdev->dev; -- cgit v0.10.2 From f63a896e532b12f9104749b13861080981b64bad Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 5 May 2016 15:33:19 +0530 Subject: greybus: fw-download: Manage firmware requests with kref This patch updates the fw-download core to manage firmware requests with kref. This is required for the next patch, which will introduce timeouts for firmware downloads. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/fw-download.c b/drivers/staging/greybus/fw-download.c index e60abde..6bd2618 100644 --- a/drivers/staging/greybus/fw-download.c +++ b/drivers/staging/greybus/fw-download.c @@ -19,6 +19,9 @@ struct fw_request { char name[FW_NAME_LEN]; const struct firmware *fw; struct list_head node; + + struct kref kref; + struct fw_download *fw_download; }; struct fw_download { @@ -28,26 +31,49 @@ struct fw_download { struct ida id_map; }; -static struct fw_request *match_firmware(struct fw_download *fw_download, - u8 firmware_id) +static void fw_req_release(struct kref *kref) +{ + struct fw_request *fw_req = container_of(kref, struct fw_request, kref); + + dev_dbg(fw_req->fw_download->parent, "firmware %s released\n", + fw_req->name); + + release_firmware(fw_req->fw); + ida_simple_remove(&fw_req->fw_download->id_map, fw_req->firmware_id); + kfree(fw_req); +} + +/* Caller must call put_fw_req() after using struct fw_request */ +static struct fw_request *get_fw_req(struct fw_download *fw_download, + u8 firmware_id) { struct fw_request *fw_req; list_for_each_entry(fw_req, &fw_download->fw_requests, node) { - if (fw_req->firmware_id == firmware_id) + if (fw_req->firmware_id == firmware_id) { + kref_get(&fw_req->kref); return fw_req; + } } return NULL; } +/* + * Incoming requests are serialized for a connection, and this will never be + * racy. + */ +static void put_fw_req(struct fw_request *fw_req) +{ + kref_put(&fw_req->kref, fw_req_release); +} + static void free_firmware(struct fw_download *fw_download, struct fw_request *fw_req) { list_del(&fw_req->node); - release_firmware(fw_req->fw); - ida_simple_remove(&fw_download->id_map, fw_req->firmware_id); - kfree(fw_req); + + put_fw_req(fw_req); } /* This returns path of the firmware blob on the disk */ @@ -87,6 +113,8 @@ static struct fw_request *find_firmware(struct fw_download *fw_download, goto err_free_id; } + fw_req->fw_download = fw_download; + kref_init(&fw_req->kref); list_add(&fw_req->node, &fw_download->fw_requests); return fw_req; @@ -155,6 +183,7 @@ static int fw_download_fetch_firmware(struct gb_operation *op) const struct firmware *fw; unsigned int offset, size; u8 firmware_id; + int ret = 0; if (op->request->payload_size != sizeof(*request)) { dev_err(fw_download->parent, @@ -168,7 +197,7 @@ static int fw_download_fetch_firmware(struct gb_operation *op) size = le32_to_cpu(request->size); firmware_id = request->firmware_id; - fw_req = match_firmware(fw_download, firmware_id); + fw_req = get_fw_req(fw_download, firmware_id); if (!fw_req) { dev_err(fw_download->parent, "firmware not available for id: %02u\n", firmware_id); @@ -181,14 +210,16 @@ static int fw_download_fetch_firmware(struct gb_operation *op) dev_err(fw_download->parent, "bad fetch firmware request (offs = %u, size = %u)\n", offset, size); - return -EINVAL; + ret = -EINVAL; + goto put_fw; } if (!gb_operation_response_alloc(op, sizeof(*response) + size, GFP_KERNEL)) { dev_err(fw_download->parent, "error allocating fetch firmware response\n"); - return -ENOMEM; + ret = -ENOMEM; + goto put_fw; } response = op->response->payload; @@ -198,7 +229,10 @@ static int fw_download_fetch_firmware(struct gb_operation *op) "responding with firmware (offs = %u, size = %u)\n", offset, size); - return 0; +put_fw: + put_fw_req(fw_req); + + return ret; } static int fw_download_release_firmware(struct gb_operation *op) @@ -219,7 +253,7 @@ static int fw_download_release_firmware(struct gb_operation *op) request = op->request->payload; firmware_id = request->firmware_id; - fw_req = match_firmware(fw_download, firmware_id); + fw_req = get_fw_req(fw_download, firmware_id); if (!fw_req) { dev_err(fw_download->parent, "firmware not available for id: %02u\n", firmware_id); @@ -227,6 +261,7 @@ static int fw_download_release_firmware(struct gb_operation *op) } free_firmware(fw_download, fw_req); + put_fw_req(fw_req); dev_dbg(fw_download->parent, "release firmware\n"); -- cgit v0.10.2 From 69c8763eb883a331832b58e842fa0b01321ed9d6 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 5 May 2016 15:33:20 +0530 Subject: greybus: fw-download: Introduce timeouts for firmware downloads As per greybus specification, the AP can apply, implementation dependent, timeouts for: - The time interval between the Find Firmware Response and the first Fetch Firmware Request. - The time interval between a Fetch Firmware Response and the next Fetch Firmware Request. - The time interval between a Fetch Firmware Response and the Release Firmware Request. - The time interval between the Find Firmware Response and the Release Firmware Request. This patch implements those timeouts. The timeout period for the first three cases is fixed to one-second and the timeout for the last one is finalized at runtime, dependent on the total size of the firmware. There can be two possible paths now, which may race for freeing or getting the 'struct fw_request'. They are: - Request handler: initiated from the Module side. - Timeout handler: initiated on timeout of the programmed timer. And so a mutex is added to avoid races. Every caller which needs to access the 'struct fw_request' increments the reference count, so that the structure doesn't get freed in parallel. Once the structure is freed and reference is put by all the users, the structure is freed. If we timeout while waiting for a request from the Module, the AP frees the 'struct fw_request', but does *not* free the request-id. This is done to guarantee that a delayed request from the Module for the expired id, doesn't get access to a new 'struct fw_request' allocated later with the same id. Tested with gbsim by hacking its code to delay the release request and indefinitely fetch the same section of the firmware package. Both timed out on the AP side and the 'struct fw_request' is free properly. Further requests work fine after few are timed out. And rmmod (followed by more similar testing) works just fine. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/fw-download.c b/drivers/staging/greybus/fw-download.c index 6bd2618..0ebea37 100644 --- a/drivers/staging/greybus/fw-download.c +++ b/drivers/staging/greybus/fw-download.c @@ -8,18 +8,30 @@ */ #include <linux/firmware.h> +#include <linux/jiffies.h> +#include <linux/mutex.h> +#include <linux/timer.h> #include "firmware.h" #include "greybus.h" /* Length of the string in format: ara_%08x_%08x_%08x_%08x_%s.tftf */ #define FW_NAME_LEN 56 +/* Estimated minimum buffer size, actual size can be smaller than this */ +#define MIN_FETCH_SIZE 512 +/* Timeout, in jiffies, within which fetch or release firmware must be called */ +#define NEXT_REQ_TIMEOUT_J msecs_to_jiffies(1000) struct fw_request { u8 firmware_id; + bool disabled; + bool timedout; char name[FW_NAME_LEN]; const struct firmware *fw; struct list_head node; + struct timer_list timer; + /* Timeout, in jiffies, within which the firmware shall download */ + unsigned long release_timeout_j; struct kref kref; struct fw_download *fw_download; }; @@ -29,6 +41,7 @@ struct fw_download { struct gb_connection *connection; struct list_head fw_requests; struct ida id_map; + struct mutex mutex; }; static void fw_req_release(struct kref *kref) @@ -39,50 +52,120 @@ static void fw_req_release(struct kref *kref) fw_req->name); release_firmware(fw_req->fw); - ida_simple_remove(&fw_req->fw_download->id_map, fw_req->firmware_id); + + /* + * The request timed out and the module may send a fetch-fw or + * release-fw request later. Lets block the id we allocated for this + * request, so that the AP doesn't refer to a later fw-request (with + * same firmware_id) for the old timedout fw-request. + * + * NOTE: + * + * This also means that after 255 timeouts we will fail to service new + * firmware downloads. But what else can we do in that case anyway? Lets + * just hope that it never happens. + */ + if (!fw_req->timedout) + ida_simple_remove(&fw_req->fw_download->id_map, + fw_req->firmware_id); + kfree(fw_req); } +/* + * Incoming requests are serialized for a connection, and the only race possible + * is between the timeout handler freeing this and an incoming request. + * + * The operations on the fw-request list are protected by the mutex and + * get_fw_req() increments the reference count before returning a fw_req pointer + * to the users. + * + * free_firmware() also takes the mutex while removing an entry from the list, + * it guarantees that every user of fw_req has taken a kref-reference by now and + * we wouldn't have any new users. + * + * Once the last user drops the reference, the fw_req structure is freed. + */ +static void put_fw_req(struct fw_request *fw_req) +{ + kref_put(&fw_req->kref, fw_req_release); +} + /* Caller must call put_fw_req() after using struct fw_request */ static struct fw_request *get_fw_req(struct fw_download *fw_download, u8 firmware_id) { struct fw_request *fw_req; + mutex_lock(&fw_download->mutex); + list_for_each_entry(fw_req, &fw_download->fw_requests, node) { if (fw_req->firmware_id == firmware_id) { kref_get(&fw_req->kref); - return fw_req; + goto unlock; } } - return NULL; -} + fw_req = NULL; -/* - * Incoming requests are serialized for a connection, and this will never be - * racy. - */ -static void put_fw_req(struct fw_request *fw_req) -{ - kref_put(&fw_req->kref, fw_req_release); +unlock: + mutex_unlock(&fw_download->mutex); + + return fw_req; } static void free_firmware(struct fw_download *fw_download, struct fw_request *fw_req) { + /* Already disabled from timeout handlers */ + if (fw_req->disabled) + return; + + mutex_lock(&fw_download->mutex); list_del(&fw_req->node); + mutex_unlock(&fw_download->mutex); + fw_req->disabled = true; put_fw_req(fw_req); } +static void fw_request_timedout(unsigned long data) +{ + struct fw_request *fw_req = (struct fw_request *)data; + struct fw_download *fw_download = fw_req->fw_download; + + dev_err(fw_download->parent, + "Timed out waiting for fetch / release firmware requests: %u\n", + fw_req->firmware_id); + + fw_req->timedout = true; + free_firmware(fw_download, fw_req); +} + +static int exceeds_release_timeout(struct fw_request *fw_req) +{ + struct fw_download *fw_download = fw_req->fw_download; + + if (time_before(jiffies, fw_req->release_timeout_j)) + return 0; + + dev_err(fw_download->parent, + "Firmware download didn't finish in time, abort: %d\n", + fw_req->firmware_id); + + fw_req->timedout = true; + free_firmware(fw_download, fw_req); + + return -ETIMEDOUT; +} + /* This returns path of the firmware blob on the disk */ static struct fw_request *find_firmware(struct fw_download *fw_download, const char *tag) { struct gb_interface *intf = fw_download->connection->bundle->intf; struct fw_request *fw_req; - int ret; + int ret, req_count; fw_req = kzalloc(sizeof(*fw_req), GFP_KERNEL); if (!fw_req) @@ -115,7 +198,20 @@ static struct fw_request *find_firmware(struct fw_download *fw_download, fw_req->fw_download = fw_download; kref_init(&fw_req->kref); + + mutex_lock(&fw_download->mutex); list_add(&fw_req->node, &fw_download->fw_requests); + mutex_unlock(&fw_download->mutex); + + /* Timeout, in jiffies, within which firmware should get loaded */ + req_count = DIV_ROUND_UP(fw_req->fw->size, MIN_FETCH_SIZE); + fw_req->release_timeout_j = jiffies + req_count * NEXT_REQ_TIMEOUT_J; + + init_timer(&fw_req->timer); + fw_req->timer.function = fw_request_timedout; + fw_req->timer.expires = jiffies + NEXT_REQ_TIMEOUT_J; + fw_req->timer.data = (unsigned long)fw_req; + add_timer(&fw_req->timer); return fw_req; @@ -204,6 +300,24 @@ static int fw_download_fetch_firmware(struct gb_operation *op) return -EINVAL; } + /* Make sure timer handler isn't running in parallel */ + del_timer_sync(&fw_req->timer); + + /* We timed-out before reaching here ? */ + if (fw_req->disabled) { + ret = -ETIMEDOUT; + goto put_fw; + } + + /* + * Firmware download must finish within a limited time interval. If it + * doesn't, then we might have a buggy Module on the other side. Abort + * download. + */ + ret = exceeds_release_timeout(fw_req); + if (ret) + goto put_fw; + fw = fw_req->fw; if (offset >= fw->size || size > fw->size - offset) { @@ -229,6 +343,9 @@ static int fw_download_fetch_firmware(struct gb_operation *op) "responding with firmware (offs = %u, size = %u)\n", offset, size); + /* Refresh timeout */ + mod_timer(&fw_req->timer, jiffies + NEXT_REQ_TIMEOUT_J); + put_fw: put_fw_req(fw_req); @@ -260,6 +377,8 @@ static int fw_download_release_firmware(struct gb_operation *op) return -EINVAL; } + del_timer_sync(&fw_req->timer); + free_firmware(fw_download, fw_req); put_fw_req(fw_req); @@ -303,6 +422,7 @@ int gb_fw_download_connection_init(struct gb_connection *connection) ida_init(&fw_download->id_map); gb_connection_set_data(connection, fw_download); fw_download->connection = connection; + mutex_init(&fw_download->mutex); ret = gb_connection_enable(connection); if (ret) @@ -328,9 +448,21 @@ void gb_fw_download_connection_exit(struct gb_connection *connection) fw_download = gb_connection_get_data(connection); gb_connection_disable(fw_download->connection); + /* + * Make sure we have a reference to the pending requests, before they + * are freed from the timeout handler. + */ + mutex_lock(&fw_download->mutex); + list_for_each_entry(fw_req, &fw_download->fw_requests, node) + kref_get(&fw_req->kref); + mutex_unlock(&fw_download->mutex); + /* Release pending firmware packages */ - list_for_each_entry_safe(fw_req, tmp, &fw_download->fw_requests, node) + list_for_each_entry_safe(fw_req, tmp, &fw_download->fw_requests, node) { + del_timer_sync(&fw_req->timer); free_firmware(fw_download, fw_req); + put_fw_req(fw_req); + } ida_destroy(&fw_download->id_map); kfree(fw_download); -- cgit v0.10.2 From 03b4fa4b5dd9ecd11c27cdaeacf46453a948df5a Mon Sep 17 00:00:00 2001 From: Jeffrey Carlyle <jcarlyle@google.com> Date: Fri, 6 May 2016 11:29:37 -0700 Subject: greybus: Revert "bootrom: Implement timeouts to detect Module failures" This reverts commit 571348253032a86e4f0102d4dfadd390d0ea7e64. With this patch gb_bootrom_timedout was getting called in interrupt context and then proceeding to call functions that might block. In practical terms, this was leading to a kernel BUG at mm/vmalloc.c:1650. Signed-off-by: Jeffrey Carlyle <jcarlyle@google.com> Acked-by: Johan Hovold <johan@hovoldconsulting.com> diff --git a/drivers/staging/greybus/bootrom.c b/drivers/staging/greybus/bootrom.c index baada45..cf750be 100644 --- a/drivers/staging/greybus/bootrom.c +++ b/drivers/staging/greybus/bootrom.c @@ -8,48 +8,24 @@ */ #include <linux/firmware.h> -#include <linux/jiffies.h> -#include <linux/mutex.h> -#include <linux/timer.h> #include "bootrom.h" #include "greybus.h" -/* Timeout, in jiffies, within which the next request must be received */ -#define NEXT_REQ_TIMEOUT_J msecs_to_jiffies(1000) struct gb_bootrom { struct gb_connection *connection; const struct firmware *fw; u8 protocol_major; u8 protocol_minor; - struct timer_list timer; - struct mutex mutex; /* Protects bootrom->fw */ }; static void free_firmware(struct gb_bootrom *bootrom) { - if (!bootrom->fw) - return; - release_firmware(bootrom->fw); bootrom->fw = NULL; } -static void gb_bootrom_timedout(unsigned long data) -{ - struct gb_bootrom *bootrom = (struct gb_bootrom *)data; - struct device *dev = &bootrom->connection->bundle->dev; - - dev_err(dev, "Timed out waiting for request from the Module\n"); - - mutex_lock(&bootrom->mutex); - free_firmware(bootrom); - mutex_unlock(&bootrom->mutex); - - /* TODO: Power-off Module ? */ -} - /* * The es2 chip doesn't have VID/PID programmed into the hardware and we need to * hack that up to distinguish different modules and their firmware blobs. @@ -101,7 +77,8 @@ static int download_firmware(struct gb_bootrom *bootrom, u8 stage) int rc; /* Already have a firmware, free it */ - free_firmware(bootrom); + if (bootrom->fw) + free_firmware(bootrom); /* * Create firmware name @@ -137,32 +114,25 @@ static int gb_bootrom_firmware_size_request(struct gb_operation *op) struct device *dev = &op->connection->bundle->dev; int ret; - /* Disable timeouts */ - del_timer_sync(&bootrom->timer); - if (op->request->payload_size != sizeof(*size_request)) { dev_err(dev, "%s: illegal size of firmware size request (%zu != %zu)\n", __func__, op->request->payload_size, sizeof(*size_request)); - ret = -EINVAL; - goto mod_timer; + return -EINVAL; } - mutex_lock(&bootrom->mutex); - ret = download_firmware(bootrom, size_request->stage); if (ret) { dev_err(dev, "%s: failed to download firmware (%d)\n", __func__, ret); - goto unlock; + return ret; } if (!gb_operation_response_alloc(op, sizeof(*size_response), GFP_KERNEL)) { dev_err(dev, "%s: error allocating response\n", __func__); free_firmware(bootrom); - ret = -ENOMEM; - goto unlock; + return -ENOMEM; } size_response = op->response->payload; @@ -170,44 +140,28 @@ static int gb_bootrom_firmware_size_request(struct gb_operation *op) dev_dbg(dev, "%s: firmware size %d bytes\n", __func__, size_response->size); -unlock: - mutex_unlock(&bootrom->mutex); - -mod_timer: - /* Refresh timeout */ - mod_timer(&bootrom->timer, jiffies + NEXT_REQ_TIMEOUT_J); - - return ret; + return 0; } static int gb_bootrom_get_firmware(struct gb_operation *op) { struct gb_bootrom *bootrom = gb_connection_get_data(op->connection); - const struct firmware *fw; + const struct firmware *fw = bootrom->fw; struct gb_bootrom_get_firmware_request *firmware_request; struct gb_bootrom_get_firmware_response *firmware_response; struct device *dev = &op->connection->bundle->dev; unsigned int offset, size; - int ret = 0; - - /* Disable timeouts */ - del_timer_sync(&bootrom->timer); if (op->request->payload_size != sizeof(*firmware_request)) { dev_err(dev, "%s: Illegal size of get firmware request (%zu %zu)\n", __func__, op->request->payload_size, sizeof(*firmware_request)); - ret = -EINVAL; - goto mod_timer; + return -EINVAL; } - mutex_lock(&bootrom->mutex); - - fw = bootrom->fw; if (!fw) { dev_err(dev, "%s: firmware not available\n", __func__); - ret = -EINVAL; - goto unlock; + return -EINVAL; } firmware_request = op->request->payload; @@ -217,15 +171,13 @@ static int gb_bootrom_get_firmware(struct gb_operation *op) if (offset >= fw->size || size > fw->size - offset) { dev_warn(dev, "bad firmware request (offs = %u, size = %u)\n", offset, size); - ret = -EINVAL; - goto unlock; + return -EINVAL; } if (!gb_operation_response_alloc(op, sizeof(*firmware_response) + size, GFP_KERNEL)) { dev_err(dev, "%s: error allocating response\n", __func__); - ret = -ENOMEM; - goto unlock; + return -ENOMEM; } firmware_response = op->response->payload; @@ -234,59 +186,36 @@ static int gb_bootrom_get_firmware(struct gb_operation *op) dev_dbg(dev, "responding with firmware (offs = %u, size = %u)\n", offset, size); -unlock: - mutex_unlock(&bootrom->mutex); - -mod_timer: - /* Refresh timeout */ - mod_timer(&bootrom->timer, jiffies + NEXT_REQ_TIMEOUT_J); - - return ret; + return 0; } static int gb_bootrom_ready_to_boot(struct gb_operation *op) { struct gb_connection *connection = op->connection; - struct gb_bootrom *bootrom = gb_connection_get_data(connection); struct gb_bootrom_ready_to_boot_request *rtb_request; struct device *dev = &connection->bundle->dev; u8 status; - int ret = 0; - - /* Disable timeouts */ - del_timer_sync(&bootrom->timer); if (op->request->payload_size != sizeof(*rtb_request)) { dev_err(dev, "%s: Illegal size of ready to boot request (%zu %zu)\n", __func__, op->request->payload_size, sizeof(*rtb_request)); - ret = -EINVAL; - goto mod_timer; + return -EINVAL; } rtb_request = op->request->payload; status = rtb_request->status; /* Return error if the blob was invalid */ - if (status == GB_BOOTROM_BOOT_STATUS_INVALID) { - ret = -EINVAL; - goto mod_timer; - } + if (status == GB_BOOTROM_BOOT_STATUS_INVALID) + return -EINVAL; /* * XXX Should we return error for insecure firmware? */ dev_dbg(dev, "ready to boot: 0x%x, 0\n", status); -mod_timer: - /* - * Refresh timeout, the Interface shall load the new personality and - * send a new hotplug request, which shall get rid of the bootrom - * connection. As that can take some time, increase the timeout a bit. - */ - mod_timer(&bootrom->timer, jiffies + 5 * NEXT_REQ_TIMEOUT_J); - - return ret; + return 0; } static int gb_bootrom_request_handler(struct gb_operation *op) @@ -375,11 +304,6 @@ static int gb_bootrom_probe(struct gb_bundle *bundle, bootrom->connection = connection; - mutex_init(&bootrom->mutex); - init_timer(&bootrom->timer); - bootrom->timer.function = gb_bootrom_timedout; - bootrom->timer.data = (unsigned long)bootrom; - greybus_set_drvdata(bundle, bootrom); ret = gb_connection_enable_tx(connection); @@ -405,9 +329,6 @@ static int gb_bootrom_probe(struct gb_bundle *bundle, goto err_connection_disable; } - /* Refresh timeout */ - mod_timer(&bootrom->timer, jiffies + NEXT_REQ_TIMEOUT_J); - dev_dbg(&bundle->dev, "AP_READY sent\n"); return 0; @@ -430,16 +351,9 @@ static void gb_bootrom_disconnect(struct gb_bundle *bundle) gb_connection_disable(bootrom->connection); - /* Disable timeouts */ - del_timer_sync(&bootrom->timer); - - /* - * Release firmware: - * - * As the connection and the timer are already disabled, we don't need - * to lock access to bootrom->fw here. - */ - free_firmware(bootrom); + /* Release firmware */ + if (bootrom->fw) + free_firmware(bootrom); gb_connection_destroy(bootrom->connection); kfree(bootrom); -- cgit v0.10.2 From 144763bf8efd8bfc6b0c582fdf3f77564fc0296f Mon Sep 17 00:00:00 2001 From: Jeffrey Carlyle <jcarlyle@google.com> Date: Fri, 6 May 2016 12:43:52 -0700 Subject: greybus: svc: implement svc_intf_{vsys,refclk,unipro}_{enable,disable} operations Add SVC operations for fine grain control over vsys, refclk, and unipro port power. Testing done: used "new" firmware boot sequence to verify that modules were correctly detected and booted. Signed-off-by: Jeffrey Carlyle <jcarlyle@google.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 9b21a35..c77fb25 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -840,6 +840,12 @@ struct gb_spi_transfer_response { #define GB_SVC_TYPE_TIMESYNC_PING 0x1a #define GB_SVC_TYPE_MODULE_INSERTED 0x1f #define GB_SVC_TYPE_MODULE_REMOVED 0x20 +#define GB_SVC_TYPE_INTF_VSYS_ENABLE 0x21 +#define GB_SVC_TYPE_INTF_VSYS_DISABLE 0x22 +#define GB_SVC_TYPE_INTF_REFCLK_ENABLE 0x23 +#define GB_SVC_TYPE_INTF_REFCLK_DISABLE 0x24 +#define GB_SVC_TYPE_INTF_UNIPRO_ENABLE 0x25 +#define GB_SVC_TYPE_INTF_UNIPRO_DISABLE 0x26 #define GB_SVC_TYPE_INTF_ACTIVATE 0x27 #define GB_SVC_TYPE_INTF_MAILBOX_EVENT 0x29 @@ -954,6 +960,43 @@ struct gb_svc_route_destroy_request { } __packed; /* route destroy response has no payload */ +/* used for svc_intf_vsys_{enable,disable} */ +struct gb_svc_intf_vsys_request { + __u8 intf_id; +} __packed; + +struct gb_svc_intf_vsys_response { + __u8 result_code; +#define GB_SVC_INTF_VSYS_OK 0x00 +#define GB_SVC_INTF_VSYS_BUSY 0x01 +#define GB_SVC_INTF_VSYS_FAIL 0x02 +} __packed; + +/* used for svc_intf_refclk_{enable,disable} */ +struct gb_svc_intf_refclk_request { + __u8 intf_id; +} __packed; + +struct gb_svc_intf_refclk_response { + __u8 result_code; +#define GB_SVC_INTF_REFCLK_OK 0x00 +#define GB_SVC_INTF_REFCLK_BUSY 0x01 +#define GB_SVC_INTF_REFCLK_FAIL 0x02 +} __packed; + +/* used for svc_intf_unipro_{enable,disable} */ +struct gb_svc_intf_unipro_request { + __u8 intf_id; +} __packed; + +struct gb_svc_intf_unipro_response { + __u8 result_code; +#define GB_SVC_INTF_UNIPRO_OK 0x00 +#define GB_SVC_INTF_UNIPRO_BUSY 0x01 +#define GB_SVC_INTF_UNIPRO_FAIL 0x02 +#define GB_SVC_INTF_UNIPRO_NOT_OFF 0x03 +} __packed; + struct gb_svc_timesync_enable_request { __u8 count; __le64 frame_time; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index f3ee94e..1e6cab0 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -257,22 +257,70 @@ int gb_svc_intf_eject(struct gb_svc *svc, u8 intf_id) int gb_svc_intf_vsys_set(struct gb_svc *svc, u8 intf_id, bool enable) { - /* FIXME: implement */ + struct gb_svc_intf_vsys_request request; + struct gb_svc_intf_vsys_response response; + int type, ret; + + request.intf_id = intf_id; + if (enable) + type = GB_SVC_TYPE_INTF_VSYS_ENABLE; + else + type = GB_SVC_TYPE_INTF_VSYS_DISABLE; + + ret = gb_operation_sync(svc->connection, type, + &request, sizeof(request), + &response, sizeof(response)); + if (ret < 0) + return ret; + if (response.result_code != GB_SVC_INTF_VSYS_OK) + return -EREMOTEIO; return 0; } int gb_svc_intf_refclk_set(struct gb_svc *svc, u8 intf_id, bool enable) { - /* FIXME: implement */ + struct gb_svc_intf_refclk_request request; + struct gb_svc_intf_refclk_response response; + int type, ret; + request.intf_id = intf_id; + + if (enable) + type = GB_SVC_TYPE_INTF_REFCLK_ENABLE; + else + type = GB_SVC_TYPE_INTF_REFCLK_DISABLE; + + ret = gb_operation_sync(svc->connection, type, + &request, sizeof(request), + &response, sizeof(response)); + if (ret < 0) + return ret; + if (response.result_code != GB_SVC_INTF_REFCLK_OK) + return -EREMOTEIO; return 0; } int gb_svc_intf_unipro_set(struct gb_svc *svc, u8 intf_id, bool enable) { - /* FIXME: implement */ + struct gb_svc_intf_unipro_request request; + struct gb_svc_intf_unipro_response response; + int type, ret; + + request.intf_id = intf_id; + + if (enable) + type = GB_SVC_TYPE_INTF_UNIPRO_ENABLE; + else + type = GB_SVC_TYPE_INTF_UNIPRO_DISABLE; + ret = gb_operation_sync(svc->connection, type, + &request, sizeof(request), + &response, sizeof(response)); + if (ret < 0) + return ret; + if (response.result_code != GB_SVC_INTF_UNIPRO_OK) + return -EREMOTEIO; return 0; } -- cgit v0.10.2 From 140026b32f953593eb8678d67fcc95534efe1b49 Mon Sep 17 00:00:00 2001 From: Jeffrey Carlyle <jcarlyle@google.com> Date: Fri, 6 May 2016 12:43:53 -0700 Subject: greybus: svc: implement svc_intf_activate With upcoming firmware changes we will switch from an SVC-driven module boot sequence to an AP-driven module sequence. This operation allows the AP to request the SVC to boot a module to which the AP has previouslt requested power be applied. This operation will also determine if the remote interface is a dummy module, UniPro-only module, or full Greybus module. Testing done: Tested together with "new" firmware boot sequence to verify that modules are detected and booted as expected. Signed-off-by: Jeffrey Carlyle <jcarlyle@google.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 1e6cab0..a98593c 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -15,7 +15,8 @@ #define SVC_KEY_ARA_BUTTON KEY_A -#define SVC_INTF_EJECT_TIMEOUT 9000 +#define SVC_INTF_EJECT_TIMEOUT 9000 +#define SVC_INTF_ACTIVATE_TIMEOUT 6000 struct gb_svc_deferred_request { struct work_struct work; @@ -326,9 +327,21 @@ int gb_svc_intf_unipro_set(struct gb_svc *svc, u8 intf_id, bool enable) int gb_svc_intf_activate(struct gb_svc *svc, u8 intf_id, u8 *intf_type) { - /* FIXME: implement */ + struct gb_svc_intf_activate_request request; + struct gb_svc_intf_activate_response response; + int ret; + + request.intf_id = intf_id; + + ret = gb_operation_sync_timeout(svc->connection, + GB_SVC_TYPE_INTF_ACTIVATE, + &request, sizeof(request), + &response, sizeof(response), + SVC_INTF_ACTIVATE_TIMEOUT); + if (ret < 0) + return ret; - *intf_type = GB_SVC_INTF_TYPE_GREYBUS; + *intf_type = response.intf_type; return 0; } -- cgit v0.10.2 From a956d939af9e73d3375f52d5c5c63ab824e59c8b Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 9 May 2016 10:59:00 +0530 Subject: greybus: bootrom: Implement timeouts to detect Module failures Its possible that the Module may fail to download the next stage firmware, or to jump into it and boot into the new personality. We have already seen examples of both of these cases on EVT 1.5. This patch implements timeouts in the bootrom bundle driver, which now expects the next request from the Module to be received at the AP within 1 second of the previous request/response. The time interval can be increased later if required. The timeouts are added between: - AP_READY and FIRMWARE_SIZE operations - FIRMWARE_SIZE and GET_FIRMWARE operations - Two GET_FIRMWARE operations - GET_FIRMWARE and READY_TO_BOOT operations - READY_TO_BOOT operation and the call to the ->disconnect() event of the bootrom bundle (once the new hotplug request is received). The timeout for the last case is kept at 5 seconds right now (random value), as it may take a bit longer. Because 'bootrom->fw' can be accessed simultaneously (from timeout handler and incoming requests) and one of them can potentially free the '->fw' structure, a mutex is also added to take care of such races while accessing 'bootrom->fw' structure. Also note that the '!bootrom->fw' check is moved to free_firmware() routine. Note that this version uses delayed-work (instead of timers used in earlier attempt), as we need to call routines that can sleep from the timeout handler. Tested on EVT 1.5, by faking errors on certain requests, so that the bootrom doesn't send any more requests. Normal case is working just fine for audio and GP modules. This is tested with build arche_440. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/bootrom.c b/drivers/staging/greybus/bootrom.c index cf750be..f375a87 100644 --- a/drivers/staging/greybus/bootrom.c +++ b/drivers/staging/greybus/bootrom.c @@ -8,24 +8,49 @@ */ #include <linux/firmware.h> +#include <linux/jiffies.h> +#include <linux/mutex.h> +#include <linux/workqueue.h> #include "bootrom.h" #include "greybus.h" +/* Timeout, in jiffies, within which the next request must be received */ +#define NEXT_REQ_TIMEOUT_J msecs_to_jiffies(1000) struct gb_bootrom { struct gb_connection *connection; const struct firmware *fw; u8 protocol_major; u8 protocol_minor; + struct delayed_work dwork; + struct mutex mutex; /* Protects bootrom->fw */ }; static void free_firmware(struct gb_bootrom *bootrom) { + if (!bootrom->fw) + return; + release_firmware(bootrom->fw); bootrom->fw = NULL; } +static void gb_bootrom_timedout(struct work_struct *work) +{ + struct delayed_work *dwork = to_delayed_work(work); + struct gb_bootrom *bootrom = container_of(dwork, struct gb_bootrom, dwork); + struct device *dev = &bootrom->connection->bundle->dev; + + dev_err(dev, "Timed out waiting for request from the Module\n"); + + mutex_lock(&bootrom->mutex); + free_firmware(bootrom); + mutex_unlock(&bootrom->mutex); + + /* TODO: Power-off Module ? */ +} + /* * The es2 chip doesn't have VID/PID programmed into the hardware and we need to * hack that up to distinguish different modules and their firmware blobs. @@ -77,8 +102,7 @@ static int download_firmware(struct gb_bootrom *bootrom, u8 stage) int rc; /* Already have a firmware, free it */ - if (bootrom->fw) - free_firmware(bootrom); + free_firmware(bootrom); /* * Create firmware name @@ -114,25 +138,32 @@ static int gb_bootrom_firmware_size_request(struct gb_operation *op) struct device *dev = &op->connection->bundle->dev; int ret; + /* Disable timeouts */ + cancel_delayed_work_sync(&bootrom->dwork); + if (op->request->payload_size != sizeof(*size_request)) { dev_err(dev, "%s: illegal size of firmware size request (%zu != %zu)\n", __func__, op->request->payload_size, sizeof(*size_request)); - return -EINVAL; + ret = -EINVAL; + goto queue_work; } + mutex_lock(&bootrom->mutex); + ret = download_firmware(bootrom, size_request->stage); if (ret) { dev_err(dev, "%s: failed to download firmware (%d)\n", __func__, ret); - return ret; + goto unlock; } if (!gb_operation_response_alloc(op, sizeof(*size_response), GFP_KERNEL)) { dev_err(dev, "%s: error allocating response\n", __func__); free_firmware(bootrom); - return -ENOMEM; + ret = -ENOMEM; + goto unlock; } size_response = op->response->payload; @@ -140,28 +171,44 @@ static int gb_bootrom_firmware_size_request(struct gb_operation *op) dev_dbg(dev, "%s: firmware size %d bytes\n", __func__, size_response->size); - return 0; +unlock: + mutex_unlock(&bootrom->mutex); + +queue_work: + /* Refresh timeout */ + schedule_delayed_work(&bootrom->dwork, NEXT_REQ_TIMEOUT_J); + + return ret; } static int gb_bootrom_get_firmware(struct gb_operation *op) { struct gb_bootrom *bootrom = gb_connection_get_data(op->connection); - const struct firmware *fw = bootrom->fw; + const struct firmware *fw; struct gb_bootrom_get_firmware_request *firmware_request; struct gb_bootrom_get_firmware_response *firmware_response; struct device *dev = &op->connection->bundle->dev; unsigned int offset, size; + int ret = 0; + + /* Disable timeouts */ + cancel_delayed_work_sync(&bootrom->dwork); if (op->request->payload_size != sizeof(*firmware_request)) { dev_err(dev, "%s: Illegal size of get firmware request (%zu %zu)\n", __func__, op->request->payload_size, sizeof(*firmware_request)); - return -EINVAL; + ret = -EINVAL; + goto queue_work; } + mutex_lock(&bootrom->mutex); + + fw = bootrom->fw; if (!fw) { dev_err(dev, "%s: firmware not available\n", __func__); - return -EINVAL; + ret = -EINVAL; + goto unlock; } firmware_request = op->request->payload; @@ -171,13 +218,15 @@ static int gb_bootrom_get_firmware(struct gb_operation *op) if (offset >= fw->size || size > fw->size - offset) { dev_warn(dev, "bad firmware request (offs = %u, size = %u)\n", offset, size); - return -EINVAL; + ret = -EINVAL; + goto unlock; } if (!gb_operation_response_alloc(op, sizeof(*firmware_response) + size, GFP_KERNEL)) { dev_err(dev, "%s: error allocating response\n", __func__); - return -ENOMEM; + ret = -ENOMEM; + goto unlock; } firmware_response = op->response->payload; @@ -186,36 +235,59 @@ static int gb_bootrom_get_firmware(struct gb_operation *op) dev_dbg(dev, "responding with firmware (offs = %u, size = %u)\n", offset, size); - return 0; +unlock: + mutex_unlock(&bootrom->mutex); + +queue_work: + /* Refresh timeout */ + schedule_delayed_work(&bootrom->dwork, NEXT_REQ_TIMEOUT_J); + + return ret; } static int gb_bootrom_ready_to_boot(struct gb_operation *op) { struct gb_connection *connection = op->connection; + struct gb_bootrom *bootrom = gb_connection_get_data(connection); struct gb_bootrom_ready_to_boot_request *rtb_request; struct device *dev = &connection->bundle->dev; u8 status; + int ret = 0; + + /* Disable timeouts */ + cancel_delayed_work_sync(&bootrom->dwork); if (op->request->payload_size != sizeof(*rtb_request)) { dev_err(dev, "%s: Illegal size of ready to boot request (%zu %zu)\n", __func__, op->request->payload_size, sizeof(*rtb_request)); - return -EINVAL; + ret = -EINVAL; + goto queue_work; } rtb_request = op->request->payload; status = rtb_request->status; /* Return error if the blob was invalid */ - if (status == GB_BOOTROM_BOOT_STATUS_INVALID) - return -EINVAL; + if (status == GB_BOOTROM_BOOT_STATUS_INVALID) { + ret = -EINVAL; + goto queue_work; + } /* * XXX Should we return error for insecure firmware? */ dev_dbg(dev, "ready to boot: 0x%x, 0\n", status); - return 0; +queue_work: + /* + * Refresh timeout, the Interface shall load the new personality and + * send a new hotplug request, which shall get rid of the bootrom + * connection. As that can take some time, increase the timeout a bit. + */ + schedule_delayed_work(&bootrom->dwork, 5 * NEXT_REQ_TIMEOUT_J); + + return ret; } static int gb_bootrom_request_handler(struct gb_operation *op) @@ -304,6 +376,8 @@ static int gb_bootrom_probe(struct gb_bundle *bundle, bootrom->connection = connection; + mutex_init(&bootrom->mutex); + INIT_DELAYED_WORK(&bootrom->dwork, gb_bootrom_timedout); greybus_set_drvdata(bundle, bootrom); ret = gb_connection_enable_tx(connection); @@ -329,6 +403,9 @@ static int gb_bootrom_probe(struct gb_bundle *bundle, goto err_connection_disable; } + /* Refresh timeout */ + schedule_delayed_work(&bootrom->dwork, NEXT_REQ_TIMEOUT_J); + dev_dbg(&bundle->dev, "AP_READY sent\n"); return 0; @@ -351,9 +428,16 @@ static void gb_bootrom_disconnect(struct gb_bundle *bundle) gb_connection_disable(bootrom->connection); - /* Release firmware */ - if (bootrom->fw) - free_firmware(bootrom); + /* Disable timeouts */ + cancel_delayed_work_sync(&bootrom->dwork); + + /* + * Release firmware: + * + * As the connection and the delayed work are already disabled, we don't + * need to lock access to bootrom->fw here. + */ + free_firmware(bootrom); gb_connection_destroy(bootrom->connection); kfree(bootrom); -- cgit v0.10.2 From c6cc8e73eb188156494e061bdb93966b0c7d9443 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 9 May 2016 10:59:01 +0530 Subject: greybus: fw-download: Replace timer with delayed-work The timeout-handlers need to call routines that can sleep and those can't be called from interrupt context. The timer-handler is called in interrupt context and so will hit a BUG() in vmalloc.c. This patch moves away from timers to delayed-work, whose timeout handler gets called in process context and can call the sleep-able routines safely. Note that this issue wasn't hit earlier when the initial patch for timeouts was implemented due to some issues in the build arche_420. But with the new build arche_440, the BUG started crashing the phone on timeouts and so this fix is required. Tested on EVT 1.5 by triggering fake timeouts, by not sending release-firmware request for example. This is tested with build arche_440. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/fw-download.c b/drivers/staging/greybus/fw-download.c index 0ebea37..42cbbf4 100644 --- a/drivers/staging/greybus/fw-download.c +++ b/drivers/staging/greybus/fw-download.c @@ -10,7 +10,7 @@ #include <linux/firmware.h> #include <linux/jiffies.h> #include <linux/mutex.h> -#include <linux/timer.h> +#include <linux/workqueue.h> #include "firmware.h" #include "greybus.h" @@ -29,7 +29,7 @@ struct fw_request { const struct firmware *fw; struct list_head node; - struct timer_list timer; + struct delayed_work dwork; /* Timeout, in jiffies, within which the firmware shall download */ unsigned long release_timeout_j; struct kref kref; @@ -129,9 +129,10 @@ static void free_firmware(struct fw_download *fw_download, put_fw_req(fw_req); } -static void fw_request_timedout(unsigned long data) +static void fw_request_timedout(struct work_struct *work) { - struct fw_request *fw_req = (struct fw_request *)data; + struct delayed_work *dwork = to_delayed_work(work); + struct fw_request *fw_req = container_of(dwork, struct fw_request, dwork); struct fw_download *fw_download = fw_req->fw_download; dev_err(fw_download->parent, @@ -207,11 +208,8 @@ static struct fw_request *find_firmware(struct fw_download *fw_download, req_count = DIV_ROUND_UP(fw_req->fw->size, MIN_FETCH_SIZE); fw_req->release_timeout_j = jiffies + req_count * NEXT_REQ_TIMEOUT_J; - init_timer(&fw_req->timer); - fw_req->timer.function = fw_request_timedout; - fw_req->timer.expires = jiffies + NEXT_REQ_TIMEOUT_J; - fw_req->timer.data = (unsigned long)fw_req; - add_timer(&fw_req->timer); + INIT_DELAYED_WORK(&fw_req->dwork, fw_request_timedout); + schedule_delayed_work(&fw_req->dwork, NEXT_REQ_TIMEOUT_J); return fw_req; @@ -300,8 +298,8 @@ static int fw_download_fetch_firmware(struct gb_operation *op) return -EINVAL; } - /* Make sure timer handler isn't running in parallel */ - del_timer_sync(&fw_req->timer); + /* Make sure work handler isn't running in parallel */ + cancel_delayed_work_sync(&fw_req->dwork); /* We timed-out before reaching here ? */ if (fw_req->disabled) { @@ -344,7 +342,7 @@ static int fw_download_fetch_firmware(struct gb_operation *op) size); /* Refresh timeout */ - mod_timer(&fw_req->timer, jiffies + NEXT_REQ_TIMEOUT_J); + schedule_delayed_work(&fw_req->dwork, NEXT_REQ_TIMEOUT_J); put_fw: put_fw_req(fw_req); @@ -377,7 +375,7 @@ static int fw_download_release_firmware(struct gb_operation *op) return -EINVAL; } - del_timer_sync(&fw_req->timer); + cancel_delayed_work_sync(&fw_req->dwork); free_firmware(fw_download, fw_req); put_fw_req(fw_req); @@ -459,7 +457,7 @@ void gb_fw_download_connection_exit(struct gb_connection *connection) /* Release pending firmware packages */ list_for_each_entry_safe(fw_req, tmp, &fw_download->fw_requests, node) { - del_timer_sync(&fw_req->timer); + cancel_delayed_work_sync(&fw_req->dwork); free_firmware(fw_download, fw_req); put_fw_req(fw_req); } -- cgit v0.10.2 From c77bac08eca8b7dff3f76662cc8d439c111b8d0f Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Fri, 6 May 2016 18:16:24 -0700 Subject: greybus: operation: fix an inconsistent indent This patch fixes an inconsistent indent. Testing Done: - Build & boot Signed-off-by: David Lin <dtwlin@google.com> Acked-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index e7e9b0e..62d0c45 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -238,7 +238,7 @@ static void gb_operation_request_handle(struct gb_operation *operation) dev_err(&connection->hd->dev, "%s: failed to send response %d for type 0x%02x: %d\n", connection->name, status, operation->type, ret); - return; + return; } } -- cgit v0.10.2 From 03fba180ae4cc3bad27bd792e53dbb7ed2a9f7e7 Mon Sep 17 00:00:00 2001 From: Jeffrey Carlyle <jcarlyle@google.com> Date: Wed, 11 May 2016 10:08:55 -0700 Subject: greybus: svc: support status in svc_intf_activate response Update per Greybus spec. Status attribute added to activate response to return more detailed information about errors during activate. If the Greybus response is GB_OP_SUCCESS, the caller must also check the status attribute in the response to determine if any other errors occurred. Testing done: along with matchine firmware change, verified that modules were detected and enumerated as expected. Signed-off-by: Jeffrey Carlyle <jcarlyle@google.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index c77fb25..ca5eb3b 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -849,6 +849,24 @@ struct gb_spi_transfer_response { #define GB_SVC_TYPE_INTF_ACTIVATE 0x27 #define GB_SVC_TYPE_INTF_MAILBOX_EVENT 0x29 +/* Greybus SVC protocol status values */ +#define GB_SVC_OP_SUCCESS 0x00 +#define GB_SVC_OP_UNKNOWN_ERROR 0x01 +#define GB_SVC_INTF_NOT_DETECTED 0x02 +#define GB_SVC_INTF_NO_UPRO_LINK 0x03 +#define GB_SVC_INTF_UPRO_NOT_DOWN 0x04 +#define GB_SVC_INTF_UPRO_NOT_HIBERNATED 0x05 +#define GB_SVC_INTF_NO_V_SYS 0x06 +#define GB_SVC_INTF_V_CHG 0x07 +#define GB_SVC_INTF_WAKE_BUSY 0x08 +#define GB_SVC_INTF_NO_REFCLK 0x09 +#define GB_SVC_INTF_RELEASING 0x0a +#define GB_SVC_INTF_NO_ORDER 0x0b +#define GB_SVC_INTF_MBOX_SET 0x0c +#define GB_SVC_INTF_BAD_MBOX 0x0d +#define GB_SVC_INTF_OP_TIMEOUT 0x0e +#define GB_SVC_PWRMON_OP_NOT_PRESENT 0x0f + struct gb_svc_version_request { __u8 major; __u8 minor; @@ -1133,6 +1151,7 @@ struct gb_svc_intf_activate_request { #define GB_SVC_INTF_TYPE_GREYBUS 0x03 struct gb_svc_intf_activate_response { + __u8 status; __u8 intf_type; } __packed; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index a98593c..3bdf778 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -340,6 +340,11 @@ int gb_svc_intf_activate(struct gb_svc *svc, u8 intf_id, u8 *intf_type) SVC_INTF_ACTIVATE_TIMEOUT); if (ret < 0) return ret; + if (response.status != GB_SVC_OP_SUCCESS) { + dev_err(&svc->dev, "failed to activate interface %u: %u\n", + intf_id, response.status); + return -EREMOTEIO; + } *intf_type = response.intf_type; -- cgit v0.10.2 From ae0f6454bbe74df324e47041e68018649ce0bcba Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Mon, 9 May 2016 14:40:09 +0200 Subject: greybus: interface: fix type in enable error message Fix type of PTR_ERR in an interface-enable error message. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index aed45bc..0b82938 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -564,7 +564,7 @@ int gb_interface_enable(struct gb_interface *intf) /* Establish control connection */ control = gb_control_create(intf); if (IS_ERR(control)) { - dev_err(&intf->dev, "failed to create control device: %lu\n", + dev_err(&intf->dev, "failed to create control device: %ld\n", PTR_ERR(control)); return PTR_ERR(control); } -- cgit v0.10.2 From 792db396d3209f4e20aea8c73407ac1f34b45a2b Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Mon, 9 May 2016 14:40:10 +0200 Subject: greybus: interface: remove unused interface-version quirk The interface-version request was just removed so remove the now unused interface-version quirk. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 0b82938..a1435e9 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -217,18 +217,15 @@ static int gb_interface_read_and_clear_init_status(struct gb_interface *intf) /* * Check if the interface is executing the quirky ES3 bootrom that - * requires E2EFC, CSD and CSV to be disabled and that does not - * support the interface-version request. + * requires E2EFC, CSD and CSV to be disabled. */ switch (init_status) { case GB_INIT_BOOTROM_UNIPRO_BOOT_STARTED: case GB_INIT_BOOTROM_FALLBACK_UNIPRO_BOOT_STARTED: intf->quirks |= GB_INTERFACE_QUIRK_NO_CPORT_FEATURES; - intf->quirks |= GB_INTERFACE_QUIRK_NO_INTERFACE_VERSION; break; default: intf->quirks &= ~GB_INTERFACE_QUIRK_NO_CPORT_FEATURES; - intf->quirks &= ~GB_INTERFACE_QUIRK_NO_INTERFACE_VERSION; } /* Clear the init status. */ diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 7a2162a..1a25234 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -11,9 +11,8 @@ #define __INTERFACE_H #define GB_INTERFACE_QUIRK_NO_CPORT_FEATURES BIT(0) -#define GB_INTERFACE_QUIRK_NO_INTERFACE_VERSION BIT(1) -#define GB_INTERFACE_QUIRK_NO_INIT_STATUS BIT(2) -#define GB_INTERFACE_QUIRK_NO_ARA_IDS BIT(3) +#define GB_INTERFACE_QUIRK_NO_INIT_STATUS BIT(1) +#define GB_INTERFACE_QUIRK_NO_ARA_IDS BIT(2) struct gb_interface { struct device dev; -- cgit v0.10.2 From 6f8a028fd17bbb3102c81dc4fd30f2d722234b5e Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 12 May 2016 12:20:02 +0530 Subject: greybus: gpbridge: Expose protocol_id in sysfs Right now, userspace doesn't have any way to find what protocol does a gpbridge device implement. And this is essential for the scripts to know, to expect what kind of device will be present inside the gpbN directory. Expose 'protocol_id' in sysfs to fix that. Tested by checking that the field appears with GP module on EVT 1.5. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Sandeep Patil <sspatil@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c index 993cfac..64ab8dd 100644 --- a/drivers/staging/greybus/gpbridge.c +++ b/drivers/staging/greybus/gpbridge.c @@ -26,6 +26,22 @@ struct gpbridge_host { static DEFINE_IDA(gpbridge_id); +static ssize_t protocol_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gpbridge_device *gpbdev = to_gpbridge_dev(dev); + + return sprintf(buf, "0x%02x\n", gpbdev->cport_desc->protocol_id); +} +static DEVICE_ATTR_RO(protocol_id); + +static struct attribute *gpbdev_attrs[] = { + &dev_attr_protocol_id.attr, + NULL, +}; + +ATTRIBUTE_GROUPS(gpbdev); + static void gpbdev_release(struct device *dev) { struct gpbridge_device *gpbdev = to_gpbridge_dev(dev); @@ -190,7 +206,7 @@ static struct gpbridge_device *gb_gpbridge_create_dev(struct gb_bundle *bundle, gpbdev->dev.parent = &bundle->dev; gpbdev->dev.bus = &gpbridge_bus_type; gpbdev->dev.release = gpbdev_release; - gpbdev->dev.groups = NULL; + gpbdev->dev.groups = gpbdev_groups; gpbdev->dev.dma_mask = bundle->dev.dma_mask; dev_set_name(&gpbdev->dev, "gpb%d", id); -- cgit v0.10.2 From e4e55360dd6b2263bbbc83bf0f04b0bd9bb1f8fd Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 12 May 2016 11:34:05 +0530 Subject: greybus: core: Rename greybus_module_match() greybus_module_match() doesn't match modules anymore but bundle devices and should be named correctly. Though we can use greybus_bundle_match() as well, rest of the kernel uses terminology like 'greybus_match_device' and so choosing that instead. Compile tested. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 3fdc405..a44846d 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -64,7 +64,7 @@ greybus_match_id(struct gb_bundle *bundle, const struct greybus_bundle_id *id) return NULL; } -static int greybus_module_match(struct device *dev, struct device_driver *drv) +static int greybus_match_device(struct device *dev, struct device_driver *drv) { struct greybus_driver *driver = to_greybus_driver(drv); struct gb_bundle *bundle; @@ -151,7 +151,7 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) struct bus_type greybus_bus_type = { .name = "greybus", - .match = greybus_module_match, + .match = greybus_match_device, .uevent = greybus_uevent, }; -- cgit v0.10.2 From 501cc8bd09485624beaeecf476739400977489b4 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 12 May 2016 11:26:48 +0530 Subject: greybus: Fix probing of gpbridge devices The gpbridge core tries to match the driver's id-table against all CPorts available within the bundle for which the gpbridge bus was created. The gpbdev here is unique for a cport_desc and only a single cport_desc->protocol_id should be matched with the driver's id-table. Fix it. Tested on EVT 1.5 with a special manifest for GP module, where multiple CPorts are part of the same Bridged PHY bundle. Fixes: 75223f666687 ("gpbridge: implement gpbridge "bus" logic") Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c index 64ab8dd..adb317d 100644 --- a/drivers/staging/greybus/gpbridge.c +++ b/drivers/staging/greybus/gpbridge.c @@ -57,44 +57,27 @@ static int gpbdev_uevent(struct device *dev, struct kobj_uevent_env *env) } static const struct gpbridge_device_id * -gpbdev_match_cport(struct greybus_descriptor_cport *cport_desc, - const struct gpbridge_device_id *id) +gpbdev_match_id(struct gpbridge_device *gpbdev, struct gpbridge_driver *gpbdrv) { + const struct gpbridge_device_id *id = gpbdrv->id_table; + if (!id) return NULL; for (; id->protocol_id; id++) - if (id->protocol_id == cport_desc->protocol_id) + if (id->protocol_id == gpbdev->cport_desc->protocol_id) return id; return NULL; } -static const struct gpbridge_device_id *gpbdev_match_id(struct gb_bundle *bundle, - const struct gpbridge_device_id *id_table) -{ - const struct gpbridge_device_id *id; - int i; - - if (!id_table || !bundle || bundle->num_cports == 0) - return NULL; - - for (i = 0; i < bundle->num_cports; i++) { - id = gpbdev_match_cport(&bundle->cport_desc[i], id_table); - if (id) - return id; - } - - return NULL; -} - static int gpbdev_match(struct device *dev, struct device_driver *drv) { struct gpbridge_driver *gpbdrv = to_gpbridge_driver(drv); struct gpbridge_device *gpbdev = to_gpbridge_dev(dev); const struct gpbridge_device_id *id; - id = gpbdev_match_id(gpbdev->bundle, gpbdrv->id_table); + id = gpbdev_match_id(gpbdev, gpbdrv); if (id) return 1; @@ -107,7 +90,7 @@ static int gpbdev_probe(struct device *dev) struct gpbridge_device *gpbdev = to_gpbridge_dev(dev); const struct gpbridge_device_id *id; - id = gpbdev_match_id(gpbdev->bundle, gpbdrv->id_table); + id = gpbdev_match_id(gpbdev, gpbdrv); if (!id) return -ENODEV; -- cgit v0.10.2 From 0e9b41ab98ec8065263e6def8baebff1c1cd2c31 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 11 May 2016 10:17:55 +0200 Subject: greybus: connection: add no-flow-control connection flag Add a no-flow-control connection flag, which is set for connection that should not have any flow-control feature enabled. This flag is specifically set for all connections to the legacy ES3 bootrom, and will also be used by the camera driver eventually. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 1564db8..9e88281 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -183,6 +183,8 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, connection->bundle = bundle; connection->handler = handler; connection->flags = flags; + if (intf && (intf->quirks & GB_INTERFACE_QUIRK_NO_CPORT_FEATURES)) + connection->flags |= GB_CONNECTION_FLAG_NO_FLOWCTRL; connection->state = GB_CONNECTION_STATE_DISABLED; atomic_set(&connection->op_cycle, 0); @@ -338,11 +340,10 @@ gb_connection_svc_connection_create(struct gb_connection *connection) intf = connection->intf; /* - * Enable either E2EFC or CSD, unless the interface does not support - * any CPort features. + * Enable either E2EFC or CSD, unless no flow control is requested. */ cport_flags = GB_SVC_CPORT_FLAG_CSV_N; - if (intf->quirks & GB_INTERFACE_QUIRK_NO_CPORT_FEATURES) { + if (gb_connection_flow_control_disabled(connection)) { cport_flags |= GB_SVC_CPORT_FLAG_CSD_N; } else if (gb_connection_e2efc_enabled(connection)) { cport_flags |= GB_SVC_CPORT_FLAG_CSD_N | diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 443d27b..bb25abf 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -14,6 +14,7 @@ #include <linux/kfifo.h> #define GB_CONNECTION_FLAG_CSD BIT(0) +#define GB_CONNECTION_FLAG_NO_FLOWCTRL BIT(1) enum gb_connection_state { GB_CONNECTION_STATE_INVALID = 0, @@ -88,6 +89,12 @@ static inline bool gb_connection_e2efc_enabled(struct gb_connection *connection) return !(connection->flags & GB_CONNECTION_FLAG_CSD); } +static inline bool +gb_connection_flow_control_disabled(struct gb_connection *connection) +{ + return connection->flags & GB_CONNECTION_FLAG_NO_FLOWCTRL; +} + static inline void *gb_connection_get_data(struct gb_connection *connection) { return connection->private; -- cgit v0.10.2 From ca1f8f809024db5fb1434d7e864a356fd5132c03 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 11 May 2016 10:17:56 +0200 Subject: greybus: connection: add offloaded connection flag Add an offloaded connection flag, which is used to mark a connection as offloaded and prevent drivers from initiating operation over it. This will be used for the audio and camera data connections. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index bb25abf..c740c381 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -15,6 +15,7 @@ #define GB_CONNECTION_FLAG_CSD BIT(0) #define GB_CONNECTION_FLAG_NO_FLOWCTRL BIT(1) +#define GB_CONNECTION_FLAG_OFFLOADED BIT(2) enum gb_connection_state { GB_CONNECTION_STATE_INVALID = 0, @@ -95,6 +96,11 @@ gb_connection_flow_control_disabled(struct gb_connection *connection) return connection->flags & GB_CONNECTION_FLAG_NO_FLOWCTRL; } +static inline bool gb_connection_is_offloaded(struct gb_connection *connection) +{ + return connection->flags & GB_CONNECTION_FLAG_OFFLOADED; +} + static inline void *gb_connection_get_data(struct gb_connection *connection) { return connection->private; diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 62d0c45..716627e 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -654,6 +654,9 @@ int gb_operation_request_send(struct gb_operation *operation, unsigned int cycle; int ret; + if (gb_connection_is_offloaded(connection)) + return -EBUSY; + if (!callback) return -EINVAL; @@ -950,8 +953,9 @@ void gb_connection_recv(struct gb_connection *connection, size_t msg_size; u16 operation_id; - if (connection->state != GB_CONNECTION_STATE_ENABLED && - connection->state != GB_CONNECTION_STATE_ENABLED_TX) { + if ((connection->state != GB_CONNECTION_STATE_ENABLED && + connection->state != GB_CONNECTION_STATE_ENABLED_TX) || + gb_connection_is_offloaded(connection)) { dev_warn(dev, "%s: dropping %zu received bytes\n", connection->name, size); return; -- cgit v0.10.2 From 781ac8662ffafa89e6675c3eb608ec9c569f24b7 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 11 May 2016 10:17:57 +0200 Subject: greybus: connection: add helper for creating offloaded connection Add helper for creating offloaded connection. This can later be extended to support more elaborate resource management. Also fix a minor white space issue. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 9e88281..95855d1 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -264,6 +264,19 @@ gb_connection_create_flags(struct gb_bundle *bundle, u16 cport_id, } EXPORT_SYMBOL_GPL(gb_connection_create_flags); +struct gb_connection * +gb_connection_create_offloaded(struct gb_bundle *bundle, u16 cport_id, + unsigned long flags) +{ + struct gb_interface *intf = bundle->intf; + + flags |= GB_CONNECTION_FLAG_OFFLOADED; + + return _gb_connection_create(intf->hd, -1, intf, bundle, cport_id, + NULL, flags); +} +EXPORT_SYMBOL_GPL(gb_connection_create_offloaded); + static int gb_connection_hd_cport_enable(struct gb_connection *connection) { struct gb_host_device *hd = connection->hd; diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index c740c381..a8da9ca 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -64,9 +64,11 @@ struct gb_connection *gb_connection_create_static(struct gb_host_device *hd, struct gb_connection *gb_connection_create_control(struct gb_interface *intf); struct gb_connection *gb_connection_create(struct gb_bundle *bundle, u16 cport_id, gb_request_handler_t handler); -struct gb_connection * gb_connection_create_flags(struct gb_bundle *bundle, +struct gb_connection *gb_connection_create_flags(struct gb_bundle *bundle, u16 cport_id, gb_request_handler_t handler, unsigned long flags); +struct gb_connection *gb_connection_create_offloaded(struct gb_bundle *bundle, + u16 cport_id, unsigned long flags); void gb_connection_destroy(struct gb_connection *connection); static inline bool gb_connection_is_static(struct gb_connection *connection) -- cgit v0.10.2 From a8af16313d18ce75d56c256fdfefed53a0572d45 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 11 May 2016 10:17:58 +0200 Subject: greybus: audio: mark the data connection as offloaded Mark the data-connection as offloaded, that is, under control of the host device (AP-bridge). This prevents messages from being sent from or forwarded to the AP. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_module.c b/drivers/staging/greybus/audio_module.c index d2dd5b8..57d3b02 100644 --- a/drivers/staging/greybus/audio_module.c +++ b/drivers/staging/greybus/audio_module.c @@ -146,15 +146,6 @@ static int gbaudio_codec_request_handler(struct gb_operation *op) return ret; } -static int gbaudio_data_connection_request_handler(struct gb_operation *op) -{ - struct gb_connection *connection = op->connection; - - dev_warn(&connection->bundle->dev, "Audio Event received\n"); - - return 0; -} - static int gb_audio_add_mgmt_connection(struct gbaudio_module_info *gbmodule, struct greybus_descriptor_cport *cport_desc, struct gb_bundle *bundle) @@ -192,9 +183,8 @@ static int gb_audio_add_data_connection(struct gbaudio_module_info *gbmodule, return -ENOMEM; } - connection = gb_connection_create_flags(bundle, + connection = gb_connection_create_offloaded(bundle, le16_to_cpu(cport_desc->id), - gbaudio_data_connection_request_handler, GB_CONNECTION_FLAG_CSD); if (IS_ERR(connection)) { devm_kfree(gbmodule->dev, dai); -- cgit v0.10.2 From 74a5d93cee1fb08d8e576888418ddd401aba6713 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 11 May 2016 10:17:59 +0200 Subject: greybus: hd: move CPort allocation to host-device code Move host-device CPort allocation to the host-device code. Proper CPort allocation requires knowledge of the hardware and must be handled by the host-device driver. This is an intermediate step that moves the generic CPort-allocation code to the host-device code. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 95855d1..ac99fc04 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -142,21 +142,8 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, unsigned long flags) { struct gb_connection *connection; - struct ida *id_map = &hd->cport_id_map; - int ida_start, ida_end; int ret; - if (hd_cport_id < 0) { - ida_start = 0; - ida_end = hd->num_cports; - } else if (hd_cport_id < hd->num_cports) { - ida_start = hd_cport_id; - ida_end = hd_cport_id + 1; - } else { - dev_err(&hd->dev, "cport %d not available\n", hd_cport_id); - return ERR_PTR(-EINVAL); - } - mutex_lock(&gb_connection_mutex); if (intf && gb_connection_intf_find(intf, cport_id)) { @@ -165,15 +152,17 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, goto err_unlock; } - ret = ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL); - if (ret < 0) + ret = gb_hd_cport_allocate(hd, hd_cport_id); + if (ret < 0) { + dev_err(&hd->dev, "failed to allocate cport: %d\n", ret); goto err_unlock; + } hd_cport_id = ret; connection = kzalloc(sizeof(*connection), GFP_KERNEL); if (!connection) { ret = -ENOMEM; - goto err_remove_ida; + goto err_hd_cport_release; } connection->hd_cport_id = hd_cport_id; @@ -219,8 +208,8 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, err_free_connection: kfree(connection); -err_remove_ida: - ida_simple_remove(id_map, hd_cport_id); +err_hd_cport_release: + gb_hd_cport_release(hd, hd_cport_id); err_unlock: mutex_unlock(&gb_connection_mutex); @@ -658,8 +647,6 @@ EXPORT_SYMBOL_GPL(gb_connection_disable); /* Caller must have disabled the connection before destroying it. */ void gb_connection_destroy(struct gb_connection *connection) { - struct ida *id_map; - if (!connection) return; @@ -672,8 +659,7 @@ void gb_connection_destroy(struct gb_connection *connection) destroy_workqueue(connection->wq); - id_map = &connection->hd->cport_id_map; - ida_simple_remove(id_map, connection->hd_cport_id); + gb_hd_cport_release(connection->hd, connection->hd_cport_id); connection->hd_cport_id = CPORT_ID_BAD; mutex_unlock(&gb_connection_mutex); diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index 2863472..f24e06b 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -39,6 +39,32 @@ static struct attribute *bus_attrs[] = { }; ATTRIBUTE_GROUPS(bus); +/* Locking: Caller guarantees serialisation */ +int gb_hd_cport_allocate(struct gb_host_device *hd, int cport_id) +{ + struct ida *id_map = &hd->cport_id_map; + int ida_start, ida_end; + + if (cport_id < 0) { + ida_start = 0; + ida_end = hd->num_cports; + } else if (cport_id < hd->num_cports) { + ida_start = cport_id; + ida_end = cport_id + 1; + } else { + dev_err(&hd->dev, "cport %d not available\n", cport_id); + return -EINVAL; + } + + return ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL); +} + +/* Locking: Caller guarantees serialisation */ +void gb_hd_cport_release(struct gb_host_device *hd, u16 cport_id) +{ + ida_simple_remove(&hd->cport_id_map, cport_id); +} + static void gb_hd_release(struct device *dev) { struct gb_host_device *hd = to_gb_host_device(dev); diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h index ff71936..4a197ac 100644 --- a/drivers/staging/greybus/hd.h +++ b/drivers/staging/greybus/hd.h @@ -50,6 +50,9 @@ struct gb_host_device { }; #define to_gb_host_device(d) container_of(d, struct gb_host_device, dev) +int gb_hd_cport_allocate(struct gb_host_device *hd, int cport_id); +void gb_hd_cport_release(struct gb_host_device *hd, u16 cport_id); + struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, struct device *parent, size_t buffer_size_max, -- cgit v0.10.2 From be5d01f10bdb782d31039930a9414c2f880e3430 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 11 May 2016 10:18:00 +0200 Subject: greybus: es2: fix probe error handling Make sure to return -ENODEV when the expected endpoints are missing and stop relying on a default error. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 1cef13d..f8bc3ec 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -938,7 +938,7 @@ static int ap_probe(struct usb_interface *interface, struct usb_endpoint_descriptor *endpoint; int bulk_in = 0; int bulk_out = 0; - int retval = -ENOMEM; + int retval; int i; int num_cports; int cport_id; @@ -1002,6 +1002,7 @@ static int ap_probe(struct usb_interface *interface, } if (bulk_in != NUM_BULKS || bulk_out != NUM_BULKS) { dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n"); + retval = -ENODEV; goto error; } @@ -1014,11 +1015,15 @@ static int ap_probe(struct usb_interface *interface, u8 *buffer; urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) + if (!urb) { + retval = -ENOMEM; goto error; + } buffer = kmalloc(ES2_GBUF_MSG_SIZE_MAX, GFP_KERNEL); - if (!buffer) + if (!buffer) { + retval = -ENOMEM; goto error; + } usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, @@ -1035,8 +1040,10 @@ static int ap_probe(struct usb_interface *interface, struct urb *urb; urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) + if (!urb) { + retval = -ENOMEM; goto error; + } es2->cport_out_urb[i] = urb; es2->cport_out_urb_busy[i] = false; /* just to be anal */ -- cgit v0.10.2 From 050615076699e537b26ed0934e105e78e7f1e765 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 11 May 2016 10:18:01 +0200 Subject: greybus: es2: clean up CDSI CPort reservation Clean up the CDSI CPort reservation by adding a host-device helper and CPort defines. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index f8bc3ec..c8ee779 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -18,6 +18,11 @@ #include "connection.h" #include "greybus_trace.h" + +/* Fixed CPort numbers */ +#define ES2_CPORT_CDSI0 16 +#define ES2_CPORT_CDSI1 17 + /* Memory sizes for the buffers sent to/from the ES2 controller */ #define ES2_GBUF_MSG_SIZE_MAX 2048 @@ -941,7 +946,6 @@ static int ap_probe(struct usb_interface *interface, int retval; int i; int num_cports; - int cport_id; udev = usb_get_dev(interface_to_usbdev(interface)); @@ -960,14 +964,6 @@ static int ap_probe(struct usb_interface *interface, return PTR_ERR(hd); } - /* - * CPorts 16 and 17 are reserved for CDSI0 and CDSI1, make sure they - * won't be allocated dynamically. - */ - do { - cport_id = ida_simple_get(&hd->cport_id_map, 16, 18, GFP_KERNEL); - } while (cport_id > 0); - es2 = hd_to_es2(hd); es2->hd = hd; es2->usb_intf = interface; @@ -976,6 +972,17 @@ static int ap_probe(struct usb_interface *interface, INIT_KFIFO(es2->apb_log_fifo); usb_set_intfdata(interface, es2); + /* + * Reserve the CDSI0 and CDSI1 CPorts so they won't be allocated + * dynamically. + */ + retval = gb_hd_cport_reserve(hd, ES2_CPORT_CDSI0); + if (retval) + goto error; + retval = gb_hd_cport_reserve(hd, ES2_CPORT_CDSI1); + if (retval) + goto error; + es2->cport_to_ep = kcalloc(hd->num_cports, sizeof(*es2->cport_to_ep), GFP_KERNEL); if (!es2->cport_to_ep) { diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index f24e06b..b87e086 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -39,6 +39,21 @@ static struct attribute *bus_attrs[] = { }; ATTRIBUTE_GROUPS(bus); +int gb_hd_cport_reserve(struct gb_host_device *hd, u16 cport_id) +{ + struct ida *id_map = &hd->cport_id_map; + int ret; + + ret = ida_simple_get(id_map, cport_id, cport_id + 1, GFP_KERNEL); + if (ret < 0) { + dev_err(&hd->dev, "failed to reserve cport %u\n", cport_id); + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(gb_hd_cport_reserve); + /* Locking: Caller guarantees serialisation */ int gb_hd_cport_allocate(struct gb_host_device *hd, int cport_id) { diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h index 4a197ac..5d74e0c 100644 --- a/drivers/staging/greybus/hd.h +++ b/drivers/staging/greybus/hd.h @@ -50,6 +50,7 @@ struct gb_host_device { }; #define to_gb_host_device(d) container_of(d, struct gb_host_device, dev) +int gb_hd_cport_reserve(struct gb_host_device *hd, u16 cport_id); int gb_hd_cport_allocate(struct gb_host_device *hd, int cport_id); void gb_hd_cport_release(struct gb_host_device *hd, u16 cport_id); -- cgit v0.10.2 From f2aae1c6e60f2acd636c005951a2c932bc5c8d05 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 11 May 2016 10:18:02 +0200 Subject: greybus: hd: generalise cport allocation Generalise CPort allocation by allowing host-device drivers to override the default implementation. Also pass the connection flags down the stack as such information is needed for proper CPort allocation. Specifically, this will initially be used to allow the camera driver to allocate the dedicated CDSI CPorts. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index ac99fc04..395a9df 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -152,7 +152,7 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, goto err_unlock; } - ret = gb_hd_cport_allocate(hd, hd_cport_id); + ret = gb_hd_cport_allocate(hd, hd_cport_id, flags); if (ret < 0) { dev_err(&hd->dev, "failed to allocate cport: %d\n", ret); goto err_unlock; diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index b87e086..fba6d76 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -55,11 +55,15 @@ int gb_hd_cport_reserve(struct gb_host_device *hd, u16 cport_id) EXPORT_SYMBOL_GPL(gb_hd_cport_reserve); /* Locking: Caller guarantees serialisation */ -int gb_hd_cport_allocate(struct gb_host_device *hd, int cport_id) +int gb_hd_cport_allocate(struct gb_host_device *hd, int cport_id, + unsigned long flags) { struct ida *id_map = &hd->cport_id_map; int ida_start, ida_end; + if (hd->driver->cport_allocate) + return hd->driver->cport_allocate(hd, cport_id, flags); + if (cport_id < 0) { ida_start = 0; ida_end = hd->num_cports; @@ -77,6 +81,11 @@ int gb_hd_cport_allocate(struct gb_host_device *hd, int cport_id) /* Locking: Caller guarantees serialisation */ void gb_hd_cport_release(struct gb_host_device *hd, u16 cport_id) { + if (hd->driver->cport_release) { + hd->driver->cport_release(hd, cport_id); + return; + } + ida_simple_remove(&hd->cport_id_map, cport_id); } diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h index 5d74e0c..80573ae 100644 --- a/drivers/staging/greybus/hd.h +++ b/drivers/staging/greybus/hd.h @@ -16,6 +16,9 @@ struct gb_message; struct gb_hd_driver { size_t hd_priv_size; + int (*cport_allocate)(struct gb_host_device *hd, int cport_id, + unsigned long flags); + void (*cport_release)(struct gb_host_device *hd, u16 cport_id); int (*cport_enable)(struct gb_host_device *hd, u16 cport_id); int (*cport_disable)(struct gb_host_device *hd, u16 cport_id); int (*message_send)(struct gb_host_device *hd, u16 dest_cport_id, @@ -51,7 +54,8 @@ struct gb_host_device { #define to_gb_host_device(d) container_of(d, struct gb_host_device, dev) int gb_hd_cport_reserve(struct gb_host_device *hd, u16 cport_id); -int gb_hd_cport_allocate(struct gb_host_device *hd, int cport_id); +int gb_hd_cport_allocate(struct gb_host_device *hd, int cport_id, + unsigned long flags); void gb_hd_cport_release(struct gb_host_device *hd, u16 cport_id); struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, -- cgit v0.10.2 From e7b848c288dbcfb4b153ca5c772c8573caf739fb Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 11 May 2016 10:18:03 +0200 Subject: greybus: es2: clean up cport-reset handling Move handling of CPort-reset exceptions to the reset handler. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index c8ee779..f06a322 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -506,6 +506,11 @@ static int cport_reset(struct gb_host_device *hd, u16 cport_id) struct usb_device *udev = es2->usb_dev; int retval; + switch (cport_id) { + case GB_SVC_CPORT_ID: + return 0; + } + retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), GB_APB_REQUEST_RESET_CPORT, USB_DIR_OUT | USB_TYPE_VENDOR | @@ -524,11 +529,9 @@ static int cport_enable(struct gb_host_device *hd, u16 cport_id) { int retval; - if (cport_id != GB_SVC_CPORT_ID) { - retval = cport_reset(hd, cport_id); - if (retval) - return retval; - } + retval = cport_reset(hd, cport_id); + if (retval) + return retval; return 0; } -- cgit v0.10.2 From 045d356114557781f4b703ff569f2e3785e87b2e Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 11 May 2016 10:18:04 +0200 Subject: greybus: es2: add support for CDSI1 allocation Use the new CPort-allocation callbacks to allow for rudimentary resource management of the CDSI CPorts. How to manage offloaded resources in a generic fashion is yet to be determined, but this minimal implementation will allow core to manage the camera data connection so that the current camera-driver hacks can be removed. This is specifically required to be able to implement proper connection closing and for power management. Note that the CDSI CPorts can not (currently) be reset through the USB vendor request. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index a8da9ca..b152e23 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -16,6 +16,7 @@ #define GB_CONNECTION_FLAG_CSD BIT(0) #define GB_CONNECTION_FLAG_NO_FLOWCTRL BIT(1) #define GB_CONNECTION_FLAG_OFFLOADED BIT(2) +#define GB_CONNECTION_FLAG_CDSI1 BIT(3) enum gb_connection_state { GB_CONNECTION_STATE_INVALID = 0, diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index f06a322..998b41e 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -99,6 +99,8 @@ struct es2_ap_dev { bool cport_out_urb_cancelled[NUM_CPORT_OUT_URB]; spinlock_t cport_out_urb_lock; + bool cdsi1_in_use; + int *cport_to_ep; struct task_struct *apb_log_task; @@ -508,6 +510,8 @@ static int cport_reset(struct gb_host_device *hd, u16 cport_id) switch (cport_id) { case GB_SVC_CPORT_ID: + case ES2_CPORT_CDSI0: + case ES2_CPORT_CDSI1: return 0; } @@ -525,6 +529,59 @@ static int cport_reset(struct gb_host_device *hd, u16 cport_id) return 0; } +static int es2_cport_allocate(struct gb_host_device *hd, int cport_id, + unsigned long flags) +{ + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct ida *id_map = &hd->cport_id_map; + int ida_start, ida_end; + + switch (cport_id) { + case ES2_CPORT_CDSI0: + case ES2_CPORT_CDSI1: + dev_err(&hd->dev, "cport %d not available\n", cport_id); + return -EBUSY; + } + + if (flags & GB_CONNECTION_FLAG_OFFLOADED && + flags & GB_CONNECTION_FLAG_CDSI1) { + if (es2->cdsi1_in_use) { + dev_err(&hd->dev, "CDSI1 already in use\n"); + return -EBUSY; + } + + es2->cdsi1_in_use = true; + + return ES2_CPORT_CDSI1; + } + + if (cport_id < 0) { + ida_start = 0; + ida_end = hd->num_cports; + } else if (cport_id < hd->num_cports) { + ida_start = cport_id; + ida_end = cport_id + 1; + } else { + dev_err(&hd->dev, "cport %d not available\n", cport_id); + return -EINVAL; + } + + return ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL); +} + +static void es2_cport_release(struct gb_host_device *hd, u16 cport_id) +{ + struct es2_ap_dev *es2 = hd_to_es2(hd); + + switch (cport_id) { + case ES2_CPORT_CDSI1: + es2->cdsi1_in_use = false; + return; + } + + ida_simple_remove(&hd->cport_id_map, cport_id); +} + static int cport_enable(struct gb_host_device *hd, u16 cport_id) { int retval; @@ -621,6 +678,8 @@ static struct gb_hd_driver es2_driver = { .hd_priv_size = sizeof(struct es2_ap_dev), .message_send = message_send, .message_cancel = message_cancel, + .cport_allocate = es2_cport_allocate, + .cport_release = es2_cport_release, .cport_enable = cport_enable, .latency_tag_enable = latency_tag_enable, .latency_tag_disable = latency_tag_disable, -- cgit v0.10.2 From 3b05d8508f82fc18fe7ef0618671c0603c490c0d Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 11 May 2016 10:18:05 +0200 Subject: greybus: connection: add camera-data connected workaround Firmware currently lacks a representation of the offloaded CDSI connections and connected requests sent for these ports therefore fails. Add a temporary work-around until this has been resolved in firmware. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 395a9df..f803d40 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -402,6 +402,16 @@ static int gb_connection_control_connected(struct gb_connection *connection) if (gb_connection_is_static(connection)) return 0; + /* + * HACK: Suppress connected request for the offloaded camera + * connection as it is currently not supported by firmware. Note that + * the corresponding non-fatal disconnected event is still sent. + */ + if (gb_connection_is_offloaded(connection) && + connection->flags & GB_CONNECTION_FLAG_CDSI1) { + return 0; + } + control = connection->intf->control; if (connection == control->connection) -- cgit v0.10.2 From 3ba9fa5c9220e5a6dbbe0b88fc40f857f299b040 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 11 May 2016 10:18:06 +0200 Subject: greybus: camera: fix data-connection handling Now that core supports offloaded connections, we can remove the hack that was used to setup the data connection. Note that offloaded-resource management may need to be refined later, but the current minimal implementation is enough to allow core to manage the connections (e.g. needed for proper connection tear down and power management). This will also allow the camera driver to be converted to a bundle driver. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index ba76f56..4831ad6 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -42,7 +42,7 @@ struct gb_camera_debugfs_buffer { */ struct gb_camera { struct gb_connection *connection; - bool data_connected; + struct gb_connection *data_connection; struct { struct dentry *root; @@ -900,13 +900,9 @@ static void gb_camera_cleanup(struct gb_camera *gcam) { gb_camera_debugfs_cleanup(gcam); - if (gcam->data_connected) { - struct gb_interface *intf = gcam->connection->intf; - struct gb_svc *svc = gcam->connection->hd->svc; - - gb_svc_connection_destroy(svc, intf->interface_id, - ES2_APB_CDSI0_CPORT, svc->ap_intf_id, - ES2_APB_CDSI1_CPORT); + if (gcam->data_connection) { + gb_connection_disable(gcam->data_connection); + gb_connection_destroy(gcam->data_connection); } kfree(gcam); @@ -914,9 +910,9 @@ static void gb_camera_cleanup(struct gb_camera *gcam) static int gb_camera_connection_init(struct gb_connection *connection) { - struct gb_svc *svc = connection->hd->svc; + struct gb_connection *data; struct gb_camera *gcam; - u8 cport_flags; + unsigned long data_flags; int ret; gcam = kzalloc(sizeof(*gcam), GFP_KERNEL); @@ -930,14 +926,20 @@ static int gb_camera_connection_init(struct gb_connection *connection) * Create the data connection between camera module CDSI0 and APB CDS1. * The CPort IDs are hardcoded by the ES2 bridges. */ - cport_flags = GB_SVC_CPORT_FLAG_CSD_N | GB_SVC_CPORT_FLAG_CSV_N; - ret = gb_svc_connection_create(svc, connection->intf->interface_id, - ES2_APB_CDSI0_CPORT, svc->ap_intf_id, - ES2_APB_CDSI1_CPORT, cport_flags); - if (ret < 0) + data_flags = GB_CONNECTION_FLAG_NO_FLOWCTRL | GB_CONNECTION_FLAG_CDSI1; + + data = gb_connection_create_offloaded(connection->bundle, + ES2_APB_CDSI0_CPORT, + data_flags); + if (IS_ERR(data)) { + ret = PTR_ERR(data); goto error; + } + gcam->data_connection = data; - gcam->data_connected = true; + ret = gb_connection_enable(data); + if (ret) + goto error; ret = gb_camera_debugfs_init(gcam); if (ret < 0) -- cgit v0.10.2 From 14a5f47b29bf4c92ba4233cdd89ea5ce67acac0f Mon Sep 17 00:00:00 2001 From: Sandeep Patil <sspatil@google.com> Date: Fri, 13 May 2016 11:51:03 -0700 Subject: greybus: gpbridge: add gpbridge device type Right now, there is no way to know the device type of gpbridge (bridged-phy) devices in userspace. So, add that. Testing Done: Tested by reading the 'uevent' for gpb device of gpbridge module Signed-off-by: Sandeep Patil <sspatil@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c index adb317d..82fbf26 100644 --- a/drivers/staging/greybus/gpbridge.c +++ b/drivers/staging/greybus/gpbridge.c @@ -50,6 +50,11 @@ static void gpbdev_release(struct device *dev) kfree(gpbdev); } +struct device_type greybus_gpbdev_type = { + .name = "gpbridge_device", + .release = gpbdev_release, +}; + static int gpbdev_uevent(struct device *dev, struct kobj_uevent_env *env) { /* FIXME add something here, userspace will care about these... */ @@ -188,7 +193,7 @@ static struct gpbridge_device *gb_gpbridge_create_dev(struct gb_bundle *bundle, gpbdev->cport_desc = cport_desc; gpbdev->dev.parent = &bundle->dev; gpbdev->dev.bus = &gpbridge_bus_type; - gpbdev->dev.release = gpbdev_release; + gpbdev->dev.type = &greybus_gpbdev_type; gpbdev->dev.groups = gpbdev_groups; gpbdev->dev.dma_mask = bundle->dev.dma_mask; dev_set_name(&gpbdev->dev, "gpb%d", id); -- cgit v0.10.2 From c7092b22fc7d0debae114fe37cf3b967997e1cdb Mon Sep 17 00:00:00 2001 From: Sandeep Patil <sspatil@google.com> Date: Fri, 13 May 2016 11:51:04 -0700 Subject: greybus: gpbridge: make gpbridge device ids start with 1 Making gpb device ids consistent with all other devices on greybus Testing Done: Tested using gpb module to make sure the first gpbX/ device starts with 1. Signed-off-by: Sandeep Patil <sspatil@google.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c index 82fbf26..b22f5e4 100644 --- a/drivers/staging/greybus/gpbridge.c +++ b/drivers/staging/greybus/gpbridge.c @@ -178,7 +178,7 @@ static struct gpbridge_device *gb_gpbridge_create_dev(struct gb_bundle *bundle, int retval; int id; - id = ida_simple_get(&gpbridge_id, 0, 0, GFP_KERNEL); + id = ida_simple_get(&gpbridge_id, 1, 0, GFP_KERNEL); if (id < 0) return ERR_PTR(id); -- cgit v0.10.2 From 6458492e9c019bd15c9a543171df1cbe27122543 Mon Sep 17 00:00:00 2001 From: Sandeep Patil <sspatil@google.com> Date: Fri, 13 May 2016 11:51:05 -0700 Subject: greybus: gpbridge: add uevent vars for gpbridge devices The uevent vars now include module, interface, greybus_id, bundle id, class and gpbridge device specific properties. This make it consistent with how we are reporting uevents for all other greybus devices. Testing Done: Tested by reading uevent from gpbridge devices that enumerate using gpb module Signed-off-by: Sandeep Patil <sspatil@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c index b22f5e4..c8b3822 100644 --- a/drivers/staging/greybus/gpbridge.c +++ b/drivers/staging/greybus/gpbridge.c @@ -57,7 +57,31 @@ struct device_type greybus_gpbdev_type = { static int gpbdev_uevent(struct device *dev, struct kobj_uevent_env *env) { - /* FIXME add something here, userspace will care about these... */ + struct gpbridge_device *gpbdev = to_gpbridge_dev(dev); + struct greybus_descriptor_cport *cport_desc = gpbdev->cport_desc; + struct gb_bundle *bundle = gpbdev->bundle; + struct gb_interface *intf = bundle->intf; + struct gb_module *module = intf->module; + struct gb_host_device *hd = intf->hd; + + if (add_uevent_var(env, "BUS=%u", hd->bus_id)) + return -ENOMEM; + if (add_uevent_var(env, "MODULE=%u", module->module_id)) + return -ENOMEM; + if (add_uevent_var(env, "INTERFACE=%u", intf->interface_id)) + return -ENOMEM; + if (add_uevent_var(env, "GREYBUS_ID=%08x/%08x", + intf->vendor_id, intf->product_id)) + return -ENOMEM; + if (add_uevent_var(env, "BUNDLE=%u", gpbdev->bundle->id)) + return -ENOMEM; + if (add_uevent_var(env, "BUNDLE_CLASS=%02x", bundle->class)) + return -ENOMEM; + if (add_uevent_var(env, "GPBDEV_ID=%u", gpbdev->id)) + return -ENOMEM; + if (add_uevent_var(env, "PROTOCOL_ID=%02x", cport_desc->protocol_id)) + return -ENOMEM; + return 0; } -- cgit v0.10.2 From a974f469ff097f8f6e242f3ef5b26ba3604fbaf2 Mon Sep 17 00:00:00 2001 From: Sandeep Patil <sspatil@google.com> Date: Fri, 13 May 2016 12:00:56 -0700 Subject: greybus: arche-platform: Fix the MODULE_LICENSE to match with header The header calls out the license to be GPL v2, while the module declares itself as "GPL" Testing Done: Trivial Signed-off-by: Sandeep Patil <sspatil@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 83d823c..e385434 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -754,6 +754,6 @@ static void __exit arche_exit(void) } module_exit(arche_exit); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Vaibhav Hiremath <vaibhav.hiremath@linaro.org>"); MODULE_DESCRIPTION("Arche Platform Driver"); -- cgit v0.10.2 From 5705020fbe2a274a1a49709e688b4cc471425036 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Thu, 12 May 2016 12:43:50 +0100 Subject: greybus: svc: Add TimeSync SVC commands Simple addition of the TimeSync commands defined in the specification. Adds: - svc.c::timesync_enable(u8 count, u64 frame_time, u32 strobe_delay, u32 refclk) Commands the SVC to initiate count TimeSync strobe pulses with strobe_delay microseconds delay between each strobe to the specified bit-mask of Interface IDs indicated in a previous timesync_wake_pins_acquire command. The frame_time parameter indicates the initial time the SVC should base the first strobe from. The refclk parameter indicates the APs clock rate, the SVC should ensure its own clock ticks at this rate. Once enabled the SVC may not enter a low-power mode which will result in the reference timer used to track time switching off. The SVC will capture the authoritative FrameTime at each strobe and store these values for later propagation to the AP with the timesync_authoritative request. - svc.c::timesync_disable(void) Commands the SVC to immediately halt TimeSync logic. This will allow the SVC to transition into low-power modes where the reference timer being used for TimeSync may switch off. - svc.c::timesync_authoritative(u64 *frame_time) Used by the AP Module to ask the SVC for the authoritative FrameTime as captured at each TimeSync strobe. - svc.c::timesync_ping(u64 *frame_time) Used by the AP Module to command the SVC to initiate a single strobe on a specified bit-mask of Interface IDs communicated in a previous timesync_wake_pins_acquire command. SVC will latch the FrameTime on the rising edge of the outbound pulse and will return the FrameTime to the AP Module in the response phase of the greybus transaction. - svc::timesync_wake_pins_acquire(u32 strobe_mask) Used by the AP to tell the SVC to set a bit-mask of wake lines associated with a bit-mask of Interface IDs to a known initial state prior to the SVC generating a TimeSync related pulse such as timesync-enable or timesync-ping. - svc::timesync_wake_pins_release(void) Used by the AP to tell the SVC to release all wake-detect lines in the timesync active state as previously specified in the timesync_wake_pins_acquire operation. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Reviewed-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 3bdf778..80e8cf0 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -459,6 +459,91 @@ void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, } EXPORT_SYMBOL_GPL(gb_svc_connection_destroy); +int gb_svc_timesync_enable(struct gb_svc *svc, u8 count, u64 frame_time, + u32 strobe_delay, u32 refclk) +{ + struct gb_connection *connection = svc->connection; + struct gb_svc_timesync_enable_request request; + + request.count = count; + request.frame_time = cpu_to_le64(frame_time); + request.strobe_delay = cpu_to_le32(strobe_delay); + request.refclk = cpu_to_le32(refclk); + return gb_operation_sync(connection, + GB_SVC_TYPE_TIMESYNC_ENABLE, + &request, sizeof(request), NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_svc_timesync_enable); + +int gb_svc_timesync_disable(struct gb_svc *svc) +{ + struct gb_connection *connection = svc->connection; + + return gb_operation_sync(connection, + GB_SVC_TYPE_TIMESYNC_DISABLE, + NULL, 0, NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_svc_timesync_disable); + +int gb_svc_timesync_authoritative(struct gb_svc *svc, u64 *frame_time) +{ + struct gb_connection *connection = svc->connection; + struct gb_svc_timesync_authoritative_response response; + int ret, i; + + ret = gb_operation_sync(connection, + GB_SVC_TYPE_TIMESYNC_AUTHORITATIVE, NULL, 0, + &response, sizeof(response)); + if (ret < 0) + return ret; + + for (i = 0; i < GB_TIMESYNC_MAX_STROBES; i++) + frame_time[i] = le64_to_cpu(response.frame_time[i]); + return 0; +} +EXPORT_SYMBOL_GPL(gb_svc_timesync_authoritative); + +int gb_svc_timesync_ping(struct gb_svc *svc, u64 *frame_time) +{ + struct gb_connection *connection = svc->connection; + struct gb_svc_timesync_ping_response response; + int ret; + + ret = gb_operation_sync(connection, + GB_SVC_TYPE_TIMESYNC_PING, + NULL, 0, + &response, sizeof(response)); + if (ret < 0) + return ret; + + *frame_time = le64_to_cpu(response.frame_time); + return 0; +} +EXPORT_SYMBOL_GPL(gb_svc_timesync_ping); + +int gb_svc_timesync_wake_pins_acquire(struct gb_svc *svc, u32 strobe_mask) +{ + struct gb_connection *connection = svc->connection; + struct gb_svc_timesync_wake_pins_acquire_request request; + + request.strobe_mask = cpu_to_le32(strobe_mask); + return gb_operation_sync(connection, + GB_SVC_TYPE_TIMESYNC_WAKE_PINS_ACQUIRE, + &request, sizeof(request), + NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_svc_timesync_wake_pins_acquire); + +int gb_svc_timesync_wake_pins_release(struct gb_svc *svc) +{ + struct gb_connection *connection = svc->connection; + + return gb_operation_sync(connection, + GB_SVC_TYPE_TIMESYNC_WAKE_PINS_RELEASE, + NULL, 0, NULL, 0); +} +EXPORT_SYMBOL_GPL(gb_svc_timesync_wake_pins_release); + /* Creates bi-directional routes between the devices */ int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, u8 intf2_id, u8 dev2_id) diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index 7268db6..e3e0aa1 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -85,6 +85,13 @@ void gb_svc_watchdog_destroy(struct gb_svc *svc); bool gb_svc_watchdog_enabled(struct gb_svc *svc); int gb_svc_watchdog_enable(struct gb_svc *svc); int gb_svc_watchdog_disable(struct gb_svc *svc); +int gb_svc_timesync_enable(struct gb_svc *svc, u8 count, u64 frame_time, + u32 strobe_delay, u32 refclk); +int gb_svc_timesync_disable(struct gb_svc *svc); +int gb_svc_timesync_authoritative(struct gb_svc *svc, u64 *frame_time); +int gb_svc_timesync_ping(struct gb_svc *svc, u64 *frame_time); +int gb_svc_timesync_wake_pins_acquire(struct gb_svc *svc, u32 strobe_mask); +int gb_svc_timesync_wake_pins_release(struct gb_svc *svc); int gb_svc_protocol_init(void); void gb_svc_protocol_exit(void); -- cgit v0.10.2 From fa433b619655bf2d253094074d132004a9fa479c Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Thu, 12 May 2016 12:43:51 +0100 Subject: greybus: control: Add TimeSync get-last-event logic gb_control_timesync_get_last_event() sends a request asking for the FrameTime at the last SVC strobe event. The responding entity returns the FrameTime in the response phase of the request. Performing this operation to an Interface after previously: 1. Synchronizing time using timesync-enable/timesync-authoritative 2. Sending an SVC_TIMESYNC_PING will return the FrameTime of the responding entity at the SVC-ping. If this command is sent before synchronization has been initiated or successfully completed the responding entity should return an error code. - control.c::gb_control_timesync_get_last_event(u64 *frame_time) Returns the FrameTime at the last SVC_TIMESYNC_PING to the AP Module. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Reviewed-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index 13c68f3..7a83806 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -177,6 +177,20 @@ int gb_control_timesync_disable(struct gb_control *control) NULL, 0); } +int gb_control_timesync_get_last_event(struct gb_control *control, + u64 *frame_time) +{ + struct gb_control_timesync_get_last_event_response response; + int ret; + + ret = gb_operation_sync(control->connection, + GB_CONTROL_TYPE_TIMESYNC_GET_LAST_EVENT, + NULL, 0, &response, sizeof(response)); + if (!ret) + *frame_time = le64_to_cpu(response.frame_time); + return ret; +} + int gb_control_timesync_authoritative(struct gb_control *control, u64 *frame_time, u8 count) { diff --git a/drivers/staging/greybus/control.h b/drivers/staging/greybus/control.h index 773cdde..02b5839 100644 --- a/drivers/staging/greybus/control.h +++ b/drivers/staging/greybus/control.h @@ -43,6 +43,8 @@ int gb_control_get_manifest_operation(struct gb_interface *intf, void *manifest, int gb_control_timesync_enable(struct gb_control *control, u8 count, u64 frame_time, u32 strobe_delay, u32 refclk); int gb_control_timesync_disable(struct gb_control *control); +int gb_control_timesync_get_last_event(struct gb_control *control, + u64 *frame_time); int gb_control_timesync_authoritative(struct gb_control *control, u64 *frame_time, u8 count); diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index ca5eb3b..40bd6c0 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -123,6 +123,7 @@ struct gb_protocol_version_response { #define GB_CONTROL_TYPE_TIMESYNC_AUTHORITATIVE 0x09 /* Unused 0x0a */ #define GB_CONTROL_TYPE_BUNDLE_VERSION 0x0b +#define GB_CONTROL_TYPE_TIMESYNC_GET_LAST_EVENT 0x0d #define GB_CONTROL_TYPE_MODE_SWITCH 0x0e struct gb_control_version_request { @@ -179,6 +180,11 @@ struct gb_control_timesync_authoritative_request { } __packed; /* timesync authoritative response has no payload */ +/* timesync get_last_event_request has no payload */ +struct gb_control_timesync_get_last_event_response { + __le64 frame_time; +} __packed; + /* APBridge protocol */ /* request APB1 log */ -- cgit v0.10.2 From 123e7497237a43068d88d49efaca6fff1f5e29e3 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Thu, 12 May 2016 12:43:52 +0100 Subject: greybus: control: Drop unused parameter from timesync_authoritative The count field is redundant and unused. Drop it from the control timesync_authoritative command. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index 7a83806..b4a1c14 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -192,7 +192,7 @@ int gb_control_timesync_get_last_event(struct gb_control *control, } int gb_control_timesync_authoritative(struct gb_control *control, - u64 *frame_time, u8 count) + u64 *frame_time) { struct gb_control_timesync_authoritative_request request; int i; diff --git a/drivers/staging/greybus/control.h b/drivers/staging/greybus/control.h index 02b5839..33e7e27 100644 --- a/drivers/staging/greybus/control.h +++ b/drivers/staging/greybus/control.h @@ -46,6 +46,6 @@ int gb_control_timesync_disable(struct gb_control *control); int gb_control_timesync_get_last_event(struct gb_control *control, u64 *frame_time); int gb_control_timesync_authoritative(struct gb_control *control, - u64 *frame_time, u8 count); + u64 *frame_time); #endif /* __CONTROL_H */ -- cgit v0.10.2 From 90fa0e6c3ea768a649e50f810b83814b0d15ee92 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 9 May 2016 18:15:04 +0530 Subject: greybus: gpbridge: Export few routines In order to separate protocol specific drivers into their own modules, some of the gpbridge routines need to be exported. Tested on EVT 1.5 by inserting GP test module, all the devices were enumerated correctly. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c index c8b3822..4cb587f 100644 --- a/drivers/staging/greybus/gpbridge.c +++ b/drivers/staging/greybus/gpbridge.c @@ -163,11 +163,13 @@ int gb_gpbridge_register_driver(struct gpbridge_driver *driver, pr_info("registered new driver %s\n", driver->name); return 0; } +EXPORT_SYMBOL_GPL(gb_gpbridge_register_driver); void gb_gpbridge_deregister_driver(struct gpbridge_driver *driver) { driver_unregister(&driver->driver); } +EXPORT_SYMBOL_GPL(gb_gpbridge_deregister_driver); int gb_gpbridge_get_version(struct gb_connection *connection) { @@ -194,6 +196,7 @@ int gb_gpbridge_get_version(struct gb_connection *connection) return 0; } +EXPORT_SYMBOL_GPL(gb_gpbridge_get_version); static struct gpbridge_device *gb_gpbridge_create_dev(struct gb_bundle *bundle, struct greybus_descriptor_cport *cport_desc) -- cgit v0.10.2 From 9b919bdfcc6e9f8b3ea9f813b1604089ea769cfc Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 9 May 2016 18:15:05 +0530 Subject: greybus: gpbridge: Create module_gpbridge_driver() Create module_gpbridge_driver() for registering gpbridge module drivers. Tested on EVT 1.5 by inserting GP test module, all the devices were enumerated correctly. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/gpbridge.h b/drivers/staging/greybus/gpbridge.h index 1af20d8..cd5ba98 100644 --- a/drivers/staging/greybus/gpbridge.h +++ b/drivers/staging/greybus/gpbridge.h @@ -87,5 +87,16 @@ extern void gb_i2c_driver_exit(void); extern int gb_spi_driver_init(void); extern void gb_spi_driver_exit(void); +/** + * module_gpbridge_driver() - Helper macro for registering a gpbridge driver + * @__gpbridge_driver: gpbridge_driver structure + * + * Helper macro for gpbridge drivers to set up proper module init / exit + * functions. Replaces module_init() and module_exit() and keeps people from + * printing pointless things to the kernel log when their driver is loaded. + */ +#define module_gpbridge_driver(__gpbridge_driver) \ + module_driver(__gpbridge_driver, gb_gpbridge_register, gb_gpbridge_deregister) + #endif /* __GPBRIDGE_H */ -- cgit v0.10.2 From 7c0925eb57785190be3d9f3d173fefb3d791cba0 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 9 May 2016 18:15:06 +0530 Subject: greybus: gpio: Create separate module Create separate module for gpio gpbridge driver. Tested on EVT 1.5 by inserting GP test module, all the devices were enumerated correctly. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 43c0c99..e5c784d 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -18,7 +18,6 @@ gb-phy-y := gpbridge.o \ sdio.o \ uart.o \ pwm.o \ - gpio.o \ i2c.o \ spi.o \ usb.o @@ -40,6 +39,7 @@ gb-audio-manager-y += audio_manager.o gb-audio-manager-y += audio_manager_module.o gb-camera-y := camera.o gb-firmware-y := fw-core.o fw-download.o +gb-gpio-y := gpio.o obj-m += greybus.o obj-m += gb-phy.o @@ -62,6 +62,7 @@ obj-m += gb-audio-gb.o obj-m += gb-audio-apbridgea.o obj-m += gb-audio-manager.o obj-m += gb-firmware.o +obj-m += gb-gpio.o KERNELVER ?= $(shell uname -r) KERNELDIR ?= /lib/modules/$(KERNELVER)/build diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c index 4cb587f..8622677 100644 --- a/drivers/staging/greybus/gpbridge.c +++ b/drivers/staging/greybus/gpbridge.c @@ -317,10 +317,6 @@ static int __init gpbridge_init(void) goto error_gpbridge; } - if (gb_gpio_driver_init()) { - pr_err("error initializing gpio driver\n"); - goto error_gpio; - } if (gb_pwm_driver_init()) { pr_err("error initializing pwm driver\n"); goto error_pwm; @@ -359,8 +355,6 @@ error_sdio: error_uart: gb_pwm_driver_exit(); error_pwm: - gb_gpio_driver_exit(); -error_gpio: greybus_deregister(&gb_gpbridge_driver); error_gpbridge: bus_unregister(&gpbridge_bus_type); @@ -377,7 +371,6 @@ static void __exit gpbridge_exit(void) gb_sdio_driver_exit(); gb_uart_driver_exit(); gb_pwm_driver_exit(); - gb_gpio_driver_exit(); greybus_deregister(&gb_gpbridge_driver); bus_unregister(&gpbridge_bus_type); diff --git a/drivers/staging/greybus/gpbridge.h b/drivers/staging/greybus/gpbridge.h index cd5ba98..a346fa2 100644 --- a/drivers/staging/greybus/gpbridge.h +++ b/drivers/staging/greybus/gpbridge.h @@ -66,9 +66,6 @@ void gb_##__driver##_exit(void) \ gb_gpbridge_deregister(&__driver); \ } -extern int gb_gpio_driver_init(void); -extern void gb_gpio_driver_exit(void); - extern int gb_pwm_driver_init(void); extern void gb_pwm_driver_exit(void); diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 4f0695b..adb213f 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -747,6 +747,7 @@ static const struct gpbridge_device_id gb_gpio_id_table[] = { { GPBRIDGE_PROTOCOL(GREYBUS_PROTOCOL_GPIO) }, { }, }; +MODULE_DEVICE_TABLE(gpbridge, gb_gpio_id_table); static struct gpbridge_driver gpio_driver = { .name = "gpio", @@ -754,4 +755,6 @@ static struct gpbridge_driver gpio_driver = { .remove = gb_gpio_remove, .id_table = gb_gpio_id_table, }; -gb_gpbridge_builtin_driver(gpio_driver); + +module_gpbridge_driver(gpio_driver); +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From d6046b44a5663865a316f9d73a44d64c99aa9fb2 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 9 May 2016 18:15:07 +0530 Subject: greybus: i2c : Create separate module Create separate module for i2c gpbridge driver. Tested on EVT 1.5 by inserting GP test module, all the devices were enumerated correctly. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index e5c784d..b9e4e96 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -18,7 +18,6 @@ gb-phy-y := gpbridge.o \ sdio.o \ uart.o \ pwm.o \ - i2c.o \ spi.o \ usb.o @@ -40,6 +39,7 @@ gb-audio-manager-y += audio_manager_module.o gb-camera-y := camera.o gb-firmware-y := fw-core.o fw-download.o gb-gpio-y := gpio.o +gb-i2c-y := i2c.o obj-m += greybus.o obj-m += gb-phy.o @@ -63,6 +63,7 @@ obj-m += gb-audio-apbridgea.o obj-m += gb-audio-manager.o obj-m += gb-firmware.o obj-m += gb-gpio.o +obj-m += gb-i2c.o KERNELVER ?= $(shell uname -r) KERNELDIR ?= /lib/modules/$(KERNELVER)/build diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c index 8622677..92838d5 100644 --- a/drivers/staging/greybus/gpbridge.c +++ b/drivers/staging/greybus/gpbridge.c @@ -333,10 +333,6 @@ static int __init gpbridge_init(void) pr_err("error initializing usb driver\n"); goto error_usb; } - if (gb_i2c_driver_init()) { - pr_err("error initializing i2c driver\n"); - goto error_i2c; - } if (gb_spi_driver_init()) { pr_err("error initializing spi driver\n"); goto error_spi; @@ -345,8 +341,6 @@ static int __init gpbridge_init(void) return 0; error_spi: - gb_i2c_driver_exit(); -error_i2c: gb_usb_driver_exit(); error_usb: gb_sdio_driver_exit(); @@ -366,7 +360,6 @@ module_init(gpbridge_init); static void __exit gpbridge_exit(void) { gb_spi_driver_exit(); - gb_i2c_driver_exit(); gb_usb_driver_exit(); gb_sdio_driver_exit(); gb_uart_driver_exit(); diff --git a/drivers/staging/greybus/gpbridge.h b/drivers/staging/greybus/gpbridge.h index a346fa2..3f0340e 100644 --- a/drivers/staging/greybus/gpbridge.h +++ b/drivers/staging/greybus/gpbridge.h @@ -78,9 +78,6 @@ extern void gb_sdio_driver_exit(void); extern int gb_usb_driver_init(void); extern void gb_usb_driver_exit(void); -extern int gb_i2c_driver_init(void); -extern void gb_i2c_driver_exit(void); - extern int gb_spi_driver_init(void); extern void gb_spi_driver_exit(void); diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c index b49e8b4..69d6f07 100644 --- a/drivers/staging/greybus/i2c.c +++ b/drivers/staging/greybus/i2c.c @@ -321,6 +321,7 @@ static const struct gpbridge_device_id gb_i2c_id_table[] = { { GPBRIDGE_PROTOCOL(GREYBUS_PROTOCOL_I2C) }, { }, }; +MODULE_DEVICE_TABLE(gpbridge, gb_i2c_id_table); static struct gpbridge_driver i2c_driver = { .name = "i2c", @@ -328,4 +329,6 @@ static struct gpbridge_driver i2c_driver = { .remove = gb_i2c_remove, .id_table = gb_i2c_id_table, }; -gb_gpbridge_builtin_driver(i2c_driver); + +module_gpbridge_driver(i2c_driver); +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From dca8060db87bd851d77a64ef70b822ce3a82b3b5 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 9 May 2016 18:15:08 +0530 Subject: greybus: pwm: Create separate module Create separate module for pwm gpbridge driver. Tested on EVT 1.5 by inserting GP test module, all the devices were enumerated correctly. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index b9e4e96..2bd23b7 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -17,7 +17,6 @@ greybus-y := core.o \ gb-phy-y := gpbridge.o \ sdio.o \ uart.o \ - pwm.o \ spi.o \ usb.o @@ -38,6 +37,7 @@ gb-audio-manager-y += audio_manager.o gb-audio-manager-y += audio_manager_module.o gb-camera-y := camera.o gb-firmware-y := fw-core.o fw-download.o +gb-pwm-y := pwm.o gb-gpio-y := gpio.o gb-i2c-y := i2c.o @@ -62,6 +62,7 @@ obj-m += gb-audio-gb.o obj-m += gb-audio-apbridgea.o obj-m += gb-audio-manager.o obj-m += gb-firmware.o +obj-m += gb-pwm.o obj-m += gb-gpio.o obj-m += gb-i2c.o diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c index 92838d5..ecff3b1 100644 --- a/drivers/staging/greybus/gpbridge.c +++ b/drivers/staging/greybus/gpbridge.c @@ -317,10 +317,6 @@ static int __init gpbridge_init(void) goto error_gpbridge; } - if (gb_pwm_driver_init()) { - pr_err("error initializing pwm driver\n"); - goto error_pwm; - } if (gb_uart_driver_init()) { pr_err("error initializing uart driver\n"); goto error_uart; @@ -347,8 +343,6 @@ error_usb: error_sdio: gb_uart_driver_exit(); error_uart: - gb_pwm_driver_exit(); -error_pwm: greybus_deregister(&gb_gpbridge_driver); error_gpbridge: bus_unregister(&gpbridge_bus_type); @@ -363,7 +357,6 @@ static void __exit gpbridge_exit(void) gb_usb_driver_exit(); gb_sdio_driver_exit(); gb_uart_driver_exit(); - gb_pwm_driver_exit(); greybus_deregister(&gb_gpbridge_driver); bus_unregister(&gpbridge_bus_type); diff --git a/drivers/staging/greybus/gpbridge.h b/drivers/staging/greybus/gpbridge.h index 3f0340e..fe254bd 100644 --- a/drivers/staging/greybus/gpbridge.h +++ b/drivers/staging/greybus/gpbridge.h @@ -66,9 +66,6 @@ void gb_##__driver##_exit(void) \ gb_gpbridge_deregister(&__driver); \ } -extern int gb_pwm_driver_init(void); -extern void gb_pwm_driver_exit(void); - extern int gb_uart_driver_init(void); extern void gb_uart_driver_exit(void); diff --git a/drivers/staging/greybus/pwm.c b/drivers/staging/greybus/pwm.c index b11e77d..1c4ffb9 100644 --- a/drivers/staging/greybus/pwm.c +++ b/drivers/staging/greybus/pwm.c @@ -256,6 +256,7 @@ static const struct gpbridge_device_id gb_pwm_id_table[] = { { GPBRIDGE_PROTOCOL(GREYBUS_PROTOCOL_PWM) }, { }, }; +MODULE_DEVICE_TABLE(gpbridge, gb_pwm_id_table); static struct gpbridge_driver pwm_driver = { .name = "pwm", @@ -263,4 +264,6 @@ static struct gpbridge_driver pwm_driver = { .remove = gb_pwm_remove, .id_table = gb_pwm_id_table, }; -gb_gpbridge_builtin_driver(pwm_driver); + +module_gpbridge_driver(pwm_driver); +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 3d64730e119480062ffd2d94c49532fbf3dbb217 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 9 May 2016 18:15:09 +0530 Subject: greybus: sdio: Create separate module Create separate module for sdio gpbridge driver. Tested on EVT 1.5 by inserting GP test module, all the devices were enumerated correctly. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 2bd23b7..bffb1bd 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -15,7 +15,6 @@ greybus-y := core.o \ legacy.o gb-phy-y := gpbridge.o \ - sdio.o \ uart.o \ spi.o \ usb.o @@ -37,6 +36,7 @@ gb-audio-manager-y += audio_manager.o gb-audio-manager-y += audio_manager_module.o gb-camera-y := camera.o gb-firmware-y := fw-core.o fw-download.o +gb-sdio-y := sdio.o gb-pwm-y := pwm.o gb-gpio-y := gpio.o gb-i2c-y := i2c.o @@ -62,6 +62,7 @@ obj-m += gb-audio-gb.o obj-m += gb-audio-apbridgea.o obj-m += gb-audio-manager.o obj-m += gb-firmware.o +obj-m += gb-sdio.o obj-m += gb-pwm.o obj-m += gb-gpio.o obj-m += gb-i2c.o diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c index ecff3b1..d5ccdc4 100644 --- a/drivers/staging/greybus/gpbridge.c +++ b/drivers/staging/greybus/gpbridge.c @@ -321,10 +321,6 @@ static int __init gpbridge_init(void) pr_err("error initializing uart driver\n"); goto error_uart; } - if (gb_sdio_driver_init()) { - pr_err("error initializing sdio driver\n"); - goto error_sdio; - } if (gb_usb_driver_init()) { pr_err("error initializing usb driver\n"); goto error_usb; @@ -339,8 +335,6 @@ static int __init gpbridge_init(void) error_spi: gb_usb_driver_exit(); error_usb: - gb_sdio_driver_exit(); -error_sdio: gb_uart_driver_exit(); error_uart: greybus_deregister(&gb_gpbridge_driver); @@ -355,7 +349,6 @@ static void __exit gpbridge_exit(void) { gb_spi_driver_exit(); gb_usb_driver_exit(); - gb_sdio_driver_exit(); gb_uart_driver_exit(); greybus_deregister(&gb_gpbridge_driver); diff --git a/drivers/staging/greybus/gpbridge.h b/drivers/staging/greybus/gpbridge.h index fe254bd..44d4781 100644 --- a/drivers/staging/greybus/gpbridge.h +++ b/drivers/staging/greybus/gpbridge.h @@ -69,9 +69,6 @@ void gb_##__driver##_exit(void) \ extern int gb_uart_driver_init(void); extern void gb_uart_driver_exit(void); -extern int gb_sdio_driver_init(void); -extern void gb_sdio_driver_exit(void); - extern int gb_usb_driver_init(void); extern void gb_usb_driver_exit(void); diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index 8ee4d4c..7f063b4 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -827,6 +827,7 @@ static const struct gpbridge_device_id gb_sdio_id_table[] = { { GPBRIDGE_PROTOCOL(GREYBUS_PROTOCOL_SDIO) }, { }, }; +MODULE_DEVICE_TABLE(gpbridge, gb_sdio_id_table); static struct gpbridge_driver sdio_driver = { .name = "sdio", @@ -834,4 +835,6 @@ static struct gpbridge_driver sdio_driver = { .remove = gb_sdio_remove, .id_table = gb_sdio_id_table, }; -gb_gpbridge_builtin_driver(sdio_driver); + +module_gpbridge_driver(sdio_driver); +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From bebc013bafed3cc42eada99da0a924e46b0cd0c3 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 9 May 2016 18:15:10 +0530 Subject: greybus: spi: Create separate module Create separate module for spi gpbridge driver. Tested on EVT 1.5 by inserting GP test module, all the devices were enumerated correctly. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index bffb1bd..61d4ca9 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -16,7 +16,6 @@ greybus-y := core.o \ gb-phy-y := gpbridge.o \ uart.o \ - spi.o \ usb.o # Prefix all modules with gb- @@ -36,6 +35,7 @@ gb-audio-manager-y += audio_manager.o gb-audio-manager-y += audio_manager_module.o gb-camera-y := camera.o gb-firmware-y := fw-core.o fw-download.o +gb-spi-y := spi.o gb-sdio-y := sdio.o gb-pwm-y := pwm.o gb-gpio-y := gpio.o @@ -62,6 +62,7 @@ obj-m += gb-audio-gb.o obj-m += gb-audio-apbridgea.o obj-m += gb-audio-manager.o obj-m += gb-firmware.o +obj-m += gb-spi.o obj-m += gb-sdio.o obj-m += gb-pwm.o obj-m += gb-gpio.o diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c index d5ccdc4..2425df7 100644 --- a/drivers/staging/greybus/gpbridge.c +++ b/drivers/staging/greybus/gpbridge.c @@ -325,15 +325,9 @@ static int __init gpbridge_init(void) pr_err("error initializing usb driver\n"); goto error_usb; } - if (gb_spi_driver_init()) { - pr_err("error initializing spi driver\n"); - goto error_spi; - } return 0; -error_spi: - gb_usb_driver_exit(); error_usb: gb_uart_driver_exit(); error_uart: @@ -347,7 +341,6 @@ module_init(gpbridge_init); static void __exit gpbridge_exit(void) { - gb_spi_driver_exit(); gb_usb_driver_exit(); gb_uart_driver_exit(); diff --git a/drivers/staging/greybus/gpbridge.h b/drivers/staging/greybus/gpbridge.h index 44d4781..4fff2a6 100644 --- a/drivers/staging/greybus/gpbridge.h +++ b/drivers/staging/greybus/gpbridge.h @@ -72,9 +72,6 @@ extern void gb_uart_driver_exit(void); extern int gb_usb_driver_init(void); extern void gb_usb_driver_exit(void); -extern int gb_spi_driver_init(void); -extern void gb_spi_driver_exit(void); - /** * module_gpbridge_driver() - Helper macro for registering a gpbridge driver * @__gpbridge_driver: gpbridge_driver structure diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index dc811b1..6cf18d1 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -550,6 +550,7 @@ static const struct gpbridge_device_id gb_spi_id_table[] = { { GPBRIDGE_PROTOCOL(GREYBUS_PROTOCOL_SPI) }, { }, }; +MODULE_DEVICE_TABLE(gpbridge, gb_spi_id_table); static struct gpbridge_driver spi_driver = { .name = "spi", @@ -557,4 +558,6 @@ static struct gpbridge_driver spi_driver = { .remove = gb_spi_remove, .id_table = gb_spi_id_table, }; -gb_gpbridge_builtin_driver(spi_driver); + +module_gpbridge_driver(spi_driver); +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 66b9e09e28b0c32d9b071fc9084bbb8880b88d74 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 9 May 2016 18:15:11 +0530 Subject: greybus: uart: Create separate module Create separate module for uart gpbridge driver. Tested on EVT 1.5 by inserting GP test module, all the devices were enumerated correctly. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 61d4ca9..e99a9a8 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -15,7 +15,6 @@ greybus-y := core.o \ legacy.o gb-phy-y := gpbridge.o \ - uart.o \ usb.o # Prefix all modules with gb- @@ -37,6 +36,7 @@ gb-camera-y := camera.o gb-firmware-y := fw-core.o fw-download.o gb-spi-y := spi.o gb-sdio-y := sdio.o +gb-uart-y := uart.o gb-pwm-y := pwm.o gb-gpio-y := gpio.o gb-i2c-y := i2c.o @@ -64,6 +64,7 @@ obj-m += gb-audio-manager.o obj-m += gb-firmware.o obj-m += gb-spi.o obj-m += gb-sdio.o +obj-m += gb-uart.o obj-m += gb-pwm.o obj-m += gb-gpio.o obj-m += gb-i2c.o diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c index 2425df7..5a65564 100644 --- a/drivers/staging/greybus/gpbridge.c +++ b/drivers/staging/greybus/gpbridge.c @@ -317,10 +317,6 @@ static int __init gpbridge_init(void) goto error_gpbridge; } - if (gb_uart_driver_init()) { - pr_err("error initializing uart driver\n"); - goto error_uart; - } if (gb_usb_driver_init()) { pr_err("error initializing usb driver\n"); goto error_usb; @@ -329,8 +325,6 @@ static int __init gpbridge_init(void) return 0; error_usb: - gb_uart_driver_exit(); -error_uart: greybus_deregister(&gb_gpbridge_driver); error_gpbridge: bus_unregister(&gpbridge_bus_type); @@ -342,7 +336,6 @@ module_init(gpbridge_init); static void __exit gpbridge_exit(void) { gb_usb_driver_exit(); - gb_uart_driver_exit(); greybus_deregister(&gb_gpbridge_driver); bus_unregister(&gpbridge_bus_type); diff --git a/drivers/staging/greybus/gpbridge.h b/drivers/staging/greybus/gpbridge.h index 4fff2a6..532dd56 100644 --- a/drivers/staging/greybus/gpbridge.h +++ b/drivers/staging/greybus/gpbridge.h @@ -66,9 +66,6 @@ void gb_##__driver##_exit(void) \ gb_gpbridge_deregister(&__driver); \ } -extern int gb_uart_driver_init(void); -extern void gb_uart_driver_exit(void); - extern int gb_usb_driver_init(void); extern void gb_usb_driver_exit(void); diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 0d8fcb5..aa28ce5 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -804,6 +804,7 @@ static const struct gpbridge_device_id gb_uart_id_table[] = { { GPBRIDGE_PROTOCOL(GREYBUS_PROTOCOL_UART) }, { }, }; +MODULE_DEVICE_TABLE(gpbridge, gb_uart_id_table); static struct gpbridge_driver uart_driver = { .name = "uart", @@ -812,7 +813,7 @@ static struct gpbridge_driver uart_driver = { .id_table = gb_uart_id_table, }; -int gb_uart_driver_init(void) +static int gb_uart_driver_init(void) { int ret; @@ -828,9 +829,13 @@ int gb_uart_driver_init(void) return 0; } +module_init(gb_uart_driver_init); -void gb_uart_driver_exit(void) +static void gb_uart_driver_exit(void) { gb_gpbridge_deregister(&uart_driver); gb_tty_exit(); } + +module_exit(gb_uart_driver_exit); +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From ea7c47771ba13e143b3c328af8e03a1c45045cf0 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 9 May 2016 18:15:12 +0530 Subject: greybus: usb: Create separate module Create separate module for usb gpbridge driver. Tested on EVT 1.5 by inserting GP test module, all the devices were enumerated correctly. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index e99a9a8..592525c 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -14,8 +14,7 @@ greybus-y := core.o \ operation.o \ legacy.o -gb-phy-y := gpbridge.o \ - usb.o +gb-phy-y := gpbridge.o # Prefix all modules with gb- gb-vibrator-y := vibrator.o @@ -40,6 +39,7 @@ gb-uart-y := uart.o gb-pwm-y := pwm.o gb-gpio-y := gpio.o gb-i2c-y := i2c.o +gb-usb-y := usb.o obj-m += greybus.o obj-m += gb-phy.o @@ -68,6 +68,7 @@ obj-m += gb-uart.o obj-m += gb-pwm.o obj-m += gb-gpio.o obj-m += gb-i2c.o +obj-m += gb-usb.o KERNELVER ?= $(shell uname -r) KERNELDIR ?= /lib/modules/$(KERNELVER)/build diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c index 5a65564..67f18ac 100644 --- a/drivers/staging/greybus/gpbridge.c +++ b/drivers/staging/greybus/gpbridge.c @@ -317,15 +317,8 @@ static int __init gpbridge_init(void) goto error_gpbridge; } - if (gb_usb_driver_init()) { - pr_err("error initializing usb driver\n"); - goto error_usb; - } - return 0; -error_usb: - greybus_deregister(&gb_gpbridge_driver); error_gpbridge: bus_unregister(&gpbridge_bus_type); ida_destroy(&gpbridge_id); @@ -335,8 +328,6 @@ module_init(gpbridge_init); static void __exit gpbridge_exit(void) { - gb_usb_driver_exit(); - greybus_deregister(&gb_gpbridge_driver); bus_unregister(&gpbridge_bus_type); ida_destroy(&gpbridge_id); diff --git a/drivers/staging/greybus/gpbridge.h b/drivers/staging/greybus/gpbridge.h index 532dd56..d4339e6 100644 --- a/drivers/staging/greybus/gpbridge.h +++ b/drivers/staging/greybus/gpbridge.h @@ -66,9 +66,6 @@ void gb_##__driver##_exit(void) \ gb_gpbridge_deregister(&__driver); \ } -extern int gb_usb_driver_init(void); -extern void gb_usb_driver_exit(void); - /** * module_gpbridge_driver() - Helper macro for registering a gpbridge driver * @__gpbridge_driver: gpbridge_driver structure diff --git a/drivers/staging/greybus/usb.c b/drivers/staging/greybus/usb.c index 2b4789b..2f68a1b 100644 --- a/drivers/staging/greybus/usb.c +++ b/drivers/staging/greybus/usb.c @@ -242,6 +242,7 @@ static const struct gpbridge_device_id gb_usb_id_table[] = { { GPBRIDGE_PROTOCOL(GREYBUS_PROTOCOL_USB) }, { }, }; +MODULE_DEVICE_TABLE(gpbridge, gb_usb_id_table); static struct gpbridge_driver usb_driver = { .name = "usb", @@ -249,4 +250,6 @@ static struct gpbridge_driver usb_driver = { .remove = gb_usb_remove, .id_table = gb_usb_id_table, }; -gb_gpbridge_builtin_driver(usb_driver); + +module_gpbridge_driver(usb_driver); +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From a4b9a098f27a653884d259ad4ca3500d4ad3107f Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 9 May 2016 18:15:13 +0530 Subject: greybus: gpbridge: Rename gb-phy.ko module Rename gb-phy.ko module as gb-gpbridge.ko. Tested on EVT 1.5 by inserting GP test module, all the devices were enumerated correctly. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 592525c..2680f7e 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -14,7 +14,7 @@ greybus-y := core.o \ operation.o \ legacy.o -gb-phy-y := gpbridge.o +gb-gpbridge-y := gpbridge.o # Prefix all modules with gb- gb-vibrator-y := vibrator.o @@ -42,7 +42,7 @@ gb-i2c-y := i2c.o gb-usb-y := usb.o obj-m += greybus.o -obj-m += gb-phy.o +obj-m += gb-gpbridge.o obj-m += gb-vibrator.o obj-m += gb-power-supply.o obj-m += gb-loopback.o -- cgit v0.10.2 From b9662266aa2694936836bace57a90f908a0b7e24 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 9 May 2016 18:15:14 +0530 Subject: greybus: gpbridge: Remove (now) unused macro gb_gpbridge_builtin_driver() gb_gpbridge_builtin_driver() isn't used anymore, remove it. Tested on EVT 1.5 by inserting GP test module, all the devices were enumerated correctly. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/gpbridge.h b/drivers/staging/greybus/gpbridge.h index d4339e6..0cee2eb 100644 --- a/drivers/staging/greybus/gpbridge.h +++ b/drivers/staging/greybus/gpbridge.h @@ -56,16 +56,6 @@ void gb_gpbridge_deregister_driver(struct gpbridge_driver *driver); #define gb_gpbridge_deregister(driver) \ gb_gpbridge_deregister_driver(driver) -#define gb_gpbridge_builtin_driver(__driver) \ - int __init gb_##__driver##_init(void) \ -{ \ - return gb_gpbridge_register(&__driver); \ -} \ -void gb_##__driver##_exit(void) \ -{ \ - gb_gpbridge_deregister(&__driver); \ -} - /** * module_gpbridge_driver() - Helper macro for registering a gpbridge driver * @__gpbridge_driver: gpbridge_driver structure -- cgit v0.10.2 From dc0754088e53e42fee1f880bc0c2002f624fe26f Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Tue, 10 May 2016 08:50:13 +0530 Subject: greybus: Remove bridge PHY protocol specific classes These protocols are managed under the bridged PHY class and doesn't need protocol specific classes anymore. Remove their entries from gb_gpbridge_id_table array and remove the now unused macro's and mark their values as unused. Tested on EVT 1.5 with generic-test module. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Acked-by: Sandeep Patil <sspatil@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c index 67f18ac..f082658 100644 --- a/drivers/staging/greybus/gpbridge.c +++ b/drivers/staging/greybus/gpbridge.c @@ -283,13 +283,6 @@ static int gb_gpbridge_probe(struct gb_bundle *bundle, static const struct greybus_bundle_id gb_gpbridge_id_table[] = { { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_BRIDGED_PHY) }, - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_GPIO) }, - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_I2C) }, - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_PWM) }, - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SDIO) }, - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SPI) }, - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_UART) }, - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_USB) }, { }, }; MODULE_DEVICE_TABLE(greybus, gb_gpbridge_id_table); diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 5d00f7d..4f70190 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -55,16 +55,16 @@ enum greybus_protocol { enum greybus_class_type { GREYBUS_CLASS_CONTROL = 0x00, /* 0x01 is unused */ - GREYBUS_CLASS_GPIO = 0x02, - GREYBUS_CLASS_I2C = 0x03, - GREYBUS_CLASS_UART = 0x04, + /* 0x02 is unused */ + /* 0x03 is unused */ + /* 0x04 is unused */ GREYBUS_CLASS_HID = 0x05, - GREYBUS_CLASS_USB = 0x06, - GREYBUS_CLASS_SDIO = 0x07, + /* 0x06 is unused */ + /* 0x07 is unused */ GREYBUS_CLASS_POWER_SUPPLY = 0x08, - GREYBUS_CLASS_PWM = 0x09, + /* 0x09 is unused */ GREYBUS_CLASS_BRIDGED_PHY = 0x0a, - GREYBUS_CLASS_SPI = 0x0b, + /* 0x0b is unused */ GREYBUS_CLASS_DISPLAY = 0x0c, GREYBUS_CLASS_CAMERA = 0x0d, GREYBUS_CLASS_SENSOR = 0x0e, -- cgit v0.10.2 From 4c412921c78732f8f803a5906c97746ede5cf77c Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Sat, 14 May 2016 23:42:19 +0530 Subject: greybus: spi: Restructure spi.c to share it with other bundle drivers This patch restructures spi.c as spilib core, so that the same logic can be reused for SPI connections implemented as part of different bundle types. This is required for Firmware Management Bundle. Note that the 'struct gb_protocol' and its callback aren't moved to a separate file in this commit to make its reviews easier. That will be done by a following patch. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Rui Miguel Silva <rui.silva@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 2680f7e..a9802da 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -33,7 +33,7 @@ gb-audio-manager-y += audio_manager.o gb-audio-manager-y += audio_manager_module.o gb-camera-y := camera.o gb-firmware-y := fw-core.o fw-download.o -gb-spi-y := spi.o +gb-spilib-y := spilib.o gb-sdio-y := sdio.o gb-uart-y := uart.o gb-pwm-y := pwm.o @@ -62,7 +62,7 @@ obj-m += gb-audio-gb.o obj-m += gb-audio-apbridgea.o obj-m += gb-audio-manager.o obj-m += gb-firmware.o -obj-m += gb-spi.o +obj-m += gb-spilib.o obj-m += gb-sdio.o obj-m += gb-uart.o obj-m += gb-pwm.o diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c deleted file mode 100644 index 6cf18d1..0000000 --- a/drivers/staging/greybus/spi.c +++ /dev/null @@ -1,563 +0,0 @@ -/* - * SPI bridge driver for the Greybus "generic" SPI module. - * - * Copyright 2014-2015 Google Inc. - * Copyright 2014-2015 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#include <linux/bitops.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/spi/spi.h> - -#include "greybus.h" -#include "gpbridge.h" - -struct gb_spi { - struct gb_connection *connection; - struct gpbridge_device *gpbdev; - struct spi_transfer *first_xfer; - struct spi_transfer *last_xfer; - u32 rx_xfer_offset; - u32 tx_xfer_offset; - u32 last_xfer_size; - unsigned int op_timeout; - u16 mode; - u16 flags; - u32 bits_per_word_mask; - u8 num_chipselect; - u32 min_speed_hz; - u32 max_speed_hz; -}; - -#define GB_SPI_STATE_MSG_DONE ((void *)0) -#define GB_SPI_STATE_MSG_IDLE ((void *)1) -#define GB_SPI_STATE_MSG_RUNNING ((void *)2) -#define GB_SPI_STATE_OP_READY ((void *)3) -#define GB_SPI_STATE_OP_DONE ((void *)4) -#define GB_SPI_STATE_MSG_ERROR ((void *)-1) - -#define XFER_TIMEOUT_TOLERANCE 200 - -static struct spi_master *get_master_from_spi(struct gb_spi *spi) -{ - return gb_connection_get_data(spi->connection); -} - -static int tx_header_fit_operation(u32 tx_size, u32 count, size_t data_max) -{ - size_t headers_size; - - data_max -= sizeof(struct gb_spi_transfer_request); - headers_size = (count + 1) * sizeof(struct gb_spi_transfer); - - return tx_size + headers_size > data_max ? 0 : 1; -} - -static size_t calc_rx_xfer_size(u32 rx_size, u32 *tx_xfer_size, u32 len, - size_t data_max) -{ - size_t rx_xfer_size; - - data_max -= sizeof(struct gb_spi_transfer_response); - - if (rx_size + len > data_max) - rx_xfer_size = data_max - rx_size; - else - rx_xfer_size = len; - - /* if this is a write_read, for symmetry read the same as write */ - if (*tx_xfer_size && rx_xfer_size > *tx_xfer_size) - rx_xfer_size = *tx_xfer_size; - if (*tx_xfer_size && rx_xfer_size < *tx_xfer_size) - *tx_xfer_size = rx_xfer_size; - - return rx_xfer_size; -} - -static size_t calc_tx_xfer_size(u32 tx_size, u32 count, size_t len, - size_t data_max) -{ - size_t headers_size; - - data_max -= sizeof(struct gb_spi_transfer_request); - headers_size = (count + 1) * sizeof(struct gb_spi_transfer); - - if (tx_size + headers_size + len > data_max) - return data_max - (tx_size + sizeof(struct gb_spi_transfer)); - - return len; -} - -static void clean_xfer_state(struct gb_spi *spi) -{ - spi->first_xfer = NULL; - spi->last_xfer = NULL; - spi->rx_xfer_offset = 0; - spi->tx_xfer_offset = 0; - spi->last_xfer_size = 0; - spi->op_timeout = 0; -} - -static int setup_next_xfer(struct gb_spi *spi, struct spi_message *msg) -{ - struct spi_transfer *last_xfer = spi->last_xfer; - - if (msg->state != GB_SPI_STATE_OP_DONE) - return 0; - - /* - * if we transferred all content of the last transfer, reset values and - * check if this was the last transfer in the message - */ - if ((spi->tx_xfer_offset + spi->last_xfer_size == last_xfer->len) || - (spi->rx_xfer_offset + spi->last_xfer_size == last_xfer->len)) { - spi->tx_xfer_offset = 0; - spi->rx_xfer_offset = 0; - spi->op_timeout = 0; - if (last_xfer == list_last_entry(&msg->transfers, - struct spi_transfer, - transfer_list)) - msg->state = GB_SPI_STATE_MSG_DONE; - else - spi->first_xfer = list_next_entry(last_xfer, - transfer_list); - return 0; - } - - spi->first_xfer = last_xfer; - if (last_xfer->tx_buf) - spi->tx_xfer_offset += spi->last_xfer_size; - - if (last_xfer->rx_buf) - spi->rx_xfer_offset += spi->last_xfer_size; - - return 0; -} - -static struct spi_transfer *get_next_xfer(struct spi_transfer *xfer, - struct spi_message *msg) -{ - if (xfer == list_last_entry(&msg->transfers, struct spi_transfer, - transfer_list)) - return NULL; - - return list_next_entry(xfer, transfer_list); -} - -/* Routines to transfer data */ -static struct gb_operation * -gb_spi_operation_create(struct gb_spi *spi, struct gb_connection *connection, - struct spi_message *msg) -{ - struct gb_spi_transfer_request *request; - struct spi_device *dev = msg->spi; - struct spi_transfer *xfer; - struct gb_spi_transfer *gb_xfer; - struct gb_operation *operation; - u32 tx_size = 0, rx_size = 0, count = 0, xfer_len = 0, request_size; - u32 tx_xfer_size = 0, rx_xfer_size = 0, len; - u32 total_len = 0; - unsigned int xfer_timeout; - size_t data_max; - void *tx_data; - - data_max = gb_operation_get_payload_size_max(connection); - xfer = spi->first_xfer; - - /* Find number of transfers queued and tx/rx length in the message */ - - while (msg->state != GB_SPI_STATE_OP_READY) { - msg->state = GB_SPI_STATE_MSG_RUNNING; - spi->last_xfer = xfer; - - if (!xfer->tx_buf && !xfer->rx_buf) { - dev_err(&spi->gpbdev->dev, - "bufferless transfer, length %u\n", xfer->len); - msg->state = GB_SPI_STATE_MSG_ERROR; - return NULL; - } - - tx_xfer_size = 0; - rx_xfer_size = 0; - - if (xfer->tx_buf) { - len = xfer->len - spi->tx_xfer_offset; - if (!tx_header_fit_operation(tx_size, count, data_max)) - break; - tx_xfer_size = calc_tx_xfer_size(tx_size, count, - len, data_max); - spi->last_xfer_size = tx_xfer_size; - } - - if (xfer->rx_buf) { - len = xfer->len - spi->rx_xfer_offset; - rx_xfer_size = calc_rx_xfer_size(rx_size, &tx_xfer_size, - len, data_max); - spi->last_xfer_size = rx_xfer_size; - } - - tx_size += tx_xfer_size; - rx_size += rx_xfer_size; - - total_len += spi->last_xfer_size; - count++; - - xfer = get_next_xfer(xfer, msg); - if (!xfer || total_len >= data_max) - msg->state = GB_SPI_STATE_OP_READY; - } - - /* - * In addition to space for all message descriptors we need - * to have enough to hold all tx data. - */ - request_size = sizeof(*request); - request_size += count * sizeof(*gb_xfer); - request_size += tx_size; - - /* Response consists only of incoming data */ - operation = gb_operation_create(connection, GB_SPI_TYPE_TRANSFER, - request_size, rx_size, GFP_KERNEL); - if (!operation) - return NULL; - - request = operation->request->payload; - request->count = cpu_to_le16(count); - request->mode = dev->mode; - request->chip_select = dev->chip_select; - - gb_xfer = &request->transfers[0]; - tx_data = gb_xfer + count; /* place tx data after last gb_xfer */ - - /* Fill in the transfers array */ - xfer = spi->first_xfer; - while (msg->state != GB_SPI_STATE_OP_DONE) { - if (xfer == spi->last_xfer) - xfer_len = spi->last_xfer_size; - else - xfer_len = xfer->len; - - /* make sure we do not timeout in a slow transfer */ - xfer_timeout = xfer_len * 8 * MSEC_PER_SEC / xfer->speed_hz; - xfer_timeout += GB_OPERATION_TIMEOUT_DEFAULT; - - if (xfer_timeout > spi->op_timeout) - spi->op_timeout = xfer_timeout; - - gb_xfer->speed_hz = cpu_to_le32(xfer->speed_hz); - gb_xfer->len = cpu_to_le32(xfer_len); - gb_xfer->delay_usecs = cpu_to_le16(xfer->delay_usecs); - gb_xfer->cs_change = xfer->cs_change; - gb_xfer->bits_per_word = xfer->bits_per_word; - - /* Copy tx data */ - if (xfer->tx_buf) { - gb_xfer->rdwr |= GB_SPI_XFER_WRITE; - memcpy(tx_data, xfer->tx_buf + spi->tx_xfer_offset, - xfer_len); - tx_data += xfer_len; - } - - if (xfer->rx_buf) - gb_xfer->rdwr |= GB_SPI_XFER_READ; - - if (xfer == spi->last_xfer) { - msg->state = GB_SPI_STATE_OP_DONE; - continue; - } - - gb_xfer++; - xfer = get_next_xfer(xfer, msg); - } - - msg->actual_length += total_len; - - return operation; -} - -static void gb_spi_decode_response(struct gb_spi *spi, struct spi_message *msg, - struct gb_spi_transfer_response *response) -{ - struct spi_transfer *xfer = spi->first_xfer; - void *rx_data = response->data; - u32 xfer_len; - - while (xfer) { - /* Copy rx data */ - if (xfer->rx_buf) { - if (xfer == spi->first_xfer) - xfer_len = xfer->len - spi->rx_xfer_offset; - else if (xfer == spi->last_xfer) - xfer_len = spi->last_xfer_size; - else - xfer_len = xfer->len; - - memcpy(xfer->rx_buf + spi->rx_xfer_offset, rx_data, - xfer_len); - rx_data += xfer_len; - } - - if (xfer == spi->last_xfer) - break; - - xfer = list_next_entry(xfer, transfer_list); - } -} - -static int gb_spi_transfer_one_message(struct spi_master *master, - struct spi_message *msg) -{ - struct gb_spi *spi = spi_master_get_devdata(master); - struct gb_connection *connection = spi->connection; - struct gb_spi_transfer_response *response; - struct gb_operation *operation; - int ret = 0; - - spi->first_xfer = list_first_entry_or_null(&msg->transfers, - struct spi_transfer, - transfer_list); - if (!spi->first_xfer) { - ret = -ENOMEM; - goto out; - } - - msg->state = GB_SPI_STATE_MSG_IDLE; - - while (msg->state != GB_SPI_STATE_MSG_DONE && - msg->state != GB_SPI_STATE_MSG_ERROR) { - operation = gb_spi_operation_create(spi, connection, msg); - if (!operation) { - msg->state = GB_SPI_STATE_MSG_ERROR; - ret = -EINVAL; - continue; - } - - ret = gb_operation_request_send_sync_timeout(operation, - spi->op_timeout); - if (!ret) { - response = operation->response->payload; - if (response) - gb_spi_decode_response(spi, msg, response); - } else { - dev_err(&spi->gpbdev->dev, - "transfer operation failed: %d\n", ret); - msg->state = GB_SPI_STATE_MSG_ERROR; - } - - gb_operation_put(operation); - setup_next_xfer(spi, msg); - } - -out: - msg->status = ret; - clean_xfer_state(spi); - spi_finalize_current_message(master); - - return ret; -} - -static int gb_spi_setup(struct spi_device *spi) -{ - /* Nothing to do for now */ - return 0; -} - -static void gb_spi_cleanup(struct spi_device *spi) -{ - /* Nothing to do for now */ -} - - -/* Routines to get controller information */ - -/* - * Map Greybus spi mode bits/flags/bpw into Linux ones. - * All bits are same for now and so these macro's return same values. - */ -#define gb_spi_mode_map(mode) mode -#define gb_spi_flags_map(flags) flags - -static int gb_spi_get_master_config(struct gb_spi *spi) -{ - struct gb_spi_master_config_response response; - u16 mode, flags; - int ret; - - ret = gb_operation_sync(spi->connection, GB_SPI_TYPE_MASTER_CONFIG, - NULL, 0, &response, sizeof(response)); - if (ret < 0) - return ret; - - mode = le16_to_cpu(response.mode); - spi->mode = gb_spi_mode_map(mode); - - flags = le16_to_cpu(response.flags); - spi->flags = gb_spi_flags_map(flags); - - spi->bits_per_word_mask = le32_to_cpu(response.bits_per_word_mask); - spi->num_chipselect = response.num_chipselect; - - spi->min_speed_hz = le32_to_cpu(response.min_speed_hz); - spi->max_speed_hz = le32_to_cpu(response.max_speed_hz); - - return 0; -} - -static int gb_spi_setup_device(struct gb_spi *spi, u8 cs) -{ - struct spi_master *master = get_master_from_spi(spi); - struct gb_spi_device_config_request request; - struct gb_spi_device_config_response response; - struct spi_board_info spi_board = { {0} }; - struct spi_device *spidev; - int ret; - u8 dev_type; - - request.chip_select = cs; - - ret = gb_operation_sync(spi->connection, GB_SPI_TYPE_DEVICE_CONFIG, - &request, sizeof(request), - &response, sizeof(response)); - if (ret < 0) - return ret; - - dev_type = response.device_type; - - if (dev_type == GB_SPI_SPI_DEV) - strlcpy(spi_board.modalias, SPI_DEV_MODALIAS, - sizeof(spi_board.modalias)); - else if (dev_type == GB_SPI_SPI_NOR) - strlcpy(spi_board.modalias, SPI_NOR_MODALIAS, - sizeof(spi_board.modalias)); - else if (dev_type == GB_SPI_SPI_MODALIAS) - memcpy(spi_board.modalias, response.name, - sizeof(spi_board.modalias)); - else - return -EINVAL; - - spi_board.mode = le16_to_cpu(response.mode); - spi_board.bus_num = master->bus_num; - spi_board.chip_select = cs; - spi_board.max_speed_hz = le32_to_cpu(response.max_speed_hz); - - spidev = spi_new_device(master, &spi_board); - if (!spidev) - return -EINVAL; - - return 0; -} - -static int gb_spi_probe(struct gpbridge_device *gpbdev, - const struct gpbridge_device_id *id) -{ - struct gb_connection *connection; - struct gb_spi *spi; - struct spi_master *master; - int ret; - u8 i; - - /* Allocate master with space for data */ - master = spi_alloc_master(&gpbdev->dev, sizeof(*spi)); - if (!master) { - dev_err(&gpbdev->dev, "cannot alloc SPI master\n"); - return -ENOMEM; - } - - connection = gb_connection_create(gpbdev->bundle, - le16_to_cpu(gpbdev->cport_desc->id), - NULL); - if (IS_ERR(connection)) { - ret = PTR_ERR(connection); - goto exit_spi_put; - } - - spi = spi_master_get_devdata(master); - spi->connection = connection; - gb_connection_set_data(connection, master); - spi->gpbdev = gpbdev; - gb_gpbridge_set_data(gpbdev, master); - - ret = gb_connection_enable(connection); - if (ret) - goto exit_connection_destroy; - - ret = gb_gpbridge_get_version(connection); - if (ret) - goto exit_connection_disable; - - /* get master configuration */ - ret = gb_spi_get_master_config(spi); - if (ret) - goto exit_connection_disable; - - master->bus_num = -1; /* Allow spi-core to allocate it dynamically */ - master->num_chipselect = spi->num_chipselect; - master->mode_bits = spi->mode; - master->flags = spi->flags; - master->bits_per_word_mask = spi->bits_per_word_mask; - - /* Attach methods */ - master->cleanup = gb_spi_cleanup; - master->setup = gb_spi_setup; - master->transfer_one_message = gb_spi_transfer_one_message; - - ret = spi_register_master(master); - if (ret < 0) - goto exit_connection_disable; - - /* now, fetch the devices configuration */ - for (i = 0; i < spi->num_chipselect; i++) { - ret = gb_spi_setup_device(spi, i); - if (ret < 0) { - dev_err(&gpbdev->dev, - "failed to allocate spi device %d: %d\n", - i, ret); - goto exit_spi_unregister; - } - } - - return ret; - -exit_spi_unregister: - spi_unregister_master(master); -exit_connection_disable: - gb_connection_disable(connection); -exit_connection_destroy: - gb_connection_destroy(connection); -exit_spi_put: - spi_master_put(master); - - return ret; -} - -static void gb_spi_remove(struct gpbridge_device *gpbdev) -{ - struct spi_master *master = gb_gpbridge_get_data(gpbdev); - struct gb_spi *spi = spi_master_get_devdata(master); - struct gb_connection *connection = spi->connection; - - spi_unregister_master(master); - gb_connection_disable(connection); - gb_connection_destroy(connection); - spi_master_put(master); -} - -static const struct gpbridge_device_id gb_spi_id_table[] = { - { GPBRIDGE_PROTOCOL(GREYBUS_PROTOCOL_SPI) }, - { }, -}; -MODULE_DEVICE_TABLE(gpbridge, gb_spi_id_table); - -static struct gpbridge_driver spi_driver = { - .name = "spi", - .probe = gb_spi_probe, - .remove = gb_spi_remove, - .id_table = gb_spi_id_table, -}; - -module_gpbridge_driver(spi_driver); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/spilib.c b/drivers/staging/greybus/spilib.c new file mode 100644 index 0000000..c7fe878 --- /dev/null +++ b/drivers/staging/greybus/spilib.c @@ -0,0 +1,583 @@ +/* + * Greybus SPI library + * + * Copyright 2014-2016 Google Inc. + * Copyright 2014-2016 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include <linux/bitops.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/spi/spi.h> + +#include "greybus.h" +#include "gpbridge.h" +#include "spilib.h" + +struct gb_spilib { + struct gb_connection *connection; + struct device *parent; + struct spi_transfer *first_xfer; + struct spi_transfer *last_xfer; + u32 rx_xfer_offset; + u32 tx_xfer_offset; + u32 last_xfer_size; + unsigned int op_timeout; + u16 mode; + u16 flags; + u32 bits_per_word_mask; + u8 num_chipselect; + u32 min_speed_hz; + u32 max_speed_hz; +}; + +#define GB_SPI_STATE_MSG_DONE ((void *)0) +#define GB_SPI_STATE_MSG_IDLE ((void *)1) +#define GB_SPI_STATE_MSG_RUNNING ((void *)2) +#define GB_SPI_STATE_OP_READY ((void *)3) +#define GB_SPI_STATE_OP_DONE ((void *)4) +#define GB_SPI_STATE_MSG_ERROR ((void *)-1) + +#define XFER_TIMEOUT_TOLERANCE 200 + +static struct spi_master *get_master_from_spi(struct gb_spilib *spi) +{ + return gb_connection_get_data(spi->connection); +} + +static int tx_header_fit_operation(u32 tx_size, u32 count, size_t data_max) +{ + size_t headers_size; + + data_max -= sizeof(struct gb_spi_transfer_request); + headers_size = (count + 1) * sizeof(struct gb_spi_transfer); + + return tx_size + headers_size > data_max ? 0 : 1; +} + +static size_t calc_rx_xfer_size(u32 rx_size, u32 *tx_xfer_size, u32 len, + size_t data_max) +{ + size_t rx_xfer_size; + + data_max -= sizeof(struct gb_spi_transfer_response); + + if (rx_size + len > data_max) + rx_xfer_size = data_max - rx_size; + else + rx_xfer_size = len; + + /* if this is a write_read, for symmetry read the same as write */ + if (*tx_xfer_size && rx_xfer_size > *tx_xfer_size) + rx_xfer_size = *tx_xfer_size; + if (*tx_xfer_size && rx_xfer_size < *tx_xfer_size) + *tx_xfer_size = rx_xfer_size; + + return rx_xfer_size; +} + +static size_t calc_tx_xfer_size(u32 tx_size, u32 count, size_t len, + size_t data_max) +{ + size_t headers_size; + + data_max -= sizeof(struct gb_spi_transfer_request); + headers_size = (count + 1) * sizeof(struct gb_spi_transfer); + + if (tx_size + headers_size + len > data_max) + return data_max - (tx_size + sizeof(struct gb_spi_transfer)); + + return len; +} + +static void clean_xfer_state(struct gb_spilib *spi) +{ + spi->first_xfer = NULL; + spi->last_xfer = NULL; + spi->rx_xfer_offset = 0; + spi->tx_xfer_offset = 0; + spi->last_xfer_size = 0; + spi->op_timeout = 0; +} + +static int setup_next_xfer(struct gb_spilib *spi, struct spi_message *msg) +{ + struct spi_transfer *last_xfer = spi->last_xfer; + + if (msg->state != GB_SPI_STATE_OP_DONE) + return 0; + + /* + * if we transferred all content of the last transfer, reset values and + * check if this was the last transfer in the message + */ + if ((spi->tx_xfer_offset + spi->last_xfer_size == last_xfer->len) || + (spi->rx_xfer_offset + spi->last_xfer_size == last_xfer->len)) { + spi->tx_xfer_offset = 0; + spi->rx_xfer_offset = 0; + spi->op_timeout = 0; + if (last_xfer == list_last_entry(&msg->transfers, + struct spi_transfer, + transfer_list)) + msg->state = GB_SPI_STATE_MSG_DONE; + else + spi->first_xfer = list_next_entry(last_xfer, + transfer_list); + return 0; + } + + spi->first_xfer = last_xfer; + if (last_xfer->tx_buf) + spi->tx_xfer_offset += spi->last_xfer_size; + + if (last_xfer->rx_buf) + spi->rx_xfer_offset += spi->last_xfer_size; + + return 0; +} + +static struct spi_transfer *get_next_xfer(struct spi_transfer *xfer, + struct spi_message *msg) +{ + if (xfer == list_last_entry(&msg->transfers, struct spi_transfer, + transfer_list)) + return NULL; + + return list_next_entry(xfer, transfer_list); +} + +/* Routines to transfer data */ +static struct gb_operation *gb_spi_operation_create(struct gb_spilib *spi, + struct gb_connection *connection, struct spi_message *msg) +{ + struct gb_spi_transfer_request *request; + struct spi_device *dev = msg->spi; + struct spi_transfer *xfer; + struct gb_spi_transfer *gb_xfer; + struct gb_operation *operation; + u32 tx_size = 0, rx_size = 0, count = 0, xfer_len = 0, request_size; + u32 tx_xfer_size = 0, rx_xfer_size = 0, len; + u32 total_len = 0; + unsigned int xfer_timeout; + size_t data_max; + void *tx_data; + + data_max = gb_operation_get_payload_size_max(connection); + xfer = spi->first_xfer; + + /* Find number of transfers queued and tx/rx length in the message */ + + while (msg->state != GB_SPI_STATE_OP_READY) { + msg->state = GB_SPI_STATE_MSG_RUNNING; + spi->last_xfer = xfer; + + if (!xfer->tx_buf && !xfer->rx_buf) { + dev_err(spi->parent, + "bufferless transfer, length %u\n", xfer->len); + msg->state = GB_SPI_STATE_MSG_ERROR; + return NULL; + } + + tx_xfer_size = 0; + rx_xfer_size = 0; + + if (xfer->tx_buf) { + len = xfer->len - spi->tx_xfer_offset; + if (!tx_header_fit_operation(tx_size, count, data_max)) + break; + tx_xfer_size = calc_tx_xfer_size(tx_size, count, + len, data_max); + spi->last_xfer_size = tx_xfer_size; + } + + if (xfer->rx_buf) { + len = xfer->len - spi->rx_xfer_offset; + rx_xfer_size = calc_rx_xfer_size(rx_size, &tx_xfer_size, + len, data_max); + spi->last_xfer_size = rx_xfer_size; + } + + tx_size += tx_xfer_size; + rx_size += rx_xfer_size; + + total_len += spi->last_xfer_size; + count++; + + xfer = get_next_xfer(xfer, msg); + if (!xfer || total_len >= data_max) + msg->state = GB_SPI_STATE_OP_READY; + } + + /* + * In addition to space for all message descriptors we need + * to have enough to hold all tx data. + */ + request_size = sizeof(*request); + request_size += count * sizeof(*gb_xfer); + request_size += tx_size; + + /* Response consists only of incoming data */ + operation = gb_operation_create(connection, GB_SPI_TYPE_TRANSFER, + request_size, rx_size, GFP_KERNEL); + if (!operation) + return NULL; + + request = operation->request->payload; + request->count = cpu_to_le16(count); + request->mode = dev->mode; + request->chip_select = dev->chip_select; + + gb_xfer = &request->transfers[0]; + tx_data = gb_xfer + count; /* place tx data after last gb_xfer */ + + /* Fill in the transfers array */ + xfer = spi->first_xfer; + while (msg->state != GB_SPI_STATE_OP_DONE) { + if (xfer == spi->last_xfer) + xfer_len = spi->last_xfer_size; + else + xfer_len = xfer->len; + + /* make sure we do not timeout in a slow transfer */ + xfer_timeout = xfer_len * 8 * MSEC_PER_SEC / xfer->speed_hz; + xfer_timeout += GB_OPERATION_TIMEOUT_DEFAULT; + + if (xfer_timeout > spi->op_timeout) + spi->op_timeout = xfer_timeout; + + gb_xfer->speed_hz = cpu_to_le32(xfer->speed_hz); + gb_xfer->len = cpu_to_le32(xfer_len); + gb_xfer->delay_usecs = cpu_to_le16(xfer->delay_usecs); + gb_xfer->cs_change = xfer->cs_change; + gb_xfer->bits_per_word = xfer->bits_per_word; + + /* Copy tx data */ + if (xfer->tx_buf) { + gb_xfer->rdwr |= GB_SPI_XFER_WRITE; + memcpy(tx_data, xfer->tx_buf + spi->tx_xfer_offset, + xfer_len); + tx_data += xfer_len; + } + + if (xfer->rx_buf) + gb_xfer->rdwr |= GB_SPI_XFER_READ; + + if (xfer == spi->last_xfer) { + msg->state = GB_SPI_STATE_OP_DONE; + continue; + } + + gb_xfer++; + xfer = get_next_xfer(xfer, msg); + } + + msg->actual_length += total_len; + + return operation; +} + +static void gb_spi_decode_response(struct gb_spilib *spi, + struct spi_message *msg, + struct gb_spi_transfer_response *response) +{ + struct spi_transfer *xfer = spi->first_xfer; + void *rx_data = response->data; + u32 xfer_len; + + while (xfer) { + /* Copy rx data */ + if (xfer->rx_buf) { + if (xfer == spi->first_xfer) + xfer_len = xfer->len - spi->rx_xfer_offset; + else if (xfer == spi->last_xfer) + xfer_len = spi->last_xfer_size; + else + xfer_len = xfer->len; + + memcpy(xfer->rx_buf + spi->rx_xfer_offset, rx_data, + xfer_len); + rx_data += xfer_len; + } + + if (xfer == spi->last_xfer) + break; + + xfer = list_next_entry(xfer, transfer_list); + } +} + +static int gb_spi_transfer_one_message(struct spi_master *master, + struct spi_message *msg) +{ + struct gb_spilib *spi = spi_master_get_devdata(master); + struct gb_connection *connection = spi->connection; + struct gb_spi_transfer_response *response; + struct gb_operation *operation; + int ret = 0; + + spi->first_xfer = list_first_entry_or_null(&msg->transfers, + struct spi_transfer, + transfer_list); + if (!spi->first_xfer) { + ret = -ENOMEM; + goto out; + } + + msg->state = GB_SPI_STATE_MSG_IDLE; + + while (msg->state != GB_SPI_STATE_MSG_DONE && + msg->state != GB_SPI_STATE_MSG_ERROR) { + operation = gb_spi_operation_create(spi, connection, msg); + if (!operation) { + msg->state = GB_SPI_STATE_MSG_ERROR; + ret = -EINVAL; + continue; + } + + ret = gb_operation_request_send_sync_timeout(operation, + spi->op_timeout); + if (!ret) { + response = operation->response->payload; + if (response) + gb_spi_decode_response(spi, msg, response); + } else { + dev_err(spi->parent, + "transfer operation failed: %d\n", ret); + msg->state = GB_SPI_STATE_MSG_ERROR; + } + + gb_operation_put(operation); + setup_next_xfer(spi, msg); + } + +out: + msg->status = ret; + clean_xfer_state(spi); + spi_finalize_current_message(master); + + return ret; +} + +static int gb_spi_setup(struct spi_device *spi) +{ + /* Nothing to do for now */ + return 0; +} + +static void gb_spi_cleanup(struct spi_device *spi) +{ + /* Nothing to do for now */ +} + + +/* Routines to get controller information */ + +/* + * Map Greybus spi mode bits/flags/bpw into Linux ones. + * All bits are same for now and so these macro's return same values. + */ +#define gb_spi_mode_map(mode) mode +#define gb_spi_flags_map(flags) flags + +static int gb_spi_get_master_config(struct gb_spilib *spi) +{ + struct gb_spi_master_config_response response; + u16 mode, flags; + int ret; + + ret = gb_operation_sync(spi->connection, GB_SPI_TYPE_MASTER_CONFIG, + NULL, 0, &response, sizeof(response)); + if (ret < 0) + return ret; + + mode = le16_to_cpu(response.mode); + spi->mode = gb_spi_mode_map(mode); + + flags = le16_to_cpu(response.flags); + spi->flags = gb_spi_flags_map(flags); + + spi->bits_per_word_mask = le32_to_cpu(response.bits_per_word_mask); + spi->num_chipselect = response.num_chipselect; + + spi->min_speed_hz = le32_to_cpu(response.min_speed_hz); + spi->max_speed_hz = le32_to_cpu(response.max_speed_hz); + + return 0; +} + +static int gb_spi_setup_device(struct gb_spilib *spi, u8 cs) +{ + struct spi_master *master = get_master_from_spi(spi); + struct gb_spi_device_config_request request; + struct gb_spi_device_config_response response; + struct spi_board_info spi_board = { {0} }; + struct spi_device *spidev; + int ret; + u8 dev_type; + + request.chip_select = cs; + + ret = gb_operation_sync(spi->connection, GB_SPI_TYPE_DEVICE_CONFIG, + &request, sizeof(request), + &response, sizeof(response)); + if (ret < 0) + return ret; + + dev_type = response.device_type; + + if (dev_type == GB_SPI_SPI_DEV) + strlcpy(spi_board.modalias, SPI_DEV_MODALIAS, + sizeof(spi_board.modalias)); + else if (dev_type == GB_SPI_SPI_NOR) + strlcpy(spi_board.modalias, SPI_NOR_MODALIAS, + sizeof(spi_board.modalias)); + else if (dev_type == GB_SPI_SPI_MODALIAS) + memcpy(spi_board.modalias, response.name, + sizeof(spi_board.modalias)); + else + return -EINVAL; + + spi_board.mode = le16_to_cpu(response.mode); + spi_board.bus_num = master->bus_num; + spi_board.chip_select = cs; + spi_board.max_speed_hz = le32_to_cpu(response.max_speed_hz); + + spidev = spi_new_device(master, &spi_board); + if (!spidev) + return -EINVAL; + + return 0; +} + +int gb_spilib_master_init(struct gb_connection *connection, struct device *dev) +{ + struct gb_spilib *spi; + struct spi_master *master; + int ret; + u8 i; + + /* Allocate master with space for data */ + master = spi_alloc_master(dev, sizeof(*spi)); + if (!master) { + dev_err(dev, "cannot alloc SPI master\n"); + return -ENOMEM; + } + + spi = spi_master_get_devdata(master); + spi->connection = connection; + gb_connection_set_data(connection, master); + spi->parent = dev; + + /* get master configuration */ + ret = gb_spi_get_master_config(spi); + if (ret) + goto exit_spi_put; + + master->bus_num = -1; /* Allow spi-core to allocate it dynamically */ + master->num_chipselect = spi->num_chipselect; + master->mode_bits = spi->mode; + master->flags = spi->flags; + master->bits_per_word_mask = spi->bits_per_word_mask; + + /* Attach methods */ + master->cleanup = gb_spi_cleanup; + master->setup = gb_spi_setup; + master->transfer_one_message = gb_spi_transfer_one_message; + + ret = spi_register_master(master); + if (ret < 0) + goto exit_spi_put; + + /* now, fetch the devices configuration */ + for (i = 0; i < spi->num_chipselect; i++) { + ret = gb_spi_setup_device(spi, i); + if (ret < 0) { + dev_err(dev, "failed to allocate spi device %d: %d\n", + i, ret); + goto exit_spi_unregister; + } + } + + return 0; + +exit_spi_unregister: + spi_unregister_master(master); +exit_spi_put: + spi_master_put(master); + + return ret; +} +EXPORT_SYMBOL_GPL(gb_spilib_master_init); + +void gb_spilib_master_exit(struct gb_connection *connection) +{ + struct spi_master *master = gb_connection_get_data(connection); + + spi_unregister_master(master); + spi_master_put(master); +} +EXPORT_SYMBOL_GPL(gb_spilib_master_exit); + +static int gb_spi_probe(struct gpbridge_device *gpbdev, + const struct gpbridge_device_id *id) +{ + struct gb_connection *connection; + int ret; + + connection = gb_connection_create(gpbdev->bundle, + le16_to_cpu(gpbdev->cport_desc->id), + NULL); + if (IS_ERR(connection)) + return PTR_ERR(connection); + + ret = gb_connection_enable(connection); + if (ret) + goto exit_connection_destroy; + + ret = gb_gpbridge_get_version(connection); + if (ret) + goto exit_connection_disable; + + ret = gb_spilib_master_init(connection, &gpbdev->dev); + if (ret) + goto exit_connection_disable; + + gb_gpbridge_set_data(gpbdev, connection); + + return 0; + +exit_connection_disable: + gb_connection_disable(connection); +exit_connection_destroy: + gb_connection_destroy(connection); + + return ret; +} + +static void gb_spi_remove(struct gpbridge_device *gpbdev) +{ + struct gb_connection *connection = gb_gpbridge_get_data(gpbdev); + + gb_spilib_master_exit(connection); + gb_connection_disable(connection); + gb_connection_destroy(connection); +} + +static const struct gpbridge_device_id gb_spi_id_table[] = { + { GPBRIDGE_PROTOCOL(GREYBUS_PROTOCOL_SPI) }, + { }, +}; +MODULE_DEVICE_TABLE(gpbridge, gb_spi_id_table); + +static struct gpbridge_driver spi_driver = { + .name = "spi", + .probe = gb_spi_probe, + .remove = gb_spi_remove, + .id_table = gb_spi_id_table, +}; + +module_gpbridge_driver(spi_driver); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/spilib.h b/drivers/staging/greybus/spilib.h new file mode 100644 index 0000000..9be1b31 --- /dev/null +++ b/drivers/staging/greybus/spilib.h @@ -0,0 +1,18 @@ +/* + * Greybus SPI library header + * + * copyright 2016 google inc. + * copyright 2016 linaro ltd. + * + * released under the gplv2 only. + */ + +#ifndef __SPILIB_H +#define __SPILIB_H + +struct gb_connection; + +int gb_spilib_master_init(struct gb_connection *connection, struct device *dev); +void gb_spilib_master_exit(struct gb_connection *connection); + +#endif /* __SPILIB_H */ -- cgit v0.10.2 From 8888b963743be7aad2a98bc165fb51150db5fd9f Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Sat, 14 May 2016 23:42:20 +0530 Subject: greybus: spi: Separate out spilib from spi bridged PHY bundle driver spilib can be used by multiple bridge drivers implementing different bundle classes. Separate out bridged PHY bundle drivers parts. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Rui Miguel Silva <rui.silva@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index a9802da..35fc6bf 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -40,6 +40,7 @@ gb-pwm-y := pwm.o gb-gpio-y := gpio.o gb-i2c-y := i2c.o gb-usb-y := usb.o +gb-spi-y := spi.o obj-m += greybus.o obj-m += gb-gpbridge.o @@ -69,6 +70,7 @@ obj-m += gb-pwm.o obj-m += gb-gpio.o obj-m += gb-i2c.o obj-m += gb-usb.o +obj-m += gb-spi.o KERNELVER ?= $(shell uname -r) KERNELDIR ?= /lib/modules/$(KERNELVER)/build diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c new file mode 100644 index 0000000..1cf5f50 --- /dev/null +++ b/drivers/staging/greybus/spi.c @@ -0,0 +1,75 @@ +/* + * SPI bridge PHY driver. + * + * Copyright 2014-2016 Google Inc. + * Copyright 2014-2016 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include <linux/module.h> + +#include "greybus.h" +#include "gpbridge.h" +#include "spilib.h" + +static int gb_spi_probe(struct gpbridge_device *gpbdev, + const struct gpbridge_device_id *id) +{ + struct gb_connection *connection; + int ret; + + connection = gb_connection_create(gpbdev->bundle, + le16_to_cpu(gpbdev->cport_desc->id), + NULL); + if (IS_ERR(connection)) + return PTR_ERR(connection); + + ret = gb_connection_enable(connection); + if (ret) + goto exit_connection_destroy; + + ret = gb_gpbridge_get_version(connection); + if (ret) + goto exit_connection_disable; + + ret = gb_spilib_master_init(connection, &gpbdev->dev); + if (ret) + goto exit_connection_disable; + + gb_gpbridge_set_data(gpbdev, connection); + + return 0; + +exit_connection_disable: + gb_connection_disable(connection); +exit_connection_destroy: + gb_connection_destroy(connection); + + return ret; +} + +static void gb_spi_remove(struct gpbridge_device *gpbdev) +{ + struct gb_connection *connection = gb_gpbridge_get_data(gpbdev); + + gb_spilib_master_exit(connection); + gb_connection_disable(connection); + gb_connection_destroy(connection); +} + +static const struct gpbridge_device_id gb_spi_id_table[] = { + { GPBRIDGE_PROTOCOL(GREYBUS_PROTOCOL_SPI) }, + { }, +}; +MODULE_DEVICE_TABLE(gpbridge, gb_spi_id_table); + +static struct gpbridge_driver spi_driver = { + .name = "spi", + .probe = gb_spi_probe, + .remove = gb_spi_remove, + .id_table = gb_spi_id_table, +}; + +module_gpbridge_driver(spi_driver); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/spilib.c b/drivers/staging/greybus/spilib.c index c7fe878..6ab1c5f 100644 --- a/drivers/staging/greybus/spilib.c +++ b/drivers/staging/greybus/spilib.c @@ -14,7 +14,6 @@ #include <linux/spi/spi.h> #include "greybus.h" -#include "gpbridge.h" #include "spilib.h" struct gb_spilib { @@ -521,63 +520,4 @@ void gb_spilib_master_exit(struct gb_connection *connection) } EXPORT_SYMBOL_GPL(gb_spilib_master_exit); -static int gb_spi_probe(struct gpbridge_device *gpbdev, - const struct gpbridge_device_id *id) -{ - struct gb_connection *connection; - int ret; - - connection = gb_connection_create(gpbdev->bundle, - le16_to_cpu(gpbdev->cport_desc->id), - NULL); - if (IS_ERR(connection)) - return PTR_ERR(connection); - - ret = gb_connection_enable(connection); - if (ret) - goto exit_connection_destroy; - - ret = gb_gpbridge_get_version(connection); - if (ret) - goto exit_connection_disable; - - ret = gb_spilib_master_init(connection, &gpbdev->dev); - if (ret) - goto exit_connection_disable; - - gb_gpbridge_set_data(gpbdev, connection); - - return 0; - -exit_connection_disable: - gb_connection_disable(connection); -exit_connection_destroy: - gb_connection_destroy(connection); - - return ret; -} - -static void gb_spi_remove(struct gpbridge_device *gpbdev) -{ - struct gb_connection *connection = gb_gpbridge_get_data(gpbdev); - - gb_spilib_master_exit(connection); - gb_connection_disable(connection); - gb_connection_destroy(connection); -} - -static const struct gpbridge_device_id gb_spi_id_table[] = { - { GPBRIDGE_PROTOCOL(GREYBUS_PROTOCOL_SPI) }, - { }, -}; -MODULE_DEVICE_TABLE(gpbridge, gb_spi_id_table); - -static struct gpbridge_driver spi_driver = { - .name = "spi", - .probe = gb_spi_probe, - .remove = gb_spi_remove, - .id_table = gb_spi_id_table, -}; - -module_gpbridge_driver(spi_driver); MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 8502eb3b7870c6a0c53f39caaf5b4c01a22f2a25 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Sat, 14 May 2016 19:22:24 +0200 Subject: greybus: make greybus_gpbdev_type static 'make check' correctly complains that this should be static, so make it so. Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c index f082658..88f7d26 100644 --- a/drivers/staging/greybus/gpbridge.c +++ b/drivers/staging/greybus/gpbridge.c @@ -50,7 +50,7 @@ static void gpbdev_release(struct device *dev) kfree(gpbdev); } -struct device_type greybus_gpbdev_type = { +static struct device_type greybus_gpbdev_type = { .name = "gpbridge_device", .release = gpbdev_release, }; -- cgit v0.10.2 From 013e665372733fafd08599f0fc58ff5f450e4694 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Sat, 14 May 2016 23:42:21 +0530 Subject: greybus: fw-management: Add firmware-management protocol driver This patch adds Firmware Management Protocol support to firmware core, which allows the AP to manage firmware on an Interface. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Jun Li <li_jun@projectara.com> Tested-by: Karthik Ravi Shankar <karthikrs@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 35fc6bf..608bd51 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -32,7 +32,7 @@ gb-audio-apbridgea-y := audio_apbridgea.o gb-audio-manager-y += audio_manager.o gb-audio-manager-y += audio_manager_module.o gb-camera-y := camera.o -gb-firmware-y := fw-core.o fw-download.o +gb-firmware-y := fw-core.o fw-download.o fw-management.o gb-spilib-y := spilib.o gb-sdio-y := sdio.o gb-uart-y := uart.o diff --git a/drivers/staging/greybus/firmware.h b/drivers/staging/greybus/firmware.h index c5736d5..a82d020 100644 --- a/drivers/staging/greybus/firmware.h +++ b/drivers/staging/greybus/firmware.h @@ -12,6 +12,14 @@ #include "greybus.h" +/* Firmware Management Protocol specific functions */ +int fw_mgmt_init(void); +void fw_mgmt_exit(void); +struct gb_connection *to_fw_mgmt_connection(struct device *dev); +int gb_fw_mgmt_request_handler(struct gb_operation *op); +int gb_fw_mgmt_connection_init(struct gb_connection *connection); +void gb_fw_mgmt_connection_exit(struct gb_connection *connection); + /* Firmware Download Protocol specific functions */ int gb_fw_download_request_handler(struct gb_operation *op); int gb_fw_download_connection_init(struct gb_connection *connection); diff --git a/drivers/staging/greybus/fw-core.c b/drivers/staging/greybus/fw-core.c index a686527..0a456c5 100644 --- a/drivers/staging/greybus/fw-core.c +++ b/drivers/staging/greybus/fw-core.c @@ -17,6 +17,13 @@ struct gb_fw_core { struct gb_connection *mgmt_connection; }; +struct gb_connection *to_fw_mgmt_connection(struct device *dev) +{ + struct gb_fw_core *fw_core = dev_get_drvdata(dev); + + return fw_core->mgmt_connection; +} + static int gb_fw_core_probe(struct gb_bundle *bundle, const struct greybus_bundle_id *id) { @@ -48,7 +55,7 @@ static int gb_fw_core_probe(struct gb_bundle *bundle, } connection = gb_connection_create(bundle, cport_id, - NULL); + gb_fw_mgmt_request_handler); if (IS_ERR(connection)) { ret = PTR_ERR(connection); dev_err(&bundle->dev, @@ -102,13 +109,23 @@ static int gb_fw_core_probe(struct gb_bundle *bundle, fw_core->download_connection = NULL; } + ret = gb_fw_mgmt_connection_init(fw_core->mgmt_connection); + if (ret) { + /* We may still be able to work with the Interface */ + dev_err(&bundle->dev, "failed to initialize firmware management connection, disable it (%d)\n", + ret); + goto err_exit_connections; + } + greybus_set_drvdata(bundle, fw_core); return 0; +err_exit_connections: + gb_fw_download_connection_exit(fw_core->download_connection); err_destroy_connections: - gb_connection_destroy(fw_core->download_connection); gb_connection_destroy(fw_core->mgmt_connection); + gb_connection_destroy(fw_core->download_connection); err_free_fw_core: kfree(fw_core); @@ -119,9 +136,11 @@ static void gb_fw_core_disconnect(struct gb_bundle *bundle) { struct gb_fw_core *fw_core = greybus_get_drvdata(bundle); + gb_fw_mgmt_connection_exit(fw_core->mgmt_connection); gb_fw_download_connection_exit(fw_core->download_connection); - gb_connection_destroy(fw_core->download_connection); + gb_connection_destroy(fw_core->mgmt_connection); + gb_connection_destroy(fw_core->download_connection); kfree(fw_core); } @@ -140,13 +159,28 @@ static struct greybus_driver gb_fw_core_driver = { static int fw_core_init(void) { - return greybus_register(&gb_fw_core_driver); + int ret; + + ret = fw_mgmt_init(); + if (ret) { + pr_err("Failed to initialize fw-mgmt core (%d)\n", ret); + return ret; + } + + ret = greybus_register(&gb_fw_core_driver); + if (ret) { + fw_mgmt_exit(); + return ret; + } + + return 0; } module_init(fw_core_init); static void __exit fw_core_exit(void) { greybus_deregister(&gb_fw_core_driver); + fw_mgmt_exit(); } module_exit(fw_core_exit); diff --git a/drivers/staging/greybus/fw-management.c b/drivers/staging/greybus/fw-management.c new file mode 100644 index 0000000..2db5a11 --- /dev/null +++ b/drivers/staging/greybus/fw-management.c @@ -0,0 +1,564 @@ +/* + * Greybus Firmware Management Protocol Driver. + * + * Copyright 2016 Google Inc. + * Copyright 2016 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include <linux/cdev.h> +#include <linux/completion.h> +#include <linux/firmware.h> +#include <linux/fs.h> +#include <linux/idr.h> +#include <linux/ioctl.h> +#include <linux/uaccess.h> + +#include "firmware.h" +#include "greybus_firmware.h" +#include "greybus.h" + +#define FW_MGMT_TIMEOUT_MS 1000 + +struct fw_mgmt { + struct device *parent; + struct gb_connection *connection; + /* Common id-map for interface and backend firmware requests */ + struct ida id_map; + struct mutex mutex; + struct completion completion; + struct cdev cdev; + struct device *class_device; + dev_t dev_num; + unsigned int timeout_jiffies; + + /* Interface Firmware specific fields */ + u8 intf_fw_request_id; + u8 intf_fw_status; + u16 intf_fw_major; + u16 intf_fw_minor; + + /* Backend Firmware specific fields */ + u8 backend_fw_request_id; + u8 backend_fw_status; +}; + +/* + * Number of minor devices this driver supports. + * There will be exactly one required per Interface. + */ +#define NUM_MINORS U8_MAX + +static struct class *fw_mgmt_class; +static dev_t fw_mgmt_dev_num; +static DEFINE_IDA(fw_mgmt_minors_map); + +static int fw_mgmt_interface_fw_version_operation(struct fw_mgmt *fw_mgmt, + struct fw_mgmt_ioc_get_fw *fw_info) +{ + struct gb_connection *connection = fw_mgmt->connection; + struct gb_fw_mgmt_interface_fw_version_response response; + int ret; + + ret = gb_operation_sync(connection, + GB_FW_MGMT_TYPE_INTERFACE_FW_VERSION, NULL, 0, + &response, sizeof(response)); + if (ret) { + dev_err(fw_mgmt->parent, + "failed to get interface firmware version (%d)\n", ret); + return ret; + } + + fw_info->major = le16_to_cpu(response.major); + fw_info->minor = le16_to_cpu(response.minor); + + strncpy(fw_info->firmware_tag, response.firmware_tag, + GB_FIRMWARE_TAG_MAX_LEN); + + /* + * The firmware-tag should be NULL terminated, otherwise throw error but + * don't fail. + */ + if (fw_info->firmware_tag[GB_FIRMWARE_TAG_MAX_LEN - 1] != '\0') { + dev_err(fw_mgmt->parent, + "fw-version: firmware-tag is not NULL terminated\n"); + fw_info->firmware_tag[GB_FIRMWARE_TAG_MAX_LEN - 1] = '\0'; + } + + return 0; +} + +static int fw_mgmt_load_and_validate_operation(struct fw_mgmt *fw_mgmt, + u8 load_method, const char *tag) +{ + struct gb_fw_mgmt_load_and_validate_fw_request request; + int ret; + + if (load_method != GB_FW_LOAD_METHOD_UNIPRO && + load_method != GB_FW_LOAD_METHOD_INTERNAL) { + dev_err(fw_mgmt->parent, + "invalid load-method (%d)\n", load_method); + return -EINVAL; + } + + request.load_method = load_method; + strncpy(request.firmware_tag, tag, GB_FIRMWARE_TAG_MAX_LEN); + + /* + * The firmware-tag should be NULL terminated, otherwise throw error and + * fail. + */ + if (request.firmware_tag[GB_FIRMWARE_TAG_MAX_LEN - 1] != '\0') { + dev_err(fw_mgmt->parent, "load-and-validate: firmware-tag is not NULL terminated\n"); + return -EINVAL; + } + + /* Allocate ids from 1 to 255 (u8-max), 0 is an invalid id */ + ret = ida_simple_get(&fw_mgmt->id_map, 1, 256, GFP_KERNEL); + if (ret < 0) { + dev_err(fw_mgmt->parent, "failed to allocate request id (%d)\n", + ret); + return ret; + } + + fw_mgmt->intf_fw_request_id = ret; + request.request_id = ret; + + ret = gb_operation_sync(fw_mgmt->connection, + GB_FW_MGMT_TYPE_LOAD_AND_VALIDATE_FW, &request, + sizeof(request), NULL, 0); + if (ret) { + ida_simple_remove(&fw_mgmt->id_map, + fw_mgmt->intf_fw_request_id); + fw_mgmt->intf_fw_request_id = 0; + dev_err(fw_mgmt->parent, + "load and validate firmware request failed (%d)\n", + ret); + return ret; + } + + return 0; +} + +static int fw_mgmt_interface_fw_loaded_operation(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct fw_mgmt *fw_mgmt = gb_connection_get_data(connection); + struct gb_fw_mgmt_loaded_fw_request *request; + + /* No pending load and validate request ? */ + if (!fw_mgmt->intf_fw_request_id) { + dev_err(fw_mgmt->parent, + "unexpected firmware loaded request received\n"); + return -ENODEV; + } + + if (op->request->payload_size != sizeof(*request)) { + dev_err(fw_mgmt->parent, "illegal size of firmware loaded request (%zu != %zu)\n", + op->request->payload_size, sizeof(*request)); + return -EINVAL; + } + + request = op->request->payload; + + /* Invalid request-id ? */ + if (request->request_id != fw_mgmt->intf_fw_request_id) { + dev_err(fw_mgmt->parent, "invalid request id for firmware loaded request (%02u != %02u)\n", + fw_mgmt->intf_fw_request_id, request->request_id); + return -ENODEV; + } + + ida_simple_remove(&fw_mgmt->id_map, fw_mgmt->intf_fw_request_id); + fw_mgmt->intf_fw_request_id = 0; + fw_mgmt->intf_fw_status = request->status; + fw_mgmt->intf_fw_major = le16_to_cpu(request->major); + fw_mgmt->intf_fw_minor = le16_to_cpu(request->minor); + + if (fw_mgmt->intf_fw_status == GB_FW_LOAD_STATUS_FAILED) + dev_err(fw_mgmt->parent, + "failed to load interface firmware, status:%02x\n", + fw_mgmt->intf_fw_status); + else if (fw_mgmt->intf_fw_status == GB_FW_LOAD_STATUS_VALIDATION_FAILED) + dev_err(fw_mgmt->parent, + "failed to validate interface firmware, status:%02x\n", + fw_mgmt->intf_fw_status); + + complete(&fw_mgmt->completion); + + return 0; +} + +static int fw_mgmt_backend_fw_version_operation(struct fw_mgmt *fw_mgmt, + struct fw_mgmt_ioc_get_fw *fw_info) +{ + struct gb_connection *connection = fw_mgmt->connection; + struct gb_fw_mgmt_backend_fw_version_request request; + struct gb_fw_mgmt_backend_fw_version_response response; + int ret; + + strncpy(request.firmware_tag, fw_info->firmware_tag, + GB_FIRMWARE_TAG_MAX_LEN); + + /* + * The firmware-tag should be NULL terminated, otherwise throw error and + * fail. + */ + if (request.firmware_tag[GB_FIRMWARE_TAG_MAX_LEN - 1] != '\0') { + dev_err(fw_mgmt->parent, "backend-version: firmware-tag is not NULL terminated\n"); + return -EINVAL; + } + + ret = gb_operation_sync(connection, + GB_FW_MGMT_TYPE_BACKEND_FW_VERSION, &request, + sizeof(request), &response, sizeof(response)); + if (ret) { + dev_err(fw_mgmt->parent, "failed to get version of %s backend firmware (%d)\n", + fw_info->firmware_tag, ret); + return ret; + } + + fw_info->major = le16_to_cpu(response.major); + fw_info->minor = le16_to_cpu(response.minor); + + return 0; +} + +static int fw_mgmt_backend_fw_update_operation(struct fw_mgmt *fw_mgmt, + char *tag) +{ + struct gb_fw_mgmt_backend_fw_update_request request; + int ret; + + strncpy(request.firmware_tag, tag, GB_FIRMWARE_TAG_MAX_LEN); + + /* + * The firmware-tag should be NULL terminated, otherwise throw error and + * fail. + */ + if (request.firmware_tag[GB_FIRMWARE_TAG_MAX_LEN - 1] != '\0') { + dev_err(fw_mgmt->parent, "backend-update: firmware-tag is not NULL terminated\n"); + return -EINVAL; + } + + /* Allocate ids from 1 to 255 (u8-max), 0 is an invalid id */ + ret = ida_simple_get(&fw_mgmt->id_map, 1, 256, GFP_KERNEL); + if (ret < 0) { + dev_err(fw_mgmt->parent, "failed to allocate request id (%d)\n", + ret); + return ret; + } + + fw_mgmt->backend_fw_request_id = ret; + request.request_id = ret; + + ret = gb_operation_sync(fw_mgmt->connection, + GB_FW_MGMT_TYPE_BACKEND_FW_UPDATE, &request, + sizeof(request), NULL, 0); + if (ret) { + ida_simple_remove(&fw_mgmt->id_map, + fw_mgmt->backend_fw_request_id); + fw_mgmt->backend_fw_request_id = 0; + dev_err(fw_mgmt->parent, + "backend %s firmware update request failed (%d)\n", tag, + ret); + return ret; + } + + return 0; +} + +static int fw_mgmt_backend_fw_updated_operation(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct fw_mgmt *fw_mgmt = gb_connection_get_data(connection); + struct gb_fw_mgmt_backend_fw_updated_request *request; + + /* No pending load and validate request ? */ + if (!fw_mgmt->backend_fw_request_id) { + dev_err(fw_mgmt->parent, "unexpected backend firmware updated request received\n"); + return -ENODEV; + } + + if (op->request->payload_size != sizeof(*request)) { + dev_err(fw_mgmt->parent, "illegal size of backend firmware updated request (%zu != %zu)\n", + op->request->payload_size, sizeof(*request)); + return -EINVAL; + } + + request = op->request->payload; + + /* Invalid request-id ? */ + if (request->request_id != fw_mgmt->backend_fw_request_id) { + dev_err(fw_mgmt->parent, "invalid request id for backend firmware updated request (%02u != %02u)\n", + fw_mgmt->backend_fw_request_id, request->request_id); + return -ENODEV; + } + + ida_simple_remove(&fw_mgmt->id_map, fw_mgmt->backend_fw_request_id); + fw_mgmt->backend_fw_request_id = 0; + fw_mgmt->backend_fw_status = request->status; + + if (fw_mgmt->backend_fw_status != GB_FW_BACKEND_FW_STATUS_SUCCESS) + dev_err(fw_mgmt->parent, + "failed to backend load firmware, status:%02x\n", + fw_mgmt->backend_fw_status); + + complete(&fw_mgmt->completion); + + return 0; +} + +/* Char device fops */ + +static int fw_mgmt_open(struct inode *inode, struct file *file) +{ + struct fw_mgmt *fw_mgmt = container_of(inode->i_cdev, struct fw_mgmt, + cdev); + + file->private_data = fw_mgmt; + return 0; +} + +static int fw_mgmt_ioctl(struct fw_mgmt *fw_mgmt, unsigned int cmd, + void __user *buf) +{ + struct fw_mgmt_ioc_get_fw fw_info; + struct fw_mgmt_ioc_intf_load_and_validate intf_load; + struct fw_mgmt_ioc_backend_fw_update backend_update; + unsigned int timeout; + int ret; + + switch (cmd) { + case FW_MGMT_IOC_GET_INTF_FW: + ret = fw_mgmt_interface_fw_version_operation(fw_mgmt, &fw_info); + if (ret) + return ret; + + if (copy_to_user(buf, &fw_info, sizeof(fw_info))) + return -EFAULT; + + return 0; + case FW_MGMT_IOC_GET_BACKEND_FW: + if (copy_from_user(&fw_info, buf, sizeof(fw_info))) + return -EFAULT; + + ret = fw_mgmt_backend_fw_version_operation(fw_mgmt, &fw_info); + if (ret) + return ret; + + if (copy_to_user(buf, &fw_info, sizeof(fw_info))) + return -EFAULT; + + return 0; + case FW_MGMT_IOC_INTF_LOAD_AND_VALIDATE: + if (copy_from_user(&intf_load, buf, sizeof(intf_load))) + return -EFAULT; + + ret = fw_mgmt_load_and_validate_operation(fw_mgmt, + intf_load.load_method, intf_load.firmware_tag); + if (ret) + return ret; + + if (!wait_for_completion_timeout(&fw_mgmt->completion, + fw_mgmt->timeout_jiffies)) { + dev_err(fw_mgmt->parent, "timed out waiting for firmware load and validation to finish\n"); + return -ETIMEDOUT; + } + + intf_load.status = fw_mgmt->intf_fw_status; + intf_load.major = cpu_to_le16(fw_mgmt->intf_fw_major); + intf_load.minor = cpu_to_le16(fw_mgmt->intf_fw_minor); + + if (copy_to_user(buf, &intf_load, sizeof(intf_load))) + return -EFAULT; + + return 0; + case FW_MGMT_IOC_INTF_BACKEND_FW_UPDATE: + if (copy_from_user(&backend_update, buf, + sizeof(backend_update))) + return -EFAULT; + + ret = fw_mgmt_backend_fw_update_operation(fw_mgmt, + backend_update.firmware_tag); + if (ret) + return ret; + + if (!wait_for_completion_timeout(&fw_mgmt->completion, + fw_mgmt->timeout_jiffies)) { + dev_err(fw_mgmt->parent, "timed out waiting for backend firmware update to finish\n"); + return -ETIMEDOUT; + } + + backend_update.status = fw_mgmt->backend_fw_status; + + if (copy_to_user(buf, &backend_update, sizeof(backend_update))) + return -EFAULT; + + return 0; + case FW_MGMT_IOC_SET_TIMEOUT_MS: + if (get_user(timeout, (unsigned int __user *)buf)) + return -EFAULT; + + if (!timeout) { + dev_err(fw_mgmt->parent, "timeout can't be zero\n"); + return -EINVAL; + } + + fw_mgmt->timeout_jiffies = msecs_to_jiffies(timeout); + + return 0; + default: + return -ENOTTY; + } +} + +static long fw_mgmt_ioctl_unlocked(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct fw_mgmt *fw_mgmt = file->private_data; + int ret; + + /* + * Serialize ioctls + * + * We don't want the user to do few operations in parallel. For example, + * updating Interface firmware in parallel for the same Interface. There + * is no need to do things in parallel for speed and we can avoid having + * complicated for now. + */ + mutex_lock(&fw_mgmt->mutex); + ret = fw_mgmt_ioctl(fw_mgmt, cmd, (void __user *)arg); + mutex_unlock(&fw_mgmt->mutex); + + return ret; +} + +static const struct file_operations fw_mgmt_fops = { + .owner = THIS_MODULE, + .open = fw_mgmt_open, + .unlocked_ioctl = fw_mgmt_ioctl_unlocked, +}; + +int gb_fw_mgmt_request_handler(struct gb_operation *op) +{ + u8 type = op->type; + + switch (type) { + case GB_FW_MGMT_TYPE_LOADED_FW: + return fw_mgmt_interface_fw_loaded_operation(op); + case GB_FW_MGMT_TYPE_BACKEND_FW_UPDATED: + return fw_mgmt_backend_fw_updated_operation(op); + default: + dev_err(&op->connection->bundle->dev, + "unsupported request: %u\n", type); + return -EINVAL; + } +} + +int gb_fw_mgmt_connection_init(struct gb_connection *connection) +{ + struct fw_mgmt *fw_mgmt; + int ret, minor; + + if (!connection) + return 0; + + fw_mgmt = kzalloc(sizeof(*fw_mgmt), GFP_KERNEL); + if (!fw_mgmt) + return -ENOMEM; + + fw_mgmt->parent = &connection->bundle->dev; + fw_mgmt->timeout_jiffies = msecs_to_jiffies(FW_MGMT_TIMEOUT_MS); + fw_mgmt->connection = connection; + + gb_connection_set_data(connection, fw_mgmt); + init_completion(&fw_mgmt->completion); + ida_init(&fw_mgmt->id_map); + mutex_init(&fw_mgmt->mutex); + + ret = gb_connection_enable(connection); + if (ret) + goto err_destroy_ida; + + minor = ida_simple_get(&fw_mgmt_minors_map, 0, NUM_MINORS, GFP_KERNEL); + if (minor < 0) { + ret = minor; + goto err_connection_disable; + } + + /* Add a char device to allow userspace to interact with fw-mgmt */ + fw_mgmt->dev_num = MKDEV(MAJOR(fw_mgmt_dev_num), minor); + cdev_init(&fw_mgmt->cdev, &fw_mgmt_fops); + + ret = cdev_add(&fw_mgmt->cdev, fw_mgmt->dev_num, 1); + if (ret) + goto err_remove_ida; + + /* Add a soft link to the previously added char-dev within the bundle */ + fw_mgmt->class_device = device_create(fw_mgmt_class, fw_mgmt->parent, + fw_mgmt->dev_num, NULL, + "fw-mgmt-%d", minor); + if (IS_ERR(fw_mgmt->class_device)) { + ret = PTR_ERR(fw_mgmt->class_device); + goto err_del_cdev; + } + + return 0; + +err_del_cdev: + cdev_del(&fw_mgmt->cdev); +err_remove_ida: + ida_simple_remove(&fw_mgmt_minors_map, minor); +err_connection_disable: + gb_connection_disable(connection); +err_destroy_ida: + ida_destroy(&fw_mgmt->id_map); + kfree(fw_mgmt); + + return ret; +} + +void gb_fw_mgmt_connection_exit(struct gb_connection *connection) +{ + struct fw_mgmt *fw_mgmt; + + if (!connection) + return; + + fw_mgmt = gb_connection_get_data(connection); + device_destroy(fw_mgmt_class, fw_mgmt->dev_num); + cdev_del(&fw_mgmt->cdev); + ida_simple_remove(&fw_mgmt_minors_map, MINOR(fw_mgmt->dev_num)); + gb_connection_disable(fw_mgmt->connection); + ida_destroy(&fw_mgmt->id_map); + + kfree(fw_mgmt); +} + +int fw_mgmt_init(void) +{ + int ret; + + fw_mgmt_class = class_create(THIS_MODULE, "gb_fw_mgmt"); + if (IS_ERR(fw_mgmt_class)) + return PTR_ERR(fw_mgmt_class); + + ret = alloc_chrdev_region(&fw_mgmt_dev_num, 0, NUM_MINORS, + "gb_fw_mgmt"); + if (ret) + goto err_remove_class; + + return 0; + +err_remove_class: + class_destroy(fw_mgmt_class); + return ret; +} + +void fw_mgmt_exit(void) +{ + unregister_chrdev_region(fw_mgmt_dev_num, NUM_MINORS); + class_destroy(fw_mgmt_class); + ida_destroy(&fw_mgmt_minors_map); +} diff --git a/drivers/staging/greybus/greybus_firmware.h b/drivers/staging/greybus/greybus_firmware.h new file mode 100644 index 0000000..9c5ad75 --- /dev/null +++ b/drivers/staging/greybus/greybus_firmware.h @@ -0,0 +1,84 @@ +/* + * Greybus Firmware Management User Header + * + * This file is provided under the GPLv2 license. When using or + * redistributing this file, you may do so under that license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2016 Google Inc. All rights reserved. + * Copyright(c) 2016 Linaro Ltd. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details. + * + * 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 GOOGLE INC. OR + * LINARO LTD. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __GREYBUS_FIRMWARE_USER_H +#define __GREYBUS_FIRMWARE_USER_H + +#include <linux/ioctl.h> +#include <linux/types.h> + +#define GB_FIRMWARE_U_TAG_MAX_LEN 10 + +#define GB_FW_U_LOAD_METHOD_UNIPRO 0x01 +#define GB_FW_U_LOAD_METHOD_INTERNAL 0x02 + +#define GB_FW_U_LOAD_STATUS_FAILED 0x00 +#define GB_FW_U_LOAD_STATUS_UNVALIDATED 0x01 +#define GB_FW_U_LOAD_STATUS_VALIDATED 0x02 +#define GB_FW_U_LOAD_STATUS_VALIDATION_FAILED 0x03 + +#define GB_FW_U_BACKEND_FW_STATUS_SUCCESS 0x01 +#define GB_FW_U_BACKEND_FW_STATUS_FAIL_FIND 0x02 +#define GB_FW_U_BACKEND_FW_STATUS_FAIL_FETCH 0x03 +#define GB_FW_U_BACKEND_FW_STATUS_FAIL_WRITE 0x04 +#define GB_FW_U_BACKEND_FW_STATUS_INT 0x05 + +/* IOCTL support */ +struct fw_mgmt_ioc_get_fw { + __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_LEN]; + __u16 major; + __u16 minor; +} __attribute__ ((__packed__)); + +struct fw_mgmt_ioc_intf_load_and_validate { + __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_LEN]; + __u8 load_method; + __u8 status; + __u16 major; + __u16 minor; +} __attribute__ ((__packed__)); + +struct fw_mgmt_ioc_backend_fw_update { + __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_LEN]; + __u8 status; +} __attribute__ ((__packed__)); + +#define FW_MGMT_IOCTL_BASE 'F' +#define FW_MGMT_IOC_GET_INTF_FW _IOR(FW_MGMT_IOCTL_BASE, 0, struct fw_mgmt_ioc_get_fw) +#define FW_MGMT_IOC_GET_BACKEND_FW _IOWR(FW_MGMT_IOCTL_BASE, 1, struct fw_mgmt_ioc_get_fw) +#define FW_MGMT_IOC_INTF_LOAD_AND_VALIDATE _IOWR(FW_MGMT_IOCTL_BASE, 2, struct fw_mgmt_ioc_intf_load_and_validate) +#define FW_MGMT_IOC_INTF_BACKEND_FW_UPDATE _IOWR(FW_MGMT_IOCTL_BASE, 3, struct fw_mgmt_ioc_backend_fw_update) +#define FW_MGMT_IOC_SET_TIMEOUT_MS _IOW(FW_MGMT_IOCTL_BASE, 4, unsigned int) + +#endif /* __GREYBUS_FIRMWARE_USER_H */ + diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 40bd6c0..e3ad5d7 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -250,6 +250,79 @@ struct gb_fw_download_release_firmware_request { /* firmware download release firmware response has no payload */ +/* Firmware Management Protocol */ + +/* Request Types */ +#define GB_FW_MGMT_TYPE_INTERFACE_FW_VERSION 0x01 +#define GB_FW_MGMT_TYPE_LOAD_AND_VALIDATE_FW 0x02 +#define GB_FW_MGMT_TYPE_LOADED_FW 0x03 +#define GB_FW_MGMT_TYPE_BACKEND_FW_VERSION 0x04 +#define GB_FW_MGMT_TYPE_BACKEND_FW_UPDATE 0x05 +#define GB_FW_MGMT_TYPE_BACKEND_FW_UPDATED 0x06 + +#define GB_FW_LOAD_METHOD_UNIPRO 0x01 +#define GB_FW_LOAD_METHOD_INTERNAL 0x02 + +#define GB_FW_LOAD_STATUS_FAILED 0x00 +#define GB_FW_LOAD_STATUS_UNVALIDATED 0x01 +#define GB_FW_LOAD_STATUS_VALIDATED 0x02 +#define GB_FW_LOAD_STATUS_VALIDATION_FAILED 0x03 + +#define GB_FW_BACKEND_FW_STATUS_SUCCESS 0x01 +#define GB_FW_BACKEND_FW_STATUS_FAIL_FIND 0x02 +#define GB_FW_BACKEND_FW_STATUS_FAIL_FETCH 0x03 +#define GB_FW_BACKEND_FW_STATUS_FAIL_WRITE 0x04 +#define GB_FW_BACKEND_FW_STATUS_INT 0x05 + +/* firmware management interface firmware version request has no payload */ +struct gb_fw_mgmt_interface_fw_version_response { + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_LEN]; + __le16 major; + __le16 minor; +} __packed; + +/* firmware management load and validate firmware request/response */ +struct gb_fw_mgmt_load_and_validate_fw_request { + __u8 request_id; + __u8 load_method; + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_LEN]; +} __packed; +/* firmware management load and validate firmware response has no payload*/ + +/* firmware management loaded firmware request */ +struct gb_fw_mgmt_loaded_fw_request { + __u8 request_id; + __u8 status; + __le16 major; + __le16 minor; +} __packed; +/* firmware management loaded firmware response has no payload */ + +/* firmware management backend firmware version request/response */ +struct gb_fw_mgmt_backend_fw_version_request { + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_LEN]; +} __packed; + +struct gb_fw_mgmt_backend_fw_version_response { + __le16 major; + __le16 minor; +} __packed; + +/* firmware management backend firmware update request */ +struct gb_fw_mgmt_backend_fw_update_request { + __u8 request_id; + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_LEN]; +} __packed; +/* firmware management backend firmware update response has no payload */ + +/* firmware management backend firmware updated request */ +struct gb_fw_mgmt_backend_fw_updated_request { + __u8 request_id; + __u8 status; +} __packed; +/* firmware management backend firmware updated response has no payload */ + + /* Bootrom Protocol */ /* Version of the Greybus bootrom protocol we support */ -- cgit v0.10.2 From 04f0e6ebd1a2ca3a1f1a356e9a07ef1797ef1b7c Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Sat, 14 May 2016 23:42:22 +0530 Subject: greybus: fw-management: Add ioctl to initiate mode-switch Once the interface firmware is loaded successfully to a module, userspace can ask it to mode switch to the newly loaded firmware. This patch provides a new ioctl to initiate mode switch. Userspace can initiate a mode switch if it has previously loaded the interface firmware successfully, otherwise the firmware core rejects it. Also, once the mode-switch is initiated, disallow any more interactions from the userspace. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Tested-by: Karthik Ravi Shankar <karthikrs@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/fw-management.c b/drivers/staging/greybus/fw-management.c index 2db5a11..7c2226a 100644 --- a/drivers/staging/greybus/fw-management.c +++ b/drivers/staging/greybus/fw-management.c @@ -34,6 +34,8 @@ struct fw_mgmt { unsigned int timeout_jiffies; /* Interface Firmware specific fields */ + bool mode_switch_started; + bool intf_fw_loaded; u8 intf_fw_request_id; u8 intf_fw_status; u16 intf_fw_major; @@ -123,6 +125,7 @@ static int fw_mgmt_load_and_validate_operation(struct fw_mgmt *fw_mgmt, } fw_mgmt->intf_fw_request_id = ret; + fw_mgmt->intf_fw_loaded = false; request.request_id = ret; ret = gb_operation_sync(fw_mgmt->connection, @@ -183,6 +186,8 @@ static int fw_mgmt_interface_fw_loaded_operation(struct gb_operation *op) dev_err(fw_mgmt->parent, "failed to validate interface firmware, status:%02x\n", fw_mgmt->intf_fw_status); + else + fw_mgmt->intf_fw_loaded = true; complete(&fw_mgmt->completion); @@ -329,6 +334,10 @@ static int fw_mgmt_ioctl(struct fw_mgmt *fw_mgmt, unsigned int cmd, unsigned int timeout; int ret; + /* Reject any operations after mode-switch has started */ + if (fw_mgmt->mode_switch_started) + return -EBUSY; + switch (cmd) { case FW_MGMT_IOC_GET_INTF_FW: ret = fw_mgmt_interface_fw_version_operation(fw_mgmt, &fw_info); @@ -408,6 +417,17 @@ static int fw_mgmt_ioctl(struct fw_mgmt *fw_mgmt, unsigned int cmd, fw_mgmt->timeout_jiffies = msecs_to_jiffies(timeout); return 0; + case FW_MGMT_IOC_MODE_SWITCH: + if (!fw_mgmt->intf_fw_loaded) { + dev_err(fw_mgmt->parent, + "Firmware not loaded for mode-switch\n"); + return -EPERM; + } + + fw_mgmt->mode_switch_started = true; + + /* FIXME: Initiate mode-switch from here */ + return 0; default: return -ENOTTY; } diff --git a/drivers/staging/greybus/greybus_firmware.h b/drivers/staging/greybus/greybus_firmware.h index 9c5ad75..4e194f2 100644 --- a/drivers/staging/greybus/greybus_firmware.h +++ b/drivers/staging/greybus/greybus_firmware.h @@ -79,6 +79,7 @@ struct fw_mgmt_ioc_backend_fw_update { #define FW_MGMT_IOC_INTF_LOAD_AND_VALIDATE _IOWR(FW_MGMT_IOCTL_BASE, 2, struct fw_mgmt_ioc_intf_load_and_validate) #define FW_MGMT_IOC_INTF_BACKEND_FW_UPDATE _IOWR(FW_MGMT_IOCTL_BASE, 3, struct fw_mgmt_ioc_backend_fw_update) #define FW_MGMT_IOC_SET_TIMEOUT_MS _IOW(FW_MGMT_IOCTL_BASE, 4, unsigned int) +#define FW_MGMT_IOC_MODE_SWITCH _IO(FW_MGMT_IOCTL_BASE, 5) #endif /* __GREYBUS_FIRMWARE_USER_H */ -- cgit v0.10.2 From 96ba6740099b1f1a2732c86204d2931cda11d638 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Sat, 14 May 2016 23:42:23 +0530 Subject: greybus: fw-management: Free fw-mgmt only after all users are gone The fw-management driver rightly destroys the char device on connection-exit, but that doesn't guarantee that all of the users of the device are gone. Userspace may still be holding file-descriptor of the char device and can initiate new ioctl operations. And that *will* lead to kernel crash. To avoid this issue, manage struct users with kref, manage a list of 'struct fw-mgmt' and start using the structure only after getting its kref incremented. The important part is the routine get_fw_mgmt(), which increments the reference to the struct before returning it to the caller. The list of fw-mgmt structs in protected with a mutex to avoid any races around that. The kref is incremented once the char device is opened and dropped only when it is closed. Reported-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/fw-management.c b/drivers/staging/greybus/fw-management.c index 7c2226a..0c73f1e 100644 --- a/drivers/staging/greybus/fw-management.c +++ b/drivers/staging/greybus/fw-management.c @@ -24,6 +24,9 @@ struct fw_mgmt { struct device *parent; struct gb_connection *connection; + struct kref kref; + struct list_head node; + /* Common id-map for interface and backend firmware requests */ struct ida id_map; struct mutex mutex; @@ -32,6 +35,7 @@ struct fw_mgmt { struct device *class_device; dev_t dev_num; unsigned int timeout_jiffies; + bool disabled; /* connection getting disabled */ /* Interface Firmware specific fields */ bool mode_switch_started; @@ -55,6 +59,48 @@ struct fw_mgmt { static struct class *fw_mgmt_class; static dev_t fw_mgmt_dev_num; static DEFINE_IDA(fw_mgmt_minors_map); +static LIST_HEAD(fw_mgmt_list); +static DEFINE_MUTEX(list_mutex); + +static void fw_mgmt_kref_release(struct kref *kref) +{ + struct fw_mgmt *fw_mgmt = container_of(kref, struct fw_mgmt, kref); + + ida_destroy(&fw_mgmt->id_map); + kfree(fw_mgmt); +} + +/* + * All users of fw_mgmt take a reference (from within list_mutex lock), before + * they get a pointer to play with. And the structure will be freed only after + * the last user has put the reference to it. + */ +static void put_fw_mgmt(struct fw_mgmt *fw_mgmt) +{ + kref_put(&fw_mgmt->kref, fw_mgmt_kref_release); +} + +/* Caller must call put_fw_mgmt() after using struct fw_mgmt */ +static struct fw_mgmt *get_fw_mgmt(struct cdev *cdev) +{ + struct fw_mgmt *fw_mgmt; + + mutex_lock(&list_mutex); + + list_for_each_entry(fw_mgmt, &fw_mgmt_list, node) { + if (&fw_mgmt->cdev == cdev) { + kref_get(&fw_mgmt->kref); + goto unlock; + } + } + + fw_mgmt = NULL; + +unlock: + mutex_unlock(&list_mutex); + + return fw_mgmt; +} static int fw_mgmt_interface_fw_version_operation(struct fw_mgmt *fw_mgmt, struct fw_mgmt_ioc_get_fw *fw_info) @@ -318,10 +364,22 @@ static int fw_mgmt_backend_fw_updated_operation(struct gb_operation *op) static int fw_mgmt_open(struct inode *inode, struct file *file) { - struct fw_mgmt *fw_mgmt = container_of(inode->i_cdev, struct fw_mgmt, - cdev); + struct fw_mgmt *fw_mgmt = get_fw_mgmt(inode->i_cdev); - file->private_data = fw_mgmt; + /* fw_mgmt structure can't get freed until file descriptor is closed */ + if (fw_mgmt) { + file->private_data = fw_mgmt; + return 0; + } + + return -ENODEV; +} + +static int fw_mgmt_release(struct inode *inode, struct file *file) +{ + struct fw_mgmt *fw_mgmt = file->private_data; + + put_fw_mgmt(fw_mgmt); return 0; } @@ -437,18 +495,23 @@ static long fw_mgmt_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg) { struct fw_mgmt *fw_mgmt = file->private_data; - int ret; + int ret = -ENODEV; /* - * Serialize ioctls + * Serialize ioctls. * * We don't want the user to do few operations in parallel. For example, * updating Interface firmware in parallel for the same Interface. There * is no need to do things in parallel for speed and we can avoid having - * complicated for now. + * complicated code for now. + * + * This is also used to protect ->disabled, which is used to check if + * the connection is getting disconnected, so that we don't start any + * new operations. */ mutex_lock(&fw_mgmt->mutex); - ret = fw_mgmt_ioctl(fw_mgmt, cmd, (void __user *)arg); + if (!fw_mgmt->disabled) + ret = fw_mgmt_ioctl(fw_mgmt, cmd, (void __user *)arg); mutex_unlock(&fw_mgmt->mutex); return ret; @@ -457,6 +520,7 @@ static long fw_mgmt_ioctl_unlocked(struct file *file, unsigned int cmd, static const struct file_operations fw_mgmt_fops = { .owner = THIS_MODULE, .open = fw_mgmt_open, + .release = fw_mgmt_release, .unlocked_ioctl = fw_mgmt_ioctl_unlocked, }; @@ -496,10 +560,15 @@ int gb_fw_mgmt_connection_init(struct gb_connection *connection) init_completion(&fw_mgmt->completion); ida_init(&fw_mgmt->id_map); mutex_init(&fw_mgmt->mutex); + kref_init(&fw_mgmt->kref); + + mutex_lock(&list_mutex); + list_add(&fw_mgmt->node, &fw_mgmt_list); + mutex_unlock(&list_mutex); ret = gb_connection_enable(connection); if (ret) - goto err_destroy_ida; + goto err_list_del; minor = ida_simple_get(&fw_mgmt_minors_map, 0, NUM_MINORS, GFP_KERNEL); if (minor < 0) { @@ -532,9 +601,12 @@ err_remove_ida: ida_simple_remove(&fw_mgmt_minors_map, minor); err_connection_disable: gb_connection_disable(connection); -err_destroy_ida: - ida_destroy(&fw_mgmt->id_map); - kfree(fw_mgmt); +err_list_del: + mutex_lock(&list_mutex); + list_del(&fw_mgmt->node); + mutex_unlock(&list_mutex); + + put_fw_mgmt(fw_mgmt); return ret; } @@ -547,13 +619,33 @@ void gb_fw_mgmt_connection_exit(struct gb_connection *connection) return; fw_mgmt = gb_connection_get_data(connection); + device_destroy(fw_mgmt_class, fw_mgmt->dev_num); cdev_del(&fw_mgmt->cdev); ida_simple_remove(&fw_mgmt_minors_map, MINOR(fw_mgmt->dev_num)); + + /* + * Disallow any new ioctl operations on the char device and wait for + * existing ones to finish. + */ + mutex_lock(&fw_mgmt->mutex); + fw_mgmt->disabled = true; + mutex_unlock(&fw_mgmt->mutex); + + /* All pending greybus operations should have finished by now */ gb_connection_disable(fw_mgmt->connection); - ida_destroy(&fw_mgmt->id_map); - kfree(fw_mgmt); + /* Disallow new users to get access to the fw_mgmt structure */ + mutex_lock(&list_mutex); + list_del(&fw_mgmt->node); + mutex_unlock(&list_mutex); + + /* + * All current users of fw_mgmt would have taken a reference to it by + * now, we can drop our reference and wait the last user will get + * fw_mgmt freed. + */ + put_fw_mgmt(fw_mgmt); } int fw_mgmt_init(void) -- cgit v0.10.2 From e2386c9327ab30288f995fc23fb97a3f21b08787 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Sat, 14 May 2016 23:42:24 +0530 Subject: greybus: firmware: Add SPI protocol support This patch adds SPI Protocol support to firmware core, which allows the AP to access an SPI flash memory present with an Interface. Tested by using the API from fw-management driver and compiling it. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/fw-core.c b/drivers/staging/greybus/fw-core.c index 0a456c5..90d3222 100644 --- a/drivers/staging/greybus/fw-core.c +++ b/drivers/staging/greybus/fw-core.c @@ -11,10 +11,12 @@ #include <linux/firmware.h> #include "firmware.h" #include "greybus.h" +#include "spilib.h" struct gb_fw_core { struct gb_connection *download_connection; struct gb_connection *mgmt_connection; + struct gb_connection *spi_connection; }; struct gb_connection *to_fw_mgmt_connection(struct device *dev) @@ -24,6 +26,35 @@ struct gb_connection *to_fw_mgmt_connection(struct device *dev) return fw_core->mgmt_connection; } +static int gb_fw_spi_connection_init(struct gb_connection *connection) +{ + int ret; + + if (!connection) + return 0; + + ret = gb_connection_enable(connection); + if (ret) + return ret; + + ret = gb_spilib_master_init(connection, &connection->bundle->dev); + if (ret) { + gb_connection_disable(connection); + return ret; + } + + return 0; +} + +static void gb_fw_spi_connection_exit(struct gb_connection *connection) +{ + if (!connection) + return; + + gb_spilib_master_exit(connection); + gb_connection_disable(connection); +} + static int gb_fw_core_probe(struct gb_bundle *bundle, const struct greybus_bundle_id *id) { @@ -85,6 +116,25 @@ static int gb_fw_core_probe(struct gb_bundle *bundle, } break; + case GREYBUS_PROTOCOL_SPI: + /* Disallow multiple SPI CPorts */ + if (fw_core->spi_connection) { + dev_err(&bundle->dev, + "multiple SPI CPorts found\n"); + ret = -EINVAL; + goto err_destroy_connections; + } + + connection = gb_connection_create(bundle, cport_id, + NULL); + if (IS_ERR(connection)) { + dev_err(&bundle->dev, "failed to create SPI connection (%ld)\n", + PTR_ERR(connection)); + } else { + fw_core->spi_connection = connection; + } + + break; default: dev_err(&bundle->dev, "invalid protocol id (0x%02x)\n", protocol_id); @@ -109,6 +159,15 @@ static int gb_fw_core_probe(struct gb_bundle *bundle, fw_core->download_connection = NULL; } + ret = gb_fw_spi_connection_init(fw_core->spi_connection); + if (ret) { + /* We may still be able to work with the Interface */ + dev_err(&bundle->dev, "failed to initialize SPI connection, disable it (%d)\n", + ret); + gb_connection_destroy(fw_core->spi_connection); + fw_core->spi_connection = NULL; + } + ret = gb_fw_mgmt_connection_init(fw_core->mgmt_connection); if (ret) { /* We may still be able to work with the Interface */ @@ -122,9 +181,11 @@ static int gb_fw_core_probe(struct gb_bundle *bundle, return 0; err_exit_connections: + gb_fw_spi_connection_exit(fw_core->spi_connection); gb_fw_download_connection_exit(fw_core->download_connection); err_destroy_connections: gb_connection_destroy(fw_core->mgmt_connection); + gb_connection_destroy(fw_core->spi_connection); gb_connection_destroy(fw_core->download_connection); err_free_fw_core: kfree(fw_core); @@ -137,9 +198,11 @@ static void gb_fw_core_disconnect(struct gb_bundle *bundle) struct gb_fw_core *fw_core = greybus_get_drvdata(bundle); gb_fw_mgmt_connection_exit(fw_core->mgmt_connection); + gb_fw_spi_connection_exit(fw_core->spi_connection); gb_fw_download_connection_exit(fw_core->download_connection); gb_connection_destroy(fw_core->mgmt_connection); + gb_connection_destroy(fw_core->spi_connection); gb_connection_destroy(fw_core->download_connection); kfree(fw_core); -- cgit v0.10.2 From 7bf7fa12fcb24fccb99d7957e44b8be6e0b82986 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Sat, 14 May 2016 23:42:25 +0530 Subject: greybus: Documentation: Document firmware-management interfaces This patch adds a new 'firmware' folder in Documentation, which contains two files: - firmware-management: This describes the userspace interface for interacting with firmware-management bundle. - firmware.c: Sample application to test firmware load for Interface Firmware and firmware updates to Backend Interface Firmware. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Jun Li <li_jun@projectara.com> Tested-by: Karthik Ravi Shankar <karthikrs@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/firmware/firmware-management b/drivers/staging/greybus/Documentation/firmware/firmware-management new file mode 100644 index 0000000..f70d3cd --- /dev/null +++ b/drivers/staging/greybus/Documentation/firmware/firmware-management @@ -0,0 +1,190 @@ + +Firmware Management +------------------- + Copyright 2016 Google Inc. + Copyright 2016 Linaro Ltd. + +Interface-Manifest +------------------ + +All firmware packages on the Modules or Interfaces are managed by a special +Firmware Management Protocol. To support Firmware Management by the AP, the +Interface Manifest shall at least contain the Firmware Management Bundle and a +Firmware Management Protocol CPort within it. + +The bundle may contain additional CPorts based on the extra functionality +required to manage firmware packages. + +For example, this is how the Firmware Management part of the Interface Manifest +may look like: + + ; Firmware Management Bundle (Bundle 1): + [bundle-descriptor 1] + class = 0x16 + + ; (Mandatory) Firmware Management Protocol on CPort 1 + [cport-descriptor 2] + bundle = 1 + protocol = 0x18 + + ; (Optional) Firmware Download Protocol on CPort 2 + [cport-descriptor 1] + bundle = 1 + protocol = 0x17 + + ; (Optional) SPI protocol on CPort 3 + [cport-descriptor 3] + bundle = 1 + protocol = 0x0b + + ; (Optional) Component Authentication Protocol (CAP) on CPort 4 + [cport-descriptor 4] + bundle = 1 + protocol = 0xXX //TBD + + + +Sysfs Interfaces - Firmware Management +-------------------------------------- + +The Firmware Management Protocol interacts with Userspace using the character +device interface. The character device will be present in /dev/ directory +and will be named fw-mgmt-<N>. The number <N> is assigned at runtime. + +Identifying the Character Device +================================ + +There can be multiple devices present in /dev/ directory with name fw-mgmt-N and +user first needs to identify the character device used for firmware-management +for a particular interface. + +The Firmware Management core creates a device of class 'gb_fw_mgmt', which shall +be used by the user to identify the right character device for it. The class +device is created within the Bundle directory for a particular Interface. + +For example this is how the class-device can be present: + +/sys/bus/greybus/devices/1-1/1-1.1/1-1.1.1/gb_fw_mgmt/fw-mgmt-0 + +The last name in this path: fw-mgmt-0 is precisely the name of the char device +and so the device in this case will be: + +/dev/fw-mgmt-0. + +Operations on the Char device +============================= + +The Character device (fw-mgmt-0 in example) can be opened by the userspace +application and it can perform various 'ioctl' operations on the device. The +device doesn't support any read/write operations. + +Following are the IOCTLs and their data structures available to the user: + +/* IOCTL support */ +#define GB_FW_LOAD_METHOD_UNIPRO 0x01 +#define GB_FW_LOAD_METHOD_INTERNAL 0x02 + +#define GB_FW_LOAD_STATUS_FAILED 0x00 +#define GB_FW_LOAD_STATUS_UNVALIDATED 0x01 +#define GB_FW_LOAD_STATUS_VALIDATED 0x02 +#define GB_FW_LOAD_STATUS_VALIDATION_FAILED 0x03 + +#define GB_FW_BACKEND_FW_STATUS_SUCCESS 0x01 +#define GB_FW_BACKEND_FW_STATUS_FAIL_FIND 0x02 +#define GB_FW_BACKEND_FW_STATUS_FAIL_FETCH 0x03 +#define GB_FW_BACKEND_FW_STATUS_FAIL_WRITE 0x04 +#define GB_FW_BACKEND_FW_STATUS_INT 0x05 + +struct fw_mgmt_ioc_get_fw { + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_LEN]; + __u16 major; + __u16 minor; +} __packed; + +struct fw_mgmt_ioc_intf_load_and_validate { + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_LEN]; + __u8 load_method; + __u8 status; + __u16 major; + __u16 minor; +} __packed; + +struct fw_mgmt_ioc_backend_fw_update { + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_LEN]; + __u8 status; +} __packed; + +#define FW_MGMT_IOCTL_BASE 'S' +#define FW_MGMT_IOC_GET_INTF_FW _IOR(FW_MGMT_IOCTL_BASE, 0, struct fw_mgmt_ioc_get_fw) +#define FW_MGMT_IOC_GET_BACKEND_FW _IOWR(FW_MGMT_IOCTL_BASE, 1, struct fw_mgmt_ioc_get_fw) +#define FW_MGMT_IOC_INTF_LOAD_AND_VALIDATE _IOWR(FW_MGMT_IOCTL_BASE, 2, struct fw_mgmt_ioc_intf_load_and_validate) +#define FW_MGMT_IOC_INTF_BACKEND_FW_UPDATE _IOWR(FW_MGMT_IOCTL_BASE, 3, struct fw_mgmt_ioc_backend_fw_update) +#define FW_MGMT_IOC_SET_TIMEOUT_MS _IOW(FW_MGMT_IOCTL_BASE, 4, unsigned int) +#define FW_MGMT_IOC_MODE_SWITCH _IO(FW_MGMT_IOCTL_BASE, 5) + +1. FW_MGMT_IOC_GET_INTF_FW: + + This ioctl shall be used the user to get the version and firmware-tag of the + currently running Interface Firmware. All the fields of the 'struct + fw_mgmt_ioc_get_fw' are filled by the kernel. + +2. FW_MGMT_IOC_GET_BACKEND_FW: + + This ioctl shall be used the user to get the version of a currently running + Backend Interface Firmware identified by a firmware-tag. The user is required + to fill the 'firmware_tag' field of the 'struct fw_mgmt_ioc_get_fw' in this + case. The 'major' and 'minor' fields are set by the kernel in response. + +3. FW_MGMT_IOC_INTF_LOAD_AND_VALIDATE: + + This ioctl shall be used the user to load an Interface Firmware package on an + Interface. The user needs to fill the 'firmware_tag' and 'load_method' fields + of the 'struct fw_mgmt_ioc_intf_load_and_validate'. The 'status', 'major' and + 'minor' fields are set by the kernel in response. + +4. FW_MGMT_IOC_INTF_BACKEND_FW_UPDATE: + + This ioctl shall be used the user to request an Interface to update a Backend + Interface Firmware. The user is required to fill the 'firmware_tag' field of + the 'struct fw_mgmt_ioc_get_fw' in this case. The 'status' field is set by + the kernel in response. + +5. FW_MGMT_IOC_SET_TIMEOUT_MS: + + This ioctl shall be used the user to increase the timeout interval within + which the firmware must get loaded by the Module. The default timeout is 1 + second. The user needs to pass the timeout in milliseconds. + +6. FW_MGMT_IOC_MODE_SWITCH: + + This ioctl shall be used the user to mode-switch the module to the previously + loaded interface firmware. If the interface firmware isn't loaded previously, + or if another unsuccessful FW_MGMT_IOC_INTF_LOAD_AND_VALIDATE operation is + started after loading interface firmware, then the firmware core wouldn't + allow mode-switch. + + +Sysfs Interfaces - Firmware Download +------------------------------------ + +The Firmware Download Protocol uses the existing Linux Kernel's Firmware class +and the interface provided to userspace are described in: +Documentation/firmware_class/. + + +Sysfs Interfaces - SPI Flash +---------------------------- + +The SPI flash is exposed in userspace as a MTD device and is created +within the Bundle directory. For example, this is how the path may look like: + +$ ls /sys/bus/greybus/devices/1-1/1-1.1/1-1.1.1/spi_master/spi32766/spi32766.0/mtd +mtd0 mtd0ro + + +Sample Application +------------------ + +The current directly also provides a firmware.c test application, which can be +referenced while developing userspace application to talk to firmware-management +protocol. diff --git a/drivers/staging/greybus/Documentation/firmware/firmware.c b/drivers/staging/greybus/Documentation/firmware/firmware.c new file mode 100644 index 0000000..e367860 --- /dev/null +++ b/drivers/staging/greybus/Documentation/firmware/firmware.c @@ -0,0 +1,146 @@ +/* Sample code to test firmware-management protocol */ + +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include "../../greybus_firmware.h" + +static const char *firmware_tag = "03"; /* S3 firmware */ + +static struct fw_mgmt_ioc_get_fw fw_info; +static struct fw_mgmt_ioc_intf_load_and_validate intf_load; +static struct fw_mgmt_ioc_backend_fw_update backend_update; + +int main(int argc, char *argv[]) +{ + unsigned int timeout = 10000; + char *fwdev; + int fd, ret; + + /* Make sure arguments are correct */ + if (argc != 2) { + printf("\nUsage: ./firmware <Path of the fw-mgmt-X dev>\n"); + return 0; + } + + fwdev = argv[1]; + + printf("Opening %s firmware management device\n", fwdev); + + fd = open(fwdev, O_RDWR); + if (fd < 0) { + printf("Failed to open: %s\n", fwdev); + ret = -1; + goto close_fd; + } + + /* Set Timeout */ + printf("Setting timeout to %u ms\n", timeout); + + ret = ioctl(fd, FW_MGMT_IOC_SET_TIMEOUT_MS, &timeout); + if (ret < 0) { + printf("Failed to set timeout: %s (%d)\n", fwdev, ret); + ret = -1; + goto close_fd; + } + + /* Get Interface Firmware Version */ + printf("Get Interface Firmware Version\n"); + + ret = ioctl(fd, FW_MGMT_IOC_GET_INTF_FW, &fw_info); + if (ret < 0) { + printf("Failed to get interface firmware version: %s (%d)\n", + fwdev, ret); + ret = -1; + goto close_fd; + } + + printf("Interface Firmware tag (%s), major (%d), minor (%d)\n", + fw_info.firmware_tag, fw_info.major, fw_info.minor); + + /* Try Interface Firmware load over Unipro */ + printf("Loading Interface Firmware\n"); + + intf_load.load_method = GB_FW_U_LOAD_METHOD_UNIPRO; + intf_load.status = 0; + intf_load.major = 0; + intf_load.minor = 0; + strncpy((char *)&intf_load.firmware_tag, firmware_tag, + GB_FIRMWARE_U_TAG_MAX_LEN); + + ret = ioctl(fd, FW_MGMT_IOC_INTF_LOAD_AND_VALIDATE, &intf_load); + if (ret < 0) { + printf("Failed to load interface firmware: %s (%d)\n", fwdev, + ret); + ret = -1; + goto close_fd; + } + + if (intf_load.status != GB_FW_U_LOAD_STATUS_VALIDATED && + intf_load.status != GB_FW_U_LOAD_STATUS_UNVALIDATED) { + printf("Load status says loading failed: %d\n", + intf_load.status); + ret = -1; + goto close_fd; + } + + printf("Interface Firmware (%s) Load done: major: %d, minor: %d, status: %d\n", + firmware_tag, intf_load.major, intf_load.minor, + intf_load.status); + + /* Get Backend Firmware Version */ + printf("Getting Backend Firmware Version\n"); + + strncpy((char *)&fw_info.firmware_tag, firmware_tag, + GB_FIRMWARE_U_TAG_MAX_LEN); + fw_info.major = 0; + fw_info.minor = 0; + + ret = ioctl(fd, FW_MGMT_IOC_GET_BACKEND_FW, &fw_info); + if (ret < 0) { + printf("Failed to get backend firmware version: %s (%d)\n", + fwdev, ret); + goto mode_switch; + } + + printf("Backend Firmware tag (%s), major (%d), minor (%d)\n", + fw_info.firmware_tag, fw_info.major, fw_info.minor); + + /* Try Backend Firmware Update over Unipro */ + printf("Updating Backend Firmware\n"); + + backend_update.status = 0; + strncpy((char *)&backend_update.firmware_tag, firmware_tag, + GB_FIRMWARE_U_TAG_MAX_LEN); + + ret = ioctl(fd, FW_MGMT_IOC_INTF_BACKEND_FW_UPDATE, &backend_update); + if (ret < 0) { + printf("Failed to load backend firmware: %s (%d)\n", fwdev, ret); + goto mode_switch; + } + + printf("Backend Firmware (%s) Load done: status: %d\n", + firmware_tag, backend_update.status); + + if (backend_update.status != GB_FW_U_BACKEND_FW_STATUS_SUCCESS) { + printf("Load status says loading failed: %d\n", + backend_update.status); + } + +mode_switch: + /* Initiate Mode-switch to the newly loaded firmware */ + printf("Initiate Mode switch\n"); + + ret = ioctl(fd, FW_MGMT_IOC_MODE_SWITCH); + if (ret < 0) + printf("Failed to initiate mode-switch (%d)\n", ret); + +close_fd: + close(fd); + + return ret; +} -- cgit v0.10.2 From c8a657ba3f84643d7ef4b13ff6828e141172419a Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Sun, 15 May 2016 19:37:48 +0100 Subject: greybus: hd: Add TimeSync APBridge commands This patch adds a number of USB Vendor commands to es2.c to enable TimeSync in the bridge. Adds: - es2.c::timesync_enable(u8 count, u64 frame_time, u32 strobe_delay, u32 refclk); Commands APBx to enable timers and clocks to track a pulse-train of incoming TIME_SYNC strobes with strobe_delay microseconds between each. Provides the reference clock the AP is using to track FrameTime. It is the responsibility of APBx to adequately track the FrameTime based on the indicated AP refclk. Once this command has succeeded APBx may not transition to a low-power state were FrameTime counters stop. This function is initiated from the timesync worker thread logic when re-synchronizing frame-time throughout the system. TimeSync is at this time enabled for all APBx active in the system i.e. currently APB2 will not receive TimeSync commands until it becomes a registered host-device in Greybus. - es2.c::timesync_disable(void) Commands APBx to discontinue tracking of FrameTime. After this operation completes APBx may transition to a low-power state where timer-clocks stop operating. - es2.c::timesync_authoritative(u64 *frame_time) Provides an authoritative time for each TIME_SYNC strobe to APBx. APBx must align its local FrameTime to the authoritative clock. - es2.c::timesync_get_last_event(u64 *frame_time) Returns the FrameTime at the last SVC_TIMESYNC_PING to the AP Module. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 998b41e..d6abfda 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -121,6 +121,29 @@ struct cport_to_ep { __u8 endpoint_out; }; +/** + * timesync_enable_request - Enable timesync in an APBridge + * @count: number of TimeSync Pulses to expect + * @frame_time: the initial FrameTime at the first TimeSync Pulse + * @strobe_delay: the expected delay in microseconds between each TimeSync Pulse + * @refclk: The AP mandated reference clock to run FrameTime at + */ +struct timesync_enable_request { + __u8 count; + __le64 frame_time; + __le32 strobe_delay; + __le32 refclk; +} __packed; + +/** + * timesync_authoritative_request - Transmit authoritative FrameTime to APBridge + * @frame_time: An array of authoritative FrameTimes provided by the SVC + * and relayed to the APBridge by the AP + */ +struct timesync_authoritative_request { + __le64 frame_time[GB_TIMESYNC_MAX_STROBES]; +} __packed; + static inline struct es2_ap_dev *hd_to_es2(struct gb_host_device *hd) { return (struct es2_ap_dev *)&hd->hd_priv; @@ -674,18 +697,126 @@ static int cport_features_disable(struct gb_host_device *hd, u16 cport_id) return retval; } +static int timesync_enable(struct gb_host_device *hd, u8 count, + u64 frame_time, u32 strobe_delay, u32 refclk) +{ + int retval; + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct usb_device *udev = es2->usb_dev; + struct gb_control_timesync_enable_request *request; + + request = kzalloc(sizeof(*request), GFP_KERNEL); + if (!request) + return -ENOMEM; + + request->count = count; + request->frame_time = cpu_to_le64(frame_time); + request->strobe_delay = cpu_to_le32(strobe_delay); + request->refclk = cpu_to_le32(refclk); + retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + REQUEST_TIMESYNC_ENABLE, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, 0, 0, request, + sizeof(*request), ES2_TIMEOUT); + if (retval < 0) + dev_err(&udev->dev, "Cannot enable timesync %d\n", retval); + + kfree(request); + return retval; +} + +static int timesync_disable(struct gb_host_device *hd) +{ + int retval; + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct usb_device *udev = es2->usb_dev; + + retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + REQUEST_TIMESYNC_DISABLE, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, 0, 0, NULL, + 0, ES2_TIMEOUT); + if (retval < 0) + dev_err(&udev->dev, "Cannot disable timesync %d\n", retval); + + return retval; +} + +static int timesync_authoritative(struct gb_host_device *hd, u64 *frame_time) +{ + int retval, i; + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct usb_device *udev = es2->usb_dev; + struct timesync_authoritative_request *request; + + request = kzalloc(sizeof(*request), GFP_KERNEL); + if (!request) + return -ENOMEM; + + for (i = 0; i < GB_TIMESYNC_MAX_STROBES; i++) + request->frame_time[i] = cpu_to_le64(frame_time[i]); + + retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + REQUEST_TIMESYNC_AUTHORITATIVE, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, 0, 0, request, + sizeof(*request), ES2_TIMEOUT); + if (retval < 0) + dev_err(&udev->dev, "Cannot timesync authoritative out %d\n", retval); + + kfree(request); + return retval; +} + +static int timesync_get_last_event(struct gb_host_device *hd, u64 *frame_time) +{ + int retval; + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct usb_device *udev = es2->usb_dev; + u64 *response_frame_time; + + response_frame_time = kzalloc(sizeof(*response_frame_time), GFP_KERNEL); + if (!response_frame_time) + return -ENOMEM; + + retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + REQUEST_TIMESYNC_GET_LAST_EVENT, + USB_DIR_IN | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, 0, 0, response_frame_time, + sizeof(*response_frame_time), ES2_TIMEOUT); + + if (retval != sizeof(*response_frame_time)) { + dev_err(&udev->dev, "Cannot get last TimeSync event: %d\n", + retval); + + if (retval >= 0) + retval = -EIO; + + goto out; + } + *frame_time = le64_to_cpu(*response_frame_time); + retval = 0; +out: + kfree(response_frame_time); + return retval; +} + static struct gb_hd_driver es2_driver = { - .hd_priv_size = sizeof(struct es2_ap_dev), - .message_send = message_send, - .message_cancel = message_cancel, - .cport_allocate = es2_cport_allocate, - .cport_release = es2_cport_release, - .cport_enable = cport_enable, - .latency_tag_enable = latency_tag_enable, - .latency_tag_disable = latency_tag_disable, - .output = output, - .cport_features_enable = cport_features_enable, - .cport_features_disable = cport_features_disable, + .hd_priv_size = sizeof(struct es2_ap_dev), + .message_send = message_send, + .message_cancel = message_cancel, + .cport_allocate = es2_cport_allocate, + .cport_release = es2_cport_release, + .cport_enable = cport_enable, + .latency_tag_enable = latency_tag_enable, + .latency_tag_disable = latency_tag_disable, + .output = output, + .cport_features_enable = cport_features_enable, + .cport_features_disable = cport_features_disable, + .timesync_enable = timesync_enable, + .timesync_disable = timesync_disable, + .timesync_authoritative = timesync_authoritative, + .timesync_get_last_event = timesync_get_last_event, }; /* Common function to report consistent warnings based on URB status */ diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index e3ad5d7..d379fe3 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -188,30 +188,36 @@ struct gb_control_timesync_get_last_event_response { /* APBridge protocol */ /* request APB1 log */ -#define GB_APB_REQUEST_LOG 0x02 +#define GB_APB_REQUEST_LOG 0x02 /* request to map a cport to bulk in and bulk out endpoints */ -#define GB_APB_REQUEST_EP_MAPPING 0x03 +#define GB_APB_REQUEST_EP_MAPPING 0x03 /* request to get the number of cports available */ -#define GB_APB_REQUEST_CPORT_COUNT 0x04 +#define GB_APB_REQUEST_CPORT_COUNT 0x04 /* request to reset a cport state */ -#define GB_APB_REQUEST_RESET_CPORT 0x05 +#define GB_APB_REQUEST_RESET_CPORT 0x05 /* request to time the latency of messages on a given cport */ -#define GB_APB_REQUEST_LATENCY_TAG_EN 0x06 -#define GB_APB_REQUEST_LATENCY_TAG_DIS 0x07 +#define GB_APB_REQUEST_LATENCY_TAG_EN 0x06 +#define GB_APB_REQUEST_LATENCY_TAG_DIS 0x07 /* request to control the CSI transmitter */ -#define GB_APB_REQUEST_CSI_TX_CONTROL 0x08 +#define GB_APB_REQUEST_CSI_TX_CONTROL 0x08 /* request to control the CSI transmitter */ -#define GB_APB_REQUEST_AUDIO_CONTROL 0x09 +#define GB_APB_REQUEST_AUDIO_CONTROL 0x09 /* vendor requests to enable/disable CPort features */ -#define GB_APB_REQUEST_CPORT_FEAT_EN 0x0b -#define GB_APB_REQUEST_CPORT_FEAT_DIS 0x0c +#define GB_APB_REQUEST_CPORT_FEAT_EN 0x0b +#define GB_APB_REQUEST_CPORT_FEAT_DIS 0x0c + +/* TimeSync commands */ +#define REQUEST_TIMESYNC_ENABLE 0x0d +#define REQUEST_TIMESYNC_DISABLE 0x0e +#define REQUEST_TIMESYNC_AUTHORITATIVE 0x0f +#define REQUEST_TIMESYNC_GET_LAST_EVENT 0x10 /* Firmware Download Protocol */ diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h index 80573ae..8510816 100644 --- a/drivers/staging/greybus/hd.h +++ b/drivers/staging/greybus/hd.h @@ -30,6 +30,13 @@ struct gb_hd_driver { bool async); int (*cport_features_enable)(struct gb_host_device *hd, u16 cport_id); int (*cport_features_disable)(struct gb_host_device *hd, u16 cport_id); + int (*timesync_enable)(struct gb_host_device *hd, u8 count, + u64 frame_time, u32 strobe_delay, u32 refclk); + int (*timesync_disable)(struct gb_host_device *hd); + int (*timesync_authoritative)(struct gb_host_device *hd, + u64 *frame_time); + int (*timesync_get_last_event)(struct gb_host_device *hd, + u64 *frame_time); }; struct gb_host_device { -- cgit v0.10.2 From 8c81d4608dc54225005129e32cf5d2035176df5e Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Sun, 15 May 2016 19:37:49 +0100 Subject: greybus: interface: Extract and store Interface feature byte The Interface description in the Greybus specification contains a 'features' field which is currently not implemented on the AP side. The Interface features field provides information on optional attributes of an Interface as a bitmask. Currently only GREYBUS_INTERFACE_FEATURE_TIMESYNC is implemented in the specification but, the expectation is that other feature flags will be added over time. This patch adds support to extract the feature byte communicated in the features field of the Interface Descriptor header and extends struct interface to contain a features field through which any user with a pointer to struct interface may interrogate the features of an Interface. This is a necessary pre-cursor for TimeSync to ensure only Interfaces which declare GREYBUS_INTERFACE_FEATURE_TIMESYNC will be included when we go through the process of FrameTime synchronization. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 4f70190..28bbadd 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -81,6 +81,10 @@ enum greybus_class_type { GREYBUS_CLASS_VENDOR = 0xff, }; +enum { + GREYBUS_INTERFACE_FEATURE_TIMESYNC = BIT(0), +}; + /* * The string in a string descriptor is not NUL-terminated. The * size of the descriptor will be rounded up to a multiple of 4 @@ -99,7 +103,8 @@ struct greybus_descriptor_string { struct greybus_descriptor_interface { __u8 vendor_stringid; __u8 product_stringid; - __u8 pad[2]; + __u8 features; + __u8 pad; } __packed; /* diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 1a25234..51772cc 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -23,6 +23,7 @@ struct gb_interface { struct list_head manifest_descs; u8 interface_id; /* Physical location within the Endo */ u8 device_id; + u8 features; /* Feature flags set in the manifest */ u32 ddbl1_manufacturer_id; u32 ddbl1_product_id; diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 886c5fb..529a984 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -398,6 +398,9 @@ static bool gb_manifest_parse_interface(struct gb_interface *intf, goto out_free_vendor_string; control->product_string = str; + /* Assign feature flags communicated via manifest */ + intf->features = desc_intf->features; + /* Release the interface descriptor, now that we're done with it */ release_manifest_descriptor(interface_desc); -- cgit v0.10.2 From 5319a889eafc5c8c13ef51e38fed224c4c3b33f2 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Sun, 15 May 2016 23:34:51 +0100 Subject: greybus: es2.c: Declare local __le64 not u64 The value passed to le64_to_cpu wants to be an __le64 not a u64. Note to self - remember to run "make check" Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Reported-by: Greg Kroah-Hartman <gregkh@google.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index d6abfda..947ebae 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -773,7 +773,7 @@ static int timesync_get_last_event(struct gb_host_device *hd, u64 *frame_time) int retval; struct es2_ap_dev *es2 = hd_to_es2(hd); struct usb_device *udev = es2->usb_dev; - u64 *response_frame_time; + __le64 *response_frame_time; response_frame_time = kzalloc(sizeof(*response_frame_time), GFP_KERNEL); if (!response_frame_time) -- cgit v0.10.2 From e27f1da93f00f33db2559be69ea5efc9c2f28de4 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 16 May 2016 07:49:45 +0530 Subject: greybus: fw-management: Replace double-tabs with space for structures Reformat structures to use a single space instead of multiple tabs. Reported-by: Greg Kroah-Hartman <gregkh@google.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_firmware.h b/drivers/staging/greybus/greybus_firmware.h index 4e194f2..0232260 100644 --- a/drivers/staging/greybus/greybus_firmware.h +++ b/drivers/staging/greybus/greybus_firmware.h @@ -55,22 +55,22 @@ /* IOCTL support */ struct fw_mgmt_ioc_get_fw { - __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_LEN]; - __u16 major; - __u16 minor; + __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_LEN]; + __u16 major; + __u16 minor; } __attribute__ ((__packed__)); struct fw_mgmt_ioc_intf_load_and_validate { - __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_LEN]; - __u8 load_method; - __u8 status; - __u16 major; - __u16 minor; + __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_LEN]; + __u8 load_method; + __u8 status; + __u16 major; + __u16 minor; } __attribute__ ((__packed__)); struct fw_mgmt_ioc_backend_fw_update { - __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_LEN]; - __u8 status; + __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_LEN]; + __u8 status; } __attribute__ ((__packed__)); #define FW_MGMT_IOCTL_BASE 'F' -- cgit v0.10.2 From 79b140fe2b6f2db8c4a4a45bde6065fc34b24e77 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 16 May 2016 07:49:43 +0530 Subject: greybus: fw-management: Fix 'make check' warnings Fix below warnings observed with 'make check'. ~/ara/greybus/fw-management.c:438:33: warning: incorrect type in assignment (different base types) ~/ara/greybus/fw-management.c:438:33: expected unsigned short [unsigned] [addressable] [assigned] [usertype] major ~/ara/greybus/fw-management.c:438:33: got restricted __le16 [usertype] <noident> ~/ara/greybus/fw-management.c:439:33: warning: incorrect type in assignment (different base types) ~/ara/greybus/fw-management.c:439:33: expected unsigned short [unsigned] [addressable] [assigned] [usertype] minor ~/ara/greybus/fw-management.c:439:33: got restricted __le16 [usertype] <noident> Reported-by: Greg Kroah-Hartman <gregkh@google.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/fw-management.c b/drivers/staging/greybus/fw-management.c index 0c73f1e..96758f4 100644 --- a/drivers/staging/greybus/fw-management.c +++ b/drivers/staging/greybus/fw-management.c @@ -434,8 +434,8 @@ static int fw_mgmt_ioctl(struct fw_mgmt *fw_mgmt, unsigned int cmd, } intf_load.status = fw_mgmt->intf_fw_status; - intf_load.major = cpu_to_le16(fw_mgmt->intf_fw_major); - intf_load.minor = cpu_to_le16(fw_mgmt->intf_fw_minor); + intf_load.major = fw_mgmt->intf_fw_major; + intf_load.minor = fw_mgmt->intf_fw_minor; if (copy_to_user(buf, &intf_load, sizeof(intf_load))) return -EFAULT; -- cgit v0.10.2 From 3b077247b6499aa5bf2183968be8cb6ad675171c Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 16 May 2016 20:54:53 +0530 Subject: greybus: fw-management: Update header's license The header should include both BSD and GPLv2 licenses and so should have been a copy of greybus_protocols.h. This file had only the GPLv2 bits earlier, update it to include BSD bits as well. Reported-by: Greg Kroah-Hartman <gregkh@google.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_firmware.h b/drivers/staging/greybus/greybus_firmware.h index 0232260..1b68821 100644 --- a/drivers/staging/greybus/greybus_firmware.h +++ b/drivers/staging/greybus/greybus_firmware.h @@ -1,8 +1,8 @@ /* * Greybus Firmware Management User Header * - * This file is provided under the GPLv2 license. When using or - * redistributing this file, you may do so under that license. + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * @@ -18,6 +18,26 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details. * + * BSD LICENSE + * + * Copyright(c) 2016 Google Inc. All rights reserved. + * Copyright(c) 2016 Linaro Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. or Linaro Ltd. nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * * 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 -- cgit v0.10.2 From 22e26a3a13503f3c35ed8bbb6a7e9e33ad2c6987 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva <rui.silva@linaro.org> Date: Mon, 16 May 2016 10:33:20 +0100 Subject: greybus: spi: rename rdwr field to xfer_flags As more bits will be added to the field, let's make the field more generic and name it accordingly. So, rename it from rdwr to xfer_flags. Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index d379fe3..0cddbb6 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -876,7 +876,7 @@ struct gb_spi_transfer { __le16 delay_usecs; __u8 cs_change; __u8 bits_per_word; - __u8 rdwr; + __u8 xfer_flags; #define GB_SPI_XFER_READ 0x01 #define GB_SPI_XFER_WRITE 0x02 } __packed; diff --git a/drivers/staging/greybus/spilib.c b/drivers/staging/greybus/spilib.c index 6ab1c5f..9eecbf3 100644 --- a/drivers/staging/greybus/spilib.c +++ b/drivers/staging/greybus/spilib.c @@ -255,14 +255,14 @@ static struct gb_operation *gb_spi_operation_create(struct gb_spilib *spi, /* Copy tx data */ if (xfer->tx_buf) { - gb_xfer->rdwr |= GB_SPI_XFER_WRITE; + gb_xfer->xfer_flags |= GB_SPI_XFER_WRITE; memcpy(tx_data, xfer->tx_buf + spi->tx_xfer_offset, xfer_len); tx_data += xfer_len; } if (xfer->rx_buf) - gb_xfer->rdwr |= GB_SPI_XFER_READ; + gb_xfer->xfer_flags |= GB_SPI_XFER_READ; if (xfer == spi->last_xfer) { msg->state = GB_SPI_STATE_OP_DONE; -- cgit v0.10.2 From 3a238fc7844f93c799283d8b822178af9638ff0c Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva <rui.silva@linaro.org> Date: Mon, 16 May 2016 10:33:21 +0100 Subject: greybus: spi: add inprogress bit to xfer_flags When a SPI transfer needs to be split by more than one greybus spi transfer operation, we need to indicate it so the controller can handle the chip select lines correctly. Add a new bit to indicate it, GB_SPI_XFER_INPROGRESS, and create an helper function to calculate when the transfer is done. As we need this information also in other places. Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 0cddbb6..b98f02c 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -879,6 +879,7 @@ struct gb_spi_transfer { __u8 xfer_flags; #define GB_SPI_XFER_READ 0x01 #define GB_SPI_XFER_WRITE 0x02 +#define GB_SPI_XFER_INPROGRESS 0x04 } __packed; struct gb_spi_transfer_request { diff --git a/drivers/staging/greybus/spilib.c b/drivers/staging/greybus/spilib.c index 9eecbf3..79ae044 100644 --- a/drivers/staging/greybus/spilib.c +++ b/drivers/staging/greybus/spilib.c @@ -102,6 +102,17 @@ static void clean_xfer_state(struct gb_spilib *spi) spi->op_timeout = 0; } +static bool is_last_xfer_done(struct gb_spilib *spi) +{ + struct spi_transfer *last_xfer = spi->last_xfer; + + if ((spi->tx_xfer_offset + spi->last_xfer_size == last_xfer->len) || + (spi->rx_xfer_offset + spi->last_xfer_size == last_xfer->len)) + return true; + + return false; +} + static int setup_next_xfer(struct gb_spilib *spi, struct spi_message *msg) { struct spi_transfer *last_xfer = spi->last_xfer; @@ -113,8 +124,7 @@ static int setup_next_xfer(struct gb_spilib *spi, struct spi_message *msg) * if we transferred all content of the last transfer, reset values and * check if this was the last transfer in the message */ - if ((spi->tx_xfer_offset + spi->last_xfer_size == last_xfer->len) || - (spi->rx_xfer_offset + spi->last_xfer_size == last_xfer->len)) { + if (is_last_xfer_done(spi)) { spi->tx_xfer_offset = 0; spi->rx_xfer_offset = 0; spi->op_timeout = 0; @@ -265,6 +275,8 @@ static struct gb_operation *gb_spi_operation_create(struct gb_spilib *spi, gb_xfer->xfer_flags |= GB_SPI_XFER_READ; if (xfer == spi->last_xfer) { + if (!is_last_xfer_done(spi)) + gb_xfer->xfer_flags |= GB_SPI_XFER_INPROGRESS; msg->state = GB_SPI_STATE_OP_DONE; continue; } -- cgit v0.10.2 From b0e97bce153a416c4de4841078fba57b69de10f5 Mon Sep 17 00:00:00 2001 From: Eli Sennesh <esennesh@leaflabs.com> Date: Fri, 13 May 2016 13:27:40 -0400 Subject: greybus: operation: rate-limit dev_err printing on the receive path When we receive Greybus operations we don't recognize, requests or responses, en masse, we can pile up a lot of dev_err() printk messages. Doing so along the gb_connection_recv() code path can delay receive processing by up to seven milliseconds, starving the system of bulk-IN urbs. Rate limit those printk messages, ensuring that after too many repeated errors at the same place in the code-path, we'll stop printing to the console at all and let the urbs get returned. This will help prevent denial-of-service attacks on the AP through the UniPro network from malicious or malfunctioning modules. Testing Done: 7 msec recv-to-resubmit-urb processing times go down to <20 usecs Signed-off-by: Eli Sennesh <esennesh@leaflabs.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Reviewed-by: Mitchell Tasman <tasman@leaflabs.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 716627e..31df413 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -891,7 +891,7 @@ static void gb_connection_recv_response(struct gb_connection *connection, size_t message_size; if (!operation_id) { - dev_err(&connection->hd->dev, + dev_err_ratelimited(&connection->hd->dev, "%s: invalid response id 0 received\n", connection->name); return; @@ -899,9 +899,9 @@ static void gb_connection_recv_response(struct gb_connection *connection, operation = gb_operation_find_outgoing(connection, operation_id); if (!operation) { - dev_err(&connection->hd->dev, - "%s: unexpected response id 0x%04x received\n", - connection->name, operation_id); + dev_err_ratelimited(&connection->hd->dev, + "%s: unexpected response id 0x%04x received\n", + connection->name, operation_id); return; } @@ -909,7 +909,7 @@ static void gb_connection_recv_response(struct gb_connection *connection, header = message->header; message_size = sizeof(*header) + message->payload_size; if (!errno && size > message_size) { - dev_err(&connection->hd->dev, + dev_err_ratelimited(&connection->hd->dev, "%s: malformed response 0x%02x received (%zu > %zu)\n", connection->name, header->type, size, message_size); @@ -918,7 +918,7 @@ static void gb_connection_recv_response(struct gb_connection *connection, if (gb_operation_short_response_allowed(operation)) { message->payload_size = size - sizeof(*header); } else { - dev_err(&connection->hd->dev, + dev_err_ratelimited(&connection->hd->dev, "%s: short response 0x%02x received (%zu < %zu)\n", connection->name, header->type, size, message_size); @@ -956,13 +956,14 @@ void gb_connection_recv(struct gb_connection *connection, if ((connection->state != GB_CONNECTION_STATE_ENABLED && connection->state != GB_CONNECTION_STATE_ENABLED_TX) || gb_connection_is_offloaded(connection)) { - dev_warn(dev, "%s: dropping %zu received bytes\n", + dev_warn_ratelimited(dev, "%s: dropping %zu received bytes\n", connection->name, size); return; } if (size < sizeof(header)) { - dev_err(dev, "%s: short message received\n", connection->name); + dev_err_ratelimited(dev, "%s: short message received\n", + connection->name); return; } @@ -970,10 +971,11 @@ void gb_connection_recv(struct gb_connection *connection, memcpy(&header, data, sizeof(header)); msg_size = le16_to_cpu(header.size); if (size < msg_size) { - dev_err(dev, - "%s: incomplete message 0x%04x of type 0x%02x received (%zu < %zu)\n", - connection->name, le16_to_cpu(header.operation_id), - header.type, size, msg_size); + dev_err_ratelimited(dev, + "%s: incomplete message 0x%04x of type 0x%02x received (%zu < %zu)\n", + connection->name, + le16_to_cpu(header.operation_id), + header.type, size, msg_size); return; /* XXX Should still complete operation */ } -- cgit v0.10.2 From ef62adae82524c745640850f62ab0dfe0b580c9f Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 18 May 2016 15:47:48 +0200 Subject: greybus: operation: fix broken activation logic An operation should only be added to the connection active list if the connection is in the enabled state, or if it is in the enabled_tx state and the operation is not incoming. This fixes a race where an early or late incoming request could be added to the active list while the connection is being enabled or disabled, something which could lead to use-after-free issues or worse. Note that the early connection-state checks in the receive path limited the impact of this bug. Fixes: e903a2ce7379 ("connection: add unidirectional enabled state") Reported-by: Alex Elder <elder@linaro.org> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 31df413..b7cc59d 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -48,8 +48,8 @@ static int gb_operation_get_active(struct gb_operation *operation) spin_lock_irqsave(&connection->lock, flags); if (connection->state != GB_CONNECTION_STATE_ENABLED && - connection->state != GB_CONNECTION_STATE_ENABLED_TX && - !gb_operation_is_incoming(operation)) { + (connection->state != GB_CONNECTION_STATE_ENABLED_TX || + gb_operation_is_incoming(operation))) { spin_unlock_irqrestore(&connection->lock, flags); return -ENOTCONN; } -- cgit v0.10.2 From ac00154a7c6a8f3b2a98c1cf3cef893af2b0abac Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Tue, 17 May 2016 22:29:08 +0530 Subject: greybus: audio: gb_manager: Use valid argument while removing ida allocated id. module->id is used as an argument to ida_simple_remove(). Since module is already dereferenced, module->id might contain invalid data. So fix this. Fixes: da4cc2d0b066 ("audio:gb_manager: Use proper locking around kobject_xxx") Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_manager.c b/drivers/staging/greybus/audio_manager.c index 9def014..aa6508b 100644 --- a/drivers/staging/greybus/audio_manager.c +++ b/drivers/staging/greybus/audio_manager.c @@ -76,7 +76,7 @@ int gb_audio_manager_remove(int id) list_del(&module->list); kobject_put(&module->kobj); up_write(&modules_rwsem); - ida_simple_remove(&module_id, module->id); + ida_simple_remove(&module_id, id); return 0; } EXPORT_SYMBOL_GPL(gb_audio_manager_remove); -- cgit v0.10.2 From 814ae531d161d789496503969657ea9550e286b5 Mon Sep 17 00:00:00 2001 From: Alex Elder <elder@linaro.org> Date: Tue, 17 May 2016 09:13:16 -0500 Subject: greybus: connection: verify disabled when destroyed A connection must be in DISABLED state before it gets destroyed. Warn if this is ever not the case (and do the disconnect) before proceeding with connection destruction. Signed-off-by: Alex Elder <elder@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index f803d40..ac3be2f 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -660,6 +660,9 @@ void gb_connection_destroy(struct gb_connection *connection) if (!connection) return; + if (WARN_ON(connection->state != GB_CONNECTION_STATE_DISABLED)) + gb_connection_disable(connection); + mutex_lock(&gb_connection_mutex); spin_lock_irq(&gb_connections_lock); -- cgit v0.10.2 From 9bc63b7ff56f7a1cad5dbf062d1d5dd7a81d7d93 Mon Sep 17 00:00:00 2001 From: Axel Haslam <ahaslam@baylibre.com> Date: Mon, 16 May 2016 17:39:32 +0200 Subject: greybus: uart fix missing negation on DTR setting The unset the DTR flag is missing "~" Signed-off-by: Axel Haslam <ahaslam@baylibre.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index aa28ce5..75fa527 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -375,7 +375,7 @@ static void gb_tty_set_termios(struct tty_struct *tty, if (C_BAUD(tty) == B0) { newline.rate = gb_tty->line_coding.rate; - newctrl &= GB_UART_CTRL_DTR; + newctrl &= ~GB_UART_CTRL_DTR; } else if (termios_old && (termios_old->c_cflag & CBAUD) == B0) { newctrl |= GB_UART_CTRL_DTR; } -- cgit v0.10.2 From e16715c135d80aafea867849f938b080d4f4eadb Mon Sep 17 00:00:00 2001 From: Jeffrey Carlyle <jcarlyle@google.com> Date: Wed, 18 May 2016 18:55:13 -0700 Subject: greybus: interface: retry enumeration of UniPro-only modules Greybus modules will sometimes fail to send the mailbox poke and erroneously be enumerated as UniPro-only modules. The root cause for this on the module side is not fully understand, but it seems that this may be due to "the bootrom bug:" a known problem with the bootrom where linkup will occasionally fail because of a race condition. Before the new hotplug code was implemented in the firmware, the SVC would retry enumeration of modules that did not send the mailbox poke; this patch ports that functionality to the AP. Signed-off-by: Jeffrey Carlyle <jcarlyle@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index a1435e9..3b56693 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -447,7 +447,8 @@ static int gb_interface_activate_operation(struct gb_interface *intf) return -ENODEV; case GB_SVC_INTF_TYPE_UNIPRO: dev_err(&intf->dev, "interface type UniPro not supported\n"); - return -ENODEV; + /* FIXME: check if this is a Toshiba bridge before retrying? */ + return -EAGAIN; case GB_SVC_INTF_TYPE_GREYBUS: break; default: diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index 5077253..ea58954 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -138,13 +138,32 @@ static void gb_module_register_interface(struct gb_interface *intf) struct gb_module *module = intf->module; u8 intf_id = intf->interface_id; int ret; + int retries = 3; mutex_lock(&intf->mutex); - ret = gb_interface_activate(intf); + while (retries--) { + ret = gb_interface_activate(intf); + if (ret != -EAGAIN) + break; + } if (ret) { dev_err(&module->dev, "failed to activate interface %u: %d\n", intf_id, ret); + + /* + * -EAGAIN indicates that the Greybus operation + * interface_activate determined the remote interface to be + * UniPro-only. At present, we assume a UniPro-only module + * to be a Greybus module that failed to send its mailbox + * poke. There is some reason to believe that this is + * because of a bug in the ES3 bootrom. If we exhause our + * retries trying to activate such an interface, convert + * the error code back into a "no device" error. + */ + if (ret == -EAGAIN) + ret = -ENODEV; + gb_interface_add(intf); goto err_unlock; } -- cgit v0.10.2 From e54b106dd1be50377fe8365392466e080b659ab6 Mon Sep 17 00:00:00 2001 From: Sandeep Patil <patil_sandeep@projectara.com> Date: Thu, 19 May 2016 08:52:39 -0700 Subject: greybus: gpbridge: rename 'gpbridge' to 'gbphy' everywhere The 'gpbridge' name didn't relaly reflect what the bus is; which is a bus for bridged-phy devices. So, rename all instances of 'gpbridge' to more appropriate 'gbphy' Testing Done: Build and boot tested. 'lsgb' will stop displaying 'GPBridge' devices until I change the library to reflect this change. Signed-off-by: Sandeep Patil <patil_sandeep@projectara.com> Suggested-by: Greg Kroah-Hartman <gregkh@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 608bd51..ae9a478 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -14,7 +14,7 @@ greybus-y := core.o \ operation.o \ legacy.o -gb-gpbridge-y := gpbridge.o +gb-gbphy-y := gbphy.o # Prefix all modules with gb- gb-vibrator-y := vibrator.o @@ -43,7 +43,7 @@ gb-usb-y := usb.o gb-spi-y := spi.o obj-m += greybus.o -obj-m += gb-gpbridge.o +obj-m += gb-gbphy.o obj-m += gb-vibrator.o obj-m += gb-power-supply.o obj-m += gb-loopback.o diff --git a/drivers/staging/greybus/gbphy.c b/drivers/staging/greybus/gbphy.c new file mode 100644 index 0000000..c11a136 --- /dev/null +++ b/drivers/staging/greybus/gbphy.c @@ -0,0 +1,330 @@ +/* + * Greybus Bridged-Phy Bus driver + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/types.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/device.h> + +#include "greybus.h" +#include "gbphy.h" + +struct gbphy_host { + struct gb_bundle *bundle; + struct list_head devices; +}; + +static DEFINE_IDA(gbphy_id); + +static ssize_t protocol_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gbphy_device *gbphy_dev = to_gbphy_dev(dev); + + return sprintf(buf, "0x%02x\n", gbphy_dev->cport_desc->protocol_id); +} +static DEVICE_ATTR_RO(protocol_id); + +static struct attribute *gbphy_dev_attrs[] = { + &dev_attr_protocol_id.attr, + NULL, +}; + +ATTRIBUTE_GROUPS(gbphy_dev); + +static void gbphy_dev_release(struct device *dev) +{ + struct gbphy_device *gbphy_dev = to_gbphy_dev(dev); + + ida_simple_remove(&gbphy_id, gbphy_dev->id); + kfree(gbphy_dev); +} + +static struct device_type greybus_gbphy_dev_type = { + .name = "gbphy_device", + .release = gbphy_dev_release, +}; + +static int gbphy_dev_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + struct gbphy_device *gbphy_dev = to_gbphy_dev(dev); + struct greybus_descriptor_cport *cport_desc = gbphy_dev->cport_desc; + struct gb_bundle *bundle = gbphy_dev->bundle; + struct gb_interface *intf = bundle->intf; + struct gb_module *module = intf->module; + struct gb_host_device *hd = intf->hd; + + if (add_uevent_var(env, "BUS=%u", hd->bus_id)) + return -ENOMEM; + if (add_uevent_var(env, "MODULE=%u", module->module_id)) + return -ENOMEM; + if (add_uevent_var(env, "INTERFACE=%u", intf->interface_id)) + return -ENOMEM; + if (add_uevent_var(env, "GREYBUS_ID=%08x/%08x", + intf->vendor_id, intf->product_id)) + return -ENOMEM; + if (add_uevent_var(env, "BUNDLE=%u", gbphy_dev->bundle->id)) + return -ENOMEM; + if (add_uevent_var(env, "BUNDLE_CLASS=%02x", bundle->class)) + return -ENOMEM; + if (add_uevent_var(env, "GBPHY=%u", gbphy_dev->id)) + return -ENOMEM; + if (add_uevent_var(env, "PROTOCOL_ID=%02x", cport_desc->protocol_id)) + return -ENOMEM; + + return 0; +} + +static const struct gbphy_device_id * +gbphy_dev_match_id(struct gbphy_device *gbphy_dev, struct gbphy_driver *gbphy_drv) +{ + const struct gbphy_device_id *id = gbphy_drv->id_table; + + if (!id) + return NULL; + + for (; id->protocol_id; id++) + if (id->protocol_id == gbphy_dev->cport_desc->protocol_id) + return id; + + return NULL; +} + +static int gbphy_dev_match(struct device *dev, struct device_driver *drv) +{ + struct gbphy_driver *gbphy_drv = to_gbphy_driver(drv); + struct gbphy_device *gbphy_dev = to_gbphy_dev(dev); + const struct gbphy_device_id *id; + + id = gbphy_dev_match_id(gbphy_dev, gbphy_drv); + if (id) + return 1; + + return 0; +} + +static int gbphy_dev_probe(struct device *dev) +{ + struct gbphy_driver *gbphy_drv = to_gbphy_driver(dev->driver); + struct gbphy_device *gbphy_dev = to_gbphy_dev(dev); + const struct gbphy_device_id *id; + + id = gbphy_dev_match_id(gbphy_dev, gbphy_drv); + if (!id) + return -ENODEV; + + return gbphy_drv->probe(gbphy_dev, id); +} + +static int gbphy_dev_remove(struct device *dev) +{ + struct gbphy_driver *gbphy_drv = to_gbphy_driver(dev->driver); + struct gbphy_device *gbphy_dev = to_gbphy_dev(dev); + + gbphy_drv->remove(gbphy_dev); + return 0; +} + +static struct bus_type gbphy_bus_type = { + .name = "gbphy", + .match = gbphy_dev_match, + .probe = gbphy_dev_probe, + .remove = gbphy_dev_remove, + .uevent = gbphy_dev_uevent, +}; + +int gb_gbphy_register_driver(struct gbphy_driver *driver, + struct module *owner, const char *mod_name) +{ + int retval; + + if (greybus_disabled()) + return -ENODEV; + + driver->driver.bus = &gbphy_bus_type; + driver->driver.name = driver->name; + driver->driver.owner = owner; + driver->driver.mod_name = mod_name; + + retval = driver_register(&driver->driver); + if (retval) + return retval; + + pr_info("registered new driver %s\n", driver->name); + return 0; +} +EXPORT_SYMBOL_GPL(gb_gbphy_register_driver); + +void gb_gbphy_deregister_driver(struct gbphy_driver *driver) +{ + driver_unregister(&driver->driver); +} +EXPORT_SYMBOL_GPL(gb_gbphy_deregister_driver); + +int gb_gbphy_get_version(struct gb_connection *connection) +{ + struct gb_protocol_version_request request; + struct gb_protocol_version_response response; + int retval; + + request.major = 1; + request.minor = 0; + + retval = gb_operation_sync(connection, GB_REQUEST_TYPE_PROTOCOL_VERSION, + &request, sizeof(request), &response, + sizeof(response)); + if (retval) + return retval; + + /* FIXME - do proper version negotiation here someday... */ + + connection->module_major = response.major; + connection->module_minor = response.minor; + + dev_dbg(&connection->hd->dev, "%s: v%u.%u\n", connection->name, + response.major, response.minor); + + return 0; +} +EXPORT_SYMBOL_GPL(gb_gbphy_get_version); + +static struct gbphy_device *gb_gbphy_create_dev(struct gb_bundle *bundle, + struct greybus_descriptor_cport *cport_desc) +{ + struct gbphy_device *gbphy_dev; + int retval; + int id; + + id = ida_simple_get(&gbphy_id, 1, 0, GFP_KERNEL); + if (id < 0) + return ERR_PTR(id); + + gbphy_dev = kzalloc(sizeof(*gbphy_dev), GFP_KERNEL); + if (!gbphy_dev) { + ida_simple_remove(&gbphy_id, id); + return ERR_PTR(-ENOMEM); + } + + gbphy_dev->id = id; + gbphy_dev->bundle = bundle; + gbphy_dev->cport_desc = cport_desc; + gbphy_dev->dev.parent = &bundle->dev; + gbphy_dev->dev.bus = &gbphy_bus_type; + gbphy_dev->dev.type = &greybus_gbphy_dev_type; + gbphy_dev->dev.groups = gbphy_dev_groups; + gbphy_dev->dev.dma_mask = bundle->dev.dma_mask; + dev_set_name(&gbphy_dev->dev, "gbphy%d", id); + + retval = device_register(&gbphy_dev->dev); + if (retval) { + put_device(&gbphy_dev->dev); + return ERR_PTR(retval); + } + + return gbphy_dev; +} + +static void gb_gbphy_disconnect(struct gb_bundle *bundle) +{ + struct gbphy_host *gbphy_host = greybus_get_drvdata(bundle); + struct gbphy_device *gbphy_dev, *temp; + + list_for_each_entry_safe(gbphy_dev, temp, &gbphy_host->devices, list) { + list_del(&gbphy_dev->list); + device_unregister(&gbphy_dev->dev); + } + + kfree(gbphy_host); +} + +static int gb_gbphy_probe(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) +{ + struct gbphy_host *gbphy_host; + struct gbphy_device *gbphy_dev; + int i; + + if (bundle->num_cports == 0) + return -ENODEV; + + gbphy_host = kzalloc(sizeof(*gbphy_host), GFP_KERNEL); + if (!gbphy_host) + return -ENOMEM; + + gbphy_host->bundle = bundle; + INIT_LIST_HEAD(&gbphy_host->devices); + greybus_set_drvdata(bundle, gbphy_host); + + /* + * Create a bunch of children devices, one per cport, and bind the + * bridged phy drivers to them. + */ + for (i = 0; i < bundle->num_cports; ++i) { + gbphy_dev = gb_gbphy_create_dev(bundle, &bundle->cport_desc[i]); + if (IS_ERR(gbphy_dev)) { + gb_gbphy_disconnect(bundle); + return PTR_ERR(gbphy_dev); + } + list_add(&gbphy_dev->list, &gbphy_host->devices); + } + + return 0; +} + +static const struct greybus_bundle_id gb_gbphy_id_table[] = { + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_BRIDGED_PHY) }, + { }, +}; +MODULE_DEVICE_TABLE(greybus, gb_gbphy_id_table); + +static struct greybus_driver gb_gbphy_driver = { + .name = "gbphy", + .probe = gb_gbphy_probe, + .disconnect = gb_gbphy_disconnect, + .id_table = gb_gbphy_id_table, +}; + +static int __init gbphy_init(void) +{ + int retval; + + retval = bus_register(&gbphy_bus_type); + if (retval) { + pr_err("gbphy bus register failed (%d)\n", retval); + return retval; + } + + retval = greybus_register(&gb_gbphy_driver); + if (retval) { + pr_err("error registering greybus driver\n"); + goto error_gbphy; + } + + return 0; + +error_gbphy: + bus_unregister(&gbphy_bus_type); + ida_destroy(&gbphy_id); + return retval; +} +module_init(gbphy_init); + +static void __exit gbphy_exit(void) +{ + greybus_deregister(&gb_gbphy_driver); + bus_unregister(&gbphy_bus_type); + ida_destroy(&gbphy_id); +} +module_exit(gbphy_exit); + +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/gbphy.h b/drivers/staging/greybus/gbphy.h new file mode 100644 index 0000000..79dbf7e --- /dev/null +++ b/drivers/staging/greybus/gbphy.h @@ -0,0 +1,71 @@ +/* + * Greybus Bridged-Phy Bus driver + * + * Copyright 2016 Google Inc. + * + * Released under the GPLv2 only. + */ + +#ifndef __GBPHY_H +#define __GBPHY_H + +struct gbphy_device { + u32 id; + struct greybus_descriptor_cport *cport_desc; + struct gb_bundle *bundle; + struct list_head list; + struct device dev; +}; +#define to_gbphy_dev(d) container_of(d, struct gbphy_device, dev) + +static inline void *gb_gbphy_get_data(struct gbphy_device *gdev) +{ + return dev_get_drvdata(&gdev->dev); +} + +static inline void gb_gbphy_set_data(struct gbphy_device *gdev, void *data) +{ + dev_set_drvdata(&gdev->dev, data); +} + +struct gbphy_device_id { + __u8 protocol_id; +}; + +#define GBPHY_PROTOCOL(p) \ + .protocol_id = (p), + +struct gbphy_driver { + const char *name; + int (*probe)(struct gbphy_device *, + const struct gbphy_device_id *id); + void (*remove)(struct gbphy_device *); + const struct gbphy_device_id *id_table; + + struct device_driver driver; +}; +#define to_gbphy_driver(d) container_of(d, struct gbphy_driver, driver) + +int gb_gbphy_get_version(struct gb_connection *connection); +int gb_gbphy_register_driver(struct gbphy_driver *driver, + struct module *owner, const char *mod_name); +void gb_gbphy_deregister_driver(struct gbphy_driver *driver); + +#define gb_gbphy_register(driver) \ + gb_gbphy_register_driver(driver, THIS_MODULE, KBUILD_MODNAME) +#define gb_gbphy_deregister(driver) \ + gb_gbphy_deregister_driver(driver) + +/** + * module_gbphy_driver() - Helper macro for registering a gbphy driver + * @__gbphy_driver: gbphy_driver structure + * + * Helper macro for gbphy drivers to set up proper module init / exit + * functions. Replaces module_init() and module_exit() and keeps people from + * printing pointless things to the kernel log when their driver is loaded. + */ +#define module_gbphy_driver(__gbphy_driver) \ + module_driver(__gbphy_driver, gb_gbphy_register, gb_gbphy_deregister) + +#endif /* __GBPHY_H */ + diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c deleted file mode 100644 index 88f7d26..0000000 --- a/drivers/staging/greybus/gpbridge.c +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Greybus GP Bridge driver - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/types.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/device.h> - -#include "greybus.h" -#include "gpbridge.h" - -struct gpbridge_host { - struct gb_bundle *bundle; - struct list_head devices; -}; - -static DEFINE_IDA(gpbridge_id); - -static ssize_t protocol_id_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gpbridge_device *gpbdev = to_gpbridge_dev(dev); - - return sprintf(buf, "0x%02x\n", gpbdev->cport_desc->protocol_id); -} -static DEVICE_ATTR_RO(protocol_id); - -static struct attribute *gpbdev_attrs[] = { - &dev_attr_protocol_id.attr, - NULL, -}; - -ATTRIBUTE_GROUPS(gpbdev); - -static void gpbdev_release(struct device *dev) -{ - struct gpbridge_device *gpbdev = to_gpbridge_dev(dev); - - ida_simple_remove(&gpbridge_id, gpbdev->id); - kfree(gpbdev); -} - -static struct device_type greybus_gpbdev_type = { - .name = "gpbridge_device", - .release = gpbdev_release, -}; - -static int gpbdev_uevent(struct device *dev, struct kobj_uevent_env *env) -{ - struct gpbridge_device *gpbdev = to_gpbridge_dev(dev); - struct greybus_descriptor_cport *cport_desc = gpbdev->cport_desc; - struct gb_bundle *bundle = gpbdev->bundle; - struct gb_interface *intf = bundle->intf; - struct gb_module *module = intf->module; - struct gb_host_device *hd = intf->hd; - - if (add_uevent_var(env, "BUS=%u", hd->bus_id)) - return -ENOMEM; - if (add_uevent_var(env, "MODULE=%u", module->module_id)) - return -ENOMEM; - if (add_uevent_var(env, "INTERFACE=%u", intf->interface_id)) - return -ENOMEM; - if (add_uevent_var(env, "GREYBUS_ID=%08x/%08x", - intf->vendor_id, intf->product_id)) - return -ENOMEM; - if (add_uevent_var(env, "BUNDLE=%u", gpbdev->bundle->id)) - return -ENOMEM; - if (add_uevent_var(env, "BUNDLE_CLASS=%02x", bundle->class)) - return -ENOMEM; - if (add_uevent_var(env, "GPBDEV_ID=%u", gpbdev->id)) - return -ENOMEM; - if (add_uevent_var(env, "PROTOCOL_ID=%02x", cport_desc->protocol_id)) - return -ENOMEM; - - return 0; -} - -static const struct gpbridge_device_id * -gpbdev_match_id(struct gpbridge_device *gpbdev, struct gpbridge_driver *gpbdrv) -{ - const struct gpbridge_device_id *id = gpbdrv->id_table; - - if (!id) - return NULL; - - for (; id->protocol_id; id++) - if (id->protocol_id == gpbdev->cport_desc->protocol_id) - return id; - - return NULL; -} - -static int gpbdev_match(struct device *dev, struct device_driver *drv) -{ - struct gpbridge_driver *gpbdrv = to_gpbridge_driver(drv); - struct gpbridge_device *gpbdev = to_gpbridge_dev(dev); - const struct gpbridge_device_id *id; - - id = gpbdev_match_id(gpbdev, gpbdrv); - if (id) - return 1; - - return 0; -} - -static int gpbdev_probe(struct device *dev) -{ - struct gpbridge_driver *gpbdrv = to_gpbridge_driver(dev->driver); - struct gpbridge_device *gpbdev = to_gpbridge_dev(dev); - const struct gpbridge_device_id *id; - - id = gpbdev_match_id(gpbdev, gpbdrv); - if (!id) - return -ENODEV; - - return gpbdrv->probe(gpbdev, id); -} - -static int gpbdev_remove(struct device *dev) -{ - struct gpbridge_driver *gpbdrv = to_gpbridge_driver(dev->driver); - struct gpbridge_device *gpbdev = to_gpbridge_dev(dev); - - gpbdrv->remove(gpbdev); - return 0; -} - -static struct bus_type gpbridge_bus_type = { - .name = "gpbridge", - .match = gpbdev_match, - .probe = gpbdev_probe, - .remove = gpbdev_remove, - .uevent = gpbdev_uevent, -}; - -int gb_gpbridge_register_driver(struct gpbridge_driver *driver, - struct module *owner, const char *mod_name) -{ - int retval; - - if (greybus_disabled()) - return -ENODEV; - - driver->driver.bus = &gpbridge_bus_type; - driver->driver.name = driver->name; - driver->driver.owner = owner; - driver->driver.mod_name = mod_name; - - retval = driver_register(&driver->driver); - if (retval) - return retval; - - pr_info("registered new driver %s\n", driver->name); - return 0; -} -EXPORT_SYMBOL_GPL(gb_gpbridge_register_driver); - -void gb_gpbridge_deregister_driver(struct gpbridge_driver *driver) -{ - driver_unregister(&driver->driver); -} -EXPORT_SYMBOL_GPL(gb_gpbridge_deregister_driver); - -int gb_gpbridge_get_version(struct gb_connection *connection) -{ - struct gb_protocol_version_request request; - struct gb_protocol_version_response response; - int retval; - - request.major = 1; - request.minor = 0; - - retval = gb_operation_sync(connection, GB_REQUEST_TYPE_PROTOCOL_VERSION, - &request, sizeof(request), &response, - sizeof(response)); - if (retval) - return retval; - - /* FIXME - do proper version negotiation here someday... */ - - connection->module_major = response.major; - connection->module_minor = response.minor; - - dev_dbg(&connection->hd->dev, "%s: v%u.%u\n", connection->name, - response.major, response.minor); - - return 0; -} -EXPORT_SYMBOL_GPL(gb_gpbridge_get_version); - -static struct gpbridge_device *gb_gpbridge_create_dev(struct gb_bundle *bundle, - struct greybus_descriptor_cport *cport_desc) -{ - struct gpbridge_device *gpbdev; - int retval; - int id; - - id = ida_simple_get(&gpbridge_id, 1, 0, GFP_KERNEL); - if (id < 0) - return ERR_PTR(id); - - gpbdev = kzalloc(sizeof(*gpbdev), GFP_KERNEL); - if (!gpbdev) { - ida_simple_remove(&gpbridge_id, id); - return ERR_PTR(-ENOMEM); - } - - gpbdev->id = id; - gpbdev->bundle = bundle; - gpbdev->cport_desc = cport_desc; - gpbdev->dev.parent = &bundle->dev; - gpbdev->dev.bus = &gpbridge_bus_type; - gpbdev->dev.type = &greybus_gpbdev_type; - gpbdev->dev.groups = gpbdev_groups; - gpbdev->dev.dma_mask = bundle->dev.dma_mask; - dev_set_name(&gpbdev->dev, "gpb%d", id); - - retval = device_register(&gpbdev->dev); - if (retval) { - put_device(&gpbdev->dev); - return ERR_PTR(retval); - } - - return gpbdev; -} - -static void gb_gpbridge_disconnect(struct gb_bundle *bundle) -{ - struct gpbridge_host *gpb_host = greybus_get_drvdata(bundle); - struct gpbridge_device *gpbdev, *temp; - - list_for_each_entry_safe(gpbdev, temp, &gpb_host->devices, list) { - list_del(&gpbdev->list); - device_unregister(&gpbdev->dev); - } - - kfree(gpb_host); -} - -static int gb_gpbridge_probe(struct gb_bundle *bundle, - const struct greybus_bundle_id *id) -{ - struct gpbridge_host *gpb_host; - struct gpbridge_device *gpbdev; - int i; - - if (bundle->num_cports == 0) - return -ENODEV; - - gpb_host = kzalloc(sizeof(*gpb_host), GFP_KERNEL); - if (!gpb_host) - return -ENOMEM; - - gpb_host->bundle = bundle; - INIT_LIST_HEAD(&gpb_host->devices); - greybus_set_drvdata(bundle, gpb_host); - - /* - * Create a bunch of children devices, one per cport, and bind the - * bridged phy drivers to them. - */ - for (i = 0; i < bundle->num_cports; ++i) { - gpbdev = gb_gpbridge_create_dev(bundle, &bundle->cport_desc[i]); - if (IS_ERR(gpbdev)) { - gb_gpbridge_disconnect(bundle); - return PTR_ERR(gpbdev); - } - list_add(&gpbdev->list, &gpb_host->devices); - } - - return 0; -} - -static const struct greybus_bundle_id gb_gpbridge_id_table[] = { - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_BRIDGED_PHY) }, - { }, -}; -MODULE_DEVICE_TABLE(greybus, gb_gpbridge_id_table); - -static struct greybus_driver gb_gpbridge_driver = { - .name = "gpbridge", - .probe = gb_gpbridge_probe, - .disconnect = gb_gpbridge_disconnect, - .id_table = gb_gpbridge_id_table, -}; - -static int __init gpbridge_init(void) -{ - int retval; - - retval = bus_register(&gpbridge_bus_type); - if (retval) { - pr_err("gpbridge bus register failed (%d)\n", retval); - return retval; - } - - retval = greybus_register(&gb_gpbridge_driver); - if (retval) { - pr_err("error registering greybus driver\n"); - goto error_gpbridge; - } - - return 0; - -error_gpbridge: - bus_unregister(&gpbridge_bus_type); - ida_destroy(&gpbridge_id); - return retval; -} -module_init(gpbridge_init); - -static void __exit gpbridge_exit(void) -{ - greybus_deregister(&gb_gpbridge_driver); - bus_unregister(&gpbridge_bus_type); - ida_destroy(&gpbridge_id); -} -module_exit(gpbridge_exit); - -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/gpbridge.h b/drivers/staging/greybus/gpbridge.h deleted file mode 100644 index 0cee2eb..0000000 --- a/drivers/staging/greybus/gpbridge.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Greybus GPBridge phy driver - * - * Copyright 2016 Google Inc. - * - * Released under the GPLv2 only. - */ - -#ifndef __GPBRIDGE_H -#define __GPBRIDGE_H - -struct gpbridge_device { - u32 id; - struct greybus_descriptor_cport *cport_desc; - struct gb_bundle *bundle; - struct list_head list; - struct device dev; -}; -#define to_gpbridge_dev(d) container_of(d, struct gpbridge_device, dev) - -static inline void *gb_gpbridge_get_data(struct gpbridge_device *gdev) -{ - return dev_get_drvdata(&gdev->dev); -} - -static inline void gb_gpbridge_set_data(struct gpbridge_device *gdev, void *data) -{ - dev_set_drvdata(&gdev->dev, data); -} - -struct gpbridge_device_id { - __u8 protocol_id; -}; - -#define GPBRIDGE_PROTOCOL(p) \ - .protocol_id = (p), - -struct gpbridge_driver { - const char *name; - int (*probe)(struct gpbridge_device *, - const struct gpbridge_device_id *id); - void (*remove)(struct gpbridge_device *); - const struct gpbridge_device_id *id_table; - - struct device_driver driver; -}; -#define to_gpbridge_driver(d) container_of(d, struct gpbridge_driver, driver) - -int gb_gpbridge_get_version(struct gb_connection *connection); -int gb_gpbridge_register_driver(struct gpbridge_driver *driver, - struct module *owner, const char *mod_name); -void gb_gpbridge_deregister_driver(struct gpbridge_driver *driver); - -#define gb_gpbridge_register(driver) \ - gb_gpbridge_register_driver(driver, THIS_MODULE, KBUILD_MODNAME) -#define gb_gpbridge_deregister(driver) \ - gb_gpbridge_deregister_driver(driver) - -/** - * module_gpbridge_driver() - Helper macro for registering a gpbridge driver - * @__gpbridge_driver: gpbridge_driver structure - * - * Helper macro for gpbridge drivers to set up proper module init / exit - * functions. Replaces module_init() and module_exit() and keeps people from - * printing pointless things to the kernel log when their driver is loaded. - */ -#define module_gpbridge_driver(__gpbridge_driver) \ - module_driver(__gpbridge_driver, gb_gpbridge_register, gb_gpbridge_deregister) - -#endif /* __GPBRIDGE_H */ - diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index adb213f..e1ad680 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -16,7 +16,7 @@ #include <linux/mutex.h> #include "greybus.h" -#include "gpbridge.h" +#include "gbphy.h" struct gb_gpio_line { /* The following has to be an array of line_max entries */ @@ -33,7 +33,7 @@ struct gb_gpio_line { }; struct gb_gpio_controller { - struct gpbridge_device *gpbdev; + struct gbphy_device *gbphy_dev; struct gb_connection *connection; u8 line_max; /* max line number */ struct gb_gpio_line *lines; @@ -79,7 +79,7 @@ static int gb_gpio_activate_operation(struct gb_gpio_controller *ggc, u8 which) static void gb_gpio_deactivate_operation(struct gb_gpio_controller *ggc, u8 which) { - struct device *dev = &ggc->gpbdev->dev; + struct device *dev = &ggc->gbphy_dev->dev; struct gb_gpio_deactivate_request request; int ret; @@ -97,7 +97,7 @@ static void gb_gpio_deactivate_operation(struct gb_gpio_controller *ggc, static int gb_gpio_get_direction_operation(struct gb_gpio_controller *ggc, u8 which) { - struct device *dev = &ggc->gpbdev->dev; + struct device *dev = &ggc->gbphy_dev->dev; struct gb_gpio_get_direction_request request; struct gb_gpio_get_direction_response response; int ret; @@ -151,7 +151,7 @@ static int gb_gpio_direction_out_operation(struct gb_gpio_controller *ggc, static int gb_gpio_get_value_operation(struct gb_gpio_controller *ggc, u8 which) { - struct device *dev = &ggc->gpbdev->dev; + struct device *dev = &ggc->gbphy_dev->dev; struct gb_gpio_get_value_request request; struct gb_gpio_get_value_response response; int ret; @@ -178,7 +178,7 @@ static int gb_gpio_get_value_operation(struct gb_gpio_controller *ggc, static void gb_gpio_set_value_operation(struct gb_gpio_controller *ggc, u8 which, bool value_high) { - struct device *dev = &ggc->gpbdev->dev; + struct device *dev = &ggc->gbphy_dev->dev; struct gb_gpio_set_value_request request; int ret; @@ -217,7 +217,7 @@ static int gb_gpio_set_debounce_operation(struct gb_gpio_controller *ggc, static void _gb_gpio_irq_mask(struct gb_gpio_controller *ggc, u8 hwirq) { - struct device *dev = &ggc->gpbdev->dev; + struct device *dev = &ggc->gbphy_dev->dev; struct gb_gpio_irq_mask_request request; int ret; @@ -231,7 +231,7 @@ static void _gb_gpio_irq_mask(struct gb_gpio_controller *ggc, u8 hwirq) static void _gb_gpio_irq_unmask(struct gb_gpio_controller *ggc, u8 hwirq) { - struct device *dev = &ggc->gpbdev->dev; + struct device *dev = &ggc->gbphy_dev->dev; struct gb_gpio_irq_unmask_request request; int ret; @@ -246,7 +246,7 @@ static void _gb_gpio_irq_unmask(struct gb_gpio_controller *ggc, u8 hwirq) static void _gb_gpio_irq_set_type(struct gb_gpio_controller *ggc, u8 hwirq, u8 type) { - struct device *dev = &ggc->gpbdev->dev; + struct device *dev = &ggc->gbphy_dev->dev; struct gb_gpio_irq_type_request request; int ret; @@ -285,7 +285,7 @@ static int gb_gpio_irq_set_type(struct irq_data *d, unsigned int type) struct gpio_chip *chip = irq_data_to_gpio_chip(d); struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); struct gb_gpio_line *line = &ggc->lines[d->hwirq]; - struct device *dev = &ggc->gpbdev->dev; + struct device *dev = &ggc->gbphy_dev->dev; u8 irq_type; switch (type) { @@ -352,7 +352,7 @@ static int gb_gpio_request_handler(struct gb_operation *op) { struct gb_connection *connection = op->connection; struct gb_gpio_controller *ggc = gb_connection_get_data(connection); - struct device *dev = &ggc->gpbdev->dev; + struct device *dev = &ggc->gbphy_dev->dev; struct gb_message *request; struct gb_gpio_irq_event_request *event; u8 type = op->type; @@ -624,8 +624,8 @@ static int gb_gpio_to_irq(struct gpio_chip *chip, unsigned offset) return irq_find_mapping(ggc->irqdomain, offset); } -static int gb_gpio_probe(struct gpbridge_device *gpbdev, - const struct gpbridge_device_id *id) +static int gb_gpio_probe(struct gbphy_device *gbphy_dev, + const struct gbphy_device_id *id) { struct gb_connection *connection; struct gb_gpio_controller *ggc; @@ -637,8 +637,8 @@ static int gb_gpio_probe(struct gpbridge_device *gpbdev, if (!ggc) return -ENOMEM; - connection = gb_connection_create(gpbdev->bundle, - le16_to_cpu(gpbdev->cport_desc->id), + connection = gb_connection_create(gbphy_dev->bundle, + le16_to_cpu(gbphy_dev->cport_desc->id), gb_gpio_request_handler); if (IS_ERR(connection)) { ret = PTR_ERR(connection); @@ -647,14 +647,14 @@ static int gb_gpio_probe(struct gpbridge_device *gpbdev, ggc->connection = connection; gb_connection_set_data(connection, ggc); - ggc->gpbdev = gpbdev; - gb_gpbridge_set_data(gpbdev, ggc); + ggc->gbphy_dev = gbphy_dev; + gb_gbphy_set_data(gbphy_dev, ggc); ret = gb_connection_enable_tx(connection); if (ret) goto exit_connection_destroy; - ret = gb_gpbridge_get_version(connection); + ret = gb_gbphy_get_version(connection); if (ret) goto exit_connection_disable; @@ -676,9 +676,9 @@ static int gb_gpio_probe(struct gpbridge_device *gpbdev, gpio->label = "greybus_gpio"; #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0) - gpio->parent = &gpbdev->dev; + gpio->parent = &gbphy_dev->dev; #else - gpio->dev = &gpbdev->dev; + gpio->dev = &gbphy_dev->dev; #endif gpio->owner = THIS_MODULE; @@ -729,9 +729,9 @@ exit_ggc_free: return ret; } -static void gb_gpio_remove(struct gpbridge_device *gpbdev) +static void gb_gpio_remove(struct gbphy_device *gbphy_dev) { - struct gb_gpio_controller *ggc = gb_gpbridge_get_data(gpbdev); + struct gb_gpio_controller *ggc = gb_gbphy_get_data(gbphy_dev); struct gb_connection *connection = ggc->connection; gb_connection_disable_rx(connection); @@ -743,18 +743,18 @@ static void gb_gpio_remove(struct gpbridge_device *gpbdev) kfree(ggc); } -static const struct gpbridge_device_id gb_gpio_id_table[] = { - { GPBRIDGE_PROTOCOL(GREYBUS_PROTOCOL_GPIO) }, +static const struct gbphy_device_id gb_gpio_id_table[] = { + { GBPHY_PROTOCOL(GREYBUS_PROTOCOL_GPIO) }, { }, }; -MODULE_DEVICE_TABLE(gpbridge, gb_gpio_id_table); +MODULE_DEVICE_TABLE(gbphy, gb_gpio_id_table); -static struct gpbridge_driver gpio_driver = { +static struct gbphy_driver gpio_driver = { .name = "gpio", .probe = gb_gpio_probe, .remove = gb_gpio_remove, .id_table = gb_gpio_id_table, }; -module_gpbridge_driver(gpio_driver); +module_gbphy_driver(gpio_driver); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c index 69d6f07..6c14e67 100644 --- a/drivers/staging/greybus/i2c.c +++ b/drivers/staging/greybus/i2c.c @@ -13,11 +13,11 @@ #include <linux/i2c.h> #include "greybus.h" -#include "gpbridge.h" +#include "gbphy.h" struct gb_i2c_device { struct gb_connection *connection; - struct gpbridge_device *gpbdev; + struct gbphy_device *gbphy_dev; u32 functionality; @@ -85,7 +85,7 @@ gb_i2c_operation_create(struct gb_connection *connection, u32 i; if (msg_count > (u32)U16_MAX) { - dev_err(&gb_i2c_dev->gpbdev->dev, "msg_count (%u) too big\n", + dev_err(&gb_i2c_dev->gbphy_dev->dev, "msg_count (%u) too big\n", msg_count); return NULL; } @@ -168,7 +168,7 @@ static int gb_i2c_transfer_operation(struct gb_i2c_device *gb_i2c_dev, struct i2c_msg *msgs, u32 msg_count) { struct gb_connection *connection = gb_i2c_dev->connection; - struct device *dev = &gb_i2c_dev->gpbdev->dev; + struct device *dev = &gb_i2c_dev->gbphy_dev->dev; struct gb_operation *operation; int ret; @@ -242,8 +242,8 @@ static int gb_i2c_device_setup(struct gb_i2c_device *gb_i2c_dev) return gb_i2c_functionality_operation(gb_i2c_dev); } -static int gb_i2c_probe(struct gpbridge_device *gpbdev, - const struct gpbridge_device_id *id) +static int gb_i2c_probe(struct gbphy_device *gbphy_dev, + const struct gbphy_device_id *id) { struct gb_connection *connection; struct gb_i2c_device *gb_i2c_dev; @@ -254,8 +254,8 @@ static int gb_i2c_probe(struct gpbridge_device *gpbdev, if (!gb_i2c_dev) return -ENOMEM; - connection = gb_connection_create(gpbdev->bundle, - le16_to_cpu(gpbdev->cport_desc->id), + connection = gb_connection_create(gbphy_dev->bundle, + le16_to_cpu(gbphy_dev->cport_desc->id), NULL); if (IS_ERR(connection)) { ret = PTR_ERR(connection); @@ -264,14 +264,14 @@ static int gb_i2c_probe(struct gpbridge_device *gpbdev, gb_i2c_dev->connection = connection; gb_connection_set_data(connection, gb_i2c_dev); - gb_i2c_dev->gpbdev = gpbdev; - gb_gpbridge_set_data(gpbdev, gb_i2c_dev); + gb_i2c_dev->gbphy_dev = gbphy_dev; + gb_gbphy_set_data(gbphy_dev, gb_i2c_dev); ret = gb_connection_enable(connection); if (ret) goto exit_connection_destroy; - ret = gb_gpbridge_get_version(connection); + ret = gb_gbphy_get_version(connection); if (ret) goto exit_connection_disable; @@ -286,7 +286,7 @@ static int gb_i2c_probe(struct gpbridge_device *gpbdev, adapter->algo = &gb_i2c_algorithm; /* adapter->algo_data = what? */ - adapter->dev.parent = &gpbdev->dev; + adapter->dev.parent = &gbphy_dev->dev; snprintf(adapter->name, sizeof(adapter->name), "Greybus i2c adapter"); i2c_set_adapdata(adapter, gb_i2c_dev); @@ -306,9 +306,9 @@ exit_i2cdev_free: return ret; } -static void gb_i2c_remove(struct gpbridge_device *gpbdev) +static void gb_i2c_remove(struct gbphy_device *gbphy_dev) { - struct gb_i2c_device *gb_i2c_dev = gb_gpbridge_get_data(gpbdev); + struct gb_i2c_device *gb_i2c_dev = gb_gbphy_get_data(gbphy_dev); struct gb_connection *connection = gb_i2c_dev->connection; i2c_del_adapter(&gb_i2c_dev->adapter); @@ -317,18 +317,18 @@ static void gb_i2c_remove(struct gpbridge_device *gpbdev) kfree(gb_i2c_dev); } -static const struct gpbridge_device_id gb_i2c_id_table[] = { - { GPBRIDGE_PROTOCOL(GREYBUS_PROTOCOL_I2C) }, +static const struct gbphy_device_id gb_i2c_id_table[] = { + { GBPHY_PROTOCOL(GREYBUS_PROTOCOL_I2C) }, { }, }; -MODULE_DEVICE_TABLE(gpbridge, gb_i2c_id_table); +MODULE_DEVICE_TABLE(gbphy, gb_i2c_id_table); -static struct gpbridge_driver i2c_driver = { +static struct gbphy_driver i2c_driver = { .name = "i2c", .probe = gb_i2c_probe, .remove = gb_i2c_remove, .id_table = gb_i2c_id_table, }; -module_gpbridge_driver(i2c_driver); +module_gbphy_driver(i2c_driver); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 3b56693..e3e8e169 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -32,7 +32,7 @@ #define TOSHIBA_DMID 0x0126 #define TOSHIBA_ES2_BRIDGE_DPID 0x1000 #define TOSHIBA_ES3_APBRIDGE_DPID 0x1001 -#define TOSHIBA_ES3_GPBRIDGE_DPID 0x1002 +#define TOSHIBA_ES3_GBPHY_DPID 0x1002 static int gb_interface_dme_attr_get(struct gb_interface *intf, diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index ccb2799..702cf06 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -86,7 +86,7 @@ struct gb_loopback { struct gb_loopback_stats throughput; struct gb_loopback_stats requests_per_second; struct gb_loopback_stats apbridge_unipro_latency; - struct gb_loopback_stats gpbridge_firmware_latency; + struct gb_loopback_stats gbphy_firmware_latency; int type; int async; @@ -106,7 +106,7 @@ struct gb_loopback { u32 lbid; u64 elapsed_nsecs; u32 apbridge_latency_ts; - u32 gpbridge_latency_ts; + u32 gbphy_latency_ts; u32 send_count; }; @@ -290,7 +290,7 @@ gb_loopback_stats_attrs(throughput); /* Latency across the UniPro link from APBridge's perspective */ gb_loopback_stats_attrs(apbridge_unipro_latency); /* Firmware induced overhead in the GPBridge */ -gb_loopback_stats_attrs(gpbridge_firmware_latency); +gb_loopback_stats_attrs(gbphy_firmware_latency); /* Number of errors encountered during loop */ gb_loopback_ro_attr(error); @@ -340,9 +340,9 @@ static struct attribute *loopback_attrs[] = { &dev_attr_apbridge_unipro_latency_min.attr, &dev_attr_apbridge_unipro_latency_max.attr, &dev_attr_apbridge_unipro_latency_avg.attr, - &dev_attr_gpbridge_firmware_latency_min.attr, - &dev_attr_gpbridge_firmware_latency_max.attr, - &dev_attr_gpbridge_firmware_latency_avg.attr, + &dev_attr_gbphy_firmware_latency_min.attr, + &dev_attr_gbphy_firmware_latency_max.attr, + &dev_attr_gbphy_firmware_latency_avg.attr, &dev_attr_type.attr, &dev_attr_size.attr, &dev_attr_us_wait.attr, @@ -670,7 +670,7 @@ static int gb_loopback_sync_transfer(struct gb_loopback *gb, u32 len) int retval; gb->apbridge_latency_ts = 0; - gb->gpbridge_latency_ts = 0; + gb->gbphy_latency_ts = 0; request = kmalloc(len + sizeof(*request), GFP_KERNEL); if (!request) @@ -696,7 +696,7 @@ static int gb_loopback_sync_transfer(struct gb_loopback *gb, u32 len) retval = -EREMOTEIO; } gb->apbridge_latency_ts = (u32)__le32_to_cpu(response->reserved0); - gb->gpbridge_latency_ts = (u32)__le32_to_cpu(response->reserved1); + gb->gbphy_latency_ts = (u32)__le32_to_cpu(response->reserved1); gb_error: kfree(request); @@ -752,7 +752,7 @@ static int gb_loopback_async_transfer_complete( } else { gb->apbridge_latency_ts = (u32)__le32_to_cpu(response->reserved0); - gb->gpbridge_latency_ts = + gb->gbphy_latency_ts = (u32)__le32_to_cpu(response->reserved1); } @@ -850,12 +850,12 @@ static void gb_loopback_reset_stats(struct gb_loopback *gb) sizeof(struct gb_loopback_stats)); memcpy(&gb->apbridge_unipro_latency, &reset, sizeof(struct gb_loopback_stats)); - memcpy(&gb->gpbridge_firmware_latency, &reset, + memcpy(&gb->gbphy_firmware_latency, &reset, sizeof(struct gb_loopback_stats)); /* Should be initialized at least once per transaction set */ gb->apbridge_latency_ts = 0; - gb->gpbridge_latency_ts = 0; + gb->gbphy_latency_ts = 0; memset(&gb->ts, 0, sizeof(struct timeval)); } @@ -931,8 +931,8 @@ static void gb_loopback_calculate_latency_stats(struct gb_loopback *gb) /* Log the firmware supplied latency values */ gb_loopback_update_stats(&gb->apbridge_unipro_latency, gb->apbridge_latency_ts); - gb_loopback_update_stats(&gb->gpbridge_firmware_latency, - gb->gpbridge_latency_ts); + gb_loopback_update_stats(&gb->gbphy_firmware_latency, + gb->gbphy_latency_ts); } static void gb_loopback_calculate_stats(struct gb_loopback *gb, bool error) diff --git a/drivers/staging/greybus/pwm.c b/drivers/staging/greybus/pwm.c index 1c4ffb9..77b05e8 100644 --- a/drivers/staging/greybus/pwm.c +++ b/drivers/staging/greybus/pwm.c @@ -13,7 +13,7 @@ #include <linux/pwm.h> #include "greybus.h" -#include "gpbridge.h" +#include "gbphy.h" struct gb_pwm_chip { struct gb_connection *connection; @@ -178,8 +178,8 @@ static const struct pwm_ops gb_pwm_ops = { .owner = THIS_MODULE, }; -static int gb_pwm_probe(struct gpbridge_device *gpbdev, - const struct gpbridge_device_id *id) +static int gb_pwm_probe(struct gbphy_device *gbphy_dev, + const struct gbphy_device_id *id) { struct gb_connection *connection; struct gb_pwm_chip *pwmc; @@ -190,8 +190,8 @@ static int gb_pwm_probe(struct gpbridge_device *gpbdev, if (!pwmc) return -ENOMEM; - connection = gb_connection_create(gpbdev->bundle, - le16_to_cpu(gpbdev->cport_desc->id), + connection = gb_connection_create(gbphy_dev->bundle, + le16_to_cpu(gbphy_dev->cport_desc->id), NULL); if (IS_ERR(connection)) { ret = PTR_ERR(connection); @@ -200,13 +200,13 @@ static int gb_pwm_probe(struct gpbridge_device *gpbdev, pwmc->connection = connection; gb_connection_set_data(connection, pwmc); - gb_gpbridge_set_data(gpbdev, pwmc); + gb_gbphy_set_data(gbphy_dev, pwmc); ret = gb_connection_enable(connection); if (ret) goto exit_connection_destroy; - ret = gb_gpbridge_get_version(connection); + ret = gb_gbphy_get_version(connection); if (ret) goto exit_connection_disable; @@ -217,7 +217,7 @@ static int gb_pwm_probe(struct gpbridge_device *gpbdev, pwm = &pwmc->chip; - pwm->dev = &gpbdev->dev; + pwm->dev = &gbphy_dev->dev; pwm->ops = &gb_pwm_ops; pwm->base = -1; /* Allocate base dynamically */ pwm->npwm = pwmc->pwm_max + 1; @@ -225,7 +225,7 @@ static int gb_pwm_probe(struct gpbridge_device *gpbdev, ret = pwmchip_add(pwm); if (ret) { - dev_err(&gpbdev->dev, + dev_err(&gbphy_dev->dev, "failed to register PWM: %d\n", ret); goto exit_connection_disable; } @@ -241,9 +241,9 @@ exit_pwmc_free: return ret; } -static void gb_pwm_remove(struct gpbridge_device *gpbdev) +static void gb_pwm_remove(struct gbphy_device *gbphy_dev) { - struct gb_pwm_chip *pwmc = gb_gpbridge_get_data(gpbdev); + struct gb_pwm_chip *pwmc = gb_gbphy_get_data(gbphy_dev); struct gb_connection *connection = pwmc->connection; pwmchip_remove(&pwmc->chip); @@ -252,18 +252,18 @@ static void gb_pwm_remove(struct gpbridge_device *gpbdev) kfree(pwmc); } -static const struct gpbridge_device_id gb_pwm_id_table[] = { - { GPBRIDGE_PROTOCOL(GREYBUS_PROTOCOL_PWM) }, +static const struct gbphy_device_id gb_pwm_id_table[] = { + { GBPHY_PROTOCOL(GREYBUS_PROTOCOL_PWM) }, { }, }; -MODULE_DEVICE_TABLE(gpbridge, gb_pwm_id_table); +MODULE_DEVICE_TABLE(gbphy, gb_pwm_id_table); -static struct gpbridge_driver pwm_driver = { +static struct gbphy_driver pwm_driver = { .name = "pwm", .probe = gb_pwm_probe, .remove = gb_pwm_remove, .id_table = gb_pwm_id_table, }; -module_gpbridge_driver(pwm_driver); +module_gbphy_driver(pwm_driver); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index 7f063b4..4d4cfdf 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -15,11 +15,11 @@ #include <linux/workqueue.h> #include "greybus.h" -#include "gpbridge.h" +#include "gbphy.h" struct gb_sdio_host { struct gb_connection *connection; - struct gpbridge_device *gpbdev; + struct gbphy_device *gbphy_dev; struct mmc_host *mmc; struct mmc_request *mrq; struct mutex lock; /* lock for this host */ @@ -708,8 +708,8 @@ static const struct mmc_host_ops gb_sdio_ops = { .get_cd = gb_mmc_get_cd, }; -static int gb_sdio_probe(struct gpbridge_device *gpbdev, - const struct gpbridge_device_id *id) +static int gb_sdio_probe(struct gbphy_device *gbphy_dev, + const struct gbphy_device_id *id) { struct gb_connection *connection; struct mmc_host *mmc; @@ -717,12 +717,12 @@ static int gb_sdio_probe(struct gpbridge_device *gpbdev, size_t max_buffer; int ret = 0; - mmc = mmc_alloc_host(sizeof(*host), &gpbdev->dev); + mmc = mmc_alloc_host(sizeof(*host), &gbphy_dev->dev); if (!mmc) return -ENOMEM; - connection = gb_connection_create(gpbdev->bundle, - le16_to_cpu(gpbdev->cport_desc->id), + connection = gb_connection_create(gbphy_dev->bundle, + le16_to_cpu(gbphy_dev->cport_desc->id), gb_sdio_request_handler); if (IS_ERR(connection)) { ret = PTR_ERR(connection); @@ -735,14 +735,14 @@ static int gb_sdio_probe(struct gpbridge_device *gpbdev, host->connection = connection; gb_connection_set_data(connection, host); - host->gpbdev = gpbdev; - gb_gpbridge_set_data(gpbdev, host); + host->gbphy_dev = gbphy_dev; + gb_gbphy_set_data(gbphy_dev, host); ret = gb_connection_enable_tx(connection); if (ret) goto exit_connection_destroy; - ret = gb_gpbridge_get_version(connection); + ret = gb_gbphy_get_version(connection); if (ret) goto exit_connection_disable; @@ -767,7 +767,7 @@ static int gb_sdio_probe(struct gpbridge_device *gpbdev, mutex_init(&host->lock); spin_lock_init(&host->xfer); host->mrq_workqueue = alloc_workqueue("mmc-%s", 0, 1, - dev_name(&gpbdev->dev)); + dev_name(&gbphy_dev->dev)); if (!host->mrq_workqueue) { ret = -ENOMEM; goto exit_buf_free; @@ -801,9 +801,9 @@ exit_mmc_free: return ret; } -static void gb_sdio_remove(struct gpbridge_device *gpbdev) +static void gb_sdio_remove(struct gbphy_device *gbphy_dev) { - struct gb_sdio_host *host = gb_gpbridge_get_data(gpbdev); + struct gb_sdio_host *host = gb_gbphy_get_data(gbphy_dev); struct gb_connection *connection = host->connection; struct mmc_host *mmc; @@ -823,18 +823,18 @@ static void gb_sdio_remove(struct gpbridge_device *gpbdev) mmc_free_host(mmc); } -static const struct gpbridge_device_id gb_sdio_id_table[] = { - { GPBRIDGE_PROTOCOL(GREYBUS_PROTOCOL_SDIO) }, +static const struct gbphy_device_id gb_sdio_id_table[] = { + { GBPHY_PROTOCOL(GREYBUS_PROTOCOL_SDIO) }, { }, }; -MODULE_DEVICE_TABLE(gpbridge, gb_sdio_id_table); +MODULE_DEVICE_TABLE(gbphy, gb_sdio_id_table); -static struct gpbridge_driver sdio_driver = { +static struct gbphy_driver sdio_driver = { .name = "sdio", .probe = gb_sdio_probe, .remove = gb_sdio_remove, .id_table = gb_sdio_id_table, }; -module_gpbridge_driver(sdio_driver); +module_gbphy_driver(sdio_driver); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index 1cf5f50..4f13efe 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -10,17 +10,17 @@ #include <linux/module.h> #include "greybus.h" -#include "gpbridge.h" +#include "gbphy.h" #include "spilib.h" -static int gb_spi_probe(struct gpbridge_device *gpbdev, - const struct gpbridge_device_id *id) +static int gb_spi_probe(struct gbphy_device *gbphy_dev, + const struct gbphy_device_id *id) { struct gb_connection *connection; int ret; - connection = gb_connection_create(gpbdev->bundle, - le16_to_cpu(gpbdev->cport_desc->id), + connection = gb_connection_create(gbphy_dev->bundle, + le16_to_cpu(gbphy_dev->cport_desc->id), NULL); if (IS_ERR(connection)) return PTR_ERR(connection); @@ -29,15 +29,15 @@ static int gb_spi_probe(struct gpbridge_device *gpbdev, if (ret) goto exit_connection_destroy; - ret = gb_gpbridge_get_version(connection); + ret = gb_gbphy_get_version(connection); if (ret) goto exit_connection_disable; - ret = gb_spilib_master_init(connection, &gpbdev->dev); + ret = gb_spilib_master_init(connection, &gbphy_dev->dev); if (ret) goto exit_connection_disable; - gb_gpbridge_set_data(gpbdev, connection); + gb_gbphy_set_data(gbphy_dev, connection); return 0; @@ -49,27 +49,27 @@ exit_connection_destroy: return ret; } -static void gb_spi_remove(struct gpbridge_device *gpbdev) +static void gb_spi_remove(struct gbphy_device *gbphy_dev) { - struct gb_connection *connection = gb_gpbridge_get_data(gpbdev); + struct gb_connection *connection = gb_gbphy_get_data(gbphy_dev); gb_spilib_master_exit(connection); gb_connection_disable(connection); gb_connection_destroy(connection); } -static const struct gpbridge_device_id gb_spi_id_table[] = { - { GPBRIDGE_PROTOCOL(GREYBUS_PROTOCOL_SPI) }, +static const struct gbphy_device_id gb_spi_id_table[] = { + { GBPHY_PROTOCOL(GREYBUS_PROTOCOL_SPI) }, { }, }; -MODULE_DEVICE_TABLE(gpbridge, gb_spi_id_table); +MODULE_DEVICE_TABLE(gbphy, gb_spi_id_table); -static struct gpbridge_driver spi_driver = { +static struct gbphy_driver spi_driver = { .name = "spi", .probe = gb_spi_probe, .remove = gb_spi_remove, .id_table = gb_spi_id_table, }; -module_gpbridge_driver(spi_driver); +module_gbphy_driver(spi_driver); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 75fa527..5d8f4e8 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -29,7 +29,7 @@ #include <linux/kdev_t.h> #include "greybus.h" -#include "gpbridge.h" +#include "gbphy.h" #define GB_NUM_MINORS 16 /* 16 is is more than enough */ #define GB_NAME "ttyGB" @@ -42,7 +42,7 @@ struct gb_tty_line_coding { }; struct gb_tty { - struct gpbridge_device *gpbdev; + struct gbphy_device *gbphy_dev; struct tty_port port; void *buffer; size_t buffer_payload_max; @@ -78,7 +78,7 @@ static int gb_uart_receive_data_handler(struct gb_operation *op) unsigned long tty_flags = TTY_NORMAL; if (request->payload_size < sizeof(*receive_data)) { - dev_err(&gb_tty->gpbdev->dev, + dev_err(&gb_tty->gbphy_dev->dev, "short receive-data request received (%zu < %zu)\n", request->payload_size, sizeof(*receive_data)); return -EINVAL; @@ -88,7 +88,7 @@ static int gb_uart_receive_data_handler(struct gb_operation *op) recv_data_size = le16_to_cpu(receive_data->size); if (recv_data_size != request->payload_size - sizeof(*receive_data)) { - dev_err(&gb_tty->gpbdev->dev, + dev_err(&gb_tty->gbphy_dev->dev, "malformed receive-data request received (%u != %zu)\n", recv_data_size, request->payload_size - sizeof(*receive_data)); @@ -113,7 +113,7 @@ static int gb_uart_receive_data_handler(struct gb_operation *op) count = tty_insert_flip_string_fixed_flag(port, receive_data->data, tty_flags, recv_data_size); if (count != recv_data_size) { - dev_err(&gb_tty->gpbdev->dev, + dev_err(&gb_tty->gbphy_dev->dev, "UART: RX 0x%08x bytes only wrote 0x%08x\n", recv_data_size, count); } @@ -130,7 +130,7 @@ static int gb_uart_serial_state_handler(struct gb_operation *op) struct gb_uart_serial_state_request *serial_state; if (request->payload_size < sizeof(*serial_state)) { - dev_err(&gb_tty->gpbdev->dev, + dev_err(&gb_tty->gbphy_dev->dev, "short serial-state event received (%zu < %zu)\n", request->payload_size, sizeof(*serial_state)); return -EINVAL; @@ -157,7 +157,7 @@ static int gb_uart_request_handler(struct gb_operation *op) ret = gb_uart_serial_state_handler(op); break; default: - dev_err(&gb_tty->gpbdev->dev, + dev_err(&gb_tty->gbphy_dev->dev, "unsupported unsolicited request: 0x%02x\n", type); ret = -EINVAL; } @@ -211,7 +211,7 @@ static int send_break(struct gb_tty *gb_tty, u8 state) struct gb_uart_set_break_request request; if ((state != 0) && (state != 1)) { - dev_err(&gb_tty->gpbdev->dev, + dev_err(&gb_tty->gbphy_dev->dev, "invalid break state of %d\n", state); return -EINVAL; } @@ -619,8 +619,8 @@ static const struct tty_operations gb_ops = { static struct tty_port_operations null_ops = { }; -static int gb_uart_probe(struct gpbridge_device *gpbdev, - const struct gpbridge_device_id *id) +static int gb_uart_probe(struct gbphy_device *gbphy_dev, + const struct gbphy_device_id *id) { struct gb_connection *connection; size_t max_payload; @@ -633,8 +633,8 @@ static int gb_uart_probe(struct gpbridge_device *gpbdev, if (!gb_tty) return -ENOMEM; - connection = gb_connection_create(gpbdev->bundle, - le16_to_cpu(gpbdev->cport_desc->id), + connection = gb_connection_create(gbphy_dev->bundle, + le16_to_cpu(gbphy_dev->cport_desc->id), gb_uart_request_handler); if (IS_ERR(connection)) { retval = PTR_ERR(connection); @@ -678,15 +678,15 @@ static int gb_uart_probe(struct gpbridge_device *gpbdev, gb_tty->port.ops = &null_ops; gb_tty->connection = connection; - gb_tty->gpbdev = gpbdev; + gb_tty->gbphy_dev = gbphy_dev; gb_connection_set_data(connection, gb_tty); - gb_gpbridge_set_data(gpbdev, gb_tty); + gb_gbphy_set_data(gbphy_dev, gb_tty); retval = gb_connection_enable_tx(connection); if (retval) goto exit_release_minor; - retval = gb_gpbridge_get_version(connection); + retval = gb_gbphy_get_version(connection); if (retval) goto exit_connection_disable; @@ -704,7 +704,7 @@ static int gb_uart_probe(struct gpbridge_device *gpbdev, goto exit_connection_disable; tty_dev = tty_port_register_device(&gb_tty->port, gb_tty_driver, minor, - &gpbdev->dev); + &gbphy_dev->dev); if (IS_ERR(tty_dev)) { retval = PTR_ERR(tty_dev); goto exit_connection_disable; @@ -727,9 +727,9 @@ exit_tty_free: return retval; } -static void gb_uart_remove(struct gpbridge_device *gpbdev) +static void gb_uart_remove(struct gbphy_device *gbphy_dev) { - struct gb_tty *gb_tty = gb_gpbridge_get_data(gpbdev); + struct gb_tty *gb_tty = gb_gbphy_get_data(gbphy_dev); struct gb_connection *connection = gb_tty->connection; struct tty_struct *tty; @@ -800,13 +800,13 @@ static void gb_tty_exit(void) idr_destroy(&tty_minors); } -static const struct gpbridge_device_id gb_uart_id_table[] = { - { GPBRIDGE_PROTOCOL(GREYBUS_PROTOCOL_UART) }, +static const struct gbphy_device_id gb_uart_id_table[] = { + { GBPHY_PROTOCOL(GREYBUS_PROTOCOL_UART) }, { }, }; -MODULE_DEVICE_TABLE(gpbridge, gb_uart_id_table); +MODULE_DEVICE_TABLE(gbphy, gb_uart_id_table); -static struct gpbridge_driver uart_driver = { +static struct gbphy_driver uart_driver = { .name = "uart", .probe = gb_uart_probe, .remove = gb_uart_remove, @@ -821,7 +821,7 @@ static int gb_uart_driver_init(void) if (ret) return ret; - ret = gb_gpbridge_register(&uart_driver); + ret = gb_gbphy_register(&uart_driver); if (ret) { gb_tty_exit(); return ret; @@ -833,7 +833,7 @@ module_init(gb_uart_driver_init); static void gb_uart_driver_exit(void) { - gb_gpbridge_deregister(&uart_driver); + gb_gbphy_deregister(&uart_driver); gb_tty_exit(); } diff --git a/drivers/staging/greybus/usb.c b/drivers/staging/greybus/usb.c index 2f68a1b..7ed6a60 100644 --- a/drivers/staging/greybus/usb.c +++ b/drivers/staging/greybus/usb.c @@ -14,7 +14,7 @@ #include <linux/usb/hcd.h> #include "greybus.h" -#include "gpbridge.h" +#include "gbphy.h" /* Version of the Greybus USB protocol we support */ #define GB_USB_VERSION_MAJOR 0x00 @@ -38,7 +38,7 @@ struct gb_usb_hub_control_response { struct gb_usb_device { struct gb_connection *connection; - struct gpbridge_device *gpbdev; + struct gbphy_device *gbphy_dev; }; static inline struct gb_usb_device *to_gb_usb_device(struct usb_hcd *hcd) @@ -59,7 +59,7 @@ static void hcd_stop(struct usb_hcd *hcd) ret = gb_operation_sync(dev->connection, GB_USB_TYPE_HCD_STOP, NULL, 0, NULL, 0); if (ret) - dev_err(&dev->gpbdev->dev, "HCD stop failed '%d'\n", ret); + dev_err(&dev->gbphy_dev->dev, "HCD stop failed '%d'\n", ret); } static int hcd_start(struct usb_hcd *hcd) @@ -71,7 +71,7 @@ static int hcd_start(struct usb_hcd *hcd) ret = gb_operation_sync(dev->connection, GB_USB_TYPE_HCD_START, NULL, 0, NULL, 0); if (ret) { - dev_err(&dev->gpbdev->dev, "HCD start failed '%d'\n", ret); + dev_err(&dev->gbphy_dev->dev, "HCD start failed '%d'\n", ret); return ret; } @@ -161,11 +161,11 @@ static struct hc_driver usb_gb_hc_driver = { .hub_control = hub_control, }; -static int gb_usb_probe(struct gpbridge_device *gpbdev, - const struct gpbridge_device_id *id) +static int gb_usb_probe(struct gbphy_device *gbphy_dev, + const struct gbphy_device_id *id) { struct gb_connection *connection; - struct device *dev = &gpbdev->dev; + struct device *dev = &gbphy_dev->dev; struct gb_usb_device *gb_usb_dev; struct usb_hcd *hcd; int retval; @@ -174,8 +174,8 @@ static int gb_usb_probe(struct gpbridge_device *gpbdev, if (!hcd) return -ENOMEM; - connection = gb_connection_create(gpbdev->bundle, - le16_to_cpu(gpbdev->cport_desc->id), + connection = gb_connection_create(gbphy_dev->bundle, + le16_to_cpu(gbphy_dev->cport_desc->id), NULL); if (IS_ERR(connection)) { retval = PTR_ERR(connection); @@ -185,8 +185,8 @@ static int gb_usb_probe(struct gpbridge_device *gpbdev, gb_usb_dev = to_gb_usb_device(hcd); gb_usb_dev->connection = connection; gb_connection_set_data(connection, gb_usb_dev); - gb_usb_dev->gpbdev = gpbdev; - gb_gpbridge_set_data(gpbdev, gb_usb_dev); + gb_usb_dev->gbphy_dev = gbphy_dev; + gb_gbphy_set_data(gbphy_dev, gb_usb_dev); hcd->has_tt = 1; @@ -194,7 +194,7 @@ static int gb_usb_probe(struct gpbridge_device *gpbdev, if (retval) goto exit_connection_destroy; - retval = gb_gpbridge_get_version(connection); + retval = gb_gbphy_get_version(connection); if (retval) goto exit_connection_disable; @@ -226,9 +226,9 @@ exit_usb_put: return retval; } -static void gb_usb_remove(struct gpbridge_device *gpbdev) +static void gb_usb_remove(struct gbphy_device *gbphy_dev) { - struct gb_usb_device *gb_usb_dev = gb_gpbridge_get_data(gpbdev); + struct gb_usb_device *gb_usb_dev = gb_gbphy_get_data(gbphy_dev); struct gb_connection *connection = gb_usb_dev->connection; struct usb_hcd *hcd = gb_usb_device_to_hcd(gb_usb_dev); @@ -238,18 +238,18 @@ static void gb_usb_remove(struct gpbridge_device *gpbdev) usb_put_hcd(hcd); } -static const struct gpbridge_device_id gb_usb_id_table[] = { - { GPBRIDGE_PROTOCOL(GREYBUS_PROTOCOL_USB) }, +static const struct gbphy_device_id gb_usb_id_table[] = { + { GBPHY_PROTOCOL(GREYBUS_PROTOCOL_USB) }, { }, }; -MODULE_DEVICE_TABLE(gpbridge, gb_usb_id_table); +MODULE_DEVICE_TABLE(gbphy, gb_usb_id_table); -static struct gpbridge_driver usb_driver = { +static struct gbphy_driver usb_driver = { .name = "usb", .probe = gb_usb_probe, .remove = gb_usb_remove, .id_table = gb_usb_id_table, }; -module_gpbridge_driver(usb_driver); +module_gbphy_driver(usb_driver); MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 16fd976c392bf2e9b88531e842d8d255bccddc98 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Date: Tue, 17 May 2016 22:39:46 +0530 Subject: greybus: arche-platform: Do not assert wake/detect signal to SVC With new definition of AP module boot flow (from HotPlug camp), AP is not supposed to send any wake/detect signal to SVC, instead, during boot SVC would straight away send wake_out pulse on wake/detect line. Note that, pin configuration of wake/detect line would be set to active-high by default, so wake/detect line would always stay high, unless SVC drives it. AP module uses wake/detect line strictly in input mode. Testing Done: Tested on EVT1.5 platform. Note: We are yet to decide on PM support for APBx, so we may need to generate/handshake with SVC over wake/detect line in the future. As of now, follow the implementation and add stuff as and when they come. Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index e385434..c02ff58 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -207,9 +207,6 @@ static int apb_poweroff(struct device *dev, void *data) static void assert_wakedetect(struct arche_platform_drvdata *arche_pdata) { - /* Assert wake/detect = Detect event from AP */ - gpio_direction_output(arche_pdata->wake_detect_gpio, 1); - /* Enable interrupt here, to read event back from SVC */ gpio_direction_input(arche_pdata->wake_detect_gpio); enable_irq(arche_pdata->wake_detect_irq); @@ -371,9 +368,7 @@ static void arche_platform_poweroff_seq(struct arche_platform_drvdata *arche_pda /* If in fw_flashing mode, then no need to repeate things again */ if (arche_pdata->state != ARCHE_PLATFORM_STATE_FW_FLASHING) { disable_irq(arche_pdata->wake_detect_irq); - /* Send disconnect/detach event to SVC */ - gpio_direction_output(arche_pdata->wake_detect_gpio, 0); - usleep_range(100, 200); + spin_lock_irqsave(&arche_pdata->wake_lock, flags); arche_platform_set_wake_detect_state(arche_pdata, WD_STATE_IDLE); @@ -411,9 +406,9 @@ static ssize_t state_store(struct device *dev, if (arche_pdata->state == ARCHE_PLATFORM_STATE_ACTIVE) goto exit; + assert_wakedetect(arche_pdata); ret = arche_platform_coldboot_seq(arche_pdata); - assert_wakedetect(arche_pdata); } else if (sysfs_streq(buf, "standby")) { if (arche_pdata->state == ARCHE_PLATFORM_STATE_STANDBY) goto exit; @@ -484,8 +479,8 @@ static int arche_platform_pm_notifier(struct notifier_block *notifier, arche_platform_poweroff_seq(arche_pdata); break; case PM_POST_SUSPEND: - arche_platform_coldboot_seq(arche_pdata); assert_wakedetect(arche_pdata); + arche_platform_coldboot_seq(arche_pdata); break; default: break; @@ -588,8 +583,7 @@ static int arche_platform_probe(struct platform_device *pdev) arche_pdata->wake_detect_gpio); return ret; } - /* deassert wake detect */ - gpio_direction_output(arche_pdata->wake_detect_gpio, 0); + arche_platform_set_wake_detect_state(arche_pdata, WD_STATE_IDLE); arche_pdata->dev = &pdev->dev; @@ -608,8 +602,8 @@ static int arche_platform_probe(struct platform_device *pdev) dev_err(dev, "failed to request wake detect IRQ %d\n", ret); return ret; } - /* Enable it only after sending wake/detect event */ - disable_irq(arche_pdata->wake_detect_irq); + + assert_wakedetect(arche_pdata); ret = device_create_file(dev, &dev_attr_state); if (ret) { @@ -630,8 +624,6 @@ static int arche_platform_probe(struct platform_device *pdev) goto err_populate; } - assert_wakedetect(arche_pdata); - arche_pdata->pm_notifier.notifier_call = arche_platform_pm_notifier; ret = register_pm_notifier(&arche_pdata->pm_notifier); mutex_unlock(&arche_pdata->platform_state_mutex); -- cgit v0.10.2 From 7ba535ec69ff670976e69adeec24dac2b65560ee Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Date: Tue, 17 May 2016 22:39:47 +0530 Subject: greybus: arche-platform: Rename assert_wakedetect=>arche_platform_wd_irq_en Now, since AP module does not send any signal to SVC, so it automatically restricts the wake/detect gpio to input. So rename assert_wakedetect() fn to arche_platform_wd_irq_en(), as per implementation. Testing Done: Tested on EVT1.5 platform. Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index c02ff58..bc45077 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -205,7 +205,7 @@ static int apb_poweroff(struct device *dev, void *data) return 0; } -static void assert_wakedetect(struct arche_platform_drvdata *arche_pdata) +static void arche_platform_wd_irq_en(struct arche_platform_drvdata *arche_pdata) { /* Enable interrupt here, to read event back from SVC */ gpio_direction_input(arche_pdata->wake_detect_gpio); @@ -406,7 +406,7 @@ static ssize_t state_store(struct device *dev, if (arche_pdata->state == ARCHE_PLATFORM_STATE_ACTIVE) goto exit; - assert_wakedetect(arche_pdata); + arche_platform_wd_irq_en(arche_pdata); ret = arche_platform_coldboot_seq(arche_pdata); } else if (sysfs_streq(buf, "standby")) { @@ -479,7 +479,7 @@ static int arche_platform_pm_notifier(struct notifier_block *notifier, arche_platform_poweroff_seq(arche_pdata); break; case PM_POST_SUSPEND: - assert_wakedetect(arche_pdata); + arche_platform_wd_irq_en(arche_pdata); arche_platform_coldboot_seq(arche_pdata); break; default: @@ -603,7 +603,7 @@ static int arche_platform_probe(struct platform_device *pdev) return ret; } - assert_wakedetect(arche_pdata); + arche_platform_wd_irq_en(arche_pdata); ret = device_create_file(dev, &dev_attr_state); if (ret) { -- cgit v0.10.2 From 0bba4fb53adff8ee1538a654bfb5ac79298cc5dc Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Thu, 19 May 2016 16:20:14 +0200 Subject: greybus: svc: fix another pwrmon return value Errno -ENOSYS is reserved for missing syscalls, replace it with -ENOMSG. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 80e8cf0..3e22ed8 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -202,7 +202,7 @@ int gb_svc_pwrmon_intf_sample_get(struct gb_svc *svc, u8 intf_id, case GB_SVC_PWRMON_GET_SAMPLE_INVAL: return -EINVAL; case GB_SVC_PWRMON_GET_SAMPLE_NOSUPP: - return -ENOSYS; + return -ENOMSG; default: return -EIO; } -- cgit v0.10.2 From deda6aaf666706346866b7d828098ba9bacfb742 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Thu, 19 May 2016 16:20:15 +0200 Subject: greybus: audio_apbridgea: fix two return values Errno -ENOSYS is reserved for missing syscalls, replace it with -EOPNOTSUPP for the the two stub operations that used it. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_apbridgea.c b/drivers/staging/greybus/audio_apbridgea.c index a6e089d..3614707 100644 --- a/drivers/staging/greybus/audio_apbridgea.c +++ b/drivers/staging/greybus/audio_apbridgea.c @@ -78,7 +78,7 @@ int gb_audio_apbridgea_get_tx_delay(struct gb_connection *connection, __u16 i2s_port, __u32 *delay) { /* TODO: implement */ - return -ENOSYS; + return -EOPNOTSUPP; } EXPORT_SYMBOL_GPL(gb_audio_apbridgea_get_tx_delay); @@ -152,7 +152,7 @@ int gb_audio_apbridgea_get_rx_delay(struct gb_connection *connection, __u16 i2s_port, __u32 *delay) { /* TODO: implement */ - return -ENOSYS; + return -EOPNOTSUPP; } EXPORT_SYMBOL_GPL(gb_audio_apbridgea_get_rx_delay); -- cgit v0.10.2 From 4aea5a15ad6d8fbd9d344a84c0396176e7512d3d Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Thu, 19 May 2016 16:20:16 +0200 Subject: greybus: svc: use EREMOTEIO for remote errors Return -EREMOTEIO consistently for unspecified remote errors (e.g. a failed DME attribute read due to a remote UniPro error). Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 3e22ed8..78cc0e3 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -166,7 +166,7 @@ static int gb_svc_pwrmon_sample_get(struct gb_svc *svc, u8 rail_id, case GB_SVC_PWRMON_GET_SAMPLE_NOSUPP: return -ENOMSG; default: - return -EIO; + return -EREMOTEIO; } } @@ -204,7 +204,7 @@ int gb_svc_pwrmon_intf_sample_get(struct gb_svc *svc, u8 intf_id, case GB_SVC_PWRMON_GET_SAMPLE_NOSUPP: return -ENOMSG; default: - return -EIO; + return -EREMOTEIO; } } @@ -376,7 +376,7 @@ int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, if (result) { dev_err(&svc->dev, "UniPro error while getting DME attribute (%u 0x%04x %u): %u\n", intf_id, attr, selector, result); - return -EIO; + return -EREMOTEIO; } if (value) @@ -412,7 +412,7 @@ int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, if (result) { dev_err(&svc->dev, "UniPro error while setting DME attribute (%u 0x%04x %u %u): %u\n", intf_id, attr, selector, value, result); - return -EIO; + return -EREMOTEIO; } return 0; -- cgit v0.10.2 From 825f79ae7620fa98586c4d2504030eca96d55c59 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 19 May 2016 18:27:25 +0530 Subject: greybus: fw-core: destroy connections on error In one of the error cases we aren't destroying the connections created earlier. Fix it. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/fw-core.c b/drivers/staging/greybus/fw-core.c index 90d3222..33941ef 100644 --- a/drivers/staging/greybus/fw-core.c +++ b/drivers/staging/greybus/fw-core.c @@ -139,7 +139,7 @@ static int gb_fw_core_probe(struct gb_bundle *bundle, dev_err(&bundle->dev, "invalid protocol id (0x%02x)\n", protocol_id); ret = -EINVAL; - goto err_free_fw_core; + goto err_destroy_connections; } } @@ -187,7 +187,6 @@ err_destroy_connections: gb_connection_destroy(fw_core->mgmt_connection); gb_connection_destroy(fw_core->spi_connection); gb_connection_destroy(fw_core->download_connection); -err_free_fw_core: kfree(fw_core); return ret; -- cgit v0.10.2 From d72b5810cba5fd6f77f22742df1cb4a3c473cd6b Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 19 May 2016 18:26:27 +0530 Subject: greybus: fw-management: Fix error message's text Just reword it to make it sound better. Compile tested. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/fw-management.c b/drivers/staging/greybus/fw-management.c index 96758f4..da36de3 100644 --- a/drivers/staging/greybus/fw-management.c +++ b/drivers/staging/greybus/fw-management.c @@ -352,7 +352,7 @@ static int fw_mgmt_backend_fw_updated_operation(struct gb_operation *op) if (fw_mgmt->backend_fw_status != GB_FW_BACKEND_FW_STATUS_SUCCESS) dev_err(fw_mgmt->parent, - "failed to backend load firmware, status:%02x\n", + "failed to load backend firmware: %02x\n", fw_mgmt->backend_fw_status); complete(&fw_mgmt->completion); -- cgit v0.10.2 From 68b66c28010ebc2ebe21d6bad2de2eda1bed01fc Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Date: Fri, 20 May 2016 14:33:35 +0300 Subject: greybus: camera: Convert to bundle driver Convert the legacy camera protocol driver to a bundle driver. Modules now can (and must) declare the camera data cport in their manifest as the data connection isn't hardcoded anymore. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 4831ad6..dd482bd 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -36,11 +36,11 @@ struct gb_camera_debugfs_buffer { /** * struct gb_camera - A Greybus Camera Device * @connection: the greybus connection for camera control - * @data_connected: whether the data connection has been established * @debugfs: debugfs entries for camera protocol operations testing * @module: Greybus camera module registered to HOST processor. */ struct gb_camera { + struct gb_bundle *bundle; struct gb_connection *connection; struct gb_connection *data_connection; @@ -103,12 +103,9 @@ static const struct gb_camera_fmt_map mbus_to_gbus_format[] = { #define GB_CAMERA_MAX_SETTINGS_SIZE 8192 -#define gcam_dbg(gcam, format...) \ - dev_dbg(&gcam->connection->bundle->dev, format) -#define gcam_info(gcam, format...) \ - dev_info(&gcam->connection->bundle->dev, format) -#define gcam_err(gcam, format...) \ - dev_err(&gcam->connection->bundle->dev, format) +#define gcam_dbg(gcam, format...) dev_dbg(&gcam->bundle->dev, format) +#define gcam_info(gcam, format...) dev_info(&gcam->bundle->dev, format) +#define gcam_err(gcam, format...) dev_err(&gcam->bundle->dev, format) /* ----------------------------------------------------------------------------- * Camera Protocol Operations @@ -383,14 +380,14 @@ static int gb_camera_flush(struct gb_camera *gcam, u32 *request_id) return 0; } -static int gb_camera_event_recv(u8 type, struct gb_operation *op) +static int gb_camera_request_handler(struct gb_operation *op) { struct gb_camera *gcam = gb_connection_get_data(op->connection); struct gb_camera_metadata_request *payload; struct gb_message *request; - if (type != GB_CAMERA_TYPE_METADATA) { - gcam_err(gcam, "Unsupported unsolicited event: %u\n", type); + if (op->type != GB_CAMERA_TYPE_METADATA) { + gcam_err(gcam, "Unsupported unsolicited event: %u\n", op->type); return -EINVAL; } @@ -849,7 +846,7 @@ static int gb_camera_debugfs_init(struct gb_camera *gcam) * Create root debugfs entry and a file entry for each camera operation. */ snprintf(dirname, 27, "camera-%u.%u", connection->intf->interface_id, - connection->bundle->id); + gcam->bundle->id); gcam->debugfs.root = debugfs_create_dir(dirname, gb_debugfs_get()); if (IS_ERR(gcam->debugfs.root)) { @@ -905,39 +902,84 @@ static void gb_camera_cleanup(struct gb_camera *gcam) gb_connection_destroy(gcam->data_connection); } + if (gcam->connection) { + gb_connection_disable(gcam->connection); + gb_connection_destroy(gcam->connection); + } + kfree(gcam); } -static int gb_camera_connection_init(struct gb_connection *connection) +static int gb_camera_probe(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) { - struct gb_connection *data; + struct gb_connection *conn; struct gb_camera *gcam; - unsigned long data_flags; + u16 mgmt_cport_id = 0; + u16 data_cport_id = 0; + unsigned int i; int ret; + /* + * The camera bundle must contain exactly two CPorts, one for the + * camera management protocol and one for the camera data protocol. + */ + if (bundle->num_cports != 2) + return -ENODEV; + + for (i = 0; i < bundle->num_cports; ++i) { + struct greybus_descriptor_cport *desc = &bundle->cport_desc[i]; + + switch (desc->protocol_id) { + case GREYBUS_PROTOCOL_CAMERA_MGMT: + mgmt_cport_id = le16_to_cpu(desc->id); + break; + case GREYBUS_PROTOCOL_CAMERA_DATA: + data_cport_id = le16_to_cpu(desc->id); + break; + default: + return -ENODEV; + } + } + + if (!mgmt_cport_id || !data_cport_id) + return -ENODEV; + gcam = kzalloc(sizeof(*gcam), GFP_KERNEL); if (!gcam) return -ENOMEM; - gcam->connection = connection; - gb_connection_set_data(connection, gcam); + gcam->bundle = bundle; + + conn = gb_connection_create(bundle, mgmt_cport_id, + gb_camera_request_handler); + if (IS_ERR(conn)) { + ret = PTR_ERR(conn); + goto error; + } + + gcam->connection = conn; + gb_connection_set_data(conn, gcam); + + ret = gb_connection_enable(conn); + if (ret) + goto error; /* - * Create the data connection between camera module CDSI0 and APB CDS1. - * The CPort IDs are hardcoded by the ES2 bridges. + * Create the data connection between the camera module data CPort and + * APB CDSI1. The CDSI1 CPort ID is hardcoded by the ES2 bridge. */ - data_flags = GB_CONNECTION_FLAG_NO_FLOWCTRL | GB_CONNECTION_FLAG_CDSI1; - - data = gb_connection_create_offloaded(connection->bundle, - ES2_APB_CDSI0_CPORT, - data_flags); - if (IS_ERR(data)) { - ret = PTR_ERR(data); + conn = gb_connection_create_offloaded(bundle, data_cport_id, + GB_CONNECTION_FLAG_NO_FLOWCTRL | + GB_CONNECTION_FLAG_CDSI1); + if (IS_ERR(conn)) { + ret = PTR_ERR(conn); goto error; } - gcam->data_connection = data; + gcam->data_connection = conn; + gb_connection_set_data(conn, gcam); - ret = gb_connection_enable(data); + ret = gb_connection_enable(conn); if (ret) goto error; @@ -949,6 +991,8 @@ static int gb_camera_connection_init(struct gb_connection *connection) if (ret < 0) goto error; + greybus_set_drvdata(bundle, gcam); + return 0; error: @@ -956,25 +1000,26 @@ error: return ret; } -static void gb_camera_connection_exit(struct gb_connection *connection) +static void gb_camera_disconnect(struct gb_bundle *bundle) { - struct gb_camera *gcam = gb_connection_get_data(connection); + struct gb_camera *gcam = greybus_get_drvdata(bundle); gb_camera_unregister_intf_ops(gcam); - gb_camera_cleanup(gcam); } -static struct gb_protocol camera_protocol = { - .name = "camera", - .id = GREYBUS_PROTOCOL_CAMERA_MGMT, - .major = GB_CAMERA_VERSION_MAJOR, - .minor = GB_CAMERA_VERSION_MINOR, - .connection_init = gb_camera_connection_init, - .connection_exit = gb_camera_connection_exit, - .request_recv = gb_camera_event_recv, +static const struct greybus_bundle_id gb_camera_id_table[] = { + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_CAMERA) }, + { }, +}; + +static struct greybus_driver gb_camera_driver = { + .name = "camera", + .probe = gb_camera_probe, + .disconnect = gb_camera_disconnect, + .id_table = gb_camera_id_table, }; -gb_protocol_driver(&camera_protocol); +module_greybus_driver(gb_camera_driver); MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index 06bd85c..19f3d93 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -236,7 +236,6 @@ static void legacy_disconnect(struct gb_bundle *bundle) } static const struct greybus_bundle_id legacy_id_table[] = { - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_CAMERA) }, { } }; MODULE_DEVICE_TABLE(greybus, legacy_id_table); -- cgit v0.10.2 From 428888a2b672444dbab9bb5127b7f583ab58ff2f Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Fri, 20 May 2016 14:33:36 +0300 Subject: greybus: legacy: remove legacy driver support This patch removes the greybus legacy driver support Signed-off-by: David Lin <dtwlin@google.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index ae9a478..6d07b1b 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -11,8 +11,7 @@ greybus-y := core.o \ svc.o \ svc_watchdog.o \ bootrom.o \ - operation.o \ - legacy.o + operation.o gb-gbphy-y := gbphy.o diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index b152e23..53ce2845 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -43,7 +43,6 @@ struct gb_connection { gb_request_handler_t handler; unsigned long flags; - struct gb_protocol *protocol; u8 module_major; u8 module_minor; diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index a44846d..6d6a2bb 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -13,7 +13,6 @@ #include "bootrom.h" #include "greybus.h" #include "greybus_trace.h" -#include "legacy.h" EXPORT_TRACEPOINT_SYMBOL_GPL(gb_host_device_send); EXPORT_TRACEPOINT_SYMBOL_GPL(gb_host_device_recv); @@ -266,16 +265,8 @@ static int __init gb_init(void) goto error_bootrom; } - retval = gb_legacy_init(); - if (retval) { - pr_err("gb_legacy_init failed\n"); - goto error_legacy; - } - return 0; /* Success */ -error_legacy: - gb_bootrom_exit(); error_bootrom: gb_operation_exit(); error_operation: @@ -291,7 +282,6 @@ module_init(gb_init); static void __exit gb_exit(void) { - gb_legacy_exit(); gb_bootrom_exit(); gb_operation_exit(); gb_hd_exit(); diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index f5447e7..e0b194c 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -32,7 +32,6 @@ #include "interface.h" #include "bundle.h" #include "connection.h" -#include "protocol.h" #include "operation.h" diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c deleted file mode 100644 index 19f3d93..0000000 --- a/drivers/staging/greybus/legacy.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Greybus legacy-protocol driver - * - * Copyright 2015 Google Inc. - * Copyright 2015 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#include "greybus.h" -#include "legacy.h" -#include "protocol.h" - - -struct legacy_connection { - struct gb_connection *connection; - bool initialized; - struct gb_protocol *protocol; -}; - -struct legacy_data { - size_t num_cports; - struct legacy_connection *connections; -}; - - -static int legacy_connection_get_version(struct gb_connection *connection) -{ - int ret; - - ret = gb_protocol_get_version(connection); - if (ret) { - dev_err(&connection->hd->dev, - "%s: failed to get protocol version: %d\n", - connection->name, ret); - return ret; - } - - return 0; -} - -static int legacy_request_handler(struct gb_operation *operation) -{ - struct gb_protocol *protocol = operation->connection->protocol; - - return protocol->request_recv(operation->type, operation); -} - -static int legacy_connection_init(struct legacy_connection *lc) -{ - struct gb_connection *connection = lc->connection; - int ret; - - dev_dbg(&connection->bundle->dev, "%s - %s\n", __func__, - connection->name); - - ret = gb_connection_enable(connection); - if (ret) - return ret; - - ret = legacy_connection_get_version(connection); - if (ret) - goto err_disable; - - ret = connection->protocol->connection_init(connection); - if (ret) - goto err_disable; - - lc->initialized = true; - - return 0; - -err_disable: - gb_connection_disable(connection); - - return ret; -} - -static void legacy_connection_exit(struct legacy_connection *lc) -{ - struct gb_connection *connection = lc->connection; - - if (!lc->initialized) - return; - - gb_connection_disable(connection); - - connection->protocol->connection_exit(connection); - - lc->initialized = false; -} - -static int legacy_connection_create(struct legacy_connection *lc, - struct gb_bundle *bundle, - struct greybus_descriptor_cport *desc) -{ - struct gb_connection *connection; - struct gb_protocol *protocol; - gb_request_handler_t handler; - u8 major, minor; - int ret; - - /* - * The legacy protocols have always been looked up using a hard-coded - * version of 0.1, despite (or perhaps rather, due to) the fact that - * module version negotiation could not take place until after the - * protocol was bound. - */ - major = 0; - minor = 1; - - protocol = gb_protocol_get(desc->protocol_id, major, minor); - if (!protocol) { - dev_err(&bundle->dev, - "protocol 0x%02x version %u.%u not found\n", - desc->protocol_id, major, minor); - return -EPROTONOSUPPORT; - } - - if (protocol->request_recv) - handler = legacy_request_handler; - else - handler = NULL; - - connection = gb_connection_create(bundle, le16_to_cpu(desc->id), - handler); - if (IS_ERR(connection)) { - ret = PTR_ERR(connection); - goto err_protocol_put; - } - - /* - * NOTE: We need to keep a pointer to the protocol in the actual - * connection structure for now. - */ - connection->protocol = protocol; - - lc->connection = connection; - lc->protocol = protocol; - - return 0; - -err_protocol_put: - gb_protocol_put(protocol); - - return ret; -} - -static void legacy_connection_destroy(struct legacy_connection *lc) -{ - if (!lc->connection) - return; - - lc->connection->protocol = NULL; - - gb_connection_destroy(lc->connection); - - gb_protocol_put(lc->protocol); -} - -static int legacy_probe(struct gb_bundle *bundle, - const struct greybus_bundle_id *id) -{ - struct greybus_descriptor_cport *cport_desc; - struct legacy_data *data; - struct legacy_connection *lc; - int i; - int ret; - - dev_dbg(&bundle->dev, - "%s - bundle class = 0x%02x, num_cports = %zu\n", - __func__, bundle->class, bundle->num_cports); - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->num_cports = bundle->num_cports; - data->connections = kcalloc(data->num_cports, - sizeof(*data->connections), - GFP_KERNEL); - if (!data->connections) { - ret = -ENOMEM; - goto err_free_data; - } - - for (i = 0; i < data->num_cports; ++i) { - cport_desc = &bundle->cport_desc[i]; - lc = &data->connections[i]; - - ret = legacy_connection_create(lc, bundle, cport_desc); - if (ret) - goto err_connections_destroy; - } - - greybus_set_drvdata(bundle, data); - - for (i = 0; i < data->num_cports; ++i) { - lc = &data->connections[i]; - - ret = legacy_connection_init(lc); - if (ret) - goto err_connections_disable; - } - - return 0; - -err_connections_disable: - for (--i; i >= 0; --i) - legacy_connection_exit(&data->connections[i]); -err_connections_destroy: - for (i = 0; i < data->num_cports; ++i) - legacy_connection_destroy(&data->connections[i]); - kfree(data->connections); -err_free_data: - kfree(data); - - return ret; -} - -static void legacy_disconnect(struct gb_bundle *bundle) -{ - struct legacy_data *data = greybus_get_drvdata(bundle); - int i; - - dev_dbg(&bundle->dev, "%s - bundle class = 0x%02x\n", __func__, - bundle->class); - - for (i = 0; i < data->num_cports; ++i) { - legacy_connection_exit(&data->connections[i]); - legacy_connection_destroy(&data->connections[i]); - } - - kfree(data->connections); - kfree(data); -} - -static const struct greybus_bundle_id legacy_id_table[] = { - { } -}; -MODULE_DEVICE_TABLE(greybus, legacy_id_table); - -static struct greybus_driver legacy_driver = { - .name = "legacy", - .probe = legacy_probe, - .disconnect = legacy_disconnect, - .id_table = legacy_id_table, -}; - -int gb_legacy_init(void) -{ - return greybus_register(&legacy_driver); -} - -void gb_legacy_exit(void) -{ - greybus_deregister(&legacy_driver); -} diff --git a/drivers/staging/greybus/legacy.h b/drivers/staging/greybus/legacy.h deleted file mode 100644 index 2177f6a..0000000 --- a/drivers/staging/greybus/legacy.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Greybus legacy-protocol driver - * - * Copyright 2015 Google Inc. - * Copyright 2015 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#ifndef __LEGACY_H -#define __LEGACY_H - -int gb_legacy_init(void); -void gb_legacy_exit(void); - -#endif /* __LEGACY_H */ diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c deleted file mode 100644 index 057ab60..0000000 --- a/drivers/staging/greybus/protocol.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Greybus protocol handling - * - * Copyright 2014-2015 Google Inc. - * Copyright 2014-2015 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include "greybus.h" - -/* Global list of registered protocols */ -static DEFINE_SPINLOCK(gb_protocols_lock); -static LIST_HEAD(gb_protocols); - -/* Caller must hold gb_protocols_lock */ -static struct gb_protocol *gb_protocol_find(u8 id, u8 major, u8 minor) -{ - struct gb_protocol *protocol; - - list_for_each_entry(protocol, &gb_protocols, links) { - if (protocol->id < id) - continue; - if (protocol->id > id) - break; - - if (protocol->major > major) - continue; - if (protocol->major < major) - break; - - if (protocol->minor > minor) - continue; - if (protocol->minor < minor) - break; - - return protocol; - } - return NULL; -} - -int __gb_protocol_register(struct gb_protocol *protocol, struct module *module) -{ - struct gb_protocol *existing; - u8 id = protocol->id; - u8 major = protocol->major; - u8 minor = protocol->minor; - - protocol->owner = module; - - /* - * The protocols list is sorted first by protocol id (low to - * high), then by major version (high to low), and finally - * by minor version (high to low). Searching only by - * protocol id will produce the newest implemented version - * of the protocol. - */ - spin_lock_irq(&gb_protocols_lock); - - list_for_each_entry(existing, &gb_protocols, links) { - if (existing->id < id) - continue; - if (existing->id > id) - break; - - if (existing->major > major) - continue; - if (existing->major < major) - break; - - if (existing->minor > minor) - continue; - if (existing->minor < minor) - break; - - /* A matching protocol has already been registered */ - spin_unlock_irq(&gb_protocols_lock); - - return -EEXIST; - } - - /* - * We need to insert the protocol here, before the existing one - * (or before the head if we searched the whole list) - */ - list_add_tail(&protocol->links, &existing->links); - spin_unlock_irq(&gb_protocols_lock); - - pr_info("Registered %s protocol.\n", protocol->name); - - return 0; -} -EXPORT_SYMBOL_GPL(__gb_protocol_register); - -/* - * De-register a previously registered protocol. - */ -void gb_protocol_deregister(struct gb_protocol *protocol) -{ - if (!protocol) - return; - - spin_lock_irq(&gb_protocols_lock); - protocol = gb_protocol_find(protocol->id, protocol->major, - protocol->minor); - if (WARN_ON(!protocol || protocol->count)) { - spin_unlock_irq(&gb_protocols_lock); - return; - } - - list_del(&protocol->links); - spin_unlock_irq(&gb_protocols_lock); - - pr_info("Deregistered %s protocol.\n", protocol->name); -} -EXPORT_SYMBOL_GPL(gb_protocol_deregister); - -/* Returns the requested protocol if available, or a null pointer */ -struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor) -{ - struct gb_protocol *protocol; - u8 protocol_count; - - spin_lock_irq(&gb_protocols_lock); - protocol = gb_protocol_find(id, major, minor); - if (protocol) { - if (!try_module_get(protocol->owner)) { - protocol = NULL; - } else { - protocol_count = protocol->count; - if (protocol_count != U8_MAX) - protocol->count++; - } - } - spin_unlock_irq(&gb_protocols_lock); - - if (protocol) - WARN_ON(protocol_count == U8_MAX); - - return protocol; -} -EXPORT_SYMBOL_GPL(gb_protocol_get); - -int gb_protocol_get_version(struct gb_connection *connection) -{ - struct gb_protocol_version_request request; - struct gb_protocol_version_response response; - struct gb_protocol *protocol = connection->protocol; - int retval; - - request.major = protocol->major; - request.minor = protocol->minor; - - retval = gb_operation_sync(connection, GB_REQUEST_TYPE_PROTOCOL_VERSION, - &request, sizeof(request), &response, - sizeof(response)); - if (retval) - return retval; - - if (response.major > connection->protocol->major) { - dev_err(&connection->hd->dev, - "%s: unsupported major version (%u > %u)\n", - connection->name, response.major, - connection->protocol->major); - return -ENOTSUPP; - } - - connection->module_major = response.major; - connection->module_minor = response.minor; - - dev_dbg(&connection->hd->dev, - "%s: %s (0x%02x) v%u.%u\n", connection->name, - protocol->name, protocol->id, response.major, response.minor); - - return 0; -} -EXPORT_SYMBOL_GPL(gb_protocol_get_version); - -void gb_protocol_put(struct gb_protocol *protocol) -{ - u8 id; - u8 major; - u8 minor; - - id = protocol->id; - major = protocol->major; - minor = protocol->minor; - - spin_lock_irq(&gb_protocols_lock); - protocol = gb_protocol_find(id, major, minor); - if (WARN_ON(!protocol || !protocol->count)) - goto out; - - protocol->count--; - module_put(protocol->owner); -out: - spin_unlock_irq(&gb_protocols_lock); -} -EXPORT_SYMBOL_GPL(gb_protocol_put); diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h deleted file mode 100644 index 38fe14c..0000000 --- a/drivers/staging/greybus/protocol.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Greybus protocol handling - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#ifndef __PROTOCOL_H -#define __PROTOCOL_H - -struct gb_connection; -struct gb_operation; - -typedef int (*gb_connection_init_t)(struct gb_connection *); -typedef void (*gb_connection_exit_t)(struct gb_connection *); -typedef int (*gb_request_recv_t)(u8, struct gb_operation *); - -/* - * Protocols having the same id but different major and/or minor - * version numbers are treated as distinct protocols. If it makes - * sense someday we could group protocols having the same id. - */ -struct gb_protocol { - u8 id; - u8 major; - u8 minor; - u8 count; - - struct list_head links; /* global list */ - - gb_connection_init_t connection_init; - gb_connection_exit_t connection_exit; - gb_request_recv_t request_recv; - struct module *owner; - char *name; -}; - -int __gb_protocol_register(struct gb_protocol *protocol, struct module *module); -void gb_protocol_deregister(struct gb_protocol *protocol); - -#define gb_protocol_register(protocol) \ - __gb_protocol_register(protocol, THIS_MODULE) - -struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor); -int gb_protocol_get_version(struct gb_connection *connection); - -void gb_protocol_put(struct gb_protocol *protocol); - -/* __protocol: Pointer to struct gb_protocol */ -#define gb_protocol_driver(__protocol) \ -static int __init protocol_init(void) \ -{ \ - return gb_protocol_register(__protocol); \ -} \ -module_init(protocol_init); \ -static void __exit protocol_exit(void) \ -{ \ - gb_protocol_deregister(__protocol); \ -} \ -module_exit(protocol_exit) - -/* __protocol: string matching name of struct gb_protocol */ -#define gb_builtin_protocol_driver(__protocol) \ -int __init gb_##__protocol##_init(void) \ -{ \ - return gb_protocol_register(&__protocol); \ -} \ -void gb_##__protocol##_exit(void) \ -{ \ - gb_protocol_deregister(&__protocol); \ -} \ - -#endif /* __PROTOCOL_H */ -- cgit v0.10.2 From f866e66f368ee58954d83e6e99194ffcd6dfcad5 Mon Sep 17 00:00:00 2001 From: Alex Elder <elder@linaro.org> Date: Fri, 20 May 2016 11:59:57 -0500 Subject: greybus: add operation traces Define a new gb_operation event class, and define and use trace events that record when an operation is created, finally destroyed, and when its active count changes. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h index 849cfa0..3b4875d 100644 --- a/drivers/staging/greybus/greybus_trace.h +++ b/drivers/staging/greybus/greybus_trace.h @@ -15,6 +15,7 @@ #include <linux/tracepoint.h> struct gb_message; +struct gb_operation; struct gb_host_device; #define gb_bundle_name(message) \ @@ -111,6 +112,74 @@ DEFINE_EVENT(gb_message, gb_message_cancel_incoming, TP_ARGS(message) ); +DECLARE_EVENT_CLASS(gb_operation, + + TP_PROTO(struct gb_operation *operation), + + TP_ARGS(operation), + + TP_STRUCT__entry( + __field(u16, cport_id) /* CPort of HD side of connection */ + __field(u16, id) /* Operation ID */ + __field(u8, type) + __field(unsigned long, flags) + __field(int, active) + __field(int, waiters) + __field(int, errno) + ), + + TP_fast_assign( + __entry->cport_id = operation->connection->hd_cport_id; + __entry->id = operation->id; + __entry->type = operation->type; + __entry->flags = operation->flags; + __entry->active = operation->active; + __entry->waiters = atomic_read(&operation->waiters); + __entry->errno = operation->errno; + ), + + TP_printk("id=%04x type=0x%02x cport_id=%04x flags=0x%lx active=%d waiters=%d errno=%d", + __entry->id, __entry->cport_id, __entry->type, __entry->flags, + __entry->active, __entry->waiters, __entry->errno) +); + +#define DEFINE_OPERATION_EVENT(name) \ + DEFINE_EVENT(gb_operation, name, \ + TP_PROTO(struct gb_operation *operation), \ + TP_ARGS(operation)) + +/* + * Occurs after a new operation is created for an outgoing request + * has been successfully created. + */ +DEFINE_OPERATION_EVENT(gb_operation_create); + +/* + * Occurs after a new operation has been created for an incoming + * request has been successfully created and initialized. + */ +DEFINE_OPERATION_EVENT(gb_operation_create_incoming); + +/* + * Occurs when the last reference to an operation has been dropped, + * prior to freeing resources. + */ +DEFINE_OPERATION_EVENT(gb_operation_destroy); + +/* + * Occurs when an operation has been marked active, after updating + * its active count. + */ +DEFINE_OPERATION_EVENT(gb_operation_get_active); + +/* + * Occurs when an operation has been marked active, before updating + * its active count. + */ +DEFINE_OPERATION_EVENT(gb_operation_put_active); + +#undef DEFINE_OPERATION_EVENT + DECLARE_EVENT_CLASS(gb_host_device, TP_PROTO(struct gb_host_device *hd, u16 intf_cport_id, diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index b7cc59d..259bd92 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -57,6 +57,8 @@ static int gb_operation_get_active(struct gb_operation *operation) if (operation->active++ == 0) list_add_tail(&operation->links, &connection->operations); + trace_gb_operation_get_active(operation); + spin_unlock_irqrestore(&connection->lock, flags); return 0; @@ -69,6 +71,9 @@ static void gb_operation_put_active(struct gb_operation *operation) unsigned long flags; spin_lock_irqsave(&connection->lock, flags); + + trace_gb_operation_get_active(operation); + if (--operation->active == 0) { list_del(&operation->links); if (atomic_read(&operation->waiters)) @@ -536,6 +541,8 @@ gb_operation_create_flags(struct gb_connection *connection, size_t response_size, unsigned long flags, gfp_t gfp) { + struct gb_operation *operation; + if (WARN_ON_ONCE(type == GB_REQUEST_TYPE_INVALID)) return NULL; if (WARN_ON_ONCE(type & GB_MESSAGE_TYPE_RESPONSE)) @@ -544,9 +551,14 @@ gb_operation_create_flags(struct gb_connection *connection, if (WARN_ON_ONCE(flags & ~GB_OPERATION_FLAG_USER_MASK)) flags &= GB_OPERATION_FLAG_USER_MASK; - return gb_operation_create_common(connection, type, + operation = gb_operation_create_common(connection, type, request_size, response_size, flags, gfp); + if (operation) + trace_gb_operation_create(operation); + + return operation; + } EXPORT_SYMBOL_GPL(gb_operation_create_flags); @@ -581,6 +593,7 @@ gb_operation_create_incoming(struct gb_connection *connection, u16 id, operation->id = id; memcpy(operation->request->header, data, size); + trace_gb_operation_create_incoming(operation); return operation; } @@ -603,6 +616,8 @@ static void _gb_operation_destroy(struct kref *kref) operation = container_of(kref, struct gb_operation, kref); + trace_gb_operation_destroy(operation); + if (operation->response) gb_operation_message_free(operation->response); gb_operation_message_free(operation->request); -- cgit v0.10.2 From 630175698e9b3a1e24d62dddb9059f5bdcbb7cec Mon Sep 17 00:00:00 2001 From: Alex Elder <elder@linaro.org> Date: Fri, 20 May 2016 11:44:55 -0500 Subject: greybus: tracing: define events using macros A tracepoint event is defined with TP_PROTO() and TP_ARGS macros that match that of the event's class. A lot of repetition (and opportunity for inadvertent errors) in tracepoint event definitions can be eliminated by using a macro. Define and use class-specific event definition macros for gb_message and gb_host_device class events. Signed-off-by: Alex Elder <elder@linaro.org> Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Reviewed-by: Jeffrey Carlyle <jcarlyle@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h index 3b4875d..40c24cf 100644 --- a/drivers/staging/greybus/greybus_trace.h +++ b/drivers/staging/greybus/greybus_trace.h @@ -52,65 +52,47 @@ DECLARE_EVENT_CLASS(gb_message, __entry->hd_cport_id, __entry->payload_size) ); +#define DEFINE_MESSAGE_EVENT(name) \ + DEFINE_EVENT(gb_message, name, \ + TP_PROTO(struct gb_message *message), \ + TP_ARGS(message)) + /* * tracepoint name greybus:gb_message_send * description send a greybus message * location operation.c:gb_message_send */ -DEFINE_EVENT(gb_message, gb_message_send, - - TP_PROTO(struct gb_message *message), - - TP_ARGS(message) -); +DEFINE_MESSAGE_EVENT(gb_message_send); /* * tracepoint name greybus:gb_message_recv_request * description receive a greybus request * location operation.c:gb_connection_recv_request */ -DEFINE_EVENT(gb_message, gb_message_recv_request, - - TP_PROTO(struct gb_message *message), - - TP_ARGS(message) -); +DEFINE_MESSAGE_EVENT(gb_message_recv_request); /* * tracepoint name greybus:gb_message_recv_response * description receive a greybus response * location operation.c:gb_connection_recv_response */ -DEFINE_EVENT(gb_message, gb_message_recv_response, - - TP_PROTO(struct gb_message *message), - - TP_ARGS(message) -); +DEFINE_MESSAGE_EVENT(gb_message_recv_response); /* * tracepoint name greybus:gb_message_cancel_outgoing * description cancel outgoing greybus request * location operation.c:gb_message_cancel */ -DEFINE_EVENT(gb_message, gb_message_cancel_outgoing, - - TP_PROTO(struct gb_message *message), - - TP_ARGS(message) -); +DEFINE_MESSAGE_EVENT(gb_message_cancel_outgoing); /* * tracepoint name greybus:gb_message_cancel_incoming * description cancel incoming greybus request * location operation.c:gb_message_cancel_incoming */ -DEFINE_EVENT(gb_message, gb_message_cancel_incoming, - - TP_PROTO(struct gb_message *message), +DEFINE_MESSAGE_EVENT(gb_message_cancel_incoming); - TP_ARGS(message) -); +#undef DEFINE_MESSAGE_EVENT DECLARE_EVENT_CLASS(gb_operation, @@ -203,31 +185,28 @@ DECLARE_EVENT_CLASS(gb_host_device, __entry->intf_cport_id, __entry->payload_size) ); +#define DEFINE_HD_EVENT(name) \ + DEFINE_EVENT(gb_host_device, name, \ + TP_PROTO(struct gb_host_device *hd, \ + u16 intf_cport_id, \ + size_t payload_size), \ + TP_ARGS(hd, intf_cport_id, payload_size)) + /* * tracepoint name greybus:gb_host_device_send * description tracepoint representing the point data are transmitted * location es2.c:message_send */ -DEFINE_EVENT(gb_host_device, gb_host_device_send, - - TP_PROTO(struct gb_host_device *hd, u16 intf_cport_id, - size_t payload_size), - - TP_ARGS(hd, intf_cport_id, payload_size) -); +DEFINE_HD_EVENT(gb_host_device_send); /* * tracepoint name greybus:gb_host_device_recv * description tracepoint representing the point data are received * location es2.c:cport_in_callback */ -DEFINE_EVENT(gb_host_device, gb_host_device_recv, +DEFINE_HD_EVENT(gb_host_device_recv); - TP_PROTO(struct gb_host_device *hd, u16 intf_cport_id, - size_t payload_size), - - TP_ARGS(hd, intf_cport_id, payload_size) -); +#undef DEFINE_HD_EVENT #endif /* _TRACE_GREYBUS_H */ -- cgit v0.10.2 From 58a881376357caec4c992b73779102142096d383 Mon Sep 17 00:00:00 2001 From: Alex Elder <elder@linaro.org> Date: Fri, 20 May 2016 11:44:56 -0500 Subject: greybus: tracing: eliminate "location" comments Each message event has a set of comments preceeding its definition. One of them, "location", indicates where that event is used. I am certain that this comment will become out of date very easily. Hopefully just the name of the event is a good enough suggestion about where it will be used. Signed-off-by: Alex Elder <elder@linaro.org> Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Reviewed-by: Jeffrey Carlyle <jcarlyle@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h index 40c24cf..4fd9269 100644 --- a/drivers/staging/greybus/greybus_trace.h +++ b/drivers/staging/greybus/greybus_trace.h @@ -60,35 +60,30 @@ DECLARE_EVENT_CLASS(gb_message, /* * tracepoint name greybus:gb_message_send * description send a greybus message - * location operation.c:gb_message_send */ DEFINE_MESSAGE_EVENT(gb_message_send); /* * tracepoint name greybus:gb_message_recv_request * description receive a greybus request - * location operation.c:gb_connection_recv_request */ DEFINE_MESSAGE_EVENT(gb_message_recv_request); /* * tracepoint name greybus:gb_message_recv_response * description receive a greybus response - * location operation.c:gb_connection_recv_response */ DEFINE_MESSAGE_EVENT(gb_message_recv_response); /* * tracepoint name greybus:gb_message_cancel_outgoing * description cancel outgoing greybus request - * location operation.c:gb_message_cancel */ DEFINE_MESSAGE_EVENT(gb_message_cancel_outgoing); /* * tracepoint name greybus:gb_message_cancel_incoming * description cancel incoming greybus request - * location operation.c:gb_message_cancel_incoming */ DEFINE_MESSAGE_EVENT(gb_message_cancel_incoming); @@ -195,14 +190,12 @@ DECLARE_EVENT_CLASS(gb_host_device, /* * tracepoint name greybus:gb_host_device_send * description tracepoint representing the point data are transmitted - * location es2.c:message_send */ DEFINE_HD_EVENT(gb_host_device_send); /* * tracepoint name greybus:gb_host_device_recv * description tracepoint representing the point data are received - * location es2.c:cport_in_callback */ DEFINE_HD_EVENT(gb_host_device_recv); -- cgit v0.10.2 From 206dc534e99a5bfc10a699442f0c20d372eacf44 Mon Sep 17 00:00:00 2001 From: Alex Elder <elder@linaro.org> Date: Fri, 20 May 2016 11:44:57 -0500 Subject: greybus: tracing: refine comments I believe that duplicating the tracepoint name in comments prior to the tracepoint is redundant, and doesn't add a lot of value. I also believe that we can provide a little more information about what exactly an event means, or when exactly it is called. I don't claim this is a huge improvement, but it's a proposal. Signed-off-by: Alex Elder <elder@linaro.org> Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Reviewed-by: Jeffrey Carlyle <jcarlyle@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h index 4fd9269..ba93873 100644 --- a/drivers/staging/greybus/greybus_trace.h +++ b/drivers/staging/greybus/greybus_trace.h @@ -58,32 +58,31 @@ DECLARE_EVENT_CLASS(gb_message, TP_ARGS(message)) /* - * tracepoint name greybus:gb_message_send - * description send a greybus message + * Occurs immediately before calling a host device's message_send() + * method. */ DEFINE_MESSAGE_EVENT(gb_message_send); /* - * tracepoint name greybus:gb_message_recv_request - * description receive a greybus request + * Occurs after an incoming request message has been received */ DEFINE_MESSAGE_EVENT(gb_message_recv_request); /* - * tracepoint name greybus:gb_message_recv_response - * description receive a greybus response + * Occurs after an incoming response message has been received, + * after its matching request has been found. */ DEFINE_MESSAGE_EVENT(gb_message_recv_response); /* - * tracepoint name greybus:gb_message_cancel_outgoing - * description cancel outgoing greybus request + * Occurs after an operation has been canceled, possibly before the + * cancellation is complete. */ DEFINE_MESSAGE_EVENT(gb_message_cancel_outgoing); /* - * tracepoint name greybus:gb_message_cancel_incoming - * description cancel incoming greybus request + * Occurs when an incoming request is cancelled; if the response has + * been queued for sending, this occurs after it is sent. */ DEFINE_MESSAGE_EVENT(gb_message_cancel_incoming); @@ -188,14 +187,14 @@ DECLARE_EVENT_CLASS(gb_host_device, TP_ARGS(hd, intf_cport_id, payload_size)) /* - * tracepoint name greybus:gb_host_device_send - * description tracepoint representing the point data are transmitted + * Occurs immediately before calling usb_submit_urb() to send a + * message to the UniPro bridge. */ DEFINE_HD_EVENT(gb_host_device_send); /* - * tracepoint name greybus:gb_host_device_recv - * description tracepoint representing the point data are received + * Occurs after receiving a UniPro message via the USB subsystem, + * just prior to handing it to the Greybus core for handling. */ DEFINE_HD_EVENT(gb_host_device_recv); -- cgit v0.10.2 From 038405db982987bbe01ddc1fd90fba2dba700dd4 Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Fri, 20 May 2016 18:37:02 -0700 Subject: greybus: legacy: remove protocol.o from the makefile Commit 0917cba11 ("legacy: remove legacy driver support") removed protocol.c, however, the corresponding target in the Makefile was not removed therefore broken the build. Testing Done: - Build & boot on EVT1.5 Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 6d07b1b..f7fe4d5 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -6,7 +6,6 @@ greybus-y := core.o \ interface.o \ bundle.o \ connection.o \ - protocol.o \ control.o \ svc.o \ svc_watchdog.o \ -- cgit v0.10.2 From 37f07c0c974d78bfcdc9f3267438c91163fc3ae5 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Mon, 23 May 2016 23:31:14 +0530 Subject: greybus: audio: Fix memory leak Topology data pointer was mistakenly set to NULL before freeing it. Fix this. Fixes: 64a86d9ba850 ("audio: Add module specific driver") Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_module.c b/drivers/staging/greybus/audio_module.c index 57d3b02..53e84f5 100644 --- a/drivers/staging/greybus/audio_module.c +++ b/drivers/staging/greybus/audio_module.c @@ -368,8 +368,8 @@ static void gb_audio_disconnect(struct gb_bundle *bundle) gbaudio_unregister_module(gbmodule); gbaudio_tplg_release(gbmodule); - gbmodule->topology = NULL; kfree(gbmodule->topology); + gbmodule->topology = NULL; gb_connection_disable(gbmodule->mgmt_connection); list_for_each_entry_safe(dai, _dai, &gbmodule->data_list, list) { gb_connection_disable(dai->connection); -- cgit v0.10.2 From d7be800f7ae9398055509b3a83d0ea3118e9277f Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Mon, 23 May 2016 15:01:08 +0100 Subject: greybus: Fix unbalanced irq_enable() backtrace Tip-of-tree is exhibiting a backtrace when loading-up the set of greybus kernel modules due to calling arche_platform_wd_irq_en() directly after a call to devm_request_threaded_irq(). At the point we call arch_platform_wd_irq_en() the relevant IRQ will already be enabled. What we want to do in this situation is configure the GPIO line as an input. This patch fixes the backtrace by supplanting arche_platform_wd_irq_en() with gpio_direction_input(arche_pdata->wake_detect_gpio) in arche_platform_probe(). WARNING: at msm-ara-3.10/kernel/irq/manage.c:457 __enable_irq+0x74/0xc0() Unbalanced enable for IRQ 687 Modules linked in: gb_arche(O+) gb_camera(O) gb_es2(O) gb_vibrator(O) gb_raw(O) gb_power_supply(O) gb_loopback(O) gb_light(O) gb_hid(O) greybus(O) CPU: 0 PID: 415 Comm: insmod Tainted: G W O 3.10.78-g2a4dec8 #65 Call trace: [<ffffffc000206adc>] dump_backtrace+0x0/0x248 [<ffffffc000206d34>] show_stack+0x10/0x1c [<ffffffc000c6c698>] dump_stack+0x1c/0x28 [<ffffffc00021c95c>] warn_slowpath_common+0x74/0x9c [<ffffffc00021c9d0>] warn_slowpath_fmt+0x4c/0x58 [<ffffffc000269d7c>] __enable_irq+0x70/0xc0 [<ffffffc000269e34>] enable_irq+0x68/0x7c [<ffffffbffc0609b4>] arche_platform_probe+0x3b4/0x4f4 [gb_arche] [<ffffffc0005ace30>] platform_drv_probe+0x14/0x20 [<ffffffc0005ab980>] driver_probe_device+0x160/0x374 [<ffffffc0005abc40>] __driver_attach+0x60/0x90 [<ffffffc0005aa768>] bus_for_each_dev+0x74/0x94 [<ffffffc0005ab2c4>] driver_attach+0x1c/0x28 [<ffffffc0005aae74>] bus_add_driver+0x124/0x248 [<ffffffc0005ac270>] driver_register+0x94/0x110 [<ffffffc0005ad3c4>] platform_driver_register+0x58/0x64 [<ffffffbffc065020>] $x+0x20/0x58 [gb_arche] [<ffffffc0002007dc>] do_one_initcall+0xb0/0x14c [<ffffffc00028252c>] load_module+0x19d0/0x1b18 [<ffffffc00028278c>] SyS_init_module+0x118/0x130 Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Reviewed-by: Vaibhav Hiremath <vaibhav.hiermath@linaro.org> Tested-by: Rui Miguel Silva <rui.silva@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index bc45077..4af3498 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -603,7 +603,7 @@ static int arche_platform_probe(struct platform_device *pdev) return ret; } - arche_platform_wd_irq_en(arche_pdata); + gpio_direction_input(arche_pdata->wake_detect_gpio); ret = device_create_file(dev, &dev_attr_state); if (ret) { -- cgit v0.10.2 From 00606367141cf518e94d8354a02d298475de67e5 Mon Sep 17 00:00:00 2001 From: Eli Sennesh <esennesh@leaflabs.com> Date: Mon, 16 May 2016 14:55:17 -0400 Subject: greybus: update UniPro Set Interface Power Mode operation to match spec Bring the gb_svc_intf_set_power_mode() up-to-date with the current Greybus specification. This largely involves adding more members to the structure sent across the wire. Also change the camera code to use the new operation properly, with default values passed for the new necessary arguments. The correctness of these default values is confirmed via testing and by asking Rob Johnson. Testing Done: Took a picture with a camera module, received error code when passing deliberately incorrect values for new parameters, got proper -EIO and Greybus result code printed when operation stopped halfway through. Associated Firmware Changes: 6810-6812 on Gerrit for SW-1239, 6870 and 5612-5613 on Gerrit for SW-2945 Signed-off-by: Eli Sennesh <esennesh@leaflabs.com> Reviewed-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index dd482bd..654bfcd 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -121,17 +121,23 @@ static int gb_camera_set_intf_power_mode(struct gb_camera *gcam, u8 intf_id, ret = gb_svc_intf_set_power_mode(svc, intf_id, GB_SVC_UNIPRO_HS_SERIES_A, GB_SVC_UNIPRO_FAST_MODE, 2, 2, + GB_SVC_SMALL_AMPLITUDE, + GB_SVC_NO_DE_EMPHASIS, GB_SVC_UNIPRO_FAST_MODE, 2, 2, GB_SVC_PWRM_RXTERMINATION | - GB_SVC_PWRM_TXTERMINATION, 0); + GB_SVC_PWRM_TXTERMINATION, 0, + NULL, NULL); else ret = gb_svc_intf_set_power_mode(svc, intf_id, GB_SVC_UNIPRO_HS_SERIES_A, GB_SVC_UNIPRO_SLOW_AUTO_MODE, 2, 1, + GB_SVC_SMALL_AMPLITUDE, + GB_SVC_NO_DE_EMPHASIS, GB_SVC_UNIPRO_SLOW_AUTO_MODE, 2, 1, - 0, 0); + 0, 0, + NULL, NULL); return ret; } diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index b98f02c..ec3570a 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -1136,6 +1136,13 @@ struct gb_svc_timesync_ping_response { #define GB_SVC_UNIPRO_HIBERNATE_MODE 0x11 #define GB_SVC_UNIPRO_OFF_MODE 0x12 +#define GB_SVC_SMALL_AMPLITUDE 0x01 +#define GB_SVC_LARGE_AMPLITUDE 0x02 + +#define GB_SVC_NO_DE_EMPHASIS 0x00 +#define GB_SVC_SMALL_DE_EMPHASIS 0x01 +#define GB_SVC_LARGE_DE_EMPHASIS 0x02 + #define GB_SVC_PWRM_RXTERMINATION 0x01 #define GB_SVC_PWRM_TXTERMINATION 0x02 #define GB_SVC_PWRM_LINE_RESET 0x04 @@ -1146,17 +1153,38 @@ struct gb_svc_timesync_ping_response { #define GB_SVC_UNIPRO_HS_SERIES_A 0x01 #define GB_SVC_UNIPRO_HS_SERIES_B 0x02 +#define GB_SVC_SETPWRM_PWR_OK 0x00 +#define GB_SVC_SETPWRM_PWR_LOCAL 0x01 +#define GB_SVC_SETPWRM_PWR_REMOTE 0x02 +#define GB_SVC_SETPWRM_PWR_BUSY 0x03 +#define GB_SVC_SETPWRM_PWR_ERROR_CAP 0x04 +#define GB_SVC_SETPWRM_PWR_FATAL_ERROR 0x05 + +struct gb_svc_l2_timer_cfg { + __le16 tsb_fc0_protection_timeout; + __le16 tsb_tc0_replay_timeout; + __le16 tsb_afc0_req_timeout; + __le16 tsb_fc1_protection_timeout; + __le16 tsb_tc1_replay_timeout; + __le16 tsb_afc1_req_timeout; + __le16 reserved_for_tc2[3]; + __le16 reserved_for_tc3[3]; +} __packed; + struct gb_svc_intf_set_pwrm_request { __u8 intf_id; __u8 hs_series; __u8 tx_mode; __u8 tx_gear; __u8 tx_nlanes; + __u8 tx_amplitude; + __u8 tx_hs_equalizer; __u8 rx_mode; __u8 rx_gear; __u8 rx_nlanes; __u8 flags; __le32 quirks; + struct gb_svc_l2_timer_cfg local_l2timerdata, remote_l2timerdata; } __packed; struct gb_svc_intf_set_pwrm_response { diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 78cc0e3..90094cf 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -578,23 +578,33 @@ void gb_svc_route_destroy(struct gb_svc *svc, u8 intf1_id, u8 intf2_id) int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series, u8 tx_mode, u8 tx_gear, u8 tx_nlanes, + u8 tx_amplitude, u8 tx_hs_equalizer, u8 rx_mode, u8 rx_gear, u8 rx_nlanes, - u8 flags, u32 quirks) + u8 flags, u32 quirks, + struct gb_svc_l2_timer_cfg *local, + struct gb_svc_l2_timer_cfg *remote) { struct gb_svc_intf_set_pwrm_request request; struct gb_svc_intf_set_pwrm_response response; int ret; + u16 result_code; request.intf_id = intf_id; request.hs_series = hs_series; request.tx_mode = tx_mode; request.tx_gear = tx_gear; request.tx_nlanes = tx_nlanes; + request.tx_amplitude = tx_amplitude; + request.tx_hs_equalizer = tx_hs_equalizer; request.rx_mode = rx_mode; request.rx_gear = rx_gear; request.rx_nlanes = rx_nlanes; request.flags = flags; request.quirks = cpu_to_le32(quirks); + if (local) + request.local_l2timerdata = *local; + if (remote) + request.remote_l2timerdata = *remote; ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_INTF_SET_PWRM, &request, sizeof(request), @@ -602,7 +612,13 @@ int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series, if (ret < 0) return ret; - return le16_to_cpu(response.result_code); + result_code = le16_to_cpu(response.result_code); + if (result_code != GB_SVC_SETPWRM_PWR_LOCAL) { + dev_err(&svc->dev, "set power mode = %d\n", result_code); + return -EIO; + } + + return 0; } EXPORT_SYMBOL_GPL(gb_svc_intf_set_power_mode); @@ -926,9 +942,11 @@ static void gb_svc_process_hello_deferred(struct gb_operation *operation) GB_SVC_UNIPRO_HS_SERIES_A, GB_SVC_UNIPRO_SLOW_AUTO_MODE, 2, 1, + GB_SVC_SMALL_AMPLITUDE, GB_SVC_NO_DE_EMPHASIS, GB_SVC_UNIPRO_SLOW_AUTO_MODE, 2, 1, - 0, 0); + 0, 0, + NULL, NULL); if (ret) dev_warn(&svc->dev, diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index e3e0aa1..438806d 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -77,8 +77,11 @@ int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, u32 value); int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series, u8 tx_mode, u8 tx_gear, u8 tx_nlanes, + u8 tx_amplitude, u8 tx_hs_equalizer, u8 rx_mode, u8 rx_gear, u8 rx_nlanes, - u8 flags, u32 quirks); + u8 flags, u32 quirks, + struct gb_svc_l2_timer_cfg *local, + struct gb_svc_l2_timer_cfg *remote); int gb_svc_ping(struct gb_svc *svc); int gb_svc_watchdog_create(struct gb_svc *svc); void gb_svc_watchdog_destroy(struct gb_svc *svc); -- cgit v0.10.2 From 91a8030f781d27e84661c4a4edf1e108bfc1c594 Mon Sep 17 00:00:00 2001 From: Jeffrey Carlyle <jcarlyle@google.com> Date: Wed, 25 May 2016 16:38:47 -0700 Subject: greybus: Revert "update UniPro Set Interface Power Mode operation to match spec" This reverts commit 29fee8c55b59bb6ac59b99a0563c89c514cba42b. This change and its companion NuttX changes seem to be triggering a storm of POWERMODEIND switch interrupts on the SVC. Signed-off-by: Jeffrey Carlyle <jcarlyle@google.com> Acked-by: Sandeep Patil <sspatil@google.com> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 654bfcd..dd482bd 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -121,23 +121,17 @@ static int gb_camera_set_intf_power_mode(struct gb_camera *gcam, u8 intf_id, ret = gb_svc_intf_set_power_mode(svc, intf_id, GB_SVC_UNIPRO_HS_SERIES_A, GB_SVC_UNIPRO_FAST_MODE, 2, 2, - GB_SVC_SMALL_AMPLITUDE, - GB_SVC_NO_DE_EMPHASIS, GB_SVC_UNIPRO_FAST_MODE, 2, 2, GB_SVC_PWRM_RXTERMINATION | - GB_SVC_PWRM_TXTERMINATION, 0, - NULL, NULL); + GB_SVC_PWRM_TXTERMINATION, 0); else ret = gb_svc_intf_set_power_mode(svc, intf_id, GB_SVC_UNIPRO_HS_SERIES_A, GB_SVC_UNIPRO_SLOW_AUTO_MODE, 2, 1, - GB_SVC_SMALL_AMPLITUDE, - GB_SVC_NO_DE_EMPHASIS, GB_SVC_UNIPRO_SLOW_AUTO_MODE, 2, 1, - 0, 0, - NULL, NULL); + 0, 0); return ret; } diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index ec3570a..b98f02c 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -1136,13 +1136,6 @@ struct gb_svc_timesync_ping_response { #define GB_SVC_UNIPRO_HIBERNATE_MODE 0x11 #define GB_SVC_UNIPRO_OFF_MODE 0x12 -#define GB_SVC_SMALL_AMPLITUDE 0x01 -#define GB_SVC_LARGE_AMPLITUDE 0x02 - -#define GB_SVC_NO_DE_EMPHASIS 0x00 -#define GB_SVC_SMALL_DE_EMPHASIS 0x01 -#define GB_SVC_LARGE_DE_EMPHASIS 0x02 - #define GB_SVC_PWRM_RXTERMINATION 0x01 #define GB_SVC_PWRM_TXTERMINATION 0x02 #define GB_SVC_PWRM_LINE_RESET 0x04 @@ -1153,38 +1146,17 @@ struct gb_svc_timesync_ping_response { #define GB_SVC_UNIPRO_HS_SERIES_A 0x01 #define GB_SVC_UNIPRO_HS_SERIES_B 0x02 -#define GB_SVC_SETPWRM_PWR_OK 0x00 -#define GB_SVC_SETPWRM_PWR_LOCAL 0x01 -#define GB_SVC_SETPWRM_PWR_REMOTE 0x02 -#define GB_SVC_SETPWRM_PWR_BUSY 0x03 -#define GB_SVC_SETPWRM_PWR_ERROR_CAP 0x04 -#define GB_SVC_SETPWRM_PWR_FATAL_ERROR 0x05 - -struct gb_svc_l2_timer_cfg { - __le16 tsb_fc0_protection_timeout; - __le16 tsb_tc0_replay_timeout; - __le16 tsb_afc0_req_timeout; - __le16 tsb_fc1_protection_timeout; - __le16 tsb_tc1_replay_timeout; - __le16 tsb_afc1_req_timeout; - __le16 reserved_for_tc2[3]; - __le16 reserved_for_tc3[3]; -} __packed; - struct gb_svc_intf_set_pwrm_request { __u8 intf_id; __u8 hs_series; __u8 tx_mode; __u8 tx_gear; __u8 tx_nlanes; - __u8 tx_amplitude; - __u8 tx_hs_equalizer; __u8 rx_mode; __u8 rx_gear; __u8 rx_nlanes; __u8 flags; __le32 quirks; - struct gb_svc_l2_timer_cfg local_l2timerdata, remote_l2timerdata; } __packed; struct gb_svc_intf_set_pwrm_response { diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 90094cf..78cc0e3 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -578,33 +578,23 @@ void gb_svc_route_destroy(struct gb_svc *svc, u8 intf1_id, u8 intf2_id) int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series, u8 tx_mode, u8 tx_gear, u8 tx_nlanes, - u8 tx_amplitude, u8 tx_hs_equalizer, u8 rx_mode, u8 rx_gear, u8 rx_nlanes, - u8 flags, u32 quirks, - struct gb_svc_l2_timer_cfg *local, - struct gb_svc_l2_timer_cfg *remote) + u8 flags, u32 quirks) { struct gb_svc_intf_set_pwrm_request request; struct gb_svc_intf_set_pwrm_response response; int ret; - u16 result_code; request.intf_id = intf_id; request.hs_series = hs_series; request.tx_mode = tx_mode; request.tx_gear = tx_gear; request.tx_nlanes = tx_nlanes; - request.tx_amplitude = tx_amplitude; - request.tx_hs_equalizer = tx_hs_equalizer; request.rx_mode = rx_mode; request.rx_gear = rx_gear; request.rx_nlanes = rx_nlanes; request.flags = flags; request.quirks = cpu_to_le32(quirks); - if (local) - request.local_l2timerdata = *local; - if (remote) - request.remote_l2timerdata = *remote; ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_INTF_SET_PWRM, &request, sizeof(request), @@ -612,13 +602,7 @@ int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series, if (ret < 0) return ret; - result_code = le16_to_cpu(response.result_code); - if (result_code != GB_SVC_SETPWRM_PWR_LOCAL) { - dev_err(&svc->dev, "set power mode = %d\n", result_code); - return -EIO; - } - - return 0; + return le16_to_cpu(response.result_code); } EXPORT_SYMBOL_GPL(gb_svc_intf_set_power_mode); @@ -942,11 +926,9 @@ static void gb_svc_process_hello_deferred(struct gb_operation *operation) GB_SVC_UNIPRO_HS_SERIES_A, GB_SVC_UNIPRO_SLOW_AUTO_MODE, 2, 1, - GB_SVC_SMALL_AMPLITUDE, GB_SVC_NO_DE_EMPHASIS, GB_SVC_UNIPRO_SLOW_AUTO_MODE, 2, 1, - 0, 0, - NULL, NULL); + 0, 0); if (ret) dev_warn(&svc->dev, diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index 438806d..e3e0aa1 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -77,11 +77,8 @@ int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, u32 value); int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series, u8 tx_mode, u8 tx_gear, u8 tx_nlanes, - u8 tx_amplitude, u8 tx_hs_equalizer, u8 rx_mode, u8 rx_gear, u8 rx_nlanes, - u8 flags, u32 quirks, - struct gb_svc_l2_timer_cfg *local, - struct gb_svc_l2_timer_cfg *remote); + u8 flags, u32 quirks); int gb_svc_ping(struct gb_svc *svc); int gb_svc_watchdog_create(struct gb_svc *svc); void gb_svc_watchdog_destroy(struct gb_svc *svc); -- cgit v0.10.2 From c61a8b49846ecc11f7959f573b9548f859bc73a5 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Date: Tue, 24 May 2016 18:32:02 +0530 Subject: greybus: arche-platform: Make fw_flashing_seq() return error Make arche_platform_fw_flashing_seq() return error value, needed later when we add clock enable support for FW flashing. Testing Done: Tested on EVT1.5 platform. Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Tested-by: Michael Scott <michael.scott@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 4af3498..a8e36e1 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -335,10 +335,10 @@ static int arche_platform_coldboot_seq(struct arche_platform_drvdata *arche_pdat /* * Requires arche_pdata->platform_state_mutex to be held */ -static void arche_platform_fw_flashing_seq(struct arche_platform_drvdata *arche_pdata) +static int arche_platform_fw_flashing_seq(struct arche_platform_drvdata *arche_pdata) { if (arche_pdata->state == ARCHE_PLATFORM_STATE_FW_FLASHING) - return; + return 0; dev_info(arche_pdata->dev, "Switching to FW flashing state\n"); @@ -353,6 +353,7 @@ static void arche_platform_fw_flashing_seq(struct arche_platform_drvdata *arche_ arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_FW_FLASHING); + return 0; } /* @@ -424,7 +425,9 @@ static ssize_t state_store(struct device *dev, arche_platform_poweroff_seq(arche_pdata); - arche_platform_fw_flashing_seq(arche_pdata); + ret = arche_platform_fw_flashing_seq(arche_pdata); + if (ret) + goto exit; device_for_each_child(arche_pdata->dev, NULL, apb_fw_flashing_state); } else { -- cgit v0.10.2 From 0b1283e33f7a38645c9d060ce2e2b24a44e3b125 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Date: Tue, 24 May 2016 18:32:03 +0530 Subject: greybus: arche-platform: Enter ACTIVE state only from OFF state Make sure that, transition to active state happens only from OFF state. Instead of imposing the restriction to user-space, driver internally switches to OFF state and then to ACTIVE state. Testing Done: Tested on EVT1.5 platform. Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Tested-by: Michael Scott <michael.scott@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index a8e36e1..58b3707 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -407,8 +407,15 @@ static ssize_t state_store(struct device *dev, if (arche_pdata->state == ARCHE_PLATFORM_STATE_ACTIVE) goto exit; + /* First we want to make sure we power off everything + * and then activate back again */ + device_for_each_child(arche_pdata->dev, NULL, apb_poweroff); + arche_platform_poweroff_seq(arche_pdata); + arche_platform_wd_irq_en(arche_pdata); ret = arche_platform_coldboot_seq(arche_pdata); + if (ret) + goto exit; } else if (sysfs_streq(buf, "standby")) { if (arche_pdata->state == ARCHE_PLATFORM_STATE_STANDBY) -- cgit v0.10.2 From 7a867d149f0c0cb9184a38f83704d37439a17f3e Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Date: Tue, 24 May 2016 18:32:04 +0530 Subject: greybus: arche-platform: Enable SVC clock during FW_FLASHING state The issue is, as part of kernel-only build we started seeing failures in SVC FW flashing. It was reproducible easily in kernel-only build, but never observed on Android build. During debugging, there were couple of observations, 1. If SVC clock enabled and disables (which is REFCLK_MAIN), then SVC FW flashing works. 2. If we do not switch SVC to HSE (external clock source) it works. Recently, SVC code has been updated to switch HSE clock, so removing it (remove/skip rcc_switch_ara_pll() fn) would use internal clock only. As per STM32 spec, for flashing through USART we do not need to enable HSE, but the above observation contradicts with it. There is still something missing in terms of understanding of how STM32 device functions as far as Flashing is concerned. There is something hidden in HW, which probably still need to identify. So as a interim solution we will enable clock for FW_FLASHING state, which seems to be fixing the issue here. Testing Done: Tested on EVT1.5 with arche6.0 and kernel-only build. Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Tested-by: Michael Scott <michael.scott@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 58b3707..f47ea46 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -337,6 +337,8 @@ static int arche_platform_coldboot_seq(struct arche_platform_drvdata *arche_pdat */ static int arche_platform_fw_flashing_seq(struct arche_platform_drvdata *arche_pdata) { + int ret; + if (arche_pdata->state == ARCHE_PLATFORM_STATE_FW_FLASHING) return 0; @@ -348,6 +350,14 @@ static int arche_platform_fw_flashing_seq(struct arche_platform_drvdata *arche_p gpio_set_value(arche_pdata->svc_sysboot_gpio, 1); usleep_range(100, 200); + + ret = clk_prepare_enable(arche_pdata->svc_ref_clk); + if (ret) { + dev_err(arche_pdata->dev, "failed to enable svc_ref_clk: %d\n", + ret); + return ret; + } + svc_reset_onoff(arche_pdata->svc_reset_gpio, !arche_pdata->is_reset_act_hi); @@ -374,10 +384,10 @@ static void arche_platform_poweroff_seq(struct arche_platform_drvdata *arche_pda arche_platform_set_wake_detect_state(arche_pdata, WD_STATE_IDLE); spin_unlock_irqrestore(&arche_pdata->wake_lock, flags); - - clk_disable_unprepare(arche_pdata->svc_ref_clk); } + clk_disable_unprepare(arche_pdata->svc_ref_clk); + /* As part of exit, put APB back in reset state */ svc_reset_onoff(arche_pdata->svc_reset_gpio, arche_pdata->is_reset_act_hi); -- cgit v0.10.2 From b797c43271f77f1dfd25953d72245cb8d0b832fc Mon Sep 17 00:00:00 2001 From: Axel Haslam <ahaslam@baylibre.com> Date: Tue, 24 May 2016 16:21:29 +0200 Subject: greybus: Fix loopback app after rename to gpphy commit 6d94670 gpbridge: rename 'gpbridge' to 'gbphy' everywhere missed renaming the loopback test app. So do it too. Testing done: complie and run loopback test Signed-off-by: Axel Haslam <ahaslam@baylibre.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/tools/loopback_test.c b/drivers/staging/greybus/tools/loopback_test.c index d8ff1bc..25035f6 100644 --- a/drivers/staging/greybus/tools/loopback_test.c +++ b/drivers/staging/greybus/tools/loopback_test.c @@ -59,10 +59,10 @@ struct loopback_results { uint32_t apbridge_unipro_latency_min; uint32_t apbridge_unipro_latency_jitter; - float gpbridge_firmware_latency_avg; - uint32_t gpbridge_firmware_latency_max; - uint32_t gpbridge_firmware_latency_min; - uint32_t gpbridge_firmware_latency_jitter; + float gbphy_firmware_latency_avg; + uint32_t gbphy_firmware_latency_max; + uint32_t gbphy_firmware_latency_min; + uint32_t gbphy_firmware_latency_jitter; uint32_t error; }; @@ -155,17 +155,17 @@ GET_MAX(throughput_max); GET_MAX(request_max); GET_MAX(latency_max); GET_MAX(apbridge_unipro_latency_max); -GET_MAX(gpbridge_firmware_latency_max); +GET_MAX(gbphy_firmware_latency_max); GET_MIN(throughput_min); GET_MIN(request_min); GET_MIN(latency_min); GET_MIN(apbridge_unipro_latency_min); -GET_MIN(gpbridge_firmware_latency_min); +GET_MIN(gbphy_firmware_latency_min); GET_AVG(throughput_avg); GET_AVG(request_avg); GET_AVG(latency_avg); GET_AVG(apbridge_unipro_latency_avg); -GET_AVG(gpbridge_firmware_latency_avg); +GET_AVG(gbphy_firmware_latency_avg); void abort() { @@ -351,20 +351,20 @@ static int get_results(struct loopback_test *t) r->apbridge_unipro_latency_avg = read_sysfs_float(d->sysfs_entry, "apbridge_unipro_latency_avg"); - r->gpbridge_firmware_latency_min = - read_sysfs_int(d->sysfs_entry, "gpbridge_firmware_latency_min"); - r->gpbridge_firmware_latency_max = - read_sysfs_int(d->sysfs_entry, "gpbridge_firmware_latency_max"); - r->gpbridge_firmware_latency_avg = - read_sysfs_float(d->sysfs_entry, "gpbridge_firmware_latency_avg"); + r->gbphy_firmware_latency_min = + read_sysfs_int(d->sysfs_entry, "gbphy_firmware_latency_min"); + r->gbphy_firmware_latency_max = + read_sysfs_int(d->sysfs_entry, "gbphy_firmware_latency_max"); + r->gbphy_firmware_latency_avg = + read_sysfs_float(d->sysfs_entry, "gbphy_firmware_latency_avg"); r->request_jitter = r->request_max - r->request_min; r->latency_jitter = r->latency_max - r->latency_min; r->throughput_jitter = r->throughput_max - r->throughput_min; r->apbridge_unipro_latency_jitter = r->apbridge_unipro_latency_max - r->apbridge_unipro_latency_min; - r->gpbridge_firmware_latency_jitter = - r->gpbridge_firmware_latency_max - r->gpbridge_firmware_latency_min; + r->gbphy_firmware_latency_jitter = + r->gbphy_firmware_latency_max - r->gbphy_firmware_latency_min; } @@ -391,20 +391,20 @@ static int get_results(struct loopback_test *t) r->apbridge_unipro_latency_avg = get_apbridge_unipro_latency_avg_aggregate(t); - r->gpbridge_firmware_latency_min = - get_gpbridge_firmware_latency_min_aggregate(t); - r->gpbridge_firmware_latency_max = - get_gpbridge_firmware_latency_max_aggregate(t); - r->gpbridge_firmware_latency_avg = - get_gpbridge_firmware_latency_avg_aggregate(t); + r->gbphy_firmware_latency_min = + get_gbphy_firmware_latency_min_aggregate(t); + r->gbphy_firmware_latency_max = + get_gbphy_firmware_latency_max_aggregate(t); + r->gbphy_firmware_latency_avg = + get_gbphy_firmware_latency_avg_aggregate(t); r->request_jitter = r->request_max - r->request_min; r->latency_jitter = r->latency_max - r->latency_min; r->throughput_jitter = r->throughput_max - r->throughput_min; r->apbridge_unipro_latency_jitter = r->apbridge_unipro_latency_max - r->apbridge_unipro_latency_min; - r->gpbridge_firmware_latency_jitter = - r->gpbridge_firmware_latency_max - r->gpbridge_firmware_latency_min; + r->gbphy_firmware_latency_jitter = + r->gbphy_firmware_latency_max - r->gbphy_firmware_latency_min; } @@ -467,11 +467,11 @@ int format_output(struct loopback_test *t, r->apbridge_unipro_latency_jitter); len += snprintf(&buf[len], buf_len - len, - " gpbridge-latency usec:\tmin=%u max=%u average=%f jitter=%u\n", - r->gpbridge_firmware_latency_min, - r->gpbridge_firmware_latency_max, - r->gpbridge_firmware_latency_avg, - r->gpbridge_firmware_latency_jitter); + " gbphy-latency usec:\tmin=%u max=%u average=%f jitter=%u\n", + r->gbphy_firmware_latency_min, + r->gbphy_firmware_latency_max, + r->gbphy_firmware_latency_avg, + r->gbphy_firmware_latency_jitter); } else { len += snprintf(&buf[len], buf_len- len, ",%s,%s,%u,%u,%u", @@ -503,10 +503,10 @@ int format_output(struct loopback_test *t, r->apbridge_unipro_latency_jitter); len += snprintf(&buf[len], buf_len - len, ",%u,%u,%f,%u", - r->gpbridge_firmware_latency_min, - r->gpbridge_firmware_latency_max, - r->gpbridge_firmware_latency_avg, - r->gpbridge_firmware_latency_jitter); + r->gbphy_firmware_latency_min, + r->gbphy_firmware_latency_max, + r->gbphy_firmware_latency_avg, + r->gbphy_firmware_latency_jitter); } printf("\n%s\n", buf); -- cgit v0.10.2 From 71b7a36072cbaf86d3c69ec6473325bfea4f6f87 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Wed, 25 May 2016 12:46:24 +0530 Subject: greybus: Documentation/sysfs: Rename gpbridge to gbphy These were left in the earlier renaming series, fix them as well. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gbphy0/gpio/gpiochip490/.gitignore b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gbphy0/gpio/gpiochip490/.gitignore new file mode 100644 index 0000000..f935021 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gbphy0/gpio/gpiochip490/.gitignore @@ -0,0 +1 @@ +!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gbphy0/i2c-4/.gitignore b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gbphy0/i2c-4/.gitignore new file mode 100644 index 0000000..f935021 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gbphy0/i2c-4/.gitignore @@ -0,0 +1 @@ +!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gpbridge0/gpio/gpiochip490/.gitignore b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gpbridge0/gpio/gpiochip490/.gitignore deleted file mode 100644 index f935021..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gpbridge0/gpio/gpiochip490/.gitignore +++ /dev/null @@ -1 +0,0 @@ -!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gpbridge0/i2c-4/.gitignore b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gpbridge0/i2c-4/.gitignore deleted file mode 100644 index f935021..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gpbridge0/i2c-4/.gitignore +++ /dev/null @@ -1 +0,0 @@ -!.gitignore -- cgit v0.10.2 From 7a9a5bf01ebd31171ad747386133b126deb81c15 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Wed, 25 May 2016 12:49:26 +0530 Subject: greybus: Documentation/sysfs: gbphy0 is an invalid name The numbering of gbphy devices is going to start from 1 and not 0. Reflect the same in sysfs hierarchy. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gbphy0/gpio/gpiochip490/.gitignore b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gbphy0/gpio/gpiochip490/.gitignore deleted file mode 100644 index f935021..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gbphy0/gpio/gpiochip490/.gitignore +++ /dev/null @@ -1 +0,0 @@ -!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gbphy0/i2c-4/.gitignore b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gbphy0/i2c-4/.gitignore deleted file mode 100644 index f935021..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gbphy0/i2c-4/.gitignore +++ /dev/null @@ -1 +0,0 @@ -!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gbphy1/gpio/gpiochip490/.gitignore b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gbphy1/gpio/gpiochip490/.gitignore new file mode 100644 index 0000000..f935021 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gbphy1/gpio/gpiochip490/.gitignore @@ -0,0 +1 @@ +!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gbphy1/i2c-4/.gitignore b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gbphy1/i2c-4/.gitignore new file mode 100644 index 0000000..f935021 --- /dev/null +++ b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gbphy1/i2c-4/.gitignore @@ -0,0 +1 @@ +!.gitignore -- cgit v0.10.2 From ae36e81ed93e9fecfede1cc3dde48cfea3a8c908 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 25 May 2016 22:18:14 +0200 Subject: greybus: interface: fix svc-resource error messages The interface svc-resource helper are used to enable as well as disable the corresponding SVC resources so make sure the error messages reflect that. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index e3e8e169..ba7f880 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -387,7 +387,7 @@ static int gb_interface_vsys_set(struct gb_interface *intf, bool enable) ret = gb_svc_intf_vsys_set(svc, intf->interface_id, enable); if (ret) { - dev_err(&intf->dev, "failed to enable v_sys: %d\n", ret); + dev_err(&intf->dev, "failed to set v_sys: %d\n", ret); return ret; } @@ -403,7 +403,7 @@ static int gb_interface_refclk_set(struct gb_interface *intf, bool enable) ret = gb_svc_intf_refclk_set(svc, intf->interface_id, enable); if (ret) { - dev_err(&intf->dev, "failed to enable refclk: %d\n", ret); + dev_err(&intf->dev, "failed to set refclk: %d\n", ret); return ret; } @@ -419,7 +419,7 @@ static int gb_interface_unipro_set(struct gb_interface *intf, bool enable) ret = gb_svc_intf_unipro_set(svc, intf->interface_id, enable); if (ret) { - dev_err(&intf->dev, "failed to enable UniPro: %d\n", ret); + dev_err(&intf->dev, "failed to set UniPro: %d\n", ret); return ret; } -- cgit v0.10.2 From bae7c690354b585d98ae15bd8b1b7b0ba2bb3c42 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 25 May 2016 22:18:15 +0200 Subject: greybus: remove redundant latency-tag sanity checks Core will never call host-device callbacks with invalid arguments (and that would still need to be verified in bridge firmware anyway), so remove the redundant and insufficient sanity check from the callbacks. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 947ebae..5bd348f 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -622,11 +622,6 @@ static int latency_tag_enable(struct gb_host_device *hd, u16 cport_id) struct es2_ap_dev *es2 = hd_to_es2(hd); struct usb_device *udev = es2->usb_dev; - if (!cport_id_valid(hd, cport_id)) { - dev_err(&udev->dev, "invalid cport %u\n", cport_id); - return -EINVAL; - } - retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), GB_APB_REQUEST_LATENCY_TAG_EN, USB_DIR_OUT | USB_TYPE_VENDOR | @@ -645,11 +640,6 @@ static int latency_tag_disable(struct gb_host_device *hd, u16 cport_id) struct es2_ap_dev *es2 = hd_to_es2(hd); struct usb_device *udev = es2->usb_dev; - if (!cport_id_valid(hd, cport_id)) { - dev_err(&udev->dev, "invalid cport %u\n", cport_id); - return -EINVAL; - } - retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), GB_APB_REQUEST_LATENCY_TAG_DIS, USB_DIR_OUT | USB_TYPE_VENDOR | -- cgit v0.10.2 From df732546ce127e3bd8d55f4f7073aebd4482438c Mon Sep 17 00:00:00 2001 From: Alex Elder <elder@linaro.org> Date: Mon, 23 May 2016 23:05:29 -0500 Subject: greybus: tracing: fix a bad tracepoint In gb_operation_put_active(), the wrong trace point is being called. Fix that. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 259bd92..20a8d74 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -72,7 +72,7 @@ static void gb_operation_put_active(struct gb_operation *operation) spin_lock_irqsave(&connection->lock, flags); - trace_gb_operation_get_active(operation); + trace_gb_operation_put_active(operation); if (--operation->active == 0) { list_del(&operation->links); -- cgit v0.10.2 From 1f79046bd73abf5cc1dc5ad1f817a7851496ae0c Mon Sep 17 00:00:00 2001 From: Alex Elder <elder@linaro.org> Date: Mon, 23 May 2016 23:05:30 -0500 Subject: greybus: tracing: fix hd traces Currently there are two trace points defined for the Greybus host device structure. One records information when a message gets sent, and another when it gets received. Neither of these is really a host device event. We have trace points defined for messages that dump information about all sent and received messages. As a result, the information about sending messages over a host is redundant, and can go away. (Note that the message traces may need a little refinement so they produce all desired information.) Instead of these trace points, define some that are directly related to the host device abstraction: when one is created, added, deleted, or released (destroyed). These do not require a CPort ID or payload size, so eliminate those two parameters from the host device trace point prototype. Change the trace information recorded for a host device to be just a subset of interesting fields in a host device. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 6d6a2bb..b1a7b11 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -14,8 +14,10 @@ #include "greybus.h" #include "greybus_trace.h" -EXPORT_TRACEPOINT_SYMBOL_GPL(gb_host_device_send); -EXPORT_TRACEPOINT_SYMBOL_GPL(gb_host_device_recv); +EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_create); +EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_release); +EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_add); +EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_del); /* Allow greybus to be disabled at boot if needed */ static bool nogreybus; diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 5bd348f..24fef34 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -16,8 +16,6 @@ #include "greybus.h" #include "kernel_ver.h" #include "connection.h" -#include "greybus_trace.h" - /* Fixed CPort numbers */ #define ES2_CPORT_CDSI0 16 @@ -469,7 +467,6 @@ static int message_send(struct gb_host_device *hd, u16 cport_id, message->buffer, buffer_size, cport_out_callback, message); urb->transfer_flags |= URB_ZERO_PACKET; - trace_gb_host_device_send(hd, cport_id, buffer_size); retval = usb_submit_urb(urb, gfp_mask); if (retval) { dev_err(&udev->dev, "failed to submit out-urb: %d\n", retval); @@ -909,7 +906,6 @@ static void cport_in_callback(struct urb *urb) cport_id = gb_message_cport_unpack(header); if (cport_id_valid(hd, cport_id)) { - trace_gb_host_device_recv(hd, cport_id, urb->actual_length); greybus_data_rcvd(hd, cport_id, urb->transfer_buffer, urb->actual_length); } else { diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h index ba93873..cbbc959 100644 --- a/drivers/staging/greybus/greybus_trace.h +++ b/drivers/staging/greybus/greybus_trace.h @@ -158,45 +158,55 @@ DEFINE_OPERATION_EVENT(gb_operation_put_active); DECLARE_EVENT_CLASS(gb_host_device, - TP_PROTO(struct gb_host_device *hd, u16 intf_cport_id, - size_t payload_size), + TP_PROTO(struct gb_host_device *hd), - TP_ARGS(hd, intf_cport_id, payload_size), + TP_ARGS(hd), TP_STRUCT__entry( - __string(name, dev_name(&hd->dev)) - __field(u16, intf_cport_id) - __field(size_t, payload_size) + __field(int, bus_id) + __field(u8, num_cports) + __field(size_t, buffer_size_max) ), TP_fast_assign( - __assign_str(name, dev_name(&hd->dev)) - __entry->intf_cport_id = intf_cport_id; - __entry->payload_size = payload_size; + __entry->bus_id = hd->bus_id; + __entry->num_cports = hd->num_cports; + __entry->buffer_size_max = hd->buffer_size_max; ), - TP_printk("greybus:%s if_id=%u l=%zu", __get_str(name), - __entry->intf_cport_id, __entry->payload_size) + TP_printk("greybus: bus_id=%d num_cports=%hu mtu=%zu", + __entry->bus_id, __entry->num_cports, + __entry->buffer_size_max) ); #define DEFINE_HD_EVENT(name) \ DEFINE_EVENT(gb_host_device, name, \ - TP_PROTO(struct gb_host_device *hd, \ - u16 intf_cport_id, \ - size_t payload_size), \ - TP_ARGS(hd, intf_cport_id, payload_size)) + TP_PROTO(struct gb_host_device *hd), \ + TP_ARGS(hd)) + +/* + * Occurs after a new host device is successfully created, before + * its SVC has been set up. + */ +DEFINE_HD_EVENT(gb_hd_create); + +/* + * Occurs after the last reference to a host device has been + * dropped. + */ +DEFINE_HD_EVENT(gb_hd_release); /* - * Occurs immediately before calling usb_submit_urb() to send a - * message to the UniPro bridge. + * Occurs after a new host device has been added, after the + * connection to its SVC has * been enabled. */ -DEFINE_HD_EVENT(gb_host_device_send); +DEFINE_HD_EVENT(gb_hd_add); /* - * Occurs after receiving a UniPro message via the USB subsystem, - * just prior to handing it to the Greybus core for handling. + * Occurs when a host device is being disconnected from the AP USB + * host controller. */ -DEFINE_HD_EVENT(gb_host_device_recv); +DEFINE_HD_EVENT(gb_hd_del); #undef DEFINE_HD_EVENT diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index fba6d76..f64b592 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -11,7 +11,7 @@ #include <linux/slab.h> #include "greybus.h" - +#include "greybus_trace.h" static struct ida gb_hd_bus_id_map; @@ -87,6 +87,8 @@ void gb_hd_cport_release(struct gb_host_device *hd, u16 cport_id) } ida_simple_remove(&hd->cport_id_map, cport_id); + + trace_gb_hd_release(hd); } static void gb_hd_release(struct device *dev) @@ -168,6 +170,8 @@ struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, device_initialize(&hd->dev); dev_set_name(&hd->dev, "greybus%d", hd->bus_id); + trace_gb_hd_create(hd); + hd->svc = gb_svc_create(hd); if (!hd->svc) { dev_err(&hd->dev, "failed to create svc\n"); @@ -193,12 +197,16 @@ int gb_hd_add(struct gb_host_device *hd) return ret; } + trace_gb_hd_add(hd); + return 0; } EXPORT_SYMBOL_GPL(gb_hd_add); void gb_hd_del(struct gb_host_device *hd) { + trace_gb_hd_del(hd); + /* * Tear down the svc and flush any on-going hotplug processing before * removing the remaining interfaces. -- cgit v0.10.2 From 5451ea0e99cb7d58cbf90c7785cb50cc322a4434 Mon Sep 17 00:00:00 2001 From: Alex Elder <elder@linaro.org> Date: Mon, 23 May 2016 23:05:31 -0500 Subject: greybus: tracing: add module traces Define a new gb_module trace point event class, used to trace events associated with the module abstraction. Define four basic trace points for this--creation time, drop of last reference, before registring interfaces and after de-registering them. Signed-off-by: Alex Elder <elder@linaro.org> Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h index cbbc959..ecf2253 100644 --- a/drivers/staging/greybus/greybus_trace.h +++ b/drivers/staging/greybus/greybus_trace.h @@ -156,6 +156,59 @@ DEFINE_OPERATION_EVENT(gb_operation_put_active); #undef DEFINE_OPERATION_EVENT +DECLARE_EVENT_CLASS(gb_module, + + TP_PROTO(struct gb_module *module), + + TP_ARGS(module), + + TP_STRUCT__entry( + __field(int, hd_bus_id) + __field(u8, module_id) + __field(u8, num_interfaces) + __field(bool, disconnected) + ), + + TP_fast_assign( + __entry->hd_bus_id = module->hd->bus_id; + __entry->module_id = module->module_id; + __entry->disconnected = module->disconnected; + ), + + TP_printk("greybus: hd_bus_id=%d module_id=%hhu disconnected=%u", + __entry->hd_bus_id, __entry->module_id, __entry->disconnected) +); + +#define DEFINE_MODULE_EVENT(name) \ + DEFINE_EVENT(gb_module, name, \ + TP_PROTO(struct gb_module *module), \ + TP_ARGS(module)) + +/* + * Occurs after a new module is successfully created, before + * creating any of its interfaces. + */ +DEFINE_MODULE_EVENT(gb_module_create); + +/* + * Occurs after the last reference to a module has been dropped. + */ +DEFINE_MODULE_EVENT(gb_module_release); + +/* + * Occurs after a module is successfully created, before registering + * any of its interfaces. + */ +DEFINE_MODULE_EVENT(gb_module_add); + +/* + * Occurs when a module is deleted, before deregistering its + * interfaces. + */ +DEFINE_MODULE_EVENT(gb_module_del); + +#undef DEFINE_MODULE_EVENT + DECLARE_EVENT_CLASS(gb_host_device, TP_PROTO(struct gb_host_device *hd), diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index ea58954..c56b988 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -9,6 +9,7 @@ #include "greybus.h" +#include "greybus_trace.h" static ssize_t eject_store(struct device *dev, struct device_attribute *attr, @@ -77,6 +78,8 @@ static void gb_module_release(struct device *dev) { struct gb_module *module = to_gb_module(dev); + trace_gb_module_release(module); + kfree(module); } @@ -109,6 +112,8 @@ struct gb_module *gb_module_create(struct gb_host_device *hd, u8 module_id, device_initialize(&module->dev); dev_set_name(&module->dev, "%d-%u", hd->bus_id, module_id); + trace_gb_module_create(module); + for (i = 0; i < num_interfaces; ++i) { intf = gb_interface_create(module, module_id + i); if (!intf) { @@ -215,6 +220,8 @@ int gb_module_add(struct gb_module *module) return ret; } + trace_gb_module_add(module); + for (i = 0; i < module->num_interfaces; ++i) gb_module_register_interface(module->interfaces[i]); @@ -229,6 +236,8 @@ void gb_module_del(struct gb_module *module) for (i = 0; i < module->num_interfaces; ++i) gb_module_deregister_interface(module->interfaces[i]); + trace_gb_module_del(module); + device_del(&module->dev); } -- cgit v0.10.2 From cb4c8441e5dac4994ab63c1426babda3102beda9 Mon Sep 17 00:00:00 2001 From: Alex Elder <elder@linaro.org> Date: Mon, 23 May 2016 23:05:32 -0500 Subject: greybus: tracing: define interface traces Define a new gb_module trace point event class, used to trace events associated with the interface abstraction. Define four basic trace points for this--creation time, drop of last reference, before registring interfaces and after de-registering them. In addition, define traces for activating and deactivating, and enabling and disabling an interface. Signed-off-by: Alex Elder <elder@linaro.org> Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h index ecf2253..93e04a8 100644 --- a/drivers/staging/greybus/greybus_trace.h +++ b/drivers/staging/greybus/greybus_trace.h @@ -209,6 +209,86 @@ DEFINE_MODULE_EVENT(gb_module_del); #undef DEFINE_MODULE_EVENT +DECLARE_EVENT_CLASS(gb_interface, + + TP_PROTO(struct gb_interface *intf), + + TP_ARGS(intf), + + TP_STRUCT__entry( + __field(u8, id) /* Interface id */ + __field(u8, module_id) + __field(u8, device_id) + __field(bool, disconnected) + __field(bool, ejected) + __field(bool, active) + __field(bool, enabled) + ), + + TP_fast_assign( + __entry->id = intf->interface_id; + __entry->module_id = intf->module->module_id; + __entry->device_id = intf->device_id; + __entry->disconnected = intf->disconnected; + __entry->ejected = intf->ejected; + __entry->active = intf->active; + __entry->enabled = intf->enabled; + ), + + TP_printk("greybus: intf_id=%hhu device_id=%hhu module_id=%hhu D=%u J=%u A=%u E=%u", + __entry->id, __entry->device_id, __entry->module_id, + __entry->disconnected, __entry->ejected, __entry->active, + __entry->enabled) +); + +#define DEFINE_INTERFACE_EVENT(name) \ + DEFINE_EVENT(gb_interface, name, \ + TP_PROTO(struct gb_interface *intf), \ + TP_ARGS(intf)) + +/* + * Occurs after a new interface is successfully created. + */ +DEFINE_INTERFACE_EVENT(gb_interface_create); + +/* + * Occurs after the last reference to an interface has been dropped. + */ +DEFINE_INTERFACE_EVENT(gb_interface_release); + +/* + * Occurs after an interface been registerd. + */ +DEFINE_INTERFACE_EVENT(gb_interface_add); + +/* + * Occurs when a registered interface gets deregisterd. + */ +DEFINE_INTERFACE_EVENT(gb_interface_del); + +/* + * Occurs when a registered interface has been successfully + * activated. + */ +DEFINE_INTERFACE_EVENT(gb_interface_activate); + +/* + * Occurs when an activated interface is being deactivated. + */ +DEFINE_INTERFACE_EVENT(gb_interface_deactivate); + +/* + * Occurs when an interface has been successfully enabled. + */ +DEFINE_INTERFACE_EVENT(gb_interface_enable); + +/* + * Occurs when an enabled interface is being disabled. + */ +DEFINE_INTERFACE_EVENT(gb_interface_disable); + +#undef DEFINE_INTERFACE_EVENT + DECLARE_EVENT_CLASS(gb_host_device, TP_PROTO(struct gb_host_device *hd), diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index ba7f880..c19a09c 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -9,6 +9,7 @@ #include "greybus.h" +#include "greybus_trace.h" #define GB_INTERFACE_DEVICE_ID_BAD 0xff @@ -326,6 +327,8 @@ static void gb_interface_release(struct device *dev) { struct gb_interface *intf = to_gb_interface(dev); + trace_gb_interface_release(intf); + kfree(intf); } @@ -375,6 +378,8 @@ struct gb_interface *gb_interface_create(struct gb_module *module, dev_set_name(&intf->dev, "%s.%u", dev_name(&module->dev), interface_id); + trace_gb_interface_create(intf); + return intf; } @@ -506,6 +511,8 @@ int gb_interface_activate(struct gb_interface *intf) intf->active = true; + trace_gb_interface_activate(intf); + return 0; err_hibernate_link: @@ -530,6 +537,8 @@ void gb_interface_deactivate(struct gb_interface *intf) if (!intf->active) return; + trace_gb_interface_deactivate(intf); + gb_interface_route_destroy(intf); gb_interface_hibernate_link(intf); gb_interface_unipro_set(intf, false); @@ -629,6 +638,8 @@ int gb_interface_enable(struct gb_interface *intf) intf->enabled = true; + trace_gb_interface_enable(intf); + return 0; err_destroy_bundles: @@ -658,6 +669,8 @@ void gb_interface_disable(struct gb_interface *intf) if (!intf->enabled) return; + trace_gb_interface_disable(intf); + /* * Disable the control-connection early to avoid operation timeouts * when the interface is already gone. @@ -687,6 +700,8 @@ int gb_interface_add(struct gb_interface *intf) return ret; } + trace_gb_interface_add(intf); + dev_info(&intf->dev, "Interface added: VID=0x%08x, PID=0x%08x\n", intf->vendor_id, intf->product_id); dev_info(&intf->dev, "DDBL1 Manufacturer=0x%08x, Product=0x%08x\n", @@ -699,6 +714,8 @@ int gb_interface_add(struct gb_interface *intf) void gb_interface_del(struct gb_interface *intf) { if (device_is_registered(&intf->dev)) { + trace_gb_interface_del(intf); + device_del(&intf->dev); dev_info(&intf->dev, "Interface removed\n"); } -- cgit v0.10.2 From 29a822bdf77a0c2af5b556506f3cf3175a9a4a98 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Fri, 27 May 2016 10:49:23 +0530 Subject: greybus: hd: Add API to release reserved CPorts It is required to release all unique ids registered via ida_get_simple to avoid any possible memory leak. cport_release() already exists with special handling for ES2_CPORT_CDSI1, i.e. updating in_use flag without removing associated ida. So, added another API to release reserved cports CDSI0 and CDSI1. This is intended to be used only during es2_destroy(). Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index f64b592..5238825 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -54,6 +54,14 @@ int gb_hd_cport_reserve(struct gb_host_device *hd, u16 cport_id) } EXPORT_SYMBOL_GPL(gb_hd_cport_reserve); +void gb_hd_cport_release_reserved(struct gb_host_device *hd, u16 cport_id) +{ + struct ida *id_map = &hd->cport_id_map; + + ida_simple_remove(id_map, cport_id); +} +EXPORT_SYMBOL_GPL(gb_hd_cport_release_reserved); + /* Locking: Caller guarantees serialisation */ int gb_hd_cport_allocate(struct gb_host_device *hd, int cport_id, unsigned long flags) diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h index 8510816..ad22962 100644 --- a/drivers/staging/greybus/hd.h +++ b/drivers/staging/greybus/hd.h @@ -61,6 +61,7 @@ struct gb_host_device { #define to_gb_host_device(d) container_of(d, struct gb_host_device, dev) int gb_hd_cport_reserve(struct gb_host_device *hd, u16 cport_id); +void gb_hd_cport_release_reserved(struct gb_host_device *hd, u16 cport_id); int gb_hd_cport_allocate(struct gb_host_device *hd, int cport_id, unsigned long flags); void gb_hd_cport_release(struct gb_host_device *hd, u16 cport_id); -- cgit v0.10.2 From 52033fdebc92021490729465e27ffb47cd42b0e0 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Fri, 27 May 2016 10:49:24 +0530 Subject: greybus: es2: Release reserved cports CDSI0 and CDSI1 Unique ids were reserved for CDSI0 and CDSI1 during _probe, however missed to release those ids during disconnect. This causes a memory leak of 128 bytes for each iteration of unipro_reset. Fix this. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 24fef34..fd59c14 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -869,6 +869,10 @@ static void es2_destroy(struct es2_ap_dev *es2) kfree(es2->cport_to_ep); + /* release reserved CDSI0 and CDSI1 cports */ + gb_hd_cport_release_reserved(es2->hd, ES2_CPORT_CDSI1); + gb_hd_cport_release_reserved(es2->hd, ES2_CPORT_CDSI0); + udev = es2->usb_dev; gb_hd_put(es2->hd); -- cgit v0.10.2 From f9340fc7dd9f42edfcd7a0e332798ae01a6b48ac Mon Sep 17 00:00:00 2001 From: Alex Elder <elder@linaro.org> Date: Tue, 24 May 2016 13:34:47 -0500 Subject: greybus: report right error value Running "make coccicheck" on the Greybus code discovered that an error message in gb_camera_debugfs_init() was interpreting the wrong value in reporting the error code. Fix that. Signed-off-by: Alex Elder <elder@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index dd482bd..dda8719 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -873,7 +873,7 @@ static int gb_camera_debugfs_init(struct gb_camera *gcam) if (IS_ERR(dentry)) { gcam_err(gcam, "debugfs operation %s create failed (%ld)\n", - entry->name, PTR_ERR(gcam->debugfs.root)); + entry->name, PTR_ERR(dentry)); return PTR_ERR(dentry); } } -- cgit v0.10.2 From ebc9e3750d3112e3a84fe65386cb0e5deb994e18 Mon Sep 17 00:00:00 2001 From: Alex Elder <elder@linaro.org> Date: Tue, 24 May 2016 13:34:48 -0500 Subject: greybus: fix unbalanced mutex Running "make coccicheck" on the Greybus code reports that gb_mmc_get_ro() and gb_mmc_get_cd() can return without releasing the mutex it acquired if there's an error. Fix this. Signed-off-by: Alex Elder <elder@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index 4d4cfdf..bdcc869 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -684,9 +684,12 @@ static int gb_mmc_get_ro(struct mmc_host *mmc) struct gb_sdio_host *host = mmc_priv(mmc); mutex_lock(&host->lock); - if (host->removed) + if (host->removed) { + mutex_unlock(&host->lock); return -ESHUTDOWN; + } mutex_unlock(&host->lock); + return host->read_only; } @@ -695,9 +698,12 @@ static int gb_mmc_get_cd(struct mmc_host *mmc) struct gb_sdio_host *host = mmc_priv(mmc); mutex_lock(&host->lock); - if (host->removed) + if (host->removed) { + mutex_unlock(&host->lock); return -ESHUTDOWN; + } mutex_unlock(&host->lock); + return host->card_present; } -- cgit v0.10.2 From 66394300c37e9321a913f269021b3d6c92d786ad Mon Sep 17 00:00:00 2001 From: Alex Elder <elder@linaro.org> Date: Tue, 24 May 2016 13:34:49 -0500 Subject: greybus: eliminate unneeded null check Coccinelle points out that debugfs_remove_recursive() handles a null argument properly, so there's no need to check for NULL before making the call. I have verified this is true of the kernel we're now working with (arche-6.0). Signed-off-by: Alex Elder <elder@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index dda8719..d5496f8 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -883,8 +883,7 @@ static int gb_camera_debugfs_init(struct gb_camera *gcam) static void gb_camera_debugfs_cleanup(struct gb_camera *gcam) { - if (gcam->debugfs.root) - debugfs_remove_recursive(gcam->debugfs.root); + debugfs_remove_recursive(gcam->debugfs.root); vfree(gcam->debugfs.buffers); } -- cgit v0.10.2 From d97fca12e92d3179554baf4db42611e5fe56aeed Mon Sep 17 00:00:00 2001 From: Alex Elder <elder@linaro.org> Date: Tue, 24 May 2016 13:34:50 -0500 Subject: greybus: fix pointless null check Coccinelle points out that a call in gb_lights_channel_free() to flush_work() is passed which is always non-null. Prior to the call, there is an unnecessary check to see if that address is null. Get rid of the test. Signed-off-by: Alex Elder <elder@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index 8b71ed3..78fb8a9 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -1019,8 +1019,7 @@ static int gb_lights_light_register(struct gb_light *light) static void gb_lights_channel_free(struct gb_channel *channel) { #ifndef LED_HAVE_SET_BLOCKING - if (&channel->work_brightness_set) - flush_work(&channel->work_brightness_set); + flush_work(&channel->work_brightness_set); #endif kfree(channel->attrs); kfree(channel->attr_group); -- cgit v0.10.2 From 95073cc2e53c1352f2c244408d1bd005b07650fd Mon Sep 17 00:00:00 2001 From: Alex Elder <elder@linaro.org> Date: Tue, 24 May 2016 13:34:51 -0500 Subject: greybus: use PTR_ERR_OR_ZERO() Coccinelle points out that the macro PTR_ERR_OR_ZERO() handles the frequent case of converting a pointer into either error code (if its value is an encoded error value) or 0 (otherwise). Switch some code in gb_power_supply_register() to use that macro. I have verified this is true of the kernel we're now working with (arche-6.0). Signed-off-by: Alex Elder <elder@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c index 9cae396..8d6570d 100644 --- a/drivers/staging/greybus/power_supply.c +++ b/drivers/staging/greybus/power_supply.c @@ -547,10 +547,7 @@ static int gb_power_supply_register(struct gb_power_supply *gbpsy) gbpsy->psy = power_supply_register(&connection->bundle->dev, &gbpsy->desc, &cfg); - if (IS_ERR(gbpsy->psy)) - return PTR_ERR(gbpsy->psy); - - return 0; + return PTR_ERR_OR_ZERO(gbpsy->psy); } #endif -- cgit v0.10.2 From 898d75f4aa8b1aeb99df8fe275cb3fcfa3dc0688 Mon Sep 17 00:00:00 2001 From: Alex Elder <elder@linaro.org> Date: Tue, 24 May 2016 13:34:52 -0500 Subject: greybus: drop a bogus semicolon Coccinelle reports that gb_svc_pwrmon_debugfs_init() has a block of a for loop which is followed by an unnecessary semicolon. Get rid of that semicolon. Signed-off-by: Alex Elder <elder@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 78cc0e3..2b3b8d9 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -779,7 +779,7 @@ static void gb_svc_pwrmon_debugfs_init(struct gb_svc *svc) &pwrmon_debugfs_current_fops); debugfs_create_file("power_now", S_IRUGO, dir, rail, &pwrmon_debugfs_power_fops); - }; + } kfree(rail_names); return; -- cgit v0.10.2 From 7aefe7918f8e053f9cd8077fcc98182689f1341e Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 27 May 2016 17:26:22 +0200 Subject: greybus: core: avoid I/O to disconnected interfaces Add new helper to disable connections to interfaces that have already been disconnected (e.g. forcibly removed). The connection tear-down procedure differs enough depending on whether the interface is still present or already gone to warrant a dedicated helper. This will become more obvious with the new tear-down procedure, which involves I/O on the connection being tore down. This also simplifies handling of the legacy bootrom, which does not support the new tear-down operations. Specifically, this allows us to remove the early control-connection tear down during interface disable, and also avoids some error messages currently printed during legacy mode switch (i.e. bootrom boot-over-UniPro) and forcible removal. Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index ac3be2f..7e07ef8 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -654,6 +654,27 @@ out_unlock: } EXPORT_SYMBOL_GPL(gb_connection_disable); +/* Disable a connection without communicating with the remote end. */ +void gb_connection_disable_forced(struct gb_connection *connection) +{ + mutex_lock(&connection->mutex); + + if (connection->state == GB_CONNECTION_STATE_DISABLED) + goto out_unlock; + + spin_lock_irq(&connection->lock); + connection->state = GB_CONNECTION_STATE_DISABLED; + gb_connection_cancel_operations(connection, -ESHUTDOWN); + spin_unlock_irq(&connection->lock); + + gb_connection_svc_connection_destroy(connection); + gb_connection_hd_cport_disable(connection); + +out_unlock: + mutex_unlock(&connection->mutex); +} +EXPORT_SYMBOL_GPL(gb_connection_disable_forced); + /* Caller must have disabled the connection before destroying it. */ void gb_connection_destroy(struct gb_connection *connection) { diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 53ce2845..f159239 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -80,6 +80,7 @@ int gb_connection_enable(struct gb_connection *connection); int gb_connection_enable_tx(struct gb_connection *connection); void gb_connection_disable_rx(struct gb_connection *connection); void gb_connection_disable(struct gb_connection *connection); +void gb_connection_disable_forced(struct gb_connection *connection); void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id, u8 *data, size_t length); diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index b4a1c14..a5effcf 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -316,7 +316,10 @@ void gb_control_disable(struct gb_control *control) { dev_dbg(&control->connection->intf->dev, "%s\n", __func__); - gb_connection_disable(control->connection); + if (control->intf->disconnected) + gb_connection_disable_forced(control->connection); + else + gb_connection_disable(control->connection); } int gb_control_add(struct gb_control *control) diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index b1a7b11..7350c5e 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -189,7 +189,7 @@ static int greybus_remove(struct device *dev) list_for_each_entry(connection, &bundle->connections, bundle_links) { if (bundle->intf->disconnected) - gb_connection_disable(connection); + gb_connection_disable_forced(connection); else gb_connection_disable_rx(connection); } diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index c19a09c..d1e2c45 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -671,13 +671,6 @@ void gb_interface_disable(struct gb_interface *intf) trace_gb_interface_disable(intf); - /* - * Disable the control-connection early to avoid operation timeouts - * when the interface is already gone. - */ - if (intf->disconnected) - gb_control_disable(intf->control); - list_for_each_entry_safe(bundle, next, &intf->bundles, links) gb_bundle_destroy(bundle); -- cgit v0.10.2 From a4b08df4e01beac8a5e90f5dfb8a1ffda943d73d Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 27 May 2016 17:26:23 +0200 Subject: greybus: interface: clean up bootrom quirk handling Clean up bootrom quirk handling in preparation for addition of further flags. Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index d1e2c45..0f2b591 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -174,6 +174,7 @@ static void gb_interface_route_destroy(struct gb_interface *intf) static int gb_interface_read_and_clear_init_status(struct gb_interface *intf) { struct gb_host_device *hd = intf->hd; + unsigned long bootrom_quirks; int ret; u32 value; u16 attr; @@ -217,16 +218,18 @@ static int gb_interface_read_and_clear_init_status(struct gb_interface *intf) init_status = value >> 24; /* - * Check if the interface is executing the quirky ES3 bootrom that - * requires E2EFC, CSD and CSV to be disabled. + * Check if the interface is executing the quirky ES3 bootrom that, + * for example, requires E2EFC, CSD and CSV to be disabled. */ + bootrom_quirks = GB_INTERFACE_QUIRK_NO_CPORT_FEATURES; + switch (init_status) { case GB_INIT_BOOTROM_UNIPRO_BOOT_STARTED: case GB_INIT_BOOTROM_FALLBACK_UNIPRO_BOOT_STARTED: - intf->quirks |= GB_INTERFACE_QUIRK_NO_CPORT_FEATURES; + intf->quirks |= bootrom_quirks; break; default: - intf->quirks &= ~GB_INTERFACE_QUIRK_NO_CPORT_FEATURES; + intf->quirks &= ~bootrom_quirks; } /* Clear the init status. */ -- cgit v0.10.2 From d9fa3494b78a4e7fe9d8243ddd5ec472668f8fdf Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 27 May 2016 17:26:24 +0200 Subject: greybus: interface: avoid I/O to bootrom during removal Add an interface quirk flag to suppress I/O during interface disable. This is needed to prevent I/O to the bootrom during controlled connection tear down (e.g. eject or driver unbind). This will be more obvious with the new connection tear-down procedure. Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 0f2b591..2cfb5a4 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -221,8 +221,8 @@ static int gb_interface_read_and_clear_init_status(struct gb_interface *intf) * Check if the interface is executing the quirky ES3 bootrom that, * for example, requires E2EFC, CSD and CSV to be disabled. */ - bootrom_quirks = GB_INTERFACE_QUIRK_NO_CPORT_FEATURES; - + bootrom_quirks = GB_INTERFACE_QUIRK_NO_CPORT_FEATURES | + GB_INTERFACE_QUIRK_FORCED_DISABLE; switch (init_status) { case GB_INIT_BOOTROM_UNIPRO_BOOT_STARTED: case GB_INIT_BOOTROM_FALLBACK_UNIPRO_BOOT_STARTED: @@ -674,6 +674,10 @@ void gb_interface_disable(struct gb_interface *intf) trace_gb_interface_disable(intf); + /* Set disconnected flag to avoid I/O during connection tear down. */ + if (intf->quirks & GB_INTERFACE_QUIRK_FORCED_DISABLE) + intf->disconnected = true; + list_for_each_entry_safe(bundle, next, &intf->bundles, links) gb_bundle_destroy(bundle); diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 51772cc..e833f7d 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -13,6 +13,7 @@ #define GB_INTERFACE_QUIRK_NO_CPORT_FEATURES BIT(0) #define GB_INTERFACE_QUIRK_NO_INIT_STATUS BIT(1) #define GB_INTERFACE_QUIRK_NO_ARA_IDS BIT(2) +#define GB_INTERFACE_QUIRK_FORCED_DISABLE BIT(3) struct gb_interface { struct device dev; -- cgit v0.10.2 From aca7aab39aa2d69d0a5b1cfc9319506b7c26b79d Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 27 May 2016 17:26:25 +0200 Subject: greybus: connection: add control connection flag Add control connection flag which will be set for control connections. Also add a helper function to test if the flag is set. Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 7e07ef8..2da713ca 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -227,7 +227,8 @@ gb_connection_create_static(struct gb_host_device *hd, u16 hd_cport_id, struct gb_connection * gb_connection_create_control(struct gb_interface *intf) { - return _gb_connection_create(intf->hd, -1, intf, NULL, 0, NULL, 0); + return _gb_connection_create(intf->hd, -1, intf, NULL, 0, NULL, + GB_CONNECTION_FLAG_CONTROL); } struct gb_connection * @@ -412,11 +413,11 @@ static int gb_connection_control_connected(struct gb_connection *connection) return 0; } - control = connection->intf->control; - - if (connection == control->connection) + if (gb_connection_is_control(connection)) return 0; + control = connection->intf->control; + ret = gb_control_connected_operation(control, cport_id); if (ret) { dev_err(&connection->bundle->dev, @@ -438,11 +439,11 @@ gb_connection_control_disconnected(struct gb_connection *connection) if (gb_connection_is_static(connection)) return; - control = connection->intf->control; - - if (connection == control->connection) + if (gb_connection_is_control(connection)) return; + control = connection->intf->control; + ret = gb_control_disconnected_operation(control, cport_id); if (ret) { dev_warn(&connection->bundle->dev, diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index f159239..6120c08 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -17,6 +17,7 @@ #define GB_CONNECTION_FLAG_NO_FLOWCTRL BIT(1) #define GB_CONNECTION_FLAG_OFFLOADED BIT(2) #define GB_CONNECTION_FLAG_CDSI1 BIT(3) +#define GB_CONNECTION_FLAG_CONTROL BIT(4) enum gb_connection_state { GB_CONNECTION_STATE_INVALID = 0, @@ -104,6 +105,11 @@ static inline bool gb_connection_is_offloaded(struct gb_connection *connection) return connection->flags & GB_CONNECTION_FLAG_OFFLOADED; } +static inline bool gb_connection_is_control(struct gb_connection *connection) +{ + return connection->flags & GB_CONNECTION_FLAG_CONTROL; +} + static inline void *gb_connection_get_data(struct gb_connection *connection) { return connection->private; -- cgit v0.10.2 From 197616e227b5b562814828df4dac9477e27b0149 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 27 May 2016 17:26:26 +0200 Subject: greybus: control: implement disconnecting operation Implement the new disconnecting control operation needed for proper connection tear down. Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index a5effcf..c5cdf3c 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -149,6 +149,18 @@ int gb_control_disconnected_operation(struct gb_control *control, u16 cport_id) sizeof(request), NULL, 0); } +int gb_control_disconnecting_operation(struct gb_control *control, + u16 cport_id) +{ + struct gb_control_disconnecting_request request; + + request.cport_id = cpu_to_le16(cport_id); + + return gb_operation_sync(control->connection, + GB_CONTROL_TYPE_DISCONNECTING, &request, + sizeof(request), NULL, 0); +} + int gb_control_mode_switch_operation(struct gb_control *control) { return gb_operation_unidirectional(control->connection, diff --git a/drivers/staging/greybus/control.h b/drivers/staging/greybus/control.h index 33e7e27..9891fbd 100644 --- a/drivers/staging/greybus/control.h +++ b/drivers/staging/greybus/control.h @@ -36,6 +36,8 @@ void gb_control_put(struct gb_control *control); int gb_control_get_bundle_versions(struct gb_control *control); int gb_control_connected_operation(struct gb_control *control, u16 cport_id); int gb_control_disconnected_operation(struct gb_control *control, u16 cport_id); +int gb_control_disconnecting_operation(struct gb_control *control, + u16 cport_id); int gb_control_mode_switch_operation(struct gb_control *control); int gb_control_get_manifest_size_operation(struct gb_interface *intf); int gb_control_get_manifest_operation(struct gb_interface *intf, void *manifest, diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index b98f02c..216a1d1 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -123,6 +123,7 @@ struct gb_protocol_version_response { #define GB_CONTROL_TYPE_TIMESYNC_AUTHORITATIVE 0x09 /* Unused 0x0a */ #define GB_CONTROL_TYPE_BUNDLE_VERSION 0x0b +#define GB_CONTROL_TYPE_DISCONNECTING 0x0c #define GB_CONTROL_TYPE_TIMESYNC_GET_LAST_EVENT 0x0d #define GB_CONTROL_TYPE_MODE_SWITCH 0x0e @@ -160,6 +161,11 @@ struct gb_control_connected_request { __le16 cport_id; } __packed; +struct gb_control_disconnecting_request { + __le16 cport_id; +} __packed; +/* disconnecting response has no payload */ + struct gb_control_disconnected_request { __le16 cport_id; } __packed; -- cgit v0.10.2 From 96f5ab00c2a1bfc698bb9a51301f1cc1f83aa8e2 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 27 May 2016 17:26:27 +0200 Subject: greybus: svc: add stub connection-quiescing operation Add stubbed out connection-quiescing operation that is needed for proper connection tear down. Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 2b3b8d9..4176e23 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -438,6 +438,16 @@ int gb_svc_connection_create(struct gb_svc *svc, } EXPORT_SYMBOL_GPL(gb_svc_connection_create); +void gb_svc_connection_quiescing(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, + u8 intf2_id, u16 cport2_id) +{ + /* FIXME: implement */ + + dev_dbg(&svc->dev, "%s - (%u:%u %u:%u)\n", __func__, + intf1_id, cport1_id, intf2_id, cport2_id); +} +EXPORT_SYMBOL_GPL(gb_svc_connection_quiescing); + void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id) { diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index e3e0aa1..7a78c5b 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -64,6 +64,8 @@ int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, void gb_svc_route_destroy(struct gb_svc *svc, u8 intf1_id, u8 intf2_id); int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id, u8 cport_flags); +void gb_svc_connection_quiescing(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, + u8 intf2_id, u16 cport2_id); void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id); int gb_svc_intf_eject(struct gb_svc *svc, u8 intf_id); -- cgit v0.10.2 From 3cbe52c2e07ddb2c1f75e0ff9ff4e33a8e478877 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 27 May 2016 17:26:28 +0200 Subject: greybus: connection: log cport-enable error messages Log failures to disable a host cport, and include the connection name in cport enable/disable error messages. Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 2da713ca..785b60b 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -278,7 +278,8 @@ static int gb_connection_hd_cport_enable(struct gb_connection *connection) ret = hd->driver->cport_enable(hd, connection->hd_cport_id); if (ret) { dev_err(&hd->dev, - "failed to enable host cport: %d\n", ret); + "%s: failed to enable host cport: %d\n", + connection->name, ret); return ret; } @@ -288,11 +289,17 @@ static int gb_connection_hd_cport_enable(struct gb_connection *connection) static void gb_connection_hd_cport_disable(struct gb_connection *connection) { struct gb_host_device *hd = connection->hd; + int ret; if (!hd->driver->cport_disable) return; - hd->driver->cport_disable(hd, connection->hd_cport_id); + ret = hd->driver->cport_disable(hd, connection->hd_cport_id); + if (ret) { + dev_err(&hd->dev, + "%s: failed to disable host cport: %d\n", + connection->name, ret); + } } static int -- cgit v0.10.2 From 6adcf44170db6cddcbbf9321244e051a72120555 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 27 May 2016 17:26:29 +0200 Subject: greybus: es2: reset cports at disable Make sure to reset CPorts at disable rather than enable as per specification. Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index fd59c14..68a8461 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -602,7 +602,7 @@ static void es2_cport_release(struct gb_host_device *hd, u16 cport_id) ida_simple_remove(&hd->cport_id_map, cport_id); } -static int cport_enable(struct gb_host_device *hd, u16 cport_id) +static int cport_disable(struct gb_host_device *hd, u16 cport_id) { int retval; @@ -794,7 +794,7 @@ static struct gb_hd_driver es2_driver = { .message_cancel = message_cancel, .cport_allocate = es2_cport_allocate, .cport_release = es2_cport_release, - .cport_enable = cport_enable, + .cport_disable = cport_disable, .latency_tag_enable = latency_tag_enable, .latency_tag_disable = latency_tag_disable, .output = output, -- cgit v0.10.2 From e2efe1bbc42896c4c24fec16785be5264a2d7794 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 27 May 2016 17:26:30 +0200 Subject: greybus: connection: rename an error label Rename an error label to make it more descriptive. Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 785b60b..9c7133e 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -566,11 +566,11 @@ static int _gb_connection_enable(struct gb_connection *connection, bool rx) ret = gb_connection_control_connected(connection); if (ret) - goto err_svc_destroy; + goto err_flush_operations; return 0; -err_svc_destroy: +err_flush_operations: spin_lock_irq(&connection->lock); connection->state = GB_CONNECTION_STATE_DISABLED; gb_connection_cancel_operations(connection, -ESHUTDOWN); -- cgit v0.10.2 From 00ad6975e7ca131a446c3c2e6510eec39664646d Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 27 May 2016 17:26:31 +0200 Subject: greybus: connection: move CPort Buffer configuration out of svc helpers The CPort Buffer configuration in the host-device needs to match the CPort feature flags set by the SVC, but they need not always be configured at the same point in time. This will be used when implementing proper connection tear down. Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 9c7133e..f3a3915 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -345,7 +345,7 @@ gb_connection_svc_connection_create(struct gb_connection *connection) int ret; if (gb_connection_is_static(connection)) - return gb_connection_hd_cport_features_enable(connection); + return 0; intf = connection->intf; @@ -373,23 +373,12 @@ gb_connection_svc_connection_create(struct gb_connection *connection) return ret; } - ret = gb_connection_hd_cport_features_enable(connection); - if (ret) { - gb_svc_connection_destroy(hd->svc, hd->svc->ap_intf_id, - connection->hd_cport_id, - intf->interface_id, - connection->intf_cport_id); - return ret; - } - return 0; } static void gb_connection_svc_connection_destroy(struct gb_connection *connection) { - gb_connection_hd_cport_features_disable(connection); - if (gb_connection_is_static(connection)) return; @@ -557,6 +546,10 @@ static int _gb_connection_enable(struct gb_connection *connection, bool rx) if (ret) goto err_hd_cport_disable; + ret = gb_connection_hd_cport_features_enable(connection); + if (ret) + goto err_svc_connection_destroy; + spin_lock_irq(&connection->lock); if (connection->handler && rx) connection->state = GB_CONNECTION_STATE_ENABLED; @@ -576,6 +569,8 @@ err_flush_operations: gb_connection_cancel_operations(connection, -ESHUTDOWN); spin_unlock_irq(&connection->lock); + gb_connection_hd_cport_features_disable(connection); +err_svc_connection_destroy: gb_connection_svc_connection_destroy(connection); err_hd_cport_disable: gb_connection_hd_cport_disable(connection); @@ -654,6 +649,7 @@ void gb_connection_disable(struct gb_connection *connection) gb_connection_cancel_operations(connection, -ESHUTDOWN); spin_unlock_irq(&connection->lock); + gb_connection_hd_cport_features_disable(connection); gb_connection_svc_connection_destroy(connection); gb_connection_hd_cport_disable(connection); @@ -675,6 +671,7 @@ void gb_connection_disable_forced(struct gb_connection *connection) gb_connection_cancel_operations(connection, -ESHUTDOWN); spin_unlock_irq(&connection->lock); + gb_connection_hd_cport_features_disable(connection); gb_connection_svc_connection_destroy(connection); gb_connection_hd_cport_disable(connection); -- cgit v0.10.2 From 1430cc920ab374a94f3a31574a2d616dd7f4c4d1 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 27 May 2016 17:26:32 +0200 Subject: greybus: connection: remove unused invalid state Remove the unused legacy INVALID connection state. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 6120c08..9a35e61 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -20,10 +20,9 @@ #define GB_CONNECTION_FLAG_CONTROL BIT(4) enum gb_connection_state { - GB_CONNECTION_STATE_INVALID = 0, - GB_CONNECTION_STATE_DISABLED = 1, - GB_CONNECTION_STATE_ENABLED_TX = 2, - GB_CONNECTION_STATE_ENABLED = 3, + GB_CONNECTION_STATE_DISABLED = 0, + GB_CONNECTION_STATE_ENABLED_TX = 1, + GB_CONNECTION_STATE_ENABLED = 2, }; struct gb_operation; -- cgit v0.10.2 From 8890f95710d835ba9f843c7dd849858da1d847d8 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 27 May 2016 17:26:33 +0200 Subject: greybus: operation: clean up early connection-state check Now that the legacy invalid state is gone, clean up the early connection-state check in the receive path and explicitly drop incoming messages for disabled connection. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 20a8d74..aaa1345 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -968,8 +968,7 @@ void gb_connection_recv(struct gb_connection *connection, size_t msg_size; u16 operation_id; - if ((connection->state != GB_CONNECTION_STATE_ENABLED && - connection->state != GB_CONNECTION_STATE_ENABLED_TX) || + if (connection->state == GB_CONNECTION_STATE_DISABLED || gb_connection_is_offloaded(connection)) { dev_warn_ratelimited(dev, "%s: dropping %zu received bytes\n", connection->name, size); -- cgit v0.10.2 From 77bbbcf6d36d7ef2054a8b0dc8396cc0f092945e Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 27 May 2016 17:26:34 +0200 Subject: greybus: operation: restructure activation state handling Restructure the operation activation state handling in preparation for a new disconnecting state. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index aaa1345..75d1231 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -47,11 +47,15 @@ static int gb_operation_get_active(struct gb_operation *operation) spin_lock_irqsave(&connection->lock, flags); - if (connection->state != GB_CONNECTION_STATE_ENABLED && - (connection->state != GB_CONNECTION_STATE_ENABLED_TX || - gb_operation_is_incoming(operation))) { - spin_unlock_irqrestore(&connection->lock, flags); - return -ENOTCONN; + switch (connection->state) { + case GB_CONNECTION_STATE_ENABLED: + break; + case GB_CONNECTION_STATE_ENABLED_TX: + if (gb_operation_is_incoming(operation)) + goto err_unlock; + break; + default: + goto err_unlock; } if (operation->active++ == 0) @@ -62,6 +66,11 @@ static int gb_operation_get_active(struct gb_operation *operation) spin_unlock_irqrestore(&connection->lock, flags); return 0; + +err_unlock: + spin_unlock_irqrestore(&connection->lock, flags); + + return -ENOTCONN; } /* Caller holds operation reference. */ -- cgit v0.10.2 From 18079ece816b3b272b114b770e636f4e5567b028 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 27 May 2016 17:26:35 +0200 Subject: greybus: operation: add helper for creating core operations Add a new core operation flag and a helper that core can use to create core operations. This will be used to implement the ping operations that core sends as part of connection tear down. Note that a new trace point is also added. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h index 93e04a8..148ffaf 100644 --- a/drivers/staging/greybus/greybus_trace.h +++ b/drivers/staging/greybus/greybus_trace.h @@ -131,6 +131,11 @@ DECLARE_EVENT_CLASS(gb_operation, DEFINE_OPERATION_EVENT(gb_operation_create); /* + * Occurs after a new core operation has been created. + */ +DEFINE_OPERATION_EVENT(gb_operation_create_core); + +/* * Occurs after a new operation has been created for an incoming * request has been successfully created and initialized. */ diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 75d1231..fb4a29e 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -571,6 +571,26 @@ gb_operation_create_flags(struct gb_connection *connection, } EXPORT_SYMBOL_GPL(gb_operation_create_flags); +struct gb_operation * +gb_operation_create_core(struct gb_connection *connection, + u8 type, size_t request_size, + size_t response_size, unsigned long flags, + gfp_t gfp) +{ + struct gb_operation *operation; + + flags |= GB_OPERATION_FLAG_CORE; + + operation = gb_operation_create_common(connection, type, + request_size, response_size, + flags, gfp); + if (operation) + trace_gb_operation_create_core(operation); + + return operation; +} +/* Do not export this function. */ + size_t gb_operation_get_payload_size_max(struct gb_connection *connection) { struct gb_host_device *hd = connection->hd; diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 117d7df..de09a2c 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -60,6 +60,7 @@ struct gb_message { #define GB_OPERATION_FLAG_INCOMING BIT(0) #define GB_OPERATION_FLAG_UNIDIRECTIONAL BIT(1) #define GB_OPERATION_FLAG_SHORT_RESPONSE BIT(2) +#define GB_OPERATION_FLAG_CORE BIT(3) #define GB_OPERATION_FLAG_USER_MASK (GB_OPERATION_FLAG_SHORT_RESPONSE | \ GB_OPERATION_FLAG_UNIDIRECTIONAL) @@ -123,6 +124,11 @@ gb_operation_short_response_allowed(struct gb_operation *operation) return operation->flags & GB_OPERATION_FLAG_SHORT_RESPONSE; } +static inline bool gb_operation_is_core(struct gb_operation *operation) +{ + return operation->flags & GB_OPERATION_FLAG_CORE; +} + void gb_connection_recv(struct gb_connection *connection, void *data, size_t size); @@ -144,6 +150,12 @@ gb_operation_create(struct gb_connection *connection, response_size, 0, gfp); } +struct gb_operation * +gb_operation_create_core(struct gb_connection *connection, + u8 type, size_t request_size, + size_t response_size, unsigned long flags, + gfp_t gfp); + void gb_operation_get(struct gb_operation *operation); void gb_operation_put(struct gb_operation *operation); -- cgit v0.10.2 From 3de5acfafb3c610bc6f7013a1583852cbc2747f1 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 27 May 2016 17:26:36 +0200 Subject: greybus: connection: implement proper connection closure Implement proper connection closure, which includes sending ping requests on the connection being tore down while coordinating with the remote interface as well as the SVC. This specifically implements the new ping operation, which in case of offloaded connections is handled by the host-device driver in an implementation-defined manner through a new callback. Note that the normal connection tear-down procedure is executed in case of failed connection establishment due to failed connected operation. Specifically, the disconnecting request is sent also in case the connected operation never succeeded. This is needed since the interface may have enabled FCT flow upon receiving the connected request. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index f3a3915..7706751 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -389,6 +389,21 @@ gb_connection_svc_connection_destroy(struct gb_connection *connection) connection->intf_cport_id); } +static void +gb_connection_svc_connection_quiescing(struct gb_connection *connection) +{ + struct gb_host_device *hd = connection->hd; + + if (gb_connection_is_static(connection)) + return; + + gb_svc_connection_quiescing(hd->svc, + hd->svc->ap_intf_id, + connection->hd_cport_id, + connection->intf->interface_id, + connection->intf_cport_id); +} + /* Inform Interface about active CPorts */ static int gb_connection_control_connected(struct gb_connection *connection) { @@ -424,7 +439,26 @@ static int gb_connection_control_connected(struct gb_connection *connection) return 0; } -/* Inform Interface about inactive CPorts */ +static void +gb_connection_control_disconnecting(struct gb_connection *connection) +{ + struct gb_control *control; + u16 cport_id = connection->intf_cport_id; + int ret; + + if (gb_connection_is_static(connection)) + return; + + control = connection->intf->control; + + ret = gb_control_disconnecting_operation(control, cport_id); + if (ret) { + dev_err(&connection->hd->dev, + "%s: failed to send disconnecting: %d\n", + connection->name, ret); + } +} + static void gb_connection_control_disconnected(struct gb_connection *connection) { @@ -447,10 +481,56 @@ gb_connection_control_disconnected(struct gb_connection *connection) } } +static int gb_connection_ping_operation(struct gb_connection *connection) +{ + struct gb_operation *operation; + int ret; + + operation = gb_operation_create_core(connection, + GB_REQUEST_TYPE_PING, + 0, 0, 0, + GFP_KERNEL); + if (!operation) + return -ENOMEM; + + ret = gb_operation_request_send_sync(operation); + + gb_operation_put(operation); + + return ret; +} + +static int gb_connection_ping(struct gb_connection *connection) +{ + struct gb_host_device *hd = connection->hd; + int ret; + + if (gb_connection_is_static(connection)) + return 0; + + if (gb_connection_is_offloaded(connection)) { + if (!hd->driver->cport_ping) + return 0; + + ret = hd->driver->cport_ping(hd, connection->intf_cport_id); + } else { + ret = gb_connection_ping_operation(connection); + } + + if (ret) { + dev_err(&hd->dev, "%s: failed to send ping: %d\n", + connection->name, ret); + return ret; + } + + return 0; +} + /* * Cancel all active operations on a connection. * - * Locking: Called with connection lock held and state set to DISABLED. + * Locking: Called with connection lock held and state set to DISABLED or + * DISCONNECTING. */ static void gb_connection_cancel_operations(struct gb_connection *connection, int errno) @@ -559,17 +639,24 @@ static int _gb_connection_enable(struct gb_connection *connection, bool rx) ret = gb_connection_control_connected(connection); if (ret) - goto err_flush_operations; + goto err_control_disconnecting; return 0; -err_flush_operations: +err_control_disconnecting: + gb_connection_control_disconnecting(connection); + spin_lock_irq(&connection->lock); - connection->state = GB_CONNECTION_STATE_DISABLED; + connection->state = GB_CONNECTION_STATE_DISCONNECTING; gb_connection_cancel_operations(connection, -ESHUTDOWN); spin_unlock_irq(&connection->lock); + gb_connection_ping(connection); gb_connection_hd_cport_features_disable(connection); + gb_connection_svc_connection_quiescing(connection); + gb_connection_ping(connection); + gb_connection_control_disconnected(connection); + connection->state = GB_CONNECTION_STATE_DISABLED; err_svc_connection_destroy: gb_connection_svc_connection_destroy(connection); err_hd_cport_disable: @@ -642,14 +729,22 @@ void gb_connection_disable(struct gb_connection *connection) if (connection->state == GB_CONNECTION_STATE_DISABLED) goto out_unlock; - gb_connection_control_disconnected(connection); + gb_connection_control_disconnecting(connection); spin_lock_irq(&connection->lock); - connection->state = GB_CONNECTION_STATE_DISABLED; + connection->state = GB_CONNECTION_STATE_DISCONNECTING; gb_connection_cancel_operations(connection, -ESHUTDOWN); spin_unlock_irq(&connection->lock); + gb_connection_ping(connection); gb_connection_hd_cport_features_disable(connection); + gb_connection_svc_connection_quiescing(connection); + gb_connection_ping(connection); + + gb_connection_control_disconnected(connection); + + connection->state = GB_CONNECTION_STATE_DISABLED; + gb_connection_svc_connection_destroy(connection); gb_connection_hd_cport_disable(connection); diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 9a35e61..af171f5 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -20,9 +20,10 @@ #define GB_CONNECTION_FLAG_CONTROL BIT(4) enum gb_connection_state { - GB_CONNECTION_STATE_DISABLED = 0, - GB_CONNECTION_STATE_ENABLED_TX = 1, - GB_CONNECTION_STATE_ENABLED = 2, + GB_CONNECTION_STATE_DISABLED = 0, + GB_CONNECTION_STATE_ENABLED_TX = 1, + GB_CONNECTION_STATE_ENABLED = 2, + GB_CONNECTION_STATE_DISCONNECTING = 3, }; struct gb_operation; diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 216a1d1..6afd0a6 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -96,6 +96,7 @@ struct gb_operation_msg_hdr { /* Generic request types */ +#define GB_REQUEST_TYPE_PING 0x00 #define GB_REQUEST_TYPE_PROTOCOL_VERSION 0x01 #define GB_REQUEST_TYPE_INVALID 0x7f diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h index ad22962..7321cfd 100644 --- a/drivers/staging/greybus/hd.h +++ b/drivers/staging/greybus/hd.h @@ -21,6 +21,7 @@ struct gb_hd_driver { void (*cport_release)(struct gb_host_device *hd, u16 cport_id); int (*cport_enable)(struct gb_host_device *hd, u16 cport_id); int (*cport_disable)(struct gb_host_device *hd, u16 cport_id); + int (*cport_ping)(struct gb_host_device *hd, u16 cport_id); int (*message_send)(struct gb_host_device *hd, u16 dest_cport_id, struct gb_message *message, gfp_t gfp_mask); void (*message_cancel)(struct gb_message *message); diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index fb4a29e..7906a95 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -46,7 +46,6 @@ static int gb_operation_get_active(struct gb_operation *operation) unsigned long flags; spin_lock_irqsave(&connection->lock, flags); - switch (connection->state) { case GB_CONNECTION_STATE_ENABLED: break; @@ -54,6 +53,10 @@ static int gb_operation_get_active(struct gb_operation *operation) if (gb_operation_is_incoming(operation)) goto err_unlock; break; + case GB_CONNECTION_STATE_DISCONNECTING: + if (!gb_operation_is_core(operation)) + goto err_unlock; + break; default: goto err_unlock; } -- cgit v0.10.2 From 800d6c8f4e66cc6ff3737b4de1272c31cd9e1e3c Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 27 May 2016 17:26:37 +0200 Subject: greybus: connection: add flush host-device callback Add a new host-device callback to flush any host-device queues, including any ongoing transfers, as part of connection tear down. The host-device buffers are flushed after the disconnecting operation have completed and the AP queues have been emptied. This can be used to flush already queued messages which upon reception would have been discarded by the remote end anyway. Note that this does not remove the need to flush any host-device queues as part of CPort disable which needs to make the CPort ready for reuse after deallocating all associated state and resetting the port. Suggested-by: Mitchell Tasman <tasman@leaflabs.com> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 7706751..c1cdfcd 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -302,6 +302,24 @@ static void gb_connection_hd_cport_disable(struct gb_connection *connection) } } +static int gb_connection_hd_cport_flush(struct gb_connection *connection) +{ + struct gb_host_device *hd = connection->hd; + int ret; + + if (!hd->driver->cport_flush) + return 0; + + ret = hd->driver->cport_flush(hd, connection->hd_cport_id); + if (ret) { + dev_err(&hd->dev, "%s: failed to flush host cport: %d\n", + connection->name, ret); + return ret; + } + + return 0; +} + static int gb_connection_hd_cport_features_enable(struct gb_connection *connection) { @@ -651,6 +669,9 @@ err_control_disconnecting: gb_connection_cancel_operations(connection, -ESHUTDOWN); spin_unlock_irq(&connection->lock); + /* Transmit queue should already be empty. */ + gb_connection_hd_cport_flush(connection); + gb_connection_ping(connection); gb_connection_hd_cport_features_disable(connection); gb_connection_svc_connection_quiescing(connection); @@ -736,6 +757,8 @@ void gb_connection_disable(struct gb_connection *connection) gb_connection_cancel_operations(connection, -ESHUTDOWN); spin_unlock_irq(&connection->lock); + gb_connection_hd_cport_flush(connection); + gb_connection_ping(connection); gb_connection_hd_cport_features_disable(connection); gb_connection_svc_connection_quiescing(connection); @@ -766,6 +789,7 @@ void gb_connection_disable_forced(struct gb_connection *connection) gb_connection_cancel_operations(connection, -ESHUTDOWN); spin_unlock_irq(&connection->lock); + gb_connection_hd_cport_flush(connection); gb_connection_hd_cport_features_disable(connection); gb_connection_svc_connection_destroy(connection); gb_connection_hd_cport_disable(connection); diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h index 7321cfd..5136d0c 100644 --- a/drivers/staging/greybus/hd.h +++ b/drivers/staging/greybus/hd.h @@ -21,6 +21,7 @@ struct gb_hd_driver { void (*cport_release)(struct gb_host_device *hd, u16 cport_id); int (*cport_enable)(struct gb_host_device *hd, u16 cport_id); int (*cport_disable)(struct gb_host_device *hd, u16 cport_id); + int (*cport_flush)(struct gb_host_device *hd, u16 cport_id); int (*cport_ping)(struct gb_host_device *hd, u16 cport_id); int (*message_send)(struct gb_host_device *hd, u16 dest_cport_id, struct gb_message *message, gfp_t gfp_mask); -- cgit v0.10.2 From e3fbe484323a026ed3689c72bac186ab2009dbcb Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 27 May 2016 17:26:38 +0200 Subject: greybus: kernel_ver: backport reinit_completion to pre-3.13 Backport upstream reinit_completion() to pre-3.13 kernels. Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index f5e62ed..f6fb3bf 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -313,4 +313,19 @@ static inline bool led_sysfs_is_disabled(struct led_classdev *led_cdev) #define SPI_NOR_MODALIAS "m25p80" #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) +/** + * reinit_completion - reinitialize a completion structure + * @x: pointer to completion structure that is to be reinitialized + * + * This inline function should be used to reinitialize a completion structure + * so it can be reused. This is especially important after complete_all() is + * used. + */ +static inline void reinit_completion(struct completion *x) +{ + x->done = 0; +} +#endif + #endif /* __GREYBUS_KERNEL_VER_H */ -- cgit v0.10.2 From 08f94352e8d09f7db07b4e894b3c223ee92df5ad Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 27 May 2016 17:26:39 +0200 Subject: greybus: control: add error message to mode-switch helper Print an informative error message in case sending the mode-switch request fails. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index c5cdf3c..3e02bbb 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -163,9 +163,18 @@ int gb_control_disconnecting_operation(struct gb_control *control, int gb_control_mode_switch_operation(struct gb_control *control) { - return gb_operation_unidirectional(control->connection, + int ret; + + ret = gb_operation_unidirectional(control->connection, GB_CONTROL_TYPE_MODE_SWITCH, NULL, 0); + if (ret) { + dev_err(&control->dev, "failed to send mode switch: %d\n", + ret); + return ret; + } + + return 0; } int gb_control_timesync_enable(struct gb_control *control, u8 count, -- cgit v0.10.2 From 55742d2a071a569bf20f90d37b1b5b8a25a3f882 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 27 May 2016 17:26:40 +0200 Subject: greybus: interface: implement generic mode-switch functionality Add a generic interface for bundle drivers to use to request that a mode switch is carried out on its behalf. Mode switching involves tearing down all connections to an interface, sending a unidirectional mode-switch request, and waiting for a mailbox event that triggers deferred control connection reset and re-enumeration of the interface. In case of a timeout waiting for the interface mailbox event, or on other errors, the interface is powered off. All of this needs to be done by core from work-queue context in order not to block incoming SVC requests and bundle-device tear down. Care must also be taken to serialise against concurrent module removal events and eject requests. Special handling of legacy mode-switching is also added in order to continue to support the ES3 bootrom. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index c1cdfcd..3be767b 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -487,10 +487,23 @@ gb_connection_control_disconnected(struct gb_connection *connection) if (gb_connection_is_static(connection)) return; - if (gb_connection_is_control(connection)) + control = connection->intf->control; + + if (gb_connection_is_control(connection)) { + if (connection->mode_switch) { + ret = gb_control_mode_switch_operation(control); + if (ret) { + /* + * Allow mode switch to time out waiting for + * mailbox event. + */ + return; + } + } + return; + } - control = connection->intf->control; ret = gb_control_disconnected_operation(control, cport_id); if (ret) { @@ -743,6 +756,18 @@ out_unlock: } EXPORT_SYMBOL_GPL(gb_connection_disable_rx); +void gb_connection_mode_switch_prepare(struct gb_connection *connection) +{ + connection->mode_switch = true; +} + +void gb_connection_mode_switch_complete(struct gb_connection *connection) +{ + gb_connection_svc_connection_destroy(connection); + gb_connection_hd_cport_disable(connection); + connection->mode_switch = false; +} + void gb_connection_disable(struct gb_connection *connection) { mutex_lock(&connection->mutex); @@ -768,8 +793,11 @@ void gb_connection_disable(struct gb_connection *connection) connection->state = GB_CONNECTION_STATE_DISABLED; - gb_connection_svc_connection_destroy(connection); - gb_connection_hd_cport_disable(connection); + /* control-connection tear down is deferred when mode switching */ + if (!connection->mode_switch) { + gb_connection_svc_connection_destroy(connection); + gb_connection_hd_cport_disable(connection); + } out_unlock: mutex_unlock(&connection->mutex); diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index af171f5..9cd0bac 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -58,6 +58,8 @@ struct gb_connection { atomic_t op_cycle; void *private; + + bool mode_switch; }; struct gb_connection *gb_connection_create_static(struct gb_host_device *hd, @@ -83,6 +85,9 @@ void gb_connection_disable_rx(struct gb_connection *connection); void gb_connection_disable(struct gb_connection *connection); void gb_connection_disable_forced(struct gb_connection *connection); +void gb_connection_mode_switch_prepare(struct gb_connection *connection); +void gb_connection_mode_switch_complete(struct gb_connection *connection); + void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id, u8 *data, size_t length); diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index 3e02bbb..d772c27 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -364,7 +364,24 @@ void gb_control_del(struct gb_control *control) device_del(&control->dev); } +struct gb_control *gb_control_get(struct gb_control *control) +{ + get_device(&control->dev); + + return control; +} + void gb_control_put(struct gb_control *control) { put_device(&control->dev); } + +void gb_control_mode_switch_prepare(struct gb_control *control) +{ + gb_connection_mode_switch_prepare(control->connection); +} + +void gb_control_mode_switch_complete(struct gb_control *control) +{ + gb_connection_mode_switch_complete(control->connection); +} diff --git a/drivers/staging/greybus/control.h b/drivers/staging/greybus/control.h index 9891fbd..b1e5af2 100644 --- a/drivers/staging/greybus/control.h +++ b/drivers/staging/greybus/control.h @@ -31,6 +31,7 @@ int gb_control_enable(struct gb_control *control); void gb_control_disable(struct gb_control *control); int gb_control_add(struct gb_control *control); void gb_control_del(struct gb_control *control); +struct gb_control *gb_control_get(struct gb_control *control); void gb_control_put(struct gb_control *control); int gb_control_get_bundle_versions(struct gb_control *control); @@ -39,6 +40,8 @@ int gb_control_disconnected_operation(struct gb_control *control, u16 cport_id); int gb_control_disconnecting_operation(struct gb_control *control, u16 cport_id); int gb_control_mode_switch_operation(struct gb_control *control); +void gb_control_mode_switch_prepare(struct gb_control *control); +void gb_control_mode_switch_complete(struct gb_control *control); int gb_control_get_manifest_size_operation(struct gb_interface *intf); int gb_control_get_manifest_operation(struct gb_interface *intf, void *manifest, size_t size); diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 2cfb5a4..b5d243b 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -8,9 +8,10 @@ */ #include "greybus.h" - #include "greybus_trace.h" +#define GB_INTERFACE_MODE_SWITCH_TIMEOUT 1000 + #define GB_INTERFACE_DEVICE_ID_BAD 0xff /* Don't-care selector index */ @@ -163,6 +164,174 @@ static void gb_interface_route_destroy(struct gb_interface *intf) intf->device_id = GB_INTERFACE_DEVICE_ID_BAD; } +/* Locking: Caller holds the interface mutex. */ +static int gb_interface_legacy_mode_switch(struct gb_interface *intf) +{ + int ret; + + dev_info(&intf->dev, "legacy mode switch detected\n"); + + /* Mark as disconnected to prevent I/O during disable. */ + intf->disconnected = true; + gb_interface_disable(intf); + intf->disconnected = false; + + ret = gb_interface_enable(intf); + if (ret) { + dev_err(&intf->dev, "failed to re-enable interface: %d\n", ret); + gb_interface_deactivate(intf); + } + + return ret; +} + +void gb_interface_mailbox_event(struct gb_interface *intf, u16 result, + u32 mailbox) +{ + mutex_lock(&intf->mutex); + + if (result) { + dev_warn(&intf->dev, + "mailbox event with UniPro error: 0x%04x\n", + result); + goto err_disable; + } + + if (mailbox != GB_SVC_INTF_MAILBOX_GREYBUS) { + dev_warn(&intf->dev, + "mailbox event with unexpected value: 0x%08x\n", + mailbox); + goto err_disable; + } + + if (intf->quirks & GB_INTERFACE_QUIRK_LEGACY_MODE_SWITCH) { + gb_interface_legacy_mode_switch(intf); + goto out_unlock; + } + + if (!intf->mode_switch) { + dev_warn(&intf->dev, "unexpected mailbox event: 0x%08x\n", + mailbox); + goto err_disable; + } + + dev_info(&intf->dev, "mode switch detected\n"); + + complete(&intf->mode_switch_completion); + +out_unlock: + mutex_unlock(&intf->mutex); + + return; + +err_disable: + gb_interface_disable(intf); + gb_interface_deactivate(intf); + mutex_unlock(&intf->mutex); +} + +static void gb_interface_mode_switch_work(struct work_struct *work) +{ + struct gb_interface *intf; + struct gb_control *control; + unsigned long timeout; + int ret; + + intf = container_of(work, struct gb_interface, mode_switch_work); + + mutex_lock(&intf->mutex); + /* Make sure interface is still enabled. */ + if (!intf->enabled) { + dev_dbg(&intf->dev, "mode switch aborted\n"); + intf->mode_switch = false; + mutex_unlock(&intf->mutex); + goto out_interface_put; + } + + /* + * Prepare the control device for mode switch and make sure to get an + * extra reference before it goes away during interface disable. + */ + control = gb_control_get(intf->control); + gb_control_mode_switch_prepare(control); + gb_interface_disable(intf); + mutex_unlock(&intf->mutex); + + timeout = msecs_to_jiffies(GB_INTERFACE_MODE_SWITCH_TIMEOUT); + ret = wait_for_completion_interruptible_timeout( + &intf->mode_switch_completion, timeout); + + /* Finalise control-connection mode switch. */ + gb_control_mode_switch_complete(control); + gb_control_put(control); + + if (ret < 0) { + dev_err(&intf->dev, "mode switch interrupted\n"); + goto err_deactivate; + } else if (ret == 0) { + dev_err(&intf->dev, "mode switch timed out\n"); + goto err_deactivate; + } + + /* Re-enable (re-enumerate) interface if still active. */ + mutex_lock(&intf->mutex); + intf->mode_switch = false; + if (intf->active) { + ret = gb_interface_enable(intf); + if (ret) { + dev_err(&intf->dev, "failed to re-enable interface: %d\n", + ret); + gb_interface_deactivate(intf); + } + } + mutex_unlock(&intf->mutex); + +out_interface_put: + gb_interface_put(intf); + + return; + +err_deactivate: + mutex_lock(&intf->mutex); + intf->mode_switch = false; + gb_interface_deactivate(intf); + mutex_unlock(&intf->mutex); + + gb_interface_put(intf); +} + +int gb_interface_request_mode_switch(struct gb_interface *intf) +{ + int ret = 0; + + mutex_lock(&intf->mutex); + if (intf->mode_switch) { + ret = -EBUSY; + goto out_unlock; + } + + intf->mode_switch = true; + reinit_completion(&intf->mode_switch_completion); + + /* + * Get a reference to the interface device, which will be put once the + * mode switch is complete. + */ + get_device(&intf->dev); + + if (!queue_work(system_long_wq, &intf->mode_switch_work)) { + put_device(&intf->dev); + ret = -EBUSY; + goto out_unlock; + } + +out_unlock: + mutex_unlock(&intf->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(gb_interface_request_mode_switch); + /* * T_TstSrcIncrement is written by the module on ES2 as a stand-in for the * init-status attribute DME_TOSHIBA_INIT_STATUS. The AP needs to read and @@ -222,7 +391,8 @@ static int gb_interface_read_and_clear_init_status(struct gb_interface *intf) * for example, requires E2EFC, CSD and CSV to be disabled. */ bootrom_quirks = GB_INTERFACE_QUIRK_NO_CPORT_FEATURES | - GB_INTERFACE_QUIRK_FORCED_DISABLE; + GB_INTERFACE_QUIRK_FORCED_DISABLE | + GB_INTERFACE_QUIRK_LEGACY_MODE_SWITCH; switch (init_status) { case GB_INIT_BOOTROM_UNIPRO_BOOT_STARTED: case GB_INIT_BOOTROM_FALLBACK_UNIPRO_BOOT_STARTED: @@ -368,6 +538,8 @@ struct gb_interface *gb_interface_create(struct gb_module *module, INIT_LIST_HEAD(&intf->bundles); INIT_LIST_HEAD(&intf->manifest_descs); mutex_init(&intf->mutex); + INIT_WORK(&intf->mode_switch_work, gb_interface_mode_switch_work); + init_completion(&intf->mode_switch_completion); /* Invalid device id to start with */ intf->device_id = GB_INTERFACE_DEVICE_ID_BAD; @@ -542,6 +714,10 @@ void gb_interface_deactivate(struct gb_interface *intf) trace_gb_interface_deactivate(intf); + /* Abort any ongoing mode switch. */ + if (intf->mode_switch) + complete(&intf->mode_switch_completion); + gb_interface_route_destroy(intf); gb_interface_hibernate_link(intf); gb_interface_unipro_set(intf, false); diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index e833f7d..603f146 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -14,6 +14,7 @@ #define GB_INTERFACE_QUIRK_NO_INIT_STATUS BIT(1) #define GB_INTERFACE_QUIRK_NO_ARA_IDS BIT(2) #define GB_INTERFACE_QUIRK_FORCED_DISABLE BIT(3) +#define GB_INTERFACE_QUIRK_LEGACY_MODE_SWITCH BIT(4) struct gb_interface { struct device dev; @@ -40,9 +41,14 @@ struct gb_interface { struct mutex mutex; bool disconnected; + bool ejected; bool active; bool enabled; + bool mode_switch; + + struct work_struct mode_switch_work; + struct completion mode_switch_completion; }; #define to_gb_interface(d) container_of(d, struct gb_interface, dev) @@ -55,5 +61,9 @@ void gb_interface_disable(struct gb_interface *intf); int gb_interface_add(struct gb_interface *intf); void gb_interface_del(struct gb_interface *intf); void gb_interface_put(struct gb_interface *intf); +void gb_interface_mailbox_event(struct gb_interface *intf, u16 result, + u32 mailbox); + +int gb_interface_request_mode_switch(struct gb_interface *intf); #endif /* __INTERFACE_H */ diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 4176e23..9df3f57 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -895,28 +895,6 @@ static struct gb_module *gb_svc_module_lookup(struct gb_svc *svc, u8 module_id) return NULL; } -static void gb_svc_intf_reenable(struct gb_svc *svc, struct gb_interface *intf) -{ - int ret; - - mutex_lock(&intf->mutex); - - /* Mark as disconnected to prevent I/O during disable. */ - intf->disconnected = true; - gb_interface_disable(intf); - intf->disconnected = false; - - ret = gb_interface_enable(intf); - if (ret) { - dev_err(&svc->dev, "failed to enable interface %u: %d\n", - intf->interface_id, ret); - - gb_interface_deactivate(intf); - } - - mutex_unlock(&intf->mutex); -} - static void gb_svc_process_hello_deferred(struct gb_operation *operation) { struct gb_connection *connection = operation->connection; @@ -965,10 +943,9 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation) /* All modules are considered 1x2 for now */ module = gb_svc_module_lookup(svc, intf_id); if (module) { - dev_info(&svc->dev, "mode switch detected on interface %u\n", - intf_id); - - return gb_svc_intf_reenable(svc, module->interfaces[0]); + /* legacy mode switch */ + return gb_interface_mailbox_event(module->interfaces[0], 0, + GB_SVC_INTF_MAILBOX_GREYBUS); } module = gb_module_create(hd, intf_id, 1); @@ -1115,31 +1092,7 @@ static void gb_svc_process_intf_mailbox_event(struct gb_operation *operation) return; } - if (result_code) { - dev_warn(&svc->dev, - "mailbox event %u with UniPro error: 0x%04x\n", - intf_id, result_code); - goto err_disable_interface; - } - - if (mailbox != GB_SVC_INTF_MAILBOX_GREYBUS) { - dev_warn(&svc->dev, - "mailbox event %u with unexected value: 0x%08x\n", - intf_id, mailbox); - goto err_disable_interface; - } - - dev_info(&svc->dev, "mode switch detected on interface %u\n", intf_id); - - gb_svc_intf_reenable(svc, intf); - - return; - -err_disable_interface: - mutex_lock(&intf->mutex); - gb_interface_disable(intf); - gb_interface_deactivate(intf); - mutex_unlock(&intf->mutex); + gb_interface_mailbox_event(intf, result_code, mailbox); } static void gb_svc_process_deferred_request(struct work_struct *work) -- cgit v0.10.2 From 8ccf389b1909a644e5941217e243ca1c663c8160 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 27 May 2016 17:26:41 +0200 Subject: greybus: svc: remove deprecated hotplug operations Now that firmware has made the switch to the new interface boot sequence, we can remove support for the deprecated hotplug and hot-unplug operations. Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 6afd0a6..77ac3f2 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -908,8 +908,6 @@ struct gb_spi_transfer_response { #define GB_SVC_TYPE_PROTOCOL_VERSION 0x01 #define GB_SVC_TYPE_SVC_HELLO 0x02 #define GB_SVC_TYPE_INTF_DEVICE_ID 0x03 -#define GB_SVC_TYPE_INTF_HOTPLUG 0x04 -#define GB_SVC_TYPE_INTF_HOT_UNPLUG 0x05 #define GB_SVC_TYPE_INTF_RESET 0x06 #define GB_SVC_TYPE_CONN_CREATE 0x07 #define GB_SVC_TYPE_CONN_DESTROY 0x08 @@ -983,23 +981,6 @@ struct gb_svc_intf_device_id_request { } __packed; /* device id response has no payload */ -struct gb_svc_intf_hotplug_request { - __u8 intf_id; - struct { - __le32 ddbl1_mfr_id; - __le32 ddbl1_prod_id; - __le32 ara_vend_id; - __le32 ara_prod_id; - __le64 serial_number; - } data; -} __packed; -/* hotplug response has no payload */ - -struct gb_svc_intf_hot_unplug_request { - __u8 intf_id; -} __packed; -/* hot unplug response has no payload */ - struct gb_svc_intf_reset_request { __u8 intf_id; } __packed; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 9df3f57..b41d262 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -924,73 +924,6 @@ static void gb_svc_process_hello_deferred(struct gb_operation *operation) ret); } -static void gb_svc_process_intf_hotplug(struct gb_operation *operation) -{ - struct gb_svc_intf_hotplug_request *request; - struct gb_connection *connection = operation->connection; - struct gb_svc *svc = gb_connection_get_data(connection); - struct gb_host_device *hd = connection->hd; - struct gb_module *module; - u8 intf_id; - int ret; - - /* The request message size has already been verified. */ - request = operation->request->payload; - intf_id = request->intf_id; - - dev_dbg(&svc->dev, "%s - id = %u\n", __func__, intf_id); - - /* All modules are considered 1x2 for now */ - module = gb_svc_module_lookup(svc, intf_id); - if (module) { - /* legacy mode switch */ - return gb_interface_mailbox_event(module->interfaces[0], 0, - GB_SVC_INTF_MAILBOX_GREYBUS); - } - - module = gb_module_create(hd, intf_id, 1); - if (!module) { - dev_err(&svc->dev, "failed to create module\n"); - return; - } - - ret = gb_module_add(module); - if (ret) { - gb_module_put(module); - return; - } - - list_add(&module->hd_node, &hd->modules); -} - -static void gb_svc_process_intf_hot_unplug(struct gb_operation *operation) -{ - struct gb_svc *svc = gb_connection_get_data(operation->connection); - struct gb_svc_intf_hot_unplug_request *request; - struct gb_module *module; - u8 intf_id; - - /* The request message size has already been verified. */ - request = operation->request->payload; - intf_id = request->intf_id; - - dev_dbg(&svc->dev, "%s - id = %u\n", __func__, intf_id); - - /* All modules are considered 1x2 for now */ - module = gb_svc_module_lookup(svc, intf_id); - if (!module) { - dev_warn(&svc->dev, "could not find hot-unplug interface %u\n", - intf_id); - return; - } - - module->disconnected = true; - - gb_module_del(module); - list_del(&module->hd_node); - gb_module_put(module); -} - static void gb_svc_process_module_inserted(struct gb_operation *operation) { struct gb_svc_module_inserted_request *request; @@ -1111,12 +1044,6 @@ static void gb_svc_process_deferred_request(struct work_struct *work) case GB_SVC_TYPE_SVC_HELLO: gb_svc_process_hello_deferred(operation); break; - case GB_SVC_TYPE_INTF_HOTPLUG: - gb_svc_process_intf_hotplug(operation); - break; - case GB_SVC_TYPE_INTF_HOT_UNPLUG: - gb_svc_process_intf_hot_unplug(operation); - break; case GB_SVC_TYPE_MODULE_INSERTED: gb_svc_process_module_inserted(operation); break; @@ -1153,51 +1080,6 @@ static int gb_svc_queue_deferred_request(struct gb_operation *operation) return 0; } -/* - * Bringing up a module can be time consuming, as that may require lots of - * initialization on the module side. Over that, we may also need to download - * the firmware first and flash that on the module. - * - * In order not to make other svc events wait for all this to finish, - * handle most of module hotplug stuff outside of the hotplug callback, with - * help of a workqueue. - */ -static int gb_svc_intf_hotplug_recv(struct gb_operation *op) -{ - struct gb_svc *svc = gb_connection_get_data(op->connection); - struct gb_svc_intf_hotplug_request *request; - - if (op->request->payload_size < sizeof(*request)) { - dev_warn(&svc->dev, "short hotplug request received (%zu < %zu)\n", - op->request->payload_size, sizeof(*request)); - return -EINVAL; - } - - request = op->request->payload; - - dev_dbg(&svc->dev, "%s - id = %u\n", __func__, request->intf_id); - - return gb_svc_queue_deferred_request(op); -} - -static int gb_svc_intf_hot_unplug_recv(struct gb_operation *op) -{ - struct gb_svc *svc = gb_connection_get_data(op->connection); - struct gb_svc_intf_hot_unplug_request *request; - - if (op->request->payload_size < sizeof(*request)) { - dev_warn(&svc->dev, "short hot unplug request received (%zu < %zu)\n", - op->request->payload_size, sizeof(*request)); - return -EINVAL; - } - - request = op->request->payload; - - dev_dbg(&svc->dev, "%s - id = %u\n", __func__, request->intf_id); - - return gb_svc_queue_deferred_request(op); -} - static int gb_svc_intf_reset_recv(struct gb_operation *op) { struct gb_svc *svc = gb_connection_get_data(op->connection); @@ -1371,10 +1253,6 @@ static int gb_svc_request_handler(struct gb_operation *op) if (!ret) svc->state = GB_SVC_STATE_SVC_HELLO; return ret; - case GB_SVC_TYPE_INTF_HOTPLUG: - return gb_svc_intf_hotplug_recv(op); - case GB_SVC_TYPE_INTF_HOT_UNPLUG: - return gb_svc_intf_hot_unplug_recv(op); case GB_SVC_TYPE_INTF_RESET: return gb_svc_intf_reset_recv(op); case GB_SVC_TYPE_KEY_EVENT: -- cgit v0.10.2 From dacf3eb7f3c1c474a55f7c24eef39011784d558c Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 27 May 2016 18:23:02 +0200 Subject: greybus: fix tracepoint-related whitespace issues Fix some whitespace issues introduced by the recent tracepoint changes. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index c56b988..7f0ed9f 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -8,9 +8,9 @@ */ #include "greybus.h" - #include "greybus_trace.h" + static ssize_t eject_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 7906a95..659e84b 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -570,7 +570,6 @@ gb_operation_create_flags(struct gb_connection *connection, trace_gb_operation_create(operation); return operation; - } EXPORT_SYMBOL_GPL(gb_operation_create_flags); -- cgit v0.10.2 From 12823178332216daa76512d256dbdacb5ba76ea7 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 27 May 2016 18:23:01 +0200 Subject: greybus: hd: fix gb_hd_release tracepoint The recently added gb_hd_release tracepoint was added to the wrong function. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index 5238825..12ac0b6 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -95,14 +95,14 @@ void gb_hd_cport_release(struct gb_host_device *hd, u16 cport_id) } ida_simple_remove(&hd->cport_id_map, cport_id); - - trace_gb_hd_release(hd); } static void gb_hd_release(struct device *dev) { struct gb_host_device *hd = to_gb_host_device(dev); + trace_gb_hd_release(hd); + if (hd->svc) gb_svc_put(hd->svc); ida_simple_remove(&gb_hd_bus_id_map, hd->bus_id); -- cgit v0.10.2 From e55c25206d5c99b12443eec37b4832d6817170ba Mon Sep 17 00:00:00 2001 From: Axel Haslam <ahaslam@baylibre.com> Date: Tue, 31 May 2016 14:36:08 +0200 Subject: greybus: uart: Handle CRTSCTS flag in termios Handle the CRTSCTS flag in set_termios, so that auto flow control can be turned off. For this, add a new flag in the line coding request specifically for this purpose. Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Axel Haslam <ahaslam@baylibre.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 77ac3f2..072e5c9 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -1304,6 +1304,9 @@ struct gb_uart_set_line_coding_request { #define GB_SERIAL_SPACE_PARITY 4 __u8 data_bits; + + __u8 flow_control; +#define GB_SERIAL_AUTO_RTSCTS_EN 0x1 } __packed; /* output control lines */ diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 5d8f4e8..44d8b9a 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -39,6 +39,7 @@ struct gb_tty_line_coding { __u8 format; __u8 parity; __u8 data_bits; + __u8 flow_control; }; struct gb_tty { @@ -375,9 +376,9 @@ static void gb_tty_set_termios(struct tty_struct *tty, if (C_BAUD(tty) == B0) { newline.rate = gb_tty->line_coding.rate; - newctrl &= ~GB_UART_CTRL_DTR; + newctrl &= ~(GB_UART_CTRL_DTR | GB_UART_CTRL_RTS); } else if (termios_old && (termios_old->c_cflag & CBAUD) == B0) { - newctrl |= GB_UART_CTRL_DTR; + newctrl |= (GB_UART_CTRL_DTR | GB_UART_CTRL_RTS); } if (newctrl != gb_tty->ctrlout) { @@ -385,6 +386,11 @@ static void gb_tty_set_termios(struct tty_struct *tty, send_control(gb_tty, newctrl); } + if (C_CRTSCTS(tty) && C_BAUD(tty) != B0) + newline.flow_control |= GB_SERIAL_AUTO_RTSCTS_EN; + else + newline.flow_control &= ~GB_SERIAL_AUTO_RTSCTS_EN; + if (memcmp(&gb_tty->line_coding, &newline, sizeof(newline))) { memcpy(&gb_tty->line_coding, &newline, sizeof(newline)); send_line_coding(gb_tty); -- cgit v0.10.2 From 219ffcf3a51d0e0d8464d42db01e1e745a0d690f Mon Sep 17 00:00:00 2001 From: Axel Haslam <ahaslam@baylibre.com> Date: Tue, 31 May 2016 14:36:09 +0200 Subject: greybus: uart: Implement dtr_rts callback. Dtr_dts allows the tty layer to set the flow control lines to the correct state during open and close. Note that locking for newctrl is missing throughout the driver and will be addressed on a separate patch. Suggested-and-reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Axel Haslam <ahaslam@baylibre.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 44d8b9a..c257fbf 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -604,6 +604,22 @@ static int gb_tty_ioctl(struct tty_struct *tty, unsigned int cmd, return -ENOIOCTLCMD; } +static void gb_tty_dtr_rts(struct tty_port *port, int on) +{ + struct gb_tty *gb_tty; + u8 newctrl; + + gb_tty = container_of(port, struct gb_tty, port); + newctrl = gb_tty->ctrlout; + + if (on) + newctrl |= (GB_UART_CTRL_DTR | GB_UART_CTRL_RTS); + else + newctrl &= ~(GB_UART_CTRL_DTR | GB_UART_CTRL_RTS); + + gb_tty->ctrlout = newctrl; + send_control(gb_tty, newctrl); +} static const struct tty_operations gb_ops = { .install = gb_tty_install, @@ -623,7 +639,9 @@ static const struct tty_operations gb_ops = { .tiocmset = gb_tty_tiocmset, }; -static struct tty_port_operations null_ops = { }; +static struct tty_port_operations gb_port_ops = { + .dtr_rts = gb_tty_dtr_rts, +}; static int gb_uart_probe(struct gbphy_device *gbphy_dev, const struct gbphy_device_id *id) @@ -681,7 +699,7 @@ static int gb_uart_probe(struct gbphy_device *gbphy_dev, mutex_init(&gb_tty->mutex); tty_port_init(&gb_tty->port); - gb_tty->port.ops = &null_ops; + gb_tty->port.ops = &gb_port_ops; gb_tty->connection = connection; gb_tty->gbphy_dev = gbphy_dev; -- cgit v0.10.2 From 8d6fbe9bf9947ee875c222a2e33d5977e2d052f2 Mon Sep 17 00:00:00 2001 From: Axel Haslam <ahaslam@baylibre.com> Date: Tue, 31 May 2016 14:36:10 +0200 Subject: greybus: uart: Use a fifo to send data to the modules The firmware now buffers data instead of blocking while the transfer is sent, and the write operation cannot sleep. Instead of using gb_transfer_sync (which sleeps) in the write callback, buffer data in a fifo and send it from from a work queue. The write_room callback will will report 1 byte less that what is really available in the fifo, to leave space for extra characters that may be added by the tty layer. Signed-off-by: Axel Haslam <ahaslam@baylibre.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index c257fbf..09fae9a 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -27,6 +27,8 @@ #include <linux/idr.h> #include <linux/fs.h> #include <linux/kdev_t.h> +#include <linux/kfifo.h> +#include <linux/workqueue.h> #include "greybus.h" #include "gbphy.h" @@ -34,6 +36,9 @@ #define GB_NUM_MINORS 16 /* 16 is is more than enough */ #define GB_NAME "ttyGB" +#define GB_UART_WRITE_FIFO_SIZE PAGE_SIZE +#define GB_UART_WRITE_ROOM_MARGIN 1 /* leave some space in fifo */ + struct gb_tty_line_coding { __le32 rate; __u8 format; @@ -61,6 +66,9 @@ struct gb_tty { u8 ctrlin; /* input control lines */ u8 ctrlout; /* output control lines */ struct gb_tty_line_coding line_coding; + struct work_struct tx_work; + struct kfifo write_fifo; + bool close_pending; }; static struct tty_driver *gb_tty_driver; @@ -166,25 +174,52 @@ static int gb_uart_request_handler(struct gb_operation *op) return ret; } -static int send_data(struct gb_tty *tty, u16 size, const u8 *data) +static void gb_uart_tx_write_work(struct work_struct *work) { struct gb_uart_send_data_request *request; + struct gb_tty *gb_tty; + unsigned long flags; + unsigned int send_size; int ret; - if (!data || !size) - return 0; + gb_tty = container_of(work, struct gb_tty, tx_work); + request = gb_tty->buffer; - if (size > tty->buffer_payload_max) - size = tty->buffer_payload_max; - request = tty->buffer; - request->size = cpu_to_le16(size); - memcpy(&request->data[0], data, size); - ret = gb_operation_sync(tty->connection, GB_UART_TYPE_SEND_DATA, - request, sizeof(*request) + size, NULL, 0); - if (ret) - return ret; - else - return size; + while (1) { + if (gb_tty->close_pending) + break; + + spin_lock_irqsave(&gb_tty->write_lock, flags); + send_size = kfifo_out_peek(&gb_tty->write_fifo, + &request->data[0], + gb_tty->buffer_payload_max); + if (!send_size) { + spin_unlock_irqrestore(&gb_tty->write_lock, flags); + break; + } + + spin_unlock_irqrestore(&gb_tty->write_lock, flags); + + request->size = cpu_to_le16(send_size); + ret = gb_operation_sync(gb_tty->connection, + GB_UART_TYPE_SEND_DATA, + request, sizeof(*request) + send_size, + NULL, 0); + if (ret) { + dev_err(&gb_tty->gbphy_dev->dev, + "send data error: %d\n", ret); + if (!gb_tty->close_pending) + schedule_work(work); + return; + } + + spin_lock_irqsave(&gb_tty->write_lock, flags); + ret = kfifo_out(&gb_tty->write_fifo, &request->data[0], + send_size); + spin_unlock_irqrestore(&gb_tty->write_lock, flags); + + tty_port_tty_wakeup(&gb_tty->port); + } } static int send_line_coding(struct gb_tty *tty) @@ -318,19 +353,42 @@ static int gb_tty_write(struct tty_struct *tty, const unsigned char *buf, { struct gb_tty *gb_tty = tty->driver_data; - return send_data(gb_tty, count, buf); + count = kfifo_in_spinlocked(&gb_tty->write_fifo, buf, count, + &gb_tty->write_lock); + if (count && !gb_tty->close_pending) + schedule_work(&gb_tty->tx_work); + + return count; } static int gb_tty_write_room(struct tty_struct *tty) { struct gb_tty *gb_tty = tty->driver_data; + unsigned long flags; + int room; + + spin_lock_irqsave(&gb_tty->write_lock, flags); + room = kfifo_avail(&gb_tty->write_fifo); + spin_unlock_irqrestore(&gb_tty->write_lock, flags); + + room -= GB_UART_WRITE_ROOM_MARGIN; + if (room < 0) + return 0; - return gb_tty->buffer_payload_max; + return room; } static int gb_tty_chars_in_buffer(struct tty_struct *tty) { - return 0; + struct gb_tty *gb_tty = tty->driver_data; + unsigned long flags; + int chars; + + spin_lock_irqsave(&gb_tty->write_lock, flags); + chars = kfifo_len(&gb_tty->write_fifo); + spin_unlock_irqrestore(&gb_tty->write_lock, flags); + + return chars; } static int gb_tty_break_ctl(struct tty_struct *tty, int state) @@ -621,6 +679,24 @@ static void gb_tty_dtr_rts(struct tty_port *port, int on) send_control(gb_tty, newctrl); } +static void gb_tty_port_shutdown(struct tty_port *port) +{ + struct gb_tty *gb_tty; + unsigned long flags; + + gb_tty = container_of(port, struct gb_tty, port); + + gb_tty->close_pending = true; + + cancel_work_sync(&gb_tty->tx_work); + + spin_lock_irqsave(&gb_tty->write_lock, flags); + kfifo_reset_out(&gb_tty->write_fifo); + spin_unlock_irqrestore(&gb_tty->write_lock, flags); + + gb_tty->close_pending = false; +} + static const struct tty_operations gb_ops = { .install = gb_tty_install, .open = gb_tty_open, @@ -641,6 +717,7 @@ static const struct tty_operations gb_ops = { static struct tty_port_operations gb_port_ops = { .dtr_rts = gb_tty_dtr_rts, + .shutdown = gb_tty_port_shutdown, }; static int gb_uart_probe(struct gbphy_device *gbphy_dev, @@ -680,6 +757,13 @@ static int gb_uart_probe(struct gbphy_device *gbphy_dev, goto exit_connection_destroy; } + INIT_WORK(&gb_tty->tx_work, gb_uart_tx_write_work); + + retval = kfifo_alloc(&gb_tty->write_fifo, GB_UART_WRITE_FIFO_SIZE, + GFP_KERNEL); + if (retval) + goto exit_buf_free; + minor = alloc_minor(gb_tty); if (minor < 0) { if (minor == -ENOSPC) { @@ -689,7 +773,7 @@ static int gb_uart_probe(struct gbphy_device *gbphy_dev, } else { retval = minor; } - goto exit_buf_free; + goto exit_kfifo_free; } gb_tty->minor = minor; @@ -741,6 +825,8 @@ exit_connection_disable: gb_connection_disable(connection); exit_release_minor: release_minor(gb_tty); +exit_kfifo_free: + kfifo_free(&gb_tty->write_fifo); exit_buf_free: kfree(gb_tty->buffer); exit_connection_destroy: @@ -777,6 +863,7 @@ static void gb_uart_remove(struct gbphy_device *gbphy_dev) gb_connection_disable(connection); tty_port_destroy(&gb_tty->port); gb_connection_destroy(connection); + kfifo_free(&gb_tty->write_fifo); kfree(gb_tty->buffer); kfree(gb_tty); } -- cgit v0.10.2 From a8bc00fb88037e0107a0682478f47396a073be5c Mon Sep 17 00:00:00 2001 From: Axel Haslam <ahaslam@baylibre.com> Date: Tue, 31 May 2016 14:36:11 +0200 Subject: greybus: uart: Add credits based tracking for transmit path To avoid polling the firmware for space, a credit based system is implemented. The host will keep track of how many credits (bytes) it has sent to the firmware, and stop sending data when the quota is filled. The host will be informed that the firmware has more room for data when it handles the receive_credits request message from the firmware, and will continue to write data as credits become available. The firmware and the host may implement an algorithm to aggregate credits, and avoid extra greybus traffic. Suggested-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Axel Haslam <ahaslam@baylibre.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 072e5c9..089751c 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -1269,6 +1269,7 @@ struct gb_raw_send_request { #define GB_UART_TYPE_SET_CONTROL_LINE_STATE 0x05 #define GB_UART_TYPE_SEND_BREAK 0x06 #define GB_UART_TYPE_SERIAL_STATE 0x07 /* Unsolicited data */ +#define GB_UART_TYPE_RECEIVE_CREDITS 0x08 /* Represents data from AP -> Module */ struct gb_uart_send_data_request { @@ -1289,6 +1290,10 @@ struct gb_uart_recv_data_request { __u8 data[0]; } __packed; +struct gb_uart_receive_credits_request { + __le16 count; +} __packed; + struct gb_uart_set_line_coding_request { __le32 rate; __u8 format; diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 09fae9a..14b3e9d 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -38,6 +38,7 @@ #define GB_UART_WRITE_FIFO_SIZE PAGE_SIZE #define GB_UART_WRITE_ROOM_MARGIN 1 /* leave some space in fifo */ +#define GB_UART_FIRMWARE_CREDITS 4096 struct gb_tty_line_coding { __le32 rate; @@ -69,6 +70,7 @@ struct gb_tty { struct work_struct tx_work; struct kfifo write_fifo; bool close_pending; + unsigned int credits; }; static struct tty_driver *gb_tty_driver; @@ -151,6 +153,53 @@ static int gb_uart_serial_state_handler(struct gb_operation *op) return 0; } +static int gb_uart_receive_credits_handler(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_tty *gb_tty = gb_connection_get_data(connection); + struct gb_message *request = op->request; + struct gb_uart_receive_credits_request *credit_request; + unsigned long flags; + unsigned int incoming_credits; + int ret = 0; + + if (request->payload_size < sizeof(*credit_request)) { + dev_err(&gb_tty->gbphy_dev->dev, + "short receive_credits event received (%zu < %zu)\n", + request->payload_size, + sizeof(*credit_request)); + return -EINVAL; + } + + credit_request = request->payload; + incoming_credits = le16_to_cpu(credit_request->count); + + spin_lock_irqsave(&gb_tty->write_lock, flags); + gb_tty->credits += incoming_credits; + if (gb_tty->credits > GB_UART_FIRMWARE_CREDITS) { + gb_tty->credits -= incoming_credits; + ret = -EINVAL; + } + spin_unlock_irqrestore(&gb_tty->write_lock, flags); + + if (ret) { + dev_err(&gb_tty->gbphy_dev->dev, + "invalid number of incoming credits: %d\n", + incoming_credits); + return ret; + } + + if (!gb_tty->close_pending) + schedule_work(&gb_tty->tx_work); + + /* + * the port the tty layer may be waiting for credits + */ + tty_port_tty_wakeup(&gb_tty->port); + + return ret; +} + static int gb_uart_request_handler(struct gb_operation *op) { struct gb_connection *connection = op->connection; @@ -165,6 +214,9 @@ static int gb_uart_request_handler(struct gb_operation *op) case GB_UART_TYPE_SERIAL_STATE: ret = gb_uart_serial_state_handler(op); break; + case GB_UART_TYPE_RECEIVE_CREDITS: + ret = gb_uart_receive_credits_handler(op); + break; default: dev_err(&gb_tty->gbphy_dev->dev, "unsupported unsolicited request: 0x%02x\n", type); @@ -190,14 +242,19 @@ static void gb_uart_tx_write_work(struct work_struct *work) break; spin_lock_irqsave(&gb_tty->write_lock, flags); + send_size = gb_tty->buffer_payload_max; + if (send_size > gb_tty->credits) + send_size = gb_tty->credits; + send_size = kfifo_out_peek(&gb_tty->write_fifo, &request->data[0], - gb_tty->buffer_payload_max); + send_size); if (!send_size) { spin_unlock_irqrestore(&gb_tty->write_lock, flags); break; } + gb_tty->credits -= send_size; spin_unlock_irqrestore(&gb_tty->write_lock, flags); request->size = cpu_to_le16(send_size); @@ -208,6 +265,9 @@ static void gb_uart_tx_write_work(struct work_struct *work) if (ret) { dev_err(&gb_tty->gbphy_dev->dev, "send data error: %d\n", ret); + spin_lock_irqsave(&gb_tty->write_lock, flags); + gb_tty->credits += send_size; + spin_unlock_irqrestore(&gb_tty->write_lock, flags); if (!gb_tty->close_pending) schedule_work(work); return; @@ -386,6 +446,8 @@ static int gb_tty_chars_in_buffer(struct tty_struct *tty) spin_lock_irqsave(&gb_tty->write_lock, flags); chars = kfifo_len(&gb_tty->write_fifo); + if (gb_tty->credits < GB_UART_FIRMWARE_CREDITS) + chars += GB_UART_FIRMWARE_CREDITS - gb_tty->credits; spin_unlock_irqrestore(&gb_tty->write_lock, flags); return chars; @@ -764,6 +826,8 @@ static int gb_uart_probe(struct gbphy_device *gbphy_dev, if (retval) goto exit_buf_free; + gb_tty->credits = GB_UART_FIRMWARE_CREDITS; + minor = alloc_minor(gb_tty); if (minor < 0) { if (minor == -ENOSPC) { -- cgit v0.10.2 From 2b3b87f056b276b688cb0429faf682cac33dbf7b Mon Sep 17 00:00:00 2001 From: Axel Haslam <ahaslam@baylibre.com> Date: Tue, 31 May 2016 14:36:12 +0200 Subject: greybus: uart: Implement flush_buffer Data may be held pening in the hardware because of flow control mechanisms. When the port is closed, we need to flush all data that was not sent. For this, use the greybus message GB_UART_TYPE_FLUSH_FIFOS which will flush all data queued on the module but not yet sent on the data line. Suggested-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Axel Haslam <ahaslam@baylibre.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 089751c..ff371c4 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -1270,6 +1270,7 @@ struct gb_raw_send_request { #define GB_UART_TYPE_SEND_BREAK 0x06 #define GB_UART_TYPE_SERIAL_STATE 0x07 /* Unsolicited data */ #define GB_UART_TYPE_RECEIVE_CREDITS 0x08 +#define GB_UART_TYPE_FLUSH_FIFOS 0x09 /* Represents data from AP -> Module */ struct gb_uart_send_data_request { @@ -1335,6 +1336,12 @@ struct gb_uart_serial_state_request { __u8 control; } __packed; +struct gb_uart_serial_flush_request { + __u8 flags; +#define GB_SERIAL_FLAG_FLUSH_TRANSMITTER 0x01 +#define GB_SERIAL_FLAG_FLUSH_RECEIVER 0x02 +} __packed; + /* Loopback */ /* Version of the Greybus loopback protocol we support */ diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 14b3e9d..7dc9f9b 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -317,6 +317,14 @@ static int send_break(struct gb_tty *gb_tty, u8 state) &request, sizeof(request), NULL, 0); } +static int gb_uart_flush(struct gb_tty *gb_tty, u8 flags) +{ + struct gb_uart_serial_flush_request request; + + request.flags = flags; + return gb_operation_sync(gb_tty->connection, GB_UART_TYPE_FLUSH_FIFOS, + &request, sizeof(request), NULL, 0); +} static struct gb_tty *get_gb_by_minor(unsigned minor) { @@ -745,6 +753,7 @@ static void gb_tty_port_shutdown(struct tty_port *port) { struct gb_tty *gb_tty; unsigned long flags; + int ret; gb_tty = container_of(port, struct gb_tty, port); @@ -756,6 +765,12 @@ static void gb_tty_port_shutdown(struct tty_port *port) kfifo_reset_out(&gb_tty->write_fifo); spin_unlock_irqrestore(&gb_tty->write_lock, flags); + ret = gb_uart_flush(gb_tty, GB_SERIAL_FLAG_FLUSH_TRANSMITTER); + if (ret) { + dev_err(&gb_tty->gbphy_dev->dev, + "error flushing transmitter: %d\n", ret); + } + gb_tty->close_pending = false; } -- cgit v0.10.2 From 5dad5c314b686ca84aa5477462fcfd2b1abcba46 Mon Sep 17 00:00:00 2001 From: Axel Haslam <ahaslam@baylibre.com> Date: Tue, 31 May 2016 14:36:13 +0200 Subject: greybus: uart: wait for credits on shutdown We should try to wait until all credits are accounted for before returning from shutdown. For this purpose add a helper function that will wait on completion, and call it form the shutdown. This helper will also be useful when "wait until sent" is implemented. Signed-off-by: Axel Haslam <ahaslam@baylibre.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 7dc9f9b..a2fca3b 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -29,6 +29,7 @@ #include <linux/kdev_t.h> #include <linux/kfifo.h> #include <linux/workqueue.h> +#include <linux/completion.h> #include "greybus.h" #include "gbphy.h" @@ -39,6 +40,7 @@ #define GB_UART_WRITE_FIFO_SIZE PAGE_SIZE #define GB_UART_WRITE_ROOM_MARGIN 1 /* leave some space in fifo */ #define GB_UART_FIRMWARE_CREDITS 4096 +#define GB_UART_CREDIT_WAIT_TIMEOUT_MSEC 10000 struct gb_tty_line_coding { __le32 rate; @@ -71,6 +73,7 @@ struct gb_tty { struct kfifo write_fifo; bool close_pending; unsigned int credits; + struct completion credits_complete; }; static struct tty_driver *gb_tty_driver; @@ -197,6 +200,9 @@ static int gb_uart_receive_credits_handler(struct gb_operation *op) */ tty_port_tty_wakeup(&gb_tty->port); + if (gb_tty->credits == GB_UART_FIRMWARE_CREDITS) + complete(&gb_tty->credits_complete); + return ret; } @@ -317,6 +323,24 @@ static int send_break(struct gb_tty *gb_tty, u8 state) &request, sizeof(request), NULL, 0); } +static int gb_uart_wait_for_all_credits(struct gb_tty *gb_tty) +{ + int ret; + + if (gb_tty->credits == GB_UART_FIRMWARE_CREDITS) + return 0; + + ret = wait_for_completion_timeout(&gb_tty->credits_complete, + msecs_to_jiffies(GB_UART_CREDIT_WAIT_TIMEOUT_MSEC)); + if (!ret) { + dev_err(&gb_tty->gbphy_dev->dev, + "time out waiting for credits\n"); + return -ETIMEDOUT; + } + + return 0; +} + static int gb_uart_flush(struct gb_tty *gb_tty, u8 flags) { struct gb_uart_serial_flush_request request; @@ -765,12 +789,18 @@ static void gb_tty_port_shutdown(struct tty_port *port) kfifo_reset_out(&gb_tty->write_fifo); spin_unlock_irqrestore(&gb_tty->write_lock, flags); + if (gb_tty->credits == GB_UART_FIRMWARE_CREDITS) + goto out; + ret = gb_uart_flush(gb_tty, GB_SERIAL_FLAG_FLUSH_TRANSMITTER); if (ret) { dev_err(&gb_tty->gbphy_dev->dev, "error flushing transmitter: %d\n", ret); } + gb_uart_wait_for_all_credits(gb_tty); + +out: gb_tty->close_pending = false; } @@ -842,6 +872,7 @@ static int gb_uart_probe(struct gbphy_device *gbphy_dev, goto exit_buf_free; gb_tty->credits = GB_UART_FIRMWARE_CREDITS; + init_completion(&gb_tty->credits_complete); minor = alloc_minor(gb_tty); if (minor < 0) { -- cgit v0.10.2 From 5e569115e9b9d4af631589b9d9cc5227a660b008 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 30 May 2016 11:31:52 +0530 Subject: greybus: Remove unused VERSION specific macros We don't use these anymore. Drop them. Note that some macro's specific to bridged PHY devices aren't removed in the patch, as gbsim will break otherwise. They will be removed separately. Compile tested. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index ff371c4..6550f17 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -407,10 +407,6 @@ struct gb_bootrom_get_vid_pid_response { /* Power Supply */ -/* Version of the Greybus power supply protocol we support */ -#define GB_POWER_SUPPLY_VERSION_MAJOR 0x00 -#define GB_POWER_SUPPLY_VERSION_MINOR 0x01 - /* Greybus power supply request types */ #define GB_POWER_SUPPLY_TYPE_GET_SUPPLIES 0x02 #define GB_POWER_SUPPLY_TYPE_GET_DESCRIPTION 0x03 @@ -572,10 +568,6 @@ struct gb_power_supply_event_request { /* HID */ -/* Version of the Greybus hid protocol we support */ -#define GB_HID_VERSION_MAJOR 0x00 -#define GB_HID_VERSION_MINOR 0x01 - /* Greybus HID operation types */ #define GB_HID_TYPE_GET_DESC 0x02 #define GB_HID_TYPE_GET_REPORT_DESC 0x03 @@ -1243,10 +1235,6 @@ struct gb_svc_intf_mailbox_event_request { /* RAW */ -/* Version of the Greybus raw protocol we support */ -#define GB_RAW_VERSION_MAJOR 0x00 -#define GB_RAW_VERSION_MINOR 0x01 - /* Greybus raw request types */ #define GB_RAW_TYPE_SEND 0x02 @@ -1344,10 +1332,6 @@ struct gb_uart_serial_flush_request { /* Loopback */ -/* Version of the Greybus loopback protocol we support */ -#define GB_LOOPBACK_VERSION_MAJOR 0x00 -#define GB_LOOPBACK_VERSION_MINOR 0x01 - /* Greybus loopback request types */ #define GB_LOOPBACK_TYPE_PING 0x02 #define GB_LOOPBACK_TYPE_TRANSFER 0x03 @@ -1532,9 +1516,6 @@ struct gb_sdio_event_request { /* Camera */ -#define GB_CAMERA_VERSION_MAJOR 0x00 -#define GB_CAMERA_VERSION_MINOR 0x01 - /* Greybus Camera request types */ #define GB_CAMERA_TYPE_CAPABILITIES 0x02 #define GB_CAMERA_TYPE_CONFIGURE_STREAMS 0x03 @@ -1608,9 +1589,6 @@ struct gb_camera_metadata_request { /* Lights */ -#define GB_LIGHTS_VERSION_MAJOR 0x00 -#define GB_LIGHTS_VERSION_MINOR 0x01 - /* Greybus Lights request types */ #define GB_LIGHTS_TYPE_GET_LIGHTS 0x02 #define GB_LIGHTS_TYPE_GET_LIGHT_CONFIG 0x03 @@ -1782,11 +1760,6 @@ struct gb_lights_get_flash_fault_response { /* Audio */ -/* Version of the Greybus audio protocol we support */ -#define GB_AUDIO_VERSION_MAJOR 0x00 -#define GB_AUDIO_VERSION_MINOR 0x01 - -#define GB_AUDIO_TYPE_PROTOCOL_VERSION 0x01 #define GB_AUDIO_TYPE_GET_TOPOLOGY_SIZE 0x02 #define GB_AUDIO_TYPE_GET_TOPOLOGY 0x03 #define GB_AUDIO_TYPE_GET_CONTROL 0x04 diff --git a/drivers/staging/greybus/usb.c b/drivers/staging/greybus/usb.c index 7ed6a60..e5ba34a 100644 --- a/drivers/staging/greybus/usb.c +++ b/drivers/staging/greybus/usb.c @@ -16,10 +16,6 @@ #include "greybus.h" #include "gbphy.h" -/* Version of the Greybus USB protocol we support */ -#define GB_USB_VERSION_MAJOR 0x00 -#define GB_USB_VERSION_MINOR 0x01 - /* Greybus USB request types */ #define GB_USB_TYPE_HCD_START 0x02 #define GB_USB_TYPE_HCD_STOP 0x03 diff --git a/drivers/staging/greybus/vibrator.c b/drivers/staging/greybus/vibrator.c index 5afcb27..33b2bf9c 100644 --- a/drivers/staging/greybus/vibrator.c +++ b/drivers/staging/greybus/vibrator.c @@ -21,10 +21,6 @@ struct gb_vibrator_device { int minor; /* vibrator minor number */ }; -/* Version of the Greybus vibrator protocol we support */ -#define GB_VIBRATOR_VERSION_MAJOR 0x00 -#define GB_VIBRATOR_VERSION_MINOR 0x01 - /* Greybus Vibrator operation types */ #define GB_VIBRATOR_TYPE_ON 0x02 #define GB_VIBRATOR_TYPE_OFF 0x03 -- cgit v0.10.2 From 64060fe95458f22bac7327b2ee8dc5ce9e488d44 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 30 May 2016 11:31:53 +0530 Subject: greybus: gbphy: Remove protocol specific version handling We should be using the generic version handling at bundle level, instead of at protocol level for bridged PHY devices as well. The bundle version handling is already in place, though it is *not* used today as we haven't bumped the version of control protocol yet. Remove protocol specific handling for bridged PHY devices. Tested on EVT 1.5 with gpbridge-test module. No nuttx changes are required with this. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 9cd0bac..7d0988e 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -44,9 +44,6 @@ struct gb_connection { gb_request_handler_t handler; unsigned long flags; - u8 module_major; - u8 module_minor; - struct mutex mutex; spinlock_t lock; enum gb_connection_state state; diff --git a/drivers/staging/greybus/gbphy.c b/drivers/staging/greybus/gbphy.c index c11a136..2727e4a 100644 --- a/drivers/staging/greybus/gbphy.c +++ b/drivers/staging/greybus/gbphy.c @@ -171,33 +171,6 @@ void gb_gbphy_deregister_driver(struct gbphy_driver *driver) } EXPORT_SYMBOL_GPL(gb_gbphy_deregister_driver); -int gb_gbphy_get_version(struct gb_connection *connection) -{ - struct gb_protocol_version_request request; - struct gb_protocol_version_response response; - int retval; - - request.major = 1; - request.minor = 0; - - retval = gb_operation_sync(connection, GB_REQUEST_TYPE_PROTOCOL_VERSION, - &request, sizeof(request), &response, - sizeof(response)); - if (retval) - return retval; - - /* FIXME - do proper version negotiation here someday... */ - - connection->module_major = response.major; - connection->module_minor = response.minor; - - dev_dbg(&connection->hd->dev, "%s: v%u.%u\n", connection->name, - response.major, response.minor); - - return 0; -} -EXPORT_SYMBOL_GPL(gb_gbphy_get_version); - static struct gbphy_device *gb_gbphy_create_dev(struct gb_bundle *bundle, struct greybus_descriptor_cport *cport_desc) { diff --git a/drivers/staging/greybus/gbphy.h b/drivers/staging/greybus/gbphy.h index 79dbf7e..68ad518 100644 --- a/drivers/staging/greybus/gbphy.h +++ b/drivers/staging/greybus/gbphy.h @@ -46,7 +46,6 @@ struct gbphy_driver { }; #define to_gbphy_driver(d) container_of(d, struct gbphy_driver, driver) -int gb_gbphy_get_version(struct gb_connection *connection); int gb_gbphy_register_driver(struct gbphy_driver *driver, struct module *owner, const char *mod_name); void gb_gbphy_deregister_driver(struct gbphy_driver *driver); diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index e1ad680..f60cc1d 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -654,10 +654,6 @@ static int gb_gpio_probe(struct gbphy_device *gbphy_dev, if (ret) goto exit_connection_destroy; - ret = gb_gbphy_get_version(connection); - if (ret) - goto exit_connection_disable; - ret = gb_gpio_controller_setup(ggc); if (ret) goto exit_connection_disable; diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 6550f17..82075c7 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -97,7 +97,6 @@ struct gb_operation_msg_hdr { /* Generic request types */ #define GB_REQUEST_TYPE_PING 0x00 -#define GB_REQUEST_TYPE_PROTOCOL_VERSION 0x01 #define GB_REQUEST_TYPE_INVALID 0x7f struct gb_protocol_version_request { @@ -614,10 +613,6 @@ struct gb_hid_input_report_request { /* I2C */ -/* Version of the Greybus i2c protocol we support */ -#define GB_I2C_VERSION_MAJOR 0x00 -#define GB_I2C_VERSION_MINOR 0x01 - /* Greybus i2c request types */ #define GB_I2C_TYPE_FUNCTIONALITY 0x02 #define GB_I2C_TYPE_TRANSFER 0x05 @@ -654,10 +649,6 @@ struct gb_i2c_transfer_response { /* GPIO */ -/* Version of the Greybus GPIO protocol we support */ -#define GB_GPIO_VERSION_MAJOR 0x00 -#define GB_GPIO_VERSION_MINOR 0x01 - /* Greybus GPIO request types */ #define GB_GPIO_TYPE_LINE_COUNT 0x02 #define GB_GPIO_TYPE_ACTIVATE 0x03 @@ -757,10 +748,6 @@ struct gb_gpio_irq_event_request { /* PWM */ -/* Version of the Greybus PWM protocol we support */ -#define GB_PWM_VERSION_MAJOR 0x00 -#define GB_PWM_VERSION_MINOR 0x01 - /* Greybus PWM operation types */ #define GB_PWM_TYPE_PWM_COUNT 0x02 #define GB_PWM_TYPE_ACTIVATE 0x03 @@ -804,10 +791,6 @@ struct gb_pwm_disable_request { /* SPI */ -/* Version of the Greybus spi protocol we support */ -#define GB_SPI_VERSION_MAJOR 0x00 -#define GB_SPI_VERSION_MINOR 0x01 - /* Should match up with modes in linux/spi/spi.h */ #define GB_SPI_MODE_CPHA 0x01 /* clock phase */ #define GB_SPI_MODE_CPOL 0x02 /* clock polarity */ @@ -1246,10 +1229,6 @@ struct gb_raw_send_request { /* UART */ -/* Version of the Greybus UART protocol we support */ -#define GB_UART_VERSION_MAJOR 0x00 -#define GB_UART_VERSION_MINOR 0x01 - /* Greybus UART operation types */ #define GB_UART_TYPE_SEND_DATA 0x02 #define GB_UART_TYPE_RECEIVE_DATA 0x03 /* Unsolicited data */ @@ -1356,10 +1335,6 @@ struct gb_loopback_transfer_response { } __packed; /* SDIO */ -/* Version of the Greybus sdio protocol we support */ -#define GB_SDIO_VERSION_MAJOR 0x00 -#define GB_SDIO_VERSION_MINOR 0x01 - /* Greybus SDIO operation types */ #define GB_SDIO_TYPE_GET_CAPABILITIES 0x02 #define GB_SDIO_TYPE_SET_IOS 0x03 diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c index 6c14e67..2541bdb 100644 --- a/drivers/staging/greybus/i2c.c +++ b/drivers/staging/greybus/i2c.c @@ -271,10 +271,6 @@ static int gb_i2c_probe(struct gbphy_device *gbphy_dev, if (ret) goto exit_connection_destroy; - ret = gb_gbphy_get_version(connection); - if (ret) - goto exit_connection_disable; - ret = gb_i2c_device_setup(gb_i2c_dev); if (ret) goto exit_connection_disable; diff --git a/drivers/staging/greybus/pwm.c b/drivers/staging/greybus/pwm.c index 77b05e8..b941cb5 100644 --- a/drivers/staging/greybus/pwm.c +++ b/drivers/staging/greybus/pwm.c @@ -206,10 +206,6 @@ static int gb_pwm_probe(struct gbphy_device *gbphy_dev, if (ret) goto exit_connection_destroy; - ret = gb_gbphy_get_version(connection); - if (ret) - goto exit_connection_disable; - /* Query number of pwms present */ ret = gb_pwm_count_operation(pwmc); if (ret) diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index bdcc869..a270517 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -748,10 +748,6 @@ static int gb_sdio_probe(struct gbphy_device *gbphy_dev, if (ret) goto exit_connection_destroy; - ret = gb_gbphy_get_version(connection); - if (ret) - goto exit_connection_disable; - ret = gb_sdio_get_caps(host); if (ret < 0) goto exit_connection_disable; diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index 4f13efe..a823379 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -29,10 +29,6 @@ static int gb_spi_probe(struct gbphy_device *gbphy_dev, if (ret) goto exit_connection_destroy; - ret = gb_gbphy_get_version(connection); - if (ret) - goto exit_connection_disable; - ret = gb_spilib_master_init(connection, &gbphy_dev->dev); if (ret) goto exit_connection_disable; diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index a2fca3b..d1611ab 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -904,10 +904,6 @@ static int gb_uart_probe(struct gbphy_device *gbphy_dev, if (retval) goto exit_release_minor; - retval = gb_gbphy_get_version(connection); - if (retval) - goto exit_connection_disable; - send_control(gb_tty, gb_tty->ctrlout); /* initialize the uart to be 9600n81 */ diff --git a/drivers/staging/greybus/usb.c b/drivers/staging/greybus/usb.c index e5ba34a..ccadda0 100644 --- a/drivers/staging/greybus/usb.c +++ b/drivers/staging/greybus/usb.c @@ -190,10 +190,6 @@ static int gb_usb_probe(struct gbphy_device *gbphy_dev, if (retval) goto exit_connection_destroy; - retval = gb_gbphy_get_version(connection); - if (retval) - goto exit_connection_disable; - /* * FIXME: The USB bridged-PHY protocol driver depends on changes to * USB core which are not yet upstream. -- cgit v0.10.2 From c92c1d026b1e13f20fee3350975a4986608ff84a Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 30 May 2016 13:05:08 +0530 Subject: greybus: fw-mgmt: Add hooks to do mode-switch This is the last step to required to finish the mode switch story. That is, call the hook provided by Interface layer to accomplish mode switch. Tested on EVT 1.5 with gpbridge-test module. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Tested-by: Karthik Ravi Shankar <karthikrs@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/fw-management.c b/drivers/staging/greybus/fw-management.c index da36de3..22dcad2 100644 --- a/drivers/staging/greybus/fw-management.c +++ b/drivers/staging/greybus/fw-management.c @@ -484,7 +484,14 @@ static int fw_mgmt_ioctl(struct fw_mgmt *fw_mgmt, unsigned int cmd, fw_mgmt->mode_switch_started = true; - /* FIXME: Initiate mode-switch from here */ + ret = gb_interface_request_mode_switch(fw_mgmt->connection->intf); + if (ret) { + dev_err(fw_mgmt->parent, "Mode-switch failed: %d\n", + ret); + fw_mgmt->mode_switch_started = false; + return ret; + } + return 0; default: return -ENOTTY; -- cgit v0.10.2 From 7ff6e0128a7da5d5a8b51abb09fafeb7b8944792 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 30 May 2016 13:05:09 +0530 Subject: greybus: control: Mode-switch is a 'core' operation The operation layer allows only the 'core' operations on a connection, which is in its 'disconnecting' state. Mode switch is sent at the very end of interface-disable sequence, and the control connection is already in its 'disconnecting' state at that time. And so gb_operation_get_active() always fail with error -ENOTCONN. The operation core already has support for such 'core' operations, just that we were missing the needed flag while creating the mode switch operation. Fix that. Tested on EVT 1.5 with gpbridge-test module. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Tested-by: Karthik Ravi Shankar <karthikrs@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index d772c27..88e5718 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -163,18 +163,24 @@ int gb_control_disconnecting_operation(struct gb_control *control, int gb_control_mode_switch_operation(struct gb_control *control) { + struct gb_operation *operation; int ret; - ret = gb_operation_unidirectional(control->connection, - GB_CONTROL_TYPE_MODE_SWITCH, - NULL, 0); + operation = gb_operation_create_core(control->connection, + GB_CONTROL_TYPE_MODE_SWITCH, + 0, 0, GB_OPERATION_FLAG_UNIDIRECTIONAL, + GFP_KERNEL); + if (!operation) + return -ENOMEM; + + ret = gb_operation_request_send_sync(operation); if (ret) { - dev_err(&control->dev, "failed to send mode switch: %d\n", - ret); - return ret; + dev_err(&control->dev, "failed to send mode switch: %d\n", ret); } - return 0; + gb_operation_put(operation); + + return ret; } int gb_control_timesync_enable(struct gb_control *control, u8 count, -- cgit v0.10.2 From 7dea1d5f8a9d3141881dab40bb55c1a7ae84d8ab Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 30 May 2016 13:05:10 +0530 Subject: greybus: interface: Mode switch takes over a second Mode switch takes just over a second to complete and the current timeout of one second isn't sufficient. Mode-switch logs from EVT 1.5: [ 56.709082] gb-firmware 1-3.3.1: Requested firmware package 'ara_00000126_00001002_fffe0001_ff980067_03.tftf' [ 57.003968] gb_control_mode_switch_operation: 176 [ 58.041616] greybus 1-3.3: mode switch detected Increase the timeout to two seconds. Tested with EVT 1.5 with gpbridge-test module. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Tested-by: Karthik Ravi Shankar <karthikrs@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index b5d243b..577d15f 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -10,7 +10,7 @@ #include "greybus.h" #include "greybus_trace.h" -#define GB_INTERFACE_MODE_SWITCH_TIMEOUT 1000 +#define GB_INTERFACE_MODE_SWITCH_TIMEOUT 2000 #define GB_INTERFACE_DEVICE_ID_BAD 0xff -- cgit v0.10.2 From 68ee90c29ea4068e03ad637af07f6ad7c27da544 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 30 May 2016 14:32:09 +0530 Subject: greybus: Add comment about the mode_switch_started flag Add a comment to describe the purpose of the flag. Suggested-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/fw-management.c b/drivers/staging/greybus/fw-management.c index 22dcad2..c9c28fc 100644 --- a/drivers/staging/greybus/fw-management.c +++ b/drivers/staging/greybus/fw-management.c @@ -482,6 +482,11 @@ static int fw_mgmt_ioctl(struct fw_mgmt *fw_mgmt, unsigned int cmd, return -EPERM; } + /* + * Disallow new ioctls as the fw-core bundle driver is going to + * get disconnected soon and the character device will get + * removed. + */ fw_mgmt->mode_switch_started = true; ret = gb_interface_request_mode_switch(fw_mgmt->connection->intf); -- cgit v0.10.2 From 07f91c75b490f67b1684a3a4d2b708a19ab93676 Mon Sep 17 00:00:00 2001 From: Evgeniy Borisov <borisov_evgeniy@projectara.com> Date: Tue, 31 May 2016 11:33:09 +0300 Subject: greybus: camera-gb: Add description of interface header Add description for all interface structures in gb-camera.h. Signed-off-by: Evgeniy Borisov <eborisov@mm-sol.com> Reviewed-by: Gjorgji Rosikopulos <grosikopulos@mm-sol.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/gb-camera.h b/drivers/staging/greybus/gb-camera.h index cc9c012..63f8c92 100644 --- a/drivers/staging/greybus/gb-camera.h +++ b/drivers/staging/greybus/gb-camera.h @@ -15,6 +15,19 @@ /* Output flags returned */ #define GB_CAMERA_OUT_FLAG_ADJUSTED (1 << 0) +/** + * struct gb_camera_stream - Represents greybus camera stream. + * @width: Stream width in pixels. + * @height: Stream height in pixels. + * @pixel_code: Media bus pixel code. + * @vc: MIPI CSI virtual channel. + * @dt: MIPI CSI data types. Most formats use a single data type, in which case + * the second element will be ignored. + * @max_size: Maximum size of a frame in bytes. The camera module guarantees + * that all data between the Frame Start and Frame End packet for + * the associated virtual channel and data type(s) will not exceed + * this size. + */ struct gb_camera_stream { unsigned int width; unsigned int height; @@ -26,10 +39,10 @@ struct gb_camera_stream { /** * struct gb_camera_csi_params - CSI configuration parameters - * @num_lanes: number of CSI data lanes - * @clk_freq: CSI clock frequency in Hz - * @lines_per_second: total number of lines in a second of transmission - * (blanking included) + * @num_lanes: number of CSI data lanes + * @clk_freq: CSI clock frequency in Hz + * @lines_per_second: Total number of lines in a second of transmission + * (blanking included) */ struct gb_camera_csi_params { unsigned int num_lanes; @@ -37,6 +50,46 @@ struct gb_camera_csi_params { unsigned int lines_per_second; }; +/** + * struct gb_camera_ops - Greybus camera operations, used by the Greybus camera + * driver to expose operations to the host camera driver. + * @capabilities: Retrieve camera capabilities and store them in the buffer + * 'buf' capabilities. The buffer maximum size is specified by + * the caller in the 'size' parameter, and the effective + * capabilities size is returned from the function. If the buffer + * size is too small to hold the capabilities an error is + * returned and the buffer is left untouched. + * + * @configure_streams: Negotiate configuration and prepare the module for video + * capture. The caller specifies the number of streams it + * requests in the 'nstreams' argument and the associated + * streams configurations in the 'streams' argument. The + * GB_CAMERA_IN_FLAG_TEST 'flag' can be set to test a + * configuration without applying it, otherwise the + * configuration is applied by the module. The module can + * decide to modify the requested configuration, including + * using a different number of streams. In that case the + * modified configuration won't be applied, the + * GB_CAMERA_OUT_FLAG_ADJUSTED 'flag' will be set upon + * return, and the modified configuration and number of + * streams stored in 'streams' and 'array'. The module + * returns its CSI-2 bus parameters in the 'csi_params' + * structure in all cases. + * + * @capture: Submit a capture request. The supplied 'request_id' must be unique + * and higher than the IDs of all the previously submitted requests. + * The 'streams' argument specifies which streams are affected by the + * request in the form of a bitmask, with bits corresponding to the + * configured streams indexes. If the request contains settings, the + * 'settings' argument points to the settings buffer and its size is + * specified by the 'settings_size' argument. Otherwise the 'settings' + * argument should be set to NULL and 'settings_size' to 0. + * + * @flush: Flush the capture requests queue. Return the ID of the last request + * that will processed by the device before it stops transmitting video + * frames. All queued capture requests with IDs higher than the returned + * ID will be dropped without being processed. + */ struct gb_camera_ops { ssize_t (*capabilities)(void *priv, char *buf, size_t len); int (*configure_streams)(void *priv, unsigned int *nstreams, @@ -48,6 +101,12 @@ struct gb_camera_ops { int (*flush)(void *priv, u32 *request_id); }; +/** + * struct gb_camera_module - Represents greybus camera module. + * @priv: Module private data, passed to all camera operations. + * @ops: Greybus camera operation callbacks. + * @list: List entry in the camera modules list. + */ struct gb_camera_module { void *priv; const struct gb_camera_ops *ops; -- cgit v0.10.2 From 6c5ce637db01c33712db996a78a74b25f3a5e0e3 Mon Sep 17 00:00:00 2001 From: Evgeniy Borisov <borisov_evgeniy@projectara.com> Date: Tue, 31 May 2016 11:33:10 +0300 Subject: greybus: camera-gb: Extend gb camera module structure Add additional information in gb camera module. - interface ID - reference count - release handle Signed-off-by: Evgeniy Borisov <eborisov@mm-sol.com> Reviewed-by: Gjorgji Rosikopulos <grosikopulos@mm-sol.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/gb-camera.h b/drivers/staging/greybus/gb-camera.h index 63f8c92..b8651ed 100644 --- a/drivers/staging/greybus/gb-camera.h +++ b/drivers/staging/greybus/gb-camera.h @@ -105,12 +105,18 @@ struct gb_camera_ops { * struct gb_camera_module - Represents greybus camera module. * @priv: Module private data, passed to all camera operations. * @ops: Greybus camera operation callbacks. + * @interface_id: Interface id of the module. + * @refcount: Reference counting object. + * @release: Module release function. * @list: List entry in the camera modules list. */ struct gb_camera_module { void *priv; const struct gb_camera_ops *ops; + unsigned int interface_id; + struct kref refcount; + void (*release)(struct kref *kref); struct list_head list; /* Global list */ }; -- cgit v0.10.2 From 17ca677018117deee1bd75b301894dca975e7fc5 Mon Sep 17 00:00:00 2001 From: Evgeniy Borisov <borisov_evgeniy@projectara.com> Date: Tue, 31 May 2016 11:33:11 +0300 Subject: greybus: camera-gb: Implement camera module reference counting as subject. In explanation: The main idea for implementing reference counting is to not block exit until any other modules are in use. Camera responsibility is to handle properly any additional calls after camera exit and that what this patch is doing: 1. Free camera module when reference count is zero. 2. After camera cleanup handle properly any additional ongoing transaction. Return error if connection is destroyed. Signed-off-by: Evgeniy Borisov <eborisov@mm-sol.com> Reviewed-by: Gjorgji Rosikopulos <grosikopulos@mm-sol.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index d5496f8..d7cef2a 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -35,7 +35,9 @@ struct gb_camera_debugfs_buffer { /** * struct gb_camera - A Greybus Camera Device - * @connection: the greybus connection for camera control + * @connection: the greybus connection for camera management + * @data_connection: the greybus connection for camera data + * @mutex: protects the connection field * @debugfs: debugfs entries for camera protocol operations testing * @module: Greybus camera module registered to HOST processor. */ @@ -43,6 +45,7 @@ struct gb_camera { struct gb_bundle *bundle; struct gb_connection *connection; struct gb_connection *data_connection; + struct mutex mutex; struct { struct dentry *root; @@ -163,15 +166,24 @@ static int gb_camera_set_power_mode(struct gb_camera *gcam, bool hs) static int gb_camera_capabilities(struct gb_camera *gcam, u8 *capabilities, size_t *size) { - struct gb_operation *op; + struct gb_operation *op = NULL; int ret; + mutex_lock(&gcam->mutex); + + if (!gcam->connection) { + ret = -EINVAL; + goto done; + } + op = gb_operation_create_flags(gcam->connection, GB_CAMERA_TYPE_CAPABILITIES, 0, *size, GB_OPERATION_FLAG_SHORT_RESPONSE, GFP_KERNEL); - if (!op) - return -ENOMEM; + if (!op) { + ret = -ENOMEM; + goto done; + } ret = gb_operation_request_send_sync(op); if (ret) { @@ -183,7 +195,9 @@ static int gb_camera_capabilities(struct gb_camera *gcam, *size = op->response->payload_size; done: - gb_operation_put(op); + mutex_unlock(&gcam->mutex); + if (op) + gb_operation_put(op); return ret; } @@ -222,8 +236,9 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, req = kmalloc(req_size, GFP_KERNEL); resp = kmalloc(resp_size, GFP_KERNEL); if (!req || !resp) { - ret = -ENOMEM; - goto done; + kfree(req); + kfree(resp); + return -ENOMEM; } req->num_streams = nstreams; @@ -239,6 +254,13 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, cfg->padding = 0; } + mutex_lock(&gcam->mutex); + + if (!gcam->connection) { + ret = -EINVAL; + goto done; + } + ret = gb_operation_sync(gcam->connection, GB_CAMERA_TYPE_CONFIGURE_STREAMS, req, req_size, resp, resp_size); @@ -329,6 +351,7 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, ret = 0; done: + mutex_unlock(&gcam->mutex); kfree(req); kfree(resp); return ret; @@ -356,8 +379,17 @@ static int gb_camera_capture(struct gb_camera *gcam, u32 request_id, req->num_frames = cpu_to_le16(num_frames); memcpy(req->settings, settings, settings_size); + mutex_lock(&gcam->mutex); + + if (!gcam->connection) { + ret = -EINVAL; + goto done; + } + ret = gb_operation_sync(gcam->connection, GB_CAMERA_TYPE_CAPTURE, - req, req_size, NULL, 0); + req, req_size, NULL, 0); +done: + mutex_unlock(&gcam->mutex); kfree(req); @@ -369,15 +401,26 @@ static int gb_camera_flush(struct gb_camera *gcam, u32 *request_id) struct gb_camera_flush_response resp; int ret; + mutex_lock(&gcam->mutex); + + if (!gcam->connection) { + ret = -EINVAL; + goto done; + } + ret = gb_operation_sync(gcam->connection, GB_CAMERA_TYPE_FLUSH, NULL, 0, &resp, sizeof(resp)); + if (ret < 0) - return ret; + goto done; if (request_id) *request_id = le32_to_cpu(resp.request_id); - return 0; +done: + mutex_unlock(&gcam->mutex); + + return ret; } static int gb_camera_request_handler(struct gb_operation *op) @@ -527,18 +570,6 @@ static const struct gb_camera_ops gb_cam_ops = { .flush = gb_camera_op_flush, }; -static int gb_camera_register_intf_ops(struct gb_camera *gcam) -{ - gcam->module.priv = gcam; - gcam->module.ops = &gb_cam_ops; - return gb_camera_register(&gcam->module); -} - -static int gb_camera_unregister_intf_ops(struct gb_camera *gcam) -{ - return gb_camera_unregister(&gcam->module); -} - /* ----------------------------------------------------------------------------- * DebugFS */ @@ -899,14 +930,23 @@ static void gb_camera_cleanup(struct gb_camera *gcam) if (gcam->data_connection) { gb_connection_disable(gcam->data_connection); gb_connection_destroy(gcam->data_connection); + gcam->data_connection = NULL; } + mutex_lock(&gcam->mutex); if (gcam->connection) { gb_connection_disable(gcam->connection); gb_connection_destroy(gcam->connection); + gcam->connection = NULL; } + mutex_unlock(&gcam->mutex); +} - kfree(gcam); +static void gb_camera_release_module(struct kref *ref) +{ + struct gb_camera_module *cam_mod = + container_of(ref, struct gb_camera_module, refcount); + kfree(cam_mod->priv); } static int gb_camera_probe(struct gb_bundle *bundle, @@ -964,6 +1004,8 @@ static int gb_camera_probe(struct gb_bundle *bundle, if (ret) goto error; + mutex_init(&gcam->mutex); + /* * Create the data connection between the camera module data CPort and * APB CDSI1. The CDSI1 CPort ID is hardcoded by the ES2 bridge. @@ -986,7 +1028,11 @@ static int gb_camera_probe(struct gb_bundle *bundle, if (ret < 0) goto error; - ret = gb_camera_register_intf_ops(gcam); + gcam->module.priv = gcam; + gcam->module.ops = &gb_cam_ops; + gcam->module.interface_id = gcam->connection->intf->interface_id; + gcam->module.release = gb_camera_release_module; + ret = gb_camera_register(&gcam->module); if (ret < 0) goto error; @@ -996,6 +1042,7 @@ static int gb_camera_probe(struct gb_bundle *bundle, error: gb_camera_cleanup(gcam); + kfree(gcam); return ret; } @@ -1003,8 +1050,8 @@ static void gb_camera_disconnect(struct gb_bundle *bundle) { struct gb_camera *gcam = greybus_get_drvdata(bundle); - gb_camera_unregister_intf_ops(gcam); gb_camera_cleanup(gcam); + gb_camera_unregister(&gcam->module); } static const struct greybus_bundle_id gb_camera_id_table[] = { -- cgit v0.10.2 From e5f23c45841ff371e4e515e8c5395fc659017930 Mon Sep 17 00:00:00 2001 From: Alex Elder <elder@linaro.org> Date: Fri, 3 Jun 2016 15:55:29 -0500 Subject: greybus: tracing: fix "make check" warnings Some of the trace buffer fields were defined as Booleans. This leads to two problems reported by "make check": - the __field() macro (or some descendent macro) performs a sizeof(bool) operation, which results in a warning - The TP_printk() macro, which specifies a printf() style format string, produces a warning when one attempts to format a Boolean as an integer. Fix both problems implicitly converting Boolean values from the data structures into integers in the trace buffer. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h index 148ffaf..52a7ef5 100644 --- a/drivers/staging/greybus/greybus_trace.h +++ b/drivers/staging/greybus/greybus_trace.h @@ -171,7 +171,7 @@ DECLARE_EVENT_CLASS(gb_module, __field(int, hd_bus_id) __field(u8, module_id) __field(u8, num_interfaces) - __field(bool, disconnected) + __field(int, disconnected) /* bool */ ), TP_fast_assign( @@ -180,7 +180,7 @@ DECLARE_EVENT_CLASS(gb_module, __entry->disconnected = module->disconnected; ), - TP_printk("greybus: hd_bus_id=%d module_id=%hhu disconnected=%u", + TP_printk("greybus: hd_bus_id=%d module_id=%hhu disconnected=%d", __entry->hd_bus_id, __entry->module_id, __entry->disconnected) ); @@ -224,10 +224,10 @@ DECLARE_EVENT_CLASS(gb_interface, __field(u8, id) /* Interface id */ __field(u8, module_id) __field(u8, device_id) - __field(bool, disconnected) - __field(bool, ejected) - __field(bool, active) - __field(bool, enabled) + __field(int, disconnected) /* bool */ + __field(int, ejected) /* bool */ + __field(int, active) /* bool */ + __field(int, enabled) /* bool */ ), TP_fast_assign( @@ -240,7 +240,7 @@ DECLARE_EVENT_CLASS(gb_interface, __entry->enabled = intf->enabled; ), - TP_printk("greybus: intf_id=%hhu device_id=%hhu module_id=%hhu D=%u J=%u A=%u E=%u", + TP_printk("greybus: intf_id=%hhu device_id=%hhu module_id=%hhu D=%d J=%d A=%d E=%d", __entry->id, __entry->device_id, __entry->module_id, __entry->disconnected, __entry->ejected, __entry->active, __entry->enabled) -- cgit v0.10.2 From 76639ef579012a1276043ed765a14170997155b2 Mon Sep 17 00:00:00 2001 From: Alex Elder <elder@linaro.org> Date: Fri, 3 Jun 2016 15:55:30 -0500 Subject: greybus: define BUNDLE_ID_NONE Define a bundle ID that means "no bundle". This will be used for tracing connection events during the portion of a connection's lifetime when it has no bundle associated with it. Don't allow any bundle to be created using that ID. Signed-off-by: Alex Elder <elder@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 1810b62..e7c00b6 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -102,6 +102,11 @@ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, { struct gb_bundle *bundle; + if (bundle_id == BUNDLE_ID_NONE) { + dev_err(&intf->dev, "can't use bundle id %u\n", bundle_id); + return NULL; + } + /* * Reject any attempt to reuse a bundle id. We initialize * these serially, so there's no need to worry about keeping diff --git a/drivers/staging/greybus/bundle.h b/drivers/staging/greybus/bundle.h index 2dc61ab..3895f94 100644 --- a/drivers/staging/greybus/bundle.h +++ b/drivers/staging/greybus/bundle.h @@ -12,6 +12,8 @@ #include <linux/list.h> +#define BUNDLE_ID_NONE U8_MAX + /* Greybus "public" definitions" */ struct gb_bundle { struct device dev; -- cgit v0.10.2 From c507397455a6b0b7de7393dad9b4c46c6926bc3f Mon Sep 17 00:00:00 2001 From: Alex Elder <elder@linaro.org> Date: Fri, 3 Jun 2016 15:55:31 -0500 Subject: greybus: tracing: fix host device num_cports The type of the gb_host_device num_cports field is size_t. Correct the num_cports data recorded with a host device event so its type matches that; fix the format length modifier used for it as well. Signed-off-by: Alex Elder <elder@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h index 52a7ef5..7157a67 100644 --- a/drivers/staging/greybus/greybus_trace.h +++ b/drivers/staging/greybus/greybus_trace.h @@ -302,7 +302,7 @@ DECLARE_EVENT_CLASS(gb_host_device, TP_STRUCT__entry( __field(int, bus_id) - __field(u8, num_cports) + __field(size_t, num_cports) __field(size_t, buffer_size_max) ), @@ -312,7 +312,7 @@ DECLARE_EVENT_CLASS(gb_host_device, __entry->buffer_size_max = hd->buffer_size_max; ), - TP_printk("greybus: bus_id=%d num_cports=%hu mtu=%zu", + TP_printk("greybus: bus_id=%d num_cports=%zu mtu=%zu", __entry->bus_id, __entry->num_cports, __entry->buffer_size_max) ); -- cgit v0.10.2 From 1ea3ed54dcc2e623db650cf9592d4d3469c99e65 Mon Sep 17 00:00:00 2001 From: Alex Elder <elder@linaro.org> Date: Fri, 3 Jun 2016 15:55:32 -0500 Subject: greybus: tracing: reorder trace definitions Move the definition of the module trace events below those for the interface. We'll define them in an order that represents a sort of layering of the abstractions (note not all of these are defined yet): message operation connection bundle interface module host device Other tracepoints (like perhaps some tied to timesync) will go at the beginning or end. Signed-off-by: Alex Elder <elder@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h index 7157a67..cd930ea 100644 --- a/drivers/staging/greybus/greybus_trace.h +++ b/drivers/staging/greybus/greybus_trace.h @@ -161,59 +161,6 @@ DEFINE_OPERATION_EVENT(gb_operation_put_active); #undef DEFINE_OPERATION_EVENT -DECLARE_EVENT_CLASS(gb_module, - - TP_PROTO(struct gb_module *module), - - TP_ARGS(module), - - TP_STRUCT__entry( - __field(int, hd_bus_id) - __field(u8, module_id) - __field(u8, num_interfaces) - __field(int, disconnected) /* bool */ - ), - - TP_fast_assign( - __entry->hd_bus_id = module->hd->bus_id; - __entry->module_id = module->module_id; - __entry->disconnected = module->disconnected; - ), - - TP_printk("greybus: hd_bus_id=%d module_id=%hhu disconnected=%d", - __entry->hd_bus_id, __entry->module_id, __entry->disconnected) -); - -#define DEFINE_MODULE_EVENT(name) \ - DEFINE_EVENT(gb_module, name, \ - TP_PROTO(struct gb_module *module), \ - TP_ARGS(module)) - -/* - * Occurs after a new module is successfully created, before - * creating any of its interfaces. - */ -DEFINE_MODULE_EVENT(gb_module_create); - -/* - * Occurs after the last reference to a module has been dropped. - */ -DEFINE_MODULE_EVENT(gb_module_release); - -/* - * Occurs after a module is successfully created, before registering - * any of its interfaces. - */ -DEFINE_MODULE_EVENT(gb_module_add); - -/* - * Occurs when a module is deleted, before deregistering its - * interfaces. - */ -DEFINE_MODULE_EVENT(gb_module_del); - -#undef DEFINE_MODULE_EVENT - DECLARE_EVENT_CLASS(gb_interface, TP_PROTO(struct gb_interface *intf), @@ -294,6 +241,59 @@ DEFINE_INTERFACE_EVENT(gb_interface_disable); #undef DEFINE_INTERFACE_EVENT +DECLARE_EVENT_CLASS(gb_module, + + TP_PROTO(struct gb_module *module), + + TP_ARGS(module), + + TP_STRUCT__entry( + __field(int, hd_bus_id) + __field(u8, module_id) + __field(u8, num_interfaces) + __field(int, disconnected) /* bool */ + ), + + TP_fast_assign( + __entry->hd_bus_id = module->hd->bus_id; + __entry->module_id = module->module_id; + __entry->disconnected = module->disconnected; + ), + + TP_printk("greybus: hd_bus_id=%d module_id=%hhu disconnected=%d", + __entry->hd_bus_id, __entry->module_id, __entry->disconnected) +); + +#define DEFINE_MODULE_EVENT(name) \ + DEFINE_EVENT(gb_module, name, \ + TP_PROTO(struct gb_module *module), \ + TP_ARGS(module)) + +/* + * Occurs after a new module is successfully created, before + * creating any of its interfaces. + */ +DEFINE_MODULE_EVENT(gb_module_create); + +/* + * Occurs after the last reference to a module has been dropped. + */ +DEFINE_MODULE_EVENT(gb_module_release); + +/* + * Occurs after a module is successfully created, before registering + * any of its interfaces. + */ +DEFINE_MODULE_EVENT(gb_module_add); + +/* + * Occurs when a module is deleted, before deregistering its + * interfaces. + */ +DEFINE_MODULE_EVENT(gb_module_del); + +#undef DEFINE_MODULE_EVENT + DECLARE_EVENT_CLASS(gb_host_device, TP_PROTO(struct gb_host_device *hd), -- cgit v0.10.2 From c65fdf031816001dde2bf852560c86d226e54da4 Mon Sep 17 00:00:00 2001 From: Alex Elder <elder@linaro.org> Date: Fri, 3 Jun 2016 15:55:33 -0500 Subject: greybus: tracing: fix module num_interfaces A module's num_interfaces field is included in the data to be recorded for tracing, but it's never assigned or reported. Fix its type to be size_t, to match its definition in the gb_module structure. Also correct a format length modifier used for a host device's num_cports field. Signed-off-by: Alex Elder <elder@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h index cd930ea..9d38cb3 100644 --- a/drivers/staging/greybus/greybus_trace.h +++ b/drivers/staging/greybus/greybus_trace.h @@ -250,18 +250,20 @@ DECLARE_EVENT_CLASS(gb_module, TP_STRUCT__entry( __field(int, hd_bus_id) __field(u8, module_id) - __field(u8, num_interfaces) + __field(size_t, num_interfaces) __field(int, disconnected) /* bool */ ), TP_fast_assign( __entry->hd_bus_id = module->hd->bus_id; __entry->module_id = module->module_id; + __entry->num_interfaces = module->num_interfaces; __entry->disconnected = module->disconnected; ), - TP_printk("greybus: hd_bus_id=%d module_id=%hhu disconnected=%d", - __entry->hd_bus_id, __entry->module_id, __entry->disconnected) + TP_printk("greybus: hd_bus_id=%d module_id=%hhu num_interfaces=%zu disconnected=%d", + __entry->hd_bus_id, __entry->module_id, + __entry->num_interfaces, __entry->disconnected) ); #define DEFINE_MODULE_EVENT(name) \ -- cgit v0.10.2 From 14a36ae70429f2872a8f750c60c75d14862761dc Mon Sep 17 00:00:00 2001 From: Alex Elder <elder@linaro.org> Date: Fri, 3 Jun 2016 15:55:34 -0500 Subject: greybus: tracing: assign "parent" id first Most abstractions to be traced will have a sort of "parent" object it is associated with, and an identifier for that parent is stored with the as trace event data. For example, the parent of a message is the operation it's a part of, and the parent of an operation is the connection it uses. We'll arrange to define that parent id first in all events. Most abstractions already do this. Move an interface's module id so it's defined and assigned first. The message traces are going to be changed soon, so leave that one alone. Signed-off-by: Alex Elder <elder@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h index 9d38cb3..5ecb504 100644 --- a/drivers/staging/greybus/greybus_trace.h +++ b/drivers/staging/greybus/greybus_trace.h @@ -168,8 +168,8 @@ DECLARE_EVENT_CLASS(gb_interface, TP_ARGS(intf), TP_STRUCT__entry( - __field(u8, id) /* Interface id */ __field(u8, module_id) + __field(u8, id) /* Interface id */ __field(u8, device_id) __field(int, disconnected) /* bool */ __field(int, ejected) /* bool */ @@ -178,8 +178,8 @@ DECLARE_EVENT_CLASS(gb_interface, ), TP_fast_assign( - __entry->id = intf->interface_id; __entry->module_id = intf->module->module_id; + __entry->id = intf->interface_id; __entry->device_id = intf->device_id; __entry->disconnected = intf->disconnected; __entry->ejected = intf->ejected; -- cgit v0.10.2 From 6879dbf15e866565cde7591337c2fcca7440ab6f Mon Sep 17 00:00:00 2001 From: Alex Elder <elder@linaro.org> Date: Fri, 3 Jun 2016 15:55:35 -0500 Subject: greybus: tracing: add interface mode_switch Add the value of an interface's mode_switch field to the information tracked and reported for tracing. Signed-off-by: Alex Elder <elder@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h index 5ecb504..80c428d 100644 --- a/drivers/staging/greybus/greybus_trace.h +++ b/drivers/staging/greybus/greybus_trace.h @@ -175,6 +175,7 @@ DECLARE_EVENT_CLASS(gb_interface, __field(int, ejected) /* bool */ __field(int, active) /* bool */ __field(int, enabled) /* bool */ + __field(int, mode_switch) /* bool */ ), TP_fast_assign( @@ -185,12 +186,13 @@ DECLARE_EVENT_CLASS(gb_interface, __entry->ejected = intf->ejected; __entry->active = intf->active; __entry->enabled = intf->enabled; + __entry->mode_switch = intf->mode_switch; ), - TP_printk("greybus: intf_id=%hhu device_id=%hhu module_id=%hhu D=%d J=%d A=%d E=%d", + TP_printk("greybus: intf_id=%hhu device_id=%hhu module_id=%hhu D=%d J=%d A=%d E=%d M=%d", __entry->id, __entry->device_id, __entry->module_id, __entry->disconnected, __entry->ejected, __entry->active, - __entry->enabled) + __entry->enabled, __entry->mode_switch) ); #define DEFINE_INTERFACE_EVENT(name) \ -- cgit v0.10.2 From 4f9c5c0bbb9fb4715ca01cd28ba04a3117a9be6f Mon Sep 17 00:00:00 2001 From: Alex Elder <elder@linaro.org> Date: Fri, 3 Jun 2016 15:55:36 -0500 Subject: greybus: tracing: define bundle traces Define a new gb_bundle trace point event class, used to trace events associated with the bundle abstraction. Define four basic trace points for this--creation time, drop of last reference, before adding it to its interface and when removed when its interface is destroyed. Signed-off-by: Alex Elder <elder@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index e7c00b6..c1c3d67 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -8,6 +8,7 @@ */ #include "greybus.h" +#include "greybus_trace.h" static ssize_t bundle_class_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -82,6 +83,8 @@ static void gb_bundle_release(struct device *dev) { struct gb_bundle *bundle = to_gb_bundle(dev); + trace_gb_bundle_release(bundle); + kfree(bundle->state); kfree(bundle->cport_desc); kfree(bundle); @@ -136,6 +139,8 @@ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, list_add(&bundle->links, &intf->bundles); + trace_gb_bundle_create(bundle); + return bundle; } @@ -149,6 +154,8 @@ int gb_bundle_add(struct gb_bundle *bundle) return ret; } + trace_gb_bundle_add(bundle); + return 0; } @@ -157,6 +164,8 @@ int gb_bundle_add(struct gb_bundle *bundle) */ void gb_bundle_destroy(struct gb_bundle *bundle) { + trace_gb_bundle_destroy(bundle); + if (device_is_registered(&bundle->dev)) device_del(&bundle->dev); diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h index 80c428d..a1dc070 100644 --- a/drivers/staging/greybus/greybus_trace.h +++ b/drivers/staging/greybus/greybus_trace.h @@ -16,6 +16,7 @@ struct gb_message; struct gb_operation; +struct gb_bundle; struct gb_host_device; #define gb_bundle_name(message) \ @@ -161,6 +162,61 @@ DEFINE_OPERATION_EVENT(gb_operation_put_active); #undef DEFINE_OPERATION_EVENT +DECLARE_EVENT_CLASS(gb_bundle, + + TP_PROTO(struct gb_bundle *bundle), + + TP_ARGS(bundle), + + TP_STRUCT__entry( + __field(u8, intf_id) + __field(u8, id) + __field(u8, class) + __field(size_t, num_cports) + ), + + TP_fast_assign( + __entry->intf_id = bundle->intf->interface_id; + __entry->id = bundle->id; + __entry->class = bundle->class; + __entry->num_cports = bundle->num_cports; + ), + + TP_printk("intf_id=0x%02x id=%02x class=0x%02x num_cports=%zu", + __entry->intf_id, __entry->id, __entry->class, + __entry->num_cports) +); + +#define DEFINE_BUNDLE_EVENT(name) \ + DEFINE_EVENT(gb_bundle, name, \ + TP_PROTO(struct gb_bundle *bundle), \ + TP_ARGS(bundle)) + +/* + * Occurs after a new bundle is successfully created. + */ +DEFINE_BUNDLE_EVENT(gb_bundle_create); + +/* + * Occurs when the last reference to a bundle has been dropped, + * before its resources are freed. + */ +DEFINE_BUNDLE_EVENT(gb_bundle_release); + +/* + * Occurs when a bundle is added to an interface when the interface + * is enabled. + */ +DEFINE_BUNDLE_EVENT(gb_bundle_add); + +/* + * Occurs when a registered bundle gets destroyed, normally at the + * time an interface is disabled. + */ +DEFINE_BUNDLE_EVENT(gb_bundle_destroy); + +#undef DEFINE_BUNDLE_EVENT + DECLARE_EVENT_CLASS(gb_interface, TP_PROTO(struct gb_interface *intf), -- cgit v0.10.2 From 79c8c6494220dafeaedf8dc94b50c9a787e25e5d Mon Sep 17 00:00:00 2001 From: Alex Elder <elder@linaro.org> Date: Fri, 3 Jun 2016 15:55:37 -0500 Subject: greybus: tracing: define connection traces Define a new gb_connection trace point event class, used to trace events associated with the connection abstraction. Define four basic trace events for this--creation, drop of last reference, and when adding or dropping any other reference. There are certainly more events that we might want to add, but aim is to just get the basic framework in place. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 3be767b..d35e95a 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -10,6 +10,7 @@ #include <linux/workqueue.h> #include "greybus.h" +#include "greybus_trace.h" static void gb_connection_kref_release(struct kref *kref); @@ -38,10 +39,14 @@ gb_connection_intf_find(struct gb_interface *intf, u16 cport_id) static void gb_connection_get(struct gb_connection *connection) { kref_get(&connection->kref); + + trace_gb_connection_get(connection); } static void gb_connection_put(struct gb_connection *connection) { + trace_gb_connection_put(connection); + kref_put(&connection->kref, gb_connection_kref_release); } @@ -93,6 +98,8 @@ static void gb_connection_kref_release(struct kref *kref) connection = container_of(kref, struct gb_connection, kref); + trace_gb_connection_release(connection); + kfree(connection); } @@ -204,6 +211,8 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, mutex_unlock(&gb_connection_mutex); + trace_gb_connection_create(connection); + return connection; err_free_connection: @@ -709,6 +718,9 @@ int gb_connection_enable(struct gb_connection *connection) goto out_unlock; ret = _gb_connection_enable(connection, true); + if (!ret) + trace_gb_connection_enable(connection); + out_unlock: mutex_unlock(&connection->mutex); @@ -731,6 +743,9 @@ int gb_connection_enable_tx(struct gb_connection *connection) goto out_unlock; ret = _gb_connection_enable(connection, false); + if (!ret) + trace_gb_connection_enable(connection); + out_unlock: mutex_unlock(&connection->mutex); @@ -751,6 +766,8 @@ void gb_connection_disable_rx(struct gb_connection *connection) gb_connection_flush_incoming_operations(connection, -ESHUTDOWN); spin_unlock_irq(&connection->lock); + trace_gb_connection_disable(connection); + out_unlock: mutex_unlock(&connection->mutex); } @@ -793,6 +810,8 @@ void gb_connection_disable(struct gb_connection *connection) connection->state = GB_CONNECTION_STATE_DISABLED; + trace_gb_connection_disable(connection); + /* control-connection tear down is deferred when mode switching */ if (!connection->mode_switch) { gb_connection_svc_connection_destroy(connection); @@ -822,6 +841,8 @@ void gb_connection_disable_forced(struct gb_connection *connection) gb_connection_svc_connection_destroy(connection); gb_connection_hd_cport_disable(connection); + trace_gb_connection_disable(connection); + out_unlock: mutex_unlock(&connection->mutex); } diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h index a1dc070..a075740 100644 --- a/drivers/staging/greybus/greybus_trace.h +++ b/drivers/staging/greybus/greybus_trace.h @@ -16,6 +16,7 @@ struct gb_message; struct gb_operation; +struct gb_connection; struct gb_bundle; struct gb_host_device; @@ -162,6 +163,80 @@ DEFINE_OPERATION_EVENT(gb_operation_put_active); #undef DEFINE_OPERATION_EVENT +DECLARE_EVENT_CLASS(gb_connection, + + TP_PROTO(struct gb_connection *connection), + + TP_ARGS(connection), + + TP_STRUCT__entry( + __field(int, hd_bus_id) + __field(u8, bundle_id) + /* name contains "hd_cport_id/intf_id:cport_id" */ + __dynamic_array(char, name, sizeof(connection->name)) + __field(enum gb_connection_state, state) + __field(unsigned long, flags) + ), + + TP_fast_assign( + __entry->hd_bus_id = connection->hd->bus_id; + __entry->bundle_id = connection->bundle ? + connection->bundle->id : BUNDLE_ID_NONE; + memcpy(__get_str(name), connection->name, + sizeof(connection->name)); + __entry->state = connection->state; + __entry->flags = connection->flags; + ), + + TP_printk("hd_bus_id=%d bundle_id=0x%02x name=\"%s\" state=%u flags=0x%lx", + __entry->hd_bus_id, __entry->bundle_id, __get_str(name), + (unsigned int)__entry->state, __entry->flags) +); + +#define DEFINE_CONNECTION_EVENT(name) \ + DEFINE_EVENT(gb_connection, name, \ + TP_PROTO(struct gb_connection *connection), \ + TP_ARGS(connection)) + +/* + * Occurs after a new connection is successfully created. + */ +DEFINE_CONNECTION_EVENT(gb_connection_create); + +/* + * Occurs when the last reference to a connection has been dropped, + * before its resources are freed. + */ +DEFINE_CONNECTION_EVENT(gb_connection_release); + +/* + * Occurs when a new reference to connection is added, currently + * only when a message over the connection is received. + */ +DEFINE_CONNECTION_EVENT(gb_connection_get); + +/* + * Occurs when a new reference to connection is dropped, after a + * a received message is handled, or when the connection is + * destroyed. + */ +DEFINE_CONNECTION_EVENT(gb_connection_put); + +/* + * Occurs when a request to enable a connection is made, either for + * transmit only, or for both transmit and receive. + */ +DEFINE_CONNECTION_EVENT(gb_connection_enable); + +/* + * Occurs when a request to disable a connection is made, either for + * receive only, or for both transmit and receive. Also occurs when + * a request to forcefully disable a connection is made. + */ +DEFINE_CONNECTION_EVENT(gb_connection_disable); + +#undef DEFINE_CONNECTION_EVENT + DECLARE_EVENT_CLASS(gb_bundle, TP_PROTO(struct gb_bundle *bundle), -- cgit v0.10.2 From 495787a792ac498843b25e5569597c24cd026f2b Mon Sep 17 00:00:00 2001 From: Alex Elder <elder@linaro.org> Date: Fri, 3 Jun 2016 15:55:38 -0500 Subject: greybus: tracing: add timing traces Bryan reports he used certain message traces to determine when time sync messages transit the boundary between the Greybus core and the host device. This patch adds two trace events--one a message event for outbound messages (because it indicates its operation and its destination), and one host device event for incoming messages (because message information isn't available as early as desired). These events are being created to allow the same sort of analysis of messages without having to store extra information for every message trace. (The next patch changes the information a message trace records.) Signed-off-by: Alex Elder <elder@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index d35e95a..7def600 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -81,6 +81,8 @@ void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id, { struct gb_connection *connection; + trace_gb_hd_in(hd); + connection = gb_connection_hd_find(hd, cport_id); if (!connection) { dev_err(&hd->dev, diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 68a8461..bdf5024 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -14,6 +14,7 @@ #include <asm/unaligned.h> #include "greybus.h" +#include "greybus_trace.h" #include "kernel_ver.h" #include "connection.h" @@ -467,6 +468,9 @@ static int message_send(struct gb_host_device *hd, u16 cport_id, message->buffer, buffer_size, cport_out_callback, message); urb->transfer_flags |= URB_ZERO_PACKET; + + trace_gb_message_submit(message); + retval = usb_submit_urb(urb, gfp_mask); if (retval) { dev_err(&udev->dev, "failed to submit out-urb: %d\n", retval); diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h index a075740..62f5803 100644 --- a/drivers/staging/greybus/greybus_trace.h +++ b/drivers/staging/greybus/greybus_trace.h @@ -88,6 +88,12 @@ DEFINE_MESSAGE_EVENT(gb_message_cancel_outgoing); */ DEFINE_MESSAGE_EVENT(gb_message_cancel_incoming); +/* + * Occurs in the host driver message_send() function just prior to + * handing off the data to be processed by hardware. + */ +DEFINE_MESSAGE_EVENT(gb_message_submit); + #undef DEFINE_MESSAGE_EVENT DECLARE_EVENT_CLASS(gb_operation, @@ -471,7 +477,7 @@ DEFINE_HD_EVENT(gb_hd_release); /* * Occurs after a new host device has been added, after the - * connection to its SVC has * been enabled. + * connection to its SVC has been enabled. */ DEFINE_HD_EVENT(gb_hd_add); @@ -481,6 +487,13 @@ DEFINE_HD_EVENT(gb_hd_add); */ DEFINE_HD_EVENT(gb_hd_del); +/* + * Occurs when a host device has passed received data to the Greybus + * core, after it has been determined it is destined for a valid + * CPort. + */ +DEFINE_HD_EVENT(gb_hd_in); + #undef DEFINE_HD_EVENT #endif /* _TRACE_GREYBUS_H */ diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index 12ac0b6..6d952ba 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -13,6 +13,9 @@ #include "greybus.h" #include "greybus_trace.h" +EXPORT_TRACEPOINT_SYMBOL_GPL(gb_message_submit); +EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_in); + static struct ida gb_hd_bus_id_map; int gb_hd_output(struct gb_host_device *hd, void *req, u16 size, u8 cmd, -- cgit v0.10.2 From 0790c09a3bc987a22749b0fb9b3effa313b1ece7 Mon Sep 17 00:00:00 2001 From: Alex Elder <elder@linaro.org> Date: Fri, 3 Jun 2016 15:55:39 -0500 Subject: greybus: tracing: fix message traces The original message trace events were defined long before the recent tracing updates. It records information that's not really directly related to a message. Change the information recorded and reported for message events to just be the content of the message header. Signed-off-by: Alex Elder <elder@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h index 62f5803..342f5ad 100644 --- a/drivers/staging/greybus/greybus_trace.h +++ b/drivers/staging/greybus/greybus_trace.h @@ -20,11 +20,6 @@ struct gb_connection; struct gb_bundle; struct gb_host_device; -#define gb_bundle_name(message) \ - (message->operation->connection->bundle ? \ - dev_name(&message->operation->connection->bundle->dev) : \ - dev_name(&message->operation->connection->hd->svc->dev)) - DECLARE_EVENT_CLASS(gb_message, TP_PROTO(struct gb_message *message), @@ -32,26 +27,23 @@ DECLARE_EVENT_CLASS(gb_message, TP_ARGS(message), TP_STRUCT__entry( - __string(name, gb_bundle_name(message)) - __field(u16, op_id) - __field(u16, intf_cport_id) - __field(u16, hd_cport_id) - __field(size_t, payload_size) + __field(u16, size) + __field(u16, operation_id) + __field(u8, type) + __field(u8, result) ), TP_fast_assign( - __assign_str(name, gb_bundle_name(message)) - __entry->op_id = message->operation->id; - __entry->intf_cport_id = - message->operation->connection->intf_cport_id; - __entry->hd_cport_id = - message->operation->connection->hd_cport_id; - __entry->payload_size = message->payload_size; + __entry->size = le16_to_cpu(message->header->size); + __entry->operation_id = + le16_to_cpu(message->header->operation_id); + __entry->type = message->header->type; + __entry->result = message->header->result; ), - TP_printk("greybus:%s op=%04x if_id=%u hd_id=%u l=%zu", - __get_str(name), __entry->op_id, __entry->intf_cport_id, - __entry->hd_cport_id, __entry->payload_size) + TP_printk("greybus: size=%hu operation_id=0x%04x type=0x%02x result=0x%02x", + __entry->size, __entry->operation_id, + __entry->type, __entry->result) ); #define DEFINE_MESSAGE_EVENT(name) \ -- cgit v0.10.2 From 02f1c12cca45ed684a268563919787f06877bef2 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Fri, 3 Jun 2016 17:45:29 +0530 Subject: greybus: audio: Report warning in case module is already removed Added warning message in find_gb_module(). This will help to identify invalid mixer control/widget modification triggered from above layer. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index e423e6d..dfe120b 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -47,6 +47,8 @@ static struct gbaudio_module_info *find_gb_module( } } mutex_unlock(&codec->lock); + dev_warn(codec->dev, "%s: module#%d missing in codec list\n", name, + dev_id); return NULL; } -- cgit v0.10.2 From 698282f659d7c657aad4e0a72ed33190f2332e04 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Fri, 3 Jun 2016 17:45:30 +0530 Subject: greybus: audio: Report DISCONNECT event after resource cleanup. Reporting DISCONNECT event immediately on module removal causes race condition while re-populating mixer controls by above HAL. The original intent was to avoid any (invalid) mixer control modification request from above layer. Ideally, it should report 'MODULE_NOT_READY' on module plug-out and DISCONNECT after resource cleanup. This would involve changes in GB Audio manager and HAL layer. Since we already have a plan to remove GB Audio manager, I'm making this change in GB codec driver to avoid any race condition. Also, codec driver already ensures mixer control modifcations for disconnected modules are not triggered to AP Bridge audio FW & reported invalid. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_module.c b/drivers/staging/greybus/audio_module.c index 53e84f5..95d2dda 100644 --- a/drivers/staging/greybus/audio_module.c +++ b/drivers/staging/greybus/audio_module.c @@ -363,10 +363,12 @@ static void gb_audio_disconnect(struct gb_bundle *bundle) struct gbaudio_data_connection *dai, *_dai; + /* cleanup module related resources first */ + gbaudio_unregister_module(gbmodule); + /* inform uevent to above layers */ gb_audio_manager_remove(gbmodule->manager_id); - gbaudio_unregister_module(gbmodule); gbaudio_tplg_release(gbmodule); kfree(gbmodule->topology); gbmodule->topology = NULL; -- cgit v0.10.2 From 970dc85bd95d931def5926ae81b5aa84ef14fb7c Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Sun, 5 Jun 2016 14:03:26 +0100 Subject: greybus: timesync: Add timesync core driver This patch adds the core timesync functionality. 0. arche-platform.c/arche-apb-ctrl.c Modifies the platform layer to hook the incoming TIME_SYNC signal up to the timesync strobe IRQ handler. If the arche-platform driver can't satisfy the request for the wake-detect line, it will return -EAGAIN and the calling work-queue must reschedule the attempt to get exclusive access to the wake-detect pin logic. A private data field is added to the arche-platform driver to enable passing of a timesync pointer to the ISR responsible for synchronizing time. 1. timesync.c A new file added which contains all of the logic associated with sending greybus commands to SVC, APBx or Interfaces to enable, disable and disseminate timing information. 2. timesync_platform.c Any platform/arch specific code goes into timesync_platform.c. Originally the idea was to keep the x86 and ARM arch dependencies in a timesync_platform_arch.c file - however with further refinement that's currently not necessary however just-in-case it becomes necessary to resuscitate arch or platform specific methods for accessing timer resources that access shouldn't be part of the core timesync.c logic and so for the moment we access these timer resources through a thin access layer in timesync_platform.c. Expect this to go away long term ideally. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Acked-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index f7fe4d5..981569d 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -10,7 +10,9 @@ greybus-y := core.o \ svc.o \ svc_watchdog.o \ bootrom.o \ - operation.o + operation.o \ + timesync.o \ + timesync_platform.o gb-gbphy-y := gbphy.o diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index a9d78a8..fce6a18 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -90,7 +90,7 @@ static int coldboot_seq(struct platform_device *pdev) } } - gpio_set_value(apb->boot_ret_gpio, 0); + apb_bootret_deassert(dev); /* On DB3 clock was not mandatory */ if (gpio_is_valid(apb->clk_en_gpio)) @@ -184,6 +184,20 @@ static void poweroff_seq(struct platform_device *pdev) /* TODO: May have to send an event to SVC about this exit */ } +void apb_bootret_assert(struct device *dev) +{ + struct arche_apb_ctrl_drvdata *apb = dev_get_drvdata(dev); + + gpio_set_value(apb->boot_ret_gpio, 1); +} + +void apb_bootret_deassert(struct device *dev) +{ + struct arche_apb_ctrl_drvdata *apb = dev_get_drvdata(dev); + + gpio_set_value(apb->boot_ret_gpio, 0); +} + int apb_ctrl_coldboot(struct device *dev) { return coldboot_seq(to_platform_device(dev)); diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index f47ea46..31c9524 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -22,6 +22,7 @@ #include <linux/suspend.h> #include <linux/time.h> #include "arche_platform.h" +#include "greybus.h" #include <linux/usb/usb3613.h> @@ -34,6 +35,7 @@ enum svc_wakedetect_state { WD_STATE_STANDBYBOOT_TRIG, /* As of now not used ?? */ WD_STATE_COLDBOOT_START, /* Cold boot process started */ WD_STATE_STANDBYBOOT_START, /* Not used */ + WD_STATE_TIMESYNC, }; struct arche_platform_drvdata { @@ -57,13 +59,27 @@ struct arche_platform_drvdata { int wake_detect_irq; spinlock_t wake_lock; /* Protect wake_detect_state */ struct mutex platform_state_mutex; /* Protect state */ + wait_queue_head_t wq; /* WQ for arche_pdata->state */ unsigned long wake_detect_start; struct notifier_block pm_notifier; struct device *dev; + struct gb_timesync_svc *timesync_svc_pdata; }; -/* Requires calling context to hold arche_pdata->spinlock */ +static int arche_apb_bootret_assert(struct device *dev, void *data) +{ + apb_bootret_assert(dev); + return 0; +} + +static int arche_apb_bootret_deassert(struct device *dev, void *data) +{ + apb_bootret_deassert(dev); + return 0; +} + +/* Requires calling context to hold arche_pdata->platform_state_mutex */ static void arche_platform_set_state(struct arche_platform_drvdata *arche_pdata, enum arche_platform_state state) { @@ -94,7 +110,8 @@ static void arche_platform_set_state(struct arche_platform_drvdata *arche_pdata, * satisfy the requested state-transition or -EINVAL for all other * state-transition requests. */ -int arche_platform_change_state(enum arche_platform_state state) +int arche_platform_change_state(enum arche_platform_state state, + struct gb_timesync_svc *timesync_svc_pdata) { struct arche_platform_drvdata *arche_pdata; struct platform_device *pdev; @@ -118,11 +135,6 @@ int arche_platform_change_state(enum arche_platform_state state) mutex_lock(&arche_pdata->platform_state_mutex); spin_lock_irqsave(&arche_pdata->wake_lock, flags); - if (arche_pdata->wake_detect_state != WD_STATE_IDLE) { - dev_err(arche_pdata->dev, - "driver busy with wake/detect line ops\n"); - goto exit; - } if (arche_pdata->state == state) { ret = 0; @@ -131,10 +143,27 @@ int arche_platform_change_state(enum arche_platform_state state) switch (state) { case ARCHE_PLATFORM_STATE_TIME_SYNC: - disable_irq(arche_pdata->wake_detect_irq); + if (arche_pdata->state != ARCHE_PLATFORM_STATE_ACTIVE) { + ret = -EINVAL; + goto exit; + } + if (arche_pdata->wake_detect_state != WD_STATE_IDLE) { + dev_err(arche_pdata->dev, + "driver busy with wake/detect line ops\n"); + goto exit; + } + device_for_each_child(arche_pdata->dev, NULL, + arche_apb_bootret_assert); + arche_pdata->wake_detect_state = WD_STATE_TIMESYNC; break; case ARCHE_PLATFORM_STATE_ACTIVE: - enable_irq(arche_pdata->wake_detect_irq); + if (arche_pdata->state != ARCHE_PLATFORM_STATE_TIME_SYNC) { + ret = -EINVAL; + goto exit; + } + device_for_each_child(arche_pdata->dev, NULL, + arche_apb_bootret_deassert); + arche_pdata->wake_detect_state = WD_STATE_IDLE; break; case ARCHE_PLATFORM_STATE_OFF: case ARCHE_PLATFORM_STATE_STANDBY: @@ -147,7 +176,11 @@ int arche_platform_change_state(enum arche_platform_state state) "invalid state transition request\n"); goto exit; } + arche_pdata->timesync_svc_pdata = timesync_svc_pdata; arche_platform_set_state(arche_pdata, state); + if (state == ARCHE_PLATFORM_STATE_ACTIVE) + wake_up(&arche_pdata->wq); + ret = 0; exit: spin_unlock_irqrestore(&arche_pdata->wake_lock, flags); @@ -252,6 +285,11 @@ static irqreturn_t arche_platform_wd_irq(int irq, void *devid) spin_lock_irqsave(&arche_pdata->wake_lock, flags); + if (arche_pdata->wake_detect_state == WD_STATE_TIMESYNC) { + gb_timesync_irq(arche_pdata->timesync_svc_pdata); + goto exit; + } + if (gpio_get_value(arche_pdata->wake_detect_gpio)) { /* wake/detect rising */ @@ -293,6 +331,7 @@ static irqreturn_t arche_platform_wd_irq(int irq, void *devid) } } +exit: spin_unlock_irqrestore(&arche_pdata->wake_lock, flags); return IRQ_HANDLED; @@ -402,7 +441,17 @@ static ssize_t state_store(struct device *dev, struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev); int ret = 0; +retry: mutex_lock(&arche_pdata->platform_state_mutex); + if (arche_pdata->state == ARCHE_PLATFORM_STATE_TIME_SYNC) { + mutex_unlock(&arche_pdata->platform_state_mutex); + ret = wait_event_interruptible( + arche_pdata->wq, + arche_pdata->state != ARCHE_PLATFORM_STATE_TIME_SYNC); + if (ret) + return ret; + goto retry; + } if (sysfs_streq(buf, "off")) { if (arche_pdata->state == ARCHE_PLATFORM_STATE_OFF) @@ -610,6 +659,7 @@ static int arche_platform_probe(struct platform_device *pdev) spin_lock_init(&arche_pdata->wake_lock); mutex_init(&arche_pdata->platform_state_mutex); + init_waitqueue_head(&arche_pdata->wq); arche_pdata->wake_detect_irq = gpio_to_irq(arche_pdata->wake_detect_gpio); @@ -653,6 +703,9 @@ static int arche_platform_probe(struct platform_device *pdev) goto err_populate; } + /* Register callback pointer */ + arche_platform_change_state_cb = arche_platform_change_state; + dev_info(dev, "Device registered successfully\n"); return 0; diff --git a/drivers/staging/greybus/arche_platform.h b/drivers/staging/greybus/arche_platform.h index 0f2d292..bd12345 100644 --- a/drivers/staging/greybus/arche_platform.h +++ b/drivers/staging/greybus/arche_platform.h @@ -10,6 +10,8 @@ #ifndef __ARCHE_PLATFORM_H #define __ARCHE_PLATFORM_H +#include "timesync.h" + enum arche_platform_state { ARCHE_PLATFORM_STATE_OFF, ARCHE_PLATFORM_STATE_ACTIVE, @@ -18,8 +20,11 @@ enum arche_platform_state { ARCHE_PLATFORM_STATE_TIME_SYNC, }; -int arche_platform_change_state(enum arche_platform_state state); +int arche_platform_change_state(enum arche_platform_state state, + struct gb_timesync_svc *pdata); +extern int (*arche_platform_change_state_cb)(enum arche_platform_state state, + struct gb_timesync_svc *pdata); int __init arche_apb_init(void); void __exit arche_apb_exit(void); @@ -28,5 +33,7 @@ int apb_ctrl_coldboot(struct device *dev); int apb_ctrl_fw_flashing(struct device *dev); int apb_ctrl_standby_boot(struct device *dev); void apb_ctrl_poweroff(struct device *dev); +void apb_bootret_assert(struct device *dev); +void apb_bootret_deassert(struct device *dev); #endif /* __ARCHE_PLATFORM_H */ diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index e0b194c..154dfd1 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -33,7 +33,7 @@ #include "bundle.h" #include "connection.h" #include "operation.h" - +#include "timesync.h" /* Matches up with the Greybus Protocol specification document */ #define GREYBUS_VERSION_MAJOR 0x00 diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 577d15f..3eb8754 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -865,6 +865,61 @@ void gb_interface_disable(struct gb_interface *intf) intf->enabled = false; } +/* + * Enable TimeSync on an Interface control connection. + * + * Locking: Takes and releases the interface mutex. + */ +int gb_interface_timesync_enable(struct gb_interface *intf, u8 count, + u64 frame_time, u32 strobe_delay, u32 refclk) +{ + int ret = -ENODEV; + + mutex_lock(&intf->mutex); + if (intf->enabled) { + ret = gb_control_timesync_enable(intf->control, count, + frame_time, strobe_delay, + refclk); + } + mutex_unlock(&intf->mutex); + return ret; +} + +/* + * Disable TimeSync on an Interface control connection. + * + * Locking: Takes and releases the interface mutex. + */ +int gb_interface_timesync_disable(struct gb_interface *intf) +{ + int ret = -ENODEV; + + mutex_lock(&intf->mutex); + if (intf->enabled) + ret = gb_control_timesync_disable(intf->control); + mutex_unlock(&intf->mutex); + return ret; +} + +/* + * Transmit the Authoritative FrameTime via an Interface control connection. + * + * Locking: Takes and releases the interface mutex. + */ +int gb_interface_timesync_authoritative(struct gb_interface *intf, + u64 *frame_time) +{ + int ret = -ENODEV; + + mutex_lock(&intf->mutex); + if (intf->enabled) { + ret = gb_control_timesync_authoritative(intf->control, + frame_time); + } + mutex_unlock(&intf->mutex); + return ret; +} + /* Register an interface. */ int gb_interface_add(struct gb_interface *intf) { diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 603f146..8796c55 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -58,6 +58,11 @@ int gb_interface_activate(struct gb_interface *intf); void gb_interface_deactivate(struct gb_interface *intf); int gb_interface_enable(struct gb_interface *intf); void gb_interface_disable(struct gb_interface *intf); +int gb_interface_timesync_enable(struct gb_interface *intf, u8 count, + u64 frame_time, u32 strobe_delay, u32 refclk); +int gb_interface_timesync_authoritative(struct gb_interface *intf, + u64 *frame_time); +int gb_interface_timesync_disable(struct gb_interface *intf); int gb_interface_add(struct gb_interface *intf); void gb_interface_del(struct gb_interface *intf); void gb_interface_put(struct gb_interface *intf); diff --git a/drivers/staging/greybus/timesync.c b/drivers/staging/greybus/timesync.c new file mode 100644 index 0000000..260b670 --- /dev/null +++ b/drivers/staging/greybus/timesync.c @@ -0,0 +1,1021 @@ +/* + * TimeSync API driver. + * + * Copyright 2016 Google Inc. + * Copyright 2016 Linaro Ltd. + * + * Released under the GPLv2 only. + */ +#include <linux/debugfs.h> +#include "greybus.h" +#include "timesync.h" + +/* + * Minimum inter-strobe value of one millisecond is chosen because it + * just-about fits the common definition of a jiffy. + * + * Maximum value OTOH is constrained by the number of bits the SVC can fit + * into a 16 bit up-counter. The SVC configures the timer in microseconds + * so the maximum allowable value is 65535 microseconds. We clip that value + * to 10000 microseconds for the sake of using nice round base 10 numbers + * and since right-now there's no imaginable use-case requiring anything + * other than a one millisecond inter-strobe time, let alone something + * higher than ten milliseconds. + */ +#define GB_TIMESYNC_STROBE_DELAY_US 1000 +#define GB_TIMESYNC_DEFAULT_OFFSET_US 1000 + +/* Work queue timers long, short and SVC strobe timeout */ +#define GB_TIMESYNC_DELAYED_WORK_LONG msecs_to_jiffies(1000) +#define GB_TIMESYNC_DELAYED_WORK_SHORT msecs_to_jiffies(1) +#define GB_TIMESYNC_MAX_WAIT_SVC msecs_to_jiffies(5000) + +/* Reported nanoseconds per clock */ +static u64 gb_timesync_ns_per_clock; + +/* Reported clock rate */ +static unsigned long gb_timesync_clock_rate; + +/* Workqueue */ +static void gb_timesync_worker(struct work_struct *work); + +/* List of SVCs with one FrameTime per SVC */ +static LIST_HEAD(gb_timesync_svc_list); + +/* Synchronize parallel contexts accessing a valid timesync_svc pointer */ +static DEFINE_MUTEX(gb_timesync_svc_list_mutex); + +struct gb_timesync_svc { + struct list_head list; + struct list_head interface_list; + struct gb_svc *svc; + struct gb_timesync_host_device *timesync_hd; + + spinlock_t spinlock; /* Per SVC spinlock to sync with ISR */ + struct mutex mutex; /* Per SVC mutex for regular synchronization */ + + struct dentry *frame_time_dentry; + struct workqueue_struct *work_queue; + wait_queue_head_t wait_queue; + struct delayed_work delayed_work; + + /* The current local FrameTime */ + u64 frame_time_offset; + u64 strobe_time[GB_TIMESYNC_MAX_STROBES]; + + /* The SVC FrameTime and relative AP FrameTime @ last TIMESYNC_PING */ + u64 svc_ping_frame_time; + u64 ap_ping_frame_time; + + /* Transitory settings */ + u32 strobe_mask; + bool offset_down; + bool print_ping; + bool capture_ping; + int strobe; + + /* Current state */ + int state; +}; + +struct gb_timesync_host_device { + struct list_head list; + struct gb_host_device *hd; + u64 ping_frame_time; +}; + +struct gb_timesync_interface { + struct list_head list; + struct gb_interface *interface; + u64 ping_frame_time; +}; + +enum gb_timesync_state { + GB_TIMESYNC_STATE_INVALID = 0, + GB_TIMESYNC_STATE_INACTIVE = 1, + GB_TIMESYNC_STATE_INIT = 2, + GB_TIMESYNC_STATE_WAIT_SVC = 3, + GB_TIMESYNC_STATE_AUTHORITATIVE = 4, + GB_TIMESYNC_STATE_PING = 5, + GB_TIMESYNC_STATE_ACTIVE = 6, +}; + +static u64 gb_timesync_adjust_count(struct gb_timesync_svc *timesync_svc, + u64 counts) +{ + if (timesync_svc->offset_down) + return counts - timesync_svc->frame_time_offset; + else + return counts + timesync_svc->frame_time_offset; +} + +/* + * This function provides the authoritative FrameTime to a calling function. It + * is designed to be lockless and should remain that way the caller is assumed + * to be state-aware. + */ +static u64 __gb_timesync_get_frame_time(struct gb_timesync_svc *timesync_svc) +{ + u64 clocks = gb_timesync_platform_get_counter(); + + return gb_timesync_adjust_count(timesync_svc, clocks); +} + +static void gb_timesync_schedule_svc_timeout(struct gb_timesync_svc + *timesync_svc) +{ + queue_delayed_work(timesync_svc->work_queue, + ×ync_svc->delayed_work, + GB_TIMESYNC_MAX_WAIT_SVC); +} + +static void gb_timesync_set_state(struct gb_timesync_svc *timesync_svc, + int state) +{ + switch (state) { + case GB_TIMESYNC_STATE_INVALID: + timesync_svc->state = state; + wake_up(×ync_svc->wait_queue); + break; + case GB_TIMESYNC_STATE_INACTIVE: + if (timesync_svc->state != GB_TIMESYNC_STATE_INIT) { + timesync_svc->state = state; + wake_up(×ync_svc->wait_queue); + } + break; + case GB_TIMESYNC_STATE_INIT: + if (timesync_svc->state != GB_TIMESYNC_STATE_INVALID) { + timesync_svc->strobe = 0; + timesync_svc->frame_time_offset = 0; + timesync_svc->state = state; + cancel_delayed_work(×ync_svc->delayed_work); + queue_delayed_work(timesync_svc->work_queue, + ×ync_svc->delayed_work, + GB_TIMESYNC_DELAYED_WORK_LONG); + } + break; + case GB_TIMESYNC_STATE_WAIT_SVC: + if (timesync_svc->state == GB_TIMESYNC_STATE_INIT) + timesync_svc->state = state; + break; + case GB_TIMESYNC_STATE_AUTHORITATIVE: + if (timesync_svc->state == GB_TIMESYNC_STATE_WAIT_SVC) { + timesync_svc->state = state; + cancel_delayed_work(×ync_svc->delayed_work); + queue_delayed_work(timesync_svc->work_queue, + ×ync_svc->delayed_work, 0); + } + break; + case GB_TIMESYNC_STATE_PING: + if (timesync_svc->state == GB_TIMESYNC_STATE_ACTIVE) { + timesync_svc->state = state; + queue_delayed_work(timesync_svc->work_queue, + ×ync_svc->delayed_work, + GB_TIMESYNC_DELAYED_WORK_SHORT); + } + break; + case GB_TIMESYNC_STATE_ACTIVE: + if (timesync_svc->state == GB_TIMESYNC_STATE_AUTHORITATIVE || + timesync_svc->state == GB_TIMESYNC_STATE_PING) { + timesync_svc->state = state; + wake_up(×ync_svc->wait_queue); + } + break; + } + + if (WARN_ON(timesync_svc->state != state)) { + pr_err("Invalid state transition %d=>%d\n", + timesync_svc->state, state); + } +} + +static void gb_timesync_set_state_atomic(struct gb_timesync_svc *timesync_svc, + int state) +{ + unsigned long flags; + + spin_lock_irqsave(×ync_svc->spinlock, flags); + gb_timesync_set_state(timesync_svc, state); + spin_unlock_irqrestore(×ync_svc->spinlock, flags); +} + +static u64 gb_timesync_diff(u64 x, u64 y) +{ + if (x > y) + return x - y; + else + return y - x; +} + +static void gb_timesync_adjust_to_svc(struct gb_timesync_svc *svc, + u64 svc_frame_time, u64 ap_frame_time) +{ + if (svc_frame_time > ap_frame_time) { + svc->frame_time_offset = svc_frame_time - ap_frame_time; + svc->offset_down = false; + } else { + svc->frame_time_offset = ap_frame_time - svc_frame_time; + svc->offset_down = true; + } +} + +/* + * Find the two pulses that best-match our expected inter-strobe gap and + * then calculate the difference between the SVC time at the second pulse + * to the local time at the second pulse. + */ +static void gb_timesync_collate_frame_time(struct gb_timesync_svc *timesync_svc, + u64 *frame_time) +{ + int i = 0; + u64 delta; + u64 strobe_delay_ns = GB_TIMESYNC_STROBE_DELAY_US * NSEC_PER_USEC; + u64 least = 0; + + for (i = 1; i < GB_TIMESYNC_MAX_STROBES; i++) { + delta = timesync_svc->strobe_time[i] - + timesync_svc->strobe_time[i - 1]; + delta *= gb_timesync_ns_per_clock; + delta = gb_timesync_diff(delta, strobe_delay_ns); + + if (!least || delta < least) { + least = delta; + gb_timesync_adjust_to_svc(timesync_svc, frame_time[i], + timesync_svc->strobe_time[i]); + pr_debug("adjust %s local %llu svc %llu delta %llu\n", + timesync_svc->offset_down ? "down" : "up", + timesync_svc->strobe_time[i], frame_time[i], + delta); + } + } +} + +static void gb_timesync_teardown(struct gb_timesync_svc *timesync_svc) +{ + struct gb_timesync_interface *timesync_interface; + struct gb_svc *svc = timesync_svc->svc; + struct gb_interface *interface; + struct gb_host_device *hd; + int ret; + + list_for_each_entry(timesync_interface, + ×ync_svc->interface_list, list) { + interface = timesync_interface->interface; + ret = gb_interface_timesync_disable(interface); + if (ret) { + dev_err(&interface->dev, + "interface timesync_disable %d\n", ret); + } + } + + hd = timesync_svc->timesync_hd->hd; + ret = hd->driver->timesync_disable(hd); + if (ret < 0) { + dev_err(&hd->dev, "host timesync_disable %d\n", + ret); + } + + gb_svc_timesync_wake_pins_release(svc); + gb_svc_timesync_disable(svc); + gb_timesync_platform_unlock_bus(); + + gb_timesync_set_state_atomic(timesync_svc, GB_TIMESYNC_STATE_INACTIVE); +} + +static void gb_timesync_platform_lock_bus_fail(struct gb_timesync_svc + *timesync_svc, int ret) +{ + if (ret == -EAGAIN) { + gb_timesync_set_state(timesync_svc, timesync_svc->state); + } else { + pr_err("Failed to lock timesync bus %d\n", ret); + gb_timesync_set_state(timesync_svc, GB_TIMESYNC_STATE_INACTIVE); + } +} + +static void gb_timesync_enable(struct gb_timesync_svc *timesync_svc) +{ + struct gb_svc *svc = timesync_svc->svc; + struct gb_host_device *hd; + struct gb_timesync_interface *timesync_interface; + struct gb_interface *interface; + u64 init_frame_time; + unsigned long clock_rate = gb_timesync_clock_rate; + int ret; + + /* + * Get access to the wake pins in the AP and SVC + * Release these pins either in gb_timesync_teardown() or in + * gb_timesync_authoritative() + */ + ret = gb_timesync_platform_lock_bus(timesync_svc); + if (ret < 0) { + gb_timesync_platform_lock_bus_fail(timesync_svc, ret); + return; + } + ret = gb_svc_timesync_wake_pins_acquire(svc, timesync_svc->strobe_mask); + if (ret) { + dev_err(&svc->dev, + "gb_svc_timesync_wake_pins_acquire %d\n", ret); + gb_timesync_teardown(timesync_svc); + return; + } + + /* Choose an initial time in the future */ + init_frame_time = __gb_timesync_get_frame_time(timesync_svc) + 100000UL; + + /* Send enable command to all relevant participants */ + list_for_each_entry(timesync_interface, ×ync_svc->interface_list, + list) { + interface = timesync_interface->interface; + ret = gb_interface_timesync_enable(interface, + GB_TIMESYNC_MAX_STROBES, + init_frame_time, + GB_TIMESYNC_STROBE_DELAY_US, + clock_rate); + if (ret) { + dev_err(&interface->dev, + "interface timesync_enable %d\n", ret); + } + } + + hd = timesync_svc->timesync_hd->hd; + ret = hd->driver->timesync_enable(hd, GB_TIMESYNC_MAX_STROBES, + init_frame_time, + GB_TIMESYNC_STROBE_DELAY_US, + clock_rate); + if (ret < 0) { + dev_err(&hd->dev, "host timesync_enable %d\n", + ret); + } + + gb_timesync_set_state_atomic(timesync_svc, GB_TIMESYNC_STATE_WAIT_SVC); + ret = gb_svc_timesync_enable(svc, GB_TIMESYNC_MAX_STROBES, + init_frame_time, + GB_TIMESYNC_STROBE_DELAY_US, + clock_rate); + if (ret) { + dev_err(&svc->dev, + "gb_svc_timesync_enable %d\n", ret); + gb_timesync_teardown(timesync_svc); + return; + } + + /* Schedule a timeout waiting for SVC to complete strobing */ + gb_timesync_schedule_svc_timeout(timesync_svc); +} + +static void gb_timesync_authoritative(struct gb_timesync_svc *timesync_svc) +{ + struct gb_svc *svc = timesync_svc->svc; + struct gb_host_device *hd; + struct gb_timesync_interface *timesync_interface; + struct gb_interface *interface; + u64 svc_frame_time[GB_TIMESYNC_MAX_STROBES]; + int ret; + + /* Get authoritative time from SVC and adjust local clock */ + ret = gb_svc_timesync_authoritative(svc, svc_frame_time); + if (ret) { + dev_err(&svc->dev, + "gb_svc_timesync_authoritative %d\n", ret); + gb_timesync_teardown(timesync_svc); + return; + } + gb_timesync_collate_frame_time(timesync_svc, svc_frame_time); + + /* Transmit authoritative time to downstream slaves */ + hd = timesync_svc->timesync_hd->hd; + ret = hd->driver->timesync_authoritative(hd, svc_frame_time); + if (ret < 0) + dev_err(&hd->dev, "host timesync_authoritative %d\n", ret); + + list_for_each_entry(timesync_interface, + ×ync_svc->interface_list, list) { + interface = timesync_interface->interface; + ret = gb_interface_timesync_authoritative( + interface, + svc_frame_time); + if (ret) { + dev_err(&interface->dev, + "interface timesync_authoritative %d\n", ret); + } + } + + /* Release wake pins */ + gb_svc_timesync_wake_pins_release(svc); + gb_timesync_platform_unlock_bus(); + + /* Transition to state ACTIVE */ + gb_timesync_set_state_atomic(timesync_svc, GB_TIMESYNC_STATE_ACTIVE); + + /* Schedule a ping to verify the synchronized system time */ + timesync_svc->print_ping = true; + gb_timesync_set_state_atomic(timesync_svc, GB_TIMESYNC_STATE_PING); +} + +static size_t gb_timesync_log_frame_time(struct gb_timesync_svc *timesync_svc, + char *buf, size_t buflen) +{ + struct gb_svc *svc = timesync_svc->svc; + struct gb_host_device *hd; + struct gb_timesync_interface *timesync_interface; + struct gb_interface *interface; + unsigned int len; + size_t off; + + /* AP/SVC */ + memset(buf, 0x00, buflen); + off = snprintf(buf, buflen, "timesync: ping-time ap=%llu %s=%llu ", + timesync_svc->ap_ping_frame_time, dev_name(&svc->dev), + timesync_svc->svc_ping_frame_time); + len = buflen - off; + + /* APB/GPB */ + if (len < buflen) { + hd = timesync_svc->timesync_hd->hd; + off += snprintf(&buf[off], len, "%s=%llu ", dev_name(&hd->dev), + timesync_svc->timesync_hd->ping_frame_time); + len = buflen - off; + } + + list_for_each_entry(timesync_interface, + ×ync_svc->interface_list, list) { + if (len < buflen) { + interface = timesync_interface->interface; + off += snprintf(&buf[off], len, "%s=%llu ", + dev_name(&interface->dev), + timesync_interface->ping_frame_time); + len = buflen - off; + } + } + if (len < buflen) + off += snprintf(&buf[off], len, "\n"); + return off; +} + +/* + * Send an SVC initiated wake 'ping' to each TimeSync participant. + * Get the FrameTime from each participant associated with the wake + * ping. + */ +static void gb_timesync_ping(struct gb_timesync_svc *timesync_svc) +{ + struct gb_svc *svc = timesync_svc->svc; + struct gb_host_device *hd; + struct gb_timesync_interface *timesync_interface; + struct gb_control *control; + u64 *ping_frame_time; + int ret; + + /* Get access to the wake pins in the AP and SVC */ + ret = gb_timesync_platform_lock_bus(timesync_svc); + if (ret < 0) { + gb_timesync_platform_lock_bus_fail(timesync_svc, ret); + return; + } + ret = gb_svc_timesync_wake_pins_acquire(svc, timesync_svc->strobe_mask); + if (ret) { + dev_err(&svc->dev, + "gb_svc_timesync_wake_pins_acquire %d\n", ret); + gb_timesync_teardown(timesync_svc); + return; + } + + /* Have SVC generate a timesync ping */ + timesync_svc->capture_ping = true; + ret = gb_svc_timesync_ping(svc, ×ync_svc->svc_ping_frame_time); + timesync_svc->capture_ping = false; + if (ret) { + dev_err(&svc->dev, + "gb_svc_timesync_ping %d\n", ret); + gb_timesync_teardown(timesync_svc); + return; + } + + /* Get the ping FrameTime from each APB/GPB */ + hd = timesync_svc->timesync_hd->hd; + ret = hd->driver->timesync_get_last_event(hd, + ×ync_svc->timesync_hd->ping_frame_time); + if (ret) + dev_err(&hd->dev, "host timesync_get_last_event %d\n", ret); + + list_for_each_entry(timesync_interface, + ×ync_svc->interface_list, list) { + control = timesync_interface->interface->control; + ping_frame_time = ×ync_interface->ping_frame_time; + ret = gb_control_timesync_get_last_event(control, + ping_frame_time); + if (ret) { + dev_err(×ync_interface->interface->dev, + "gb_control_timesync_get_last_event %d\n", ret); + } + } + + /* Ping success - move to timesync active */ + gb_svc_timesync_wake_pins_release(svc); + gb_timesync_platform_unlock_bus(); + gb_timesync_set_state_atomic(timesync_svc, GB_TIMESYNC_STATE_ACTIVE); +} + +static void gb_timesync_log_ping_time(struct gb_timesync_svc *timesync_svc) +{ + char *buf; + + if (!timesync_svc->print_ping) + return; + + buf = kzalloc(PAGE_SIZE, GFP_KERNEL); + if (buf) { + gb_timesync_log_frame_time(timesync_svc, buf, PAGE_SIZE); + pr_info("%s", buf); + kfree(buf); + } +} + +/* + * Perform the actual work of scheduled TimeSync logic. + */ +static void gb_timesync_worker(struct work_struct *work) +{ + struct delayed_work *delayed_work = to_delayed_work(work); + struct gb_timesync_svc *timesync_svc = + container_of(delayed_work, struct gb_timesync_svc, delayed_work); + + mutex_lock(×ync_svc->mutex); + + switch (timesync_svc->state) { + case GB_TIMESYNC_STATE_INIT: + gb_timesync_enable(timesync_svc); + break; + + case GB_TIMESYNC_STATE_WAIT_SVC: + dev_err(×ync_svc->svc->dev, + "timeout SVC strobe completion\n"); + gb_timesync_teardown(timesync_svc); + break; + + case GB_TIMESYNC_STATE_AUTHORITATIVE: + gb_timesync_authoritative(timesync_svc); + break; + + case GB_TIMESYNC_STATE_PING: + gb_timesync_ping(timesync_svc); + gb_timesync_log_ping_time(timesync_svc); + break; + + default: + pr_err("Invalid state %d for delayed work\n", + timesync_svc->state); + break; + } + + mutex_unlock(×ync_svc->mutex); +} + +/* + * Schedule a new TimeSync INIT or PING operation serialized w/r to + * gb_timesync_worker(). + */ +static int gb_timesync_schedule(struct gb_timesync_svc *timesync_svc, int state) +{ + int ret = 0; + + if (state != GB_TIMESYNC_STATE_INIT && state != GB_TIMESYNC_STATE_PING) + return -EINVAL; + + mutex_lock(×ync_svc->mutex); + if (timesync_svc->state == GB_TIMESYNC_STATE_INACTIVE || + timesync_svc->state == GB_TIMESYNC_STATE_ACTIVE) { + gb_timesync_set_state_atomic(timesync_svc, state); + } else { + ret = -ENODEV; + } + mutex_unlock(×ync_svc->mutex); + return ret; +} + +static int __gb_timesync_schedule_synchronous( + struct gb_timesync_svc *timesync_svc, int state) +{ + unsigned long flags; + int ret; + + ret = gb_timesync_schedule(timesync_svc, state); + if (ret) + return ret; + + ret = wait_event_interruptible(timesync_svc->wait_queue, + (timesync_svc->state == GB_TIMESYNC_STATE_ACTIVE || + timesync_svc->state == GB_TIMESYNC_STATE_INACTIVE || + timesync_svc->state == GB_TIMESYNC_STATE_INVALID)); + if (ret) + return ret; + + mutex_lock(×ync_svc->mutex); + spin_lock_irqsave(×ync_svc->spinlock, flags); + + switch (timesync_svc->state) { + case GB_TIMESYNC_STATE_INVALID: + case GB_TIMESYNC_STATE_INACTIVE: + ret = -ENODEV; + break; + case GB_TIMESYNC_STATE_INIT: + case GB_TIMESYNC_STATE_WAIT_SVC: + case GB_TIMESYNC_STATE_AUTHORITATIVE: + case GB_TIMESYNC_STATE_PING: + ret = -EAGAIN; + break; + case GB_TIMESYNC_STATE_ACTIVE: + ret = 0; + break; + } + + spin_unlock_irqrestore(×ync_svc->spinlock, flags); + mutex_unlock(×ync_svc->mutex); + + return ret; +} + +static struct gb_timesync_svc *gb_timesync_find_timesync_svc( + struct gb_host_device *hd) +{ + struct gb_timesync_svc *timesync_svc; + + list_for_each_entry(timesync_svc, &gb_timesync_svc_list, list) { + if (timesync_svc->svc == hd->svc) + return timesync_svc; + } + return NULL; +} + +static struct gb_timesync_interface *gb_timesync_find_timesync_interface( + struct gb_timesync_svc *timesync_svc, + struct gb_interface *interface) +{ + struct gb_timesync_interface *timesync_interface; + + list_for_each_entry(timesync_interface, ×ync_svc->interface_list, list) { + if (timesync_interface->interface == interface) + return timesync_interface; + } + return NULL; +} + +int gb_timesync_schedule_synchronous(struct gb_interface *interface) +{ + int ret; + struct gb_timesync_svc *timesync_svc; + + if (!(interface->features & GREYBUS_INTERFACE_FEATURE_TIMESYNC)) + return 0; + + mutex_lock(&gb_timesync_svc_list_mutex); + timesync_svc = gb_timesync_find_timesync_svc(interface->hd); + if (!timesync_svc) { + ret = -ENODEV; + goto done; + } + + ret = __gb_timesync_schedule_synchronous(timesync_svc, + GB_TIMESYNC_STATE_INIT); +done: + mutex_unlock(&gb_timesync_svc_list_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(gb_timesync_schedule_synchronous); + +void gb_timesync_schedule_asynchronous(struct gb_interface *interface) +{ + struct gb_timesync_svc *timesync_svc; + + if (!(interface->features & GREYBUS_INTERFACE_FEATURE_TIMESYNC)) + return; + + mutex_lock(&gb_timesync_svc_list_mutex); + timesync_svc = gb_timesync_find_timesync_svc(interface->hd); + if (!timesync_svc) + goto done; + + gb_timesync_schedule(timesync_svc, GB_TIMESYNC_STATE_INIT); +done: + mutex_unlock(&gb_timesync_svc_list_mutex); + return; +} +EXPORT_SYMBOL_GPL(gb_timesync_schedule_asynchronous); + +static ssize_t gb_timesync_ping_read(struct file *file, char __user *buf, + size_t len, loff_t *offset) +{ + struct gb_timesync_svc *timesync_svc = file->f_inode->i_private; + char *pbuf; + ssize_t ret = 0; + + mutex_lock(&gb_timesync_svc_list_mutex); + mutex_lock(×ync_svc->mutex); + if (list_empty(×ync_svc->interface_list)) + ret = -ENODEV; + timesync_svc->print_ping = false; + mutex_unlock(×ync_svc->mutex); + if (ret) + goto done; + + ret = __gb_timesync_schedule_synchronous(timesync_svc, + GB_TIMESYNC_STATE_PING); + if (ret) + goto done; + + pbuf = kzalloc(PAGE_SIZE, GFP_KERNEL); + if (!pbuf) { + ret = -ENOMEM; + goto done; + } + + ret = gb_timesync_log_frame_time(timesync_svc, pbuf, PAGE_SIZE); + if (ret > 0) + ret = simple_read_from_buffer(buf, len, offset, pbuf, ret); + kfree(pbuf); +done: + mutex_unlock(&gb_timesync_svc_list_mutex); + return ret; +} + +static const struct file_operations gb_timesync_debugfs_ops = { + .read = gb_timesync_ping_read, +}; + +static int gb_timesync_hd_add(struct gb_timesync_svc *timesync_svc, + struct gb_host_device *hd) +{ + struct gb_timesync_host_device *timesync_hd; + + timesync_hd = kzalloc(sizeof(*timesync_hd), GFP_KERNEL); + if (!timesync_hd) + return -ENOMEM; + + WARN_ON(timesync_svc->timesync_hd); + timesync_hd->hd = hd; + timesync_svc->timesync_hd = timesync_hd; + + return 0; +} + +static void gb_timesync_hd_remove(struct gb_timesync_svc *timesync_svc, + struct gb_host_device *hd) +{ + if (timesync_svc->timesync_hd->hd == hd) { + kfree(timesync_svc->timesync_hd); + timesync_svc->timesync_hd = NULL; + return; + } + WARN_ON(1); +} + +int gb_timesync_svc_add(struct gb_svc *svc) +{ + struct gb_timesync_svc *timesync_svc; + int ret; + + timesync_svc = kzalloc(sizeof(*timesync_svc), GFP_KERNEL); + if (!timesync_svc) + return -ENOMEM; + + timesync_svc->work_queue = + create_singlethread_workqueue("gb-timesync-work_queue"); + + if (!timesync_svc->work_queue) { + kfree(timesync_svc); + return -ENOMEM; + } + + mutex_lock(&gb_timesync_svc_list_mutex); + INIT_LIST_HEAD(×ync_svc->interface_list); + INIT_DELAYED_WORK(×ync_svc->delayed_work, gb_timesync_worker); + mutex_init(×ync_svc->mutex); + spin_lock_init(×ync_svc->spinlock); + init_waitqueue_head(×ync_svc->wait_queue); + + timesync_svc->svc = svc; + timesync_svc->frame_time_offset = 0; + timesync_svc->capture_ping = false; + gb_timesync_set_state_atomic(timesync_svc, GB_TIMESYNC_STATE_INACTIVE); + timesync_svc->frame_time_dentry = + debugfs_create_file("frame-time", S_IRUGO, svc->debugfs_dentry, + timesync_svc, &gb_timesync_debugfs_ops); + list_add(×ync_svc->list, &gb_timesync_svc_list); + ret = gb_timesync_hd_add(timesync_svc, svc->hd); + if (ret) { + list_del(×ync_svc->list); + debugfs_remove(timesync_svc->frame_time_dentry); + destroy_workqueue(timesync_svc->work_queue); + kfree(timesync_svc); + } + mutex_unlock(&gb_timesync_svc_list_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(gb_timesync_svc_add); + +void gb_timesync_svc_remove(struct gb_svc *svc) +{ + struct gb_timesync_svc *timesync_svc; + struct gb_timesync_interface *timesync_interface; + struct gb_timesync_interface *next; + + mutex_lock(&gb_timesync_svc_list_mutex); + timesync_svc = gb_timesync_find_timesync_svc(svc->hd); + if (!timesync_svc) + goto done; + + mutex_lock(×ync_svc->mutex); + + gb_timesync_teardown(timesync_svc); + + gb_timesync_hd_remove(timesync_svc, svc->hd); + list_for_each_entry_safe(timesync_interface, next, + ×ync_svc->interface_list, list) { + list_del(×ync_interface->list); + kfree(timesync_interface); + } + gb_timesync_set_state_atomic(timesync_svc, GB_TIMESYNC_STATE_INVALID); + debugfs_remove(timesync_svc->frame_time_dentry); + cancel_delayed_work_sync(×ync_svc->delayed_work); + destroy_workqueue(timesync_svc->work_queue); + list_del(×ync_svc->list); + + mutex_unlock(×ync_svc->mutex); + + kfree(timesync_svc); +done: + mutex_unlock(&gb_timesync_svc_list_mutex); +} +EXPORT_SYMBOL_GPL(gb_timesync_svc_remove); + +/* + * Add a Greybus Interface to the set of TimeSync Interfaces. + */ +int gb_timesync_interface_add(struct gb_interface *interface) +{ + struct gb_timesync_svc *timesync_svc; + struct gb_timesync_interface *timesync_interface; + int ret = 0; + + if (!(interface->features & GREYBUS_INTERFACE_FEATURE_TIMESYNC)) + return 0; + + mutex_lock(&gb_timesync_svc_list_mutex); + timesync_svc = gb_timesync_find_timesync_svc(interface->hd); + if (!timesync_svc) { + ret = -ENODEV; + goto done; + } + + timesync_interface = kzalloc(sizeof(*timesync_interface), GFP_KERNEL); + if (!timesync_interface) { + ret = -ENOMEM; + goto done; + } + + mutex_lock(×ync_svc->mutex); + timesync_interface->interface = interface; + list_add(×ync_interface->list, ×ync_svc->interface_list); + timesync_svc->strobe_mask |= 1 << interface->interface_id; + mutex_unlock(×ync_svc->mutex); + +done: + mutex_unlock(&gb_timesync_svc_list_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(gb_timesync_interface_add); + +/* + * Remove a Greybus Interface from the set of TimeSync Interfaces. + */ +void gb_timesync_interface_remove(struct gb_interface *interface) +{ + struct gb_timesync_svc *timesync_svc; + struct gb_timesync_interface *timesync_interface; + + if (!(interface->features & GREYBUS_INTERFACE_FEATURE_TIMESYNC)) + return; + + mutex_lock(&gb_timesync_svc_list_mutex); + timesync_svc = gb_timesync_find_timesync_svc(interface->hd); + if (!timesync_svc) + goto done; + + timesync_interface = gb_timesync_find_timesync_interface(timesync_svc, + interface); + if (!timesync_interface) + goto done; + + mutex_lock(×ync_svc->mutex); + timesync_svc->strobe_mask &= ~(1 << interface->interface_id); + list_del(×ync_interface->list); + kfree(timesync_interface); + mutex_unlock(×ync_svc->mutex); +done: + mutex_unlock(&gb_timesync_svc_list_mutex); +} +EXPORT_SYMBOL_GPL(gb_timesync_interface_remove); + +/* + * Give the authoritative FrameTime to the calling function. Returns zero if we + * are not in GB_TIMESYNC_STATE_ACTIVE. + */ +static u64 gb_timesync_get_frame_time(struct gb_timesync_svc *timesync_svc) +{ + unsigned long flags; + u64 ret; + + spin_lock_irqsave(×ync_svc->spinlock, flags); + if (timesync_svc->state == GB_TIMESYNC_STATE_ACTIVE) + ret = __gb_timesync_get_frame_time(timesync_svc); + else + ret = 0; + spin_unlock_irqrestore(×ync_svc->spinlock, flags); + return ret; +} + +u64 gb_timesync_get_frame_time_by_interface(struct gb_interface *interface) +{ + struct gb_timesync_svc *timesync_svc; + u64 ret = 0; + + mutex_lock(&gb_timesync_svc_list_mutex); + timesync_svc = gb_timesync_find_timesync_svc(interface->hd); + if (!timesync_svc) + goto done; + + ret = gb_timesync_get_frame_time(timesync_svc); +done: + mutex_unlock(&gb_timesync_svc_list_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(gb_timesync_get_frame_time_by_interface); + +u64 gb_timesync_get_frame_time_by_svc(struct gb_svc *svc) +{ + struct gb_timesync_svc *timesync_svc; + u64 ret = 0; + + mutex_lock(&gb_timesync_svc_list_mutex); + timesync_svc = gb_timesync_find_timesync_svc(svc->hd); + if (!timesync_svc) + goto done; + + ret = gb_timesync_get_frame_time(timesync_svc); +done: + mutex_unlock(&gb_timesync_svc_list_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(gb_timesync_get_frame_time_by_svc); + +void gb_timesync_irq(struct gb_timesync_svc *timesync_svc) +{ + unsigned long flags; + u64 strobe_time; + + strobe_time = __gb_timesync_get_frame_time(timesync_svc); + + spin_lock_irqsave(×ync_svc->spinlock, flags); + + if (timesync_svc->state == GB_TIMESYNC_STATE_PING) { + if (timesync_svc->capture_ping) + timesync_svc->ap_ping_frame_time = strobe_time; + goto done; + } else if (timesync_svc->state != GB_TIMESYNC_STATE_WAIT_SVC) { + goto done; + } + + timesync_svc->strobe_time[timesync_svc->strobe] = strobe_time; + + if (++timesync_svc->strobe == GB_TIMESYNC_MAX_STROBES) { + gb_timesync_set_state(timesync_svc, + GB_TIMESYNC_STATE_AUTHORITATIVE); + } +done: + spin_unlock_irqrestore(×ync_svc->spinlock, flags); +} +EXPORT_SYMBOL(gb_timesync_irq); + +int __init gb_timesync_init(void) +{ + int ret = 0; + + ret = gb_timesync_platform_init(); + if (ret) { + pr_err("timesync platform init fail!\n"); + return ret; + } + + gb_timesync_clock_rate = gb_timesync_platform_get_clock_rate(); + gb_timesync_ns_per_clock = NSEC_PER_SEC / gb_timesync_clock_rate; + + pr_info("Time-Sync timer frequency %lu Hz\n", gb_timesync_clock_rate); + return 0; +} + +void gb_timesync_exit(void) +{ + gb_timesync_platform_exit(); +} diff --git a/drivers/staging/greybus/timesync.h b/drivers/staging/greybus/timesync.h new file mode 100644 index 0000000..d907b0f --- /dev/null +++ b/drivers/staging/greybus/timesync.h @@ -0,0 +1,41 @@ +/* + * TimeSync API driver. + * + * Copyright 2016 Google Inc. + * Copyright 2016 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#ifndef __TIMESYNC_H +#define __TIMESYNC_H + +struct gb_svc; +struct gb_interface; +struct gb_timesync_svc; + +/* Platform */ +u64 gb_timesync_platform_get_counter(void); +u32 gb_timesync_platform_get_clock_rate(void); +int gb_timesync_platform_lock_bus(struct gb_timesync_svc *pdata); +void gb_timesync_platform_unlock_bus(void); + +int gb_timesync_platform_init(void); +void gb_timesync_platform_exit(void); + +/* Core API */ +int gb_timesync_interface_add(struct gb_interface *interface); +void gb_timesync_interface_remove(struct gb_interface *interface); +int gb_timesync_svc_add(struct gb_svc *svc); +void gb_timesync_svc_remove(struct gb_svc *svc); + +u64 gb_timesync_get_frame_time_by_interface(struct gb_interface *interface); +u64 gb_timesync_get_frame_time_by_svc(struct gb_svc *svc); + +int gb_timesync_schedule_synchronous(struct gb_interface *intf); +void gb_timesync_schedule_asynchronous(struct gb_interface *intf); +void gb_timesync_irq(struct gb_timesync_svc *timesync_svc); +int gb_timesync_init(void); +void gb_timesync_exit(void); + +#endif /* __TIMESYNC_H */ diff --git a/drivers/staging/greybus/timesync_platform.c b/drivers/staging/greybus/timesync_platform.c new file mode 100644 index 0000000..50e8883 --- /dev/null +++ b/drivers/staging/greybus/timesync_platform.c @@ -0,0 +1,77 @@ +/* + * TimeSync API driver. + * + * Copyright 2016 Google Inc. + * Copyright 2016 Linaro Ltd. + * + * Released under the GPLv2 only. + * + * This code reads directly from an ARMv7 memory-mapped timer that lives in + * MMIO space. Since this counter lives inside of MMIO space its shared between + * cores and that means we don't have to worry about issues like TSC on x86 + * where each time-stamp-counter (TSC) is local to a particular core. + * + * Register-level access code is based on + * drivers/clocksource/arm_arch_timer.c + */ +#include <linux/cpufreq.h> +#include <linux/of_platform.h> + +#include "greybus.h" +#include "arche_platform.h" + +static u32 gb_timesync_clock_frequency; +int (*arche_platform_change_state_cb)(enum arche_platform_state state, + struct gb_timesync_svc *pdata); +EXPORT_SYMBOL_GPL(arche_platform_change_state_cb); + +u64 gb_timesync_platform_get_counter(void) +{ + return (u64)get_cycles(); +} + +u32 gb_timesync_platform_get_clock_rate(void) +{ + if (unlikely(!gb_timesync_clock_frequency)) + return cpufreq_get(0); + + return gb_timesync_clock_frequency; +} + +int gb_timesync_platform_lock_bus(struct gb_timesync_svc *pdata) +{ + return arche_platform_change_state_cb(ARCHE_PLATFORM_STATE_TIME_SYNC, + pdata); +} + +void gb_timesync_platform_unlock_bus(void) +{ + arche_platform_change_state_cb(ARCHE_PLATFORM_STATE_ACTIVE, NULL); +} + +static const struct of_device_id arch_timer_of_match[] = { + { .compatible = "google,greybus-frame-time-counter", }, + {}, +}; + +int __init gb_timesync_platform_init(void) +{ + struct device_node *np; + + np = of_find_matching_node(NULL, arch_timer_of_match); + if (!np) { + /* Tolerate not finding to allow BBB etc to continue */ + pr_warn("Unable to find a compatible ARMv7 timer\n"); + return 0; + } + + if (of_property_read_u32(np, "clock-frequency", + &gb_timesync_clock_frequency)) { + pr_err("Unable to find timer clock-frequency\n"); + return -ENODEV; + } + + return 0; +} + +void gb_timesync_platform_exit(void) {} -- cgit v0.10.2 From 4a4484274f7431c68e104a66b497639e1ac9022c Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Sun, 5 Jun 2016 14:03:27 +0100 Subject: greybus: timesync: Bind TimeSync into Greybus TimeSync needs to bind into Greybus in a few places. - core.c To initialize its internal state and tear-down its internal state. To schedule a timesync to a newly added Bundle after probe() completes. - svc.c To get access to the SVC and enable/disable timesync as well as extracting the authoritative time from the SVC to subsequently disseminate to other entities in the system. - interface.c To get access to an Interface in order to inform APBx of timesync enable/disable and authoritative operations. This patch adds those bindings into Greybus core. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Reviewed-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Acked-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 7350c5e..c812906 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -178,6 +178,8 @@ static int greybus_probe(struct device *dev) return retval; } + gb_timesync_schedule_asynchronous(bundle->intf); + return 0; } @@ -267,8 +269,15 @@ static int __init gb_init(void) goto error_bootrom; } + retval = gb_timesync_init(); + if (retval) { + pr_err("gb_timesync_init failed\n"); + goto error_timesync; + } return 0; /* Success */ +error_timesync: + gb_bootrom_exit(); error_bootrom: gb_operation_exit(); error_operation: @@ -284,6 +293,7 @@ module_init(gb_init); static void __exit gb_exit(void) { + gb_timesync_exit(); gb_bootrom_exit(); gb_operation_exit(); gb_hd_exit(); diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 3eb8754..9b90209 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -805,6 +805,12 @@ int gb_interface_enable(struct gb_interface *intf) if (ret) goto err_destroy_bundles; + ret = gb_timesync_interface_add(intf); + if (ret) { + dev_err(&intf->dev, "failed to add to timesync: %d\n", ret); + goto err_destroy_bundles; + } + list_for_each_entry_safe_reverse(bundle, tmp, &intf->bundles, links) { ret = gb_bundle_add(bundle); if (ret) { @@ -857,6 +863,7 @@ void gb_interface_disable(struct gb_interface *intf) list_for_each_entry_safe(bundle, next, &intf->bundles, links) gb_bundle_destroy(bundle); + gb_timesync_interface_remove(intf); gb_control_del(intf->control); gb_control_disable(intf->control); gb_control_put(intf->control); diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index b41d262..d7458c5 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -851,14 +851,25 @@ static int gb_svc_hello(struct gb_operation *op) ret = gb_svc_watchdog_create(svc); if (ret) { dev_err(&svc->dev, "failed to create watchdog: %d\n", ret); - input_unregister_device(svc->input); - device_del(&svc->dev); - return ret; + goto err_unregister_device; } gb_svc_debugfs_init(svc); + ret = gb_timesync_svc_add(svc); + if (ret) { + dev_err(&svc->dev, "failed to add SVC to timesync: %d\n", ret); + gb_svc_debugfs_exit(svc); + goto err_unregister_device; + } + return gb_svc_queue_deferred_request(op); + +err_unregister_device: + gb_svc_watchdog_destroy(svc); + input_unregister_device(svc->input); + device_del(&svc->dev); + return ret; } static struct gb_interface *gb_svc_interface_lookup(struct gb_svc *svc, @@ -1404,6 +1415,7 @@ void gb_svc_del(struct gb_svc *svc) * from the request handler. */ if (device_is_registered(&svc->dev)) { + gb_timesync_svc_remove(svc); gb_svc_debugfs_exit(svc); gb_svc_watchdog_destroy(svc); input_unregister_device(svc->input); -- cgit v0.10.2 From 6da7c88972a0153db427c14c6c5b2c4e2ccaefb7 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Sun, 5 Jun 2016 14:03:28 +0100 Subject: greybus: tracepoints: Add standard Linux tracepoint for TimeSync event This patch adds a tracepoint to the TimeSync ISR, the purpose of which is to indicate a TimeSync event has happened. This tracepoint can be enabled by issuing the following command: echo 1 > /sys/kernel/debug/tracing/events/greybus/gb_timesync_irq/enable Synchronization looks like this: TIMESTAMP FUNCTION | | 147.865788: gb_timesync_irq: strobe 1/4 frame-time 2910076529 147.866781: gb_timesync_irq: strobe 2/4 frame-time 2910095689 147.867777: gb_timesync_irq: strobe 3/4 frame-time 2910114820 147.868791: gb_timesync_irq: strobe 4/4 frame-time 2910134038 A ping can be triggered like this: cat /sys/kernel/debug/greybus/frame-time And that ping looks like this: TIMESTAMP FUNCTION | | 147.934678: gb_timesync_irq: ping 4/4 frame-time 2911380356 169.280551: gb_timesync_irq: ping 4/4 frame-time 3321221069 Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Reviewed-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Acked-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h index 342f5ad..7249b8a 100644 --- a/drivers/staging/greybus/greybus_trace.h +++ b/drivers/staging/greybus/greybus_trace.h @@ -488,6 +488,34 @@ DEFINE_HD_EVENT(gb_hd_in); #undef DEFINE_HD_EVENT +/* + * Occurs on a TimeSync synchronization event or a TimeSync ping event. + */ +TRACE_EVENT(gb_timesync_irq, + + TP_PROTO(u8 ping, u8 strobe, u8 count, u64 frame_time), + + TP_ARGS(ping, strobe, count, frame_time), + + TP_STRUCT__entry( + __field(u8, ping) + __field(u8, strobe) + __field(u8, count) + __field(u64, frame_time) + ), + + TP_fast_assign( + __entry->ping = ping; + __entry->strobe = strobe; + __entry->count = count; + __entry->frame_time = frame_time; + ), + + TP_printk("%s %d/%d frame-time %llu\n", + __entry->ping ? "ping" : "strobe", __entry->strobe, + __entry->count, __entry->frame_time) +); + #endif /* _TRACE_GREYBUS_H */ /* This part must be outside protection */ diff --git a/drivers/staging/greybus/timesync.c b/drivers/staging/greybus/timesync.c index 260b670..4bf62ad 100644 --- a/drivers/staging/greybus/timesync.c +++ b/drivers/staging/greybus/timesync.c @@ -9,6 +9,7 @@ #include <linux/debugfs.h> #include "greybus.h" #include "timesync.h" +#include "greybus_trace.h" /* * Minimum inter-strobe value of one millisecond is chosen because it @@ -974,17 +975,19 @@ void gb_timesync_irq(struct gb_timesync_svc *timesync_svc) { unsigned long flags; u64 strobe_time; + bool strobe_is_ping = true; strobe_time = __gb_timesync_get_frame_time(timesync_svc); spin_lock_irqsave(×ync_svc->spinlock, flags); if (timesync_svc->state == GB_TIMESYNC_STATE_PING) { - if (timesync_svc->capture_ping) - timesync_svc->ap_ping_frame_time = strobe_time; - goto done; + if (!timesync_svc->capture_ping) + goto done_nolog; + timesync_svc->ap_ping_frame_time = strobe_time; + goto done_log; } else if (timesync_svc->state != GB_TIMESYNC_STATE_WAIT_SVC) { - goto done; + goto done_nolog; } timesync_svc->strobe_time[timesync_svc->strobe] = strobe_time; @@ -993,7 +996,11 @@ void gb_timesync_irq(struct gb_timesync_svc *timesync_svc) gb_timesync_set_state(timesync_svc, GB_TIMESYNC_STATE_AUTHORITATIVE); } -done: + strobe_is_ping = false; +done_log: + trace_gb_timesync_irq(strobe_is_ping, timesync_svc->strobe, + GB_TIMESYNC_MAX_STROBES, strobe_time); +done_nolog: spin_unlock_irqrestore(×ync_svc->spinlock, flags); } EXPORT_SYMBOL(gb_timesync_irq); -- cgit v0.10.2 From 00fdbae1a9d2cecfcbab98fe69e4483f80fb80c4 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Sun, 5 Jun 2016 14:03:29 +0100 Subject: greybus: timesync: Add gb_timesync_frame_time_to_timespec() This patch adds gb_timesync_to_timespec_by_svc() and gb_timesync_to_timespec_by_interface() respectively. These routines will convert from a given FrameTime to a ktime/timespec within an envelope of about 17 seconds. The purpose of this routine is to enable reporting of a FrameTime from a Module such as a Camera Module and to allow the AP to then convert this timestamp into a Linux-native timestamp such as ktime. This is useful and required in the v4l layer. At 19.2MHz the accuracy of this conversion is about .3 femtoseconds per count, which means at a 1 second offset from the reference the cumulative error is about 1.59 nanoseconds. 1.59 nanoseconds is still less than 1 clock's worth of error @ 19.2MHz where each clock is 52.0833~ nanoseconds. We're aiming for a maximum error rate of 30 nanoseconds which means at the clock rate we are running at, the conversion from a FrameTime to a Linux ktime/timespec can be plus-or-minus about 17 seconds from the reference FrameTime/ktime pair before the routine will refuse to convert. A realistic use-case for this routine is envisaged to be - Greybus message received - Some processing takes place - taking milliseconds - Call into this routine is made - Actual time between event in Module and conversion in AP < 1 second - Error rate in conversion at 1.59 nanoseconds is less than 1 clock @ 19.2MHz This routine is not designed to allow for conversions for events with large gaps between the event time and the current reference time for conversion. Since FrameTime can be a very large integer we cannot convert an arbitrarily large FrameTime to ktime, the feeling and objective here is to make an over-provisioned envelope that in practical terms can never be exceeded by expected use-cases. To convert longer gaps more work would have to be done but ultimately some limit needs to be imposed and right now 0.3 femotseconds per clock on MSM8994 is both accurate and generous. Adds: - timesync.c::gb_timesync_frame_time_to_timespec_by_svc( struct gb_svc *, u64 frame_time, struct timespec *ts) - gb_svc is a pointer to a standard greybus SVC data structure - frame_time is a system FrameTime. - ts is an output parameter which represents the converted FrameTime as a CLOCK_MONOTONIC timespec value. - Returns 0 on success or a negative number indicating the type of error on failure. - timesync.c::gb_timesync_frame_time_to_timespec_by_interface( struct gb_interface *, u64 frame_time, struct timespec *ts) - gb_svc is a pointer to a standard greybus Interface data structure - frame_time is a system FrameTime. - ts is an output parameter which represents the converted FrameTime as a CLOCK_MONOTONIC timespec value. - Returns 0 on success or a negative number indicating the type of error on failure. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Acked-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/timesync.c b/drivers/staging/greybus/timesync.c index 4bf62ad..ebc61ef 100644 --- a/drivers/staging/greybus/timesync.c +++ b/drivers/staging/greybus/timesync.c @@ -7,6 +7,7 @@ * Released under the GPLv2 only. */ #include <linux/debugfs.h> +#include <linux/hrtimer.h> #include "greybus.h" #include "timesync.h" #include "greybus_trace.h" @@ -30,9 +31,15 @@ #define GB_TIMESYNC_DELAYED_WORK_LONG msecs_to_jiffies(1000) #define GB_TIMESYNC_DELAYED_WORK_SHORT msecs_to_jiffies(1) #define GB_TIMESYNC_MAX_WAIT_SVC msecs_to_jiffies(5000) +#define GB_TIMESYNC_KTIME_UPDATE msecs_to_jiffies(1000) +#define GB_TIMESYNC_MAX_KTIME_CONVERSION 15 -/* Reported nanoseconds per clock */ +/* Reported nanoseconds/femtoseconds per clock */ static u64 gb_timesync_ns_per_clock; +static u64 gb_timesync_fs_per_clock; + +/* Maximum difference we will accept converting FrameTime to ktime */ +static u32 gb_timesync_max_ktime_diff; /* Reported clock rate */ static unsigned long gb_timesync_clock_rate; @@ -46,6 +53,12 @@ static LIST_HEAD(gb_timesync_svc_list); /* Synchronize parallel contexts accessing a valid timesync_svc pointer */ static DEFINE_MUTEX(gb_timesync_svc_list_mutex); +/* Structure to convert from FrameTime to timespec/ktime */ +struct gb_timesync_frame_time_data { + u64 frame_time; + struct timespec ts; +}; + struct gb_timesync_svc { struct list_head list; struct list_head interface_list; @@ -59,10 +72,12 @@ struct gb_timesync_svc { struct workqueue_struct *work_queue; wait_queue_head_t wait_queue; struct delayed_work delayed_work; + struct timer_list ktime_timer; /* The current local FrameTime */ u64 frame_time_offset; - u64 strobe_time[GB_TIMESYNC_MAX_STROBES]; + struct gb_timesync_frame_time_data strobe_data[GB_TIMESYNC_MAX_STROBES]; + struct gb_timesync_frame_time_data ktime_data; /* The SVC FrameTime and relative AP FrameTime @ last TIMESYNC_PING */ u64 svc_ping_frame_time; @@ -101,6 +116,8 @@ enum gb_timesync_state { GB_TIMESYNC_STATE_ACTIVE = 6, }; +static void gb_timesync_ktime_timer_fn(unsigned long data); + static u64 gb_timesync_adjust_count(struct gb_timesync_svc *timesync_svc, u64 counts) { @@ -221,6 +238,17 @@ static void gb_timesync_adjust_to_svc(struct gb_timesync_svc *svc, } /* + * Associate a FrameTime with a ktime timestamp represented as struct timespec + * Requires the calling context to hold timesync_svc->mutex + */ +static void gb_timesync_store_ktime(struct gb_timesync_svc *timesync_svc, + struct timespec ts, u64 frame_time) +{ + timesync_svc->ktime_data.ts = ts; + timesync_svc->ktime_data.frame_time = frame_time; +} + +/* * Find the two pulses that best-match our expected inter-strobe gap and * then calculate the difference between the SVC time at the second pulse * to the local time at the second pulse. @@ -229,24 +257,32 @@ static void gb_timesync_collate_frame_time(struct gb_timesync_svc *timesync_svc, u64 *frame_time) { int i = 0; - u64 delta; + u64 delta, ap_frame_time; u64 strobe_delay_ns = GB_TIMESYNC_STROBE_DELAY_US * NSEC_PER_USEC; u64 least = 0; for (i = 1; i < GB_TIMESYNC_MAX_STROBES; i++) { - delta = timesync_svc->strobe_time[i] - - timesync_svc->strobe_time[i - 1]; + delta = timesync_svc->strobe_data[i].frame_time - + timesync_svc->strobe_data[i - 1].frame_time; delta *= gb_timesync_ns_per_clock; delta = gb_timesync_diff(delta, strobe_delay_ns); if (!least || delta < least) { least = delta; gb_timesync_adjust_to_svc(timesync_svc, frame_time[i], - timesync_svc->strobe_time[i]); + timesync_svc->strobe_data[i].frame_time); + + ap_frame_time = timesync_svc->strobe_data[i].frame_time; + ap_frame_time = gb_timesync_adjust_count(timesync_svc, + ap_frame_time); + gb_timesync_store_ktime(timesync_svc, + timesync_svc->strobe_data[i].ts, + ap_frame_time); + pr_debug("adjust %s local %llu svc %llu delta %llu\n", timesync_svc->offset_down ? "down" : "up", - timesync_svc->strobe_time[i], frame_time[i], - delta); + timesync_svc->strobe_data[i].frame_time, + frame_time[i], delta); } } } @@ -415,6 +451,119 @@ static void gb_timesync_authoritative(struct gb_timesync_svc *timesync_svc) gb_timesync_set_state_atomic(timesync_svc, GB_TIMESYNC_STATE_PING); } +static int __gb_timesync_get_status(struct gb_timesync_svc *timesync_svc) +{ + int ret = -EINVAL; + + switch (timesync_svc->state) { + case GB_TIMESYNC_STATE_INVALID: + case GB_TIMESYNC_STATE_INACTIVE: + ret = -ENODEV; + break; + case GB_TIMESYNC_STATE_INIT: + case GB_TIMESYNC_STATE_WAIT_SVC: + case GB_TIMESYNC_STATE_AUTHORITATIVE: + case GB_TIMESYNC_STATE_PING: + ret = -EAGAIN; + break; + case GB_TIMESYNC_STATE_ACTIVE: + ret = 0; + break; + } + return ret; +} + +/* + * This routine takes a FrameTime and derives the difference with-respect + * to a reference FrameTime/ktime pair. It then returns the calculated + * ktime based on the difference between the supplied FrameTime and + * the reference FrameTime. + * + * The time difference is calculated to six decimal places. Taking 19.2MHz + * as an example this means we have 52.083333~ nanoseconds per clock or + * 52083333~ femtoseconds per clock. + * + * Naively taking the count difference and converting to + * seconds/nanoseconds would quickly see the 0.0833 component produce + * noticeable errors. For example a time difference of one second would + * loose 19200000 * 0.08333x nanoseconds or 1.59 seconds. + * + * In contrast calculating in femtoseconds the same example of 19200000 * + * 0.000000083333x nanoseconds per count of error is just 1.59 nanoseconds! + * + * Continuing the example of 19.2 MHz we cap the maximum error difference + * at a worst-case 0.3 microseconds over a potential calculation window of + * abount 15 seconds, meaning you can convert a FrameTime that is <= 15 + * seconds older/younger than the reference time with a maximum error of + * 0.2385 useconds. Note 19.2MHz is an example frequency not a requirement. + */ +static int gb_timesync_to_timespec(struct gb_timesync_svc *timesync_svc, + u64 frame_time, struct timespec *ts) +{ + unsigned long flags; + u64 delta_fs, counts; + u32 sec, nsec; + bool add; + int ret = 0; + + mutex_lock(×ync_svc->mutex); + spin_lock_irqsave(×ync_svc->spinlock, flags); + + ret = __gb_timesync_get_status(timesync_svc); + if (ret) + goto done; + + /* Support calculating ktime upwards or downwards from the reference */ + if (frame_time < timesync_svc->ktime_data.frame_time) { + add = false; + counts = timesync_svc->ktime_data.frame_time - frame_time; + } else { + add = true; + counts = frame_time - timesync_svc->ktime_data.frame_time; + } + + /* Enforce the .23 of a usecond boundary @ 19.2MHz */ + if (counts > gb_timesync_max_ktime_diff) { + ret = -EINVAL; + goto done; + } + + /* Determine the time difference in femtoseconds */ + delta_fs = counts * gb_timesync_fs_per_clock; + sec = delta_fs / FSEC_PER_SEC; + nsec = (delta_fs % FSEC_PER_SEC) / 1000000UL; + + if (add) { + /* Add the calculated offset - overflow nanoseconds upwards */ + ts->tv_sec = timesync_svc->ktime_data.ts.tv_sec + sec; + ts->tv_nsec = timesync_svc->ktime_data.ts.tv_nsec + nsec; + if (ts->tv_nsec >= NSEC_PER_SEC) { + ts->tv_sec++; + ts->tv_nsec -= NSEC_PER_SEC; + } + } else { + /* Subtract the difference over/underflow as necessary */ + if (nsec > timesync_svc->ktime_data.ts.tv_nsec) { + sec++; + nsec = nsec + timesync_svc->ktime_data.ts.tv_nsec; + nsec %= NSEC_PER_SEC; + } else { + nsec = timesync_svc->ktime_data.ts.tv_nsec - nsec; + } + /* Cannot return a negative second value */ + if (sec > timesync_svc->ktime_data.ts.tv_sec) { + ret = -EINVAL; + goto done; + } + ts->tv_sec = timesync_svc->ktime_data.ts.tv_sec - sec; + ts->tv_nsec = nsec; + } +done: + spin_unlock_irqrestore(×ync_svc->spinlock, flags); + mutex_unlock(×ync_svc->mutex); + return ret; +} + static size_t gb_timesync_log_frame_time(struct gb_timesync_svc *timesync_svc, char *buf, size_t buflen) { @@ -616,21 +765,7 @@ static int __gb_timesync_schedule_synchronous( mutex_lock(×ync_svc->mutex); spin_lock_irqsave(×ync_svc->spinlock, flags); - switch (timesync_svc->state) { - case GB_TIMESYNC_STATE_INVALID: - case GB_TIMESYNC_STATE_INACTIVE: - ret = -ENODEV; - break; - case GB_TIMESYNC_STATE_INIT: - case GB_TIMESYNC_STATE_WAIT_SVC: - case GB_TIMESYNC_STATE_AUTHORITATIVE: - case GB_TIMESYNC_STATE_PING: - ret = -EAGAIN; - break; - case GB_TIMESYNC_STATE_ACTIVE: - ret = 0; - break; - } + ret = __gb_timesync_get_status(timesync_svc); spin_unlock_irqrestore(×ync_svc->spinlock, flags); mutex_unlock(×ync_svc->mutex); @@ -810,7 +945,15 @@ int gb_timesync_svc_add(struct gb_svc *svc) debugfs_remove(timesync_svc->frame_time_dentry); destroy_workqueue(timesync_svc->work_queue); kfree(timesync_svc); + goto done; } + + init_timer(×ync_svc->ktime_timer); + timesync_svc->ktime_timer.function = gb_timesync_ktime_timer_fn; + timesync_svc->ktime_timer.expires = jiffies + GB_TIMESYNC_KTIME_UPDATE; + timesync_svc->ktime_timer.data = (unsigned long)timesync_svc; + add_timer(×ync_svc->ktime_timer); +done: mutex_unlock(&gb_timesync_svc_list_mutex); return ret; } @@ -830,6 +973,7 @@ void gb_timesync_svc_remove(struct gb_svc *svc) mutex_lock(×ync_svc->mutex); gb_timesync_teardown(timesync_svc); + del_timer_sync(×ync_svc->ktime_timer); gb_timesync_hd_remove(timesync_svc, svc->hd); list_for_each_entry_safe(timesync_interface, next, @@ -971,12 +1115,77 @@ done: } EXPORT_SYMBOL_GPL(gb_timesync_get_frame_time_by_svc); +/* Incrementally updates the conversion base from FrameTime to ktime */ +static void gb_timesync_ktime_timer_fn(unsigned long data) +{ + struct gb_timesync_svc *timesync_svc = + (struct gb_timesync_svc *)data; + unsigned long flags; + u64 frame_time; + struct timespec ts; + + spin_lock_irqsave(×ync_svc->spinlock, flags); + + if (timesync_svc->state != GB_TIMESYNC_STATE_ACTIVE) + goto done; + + ktime_get_ts(&ts); + frame_time = __gb_timesync_get_frame_time(timesync_svc); + gb_timesync_store_ktime(timesync_svc, ts, frame_time); + +done: + spin_unlock_irqrestore(×ync_svc->spinlock, flags); + mod_timer(×ync_svc->ktime_timer, + jiffies + GB_TIMESYNC_KTIME_UPDATE); +} + +int gb_timesync_to_timespec_by_svc(struct gb_svc *svc, u64 frame_time, + struct timespec *ts) +{ + struct gb_timesync_svc *timesync_svc; + int ret = 0; + + mutex_lock(&gb_timesync_svc_list_mutex); + timesync_svc = gb_timesync_find_timesync_svc(svc->hd); + if (!timesync_svc) { + ret = -ENODEV; + goto done; + } + ret = gb_timesync_to_timespec(timesync_svc, frame_time, ts); +done: + mutex_unlock(&gb_timesync_svc_list_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(gb_timesync_to_timespec_by_svc); + +int gb_timesync_to_timespec_by_interface(struct gb_interface *interface, + u64 frame_time, struct timespec *ts) +{ + struct gb_timesync_svc *timesync_svc; + int ret = 0; + + mutex_lock(&gb_timesync_svc_list_mutex); + timesync_svc = gb_timesync_find_timesync_svc(interface->hd); + if (!timesync_svc) { + ret = -ENODEV; + goto done; + } + + ret = gb_timesync_to_timespec(timesync_svc, frame_time, ts); +done: + mutex_unlock(&gb_timesync_svc_list_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(gb_timesync_to_timespec_by_interface); + void gb_timesync_irq(struct gb_timesync_svc *timesync_svc) { unsigned long flags; u64 strobe_time; bool strobe_is_ping = true; + struct timespec ts; + ktime_get_ts(&ts); strobe_time = __gb_timesync_get_frame_time(timesync_svc); spin_lock_irqsave(×ync_svc->spinlock, flags); @@ -990,7 +1199,8 @@ void gb_timesync_irq(struct gb_timesync_svc *timesync_svc) goto done_nolog; } - timesync_svc->strobe_time[timesync_svc->strobe] = strobe_time; + timesync_svc->strobe_data[timesync_svc->strobe].frame_time = strobe_time; + timesync_svc->strobe_data[timesync_svc->strobe].ts = ts; if (++timesync_svc->strobe == GB_TIMESYNC_MAX_STROBES) { gb_timesync_set_state(timesync_svc, @@ -1016,9 +1226,17 @@ int __init gb_timesync_init(void) } gb_timesync_clock_rate = gb_timesync_platform_get_clock_rate(); + + /* Calculate nanoseconds and femtoseconds per clock */ + gb_timesync_fs_per_clock = FSEC_PER_SEC / gb_timesync_clock_rate; gb_timesync_ns_per_clock = NSEC_PER_SEC / gb_timesync_clock_rate; - pr_info("Time-Sync timer frequency %lu Hz\n", gb_timesync_clock_rate); + /* Calculate the maximum number of clocks we will convert to ktime */ + gb_timesync_max_ktime_diff = + GB_TIMESYNC_MAX_KTIME_CONVERSION * gb_timesync_clock_rate; + + pr_info("Time-Sync @ %lu Hz max ktime conversion +/- %d seconds\n", + gb_timesync_clock_rate, GB_TIMESYNC_MAX_KTIME_CONVERSION); return 0; } diff --git a/drivers/staging/greybus/timesync.h b/drivers/staging/greybus/timesync.h index d907b0f..72fc9a3 100644 --- a/drivers/staging/greybus/timesync.h +++ b/drivers/staging/greybus/timesync.h @@ -31,6 +31,10 @@ void gb_timesync_svc_remove(struct gb_svc *svc); u64 gb_timesync_get_frame_time_by_interface(struct gb_interface *interface); u64 gb_timesync_get_frame_time_by_svc(struct gb_svc *svc); +int gb_timesync_to_timespec_by_svc(struct gb_svc *svc, u64 frame_time, + struct timespec *ts); +int gb_timesync_to_timespec_by_interface(struct gb_interface *interface, + u64 frame_time, struct timespec *ts); int gb_timesync_schedule_synchronous(struct gb_interface *intf); void gb_timesync_schedule_asynchronous(struct gb_interface *intf); -- cgit v0.10.2 From 423042f4b2dc763f16c27b18a19611fa1773ac30 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Sun, 5 Jun 2016 14:03:30 +0100 Subject: greybus: timesync: Add debugfs entry to display frame-ping in ktime This patch makes a debugfs entry in /sys/kernel/debug/greybus/X-svc/frame-ktime that generates a TimeSync ping event to the system and then subsequently presents that data to user-space as a ktime/timespec clock-monotonic value rather than as a raw frame-time, to aid humans in debugging and understanding frame-time and to provide an example of the converting a frame-time to timespec/ktime to other developers. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Acked-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/timesync.c b/drivers/staging/greybus/timesync.c index ebc61ef..87cbe10 100644 --- a/drivers/staging/greybus/timesync.c +++ b/drivers/staging/greybus/timesync.c @@ -69,6 +69,7 @@ struct gb_timesync_svc { struct mutex mutex; /* Per SVC mutex for regular synchronization */ struct dentry *frame_time_dentry; + struct dentry *frame_ktime_dentry; struct workqueue_struct *work_queue; wait_queue_head_t wait_queue; struct delayed_work delayed_work; @@ -506,6 +507,7 @@ static int gb_timesync_to_timespec(struct gb_timesync_svc *timesync_svc, bool add; int ret = 0; + memset(ts, 0x00, sizeof(*ts)); mutex_lock(×ync_svc->mutex); spin_lock_irqsave(×ync_svc->spinlock, flags); @@ -575,7 +577,6 @@ static size_t gb_timesync_log_frame_time(struct gb_timesync_svc *timesync_svc, size_t off; /* AP/SVC */ - memset(buf, 0x00, buflen); off = snprintf(buf, buflen, "timesync: ping-time ap=%llu %s=%llu ", timesync_svc->ap_ping_frame_time, dev_name(&svc->dev), timesync_svc->svc_ping_frame_time); @@ -604,6 +605,65 @@ static size_t gb_timesync_log_frame_time(struct gb_timesync_svc *timesync_svc, return off; } +static size_t gb_timesync_log_frame_ktime(struct gb_timesync_svc *timesync_svc, + char *buf, size_t buflen) +{ + struct gb_svc *svc = timesync_svc->svc; + struct gb_host_device *hd; + struct gb_timesync_interface *timesync_interface; + struct gb_interface *interface; + struct timespec ts; + unsigned int len; + size_t off; + + /* AP */ + gb_timesync_to_timespec(timesync_svc, timesync_svc->ap_ping_frame_time, + &ts); + off = snprintf(buf, buflen, "timesync: ping-time ap=%lu.%lu ", + ts.tv_sec, ts.tv_nsec); + len = buflen - off; + if (len >= buflen) + goto done; + + /* SVC */ + gb_timesync_to_timespec(timesync_svc, timesync_svc->svc_ping_frame_time, + &ts); + off += snprintf(&buf[off], len, "%s=%lu.%lu ", dev_name(&svc->dev), + ts.tv_sec, ts.tv_nsec); + len = buflen - off; + if (len >= buflen) + goto done; + + /* APB/GPB */ + hd = timesync_svc->timesync_hd->hd; + gb_timesync_to_timespec(timesync_svc, + timesync_svc->timesync_hd->ping_frame_time, + &ts); + off += snprintf(&buf[off], len, "%s=%lu.%lu ", + dev_name(&hd->dev), + ts.tv_sec, ts.tv_nsec); + len = buflen - off; + if (len >= buflen) + goto done; + + list_for_each_entry(timesync_interface, + ×ync_svc->interface_list, list) { + interface = timesync_interface->interface; + gb_timesync_to_timespec(timesync_svc, + timesync_interface->ping_frame_time, + &ts); + off += snprintf(&buf[off], len, "%s=%lu.%lu ", + dev_name(&interface->dev), + ts.tv_sec, ts.tv_nsec); + len = buflen - off; + if (len >= buflen) + goto done; + } + off += snprintf(&buf[off], len, "\n"); +done: + return off; +} + /* * Send an SVC initiated wake 'ping' to each TimeSync participant. * Get the FrameTime from each participant associated with the wake @@ -840,11 +900,11 @@ done: } EXPORT_SYMBOL_GPL(gb_timesync_schedule_asynchronous); -static ssize_t gb_timesync_ping_read(struct file *file, char __user *buf, - size_t len, loff_t *offset) +static ssize_t gb_timesync_ping_read(struct file *file, char __user *ubuf, + size_t len, loff_t *offset, bool ktime) { struct gb_timesync_svc *timesync_svc = file->f_inode->i_private; - char *pbuf; + char *buf; ssize_t ret = 0; mutex_lock(&gb_timesync_svc_list_mutex); @@ -861,23 +921,44 @@ static ssize_t gb_timesync_ping_read(struct file *file, char __user *buf, if (ret) goto done; - pbuf = kzalloc(PAGE_SIZE, GFP_KERNEL); - if (!pbuf) { + buf = kzalloc(PAGE_SIZE, GFP_KERNEL); + if (!buf) { ret = -ENOMEM; goto done; } - ret = gb_timesync_log_frame_time(timesync_svc, pbuf, PAGE_SIZE); + if (ktime) + ret = gb_timesync_log_frame_ktime(timesync_svc, buf, PAGE_SIZE); + else + ret = gb_timesync_log_frame_time(timesync_svc, buf, PAGE_SIZE); if (ret > 0) - ret = simple_read_from_buffer(buf, len, offset, pbuf, ret); - kfree(pbuf); + ret = simple_read_from_buffer(ubuf, len, offset, buf, ret); + kfree(buf); done: mutex_unlock(&gb_timesync_svc_list_mutex); return ret; } -static const struct file_operations gb_timesync_debugfs_ops = { - .read = gb_timesync_ping_read, +static ssize_t gb_timesync_ping_read_frame_time(struct file *file, + char __user *buf, + size_t len, loff_t *offset) +{ + return gb_timesync_ping_read(file, buf, len, offset, false); +} + +static ssize_t gb_timesync_ping_read_frame_ktime(struct file *file, + char __user *buf, + size_t len, loff_t *offset) +{ + return gb_timesync_ping_read(file, buf, len, offset, true); +} + +static const struct file_operations gb_timesync_debugfs_frame_time_ops = { + .read = gb_timesync_ping_read_frame_time, +}; + +static const struct file_operations gb_timesync_debugfs_frame_ktime_ops = { + .read = gb_timesync_ping_read_frame_ktime, }; static int gb_timesync_hd_add(struct gb_timesync_svc *timesync_svc, @@ -935,13 +1016,21 @@ int gb_timesync_svc_add(struct gb_svc *svc) timesync_svc->frame_time_offset = 0; timesync_svc->capture_ping = false; gb_timesync_set_state_atomic(timesync_svc, GB_TIMESYNC_STATE_INACTIVE); + timesync_svc->frame_time_dentry = debugfs_create_file("frame-time", S_IRUGO, svc->debugfs_dentry, - timesync_svc, &gb_timesync_debugfs_ops); + timesync_svc, + &gb_timesync_debugfs_frame_time_ops); + timesync_svc->frame_ktime_dentry = + debugfs_create_file("frame-ktime", S_IRUGO, svc->debugfs_dentry, + timesync_svc, + &gb_timesync_debugfs_frame_ktime_ops); + list_add(×ync_svc->list, &gb_timesync_svc_list); ret = gb_timesync_hd_add(timesync_svc, svc->hd); if (ret) { list_del(×ync_svc->list); + debugfs_remove(timesync_svc->frame_ktime_dentry); debugfs_remove(timesync_svc->frame_time_dentry); destroy_workqueue(timesync_svc->work_queue); kfree(timesync_svc); @@ -982,6 +1071,7 @@ void gb_timesync_svc_remove(struct gb_svc *svc) kfree(timesync_interface); } gb_timesync_set_state_atomic(timesync_svc, GB_TIMESYNC_STATE_INVALID); + debugfs_remove(timesync_svc->frame_ktime_dentry); debugfs_remove(timesync_svc->frame_time_dentry); cancel_delayed_work_sync(×ync_svc->delayed_work); destroy_workqueue(timesync_svc->work_queue); -- cgit v0.10.2 From 109fbdfd6a23c122c564a6cd6671b9911e0a24b5 Mon Sep 17 00:00:00 2001 From: Jeffrey Carlyle <jcarlyle@google.com> Date: Tue, 7 Jun 2016 08:22:22 -0700 Subject: greybus: svc: implement connection_quiescing call Implement Greybus remote call to connection_quiescing operation. This operation disables flow contorl for the connection and resets associated attributes. Testing done: tested along with required NuttX firmware changes, booted EVT2, inserted module, removed module, inserted module. Verified module was functioning as expected. Signed-off-by: Jeffrey Carlyle <jcarlyle@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 82075c7..8125fb7 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -904,6 +904,7 @@ struct gb_spi_transfer_response { #define GB_SVC_TYPE_TIMESYNC_WAKE_PINS_ACQUIRE 0x18 #define GB_SVC_TYPE_TIMESYNC_WAKE_PINS_RELEASE 0x19 #define GB_SVC_TYPE_TIMESYNC_PING 0x1a +#define GB_SVC_TYPE_CONN_QUIESCING 0x1e #define GB_SVC_TYPE_MODULE_INSERTED 0x1f #define GB_SVC_TYPE_MODULE_REMOVED 0x20 #define GB_SVC_TYPE_INTF_VSYS_ENABLE 0x21 @@ -1215,6 +1216,17 @@ struct gb_svc_intf_mailbox_event_request { } __packed; /* intf_mailbox_event response has no payload */ +struct gb_svc_conn_quiescing_request { + __u8 intf1_id; + __le16 cport1_id; + __u8 intf2_id; + __le16 cport2_id; +} __packed; + +struct gb_svc_conn_quiescing_response { + __u8 status; +} __packed; + /* RAW */ diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index d7458c5..bfdd0ce 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -441,10 +441,31 @@ EXPORT_SYMBOL_GPL(gb_svc_connection_create); void gb_svc_connection_quiescing(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id) { - /* FIXME: implement */ + struct gb_svc_conn_quiescing_request request; + struct gb_svc_conn_quiescing_response response; + int ret; dev_dbg(&svc->dev, "%s - (%u:%u %u:%u)\n", __func__, intf1_id, cport1_id, intf2_id, cport2_id); + + request.intf1_id = intf1_id; + request.cport1_id = cpu_to_le16(cport1_id); + request.intf2_id = intf2_id; + request.cport2_id = cpu_to_le16(cport2_id); + + ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_CONN_QUIESCING, + &request, sizeof(request), + &response, sizeof(response)); + if (ret < 0) + return; + if (response.status != GB_SVC_OP_SUCCESS) { + dev_err(&svc->dev, "quiescing connection failed (%u:%u %u:%u): %u\n", + intf1_id, cport1_id, intf2_id, cport2_id, + response.status); + return; + } + + return; } EXPORT_SYMBOL_GPL(gb_svc_connection_quiescing); -- cgit v0.10.2 From 4d27574cd354bc47758268c2e32a0a47b7aacfc0 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Wed, 8 Jun 2016 20:33:26 +0530 Subject: greybus: audio: Ratelimit err messages In case of audio mgmt connection failure, GB requests would fail giving an error message within the driver and reporting error. However there is no error handling in above HAL and it'll keep on triggering similar request via GB codec driver. This may overflood serial console. In one of the instance it locked CPU for >10sec and caused a watchdog bite. Thus ratelimit those error messages. Testing Done: compile tested Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 23dde70..975d2e8 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -92,7 +92,7 @@ static int gbaudio_module_disable(struct gbaudio_codec_info *codec, ret = -EINVAL; } if (ret) { - dev_err(codec->dev, "deactivate for %s failed:%d\n", + dev_err_ratelimited(codec->dev, "deactivate for %s failed:%d\n", module->name, ret); goto func_exit; } @@ -118,7 +118,7 @@ static int gbaudio_module_disable(struct gbaudio_codec_info *codec, ret = -EINVAL; } if (ret) { - dev_err(codec->dev, "unregister_cport for %s failed:%d\n", + dev_err_ratelimited(codec->dev, "unregister_cport for %s failed:%d\n", module->name, ret); goto func_exit; } @@ -195,7 +195,7 @@ static int gbaudio_module_enable(struct gbaudio_codec_info *codec, ret = -EINVAL; } if (ret) { - dev_err(codec->dev, "reg_cport for %s\n", module->name); + dev_err_ratelimited(codec->dev, "reg_cport for %s\n", module->name); goto func_exit; } module_state = GBAUDIO_CODEC_STARTUP; @@ -209,7 +209,7 @@ static int gbaudio_module_enable(struct gbaudio_codec_info *codec, ret = gb_audio_gb_set_pcm(module->mgmt_connection, data_cport, format, rate, channels, sig_bits); if (ret) { - dev_err(codec->dev, "set_pcm for %s\n", module->name); + dev_err_ratelimited(codec->dev, "set_pcm for %s\n", module->name); goto func_exit; } module_state = GBAUDIO_CODEC_HWPARAMS; @@ -226,7 +226,7 @@ static int gbaudio_module_enable(struct gbaudio_codec_info *codec, module->mgmt_connection, data_cport, 192); if (ret) { - dev_err(codec->dev, + dev_err_ratelimited(codec->dev, "set_rx_data_size for %s\n", module->name); goto func_exit; @@ -234,7 +234,7 @@ static int gbaudio_module_enable(struct gbaudio_codec_info *codec, ret = gb_audio_gb_activate_rx(module->mgmt_connection, data_cport); if (ret) { - dev_err(codec->dev, "activate_rx for %s\n", + dev_err_ratelimited(codec->dev, "activate_rx for %s\n", module->name); goto func_exit; } @@ -244,7 +244,7 @@ static int gbaudio_module_enable(struct gbaudio_codec_info *codec, module->mgmt_connection, data_cport, 192); if (ret) { - dev_err(codec->dev, + dev_err_ratelimited(codec->dev, "set_tx_data_size for %s\n", module->name); goto func_exit; @@ -252,7 +252,7 @@ static int gbaudio_module_enable(struct gbaudio_codec_info *codec, ret = gb_audio_gb_activate_tx(module->mgmt_connection, data_cport); if (ret) { - dev_err(codec->dev, "activate_tx for %s\n", + dev_err_ratelimited(codec->dev, "activate_tx for %s\n", module->name); goto func_exit; } @@ -579,7 +579,7 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream, ret = gb_audio_gb_set_pcm(module->mgmt_connection, data_cport, format, rate, channels, sig_bits); if (ret) { - dev_err(dai->dev, "%d: Error during set_pcm\n", ret); + dev_err_ratelimited(dai->dev, "%d: Error during set_pcm\n", ret); goto func_exit; } if (state < GBAUDIO_CODEC_HWPARAMS) { @@ -588,7 +588,7 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream, AUDIO_APBRIDGEA_PCM_RATE_48000, 6144000); if (ret) { - dev_err(dai->dev, + dev_err_ratelimited(dai->dev, "%d: Error during set_config\n", ret); goto func_exit; } @@ -619,7 +619,7 @@ static int gbmodule_prepare_tx(struct gbaudio_module_info *module, ret = gb_audio_gb_set_tx_data_size(module->mgmt_connection, data_cport, 192); if (ret) { - dev_err(dev, "%d:Error during set_tx_data_size, cport:%d\n", + dev_err_ratelimited(dev, "%d:Error during set_tx_data_size, cport:%d\n", ret, data_cport); return ret; } @@ -627,7 +627,7 @@ static int gbmodule_prepare_tx(struct gbaudio_module_info *module, ret = gb_audio_apbridgea_set_tx_data_size(data->connection, 0, 192); if (ret) { - dev_err(dev, + dev_err_ratelimited(dev, "%d:Error during apbridgea set_tx_data_size, cport\n", ret); return ret; @@ -636,7 +636,7 @@ static int gbmodule_prepare_tx(struct gbaudio_module_info *module, ret = gb_audio_gb_activate_tx(module->mgmt_connection, data_cport); if (ret) - dev_err(dev, "%s:Error during activate stream,%d\n", + dev_err_ratelimited(dev, "%s:Error during activate stream,%d\n", module->name, ret); return ret; @@ -654,7 +654,7 @@ static int gbmodule_prepare_rx(struct gbaudio_module_info *module, ret = gb_audio_gb_set_rx_data_size(module->mgmt_connection, data_cport, 192); if (ret) { - dev_err(dev, "%d:Error during set_rx_data_size, cport:%d\n", + dev_err_ratelimited(dev, "%d:Error during set_rx_data_size, cport:%d\n", ret, data_cport); return ret; } @@ -662,7 +662,7 @@ static int gbmodule_prepare_rx(struct gbaudio_module_info *module, ret = gb_audio_apbridgea_set_rx_data_size(data->connection, 0, 192); if (ret) { - dev_err(dev, + dev_err_ratelimited(dev, "%d:Error during apbridgea_set_rx_data_size\n", ret); return ret; @@ -671,7 +671,7 @@ static int gbmodule_prepare_rx(struct gbaudio_module_info *module, ret = gb_audio_gb_activate_rx(module->mgmt_connection, data_cport); if (ret) - dev_err(dev, "%s:Error during activate stream,%d\n", + dev_err_ratelimited(dev, "%s:Error during activate stream,%d\n", module->name, ret); return ret; @@ -820,7 +820,7 @@ static int gbcodec_trigger(struct snd_pcm_substream *substream, int cmd, } else ret = -EINVAL; if (ret) - dev_err(dai->dev, "%s:Error during %s stream:%d\n", + dev_err_ratelimited(dai->dev, "%s:Error during %s stream:%d\n", module->name, start ? "Start" : "Stop", ret); func_exit: -- cgit v0.10.2 From 44d6449350b866cbea613aabe5aba4aa640791cd Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Tue, 7 Jun 2016 21:33:54 -0700 Subject: greybus: kernel_ver.h: provide pwm_is_enabled() In the 4.7-rc1 kernel release, PWMF_ENABLED is removed and pwm_is_enabled() is the correct way to test if a pwm device is enabled, so provide a version of that function that will work on all older kernels and change the pwm.c driver to use it so that it will work on newer kernels as well. Tested: Tree now builds successfully against 3.14.y, 4.4.y, 4.5.y, 4.6.y, and 4.7-rc2 kernels Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index f6fb3bf..9819c3e 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -328,4 +328,11 @@ static inline void reinit_completion(struct completion *x) } #endif +#ifdef PWMF_ENABLED +static inline bool pwm_is_enabled(const struct pwm_device *pwm) +{ + return test_bit(PWMF_ENABLED, &pwm->flags); +} +#endif + #endif /* __GREYBUS_KERNEL_VER_H */ diff --git a/drivers/staging/greybus/pwm.c b/drivers/staging/greybus/pwm.c index b941cb5..71312323 100644 --- a/drivers/staging/greybus/pwm.c +++ b/drivers/staging/greybus/pwm.c @@ -132,7 +132,7 @@ static void gb_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) { struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); - if (test_bit(PWMF_ENABLED, &pwm->flags)) + if (pwm_is_enabled(pwm)) dev_warn(chip->dev, "freeing PWM device without disabling\n"); gb_pwm_deactivate_operation(pwmc, pwm->hwpwm); -- cgit v0.10.2 From 8fb76c3cfd5c54cb0d8713436d480a8062217d5c Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Wed, 8 Jun 2016 09:39:00 +0200 Subject: greybus: svc: pwrmon: validate svc protocol op status when getting rail names AP should check for Greybus SVC Protocol Operation Status to determine if the operation was successfully completed by the SVC Testing Done: - Successfully getting the rail names in the pwrmon_dummy sandbox branch Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Bartosz Golaszewski <bgolaszewski@baylibre.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 8125fb7..3c6415f 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -1145,6 +1145,7 @@ struct gb_svc_pwrmon_rail_count_get_response { #define GB_SVC_PWRMON_RAIL_NAME_BUFSIZE 32 struct gb_svc_pwrmon_rail_names_get_response { + __u8 status; __u8 name[0][GB_SVC_PWRMON_RAIL_NAME_BUFSIZE]; } __packed; diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index bfdd0ce..e2ab942 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -135,6 +135,13 @@ static int gb_svc_pwrmon_rail_names_get(struct gb_svc *svc, return ret; } + if (response->status != GB_SVC_OP_SUCCESS) { + dev_err(&svc->dev, + "SVC error while getting rail names: %u\n", + response->status); + return -EREMOTEIO; + } + return 0; } @@ -778,7 +785,8 @@ static void gb_svc_pwrmon_debugfs_init(struct gb_svc *svc) if (!rail_count || rail_count > GB_SVC_PWRMON_MAX_RAIL_COUNT) goto err_pwrmon_debugfs; - bufsize = GB_SVC_PWRMON_RAIL_NAME_BUFSIZE * rail_count; + bufsize = sizeof(*rail_names) + + GB_SVC_PWRMON_RAIL_NAME_BUFSIZE * rail_count; rail_names = kzalloc(bufsize, GFP_KERNEL); if (!rail_names) -- cgit v0.10.2 From 365d79fc20232dd730723801b7417cca9766dd79 Mon Sep 17 00:00:00 2001 From: Alex Elder <elder@linaro.org> Date: Wed, 8 Jun 2016 12:44:22 -0700 Subject: greybus: don't key on an enumerated constant The symbol PWMF_ENABLED is defined via an enum, which is not defined at the time the preprocessor passes through "kernel_ver.h". So we can't use it in an #if statement expression. Use the Linux kernel version instead. Change-Id: Id427224b1dfecfd886fcdae89c4bcf711b616439 Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index 9819c3e..fd5a6cc 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -328,7 +328,13 @@ static inline void reinit_completion(struct completion *x) } #endif -#ifdef PWMF_ENABLED +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0) +#include <linux/pwm.h> +/* + * pwm_is_enabled() was first defined in 4.2-rc1 (first commit!). + * PWMF_ENABLED was first defined in 3.5-rc2, but our code is + * always newer than that. +*/ static inline bool pwm_is_enabled(const struct pwm_device *pwm) { return test_bit(PWMF_ENABLED, &pwm->flags); -- cgit v0.10.2 From c0b06a6d4e07902f7e1eef88d242901c0a1faf03 Mon Sep 17 00:00:00 2001 From: Alex Elder <elder@linaro.org> Date: Wed, 8 Jun 2016 16:54:01 -0500 Subject: greybus: tracing: drop "greybus" prefix I posted this once before but it got rejected for fear it would not be clear which messages were related to Greybus. Every trace event currently defined for Greybus is recorded in a function whose name begins with "gb_". Every trace event reported in /sys/kernel/debug/tracing/trace includes the name of the function in which the event was recorded. Get rid of the "greybus: " prefix in all of the Greybus trace events. It just takes up precious space and is not actually helpful. Anyone actually enabling individual trace events should know enough about what they're doing to recognize which ones are being enabled. Signed-off-by: Alex Elder <elder@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h index 7249b8a..6f8692d 100644 --- a/drivers/staging/greybus/greybus_trace.h +++ b/drivers/staging/greybus/greybus_trace.h @@ -41,7 +41,7 @@ DECLARE_EVENT_CLASS(gb_message, __entry->result = message->header->result; ), - TP_printk("greybus: size=%hu operation_id=0x%04x type=0x%02x result=0x%02x", + TP_printk("size=%hu operation_id=0x%04x type=0x%02x result=0x%02x", __entry->size, __entry->operation_id, __entry->type, __entry->result) ); @@ -318,7 +318,7 @@ DECLARE_EVENT_CLASS(gb_interface, __entry->mode_switch = intf->mode_switch; ), - TP_printk("greybus: intf_id=%hhu device_id=%hhu module_id=%hhu D=%d J=%d A=%d E=%d M=%d", + TP_printk("intf_id=%hhu device_id=%hhu module_id=%hhu D=%d J=%d A=%d E=%d M=%d", __entry->id, __entry->device_id, __entry->module_id, __entry->disconnected, __entry->ejected, __entry->active, __entry->enabled, __entry->mode_switch) @@ -392,7 +392,7 @@ DECLARE_EVENT_CLASS(gb_module, __entry->disconnected = module->disconnected; ), - TP_printk("greybus: hd_bus_id=%d module_id=%hhu num_interfaces=%zu disconnected=%d", + TP_printk("hd_bus_id=%d module_id=%hhu num_interfaces=%zu disconnected=%d", __entry->hd_bus_id, __entry->module_id, __entry->num_interfaces, __entry->disconnected) ); @@ -445,7 +445,7 @@ DECLARE_EVENT_CLASS(gb_host_device, __entry->buffer_size_max = hd->buffer_size_max; ), - TP_printk("greybus: bus_id=%d num_cports=%zu mtu=%zu", + TP_printk("bus_id=%d num_cports=%zu mtu=%zu", __entry->bus_id, __entry->num_cports, __entry->buffer_size_max) ); -- cgit v0.10.2 From 82278bfea04c9cda1e01ac4fe41938cc3f5f1252 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Thu, 9 Jun 2016 18:42:19 +0200 Subject: greybus: fix forced disable of offloaded connections Core disables all connections for bundles whose interface is already gone in order to avoid unnecessary operation timeouts during driver disconnect. This isn't needed for offloaded connections (as the AP can not send requests over such connections), and in fact must not be done since only the bundle driver currently knows how to disable I/O on such connections in a class-specific way (this may eventually be handled by core though). Also add comment about why connection are disabled early on forced disconnect. Testing Done: Tested on EVT2. Reported-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Tested-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index c812906..5811299 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -189,7 +189,15 @@ static int greybus_remove(struct device *dev) struct gb_bundle *bundle = to_gb_bundle(dev); struct gb_connection *connection; + /* + * Disable (non-offloaded) connections early in case the interface is + * already gone to avoid unceccessary operation timeouts during + * driver disconnect. Otherwise, only disable incoming requests. + */ list_for_each_entry(connection, &bundle->connections, bundle_links) { + if (gb_connection_is_offloaded(connection)) + continue; + if (bundle->intf->disconnected) gb_connection_disable_forced(connection); else -- cgit v0.10.2 From cb14e97623d9289a30c3cfab02747581dda22f58 Mon Sep 17 00:00:00 2001 From: Gjorgji Rosikopulos <grosikopulos@mms-0359.ent.mm-sol.com> Date: Thu, 9 Jun 2016 11:53:15 +0300 Subject: greybus: camera: Add debug data format Add support for greybus debug data format. Greybus debug data format id is 0x42. Signed-off-by: Gjorgji Rosikopulos <grosikopulos@mm-sol.com> Acked-by: Laurent Pinchart <laurent.pinchart@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index d7cef2a..162cb7d 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -98,7 +98,11 @@ static const struct gb_camera_fmt_map mbus_to_gbus_format[] = { { .mbus_code = V4L2_MBUS_FMT_ARA_METADATA_1X8, .gb_format = 0x41, - } + }, + { + .mbus_code = V4L2_MBUS_FMT_ARA_DEBUG_DATA_1X8, + .gb_format = 0x42, + }, }; #define ES2_APB_CDSI0_CPORT 16 -- cgit v0.10.2 From 12e6895d1e343512990eec5ae8747b5968a8f8b8 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 9 Jun 2016 16:34:34 +0530 Subject: greybus: pwm: Fix compilation with v4.3 kernel pwm_is_enabled() wasn't enabled by v4.2-rc1, but it was based of v4.2-rc1. It was actually first included in v4.3. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index fd5a6cc..2a541fa 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -328,10 +328,10 @@ static inline void reinit_completion(struct completion *x) } #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0) #include <linux/pwm.h> /* - * pwm_is_enabled() was first defined in 4.2-rc1 (first commit!). + * pwm_is_enabled() was first defined in 4.3. * PWMF_ENABLED was first defined in 3.5-rc2, but our code is * always newer than that. */ -- cgit v0.10.2 From 9e50e987f55dc16364786525abdb4c7eac50e00b Mon Sep 17 00:00:00 2001 From: Marti Bolivar <mbolivar@leaflabs.com> Date: Thu, 9 Jun 2016 17:46:47 -0400 Subject: greybus: remove obsolete SVC result codes The "busy" SVC result codes are gone from the spec. Delete them. Testing Done: compile. Signed-off-by: Marti Bolivar <mbolivar@leaflabs.com> Reviewed-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 3c6415f..8b5563e 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -1036,7 +1036,7 @@ struct gb_svc_intf_vsys_request { struct gb_svc_intf_vsys_response { __u8 result_code; #define GB_SVC_INTF_VSYS_OK 0x00 -#define GB_SVC_INTF_VSYS_BUSY 0x01 + /* 0x01 is reserved */ #define GB_SVC_INTF_VSYS_FAIL 0x02 } __packed; @@ -1048,7 +1048,7 @@ struct gb_svc_intf_refclk_request { struct gb_svc_intf_refclk_response { __u8 result_code; #define GB_SVC_INTF_REFCLK_OK 0x00 -#define GB_SVC_INTF_REFCLK_BUSY 0x01 + /* 0x01 is reserved */ #define GB_SVC_INTF_REFCLK_FAIL 0x02 } __packed; @@ -1060,7 +1060,7 @@ struct gb_svc_intf_unipro_request { struct gb_svc_intf_unipro_response { __u8 result_code; #define GB_SVC_INTF_UNIPRO_OK 0x00 -#define GB_SVC_INTF_UNIPRO_BUSY 0x01 + /* 0x01 is reserved */ #define GB_SVC_INTF_UNIPRO_FAIL 0x02 #define GB_SVC_INTF_UNIPRO_NOT_OFF 0x03 } __packed; -- cgit v0.10.2 From aa62b5e49a596cad71a816fc36a4da6ad0c0cd0f Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 9 Jun 2016 16:34:35 +0530 Subject: greybus: bootrom: Compile as a separate module User space doesn't break anymore with new greybus modules and its time to make bootrom a separate module. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 981569d..40325b3 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -9,7 +9,6 @@ greybus-y := core.o \ control.o \ svc.o \ svc_watchdog.o \ - bootrom.o \ operation.o \ timesync.o \ timesync_platform.o @@ -31,6 +30,7 @@ gb-audio-gb-y := audio_gb.o gb-audio-apbridgea-y := audio_apbridgea.o gb-audio-manager-y += audio_manager.o gb-audio-manager-y += audio_manager_module.o +gb-bootrom-y := bootrom.o gb-camera-y := camera.o gb-firmware-y := fw-core.o fw-download.o fw-management.o gb-spilib-y := spilib.o @@ -62,6 +62,7 @@ endif obj-m += gb-audio-gb.o obj-m += gb-audio-apbridgea.o obj-m += gb-audio-manager.o +obj-m += gb-bootrom.o obj-m += gb-firmware.o obj-m += gb-spilib.o obj-m += gb-sdio.o diff --git a/drivers/staging/greybus/bootrom.c b/drivers/staging/greybus/bootrom.c index f375a87..2cebffa 100644 --- a/drivers/staging/greybus/bootrom.c +++ b/drivers/staging/greybus/bootrom.c @@ -12,7 +12,6 @@ #include <linux/mutex.h> #include <linux/workqueue.h> -#include "bootrom.h" #include "greybus.h" /* Timeout, in jiffies, within which the next request must be received */ @@ -455,12 +454,6 @@ static struct greybus_driver gb_bootrom_driver = { .id_table = gb_bootrom_id_table, }; -int gb_bootrom_init(void) -{ - return greybus_register(&gb_bootrom_driver); -} +module_greybus_driver(gb_bootrom_driver); -void gb_bootrom_exit(void) -{ - greybus_deregister(&gb_bootrom_driver); -} +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/greybus/bootrom.h b/drivers/staging/greybus/bootrom.h deleted file mode 100644 index fd2d193..0000000 --- a/drivers/staging/greybus/bootrom.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Greybus bootrom code - * - * Copyright 2016 Google Inc. - * Copyright 2016 Linaro Ltd. - * - * Released under the GPLv2 only. - */ - -#ifndef __BOOTROM_H -#define __BOOTROM_H - -int gb_bootrom_init(void); -void gb_bootrom_exit(void); - -#endif /* __BOOTROM_H */ diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 5811299..75bc608 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -10,7 +10,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define CREATE_TRACE_POINTS -#include "bootrom.h" #include "greybus.h" #include "greybus_trace.h" @@ -271,12 +270,6 @@ static int __init gb_init(void) goto error_operation; } - retval = gb_bootrom_init(); - if (retval) { - pr_err("gb_bootrom_init failed\n"); - goto error_bootrom; - } - retval = gb_timesync_init(); if (retval) { pr_err("gb_timesync_init failed\n"); @@ -285,8 +278,6 @@ static int __init gb_init(void) return 0; /* Success */ error_timesync: - gb_bootrom_exit(); -error_bootrom: gb_operation_exit(); error_operation: gb_hd_exit(); @@ -302,7 +293,6 @@ module_init(gb_init); static void __exit gb_exit(void) { gb_timesync_exit(); - gb_bootrom_exit(); gb_operation_exit(); gb_hd_exit(); bus_unregister(&greybus_bus_type); -- cgit v0.10.2 From 129a6fbe7648987b23a87d5d9c4fbf0780c528ed Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 9 Jun 2016 16:34:36 +0530 Subject: greybus: core: Make greybus_match_one_id() return bool This routine always returns 0 or 1 and a return type of 'bool' suits it the best. Update it. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 75bc608..a3837b2 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -31,22 +31,22 @@ int greybus_disabled(void) } EXPORT_SYMBOL_GPL(greybus_disabled); -static int greybus_match_one_id(struct gb_bundle *bundle, +static bool greybus_match_one_id(struct gb_bundle *bundle, const struct greybus_bundle_id *id) { if ((id->match_flags & GREYBUS_ID_MATCH_VENDOR) && (id->vendor != bundle->intf->vendor_id)) - return 0; + return false; if ((id->match_flags & GREYBUS_ID_MATCH_PRODUCT) && (id->product != bundle->intf->product_id)) - return 0; + return false; if ((id->match_flags & GREYBUS_ID_MATCH_CLASS) && (id->class != bundle->class)) - return 0; + return false; - return 1; + return true; } static const struct greybus_bundle_id * -- cgit v0.10.2 From 8a285fed1af3b9aae5e63ff3135fb9a0bf5d2c3c Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 9 Jun 2016 16:34:38 +0530 Subject: greybus: Use BIT(2) for GREYBUS_ID_MATCH_CLASS Bit 2 was left unused, use it. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_id.h b/drivers/staging/greybus/greybus_id.h index c91e7be..4bb1fc1 100644 --- a/drivers/staging/greybus/greybus_id.h +++ b/drivers/staging/greybus/greybus_id.h @@ -21,6 +21,6 @@ struct greybus_bundle_id { /* Used to match the greybus_bundle_id */ #define GREYBUS_ID_MATCH_VENDOR BIT(0) #define GREYBUS_ID_MATCH_PRODUCT BIT(1) -#define GREYBUS_ID_MATCH_CLASS BIT(3) +#define GREYBUS_ID_MATCH_CLASS BIT(2) #endif /* __LINUX_GREYBUS_ID_H */ -- cgit v0.10.2 From c05d471b2d6f4b9775674a3ada32a08079b1d24b Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 9 Jun 2016 16:34:39 +0530 Subject: greybus: Remove legacy suspend/resume callbacks We should be using the PM hooks available within the 'struct device_driver', instead of adding legacy suspend/resume callbacks. Remove them. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 154dfd1..dbc9be0 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -62,9 +62,6 @@ struct greybus_driver { const struct greybus_bundle_id *id); void (*disconnect)(struct gb_bundle *bundle); - int (*suspend)(struct gb_bundle *bundle, pm_message_t message); - int (*resume)(struct gb_bundle *bundle); - const struct greybus_bundle_id *id_table; struct device_driver driver; -- cgit v0.10.2 From 56278c7384a3c0242fe2f7ba91473c978ab500ae Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 9 Jun 2016 16:34:40 +0530 Subject: greybus: hd: Export host device tracepoint from hd.c There is no point keeping this code in core.c, while its only used by hd.c. Relocate it. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index a3837b2..dacc49c 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -13,11 +13,6 @@ #include "greybus.h" #include "greybus_trace.h" -EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_create); -EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_release); -EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_add); -EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_del); - /* Allow greybus to be disabled at boot if needed */ static bool nogreybus; #ifdef MODULE diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index 6d952ba..8ef849a 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -13,8 +13,12 @@ #include "greybus.h" #include "greybus_trace.h" -EXPORT_TRACEPOINT_SYMBOL_GPL(gb_message_submit); +EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_create); +EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_release); +EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_add); +EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_del); EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_in); +EXPORT_TRACEPOINT_SYMBOL_GPL(gb_message_submit); static struct ida gb_hd_bus_id_map; -- cgit v0.10.2 From 62e04623530c9a4312817438dea4859c549d01c1 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 9 Jun 2016 16:34:42 +0530 Subject: greybus: connection: Avoid unnecessary line breaks Some line breaks weren't required as we never crossed 80 columns, remove them. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 7def600..e0ee82f 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -288,8 +288,7 @@ static int gb_connection_hd_cport_enable(struct gb_connection *connection) ret = hd->driver->cport_enable(hd, connection->hd_cport_id); if (ret) { - dev_err(&hd->dev, - "%s: failed to enable host cport: %d\n", + dev_err(&hd->dev, "%s: failed to enable host cport: %d\n", connection->name, ret); return ret; } @@ -307,8 +306,7 @@ static void gb_connection_hd_cport_disable(struct gb_connection *connection) ret = hd->driver->cport_disable(hd, connection->hd_cport_id); if (ret) { - dev_err(&hd->dev, - "%s: failed to disable host cport: %d\n", + dev_err(&hd->dev, "%s: failed to disable host cport: %d\n", connection->name, ret); } } -- cgit v0.10.2 From 8c2522d87ab20ba245ddf92e4e8b19a76e5760fd Mon Sep 17 00:00:00 2001 From: Eli Sennesh <esennesh@leaflabs.com> Date: Fri, 3 Jun 2016 11:24:44 -0400 Subject: greybus: update UniPro Set Interface Power Mode operation to match spec Bring the gb_svc_intf_set_power_mode() up-to-date with the current Greybus specification. This largely involves adding more members to the structure sent across the wire. Also change the camera code to use the new operation properly, with default values passed for the new necessary arguments. The correctness of these default values is confirmed via testing and by asking Rob Johnson. We must make sure to zero the request structure sent across the wire, lest bite us most cruelly, and we fix by changing the Set Power Mode Response structure to use a __u8 rather than a __le16. Testing Done: Took a picture with a camera module, received error code when passing deliberately incorrect values for new parameters, got proper -EIO and Greybus result code printed when operation stopped halfway through. Could induce error by initializing request struct with random nonsense, and can stop it by initializing request struct with zeroes. Associated Firmware Changes: 1669-1671 on Android N Gerrit for SW-2945 Signed-off-by: Eli Sennesh <esennesh@leaflabs.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 162cb7d..ca1f498 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -128,17 +128,23 @@ static int gb_camera_set_intf_power_mode(struct gb_camera *gcam, u8 intf_id, ret = gb_svc_intf_set_power_mode(svc, intf_id, GB_SVC_UNIPRO_HS_SERIES_A, GB_SVC_UNIPRO_FAST_MODE, 2, 2, + GB_SVC_SMALL_AMPLITUDE, + GB_SVC_NO_DE_EMPHASIS, GB_SVC_UNIPRO_FAST_MODE, 2, 2, GB_SVC_PWRM_RXTERMINATION | - GB_SVC_PWRM_TXTERMINATION, 0); + GB_SVC_PWRM_TXTERMINATION, 0, + NULL, NULL); else ret = gb_svc_intf_set_power_mode(svc, intf_id, GB_SVC_UNIPRO_HS_SERIES_A, GB_SVC_UNIPRO_SLOW_AUTO_MODE, 2, 1, + GB_SVC_SMALL_AMPLITUDE, + GB_SVC_NO_DE_EMPHASIS, GB_SVC_UNIPRO_SLOW_AUTO_MODE, 2, 1, - 0, 0); + 0, 0, + NULL, NULL); return ret; } diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 8b5563e..63dd204 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -1100,6 +1100,13 @@ struct gb_svc_timesync_ping_response { #define GB_SVC_UNIPRO_HIBERNATE_MODE 0x11 #define GB_SVC_UNIPRO_OFF_MODE 0x12 +#define GB_SVC_SMALL_AMPLITUDE 0x01 +#define GB_SVC_LARGE_AMPLITUDE 0x02 + +#define GB_SVC_NO_DE_EMPHASIS 0x00 +#define GB_SVC_SMALL_DE_EMPHASIS 0x01 +#define GB_SVC_LARGE_DE_EMPHASIS 0x02 + #define GB_SVC_PWRM_RXTERMINATION 0x01 #define GB_SVC_PWRM_TXTERMINATION 0x02 #define GB_SVC_PWRM_LINE_RESET 0x04 @@ -1110,21 +1117,42 @@ struct gb_svc_timesync_ping_response { #define GB_SVC_UNIPRO_HS_SERIES_A 0x01 #define GB_SVC_UNIPRO_HS_SERIES_B 0x02 +#define GB_SVC_SETPWRM_PWR_OK 0x00 +#define GB_SVC_SETPWRM_PWR_LOCAL 0x01 +#define GB_SVC_SETPWRM_PWR_REMOTE 0x02 +#define GB_SVC_SETPWRM_PWR_BUSY 0x03 +#define GB_SVC_SETPWRM_PWR_ERROR_CAP 0x04 +#define GB_SVC_SETPWRM_PWR_FATAL_ERROR 0x05 + +struct gb_svc_l2_timer_cfg { + __le16 tsb_fc0_protection_timeout; + __le16 tsb_tc0_replay_timeout; + __le16 tsb_afc0_req_timeout; + __le16 tsb_fc1_protection_timeout; + __le16 tsb_tc1_replay_timeout; + __le16 tsb_afc1_req_timeout; + __le16 reserved_for_tc2[3]; + __le16 reserved_for_tc3[3]; +} __packed; + struct gb_svc_intf_set_pwrm_request { __u8 intf_id; __u8 hs_series; __u8 tx_mode; __u8 tx_gear; __u8 tx_nlanes; + __u8 tx_amplitude; + __u8 tx_hs_equalizer; __u8 rx_mode; __u8 rx_gear; __u8 rx_nlanes; __u8 flags; __le32 quirks; + struct gb_svc_l2_timer_cfg local_l2timerdata, remote_l2timerdata; } __packed; struct gb_svc_intf_set_pwrm_response { - __le16 result_code; + __u8 result_code; } __packed; struct gb_svc_key_event_request { diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index e2ab942..cee058f 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -616,23 +616,35 @@ void gb_svc_route_destroy(struct gb_svc *svc, u8 intf1_id, u8 intf2_id) int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series, u8 tx_mode, u8 tx_gear, u8 tx_nlanes, + u8 tx_amplitude, u8 tx_hs_equalizer, u8 rx_mode, u8 rx_gear, u8 rx_nlanes, - u8 flags, u32 quirks) + u8 flags, u32 quirks, + struct gb_svc_l2_timer_cfg *local, + struct gb_svc_l2_timer_cfg *remote) { struct gb_svc_intf_set_pwrm_request request; struct gb_svc_intf_set_pwrm_response response; int ret; + u16 result_code; + + memset(&request, 0, sizeof(request)); request.intf_id = intf_id; request.hs_series = hs_series; request.tx_mode = tx_mode; request.tx_gear = tx_gear; request.tx_nlanes = tx_nlanes; + request.tx_amplitude = tx_amplitude; + request.tx_hs_equalizer = tx_hs_equalizer; request.rx_mode = rx_mode; request.rx_gear = rx_gear; request.rx_nlanes = rx_nlanes; request.flags = flags; request.quirks = cpu_to_le32(quirks); + if (local) + request.local_l2timerdata = *local; + if (remote) + request.remote_l2timerdata = *remote; ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_INTF_SET_PWRM, &request, sizeof(request), @@ -640,7 +652,13 @@ int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series, if (ret < 0) return ret; - return le16_to_cpu(response.result_code); + result_code = response.result_code; + if (result_code != GB_SVC_SETPWRM_PWR_LOCAL) { + dev_err(&svc->dev, "set power mode = %d\n", result_code); + return -EIO; + } + + return 0; } EXPORT_SYMBOL_GPL(gb_svc_intf_set_power_mode); @@ -954,9 +972,11 @@ static void gb_svc_process_hello_deferred(struct gb_operation *operation) GB_SVC_UNIPRO_HS_SERIES_A, GB_SVC_UNIPRO_SLOW_AUTO_MODE, 2, 1, + GB_SVC_SMALL_AMPLITUDE, GB_SVC_NO_DE_EMPHASIS, GB_SVC_UNIPRO_SLOW_AUTO_MODE, 2, 1, - 0, 0); + 0, 0, + NULL, NULL); if (ret) dev_warn(&svc->dev, diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index 7a78c5b..dab8fba 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -79,8 +79,11 @@ int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, u32 value); int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series, u8 tx_mode, u8 tx_gear, u8 tx_nlanes, + u8 tx_amplitude, u8 tx_hs_equalizer, u8 rx_mode, u8 rx_gear, u8 rx_nlanes, - u8 flags, u32 quirks); + u8 flags, u32 quirks, + struct gb_svc_l2_timer_cfg *local, + struct gb_svc_l2_timer_cfg *remote); int gb_svc_ping(struct gb_svc *svc); int gb_svc_watchdog_create(struct gb_svc *svc); void gb_svc_watchdog_destroy(struct gb_svc *svc); -- cgit v0.10.2 From 27c243cf5fcf4b3bb525f1f3f15ed8db91199507 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Thu, 9 Jun 2016 09:30:39 +0530 Subject: greybus: Use mute_stream callback to initiate GB data xfer Currently trigger callback is used to start/stop greybus tx/rx path. This works well for almost all scenario except few specially handled usecases by Android Audio subsystem. In case of Music playback followed by Incoming ringtone, above layer tries to trigger_pause from one FE dailink and start a fresh playback via different FE dailink. Since, same BE dailink is used for both cases, an invalid state transition is requested i.e. from PAUSE->START. This fails & thus causes ringtone playback failure. With built-in codec, trigger callback is not required to initiate data xfer unlike gb-codec driver. This state transition should be handled in Android layer, but since it can lead to multiple side effects for various usecase we are trying to avoid trigger callback in gbcodec driver as well. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 975d2e8..3344693 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -731,54 +731,24 @@ func_exit: return ret; } -static int gbcodec_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) +static int gbcodec_mute_stream(struct snd_soc_dai *dai, int mute, int stream) { int ret; - int tx, rx, start, stop; struct gbaudio_data_connection *data; struct gbaudio_module_info *module; struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev); + + dev_dbg(dai->dev, "Mute:%d, Direction:%s\n", mute, + stream ? "CAPTURE":"PLAYBACK"); + mutex_lock(&codec->lock); if (list_empty(&codec->module_list)) { dev_err(codec->dev, "No codec module available\n"); mutex_unlock(&codec->lock); - if (cmd == SNDRV_PCM_TRIGGER_STOP) - return 0; return -ENODEV; } - tx = rx = start = stop = 0; - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - start = 1; - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - stop = 1; - break; - default: - dev_err(dai->dev, "Invalid tigger cmd:%d\n", cmd); - ret = -EINVAL; - goto func_exit; - } - - switch (substream->stream) { - case SNDRV_PCM_STREAM_CAPTURE: - rx = 1; - break; - case SNDRV_PCM_STREAM_PLAYBACK: - tx = 1; - break; - default: - dev_err(dai->dev, "Invalid stream type:%d\n", - substream->stream); - ret = -EINVAL; - goto func_exit; - } - list_for_each_entry(module, &codec->module_list, list) { /* find the dai */ data = find_data(module, dai->name); @@ -791,50 +761,43 @@ static int gbcodec_trigger(struct snd_pcm_substream *substream, int cmd, ret = -ENODEV; goto func_exit; } - if (start && tx) { + + if (!mute && !stream) {/* start playback */ ret = gb_audio_apbridgea_prepare_tx(data->connection, 0); if (!ret) ret = gb_audio_apbridgea_start_tx(data->connection, 0, 0); - codec->stream[substream->stream].state = GBAUDIO_CODEC_START; - } else if (start && rx) { + codec->stream[stream].state = GBAUDIO_CODEC_START; + } else if (!mute && stream) {/* start capture */ ret = gb_audio_apbridgea_prepare_rx(data->connection, 0); if (!ret) ret = gb_audio_apbridgea_start_rx(data->connection, 0); - codec->stream[substream->stream].state = GBAUDIO_CODEC_START; - } else if (stop && tx) { + codec->stream[stream].state = GBAUDIO_CODEC_START; + } else if (mute && !stream) {/* stop playback */ ret = gb_audio_apbridgea_stop_tx(data->connection, 0); if (!ret) ret = gb_audio_apbridgea_shutdown_tx(data->connection, 0); - codec->stream[substream->stream].state = GBAUDIO_CODEC_STOP; - } else if (stop && rx) { + codec->stream[stream].state = GBAUDIO_CODEC_STOP; + } else if (mute && stream) {/* stop capture */ ret = gb_audio_apbridgea_stop_rx(data->connection, 0); if (!ret) ret = gb_audio_apbridgea_shutdown_rx(data->connection, 0); - codec->stream[substream->stream].state = GBAUDIO_CODEC_STOP; + codec->stream[stream].state = GBAUDIO_CODEC_STOP; } else ret = -EINVAL; if (ret) - dev_err_ratelimited(dai->dev, "%s:Error during %s stream:%d\n", - module->name, start ? "Start" : "Stop", ret); + dev_err_ratelimited(dai->dev, + "%s:Error during %s %s stream:%d\n", + module->name, mute ? "Mute" : "Unmute", + stream ? "Capture" : "Playback", ret); func_exit: mutex_unlock(&codec->lock); - return ret; -} - -static int gbcodec_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) -{ - return 0; -} - -static int gbcodec_digital_mute(struct snd_soc_dai *dai, int mute) -{ return 0; } @@ -842,10 +805,8 @@ static struct snd_soc_dai_ops gbcodec_dai_ops = { .startup = gbcodec_startup, .shutdown = gbcodec_shutdown, .hw_params = gbcodec_hw_params, - .trigger = gbcodec_trigger, .prepare = gbcodec_prepare, - .set_fmt = gbcodec_set_dai_fmt, - .digital_mute = gbcodec_digital_mute, + .mute_stream = gbcodec_mute_stream, }; static int gbaudio_init_jack(struct gbaudio_module_info *module, -- cgit v0.10.2 From f2b6303d4505b5b046691a936c346a0e376cd9f3 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Thu, 9 Jun 2016 09:30:40 +0530 Subject: greybus: Remove apbridgea_shutdown_xx sequence if already done While reordering gb_deactivate sequence to avoid protocol error this was mistakenly added even during shutdown_tx/rx. It is supposed to be done immediately after stop_tx and only once. Fixes: 739f25d5f490 ("audio: Reorder gb_deactivate sequence to avoid protocol error") Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 3344693..2feac6b 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -396,12 +396,6 @@ static int gbmodule_shutdown_tx(struct gbaudio_module_info *module, return 0; } - if (codec_state == GBAUDIO_CODEC_STOP) { - ret = gb_audio_apbridgea_shutdown_tx(data->connection, 0); - if (ret) - return ret; - } - /* deactivate */ cportid = data->connection->intf_cport_id; if (module_state >= GBAUDIO_CODEC_PREPARE) { @@ -435,12 +429,6 @@ static int gbmodule_shutdown_rx(struct gbaudio_module_info *module, return 0; } - if (codec_state == GBAUDIO_CODEC_STOP) { - ret = gb_audio_apbridgea_shutdown_rx(data->connection, 0); - if (ret) - return ret; - } - /* deactivate */ cportid = data->connection->intf_cport_id; if (module_state >= GBAUDIO_CODEC_PREPARE) { -- cgit v0.10.2 From c6722ab5d3c3d23021dd32bd1ae569665ee2263b Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Fri, 10 Jun 2016 12:59:11 +0530 Subject: greybus: audio: Ratelimit err messages in bundle, topology driver Earlier I have shared a patch to rate limit err messages in audio_codec driver. However, missed to include suggestion from Mark to do similar changes in audio bundle & topology parser as well. Doing it now. Testing Done: Compile tested Fixes: 4cb3d109e5fc ("audio: Ratelimit err messages") Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_module.c b/drivers/staging/greybus/audio_module.c index 95d2dda..8100132 100644 --- a/drivers/staging/greybus/audio_module.c +++ b/drivers/staging/greybus/audio_module.c @@ -23,8 +23,9 @@ static int gbaudio_request_jack(struct gbaudio_module_info *module, { int report, button_status; - dev_warn(module->dev, "Jack Event received: type: %u, event: %u\n", - req->jack_attribute, req->event); + dev_warn_ratelimited(module->dev, + "Jack Event received: type: %u, event: %u\n", + req->jack_attribute, req->event); if (req->event == GB_AUDIO_JACK_EVENT_REMOVAL) { module->jack_type = 0; @@ -42,8 +43,9 @@ static int gbaudio_request_jack(struct gbaudio_module_info *module, report &= ~GBCODEC_JACK_MASK; report |= req->jack_attribute & GBCODEC_JACK_MASK; if (module->jack_type) - dev_warn(module->dev, "Modifying jack from %d to %d\n", - module->jack_type, report); + dev_warn_ratelimited(module->dev, + "Modifying jack from %d to %d\n", + module->jack_type, report); module->jack_type = report; snd_soc_jack_report(&module->headset_jack, report, GBCODEC_JACK_MASK); @@ -56,12 +58,14 @@ static int gbaudio_request_button(struct gbaudio_module_info *module, { int soc_button_id, report; - dev_warn(module->dev, "Button Event received: id: %u, event: %u\n", - req->button_id, req->event); + dev_warn_ratelimited(module->dev, + "Button Event received: id: %u, event: %u\n", + req->button_id, req->event); /* currently supports 4 buttons only */ if (!module->jack_type) { - dev_err(module->dev, "Jack not present. Bogus event!!\n"); + dev_err_ratelimited(module->dev, + "Jack not present. Bogus event!!\n"); return -EINVAL; } @@ -84,7 +88,8 @@ static int gbaudio_request_button(struct gbaudio_module_info *module, soc_button_id = SND_JACK_BTN_3; break; default: - dev_err(module->dev, "Invalid button request received\n"); + dev_err_ratelimited(module->dev, + "Invalid button request received\n"); return -EINVAL; } @@ -138,8 +143,8 @@ static int gbaudio_codec_request_handler(struct gb_operation *op) break; default: - dev_err(&connection->bundle->dev, - "Invalid Audio Event received\n"); + dev_err_ratelimited(&connection->bundle->dev, + "Invalid Audio Event received\n"); return -EINVAL; } diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index dfe120b..1e07686 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -173,8 +173,8 @@ static int gbcodec_mixer_ctl_get(struct snd_kcontrol *kcontrol, ret = gb_audio_gb_get_control(module->mgmt_connection, data->ctl_id, GB_AUDIO_INVALID_INDEX, &gbvalue); if (ret) { - dev_err(codec->dev, "%d:Error in %s for %s\n", ret, __func__, - kcontrol->id.name); + dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, + __func__, kcontrol->id.name); return ret; } @@ -253,8 +253,8 @@ static int gbcodec_mixer_ctl_put(struct snd_kcontrol *kcontrol, ret = gb_audio_gb_set_control(module->mgmt_connection, data->ctl_id, GB_AUDIO_INVALID_INDEX, &gbvalue); if (ret) { - dev_err(codec->dev, "%d:Error in %s for %s\n", ret, __func__, - kcontrol->id.name); + dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, + __func__, kcontrol->id.name); } return ret; @@ -335,8 +335,8 @@ static int gbcodec_mixer_dapm_ctl_get(struct snd_kcontrol *kcontrol, ret = gb_audio_gb_get_control(module->mgmt_connection, data->ctl_id, GB_AUDIO_INVALID_INDEX, &gbvalue); if (ret) { - dev_err(codec->dev, "%d:Error in %s for %s\n", ret, __func__, - kcontrol->id.name); + dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, + __func__, kcontrol->id.name); return ret; } /* update ucontrol */ @@ -393,9 +393,9 @@ static int gbcodec_mixer_dapm_ctl_put(struct snd_kcontrol *kcontrol, data->ctl_id, GB_AUDIO_INVALID_INDEX, &gbvalue); if (ret) { - dev_err(codec->dev, - "%d:Error in %s for %s\n", ret, __func__, - kcontrol->id.name); + dev_err_ratelimited(codec->dev, + "%d:Error in %s for %s\n", ret, + __func__, kcontrol->id.name); } } @@ -600,8 +600,9 @@ static int gbaudio_widget_event(struct snd_soc_dapm_widget *w, break; } if (ret) - dev_err(codec->dev, "%d: widget, event:%d failed:%d\n", wid, - event, ret); + dev_err_ratelimited(codec->dev, + "%d: widget, event:%d failed:%d\n", wid, + event, ret); return ret; } -- cgit v0.10.2 From 6db9cc68d7f9cea440293af4225a7b7f22d1d86d Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Fri, 10 Jun 2016 17:33:03 +0100 Subject: greybus: uart: Fix minor number leak On the gb_uart_remove() path we are forgetting to do a release_minor() leading to a minor number leak. This is a simple one-line fix. Tested on EVT 2.0 Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index d1611ab..7460bdbd 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -969,6 +969,7 @@ static void gb_uart_remove(struct gbphy_device *gbphy_dev) gb_connection_disable(connection); tty_port_destroy(&gb_tty->port); gb_connection_destroy(connection); + release_minor(gb_tty); kfifo_free(&gb_tty->write_fifo); kfree(gb_tty->buffer); kfree(gb_tty); -- cgit v0.10.2 From 4c2f8a48e989c323e4fb378f95ceaa8091760832 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Fri, 10 Jun 2016 16:10:12 +0100 Subject: greybus: timesync: Do 64 bit divisions in a 32 friendly way We need to use 'do_div()' when doing 64 bit division or modulo division since the kernel will not pull in the gcc builtins __aeabi_ldivmod and __aeabi_uldivmod on 32 bit builds. Reported-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/timesync.c b/drivers/staging/greybus/timesync.c index 87cbe10..a029fa0 100644 --- a/drivers/staging/greybus/timesync.c +++ b/drivers/staging/greybus/timesync.c @@ -502,8 +502,7 @@ static int gb_timesync_to_timespec(struct gb_timesync_svc *timesync_svc, u64 frame_time, struct timespec *ts) { unsigned long flags; - u64 delta_fs, counts; - u32 sec, nsec; + u64 delta_fs, counts, sec, nsec; bool add; int ret = 0; @@ -532,8 +531,15 @@ static int gb_timesync_to_timespec(struct gb_timesync_svc *timesync_svc, /* Determine the time difference in femtoseconds */ delta_fs = counts * gb_timesync_fs_per_clock; - sec = delta_fs / FSEC_PER_SEC; - nsec = (delta_fs % FSEC_PER_SEC) / 1000000UL; + + /* Convert to seconds */ + sec = delta_fs; + do_div(sec, NSEC_PER_SEC); + do_div(sec, 1000000UL); + + /* Get the nanosecond remainder */ + nsec = do_div(delta_fs, sec); + do_div(nsec, 1000000UL); if (add) { /* Add the calculated offset - overflow nanoseconds upwards */ @@ -548,7 +554,7 @@ static int gb_timesync_to_timespec(struct gb_timesync_svc *timesync_svc, if (nsec > timesync_svc->ktime_data.ts.tv_nsec) { sec++; nsec = nsec + timesync_svc->ktime_data.ts.tv_nsec; - nsec %= NSEC_PER_SEC; + nsec = do_div(nsec, NSEC_PER_SEC); } else { nsec = timesync_svc->ktime_data.ts.tv_nsec - nsec; } @@ -1318,8 +1324,10 @@ int __init gb_timesync_init(void) gb_timesync_clock_rate = gb_timesync_platform_get_clock_rate(); /* Calculate nanoseconds and femtoseconds per clock */ - gb_timesync_fs_per_clock = FSEC_PER_SEC / gb_timesync_clock_rate; - gb_timesync_ns_per_clock = NSEC_PER_SEC / gb_timesync_clock_rate; + gb_timesync_fs_per_clock = FSEC_PER_SEC; + do_div(gb_timesync_fs_per_clock, gb_timesync_clock_rate); + gb_timesync_ns_per_clock = NSEC_PER_SEC; + do_div(gb_timesync_ns_per_clock, gb_timesync_clock_rate); /* Calculate the maximum number of clocks we will convert to ktime */ gb_timesync_max_ktime_diff = -- cgit v0.10.2 From 6554efa28edc09029012f8217c5481ff320b7fca Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Fri, 10 Jun 2016 11:37:54 +0530 Subject: greybus: firmware: Fix spelling mistake s/directly/directory :) Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/firmware/firmware-management b/drivers/staging/greybus/Documentation/firmware/firmware-management index f70d3cd..bafe700 100644 --- a/drivers/staging/greybus/Documentation/firmware/firmware-management +++ b/drivers/staging/greybus/Documentation/firmware/firmware-management @@ -185,6 +185,6 @@ mtd0 mtd0ro Sample Application ------------------ -The current directly also provides a firmware.c test application, which can be +The current directory also provides a firmware.c test application, which can be referenced while developing userspace application to talk to firmware-management protocol. -- cgit v0.10.2 From 60fb3405c73ea0bbab942c699496123f9e987c04 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Fri, 10 Jun 2016 14:59:07 +0530 Subject: greybus: Remove extra blank lines This patch removes few blank lines across the repository at places where two blank lines were present together or when a blank line is present at the start or end of a routine. Note that this doesn't remove most of them from greybus_protocols.h as they were added on purpose. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 2feac6b..45e12b1 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -1164,7 +1164,6 @@ static struct snd_soc_codec_driver soc_codec_dev_gbaudio = { .ignore_pmdown_time = 1, }; - #ifdef CONFIG_PM static int gbaudio_codec_suspend(struct device *dev) { diff --git a/drivers/staging/greybus/audio_module.c b/drivers/staging/greybus/audio_module.c index 8100132..d87b998 100644 --- a/drivers/staging/greybus/audio_module.c +++ b/drivers/staging/greybus/audio_module.c @@ -221,7 +221,6 @@ static int gb_audio_probe(struct gb_bundle *bundle, int ret, i; struct gb_audio_topology *topology; - /* There should be at least one Management and one Data cport */ if (bundle->num_cports < 2) return -ENODEV; @@ -367,7 +366,6 @@ static void gb_audio_disconnect(struct gb_bundle *bundle) struct gbaudio_module_info *gbmodule = greybus_get_drvdata(bundle); struct gbaudio_data_connection *dai, *_dai; - /* cleanup module related resources first */ gbaudio_unregister_module(gbmodule); diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index 1e07686..1f9e8b6 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -872,7 +872,6 @@ static int gbaudio_tplg_process_routes(struct gbaudio_module_info *module, if (!dapm_routes) return -ENOMEM; - module->dapm_routes = dapm_routes; curr = routes; diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index c1c3d67..80f54c9 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -56,7 +56,6 @@ static ssize_t state_store(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR_RW(state); - static struct attribute *bundle_attrs[] = { &dev_attr_bundle_class.attr, &dev_attr_bundle_id.attr, diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index e0ee82f..28076d0 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -513,7 +513,6 @@ gb_connection_control_disconnected(struct gb_connection *connection) return; } - ret = gb_control_disconnected_operation(control, cport_id); if (ret) { dev_warn(&connection->bundle->dev, diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index f60cc1d..deae265 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -556,7 +556,6 @@ static void gb_gpio_irqchip_remove(struct gb_gpio_controller *ggc) } } - /** * gb_gpio_irqchip_add() - adds an irqchip to a gpio chip * @chip: the gpio chip to add the irqchip to diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index fd4a7e0..ca0c949 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -116,7 +116,6 @@ static int gb_hid_request_handler(struct gb_operation *op) return 0; } - static int gb_hid_report_len(struct hid_report *report) { return ((report->size - 1) >> 3) + 1 + diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c index 8d6570d..e96c24d 100644 --- a/drivers/staging/greybus/power_supply.c +++ b/drivers/staging/greybus/power_supply.c @@ -290,7 +290,6 @@ static int gb_power_supply_prop_descriptors_get(struct gb_power_supply *gbpsy) goto out_put_operation; } - /* Store available properties */ for (i = 0; i < gbpsy->properties_count; i++) { gbpsy->props[i].prop = resp->props[i].property; @@ -512,7 +511,6 @@ static int property_is_writeable(struct power_supply *b, return is_psy_prop_writeable(gbpsy, psp); } - #ifndef CORE_OWNS_PSY_STRUCT static int gb_power_supply_register(struct gb_power_supply *gbpsy) { @@ -562,7 +560,6 @@ static void _gb_power_supply_free(struct gb_power_supply *gbpsy) static void _gb_power_supply_release(struct gb_power_supply *gbpsy) { - gbpsy->update_interval = 0; cancel_delayed_work_sync(&gbpsy->work); diff --git a/drivers/staging/greybus/pwm.c b/drivers/staging/greybus/pwm.c index 71312323..1438b2e 100644 --- a/drivers/staging/greybus/pwm.c +++ b/drivers/staging/greybus/pwm.c @@ -80,7 +80,6 @@ static int gb_pwm_config_operation(struct gb_pwm_chip *pwmc, &request, sizeof(request), NULL, 0); } - static int gb_pwm_set_polarity_operation(struct gb_pwm_chip *pwmc, u8 which, u8 polarity) { diff --git a/drivers/staging/greybus/spilib.c b/drivers/staging/greybus/spilib.c index 79ae044..527909b 100644 --- a/drivers/staging/greybus/spilib.c +++ b/drivers/staging/greybus/spilib.c @@ -383,7 +383,6 @@ static void gb_spi_cleanup(struct spi_device *spi) /* Nothing to do for now */ } - /* Routines to get controller information */ /* diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index cee058f..d467ceb 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -44,7 +44,6 @@ static ssize_t ap_intf_id_show(struct device *dev, } static DEVICE_ATTR_RO(ap_intf_id); - // FIXME // This is a hack, we need to do this "right" and clean the interface up // properly, not just forcibly yank the thing out of the system and hope for the diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 7460bdbd..6260569 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -597,7 +597,6 @@ static void gb_tty_throttle(struct tty_struct *tty) gb_tty->ctrlout &= ~GB_UART_CTRL_RTS; retval = send_control(gb_tty, gb_tty->ctrlout); } - } static void gb_tty_unthrottle(struct tty_struct *tty) @@ -710,7 +709,6 @@ static int wait_serial_change(struct gb_tty *gb_tty, unsigned long arg) } while (!retval); return retval; - } static int get_serial_usage(struct gb_tty *gb_tty, @@ -924,7 +922,6 @@ static int gb_uart_probe(struct gbphy_device *gbphy_dev, goto exit_connection_disable; } - return 0; exit_connection_disable: -- cgit v0.10.2 From 54131222e6dc3a26de5cb036e599307666e58fd9 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Fri, 10 Jun 2016 14:59:09 +0530 Subject: greybus: connection: Return bool from gb_connection_intf_find() This is used only to check if an existing connection already uses the cport_id or not and doesn't really need to return pointer to the connection. While at it, also rename it to suit its purpose. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 28076d0..3cfc4dd 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -21,8 +21,7 @@ static DEFINE_MUTEX(gb_connection_mutex); /* Caller holds gb_connection_mutex. */ -static struct gb_connection * -gb_connection_intf_find(struct gb_interface *intf, u16 cport_id) +static bool gb_connection_cport_in_use(struct gb_interface *intf, u16 cport_id) { struct gb_host_device *hd = intf->hd; struct gb_connection *connection; @@ -30,10 +29,10 @@ gb_connection_intf_find(struct gb_interface *intf, u16 cport_id) list_for_each_entry(connection, &hd->connections, hd_links) { if (connection->intf == intf && connection->intf_cport_id == cport_id) - return connection; + return true; } - return NULL; + return false; } static void gb_connection_get(struct gb_connection *connection) @@ -155,7 +154,7 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, mutex_lock(&gb_connection_mutex); - if (intf && gb_connection_intf_find(intf, cport_id)) { + if (intf && gb_connection_cport_in_use(intf, cport_id)) { dev_err(&intf->dev, "cport %u already in use\n", cport_id); ret = -EBUSY; goto err_unlock; -- cgit v0.10.2 From d9e4c4ee12e490aca06a0a70d534c60648e2f43a Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 13 Jun 2016 15:08:01 +0530 Subject: greybus: camera: Initialize mutex before using it We are using the mutex from gb_camera_cleanup(), which can get called even before the mutex is initialized. Fix it by initializing the mutex early enough. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@linaro.org> Reviewed-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index ca1f498..0d20c6b 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -999,6 +999,7 @@ static int gb_camera_probe(struct gb_bundle *bundle, return -ENOMEM; gcam->bundle = bundle; + mutex_init(&gcam->mutex); conn = gb_connection_create(bundle, mgmt_cport_id, gb_camera_request_handler); @@ -1014,8 +1015,6 @@ static int gb_camera_probe(struct gb_bundle *bundle, if (ret) goto error; - mutex_init(&gcam->mutex); - /* * Create the data connection between the camera module data CPort and * APB CDSI1. The CDSI1 CPort ID is hardcoded by the ES2 bridge. -- cgit v0.10.2 From d1a8c36ec10446c3584033b06beaa51bad188144 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 13 Jun 2016 21:48:28 +0530 Subject: greybus: svc: disable connection after all its users are gone gb_svc_del() can be called during removal of gb-es2.ko module as well, and in that case we would like to properly shutdown all modules and interfaces as USB is still alive. This requires that we don't disable the svc connection, at least for tx, as that will be used while removing modules and interfaces. Disable only rx to begin with, as we shouldn't be handling any requests from the SVC. Disable tx only after all the users of svc connection are gone. Tested on EVT 2.0 by remove gb-es2.ko module. There are still few errors, specially while quiescing the connections (-22), but not that many. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index d467ceb..e316f08 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -1456,7 +1456,7 @@ static void gb_svc_remove_modules(struct gb_svc *svc) void gb_svc_del(struct gb_svc *svc) { - gb_connection_disable(svc->connection); + gb_connection_disable_rx(svc->connection); /* * The SVC device and input device may have been registered @@ -1473,6 +1473,8 @@ void gb_svc_del(struct gb_svc *svc) flush_workqueue(svc->wq); gb_svc_remove_modules(svc); + + gb_connection_disable(svc->connection); } void gb_svc_put(struct gb_svc *svc) -- cgit v0.10.2 From f3d5f6613f0da3ba1135f6e06b9692202fb9920b Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Date: Tue, 14 Jun 2016 15:59:23 +0300 Subject: greybus: camera: Clean up on stream configuration failure When the camera pipeline can't be configured due to a failure of one of the components (failure to start the CSI transmitter for instance), components that have already been setup for video streaming need to be set back to a quiescient state. This is especially important to ensure that a stream configuration failure won't keep the UniPro links in high speed mode forever. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Gjorgji Rosikopulos <grosikopulos@mm-sol.com> Tested-by: Gjorgji Rosikopulos <grosikopulos@mm-sol.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 0d20c6b..bbf54d7f 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -115,7 +115,7 @@ static const struct gb_camera_fmt_map mbus_to_gbus_format[] = { #define gcam_err(gcam, format...) dev_err(&gcam->bundle->dev, format) /* ----------------------------------------------------------------------------- - * Camera Protocol Operations + * Hardware Configuration */ static int gb_camera_set_intf_power_mode(struct gb_camera *gcam, u8 intf_id, @@ -173,6 +173,87 @@ static int gb_camera_set_power_mode(struct gb_camera *gcam, bool hs) return 0; } +struct ap_csi_config_request { + __u8 csi_id; + __u8 flags; +#define GB_CAMERA_CSI_FLAG_CLOCK_CONTINUOUS 0x01 + __u8 num_lanes; + __u8 padding; + __le32 bus_freq; + __le32 lines_per_second; +} __packed; + +static int gb_camera_setup_data_connection(struct gb_camera *gcam, + const struct gb_camera_configure_streams_response *resp, + struct gb_camera_csi_params *csi_params) +{ + struct ap_csi_config_request csi_cfg; + int ret; + + /* Set the UniPro link to high speed mode. */ + ret = gb_camera_set_power_mode(gcam, true); + if (ret < 0) + return ret; + + /* + * Configure the APB1 CSI transmitter using the lines count reported by + * the camera module, but with hard-coded bus frequency and lanes number. + * + * TODO: use the clocking and size informations reported by camera module + * to compute the required CSI bandwidth, and configure the CSI receiver + * on AP side, and the CSI transmitter on APB1 side accordingly. + */ + memset(&csi_cfg, 0, sizeof(csi_cfg)); + csi_cfg.csi_id = 1; + csi_cfg.flags = 0; + csi_cfg.num_lanes = resp->num_lanes; + csi_cfg.bus_freq = cpu_to_le32(960000000); + csi_cfg.lines_per_second = resp->lines_per_second; + + ret = gb_hd_output(gcam->connection->hd, &csi_cfg, + sizeof(csi_cfg), + GB_APB_REQUEST_CSI_TX_CONTROL, false); + + if (ret < 0) { + gcam_err(gcam, "failed to start the CSI transmitter\n"); + gb_camera_set_power_mode(gcam, false); + return ret; + } + + if (csi_params) { + csi_params->num_lanes = csi_cfg.num_lanes; + /* Transmitting two bits per cycle. (DDR clock) */ + csi_params->clk_freq = csi_cfg.bus_freq / 2; + csi_params->lines_per_second = csi_cfg.lines_per_second; + } + + return 0; +} + +static void gb_camera_teardown_data_connection(struct gb_camera *gcam) +{ + struct ap_csi_config_request csi_cfg; + int ret; + + /* Stop the APB1 CSI transmitter. */ + memset(&csi_cfg, 0, sizeof(csi_cfg)); + csi_cfg.csi_id = 1; + + ret = gb_hd_output(gcam->connection->hd, &csi_cfg, + sizeof(csi_cfg), + GB_APB_REQUEST_CSI_TX_CONTROL, false); + + if (ret < 0) + gcam_err(gcam, "failed to stop the CSI transmitter\n"); + + /* Set the UniPro link to low speed mode. */ + gb_camera_set_power_mode(gcam, false); +} + +/* ----------------------------------------------------------------------------- + * Camera Protocol Operations + */ + static int gb_camera_capabilities(struct gb_camera *gcam, u8 *capabilities, size_t *size) { @@ -211,16 +292,6 @@ done: return ret; } -struct ap_csi_config_request { - __u8 csi_id; - __u8 flags; -#define GB_CAMERA_CSI_FLAG_CLOCK_CONTINUOUS 0x01 - __u8 num_lanes; - __u8 padding; - __le32 bus_freq; - __le32 lines_per_second; -} __packed; - static int gb_camera_configure_streams(struct gb_camera *gcam, unsigned int *num_streams, unsigned int *flags, @@ -229,7 +300,6 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, { struct gb_camera_configure_streams_request *req; struct gb_camera_configure_streams_response *resp; - struct ap_csi_config_request csi_cfg; unsigned int nstreams = *num_streams; unsigned int i; @@ -315,50 +385,21 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, goto done; } - /* Setup unipro link speed. */ - ret = gb_camera_set_power_mode(gcam, nstreams != 0); - if (ret < 0) - goto done; - - /* - * Configure the APB1 CSI transmitter using the lines count reported by - * the camera module, but with hard-coded bus frequency and lanes number. - * - * TODO: use the clocking and size informations reported by camera module - * to compute the required CSI bandwidth, and configure the CSI receiver - * on AP side, and the CSI transmitter on APB1 side accordingly. - */ - memset(&csi_cfg, 0, sizeof(csi_cfg)); - - if (nstreams) { - csi_cfg.csi_id = 1; - csi_cfg.flags = 0; - csi_cfg.num_lanes = resp->num_lanes; - csi_cfg.bus_freq = cpu_to_le32(960000000); - csi_cfg.lines_per_second = resp->lines_per_second; - ret = gb_hd_output(gcam->connection->hd, &csi_cfg, - sizeof(csi_cfg), - GB_APB_REQUEST_CSI_TX_CONTROL, false); - if (csi_params) { - csi_params->num_lanes = csi_cfg.num_lanes; - /* Transmitting two bits per cycle. (DDR clock) */ - csi_params->clk_freq = csi_cfg.bus_freq / 2; - csi_params->lines_per_second = csi_cfg.lines_per_second; + if (resp->num_streams) { + ret = gb_camera_setup_data_connection(gcam, resp, csi_params); + if (ret < 0) { + memset(req, 0, sizeof(*req)); + gb_operation_sync(gcam->connection, + GB_CAMERA_TYPE_CONFIGURE_STREAMS, + req, req_size, resp, resp_size); + goto done; } } else { - csi_cfg.csi_id = 1; - ret = gb_hd_output(gcam->connection->hd, &csi_cfg, - sizeof(csi_cfg), - GB_APB_REQUEST_CSI_TX_CONTROL, false); + gb_camera_teardown_data_connection(gcam); } - if (ret < 0) - gcam_err(gcam, "failed to %s the CSI transmitter\n", - nstreams ? "start" : "stop"); - *flags = resp->flags; *num_streams = resp->num_streams; - ret = 0; done: mutex_unlock(&gcam->mutex); -- cgit v0.10.2 From 3b8ebfeb32daf13ef5fccb7ec3d163783e6a01a2 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Date: Tue, 14 Jun 2016 15:59:24 +0300 Subject: greybus: camera: Fix data connection setup When the module is in the configured state, an attempt to change the configuration must first tear down the data connection to update its parameters, as the APB1 bridge doesn't support modifying the CSI transmitter configuration when it is already started. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Gjorgji Rosikopulos <grosikopulos@mm-sol.com> Tested-by: Gjorgji Rosikopulos <grosikopulos@mm-sol.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index bbf54d7f..db7cdce 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -33,11 +33,17 @@ struct gb_camera_debugfs_buffer { size_t length; }; +enum gb_camera_state { + GB_CAMERA_STATE_UNCONFIGURED, + GB_CAMERA_STATE_CONFIGURED, +}; + /** * struct gb_camera - A Greybus Camera Device * @connection: the greybus connection for camera management * @data_connection: the greybus connection for camera data - * @mutex: protects the connection field + * @mutex: protects the connection and state fields + * @state: the current module state * @debugfs: debugfs entries for camera protocol operations testing * @module: Greybus camera module registered to HOST processor. */ @@ -45,7 +51,9 @@ struct gb_camera { struct gb_bundle *bundle; struct gb_connection *connection; struct gb_connection *data_connection; + struct mutex mutex; + enum gb_camera_state state; struct { struct dentry *root; @@ -300,7 +308,6 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, { struct gb_camera_configure_streams_request *req; struct gb_camera_configure_streams_response *resp; - unsigned int nstreams = *num_streams; unsigned int i; size_t req_size; @@ -385,6 +392,11 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, goto done; } + if (gcam->state == GB_CAMERA_STATE_CONFIGURED) { + gb_camera_teardown_data_connection(gcam); + gcam->state = GB_CAMERA_STATE_UNCONFIGURED; + } + if (resp->num_streams) { ret = gb_camera_setup_data_connection(gcam, resp, csi_params); if (ret < 0) { @@ -394,8 +406,8 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, req, req_size, resp, resp_size); goto done; } - } else { - gb_camera_teardown_data_connection(gcam); + + gcam->state = GB_CAMERA_STATE_CONFIGURED; } *flags = resp->flags; @@ -1039,9 +1051,11 @@ static int gb_camera_probe(struct gb_bundle *bundle, if (!gcam) return -ENOMEM; - gcam->bundle = bundle; mutex_init(&gcam->mutex); + gcam->bundle = bundle; + gcam->state = GB_CAMERA_STATE_UNCONFIGURED; + conn = gb_connection_create(bundle, mgmt_cport_id, gb_camera_request_handler); if (IS_ERR(conn)) { -- cgit v0.10.2 From 9120b9060bca4528d13de5c4e6522e6a78110704 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Date: Tue, 14 Jun 2016 15:59:25 +0300 Subject: greybus: camera: Create and destroy data connection on demand Creating the data connection at probe time makes it impossible to support multiple inserted camera modules as they would all try to establish a data connection to the same CPort on the AP side. Create and destroy the data connection when configuring the streams instead, as a single module can be streaming at a time. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Gjorgji Rosikopulos <grosikopulos@mm-sol.com> Tested-by: Gjorgji Rosikopulos <grosikopulos@mm-sol.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index db7cdce..0062f48 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -42,6 +42,7 @@ enum gb_camera_state { * struct gb_camera - A Greybus Camera Device * @connection: the greybus connection for camera management * @data_connection: the greybus connection for camera data + * @data_cport_id: the data CPort ID on the module side * @mutex: protects the connection and state fields * @state: the current module state * @debugfs: debugfs entries for camera protocol operations testing @@ -51,6 +52,7 @@ struct gb_camera { struct gb_bundle *bundle; struct gb_connection *connection; struct gb_connection *data_connection; + u16 data_cport_id; struct mutex mutex; enum gb_camera_state state; @@ -196,12 +198,30 @@ static int gb_camera_setup_data_connection(struct gb_camera *gcam, struct gb_camera_csi_params *csi_params) { struct ap_csi_config_request csi_cfg; + struct gb_connection *conn; int ret; + /* + * Create the data connection between the camera module data CPort and + * APB CDSI1. The CDSI1 CPort ID is hardcoded by the ES2 bridge. + */ + conn = gb_connection_create_offloaded(gcam->bundle, gcam->data_cport_id, + GB_CONNECTION_FLAG_NO_FLOWCTRL | + GB_CONNECTION_FLAG_CDSI1); + if (IS_ERR(conn)) + return PTR_ERR(conn); + + gcam->data_connection = conn; + gb_connection_set_data(conn, gcam); + + ret = gb_connection_enable(conn); + if (ret) + goto error_conn_destroy; + /* Set the UniPro link to high speed mode. */ ret = gb_camera_set_power_mode(gcam, true); if (ret < 0) - return ret; + goto error_conn_disable; /* * Configure the APB1 CSI transmitter using the lines count reported by @@ -224,8 +244,7 @@ static int gb_camera_setup_data_connection(struct gb_camera *gcam, if (ret < 0) { gcam_err(gcam, "failed to start the CSI transmitter\n"); - gb_camera_set_power_mode(gcam, false); - return ret; + goto error_power; } if (csi_params) { @@ -236,6 +255,15 @@ static int gb_camera_setup_data_connection(struct gb_camera *gcam, } return 0; + +error_power: + gb_camera_set_power_mode(gcam, false); +error_conn_disable: + gb_connection_disable(gcam->data_connection); +error_conn_destroy: + gb_connection_destroy(gcam->data_connection); + gcam->data_connection = NULL; + return ret; } static void gb_camera_teardown_data_connection(struct gb_camera *gcam) @@ -256,6 +284,11 @@ static void gb_camera_teardown_data_connection(struct gb_camera *gcam) /* Set the UniPro link to low speed mode. */ gb_camera_set_power_mode(gcam, false); + + /* Destroy the data connection. */ + gb_connection_disable(gcam->data_connection); + gb_connection_destroy(gcam->data_connection); + gcam->data_connection = NULL; } /* ----------------------------------------------------------------------------- @@ -990,13 +1023,13 @@ static void gb_camera_cleanup(struct gb_camera *gcam) { gb_camera_debugfs_cleanup(gcam); + mutex_lock(&gcam->mutex); if (gcam->data_connection) { gb_connection_disable(gcam->data_connection); gb_connection_destroy(gcam->data_connection); gcam->data_connection = NULL; } - mutex_lock(&gcam->mutex); if (gcam->connection) { gb_connection_disable(gcam->connection); gb_connection_destroy(gcam->connection); @@ -1055,6 +1088,7 @@ static int gb_camera_probe(struct gb_bundle *bundle, gcam->bundle = bundle; gcam->state = GB_CAMERA_STATE_UNCONFIGURED; + gcam->data_cport_id = data_cport_id; conn = gb_connection_create(bundle, mgmt_cport_id, gb_camera_request_handler); @@ -1070,24 +1104,6 @@ static int gb_camera_probe(struct gb_bundle *bundle, if (ret) goto error; - /* - * Create the data connection between the camera module data CPort and - * APB CDSI1. The CDSI1 CPort ID is hardcoded by the ES2 bridge. - */ - conn = gb_connection_create_offloaded(bundle, data_cport_id, - GB_CONNECTION_FLAG_NO_FLOWCTRL | - GB_CONNECTION_FLAG_CDSI1); - if (IS_ERR(conn)) { - ret = PTR_ERR(conn); - goto error; - } - gcam->data_connection = conn; - gb_connection_set_data(conn, gcam); - - ret = gb_connection_enable(conn); - if (ret) - goto error; - ret = gb_camera_debugfs_init(gcam); if (ret < 0) goto error; -- cgit v0.10.2 From 880bc0a4afa66e36f62e5687bef464a751781d55 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath <hiremath_vaibhav@projectara.com> Date: Wed, 15 Jun 2016 10:23:23 +0530 Subject: greybus: svc: Pass the correct pointer to input_free_device() In gb_svc_input_create() fn, on failure, wrong pointer was being passed to input_free_device(). Correct it. svc->input gets initialized only on successful return of this fn, so it is absolutely wrong to pass svc->input to input_free_device(). Testing Done: Tested on EVT2.0 platform. Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index e316f08..48d07a9 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -1352,7 +1352,7 @@ static struct input_dev *gb_svc_input_create(struct gb_svc *svc) return input_dev; err_free_input: - input_free_device(svc->input); + input_free_device(input_dev); return ERR_PTR(-ENOMEM); } -- cgit v0.10.2 From 42830f7f63c7db6422467d6c5c4480b2948b63ef Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Sat, 11 Jun 2016 08:01:01 +0530 Subject: greybus: manifest: Disallow reuse of control cport We should be checking if any of the bundles contains a CPort with its id set to the special value of '0', which is reserved for control CPort. Discard the bundle in that case. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 529a984..3d1592f 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -250,6 +250,13 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) if (cport_id > CPORT_ID_MAX) goto exit; + /* Nothing else should have its cport_id as control cport id */ + if (cport_id == GB_CONTROL_CPORT_ID) { + dev_err(&bundle->dev, "invalid cport id found (%02u)\n", + cport_id); + goto exit; + } + /* * Found one, move it to our temporary list after checking for * duplicates. -- cgit v0.10.2 From df124299d1d3e64175c79f83b4ecf2710d202e49 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 16 Jun 2016 10:03:57 +0530 Subject: greybus: firmware: Add license and copyright header to application Add license and copyright header to the firmware.c test application. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/firmware/firmware.c b/drivers/staging/greybus/Documentation/firmware/firmware.c index e367860..4a3782e 100644 --- a/drivers/staging/greybus/Documentation/firmware/firmware.c +++ b/drivers/staging/greybus/Documentation/firmware/firmware.c @@ -1,4 +1,55 @@ -/* Sample code to test firmware-management protocol */ +/* + * Sample code to test firmware-management protocol + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2016 Google Inc. All rights reserved. + * Copyright(c) 2016 Linaro Ltd. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details. + * + * BSD LICENSE + * + * Copyright(c) 2016 Google Inc. All rights reserved. + * Copyright(c) 2016 Linaro Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. or Linaro Ltd. nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * 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 GOOGLE INC. OR + * LINARO LTD. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #include <stdio.h> #include <string.h> -- cgit v0.10.2 From c9e8f893eeef4f0e2d10333aed2d175e50a56dab Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Thu, 16 Jun 2016 13:42:14 +0100 Subject: greybus: timesync: Do not hold mutex on cancel_delayed_work_sync There is a scenario where gb_timesync_svc_remove() can run, attain a mutex and call cancel_delayed_work_sync(). In the meantime a worker may already be running and trying to attain the same mutex but will never do so as the gb_timesync_svc_remove() path is holding the mutex and waiting on the delayed_work_sync() to complete - leading to deadlock. This patch addresses by calling the cancel_delayed_work_sync() before locking the relevant mutex. Reported-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Reviewed-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Tested-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/timesync.c b/drivers/staging/greybus/timesync.c index a029fa0..a9b6202 100644 --- a/drivers/staging/greybus/timesync.c +++ b/drivers/staging/greybus/timesync.c @@ -1065,6 +1065,8 @@ void gb_timesync_svc_remove(struct gb_svc *svc) if (!timesync_svc) goto done; + cancel_delayed_work_sync(×ync_svc->delayed_work); + mutex_lock(×ync_svc->mutex); gb_timesync_teardown(timesync_svc); @@ -1079,7 +1081,6 @@ void gb_timesync_svc_remove(struct gb_svc *svc) gb_timesync_set_state_atomic(timesync_svc, GB_TIMESYNC_STATE_INVALID); debugfs_remove(timesync_svc->frame_ktime_dentry); debugfs_remove(timesync_svc->frame_time_dentry); - cancel_delayed_work_sync(×ync_svc->delayed_work); destroy_workqueue(timesync_svc->work_queue); list_del(×ync_svc->list); -- cgit v0.10.2 From 0cc3bc6930d02ff5083b7b7bc18ca53299bb383a Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Thu, 16 Jun 2016 13:42:15 +0100 Subject: greybus: timesync: Fix transitions to the INACTIVE state Analysing a backtrace associated with the current EHCI runtime suspend code has highlighted several places where its perfectly valid to make a transition to GB_TIMESYNC_STATE_INACTIVE when not already in the GB_TIMESYNC_STATE_INIT state, for example failure to issue a TimeSync enable command to the SVC can and should legitimately call gb_timesync_teardown() - at this point the state will be GB_TIMESYNC_STATE_WAIT_SVC and it's legitimate and desirable to transition to the INACTIVE state in this case. This patch fixes by removing the restrictive and incorrect restriction on the transition to INACTIVE only being valid when state == GB_TIMESYNC_STATE_INIT. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Reviewed-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Tested-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/timesync.c b/drivers/staging/greybus/timesync.c index a9b6202..cc08b09 100644 --- a/drivers/staging/greybus/timesync.c +++ b/drivers/staging/greybus/timesync.c @@ -157,10 +157,8 @@ static void gb_timesync_set_state(struct gb_timesync_svc *timesync_svc, wake_up(×ync_svc->wait_queue); break; case GB_TIMESYNC_STATE_INACTIVE: - if (timesync_svc->state != GB_TIMESYNC_STATE_INIT) { - timesync_svc->state = state; - wake_up(×ync_svc->wait_queue); - } + timesync_svc->state = state; + wake_up(×ync_svc->wait_queue); break; case GB_TIMESYNC_STATE_INIT: if (timesync_svc->state != GB_TIMESYNC_STATE_INVALID) { -- cgit v0.10.2 From 93dbb97a3e2455cdb5efee17a497758ece4b8ed7 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Thu, 16 Jun 2016 13:42:16 +0100 Subject: greybus: timesync: Rework timesync removal serialization logic We need to make sure we adequately cancel and quiesce any scheduled TimeSync synchronization operations in the case of greybus.ko being yanked out of memory i.e. when doing an EHCI runtime suspend or just a plain rmmod. The scenario is a new TimeSync sync operation has been scheduled. Next gb_timesync_svc_remove() runs. In this case we should terminate any scheduled work, terminate our ktime tracking timer and state transition to GB_TIMESYNC_STATE_INVALID to ensure no other context may schedule any new TimeSync operations. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Reviewed-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/timesync.c b/drivers/staging/greybus/timesync.c index cc08b09..b9b29f5 100644 --- a/drivers/staging/greybus/timesync.c +++ b/drivers/staging/greybus/timesync.c @@ -1067,8 +1067,9 @@ void gb_timesync_svc_remove(struct gb_svc *svc) mutex_lock(×ync_svc->mutex); - gb_timesync_teardown(timesync_svc); + gb_timesync_set_state_atomic(timesync_svc, GB_TIMESYNC_STATE_INVALID); del_timer_sync(×ync_svc->ktime_timer); + gb_timesync_teardown(timesync_svc); gb_timesync_hd_remove(timesync_svc, svc->hd); list_for_each_entry_safe(timesync_interface, next, @@ -1076,7 +1077,6 @@ void gb_timesync_svc_remove(struct gb_svc *svc) list_del(×ync_interface->list); kfree(timesync_interface); } - gb_timesync_set_state_atomic(timesync_svc, GB_TIMESYNC_STATE_INVALID); debugfs_remove(timesync_svc->frame_ktime_dentry); debugfs_remove(timesync_svc->frame_time_dentry); destroy_workqueue(timesync_svc->work_queue); -- cgit v0.10.2 From 4ee48a5ecb7a3af272ac2c6cd6a0865b95a3d5f2 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Wed, 15 Jun 2016 15:58:22 +0530 Subject: greybus: firmware: prefix char-device with 'gb-' This will make it consistent with any other character devices we have for greybus and let us identify greybus character devices easily. Compiled tested only. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/firmware/firmware-management b/drivers/staging/greybus/Documentation/firmware/firmware-management index bafe700..7997739 100644 --- a/drivers/staging/greybus/Documentation/firmware/firmware-management +++ b/drivers/staging/greybus/Documentation/firmware/firmware-management @@ -49,14 +49,14 @@ Sysfs Interfaces - Firmware Management The Firmware Management Protocol interacts with Userspace using the character device interface. The character device will be present in /dev/ directory -and will be named fw-mgmt-<N>. The number <N> is assigned at runtime. +and will be named gb-fw-mgmt-<N>. The number <N> is assigned at runtime. Identifying the Character Device ================================ -There can be multiple devices present in /dev/ directory with name fw-mgmt-N and -user first needs to identify the character device used for firmware-management -for a particular interface. +There can be multiple devices present in /dev/ directory with name gb-fw-mgmt-N +and user first needs to identify the character device used for +firmware-management for a particular interface. The Firmware Management core creates a device of class 'gb_fw_mgmt', which shall be used by the user to identify the right character device for it. The class @@ -64,17 +64,17 @@ device is created within the Bundle directory for a particular Interface. For example this is how the class-device can be present: -/sys/bus/greybus/devices/1-1/1-1.1/1-1.1.1/gb_fw_mgmt/fw-mgmt-0 +/sys/bus/greybus/devices/1-1/1-1.1/1-1.1.1/gb_fw_mgmt/gb-fw-mgmt-0 -The last name in this path: fw-mgmt-0 is precisely the name of the char device -and so the device in this case will be: +The last name in this path: gb-fw-mgmt-0 is precisely the name of the char +device and so the device in this case will be: -/dev/fw-mgmt-0. +/dev/gb-fw-mgmt-0. Operations on the Char device ============================= -The Character device (fw-mgmt-0 in example) can be opened by the userspace +The Character device (gb-fw-mgmt-0 in example) can be opened by the userspace application and it can perform various 'ioctl' operations on the device. The device doesn't support any read/write operations. diff --git a/drivers/staging/greybus/Documentation/firmware/firmware.c b/drivers/staging/greybus/Documentation/firmware/firmware.c index 4a3782e..3c305f7 100644 --- a/drivers/staging/greybus/Documentation/firmware/firmware.c +++ b/drivers/staging/greybus/Documentation/firmware/firmware.c @@ -74,7 +74,7 @@ int main(int argc, char *argv[]) /* Make sure arguments are correct */ if (argc != 2) { - printf("\nUsage: ./firmware <Path of the fw-mgmt-X dev>\n"); + printf("\nUsage: ./firmware <Path of the gb-fw-mgmt-X dev>\n"); return 0; } diff --git a/drivers/staging/greybus/fw-management.c b/drivers/staging/greybus/fw-management.c index c9c28fc..ccd9d7c 100644 --- a/drivers/staging/greybus/fw-management.c +++ b/drivers/staging/greybus/fw-management.c @@ -599,7 +599,7 @@ int gb_fw_mgmt_connection_init(struct gb_connection *connection) /* Add a soft link to the previously added char-dev within the bundle */ fw_mgmt->class_device = device_create(fw_mgmt_class, fw_mgmt->parent, fw_mgmt->dev_num, NULL, - "fw-mgmt-%d", minor); + "gb-fw-mgmt-%d", minor); if (IS_ERR(fw_mgmt->class_device)) { ret = PTR_ERR(fw_mgmt->class_device); goto err_del_cdev; -- cgit v0.10.2 From 0698be0281e915ac42235b711f35465e8e14785b Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Wed, 15 Jun 2016 08:25:56 +0530 Subject: greybus: connection: add trace events before disabling connection This is what we are doing elsewhere: - Send enable/create trace events after enabling/creating stuff. - Send disable/remove trace events before disabling/removing stuff. This wasn't followed in a same way while disabling connections. Fix it. Compile tested. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 3cfc4dd..3a17db9 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -790,6 +790,8 @@ void gb_connection_disable(struct gb_connection *connection) if (connection->state == GB_CONNECTION_STATE_DISABLED) goto out_unlock; + trace_gb_connection_disable(connection); + gb_connection_control_disconnecting(connection); spin_lock_irq(&connection->lock); @@ -808,8 +810,6 @@ void gb_connection_disable(struct gb_connection *connection) connection->state = GB_CONNECTION_STATE_DISABLED; - trace_gb_connection_disable(connection); - /* control-connection tear down is deferred when mode switching */ if (!connection->mode_switch) { gb_connection_svc_connection_destroy(connection); @@ -829,6 +829,8 @@ void gb_connection_disable_forced(struct gb_connection *connection) if (connection->state == GB_CONNECTION_STATE_DISABLED) goto out_unlock; + trace_gb_connection_disable(connection); + spin_lock_irq(&connection->lock); connection->state = GB_CONNECTION_STATE_DISABLED; gb_connection_cancel_operations(connection, -ESHUTDOWN); @@ -839,8 +841,6 @@ void gb_connection_disable_forced(struct gb_connection *connection) gb_connection_svc_connection_destroy(connection); gb_connection_hd_cport_disable(connection); - trace_gb_connection_disable(connection); - out_unlock: mutex_unlock(&connection->mutex); } -- cgit v0.10.2 From e3b090ea954ed6f8de295511b4e533e2ef425a0f Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva <rui.silva@linaro.org> Date: Tue, 21 Jun 2016 16:56:16 +0100 Subject: greybus: sdio: avoid extra memory operation at data transfer Right now greybus sdio uses the greybus operation_sync to transfer data, this will imply an extra memcpy at greybus core that we can avoid. Also with this change we remove the need for an extra buffer to store intermediate copy. So, let us create the operation and do the memory operations in the sdio driver. Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index a270517..8d2de7d 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -24,7 +24,6 @@ struct gb_sdio_host { struct mmc_request *mrq; struct mutex lock; /* lock for this host */ size_t data_max; - void *xfer_buffer; spinlock_t xfer; /* lock to cancel ongoing transfer */ bool xfer_stop; struct workqueue_struct *mrq_workqueue; @@ -245,7 +244,8 @@ static int _gb_sdio_send(struct gb_sdio_host *host, struct mmc_data *data, size_t len, u16 nblocks, off_t skip) { struct gb_sdio_transfer_request *request; - struct gb_sdio_transfer_response response; + struct gb_sdio_transfer_response *response; + struct gb_operation *operation; struct scatterlist *sg = data->sg; unsigned int sg_len = data->sg_len; size_t copied; @@ -255,39 +255,51 @@ static int _gb_sdio_send(struct gb_sdio_host *host, struct mmc_data *data, WARN_ON(len > host->data_max); - request = host->xfer_buffer; + operation = gb_operation_create(host->connection, GB_SDIO_TYPE_TRANSFER, + len + sizeof(*request), + sizeof(*response), GFP_KERNEL); + if (!operation) + return -ENOMEM; + + request = operation->request->payload; request->data_flags = (data->flags >> 8); request->data_blocks = cpu_to_le16(nblocks); request->data_blksz = cpu_to_le16(data->blksz); copied = sg_pcopy_to_buffer(sg, sg_len, &request->data[0], len, skip); - if (copied != len) - return -EINVAL; + if (copied != len) { + ret = -EINVAL; + goto err_put_operation; + } - ret = gb_operation_sync(host->connection, GB_SDIO_TYPE_TRANSFER, - request, len + sizeof(*request), - &response, sizeof(response)); + ret = gb_operation_request_send_sync(operation); if (ret < 0) - return ret; + goto err_put_operation; - send_blocks = le16_to_cpu(response.data_blocks); - send_blksz = le16_to_cpu(response.data_blksz); + response = operation->response->payload; + + send_blocks = le16_to_cpu(response->data_blocks); + send_blksz = le16_to_cpu(response->data_blksz); if (len != send_blksz * send_blocks) { dev_err(mmc_dev(host->mmc), "send: size received: %zu != %d\n", len, send_blksz * send_blocks); - return -EINVAL; + ret = -EINVAL; } +err_put_operation: + gb_operation_put(operation); + return ret; } static int _gb_sdio_recv(struct gb_sdio_host *host, struct mmc_data *data, size_t len, u16 nblocks, off_t skip) { - struct gb_sdio_transfer_request request; + struct gb_sdio_transfer_request *request; struct gb_sdio_transfer_response *response; + struct gb_operation *operation; struct scatterlist *sg = data->sg; unsigned int sg_len = data->sg_len; size_t copied; @@ -297,33 +309,41 @@ static int _gb_sdio_recv(struct gb_sdio_host *host, struct mmc_data *data, WARN_ON(len > host->data_max); - request.data_flags = (data->flags >> 8); - request.data_blocks = cpu_to_le16(nblocks); - request.data_blksz = cpu_to_le16(data->blksz); + operation = gb_operation_create(host->connection, GB_SDIO_TYPE_TRANSFER, + sizeof(*request), + len + sizeof(*response), GFP_KERNEL); + if (!operation) + return -ENOMEM; - response = host->xfer_buffer; + request = operation->request->payload; + request->data_flags = (data->flags >> 8); + request->data_blocks = cpu_to_le16(nblocks); + request->data_blksz = cpu_to_le16(data->blksz); - ret = gb_operation_sync(host->connection, GB_SDIO_TYPE_TRANSFER, - &request, sizeof(request), response, len + - sizeof(*response)); + ret = gb_operation_request_send_sync(operation); if (ret < 0) - return ret; + goto err_put_operation; + response = operation->response->payload; recv_blocks = le16_to_cpu(response->data_blocks); recv_blksz = le16_to_cpu(response->data_blksz); if (len != recv_blksz * recv_blocks) { dev_err(mmc_dev(host->mmc), "recv: size received: %d != %zu\n", recv_blksz * recv_blocks, len); - return -EINVAL; + ret = -EINVAL; + goto err_put_operation; } copied = sg_pcopy_from_buffer(sg, sg_len, &response->data[0], len, skip); if (copied != len) - return -EINVAL; + ret = -EINVAL; - return 0; +err_put_operation: + gb_operation_put(operation); + + return ret; } static int gb_sdio_transfer(struct gb_sdio_host *host, struct mmc_data *data) @@ -720,7 +740,6 @@ static int gb_sdio_probe(struct gbphy_device *gbphy_dev, struct gb_connection *connection; struct mmc_host *mmc; struct gb_sdio_host *host; - size_t max_buffer; int ret = 0; mmc = mmc_alloc_host(sizeof(*host), &gbphy_dev->dev); @@ -760,19 +779,13 @@ static int gb_sdio_probe(struct gbphy_device *gbphy_dev, mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; - max_buffer = gb_operation_get_payload_size_max(host->connection); - host->xfer_buffer = kzalloc(max_buffer, GFP_KERNEL); - if (!host->xfer_buffer) { - ret = -ENOMEM; - goto exit_connection_disable; - } mutex_init(&host->lock); spin_lock_init(&host->xfer); host->mrq_workqueue = alloc_workqueue("mmc-%s", 0, 1, dev_name(&gbphy_dev->dev)); if (!host->mrq_workqueue) { ret = -ENOMEM; - goto exit_buf_free; + goto exit_connection_disable; } INIT_WORK(&host->mrqwork, gb_sdio_mrq_work); @@ -791,8 +804,6 @@ static int gb_sdio_probe(struct gbphy_device *gbphy_dev, exit_wq_destroy: destroy_workqueue(host->mrq_workqueue); -exit_buf_free: - kfree(host->xfer_buffer); exit_connection_disable: gb_connection_disable(connection); exit_connection_destroy: @@ -821,7 +832,6 @@ static void gb_sdio_remove(struct gbphy_device *gbphy_dev) mmc_remove_host(mmc); gb_connection_disable(connection); gb_connection_destroy(connection); - kfree(host->xfer_buffer); mmc_free_host(mmc); } -- cgit v0.10.2 From 2d533cf16bffc579b03f8e376b2f01f09a092aeb Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Date: Tue, 21 Jun 2016 23:28:02 +0530 Subject: greybus: ratelimit errors usually seen on unipro_reset It is believed that excessive serial messages from greybus on suspend/resume is leading to watchdog bite. There is still discussion going on whether ratelimiting prints would really fix anything, except it may reduce traffic on serial console and probably bring out real issues in the front. So in order to meet the alpha requirement, we all decided to get ratelimit change "as a TEMP fix" and decide later whether we should revert back once we get proper suspend/resume implementation. Please follow the discussion on Jira card SW-6261. Testing Done: Build tested against ara/main branch. Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Reviewed-by: Konstantin Buhchev <buhchev_konstantin@projectara.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index bdf5024..426f83e 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -473,7 +473,7 @@ static int message_send(struct gb_host_device *hd, u16 cport_id, retval = usb_submit_urb(urb, gfp_mask); if (retval) { - dev_err(&udev->dev, "failed to submit out-urb: %d\n", retval); + dev_err_ratelimited(&udev->dev, "failed to submit out-urb: %d\n", retval); spin_lock_irqsave(&es2->cport_out_urb_lock, flags); message->hcpriv = NULL; diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 659e84b..1367070 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -1127,7 +1127,7 @@ int gb_operation_sync_timeout(struct gb_connection *connection, int type, ret = gb_operation_request_send_sync_timeout(operation, timeout); if (ret) { - dev_err(&connection->hd->dev, + dev_err_ratelimited(&connection->hd->dev, "%s: synchronous operation of type 0x%02x failed: %d\n", connection->name, type, ret); } else { -- cgit v0.10.2 From c13a206f7e44d8bb207512dfe58677674e514833 Mon Sep 17 00:00:00 2001 From: Michael Scott <michael.scott@linaro.org> Date: Tue, 21 Jun 2016 16:41:46 -0700 Subject: greybus: adjust kernel version check for led_sysfs_is_disabled When building greybus against a 3.18 kernel the following error is generated: light.c:205:9: error: implicit declaration of function 'led_sysfs_is_disabled' [-Werror=implicit-function-declaration] led_sysfs_is_disabled was not added until 3.19 kernel cycle Verification: https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/tree/include/linux/leds.h?h=linux-3.18.y (no function led_sysfs_is_disabled defined here) Testing Done: - Successfully built greybus for 3.18 kernel Signed-off-by: Michael Scott <michael.scott@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index 2a541fa..98e3179 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -276,7 +276,7 @@ static inline size_t sg_pcopy_from_buffer(struct scatterlist *sgl, #define LED_HAVE_SET_BLOCKING #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) /* * From this version upper it was introduced the possibility to disable led * sysfs entries to handle control of the led device to v4l2, which was -- cgit v0.10.2 From 05e3095563670ab9188eab2c38808e9fd1f3a99d Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 23 Jun 2016 23:22:15 +0530 Subject: greybus: Revert "greybus: ratelimit errors usually seen on unipro_reset" This reverts commit 9b891f4fda8dfd6c1d8dc16479c5f6d418a9ccc7. We discussed this over the other thread, [PATCH 0/2] Improve watchdog's implementation a bit, and decided that we shouldn't be trying to hide the watchdog reboot problem by using such patches, rather we should make sure they occur consistently so that the real problem can be fixed. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 426f83e..bdf5024 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -473,7 +473,7 @@ static int message_send(struct gb_host_device *hd, u16 cport_id, retval = usb_submit_urb(urb, gfp_mask); if (retval) { - dev_err_ratelimited(&udev->dev, "failed to submit out-urb: %d\n", retval); + dev_err(&udev->dev, "failed to submit out-urb: %d\n", retval); spin_lock_irqsave(&es2->cport_out_urb_lock, flags); message->hcpriv = NULL; diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 1367070..659e84b 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -1127,7 +1127,7 @@ int gb_operation_sync_timeout(struct gb_connection *connection, int type, ret = gb_operation_request_send_sync_timeout(operation, timeout); if (ret) { - dev_err_ratelimited(&connection->hd->dev, + dev_err(&connection->hd->dev, "%s: synchronous operation of type 0x%02x failed: %d\n", connection->name, type, ret); } else { -- cgit v0.10.2 From 5e2b63915cb6f1e86f9515342cfcfb28cd82c5b0 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 23 Jun 2016 23:23:06 +0530 Subject: greybus: don't use spin_lock_irq() spin_[un]lock_irq() routines should be used carefully as they things can go wrong, if they are mixed with spin_lock_irqsave() or other variants. The main problem is that spin_[un]lock_irq() routines doesn't check if the IRQs are already disabled/enabled on the local CPU and so spin_unlock_irq() will forcefully enable interrupts for example. This may not work well, if some other code was relying on interrupts being disabled. Use spin_lock_irqsave() and spin_unlock_restore() instead. This patch doesn't claim that it fixes the JIRA completely, but the issue was harder to reproduce for some iterations after this, which was quite easy to reproduce earlier on. Tested on EVT 2.0 with lots of debug patches to kernel and greybus. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Jeffrey Carlyle <jcarlyle@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 3a17db9..0132e36 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -150,6 +150,7 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, unsigned long flags) { struct gb_connection *connection; + unsigned long irqflags; int ret; mutex_lock(&gb_connection_mutex); @@ -200,7 +201,7 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, gb_connection_init_name(connection); - spin_lock_irq(&gb_connections_lock); + spin_lock_irqsave(&gb_connections_lock, irqflags); list_add(&connection->hd_links, &hd->connections); if (bundle) @@ -208,7 +209,7 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, else INIT_LIST_HEAD(&connection->bundle_links); - spin_unlock_irq(&gb_connections_lock); + spin_unlock_irqrestore(&gb_connections_lock, irqflags); mutex_unlock(&gb_connection_mutex); @@ -571,7 +572,7 @@ static int gb_connection_ping(struct gb_connection *connection) * DISCONNECTING. */ static void gb_connection_cancel_operations(struct gb_connection *connection, - int errno) + int errno, unsigned long flags) __must_hold(&connection->lock) { struct gb_operation *operation; @@ -580,7 +581,7 @@ static void gb_connection_cancel_operations(struct gb_connection *connection, operation = list_last_entry(&connection->operations, struct gb_operation, links); gb_operation_get(operation); - spin_unlock_irq(&connection->lock); + spin_unlock_irqrestore(&connection->lock, flags); if (gb_operation_is_incoming(operation)) gb_operation_cancel_incoming(operation, errno); @@ -589,7 +590,7 @@ static void gb_connection_cancel_operations(struct gb_connection *connection, gb_operation_put(operation); - spin_lock_irq(&connection->lock); + spin_lock_irqsave(&connection->lock, flags); } } @@ -600,7 +601,7 @@ static void gb_connection_cancel_operations(struct gb_connection *connection, */ static void gb_connection_flush_incoming_operations(struct gb_connection *connection, - int errno) + int errno, unsigned long flags) __must_hold(&connection->lock) { struct gb_operation *operation; @@ -620,13 +621,13 @@ gb_connection_flush_incoming_operations(struct gb_connection *connection, if (!incoming) break; - spin_unlock_irq(&connection->lock); + spin_unlock_irqrestore(&connection->lock, flags); /* FIXME: flush, not cancel? */ gb_operation_cancel_incoming(operation, errno); gb_operation_put(operation); - spin_lock_irq(&connection->lock); + spin_lock_irqsave(&connection->lock, flags); } } @@ -642,6 +643,7 @@ gb_connection_flush_incoming_operations(struct gb_connection *connection, */ static int _gb_connection_enable(struct gb_connection *connection, bool rx) { + unsigned long flags; int ret; /* Handle ENABLED_TX -> ENABLED transitions. */ @@ -649,9 +651,9 @@ static int _gb_connection_enable(struct gb_connection *connection, bool rx) if (!(connection->handler && rx)) return 0; - spin_lock_irq(&connection->lock); + spin_lock_irqsave(&connection->lock, flags); connection->state = GB_CONNECTION_STATE_ENABLED; - spin_unlock_irq(&connection->lock); + spin_unlock_irqrestore(&connection->lock, flags); return 0; } @@ -668,12 +670,12 @@ static int _gb_connection_enable(struct gb_connection *connection, bool rx) if (ret) goto err_svc_connection_destroy; - spin_lock_irq(&connection->lock); + spin_lock_irqsave(&connection->lock, flags); if (connection->handler && rx) connection->state = GB_CONNECTION_STATE_ENABLED; else connection->state = GB_CONNECTION_STATE_ENABLED_TX; - spin_unlock_irq(&connection->lock); + spin_unlock_irqrestore(&connection->lock, flags); ret = gb_connection_control_connected(connection); if (ret) @@ -684,10 +686,10 @@ static int _gb_connection_enable(struct gb_connection *connection, bool rx) err_control_disconnecting: gb_connection_control_disconnecting(connection); - spin_lock_irq(&connection->lock); + spin_lock_irqsave(&connection->lock, flags); connection->state = GB_CONNECTION_STATE_DISCONNECTING; - gb_connection_cancel_operations(connection, -ESHUTDOWN); - spin_unlock_irq(&connection->lock); + gb_connection_cancel_operations(connection, -ESHUTDOWN, flags); + spin_unlock_irqrestore(&connection->lock, flags); /* Transmit queue should already be empty. */ gb_connection_hd_cport_flush(connection); @@ -753,16 +755,18 @@ EXPORT_SYMBOL_GPL(gb_connection_enable_tx); void gb_connection_disable_rx(struct gb_connection *connection) { + unsigned long flags; + mutex_lock(&connection->mutex); - spin_lock_irq(&connection->lock); + spin_lock_irqsave(&connection->lock, flags); if (connection->state != GB_CONNECTION_STATE_ENABLED) { - spin_unlock_irq(&connection->lock); + spin_unlock_irqrestore(&connection->lock, flags); goto out_unlock; } connection->state = GB_CONNECTION_STATE_ENABLED_TX; - gb_connection_flush_incoming_operations(connection, -ESHUTDOWN); - spin_unlock_irq(&connection->lock); + gb_connection_flush_incoming_operations(connection, -ESHUTDOWN, flags); + spin_unlock_irqrestore(&connection->lock, flags); trace_gb_connection_disable(connection); @@ -785,6 +789,8 @@ void gb_connection_mode_switch_complete(struct gb_connection *connection) void gb_connection_disable(struct gb_connection *connection) { + unsigned long flags; + mutex_lock(&connection->mutex); if (connection->state == GB_CONNECTION_STATE_DISABLED) @@ -794,10 +800,10 @@ void gb_connection_disable(struct gb_connection *connection) gb_connection_control_disconnecting(connection); - spin_lock_irq(&connection->lock); + spin_lock_irqsave(&connection->lock, flags); connection->state = GB_CONNECTION_STATE_DISCONNECTING; - gb_connection_cancel_operations(connection, -ESHUTDOWN); - spin_unlock_irq(&connection->lock); + gb_connection_cancel_operations(connection, -ESHUTDOWN, flags); + spin_unlock_irqrestore(&connection->lock, flags); gb_connection_hd_cport_flush(connection); @@ -824,6 +830,8 @@ EXPORT_SYMBOL_GPL(gb_connection_disable); /* Disable a connection without communicating with the remote end. */ void gb_connection_disable_forced(struct gb_connection *connection) { + unsigned long flags; + mutex_lock(&connection->mutex); if (connection->state == GB_CONNECTION_STATE_DISABLED) @@ -831,10 +839,10 @@ void gb_connection_disable_forced(struct gb_connection *connection) trace_gb_connection_disable(connection); - spin_lock_irq(&connection->lock); + spin_lock_irqsave(&connection->lock, flags); connection->state = GB_CONNECTION_STATE_DISABLED; - gb_connection_cancel_operations(connection, -ESHUTDOWN); - spin_unlock_irq(&connection->lock); + gb_connection_cancel_operations(connection, -ESHUTDOWN, flags); + spin_unlock_irqrestore(&connection->lock, flags); gb_connection_hd_cport_flush(connection); gb_connection_hd_cport_features_disable(connection); @@ -849,6 +857,8 @@ EXPORT_SYMBOL_GPL(gb_connection_disable_forced); /* Caller must have disabled the connection before destroying it. */ void gb_connection_destroy(struct gb_connection *connection) { + unsigned long flags; + if (!connection) return; @@ -857,10 +867,10 @@ void gb_connection_destroy(struct gb_connection *connection) mutex_lock(&gb_connection_mutex); - spin_lock_irq(&gb_connections_lock); + spin_lock_irqsave(&gb_connections_lock, flags); list_del(&connection->bundle_links); list_del(&connection->hd_links); - spin_unlock_irq(&gb_connections_lock); + spin_unlock_irqrestore(&gb_connections_lock, flags); destroy_workqueue(connection->wq); diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index bdf5024..89fe764 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -496,11 +496,12 @@ static void message_cancel(struct gb_message *message) struct gb_host_device *hd = message->operation->connection->hd; struct es2_ap_dev *es2 = hd_to_es2(hd); struct urb *urb; + unsigned long flags; int i; might_sleep(); - spin_lock_irq(&es2->cport_out_urb_lock); + spin_lock_irqsave(&es2->cport_out_urb_lock, flags); urb = message->hcpriv; /* Prevent dynamically allocated urb from being deallocated. */ @@ -513,14 +514,14 @@ static void message_cancel(struct gb_message *message) break; } } - spin_unlock_irq(&es2->cport_out_urb_lock); + spin_unlock_irqrestore(&es2->cport_out_urb_lock, flags); usb_kill_urb(urb); if (i < NUM_CPORT_OUT_URB) { - spin_lock_irq(&es2->cport_out_urb_lock); + spin_lock_irqsave(&es2->cport_out_urb_lock, flags); es2->cport_out_urb_cancelled[i] = false; - spin_unlock_irq(&es2->cport_out_urb_lock); + spin_unlock_irqrestore(&es2->cport_out_urb_lock, flags); } usb_free_urb(urb); diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 6260569..8089638 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -674,6 +674,7 @@ static int set_serial_info(struct gb_tty *gb_tty, static int wait_serial_change(struct gb_tty *gb_tty, unsigned long arg) { int retval = 0; + unsigned long flags; DECLARE_WAITQUEUE(wait, current); struct async_icount old; struct async_icount new; @@ -682,11 +683,11 @@ static int wait_serial_change(struct gb_tty *gb_tty, unsigned long arg) return -EINVAL; do { - spin_lock_irq(&gb_tty->read_lock); + spin_lock_irqsave(&gb_tty->read_lock, flags); old = gb_tty->oldcount; new = gb_tty->iocount; gb_tty->oldcount = new; - spin_unlock_irq(&gb_tty->read_lock); + spin_unlock_irqrestore(&gb_tty->read_lock, flags); if ((arg & TIOCM_DSR) && (old.dsr != new.dsr)) break; -- cgit v0.10.2 From 1211915127c152a86e68ea35770c9e2524020d4f Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Thu, 23 Jun 2016 16:26:00 +0100 Subject: greybus: timesync: Enforce TimeSync locks as subordinate to Interface locks gb_timesync_svc_teardown() is called from gb_timesync_svc_del() and issues a command to a remote Interface to switch off its timers. The lock ordering is TimeSync => Interface in this case. However gb_module_del() takes an Interface lock then calls gb_interface_del() => gb_timesync_svc_del() in this case the lock ordering is Interface => TimeSync. This patch fixes by removing the taking of the Interface mutex in gb_interface_timesync_do_something(). If an Interface is present in the TimeSync linked-list - it is by definition intf->enabled. Reported-by: Rui Miguel Silva <rui.silva@linaro.org> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 9b90209..05d0020 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -872,59 +872,27 @@ void gb_interface_disable(struct gb_interface *intf) intf->enabled = false; } -/* - * Enable TimeSync on an Interface control connection. - * - * Locking: Takes and releases the interface mutex. - */ +/* Enable TimeSync on an Interface control connection. */ int gb_interface_timesync_enable(struct gb_interface *intf, u8 count, u64 frame_time, u32 strobe_delay, u32 refclk) { - int ret = -ENODEV; - - mutex_lock(&intf->mutex); - if (intf->enabled) { - ret = gb_control_timesync_enable(intf->control, count, - frame_time, strobe_delay, - refclk); - } - mutex_unlock(&intf->mutex); - return ret; + return gb_control_timesync_enable(intf->control, count, + frame_time, strobe_delay, + refclk); } -/* - * Disable TimeSync on an Interface control connection. - * - * Locking: Takes and releases the interface mutex. - */ +/* Disable TimeSync on an Interface control connection. */ int gb_interface_timesync_disable(struct gb_interface *intf) { - int ret = -ENODEV; - - mutex_lock(&intf->mutex); - if (intf->enabled) - ret = gb_control_timesync_disable(intf->control); - mutex_unlock(&intf->mutex); - return ret; + return gb_control_timesync_disable(intf->control); } -/* - * Transmit the Authoritative FrameTime via an Interface control connection. - * - * Locking: Takes and releases the interface mutex. - */ +/* Transmit the Authoritative FrameTime via an Interface control connection. */ int gb_interface_timesync_authoritative(struct gb_interface *intf, u64 *frame_time) { - int ret = -ENODEV; - - mutex_lock(&intf->mutex); - if (intf->enabled) { - ret = gb_control_timesync_authoritative(intf->control, - frame_time); - } - mutex_unlock(&intf->mutex); - return ret; + return gb_control_timesync_authoritative(intf->control, + frame_time); } /* Register an interface. */ -- cgit v0.10.2 From 19cdabcf0ba92ddd87bdb86f8e3ceaae2dd6f8bb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Thu, 23 Jun 2016 14:20:02 -0700 Subject: greybus: Revert "greybus: don't use spin_lock_irq()" This reverts commit 469fbe5da0229edcb42aa08bef8e10feaa37e6d7. It isn't correct in places. Reported-by: Gjorgji Rosikopulos <rosikopulos_gjorgji@projectara.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 0132e36..3a17db9 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -150,7 +150,6 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, unsigned long flags) { struct gb_connection *connection; - unsigned long irqflags; int ret; mutex_lock(&gb_connection_mutex); @@ -201,7 +200,7 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, gb_connection_init_name(connection); - spin_lock_irqsave(&gb_connections_lock, irqflags); + spin_lock_irq(&gb_connections_lock); list_add(&connection->hd_links, &hd->connections); if (bundle) @@ -209,7 +208,7 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, else INIT_LIST_HEAD(&connection->bundle_links); - spin_unlock_irqrestore(&gb_connections_lock, irqflags); + spin_unlock_irq(&gb_connections_lock); mutex_unlock(&gb_connection_mutex); @@ -572,7 +571,7 @@ static int gb_connection_ping(struct gb_connection *connection) * DISCONNECTING. */ static void gb_connection_cancel_operations(struct gb_connection *connection, - int errno, unsigned long flags) + int errno) __must_hold(&connection->lock) { struct gb_operation *operation; @@ -581,7 +580,7 @@ static void gb_connection_cancel_operations(struct gb_connection *connection, operation = list_last_entry(&connection->operations, struct gb_operation, links); gb_operation_get(operation); - spin_unlock_irqrestore(&connection->lock, flags); + spin_unlock_irq(&connection->lock); if (gb_operation_is_incoming(operation)) gb_operation_cancel_incoming(operation, errno); @@ -590,7 +589,7 @@ static void gb_connection_cancel_operations(struct gb_connection *connection, gb_operation_put(operation); - spin_lock_irqsave(&connection->lock, flags); + spin_lock_irq(&connection->lock); } } @@ -601,7 +600,7 @@ static void gb_connection_cancel_operations(struct gb_connection *connection, */ static void gb_connection_flush_incoming_operations(struct gb_connection *connection, - int errno, unsigned long flags) + int errno) __must_hold(&connection->lock) { struct gb_operation *operation; @@ -621,13 +620,13 @@ gb_connection_flush_incoming_operations(struct gb_connection *connection, if (!incoming) break; - spin_unlock_irqrestore(&connection->lock, flags); + spin_unlock_irq(&connection->lock); /* FIXME: flush, not cancel? */ gb_operation_cancel_incoming(operation, errno); gb_operation_put(operation); - spin_lock_irqsave(&connection->lock, flags); + spin_lock_irq(&connection->lock); } } @@ -643,7 +642,6 @@ gb_connection_flush_incoming_operations(struct gb_connection *connection, */ static int _gb_connection_enable(struct gb_connection *connection, bool rx) { - unsigned long flags; int ret; /* Handle ENABLED_TX -> ENABLED transitions. */ @@ -651,9 +649,9 @@ static int _gb_connection_enable(struct gb_connection *connection, bool rx) if (!(connection->handler && rx)) return 0; - spin_lock_irqsave(&connection->lock, flags); + spin_lock_irq(&connection->lock); connection->state = GB_CONNECTION_STATE_ENABLED; - spin_unlock_irqrestore(&connection->lock, flags); + spin_unlock_irq(&connection->lock); return 0; } @@ -670,12 +668,12 @@ static int _gb_connection_enable(struct gb_connection *connection, bool rx) if (ret) goto err_svc_connection_destroy; - spin_lock_irqsave(&connection->lock, flags); + spin_lock_irq(&connection->lock); if (connection->handler && rx) connection->state = GB_CONNECTION_STATE_ENABLED; else connection->state = GB_CONNECTION_STATE_ENABLED_TX; - spin_unlock_irqrestore(&connection->lock, flags); + spin_unlock_irq(&connection->lock); ret = gb_connection_control_connected(connection); if (ret) @@ -686,10 +684,10 @@ static int _gb_connection_enable(struct gb_connection *connection, bool rx) err_control_disconnecting: gb_connection_control_disconnecting(connection); - spin_lock_irqsave(&connection->lock, flags); + spin_lock_irq(&connection->lock); connection->state = GB_CONNECTION_STATE_DISCONNECTING; - gb_connection_cancel_operations(connection, -ESHUTDOWN, flags); - spin_unlock_irqrestore(&connection->lock, flags); + gb_connection_cancel_operations(connection, -ESHUTDOWN); + spin_unlock_irq(&connection->lock); /* Transmit queue should already be empty. */ gb_connection_hd_cport_flush(connection); @@ -755,18 +753,16 @@ EXPORT_SYMBOL_GPL(gb_connection_enable_tx); void gb_connection_disable_rx(struct gb_connection *connection) { - unsigned long flags; - mutex_lock(&connection->mutex); - spin_lock_irqsave(&connection->lock, flags); + spin_lock_irq(&connection->lock); if (connection->state != GB_CONNECTION_STATE_ENABLED) { - spin_unlock_irqrestore(&connection->lock, flags); + spin_unlock_irq(&connection->lock); goto out_unlock; } connection->state = GB_CONNECTION_STATE_ENABLED_TX; - gb_connection_flush_incoming_operations(connection, -ESHUTDOWN, flags); - spin_unlock_irqrestore(&connection->lock, flags); + gb_connection_flush_incoming_operations(connection, -ESHUTDOWN); + spin_unlock_irq(&connection->lock); trace_gb_connection_disable(connection); @@ -789,8 +785,6 @@ void gb_connection_mode_switch_complete(struct gb_connection *connection) void gb_connection_disable(struct gb_connection *connection) { - unsigned long flags; - mutex_lock(&connection->mutex); if (connection->state == GB_CONNECTION_STATE_DISABLED) @@ -800,10 +794,10 @@ void gb_connection_disable(struct gb_connection *connection) gb_connection_control_disconnecting(connection); - spin_lock_irqsave(&connection->lock, flags); + spin_lock_irq(&connection->lock); connection->state = GB_CONNECTION_STATE_DISCONNECTING; - gb_connection_cancel_operations(connection, -ESHUTDOWN, flags); - spin_unlock_irqrestore(&connection->lock, flags); + gb_connection_cancel_operations(connection, -ESHUTDOWN); + spin_unlock_irq(&connection->lock); gb_connection_hd_cport_flush(connection); @@ -830,8 +824,6 @@ EXPORT_SYMBOL_GPL(gb_connection_disable); /* Disable a connection without communicating with the remote end. */ void gb_connection_disable_forced(struct gb_connection *connection) { - unsigned long flags; - mutex_lock(&connection->mutex); if (connection->state == GB_CONNECTION_STATE_DISABLED) @@ -839,10 +831,10 @@ void gb_connection_disable_forced(struct gb_connection *connection) trace_gb_connection_disable(connection); - spin_lock_irqsave(&connection->lock, flags); + spin_lock_irq(&connection->lock); connection->state = GB_CONNECTION_STATE_DISABLED; - gb_connection_cancel_operations(connection, -ESHUTDOWN, flags); - spin_unlock_irqrestore(&connection->lock, flags); + gb_connection_cancel_operations(connection, -ESHUTDOWN); + spin_unlock_irq(&connection->lock); gb_connection_hd_cport_flush(connection); gb_connection_hd_cport_features_disable(connection); @@ -857,8 +849,6 @@ EXPORT_SYMBOL_GPL(gb_connection_disable_forced); /* Caller must have disabled the connection before destroying it. */ void gb_connection_destroy(struct gb_connection *connection) { - unsigned long flags; - if (!connection) return; @@ -867,10 +857,10 @@ void gb_connection_destroy(struct gb_connection *connection) mutex_lock(&gb_connection_mutex); - spin_lock_irqsave(&gb_connections_lock, flags); + spin_lock_irq(&gb_connections_lock); list_del(&connection->bundle_links); list_del(&connection->hd_links); - spin_unlock_irqrestore(&gb_connections_lock, flags); + spin_unlock_irq(&gb_connections_lock); destroy_workqueue(connection->wq); diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 89fe764..bdf5024 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -496,12 +496,11 @@ static void message_cancel(struct gb_message *message) struct gb_host_device *hd = message->operation->connection->hd; struct es2_ap_dev *es2 = hd_to_es2(hd); struct urb *urb; - unsigned long flags; int i; might_sleep(); - spin_lock_irqsave(&es2->cport_out_urb_lock, flags); + spin_lock_irq(&es2->cport_out_urb_lock); urb = message->hcpriv; /* Prevent dynamically allocated urb from being deallocated. */ @@ -514,14 +513,14 @@ static void message_cancel(struct gb_message *message) break; } } - spin_unlock_irqrestore(&es2->cport_out_urb_lock, flags); + spin_unlock_irq(&es2->cport_out_urb_lock); usb_kill_urb(urb); if (i < NUM_CPORT_OUT_URB) { - spin_lock_irqsave(&es2->cport_out_urb_lock, flags); + spin_lock_irq(&es2->cport_out_urb_lock); es2->cport_out_urb_cancelled[i] = false; - spin_unlock_irqrestore(&es2->cport_out_urb_lock, flags); + spin_unlock_irq(&es2->cport_out_urb_lock); } usb_free_urb(urb); diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 8089638..6260569 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -674,7 +674,6 @@ static int set_serial_info(struct gb_tty *gb_tty, static int wait_serial_change(struct gb_tty *gb_tty, unsigned long arg) { int retval = 0; - unsigned long flags; DECLARE_WAITQUEUE(wait, current); struct async_icount old; struct async_icount new; @@ -683,11 +682,11 @@ static int wait_serial_change(struct gb_tty *gb_tty, unsigned long arg) return -EINVAL; do { - spin_lock_irqsave(&gb_tty->read_lock, flags); + spin_lock_irq(&gb_tty->read_lock); old = gb_tty->oldcount; new = gb_tty->iocount; gb_tty->oldcount = new; - spin_unlock_irqrestore(&gb_tty->read_lock, flags); + spin_unlock_irq(&gb_tty->read_lock); if ((arg & TIOCM_DSR) && (old.dsr != new.dsr)) break; -- cgit v0.10.2 From e9f80f3363542b645a5ceb0509273eda1d0e4eab Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 23 Jun 2016 23:23:06 +0530 Subject: greybus: uart: don't use spin_lock_irq() spin_[un]lock_irq() routines should be used carefully as they things can go wrong, if they are mixed with spin_lock_irqsave() or other variants. The main problem is that spin_[un]lock_irq() routines doesn't check if the IRQs are already disabled/enabled on the local CPU and so spin_unlock_irq() will forcefully enable interrupts for example. This may not work well, if some other code was relying on interrupts being disabled. Use spin_lock_irqsave() and spin_unlock_restore() instead. This patch doesn't claim that it fixes the JIRA completely, but the issue was harder to reproduce for some iterations after this, which was quite easy to reproduce earlier on. Tested on EVT 2.0 with lots of debug patches to kernel and greybus. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 6260569..8089638 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -674,6 +674,7 @@ static int set_serial_info(struct gb_tty *gb_tty, static int wait_serial_change(struct gb_tty *gb_tty, unsigned long arg) { int retval = 0; + unsigned long flags; DECLARE_WAITQUEUE(wait, current); struct async_icount old; struct async_icount new; @@ -682,11 +683,11 @@ static int wait_serial_change(struct gb_tty *gb_tty, unsigned long arg) return -EINVAL; do { - spin_lock_irq(&gb_tty->read_lock); + spin_lock_irqsave(&gb_tty->read_lock, flags); old = gb_tty->oldcount; new = gb_tty->iocount; gb_tty->oldcount = new; - spin_unlock_irq(&gb_tty->read_lock); + spin_unlock_irqrestore(&gb_tty->read_lock, flags); if ((arg & TIOCM_DSR) && (old.dsr != new.dsr)) break; -- cgit v0.10.2 From fe9054155d831fee7a8e737ff3898c4bc2e5fc4d Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 23 Jun 2016 23:23:06 +0530 Subject: greybus: es2.c: don't use spin_lock_irq() spin_[un]lock_irq() routines should be used carefully as they things can go wrong, if they are mixed with spin_lock_irqsave() or other variants. The main problem is that spin_[un]lock_irq() routines doesn't check if the IRQs are already disabled/enabled on the local CPU and so spin_unlock_irq() will forcefully enable interrupts for example. This may not work well, if some other code was relying on interrupts being disabled. Use spin_lock_irqsave() and spin_unlock_restore() instead. This patch doesn't claim that it fixes the JIRA completely, but the issue was harder to reproduce for some iterations after this, which was quite easy to reproduce earlier on. Tested on EVT 2.0 with lots of debug patches to kernel and greybus. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index bdf5024..89fe764 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -496,11 +496,12 @@ static void message_cancel(struct gb_message *message) struct gb_host_device *hd = message->operation->connection->hd; struct es2_ap_dev *es2 = hd_to_es2(hd); struct urb *urb; + unsigned long flags; int i; might_sleep(); - spin_lock_irq(&es2->cport_out_urb_lock); + spin_lock_irqsave(&es2->cport_out_urb_lock, flags); urb = message->hcpriv; /* Prevent dynamically allocated urb from being deallocated. */ @@ -513,14 +514,14 @@ static void message_cancel(struct gb_message *message) break; } } - spin_unlock_irq(&es2->cport_out_urb_lock); + spin_unlock_irqrestore(&es2->cport_out_urb_lock, flags); usb_kill_urb(urb); if (i < NUM_CPORT_OUT_URB) { - spin_lock_irq(&es2->cport_out_urb_lock); + spin_lock_irqsave(&es2->cport_out_urb_lock, flags); es2->cport_out_urb_cancelled[i] = false; - spin_unlock_irq(&es2->cport_out_urb_lock); + spin_unlock_irqrestore(&es2->cport_out_urb_lock, flags); } usb_free_urb(urb); -- cgit v0.10.2 From 6f7f2ae5df786bf9ced3247fda51a0a7aeb9cd0c Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 23 Jun 2016 23:23:06 +0530 Subject: greybus: gb_connections_lock: don't use spin_lock_irq() spin_[un]lock_irq() routines should be used carefully as they things can go wrong, if they are mixed with spin_lock_irqsave() or other variants. The main problem is that spin_[un]lock_irq() routines doesn't check if the IRQs are already disabled/enabled on the local CPU and so spin_unlock_irq() will forcefully enable interrupts for example. This may not work well, if some other code was relying on interrupts being disabled. Use spin_lock_irqsave() and spin_unlock_restore() instead. This patch doesn't claim that it fixes the JIRA completely, but the issue was harder to reproduce for some iterations after this, which was quite easy to reproduce earlier on. Tested on EVT 2.0 with lots of debug patches to kernel and greybus. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 3a17db9..810c618 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -150,6 +150,7 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, unsigned long flags) { struct gb_connection *connection; + unsigned long irqflags; int ret; mutex_lock(&gb_connection_mutex); @@ -200,7 +201,7 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, gb_connection_init_name(connection); - spin_lock_irq(&gb_connections_lock); + spin_lock_irqsave(&gb_connections_lock, irqflags); list_add(&connection->hd_links, &hd->connections); if (bundle) @@ -208,7 +209,7 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, else INIT_LIST_HEAD(&connection->bundle_links); - spin_unlock_irq(&gb_connections_lock); + spin_unlock_irqrestore(&gb_connections_lock, irqflags); mutex_unlock(&gb_connection_mutex); @@ -849,6 +850,8 @@ EXPORT_SYMBOL_GPL(gb_connection_disable_forced); /* Caller must have disabled the connection before destroying it. */ void gb_connection_destroy(struct gb_connection *connection) { + unsigned long flags; + if (!connection) return; @@ -857,10 +860,10 @@ void gb_connection_destroy(struct gb_connection *connection) mutex_lock(&gb_connection_mutex); - spin_lock_irq(&gb_connections_lock); + spin_lock_irqsave(&gb_connections_lock, flags); list_del(&connection->bundle_links); list_del(&connection->hd_links); - spin_unlock_irq(&gb_connections_lock); + spin_unlock_irqrestore(&gb_connections_lock, flags); destroy_workqueue(connection->wq); -- cgit v0.10.2 From c0e65d026c297c53eeb5412c31a5410317225945 Mon Sep 17 00:00:00 2001 From: Joel Porquet <porquet_joel@projectara.com> Date: Fri, 24 Jun 2016 14:41:36 -0700 Subject: greybus: add support for the log protocol Add support for the new Log class/protocol. This protocol allows modules to send their internal logging messages to the AP in order to make module debugging easier. The protocol is, for now, composed a single module-initiated request. This request contains a message and associated length. The message is integrated in the kernel log with dev_dbg(). In order to be displayed with 'dmesg', the following command needs to be entered first: $ echo "file log.c +p" > /sys/kernel/debug/dynamic_debug/control The major portion of this file was initially written by Greg KH. Signed-off-by: Joel Porquet <porquet_joel@projectara.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 40325b3..bd9967c 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -18,6 +18,7 @@ gb-gbphy-y := gbphy.o # Prefix all modules with gb- gb-vibrator-y := vibrator.o gb-power-supply-y := power_supply.o +gb-log-y := log.o gb-loopback-y := loopback.o gb-light-y := light.o gb-raw-y := raw.o @@ -46,6 +47,7 @@ obj-m += greybus.o obj-m += gb-gbphy.o obj-m += gb-vibrator.o obj-m += gb-power-supply.o +obj-m += gb-log.o obj-m += gb-loopback.o obj-m += gb-light.o obj-m += gb-hid.o diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 28bbadd..2ae39ad 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -47,6 +47,7 @@ enum greybus_protocol { GREYBUS_PROTOCOL_CAMERA_DATA = 0x16, GREYBUS_PROTOCOL_FW_DOWNLOAD = 0x17, GREYBUS_PROTOCOL_FW_MANAGEMENT = 0x18, + GREYBUS_PROTOCOL_LOG = 0x1a, /* ... */ GREYBUS_PROTOCOL_RAW = 0xfe, GREYBUS_PROTOCOL_VENDOR = 0xff, @@ -76,6 +77,7 @@ enum greybus_class_type { /* 0x14 is unused */ GREYBUS_CLASS_BOOTROM = 0x15, GREYBUS_CLASS_FW_MANAGEMENT = 0x16, + GREYBUS_CLASS_LOG = 0x17, /* ... */ GREYBUS_CLASS_RAW = 0xfe, GREYBUS_CLASS_VENDOR = 0xff, diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 63dd204..203bc46 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -2136,5 +2136,19 @@ struct gb_audio_send_data_request { __u8 data[0]; } __packed; + +/* Log */ + +/* operations */ +#define GB_LOG_TYPE_SEND_LOG 0x02 + +/* length */ +#define GB_LOG_MAX_LEN 1024 + +struct gb_log_send_log_request { + __le16 len; + __u8 msg[0]; +} __packed; + #endif /* __GREYBUS_PROTOCOLS_H */ diff --git a/drivers/staging/greybus/log.c b/drivers/staging/greybus/log.c new file mode 100644 index 0000000..70dd9e5 --- /dev/null +++ b/drivers/staging/greybus/log.c @@ -0,0 +1,132 @@ +/* + * Greybus driver for the log protocol + * + * Copyright 2016 Google Inc. + * + * Released under the GPLv2 only. + */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/sizes.h> +#include <linux/uaccess.h> + +#include "greybus.h" + +struct gb_log { + struct gb_connection *connection; +}; + +static int gb_log_request_handler(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct device *dev = &connection->bundle->dev; + struct gb_log_send_log_request *receive; + u16 len; + + if (op->type != GB_LOG_TYPE_SEND_LOG) { + dev_err(dev, "unknown request type 0x%02x\n", op->type); + return -EINVAL; + } + + /* Verify size of payload */ + if (op->request->payload_size < sizeof(*receive)) { + dev_err(dev, "log request too small (%zu < %zu)\n", + op->request->payload_size, sizeof(*receive)); + return -EINVAL; + } + receive = op->request->payload; + len = le16_to_cpu(receive->len); + if (len != (int)(op->request->payload_size - sizeof(*receive))) { + dev_err(dev, "log request wrong size %d vs %d\n", len, + (int)(op->request->payload_size - sizeof(*receive))); + return -EINVAL; + } + if (len == 0) { + dev_err(dev, "log request of 0 bytes?\n"); + return -EINVAL; + } + + if (len > GB_LOG_MAX_LEN) { + dev_err(dev, "log request too big: %d\n", len); + return -EINVAL; + } + + /* Ensure the buffer is 0 terminated */ + receive->msg[len - 1] = '\0'; + + /* Print with dev_dbg() so that it can be easily turned off using + * dynamic debugging (and prevent any DoS) */ + dev_dbg(dev, "%s", receive->msg); + + return 0; +} + +static int gb_log_probe(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) +{ + struct greybus_descriptor_cport *cport_desc; + struct gb_connection *connection; + struct gb_log *log; + int retval; + + if (bundle->num_cports != 1) + return -ENODEV; + + cport_desc = &bundle->cport_desc[0]; + if (cport_desc->protocol_id != GREYBUS_PROTOCOL_LOG) + return -ENODEV; + + log = kzalloc(sizeof(*log), GFP_KERNEL); + if (!log) + return -ENOMEM; + + connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id), + gb_log_request_handler); + if (IS_ERR(connection)) { + retval = PTR_ERR(connection); + goto error_free; + } + + log->connection = connection; + greybus_set_drvdata(bundle, log); + + retval = gb_connection_enable(connection); + if (retval) + goto error_connection_destroy; + + return 0; + +error_connection_destroy: + gb_connection_destroy(connection); +error_free: + kfree(log); + return retval; +} + +static void gb_log_disconnect(struct gb_bundle *bundle) +{ + struct gb_log *log = greybus_get_drvdata(bundle); + struct gb_connection *connection = log->connection; + + gb_connection_disable(connection); + gb_connection_destroy(connection); + + kfree(log); +} + +static const struct greybus_bundle_id gb_log_id_table[] = { + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_LOG) }, + { } +}; +MODULE_DEVICE_TABLE(greybus, gb_log_id_table); + +static struct greybus_driver gb_log_driver = { + .name = "log", + .probe = gb_log_probe, + .disconnect = gb_log_disconnect, + .id_table = gb_log_id_table, +}; +module_greybus_driver(gb_log_driver); + +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 50687f360958722de8610998a3cc886d9c9ba0b5 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Wed, 22 Jun 2016 14:58:43 +0100 Subject: greybus: timesync: Initialize the timesync ping fields to zero Remember to initialize the TimeSync ping fields to zero so that if a timesync_get_last_event() returns an error - we display a FrameTime that is obviously incorrect. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/timesync.c b/drivers/staging/greybus/timesync.c index b9b29f5..3391feb 100644 --- a/drivers/staging/greybus/timesync.c +++ b/drivers/staging/greybus/timesync.c @@ -698,6 +698,7 @@ static void gb_timesync_ping(struct gb_timesync_svc *timesync_svc) /* Have SVC generate a timesync ping */ timesync_svc->capture_ping = true; + timesync_svc->svc_ping_frame_time = 0; ret = gb_svc_timesync_ping(svc, ×ync_svc->svc_ping_frame_time); timesync_svc->capture_ping = false; if (ret) { @@ -709,6 +710,7 @@ static void gb_timesync_ping(struct gb_timesync_svc *timesync_svc) /* Get the ping FrameTime from each APB/GPB */ hd = timesync_svc->timesync_hd->hd; + timesync_svc->timesync_hd->ping_frame_time = 0; ret = hd->driver->timesync_get_last_event(hd, ×ync_svc->timesync_hd->ping_frame_time); if (ret) @@ -717,6 +719,7 @@ static void gb_timesync_ping(struct gb_timesync_svc *timesync_svc) list_for_each_entry(timesync_interface, ×ync_svc->interface_list, list) { control = timesync_interface->interface->control; + timesync_interface->ping_frame_time = 0; ping_frame_time = ×ync_interface->ping_frame_time; ret = gb_control_timesync_get_last_event(control, ping_frame_time); -- cgit v0.10.2 From fd6d6f61d83c8217a052ba494f5b44abcec7ff43 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Wed, 22 Jun 2016 14:58:44 +0100 Subject: greybus: timesync: Make printout consitent with other greybus messages The current printout on a TimeSync ping doesn't actually contain the word greybus and uses the word ping-time in the print string, something that appears nowhere in our official documentation on this feature. This patch changes the format string to contain 'greybus' and 'frametime' to bring the TimeSync printout more in-line with other greybus kernel log strings. before: timesync ping-time: ap=8632564 1-svc=8630712 greybus1=8633031 1-8.8=8633026 after: greybus frametime: ap=8632564 1-svc=8630712 greybus1=8633031 1-8.8=8633026 Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/timesync.c b/drivers/staging/greybus/timesync.c index 3391feb..14531ed 100644 --- a/drivers/staging/greybus/timesync.c +++ b/drivers/staging/greybus/timesync.c @@ -581,7 +581,8 @@ static size_t gb_timesync_log_frame_time(struct gb_timesync_svc *timesync_svc, size_t off; /* AP/SVC */ - off = snprintf(buf, buflen, "timesync: ping-time ap=%llu %s=%llu ", + off = snprintf(buf, buflen, "%s frametime: ap=%llu %s=%llu ", + greybus_bus_type.name, timesync_svc->ap_ping_frame_time, dev_name(&svc->dev), timesync_svc->svc_ping_frame_time); len = buflen - off; @@ -623,8 +624,8 @@ static size_t gb_timesync_log_frame_ktime(struct gb_timesync_svc *timesync_svc, /* AP */ gb_timesync_to_timespec(timesync_svc, timesync_svc->ap_ping_frame_time, &ts); - off = snprintf(buf, buflen, "timesync: ping-time ap=%lu.%lu ", - ts.tv_sec, ts.tv_nsec); + off = snprintf(buf, buflen, "%s frametime: ap=%lu.%lu ", + greybus_bus_type.name, ts.tv_sec, ts.tv_nsec); len = buflen - off; if (len >= buflen) goto done; -- cgit v0.10.2 From a4293e1d4e6416477976ee3bd248589d3fc4bb19 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Wed, 22 Jun 2016 14:46:39 +0530 Subject: greybus: bootrom: Enhance timeout error message The timeout message is very generic today and there are several requests we can be timing out waiting for. Update bootrom driver to also track the next expected request and enhance the error message based on that to confirm the request we timed out waiting for. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/bootrom.c b/drivers/staging/greybus/bootrom.c index 2cebffa..6d79bc6 100644 --- a/drivers/staging/greybus/bootrom.c +++ b/drivers/staging/greybus/bootrom.c @@ -17,11 +17,19 @@ /* Timeout, in jiffies, within which the next request must be received */ #define NEXT_REQ_TIMEOUT_J msecs_to_jiffies(1000) +enum next_request_type { + NEXT_REQ_FIRMWARE_SIZE, + NEXT_REQ_GET_FIRMWARE, + NEXT_REQ_READY_TO_BOOT, + NEXT_REQ_MODE_SWITCH, +}; + struct gb_bootrom { struct gb_connection *connection; const struct firmware *fw; u8 protocol_major; u8 protocol_minor; + enum next_request_type next_request; struct delayed_work dwork; struct mutex mutex; /* Protects bootrom->fw */ }; @@ -40,8 +48,28 @@ static void gb_bootrom_timedout(struct work_struct *work) struct delayed_work *dwork = to_delayed_work(work); struct gb_bootrom *bootrom = container_of(dwork, struct gb_bootrom, dwork); struct device *dev = &bootrom->connection->bundle->dev; + const char *reason; + + switch (bootrom->next_request) { + case NEXT_REQ_FIRMWARE_SIZE: + reason = "Firmware Size Request"; + break; + case NEXT_REQ_GET_FIRMWARE: + reason = "Get Firmware Request"; + break; + case NEXT_REQ_READY_TO_BOOT: + reason = "Ready to Boot Request"; + break; + case NEXT_REQ_MODE_SWITCH: + reason = "Interface Mode Switch"; + break; + default: + reason = NULL; + dev_err(dev, "Invalid next-request: %u", bootrom->next_request); + break; + } - dev_err(dev, "Timed out waiting for request from the Module\n"); + dev_err(dev, "Timed out waiting for %s from the Module\n", reason); mutex_lock(&bootrom->mutex); free_firmware(bootrom); @@ -50,6 +78,13 @@ static void gb_bootrom_timedout(struct work_struct *work) /* TODO: Power-off Module ? */ } +static void gb_bootrom_set_timeout(struct gb_bootrom *bootrom, + enum next_request_type next, unsigned long timeout) +{ + bootrom->next_request = next; + schedule_delayed_work(&bootrom->dwork, timeout); +} + /* * The es2 chip doesn't have VID/PID programmed into the hardware and we need to * hack that up to distinguish different modules and their firmware blobs. @@ -175,7 +210,8 @@ unlock: queue_work: /* Refresh timeout */ - schedule_delayed_work(&bootrom->dwork, NEXT_REQ_TIMEOUT_J); + gb_bootrom_set_timeout(bootrom, NEXT_REQ_GET_FIRMWARE, + NEXT_REQ_TIMEOUT_J); return ret; } @@ -188,6 +224,7 @@ static int gb_bootrom_get_firmware(struct gb_operation *op) struct gb_bootrom_get_firmware_response *firmware_response; struct device *dev = &op->connection->bundle->dev; unsigned int offset, size; + enum next_request_type next_request; int ret = 0; /* Disable timeouts */ @@ -239,7 +276,12 @@ unlock: queue_work: /* Refresh timeout */ - schedule_delayed_work(&bootrom->dwork, NEXT_REQ_TIMEOUT_J); + if (!ret && (offset + size == fw->size)) + next_request = NEXT_REQ_READY_TO_BOOT; + else + next_request = NEXT_REQ_GET_FIRMWARE; + + gb_bootrom_set_timeout(bootrom, next_request, NEXT_REQ_TIMEOUT_J); return ret; } @@ -284,7 +326,8 @@ queue_work: * send a new hotplug request, which shall get rid of the bootrom * connection. As that can take some time, increase the timeout a bit. */ - schedule_delayed_work(&bootrom->dwork, 5 * NEXT_REQ_TIMEOUT_J); + gb_bootrom_set_timeout(bootrom, NEXT_REQ_MODE_SWITCH, + 5 * NEXT_REQ_TIMEOUT_J); return ret; } @@ -403,7 +446,8 @@ static int gb_bootrom_probe(struct gb_bundle *bundle, } /* Refresh timeout */ - schedule_delayed_work(&bootrom->dwork, NEXT_REQ_TIMEOUT_J); + gb_bootrom_set_timeout(bootrom, NEXT_REQ_FIRMWARE_SIZE, + NEXT_REQ_TIMEOUT_J); dev_dbg(&bundle->dev, "AP_READY sent\n"); -- cgit v0.10.2 From dbb8cfeba9cc22e091eaec3dfa34ae4c7dc4d241 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Wed, 22 Jun 2016 14:46:40 +0530 Subject: greybus: bootrom: send timeout in milliseconds to gb_bootrom_set_timeout() Rename NEXT_REQ_TIMEOUT_J to NEXT_REQ_TIMEOUT_MS and store the timeout in milliseconds instead of jiffies. Suggested-by: Alex Elder <alex.elder@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/bootrom.c b/drivers/staging/greybus/bootrom.c index 6d79bc6..70785d4 100644 --- a/drivers/staging/greybus/bootrom.c +++ b/drivers/staging/greybus/bootrom.c @@ -15,7 +15,7 @@ #include "greybus.h" /* Timeout, in jiffies, within which the next request must be received */ -#define NEXT_REQ_TIMEOUT_J msecs_to_jiffies(1000) +#define NEXT_REQ_TIMEOUT_MS 1000 enum next_request_type { NEXT_REQ_FIRMWARE_SIZE, @@ -82,7 +82,7 @@ static void gb_bootrom_set_timeout(struct gb_bootrom *bootrom, enum next_request_type next, unsigned long timeout) { bootrom->next_request = next; - schedule_delayed_work(&bootrom->dwork, timeout); + schedule_delayed_work(&bootrom->dwork, msecs_to_jiffies(timeout)); } /* @@ -211,7 +211,7 @@ unlock: queue_work: /* Refresh timeout */ gb_bootrom_set_timeout(bootrom, NEXT_REQ_GET_FIRMWARE, - NEXT_REQ_TIMEOUT_J); + NEXT_REQ_TIMEOUT_MS); return ret; } @@ -281,7 +281,7 @@ queue_work: else next_request = NEXT_REQ_GET_FIRMWARE; - gb_bootrom_set_timeout(bootrom, next_request, NEXT_REQ_TIMEOUT_J); + gb_bootrom_set_timeout(bootrom, next_request, NEXT_REQ_TIMEOUT_MS); return ret; } @@ -327,7 +327,7 @@ queue_work: * connection. As that can take some time, increase the timeout a bit. */ gb_bootrom_set_timeout(bootrom, NEXT_REQ_MODE_SWITCH, - 5 * NEXT_REQ_TIMEOUT_J); + 5 * NEXT_REQ_TIMEOUT_MS); return ret; } @@ -447,7 +447,7 @@ static int gb_bootrom_probe(struct gb_bundle *bundle, /* Refresh timeout */ gb_bootrom_set_timeout(bootrom, NEXT_REQ_FIRMWARE_SIZE, - NEXT_REQ_TIMEOUT_J); + NEXT_REQ_TIMEOUT_MS); dev_dbg(&bundle->dev, "AP_READY sent\n"); -- cgit v0.10.2 From 326f98ac3168cf415f4e1681b3684614bcd79fd3 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Wed, 22 Jun 2016 14:46:41 +0530 Subject: greybus: bootrom: Wait for 10 seconds for mode-switch The greybus SVC core handles events from the SVC serially today. In some cases the SVC operations may take too long, for example trying to activate a dummy interface. If another interface receives a mode-switch mailbox event in that time, the SVC core wouldn't be able to process it in quickly enough and bootrom driver will print following error: bootrom 1-3.3.1: Timed out waiting for Interface Mode Switch from the Module This can be reproduced easily by attaching a 2x2 module along with any other normal module like camera or speaker, and doing a unipro_reset from userspace. The logs suggest this time to be around 6-7 seconds in most of the cases. Attaching multiple modules with dummy interfaces may make this worst. Lets increase the timeout from 5 to 10 seconds for now, also add a FIXME for the same. Testing Done: Tested on EVT 2.0 with camera and a 2x2 module. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/bootrom.c b/drivers/staging/greybus/bootrom.c index 70785d4..84537a0 100644 --- a/drivers/staging/greybus/bootrom.c +++ b/drivers/staging/greybus/bootrom.c @@ -17,6 +17,12 @@ /* Timeout, in jiffies, within which the next request must be received */ #define NEXT_REQ_TIMEOUT_MS 1000 +/* + * FIXME: Reduce this timeout once svc core handles parallel processing of + * events from the SVC, which are handled sequentially today. + */ +#define MODE_SWITCH_TIMEOUT_MS 10000 + enum next_request_type { NEXT_REQ_FIRMWARE_SIZE, NEXT_REQ_GET_FIRMWARE, @@ -327,7 +333,7 @@ queue_work: * connection. As that can take some time, increase the timeout a bit. */ gb_bootrom_set_timeout(bootrom, NEXT_REQ_MODE_SWITCH, - 5 * NEXT_REQ_TIMEOUT_MS); + MODE_SWITCH_TIMEOUT_MS); return ret; } -- cgit v0.10.2 From 2d466c23c64f7556d0a184a1f02b2c8a23edaf5e Mon Sep 17 00:00:00 2001 From: Jeffrey Carlyle <jcarlyle@google.com> Date: Fri, 24 Jun 2016 08:58:56 +0530 Subject: greybus: connection: switch to using spin_lock_irqsave/spin_lock_irqrestore excluisvely We know that it is a bad idea to explicitly enable IRQs when we don't don't know if they were already off before we disabled, so switch to the save _irqsave and _irqrestore functions. Ultimately, we need to review places in the Greybus drivers where IRQs are disabled and remove unnecessary instances. This is only an interim step. This code will never run from hard irq context, as it is already taking mutex in the path. Testing done: booted EVT2.0, ran suspend/resume test app with a period of 20s for a few dozen cycles. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Jeffrey Carlyle <jcarlyle@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 810c618..20a87b9 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -572,7 +572,7 @@ static int gb_connection_ping(struct gb_connection *connection) * DISCONNECTING. */ static void gb_connection_cancel_operations(struct gb_connection *connection, - int errno) + int errno, unsigned long *flags) __must_hold(&connection->lock) { struct gb_operation *operation; @@ -581,7 +581,7 @@ static void gb_connection_cancel_operations(struct gb_connection *connection, operation = list_last_entry(&connection->operations, struct gb_operation, links); gb_operation_get(operation); - spin_unlock_irq(&connection->lock); + spin_unlock_irqrestore(&connection->lock, *flags); if (gb_operation_is_incoming(operation)) gb_operation_cancel_incoming(operation, errno); @@ -590,7 +590,7 @@ static void gb_connection_cancel_operations(struct gb_connection *connection, gb_operation_put(operation); - spin_lock_irq(&connection->lock); + spin_lock_irqsave(&connection->lock, *flags); } } @@ -601,7 +601,7 @@ static void gb_connection_cancel_operations(struct gb_connection *connection, */ static void gb_connection_flush_incoming_operations(struct gb_connection *connection, - int errno) + int errno, unsigned long *flags) __must_hold(&connection->lock) { struct gb_operation *operation; @@ -621,13 +621,13 @@ gb_connection_flush_incoming_operations(struct gb_connection *connection, if (!incoming) break; - spin_unlock_irq(&connection->lock); + spin_unlock_irqrestore(&connection->lock, *flags); /* FIXME: flush, not cancel? */ gb_operation_cancel_incoming(operation, errno); gb_operation_put(operation); - spin_lock_irq(&connection->lock); + spin_lock_irqsave(&connection->lock, *flags); } } @@ -644,15 +644,16 @@ gb_connection_flush_incoming_operations(struct gb_connection *connection, static int _gb_connection_enable(struct gb_connection *connection, bool rx) { int ret; + unsigned long flags; /* Handle ENABLED_TX -> ENABLED transitions. */ if (connection->state == GB_CONNECTION_STATE_ENABLED_TX) { if (!(connection->handler && rx)) return 0; - spin_lock_irq(&connection->lock); + spin_lock_irqsave(&connection->lock, flags); connection->state = GB_CONNECTION_STATE_ENABLED; - spin_unlock_irq(&connection->lock); + spin_unlock_irqrestore(&connection->lock, flags); return 0; } @@ -669,12 +670,12 @@ static int _gb_connection_enable(struct gb_connection *connection, bool rx) if (ret) goto err_svc_connection_destroy; - spin_lock_irq(&connection->lock); + spin_lock_irqsave(&connection->lock, flags); if (connection->handler && rx) connection->state = GB_CONNECTION_STATE_ENABLED; else connection->state = GB_CONNECTION_STATE_ENABLED_TX; - spin_unlock_irq(&connection->lock); + spin_unlock_irqrestore(&connection->lock, flags); ret = gb_connection_control_connected(connection); if (ret) @@ -685,10 +686,10 @@ static int _gb_connection_enable(struct gb_connection *connection, bool rx) err_control_disconnecting: gb_connection_control_disconnecting(connection); - spin_lock_irq(&connection->lock); + spin_lock_irqsave(&connection->lock, flags); connection->state = GB_CONNECTION_STATE_DISCONNECTING; - gb_connection_cancel_operations(connection, -ESHUTDOWN); - spin_unlock_irq(&connection->lock); + gb_connection_cancel_operations(connection, -ESHUTDOWN, &flags); + spin_unlock_irqrestore(&connection->lock, flags); /* Transmit queue should already be empty. */ gb_connection_hd_cport_flush(connection); @@ -754,16 +755,18 @@ EXPORT_SYMBOL_GPL(gb_connection_enable_tx); void gb_connection_disable_rx(struct gb_connection *connection) { + unsigned long flags; + mutex_lock(&connection->mutex); - spin_lock_irq(&connection->lock); + spin_lock_irqsave(&connection->lock, flags); if (connection->state != GB_CONNECTION_STATE_ENABLED) { - spin_unlock_irq(&connection->lock); + spin_unlock_irqrestore(&connection->lock, flags); goto out_unlock; } connection->state = GB_CONNECTION_STATE_ENABLED_TX; - gb_connection_flush_incoming_operations(connection, -ESHUTDOWN); - spin_unlock_irq(&connection->lock); + gb_connection_flush_incoming_operations(connection, -ESHUTDOWN, &flags); + spin_unlock_irqrestore(&connection->lock, flags); trace_gb_connection_disable(connection); @@ -786,6 +789,8 @@ void gb_connection_mode_switch_complete(struct gb_connection *connection) void gb_connection_disable(struct gb_connection *connection) { + unsigned long flags; + mutex_lock(&connection->mutex); if (connection->state == GB_CONNECTION_STATE_DISABLED) @@ -795,10 +800,10 @@ void gb_connection_disable(struct gb_connection *connection) gb_connection_control_disconnecting(connection); - spin_lock_irq(&connection->lock); + spin_lock_irqsave(&connection->lock, flags); connection->state = GB_CONNECTION_STATE_DISCONNECTING; - gb_connection_cancel_operations(connection, -ESHUTDOWN); - spin_unlock_irq(&connection->lock); + gb_connection_cancel_operations(connection, -ESHUTDOWN, &flags); + spin_unlock_irqrestore(&connection->lock, flags); gb_connection_hd_cport_flush(connection); @@ -825,6 +830,8 @@ EXPORT_SYMBOL_GPL(gb_connection_disable); /* Disable a connection without communicating with the remote end. */ void gb_connection_disable_forced(struct gb_connection *connection) { + unsigned long flags; + mutex_lock(&connection->mutex); if (connection->state == GB_CONNECTION_STATE_DISABLED) @@ -832,10 +839,10 @@ void gb_connection_disable_forced(struct gb_connection *connection) trace_gb_connection_disable(connection); - spin_lock_irq(&connection->lock); + spin_lock_irqsave(&connection->lock, flags); connection->state = GB_CONNECTION_STATE_DISABLED; - gb_connection_cancel_operations(connection, -ESHUTDOWN); - spin_unlock_irq(&connection->lock); + gb_connection_cancel_operations(connection, -ESHUTDOWN, &flags); + spin_unlock_irqrestore(&connection->lock, flags); gb_connection_hd_cport_flush(connection); gb_connection_hd_cport_features_disable(connection); -- cgit v0.10.2 From 9e138dd479cb1f924a3d78e13e6ba5668db73acc Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Fri, 24 Jun 2016 13:52:43 -0700 Subject: greybus: audio: remove the unnecessary return statement The return statement immediately after the BUG_ON of the gbcodec_write() call is added by mistake. It's not causing any errors right now due to that gbcodec_reg is currently not being used. Testing Done: - Audio playback on EVT2 Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 45e12b1..3c5a5ae 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -1099,7 +1099,6 @@ static int gbcodec_write(struct snd_soc_codec *codec, unsigned int reg, return 0; BUG_ON(reg >= GBCODEC_REG_COUNT); - return 0; gbcodec_reg[reg] = value; dev_dbg(codec->dev, "reg[%d] = 0x%x\n", reg, value); -- cgit v0.10.2 From caad3090ab37d47e21505b613ad611ad6d20358d Mon Sep 17 00:00:00 2001 From: Evgeniy Borisov <borisov_evgeniy@projectara.com> Date: Thu, 23 Jun 2016 12:39:18 +0300 Subject: greybus: camera: Add RAW data format Add support for greybus RAW data format. Greybus RAW data formats starts from 0x80. Signed-off-by: Evgeniy Borisov <eborisov@mm-sol.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@linaro.org> Reviewed-by: Gjorgji Rosikopulos <grosikopulos@mm-sol.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 0062f48..c47e424 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -113,6 +113,38 @@ static const struct gb_camera_fmt_map mbus_to_gbus_format[] = { .mbus_code = V4L2_MBUS_FMT_ARA_DEBUG_DATA_1X8, .gb_format = 0x42, }, + { + .mbus_code = V4L2_MBUS_FMT_SBGGR10_1X10, + .gb_format = 0x80, + }, + { + .mbus_code = V4L2_MBUS_FMT_SGBRG10_1X10, + .gb_format = 0x81, + }, + { + .mbus_code = V4L2_MBUS_FMT_SGRBG10_1X10, + .gb_format = 0x82, + }, + { + .mbus_code = V4L2_MBUS_FMT_SRGGB10_1X10, + .gb_format = 0x83, + }, + { + .mbus_code = V4L2_MBUS_FMT_SBGGR12_1X12, + .gb_format = 0x84, + }, + { + .mbus_code = V4L2_MBUS_FMT_SGBRG12_1X12, + .gb_format = 0x85, + }, + { + .mbus_code = V4L2_MBUS_FMT_SGRBG12_1X12, + .gb_format = 0x86, + }, + { + .mbus_code = V4L2_MBUS_FMT_SRGGB12_1X12, + .gb_format = 0x87, + }, }; #define ES2_APB_CDSI0_CPORT 16 -- cgit v0.10.2 From 6910fa2dd6dc0d81c6ec4a2f36d6e21bd27b4479 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 22 Jun 2016 11:42:02 +0200 Subject: greybus: hd: add flag argument to cport_enable callback Add a flag argument to the host-device cport_enable callback that can be used to provide hints about the connection being created (e.g. connection priority). Reviewed-by: Alex Elder <elder@linaro.org> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 20a87b9..232af8d 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -286,7 +286,8 @@ static int gb_connection_hd_cport_enable(struct gb_connection *connection) if (!hd->driver->cport_enable) return 0; - ret = hd->driver->cport_enable(hd, connection->hd_cport_id); + ret = hd->driver->cport_enable(hd, connection->hd_cport_id, + connection->flags); if (ret) { dev_err(&hd->dev, "%s: failed to enable host cport: %d\n", connection->name, ret); diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h index 5136d0c..d5d8c67 100644 --- a/drivers/staging/greybus/hd.h +++ b/drivers/staging/greybus/hd.h @@ -19,7 +19,8 @@ struct gb_hd_driver { int (*cport_allocate)(struct gb_host_device *hd, int cport_id, unsigned long flags); void (*cport_release)(struct gb_host_device *hd, u16 cport_id); - int (*cport_enable)(struct gb_host_device *hd, u16 cport_id); + int (*cport_enable)(struct gb_host_device *hd, u16 cport_id, + unsigned long flags); int (*cport_disable)(struct gb_host_device *hd, u16 cport_id); int (*cport_flush)(struct gb_host_device *hd, u16 cport_id); int (*cport_ping)(struct gb_host_device *hd, u16 cport_id); -- cgit v0.10.2 From 1ba30c33096ced9d5c5814acdc46f53f3864f4e6 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 22 Jun 2016 11:42:03 +0200 Subject: greybus: connection: prevent drivers from specifying core flags Prevent drivers from specifying core flags (currently only GB_CONNECTION_FLAG_CONTROL) when creating connections. Reviewed-by: Alex Elder <elder@linaro.org> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 232af8d..7b2d635 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -260,6 +260,9 @@ gb_connection_create_flags(struct gb_bundle *bundle, u16 cport_id, { struct gb_interface *intf = bundle->intf; + if (WARN_ON_ONCE(flags & GB_CONNECTION_FLAG_CORE_MASK)) + flags &= ~GB_CONNECTION_FLAG_CORE_MASK; + return _gb_connection_create(intf->hd, -1, intf, bundle, cport_id, handler, flags); } @@ -269,12 +272,9 @@ struct gb_connection * gb_connection_create_offloaded(struct gb_bundle *bundle, u16 cport_id, unsigned long flags) { - struct gb_interface *intf = bundle->intf; - flags |= GB_CONNECTION_FLAG_OFFLOADED; - return _gb_connection_create(intf->hd, -1, intf, bundle, cport_id, - NULL, flags); + return gb_connection_create_flags(bundle, cport_id, NULL, flags); } EXPORT_SYMBOL_GPL(gb_connection_create_offloaded); diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 7d0988e..0ea8ac8 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -19,6 +19,8 @@ #define GB_CONNECTION_FLAG_CDSI1 BIT(3) #define GB_CONNECTION_FLAG_CONTROL BIT(4) +#define GB_CONNECTION_FLAG_CORE_MASK GB_CONNECTION_FLAG_CONTROL + enum gb_connection_state { GB_CONNECTION_STATE_DISABLED = 0, GB_CONNECTION_STATE_ENABLED_TX = 1, -- cgit v0.10.2 From 3094f9477301ec477fed2a43fef68c43e70e72ce Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 22 Jun 2016 11:42:04 +0200 Subject: greybus: connection: add support for high-priority connections Add connection flag to indicate that a connection has high priority. For the SVC and control connections this may be used by the host-device driver as a hint to allocate dedicated DMA channels or to use polling to avoid message congestion. We also allow drivers to set this flag on their connections, even though we currently have no use case for this (and the host-device driver is again free to ignore it). Note that this mechanism can be used to indicate also high-bandwidth connections (e.g. wanting larger buffers or dedicated endpoints), but that that should be done using a separate high-bandwidth flag rather than overloading the high-priority flag. Reviewed-by: Alex Elder <elder@linaro.org> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 7b2d635..9eb177e 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -232,14 +232,15 @@ gb_connection_create_static(struct gb_host_device *hd, u16 hd_cport_id, gb_request_handler_t handler) { return _gb_connection_create(hd, hd_cport_id, NULL, NULL, 0, handler, - 0); + GB_CONNECTION_FLAG_HIGH_PRIO); } struct gb_connection * gb_connection_create_control(struct gb_interface *intf) { return _gb_connection_create(intf->hd, -1, intf, NULL, 0, NULL, - GB_CONNECTION_FLAG_CONTROL); + GB_CONNECTION_FLAG_CONTROL | + GB_CONNECTION_FLAG_HIGH_PRIO); } struct gb_connection * diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h index 0ea8ac8..4d9f4c6 100644 --- a/drivers/staging/greybus/connection.h +++ b/drivers/staging/greybus/connection.h @@ -18,6 +18,7 @@ #define GB_CONNECTION_FLAG_OFFLOADED BIT(2) #define GB_CONNECTION_FLAG_CDSI1 BIT(3) #define GB_CONNECTION_FLAG_CONTROL BIT(4) +#define GB_CONNECTION_FLAG_HIGH_PRIO BIT(5) #define GB_CONNECTION_FLAG_CORE_MASK GB_CONNECTION_FLAG_CONTROL -- cgit v0.10.2 From 74ec7598b51fb347a1273f8deea42883ae725e6e Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 22 Jun 2016 11:42:05 +0200 Subject: greybus: es2: add support for greybus cport flags Add support for Greybus CPort flags that are sent to the bridge through a new USB vendor request when enabling a CPort as part of connection establishment. Currently the Greybus control and high-priority connection flags are recognised and forwarded to APBA. Reviewed-by: Alex Elder <elder@linaro.org> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 89fe764..2217445 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -607,6 +607,47 @@ static void es2_cport_release(struct gb_host_device *hd, u16 cport_id) ida_simple_remove(&hd->cport_id_map, cport_id); } +static int cport_enable(struct gb_host_device *hd, u16 cport_id, + unsigned long flags) +{ + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct usb_device *udev = es2->usb_dev; + struct gb_apb_request_cport_flags *req; + int ret; + + req = kzalloc(sizeof(*req), GFP_KERNEL); + if (!req) + return -ENOMEM; + + if (flags & GB_CONNECTION_FLAG_CONTROL) + req->flags |= GB_APB_CPORT_FLAG_CONTROL; + if (flags & GB_CONNECTION_FLAG_HIGH_PRIO) + req->flags |= GB_APB_CPORT_FLAG_HIGH_PRIO; + + dev_dbg(&hd->dev, "%s - cport = %u, flags = %02x\n", __func__, + cport_id, req->flags); + + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + GB_APB_REQUEST_CPORT_FLAGS, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, cport_id, 0, + req, sizeof(*req), ES2_TIMEOUT); + if (ret != sizeof(*req)) { + dev_err(&udev->dev, "failed to set cport flags for port %d\n", + cport_id); + if (ret >= 0) + ret = -EIO; + + goto out; + } + + ret = 0; +out: + kfree(req); + + return ret; +} + static int cport_disable(struct gb_host_device *hd, u16 cport_id) { int retval; @@ -799,6 +840,7 @@ static struct gb_hd_driver es2_driver = { .message_cancel = message_cancel, .cport_allocate = es2_cport_allocate, .cport_release = es2_cport_release, + .cport_enable = cport_enable, .cport_disable = cport_disable, .latency_tag_enable = latency_tag_enable, .latency_tag_disable = latency_tag_disable, diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 203bc46..327d01f 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -225,6 +225,16 @@ struct gb_control_timesync_get_last_event_response { #define REQUEST_TIMESYNC_AUTHORITATIVE 0x0f #define REQUEST_TIMESYNC_GET_LAST_EVENT 0x10 +/* requests to set Greybus CPort flags */ +#define GB_APB_REQUEST_CPORT_FLAGS 0x11 + +struct gb_apb_request_cport_flags { + u32 flags; +#define GB_APB_CPORT_FLAG_CONTROL 0x01 +#define GB_APB_CPORT_FLAG_HIGH_PRIO 0x02 +} __packed; + + /* Firmware Download Protocol */ /* Request Types */ -- cgit v0.10.2 From 0ef5be18852d0b044f916fd6194bb228f36e392a Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 27 Jun 2016 11:19:23 +0530 Subject: greybus: kernel_ver: Add kstrtobool() It was added in 4.6 and is required for one of the use case, copy it. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index 98e3179..80ed27c 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -341,4 +341,52 @@ static inline bool pwm_is_enabled(const struct pwm_device *pwm) } #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) +/** + * kstrtobool - convert common user inputs into boolean values + * @s: input string + * @res: result + * + * This routine returns 0 iff the first character is one of 'Yy1Nn0', or + * [oO][NnFf] for "on" and "off". Otherwise it will return -EINVAL. Value + * pointed to by res is updated upon finding a match. + */ +static inline int kstrtobool(const char *s, bool *res) +{ + if (!s) + return -EINVAL; + + switch (s[0]) { + case 'y': + case 'Y': + case '1': + *res = true; + return 0; + case 'n': + case 'N': + case '0': + *res = false; + return 0; + case 'o': + case 'O': + switch (s[1]) { + case 'n': + case 'N': + *res = true; + return 0; + case 'f': + case 'F': + *res = false; + return 0; + default: + break; + } + default: + break; + } + + return -EINVAL; +} +#endif + #endif /* __GREYBUS_KERNEL_VER_H */ -- cgit v0.10.2 From 1beb1fae808d82a409b1c6ad4575f890b946f0ca Mon Sep 17 00:00:00 2001 From: Sandeep Patil <sspatil@google.com> Date: Tue, 28 Jun 2016 12:10:14 -0700 Subject: greybus: svc: remove input device handling in SVC protocol The input device was added before to handle the key(s) connected directly to SVC, which is not the case anymore. So, this change removes the gb_svc_key_event() operation and the corresponding input device code with it. Testing Done: Boot tested and tried module insert/removal through AraManager Change-Id: Iaa541d4aefb5c0ed16caaa39450029de35d7c228 Signed-off-by: Sandeep Patil <sspatil@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 48d07a9..63d2a53 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -8,13 +8,10 @@ */ #include <linux/debugfs.h> -#include <linux/input.h> #include <linux/workqueue.h> #include "greybus.h" -#define SVC_KEY_ARA_BUTTON KEY_A - #define SVC_INTF_EJECT_TIMEOUT 9000 #define SVC_INTF_ACTIVATE_TIMEOUT 6000 @@ -887,13 +884,6 @@ static int gb_svc_hello(struct gb_operation *op) return ret; } - ret = input_register_device(svc->input); - if (ret) { - dev_err(&svc->dev, "failed to register input: %d\n", ret); - device_del(&svc->dev); - return ret; - } - ret = gb_svc_watchdog_create(svc); if (ret) { dev_err(&svc->dev, "failed to create watchdog: %d\n", ret); @@ -913,7 +903,6 @@ static int gb_svc_hello(struct gb_operation *op) err_unregister_device: gb_svc_watchdog_destroy(svc); - input_unregister_device(svc->input); device_del(&svc->dev); return ret; } @@ -1160,53 +1149,6 @@ static int gb_svc_intf_reset_recv(struct gb_operation *op) return 0; } -static int gb_svc_key_code_map(struct gb_svc *svc, u16 key_code, u16 *code) -{ - switch (key_code) { - case GB_KEYCODE_ARA: - *code = SVC_KEY_ARA_BUTTON; - break; - default: - dev_warn(&svc->dev, "unknown keycode received: %u\n", key_code); - return -EINVAL; - } - - return 0; -} - -static int gb_svc_key_event_recv(struct gb_operation *op) -{ - struct gb_svc *svc = gb_connection_get_data(op->connection); - struct gb_message *request = op->request; - struct gb_svc_key_event_request *key; - u16 code; - u8 event; - int ret; - - if (request->payload_size < sizeof(*key)) { - dev_warn(&svc->dev, "short key request received (%zu < %zu)\n", - request->payload_size, sizeof(*key)); - return -EINVAL; - } - - key = request->payload; - - ret = gb_svc_key_code_map(svc, le16_to_cpu(key->key_code), &code); - if (ret < 0) - return ret; - - event = key->key_event; - if ((event != GB_SVC_KEY_PRESSED) && (event != GB_SVC_KEY_RELEASED)) { - dev_warn(&svc->dev, "unknown key event received: %u\n", event); - return -EINVAL; - } - - input_report_key(svc->input, code, (event == GB_SVC_KEY_PRESSED)); - input_sync(svc->input); - - return 0; -} - static int gb_svc_module_inserted_recv(struct gb_operation *op) { struct gb_svc *svc = gb_connection_get_data(op->connection); @@ -1314,8 +1256,6 @@ static int gb_svc_request_handler(struct gb_operation *op) return ret; case GB_SVC_TYPE_INTF_RESET: return gb_svc_intf_reset_recv(op); - case GB_SVC_TYPE_KEY_EVENT: - return gb_svc_key_event_recv(op); case GB_SVC_TYPE_MODULE_INSERTED: return gb_svc_module_inserted_recv(op); case GB_SVC_TYPE_MODULE_REMOVED: @@ -1328,34 +1268,6 @@ static int gb_svc_request_handler(struct gb_operation *op) } } -static struct input_dev *gb_svc_input_create(struct gb_svc *svc) -{ - struct input_dev *input_dev; - - input_dev = input_allocate_device(); - if (!input_dev) - return ERR_PTR(-ENOMEM); - - input_dev->name = dev_name(&svc->dev); - svc->input_phys = kasprintf(GFP_KERNEL, "greybus-%s/input0", - input_dev->name); - if (!svc->input_phys) - goto err_free_input; - - input_dev->phys = svc->input_phys; - input_dev->dev.parent = &svc->dev; - - input_set_drvdata(input_dev, svc); - - input_set_capability(input_dev, EV_KEY, SVC_KEY_ARA_BUTTON); - - return input_dev; - -err_free_input: - input_free_device(input_dev); - return ERR_PTR(-ENOMEM); -} - static void gb_svc_release(struct device *dev) { struct gb_svc *svc = to_gb_svc(dev); @@ -1364,7 +1276,6 @@ static void gb_svc_release(struct device *dev) gb_connection_destroy(svc->connection); ida_destroy(&svc->device_id_map); destroy_workqueue(svc->wq); - kfree(svc->input_phys); kfree(svc); } @@ -1400,27 +1311,18 @@ struct gb_svc *gb_svc_create(struct gb_host_device *hd) svc->state = GB_SVC_STATE_RESET; svc->hd = hd; - svc->input = gb_svc_input_create(svc); - if (IS_ERR(svc->input)) { - dev_err(&svc->dev, "failed to create input device: %ld\n", - PTR_ERR(svc->input)); - goto err_put_device; - } - svc->connection = gb_connection_create_static(hd, GB_SVC_CPORT_ID, gb_svc_request_handler); if (IS_ERR(svc->connection)) { dev_err(&svc->dev, "failed to create connection: %ld\n", PTR_ERR(svc->connection)); - goto err_free_input; + goto err_put_device; } gb_connection_set_data(svc->connection, svc); return svc; -err_free_input: - input_free_device(svc->input); err_put_device: put_device(&svc->dev); return NULL; @@ -1459,14 +1361,12 @@ void gb_svc_del(struct gb_svc *svc) gb_connection_disable_rx(svc->connection); /* - * The SVC device and input device may have been registered - * from the request handler. + * The SVC device may have been registered from the request handler. */ if (device_is_registered(&svc->dev)) { gb_timesync_svc_remove(svc); gb_svc_debugfs_exit(svc); gb_svc_watchdog_destroy(svc); - input_unregister_device(svc->input); device_del(&svc->dev); } diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index dab8fba..7f5e534 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -42,8 +42,6 @@ struct gb_svc { u8 protocol_major; u8 protocol_minor; - struct input_dev *input; - char *input_phys; struct gb_svc_watchdog *watchdog; struct dentry *debugfs_dentry; -- cgit v0.10.2 From a29bac623f015045385411eb9b3eced95aa96686 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Mon, 27 Jun 2016 20:07:09 +0200 Subject: greybus: Revert "connection: switch to using spin_lock_irqsave/spin_lock_irqrestore excluisvely" This reverts commit 426237c515b42b9f06d9a2b1021a6d2c4d440c51. Someone decided that all use of spin_lock_irq was to be considered a bug and went on a search-and-replace type "bug-fixing" spree last week. This is however just plain wrong. Using spin_lock_irq is perfectly fine in paths were interrupts have not been disabled, and this is in fact even preferred over the lazy approach of always using spin_lock_irqsave instead of understanding the code that is being written or modified. All current uses of spin_lock_irq have already been vetted in this respect. Also note that it is only used in functions that may sleep, that is, in functions that must not be called with interrupts disabled in the first place. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 9eb177e..f261468 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -574,7 +574,7 @@ static int gb_connection_ping(struct gb_connection *connection) * DISCONNECTING. */ static void gb_connection_cancel_operations(struct gb_connection *connection, - int errno, unsigned long *flags) + int errno) __must_hold(&connection->lock) { struct gb_operation *operation; @@ -583,7 +583,7 @@ static void gb_connection_cancel_operations(struct gb_connection *connection, operation = list_last_entry(&connection->operations, struct gb_operation, links); gb_operation_get(operation); - spin_unlock_irqrestore(&connection->lock, *flags); + spin_unlock_irq(&connection->lock); if (gb_operation_is_incoming(operation)) gb_operation_cancel_incoming(operation, errno); @@ -592,7 +592,7 @@ static void gb_connection_cancel_operations(struct gb_connection *connection, gb_operation_put(operation); - spin_lock_irqsave(&connection->lock, *flags); + spin_lock_irq(&connection->lock); } } @@ -603,7 +603,7 @@ static void gb_connection_cancel_operations(struct gb_connection *connection, */ static void gb_connection_flush_incoming_operations(struct gb_connection *connection, - int errno, unsigned long *flags) + int errno) __must_hold(&connection->lock) { struct gb_operation *operation; @@ -623,13 +623,13 @@ gb_connection_flush_incoming_operations(struct gb_connection *connection, if (!incoming) break; - spin_unlock_irqrestore(&connection->lock, *flags); + spin_unlock_irq(&connection->lock); /* FIXME: flush, not cancel? */ gb_operation_cancel_incoming(operation, errno); gb_operation_put(operation); - spin_lock_irqsave(&connection->lock, *flags); + spin_lock_irq(&connection->lock); } } @@ -646,16 +646,15 @@ gb_connection_flush_incoming_operations(struct gb_connection *connection, static int _gb_connection_enable(struct gb_connection *connection, bool rx) { int ret; - unsigned long flags; /* Handle ENABLED_TX -> ENABLED transitions. */ if (connection->state == GB_CONNECTION_STATE_ENABLED_TX) { if (!(connection->handler && rx)) return 0; - spin_lock_irqsave(&connection->lock, flags); + spin_lock_irq(&connection->lock); connection->state = GB_CONNECTION_STATE_ENABLED; - spin_unlock_irqrestore(&connection->lock, flags); + spin_unlock_irq(&connection->lock); return 0; } @@ -672,12 +671,12 @@ static int _gb_connection_enable(struct gb_connection *connection, bool rx) if (ret) goto err_svc_connection_destroy; - spin_lock_irqsave(&connection->lock, flags); + spin_lock_irq(&connection->lock); if (connection->handler && rx) connection->state = GB_CONNECTION_STATE_ENABLED; else connection->state = GB_CONNECTION_STATE_ENABLED_TX; - spin_unlock_irqrestore(&connection->lock, flags); + spin_unlock_irq(&connection->lock); ret = gb_connection_control_connected(connection); if (ret) @@ -688,10 +687,10 @@ static int _gb_connection_enable(struct gb_connection *connection, bool rx) err_control_disconnecting: gb_connection_control_disconnecting(connection); - spin_lock_irqsave(&connection->lock, flags); + spin_lock_irq(&connection->lock); connection->state = GB_CONNECTION_STATE_DISCONNECTING; - gb_connection_cancel_operations(connection, -ESHUTDOWN, &flags); - spin_unlock_irqrestore(&connection->lock, flags); + gb_connection_cancel_operations(connection, -ESHUTDOWN); + spin_unlock_irq(&connection->lock); /* Transmit queue should already be empty. */ gb_connection_hd_cport_flush(connection); @@ -757,18 +756,16 @@ EXPORT_SYMBOL_GPL(gb_connection_enable_tx); void gb_connection_disable_rx(struct gb_connection *connection) { - unsigned long flags; - mutex_lock(&connection->mutex); - spin_lock_irqsave(&connection->lock, flags); + spin_lock_irq(&connection->lock); if (connection->state != GB_CONNECTION_STATE_ENABLED) { - spin_unlock_irqrestore(&connection->lock, flags); + spin_unlock_irq(&connection->lock); goto out_unlock; } connection->state = GB_CONNECTION_STATE_ENABLED_TX; - gb_connection_flush_incoming_operations(connection, -ESHUTDOWN, &flags); - spin_unlock_irqrestore(&connection->lock, flags); + gb_connection_flush_incoming_operations(connection, -ESHUTDOWN); + spin_unlock_irq(&connection->lock); trace_gb_connection_disable(connection); @@ -791,8 +788,6 @@ void gb_connection_mode_switch_complete(struct gb_connection *connection) void gb_connection_disable(struct gb_connection *connection) { - unsigned long flags; - mutex_lock(&connection->mutex); if (connection->state == GB_CONNECTION_STATE_DISABLED) @@ -802,10 +797,10 @@ void gb_connection_disable(struct gb_connection *connection) gb_connection_control_disconnecting(connection); - spin_lock_irqsave(&connection->lock, flags); + spin_lock_irq(&connection->lock); connection->state = GB_CONNECTION_STATE_DISCONNECTING; - gb_connection_cancel_operations(connection, -ESHUTDOWN, &flags); - spin_unlock_irqrestore(&connection->lock, flags); + gb_connection_cancel_operations(connection, -ESHUTDOWN); + spin_unlock_irq(&connection->lock); gb_connection_hd_cport_flush(connection); @@ -832,8 +827,6 @@ EXPORT_SYMBOL_GPL(gb_connection_disable); /* Disable a connection without communicating with the remote end. */ void gb_connection_disable_forced(struct gb_connection *connection) { - unsigned long flags; - mutex_lock(&connection->mutex); if (connection->state == GB_CONNECTION_STATE_DISABLED) @@ -841,10 +834,10 @@ void gb_connection_disable_forced(struct gb_connection *connection) trace_gb_connection_disable(connection); - spin_lock_irqsave(&connection->lock, flags); + spin_lock_irq(&connection->lock); connection->state = GB_CONNECTION_STATE_DISABLED; - gb_connection_cancel_operations(connection, -ESHUTDOWN, &flags); - spin_unlock_irqrestore(&connection->lock, flags); + gb_connection_cancel_operations(connection, -ESHUTDOWN); + spin_unlock_irq(&connection->lock); gb_connection_hd_cport_flush(connection); gb_connection_hd_cport_features_disable(connection); -- cgit v0.10.2 From 0b1d262354214daab1a3b7df763dc51c355ec353 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Mon, 27 Jun 2016 20:07:10 +0200 Subject: greybus: Revert "greybus: gb_connections_lock: don't use spin_lock_irq()" This reverts commit b022fd95108e8b9d202532a74d39e86152bc8f7f. Someone decided that all use of spin_lock_irq was to be considered a bug and went on a search-and-replace type "bug-fixing" spree last week. This is however just plain wrong. Using spin_lock_irq is perfectly fine in paths were interrupts have not been disabled, and this is in fact even preferred over the lazy approach of always using spin_lock_irqsave instead of understanding the code that is being written or modified. All current uses of spin_lock_irq have already been vetted in this respect. Also note that it is only used in functions that may sleep, that is, in functions that must not be called with interrupts disabled in the first place. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index f261468..632c8be 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -150,7 +150,6 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, unsigned long flags) { struct gb_connection *connection; - unsigned long irqflags; int ret; mutex_lock(&gb_connection_mutex); @@ -201,7 +200,7 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, gb_connection_init_name(connection); - spin_lock_irqsave(&gb_connections_lock, irqflags); + spin_lock_irq(&gb_connections_lock); list_add(&connection->hd_links, &hd->connections); if (bundle) @@ -209,7 +208,7 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, else INIT_LIST_HEAD(&connection->bundle_links); - spin_unlock_irqrestore(&gb_connections_lock, irqflags); + spin_unlock_irq(&gb_connections_lock); mutex_unlock(&gb_connection_mutex); @@ -852,8 +851,6 @@ EXPORT_SYMBOL_GPL(gb_connection_disable_forced); /* Caller must have disabled the connection before destroying it. */ void gb_connection_destroy(struct gb_connection *connection) { - unsigned long flags; - if (!connection) return; @@ -862,10 +859,10 @@ void gb_connection_destroy(struct gb_connection *connection) mutex_lock(&gb_connection_mutex); - spin_lock_irqsave(&gb_connections_lock, flags); + spin_lock_irq(&gb_connections_lock); list_del(&connection->bundle_links); list_del(&connection->hd_links); - spin_unlock_irqrestore(&gb_connections_lock, flags); + spin_unlock_irq(&gb_connections_lock); destroy_workqueue(connection->wq); -- cgit v0.10.2 From 07af934094ed7d79442dcec82305001e3a66ad6c Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Mon, 27 Jun 2016 20:07:11 +0200 Subject: greybus: Revert "greybus: es2.c: don't use spin_lock_irq()" This reverts commit b44c3b5b0307788750eb4c462ed5982236876a8b. Someone decided that all use of spin_lock_irq was to be considered a bug and went on a search-and-replace type "bug-fixing" spree last week. This is however just plain wrong. Using spin_lock_irq is perfectly fine in paths were interrupts have not been disabled, and this is in fact even preferred over the lazy approach of always using spin_lock_irqsave instead of understanding the code that is being written or modified. All current uses of spin_lock_irq have already been vetted in this respect. Also note that it is only used in functions that may sleep, that is, in functions that must not be called with interrupts disabled in the first place. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 2217445..5bdf2e1 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -496,12 +496,11 @@ static void message_cancel(struct gb_message *message) struct gb_host_device *hd = message->operation->connection->hd; struct es2_ap_dev *es2 = hd_to_es2(hd); struct urb *urb; - unsigned long flags; int i; might_sleep(); - spin_lock_irqsave(&es2->cport_out_urb_lock, flags); + spin_lock_irq(&es2->cport_out_urb_lock); urb = message->hcpriv; /* Prevent dynamically allocated urb from being deallocated. */ @@ -514,14 +513,14 @@ static void message_cancel(struct gb_message *message) break; } } - spin_unlock_irqrestore(&es2->cport_out_urb_lock, flags); + spin_unlock_irq(&es2->cport_out_urb_lock); usb_kill_urb(urb); if (i < NUM_CPORT_OUT_URB) { - spin_lock_irqsave(&es2->cport_out_urb_lock, flags); + spin_lock_irq(&es2->cport_out_urb_lock); es2->cport_out_urb_cancelled[i] = false; - spin_unlock_irqrestore(&es2->cport_out_urb_lock, flags); + spin_unlock_irq(&es2->cport_out_urb_lock); } usb_free_urb(urb); -- cgit v0.10.2 From 2aae92bdc25325cfd782cc76842a4302540958f2 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Mon, 27 Jun 2016 20:07:12 +0200 Subject: greybus: Revert "greybus: uart: don't use spin_lock_irq()" This reverts commit bd3c4aa99dc23449699432e0744bcb5af7afa98c. Someone decided that all use of spin_lock_irq was to be considered a bug and went on a search-and-replace type "bug-fixing" spree last week. This is however just plain wrong. Using spin_lock_irq is perfectly fine in paths were interrupts have not been disabled, and this is in fact even preferred over the lazy approach of always using spin_lock_irqsave instead of understanding the code that is being written or modified. All current uses of spin_lock_irq have already been vetted in this respect. Also note that it is only used in functions that may sleep, that is, in functions that must not be called with interrupts disabled in the first place. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 8089638..6260569 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -674,7 +674,6 @@ static int set_serial_info(struct gb_tty *gb_tty, static int wait_serial_change(struct gb_tty *gb_tty, unsigned long arg) { int retval = 0; - unsigned long flags; DECLARE_WAITQUEUE(wait, current); struct async_icount old; struct async_icount new; @@ -683,11 +682,11 @@ static int wait_serial_change(struct gb_tty *gb_tty, unsigned long arg) return -EINVAL; do { - spin_lock_irqsave(&gb_tty->read_lock, flags); + spin_lock_irq(&gb_tty->read_lock); old = gb_tty->oldcount; new = gb_tty->iocount; gb_tty->oldcount = new; - spin_unlock_irqrestore(&gb_tty->read_lock, flags); + spin_unlock_irq(&gb_tty->read_lock); if ((arg & TIOCM_DSR) && (old.dsr != new.dsr)) break; -- cgit v0.10.2 From 957ccca08a990888e2a8f057dee646b8f37b1660 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Wed, 29 Jun 2016 13:42:26 -0700 Subject: greybus: light: Initialize mutex before using it Light protocol driver is suffering from the same issue that was fixed in camera driver earlier (commit a7c3b0c3c8da). Big cleanup function is used instead of fine grained control in the error path, and in one of the cases the mutex was found uninitialized and so the oops seen in SW-6752. Initialize the mutex before any code can access it. Compile tested only. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Rui Miguel Silva <rui.silva@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index 78fb8a9..3d42a5d 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -1221,6 +1221,8 @@ static int gb_lights_probe(struct gb_bundle *bundle, if (!glights) return -ENOMEM; + mutex_init(&glights->lights_lock); + connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id), gb_lights_request_handler); if (IS_ERR(connection)) { @@ -1231,8 +1233,6 @@ static int gb_lights_probe(struct gb_bundle *bundle, glights->connection = connection; gb_connection_set_data(connection, glights); - mutex_init(&glights->lights_lock); - greybus_set_drvdata(bundle, glights); /* We aren't ready to receive an incoming request yet */ -- cgit v0.10.2 From 0c15a9e0f3f7174718351fcb1c16be944f3b8a57 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Tue, 5 Jul 2016 17:09:20 -0500 Subject: greybus: audio: topology: Add helper API to map controlid with widget name This API is used by enumerated controls .get/.set callback functions to fetch control id associated with a widget. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mark.greer@animalcreek.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index 5a19467..f4936f1 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -123,6 +123,7 @@ struct gbaudio_widget { struct gbaudio_control { __u8 id; char *name; + char *wname; const char * const *texts; struct list_head list; }; diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index 1f9e8b6..1bc9874 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -77,6 +77,20 @@ static const char *gbaudio_map_controlid(struct gbaudio_module_info *module, return NULL; } +static int gbaudio_map_wcontrolname(struct gbaudio_module_info *module, + const char *name) +{ + struct gbaudio_control *control; + + list_for_each_entry(control, &module->widget_ctl_list, list) { + if (!strncmp(control->wname, name, NAME_SIZE)) + return control->id; + } + dev_warn(module->dev, "%s: missing in modules controls list\n", name); + + return -EINVAL; +} + static int gbaudio_map_widgetname(struct gbaudio_module_info *module, const char *name) { @@ -652,6 +666,8 @@ static int gbaudio_tplg_create_widget(struct gbaudio_module_info *module, } control->id = curr->id; control->name = curr->name; + control->wname = w->name; + if (curr->info.type == GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED) control->texts = (const char * const *) curr->info.value.enumerated.names; -- cgit v0.10.2 From bb296b48038010dee1c55aa24264f3205ec949fd Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Thu, 30 Jun 2016 18:45:35 +0530 Subject: greybus: added warning message in case of missing widget Additional warning message added to notify in case above layer tries to access widget that is already removed from the list. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mark.greer@animalcreek.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index 1bc9874..92f2ada 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -99,6 +99,8 @@ static int gbaudio_map_widgetname(struct gbaudio_module_info *module, if (!strncmp(widget->name, name, NAME_SIZE)) return widget->id; } + dev_warn(module->dev, "%s: missing in modules widgets list\n", name); + return -EINVAL; } -- cgit v0.10.2 From d4cd9daa49b2dc46497d40d0251b27d0d685754e Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Tue, 5 Jul 2016 17:09:20 -0500 Subject: greybus: audio: topology: Use csize while computing next_ptr in parser Size of control elements vary in case of enumerated controls. As a preparation to enable enumerated control in topology parser, this patch uses csize while parsing controls & wsize while parsing widgets & its control to update next pointer. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mark.greer@animalcreek.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index 92f2ada..1305483 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -624,9 +624,9 @@ static int gbaudio_widget_event(struct snd_soc_dapm_widget *w, static int gbaudio_tplg_create_widget(struct gbaudio_module_info *module, struct snd_soc_dapm_widget *dw, - struct gb_audio_widget *w) + struct gb_audio_widget *w, int *w_size) { - int i, ret; + int i, ret, csize; struct snd_kcontrol_new *widget_kctls; struct gb_audio_control *curr; struct gbaudio_control *control, *_control; @@ -648,9 +648,11 @@ static int gbaudio_tplg_create_widget(struct gbaudio_module_info *module, return -ENOMEM; } + *w_size = sizeof(struct gb_audio_widget); + /* create relevant kcontrols */ + curr = w->ctl; for (i = 0; i < w->ncontrols; i++) { - curr = &w->ctl[i]; ret = gbaudio_tplg_create_wcontrol(module, &widget_kctls[i], curr); if (ret) { @@ -673,6 +675,9 @@ static int gbaudio_tplg_create_widget(struct gbaudio_module_info *module, if (curr->info.type == GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED) control->texts = (const char * const *) curr->info.value.enumerated.names; + csize = sizeof(struct gb_audio_control); + *w_size += csize; + curr = (void *)curr + csize; list_add(&control->list, &module->widget_ctl_list); dev_dbg(module->dev, "%s: control of type %d created\n", widget_kctls[i].name, widget_kctls[i].iface); @@ -771,7 +776,7 @@ error: static int gbaudio_tplg_process_kcontrols(struct gbaudio_module_info *module, struct gb_audio_control *controls) { - int i, ret; + int i, csize, ret; struct snd_kcontrol_new *dapm_kctls; struct gb_audio_control *curr; struct gbaudio_control *control, *_control; @@ -808,10 +813,12 @@ static int gbaudio_tplg_process_kcontrols(struct gbaudio_module_info *module, if (curr->info.type == GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED) control->texts = (const char * const *) curr->info.value.enumerated.names; + csize = sizeof(struct gb_audio_control); + list_add(&control->list, &module->ctl_list); dev_dbg(module->dev, "%d:%s created of type %d\n", curr->id, curr->name, curr->info.type); - curr++; + curr = (void *)curr + csize; } module->controls = dapm_kctls; @@ -829,7 +836,7 @@ error: static int gbaudio_tplg_process_widgets(struct gbaudio_module_info *module, struct gb_audio_widget *widgets) { - int i, ret, ncontrols; + int i, ret, w_size; struct snd_soc_dapm_widget *dapm_widgets; struct gb_audio_widget *curr; struct gbaudio_widget *widget, *_widget; @@ -843,7 +850,7 @@ static int gbaudio_tplg_process_widgets(struct gbaudio_module_info *module, curr = widgets; for (i = 0; i < module->num_dapm_widgets; i++) { ret = gbaudio_tplg_create_widget(module, &dapm_widgets[i], - curr); + curr, &w_size); if (ret) { dev_err(module->dev, "%s:%d type not supported\n", curr->name, curr->type); @@ -859,9 +866,7 @@ static int gbaudio_tplg_process_widgets(struct gbaudio_module_info *module, widget->id = curr->id; widget->name = curr->name; list_add(&widget->list, &module->widget_list); - ncontrols = curr->ncontrols; - curr++; - curr = (void *)curr + ncontrols*sizeof(struct gb_audio_control); + curr = (void *)curr + w_size; } module->dapm_widgets = dapm_widgets; -- cgit v0.10.2 From e65579e335da0a65b5a76a343ddff6a6f3c77dd1 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Thu, 30 Jun 2016 18:45:37 +0530 Subject: greybus: audio: topology: Enable enumerated control support Added .get/.set callback and relevant changes in parser to enable enumerated control support for kcontrols and DAPM widget controls. Currently, it is limited to enumerated strings only. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mark.greer@animalcreek.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index 1305483..e0779ca 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -53,7 +53,7 @@ static struct gbaudio_module_info *find_gb_module( } static const char *gbaudio_map_controlid(struct gbaudio_module_info *module, - __u8 control_id, __u8 index) + __u8 control_id, __u8 index) { struct gbaudio_control *control; @@ -77,8 +77,23 @@ static const char *gbaudio_map_controlid(struct gbaudio_module_info *module, return NULL; } +static int gbaudio_map_controlname(struct gbaudio_module_info *module, + const char *name) +{ + struct gbaudio_control *control; + + list_for_each_entry(control, &module->ctl_list, list) { + if (!strncmp(control->name, name, NAME_SIZE)) + return control->id; + } + + dev_warn(module->dev, "%s: missing in modules controls list\n", name); + + return -EINVAL; +} + static int gbaudio_map_wcontrolname(struct gbaudio_module_info *module, - const char *name) + const char *name) { struct gbaudio_control *control; @@ -92,7 +107,7 @@ static int gbaudio_map_wcontrolname(struct gbaudio_module_info *module, } static int gbaudio_map_widgetname(struct gbaudio_module_info *module, - const char *name) + const char *name) { struct gbaudio_widget *widget; list_for_each_entry(widget, &module->widget_list, list) { @@ -105,7 +120,7 @@ static int gbaudio_map_widgetname(struct gbaudio_module_info *module, } static const char *gbaudio_map_widgetid(struct gbaudio_module_info *module, - __u8 widget_id) + __u8 widget_id) { struct gbaudio_widget *widget; @@ -116,6 +131,27 @@ static const char *gbaudio_map_widgetid(struct gbaudio_module_info *module, return NULL; } +const char **gb_generate_enum_strings(struct gbaudio_module_info *gb, + struct gb_audio_enumerated *gbenum) +{ + const char **strings; + int i; + __u8 *data; + + strings = devm_kzalloc(gb->dev, sizeof(char *) * gbenum->items, + GFP_KERNEL); + data = gbenum->names; + + for (i = 0; i < gbenum->items; i++) { + strings[i] = (const char *)data; + while (*data != '\0') + data++; + data++; + } + + return strings; +} + static int gbcodec_mixer_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -473,60 +509,288 @@ static int gbaudio_validate_kcontrol_count(struct gb_audio_widget *w) return ret; } +static int gbcodec_enum_ctl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret, ctl_id; + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + struct gb_audio_ctl_elem_value gbvalue; + struct gbaudio_module_info *module; + struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + + module = find_gb_module(gb, kcontrol->id.name); + if (!module) + return -EINVAL; + + ctl_id = gbaudio_map_controlname(module, kcontrol->id.name); + if (ctl_id < 0) + return -EINVAL; + + ret = gb_audio_gb_get_control(module->mgmt_connection, ctl_id, + GB_AUDIO_INVALID_INDEX, &gbvalue); + if (ret) { + dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, + __func__, kcontrol->id.name); + return ret; + } + + ucontrol->value.enumerated.item[0] = gbvalue.value.enumerated_item[0]; + if (e->shift_l != e->shift_r) + ucontrol->value.enumerated.item[1] = + gbvalue.value.enumerated_item[1]; + + return 0; +} + +static int gbcodec_enum_ctl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret, ctl_id; + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + struct gb_audio_ctl_elem_value gbvalue; + struct gbaudio_module_info *module; + struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + + module = find_gb_module(gb, kcontrol->id.name); + if (!module) + return -EINVAL; + + ctl_id = gbaudio_map_controlname(module, kcontrol->id.name); + if (ctl_id < 0) + return -EINVAL; + + if (ucontrol->value.enumerated.item[0] > e->max - 1) + return -EINVAL; + gbvalue.value.enumerated_item[0] = ucontrol->value.enumerated.item[0]; + + if (e->shift_l != e->shift_r) { + if (ucontrol->value.enumerated.item[1] > e->max - 1) + return -EINVAL; + gbvalue.value.enumerated_item[1] = + ucontrol->value.enumerated.item[1]; + } + + ret = gb_audio_gb_set_control(module->mgmt_connection, ctl_id, + GB_AUDIO_INVALID_INDEX, &gbvalue); + if (ret) { + dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, + __func__, kcontrol->id.name); + } + + return ret; +} + +static int gbaudio_tplg_create_enum_kctl(struct gbaudio_module_info *gb, + struct snd_kcontrol_new *kctl, + struct gb_audio_control *ctl) +{ + struct soc_enum *gbe; + struct gb_audio_enumerated *gb_enum; + int i; + + gbe = devm_kzalloc(gb->dev, sizeof(*gbe), GFP_KERNEL); + if (!gbe) + return -ENOMEM; + + gb_enum = &ctl->info.value.enumerated; + + /* since count=1, and reg is dummy */ + gbe->max = gb_enum->items; + gbe->texts = gb_generate_enum_strings(gb, gb_enum); + + /* debug enum info */ + dev_dbg(gb->dev, "Max:%d, name_length:%d\n", gb_enum->items, + gb_enum->names_length); + for (i = 0; i < gb_enum->items; i++) + dev_dbg(gb->dev, "src[%d]: %s\n", i, gbe->texts[i]); + + *kctl = (struct snd_kcontrol_new) + SOC_ENUM_EXT(ctl->name, *gbe, gbcodec_enum_ctl_get, + gbcodec_enum_ctl_put); + return 0; +} + static int gbaudio_tplg_create_kcontrol(struct gbaudio_module_info *gb, struct snd_kcontrol_new *kctl, struct gb_audio_control *ctl) { + int ret = 0; struct gbaudio_ctl_pvt *ctldata; switch (ctl->iface) { case SNDRV_CTL_ELEM_IFACE_MIXER: - ctldata = devm_kzalloc(gb->dev, sizeof(struct gbaudio_ctl_pvt), - GFP_KERNEL); - if (!ctldata) - return -ENOMEM; - ctldata->ctl_id = ctl->id; - ctldata->data_cport = ctl->data_cport; - ctldata->access = ctl->access; - ctldata->vcount = ctl->count_values; - ctldata->info = &ctl->info; - *kctl = (struct snd_kcontrol_new) - SOC_MIXER_GB(ctl->name, ctl->count, ctldata); - ctldata = NULL; + switch (ctl->info.type) { + case GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED: + ret = gbaudio_tplg_create_enum_kctl(gb, kctl, ctl); + break; + default: + ctldata = devm_kzalloc(gb->dev, + sizeof(struct gbaudio_ctl_pvt), + GFP_KERNEL); + if (!ctldata) + return -ENOMEM; + ctldata->ctl_id = ctl->id; + ctldata->data_cport = ctl->data_cport; + ctldata->access = ctl->access; + ctldata->vcount = ctl->count_values; + ctldata->info = &ctl->info; + *kctl = (struct snd_kcontrol_new) + SOC_MIXER_GB(ctl->name, ctl->count, ctldata); + ctldata = NULL; + break; + } break; default: return -EINVAL; } dev_dbg(gb->dev, "%s:%d control created\n", ctl->name, ctl->id); + return ret; +} + +static int gbcodec_enum_dapm_ctl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret, ctl_id; + struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); + struct snd_soc_dapm_widget *widget = wlist->widgets[0]; + struct gbaudio_module_info *module; + struct gb_audio_ctl_elem_value gbvalue; + struct snd_soc_codec *codec = widget->codec; + struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + + module = find_gb_module(gb, kcontrol->id.name); + if (!module) + return -EINVAL; + + ctl_id = gbaudio_map_wcontrolname(module, kcontrol->id.name); + if (ctl_id < 0) + return -EINVAL; + + ret = gb_audio_gb_get_control(module->mgmt_connection, ctl_id, + GB_AUDIO_INVALID_INDEX, &gbvalue); + if (ret) { + dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, + __func__, kcontrol->id.name); + return ret; + } + + ucontrol->value.enumerated.item[0] = gbvalue.value.enumerated_item[0]; + if (e->shift_l != e->shift_r) + ucontrol->value.enumerated.item[1] = + gbvalue.value.enumerated_item[1]; + return 0; } -static const char * const gbtexts[] = {"Stereo", "Left", "Right"}; +static int gbcodec_enum_dapm_ctl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret, wi, ctl_id; + unsigned int val, mux, change; + unsigned int mask; + struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); + struct snd_soc_dapm_widget *widget = wlist->widgets[0]; + struct gb_audio_ctl_elem_value gbvalue; + struct gbaudio_module_info *module; + struct snd_soc_codec *codec = widget->codec; + struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + + if (ucontrol->value.enumerated.item[0] > e->max - 1) + return -EINVAL; + + module = find_gb_module(gb, kcontrol->id.name); + if (!module) + return -EINVAL; + + ctl_id = gbaudio_map_wcontrolname(module, kcontrol->id.name); + if (ctl_id < 0) + return -EINVAL; + + change = 0; + ret = gb_audio_gb_get_control(module->mgmt_connection, ctl_id, + GB_AUDIO_INVALID_INDEX, &gbvalue); + if (ret) { + dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, + __func__, kcontrol->id.name); + return ret; + } -static const SOC_ENUM_SINGLE_DECL( - module_apb1_rx_enum, GBCODEC_APB1_MUX_REG, 0, gbtexts); + mux = ucontrol->value.enumerated.item[0]; + val = mux << e->shift_l; + mask = e->mask << e->shift_l; -static const SOC_ENUM_SINGLE_DECL( - module_mic_enum, GBCODEC_APB1_MUX_REG, 4, gbtexts); + if (gbvalue.value.enumerated_item[0] != + ucontrol->value.enumerated.item[0]) { + change = 1; + gbvalue.value.enumerated_item[0] = + ucontrol->value.enumerated.item[0]; + } + + if (e->shift_l != e->shift_r) { + if (ucontrol->value.enumerated.item[1] > e->max - 1) + return -EINVAL; + val |= ucontrol->value.enumerated.item[1] << e->shift_r; + mask |= e->mask << e->shift_r; + if (gbvalue.value.enumerated_item[1] != + ucontrol->value.enumerated.item[1]) { + change = 1; + gbvalue.value.enumerated_item[1] = + ucontrol->value.enumerated.item[1]; + } + } + + if (change) { + ret = gb_audio_gb_set_control(module->mgmt_connection, ctl_id, + GB_AUDIO_INVALID_INDEX, &gbvalue); + if (ret) { + dev_err_ratelimited(codec->dev, + "%d:Error in %s for %s\n", ret, + __func__, kcontrol->id.name); + } + for (wi = 0; wi < wlist->num_widgets; wi++) { + widget = wlist->widgets[wi]; + + widget->value = val; + widget->dapm->update = NULL; + snd_soc_dapm_mux_update_power(widget, kcontrol, mux, e); + } + } + + return change; +} static int gbaudio_tplg_create_enum_ctl(struct gbaudio_module_info *gb, struct snd_kcontrol_new *kctl, struct gb_audio_control *ctl) { - switch (ctl->id) { - case 8: - *kctl = (struct snd_kcontrol_new) - SOC_DAPM_ENUM(ctl->name, module_apb1_rx_enum); - break; - case 9: - *kctl = (struct snd_kcontrol_new) - SOC_DAPM_ENUM(ctl->name, module_mic_enum); - break; - default: - return -EINVAL; - } + struct soc_enum *gbe; + struct gb_audio_enumerated *gb_enum; + int i; + + gbe = devm_kzalloc(gb->dev, sizeof(*gbe), GFP_KERNEL); + if (!gbe) + return -ENOMEM; + gb_enum = &ctl->info.value.enumerated; + + /* since count=1, and reg is dummy */ + gbe->max = gb_enum->items; + gbe->texts = gb_generate_enum_strings(gb, gb_enum); + + /* debug enum info */ + dev_dbg(gb->dev, "Max:%d, name_length:%d\n", gb_enum->items, + gb_enum->names_length); + for (i = 0; i < gb_enum->items; i++) + dev_dbg(gb->dev, "src[%d]: %s\n", i, gbe->texts[i]); + + *kctl = (struct snd_kcontrol_new) + SOC_DAPM_ENUM_EXT(ctl->name, *gbe, gbcodec_enum_dapm_ctl_get, + gbcodec_enum_dapm_ctl_put); return 0; } @@ -672,10 +936,18 @@ static int gbaudio_tplg_create_widget(struct gbaudio_module_info *module, control->name = curr->name; control->wname = w->name; - if (curr->info.type == GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED) + if (curr->info.type == GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED) { + struct gb_audio_enumerated *gbenum = + &curr->info.value.enumerated; + + csize = offsetof(struct gb_audio_control, info); + csize += offsetof(struct gb_audio_ctl_elem_info, value); + csize += offsetof(struct gb_audio_enumerated, names); + csize += gbenum->names_length; control->texts = (const char * const *) - curr->info.value.enumerated.names; - csize = sizeof(struct gb_audio_control); + gb_generate_enum_strings(module, gbenum); + } else + csize = sizeof(struct gb_audio_control); *w_size += csize; curr = (void *)curr + csize; list_add(&control->list, &module->widget_ctl_list); @@ -810,10 +1082,18 @@ static int gbaudio_tplg_process_kcontrols(struct gbaudio_module_info *module, snprintf(curr->name, NAME_SIZE, "GB %d %s", module->dev_id, temp_name); control->name = curr->name; - if (curr->info.type == GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED) + if (curr->info.type == GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED) { + struct gb_audio_enumerated *gbenum = + &curr->info.value.enumerated; + + csize = offsetof(struct gb_audio_control, info); + csize += offsetof(struct gb_audio_ctl_elem_info, value); + csize += offsetof(struct gb_audio_enumerated, names); + csize += gbenum->names_length; control->texts = (const char * const *) - curr->info.value.enumerated.names; - csize = sizeof(struct gb_audio_control); + gb_generate_enum_strings(module, gbenum); + } else + csize = sizeof(struct gb_audio_control); list_add(&control->list, &module->ctl_list); dev_dbg(module->dev, "%d:%s created of type %d\n", curr->id, -- cgit v0.10.2 From 7f93eab7c705527b0579b1bfd4d6e9f6acc9e5ca Mon Sep 17 00:00:00 2001 From: Jacopo Mondi <jacopo.mondi@linaro.org> Date: Thu, 30 Jun 2016 09:18:00 -0500 Subject: greybus: camera: Early update num_streams and flags In configure_streams Operation, when returning from the greybus operation call, we can assign the num_streams and flags variable earlier so that if the following stream configuration inspection fails, the caller receives the right number of configured streams anyway Testing Done: White camera module preview and capture. Triggering failure during stream configuration inspection makes configuration fails, but avoid segfaulting as was previously happening Signed-off-by: Jacopo Mondi <jacopo.mondi@linaro.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@linaro.org> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index c47e424..584f85e 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -432,6 +432,9 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, goto done; } + *flags = resp->flags; + *num_streams = resp->num_streams; + for (i = 0; i < nstreams; ++i) { struct gb_camera_stream_config_response *cfg = &resp->config[i]; @@ -451,11 +454,8 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, } if ((resp->flags & GB_CAMERA_CONFIGURE_STREAMS_ADJUSTED) || - (*flags & GB_CAMERA_CONFIGURE_STREAMS_TEST_ONLY)) { - *flags = resp->flags; - *num_streams = resp->num_streams; + (req->flags & GB_CAMERA_CONFIGURE_STREAMS_TEST_ONLY)) goto done; - } if (gcam->state == GB_CAMERA_STATE_CONFIGURED) { gb_camera_teardown_data_connection(gcam); @@ -469,15 +469,14 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, gb_operation_sync(gcam->connection, GB_CAMERA_TYPE_CONFIGURE_STREAMS, req, req_size, resp, resp_size); + *flags = 0; + *num_streams = 0; goto done; } gcam->state = GB_CAMERA_STATE_CONFIGURED; } - *flags = resp->flags; - *num_streams = resp->num_streams; - done: mutex_unlock(&gcam->mutex); kfree(req); -- cgit v0.10.2 From 36ab1108b60eb649c7c0f0653f854afc1234cfcb Mon Sep 17 00:00:00 2001 From: Jacopo Mondi <jacopo.mondi@linaro.org> Date: Thu, 30 Jun 2016 09:18:00 -0500 Subject: greybus: camera: Fix number of configured streams Camera Module may report a lower number of configured streams than the one requested by the AP. All the non-supported stream configuration are zeroed. Make the stream configuration inspection loop take only the valid stream into account, to avoid unnecessarily accessing zeroed memory areas. So far, inspecting non valid streams configuration has prove to be harmless, but as we'll need to inspect stream characteristics as reported image sizes and format, we have to take only valid configurations into account. Testing Done: White Camera Module preview and capture. Signed-off-by: Jacopo Mondi <jacopo.mondi@linaro.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@linaro.org> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 584f85e..41891b2 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -435,7 +435,7 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, *flags = resp->flags; *num_streams = resp->num_streams; - for (i = 0; i < nstreams; ++i) { + for (i = 0; i < resp->num_streams; ++i) { struct gb_camera_stream_config_response *cfg = &resp->config[i]; streams[i].width = le16_to_cpu(cfg->width); -- cgit v0.10.2 From 80b3982b8d1ca463963b9d2d406098c18add2baf Mon Sep 17 00:00:00 2001 From: Jacopo Mondi <jacopo.mondi@linaro.org> Date: Thu, 30 Jun 2016 09:18:00 -0500 Subject: greybus: camera: Fix size of configure_streams(0) When APB-A CSI-Tx configuration fails, it is necessary to unconfigure the camera module issuesing a 0 stream configuration request. Fix size of request and response to avoid Greybus core complain about Response size differences. Testing Done: Triggering the error condition after APB-A CSI-tx configuration does not make Greybus core complain anymore Signed-off-by: Jacopo Mondi <jacopo.mondi@linaro.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@linaro.org> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 41891b2..ce0ff75 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -468,7 +468,8 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, memset(req, 0, sizeof(*req)); gb_operation_sync(gcam->connection, GB_CAMERA_TYPE_CONFIGURE_STREAMS, - req, req_size, resp, resp_size); + req, sizeof(*req), + resp, sizeof(*resp)); *flags = 0; *num_streams = 0; goto done; -- cgit v0.10.2 From e3eda54d0b5fef23957cc4f586f4b44fd223c881 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 30 Jun 2016 10:54:00 -0500 Subject: greybus: Add Component Authentication Protocol support This patch adds Component Authentication Protocol support in greybus. The purpose of the CAP protocol is to authenticate the Module hardware, and it can only be used when it is present as part of the firmware-management bundle, on a separate CPort. Compile tested only. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Jun Li <li_jun@projectara.com> Tested-by: Jun Li <li_jun@projectara.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index bd9967c..fa5aaf3 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -33,7 +33,7 @@ gb-audio-manager-y += audio_manager.o gb-audio-manager-y += audio_manager_module.o gb-bootrom-y := bootrom.o gb-camera-y := camera.o -gb-firmware-y := fw-core.o fw-download.o fw-management.o +gb-firmware-y := fw-core.o fw-download.o fw-management.o authentication.o gb-spilib-y := spilib.o gb-sdio-y := sdio.o gb-uart-y := uart.o diff --git a/drivers/staging/greybus/authentication.c b/drivers/staging/greybus/authentication.c new file mode 100644 index 0000000..e469780 --- /dev/null +++ b/drivers/staging/greybus/authentication.c @@ -0,0 +1,437 @@ +/* + * Greybus Component Authentication Protocol (CAP) Driver. + * + * Copyright 2016 Google Inc. + * Copyright 2016 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include "greybus.h" + +#include <linux/cdev.h> +#include <linux/fs.h> +#include <linux/ioctl.h> +#include <linux/uaccess.h> + +#include "greybus_authentication.h" +#include "firmware.h" +#include "greybus.h" + +#define CAP_TIMEOUT_MS 1000 + +/* + * Number of minor devices this driver supports. + * There will be exactly one required per Interface. + */ +#define NUM_MINORS U8_MAX + +struct gb_cap { + struct device *parent; + struct gb_connection *connection; + struct kref kref; + struct list_head node; + bool disabled; /* connection getting disabled */ + + struct mutex mutex; + struct cdev cdev; + struct device *class_device; + dev_t dev_num; +}; + +static struct class *cap_class; +static dev_t cap_dev_num; +static DEFINE_IDA(cap_minors_map); +static LIST_HEAD(cap_list); +static DEFINE_MUTEX(list_mutex); + +static void cap_kref_release(struct kref *kref) +{ + struct gb_cap *cap = container_of(kref, struct gb_cap, kref); + + kfree(cap); +} + +/* + * All users of cap take a reference (from within list_mutex lock), before + * they get a pointer to play with. And the structure will be freed only after + * the last user has put the reference to it. + */ +static void put_cap(struct gb_cap *cap) +{ + kref_put(&cap->kref, cap_kref_release); +} + +/* Caller must call put_cap() after using struct gb_cap */ +static struct gb_cap *get_cap(struct cdev *cdev) +{ + struct gb_cap *cap; + + mutex_lock(&list_mutex); + + list_for_each_entry(cap, &cap_list, node) { + if (&cap->cdev == cdev) { + kref_get(&cap->kref); + goto unlock; + } + } + + cap = NULL; + +unlock: + mutex_unlock(&list_mutex); + + return cap; +} + +static int cap_get_endpoint_uid(struct gb_cap *cap, u8 *euid) +{ + struct gb_connection *connection = cap->connection; + struct gb_cap_get_endpoint_uid_response response; + int ret; + + ret = gb_operation_sync(connection, GB_CAP_TYPE_GET_ENDPOINT_UID, NULL, + 0, &response, sizeof(response)); + if (ret) { + dev_err(cap->parent, "failed to get endpoint uid (%d)\n", ret); + return ret; + } + + memcpy(euid, response.uid, sizeof(response.uid)); + + return 0; +} + +static int cap_get_ims_certificate(struct gb_cap *cap, u32 class, u32 id, + u8 *certificate, u32 *size, u8 *result) +{ + struct gb_connection *connection = cap->connection; + struct gb_cap_get_ims_certificate_request *request; + struct gb_cap_get_ims_certificate_response *response; + size_t max_size = gb_operation_get_payload_size_max(connection); + struct gb_operation *op; + int ret; + + op = gb_operation_create_flags(connection, + GB_CAP_TYPE_GET_IMS_CERTIFICATE, + sizeof(*request), max_size, + GB_OPERATION_FLAG_SHORT_RESPONSE, + GFP_KERNEL); + if (!op) + return -ENOMEM; + + request = op->request->payload; + request->certificate_class = cpu_to_le32(class); + request->certificate_id = cpu_to_le32(id); + + ret = gb_operation_request_send_sync(op); + if (ret) { + dev_err(cap->parent, "failed to get certificate (%d)\n", ret); + goto done; + } + + response = op->response->payload; + *result = response->result_code; + *size = op->response->payload_size - sizeof(*response); + memcpy(certificate, response->certificate, *size); + +done: + gb_operation_put(op); + return ret; +} + +static int cap_authenticate(struct gb_cap *cap, u32 auth_type, u8 *uid, + u8 *challenge, u8 *result, u8 *auth_response, + u32 *signature_size, u8 *signature) +{ + struct gb_connection *connection = cap->connection; + struct gb_cap_authenticate_request *request; + struct gb_cap_authenticate_response *response; + size_t max_size = gb_operation_get_payload_size_max(connection); + struct gb_operation *op; + int ret; + + op = gb_operation_create_flags(connection, GB_CAP_TYPE_AUTHENTICATE, + sizeof(*request), max_size, + GB_OPERATION_FLAG_SHORT_RESPONSE, + GFP_KERNEL); + if (!op) + return -ENOMEM; + + request = op->request->payload; + request->auth_type = cpu_to_le32(auth_type); + memcpy(request->uid, uid, sizeof(request->uid)); + memcpy(request->challenge, challenge, sizeof(request->challenge)); + + ret = gb_operation_request_send_sync(op); + if (ret) { + dev_err(cap->parent, "failed to authenticate (%d)\n", ret); + goto done; + } + + response = op->response->payload; + *result = response->result_code; + *signature_size = op->response->payload_size - sizeof(*response); + memcpy(auth_response, response->response, sizeof(response->response)); + memcpy(signature, response->signature, *signature_size); + +done: + gb_operation_put(op); + return ret; +} + +/* Char device fops */ + +static int cap_open(struct inode *inode, struct file *file) +{ + struct gb_cap *cap = get_cap(inode->i_cdev); + + /* cap structure can't get freed until file descriptor is closed */ + if (cap) { + file->private_data = cap; + return 0; + } + + return -ENODEV; +} + +static int cap_release(struct inode *inode, struct file *file) +{ + struct gb_cap *cap = file->private_data; + + put_cap(cap); + return 0; +} + +static int cap_ioctl(struct gb_cap *cap, unsigned int cmd, + void __user *buf) +{ + struct cap_ioc_get_endpoint_uid endpoint_uid; + struct cap_ioc_get_ims_certificate *ims_cert; + struct cap_ioc_authenticate *authenticate; + int ret; + + switch (cmd) { + case CAP_IOC_GET_ENDPOINT_UID: + ret = cap_get_endpoint_uid(cap, endpoint_uid.uid); + if (ret) + return ret; + + if (copy_to_user(buf, &endpoint_uid, sizeof(endpoint_uid))) + return -EFAULT; + + return 0; + case CAP_IOC_GET_IMS_CERTIFICATE: + ims_cert = kzalloc(sizeof(*ims_cert), GFP_KERNEL); + if (!ims_cert) + return -ENOMEM; + + if (copy_from_user(ims_cert, buf, sizeof(*ims_cert))) { + ret = -EFAULT; + goto free_ims_cert; + } + + ret = cap_get_ims_certificate(cap, ims_cert->certificate_class, + ims_cert->certificate_id, + ims_cert->certificate, + &ims_cert->cert_size, + &ims_cert->result_code); + if (ret) + goto free_ims_cert; + + if (copy_to_user(buf, ims_cert, sizeof(*ims_cert))) + ret = -EFAULT; + +free_ims_cert: + kfree(ims_cert); + return ret; + case CAP_IOC_AUTHENTICATE: + authenticate = kzalloc(sizeof(*authenticate), GFP_KERNEL); + if (!authenticate) + return -ENOMEM; + + if (copy_from_user(authenticate, buf, sizeof(*authenticate))) { + ret = -EFAULT; + goto free_authenticate; + } + + ret = cap_authenticate(cap, authenticate->auth_type, + authenticate->uid, + authenticate->challenge, + &authenticate->result_code, + authenticate->response, + &authenticate->signature_size, + authenticate->signature); + if (ret) + goto free_authenticate; + + if (copy_to_user(buf, authenticate, sizeof(*authenticate))) + ret = -EFAULT; +free_authenticate: + kfree(authenticate); + return ret; + default: + return -ENOTTY; + } +} + +static long cap_ioctl_unlocked(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct gb_cap *cap = file->private_data; + int ret = -ENODEV; + + /* + * Serialize ioctls. + * + * We don't want the user to do multiple authentication operations in + * parallel. + * + * This is also used to protect ->disabled, which is used to check if + * the connection is getting disconnected, so that we don't start any + * new operations. + */ + mutex_lock(&cap->mutex); + if (!cap->disabled) + ret = cap_ioctl(cap, cmd, (void __user *)arg); + mutex_unlock(&cap->mutex); + + return ret; +} + +static const struct file_operations cap_fops = { + .owner = THIS_MODULE, + .open = cap_open, + .release = cap_release, + .unlocked_ioctl = cap_ioctl_unlocked, +}; + +int gb_cap_connection_init(struct gb_connection *connection) +{ + struct gb_cap *cap; + int ret, minor; + + if (!connection) + return 0; + + cap = kzalloc(sizeof(*cap), GFP_KERNEL); + if (!cap) + return -ENOMEM; + + cap->parent = &connection->bundle->dev; + cap->connection = connection; + mutex_init(&cap->mutex); + gb_connection_set_data(connection, cap); + kref_init(&cap->kref); + + mutex_lock(&list_mutex); + list_add(&cap->node, &cap_list); + mutex_unlock(&list_mutex); + + ret = gb_connection_enable(connection); + if (ret) + goto err_list_del; + + minor = ida_simple_get(&cap_minors_map, 0, NUM_MINORS, GFP_KERNEL); + if (minor < 0) { + ret = minor; + goto err_connection_disable; + } + + /* Add a char device to allow userspace to interact with cap */ + cap->dev_num = MKDEV(MAJOR(cap_dev_num), minor); + cdev_init(&cap->cdev, &cap_fops); + + ret = cdev_add(&cap->cdev, cap->dev_num, 1); + if (ret) + goto err_remove_ida; + + /* Add a soft link to the previously added char-dev within the bundle */ + cap->class_device = device_create(cap_class, cap->parent, cap->dev_num, + NULL, "gb-authenticate-%d", minor); + if (IS_ERR(cap->class_device)) { + ret = PTR_ERR(cap->class_device); + goto err_del_cdev; + } + + return 0; + +err_del_cdev: + cdev_del(&cap->cdev); +err_remove_ida: + ida_simple_remove(&cap_minors_map, minor); +err_connection_disable: + gb_connection_disable(connection); +err_list_del: + mutex_lock(&list_mutex); + list_del(&cap->node); + mutex_unlock(&list_mutex); + + put_cap(cap); + + return ret; +} + +void gb_cap_connection_exit(struct gb_connection *connection) +{ + struct gb_cap *cap; + + if (!connection) + return; + + cap = gb_connection_get_data(connection); + + device_destroy(cap_class, cap->dev_num); + cdev_del(&cap->cdev); + ida_simple_remove(&cap_minors_map, MINOR(cap->dev_num)); + + /* + * Disallow any new ioctl operations on the char device and wait for + * existing ones to finish. + */ + mutex_lock(&cap->mutex); + cap->disabled = true; + mutex_unlock(&cap->mutex); + + /* All pending greybus operations should have finished by now */ + gb_connection_disable(cap->connection); + + /* Disallow new users to get access to the cap structure */ + mutex_lock(&list_mutex); + list_del(&cap->node); + mutex_unlock(&list_mutex); + + /* + * All current users of cap would have taken a reference to it by + * now, we can drop our reference and wait the last user will get + * cap freed. + */ + put_cap(cap); +} + +int cap_init(void) +{ + int ret; + + cap_class = class_create(THIS_MODULE, "gb_authenticate"); + if (IS_ERR(cap_class)) + return PTR_ERR(cap_class); + + ret = alloc_chrdev_region(&cap_dev_num, 0, NUM_MINORS, + "gb_authenticate"); + if (ret) + goto err_remove_class; + + return 0; + +err_remove_class: + class_destroy(cap_class); + return ret; +} + +void cap_exit(void) +{ + unregister_chrdev_region(cap_dev_num, NUM_MINORS); + class_destroy(cap_class); + ida_destroy(&cap_minors_map); +} diff --git a/drivers/staging/greybus/firmware.h b/drivers/staging/greybus/firmware.h index a82d020..fb95537 100644 --- a/drivers/staging/greybus/firmware.h +++ b/drivers/staging/greybus/firmware.h @@ -25,4 +25,10 @@ int gb_fw_download_request_handler(struct gb_operation *op); int gb_fw_download_connection_init(struct gb_connection *connection); void gb_fw_download_connection_exit(struct gb_connection *connection); +/* CAP Protocol specific functions */ +int cap_init(void); +void cap_exit(void); +int gb_cap_connection_init(struct gb_connection *connection); +void gb_cap_connection_exit(struct gb_connection *connection); + #endif /* __FIRMWARE_H */ diff --git a/drivers/staging/greybus/fw-core.c b/drivers/staging/greybus/fw-core.c index 33941ef..9639732 100644 --- a/drivers/staging/greybus/fw-core.c +++ b/drivers/staging/greybus/fw-core.c @@ -17,6 +17,7 @@ struct gb_fw_core { struct gb_connection *download_connection; struct gb_connection *mgmt_connection; struct gb_connection *spi_connection; + struct gb_connection *cap_connection; }; struct gb_connection *to_fw_mgmt_connection(struct device *dev) @@ -135,6 +136,24 @@ static int gb_fw_core_probe(struct gb_bundle *bundle, } break; + case GREYBUS_PROTOCOL_AUTHENTICATION: + /* Disallow multiple CAP CPorts */ + if (fw_core->cap_connection) { + dev_err(&bundle->dev, "multiple Authentication CPorts found\n"); + ret = -EINVAL; + goto err_destroy_connections; + } + + connection = gb_connection_create(bundle, cport_id, + NULL); + if (IS_ERR(connection)) { + dev_err(&bundle->dev, "failed to create Authentication connection (%ld)\n", + PTR_ERR(connection)); + } else { + fw_core->cap_connection = connection; + } + + break; default: dev_err(&bundle->dev, "invalid protocol id (0x%02x)\n", protocol_id); @@ -168,6 +187,15 @@ static int gb_fw_core_probe(struct gb_bundle *bundle, fw_core->spi_connection = NULL; } + ret = gb_cap_connection_init(fw_core->cap_connection); + if (ret) { + /* We may still be able to work with the Interface */ + dev_err(&bundle->dev, "failed to initialize CAP connection, disable it (%d)\n", + ret); + gb_connection_destroy(fw_core->cap_connection); + fw_core->cap_connection = NULL; + } + ret = gb_fw_mgmt_connection_init(fw_core->mgmt_connection); if (ret) { /* We may still be able to work with the Interface */ @@ -181,10 +209,12 @@ static int gb_fw_core_probe(struct gb_bundle *bundle, return 0; err_exit_connections: + gb_cap_connection_exit(fw_core->cap_connection); gb_fw_spi_connection_exit(fw_core->spi_connection); gb_fw_download_connection_exit(fw_core->download_connection); err_destroy_connections: gb_connection_destroy(fw_core->mgmt_connection); + gb_connection_destroy(fw_core->cap_connection); gb_connection_destroy(fw_core->spi_connection); gb_connection_destroy(fw_core->download_connection); kfree(fw_core); @@ -197,10 +227,12 @@ static void gb_fw_core_disconnect(struct gb_bundle *bundle) struct gb_fw_core *fw_core = greybus_get_drvdata(bundle); gb_fw_mgmt_connection_exit(fw_core->mgmt_connection); + gb_cap_connection_exit(fw_core->cap_connection); gb_fw_spi_connection_exit(fw_core->spi_connection); gb_fw_download_connection_exit(fw_core->download_connection); gb_connection_destroy(fw_core->mgmt_connection); + gb_connection_destroy(fw_core->cap_connection); gb_connection_destroy(fw_core->spi_connection); gb_connection_destroy(fw_core->download_connection); @@ -229,19 +261,32 @@ static int fw_core_init(void) return ret; } - ret = greybus_register(&gb_fw_core_driver); + ret = cap_init(); if (ret) { - fw_mgmt_exit(); - return ret; + pr_err("Failed to initialize component authentication core (%d)\n", + ret); + goto fw_mgmt_exit; } + ret = greybus_register(&gb_fw_core_driver); + if (ret) + goto cap_exit; + return 0; + +cap_exit: + cap_exit(); +fw_mgmt_exit: + fw_mgmt_exit(); + + return ret; } module_init(fw_core_init); static void __exit fw_core_exit(void) { greybus_deregister(&gb_fw_core_driver); + cap_exit(); fw_mgmt_exit(); } module_exit(fw_core_exit); diff --git a/drivers/staging/greybus/greybus_authentication.h b/drivers/staging/greybus/greybus_authentication.h new file mode 100644 index 0000000..4784ed9 --- /dev/null +++ b/drivers/staging/greybus/greybus_authentication.h @@ -0,0 +1,120 @@ +/* + * Greybus Component Authentication User Header + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2016 Google Inc. All rights reserved. + * Copyright(c) 2016 Linaro Ltd. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details. + * + * BSD LICENSE + * + * Copyright(c) 2016 Google Inc. All rights reserved. + * Copyright(c) 2016 Linaro Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. or Linaro Ltd. nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * 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 GOOGLE INC. OR + * LINARO LTD. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __GREYBUS_AUTHENTICATION_USER_H +#define __GREYBUS_AUTHENTICATION_USER_H + +#include <linux/ioctl.h> +#include <linux/types.h> + +#define CAP_CERTIFICATE_MAX_SIZE 1600 +#define CAP_SIGNATURE_MAX_SIZE 320 + +/* Certificate class types */ +#define CAP_CERT_IMS_EAPC 0x00000001 +#define CAP_CERT_IMS_EASC 0x00000002 +#define CAP_CERT_IMS_EARC 0x00000003 +#define CAP_CERT_IMS_IAPC 0x00000004 +#define CAP_CERT_IMS_IASC 0x00000005 +#define CAP_CERT_IMS_IARC 0x00000006 + +/* IMS Certificate response result codes */ +#define CAP_IMS_RESULT_CERT_FOUND 0x00 +#define CAP_IMS_RESULT_CERT_CLASS_INVAL 0x01 +#define CAP_IMS_RESULT_CERT_CORRUPT 0x02 +#define CAP_IMS_RESULT_CERT_NOT_FOUND 0x03 + +/* Authentication types */ +#define CAP_AUTH_IMS_PRI 0x00000001 +#define CAP_AUTH_IMS_SEC 0x00000002 +#define CAP_AUTH_IMS_RSA 0x00000003 + +/* Authenticate response result codes */ +#define CAP_AUTH_RESULT_CR_SUCCESS 0x00 +#define CAP_AUTH_RESULT_CR_BAD_TYPE 0x01 +#define CAP_AUTH_RESULT_CR_WRONG_EP 0x02 +#define CAP_AUTH_RESULT_CR_NO_KEY 0x03 +#define CAP_AUTH_RESULT_CR_SIG_FAIL 0x04 + + +/* IOCTL support */ +struct cap_ioc_get_endpoint_uid { + __u8 uid[8]; +} __attribute__ ((__packed__)); + +struct cap_ioc_get_ims_certificate { + __u32 certificate_class; + __u32 certificate_id; + + __u8 result_code; + __u32 cert_size; + __u8 certificate[CAP_CERTIFICATE_MAX_SIZE]; +} __attribute__ ((__packed__)); + +struct cap_ioc_authenticate { + __u32 auth_type; + __u8 uid[8]; + __u8 challenge[32]; + + __u8 result_code; + __u8 response[64]; + __u32 signature_size; + __u8 signature[CAP_SIGNATURE_MAX_SIZE]; +} __attribute__ ((__packed__)); + +#define CAP_IOCTL_BASE 'C' +#define CAP_IOC_GET_ENDPOINT_UID _IOR(CAP_IOCTL_BASE, 0, struct cap_ioc_get_endpoint_uid) +#define CAP_IOC_GET_IMS_CERTIFICATE _IOWR(CAP_IOCTL_BASE, 1, struct cap_ioc_get_ims_certificate) +#define CAP_IOC_AUTHENTICATE _IOWR(CAP_IOCTL_BASE, 2, struct cap_ioc_authenticate) + +#endif /* __GREYBUS_AUTHENTICATION_USER_H */ diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 2ae39ad..d135945 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -47,6 +47,7 @@ enum greybus_protocol { GREYBUS_PROTOCOL_CAMERA_DATA = 0x16, GREYBUS_PROTOCOL_FW_DOWNLOAD = 0x17, GREYBUS_PROTOCOL_FW_MANAGEMENT = 0x18, + GREYBUS_PROTOCOL_AUTHENTICATION = 0x19, GREYBUS_PROTOCOL_LOG = 0x1a, /* ... */ GREYBUS_PROTOCOL_RAW = 0xfe, diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 327d01f..0043b91 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -345,6 +345,43 @@ struct gb_fw_mgmt_backend_fw_updated_request { /* firmware management backend firmware updated response has no payload */ +/* Component Authentication Protocol (CAP) */ + +/* Request Types */ +#define GB_CAP_TYPE_GET_ENDPOINT_UID 0x01 +#define GB_CAP_TYPE_GET_IMS_CERTIFICATE 0x02 +#define GB_CAP_TYPE_AUTHENTICATE 0x03 + +/* CAP get endpoint uid request has no payload */ +struct gb_cap_get_endpoint_uid_response { + __u8 uid[8]; +} __packed; + +/* CAP get endpoint ims certificate request/response */ +struct gb_cap_get_ims_certificate_request { + __le32 certificate_class; + __le32 certificate_id; +} __packed; + +struct gb_cap_get_ims_certificate_response { + __u8 result_code; + __u8 certificate[0]; +} __packed; + +/* CAP authenticate request/response */ +struct gb_cap_authenticate_request { + __le32 auth_type; + __u8 uid[8]; + __u8 challenge[32]; +} __packed; + +struct gb_cap_authenticate_response { + __u8 result_code; + __u8 response[64]; + __u8 signature[0]; +} __packed; + + /* Bootrom Protocol */ /* Version of the Greybus bootrom protocol we support */ -- cgit v0.10.2 From 6f4219dd7df0b834caad344db05d9d06d71658cd Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 30 Jun 2016 10:54:00 -0500 Subject: greybus: Documentation: Document Authentication interfaces This patch defined userspace interface of the CAP protocol. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Jun Li <li_jun@projectara.com> Tested-by: Jun Li <li_jun@projectara.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/Documentation/firmware/authenticate.c b/drivers/staging/greybus/Documentation/firmware/authenticate.c new file mode 100644 index 0000000..ab0688a --- /dev/null +++ b/drivers/staging/greybus/Documentation/firmware/authenticate.c @@ -0,0 +1,139 @@ +/* + * Sample code to test CAP protocol + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2016 Google Inc. All rights reserved. + * Copyright(c) 2016 Linaro Ltd. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details. + * + * BSD LICENSE + * + * Copyright(c) 2016 Google Inc. All rights reserved. + * Copyright(c) 2016 Linaro Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. or Linaro Ltd. nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * 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 GOOGLE INC. OR + * LINARO LTD. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include "../../greybus_authentication.h" + +struct cap_ioc_get_endpoint_uid uid; +struct cap_ioc_get_ims_certificate cert = { + .certificate_class = 0, + .certificate_id = 0, +}; + +struct cap_ioc_authenticate authenticate = { + .auth_type = 0, + .challenge = {0}, +}; + +int main(int argc, char *argv[]) +{ + unsigned int timeout = 10000; + char *capdev; + int fd, ret; + + /* Make sure arguments are correct */ + if (argc != 2) { + printf("\nUsage: ./firmware <Path of the gb-cap-X dev>\n"); + return 0; + } + + capdev = argv[1]; + + printf("Opening %s authentication device\n", capdev); + + fd = open(capdev, O_RDWR); + if (fd < 0) { + printf("Failed to open: %s\n", capdev); + return -1; + } + + /* Get UID */ + printf("Get UID\n"); + + ret = ioctl(fd, CAP_IOC_GET_ENDPOINT_UID, &uid); + if (ret < 0) { + printf("Failed to get UID: %s (%d)\n", capdev, ret); + ret = -1; + goto close_fd; + } + + printf("UID received: 0x%llx\n", *(long long unsigned int *)(uid.uid)); + + /* Get certificate */ + printf("Get IMS certificate\n"); + + ret = ioctl(fd, CAP_IOC_GET_IMS_CERTIFICATE, &cert); + if (ret < 0) { + printf("Failed to get IMS certificate: %s (%d)\n", capdev, ret); + ret = -1; + goto close_fd; + } + + printf("IMS Certificate size: %d\n", cert.cert_size); + + /* Authenticate */ + printf("Authenticate module\n"); + + memcpy(authenticate.uid, uid.uid, 8); + + ret = ioctl(fd, CAP_IOC_AUTHENTICATE, &authenticate); + if (ret < 0) { + printf("Failed to authenticate module: %s (%d)\n", capdev, ret); + ret = -1; + goto close_fd; + } + + printf("Authenticated, result (%02x), sig-size (%02x)\n", + authenticate.result_code, authenticate.signature_size); + +close_fd: + close(fd); + + return ret; +} diff --git a/drivers/staging/greybus/Documentation/firmware/firmware-management b/drivers/staging/greybus/Documentation/firmware/firmware-management index 7997739..6b7b6d8 100644 --- a/drivers/staging/greybus/Documentation/firmware/firmware-management +++ b/drivers/staging/greybus/Documentation/firmware/firmware-management @@ -40,8 +40,7 @@ may look like: ; (Optional) Component Authentication Protocol (CAP) on CPort 4 [cport-descriptor 4] bundle = 1 - protocol = 0xXX //TBD - + protocol = 0x19 Sysfs Interfaces - Firmware Management @@ -164,6 +163,129 @@ struct fw_mgmt_ioc_backend_fw_update { allow mode-switch. +Sysfs Interfaces - Authentication +--------------------------------- + +The Component Authentication Protocol interacts with Userspace using the +character device interface. The character device will be present in /dev/ +directory and will be named gb-authenticate-<N>. The number <N> is assigned at +runtime. + +Identifying the Character Device +================================ + +There can be multiple devices present in /dev/ directory with name +gb-authenticate-N and user first needs to identify the character device used for +authentication a of particular interface. + +The Authentication core creates a device of class 'gb_authenticate', which shall +be used by the user to identify the right character device for it. The class +device is created within the Bundle directory for a particular Interface. + +For example this is how the class-device can be present: + +/sys/bus/greybus/devices/1-1/1-1.1/1-1.1.1/gb_authenticate/gb-authenticate-0 + +The last name in this path: gb-authenticate-0 is precisely the name of the char +device and so the device in this case will be: + +/dev/gb-authenticate-0. + +Operations on the Char device +============================= + +The Character device (/dev/gb-authenticate-0 in above example) can be opened by +the userspace application and it can perform various 'ioctl' operations on the +device. The device doesn't support any read/write operations. + +Following are the IOCTLs and their data structures available to the user: + +#define CAP_CERTIFICATE_MAX_SIZE 1600 +#define CAP_SIGNATURE_MAX_SIZE 320 + +/* Certificate class types */ +#define CAP_CERT_IMS_EAPC 0x00000001 +#define CAP_CERT_IMS_EASC 0x00000002 +#define CAP_CERT_IMS_EARC 0x00000003 +#define CAP_CERT_IMS_IAPC 0x00000004 +#define CAP_CERT_IMS_IASC 0x00000005 +#define CAP_CERT_IMS_IARC 0x00000006 + +/* IMS Certificate response result codes */ +#define CAP_IMS_RESULT_CERT_FOUND 0x00 +#define CAP_IMS_RESULT_CERT_CLASS_INVAL 0x01 +#define CAP_IMS_RESULT_CERT_CORRUPT 0x02 +#define CAP_IMS_RESULT_CERT_NOT_FOUND 0x03 + +/* Authentication types */ +#define CAP_AUTH_IMS_PRI 0x00000001 +#define CAP_AUTH_IMS_SEC 0x00000002 +#define CAP_AUTH_IMS_RSA 0x00000003 + +/* Authenticate response result codes */ +#define CAP_AUTH_RESULT_CR_SUCCESS 0x00 +#define CAP_AUTH_RESULT_CR_BAD_TYPE 0x01 +#define CAP_AUTH_RESULT_CR_WRONG_EP 0x02 +#define CAP_AUTH_RESULT_CR_NO_KEY 0x03 +#define CAP_AUTH_RESULT_CR_SIG_FAIL 0x04 + + +/* IOCTL support */ +struct cap_ioc_get_endpoint_uid { + __u8 uid[8]; +} __attribute__ ((__packed__)); + +struct cap_ioc_get_ims_certificate { + __u32 certificate_class; + __u32 certificate_id; + + __u8 result_code; + __u32 cert_size; + __u8 certificate[CAP_CERTIFICATE_MAX_SIZE]; +} __attribute__ ((__packed__)); + +struct cap_ioc_authenticate { + __u32 auth_type; + __u8 uid[8]; + __u8 challenge[32]; + + __u8 result_code; + __u8 response[64]; + __u32 signature_size; + __u8 signature[CAP_SIGNATURE_MAX_SIZE]; +} __attribute__ ((__packed__)); + +#define CAP_IOCTL_BASE 'C' +#define CAP_IOC_GET_ENDPOINT_UID _IOR(CAP_IOCTL_BASE, 0, struct cap_ioc_get_endpoint_uid) +#define CAP_IOC_GET_IMS_CERTIFICATE _IOWR(CAP_IOCTL_BASE, 1, struct cap_ioc_get_ims_certificate) +#define CAP_IOC_AUTHENTICATE _IOWR(CAP_IOCTL_BASE, 2, struct cap_ioc_authenticate) + + +1. CAP_IOC_GET_ENDPOINT_UID: + + This ioctl shall be used the user to get the endpoint UID associated with the + Interface. All the fields of the 'struct cap_ioc_get_endpoint_uid' are + filled by the kernel. + +2. CAP_IOC_GET_IMS_CERTIFICATE: + + This ioctl shall be used the user to retrieve one of the available + cryptographic certificates held by the Interface for use in Component + Authentication. The user is required to fill the 'certificate_class' and + 'certificate_id' field of the 'struct cap_ioc_get_ims_certificate' in this + case. The other fields will be set by the kernel in response. The first + 'cert_size' bytes of the 'certificate' shall be read by the user and others + must be discarded. + +3. CAP_IOC_AUTHENTICATE: + + This ioctl shall be used the user to authenticate the Module attached to an + Interface. The user needs to fill the 'auth_type', 'uid', and 'challenge' + fields of the 'struct cap_ioc_authenticate'. The other fields will be set by + the kernel in response. The first 'signature_size' bytes of the 'signature' + shall be read by the user and others must be discarded. + + Sysfs Interfaces - Firmware Download ------------------------------------ @@ -182,9 +304,13 @@ $ ls /sys/bus/greybus/devices/1-1/1-1.1/1-1.1.1/spi_master/spi32766/spi32766.0/m mtd0 mtd0ro -Sample Application ------------------- +Sample Applications +------------------- The current directory also provides a firmware.c test application, which can be referenced while developing userspace application to talk to firmware-management protocol. + +The current directory also provides a authenticate.c test application, which can +be referenced while developing userspace application to talk to +component authentication protocol. -- cgit v0.10.2 From 776165481d8ed956ccb92465f97ba727eed53e4c Mon Sep 17 00:00:00 2001 From: Fabien Parent <fparent@baylibre.com> Date: Wed, 6 Jul 2016 10:51:00 -0500 Subject: greybus: connection: remove CDSI1 hack This hack is not necessary anymore since the firmware is now able to handle correctly (dis)connect{ed,ing} operations on the CDSI CPort. Testing Done: Checked that I could start the camera app several time and got the preview each time. Signed-off-by: Fabien Parent <fparent@baylibre.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@linaro.org> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 632c8be..174a52d 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -442,16 +442,6 @@ static int gb_connection_control_connected(struct gb_connection *connection) if (gb_connection_is_static(connection)) return 0; - /* - * HACK: Suppress connected request for the offloaded camera - * connection as it is currently not supported by firmware. Note that - * the corresponding non-fatal disconnected event is still sent. - */ - if (gb_connection_is_offloaded(connection) && - connection->flags & GB_CONNECTION_FLAG_CDSI1) { - return 0; - } - if (gb_connection_is_control(connection)) return 0; -- cgit v0.10.2 From 2c8e8841e3b8cea90cc9b7172eebfdf90b06038a Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Thu, 7 Jul 2016 22:07:00 -0500 Subject: greybus: control: add bundle suspend and resume preparations Add the AP implementation for the Greybus Control Bundle Suspend Operation. This Operation is used to request a Bundle to enter the BUNDLE_SUSPENDED state, all Connections associated with this Bundle must be closed before issuing this operation. Add the AP implementation for the Greybus Control Bundle Resume Operation. This operation request a specific Bundle to transition from the BUNDLE_SUSPENDED state to the BUNDLE_ACTIVE state. Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index 88e5718..a95c776 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -233,6 +233,71 @@ int gb_control_timesync_authoritative(struct gb_control *control, NULL, 0); } +static int gb_control_bundle_pm_status_map(u8 status) +{ + switch (status) { + case GB_CONTROL_BUNDLE_PM_INVAL: + return -EINVAL; + case GB_CONTROL_BUNDLE_PM_BUSY: + return -EBUSY; + case GB_CONTROL_BUNDLE_PM_NA: + return -ENOMSG; + case GB_CONTROL_BUNDLE_PM_FAIL: + default: + return -EREMOTEIO; + } +} + +int gb_control_bundle_suspend(struct gb_control *control, u8 bundle_id) +{ + struct gb_control_bundle_pm_request request; + struct gb_control_bundle_pm_response response; + int ret; + + request.bundle_id = bundle_id; + ret = gb_operation_sync(control->connection, + GB_CONTROL_TYPE_BUNDLE_SUSPEND, &request, + sizeof(request), &response, sizeof(response)); + if (ret) { + dev_err(&control->dev, + "failed to send bundle suspend: %d\n", ret); + return ret; + } + + if (response.status != GB_CONTROL_BUNDLE_PM_OK) { + dev_err(&control->dev, + "bundle error while suspending: %d\n", response.status); + return gb_control_bundle_pm_status_map(response.status); + } + + return 0; +} + +int gb_control_bundle_resume(struct gb_control *control, u8 bundle_id) +{ + struct gb_control_bundle_pm_request request; + struct gb_control_bundle_pm_response response; + int ret; + + request.bundle_id = bundle_id; + ret = gb_operation_sync(control->connection, + GB_CONTROL_TYPE_BUNDLE_RESUME, &request, + sizeof(request), &response, sizeof(response)); + if (ret) { + dev_err(&control->dev, + "failed to send bundle resume: %d\n", ret); + return ret; + } + + if (response.status != GB_CONTROL_BUNDLE_PM_OK) { + dev_err(&control->dev, + "bundle error while resuming: %d\n", response.status); + return gb_control_bundle_pm_status_map(response.status); + } + + return 0; +} + static ssize_t vendor_string_show(struct device *dev, struct device_attribute *attr, char *buf) { diff --git a/drivers/staging/greybus/control.h b/drivers/staging/greybus/control.h index b1e5af2..c7f3463 100644 --- a/drivers/staging/greybus/control.h +++ b/drivers/staging/greybus/control.h @@ -52,5 +52,6 @@ int gb_control_timesync_get_last_event(struct gb_control *control, u64 *frame_time); int gb_control_timesync_authoritative(struct gb_control *control, u64 *frame_time); - +int gb_control_bundle_suspend(struct gb_control *control, u8 bundle_id); +int gb_control_bundle_resume(struct gb_control *control, u8 bundle_id); #endif /* __CONTROL_H */ diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 0043b91..3b6fd02 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -126,6 +126,8 @@ struct gb_protocol_version_response { #define GB_CONTROL_TYPE_DISCONNECTING 0x0c #define GB_CONTROL_TYPE_TIMESYNC_GET_LAST_EVENT 0x0d #define GB_CONTROL_TYPE_MODE_SWITCH 0x0e +#define GB_CONTROL_TYPE_BUNDLE_SUSPEND 0x0f +#define GB_CONTROL_TYPE_BUNDLE_RESUME 0x10 struct gb_control_version_request { __u8 major; @@ -191,6 +193,25 @@ struct gb_control_timesync_get_last_event_response { __le64 frame_time; } __packed; +/* + * All Bundle power management operations use the same request and response + * layout and status codes. + */ + +#define GB_CONTROL_BUNDLE_PM_OK 0x00 +#define GB_CONTROL_BUNDLE_PM_INVAL 0x01 +#define GB_CONTROL_BUNDLE_PM_BUSY 0x02 +#define GB_CONTROL_BUNDLE_PM_FAIL 0x03 +#define GB_CONTROL_BUNDLE_PM_NA 0x04 + +struct gb_control_bundle_pm_request { + __u8 bundle_id; +} __packed; + +struct gb_control_bundle_pm_response { + __u8 status; +} __packed; + /* APBridge protocol */ /* request APB1 log */ -- cgit v0.10.2 From f61908f94a9fc550d4619224263fff16cddcc830 Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Thu, 7 Jul 2016 22:07:00 -0500 Subject: greybus: control: add bundle deactivate and activate operation Add the AP implementation for the Greybus Control Bundle Deactivate Operation. This operation requests a Bundle to enter the BUNDLE_OFF state. All Connections associated with the Bundle must be closed prior sending this operation. Add the AP implementation for the Greybus Control Bundle Activate Operation. This operation requests a specific Bundle to transition from the BUNDLE_OFF state to the BUNDLE_ACTIVE state. [elder@linaro.org: fixed a typo pointed out by Johan] Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index a95c776..a53fa3d 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -298,6 +298,56 @@ int gb_control_bundle_resume(struct gb_control *control, u8 bundle_id) return 0; } +int gb_control_bundle_deactivate(struct gb_control *control, u8 bundle_id) +{ + struct gb_control_bundle_pm_request request; + struct gb_control_bundle_pm_response response; + int ret; + + request.bundle_id = bundle_id; + ret = gb_operation_sync(control->connection, + GB_CONTROL_TYPE_BUNDLE_DEACTIVATE, &request, + sizeof(request), &response, sizeof(response)); + if (ret) { + dev_err(&control->dev, + "failed to send bundle deactivate: %d\n", ret); + return ret; + } + + if (response.status != GB_CONTROL_BUNDLE_PM_OK) { + dev_err(&control->dev, + "bundle error while deactivating: %d\n", response.status); + return gb_control_bundle_pm_status_map(response.status); + } + + return 0; +} + +int gb_control_bundle_activate(struct gb_control *control, u8 bundle_id) +{ + struct gb_control_bundle_pm_request request; + struct gb_control_bundle_pm_response response; + int ret; + + request.bundle_id = bundle_id; + ret = gb_operation_sync(control->connection, + GB_CONTROL_TYPE_BUNDLE_ACTIVATE, &request, + sizeof(request), &response, sizeof(response)); + if (ret) { + dev_err(&control->dev, + "failed to send bundle activate: %d\n", ret); + return ret; + } + + if (response.status != GB_CONTROL_BUNDLE_PM_OK) { + dev_err(&control->dev, + "bundle error while activating: %d\n", response.status); + return gb_control_bundle_pm_status_map(response.status); + } + + return 0; +} + static ssize_t vendor_string_show(struct device *dev, struct device_attribute *attr, char *buf) { diff --git a/drivers/staging/greybus/control.h b/drivers/staging/greybus/control.h index c7f3463..5ddf013 100644 --- a/drivers/staging/greybus/control.h +++ b/drivers/staging/greybus/control.h @@ -54,4 +54,6 @@ int gb_control_timesync_authoritative(struct gb_control *control, u64 *frame_time); int gb_control_bundle_suspend(struct gb_control *control, u8 bundle_id); int gb_control_bundle_resume(struct gb_control *control, u8 bundle_id); +int gb_control_bundle_deactivate(struct gb_control *control, u8 bundle_id); +int gb_control_bundle_activate(struct gb_control *control, u8 bundle_id); #endif /* __CONTROL_H */ diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 3b6fd02..1ae3350 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -128,6 +128,8 @@ struct gb_protocol_version_response { #define GB_CONTROL_TYPE_MODE_SWITCH 0x0e #define GB_CONTROL_TYPE_BUNDLE_SUSPEND 0x0f #define GB_CONTROL_TYPE_BUNDLE_RESUME 0x10 +#define GB_CONTROL_TYPE_BUNDLE_DEACTIVATE 0x11 +#define GB_CONTROL_TYPE_BUNDLE_ACTIVATE 0x12 struct gb_control_version_request { __u8 major; -- cgit v0.10.2 From f53be0eaf0603324ea90eb352df0ffa18dde646a Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Thu, 7 Jul 2016 22:07:00 -0500 Subject: greybus: control: add interface suspend prepare operation Add the AP implementation for the Greybus Control Interface Suspend Prepare Operation. AP uses this Operation during the Suspend transition to request the Interface to enter a low-power mode after it detects a subsequent UniPro link hibernation. Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index a53fa3d..252352ce 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -348,6 +348,41 @@ int gb_control_bundle_activate(struct gb_control *control, u8 bundle_id) return 0; } +static int gb_control_interface_pm_status_map(u8 status) +{ + switch (status) { + case GB_CONTROL_INTF_PM_BUSY: + return -EBUSY; + case GB_CONTROL_INTF_PM_NA: + return -ENOMSG; + default: + return -EREMOTEIO; + } +} + +int gb_control_interface_suspend_prepare(struct gb_control *control) +{ + struct gb_control_intf_pm_response response; + int ret; + + ret = gb_operation_sync(control->connection, + GB_CONTROL_TYPE_INTF_SUSPEND_PREPARE, NULL, 0, + &response, sizeof(response)); + if (ret) { + dev_err(&control->dev, + "failed to send interface suspend prepare: %d\n", ret); + return ret; + } + + if (response.status != GB_CONTROL_INTF_PM_OK) { + dev_err(&control->dev, "interface error while preparing suspend: %d\n", + response.status); + return gb_control_interface_pm_status_map(response.status); + } + + return 0; +} + static ssize_t vendor_string_show(struct device *dev, struct device_attribute *attr, char *buf) { diff --git a/drivers/staging/greybus/control.h b/drivers/staging/greybus/control.h index 5ddf013..bc32ca7 100644 --- a/drivers/staging/greybus/control.h +++ b/drivers/staging/greybus/control.h @@ -56,4 +56,5 @@ int gb_control_bundle_suspend(struct gb_control *control, u8 bundle_id); int gb_control_bundle_resume(struct gb_control *control, u8 bundle_id); int gb_control_bundle_deactivate(struct gb_control *control, u8 bundle_id); int gb_control_bundle_activate(struct gb_control *control, u8 bundle_id); +int gb_control_interface_suspend_prepare(struct gb_control *control); #endif /* __CONTROL_H */ diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 1ae3350..cd64a99 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -130,6 +130,7 @@ struct gb_protocol_version_response { #define GB_CONTROL_TYPE_BUNDLE_RESUME 0x10 #define GB_CONTROL_TYPE_BUNDLE_DEACTIVATE 0x11 #define GB_CONTROL_TYPE_BUNDLE_ACTIVATE 0x12 +#define GB_CONTROL_TYPE_INTF_SUSPEND_PREPARE 0x13 struct gb_control_version_request { __u8 major; @@ -214,6 +215,20 @@ struct gb_control_bundle_pm_response { __u8 status; } __packed; +/* + * Interface Suspend Prepare and Deactivate Prepare operations use the same + * response layout and error codes. Define a single response structure and reuse + * it. Both operations have no payload. + */ + +#define GB_CONTROL_INTF_PM_OK 0x00 +#define GB_CONTROL_INTF_PM_BUSY 0x01 +#define GB_CONTROL_INTF_PM_NA 0x02 + +struct gb_control_intf_pm_response { + __u8 status; +} __packed; + /* APBridge protocol */ /* request APB1 log */ -- cgit v0.10.2 From 30ea26bdd403396c62d6c9fa26477ca1f7af5676 Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Thu, 7 Jul 2016 22:07:00 -0500 Subject: greybus: control: add interface deactivate prepare operation Add the AP implementation for the Greybus Control Interface Deactivate Prepare Operation. AP uses this Operation during the Power Down transition to request the bridge to power down after it detects a subsequent UniPro link hibernation. Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index 252352ce..a1c78fc 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -383,6 +383,29 @@ int gb_control_interface_suspend_prepare(struct gb_control *control) return 0; } +int gb_control_interface_deactivate_prepare(struct gb_control *control) +{ + struct gb_control_intf_pm_response response; + int ret; + + ret = gb_operation_sync(control->connection, + GB_CONTROL_TYPE_INTF_DEACTIVATE_PREPARE, NULL, + 0, &response, sizeof(response)); + if (ret) { + dev_err(&control->dev, "failed to send interface deactivate prepare: %d\n", + ret); + return ret; + } + + if (response.status != GB_CONTROL_INTF_PM_OK) { + dev_err(&control->dev, "interface error while preparing deactivate: %d\n", + response.status); + return gb_control_interface_pm_status_map(response.status); + } + + return 0; +} + static ssize_t vendor_string_show(struct device *dev, struct device_attribute *attr, char *buf) { diff --git a/drivers/staging/greybus/control.h b/drivers/staging/greybus/control.h index bc32ca7..2f76ae4 100644 --- a/drivers/staging/greybus/control.h +++ b/drivers/staging/greybus/control.h @@ -57,4 +57,5 @@ int gb_control_bundle_resume(struct gb_control *control, u8 bundle_id); int gb_control_bundle_deactivate(struct gb_control *control, u8 bundle_id); int gb_control_bundle_activate(struct gb_control *control, u8 bundle_id); int gb_control_interface_suspend_prepare(struct gb_control *control); +int gb_control_interface_deactivate_prepare(struct gb_control *control); #endif /* __CONTROL_H */ diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index cd64a99..10209ae 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -131,6 +131,7 @@ struct gb_protocol_version_response { #define GB_CONTROL_TYPE_BUNDLE_DEACTIVATE 0x11 #define GB_CONTROL_TYPE_BUNDLE_ACTIVATE 0x12 #define GB_CONTROL_TYPE_INTF_SUSPEND_PREPARE 0x13 +#define GB_CONTROL_TYPE_INTF_DEACTIVATE_PREPARE 0x14 struct gb_control_version_request { __u8 major; -- cgit v0.10.2 From 385227fce67959a1ab2094fdc9afb78ac19a0dfe Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Thu, 7 Jul 2016 22:07:00 -0500 Subject: greybus: control: add interface hibernate abort operation Add the AP implementation for the Greybus Control Hibernate Abort Operation. AP may use this Operation to abort a previous Control Interface Suspend or Control Interface Deactivate Prepare Operation. Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index a1c78fc..55bb465 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -406,6 +406,30 @@ int gb_control_interface_deactivate_prepare(struct gb_control *control) return 0; } +int gb_control_interface_hibernate_abort(struct gb_control *control) +{ + struct gb_control_intf_pm_response response; + int ret; + + ret = gb_operation_sync(control->connection, + GB_CONTROL_TYPE_INTF_HIBERNATE_ABORT, NULL, 0, + &response, sizeof(response)); + if (ret) { + dev_err(&control->dev, + "failed to send interface aborting hibernate: %d\n", + ret); + return ret; + } + + if (response.status != GB_CONTROL_INTF_PM_OK) { + dev_err(&control->dev, "interface error while aborting hibernate: %d\n", + response.status); + return gb_control_interface_pm_status_map(response.status); + } + + return 0; +} + static ssize_t vendor_string_show(struct device *dev, struct device_attribute *attr, char *buf) { diff --git a/drivers/staging/greybus/control.h b/drivers/staging/greybus/control.h index 2f76ae4..86a4902 100644 --- a/drivers/staging/greybus/control.h +++ b/drivers/staging/greybus/control.h @@ -58,4 +58,5 @@ int gb_control_bundle_deactivate(struct gb_control *control, u8 bundle_id); int gb_control_bundle_activate(struct gb_control *control, u8 bundle_id); int gb_control_interface_suspend_prepare(struct gb_control *control); int gb_control_interface_deactivate_prepare(struct gb_control *control); +int gb_control_interface_hibernate_abort(struct gb_control *control); #endif /* __CONTROL_H */ diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 10209ae..dfee737 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -132,6 +132,7 @@ struct gb_protocol_version_response { #define GB_CONTROL_TYPE_BUNDLE_ACTIVATE 0x12 #define GB_CONTROL_TYPE_INTF_SUSPEND_PREPARE 0x13 #define GB_CONTROL_TYPE_INTF_DEACTIVATE_PREPARE 0x14 +#define GB_CONTROL_TYPE_INTF_HIBERNATE_ABORT 0x15 struct gb_control_version_request { __u8 major; -- cgit v0.10.2 From fc8a4027135252b49650a4dbfcf2a8fb434a6e6a Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Thu, 7 Jul 2016 22:07:00 -0500 Subject: greybus: svc: add interface resume operation Add the AP implementation for the Greybus SVC Interface Resume Operation. This operation allows the AP to request the SVC to resume an Interface which was previously SUSPENDED, allowing it to later be ENUMERATED. Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index dfee737..1a12531 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -1001,6 +1001,7 @@ struct gb_spi_transfer_response { #define GB_SVC_TYPE_INTF_UNIPRO_ENABLE 0x25 #define GB_SVC_TYPE_INTF_UNIPRO_DISABLE 0x26 #define GB_SVC_TYPE_INTF_ACTIVATE 0x27 +#define GB_SVC_TYPE_INTF_RESUME 0x28 #define GB_SVC_TYPE_INTF_MAILBOX_EVENT 0x29 /* Greybus SVC protocol status values */ @@ -1321,6 +1322,14 @@ struct gb_svc_intf_activate_response { __u8 intf_type; } __packed; +struct gb_svc_intf_resume_request { + __u8 intf_id; +} __packed; + +struct gb_svc_intf_resume_response { + __u8 status; +} __packed; + #define GB_SVC_INTF_MAILBOX_NONE 0x00 #define GB_SVC_INTF_MAILBOX_AP 0x01 #define GB_SVC_INTF_MAILBOX_GREYBUS 0x02 diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 63d2a53..a46d7fb 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -14,6 +14,7 @@ #define SVC_INTF_EJECT_TIMEOUT 9000 #define SVC_INTF_ACTIVATE_TIMEOUT 6000 +#define SVC_INTF_RESUME_TIMEOUT 3000 struct gb_svc_deferred_request { struct work_struct work; @@ -354,6 +355,34 @@ int gb_svc_intf_activate(struct gb_svc *svc, u8 intf_id, u8 *intf_type) return 0; } +int gb_svc_intf_resume(struct gb_svc *svc, u8 intf_id) +{ + struct gb_svc_intf_resume_request request; + struct gb_svc_intf_resume_response response; + int ret; + + request.intf_id = intf_id; + + ret = gb_operation_sync_timeout(svc->connection, + GB_SVC_TYPE_INTF_RESUME, + &request, sizeof(request), + &response, sizeof(response), + SVC_INTF_RESUME_TIMEOUT); + if (ret < 0) { + dev_err(&svc->dev, "failed to send interface resume %u: %d\n", + intf_id, ret); + return ret; + } + + if (response.status != GB_SVC_OP_SUCCESS) { + dev_err(&svc->dev, "failed to resume interface %u: %u\n", + intf_id, response.status); + return -EREMOTEIO; + } + + return 0; +} + int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, u32 *value) { diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index 7f5e534..750eaff 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -71,6 +71,8 @@ int gb_svc_intf_vsys_set(struct gb_svc *svc, u8 intf_id, bool enable); int gb_svc_intf_refclk_set(struct gb_svc *svc, u8 intf_id, bool enable); int gb_svc_intf_unipro_set(struct gb_svc *svc, u8 intf_id, bool enable); int gb_svc_intf_activate(struct gb_svc *svc, u8 intf_id, u8 *intf_type); +int gb_svc_intf_resume(struct gb_svc *svc, u8 intf_id); + int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, u32 *value); int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, -- cgit v0.10.2 From c7dc28ff2b47d6dc4efd420b6f1325554b6f8287 Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Thu, 7 Jul 2016 22:07:00 -0500 Subject: greybus: svc: add power mode call for link hibernation Due to when using set_power_mode to hibernate a link, it won't trigger a POWERMODEIND event, hence the hard-coded GB_SVC_SETPWRM_PWR_OK would be returned and it should also be considered as successful result code for link hibernation. Therefore, adding this set_power_mode_hibernate function to separate the two calls in order to check with the correct result code. Testing Done: - Suspend an Interface and observe no set power mode error. Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index a46d7fb..14bada9 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -687,6 +687,41 @@ int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series, } EXPORT_SYMBOL_GPL(gb_svc_intf_set_power_mode); +int gb_svc_intf_set_power_mode_hibernate(struct gb_svc *svc, u8 intf_id) +{ + struct gb_svc_intf_set_pwrm_request request; + struct gb_svc_intf_set_pwrm_response response; + int ret; + u16 result_code; + + memset(&request, 0, sizeof(request)); + + request.intf_id = intf_id; + request.hs_series = GB_SVC_UNIPRO_HS_SERIES_A; + request.tx_mode = GB_SVC_UNIPRO_HIBERNATE_MODE; + request.rx_mode = GB_SVC_UNIPRO_HIBERNATE_MODE; + + ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_INTF_SET_PWRM, + &request, sizeof(request), + &response, sizeof(response)); + if (ret < 0) { + dev_err(&svc->dev, + "failed to send set power mode operation to interface %u: %d\n", + intf_id, ret); + return ret; + } + + result_code = response.result_code; + if (result_code != GB_SVC_SETPWRM_PWR_OK) { + dev_err(&svc->dev, + "failed to hibernate the link for interface %u: %u\n", + intf_id, result_code); + return -EIO; + } + + return 0; +} + int gb_svc_ping(struct gb_svc *svc) { return gb_operation_sync_timeout(svc->connection, GB_SVC_TYPE_PING, diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index 750eaff..4ab066b 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -84,6 +84,7 @@ int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series, u8 flags, u32 quirks, struct gb_svc_l2_timer_cfg *local, struct gb_svc_l2_timer_cfg *remote); +int gb_svc_intf_set_power_mode_hibernate(struct gb_svc *svc, u8 intf_id); int gb_svc_ping(struct gb_svc *svc); int gb_svc_watchdog_create(struct gb_svc *svc); void gb_svc_watchdog_destroy(struct gb_svc *svc); -- cgit v0.10.2 From cc28c2c2283d5e1b8d2fc0a1cf2bc45783fc7f71 Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Thu, 7 Jul 2016 22:07:00 -0500 Subject: greybus: interface: implement unipro link hibernate call Adds AP implementation of unipro link hibernation set power mode call needed for proper cport closure and interface suspend and power off transition. Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 05d0020..2290a9c3f 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -641,11 +641,9 @@ static int gb_interface_activate_operation(struct gb_interface *intf) static int gb_interface_hibernate_link(struct gb_interface *intf) { - dev_dbg(&intf->dev, "%s\n", __func__); - - /* FIXME: implement */ + struct gb_svc *svc = intf->hd->svc; - return 0; + return gb_svc_intf_set_power_mode_hibernate(svc, intf->interface_id); } /* -- cgit v0.10.2 From 707a5c42ce55938de599e4461384efafd6950c37 Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Thu, 7 Jul 2016 22:07:00 -0500 Subject: greybus: control: add connection suspend and resume calls Adds function calls for handling control connection suspend and resume, for now all they do is disable and enable control connection. Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index 55bb465..37a30b3 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -546,6 +546,27 @@ void gb_control_disable(struct gb_control *control) gb_connection_disable(control->connection); } +int gb_control_suspend(struct gb_control *control) +{ + gb_connection_disable(control->connection); + + return 0; +} + +int gb_control_resume(struct gb_control *control) +{ + int ret; + + ret = gb_connection_enable_tx(control->connection); + if (ret) { + dev_err(&control->connection->intf->dev, + "failed to enable control connection: %d\n", ret); + return ret; + } + + return 0; +} + int gb_control_add(struct gb_control *control) { int ret; diff --git a/drivers/staging/greybus/control.h b/drivers/staging/greybus/control.h index 86a4902..f73ec3e 100644 --- a/drivers/staging/greybus/control.h +++ b/drivers/staging/greybus/control.h @@ -29,6 +29,8 @@ struct gb_control { struct gb_control *gb_control_create(struct gb_interface *intf); int gb_control_enable(struct gb_control *control); void gb_control_disable(struct gb_control *control); +int gb_control_suspend(struct gb_control *control); +int gb_control_resume(struct gb_control *control); int gb_control_add(struct gb_control *control); void gb_control_del(struct gb_control *control); struct gb_control *gb_control_get(struct gb_control *control); -- cgit v0.10.2 From 576bffb5a84f205c9ada777bc201b95cd8c0b868 Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Thu, 7 Jul 2016 22:07:00 -0500 Subject: greybus: interface: send deactivate prepare when interface is disabled The AP Interface shall exchange a Greybus Control Interface Deactivate Prepare Operation with the Interface being powered down. Testing Done: - Check for the return code after sending the deactivate prepare operation Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 2290a9c3f..e7efc54 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -861,6 +861,9 @@ void gb_interface_disable(struct gb_interface *intf) list_for_each_entry_safe(bundle, next, &intf->bundles, links) gb_bundle_destroy(bundle); + if (!intf->mode_switch && !intf->disconnected) + gb_control_interface_deactivate_prepare(intf->control); + gb_timesync_interface_remove(intf); gb_control_del(intf->control); gb_control_disable(intf->control); -- cgit v0.10.2 From 1f25ca11d84a3aa01b2b12a419a1385c2f5513bc Mon Sep 17 00:00:00 2001 From: Matt Ranostay <mranostay@gmail.com> Date: Mon, 4 Jul 2016 18:54:04 -0700 Subject: iio: temperature: add support for Maxim thermocouple chips Add initial driver support for MAX6675, and MAX31855 thermocouple chips. Cc: Marek Vasut <marex@denx.de> Cc: Matt Porter <mporter@konsulko.com> Signed-off-by: Matt Ranostay <mranostay@gmail.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/Documentation/devicetree/bindings/iio/temperature/maxim_thermocouple.txt b/Documentation/devicetree/bindings/iio/temperature/maxim_thermocouple.txt new file mode 100644 index 0000000..28bc5c4 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/temperature/maxim_thermocouple.txt @@ -0,0 +1,21 @@ +Maxim thermocouple support + +* https://datasheets.maximintegrated.com/en/ds/MAX6675.pdf +* https://datasheets.maximintegrated.com/en/ds/MAX31855.pdf + +Required properties: + + - compatible: must be "maxim,max31855" or "maxim,max6675" + - reg: SPI chip select number for the device + - spi-max-frequency: must be 4300000 + - spi-cpha: must be defined for max6675 to enable SPI mode 1 + + Refer to spi/spi-bus.txt for generic SPI slave bindings. + +Example: + + max31855@0 { + compatible = "maxim,max31855"; + reg = <0>; + spi-max-frequency = <4300000>; + }; diff --git a/drivers/iio/temperature/Kconfig b/drivers/iio/temperature/Kconfig index c4664e5..1d3da05 100644 --- a/drivers/iio/temperature/Kconfig +++ b/drivers/iio/temperature/Kconfig @@ -3,6 +3,20 @@ # menu "Temperature sensors" +config MAXIM_THERMOCOUPLE + tristate "Maxim thermocouple sensors" + depends on SPI + help + If you say yes here you get support for the Maxim series of + thermocouple sensors connected via SPI. + + Supported sensors: + * MAX6675 + * MAX31855 + + This driver can also be built as a module. If so, the module will + be called maxim_thermocouple. + config MLX90614 tristate "MLX90614 contact-less infrared sensor" depends on I2C diff --git a/drivers/iio/temperature/Makefile b/drivers/iio/temperature/Makefile index 02bc79d..78c3de0 100644 --- a/drivers/iio/temperature/Makefile +++ b/drivers/iio/temperature/Makefile @@ -2,6 +2,7 @@ # Makefile for industrial I/O temperature drivers # +obj-$(CONFIG_MAXIM_THERMOCOUPLE) += maxim_thermocouple.o obj-$(CONFIG_MLX90614) += mlx90614.o obj-$(CONFIG_TMP006) += tmp006.o obj-$(CONFIG_TSYS01) += tsys01.o diff --git a/drivers/iio/temperature/maxim_thermocouple.c b/drivers/iio/temperature/maxim_thermocouple.c new file mode 100644 index 0000000..030827e --- /dev/null +++ b/drivers/iio/temperature/maxim_thermocouple.c @@ -0,0 +1,281 @@ +/* + * maxim_thermocouple.c - Support for Maxim thermocouple chips + * + * Copyright (C) 2016 Matt Ranostay <mranostay@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/mutex.h> +#include <linux/err.h> +#include <linux/spi/spi.h> +#include <linux/iio/iio.h> +#include <linux/iio/trigger.h> +#include <linux/iio/buffer.h> +#include <linux/iio/triggered_buffer.h> +#include <linux/iio/trigger_consumer.h> + +#define MAXIM_THERMOCOUPLE_DRV_NAME "maxim_thermocouple" + +enum { + MAX6675, + MAX31855, +}; + +const struct iio_chan_spec max6675_channels[] = { + { /* thermocouple temperature */ + .type = IIO_TEMP, + .info_mask_separate = + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .scan_index = 0, + .scan_type = { + .sign = 's', + .realbits = 13, + .storagebits = 16, + .shift = 3, + .endianness = IIO_BE, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(1), +}; + +const struct iio_chan_spec max31855_channels[] = { + { /* thermocouple temperature */ + .type = IIO_TEMP, + .address = 2, + .info_mask_separate = + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .scan_index = 0, + .scan_type = { + .sign = 's', + .realbits = 14, + .storagebits = 16, + .shift = 2, + .endianness = IIO_BE, + }, + }, + { /* cold junction temperature */ + .type = IIO_TEMP, + .address = 0, + .channel2 = IIO_MOD_TEMP_AMBIENT, + .modified = 1, + .info_mask_separate = + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .scan_index = 1, + .scan_type = { + .sign = 's', + .realbits = 12, + .storagebits = 16, + .shift = 4, + .endianness = IIO_BE, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(2), +}; + +static const unsigned long max31855_scan_masks[] = {0x3, 0}; + +struct maxim_thermocouple_chip { + const struct iio_chan_spec *channels; + const unsigned long *scan_masks; + u8 num_channels; + u8 read_size; + + /* bit-check for valid input */ + u32 status_bit; +}; + +const struct maxim_thermocouple_chip maxim_thermocouple_chips[] = { + [MAX6675] = { + .channels = max6675_channels, + .num_channels = ARRAY_SIZE(max6675_channels), + .read_size = 2, + .status_bit = BIT(2), + }, + [MAX31855] = { + .channels = max31855_channels, + .num_channels = ARRAY_SIZE(max31855_channels), + .read_size = 4, + .scan_masks = max31855_scan_masks, + .status_bit = BIT(16), + }, +}; + +struct maxim_thermocouple_data { + struct spi_device *spi; + const struct maxim_thermocouple_chip *chip; + + u8 buffer[16] ____cacheline_aligned; +}; + +static int maxim_thermocouple_read(struct maxim_thermocouple_data *data, + struct iio_chan_spec const *chan, int *val) +{ + unsigned int storage_bytes = data->chip->read_size; + unsigned int shift = chan->scan_type.shift + (chan->address * 8); + unsigned int buf; + int ret; + + ret = spi_read(data->spi, (void *) &buf, storage_bytes); + if (ret) + return ret; + + switch (storage_bytes) { + case 2: + *val = be16_to_cpu(buf); + break; + case 4: + *val = be32_to_cpu(buf); + break; + } + + /* check to be sure this is a valid reading */ + if (*val & data->chip->status_bit) + return -EINVAL; + + *val = sign_extend32(*val >> shift, chan->scan_type.realbits - 1); + + return 0; +} + +static irqreturn_t maxim_thermocouple_trigger_handler(int irq, void *private) +{ + struct iio_poll_func *pf = private; + struct iio_dev *indio_dev = pf->indio_dev; + struct maxim_thermocouple_data *data = iio_priv(indio_dev); + int ret; + + ret = spi_read(data->spi, data->buffer, data->chip->read_size); + if (!ret) { + iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_get_time_ns(indio_dev)); + } + + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static int maxim_thermocouple_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct maxim_thermocouple_data *data = iio_priv(indio_dev); + int ret = -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + + ret = maxim_thermocouple_read(data, chan, val); + iio_device_release_direct_mode(indio_dev); + + if (!ret) + return IIO_VAL_INT; + + break; + case IIO_CHAN_INFO_SCALE: + switch (chan->channel2) { + case IIO_MOD_TEMP_AMBIENT: + *val = 62; + *val2 = 500000; /* 1000 * 0.0625 */ + ret = IIO_VAL_INT_PLUS_MICRO; + break; + default: + *val = 250; /* 1000 * 0.25 */ + ret = IIO_VAL_INT; + }; + break; + } + + return ret; +} + +static const struct iio_info maxim_thermocouple_info = { + .driver_module = THIS_MODULE, + .read_raw = maxim_thermocouple_read_raw, +}; + +static int maxim_thermocouple_probe(struct spi_device *spi) +{ + const struct spi_device_id *id = spi_get_device_id(spi); + struct iio_dev *indio_dev; + struct maxim_thermocouple_data *data; + const struct maxim_thermocouple_chip *chip = + &maxim_thermocouple_chips[id->driver_data]; + int ret; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + indio_dev->info = &maxim_thermocouple_info; + indio_dev->name = MAXIM_THERMOCOUPLE_DRV_NAME; + indio_dev->channels = chip->channels; + indio_dev->available_scan_masks = chip->scan_masks; + indio_dev->num_channels = chip->num_channels; + indio_dev->modes = INDIO_DIRECT_MODE; + + data = iio_priv(indio_dev); + data->spi = spi; + data->chip = chip; + + ret = iio_triggered_buffer_setup(indio_dev, NULL, + maxim_thermocouple_trigger_handler, NULL); + if (ret) + return ret; + + ret = iio_device_register(indio_dev); + if (ret) + goto error_unreg_buffer; + + return 0; + +error_unreg_buffer: + iio_triggered_buffer_cleanup(indio_dev); + + return ret; +} + +static int maxim_thermocouple_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + + iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); + + return 0; +} + +static const struct spi_device_id maxim_thermocouple_id[] = { + {"max6675", MAX6675}, + {"max31855", MAX31855}, + {}, +}; +MODULE_DEVICE_TABLE(spi, maxim_thermocouple_id); + +static struct spi_driver maxim_thermocouple_driver = { + .driver = { + .name = MAXIM_THERMOCOUPLE_DRV_NAME, + }, + .probe = maxim_thermocouple_probe, + .remove = maxim_thermocouple_remove, + .id_table = maxim_thermocouple_id, +}; +module_spi_driver(maxim_thermocouple_driver); + +MODULE_AUTHOR("Matt Ranostay <mranostay@gmail.com>"); +MODULE_DESCRIPTION("Maxim thermocouple sensors"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From d978bfdd0cd5fc31c27b587337f88e32deb768eb Mon Sep 17 00:00:00 2001 From: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Date: Tue, 5 Jul 2016 12:23:18 +0200 Subject: iio: light: vcnl4000: Mention and check support for VCNL4010 and VCNL4020 VCNL4000, VCNL4010 and VCNL4020 chips are fairly compatible from a software point of view, added features are not yet supported by the driver patch adds a check for the product ID and demotes the corresponding dev_info() to dev_dbg() Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 7c566f5..2821747 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -333,11 +333,11 @@ config US5182D will be called us5182d. config VCNL4000 - tristate "VCNL4000 combined ALS and proximity sensor" + tristate "VCNL4000/4010/4020 combined ALS and proximity sensor" depends on I2C help - Say Y here if you want to build a driver for the Vishay VCNL4000 - combined ambient light and proximity sensor. + Say Y here if you want to build a driver for the Vishay VCNL4000, + VCNL4010, VCNL4020 combined ambient light and proximity sensor. To compile this driver as a module, choose M here: the module will be called vcnl4000. diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index c9d85bb..071ff97 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -1,6 +1,6 @@ /* - * vcnl4000.c - Support for Vishay VCNL4000 combined ambient light and - * proximity sensor + * vcnl4000.c - Support for Vishay VCNL4000/4010/4020 combined ambient + * light and proximity sensor * * Copyright 2012 Peter Meerwald <pmeerw@pmeerw.net> * @@ -13,6 +13,8 @@ * TODO: * allow to adjust IR current * proximity threshold and event handling + * periodic ALS/proximity measurement (VCNL4010/20) + * interrupts (VCNL4010/20) */ #include <linux/module.h> @@ -24,6 +26,8 @@ #include <linux/iio/sysfs.h> #define VCNL4000_DRV_NAME "vcnl4000" +#define VCNL4000_ID 0x01 +#define VCNL4010_ID 0x02 /* for VCNL4020, VCNL4010 */ #define VCNL4000_COMMAND 0x80 /* Command register */ #define VCNL4000_PROD_REV 0x81 /* Product ID and Revision ID */ @@ -155,7 +159,7 @@ static int vcnl4000_probe(struct i2c_client *client, { struct vcnl4000_data *data; struct iio_dev *indio_dev; - int ret; + int ret, prod_id; indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); if (!indio_dev) @@ -169,8 +173,13 @@ static int vcnl4000_probe(struct i2c_client *client, if (ret < 0) return ret; - dev_info(&client->dev, "VCNL4000 Ambient light/proximity sensor, Prod %02x, Rev: %02x\n", - ret >> 4, ret & 0xf); + prod_id = ret >> 4; + if (prod_id != VCNL4010_ID && prod_id != VCNL4000_ID) + return -ENODEV; + + dev_dbg(&client->dev, "%s Ambient light/proximity sensor, Rev: %02x\n", + (prod_id == VCNL4010_ID) ? "VCNL4010/4020" : "VCNL4000", + ret & 0xf); indio_dev->dev.parent = &client->dev; indio_dev->info = &vcnl4000_info; -- cgit v0.10.2 From ff6a52590c72e2ff05b3b5ba273fb08e4b9a9a44 Mon Sep 17 00:00:00 2001 From: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Date: Tue, 5 Jul 2016 12:23:19 +0200 Subject: iio: light: vcnl4000: Use BIT() macro Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index 071ff97..7f247ed 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -41,10 +41,10 @@ #define VCNL4000_PS_MOD_ADJ 0x8a /* Proximity modulator timing adjustment */ /* Bit masks for COMMAND register */ -#define VCNL4000_AL_RDY 0x40 /* ALS data ready? */ -#define VCNL4000_PS_RDY 0x20 /* proximity data ready? */ -#define VCNL4000_AL_OD 0x10 /* start on-demand ALS measurement */ -#define VCNL4000_PS_OD 0x08 /* start on-demand proximity measurement */ +#define VCNL4000_AL_RDY BIT(6) /* ALS data ready? */ +#define VCNL4000_PS_RDY BIT(5) /* proximity data ready? */ +#define VCNL4000_AL_OD BIT(4) /* start on-demand ALS measurement */ +#define VCNL4000_PS_OD BIT(3) /* start on-demand proximity measurement */ struct vcnl4000_data { struct i2c_client *client; -- cgit v0.10.2 From 5d6931393f9dbe438a210dd33f186ec156b4d2b8 Mon Sep 17 00:00:00 2001 From: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Date: Tue, 5 Jul 2016 12:23:20 +0200 Subject: iio: light: vcnl4000: Cleanup read_raw() returns Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index 7f247ed..9f94b6b 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -109,7 +109,7 @@ static int vcnl4000_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) { - int ret = -EINVAL; + int ret; struct vcnl4000_data *data = iio_priv(indio_dev); switch (mask) { @@ -121,32 +121,27 @@ static int vcnl4000_read_raw(struct iio_dev *indio_dev, VCNL4000_AL_RESULT_HI, val); if (ret < 0) return ret; - ret = IIO_VAL_INT; - break; + return IIO_VAL_INT; case IIO_PROXIMITY: ret = vcnl4000_measure(data, VCNL4000_PS_OD, VCNL4000_PS_RDY, VCNL4000_PS_RESULT_HI, val); if (ret < 0) return ret; - ret = IIO_VAL_INT; - break; + return IIO_VAL_INT; default: - break; + return -EINVAL; } - break; case IIO_CHAN_INFO_SCALE: - if (chan->type == IIO_LIGHT) { - *val = 0; - *val2 = 250000; - ret = IIO_VAL_INT_PLUS_MICRO; - } - break; + if (chan->type != IIO_LIGHT) + return -EINVAL; + + *val = 0; + *val2 = 250000; + return IIO_VAL_INT_PLUS_MICRO; default: - break; + return -EINVAL; } - - return ret; } static const struct iio_info vcnl4000_info = { -- cgit v0.10.2 From ff34ed6d7889bb83b77dbc9216cd549f40b1bc8c Mon Sep 17 00:00:00 2001 From: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Date: Tue, 5 Jul 2016 12:23:21 +0200 Subject: iio: light: vcnl4000: Add missing locking Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index 9f94b6b..360b6e9 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -48,6 +48,7 @@ struct vcnl4000_data { struct i2c_client *client; + struct mutex lock; }; static const struct i2c_device_id vcnl4000_id[] = { @@ -63,16 +64,18 @@ static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask, __be16 buf; int ret; + mutex_lock(&data->lock); + ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, req_mask); if (ret < 0) - return ret; + goto fail; /* wait for data to become ready */ while (tries--) { ret = i2c_smbus_read_byte_data(data->client, VCNL4000_COMMAND); if (ret < 0) - return ret; + goto fail; if (ret & rdy_mask) break; msleep(20); /* measurement takes up to 100 ms */ @@ -81,17 +84,23 @@ static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask, if (tries < 0) { dev_err(&data->client->dev, "vcnl4000_measure() failed, data not ready\n"); - return -EIO; + ret = -EIO; + goto fail; } ret = i2c_smbus_read_i2c_block_data(data->client, data_reg, sizeof(buf), (u8 *) &buf); if (ret < 0) - return ret; + goto fail; + mutex_unlock(&data->lock); *val = be16_to_cpu(buf); return 0; + +fail: + mutex_unlock(&data->lock); + return ret; } static const struct iio_chan_spec vcnl4000_channels[] = { @@ -163,6 +172,7 @@ static int vcnl4000_probe(struct i2c_client *client, data = iio_priv(indio_dev); i2c_set_clientdata(client, indio_dev); data->client = client; + mutex_init(&data->lock); ret = i2c_smbus_read_byte_data(data->client, VCNL4000_PROD_REV); if (ret < 0) -- cgit v0.10.2 From 13e6d634c1c26b81a90c9a9cc5c56f95fad5195c Mon Sep 17 00:00:00 2001 From: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Date: Tue, 5 Jul 2016 13:55:36 +0200 Subject: staging: iio: isl29018: Prefix #defines Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index 76d9f74..0599337 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -32,25 +32,25 @@ #include <linux/iio/sysfs.h> #include <linux/acpi.h> -#define CONVERSION_TIME_MS 100 +#define ISL29018_CONV_TIME_MS 100 #define ISL29018_REG_ADD_COMMAND1 0x00 -#define COMMMAND1_OPMODE_SHIFT 5 -#define COMMMAND1_OPMODE_MASK (7 << COMMMAND1_OPMODE_SHIFT) -#define COMMMAND1_OPMODE_POWER_DOWN 0 -#define COMMMAND1_OPMODE_ALS_ONCE 1 -#define COMMMAND1_OPMODE_IR_ONCE 2 -#define COMMMAND1_OPMODE_PROX_ONCE 3 +#define ISL29018_CMD1_OPMODE_SHIFT 5 +#define ISL29018_CMD1_OPMODE_MASK (7 << ISL29018_CMD1_OPMODE_SHIFT) +#define ISL29018_CMD1_OPMODE_POWER_DOWN 0 +#define ISL29018_CMD1_OPMODE_ALS_ONCE 1 +#define ISL29018_CMD1_OPMODE_IR_ONCE 2 +#define ISL29018_CMD1_OPMODE_PROX_ONCE 3 -#define ISL29018_REG_ADD_COMMANDII 0x01 -#define COMMANDII_RESOLUTION_SHIFT 2 -#define COMMANDII_RESOLUTION_MASK (0x3 << COMMANDII_RESOLUTION_SHIFT) +#define ISL29018_REG_ADD_COMMAND2 0x01 +#define ISL29018_CMD2_RESOLUTION_SHIFT 2 +#define ISL29018_CMD2_RESOLUTION_MASK (0x3 << ISL29018_CMD2_RESOLUTION_SHIFT) -#define COMMANDII_RANGE_SHIFT 0 -#define COMMANDII_RANGE_MASK (0x3 << COMMANDII_RANGE_SHIFT) +#define ISL29018_CMD2_RANGE_SHIFT 0 +#define ISL29018_CMD2_RANGE_MASK (0x3 << ISL29018_CMD2_RANGE_SHIFT) -#define COMMANDII_SCHEME_SHIFT 7 -#define COMMANDII_SCHEME_MASK (0x1 << COMMANDII_SCHEME_SHIFT) +#define ISL29018_CMD2_SCHEME_SHIFT 7 +#define ISL29018_CMD2_SCHEME_MASK (0x1 << ISL29018_CMD2_SCHEME_SHIFT) #define ISL29018_REG_ADD_DATA_LSB 0x02 #define ISL29018_REG_ADD_DATA_MSB 0x03 @@ -127,9 +127,9 @@ static int isl29018_set_integration_time(struct isl29018_chip *chip, if (i >= ARRAY_SIZE(isl29018_int_utimes[chip->type])) return -EINVAL; - ret = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMANDII, - COMMANDII_RESOLUTION_MASK, - i << COMMANDII_RESOLUTION_SHIFT); + ret = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMAND2, + ISL29018_CMD2_RESOLUTION_MASK, + i << ISL29018_CMD2_RESOLUTION_SHIFT); if (ret < 0) return ret; @@ -163,9 +163,9 @@ static int isl29018_set_scale(struct isl29018_chip *chip, int scale, int uscale) if (i >= ARRAY_SIZE(isl29018_scales[chip->int_time])) return -EINVAL; - ret = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMANDII, - COMMANDII_RANGE_MASK, - i << COMMANDII_RANGE_SHIFT); + ret = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMAND2, + ISL29018_CMD2_RANGE_MASK, + i << ISL29018_CMD2_RANGE_SHIFT); if (ret < 0) return ret; @@ -183,13 +183,13 @@ static int isl29018_read_sensor_input(struct isl29018_chip *chip, int mode) /* Set mode */ status = regmap_write(chip->regmap, ISL29018_REG_ADD_COMMAND1, - mode << COMMMAND1_OPMODE_SHIFT); + mode << ISL29018_CMD1_OPMODE_SHIFT); if (status) { dev_err(dev, "Error in setting operating mode err %d\n", status); return status; } - msleep(CONVERSION_TIME_MS); + msleep(ISL29018_CONV_TIME_MS); status = regmap_read(chip->regmap, ISL29018_REG_ADD_DATA_LSB, &lsb); if (status < 0) { dev_err(dev, @@ -213,7 +213,8 @@ static int isl29018_read_lux(struct isl29018_chip *chip, int *lux) int lux_data; unsigned int data_x_range; - lux_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_ALS_ONCE); + lux_data = isl29018_read_sensor_input(chip, + ISL29018_CMD1_OPMODE_ALS_ONCE); if (lux_data < 0) return lux_data; @@ -230,7 +231,8 @@ static int isl29018_read_ir(struct isl29018_chip *chip, int *ir) { int ir_data; - ir_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_IR_ONCE); + ir_data = isl29018_read_sensor_input(chip, + ISL29018_CMD1_OPMODE_IR_ONCE); if (ir_data < 0) return ir_data; @@ -249,16 +251,16 @@ static int isl29018_read_proximity_ir(struct isl29018_chip *chip, int scheme, struct device *dev = regmap_get_device(chip->regmap); /* Do proximity sensing with required scheme */ - status = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMANDII, - COMMANDII_SCHEME_MASK, - scheme << COMMANDII_SCHEME_SHIFT); + status = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMAND2, + ISL29018_CMD2_SCHEME_MASK, + scheme << ISL29018_CMD2_SCHEME_SHIFT); if (status) { dev_err(dev, "Error in setting operating mode\n"); return status; } prox_data = isl29018_read_sensor_input(chip, - COMMMAND1_OPMODE_PROX_ONCE); + ISL29018_CMD1_OPMODE_PROX_ONCE); if (prox_data < 0) return prox_data; @@ -267,7 +269,8 @@ static int isl29018_read_proximity_ir(struct isl29018_chip *chip, int scheme, return 0; } - ir_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_IR_ONCE); + ir_data = isl29018_read_sensor_input(chip, + ISL29018_CMD1_OPMODE_IR_ONCE); if (ir_data < 0) return ir_data; -- cgit v0.10.2 From ab5b9492c0f43511ada25b3209d5645415858967 Mon Sep 17 00:00:00 2001 From: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Date: Tue, 5 Jul 2016 13:55:37 +0200 Subject: staging: iio: isl29018: Remove excessive output messages Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index 0599337..875007f 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -341,10 +341,8 @@ static ssize_t store_prox_infrared_suppression(struct device *dev, if (kstrtoint(buf, 10, &val)) return -EINVAL; - if (!(val == 0 || val == 1)) { - dev_err(dev, "The mode is not supported\n"); + if (!(val == 0 || val == 1)) return -EINVAL; - } /* * get the "proximity scheme" i.e. if the chip does on chip @@ -727,10 +725,8 @@ static int isl29018_probe(struct i2c_client *client, int dev_id = 0; indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip)); - if (!indio_dev) { - dev_err(&client->dev, "iio allocation fails\n"); + if (!indio_dev) return -ENOMEM; - } chip = iio_priv(indio_dev); i2c_set_clientdata(client, indio_dev); @@ -770,13 +766,7 @@ static int isl29018_probe(struct i2c_client *client, indio_dev->name = name; indio_dev->dev.parent = &client->dev; indio_dev->modes = INDIO_DIRECT_MODE; - err = devm_iio_device_register(&client->dev, indio_dev); - if (err) { - dev_err(&client->dev, "iio registration fails\n"); - return err; - } - - return 0; + return devm_iio_device_register(&client->dev, indio_dev); } #ifdef CONFIG_PM_SLEEP -- cgit v0.10.2 From c833c6926a0af75dec48b6a3974278bef44fd49b Mon Sep 17 00:00:00 2001 From: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Date: Tue, 5 Jul 2016 13:55:38 +0200 Subject: staging: iio: isl29018: Drop newlines Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index 875007f..9b3ca0e 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -215,7 +215,6 @@ static int isl29018_read_lux(struct isl29018_chip *chip, int *lux) lux_data = isl29018_read_sensor_input(chip, ISL29018_CMD1_OPMODE_ALS_ONCE); - if (lux_data < 0) return lux_data; @@ -233,7 +232,6 @@ static int isl29018_read_ir(struct isl29018_chip *chip, int *ir) ir_data = isl29018_read_sensor_input(chip, ISL29018_CMD1_OPMODE_IR_ONCE); - if (ir_data < 0) return ir_data; @@ -271,7 +269,6 @@ static int isl29018_read_proximity_ir(struct isl29018_chip *chip, int scheme, ir_data = isl29018_read_sensor_input(chip, ISL29018_CMD1_OPMODE_IR_ONCE); - if (ir_data < 0) return ir_data; -- cgit v0.10.2 From 96273f43a87aa94acf25ec61e4db374bd8a660e7 Mon Sep 17 00:00:00 2001 From: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Date: Tue, 5 Jul 2016 13:55:39 +0200 Subject: staging: iio: isl29018: Cleanup of comments Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index 9b3ca0e..cafa2a7 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -133,7 +133,7 @@ static int isl29018_set_integration_time(struct isl29018_chip *chip, if (ret < 0) return ret; - /* keep the same range when integration time changes */ + /* Keep the same range when integration time changes */ int_time = chip->int_time; for (i = 0; i < ARRAY_SIZE(isl29018_scales[int_time]); ++i) { if (chip->scale.scale == isl29018_scales[int_time][i].scale && @@ -313,7 +313,6 @@ static ssize_t show_int_time_available(struct device *dev, return len; } -/* proximity scheme */ static ssize_t show_prox_infrared_suppression(struct device *dev, struct device_attribute *attr, char *buf) @@ -322,7 +321,7 @@ static ssize_t show_prox_infrared_suppression(struct device *dev, struct isl29018_chip *chip = iio_priv(indio_dev); /* - * return the "proximity scheme" i.e. if the chip does on chip + * Return the "proximity scheme" i.e. if the chip does on chip * infrared suppression (1 means perform on chip suppression) */ return sprintf(buf, "%d\n", chip->prox_scheme); @@ -342,7 +341,7 @@ static ssize_t store_prox_infrared_suppression(struct device *dev, return -EINVAL; /* - * get the "proximity scheme" i.e. if the chip does on chip + * Get the "proximity scheme" i.e. if the chip does on chip * infrared suppression (1 means perform on chip suppression) */ mutex_lock(&chip->lock); @@ -352,7 +351,6 @@ static ssize_t store_prox_infrared_suppression(struct device *dev, return count; } -/* Channel IO */ static int isl29018_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, @@ -539,7 +537,7 @@ static int isl29035_detect(struct isl29018_chip *chip) if (id != ISL29035_DEVICE_ID) return -ENODEV; - /* clear out brownout bit */ + /* Clear brownout bit */ return regmap_update_bits(chip->regmap, ISL29035_REG_DEVICE_ID, ISL29035_BOUT_MASK, 0); } @@ -572,7 +570,7 @@ static int isl29018_chip_init(struct isl29018_chip *chip) * conversions, clear the test registers, and then rewrite all * registers to the desired values. * ... - * FOR ISL29011, ISL29018, ISL29021, ISL29023 + * For ISL29011, ISL29018, ISL29021, ISL29023 * 1. Write 0x00 to register 0x08 (TEST) * 2. Write 0x00 to register 0x00 (CMD1) * 3. Rewrite all registers to the desired values @@ -601,7 +599,7 @@ static int isl29018_chip_init(struct isl29018_chip *chip) usleep_range(1000, 2000); /* per data sheet, page 10 */ - /* set defaults */ + /* Set defaults */ status = isl29018_set_scale(chip, chip->scale.scale, chip->scale.uscale); if (status < 0) { @@ -647,10 +645,6 @@ static bool is_volatile_reg(struct device *dev, unsigned int reg) } } -/* - * isl29018_regmap_config: regmap configuration. - * Use RBTREE mechanism for caching. - */ static const struct regmap_config isl29018_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -660,7 +654,6 @@ static const struct regmap_config isl29018_regmap_config = { .cache_type = REGCACHE_RBTREE, }; -/* isl29035_regmap_config: regmap configuration for ISL29035 */ static const struct regmap_config isl29035_regmap_config = { .reg_bits = 8, .val_bits = 8, -- cgit v0.10.2 From 9219376d04c6e76c8897f49b9d6637a84d969f1f Mon Sep 17 00:00:00 2001 From: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Date: Tue, 5 Jul 2016 13:55:40 +0200 Subject: staging: iio: isl29018: Prefix remaining functions Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index cafa2a7..80b6a9e 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -280,7 +280,7 @@ static int isl29018_read_proximity_ir(struct isl29018_chip *chip, int scheme, return 0; } -static ssize_t show_scale_available(struct device *dev, +static ssize_t isl29018_show_scale_available(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); @@ -297,7 +297,7 @@ static ssize_t show_scale_available(struct device *dev, return len; } -static ssize_t show_int_time_available(struct device *dev, +static ssize_t isl29018_show_int_time_available(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); @@ -313,7 +313,7 @@ static ssize_t show_int_time_available(struct device *dev, return len; } -static ssize_t show_prox_infrared_suppression(struct device *dev, +static ssize_t isl29018_show_prox_infrared_suppression(struct device *dev, struct device_attribute *attr, char *buf) { @@ -327,7 +327,7 @@ static ssize_t show_prox_infrared_suppression(struct device *dev, return sprintf(buf, "%d\n", chip->prox_scheme); } -static ssize_t store_prox_infrared_suppression(struct device *dev, +static ssize_t isl29018_store_prox_infrared_suppression(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { @@ -487,13 +487,13 @@ static const struct iio_chan_spec isl29023_channels[] = { }; static IIO_DEVICE_ATTR(in_illuminance_integration_time_available, S_IRUGO, - show_int_time_available, NULL, 0); + isl29018_show_int_time_available, NULL, 0); static IIO_DEVICE_ATTR(in_illuminance_scale_available, S_IRUGO, - show_scale_available, NULL, 0); + isl29018_show_scale_available, NULL, 0); static IIO_DEVICE_ATTR(proximity_on_chip_ambient_infrared_suppression, S_IRUGO | S_IWUSR, - show_prox_infrared_suppression, - store_prox_infrared_suppression, 0); + isl29018_show_prox_infrared_suppression, + isl29018_store_prox_infrared_suppression, 0); #define ISL29018_DEV_ATTR(name) (&iio_dev_attr_##name.dev_attr.attr) @@ -631,7 +631,7 @@ static const struct iio_info isl29023_info = { .write_raw = isl29018_write_raw, }; -static bool is_volatile_reg(struct device *dev, unsigned int reg) +static bool isl29018_is_volatile_reg(struct device *dev, unsigned int reg) { switch (reg) { case ISL29018_REG_ADD_DATA_LSB: @@ -648,7 +648,7 @@ static bool is_volatile_reg(struct device *dev, unsigned int reg) static const struct regmap_config isl29018_regmap_config = { .reg_bits = 8, .val_bits = 8, - .volatile_reg = is_volatile_reg, + .volatile_reg = isl29018_is_volatile_reg, .max_register = ISL29018_REG_TEST, .num_reg_defaults_raw = ISL29018_REG_TEST + 1, .cache_type = REGCACHE_RBTREE, @@ -657,20 +657,20 @@ static const struct regmap_config isl29018_regmap_config = { static const struct regmap_config isl29035_regmap_config = { .reg_bits = 8, .val_bits = 8, - .volatile_reg = is_volatile_reg, + .volatile_reg = isl29018_is_volatile_reg, .max_register = ISL29035_REG_DEVICE_ID, .num_reg_defaults_raw = ISL29035_REG_DEVICE_ID + 1, .cache_type = REGCACHE_RBTREE, }; -struct chip_info { +struct isl29018_chip_info { const struct iio_chan_spec *channels; int num_channels; const struct iio_info *indio_info; const struct regmap_config *regmap_cfg; }; -static const struct chip_info chip_info_tbl[] = { +static const struct isl29018_chip_info isl29018_chip_info_tbl[] = { [isl29018] = { .channels = isl29018_channels, .num_channels = ARRAY_SIZE(isl29018_channels), @@ -739,7 +739,7 @@ static int isl29018_probe(struct i2c_client *client, chip->suspended = false; chip->regmap = devm_regmap_init_i2c(client, - chip_info_tbl[dev_id].regmap_cfg); + isl29018_chip_info_tbl[dev_id].regmap_cfg); if (IS_ERR(chip->regmap)) { err = PTR_ERR(chip->regmap); dev_err(&client->dev, "regmap initialization fails: %d\n", err); @@ -750,9 +750,9 @@ static int isl29018_probe(struct i2c_client *client, if (err) return err; - indio_dev->info = chip_info_tbl[dev_id].indio_info; - indio_dev->channels = chip_info_tbl[dev_id].channels; - indio_dev->num_channels = chip_info_tbl[dev_id].num_channels; + indio_dev->info = isl29018_chip_info_tbl[dev_id].indio_info; + indio_dev->channels = isl29018_chip_info_tbl[dev_id].channels; + indio_dev->num_channels = isl29018_chip_info_tbl[dev_id].num_channels; indio_dev->name = name; indio_dev->dev.parent = &client->dev; indio_dev->modes = INDIO_DIRECT_MODE; -- cgit v0.10.2 From 3a37f1c259f7150ea9a8896f165191ac7427126e Mon Sep 17 00:00:00 2001 From: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Date: Tue, 5 Jul 2016 13:55:41 +0200 Subject: staging: iio: isl29028: Prefix #defines and drop unused PROX_DRIVE Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/staging/iio/light/isl29028.c b/drivers/staging/iio/light/isl29028.c index 2e3b1d6..79f41ee 100644 --- a/drivers/staging/iio/light/isl29028.c +++ b/drivers/staging/iio/light/isl29028.c @@ -27,29 +27,27 @@ #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> -#define CONVERSION_TIME_MS 100 +#define ISL29028_CONV_TIME_MS 100 #define ISL29028_REG_CONFIGURE 0x01 -#define CONFIGURE_ALS_IR_MODE_ALS 0 -#define CONFIGURE_ALS_IR_MODE_IR BIT(0) -#define CONFIGURE_ALS_IR_MODE_MASK BIT(0) +#define ISL29028_CONF_ALS_IR_MODE_ALS 0 +#define ISL29028_CONF_ALS_IR_MODE_IR BIT(0) +#define ISL29028_CONF_ALS_IR_MODE_MASK BIT(0) -#define CONFIGURE_ALS_RANGE_LOW_LUX 0 -#define CONFIGURE_ALS_RANGE_HIGH_LUX BIT(1) -#define CONFIGURE_ALS_RANGE_MASK BIT(1) +#define ISL29028_CONF_ALS_RANGE_LOW_LUX 0 +#define ISL29028_CONF_ALS_RANGE_HIGH_LUX BIT(1) +#define ISL29028_CONF_ALS_RANGE_MASK BIT(1) -#define CONFIGURE_ALS_DIS 0 -#define CONFIGURE_ALS_EN BIT(2) -#define CONFIGURE_ALS_EN_MASK BIT(2) +#define ISL29028_CONF_ALS_DIS 0 +#define ISL29028_CONF_ALS_EN BIT(2) +#define ISL29028_CONF_ALS_EN_MASK BIT(2) -#define CONFIGURE_PROX_DRIVE BIT(3) +#define ISL29028_CONF_PROX_SLP_SH 4 +#define ISL29028_CONF_PROX_SLP_MASK (7 << ISL29028_CONF_PROX_SLP_SH) -#define CONFIGURE_PROX_SLP_SH 4 -#define CONFIGURE_PROX_SLP_MASK (7 << CONFIGURE_PROX_SLP_SH) - -#define CONFIGURE_PROX_EN BIT(7) -#define CONFIGURE_PROX_EN_MASK BIT(7) +#define ISL29028_CONF_PROX_EN BIT(7) +#define ISL29028_CONF_PROX_EN_MASK BIT(7) #define ISL29028_REG_INTERRUPT 0x02 @@ -91,7 +89,8 @@ static int isl29028_set_proxim_sampling(struct isl29028_chip *chip, break; } return regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, - CONFIGURE_PROX_SLP_MASK, sel << CONFIGURE_PROX_SLP_SH); + ISL29028_CONF_PROX_SLP_MASK, + sel << ISL29028_CONF_PROX_SLP_SH); } static int isl29028_enable_proximity(struct isl29028_chip *chip, bool enable) @@ -100,9 +99,9 @@ static int isl29028_enable_proximity(struct isl29028_chip *chip, bool enable) int val = 0; if (enable) - val = CONFIGURE_PROX_EN; + val = ISL29028_CONF_PROX_EN; ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, - CONFIGURE_PROX_EN_MASK, val); + ISL29028_CONF_PROX_EN_MASK, val); if (ret < 0) return ret; @@ -113,11 +112,11 @@ static int isl29028_enable_proximity(struct isl29028_chip *chip, bool enable) static int isl29028_set_als_scale(struct isl29028_chip *chip, int lux_scale) { - int val = (lux_scale == 2000) ? CONFIGURE_ALS_RANGE_HIGH_LUX : - CONFIGURE_ALS_RANGE_LOW_LUX; + int val = (lux_scale == 2000) ? ISL29028_CONF_ALS_RANGE_HIGH_LUX : + ISL29028_CONF_ALS_RANGE_LOW_LUX; return regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, - CONFIGURE_ALS_RANGE_MASK, val); + ISL29028_CONF_ALS_RANGE_MASK, val); } static int isl29028_set_als_ir_mode(struct isl29028_chip *chip, @@ -128,25 +127,25 @@ static int isl29028_set_als_ir_mode(struct isl29028_chip *chip, switch (mode) { case MODE_ALS: ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, - CONFIGURE_ALS_IR_MODE_MASK, - CONFIGURE_ALS_IR_MODE_ALS); + ISL29028_CONF_ALS_IR_MODE_MASK, + ISL29028_CONF_ALS_IR_MODE_ALS); if (ret < 0) return ret; ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, - CONFIGURE_ALS_RANGE_MASK, - CONFIGURE_ALS_RANGE_HIGH_LUX); + ISL29028_CONF_ALS_RANGE_MASK, + ISL29028_CONF_ALS_RANGE_HIGH_LUX); break; case MODE_IR: ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, - CONFIGURE_ALS_IR_MODE_MASK, - CONFIGURE_ALS_IR_MODE_IR); + ISL29028_CONF_ALS_IR_MODE_MASK, + ISL29028_CONF_ALS_IR_MODE_IR); break; case MODE_NONE: return regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, - CONFIGURE_ALS_EN_MASK, CONFIGURE_ALS_DIS); + ISL29028_CONF_ALS_EN_MASK, ISL29028_CONF_ALS_DIS); } if (ret < 0) @@ -154,12 +153,13 @@ static int isl29028_set_als_ir_mode(struct isl29028_chip *chip, /* Enable the ALS/IR */ ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, - CONFIGURE_ALS_EN_MASK, CONFIGURE_ALS_EN); + ISL29028_CONF_ALS_EN_MASK, + ISL29028_CONF_ALS_EN); if (ret < 0) return ret; /* Need to wait for conversion time if ALS/IR mode enabled */ - mdelay(CONVERSION_TIME_MS); + mdelay(ISL29028_CONV_TIME_MS); return 0; } -- cgit v0.10.2 From bafaa6debe9621f3afb305b6bd960d89e88eed8a Mon Sep 17 00:00:00 2001 From: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Date: Tue, 5 Jul 2016 13:55:42 +0200 Subject: staging: iio: isl29028: Prefix stuff Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/staging/iio/light/isl29028.c b/drivers/staging/iio/light/isl29028.c index 79f41ee..a73b632 100644 --- a/drivers/staging/iio/light/isl29028.c +++ b/drivers/staging/iio/light/isl29028.c @@ -60,10 +60,10 @@ #define ISL29028_NUM_REGS (ISL29028_REG_TEST2_MODE + 1) -enum als_ir_mode { - MODE_NONE = 0, - MODE_ALS, - MODE_IR +enum isl29028_als_ir_mode { + ISL29028_MODE_NONE = 0, + ISL29028_MODE_ALS, + ISL29028_MODE_IR, }; struct isl29028_chip { @@ -74,7 +74,7 @@ struct isl29028_chip { bool enable_prox; int lux_scale; - int als_ir_mode; + enum isl29028_als_ir_mode als_ir_mode; }; static int isl29028_set_proxim_sampling(struct isl29028_chip *chip, @@ -120,12 +120,12 @@ static int isl29028_set_als_scale(struct isl29028_chip *chip, int lux_scale) } static int isl29028_set_als_ir_mode(struct isl29028_chip *chip, - enum als_ir_mode mode) + enum isl29028_als_ir_mode mode) { int ret = 0; switch (mode) { - case MODE_ALS: + case ISL29028_MODE_ALS: ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, ISL29028_CONF_ALS_IR_MODE_MASK, ISL29028_CONF_ALS_IR_MODE_ALS); @@ -137,13 +137,13 @@ static int isl29028_set_als_ir_mode(struct isl29028_chip *chip, ISL29028_CONF_ALS_RANGE_HIGH_LUX); break; - case MODE_IR: + case ISL29028_MODE_IR: ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, ISL29028_CONF_ALS_IR_MODE_MASK, ISL29028_CONF_ALS_IR_MODE_IR); break; - case MODE_NONE: + case ISL29028_MODE_NONE: return regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, ISL29028_CONF_ALS_EN_MASK, ISL29028_CONF_ALS_DIS); } @@ -223,14 +223,14 @@ static int isl29028_als_get(struct isl29028_chip *chip, int *als_data) int ret; int als_ir_data; - if (chip->als_ir_mode != MODE_ALS) { - ret = isl29028_set_als_ir_mode(chip, MODE_ALS); + if (chip->als_ir_mode != ISL29028_MODE_ALS) { + ret = isl29028_set_als_ir_mode(chip, ISL29028_MODE_ALS); if (ret < 0) { dev_err(dev, "Error in enabling ALS mode err %d\n", ret); return ret; } - chip->als_ir_mode = MODE_ALS; + chip->als_ir_mode = ISL29028_MODE_ALS; } ret = isl29028_read_als_ir(chip, &als_ir_data); @@ -256,14 +256,14 @@ static int isl29028_ir_get(struct isl29028_chip *chip, int *ir_data) struct device *dev = regmap_get_device(chip->regmap); int ret; - if (chip->als_ir_mode != MODE_IR) { - ret = isl29028_set_als_ir_mode(chip, MODE_IR); + if (chip->als_ir_mode != ISL29028_MODE_IR) { + ret = isl29028_set_als_ir_mode(chip, ISL29028_MODE_IR); if (ret < 0) { dev_err(dev, "Error in enabling IR mode err %d\n", ret); return ret; } - chip->als_ir_mode = MODE_IR; + chip->als_ir_mode = ISL29028_MODE_IR; } return isl29028_read_als_ir(chip, ir_data); } @@ -428,7 +428,7 @@ static int isl29028_chip_init(struct isl29028_chip *chip) chip->enable_prox = false; chip->prox_sampling = 20; chip->lux_scale = 2000; - chip->als_ir_mode = MODE_NONE; + chip->als_ir_mode = ISL29028_MODE_NONE; ret = regmap_write(chip->regmap, ISL29028_REG_TEST1_MODE, 0x0); if (ret < 0) { -- cgit v0.10.2 From b9b689c12794bbe9605ff906da23a4e8a97ecebe Mon Sep 17 00:00:00 2001 From: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Date: Tue, 5 Jul 2016 13:55:43 +0200 Subject: staging: iio: isl29028: Expose scale and sample frequency available without comma Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/staging/iio/light/isl29028.c b/drivers/staging/iio/light/isl29028.c index a73b632..7358c3b 100644 --- a/drivers/staging/iio/light/isl29028.c +++ b/drivers/staging/iio/light/isl29028.c @@ -383,8 +383,8 @@ static int isl29028_read_raw(struct iio_dev *indio_dev, } static IIO_CONST_ATTR(in_proximity_sampling_frequency_available, - "1, 3, 5, 10, 13, 20, 83, 100"); -static IIO_CONST_ATTR(in_illuminance_scale_available, "125, 2000"); + "1 3 5 10 13 20 83 100"); +static IIO_CONST_ATTR(in_illuminance_scale_available, "125 2000"); #define ISL29028_DEV_ATTR(name) (&iio_dev_attr_##name.dev_attr.attr) #define ISL29028_CONST_ATTR(name) (&iio_const_attr_##name.dev_attr.attr) -- cgit v0.10.2 From f6127704320f70993a68abf6d17c89df461580a7 Mon Sep 17 00:00:00 2001 From: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Date: Tue, 5 Jul 2016 13:55:44 +0200 Subject: staging: iio: isl29028: Prefix functions Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/staging/iio/light/isl29028.c b/drivers/staging/iio/light/isl29028.c index 7358c3b..a238b16 100644 --- a/drivers/staging/iio/light/isl29028.c +++ b/drivers/staging/iio/light/isl29028.c @@ -462,7 +462,7 @@ static int isl29028_chip_init(struct isl29028_chip *chip) return ret; } -static bool is_volatile_reg(struct device *dev, unsigned int reg) +static bool isl29028_is_volatile_reg(struct device *dev, unsigned int reg) { switch (reg) { case ISL29028_REG_INTERRUPT: @@ -478,7 +478,7 @@ static bool is_volatile_reg(struct device *dev, unsigned int reg) static const struct regmap_config isl29028_regmap_config = { .reg_bits = 8, .val_bits = 8, - .volatile_reg = is_volatile_reg, + .volatile_reg = isl29028_is_volatile_reg, .max_register = ISL29028_NUM_REGS - 1, .num_reg_defaults_raw = ISL29028_NUM_REGS, .cache_type = REGCACHE_RBTREE, -- cgit v0.10.2 From 9d9d3777a9db5c0773d270e51b65c1252856d95e Mon Sep 17 00:00:00 2001 From: Alexandre Bailon <abailon@baylibre.com> Date: Thu, 7 Jul 2016 07:41:00 -0500 Subject: greybus: es2: Add a new bulk in endpoint for APBridgeA RPC Add a new bulk in endpoint in order to get RPC status from APbridgeA without to have to poll on control endpoint. So the new endpoint layout is: EP0: control EP EP1 and EP2: muxed endpoints (bulk in and out) EP3 to EP14: direct muxed endpoints (bulk in and out) EP15: ARPC bulk in endpoint Note: This patch is allocating ARPC URBs but does nothing with them. The following patch will use them. Testing Done: Tested with an APBridgeA enumerating 16 endpoints. Kernel doesn't print Not enough endpoints found in device, aborting! Signed-off-by: Alexandre Bailon <abailon@baylibre.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 5bdf2e1..8ebbd70 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -25,6 +25,9 @@ /* Memory sizes for the buffers sent to/from the ES2 controller */ #define ES2_GBUF_MSG_SIZE_MAX 2048 +/* Memory sizes for the ARPC buffers */ +#define ARPC_IN_SIZE_MAX 128 + static const struct usb_device_id id_table[] = { { USB_DEVICE(0x18d1, 0x1eaf) }, { }, @@ -36,6 +39,12 @@ MODULE_DEVICE_TABLE(usb, id_table); /* Number of bulk in and bulk out couple */ #define NUM_BULKS 7 +/* Expected number of bulk out endpoints */ +#define NUM_BULKS_OUT NUM_BULKS + +/* Expected number of bulk in endpoints (including ARPC endpoint) */ +#define NUM_BULKS_IN (NUM_BULKS + 1) + /* * Number of CPort IN urbs in flight at any point in time. * Adjust if we are having stalls in the USB buffer due to not enough urbs in @@ -49,6 +58,11 @@ MODULE_DEVICE_TABLE(usb, id_table); #define NUM_CPORT_OUT_URB (8 * NUM_BULKS) /* + * Number of ARPC in urbs in flight at any point in time. + */ +#define NUM_ARPC_IN_URB 2 + +/* * @endpoint: bulk in endpoint for CPort data * @urb: array of urbs for the CPort in messages * @buffer: array of buffers for the @cport_in_urb urbs @@ -85,6 +99,9 @@ struct es2_cport_out { * @apb_log_dentry: file system entry for the log file interface * @apb_log_enable_dentry: file system entry for enabling logging * @apb_log_fifo: kernel FIFO to carry logged data + * @arpc_urb: array of urbs for the ARPC in messages + * @arpc_buffer: array of buffers for the @arpc_urb urbs + * @arpc_endpoint_in: bulk in endpoint for APBridgeA RPC */ struct es2_ap_dev { struct usb_device *usb_dev; @@ -106,6 +123,10 @@ struct es2_ap_dev { struct dentry *apb_log_dentry; struct dentry *apb_log_enable_dentry; DECLARE_KFIFO(apb_log_fifo, char, APB1_LOG_SIZE); + + __u8 arpc_endpoint_in; + struct urb *arpc_urb[NUM_ARPC_IN_URB]; + u8 *arpc_buffer[NUM_ARPC_IN_URB]; }; /** @@ -344,6 +365,45 @@ static void es2_cport_in_disable(struct es2_ap_dev *es2, } } +static int es2_arpc_in_enable(struct es2_ap_dev *es2) +{ + struct urb *urb; + int ret; + int i; + + for (i = 0; i < NUM_ARPC_IN_URB; ++i) { + urb = es2->arpc_urb[i]; + + ret = usb_submit_urb(urb, GFP_KERNEL); + if (ret) { + dev_err(&es2->usb_dev->dev, + "failed to submit arpc in-urb: %d\n", ret); + goto err_kill_urbs; + } + } + + return 0; + +err_kill_urbs: + for (--i; i >= 0; --i) { + urb = es2->arpc_urb[i]; + usb_kill_urb(urb); + } + + return ret; +} + +static void es2_arpc_in_disable(struct es2_ap_dev *es2) +{ + struct urb *urb; + int i; + + for (i = 0; i < NUM_ARPC_IN_URB; ++i) { + urb = es2->arpc_urb[i]; + usb_kill_urb(urb); + } +} + static struct urb *next_free_urb(struct es2_ap_dev *es2, gfp_t gfp_mask) { struct urb *urb = NULL; @@ -899,6 +959,16 @@ static void es2_destroy(struct es2_ap_dev *es2) es2->cport_out_urb_busy[i] = false; /* just to be anal */ } + for (i = 0; i < NUM_ARPC_IN_URB; ++i) { + struct urb *urb = es2->arpc_urb[i]; + + if (!urb) + break; + usb_free_urb(urb); + kfree(es2->arpc_buffer[i]); + es2->arpc_buffer[i] = NULL; + } + for (bulk_in = 0; bulk_in < NUM_BULKS; bulk_in++) { struct es2_cport_in *cport_in = &es2->cport_in[bulk_in]; @@ -991,6 +1061,31 @@ static void cport_out_callback(struct urb *urb) free_urb(es2, urb); } +static void arpc_in_callback(struct urb *urb) +{ + struct device *dev = &urb->dev->dev; + int status = check_urb_status(urb); + int retval; + + if (status) { + if ((status == -EAGAIN) || (status == -EPROTO)) + goto exit; + + /* The urb is being unlinked */ + if (status == -ENOENT || status == -ESHUTDOWN) + return; + + dev_err(dev, "arpc in-urb error %d (dropped)\n", status); + return; + } + +exit: + /* put our urb back in the request pool */ + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) + dev_err(dev, "failed to resubmit arpc in-urb: %d\n", retval); +} + #define APB1_LOG_MSG_SIZE 64 static void apb_log_get(struct es2_ap_dev *es2, char *buf) { @@ -1225,8 +1320,13 @@ static int ap_probe(struct usb_interface *interface, endpoint = &iface_desc->endpoint[i].desc; if (usb_endpoint_is_bulk_in(endpoint)) { - es2->cport_in[bulk_in++].endpoint = - endpoint->bEndpointAddress; + if (bulk_in < NUM_BULKS) + es2->cport_in[bulk_in].endpoint = + endpoint->bEndpointAddress; + else + es2->arpc_endpoint_in = + endpoint->bEndpointAddress; + bulk_in++; } else if (usb_endpoint_is_bulk_out(endpoint)) { es2->cport_out[bulk_out++].endpoint = endpoint->bEndpointAddress; @@ -1236,7 +1336,7 @@ static int ap_probe(struct usb_interface *interface, endpoint->bEndpointAddress); } } - if (bulk_in != NUM_BULKS || bulk_out != NUM_BULKS) { + if (bulk_in != NUM_BULKS_IN || bulk_out != NUM_BULKS_OUT) { dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n"); retval = -ENODEV; goto error; @@ -1271,6 +1371,32 @@ static int ap_probe(struct usb_interface *interface, } } + /* Allocate buffers for ARPC in messages */ + for (i = 0; i < NUM_ARPC_IN_URB; ++i) { + struct urb *urb; + u8 *buffer; + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + retval = -ENOMEM; + goto error; + } + buffer = kmalloc(ARPC_IN_SIZE_MAX, GFP_KERNEL); + if (!buffer) { + retval = -ENOMEM; + goto error; + } + + usb_fill_bulk_urb(urb, udev, + usb_rcvbulkpipe(udev, + es2->arpc_endpoint_in), + buffer, ARPC_IN_SIZE_MAX, + arpc_in_callback, es2); + + es2->arpc_urb[i] = urb; + es2->arpc_buffer[i] = buffer; + } + /* Allocate urbs for our CPort OUT messages */ for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { struct urb *urb; @@ -1291,9 +1417,12 @@ static int ap_probe(struct usb_interface *interface, gb_debugfs_get(), es2, &apb_log_enable_fops); + if (es2_arpc_in_enable(es2)) + goto error; + retval = gb_hd_add(hd); if (retval) - goto error; + goto err_disable_arpc_in; for (i = 0; i < NUM_BULKS; ++i) { retval = es2_cport_in_enable(es2, &es2->cport_in[i]); @@ -1307,6 +1436,8 @@ err_disable_cport_in: for (--i; i >= 0; --i) es2_cport_in_disable(es2, &es2->cport_in[i]); gb_hd_del(hd); +err_disable_arpc_in: + es2_arpc_in_disable(es2); error: es2_destroy(es2); @@ -1322,6 +1453,7 @@ static void ap_disconnect(struct usb_interface *interface) for (i = 0; i < NUM_BULKS; ++i) es2_cport_in_disable(es2, &es2->cport_in[i]); + es2_arpc_in_disable(es2); es2_destroy(es2); } -- cgit v0.10.2 From c14118a8411c4d7ad1dd6dd501beb33ae1268b08 Mon Sep 17 00:00:00 2001 From: Alexandre Bailon <abailon@baylibre.com> Date: Thu, 7 Jul 2016 07:41:00 -0500 Subject: greybus: es2: Implement APBridgeA RPC (ARPC) Implement ARPC. In first time, we are going to use it to implement new request but the goal is to update all existing vendor request to use ARPC. In addition, Convert the current USB Vendor request for CPort Reset to ARPC so that we can be sure that the port has been fully reset by the time the request completes. Testing Done: AP can reset APBA Cports by using the ARPC command. In addition, tested with a hacked firmware that cause error during the Cport reset, and Greybus printed the error "failed to reset cport". Signed-off-by: Alexandre Bailon <abailon@baylibre.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 8ebbd70..b763b27 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -11,6 +11,7 @@ #include <linux/usb.h> #include <linux/kfifo.h> #include <linux/debugfs.h> +#include <linux/list.h> #include <asm/unaligned.h> #include "greybus.h" @@ -26,6 +27,7 @@ #define ES2_GBUF_MSG_SIZE_MAX 2048 /* Memory sizes for the ARPC buffers */ +#define ARPC_OUT_SIZE_MAX U16_MAX #define ARPC_IN_SIZE_MAX 128 static const struct usb_device_id id_table[] = { @@ -102,6 +104,9 @@ struct es2_cport_out { * @arpc_urb: array of urbs for the ARPC in messages * @arpc_buffer: array of buffers for the @arpc_urb urbs * @arpc_endpoint_in: bulk in endpoint for APBridgeA RPC + * @arpc_id_cycle: gives an unique id to ARPC + * @arpc_lock: locks ARPC list + * @arpcs: list of in progress ARPCs */ struct es2_ap_dev { struct usb_device *usb_dev; @@ -127,6 +132,10 @@ struct es2_ap_dev { __u8 arpc_endpoint_in; struct urb *arpc_urb[NUM_ARPC_IN_URB]; u8 *arpc_buffer[NUM_ARPC_IN_URB]; + + int arpc_id_cycle; + spinlock_t arpc_lock; + struct list_head arpcs; }; /** @@ -164,6 +173,14 @@ struct timesync_authoritative_request { __le64 frame_time[GB_TIMESYNC_MAX_STROBES]; } __packed; +struct arpc { + struct list_head list; + struct arpc_request_message *req; + struct arpc_response_message *resp; + struct completion response_received; + bool active; +}; + static inline struct es2_ap_dev *hd_to_es2(struct gb_host_device *hd) { return (struct es2_ap_dev *)&hd->hd_priv; @@ -172,6 +189,8 @@ static inline struct es2_ap_dev *hd_to_es2(struct gb_host_device *hd) static void cport_out_callback(struct urb *urb); static void usb_log_enable(struct es2_ap_dev *es2); static void usb_log_disable(struct es2_ap_dev *es2); +static int arpc_sync(struct es2_ap_dev *es2, u8 type, void *payload, + size_t size, int *result, unsigned int timeout); /* Get the endpoints pair mapped to the cport */ static int cport_to_ep_pair(struct es2_ap_dev *es2, u16 cport_id) @@ -590,7 +609,9 @@ static int cport_reset(struct gb_host_device *hd, u16 cport_id) { struct es2_ap_dev *es2 = hd_to_es2(hd); struct usb_device *udev = es2->usb_dev; + struct arpc_cport_reset req; int retval; + int result; switch (cport_id) { case GB_SVC_CPORT_ID: @@ -599,18 +620,15 @@ static int cport_reset(struct gb_host_device *hd, u16 cport_id) return 0; } - retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - GB_APB_REQUEST_RESET_CPORT, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_INTERFACE, cport_id, 0, - NULL, 0, ES2_TIMEOUT); - if (retval < 0) { + req.cport_id = cpu_to_le16(cport_id); + retval = arpc_sync(es2, ARPC_CPORT_RESET, &req, sizeof(req), + &result, ES2_TIMEOUT); + if (retval == -EREMOTEIO) { dev_err(&udev->dev, "failed to reset cport %u: %d\n", cport_id, - retval); - return retval; + result); } - return 0; + return retval; } static int es2_cport_allocate(struct gb_host_device *hd, int cport_id, @@ -1061,10 +1079,154 @@ static void cport_out_callback(struct urb *urb) free_urb(es2, urb); } +static struct arpc *arpc_alloc(void *payload, u16 size, u8 type) +{ + struct arpc *rpc; + + if (size + sizeof(*rpc->req) > ARPC_OUT_SIZE_MAX) + return NULL; + + rpc = kzalloc(sizeof(*rpc), GFP_KERNEL); + if (!rpc) + return NULL; + + INIT_LIST_HEAD(&rpc->list); + rpc->req = kzalloc(sizeof(*rpc->req) + size, GFP_KERNEL); + if (!rpc->req) + goto err_free_rpc; + + rpc->resp = kzalloc(sizeof(*rpc->resp), GFP_KERNEL); + if (!rpc->req) + goto err_free_req; + + rpc->req->type = type; + rpc->req->size = cpu_to_le16(sizeof(rpc->req) + size); + memcpy(rpc->req->data, payload, size); + + init_completion(&rpc->response_received); + + return rpc; + +err_free_req: + kfree(rpc->req); +err_free_rpc: + kfree(rpc); + + return NULL; +} + +static void arpc_free(struct arpc *rpc) +{ + kfree(rpc->req); + kfree(rpc->resp); + kfree(rpc); +} + +static struct arpc *arpc_find(struct es2_ap_dev *es2, u8 id) +{ + struct arpc *rpc; + + list_for_each_entry(rpc, &es2->arpcs, list) { + if (rpc->req->id == id) + return rpc; + } + + return NULL; +} + +static void arpc_add(struct es2_ap_dev *es2, struct arpc *rpc) +{ + rpc->active = true; + rpc->req->id = (u16)(es2->arpc_id_cycle++); + list_add_tail(&es2->arpcs, &rpc->list); +} + +static void arpc_del(struct es2_ap_dev *es2, struct arpc *rpc) +{ + if (rpc->active) { + rpc->active = false; + list_del(&rpc->list); + } +} + +static int arpc_send(struct es2_ap_dev *es2, struct arpc *rpc, int timeout) +{ + struct usb_device *udev = es2->usb_dev; + int retval; + + retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + APBA_REQUEST_ARPC_RUN, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, + 0, 0, + rpc->req, rpc->req->size, + ES2_TIMEOUT); + if (retval != rpc->req->size) { + dev_err(&udev->dev, + "failed to send ARPC request %d: %d\n", + rpc->req->type, retval); + if (retval > 0) + retval = -EIO; + return retval; + } + + return 0; +} + +static int arpc_sync(struct es2_ap_dev *es2, u8 type, void *payload, + size_t size, int *result, unsigned int timeout) +{ + struct arpc *rpc; + unsigned long flags; + int retval; + + rpc = arpc_alloc(payload, size, type); + if (!rpc) + return -ENOMEM; + + spin_lock_irqsave(&es2->arpc_lock, flags); + arpc_add(es2, rpc); + spin_unlock_irqrestore(&es2->arpc_lock, flags); + + retval = arpc_send(es2, rpc, timeout); + if (retval) + goto out_arpc_del; + + retval = wait_for_completion_interruptible_timeout( + &rpc->response_received, + msecs_to_jiffies(timeout)); + if (retval <= 0) { + if (!retval) + retval = -ETIMEDOUT; + goto out_arpc_del; + } + + *result = rpc->resp->result; + if (*result) + retval = -EREMOTEIO; + +out_arpc_del: + spin_lock_irqsave(&es2->arpc_lock, flags); + arpc_del(es2, rpc); + spin_unlock_irqrestore(&es2->arpc_lock, flags); + arpc_free(rpc); + + if (retval < 0 && retval != -EREMOTEIO) { + dev_err(&es2->usb_dev->dev, + "failed to execute ARPC: %d\n", retval); + } + + return retval; +} + static void arpc_in_callback(struct urb *urb) { + struct es2_ap_dev *es2 = urb->context; struct device *dev = &urb->dev->dev; int status = check_urb_status(urb); + struct arpc *rpc; + struct arpc_response_message *resp; + unsigned long flags; int retval; if (status) { @@ -1079,6 +1241,26 @@ static void arpc_in_callback(struct urb *urb) return; } + if (urb->actual_length < sizeof(*resp)) { + dev_err(dev, "short aprc response received\n"); + goto exit; + } + + resp = urb->transfer_buffer; + spin_lock_irqsave(&es2->arpc_lock, flags); + rpc = arpc_find(es2, resp->id); + if (!rpc) { + dev_err(dev, "invalid arpc response id received: %d\n", + resp->id); + spin_unlock_irqrestore(&es2->arpc_lock, flags); + goto exit; + } + + arpc_del(es2, rpc); + memcpy(rpc->resp, resp, sizeof(*resp)); + complete(&rpc->response_received); + spin_unlock_irqrestore(&es2->arpc_lock, flags); + exit: /* put our urb back in the request pool */ retval = usb_submit_urb(urb, GFP_ATOMIC); @@ -1417,6 +1599,9 @@ static int ap_probe(struct usb_interface *interface, gb_debugfs_get(), es2, &apb_log_enable_fops); + INIT_LIST_HEAD(&es2->arpcs); + spin_lock_init(&es2->arpc_lock); + if (es2_arpc_in_enable(es2)) goto error; diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 1a12531..e9f3d2c 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -268,12 +268,44 @@ struct gb_control_intf_pm_response { /* requests to set Greybus CPort flags */ #define GB_APB_REQUEST_CPORT_FLAGS 0x11 +/* ARPC command */ +#define APBA_REQUEST_ARPC_RUN 0x12 + struct gb_apb_request_cport_flags { u32 flags; #define GB_APB_CPORT_FLAG_CONTROL 0x01 #define GB_APB_CPORT_FLAG_HIGH_PRIO 0x02 } __packed; +/* APBridgeA RPC (ARPC) */ + +enum arpc_result { + ARPC_SUCCESS = 0x00, + ARPC_NO_MEMORY = 0x01, + ARPC_INVALID = 0x02, + ARPC_TIMEOUT = 0x03, + ARPC_UNKNOWN_ERROR = 0xff, +}; + +/* ARPC request */ +struct arpc_request_message { + __le16 id; /* RPC unique id */ + __le16 size; /* Size in bytes of header + payload */ + __u8 type; /* RPC type */ + __u8 data[0]; /* ARPC data */ +} __packed; + +/* ARPC response */ +struct arpc_response_message { + __le16 id; /* RPC unique id */ + __u8 result; /* Result of RPC */ +} __packed; + +#define ARPC_CPORT_RESET 0x00 + +struct arpc_cport_reset { + __le16 cport_id; +} __packed; /* Firmware Download Protocol */ -- cgit v0.10.2 From 34873949885ad66f9bc6ad6baff78aed4846c092 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 13 Jul 2016 09:34:00 -0500 Subject: greybus: es2: fix arpc return value ARPC should return 0 on success, but instead was returning the number of jiffies left until the timeout. This caused cport_reset() to report an error and an incorrect error message to be printed when disabling a connection. Reported-by: Alex Elder <elder@linaro.org> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Tested-by: Alex Elder <elder@linaro.org> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index b763b27..6ada1ee 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -1204,6 +1204,8 @@ static int arpc_sync(struct es2_ap_dev *es2, u8 type, void *payload, *result = rpc->resp->result; if (*result) retval = -EREMOTEIO; + else + retval = 0; out_arpc_del: spin_lock_irqsave(&es2->arpc_lock, flags); -- cgit v0.10.2 From cf1caac6cd7c1fa25de304925f6b239380797a46 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Tue, 12 Jul 2016 04:56:00 -0500 Subject: greybus: audio: Fix incorrect codec state modification In case module is removed dynamically with ongoing playback, during module cleanup codec state is mistakenly modified. State should be modified for module only. Fix this. Fixes: 76414cb499b7 ("audio: Use single codec driver registration") Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 3c5a5ae..5e05375 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -971,7 +971,7 @@ static void gbaudio_codec_cleanup(struct gbaudio_module_info *module) ret = gb_audio_apbridgea_unregister_cport(data->connection, i2s_port, cportid, AUDIO_APBRIDGEA_DIRECTION_TX); - gbcodec->stream[0].state = GBAUDIO_CODEC_SHUTDOWN; + module->ctrlstate[0] = GBAUDIO_CODEC_SHUTDOWN; } if (cap_state == GBAUDIO_CODEC_START) { @@ -996,7 +996,7 @@ static void gbaudio_codec_cleanup(struct gbaudio_module_info *module) ret = gb_audio_apbridgea_unregister_cport(data->connection, i2s_port, cportid, AUDIO_APBRIDGEA_DIRECTION_RX); - gbcodec->stream[1].state = GBAUDIO_CODEC_SHUTDOWN; + module->ctrlstate[1] = GBAUDIO_CODEC_SHUTDOWN; } } -- cgit v0.10.2 From 12ce523147e485fc605599f7ec94fbbc6be0fc01 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Tue, 12 Jul 2016 04:56:00 -0500 Subject: greybus: audio: Maintain proper codec state during shutdown sequence. During shutdown sequence, in case all modules are already removed, codec state is not updated. Though it's not causing any harm for now, but it's good to maintain proper codec state. Fix this. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 5e05375..9c7bec7 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -460,6 +460,8 @@ static void gbcodec_shutdown(struct snd_pcm_substream *substream, if (list_empty(&codec->module_list)) { dev_err(codec->dev, "No codec module available\n"); + codec->stream[substream->stream].state = GBAUDIO_CODEC_SHUTDOWN; + codec->stream[substream->stream].dai_name = NULL; mutex_unlock(&codec->lock); pm_relax(dai->dev); return; @@ -733,8 +735,14 @@ static int gbcodec_mute_stream(struct snd_soc_dai *dai, int mute, int stream) mutex_lock(&codec->lock); if (list_empty(&codec->module_list)) { dev_err(codec->dev, "No codec module available\n"); + if (mute) { + codec->stream[stream].state = GBAUDIO_CODEC_STOP; + ret = 0; + } else { + ret = -ENODEV; + } mutex_unlock(&codec->lock); - return -ENODEV; + return ret; } list_for_each_entry(module, &codec->module_list, list) { -- cgit v0.10.2 From e818027c0b4e2573e2e63ca04480ce7972596eb2 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 14 Jul 2016 12:18:00 -0500 Subject: greybus: es2: Fix 'make check' warnings with arpc This is what I got: greybus/es2.c:1130:29: warning: restricted __le16 degrades to integer greybus/es2.c:1140:22: warning: incorrect type in assignment (different base types) greybus/es2.c:1140:22: expected restricted __le16 [usertype] id greybus/es2.c:1140:22: got unsigned short [unsigned] [usertype] <noident> greybus/es2.c:1162:52: warning: incorrect type in argument 8 (different base types) greybus/es2.c:1162:52: expected unsigned short [unsigned] [usertype] size greybus/es2.c:1162:52: got restricted __le16 [usertype] size greybus/es2.c:1164:31: warning: restricted __le16 degrades to integer greybus/es2.c:1253:34: warning: incorrect type in argument 2 (different base types) greybus/es2.c:1253:34: expected unsigned char [unsigned] [usertype] id greybus/es2.c:1253:34: got restricted __le16 [usertype] id Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 6ada1ee..7c294c4 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -1127,7 +1127,7 @@ static struct arpc *arpc_find(struct es2_ap_dev *es2, u8 id) struct arpc *rpc; list_for_each_entry(rpc, &es2->arpcs, list) { - if (rpc->req->id == id) + if (le16_to_cpu(rpc->req->id) == id) return rpc; } @@ -1137,7 +1137,7 @@ static struct arpc *arpc_find(struct es2_ap_dev *es2, u8 id) static void arpc_add(struct es2_ap_dev *es2, struct arpc *rpc) { rpc->active = true; - rpc->req->id = (u16)(es2->arpc_id_cycle++); + rpc->req->id = cpu_to_le16(es2->arpc_id_cycle++); list_add_tail(&es2->arpcs, &rpc->list); } @@ -1159,9 +1159,9 @@ static int arpc_send(struct es2_ap_dev *es2, struct arpc *rpc, int timeout) USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0, 0, - rpc->req, rpc->req->size, + rpc->req, le16_to_cpu(rpc->req->size), ES2_TIMEOUT); - if (retval != rpc->req->size) { + if (retval != le16_to_cpu(rpc->req->size)) { dev_err(&udev->dev, "failed to send ARPC request %d: %d\n", rpc->req->type, retval); @@ -1250,7 +1250,7 @@ static void arpc_in_callback(struct urb *urb) resp = urb->transfer_buffer; spin_lock_irqsave(&es2->arpc_lock, flags); - rpc = arpc_find(es2, resp->id); + rpc = arpc_find(es2, le16_to_cpu(resp->id)); if (!rpc) { dev_err(dev, "invalid arpc response id received: %d\n", resp->id); -- cgit v0.10.2 From 165a74ab1401ac3e2b6eb5b7084607b588734e09 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Thu, 14 Jul 2016 12:55:00 -0500 Subject: greybus: es2: fix arpc response lookups Fix arpc response lookups that were truncating the 16-bit response id to 8-bit, something which would have lead to all arpc calls timing out after the 256th request. Testing done: Enumerated and ejected a module on EVT2. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 7c294c4..7961622 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -1122,12 +1122,12 @@ static void arpc_free(struct arpc *rpc) kfree(rpc); } -static struct arpc *arpc_find(struct es2_ap_dev *es2, u8 id) +static struct arpc *arpc_find(struct es2_ap_dev *es2, __le16 id) { struct arpc *rpc; list_for_each_entry(rpc, &es2->arpcs, list) { - if (le16_to_cpu(rpc->req->id) == id) + if (rpc->req->id == id) return rpc; } @@ -1250,7 +1250,7 @@ static void arpc_in_callback(struct urb *urb) resp = urb->transfer_buffer; spin_lock_irqsave(&es2->arpc_lock, flags); - rpc = arpc_find(es2, le16_to_cpu(resp->id)); + rpc = arpc_find(es2, resp->id); if (!rpc) { dev_err(dev, "invalid arpc response id received: %d\n", resp->id); -- cgit v0.10.2 From 2d48b5b4a8ca12aeff6551796357add7c05ce8cf Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Thu, 14 Jul 2016 15:13:00 -0500 Subject: greybus: bundle: add activate and deactivate AP shall send the Bundle Activate Operation to power on a bundle, and send the Bundle Deactivate Request after closing all the associated connections for power down. Testing Done: - Check for the return code of the bundle activate and deactivate operation sent Signed-off-by: David Lin <dtwlin@google.com> Signed-off-by: Axel Haslam <ahaslam@baylibre.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index dacc49c..ca3bad9 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -162,6 +162,13 @@ static int greybus_probe(struct device *dev) if (!id) return -ENODEV; + /* + * FIXME: We need to perform error handling on bundle activate call + * below when firmware is ready. We just allow the activate operation to + * fail for now since bundle may be in active already. + */ + gb_control_bundle_activate(bundle->intf->control, bundle->id); + retval = driver->probe(bundle, id); if (retval) { /* @@ -169,6 +176,8 @@ static int greybus_probe(struct device *dev) */ WARN_ON(!list_empty(&bundle->connections)); + gb_control_bundle_deactivate(bundle->intf->control, bundle->id); + return retval; } @@ -203,6 +212,9 @@ static int greybus_remove(struct device *dev) /* Catch buggy drivers that fail to destroy their connections. */ WARN_ON(!list_empty(&bundle->connections)); + if (!bundle->intf->disconnected) + gb_control_bundle_deactivate(bundle->intf->control, bundle->id); + return 0; } -- cgit v0.10.2 From 30a3bf7b30d86b94ad4fbdcf9cdce1dcf5037c58 Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Thu, 14 Jul 2016 15:13:00 -0500 Subject: greybus: interface: add runtime pm support Configure and enable runtime pm support for the Interface. Refer to the 12.2. The Interface Lifecycle of the Greybus specification for details on the requirements for transitioning from ENUMERATED to SUSPEND and vice versa. All the Bundles for the Interface have to be either OFF or SUSPENDED before the Interface can be autosuspended. Testing Done: - Check the runtime_status of an interface driver and validate the suspend current of a module. Signed-off-by: David Lin <dtwlin@google.com> Signed-off-by: Axel Haslam <ahaslam@baylibre.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index dbc9be0..3e32028 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -18,6 +18,7 @@ #include <linux/slab.h> #include <linux/device.h> #include <linux/module.h> +#include <linux/pm_runtime.h> #include <linux/idr.h> #include "kernel_ver.h" diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index e7efc54..16e268f 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -7,6 +7,8 @@ * Released under the GPLv2 only. */ +#include <linux/delay.h> + #include "greybus.h" #include "greybus_trace.h" @@ -14,6 +16,11 @@ #define GB_INTERFACE_DEVICE_ID_BAD 0xff +#define GB_INTERFACE_AUTOSUSPEND_MS 3000 + +/* Time required for interface to enter standby before disabling REFCLK */ +#define GB_INTERFACE_SUSPEND_HIBERNATE_DELAY_MS 20 + /* Don't-care selector index */ #define DME_SELECTOR_INDEX_NULL 0 @@ -36,6 +43,8 @@ #define TOSHIBA_ES3_APBRIDGE_DPID 0x1001 #define TOSHIBA_ES3_GBPHY_DPID 0x1002 +static int gb_interface_hibernate_link(struct gb_interface *intf); +static int gb_interface_refclk_set(struct gb_interface *intf, bool enable); static int gb_interface_dme_attr_get(struct gb_interface *intf, u16 attr, u32 *val) @@ -505,9 +514,92 @@ static void gb_interface_release(struct device *dev) kfree(intf); } +#ifdef CONFIG_PM_RUNTIME +static int gb_interface_suspend(struct device *dev) +{ + struct gb_interface *intf = to_gb_interface(dev); + int ret, timesync_ret; + + ret = gb_control_interface_suspend_prepare(intf->control); + if (ret) + return ret; + + gb_timesync_interface_remove(intf); + + ret = gb_control_suspend(intf->control); + if (ret) + goto err_hibernate_abort; + + ret = gb_interface_hibernate_link(intf); + if (ret) + return ret; + + /* Delay to allow interface to enter standby before disabling refclk */ + msleep(GB_INTERFACE_SUSPEND_HIBERNATE_DELAY_MS); + + ret = gb_interface_refclk_set(intf, false); + if (ret) + return ret; + + return 0; + +err_hibernate_abort: + gb_control_interface_hibernate_abort(intf->control); + + timesync_ret = gb_timesync_interface_add(intf); + if (timesync_ret) { + dev_err(dev, "failed to add to timesync: %d\n", timesync_ret); + return timesync_ret; + } + + return ret; +} + +static int gb_interface_resume(struct device *dev) +{ + struct gb_interface *intf = to_gb_interface(dev); + struct gb_svc *svc = intf->hd->svc; + int ret; + + ret = gb_interface_refclk_set(intf, true); + if (ret) + return ret; + + ret = gb_svc_intf_resume(svc, intf->interface_id); + if (ret) + return ret; + + ret = gb_control_resume(intf->control); + if (ret) + return ret; + + ret = gb_timesync_interface_add(intf); + if (ret) { + dev_err(dev, "failed to add to timesync: %d\n", ret); + return ret; + } + + return 0; +} + +static int gb_interface_runtime_idle(struct device *dev) +{ + pm_runtime_mark_last_busy(dev); + pm_request_autosuspend(dev); + + return 0; +} +#endif + +static const struct dev_pm_ops gb_interface_pm_ops = { + SET_RUNTIME_PM_OPS(gb_interface_suspend, gb_interface_resume, + gb_interface_runtime_idle) +}; + struct device_type greybus_interface_type = { .name = "greybus_interface", .release = gb_interface_release, + .pm = &gb_interface_pm_ops, }; /* @@ -553,6 +645,9 @@ struct gb_interface *gb_interface_create(struct gb_module *module, dev_set_name(&intf->dev, "%s.%u", dev_name(&module->dev), interface_id); + pm_runtime_set_autosuspend_delay(&intf->dev, + GB_INTERFACE_AUTOSUSPEND_MS); + trace_gb_interface_create(intf); return intf; @@ -809,6 +904,11 @@ int gb_interface_enable(struct gb_interface *intf) goto err_destroy_bundles; } + pm_runtime_use_autosuspend(&intf->dev); + pm_runtime_get_noresume(&intf->dev); + pm_runtime_set_active(&intf->dev); + pm_runtime_enable(&intf->dev); + list_for_each_entry_safe_reverse(bundle, tmp, &intf->bundles, links) { ret = gb_bundle_add(bundle); if (ret) { @@ -821,6 +921,8 @@ int gb_interface_enable(struct gb_interface *intf) intf->enabled = true; + pm_runtime_put(&intf->dev); + trace_gb_interface_enable(intf); return 0; @@ -854,6 +956,8 @@ void gb_interface_disable(struct gb_interface *intf) trace_gb_interface_disable(intf); + pm_runtime_get_sync(&intf->dev); + /* Set disconnected flag to avoid I/O during connection tear down. */ if (intf->quirks & GB_INTERFACE_QUIRK_FORCED_DISABLE) intf->disconnected = true; @@ -871,6 +975,11 @@ void gb_interface_disable(struct gb_interface *intf) intf->control = NULL; intf->enabled = false; + + pm_runtime_disable(&intf->dev); + pm_runtime_set_suspended(&intf->dev); + pm_runtime_dont_use_autosuspend(&intf->dev); + pm_runtime_put_noidle(&intf->dev); } /* Enable TimeSync on an Interface control connection. */ diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index 80ed27c..84beb2f 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -389,4 +389,17 @@ static inline int kstrtobool(const char *s, bool *res) } #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) +/* + * After commit b2b49ccbdd54 (PM: Kconfig: Set PM_RUNTIME if PM_SLEEP is + * selected) PM_RUNTIME is always set if PM is set, so files that are build + * conditionally if CONFIG_PM_RUNTIME is set may now be build if CONFIG_PM is + * set. + */ + +#ifdef CONFIG_PM +#define CONFIG_PM_RUNTIME +#endif /* CONFIG_PM */ +#endif + #endif /* __GREYBUS_KERNEL_VER_H */ -- cgit v0.10.2 From 61e13db9cc8945d53f72d4021594ee3be214e667 Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Thu, 14 Jul 2016 15:13:00 -0500 Subject: greybus: bundle: add runtime pm support This patch adds runtime pm support for the bundle core. Unbound bundle devices are always deactivated. During probe, Runtime PM status is set to enabled and active and the usage count is incremented. If the driver supports runtime PM, it should call pm_runtime_put() in its probe routine and pm_runtime_get_sync() in remove routine as bundle needs to be resume before it can be deactivated. Testing Done: - Check runtime_status of the bundle driver when bundle goes to suspend Signed-off-by: David Lin <dtwlin@google.com> Signed-off-by: Axel Haslam <ahaslam@baylibre.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 80f54c9..5bd7731 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -89,9 +89,89 @@ static void gb_bundle_release(struct device *dev) kfree(bundle); } +#ifdef CONFIG_PM_RUNTIME + +static void gb_bundle_disable_all_connections(struct gb_bundle *bundle) +{ + struct gb_connection *connection; + + list_for_each_entry(connection, &bundle->connections, bundle_links) + gb_connection_disable(connection); +} + +static void gb_bundle_enable_all_connections(struct gb_bundle *bundle) +{ + struct gb_connection *connection; + + list_for_each_entry(connection, &bundle->connections, bundle_links) + gb_connection_enable(connection); +} + +static int gb_bundle_suspend(struct device *dev) +{ + struct gb_bundle *bundle = to_gb_bundle(dev); + const struct dev_pm_ops *pm = dev->driver->pm; + int ret; + + if (pm && pm->runtime_suspend) { + ret = pm->runtime_suspend(&bundle->dev); + if (ret) + return ret; + } else { + gb_bundle_disable_all_connections(bundle); + } + + ret = gb_control_bundle_suspend(bundle->intf->control, bundle->id); + if (ret) { + if (pm && pm->runtime_resume) + ret = pm->runtime_resume(dev); + else + gb_bundle_enable_all_connections(bundle); + + return ret; + } + + return 0; +} + +static int gb_bundle_resume(struct device *dev) +{ + struct gb_bundle *bundle = to_gb_bundle(dev); + const struct dev_pm_ops *pm = dev->driver->pm; + int ret; + + ret = gb_control_bundle_resume(bundle->intf->control, bundle->id); + if (ret) + return ret; + + if (pm && pm->runtime_resume) { + ret = pm->runtime_resume(dev); + if (ret) + return ret; + } else { + gb_bundle_enable_all_connections(bundle); + } + + return 0; +} + +static int gb_bundle_idle(struct device *dev) +{ + pm_runtime_mark_last_busy(dev); + pm_request_autosuspend(dev); + + return 0; +} +#endif + +static const struct dev_pm_ops gb_bundle_pm_ops = { + SET_RUNTIME_PM_OPS(gb_bundle_suspend, gb_bundle_resume, gb_bundle_idle) +}; + struct device_type greybus_bundle_type = { .name = "greybus_bundle", .release = gb_bundle_release, + .pm = &gb_bundle_pm_ops, }; /* diff --git a/drivers/staging/greybus/bundle.h b/drivers/staging/greybus/bundle.h index 3895f94..349845e 100644 --- a/drivers/staging/greybus/bundle.h +++ b/drivers/staging/greybus/bundle.h @@ -40,4 +40,51 @@ struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, int gb_bundle_add(struct gb_bundle *bundle); void gb_bundle_destroy(struct gb_bundle *bundle); +/* Bundle Runtime PM wrappers */ +#ifdef CONFIG_PM_RUNTIME +static inline int gb_pm_runtime_get_sync(struct gb_bundle *bundle) +{ + int retval; + + retval = pm_runtime_get_sync(&bundle->dev); + if (retval < 0) { + dev_err(&bundle->dev, + "pm_runtime_get_sync failed: %d\n", retval); + pm_runtime_put_noidle(&bundle->dev); + return retval; + } + + return 0; +} + +static inline int gb_pm_runtime_put_autosuspend(struct gb_bundle *bundle) +{ + int retval; + + pm_runtime_mark_last_busy(&bundle->dev); + retval = pm_runtime_put_autosuspend(&bundle->dev); + + return retval; +} + +static inline void gb_pm_runtime_get_noresume(struct gb_bundle *bundle) +{ + pm_runtime_get_noresume(&bundle->dev); +} + +static inline void gb_pm_runtime_put_noidle(struct gb_bundle *bundle) +{ + pm_runtime_put_noidle(&bundle->dev); +} + +#else +static inline int gb_pm_runtime_get_sync(struct gb_bundle *bundle) +{ return 0; } +static inline int gb_pm_runtime_put_autosuspend(struct gb_bundle *bundle) +{ return 0; } + +static inline void gb_pm_runtime_get_noresume(struct gb_bundle *bundle) {} +static inline void gb_pm_runtime_put_noidle(struct gb_bundle *bundle) {} +#endif + #endif /* __BUNDLE_H */ diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index ca3bad9..53d9ba1 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -13,6 +13,8 @@ #include "greybus.h" #include "greybus_trace.h" +#define GB_BUNDLE_AUTOSUSPEND_MS 3000 + /* Allow greybus to be disabled at boot if needed */ static bool nogreybus; #ifdef MODULE @@ -162,6 +164,12 @@ static int greybus_probe(struct device *dev) if (!id) return -ENODEV; + retval = pm_runtime_get_sync(&bundle->intf->dev); + if (retval < 0) { + pm_runtime_put_noidle(&bundle->intf->dev); + return retval; + } + /* * FIXME: We need to perform error handling on bundle activate call * below when firmware is ready. We just allow the activate operation to @@ -169,6 +177,19 @@ static int greybus_probe(struct device *dev) */ gb_control_bundle_activate(bundle->intf->control, bundle->id); + /* + * Unbound bundle devices are always deactivated. During probe, the + * Runtime PM is set to enabled and active and the usage count is + * incremented. If the driver supports runtime PM, it should call + * pm_runtime_put() in its probe routine and pm_runtime_get_sync() + * in remove routine. + */ + pm_runtime_set_autosuspend_delay(dev, GB_BUNDLE_AUTOSUSPEND_MS); + pm_runtime_use_autosuspend(dev); + pm_runtime_get_noresume(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + retval = driver->probe(bundle, id); if (retval) { /* @@ -178,11 +199,19 @@ static int greybus_probe(struct device *dev) gb_control_bundle_deactivate(bundle->intf->control, bundle->id); + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); + pm_runtime_put_noidle(dev); + pm_runtime_dont_use_autosuspend(dev); + pm_runtime_put(&bundle->intf->dev); + return retval; } gb_timesync_schedule_asynchronous(bundle->intf); + pm_runtime_put(&bundle->intf->dev); + return 0; } @@ -191,6 +220,11 @@ static int greybus_remove(struct device *dev) struct greybus_driver *driver = to_greybus_driver(dev->driver); struct gb_bundle *bundle = to_gb_bundle(dev); struct gb_connection *connection; + int retval; + + retval = pm_runtime_get_sync(dev); + if (retval < 0) + dev_err(dev, "failed to resume bundle: %d\n", retval); /* * Disable (non-offloaded) connections early in case the interface is @@ -215,6 +249,12 @@ static int greybus_remove(struct device *dev) if (!bundle->intf->disconnected) gb_control_bundle_deactivate(bundle->intf->control, bundle->id); + pm_runtime_put_noidle(dev); + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); + pm_runtime_dont_use_autosuspend(dev); + pm_runtime_put_noidle(dev); + return 0; } -- cgit v0.10.2 From 6ba7fad430d6300b966800bc5d2c782e2baf6f1d Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Thu, 14 Jul 2016 15:13:00 -0500 Subject: greybus: audio: add runtime pm support Add runtime pm support to audio protocol device class driver. Testing Done: - Use white speaker module and check the interface is autosuspended when it's idle and resumed when playback audio Signed-off-by: David Lin <dtwlin@google.com> Signed-off-by: Axel Haslam <ahaslam@baylibre.com> Reviewed-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/audio_apbridgea.c b/drivers/staging/greybus/audio_apbridgea.c index 3614707..45d3522 100644 --- a/drivers/staging/greybus/audio_apbridgea.c +++ b/drivers/staging/greybus/audio_apbridgea.c @@ -33,12 +33,17 @@ int gb_audio_apbridgea_register_cport(struct gb_connection *connection, __u8 direction) { struct audio_apbridgea_register_cport_request req; + int ret; req.hdr.type = AUDIO_APBRIDGEA_TYPE_REGISTER_CPORT; req.hdr.i2s_port = cpu_to_le16(i2s_port); req.cport = cpu_to_le16(cportid); req.direction = direction; + ret = gb_pm_runtime_get_sync(connection->bundle); + if (ret) + return ret; + return gb_hd_output(connection->hd, &req, sizeof(req), GB_APB_REQUEST_AUDIO_CONTROL, true); } @@ -49,14 +54,19 @@ int gb_audio_apbridgea_unregister_cport(struct gb_connection *connection, __u8 direction) { struct audio_apbridgea_unregister_cport_request req; + int ret; req.hdr.type = AUDIO_APBRIDGEA_TYPE_UNREGISTER_CPORT; req.hdr.i2s_port = cpu_to_le16(i2s_port); req.cport = cpu_to_le16(cportid); req.direction = direction; - return gb_hd_output(connection->hd, &req, sizeof(req), - GB_APB_REQUEST_AUDIO_CONTROL, true); + ret = gb_hd_output(connection->hd, &req, sizeof(req), + GB_APB_REQUEST_AUDIO_CONTROL, true); + + gb_pm_runtime_put_autosuspend(connection->bundle); + + return ret; } EXPORT_SYMBOL_GPL(gb_audio_apbridgea_unregister_cport); diff --git a/drivers/staging/greybus/audio_module.c b/drivers/staging/greybus/audio_module.c index d87b998..7cf523e 100644 --- a/drivers/staging/greybus/audio_module.c +++ b/drivers/staging/greybus/audio_module.c @@ -332,6 +332,8 @@ static int gb_audio_probe(struct gb_bundle *bundle, dev_dbg(dev, "Add GB Audio device:%s\n", gbmodule->name); + gb_pm_runtime_put_autosuspend(bundle); + return 0; disable_data_connection: @@ -366,6 +368,8 @@ static void gb_audio_disconnect(struct gb_bundle *bundle) struct gbaudio_module_info *gbmodule = greybus_get_drvdata(bundle); struct gbaudio_data_connection *dai, *_dai; + gb_pm_runtime_get_sync(bundle); + /* cleanup module related resources first */ gbaudio_unregister_module(gbmodule); @@ -394,11 +398,58 @@ static const struct greybus_bundle_id gb_audio_id_table[] = { }; MODULE_DEVICE_TABLE(greybus, gb_audio_id_table); +#ifdef CONFIG_PM_RUNTIME +static int gb_audio_suspend(struct device *dev) +{ + struct gb_bundle *bundle = to_gb_bundle(dev); + struct gbaudio_module_info *gbmodule = greybus_get_drvdata(bundle); + struct gbaudio_data_connection *dai; + + list_for_each_entry(dai, &gbmodule->data_list, list) + gb_connection_disable(dai->connection); + + gb_connection_disable(gbmodule->mgmt_connection); + + return 0; +} + +static int gb_audio_resume(struct device *dev) +{ + struct gb_bundle *bundle = to_gb_bundle(dev); + struct gbaudio_module_info *gbmodule = greybus_get_drvdata(bundle); + struct gbaudio_data_connection *dai; + int ret; + + ret = gb_connection_enable(gbmodule->mgmt_connection); + if (ret) { + dev_err(dev, "%d:Error while enabling mgmt connection\n", ret); + return ret; + } + + list_for_each_entry(dai, &gbmodule->data_list, list) { + ret = gb_connection_enable(dai->connection); + if (ret) { + dev_err(dev, + "%d:Error while enabling %d:data connection\n", + ret, dai->data_cport); + return ret; + } + } + + return 0; +} +#endif + +static const struct dev_pm_ops gb_audio_pm_ops = { + SET_RUNTIME_PM_OPS(gb_audio_suspend, gb_audio_resume, NULL) +}; + static struct greybus_driver gb_audio_driver = { .name = "gb-audio", .probe = gb_audio_probe, .disconnect = gb_audio_disconnect, .id_table = gb_audio_id_table, + .driver.pm = &gb_audio_pm_ops, }; module_greybus_driver(gb_audio_driver); diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index e0779ca..487f744 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -213,6 +213,7 @@ static int gbcodec_mixer_ctl_get(struct snd_kcontrol *kcontrol, struct gbaudio_module_info *module; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + struct gb_bundle *bundle; dev_dbg(codec->dev, "Entered %s:%s\n", __func__, kcontrol->id.name); module = find_gb_module(gb, kcontrol->id.name); @@ -221,9 +222,17 @@ static int gbcodec_mixer_ctl_get(struct snd_kcontrol *kcontrol, data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; info = (struct gb_audio_ctl_elem_info *)data->info; + bundle = to_gb_bundle(module->dev); + + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + return ret; ret = gb_audio_gb_get_control(module->mgmt_connection, data->ctl_id, GB_AUDIO_INVALID_INDEX, &gbvalue); + + gb_pm_runtime_put_autosuspend(bundle); + if (ret) { dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, __func__, kcontrol->id.name); @@ -266,6 +275,7 @@ static int gbcodec_mixer_ctl_put(struct snd_kcontrol *kcontrol, struct gbaudio_module_info *module; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + struct gb_bundle *bundle; dev_dbg(codec->dev, "Entered %s:%s\n", __func__, kcontrol->id.name); module = find_gb_module(gb, kcontrol->id.name); @@ -274,6 +284,7 @@ static int gbcodec_mixer_ctl_put(struct snd_kcontrol *kcontrol, data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; info = (struct gb_audio_ctl_elem_info *)data->info; + bundle = to_gb_bundle(module->dev); /* update ucontrol */ switch (info->type) { @@ -302,8 +313,15 @@ static int gbcodec_mixer_ctl_put(struct snd_kcontrol *kcontrol, if (ret) return ret; + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + return ret; + ret = gb_audio_gb_set_control(module->mgmt_connection, data->ctl_id, GB_AUDIO_INVALID_INDEX, &gbvalue); + + gb_pm_runtime_put_autosuspend(bundle); + if (ret) { dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, __func__, kcontrol->id.name); @@ -370,6 +388,7 @@ static int gbcodec_mixer_dapm_ctl_get(struct snd_kcontrol *kcontrol, struct snd_soc_dapm_widget *widget = wlist->widgets[0]; struct snd_soc_codec *codec = widget->codec; struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + struct gb_bundle *bundle; dev_dbg(codec->dev, "Entered %s:%s\n", __func__, kcontrol->id.name); module = find_gb_module(gb, kcontrol->id.name); @@ -378,14 +397,22 @@ static int gbcodec_mixer_dapm_ctl_get(struct snd_kcontrol *kcontrol, data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; info = (struct gb_audio_ctl_elem_info *)data->info; + bundle = to_gb_bundle(module->dev); if (data->vcount == 2) dev_warn(widget->dapm->dev, "GB: Control '%s' is stereo, which is not supported\n", kcontrol->id.name); + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + return ret; + ret = gb_audio_gb_get_control(module->mgmt_connection, data->ctl_id, GB_AUDIO_INVALID_INDEX, &gbvalue); + + gb_pm_runtime_put_autosuspend(bundle); + if (ret) { dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, __func__, kcontrol->id.name); @@ -410,6 +437,7 @@ static int gbcodec_mixer_dapm_ctl_put(struct snd_kcontrol *kcontrol, struct snd_soc_dapm_widget *widget = wlist->widgets[0]; struct snd_soc_codec *codec = widget->codec; struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + struct gb_bundle *bundle; dev_dbg(codec->dev, "Entered %s:%s\n", __func__, kcontrol->id.name); module = find_gb_module(gb, kcontrol->id.name); @@ -418,6 +446,7 @@ static int gbcodec_mixer_dapm_ctl_put(struct snd_kcontrol *kcontrol, data = (struct gbaudio_ctl_pvt *)kcontrol->private_value; info = (struct gb_audio_ctl_elem_info *)data->info; + bundle = to_gb_bundle(module->dev); if (data->vcount == 2) dev_warn(widget->dapm->dev, @@ -441,9 +470,17 @@ static int gbcodec_mixer_dapm_ctl_put(struct snd_kcontrol *kcontrol, } gbvalue.value.integer_value[0] = ucontrol->value.integer.value[0]; + + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + return ret; + ret = gb_audio_gb_set_control(module->mgmt_connection, data->ctl_id, GB_AUDIO_INVALID_INDEX, &gbvalue); + + gb_pm_runtime_put_autosuspend(bundle); + if (ret) { dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, @@ -850,6 +887,7 @@ static int gbaudio_widget_event(struct snd_soc_dapm_widget *w, struct snd_soc_codec *codec = w->codec; struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec); struct gbaudio_module_info *module; + struct gb_bundle *bundle; dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event); @@ -865,6 +903,12 @@ static int gbaudio_widget_event(struct snd_soc_dapm_widget *w, return -EINVAL; } + bundle = to_gb_bundle(module->dev); + + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + return ret; + switch (event) { case SND_SOC_DAPM_PRE_PMU: ret = gb_audio_gb_enable_widget(module->mgmt_connection, wid); @@ -883,6 +927,9 @@ static int gbaudio_widget_event(struct snd_soc_dapm_widget *w, dev_err_ratelimited(codec->dev, "%d: widget, event:%d failed:%d\n", wid, event, ret); + + gb_pm_runtime_put_autosuspend(bundle); + return ret; } -- cgit v0.10.2 From 211634f2ca165947e37ba8b259c046a2e07b5f3c Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Thu, 14 Jul 2016 15:13:00 -0500 Subject: greybus: camera: add runtime pm support Add runtime pm support to camera protocol device class driver. Testing Done: - Make sure white camera module is able to runtime suspend and resume when the camera is being used Signed-off-by: David Lin <dtwlin@google.com> Signed-off-by: Axel Haslam <ahaslam@baylibre.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@linaro.org> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index ce0ff75..bdceb77 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -333,6 +333,10 @@ static int gb_camera_capabilities(struct gb_camera *gcam, struct gb_operation *op = NULL; int ret; + ret = gb_pm_runtime_get_sync(gcam->bundle); + if (ret) + return ret; + mutex_lock(&gcam->mutex); if (!gcam->connection) { @@ -362,6 +366,9 @@ done: mutex_unlock(&gcam->mutex); if (op) gb_operation_put(op); + + gb_pm_runtime_put_autosuspend(gcam->bundle); + return ret; } @@ -408,6 +415,10 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, mutex_lock(&gcam->mutex); + ret = gb_pm_runtime_get_sync(gcam->bundle); + if (ret) + goto done_skip_pm_put; + if (!gcam->connection) { ret = -EINVAL; goto done; @@ -460,9 +471,24 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, if (gcam->state == GB_CAMERA_STATE_CONFIGURED) { gb_camera_teardown_data_connection(gcam); gcam->state = GB_CAMERA_STATE_UNCONFIGURED; + + /* + * When unconfiguring streams release the PM runtime reference + * that was acquired when streams were configured. The bundle + * won't be suspended until the PM runtime reference acquired at + * the beginning of this function gets released right before + * returning. + */ + gb_pm_runtime_put_noidle(gcam->bundle); } if (resp->num_streams) { + /* + * Make sure the bundle won't be suspended until streams get + * unconfigured after the stream is configured successfully + */ + gb_pm_runtime_get_noresume(gcam->bundle); + ret = gb_camera_setup_data_connection(gcam, resp, csi_params); if (ret < 0) { memset(req, 0, sizeof(*req)); @@ -472,6 +498,7 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, resp, sizeof(*resp)); *flags = 0; *num_streams = 0; + gb_pm_runtime_put_noidle(gcam->bundle); goto done; } @@ -479,6 +506,9 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, } done: + gb_pm_runtime_put_autosuspend(gcam->bundle); + +done_skip_pm_put: mutex_unlock(&gcam->mutex); kfree(req); kfree(resp); @@ -1150,6 +1180,8 @@ static int gb_camera_probe(struct gb_bundle *bundle, greybus_set_drvdata(bundle, gcam); + gb_pm_runtime_put_autosuspend(gcam->bundle); + return 0; error: @@ -1161,6 +1193,11 @@ error: static void gb_camera_disconnect(struct gb_bundle *bundle) { struct gb_camera *gcam = greybus_get_drvdata(bundle); + int ret; + + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + gb_pm_runtime_get_noresume(bundle); gb_camera_cleanup(gcam); gb_camera_unregister(&gcam->module); @@ -1171,11 +1208,55 @@ static const struct greybus_bundle_id gb_camera_id_table[] = { { }, }; +#ifdef CONFIG_PM_RUNTIME +static int gb_camera_suspend(struct device *dev) +{ + struct gb_bundle *bundle = to_gb_bundle(dev); + struct gb_camera *gcam = greybus_get_drvdata(bundle); + + if (gcam->data_connection) + gb_connection_disable(gcam->data_connection); + + gb_connection_disable(gcam->connection); + + return 0; +} + +static int gb_camera_resume(struct device *dev) +{ + struct gb_bundle *bundle = to_gb_bundle(dev); + struct gb_camera *gcam = greybus_get_drvdata(bundle); + int ret; + + ret = gb_connection_enable(gcam->connection); + if (ret) { + gcam_err(gcam, "failed to enable connection: %d\n", ret); + return ret; + } + + if (gcam->data_connection) { + ret = gb_connection_enable(gcam->data_connection); + if (ret) { + gcam_err(gcam, + "failed to enable data connection: %d\n", ret); + return ret; + } + } + + return 0; +} +#endif + +static const struct dev_pm_ops gb_camera_pm_ops = { + SET_RUNTIME_PM_OPS(gb_camera_suspend, gb_camera_resume, NULL) +}; + static struct greybus_driver gb_camera_driver = { .name = "camera", .probe = gb_camera_probe, .disconnect = gb_camera_disconnect, .id_table = gb_camera_id_table, + .driver.pm = &gb_camera_pm_ops, }; module_greybus_driver(gb_camera_driver); -- cgit v0.10.2 From af5dc7f8c0f4b71fa53db2e8d6f18c26048a182f Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Thu, 14 Jul 2016 15:13:00 -0500 Subject: greybus: gbphy: add gbphy runtime pm support Since GBphy is a child of the Bundle device driver, for those runtime pm settings that are common to all the protocol drivers need to go in to the GBphy bus driver. Testing Done: - Check gbphy driver can be autosuspended Signed-off-by: David Lin <dtwlin@google.com> Signed-off-by: Axel Haslam <ahaslam@baylibre.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/gbphy.c b/drivers/staging/greybus/gbphy.c index 2727e4a..478c162 100644 --- a/drivers/staging/greybus/gbphy.c +++ b/drivers/staging/greybus/gbphy.c @@ -19,6 +19,8 @@ #include "greybus.h" #include "gbphy.h" +#define GB_GBPHY_AUTOSUSPEND_MS 3000 + struct gbphy_host { struct gb_bundle *bundle; struct list_head devices; @@ -50,9 +52,25 @@ static void gbphy_dev_release(struct device *dev) kfree(gbphy_dev); } +#ifdef CONFIG_PM_RUNTIME +static int gb_gbphy_idle(struct device *dev) +{ + pm_runtime_mark_last_busy(dev); + pm_request_autosuspend(dev); + return 0; +} +#endif + +static const struct dev_pm_ops gb_gbphy_pm_ops = { + SET_RUNTIME_PM_OPS(pm_generic_runtime_suspend, + pm_generic_runtime_resume, + gb_gbphy_idle) +}; + static struct device_type greybus_gbphy_dev_type = { .name = "gbphy_device", .release = gbphy_dev_release, + .pm = &gb_gbphy_pm_ops, }; static int gbphy_dev_uevent(struct device *dev, struct kobj_uevent_env *env) @@ -118,12 +136,38 @@ static int gbphy_dev_probe(struct device *dev) struct gbphy_driver *gbphy_drv = to_gbphy_driver(dev->driver); struct gbphy_device *gbphy_dev = to_gbphy_dev(dev); const struct gbphy_device_id *id; + int ret; id = gbphy_dev_match_id(gbphy_dev, gbphy_drv); if (!id) return -ENODEV; - return gbphy_drv->probe(gbphy_dev, id); + /* for old kernels we need get_sync to resume parent devices */ + ret = gb_pm_runtime_get_sync(gbphy_dev->bundle); + if (ret < 0) + return ret; + + pm_runtime_set_autosuspend_delay(dev, GB_GBPHY_AUTOSUSPEND_MS); + pm_runtime_use_autosuspend(dev); + pm_runtime_get_noresume(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + + /* + * Drivers should call put on the gbphy dev before returning + * from probe if they support runtime pm. + */ + ret = gbphy_drv->probe(gbphy_dev, id); + if (ret) { + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); + pm_runtime_put_noidle(dev); + pm_runtime_dont_use_autosuspend(dev); + } + + gb_pm_runtime_put_autosuspend(gbphy_dev->bundle); + + return ret; } static int gbphy_dev_remove(struct device *dev) @@ -132,6 +176,12 @@ static int gbphy_dev_remove(struct device *dev) struct gbphy_device *gbphy_dev = to_gbphy_dev(dev); gbphy_drv->remove(gbphy_dev); + + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); + pm_runtime_put_noidle(dev); + pm_runtime_dont_use_autosuspend(dev); + return 0; } @@ -211,6 +261,11 @@ static void gb_gbphy_disconnect(struct gb_bundle *bundle) { struct gbphy_host *gbphy_host = greybus_get_drvdata(bundle); struct gbphy_device *gbphy_dev, *temp; + int ret; + + ret = gb_pm_runtime_get_sync(bundle); + if (ret < 0) + gb_pm_runtime_get_noresume(bundle); list_for_each_entry_safe(gbphy_dev, temp, &gbphy_host->devices, list) { list_del(&gbphy_dev->list); @@ -251,6 +306,8 @@ static int gb_gbphy_probe(struct gb_bundle *bundle, list_add(&gbphy_dev->list, &gbphy_host->devices); } + gb_pm_runtime_put_autosuspend(bundle); + return 0; } diff --git a/drivers/staging/greybus/gbphy.h b/drivers/staging/greybus/gbphy.h index 68ad518..57c6f65 100644 --- a/drivers/staging/greybus/gbphy.h +++ b/drivers/staging/greybus/gbphy.h @@ -66,5 +66,45 @@ void gb_gbphy_deregister_driver(struct gbphy_driver *driver); #define module_gbphy_driver(__gbphy_driver) \ module_driver(__gbphy_driver, gb_gbphy_register, gb_gbphy_deregister) +#ifdef CONFIG_PM_RUNTIME +static inline int gbphy_runtime_get_sync(struct gbphy_device *gbphy_dev) +{ + struct device *dev = &gbphy_dev->dev; + int ret; + + ret = pm_runtime_get_sync(dev); + if (ret < 0) { + dev_err(dev, "pm_runtime_get_sync failed: %d\n", ret); + pm_runtime_put_noidle(dev); + return ret; + } + + return 0; +} + +static inline void gbphy_runtime_put_autosuspend(struct gbphy_device *gbphy_dev) +{ + struct device *dev = &gbphy_dev->dev; + + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); +} + +static inline void gbphy_runtime_get_noresume(struct gbphy_device *gbphy_dev) +{ + pm_runtime_get_noresume(&gbphy_dev->dev); +} + +static inline void gbphy_runtime_put_noidle(struct gbphy_device *gbphy_dev) +{ + pm_runtime_put_noidle(&gbphy_dev->dev); +} +#else +static inline int gbphy_runtime_get_sync(struct device *dev) { return 0; } +static inline void gbphy_runtime_put_autosuspend(struct device *dev) {} +static inline void gbphy_runtime_get_noresume(struct gbphy_device *gbphy_dev) {} +static inline void gbphy_runtime_put_noidle(struct gbphy_device *gbphy_dev) {} +#endif + #endif /* __GBPHY_H */ -- cgit v0.10.2 From c0e72f6af7363de8868e2847450a828f27e96c81 Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Thu, 14 Jul 2016 15:13:00 -0500 Subject: greybus: i2c: add runtime pm support Add runtime pm support to camera i2c bridged phy device class driver Testing Done: - Passed #gb_test.sh -v -t i2c Signed-off-by: David Lin <dtwlin@google.com> Signed-off-by: Axel Haslam <haslam_axel@projectara.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c index 2541bdb..c2a5008 100644 --- a/drivers/staging/greybus/i2c.c +++ b/drivers/staging/greybus/i2c.c @@ -176,6 +176,10 @@ static int gb_i2c_transfer_operation(struct gb_i2c_device *gb_i2c_dev, if (!operation) return -ENOMEM; + ret = gbphy_runtime_get_sync(gb_i2c_dev->gbphy_dev); + if (ret) + goto exit_operation_put; + ret = gb_operation_request_send_sync(operation); if (!ret) { struct gb_i2c_transfer_response *response; @@ -187,6 +191,9 @@ static int gb_i2c_transfer_operation(struct gb_i2c_device *gb_i2c_dev, dev_err(dev, "transfer operation failed (%d)\n", ret); } + gbphy_runtime_put_autosuspend(gb_i2c_dev->gbphy_dev); + +exit_operation_put: gb_operation_put(operation); return ret; @@ -290,6 +297,7 @@ static int gb_i2c_probe(struct gbphy_device *gbphy_dev, if (ret) goto exit_connection_disable; + gbphy_runtime_put_autosuspend(gbphy_dev); return 0; exit_connection_disable: @@ -306,6 +314,11 @@ static void gb_i2c_remove(struct gbphy_device *gbphy_dev) { struct gb_i2c_device *gb_i2c_dev = gb_gbphy_get_data(gbphy_dev); struct gb_connection *connection = gb_i2c_dev->connection; + int ret; + + ret = gbphy_runtime_get_sync(gbphy_dev); + if (ret) + gbphy_runtime_get_noresume(gbphy_dev); i2c_del_adapter(&gb_i2c_dev->adapter); gb_connection_disable(connection); -- cgit v0.10.2 From 22b8708725c20ce57d79e51a7e98628b382420a4 Mon Sep 17 00:00:00 2001 From: Axel Haslam <haslam_axel@projectara.com> Date: Thu, 14 Jul 2016 15:13:00 -0500 Subject: greybus: uart: Add runtime pm support This adds runtime pm support for the uart driver. Testing Done: Using the test daughter board, let the gpb bridge enter standby and do a uart transfer operation. Signed-off-by: Axel Haslam <haslam_axel@projectara.com> Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 6260569..01aeed1 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -771,6 +771,16 @@ static void gb_tty_dtr_rts(struct tty_port *port, int on) send_control(gb_tty, newctrl); } +static int gb_tty_port_activate(struct tty_port *port, + struct tty_struct *tty) +{ + struct gb_tty *gb_tty; + + gb_tty = container_of(port, struct gb_tty, port); + + return gbphy_runtime_get_sync(gb_tty->gbphy_dev); +} + static void gb_tty_port_shutdown(struct tty_port *port) { struct gb_tty *gb_tty; @@ -800,6 +810,8 @@ static void gb_tty_port_shutdown(struct tty_port *port) out: gb_tty->close_pending = false; + + gbphy_runtime_put_autosuspend(gb_tty->gbphy_dev); } static const struct tty_operations gb_ops = { @@ -822,6 +834,7 @@ static const struct tty_operations gb_ops = { static struct tty_port_operations gb_port_ops = { .dtr_rts = gb_tty_dtr_rts, + .activate = gb_tty_port_activate, .shutdown = gb_tty_port_shutdown, }; @@ -922,6 +935,7 @@ static int gb_uart_probe(struct gbphy_device *gbphy_dev, goto exit_connection_disable; } + gbphy_runtime_put_autosuspend(gbphy_dev); return 0; exit_connection_disable: @@ -945,6 +959,11 @@ static void gb_uart_remove(struct gbphy_device *gbphy_dev) struct gb_tty *gb_tty = gb_gbphy_get_data(gbphy_dev); struct gb_connection *connection = gb_tty->connection; struct tty_struct *tty; + int ret; + + ret = gbphy_runtime_get_sync(gbphy_dev); + if (ret) + gbphy_runtime_get_noresume(gbphy_dev); mutex_lock(&gb_tty->mutex); gb_tty->disconnected = true; -- cgit v0.10.2 From 993dc992f2e415adf9ddc69476ebaefda6af1043 Mon Sep 17 00:00:00 2001 From: Axel Haslam <haslam_axel@projectara.com> Date: Thu, 14 Jul 2016 15:13:00 -0500 Subject: greybus: gpio: Add runtime_pm suppourt Add runtime pm support for the gpio driver. Since there is no remote wakeup support, the module will not suspend as long as a gpio is requested. Maybe an optimization could be made, to allow suspend if all the requested gpios are in output mode, since the bridge should maintain the state of the gpio during suspend. Testing Done: using the test board, let the gpbrige enter standby and request a gpio. Signed-off-by: Axel Haslam <haslam_axel@projectara.com> Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index deae265..8fa9998 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -66,20 +66,31 @@ static int gb_gpio_line_count_operation(struct gb_gpio_controller *ggc) static int gb_gpio_activate_operation(struct gb_gpio_controller *ggc, u8 which) { struct gb_gpio_activate_request request; + struct gbphy_device *gbphy_dev = ggc->gbphy_dev; int ret; + ret = gbphy_runtime_get_sync(gbphy_dev); + if (ret) + return ret; + request.which = which; ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_ACTIVATE, &request, sizeof(request), NULL, 0); - if (!ret) - ggc->lines[which].active = true; - return ret; + if (ret) { + gbphy_runtime_put_autosuspend(gbphy_dev); + return ret; + } + + ggc->lines[which].active = true; + + return 0; } static void gb_gpio_deactivate_operation(struct gb_gpio_controller *ggc, u8 which) { - struct device *dev = &ggc->gbphy_dev->dev; + struct gbphy_device *gbphy_dev = ggc->gbphy_dev; + struct device *dev = &gbphy_dev->dev; struct gb_gpio_deactivate_request request; int ret; @@ -88,10 +99,13 @@ static void gb_gpio_deactivate_operation(struct gb_gpio_controller *ggc, &request, sizeof(request), NULL, 0); if (ret) { dev_err(dev, "failed to deactivate gpio %u\n", which); - return; + goto out_pm_put; } ggc->lines[which].active = false; + +out_pm_put: + gbphy_runtime_put_autosuspend(gbphy_dev); } static int gb_gpio_get_direction_operation(struct gb_gpio_controller *ggc, @@ -709,6 +723,7 @@ static int gb_gpio_probe(struct gbphy_device *gbphy_dev, goto exit_gpiochip_remove; } + gbphy_runtime_put_autosuspend(gbphy_dev); return 0; exit_gpiochip_remove: @@ -728,6 +743,11 @@ static void gb_gpio_remove(struct gbphy_device *gbphy_dev) { struct gb_gpio_controller *ggc = gb_gbphy_get_data(gbphy_dev); struct gb_connection *connection = ggc->connection; + int ret; + + ret = gbphy_runtime_get_sync(gbphy_dev); + if (ret) + gbphy_runtime_get_noresume(gbphy_dev); gb_connection_disable_rx(connection); gb_gpio_irqchip_remove(ggc); -- cgit v0.10.2 From afa807b8ba23952b471abb70716076bb3c98657c Mon Sep 17 00:00:00 2001 From: Axel Haslam <haslam_axel@projectara.com> Date: Thu, 14 Jul 2016 15:13:00 -0500 Subject: greybus: pwm: Add runtime_pm support Add runtime pm support for the pmw driver. Testing Done: Set the parameters of pwm0, and enable. Disable pwm0 and let the module enter standby. Enable pwm0, and observe that with an oscilloscope that the wave form is the same as before. Signed-off-by: Axel Haslam <haslam_axel@projectara.com> Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/pwm.c b/drivers/staging/greybus/pwm.c index 1438b2e..c4bf329 100644 --- a/drivers/staging/greybus/pwm.c +++ b/drivers/staging/greybus/pwm.c @@ -43,32 +43,58 @@ static int gb_pwm_activate_operation(struct gb_pwm_chip *pwmc, u8 which) { struct gb_pwm_activate_request request; + struct gbphy_device *gbphy_dev; + int ret; if (which > pwmc->pwm_max) return -EINVAL; request.which = which; - return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_ACTIVATE, - &request, sizeof(request), NULL, 0); + + gbphy_dev = to_gbphy_dev(pwmc->chip.dev); + ret = gbphy_runtime_get_sync(gbphy_dev); + if (ret) + return ret; + + ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_ACTIVATE, + &request, sizeof(request), NULL, 0); + + gbphy_runtime_put_autosuspend(gbphy_dev); + + return ret; } static int gb_pwm_deactivate_operation(struct gb_pwm_chip *pwmc, u8 which) { struct gb_pwm_deactivate_request request; + struct gbphy_device *gbphy_dev; + int ret; if (which > pwmc->pwm_max) return -EINVAL; request.which = which; - return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_DEACTIVATE, - &request, sizeof(request), NULL, 0); + + gbphy_dev = to_gbphy_dev(pwmc->chip.dev); + ret = gbphy_runtime_get_sync(gbphy_dev); + if (ret) + return ret; + + ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_DEACTIVATE, + &request, sizeof(request), NULL, 0); + + gbphy_runtime_put_autosuspend(gbphy_dev); + + return ret; } static int gb_pwm_config_operation(struct gb_pwm_chip *pwmc, u8 which, u32 duty, u32 period) { struct gb_pwm_config_request request; + struct gbphy_device *gbphy_dev; + int ret; if (which > pwmc->pwm_max) return -EINVAL; @@ -76,48 +102,90 @@ static int gb_pwm_config_operation(struct gb_pwm_chip *pwmc, request.which = which; request.duty = cpu_to_le32(duty); request.period = cpu_to_le32(period); - return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_CONFIG, - &request, sizeof(request), NULL, 0); + + gbphy_dev = to_gbphy_dev(pwmc->chip.dev); + ret = gbphy_runtime_get_sync(gbphy_dev); + if (ret) + return ret; + + ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_CONFIG, + &request, sizeof(request), NULL, 0); + + gbphy_runtime_put_autosuspend(gbphy_dev); + + return ret; } static int gb_pwm_set_polarity_operation(struct gb_pwm_chip *pwmc, u8 which, u8 polarity) { struct gb_pwm_polarity_request request; + struct gbphy_device *gbphy_dev; + int ret; if (which > pwmc->pwm_max) return -EINVAL; request.which = which; request.polarity = polarity; - return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_POLARITY, - &request, sizeof(request), NULL, 0); + + gbphy_dev = to_gbphy_dev(pwmc->chip.dev); + ret = gbphy_runtime_get_sync(gbphy_dev); + if (ret) + return ret; + + ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_POLARITY, + &request, sizeof(request), NULL, 0); + + gbphy_runtime_put_autosuspend(gbphy_dev); + + return ret; } static int gb_pwm_enable_operation(struct gb_pwm_chip *pwmc, u8 which) { struct gb_pwm_enable_request request; + struct gbphy_device *gbphy_dev; + int ret; if (which > pwmc->pwm_max) return -EINVAL; request.which = which; - return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_ENABLE, - &request, sizeof(request), NULL, 0); + + gbphy_dev = to_gbphy_dev(pwmc->chip.dev); + ret = gbphy_runtime_get_sync(gbphy_dev); + if (ret) + return ret; + + ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_ENABLE, + &request, sizeof(request), NULL, 0); + if (ret) + gbphy_runtime_put_autosuspend(gbphy_dev); + + return ret; } static int gb_pwm_disable_operation(struct gb_pwm_chip *pwmc, u8 which) { struct gb_pwm_disable_request request; + struct gbphy_device *gbphy_dev; + int ret; if (which > pwmc->pwm_max) return -EINVAL; request.which = which; - return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_DISABLE, - &request, sizeof(request), NULL, 0); + + ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_DISABLE, + &request, sizeof(request), NULL, 0); + + gbphy_dev = to_gbphy_dev(pwmc->chip.dev); + gbphy_runtime_put_autosuspend(gbphy_dev); + + return ret; } static int gb_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) @@ -225,6 +293,7 @@ static int gb_pwm_probe(struct gbphy_device *gbphy_dev, goto exit_connection_disable; } + gbphy_runtime_put_autosuspend(gbphy_dev); return 0; exit_connection_disable: @@ -240,6 +309,11 @@ static void gb_pwm_remove(struct gbphy_device *gbphy_dev) { struct gb_pwm_chip *pwmc = gb_gbphy_get_data(gbphy_dev); struct gb_connection *connection = pwmc->connection; + int ret; + + ret = gbphy_runtime_get_sync(gbphy_dev); + if (ret) + gbphy_runtime_get_noresume(gbphy_dev); pwmchip_remove(&pwmc->chip); gb_connection_disable(connection); -- cgit v0.10.2 From 4c615dcc6a9d910f8f68e4b57889b628e80165d4 Mon Sep 17 00:00:00 2001 From: Axel Haslam <ahaslam@baylibre.com> Date: Thu, 14 Jul 2016 15:13:00 -0500 Subject: greybus: spi: Add runtime_pm support Add runtime operations to the spi driver so that the module is woken up when an spi transfer is started and put back to sleep when the transfer is done. Testing Done: Let the module enter standby and initiate an spi operation. The operation wakes up the module and succeeds. Signed-off-by: Axel Haslam <ahaslam@baylibre.com> Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Rui Miguel Silva <rui.silva@linaro.org> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index 84beb2f..24d5bcd 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -313,6 +313,11 @@ static inline bool led_sysfs_is_disabled(struct led_classdev *led_cdev) #define SPI_NOR_MODALIAS "m25p80" #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0) +/* Starting from this version, the spi core handles runtime pm automatically */ +#define SPI_CORE_SUPPORT_PM +#endif + #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) /** * reinit_completion - reinitialize a completion structure diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index a823379..2e6e328 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -35,6 +35,7 @@ static int gb_spi_probe(struct gbphy_device *gbphy_dev, gb_gbphy_set_data(gbphy_dev, connection); + gbphy_runtime_put_autosuspend(gbphy_dev); return 0; exit_connection_disable: @@ -48,6 +49,11 @@ exit_connection_destroy: static void gb_spi_remove(struct gbphy_device *gbphy_dev) { struct gb_connection *connection = gb_gbphy_get_data(gbphy_dev); + int ret; + + ret = gbphy_runtime_get_sync(gbphy_dev); + if (ret) + gbphy_runtime_get_noresume(gbphy_dev); gb_spilib_master_exit(connection); gb_connection_disable(connection); diff --git a/drivers/staging/greybus/spilib.c b/drivers/staging/greybus/spilib.c index 527909b..e4c82e0 100644 --- a/drivers/staging/greybus/spilib.c +++ b/drivers/staging/greybus/spilib.c @@ -15,6 +15,7 @@ #include "greybus.h" #include "spilib.h" +#include "gbphy.h" struct gb_spilib { struct gb_connection *connection; @@ -372,6 +373,26 @@ out: return ret; } +#ifndef SPI_CORE_SUPPORT_PM +static int gb_spi_prepare_transfer_hardware(struct spi_master *master) +{ + struct gb_spilib *spi = spi_master_get_devdata(master); + struct gbphy_device *gbphy_dev = to_gbphy_dev(spi->parent); + + return gbphy_runtime_get_sync(gbphy_dev); +} + +static int gb_spi_unprepare_transfer_hardware(struct spi_master *master) +{ + struct gb_spilib *spi = spi_master_get_devdata(master); + struct gbphy_device *gbphy_dev = to_gbphy_dev(spi->parent); + + gbphy_runtime_put_autosuspend(gbphy_dev); + + return 0; +} +#endif + static int gb_spi_setup(struct spi_device *spi) { /* Nothing to do for now */ @@ -497,6 +518,14 @@ int gb_spilib_master_init(struct gb_connection *connection, struct device *dev) master->setup = gb_spi_setup; master->transfer_one_message = gb_spi_transfer_one_message; +#ifndef SPI_CORE_SUPPORT_PM + master->prepare_transfer_hardware = gb_spi_prepare_transfer_hardware; + master->unprepare_transfer_hardware = + gb_spi_unprepare_transfer_hardware; +#else + master->auto_runtime_pm = true; +#endif + ret = spi_register_master(master); if (ret < 0) goto exit_spi_put; -- cgit v0.10.2 From e854ff58ed7011f73c7cdfcb7966ffa9c103571e Mon Sep 17 00:00:00 2001 From: Axel Haslam <haslam_axel@projectara.com> Date: Thu, 14 Jul 2016 15:13:00 -0500 Subject: greybus: loopback: add runtime pm support Add runtime pm to the loopback driver so that the module wakes up from suspend while a test is executed. Testing Done: Let the module enter standby and execute a loopback test. Signed-off-by: Axel Haslam <haslam_axel@projectara.com> Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Alex Elder <elder@linaro.org> diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 702cf06..8b0d0dc 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -25,6 +25,7 @@ #include <linux/spinlock.h> #include <linux/workqueue.h> #include <linux/atomic.h> +#include <linux/pm_runtime.h> #include <asm/div64.h> @@ -976,14 +977,26 @@ static int gb_loopback_fn(void *data) int error = 0; int us_wait = 0; int type; + int ret; u32 size; struct gb_loopback *gb = data; + struct gb_bundle *bundle = gb->connection->bundle; + + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + return ret; while (1) { - if (!gb->type) + if (!gb->type) { + gb_pm_runtime_put_autosuspend(bundle); wait_event_interruptible(gb->wq, gb->type || kthread_should_stop()); + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + return ret; + } + if (kthread_should_stop()) break; @@ -1042,6 +1055,9 @@ static int gb_loopback_fn(void *data) if (us_wait) udelay(us_wait); } + + gb_pm_runtime_put_autosuspend(bundle); + return 0; } @@ -1233,6 +1249,9 @@ static int gb_loopback_probe(struct gb_bundle *bundle, spin_unlock_irqrestore(&gb_dev.lock, flags); gb_connection_latency_tag_enable(connection); + + gb_pm_runtime_put_autosuspend(bundle); + return 0; out_kfifo1: @@ -1259,6 +1278,11 @@ static void gb_loopback_disconnect(struct gb_bundle *bundle) { struct gb_loopback *gb = greybus_get_drvdata(bundle); unsigned long flags; + int ret; + + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + gb_pm_runtime_get_noresume(bundle); gb_connection_disable(gb->connection); -- cgit v0.10.2 From 99ade1766dbd11652905ec91219a643992cb3c18 Mon Sep 17 00:00:00 2001 From: Alex Elder <elder@linaro.org> Date: Thu, 14 Jul 2016 14:24:18 -0500 Subject: greybus: get rid of a compile warning The compiler has no way of knowing whether a called function will actually assign something to the object whose address is passed as an argument. So it must assume it won't happen, and this leads to a compile warning. Fix this. Signed-off-by: Alex Elder <elder@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 7961622..f64dbcb 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -611,7 +611,7 @@ static int cport_reset(struct gb_host_device *hd, u16 cport_id) struct usb_device *udev = es2->usb_dev; struct arpc_cport_reset req; int retval; - int result; + int result = 0; switch (cport_id) { case GB_SVC_CPORT_ID: -- cgit v0.10.2 From fc0c38b3d1d6648bfef8ed2478cd2505f6a97475 Mon Sep 17 00:00:00 2001 From: Alex Elder <elder@linaro.org> Date: Thu, 14 Jul 2016 14:24:19 -0500 Subject: greybus: use memdup_user() Coccinelle reports that there are two opportunities to use memdup_user() in "authentication.c". This patch simplifies the code in cap_ioctl() by taking advantage of that. Make use of a local variable "size" to improve readability. Signed-off-by: Alex Elder <elder@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/authentication.c b/drivers/staging/greybus/authentication.c index e469780..a4ac3bb 100644 --- a/drivers/staging/greybus/authentication.c +++ b/drivers/staging/greybus/authentication.c @@ -209,6 +209,7 @@ static int cap_ioctl(struct gb_cap *cap, unsigned int cmd, struct cap_ioc_get_endpoint_uid endpoint_uid; struct cap_ioc_get_ims_certificate *ims_cert; struct cap_ioc_authenticate *authenticate; + size_t size; int ret; switch (cmd) { @@ -222,38 +223,26 @@ static int cap_ioctl(struct gb_cap *cap, unsigned int cmd, return 0; case CAP_IOC_GET_IMS_CERTIFICATE: - ims_cert = kzalloc(sizeof(*ims_cert), GFP_KERNEL); - if (!ims_cert) - return -ENOMEM; - - if (copy_from_user(ims_cert, buf, sizeof(*ims_cert))) { - ret = -EFAULT; - goto free_ims_cert; - } + size = sizeof(*ims_cert); + ims_cert = memdup_user(buf, size); + if (IS_ERR(ims_cert)) + return PTR_ERR(ims_cert); ret = cap_get_ims_certificate(cap, ims_cert->certificate_class, ims_cert->certificate_id, ims_cert->certificate, &ims_cert->cert_size, &ims_cert->result_code); - if (ret) - goto free_ims_cert; - - if (copy_to_user(buf, ims_cert, sizeof(*ims_cert))) + if (!ret && copy_to_user(buf, ims_cert, size)) ret = -EFAULT; - -free_ims_cert: kfree(ims_cert); + return ret; case CAP_IOC_AUTHENTICATE: - authenticate = kzalloc(sizeof(*authenticate), GFP_KERNEL); - if (!authenticate) - return -ENOMEM; - - if (copy_from_user(authenticate, buf, sizeof(*authenticate))) { - ret = -EFAULT; - goto free_authenticate; - } + size = sizeof(*authenticate); + authenticate = memdup_user(buf, size); + if (IS_ERR(authenticate)) + return PTR_ERR(authenticate); ret = cap_authenticate(cap, authenticate->auth_type, authenticate->uid, @@ -262,13 +251,10 @@ free_ims_cert: authenticate->response, &authenticate->signature_size, authenticate->signature); - if (ret) - goto free_authenticate; - - if (copy_to_user(buf, authenticate, sizeof(*authenticate))) + if (!ret && copy_to_user(buf, authenticate, size)) ret = -EFAULT; -free_authenticate: kfree(authenticate); + return ret; default: return -ENOTTY; -- cgit v0.10.2 From 6e720c277ad126de2052b90dd4114953f2d00f79 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva <rui.silva@linaro.org> Date: Wed, 13 Jul 2016 14:11:19 +0100 Subject: greybus: power_supply: change property values to integer To align with power supply core values type (integer) move the val and previous_val to integer also. Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org> Reviewed-by: Sandeep Patil <sspatil@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c index e96c24d..f905c3c 100644 --- a/drivers/staging/greybus/power_supply.c +++ b/drivers/staging/greybus/power_supply.c @@ -18,8 +18,8 @@ struct gb_power_supply_prop { enum power_supply_property prop; - u32 val; - u32 previous_val; + int val; + int previous_val; bool is_writeable; }; @@ -142,8 +142,8 @@ static void check_changed(struct gb_power_supply *gbpsy, struct gb_power_supply_prop *prop) { const struct gb_power_supply_changes *psyc; - u32 val = prop->val; - u32 prev_val = prop->previous_val; + int val = prop->val; + int prev_val = prop->previous_val; int i; for (i = 0; i < ARRAY_SIZE(psy_props_changes); i++) { @@ -317,7 +317,7 @@ static int __gb_power_supply_property_update(struct gb_power_supply *gbpsy, struct gb_power_supply_prop *prop; struct gb_power_supply_get_property_request req; struct gb_power_supply_get_property_response resp; - u32 val; + int val; int ret; prop = get_psy_prop(gbpsy, psp); @@ -481,6 +481,7 @@ static int gb_power_supply_property_set(struct gb_power_supply *gbpsy, req.psy_id = gbpsy->id; req.property = (u8)psp; req.prop_val = cpu_to_le32(val); + req.prop_val = cpu_to_le32((s32)val); ret = gb_operation_sync(connection, GB_POWER_SUPPLY_TYPE_SET_PROPERTY, &req, sizeof(req), NULL, 0); -- cgit v0.10.2 From 47becc556d4e8dc5bcd370100edebd6ad749b702 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva <rui.silva@linaro.org> Date: Wed, 13 Jul 2016 14:11:20 +0100 Subject: greybus: power_supply: convert greybus properties to power supply properties We need to translate greybus properties to power supply core properties, for that when parsing the properties that were fetch during configuration we check if there is a match to the running kernel version and store it in a new field (gb_prop) in the gb_power_supply_prop struct. If the corresponding property does not exist in the running kernel (because of version or vendor specific property) we drop that property. A collection of properties that, at this time, may diverge are defined in the kernel_ver.h to avoid breakage at build time and run time if this properties are not supported by the kernel. Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org> Reviewed-by: Sandeep Patil <sspatil@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index 24d5bcd..5d13e36 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -305,6 +305,20 @@ static inline bool led_sysfs_is_disabled(struct led_classdev *led_cdev) #define PSY_HAVE_PUT #endif +/* + * General power supply properties that could be absent from various reasons, + * like kernel versions or vendor specific versions + */ +#ifndef POWER_SUPPLY_PROP_VOLTAGE_BOOT + #define POWER_SUPPLY_PROP_VOLTAGE_BOOT -1 +#endif +#ifndef POWER_SUPPLY_PROP_CURRENT_BOOT + #define POWER_SUPPLY_PROP_CURRENT_BOOT -1 +#endif +#ifndef POWER_SUPPLY_PROP_CALIBRATE + #define POWER_SUPPLY_PROP_CALIBRATE -1 +#endif + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) #define SPI_DEV_MODALIAS "spidev" #define SPI_NOR_MODALIAS "spi-nor" diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c index f905c3c..058fd3c 100644 --- a/drivers/staging/greybus/power_supply.c +++ b/drivers/staging/greybus/power_supply.c @@ -18,6 +18,7 @@ struct gb_power_supply_prop { enum power_supply_property prop; + u8 gb_prop; int val; int previous_val; bool is_writeable; @@ -83,6 +84,210 @@ static const struct gb_power_supply_changes psy_props_changes[] = { }, }; +static int get_psp_from_gb_prop(int gb_prop, enum power_supply_property *psp) +{ + int prop; + + switch (gb_prop) { + case GB_POWER_SUPPLY_PROP_STATUS: + prop = POWER_SUPPLY_PROP_STATUS; + break; + case GB_POWER_SUPPLY_PROP_CHARGE_TYPE: + prop = POWER_SUPPLY_PROP_CHARGE_TYPE; + break; + case GB_POWER_SUPPLY_PROP_HEALTH: + prop = POWER_SUPPLY_PROP_HEALTH; + break; + case GB_POWER_SUPPLY_PROP_PRESENT: + prop = POWER_SUPPLY_PROP_PRESENT; + break; + case GB_POWER_SUPPLY_PROP_ONLINE: + prop = POWER_SUPPLY_PROP_ONLINE; + break; + case GB_POWER_SUPPLY_PROP_AUTHENTIC: + prop = POWER_SUPPLY_PROP_AUTHENTIC; + break; + case GB_POWER_SUPPLY_PROP_TECHNOLOGY: + prop = POWER_SUPPLY_PROP_TECHNOLOGY; + break; + case GB_POWER_SUPPLY_PROP_CYCLE_COUNT: + prop = POWER_SUPPLY_PROP_CYCLE_COUNT; + break; + case GB_POWER_SUPPLY_PROP_VOLTAGE_MAX: + prop = POWER_SUPPLY_PROP_VOLTAGE_MAX; + break; + case GB_POWER_SUPPLY_PROP_VOLTAGE_MIN: + prop = POWER_SUPPLY_PROP_VOLTAGE_MIN; + break; + case GB_POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: + prop = POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN; + break; + case GB_POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: + prop = POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN; + break; + case GB_POWER_SUPPLY_PROP_VOLTAGE_NOW: + prop = POWER_SUPPLY_PROP_VOLTAGE_NOW; + break; + case GB_POWER_SUPPLY_PROP_VOLTAGE_AVG: + prop = POWER_SUPPLY_PROP_VOLTAGE_AVG; + break; + case GB_POWER_SUPPLY_PROP_VOLTAGE_OCV: + prop = POWER_SUPPLY_PROP_VOLTAGE_OCV; + break; + case GB_POWER_SUPPLY_PROP_VOLTAGE_BOOT: + prop = POWER_SUPPLY_PROP_VOLTAGE_BOOT; + break; + case GB_POWER_SUPPLY_PROP_CURRENT_MAX: + prop = POWER_SUPPLY_PROP_CURRENT_MAX; + break; + case GB_POWER_SUPPLY_PROP_CURRENT_NOW: + prop = POWER_SUPPLY_PROP_CURRENT_NOW; + break; + case GB_POWER_SUPPLY_PROP_CURRENT_AVG: + prop = POWER_SUPPLY_PROP_CURRENT_AVG; + break; + case GB_POWER_SUPPLY_PROP_CURRENT_BOOT: + prop = POWER_SUPPLY_PROP_CURRENT_BOOT; + break; + case GB_POWER_SUPPLY_PROP_POWER_NOW: + prop = POWER_SUPPLY_PROP_POWER_NOW; + break; + case GB_POWER_SUPPLY_PROP_POWER_AVG: + prop = POWER_SUPPLY_PROP_POWER_AVG; + break; + case GB_POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: + prop = POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN; + break; + case GB_POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN: + prop = POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN; + break; + case GB_POWER_SUPPLY_PROP_CHARGE_FULL: + prop = POWER_SUPPLY_PROP_CHARGE_FULL; + break; + case GB_POWER_SUPPLY_PROP_CHARGE_EMPTY: + prop = POWER_SUPPLY_PROP_CHARGE_EMPTY; + break; + case GB_POWER_SUPPLY_PROP_CHARGE_NOW: + prop = POWER_SUPPLY_PROP_CHARGE_NOW; + break; + case GB_POWER_SUPPLY_PROP_CHARGE_AVG: + prop = POWER_SUPPLY_PROP_CHARGE_AVG; + break; + case GB_POWER_SUPPLY_PROP_CHARGE_COUNTER: + prop = POWER_SUPPLY_PROP_CHARGE_COUNTER; + break; + case GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: + prop = POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT; + break; + case GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: + prop = POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX; + break; + case GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: + prop = POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE; + break; + case GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: + prop = POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX; + break; + case GB_POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT: + prop = POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT; + break; + case GB_POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX: + prop = POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX; + break; + case GB_POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: + prop = POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT; + break; + case GB_POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: + prop = POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN; + break; + case GB_POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN: + prop = POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN; + break; + case GB_POWER_SUPPLY_PROP_ENERGY_FULL: + prop = POWER_SUPPLY_PROP_ENERGY_FULL; + break; + case GB_POWER_SUPPLY_PROP_ENERGY_EMPTY: + prop = POWER_SUPPLY_PROP_ENERGY_EMPTY; + break; + case GB_POWER_SUPPLY_PROP_ENERGY_NOW: + prop = POWER_SUPPLY_PROP_ENERGY_NOW; + break; + case GB_POWER_SUPPLY_PROP_ENERGY_AVG: + prop = POWER_SUPPLY_PROP_ENERGY_AVG; + break; + case GB_POWER_SUPPLY_PROP_CAPACITY: + prop = POWER_SUPPLY_PROP_CAPACITY; + break; + case GB_POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN: + prop = POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN; + break; + case GB_POWER_SUPPLY_PROP_CAPACITY_ALERT_MAX: + prop = POWER_SUPPLY_PROP_CAPACITY_ALERT_MAX; + break; + case GB_POWER_SUPPLY_PROP_CAPACITY_LEVEL: + prop = POWER_SUPPLY_PROP_CAPACITY_LEVEL; + break; + case GB_POWER_SUPPLY_PROP_TEMP: + prop = POWER_SUPPLY_PROP_TEMP; + break; + case GB_POWER_SUPPLY_PROP_TEMP_MAX: + prop = POWER_SUPPLY_PROP_TEMP_MAX; + break; + case GB_POWER_SUPPLY_PROP_TEMP_MIN: + prop = POWER_SUPPLY_PROP_TEMP_MIN; + break; + case GB_POWER_SUPPLY_PROP_TEMP_ALERT_MIN: + prop = POWER_SUPPLY_PROP_TEMP_ALERT_MIN; + break; + case GB_POWER_SUPPLY_PROP_TEMP_ALERT_MAX: + prop = POWER_SUPPLY_PROP_TEMP_ALERT_MAX; + break; + case GB_POWER_SUPPLY_PROP_TEMP_AMBIENT: + prop = POWER_SUPPLY_PROP_TEMP_AMBIENT; + break; + case GB_POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MIN: + prop = POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MIN; + break; + case GB_POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MAX: + prop = POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MAX; + break; + case GB_POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW: + prop = POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW; + break; + case GB_POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: + prop = POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG; + break; + case GB_POWER_SUPPLY_PROP_TIME_TO_FULL_NOW: + prop = POWER_SUPPLY_PROP_TIME_TO_FULL_NOW; + break; + case GB_POWER_SUPPLY_PROP_TIME_TO_FULL_AVG: + prop = POWER_SUPPLY_PROP_TIME_TO_FULL_AVG; + break; + case GB_POWER_SUPPLY_PROP_TYPE: + prop = POWER_SUPPLY_PROP_TYPE; + break; + case GB_POWER_SUPPLY_PROP_SCOPE: + prop = POWER_SUPPLY_PROP_SCOPE; + break; + case GB_POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: + prop = POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT; + break; + case GB_POWER_SUPPLY_PROP_CALIBRATE: + prop = POWER_SUPPLY_PROP_CALIBRATE; + break; + default: + prop = -1; + break; + } + + if (prop < 0) + return prop; + + *psp = (enum power_supply_property)prop; + + return 0; +} + static struct gb_connection *get_conn_from_psy(struct gb_power_supply *gbpsy) { return gbpsy->supplies->connection; @@ -253,8 +458,9 @@ static int gb_power_supply_prop_descriptors_get(struct gb_power_supply *gbpsy) struct gb_power_supply_get_property_descriptors_response *resp; struct gb_operation *op; u8 props_count = gbpsy->properties_count; + enum power_supply_property psp; int ret; - int i; + int i, r = 0; if (props_count == 0) return 0; @@ -276,6 +482,17 @@ static int gb_power_supply_prop_descriptors_get(struct gb_power_supply *gbpsy) resp = op->response->payload; + /* validate received properties */ + for (i = 0; i < props_count; i++) { + ret = get_psp_from_gb_prop(resp->props[i].property, &psp); + if (ret < 0) { + dev_warn(&connection->bundle->dev, + "greybus property %u it is not supported by this kernel, dropped\n", + resp->props[i].property); + gbpsy->properties_count--; + } + } + gbpsy->props = kcalloc(gbpsy->properties_count, sizeof(*gbpsy->props), GFP_KERNEL); if (!gbpsy->props) { @@ -290,12 +507,18 @@ static int gb_power_supply_prop_descriptors_get(struct gb_power_supply *gbpsy) goto out_put_operation; } - /* Store available properties */ - for (i = 0; i < gbpsy->properties_count; i++) { - gbpsy->props[i].prop = resp->props[i].property; - gbpsy->props_raw[i] = resp->props[i].property; + /* Store available properties, skip the ones we do not support */ + for (i = 0; i < props_count; i++) { + ret = get_psp_from_gb_prop(resp->props[i].property, &psp); + if (ret < 0) { + r++; + continue; + } + gbpsy->props[i - r].prop = psp; + gbpsy->props[i - r].gb_prop = resp->props[i].property; + gbpsy->props_raw[i - r] = psp; if (resp->props[i].is_writeable) - gbpsy->props[i].is_writeable = true; + gbpsy->props[i - r].is_writeable = true; } /* @@ -304,6 +527,7 @@ static int gb_power_supply_prop_descriptors_get(struct gb_power_supply *gbpsy) */ _gb_power_supply_append_props(gbpsy); + ret = 0; out_put_operation: gb_operation_put(op); @@ -324,7 +548,7 @@ static int __gb_power_supply_property_update(struct gb_power_supply *gbpsy, if (!prop) return -EINVAL; req.psy_id = gbpsy->id; - req.property = (u8)psp; + req.property = prop->gb_prop; ret = gb_operation_sync(connection, GB_POWER_SUPPLY_TYPE_GET_PROPERTY, &req, sizeof(req), &resp, sizeof(resp)); @@ -479,8 +703,7 @@ static int gb_power_supply_property_set(struct gb_power_supply *gbpsy, if (!prop) return -EINVAL; req.psy_id = gbpsy->id; - req.property = (u8)psp; - req.prop_val = cpu_to_le32(val); + req.property = prop->gb_prop; req.prop_val = cpu_to_le32((s32)val); ret = gb_operation_sync(connection, GB_POWER_SUPPLY_TYPE_SET_PROPERTY, -- cgit v0.10.2 From 1f77b363bef417e28d8556a11c9a82f3e6cf24f0 Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Tue, 12 Jul 2016 17:41:21 -0700 Subject: greybus: hd: arche-platform: implement greybus shutdown Implement platform driver shutdown callback to perform proper greybus shutdown so that the userspace unipro_shutdown service that shuts down the APB/SVC abruptly can be removed. The shutdown callback in arche-platform will first remove SVC so that all the Interface can be Deactivated in a sequence according to the spec before powering off the APB: Before: -> Arche/APB power off -> SoC power off After this patch: -> HD shutdown -> SVC shutdown -> Module shutdown -> Interface shutdown -> Bundle shutdown -> Arche/APB power off -> SoC power off Testing Done: - Observe all Interfaces are deactivated in the log during shutdown - Measure power off current and make sure no regression Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index fce6a18..cae56fc 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -444,6 +444,11 @@ static int arche_apb_ctrl_resume(struct device *dev) return 0; } +static void arche_apb_ctrl_shutdown(struct platform_device *pdev) +{ + apb_ctrl_poweroff(&pdev->dev); +} + static SIMPLE_DEV_PM_OPS(arche_apb_ctrl_pm_ops, arche_apb_ctrl_suspend, arche_apb_ctrl_resume); @@ -455,6 +460,7 @@ static struct of_device_id arche_apb_ctrl_of_match[] = { static struct platform_driver arche_apb_ctrl_device_driver = { .probe = arche_apb_ctrl_probe, .remove = arche_apb_ctrl_remove, + .shutdown = arche_apb_ctrl_shutdown, .driver = { .name = "arche-apb-ctrl", .pm = &arche_apb_ctrl_pm_ops, diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 31c9524..af78420 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -770,6 +770,15 @@ static int arche_platform_resume(struct device *dev) return 0; } +static void arche_platform_shutdown(struct platform_device *pdev) +{ + struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev); + + arche_platform_poweroff_seq(arche_pdata); + + usb3613_hub_mode_ctrl(false); +} + static SIMPLE_DEV_PM_OPS(arche_platform_pm_ops, arche_platform_suspend, arche_platform_resume); @@ -789,6 +798,7 @@ MODULE_DEVICE_TABLE(of, arche_combined_id); static struct platform_driver arche_platform_device_driver = { .probe = arche_platform_probe, .remove = arche_platform_remove, + .shutdown = arche_platform_shutdown, .driver = { .name = "arche-platform-ctrl", .pm = &arche_platform_pm_ops, diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 53d9ba1..2c94bbb 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -146,10 +146,21 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) return 0; } +static void greybus_shutdown(struct device *dev) +{ + if (is_gb_host_device(dev)) { + struct gb_host_device *hd; + + hd = to_gb_host_device(dev); + gb_hd_shutdown(hd); + } +} + struct bus_type greybus_bus_type = { .name = "greybus", .match = greybus_match_device, .uevent = greybus_uevent, + .shutdown = greybus_shutdown, }; static int greybus_probe(struct device *dev) diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index 8ef849a..185ae3f 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -232,6 +232,12 @@ void gb_hd_del(struct gb_host_device *hd) } EXPORT_SYMBOL_GPL(gb_hd_del); +void gb_hd_shutdown(struct gb_host_device *hd) +{ + gb_svc_del(hd->svc); +} +EXPORT_SYMBOL_GPL(gb_hd_shutdown); + void gb_hd_put(struct gb_host_device *hd) { put_device(&hd->dev); diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h index d5d8c67..6ea5e28 100644 --- a/drivers/staging/greybus/hd.h +++ b/drivers/staging/greybus/hd.h @@ -75,6 +75,7 @@ struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, size_t num_cports); int gb_hd_add(struct gb_host_device *hd); void gb_hd_del(struct gb_host_device *hd); +void gb_hd_shutdown(struct gb_host_device *hd); void gb_hd_put(struct gb_host_device *hd); int gb_hd_output(struct gb_host_device *hd, void *req, u16 size, u8 cmd, bool in_irq); -- cgit v0.10.2 From fddd7eafc746e5ad6ea0f980e85a3fdc87091e81 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Fri, 15 Jul 2016 18:01:49 +0100 Subject: greybus: timesync/pm: Make synchronous call to restore FrameTime When we discussed and agreed a serialized way to-do PM runtime suspend/resume we omitted the necessity to restore the FrameTime on resume. This patch restores the FrameTime synchronously such that when an Interface PM resume callback completes we have either successfully restored the FrameTime including the new Interface or we've produced a result code to indicate what went wrong when trying. Suggested-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Tested-by: David Lin <dtwlin@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 16e268f..b3bd96e 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -579,6 +579,12 @@ static int gb_interface_resume(struct device *dev) return ret; } + ret = gb_timesync_schedule_synchronous(intf); + if (ret) { + dev_err(dev, "failed to synchronize FrameTime: %d\n", ret); + return ret; + } + return 0; } -- cgit v0.10.2 From c10b4ea3b23fdd1d7db531b316ba75fd2578fc2a Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva <rui.silva@linaro.org> Date: Fri, 15 Jul 2016 12:16:54 +0100 Subject: greybus: power_supply: remove references to kernel header In Greybus power supply macro definitions we have a comment that point to a kernel header, remove it since we have a specification for that. As at it, align the status values to the upper values. Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org> Reviewed-by: Sandeep Patil <sspatil@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index e9f3d2c..18c527c 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -533,7 +533,7 @@ struct gb_bootrom_get_vid_pid_response { #define GB_POWER_SUPPLY_TYPE_SET_PROPERTY 0x06 #define GB_POWER_SUPPLY_TYPE_EVENT 0x07 -/* Should match up with battery technologies in linux/power_supply.h */ +/* Greybus power supply battery technologies types */ #define GB_POWER_SUPPLY_TECH_UNKNOWN 0x0000 #define GB_POWER_SUPPLY_TECH_NiMH 0x0001 #define GB_POWER_SUPPLY_TECH_LION 0x0002 @@ -542,7 +542,7 @@ struct gb_bootrom_get_vid_pid_response { #define GB_POWER_SUPPLY_TECH_NiCd 0x0005 #define GB_POWER_SUPPLY_TECH_LiMn 0x0006 -/* Should match up with power supply types in linux/power_supply.h */ +/* Greybus power supply types */ #define GB_POWER_SUPPLY_UNKNOWN_TYPE 0x0000 #define GB_POWER_SUPPLY_BATTERY_TYPE 0x0001 #define GB_POWER_SUPPLY_UPS_TYPE 0x0002 @@ -552,7 +552,7 @@ struct gb_bootrom_get_vid_pid_response { #define GB_POWER_SUPPLY_USB_CDP_TYPE 0x0006 #define GB_POWER_SUPPLY_USB_ACA_TYPE 0x0007 -/* Should match up with power supply health in linux/power_supply.h */ +/* Greybus power supply health values */ #define GB_POWER_SUPPLY_HEALTH_UNKNOWN 0x0000 #define GB_POWER_SUPPLY_HEALTH_GOOD 0x0001 #define GB_POWER_SUPPLY_HEALTH_OVERHEAT 0x0002 @@ -563,12 +563,12 @@ struct gb_bootrom_get_vid_pid_response { #define GB_POWER_SUPPLY_HEALTH_WATCHDOG_TIMER_EXPIRE 0x0007 #define GB_POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE 0x0008 -/* Should match up with battery status in linux/power_supply.h */ -#define GB_POWER_SUPPLY_STATUS_UNKNOWN 0x0000 -#define GB_POWER_SUPPLY_STATUS_CHARGING 0x0001 -#define GB_POWER_SUPPLY_STATUS_DISCHARGING 0x0002 -#define GB_POWER_SUPPLY_STATUS_NOT_CHARGING 0x0003 -#define GB_POWER_SUPPLY_STATUS_FULL 0x0004 +/* Greybus power supply status values */ +#define GB_POWER_SUPPLY_STATUS_UNKNOWN 0x0000 +#define GB_POWER_SUPPLY_STATUS_CHARGING 0x0001 +#define GB_POWER_SUPPLY_STATUS_DISCHARGING 0x0002 +#define GB_POWER_SUPPLY_STATUS_NOT_CHARGING 0x0003 +#define GB_POWER_SUPPLY_STATUS_FULL 0x0004 struct gb_power_supply_get_supplies_response { __u8 supplies_count; -- cgit v0.10.2 From 7a0d4eae83e7dbabd02c744ec3aa0ed542ed6181 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva <rui.silva@linaro.org> Date: Fri, 15 Jul 2016 12:16:55 +0100 Subject: greybus: power_supply: add missing defines present in the specification Some of the Greybus properties values (capacity level and scope) even though they are defined in the specification were missing from the protocol header. They still match the kernel ones, but they should be present in there for protocol sake. Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org> Reviewed-by: Sandeep Patil <sspatil@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 18c527c..2166909 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -570,6 +570,19 @@ struct gb_bootrom_get_vid_pid_response { #define GB_POWER_SUPPLY_STATUS_NOT_CHARGING 0x0003 #define GB_POWER_SUPPLY_STATUS_FULL 0x0004 +/* Greybus power supply capacity level values */ +#define GB_POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN 0x0000 +#define GB_POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL 0x0001 +#define GB_POWER_SUPPLY_CAPACITY_LEVEL_LOW 0x0002 +#define GB_POWER_SUPPLY_CAPACITY_LEVEL_NORMAL 0x0003 +#define GB_POWER_SUPPLY_CAPACITY_LEVEL_HIGH 0x0004 +#define GB_POWER_SUPPLY_CAPACITY_LEVEL_FULL 0x0005 + +/* Greybus power supply scope values */ +#define GB_POWER_SUPPLY_SCOPE_UNKNOWN 0x0000 +#define GB_POWER_SUPPLY_SCOPE_SYSTEM 0x0001 +#define GB_POWER_SUPPLY_SCOPE_DEVICE 0x0002 + struct gb_power_supply_get_supplies_response { __u8 supplies_count; } __packed; -- cgit v0.10.2 From a0de502ed39663d47b568de27f46971e41f0abdf Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Sat, 16 Jul 2016 09:44:28 -0700 Subject: greybus: audio_topology: Fix compile warning Fix following compile warning by staticizing gb_generate_enum_strings(). greybus/audio_topology.c:134:12: warning: symbol 'gb_generate_enum_strings' was not declared. Should it be static? Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index 487f744..17ba0a0 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -131,8 +131,8 @@ static const char *gbaudio_map_widgetid(struct gbaudio_module_info *module, return NULL; } -const char **gb_generate_enum_strings(struct gbaudio_module_info *gb, - struct gb_audio_enumerated *gbenum) +static const char **gb_generate_enum_strings(struct gbaudio_module_info *gb, + struct gb_audio_enumerated *gbenum) { const char **strings; int i; -- cgit v0.10.2 From 6cc270483c550f1d3f7098bb7fb0de20537947a2 Mon Sep 17 00:00:00 2001 From: Jacopo Mondi <jacopo.mondi@linaro.org> Date: Fri, 15 Jul 2016 11:03:41 +0200 Subject: greybus: camera: Add bpp to Greybus Format description Add the bytes per pixel value to the structure describing a Greybus Protocol Image Format. The bpp information will be used to compute the length in bytes of a line of pixel data Signed-off-by: Jacopo Mondi <jacopo.mondi@linaro.org> Reviewed-by: Gjorgji Rosikopulos <grosikopulos@mm-sol.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index bdceb77..7835ed7 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -74,76 +74,93 @@ struct gb_camera_stream_config { unsigned int max_size; }; -struct gb_camera_fmt_map { +struct gb_camera_fmt_info { enum v4l2_mbus_pixelcode mbus_code; unsigned int gb_format; + unsigned int bpp; }; /* GB format to media code map */ -static const struct gb_camera_fmt_map mbus_to_gbus_format[] = { +static const struct gb_camera_fmt_info gb_fmt_info[] = { { .mbus_code = V4L2_MBUS_FMT_UYVY8_1X16, .gb_format = 0x01, + .bpp = 16, }, { .mbus_code = V4L2_MBUS_FMT_NV12_1x8, .gb_format = 0x12, + .bpp = 12, }, { .mbus_code = V4L2_MBUS_FMT_NV21_1x8, .gb_format = 0x13, + .bpp = 12, }, { .mbus_code = V4L2_MBUS_FMT_YU12_1x8, .gb_format = 0x16, + .bpp = 12, }, { .mbus_code = V4L2_MBUS_FMT_YV12_1x8, .gb_format = 0x17, + .bpp = 12, }, { .mbus_code = V4L2_MBUS_FMT_JPEG_1X8, .gb_format = 0x40, + .bpp = 0, }, { .mbus_code = V4L2_MBUS_FMT_ARA_METADATA_1X8, .gb_format = 0x41, + .bpp = 0, }, { .mbus_code = V4L2_MBUS_FMT_ARA_DEBUG_DATA_1X8, .gb_format = 0x42, + .bpp = 0, }, { .mbus_code = V4L2_MBUS_FMT_SBGGR10_1X10, .gb_format = 0x80, + .bpp = 10, }, { .mbus_code = V4L2_MBUS_FMT_SGBRG10_1X10, .gb_format = 0x81, + .bpp = 10, }, { .mbus_code = V4L2_MBUS_FMT_SGRBG10_1X10, .gb_format = 0x82, + .bpp = 10, }, { .mbus_code = V4L2_MBUS_FMT_SRGGB10_1X10, .gb_format = 0x83, + .bpp = 10, }, { .mbus_code = V4L2_MBUS_FMT_SBGGR12_1X12, .gb_format = 0x84, + .bpp = 12, }, { .mbus_code = V4L2_MBUS_FMT_SGBRG12_1X12, .gb_format = 0x85, + .bpp = 12, }, { .mbus_code = V4L2_MBUS_FMT_SGRBG12_1X12, .gb_format = 0x86, + .bpp = 12, }, { .mbus_code = V4L2_MBUS_FMT_SRGGB12_1X12, .gb_format = 0x87, + .bpp = 12, }, }; @@ -615,22 +632,22 @@ static unsigned int gb_camera_mbus_to_gb(enum v4l2_mbus_pixelcode mbus_code) { unsigned int i; - for (i = 0; i < ARRAY_SIZE(mbus_to_gbus_format); i++) { - if (mbus_to_gbus_format[i].mbus_code == mbus_code) - return mbus_to_gbus_format[i].gb_format; + for (i = 0; i < ARRAY_SIZE(gb_fmt_info); i++) { + if (gb_fmt_info[i].mbus_code == mbus_code) + return gb_fmt_info[i].gb_format; } - return mbus_to_gbus_format[0].gb_format; + return gb_fmt_info[0].gb_format; } static enum v4l2_mbus_pixelcode gb_camera_gb_to_mbus(u16 gb_fmt) { unsigned int i; - for (i = 0; i < ARRAY_SIZE(mbus_to_gbus_format); i++) { - if (mbus_to_gbus_format[i].gb_format == gb_fmt) - return mbus_to_gbus_format[i].mbus_code; + for (i = 0; i < ARRAY_SIZE(gb_fmt_info); i++) { + if (gb_fmt_info[i].gb_format == gb_fmt) + return gb_fmt_info[i].mbus_code; } - return mbus_to_gbus_format[0].mbus_code; + return gb_fmt_info[0].mbus_code; } static ssize_t gb_camera_op_capabilities(void *priv, char *data, size_t len) -- cgit v0.10.2 From fdf73c00c8872f6f59730955d54b2cdc963e2485 Mon Sep 17 00:00:00 2001 From: Jacopo Mondi <jacopo.mondi@linaro.org> Date: Fri, 15 Jul 2016 11:03:42 +0200 Subject: greybus: camera: Add wrapper for sync operation with flags The greybus operation core synchronous operation call doesn't support operation flags. Create a new synchronous operation wrapper with flags, and modify the capabilities operation implementation to use it. The code could be later moved to the greybus core if other drivers have a similar need. Signed-off-by: Jacopo Mondi <jacopo.mondi@linaro.org> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 7835ed7..9d9746f 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -173,6 +173,41 @@ static const struct gb_camera_fmt_info gb_fmt_info[] = { #define gcam_info(gcam, format...) dev_info(&gcam->bundle->dev, format) #define gcam_err(gcam, format...) dev_err(&gcam->bundle->dev, format) +static int gb_camera_operation_sync_flags(struct gb_connection *connection, + int type, unsigned int flags, + void *request, size_t request_size, + void *response, size_t *response_size) +{ + struct gb_operation *operation; + int ret; + + operation = gb_operation_create_flags(connection, type, request_size, + *response_size, flags, + GFP_KERNEL); + if (!operation) + return -ENOMEM; + + if (request_size) + memcpy(operation->request->payload, request, request_size); + + ret = gb_operation_request_send_sync(operation); + if (ret) { + dev_err(&connection->hd->dev, + "%s: synchronous operation of type 0x%02x failed: %d\n", + connection->name, type, ret); + } else { + *response_size = operation->response->payload_size; + + if (operation->response->payload_size) + memcpy(response, operation->response->payload, + operation->response->payload_size); + } + + gb_operation_put(operation); + + return ret; +} + /* ----------------------------------------------------------------------------- * Hardware Configuration */ @@ -347,7 +382,6 @@ static void gb_camera_teardown_data_connection(struct gb_camera *gcam) static int gb_camera_capabilities(struct gb_camera *gcam, u8 *capabilities, size_t *size) { - struct gb_operation *op = NULL; int ret; ret = gb_pm_runtime_get_sync(gcam->bundle); @@ -361,28 +395,16 @@ static int gb_camera_capabilities(struct gb_camera *gcam, goto done; } - op = gb_operation_create_flags(gcam->connection, - GB_CAMERA_TYPE_CAPABILITIES, 0, *size, - GB_OPERATION_FLAG_SHORT_RESPONSE, - GFP_KERNEL); - if (!op) { - ret = -ENOMEM; - goto done; - } - - ret = gb_operation_request_send_sync(op); - if (ret) { + ret = gb_camera_operation_sync_flags(gcam->connection, + GB_CAMERA_TYPE_CAPABILITIES, + GB_OPERATION_FLAG_SHORT_RESPONSE, + NULL, 0, + (void *)capabilities, size); + if (ret) gcam_err(gcam, "failed to retrieve capabilities: %d\n", ret); - goto done; - } - - memcpy(capabilities, op->response->payload, op->response->payload_size); - *size = op->response->payload_size; done: mutex_unlock(&gcam->mutex); - if (op) - gb_operation_put(op); gb_pm_runtime_put_autosuspend(gcam->bundle); -- cgit v0.10.2 From 24f9a6e4942d7a8b15a1bac9a96a605a433b9478 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Date: Fri, 15 Jul 2016 11:03:43 +0200 Subject: greybus: camera: Hardcode the APB-A CSI-2 TX parameters Camera modules will stop reporting the number of lines per second, hardcode the parameter in the driver until the APB-A CSI-2 TX configuration protocol gets updated as well to use a more appropriate form of bandwidth information. The number of data lanes is also hardcoded as it should not depend on the module's CSI-2 bus configuration. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 9d9746f..ceffe14 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -277,6 +277,13 @@ struct ap_csi_config_request { __le32 lines_per_second; } __packed; +/* + * TODO: Compute the number of lanes dynamically based on bandwidth + * requirements. + */ +#define GB_CAMERA_CSI_NUM_DATA_LANES 4 +#define GB_CAMERA_LINES_PER_SECOND (1280 * 30) + static int gb_camera_setup_data_connection(struct gb_camera *gcam, const struct gb_camera_configure_streams_response *resp, struct gb_camera_csi_params *csi_params) @@ -308,8 +315,8 @@ static int gb_camera_setup_data_connection(struct gb_camera *gcam, goto error_conn_disable; /* - * Configure the APB1 CSI transmitter using the lines count reported by - * the camera module, but with hard-coded bus frequency and lanes number. + * Configure the APB1 CSI transmitter with hard-coded bus frequency, + * lanes number and lines per second. * * TODO: use the clocking and size informations reported by camera module * to compute the required CSI bandwidth, and configure the CSI receiver @@ -318,9 +325,9 @@ static int gb_camera_setup_data_connection(struct gb_camera *gcam, memset(&csi_cfg, 0, sizeof(csi_cfg)); csi_cfg.csi_id = 1; csi_cfg.flags = 0; - csi_cfg.num_lanes = resp->num_lanes; + csi_cfg.num_lanes = GB_CAMERA_CSI_NUM_DATA_LANES; csi_cfg.bus_freq = cpu_to_le32(960000000); - csi_cfg.lines_per_second = resp->lines_per_second; + csi_cfg.lines_per_second = GB_CAMERA_LINES_PER_SECOND; ret = gb_hd_output(gcam->connection->hd, &csi_cfg, sizeof(csi_cfg), @@ -335,7 +342,6 @@ static int gb_camera_setup_data_connection(struct gb_camera *gcam, csi_params->num_lanes = csi_cfg.num_lanes; /* Transmitting two bits per cycle. (DDR clock) */ csi_params->clk_freq = csi_cfg.bus_freq / 2; - csi_params->lines_per_second = csi_cfg.lines_per_second; } return 0; -- cgit v0.10.2 From d165a618a14c8871f8e14090791298e1b2ef8231 Mon Sep 17 00:00:00 2001 From: Jacopo Mondi <jacopo.mondi@linaro.org> Date: Fri, 15 Jul 2016 11:03:44 +0200 Subject: greybus: camera: Update Configure Streams Response As camera specification gets updated, and Configure Stream Response payload modified, define here the new response structure. In order to not break non up-to-date camera modules, keep the existing structure and add the _deprecated suffix to it. Add the size of both new and old structure in order to discriminate dynamically which version of Camera Specification the camera module implements and translate deprecated version of configure_streams response in the new one. In order not to break camera functionalities, for testing purposes, hard-code values the APB-A CSI Tx driver still requires for proper interface configuration (lines_per_second and num_lanes) Testing Done: Preview, capture and video recording with white camera module and APB-A with legacy firmware implementations Signed-off-by: Jacopo Mondi <jacopo.mondi@linaro.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index ceffe14..9cf0d4d 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -164,6 +164,18 @@ static const struct gb_camera_fmt_info gb_fmt_info[] = { }, }; +static const struct gb_camera_fmt_info *gb_camera_get_format_info(u16 gb_fmt) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(gb_fmt_info); i++) { + if (gb_fmt_info[i].gb_format == gb_fmt) + return &gb_fmt_info[i]; + } + + return NULL; +} + #define ES2_APB_CDSI0_CPORT 16 #define ES2_APB_CDSI1_CPORT 17 @@ -208,6 +220,130 @@ static int gb_camera_operation_sync_flags(struct gb_connection *connection, return ret; } +/* + * Temporary support for camera modules implementing legacy version + * of camera specifications + */ +static int gb_camera_configure_stream_translate_deprecated( + struct gb_camera *gcam, + void *module_resp, + struct gb_camera_configure_streams_response *resp) +{ + unsigned int i; + struct gb_camera_configure_streams_response_deprecated *dresp = + (struct gb_camera_configure_streams_response_deprecated *) + module_resp; + + if (dresp->padding != 0) { + gcam_err(gcam, "legacy response padding != 0\n"); + return -EIO; + } + + resp->num_streams = dresp->num_streams; + resp->flags = dresp->flags; + resp->data_rate = dresp->bus_freq; + + for (i = 0; i < dresp->num_streams; i++) { + const struct gb_camera_fmt_info *fmt_info; + struct gb_camera_stream_config_response *cfg; + + if (dresp->config[i].padding || + dresp->config[i].max_pkt_size) { + gcam_err(gcam, "legacy stream #%u padding != 0\n", i); + return -EIO; + } + + resp->config[i] = dresp->config[i]; + cfg = &resp->config[i]; + + /* + * As implementations of legacy version of camera protocol do + * not provide the max_pkt_size attribute, re-calculate it on + * AP side. + */ + fmt_info = gb_camera_get_format_info(cfg->format); + if (!fmt_info) { + gcam_err(gcam, "unsupported greybus image format %d\n", + cfg->format); + return -EIO; + } + + if (fmt_info->bpp == 0) { + cfg->max_pkt_size = cpu_to_le16(4096); + } else if (fmt_info->bpp > 0) { + unsigned int width = le16_to_cpu(cfg->width); + + cfg->max_pkt_size = cpu_to_le32(width * fmt_info->bpp / 8); + } + } + + return 0; +} + +/* + * Validate the stream configuration response verifying padding is correctly + * set and the returned number of streams is supported + * + * FIXME: The function also checks which protocol version the camera module + * implements and if it supports or not the new bandwidth requirements + * definition parameters. + * In case the camera implements the legacy version of protocol + * specifications, it gets translated to the new one. + */ +static int gb_camera_configure_streams_validate_response( + struct gb_camera *gcam, + void *module_resp, + struct gb_camera_configure_streams_response *ap_resp, + unsigned int resp_size, + unsigned int nstreams) +{ + struct gb_camera_configure_streams_response *resp; + unsigned int i; + unsigned int module_resp_size = + resp_size - + sizeof(struct gb_camera_stream_config_response) * + nstreams; + + /* TODO: remove support for legacy camera modules */ + if (module_resp_size == GB_CAMERA_CONFIGURE_STREAMS_DEPRECATED_SIZE) + return gb_camera_configure_stream_translate_deprecated(gcam, + module_resp, ap_resp); + + if (module_resp_size != GB_CAMERA_CONFIGURE_STREAMS_SIZE) { + gcam_err(gcam, "unrecognized protocol version %u\n", + module_resp_size); + return -EIO; + } + + resp = (struct gb_camera_configure_streams_response *) module_resp; + *ap_resp = *resp; + + /* Validate the returned response structure */ + if (ap_resp->padding[0] || ap_resp->padding[1]) { + gcam_err(gcam, "response padding != 0\n"); + return -EIO; + } + + if (ap_resp->num_streams > nstreams) { + gcam_err(gcam, "got #streams %u > request %u\n", + resp->num_streams, nstreams); + return -EIO; + } + + for (i = 0; i < ap_resp->num_streams; i++) { + struct gb_camera_stream_config_response *cfg = &resp->config[i]; + + if (cfg->padding) { + gcam_err(gcam, "stream #%u padding != 0\n", i); + return -EIO; + } + + ap_resp->config[i] = *cfg; + } + + return 0; +} + /* ----------------------------------------------------------------------------- * Hardware Configuration */ @@ -318,9 +454,10 @@ static int gb_camera_setup_data_connection(struct gb_camera *gcam, * Configure the APB1 CSI transmitter with hard-coded bus frequency, * lanes number and lines per second. * - * TODO: use the clocking and size informations reported by camera module - * to compute the required CSI bandwidth, and configure the CSI receiver - * on AP side, and the CSI transmitter on APB1 side accordingly. + * TODO: Use the data rate and size information reported by camera + * module to compute the required CSI bandwidth, and configure the + * CSI receiver on AP side, and the CSI transmitter on APB1 side + * accordingly. */ memset(&csi_cfg, 0, sizeof(csi_cfg)); csi_cfg.csi_id = 1; @@ -425,10 +562,12 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, { struct gb_camera_configure_streams_request *req; struct gb_camera_configure_streams_response *resp; + void *module_resp; unsigned int nstreams = *num_streams; unsigned int i; size_t req_size; size_t resp_size; + size_t module_resp_size; int ret; if (nstreams > GB_CAMERA_MAX_STREAMS) @@ -437,11 +576,21 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, req_size = sizeof(*req) + nstreams * sizeof(req->config[0]); resp_size = sizeof(*resp) + nstreams * sizeof(resp->config[0]); + /* + * FIXME: Reserve enough space for the deprecated version of the + * configure_stream response, as it is bigger than the + * newly defined one + */ + module_resp_size = GB_CAMERA_CONFIGURE_STREAMS_DEPRECATED_SIZE + + nstreams * sizeof(resp->config[0]); + req = kmalloc(req_size, GFP_KERNEL); resp = kmalloc(resp_size, GFP_KERNEL); - if (!req || !resp) { + module_resp = kmalloc(module_resp_size, GFP_KERNEL); + if (!req || !resp || !module_resp) { kfree(req); kfree(resp); + kfree(module_resp); return -ENOMEM; } @@ -469,24 +618,18 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, goto done; } - ret = gb_operation_sync(gcam->connection, - GB_CAMERA_TYPE_CONFIGURE_STREAMS, - req, req_size, resp, resp_size); + ret = gb_camera_operation_sync_flags(gcam->connection, + GB_CAMERA_TYPE_CONFIGURE_STREAMS, + GB_OPERATION_FLAG_SHORT_RESPONSE, + req, req_size, + module_resp, &module_resp_size); if (ret < 0) goto done; - if (resp->num_streams > nstreams) { - gcam_dbg(gcam, "got #streams %u > request %u\n", - resp->num_streams, nstreams); - ret = -EIO; - goto done; - } - - if (resp->padding != 0) { - gcam_dbg(gcam, "response padding != 0"); - ret = -EIO; + ret = gb_camera_configure_streams_validate_response(gcam, + module_resp, resp, module_resp_size, nstreams); + if (ret < 0) goto done; - } *flags = resp->flags; *num_streams = resp->num_streams; @@ -501,12 +644,6 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, streams[i].dt[0] = cfg->data_type[0]; streams[i].dt[1] = cfg->data_type[1]; streams[i].max_size = le32_to_cpu(cfg->max_size); - - if (cfg->padding[0] || cfg->padding[1] || cfg->padding[2]) { - gcam_dbg(gcam, "stream #%u padding != 0", i); - ret = -EIO; - goto done; - } } if ((resp->flags & GB_CAMERA_CONFIGURE_STREAMS_ADJUSTED) || @@ -557,6 +694,7 @@ done_skip_pm_put: mutex_unlock(&gcam->mutex); kfree(req); kfree(resp); + kfree(module_resp); return ret; } diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 2166909..178ec89 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -1706,20 +1706,31 @@ struct gb_camera_stream_config_response { __le16 format; __u8 virtual_channel; __u8 data_type[2]; - __u8 padding[3]; + __le16 max_pkt_size; + __u8 padding; __le32 max_size; } __packed; -struct gb_camera_configure_streams_response { +struct gb_camera_configure_streams_response_deprecated { __u8 num_streams; __u8 flags; -#define GB_CAMERA_CONFIGURE_STREAMS_ADJUSTED 0x01 __u8 num_lanes; __u8 padding; __le32 bus_freq; __le32 lines_per_second; struct gb_camera_stream_config_response config[0]; } __packed; +#define GB_CAMERA_CONFIGURE_STREAMS_DEPRECATED_SIZE 12 + +struct gb_camera_configure_streams_response { + __u8 num_streams; +#define GB_CAMERA_CONFIGURE_STREAMS_ADJUSTED 0x01 + __u8 flags; + __u8 padding[2]; + __le32 data_rate; + struct gb_camera_stream_config_response config[0]; +}; +#define GB_CAMERA_CONFIGURE_STREAMS_SIZE 8 /* Greybus Camera Capture request payload - response has no payload */ struct gb_camera_capture_request { -- cgit v0.10.2 From f88b94ec2a3b37e8f9fd20f8fb17d9e0a104fe1f Mon Sep 17 00:00:00 2001 From: Jacopo Mondi <jacopo.mondi@linaro.org> Date: Fri, 15 Jul 2016 11:03:45 +0200 Subject: greybus: camera: Configure APB-A with new params Update the configuration supplied to APB-A to use new parameters, while keeping compatibility with legacy camera modules. Substitute hard-coded clock frequency with information provided by camera module, and retrieve the maximum CSI Long Packet length from the returned stream configuration. This patch requires APB-A csi-tx driver to be updated to comply with newly defined bandwidth requirements. Testing Done: preview, capture and video recording with updated csi-tx driver on APB-A side, and legacy white camera module firmware Signed-off-by: Jacopo Mondi <jacopo.mondi@linaro.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 9cf0d4d..e0719e2 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -220,6 +220,50 @@ static int gb_camera_operation_sync_flags(struct gb_connection *connection, return ret; } +static int gb_camera_get_max_pkt_size(struct gb_camera *gcam, + struct gb_camera_configure_streams_response *resp) +{ + unsigned int max_pkt_size = 0; + unsigned int i; + + for (i = 0; i < resp->num_streams; i++) { + struct gb_camera_stream_config_response *cfg = &resp->config[i]; + const struct gb_camera_fmt_info *fmt_info; + unsigned int pkt_size; + + fmt_info = gb_camera_get_format_info(cfg->format); + if (!fmt_info) { + gcam_err(gcam, "unsupported greybus image format: %d\n", + cfg->format); + return -EIO; + } + + if (fmt_info->bpp == 0) { + pkt_size = le32_to_cpu(cfg->max_pkt_size); + + if (pkt_size == 0) { + gcam_err(gcam, + "Stream %u: invalid zero maximum packet size\n", + i); + return -EIO; + } + } else { + pkt_size = le16_to_cpu(cfg->width) * fmt_info->bpp / 8; + + if (pkt_size != le32_to_cpu(cfg->max_pkt_size)) { + gcam_err(gcam, + "Stream %u: maximum packet size mismatch (%u/%u)\n", + i, pkt_size, cfg->max_pkt_size); + return -EIO; + } + } + + max_pkt_size = max(pkt_size, max_pkt_size); + } + + return max_pkt_size; +} + /* * Temporary support for camera modules implementing legacy version * of camera specifications @@ -409,8 +453,8 @@ struct ap_csi_config_request { #define GB_CAMERA_CSI_FLAG_CLOCK_CONTINUOUS 0x01 __u8 num_lanes; __u8 padding; - __le32 bus_freq; - __le32 lines_per_second; + __le32 csi_clk_freq; + __le32 max_pkt_size; } __packed; /* @@ -418,14 +462,18 @@ struct ap_csi_config_request { * requirements. */ #define GB_CAMERA_CSI_NUM_DATA_LANES 4 -#define GB_CAMERA_LINES_PER_SECOND (1280 * 30) + +#define GB_CAMERA_CSI_CLK_FREQ_MAX 999000000U +#define GB_CAMERA_CSI_CLK_FREQ_MIN 100000000U +#define GB_CAMERA_CSI_CLK_FREQ_MARGIN 150000000U static int gb_camera_setup_data_connection(struct gb_camera *gcam, - const struct gb_camera_configure_streams_response *resp, + struct gb_camera_configure_streams_response *resp, struct gb_camera_csi_params *csi_params) { struct ap_csi_config_request csi_cfg; struct gb_connection *conn; + unsigned int clk_freq; int ret; /* @@ -451,34 +499,40 @@ static int gb_camera_setup_data_connection(struct gb_camera *gcam, goto error_conn_disable; /* - * Configure the APB1 CSI transmitter with hard-coded bus frequency, - * lanes number and lines per second. + * Configure the APB-A CSI-2 transmitter. * - * TODO: Use the data rate and size information reported by camera - * module to compute the required CSI bandwidth, and configure the - * CSI receiver on AP side, and the CSI transmitter on APB1 side - * accordingly. + * Hardcode the number of lanes to 4 and compute the bus clock frequency + * based on the module bandwidth requirements with a safety margin. */ memset(&csi_cfg, 0, sizeof(csi_cfg)); csi_cfg.csi_id = 1; csi_cfg.flags = 0; csi_cfg.num_lanes = GB_CAMERA_CSI_NUM_DATA_LANES; - csi_cfg.bus_freq = cpu_to_le32(960000000); - csi_cfg.lines_per_second = GB_CAMERA_LINES_PER_SECOND; + + clk_freq = resp->data_rate / 2 / GB_CAMERA_CSI_NUM_DATA_LANES; + clk_freq = clamp(clk_freq + GB_CAMERA_CSI_CLK_FREQ_MARGIN, + GB_CAMERA_CSI_CLK_FREQ_MIN, + GB_CAMERA_CSI_CLK_FREQ_MAX); + csi_cfg.csi_clk_freq = clk_freq; + + ret = gb_camera_get_max_pkt_size(gcam, resp); + if (ret < 0) { + ret = -EIO; + goto error_power; + } + csi_cfg.max_pkt_size = ret; ret = gb_hd_output(gcam->connection->hd, &csi_cfg, sizeof(csi_cfg), GB_APB_REQUEST_CSI_TX_CONTROL, false); - if (ret < 0) { gcam_err(gcam, "failed to start the CSI transmitter\n"); goto error_power; } if (csi_params) { + csi_params->clk_freq = csi_cfg.csi_clk_freq; csi_params->num_lanes = csi_cfg.num_lanes; - /* Transmitting two bits per cycle. (DDR clock) */ - csi_params->clk_freq = csi_cfg.bus_freq / 2; } return 0; @@ -664,29 +718,31 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, gb_pm_runtime_put_noidle(gcam->bundle); } - if (resp->num_streams) { - /* - * Make sure the bundle won't be suspended until streams get - * unconfigured after the stream is configured successfully - */ - gb_pm_runtime_get_noresume(gcam->bundle); - - ret = gb_camera_setup_data_connection(gcam, resp, csi_params); - if (ret < 0) { - memset(req, 0, sizeof(*req)); - gb_operation_sync(gcam->connection, - GB_CAMERA_TYPE_CONFIGURE_STREAMS, - req, sizeof(*req), - resp, sizeof(*resp)); - *flags = 0; - *num_streams = 0; - gb_pm_runtime_put_noidle(gcam->bundle); - goto done; - } + if (resp->num_streams == 0) + goto done; + + /* + * Make sure the bundle won't be suspended until streams get + * unconfigured after the stream is configured successfully + */ + gb_pm_runtime_get_noresume(gcam->bundle); - gcam->state = GB_CAMERA_STATE_CONFIGURED; + /* Setup CSI-2 connection from APB-A to AP */ + ret = gb_camera_setup_data_connection(gcam, resp, csi_params); + if (ret < 0) { + memset(req, 0, sizeof(*req)); + gb_operation_sync(gcam->connection, + GB_CAMERA_TYPE_CONFIGURE_STREAMS, + req, sizeof(*req), + resp, sizeof(*resp)); + *flags = 0; + *num_streams = 0; + gb_pm_runtime_put_noidle(gcam->bundle); + goto done; } + gcam->state = GB_CAMERA_STATE_CONFIGURED; + done: gb_pm_runtime_put_autosuspend(gcam->bundle); -- cgit v0.10.2 From 433aa123f51b85b5ad8fb2f088a6365d54e2763b Mon Sep 17 00:00:00 2001 From: Jacopo Mondi <jacopo.mondi@linaro.org> Date: Fri, 15 Jul 2016 11:03:46 +0200 Subject: greybus: camera: Update CSI config parameters Remove lines_per_second parameter from csi configuration structure as VFE driver dropped dependency on it Signed-off-by: Jacopo Mondi <jacopo.mondi@linaro.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/gb-camera.h b/drivers/staging/greybus/gb-camera.h index b8651ed..d45dabc 100644 --- a/drivers/staging/greybus/gb-camera.h +++ b/drivers/staging/greybus/gb-camera.h @@ -41,13 +41,10 @@ struct gb_camera_stream { * struct gb_camera_csi_params - CSI configuration parameters * @num_lanes: number of CSI data lanes * @clk_freq: CSI clock frequency in Hz - * @lines_per_second: Total number of lines in a second of transmission - * (blanking included) */ struct gb_camera_csi_params { unsigned int num_lanes; unsigned int clk_freq; - unsigned int lines_per_second; }; /** -- cgit v0.10.2 From 6a1d29595ed7af5aebbcdb8f4cc045ae7893dc6c Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Mon, 18 Jul 2016 14:59:36 +0100 Subject: greybus: greybus_protocols.h/es2: Ensure __le32 is used not u32 There is a dangling u32 in es2/greybus_protocols.h that is only obvious when you try to compile up gbsim. We need to do a cpu_to_le32 and declare the 32-bit int in the header as __le32. This patch does that and splits out the assignment of the req->flags parameter to a temporary variable to allow for later printing. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Suggested-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index f64dbcb..afc2d6c 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -690,19 +690,23 @@ static int cport_enable(struct gb_host_device *hd, u16 cport_id, struct es2_ap_dev *es2 = hd_to_es2(hd); struct usb_device *udev = es2->usb_dev; struct gb_apb_request_cport_flags *req; + u32 connection_flags; int ret; req = kzalloc(sizeof(*req), GFP_KERNEL); if (!req) return -ENOMEM; + connection_flags = 0; if (flags & GB_CONNECTION_FLAG_CONTROL) - req->flags |= GB_APB_CPORT_FLAG_CONTROL; + connection_flags |= GB_APB_CPORT_FLAG_CONTROL; if (flags & GB_CONNECTION_FLAG_HIGH_PRIO) - req->flags |= GB_APB_CPORT_FLAG_HIGH_PRIO; + connection_flags |= GB_APB_CPORT_FLAG_HIGH_PRIO; + + req->flags = cpu_to_le32(connection_flags); dev_dbg(&hd->dev, "%s - cport = %u, flags = %02x\n", __func__, - cport_id, req->flags); + cport_id, connection_flags); ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), GB_APB_REQUEST_CPORT_FLAGS, diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 178ec89..d39a580 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -272,7 +272,7 @@ struct gb_control_intf_pm_response { #define APBA_REQUEST_ARPC_RUN 0x12 struct gb_apb_request_cport_flags { - u32 flags; + __le32 flags; #define GB_APB_CPORT_FLAG_CONTROL 0x01 #define GB_APB_CPORT_FLAG_HIGH_PRIO 0x02 } __packed; -- cgit v0.10.2 From 1455db9e1ba3f602084854fa9c222e9b68e8576c Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Mon, 18 Jul 2016 14:59:37 +0100 Subject: greybus: greybus_protocols.h: convert __u32 to __le32 All 32 bit declarations associated with data interchange to the greybus network need to be declared explicitly as little-endian since that is the byte order we use on the greybus network. struct gb_audio_topology is declaring its variables as u32. Fortunately this structure isn't currently used so we can do a conversion from u32 to __le32 without any ancillary code-churn. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index d39a580..1966136 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -2161,10 +2161,10 @@ struct gb_audio_topology { __u8 num_controls; __u8 num_widgets; __u8 num_routes; - __u32 size_dais; - __u32 size_controls; - __u32 size_widgets; - __u32 size_routes; + __le32 size_dais; + __le32 size_controls; + __le32 size_widgets; + __le32 size_routes; /* * struct gb_audio_dai dai[num_dais]; * struct gb_audio_control controls[num_controls]; -- cgit v0.10.2 From 52764bd8aac77dd8ddbdaf55ae896a55ab2a9f5e Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Tue, 19 Jul 2016 01:56:49 +0100 Subject: greybus: timesync: Bugfix ping should not result in -EAGAIN gb_timesync_schedule_synchronous() is currently making a synchronous FrameTime synchronization happen. It does a wait_event_interruptible() and then goes to check the status of the state-machine. Occasionally the state indicates PING - which is a completely valid state and should result in a result code of 0 not -EAGAIN. This patch fixes by making __gb_timesync_get_status() return 0 instead of -EAGAIN for the PING state. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Tested-by: David Lin <dtwlin@google.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/timesync.c b/drivers/staging/greybus/timesync.c index 14531ed..ddbdf2b 100644 --- a/drivers/staging/greybus/timesync.c +++ b/drivers/staging/greybus/timesync.c @@ -462,9 +462,9 @@ static int __gb_timesync_get_status(struct gb_timesync_svc *timesync_svc) case GB_TIMESYNC_STATE_INIT: case GB_TIMESYNC_STATE_WAIT_SVC: case GB_TIMESYNC_STATE_AUTHORITATIVE: - case GB_TIMESYNC_STATE_PING: ret = -EAGAIN; break; + case GB_TIMESYNC_STATE_PING: case GB_TIMESYNC_STATE_ACTIVE: ret = 0; break; -- cgit v0.10.2 From 56c78715eaaeba41317a82dc91a037cbbea16736 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Sat, 16 Jul 2016 09:57:30 -0700 Subject: greybus: bootrom: Use "s2l" instead of boot stage in package name The S3 firmware and S3-BFU firmware images will be named like this going forward: S3: ara_00000126_00001001_fffe0001_ffe70018_s3f.tftf S3-BFU: ara_00000126_00001001_fffe0001_ffe70018_s3_bfu.tftf But the current naming for S2 loader image is: ara_00000126_00001001_fffe0001_ffe70018_02.tftf It makes sense to use similar encoding for all three packages and so it should be named as: ara_00000126_00001001_fffe0001_ffe70018_s2l.tftf Because the boot stage is passed from ES3 bootrom, we can't change its value now. But the string created to match the package name is created in bootrom.c and that is the only string we create from bootrom.c. Update bootrom.c to use "s2l" instead of "02" in the package name. Compile Tested only. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Tested-by: Karthik Ravi Shankar <karthikrs@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/bootrom.c b/drivers/staging/greybus/bootrom.c index 84537a0..6881841 100644 --- a/drivers/staging/greybus/bootrom.c +++ b/drivers/staging/greybus/bootrom.c @@ -138,21 +138,28 @@ static int download_firmware(struct gb_bootrom *bootrom, u8 stage) { struct gb_connection *connection = bootrom->connection; struct gb_interface *intf = connection->bundle->intf; - char firmware_name[48]; + char firmware_name[49]; int rc; /* Already have a firmware, free it */ free_firmware(bootrom); + /* Bootrom protocol is only supported for loading Stage 2 firmware */ + if (stage != 2) { + dev_err(&connection->bundle->dev, "Invalid boot stage: %u\n", + stage); + return -EINVAL; + } + /* * Create firmware name * * XXX Name it properly.. */ snprintf(firmware_name, sizeof(firmware_name), - "ara_%08x_%08x_%08x_%08x_%02x.tftf", + "ara_%08x_%08x_%08x_%08x_s2l.tftf", intf->ddbl1_manufacturer_id, intf->ddbl1_product_id, - intf->vendor_id, intf->product_id, stage); + intf->vendor_id, intf->product_id); // FIXME: // Turn to dev_dbg later after everyone has valid bootloaders with good -- cgit v0.10.2 From 484a4d667751148654277a3ec93b8f0a327da29d Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva <rui.silva@linaro.org> Date: Tue, 19 Jul 2016 15:41:29 +0100 Subject: greybus: sdio: convert vdd kernel values to greybus We need to convert vdd kernel values to greybus ones. And we get this by shifting the kernel values by 8. Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index 8d2de7d..5e5de04 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -43,6 +43,9 @@ struct gb_sdio_host { #define GB_SDIO_RSP_R1B (GB_SDIO_RSP_PRESENT | GB_SDIO_RSP_CRC | \ GB_SDIO_RSP_OPCODE | GB_SDIO_RSP_BUSY) +/* kernel vdd starts at 0x80 and we need to translate to greybus ones 0x01 */ +#define GB_SDIO_VDD_SHIFT 8 + static inline bool single_op(struct mmc_command *cmd) { uint32_t opcode = cmd->opcode; @@ -574,10 +577,14 @@ static void gb_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) u8 timing; u8 signal_voltage; u8 drv_type; + u32 vdd = 0; mutex_lock(&host->lock); request.clock = cpu_to_le32(ios->clock); - request.vdd = cpu_to_le32(1 << ios->vdd); + + if (ios->vdd) + vdd = 1 << (ios->vdd - GB_SDIO_VDD_SHIFT); + request.vdd = cpu_to_le32(vdd); request.bus_mode = (ios->bus_mode == MMC_BUSMODE_OPENDRAIN ? GB_SDIO_BUSMODE_OPENDRAIN : -- cgit v0.10.2 From d53cc1c37e5a4006fb23df8e54dc4a50e01732d9 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva <rui.silva@linaro.org> Date: Tue, 19 Jul 2016 15:41:30 +0100 Subject: greybus: sdio: add switch voltage operation Core sd/mmc needs the start_signal_voltage_switch operation to be defined to issue a voltage switch command. So, we define it here even though we do not need to take in action on it, since all voltage control is done in the Module. Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index 5e5de04..ad448c6 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -734,11 +734,17 @@ static int gb_mmc_get_cd(struct mmc_host *mmc) return host->card_present; } +static int gb_mmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios) +{ + return 0; +} + static const struct mmc_host_ops gb_sdio_ops = { .request = gb_mmc_request, .set_ios = gb_mmc_set_ios, .get_ro = gb_mmc_get_ro, .get_cd = gb_mmc_get_cd, + .start_signal_voltage_switch = gb_mmc_switch_voltage, }; static int gb_sdio_probe(struct gbphy_device *gbphy_dev, -- cgit v0.10.2 From 042fd749abab492ae02452cf675f7bc146814955 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Tue, 19 Jul 2016 17:21:27 +0200 Subject: greybus: connection: drop the svc quiescing operation Connection tear down is being reworked, and the SVC quiescing operation is going away. Let's remove this operation now along with the coupled second ping from our intermediate tear down implementation. This both avoids unnecessary noise in the logs resulting from the fact that the SVC side of the quiescing operation was never merged, and speeds up connection tear down slightly. Testing done: Tested on EVT2 using runtime PM. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Acked-by: Sandeep Patil <sspatil@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 174a52d..634c8b1 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -417,21 +417,6 @@ gb_connection_svc_connection_destroy(struct gb_connection *connection) connection->intf_cport_id); } -static void -gb_connection_svc_connection_quiescing(struct gb_connection *connection) -{ - struct gb_host_device *hd = connection->hd; - - if (gb_connection_is_static(connection)) - return; - - gb_svc_connection_quiescing(hd->svc, - hd->svc->ap_intf_id, - connection->hd_cport_id, - connection->intf->interface_id, - connection->intf_cport_id); -} - /* Inform Interface about active CPorts */ static int gb_connection_control_connected(struct gb_connection *connection) { @@ -686,8 +671,6 @@ err_control_disconnecting: gb_connection_ping(connection); gb_connection_hd_cport_features_disable(connection); - gb_connection_svc_connection_quiescing(connection); - gb_connection_ping(connection); gb_connection_control_disconnected(connection); connection->state = GB_CONNECTION_STATE_DISABLED; err_svc_connection_destroy: @@ -795,8 +778,6 @@ void gb_connection_disable(struct gb_connection *connection) gb_connection_ping(connection); gb_connection_hd_cport_features_disable(connection); - gb_connection_svc_connection_quiescing(connection); - gb_connection_ping(connection); gb_connection_control_disconnected(connection); diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 1966136..c7fcb85 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -1036,7 +1036,6 @@ struct gb_spi_transfer_response { #define GB_SVC_TYPE_TIMESYNC_WAKE_PINS_ACQUIRE 0x18 #define GB_SVC_TYPE_TIMESYNC_WAKE_PINS_RELEASE 0x19 #define GB_SVC_TYPE_TIMESYNC_PING 0x1a -#define GB_SVC_TYPE_CONN_QUIESCING 0x1e #define GB_SVC_TYPE_MODULE_INSERTED 0x1f #define GB_SVC_TYPE_MODULE_REMOVED 0x20 #define GB_SVC_TYPE_INTF_VSYS_ENABLE 0x21 @@ -1386,17 +1385,6 @@ struct gb_svc_intf_mailbox_event_request { } __packed; /* intf_mailbox_event response has no payload */ -struct gb_svc_conn_quiescing_request { - __u8 intf1_id; - __le16 cport1_id; - __u8 intf2_id; - __le16 cport2_id; -} __packed; - -struct gb_svc_conn_quiescing_response { - __u8 status; -} __packed; - /* RAW */ diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 14bada9..da9bb1f 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -470,37 +470,6 @@ int gb_svc_connection_create(struct gb_svc *svc, } EXPORT_SYMBOL_GPL(gb_svc_connection_create); -void gb_svc_connection_quiescing(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, - u8 intf2_id, u16 cport2_id) -{ - struct gb_svc_conn_quiescing_request request; - struct gb_svc_conn_quiescing_response response; - int ret; - - dev_dbg(&svc->dev, "%s - (%u:%u %u:%u)\n", __func__, - intf1_id, cport1_id, intf2_id, cport2_id); - - request.intf1_id = intf1_id; - request.cport1_id = cpu_to_le16(cport1_id); - request.intf2_id = intf2_id; - request.cport2_id = cpu_to_le16(cport2_id); - - ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_CONN_QUIESCING, - &request, sizeof(request), - &response, sizeof(response)); - if (ret < 0) - return; - if (response.status != GB_SVC_OP_SUCCESS) { - dev_err(&svc->dev, "quiescing connection failed (%u:%u %u:%u): %u\n", - intf1_id, cport1_id, intf2_id, cport2_id, - response.status); - return; - } - - return; -} -EXPORT_SYMBOL_GPL(gb_svc_connection_quiescing); - void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id) { diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index 4ab066b..f632790 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -62,8 +62,6 @@ int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, void gb_svc_route_destroy(struct gb_svc *svc, u8 intf1_id, u8 intf2_id); int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id, u8 cport_flags); -void gb_svc_connection_quiescing(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, - u8 intf2_id, u16 cport2_id); void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id); int gb_svc_intf_eject(struct gb_svc *svc, u8 intf_id); -- cgit v0.10.2 From d29b67d44a7cf6d02e7319c0e5a4b729a0aa00e7 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Date: Tue, 19 Jul 2016 13:31:46 +0530 Subject: greybus: arche-platform: Add support for init-off feature Disable wake_detect interrupt after request As part of SW-4344/SW-7061, now we are enabling FW flashing to all builds. That means check for need of FW upgrade is going to be present in all builds, and moving to FW_FlASHING mode from active is heavy operation; so the idea here is simplify this process and save the boot time due to switching back-n-forth between ACTIVE<=>FW_FLASHING modes. So we decided to put unipro into OFF state by default on boot, which can be changed through DT property. If arche-platform device node has "arche,init-off" property set, then unipro will be in OFF state on boot. User can bring it back by # echo active > /sys/devices/arche_platform*/state And to simply the exit code of probe() fn the arche_platform_coldboot_seq() has been shifted to the bottom of the _probe() fn. Testing Done: Tested on EVT2 platform, with and without "arche,init-off" property, multiple times. Note: I am seeing SW-7128, which is not related to these changes. Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Tested-by: Michael Scott <michael.scott@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index af78420..cbe8bdc 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -672,8 +672,7 @@ static int arche_platform_probe(struct platform_device *pdev) dev_err(dev, "failed to request wake detect IRQ %d\n", ret); return ret; } - - gpio_direction_input(arche_pdata->wake_detect_gpio); + disable_irq(arche_pdata->wake_detect_irq); ret = device_create_file(dev, &dev_attr_state); if (ret) { @@ -681,38 +680,41 @@ static int arche_platform_probe(struct platform_device *pdev) return ret; } - mutex_lock(&arche_pdata->platform_state_mutex); - ret = arche_platform_coldboot_seq(arche_pdata); - if (ret) { - dev_err(dev, "Failed to cold boot svc %d\n", ret); - goto err_coldboot; - } - ret = of_platform_populate(np, NULL, NULL, dev); if (ret) { dev_err(dev, "failed to populate child nodes %d\n", ret); - goto err_populate; + goto err_device_remove; } arche_pdata->pm_notifier.notifier_call = arche_platform_pm_notifier; ret = register_pm_notifier(&arche_pdata->pm_notifier); - mutex_unlock(&arche_pdata->platform_state_mutex); if (ret) { dev_err(dev, "failed to register pm notifier %d\n", ret); - goto err_populate; + goto err_device_remove; } /* Register callback pointer */ arche_platform_change_state_cb = arche_platform_change_state; + /* Explicitly power off if requested */ + if (!of_property_read_bool(pdev->dev.of_node, "arche,init-off")) { + mutex_lock(&arche_pdata->platform_state_mutex); + ret = arche_platform_coldboot_seq(arche_pdata); + if (ret) { + dev_err(dev, "Failed to cold boot svc %d\n", ret); + goto err_coldboot; + } + arche_platform_wd_irq_en(arche_pdata); + mutex_unlock(&arche_pdata->platform_state_mutex); + } + dev_info(dev, "Device registered successfully\n"); return 0; -err_populate: - arche_platform_poweroff_seq(arche_pdata); err_coldboot: mutex_unlock(&arche_pdata->platform_state_mutex); +err_device_remove: device_remove_file(&pdev->dev, &dev_attr_state); return ret; } -- cgit v0.10.2 From 1bb61840c4db64e27f0077dcfc5389e662022d40 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Tue, 19 Jul 2016 15:24:46 +0200 Subject: greybus: interface: add interface-type attribute Add an interface-type string attribute that represents the detected interface type as either "dummy", "unipro", "greybus", or "unknown". Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Sandeep Patil <sspatil@google.com> Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 8605d70..721010e 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -82,6 +82,14 @@ Contact: Greg Kroah-Hartman <greg@kroah.com> Description: The ID of a Greybus interface. +What: /sys/bus/greybus/devices/N-M.I/interface_type +Date: June 2016 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman <greg@kroah.com> +Description: + The type of a Greybus interface; "dummy", "unipro", "greybus", + or "unknown". + What: /sys/bus/greybus/devices/N-M.I/power_now Date: March 2016 KernelVersion: 4.XX diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index b3bd96e..1d50877 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -491,6 +491,27 @@ static ssize_t power_now_show(struct device *dev, } static DEVICE_ATTR_RO(power_now); +static const char *gb_interface_type_string(struct gb_interface *intf) +{ + static const char * const types[] = { + [GB_SVC_INTF_TYPE_UNKNOWN] = "unknown", + [GB_SVC_INTF_TYPE_DUMMY] = "dummy", + [GB_SVC_INTF_TYPE_UNIPRO] = "unipro", + [GB_SVC_INTF_TYPE_GREYBUS] = "greybus", + }; + + return types[intf->type]; +} + +static ssize_t interface_type_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_interface *intf = to_gb_interface(dev); + + return sprintf(buf, "%s\n", gb_interface_type_string(intf)); +} +static DEVICE_ATTR_RO(interface_type); + static struct attribute *interface_attrs[] = { &dev_attr_ddbl1_manufacturer_id.attr, &dev_attr_ddbl1_product_id.attr, @@ -501,6 +522,7 @@ static struct attribute *interface_attrs[] = { &dev_attr_voltage_now.attr, &dev_attr_current_now.attr, &dev_attr_power_now.attr, + &dev_attr_interface_type.attr, NULL, }; ATTRIBUTE_GROUPS(interface); @@ -721,6 +743,8 @@ static int gb_interface_activate_operation(struct gb_interface *intf) return ret; } + intf->type = type; + switch (type) { case GB_SVC_INTF_TYPE_DUMMY: dev_info(&intf->dev, "dummy interface detected\n"); @@ -734,6 +758,7 @@ static int gb_interface_activate_operation(struct gb_interface *intf) break; default: dev_err(&intf->dev, "unknown interface type: %u\n", type); + intf->type = GB_SVC_INTF_TYPE_UNKNOWN; return -ENODEV; } diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 8796c55..05a3909 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -26,6 +26,7 @@ struct gb_interface { u8 interface_id; /* Physical location within the Endo */ u8 device_id; u8 features; /* Feature flags set in the manifest */ + u8 type; u32 ddbl1_manufacturer_id; u32 ddbl1_product_id; -- cgit v0.10.2 From 441ac1fa9ecdccf9d54803e2548464ca83ad8514 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Tue, 19 Jul 2016 15:24:47 +0200 Subject: greybus: interface: partition attribute group Partition the current attribute group into four groups for UniPro, Greybus, power and common attributes. This is a step in refining the interface-type handling as attributes are type dependent. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 1d50877..1d50bd4 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -512,20 +512,55 @@ static ssize_t interface_type_show(struct device *dev, } static DEVICE_ATTR_RO(interface_type); -static struct attribute *interface_attrs[] = { +static struct attribute *interface_unipro_attrs[] = { &dev_attr_ddbl1_manufacturer_id.attr, &dev_attr_ddbl1_product_id.attr, + NULL +}; + +static struct attribute *interface_greybus_attrs[] = { &dev_attr_interface_id.attr, &dev_attr_vendor_id.attr, &dev_attr_product_id.attr, &dev_attr_serial_number.attr, + NULL +}; + +static struct attribute *interface_power_attrs[] = { &dev_attr_voltage_now.attr, &dev_attr_current_now.attr, &dev_attr_power_now.attr, + NULL +}; + +static struct attribute *interface_common_attrs[] = { &dev_attr_interface_type.attr, - NULL, + NULL +}; + +static const struct attribute_group interface_unipro_group = { + .attrs = interface_unipro_attrs, +}; + +static const struct attribute_group interface_greybus_group = { + .attrs = interface_greybus_attrs, +}; + +static const struct attribute_group interface_power_group = { + .attrs = interface_power_attrs, +}; + +static const struct attribute_group interface_common_group = { + .attrs = interface_common_attrs, +}; + +static const struct attribute_group *interface_groups[] = { + &interface_unipro_group, + &interface_greybus_group, + &interface_power_group, + &interface_common_group, + NULL }; -ATTRIBUTE_GROUPS(interface); static void gb_interface_release(struct device *dev) { -- cgit v0.10.2 From 835642526e9310d435cc718cdb69f2fcd7a53b84 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Tue, 19 Jul 2016 15:24:48 +0200 Subject: greybus: interface: make attributes type dependent Make most interface attributes type dependent (e.g only UniPro and Greybus interfaces should have a DDBL1 Manufacturer ID attribute). Note that the power attributes (e.g. current_now) will only be visible for UniPro- and Greybus-type interfaces (i.e. interfaces that can draw power). Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 1d50bd4..c27b18b 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -538,15 +538,62 @@ static struct attribute *interface_common_attrs[] = { NULL }; +static umode_t interface_unipro_is_visible(struct kobject *kobj, + struct attribute *attr, int n) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct gb_interface *intf = to_gb_interface(dev); + + switch (intf->type) { + case GB_SVC_INTF_TYPE_UNIPRO: + case GB_SVC_INTF_TYPE_GREYBUS: + return attr->mode; + default: + return 0; + } +} + +static umode_t interface_greybus_is_visible(struct kobject *kobj, + struct attribute *attr, int n) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct gb_interface *intf = to_gb_interface(dev); + + switch (intf->type) { + case GB_SVC_INTF_TYPE_GREYBUS: + return attr->mode; + default: + return 0; + } +} + +static umode_t interface_power_is_visible(struct kobject *kobj, + struct attribute *attr, int n) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct gb_interface *intf = to_gb_interface(dev); + + switch (intf->type) { + case GB_SVC_INTF_TYPE_UNIPRO: + case GB_SVC_INTF_TYPE_GREYBUS: + return attr->mode; + default: + return 0; + } +} + static const struct attribute_group interface_unipro_group = { + .is_visible = interface_unipro_is_visible, .attrs = interface_unipro_attrs, }; static const struct attribute_group interface_greybus_group = { + .is_visible = interface_greybus_is_visible, .attrs = interface_greybus_attrs, }; static const struct attribute_group interface_power_group = { + .is_visible = interface_power_is_visible, .attrs = interface_power_attrs, }; -- cgit v0.10.2 From c80a982fc1f8b2b1546c4b2acc08ffd543f6f6c5 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Tue, 19 Jul 2016 15:24:49 +0200 Subject: greybus: interface: amend interface registration message Amend the interface registration message with the detected interface type, and only print the Ara VID/PID and DDBL1 attributes for the types for which they exist. Also drop the now redundant message about a detected dummy interface from the activate operation helper. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index c27b18b..22b7342 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -829,7 +829,6 @@ static int gb_interface_activate_operation(struct gb_interface *intf) switch (type) { case GB_SVC_INTF_TYPE_DUMMY: - dev_info(&intf->dev, "dummy interface detected\n"); /* FIXME: handle as an error for now */ return -ENODEV; case GB_SVC_INTF_TYPE_UNIPRO: @@ -1131,10 +1130,20 @@ int gb_interface_add(struct gb_interface *intf) trace_gb_interface_add(intf); - dev_info(&intf->dev, "Interface added: VID=0x%08x, PID=0x%08x\n", - intf->vendor_id, intf->product_id); - dev_info(&intf->dev, "DDBL1 Manufacturer=0x%08x, Product=0x%08x\n", - intf->ddbl1_manufacturer_id, intf->ddbl1_product_id); + dev_info(&intf->dev, "Interface added (%s)\n", + gb_interface_type_string(intf)); + + switch (intf->type) { + case GB_SVC_INTF_TYPE_GREYBUS: + dev_info(&intf->dev, "Ara VID=0x%08x, PID=0x%08x\n", + intf->vendor_id, intf->product_id); + /* fall-through */ + case GB_SVC_INTF_TYPE_UNIPRO: + dev_info(&intf->dev, "DDBL1 Manufacturer=0x%08x, Product=0x%08x\n", + intf->ddbl1_manufacturer_id, + intf->ddbl1_product_id); + break; + } return 0; } -- cgit v0.10.2 From 6633d80afbeecd91d5d786d6fbb32cdb8bc0a567 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Tue, 19 Jul 2016 15:24:50 +0200 Subject: greybus: module: suppress activation error message for dummy interfaces We currently handle dummy interfaces by deactivating them using activation error paths, but we don't want the corresponding module_inserted error message to be printed. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index 7f0ed9f..242be49 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -153,8 +153,11 @@ static void gb_module_register_interface(struct gb_interface *intf) break; } if (ret) { - dev_err(&module->dev, "failed to activate interface %u: %d\n", - intf_id, ret); + if (intf->type != GB_SVC_INTF_TYPE_DUMMY) { + dev_err(&module->dev, + "failed to activate interface %u: %d\n", + intf_id, ret); + } /* * -EAGAIN indicates that the Greybus operation -- cgit v0.10.2 From a212b7586712208804d3d51efa9fdf6e23b2480a Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 20 Jul 2016 16:40:20 +0200 Subject: greybus: interface: use an enum for interface type Use an enum for the interface type instead of using the SVC protocol values directly. Suggested-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Alex Elder <elder@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Sandeep Patil <sspatil@google.com> Reviewed-by: Patrick Titiano <ptitiano@baylibre.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 22b7342..e21491b 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -494,10 +494,11 @@ static DEVICE_ATTR_RO(power_now); static const char *gb_interface_type_string(struct gb_interface *intf) { static const char * const types[] = { - [GB_SVC_INTF_TYPE_UNKNOWN] = "unknown", - [GB_SVC_INTF_TYPE_DUMMY] = "dummy", - [GB_SVC_INTF_TYPE_UNIPRO] = "unipro", - [GB_SVC_INTF_TYPE_GREYBUS] = "greybus", + [GB_INTERFACE_TYPE_INVALID] = "invalid", + [GB_INTERFACE_TYPE_UNKNOWN] = "unknown", + [GB_INTERFACE_TYPE_DUMMY] = "dummy", + [GB_INTERFACE_TYPE_UNIPRO] = "unipro", + [GB_INTERFACE_TYPE_GREYBUS] = "greybus", }; return types[intf->type]; @@ -545,8 +546,8 @@ static umode_t interface_unipro_is_visible(struct kobject *kobj, struct gb_interface *intf = to_gb_interface(dev); switch (intf->type) { - case GB_SVC_INTF_TYPE_UNIPRO: - case GB_SVC_INTF_TYPE_GREYBUS: + case GB_INTERFACE_TYPE_UNIPRO: + case GB_INTERFACE_TYPE_GREYBUS: return attr->mode; default: return 0; @@ -560,7 +561,7 @@ static umode_t interface_greybus_is_visible(struct kobject *kobj, struct gb_interface *intf = to_gb_interface(dev); switch (intf->type) { - case GB_SVC_INTF_TYPE_GREYBUS: + case GB_INTERFACE_TYPE_GREYBUS: return attr->mode; default: return 0; @@ -574,8 +575,8 @@ static umode_t interface_power_is_visible(struct kobject *kobj, struct gb_interface *intf = to_gb_interface(dev); switch (intf->type) { - case GB_SVC_INTF_TYPE_UNIPRO: - case GB_SVC_INTF_TYPE_GREYBUS: + case GB_INTERFACE_TYPE_UNIPRO: + case GB_INTERFACE_TYPE_GREYBUS: return attr->mode; default: return 0; @@ -825,21 +826,22 @@ static int gb_interface_activate_operation(struct gb_interface *intf) return ret; } - intf->type = type; - switch (type) { case GB_SVC_INTF_TYPE_DUMMY: + intf->type = GB_INTERFACE_TYPE_DUMMY; /* FIXME: handle as an error for now */ return -ENODEV; case GB_SVC_INTF_TYPE_UNIPRO: + intf->type = GB_INTERFACE_TYPE_UNIPRO; dev_err(&intf->dev, "interface type UniPro not supported\n"); /* FIXME: check if this is a Toshiba bridge before retrying? */ return -EAGAIN; case GB_SVC_INTF_TYPE_GREYBUS: + intf->type = GB_INTERFACE_TYPE_GREYBUS; break; default: dev_err(&intf->dev, "unknown interface type: %u\n", type); - intf->type = GB_SVC_INTF_TYPE_UNKNOWN; + intf->type = GB_INTERFACE_TYPE_UNKNOWN; return -ENODEV; } @@ -1134,15 +1136,17 @@ int gb_interface_add(struct gb_interface *intf) gb_interface_type_string(intf)); switch (intf->type) { - case GB_SVC_INTF_TYPE_GREYBUS: + case GB_INTERFACE_TYPE_GREYBUS: dev_info(&intf->dev, "Ara VID=0x%08x, PID=0x%08x\n", intf->vendor_id, intf->product_id); /* fall-through */ - case GB_SVC_INTF_TYPE_UNIPRO: + case GB_INTERFACE_TYPE_UNIPRO: dev_info(&intf->dev, "DDBL1 Manufacturer=0x%08x, Product=0x%08x\n", intf->ddbl1_manufacturer_id, intf->ddbl1_product_id); break; + default: + break; } return 0; diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 05a3909..bba1881 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -10,6 +10,14 @@ #ifndef __INTERFACE_H #define __INTERFACE_H +enum gb_interface_type { + GB_INTERFACE_TYPE_INVALID = 0, + GB_INTERFACE_TYPE_UNKNOWN, + GB_INTERFACE_TYPE_DUMMY, + GB_INTERFACE_TYPE_UNIPRO, + GB_INTERFACE_TYPE_GREYBUS, +}; + #define GB_INTERFACE_QUIRK_NO_CPORT_FEATURES BIT(0) #define GB_INTERFACE_QUIRK_NO_INIT_STATUS BIT(1) #define GB_INTERFACE_QUIRK_NO_ARA_IDS BIT(2) @@ -26,7 +34,8 @@ struct gb_interface { u8 interface_id; /* Physical location within the Endo */ u8 device_id; u8 features; /* Feature flags set in the manifest */ - u8 type; + + enum gb_interface_type type; u32 ddbl1_manufacturer_id; u32 ddbl1_product_id; diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index 242be49..3ae5876 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -153,7 +153,7 @@ static void gb_module_register_interface(struct gb_interface *intf) break; } if (ret) { - if (intf->type != GB_SVC_INTF_TYPE_DUMMY) { + if (intf->type != GB_INTERFACE_TYPE_DUMMY) { dev_err(&module->dev, "failed to activate interface %u: %d\n", intf_id, ret); -- cgit v0.10.2 From 27b9e257dd57fba0d63d996bf050fcbd94d998d7 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 20 Jul 2016 16:40:21 +0200 Subject: greybus: interface: do not read DME during reactivation It will soon be possible to reactivate an interface that has been powered down after already having been activated. In that case there's no need to re-read the DME attributes as part of activation as the values are already cached. Reviewed-by: Sandeep Patil <sspatil@google.com> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Alex Elder <elder@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Patrick Titiano <ptitiano@baylibre.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index e21491b..9fe6764 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -95,6 +95,10 @@ static int gb_interface_read_dme(struct gb_interface *intf) { int ret; + /* DME attributes have already been read */ + if (intf->dme_read) + return 0; + ret = gb_interface_dme_attr_get(intf, DME_DDBL1_MANUFACTURERID, &intf->ddbl1_manufacturer_id); if (ret) @@ -111,7 +115,13 @@ static int gb_interface_read_dme(struct gb_interface *intf) intf->quirks |= GB_INTERFACE_QUIRK_NO_INIT_STATUS; } - return gb_interface_read_ara_dme(intf); + ret = gb_interface_read_ara_dme(intf); + if (ret) + return ret; + + intf->dme_read = true; + + return 0; } static int gb_interface_route_create(struct gb_interface *intf) diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index bba1881..f52dfd0 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -56,6 +56,7 @@ struct gb_interface { bool active; bool enabled; bool mode_switch; + bool dme_read; struct work_struct mode_switch_work; struct completion mode_switch_completion; -- cgit v0.10.2 From 3e93cb6abbc023aebf311618481263e000bf26fb Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 20 Jul 2016 16:40:22 +0200 Subject: greybus: interface: clean up ES3 activation-retry hack Clean up the ES3 activation retry-hack and isolate it in the interface code. This way the retry hack can be reused when we soon start allowing interfaces to be reactivated after having been powered down. Reviewed-by: Sandeep Patil <sspatil@google.com> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Alex Elder <elder@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Patrick Titiano <ptitiano@baylibre.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 9fe6764..8e1b6c0 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -844,8 +844,8 @@ static int gb_interface_activate_operation(struct gb_interface *intf) case GB_SVC_INTF_TYPE_UNIPRO: intf->type = GB_INTERFACE_TYPE_UNIPRO; dev_err(&intf->dev, "interface type UniPro not supported\n"); - /* FIXME: check if this is a Toshiba bridge before retrying? */ - return -EAGAIN; + /* FIXME: handle as an error for now */ + return -ENODEV; case GB_SVC_INTF_TYPE_GREYBUS: intf->type = GB_INTERFACE_TYPE_GREYBUS; break; @@ -865,12 +865,7 @@ static int gb_interface_hibernate_link(struct gb_interface *intf) return gb_svc_intf_set_power_mode_hibernate(svc, intf->interface_id); } -/* - * Activate an interface. - * - * Locking: Caller holds the interface mutex. - */ -int gb_interface_activate(struct gb_interface *intf) +static int _gb_interface_activate(struct gb_interface *intf) { int ret; @@ -920,6 +915,35 @@ err_vsys_disable: } /* + * Activate an interface. + * + * Locking: Caller holds the interface mutex. + */ +int gb_interface_activate(struct gb_interface *intf) +{ + int retries = 3; + int ret; + + /* + * At present, we assume a UniPro-only module + * to be a Greybus module that failed to send its mailbox + * poke. There is some reason to believe that this is + * because of a bug in the ES3 bootrom. + * + * FIXME: Check if this is a Toshiba bridge before retrying? + */ + while (retries--) { + ret = _gb_interface_activate(intf); + if (ret == -ENODEV && intf->type == GB_SVC_INTF_TYPE_UNIPRO) + continue; + + break; + } + + return ret; +} + +/* * Deactivate an interface. * * Locking: Caller holds the interface mutex. diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index 3ae5876..d506fa0 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -143,15 +143,10 @@ static void gb_module_register_interface(struct gb_interface *intf) struct gb_module *module = intf->module; u8 intf_id = intf->interface_id; int ret; - int retries = 3; mutex_lock(&intf->mutex); - while (retries--) { - ret = gb_interface_activate(intf); - if (ret != -EAGAIN) - break; - } + ret = gb_interface_activate(intf); if (ret) { if (intf->type != GB_INTERFACE_TYPE_DUMMY) { dev_err(&module->dev, @@ -159,19 +154,6 @@ static void gb_module_register_interface(struct gb_interface *intf) intf_id, ret); } - /* - * -EAGAIN indicates that the Greybus operation - * interface_activate determined the remote interface to be - * UniPro-only. At present, we assume a UniPro-only module - * to be a Greybus module that failed to send its mailbox - * poke. There is some reason to believe that this is - * because of a bug in the ES3 bootrom. If we exhause our - * retries trying to activate such an interface, convert - * the error code back into a "no device" error. - */ - if (ret == -EAGAIN) - ret = -ENODEV; - gb_interface_add(intf); goto err_unlock; } -- cgit v0.10.2 From 62491622db9c9b6a51630f4c8c653f59c2c834f9 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 20 Jul 2016 16:40:23 +0200 Subject: greybus: interface: make sure type is invariant during reactivation An interface is not expected to change its type after a power down and reactivation so make sure to treat that as a fatal error. This is complicated by the current Toshiba ES3 hack which requires us to retry activation as Greybus interfaces are sometimes misdetected as UniPro interfaces. Handle that by only retrying activation the first time an interface is activated, and for interfaces already detected as having Greybus type. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Alex Elder <elder@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Sandeep Patil <sspatil@google.com> Reviewed-by: Patrick Titiano <ptitiano@baylibre.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 8e1b6c0..01cefce 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -822,7 +822,8 @@ static int gb_interface_unipro_set(struct gb_interface *intf, bool enable) return 0; } -static int gb_interface_activate_operation(struct gb_interface *intf) +static int gb_interface_activate_operation(struct gb_interface *intf, + enum gb_interface_type *intf_type) { struct gb_svc *svc = intf->hd->svc; u8 type; @@ -838,20 +839,20 @@ static int gb_interface_activate_operation(struct gb_interface *intf) switch (type) { case GB_SVC_INTF_TYPE_DUMMY: - intf->type = GB_INTERFACE_TYPE_DUMMY; + *intf_type = GB_INTERFACE_TYPE_DUMMY; /* FIXME: handle as an error for now */ return -ENODEV; case GB_SVC_INTF_TYPE_UNIPRO: - intf->type = GB_INTERFACE_TYPE_UNIPRO; + *intf_type = GB_INTERFACE_TYPE_UNIPRO; dev_err(&intf->dev, "interface type UniPro not supported\n"); /* FIXME: handle as an error for now */ return -ENODEV; case GB_SVC_INTF_TYPE_GREYBUS: - intf->type = GB_INTERFACE_TYPE_GREYBUS; + *intf_type = GB_INTERFACE_TYPE_GREYBUS; break; default: dev_err(&intf->dev, "unknown interface type: %u\n", type); - intf->type = GB_INTERFACE_TYPE_UNKNOWN; + *intf_type = GB_INTERFACE_TYPE_UNKNOWN; return -ENODEV; } @@ -865,10 +866,13 @@ static int gb_interface_hibernate_link(struct gb_interface *intf) return gb_svc_intf_set_power_mode_hibernate(svc, intf->interface_id); } -static int _gb_interface_activate(struct gb_interface *intf) +static int _gb_interface_activate(struct gb_interface *intf, + enum gb_interface_type *type) { int ret; + *type = GB_INTERFACE_TYPE_UNKNOWN; + if (intf->ejected) return -ENODEV; @@ -884,7 +888,7 @@ static int _gb_interface_activate(struct gb_interface *intf) if (ret) goto err_refclk_disable; - ret = gb_interface_activate_operation(intf); + ret = gb_interface_activate_operation(intf, type); if (ret) goto err_unipro_disable; @@ -915,26 +919,21 @@ err_vsys_disable: } /* - * Activate an interface. + * At present, we assume a UniPro-only module to be a Greybus module that + * failed to send its mailbox poke. There is some reason to believe that this + * is because of a bug in the ES3 bootrom. * - * Locking: Caller holds the interface mutex. + * FIXME: Check if this is a Toshiba bridge before retrying? */ -int gb_interface_activate(struct gb_interface *intf) +static int _gb_interface_activate_es3_hack(struct gb_interface *intf, + enum gb_interface_type *type) { int retries = 3; int ret; - /* - * At present, we assume a UniPro-only module - * to be a Greybus module that failed to send its mailbox - * poke. There is some reason to believe that this is - * because of a bug in the ES3 bootrom. - * - * FIXME: Check if this is a Toshiba bridge before retrying? - */ while (retries--) { - ret = _gb_interface_activate(intf); - if (ret == -ENODEV && intf->type == GB_SVC_INTF_TYPE_UNIPRO) + ret = _gb_interface_activate(intf, type); + if (ret == -ENODEV && *type == GB_INTERFACE_TYPE_UNIPRO) continue; break; @@ -944,6 +943,42 @@ int gb_interface_activate(struct gb_interface *intf) } /* + * Activate an interface. + * + * Locking: Caller holds the interface mutex. + */ +int gb_interface_activate(struct gb_interface *intf) +{ + enum gb_interface_type type; + int ret; + + switch (intf->type) { + case GB_INTERFACE_TYPE_INVALID: + case GB_INTERFACE_TYPE_GREYBUS: + ret = _gb_interface_activate_es3_hack(intf, &type); + break; + default: + ret = _gb_interface_activate(intf, &type); + } + + /* Make sure type is detected correctly during reactivation. */ + if (intf->type != GB_INTERFACE_TYPE_INVALID) { + if (type != intf->type) { + dev_err(&intf->dev, "failed to detect interface type\n"); + + if (!ret) + gb_interface_deactivate(intf); + + return -EIO; + } + } else { + intf->type = type; + } + + return ret; +} + +/* * Deactivate an interface. * * Locking: Caller holds the interface mutex. -- cgit v0.10.2 From 12169bc9143ed24ad7a5ea12a7c28d1dba891131 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 20 Jul 2016 16:40:24 +0200 Subject: greybus: interface: prevent reactivation during removal Make sure to prevent an interface that is going away from being reactivated. This is needed to preemptively close a race between the upcoming feature to reactivate a powered-down interface and physical removal (i.e. module_removed event processing) as well as logical removal (e.g. the current system-suspend hack). Reviewed-by: Sandeep Patil <sspatil@google.com> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Alex Elder <elder@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Patrick Titiano <ptitiano@baylibre.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 01cefce..3ad1c75 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -873,7 +873,7 @@ static int _gb_interface_activate(struct gb_interface *intf, *type = GB_INTERFACE_TYPE_UNKNOWN; - if (intf->ejected) + if (intf->ejected || intf->removed) return -ENODEV; ret = gb_interface_vsys_set(intf, true); diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index f52dfd0..daa9759 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -53,6 +53,7 @@ struct gb_interface { bool disconnected; bool ejected; + bool removed; bool active; bool enabled; bool mode_switch; diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index d506fa0..69f67dd 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -186,6 +186,7 @@ static void gb_module_deregister_interface(struct gb_interface *intf) intf->disconnected = true; mutex_lock(&intf->mutex); + intf->removed = true; gb_interface_disable(intf); gb_interface_deactivate(intf); mutex_unlock(&intf->mutex); -- cgit v0.10.2 From 93e29c8530881766837e62088d54ffb733f8bc2a Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Wed, 20 Jul 2016 16:40:25 +0200 Subject: greybus: interface: add power_state attribute User space needs the capability of powering ON or OFF an Interface for multiple use cases. For example, userspace may want an Interface currently in its S3 boot stage, to boot into its S2 Loader stage to update the bridge SPI flash. Or the Interface is running its S2 Loader stage and updated the SPI flash with the new S2 Loader firmware and wants to boot into the new S2 Loader firmware. Another use case can be, Android wants to disable (not eject) a misbehaving module. Add a 'power_state' sysfs file within the interface directory. It can be read to know the current power state of the Interface and can be written to power ON or power OFF an Interface. Possible values that can be written or read from it are: "on" and "off". Testing Done: Tested by enabling/disabling camera module on EVT 2.0. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> CC: David Lin <dtwlin@google.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> [johan: drop es3-quirk duplication, add to power attribute group, fix return value, drop tags ] Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Alex Elder <elder@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Sandeep Patil <sspatil@google.com> Reviewed-by: Patrick Titiano <ptitiano@baylibre.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 721010e..62d03af 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -97,6 +97,23 @@ Contact: Greg Kroah-Hartman <greg@kroah.com> Description: Power measurement of the interface in microwatts (uW) +What: /sys/bus/greybus/devices/N-M.I/power_state +Date: March 2016 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman <greg@kroah.com> +Description: + This reflects the power state of a Greybus Interface. If the + value read from it is "on", then power is currently supplied to + the Interface. Otherwise this will read "off" and the power is + currently not supplied to the Interface. + + If the value read is "off", then writing "on" (or '1', 'y', + 'Y') to it will enable power to the Interface. If the value + read is "on", then writing "off" (or '0', 'n', 'N') to it will + disable power to the Interface. + + Writing the currently read value to it has no effect. + What: /sys/bus/greybus/devices/N-M.I/product_id Date: October 2015 KernelVersion: 4.XX diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 3ad1c75..f5ed79c 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -501,6 +501,63 @@ static ssize_t power_now_show(struct device *dev, } static DEVICE_ATTR_RO(power_now); +static ssize_t power_state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_interface *intf = to_gb_interface(dev); + + if (intf->active) + return scnprintf(buf, PAGE_SIZE, "on\n"); + else + return scnprintf(buf, PAGE_SIZE, "off\n"); +} + +static ssize_t power_state_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t len) +{ + struct gb_interface *intf = to_gb_interface(dev); + bool activate; + int ret = 0; + + if (kstrtobool(buf, &activate)) + return -EINVAL; + + mutex_lock(&intf->mutex); + + if (activate == intf->active) + goto unlock; + + if (activate) { + ret = gb_interface_activate(intf); + if (ret) { + dev_err(&intf->dev, + "failed to activate interface: %d\n", ret); + goto unlock; + } + + ret = gb_interface_enable(intf); + if (ret) { + dev_err(&intf->dev, + "failed to enable interface: %d\n", ret); + gb_interface_deactivate(intf); + goto unlock; + } + } else { + gb_interface_disable(intf); + gb_interface_deactivate(intf); + } + +unlock: + mutex_unlock(&intf->mutex); + + if (ret) + return ret; + + return len; +} +static DEVICE_ATTR_RW(power_state); + static const char *gb_interface_type_string(struct gb_interface *intf) { static const char * const types[] = { @@ -541,6 +598,7 @@ static struct attribute *interface_power_attrs[] = { &dev_attr_voltage_now.attr, &dev_attr_current_now.attr, &dev_attr_power_now.attr, + &dev_attr_power_state.attr, NULL }; -- cgit v0.10.2 From e21e6bad3f425e8bc74186f3ab1e21cd40f7a208 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 20 Jul 2016 16:40:26 +0200 Subject: greybus: interface: fix power_state documentation Reword the power_state attribute documentation to make it clear that an attempt to boot and possibly enumerate an interface is made when writing "on" to the file, and that on errors the interface will again be powered down. Drop the incorrect claim that writing the currently read value has no effect, since no such guarantees can be made (e.g. several writers may be sleeping on the interface mutex). Also fix some minor language issues. Reviewed-by: Sandeep Patil <sspatil@google.com> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Alex Elder <elder@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Patrick Titiano <ptitiano@baylibre.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 62d03af..e202eac 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -102,17 +102,18 @@ Date: March 2016 KernelVersion: 4.XX Contact: Greg Kroah-Hartman <greg@kroah.com> Description: - This reflects the power state of a Greybus Interface. If the - value read from it is "on", then power is currently supplied to - the Interface. Otherwise this will read "off" and the power is - currently not supplied to the Interface. + This file reflects the power state of a Greybus interface. If + the value read from it is "on", then power is currently + supplied to the interface. Otherwise it will read "off" and + power is currently not supplied to the interface. If the value read is "off", then writing "on" (or '1', 'y', - 'Y') to it will enable power to the Interface. If the value - read is "on", then writing "off" (or '0', 'n', 'N') to it will - disable power to the Interface. + 'Y') to this file will enable power to the interface and an + attempt to boot and possibly enumerate it will be made. Note + that on errors, the interface will again be powered down. - Writing the currently read value to it has no effect. + If the value read is "on", then writing "off" (or '0', 'n', + 'N') to this file will power down the interface. What: /sys/bus/greybus/devices/N-M.I/product_id Date: October 2015 -- cgit v0.10.2 From 4f7e413b2d2d2825dbb36b73f06e69514022b132 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 20 Jul 2016 16:40:27 +0200 Subject: greybus: interface: hibernate UniPro link in activation error path To be well-behaved, we should hibernate the link before disabling UniPro in case the link has already been established (i.e. when the interface type has been detected as UniPro or Greybus). Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Alex Elder <elder@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Sandeep Patil <sspatil@google.com> Reviewed-by: Patrick Titiano <ptitiano@baylibre.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index f5ed79c..919eaa0 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -947,8 +947,15 @@ static int _gb_interface_activate(struct gb_interface *intf, goto err_refclk_disable; ret = gb_interface_activate_operation(intf, type); - if (ret) - goto err_unipro_disable; + if (ret) { + switch (*type) { + case GB_INTERFACE_TYPE_UNIPRO: + case GB_INTERFACE_TYPE_GREYBUS: + goto err_hibernate_link; + default: + goto err_unipro_disable; + } + } ret = gb_interface_read_dme(intf); if (ret) -- cgit v0.10.2 From 8a704565ebda9603c294aacebb34e47cd9d9a3a0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Wed, 20 Jul 2016 10:11:37 -0700 Subject: greybus: move all firmware prefix strings to one place The firmware prefix is hard-coded in a few different places. Put it all in one handy #define, for when/if we ever decide to change it in the future... Testing: 'strings gb-firmware.ko gb-bootrom.ko | grep ara_' produced the same output before and after this patch. Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Acked-by: Sandeep Patil <sspatil@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/bootrom.c b/drivers/staging/greybus/bootrom.c index 6881841..309e0a7 100644 --- a/drivers/staging/greybus/bootrom.c +++ b/drivers/staging/greybus/bootrom.c @@ -13,6 +13,7 @@ #include <linux/workqueue.h> #include "greybus.h" +#include "firmware.h" /* Timeout, in jiffies, within which the next request must be received */ #define NEXT_REQ_TIMEOUT_MS 1000 @@ -157,7 +158,7 @@ static int download_firmware(struct gb_bootrom *bootrom, u8 stage) * XXX Name it properly.. */ snprintf(firmware_name, sizeof(firmware_name), - "ara_%08x_%08x_%08x_%08x_s2l.tftf", + FW_NAME_PREFIX "%08x_%08x_%08x_%08x_s2l.tftf", intf->ddbl1_manufacturer_id, intf->ddbl1_product_id, intf->vendor_id, intf->product_id); diff --git a/drivers/staging/greybus/firmware.h b/drivers/staging/greybus/firmware.h index fb95537..2fbb263 100644 --- a/drivers/staging/greybus/firmware.h +++ b/drivers/staging/greybus/firmware.h @@ -12,6 +12,11 @@ #include "greybus.h" +#define FW_NAME_PREFIX "ara_" + +/* Length of the string in format: "FW_NAME_PREFIX""%08x_%08x_%08x_%08x_%s.tftf" */ +#define FW_NAME_LEN 56 + /* Firmware Management Protocol specific functions */ int fw_mgmt_init(void); void fw_mgmt_exit(void); diff --git a/drivers/staging/greybus/fw-download.c b/drivers/staging/greybus/fw-download.c index 42cbbf4..41a45ec 100644 --- a/drivers/staging/greybus/fw-download.c +++ b/drivers/staging/greybus/fw-download.c @@ -14,8 +14,6 @@ #include "firmware.h" #include "greybus.h" -/* Length of the string in format: ara_%08x_%08x_%08x_%08x_%s.tftf */ -#define FW_NAME_LEN 56 /* Estimated minimum buffer size, actual size can be smaller than this */ #define MIN_FETCH_SIZE 512 /* Timeout, in jiffies, within which fetch or release firmware must be called */ @@ -182,7 +180,7 @@ static struct fw_request *find_firmware(struct fw_download *fw_download, fw_req->firmware_id = ret; snprintf(fw_req->name, sizeof(fw_req->name), - "ara_%08x_%08x_%08x_%08x_%s.tftf", + FW_NAME_PREFIX "%08x_%08x_%08x_%08x_%s.tftf", intf->ddbl1_manufacturer_id, intf->ddbl1_product_id, intf->vendor_id, intf->product_id, tag); -- cgit v0.10.2 From 93a738894346d01687c8979bca129d7eaaf7d35f Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Tue, 19 Jul 2016 15:04:37 +0100 Subject: greybus: timesync: reduce initial startup time Currently we have a long initial delay when initiating the first operation to synchronize the FrameTime. That made sense during development of the feature since we did synchronization asynchronously and wanted to give some grace time for new Interfaces to be added before initiating a new synchronization. On the PM runtime resume path though we do a synchronous restoration of FrameTime and in this case waiting for 1 second before initiating the first operation is clearly wrong. This patch reduces the initial operation time bringing the synchronous call time down by 990 milliseconds. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/timesync.c b/drivers/staging/greybus/timesync.c index ddbdf2b..23b2091 100644 --- a/drivers/staging/greybus/timesync.c +++ b/drivers/staging/greybus/timesync.c @@ -28,7 +28,7 @@ #define GB_TIMESYNC_DEFAULT_OFFSET_US 1000 /* Work queue timers long, short and SVC strobe timeout */ -#define GB_TIMESYNC_DELAYED_WORK_LONG msecs_to_jiffies(1000) +#define GB_TIMESYNC_DELAYED_WORK_LONG msecs_to_jiffies(10) #define GB_TIMESYNC_DELAYED_WORK_SHORT msecs_to_jiffies(1) #define GB_TIMESYNC_MAX_WAIT_SVC msecs_to_jiffies(5000) #define GB_TIMESYNC_KTIME_UPDATE msecs_to_jiffies(1000) -- cgit v0.10.2 From 2861e2079081a156b0b731e1f6acb2aaf5605c5e Mon Sep 17 00:00:00 2001 From: Ryan Lim <limryan@google.com> Date: Wed, 20 Jul 2016 08:14:02 -0700 Subject: greybus: loopback_test: Cancel only the tests running on selected devices When starting a loopback test, it cancels all currently running tests on all loopback devices. When -m argument is given, which runs the test on specific loopback devices, only the tests running on the selected devices need to be cancelled before starting new tests. Signed-off-by: Ryan Lim <limryan@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/tools/loopback_test.c b/drivers/staging/greybus/tools/loopback_test.c index 25035f6..ec44892 100644 --- a/drivers/staging/greybus/tools/loopback_test.c +++ b/drivers/staging/greybus/tools/loopback_test.c @@ -780,7 +780,8 @@ static void prepare_devices(struct loopback_test *t) /* Cancel any running tests */ for (i = 0; i < t->device_count; i++) - write_sysfs_val(t->devices[i].sysfs_entry, "type", 0); + if (device_enabled(t, i)) + write_sysfs_val(t->devices[i].sysfs_entry, "type", 0); for (i = 0; i < t->device_count; i++) { -- cgit v0.10.2 From bf32654a24441230fac32479b6a5ba8bbfc3b731 Mon Sep 17 00:00:00 2001 From: Ryan Lim <limryan@google.com> Date: Wed, 20 Jul 2016 08:14:03 -0700 Subject: greybus: loopback_test: Fix -z argument bug The -z argument was missing the break statement needed in the switch block and was not in the getopt list. Signed-off-by: Ryan Lim <limryan@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/tools/loopback_test.c b/drivers/staging/greybus/tools/loopback_test.c index ec44892..412e6dc 100644 --- a/drivers/staging/greybus/tools/loopback_test.c +++ b/drivers/staging/greybus/tools/loopback_test.c @@ -901,7 +901,7 @@ int main(int argc, char *argv[]) memset(&t, 0, sizeof(t)); while ((o = getopt(argc, argv, - "t:s:i:S:D:m:v::d::r::p::a::l::x::o:c:w:O:")) != -1) { + "t:s:i:S:D:m:v::d::r::p::a::l::x::o:O:c:w:z::")) != -1) { switch (o) { case 't': snprintf(t.test_name, MAX_STR_LEN, "%s", optarg); @@ -956,6 +956,7 @@ int main(int argc, char *argv[]) break; case 'z': t.file_output = 1; + break; default: usage(); return -EINVAL; -- cgit v0.10.2 From 346bae656e4e1a471771590f1f4e16e9f9332d1d Mon Sep 17 00:00:00 2001 From: Ryan Lim <limryan@google.com> Date: Wed, 20 Jul 2016 08:14:04 -0700 Subject: greybus: loopback_test: Add -f argument to cancel all tests To make sure tests on all devices, enabled or not, are cancelled, specify -f when starting new loopback test. Signed-off-by: Ryan Lim <limryan@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/tools/loopback_test.c b/drivers/staging/greybus/tools/loopback_test.c index 412e6dc..f7f4cd6 100644 --- a/drivers/staging/greybus/tools/loopback_test.c +++ b/drivers/staging/greybus/tools/loopback_test.c @@ -91,6 +91,7 @@ struct loopback_test { int async_outstanding_operations; int us_wait; int file_output; + int stop_all; int poll_count; char test_name[MAX_STR_LEN]; char sysfs_prefix[MAX_SYSFS_PATH]; @@ -207,6 +208,7 @@ void usage(void) " -c Max number of outstanding operations for async operations\n" " -w Wait in uSec between operations\n" " -z Enable output to a CSV file (incompatible with -p)\n" + " -f When starting new loopback test, stop currently running tests on all devices\n" "Examples:\n" " Send 10000 transfers with a packet size of 128 bytes to all active connections\n" " loopback_test -t transfer -s 128 -i 10000 -S /sys/bus/greybus/devices/ -D /sys/kernel/debug/gb_loopback/\n" @@ -778,9 +780,11 @@ static void prepare_devices(struct loopback_test *t) { int i; - /* Cancel any running tests */ + /* Cancel any running tests on enabled devices. If + * stop_all option is given, stop test on all devices. + */ for (i = 0; i < t->device_count; i++) - if (device_enabled(t, i)) + if (t->stop_all || device_enabled(t, i)) write_sysfs_val(t->devices[i].sysfs_entry, "type", 0); @@ -901,7 +905,7 @@ int main(int argc, char *argv[]) memset(&t, 0, sizeof(t)); while ((o = getopt(argc, argv, - "t:s:i:S:D:m:v::d::r::p::a::l::x::o:O:c:w:z::")) != -1) { + "t:s:i:S:D:m:v::d::r::p::a::l::x::o:O:c:w:z::f::")) != -1) { switch (o) { case 't': snprintf(t.test_name, MAX_STR_LEN, "%s", optarg); @@ -957,6 +961,9 @@ int main(int argc, char *argv[]) case 'z': t.file_output = 1; break; + case 'f': + t.stop_all = 1; + break; default: usage(); return -EINVAL; -- cgit v0.10.2 From 10a24b7c0911d63c7342dfb860e939221b4a9465 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Wed, 20 Jul 2016 19:31:18 +0100 Subject: greybus: timesync: probe shouldn't complete until FrameTime sync does Currently the probe() function contains the asynchronous() variant of FrameTime synchronization. This patch converts to the synchronous() version of synchronization. This is required for two reasons first a probe() cannot reasonably be considered to be complete without successfully completing a time synchronization for Interfaces that care about that sync. Secondly scheduling the operation asynchronously means its possible the PM-runtime suspend() path can execute before the async timesync operation completes. For both reasons we want to run synchronization - synchronously. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 2c94bbb..8c77d6c 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -219,7 +219,7 @@ static int greybus_probe(struct device *dev) return retval; } - gb_timesync_schedule_asynchronous(bundle->intf); + gb_timesync_schedule_synchronous(bundle->intf); pm_runtime_put(&bundle->intf->dev); -- cgit v0.10.2 From b5d1d1282bbb318a67fdcfc8ef2615e93d1d1724 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Thu, 21 Jul 2016 12:48:57 +0200 Subject: greybus: interface: fix interface_id attribute group All interfaces, regardless of type, should have an interface_id attribute reflecting its position on the frame. This has been reported to cause an assertion failure in libmoduleutil for dummy modules. Testing done: Verified that the attribute is present for registered dummy interfaces. Reported-by: Gjorgji Rosikopulos <grosikopulos@mm-sol.com> Tested-by: Gjorgji Rosikopulos <grosikopulos@mm-sol.com> Reviewed-by: Patrick Titiano <ptitiano@baylibre.com> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 919eaa0..6abe131 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -587,7 +587,6 @@ static struct attribute *interface_unipro_attrs[] = { }; static struct attribute *interface_greybus_attrs[] = { - &dev_attr_interface_id.attr, &dev_attr_vendor_id.attr, &dev_attr_product_id.attr, &dev_attr_serial_number.attr, @@ -603,6 +602,7 @@ static struct attribute *interface_power_attrs[] = { }; static struct attribute *interface_common_attrs[] = { + &dev_attr_interface_id.attr, &dev_attr_interface_type.attr, NULL }; -- cgit v0.10.2 From 350e3ac2ceb696435efbbe688e6e912801a4b8c4 Mon Sep 17 00:00:00 2001 From: Joel Porquet <porquet_joel@projectara.com> Date: Thu, 21 Jul 2016 15:57:38 -0700 Subject: greybus: firmware.h: rename TFTF firmware filenames Replace prefix "ara_" with prefix "gmp_" for TFTF firmware filenames. Testing Done: compiled and flashed EVT2 (bootimage) and tested that "gmp_" prefixed tftf files are expected. Pushed one from FDK and checked that it's properly loaded. Signed-off-by: Joel Porquet <porquet_joel@projectara.com> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Acked-by: Sandeep Patil <sspatil@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/firmware.h b/drivers/staging/greybus/firmware.h index 2fbb263..841a0d5 100644 --- a/drivers/staging/greybus/firmware.h +++ b/drivers/staging/greybus/firmware.h @@ -12,7 +12,7 @@ #include "greybus.h" -#define FW_NAME_PREFIX "ara_" +#define FW_NAME_PREFIX "gmp_" /* Length of the string in format: "FW_NAME_PREFIX""%08x_%08x_%08x_%08x_%s.tftf" */ #define FW_NAME_LEN 56 -- cgit v0.10.2 From 2358024b67fccc07b95c5d8e637927acdb8e30fa Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Thu, 21 Jul 2016 14:24:11 +0200 Subject: greybus: control: suppress bundle_activate() for bootrom We always knew backward compatibility with the ES3 bootrom, which was finalised about a year ago, would be a pain. Here we go again. The bootrom does not support control requests added after it was burnt into ROM for obvious reasons. This means that we need to suppress sending the new bundle_activate() operation to any interface executing the legacy bootrom. Do so by adding a new NO_PM interface quirk (we can use the control-protocol version for this later once we bump it). Note that the interface-disable path (e.g. for power down) is already handled by the FORCED_DISABLE quirk, and that the suspend/resume paths are currently avoided by making sure that the bootrom bundle never suspends. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Acked-by: Bartosz Golaszewski <bgolaszewski@baylibre.com> Tested-by: Bartosz Golaszewski <bgolaszewski@baylibre.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index 37a30b3..a08a79d 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -329,6 +329,9 @@ int gb_control_bundle_activate(struct gb_control *control, u8 bundle_id) struct gb_control_bundle_pm_response response; int ret; + if (!control->has_bundle_activate) + return 0; + request.bundle_id = bundle_id; ret = gb_operation_sync(control->connection, GB_CONTROL_TYPE_BUNDLE_ACTIVATE, &request, @@ -528,6 +531,10 @@ int gb_control_enable(struct gb_control *control) if (control->protocol_major > 0 || control->protocol_minor > 1) control->has_bundle_version = true; + /* FIXME: use protocol version instead */ + if (!(control->intf->quirks & GB_INTERFACE_QUIRK_NO_PM)) + control->has_bundle_activate = true; + return 0; err_disable_connection: diff --git a/drivers/staging/greybus/control.h b/drivers/staging/greybus/control.h index f73ec3e..f9a60da 100644 --- a/drivers/staging/greybus/control.h +++ b/drivers/staging/greybus/control.h @@ -19,6 +19,7 @@ struct gb_control { u8 protocol_major; u8 protocol_minor; + bool has_bundle_activate; bool has_bundle_version; char *vendor_string; diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 6abe131..74fa298 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -411,7 +411,8 @@ static int gb_interface_read_and_clear_init_status(struct gb_interface *intf) */ bootrom_quirks = GB_INTERFACE_QUIRK_NO_CPORT_FEATURES | GB_INTERFACE_QUIRK_FORCED_DISABLE | - GB_INTERFACE_QUIRK_LEGACY_MODE_SWITCH; + GB_INTERFACE_QUIRK_LEGACY_MODE_SWITCH | + GB_INTERFACE_QUIRK_NO_PM; switch (init_status) { case GB_INIT_BOOTROM_UNIPRO_BOOT_STARTED: case GB_INIT_BOOTROM_FALLBACK_UNIPRO_BOOT_STARTED: diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index daa9759..a08d104 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -23,6 +23,7 @@ enum gb_interface_type { #define GB_INTERFACE_QUIRK_NO_ARA_IDS BIT(2) #define GB_INTERFACE_QUIRK_FORCED_DISABLE BIT(3) #define GB_INTERFACE_QUIRK_LEGACY_MODE_SWITCH BIT(4) +#define GB_INTERFACE_QUIRK_NO_PM BIT(5) struct gb_interface { struct device dev; -- cgit v0.10.2 From f5c93dea8fb7daf5ec26176caa791719895cd28e Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski <bgolaszewski@baylibre.com> Date: Thu, 21 Jul 2016 18:09:34 +0200 Subject: greybus: pm: add error handling to bundle activation The firmware now keeps the underlying hardware disabled until receiving the first Bundle Activate request. Additionally: requesting transition to a state the bundle is already in is no longer an error. We can now add proper error handling to the bundle activate call. Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index 8c77d6c..1049e9c 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -181,12 +181,11 @@ static int greybus_probe(struct device *dev) return retval; } - /* - * FIXME: We need to perform error handling on bundle activate call - * below when firmware is ready. We just allow the activate operation to - * fail for now since bundle may be in active already. - */ - gb_control_bundle_activate(bundle->intf->control, bundle->id); + retval = gb_control_bundle_activate(bundle->intf->control, bundle->id); + if (retval) { + pm_runtime_put(&bundle->intf->dev); + return retval; + } /* * Unbound bundle devices are always deactivated. During probe, the -- cgit v0.10.2 From db2951835b9b11abf3075302279a41cd345db312 Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Wed, 20 Jul 2016 17:18:39 -0700 Subject: greybus: timesync: do not print frametime by default Currently frametime are being printed whenever an Interface is runtime-resumed. This is unnecessarily chatty. This patch moves the frametime print from using pr_info() to dev_dbg(). Testing Done: - $ echo "module greybus +p" > /d/dynamic_debug/control [ 97.699395] greybus 1-svc: greybus frametime: ap=2042778707 1-svc=2042775185 greybus1=2042778397 1-6.6=2042778390 Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Jeffrey Carlyle <jcarlyle@google.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/timesync.c b/drivers/staging/greybus/timesync.c index 23b2091..ec0a51d 100644 --- a/drivers/staging/greybus/timesync.c +++ b/drivers/staging/greybus/timesync.c @@ -746,7 +746,7 @@ static void gb_timesync_log_ping_time(struct gb_timesync_svc *timesync_svc) buf = kzalloc(PAGE_SIZE, GFP_KERNEL); if (buf) { gb_timesync_log_frame_time(timesync_svc, buf, PAGE_SIZE); - pr_info("%s", buf); + dev_dbg(×ync_svc->svc->dev, "%s", buf); kfree(buf); } } -- cgit v0.10.2 From adac4b95941189ca301759a67da4a132fc2804d5 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Wed, 20 Jul 2016 16:39:00 -0700 Subject: greybus: firmware: Improve test application It can take arguments not and we can perform all the operations with a single binary, sorry for missing that initially. Usage: ./firmware <gb-fw-mgmt-X> <type: interface/backend> <firmware-tag> <timeout> And all of them have default values, etc. Tested with a semco 13 MP module. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/firmware/firmware.c b/drivers/staging/greybus/Documentation/firmware/firmware.c index 3c305f7..c557bf1 100644 --- a/drivers/staging/greybus/Documentation/firmware/firmware.c +++ b/drivers/staging/greybus/Documentation/firmware/firmware.c @@ -60,44 +60,29 @@ #include "../../greybus_firmware.h" -static const char *firmware_tag = "03"; /* S3 firmware */ +#define FW_DEV_DEFAULT "/dev/gb-fw-mgmt-0" +#define FW_TAG_INT_DEFAULT "s3f" +#define FW_TAG_BCND_DEFAULT "bf_01" +#define FW_UPDATE_TYPE_DEFAULT 0 +#define FW_TIMEOUT_DEFAULT 10000; + +static const char *firmware_tag; +static const char *fwdev = FW_DEV_DEFAULT; +static int fw_update_type = FW_UPDATE_TYPE_DEFAULT; +static int fw_timeout = FW_TIMEOUT_DEFAULT; static struct fw_mgmt_ioc_get_fw fw_info; static struct fw_mgmt_ioc_intf_load_and_validate intf_load; static struct fw_mgmt_ioc_backend_fw_update backend_update; -int main(int argc, char *argv[]) +static void usage(void) { - unsigned int timeout = 10000; - char *fwdev; - int fd, ret; - - /* Make sure arguments are correct */ - if (argc != 2) { - printf("\nUsage: ./firmware <Path of the gb-fw-mgmt-X dev>\n"); - return 0; - } - - fwdev = argv[1]; - - printf("Opening %s firmware management device\n", fwdev); - - fd = open(fwdev, O_RDWR); - if (fd < 0) { - printf("Failed to open: %s\n", fwdev); - ret = -1; - goto close_fd; - } - - /* Set Timeout */ - printf("Setting timeout to %u ms\n", timeout); + printf("\nUsage: ./firmware <gb-fw-mgmt-X (default: gb-fw-mgmt-0)> <interface: 0, backend: 1 (default: 0)> <firmware-tag> (default: \"s3f\"/\"bf_01\") <timeout (default: 10000 ms)>\n"); +} - ret = ioctl(fd, FW_MGMT_IOC_SET_TIMEOUT_MS, &timeout); - if (ret < 0) { - printf("Failed to set timeout: %s (%d)\n", fwdev, ret); - ret = -1; - goto close_fd; - } +static int update_intf_firmware(int fd) +{ + int ret; /* Get Interface Firmware Version */ printf("Get Interface Firmware Version\n"); @@ -106,8 +91,7 @@ int main(int argc, char *argv[]) if (ret < 0) { printf("Failed to get interface firmware version: %s (%d)\n", fwdev, ret); - ret = -1; - goto close_fd; + return -1; } printf("Interface Firmware tag (%s), major (%d), minor (%d)\n", @@ -120,6 +104,7 @@ int main(int argc, char *argv[]) intf_load.status = 0; intf_load.major = 0; intf_load.minor = 0; + strncpy((char *)&intf_load.firmware_tag, firmware_tag, GB_FIRMWARE_U_TAG_MAX_LEN); @@ -127,35 +112,47 @@ int main(int argc, char *argv[]) if (ret < 0) { printf("Failed to load interface firmware: %s (%d)\n", fwdev, ret); - ret = -1; - goto close_fd; + return -1; } if (intf_load.status != GB_FW_U_LOAD_STATUS_VALIDATED && intf_load.status != GB_FW_U_LOAD_STATUS_UNVALIDATED) { printf("Load status says loading failed: %d\n", intf_load.status); - ret = -1; - goto close_fd; + return -1; } printf("Interface Firmware (%s) Load done: major: %d, minor: %d, status: %d\n", firmware_tag, intf_load.major, intf_load.minor, intf_load.status); + /* Initiate Mode-switch to the newly loaded firmware */ + printf("Initiate Mode switch\n"); + + ret = ioctl(fd, FW_MGMT_IOC_MODE_SWITCH); + if (ret < 0) + printf("Failed to initiate mode-switch (%d)\n", ret); + + return ret; +} + +static int update_backend_firmware(int fd) +{ + int ret; + /* Get Backend Firmware Version */ printf("Getting Backend Firmware Version\n"); - strncpy((char *)&fw_info.firmware_tag, firmware_tag, - GB_FIRMWARE_U_TAG_MAX_LEN); fw_info.major = 0; fw_info.minor = 0; + strncpy((char *)&fw_info.firmware_tag, firmware_tag, + GB_FIRMWARE_U_TAG_MAX_LEN); ret = ioctl(fd, FW_MGMT_IOC_GET_BACKEND_FW, &fw_info); if (ret < 0) { printf("Failed to get backend firmware version: %s (%d)\n", fwdev, ret); - goto mode_switch; + return -1; } printf("Backend Firmware tag (%s), major (%d), minor (%d)\n", @@ -171,24 +168,73 @@ int main(int argc, char *argv[]) ret = ioctl(fd, FW_MGMT_IOC_INTF_BACKEND_FW_UPDATE, &backend_update); if (ret < 0) { printf("Failed to load backend firmware: %s (%d)\n", fwdev, ret); - goto mode_switch; + return -1; } - printf("Backend Firmware (%s) Load done: status: %d\n", - firmware_tag, backend_update.status); - if (backend_update.status != GB_FW_U_BACKEND_FW_STATUS_SUCCESS) { printf("Load status says loading failed: %d\n", backend_update.status); + } else { + printf("Backend Firmware (%s) Load done: status: %d\n", + firmware_tag, backend_update.status); } -mode_switch: - /* Initiate Mode-switch to the newly loaded firmware */ - printf("Initiate Mode switch\n"); + return 0; +} - ret = ioctl(fd, FW_MGMT_IOC_MODE_SWITCH); - if (ret < 0) - printf("Failed to initiate mode-switch (%d)\n", ret); +int main(int argc, char *argv[]) +{ + int fd, ret; + + if (argc > 1 && + (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))) { + usage(); + return -1; + } + + if (argc > 1) + fwdev = argv[1]; + + if (argc > 2) + sscanf(argv[2], "%u", &fw_update_type); + + if (argc > 3) { + firmware_tag = argv[3]; + } else if (!fw_update_type) { + firmware_tag = FW_TAG_INT_DEFAULT; + } else { + firmware_tag = FW_TAG_BCND_DEFAULT; + } + + if (argc > 4) + sscanf(argv[4], "%u", &fw_timeout); + + printf("Trying Firmware update: fwdev: %s, type: %s, tag: %s, timeout: %d\n", + fwdev, fw_update_type == 0 ? "interface" : "backend", + firmware_tag, fw_timeout); + + printf("Opening %s firmware management device\n", fwdev); + + fd = open(fwdev, O_RDWR); + if (fd < 0) { + printf("Failed to open: %s\n", fwdev); + return -1; + } + + /* Set Timeout */ + printf("Setting timeout to %u ms\n", fw_timeout); + + ret = ioctl(fd, FW_MGMT_IOC_SET_TIMEOUT_MS, &fw_timeout); + if (ret < 0) { + printf("Failed to set timeout: %s (%d)\n", fwdev, ret); + ret = -1; + goto close_fd; + } + + if (!fw_update_type) + ret = update_intf_firmware(fd); + else + ret = update_backend_firmware(fd); close_fd: close(fd); -- cgit v0.10.2 From 92bcaddea3197e477bb37439805fcb5a2f9942d7 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 21 Jul 2016 14:45:06 -0700 Subject: greybus: spilib: make spilib independent of gbphy spilib is used by multiple users currently (spi.c and fw-core.c) but commit aa52b62a0556 broke that hierarchy and introduced gbphy dependent code in spilib. This may have unreliable consequences as we are doing following operation unconditionally now: gbphy_dev = to_gbphy_dev(spi->parent); gbphy_runtime_get_sync(gbphy_dev); which may not go well when the parent is of type &bundle->dev (fw-core.c). This patch introduces spilib_ops and lets the users of the core register them. This shall have no functional change for the spi.c usecase and shall fix the unreliable results for the fw-core.c usecase. Tested by writing to mtd0 dev and verifying (with print messages) that the below routines are getting called for a gpbridge-test module. Fixes: aa52b62a0556 ("spi: Add runtime_pm support") Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/fw-core.c b/drivers/staging/greybus/fw-core.c index 9639732..19f92fb 100644 --- a/drivers/staging/greybus/fw-core.c +++ b/drivers/staging/greybus/fw-core.c @@ -38,7 +38,7 @@ static int gb_fw_spi_connection_init(struct gb_connection *connection) if (ret) return ret; - ret = gb_spilib_master_init(connection, &connection->bundle->dev); + ret = gb_spilib_master_init(connection, &connection->bundle->dev, NULL); if (ret) { gb_connection_disable(connection); return ret; diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index 2e6e328..bb76b3c 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -13,6 +13,27 @@ #include "gbphy.h" #include "spilib.h" +#ifndef SPI_CORE_SUPPORT_PM +static int gbphy_spi_prepare_transfer_hardware(struct device *dev) +{ + return gbphy_runtime_get_sync(to_gbphy_dev(dev)); +} + +static void gbphy_spi_unprepare_transfer_hardware(struct device *dev) +{ + gbphy_runtime_put_autosuspend(to_gbphy_dev(dev)); +} + +static struct spilib_ops __spilib_ops = { + .prepare_transfer_hardware = gbphy_spi_prepare_transfer_hardware, + .unprepare_transfer_hardware = gbphy_spi_unprepare_transfer_hardware, +}; + +static struct spilib_ops *spilib_ops = &__spilib_ops; +#else +static struct spilib_ops *spilib_ops = NULL; +#endif + static int gb_spi_probe(struct gbphy_device *gbphy_dev, const struct gbphy_device_id *id) { @@ -29,7 +50,7 @@ static int gb_spi_probe(struct gbphy_device *gbphy_dev, if (ret) goto exit_connection_destroy; - ret = gb_spilib_master_init(connection, &gbphy_dev->dev); + ret = gb_spilib_master_init(connection, &gbphy_dev->dev, spilib_ops); if (ret) goto exit_connection_disable; diff --git a/drivers/staging/greybus/spilib.c b/drivers/staging/greybus/spilib.c index e4c82e0..9427c31 100644 --- a/drivers/staging/greybus/spilib.c +++ b/drivers/staging/greybus/spilib.c @@ -15,13 +15,13 @@ #include "greybus.h" #include "spilib.h" -#include "gbphy.h" struct gb_spilib { struct gb_connection *connection; struct device *parent; struct spi_transfer *first_xfer; struct spi_transfer *last_xfer; + struct spilib_ops *ops; u32 rx_xfer_offset; u32 tx_xfer_offset; u32 last_xfer_size; @@ -373,25 +373,21 @@ out: return ret; } -#ifndef SPI_CORE_SUPPORT_PM static int gb_spi_prepare_transfer_hardware(struct spi_master *master) { struct gb_spilib *spi = spi_master_get_devdata(master); - struct gbphy_device *gbphy_dev = to_gbphy_dev(spi->parent); - return gbphy_runtime_get_sync(gbphy_dev); + return spi->ops->prepare_transfer_hardware(spi->parent); } static int gb_spi_unprepare_transfer_hardware(struct spi_master *master) { struct gb_spilib *spi = spi_master_get_devdata(master); - struct gbphy_device *gbphy_dev = to_gbphy_dev(spi->parent); - gbphy_runtime_put_autosuspend(gbphy_dev); + spi->ops->unprepare_transfer_hardware(spi->parent); return 0; } -#endif static int gb_spi_setup(struct spi_device *spi) { @@ -483,7 +479,8 @@ static int gb_spi_setup_device(struct gb_spilib *spi, u8 cs) return 0; } -int gb_spilib_master_init(struct gb_connection *connection, struct device *dev) +int gb_spilib_master_init(struct gb_connection *connection, struct device *dev, + struct spilib_ops *ops) { struct gb_spilib *spi; struct spi_master *master; @@ -501,6 +498,7 @@ int gb_spilib_master_init(struct gb_connection *connection, struct device *dev) spi->connection = connection; gb_connection_set_data(connection, master); spi->parent = dev; + spi->ops = ops; /* get master configuration */ ret = gb_spi_get_master_config(spi); @@ -518,11 +516,17 @@ int gb_spilib_master_init(struct gb_connection *connection, struct device *dev) master->setup = gb_spi_setup; master->transfer_one_message = gb_spi_transfer_one_message; -#ifndef SPI_CORE_SUPPORT_PM - master->prepare_transfer_hardware = gb_spi_prepare_transfer_hardware; - master->unprepare_transfer_hardware = + if (ops && ops->prepare_transfer_hardware) { + master->prepare_transfer_hardware = + gb_spi_prepare_transfer_hardware; + } + + if (ops && ops->unprepare_transfer_hardware) { + master->unprepare_transfer_hardware = gb_spi_unprepare_transfer_hardware; -#else + } + +#ifdef SPI_CORE_SUPPORT_PM master->auto_runtime_pm = true; #endif diff --git a/drivers/staging/greybus/spilib.h b/drivers/staging/greybus/spilib.h index 9be1b31..566d0dd 100644 --- a/drivers/staging/greybus/spilib.h +++ b/drivers/staging/greybus/spilib.h @@ -10,9 +10,15 @@ #ifndef __SPILIB_H #define __SPILIB_H +struct device; struct gb_connection; -int gb_spilib_master_init(struct gb_connection *connection, struct device *dev); +struct spilib_ops { + int (*prepare_transfer_hardware)(struct device *dev); + void (*unprepare_transfer_hardware)(struct device *dev); +}; + +int gb_spilib_master_init(struct gb_connection *connection, struct device *dev, struct spilib_ops *ops); void gb_spilib_master_exit(struct gb_connection *connection); #endif /* __SPILIB_H */ -- cgit v0.10.2 From 098dfaf45e76442d032207d2023930c685ab7c2e Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Fri, 22 Jul 2016 09:41:30 +0530 Subject: greybus: audio: Avoid using ARA keyword It is suggested to avoid using ARA keyword externally. So we need to update GB codec driver. Also, codec name is currently set to 'gb-codec'. However, it makes more sense to name it as apb-dummy-codec, since it is used to control various audio modules connected to APB via greybus. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 9c7bec7..d7679e6 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -1,5 +1,5 @@ /* - * audio codec driver + * APBridge ALSA SoC dummy codec driver * Copyright 2016 Google Inc. * Copyright 2016 Linaro Ltd. * @@ -1203,13 +1203,13 @@ static int gbaudio_codec_remove(struct platform_device *pdev) } static const struct of_device_id greybus_asoc_machine_of_match[] = { - { .compatible = "qcom,ara-codec", }, + { .compatible = "toshiba,apb-dummy-codec", }, {}, }; static struct platform_driver gbaudio_codec_driver = { .driver = { - .name = "gb-codec", + .name = "apb-dummy-codec", .owner = THIS_MODULE, #ifdef CONFIG_PM .pm = &gbaudio_codec_pm_ops, @@ -1221,7 +1221,7 @@ static struct platform_driver gbaudio_codec_driver = { }; module_platform_driver(gbaudio_codec_driver); -MODULE_DESCRIPTION("Greybus codec driver"); +MODULE_DESCRIPTION("APBridge ALSA SoC dummy codec driver"); MODULE_AUTHOR("Vaibhav Agarwal <vaibhav.agarwal@linaro.org>"); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:gbaudio-codec"); +MODULE_ALIAS("platform:apb-dummy-codec"); -- cgit v0.10.2 From e514dec730284da080286bdf7229d21c2be68b24 Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Fri, 22 Jul 2016 13:46:25 -0700 Subject: greybus: operation: print id when synchronous operation timeout In case of a synchronous operation timeout error, it's helpful for purpose of debugging to print the operation id in the error message, so that we know if the response is received at a later time after operation time out. Testing Done: - Observe the error message below when response comes later after operation timeout: [ 792.973978] greybus greybus1: 0/0:0: synchronous operation id 0x0005 of type 0x21 failed: -110 [ 800.646694] greybus greybus1: 0/0:0: unexpected response id 0x0005 received Signed-off-by: David Lin <dtwlin@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 659e84b..7475ec7 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -1128,8 +1128,8 @@ int gb_operation_sync_timeout(struct gb_connection *connection, int type, ret = gb_operation_request_send_sync_timeout(operation, timeout); if (ret) { dev_err(&connection->hd->dev, - "%s: synchronous operation of type 0x%02x failed: %d\n", - connection->name, type, ret); + "%s: synchronous operation id 0x%04x of type 0x%02x failed: %d\n", + connection->name, operation->id, type, ret); } else { if (response_size) { memcpy(response, operation->response->payload, -- cgit v0.10.2 From 553cba82b1ada07c8d29405c4900a66891c06052 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 21 Jul 2016 22:41:05 -0700 Subject: greybus: control: Print bundle-id in print messages The new power management specific operations added to the control protocol do not print the bundle-id in the error messages and it is not possible to identify which bundle-id the operation failed for. Fix that and do minor rewriting of the print messages to make them more readable. Tested on EVT 2.0 with gpbridge-test module. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Sandeep Patil <sspatil@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index a08a79d..d7fd378 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -259,14 +259,14 @@ int gb_control_bundle_suspend(struct gb_control *control, u8 bundle_id) GB_CONTROL_TYPE_BUNDLE_SUSPEND, &request, sizeof(request), &response, sizeof(response)); if (ret) { - dev_err(&control->dev, - "failed to send bundle suspend: %d\n", ret); + dev_err(&control->dev, "failed to send bundle %u suspend: %d\n", + bundle_id, ret); return ret; } if (response.status != GB_CONTROL_BUNDLE_PM_OK) { - dev_err(&control->dev, - "bundle error while suspending: %d\n", response.status); + dev_err(&control->dev, "failed to suspend bundle %u: %d\n", + bundle_id, response.status); return gb_control_bundle_pm_status_map(response.status); } @@ -284,14 +284,14 @@ int gb_control_bundle_resume(struct gb_control *control, u8 bundle_id) GB_CONTROL_TYPE_BUNDLE_RESUME, &request, sizeof(request), &response, sizeof(response)); if (ret) { - dev_err(&control->dev, - "failed to send bundle resume: %d\n", ret); + dev_err(&control->dev, "failed to send bundle %u resume: %d\n", + bundle_id, ret); return ret; } if (response.status != GB_CONTROL_BUNDLE_PM_OK) { - dev_err(&control->dev, - "bundle error while resuming: %d\n", response.status); + dev_err(&control->dev, "failed to resume bundle %u: %d\n", + bundle_id, response.status); return gb_control_bundle_pm_status_map(response.status); } @@ -310,13 +310,14 @@ int gb_control_bundle_deactivate(struct gb_control *control, u8 bundle_id) sizeof(request), &response, sizeof(response)); if (ret) { dev_err(&control->dev, - "failed to send bundle deactivate: %d\n", ret); + "failed to send bundle %u deactivate: %d\n", bundle_id, + ret); return ret; } if (response.status != GB_CONTROL_BUNDLE_PM_OK) { - dev_err(&control->dev, - "bundle error while deactivating: %d\n", response.status); + dev_err(&control->dev, "failed to deactivate bundle %u: %d\n", + bundle_id, response.status); return gb_control_bundle_pm_status_map(response.status); } @@ -338,13 +339,14 @@ int gb_control_bundle_activate(struct gb_control *control, u8 bundle_id) sizeof(request), &response, sizeof(response)); if (ret) { dev_err(&control->dev, - "failed to send bundle activate: %d\n", ret); + "failed to send bundle %u activate: %d\n", bundle_id, + ret); return ret; } if (response.status != GB_CONTROL_BUNDLE_PM_OK) { - dev_err(&control->dev, - "bundle error while activating: %d\n", response.status); + dev_err(&control->dev, "failed to activate bundle %u: %d\n", + bundle_id, response.status); return gb_control_bundle_pm_status_map(response.status); } -- cgit v0.10.2 From 633e45eaac40406739baae960d2c8abac40dbb83 Mon Sep 17 00:00:00 2001 From: Ann Chen <chen_ann@projectara.com> Date: Fri, 22 Jul 2016 15:33:55 +0800 Subject: greybus: vibrator: integrate runtime pm Integrate greybus drivers with the Linux Kernel RuntimePM framework for vibrator driver. Testing Done: AP side (kernel) can control the vibrator driver with suspend and resume. Signed-off-by: Ann Chen <chen_ann@projectara.com> Reviewed-by: David Lin <dtwlin@google.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/vibrator.c b/drivers/staging/greybus/vibrator.c index 33b2bf9c..db55839 100644 --- a/drivers/staging/greybus/vibrator.c +++ b/drivers/staging/greybus/vibrator.c @@ -13,6 +13,8 @@ #include <linux/device.h> #include <linux/kdev_t.h> #include <linux/idr.h> +#include <linux/pm_runtime.h> + #include "greybus.h" struct gb_vibrator_device { @@ -32,16 +34,37 @@ struct gb_vibrator_on_request { static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms) { struct gb_vibrator_on_request request; + struct gb_bundle *bundle = vib->connection->bundle; + int ret; + + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + return ret; request.timeout_ms = cpu_to_le16(timeout_ms); - return gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_ON, - &request, sizeof(request), NULL, 0); + ret = gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_ON, + &request, sizeof(request), NULL, 0); + + gb_pm_runtime_put_autosuspend(bundle); + + return ret; } static int turn_off(struct gb_vibrator_device *vib) { - return gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_OFF, - NULL, 0, NULL, 0); + struct gb_bundle *bundle = vib->connection->bundle; + int ret; + + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + return ret; + + ret = gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_OFF, + NULL, 0, NULL, 0); + + gb_pm_runtime_put_autosuspend(bundle); + + return ret; } static ssize_t timeout_store(struct device *dev, struct device_attribute *attr, @@ -151,6 +174,8 @@ static int gb_vibrator_probe(struct gb_bundle *bundle, } #endif + gb_pm_runtime_put_autosuspend(bundle); + return 0; err_ida_remove: @@ -168,6 +193,11 @@ err_free_vib: static void gb_vibrator_disconnect(struct gb_bundle *bundle) { struct gb_vibrator_device *vib = greybus_get_drvdata(bundle); + int ret; + + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + gb_pm_runtime_get_noresume(bundle); #if LINUX_VERSION_CODE <= KERNEL_VERSION(3,11,0) sysfs_remove_group(&vib->dev->kobj, vibrator_groups[0]); -- cgit v0.10.2 From cc90d6fce858cea167102380e57a63af2f75ec8b Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Fri, 22 Jul 2016 14:13:40 -0700 Subject: greybus: bootrom: Skip setting timeout in failure path of size request The currently set value of next_request_type in the error path of gb_bootrom_firmware_size_request() is not correct, as it should have been NEXT_REQ_FIRMWARE_SIZE for the failure case (as we should be waiting for another similar request). But, if an error occurs in gb_bootrom_firmware_size_request(), then the ES3 bootrom will never be able to recover from it and send another request. And so there is no point waiting for another request and timing out. Skip doing that in error path. Reported-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/bootrom.c b/drivers/staging/greybus/bootrom.c index 309e0a7..d16f13e 100644 --- a/drivers/staging/greybus/bootrom.c +++ b/drivers/staging/greybus/bootrom.c @@ -223,9 +223,11 @@ unlock: mutex_unlock(&bootrom->mutex); queue_work: - /* Refresh timeout */ - gb_bootrom_set_timeout(bootrom, NEXT_REQ_GET_FIRMWARE, - NEXT_REQ_TIMEOUT_MS); + if (!ret) { + /* Refresh timeout */ + gb_bootrom_set_timeout(bootrom, NEXT_REQ_GET_FIRMWARE, + NEXT_REQ_TIMEOUT_MS); + } return ret; } -- cgit v0.10.2 From 2d6f1c29988c0f5b51949bb674fe9dcdb923c4a6 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Fri, 22 Jul 2016 14:13:41 -0700 Subject: greybus: bootrom: Don't print duplicate error messages On failing to find a firmware image, we get these today: bootrom 1-3.3.1: Firmware request for ara_00000126_00001001_fffe0001_ffe5001a_s2l.tftf has failed : -12 bootrom 1-3.3.1: gb_bootrom_firmware_size_request: failed to download firmware (-12) Which are more or less duplicate, as they print error for the same root cause. With this patch this is all we get now: bootrom 1-3.3.1: failed to download ara_00000126_00001001_fffe0001_ffe5001a_s2l.tftf firmware (-12) Reported-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/bootrom.c b/drivers/staging/greybus/bootrom.c index d16f13e..c5b3971 100644 --- a/drivers/staging/greybus/bootrom.c +++ b/drivers/staging/greybus/bootrom.c @@ -171,10 +171,11 @@ static int download_firmware(struct gb_bootrom *bootrom, u8 stage) rc = request_firmware(&bootrom->fw, firmware_name, &connection->bundle->dev); - if (rc) - dev_err(&connection->bundle->dev, - "Firmware request for %s has failed : %d", + if (rc) { + dev_err(&connection->bundle->dev, "failed to download %s firmware (%d)\n", firmware_name, rc); + } + return rc; } @@ -200,11 +201,8 @@ static int gb_bootrom_firmware_size_request(struct gb_operation *op) mutex_lock(&bootrom->mutex); ret = download_firmware(bootrom, size_request->stage); - if (ret) { - dev_err(dev, "%s: failed to download firmware (%d)\n", __func__, - ret); + if (ret) goto unlock; - } if (!gb_operation_response_alloc(op, sizeof(*size_response), GFP_KERNEL)) { -- cgit v0.10.2 From 6d9e6ffca4226007672800a6681c42cc877aab60 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Fri, 22 Jul 2016 14:13:42 -0700 Subject: greybus: bootrom: Set timeout before sending AP_READY A special race is observed in the case where the phone boots with modules attached to it. In that case, the AP processes a later FIRMWARE_SIZE request from the bootrom, before processing the response to the earlier AP_READY request. And because of that, we set the timeout from gb_bootrom_probe() after trying to cancel it from gb_bootrom_firmware_size_request(). And with that, if the firmware package isn't available for the kernel to directly read from, then we get a timeout print message like below: [ 23.669764] bootrom 1-3.3.1: Firmware file 'ara_00000126_00001001_fffe0001_ffe5001a_s2l.tftf' requested [ 24.680528] bootrom 1-3.3.1: Timed out waiting for Firmware Size Request from the Module Note that this doesn't happen if the module is inserted into the frame, after the phone is already booted. This behavior is the result of an earlier commit cdd1cb3f4943 ("operation: add completion work queue"). This perhaps happens only at boot time because the UNBOUND wq (connection->wq) gets a chance to run on other CPUs, while the BOUND wq (gb_operation_completion_wq) doesn't at that stage (24 seconds since boot). Setting the timeout before sending the AP_READY request fixes it for now. Reported-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/bootrom.c b/drivers/staging/greybus/bootrom.c index c5b3971..7cc4d03 100644 --- a/drivers/staging/greybus/bootrom.c +++ b/drivers/staging/greybus/bootrom.c @@ -450,23 +450,25 @@ static int gb_bootrom_probe(struct gb_bundle *bundle, if (ret) goto err_connection_disable; + /* Refresh timeout */ + gb_bootrom_set_timeout(bootrom, NEXT_REQ_FIRMWARE_SIZE, + NEXT_REQ_TIMEOUT_MS); + /* Tell bootrom we're ready. */ ret = gb_operation_sync(connection, GB_BOOTROM_TYPE_AP_READY, NULL, 0, NULL, 0); if (ret) { dev_err(&connection->bundle->dev, "failed to send AP READY: %d\n", ret); - goto err_connection_disable; + goto err_cancel_timeout; } - /* Refresh timeout */ - gb_bootrom_set_timeout(bootrom, NEXT_REQ_FIRMWARE_SIZE, - NEXT_REQ_TIMEOUT_MS); - dev_dbg(&bundle->dev, "AP_READY sent\n"); return 0; +err_cancel_timeout: + cancel_delayed_work_sync(&bootrom->dwork); err_connection_disable: gb_connection_disable(connection); err_connection_destroy: -- cgit v0.10.2 From 40d276ede92e85e4f414ac655c217e0bf5292cbb Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Fri, 22 Jul 2016 14:13:43 -0700 Subject: greybus: bootrom: Create gb_bootrom_cancel_timeout() We set timeouts using gb_bootrom_set_timeout(), which hides the internal implementation, i.e. workqueues. While canceling timeouts, we do cancel_delayed_work_sync(), which exposes the internal implementation and doesn't look that clean. Create gb_bootrom_cancel_timeout() to hide the internal implementation here as well. Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/bootrom.c b/drivers/staging/greybus/bootrom.c index 7cc4d03..b90b25c 100644 --- a/drivers/staging/greybus/bootrom.c +++ b/drivers/staging/greybus/bootrom.c @@ -92,6 +92,11 @@ static void gb_bootrom_set_timeout(struct gb_bootrom *bootrom, schedule_delayed_work(&bootrom->dwork, msecs_to_jiffies(timeout)); } +static void gb_bootrom_cancel_timeout(struct gb_bootrom *bootrom) +{ + cancel_delayed_work_sync(&bootrom->dwork); +} + /* * The es2 chip doesn't have VID/PID programmed into the hardware and we need to * hack that up to distinguish different modules and their firmware blobs. @@ -188,7 +193,7 @@ static int gb_bootrom_firmware_size_request(struct gb_operation *op) int ret; /* Disable timeouts */ - cancel_delayed_work_sync(&bootrom->dwork); + gb_bootrom_cancel_timeout(bootrom); if (op->request->payload_size != sizeof(*size_request)) { dev_err(dev, "%s: illegal size of firmware size request (%zu != %zu)\n", @@ -242,7 +247,7 @@ static int gb_bootrom_get_firmware(struct gb_operation *op) int ret = 0; /* Disable timeouts */ - cancel_delayed_work_sync(&bootrom->dwork); + gb_bootrom_cancel_timeout(bootrom); if (op->request->payload_size != sizeof(*firmware_request)) { dev_err(dev, "%s: Illegal size of get firmware request (%zu %zu)\n", @@ -310,7 +315,7 @@ static int gb_bootrom_ready_to_boot(struct gb_operation *op) int ret = 0; /* Disable timeouts */ - cancel_delayed_work_sync(&bootrom->dwork); + gb_bootrom_cancel_timeout(bootrom); if (op->request->payload_size != sizeof(*rtb_request)) { dev_err(dev, "%s: Illegal size of ready to boot request (%zu %zu)\n", @@ -468,7 +473,7 @@ static int gb_bootrom_probe(struct gb_bundle *bundle, return 0; err_cancel_timeout: - cancel_delayed_work_sync(&bootrom->dwork); + gb_bootrom_cancel_timeout(bootrom); err_connection_disable: gb_connection_disable(connection); err_connection_destroy: @@ -488,7 +493,7 @@ static void gb_bootrom_disconnect(struct gb_bundle *bundle) gb_connection_disable(bootrom->connection); /* Disable timeouts */ - cancel_delayed_work_sync(&bootrom->dwork); + gb_bootrom_cancel_timeout(bootrom); /* * Release firmware: -- cgit v0.10.2 From 68793c4c8824a0b1e0cb89737c5919a0b10d70cf Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Fri, 22 Jul 2016 14:13:44 -0700 Subject: greybus: bootrom: Rename download_firmware() as find_firmware() The download_firmware() function isn't downloading the firmware but just finding if one is available or not. The same applies to the error message printed by it. Replace 'download' with 'find' to make it sound better. Reported-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/bootrom.c b/drivers/staging/greybus/bootrom.c index b90b25c..e7cfa80 100644 --- a/drivers/staging/greybus/bootrom.c +++ b/drivers/staging/greybus/bootrom.c @@ -140,7 +140,7 @@ static void bootrom_es2_fixup_vid_pid(struct gb_bootrom *bootrom) } /* This returns path of the firmware blob on the disk */ -static int download_firmware(struct gb_bootrom *bootrom, u8 stage) +static int find_firmware(struct gb_bootrom *bootrom, u8 stage) { struct gb_connection *connection = bootrom->connection; struct gb_interface *intf = connection->bundle->intf; @@ -177,8 +177,8 @@ static int download_firmware(struct gb_bootrom *bootrom, u8 stage) rc = request_firmware(&bootrom->fw, firmware_name, &connection->bundle->dev); if (rc) { - dev_err(&connection->bundle->dev, "failed to download %s firmware (%d)\n", - firmware_name, rc); + dev_err(&connection->bundle->dev, + "failed to find %s firmware (%d)\n", firmware_name, rc); } return rc; @@ -205,7 +205,7 @@ static int gb_bootrom_firmware_size_request(struct gb_operation *op) mutex_lock(&bootrom->mutex); - ret = download_firmware(bootrom, size_request->stage); + ret = find_firmware(bootrom, size_request->stage); if (ret) goto unlock; -- cgit v0.10.2 From 43c85a09b12cd3e782ae237be9903fef4559cc0d Mon Sep 17 00:00:00 2001 From: Philip Yang <yang_philip@projectara.com> Date: Sat, 23 Jul 2016 05:48:14 +0800 Subject: greybus: HID: Add runtime pm support Modify HID greybus driver to support runtime PM framework. The suspend and resume fucntion have been test with tutorial-hid, e-ink-display and gpbridge-test image by sysfs resume, all HID buttons work well on suspend/resume. Testing Done: Compiled and verified on EVT2, DB3.5, GPB test module with daughter board, Red module. Signed-off-by: Philip Yang <yang_philip@projectara.com> Reviewed-by: David Lin <dtwlin@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index ca0c949..b558c81 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -18,6 +18,7 @@ /* Greybus HID device's structure */ struct gb_hid { + struct gb_bundle *bundle; struct gb_connection *connection; struct hid_device *hid; @@ -44,26 +45,55 @@ static int gb_hid_get_desc(struct gb_hid *ghid) static int gb_hid_get_report_desc(struct gb_hid *ghid, char *rdesc) { - return gb_operation_sync(ghid->connection, GB_HID_TYPE_GET_REPORT_DESC, + int ret; + + ret = gb_pm_runtime_get_sync(ghid->bundle); + if (ret) + return ret; + + ret = gb_operation_sync(ghid->connection, GB_HID_TYPE_GET_REPORT_DESC, NULL, 0, rdesc, le16_to_cpu(ghid->hdesc.wReportDescLength)); + + gb_pm_runtime_put_autosuspend(ghid->bundle); + + return ret; } static int gb_hid_set_power(struct gb_hid *ghid, int type) { - return gb_operation_sync(ghid->connection, type, NULL, 0, NULL, 0); + int ret; + + ret = gb_pm_runtime_get_sync(ghid->bundle); + if (ret) + return ret; + + ret = gb_operation_sync(ghid->connection, type, NULL, 0, NULL, 0); + + gb_pm_runtime_put_autosuspend(ghid->bundle); + + return ret; } static int gb_hid_get_report(struct gb_hid *ghid, u8 report_type, u8 report_id, unsigned char *buf, int len) { struct gb_hid_get_report_request request; + int ret; + + ret = gb_pm_runtime_get_sync(ghid->bundle); + if (ret) + return ret; request.report_type = report_type; request.report_id = report_id; - return gb_operation_sync(ghid->connection, GB_HID_TYPE_GET_REPORT, + ret = gb_operation_sync(ghid->connection, GB_HID_TYPE_GET_REPORT, &request, sizeof(request), buf, len); + + gb_pm_runtime_put_autosuspend(ghid->bundle); + + return ret; } static int gb_hid_set_report(struct gb_hid *ghid, u8 report_type, u8 report_id, @@ -73,11 +103,17 @@ static int gb_hid_set_report(struct gb_hid *ghid, u8 report_type, u8 report_id, struct gb_operation *operation; int ret, size = sizeof(*request) + len - 1; + ret = gb_pm_runtime_get_sync(ghid->bundle); + if (ret) + return ret; + operation = gb_operation_create(ghid->connection, GB_HID_TYPE_SET_REPORT, size, 0, GFP_KERNEL); - if (!operation) + if (!operation) { + gb_pm_runtime_put_autosuspend(ghid->bundle); return -ENOMEM; + } request = operation->request->payload; request->report_type = report_type; @@ -93,6 +129,7 @@ static int gb_hid_set_report(struct gb_hid *ghid, u8 report_type, u8 report_id, } gb_operation_put(operation); + gb_pm_runtime_put_autosuspend(ghid->bundle); return ret; } @@ -458,6 +495,7 @@ static int gb_hid_probe(struct gb_bundle *bundle, } ghid->hid = hid; + ghid->bundle = bundle; greybus_set_drvdata(bundle, ghid); @@ -475,6 +513,8 @@ static int gb_hid_probe(struct gb_bundle *bundle, goto err_connection_disable; } + gb_pm_runtime_put_autosuspend(bundle); + return 0; err_connection_disable: @@ -493,6 +533,9 @@ static void gb_hid_disconnect(struct gb_bundle *bundle) { struct gb_hid *ghid = greybus_get_drvdata(bundle); + if (gb_pm_runtime_get_sync(bundle)) + gb_pm_runtime_get_noresume(bundle); + hid_destroy_device(ghid->hid); gb_connection_disable(ghid->connection); gb_connection_destroy(ghid->connection); -- cgit v0.10.2 From b75b23bc59cda08c99050a9dc14acd43aac66afc Mon Sep 17 00:00:00 2001 From: Alison Schofield <amsfield22@gmail.com> Date: Fri, 15 Jul 2016 19:28:47 -0700 Subject: staging: iio: light: isl29018/28: remove I2C_CLASS_HWMON .class setting I2C_CLASS_HWMON is for a hardware monitoring chip wanting auto-detection. IIO drivers don't typically use .class. Remove it. Signed-off-by: Alison Schofield <amsfield22@gmail.com> Cc: Daniel Baluta <daniel.baluta@gmail.com> Acked-by: Laxman Dewangan <ldewangan@nvidia.com> Acked-by: Wolfram Sang <wsa@the-dreams.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index 80b6a9e..f47a17d 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -823,7 +823,6 @@ static const struct of_device_id isl29018_of_match[] = { MODULE_DEVICE_TABLE(of, isl29018_of_match); static struct i2c_driver isl29018_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "isl29018", .acpi_match_table = ACPI_PTR(isl29018_acpi_match), diff --git a/drivers/staging/iio/light/isl29028.c b/drivers/staging/iio/light/isl29028.c index a238b16..aa413e5 100644 --- a/drivers/staging/iio/light/isl29028.c +++ b/drivers/staging/iio/light/isl29028.c @@ -546,7 +546,6 @@ static const struct of_device_id isl29028_of_match[] = { MODULE_DEVICE_TABLE(of, isl29028_of_match); static struct i2c_driver isl29028_driver = { - .class = I2C_CLASS_HWMON, .driver = { .name = "isl29028", .of_match_table = isl29028_of_match, -- cgit v0.10.2 From 4d19c487555e8fe6e40f645c17e12cc30d4a18bf Mon Sep 17 00:00:00 2001 From: Christophe Chapuis <chris.chapuis@gmail.com> Date: Sun, 17 Jul 2016 10:15:15 +0200 Subject: iio: accel: kxcjk-1013: add the "KIOX000A" ACPI id On the Cube i9 tablet, the ACPI id for the Kionix kxcj9 accelerometer is "KIOX000A" (as can be seen in the DSDT of the Cube i9 tablet). It is the same accelerometer, so only adding the ACPI id is needed. Signed-off-by: Christophe Chapuis <chris.chapuis@gmail.com> Reviewed-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index 765a723..3f968c4 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -1392,6 +1392,7 @@ static const struct acpi_device_id kx_acpi_match[] = { {"KXCJ1013", KXCJK1013}, {"KXCJ1008", KXCJ91008}, {"KXCJ9000", KXCJ91008}, + {"KIOX000A", KXCJ91008}, {"KXTJ1009", KXTJ21009}, {"SMO8500", KXCJ91008}, { }, -- cgit v0.10.2 From b4d46409d603ab041bcb1ac9858d076d29e78af8 Mon Sep 17 00:00:00 2001 From: Alison Schofield <amsfield22@gmail.com> Date: Mon, 18 Jul 2016 12:35:24 -0700 Subject: iio: adc: ad7793: use iio helper function to guarantee direct mode Replace the code that guarantees the device stays in direct mode with iio_device_claim_direct_mode() which does same. Signed-off-by: Alison Schofield <amsfield22@gmail.com> Cc: Daniel Baluta <daniel.baluta@gmail.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/adc/ad7793.c b/drivers/iio/adc/ad7793.c index 847789b..e6706a0 100644 --- a/drivers/iio/adc/ad7793.c +++ b/drivers/iio/adc/ad7793.c @@ -519,11 +519,9 @@ static int ad7793_write_raw(struct iio_dev *indio_dev, int ret, i; unsigned int tmp; - mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) { - mutex_unlock(&indio_dev->mlock); - return -EBUSY; - } + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; switch (mask) { case IIO_CHAN_INFO_SCALE: @@ -548,7 +546,7 @@ static int ad7793_write_raw(struct iio_dev *indio_dev, ret = -EINVAL; } - mutex_unlock(&indio_dev->mlock); + iio_device_release_direct_mode(indio_dev); return ret; } -- cgit v0.10.2 From d02ec00d00a5eb5e0ca8ef6ddf0a3774adb52b6a Mon Sep 17 00:00:00 2001 From: Alison Schofield <amsfield22@gmail.com> Date: Mon, 18 Jul 2016 12:34:17 -0700 Subject: iio: adc: ad7298: use iio helper function to guarantee direct mode Replace the code that guarantees the device stays in direct mode with iio_device_claim_direct_mode() which does same. Signed-off-by: Alison Schofield <amsfield22@gmail.com> Cc: Daniel Baluta <daniel.baluta@gmail.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/adc/ad7298.c b/drivers/iio/adc/ad7298.c index 10ec8fc..e399bf0 100644 --- a/drivers/iio/adc/ad7298.c +++ b/drivers/iio/adc/ad7298.c @@ -239,16 +239,16 @@ static int ad7298_read_raw(struct iio_dev *indio_dev, switch (m) { case IIO_CHAN_INFO_RAW: - mutex_lock(&indio_dev->mlock); - if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) { - ret = -EBUSY; - } else { - if (chan->address == AD7298_CH_TEMP) - ret = ad7298_scan_temp(st, val); - else - ret = ad7298_scan_direct(st, chan->address); - } - mutex_unlock(&indio_dev->mlock); + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + + if (chan->address == AD7298_CH_TEMP) + ret = ad7298_scan_temp(st, val); + else + ret = ad7298_scan_direct(st, chan->address); + + iio_device_release_direct_mode(indio_dev); if (ret < 0) return ret; -- cgit v0.10.2 From 3b8df5fd526e70e8c89e47e3fcb253b80f6192f6 Mon Sep 17 00:00:00 2001 From: William Breathitt Gray <vilhelm.gray@gmail.com> Date: Tue, 12 Jul 2016 09:33:14 -0400 Subject: iio: Add IIO support for the Measurement Computing CIO-DAC family The Measurement Computing CIO-DAC is a family of 16-bit and 12-bit analog output devices. The analog outputs are from AD660BN/AD7237 converters with each output buffered by an OP-27. Voltage ranges are configured via physical jumpers on the device. This driver does not support the devices' simulataneous update mode; the XFER jumper option should be deselected for all analog output channels. This driver provides IIO support for the Measurement Computing CIO-DAC family: CIO-DAC16, CIO-DAC08, and PC104-DAC06. The base port addresses for the devices may be configured via the base array module parameter. Signed-off-by: William Breathitt Gray <vilhelm.gray@gmail.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/MAINTAINERS b/MAINTAINERS index 345e757..b5c802d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7318,6 +7318,12 @@ L: linux-iio@vger.kernel.org S: Maintained F: drivers/iio/potentiometer/mcp4531.c +MEASUREMENT COMPUTING CIO-DAC IIO DRIVER +M: William Breathitt Gray <vilhelm.gray@gmail.com> +L: linux-iio@vger.kernel.org +S: Maintained +F: drivers/iio/dac/cio-dac.c + MEDIA DRIVERS FOR RENESAS - VSP1 M: Laurent Pinchart <laurent.pinchart@ideasonboard.com> L: linux-media@vger.kernel.org diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index ca81447..b9f0442 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig @@ -181,6 +181,15 @@ config AD7303 To compile this driver as module choose M here: the module will be called ad7303. +config CIO_DAC + tristate "Measurement Computing CIO-DAC IIO driver" + depends on X86 && ISA_BUS_API + help + Say yes here to build support for the Measurement Computing CIO-DAC + analog output device family (CIO-DAC16, CIO-DAC08, PC104-DAC06). The + base port addresses for the devices may be configured via the base + array module parameter. + config LPC18XX_DAC tristate "NXP LPC18xx DAC driver" depends on ARCH_LPC18XX || COMPILE_TEST diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile index 8b78d5c..b1a1206 100644 --- a/drivers/iio/dac/Makefile +++ b/drivers/iio/dac/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_AD5764) += ad5764.o obj-$(CONFIG_AD5791) += ad5791.o obj-$(CONFIG_AD5686) += ad5686.o obj-$(CONFIG_AD7303) += ad7303.o +obj-$(CONFIG_CIO_DAC) += cio-dac.o obj-$(CONFIG_LPC18XX_DAC) += lpc18xx_dac.o obj-$(CONFIG_M62332) += m62332.o obj-$(CONFIG_MAX517) += max517.o diff --git a/drivers/iio/dac/cio-dac.c b/drivers/iio/dac/cio-dac.c new file mode 100644 index 0000000..5a743e2 --- /dev/null +++ b/drivers/iio/dac/cio-dac.c @@ -0,0 +1,144 @@ +/* + * IIO driver for the Measurement Computing CIO-DAC + * Copyright (C) 2016 William Breathitt Gray + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * This driver supports the following Measurement Computing devices: CIO-DAC16, + * CIO-DAC06, and PC104-DAC06. + */ +#include <linux/bitops.h> +#include <linux/device.h> +#include <linux/errno.h> +#include <linux/iio/iio.h> +#include <linux/iio/types.h> +#include <linux/io.h> +#include <linux/ioport.h> +#include <linux/isa.h> +#include <linux/module.h> +#include <linux/moduleparam.h> + +#define CIO_DAC_NUM_CHAN 16 + +#define CIO_DAC_CHAN(chan) { \ + .type = IIO_VOLTAGE, \ + .channel = chan, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .indexed = 1, \ + .output = 1 \ +} + +#define CIO_DAC_EXTENT 32 + +static unsigned int base[max_num_isa_dev(CIO_DAC_EXTENT)]; +static unsigned int num_cio_dac; +module_param_array(base, uint, &num_cio_dac, 0); +MODULE_PARM_DESC(base, "Measurement Computing CIO-DAC base addresses"); + +/** + * struct cio_dac_iio - IIO device private data structure + * @chan_out_states: channels' output states + * @base: base port address of the IIO device + */ +struct cio_dac_iio { + int chan_out_states[CIO_DAC_NUM_CHAN]; + unsigned int base; +}; + +static int cio_dac_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, int *val2, long mask) +{ + struct cio_dac_iio *const priv = iio_priv(indio_dev); + + if (mask != IIO_CHAN_INFO_RAW) + return -EINVAL; + + *val = priv->chan_out_states[chan->channel]; + + return IIO_VAL_INT; +} + +static int cio_dac_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, int val2, long mask) +{ + struct cio_dac_iio *const priv = iio_priv(indio_dev); + const unsigned int chan_addr_offset = 2 * chan->channel; + + if (mask != IIO_CHAN_INFO_RAW) + return -EINVAL; + + /* DAC can only accept up to a 16-bit value */ + if ((unsigned int)val > 65535) + return -EINVAL; + + priv->chan_out_states[chan->channel] = val; + outw(val, priv->base + chan_addr_offset); + + return 0; +} + +static const struct iio_info cio_dac_info = { + .driver_module = THIS_MODULE, + .read_raw = cio_dac_read_raw, + .write_raw = cio_dac_write_raw +}; + +static const struct iio_chan_spec cio_dac_channels[CIO_DAC_NUM_CHAN] = { + CIO_DAC_CHAN(0), CIO_DAC_CHAN(1), CIO_DAC_CHAN(2), CIO_DAC_CHAN(3), + CIO_DAC_CHAN(4), CIO_DAC_CHAN(5), CIO_DAC_CHAN(6), CIO_DAC_CHAN(7), + CIO_DAC_CHAN(8), CIO_DAC_CHAN(9), CIO_DAC_CHAN(10), CIO_DAC_CHAN(11), + CIO_DAC_CHAN(12), CIO_DAC_CHAN(13), CIO_DAC_CHAN(14), CIO_DAC_CHAN(15) +}; + +static int cio_dac_probe(struct device *dev, unsigned int id) +{ + struct iio_dev *indio_dev; + struct cio_dac_iio *priv; + unsigned int i; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*priv)); + if (!indio_dev) + return -ENOMEM; + + if (!devm_request_region(dev, base[id], CIO_DAC_EXTENT, + dev_name(dev))) { + dev_err(dev, "Unable to request port addresses (0x%X-0x%X)\n", + base[id], base[id] + CIO_DAC_EXTENT); + return -EBUSY; + } + + indio_dev->info = &cio_dac_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = cio_dac_channels; + indio_dev->num_channels = CIO_DAC_NUM_CHAN; + indio_dev->name = dev_name(dev); + + priv = iio_priv(indio_dev); + priv->base = base[id]; + + /* initialize DAC outputs to 0V */ + for (i = 0; i < 32; i += 2) + outw(0, base[id] + i); + + return devm_iio_device_register(dev, indio_dev); +} + +static struct isa_driver cio_dac_driver = { + .probe = cio_dac_probe, + .driver = { + .name = "cio-dac" + } +}; + +module_isa_driver(cio_dac_driver, num_cio_dac); + +MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); +MODULE_DESCRIPTION("Measurement Computing CIO-DAC IIO driver"); +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From dfcba8626f55fe5d6ba6e2847178cbf629740773 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Tue, 26 Jul 2016 17:11:28 +0200 Subject: greybus: operation: fix broken response error messages The operation type included in the error message printed for malformed responses has never been correct. An uninitialised buffer was used to retrieve the type, resulting in the type always being reported as 0. Fix this by passing a properly aligned header to the response handler, and drop the now redundant id and result parameters. Fixes: cb0ef0c019ab ("operation: print message type on errors") Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@linaro.org> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 7475ec7..e26b1e1 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -928,13 +928,16 @@ static void gb_connection_recv_request(struct gb_connection *connection, * data into the response buffer and handle the rest via workqueue. */ static void gb_connection_recv_response(struct gb_connection *connection, - u16 operation_id, u8 result, void *data, size_t size) + const struct gb_operation_msg_hdr *header, + void *data, size_t size) { - struct gb_operation_msg_hdr *header; struct gb_operation *operation; struct gb_message *message; - int errno = gb_operation_status_map(result); size_t message_size; + u16 operation_id; + int errno; + + operation_id = le16_to_cpu(header->operation_id); if (!operation_id) { dev_err_ratelimited(&connection->hd->dev, @@ -951,8 +954,8 @@ static void gb_connection_recv_response(struct gb_connection *connection, return; } + errno = gb_operation_status_map(header->result); message = operation->response; - header = message->header; message_size = sizeof(*header) + message->payload_size; if (!errno && size > message_size) { dev_err_ratelimited(&connection->hd->dev, @@ -979,7 +982,7 @@ static void gb_connection_recv_response(struct gb_connection *connection, /* The rest will be handled in work queue context */ if (gb_operation_result_set(operation, errno)) { - memcpy(header, data, size); + memcpy(message->buffer, data, size); queue_work(gb_operation_completion_wq, &operation->work); } @@ -1026,8 +1029,8 @@ void gb_connection_recv(struct gb_connection *connection, operation_id = le16_to_cpu(header.operation_id); if (header.type & GB_MESSAGE_TYPE_RESPONSE) - gb_connection_recv_response(connection, operation_id, - header.result, data, msg_size); + gb_connection_recv_response(connection, &header, data, + msg_size); else gb_connection_recv_request(connection, operation_id, header.type, data, msg_size); -- cgit v0.10.2 From 112f563e1879ab73853fed9d875f45d96d5990fd Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Tue, 26 Jul 2016 17:11:29 +0200 Subject: greybus: operation: fix broken response tracepoint The response-received tracepoint is currently broken. Instead of parsing the received message header it was tracing a bunch of zeroed fields from an uninitialised response buffer. Fix this by moving the tracepoint after were the response buffer is initialised. Fixes: 7cb496e6890e ("greybus: tracing: fix message traces") Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index e26b1e1..b9692b7 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -974,7 +974,6 @@ static void gb_connection_recv_response(struct gb_connection *connection, errno = -EMSGSIZE; } } - trace_gb_message_recv_response(operation->response); /* We must ignore the payload if a bad status is returned */ if (errno) @@ -983,6 +982,9 @@ static void gb_connection_recv_response(struct gb_connection *connection, /* The rest will be handled in work queue context */ if (gb_operation_result_set(operation, errno)) { memcpy(message->buffer, data, size); + + trace_gb_message_recv_response(message); + queue_work(gb_operation_completion_wq, &operation->work); } -- cgit v0.10.2 From 2321f049a93368fffc3375cfbf2f9f9561ef1e69 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Tue, 26 Jul 2016 17:11:30 +0200 Subject: greybus: operation: clean up request handler Clean up the incoming request handler somewhat by passing a properly aligned header and dropping the now redundant id and type parameters. Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@linaro.org> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index b9692b7..0123109 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -889,12 +889,17 @@ EXPORT_SYMBOL_GPL(greybus_message_sent); * data into the request buffer and handle the rest via workqueue. */ static void gb_connection_recv_request(struct gb_connection *connection, - u16 operation_id, u8 type, - void *data, size_t size) + const struct gb_operation_msg_hdr *header, + void *data, size_t size) { struct gb_operation *operation; + u16 operation_id; + u8 type; int ret; + operation_id = le16_to_cpu(header->operation_id); + type = header->type; + operation = gb_operation_create_incoming(connection, operation_id, type, data, size); if (!operation) { @@ -1002,7 +1007,6 @@ void gb_connection_recv(struct gb_connection *connection, struct gb_operation_msg_hdr header; struct device *dev = &connection->hd->dev; size_t msg_size; - u16 operation_id; if (connection->state == GB_CONNECTION_STATE_DISABLED || gb_connection_is_offloaded(connection)) { @@ -1029,13 +1033,13 @@ void gb_connection_recv(struct gb_connection *connection, return; /* XXX Should still complete operation */ } - operation_id = le16_to_cpu(header.operation_id); - if (header.type & GB_MESSAGE_TYPE_RESPONSE) + if (header.type & GB_MESSAGE_TYPE_RESPONSE) { gb_connection_recv_response(connection, &header, data, msg_size); - else - gb_connection_recv_request(connection, operation_id, - header.type, data, msg_size); + } else { + gb_connection_recv_request(connection, &header, data, + msg_size); + } } /* -- cgit v0.10.2 From c57fbb404af28eda44d0590ede8812b889a89b8c Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Tue, 26 Jul 2016 13:41:02 -0700 Subject: greybus: firmware: Add runtime PM support This patch implements runtime PM support for firmware management bundle. This guarantees that the bundle will be active, while the AP or the Module is trying to exchange any operations over any of the CPorts. - Firmware Management CPort: Runtime PM get/put calls are placed around the ioctl calls, which are all implemented as blocking ioctls. - Component Authentication CPort: Runtime PM get/put calls are placed around the ioctl calls, which are all implemented as blocking ioctls. - SPI: Uses the interface provided by spilib.c and runtime PM get/put are called around connection usage. - firmware-download: This is the most tricky one. All operations on this CPort are initiated from the Module and not from the AP. And the AP needs to do runtime_pm_get() before any request is received over this CPort. The module doesn't send any request over this connection, unless the AP has requested the module over firmware management CPort to download a firmware package over firmware download CPort. And so the runtime PM get/put calls around the ioctls in fw-management.c are sufficient to handle the firmware management CPort as well. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/authentication.c b/drivers/staging/greybus/authentication.c index a4ac3bb..168626b 100644 --- a/drivers/staging/greybus/authentication.c +++ b/drivers/staging/greybus/authentication.c @@ -265,6 +265,7 @@ static long cap_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg) { struct gb_cap *cap = file->private_data; + struct gb_bundle *bundle = cap->connection->bundle; int ret = -ENODEV; /* @@ -278,8 +279,13 @@ static long cap_ioctl_unlocked(struct file *file, unsigned int cmd, * new operations. */ mutex_lock(&cap->mutex); - if (!cap->disabled) - ret = cap_ioctl(cap, cmd, (void __user *)arg); + if (!cap->disabled) { + ret = gb_pm_runtime_get_sync(bundle); + if (!ret) { + ret = cap_ioctl(cap, cmd, (void __user *)arg); + gb_pm_runtime_put_autosuspend(bundle); + } + } mutex_unlock(&cap->mutex); return ret; diff --git a/drivers/staging/greybus/fw-core.c b/drivers/staging/greybus/fw-core.c index 19f92fb..56296db 100644 --- a/drivers/staging/greybus/fw-core.c +++ b/drivers/staging/greybus/fw-core.c @@ -20,6 +20,27 @@ struct gb_fw_core { struct gb_connection *cap_connection; }; +#ifndef SPI_CORE_SUPPORT_PM +static int fw_spi_prepare_transfer_hardware(struct device *dev) +{ + return gb_pm_runtime_get_sync(to_gb_bundle(dev)); +} + +static void fw_spi_unprepare_transfer_hardware(struct device *dev) +{ + gb_pm_runtime_put_autosuspend(to_gb_bundle(dev)); +} + +static struct spilib_ops __spilib_ops = { + .prepare_transfer_hardware = fw_spi_prepare_transfer_hardware, + .unprepare_transfer_hardware = fw_spi_unprepare_transfer_hardware, +}; + +static struct spilib_ops *spilib_ops = &__spilib_ops; +#else +static struct spilib_ops *spilib_ops = NULL; +#endif + struct gb_connection *to_fw_mgmt_connection(struct device *dev) { struct gb_fw_core *fw_core = dev_get_drvdata(dev); @@ -38,7 +59,8 @@ static int gb_fw_spi_connection_init(struct gb_connection *connection) if (ret) return ret; - ret = gb_spilib_master_init(connection, &connection->bundle->dev, NULL); + ret = gb_spilib_master_init(connection, &connection->bundle->dev, + spilib_ops); if (ret) { gb_connection_disable(connection); return ret; @@ -206,6 +228,8 @@ static int gb_fw_core_probe(struct gb_bundle *bundle, greybus_set_drvdata(bundle, fw_core); + gb_pm_runtime_put_autosuspend(bundle); + return 0; err_exit_connections: @@ -225,6 +249,11 @@ err_destroy_connections: static void gb_fw_core_disconnect(struct gb_bundle *bundle) { struct gb_fw_core *fw_core = greybus_get_drvdata(bundle); + int ret; + + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + gb_pm_runtime_get_noresume(bundle); gb_fw_mgmt_connection_exit(fw_core->mgmt_connection); gb_cap_connection_exit(fw_core->cap_connection); diff --git a/drivers/staging/greybus/fw-management.c b/drivers/staging/greybus/fw-management.c index ccd9d7c..2efe65c 100644 --- a/drivers/staging/greybus/fw-management.c +++ b/drivers/staging/greybus/fw-management.c @@ -507,6 +507,7 @@ static long fw_mgmt_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg) { struct fw_mgmt *fw_mgmt = file->private_data; + struct gb_bundle *bundle = fw_mgmt->connection->bundle; int ret = -ENODEV; /* @@ -522,8 +523,13 @@ static long fw_mgmt_ioctl_unlocked(struct file *file, unsigned int cmd, * new operations. */ mutex_lock(&fw_mgmt->mutex); - if (!fw_mgmt->disabled) - ret = fw_mgmt_ioctl(fw_mgmt, cmd, (void __user *)arg); + if (!fw_mgmt->disabled) { + ret = gb_pm_runtime_get_sync(bundle); + if (!ret) { + ret = fw_mgmt_ioctl(fw_mgmt, cmd, (void __user *)arg); + gb_pm_runtime_put_autosuspend(bundle); + } + } mutex_unlock(&fw_mgmt->mutex); return ret; -- cgit v0.10.2 From 47cbaf5e55a6906f404da06cab652cd19aa37537 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Tue, 26 Jul 2016 13:41:03 -0700 Subject: greybus: interface: Rename *_NO_PM as *_NO_BUNDLE_ACTIVATE Its a special quirk just for the bootrom as it doesn't have any PM operations implemented. As the greybus bootrom bundle driver doesn't try to do any PM stuff, this quirk is used only to skip bundle activate operation currently. Rename the GB_INTERFACE_QUIRK_NO_PM quirk to GB_INTERFACE_QUIRK_NO_BUNDLE_ACTIVATE to suit its purpose better as the GB_INTERFACE_QUIRK_NO_PM will be used for other quirk now. Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index d7fd378..34493d5 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -534,7 +534,7 @@ int gb_control_enable(struct gb_control *control) control->has_bundle_version = true; /* FIXME: use protocol version instead */ - if (!(control->intf->quirks & GB_INTERFACE_QUIRK_NO_PM)) + if (!(control->intf->quirks & GB_INTERFACE_QUIRK_NO_BUNDLE_ACTIVATE)) control->has_bundle_activate = true; return 0; diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 74fa298..c20077a 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -412,7 +412,7 @@ static int gb_interface_read_and_clear_init_status(struct gb_interface *intf) bootrom_quirks = GB_INTERFACE_QUIRK_NO_CPORT_FEATURES | GB_INTERFACE_QUIRK_FORCED_DISABLE | GB_INTERFACE_QUIRK_LEGACY_MODE_SWITCH | - GB_INTERFACE_QUIRK_NO_PM; + GB_INTERFACE_QUIRK_NO_BUNDLE_ACTIVATE; switch (init_status) { case GB_INIT_BOOTROM_UNIPRO_BOOT_STARTED: case GB_INIT_BOOTROM_FALLBACK_UNIPRO_BOOT_STARTED: diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index a08d104..89eecf0 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -23,7 +23,7 @@ enum gb_interface_type { #define GB_INTERFACE_QUIRK_NO_ARA_IDS BIT(2) #define GB_INTERFACE_QUIRK_FORCED_DISABLE BIT(3) #define GB_INTERFACE_QUIRK_LEGACY_MODE_SWITCH BIT(4) -#define GB_INTERFACE_QUIRK_NO_PM BIT(5) +#define GB_INTERFACE_QUIRK_NO_BUNDLE_ACTIVATE BIT(5) struct gb_interface { struct device dev; -- cgit v0.10.2 From 0c543f9bb2dfa4239a601bff70e66020c2daec59 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Tue, 26 Jul 2016 13:41:04 -0700 Subject: greybus: interface: Add quirk for no PM for S2 Loader S2 Loader doesn't support runtime PM operations currently and we will fail to suspend/resume the bundle for firmware management protocols. Once that happens, the bundle and its connections will be pretty much useless as we would have tried to disable/enable all connections during such an operation and the S2 loader doesn't expect the connections to go away during normal operation (except in the case of mode-switch). This patch defines a new quirk GB_INTERFACE_QUIRK_NO_PM and uses a new interface init status value (GB_INIT_S2_LOADER_INITIALIZED) which will be advertised by S2 Loader now in the init status. After detecting the currently running stage as S2 Loader, the kernel wouldn't attempt suspending or resuming the bundle. Reviewed-by: David Lin <dtwlin@google.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/fw-core.c b/drivers/staging/greybus/fw-core.c index 56296db..a7e4a8c 100644 --- a/drivers/staging/greybus/fw-core.c +++ b/drivers/staging/greybus/fw-core.c @@ -228,7 +228,9 @@ static int gb_fw_core_probe(struct gb_bundle *bundle, greybus_set_drvdata(bundle, fw_core); - gb_pm_runtime_put_autosuspend(bundle); + /* FIXME: Remove this after S2 Loader gets runtime PM support */ + if (!(bundle->intf->quirks & GB_INTERFACE_QUIRK_NO_PM)) + gb_pm_runtime_put_autosuspend(bundle); return 0; @@ -251,9 +253,12 @@ static void gb_fw_core_disconnect(struct gb_bundle *bundle) struct gb_fw_core *fw_core = greybus_get_drvdata(bundle); int ret; - ret = gb_pm_runtime_get_sync(bundle); - if (ret) - gb_pm_runtime_get_noresume(bundle); + /* FIXME: Remove this after S2 Loader gets runtime PM support */ + if (!(bundle->intf->quirks & GB_INTERFACE_QUIRK_NO_PM)) { + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + gb_pm_runtime_get_noresume(bundle); + } gb_fw_mgmt_connection_exit(fw_core->mgmt_connection); gb_cap_connection_exit(fw_core->cap_connection); diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index c7fcb85..2de5aef 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -1145,6 +1145,7 @@ struct gb_svc_dme_peer_set_response { #define GB_INIT_UNTRUSTED_SPI_BOOT_FINISHED 0x04 #define GB_INIT_BOOTROM_UNIPRO_BOOT_STARTED 0x06 #define GB_INIT_BOOTROM_FALLBACK_UNIPRO_BOOT_STARTED 0x09 +#define GB_INIT_S2_LOADER_BOOT_STARTED 0x0D struct gb_svc_route_create_request { __u8 intf1_id; diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index c20077a..faa6239 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -363,6 +363,7 @@ static int gb_interface_read_and_clear_init_status(struct gb_interface *intf) { struct gb_host_device *hd = intf->hd; unsigned long bootrom_quirks; + unsigned long s2l_quirks; int ret; u32 value; u16 attr; @@ -413,13 +414,22 @@ static int gb_interface_read_and_clear_init_status(struct gb_interface *intf) GB_INTERFACE_QUIRK_FORCED_DISABLE | GB_INTERFACE_QUIRK_LEGACY_MODE_SWITCH | GB_INTERFACE_QUIRK_NO_BUNDLE_ACTIVATE; + + s2l_quirks = GB_INTERFACE_QUIRK_NO_PM; + switch (init_status) { case GB_INIT_BOOTROM_UNIPRO_BOOT_STARTED: case GB_INIT_BOOTROM_FALLBACK_UNIPRO_BOOT_STARTED: intf->quirks |= bootrom_quirks; break; + case GB_INIT_S2_LOADER_BOOT_STARTED: + /* S2 Loader doesn't support runtime PM */ + intf->quirks &= ~bootrom_quirks; + intf->quirks |= s2l_quirks; + break; default: intf->quirks &= ~bootrom_quirks; + intf->quirks &= ~s2l_quirks; } /* Clear the init status. */ diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 89eecf0..174bc74 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -24,6 +24,7 @@ enum gb_interface_type { #define GB_INTERFACE_QUIRK_FORCED_DISABLE BIT(3) #define GB_INTERFACE_QUIRK_LEGACY_MODE_SWITCH BIT(4) #define GB_INTERFACE_QUIRK_NO_BUNDLE_ACTIVATE BIT(5) +#define GB_INTERFACE_QUIRK_NO_PM BIT(6) struct gb_interface { struct device dev; -- cgit v0.10.2 From 911415ae6ee29cb76e018e8df8715c743a3a3d63 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 25 Jul 2016 14:38:07 -0700 Subject: greybus: firmware: Add new status types for backend updated request The specification got updated with two more status values, add their support in greybus. As retry isn't really an error, skip printing error messages for it as well. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/fw-management.c b/drivers/staging/greybus/fw-management.c index 2efe65c..642a393 100644 --- a/drivers/staging/greybus/fw-management.c +++ b/drivers/staging/greybus/fw-management.c @@ -350,7 +350,8 @@ static int fw_mgmt_backend_fw_updated_operation(struct gb_operation *op) fw_mgmt->backend_fw_request_id = 0; fw_mgmt->backend_fw_status = request->status; - if (fw_mgmt->backend_fw_status != GB_FW_BACKEND_FW_STATUS_SUCCESS) + if ((fw_mgmt->backend_fw_status != GB_FW_BACKEND_FW_STATUS_SUCCESS) && + (fw_mgmt->backend_fw_status != GB_FW_BACKEND_FW_STATUS_RETRY)) dev_err(fw_mgmt->parent, "failed to load backend firmware: %02x\n", fw_mgmt->backend_fw_status); diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 2de5aef..e51c2b1 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -367,6 +367,8 @@ struct gb_fw_download_release_firmware_request { #define GB_FW_BACKEND_FW_STATUS_FAIL_FETCH 0x03 #define GB_FW_BACKEND_FW_STATUS_FAIL_WRITE 0x04 #define GB_FW_BACKEND_FW_STATUS_INT 0x05 +#define GB_FW_BACKEND_FW_STATUS_RETRY 0x06 +#define GB_FW_BACKEND_FW_STATUS_NOT_SUPPORTED 0x07 /* firmware management interface firmware version request has no payload */ struct gb_fw_mgmt_interface_fw_version_response { -- cgit v0.10.2 From 5e10f0047a1b79e6c8ac1ee0e9a0165e7d0bc7d6 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 25 Jul 2016 14:38:08 -0700 Subject: greybus: firmware: Add 'status' byte to backend fw version response The backend processor may not be ready to return the version of firmware it is running by the time AP requests for it. The greybus specification is updated to return 1-byte 'status' to return the error type, RETRY is one of them. This patch implements that in greybus now. Note that the version structure was common across interface and backend version requests earlier, but that is changing as well. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/fw-management.c b/drivers/staging/greybus/fw-management.c index 642a393..7cbe71d 100644 --- a/drivers/staging/greybus/fw-management.c +++ b/drivers/staging/greybus/fw-management.c @@ -103,7 +103,7 @@ unlock: } static int fw_mgmt_interface_fw_version_operation(struct fw_mgmt *fw_mgmt, - struct fw_mgmt_ioc_get_fw *fw_info) + struct fw_mgmt_ioc_get_intf_version *fw_info) { struct gb_connection *connection = fw_mgmt->connection; struct gb_fw_mgmt_interface_fw_version_response response; @@ -241,7 +241,7 @@ static int fw_mgmt_interface_fw_loaded_operation(struct gb_operation *op) } static int fw_mgmt_backend_fw_version_operation(struct fw_mgmt *fw_mgmt, - struct fw_mgmt_ioc_get_fw *fw_info) + struct fw_mgmt_ioc_get_backend_version *fw_info) { struct gb_connection *connection = fw_mgmt->connection; struct gb_fw_mgmt_backend_fw_version_request request; @@ -269,8 +269,29 @@ static int fw_mgmt_backend_fw_version_operation(struct fw_mgmt *fw_mgmt, return ret; } - fw_info->major = le16_to_cpu(response.major); - fw_info->minor = le16_to_cpu(response.minor); + fw_info->status = response.status; + + /* Reset version as that should be non-zero only for success case */ + fw_info->major = 0; + fw_info->minor = 0; + + switch (fw_info->status) { + case GB_FW_BACKEND_VERSION_STATUS_SUCCESS: + fw_info->major = le16_to_cpu(response.major); + fw_info->minor = le16_to_cpu(response.minor); + break; + case GB_FW_BACKEND_VERSION_STATUS_NOT_AVAILABLE: + case GB_FW_BACKEND_VERSION_STATUS_RETRY: + break; + case GB_FW_BACKEND_VERSION_STATUS_NOT_SUPPORTED: + dev_err(fw_mgmt->parent, + "Firmware with tag %s is not supported by Interface\n", + fw_info->firmware_tag); + break; + default: + dev_err(fw_mgmt->parent, "Invalid status received: %u\n", + fw_info->status); + } return 0; } @@ -387,7 +408,8 @@ static int fw_mgmt_release(struct inode *inode, struct file *file) static int fw_mgmt_ioctl(struct fw_mgmt *fw_mgmt, unsigned int cmd, void __user *buf) { - struct fw_mgmt_ioc_get_fw fw_info; + struct fw_mgmt_ioc_get_intf_version intf_fw_info; + struct fw_mgmt_ioc_get_backend_version backend_fw_info; struct fw_mgmt_ioc_intf_load_and_validate intf_load; struct fw_mgmt_ioc_backend_fw_update backend_update; unsigned int timeout; @@ -399,23 +421,27 @@ static int fw_mgmt_ioctl(struct fw_mgmt *fw_mgmt, unsigned int cmd, switch (cmd) { case FW_MGMT_IOC_GET_INTF_FW: - ret = fw_mgmt_interface_fw_version_operation(fw_mgmt, &fw_info); + ret = fw_mgmt_interface_fw_version_operation(fw_mgmt, + &intf_fw_info); if (ret) return ret; - if (copy_to_user(buf, &fw_info, sizeof(fw_info))) + if (copy_to_user(buf, &intf_fw_info, sizeof(intf_fw_info))) return -EFAULT; return 0; case FW_MGMT_IOC_GET_BACKEND_FW: - if (copy_from_user(&fw_info, buf, sizeof(fw_info))) + if (copy_from_user(&backend_fw_info, buf, + sizeof(backend_fw_info))) return -EFAULT; - ret = fw_mgmt_backend_fw_version_operation(fw_mgmt, &fw_info); + ret = fw_mgmt_backend_fw_version_operation(fw_mgmt, + &backend_fw_info); if (ret) return ret; - if (copy_to_user(buf, &fw_info, sizeof(fw_info))) + if (copy_to_user(buf, &backend_fw_info, + sizeof(backend_fw_info))) return -EFAULT; return 0; diff --git a/drivers/staging/greybus/greybus_firmware.h b/drivers/staging/greybus/greybus_firmware.h index 1b68821..8279651 100644 --- a/drivers/staging/greybus/greybus_firmware.h +++ b/drivers/staging/greybus/greybus_firmware.h @@ -72,14 +72,29 @@ #define GB_FW_U_BACKEND_FW_STATUS_FAIL_FETCH 0x03 #define GB_FW_U_BACKEND_FW_STATUS_FAIL_WRITE 0x04 #define GB_FW_U_BACKEND_FW_STATUS_INT 0x05 +#define GB_FW_U_BACKEND_FW_STATUS_RETRY 0x06 +#define GB_FW_U_BACKEND_FW_STATUS_NOT_SUPPORTED 0x07 + +#define GB_FW_U_BACKEND_VERSION_STATUS_SUCCESS 0x01 +#define GB_FW_U_BACKEND_VERSION_STATUS_NOT_AVAILABLE 0x02 +#define GB_FW_U_BACKEND_VERSION_STATUS_NOT_SUPPORTED 0x03 +#define GB_FW_U_BACKEND_VERSION_STATUS_RETRY 0x04 +#define GB_FW_U_BACKEND_VERSION_STATUS_FAIL_INT 0x05 /* IOCTL support */ -struct fw_mgmt_ioc_get_fw { +struct fw_mgmt_ioc_get_intf_version { __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_LEN]; __u16 major; __u16 minor; } __attribute__ ((__packed__)); +struct fw_mgmt_ioc_get_backend_version { + __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_LEN]; + __u16 major; + __u16 minor; + __u8 status; +} __attribute__ ((__packed__)); + struct fw_mgmt_ioc_intf_load_and_validate { __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_LEN]; __u8 load_method; @@ -94,8 +109,8 @@ struct fw_mgmt_ioc_backend_fw_update { } __attribute__ ((__packed__)); #define FW_MGMT_IOCTL_BASE 'F' -#define FW_MGMT_IOC_GET_INTF_FW _IOR(FW_MGMT_IOCTL_BASE, 0, struct fw_mgmt_ioc_get_fw) -#define FW_MGMT_IOC_GET_BACKEND_FW _IOWR(FW_MGMT_IOCTL_BASE, 1, struct fw_mgmt_ioc_get_fw) +#define FW_MGMT_IOC_GET_INTF_FW _IOR(FW_MGMT_IOCTL_BASE, 0, struct fw_mgmt_ioc_get_intf_version) +#define FW_MGMT_IOC_GET_BACKEND_FW _IOWR(FW_MGMT_IOCTL_BASE, 1, struct fw_mgmt_ioc_get_backend_version) #define FW_MGMT_IOC_INTF_LOAD_AND_VALIDATE _IOWR(FW_MGMT_IOCTL_BASE, 2, struct fw_mgmt_ioc_intf_load_and_validate) #define FW_MGMT_IOC_INTF_BACKEND_FW_UPDATE _IOWR(FW_MGMT_IOCTL_BASE, 3, struct fw_mgmt_ioc_backend_fw_update) #define FW_MGMT_IOC_SET_TIMEOUT_MS _IOW(FW_MGMT_IOCTL_BASE, 4, unsigned int) diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index e51c2b1..edbc5df 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -370,6 +370,12 @@ struct gb_fw_download_release_firmware_request { #define GB_FW_BACKEND_FW_STATUS_RETRY 0x06 #define GB_FW_BACKEND_FW_STATUS_NOT_SUPPORTED 0x07 +#define GB_FW_BACKEND_VERSION_STATUS_SUCCESS 0x01 +#define GB_FW_BACKEND_VERSION_STATUS_NOT_AVAILABLE 0x02 +#define GB_FW_BACKEND_VERSION_STATUS_NOT_SUPPORTED 0x03 +#define GB_FW_BACKEND_VERSION_STATUS_RETRY 0x04 +#define GB_FW_BACKEND_VERSION_STATUS_FAIL_INT 0x05 + /* firmware management interface firmware version request has no payload */ struct gb_fw_mgmt_interface_fw_version_response { __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_LEN]; @@ -402,6 +408,7 @@ struct gb_fw_mgmt_backend_fw_version_request { struct gb_fw_mgmt_backend_fw_version_response { __le16 major; __le16 minor; + __u8 status; } __packed; /* firmware management backend firmware update request */ -- cgit v0.10.2 From 6136cce89ca5d344d5183d36e887f0ff46896f1c Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Mon, 25 Jul 2016 14:38:09 -0700 Subject: greybus: firmware: Update Documentation and sample application Update documentation and sample application to capture the 'status' byte in backend version operation and new error types in backend firmware update operation. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/firmware/firmware-management b/drivers/staging/greybus/Documentation/firmware/firmware-management index 6b7b6d8..77d272c 100644 --- a/drivers/staging/greybus/Documentation/firmware/firmware-management +++ b/drivers/staging/greybus/Documentation/firmware/firmware-management @@ -93,12 +93,28 @@ Following are the IOCTLs and their data structures available to the user: #define GB_FW_BACKEND_FW_STATUS_FAIL_FETCH 0x03 #define GB_FW_BACKEND_FW_STATUS_FAIL_WRITE 0x04 #define GB_FW_BACKEND_FW_STATUS_INT 0x05 +#define GB_FW_BACKEND_FW_STATUS_RETRY 0x06 +#define GB_FW_BACKEND_FW_STATUS_NOT_SUPPORTED 0x07 -struct fw_mgmt_ioc_get_fw { - __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_LEN]; - __u16 major; - __u16 minor; -} __packed; +#define GB_FW_BACKEND_VERSION_STATUS_SUCCESS 0x01 +#define GB_FW_BACKEND_VERSION_STATUS_NOT_AVAILABLE 0x02 +#define GB_FW_BACKEND_VERSION_STATUS_NOT_SUPPORTED 0x03 +#define GB_FW_BACKEND_VERSION_STATUS_RETRY 0x04 +#define GB_FW_BACKEND_VERSION_STATUS_FAIL_INT 0x05 + + +struct fw_mgmt_ioc_get_intf_version { + __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_LEN]; + __u16 major; + __u16 minor; +} __attribute__ ((__packed__)); + +struct fw_mgmt_ioc_get_backend_version { + __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_LEN]; + __u16 major; + __u16 minor; + __u8 status; +} __attribute__ ((__packed__)); struct fw_mgmt_ioc_intf_load_and_validate { __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_LEN]; @@ -114,8 +130,8 @@ struct fw_mgmt_ioc_backend_fw_update { } __packed; #define FW_MGMT_IOCTL_BASE 'S' -#define FW_MGMT_IOC_GET_INTF_FW _IOR(FW_MGMT_IOCTL_BASE, 0, struct fw_mgmt_ioc_get_fw) -#define FW_MGMT_IOC_GET_BACKEND_FW _IOWR(FW_MGMT_IOCTL_BASE, 1, struct fw_mgmt_ioc_get_fw) +#define FW_MGMT_IOC_GET_INTF_FW _IOR(FW_MGMT_IOCTL_BASE, 0, struct fw_mgmt_ioc_get_intf_version) +#define FW_MGMT_IOC_GET_BACKEND_FW _IOWR(FW_MGMT_IOCTL_BASE, 1, struct fw_mgmt_ioc_get_backend_version) #define FW_MGMT_IOC_INTF_LOAD_AND_VALIDATE _IOWR(FW_MGMT_IOCTL_BASE, 2, struct fw_mgmt_ioc_intf_load_and_validate) #define FW_MGMT_IOC_INTF_BACKEND_FW_UPDATE _IOWR(FW_MGMT_IOCTL_BASE, 3, struct fw_mgmt_ioc_backend_fw_update) #define FW_MGMT_IOC_SET_TIMEOUT_MS _IOW(FW_MGMT_IOCTL_BASE, 4, unsigned int) diff --git a/drivers/staging/greybus/Documentation/firmware/firmware.c b/drivers/staging/greybus/Documentation/firmware/firmware.c index c557bf1..5170886 100644 --- a/drivers/staging/greybus/Documentation/firmware/firmware.c +++ b/drivers/staging/greybus/Documentation/firmware/firmware.c @@ -71,7 +71,8 @@ static const char *fwdev = FW_DEV_DEFAULT; static int fw_update_type = FW_UPDATE_TYPE_DEFAULT; static int fw_timeout = FW_TIMEOUT_DEFAULT; -static struct fw_mgmt_ioc_get_fw fw_info; +static struct fw_mgmt_ioc_get_intf_version intf_fw_info; +static struct fw_mgmt_ioc_get_backend_version backend_fw_info; static struct fw_mgmt_ioc_intf_load_and_validate intf_load; static struct fw_mgmt_ioc_backend_fw_update backend_update; @@ -87,7 +88,7 @@ static int update_intf_firmware(int fd) /* Get Interface Firmware Version */ printf("Get Interface Firmware Version\n"); - ret = ioctl(fd, FW_MGMT_IOC_GET_INTF_FW, &fw_info); + ret = ioctl(fd, FW_MGMT_IOC_GET_INTF_FW, &intf_fw_info); if (ret < 0) { printf("Failed to get interface firmware version: %s (%d)\n", fwdev, ret); @@ -95,7 +96,8 @@ static int update_intf_firmware(int fd) } printf("Interface Firmware tag (%s), major (%d), minor (%d)\n", - fw_info.firmware_tag, fw_info.major, fw_info.minor); + intf_fw_info.firmware_tag, intf_fw_info.major, + intf_fw_info.minor); /* Try Interface Firmware load over Unipro */ printf("Loading Interface Firmware\n"); @@ -143,34 +145,51 @@ static int update_backend_firmware(int fd) /* Get Backend Firmware Version */ printf("Getting Backend Firmware Version\n"); - fw_info.major = 0; - fw_info.minor = 0; - strncpy((char *)&fw_info.firmware_tag, firmware_tag, + strncpy((char *)&backend_fw_info.firmware_tag, firmware_tag, GB_FIRMWARE_U_TAG_MAX_LEN); - ret = ioctl(fd, FW_MGMT_IOC_GET_BACKEND_FW, &fw_info); +retry_fw_version: + ret = ioctl(fd, FW_MGMT_IOC_GET_BACKEND_FW, &backend_fw_info); if (ret < 0) { printf("Failed to get backend firmware version: %s (%d)\n", fwdev, ret); return -1; } - printf("Backend Firmware tag (%s), major (%d), minor (%d)\n", - fw_info.firmware_tag, fw_info.major, fw_info.minor); + printf("Backend Firmware tag (%s), major (%d), minor (%d), status (%d)\n", + backend_fw_info.firmware_tag, backend_fw_info.major, + backend_fw_info.minor, backend_fw_info.status); + + if (backend_fw_info.status == GB_FW_U_BACKEND_VERSION_STATUS_RETRY) + goto retry_fw_version; + + if ((backend_fw_info.status != GB_FW_U_BACKEND_VERSION_STATUS_SUCCESS) + && (backend_fw_info.status != GB_FW_U_BACKEND_VERSION_STATUS_NOT_AVAILABLE)) { + printf("Failed to get backend firmware version: %s (%d)\n", + fwdev, backend_fw_info.status); + return -1; + } /* Try Backend Firmware Update over Unipro */ printf("Updating Backend Firmware\n"); - backend_update.status = 0; strncpy((char *)&backend_update.firmware_tag, firmware_tag, GB_FIRMWARE_U_TAG_MAX_LEN); +retry_fw_update: + backend_update.status = 0; + ret = ioctl(fd, FW_MGMT_IOC_INTF_BACKEND_FW_UPDATE, &backend_update); if (ret < 0) { printf("Failed to load backend firmware: %s (%d)\n", fwdev, ret); return -1; } + if (backend_update.status == GB_FW_U_BACKEND_FW_STATUS_RETRY) { + printf("Retrying firmware update: %d\n", backend_update.status); + goto retry_fw_update; + } + if (backend_update.status != GB_FW_U_BACKEND_FW_STATUS_SUCCESS) { printf("Load status says loading failed: %d\n", backend_update.status); -- cgit v0.10.2 From 7c4a0edb38ba734bd89efbda4262698a58839c26 Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Tue, 26 Jul 2016 16:27:28 -0700 Subject: greybus: svc_watchdog: Add sysfs file to change the behavior of bite Currently, AP performs unipro_reset if SVC fails to response to its ping. While this error recovery is best suited for the end-user experience, errors in the UniPro network could potentially go unnoticed by the QA and fishfooders in the development phase of the project. This patch adds an option to trigger a kernel panic so logs can be collected for analysis. Testing Done: - Reproduce issue and observe kernel panic when watchdob_control is changed to 'panic' Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index e202eac..c49c81b 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -257,3 +257,19 @@ Contact: Greg Kroah-Hartman <greg@kroah.com> Description: If the SVC watchdog is enabled or not. Writing 0 to this file will disable the watchdog, writing 1 will enable it. + +What: /sys/bus/greybus/devices/N-svc/watchdog_action +Date: July 2016 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman <greg@kroah.com> +Description: + This attribute indicates the action to be performed upon SVC + watchdog bite. + + The action can be one of the "reset" or "panic". Writing either + one of the "reset" or "panic" will change the behavior of SVC + watchdog bite. Default value is "reset". + + "reset" means the UniPro subsystem is to be reset. + + "panic" means SVC watchdog bite will cause kernel to panic. diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index da9bb1f..1170515 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -100,6 +100,36 @@ static ssize_t watchdog_store(struct device *dev, } static DEVICE_ATTR_RW(watchdog); +static ssize_t watchdog_action_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_svc *svc = to_gb_svc(dev); + + if (svc->action == GB_SVC_WATCHDOG_BITE_PANIC_KERNEL) + return sprintf(buf, "panic\n"); + else if (svc->action == GB_SVC_WATCHDOG_BITE_RESET_UNIPRO) + return sprintf(buf, "reset\n"); + + return -EINVAL; +} + +static ssize_t watchdog_action_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct gb_svc *svc = to_gb_svc(dev); + + if (sysfs_streq(buf, "panic")) + svc->action = GB_SVC_WATCHDOG_BITE_PANIC_KERNEL; + else if (sysfs_streq(buf, "reset")) + svc->action = GB_SVC_WATCHDOG_BITE_RESET_UNIPRO; + else + return -EINVAL; + + return len; +} +static DEVICE_ATTR_RW(watchdog_action); + static int gb_svc_pwrmon_rail_count_get(struct gb_svc *svc, u8 *value) { struct gb_svc_pwrmon_rail_count_get_response response; @@ -222,6 +252,7 @@ static struct attribute *svc_attrs[] = { &dev_attr_ap_intf_id.attr, &dev_attr_intf_eject.attr, &dev_attr_watchdog.attr, + &dev_attr_watchdog_action.attr, NULL, }; ATTRIBUTE_GROUPS(svc); diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index f632790..d1d7ef9 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -20,6 +20,11 @@ enum gb_svc_state { GB_SVC_STATE_SVC_HELLO, }; +enum gb_svc_watchdog_bite { + GB_SVC_WATCHDOG_BITE_RESET_UNIPRO = 0, + GB_SVC_WATCHDOG_BITE_PANIC_KERNEL, +}; + struct gb_svc_watchdog; struct svc_debugfs_pwrmon_rail { @@ -43,6 +48,7 @@ struct gb_svc { u8 protocol_minor; struct gb_svc_watchdog *watchdog; + enum gb_svc_watchdog_bite action; struct dentry *debugfs_dentry; struct svc_debugfs_pwrmon_rail *pwrmon_rails; diff --git a/drivers/staging/greybus/svc_watchdog.c b/drivers/staging/greybus/svc_watchdog.c index 6cd3bac..1295cc1 100644 --- a/drivers/staging/greybus/svc_watchdog.c +++ b/drivers/staging/greybus/svc_watchdog.c @@ -83,16 +83,21 @@ static void do_work(struct work_struct *work) dev_err(&svc->dev, "SVC ping has returned %d, something is wrong!!!\n", retval); - dev_err(&svc->dev, "Resetting the greybus network, watch out!!!\n"); - INIT_DELAYED_WORK(&reset_work, greybus_reset); - queue_delayed_work(system_wq, &reset_work, HZ/2); + if (svc->action == GB_SVC_WATCHDOG_BITE_PANIC_KERNEL) { + panic("SVC is not responding\n"); + } else if (svc->action == GB_SVC_WATCHDOG_BITE_RESET_UNIPRO) { + dev_err(&svc->dev, "Resetting the greybus network, watch out!!!\n"); - /* - * Disable ourselves, we don't want to trip again unless - * userspace wants us to. - */ - watchdog->enabled = false; + INIT_DELAYED_WORK(&reset_work, greybus_reset); + queue_delayed_work(system_wq, &reset_work, HZ / 2); + + /* + * Disable ourselves, we don't want to trip again unless + * userspace wants us to. + */ + watchdog->enabled = false; + } } /* resubmit our work to happen again, if we are still "alive" */ -- cgit v0.10.2 From 9d3717f71c22c4f39723f18ed094c552f4b73146 Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Mon, 25 Jul 2016 16:29:20 -0700 Subject: greybus: audio: add runtime pm to enumerated control and DAPM widget There's an issue that the userspace is not able to control both the enumerated control and DAPM widget when audio bundle is in the SUSPEND state. This patch fixes the issue by adding pm_runtime_get/put() calls for the both controls. Testing Done: - Use tinymix to get and put both enumerated control and DAPM widget as the followings, and observe audio bundle is able to wake up from suspend. $ tinymix "GB 3 PB source" 1 $ tinymix "GB 3 PB source" GB 3 PB source: AIF1 >AIF2 $ tinymix "GB 3 AIF1_RX MUX" 2 $ tinymix "GB 3 AIF1_RX MUX" GB 3 AIF1_RX MUX: Stereo Left >Right Reported-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index 17ba0a0..3c7c786 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -555,6 +555,7 @@ static int gbcodec_enum_ctl_get(struct snd_kcontrol *kcontrol, struct gb_audio_ctl_elem_value gbvalue; struct gbaudio_module_info *module; struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + struct gb_bundle *bundle; module = find_gb_module(gb, kcontrol->id.name); if (!module) @@ -564,8 +565,17 @@ static int gbcodec_enum_ctl_get(struct snd_kcontrol *kcontrol, if (ctl_id < 0) return -EINVAL; + bundle = to_gb_bundle(module->dev); + + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + return ret; + ret = gb_audio_gb_get_control(module->mgmt_connection, ctl_id, GB_AUDIO_INVALID_INDEX, &gbvalue); + + gb_pm_runtime_put_autosuspend(bundle); + if (ret) { dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, __func__, kcontrol->id.name); @@ -589,6 +599,7 @@ static int gbcodec_enum_ctl_put(struct snd_kcontrol *kcontrol, struct gb_audio_ctl_elem_value gbvalue; struct gbaudio_module_info *module; struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); + struct gb_bundle *bundle; module = find_gb_module(gb, kcontrol->id.name); if (!module) @@ -609,8 +620,17 @@ static int gbcodec_enum_ctl_put(struct snd_kcontrol *kcontrol, ucontrol->value.enumerated.item[1]; } + bundle = to_gb_bundle(module->dev); + + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + return ret; + ret = gb_audio_gb_set_control(module->mgmt_connection, ctl_id, GB_AUDIO_INVALID_INDEX, &gbvalue); + + gb_pm_runtime_put_autosuspend(bundle); + if (ret) { dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, __func__, kcontrol->id.name); @@ -698,6 +718,7 @@ static int gbcodec_enum_dapm_ctl_get(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = widget->codec; struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + struct gb_bundle *bundle; module = find_gb_module(gb, kcontrol->id.name); if (!module) @@ -707,8 +728,17 @@ static int gbcodec_enum_dapm_ctl_get(struct snd_kcontrol *kcontrol, if (ctl_id < 0) return -EINVAL; + bundle = to_gb_bundle(module->dev); + + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + return ret; + ret = gb_audio_gb_get_control(module->mgmt_connection, ctl_id, GB_AUDIO_INVALID_INDEX, &gbvalue); + + gb_pm_runtime_put_autosuspend(bundle); + if (ret) { dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, __func__, kcontrol->id.name); @@ -736,6 +766,7 @@ static int gbcodec_enum_dapm_ctl_put(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = widget->codec; struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + struct gb_bundle *bundle; if (ucontrol->value.enumerated.item[0] > e->max - 1) return -EINVAL; @@ -749,8 +780,17 @@ static int gbcodec_enum_dapm_ctl_put(struct snd_kcontrol *kcontrol, return -EINVAL; change = 0; + bundle = to_gb_bundle(module->dev); + + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + return ret; + ret = gb_audio_gb_get_control(module->mgmt_connection, ctl_id, GB_AUDIO_INVALID_INDEX, &gbvalue); + + gb_pm_runtime_put_autosuspend(bundle); + if (ret) { dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, __func__, kcontrol->id.name); @@ -782,8 +822,15 @@ static int gbcodec_enum_dapm_ctl_put(struct snd_kcontrol *kcontrol, } if (change) { + ret = gb_pm_runtime_get_sync(bundle); + if (ret) + return ret; + ret = gb_audio_gb_set_control(module->mgmt_connection, ctl_id, GB_AUDIO_INVALID_INDEX, &gbvalue); + + gb_pm_runtime_put_autosuspend(bundle); + if (ret) { dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, -- cgit v0.10.2 From 563c742adab959362aca106248b4ab24c4186217 Mon Sep 17 00:00:00 2001 From: Gjorgji Rosikopulos <grosikopulos@mm-sol.com> Date: Wed, 27 Jul 2016 11:47:01 -0700 Subject: greybus: camera: Rename debug and metadata mbus formats Change ARA prefix to GB_CAM for greyus camera specific formats. Change-Id: I1a0552516e8ea727c48085c59fc49f2409a89486 Signed-off-by: Gjorgji Rosikopulos <grosikopulos@mm-sol.com> Signed-off-by: Blagovest Borisov Kolenichev <kolenichev_blagovest@projectara.com> Acked-by: Laurent Pinchart <laurent.pinchart@linaro.org> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index e0719e2..0e7f643 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -113,12 +113,12 @@ static const struct gb_camera_fmt_info gb_fmt_info[] = { .bpp = 0, }, { - .mbus_code = V4L2_MBUS_FMT_ARA_METADATA_1X8, + .mbus_code = V4L2_MBUS_FMT_GB_CAM_METADATA_1X8, .gb_format = 0x41, .bpp = 0, }, { - .mbus_code = V4L2_MBUS_FMT_ARA_DEBUG_DATA_1X8, + .mbus_code = V4L2_MBUS_FMT_GB_CAM_DEBUG_DATA_1X8, .gb_format = 0x42, .bpp = 0, }, -- cgit v0.10.2 From 20de72f5dee480e72d82d702e709a07217c0900f Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Date: Thu, 28 Jul 2016 13:56:44 +0530 Subject: greybus: arche-apb-ctrl: Rename ara,init-disable => arche,init-disable Inline with other properties used for arche-platform driver, rename ara,init-disable => arche,init-disable. Testing Done: Boot tested on EVT2 platform Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index cae56fc..049d496 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -391,7 +391,7 @@ static int arche_apb_ctrl_probe(struct platform_device *pdev) /* Initially set APB to OFF state */ apb->state = ARCHE_PLATFORM_STATE_OFF; /* Check whether device needs to be enabled on boot */ - if (of_property_read_bool(pdev->dev.of_node, "ara,init-disable")) + if (of_property_read_bool(pdev->dev.of_node, "arche,init-disable")) apb->init_disabled = true; platform_set_drvdata(pdev, apb); -- cgit v0.10.2 From 6c298035a14d30e94861833df5c490feda2c73db Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Thu, 28 Jul 2016 11:40:52 +0200 Subject: greybus: Documentation/sysfs: replace Ara references Refer to the MDK as GMP MDK. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index c49c81b..2e99896 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -223,7 +223,7 @@ Contact: Greg Kroah-Hartman <greg@kroah.com> Description: The AP interface ID, a 1-byte non-zero integer which defines the position of the AP module on the frame. - The interface positions are defined in the ARA + The interface positions are defined in the GMP Module Developer Kit. What: /sys/bus/greybus/devices/N-svc/endo_id @@ -233,7 +233,7 @@ Contact: Greg Kroah-Hartman <greg@kroah.com> Description: The Endo ID, which is a 2-byte hexadecimal value defined by the Endo layout scheme, documented in - the ARA Module Developer Kit. + the GMP Module Developer Kit. What: /sys/bus/greybus/devices/N-svc/intf_eject Date: October 2015 -- cgit v0.10.2 From 23931ffb9ac892a51cdef4eefdfc255e3f810a8b Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Thu, 28 Jul 2016 11:40:53 +0200 Subject: greybus: replace Ara references Replace all occurrences of the term "Ara" with "GMP" in core. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/bootrom.c b/drivers/staging/greybus/bootrom.c index e7cfa80..5f90721 100644 --- a/drivers/staging/greybus/bootrom.c +++ b/drivers/staging/greybus/bootrom.c @@ -114,7 +114,7 @@ static void bootrom_es2_fixup_vid_pid(struct gb_bootrom *bootrom) struct gb_interface *intf = connection->bundle->intf; int ret; - if (!(intf->quirks & GB_INTERFACE_QUIRK_NO_ARA_IDS)) + if (!(intf->quirks & GB_INTERFACE_QUIRK_NO_GMP_IDS)) return; ret = gb_operation_sync(connection, GB_BOOTROM_TYPE_GET_VID_PID, diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index faa6239..19f5c71 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -31,11 +31,11 @@ #define DME_DDBL1_MANUFACTURERID 0x5003 #define DME_DDBL1_PRODUCTID 0x5004 -#define DME_TOSHIBA_ARA_VID 0x6000 -#define DME_TOSHIBA_ARA_PID 0x6001 -#define DME_TOSHIBA_ARA_SN0 0x6002 -#define DME_TOSHIBA_ARA_SN1 0x6003 -#define DME_TOSHIBA_ARA_INIT_STATUS 0x6101 +#define DME_TOSHIBA_GMP_VID 0x6000 +#define DME_TOSHIBA_GMP_PID 0x6001 +#define DME_TOSHIBA_GMP_SN0 0x6002 +#define DME_TOSHIBA_GMP_SN1 0x6003 +#define DME_TOSHIBA_GMP_INIT_STATUS 0x6101 /* DDBL1 Manufacturer and Product ids */ #define TOSHIBA_DMID 0x0126 @@ -60,7 +60,7 @@ static int gb_interface_read_ara_dme(struct gb_interface *intf) /* * Unless this is a Toshiba bridge, bail out until we have defined - * standard Ara attributes. + * standard GMP attributes. */ if (intf->ddbl1_manufacturer_id != TOSHIBA_DMID) { dev_err(&intf->dev, "unknown manufacturer %08x\n", @@ -68,21 +68,21 @@ static int gb_interface_read_ara_dme(struct gb_interface *intf) return -ENODEV; } - ret = gb_interface_dme_attr_get(intf, DME_TOSHIBA_ARA_VID, + ret = gb_interface_dme_attr_get(intf, DME_TOSHIBA_GMP_VID, &intf->vendor_id); if (ret) return ret; - ret = gb_interface_dme_attr_get(intf, DME_TOSHIBA_ARA_PID, + ret = gb_interface_dme_attr_get(intf, DME_TOSHIBA_GMP_PID, &intf->product_id); if (ret) return ret; - ret = gb_interface_dme_attr_get(intf, DME_TOSHIBA_ARA_SN0, &sn0); + ret = gb_interface_dme_attr_get(intf, DME_TOSHIBA_GMP_SN0, &sn0); if (ret) return ret; - ret = gb_interface_dme_attr_get(intf, DME_TOSHIBA_ARA_SN1, &sn1); + ret = gb_interface_dme_attr_get(intf, DME_TOSHIBA_GMP_SN1, &sn1); if (ret) return ret; @@ -111,7 +111,7 @@ static int gb_interface_read_dme(struct gb_interface *intf) if (intf->ddbl1_manufacturer_id == TOSHIBA_DMID && intf->ddbl1_product_id == TOSHIBA_ES2_BRIDGE_DPID) { - intf->quirks |= GB_INTERFACE_QUIRK_NO_ARA_IDS; + intf->quirks |= GB_INTERFACE_QUIRK_NO_GMP_IDS; intf->quirks |= GB_INTERFACE_QUIRK_NO_INIT_STATUS; } @@ -377,7 +377,7 @@ static int gb_interface_read_and_clear_init_status(struct gb_interface *intf) if (intf->quirks & GB_INTERFACE_QUIRK_NO_INIT_STATUS) attr = DME_T_TST_SRC_INCREMENT; else - attr = DME_TOSHIBA_ARA_INIT_STATUS; + attr = DME_TOSHIBA_GMP_INIT_STATUS; ret = gb_svc_dme_peer_get(hd->svc, intf->interface_id, attr, DME_SELECTOR_INDEX_NULL, &value); @@ -793,7 +793,7 @@ struct device_type greybus_interface_type = { }; /* - * A Greybus module represents a user-replaceable component on an Ara + * A Greybus module represents a user-replaceable component on a GMP * phone. An interface is the physical connection on that module. A * module may have more than one interface. * @@ -1282,7 +1282,7 @@ int gb_interface_add(struct gb_interface *intf) switch (intf->type) { case GB_INTERFACE_TYPE_GREYBUS: - dev_info(&intf->dev, "Ara VID=0x%08x, PID=0x%08x\n", + dev_info(&intf->dev, "GMP VID=0x%08x, PID=0x%08x\n", intf->vendor_id, intf->product_id); /* fall-through */ case GB_INTERFACE_TYPE_UNIPRO: diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 174bc74..03299d2 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -20,7 +20,7 @@ enum gb_interface_type { #define GB_INTERFACE_QUIRK_NO_CPORT_FEATURES BIT(0) #define GB_INTERFACE_QUIRK_NO_INIT_STATUS BIT(1) -#define GB_INTERFACE_QUIRK_NO_ARA_IDS BIT(2) +#define GB_INTERFACE_QUIRK_NO_GMP_IDS BIT(2) #define GB_INTERFACE_QUIRK_FORCED_DISABLE BIT(3) #define GB_INTERFACE_QUIRK_LEGACY_MODE_SWITCH BIT(4) #define GB_INTERFACE_QUIRK_NO_BUNDLE_ACTIVATE BIT(5) -- cgit v0.10.2 From fcba5d04c87c5c0174f159d26b295a46bfb6da58 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 27 Jul 2016 16:37:20 +0200 Subject: greybus: es2: fix arpc response-allocation error handling The wrong pointer was checked for allocation failures when allocating the ARPC response buffer, something which would lead to allocation failures going undetected. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index afc2d6c..130549f9 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -1100,7 +1100,7 @@ static struct arpc *arpc_alloc(void *payload, u16 size, u8 type) goto err_free_rpc; rpc->resp = kzalloc(sizeof(*rpc->resp), GFP_KERNEL); - if (!rpc->req) + if (!rpc->resp) goto err_free_req; rpc->req->type = type; -- cgit v0.10.2 From 178457e171bf1ae7a90a6b0aa6a404fec129e8c4 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 27 Jul 2016 16:37:21 +0200 Subject: greybus: es2: fix arpc error message Add missing le16_to_cpu() to an ARPC error message in the receive path, and also use %u to print the unsigned id. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 130549f9..a22cb67 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -1256,8 +1256,8 @@ static void arpc_in_callback(struct urb *urb) spin_lock_irqsave(&es2->arpc_lock, flags); rpc = arpc_find(es2, resp->id); if (!rpc) { - dev_err(dev, "invalid arpc response id received: %d\n", - resp->id); + dev_err(dev, "invalid arpc response id received: %u\n", + le16_to_cpu(resp->id)); spin_unlock_irqrestore(&es2->arpc_lock, flags); goto exit; } -- cgit v0.10.2 From c0219cbf72418d5355e319a0d787dc2671df9d4f Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 27 Jul 2016 16:37:22 +0200 Subject: greybus: es2: fix arpc active-list corruption Fix ARPC active-list corruption due to incorrect list-interface usage. The corruption manifested itself as ARPC timeouts due to expected responses not being recognised whenever more than one ARPC was active. This could be seen for example when two interfaces were being runtime suspended in parallel: [ 165.739896] usb 1-1.1: invalid arpc response id received: 13 [ 165.794743] greybus 1-5.5: gb_interface_refclk_set - 0 [ 166.241202] usb 1-1.1: failed to execute ARPC: -110 Fortunately the impact of this bug has so far been limited to such timeouts and error messages due to ARPC currently only being used for CPort reset in the connection tear-down path. Reported-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index a22cb67..2020187 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -1142,7 +1142,7 @@ static void arpc_add(struct es2_ap_dev *es2, struct arpc *rpc) { rpc->active = true; rpc->req->id = cpu_to_le16(es2->arpc_id_cycle++); - list_add_tail(&es2->arpcs, &rpc->list); + list_add_tail(&rpc->list, &es2->arpcs); } static void arpc_del(struct es2_ap_dev *es2, struct arpc *rpc) -- cgit v0.10.2 From ea2ff95ab4e178559e63b1ab5a174dd4dd6b4019 Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Tue, 2 Aug 2016 15:34:46 -0700 Subject: greybus: interface: delete control device upon enable failure There is an issue that when an interface failed to be enabled due to timesync failure, a previously added control device is not deleted as part of the error clean-up. This causes a leak in the sysfs file when the interface is disabled. This would eventually cause this particular interface to be unable to register future control device even after unipro_reset. See failure logs below: [ 906.495261] greybus 1-3.3: failed to add to timesync: -19 [ 906.516497] greybus 1-3.3: failed to re-enable interface: -19 [ 907.016016] greybus 1-3.3: Interface removed ... [ 1623.677343] ------------[ cut here ]------------ [ 1623.681116] WARNING: at kernel/arche/fs/sysfs/dir.c:530 sysfs_add_one+0x98/0xb4() [ 1623.681128] sysfs: cannot create duplicate filename '/bus/greybus/devices/1-3.3.ctrl' [ 1623.681252] Call trace: [ 1623.681265] [<ffffffc000207b40>] dump_backtrace+0x0/0x268 [ 1623.681272] [<ffffffc000207db8>] show_stack+0x10/0x1c [ 1623.681284] [<ffffffc000ccb890>] dump_stack+0x1c/0x28 [ 1623.681295] [<ffffffc00021f9dc>] warn_slowpath_common+0x74/0x9c [ 1623.681301] [<ffffffc00021fa60>] warn_slowpath_fmt+0x5c/0x80 [ 1623.681307] [<ffffffc000366624>] sysfs_add_one+0x94/0xb4 [ 1623.681315] [<ffffffc0003670b4>] sysfs_do_create_link_sd+0x100/0x1c8 [ 1623.681320] [<ffffffc0003671a8>] sysfs_create_link+0x2c/0x38 [ 1623.681332] [<ffffffc0005d5890>] bus_add_device+0xd8/0x190 [ 1623.681338] [<ffffffc0005d39ec>] device_add+0x2b4/0x604 [ 1623.681349] [<ffffffbffc006dfc>] gb_control_add+0x10/0x40 [greybus] [ 1623.681362] [<ffffffbffc003dac>] gb_interface_enable+0x20c/0x3b8 [greybus] [ 1623.681373] [<ffffffbffc002a30>] gb_module_add+0x124/0x174 [greybus] [ 1623.681385] [<ffffffbffc0082cc>] gb_svc_intf_set_power_mode+0xdd4/0xfe8 [greybus] [ 1623.681394] [<ffffffc00023888c>] process_one_work+0x268/0x3c8 [ 1623.681400] [<ffffffc000239a64>] worker_thread+0x204/0x358 [ 1623.681410] [<ffffffc00023f43c>] kthread+0xb8/0xc4 [ 1623.681414] ---[ end trace 44489577dd9220db ]--- [ 1623.681818] greybus 1-3.3.ctrl: failed to register control device: -17 Testing Done: - Continuous unipro_reset stress test Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Jeffrey Carlyle <jcarlyle@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 19f5c71..76569f8 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -1160,7 +1160,7 @@ int gb_interface_enable(struct gb_interface *intf) ret = gb_timesync_interface_add(intf); if (ret) { dev_err(&intf->dev, "failed to add to timesync: %d\n", ret); - goto err_destroy_bundles; + goto err_del_control; } pm_runtime_use_autosuspend(&intf->dev); @@ -1186,6 +1186,8 @@ int gb_interface_enable(struct gb_interface *intf) return 0; +err_del_control: + gb_control_del(intf->control); err_destroy_bundles: list_for_each_entry_safe(bundle, tmp, &intf->bundles, links) gb_bundle_destroy(bundle); -- cgit v0.10.2 From b6fc2876a060fdd89f6dd55a4923580983092b0f Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Mon, 1 Aug 2016 20:51:38 -0700 Subject: greybus: svc_watchdog: use schedule_delayed_work helper Instead of using the queue_delayed_work call for delayed work on system_wq, use the schedule_delayed_work helper to be more consistent on the style. Testing Done: - Check SVC watchdog is pining after the change. Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/svc_watchdog.c b/drivers/staging/greybus/svc_watchdog.c index 1295cc1..3729460 100644 --- a/drivers/staging/greybus/svc_watchdog.c +++ b/drivers/staging/greybus/svc_watchdog.c @@ -90,7 +90,7 @@ static void do_work(struct work_struct *work) dev_err(&svc->dev, "Resetting the greybus network, watch out!!!\n"); INIT_DELAYED_WORK(&reset_work, greybus_reset); - queue_delayed_work(system_wq, &reset_work, HZ / 2); + schedule_delayed_work(&reset_work, HZ / 2); /* * Disable ourselves, we don't want to trip again unless @@ -102,8 +102,7 @@ static void do_work(struct work_struct *work) /* resubmit our work to happen again, if we are still "alive" */ if (watchdog->enabled) - queue_delayed_work(system_wq, &watchdog->work, - SVC_WATCHDOG_PERIOD); + schedule_delayed_work(&watchdog->work, SVC_WATCHDOG_PERIOD); } int gb_svc_watchdog_create(struct gb_svc *svc) @@ -178,8 +177,7 @@ int gb_svc_watchdog_enable(struct gb_svc *svc) return 0; watchdog->enabled = true; - queue_delayed_work(system_wq, &watchdog->work, - SVC_WATCHDOG_PERIOD); + schedule_delayed_work(&watchdog->work, SVC_WATCHDOG_PERIOD); return 0; } -- cgit v0.10.2 From 7aa278b771505f8fb85406a891af0b7743710620 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Tue, 2 Aug 2016 13:18:30 +0100 Subject: greybus: timesync: Implement a retry mechanism It's possible the AP could miss an incoming SVC timesync pulse i.e. the AP could have interrupts switched off for long enough that one SVC GPIO strobe ends up over-lapping another one. TimeSync should be able to deal with this type of transitory failure by retrying a failed synchronous TimeSync resync up to 'n' number of times. For this patch 'n' has been set to five, which is a hand-wavy choice that 'feels' right. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/timesync.c b/drivers/staging/greybus/timesync.c index ec0a51d..744ae0c 100644 --- a/drivers/staging/greybus/timesync.c +++ b/drivers/staging/greybus/timesync.c @@ -34,6 +34,9 @@ #define GB_TIMESYNC_KTIME_UPDATE msecs_to_jiffies(1000) #define GB_TIMESYNC_MAX_KTIME_CONVERSION 15 +/* Maximum number of times we'll retry a failed synchronous sync */ +#define GB_TIMESYNC_MAX_RETRIES 5 + /* Reported nanoseconds/femtoseconds per clock */ static u64 gb_timesync_ns_per_clock; static u64 gb_timesync_fs_per_clock; @@ -870,19 +873,26 @@ int gb_timesync_schedule_synchronous(struct gb_interface *interface) { int ret; struct gb_timesync_svc *timesync_svc; + int retries; if (!(interface->features & GREYBUS_INTERFACE_FEATURE_TIMESYNC)) return 0; mutex_lock(&gb_timesync_svc_list_mutex); - timesync_svc = gb_timesync_find_timesync_svc(interface->hd); - if (!timesync_svc) { - ret = -ENODEV; - goto done; - } + for (retries = 0; retries < GB_TIMESYNC_MAX_RETRIES; retries++) { + timesync_svc = gb_timesync_find_timesync_svc(interface->hd); + if (!timesync_svc) { + ret = -ENODEV; + goto done; + } - ret = __gb_timesync_schedule_synchronous(timesync_svc, + ret = __gb_timesync_schedule_synchronous(timesync_svc, GB_TIMESYNC_STATE_INIT); + if (!ret) + break; + } + if (ret && retries == GB_TIMESYNC_MAX_RETRIES) + ret = -ETIMEDOUT; done: mutex_unlock(&gb_timesync_svc_list_mutex); return ret; -- cgit v0.10.2 From 5cb74976b9025b1a5e6e3bfd15fde0afbaf98ae4 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Tue, 2 Aug 2016 13:18:28 +0100 Subject: greybus: timesync: Ensure parallel synchronous calls succeed The guard for initiating a new synchronization operation should allow for that resync to happen in every single state except for INVALID. This patch fixes by ensuring the guard does just that. With local testing it was possible to break a sync to a Module. This hasn't been observed in a buglog but should be fixed anyway. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Acked-by: David Lin <dtwlin@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/timesync.c b/drivers/staging/greybus/timesync.c index 744ae0c..561bbea 100644 --- a/drivers/staging/greybus/timesync.c +++ b/drivers/staging/greybus/timesync.c @@ -806,8 +806,7 @@ static int gb_timesync_schedule(struct gb_timesync_svc *timesync_svc, int state) return -EINVAL; mutex_lock(×ync_svc->mutex); - if (timesync_svc->state == GB_TIMESYNC_STATE_INACTIVE || - timesync_svc->state == GB_TIMESYNC_STATE_ACTIVE) { + if (timesync_svc->state != GB_TIMESYNC_STATE_INVALID) { gb_timesync_set_state_atomic(timesync_svc, state); } else { ret = -ENODEV; -- cgit v0.10.2 From ca9551f6815efd4e7bbdee0cd2c71c368ebdf92c Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Date: Tue, 2 Aug 2016 13:18:29 +0100 Subject: greybus: timesync: Printout strobe count on sync failure If we failed to synchronize the FrameTime it would be useful to know how many of the expected strobes arrived, for example a value of 0/5 would indicate the SVC was completely dead but a value of 4/5 would indicate one GPIO pulse got lost i.e. the AP was too slow reacting to an interrupt and completely missed one of the strobe events. In either case the actual number of strobes is a useful thing to print out. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Reviewed-by: Alex Elder <elder@linaro.org> Reviewed-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/timesync.c b/drivers/staging/greybus/timesync.c index 561bbea..2e68af7 100644 --- a/drivers/staging/greybus/timesync.c +++ b/drivers/staging/greybus/timesync.c @@ -772,7 +772,8 @@ static void gb_timesync_worker(struct work_struct *work) case GB_TIMESYNC_STATE_WAIT_SVC: dev_err(×ync_svc->svc->dev, - "timeout SVC strobe completion\n"); + "timeout SVC strobe completion %d/%d\n", + timesync_svc->strobe, GB_TIMESYNC_MAX_STROBES); gb_timesync_teardown(timesync_svc); break; -- cgit v0.10.2 From ccc57e20d1cc54b6536a4e63f6da91f42b65000f Mon Sep 17 00:00:00 2001 From: Mark Greer <mgreer@animalcreek.com> Date: Tue, 2 Aug 2016 20:36:07 -0700 Subject: greybus: audio: apbridgea: Remove GET_TX/RX_DELAY message types The 'AUDIO_APBRIDGEA_TYPE_GET_TX_DELAY' and 'AUDIO_APBRIDGEA_TYPE_GET_RX_DELAY' message types have been removed from the AP <-> APBrigdeA Audio Protocol so remove them from the code. Do not coalesce the message type numbers to prevent compatibility issues between the AP and APBridgeA. Testing Done: Played music using a speaker module Signed-off-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_apbridgea.c b/drivers/staging/greybus/audio_apbridgea.c index 45d3522..1b4252d 100644 --- a/drivers/staging/greybus/audio_apbridgea.c +++ b/drivers/staging/greybus/audio_apbridgea.c @@ -84,14 +84,6 @@ int gb_audio_apbridgea_set_tx_data_size(struct gb_connection *connection, } EXPORT_SYMBOL_GPL(gb_audio_apbridgea_set_tx_data_size); -int gb_audio_apbridgea_get_tx_delay(struct gb_connection *connection, - __u16 i2s_port, __u32 *delay) -{ - /* TODO: implement */ - return -EOPNOTSUPP; -} -EXPORT_SYMBOL_GPL(gb_audio_apbridgea_get_tx_delay); - int gb_audio_apbridgea_prepare_tx(struct gb_connection *connection, __u16 i2s_port) { @@ -158,14 +150,6 @@ int gb_audio_apbridgea_set_rx_data_size(struct gb_connection *connection, } EXPORT_SYMBOL_GPL(gb_audio_apbridgea_set_rx_data_size); -int gb_audio_apbridgea_get_rx_delay(struct gb_connection *connection, - __u16 i2s_port, __u32 *delay) -{ - /* TODO: implement */ - return -EOPNOTSUPP; -} -EXPORT_SYMBOL_GPL(gb_audio_apbridgea_get_rx_delay); - int gb_audio_apbridgea_prepare_rx(struct gb_connection *connection, __u16 i2s_port) { diff --git a/drivers/staging/greybus/audio_apbridgea.h b/drivers/staging/greybus/audio_apbridgea.h index a48f815..b94cb05 100644 --- a/drivers/staging/greybus/audio_apbridgea.h +++ b/drivers/staging/greybus/audio_apbridgea.h @@ -47,13 +47,13 @@ #define AUDIO_APBRIDGEA_TYPE_REGISTER_CPORT 0x02 #define AUDIO_APBRIDGEA_TYPE_UNREGISTER_CPORT 0x03 #define AUDIO_APBRIDGEA_TYPE_SET_TX_DATA_SIZE 0x04 -#define AUDIO_APBRIDGEA_TYPE_GET_TX_DELAY 0x05 + /* 0x05 unused */ #define AUDIO_APBRIDGEA_TYPE_PREPARE_TX 0x06 #define AUDIO_APBRIDGEA_TYPE_START_TX 0x07 #define AUDIO_APBRIDGEA_TYPE_STOP_TX 0x08 #define AUDIO_APBRIDGEA_TYPE_SHUTDOWN_TX 0x09 #define AUDIO_APBRIDGEA_TYPE_SET_RX_DATA_SIZE 0x0a -#define AUDIO_APBRIDGEA_TYPE_GET_RX_DELAY 0x0b + /* 0x0b unused */ #define AUDIO_APBRIDGEA_TYPE_PREPARE_RX 0x0c #define AUDIO_APBRIDGEA_TYPE_START_RX 0x0d #define AUDIO_APBRIDGEA_TYPE_STOP_RX 0x0e @@ -115,15 +115,6 @@ struct audio_apbridgea_set_tx_data_size_request { __le16 size; } __packed; -struct audio_apbridgea_get_tx_delay_request { - struct audio_apbridgea_hdr hdr; -} __packed; - -struct audio_apbridgea_get_tx_delay_response { - struct audio_apbridgea_hdr hdr; - __le16 delay; -} __packed; - struct audio_apbridgea_prepare_tx_request { struct audio_apbridgea_hdr hdr; } __packed; @@ -146,15 +137,6 @@ struct audio_apbridgea_set_rx_data_size_request { __le16 size; } __packed; -struct audio_apbridgea_get_rx_delay_request { - struct audio_apbridgea_hdr hdr; -} __packed; - -struct audio_apbridgea_get_rx_delay_response { - struct audio_apbridgea_hdr hdr; - __le16 delay; -} __packed; - struct audio_apbridgea_prepare_rx_request { struct audio_apbridgea_hdr hdr; } __packed; diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index f4936f1..40de7e7 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -260,8 +260,6 @@ extern int gb_audio_apbridgea_unregister_cport(struct gb_connection *connection, __u8 direction); extern int gb_audio_apbridgea_set_tx_data_size(struct gb_connection *connection, __u16 i2s_port, __u16 size); -extern int gb_audio_apbridgea_get_tx_delay(struct gb_connection *connection, - __u16 i2s_port, __u32 *delay); extern int gb_audio_apbridgea_prepare_tx(struct gb_connection *connection, __u16 i2s_port); extern int gb_audio_apbridgea_start_tx(struct gb_connection *connection, @@ -272,8 +270,6 @@ extern int gb_audio_apbridgea_shutdown_tx(struct gb_connection *connection, __u16 i2s_port); extern int gb_audio_apbridgea_set_rx_data_size(struct gb_connection *connection, __u16 i2s_port, __u16 size); -extern int gb_audio_apbridgea_get_rx_delay(struct gb_connection *connection, - __u16 i2s_port, __u32 *delay); extern int gb_audio_apbridgea_prepare_rx(struct gb_connection *connection, __u16 i2s_port); extern int gb_audio_apbridgea_start_rx(struct gb_connection *connection, -- cgit v0.10.2 From 8f60ce76a4eb0911ddd5833badd0d27bb5dfb894 Mon Sep 17 00:00:00 2001 From: Mark Greer <mgreer@animalcreek.com> Date: Tue, 2 Aug 2016 20:30:28 -0700 Subject: greybus: audio: Remove GET_TX/RX_DELAY message types The 'GB_AUDIO_TYPE_GET_TX_DELAY' and 'GB_AUDIO_TYPE_GET_RX_DELAY' are no longer a part of the Greybus Audio Device Class Protocol so remove support for them. The message numbers are not coalesced to prevent compatibility issues between the AP and the module. Testing Done: Played music using a speaker module Signed-off-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index 40de7e7..1646b2c 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -235,16 +235,12 @@ extern int gb_audio_gb_set_pcm(struct gb_connection *connection, uint8_t sig_bits); extern int gb_audio_gb_set_tx_data_size(struct gb_connection *connection, uint16_t data_cport, uint16_t size); -extern int gb_audio_gb_get_tx_delay(struct gb_connection *connection, - uint16_t data_cport, uint32_t *delay); extern int gb_audio_gb_activate_tx(struct gb_connection *connection, uint16_t data_cport); extern int gb_audio_gb_deactivate_tx(struct gb_connection *connection, uint16_t data_cport); extern int gb_audio_gb_set_rx_data_size(struct gb_connection *connection, uint16_t data_cport, uint16_t size); -extern int gb_audio_gb_get_rx_delay(struct gb_connection *connection, - uint16_t data_cport, uint32_t *delay); extern int gb_audio_gb_activate_rx(struct gb_connection *connection, uint16_t data_cport); extern int gb_audio_gb_deactivate_rx(struct gb_connection *connection, diff --git a/drivers/staging/greybus/audio_gb.c b/drivers/staging/greybus/audio_gb.c index 167683d..a2f1c92 100644 --- a/drivers/staging/greybus/audio_gb.c +++ b/drivers/staging/greybus/audio_gb.c @@ -161,26 +161,6 @@ int gb_audio_gb_set_tx_data_size(struct gb_connection *connection, } EXPORT_SYMBOL_GPL(gb_audio_gb_set_tx_data_size); -int gb_audio_gb_get_tx_delay(struct gb_connection *connection, - uint16_t data_cport, uint32_t *delay) -{ - struct gb_audio_get_tx_delay_request req; - struct gb_audio_get_tx_delay_response resp; - int ret; - - req.data_cport = cpu_to_le16(data_cport); - - ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_TX_DELAY, - &req, sizeof(req), &resp, sizeof(resp)); - if (ret) - return ret; - - *delay = le32_to_cpu(resp.delay); - - return 0; -} -EXPORT_SYMBOL_GPL(gb_audio_gb_get_tx_delay); - int gb_audio_gb_activate_tx(struct gb_connection *connection, uint16_t data_cport) { @@ -218,26 +198,6 @@ int gb_audio_gb_set_rx_data_size(struct gb_connection *connection, } EXPORT_SYMBOL_GPL(gb_audio_gb_set_rx_data_size); -int gb_audio_gb_get_rx_delay(struct gb_connection *connection, - uint16_t data_cport, uint32_t *delay) -{ - struct gb_audio_get_rx_delay_request req; - struct gb_audio_get_rx_delay_response resp; - int ret; - - req.data_cport = cpu_to_le16(data_cport); - - ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_RX_DELAY, - &req, sizeof(req), &resp, sizeof(resp)); - if (ret) - return ret; - - *delay = le32_to_cpu(resp.delay); - - return 0; -} -EXPORT_SYMBOL_GPL(gb_audio_gb_get_rx_delay); - int gb_audio_gb_activate_rx(struct gb_connection *connection, uint16_t data_cport) { diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index edbc5df..7628c18 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -1935,11 +1935,11 @@ struct gb_lights_get_flash_fault_response { #define GB_AUDIO_TYPE_GET_PCM 0x08 #define GB_AUDIO_TYPE_SET_PCM 0x09 #define GB_AUDIO_TYPE_SET_TX_DATA_SIZE 0x0a -#define GB_AUDIO_TYPE_GET_TX_DELAY 0x0b + /* 0x0b unused */ #define GB_AUDIO_TYPE_ACTIVATE_TX 0x0c #define GB_AUDIO_TYPE_DEACTIVATE_TX 0x0d #define GB_AUDIO_TYPE_SET_RX_DATA_SIZE 0x0e -#define GB_AUDIO_TYPE_GET_RX_DELAY 0x0f + /* 0x0f unused */ #define GB_AUDIO_TYPE_ACTIVATE_RX 0x10 #define GB_AUDIO_TYPE_DEACTIVATE_RX 0x11 #define GB_AUDIO_TYPE_JACK_EVENT 0x12 @@ -2227,14 +2227,6 @@ struct gb_audio_set_tx_data_size_request { __le16 size; } __packed; -struct gb_audio_get_tx_delay_request { - __le16 data_cport; -} __packed; - -struct gb_audio_get_tx_delay_response { - __le32 delay; -} __packed; - struct gb_audio_activate_tx_request { __le16 data_cport; } __packed; @@ -2248,14 +2240,6 @@ struct gb_audio_set_rx_data_size_request { __le16 size; } __packed; -struct gb_audio_get_rx_delay_request { - __le16 data_cport; -} __packed; - -struct gb_audio_get_rx_delay_response { - __le32 delay; -} __packed; - struct gb_audio_activate_rx_request { __le16 data_cport; } __packed; -- cgit v0.10.2 From 6e8fc8c4c939730e4550a3f70c640f6f0a281079 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 3 Aug 2016 14:09:28 +0200 Subject: greybus: remove unused protocol-version messages Remove the unused protocol-version messages. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 7628c18..d8f8194 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -99,15 +99,6 @@ struct gb_operation_msg_hdr { #define GB_REQUEST_TYPE_PING 0x00 #define GB_REQUEST_TYPE_INVALID 0x7f -struct gb_protocol_version_request { - __u8 major; - __u8 minor; -} __packed; - -struct gb_protocol_version_response { - __u8 major; - __u8 minor; -} __packed; /* Control Protocol */ -- cgit v0.10.2 From 081ee14ab4452bbf7bab9b4df61519bb48a44375 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 3 Aug 2016 14:09:29 +0200 Subject: greybus: control: remove some braces Remove some no-longer-needed braces around an error path. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index 34493d5..658f8a6 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -174,9 +174,8 @@ int gb_control_mode_switch_operation(struct gb_control *control) return -ENOMEM; ret = gb_operation_request_send_sync(operation); - if (ret) { + if (ret) dev_err(&control->dev, "failed to send mode switch: %d\n", ret); - } gb_operation_put(operation); -- cgit v0.10.2 From 06d8b7d9cf37c323aae23bfe97eabdebf0e94ce7 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 3 Aug 2016 14:09:30 +0200 Subject: greybus: connection: fix offloaded-connection ping cport id The host-device cport_ping callback expects the AP side cport id, but was incorrectly passed the interface cport id. Note that no host-device driver currently implements this callback, and that it is soon even to be removed. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 634c8b1..ce8ba9c 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -527,7 +527,7 @@ static int gb_connection_ping(struct gb_connection *connection) if (!hd->driver->cport_ping) return 0; - ret = hd->driver->cport_ping(hd, connection->intf_cport_id); + ret = hd->driver->cport_ping(hd, connection->hd_cport_id); } else { ret = gb_connection_ping_operation(connection); } -- cgit v0.10.2 From c468999e6acd3e8330db7d18dca320f8b21bf074 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 3 Aug 2016 14:09:31 +0200 Subject: greybus: es2: clean up ARPC symbol names Add a _req suffix to request message structures, and a _TYPE_ infix to request type defines. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 2020187..0850b59 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -609,7 +609,7 @@ static int cport_reset(struct gb_host_device *hd, u16 cport_id) { struct es2_ap_dev *es2 = hd_to_es2(hd); struct usb_device *udev = es2->usb_dev; - struct arpc_cport_reset req; + struct arpc_cport_reset_req req; int retval; int result = 0; @@ -621,7 +621,7 @@ static int cport_reset(struct gb_host_device *hd, u16 cport_id) } req.cport_id = cpu_to_le16(cport_id); - retval = arpc_sync(es2, ARPC_CPORT_RESET, &req, sizeof(req), + retval = arpc_sync(es2, ARPC_TYPE_CPORT_RESET, &req, sizeof(req), &result, ES2_TIMEOUT); if (retval == -EREMOTEIO) { dev_err(&udev->dev, "failed to reset cport %u: %d\n", cport_id, diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index d8f8194..8484f05 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -292,9 +292,9 @@ struct arpc_response_message { __u8 result; /* Result of RPC */ } __packed; -#define ARPC_CPORT_RESET 0x00 +#define ARPC_TYPE_CPORT_RESET 0x00 -struct arpc_cport_reset { +struct arpc_cport_reset_req { __le16 cport_id; } __packed; -- cgit v0.10.2 From 4ae2d962637e4a002d1f0884dceec800c79b3ea4 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 3 Aug 2016 14:09:32 +0200 Subject: greybus: es2: always set result value Make sure to always set the result value for ARPC instead of forcing every caller to do it in order to avoid compiler warnings. The ARPC result should still be ignored unless arpc_sync returns -EREMOTEIO. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 0850b59..c31124d 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -611,7 +611,7 @@ static int cport_reset(struct gb_host_device *hd, u16 cport_id) struct usb_device *udev = es2->usb_dev; struct arpc_cport_reset_req req; int retval; - int result = 0; + int result; switch (cport_id) { case GB_SVC_CPORT_ID: @@ -1184,6 +1184,8 @@ static int arpc_sync(struct es2_ap_dev *es2, u8 type, void *payload, unsigned long flags; int retval; + *result = 0; + rpc = arpc_alloc(payload, size, type); if (!rpc) return -ENOMEM; @@ -1205,11 +1207,12 @@ static int arpc_sync(struct es2_ap_dev *es2, u8 type, void *payload, goto out_arpc_del; } - *result = rpc->resp->result; - if (*result) + if (rpc->resp->result) { retval = -EREMOTEIO; - else + *result = rpc->resp->result; + } else { retval = 0; + } out_arpc_del: spin_lock_irqsave(&es2->arpc_lock, flags); -- cgit v0.10.2 From 121bae2bec47a9944049f2583b1d31f479110f0f Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 3 Aug 2016 14:09:33 +0200 Subject: greybus: es2: allow ARPC result to be ignored Allow user of ARPC to pass a NULL pointer for the ARPC result. For simple requests there may only be one error code for remote errors, or the caller may simply not care to differentiate them. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index c31124d..8d0e52d 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -1184,7 +1184,8 @@ static int arpc_sync(struct es2_ap_dev *es2, u8 type, void *payload, unsigned long flags; int retval; - *result = 0; + if (result) + *result = 0; rpc = arpc_alloc(payload, size, type); if (!rpc) @@ -1209,7 +1210,8 @@ static int arpc_sync(struct es2_ap_dev *es2, u8 type, void *payload, if (rpc->resp->result) { retval = -EREMOTEIO; - *result = rpc->resp->result; + if (result) + *result = rpc->resp->result; } else { retval = 0; } -- cgit v0.10.2 From 54f34e1e4d065ea38f531341018b41c590d71861 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 3 Aug 2016 14:09:34 +0200 Subject: greybus: es2: add define for ARPC CPort requests Add dedicated define for ARPC CPort requests instead of using the default timeout for USB vendor requests. We still allow responses to take 500 ms to arrive, but note that this adds on top of the 500ms already allowed for a requests to be acknowledged. This should probably be tightened up at some point. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 8d0e52d..66fd92d 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -19,6 +19,10 @@ #include "kernel_ver.h" #include "connection.h" + +/* Default timeout for ARPC CPort requests */ +#define ES2_ARPC_CPORT_TIMEOUT 500 + /* Fixed CPort numbers */ #define ES2_CPORT_CDSI0 16 #define ES2_CPORT_CDSI1 17 @@ -622,7 +626,7 @@ static int cport_reset(struct gb_host_device *hd, u16 cport_id) req.cport_id = cpu_to_le16(cport_id); retval = arpc_sync(es2, ARPC_TYPE_CPORT_RESET, &req, sizeof(req), - &result, ES2_TIMEOUT); + &result, ES2_ARPC_CPORT_TIMEOUT); if (retval == -EREMOTEIO) { dev_err(&udev->dev, "failed to reset cport %u: %d\n", cport_id, result); -- cgit v0.10.2 From 60793c9be9a140e2102a0f64a38d34e9b28a1357 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 3 Aug 2016 14:09:35 +0200 Subject: greybus: es2: rename USB vendor-request timeout define Give the USB vendor-request timeout define a more descriptive name. Also drop the since-long obsolete comments about allowing "the SVC to do something" and "SVC messages go down our control pipe". Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 66fd92d..3b8d81ef 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -20,6 +20,9 @@ #include "connection.h" +/* Default timeout for USB vendor requests. */ +#define ES2_USB_CTRL_TIMEOUT 500 + /* Default timeout for ARPC CPort requests */ #define ES2_ARPC_CPORT_TIMEOUT 500 @@ -204,8 +207,6 @@ static int cport_to_ep_pair(struct es2_ap_dev *es2, u16 cport_id) return es2->cport_to_ep[cport_id]; } -#define ES2_TIMEOUT 500 /* 500 ms for the SVC to do something */ - /* Disable for now until we work all of this out to keep a warning-free build */ #if 0 /* Test if the endpoints pair is already mapped to a cport */ @@ -250,7 +251,7 @@ static int map_cport_to_ep(struct es2_ap_dev *es2, 0x00, 0x00, (char *)cport_to_ep, sizeof(*cport_to_ep), - ES2_TIMEOUT); + ES2_USB_CTRL_TIMEOUT); if (retval == sizeof(*cport_to_ep)) retval = 0; kfree(cport_to_ep); @@ -280,7 +281,7 @@ static int output_sync(struct es2_ap_dev *es2, void *req, u16 size, u8 cmd) cmd, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - 0, 0, data, size, ES2_TIMEOUT); + 0, 0, data, size, ES2_USB_CTRL_TIMEOUT); if (retval < 0) dev_err(&udev->dev, "%s: return error %d\n", __func__, retval); else @@ -716,7 +717,7 @@ static int cport_enable(struct gb_host_device *hd, u16 cport_id, GB_APB_REQUEST_CPORT_FLAGS, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, cport_id, 0, - req, sizeof(*req), ES2_TIMEOUT); + req, sizeof(*req), ES2_USB_CTRL_TIMEOUT); if (ret != sizeof(*req)) { dev_err(&udev->dev, "failed to set cport flags for port %d\n", cport_id); @@ -754,7 +755,7 @@ static int latency_tag_enable(struct gb_host_device *hd, u16 cport_id) GB_APB_REQUEST_LATENCY_TAG_EN, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, cport_id, 0, NULL, - 0, ES2_TIMEOUT); + 0, ES2_USB_CTRL_TIMEOUT); if (retval < 0) dev_err(&udev->dev, "Cannot enable latency tag for cport %d\n", @@ -772,7 +773,7 @@ static int latency_tag_disable(struct gb_host_device *hd, u16 cport_id) GB_APB_REQUEST_LATENCY_TAG_DIS, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, cport_id, 0, NULL, - 0, ES2_TIMEOUT); + 0, ES2_USB_CTRL_TIMEOUT); if (retval < 0) dev_err(&udev->dev, "Cannot disable latency tag for cport %d\n", @@ -790,7 +791,7 @@ static int cport_features_enable(struct gb_host_device *hd, u16 cport_id) GB_APB_REQUEST_CPORT_FEAT_EN, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, cport_id, 0, NULL, - 0, ES2_TIMEOUT); + 0, ES2_USB_CTRL_TIMEOUT); if (retval < 0) dev_err(&udev->dev, "Cannot enable CPort features for cport %u: %d\n", cport_id, retval); @@ -807,7 +808,7 @@ static int cport_features_disable(struct gb_host_device *hd, u16 cport_id) GB_APB_REQUEST_CPORT_FEAT_DIS, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, cport_id, 0, NULL, - 0, ES2_TIMEOUT); + 0, ES2_USB_CTRL_TIMEOUT); if (retval < 0) dev_err(&udev->dev, "Cannot disable CPort features for cport %u: %d\n", @@ -835,7 +836,7 @@ static int timesync_enable(struct gb_host_device *hd, u8 count, REQUEST_TIMESYNC_ENABLE, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0, 0, request, - sizeof(*request), ES2_TIMEOUT); + sizeof(*request), ES2_USB_CTRL_TIMEOUT); if (retval < 0) dev_err(&udev->dev, "Cannot enable timesync %d\n", retval); @@ -853,7 +854,7 @@ static int timesync_disable(struct gb_host_device *hd) REQUEST_TIMESYNC_DISABLE, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0, 0, NULL, - 0, ES2_TIMEOUT); + 0, ES2_USB_CTRL_TIMEOUT); if (retval < 0) dev_err(&udev->dev, "Cannot disable timesync %d\n", retval); @@ -878,7 +879,7 @@ static int timesync_authoritative(struct gb_host_device *hd, u64 *frame_time) REQUEST_TIMESYNC_AUTHORITATIVE, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0, 0, request, - sizeof(*request), ES2_TIMEOUT); + sizeof(*request), ES2_USB_CTRL_TIMEOUT); if (retval < 0) dev_err(&udev->dev, "Cannot timesync authoritative out %d\n", retval); @@ -901,7 +902,8 @@ static int timesync_get_last_event(struct gb_host_device *hd, u64 *frame_time) REQUEST_TIMESYNC_GET_LAST_EVENT, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0, 0, response_frame_time, - sizeof(*response_frame_time), ES2_TIMEOUT); + sizeof(*response_frame_time), + ES2_USB_CTRL_TIMEOUT); if (retval != sizeof(*response_frame_time)) { dev_err(&udev->dev, "Cannot get last TimeSync event: %d\n", @@ -1168,7 +1170,7 @@ static int arpc_send(struct es2_ap_dev *es2, struct arpc *rpc, int timeout) USB_RECIP_INTERFACE, 0, 0, rpc->req, le16_to_cpu(rpc->req->size), - ES2_TIMEOUT); + ES2_USB_CTRL_TIMEOUT); if (retval != le16_to_cpu(rpc->req->size)) { dev_err(&udev->dev, "failed to send ARPC request %d: %d\n", @@ -1288,7 +1290,6 @@ static void apb_log_get(struct es2_ap_dev *es2, char *buf) { int retval; - /* SVC messages go down our control pipe */ do { retval = usb_control_msg(es2->usb_dev, usb_rcvctrlpipe(es2->usb_dev, 0), @@ -1297,7 +1298,7 @@ static void apb_log_get(struct es2_ap_dev *es2, char *buf) 0x00, 0x00, buf, APB1_LOG_MSG_SIZE, - ES2_TIMEOUT); + ES2_USB_CTRL_TIMEOUT); if (retval > 0) kfifo_in(&es2->apb_log_fifo, buf, retval); } while (retval > 0); @@ -1424,7 +1425,7 @@ static int apb_get_cport_count(struct usb_device *udev) GB_APB_REQUEST_CPORT_COUNT, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0, 0, cport_count, - sizeof(*cport_count), ES2_TIMEOUT); + sizeof(*cport_count), ES2_USB_CTRL_TIMEOUT); if (retval != sizeof(*cport_count)) { dev_err(&udev->dev, "Cannot retrieve CPort count: %d\n", retval); -- cgit v0.10.2 From 8ef0b5383110977d81746cd0b09c3877d51c3a67 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath <hiremath_vaibhav@projectara.com> Date: Wed, 3 Aug 2016 17:15:38 +0530 Subject: greybus: arche-platform: Reset SVC & APB only if turned off by SUSPEND_PREPARE There is possible race condition in arche platform driver for maintaining of ->state field, when shared with timesync driver. Assume device booted fine, all connected modules have been enumerated correctly. As part of suspend-resume operation we have pm_notifier callback, where we turn off SVC & APB and coldboot on resume. In the process of resume, all modules gets enumerated again, and timesync driver does come into picture everytime. So when timesync driver requests arche-platform to change the state to TIMESYNC and in the middle of sync operation, if suspend gets triggered, then execution lands into arche-platform->pm_notifier callback, leading to race condition in the driver, where it checks for (state != ACTIVE) in PM_SUSPEND_PREPARE and returns, but in PM_POST_SUSPEND it just simply coldboots SVC & APB, which would inbalance all resources (including IRQ). So we need a add check in PM_POST_SUSPEND, to make sure that, we only coldboot devices if they are in to off state, i.e. if (state != OFF) then return. Testing Done: Done regressive suspend/resume testing on EVT2 platform. Note that, I some time hit issue. Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index cbe8bdc..adec1fd 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -548,6 +548,9 @@ static int arche_platform_pm_notifier(struct notifier_block *notifier, arche_platform_poweroff_seq(arche_pdata); break; case PM_POST_SUSPEND: + if (arche_pdata->state != ARCHE_PLATFORM_STATE_OFF) + break; + arche_platform_wd_irq_en(arche_pdata); arche_platform_coldboot_seq(arche_pdata); break; -- cgit v0.10.2 From 921dbe52b40b2573d9a0e8337c768930bef25fb4 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Date: Thu, 28 Jul 2016 13:47:37 +0530 Subject: greybus: arche-platform: Add support for SPI bus sharing for Mihi In case of Mihi, SPI bus is shared between APB1 and APB2 SPI ROMs, so their FW flashing must be sequential and arche-platform driver should make sure that they are mutual exclusive in nature. So this patch adds certain restrictions to the user of the arche-platform driver, - User can no longer flash APB1 and APB2 SPI ROM in parallel - SPI bus becomes an resource, so user must claim it by moving respective APB device into FW_FLASHING mode and release it by exiting FW_FLASHING mode. User can exit FW_FLASHING mode by switching to any other modes (ACTIVE, OFF, STANDBY). - If APB1 is in FW_FLASHING mode, APB2 can no longer enter into FW_FLASHING mode. User will get -EBUSY. Having said that, while APB1 is into FW_FLASHING mode, APB2 can independently boot from its own SPI ROM. Testing Done: Tested by simulating usecase on EVT2. - Made sure that APB1 and APB2 FW_FLASHING mode is mutual exclusive in nature. Confirmed that an attempt on second device return -EBUSY. - Added simulating code, where printed state of dummy gpio for spi-en and verified that it shows right pin status for both APBs Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index 049d496..59d9d42 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -42,6 +42,10 @@ struct arche_apb_ctrl_drvdata { struct pinctrl *pinctrl; struct pinctrl_state *pin_default; + + /* V2: SPI Bus control */ + int spi_en_gpio; + bool spi_en_polarity_high; }; /* @@ -73,6 +77,10 @@ static int coldboot_seq(struct platform_device *pdev) /* Hold APB in reset state */ assert_reset(apb->resetn_gpio); + if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING && + gpio_is_valid(apb->spi_en_gpio)) + devm_gpio_free(dev, apb->spi_en_gpio); + /* Enable power to APB */ if (!IS_ERR(apb->vcore)) { ret = regulator_enable(apb->vcore); @@ -128,6 +136,23 @@ static int fw_flashing_seq(struct platform_device *pdev) return ret; } + if (gpio_is_valid(apb->spi_en_gpio)) { + unsigned long flags; + + if (apb->spi_en_polarity_high) + flags = GPIOF_OUT_INIT_HIGH; + else + flags = GPIOF_OUT_INIT_LOW; + + ret = devm_gpio_request_one(dev, apb->spi_en_gpio, + flags, "apb_spi_en"); + if (ret) { + dev_err(dev, "Failed requesting SPI bus en gpio %d\n", + apb->spi_en_gpio); + return ret; + } + } + /* for flashing device should be in reset state */ assert_reset(apb->resetn_gpio); apb->state = ARCHE_PLATFORM_STATE_FW_FLASHING; @@ -137,6 +162,7 @@ static int fw_flashing_seq(struct platform_device *pdev) static int standby_boot_seq(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); if (apb->init_disabled) @@ -147,6 +173,10 @@ static int standby_boot_seq(struct platform_device *pdev) apb->state == ARCHE_PLATFORM_STATE_OFF) return 0; + if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING && + gpio_is_valid(apb->spi_en_gpio)) + devm_gpio_free(dev, apb->spi_en_gpio); + /* * As per WDM spec, do nothing * @@ -162,11 +192,16 @@ static int standby_boot_seq(struct platform_device *pdev) static void poweroff_seq(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); if (apb->init_disabled || apb->state == ARCHE_PLATFORM_STATE_OFF) return; + if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING && + gpio_is_valid(apb->spi_en_gpio)) + devm_gpio_free(dev, apb->spi_en_gpio); + /* disable the clock */ if (gpio_is_valid(apb->clk_en_gpio)) gpio_set_value(apb->clk_en_gpio, 0); @@ -369,6 +404,14 @@ static int apb_ctrl_get_devtree_data(struct platform_device *pdev, return PTR_ERR(apb->pin_default); } + /* Only applicable for platform >= V2 */ + apb->spi_en_gpio = of_get_named_gpio(np, "spi-en-gpio", 0); + if (apb->spi_en_gpio >= 0) { + if (of_property_read_bool(pdev->dev.of_node, + "spi-en-active-high")) + apb->spi_en_polarity_high = true; + } + return 0; } diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index adec1fd..9d9048e 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -215,18 +215,6 @@ static int apb_cold_boot(struct device *dev, void *data) return 0; } -static int apb_fw_flashing_state(struct device *dev, void *data) -{ - int ret; - - ret = apb_ctrl_fw_flashing(dev); - if (ret) - dev_warn(dev, "failed to switch to fw flashing state\n"); - - /*Child nodes are independent, so do not exit coldboot operation */ - return 0; -} - static int apb_poweroff(struct device *dev, void *data) { apb_ctrl_poweroff(dev); @@ -485,17 +473,18 @@ retry: if (arche_pdata->state == ARCHE_PLATFORM_STATE_FW_FLASHING) goto exit; - /* First we want to make sure we power off everything - * and then enter FW flashing state */ - device_for_each_child(arche_pdata->dev, NULL, apb_poweroff); - + /* + * Here we only control SVC. + * + * In case of FW_FLASHING mode we do not want to control + * APBs, as in case of V2, SPI bus is shared between both + * the APBs. So let user chose which APB he wants to flash. + */ arche_platform_poweroff_seq(arche_pdata); ret = arche_platform_fw_flashing_seq(arche_pdata); if (ret) goto exit; - - device_for_each_child(arche_pdata->dev, NULL, apb_fw_flashing_state); } else { dev_err(arche_pdata->dev, "unknown state\n"); ret = -EINVAL; -- cgit v0.10.2 From 90579d4b577154606a54cab9771e15a41867b79b Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Thu, 4 Aug 2016 15:14:28 +0530 Subject: greybus: audio: Remove un-necessary goto statement For most of the helper functions, goto statement is widely used. It was originally used with an intent of single exit point for the function with some cleanup required. This is no more the case. So, simplify code by avoiding un-necessary gotos. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index d7679e6..9b98e9c 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -64,7 +64,8 @@ static int gbaudio_module_disable(struct gbaudio_codec_info *codec, if (module_state == GBAUDIO_CODEC_SHUTDOWN) { dev_dbg(codec->dev, "%s: module already configured\n", module->name); - goto func_exit; + mutex_unlock(&codec->lock); + return 0; } /* find the dai */ @@ -72,8 +73,8 @@ static int gbaudio_module_disable(struct gbaudio_codec_info *codec, if (!data) { dev_err(codec->dev, "%s:%s DATA connection missing\n", dai_name, module->name); - ret = -ENODEV; - goto func_exit; + mutex_unlock(&codec->lock); + return -ENODEV; } if (codec_state > GBAUDIO_CODEC_HWPARAMS) { data_cport = data->connection->intf_cport_id; @@ -162,7 +163,8 @@ static int gbaudio_module_enable(struct gbaudio_codec_info *codec, if (module_state == codec_state) { dev_dbg(codec->dev, "%s: module already configured\n", module->name); - goto func_exit; + mutex_unlock(&codec->lock); + return 0; } /* find the dai */ @@ -170,8 +172,8 @@ static int gbaudio_module_enable(struct gbaudio_codec_info *codec, if (!data) { dev_err(codec->dev, "%s:%s DATA connection missing\n", dai_name, module->name); - ret = -ENODEV; - goto func_exit; + mutex_unlock(&codec->lock); + return -ENODEV; } /* register cport */ @@ -754,8 +756,8 @@ static int gbcodec_mute_stream(struct snd_soc_dai *dai, int mute, int stream) if (!data) { dev_err(dai->dev, "%s:%s DATA connection missing\n", dai->name, module->name); - ret = -ENODEV; - goto func_exit; + mutex_unlock(&codec->lock); + return -ENODEV; } if (!mute && !stream) {/* start playback */ @@ -792,9 +794,8 @@ static int gbcodec_mute_stream(struct snd_soc_dai *dai, int mute, int stream) module->name, mute ? "Mute" : "Unmute", stream ? "Capture" : "Playback", ret); -func_exit: mutex_unlock(&codec->lock); - return 0; + return ret; } static struct snd_soc_dai_ops gbcodec_dai_ops = { -- cgit v0.10.2 From ce9413062f8e2366916beebbfa8e73c6ff1a2c8c Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Thu, 4 Aug 2016 15:14:29 +0530 Subject: greybus: audio: Enable audio path based on control switch state only As per current implementation, audio data is played from each individual SPK module connected to endo frame. This is not a valid requirement in case of capture/headset path. So, provide a mechanism to enable individual module path based on it's control switch state. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 9b98e9c..0bcd3d4 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -323,11 +323,6 @@ EXPORT_SYMBOL(gbaudio_module_update); static int gbcodec_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - int ret = 0; - __u16 i2s_port, cportid; - int state; - struct gbaudio_data_connection *data; - struct gbaudio_module_info *module; struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev); mutex_lock(&codec->lock); @@ -338,164 +333,26 @@ static int gbcodec_startup(struct snd_pcm_substream *substream, return -ENODEV; } - state = codec->stream[substream->stream].state; - list_for_each_entry(module, &codec->module_list, list) { - /* find the dai */ - data = find_data(module, dai->name); - if (!data) { - dev_err(dai->dev, "%s:%s DATA connection missing\n", - dai->name, module->name); - continue; - } - - /* register cport */ - i2s_port = 0; /* fixed for now */ - cportid = data->connection->hd_cport_id; - switch (substream->stream) { - case SNDRV_PCM_STREAM_CAPTURE: - ret = gb_audio_apbridgea_register_cport( - data->connection, - i2s_port, cportid, - AUDIO_APBRIDGEA_DIRECTION_RX); - break; - case SNDRV_PCM_STREAM_PLAYBACK: - ret = gb_audio_apbridgea_register_cport( - data->connection, - i2s_port, cportid, - AUDIO_APBRIDGEA_DIRECTION_TX); - break; - default: - dev_err(dai->dev, "Inavlid stream\n"); - mutex_unlock(&codec->lock); - return -EINVAL; - } - dev_dbg(dai->dev, "Register %s:%d DAI, ret:%d\n", dai->name, - cportid, ret); - state = GBAUDIO_CODEC_STARTUP; - module->ctrlstate[substream->stream] = state; - dev_dbg(dai->dev, "%s: state:%d\n", module->name, state); - } - codec->stream[substream->stream].state = state; + codec->stream[substream->stream].state = GBAUDIO_CODEC_STARTUP; codec->stream[substream->stream].dai_name = dai->name; mutex_unlock(&codec->lock); /* to prevent suspend in case of active audio */ pm_stay_awake(dai->dev); - return ret; -} - -static int gbmodule_shutdown_tx(struct gbaudio_module_info *module, - struct gbaudio_data_connection *data, - int codec_state, struct device *dev) -{ - int ret, module_state; - __u16 i2s_port, cportid; - - module_state = module->ctrlstate[0]; - if (module_state == GBAUDIO_CODEC_SHUTDOWN) { - dev_dbg(dev, "%s: module already configured\n", - module->name); - return 0; - } - - /* deactivate */ - cportid = data->connection->intf_cport_id; - if (module_state >= GBAUDIO_CODEC_PREPARE) { - ret = gb_audio_gb_deactivate_tx(module->mgmt_connection, - cportid); - if (ret) - return ret; - } - - /* unregister cport */ - i2s_port = 0; /* fixed for now */ - cportid = data->connection->hd_cport_id; - ret = gb_audio_apbridgea_unregister_cport(data->connection, i2s_port, - cportid, - AUDIO_APBRIDGEA_DIRECTION_TX); - - return ret; -} - -static int gbmodule_shutdown_rx(struct gbaudio_module_info *module, - struct gbaudio_data_connection *data, - int codec_state, struct device *dev) -{ - int ret, module_state; - __u16 i2s_port, cportid; - - module_state = module->ctrlstate[1]; - if (module_state == GBAUDIO_CODEC_SHUTDOWN) { - dev_dbg(dev, "%s: module already configured\n", - module->name); - return 0; - } - - /* deactivate */ - cportid = data->connection->intf_cport_id; - if (module_state >= GBAUDIO_CODEC_PREPARE) { - ret = gb_audio_gb_deactivate_rx(module->mgmt_connection, - cportid); - if (ret) - return ret; - } - - /* unregister cport */ - i2s_port = 0; /* fixed for now */ - cportid = data->connection->hd_cport_id; - ret = gb_audio_apbridgea_unregister_cport(data->connection, i2s_port, - cportid, - AUDIO_APBRIDGEA_DIRECTION_RX); - - return ret; + return 0; } static void gbcodec_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - int ret, state; - struct gbaudio_module_info *module; - struct gbaudio_data_connection *data; struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev); mutex_lock(&codec->lock); - if (list_empty(&codec->module_list)) { - dev_err(codec->dev, "No codec module available\n"); - codec->stream[substream->stream].state = GBAUDIO_CODEC_SHUTDOWN; - codec->stream[substream->stream].dai_name = NULL; - mutex_unlock(&codec->lock); - pm_relax(dai->dev); - return; - } + if (list_empty(&codec->module_list)) + dev_info(codec->dev, "No codec module available during shutdown\n"); - state = codec->stream[substream->stream].state; - list_for_each_entry(module, &codec->module_list, list) { - /* find the dai */ - data = find_data(module, dai->name); - if (!data) { - dev_err(dai->dev, "%s:%s DATA connection missing\n", - dai->name, module->name); - continue; - } - - switch (substream->stream) { - case SNDRV_PCM_STREAM_PLAYBACK: - ret = gbmodule_shutdown_tx(module, data, state, - dai->dev); - break; - case SNDRV_PCM_STREAM_CAPTURE: - ret = gbmodule_shutdown_rx(module, data, state, - dai->dev); - break; - } - dev_dbg(dai->dev, "Unregister %s DAI, ret:%d\n", dai->name, - ret); - state = GBAUDIO_CODEC_SHUTDOWN; - module->ctrlstate[substream->stream] = state; - dev_dbg(dai->dev, "%s: state:%d\n", module->name, state); - } - codec->stream[substream->stream].state = state; + codec->stream[substream->stream].state = GBAUDIO_CODEC_SHUTDOWN; codec->stream[substream->stream].dai_name = NULL; mutex_unlock(&codec->lock); pm_relax(dai->dev); @@ -509,10 +366,8 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream, int ret; uint8_t sig_bits, channels; uint32_t format, rate; - uint16_t data_cport; struct gbaudio_module_info *module; struct gbaudio_data_connection *data; - int state; struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev); mutex_lock(&codec->lock); @@ -551,122 +406,37 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream, } format = GB_AUDIO_PCM_FMT_S16_LE; - state = codec->stream[substream->stream].state; + /* find the data connection */ list_for_each_entry(module, &codec->module_list, list) { - /* find the data connection */ data = find_data(module, dai->name); - if (!data) { - dev_err(dai->dev, "%s:%s DATA connection missing\n", - dai->name, module->name); - continue; - } - - data_cport = data->connection->intf_cport_id; - /* XXX check impact of sig_bit - * it should not change ideally - */ - dev_dbg(dai->dev, - "cport:%d, rate:%d, channel %d, format %d, sig_bits:%d\n", - data_cport, rate, channels, format, sig_bits); - ret = gb_audio_gb_set_pcm(module->mgmt_connection, data_cport, - format, rate, channels, sig_bits); - if (ret) { - dev_err_ratelimited(dai->dev, "%d: Error during set_pcm\n", ret); - goto func_exit; - } - if (state < GBAUDIO_CODEC_HWPARAMS) { - ret = gb_audio_apbridgea_set_config(data->connection, 0, - AUDIO_APBRIDGEA_PCM_FMT_16, - AUDIO_APBRIDGEA_PCM_RATE_48000, - 6144000); - if (ret) { - dev_err_ratelimited(dai->dev, - "%d: Error during set_config\n", ret); - goto func_exit; - } - } - state = GBAUDIO_CODEC_HWPARAMS; - module->ctrlstate[substream->stream] = state; - dev_dbg(dai->dev, "%s: state:%d\n", module->name, state); + if (data) + break; } - codec->stream[substream->stream].state = state; - codec->stream[substream->stream].format = format; - codec->stream[substream->stream].rate = rate; - codec->stream[substream->stream].channels = channels; - codec->stream[substream->stream].sig_bits = sig_bits; - -func_exit: - mutex_unlock(&codec->lock); - return ret; -} - -static int gbmodule_prepare_tx(struct gbaudio_module_info *module, - struct gbaudio_data_connection *data, - int codec_state, struct device *dev) -{ - int ret; - uint16_t data_cport; - data_cport = data->connection->intf_cport_id; - ret = gb_audio_gb_set_tx_data_size(module->mgmt_connection, data_cport, - 192); - if (ret) { - dev_err_ratelimited(dev, "%d:Error during set_tx_data_size, cport:%d\n", - ret, data_cport); - return ret; - } - if (codec_state < GBAUDIO_CODEC_PREPARE) { - ret = gb_audio_apbridgea_set_tx_data_size(data->connection, 0, - 192); - if (ret) { - dev_err_ratelimited(dev, - "%d:Error during apbridgea set_tx_data_size, cport\n", - ret); - return ret; - } + if (!data) { + dev_err(dai->dev, "DATA connection missing\n"); + mutex_unlock(&codec->lock); + return -EINVAL; } - ret = gb_audio_gb_activate_tx(module->mgmt_connection, - data_cport); - if (ret) - dev_err_ratelimited(dev, "%s:Error during activate stream,%d\n", - module->name, ret); - - return ret; -} - -static int gbmodule_prepare_rx(struct gbaudio_module_info *module, - struct gbaudio_data_connection *data, - int codec_state, struct device *dev) -{ - int ret; - uint16_t data_cport; - data_cport = data->connection->intf_cport_id; - - ret = gb_audio_gb_set_rx_data_size(module->mgmt_connection, data_cport, - 192); + ret = gb_audio_apbridgea_set_config(data->connection, 0, + AUDIO_APBRIDGEA_PCM_FMT_16, + AUDIO_APBRIDGEA_PCM_RATE_48000, + 6144000); if (ret) { - dev_err_ratelimited(dev, "%d:Error during set_rx_data_size, cport:%d\n", - ret, data_cport); + dev_err_ratelimited(dai->dev, "%d: Error during set_config\n", + ret); + mutex_unlock(&codec->lock); return ret; } - if (codec_state < GBAUDIO_CODEC_PREPARE) { - ret = gb_audio_apbridgea_set_rx_data_size(data->connection, 0, - 192); - if (ret) { - dev_err_ratelimited(dev, - "%d:Error during apbridgea_set_rx_data_size\n", - ret); - return ret; - } - } - ret = gb_audio_gb_activate_rx(module->mgmt_connection, - data_cport); - if (ret) - dev_err_ratelimited(dev, "%s:Error during activate stream,%d\n", - module->name, ret); + codec->stream[substream->stream].state = GBAUDIO_CODEC_HWPARAMS; + codec->stream[substream->stream].format = format; + codec->stream[substream->stream].rate = rate; + codec->stream[substream->stream].channels = channels; + codec->stream[substream->stream].sig_bits = sig_bits; - return ret; + mutex_unlock(&codec->lock); + return 0; } static int gbcodec_prepare(struct snd_pcm_substream *substream, @@ -674,7 +444,6 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream, { int ret; struct gbaudio_module_info *module; - int state; struct gbaudio_data_connection *data; struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev); @@ -686,41 +455,38 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream, return -ENODEV; } - state = codec->stream[substream->stream].state; list_for_each_entry(module, &codec->module_list, list) { /* find the dai */ data = find_data(module, dai->name); - if (!data) { - dev_err(dai->dev, "%s:%s DATA connection missing\n", - dai->name, module->name); - continue; - } - - switch (substream->stream) { - case SNDRV_PCM_STREAM_PLAYBACK: - ret = gbmodule_prepare_tx(module, data, state, - dai->dev); - break; - case SNDRV_PCM_STREAM_CAPTURE: - ret = gbmodule_prepare_rx(module, data, state, - dai->dev); + if (data) break; - } - if (ret == -ENODEV) - continue; - if (ret) { - goto func_exit; - } + } + if (!data) { + dev_err(dai->dev, "DATA connection missing\n"); + mutex_unlock(&codec->lock); + return -ENODEV; + } - state = GBAUDIO_CODEC_PREPARE; - module->ctrlstate[substream->stream] = state; - dev_dbg(dai->dev, "%s: state:%d\n", module->name, state); + switch (substream->stream) { + case SNDRV_PCM_STREAM_PLAYBACK: + ret = gb_audio_apbridgea_set_tx_data_size(data->connection, 0, + 192); + break; + case SNDRV_PCM_STREAM_CAPTURE: + ret = gb_audio_apbridgea_set_rx_data_size(data->connection, 0, + 192); + break; + } + if (ret) { + mutex_unlock(&codec->lock); + dev_err_ratelimited(dai->dev, "set_data_size failed:%d\n", + ret); + return ret; } - codec->stream[substream->stream].state = state; -func_exit: + codec->stream[substream->stream].state = GBAUDIO_CODEC_PREPARE; mutex_unlock(&codec->lock); - return ret; + return 0; } static int gbcodec_mute_stream(struct snd_soc_dai *dai, int mute, int stream) -- cgit v0.10.2 From aaef32a6cc552d50b86fcf9c5b2105f08c048cdc Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Thu, 4 Aug 2016 15:14:30 +0530 Subject: greybus: audio: Split helper APIs based on stream direction Now, module is enabled/disabled based on widget event only and not during startup/shutdown callbacks. Thus, we needn't compare codec_state in enable/disable module helper APIs. Also, these can be further simplified based on stream direction. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 0bcd3d4..70b9a79 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -40,239 +40,296 @@ static int find_stream(const char *name) return stream; } -static int gbaudio_module_disable(struct gbaudio_codec_info *codec, - struct gbaudio_module_info *module, - int dir) +static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec, + struct gbaudio_module_info *module) { - int ret = 0; - uint16_t data_cport, cportid, i2s_port; - int codec_state, module_state; + int module_state, ret = 0; + uint16_t data_cport, i2s_port, cportid; + uint8_t sig_bits, channels; + uint32_t format, rate; struct gbaudio_data_connection *data; const char *dai_name; - mutex_lock(&codec->lock); + dai_name = codec->stream[SNDRV_PCM_STREAM_PLAYBACK].dai_name; + format = codec->stream[SNDRV_PCM_STREAM_PLAYBACK].format; + channels = codec->stream[SNDRV_PCM_STREAM_PLAYBACK].channels; + rate = codec->stream[SNDRV_PCM_STREAM_PLAYBACK].rate; + sig_bits = codec->stream[SNDRV_PCM_STREAM_PLAYBACK].sig_bits; - codec_state = codec->stream[dir].state; - if (codec_state == GBAUDIO_CODEC_SHUTDOWN) { - mutex_unlock(&codec->lock); - return 0; + module_state = module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK]; + + /* find the dai */ + data = find_data(module, dai_name); + if (!data) { + dev_err(module->dev, "%s:DATA connection missing\n", dai_name); + return -ENODEV; + } + + /* register cport */ + if (module_state < GBAUDIO_CODEC_STARTUP) { + i2s_port = 0; /* fixed for now */ + cportid = data->connection->hd_cport_id; + ret = gb_audio_apbridgea_register_cport(data->connection, + i2s_port, cportid, + AUDIO_APBRIDGEA_DIRECTION_TX); + if (ret) { + dev_err_ratelimited(module->dev, + "reg_cport failed:%d\n", ret); + return ret; + } + module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK] = + GBAUDIO_CODEC_STARTUP; + dev_dbg(module->dev, "Dynamic Register %s:%d DAI\n", dai_name, + cportid); + } + + /* hw_params */ + if (module_state < GBAUDIO_CODEC_HWPARAMS) { + data_cport = data->connection->intf_cport_id; + ret = gb_audio_gb_set_pcm(module->mgmt_connection, data_cport, + format, rate, channels, sig_bits); + if (ret) { + dev_err_ratelimited(module->dev, "set_pcm failed:%d\n", + ret); + return ret; + } + module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK] = + GBAUDIO_CODEC_HWPARAMS; + dev_dbg(module->dev, "Dynamic hw_params %s:%d DAI\n", dai_name, + data_cport); + } + + /* prepare */ + if (module_state < GBAUDIO_CODEC_PREPARE) { + data_cport = data->connection->intf_cport_id; + ret = gb_audio_gb_set_tx_data_size(module->mgmt_connection, + data_cport, 192); + if (ret) { + dev_err_ratelimited(module->dev, + "set_tx_data_size failed:%d\n", + ret); + return ret; + } + ret = gb_audio_gb_activate_tx(module->mgmt_connection, + data_cport); + if (ret) { + dev_err_ratelimited(module->dev, + "activate_tx failed:%d\n", ret); + return ret; + } + module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK] = + GBAUDIO_CODEC_PREPARE; + dev_dbg(module->dev, "Dynamic prepare %s:%d DAI\n", dai_name, + data_cport); } - dai_name = codec->stream[dir].dai_name; + return 0; +} + +static int gbaudio_module_disable_tx(struct gbaudio_codec_info *codec, + struct gbaudio_module_info *module) +{ + int ret; + uint16_t data_cport, cportid, i2s_port; + int module_state; + struct gbaudio_data_connection *data; + const char *dai_name; + + dai_name = codec->stream[SNDRV_PCM_STREAM_PLAYBACK].dai_name; + module_state = module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK]; - module_state = module->ctrlstate[dir]; if (module_state == GBAUDIO_CODEC_SHUTDOWN) { - dev_dbg(codec->dev, "%s: module already configured\n", - module->name); - mutex_unlock(&codec->lock); + dev_dbg(module->dev, "module already configured\n"); return 0; } /* find the dai */ data = find_data(module, dai_name); if (!data) { - dev_err(codec->dev, "%s:%s DATA connection missing\n", - dai_name, module->name); - mutex_unlock(&codec->lock); + dev_err(module->dev, "%s:DATA connection missing\n", dai_name); return -ENODEV; } - if (codec_state > GBAUDIO_CODEC_HWPARAMS) { + + if (module_state > GBAUDIO_CODEC_HWPARAMS) { data_cport = data->connection->intf_cport_id; - switch(dir) { - case SNDRV_PCM_STREAM_CAPTURE: - ret = gb_audio_gb_deactivate_rx( - module->mgmt_connection, - data_cport); - break; - case SNDRV_PCM_STREAM_PLAYBACK: - ret = gb_audio_gb_deactivate_tx( - module->mgmt_connection, + ret = gb_audio_gb_deactivate_tx(module->mgmt_connection, data_cport); - break; - default: - ret = -EINVAL; - } if (ret) { - dev_err_ratelimited(codec->dev, "deactivate for %s failed:%d\n", - module->name, ret); - goto func_exit; + dev_err_ratelimited(module->dev, + "deactivate_tx failed:%d\n", ret); + return ret; } - dev_dbg(codec->dev, "Dynamic deactivate %s:%d DAI\n", dai_name, + dev_dbg(module->dev, "Dynamic deactivate %s:%d DAI\n", dai_name, data_cport); + module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK] = + GBAUDIO_CODEC_HWPARAMS; } - if (codec_state > GBAUDIO_CODEC_SHUTDOWN) { + + if (module_state > GBAUDIO_CODEC_SHUTDOWN) { + i2s_port = 0; /* fixed for now */ cportid = data->connection->hd_cport_id; - switch(dir) { - case SNDRV_PCM_STREAM_CAPTURE: - ret = gb_audio_apbridgea_unregister_cport( - data->connection, - i2s_port, cportid, - AUDIO_APBRIDGEA_DIRECTION_RX); - break; - case SNDRV_PCM_STREAM_PLAYBACK: - ret = gb_audio_apbridgea_unregister_cport( - data->connection, + ret = gb_audio_apbridgea_unregister_cport(data->connection, i2s_port, cportid, AUDIO_APBRIDGEA_DIRECTION_TX); - break; - default: - ret = -EINVAL; - } if (ret) { - dev_err_ratelimited(codec->dev, "unregister_cport for %s failed:%d\n", - module->name, ret); - goto func_exit; + dev_err_ratelimited(module->dev, + "unregister_cport failed:%d\n", + ret); + return ret; } - dev_dbg(codec->dev, "Dynamic Unregister %s:%d DAI\n", dai_name, + dev_dbg(module->dev, "Dynamic Unregister %s:%d DAI\n", dai_name, cportid); + module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK] = + GBAUDIO_CODEC_SHUTDOWN; } - module->ctrlstate[dir] = GBAUDIO_CODEC_SHUTDOWN; -func_exit: - mutex_unlock(&codec->lock); - return ret; + return 0; } -static int gbaudio_module_enable(struct gbaudio_codec_info *codec, - struct gbaudio_module_info *module, int dir) +static int gbaudio_module_enable_rx(struct gbaudio_codec_info *codec, + struct gbaudio_module_info *module) { - int ret = 0; - __u16 i2s_port, cportid; - int codec_state, module_state; - uint16_t data_cport; + int module_state, ret = 0; + uint16_t data_cport, i2s_port, cportid; uint8_t sig_bits, channels; uint32_t format, rate; struct gbaudio_data_connection *data; const char *dai_name; - mutex_lock(&codec->lock); - - codec_state = codec->stream[dir].state; - if (codec_state == GBAUDIO_CODEC_SHUTDOWN) { - mutex_unlock(&codec->lock); - return 0; - } - - dai_name = codec->stream[dir].dai_name; - format = codec->stream[dir].format; - channels = codec->stream[dir].channels; - rate = codec->stream[dir].rate; - sig_bits = codec->stream[dir].sig_bits; - - module_state = module->ctrlstate[dir]; - if (module_state == codec_state) { - dev_dbg(codec->dev, "%s: module already configured\n", - module->name); - mutex_unlock(&codec->lock); - return 0; - } + dai_name = codec->stream[SNDRV_PCM_STREAM_CAPTURE].dai_name; + format = codec->stream[SNDRV_PCM_STREAM_CAPTURE].format; + channels = codec->stream[SNDRV_PCM_STREAM_CAPTURE].channels; + rate = codec->stream[SNDRV_PCM_STREAM_CAPTURE].rate; + sig_bits = codec->stream[SNDRV_PCM_STREAM_CAPTURE].sig_bits; + module_state = module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE]; /* find the dai */ data = find_data(module, dai_name); if (!data) { - dev_err(codec->dev, "%s:%s DATA connection missing\n", - dai_name, module->name); - mutex_unlock(&codec->lock); + dev_err(module->dev, "%s:DATA connection missing\n", dai_name); return -ENODEV; } /* register cport */ - if (module_state < codec_state) { + if (module_state < GBAUDIO_CODEC_STARTUP) { i2s_port = 0; /* fixed for now */ cportid = data->connection->hd_cport_id; - switch(dir) { - case SNDRV_PCM_STREAM_CAPTURE: - ret = gb_audio_apbridgea_register_cport( - data->connection, - i2s_port, cportid, - AUDIO_APBRIDGEA_DIRECTION_RX); - break; - case SNDRV_PCM_STREAM_PLAYBACK: - ret = gb_audio_apbridgea_register_cport( - data->connection, + ret = gb_audio_apbridgea_register_cport(data->connection, i2s_port, cportid, AUDIO_APBRIDGEA_DIRECTION_TX); - break; - default: - ret = -EINVAL; - } if (ret) { - dev_err_ratelimited(codec->dev, "reg_cport for %s\n", module->name); - goto func_exit; + dev_err_ratelimited(module->dev, + "reg_cport failed:%d\n", ret); + return ret; } - module_state = GBAUDIO_CODEC_STARTUP; - dev_dbg(codec->dev, "Dynamic Register %s:%d DAI\n", dai_name, + module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE] = + GBAUDIO_CODEC_STARTUP; + dev_dbg(module->dev, "Dynamic Register %s:%d DAI\n", dai_name, cportid); } /* hw_params */ - if (module_state < codec_state) { + if (module_state < GBAUDIO_CODEC_HWPARAMS) { data_cport = data->connection->intf_cport_id; ret = gb_audio_gb_set_pcm(module->mgmt_connection, data_cport, format, rate, channels, sig_bits); if (ret) { - dev_err_ratelimited(codec->dev, "set_pcm for %s\n", module->name); - goto func_exit; + dev_err_ratelimited(module->dev, "set_pcm failed:%d\n", + ret); + return ret; } - module_state = GBAUDIO_CODEC_HWPARAMS; - dev_dbg(codec->dev, "Dynamic hw_params %s:%d DAI\n", dai_name, + module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE] = + GBAUDIO_CODEC_HWPARAMS; + dev_dbg(module->dev, "Dynamic hw_params %s:%d DAI\n", dai_name, data_cport); } /* prepare */ - if (module_state < codec_state) { + if (module_state < GBAUDIO_CODEC_PREPARE) { data_cport = data->connection->intf_cport_id; - switch(dir) { - case SNDRV_PCM_STREAM_CAPTURE: - ret = gb_audio_gb_set_rx_data_size( - module->mgmt_connection, - data_cport, 192); - if (ret) { - dev_err_ratelimited(codec->dev, - "set_rx_data_size for %s\n", - module->name); - goto func_exit; - } - ret = gb_audio_gb_activate_rx(module->mgmt_connection, - data_cport); - if (ret) { - dev_err_ratelimited(codec->dev, "activate_rx for %s\n", - module->name); - goto func_exit; - } - break; - case SNDRV_PCM_STREAM_PLAYBACK: - ret = gb_audio_gb_set_tx_data_size( - module->mgmt_connection, - data_cport, 192); - if (ret) { - dev_err_ratelimited(codec->dev, - "set_tx_data_size for %s\n", - module->name); - goto func_exit; - } - ret = gb_audio_gb_activate_tx(module->mgmt_connection, - data_cport); - if (ret) { - dev_err_ratelimited(codec->dev, "activate_tx for %s\n", - module->name); - goto func_exit; - } - break; - default: - dev_err(codec->dev, "Inavlid stream direction\n"); - ret = -EINVAL; - goto func_exit; + ret = gb_audio_gb_set_rx_data_size(module->mgmt_connection, + data_cport, 192); + if (ret) { + dev_err_ratelimited(module->dev, + "set_rx_data_size failed:%d\n", + ret); + return ret; } - module_state = GBAUDIO_CODEC_PREPARE; - dev_dbg(codec->dev, "Dynamic prepare %s:%d DAI\n", dai_name, + ret = gb_audio_gb_activate_rx(module->mgmt_connection, + data_cport); + if (ret) { + dev_err_ratelimited(module->dev, + "activate_rx failed:%d\n", ret); + return ret; + } + module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE] = + GBAUDIO_CODEC_PREPARE; + dev_dbg(module->dev, "Dynamic prepare %s:%d DAI\n", dai_name, data_cport); } -func_exit: - module->ctrlstate[dir] = module_state; - mutex_unlock(&codec->lock); - return ret; + return 0; +} + +static int gbaudio_module_disable_rx(struct gbaudio_codec_info *codec, + struct gbaudio_module_info *module) +{ + int ret; + uint16_t data_cport, cportid, i2s_port; + int module_state; + struct gbaudio_data_connection *data; + const char *dai_name; + + dai_name = codec->stream[SNDRV_PCM_STREAM_CAPTURE].dai_name; + module_state = module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE]; + + if (module_state == GBAUDIO_CODEC_SHUTDOWN) { + dev_dbg(module->dev, "%s: module already configured\n", + module->name); + return 0; + } + + /* find the dai */ + data = find_data(module, dai_name); + if (!data) { + dev_err(module->dev, "%s:DATA connection missing\n", dai_name); + return -ENODEV; + } + + if (module_state > GBAUDIO_CODEC_HWPARAMS) { + data_cport = data->connection->intf_cport_id; + ret = gb_audio_gb_deactivate_rx(module->mgmt_connection, + data_cport); + if (ret) { + dev_err_ratelimited(module->dev, + "deactivate_rx failed:%d\n", ret); + return ret; + } + dev_dbg(module->dev, "Dynamic deactivate %s:%d DAI\n", dai_name, + data_cport); + module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE] = + GBAUDIO_CODEC_HWPARAMS; + } + + if (module_state > GBAUDIO_CODEC_SHUTDOWN) { + i2s_port = 0; /* fixed for now */ + cportid = data->connection->hd_cport_id; + ret = gb_audio_apbridgea_unregister_cport(data->connection, + i2s_port, cportid, + AUDIO_APBRIDGEA_DIRECTION_RX); + if (ret) { + dev_err_ratelimited(module->dev, + "unregister_cport failed:%d\n", + ret); + return ret; + } + dev_dbg(module->dev, "Dynamic Unregister %s:%d DAI\n", dai_name, + cportid); + module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE] = + GBAUDIO_CODEC_SHUTDOWN; + } + + return 0; } int gbaudio_module_update(struct gbaudio_codec_info *codec, @@ -280,9 +337,8 @@ int gbaudio_module_update(struct gbaudio_codec_info *codec, struct gbaudio_module_info *module, int enable) { int stream, ret = 0; - int pb_state, cap_state; - dev_dbg(module->dev, "Module update %s sequence\n", + dev_dbg(module->dev, "%s:Module update %s sequence\n", w_name, enable ? "Enable":"Disable"); stream = find_stream(w_name); @@ -291,27 +347,22 @@ int gbaudio_module_update(struct gbaudio_codec_info *codec, return 0; } - /* check if playback active */ - pb_state = codec->stream[SNDRV_PCM_STREAM_PLAYBACK].state; - if ((stream & GB_PLAYBACK) && (pb_state > GBAUDIO_CODEC_SHUTDOWN)) { + mutex_lock(&codec->lock); + if (stream & GB_PLAYBACK) { if (enable) - ret = gbaudio_module_enable(codec, module, - SNDRV_PCM_STREAM_PLAYBACK); + ret = gbaudio_module_enable_tx(codec, module); else - ret = gbaudio_module_disable(codec, module, - SNDRV_PCM_STREAM_PLAYBACK); + ret = gbaudio_module_disable_tx(codec, module); } /* check if capture active */ - cap_state = codec->stream[SNDRV_PCM_STREAM_CAPTURE].state; - if ((stream & GB_CAPTURE) && (cap_state > GBAUDIO_CODEC_SHUTDOWN)) { + if (stream & GB_CAPTURE) { if (enable) - ret = gbaudio_module_enable(codec, module, - SNDRV_PCM_STREAM_CAPTURE); + ret = gbaudio_module_enable_rx(codec, module); else - ret = gbaudio_module_disable(codec, module, - SNDRV_PCM_STREAM_CAPTURE); + ret = gbaudio_module_disable_rx(codec, module); } + mutex_unlock(&codec->lock); return ret; } -- cgit v0.10.2 From 1568159868f6b6c4ab17aa28ef4d5d4fc02317f1 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Thu, 4 Aug 2016 15:14:31 +0530 Subject: greybus: audio: Update dai_driver table with appropriate fields Currently, the stream name for the DAI driver is generically set to "GB Audio Playback" and "GB Audio Capture". This is OK since we use a single interface on APB1 but that could change in the future. Update the DAI driver table entries to properly reflect the interface used. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 70b9a79..a6f8437 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -950,10 +950,10 @@ static unsigned int gbcodec_read(struct snd_soc_codec *codec, static struct snd_soc_dai_driver gbaudio_dai[] = { { - .name = "greybus-apb1", + .name = "apb-i2s0", .id = 0, .playback = { - .stream_name = "GB Audio Playback", + .stream_name = "I2S 0 Playback", .rates = SNDRV_PCM_RATE_48000, .formats = SNDRV_PCM_FORMAT_S16_LE, .rate_max = 48000, @@ -962,7 +962,7 @@ static struct snd_soc_dai_driver gbaudio_dai[] = { .channels_max = 2, }, .capture = { - .stream_name = "GB Audio Capture", + .stream_name = "I2S 0 Capture", .rates = SNDRV_PCM_RATE_48000, .formats = SNDRV_PCM_FORMAT_S16_LE, .rate_max = 48000, -- cgit v0.10.2 From 4ffca62a051c3e1722bcaf6a367b419e6e5e40e0 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Thu, 4 Aug 2016 15:14:32 +0530 Subject: greybus: audio: Update parameters for gbaudio_module_update API Earlier, module path was enabled based on module's control switch e.g. 'SPK Amp switch'. Thus widget's name was sufficient to parse and identify the direction. Now individual modules' path will be enabled based on AIF widget status. So, it is required to get complete widget details, say w->type is used to identify direction (playback/capture) and w->sname is used to identify module's DATA connection used for communication via greybus. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index a6f8437..e2a0c163 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -333,10 +333,11 @@ static int gbaudio_module_disable_rx(struct gbaudio_codec_info *codec, } int gbaudio_module_update(struct gbaudio_codec_info *codec, - const char *w_name, - struct gbaudio_module_info *module, int enable) + struct snd_soc_dapm_widget *w, + struct gbaudio_module_info *module, int enable) { int stream, ret = 0; + const char *w_name = w->name; dev_dbg(module->dev, "%s:Module update %s sequence\n", w_name, enable ? "Enable":"Disable"); diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index 1646b2c..c5a8808 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -206,9 +206,9 @@ int gbaudio_tplg_parse_data(struct gbaudio_module_info *module, void gbaudio_tplg_release(struct gbaudio_module_info *module); int gbaudio_module_update(struct gbaudio_codec_info *codec, - const char *w_name, - struct gbaudio_module_info *module, - int enable); + struct snd_soc_dapm_widget *w, + struct gbaudio_module_info *module, + int enable); int gbaudio_register_module(struct gbaudio_module_info *module); void gbaudio_unregister_module(struct gbaudio_module_info *module); diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index 3c7c786..9375296 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -960,14 +960,12 @@ static int gbaudio_widget_event(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_PRE_PMU: ret = gb_audio_gb_enable_widget(module->mgmt_connection, wid); if (!ret) - ret = gbaudio_module_update(gbcodec, w->name, module, - 1); + ret = gbaudio_module_update(gbcodec, w, module, 1); break; case SND_SOC_DAPM_POST_PMD: ret = gb_audio_gb_disable_widget(module->mgmt_connection, wid); if (!ret) - ret = gbaudio_module_update(gbcodec, w->name, module, - 0); + ret = gbaudio_module_update(gbcodec, w, module, 0); break; } if (ret) -- cgit v0.10.2 From 487dcbd6ba46548f8f24dbd75423785ec8153712 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Thu, 4 Aug 2016 15:14:33 +0530 Subject: greybus: audio: Use AIF widget to enable path between module & APB Currently, SPK Amp switch is used to identify when to enable data path between module and APB. With headset, other switch controls added, it is not possible to use this switch to control data path. Instead path should be established based on AIF widget. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index e2a0c163..3067c1a 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -30,16 +30,6 @@ find_data(struct gbaudio_module_info *module, const char *name) return NULL; } -static int find_stream(const char *name) -{ - int stream = 0; - - if (strnstr(name, "SPK Amp", NAME_SIZE)) - stream |= GB_PLAYBACK; - - return stream; -} - static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec, struct gbaudio_module_info *module) { @@ -336,33 +326,30 @@ int gbaudio_module_update(struct gbaudio_codec_info *codec, struct snd_soc_dapm_widget *w, struct gbaudio_module_info *module, int enable) { - int stream, ret = 0; + int ret = 0; const char *w_name = w->name; dev_dbg(module->dev, "%s:Module update %s sequence\n", w_name, enable ? "Enable":"Disable"); - stream = find_stream(w_name); - if (!stream) { + if ((w->id != snd_soc_dapm_aif_in) && (w->id != snd_soc_dapm_aif_out)){ dev_dbg(codec->dev, "No action required for %s\n", w_name); return 0; } mutex_lock(&codec->lock); - if (stream & GB_PLAYBACK) { + if (w->id == snd_soc_dapm_aif_in) { if (enable) ret = gbaudio_module_enable_tx(codec, module); else ret = gbaudio_module_disable_tx(codec, module); - } - - /* check if capture active */ - if (stream & GB_CAPTURE) { + } else if (w->id == snd_soc_dapm_aif_out) { if (enable) ret = gbaudio_module_enable_rx(codec, module); else ret = gbaudio_module_disable_rx(codec, module); } + mutex_unlock(&codec->lock); return ret; -- cgit v0.10.2 From b7e7dc0083d662c061dcd547c7dde4db24331ebc Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Thu, 4 Aug 2016 15:14:34 +0530 Subject: greybus: audio: Add id to identify data connection Added id field to data connection struct. This is used to identify which data connection to use while enabling interface between module & APB. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index c5a8808..8cd5bd7 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -129,6 +129,7 @@ struct gbaudio_control { }; struct gbaudio_data_connection { + int id; __le16 data_cport; int cport_configured; char name[NAME_SIZE]; diff --git a/drivers/staging/greybus/audio_module.c b/drivers/staging/greybus/audio_module.c index 7cf523e..9632bc1 100644 --- a/drivers/staging/greybus/audio_module.c +++ b/drivers/staging/greybus/audio_module.c @@ -199,6 +199,7 @@ static int gb_audio_add_data_connection(struct gbaudio_module_info *gbmodule, greybus_set_drvdata(bundle, gbmodule); /* dai->name should be same as codec->dai_name */ strlcpy(dai->name, "greybus-apb1", NAME_SIZE); + dai->id = 0; dai->data_cport = connection->intf_cport_id; dai->connection = connection; list_add(&dai->list, &gbmodule->data_list); -- cgit v0.10.2 From 60e7327d54b270eeadc120b6202af50856548376 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Thu, 4 Aug 2016 15:14:35 +0530 Subject: greybus: audio: Find data connection based on id Currently we are using dai->name to identify data connection from list for a module. Now since we are enabling data path based on widget, dai->name might be invalid by the time driver receives disable request for a widget. So, use id fetched from AIF widget->sname to identify data connection for a module. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 3067c1a..b64aca5 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -19,19 +19,19 @@ static struct gbaudio_codec_info *gbcodec; static struct gbaudio_data_connection * -find_data(struct gbaudio_module_info *module, const char *name) +find_data(struct gbaudio_module_info *module, int id) { struct gbaudio_data_connection *data; list_for_each_entry(data, &module->data_list, list) { - if (name && !strncmp(data->name, name, NAME_SIZE)) + if (id == data->id) return data; } return NULL; } static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec, - struct gbaudio_module_info *module) + struct gbaudio_module_info *module, int id) { int module_state, ret = 0; uint16_t data_cport, i2s_port, cportid; @@ -49,9 +49,9 @@ static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec, module_state = module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK]; /* find the dai */ - data = find_data(module, dai_name); + data = find_data(module, id); if (!data) { - dev_err(module->dev, "%s:DATA connection missing\n", dai_name); + dev_err(module->dev, "%d:DATA connection missing\n", id); return -ENODEV; } @@ -116,16 +116,13 @@ static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec, return 0; } -static int gbaudio_module_disable_tx(struct gbaudio_codec_info *codec, - struct gbaudio_module_info *module) +static int gbaudio_module_disable_tx(struct gbaudio_module_info *module, int id) { int ret; uint16_t data_cport, cportid, i2s_port; int module_state; struct gbaudio_data_connection *data; - const char *dai_name; - dai_name = codec->stream[SNDRV_PCM_STREAM_PLAYBACK].dai_name; module_state = module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK]; if (module_state == GBAUDIO_CODEC_SHUTDOWN) { @@ -134,9 +131,9 @@ static int gbaudio_module_disable_tx(struct gbaudio_codec_info *codec, } /* find the dai */ - data = find_data(module, dai_name); + data = find_data(module, id); if (!data) { - dev_err(module->dev, "%s:DATA connection missing\n", dai_name); + dev_err(module->dev, "%d:DATA connection missing\n", id); return -ENODEV; } @@ -149,8 +146,7 @@ static int gbaudio_module_disable_tx(struct gbaudio_codec_info *codec, "deactivate_tx failed:%d\n", ret); return ret; } - dev_dbg(module->dev, "Dynamic deactivate %s:%d DAI\n", dai_name, - data_cport); + dev_dbg(module->dev, "Dynamic deactivate %d DAI\n", data_cport); module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK] = GBAUDIO_CODEC_HWPARAMS; } @@ -167,8 +163,7 @@ static int gbaudio_module_disable_tx(struct gbaudio_codec_info *codec, ret); return ret; } - dev_dbg(module->dev, "Dynamic Unregister %s:%d DAI\n", dai_name, - cportid); + dev_dbg(module->dev, "Dynamic Unregister %d DAI\n", cportid); module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK] = GBAUDIO_CODEC_SHUTDOWN; } @@ -177,7 +172,7 @@ static int gbaudio_module_disable_tx(struct gbaudio_codec_info *codec, } static int gbaudio_module_enable_rx(struct gbaudio_codec_info *codec, - struct gbaudio_module_info *module) + struct gbaudio_module_info *module, int id) { int module_state, ret = 0; uint16_t data_cport, i2s_port, cportid; @@ -194,9 +189,9 @@ static int gbaudio_module_enable_rx(struct gbaudio_codec_info *codec, module_state = module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE]; /* find the dai */ - data = find_data(module, dai_name); + data = find_data(module, id); if (!data) { - dev_err(module->dev, "%s:DATA connection missing\n", dai_name); + dev_err(module->dev, "%d:DATA connection missing\n", id); return -ENODEV; } @@ -261,16 +256,13 @@ static int gbaudio_module_enable_rx(struct gbaudio_codec_info *codec, return 0; } -static int gbaudio_module_disable_rx(struct gbaudio_codec_info *codec, - struct gbaudio_module_info *module) +static int gbaudio_module_disable_rx(struct gbaudio_module_info *module, int id) { int ret; uint16_t data_cport, cportid, i2s_port; int module_state; struct gbaudio_data_connection *data; - const char *dai_name; - dai_name = codec->stream[SNDRV_PCM_STREAM_CAPTURE].dai_name; module_state = module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE]; if (module_state == GBAUDIO_CODEC_SHUTDOWN) { @@ -280,9 +272,9 @@ static int gbaudio_module_disable_rx(struct gbaudio_codec_info *codec, } /* find the dai */ - data = find_data(module, dai_name); + data = find_data(module, id); if (!data) { - dev_err(module->dev, "%s:DATA connection missing\n", dai_name); + dev_err(module->dev, "%d:DATA connection missing\n", id); return -ENODEV; } @@ -295,8 +287,7 @@ static int gbaudio_module_disable_rx(struct gbaudio_codec_info *codec, "deactivate_rx failed:%d\n", ret); return ret; } - dev_dbg(module->dev, "Dynamic deactivate %s:%d DAI\n", dai_name, - data_cport); + dev_dbg(module->dev, "Dynamic deactivate %d DAI\n", data_cport); module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE] = GBAUDIO_CODEC_HWPARAMS; } @@ -313,8 +304,7 @@ static int gbaudio_module_disable_rx(struct gbaudio_codec_info *codec, ret); return ret; } - dev_dbg(module->dev, "Dynamic Unregister %s:%d DAI\n", dai_name, - cportid); + dev_dbg(module->dev, "Dynamic Unregister %d DAI\n", cportid); module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE] = GBAUDIO_CODEC_SHUTDOWN; } @@ -326,28 +316,36 @@ int gbaudio_module_update(struct gbaudio_codec_info *codec, struct snd_soc_dapm_widget *w, struct gbaudio_module_info *module, int enable) { - int ret = 0; - const char *w_name = w->name; + int dai_id, ret; + char intf_name[NAME_SIZE], dir[NAME_SIZE]; - dev_dbg(module->dev, "%s:Module update %s sequence\n", w_name, + dev_dbg(module->dev, "%s:Module update %s sequence\n", w->name, enable ? "Enable":"Disable"); if ((w->id != snd_soc_dapm_aif_in) && (w->id != snd_soc_dapm_aif_out)){ - dev_dbg(codec->dev, "No action required for %s\n", w_name); + dev_dbg(codec->dev, "No action required for %s\n", w->name); return 0; } + /* parse dai_id from AIF widget's stream_name */ + ret = sscanf(w->sname, "%s %d %s", intf_name, &dai_id, dir); + if (ret < 3) { + dev_err(codec->dev, "Error while parsing dai_id for %s\n", + w->name); + return -EINVAL; + } + mutex_lock(&codec->lock); if (w->id == snd_soc_dapm_aif_in) { if (enable) - ret = gbaudio_module_enable_tx(codec, module); + ret = gbaudio_module_enable_tx(codec, module, dai_id); else - ret = gbaudio_module_disable_tx(codec, module); + ret = gbaudio_module_disable_tx(module, dai_id); } else if (w->id == snd_soc_dapm_aif_out) { if (enable) - ret = gbaudio_module_enable_rx(codec, module); + ret = gbaudio_module_enable_rx(codec, module, dai_id); else - ret = gbaudio_module_disable_rx(codec, module); + ret = gbaudio_module_disable_rx(module, dai_id); } mutex_unlock(&codec->lock); @@ -447,7 +445,7 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream, /* find the data connection */ list_for_each_entry(module, &codec->module_list, list) { - data = find_data(module, dai->name); + data = find_data(module, dai->id); if (data) break; } @@ -496,7 +494,7 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream, list_for_each_entry(module, &codec->module_list, list) { /* find the dai */ - data = find_data(module, dai->name); + data = find_data(module, dai->id); if (data) break; } @@ -554,7 +552,7 @@ static int gbcodec_mute_stream(struct snd_soc_dai *dai, int mute, int stream) list_for_each_entry(module, &codec->module_list, list) { /* find the dai */ - data = find_data(module, dai->name); + data = find_data(module, dai->id); if (data) break; } @@ -764,7 +762,7 @@ static void gbaudio_codec_cleanup(struct gbaudio_module_info *module) dev_dbg(gbcodec->dev, "%s: removed, cleanup APBridge\n", module->name); if (pb_state == GBAUDIO_CODEC_START) { /* cleanup PB path, only APBridge specific */ - data = find_data(module, gbcodec->stream[0].dai_name); + data = find_data(module, 1); if (!data) { dev_err(gbcodec->dev, "%s: Missing data pointer\n", __func__); @@ -790,7 +788,7 @@ static void gbaudio_codec_cleanup(struct gbaudio_module_info *module) if (cap_state == GBAUDIO_CODEC_START) { /* cleanup CAP path, only APBridge specific */ - data = find_data(module, gbcodec->stream[1].dai_name); + data = find_data(module, 1); if (!data) { dev_err(gbcodec->dev, "%s: Missing data pointer\n", __func__); -- cgit v0.10.2 From 956adf749d697decd9fb5f46aa0fbbc889f4dfe1 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Thu, 4 Aug 2016 15:14:36 +0530 Subject: greybus: Remove unused field from data_connection Audio codec driver internally maintains a struct containing info about module's data connection. Remove unused field from this struct. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index 8cd5bd7..7a2dbc5 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -131,8 +131,6 @@ struct gbaudio_control { struct gbaudio_data_connection { int id; __le16 data_cport; - int cport_configured; - char name[NAME_SIZE]; struct gb_connection *connection; struct list_head list; }; diff --git a/drivers/staging/greybus/audio_module.c b/drivers/staging/greybus/audio_module.c index 9632bc1..c217271 100644 --- a/drivers/staging/greybus/audio_module.c +++ b/drivers/staging/greybus/audio_module.c @@ -197,8 +197,6 @@ static int gb_audio_add_data_connection(struct gbaudio_module_info *gbmodule, } greybus_set_drvdata(bundle, gbmodule); - /* dai->name should be same as codec->dai_name */ - strlcpy(dai->name, "greybus-apb1", NAME_SIZE); dai->id = 0; dai->data_cport = connection->intf_cport_id; dai->connection = connection; -- cgit v0.10.2 From c388ae769699262bd48da1d529bbed731c2de559 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Thu, 4 Aug 2016 15:14:37 +0530 Subject: greybus: audio: Update pm runtime support in dai_ops callback Ensure pm runtime get_sync/put protection in codec_dai ops callback functions before accessing apbridge. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index b64aca5..9f050bd 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -405,6 +405,7 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream, uint32_t format, rate; struct gbaudio_module_info *module; struct gbaudio_data_connection *data; + struct gb_bundle *bundle; struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev); mutex_lock(&codec->lock); @@ -456,6 +457,13 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } + bundle = to_gb_bundle(module->dev); + ret = gb_pm_runtime_get_sync(bundle); + if (ret) { + mutex_unlock(&codec->lock); + return ret; + } + ret = gb_audio_apbridgea_set_config(data->connection, 0, AUDIO_APBRIDGEA_PCM_FMT_16, AUDIO_APBRIDGEA_PCM_RATE_48000, @@ -466,6 +474,9 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream, mutex_unlock(&codec->lock); return ret; } + + gb_pm_runtime_put_noidle(bundle); + codec->stream[substream->stream].state = GBAUDIO_CODEC_HWPARAMS; codec->stream[substream->stream].format = format; codec->stream[substream->stream].rate = rate; @@ -482,6 +493,7 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream, int ret; struct gbaudio_module_info *module; struct gbaudio_data_connection *data; + struct gb_bundle *bundle; struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev); mutex_lock(&codec->lock); @@ -504,6 +516,13 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream, return -ENODEV; } + bundle = to_gb_bundle(module->dev); + ret = gb_pm_runtime_get_sync(bundle); + if (ret) { + mutex_unlock(&codec->lock); + return ret; + } + switch (substream->stream) { case SNDRV_PCM_STREAM_PLAYBACK: ret = gb_audio_apbridgea_set_tx_data_size(data->connection, 0, @@ -521,6 +540,8 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream, return ret; } + gb_pm_runtime_put_noidle(bundle); + codec->stream[substream->stream].state = GBAUDIO_CODEC_PREPARE; mutex_unlock(&codec->lock); return 0; @@ -531,6 +552,7 @@ static int gbcodec_mute_stream(struct snd_soc_dai *dai, int mute, int stream) int ret; struct gbaudio_data_connection *data; struct gbaudio_module_info *module; + struct gb_bundle *bundle; struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev); @@ -563,6 +585,13 @@ static int gbcodec_mute_stream(struct snd_soc_dai *dai, int mute, int stream) return -ENODEV; } + bundle = to_gb_bundle(module->dev); + ret = gb_pm_runtime_get_sync(bundle); + if (ret) { + mutex_unlock(&codec->lock); + return ret; + } + if (!mute && !stream) {/* start playback */ ret = gb_audio_apbridgea_prepare_tx(data->connection, 0); @@ -597,6 +626,7 @@ static int gbcodec_mute_stream(struct snd_soc_dai *dai, int mute, int stream) module->name, mute ? "Mute" : "Unmute", stream ? "Capture" : "Playback", ret); + gb_pm_runtime_put_noidle(bundle); mutex_unlock(&codec->lock); return ret; } -- cgit v0.10.2 From 19866603be2ad58735f82511f3d5f680e61479ea Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Thu, 4 Aug 2016 15:14:38 +0530 Subject: greybus: audio: Maintain runtime stream params for each DAI Runtime streams are required while configuring GB module plugged-in during active stream. Currently, it is maintained for single stream. However, this should be maintained for a stream corresponding to each DAI. Fix this! Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 9f050bd..e1ad685 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -30,6 +30,18 @@ find_data(struct gbaudio_module_info *module, int id) return NULL; } +static struct gbaudio_stream_params * +find_dai_stream_params(struct gbaudio_codec_info *codec, int id, int stream) +{ + struct gbaudio_codec_dai *dai; + + list_for_each_entry(dai, &codec->dai_list, list) { + if (dai->id == id) + return &dai->params[stream]; + } + return NULL; +} + static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec, struct gbaudio_module_info *module, int id) { @@ -38,13 +50,7 @@ static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec, uint8_t sig_bits, channels; uint32_t format, rate; struct gbaudio_data_connection *data; - const char *dai_name; - - dai_name = codec->stream[SNDRV_PCM_STREAM_PLAYBACK].dai_name; - format = codec->stream[SNDRV_PCM_STREAM_PLAYBACK].format; - channels = codec->stream[SNDRV_PCM_STREAM_PLAYBACK].channels; - rate = codec->stream[SNDRV_PCM_STREAM_PLAYBACK].rate; - sig_bits = codec->stream[SNDRV_PCM_STREAM_PLAYBACK].sig_bits; + struct gbaudio_stream_params *params; module_state = module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK]; @@ -55,6 +61,12 @@ static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec, return -ENODEV; } + params = find_dai_stream_params(codec, id, SNDRV_PCM_STREAM_PLAYBACK); + if (!params) { + dev_err(codec->dev, "Failed to fetch dai_stream pointer\n"); + return -EINVAL; + } + /* register cport */ if (module_state < GBAUDIO_CODEC_STARTUP) { i2s_port = 0; /* fixed for now */ @@ -69,12 +81,15 @@ static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec, } module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK] = GBAUDIO_CODEC_STARTUP; - dev_dbg(module->dev, "Dynamic Register %s:%d DAI\n", dai_name, - cportid); + dev_dbg(module->dev, "Dynamic Register %d DAI\n", cportid); } /* hw_params */ if (module_state < GBAUDIO_CODEC_HWPARAMS) { + format = params->format; + channels = params->channels; + rate = params->rate; + sig_bits = params->sig_bits; data_cport = data->connection->intf_cport_id; ret = gb_audio_gb_set_pcm(module->mgmt_connection, data_cport, format, rate, channels, sig_bits); @@ -85,8 +100,7 @@ static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec, } module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK] = GBAUDIO_CODEC_HWPARAMS; - dev_dbg(module->dev, "Dynamic hw_params %s:%d DAI\n", dai_name, - data_cport); + dev_dbg(module->dev, "Dynamic hw_params %d DAI\n", data_cport); } /* prepare */ @@ -109,8 +123,7 @@ static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec, } module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK] = GBAUDIO_CODEC_PREPARE; - dev_dbg(module->dev, "Dynamic prepare %s:%d DAI\n", dai_name, - data_cport); + dev_dbg(module->dev, "Dynamic prepare %d DAI\n", data_cport); } return 0; @@ -179,13 +192,8 @@ static int gbaudio_module_enable_rx(struct gbaudio_codec_info *codec, uint8_t sig_bits, channels; uint32_t format, rate; struct gbaudio_data_connection *data; - const char *dai_name; + struct gbaudio_stream_params *params; - dai_name = codec->stream[SNDRV_PCM_STREAM_CAPTURE].dai_name; - format = codec->stream[SNDRV_PCM_STREAM_CAPTURE].format; - channels = codec->stream[SNDRV_PCM_STREAM_CAPTURE].channels; - rate = codec->stream[SNDRV_PCM_STREAM_CAPTURE].rate; - sig_bits = codec->stream[SNDRV_PCM_STREAM_CAPTURE].sig_bits; module_state = module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE]; /* find the dai */ @@ -195,6 +203,12 @@ static int gbaudio_module_enable_rx(struct gbaudio_codec_info *codec, return -ENODEV; } + params = find_dai_stream_params(codec, id, SNDRV_PCM_STREAM_CAPTURE); + if (!params) { + dev_err(codec->dev, "Failed to fetch dai_stream pointer\n"); + return -EINVAL; + } + /* register cport */ if (module_state < GBAUDIO_CODEC_STARTUP) { i2s_port = 0; /* fixed for now */ @@ -209,12 +223,15 @@ static int gbaudio_module_enable_rx(struct gbaudio_codec_info *codec, } module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE] = GBAUDIO_CODEC_STARTUP; - dev_dbg(module->dev, "Dynamic Register %s:%d DAI\n", dai_name, - cportid); + dev_dbg(module->dev, "Dynamic Register %d DAI\n", cportid); } /* hw_params */ if (module_state < GBAUDIO_CODEC_HWPARAMS) { + format = params->format; + channels = params->channels; + rate = params->rate; + sig_bits = params->sig_bits; data_cport = data->connection->intf_cport_id; ret = gb_audio_gb_set_pcm(module->mgmt_connection, data_cport, format, rate, channels, sig_bits); @@ -225,8 +242,7 @@ static int gbaudio_module_enable_rx(struct gbaudio_codec_info *codec, } module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE] = GBAUDIO_CODEC_HWPARAMS; - dev_dbg(module->dev, "Dynamic hw_params %s:%d DAI\n", dai_name, - data_cport); + dev_dbg(module->dev, "Dynamic hw_params %d DAI\n", data_cport); } /* prepare */ @@ -249,8 +265,7 @@ static int gbaudio_module_enable_rx(struct gbaudio_codec_info *codec, } module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE] = GBAUDIO_CODEC_PREPARE; - dev_dbg(module->dev, "Dynamic prepare %s:%d DAI\n", dai_name, - data_cport); + dev_dbg(module->dev, "Dynamic prepare %d DAI\n", data_cport); } return 0; @@ -361,6 +376,7 @@ static int gbcodec_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev); + struct gbaudio_stream_params *params; mutex_lock(&codec->lock); @@ -370,8 +386,13 @@ static int gbcodec_startup(struct snd_pcm_substream *substream, return -ENODEV; } - codec->stream[substream->stream].state = GBAUDIO_CODEC_STARTUP; - codec->stream[substream->stream].dai_name = dai->name; + params = find_dai_stream_params(codec, dai->id, substream->stream); + if (!params) { + dev_err(codec->dev, "Failed to fetch dai_stream pointer\n"); + mutex_unlock(&codec->lock); + return -EINVAL; + } + params->state = GBAUDIO_CODEC_STARTUP; mutex_unlock(&codec->lock); /* to prevent suspend in case of active audio */ pm_stay_awake(dai->dev); @@ -383,14 +404,20 @@ static void gbcodec_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev); + struct gbaudio_stream_params *params; mutex_lock(&codec->lock); if (list_empty(&codec->module_list)) dev_info(codec->dev, "No codec module available during shutdown\n"); - codec->stream[substream->stream].state = GBAUDIO_CODEC_SHUTDOWN; - codec->stream[substream->stream].dai_name = NULL; + params = find_dai_stream_params(codec, dai->id, substream->stream); + if (!params) { + dev_err(codec->dev, "Failed to fetch dai_stream pointer\n"); + mutex_unlock(&codec->lock); + return; + } + params->state = GBAUDIO_CODEC_SHUTDOWN; mutex_unlock(&codec->lock); pm_relax(dai->dev); return; @@ -407,6 +434,7 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream, struct gbaudio_data_connection *data; struct gb_bundle *bundle; struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev); + struct gbaudio_stream_params *params; mutex_lock(&codec->lock); @@ -457,6 +485,13 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } + params = find_dai_stream_params(codec, dai->id, substream->stream); + if (!params) { + dev_err(codec->dev, "Failed to fetch dai_stream pointer\n"); + mutex_unlock(&codec->lock); + return -EINVAL; + } + bundle = to_gb_bundle(module->dev); ret = gb_pm_runtime_get_sync(bundle); if (ret) { @@ -477,11 +512,11 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream, gb_pm_runtime_put_noidle(bundle); - codec->stream[substream->stream].state = GBAUDIO_CODEC_HWPARAMS; - codec->stream[substream->stream].format = format; - codec->stream[substream->stream].rate = rate; - codec->stream[substream->stream].channels = channels; - codec->stream[substream->stream].sig_bits = sig_bits; + params->state = GBAUDIO_CODEC_HWPARAMS; + params->format = format; + params->rate = rate; + params->channels = channels; + params->sig_bits = sig_bits; mutex_unlock(&codec->lock); return 0; @@ -495,6 +530,7 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream, struct gbaudio_data_connection *data; struct gb_bundle *bundle; struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev); + struct gbaudio_stream_params *params; mutex_lock(&codec->lock); @@ -516,6 +552,13 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream, return -ENODEV; } + params = find_dai_stream_params(codec, dai->id, substream->stream); + if (!params) { + dev_err(codec->dev, "Failed to fetch dai_stream pointer\n"); + mutex_unlock(&codec->lock); + return -EINVAL; + } + bundle = to_gb_bundle(module->dev); ret = gb_pm_runtime_get_sync(bundle); if (ret) { @@ -542,7 +585,7 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream, gb_pm_runtime_put_noidle(bundle); - codec->stream[substream->stream].state = GBAUDIO_CODEC_PREPARE; + params->state = GBAUDIO_CODEC_PREPARE; mutex_unlock(&codec->lock); return 0; } @@ -554,16 +597,25 @@ static int gbcodec_mute_stream(struct snd_soc_dai *dai, int mute, int stream) struct gbaudio_module_info *module; struct gb_bundle *bundle; struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev); + struct gbaudio_stream_params *params; dev_dbg(dai->dev, "Mute:%d, Direction:%s\n", mute, stream ? "CAPTURE":"PLAYBACK"); mutex_lock(&codec->lock); + + params = find_dai_stream_params(codec, dai->id, stream); + if (!params) { + dev_err(codec->dev, "Failed to fetch dai_stream pointer\n"); + mutex_unlock(&codec->lock); + return -EINVAL; + } + if (list_empty(&codec->module_list)) { dev_err(codec->dev, "No codec module available\n"); if (mute) { - codec->stream[stream].state = GBAUDIO_CODEC_STOP; + params->state = GBAUDIO_CODEC_STOP; ret = 0; } else { ret = -ENODEV; @@ -598,26 +650,26 @@ static int gbcodec_mute_stream(struct snd_soc_dai *dai, int mute, int stream) if (!ret) ret = gb_audio_apbridgea_start_tx(data->connection, 0, 0); - codec->stream[stream].state = GBAUDIO_CODEC_START; + params->state = GBAUDIO_CODEC_START; } else if (!mute && stream) {/* start capture */ ret = gb_audio_apbridgea_prepare_rx(data->connection, 0); if (!ret) ret = gb_audio_apbridgea_start_rx(data->connection, 0); - codec->stream[stream].state = GBAUDIO_CODEC_START; + params->state = GBAUDIO_CODEC_START; } else if (mute && !stream) {/* stop playback */ ret = gb_audio_apbridgea_stop_tx(data->connection, 0); if (!ret) ret = gb_audio_apbridgea_shutdown_tx(data->connection, 0); - codec->stream[stream].state = GBAUDIO_CODEC_STOP; + params->state = GBAUDIO_CODEC_STOP; } else if (mute && stream) {/* stop capture */ ret = gb_audio_apbridgea_stop_rx(data->connection, 0); if (!ret) ret = gb_audio_apbridgea_shutdown_rx(data->connection, 0); - codec->stream[stream].state = GBAUDIO_CODEC_STOP; + params->state = GBAUDIO_CODEC_STOP; } else ret = -EINVAL; if (ret) @@ -639,6 +691,32 @@ static struct snd_soc_dai_ops gbcodec_dai_ops = { .mute_stream = gbcodec_mute_stream, }; +static struct snd_soc_dai_driver gbaudio_dai[] = { + { + .name = "apb-i2s0", + .id = 0, + .playback = { + .stream_name = "I2S 0 Playback", + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FORMAT_S16_LE, + .rate_max = 48000, + .rate_min = 48000, + .channels_min = 1, + .channels_max = 2, + }, + .capture = { + .stream_name = "I2S 0 Capture", + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FORMAT_S16_LE, + .rate_max = 48000, + .rate_min = 48000, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &gbcodec_dai_ops, + }, +}; + static int gbaudio_init_jack(struct gbaudio_module_info *module, struct snd_soc_codec *codec) { @@ -898,7 +976,9 @@ EXPORT_SYMBOL(gbaudio_unregister_module); */ static int gbcodec_probe(struct snd_soc_codec *codec) { + int i; struct gbaudio_codec_info *info; + struct gbaudio_codec_dai *dai; info = devm_kzalloc(codec->dev, sizeof(*info), GFP_KERNEL); if (!info) @@ -907,6 +987,17 @@ static int gbcodec_probe(struct snd_soc_codec *codec) info->dev = codec->dev; INIT_LIST_HEAD(&info->module_list); mutex_init(&info->lock); + INIT_LIST_HEAD(&info->dai_list); + + /* init dai_list used to maintain runtime stream info */ + for (i = 0; i < ARRAY_SIZE(gbaudio_dai); i++) { + dai = devm_kzalloc(codec->dev, sizeof(*dai), GFP_KERNEL); + if (!dai) + return -ENOMEM; + dai->id = gbaudio_dai[i].id; + list_add(&dai->list, &info->dai_list); + } + info->codec = codec; snd_soc_codec_set_drvdata(codec, info); gbcodec = info; @@ -964,32 +1055,6 @@ static unsigned int gbcodec_read(struct snd_soc_codec *codec, return val; } -static struct snd_soc_dai_driver gbaudio_dai[] = { - { - .name = "apb-i2s0", - .id = 0, - .playback = { - .stream_name = "I2S 0 Playback", - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FORMAT_S16_LE, - .rate_max = 48000, - .rate_min = 48000, - .channels_min = 1, - .channels_max = 2, - }, - .capture = { - .stream_name = "I2S 0 Capture", - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FORMAT_S16_LE, - .rate_max = 48000, - .rate_min = 48000, - .channels_min = 1, - .channels_max = 2, - }, - .ops = &gbcodec_dai_ops, - }, -}; - static struct snd_soc_codec_driver soc_codec_dev_gbaudio = { .probe = gbcodec_probe, .remove = gbcodec_remove, diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index 7a2dbc5..40c39b3 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -98,18 +98,25 @@ enum gbaudio_codec_state { GBAUDIO_CODEC_STOP, }; -struct gbaudio_stream { - const char *dai_name; +struct gbaudio_stream_params { int state; uint8_t sig_bits, channels; uint32_t format, rate; }; +struct gbaudio_codec_dai { + int id; + /* runtime params for playback/capture streams */ + struct gbaudio_stream_params params[2]; + struct list_head list; +}; + struct gbaudio_codec_info { struct device *dev; struct snd_soc_codec *codec; struct list_head module_list; - struct gbaudio_stream stream[2]; /* PB/CAP */ + /* to maintain runtime stream params for each DAI */ + struct list_head dai_list; struct mutex lock; u8 reg[GBCODEC_REG_COUNT]; }; -- cgit v0.10.2 From 591c45227a77505f111dd42347b2ad09b60ed131 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Thu, 4 Aug 2016 15:14:39 +0530 Subject: greybus: audio: Maintain module stream state for each data connection For SPK module, each data connection corresponds to codec DAI. Now stream state is maintained for each DAI. So, need to maintain stream state for each DAI/data connection for individual module as well. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index e1ad685..cf86f51 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -52,14 +52,13 @@ static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec, struct gbaudio_data_connection *data; struct gbaudio_stream_params *params; - module_state = module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK]; - /* find the dai */ data = find_data(module, id); if (!data) { dev_err(module->dev, "%d:DATA connection missing\n", id); return -ENODEV; } + module_state = data->state[SNDRV_PCM_STREAM_PLAYBACK]; params = find_dai_stream_params(codec, id, SNDRV_PCM_STREAM_PLAYBACK); if (!params) { @@ -79,7 +78,7 @@ static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec, "reg_cport failed:%d\n", ret); return ret; } - module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK] = + data->state[SNDRV_PCM_STREAM_PLAYBACK] = GBAUDIO_CODEC_STARTUP; dev_dbg(module->dev, "Dynamic Register %d DAI\n", cportid); } @@ -98,7 +97,7 @@ static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec, ret); return ret; } - module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK] = + data->state[SNDRV_PCM_STREAM_PLAYBACK] = GBAUDIO_CODEC_HWPARAMS; dev_dbg(module->dev, "Dynamic hw_params %d DAI\n", data_cport); } @@ -121,7 +120,7 @@ static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec, "activate_tx failed:%d\n", ret); return ret; } - module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK] = + data->state[SNDRV_PCM_STREAM_PLAYBACK] = GBAUDIO_CODEC_PREPARE; dev_dbg(module->dev, "Dynamic prepare %d DAI\n", data_cport); } @@ -136,19 +135,13 @@ static int gbaudio_module_disable_tx(struct gbaudio_module_info *module, int id) int module_state; struct gbaudio_data_connection *data; - module_state = module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK]; - - if (module_state == GBAUDIO_CODEC_SHUTDOWN) { - dev_dbg(module->dev, "module already configured\n"); - return 0; - } - /* find the dai */ data = find_data(module, id); if (!data) { dev_err(module->dev, "%d:DATA connection missing\n", id); return -ENODEV; } + module_state = data->state[SNDRV_PCM_STREAM_PLAYBACK]; if (module_state > GBAUDIO_CODEC_HWPARAMS) { data_cport = data->connection->intf_cport_id; @@ -160,7 +153,7 @@ static int gbaudio_module_disable_tx(struct gbaudio_module_info *module, int id) return ret; } dev_dbg(module->dev, "Dynamic deactivate %d DAI\n", data_cport); - module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK] = + data->state[SNDRV_PCM_STREAM_PLAYBACK] = GBAUDIO_CODEC_HWPARAMS; } @@ -177,7 +170,7 @@ static int gbaudio_module_disable_tx(struct gbaudio_module_info *module, int id) return ret; } dev_dbg(module->dev, "Dynamic Unregister %d DAI\n", cportid); - module->ctrlstate[SNDRV_PCM_STREAM_PLAYBACK] = + data->state[SNDRV_PCM_STREAM_PLAYBACK] = GBAUDIO_CODEC_SHUTDOWN; } @@ -194,14 +187,13 @@ static int gbaudio_module_enable_rx(struct gbaudio_codec_info *codec, struct gbaudio_data_connection *data; struct gbaudio_stream_params *params; - module_state = module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE]; - /* find the dai */ data = find_data(module, id); if (!data) { dev_err(module->dev, "%d:DATA connection missing\n", id); return -ENODEV; } + module_state = data->state[SNDRV_PCM_STREAM_CAPTURE]; params = find_dai_stream_params(codec, id, SNDRV_PCM_STREAM_CAPTURE); if (!params) { @@ -221,7 +213,7 @@ static int gbaudio_module_enable_rx(struct gbaudio_codec_info *codec, "reg_cport failed:%d\n", ret); return ret; } - module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE] = + data->state[SNDRV_PCM_STREAM_CAPTURE] = GBAUDIO_CODEC_STARTUP; dev_dbg(module->dev, "Dynamic Register %d DAI\n", cportid); } @@ -240,7 +232,7 @@ static int gbaudio_module_enable_rx(struct gbaudio_codec_info *codec, ret); return ret; } - module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE] = + data->state[SNDRV_PCM_STREAM_CAPTURE] = GBAUDIO_CODEC_HWPARAMS; dev_dbg(module->dev, "Dynamic hw_params %d DAI\n", data_cport); } @@ -263,7 +255,7 @@ static int gbaudio_module_enable_rx(struct gbaudio_codec_info *codec, "activate_rx failed:%d\n", ret); return ret; } - module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE] = + data->state[SNDRV_PCM_STREAM_CAPTURE] = GBAUDIO_CODEC_PREPARE; dev_dbg(module->dev, "Dynamic prepare %d DAI\n", data_cport); } @@ -278,20 +270,13 @@ static int gbaudio_module_disable_rx(struct gbaudio_module_info *module, int id) int module_state; struct gbaudio_data_connection *data; - module_state = module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE]; - - if (module_state == GBAUDIO_CODEC_SHUTDOWN) { - dev_dbg(module->dev, "%s: module already configured\n", - module->name); - return 0; - } - /* find the dai */ data = find_data(module, id); if (!data) { dev_err(module->dev, "%d:DATA connection missing\n", id); return -ENODEV; } + module_state = data->state[SNDRV_PCM_STREAM_CAPTURE]; if (module_state > GBAUDIO_CODEC_HWPARAMS) { data_cport = data->connection->intf_cport_id; @@ -303,7 +288,7 @@ static int gbaudio_module_disable_rx(struct gbaudio_module_info *module, int id) return ret; } dev_dbg(module->dev, "Dynamic deactivate %d DAI\n", data_cport); - module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE] = + data->state[SNDRV_PCM_STREAM_CAPTURE] = GBAUDIO_CODEC_HWPARAMS; } @@ -320,7 +305,7 @@ static int gbaudio_module_disable_rx(struct gbaudio_module_info *module, int id) return ret; } dev_dbg(module->dev, "Dynamic Unregister %d DAI\n", cportid); - module->ctrlstate[SNDRV_PCM_STREAM_CAPTURE] = + data->state[SNDRV_PCM_STREAM_CAPTURE] = GBAUDIO_CODEC_SHUTDOWN; } @@ -855,68 +840,67 @@ int gbaudio_register_module(struct gbaudio_module_info *module) } EXPORT_SYMBOL(gbaudio_register_module); -static void gbaudio_codec_cleanup(struct gbaudio_module_info *module) +static void gbaudio_codec_clean_data_tx(struct gbaudio_data_connection *data) { - struct gbaudio_data_connection *data; - int pb_state = gbcodec->stream[0].state; - int cap_state = gbcodec->stream[1].state; + uint16_t i2s_port, cportid; int ret; + + if (list_is_singular(&gbcodec->module_list)) { + ret = gb_audio_apbridgea_stop_tx(data->connection, 0); + if (ret) + return; + ret = gb_audio_apbridgea_shutdown_tx(data->connection, + 0); + if (ret) + return; + } + i2s_port = 0; /* fixed for now */ + cportid = data->connection->hd_cport_id; + ret = gb_audio_apbridgea_unregister_cport(data->connection, + i2s_port, cportid, + AUDIO_APBRIDGEA_DIRECTION_TX); + data->state[0] = GBAUDIO_CODEC_SHUTDOWN; +} + +static void gbaudio_codec_clean_data_rx(struct gbaudio_data_connection *data) +{ uint16_t i2s_port, cportid; + int ret; - /* locks already acquired */ - if (!pb_state && !cap_state) - return; + if (list_is_singular(&gbcodec->module_list)) { + ret = gb_audio_apbridgea_stop_rx(data->connection, 0); + if (ret) + return; + ret = gb_audio_apbridgea_shutdown_rx(data->connection, + 0); + if (ret) + return; + } + i2s_port = 0; /* fixed for now */ + cportid = data->connection->hd_cport_id; + ret = gb_audio_apbridgea_unregister_cport(data->connection, + i2s_port, cportid, + AUDIO_APBRIDGEA_DIRECTION_RX); + data->state[1] = GBAUDIO_CODEC_SHUTDOWN; +} + + +static void gbaudio_codec_cleanup(struct gbaudio_module_info *module) +{ + struct gbaudio_data_connection *data; + int pb_state, cap_state; dev_dbg(gbcodec->dev, "%s: removed, cleanup APBridge\n", module->name); - if (pb_state == GBAUDIO_CODEC_START) { - /* cleanup PB path, only APBridge specific */ - data = find_data(module, 1); - if (!data) { - dev_err(gbcodec->dev, "%s: Missing data pointer\n", - __func__); - return; - } + list_for_each_entry(data, &module->data_list, list) { + pb_state = data->state[0]; + cap_state = data->state[1]; - if (list_is_singular(&gbcodec->module_list)) { - ret = gb_audio_apbridgea_stop_tx(data->connection, 0); - if (ret) - return; - ret = gb_audio_apbridgea_shutdown_tx(data->connection, - 0); - if (ret) - return; - } - i2s_port = 0; /* fixed for now */ - cportid = data->connection->hd_cport_id; - ret = gb_audio_apbridgea_unregister_cport(data->connection, - i2s_port, cportid, - AUDIO_APBRIDGEA_DIRECTION_TX); - module->ctrlstate[0] = GBAUDIO_CODEC_SHUTDOWN; - } + if (pb_state > GBAUDIO_CODEC_SHUTDOWN) + gbaudio_codec_clean_data_tx(data); + + if (cap_state > GBAUDIO_CODEC_SHUTDOWN) + gbaudio_codec_clean_data_rx(data); - if (cap_state == GBAUDIO_CODEC_START) { - /* cleanup CAP path, only APBridge specific */ - data = find_data(module, 1); - if (!data) { - dev_err(gbcodec->dev, "%s: Missing data pointer\n", - __func__); - return; - } - if (list_is_singular(&gbcodec->module_list)) { - ret = gb_audio_apbridgea_stop_rx(data->connection, 0); - if (ret) - return; - ret = gb_audio_apbridgea_shutdown_rx(data->connection, - 0); - if (ret) - return; - } - i2s_port = 0; /* fixed for now */ - cportid = data->connection->hd_cport_id; - ret = gb_audio_apbridgea_unregister_cport(data->connection, - i2s_port, cportid, - AUDIO_APBRIDGEA_DIRECTION_RX); - module->ctrlstate[1] = GBAUDIO_CODEC_SHUTDOWN; } } diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index 40c39b3..0de2ad9 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -140,6 +140,8 @@ struct gbaudio_data_connection { __le16 data_cport; struct gb_connection *connection; struct list_head list; + /* maintain runtime state for playback/capture stream */ + int state[2]; }; /* stream direction */ @@ -178,9 +180,6 @@ struct gbaudio_module_info { struct snd_soc_jack headset_jack; struct snd_soc_jack button_jack; - /* used by codec_ops */ - int ctrlstate[2]; /* PB/CAP */ - /* connection info */ struct gb_connection *mgmt_connection; size_t num_data_connections; -- cgit v0.10.2 From 8f3972f78f3ac52833fb781cbb689af39fc8b0f1 Mon Sep 17 00:00:00 2001 From: Jackson Chang <chang_jackson@projectara.com> Date: Fri, 5 Aug 2016 10:22:02 +0800 Subject: greybus: SDIO: Add runtime pm support Modify SDIO greybus driver to support runtime PM framework. To enable SDIO runtime PM, it needs to remove MMC_CAP_NEEDS_POLL and add MMC_CAP2_CORE_RUNTIME_PM in set_host_caps(). The suspend function and resume function have been tested with micron-sdio image by sysfs. SDIO functions work well on suspend/resume. Testing Done: Compiled and verified on EVT2.0 + Micron ARA SD module with USB connector Signed-off-by: Jackson Chang <chang_jackson@projectara.com> Reviewed-by: Rui Miguel Silva <rui.silva@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index 5d13e36..62d6400 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -140,6 +140,10 @@ static inline void sysfs_remove_groups(struct kobject *kobj, #define MMC_DDR52_DEFINED #endif +#ifndef MMC_CAP2_CORE_RUNTIME_PM +#define MMC_CAP2_CORE_RUNTIME_PM 0 +#endif + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0) #define MMC_POWER_UNDEFINED_SUPPORTED #endif diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index ad448c6..3d3599a 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -84,8 +84,8 @@ static void _gb_sdio_set_host_caps(struct gb_sdio_host *host, u32 r) #endif ((r & GB_SDIO_CAP_HS200_1_8V) ? MMC_CAP2_HS200_1_8V_SDR : 0); - host->mmc->caps = caps | MMC_CAP_NEEDS_POLL; - host->mmc->caps2 = caps2; + host->mmc->caps = caps; + host->mmc->caps2 = caps2 | MMC_CAP2_CORE_RUNTIME_PM; if (caps & MMC_CAP_NONREMOVABLE) host->card_present = true; @@ -239,8 +239,18 @@ static int gb_sdio_request_handler(struct gb_operation *op) static int gb_sdio_set_ios(struct gb_sdio_host *host, struct gb_sdio_set_ios_request *request) { - return gb_operation_sync(host->connection, GB_SDIO_TYPE_SET_IOS, - request, sizeof(*request), NULL, 0); + int ret; + + ret = gbphy_runtime_get_sync(host->gbphy_dev); + if (ret) + return ret; + + ret = gb_operation_sync(host->connection, GB_SDIO_TYPE_SET_IOS, request, + sizeof(*request), NULL, 0); + + gbphy_runtime_put_autosuspend(host->gbphy_dev); + + return ret; } static int _gb_sdio_send(struct gb_sdio_host *host, struct mmc_data *data, @@ -489,10 +499,15 @@ static void gb_sdio_mrq_work(struct work_struct *work) host = container_of(work, struct gb_sdio_host, mrqwork); + ret = gbphy_runtime_get_sync(host->gbphy_dev); + if (ret) + return; + mutex_lock(&host->lock); mrq = host->mrq; if (!mrq) { mutex_unlock(&host->lock); + gbphy_runtime_put_autosuspend(host->gbphy_dev); dev_err(mmc_dev(host->mmc), "mmc request is NULL"); return; } @@ -528,6 +543,7 @@ done: host->mrq = NULL; mutex_unlock(&host->lock); mmc_request_done(host->mmc, mrq); + gbphy_runtime_put_autosuspend(host->gbphy_dev); } static void gb_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) @@ -813,6 +829,8 @@ static int gb_sdio_probe(struct gbphy_device *gbphy_dev, ret = _gb_sdio_process_events(host, host->queued_events); host->queued_events = 0; + gbphy_runtime_put_autosuspend(gbphy_dev); + return ret; exit_wq_destroy: @@ -832,6 +850,11 @@ static void gb_sdio_remove(struct gbphy_device *gbphy_dev) struct gb_sdio_host *host = gb_gbphy_get_data(gbphy_dev); struct gb_connection *connection = host->connection; struct mmc_host *mmc; + int ret; + + ret = gbphy_runtime_get_sync(gbphy_dev); + if (ret) + gbphy_runtime_get_noresume(gbphy_dev); mutex_lock(&host->lock); host->removed = true; -- cgit v0.10.2 From 9141ad8773f4f6ebb8cd9fa376d9497fa7e73374 Mon Sep 17 00:00:00 2001 From: Kris Huang <huang_kris@projectara.com> Date: Fri, 5 Aug 2016 12:59:08 +0800 Subject: greybus: lights: Add runtime pm support Modify Lights greybus driver to support runtime PM framework. The suspend and resume function have been tested with gpbridge-test image by sysfs. Lights functions work well on suspend/resume. Testing Done: Compiled and verified on EVT2 and gpbridge-test module with device class daughter board. Signed-off-by: Kris Huang <huang_kris@projectara.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index 3d42a5d..fb41b0b 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -117,17 +117,27 @@ static int __gb_lights_flash_intensity_set(struct gb_channel *channel, u32 intensity) { struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_bundle *bundle = connection->bundle; struct gb_lights_set_flash_intensity_request req; + int ret; if (channel->releasing) return -ESHUTDOWN; + ret = gb_pm_runtime_get_sync(bundle); + if (ret < 0) + return ret; + req.light_id = channel->light->id; req.channel_id = channel->id; req.intensity_uA = cpu_to_le32(intensity); - return gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_FLASH_INTENSITY, - &req, sizeof(req), NULL, 0); + ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_FLASH_INTENSITY, + &req, sizeof(req), NULL, 0); + + gb_pm_runtime_put_autosuspend(bundle); + + return ret; } static int __gb_lights_flash_brightness_set(struct gb_channel *channel) @@ -321,32 +331,52 @@ static int channel_attr_groups_set(struct gb_channel *channel, static int gb_lights_fade_set(struct gb_channel *channel) { struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_bundle *bundle = connection->bundle; struct gb_lights_set_fade_request req; + int ret; if (channel->releasing) return -ESHUTDOWN; + ret = gb_pm_runtime_get_sync(bundle); + if (ret < 0) + return ret; + req.light_id = channel->light->id; req.channel_id = channel->id; req.fade_in = channel->fade_in; req.fade_out = channel->fade_out; - return gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_FADE, - &req, sizeof(req), NULL, 0); + ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_FADE, + &req, sizeof(req), NULL, 0); + + gb_pm_runtime_put_autosuspend(bundle); + + return ret; } static int gb_lights_color_set(struct gb_channel *channel, u32 color) { struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_bundle *bundle = connection->bundle; struct gb_lights_set_color_request req; + int ret; if (channel->releasing) return -ESHUTDOWN; + ret = gb_pm_runtime_get_sync(bundle); + if (ret < 0) + return ret; + req.light_id = channel->light->id; req.channel_id = channel->id; req.color = cpu_to_le32(color); - return gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_COLOR, - &req, sizeof(req), NULL, 0); + ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_COLOR, + &req, sizeof(req), NULL, 0); + + gb_pm_runtime_put_autosuspend(bundle); + + return ret; } #else /* LED_HAVE_GROUPS */ static int channel_attr_groups_set(struct gb_channel *channel, @@ -360,13 +390,23 @@ static int __gb_lights_led_brightness_set(struct gb_channel *channel) { struct gb_lights_set_brightness_request req; struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_bundle *bundle = connection->bundle; + int ret; + + ret = gb_pm_runtime_get_sync(bundle); + if (ret < 0) + return ret; req.light_id = channel->light->id; req.channel_id = channel->id; req.brightness = (u8)channel->led->brightness; - return gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_BRIGHTNESS, - &req, sizeof(req), NULL, 0); + ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_BRIGHTNESS, + &req, sizeof(req), NULL, 0); + + gb_pm_runtime_put_autosuspend(bundle); + + return ret; } static int __gb_lights_brightness_set(struct gb_channel *channel) @@ -441,18 +481,28 @@ static int gb_blink_set(struct led_classdev *cdev, unsigned long *delay_on, { struct gb_channel *channel = get_channel_from_cdev(cdev); struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_bundle *bundle = connection->bundle; struct gb_lights_blink_request req; + int ret; if (channel->releasing) return -ESHUTDOWN; + ret = gb_pm_runtime_get_sync(bundle); + if (ret < 0) + return ret; + req.light_id = channel->light->id; req.channel_id = channel->id; req.time_on_ms = cpu_to_le16(*delay_on); req.time_off_ms = cpu_to_le16(*delay_off); - return gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_BLINK, &req, - sizeof(req), NULL, 0); + ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_BLINK, &req, + sizeof(req), NULL, 0); + + gb_pm_runtime_put_autosuspend(bundle); + + return ret; } static void gb_lights_led_operations_set(struct gb_channel *channel, @@ -592,23 +642,29 @@ static int gb_lights_flash_strobe_set(struct led_classdev_flash *fcdev, struct gb_channel *channel = container_of(fcdev, struct gb_channel, fled); struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_bundle *bundle = connection->bundle; struct gb_lights_set_flash_strobe_request req; int ret; if (channel->releasing) return -ESHUTDOWN; + ret = gb_pm_runtime_get_sync(bundle); + if (ret < 0) + return ret; + req.light_id = channel->light->id; req.channel_id = channel->id; req.state = state ? 1 : 0; ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_FLASH_STROBE, &req, sizeof(req), NULL, 0); - if (ret < 0) - return ret; - channel->strobe_state = state; + if (!ret) + channel->strobe_state = state; - return 0; + gb_pm_runtime_put_autosuspend(bundle); + + return ret; } static int gb_lights_flash_strobe_get(struct led_classdev_flash *fcdev, @@ -627,23 +683,29 @@ static int gb_lights_flash_timeout_set(struct led_classdev_flash *fcdev, struct gb_channel *channel = container_of(fcdev, struct gb_channel, fled); struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_bundle *bundle = connection->bundle; struct gb_lights_set_flash_timeout_request req; int ret; if (channel->releasing) return -ESHUTDOWN; + ret = gb_pm_runtime_get_sync(bundle); + if (ret < 0) + return ret; + req.light_id = channel->light->id; req.channel_id = channel->id; req.timeout_us = cpu_to_le32(timeout); ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_FLASH_TIMEOUT, &req, sizeof(req), NULL, 0); - if (ret < 0) - return ret; - fcdev->timeout.val = timeout; + if (!ret) + fcdev->timeout.val = timeout; - return 0; + gb_pm_runtime_put_autosuspend(bundle); + + return ret; } static int gb_lights_flash_fault_get(struct led_classdev_flash *fcdev, @@ -652,6 +714,7 @@ static int gb_lights_flash_fault_get(struct led_classdev_flash *fcdev, struct gb_channel *channel = container_of(fcdev, struct gb_channel, fled); struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_bundle *bundle = connection->bundle; struct gb_lights_get_flash_fault_request req; struct gb_lights_get_flash_fault_response resp; int ret; @@ -659,17 +722,21 @@ static int gb_lights_flash_fault_get(struct led_classdev_flash *fcdev, if (channel->releasing) return -ESHUTDOWN; + ret = gb_pm_runtime_get_sync(bundle); + if (ret < 0) + return ret; + req.light_id = channel->light->id; req.channel_id = channel->id; ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_GET_FLASH_FAULT, &req, sizeof(req), &resp, sizeof(resp)); - if (ret < 0) - return ret; + if (!ret) + *fault = le32_to_cpu(resp.fault); - *fault = le32_to_cpu(resp.fault); + gb_pm_runtime_put_autosuspend(bundle); - return 0; + return ret; } static const struct led_flash_ops gb_lights_flash_ops = { @@ -1258,6 +1325,8 @@ static int gb_lights_probe(struct gb_bundle *bundle, if (ret < 0) goto error_connection_disable; + gb_pm_runtime_put_autosuspend(bundle); + return 0; error_connection_disable: @@ -1273,6 +1342,9 @@ static void gb_lights_disconnect(struct gb_bundle *bundle) { struct gb_lights *glights = greybus_get_drvdata(bundle); + if (gb_pm_runtime_get_sync(bundle)) + gb_pm_runtime_get_noresume(bundle); + gb_connection_disable(glights->connection); gb_connection_destroy(glights->connection); -- cgit v0.10.2 From 33cc283928249b2230a6519a2303fe30161cf788 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Fri, 5 Aug 2016 18:16:30 +0530 Subject: greybus: audio: Report jack removal along with module removal For GB module with jack slot supported, headset/headphone can still be inserted at the time of module removal. In this case, above layer is unaware about jack removal event which happened due to module removal. This may lead to inconsistent state in above HAL layer. Fix this by reporting jack removal event explicitly. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index cf86f51..3eb3d2c 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -909,6 +909,7 @@ void gbaudio_unregister_module(struct gbaudio_module_info *module) struct snd_soc_codec *codec = gbcodec->codec; struct snd_card *card = codec->card->snd_card; struct snd_soc_jack *jack, *next_j; + int mask; dev_dbg(codec->dev, "Unregister %s module\n", module->name); @@ -922,8 +923,16 @@ void gbaudio_unregister_module(struct gbaudio_module_info *module) #ifdef CONFIG_SND_JACK /* free jack devices for this module from codec->jack_list */ list_for_each_entry_safe(jack, next_j, &codec->jack_list, list) { - if ((jack == &module->headset_jack) - || (jack == &module->button_jack)) { + if (jack == &module->headset_jack) + mask = GBCODEC_JACK_MASK; + else if (jack == &module->button_jack) + mask = GBCODEC_JACK_BUTTON_MASK; + else + mask = 0; + if (mask) { + dev_dbg(module->dev, "Report %s removal\n", + jack->jack->id); + snd_soc_jack_report(jack, 0, mask); snd_device_free(codec->card->snd_card, jack->jack); list_del(&jack->list); } -- cgit v0.10.2 From 4523eae6f8446e3943415683bc9a136ce11fb32b Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Fri, 5 Aug 2016 15:08:40 -0700 Subject: greybus: interface: fix timesync registration sequencing When enabling an interface, control device should be registered after having successfully added the timesync. Similarly for the interface disable path, control device should be removed first before removing timesync. Testing Done: - Enable and disable the interface Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Suggested-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: David Lin <dtwlin@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 76569f8..c3ed3d7 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -1152,17 +1152,17 @@ int gb_interface_enable(struct gb_interface *intf) if (ret) goto err_destroy_bundles; - /* Register the control device and any bundles */ - ret = gb_control_add(intf->control); - if (ret) - goto err_destroy_bundles; - ret = gb_timesync_interface_add(intf); if (ret) { dev_err(&intf->dev, "failed to add to timesync: %d\n", ret); - goto err_del_control; + goto err_destroy_bundles; } + /* Register the control device and any bundles */ + ret = gb_control_add(intf->control); + if (ret) + goto err_remove_timesync; + pm_runtime_use_autosuspend(&intf->dev); pm_runtime_get_noresume(&intf->dev); pm_runtime_set_active(&intf->dev); @@ -1186,8 +1186,8 @@ int gb_interface_enable(struct gb_interface *intf) return 0; -err_del_control: - gb_control_del(intf->control); +err_remove_timesync: + gb_timesync_interface_remove(intf); err_destroy_bundles: list_for_each_entry_safe(bundle, tmp, &intf->bundles, links) gb_bundle_destroy(bundle); @@ -1229,8 +1229,8 @@ void gb_interface_disable(struct gb_interface *intf) if (!intf->mode_switch && !intf->disconnected) gb_control_interface_deactivate_prepare(intf->control); - gb_timesync_interface_remove(intf); gb_control_del(intf->control); + gb_timesync_interface_remove(intf); gb_control_disable(intf->control); gb_control_put(intf->control); intf->control = NULL; -- cgit v0.10.2 From 64f28ada9349ab071096484281548b6be1791cd7 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva <rui.silva@linaro.org> Date: Tue, 9 Aug 2016 23:35:34 +0100 Subject: greybus: greybus_protocol: fix order of sdio get caps response Order of the field of the sdio get caps operation response were wrong, that influence later the frequencies used by core, during normal operation. Tested: verified that the values inserted by the fw are the correct ones for the field. Suggested-by: Jackson Chang <jacksonc@bsquare.com> Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 8484f05..3082cbf 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -1540,10 +1540,10 @@ struct gb_sdio_get_caps_response { /* see possible values below at vdd */ __le32 ocr; - __le16 max_blk_count; - __le16 max_blk_size; __le32 f_min; __le32 f_max; + __le16 max_blk_count; + __le16 max_blk_size; } __packed; /* set ios request: response has no payload */ -- cgit v0.10.2 From afbf72505be3da3bb7563e3e403020a3ba62f4f7 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva <rui.silva@linaro.org> Date: Tue, 9 Aug 2016 23:35:35 +0100 Subject: greybus: sdio: increase maximum segment size Adjust maximum segment size of the sg list to meet the maximum request size, this will allow to have less segments which increase the performance of data movement during transfer operations. Test Done: using mmc_test with best-case read/write performance and see that only one segment is used and that the results are better (288KiB vs 300KiB in read operation). Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index 3d3599a..a78d9e4 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -802,11 +802,11 @@ static int gb_sdio_probe(struct gbphy_device *gbphy_dev, mmc->ops = &gb_sdio_ops; - /* for now we just make a map 1:1 between max blocks and segments */ mmc->max_segs = host->mmc->max_blk_count; - mmc->max_seg_size = host->mmc->max_blk_size; + /* for now we make a map 1:1 between max request and segment size */ mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; + mmc->max_seg_size = mmc->max_req_size; mutex_init(&host->lock); spin_lock_init(&host->xfer); -- cgit v0.10.2 From a4fe35072f3c531c97694de2e7fe28939b72c742 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 10 Aug 2016 12:58:39 +0200 Subject: greybus: greybus_protocols: fix apba vendor-request comment Fix copy-paste error in an APBA USB vendor-request comment. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 3082cbf..63fd48d 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -243,7 +243,7 @@ struct gb_control_intf_pm_response { /* request to control the CSI transmitter */ #define GB_APB_REQUEST_CSI_TX_CONTROL 0x08 -/* request to control the CSI transmitter */ +/* request to control audio streaming */ #define GB_APB_REQUEST_AUDIO_CONTROL 0x09 /* vendor requests to enable/disable CPort features */ -- cgit v0.10.2 From 83d474f7aa467a8cc4cb33337a790fea891a98f1 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 10 Aug 2016 12:58:40 +0200 Subject: greybus: es2: fix USB vendor-request prefixes Make sure to use the common GB_APB prefix for all APBA USB vendor requests. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 3b8d81ef..996cfc6 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -833,7 +833,7 @@ static int timesync_enable(struct gb_host_device *hd, u8 count, request->strobe_delay = cpu_to_le32(strobe_delay); request->refclk = cpu_to_le32(refclk); retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - REQUEST_TIMESYNC_ENABLE, + GB_APB_REQUEST_TIMESYNC_ENABLE, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0, 0, request, sizeof(*request), ES2_USB_CTRL_TIMEOUT); @@ -851,7 +851,7 @@ static int timesync_disable(struct gb_host_device *hd) struct usb_device *udev = es2->usb_dev; retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - REQUEST_TIMESYNC_DISABLE, + GB_APB_REQUEST_TIMESYNC_DISABLE, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0, 0, NULL, 0, ES2_USB_CTRL_TIMEOUT); @@ -876,7 +876,7 @@ static int timesync_authoritative(struct gb_host_device *hd, u64 *frame_time) request->frame_time[i] = cpu_to_le64(frame_time[i]); retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - REQUEST_TIMESYNC_AUTHORITATIVE, + GB_APB_REQUEST_TIMESYNC_AUTHORITATIVE, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0, 0, request, sizeof(*request), ES2_USB_CTRL_TIMEOUT); @@ -899,7 +899,7 @@ static int timesync_get_last_event(struct gb_host_device *hd, u64 *frame_time) return -ENOMEM; retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - REQUEST_TIMESYNC_GET_LAST_EVENT, + GB_APB_REQUEST_TIMESYNC_GET_LAST_EVENT, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0, 0, response_frame_time, sizeof(*response_frame_time), @@ -1165,7 +1165,7 @@ static int arpc_send(struct es2_ap_dev *es2, struct arpc *rpc, int timeout) int retval; retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - APBA_REQUEST_ARPC_RUN, + GB_APB_REQUEST_ARPC_RUN, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0, 0, diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 63fd48d..4bf494c 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -250,17 +250,17 @@ struct gb_control_intf_pm_response { #define GB_APB_REQUEST_CPORT_FEAT_EN 0x0b #define GB_APB_REQUEST_CPORT_FEAT_DIS 0x0c -/* TimeSync commands */ -#define REQUEST_TIMESYNC_ENABLE 0x0d -#define REQUEST_TIMESYNC_DISABLE 0x0e -#define REQUEST_TIMESYNC_AUTHORITATIVE 0x0f -#define REQUEST_TIMESYNC_GET_LAST_EVENT 0x10 +/* TimeSync requests */ +#define GB_APB_REQUEST_TIMESYNC_ENABLE 0x0d +#define GB_APB_REQUEST_TIMESYNC_DISABLE 0x0e +#define GB_APB_REQUEST_TIMESYNC_AUTHORITATIVE 0x0f +#define GB_APB_REQUEST_TIMESYNC_GET_LAST_EVENT 0x10 /* requests to set Greybus CPort flags */ #define GB_APB_REQUEST_CPORT_FLAGS 0x11 -/* ARPC command */ -#define APBA_REQUEST_ARPC_RUN 0x12 +/* ARPC request */ +#define GB_APB_REQUEST_ARPC_RUN 0x12 struct gb_apb_request_cport_flags { __le32 flags; -- cgit v0.10.2 From 7d0e76d6cbbcc7b71f65d39ee2b4231beab42faa Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 10 Aug 2016 12:58:41 +0200 Subject: greybus: arpc: move arpc definitions to their own header Move the ARPC definitions to their own header. ARPC is not part of greybus, but is rather an implementation-specific means of communicating with a certain class of host-device hardware. Note that the same is true for the APBA USB vendor requests, but we keep them in the greybus header for the time being. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/arpc.h b/drivers/staging/greybus/arpc.h new file mode 100644 index 0000000..7ce7a84 --- /dev/null +++ b/drivers/staging/greybus/arpc.h @@ -0,0 +1,85 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2014-2016 Google Inc. All rights reserved. + * Copyright(c) 2014-2016 Linaro Ltd. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details. + * + * BSD LICENSE + * + * Copyright(c) 2014-2016 Google Inc. All rights reserved. + * Copyright(c) 2014-2016 Linaro Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. or Linaro Ltd. nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * 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 GOOGLE INC. OR + * LINARO LTD. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __ARPC_H +#define __ARPC_H + +/* APBridgeA RPC (ARPC) */ + +enum arpc_result { + ARPC_SUCCESS = 0x00, + ARPC_NO_MEMORY = 0x01, + ARPC_INVALID = 0x02, + ARPC_TIMEOUT = 0x03, + ARPC_UNKNOWN_ERROR = 0xff, +}; + +struct arpc_request_message { + __le16 id; /* RPC unique id */ + __le16 size; /* Size in bytes of header + payload */ + __u8 type; /* RPC type */ + __u8 data[0]; /* ARPC data */ +} __packed; + +struct arpc_response_message { + __le16 id; /* RPC unique id */ + __u8 result; /* Result of RPC */ +} __packed; + + +/* ARPC requests */ +#define ARPC_TYPE_CPORT_RESET 0x00 + +struct arpc_cport_reset_req { + __le16 cport_id; +} __packed; + +#endif /* __ARPC_H */ diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 996cfc6..955b37d 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -14,6 +14,7 @@ #include <linux/list.h> #include <asm/unaligned.h> +#include "arpc.h" #include "greybus.h" #include "greybus_trace.h" #include "kernel_ver.h" diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 4bf494c..d43b367 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -268,35 +268,6 @@ struct gb_apb_request_cport_flags { #define GB_APB_CPORT_FLAG_HIGH_PRIO 0x02 } __packed; -/* APBridgeA RPC (ARPC) */ - -enum arpc_result { - ARPC_SUCCESS = 0x00, - ARPC_NO_MEMORY = 0x01, - ARPC_INVALID = 0x02, - ARPC_TIMEOUT = 0x03, - ARPC_UNKNOWN_ERROR = 0xff, -}; - -/* ARPC request */ -struct arpc_request_message { - __le16 id; /* RPC unique id */ - __le16 size; /* Size in bytes of header + payload */ - __u8 type; /* RPC type */ - __u8 data[0]; /* ARPC data */ -} __packed; - -/* ARPC response */ -struct arpc_response_message { - __le16 id; /* RPC unique id */ - __u8 result; /* Result of RPC */ -} __packed; - -#define ARPC_TYPE_CPORT_RESET 0x00 - -struct arpc_cport_reset_req { - __le16 cport_id; -} __packed; /* Firmware Download Protocol */ -- cgit v0.10.2 From 127bada1a1951d9624c08eeab99234ced0df900e Mon Sep 17 00:00:00 2001 From: Jacopo Mondi <jacopo.mondi@linaro.org> Date: Wed, 10 Aug 2016 09:08:19 +0200 Subject: greybus: camera: Remove reference to ara subdevice Remove last occurrence of "ara" term in camera driver. Replace reference to "ara subdevice" with "gmp subdevice" Signed-off-by: Jacopo Mondi <jacopo.mondi@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 0e7f643..94b6712 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -848,7 +848,7 @@ static int gb_camera_request_handler(struct gb_operation *op) } /* ----------------------------------------------------------------------------- - * Interface with HOST ara camera. + * Interface with HOST gmp camera. */ static unsigned int gb_camera_mbus_to_gb(enum v4l2_mbus_pixelcode mbus_code) { -- cgit v0.10.2 From 57fa2de1e5671c3632c5666ce08e03f1e3dc0242 Mon Sep 17 00:00:00 2001 From: Georgi Dobrev <gdobrev@mm-sol.com> Date: Tue, 9 Aug 2016 14:37:32 -0700 Subject: greybus: greybus-driver: Add intf_oops operation Add intf_oops operation to SVC Protocol. This operation will notify the AP about a fatal error in a module. The request has two arguments: -u8 intf - the interface in question -u8 reason - reason of the error The response has no payload. Upon receiving the Request, the driver disables the Interface. Signed-off-by: Georgi Dobrev <gdobrev@mm-sol.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Ashwin Chaugule <ashwinch@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index d43b367..19ca1db 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -1018,6 +1018,7 @@ struct gb_spi_transfer_response { #define GB_SVC_TYPE_INTF_ACTIVATE 0x27 #define GB_SVC_TYPE_INTF_RESUME 0x28 #define GB_SVC_TYPE_INTF_MAILBOX_EVENT 0x29 +#define GB_SVC_TYPE_INTF_OOPS 0x2a /* Greybus SVC protocol status values */ #define GB_SVC_OP_SUCCESS 0x00 @@ -1357,6 +1358,12 @@ struct gb_svc_intf_mailbox_event_request { } __packed; /* intf_mailbox_event response has no payload */ +struct gb_svc_intf_oops_request { + __u8 intf_id; + __u8 reason; +} __packed; +/* intf_oops response has no payload */ + /* RAW */ diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 1170515..c5aedd5 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -1112,6 +1112,37 @@ static void gb_svc_process_module_removed(struct gb_operation *operation) gb_module_put(module); } +static void gb_svc_process_intf_oops(struct gb_operation *operation) +{ + struct gb_svc_intf_oops_request *request; + struct gb_connection *connection = operation->connection; + struct gb_svc *svc = gb_connection_get_data(connection); + struct gb_interface *intf; + u8 intf_id; + u8 reason; + + /* The request message size has already been verified. */ + request = operation->request->payload; + intf_id = request->intf_id; + reason = request->reason; + + intf = gb_svc_interface_lookup(svc, intf_id); + if (!intf) { + dev_warn(&svc->dev, "unexpected interface-oops event %u\n", + intf_id); + return; + } + + dev_info(&svc->dev, "Deactivating interface %u, interface oops reason = %u\n", + intf_id, reason); + + mutex_lock(&intf->mutex); + intf->disconnected = true; + gb_interface_disable(intf); + gb_interface_deactivate(intf); + mutex_unlock(&intf->mutex); +} + static void gb_svc_process_intf_mailbox_event(struct gb_operation *operation) { struct gb_svc_intf_mailbox_event_request *request; @@ -1165,6 +1196,9 @@ static void gb_svc_process_deferred_request(struct work_struct *work) case GB_SVC_TYPE_INTF_MAILBOX_EVENT: gb_svc_process_intf_mailbox_event(operation); break; + case GB_SVC_TYPE_INTF_OOPS: + gb_svc_process_intf_oops(operation); + break; default: dev_err(&svc->dev, "bad deferred request type: 0x%02x\n", type); } @@ -1251,6 +1285,20 @@ static int gb_svc_module_removed_recv(struct gb_operation *op) return gb_svc_queue_deferred_request(op); } +static int gb_svc_intf_oops_recv(struct gb_operation *op) +{ + struct gb_svc *svc = gb_connection_get_data(op->connection); + struct gb_svc_intf_oops_request *request; + + if (op->request->payload_size < sizeof(*request)) { + dev_warn(&svc->dev, "short intf-oops request received (%zu < %zu)\n", + op->request->payload_size, sizeof(*request)); + return -EINVAL; + } + + return gb_svc_queue_deferred_request(op); +} + static int gb_svc_intf_mailbox_event_recv(struct gb_operation *op) { struct gb_svc *svc = gb_connection_get_data(op->connection); @@ -1326,6 +1374,8 @@ static int gb_svc_request_handler(struct gb_operation *op) return gb_svc_module_removed_recv(op); case GB_SVC_TYPE_INTF_MAILBOX_EVENT: return gb_svc_intf_mailbox_event_recv(op); + case GB_SVC_TYPE_INTF_OOPS: + return gb_svc_intf_oops_recv(op); default: dev_warn(&svc->dev, "unsupported request 0x%02x\n", type); return -EINVAL; -- cgit v0.10.2 From 811b1f58610d219610c223a1d63031171a079a7c Mon Sep 17 00:00:00 2001 From: Kris Huang <huang_kris@projectara.com> Date: Tue, 9 Aug 2016 11:28:37 +0800 Subject: greybus: lights: enable multi color LED support A backport (commit 79c4de08c0e5a26b04a4ac9e6543dad6379f0b40) was applied in kernel which adding attribute-group support in led-class. Remove the LED_HAVE_GROUPS flag check entirely that allow led drivers to create custom attributes like color/fade_in/fade_out. Testing Done: Compiled and verified on EVT2 and gpbridge-test module with device class daughter board. Signed-off-by: Kris Huang <huang_kris@projectara.com> Reviewed-by: Rui Miguel Silva <rui.silva@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index 62d6400..97e7ac9 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -252,13 +252,6 @@ static inline size_t sg_pcopy_from_buffer(struct scatterlist *sgl, list_entry((ptr)->prev, type, member) #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0) -/* - * Before this version the led classdev did not support groups - */ -#define LED_HAVE_GROUPS -#endif - #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) /* * At this time the internal API for the set brightness was changed to the async diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index fb41b0b..a57d593 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -172,7 +172,6 @@ static int __gb_lights_flash_brightness_set(struct gb_channel *channel) } #endif /* !LED_HAVE_FLASH */ -#ifdef LED_HAVE_GROUPS static int gb_lights_color_set(struct gb_channel *channel, u32 color); static int gb_lights_fade_set(struct gb_channel *channel); @@ -378,13 +377,6 @@ static int gb_lights_color_set(struct gb_channel *channel, u32 color) return ret; } -#else /* LED_HAVE_GROUPS */ -static int channel_attr_groups_set(struct gb_channel *channel, - struct led_classdev *cdev) -{ - return 0; -} -#endif /* !LED_HAVE_GROUPS */ static int __gb_lights_led_brightness_set(struct gb_channel *channel) { -- cgit v0.10.2 From b3136a77a49026c2f393e8ad6c99e3b5514d1e5a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Wed, 10 Aug 2016 17:02:05 +0200 Subject: greybus: fix up copyright dates on arpc.h I got them wrong, Johan was right, my fault. Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/arpc.h b/drivers/staging/greybus/arpc.h index 7ce7a84..1bfb7db 100644 --- a/drivers/staging/greybus/arpc.h +++ b/drivers/staging/greybus/arpc.h @@ -4,8 +4,8 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2014-2016 Google Inc. All rights reserved. - * Copyright(c) 2014-2016 Linaro Ltd. All rights reserved. + * Copyright(c) 2016 Google Inc. All rights reserved. + * Copyright(c) 2016 Linaro Ltd. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -18,8 +18,8 @@ * * BSD LICENSE * - * Copyright(c) 2014-2016 Google Inc. All rights reserved. - * Copyright(c) 2014-2016 Linaro Ltd. All rights reserved. + * Copyright(c) 2016 Google Inc. All rights reserved. + * Copyright(c) 2016 Linaro Ltd. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions -- cgit v0.10.2 From a9dc1cf5b7b5ce8183249c2229ae0ab849525e37 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 10 Aug 2016 12:58:42 +0200 Subject: greybus: hd/es2: add cport_connected callback and ARPC Add a host-device cport_connected callback, which will be called after a connection has been created and that can be used by the host-device driver to make sure its internal state is updated to match the CPort attributes set by the SVC. This callback will eventually replace the cport_features_enable callback. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Acked-by: Sandeep Patil <sspatil@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/arpc.h b/drivers/staging/greybus/arpc.h index 1bfb7db..8a90271 100644 --- a/drivers/staging/greybus/arpc.h +++ b/drivers/staging/greybus/arpc.h @@ -77,9 +77,15 @@ struct arpc_response_message { /* ARPC requests */ #define ARPC_TYPE_CPORT_RESET 0x00 +#define ARPC_TYPE_CPORT_CONNECTED 0x01 struct arpc_cport_reset_req { __le16 cport_id; } __packed; +struct arpc_cport_connected_req { + __le16 cport_id; +} __packed; + + #endif /* __ARPC_H */ diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 955b37d..9af9b73 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -746,6 +746,25 @@ static int cport_disable(struct gb_host_device *hd, u16 cport_id) return 0; } +static int es2_cport_connected(struct gb_host_device *hd, u16 cport_id) +{ + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct device *dev = &es2->usb_dev->dev; + struct arpc_cport_connected_req req; + int ret; + + req.cport_id = cpu_to_le16(cport_id); + ret = arpc_sync(es2, ARPC_TYPE_CPORT_CONNECTED, &req, sizeof(req), + NULL, ES2_ARPC_CPORT_TIMEOUT); + if (ret) { + dev_err(dev, "failed to set connected state for cport %u: %d\n", + cport_id, ret); + return ret; + } + + return 0; +} + static int latency_tag_enable(struct gb_host_device *hd, u16 cport_id) { int retval; @@ -930,6 +949,7 @@ static struct gb_hd_driver es2_driver = { .cport_release = es2_cport_release, .cport_enable = cport_enable, .cport_disable = cport_disable, + .cport_connected = es2_cport_connected, .latency_tag_enable = latency_tag_enable, .latency_tag_disable = latency_tag_disable, .output = output, diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h index 6ea5e28..be81879 100644 --- a/drivers/staging/greybus/hd.h +++ b/drivers/staging/greybus/hd.h @@ -22,6 +22,7 @@ struct gb_hd_driver { int (*cport_enable)(struct gb_host_device *hd, u16 cport_id, unsigned long flags); int (*cport_disable)(struct gb_host_device *hd, u16 cport_id); + int (*cport_connected)(struct gb_host_device *hd, u16 cport_id); int (*cport_flush)(struct gb_host_device *hd, u16 cport_id); int (*cport_ping)(struct gb_host_device *hd, u16 cport_id); int (*message_send)(struct gb_host_device *hd, u16 dest_cport_id, -- cgit v0.10.2 From 0e7cd0d259890f21d13171d5798eed24a03903dc Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 10 Aug 2016 12:58:43 +0200 Subject: greybus: hd/es2: add cport_quiesce callback and ARPC Add a host-device cport_quiesce callback, which will be called as part of the new connection tear-down sequence to disable flow control after first making sure that enough peer buffer space is available for the next messages about to be sent. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Acked-by: Sandeep Patil <sspatil@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/arpc.h b/drivers/staging/greybus/arpc.h index 8a90271..9fb1608 100644 --- a/drivers/staging/greybus/arpc.h +++ b/drivers/staging/greybus/arpc.h @@ -78,6 +78,7 @@ struct arpc_response_message { /* ARPC requests */ #define ARPC_TYPE_CPORT_RESET 0x00 #define ARPC_TYPE_CPORT_CONNECTED 0x01 +#define ARPC_TYPE_CPORT_QUIESCE 0x02 struct arpc_cport_reset_req { __le16 cport_id; @@ -87,5 +88,11 @@ struct arpc_cport_connected_req { __le16 cport_id; } __packed; +struct arpc_cport_quiesce_req { + __le16 cport_id; + __le16 peer_space; + __le16 timeout; +} __packed; + #endif /* __ARPC_H */ diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 9af9b73..42f2483 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -765,6 +765,35 @@ static int es2_cport_connected(struct gb_host_device *hd, u16 cport_id) return 0; } +static int es2_cport_quiesce(struct gb_host_device *hd, u16 cport_id, + size_t peer_space, unsigned int timeout) +{ + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct device *dev = &es2->usb_dev->dev; + struct arpc_cport_quiesce_req req; + int result; + int ret; + + if (peer_space > U16_MAX) + return -EINVAL; + + if (timeout > U16_MAX) + return -EINVAL; + + req.cport_id = cpu_to_le16(cport_id); + req.peer_space = cpu_to_le16(peer_space); + req.timeout = cpu_to_le16(timeout); + ret = arpc_sync(es2, ARPC_TYPE_CPORT_QUIESCE, &req, sizeof(req), + &result, ES2_ARPC_CPORT_TIMEOUT + timeout); + if (ret) { + dev_err(dev, "failed to quiesce cport %u: %d (%d)\n", + cport_id, ret, result); + return ret; + } + + return 0; +} + static int latency_tag_enable(struct gb_host_device *hd, u16 cport_id) { int retval; @@ -950,6 +979,7 @@ static struct gb_hd_driver es2_driver = { .cport_enable = cport_enable, .cport_disable = cport_disable, .cport_connected = es2_cport_connected, + .cport_quiesce = es2_cport_quiesce, .latency_tag_enable = latency_tag_enable, .latency_tag_disable = latency_tag_disable, .output = output, diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h index be81879..feaba01 100644 --- a/drivers/staging/greybus/hd.h +++ b/drivers/staging/greybus/hd.h @@ -25,6 +25,8 @@ struct gb_hd_driver { int (*cport_connected)(struct gb_host_device *hd, u16 cport_id); int (*cport_flush)(struct gb_host_device *hd, u16 cport_id); int (*cport_ping)(struct gb_host_device *hd, u16 cport_id); + int (*cport_quiesce)(struct gb_host_device *hd, u16 cport_id, + size_t peer_space, unsigned int timeout); int (*message_send)(struct gb_host_device *hd, u16 dest_cport_id, struct gb_message *message, gfp_t gfp_mask); void (*message_cancel)(struct gb_message *message); -- cgit v0.10.2 From 6471c0039cd2fa92bb7df1262c57cb5190eb4311 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 10 Aug 2016 12:58:44 +0200 Subject: greybus: hd/es2: add cport_clear callback and ARPC Add a host-device cport_clear callback, which will be called as part of the new connection tear-down sequence to reset the CPort state. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Acked-by: Sandeep Patil <sspatil@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/arpc.h b/drivers/staging/greybus/arpc.h index 9fb1608..6d27769 100644 --- a/drivers/staging/greybus/arpc.h +++ b/drivers/staging/greybus/arpc.h @@ -79,6 +79,7 @@ struct arpc_response_message { #define ARPC_TYPE_CPORT_RESET 0x00 #define ARPC_TYPE_CPORT_CONNECTED 0x01 #define ARPC_TYPE_CPORT_QUIESCE 0x02 +#define ARPC_TYPE_CPORT_CLEAR 0x03 struct arpc_cport_reset_req { __le16 cport_id; @@ -94,5 +95,9 @@ struct arpc_cport_quiesce_req { __le16 timeout; } __packed; +struct arpc_cport_clear_req { + __le16 cport_id; +} __packed; + #endif /* __ARPC_H */ diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 42f2483..7f46f2a 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -794,6 +794,24 @@ static int es2_cport_quiesce(struct gb_host_device *hd, u16 cport_id, return 0; } +static int es2_cport_clear(struct gb_host_device *hd, u16 cport_id) +{ + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct device *dev = &es2->usb_dev->dev; + struct arpc_cport_clear_req req; + int ret; + + req.cport_id = cpu_to_le16(cport_id); + ret = arpc_sync(es2, ARPC_TYPE_CPORT_CLEAR, &req, sizeof(req), + NULL, ES2_ARPC_CPORT_TIMEOUT); + if (ret) { + dev_err(dev, "failed to clear cport %u: %d\n", cport_id, ret); + return ret; + } + + return 0; +} + static int latency_tag_enable(struct gb_host_device *hd, u16 cport_id) { int retval; @@ -980,6 +998,7 @@ static struct gb_hd_driver es2_driver = { .cport_disable = cport_disable, .cport_connected = es2_cport_connected, .cport_quiesce = es2_cport_quiesce, + .cport_clear = es2_cport_clear, .latency_tag_enable = latency_tag_enable, .latency_tag_disable = latency_tag_disable, .output = output, diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h index feaba01..67f4f3c 100644 --- a/drivers/staging/greybus/hd.h +++ b/drivers/staging/greybus/hd.h @@ -27,6 +27,8 @@ struct gb_hd_driver { int (*cport_ping)(struct gb_host_device *hd, u16 cport_id); int (*cport_quiesce)(struct gb_host_device *hd, u16 cport_id, size_t peer_space, unsigned int timeout); + int (*cport_clear)(struct gb_host_device *hd, u16 cport_id); + int (*message_send)(struct gb_host_device *hd, u16 dest_cport_id, struct gb_message *message, gfp_t gfp_mask); void (*message_cancel)(struct gb_message *message); -- cgit v0.10.2 From 8f71a975d4150abf8ab1fbea65b51e73ff9936d6 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 10 Aug 2016 12:58:45 +0200 Subject: greybus: hd: add cport_shutdown callback Add a host-device cport_shutdown callback which will be called as part of the new connection tear-down sequence for offloaded connection in order to do a cport_shutdown operation on behalf of the AP. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Acked-by: Sandeep Patil <sspatil@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h index 67f4f3c..1274224 100644 --- a/drivers/staging/greybus/hd.h +++ b/drivers/staging/greybus/hd.h @@ -25,6 +25,8 @@ struct gb_hd_driver { int (*cport_connected)(struct gb_host_device *hd, u16 cport_id); int (*cport_flush)(struct gb_host_device *hd, u16 cport_id); int (*cport_ping)(struct gb_host_device *hd, u16 cport_id); + int (*cport_shutdown)(struct gb_host_device *hd, u16 cport_id, + u8 phase, unsigned int timeout); int (*cport_quiesce)(struct gb_host_device *hd, u16 cport_id, size_t peer_space, unsigned int timeout); int (*cport_clear)(struct gb_host_device *hd, u16 cport_id); -- cgit v0.10.2 From 9f77b80fdfeb72bdecf7855bb526ef14b6ed2ba8 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 10 Aug 2016 12:58:46 +0200 Subject: greybus: control: make disconnecting a core operation Make the control-protocol disconnecting operation a "core" operation. This is needed to be able to use the operation in the new connection tear-down sequence of control connections, which moves disconnecting after the flush barrier. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Acked-by: Sandeep Patil <sspatil@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index 658f8a6..4716190 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -152,13 +152,29 @@ int gb_control_disconnected_operation(struct gb_control *control, u16 cport_id) int gb_control_disconnecting_operation(struct gb_control *control, u16 cport_id) { - struct gb_control_disconnecting_request request; + struct gb_control_disconnecting_request *request; + struct gb_operation *operation; + int ret; - request.cport_id = cpu_to_le16(cport_id); + operation = gb_operation_create_core(control->connection, + GB_CONTROL_TYPE_DISCONNECTING, + sizeof(*request), 0, 0, + GFP_KERNEL); + if (!operation) + return -ENOMEM; - return gb_operation_sync(control->connection, - GB_CONTROL_TYPE_DISCONNECTING, &request, - sizeof(request), NULL, 0); + request = operation->request->payload; + request->cport_id = cpu_to_le16(cport_id); + + ret = gb_operation_request_send_sync(operation); + if (ret) { + dev_err(&control->dev, "failed to send disconnecting: %d\n", + ret); + } + + gb_operation_put(operation); + + return ret; } int gb_control_mode_switch_operation(struct gb_control *control) -- cgit v0.10.2 From 295b5269d63841183257d9da9035dd3e3fde4200 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Wed, 10 Aug 2016 10:48:31 -0700 Subject: greybus: firmware: use 'tag' instead of 'firmware_tag' We already have another direct pointer for this, use that instead. Testing Done: Compiled. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/fw-download.c b/drivers/staging/greybus/fw-download.c index 41a45ec..16de71c 100644 --- a/drivers/staging/greybus/fw-download.c +++ b/drivers/staging/greybus/fw-download.c @@ -245,7 +245,7 @@ static int fw_download_find_firmware(struct gb_operation *op) return -EINVAL; } - fw_req = find_firmware(fw_download, request->firmware_tag); + fw_req = find_firmware(fw_download, tag); if (IS_ERR(fw_req)) return PTR_ERR(fw_req); -- cgit v0.10.2 From d581bc88cb0b89ba3bf135855843916fc78e6693 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Wed, 10 Aug 2016 10:48:32 -0700 Subject: greybus: firmware: Fix typo in documentation s/shall be used the user/shall be used by the user/ Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/firmware/firmware-management b/drivers/staging/greybus/Documentation/firmware/firmware-management index 77d272c..ced41d2 100644 --- a/drivers/staging/greybus/Documentation/firmware/firmware-management +++ b/drivers/staging/greybus/Documentation/firmware/firmware-management @@ -139,44 +139,45 @@ struct fw_mgmt_ioc_backend_fw_update { 1. FW_MGMT_IOC_GET_INTF_FW: - This ioctl shall be used the user to get the version and firmware-tag of the - currently running Interface Firmware. All the fields of the 'struct + This ioctl shall be used by the user to get the version and firmware-tag of + the currently running Interface Firmware. All the fields of the 'struct fw_mgmt_ioc_get_fw' are filled by the kernel. 2. FW_MGMT_IOC_GET_BACKEND_FW: - This ioctl shall be used the user to get the version of a currently running - Backend Interface Firmware identified by a firmware-tag. The user is required - to fill the 'firmware_tag' field of the 'struct fw_mgmt_ioc_get_fw' in this - case. The 'major' and 'minor' fields are set by the kernel in response. + This ioctl shall be used by the user to get the version of a currently + running Backend Interface Firmware identified by a firmware-tag. The user is + required to fill the 'firmware_tag' field of the 'struct fw_mgmt_ioc_get_fw' + in this case. The 'major' and 'minor' fields are set by the kernel in + response. 3. FW_MGMT_IOC_INTF_LOAD_AND_VALIDATE: - This ioctl shall be used the user to load an Interface Firmware package on an - Interface. The user needs to fill the 'firmware_tag' and 'load_method' fields - of the 'struct fw_mgmt_ioc_intf_load_and_validate'. The 'status', 'major' and - 'minor' fields are set by the kernel in response. + This ioctl shall be used by the user to load an Interface Firmware package on + an Interface. The user needs to fill the 'firmware_tag' and 'load_method' + fields of the 'struct fw_mgmt_ioc_intf_load_and_validate'. The 'status', + 'major' and 'minor' fields are set by the kernel in response. 4. FW_MGMT_IOC_INTF_BACKEND_FW_UPDATE: - This ioctl shall be used the user to request an Interface to update a Backend - Interface Firmware. The user is required to fill the 'firmware_tag' field of - the 'struct fw_mgmt_ioc_get_fw' in this case. The 'status' field is set by - the kernel in response. + This ioctl shall be used by the user to request an Interface to update a + Backend Interface Firmware. The user is required to fill the 'firmware_tag' + field of the 'struct fw_mgmt_ioc_get_fw' in this case. The 'status' field is + set by the kernel in response. 5. FW_MGMT_IOC_SET_TIMEOUT_MS: - This ioctl shall be used the user to increase the timeout interval within + This ioctl shall be used by the user to increase the timeout interval within which the firmware must get loaded by the Module. The default timeout is 1 second. The user needs to pass the timeout in milliseconds. 6. FW_MGMT_IOC_MODE_SWITCH: - This ioctl shall be used the user to mode-switch the module to the previously - loaded interface firmware. If the interface firmware isn't loaded previously, - or if another unsuccessful FW_MGMT_IOC_INTF_LOAD_AND_VALIDATE operation is - started after loading interface firmware, then the firmware core wouldn't - allow mode-switch. + This ioctl shall be used by the user to mode-switch the module to the + previously loaded interface firmware. If the interface firmware isn't loaded + previously, or if another unsuccessful FW_MGMT_IOC_INTF_LOAD_AND_VALIDATE + operation is started after loading interface firmware, then the firmware core + wouldn't allow mode-switch. Sysfs Interfaces - Authentication @@ -279,13 +280,13 @@ struct cap_ioc_authenticate { 1. CAP_IOC_GET_ENDPOINT_UID: - This ioctl shall be used the user to get the endpoint UID associated with the - Interface. All the fields of the 'struct cap_ioc_get_endpoint_uid' are + This ioctl shall be used by the user to get the endpoint UID associated with + the Interface. All the fields of the 'struct cap_ioc_get_endpoint_uid' are filled by the kernel. 2. CAP_IOC_GET_IMS_CERTIFICATE: - This ioctl shall be used the user to retrieve one of the available + This ioctl shall be used by the user to retrieve one of the available cryptographic certificates held by the Interface for use in Component Authentication. The user is required to fill the 'certificate_class' and 'certificate_id' field of the 'struct cap_ioc_get_ims_certificate' in this @@ -295,8 +296,8 @@ struct cap_ioc_authenticate { 3. CAP_IOC_AUTHENTICATE: - This ioctl shall be used the user to authenticate the Module attached to an - Interface. The user needs to fill the 'auth_type', 'uid', and 'challenge' + This ioctl shall be used by the user to authenticate the Module attached to + an Interface. The user needs to fill the 'auth_type', 'uid', and 'challenge' fields of the 'struct cap_ioc_authenticate'. The other fields will be set by the kernel in response. The first 'signature_size' bytes of the 'signature' shall be read by the user and others must be discarded. -- cgit v0.10.2 From 769cb83704db127119d063b55091f782007368e7 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 11 Aug 2016 13:27:22 -0700 Subject: greybus: firmware: Remove extra parenthesis Remove the unnecessary parenthesis. Reported-by: Alex Elder <alex.elder@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/fw-download.c b/drivers/staging/greybus/fw-download.c index 16de71c..96c11aa 100644 --- a/drivers/staging/greybus/fw-download.c +++ b/drivers/staging/greybus/fw-download.c @@ -236,7 +236,7 @@ static int fw_download_find_firmware(struct gb_operation *op) } request = op->request->payload; - tag = (const char *)(request->firmware_tag); + tag = (const char *)request->firmware_tag; /* firmware_tag should be null-terminated */ if (strnlen(tag, GB_FIRMWARE_TAG_MAX_LEN) == GB_FIRMWARE_TAG_MAX_LEN) { -- cgit v0.10.2 From b2abeaa10d5711e7730bb07120dd60ae27d7b930 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 11 Aug 2016 13:27:23 -0700 Subject: greybus: firmware: s/_LEN/_SIZE Alex Elder pointed out that the macros also count the trailing NULL ('\0') character and so it should be using SIZE instead of LEN. This patch makes that change. Reported-by: Alex Elder <alex.elder@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/firmware/firmware-management b/drivers/staging/greybus/Documentation/firmware/firmware-management index ced41d2..7918257 100644 --- a/drivers/staging/greybus/Documentation/firmware/firmware-management +++ b/drivers/staging/greybus/Documentation/firmware/firmware-management @@ -104,20 +104,20 @@ Following are the IOCTLs and their data structures available to the user: struct fw_mgmt_ioc_get_intf_version { - __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_LEN]; + __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_SIZE]; __u16 major; __u16 minor; } __attribute__ ((__packed__)); struct fw_mgmt_ioc_get_backend_version { - __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_LEN]; + __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_SIZE]; __u16 major; __u16 minor; __u8 status; } __attribute__ ((__packed__)); struct fw_mgmt_ioc_intf_load_and_validate { - __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_LEN]; + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE]; __u8 load_method; __u8 status; __u16 major; @@ -125,7 +125,7 @@ struct fw_mgmt_ioc_intf_load_and_validate { } __packed; struct fw_mgmt_ioc_backend_fw_update { - __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_LEN]; + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE]; __u8 status; } __packed; diff --git a/drivers/staging/greybus/Documentation/firmware/firmware.c b/drivers/staging/greybus/Documentation/firmware/firmware.c index 5170886..ff93824 100644 --- a/drivers/staging/greybus/Documentation/firmware/firmware.c +++ b/drivers/staging/greybus/Documentation/firmware/firmware.c @@ -108,7 +108,7 @@ static int update_intf_firmware(int fd) intf_load.minor = 0; strncpy((char *)&intf_load.firmware_tag, firmware_tag, - GB_FIRMWARE_U_TAG_MAX_LEN); + GB_FIRMWARE_U_TAG_MAX_SIZE); ret = ioctl(fd, FW_MGMT_IOC_INTF_LOAD_AND_VALIDATE, &intf_load); if (ret < 0) { @@ -146,7 +146,7 @@ static int update_backend_firmware(int fd) printf("Getting Backend Firmware Version\n"); strncpy((char *)&backend_fw_info.firmware_tag, firmware_tag, - GB_FIRMWARE_U_TAG_MAX_LEN); + GB_FIRMWARE_U_TAG_MAX_SIZE); retry_fw_version: ret = ioctl(fd, FW_MGMT_IOC_GET_BACKEND_FW, &backend_fw_info); @@ -174,7 +174,7 @@ retry_fw_version: printf("Updating Backend Firmware\n"); strncpy((char *)&backend_update.firmware_tag, firmware_tag, - GB_FIRMWARE_U_TAG_MAX_LEN); + GB_FIRMWARE_U_TAG_MAX_SIZE); retry_fw_update: backend_update.status = 0; diff --git a/drivers/staging/greybus/firmware.h b/drivers/staging/greybus/firmware.h index 841a0d5..ec6bfb7 100644 --- a/drivers/staging/greybus/firmware.h +++ b/drivers/staging/greybus/firmware.h @@ -15,7 +15,7 @@ #define FW_NAME_PREFIX "gmp_" /* Length of the string in format: "FW_NAME_PREFIX""%08x_%08x_%08x_%08x_%s.tftf" */ -#define FW_NAME_LEN 56 +#define FW_NAME_SIZE 56 /* Firmware Management Protocol specific functions */ int fw_mgmt_init(void); diff --git a/drivers/staging/greybus/fw-download.c b/drivers/staging/greybus/fw-download.c index 96c11aa..1c63256 100644 --- a/drivers/staging/greybus/fw-download.c +++ b/drivers/staging/greybus/fw-download.c @@ -23,7 +23,7 @@ struct fw_request { u8 firmware_id; bool disabled; bool timedout; - char name[FW_NAME_LEN]; + char name[FW_NAME_SIZE]; const struct firmware *fw; struct list_head node; @@ -239,7 +239,7 @@ static int fw_download_find_firmware(struct gb_operation *op) tag = (const char *)request->firmware_tag; /* firmware_tag should be null-terminated */ - if (strnlen(tag, GB_FIRMWARE_TAG_MAX_LEN) == GB_FIRMWARE_TAG_MAX_LEN) { + if (strnlen(tag, GB_FIRMWARE_TAG_MAX_SIZE) == GB_FIRMWARE_TAG_MAX_SIZE) { dev_err(fw_download->parent, "firmware-tag is not null-terminated\n"); return -EINVAL; diff --git a/drivers/staging/greybus/fw-management.c b/drivers/staging/greybus/fw-management.c index 7cbe71d..3cd6cf0 100644 --- a/drivers/staging/greybus/fw-management.c +++ b/drivers/staging/greybus/fw-management.c @@ -122,16 +122,16 @@ static int fw_mgmt_interface_fw_version_operation(struct fw_mgmt *fw_mgmt, fw_info->minor = le16_to_cpu(response.minor); strncpy(fw_info->firmware_tag, response.firmware_tag, - GB_FIRMWARE_TAG_MAX_LEN); + GB_FIRMWARE_TAG_MAX_SIZE); /* * The firmware-tag should be NULL terminated, otherwise throw error but * don't fail. */ - if (fw_info->firmware_tag[GB_FIRMWARE_TAG_MAX_LEN - 1] != '\0') { + if (fw_info->firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE - 1] != '\0') { dev_err(fw_mgmt->parent, "fw-version: firmware-tag is not NULL terminated\n"); - fw_info->firmware_tag[GB_FIRMWARE_TAG_MAX_LEN - 1] = '\0'; + fw_info->firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE - 1] = '\0'; } return 0; @@ -151,13 +151,13 @@ static int fw_mgmt_load_and_validate_operation(struct fw_mgmt *fw_mgmt, } request.load_method = load_method; - strncpy(request.firmware_tag, tag, GB_FIRMWARE_TAG_MAX_LEN); + strncpy(request.firmware_tag, tag, GB_FIRMWARE_TAG_MAX_SIZE); /* * The firmware-tag should be NULL terminated, otherwise throw error and * fail. */ - if (request.firmware_tag[GB_FIRMWARE_TAG_MAX_LEN - 1] != '\0') { + if (request.firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE - 1] != '\0') { dev_err(fw_mgmt->parent, "load-and-validate: firmware-tag is not NULL terminated\n"); return -EINVAL; } @@ -249,13 +249,13 @@ static int fw_mgmt_backend_fw_version_operation(struct fw_mgmt *fw_mgmt, int ret; strncpy(request.firmware_tag, fw_info->firmware_tag, - GB_FIRMWARE_TAG_MAX_LEN); + GB_FIRMWARE_TAG_MAX_SIZE); /* * The firmware-tag should be NULL terminated, otherwise throw error and * fail. */ - if (request.firmware_tag[GB_FIRMWARE_TAG_MAX_LEN - 1] != '\0') { + if (request.firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE - 1] != '\0') { dev_err(fw_mgmt->parent, "backend-version: firmware-tag is not NULL terminated\n"); return -EINVAL; } @@ -302,13 +302,13 @@ static int fw_mgmt_backend_fw_update_operation(struct fw_mgmt *fw_mgmt, struct gb_fw_mgmt_backend_fw_update_request request; int ret; - strncpy(request.firmware_tag, tag, GB_FIRMWARE_TAG_MAX_LEN); + strncpy(request.firmware_tag, tag, GB_FIRMWARE_TAG_MAX_SIZE); /* * The firmware-tag should be NULL terminated, otherwise throw error and * fail. */ - if (request.firmware_tag[GB_FIRMWARE_TAG_MAX_LEN - 1] != '\0') { + if (request.firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE - 1] != '\0') { dev_err(fw_mgmt->parent, "backend-update: firmware-tag is not NULL terminated\n"); return -EINVAL; } diff --git a/drivers/staging/greybus/greybus_firmware.h b/drivers/staging/greybus/greybus_firmware.h index 8279651..277a2ac 100644 --- a/drivers/staging/greybus/greybus_firmware.h +++ b/drivers/staging/greybus/greybus_firmware.h @@ -57,7 +57,7 @@ #include <linux/ioctl.h> #include <linux/types.h> -#define GB_FIRMWARE_U_TAG_MAX_LEN 10 +#define GB_FIRMWARE_U_TAG_MAX_SIZE 10 #define GB_FW_U_LOAD_METHOD_UNIPRO 0x01 #define GB_FW_U_LOAD_METHOD_INTERNAL 0x02 @@ -83,20 +83,20 @@ /* IOCTL support */ struct fw_mgmt_ioc_get_intf_version { - __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_LEN]; + __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_SIZE]; __u16 major; __u16 minor; } __attribute__ ((__packed__)); struct fw_mgmt_ioc_get_backend_version { - __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_LEN]; + __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_SIZE]; __u16 major; __u16 minor; __u8 status; } __attribute__ ((__packed__)); struct fw_mgmt_ioc_intf_load_and_validate { - __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_LEN]; + __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_SIZE]; __u8 load_method; __u8 status; __u16 major; @@ -104,7 +104,7 @@ struct fw_mgmt_ioc_intf_load_and_validate { } __attribute__ ((__packed__)); struct fw_mgmt_ioc_backend_fw_update { - __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_LEN]; + __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_SIZE]; __u8 status; } __attribute__ ((__packed__)); diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 19ca1db..be97759 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -276,11 +276,11 @@ struct gb_apb_request_cport_flags { #define GB_FW_DOWNLOAD_TYPE_FETCH_FIRMWARE 0x02 #define GB_FW_DOWNLOAD_TYPE_RELEASE_FIRMWARE 0x03 -#define GB_FIRMWARE_TAG_MAX_LEN 10 +#define GB_FIRMWARE_TAG_MAX_SIZE 10 /* firmware download find firmware request/response */ struct gb_fw_download_find_firmware_request { - __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_LEN]; + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE]; } __packed; struct gb_fw_download_find_firmware_response { @@ -340,7 +340,7 @@ struct gb_fw_download_release_firmware_request { /* firmware management interface firmware version request has no payload */ struct gb_fw_mgmt_interface_fw_version_response { - __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_LEN]; + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE]; __le16 major; __le16 minor; } __packed; @@ -349,7 +349,7 @@ struct gb_fw_mgmt_interface_fw_version_response { struct gb_fw_mgmt_load_and_validate_fw_request { __u8 request_id; __u8 load_method; - __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_LEN]; + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE]; } __packed; /* firmware management load and validate firmware response has no payload*/ @@ -364,7 +364,7 @@ struct gb_fw_mgmt_loaded_fw_request { /* firmware management backend firmware version request/response */ struct gb_fw_mgmt_backend_fw_version_request { - __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_LEN]; + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE]; } __packed; struct gb_fw_mgmt_backend_fw_version_response { @@ -376,7 +376,7 @@ struct gb_fw_mgmt_backend_fw_version_response { /* firmware management backend firmware update request */ struct gb_fw_mgmt_backend_fw_update_request { __u8 request_id; - __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_LEN]; + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE]; } __packed; /* firmware management backend firmware update response has no payload */ -- cgit v0.10.2 From 0675363ac7ffe27a25bf237ce2bf1e084637a3a0 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 11 Aug 2016 13:27:24 -0700 Subject: greybus: firmware: s/should/must Replace 'should' with 'must' to clear the expectation a bit more. Reported-by: Alex Elder <alex.elder@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/fw-download.c b/drivers/staging/greybus/fw-download.c index 1c63256..2d72468 100644 --- a/drivers/staging/greybus/fw-download.c +++ b/drivers/staging/greybus/fw-download.c @@ -238,7 +238,7 @@ static int fw_download_find_firmware(struct gb_operation *op) request = op->request->payload; tag = (const char *)request->firmware_tag; - /* firmware_tag should be null-terminated */ + /* firmware_tag must be null-terminated */ if (strnlen(tag, GB_FIRMWARE_TAG_MAX_SIZE) == GB_FIRMWARE_TAG_MAX_SIZE) { dev_err(fw_download->parent, "firmware-tag is not null-terminated\n"); -- cgit v0.10.2 From ac96a609dca8b1909f93d13277dd5368e2de5a2a Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Thu, 11 Aug 2016 13:27:25 -0700 Subject: greybus: firmware: add comment to show size calculations The firmware file name's maximum length is set to 56 right now, but it isn't very much readable how we got to that value (unless someone reads that line). Update the comment to show calculations. Reported-by: Alex Elder <alex.elder@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/firmware.h b/drivers/staging/greybus/firmware.h index ec6bfb7..f4f0db1 100644 --- a/drivers/staging/greybus/firmware.h +++ b/drivers/staging/greybus/firmware.h @@ -14,7 +14,10 @@ #define FW_NAME_PREFIX "gmp_" -/* Length of the string in format: "FW_NAME_PREFIX""%08x_%08x_%08x_%08x_%s.tftf" */ +/* + * Length of the string in format: "FW_NAME_PREFIX""%08x_%08x_%08x_%08x_%s.tftf" + * (3 + 1 + 4 * (8 + 1) + 10 + 1 + 4 + 1) + */ #define FW_NAME_SIZE 56 /* Firmware Management Protocol specific functions */ -- cgit v0.10.2 From c9161d72b33ff5a3e43dd60c87adf113363866a1 Mon Sep 17 00:00:00 2001 From: Jacopo Mondi <jacopo.mondi@linaro.org> Date: Fri, 12 Aug 2016 10:05:41 +0200 Subject: greybus: camera: Remove support for legacy modules Remove support for module implementing legacy version of camera bandwidth requirements specifications, now that all available camera modules have been updated to use the new version Signed-off-by: Jacopo Mondi <jacopo.mondi@linaro.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 94b6712..e1f3046 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -265,124 +265,34 @@ static int gb_camera_get_max_pkt_size(struct gb_camera *gcam, } /* - * Temporary support for camera modules implementing legacy version - * of camera specifications - */ -static int gb_camera_configure_stream_translate_deprecated( - struct gb_camera *gcam, - void *module_resp, - struct gb_camera_configure_streams_response *resp) -{ - unsigned int i; - struct gb_camera_configure_streams_response_deprecated *dresp = - (struct gb_camera_configure_streams_response_deprecated *) - module_resp; - - if (dresp->padding != 0) { - gcam_err(gcam, "legacy response padding != 0\n"); - return -EIO; - } - - resp->num_streams = dresp->num_streams; - resp->flags = dresp->flags; - resp->data_rate = dresp->bus_freq; - - for (i = 0; i < dresp->num_streams; i++) { - const struct gb_camera_fmt_info *fmt_info; - struct gb_camera_stream_config_response *cfg; - - if (dresp->config[i].padding || - dresp->config[i].max_pkt_size) { - gcam_err(gcam, "legacy stream #%u padding != 0\n", i); - return -EIO; - } - - resp->config[i] = dresp->config[i]; - cfg = &resp->config[i]; - - /* - * As implementations of legacy version of camera protocol do - * not provide the max_pkt_size attribute, re-calculate it on - * AP side. - */ - fmt_info = gb_camera_get_format_info(cfg->format); - if (!fmt_info) { - gcam_err(gcam, "unsupported greybus image format %d\n", - cfg->format); - return -EIO; - } - - if (fmt_info->bpp == 0) { - cfg->max_pkt_size = cpu_to_le16(4096); - } else if (fmt_info->bpp > 0) { - unsigned int width = le16_to_cpu(cfg->width); - - cfg->max_pkt_size = cpu_to_le32(width * fmt_info->bpp / 8); - } - } - - return 0; -} - -/* * Validate the stream configuration response verifying padding is correctly * set and the returned number of streams is supported - * - * FIXME: The function also checks which protocol version the camera module - * implements and if it supports or not the new bandwidth requirements - * definition parameters. - * In case the camera implements the legacy version of protocol - * specifications, it gets translated to the new one. */ -static int gb_camera_configure_streams_validate_response( +static const int gb_camera_configure_streams_validate_response( struct gb_camera *gcam, - void *module_resp, - struct gb_camera_configure_streams_response *ap_resp, - unsigned int resp_size, + struct gb_camera_configure_streams_response *resp, unsigned int nstreams) { - struct gb_camera_configure_streams_response *resp; unsigned int i; - unsigned int module_resp_size = - resp_size - - sizeof(struct gb_camera_stream_config_response) * - nstreams; - - /* TODO: remove support for legacy camera modules */ - if (module_resp_size == GB_CAMERA_CONFIGURE_STREAMS_DEPRECATED_SIZE) - return gb_camera_configure_stream_translate_deprecated(gcam, - module_resp, ap_resp); - - if (module_resp_size != GB_CAMERA_CONFIGURE_STREAMS_SIZE) { - gcam_err(gcam, "unrecognized protocol version %u\n", - module_resp_size); - return -EIO; - } - - resp = (struct gb_camera_configure_streams_response *) module_resp; - *ap_resp = *resp; /* Validate the returned response structure */ - if (ap_resp->padding[0] || ap_resp->padding[1]) { + if (resp->padding[0] || resp->padding[1]) { gcam_err(gcam, "response padding != 0\n"); return -EIO; } - if (ap_resp->num_streams > nstreams) { + if (resp->num_streams > nstreams) { gcam_err(gcam, "got #streams %u > request %u\n", resp->num_streams, nstreams); return -EIO; } - for (i = 0; i < ap_resp->num_streams; i++) { + for (i = 0; i < resp->num_streams; i++) { struct gb_camera_stream_config_response *cfg = &resp->config[i]; - if (cfg->padding) { gcam_err(gcam, "stream #%u padding != 0\n", i); return -EIO; } - - ap_resp->config[i] = *cfg; } return 0; @@ -616,12 +526,10 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, { struct gb_camera_configure_streams_request *req; struct gb_camera_configure_streams_response *resp; - void *module_resp; unsigned int nstreams = *num_streams; unsigned int i; size_t req_size; size_t resp_size; - size_t module_resp_size; int ret; if (nstreams > GB_CAMERA_MAX_STREAMS) @@ -630,21 +538,11 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, req_size = sizeof(*req) + nstreams * sizeof(req->config[0]); resp_size = sizeof(*resp) + nstreams * sizeof(resp->config[0]); - /* - * FIXME: Reserve enough space for the deprecated version of the - * configure_stream response, as it is bigger than the - * newly defined one - */ - module_resp_size = GB_CAMERA_CONFIGURE_STREAMS_DEPRECATED_SIZE + - nstreams * sizeof(resp->config[0]); - req = kmalloc(req_size, GFP_KERNEL); resp = kmalloc(resp_size, GFP_KERNEL); - module_resp = kmalloc(module_resp_size, GFP_KERNEL); - if (!req || !resp || !module_resp) { + if (!req || !resp) { kfree(req); kfree(resp); - kfree(module_resp); return -ENOMEM; } @@ -676,12 +574,12 @@ static int gb_camera_configure_streams(struct gb_camera *gcam, GB_CAMERA_TYPE_CONFIGURE_STREAMS, GB_OPERATION_FLAG_SHORT_RESPONSE, req, req_size, - module_resp, &module_resp_size); + resp, &resp_size); if (ret < 0) goto done; - ret = gb_camera_configure_streams_validate_response(gcam, - module_resp, resp, module_resp_size, nstreams); + ret = gb_camera_configure_streams_validate_response(gcam, resp, + nstreams); if (ret < 0) goto done; @@ -750,7 +648,6 @@ done_skip_pm_put: mutex_unlock(&gcam->mutex); kfree(req); kfree(resp); - kfree(module_resp); return ret; } diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index be97759..dd84e75 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -1678,17 +1678,6 @@ struct gb_camera_stream_config_response { __le32 max_size; } __packed; -struct gb_camera_configure_streams_response_deprecated { - __u8 num_streams; - __u8 flags; - __u8 num_lanes; - __u8 padding; - __le32 bus_freq; - __le32 lines_per_second; - struct gb_camera_stream_config_response config[0]; -} __packed; -#define GB_CAMERA_CONFIGURE_STREAMS_DEPRECATED_SIZE 12 - struct gb_camera_configure_streams_response { __u8 num_streams; #define GB_CAMERA_CONFIGURE_STREAMS_ADJUSTED 0x01 @@ -1697,7 +1686,6 @@ struct gb_camera_configure_streams_response { __le32 data_rate; struct gb_camera_stream_config_response config[0]; }; -#define GB_CAMERA_CONFIGURE_STREAMS_SIZE 8 /* Greybus Camera Capture request payload - response has no payload */ struct gb_camera_capture_request { -- cgit v0.10.2 From 1a55f38d630285b53b83f6809c34c599d43f02c0 Mon Sep 17 00:00:00 2001 From: Wolfram Sang <wsa-dev@sang-engineering.com> Date: Thu, 11 Aug 2016 23:23:38 +0200 Subject: staging: comedi: drivers: usbduxfast: don't print error when allocating urb fails kmalloc will print enough information in case of failure. Signed-off-by: Wolfram Sang <wsa-dev@sang-engineering.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c index 10f94ec..608403c 100644 --- a/drivers/staging/comedi/drivers/usbduxfast.c +++ b/drivers/staging/comedi/drivers/usbduxfast.c @@ -946,10 +946,8 @@ static int usbduxfast_auto_attach(struct comedi_device *dev, } devpriv->urb = usb_alloc_urb(0, GFP_KERNEL); - if (!devpriv->urb) { - dev_err(dev->class_dev, "Could not alloc. urb\n"); + if (!devpriv->urb) return -ENOMEM; - } devpriv->inbuf = kmalloc(SIZEINBUF, GFP_KERNEL); if (!devpriv->inbuf) -- cgit v0.10.2 From f11055b9aeb8f7cf7c4780fd071467424a7e661d Mon Sep 17 00:00:00 2001 From: Wolfram Sang <wsa-dev@sang-engineering.com> Date: Thu, 11 Aug 2016 23:23:39 +0200 Subject: staging: media: lirc: lirc_imon: don't print error when allocating urb fails kmalloc will print enough information in case of failure. Signed-off-by: Wolfram Sang <wsa-dev@sang-engineering.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/media/lirc/lirc_imon.c b/drivers/staging/media/lirc/lirc_imon.c index ff1926c..a183e68 100644 --- a/drivers/staging/media/lirc/lirc_imon.c +++ b/drivers/staging/media/lirc/lirc_imon.c @@ -797,16 +797,11 @@ static int imon_probe(struct usb_interface *interface, goto free_rbuf; } rx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!rx_urb) { - dev_err(dev, "%s: usb_alloc_urb failed for IR urb\n", __func__); + if (!rx_urb) goto free_lirc_buf; - } tx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!tx_urb) { - dev_err(dev, "%s: usb_alloc_urb failed for display urb\n", - __func__); + if (!tx_urb) goto free_rx_urb; - } mutex_init(&context->ctx_lock); context->vfd_proto_6p = vfd_proto_6p; -- cgit v0.10.2 From 86b368dbfd8378f1a58008b92d9652c8a80e56ad Mon Sep 17 00:00:00 2001 From: Wolfram Sang <wsa-dev@sang-engineering.com> Date: Thu, 11 Aug 2016 23:23:40 +0200 Subject: staging: media: lirc: lirc_sasem: don't print error when allocating urb fails kmalloc will print enough information in case of failure. Signed-off-by: Wolfram Sang <wsa-dev@sang-engineering.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/media/lirc/lirc_sasem.c b/drivers/staging/media/lirc/lirc_sasem.c index 2218d00..b080fde 100644 --- a/drivers/staging/media/lirc/lirc_sasem.c +++ b/drivers/staging/media/lirc/lirc_sasem.c @@ -758,17 +758,12 @@ static int sasem_probe(struct usb_interface *interface, } rx_urb = usb_alloc_urb(0, GFP_KERNEL); if (!rx_urb) { - dev_err(&interface->dev, - "%s: usb_alloc_urb failed for IR urb\n", __func__); alloc_status = 5; goto alloc_status_switch; } if (vfd_ep_found) { tx_urb = usb_alloc_urb(0, GFP_KERNEL); if (!tx_urb) { - dev_err(&interface->dev, - "%s: usb_alloc_urb failed for VFD urb", - __func__); alloc_status = 6; goto alloc_status_switch; } -- cgit v0.10.2 From ca47d8f3ff7b3ee5ca04e03bc22052c3d1dbd5e2 Mon Sep 17 00:00:00 2001 From: Wolfram Sang <wsa-dev@sang-engineering.com> Date: Thu, 11 Aug 2016 23:23:41 +0200 Subject: staging: most: hdm-usb: hdm_usb: don't print error when allocating urb fails kmalloc will print enough information in case of failure. Signed-off-by: Wolfram Sang <wsa-dev@sang-engineering.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index aeae071..9ec2978 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -650,10 +650,8 @@ static int hdm_enqueue(struct most_interface *iface, int channel, return -ENODEV; urb = usb_alloc_urb(NO_ISOCHRONOUS_URB, GFP_ATOMIC); - if (!urb) { - dev_err(dev, "Failed to allocate URB\n"); + if (!urb) return -ENOMEM; - } anchor = kzalloc(sizeof(*anchor), GFP_ATOMIC); if (!anchor) { -- cgit v0.10.2 From e89549b91e484fe592af3ec2b4780bed716d1c2e Mon Sep 17 00:00:00 2001 From: Wolfram Sang <wsa-dev@sang-engineering.com> Date: Thu, 11 Aug 2016 23:23:42 +0200 Subject: staging: rtl8192u: r8192U_core: don't print error when allocating urb fails kmalloc will print enough information in case of failure. Signed-off-by: Wolfram Sang <wsa-dev@sang-engineering.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c index dd0970f..7af1af8 100644 --- a/drivers/staging/rtl8192u/r8192U_core.c +++ b/drivers/staging/rtl8192u/r8192U_core.c @@ -1702,11 +1702,8 @@ short rtl8192_tx(struct net_device *dev, struct sk_buff *skb) } if (bSend0Byte) { tx_urb_zero = usb_alloc_urb(0, GFP_ATOMIC); - if (!tx_urb_zero) { - RT_TRACE(COMP_ERR, - "can't alloc urb for zero byte\n"); + if (!tx_urb_zero) return -ENOMEM; - } usb_fill_bulk_urb(tx_urb_zero, udev, usb_sndbulkpipe(udev, idx_pipe), &zero, 0, tx_zero_isr, dev); -- cgit v0.10.2 From 68d81dea4fc105666516146f6c5e91aa0fe1be02 Mon Sep 17 00:00:00 2001 From: Wolfram Sang <wsa-dev@sang-engineering.com> Date: Thu, 11 Aug 2016 23:23:43 +0200 Subject: staging: vt6656: main_usb: don't print error when allocating urb fails kmalloc will print enough information in case of failure. Signed-off-by: Wolfram Sang <wsa-dev@sang-engineering.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index ac4fecb..0594828 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -440,10 +440,8 @@ static bool vnt_alloc_bufs(struct vnt_private *priv) /* allocate URBs */ tx_context->urb = usb_alloc_urb(0, GFP_KERNEL); - if (!tx_context->urb) { - dev_err(&priv->usb->dev, "alloc tx urb failed\n"); + if (!tx_context->urb) goto free_tx; - } tx_context->in_use = false; } @@ -462,10 +460,8 @@ static bool vnt_alloc_bufs(struct vnt_private *priv) /* allocate URBs */ rcb->urb = usb_alloc_urb(0, GFP_KERNEL); - if (!rcb->urb) { - dev_err(&priv->usb->dev, "Failed to alloc rx urb\n"); + if (!rcb->urb) goto free_rx_tx; - } rcb->skb = dev_alloc_skb(priv->rx_buf_sz); if (!rcb->skb) @@ -479,10 +475,8 @@ static bool vnt_alloc_bufs(struct vnt_private *priv) } priv->interrupt_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!priv->interrupt_urb) { - dev_err(&priv->usb->dev, "Failed to alloc int urb\n"); + if (!priv->interrupt_urb) goto free_rx_tx; - } priv->int_buf.data_buf = kmalloc(MAX_INTERRUPT_SIZE, GFP_KERNEL); if (!priv->int_buf.data_buf) { -- cgit v0.10.2 From 58043f2527fe012e48ce30a5386c9763c88e5dd3 Mon Sep 17 00:00:00 2001 From: Markus Elfring <elfring@users.sourceforge.net> Date: Sun, 17 Jul 2016 13:14:57 +0200 Subject: staging: ks7010: Delete unnecessary checks before the function call "kfree" The kfree() function tests whether its argument is NULL and then returns immediately. Thus the test around the calls is not needed. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring <elfring@users.sourceforge.net> Acked-by: Wolfram Sang <wsa@the-dreams.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c index b7337fd..7da6c84 100644 --- a/drivers/staging/ks7010/ks7010_sdio.c +++ b/drivers/staging/ks7010/ks7010_sdio.c @@ -732,8 +732,7 @@ static int ks7010_sdio_update_index(struct ks_wlan_private *priv, u32 index) goto error_out; } error_out: - if (data_buf) - kfree(data_buf); + kfree(data_buf); return rc; } @@ -763,8 +762,7 @@ static int ks7010_sdio_data_compare(struct ks_wlan_private *priv, u32 address, goto error_out; } error_out: - if (read_buf) - kfree(read_buf); + kfree(read_buf); return rc; } @@ -879,8 +877,7 @@ static int ks7010_upload_firmware(struct ks_wlan_private *priv, release_firmware(fw_entry); error_out0: sdio_release_host(card->func); - if (rom_buf) - kfree(rom_buf); + kfree(rom_buf); return rc; } @@ -1199,9 +1196,7 @@ static void ks7010_sdio_remove(struct sdio_func *func) unregister_netdev(netdev); trx_device_exit(priv); - if (priv->ks_wlan_hw.read_buf) { - kfree(priv->ks_wlan_hw.read_buf); - } + kfree(priv->ks_wlan_hw.read_buf); free_netdev(priv->net_dev); card->priv = NULL; } -- cgit v0.10.2 From eeed92c0c0829e63c04a9f2c0c1926a4a48f6c0a Mon Sep 17 00:00:00 2001 From: Markus Elfring <elfring@users.sourceforge.net> Date: Sun, 17 Jul 2016 13:38:46 +0200 Subject: staging: ks7010: Delete unnecessary assignments for buffer variables A few variables were assigned a null pointer despite of the detail that they were immediately reassigned by the following statement. Thus remove such unnecessary assignments. Signed-off-by: Markus Elfring <elfring@users.sourceforge.net> Reviewed-by: Wolfram Sang <wsa@the-dreams.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c index 7da6c84..3622fba 100644 --- a/drivers/staging/ks7010/ks7010_sdio.c +++ b/drivers/staging/ks7010/ks7010_sdio.c @@ -711,7 +711,6 @@ static int ks7010_sdio_update_index(struct ks_wlan_private *priv, u32 index) int rc = 0; int retval; unsigned char *data_buf; - data_buf = NULL; data_buf = kmalloc(sizeof(u32), GFP_KERNEL); if (!data_buf) { @@ -743,7 +742,7 @@ static int ks7010_sdio_data_compare(struct ks_wlan_private *priv, u32 address, int rc = 0; int retval; unsigned char *read_buf; - read_buf = NULL; + read_buf = kmalloc(ROM_BUFF_SIZE, GFP_KERNEL); if (!read_buf) { rc = 1; @@ -776,8 +775,6 @@ static int ks7010_upload_firmware(struct ks_wlan_private *priv, int length; const struct firmware *fw_entry = NULL; - rom_buf = NULL; - /* buffer allocate */ rom_buf = kmalloc(ROM_BUFF_SIZE, GFP_KERNEL); if (!rom_buf) { -- cgit v0.10.2 From 695872eae5cb8292ad5a748451453468f0576001 Mon Sep 17 00:00:00 2001 From: Markus Elfring <elfring@users.sourceforge.net> Date: Sun, 17 Jul 2016 19:26:15 +0200 Subject: staging: ks7010: Delete a variable in write_to_device() The local variable "rc" was assigned a zero at one place. But it was not read within this function. Thus delete it. Signed-off-by: Markus Elfring <elfring@users.sourceforge.net> Reviewed-by: Wolfram Sang <wsa@the-dreams.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c index 3622fba..a0facfc 100644 --- a/drivers/staging/ks7010/ks7010_sdio.c +++ b/drivers/staging/ks7010/ks7010_sdio.c @@ -297,11 +297,10 @@ static int enqueue_txdev(struct ks_wlan_private *priv, unsigned char *p, static int write_to_device(struct ks_wlan_private *priv, unsigned char *buffer, unsigned long size) { - int rc, retval; + int retval; unsigned char rw_data; struct hostif_hdr *hdr; hdr = (struct hostif_hdr *)buffer; - rc = 0; DPRINTK(4, "size=%d\n", hdr->size); if (hdr->event < HIF_DATA_REQ || HIF_REQ_MAX < hdr->event) { -- cgit v0.10.2 From 6bef3f01398dc12532873f8b2376dba1339908bb Mon Sep 17 00:00:00 2001 From: Bing Sun <sunbing@redflag-linux.com> Date: Tue, 19 Jul 2016 09:51:06 +0800 Subject: Staging: ks7010: michael_mic: fixed macros coding style issue Fixed coding style issue: Enclose multiple statements macros definition in a do while loop. Use one space around binary operators. Signed-off-by: Bing Sun <sunbing@redflag-linux.com> Reviewed-by: Wolfram Sang <wsa@the-dreams.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/michael_mic.c b/drivers/staging/ks7010/michael_mic.c index e14c109..d332678 100644 --- a/drivers/staging/ks7010/michael_mic.c +++ b/drivers/staging/ks7010/michael_mic.c @@ -20,15 +20,21 @@ #define getUInt32( A, B ) (uint32_t)(A[B+0] << 0) + (A[B+1] << 8) + (A[B+2] << 16) + (A[B+3] << 24) // Convert from UInt32 to Byte[] in a portable way -#define putUInt32( A, B, C ) A[B+0] = (uint8_t) (C & 0xff); \ - A[B+1] = (uint8_t) ((C>>8) & 0xff); \ - A[B+2] = (uint8_t) ((C>>16) & 0xff); \ - A[B+3] = (uint8_t) ((C>>24) & 0xff) +#define putUInt32(A, B, C) \ +do { \ + A[B + 0] = (uint8_t)(C & 0xff); \ + A[B + 1] = (uint8_t)((C >> 8) & 0xff); \ + A[B + 2] = (uint8_t)((C >> 16) & 0xff); \ + A[B + 3] = (uint8_t)((C >> 24) & 0xff); \ +} while (0) // Reset the state to the empty message. -#define MichaelClear( A ) A->L = A->K0; \ - A->R = A->K1; \ - A->nBytesInM = 0; +#define MichaelClear(A) \ +do { \ + A->L = A->K0; \ + A->R = A->K1; \ + A->nBytesInM = 0; \ +} while (0) static void MichaelInitializeFunction(struct michel_mic_t *Mic, uint8_t * key) -- cgit v0.10.2 From 803394d03b43ba0ef4a9ed148de19c01d87cd13a Mon Sep 17 00:00:00 2001 From: Colin Ian King <colin.king@canonical.com> Date: Sat, 13 Aug 2016 19:52:38 +0100 Subject: staging: ks7010: do not dereference priv if priv is null priv is being dereferenced before a check for it being null is made, so there is a possibililty a null pointer deference can occur. Instead, only dereference priv if it is non-null. Signed-off-by: Colin Ian King <colin.king@canonical.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c index a0facfc..47b69cb 100644 --- a/drivers/staging/ks7010/ks7010_sdio.c +++ b/drivers/staging/ks7010/ks7010_sdio.c @@ -1134,7 +1134,6 @@ static void ks7010_sdio_remove(struct sdio_func *func) int ret; struct ks_sdio_card *card; struct ks_wlan_private *priv; - struct net_device *netdev; DPRINTK(1, "ks7010_sdio_remove()\n"); card = sdio_get_drvdata(func); @@ -1144,8 +1143,9 @@ static void ks7010_sdio_remove(struct sdio_func *func) DPRINTK(1, "priv = card->priv\n"); priv = card->priv; - netdev = priv->net_dev; if (priv) { + struct net_device *netdev = priv->net_dev; + ks_wlan_net_stop(netdev); DPRINTK(1, "ks_wlan_net_stop\n"); -- cgit v0.10.2 From c7df077b6d6db8d3bed1d5de2707f3386198ae0d Mon Sep 17 00:00:00 2001 From: Laura Abbott <labbott@redhat.com> Date: Mon, 8 Aug 2016 09:52:54 -0700 Subject: staging: android: ion: Get rid of ion_sg_table The ion_sg_table interface is mostly a reimplementation of what dma_buf is doing. Clients should be using dma_buf APIs instead. Signed-off-by: Laura Abbott <labbott@redhat.com> Reviewed-by: Benjamin Gaignard <benjamin.gaignard@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index a2cf93b..95b18ac 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -917,26 +917,6 @@ void ion_client_destroy(struct ion_client *client) } EXPORT_SYMBOL(ion_client_destroy); -struct sg_table *ion_sg_table(struct ion_client *client, - struct ion_handle *handle) -{ - struct ion_buffer *buffer; - struct sg_table *table; - - mutex_lock(&client->lock); - if (!ion_handle_validate(client, handle)) { - pr_err("%s: invalid handle passed to map_dma.\n", - __func__); - mutex_unlock(&client->lock); - return ERR_PTR(-EINVAL); - } - buffer = handle->buffer; - table = buffer->sg_table; - mutex_unlock(&client->lock); - return table; -} -EXPORT_SYMBOL(ion_sg_table); - static void ion_buffer_sync_for_device(struct ion_buffer *buffer, struct device *dev, enum dma_data_direction direction); diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index a1331fc..225c34a 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -149,17 +149,6 @@ int ion_phys(struct ion_client *client, struct ion_handle *handle, ion_phys_addr_t *addr, size_t *len); /** - * ion_map_dma - return an sg_table describing a handle - * @client: the client - * @handle: the handle - * - * This function returns the sg_table describing - * a particular ion handle. - */ -struct sg_table *ion_sg_table(struct ion_client *client, - struct ion_handle *handle); - -/** * ion_map_kernel - create mapping for the given handle * @client: the client * @handle: handle to map -- cgit v0.10.2 From da792ccb63d69abd0c6c84857666a086a38d1ef9 Mon Sep 17 00:00:00 2001 From: Laura Abbott <labbott@redhat.com> Date: Mon, 8 Aug 2016 09:52:55 -0700 Subject: staging: android: ion: Drop ion_phys interface ion_phys was an interface used for older legacy behavior. sg_tables are the standard now. Get rid of it. Signed-off-by: Laura Abbott <labbott@redhat.com> Reviewed-by: Benjamin Gaignard <benjamin.gaignard@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 95b18ac..bcf113f 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -576,32 +576,6 @@ void ion_free(struct ion_client *client, struct ion_handle *handle) } EXPORT_SYMBOL(ion_free); -int ion_phys(struct ion_client *client, struct ion_handle *handle, - ion_phys_addr_t *addr, size_t *len) -{ - struct ion_buffer *buffer; - int ret; - - mutex_lock(&client->lock); - if (!ion_handle_validate(client, handle)) { - mutex_unlock(&client->lock); - return -EINVAL; - } - - buffer = handle->buffer; - - if (!buffer->heap->ops->phys) { - pr_err("%s: ion_phys is not implemented by this heap (name=%s, type=%d).\n", - __func__, buffer->heap->name, buffer->heap->type); - mutex_unlock(&client->lock); - return -ENODEV; - } - mutex_unlock(&client->lock); - ret = buffer->heap->ops->phys(buffer->heap, buffer, addr, len); - return ret; -} -EXPORT_SYMBOL(ion_phys); - static void *ion_buffer_kmap_get(struct ion_buffer *buffer) { void *vaddr; diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index 225c34a..97eb7a7 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -130,25 +130,6 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, void ion_free(struct ion_client *client, struct ion_handle *handle); /** - * ion_phys - returns the physical address and len of a handle - * @client: the client - * @handle: the handle - * @addr: a pointer to put the address in - * @len: a pointer to put the length in - * - * This function queries the heap for a particular handle to get the - * handle's physical address. It't output is only correct if - * a heap returns physically contiguous memory -- in other cases - * this api should not be implemented -- ion_sg_table should be used - * instead. Returns -EINVAL if the handle is invalid. This has - * no implications on the reference counting of the handle -- - * the returned value may not be valid if the caller is not - * holding a reference. - */ -int ion_phys(struct ion_client *client, struct ion_handle *handle, - ion_phys_addr_t *addr, size_t *len); - -/** * ion_map_kernel - create mapping for the given handle * @client: the client * @handle: handle to map diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index 1fb0d81..25b969b 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -56,19 +56,6 @@ void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr, gen_pool_free(carveout_heap->pool, addr, size); } -static int ion_carveout_heap_phys(struct ion_heap *heap, - struct ion_buffer *buffer, - ion_phys_addr_t *addr, size_t *len) -{ - struct sg_table *table = buffer->priv_virt; - struct page *page = sg_page(table->sgl); - ion_phys_addr_t paddr = PFN_PHYS(page_to_pfn(page)); - - *addr = paddr; - *len = buffer->size; - return 0; -} - static int ion_carveout_heap_allocate(struct ion_heap *heap, struct ion_buffer *buffer, unsigned long size, unsigned long align, @@ -138,7 +125,6 @@ static void ion_carveout_heap_unmap_dma(struct ion_heap *heap, static struct ion_heap_ops carveout_heap_ops = { .allocate = ion_carveout_heap_allocate, .free = ion_carveout_heap_free, - .phys = ion_carveout_heap_phys, .map_dma = ion_carveout_heap_map_dma, .unmap_dma = ion_carveout_heap_unmap_dma, .map_user = ion_heap_map_user, diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c index a3446da..0828e33 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -105,23 +105,6 @@ static void ion_cma_free(struct ion_buffer *buffer) kfree(info); } -/* return physical address in addr */ -static int ion_cma_phys(struct ion_heap *heap, struct ion_buffer *buffer, - ion_phys_addr_t *addr, size_t *len) -{ - struct ion_cma_heap *cma_heap = to_cma_heap(buffer->heap); - struct device *dev = cma_heap->dev; - struct ion_cma_buffer_info *info = buffer->priv_virt; - - dev_dbg(dev, "Return buffer %p physical address %pa\n", buffer, - &info->handle); - - *addr = info->handle; - *len = buffer->size; - - return 0; -} - static struct sg_table *ion_cma_heap_map_dma(struct ion_heap *heap, struct ion_buffer *buffer) { @@ -164,7 +147,6 @@ static struct ion_heap_ops ion_cma_ops = { .free = ion_cma_free, .map_dma = ion_cma_heap_map_dma, .unmap_dma = ion_cma_heap_unmap_dma, - .phys = ion_cma_phys, .map_user = ion_cma_mmap, .map_kernel = ion_cma_map_kernel, .unmap_kernel = ion_cma_unmap_kernel, diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index 0239883..141fb0d7 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -42,8 +42,6 @@ struct ion_buffer *ion_handle_buffer(struct ion_handle *handle); * @size: size of the buffer * @priv_virt: private data to the buffer representable as * a void * - * @priv_phys: private data to the buffer representable as - * an ion_phys_addr_t (and someday a phys_addr_t) * @lock: protects the buffers cnt fields * @kmap_cnt: number of times the buffer is mapped to the kernel * @vaddr: the kernel mapping if kmap_cnt is not zero @@ -69,10 +67,7 @@ struct ion_buffer { unsigned long flags; unsigned long private_flags; size_t size; - union { - void *priv_virt; - ion_phys_addr_t priv_phys; - }; + void *priv_virt; struct mutex lock; int kmap_cnt; void *vaddr; @@ -91,8 +86,6 @@ void ion_buffer_destroy(struct ion_buffer *buffer); * struct ion_heap_ops - ops to operate on a given heap * @allocate: allocate memory * @free: free memory - * @phys get physical address of a buffer (only define on - * physically contiguous heaps) * @map_dma map the memory for dma to a scatterlist * @unmap_dma unmap the memory for dma * @map_kernel map memory to the kernel @@ -111,8 +104,6 @@ struct ion_heap_ops { struct ion_buffer *buffer, unsigned long len, unsigned long align, unsigned long flags); void (*free)(struct ion_buffer *buffer); - int (*phys)(struct ion_heap *heap, struct ion_buffer *buffer, - ion_phys_addr_t *addr, size_t *len); struct sg_table * (*map_dma)(struct ion_heap *heap, struct ion_buffer *buffer); void (*unmap_dma)(struct ion_heap *heap, struct ion_buffer *buffer); diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index b69dfc7..02bae94 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -386,17 +386,6 @@ static void ion_system_contig_heap_free(struct ion_buffer *buffer) kfree(table); } -static int ion_system_contig_heap_phys(struct ion_heap *heap, - struct ion_buffer *buffer, - ion_phys_addr_t *addr, size_t *len) -{ - struct sg_table *table = buffer->priv_virt; - struct page *page = sg_page(table->sgl); - *addr = page_to_phys(page); - *len = buffer->size; - return 0; -} - static struct sg_table *ion_system_contig_heap_map_dma(struct ion_heap *heap, struct ion_buffer *buffer) { @@ -411,7 +400,6 @@ static void ion_system_contig_heap_unmap_dma(struct ion_heap *heap, static struct ion_heap_ops kmalloc_ops = { .allocate = ion_system_contig_heap_allocate, .free = ion_system_contig_heap_free, - .phys = ion_system_contig_heap_phys, .map_dma = ion_system_contig_heap_map_dma, .unmap_dma = ion_system_contig_heap_unmap_dma, .map_kernel = ion_heap_map_kernel, -- cgit v0.10.2 From f82ad60e2b82c1efb48c3aa1eddbd516c7b2feea Mon Sep 17 00:00:00 2001 From: Laura Abbott <labbott@redhat.com> Date: Mon, 8 Aug 2016 09:52:56 -0700 Subject: staging: android: ion: Get rid of map_dma/unmap_dma The map_dma API interface was designed to generate an sg_table. Currently, every client just creates the table at allocation time and then returns the one table. Nothing happens on unmap_dma either. Just get rid of the API and assign the sg_table directly. Signed-off-by: Laura Abbott <labbott@redhat.com> Reviewed-by: Benjamin Gaignard <benjamin.gaignard@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index bcf113f..cd73082 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -205,19 +205,16 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, goto err2; } - buffer->dev = dev; - buffer->size = len; - - table = heap->ops->map_dma(heap, buffer); - if (WARN_ONCE(table == NULL, - "heap->ops->map_dma should return ERR_PTR on error")) - table = ERR_PTR(-EINVAL); - if (IS_ERR(table)) { + if (buffer->sg_table == NULL) { + WARN_ONCE(1, "This heap needs to set the sgtable"); ret = -EINVAL; goto err1; } - buffer->sg_table = table; + table = buffer->sg_table; + buffer->dev = dev; + buffer->size = len; + if (ion_buffer_fault_user_mappings(buffer)) { int num_pages = PAGE_ALIGN(buffer->size) / PAGE_SIZE; struct scatterlist *sg; @@ -226,7 +223,7 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, buffer->pages = vmalloc(sizeof(struct page *) * num_pages); if (!buffer->pages) { ret = -ENOMEM; - goto err; + goto err1; } for_each_sg(table->sgl, sg, table->nents, i) { @@ -260,8 +257,6 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, mutex_unlock(&dev->buffer_lock); return buffer; -err: - heap->ops->unmap_dma(heap, buffer); err1: heap->ops->free(buffer); err2: @@ -273,7 +268,6 @@ void ion_buffer_destroy(struct ion_buffer *buffer) { if (WARN_ON(buffer->kmap_cnt > 0)) buffer->heap->ops->unmap_kernel(buffer->heap, buffer); - buffer->heap->ops->unmap_dma(buffer->heap, buffer); buffer->heap->ops->free(buffer); vfree(buffer->pages); kfree(buffer); @@ -1542,8 +1536,7 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) { struct dentry *debug_file; - if (!heap->ops->allocate || !heap->ops->free || !heap->ops->map_dma || - !heap->ops->unmap_dma) + if (!heap->ops->allocate || !heap->ops->free) pr_err("%s: can not add heap with invalid ops struct.\n", __func__); diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index 25b969b..cc2a3b8 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -82,7 +82,7 @@ static int ion_carveout_heap_allocate(struct ion_heap *heap, } sg_set_page(table->sgl, pfn_to_page(PFN_DOWN(paddr)), size, 0); - buffer->priv_virt = table; + buffer->sg_table = table; return 0; @@ -96,7 +96,7 @@ err_free: static void ion_carveout_heap_free(struct ion_buffer *buffer) { struct ion_heap *heap = buffer->heap; - struct sg_table *table = buffer->priv_virt; + struct sg_table *table = buffer->sg_table; struct page *page = sg_page(table->sgl); ion_phys_addr_t paddr = PFN_PHYS(page_to_pfn(page)); @@ -111,22 +111,9 @@ static void ion_carveout_heap_free(struct ion_buffer *buffer) kfree(table); } -static struct sg_table *ion_carveout_heap_map_dma(struct ion_heap *heap, - struct ion_buffer *buffer) -{ - return buffer->priv_virt; -} - -static void ion_carveout_heap_unmap_dma(struct ion_heap *heap, - struct ion_buffer *buffer) -{ -} - static struct ion_heap_ops carveout_heap_ops = { .allocate = ion_carveout_heap_allocate, .free = ion_carveout_heap_free, - .map_dma = ion_carveout_heap_map_dma, - .unmap_dma = ion_carveout_heap_unmap_dma, .map_user = ion_heap_map_user, .map_kernel = ion_heap_map_kernel, .unmap_kernel = ion_heap_unmap_kernel, diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index e0553fe..560cf90 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -75,7 +75,7 @@ static int ion_chunk_heap_allocate(struct ion_heap *heap, sg = sg_next(sg); } - buffer->priv_virt = table; + buffer->sg_table = table; chunk_heap->allocated += allocated_size; return 0; err: @@ -95,7 +95,7 @@ static void ion_chunk_heap_free(struct ion_buffer *buffer) struct ion_heap *heap = buffer->heap; struct ion_chunk_heap *chunk_heap = container_of(heap, struct ion_chunk_heap, heap); - struct sg_table *table = buffer->priv_virt; + struct sg_table *table = buffer->sg_table; struct scatterlist *sg; int i; unsigned long allocated_size; @@ -117,22 +117,9 @@ static void ion_chunk_heap_free(struct ion_buffer *buffer) kfree(table); } -static struct sg_table *ion_chunk_heap_map_dma(struct ion_heap *heap, - struct ion_buffer *buffer) -{ - return buffer->priv_virt; -} - -static void ion_chunk_heap_unmap_dma(struct ion_heap *heap, - struct ion_buffer *buffer) -{ -} - static struct ion_heap_ops chunk_heap_ops = { .allocate = ion_chunk_heap_allocate, .free = ion_chunk_heap_free, - .map_dma = ion_chunk_heap_map_dma, - .unmap_dma = ion_chunk_heap_unmap_dma, .map_user = ion_heap_map_user, .map_kernel = ion_heap_map_kernel, .unmap_kernel = ion_heap_unmap_kernel, diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c index 0828e33..d5ff3a2 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -78,6 +78,7 @@ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer, goto free_table; /* keep this for memory release */ buffer->priv_virt = info; + buffer->sg_table = info->table; dev_dbg(dev, "Allocate buffer %p\n", buffer); return 0; @@ -105,19 +106,6 @@ static void ion_cma_free(struct ion_buffer *buffer) kfree(info); } -static struct sg_table *ion_cma_heap_map_dma(struct ion_heap *heap, - struct ion_buffer *buffer) -{ - struct ion_cma_buffer_info *info = buffer->priv_virt; - - return info->table; -} - -static void ion_cma_heap_unmap_dma(struct ion_heap *heap, - struct ion_buffer *buffer) -{ -} - static int ion_cma_mmap(struct ion_heap *mapper, struct ion_buffer *buffer, struct vm_area_struct *vma) { @@ -145,8 +133,6 @@ static void ion_cma_unmap_kernel(struct ion_heap *heap, static struct ion_heap_ops ion_cma_ops = { .allocate = ion_cma_allocate, .free = ion_cma_free, - .map_dma = ion_cma_heap_map_dma, - .unmap_dma = ion_cma_heap_unmap_dma, .map_user = ion_cma_mmap, .map_kernel = ion_cma_map_kernel, .unmap_kernel = ion_cma_unmap_kernel, diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index 141fb0d7..3dd9117 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -86,8 +86,6 @@ void ion_buffer_destroy(struct ion_buffer *buffer); * struct ion_heap_ops - ops to operate on a given heap * @allocate: allocate memory * @free: free memory - * @map_dma map the memory for dma to a scatterlist - * @unmap_dma unmap the memory for dma * @map_kernel map memory to the kernel * @unmap_kernel unmap memory to the kernel * @map_user map memory to userspace @@ -104,9 +102,6 @@ struct ion_heap_ops { struct ion_buffer *buffer, unsigned long len, unsigned long align, unsigned long flags); void (*free)(struct ion_buffer *buffer); - struct sg_table * (*map_dma)(struct ion_heap *heap, - struct ion_buffer *buffer); - void (*unmap_dma)(struct ion_heap *heap, struct ion_buffer *buffer); void * (*map_kernel)(struct ion_heap *heap, struct ion_buffer *buffer); void (*unmap_kernel)(struct ion_heap *heap, struct ion_buffer *buffer); int (*map_user)(struct ion_heap *mapper, struct ion_buffer *buffer, diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 02bae94..b697c6d 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -164,7 +164,7 @@ static int ion_system_heap_allocate(struct ion_heap *heap, list_del(&page->lru); } - buffer->priv_virt = table; + buffer->sg_table = table; return 0; free_table: @@ -199,17 +199,6 @@ static void ion_system_heap_free(struct ion_buffer *buffer) kfree(table); } -static struct sg_table *ion_system_heap_map_dma(struct ion_heap *heap, - struct ion_buffer *buffer) -{ - return buffer->priv_virt; -} - -static void ion_system_heap_unmap_dma(struct ion_heap *heap, - struct ion_buffer *buffer) -{ -} - static int ion_system_heap_shrink(struct ion_heap *heap, gfp_t gfp_mask, int nr_to_scan) { @@ -243,8 +232,6 @@ static int ion_system_heap_shrink(struct ion_heap *heap, gfp_t gfp_mask, static struct ion_heap_ops system_heap_ops = { .allocate = ion_system_heap_allocate, .free = ion_system_heap_free, - .map_dma = ion_system_heap_map_dma, - .unmap_dma = ion_system_heap_unmap_dma, .map_kernel = ion_heap_map_kernel, .unmap_kernel = ion_heap_unmap_kernel, .map_user = ion_heap_map_user, @@ -358,7 +345,7 @@ static int ion_system_contig_heap_allocate(struct ion_heap *heap, sg_set_page(table->sgl, page, len, 0); - buffer->priv_virt = table; + buffer->sg_table = table; ion_pages_sync_for_device(NULL, page, len, DMA_BIDIRECTIONAL); @@ -375,7 +362,7 @@ free_pages: static void ion_system_contig_heap_free(struct ion_buffer *buffer) { - struct sg_table *table = buffer->priv_virt; + struct sg_table *table = buffer->sg_table; struct page *page = sg_page(table->sgl); unsigned long pages = PAGE_ALIGN(buffer->size) >> PAGE_SHIFT; unsigned long i; @@ -386,22 +373,9 @@ static void ion_system_contig_heap_free(struct ion_buffer *buffer) kfree(table); } -static struct sg_table *ion_system_contig_heap_map_dma(struct ion_heap *heap, - struct ion_buffer *buffer) -{ - return buffer->priv_virt; -} - -static void ion_system_contig_heap_unmap_dma(struct ion_heap *heap, - struct ion_buffer *buffer) -{ -} - static struct ion_heap_ops kmalloc_ops = { .allocate = ion_system_contig_heap_allocate, .free = ion_system_contig_heap_free, - .map_dma = ion_system_contig_heap_map_dma, - .unmap_dma = ion_system_contig_heap_unmap_dma, .map_kernel = ion_heap_map_kernel, .unmap_kernel = ion_heap_unmap_kernel, .map_user = ion_heap_map_user, -- cgit v0.10.2 From 0ba5aa477f42c45e2057eb5d3eaa408d0dffec74 Mon Sep 17 00:00:00 2001 From: Laura Abbott <labbott@redhat.com> Date: Mon, 8 Aug 2016 09:52:57 -0700 Subject: staging: android: ion: Drop ion_carveout_allocate definitions ion_carveout_allocate and ion_carveout_free aren't used outside of the carveout heap. Get rid of the definitions. Signed-off-by: Laura Abbott <labbott@redhat.com> Reviewed-by: Benjamin Gaignard <benjamin.gaignard@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index cc2a3b8..c4f0795 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -25,6 +25,8 @@ #include "ion.h" #include "ion_priv.h" +#define ION_CARVEOUT_ALLOCATE_FAIL -1 + struct ion_carveout_heap { struct ion_heap heap; struct gen_pool *pool; diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index 3dd9117..25e4bb2 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -314,20 +314,6 @@ struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *); void ion_cma_heap_destroy(struct ion_heap *); /** - * kernel api to allocate/free from carveout -- used when carveout is - * used to back an architecture specific custom heap - */ -ion_phys_addr_t ion_carveout_allocate(struct ion_heap *heap, unsigned long size, - unsigned long align); -void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr, - unsigned long size); -/** - * The carveout heap returns physical addresses, since 0 may be a valid - * physical address, this is used to indicate allocation failed - */ -#define ION_CARVEOUT_ALLOCATE_FAIL -1 - -/** * functions for creating and destroying a heap pool -- allows you * to keep a pool of pre allocated memory to use from your heap. Keeping * a pool of memory that is ready for dma, ie any cached mapping have been -- cgit v0.10.2 From 04b8290f3b95a3935ed07f2954bad9c87e8fb143 Mon Sep 17 00:00:00 2001 From: Laura Abbott <labbott@redhat.com> Date: Mon, 8 Aug 2016 09:52:58 -0700 Subject: staging: android: ion: Get rid of ion_reserve ion_reserve was supposed to be used to reserve memory in board files. These days, board files are no more and there are other more controlled mechanisms for reserving memory. Get rid of this function. Signed-off-by: Laura Abbott <labbott@redhat.com> Reviewed-by: Benjamin Gaignard <benjamin.gaignard@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index cd73082..7138a5b 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -1650,37 +1650,3 @@ void ion_device_destroy(struct ion_device *dev) } EXPORT_SYMBOL(ion_device_destroy); -void __init ion_reserve(struct ion_platform_data *data) -{ - int i; - - for (i = 0; i < data->nr; i++) { - if (data->heaps[i].size == 0) - continue; - - if (data->heaps[i].base == 0) { - phys_addr_t paddr; - - paddr = memblock_alloc_base(data->heaps[i].size, - data->heaps[i].align, - MEMBLOCK_ALLOC_ANYWHERE); - if (!paddr) { - pr_err("%s: error allocating memblock for heap %d\n", - __func__, i); - continue; - } - data->heaps[i].base = paddr; - } else { - int ret = memblock_reserve(data->heaps[i].base, - data->heaps[i].size); - if (ret) - pr_err("memblock reserve of %zx@%lx failed\n", - data->heaps[i].size, - data->heaps[i].base); - } - pr_info("%s: %s reserved base %lx size %zu\n", __func__, - data->heaps[i].name, - data->heaps[i].base, - data->heaps[i].size); - } -} diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index 97eb7a7..93dafb4 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -73,17 +73,6 @@ struct ion_platform_data { }; /** - * ion_reserve() - reserve memory for ion heaps if applicable - * @data: platform data specifying starting physical address and - * size - * - * Calls memblock reserve to set aside memory for heaps that are - * located at specific memory addresses or of specific sizes not - * managed by the kernel - */ -void ion_reserve(struct ion_platform_data *data); - -/** * ion_client_create() - allocate a client and returns it * @dev: the global ion device * @name: used for debugging -- cgit v0.10.2 From a4ebee657c9be3afd35530cd4478b0fa514706d7 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan <gustavo.padovan@collabora.co.uk> Date: Thu, 11 Aug 2016 12:26:40 -0300 Subject: staging/android: do not let userspace trigger WARN_ON Closing the timeline without waiting all fences to signal is not a critical failure, it is just bad usage from userspace so avoid calling WARN_ON in this case. Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/sw_sync.c b/drivers/staging/android/sw_sync.c index 115c917..bda1f6a 100644 --- a/drivers/staging/android/sw_sync.c +++ b/drivers/staging/android/sw_sync.c @@ -176,7 +176,7 @@ static void timeline_fence_release(struct fence *fence) spin_lock_irqsave(fence->lock, flags); list_del(&pt->child_list); - if (WARN_ON_ONCE(!list_empty(&pt->active_list))) + if (!list_empty(&pt->active_list)) list_del(&pt->active_list); spin_unlock_irqrestore(fence->lock, flags); -- cgit v0.10.2 From a04f915eba944d41773146bb6c004212b29a6ace Mon Sep 17 00:00:00 2001 From: Gustavo Padovan <gustavo.padovan@collabora.co.uk> Date: Thu, 11 Aug 2016 12:26:41 -0300 Subject: staging/android: move trace/sync.h to sync_trace.h The common behaviour for trace headers is to have them in the same folder they are used, instead of creating a special trace/ directory. Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk> Reviewed-by: Eric Engestrom <eric.engestrom@imgtec.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/sw_sync.c b/drivers/staging/android/sw_sync.c index bda1f6a..92c1f8b 100644 --- a/drivers/staging/android/sw_sync.c +++ b/drivers/staging/android/sw_sync.c @@ -23,7 +23,7 @@ #include "sync_debug.h" #define CREATE_TRACE_POINTS -#include "trace/sync.h" +#include "sync_trace.h" struct sw_sync_create_fence_data { __u32 value; diff --git a/drivers/staging/android/sync_trace.h b/drivers/staging/android/sync_trace.h new file mode 100644 index 0000000..ea485f7 --- /dev/null +++ b/drivers/staging/android/sync_trace.h @@ -0,0 +1,32 @@ +#undef TRACE_SYSTEM +#define TRACE_INCLUDE_PATH ../../drivers/staging/android +#define TRACE_SYSTEM sync_trace + +#if !defined(_TRACE_SYNC_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_SYNC_H + +#include "sync_debug.h" +#include <linux/tracepoint.h> + +TRACE_EVENT(sync_timeline, + TP_PROTO(struct sync_timeline *timeline), + + TP_ARGS(timeline), + + TP_STRUCT__entry( + __string(name, timeline->name) + __field(u32, value) + ), + + TP_fast_assign( + __assign_str(name, timeline->name); + __entry->value = timeline->value; + ), + + TP_printk("name=%s value=%d", __get_str(name), __entry->value) +); + +#endif /* if !defined(_TRACE_SYNC_H) || defined(TRACE_HEADER_MULTI_READ) */ + +/* This part must be outside protection */ +#include <trace/define_trace.h> diff --git a/drivers/staging/android/trace/sync.h b/drivers/staging/android/trace/sync.h deleted file mode 100644 index 6b5ce96..0000000 --- a/drivers/staging/android/trace/sync.h +++ /dev/null @@ -1,32 +0,0 @@ -#undef TRACE_SYSTEM -#define TRACE_INCLUDE_PATH ../../drivers/staging/android/trace -#define TRACE_SYSTEM sync - -#if !defined(_TRACE_SYNC_H) || defined(TRACE_HEADER_MULTI_READ) -#define _TRACE_SYNC_H - -#include "../sync_debug.h" -#include <linux/tracepoint.h> - -TRACE_EVENT(sync_timeline, - TP_PROTO(struct sync_timeline *timeline), - - TP_ARGS(timeline), - - TP_STRUCT__entry( - __string(name, timeline->name) - __field(u32, value) - ), - - TP_fast_assign( - __assign_str(name, timeline->name); - __entry->value = timeline->value; - ), - - TP_printk("name=%s value=%d", __get_str(name), __entry->value) -); - -#endif /* if !defined(_TRACE_SYNC_H) || defined(TRACE_HEADER_MULTI_READ) */ - -/* This part must be outside protection */ -#include <trace/define_trace.h> -- cgit v0.10.2 From e912c881f13523fa696f5a7233ee3fffc66fa6a3 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan <gustavo.padovan@collabora.co.uk> Date: Thu, 11 Aug 2016 12:26:42 -0300 Subject: staging/android: prepare sw_sync files for de-staging remove file paths in the comments and add short description about each file. v2: remove file paths instead of just change them. v3: improve header description as sugggested by Eric Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk> Reviewed-by: Eric Engestrom <eric.engestrom@imgtec.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/sw_sync.c b/drivers/staging/android/sw_sync.c index 92c1f8b..039e1f4 100644 --- a/drivers/staging/android/sw_sync.c +++ b/drivers/staging/android/sw_sync.c @@ -1,5 +1,5 @@ /* - * drivers/dma-buf/sw_sync.c + * Sync File validation framework * * Copyright (C) 2012 Google, Inc. * diff --git a/drivers/staging/android/sync_debug.c b/drivers/staging/android/sync_debug.c index 4c5a855..fab9520 100644 --- a/drivers/staging/android/sync_debug.c +++ b/drivers/staging/android/sync_debug.c @@ -1,5 +1,5 @@ /* - * drivers/base/sync.c + * Sync File validation framework and debug information * * Copyright (C) 2012 Google, Inc. * diff --git a/drivers/staging/android/sync_debug.h b/drivers/staging/android/sync_debug.h index fab6639..d269aa6 100644 --- a/drivers/staging/android/sync_debug.h +++ b/drivers/staging/android/sync_debug.h @@ -1,5 +1,5 @@ /* - * include/linux/sync.h + * Sync File validation framework and debug infomation * * Copyright (C) 2012 Google, Inc. * -- cgit v0.10.2 From fc0c9a03b57efb769a74fa8b33d68d90153b5950 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan <gustavo.padovan@collabora.co.uk> Date: Thu, 11 Aug 2016 13:45:53 -0300 Subject: staging/android: add Doc for SW_SYNC ioctl interface This interface is hidden from kernel headers and it is intended for use only for testing. So testers would have to add the ioctl information internally. This is to prevent misuse of this feature. v2: take in Eric suggestions for the Documentation v3: really take in Eric suggestions Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk> Reviewed-by: Eric Engestrom <eric.engestrom@imgtec.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/sw_sync.c b/drivers/staging/android/sw_sync.c index 039e1f4..62e8e6d 100644 --- a/drivers/staging/android/sw_sync.c +++ b/drivers/staging/android/sw_sync.c @@ -25,6 +25,36 @@ #define CREATE_TRACE_POINTS #include "sync_trace.h" +/* + * SW SYNC validation framework + * + * A sync object driver that uses a 32bit counter to coordinate + * synchronization. Useful when there is no hardware primitive backing + * the synchronization. + * + * To start the framework just open: + * + * <debugfs>/sync/sw_sync + * + * That will create a sync timeline, all fences created under this timeline + * file descriptor will belong to the this timeline. + * + * The 'sw_sync' file can be opened many times as to create different + * timelines. + * + * Fences can be created with SW_SYNC_IOC_CREATE_FENCE ioctl with struct + * sw_sync_ioctl_create_fence as parameter. + * + * To increment the timeline counter, SW_SYNC_IOC_INC ioctl should be used + * with the increment as u32. This will update the last signaled value + * from the timeline and signal any fence that has a seqno smaller or equal + * to it. + * + * struct sw_sync_ioctl_create_fence + * @value: the seqno to initialise the fence with + * @name: the name of the new sync point + * @fence: return the fd of the new sync_file with the created fence + */ struct sw_sync_create_fence_data { __u32 value; char name[32]; @@ -35,6 +65,7 @@ struct sw_sync_create_fence_data { #define SW_SYNC_IOC_CREATE_FENCE _IOWR(SW_SYNC_IOC_MAGIC, 0,\ struct sw_sync_create_fence_data) + #define SW_SYNC_IOC_INC _IOW(SW_SYNC_IOC_MAGIC, 1, __u32) static const struct fence_ops timeline_fence_ops; -- cgit v0.10.2 From 35538d7822e86cb38015c21bb708a433f8814af0 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan <gustavo.padovan@collabora.co.uk> Date: Thu, 11 Aug 2016 12:26:44 -0300 Subject: dma-buf/sw_sync: de-stage SW_SYNC SW_SYNC allows to run tests on the sync_file framework via debugfs on <debugfs>/sync/sw_sync Opening and closing the file triggers creation and release of a sync timeline. To create fences on this timeline the SW_SYNC_IOC_CREATE_FENCE ioctl should be used. To increment the timeline value use SW_SYNC_IOC_INC. Also it exports Sync information on <debugfs>/sync/info Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk> Reviewed-by: Eric Engestrom <eric.engestrom@imgtec.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/dma-buf/Kconfig b/drivers/dma-buf/Kconfig index 25bcfa0..2585821 100644 --- a/drivers/dma-buf/Kconfig +++ b/drivers/dma-buf/Kconfig @@ -17,4 +17,17 @@ config SYNC_FILE Files fds, to the DRM driver for example. More details at Documentation/sync_file.txt. +config SW_SYNC + bool "Sync File Validation Framework" + default n + depends on SYNC_FILE + depends on DEBUG_FS + ---help--- + A sync object driver that uses a 32bit counter to coordinate + synchronization. Useful when there is no hardware primitive backing + the synchronization. + + WARNING: improper use of this can result in deadlocking kernel + drivers from userspace. Intended for test and debug only. + endmenu diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile index f353db2..210a10b 100644 --- a/drivers/dma-buf/Makefile +++ b/drivers/dma-buf/Makefile @@ -1,2 +1,3 @@ obj-y := dma-buf.o fence.o reservation.o seqno-fence.o fence-array.o obj-$(CONFIG_SYNC_FILE) += sync_file.o +obj-$(CONFIG_SW_SYNC) += sw_sync.o sync_debug.o diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c new file mode 100644 index 0000000..62e8e6d --- /dev/null +++ b/drivers/dma-buf/sw_sync.c @@ -0,0 +1,375 @@ +/* + * Sync File validation framework + * + * Copyright (C) 2012 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/file.h> +#include <linux/fs.h> +#include <linux/uaccess.h> +#include <linux/slab.h> +#include <linux/sync_file.h> + +#include "sync_debug.h" + +#define CREATE_TRACE_POINTS +#include "sync_trace.h" + +/* + * SW SYNC validation framework + * + * A sync object driver that uses a 32bit counter to coordinate + * synchronization. Useful when there is no hardware primitive backing + * the synchronization. + * + * To start the framework just open: + * + * <debugfs>/sync/sw_sync + * + * That will create a sync timeline, all fences created under this timeline + * file descriptor will belong to the this timeline. + * + * The 'sw_sync' file can be opened many times as to create different + * timelines. + * + * Fences can be created with SW_SYNC_IOC_CREATE_FENCE ioctl with struct + * sw_sync_ioctl_create_fence as parameter. + * + * To increment the timeline counter, SW_SYNC_IOC_INC ioctl should be used + * with the increment as u32. This will update the last signaled value + * from the timeline and signal any fence that has a seqno smaller or equal + * to it. + * + * struct sw_sync_ioctl_create_fence + * @value: the seqno to initialise the fence with + * @name: the name of the new sync point + * @fence: return the fd of the new sync_file with the created fence + */ +struct sw_sync_create_fence_data { + __u32 value; + char name[32]; + __s32 fence; /* fd of new fence */ +}; + +#define SW_SYNC_IOC_MAGIC 'W' + +#define SW_SYNC_IOC_CREATE_FENCE _IOWR(SW_SYNC_IOC_MAGIC, 0,\ + struct sw_sync_create_fence_data) + +#define SW_SYNC_IOC_INC _IOW(SW_SYNC_IOC_MAGIC, 1, __u32) + +static const struct fence_ops timeline_fence_ops; + +static inline struct sync_pt *fence_to_sync_pt(struct fence *fence) +{ + if (fence->ops != &timeline_fence_ops) + return NULL; + return container_of(fence, struct sync_pt, base); +} + +/** + * sync_timeline_create() - creates a sync object + * @name: sync_timeline name + * + * Creates a new sync_timeline. Returns the sync_timeline object or NULL in + * case of error. + */ +struct sync_timeline *sync_timeline_create(const char *name) +{ + struct sync_timeline *obj; + + obj = kzalloc(sizeof(*obj), GFP_KERNEL); + if (!obj) + return NULL; + + kref_init(&obj->kref); + obj->context = fence_context_alloc(1); + strlcpy(obj->name, name, sizeof(obj->name)); + + INIT_LIST_HEAD(&obj->child_list_head); + INIT_LIST_HEAD(&obj->active_list_head); + spin_lock_init(&obj->child_list_lock); + + sync_timeline_debug_add(obj); + + return obj; +} + +static void sync_timeline_free(struct kref *kref) +{ + struct sync_timeline *obj = + container_of(kref, struct sync_timeline, kref); + + sync_timeline_debug_remove(obj); + + kfree(obj); +} + +static void sync_timeline_get(struct sync_timeline *obj) +{ + kref_get(&obj->kref); +} + +static void sync_timeline_put(struct sync_timeline *obj) +{ + kref_put(&obj->kref, sync_timeline_free); +} + +/** + * sync_timeline_signal() - signal a status change on a sync_timeline + * @obj: sync_timeline to signal + * @inc: num to increment on timeline->value + * + * A sync implementation should call this any time one of it's fences + * has signaled or has an error condition. + */ +static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc) +{ + unsigned long flags; + struct sync_pt *pt, *next; + + trace_sync_timeline(obj); + + spin_lock_irqsave(&obj->child_list_lock, flags); + + obj->value += inc; + + list_for_each_entry_safe(pt, next, &obj->active_list_head, + active_list) { + if (fence_is_signaled_locked(&pt->base)) + list_del_init(&pt->active_list); + } + + spin_unlock_irqrestore(&obj->child_list_lock, flags); +} + +/** + * sync_pt_create() - creates a sync pt + * @parent: fence's parent sync_timeline + * @size: size to allocate for this pt + * @inc: value of the fence + * + * Creates a new sync_pt as a child of @parent. @size bytes will be + * allocated allowing for implementation specific data to be kept after + * the generic sync_timeline struct. Returns the sync_pt object or + * NULL in case of error. + */ +static struct sync_pt *sync_pt_create(struct sync_timeline *obj, int size, + unsigned int value) +{ + unsigned long flags; + struct sync_pt *pt; + + if (size < sizeof(*pt)) + return NULL; + + pt = kzalloc(size, GFP_KERNEL); + if (!pt) + return NULL; + + spin_lock_irqsave(&obj->child_list_lock, flags); + sync_timeline_get(obj); + fence_init(&pt->base, &timeline_fence_ops, &obj->child_list_lock, + obj->context, value); + list_add_tail(&pt->child_list, &obj->child_list_head); + INIT_LIST_HEAD(&pt->active_list); + spin_unlock_irqrestore(&obj->child_list_lock, flags); + return pt; +} + +static const char *timeline_fence_get_driver_name(struct fence *fence) +{ + return "sw_sync"; +} + +static const char *timeline_fence_get_timeline_name(struct fence *fence) +{ + struct sync_timeline *parent = fence_parent(fence); + + return parent->name; +} + +static void timeline_fence_release(struct fence *fence) +{ + struct sync_pt *pt = fence_to_sync_pt(fence); + struct sync_timeline *parent = fence_parent(fence); + unsigned long flags; + + spin_lock_irqsave(fence->lock, flags); + list_del(&pt->child_list); + if (!list_empty(&pt->active_list)) + list_del(&pt->active_list); + spin_unlock_irqrestore(fence->lock, flags); + + sync_timeline_put(parent); + fence_free(fence); +} + +static bool timeline_fence_signaled(struct fence *fence) +{ + struct sync_timeline *parent = fence_parent(fence); + + return (fence->seqno > parent->value) ? false : true; +} + +static bool timeline_fence_enable_signaling(struct fence *fence) +{ + struct sync_pt *pt = fence_to_sync_pt(fence); + struct sync_timeline *parent = fence_parent(fence); + + if (timeline_fence_signaled(fence)) + return false; + + list_add_tail(&pt->active_list, &parent->active_list_head); + return true; +} + +static void timeline_fence_value_str(struct fence *fence, + char *str, int size) +{ + snprintf(str, size, "%d", fence->seqno); +} + +static void timeline_fence_timeline_value_str(struct fence *fence, + char *str, int size) +{ + struct sync_timeline *parent = fence_parent(fence); + + snprintf(str, size, "%d", parent->value); +} + +static const struct fence_ops timeline_fence_ops = { + .get_driver_name = timeline_fence_get_driver_name, + .get_timeline_name = timeline_fence_get_timeline_name, + .enable_signaling = timeline_fence_enable_signaling, + .signaled = timeline_fence_signaled, + .wait = fence_default_wait, + .release = timeline_fence_release, + .fence_value_str = timeline_fence_value_str, + .timeline_value_str = timeline_fence_timeline_value_str, +}; + +/* + * *WARNING* + * + * improper use of this can result in deadlocking kernel drivers from userspace. + */ + +/* opening sw_sync create a new sync obj */ +static int sw_sync_debugfs_open(struct inode *inode, struct file *file) +{ + struct sync_timeline *obj; + char task_comm[TASK_COMM_LEN]; + + get_task_comm(task_comm, current); + + obj = sync_timeline_create(task_comm); + if (!obj) + return -ENOMEM; + + file->private_data = obj; + + return 0; +} + +static int sw_sync_debugfs_release(struct inode *inode, struct file *file) +{ + struct sync_timeline *obj = file->private_data; + + smp_wmb(); + + sync_timeline_put(obj); + return 0; +} + +static long sw_sync_ioctl_create_fence(struct sync_timeline *obj, + unsigned long arg) +{ + int fd = get_unused_fd_flags(O_CLOEXEC); + int err; + struct sync_pt *pt; + struct sync_file *sync_file; + struct sw_sync_create_fence_data data; + + if (fd < 0) + return fd; + + if (copy_from_user(&data, (void __user *)arg, sizeof(data))) { + err = -EFAULT; + goto err; + } + + pt = sync_pt_create(obj, sizeof(*pt), data.value); + if (!pt) { + err = -ENOMEM; + goto err; + } + + sync_file = sync_file_create(&pt->base); + if (!sync_file) { + fence_put(&pt->base); + err = -ENOMEM; + goto err; + } + + data.fence = fd; + if (copy_to_user((void __user *)arg, &data, sizeof(data))) { + fput(sync_file->file); + err = -EFAULT; + goto err; + } + + fd_install(fd, sync_file->file); + + return 0; + +err: + put_unused_fd(fd); + return err; +} + +static long sw_sync_ioctl_inc(struct sync_timeline *obj, unsigned long arg) +{ + u32 value; + + if (copy_from_user(&value, (void __user *)arg, sizeof(value))) + return -EFAULT; + + sync_timeline_signal(obj, value); + + return 0; +} + +static long sw_sync_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct sync_timeline *obj = file->private_data; + + switch (cmd) { + case SW_SYNC_IOC_CREATE_FENCE: + return sw_sync_ioctl_create_fence(obj, arg); + + case SW_SYNC_IOC_INC: + return sw_sync_ioctl_inc(obj, arg); + + default: + return -ENOTTY; + } +} + +const struct file_operations sw_sync_debugfs_fops = { + .open = sw_sync_debugfs_open, + .release = sw_sync_debugfs_release, + .unlocked_ioctl = sw_sync_ioctl, + .compat_ioctl = sw_sync_ioctl, +}; diff --git a/drivers/dma-buf/sync_debug.c b/drivers/dma-buf/sync_debug.c new file mode 100644 index 0000000..fab9520 --- /dev/null +++ b/drivers/dma-buf/sync_debug.c @@ -0,0 +1,230 @@ +/* + * Sync File validation framework and debug information + * + * Copyright (C) 2012 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/debugfs.h> +#include "sync_debug.h" + +static struct dentry *dbgfs; + +static LIST_HEAD(sync_timeline_list_head); +static DEFINE_SPINLOCK(sync_timeline_list_lock); +static LIST_HEAD(sync_file_list_head); +static DEFINE_SPINLOCK(sync_file_list_lock); + +void sync_timeline_debug_add(struct sync_timeline *obj) +{ + unsigned long flags; + + spin_lock_irqsave(&sync_timeline_list_lock, flags); + list_add_tail(&obj->sync_timeline_list, &sync_timeline_list_head); + spin_unlock_irqrestore(&sync_timeline_list_lock, flags); +} + +void sync_timeline_debug_remove(struct sync_timeline *obj) +{ + unsigned long flags; + + spin_lock_irqsave(&sync_timeline_list_lock, flags); + list_del(&obj->sync_timeline_list); + spin_unlock_irqrestore(&sync_timeline_list_lock, flags); +} + +void sync_file_debug_add(struct sync_file *sync_file) +{ + unsigned long flags; + + spin_lock_irqsave(&sync_file_list_lock, flags); + list_add_tail(&sync_file->sync_file_list, &sync_file_list_head); + spin_unlock_irqrestore(&sync_file_list_lock, flags); +} + +void sync_file_debug_remove(struct sync_file *sync_file) +{ + unsigned long flags; + + spin_lock_irqsave(&sync_file_list_lock, flags); + list_del(&sync_file->sync_file_list); + spin_unlock_irqrestore(&sync_file_list_lock, flags); +} + +static const char *sync_status_str(int status) +{ + if (status == 0) + return "signaled"; + + if (status > 0) + return "active"; + + return "error"; +} + +static void sync_print_fence(struct seq_file *s, struct fence *fence, bool show) +{ + int status = 1; + struct sync_timeline *parent = fence_parent(fence); + + if (fence_is_signaled_locked(fence)) + status = fence->status; + + seq_printf(s, " %s%sfence %s", + show ? parent->name : "", + show ? "_" : "", + sync_status_str(status)); + + if (status <= 0) { + struct timespec64 ts64 = + ktime_to_timespec64(fence->timestamp); + + seq_printf(s, "@%lld.%09ld", (s64)ts64.tv_sec, ts64.tv_nsec); + } + + if (fence->ops->timeline_value_str && + fence->ops->fence_value_str) { + char value[64]; + bool success; + + fence->ops->fence_value_str(fence, value, sizeof(value)); + success = strlen(value); + + if (success) { + seq_printf(s, ": %s", value); + + fence->ops->timeline_value_str(fence, value, + sizeof(value)); + + if (strlen(value)) + seq_printf(s, " / %s", value); + } + } + + seq_puts(s, "\n"); +} + +static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj) +{ + struct list_head *pos; + unsigned long flags; + + seq_printf(s, "%s: %d\n", obj->name, obj->value); + + spin_lock_irqsave(&obj->child_list_lock, flags); + list_for_each(pos, &obj->child_list_head) { + struct sync_pt *pt = + container_of(pos, struct sync_pt, child_list); + sync_print_fence(s, &pt->base, false); + } + spin_unlock_irqrestore(&obj->child_list_lock, flags); +} + +static void sync_print_sync_file(struct seq_file *s, + struct sync_file *sync_file) +{ + int i; + + seq_printf(s, "[%p] %s: %s\n", sync_file, sync_file->name, + sync_status_str(atomic_read(&sync_file->status))); + + for (i = 0; i < sync_file->num_fences; ++i) + sync_print_fence(s, sync_file->cbs[i].fence, true); +} + +static int sync_debugfs_show(struct seq_file *s, void *unused) +{ + unsigned long flags; + struct list_head *pos; + + seq_puts(s, "objs:\n--------------\n"); + + spin_lock_irqsave(&sync_timeline_list_lock, flags); + list_for_each(pos, &sync_timeline_list_head) { + struct sync_timeline *obj = + container_of(pos, struct sync_timeline, + sync_timeline_list); + + sync_print_obj(s, obj); + seq_puts(s, "\n"); + } + spin_unlock_irqrestore(&sync_timeline_list_lock, flags); + + seq_puts(s, "fences:\n--------------\n"); + + spin_lock_irqsave(&sync_file_list_lock, flags); + list_for_each(pos, &sync_file_list_head) { + struct sync_file *sync_file = + container_of(pos, struct sync_file, sync_file_list); + + sync_print_sync_file(s, sync_file); + seq_puts(s, "\n"); + } + spin_unlock_irqrestore(&sync_file_list_lock, flags); + return 0; +} + +static int sync_info_debugfs_open(struct inode *inode, struct file *file) +{ + return single_open(file, sync_debugfs_show, inode->i_private); +} + +static const struct file_operations sync_info_debugfs_fops = { + .open = sync_info_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static __init int sync_debugfs_init(void) +{ + dbgfs = debugfs_create_dir("sync", NULL); + + /* + * The debugfs files won't ever get removed and thus, there is + * no need to protect it against removal races. The use of + * debugfs_create_file_unsafe() is actually safe here. + */ + debugfs_create_file_unsafe("info", 0444, dbgfs, NULL, + &sync_info_debugfs_fops); + debugfs_create_file_unsafe("sw_sync", 0644, dbgfs, NULL, + &sw_sync_debugfs_fops); + + return 0; +} +late_initcall(sync_debugfs_init); + +#define DUMP_CHUNK 256 +static char sync_dump_buf[64 * 1024]; +void sync_dump(void) +{ + struct seq_file s = { + .buf = sync_dump_buf, + .size = sizeof(sync_dump_buf) - 1, + }; + int i; + + sync_debugfs_show(&s, NULL); + + for (i = 0; i < s.count; i += DUMP_CHUNK) { + if ((s.count - i) > DUMP_CHUNK) { + char c = s.buf[i + DUMP_CHUNK]; + + s.buf[i + DUMP_CHUNK] = 0; + pr_cont("%s", s.buf + i); + s.buf[i + DUMP_CHUNK] = c; + } else { + s.buf[s.count] = 0; + pr_cont("%s", s.buf + i); + } + } +} diff --git a/drivers/dma-buf/sync_debug.h b/drivers/dma-buf/sync_debug.h new file mode 100644 index 0000000..d269aa6 --- /dev/null +++ b/drivers/dma-buf/sync_debug.h @@ -0,0 +1,84 @@ +/* + * Sync File validation framework and debug infomation + * + * Copyright (C) 2012 Google, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _LINUX_SYNC_H +#define _LINUX_SYNC_H + +#include <linux/list.h> +#include <linux/spinlock.h> +#include <linux/fence.h> + +#include <linux/sync_file.h> +#include <uapi/linux/sync_file.h> + +/** + * struct sync_timeline - sync object + * @kref: reference count on fence. + * @name: name of the sync_timeline. Useful for debugging + * @child_list_head: list of children sync_pts for this sync_timeline + * @child_list_lock: lock protecting @child_list_head and fence.status + * @active_list_head: list of active (unsignaled/errored) sync_pts + * @sync_timeline_list: membership in global sync_timeline_list + */ +struct sync_timeline { + struct kref kref; + char name[32]; + + /* protected by child_list_lock */ + u64 context; + int value; + + struct list_head child_list_head; + spinlock_t child_list_lock; + + struct list_head active_list_head; + + struct list_head sync_timeline_list; +}; + +static inline struct sync_timeline *fence_parent(struct fence *fence) +{ + return container_of(fence->lock, struct sync_timeline, + child_list_lock); +} + +/** + * struct sync_pt - sync_pt object + * @base: base fence object + * @child_list: sync timeline child's list + * @active_list: sync timeline active child's list + */ +struct sync_pt { + struct fence base; + struct list_head child_list; + struct list_head active_list; +}; + +#ifdef CONFIG_SW_SYNC + +extern const struct file_operations sw_sync_debugfs_fops; + +void sync_timeline_debug_add(struct sync_timeline *obj); +void sync_timeline_debug_remove(struct sync_timeline *obj); +void sync_file_debug_add(struct sync_file *fence); +void sync_file_debug_remove(struct sync_file *fence); +void sync_dump(void); + +#else +# define sync_timeline_debug_add(obj) +# define sync_timeline_debug_remove(obj) +# define sync_file_debug_add(fence) +# define sync_file_debug_remove(fence) +# define sync_dump() +#endif + +#endif /* _LINUX_SYNC_H */ diff --git a/drivers/dma-buf/sync_trace.h b/drivers/dma-buf/sync_trace.h new file mode 100644 index 0000000..d13d59f --- /dev/null +++ b/drivers/dma-buf/sync_trace.h @@ -0,0 +1,32 @@ +#undef TRACE_SYSTEM +#define TRACE_INCLUDE_PATH ../../drivers/dma-buf +#define TRACE_SYSTEM sync_trace + +#if !defined(_TRACE_SYNC_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_SYNC_H + +#include "sync_debug.h" +#include <linux/tracepoint.h> + +TRACE_EVENT(sync_timeline, + TP_PROTO(struct sync_timeline *timeline), + + TP_ARGS(timeline), + + TP_STRUCT__entry( + __string(name, timeline->name) + __field(u32, value) + ), + + TP_fast_assign( + __assign_str(name, timeline->name); + __entry->value = timeline->value; + ), + + TP_printk("name=%s value=%d", __get_str(name), __entry->value) +); + +#endif /* if !defined(_TRACE_SYNC_H) || defined(TRACE_HEADER_MULTI_READ) */ + +/* This part must be outside protection */ +#include <trace/define_trace.h> diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index 06e41d2..6c00d6f 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig @@ -24,19 +24,6 @@ config ANDROID_LOW_MEMORY_KILLER scripts (/init.rc), and it defines priority values with minimum free memory size for each priority. -config SW_SYNC - bool "Software synchronization framework" - default n - depends on SYNC_FILE - depends on DEBUG_FS - ---help--- - A sync object driver that uses a 32bit counter to coordinate - synchronization. Useful when there is no hardware primitive backing - the synchronization. - - WARNING: improper use of this can result in deadlocking kernel - drivers from userspace. Intended for test and debug only. - source "drivers/staging/android/ion/Kconfig" endif # if ANDROID diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile index 7ca61b7..7ed1be7 100644 --- a/drivers/staging/android/Makefile +++ b/drivers/staging/android/Makefile @@ -4,4 +4,3 @@ obj-y += ion/ obj-$(CONFIG_ASHMEM) += ashmem.o obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o -obj-$(CONFIG_SW_SYNC) += sw_sync.o sync_debug.o diff --git a/drivers/staging/android/sw_sync.c b/drivers/staging/android/sw_sync.c deleted file mode 100644 index 62e8e6d..0000000 --- a/drivers/staging/android/sw_sync.c +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Sync File validation framework - * - * Copyright (C) 2012 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include <linux/file.h> -#include <linux/fs.h> -#include <linux/uaccess.h> -#include <linux/slab.h> -#include <linux/sync_file.h> - -#include "sync_debug.h" - -#define CREATE_TRACE_POINTS -#include "sync_trace.h" - -/* - * SW SYNC validation framework - * - * A sync object driver that uses a 32bit counter to coordinate - * synchronization. Useful when there is no hardware primitive backing - * the synchronization. - * - * To start the framework just open: - * - * <debugfs>/sync/sw_sync - * - * That will create a sync timeline, all fences created under this timeline - * file descriptor will belong to the this timeline. - * - * The 'sw_sync' file can be opened many times as to create different - * timelines. - * - * Fences can be created with SW_SYNC_IOC_CREATE_FENCE ioctl with struct - * sw_sync_ioctl_create_fence as parameter. - * - * To increment the timeline counter, SW_SYNC_IOC_INC ioctl should be used - * with the increment as u32. This will update the last signaled value - * from the timeline and signal any fence that has a seqno smaller or equal - * to it. - * - * struct sw_sync_ioctl_create_fence - * @value: the seqno to initialise the fence with - * @name: the name of the new sync point - * @fence: return the fd of the new sync_file with the created fence - */ -struct sw_sync_create_fence_data { - __u32 value; - char name[32]; - __s32 fence; /* fd of new fence */ -}; - -#define SW_SYNC_IOC_MAGIC 'W' - -#define SW_SYNC_IOC_CREATE_FENCE _IOWR(SW_SYNC_IOC_MAGIC, 0,\ - struct sw_sync_create_fence_data) - -#define SW_SYNC_IOC_INC _IOW(SW_SYNC_IOC_MAGIC, 1, __u32) - -static const struct fence_ops timeline_fence_ops; - -static inline struct sync_pt *fence_to_sync_pt(struct fence *fence) -{ - if (fence->ops != &timeline_fence_ops) - return NULL; - return container_of(fence, struct sync_pt, base); -} - -/** - * sync_timeline_create() - creates a sync object - * @name: sync_timeline name - * - * Creates a new sync_timeline. Returns the sync_timeline object or NULL in - * case of error. - */ -struct sync_timeline *sync_timeline_create(const char *name) -{ - struct sync_timeline *obj; - - obj = kzalloc(sizeof(*obj), GFP_KERNEL); - if (!obj) - return NULL; - - kref_init(&obj->kref); - obj->context = fence_context_alloc(1); - strlcpy(obj->name, name, sizeof(obj->name)); - - INIT_LIST_HEAD(&obj->child_list_head); - INIT_LIST_HEAD(&obj->active_list_head); - spin_lock_init(&obj->child_list_lock); - - sync_timeline_debug_add(obj); - - return obj; -} - -static void sync_timeline_free(struct kref *kref) -{ - struct sync_timeline *obj = - container_of(kref, struct sync_timeline, kref); - - sync_timeline_debug_remove(obj); - - kfree(obj); -} - -static void sync_timeline_get(struct sync_timeline *obj) -{ - kref_get(&obj->kref); -} - -static void sync_timeline_put(struct sync_timeline *obj) -{ - kref_put(&obj->kref, sync_timeline_free); -} - -/** - * sync_timeline_signal() - signal a status change on a sync_timeline - * @obj: sync_timeline to signal - * @inc: num to increment on timeline->value - * - * A sync implementation should call this any time one of it's fences - * has signaled or has an error condition. - */ -static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc) -{ - unsigned long flags; - struct sync_pt *pt, *next; - - trace_sync_timeline(obj); - - spin_lock_irqsave(&obj->child_list_lock, flags); - - obj->value += inc; - - list_for_each_entry_safe(pt, next, &obj->active_list_head, - active_list) { - if (fence_is_signaled_locked(&pt->base)) - list_del_init(&pt->active_list); - } - - spin_unlock_irqrestore(&obj->child_list_lock, flags); -} - -/** - * sync_pt_create() - creates a sync pt - * @parent: fence's parent sync_timeline - * @size: size to allocate for this pt - * @inc: value of the fence - * - * Creates a new sync_pt as a child of @parent. @size bytes will be - * allocated allowing for implementation specific data to be kept after - * the generic sync_timeline struct. Returns the sync_pt object or - * NULL in case of error. - */ -static struct sync_pt *sync_pt_create(struct sync_timeline *obj, int size, - unsigned int value) -{ - unsigned long flags; - struct sync_pt *pt; - - if (size < sizeof(*pt)) - return NULL; - - pt = kzalloc(size, GFP_KERNEL); - if (!pt) - return NULL; - - spin_lock_irqsave(&obj->child_list_lock, flags); - sync_timeline_get(obj); - fence_init(&pt->base, &timeline_fence_ops, &obj->child_list_lock, - obj->context, value); - list_add_tail(&pt->child_list, &obj->child_list_head); - INIT_LIST_HEAD(&pt->active_list); - spin_unlock_irqrestore(&obj->child_list_lock, flags); - return pt; -} - -static const char *timeline_fence_get_driver_name(struct fence *fence) -{ - return "sw_sync"; -} - -static const char *timeline_fence_get_timeline_name(struct fence *fence) -{ - struct sync_timeline *parent = fence_parent(fence); - - return parent->name; -} - -static void timeline_fence_release(struct fence *fence) -{ - struct sync_pt *pt = fence_to_sync_pt(fence); - struct sync_timeline *parent = fence_parent(fence); - unsigned long flags; - - spin_lock_irqsave(fence->lock, flags); - list_del(&pt->child_list); - if (!list_empty(&pt->active_list)) - list_del(&pt->active_list); - spin_unlock_irqrestore(fence->lock, flags); - - sync_timeline_put(parent); - fence_free(fence); -} - -static bool timeline_fence_signaled(struct fence *fence) -{ - struct sync_timeline *parent = fence_parent(fence); - - return (fence->seqno > parent->value) ? false : true; -} - -static bool timeline_fence_enable_signaling(struct fence *fence) -{ - struct sync_pt *pt = fence_to_sync_pt(fence); - struct sync_timeline *parent = fence_parent(fence); - - if (timeline_fence_signaled(fence)) - return false; - - list_add_tail(&pt->active_list, &parent->active_list_head); - return true; -} - -static void timeline_fence_value_str(struct fence *fence, - char *str, int size) -{ - snprintf(str, size, "%d", fence->seqno); -} - -static void timeline_fence_timeline_value_str(struct fence *fence, - char *str, int size) -{ - struct sync_timeline *parent = fence_parent(fence); - - snprintf(str, size, "%d", parent->value); -} - -static const struct fence_ops timeline_fence_ops = { - .get_driver_name = timeline_fence_get_driver_name, - .get_timeline_name = timeline_fence_get_timeline_name, - .enable_signaling = timeline_fence_enable_signaling, - .signaled = timeline_fence_signaled, - .wait = fence_default_wait, - .release = timeline_fence_release, - .fence_value_str = timeline_fence_value_str, - .timeline_value_str = timeline_fence_timeline_value_str, -}; - -/* - * *WARNING* - * - * improper use of this can result in deadlocking kernel drivers from userspace. - */ - -/* opening sw_sync create a new sync obj */ -static int sw_sync_debugfs_open(struct inode *inode, struct file *file) -{ - struct sync_timeline *obj; - char task_comm[TASK_COMM_LEN]; - - get_task_comm(task_comm, current); - - obj = sync_timeline_create(task_comm); - if (!obj) - return -ENOMEM; - - file->private_data = obj; - - return 0; -} - -static int sw_sync_debugfs_release(struct inode *inode, struct file *file) -{ - struct sync_timeline *obj = file->private_data; - - smp_wmb(); - - sync_timeline_put(obj); - return 0; -} - -static long sw_sync_ioctl_create_fence(struct sync_timeline *obj, - unsigned long arg) -{ - int fd = get_unused_fd_flags(O_CLOEXEC); - int err; - struct sync_pt *pt; - struct sync_file *sync_file; - struct sw_sync_create_fence_data data; - - if (fd < 0) - return fd; - - if (copy_from_user(&data, (void __user *)arg, sizeof(data))) { - err = -EFAULT; - goto err; - } - - pt = sync_pt_create(obj, sizeof(*pt), data.value); - if (!pt) { - err = -ENOMEM; - goto err; - } - - sync_file = sync_file_create(&pt->base); - if (!sync_file) { - fence_put(&pt->base); - err = -ENOMEM; - goto err; - } - - data.fence = fd; - if (copy_to_user((void __user *)arg, &data, sizeof(data))) { - fput(sync_file->file); - err = -EFAULT; - goto err; - } - - fd_install(fd, sync_file->file); - - return 0; - -err: - put_unused_fd(fd); - return err; -} - -static long sw_sync_ioctl_inc(struct sync_timeline *obj, unsigned long arg) -{ - u32 value; - - if (copy_from_user(&value, (void __user *)arg, sizeof(value))) - return -EFAULT; - - sync_timeline_signal(obj, value); - - return 0; -} - -static long sw_sync_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - struct sync_timeline *obj = file->private_data; - - switch (cmd) { - case SW_SYNC_IOC_CREATE_FENCE: - return sw_sync_ioctl_create_fence(obj, arg); - - case SW_SYNC_IOC_INC: - return sw_sync_ioctl_inc(obj, arg); - - default: - return -ENOTTY; - } -} - -const struct file_operations sw_sync_debugfs_fops = { - .open = sw_sync_debugfs_open, - .release = sw_sync_debugfs_release, - .unlocked_ioctl = sw_sync_ioctl, - .compat_ioctl = sw_sync_ioctl, -}; diff --git a/drivers/staging/android/sync_debug.c b/drivers/staging/android/sync_debug.c deleted file mode 100644 index fab9520..0000000 --- a/drivers/staging/android/sync_debug.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Sync File validation framework and debug information - * - * Copyright (C) 2012 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include <linux/debugfs.h> -#include "sync_debug.h" - -static struct dentry *dbgfs; - -static LIST_HEAD(sync_timeline_list_head); -static DEFINE_SPINLOCK(sync_timeline_list_lock); -static LIST_HEAD(sync_file_list_head); -static DEFINE_SPINLOCK(sync_file_list_lock); - -void sync_timeline_debug_add(struct sync_timeline *obj) -{ - unsigned long flags; - - spin_lock_irqsave(&sync_timeline_list_lock, flags); - list_add_tail(&obj->sync_timeline_list, &sync_timeline_list_head); - spin_unlock_irqrestore(&sync_timeline_list_lock, flags); -} - -void sync_timeline_debug_remove(struct sync_timeline *obj) -{ - unsigned long flags; - - spin_lock_irqsave(&sync_timeline_list_lock, flags); - list_del(&obj->sync_timeline_list); - spin_unlock_irqrestore(&sync_timeline_list_lock, flags); -} - -void sync_file_debug_add(struct sync_file *sync_file) -{ - unsigned long flags; - - spin_lock_irqsave(&sync_file_list_lock, flags); - list_add_tail(&sync_file->sync_file_list, &sync_file_list_head); - spin_unlock_irqrestore(&sync_file_list_lock, flags); -} - -void sync_file_debug_remove(struct sync_file *sync_file) -{ - unsigned long flags; - - spin_lock_irqsave(&sync_file_list_lock, flags); - list_del(&sync_file->sync_file_list); - spin_unlock_irqrestore(&sync_file_list_lock, flags); -} - -static const char *sync_status_str(int status) -{ - if (status == 0) - return "signaled"; - - if (status > 0) - return "active"; - - return "error"; -} - -static void sync_print_fence(struct seq_file *s, struct fence *fence, bool show) -{ - int status = 1; - struct sync_timeline *parent = fence_parent(fence); - - if (fence_is_signaled_locked(fence)) - status = fence->status; - - seq_printf(s, " %s%sfence %s", - show ? parent->name : "", - show ? "_" : "", - sync_status_str(status)); - - if (status <= 0) { - struct timespec64 ts64 = - ktime_to_timespec64(fence->timestamp); - - seq_printf(s, "@%lld.%09ld", (s64)ts64.tv_sec, ts64.tv_nsec); - } - - if (fence->ops->timeline_value_str && - fence->ops->fence_value_str) { - char value[64]; - bool success; - - fence->ops->fence_value_str(fence, value, sizeof(value)); - success = strlen(value); - - if (success) { - seq_printf(s, ": %s", value); - - fence->ops->timeline_value_str(fence, value, - sizeof(value)); - - if (strlen(value)) - seq_printf(s, " / %s", value); - } - } - - seq_puts(s, "\n"); -} - -static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj) -{ - struct list_head *pos; - unsigned long flags; - - seq_printf(s, "%s: %d\n", obj->name, obj->value); - - spin_lock_irqsave(&obj->child_list_lock, flags); - list_for_each(pos, &obj->child_list_head) { - struct sync_pt *pt = - container_of(pos, struct sync_pt, child_list); - sync_print_fence(s, &pt->base, false); - } - spin_unlock_irqrestore(&obj->child_list_lock, flags); -} - -static void sync_print_sync_file(struct seq_file *s, - struct sync_file *sync_file) -{ - int i; - - seq_printf(s, "[%p] %s: %s\n", sync_file, sync_file->name, - sync_status_str(atomic_read(&sync_file->status))); - - for (i = 0; i < sync_file->num_fences; ++i) - sync_print_fence(s, sync_file->cbs[i].fence, true); -} - -static int sync_debugfs_show(struct seq_file *s, void *unused) -{ - unsigned long flags; - struct list_head *pos; - - seq_puts(s, "objs:\n--------------\n"); - - spin_lock_irqsave(&sync_timeline_list_lock, flags); - list_for_each(pos, &sync_timeline_list_head) { - struct sync_timeline *obj = - container_of(pos, struct sync_timeline, - sync_timeline_list); - - sync_print_obj(s, obj); - seq_puts(s, "\n"); - } - spin_unlock_irqrestore(&sync_timeline_list_lock, flags); - - seq_puts(s, "fences:\n--------------\n"); - - spin_lock_irqsave(&sync_file_list_lock, flags); - list_for_each(pos, &sync_file_list_head) { - struct sync_file *sync_file = - container_of(pos, struct sync_file, sync_file_list); - - sync_print_sync_file(s, sync_file); - seq_puts(s, "\n"); - } - spin_unlock_irqrestore(&sync_file_list_lock, flags); - return 0; -} - -static int sync_info_debugfs_open(struct inode *inode, struct file *file) -{ - return single_open(file, sync_debugfs_show, inode->i_private); -} - -static const struct file_operations sync_info_debugfs_fops = { - .open = sync_info_debugfs_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static __init int sync_debugfs_init(void) -{ - dbgfs = debugfs_create_dir("sync", NULL); - - /* - * The debugfs files won't ever get removed and thus, there is - * no need to protect it against removal races. The use of - * debugfs_create_file_unsafe() is actually safe here. - */ - debugfs_create_file_unsafe("info", 0444, dbgfs, NULL, - &sync_info_debugfs_fops); - debugfs_create_file_unsafe("sw_sync", 0644, dbgfs, NULL, - &sw_sync_debugfs_fops); - - return 0; -} -late_initcall(sync_debugfs_init); - -#define DUMP_CHUNK 256 -static char sync_dump_buf[64 * 1024]; -void sync_dump(void) -{ - struct seq_file s = { - .buf = sync_dump_buf, - .size = sizeof(sync_dump_buf) - 1, - }; - int i; - - sync_debugfs_show(&s, NULL); - - for (i = 0; i < s.count; i += DUMP_CHUNK) { - if ((s.count - i) > DUMP_CHUNK) { - char c = s.buf[i + DUMP_CHUNK]; - - s.buf[i + DUMP_CHUNK] = 0; - pr_cont("%s", s.buf + i); - s.buf[i + DUMP_CHUNK] = c; - } else { - s.buf[s.count] = 0; - pr_cont("%s", s.buf + i); - } - } -} diff --git a/drivers/staging/android/sync_debug.h b/drivers/staging/android/sync_debug.h deleted file mode 100644 index d269aa6..0000000 --- a/drivers/staging/android/sync_debug.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Sync File validation framework and debug infomation - * - * Copyright (C) 2012 Google, Inc. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef _LINUX_SYNC_H -#define _LINUX_SYNC_H - -#include <linux/list.h> -#include <linux/spinlock.h> -#include <linux/fence.h> - -#include <linux/sync_file.h> -#include <uapi/linux/sync_file.h> - -/** - * struct sync_timeline - sync object - * @kref: reference count on fence. - * @name: name of the sync_timeline. Useful for debugging - * @child_list_head: list of children sync_pts for this sync_timeline - * @child_list_lock: lock protecting @child_list_head and fence.status - * @active_list_head: list of active (unsignaled/errored) sync_pts - * @sync_timeline_list: membership in global sync_timeline_list - */ -struct sync_timeline { - struct kref kref; - char name[32]; - - /* protected by child_list_lock */ - u64 context; - int value; - - struct list_head child_list_head; - spinlock_t child_list_lock; - - struct list_head active_list_head; - - struct list_head sync_timeline_list; -}; - -static inline struct sync_timeline *fence_parent(struct fence *fence) -{ - return container_of(fence->lock, struct sync_timeline, - child_list_lock); -} - -/** - * struct sync_pt - sync_pt object - * @base: base fence object - * @child_list: sync timeline child's list - * @active_list: sync timeline active child's list - */ -struct sync_pt { - struct fence base; - struct list_head child_list; - struct list_head active_list; -}; - -#ifdef CONFIG_SW_SYNC - -extern const struct file_operations sw_sync_debugfs_fops; - -void sync_timeline_debug_add(struct sync_timeline *obj); -void sync_timeline_debug_remove(struct sync_timeline *obj); -void sync_file_debug_add(struct sync_file *fence); -void sync_file_debug_remove(struct sync_file *fence); -void sync_dump(void); - -#else -# define sync_timeline_debug_add(obj) -# define sync_timeline_debug_remove(obj) -# define sync_file_debug_add(fence) -# define sync_file_debug_remove(fence) -# define sync_dump() -#endif - -#endif /* _LINUX_SYNC_H */ diff --git a/drivers/staging/android/sync_trace.h b/drivers/staging/android/sync_trace.h deleted file mode 100644 index ea485f7..0000000 --- a/drivers/staging/android/sync_trace.h +++ /dev/null @@ -1,32 +0,0 @@ -#undef TRACE_SYSTEM -#define TRACE_INCLUDE_PATH ../../drivers/staging/android -#define TRACE_SYSTEM sync_trace - -#if !defined(_TRACE_SYNC_H) || defined(TRACE_HEADER_MULTI_READ) -#define _TRACE_SYNC_H - -#include "sync_debug.h" -#include <linux/tracepoint.h> - -TRACE_EVENT(sync_timeline, - TP_PROTO(struct sync_timeline *timeline), - - TP_ARGS(timeline), - - TP_STRUCT__entry( - __string(name, timeline->name) - __field(u32, value) - ), - - TP_fast_assign( - __assign_str(name, timeline->name); - __entry->value = timeline->value; - ), - - TP_printk("name=%s value=%d", __get_str(name), __entry->value) -); - -#endif /* if !defined(_TRACE_SYNC_H) || defined(TRACE_HEADER_MULTI_READ) */ - -/* This part must be outside protection */ -#include <trace/define_trace.h> -- cgit v0.10.2 From 6a9aabb107c65ecb6f08b010853f5571d781ba5a Mon Sep 17 00:00:00 2001 From: Didik Setiawan <didik.swn@gmail.com> Date: Sat, 14 May 2016 10:28:10 +0700 Subject: staging: android: ion: fix 'line over 80 characters' fix checkpatch.pl warning about 'line over 80 characters'. Signed-off-by: Didik Setiawan <didik.swn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 7138a5b..88dd17e 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -545,7 +545,8 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, } EXPORT_SYMBOL(ion_alloc); -static void ion_free_nolock(struct ion_client *client, struct ion_handle *handle) +static void ion_free_nolock(struct ion_client *client, + struct ion_handle *handle) { bool valid_handle; @@ -1306,7 +1307,8 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) struct ion_handle *handle; mutex_lock(&client->lock); - handle = ion_handle_get_by_id_nolock(client, data.handle.handle); + handle = ion_handle_get_by_id_nolock(client, + data.handle.handle); if (IS_ERR(handle)) { mutex_unlock(&client->lock); return PTR_ERR(handle); -- cgit v0.10.2 From 1beba52d46f039a24f31cf5717c239c89a9d4e6f Mon Sep 17 00:00:00 2001 From: Bhaktipriya Shridhar <bhaktipriya96@gmail.com> Date: Sat, 13 Aug 2016 22:16:24 +0530 Subject: android: binder: Remove deprecated create_singlethread_workqueue The workqueue is being used to run deferred work for the android binder. The "binder_deferred_workqueue" queues only a single work item and hence does not require ordering. Also, this workqueue is not being used on a memory recliam path. Hence, the singlethreaded workqueue has been replaced with the use of system_wq. System workqueues have been able to handle high level of concurrency for a long time now and hence it's not required to have a singlethreaded workqueue just to gain concurrency. Unlike a dedicated per-cpu workqueue created with create_singlethread_workqueue(), system_wq allows multiple work items to overlap executions even on the same CPU; however, a per-cpu workqueue doesn't have any CPU locality or global ordering guarantee unless the target CPU is explicitly specified and thus the increase of local concurrency shouldn't make any difference. Signed-off-by: Bhaktipriya Shridhar <bhaktipriya96@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 16288e7..562af94 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -59,7 +59,6 @@ static struct dentry *binder_debugfs_dir_entry_proc; static struct binder_node *binder_context_mgr_node; static kuid_t binder_context_mgr_uid = INVALID_UID; static int binder_last_id; -static struct workqueue_struct *binder_deferred_workqueue; #define BINDER_DEBUG_ENTRY(name) \ static int binder_##name##_open(struct inode *inode, struct file *file) \ @@ -3227,7 +3226,7 @@ binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer) if (hlist_unhashed(&proc->deferred_work_node)) { hlist_add_head(&proc->deferred_work_node, &binder_deferred_list); - queue_work(binder_deferred_workqueue, &binder_deferred_work); + schedule_work(&binder_deferred_work); } mutex_unlock(&binder_deferred_lock); } @@ -3679,10 +3678,6 @@ static int __init binder_init(void) { int ret; - binder_deferred_workqueue = create_singlethread_workqueue("binder"); - if (!binder_deferred_workqueue) - return -ENOMEM; - binder_debugfs_dir_entry_root = debugfs_create_dir("binder", NULL); if (binder_debugfs_dir_entry_root) binder_debugfs_dir_entry_proc = debugfs_create_dir("proc", -- cgit v0.10.2 From bcdf177d046c13db727c80ac9023b916dd878f8f Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Mon, 25 Jul 2016 15:54:54 +0200 Subject: iio: magn: DT bindings for AK8974 This adds device tree bindings for the AK8974 magnetometer, similar to those for the AK8975. Cc: devicetree@vger.kernel.org Cc: Samu Onkalo <samu.onkalo@intel.com> Cc: Sebastian Reichel <sre@kernel.org> Cc: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Acked-by: Rob Herring <robh@kernel.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/Documentation/devicetree/bindings/iio/magnetometer/ak8974.txt b/Documentation/devicetree/bindings/iio/magnetometer/ak8974.txt new file mode 100644 index 0000000..77d5aba1 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/magnetometer/ak8974.txt @@ -0,0 +1,29 @@ +* Asahi Kasei AK8974 magnetometer sensor + +Required properties: + +- compatible : should be "asahi-kasei,ak8974" +- reg : the I2C address of the magnetometer + +Optional properties: + +- avdd-supply: regulator supply for the analog voltage + (see regulator/regulator.txt) +- dvdd-supply: regulator supply for the digital voltage + (see regulator/regulator.txt) +- interrupts: data ready (DRDY) and interrupt (INT1) lines + from the chip, the DRDY interrupt must be placed first. + The interrupts can be triggered on rising or falling + edges alike. +- mount-matrix: an optional 3x3 mounting rotation matrix + +Example: + +ak8974@0f { + compatible = "asahi-kasei,ak8974"; + reg = <0x0f>; + avdd-supply = <&foo_reg>; + dvdd-supply = <&bar_reg>; + interrupts = <0 IRQ_TYPE_EDGE_RISING>, + <1 IRQ_TYPE_EDGE_RISING>; +}; -- cgit v0.10.2 From 7c94a8b2ee8cfe915f332575566b4870976ab8f4 Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Mon, 25 Jul 2016 15:54:55 +0200 Subject: iio: magn: add a driver for AK8974 This adds a driver for the Asahi Kasei AK8974 and its sibling AMI305 magnetometers. It was deployed on scale in 2009 on a multitude of devices. It is distincly different from AK8973 and AK8975 and needs its own driver. This patch is based on the long lost work of Samu Onkalo at Nokia, who made a misc character device driver for the Maemo/MeeGo Nokia devices, before the time of the IIO subsystem. It was mounted in e.g. the Nokia N950, N8, N86, N97 etc. It is also mounted on the ST-Ericsson HREF reference designs. It works nicely in sysfs: $ cat in_magn_x_raw && cat in_magn_y_raw && cat in_magn_z_raw -55 -101 161 And with buffered reads using a simple HRTimer trigger: $ generic_buffer -c10 -a -n ak8974 -t foo iio device number being used is 3 iio trigger number being used is 2 No channels are enabled, enabling all channels Enabling: in_magn_x_en Enabling: in_magn_y_en Enabling: in_magn_z_en Enabling: in_timestamp_en /sys/bus/iio/devices/iio:device3 foo -58.000000 -102.000000 157.000000 946684970985321044 -60.000000 -98.000000 159.000000 946684971012237548 -60.000000 -106.000000 163.000000 946684971032257080 -62.000000 -94.000000 169.000000 946684971052185058 -58.000000 -98.000000 163.000000 946684971072204589 -54.000000 -100.000000 163.000000 946684971092224121 -53.000000 -103.000000 164.000000 946684971112731933 -50.000000 -102.000000 165.000000 946684971132232666 -61.000000 -101.000000 164.000000 946684971152191162 -57.000000 -99.000000 168.000000 946684971172210693 Disabling: in_magn_x_en Disabling: in_magn_y_en Disabling: in_magn_z_en Disabling: in_timestamp_en I cannot currently scale these raw values to gauss. This is because of lack of documentation. I have sent a request for a datasheet to Asahi Kasei. The driver can optionally use a DRDY line IRQ to capture data, else it will sleep and poll. Cc: Samu Onkalo <samu.onkalo@intel.com> Cc: Sebastian Reichel <sre@kernel.org> Cc: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Tested-By: Sebastian Reichel <sre@kernel.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/MAINTAINERS b/MAINTAINERS index b5c802d..372bd64 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1930,6 +1930,13 @@ S: Maintained F: drivers/media/i2c/as3645a.c F: include/media/i2c/as3645a.h +ASAHI KASEI AK8974 DRIVER +M: Linus Walleij <linus.walleij@linaro.org> +L: linux-iio@vger.kernel.org +W: http://www.akm.com/ +S: Supported +F: drivers/iio/magnetometer/ak8974.c + ASC7621 HARDWARE MONITOR DRIVER M: George Joseph <george.joseph@fairview5.com> L: linux-hwmon@vger.kernel.org diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig index 1f842ab..421ad90 100644 --- a/drivers/iio/magnetometer/Kconfig +++ b/drivers/iio/magnetometer/Kconfig @@ -5,8 +5,22 @@ menu "Magnetometer sensors" +config AK8974 + tristate "Asahi Kasei AK8974 3-Axis Magnetometer" + depends on I2C + depends on OF + select REGMAP_I2C + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say yes here to build support for Asahi Kasei AK8974 or + AMI305 I2C-based 3-axis magnetometer chips. + + To compile this driver as a module, choose M here: the module + will be called ak8974. + config AK8975 - tristate "Asahi Kasei AK 3-Axis Magnetometer" + tristate "Asahi Kasei AK8975 3-Axis Magnetometer" depends on I2C depends on GPIOLIB || COMPILE_TEST select IIO_BUFFER diff --git a/drivers/iio/magnetometer/Makefile b/drivers/iio/magnetometer/Makefile index 92a745c..b86d6cb 100644 --- a/drivers/iio/magnetometer/Makefile +++ b/drivers/iio/magnetometer/Makefile @@ -3,6 +3,7 @@ # # When adding new entries keep the list in alphabetical order +obj-$(CONFIG_AK8974) += ak8974.o obj-$(CONFIG_AK8975) += ak8975.o obj-$(CONFIG_BMC150_MAGN) += bmc150_magn.o obj-$(CONFIG_BMC150_MAGN_I2C) += bmc150_magn_i2c.o diff --git a/drivers/iio/magnetometer/ak8974.c b/drivers/iio/magnetometer/ak8974.c new file mode 100644 index 0000000..e70e4e2 --- /dev/null +++ b/drivers/iio/magnetometer/ak8974.c @@ -0,0 +1,863 @@ +/* + * Driver for the Asahi Kasei EMD Corporation AK8974 + * and Aichi Steel AMI305 magnetometer chips. + * Based on a patch from Samu Onkalo and the AK8975 IIO driver. + * + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * Copyright (c) 2010 NVIDIA Corporation. + * Copyright (C) 2016 Linaro Ltd. + * + * Author: Samu Onkalo <samu.p.onkalo@nokia.com> + * Author: Linus Walleij <linus.walleij@linaro.org> + */ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/i2c.h> +#include <linux/interrupt.h> +#include <linux/irq.h> /* For irq_get_irq_data() */ +#include <linux/completion.h> +#include <linux/err.h> +#include <linux/mutex.h> +#include <linux/delay.h> +#include <linux/bitops.h> +#include <linux/regmap.h> +#include <linux/regulator/consumer.h> +#include <linux/pm_runtime.h> + +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/buffer.h> +#include <linux/iio/trigger.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/iio/triggered_buffer.h> + +/* + * 16-bit registers are little-endian. LSB is at the address defined below + * and MSB is at the next higher address. + */ + +/* These registers are common for AK8974 and AMI305 */ +#define AK8974_SELFTEST 0x0C +#define AK8974_SELFTEST_IDLE 0x55 +#define AK8974_SELFTEST_OK 0xAA + +#define AK8974_INFO 0x0D + +#define AK8974_WHOAMI 0x0F +#define AK8974_WHOAMI_VALUE_AMI305 0x47 +#define AK8974_WHOAMI_VALUE_AK8974 0x48 + +#define AK8974_DATA_X 0x10 +#define AK8974_DATA_Y 0x12 +#define AK8974_DATA_Z 0x14 +#define AK8974_INT_SRC 0x16 +#define AK8974_STATUS 0x18 +#define AK8974_INT_CLEAR 0x1A +#define AK8974_CTRL1 0x1B +#define AK8974_CTRL2 0x1C +#define AK8974_CTRL3 0x1D +#define AK8974_INT_CTRL 0x1E +#define AK8974_INT_THRES 0x26 /* Absolute any axis value threshold */ +#define AK8974_PRESET 0x30 + +/* AK8974-specific offsets */ +#define AK8974_OFFSET_X 0x20 +#define AK8974_OFFSET_Y 0x22 +#define AK8974_OFFSET_Z 0x24 +/* AMI305-specific offsets */ +#define AMI305_OFFSET_X 0x6C +#define AMI305_OFFSET_Y 0x72 +#define AMI305_OFFSET_Z 0x78 + +/* Different temperature registers */ +#define AK8974_TEMP 0x31 +#define AMI305_TEMP 0x60 + +#define AK8974_INT_X_HIGH BIT(7) /* Axis over +threshold */ +#define AK8974_INT_Y_HIGH BIT(6) +#define AK8974_INT_Z_HIGH BIT(5) +#define AK8974_INT_X_LOW BIT(4) /* Axis below -threshold */ +#define AK8974_INT_Y_LOW BIT(3) +#define AK8974_INT_Z_LOW BIT(2) +#define AK8974_INT_RANGE BIT(1) /* Range overflow (any axis) */ + +#define AK8974_STATUS_DRDY BIT(6) /* Data ready */ +#define AK8974_STATUS_OVERRUN BIT(5) /* Data overrun */ +#define AK8974_STATUS_INT BIT(4) /* Interrupt occurred */ + +#define AK8974_CTRL1_POWER BIT(7) /* 0 = standby; 1 = active */ +#define AK8974_CTRL1_RATE BIT(4) /* 0 = 10 Hz; 1 = 20 Hz */ +#define AK8974_CTRL1_FORCE_EN BIT(1) /* 0 = normal; 1 = force */ +#define AK8974_CTRL1_MODE2 BIT(0) /* 0 */ + +#define AK8974_CTRL2_INT_EN BIT(4) /* 1 = enable interrupts */ +#define AK8974_CTRL2_DRDY_EN BIT(3) /* 1 = enable data ready signal */ +#define AK8974_CTRL2_DRDY_POL BIT(2) /* 1 = data ready active high */ +#define AK8974_CTRL2_RESDEF (AK8974_CTRL2_DRDY_POL) + +#define AK8974_CTRL3_RESET BIT(7) /* Software reset */ +#define AK8974_CTRL3_FORCE BIT(6) /* Start forced measurement */ +#define AK8974_CTRL3_SELFTEST BIT(4) /* Set selftest register */ +#define AK8974_CTRL3_RESDEF 0x00 + +#define AK8974_INT_CTRL_XEN BIT(7) /* Enable interrupt for this axis */ +#define AK8974_INT_CTRL_YEN BIT(6) +#define AK8974_INT_CTRL_ZEN BIT(5) +#define AK8974_INT_CTRL_XYZEN (BIT(7)|BIT(6)|BIT(5)) +#define AK8974_INT_CTRL_POL BIT(3) /* 0 = active low; 1 = active high */ +#define AK8974_INT_CTRL_PULSE BIT(1) /* 0 = latched; 1 = pulse (50 usec) */ +#define AK8974_INT_CTRL_RESDEF (AK8974_INT_CTRL_XYZEN | AK8974_INT_CTRL_POL) + +/* The AMI305 has elaborate FW version and serial number registers */ +#define AMI305_VER 0xE8 +#define AMI305_SN 0xEA + +#define AK8974_MAX_RANGE 2048 + +#define AK8974_POWERON_DELAY 50 +#define AK8974_ACTIVATE_DELAY 1 +#define AK8974_SELFTEST_DELAY 1 +/* + * Set the autosuspend to two orders of magnitude larger than the poweron + * delay to make sane reasonable power tradeoff savings (5 seconds in + * this case). + */ +#define AK8974_AUTOSUSPEND_DELAY 5000 + +#define AK8974_MEASTIME 3 + +#define AK8974_PWR_ON 1 +#define AK8974_PWR_OFF 0 + +/** + * struct ak8974 - state container for the AK8974 driver + * @i2c: parent I2C client + * @orientation: mounting matrix, flipped axis etc + * @map: regmap to access the AK8974 registers over I2C + * @regs: the avdd and dvdd power regulators + * @name: the name of the part + * @variant: the whoami ID value (for selecting code paths) + * @lock: locks the magnetometer for exclusive use during a measurement + * @drdy_irq: uses the DRDY IRQ line + * @drdy_complete: completion for DRDY + * @drdy_active_low: the DRDY IRQ is active low + */ +struct ak8974 { + struct i2c_client *i2c; + struct iio_mount_matrix orientation; + struct regmap *map; + struct regulator_bulk_data regs[2]; + const char *name; + u8 variant; + struct mutex lock; + bool drdy_irq; + struct completion drdy_complete; + bool drdy_active_low; +}; + +static const char ak8974_reg_avdd[] = "avdd"; +static const char ak8974_reg_dvdd[] = "dvdd"; + +static int ak8974_set_power(struct ak8974 *ak8974, bool mode) +{ + int ret; + u8 val; + + val = mode ? AK8974_CTRL1_POWER : 0; + val |= AK8974_CTRL1_FORCE_EN; + ret = regmap_write(ak8974->map, AK8974_CTRL1, val); + if (ret < 0) + return ret; + + if (mode) + msleep(AK8974_ACTIVATE_DELAY); + + return 0; +} + +static int ak8974_reset(struct ak8974 *ak8974) +{ + int ret; + + /* Power on to get register access. Sets CTRL1 reg to reset state */ + ret = ak8974_set_power(ak8974, AK8974_PWR_ON); + if (ret) + return ret; + ret = regmap_write(ak8974->map, AK8974_CTRL2, AK8974_CTRL2_RESDEF); + if (ret) + return ret; + ret = regmap_write(ak8974->map, AK8974_CTRL3, AK8974_CTRL3_RESDEF); + if (ret) + return ret; + ret = regmap_write(ak8974->map, AK8974_INT_CTRL, + AK8974_INT_CTRL_RESDEF); + if (ret) + return ret; + + /* After reset, power off is default state */ + return ak8974_set_power(ak8974, AK8974_PWR_OFF); +} + +static int ak8974_configure(struct ak8974 *ak8974) +{ + int ret; + + ret = regmap_write(ak8974->map, AK8974_CTRL2, AK8974_CTRL2_DRDY_EN | + AK8974_CTRL2_INT_EN); + if (ret) + return ret; + ret = regmap_write(ak8974->map, AK8974_CTRL3, 0); + if (ret) + return ret; + ret = regmap_write(ak8974->map, AK8974_INT_CTRL, AK8974_INT_CTRL_POL); + if (ret) + return ret; + + return regmap_write(ak8974->map, AK8974_PRESET, 0); +} + +static int ak8974_trigmeas(struct ak8974 *ak8974) +{ + unsigned int clear; + u8 mask; + u8 val; + int ret; + + /* Clear any previous measurement overflow status */ + ret = regmap_read(ak8974->map, AK8974_INT_CLEAR, &clear); + if (ret) + return ret; + + /* If we have a DRDY IRQ line, use it */ + if (ak8974->drdy_irq) { + mask = AK8974_CTRL2_INT_EN | + AK8974_CTRL2_DRDY_EN | + AK8974_CTRL2_DRDY_POL; + val = AK8974_CTRL2_DRDY_EN; + + if (!ak8974->drdy_active_low) + val |= AK8974_CTRL2_DRDY_POL; + + init_completion(&ak8974->drdy_complete); + ret = regmap_update_bits(ak8974->map, AK8974_CTRL2, + mask, val); + if (ret) + return ret; + } + + /* Force a measurement */ + return regmap_update_bits(ak8974->map, + AK8974_CTRL3, + AK8974_CTRL3_FORCE, + AK8974_CTRL3_FORCE); +} + +static int ak8974_await_drdy(struct ak8974 *ak8974) +{ + int timeout = 2; + unsigned int val; + int ret; + + if (ak8974->drdy_irq) { + ret = wait_for_completion_timeout(&ak8974->drdy_complete, + 1 + msecs_to_jiffies(1000)); + if (!ret) { + dev_err(&ak8974->i2c->dev, + "timeout waiting for DRDY IRQ\n"); + return -ETIMEDOUT; + } + return 0; + } + + /* Default delay-based poll loop */ + do { + msleep(AK8974_MEASTIME); + ret = regmap_read(ak8974->map, AK8974_STATUS, &val); + if (ret < 0) + return ret; + if (val & AK8974_STATUS_DRDY) + return 0; + } while (--timeout); + if (!timeout) { + dev_err(&ak8974->i2c->dev, + "timeout waiting for DRDY\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static int ak8974_getresult(struct ak8974 *ak8974, s16 *result) +{ + unsigned int src; + int ret; + + ret = ak8974_await_drdy(ak8974); + if (ret) + return ret; + ret = regmap_read(ak8974->map, AK8974_INT_SRC, &src); + if (ret < 0) + return ret; + + /* Out of range overflow! Strong magnet close? */ + if (src & AK8974_INT_RANGE) { + dev_err(&ak8974->i2c->dev, + "range overflow in sensor\n"); + return -ERANGE; + } + + ret = regmap_bulk_read(ak8974->map, AK8974_DATA_X, result, 6); + if (ret) + return ret; + + return ret; +} + +static irqreturn_t ak8974_drdy_irq(int irq, void *d) +{ + struct ak8974 *ak8974 = d; + + if (!ak8974->drdy_irq) + return IRQ_NONE; + + /* TODO: timestamp here to get good measurement stamps */ + return IRQ_WAKE_THREAD; +} + +static irqreturn_t ak8974_drdy_irq_thread(int irq, void *d) +{ + struct ak8974 *ak8974 = d; + unsigned int val; + int ret; + + /* Check if this was a DRDY from us */ + ret = regmap_read(ak8974->map, AK8974_STATUS, &val); + if (ret < 0) { + dev_err(&ak8974->i2c->dev, "error reading DRDY status\n"); + return IRQ_HANDLED; + } + if (val & AK8974_STATUS_DRDY) { + /* Yes this was our IRQ */ + complete(&ak8974->drdy_complete); + return IRQ_HANDLED; + } + + /* We may be on a shared IRQ, let the next client check */ + return IRQ_NONE; +} + +static int ak8974_selftest(struct ak8974 *ak8974) +{ + struct device *dev = &ak8974->i2c->dev; + unsigned int val; + int ret; + + ret = regmap_read(ak8974->map, AK8974_SELFTEST, &val); + if (ret) + return ret; + if (val != AK8974_SELFTEST_IDLE) { + dev_err(dev, "selftest not idle before test\n"); + return -EIO; + } + + /* Trigger self-test */ + ret = regmap_update_bits(ak8974->map, + AK8974_CTRL3, + AK8974_CTRL3_SELFTEST, + AK8974_CTRL3_SELFTEST); + if (ret) { + dev_err(dev, "could not write CTRL3\n"); + return ret; + } + + msleep(AK8974_SELFTEST_DELAY); + + ret = regmap_read(ak8974->map, AK8974_SELFTEST, &val); + if (ret) + return ret; + if (val != AK8974_SELFTEST_OK) { + dev_err(dev, "selftest result NOT OK (%02x)\n", val); + return -EIO; + } + + ret = regmap_read(ak8974->map, AK8974_SELFTEST, &val); + if (ret) + return ret; + if (val != AK8974_SELFTEST_IDLE) { + dev_err(dev, "selftest not idle after test (%02x)\n", val); + return -EIO; + } + dev_dbg(dev, "passed self-test\n"); + + return 0; +} + +static int ak8974_get_u16_val(struct ak8974 *ak8974, u8 reg, u16 *val) +{ + int ret; + u16 bulk; + + ret = regmap_bulk_read(ak8974->map, reg, &bulk, 2); + if (ret) + return ret; + *val = le16_to_cpu(bulk); + + return 0; +} + +static int ak8974_detect(struct ak8974 *ak8974) +{ + unsigned int whoami; + const char *name; + int ret; + unsigned int fw; + u16 sn; + + ret = regmap_read(ak8974->map, AK8974_WHOAMI, &whoami); + if (ret) + return ret; + + switch (whoami) { + case AK8974_WHOAMI_VALUE_AMI305: + name = "ami305"; + ret = regmap_read(ak8974->map, AMI305_VER, &fw); + if (ret) + return ret; + fw &= 0x7f; /* only bits 0 thru 6 valid */ + ret = ak8974_get_u16_val(ak8974, AMI305_SN, &sn); + if (ret) + return ret; + dev_info(&ak8974->i2c->dev, + "detected %s, FW ver %02x, S/N: %04x\n", + name, fw, sn); + break; + case AK8974_WHOAMI_VALUE_AK8974: + name = "ak8974"; + dev_info(&ak8974->i2c->dev, "detected AK8974\n"); + break; + default: + dev_err(&ak8974->i2c->dev, "unsupported device (%02x) ", + whoami); + return -ENODEV; + } + + ak8974->name = name; + ak8974->variant = whoami; + + return 0; +} + +static int ak8974_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, + long mask) +{ + struct ak8974 *ak8974 = iio_priv(indio_dev); + s16 hw_values[3]; + int ret = -EINVAL; + + pm_runtime_get_sync(&ak8974->i2c->dev); + mutex_lock(&ak8974->lock); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (chan->address > 2) { + dev_err(&ak8974->i2c->dev, "faulty channel address\n"); + ret = -EIO; + goto out_unlock; + } + ret = ak8974_trigmeas(ak8974); + if (ret) + goto out_unlock; + ret = ak8974_getresult(ak8974, hw_values); + if (ret) + goto out_unlock; + + /* + * We read all axes and discard all but one, for optimized + * reading, use the triggered buffer. + */ + *val = le16_to_cpu(hw_values[chan->address]); + + ret = IIO_VAL_INT; + } + + out_unlock: + mutex_unlock(&ak8974->lock); + pm_runtime_mark_last_busy(&ak8974->i2c->dev); + pm_runtime_put_autosuspend(&ak8974->i2c->dev); + + return ret; +} + +static void ak8974_fill_buffer(struct iio_dev *indio_dev) +{ + struct ak8974 *ak8974 = iio_priv(indio_dev); + int ret; + s16 hw_values[8]; /* Three axes + 64bit padding */ + + pm_runtime_get_sync(&ak8974->i2c->dev); + mutex_lock(&ak8974->lock); + + ret = ak8974_trigmeas(ak8974); + if (ret) { + dev_err(&ak8974->i2c->dev, "error triggering measure\n"); + goto out_unlock; + } + ret = ak8974_getresult(ak8974, hw_values); + if (ret) { + dev_err(&ak8974->i2c->dev, "error getting measures\n"); + goto out_unlock; + } + + iio_push_to_buffers_with_timestamp(indio_dev, hw_values, + iio_get_time_ns(indio_dev)); + + out_unlock: + mutex_unlock(&ak8974->lock); + pm_runtime_mark_last_busy(&ak8974->i2c->dev); + pm_runtime_put_autosuspend(&ak8974->i2c->dev); +} + +static irqreturn_t ak8974_handle_trigger(int irq, void *p) +{ + const struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + + ak8974_fill_buffer(indio_dev); + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static const struct iio_mount_matrix * +ak8974_get_mount_matrix(const struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct ak8974 *ak8974 = iio_priv(indio_dev); + + return &ak8974->orientation; +} + +static const struct iio_chan_spec_ext_info ak8974_ext_info[] = { + IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, ak8974_get_mount_matrix), + { }, +}; + +#define AK8974_AXIS_CHANNEL(axis, index) \ + { \ + .type = IIO_MAGN, \ + .modified = 1, \ + .channel2 = IIO_MOD_##axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .ext_info = ak8974_ext_info, \ + .address = index, \ + .scan_index = index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_LE \ + }, \ + } + +static const struct iio_chan_spec ak8974_channels[] = { + AK8974_AXIS_CHANNEL(X, 0), + AK8974_AXIS_CHANNEL(Y, 1), + AK8974_AXIS_CHANNEL(Z, 2), + IIO_CHAN_SOFT_TIMESTAMP(3), +}; + +static const unsigned long ak8974_scan_masks[] = { 0x7, 0 }; + +static const struct iio_info ak8974_info = { + .read_raw = &ak8974_read_raw, + .driver_module = THIS_MODULE, +}; + +static bool ak8974_writeable_reg(struct device *dev, unsigned int reg) +{ + struct i2c_client *i2c = to_i2c_client(dev); + struct iio_dev *indio_dev = i2c_get_clientdata(i2c); + struct ak8974 *ak8974 = iio_priv(indio_dev); + + switch (reg) { + case AK8974_CTRL1: + case AK8974_CTRL2: + case AK8974_CTRL3: + case AK8974_INT_CTRL: + case AK8974_INT_THRES: + case AK8974_INT_THRES + 1: + case AK8974_PRESET: + case AK8974_PRESET + 1: + return true; + case AK8974_OFFSET_X: + case AK8974_OFFSET_X + 1: + case AK8974_OFFSET_Y: + case AK8974_OFFSET_Y + 1: + case AK8974_OFFSET_Z: + case AK8974_OFFSET_Z + 1: + if (ak8974->variant == AK8974_WHOAMI_VALUE_AK8974) + return true; + return false; + case AMI305_OFFSET_X: + case AMI305_OFFSET_X + 1: + case AMI305_OFFSET_Y: + case AMI305_OFFSET_Y + 1: + case AMI305_OFFSET_Z: + case AMI305_OFFSET_Z + 1: + if (ak8974->variant == AK8974_WHOAMI_VALUE_AMI305) + return true; + return false; + default: + return false; + } +} + +static const struct regmap_config ak8974_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0xff, + .writeable_reg = ak8974_writeable_reg, +}; + +static int ak8974_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct iio_dev *indio_dev; + struct ak8974 *ak8974; + unsigned long irq_trig; + int irq = i2c->irq; + int ret; + + /* Register with IIO */ + indio_dev = devm_iio_device_alloc(&i2c->dev, sizeof(*ak8974)); + if (indio_dev == NULL) + return -ENOMEM; + + ak8974 = iio_priv(indio_dev); + i2c_set_clientdata(i2c, indio_dev); + ak8974->i2c = i2c; + mutex_init(&ak8974->lock); + + ret = of_iio_read_mount_matrix(&i2c->dev, + "mount-matrix", + &ak8974->orientation); + if (ret) + return ret; + + ak8974->regs[0].supply = ak8974_reg_avdd; + ak8974->regs[1].supply = ak8974_reg_dvdd; + + ret = devm_regulator_bulk_get(&i2c->dev, + ARRAY_SIZE(ak8974->regs), + ak8974->regs); + if (ret < 0) { + dev_err(&i2c->dev, "cannot get regulators\n"); + return ret; + } + + ret = regulator_bulk_enable(ARRAY_SIZE(ak8974->regs), ak8974->regs); + if (ret < 0) { + dev_err(&i2c->dev, "cannot enable regulators\n"); + return ret; + } + + /* Take runtime PM online */ + pm_runtime_get_noresume(&i2c->dev); + pm_runtime_set_active(&i2c->dev); + pm_runtime_enable(&i2c->dev); + + ak8974->map = devm_regmap_init_i2c(i2c, &ak8974_regmap_config); + if (IS_ERR(ak8974->map)) { + dev_err(&i2c->dev, "failed to allocate register map\n"); + return PTR_ERR(ak8974->map); + } + + ret = ak8974_set_power(ak8974, AK8974_PWR_ON); + if (ret) { + dev_err(&i2c->dev, "could not power on\n"); + goto power_off; + } + + ret = ak8974_detect(ak8974); + if (ret) { + dev_err(&i2c->dev, "neither AK8974 nor AMI305 found\n"); + goto power_off; + } + + ret = ak8974_selftest(ak8974); + if (ret) + dev_err(&i2c->dev, "selftest failed (continuing anyway)\n"); + + ret = ak8974_reset(ak8974); + if (ret) { + dev_err(&i2c->dev, "AK8974 reset failed\n"); + goto power_off; + } + + pm_runtime_set_autosuspend_delay(&i2c->dev, + AK8974_AUTOSUSPEND_DELAY); + pm_runtime_use_autosuspend(&i2c->dev); + pm_runtime_put(&i2c->dev); + + indio_dev->dev.parent = &i2c->dev; + indio_dev->channels = ak8974_channels; + indio_dev->num_channels = ARRAY_SIZE(ak8974_channels); + indio_dev->info = &ak8974_info; + indio_dev->available_scan_masks = ak8974_scan_masks; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->name = ak8974->name; + + ret = iio_triggered_buffer_setup(indio_dev, NULL, + ak8974_handle_trigger, + NULL); + if (ret) { + dev_err(&i2c->dev, "triggered buffer setup failed\n"); + goto disable_pm; + } + + /* If we have a valid DRDY IRQ, make use of it */ + if (irq > 0) { + irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq)); + if (irq_trig == IRQF_TRIGGER_RISING) { + dev_info(&i2c->dev, "enable rising edge DRDY IRQ\n"); + } else if (irq_trig == IRQF_TRIGGER_FALLING) { + ak8974->drdy_active_low = true; + dev_info(&i2c->dev, "enable falling edge DRDY IRQ\n"); + } else { + irq_trig = IRQF_TRIGGER_RISING; + } + irq_trig |= IRQF_ONESHOT; + irq_trig |= IRQF_SHARED; + + ret = devm_request_threaded_irq(&i2c->dev, + irq, + ak8974_drdy_irq, + ak8974_drdy_irq_thread, + irq_trig, + ak8974->name, + ak8974); + if (ret) { + dev_err(&i2c->dev, "unable to request DRDY IRQ " + "- proceeding without IRQ\n"); + goto no_irq; + } + ak8974->drdy_irq = true; + } + +no_irq: + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(&i2c->dev, "device register failed\n"); + goto cleanup_buffer; + } + + return 0; + +cleanup_buffer: + iio_triggered_buffer_cleanup(indio_dev); +disable_pm: + pm_runtime_put_noidle(&i2c->dev); + pm_runtime_disable(&i2c->dev); + ak8974_set_power(ak8974, AK8974_PWR_OFF); +power_off: + regulator_bulk_disable(ARRAY_SIZE(ak8974->regs), ak8974->regs); + + return ret; +} + +static int __exit ak8974_remove(struct i2c_client *i2c) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(i2c); + struct ak8974 *ak8974 = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); + pm_runtime_get_sync(&i2c->dev); + pm_runtime_put_noidle(&i2c->dev); + pm_runtime_disable(&i2c->dev); + ak8974_set_power(ak8974, AK8974_PWR_OFF); + regulator_bulk_disable(ARRAY_SIZE(ak8974->regs), ak8974->regs); + + return 0; +} + +#ifdef CONFIG_PM +static int ak8974_runtime_suspend(struct device *dev) +{ + struct ak8974 *ak8974 = + iio_priv(i2c_get_clientdata(to_i2c_client(dev))); + + ak8974_set_power(ak8974, AK8974_PWR_OFF); + regulator_bulk_disable(ARRAY_SIZE(ak8974->regs), ak8974->regs); + + return 0; +} + +static int ak8974_runtime_resume(struct device *dev) +{ + struct ak8974 *ak8974 = + iio_priv(i2c_get_clientdata(to_i2c_client(dev))); + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(ak8974->regs), ak8974->regs); + if (ret) + return ret; + msleep(AK8974_POWERON_DELAY); + ret = ak8974_set_power(ak8974, AK8974_PWR_ON); + if (ret) + goto out_regulator_disable; + + ret = ak8974_configure(ak8974); + if (ret) + goto out_disable_power; + + return 0; + +out_disable_power: + ak8974_set_power(ak8974, AK8974_PWR_OFF); +out_regulator_disable: + regulator_bulk_disable(ARRAY_SIZE(ak8974->regs), ak8974->regs); + + return ret; +} +#endif /* CONFIG_PM */ + +static const struct dev_pm_ops ak8974_dev_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) + SET_RUNTIME_PM_OPS(ak8974_runtime_suspend, + ak8974_runtime_resume, NULL) +}; + +static const struct i2c_device_id ak8974_id[] = { + {"ami305", 0 }, + {"ak8974", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, ak8974_id); + +static const struct of_device_id ak8974_of_match[] = { + { .compatible = "asahi-kasei,ak8974", }, + {} +}; +MODULE_DEVICE_TABLE(of, ak8974_of_match); + +static struct i2c_driver ak8974_driver = { + .driver = { + .name = "ak8974", + .owner = THIS_MODULE, + .pm = &ak8974_dev_pm_ops, + .of_match_table = of_match_ptr(ak8974_of_match), + }, + .probe = ak8974_probe, + .remove = __exit_p(ak8974_remove), + .id_table = ak8974_id, +}; +module_i2c_driver(ak8974_driver); + +MODULE_DESCRIPTION("AK8974 and AMI305 3-axis magnetometer driver"); +MODULE_AUTHOR("Samu Onkalo"); +MODULE_AUTHOR("Linus Walleij"); +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 281269f8a0b00f5c95de5158e8595ed51bdb4b0a Mon Sep 17 00:00:00 2001 From: Christophe JAILLET <christophe.jaillet@wanadoo.fr> Date: Wed, 10 Aug 2016 07:18:16 +0200 Subject: iio: light: us5182d: Add missing error code assignment before test It is likely that checking the result of 'pm_runtime_set_active' is expected here. Fixes: f0e5f57d3ac2 ("iio: light: us8152d: Add power management support") Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/light/us5182d.c b/drivers/iio/light/us5182d.c index 20c40f7..18cf2e2 100644 --- a/drivers/iio/light/us5182d.c +++ b/drivers/iio/light/us5182d.c @@ -894,7 +894,7 @@ static int us5182d_probe(struct i2c_client *client, goto out_err; if (data->default_continuous) { - pm_runtime_set_active(&client->dev); + ret = pm_runtime_set_active(&client->dev); if (ret < 0) goto out_err; } -- cgit v0.10.2 From ca1902ff98bcd9fe655028b19573e436fe9d3c76 Mon Sep 17 00:00:00 2001 From: Alison Schofield <amsfield22@gmail.com> Date: Mon, 25 Jul 2016 11:50:12 -0700 Subject: iio: humidity: hdc100x: add HDC1000 and HDC1008 to Kconfig hdc100x supports Texas Instruments HDC1000 and HDC1008 relative humidity and temperature sensors. Add these product names to Kconfig. Signed-off-by: Alison Schofield <amsfield22@gmail.com> Cc: Daniel Baluta <daniel.baluta@gmail.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/humidity/Kconfig b/drivers/iio/humidity/Kconfig index 738a86d..f155386 100644 --- a/drivers/iio/humidity/Kconfig +++ b/drivers/iio/humidity/Kconfig @@ -26,11 +26,11 @@ config HDC100X tristate "TI HDC100x relative humidity and temperature sensor" depends on I2C help - Say yes here to build support for the TI HDC100x series of - relative humidity and temperature sensors. + Say yes here to build support for the Texas Instruments + HDC1000 and HDC1008 relative humidity and temperature sensors. - To compile this driver as a module, choose M here: the module - will be called hdc100x. + To compile this driver as a module, choose M here: the module + will be called hdc100x. config HTU21 tristate "Measurement Specialties HTU21 humidity & temperature sensor" -- cgit v0.10.2 From b75b58b46b7cfd9c8e715bb3eada9e3892d217e2 Mon Sep 17 00:00:00 2001 From: Alison Schofield <amsfield22@gmail.com> Date: Mon, 25 Jul 2016 12:11:20 -0700 Subject: iio: accel: bma180: use iio helper function to guarantee direct mode Replace the code that guarantees the device stays in direct mode with iio_device_claim_direct_mode() which does same. Signed-off-by: Alison Schofield <amsfield22@gmail.com> Cc: Daniel Baluta <daniel.baluta@gmail.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c index e3f88ba..0890934 100644 --- a/drivers/iio/accel/bma180.c +++ b/drivers/iio/accel/bma180.c @@ -469,13 +469,14 @@ static int bma180_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + mutex_lock(&data->mutex); - if (iio_buffer_enabled(indio_dev)) { - mutex_unlock(&data->mutex); - return -EBUSY; - } ret = bma180_get_data_reg(data, chan->scan_index); mutex_unlock(&data->mutex); + iio_device_release_direct_mode(indio_dev); if (ret < 0) return ret; *val = sign_extend32(ret >> chan->scan_type.shift, -- cgit v0.10.2 From 1e1f9ff406fd5f6003a5dab2ab5a26c4c5bb8cbd Mon Sep 17 00:00:00 2001 From: James Simmons <jsimmons@infradead.org> Date: Mon, 20 Jun 2016 18:47:50 -0400 Subject: staging: lustre: llite: break ll_getxattr_common into 2 functions Split the function ll_getxattr_common into two functions. The code used for listing xattrs and ll_getxattr_common is placed into a new function ll_getxattr_list. This allows ll_listxattr to call directly ll_getxattr_list instead of going through ll_getxattr_common. This change is needed for the upcoming VFS move xattr_handler from [s|g]etxattr. Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/xattr.c b/drivers/staging/lustre/lustre/llite/xattr.c index 98303cf..a034a5f 100644 --- a/drivers/staging/lustre/lustre/llite/xattr.c +++ b/drivers/staging/lustre/lustre/llite/xattr.c @@ -217,69 +217,18 @@ int ll_removexattr(struct dentry *dentry, const char *name) OBD_MD_FLXATTRRM); } -static -int ll_getxattr_common(struct inode *inode, const char *name, - void *buffer, size_t size, __u64 valid) +static int +ll_xattr_list(struct inode *inode, const char *name, int type, void *buffer, + size_t size, __u64 valid) { + struct ll_inode_info *lli = ll_i2info(inode); struct ll_sb_info *sbi = ll_i2sbi(inode); struct ptlrpc_request *req = NULL; struct mdt_body *body; - int xattr_type, rc; void *xdata; - struct ll_inode_info *lli = ll_i2info(inode); - - CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p)\n", - PFID(ll_inode2fid(inode)), inode); - - /* listxattr have slightly different behavior from of ext3: - * without 'user_xattr' ext3 will list all xattr names but - * filtered out "^user..*"; we list them all for simplicity. - */ - if (!name) { - xattr_type = XATTR_OTHER_T; - goto do_getxattr; - } - - xattr_type = get_xattr_type(name); - rc = xattr_type_filter(sbi, xattr_type); - if (rc) - return rc; - - /* b15587: ignore security.capability xattr for now */ - if ((xattr_type == XATTR_SECURITY_T && - strcmp(name, "security.capability") == 0)) - return -ENODATA; - - /* LU-549: Disable security.selinux when selinux is disabled */ - if (xattr_type == XATTR_SECURITY_T && !selinux_is_enabled() && - strcmp(name, "security.selinux") == 0) - return -EOPNOTSUPP; - -#ifdef CONFIG_FS_POSIX_ACL - /* posix acl is under protection of LOOKUP lock. when calling to this, - * we just have path resolution to the target inode, so we have great - * chance that cached ACL is uptodate. - */ - if (xattr_type == XATTR_ACL_ACCESS_T) { - struct posix_acl *acl; - - spin_lock(&lli->lli_lock); - acl = posix_acl_dup(lli->lli_posix_acl); - spin_unlock(&lli->lli_lock); - - if (!acl) - return -ENODATA; - - rc = posix_acl_to_xattr(&init_user_ns, acl, buffer, size); - posix_acl_release(acl); - return rc; - } - if (xattr_type == XATTR_ACL_DEFAULT_T && !S_ISDIR(inode->i_mode)) - return -ENODATA; -#endif + int rc; -do_getxattr: - if (sbi->ll_xattr_cache_enabled && xattr_type != XATTR_ACL_ACCESS_T) { + if (sbi->ll_xattr_cache_enabled && type != XATTR_ACL_ACCESS_T) { rc = ll_xattr_cache_get(inode, name, buffer, size, valid); if (rc == -EAGAIN) goto getxattr_nocache; @@ -340,7 +289,7 @@ getxattr_nocache: } out_xattr: - if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) { + if (rc == -EOPNOTSUPP && type == XATTR_USER_T) { LCONSOLE_INFO( "%s: disabling user_xattr feature because it is not supported on the server: rc = %d\n", ll_get_fsname(inode->i_sb, NULL, 0), rc); @@ -351,6 +300,58 @@ out: return rc; } +static +int ll_getxattr_common(struct inode *inode, const char *name, + void *buffer, size_t size) +{ + struct ll_sb_info *sbi = ll_i2sbi(inode); + int xattr_type, rc; + struct ll_inode_info *lli = ll_i2info(inode); + + CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p)\n", + PFID(ll_inode2fid(inode)), inode); + + xattr_type = get_xattr_type(name); + rc = xattr_type_filter(sbi, xattr_type); + if (rc) + return rc; + + /* b15587: ignore security.capability xattr for now */ + if ((xattr_type == XATTR_SECURITY_T && + strcmp(name, "security.capability") == 0)) + return -ENODATA; + + /* LU-549: Disable security.selinux when selinux is disabled */ + if (xattr_type == XATTR_SECURITY_T && !selinux_is_enabled() && + strcmp(name, "security.selinux") == 0) + return -EOPNOTSUPP; + +#ifdef CONFIG_FS_POSIX_ACL + /* posix acl is under protection of LOOKUP lock. when calling to this, + * we just have path resolution to the target inode, so we have great + * chance that cached ACL is uptodate. + */ + if (xattr_type == XATTR_ACL_ACCESS_T) { + struct posix_acl *acl; + + spin_lock(&lli->lli_lock); + acl = posix_acl_dup(lli->lli_posix_acl); + spin_unlock(&lli->lli_lock); + + if (!acl) + return -ENODATA; + + rc = posix_acl_to_xattr(&init_user_ns, acl, buffer, size); + posix_acl_release(acl); + return rc; + } + if (xattr_type == XATTR_ACL_DEFAULT_T && !S_ISDIR(inode->i_mode)) + return -ENODATA; +#endif + return ll_xattr_list(inode, name, xattr_type, buffer, size, + OBD_MD_FLXATTR); +} + ssize_t ll_getxattr(struct dentry *dentry, struct inode *inode, const char *name, void *buffer, size_t size) { @@ -439,7 +440,7 @@ out: return rc; } - return ll_getxattr_common(inode, name, buffer, size, OBD_MD_FLXATTR); + return ll_getxattr_common(inode, name, buffer, size); } ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size) @@ -457,7 +458,8 @@ ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size) ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_LISTXATTR, 1); - rc = ll_getxattr_common(inode, NULL, buffer, size, OBD_MD_FLXATTRLS); + rc = ll_xattr_list(inode, NULL, XATTR_OTHER_T, buffer, size, + OBD_MD_FLXATTRLS); if (rc < 0) goto out; -- cgit v0.10.2 From 1b851095d64e55a4345cddf4928256b1452b25ed Mon Sep 17 00:00:00 2001 From: Ben Evans <bevans@cray.com> Date: Wed, 22 Jun 2016 11:19:54 -0400 Subject: staging: lustre: lnet: Remove old commented out code These #if 0 blocks have been in place for years. Assume they are not used and remove them Signed-off-by: Ben Evans <bevans@cray.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-8058 Reviewed-on: http://review.whamcloud.com/20414 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: James Simmons <uja.ornl@yahoo.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c index 07ec540..cbc9a9c 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c @@ -1468,11 +1468,6 @@ ksocknal_close_conn_locked(struct ksock_conn *conn, int error) conn->ksnc_route = NULL; -#if 0 /* irrelevant with only eager routes */ - /* make route least favourite */ - list_del(&route->ksnr_list); - list_add_tail(&route->ksnr_list, &peer->ksnp_routes); -#endif ksocknal_route_decref(route); /* drop conn's ref on route */ } diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c index 303576d..d53da55 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c @@ -2008,13 +2008,6 @@ ksocknal_connect(struct ksock_route *route) list_splice_init(&peer->ksnp_tx_queue, &zombies); } -#if 0 /* irrelevant with only eager routes */ - if (!route->ksnr_deleted) { - /* make this route least-favourite for re-selection */ - list_del(&route->ksnr_list); - list_add_tail(&route->ksnr_list, &peer->ksnp_routes); - } -#endif write_unlock_bh(&ksocknal_data.ksnd_global_lock); ksocknal_peer_failed(peer); diff --git a/drivers/staging/lustre/lnet/lnet/lib-msg.c b/drivers/staging/lustre/lnet/lnet/lib-msg.c index 910e106..0897e58 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-msg.c +++ b/drivers/staging/lustre/lnet/lnet/lib-msg.c @@ -449,23 +449,7 @@ lnet_finalize(lnet_ni_t *ni, lnet_msg_t *msg, int status) if (!msg) return; -#if 0 - CDEBUG(D_WARNING, "%s msg->%s Flags:%s%s%s%s%s%s%s%s%s%s%s txp %s rxp %s\n", - lnet_msgtyp2str(msg->msg_type), libcfs_id2str(msg->msg_target), - msg->msg_target_is_router ? "t" : "", - msg->msg_routing ? "X" : "", - msg->msg_ack ? "A" : "", - msg->msg_sending ? "S" : "", - msg->msg_receiving ? "R" : "", - msg->msg_delayed ? "d" : "", - msg->msg_txcredit ? "C" : "", - msg->msg_peertxcredit ? "c" : "", - msg->msg_rtrcredit ? "F" : "", - msg->msg_peerrtrcredit ? "f" : "", - msg->msg_onactivelist ? "!" : "", - !msg->msg_txpeer ? "<none>" : libcfs_nid2str(msg->msg_txpeer->lp_nid), - !msg->msg_rxpeer ? "<none>" : libcfs_nid2str(msg->msg_rxpeer->lp_nid)); -#endif + msg->msg_ev.status = status; if (msg->msg_md) { -- cgit v0.10.2 From 2c563880ea8fdc900693ae372fa07b3894f8ff63 Mon Sep 17 00:00:00 2001 From: James Simmons <jsimmons@infradead.org> Date: Mon, 11 Jul 2016 09:40:10 -0400 Subject: staging: lustre: llite: basic port to xattr_handler API Port the xattr functionality to the new xattr_handler API. This is smallest changes needed to move to this new API. The function ll_removexattr can be replaced by generic_removexattr as well since it also uses the xattr_handler set xattr backend. To tell the difference between the two cases we test the flag passed in for XATTR_REPLACE. The ll_getxattr function is replaced by the generic_getxattr function. Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 57281b9..58a7401 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -3213,10 +3213,10 @@ const struct inode_operations ll_file_inode_operations = { .setattr = ll_setattr, .getattr = ll_getattr, .permission = ll_inode_permission, - .setxattr = ll_setxattr, - .getxattr = ll_getxattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, .listxattr = ll_listxattr, - .removexattr = ll_removexattr, + .removexattr = generic_removexattr, .fiemap = ll_fiemap, .get_acl = ll_get_acl, }; diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 4d6d589..27d3f77 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -42,6 +42,7 @@ #include "../include/lustre_mdc.h" #include "../include/lustre_intent.h" #include <linux/compat.h> +#include <linux/xattr.h> #include <linux/posix_acl_xattr.h> #include "vvp_internal.h" @@ -933,12 +934,9 @@ static inline __u64 ll_file_maxbytes(struct inode *inode) } /* llite/xattr.c */ -int ll_setxattr(struct dentry *dentry, struct inode *inode, - const char *name, const void *value, size_t size, int flags); -ssize_t ll_getxattr(struct dentry *dentry, struct inode *inode, - const char *name, void *buffer, size_t size); +extern const struct xattr_handler *ll_xattr_handlers[]; + ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size); -int ll_removexattr(struct dentry *dentry, const char *name); /** * Common IO arguments for various VFS I/O interfaces. diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 546063e..75d568f 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -418,6 +418,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, CDEBUG(D_SUPER, "rootfid "DFID"\n", PFID(&sbi->ll_root_fid)); sb->s_op = &lustre_super_operations; + sb->s_xattr = ll_xattr_handlers; #if THREAD_SIZE >= 8192 /*b=17630*/ sb->s_export_op = &lustre_export_operations; #endif diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index 3664bfd..1e75f5b 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -1101,10 +1101,10 @@ const struct inode_operations ll_dir_inode_operations = { .setattr = ll_setattr, .getattr = ll_getattr, .permission = ll_inode_permission, - .setxattr = ll_setxattr, - .getxattr = ll_getxattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, .listxattr = ll_listxattr, - .removexattr = ll_removexattr, + .removexattr = generic_removexattr, .get_acl = ll_get_acl, }; @@ -1112,9 +1112,9 @@ const struct inode_operations ll_special_inode_operations = { .setattr = ll_setattr, .getattr = ll_getattr, .permission = ll_inode_permission, - .setxattr = ll_setxattr, - .getxattr = ll_getxattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, .listxattr = ll_listxattr, - .removexattr = ll_removexattr, + .removexattr = generic_removexattr, .get_acl = ll_get_acl, }; diff --git a/drivers/staging/lustre/lustre/llite/symlink.c b/drivers/staging/lustre/lustre/llite/symlink.c index 8c8bdfe..4601be9 100644 --- a/drivers/staging/lustre/lustre/llite/symlink.c +++ b/drivers/staging/lustre/lustre/llite/symlink.c @@ -155,8 +155,8 @@ const struct inode_operations ll_fast_symlink_inode_operations = { .get_link = ll_get_link, .getattr = ll_getattr, .permission = ll_inode_permission, - .setxattr = ll_setxattr, - .getxattr = ll_getxattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, .listxattr = ll_listxattr, - .removexattr = ll_removexattr, + .removexattr = generic_removexattr, }; diff --git a/drivers/staging/lustre/lustre/llite/xattr.c b/drivers/staging/lustre/lustre/llite/xattr.c index a034a5f..a02b802 100644 --- a/drivers/staging/lustre/lustre/llite/xattr.c +++ b/drivers/staging/lustre/lustre/llite/xattr.c @@ -99,46 +99,57 @@ int xattr_type_filter(struct ll_sb_info *sbi, int xattr_type) return 0; } -static -int ll_setxattr_common(struct inode *inode, const char *name, - const void *value, size_t size, - int flags, __u64 valid) +static int +ll_xattr_set_common(const struct xattr_handler *handler, + struct dentry *dentry, struct inode *inode, + const char *name, const void *value, size_t size, + int flags) { + char fullname[strlen(handler->prefix) + strlen(name) + 1]; struct ll_sb_info *sbi = ll_i2sbi(inode); struct ptlrpc_request *req = NULL; - int xattr_type, rc; const char *pv = value; + __u64 valid; + int rc; - xattr_type = get_xattr_type(name); - rc = xattr_type_filter(sbi, xattr_type); + if (flags == XATTR_REPLACE) { + ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_REMOVEXATTR, 1); + valid = OBD_MD_FLXATTRRM; + } else { + ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_SETXATTR, 1); + valid = OBD_MD_FLXATTR; + } + + rc = xattr_type_filter(sbi, handler->flags); if (rc) return rc; - if ((xattr_type == XATTR_ACL_ACCESS_T || - xattr_type == XATTR_ACL_DEFAULT_T) && + if ((handler->flags == XATTR_ACL_ACCESS_T || + handler->flags == XATTR_ACL_DEFAULT_T) && !inode_owner_or_capable(inode)) return -EPERM; /* b10667: ignore lustre special xattr for now */ - if ((xattr_type == XATTR_TRUSTED_T && strcmp(name, "trusted.lov") == 0) || - (xattr_type == XATTR_LUSTRE_T && strcmp(name, "lustre.lov") == 0)) + if ((handler->flags == XATTR_TRUSTED_T && !strcmp(name, "lov")) || + (handler->flags == XATTR_LUSTRE_T && !strcmp(name, "lov"))) return 0; /* b15587: ignore security.capability xattr for now */ - if ((xattr_type == XATTR_SECURITY_T && - strcmp(name, "security.capability") == 0)) + if ((handler->flags == XATTR_SECURITY_T && + !strcmp(name, "capability"))) return 0; /* LU-549: Disable security.selinux when selinux is disabled */ - if (xattr_type == XATTR_SECURITY_T && !selinux_is_enabled() && - strcmp(name, "security.selinux") == 0) + if (handler->flags == XATTR_SECURITY_T && !selinux_is_enabled() && + strcmp(name, "selinux") == 0) return -EOPNOTSUPP; + sprintf(fullname, "%s%s\n", handler->prefix, name); rc = md_setxattr(sbi->ll_md_exp, ll_inode2fid(inode), - valid, name, pv, size, 0, flags, + valid, fullname, pv, size, 0, flags, ll_i2suppgid(inode), &req); if (rc) { - if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) { + if (rc == -EOPNOTSUPP && handler->flags == XATTR_USER_T) { LCONSOLE_INFO("Disabling user_xattr feature because it is not supported on the server\n"); sbi->ll_flags &= ~LL_SBI_USER_XATTR; } @@ -149,8 +160,10 @@ int ll_setxattr_common(struct inode *inode, const char *name, return 0; } -int ll_setxattr(struct dentry *dentry, struct inode *inode, - const char *name, const void *value, size_t size, int flags) +static int ll_xattr_set(const struct xattr_handler *handler, + struct dentry *dentry, struct inode *inode, + const char *name, const void *value, size_t size, + int flags) { LASSERT(inode); LASSERT(name); @@ -158,20 +171,24 @@ int ll_setxattr(struct dentry *dentry, struct inode *inode, CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), xattr %s\n", PFID(ll_inode2fid(inode)), inode, name); - ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_SETXATTR, 1); - - if ((strncmp(name, XATTR_TRUSTED_PREFIX, - sizeof(XATTR_TRUSTED_PREFIX) - 1) == 0 && - strcmp(name + sizeof(XATTR_TRUSTED_PREFIX) - 1, "lov") == 0) || - (strncmp(name, XATTR_LUSTRE_PREFIX, - sizeof(XATTR_LUSTRE_PREFIX) - 1) == 0 && - strcmp(name + sizeof(XATTR_LUSTRE_PREFIX) - 1, "lov") == 0)) { + if (!strcmp(name, "lov")) { struct lov_user_md *lump = (struct lov_user_md *)value; + int op_type = flags == XATTR_REPLACE ? LPROC_LL_REMOVEXATTR : + LPROC_LL_SETXATTR; int rc = 0; + ll_stats_ops_tally(ll_i2sbi(inode), op_type, 1); + if (size != 0 && size < sizeof(struct lov_user_md)) return -EINVAL; + /* + * It is possible to set an xattr to a "" value of zero size. + * For this case we are going to treat it as a removal. + */ + if (!size && lump) + lump = NULL; + /* Attributes that are saved via getxattr will always have * the stripe_offset as 0. Instead, the MDS should be * allowed to pick the starting OST index. b=17846 @@ -194,27 +211,13 @@ int ll_setxattr(struct dentry *dentry, struct inode *inode, return rc; - } else if (strcmp(name, XATTR_NAME_LMA) == 0 || - strcmp(name, XATTR_NAME_LINK) == 0) + } else if (!strcmp(name, "lma") || !strcmp(name, "link")) { + ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_SETXATTR, 1); return 0; + } - return ll_setxattr_common(inode, name, value, size, flags, - OBD_MD_FLXATTR); -} - -int ll_removexattr(struct dentry *dentry, const char *name) -{ - struct inode *inode = d_inode(dentry); - - LASSERT(inode); - LASSERT(name); - - CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), xattr %s\n", - PFID(ll_inode2fid(inode)), inode, name); - - ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_REMOVEXATTR, 1); - return ll_setxattr_common(inode, name, NULL, 0, 0, - OBD_MD_FLXATTRRM); + return ll_xattr_set_common(handler, dentry, inode, name, value, size, + flags); } static int @@ -300,30 +303,31 @@ out: return rc; } -static -int ll_getxattr_common(struct inode *inode, const char *name, - void *buffer, size_t size) +static int ll_xattr_get_common(const struct xattr_handler *handler, + struct dentry *dentry, struct inode *inode, + const char *name, void *buffer, size_t size) { + char fullname[strlen(handler->prefix) + strlen(name) + 1]; struct ll_sb_info *sbi = ll_i2sbi(inode); - int xattr_type, rc; struct ll_inode_info *lli = ll_i2info(inode); + int rc; CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p)\n", PFID(ll_inode2fid(inode)), inode); - xattr_type = get_xattr_type(name); - rc = xattr_type_filter(sbi, xattr_type); + ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_GETXATTR, 1); + + rc = xattr_type_filter(sbi, handler->flags); if (rc) return rc; /* b15587: ignore security.capability xattr for now */ - if ((xattr_type == XATTR_SECURITY_T && - strcmp(name, "security.capability") == 0)) + if ((handler->flags == XATTR_SECURITY_T && !strcmp(name, "capability"))) return -ENODATA; /* LU-549: Disable security.selinux when selinux is disabled */ - if (xattr_type == XATTR_SECURITY_T && !selinux_is_enabled() && - strcmp(name, "security.selinux") == 0) + if (handler->flags == XATTR_SECURITY_T && !selinux_is_enabled() && + !strcmp(name, "selinux")) return -EOPNOTSUPP; #ifdef CONFIG_FS_POSIX_ACL @@ -331,7 +335,7 @@ int ll_getxattr_common(struct inode *inode, const char *name, * we just have path resolution to the target inode, so we have great * chance that cached ACL is uptodate. */ - if (xattr_type == XATTR_ACL_ACCESS_T) { + if (handler->flags == XATTR_ACL_ACCESS_T) { struct posix_acl *acl; spin_lock(&lli->lli_lock); @@ -345,15 +349,17 @@ int ll_getxattr_common(struct inode *inode, const char *name, posix_acl_release(acl); return rc; } - if (xattr_type == XATTR_ACL_DEFAULT_T && !S_ISDIR(inode->i_mode)) + if (handler->flags == XATTR_ACL_DEFAULT_T && !S_ISDIR(inode->i_mode)) return -ENODATA; #endif - return ll_xattr_list(inode, name, xattr_type, buffer, size, + sprintf(fullname, "%s%s\n", handler->prefix, name); + return ll_xattr_list(inode, fullname, handler->flags, buffer, size, OBD_MD_FLXATTR); } -ssize_t ll_getxattr(struct dentry *dentry, struct inode *inode, - const char *name, void *buffer, size_t size) +static int ll_xattr_get(const struct xattr_handler *handler, + struct dentry *dentry, struct inode *inode, + const char *name, void *buffer, size_t size) { LASSERT(inode); LASSERT(name); @@ -361,20 +367,15 @@ ssize_t ll_getxattr(struct dentry *dentry, struct inode *inode, CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), xattr %s\n", PFID(ll_inode2fid(inode)), inode, name); - ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_GETXATTR, 1); - - if ((strncmp(name, XATTR_TRUSTED_PREFIX, - sizeof(XATTR_TRUSTED_PREFIX) - 1) == 0 && - strcmp(name + sizeof(XATTR_TRUSTED_PREFIX) - 1, "lov") == 0) || - (strncmp(name, XATTR_LUSTRE_PREFIX, - sizeof(XATTR_LUSTRE_PREFIX) - 1) == 0 && - strcmp(name + sizeof(XATTR_LUSTRE_PREFIX) - 1, "lov") == 0)) { + if (!strcmp(name, "lov")) { struct lov_stripe_md *lsm; struct lov_user_md *lump; struct lov_mds_md *lmm = NULL; struct ptlrpc_request *request = NULL; int rc = 0, lmmsize = 0; + ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_GETXATTR, 1); + if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode)) return -ENODATA; @@ -440,7 +441,7 @@ out: return rc; } - return ll_getxattr_common(inode, name, buffer, size); + return ll_xattr_get_common(handler, dentry, inode, name, buffer, size); } ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size) @@ -520,3 +521,57 @@ out: return rc; } + +static const struct xattr_handler ll_user_xattr_handler = { + .prefix = XATTR_USER_PREFIX, + .flags = XATTR_USER_T, + .get = ll_xattr_get_common, + .set = ll_xattr_set_common, +}; + +static const struct xattr_handler ll_trusted_xattr_handler = { + .prefix = XATTR_TRUSTED_PREFIX, + .flags = XATTR_TRUSTED_T, + .get = ll_xattr_get, + .set = ll_xattr_set, +}; + +static const struct xattr_handler ll_security_xattr_handler = { + .prefix = XATTR_SECURITY_PREFIX, + .flags = XATTR_SECURITY_T, + .get = ll_xattr_get_common, + .set = ll_xattr_set_common, +}; + +static const struct xattr_handler ll_acl_access_xattr_handler = { + .prefix = XATTR_NAME_POSIX_ACL_ACCESS, + .flags = XATTR_ACL_ACCESS_T, + .get = ll_xattr_get_common, + .set = ll_xattr_set_common, +}; + +static const struct xattr_handler ll_acl_default_xattr_handler = { + .prefix = XATTR_NAME_POSIX_ACL_DEFAULT, + .flags = XATTR_ACL_DEFAULT_T, + .get = ll_xattr_get_common, + .set = ll_xattr_set_common, +}; + +static const struct xattr_handler ll_lustre_xattr_handler = { + .prefix = XATTR_LUSTRE_PREFIX, + .flags = XATTR_LUSTRE_T, + .get = ll_xattr_get, + .set = ll_xattr_set, +}; + +const struct xattr_handler *ll_xattr_handlers[] = { + &ll_user_xattr_handler, + &ll_trusted_xattr_handler, + &ll_security_xattr_handler, +#ifdef CONFIG_FS_POSIX_ACL + &ll_acl_access_xattr_handler, + &ll_acl_default_xattr_handler, +#endif + &ll_lustre_xattr_handler, + NULL, +}; -- cgit v0.10.2 From c08db984971b01cb8f87a688a828c067eeb02db3 Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Thu, 21 Jul 2016 22:43:54 -0400 Subject: staging: lustre: obd: expand op_cli_flags Add new flags for metadata handling. These flags are related to DNE2 handling. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/7043 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3531 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index a1bc2c4..e6fca90 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -867,6 +867,8 @@ struct md_op_data { enum op_cli_flags { CLI_SET_MEA = 1 << 0, CLI_RM_ENTRY = 1 << 1, + CLI_HASH64 = BIT(2), + CLI_API32 = BIT(3), }; struct md_enqueue_info; -- cgit v0.10.2 From f6718d1d9c9272849e2217a940269e65814e2fde Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Thu, 21 Jul 2016 22:43:55 -0400 Subject: staging: lustre: obd: rename struct lmv_stripe_md field mea to lmv Rename struct lmv_stripe_md in struct lustre_md from mea to lmv. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/7043 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3531 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index e6fca90..1575c82 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -1031,7 +1031,7 @@ enum { struct lustre_md { struct mdt_body *body; struct lov_stripe_md *lsm; - struct lmv_stripe_md *mea; + struct lmv_stripe_md *lmv; #ifdef CONFIG_FS_POSIX_ACL struct posix_acl *posix_acl; #endif diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 0e1588a..fac04f0 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -2571,8 +2571,8 @@ static int lmv_free_lustre_md(struct obd_export *exp, struct lustre_md *md) struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt = lmv->tgts[0]; - if (md->mea) - obd_free_memmd(exp, (void *)&md->mea); + if (md->lmv) + obd_free_memmd(exp, (void *)&md->lmv); if (!tgt || !tgt->ltd_exp) return -EINVAL; return md_free_lustre_md(tgt->ltd_exp, md); diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 542801f..55859a0 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -504,15 +504,15 @@ static int mdc_get_lustre_md(struct obd_export *exp, goto out; } - rc = obd_unpackmd(md_exp, (void *)&md->mea, lmv, + rc = obd_unpackmd(md_exp, (void *)&md->lmv, lmv, lmvsize); if (rc < 0) goto out; - if (rc < sizeof(*md->mea)) { + if (rc < sizeof(*md->lmv)) { CDEBUG(D_INFO, - "size too small: rc < sizeof(*md->mea) (%d < %d)\n", - rc, (int)sizeof(*md->mea)); + "size too small: rc < sizeof(*md->lmv) (%d < %d)\n", + rc, (int)sizeof(*md->lmv)); rc = -EPROTO; goto out; } -- cgit v0.10.2 From c55459a27665018a8c78347c398cf53cb1eef55f Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Thu, 21 Jul 2016 22:43:56 -0400 Subject: staging: lustre: ptlrpc: remove wirecheck for struct lmv_stripe_md Remove the wiretest check for this data structure. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/7043 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3531 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c index 6cc2b2e..4c500a9 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c +++ b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c @@ -2617,35 +2617,6 @@ void lustre_assert_wire_constants(void) LASSERTF((int)sizeof(((struct lmv_desc *)0)->ld_uuid) == 40, "found %lld\n", (long long)(int)sizeof(((struct lmv_desc *)0)->ld_uuid)); - /* Checks for struct lmv_stripe_md */ - LASSERTF((int)sizeof(struct lmv_stripe_md) == 32, "found %lld\n", - (long long)(int)sizeof(struct lmv_stripe_md)); - LASSERTF((int)offsetof(struct lmv_stripe_md, mea_magic) == 0, "found %lld\n", - (long long)(int)offsetof(struct lmv_stripe_md, mea_magic)); - LASSERTF((int)sizeof(((struct lmv_stripe_md *)0)->mea_magic) == 4, "found %lld\n", - (long long)(int)sizeof(((struct lmv_stripe_md *)0)->mea_magic)); - LASSERTF((int)offsetof(struct lmv_stripe_md, mea_count) == 4, "found %lld\n", - (long long)(int)offsetof(struct lmv_stripe_md, mea_count)); - LASSERTF((int)sizeof(((struct lmv_stripe_md *)0)->mea_count) == 4, "found %lld\n", - (long long)(int)sizeof(((struct lmv_stripe_md *)0)->mea_count)); - LASSERTF((int)offsetof(struct lmv_stripe_md, mea_master) == 8, "found %lld\n", - (long long)(int)offsetof(struct lmv_stripe_md, mea_master)); - LASSERTF((int)sizeof(((struct lmv_stripe_md *)0)->mea_master) == 4, "found %lld\n", - (long long)(int)sizeof(((struct lmv_stripe_md *)0)->mea_master)); - LASSERTF((int)offsetof(struct lmv_stripe_md, mea_padding) == 12, "found %lld\n", - (long long)(int)offsetof(struct lmv_stripe_md, mea_padding)); - LASSERTF((int)sizeof(((struct lmv_stripe_md *)0)->mea_padding) == 4, "found %lld\n", - (long long)(int)sizeof(((struct lmv_stripe_md *)0)->mea_padding)); - CLASSERT(LOV_MAXPOOLNAME == 16); - LASSERTF((int)offsetof(struct lmv_stripe_md, mea_pool_name[16]) == 32, "found %lld\n", - (long long)(int)offsetof(struct lmv_stripe_md, mea_pool_name[16])); - LASSERTF((int)sizeof(((struct lmv_stripe_md *)0)->mea_pool_name[16]) == 1, "found %lld\n", - (long long)(int)sizeof(((struct lmv_stripe_md *)0)->mea_pool_name[16])); - LASSERTF((int)offsetof(struct lmv_stripe_md, mea_ids[0]) == 32, "found %lld\n", - (long long)(int)offsetof(struct lmv_stripe_md, mea_ids[0])); - LASSERTF((int)sizeof(((struct lmv_stripe_md *)0)->mea_ids[0]) == 16, "found %lld\n", - (long long)(int)sizeof(((struct lmv_stripe_md *)0)->mea_ids[0])); - /* Checks for struct lov_desc */ LASSERTF((int)sizeof(struct lov_desc) == 88, "found %lld\n", (long long)(int)sizeof(struct lov_desc)); -- cgit v0.10.2 From 1c12cf634e3f9c03239a492f927a9eb374f67033 Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Thu, 21 Jul 2016 22:43:57 -0400 Subject: staging: lustre: llite: cache directory striping information Cache directory striping information that the clients receive from the metadata servers. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/7043 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3531 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 27d3f77..baa208f 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -173,6 +173,8 @@ struct ll_inode_info { * -- I am the owner of dir statahead. */ pid_t d_opendir_pid; + /* directory stripe information */ + struct lmv_stripe_md *d_lmv_md; } d; #define lli_readdir_mutex u.d.d_readdir_mutex @@ -180,6 +182,7 @@ struct ll_inode_info { #define lli_sai u.d.d_sai #define lli_sa_lock u.d.d_sa_lock #define lli_opendir_pid u.d.d_opendir_pid +#define lli_lmv_md u.d.d_lmv_md /* for non-directory */ struct { diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 75d568f..eb715be 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -2090,11 +2090,22 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, ll_i2gids(op_data->op_suppgids, i1, i2); op_data->op_fid1 = *ll_inode2fid(i1); + if (S_ISDIR(i1->i_mode)) + op_data->op_mea1 = ll_i2info(i1)->lli_lmv_md; - if (i2) + if (i2) { op_data->op_fid2 = *ll_inode2fid(i2); - else + if (S_ISDIR(i2->i_mode)) + op_data->op_mea2 = ll_i2info(i2)->lli_lmv_md; + } else { fid_zero(&op_data->op_fid2); + } + + if (ll_i2sbi(i1)->ll_flags & LL_SBI_64BIT_HASH) + op_data->op_cli_flags |= CLI_HASH64; + + if (ll_need_32bit_api(ll_i2sbi(i1))) + op_data->op_cli_flags |= CLI_API32; op_data->op_name = name; op_data->op_namelen = namelen; -- cgit v0.10.2 From 8e9dfe8a22024fc10bdef39b07a8a7c1d797d061 Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Thu, 21 Jul 2016 22:43:58 -0400 Subject: staging: lustre: lmv: add new lmv structures Newer lustre version on metadata servers support different version of lmv magic. This add the new data structures to handle these new lmv magic versions. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/7043 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3531 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 051864c..32471a6 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -2482,16 +2482,6 @@ struct lmv_desc { struct obd_uuid ld_uuid; }; -/* TODO: lmv_stripe_md should contain mds capabilities for all slave fids */ -struct lmv_stripe_md { - __u32 mea_magic; - __u32 mea_count; - __u32 mea_master; - __u32 mea_padding; - char mea_pool_name[LOV_MAXPOOLNAME]; - struct lu_fid mea_ids[0]; -}; - #define MEA_MAGIC_LAST_CHAR 0xb2221ca1 #define MEA_MAGIC_ALL_CHARS 0xb222a11c #define MEA_MAGIC_HASH_SEGMENT 0xb222a11b @@ -2500,6 +2490,77 @@ struct lmv_stripe_md { #define MAX_HASH_SIZE 0x7fffffffffffffffULL #define MAX_HASH_HIGHEST_BIT 0x1000000000000000ULL +/* lmv structures */ +#define LMV_MAGIC_V1 0x0CD10CD0 /* normal stripe lmv magic */ +#define LMV_USER_MAGIC 0x0CD20CD0 /* default lmv magic*/ +#define LMV_MAGIC LMV_MAGIC_V1 +struct lmv_mds_md_v1 { + __u32 lmv_magic; + __u32 lmv_stripe_count; /* stripe count */ + __u32 lmv_master_mdt_index; /* master MDT index */ + __u32 lmv_hash_type; /* dir stripe policy, i.e. indicate + * which hash function to be used + */ + __u32 lmv_layout_version; /* Used for directory restriping */ + __u32 lmv_padding; + char lmv_pool_name[LOV_MAXPOOLNAME]; /* pool name */ + struct lu_fid lmv_stripe_fids[0]; /* FIDs for each stripe */ +}; + +union lmv_mds_md { + __u32 lmv_magic; + struct lmv_mds_md_v1 lmv_md_v1; + struct lmv_user_md lmv_user_md; +}; + +static inline ssize_t lmv_mds_md_size(int stripe_count, unsigned int lmm_magic) +{ + ssize_t len = -EINVAL; + + switch (lmm_magic) { + case LMV_MAGIC_V1: { + struct lmv_mds_md_v1 *lmm1; + + len = sizeof(*lmm1); + len += stripe_count * sizeof(lmm1->lmv_stripe_fids[0]); + break; } + default: + break; + } + return len; +} + +static inline int lmv_mds_md_stripe_count_get(const union lmv_mds_md *lmm) +{ + switch (le32_to_cpu(lmm->lmv_magic)) { + case LMV_MAGIC_V1: + return le32_to_cpu(lmm->lmv_md_v1.lmv_stripe_count); + case LMV_USER_MAGIC: + return le32_to_cpu(lmm->lmv_user_md.lum_stripe_count); + default: + return -EINVAL; + } +} + +static inline int lmv_mds_md_stripe_count_set(union lmv_mds_md *lmm, + unsigned int stripe_count) +{ + int rc = 0; + + switch (le32_to_cpu(lmm->lmv_magic)) { + case LMV_MAGIC_V1: + lmm->lmv_md_v1.lmv_stripe_count = cpu_to_le32(stripe_count); + break; + case LMV_USER_MAGIC: + lmm->lmv_user_md.lum_stripe_count = cpu_to_le32(stripe_count); + break; + default: + rc = -EINVAL; + break; + } + return rc; +} + enum fld_rpc_opc { FLD_QUERY = 900, FLD_READ = 901, diff --git a/drivers/staging/lustre/lustre/include/lustre_lmv.h b/drivers/staging/lustre/lustre/include/lustre_lmv.h new file mode 100644 index 0000000..0620c8c --- /dev/null +++ b/drivers/staging/lustre/lustre/include/lustre_lmv.h @@ -0,0 +1,66 @@ +/* + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License version 2 for more details. A copy is + * included in the COPYING file that accompanied this code. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf + * + * GPL HEADER END + */ +/* + * Copyright (c) 2013, Intel Corporation. + */ +/* + * lustre/include/lustre_lmv.h + * + * Lustre LMV structures and functions. + * + * Author: Di Wang <di.wang@intel.com> + */ + +#ifndef _LUSTRE_LMV_H +#define _LUSTRE_LMV_H +#include "lustre/lustre_idl.h" + +struct lmv_oinfo { + struct lu_fid lmo_fid; + u32 lmo_mds; + struct inode *lmo_root; +}; + +struct lmv_stripe_md { + __u32 mea_magic; + __u32 mea_count; + __u32 mea_master; + __u32 mea_padding; + char mea_pool_name[LOV_MAXPOOLNAME]; + struct lu_fid mea_ids[0]; +}; + +union lmv_mds_md; + +int lmv_unpack_md(struct obd_export *exp, struct lmv_stripe_md **lsmp, + const union lmv_mds_md *lmm, int stripe_count); + +static inline int lmv_alloc_memmd(struct lmv_stripe_md **lsmp, int stripe_count) +{ + return lmv_unpack_md(NULL, lsmp, NULL, stripe_count); +} + +static inline void lmv_free_memmd(struct lmv_stripe_md *lsm) +{ + lmv_unpack_md(NULL, &lsm, NULL, 0); +} +#endif diff --git a/drivers/staging/lustre/lustre/lmv/lmv_internal.h b/drivers/staging/lustre/lustre/lmv/lmv_internal.h index 0beafc4..471470b 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_internal.h +++ b/drivers/staging/lustre/lustre/lmv/lmv_internal.h @@ -35,6 +35,7 @@ #include "../include/lustre/lustre_idl.h" #include "../include/obd.h" +#include "../include/lustre_lmv.h" #define LMV_MAX_TGT_COUNT 128 diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index fac04f0..8e83263 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -46,6 +46,7 @@ #include "../include/lustre_lib.h" #include "../include/lustre_net.h" #include "../include/obd_class.h" +#include "../include/lustre_lmv.h" #include "../include/lprocfs_status.h" #include "../include/lustre_lite.h" #include "../include/lustre_fid.h" diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 55859a0..702ced9 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -40,6 +40,7 @@ #include "../include/lustre_acl.h" #include "../include/obd_class.h" +#include "../include/lustre_lmv.h" #include "../include/lustre_fid.h" #include "../include/lprocfs_status.h" #include "../include/lustre_param.h" -- cgit v0.10.2 From 34a60457a8533068498679d31af91db66aaaae6e Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Thu, 21 Jul 2016 22:43:59 -0400 Subject: staging: lustre: mdc: handle IT_READDIR operations The readdir operations lock was incomplete. This patch fills in the missing pieces. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/7043 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3531 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 1575c82..17b8d22 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -801,9 +801,11 @@ static inline int it_to_lock_mode(struct lookup_intent *it) /* CREAT needs to be tested before open (both could be set) */ if (it->it_op & IT_CREAT) return LCK_CW; - else if (it->it_op & (IT_READDIR | IT_GETATTR | IT_OPEN | IT_LOOKUP | + else if (it->it_op & (IT_GETATTR | IT_OPEN | IT_LOOKUP | IT_LAYOUT)) return LCK_CR; + else if (it->it_op & IT_READDIR) + return LCK_PR; else if (it->it_op & IT_GETXATTR) return LCK_PR; else if (it->it_op & IT_SETXATTR) diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index f48b584..06a1274 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -903,6 +903,9 @@ static int mdc_finish_intent_lock(struct obd_export *exp, LASSERT(request != LP_POISON); LASSERT(request->rq_repmsg != LP_POISON); + if (it->it_op & IT_READDIR) + return 0; + if (!it_disposition(it, DISP_IT_EXECD)) { /* The server failed before it even started executing the * intent, i.e. because it couldn't unpack the request. @@ -1042,6 +1045,9 @@ int mdc_revalidate_lock(struct obd_export *exp, struct lookup_intent *it, MDS_INODELOCK_LOOKUP | MDS_INODELOCK_PERM; break; + case IT_READDIR: + policy.l_inodebits.bits = MDS_INODELOCK_UPDATE; + break; case IT_LAYOUT: policy.l_inodebits.bits = MDS_INODELOCK_LAYOUT; break; @@ -1119,7 +1125,7 @@ int mdc_intent_lock(struct obd_export *exp, struct md_op_data *op_data, lockh.cookie = 0; if (fid_is_sane(&op_data->op_fid2) && - (it->it_op & (IT_LOOKUP | IT_GETATTR))) { + (it->it_op & (IT_LOOKUP | IT_GETATTR | IT_READDIR))) { /* We could just return 1 immediately, but since we should only * be called in revalidate_it if we already have a lock, let's * verify that. -- cgit v0.10.2 From 969d25d401e6c9c70bcb43042c91e2e1b9831f00 Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Thu, 21 Jul 2016 22:44:00 -0400 Subject: staging: lustre: llite: label the debug info We report the inode size but never print in the debug message that the number reported is the size. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/7043 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3531 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 5b38177..4d81a64 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -615,7 +615,7 @@ static int ll_readdir(struct file *filp, struct dir_context *ctx) int api32 = ll_need_32bit_api(sbi); int rc; - CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p) pos %lu/%llu 32bit_api %d\n", + CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p) pos/size %lu/%llu 32bit_api %d\n", PFID(ll_inode2fid(inode)), inode, (unsigned long)pos, i_size_read(inode), api32); -- cgit v0.10.2 From 307bef744f65f219e81edd0e8610cb089cd3c262 Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Thu, 21 Jul 2016 22:44:01 -0400 Subject: staging: lustre: llite: pass struct md_op_data to ll_dir_read Add struct md_op_data as a parameter to ll_dir_read. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/7043 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3531 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 4d81a64..75d01764 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -489,7 +489,8 @@ static __u16 ll_dirent_type_get(struct lu_dirent *ent) return type; } -int ll_dir_read(struct inode *inode, struct dir_context *ctx) +int ll_dir_read(struct inode *inode, struct md_op_data *op_data, + struct dir_context *ctx) { struct ll_inode_info *info = ll_i2info(inode); struct ll_sb_info *sbi = ll_i2sbi(inode); @@ -613,6 +614,7 @@ static int ll_readdir(struct file *filp, struct dir_context *ctx) __u64 pos = lfd ? lfd->lfd_pos : 0; int hash64 = sbi->ll_flags & LL_SBI_64BIT_HASH; int api32 = ll_need_32bit_api(sbi); + struct md_op_data *op_data; int rc; CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p) pos/size %lu/%llu 32bit_api %d\n", @@ -627,8 +629,15 @@ static int ll_readdir(struct file *filp, struct dir_context *ctx) goto out; } + op_data = ll_prep_md_op_data(NULL, inode, inode, NULL, 0, 0, + LUSTRE_OPC_ANY, inode); + if (IS_ERR(op_data)) { + rc = PTR_ERR(op_data); + goto out; + } + ctx->pos = pos; - rc = ll_dir_read(inode, ctx); + rc = ll_dir_read(inode, op_data, ctx); if (lfd) lfd->lfd_pos = ctx->pos; if (ctx->pos == MDS_DIR_END_OFF) { @@ -640,6 +649,7 @@ static int ll_readdir(struct file *filp, struct dir_context *ctx) if (api32 && hash64) ctx->pos >>= 32; } + ll_finish_md_op_data(op_data); filp->f_version = inode->i_version; out: diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index baa208f..623455f 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -653,7 +653,8 @@ extern const struct file_operations ll_dir_operations; extern const struct inode_operations ll_dir_inode_operations; struct page *ll_get_dir_page(struct inode *dir, __u64 hash, struct ll_dir_chain *chain); -int ll_dir_read(struct inode *inode, struct dir_context *ctx); +int ll_dir_read(struct inode *inode, struct md_op_data *op_data, + struct dir_context *ctx); int ll_get_mdt_idx(struct inode *inode); /* llite/namei.c */ diff --git a/drivers/staging/lustre/lustre/llite/llite_nfs.c b/drivers/staging/lustre/lustre/llite/llite_nfs.c index 65972c8..b74582a9 100644 --- a/drivers/staging/lustre/lustre/llite/llite_nfs.c +++ b/drivers/staging/lustre/lustre/llite/llite_nfs.c @@ -255,6 +255,7 @@ static int ll_get_name(struct dentry *dentry, char *name, .lgd_fid = ll_i2info(d_inode(child))->lli_fid, .ctx.actor = ll_nfs_get_name_filldir, }; + struct md_op_data *op_data; if (!dir || !S_ISDIR(dir->i_mode)) { rc = -ENOTDIR; @@ -266,9 +267,17 @@ static int ll_get_name(struct dentry *dentry, char *name, goto out; } + op_data = ll_prep_md_op_data(NULL, dir, dir, NULL, 0, 0, + LUSTRE_OPC_ANY, dir); + if (IS_ERR(op_data)) { + rc = PTR_ERR(op_data); + goto out; + } + inode_lock(dir); - rc = ll_dir_read(dir, &lgd.ctx); + rc = ll_dir_read(dir, op_data, &lgd.ctx); inode_unlock(dir); + ll_finish_md_op_data(op_data); if (!rc && !lgd.lgd_found) rc = -ENOENT; out: diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c index c1cb6b1..6d9368c 100644 --- a/drivers/staging/lustre/lustre/llite/statahead.c +++ b/drivers/staging/lustre/lustre/llite/statahead.c @@ -1039,6 +1039,7 @@ static int ll_statahead_thread(void *arg) __u64 pos = 0; int first = 0; int rc = 0; + struct md_op_data *op_data; struct ll_dir_chain chain; struct l_wait_info lwi = { 0 }; @@ -1046,6 +1047,11 @@ static int ll_statahead_thread(void *arg) CDEBUG(D_READA, "statahead thread starting: sai %p, parent %pd\n", sai, parent); + op_data = ll_prep_md_op_data(NULL, dir, dir, NULL, 0, 0, + LUSTRE_OPC_ANY, dir); + if (IS_ERR(op_data)) + return PTR_ERR(op_data); + if (sbi->ll_flags & LL_SBI_AGL_ENABLED) ll_start_agl(parent, sai); @@ -1236,6 +1242,7 @@ do_it: } out: + ll_finish_md_op_data(op_data); if (sai->sai_agl_valid) { spin_lock(&plli->lli_agl_lock); thread_set_flags(agl_thread, SVC_STOPPING); -- cgit v0.10.2 From 0ddf80c1b97500e33c6efd79f0ea46fab9f3200e Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Thu, 21 Jul 2016 22:44:02 -0400 Subject: staging: lustre: llite: remove debug message in ll_dir_read Remove debug message and struct ll_inode_info. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/10761 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4906 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 75d01764..5b46dd8 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -492,7 +492,6 @@ static __u16 ll_dirent_type_get(struct lu_dirent *ent) int ll_dir_read(struct inode *inode, struct md_op_data *op_data, struct dir_context *ctx) { - struct ll_inode_info *info = ll_i2info(inode); struct ll_sb_info *sbi = ll_i2sbi(inode); __u64 pos = ctx->pos; int api32 = ll_need_32bit_api(sbi); @@ -596,8 +595,6 @@ int ll_dir_read(struct inode *inode, struct md_op_data *op_data, } } else { rc = PTR_ERR(page); - CERROR("error reading dir "DFID" at %lu: rc %d\n", - PFID(&info->lli_fid), (unsigned long)pos, rc); } } -- cgit v0.10.2 From b1f048c147bb192b25e37591cfc8855aa3c34d38 Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Thu, 21 Jul 2016 22:44:03 -0400 Subject: staging: lustre: llite: reduce indent in ll_dir_read Instead of making a large chunk of code conditional based on if a page is valid we reverse the page validity test and exit the loop if the page is invalid instead. This allows a section of code to reduce its indentation one level. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/10761 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4906 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 5b46dd8..77fadf1 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -508,93 +508,90 @@ int ll_dir_read(struct inode *inode, struct md_op_data *op_data, while (rc == 0 && !done) { struct lu_dirpage *dp; struct lu_dirent *ent; + __u64 hash; + __u64 next; + + if (IS_ERR(page)) { + rc = PTR_ERR(page); + break; + } + + hash = MDS_DIR_END_OFF; + dp = page_address(page); + for (ent = lu_dirent_start(dp); ent && !done; + ent = lu_dirent_next(ent)) { + __u16 type; + int namelen; + struct lu_fid fid; + __u64 lhash; + __u64 ino; - if (!IS_ERR(page)) { /* - * If page is empty (end of directory is reached), - * use this value. + * XXX: implement correct swabbing here. */ - __u64 hash = MDS_DIR_END_OFF; - __u64 next; - - dp = page_address(page); - for (ent = lu_dirent_start(dp); ent && !done; - ent = lu_dirent_next(ent)) { - __u16 type; - int namelen; - struct lu_fid fid; - __u64 lhash; - __u64 ino; + hash = le64_to_cpu(ent->lde_hash); + if (hash < pos) /* - * XXX: implement correct swabbing here. + * Skip until we find target hash + * value. */ + continue; - hash = le64_to_cpu(ent->lde_hash); - if (hash < pos) - /* - * Skip until we find target hash - * value. - */ - continue; - - namelen = le16_to_cpu(ent->lde_namelen); - if (namelen == 0) - /* - * Skip dummy record. - */ - continue; - - if (api32 && hash64) - lhash = hash >> 32; - else - lhash = hash; - fid_le_to_cpu(&fid, &ent->lde_fid); - ino = cl_fid_build_ino(&fid, api32); - type = ll_dirent_type_get(ent); - ctx->pos = lhash; - /* For 'll_nfs_get_name_filldir()', it will try - * to access the 'ent' through its 'lde_name', - * so the parameter 'name' for 'ctx->actor()' - * must be part of the 'ent'. + namelen = le16_to_cpu(ent->lde_namelen); + if (namelen == 0) + /* + * Skip dummy record. */ - done = !dir_emit(ctx, ent->lde_name, - namelen, ino, type); - } - next = le64_to_cpu(dp->ldp_hash_end); - if (!done) { - pos = next; - if (pos == MDS_DIR_END_OFF) { - /* - * End of directory reached. - */ - done = 1; - ll_release_page(page, 0); - } else if (1 /* chain is exhausted*/) { - /* - * Normal case: continue to the next - * page. - */ - ll_release_page(page, - le32_to_cpu(dp->ldp_flags) & - LDF_COLLIDE); - next = pos; - page = ll_get_dir_page(inode, pos, - &chain); - } else { - /* - * go into overflow page. - */ - LASSERT(le32_to_cpu(dp->ldp_flags) & + continue; + + if (api32 && hash64) + lhash = hash >> 32; + else + lhash = hash; + fid_le_to_cpu(&fid, &ent->lde_fid); + ino = cl_fid_build_ino(&fid, api32); + type = ll_dirent_type_get(ent); + ctx->pos = lhash; + /* For 'll_nfs_get_name_filldir()', it will try + * to access the 'ent' through its 'lde_name', + * so the parameter 'name' for 'ctx->actor()' + * must be part of the 'ent'. + */ + done = !dir_emit(ctx, ent->lde_name, + namelen, ino, type); + } + next = le64_to_cpu(dp->ldp_hash_end); + if (!done) { + pos = next; + if (pos == MDS_DIR_END_OFF) { + /* + * End of directory reached. + */ + done = 1; + ll_release_page(page, 0); + } else if (1 /* chain is exhausted*/) { + /* + * Normal case: continue to the next + * page. + */ + ll_release_page(page, + le32_to_cpu(dp->ldp_flags) & LDF_COLLIDE); - ll_release_page(page, 1); - } + next = pos; + page = ll_get_dir_page(inode, pos, + &chain); } else { - pos = hash; - ll_release_page(page, 0); + /* + * go into overflow page. + */ + LASSERT(le32_to_cpu(dp->ldp_flags) & + LDF_COLLIDE); + ll_release_page(page, 1); } } else { - rc = PTR_ERR(page); + pos = hash; + ll_release_page(page, 0); } } -- cgit v0.10.2 From fb659ca1a6ef6a952da1af50a63210e8cfb6daca Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Thu, 21 Jul 2016 22:44:04 -0400 Subject: staging: lustre: llite: set next only when needed in ll_dir_read The variable next needs only to be set when done is false. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/10761 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4906 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 77fadf1..48eacee 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -561,8 +561,9 @@ int ll_dir_read(struct inode *inode, struct md_op_data *op_data, done = !dir_emit(ctx, ent->lde_name, namelen, ino, type); } - next = le64_to_cpu(dp->ldp_hash_end); + if (!done) { + next = le64_to_cpu(dp->ldp_hash_end); pos = next; if (pos == MDS_DIR_END_OFF) { /* -- cgit v0.10.2 From fee8cc87512ff3835093392656bcaa140c479709 Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Thu, 21 Jul 2016 22:44:05 -0400 Subject: staging: lustre: llite: handle done flags differently in ll_dir_read Invert the done flag test to reduce the code indentation. If done is true release the page and break out of the while loop. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/10761 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4906 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 48eacee..e4d3176 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -562,37 +562,38 @@ int ll_dir_read(struct inode *inode, struct md_op_data *op_data, namelen, ino, type); } - if (!done) { - next = le64_to_cpu(dp->ldp_hash_end); - pos = next; - if (pos == MDS_DIR_END_OFF) { - /* - * End of directory reached. - */ - done = 1; - ll_release_page(page, 0); - } else if (1 /* chain is exhausted*/) { - /* - * Normal case: continue to the next - * page. - */ - ll_release_page(page, - le32_to_cpu(dp->ldp_flags) & - LDF_COLLIDE); - next = pos; - page = ll_get_dir_page(inode, pos, - &chain); - } else { - /* - * go into overflow page. - */ - LASSERT(le32_to_cpu(dp->ldp_flags) & - LDF_COLLIDE); - ll_release_page(page, 1); - } - } else { + if (done) { pos = hash; ll_release_page(page, 0); + break; + } + + next = le64_to_cpu(dp->ldp_hash_end); + pos = next; + if (pos == MDS_DIR_END_OFF) { + /* + * End of directory reached. + */ + done = 1; + ll_release_page(page, 0); + } else if (1 /* chain is exhausted*/) { + /* + * Normal case: continue to the next + * page. + */ + ll_release_page(page, + le32_to_cpu(dp->ldp_flags) & + LDF_COLLIDE); + next = pos; + page = ll_get_dir_page(inode, pos, + &chain); + } else { + /* + * go into overflow page. + */ + LASSERT(le32_to_cpu(dp->ldp_flags) & + LDF_COLLIDE); + ll_release_page(page, 1); } } -- cgit v0.10.2 From 13810b0f564bc3a299075b9a7b6e865adea8cabe Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Thu, 21 Jul 2016 22:44:06 -0400 Subject: staging: lustre: llite: change done flag in ll_dir_read to bool Change the done flag from integer to bool. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/10761 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4906 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index e4d3176..70a3ca0 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -498,7 +498,7 @@ int ll_dir_read(struct inode *inode, struct md_op_data *op_data, int hash64 = sbi->ll_flags & LL_SBI_64BIT_HASH; struct page *page; struct ll_dir_chain chain; - int done = 0; + bool done = false; int rc = 0; ll_dir_chain_init(&chain); -- cgit v0.10.2 From 67537558c473e80ac2cb39b37f5bce14381a260f Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Thu, 21 Jul 2016 22:44:07 -0400 Subject: staging: lustre: llite: rename some variables for ll_dir_read The variables api32 and hash64 was renamed to is_api32 and is_hash64. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/7043 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3531 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 70a3ca0..907fae4 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -494,8 +494,8 @@ int ll_dir_read(struct inode *inode, struct md_op_data *op_data, { struct ll_sb_info *sbi = ll_i2sbi(inode); __u64 pos = ctx->pos; - int api32 = ll_need_32bit_api(sbi); - int hash64 = sbi->ll_flags & LL_SBI_64BIT_HASH; + int is_api32 = ll_need_32bit_api(sbi); + int is_hash64 = sbi->ll_flags & LL_SBI_64BIT_HASH; struct page *page; struct ll_dir_chain chain; bool done = false; @@ -545,12 +545,12 @@ int ll_dir_read(struct inode *inode, struct md_op_data *op_data, */ continue; - if (api32 && hash64) + if (is_api32 && is_hash64) lhash = hash >> 32; else lhash = hash; fid_le_to_cpu(&fid, &ent->lde_fid); - ino = cl_fid_build_ino(&fid, api32); + ino = cl_fid_build_ino(&fid, is_api32); type = ll_dirent_type_get(ent); ctx->pos = lhash; /* For 'll_nfs_get_name_filldir()', it will try -- cgit v0.10.2 From 4f48c52c57d4adf1f67757ae1a3b4b6ae091a90d Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Thu, 21 Jul 2016 22:44:08 -0400 Subject: staging: lustre: llite: clarify some debug messages for statahead Make some of the error reporting more clear for the statahead thread startup and is_first_dirent() function. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/7043 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3531 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c index 6d9368c..b1994a7 100644 --- a/drivers/staging/lustre/lustre/llite/statahead.c +++ b/drivers/staging/lustre/lustre/llite/statahead.c @@ -1075,9 +1075,9 @@ static int ll_statahead_thread(void *arg) if (IS_ERR(page)) { rc = PTR_ERR(page); - CDEBUG(D_READA, "error reading dir "DFID" at %llu/%llu: [rc %d] [parent %u]\n", + CDEBUG(D_READA, "error reading dir "DFID" at %llu/%llu: opendir_pid = %u: rc = %d\n", PFID(ll_inode2fid(dir)), pos, sai->sai_index, - rc, plli->lli_opendir_pid); + plli->lli_opendir_pid, rc); goto out; } @@ -1364,9 +1364,10 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry) struct ll_inode_info *lli = ll_i2info(dir); rc = PTR_ERR(page); - CERROR("error reading dir "DFID" at %llu: [rc %d] [parent %u]\n", + CERROR("%s: error reading dir "DFID" at %llu: opendir_pid = %u : rc = %d\n", + ll_get_fsname(dir->i_sb, NULL, 0), PFID(ll_inode2fid(dir)), pos, - rc, lli->lli_opendir_pid); + lli->lli_opendir_pid, rc); break; } -- cgit v0.10.2 From 26f5c084c6cf87de694d62308a97293158e10c37 Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Thu, 21 Jul 2016 22:44:09 -0400 Subject: staging: lustre: llite: remove code never called We have if (1) conditionals which is pointless so remove it and the next code block is never called so remove that as well. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/7043 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3531 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 907fae4..2307e70 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -576,7 +576,7 @@ int ll_dir_read(struct inode *inode, struct md_op_data *op_data, */ done = 1; ll_release_page(page, 0); - } else if (1 /* chain is exhausted*/) { + } else { /* * Normal case: continue to the next * page. @@ -587,13 +587,6 @@ int ll_dir_read(struct inode *inode, struct md_op_data *op_data, next = pos; page = ll_get_dir_page(inode, pos, &chain); - } else { - /* - * go into overflow page. - */ - LASSERT(le32_to_cpu(dp->ldp_flags) & - LDF_COLLIDE); - ll_release_page(page, 1); } } diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c index b1994a7..df51f14 100644 --- a/drivers/staging/lustre/lustre/llite/statahead.c +++ b/drivers/staging/lustre/lustre/llite/statahead.c @@ -1224,7 +1224,7 @@ do_it: rc = 0; goto out; - } else if (1) { + } else { /* * chain is exhausted. * Normal case: continue to the next page. @@ -1232,12 +1232,6 @@ do_it: ll_release_page(page, le32_to_cpu(dp->ldp_flags) & LDF_COLLIDE); page = ll_get_dir_page(dir, pos, &chain); - } else { - LASSERT(le32_to_cpu(dp->ldp_flags) & LDF_COLLIDE); - ll_release_page(page, 1); - /* - * go into overflow page. - */ } } @@ -1434,8 +1428,8 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry) * End of directory reached. */ ll_release_page(page, 0); - break; - } else if (1) { + goto out; + } else { /* * chain is exhausted * Normal case: continue to the next page. @@ -1443,12 +1437,6 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry) ll_release_page(page, le32_to_cpu(dp->ldp_flags) & LDF_COLLIDE); page = ll_get_dir_page(dir, pos, &chain); - } else { - /* - * go into overflow page. - */ - LASSERT(le32_to_cpu(dp->ldp_flags) & LDF_COLLIDE); - ll_release_page(page, 1); } } -- cgit v0.10.2 From 218ba48524ae1ac88e239aa2dbcf6017120dc180 Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Thu, 21 Jul 2016 22:44:10 -0400 Subject: staging: lustre: llite: pass in __u64 pos for ll_dir_read Some cases we want to preserve the ctx->pos value or use a different value altogther. So allow the passing in of a position offset to ll_dir_read. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/10761 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4906 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 2307e70..031c9e4 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -489,11 +489,11 @@ static __u16 ll_dirent_type_get(struct lu_dirent *ent) return type; } -int ll_dir_read(struct inode *inode, struct md_op_data *op_data, +int ll_dir_read(struct inode *inode, __u64 *ppos, struct md_op_data *op_data, struct dir_context *ctx) { struct ll_sb_info *sbi = ll_i2sbi(inode); - __u64 pos = ctx->pos; + __u64 pos = *ppos; int is_api32 = ll_need_32bit_api(sbi); int is_hash64 = sbi->ll_flags & LL_SBI_64BIT_HASH; struct page *page; @@ -626,18 +626,21 @@ static int ll_readdir(struct file *filp, struct dir_context *ctx) } ctx->pos = pos; - rc = ll_dir_read(inode, op_data, ctx); + rc = ll_dir_read(inode, &pos, op_data, ctx); + pos = ctx->pos; if (lfd) - lfd->lfd_pos = ctx->pos; - if (ctx->pos == MDS_DIR_END_OFF) { + lfd->lfd_pos = pos; + + if (pos == MDS_DIR_END_OFF) { if (api32) - ctx->pos = LL_DIR_END_OFF_32BIT; + pos = LL_DIR_END_OFF_32BIT; else - ctx->pos = LL_DIR_END_OFF; + pos = LL_DIR_END_OFF; } else { if (api32 && hash64) - ctx->pos >>= 32; + pos >>= 32; } + ctx->pos = pos; ll_finish_md_op_data(op_data); filp->f_version = inode->i_version; diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 623455f..e650aeb 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -653,7 +653,7 @@ extern const struct file_operations ll_dir_operations; extern const struct inode_operations ll_dir_inode_operations; struct page *ll_get_dir_page(struct inode *dir, __u64 hash, struct ll_dir_chain *chain); -int ll_dir_read(struct inode *inode, struct md_op_data *op_data, +int ll_dir_read(struct inode *inode, __u64 *ppos, struct md_op_data *op_data, struct dir_context *ctx); int ll_get_mdt_idx(struct inode *inode); diff --git a/drivers/staging/lustre/lustre/llite/llite_nfs.c b/drivers/staging/lustre/lustre/llite/llite_nfs.c index b74582a9..74eb1fc 100644 --- a/drivers/staging/lustre/lustre/llite/llite_nfs.c +++ b/drivers/staging/lustre/lustre/llite/llite_nfs.c @@ -256,6 +256,7 @@ static int ll_get_name(struct dentry *dentry, char *name, .ctx.actor = ll_nfs_get_name_filldir, }; struct md_op_data *op_data; + __u64 pos = 0; if (!dir || !S_ISDIR(dir->i_mode)) { rc = -ENOTDIR; @@ -275,7 +276,7 @@ static int ll_get_name(struct dentry *dentry, char *name, } inode_lock(dir); - rc = ll_dir_read(dir, op_data, &lgd.ctx); + rc = ll_dir_read(dir, &pos, op_data, &lgd.ctx); inode_unlock(dir); ll_finish_md_op_data(op_data); if (!rc && !lgd.lgd_found) -- cgit v0.10.2 From 2afad7fc9fc397d0540704c0602e80dfcec145b5 Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Thu, 21 Jul 2016 22:44:11 -0400 Subject: staging: lustre: llite: do post work for statahead in readdir case Increase the post-work for the statahead thread in the readdir case since it can become very busy. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/10761 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4906 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index e650aeb..dc15957 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -997,7 +997,8 @@ struct ll_statahead_info { unsigned int sai_ls_all:1, /* "ls -al", do stat-ahead for * hidden entries */ - sai_agl_valid:1;/* AGL is valid for the dir */ + sai_agl_valid:1,/* AGL is valid for the dir */ + sai_in_readpage:1;/* statahead is in readdir() */ wait_queue_head_t sai_waitq; /* stat-ahead wait queue */ struct ptlrpc_thread sai_thread; /* stat-ahead thread */ struct ptlrpc_thread sai_agl_thread; /* AGL thread */ diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c index df51f14..54ed52e 100644 --- a/drivers/staging/lustre/lustre/llite/statahead.c +++ b/drivers/staging/lustre/lustre/llite/statahead.c @@ -1231,7 +1231,9 @@ do_it: */ ll_release_page(page, le32_to_cpu(dp->ldp_flags) & LDF_COLLIDE); + sai->sai_in_readpage = 1; page = ll_get_dir_page(dir, pos, &chain); + sai->sai_in_readpage = 0; } } @@ -1550,6 +1552,11 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp, return entry ? 1 : -EAGAIN; } + /* if statahead is busy in readdir, help it do post-work */ + while (!ll_sa_entry_stated(entry) && sai->sai_in_readpage && + !sa_received_empty(sai)) + ll_post_statahead(sai); + if (!ll_sa_entry_stated(entry)) { sai->sai_index_wait = entry->se_index; lwi = LWI_TIMEOUT_INTR(cfs_time_seconds(30), NULL, -- cgit v0.10.2 From fd25dc346043380997a0e5563f81c3e94019c238 Mon Sep 17 00:00:00 2001 From: Al Viro <viro@zeniv.linux.org.uk> Date: Sat, 23 Jul 2016 02:36:58 -0400 Subject: lustre: switch lnet_sock_write() to sock_sendmsg() Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lnet/lnet/lib-socket.c b/drivers/staging/lustre/lnet/lnet/lib-socket.c index 891fd59..4e6dd51 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-socket.c +++ b/drivers/staging/lustre/lnet/lnet/lib-socket.c @@ -265,21 +265,17 @@ lnet_sock_write(struct socket *sock, void *buffer, int nob, int timeout) long jiffies_left = timeout * msecs_to_jiffies(MSEC_PER_SEC); unsigned long then; struct timeval tv; + struct kvec iov = { .iov_base = buffer, .iov_len = nob }; + struct msghdr msg = {NULL,}; LASSERT(nob > 0); /* * Caller may pass a zero timeout if she thinks the socket buffer is * empty enough to take the whole message immediately */ + iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &iov, 1, nob); for (;;) { - struct kvec iov = { - .iov_base = buffer, - .iov_len = nob - }; - struct msghdr msg = { - .msg_flags = !timeout ? MSG_DONTWAIT : 0 - }; - + msg.msg_flags = !timeout ? MSG_DONTWAIT : 0; if (timeout) { /* Set send timeout to remaining time */ jiffies_to_timeval(jiffies_left, &tv); @@ -296,9 +292,6 @@ lnet_sock_write(struct socket *sock, void *buffer, int nob, int timeout) rc = kernel_sendmsg(sock, &msg, &iov, 1, nob); jiffies_left -= jiffies - then; - if (rc == nob) - return 0; - if (rc < 0) return rc; @@ -307,11 +300,11 @@ lnet_sock_write(struct socket *sock, void *buffer, int nob, int timeout) return -ECONNABORTED; } + if (!msg_data_left(&msg)) + break; + if (jiffies_left <= 0) return -EAGAIN; - - buffer = ((char *)buffer) + rc; - nob -= rc; } return 0; } -- cgit v0.10.2 From 28ac4ad0e3b12c38a6aee53ea57a328c0821eeec Mon Sep 17 00:00:00 2001 From: Al Viro <viro@zeniv.linux.org.uk> Date: Sat, 23 Jul 2016 02:36:59 -0400 Subject: lustre: simplify the living hell out of ksocknal_lib_recv_kiov() ... by using ITER_BVEC recvmsg Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h index a56632b..d5efb42 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h @@ -86,8 +86,10 @@ struct ksock_sched { /* per scheduler state */ int kss_nconns; /* # connections assigned to * this scheduler */ struct ksock_sched_info *kss_info; /* owner of it */ - struct page *kss_rx_scratch_pgs[LNET_MAX_IOV]; - struct kvec kss_scratch_iov[LNET_MAX_IOV]; + union { + struct bio_vec kss_scratch_bvec[LNET_MAX_IOV]; + struct kvec kss_scratch_iov[LNET_MAX_IOV]; + }; }; struct ksock_sched_info { diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c index 6a17757..8479b53 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c @@ -259,67 +259,11 @@ ksocknal_lib_recv_iov(struct ksock_conn *conn) return rc; } -static void -ksocknal_lib_kiov_vunmap(void *addr) -{ - if (!addr) - return; - - vunmap(addr); -} - -static void * -ksocknal_lib_kiov_vmap(lnet_kiov_t *kiov, int niov, - struct kvec *iov, struct page **pages) -{ - void *addr; - int nob; - int i; - - if (!*ksocknal_tunables.ksnd_zc_recv || !pages) - return NULL; - - LASSERT(niov <= LNET_MAX_IOV); - - if (niov < 2 || - niov < *ksocknal_tunables.ksnd_zc_recv_min_nfrags) - return NULL; - - for (nob = i = 0; i < niov; i++) { - if ((kiov[i].kiov_offset && i > 0) || - (kiov[i].kiov_offset + kiov[i].kiov_len != PAGE_SIZE && i < niov - 1)) - return NULL; - - pages[i] = kiov[i].kiov_page; - nob += kiov[i].kiov_len; - } - - addr = vmap(pages, niov, VM_MAP, PAGE_KERNEL); - if (!addr) - return NULL; - - iov->iov_base = addr + kiov[0].kiov_offset; - iov->iov_len = nob; - - return addr; -} - int ksocknal_lib_recv_kiov(struct ksock_conn *conn) { -#if SOCKNAL_SINGLE_FRAG_RX || !SOCKNAL_RISK_KMAP_DEADLOCK - struct kvec scratch; - struct kvec *scratchiov = &scratch; - struct page **pages = NULL; - unsigned int niov = 1; -#else -#ifdef CONFIG_HIGHMEM -#warning "XXX risk of kmap deadlock on multiple frags..." -#endif - struct kvec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov; - struct page **pages = conn->ksnc_scheduler->kss_rx_scratch_pgs; + struct bio_vec *bv = conn->ksnc_scheduler->kss_scratch_bvec; unsigned int niov = conn->ksnc_rx_nkiov; -#endif lnet_kiov_t *kiov = conn->ksnc_rx_kiov; struct msghdr msg = { .msg_flags = 0 @@ -328,44 +272,26 @@ ksocknal_lib_recv_kiov(struct ksock_conn *conn) int i; int rc; void *base; - void *addr; int sum; int fragnob; int n; - /* - * NB we can't trust socket ops to either consume our iovs - * or leave them alone. - */ - addr = ksocknal_lib_kiov_vmap(kiov, niov, scratchiov, pages); - if (addr) { - nob = scratchiov[0].iov_len; - n = 1; - - } else { - for (nob = i = 0; i < niov; i++) { - nob += scratchiov[i].iov_len = kiov[i].kiov_len; - scratchiov[i].iov_base = kmap(kiov[i].kiov_page) + - kiov[i].kiov_offset; - } - n = niov; + for (nob = i = 0; i < niov; i++) { + nob += bv[i].bv_len = kiov[i].kiov_len; + bv[i].bv_page = kiov[i].kiov_page; + bv[i].bv_offset = kiov[i].kiov_offset; } + n = niov; LASSERT(nob <= conn->ksnc_rx_nob_wanted); - rc = kernel_recvmsg(conn->ksnc_sock, &msg, (struct kvec *)scratchiov, - n, nob, MSG_DONTWAIT); + iov_iter_bvec(&msg.msg_iter, READ | ITER_BVEC, bv, n, nob); + rc = sock_recvmsg(conn->ksnc_sock, &msg, MSG_DONTWAIT); if (conn->ksnc_msg.ksm_csum) { for (i = 0, sum = rc; sum > 0; i++, sum -= fragnob) { LASSERT(i < niov); - /* - * Dang! have to kmap again because I have nowhere to - * stash the mapped address. But by doing it while the - * page is still mapped, the kernel just bumps the map - * count and returns me the address it stashed. - */ base = kmap(kiov[i].kiov_page) + kiov[i].kiov_offset; fragnob = kiov[i].kiov_len; if (fragnob > sum) @@ -377,14 +303,6 @@ ksocknal_lib_recv_kiov(struct ksock_conn *conn) kunmap(kiov[i].kiov_page); } } - - if (addr) { - ksocknal_lib_kiov_vunmap(addr); - } else { - for (i = 0; i < niov; i++) - kunmap(kiov[i].kiov_page); - } - return rc; } -- cgit v0.10.2 From 65ffc6799340818e640bc59ab8a296efb1ed7c42 Mon Sep 17 00:00:00 2001 From: Al Viro <viro@zeniv.linux.org.uk> Date: Sat, 23 Jul 2016 02:37:00 -0400 Subject: lustre: don't reinvent struct bio_vec Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/include/linux/lnet/types.h b/drivers/staging/lustre/include/linux/lnet/types.h index e098b6c..f8be0e2 100644 --- a/drivers/staging/lustre/include/linux/lnet/types.h +++ b/drivers/staging/lustre/include/linux/lnet/types.h @@ -503,21 +503,7 @@ typedef struct { /* NB lustre portals uses struct iovec internally! */ typedef struct iovec lnet_md_iovec_t; -/** - * A page-based fragment of a MD. - */ -typedef struct { - /** Pointer to the page where the fragment resides */ - struct page *kiov_page; - /** Length in bytes of the fragment */ - unsigned int kiov_len; - /** - * Starting offset of the fragment within the page. Note that the - * end of the fragment must not pass the end of the page; i.e., - * kiov_len + kiov_offset <= PAGE_SIZE. - */ - unsigned int kiov_offset; -} lnet_kiov_t; +typedef struct bio_vec lnet_kiov_t; /** @} lnet_md */ /** \addtogroup lnet_eq diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index 596a697..9eb1db6 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -717,8 +717,8 @@ kiblnd_setup_rd_kiov(lnet_ni_t *ni, struct kib_tx *tx, struct kib_rdma_desc *rd, LASSERT(nkiov > 0); LASSERT(net); - while (offset >= kiov->kiov_len) { - offset -= kiov->kiov_len; + while (offset >= kiov->bv_len) { + offset -= kiov->bv_len; nkiov--; kiov++; LASSERT(nkiov > 0); @@ -728,10 +728,10 @@ kiblnd_setup_rd_kiov(lnet_ni_t *ni, struct kib_tx *tx, struct kib_rdma_desc *rd, do { LASSERT(nkiov > 0); - fragnob = min((int)(kiov->kiov_len - offset), nob); + fragnob = min((int)(kiov->bv_len - offset), nob); - sg_set_page(sg, kiov->kiov_page, fragnob, - kiov->kiov_offset + offset); + sg_set_page(sg, kiov->bv_page, fragnob, + kiov->bv_offset + offset); sg = sg_next(sg); if (!sg) { CERROR("lacking enough sg entries to map tx\n"); diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c index d53da55..f8573ed 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c @@ -164,13 +164,13 @@ ksocknal_send_kiov(struct ksock_conn *conn, struct ksock_tx *tx) do { LASSERT(tx->tx_nkiov > 0); - if (nob < (int)kiov->kiov_len) { - kiov->kiov_offset += nob; - kiov->kiov_len -= nob; + if (nob < (int)kiov->bv_len) { + kiov->bv_offset += nob; + kiov->bv_len -= nob; return rc; } - nob -= (int)kiov->kiov_len; + nob -= (int)kiov->bv_len; tx->tx_kiov = ++kiov; tx->tx_nkiov--; } while (nob); @@ -326,13 +326,13 @@ ksocknal_recv_kiov(struct ksock_conn *conn) do { LASSERT(conn->ksnc_rx_nkiov > 0); - if (nob < (int)kiov->kiov_len) { - kiov->kiov_offset += nob; - kiov->kiov_len -= nob; + if (nob < (int)kiov->bv_len) { + kiov->bv_offset += nob; + kiov->bv_len -= nob; return -EAGAIN; } - nob -= kiov->kiov_len; + nob -= kiov->bv_len; conn->ksnc_rx_kiov = ++kiov; conn->ksnc_rx_nkiov--; } while (nob); diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c index 8479b53..fe7b9f9 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c @@ -131,13 +131,13 @@ ksocknal_lib_send_kiov(struct ksock_conn *conn, struct ksock_tx *tx) if (tx->tx_msg.ksm_zc_cookies[0]) { /* Zero copy is enabled */ struct sock *sk = sock->sk; - struct page *page = kiov->kiov_page; - int offset = kiov->kiov_offset; - int fragsize = kiov->kiov_len; + struct page *page = kiov->bv_page; + int offset = kiov->bv_offset; + int fragsize = kiov->bv_len; int msgflg = MSG_DONTWAIT; CDEBUG(D_NET, "page %p + offset %x for %d\n", - page, offset, kiov->kiov_len); + page, offset, kiov->bv_len); if (!list_empty(&conn->ksnc_tx_queue) || fragsize < tx->tx_resid) @@ -165,9 +165,9 @@ ksocknal_lib_send_kiov(struct ksock_conn *conn, struct ksock_tx *tx) int i; for (nob = i = 0; i < niov; i++) { - scratchiov[i].iov_base = kmap(kiov[i].kiov_page) + - kiov[i].kiov_offset; - nob += scratchiov[i].iov_len = kiov[i].kiov_len; + scratchiov[i].iov_base = kmap(kiov[i].bv_page) + + kiov[i].bv_offset; + nob += scratchiov[i].iov_len = kiov[i].bv_len; } if (!list_empty(&conn->ksnc_tx_queue) || @@ -177,7 +177,7 @@ ksocknal_lib_send_kiov(struct ksock_conn *conn, struct ksock_tx *tx) rc = kernel_sendmsg(sock, &msg, (struct kvec *)scratchiov, niov, nob); for (i = 0; i < niov; i++) - kunmap(kiov[i].kiov_page); + kunmap(kiov[i].bv_page); } return rc; } @@ -262,7 +262,6 @@ ksocknal_lib_recv_iov(struct ksock_conn *conn) int ksocknal_lib_recv_kiov(struct ksock_conn *conn) { - struct bio_vec *bv = conn->ksnc_scheduler->kss_scratch_bvec; unsigned int niov = conn->ksnc_rx_nkiov; lnet_kiov_t *kiov = conn->ksnc_rx_kiov; struct msghdr msg = { @@ -274,33 +273,28 @@ ksocknal_lib_recv_kiov(struct ksock_conn *conn) void *base; int sum; int fragnob; - int n; - for (nob = i = 0; i < niov; i++) { - nob += bv[i].bv_len = kiov[i].kiov_len; - bv[i].bv_page = kiov[i].kiov_page; - bv[i].bv_offset = kiov[i].kiov_offset; - } - n = niov; + for (nob = i = 0; i < niov; i++) + nob += kiov[i].bv_len; LASSERT(nob <= conn->ksnc_rx_nob_wanted); - iov_iter_bvec(&msg.msg_iter, READ | ITER_BVEC, bv, n, nob); + iov_iter_bvec(&msg.msg_iter, READ | ITER_BVEC, kiov, niov, nob); rc = sock_recvmsg(conn->ksnc_sock, &msg, MSG_DONTWAIT); if (conn->ksnc_msg.ksm_csum) { for (i = 0, sum = rc; sum > 0; i++, sum -= fragnob) { LASSERT(i < niov); - base = kmap(kiov[i].kiov_page) + kiov[i].kiov_offset; - fragnob = kiov[i].kiov_len; + base = kmap(kiov[i].bv_page) + kiov[i].bv_offset; + fragnob = kiov[i].bv_len; if (fragnob > sum) fragnob = sum; conn->ksnc_rx_csum = ksocknal_csum(conn->ksnc_rx_csum, base, fragnob); - kunmap(kiov[i].kiov_page); + kunmap(kiov[i].bv_page); } } return rc; @@ -324,12 +318,12 @@ ksocknal_lib_csum_tx(struct ksock_tx *tx) if (tx->tx_kiov) { for (i = 0; i < tx->tx_nkiov; i++) { - base = kmap(tx->tx_kiov[i].kiov_page) + - tx->tx_kiov[i].kiov_offset; + base = kmap(tx->tx_kiov[i].bv_page) + + tx->tx_kiov[i].bv_offset; - csum = ksocknal_csum(csum, base, tx->tx_kiov[i].kiov_len); + csum = ksocknal_csum(csum, base, tx->tx_kiov[i].bv_len); - kunmap(tx->tx_kiov[i].kiov_page); + kunmap(tx->tx_kiov[i].bv_page); } } else { for (i = 1; i < tx->tx_niov; i++) diff --git a/drivers/staging/lustre/lnet/lnet/lib-md.c b/drivers/staging/lustre/lnet/lnet/lib-md.c index 1834bf7..e0b2f16 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-md.c +++ b/drivers/staging/lustre/lnet/lnet/lib-md.c @@ -134,11 +134,11 @@ lnet_md_build(lnet_libmd_t *lmd, lnet_md_t *umd, int unlink) for (i = 0; i < (int)niov; i++) { /* We take the page pointer on trust */ - if (lmd->md_iov.kiov[i].kiov_offset + - lmd->md_iov.kiov[i].kiov_len > PAGE_SIZE) + if (lmd->md_iov.kiov[i].bv_offset + + lmd->md_iov.kiov[i].bv_len > PAGE_SIZE) return -EINVAL; /* invalid length */ - total_length += lmd->md_iov.kiov[i].kiov_len; + total_length += lmd->md_iov.kiov[i].bv_len; } lmd->md_length = total_length; diff --git a/drivers/staging/lustre/lnet/lnet/lib-move.c b/drivers/staging/lustre/lnet/lnet/lib-move.c index e6d3b80..6a3f2e1 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-move.c +++ b/drivers/staging/lustre/lnet/lnet/lib-move.c @@ -280,7 +280,7 @@ lnet_kiov_nob(unsigned int niov, lnet_kiov_t *kiov) LASSERT(!niov || kiov); while (niov-- > 0) - nob += (kiov++)->kiov_len; + nob += (kiov++)->bv_len; return nob; } @@ -302,16 +302,16 @@ lnet_copy_kiov2kiov(unsigned int ndiov, lnet_kiov_t *diov, unsigned int doffset, LASSERT(!in_interrupt()); LASSERT(ndiov > 0); - while (doffset >= diov->kiov_len) { - doffset -= diov->kiov_len; + while (doffset >= diov->bv_len) { + doffset -= diov->bv_len; diov++; ndiov--; LASSERT(ndiov > 0); } LASSERT(nsiov > 0); - while (soffset >= siov->kiov_len) { - soffset -= siov->kiov_len; + while (soffset >= siov->bv_len) { + soffset -= siov->bv_len; siov++; nsiov--; LASSERT(nsiov > 0); @@ -320,16 +320,16 @@ lnet_copy_kiov2kiov(unsigned int ndiov, lnet_kiov_t *diov, unsigned int doffset, do { LASSERT(ndiov > 0); LASSERT(nsiov > 0); - this_nob = min(diov->kiov_len - doffset, - siov->kiov_len - soffset); + this_nob = min(diov->bv_len - doffset, + siov->bv_len - soffset); this_nob = min(this_nob, nob); if (!daddr) - daddr = ((char *)kmap(diov->kiov_page)) + - diov->kiov_offset + doffset; + daddr = ((char *)kmap(diov->bv_page)) + + diov->bv_offset + doffset; if (!saddr) - saddr = ((char *)kmap(siov->kiov_page)) + - siov->kiov_offset + soffset; + saddr = ((char *)kmap(siov->bv_page)) + + siov->bv_offset + soffset; /* * Vanishing risk of kmap deadlock when mapping 2 pages. @@ -339,22 +339,22 @@ lnet_copy_kiov2kiov(unsigned int ndiov, lnet_kiov_t *diov, unsigned int doffset, memcpy(daddr, saddr, this_nob); nob -= this_nob; - if (diov->kiov_len > doffset + this_nob) { + if (diov->bv_len > doffset + this_nob) { daddr += this_nob; doffset += this_nob; } else { - kunmap(diov->kiov_page); + kunmap(diov->bv_page); daddr = NULL; diov++; ndiov--; doffset = 0; } - if (siov->kiov_len > soffset + this_nob) { + if (siov->bv_len > soffset + this_nob) { saddr += this_nob; soffset += this_nob; } else { - kunmap(siov->kiov_page); + kunmap(siov->bv_page); saddr = NULL; siov++; nsiov--; @@ -363,9 +363,9 @@ lnet_copy_kiov2kiov(unsigned int ndiov, lnet_kiov_t *diov, unsigned int doffset, } while (nob > 0); if (daddr) - kunmap(diov->kiov_page); + kunmap(diov->bv_page); if (saddr) - kunmap(siov->kiov_page); + kunmap(siov->bv_page); } EXPORT_SYMBOL(lnet_copy_kiov2kiov); @@ -392,8 +392,8 @@ lnet_copy_kiov2iov(unsigned int niov, struct kvec *iov, unsigned int iovoffset, } LASSERT(nkiov > 0); - while (kiovoffset >= kiov->kiov_len) { - kiovoffset -= kiov->kiov_len; + while (kiovoffset >= kiov->bv_len) { + kiovoffset -= kiov->bv_len; kiov++; nkiov--; LASSERT(nkiov > 0); @@ -403,12 +403,12 @@ lnet_copy_kiov2iov(unsigned int niov, struct kvec *iov, unsigned int iovoffset, LASSERT(niov > 0); LASSERT(nkiov > 0); this_nob = min(iov->iov_len - iovoffset, - (__kernel_size_t)kiov->kiov_len - kiovoffset); + (__kernel_size_t)kiov->bv_len - kiovoffset); this_nob = min(this_nob, nob); if (!addr) - addr = ((char *)kmap(kiov->kiov_page)) + - kiov->kiov_offset + kiovoffset; + addr = ((char *)kmap(kiov->bv_page)) + + kiov->bv_offset + kiovoffset; memcpy((char *)iov->iov_base + iovoffset, addr, this_nob); nob -= this_nob; @@ -421,11 +421,11 @@ lnet_copy_kiov2iov(unsigned int niov, struct kvec *iov, unsigned int iovoffset, iovoffset = 0; } - if (kiov->kiov_len > kiovoffset + this_nob) { + if (kiov->bv_len > kiovoffset + this_nob) { addr += this_nob; kiovoffset += this_nob; } else { - kunmap(kiov->kiov_page); + kunmap(kiov->bv_page); addr = NULL; kiov++; nkiov--; @@ -435,7 +435,7 @@ lnet_copy_kiov2iov(unsigned int niov, struct kvec *iov, unsigned int iovoffset, } while (nob > 0); if (addr) - kunmap(kiov->kiov_page); + kunmap(kiov->bv_page); } EXPORT_SYMBOL(lnet_copy_kiov2iov); @@ -455,8 +455,8 @@ lnet_copy_iov2kiov(unsigned int nkiov, lnet_kiov_t *kiov, LASSERT(!in_interrupt()); LASSERT(nkiov > 0); - while (kiovoffset >= kiov->kiov_len) { - kiovoffset -= kiov->kiov_len; + while (kiovoffset >= kiov->bv_len) { + kiovoffset -= kiov->bv_len; kiov++; nkiov--; LASSERT(nkiov > 0); @@ -473,22 +473,22 @@ lnet_copy_iov2kiov(unsigned int nkiov, lnet_kiov_t *kiov, do { LASSERT(nkiov > 0); LASSERT(niov > 0); - this_nob = min((__kernel_size_t)kiov->kiov_len - kiovoffset, + this_nob = min((__kernel_size_t)kiov->bv_len - kiovoffset, iov->iov_len - iovoffset); this_nob = min(this_nob, nob); if (!addr) - addr = ((char *)kmap(kiov->kiov_page)) + - kiov->kiov_offset + kiovoffset; + addr = ((char *)kmap(kiov->bv_page)) + + kiov->bv_offset + kiovoffset; memcpy(addr, (char *)iov->iov_base + iovoffset, this_nob); nob -= this_nob; - if (kiov->kiov_len > kiovoffset + this_nob) { + if (kiov->bv_len > kiovoffset + this_nob) { addr += this_nob; kiovoffset += this_nob; } else { - kunmap(kiov->kiov_page); + kunmap(kiov->bv_page); addr = NULL; kiov++; nkiov--; @@ -505,7 +505,7 @@ lnet_copy_iov2kiov(unsigned int nkiov, lnet_kiov_t *kiov, } while (nob > 0); if (addr) - kunmap(kiov->kiov_page); + kunmap(kiov->bv_page); } EXPORT_SYMBOL(lnet_copy_iov2kiov); @@ -526,8 +526,8 @@ lnet_extract_kiov(int dst_niov, lnet_kiov_t *dst, return 0; /* no frags */ LASSERT(src_niov > 0); - while (offset >= src->kiov_len) { /* skip initial frags */ - offset -= src->kiov_len; + while (offset >= src->bv_len) { /* skip initial frags */ + offset -= src->bv_len; src_niov--; src++; LASSERT(src_niov > 0); @@ -538,19 +538,19 @@ lnet_extract_kiov(int dst_niov, lnet_kiov_t *dst, LASSERT(src_niov > 0); LASSERT((int)niov <= dst_niov); - frag_len = src->kiov_len - offset; - dst->kiov_page = src->kiov_page; - dst->kiov_offset = src->kiov_offset + offset; + frag_len = src->bv_len - offset; + dst->bv_page = src->bv_page; + dst->bv_offset = src->bv_offset + offset; if (len <= frag_len) { - dst->kiov_len = len; - LASSERT(dst->kiov_offset + dst->kiov_len + dst->bv_len = len; + LASSERT(dst->bv_offset + dst->bv_len <= PAGE_SIZE); return niov; } - dst->kiov_len = frag_len; - LASSERT(dst->kiov_offset + dst->kiov_len <= PAGE_SIZE); + dst->bv_len = frag_len; + LASSERT(dst->bv_offset + dst->bv_len <= PAGE_SIZE); len -= frag_len; dst++; diff --git a/drivers/staging/lustre/lnet/lnet/router.c b/drivers/staging/lustre/lnet/lnet/router.c index 0635432..69819c9 100644 --- a/drivers/staging/lustre/lnet/lnet/router.c +++ b/drivers/staging/lustre/lnet/lnet/router.c @@ -1307,7 +1307,7 @@ lnet_destroy_rtrbuf(lnet_rtrbuf_t *rb, int npages) int sz = offsetof(lnet_rtrbuf_t, rb_kiov[npages]); while (--npages >= 0) - __free_page(rb->rb_kiov[npages].kiov_page); + __free_page(rb->rb_kiov[npages].bv_page); LIBCFS_FREE(rb, sz); } @@ -1333,15 +1333,15 @@ lnet_new_rtrbuf(lnet_rtrbufpool_t *rbp, int cpt) GFP_KERNEL | __GFP_ZERO, 0); if (!page) { while (--i >= 0) - __free_page(rb->rb_kiov[i].kiov_page); + __free_page(rb->rb_kiov[i].bv_page); LIBCFS_FREE(rb, sz); return NULL; } - rb->rb_kiov[i].kiov_len = PAGE_SIZE; - rb->rb_kiov[i].kiov_offset = 0; - rb->rb_kiov[i].kiov_page = page; + rb->rb_kiov[i].bv_len = PAGE_SIZE; + rb->rb_kiov[i].bv_offset = 0; + rb->rb_kiov[i].bv_page = page; } return rb; diff --git a/drivers/staging/lustre/lnet/selftest/brw_test.c b/drivers/staging/lustre/lnet/selftest/brw_test.c index 13d0454..b20c5d3 100644 --- a/drivers/staging/lustre/lnet/selftest/brw_test.c +++ b/drivers/staging/lustre/lnet/selftest/brw_test.c @@ -226,7 +226,7 @@ brw_fill_bulk(struct srpc_bulk *bk, int pattern, __u64 magic) struct page *pg; for (i = 0; i < bk->bk_niov; i++) { - pg = bk->bk_iovs[i].kiov_page; + pg = bk->bk_iovs[i].bv_page; brw_fill_page(pg, pattern, magic); } } @@ -238,7 +238,7 @@ brw_check_bulk(struct srpc_bulk *bk, int pattern, __u64 magic) struct page *pg; for (i = 0; i < bk->bk_niov; i++) { - pg = bk->bk_iovs[i].kiov_page; + pg = bk->bk_iovs[i].bv_page; if (brw_check_page(pg, pattern, magic)) { CERROR("Bulk page %p (%d/%d) is corrupted!\n", pg, i, bk->bk_niov); diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c index 1be3cad..55afb53 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.c +++ b/drivers/staging/lustre/lnet/selftest/conrpc.c @@ -152,10 +152,10 @@ lstcon_rpc_put(struct lstcon_rpc *crpc) LASSERT(list_empty(&crpc->crp_link)); for (i = 0; i < bulk->bk_niov; i++) { - if (!bulk->bk_iovs[i].kiov_page) + if (!bulk->bk_iovs[i].bv_page) continue; - __free_page(bulk->bk_iovs[i].kiov_page); + __free_page(bulk->bk_iovs[i].bv_page); } srpc_client_rpc_decref(crpc->crp_rpc); @@ -705,7 +705,7 @@ lstcon_next_id(int idx, int nkiov, lnet_kiov_t *kiov) LASSERT(i < nkiov); - pid = (lnet_process_id_packed_t *)page_address(kiov[i].kiov_page); + pid = (lnet_process_id_packed_t *)page_address(kiov[i].bv_page); return &pid[idx % SFW_ID_PER_PAGE]; } @@ -849,12 +849,11 @@ lstcon_testrpc_prep(struct lstcon_node *nd, int transop, unsigned feats, min_t(int, nob, PAGE_SIZE); nob -= len; - bulk->bk_iovs[i].kiov_offset = 0; - bulk->bk_iovs[i].kiov_len = len; - bulk->bk_iovs[i].kiov_page = - alloc_page(GFP_KERNEL); + bulk->bk_iovs[i].bv_offset = 0; + bulk->bk_iovs[i].bv_len = len; + bulk->bk_iovs[i].bv_page = alloc_page(GFP_KERNEL); - if (!bulk->bk_iovs[i].kiov_page) { + if (!bulk->bk_iovs[i].bv_page) { lstcon_rpc_put(*crpc); return -ENOMEM; } diff --git a/drivers/staging/lustre/lnet/selftest/framework.c b/drivers/staging/lustre/lnet/selftest/framework.c index c2f121f..abbd628 100644 --- a/drivers/staging/lustre/lnet/selftest/framework.c +++ b/drivers/staging/lustre/lnet/selftest/framework.c @@ -784,8 +784,8 @@ sfw_add_test_instance(struct sfw_batch *tsb, struct srpc_server_rpc *rpc) lnet_process_id_packed_t id; int j; - dests = page_address(bk->bk_iovs[i / SFW_ID_PER_PAGE].kiov_page); - LASSERT(dests); /* my pages are within KVM always */ + dests = page_address(bk->bk_iovs[i / SFW_ID_PER_PAGE].bv_page); + LASSERT(dests); /* my pages are within KVM always */ id = dests[i % SFW_ID_PER_PAGE]; if (msg->msg_magic != SRPC_MSG_MAGIC) sfw_unpack_id(id); diff --git a/drivers/staging/lustre/lnet/selftest/rpc.c b/drivers/staging/lustre/lnet/selftest/rpc.c index 3b26d6e..f5619d8 100644 --- a/drivers/staging/lustre/lnet/selftest/rpc.c +++ b/drivers/staging/lustre/lnet/selftest/rpc.c @@ -91,9 +91,9 @@ srpc_add_bulk_page(struct srpc_bulk *bk, struct page *pg, int i, int nob) LASSERT(nob > 0); LASSERT(i >= 0 && i < bk->bk_niov); - bk->bk_iovs[i].kiov_offset = 0; - bk->bk_iovs[i].kiov_page = pg; - bk->bk_iovs[i].kiov_len = nob; + bk->bk_iovs[i].bv_offset = 0; + bk->bk_iovs[i].bv_page = pg; + bk->bk_iovs[i].bv_len = nob; return nob; } @@ -106,7 +106,7 @@ srpc_free_bulk(struct srpc_bulk *bk) LASSERT(bk); for (i = 0; i < bk->bk_niov; i++) { - pg = bk->bk_iovs[i].kiov_page; + pg = bk->bk_iovs[i].bv_page; if (!pg) break; diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index d011135..53b5d73 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -1864,8 +1864,7 @@ void osc_dec_unstable_pages(struct ptlrpc_request *req) LASSERT(page_count >= 0); for (i = 0; i < page_count; i++) - dec_node_page_state(desc->bd_iov[i].kiov_page, - NR_UNSTABLE_NFS); + dec_node_page_state(desc->bd_iov[i].bv_page, NR_UNSTABLE_NFS); atomic_sub(page_count, &cli->cl_cache->ccc_unstable_nr); LASSERT(atomic_read(&cli->cl_cache->ccc_unstable_nr) >= 0); @@ -1899,8 +1898,7 @@ void osc_inc_unstable_pages(struct ptlrpc_request *req) LASSERT(page_count >= 0); for (i = 0; i < page_count; i++) - inc_node_page_state(desc->bd_iov[i].kiov_page, - NR_UNSTABLE_NFS); + inc_node_page_state(desc->bd_iov[i].bv_page, NR_UNSTABLE_NFS); LASSERT(atomic_read(&cli->cl_cache->ccc_unstable_nr) >= 0); atomic_add(page_count, &cli->cl_cache->ccc_unstable_nr); diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index d4463d7..549c62c 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -202,7 +202,7 @@ void __ptlrpc_free_bulk(struct ptlrpc_bulk_desc *desc, int unpin) if (unpin) { for (i = 0; i < desc->bd_iov_count; i++) - put_page(desc->bd_iov[i].kiov_page); + put_page(desc->bd_iov[i].bv_page); } kfree(desc); diff --git a/drivers/staging/lustre/lustre/ptlrpc/pers.c b/drivers/staging/lustre/lustre/ptlrpc/pers.c index 6c820e9..5b9fb11 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pers.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pers.c @@ -64,9 +64,9 @@ void ptlrpc_add_bulk_page(struct ptlrpc_bulk_desc *desc, struct page *page, { lnet_kiov_t *kiov = &desc->bd_iov[desc->bd_iov_count]; - kiov->kiov_page = page; - kiov->kiov_offset = pageoffset; - kiov->kiov_len = len; + kiov->bv_page = page; + kiov->bv_offset = pageoffset; + kiov->bv_len = len; desc->bd_iov_count++; } diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c index 5f4d797..bb00185 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c @@ -326,12 +326,12 @@ void sptlrpc_enc_pool_put_pages(struct ptlrpc_bulk_desc *desc) LASSERT(page_pools.epp_pools[p_idx]); for (i = 0; i < desc->bd_iov_count; i++) { - LASSERT(desc->bd_enc_iov[i].kiov_page); + LASSERT(desc->bd_enc_iov[i].bv_page); LASSERT(g_idx != 0 || page_pools.epp_pools[p_idx]); LASSERT(!page_pools.epp_pools[p_idx][g_idx]); page_pools.epp_pools[p_idx][g_idx] = - desc->bd_enc_iov[i].kiov_page; + desc->bd_enc_iov[i].bv_page; if (++g_idx == PAGES_PER_POOL) { p_idx++; @@ -522,9 +522,9 @@ int sptlrpc_get_bulk_checksum(struct ptlrpc_bulk_desc *desc, __u8 alg, hashsize = cfs_crypto_hash_digestsize(cfs_hash_alg_id[alg]); for (i = 0; i < desc->bd_iov_count; i++) { - cfs_crypto_hash_update_page(hdesc, desc->bd_iov[i].kiov_page, - desc->bd_iov[i].kiov_offset & ~PAGE_MASK, - desc->bd_iov[i].kiov_len); + cfs_crypto_hash_update_page(hdesc, desc->bd_iov[i].bv_page, + desc->bd_iov[i].bv_offset & ~PAGE_MASK, + desc->bd_iov[i].bv_len); } if (hashsize > buflen) { diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c b/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c index 5c4590b..8322550 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c @@ -154,13 +154,13 @@ static void corrupt_bulk_data(struct ptlrpc_bulk_desc *desc) unsigned int off, i; for (i = 0; i < desc->bd_iov_count; i++) { - if (desc->bd_iov[i].kiov_len == 0) + if (desc->bd_iov[i].bv_len == 0) continue; - ptr = kmap(desc->bd_iov[i].kiov_page); - off = desc->bd_iov[i].kiov_offset & ~PAGE_MASK; + ptr = kmap(desc->bd_iov[i].bv_page); + off = desc->bd_iov[i].bv_offset & ~PAGE_MASK; ptr[off] ^= 0x1; - kunmap(desc->bd_iov[i].kiov_page); + kunmap(desc->bd_iov[i].bv_page); return; } } @@ -349,11 +349,11 @@ int plain_cli_unwrap_bulk(struct ptlrpc_cli_ctx *ctx, /* fix the actual data size */ for (i = 0, nob = 0; i < desc->bd_iov_count; i++) { - if (desc->bd_iov[i].kiov_len + nob > desc->bd_nob_transferred) { - desc->bd_iov[i].kiov_len = + if (desc->bd_iov[i].bv_len + nob > desc->bd_nob_transferred) { + desc->bd_iov[i].bv_len = desc->bd_nob_transferred - nob; } - nob += desc->bd_iov[i].kiov_len; + nob += desc->bd_iov[i].bv_len; } rc = plain_verify_bulk_csum(desc, req->rq_flvr.u_bulk.hash.hash_alg, -- cgit v0.10.2 From cba4985ed5bdb76636d5e2dd1867b2770741a331 Mon Sep 17 00:00:00 2001 From: Daniel Wagner <daniel.wagner@bmw-carit.de> Date: Thu, 4 Aug 2016 15:07:09 +0200 Subject: iio: adc: Use complete() instead of complete_all() There is only one waiter for the completion, therefore there is no need to use complete_all(). Let's make that clear by using complete() instead of complete_all(). The usage pattern of the completion is: waiter context waker context nau7802_read_irq() reinit_completion() nau7802_read_conversion() wait_for_completion_interruptible_timeout() nau7802_eoc_trigger() complete() Signed-off-by: Daniel Wagner <daniel.wagner@bmw-carit.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/adc/nau7802.c b/drivers/iio/adc/nau7802.c index db9b829..08f4466 100644 --- a/drivers/iio/adc/nau7802.c +++ b/drivers/iio/adc/nau7802.c @@ -197,7 +197,7 @@ static irqreturn_t nau7802_eoc_trigger(int irq, void *private) if (st->conversion_count < NAU7802_MIN_CONVERSIONS) st->conversion_count++; if (st->conversion_count >= NAU7802_MIN_CONVERSIONS) - complete_all(&st->value_ok); + complete(&st->value_ok); return IRQ_HANDLED; } -- cgit v0.10.2 From 8c11e16177b16c0aa0c3b08987f316fd89aa1ead Mon Sep 17 00:00:00 2001 From: Daniel Wagner <daniel.wagner@bmw-carit.de> Date: Thu, 4 Aug 2016 15:07:10 +0200 Subject: iio: sx9500: Use complete() instead of complete_all() There is only one waiter for the completion, therefore there is no need to use complete_all(). Let's make that clear by using complete() instead of complete_all(). The usage pattern of the completion is: waiter context waker context sx9500_read_proximity() sx9500_inc_chan_users() sx9500_inc_data_rdy_users() wait_for_completion_interruptible() s9500_irq_thread_handler() complete() reinit_completion() Signed-off-by: Daniel Wagner <daniel.wagner@bmw-carit.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c index 1d74b3a..6f84f53 100644 --- a/drivers/iio/proximity/sx9500.c +++ b/drivers/iio/proximity/sx9500.c @@ -516,7 +516,7 @@ static irqreturn_t sx9500_irq_thread_handler(int irq, void *private) sx9500_push_events(indio_dev); if (val & SX9500_CONVDONE_IRQ) - complete_all(&data->completion); + complete(&data->completion); out: mutex_unlock(&data->mutex); -- cgit v0.10.2 From 598b1529d6ceddeadd528187996f08cc3c39cc55 Mon Sep 17 00:00:00 2001 From: Joshua Houghton <josh@awful.name> Date: Sat, 18 Jun 2016 19:42:07 +0000 Subject: staging: dgnc: add __exit macro to dgnc_driver.c Add the __exit macro to the dgnc_cleanup_module(void) function in dgnc_driver.c Signed-off-by: Joshua Houghton <josh@awful.name> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c index af2e835..2c3fb2a 100644 --- a/drivers/staging/dgnc/dgnc_driver.c +++ b/drivers/staging/dgnc/dgnc_driver.c @@ -158,7 +158,7 @@ static void cleanup(bool sysfiles) * * Module unload. This is where it all ends. */ -static void dgnc_cleanup_module(void) +static void __exit dgnc_cleanup_module(void) { cleanup(true); pci_unregister_driver(&dgnc_driver); -- cgit v0.10.2 From 10334418d62d968e2901eb116ea449828b782c96 Mon Sep 17 00:00:00 2001 From: Daeseok Youn <daeseok.youn@gmail.com> Date: Wed, 6 Jul 2016 15:11:13 +0900 Subject: staging: dgnc: remove redundant NULL checks in The dgnc_block_til_ready() is only used in dgnc_tty_open(). The unit data(struct un_t) was stored into tty->driver_data in dgnc_tty_open(). And also tty and un were tested about NULL so these variables doesn't need to check for NULL in dgnc_block_til_ready(). Signed-off-by: Daeseok Youn <daeseok.youn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index 4eeecc9..6758859 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -1172,17 +1172,12 @@ static int dgnc_block_til_ready(struct tty_struct *tty, struct channel_t *ch) { int retval = 0; - struct un_t *un = NULL; + struct un_t *un = tty->driver_data; unsigned long flags; uint old_flags = 0; int sleep_on_un_flags = 0; - if (!tty || tty->magic != TTY_MAGIC || !file || !ch || - ch->magic != DGNC_CHANNEL_MAGIC) - return -ENXIO; - - un = tty->driver_data; - if (!un || un->magic != DGNC_UNIT_MAGIC) + if (!file) return -ENXIO; spin_lock_irqsave(&ch->ch_lock, flags); -- cgit v0.10.2 From 290e3abaccbac6afeb3376b13627b3fc6974554b Mon Sep 17 00:00:00 2001 From: Daeseok Youn <daeseok.youn@gmail.com> Date: Wed, 6 Jul 2016 15:11:52 +0900 Subject: staging: dgnc: remove useless error value assignment The "result" variable in dgnc_get_mstat() was initialized with "-EIO". But if the "ch" is not null, "result" will be set to zero and if the "ch" is null, dgnc_get_mstat() will return "-ENXIO" as an error. So "-EIO" error value was useless in dgnc_get_mstat(). Signed-off-by: Daeseok Youn <daeseok.youn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index 6758859..17ba966 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -1979,7 +1979,7 @@ static void dgnc_tty_send_xchar(struct tty_struct *tty, char c) static inline int dgnc_get_mstat(struct channel_t *ch) { unsigned char mstat; - int result = -EIO; + int result = 0; unsigned long flags; if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) @@ -1991,8 +1991,6 @@ static inline int dgnc_get_mstat(struct channel_t *ch) spin_unlock_irqrestore(&ch->ch_lock, flags); - result = 0; - if (mstat & UART_MCR_DTR) result |= TIOCM_DTR; if (mstat & UART_MCR_RTS) -- cgit v0.10.2 From 3ca4b20a765f4429e5c2795fcae1a3ce312f075b Mon Sep 17 00:00:00 2001 From: Daeseok Youn <daeseok.youn@gmail.com> Date: Wed, 6 Jul 2016 15:12:29 +0900 Subject: staging: dgnc: remove redundant local variable for The local variable "bd" was not used in dgnc_carrier() function. Signed-off-by: Daeseok Youn <daeseok.youn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index 17ba966..1387041 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -640,19 +640,12 @@ exit_unlock: ************************************************************************/ void dgnc_carrier(struct channel_t *ch) { - struct dgnc_board *bd; - int virt_carrier = 0; int phys_carrier = 0; if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) return; - bd = ch->ch_bd; - - if (!bd || bd->magic != DGNC_BOARD_MAGIC) - return; - if (ch->ch_mistat & UART_MSR_DCD) phys_carrier = 1; -- cgit v0.10.2 From 18419f77a22ae8d3b9330c83f6d09e0e66d2d755 Mon Sep 17 00:00:00 2001 From: Daeseok Youn <daeseok.youn@gmail.com> Date: Wed, 6 Jul 2016 15:13:14 +0900 Subject: staging: dgnc: remove redundant variable null check The unit struct(un_t) was not used in dgnc_tty_hangup(). Signed-off-by: Daeseok Youn <daeseok.youn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index 1387041..b33b07c 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -1289,15 +1289,9 @@ static int dgnc_block_til_ready(struct tty_struct *tty, */ static void dgnc_tty_hangup(struct tty_struct *tty) { - struct un_t *un; - if (!tty || tty->magic != TTY_MAGIC) return; - un = tty->driver_data; - if (!un || un->magic != DGNC_UNIT_MAGIC) - return; - /* flush the transmit queues */ dgnc_tty_flush_buffer(tty); } -- cgit v0.10.2 From c23b48e0ed4764af410cacc09d49fe300743e55b Mon Sep 17 00:00:00 2001 From: Daeseok Youn <daeseok.youn@gmail.com> Date: Wed, 6 Jul 2016 15:13:55 +0900 Subject: staging: dgnc: removes redundant null check and change The dgnc_set_modem_info() used only channel_t variable. Any other variables were used only for checking NULL. So fist parameter changed from "tty_struct" to "channel_t" and useless NULL checks and variables are removed. Signed-off-by: Daeseok Youn <daeseok.youn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index b33b07c..e4c6c3f 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -100,7 +100,7 @@ static void dgnc_tty_unthrottle(struct tty_struct *tty); static void dgnc_tty_flush_chars(struct tty_struct *tty); static void dgnc_tty_flush_buffer(struct tty_struct *tty); static void dgnc_tty_hangup(struct tty_struct *tty); -static int dgnc_set_modem_info(struct tty_struct *tty, unsigned int command, +static int dgnc_set_modem_info(struct channel_t *ch, unsigned int command, unsigned int __user *value); static int dgnc_get_modem_info(struct channel_t *ch, unsigned int __user *value); @@ -2008,32 +2008,14 @@ static int dgnc_get_modem_info(struct channel_t *ch, * * Set modem signals, called by ld. */ -static int dgnc_set_modem_info(struct tty_struct *tty, +static int dgnc_set_modem_info(struct channel_t *ch, unsigned int command, unsigned int __user *value) { - struct dgnc_board *bd; - struct channel_t *ch; - struct un_t *un; int ret = -ENXIO; unsigned int arg = 0; unsigned long flags; - if (!tty || tty->magic != TTY_MAGIC) - return ret; - - un = tty->driver_data; - if (!un || un->magic != DGNC_UNIT_MAGIC) - return ret; - - ch = un->un_ch; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) - return ret; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGNC_BOARD_MAGIC) - return ret; - ret = get_user(arg, value); if (ret) return ret; @@ -2600,7 +2582,7 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, case TIOCMBIC: case TIOCMSET: spin_unlock_irqrestore(&ch->ch_lock, flags); - return dgnc_set_modem_info(tty, cmd, uarg); + return dgnc_set_modem_info(ch, cmd, uarg); /* * Here are any additional ioctl's that we want to implement -- cgit v0.10.2 From a2237a2d60db69c4df74a5fa1591c02247ba0f49 Mon Sep 17 00:00:00 2001 From: Daeseok Youn <daeseok.youn@gmail.com> Date: Wed, 6 Jul 2016 15:14:37 +0900 Subject: staging: dgnc: re-arrange functions for removing Re-arrange the functions for removing forward declarations in dgnc_cls.c file. Signed-off-by: Daeseok Youn <daeseok.youn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_cls.c b/drivers/staging/dgnc/dgnc_cls.c index 46c050c..2347bdc 100644 --- a/drivers/staging/dgnc/dgnc_cls.c +++ b/drivers/staging/dgnc/dgnc_cls.c @@ -26,56 +26,6 @@ #include "dgnc_cls.h" #include "dgnc_tty.h" -static inline void cls_parse_isr(struct dgnc_board *brd, uint port); -static inline void cls_clear_break(struct channel_t *ch, int force); -static inline void cls_set_cts_flow_control(struct channel_t *ch); -static inline void cls_set_rts_flow_control(struct channel_t *ch); -static inline void cls_set_ixon_flow_control(struct channel_t *ch); -static inline void cls_set_ixoff_flow_control(struct channel_t *ch); -static inline void cls_set_no_output_flow_control(struct channel_t *ch); -static inline void cls_set_no_input_flow_control(struct channel_t *ch); -static void cls_parse_modem(struct channel_t *ch, unsigned char signals); -static void cls_tasklet(unsigned long data); -static void cls_vpd(struct dgnc_board *brd); -static void cls_uart_init(struct channel_t *ch); -static void cls_uart_off(struct channel_t *ch); -static int cls_drain(struct tty_struct *tty, uint seconds); -static void cls_param(struct tty_struct *tty); -static void cls_assert_modem_signals(struct channel_t *ch); -static void cls_flush_uart_write(struct channel_t *ch); -static void cls_flush_uart_read(struct channel_t *ch); -static void cls_disable_receiver(struct channel_t *ch); -static void cls_enable_receiver(struct channel_t *ch); -static void cls_send_break(struct channel_t *ch, int msecs); -static void cls_send_start_character(struct channel_t *ch); -static void cls_send_stop_character(struct channel_t *ch); -static void cls_copy_data_from_uart_to_queue(struct channel_t *ch); -static void cls_copy_data_from_queue_to_uart(struct channel_t *ch); -static uint cls_get_uart_bytes_left(struct channel_t *ch); -static void cls_send_immediate_char(struct channel_t *ch, unsigned char); -static irqreturn_t cls_intr(int irq, void *voidbrd); - -struct board_ops dgnc_cls_ops = { - .tasklet = cls_tasklet, - .intr = cls_intr, - .uart_init = cls_uart_init, - .uart_off = cls_uart_off, - .drain = cls_drain, - .param = cls_param, - .vpd = cls_vpd, - .assert_modem_signals = cls_assert_modem_signals, - .flush_uart_write = cls_flush_uart_write, - .flush_uart_read = cls_flush_uart_read, - .disable_receiver = cls_disable_receiver, - .enable_receiver = cls_enable_receiver, - .send_break = cls_send_break, - .send_start_character = cls_send_start_character, - .send_stop_character = cls_send_stop_character, - .copy_data_from_queue_to_uart = cls_copy_data_from_queue_to_uart, - .get_uart_bytes_left = cls_get_uart_bytes_left, - .send_immediate_char = cls_send_immediate_char -}; - static inline void cls_set_cts_flow_control(struct channel_t *ch) { unsigned char lcrb = readb(&ch->ch_cls_uart->lcr); @@ -357,164 +307,444 @@ static inline void cls_clear_break(struct channel_t *ch, int force) spin_unlock_irqrestore(&ch->ch_lock, flags); } -/* Parse the ISR register for the specific port */ -static inline void cls_parse_isr(struct dgnc_board *brd, uint port) +static void cls_copy_data_from_uart_to_queue(struct channel_t *ch) { - struct channel_t *ch; - unsigned char isr = 0; + int qleft = 0; + unsigned char linestatus = 0; + unsigned char error_mask = 0; + ushort head; + ushort tail; unsigned long flags; - /* - * No need to verify board pointer, it was already - * verified in the interrupt routine. - */ - - if (port >= brd->nasync) + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) return; - ch = brd->channels[port]; - if (ch->magic != DGNC_CHANNEL_MAGIC) - return; + spin_lock_irqsave(&ch->ch_lock, flags); + + /* cache head and tail of queue */ + head = ch->ch_r_head; + tail = ch->ch_r_tail; + + /* Store how much space we have left in the queue */ + qleft = tail - head - 1; + if (qleft < 0) + qleft += RQUEUEMASK + 1; + + /* + * Create a mask to determine whether we should + * insert the character (if any) into our queue. + */ + if (ch->ch_c_iflag & IGNBRK) + error_mask |= UART_LSR_BI; - /* Here we try to figure out what caused the interrupt to happen */ while (1) { - isr = readb(&ch->ch_cls_uart->isr_fcr); + linestatus = readb(&ch->ch_cls_uart->lsr); - /* Bail if no pending interrupt on port */ - if (isr & UART_IIR_NO_INT) + if (!(linestatus & (UART_LSR_DR))) break; - /* Receive Interrupt pending */ - if (isr & (UART_IIR_RDI | UART_IIR_RDI_TIMEOUT)) { - /* Read data from uart -> queue */ - brd->intr_rx++; - ch->ch_intr_rx++; - cls_copy_data_from_uart_to_queue(ch); - dgnc_check_queue_flow_control(ch); + /* + * Discard character if we are ignoring the error mask. + */ + if (linestatus & error_mask) { + linestatus = 0; + readb(&ch->ch_cls_uart->txrx); + continue; } - /* Transmit Hold register empty pending */ - if (isr & UART_IIR_THRI) { - /* Transfer data (if any) from Write Queue -> UART. */ - spin_lock_irqsave(&ch->ch_lock, flags); - ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); - brd->intr_tx++; - ch->ch_intr_tx++; - spin_unlock_irqrestore(&ch->ch_lock, flags); - cls_copy_data_from_queue_to_uart(ch); + /* + * If our queue is full, we have no choice but to drop some + * data. The assumption is that HWFLOW or SWFLOW should have + * stopped things way way before we got to this point. + * + * I decided that I wanted to ditch the oldest data first, + * I hope thats okay with everyone? Yes? Good. + */ + while (qleft < 1) { + tail = (tail + 1) & RQUEUEMASK; + ch->ch_r_tail = tail; + ch->ch_err_overrun++; + qleft++; } - /* CTS/RTS change of state */ - if (isr & UART_IIR_CTSRTS) { - brd->intr_modem++; - ch->ch_intr_modem++; - /* - * Don't need to do anything, the cls_parse_modem - * below will grab the updated modem signals. - */ - } + ch->ch_equeue[head] = linestatus & (UART_LSR_BI | UART_LSR_PE + | UART_LSR_FE); + ch->ch_rqueue[head] = readb(&ch->ch_cls_uart->txrx); - /* Parse any modem signal changes */ - cls_parse_modem(ch, readb(&ch->ch_cls_uart->msr)); + qleft--; + + if (ch->ch_equeue[head] & UART_LSR_PE) + ch->ch_err_parity++; + if (ch->ch_equeue[head] & UART_LSR_BI) + ch->ch_err_break++; + if (ch->ch_equeue[head] & UART_LSR_FE) + ch->ch_err_frame++; + + /* Add to, and flip head if needed */ + head = (head + 1) & RQUEUEMASK; + ch->ch_rxcount++; } + + /* + * Write new final heads to channel structure. + */ + ch->ch_r_head = head & RQUEUEMASK; + ch->ch_e_head = head & EQUEUEMASK; + + spin_unlock_irqrestore(&ch->ch_lock, flags); } -/* - * cls_param() - * Send any/all changes to the line to the UART. - */ -static void cls_param(struct tty_struct *tty) +/* Make the UART raise any of the output signals we want up */ +static void cls_assert_modem_signals(struct channel_t *ch) { - unsigned char lcr = 0; - unsigned char uart_lcr = 0; - unsigned char ier = 0; - unsigned char uart_ier = 0; - uint baud = 9600; - int quot = 0; - struct dgnc_board *bd; - struct channel_t *ch; - struct un_t *un; + unsigned char out; - if (!tty || tty->magic != TTY_MAGIC) + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) return; - un = (struct un_t *)tty->driver_data; - if (!un || un->magic != DGNC_UNIT_MAGIC) - return; + out = ch->ch_mostat; + + if (ch->ch_flags & CH_LOOPBACK) + out |= UART_MCR_LOOP; + + writeb(out, &ch->ch_cls_uart->mcr); + + /* Give time for the UART to actually drop the signals */ + udelay(10); +} + +static void cls_copy_data_from_queue_to_uart(struct channel_t *ch) +{ + ushort head; + ushort tail; + int n; + int qlen; + uint len_written = 0; + unsigned long flags; - ch = un->un_ch; if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) return; - bd = ch->ch_bd; - if (!bd || bd->magic != DGNC_BOARD_MAGIC) - return; + spin_lock_irqsave(&ch->ch_lock, flags); - /* - * If baud rate is zero, flush queues, and set mval to drop DTR. - */ - if ((ch->ch_c_cflag & (CBAUD)) == 0) { - ch->ch_r_head = 0; - ch->ch_r_tail = 0; - ch->ch_e_head = 0; - ch->ch_e_tail = 0; - ch->ch_w_head = 0; - ch->ch_w_tail = 0; + /* No data to write to the UART */ + if (ch->ch_w_tail == ch->ch_w_head) + goto exit_unlock; - cls_flush_uart_write(ch); - cls_flush_uart_read(ch); + /* If port is "stopped", don't send any data to the UART */ + if ((ch->ch_flags & CH_FORCED_STOP) || + (ch->ch_flags & CH_BREAK_SENDING)) + goto exit_unlock; - /* The baudrate is B0 so all modem lines are to be dropped. */ - ch->ch_flags |= (CH_BAUD0); - ch->ch_mostat &= ~(UART_MCR_RTS | UART_MCR_DTR); - cls_assert_modem_signals(ch); - ch->ch_old_baud = 0; - return; - } else if (ch->ch_custom_speed) { - baud = ch->ch_custom_speed; - /* Handle transition from B0 */ - if (ch->ch_flags & CH_BAUD0) { - ch->ch_flags &= ~(CH_BAUD0); + if (!(ch->ch_flags & (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM))) + goto exit_unlock; - /* - * Bring back up RTS and DTR... - * Also handle RTS or DTR toggle if set. - */ - if (!(ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE)) - ch->ch_mostat |= (UART_MCR_RTS); - if (!(ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE)) - ch->ch_mostat |= (UART_MCR_DTR); - } + n = 32; - } else { - int iindex = 0; - int jindex = 0; + /* cache head and tail of queue */ + head = ch->ch_w_head & WQUEUEMASK; + tail = ch->ch_w_tail & WQUEUEMASK; + qlen = (head - tail) & WQUEUEMASK; - ulong bauds[4][16] = { - { /* slowbaud */ - 0, 50, 75, 110, - 134, 150, 200, 300, - 600, 1200, 1800, 2400, - 4800, 9600, 19200, 38400 }, - { /* slowbaud & CBAUDEX */ - 0, 57600, 115200, 230400, - 460800, 150, 200, 921600, - 600, 1200, 1800, 2400, - 4800, 9600, 19200, 38400 }, - { /* fastbaud */ - 0, 57600, 76800, 115200, - 131657, 153600, 230400, 460800, - 921600, 1200, 1800, 2400, - 4800, 9600, 19200, 38400 }, - { /* fastbaud & CBAUDEX */ - 0, 57600, 115200, 230400, - 460800, 150, 200, 921600, - 600, 1200, 1800, 2400, - 4800, 9600, 19200, 38400 } - }; + /* Find minimum of the FIFO space, versus queue length */ + n = min(n, qlen); + while (n > 0) { /* - * Only use the TXPrint baud rate if the terminal + * If RTS Toggle mode is on, turn on RTS now if not already set, + * and make sure we get an event when the data transfer has + * completed. + */ + if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) { + if (!(ch->ch_mostat & UART_MCR_RTS)) { + ch->ch_mostat |= (UART_MCR_RTS); + cls_assert_modem_signals(ch); + } + ch->ch_tun.un_flags |= (UN_EMPTY); + } + + /* + * If DTR Toggle mode is on, turn on DTR now if not already set, + * and make sure we get an event when the data transfer has + * completed. + */ + if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) { + if (!(ch->ch_mostat & UART_MCR_DTR)) { + ch->ch_mostat |= (UART_MCR_DTR); + cls_assert_modem_signals(ch); + } + ch->ch_tun.un_flags |= (UN_EMPTY); + } + writeb(ch->ch_wqueue[ch->ch_w_tail], &ch->ch_cls_uart->txrx); + ch->ch_w_tail++; + ch->ch_w_tail &= WQUEUEMASK; + ch->ch_txcount++; + len_written++; + n--; + } + + if (len_written > 0) + ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); + +exit_unlock: + spin_unlock_irqrestore(&ch->ch_lock, flags); +} + +static void cls_parse_modem(struct channel_t *ch, unsigned char signals) +{ + unsigned char msignals = signals; + unsigned long flags; + + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + /* + * Do altpin switching. Altpin switches DCD and DSR. + * This prolly breaks DSRPACE, so we should be more clever here. + */ + spin_lock_irqsave(&ch->ch_lock, flags); + if (ch->ch_digi.digi_flags & DIGI_ALTPIN) { + unsigned char mswap = signals; + + if (mswap & UART_MSR_DDCD) { + msignals &= ~UART_MSR_DDCD; + msignals |= UART_MSR_DDSR; + } + if (mswap & UART_MSR_DDSR) { + msignals &= ~UART_MSR_DDSR; + msignals |= UART_MSR_DDCD; + } + if (mswap & UART_MSR_DCD) { + msignals &= ~UART_MSR_DCD; + msignals |= UART_MSR_DSR; + } + if (mswap & UART_MSR_DSR) { + msignals &= ~UART_MSR_DSR; + msignals |= UART_MSR_DCD; + } + } + spin_unlock_irqrestore(&ch->ch_lock, flags); + + /* + * Scrub off lower bits. They signify delta's, which I don't + * care about + */ + signals &= 0xf0; + + spin_lock_irqsave(&ch->ch_lock, flags); + if (msignals & UART_MSR_DCD) + ch->ch_mistat |= UART_MSR_DCD; + else + ch->ch_mistat &= ~UART_MSR_DCD; + + if (msignals & UART_MSR_DSR) + ch->ch_mistat |= UART_MSR_DSR; + else + ch->ch_mistat &= ~UART_MSR_DSR; + + if (msignals & UART_MSR_RI) + ch->ch_mistat |= UART_MSR_RI; + else + ch->ch_mistat &= ~UART_MSR_RI; + + if (msignals & UART_MSR_CTS) + ch->ch_mistat |= UART_MSR_CTS; + else + ch->ch_mistat &= ~UART_MSR_CTS; + spin_unlock_irqrestore(&ch->ch_lock, flags); +} + +/* Parse the ISR register for the specific port */ +static inline void cls_parse_isr(struct dgnc_board *brd, uint port) +{ + struct channel_t *ch; + unsigned char isr = 0; + unsigned long flags; + + /* + * No need to verify board pointer, it was already + * verified in the interrupt routine. + */ + + if (port >= brd->nasync) + return; + + ch = brd->channels[port]; + if (ch->magic != DGNC_CHANNEL_MAGIC) + return; + + /* Here we try to figure out what caused the interrupt to happen */ + while (1) { + isr = readb(&ch->ch_cls_uart->isr_fcr); + + /* Bail if no pending interrupt on port */ + if (isr & UART_IIR_NO_INT) + break; + + /* Receive Interrupt pending */ + if (isr & (UART_IIR_RDI | UART_IIR_RDI_TIMEOUT)) { + /* Read data from uart -> queue */ + brd->intr_rx++; + ch->ch_intr_rx++; + cls_copy_data_from_uart_to_queue(ch); + dgnc_check_queue_flow_control(ch); + } + + /* Transmit Hold register empty pending */ + if (isr & UART_IIR_THRI) { + /* Transfer data (if any) from Write Queue -> UART. */ + spin_lock_irqsave(&ch->ch_lock, flags); + ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); + brd->intr_tx++; + ch->ch_intr_tx++; + spin_unlock_irqrestore(&ch->ch_lock, flags); + cls_copy_data_from_queue_to_uart(ch); + } + + /* CTS/RTS change of state */ + if (isr & UART_IIR_CTSRTS) { + brd->intr_modem++; + ch->ch_intr_modem++; + /* + * Don't need to do anything, the cls_parse_modem + * below will grab the updated modem signals. + */ + } + + /* Parse any modem signal changes */ + cls_parse_modem(ch, readb(&ch->ch_cls_uart->msr)); + } +} + +/* Channel lock MUST be held before calling this function! */ +static void cls_flush_uart_write(struct channel_t *ch) +{ + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_XMIT), + &ch->ch_cls_uart->isr_fcr); + usleep_range(10, 20); + + ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); +} + +/* Channel lock MUST be held before calling this function! */ +static void cls_flush_uart_read(struct channel_t *ch) +{ + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + /* + * For complete POSIX compatibility, we should be purging the + * read FIFO in the UART here. + * + * However, clearing the read FIFO (UART_FCR_CLEAR_RCVR) also + * incorrectly flushes write data as well as just basically trashing the + * FIFO. + * + * Presumably, this is a bug in this UART. + */ + + udelay(10); +} + +/* + * cls_param() + * Send any/all changes to the line to the UART. + */ +static void cls_param(struct tty_struct *tty) +{ + unsigned char lcr = 0; + unsigned char uart_lcr = 0; + unsigned char ier = 0; + unsigned char uart_ier = 0; + uint baud = 9600; + int quot = 0; + struct dgnc_board *bd; + struct channel_t *ch; + struct un_t *un; + + if (!tty || tty->magic != TTY_MAGIC) + return; + + un = (struct un_t *)tty->driver_data; + if (!un || un->magic != DGNC_UNIT_MAGIC) + return; + + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + bd = ch->ch_bd; + if (!bd || bd->magic != DGNC_BOARD_MAGIC) + return; + + /* + * If baud rate is zero, flush queues, and set mval to drop DTR. + */ + if ((ch->ch_c_cflag & (CBAUD)) == 0) { + ch->ch_r_head = 0; + ch->ch_r_tail = 0; + ch->ch_e_head = 0; + ch->ch_e_tail = 0; + ch->ch_w_head = 0; + ch->ch_w_tail = 0; + + cls_flush_uart_write(ch); + cls_flush_uart_read(ch); + + /* The baudrate is B0 so all modem lines are to be dropped. */ + ch->ch_flags |= (CH_BAUD0); + ch->ch_mostat &= ~(UART_MCR_RTS | UART_MCR_DTR); + cls_assert_modem_signals(ch); + ch->ch_old_baud = 0; + return; + } else if (ch->ch_custom_speed) { + baud = ch->ch_custom_speed; + /* Handle transition from B0 */ + if (ch->ch_flags & CH_BAUD0) { + ch->ch_flags &= ~(CH_BAUD0); + + /* + * Bring back up RTS and DTR... + * Also handle RTS or DTR toggle if set. + */ + if (!(ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE)) + ch->ch_mostat |= (UART_MCR_RTS); + if (!(ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE)) + ch->ch_mostat |= (UART_MCR_DTR); + } + + } else { + int iindex = 0; + int jindex = 0; + + ulong bauds[4][16] = { + { /* slowbaud */ + 0, 50, 75, 110, + 134, 150, 200, 300, + 600, 1200, 1800, 2400, + 4800, 9600, 19200, 38400 }, + { /* slowbaud & CBAUDEX */ + 0, 57600, 115200, 230400, + 460800, 150, 200, 921600, + 600, 1200, 1800, 2400, + 4800, 9600, 19200, 38400 }, + { /* fastbaud */ + 0, 57600, 76800, 115200, + 131657, 153600, 230400, 460800, + 921600, 1200, 1800, 2400, + 4800, 9600, 19200, 38400 }, + { /* fastbaud & CBAUDEX */ + 0, 57600, 115200, 230400, + 460800, 150, 200, 921600, + 600, 1200, 1800, 2400, + 4800, 9600, 19200, 38400 } + }; + + /* + * Only use the TXPrint baud rate if the terminal * unit is NOT open */ if (!(ch->ch_tun.un_flags & UN_ISOPEN) && @@ -762,133 +992,46 @@ static irqreturn_t cls_intr(int irq, void *voidbrd) brd->intr_count++; - /* - * Check the board's global interrupt offset to see if we - * we actually do have an interrupt pending for us. - */ - poll_reg = readb(brd->re_map_membase + UART_CLASSIC_POLL_ADDR_OFFSET); - - /* If 0, no interrupts pending */ - if (!poll_reg) { - spin_unlock_irqrestore(&brd->bd_intr_lock, flags); - return IRQ_NONE; - } - - /* Parse each port to find out what caused the interrupt */ - for (i = 0; i < brd->nasync; i++) - cls_parse_isr(brd, i); - - /* - * Schedule tasklet to more in-depth servicing at a better time. - */ - tasklet_schedule(&brd->helper_tasklet); - - spin_unlock_irqrestore(&brd->bd_intr_lock, flags); - - return IRQ_HANDLED; -} - -static void cls_disable_receiver(struct channel_t *ch) -{ - unsigned char tmp = readb(&ch->ch_cls_uart->ier); - - tmp &= ~(UART_IER_RDI); - writeb(tmp, &ch->ch_cls_uart->ier); -} - -static void cls_enable_receiver(struct channel_t *ch) -{ - unsigned char tmp = readb(&ch->ch_cls_uart->ier); - - tmp |= (UART_IER_RDI); - writeb(tmp, &ch->ch_cls_uart->ier); -} - -static void cls_copy_data_from_uart_to_queue(struct channel_t *ch) -{ - int qleft = 0; - unsigned char linestatus = 0; - unsigned char error_mask = 0; - ushort head; - ushort tail; - unsigned long flags; - - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) - return; - - spin_lock_irqsave(&ch->ch_lock, flags); - - /* cache head and tail of queue */ - head = ch->ch_r_head; - tail = ch->ch_r_tail; - - /* Store how much space we have left in the queue */ - qleft = tail - head - 1; - if (qleft < 0) - qleft += RQUEUEMASK + 1; - - /* - * Create a mask to determine whether we should - * insert the character (if any) into our queue. - */ - if (ch->ch_c_iflag & IGNBRK) - error_mask |= UART_LSR_BI; - - while (1) { - linestatus = readb(&ch->ch_cls_uart->lsr); - - if (!(linestatus & (UART_LSR_DR))) - break; - - /* - * Discard character if we are ignoring the error mask. - */ - if (linestatus & error_mask) { - linestatus = 0; - readb(&ch->ch_cls_uart->txrx); - continue; - } - - /* - * If our queue is full, we have no choice but to drop some - * data. The assumption is that HWFLOW or SWFLOW should have - * stopped things way way before we got to this point. - * - * I decided that I wanted to ditch the oldest data first, - * I hope thats okay with everyone? Yes? Good. - */ - while (qleft < 1) { - tail = (tail + 1) & RQUEUEMASK; - ch->ch_r_tail = tail; - ch->ch_err_overrun++; - qleft++; - } - - ch->ch_equeue[head] = linestatus & (UART_LSR_BI | UART_LSR_PE - | UART_LSR_FE); - ch->ch_rqueue[head] = readb(&ch->ch_cls_uart->txrx); - - qleft--; - - if (ch->ch_equeue[head] & UART_LSR_PE) - ch->ch_err_parity++; - if (ch->ch_equeue[head] & UART_LSR_BI) - ch->ch_err_break++; - if (ch->ch_equeue[head] & UART_LSR_FE) - ch->ch_err_frame++; - - /* Add to, and flip head if needed */ - head = (head + 1) & RQUEUEMASK; - ch->ch_rxcount++; + /* + * Check the board's global interrupt offset to see if we + * we actually do have an interrupt pending for us. + */ + poll_reg = readb(brd->re_map_membase + UART_CLASSIC_POLL_ADDR_OFFSET); + + /* If 0, no interrupts pending */ + if (!poll_reg) { + spin_unlock_irqrestore(&brd->bd_intr_lock, flags); + return IRQ_NONE; } + /* Parse each port to find out what caused the interrupt */ + for (i = 0; i < brd->nasync; i++) + cls_parse_isr(brd, i); + /* - * Write new final heads to channel structure. + * Schedule tasklet to more in-depth servicing at a better time. */ - ch->ch_r_head = head & RQUEUEMASK; - ch->ch_e_head = head & EQUEUEMASK; + tasklet_schedule(&brd->helper_tasklet); - spin_unlock_irqrestore(&ch->ch_lock, flags); + spin_unlock_irqrestore(&brd->bd_intr_lock, flags); + + return IRQ_HANDLED; +} + +static void cls_disable_receiver(struct channel_t *ch) +{ + unsigned char tmp = readb(&ch->ch_cls_uart->ier); + + tmp &= ~(UART_IER_RDI); + writeb(tmp, &ch->ch_cls_uart->ier); +} + +static void cls_enable_receiver(struct channel_t *ch) +{ + unsigned char tmp = readb(&ch->ch_cls_uart->ier); + + tmp |= (UART_IER_RDI); + writeb(tmp, &ch->ch_cls_uart->ier); } /* @@ -926,199 +1069,6 @@ static int cls_drain(struct tty_struct *tty, uint seconds) ((un->un_flags & UN_EMPTY) == 0)); } -/* Channel lock MUST be held before calling this function! */ -static void cls_flush_uart_write(struct channel_t *ch) -{ - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) - return; - - writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_XMIT), - &ch->ch_cls_uart->isr_fcr); - usleep_range(10, 20); - - ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); -} - -/* Channel lock MUST be held before calling this function! */ -static void cls_flush_uart_read(struct channel_t *ch) -{ - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) - return; - - /* - * For complete POSIX compatibility, we should be purging the - * read FIFO in the UART here. - * - * However, clearing the read FIFO (UART_FCR_CLEAR_RCVR) also - * incorrectly flushes write data as well as just basically trashing the - * FIFO. - * - * Presumably, this is a bug in this UART. - */ - - udelay(10); -} - -static void cls_copy_data_from_queue_to_uart(struct channel_t *ch) -{ - ushort head; - ushort tail; - int n; - int qlen; - uint len_written = 0; - unsigned long flags; - - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) - return; - - spin_lock_irqsave(&ch->ch_lock, flags); - - /* No data to write to the UART */ - if (ch->ch_w_tail == ch->ch_w_head) - goto exit_unlock; - - /* If port is "stopped", don't send any data to the UART */ - if ((ch->ch_flags & CH_FORCED_STOP) || - (ch->ch_flags & CH_BREAK_SENDING)) - goto exit_unlock; - - if (!(ch->ch_flags & (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM))) - goto exit_unlock; - - n = 32; - - /* cache head and tail of queue */ - head = ch->ch_w_head & WQUEUEMASK; - tail = ch->ch_w_tail & WQUEUEMASK; - qlen = (head - tail) & WQUEUEMASK; - - /* Find minimum of the FIFO space, versus queue length */ - n = min(n, qlen); - - while (n > 0) { - /* - * If RTS Toggle mode is on, turn on RTS now if not already set, - * and make sure we get an event when the data transfer has - * completed. - */ - if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) { - if (!(ch->ch_mostat & UART_MCR_RTS)) { - ch->ch_mostat |= (UART_MCR_RTS); - cls_assert_modem_signals(ch); - } - ch->ch_tun.un_flags |= (UN_EMPTY); - } - - /* - * If DTR Toggle mode is on, turn on DTR now if not already set, - * and make sure we get an event when the data transfer has - * completed. - */ - if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) { - if (!(ch->ch_mostat & UART_MCR_DTR)) { - ch->ch_mostat |= (UART_MCR_DTR); - cls_assert_modem_signals(ch); - } - ch->ch_tun.un_flags |= (UN_EMPTY); - } - writeb(ch->ch_wqueue[ch->ch_w_tail], &ch->ch_cls_uart->txrx); - ch->ch_w_tail++; - ch->ch_w_tail &= WQUEUEMASK; - ch->ch_txcount++; - len_written++; - n--; - } - - if (len_written > 0) - ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); - -exit_unlock: - spin_unlock_irqrestore(&ch->ch_lock, flags); -} - -static void cls_parse_modem(struct channel_t *ch, unsigned char signals) -{ - unsigned char msignals = signals; - unsigned long flags; - - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) - return; - - /* - * Do altpin switching. Altpin switches DCD and DSR. - * This prolly breaks DSRPACE, so we should be more clever here. - */ - spin_lock_irqsave(&ch->ch_lock, flags); - if (ch->ch_digi.digi_flags & DIGI_ALTPIN) { - unsigned char mswap = signals; - - if (mswap & UART_MSR_DDCD) { - msignals &= ~UART_MSR_DDCD; - msignals |= UART_MSR_DDSR; - } - if (mswap & UART_MSR_DDSR) { - msignals &= ~UART_MSR_DDSR; - msignals |= UART_MSR_DDCD; - } - if (mswap & UART_MSR_DCD) { - msignals &= ~UART_MSR_DCD; - msignals |= UART_MSR_DSR; - } - if (mswap & UART_MSR_DSR) { - msignals &= ~UART_MSR_DSR; - msignals |= UART_MSR_DCD; - } - } - spin_unlock_irqrestore(&ch->ch_lock, flags); - - /* - * Scrub off lower bits. They signify delta's, which I don't - * care about - */ - signals &= 0xf0; - - spin_lock_irqsave(&ch->ch_lock, flags); - if (msignals & UART_MSR_DCD) - ch->ch_mistat |= UART_MSR_DCD; - else - ch->ch_mistat &= ~UART_MSR_DCD; - - if (msignals & UART_MSR_DSR) - ch->ch_mistat |= UART_MSR_DSR; - else - ch->ch_mistat &= ~UART_MSR_DSR; - - if (msignals & UART_MSR_RI) - ch->ch_mistat |= UART_MSR_RI; - else - ch->ch_mistat &= ~UART_MSR_RI; - - if (msignals & UART_MSR_CTS) - ch->ch_mistat |= UART_MSR_CTS; - else - ch->ch_mistat &= ~UART_MSR_CTS; - spin_unlock_irqrestore(&ch->ch_lock, flags); -} - -/* Make the UART raise any of the output signals we want up */ -static void cls_assert_modem_signals(struct channel_t *ch) -{ - unsigned char out; - - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) - return; - - out = ch->ch_mostat; - - if (ch->ch_flags & CH_LOOPBACK) - out |= UART_MCR_LOOP; - - writeb(out, &ch->ch_cls_uart->mcr); - - /* Give time for the UART to actually drop the signals */ - udelay(10); -} - static void cls_send_start_character(struct channel_t *ch) { if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) @@ -1298,3 +1248,24 @@ static void cls_vpd(struct dgnc_board *brd) iounmap(re_map_vpdbase); } + +struct board_ops dgnc_cls_ops = { + .tasklet = cls_tasklet, + .intr = cls_intr, + .uart_init = cls_uart_init, + .uart_off = cls_uart_off, + .drain = cls_drain, + .param = cls_param, + .vpd = cls_vpd, + .assert_modem_signals = cls_assert_modem_signals, + .flush_uart_write = cls_flush_uart_write, + .flush_uart_read = cls_flush_uart_read, + .disable_receiver = cls_disable_receiver, + .enable_receiver = cls_enable_receiver, + .send_break = cls_send_break, + .send_start_character = cls_send_start_character, + .send_stop_character = cls_send_stop_character, + .copy_data_from_queue_to_uart = cls_copy_data_from_queue_to_uart, + .get_uart_bytes_left = cls_get_uart_bytes_left, + .send_immediate_char = cls_send_immediate_char +}; -- cgit v0.10.2 From 3bd0010a18795f3e48e96fe75e67fb3f84706fcf Mon Sep 17 00:00:00 2001 From: Daeseok Youn <daeseok.youn@gmail.com> Date: Wed, 6 Jul 2016 15:15:34 +0900 Subject: staging: dgnc: remove redundant NULL check for brd the "brd" value cannot be NULL in dgnc_finalize_board_init(). Because "brd" as a parameter of this function was already checked for NULL. the dgnc_finalize_board_init() as a static function was called only from dgnc_found_board() function and brd->magic value was assigned once in dgnc_found_board(). So it doesn't need to check for DGNC_BOARD_MAGIC value. Signed-off-by: Daeseok Youn <daeseok.youn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c index 2c3fb2a..e699375 100644 --- a/drivers/staging/dgnc/dgnc_driver.c +++ b/drivers/staging/dgnc/dgnc_driver.c @@ -579,9 +579,6 @@ static int dgnc_finalize_board_init(struct dgnc_board *brd) { int rc = 0; - if (!brd || brd->magic != DGNC_BOARD_MAGIC) - return -ENODEV; - if (brd->irq) { rc = request_irq(brd->irq, brd->bd_ops->intr, IRQF_SHARED, "DGNC", brd); -- cgit v0.10.2 From fb7d94a7582e494a71c3a0b311910f7b179c01d9 Mon Sep 17 00:00:00 2001 From: Daeseok Youn <daeseok.youn@gmail.com> Date: Wed, 6 Jul 2016 15:16:12 +0900 Subject: staging: dgnc: remove useless variable 'intr_count' The 'intr_count' variable was used only for increasing. So the 'intr_count' variable is not useful for this driver. Signed-off-by: Daeseok Youn <daeseok.youn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_cls.c b/drivers/staging/dgnc/dgnc_cls.c index 2347bdc..ac0899a 100644 --- a/drivers/staging/dgnc/dgnc_cls.c +++ b/drivers/staging/dgnc/dgnc_cls.c @@ -990,8 +990,6 @@ static irqreturn_t cls_intr(int irq, void *voidbrd) spin_lock_irqsave(&brd->bd_intr_lock, flags); - brd->intr_count++; - /* * Check the board's global interrupt offset to see if we * we actually do have an interrupt pending for us. diff --git a/drivers/staging/dgnc/dgnc_driver.h b/drivers/staging/dgnc/dgnc_driver.h index 95ec729..7ac33ed 100644 --- a/drivers/staging/dgnc/dgnc_driver.h +++ b/drivers/staging/dgnc/dgnc_driver.h @@ -183,7 +183,6 @@ struct dgnc_board { uint nasync; /* Number of ports on card */ uint irq; /* Interrupt request number */ - ulong intr_count; /* Count of interrupts */ ulong intr_modem; /* Count of interrupts */ ulong intr_tx; /* Count of interrupts */ ulong intr_rx; /* Count of interrupts */ diff --git a/drivers/staging/dgnc/dgnc_neo.c b/drivers/staging/dgnc/dgnc_neo.c index ba57e95..3f8bbb3 100644 --- a/drivers/staging/dgnc/dgnc_neo.c +++ b/drivers/staging/dgnc/dgnc_neo.c @@ -926,8 +926,6 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) if (!brd || brd->magic != DGNC_BOARD_MAGIC) return IRQ_NONE; - brd->intr_count++; - /* Lock out the slow poller from running on this board. */ spin_lock_irqsave(&brd->bd_intr_lock, flags); -- cgit v0.10.2 From 14ad5165117713d521969eff9a25a7692531bb22 Mon Sep 17 00:00:00 2001 From: Daeseok Youn <daeseok.youn@gmail.com> Date: Wed, 6 Jul 2016 15:16:44 +0900 Subject: staging: dgnc: remove redundant null check in the "brd" was already checked for NULL before calling dgnc_do_remap(). the dgnc_do_remap() function was called only from the dgnc_found_board() and the DGNC_BOARD_MAGIC value was assigned to "brd->magic" in dgcn_found_board(). So it doesn't need to check about magic value. Signed-off-by: Daeseok Youn <daeseok.youn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c index e699375..cc6105a 100644 --- a/drivers/staging/dgnc/dgnc_driver.c +++ b/drivers/staging/dgnc/dgnc_driver.c @@ -599,9 +599,6 @@ static int dgnc_finalize_board_init(struct dgnc_board *brd) */ static void dgnc_do_remap(struct dgnc_board *brd) { - if (!brd || brd->magic != DGNC_BOARD_MAGIC) - return; - brd->re_map_membase = ioremap(brd->membase, 0x1000); } -- cgit v0.10.2 From ca0d0b889c055669e4efe4b8bb656d48b7e40944 Mon Sep 17 00:00:00 2001 From: Daeseok Youn <daeseok.youn@gmail.com> Date: Wed, 6 Jul 2016 15:17:18 +0900 Subject: staging: dgnc: remove unused variable 'intr_modem' The 'intr_modem' variable was used only for increasing. So the 'intr_modem' variable is not useful for this driver. Signed-off-by: Daeseok Youn <daeseok.youn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_cls.c b/drivers/staging/dgnc/dgnc_cls.c index ac0899a..449a6bb 100644 --- a/drivers/staging/dgnc/dgnc_cls.c +++ b/drivers/staging/dgnc/dgnc_cls.c @@ -603,7 +603,6 @@ static inline void cls_parse_isr(struct dgnc_board *brd, uint port) /* CTS/RTS change of state */ if (isr & UART_IIR_CTSRTS) { - brd->intr_modem++; ch->ch_intr_modem++; /* * Don't need to do anything, the cls_parse_modem diff --git a/drivers/staging/dgnc/dgnc_driver.h b/drivers/staging/dgnc/dgnc_driver.h index 7ac33ed..2caeff7 100644 --- a/drivers/staging/dgnc/dgnc_driver.h +++ b/drivers/staging/dgnc/dgnc_driver.h @@ -183,7 +183,6 @@ struct dgnc_board { uint nasync; /* Number of ports on card */ uint irq; /* Interrupt request number */ - ulong intr_modem; /* Count of interrupts */ ulong intr_tx; /* Count of interrupts */ ulong intr_rx; /* Count of interrupts */ diff --git a/drivers/staging/dgnc/dgnc_neo.c b/drivers/staging/dgnc/dgnc_neo.c index 3f8bbb3..a3e100b 100644 --- a/drivers/staging/dgnc/dgnc_neo.c +++ b/drivers/staging/dgnc/dgnc_neo.c @@ -452,7 +452,6 @@ static inline void neo_parse_isr(struct dgnc_board *brd, uint port) * If we get here, this means the hardware is doing auto flow control. * Check to see whether RTS/DTR or CTS/DSR caused this interrupt. */ - brd->intr_modem++; ch->ch_intr_modem++; cause = readb(&ch->ch_neo_uart->mcr); /* Which pin is doing auto flow? RTS or DTR? */ -- cgit v0.10.2 From 262c5e1bab2a8bedb9e5148b17cf6de7674934cf Mon Sep 17 00:00:00 2001 From: Daeseok Youn <daeseok.youn@gmail.com> Date: Wed, 6 Jul 2016 15:17:53 +0900 Subject: staging: dgnc: remove useless variable 'intr_tx' The 'intr_tx' variable was used only for increasing. So the 'intr_tx' variable is not useful for this driver. Signed-off-by: Daeseok Youn <daeseok.youn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_cls.c b/drivers/staging/dgnc/dgnc_cls.c index 449a6bb..088b546 100644 --- a/drivers/staging/dgnc/dgnc_cls.c +++ b/drivers/staging/dgnc/dgnc_cls.c @@ -595,7 +595,6 @@ static inline void cls_parse_isr(struct dgnc_board *brd, uint port) /* Transfer data (if any) from Write Queue -> UART. */ spin_lock_irqsave(&ch->ch_lock, flags); ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); - brd->intr_tx++; ch->ch_intr_tx++; spin_unlock_irqrestore(&ch->ch_lock, flags); cls_copy_data_from_queue_to_uart(ch); diff --git a/drivers/staging/dgnc/dgnc_driver.h b/drivers/staging/dgnc/dgnc_driver.h index 2caeff7..a8d823b 100644 --- a/drivers/staging/dgnc/dgnc_driver.h +++ b/drivers/staging/dgnc/dgnc_driver.h @@ -183,7 +183,6 @@ struct dgnc_board { uint nasync; /* Number of ports on card */ uint irq; /* Interrupt request number */ - ulong intr_tx; /* Count of interrupts */ ulong intr_rx; /* Count of interrupts */ ulong membase; /* Start of base memory of the card */ diff --git a/drivers/staging/dgnc/dgnc_neo.c b/drivers/staging/dgnc/dgnc_neo.c index a3e100b..5f3eacdf 100644 --- a/drivers/staging/dgnc/dgnc_neo.c +++ b/drivers/staging/dgnc/dgnc_neo.c @@ -410,7 +410,6 @@ static inline void neo_parse_isr(struct dgnc_board *brd, uint port) } if (isr & UART_IIR_THRI) { - brd->intr_tx++; ch->ch_intr_tx++; /* Transfer data (if any) from Write Queue -> UART. */ spin_lock_irqsave(&ch->ch_lock, flags); @@ -550,7 +549,6 @@ static inline void neo_parse_lsr(struct dgnc_board *brd, uint port) } if (linestatus & UART_LSR_THRE) { - brd->intr_tx++; ch->ch_intr_tx++; spin_lock_irqsave(&ch->ch_lock, flags); ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); @@ -559,7 +557,6 @@ static inline void neo_parse_lsr(struct dgnc_board *brd, uint port) /* Transfer data (if any) from Write Queue -> UART. */ neo_copy_data_from_queue_to_uart(ch); } else if (linestatus & UART_17158_TX_AND_FIFO_CLR) { - brd->intr_tx++; ch->ch_intr_tx++; spin_lock_irqsave(&ch->ch_lock, flags); ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); -- cgit v0.10.2 From 572f4f61cd56a192dca8415f84d1abd6b10e2b26 Mon Sep 17 00:00:00 2001 From: Daeseok Youn <daeseok.youn@gmail.com> Date: Wed, 6 Jul 2016 15:18:25 +0900 Subject: staging: dgnc: remove useless variable 'intr_rx' The 'intr_rx' variable was used only for increasing. So the 'intr_rx' variable is not useful for this driver. Signed-off-by: Daeseok Youn <daeseok.youn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_cls.c b/drivers/staging/dgnc/dgnc_cls.c index 088b546..31fcf04 100644 --- a/drivers/staging/dgnc/dgnc_cls.c +++ b/drivers/staging/dgnc/dgnc_cls.c @@ -584,7 +584,6 @@ static inline void cls_parse_isr(struct dgnc_board *brd, uint port) /* Receive Interrupt pending */ if (isr & (UART_IIR_RDI | UART_IIR_RDI_TIMEOUT)) { /* Read data from uart -> queue */ - brd->intr_rx++; ch->ch_intr_rx++; cls_copy_data_from_uart_to_queue(ch); dgnc_check_queue_flow_control(ch); diff --git a/drivers/staging/dgnc/dgnc_driver.h b/drivers/staging/dgnc/dgnc_driver.h index a8d823b..914130d 100644 --- a/drivers/staging/dgnc/dgnc_driver.h +++ b/drivers/staging/dgnc/dgnc_driver.h @@ -183,7 +183,6 @@ struct dgnc_board { uint nasync; /* Number of ports on card */ uint irq; /* Interrupt request number */ - ulong intr_rx; /* Count of interrupts */ ulong membase; /* Start of base memory of the card */ ulong membase_end; /* End of base memory of the card */ diff --git a/drivers/staging/dgnc/dgnc_neo.c b/drivers/staging/dgnc/dgnc_neo.c index 5f3eacdf..f99c0db 100644 --- a/drivers/staging/dgnc/dgnc_neo.c +++ b/drivers/staging/dgnc/dgnc_neo.c @@ -399,7 +399,6 @@ static inline void neo_parse_isr(struct dgnc_board *brd, uint port) if (isr & (UART_17158_IIR_RDI_TIMEOUT | UART_IIR_RDI)) { /* Read data from uart -> queue */ - brd->intr_rx++; ch->ch_intr_rx++; neo_copy_data_from_uart_to_queue(ch); @@ -515,7 +514,6 @@ static inline void neo_parse_lsr(struct dgnc_board *brd, uint port) ch->ch_cached_lsr |= linestatus; if (ch->ch_cached_lsr & UART_LSR_DR) { - brd->intr_rx++; ch->ch_intr_rx++; /* Read data from uart -> queue */ neo_copy_data_from_uart_to_queue(ch); -- cgit v0.10.2 From 74c900f5e99e2af69e71e4527088a204ad9dd6e4 Mon Sep 17 00:00:00 2001 From: Daeseok Youn <daeseok.youn@gmail.com> Date: Wed, 6 Jul 2016 15:18:56 +0900 Subject: staging: dgnc: remove useless variable 'ch_intr_modem' The 'ch_intr_modem' variable was used only for increasing. So the 'ch_intr_modem' variable is not useful for this driver. Signed-off-by: Daeseok Youn <daeseok.youn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_cls.c b/drivers/staging/dgnc/dgnc_cls.c index 31fcf04..b9955be 100644 --- a/drivers/staging/dgnc/dgnc_cls.c +++ b/drivers/staging/dgnc/dgnc_cls.c @@ -599,15 +599,6 @@ static inline void cls_parse_isr(struct dgnc_board *brd, uint port) cls_copy_data_from_queue_to_uart(ch); } - /* CTS/RTS change of state */ - if (isr & UART_IIR_CTSRTS) { - ch->ch_intr_modem++; - /* - * Don't need to do anything, the cls_parse_modem - * below will grab the updated modem signals. - */ - } - /* Parse any modem signal changes */ cls_parse_modem(ch, readb(&ch->ch_cls_uart->msr)); } diff --git a/drivers/staging/dgnc/dgnc_driver.h b/drivers/staging/dgnc/dgnc_driver.h index 914130d..10633880 100644 --- a/drivers/staging/dgnc/dgnc_driver.h +++ b/drivers/staging/dgnc/dgnc_driver.h @@ -377,7 +377,6 @@ struct channel_t { ulong ch_xon_sends; /* Count of xons transmitted */ ulong ch_xoff_sends; /* Count of xoffs transmitted */ - ulong ch_intr_modem; /* Count of interrupts */ ulong ch_intr_tx; /* Count of interrupts */ ulong ch_intr_rx; /* Count of interrupts */ diff --git a/drivers/staging/dgnc/dgnc_neo.c b/drivers/staging/dgnc/dgnc_neo.c index f99c0db..9b3264c 100644 --- a/drivers/staging/dgnc/dgnc_neo.c +++ b/drivers/staging/dgnc/dgnc_neo.c @@ -450,7 +450,6 @@ static inline void neo_parse_isr(struct dgnc_board *brd, uint port) * If we get here, this means the hardware is doing auto flow control. * Check to see whether RTS/DTR or CTS/DSR caused this interrupt. */ - ch->ch_intr_modem++; cause = readb(&ch->ch_neo_uart->mcr); /* Which pin is doing auto flow? RTS or DTR? */ if ((cause & 0x4) == 0) { -- cgit v0.10.2 From 2c7d924e28c24cfced3528c344faedfba8aaee56 Mon Sep 17 00:00:00 2001 From: Daeseok Youn <daeseok.youn@gmail.com> Date: Wed, 6 Jul 2016 15:19:27 +0900 Subject: staging: dgnc: remove useless variable 'ch_intr_tx' The 'ch_intr_tx' variable was used only for increasing. So the 'ch_intr_tx' variable is not useful for this driver. Signed-off-by: Daeseok Youn <daeseok.youn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_cls.c b/drivers/staging/dgnc/dgnc_cls.c index b9955be..35b59ca 100644 --- a/drivers/staging/dgnc/dgnc_cls.c +++ b/drivers/staging/dgnc/dgnc_cls.c @@ -594,7 +594,6 @@ static inline void cls_parse_isr(struct dgnc_board *brd, uint port) /* Transfer data (if any) from Write Queue -> UART. */ spin_lock_irqsave(&ch->ch_lock, flags); ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); - ch->ch_intr_tx++; spin_unlock_irqrestore(&ch->ch_lock, flags); cls_copy_data_from_queue_to_uart(ch); } diff --git a/drivers/staging/dgnc/dgnc_driver.h b/drivers/staging/dgnc/dgnc_driver.h index 10633880..8bdf556 100644 --- a/drivers/staging/dgnc/dgnc_driver.h +++ b/drivers/staging/dgnc/dgnc_driver.h @@ -377,7 +377,6 @@ struct channel_t { ulong ch_xon_sends; /* Count of xons transmitted */ ulong ch_xoff_sends; /* Count of xoffs transmitted */ - ulong ch_intr_tx; /* Count of interrupts */ ulong ch_intr_rx; /* Count of interrupts */ /* /proc/<board>/<channel> entries */ diff --git a/drivers/staging/dgnc/dgnc_neo.c b/drivers/staging/dgnc/dgnc_neo.c index 9b3264c..574a227 100644 --- a/drivers/staging/dgnc/dgnc_neo.c +++ b/drivers/staging/dgnc/dgnc_neo.c @@ -409,7 +409,6 @@ static inline void neo_parse_isr(struct dgnc_board *brd, uint port) } if (isr & UART_IIR_THRI) { - ch->ch_intr_tx++; /* Transfer data (if any) from Write Queue -> UART. */ spin_lock_irqsave(&ch->ch_lock, flags); ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); @@ -546,7 +545,6 @@ static inline void neo_parse_lsr(struct dgnc_board *brd, uint port) } if (linestatus & UART_LSR_THRE) { - ch->ch_intr_tx++; spin_lock_irqsave(&ch->ch_lock, flags); ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); spin_unlock_irqrestore(&ch->ch_lock, flags); @@ -554,7 +552,6 @@ static inline void neo_parse_lsr(struct dgnc_board *brd, uint port) /* Transfer data (if any) from Write Queue -> UART. */ neo_copy_data_from_queue_to_uart(ch); } else if (linestatus & UART_17158_TX_AND_FIFO_CLR) { - ch->ch_intr_tx++; spin_lock_irqsave(&ch->ch_lock, flags); ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); spin_unlock_irqrestore(&ch->ch_lock, flags); -- cgit v0.10.2 From 4875bb884e761acbd141785b44dbbd715bd71195 Mon Sep 17 00:00:00 2001 From: Daeseok Youn <daeseok.youn@gmail.com> Date: Wed, 6 Jul 2016 15:19:58 +0900 Subject: staging: dgnc: remove useless variable 'ch_intr_rx' The 'ch_intr_rx' variable was used only for increasing. So the 'ch_intr_rx' variable is not useful for this driver. Signed-off-by: Daeseok Youn <daeseok.youn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_cls.c b/drivers/staging/dgnc/dgnc_cls.c index 35b59ca..4e1e0dc6 100644 --- a/drivers/staging/dgnc/dgnc_cls.c +++ b/drivers/staging/dgnc/dgnc_cls.c @@ -584,7 +584,6 @@ static inline void cls_parse_isr(struct dgnc_board *brd, uint port) /* Receive Interrupt pending */ if (isr & (UART_IIR_RDI | UART_IIR_RDI_TIMEOUT)) { /* Read data from uart -> queue */ - ch->ch_intr_rx++; cls_copy_data_from_uart_to_queue(ch); dgnc_check_queue_flow_control(ch); } diff --git a/drivers/staging/dgnc/dgnc_driver.h b/drivers/staging/dgnc/dgnc_driver.h index 8bdf556..3092abe 100644 --- a/drivers/staging/dgnc/dgnc_driver.h +++ b/drivers/staging/dgnc/dgnc_driver.h @@ -377,8 +377,6 @@ struct channel_t { ulong ch_xon_sends; /* Count of xons transmitted */ ulong ch_xoff_sends; /* Count of xoffs transmitted */ - ulong ch_intr_rx; /* Count of interrupts */ - /* /proc/<board>/<channel> entries */ struct proc_dir_entry *proc_entry_pointer; struct dgnc_proc_entry *dgnc_channel_table; diff --git a/drivers/staging/dgnc/dgnc_neo.c b/drivers/staging/dgnc/dgnc_neo.c index 574a227..5ef5b3e 100644 --- a/drivers/staging/dgnc/dgnc_neo.c +++ b/drivers/staging/dgnc/dgnc_neo.c @@ -399,7 +399,6 @@ static inline void neo_parse_isr(struct dgnc_board *brd, uint port) if (isr & (UART_17158_IIR_RDI_TIMEOUT | UART_IIR_RDI)) { /* Read data from uart -> queue */ - ch->ch_intr_rx++; neo_copy_data_from_uart_to_queue(ch); /* Call our tty layer to enforce queue flow control if needed. */ @@ -512,7 +511,6 @@ static inline void neo_parse_lsr(struct dgnc_board *brd, uint port) ch->ch_cached_lsr |= linestatus; if (ch->ch_cached_lsr & UART_LSR_DR) { - ch->ch_intr_rx++; /* Read data from uart -> queue */ neo_copy_data_from_uart_to_queue(ch); spin_lock_irqsave(&ch->ch_lock, flags); -- cgit v0.10.2 From b6ed5a233aea3bd44243bb18d396941c4076e3dc Mon Sep 17 00:00:00 2001 From: Laurence Rochfort <laurence.rochfort@gmail.com> Date: Wed, 18 May 2016 21:07:45 +0100 Subject: Staging: speakup: Remove space after cast Fix the checkpatch.pl warning "No space is necessary after a cast". Signed-off-by: Laurence Rochfort <laurence.rochfort@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/speakup/devsynth.c b/drivers/staging/speakup/devsynth.c index 8498971..58abd1d 100644 --- a/drivers/staging/speakup/devsynth.c +++ b/drivers/staging/speakup/devsynth.c @@ -34,7 +34,7 @@ static ssize_t speakup_file_write(struct file *fp, const char __user *buffer, synth_write(buf, bytes); spin_unlock_irqrestore(&speakup_info.spinlock, flags); } - return (ssize_t) nbytes; + return (ssize_t)nbytes; } static ssize_t speakup_file_read(struct file *fp, char __user *buf, -- cgit v0.10.2 From 99a9ffacc1d390e9548b2370beb816c6739b84b2 Mon Sep 17 00:00:00 2001 From: Colin Ian King <colin.king@canonical.com> Date: Mon, 9 May 2016 23:22:14 +0100 Subject: staging: speakup: ensure we do not overrun synths array synth_add allows one to add MAXSYNTHS synths to the synths array; however it always NULLifies the next synth in the array which means that on the MAXSYNTHS synth we get an out-of-bounds write of the NULL to the synths array. Make the synths array MAXSYNTHS + 1 elements in size to allow for the final NULL sentinal to avoid the out-of-bounds write. Issue found wit CoverityScan, CID#744671 Signed-off-by: Colin Ian King <colin.king@canonical.com> Reviewed-by: Samuel Thibault <samuel.thibault@ens-lyon.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/speakup/synth.c b/drivers/staging/speakup/synth.c index 4f462c3..810a214 100644 --- a/drivers/staging/speakup/synth.c +++ b/drivers/staging/speakup/synth.c @@ -18,7 +18,7 @@ #include "serialio.h" #define MAXSYNTHS 16 /* Max number of synths in array. */ -static struct spk_synth *synths[MAXSYNTHS]; +static struct spk_synth *synths[MAXSYNTHS + 1]; struct spk_synth *synth; char spk_pitch_buff[32] = ""; static int module_status; -- cgit v0.10.2 From e494df039df0fc73587fda48752bfdbe88a6e7ce Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Mon, 6 Jun 2016 15:23:05 +0200 Subject: staging: most: v4l2-aim: fix interrupt unsafe spinlocks The functions get_aim_dev() and aim_rx_data() are using interrupt unsafe spinlocks even though they may be called from an interrupt context. This patch fixes the described problem. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/aim-v4l2/video.c b/drivers/staging/most/aim-v4l2/video.c index 13abf7c..1fea839 100644 --- a/drivers/staging/most/aim-v4l2/video.c +++ b/drivers/staging/most/aim-v4l2/video.c @@ -139,15 +139,15 @@ static int aim_vdev_close(struct file *filp) * This must be implemented in core. */ - spin_lock(&mdev->list_lock); + spin_lock_irq(&mdev->list_lock); mdev->mute = true; list_for_each_entry_safe(mbo, tmp, &mdev->pending_mbos, list) { list_del(&mbo->list); - spin_unlock(&mdev->list_lock); + spin_unlock_irq(&mdev->list_lock); most_put_mbo(mbo); - spin_lock(&mdev->list_lock); + spin_lock_irq(&mdev->list_lock); } - spin_unlock(&mdev->list_lock); + spin_unlock_irq(&mdev->list_lock); most_stop_channel(mdev->iface, mdev->ch_idx, &aim_info); mdev->mute = false; @@ -200,9 +200,9 @@ static ssize_t aim_vdev_read(struct file *filp, char __user *buf, if (cnt >= rem) { fh->offs = 0; - spin_lock(&mdev->list_lock); + spin_lock_irq(&mdev->list_lock); list_del(&mbo->list); - spin_unlock(&mdev->list_lock); + spin_unlock_irq(&mdev->list_lock); most_put_mbo(mbo); } } @@ -394,34 +394,36 @@ static struct most_video_dev *get_aim_dev( struct most_interface *iface, int channel_idx) { struct most_video_dev *mdev, *tmp; + unsigned long flags; - spin_lock(&list_lock); + spin_lock_irqsave(&list_lock, flags); list_for_each_entry_safe(mdev, tmp, &video_devices, list) { if (mdev->iface == iface && mdev->ch_idx == channel_idx) { - spin_unlock(&list_lock); + spin_unlock_irqrestore(&list_lock, flags); return mdev; } } - spin_unlock(&list_lock); + spin_unlock_irqrestore(&list_lock, flags); return NULL; } static int aim_rx_data(struct mbo *mbo) { + unsigned long flags; struct most_video_dev *mdev = get_aim_dev(mbo->ifp, mbo->hdm_channel_id); if (!mdev) return -EIO; - spin_lock(&mdev->list_lock); + spin_lock_irqsave(&mdev->list_lock, flags); if (unlikely(mdev->mute)) { - spin_unlock(&mdev->list_lock); + spin_unlock_irqrestore(&mdev->list_lock, flags); return -EIO; } list_add_tail(&mbo->list, &mdev->pending_mbos); - spin_unlock(&mdev->list_lock); + spin_unlock_irqrestore(&mdev->list_lock, flags); wake_up_interruptible(&mdev->wait_data); return 0; } @@ -529,9 +531,9 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx, if (ret) goto err_unreg; - spin_lock(&list_lock); + spin_lock_irq(&list_lock); list_add(&mdev->list, &video_devices); - spin_unlock(&list_lock); + spin_unlock_irq(&list_lock); return 0; err_unreg: @@ -552,9 +554,9 @@ static int aim_disconnect_channel(struct most_interface *iface, return -ENOENT; } - spin_lock(&list_lock); + spin_lock_irq(&list_lock); list_del(&mdev->list); - spin_unlock(&list_lock); + spin_unlock_irq(&list_lock); aim_unregister_videodev(mdev); v4l2_device_disconnect(&mdev->v4l2_dev); @@ -585,17 +587,17 @@ static void __exit aim_exit(void) * we simulate this call here. * This must be fixed in core. */ - spin_lock(&list_lock); + spin_lock_irq(&list_lock); list_for_each_entry_safe(mdev, tmp, &video_devices, list) { list_del(&mdev->list); - spin_unlock(&list_lock); + spin_unlock_irq(&list_lock); aim_unregister_videodev(mdev); v4l2_device_disconnect(&mdev->v4l2_dev); v4l2_device_put(&mdev->v4l2_dev); - spin_lock(&list_lock); + spin_lock_irq(&list_lock); } - spin_unlock(&list_lock); + spin_unlock_irq(&list_lock); most_deregister_aim(&aim_info); BUG_ON(!list_empty(&video_devices)); -- cgit v0.10.2 From db5a48d595cfd27ba66625558d982205b46d11fd Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Mon, 6 Jun 2016 15:23:06 +0200 Subject: staging: most: v4l2-aim: optimize list_for_each_entry_safe As the function get_aim_dev() does not delete elements of the list, the use of macro list_for_each_entry_safe is not necessary. This patch replaces the macro list_for_each_entry_safe with the macro list_for_each_entry. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/aim-v4l2/video.c b/drivers/staging/most/aim-v4l2/video.c index 1fea839..6b7e220 100644 --- a/drivers/staging/most/aim-v4l2/video.c +++ b/drivers/staging/most/aim-v4l2/video.c @@ -393,11 +393,11 @@ static const struct video_device aim_videodev_template = { static struct most_video_dev *get_aim_dev( struct most_interface *iface, int channel_idx) { - struct most_video_dev *mdev, *tmp; + struct most_video_dev *mdev; unsigned long flags; spin_lock_irqsave(&list_lock, flags); - list_for_each_entry_safe(mdev, tmp, &video_devices, list) { + list_for_each_entry(mdev, &video_devices, list) { if (mdev->iface == iface && mdev->ch_idx == channel_idx) { spin_unlock_irqrestore(&list_lock, flags); return mdev; -- cgit v0.10.2 From 323977d5d33a8dff63193f2c68a2aff001e9b68f Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Mon, 6 Jun 2016 15:23:07 +0200 Subject: staging: most: v4l2-aim: assign unique names to devices The current V4L2 AIM implementation assigns to all video devices and to all V4L devices the same names. This patch makes use of hardware dependent names for the video devices and allows the user to choose the names for the V4L devices. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/aim-v4l2/video.c b/drivers/staging/most/aim-v4l2/video.c index 6b7e220..9a383e0 100644 --- a/drivers/staging/most/aim-v4l2/video.c +++ b/drivers/staging/most/aim-v4l2/video.c @@ -259,7 +259,7 @@ static int vidioc_querycap(struct file *file, void *priv, pr_info("vidioc_querycap()\n"); strlcpy(cap->driver, "v4l2_most_aim", sizeof(cap->driver)); - strlcpy(cap->card, "my_card", sizeof(cap->card)); + strlcpy(cap->card, "MOST", sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "%s", mdev->iface->description); @@ -446,7 +446,8 @@ static int aim_register_videodev(struct most_video_dev *mdev) *mdev->vdev = aim_videodev_template; mdev->vdev->v4l2_dev = &mdev->v4l2_dev; mdev->vdev->lock = &mdev->lock; - strcpy(mdev->vdev->name, "most v4l2 aim video"); + snprintf(mdev->vdev->name, sizeof(mdev->vdev->name), "MOST: %s", + mdev->v4l2_dev.name); /* Register the v4l2 device */ video_set_drvdata(mdev->vdev, mdev); @@ -518,8 +519,7 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx, mdev->v4l2_dev.release = aim_v4l2_dev_release; /* Create the v4l2_device */ - strlcpy(mdev->v4l2_dev.name, "most_video_device", - sizeof(mdev->v4l2_dev.name)); + strlcpy(mdev->v4l2_dev.name, name, sizeof(mdev->v4l2_dev.name)); ret = v4l2_device_register(NULL, &mdev->v4l2_dev); if (ret) { pr_err("v4l2_device_register() failed\n"); -- cgit v0.10.2 From 8f6f9ed15d679ad9384efd74d39aed4438cd0252 Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Mon, 6 Jun 2016 15:23:08 +0200 Subject: staging: most: v4l2-aim: replace pr_xx calls by v4l2_xx calls This patch replaces pr_info, pr_err, etc. function calls by the v4l2_... ones to get the device dependent logs. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/aim-v4l2/video.c b/drivers/staging/most/aim-v4l2/video.c index 9a383e0..b55ab62 100644 --- a/drivers/staging/most/aim-v4l2/video.c +++ b/drivers/staging/most/aim-v4l2/video.c @@ -79,7 +79,7 @@ static int aim_vdev_open(struct file *filp) struct most_video_dev *mdev = video_drvdata(filp); struct aim_fh *fh; - pr_info("aim_vdev_open()\n"); + v4l2_info(&mdev->v4l2_dev, "aim_vdev_open()\n"); switch (vdev->vfl_type) { case VFL_TYPE_GRABBER: @@ -93,7 +93,7 @@ static int aim_vdev_open(struct file *filp) return -ENOMEM; if (!atomic_inc_and_test(&mdev->access_ref)) { - pr_err("too many clients\n"); + v4l2_err(&mdev->v4l2_dev, "too many clients\n"); ret = -EBUSY; goto err_dec; } @@ -106,7 +106,7 @@ static int aim_vdev_open(struct file *filp) ret = most_start_channel(mdev->iface, mdev->ch_idx, &aim_info); if (ret) { - pr_err("most_start_channel() failed\n"); + v4l2_err(&mdev->v4l2_dev, "most_start_channel() failed\n"); goto err_rm; } @@ -128,7 +128,7 @@ static int aim_vdev_close(struct file *filp) struct most_video_dev *mdev = fh->mdev; struct mbo *mbo, *tmp; - pr_info("aim_vdev_close()\n"); + v4l2_info(&mdev->v4l2_dev, "aim_vdev_close()\n"); /* * We need to put MBOs back before we call most_stop_channel() @@ -187,7 +187,7 @@ static ssize_t aim_vdev_read(struct file *filp, char __user *buf, int const cnt = rem < count ? rem : count; if (copy_to_user(buf, mbo->virt_address + fh->offs, cnt)) { - pr_err("read: copy_to_user failed\n"); + v4l2_err(&mdev->v4l2_dev, "read: copy_to_user failed\n"); if (!ret) ret = -EFAULT; return ret; @@ -256,7 +256,7 @@ static int vidioc_querycap(struct file *file, void *priv, struct aim_fh *fh = priv; struct most_video_dev *mdev = fh->mdev; - pr_info("vidioc_querycap()\n"); + v4l2_info(&mdev->v4l2_dev, "vidioc_querycap()\n"); strlcpy(cap->driver, "v4l2_most_aim", sizeof(cap->driver)); strlcpy(cap->card, "MOST", sizeof(cap->card)); @@ -273,7 +273,10 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - pr_info("vidioc_enum_fmt_vid_cap() %d\n", f->index); + struct aim_fh *fh = priv; + struct most_video_dev *mdev = fh->mdev; + + v4l2_info(&mdev->v4l2_dev, "vidioc_enum_fmt_vid_cap() %d\n", f->index); if (f->index) return -EINVAL; @@ -289,7 +292,10 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - pr_info("vidioc_g_fmt_vid_cap()\n"); + struct aim_fh *fh = priv; + struct most_video_dev *mdev = fh->mdev; + + v4l2_info(&mdev->v4l2_dev, "vidioc_g_fmt_vid_cap()\n"); aim_set_format_struct(f); return 0; @@ -315,7 +321,10 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm) { - pr_info("vidioc_g_std()\n"); + struct aim_fh *fh = priv; + struct most_video_dev *mdev = fh->mdev; + + v4l2_info(&mdev->v4l2_dev, "vidioc_g_std()\n"); *norm = V4L2_STD_UNKNOWN; return 0; @@ -352,7 +361,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index) struct aim_fh *fh = priv; struct most_video_dev *mdev = fh->mdev; - pr_info("vidioc_s_input(%d)\n", index); + v4l2_info(&mdev->v4l2_dev, "vidioc_s_input(%d)\n", index); if (index >= V4L2_AIM_MAX_INPUT) return -EINVAL; @@ -433,7 +442,7 @@ static int aim_register_videodev(struct most_video_dev *mdev) int retval = -ENOMEM; int ret; - pr_info("aim_register_videodev()\n"); + v4l2_info(&mdev->v4l2_dev, "aim_register_videodev()\n"); init_waitqueue_head(&mdev->wait_data); @@ -453,7 +462,8 @@ static int aim_register_videodev(struct most_video_dev *mdev) video_set_drvdata(mdev->vdev, mdev); retval = video_register_device(mdev->vdev, VFL_TYPE_GRABBER, -1); if (retval != 0) { - pr_err("video_register_device failed (%d)\n", retval); + v4l2_err(&mdev->v4l2_dev, "video_register_device failed (%d)\n", + retval); ret = -ENODEV; goto err_vbi_dev; } @@ -467,7 +477,7 @@ err_vbi_dev: static void aim_unregister_videodev(struct most_video_dev *mdev) { - pr_info("aim_unregister_videodev()\n"); + v4l2_info(&mdev->v4l2_dev, "aim_unregister_videodev()\n"); video_unregister_device(mdev->vdev); } @@ -488,7 +498,7 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx, int ret; struct most_video_dev *mdev = get_aim_dev(iface, channel_idx); - pr_info("aim_probe_channel()\n"); + pr_info("aim_probe_channel(%s)\n", name); if (mdev) { pr_err("channel already linked\n"); @@ -534,6 +544,7 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx, spin_lock_irq(&list_lock); list_add(&mdev->list, &video_devices); spin_unlock_irq(&list_lock); + v4l2_info(&mdev->v4l2_dev, "aim_probe_channel() done\n"); return 0; err_unreg: @@ -547,13 +558,13 @@ static int aim_disconnect_channel(struct most_interface *iface, { struct most_video_dev *mdev = get_aim_dev(iface, channel_idx); - pr_info("aim_disconnect_channel()\n"); - if (!mdev) { pr_err("no such channel is linked\n"); return -ENOENT; } + v4l2_info(&mdev->v4l2_dev, "aim_disconnect_channel()\n"); + spin_lock_irq(&list_lock); list_del(&mdev->list); spin_unlock_irq(&list_lock); -- cgit v0.10.2 From b23e8e51e6dc40cfbdb0ae3f60fc0da3a3fda5a8 Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Mon, 6 Jun 2016 15:23:09 +0200 Subject: staging: most: v4l2-aim: remove unnecessary retval The function aim_register_videodev() uses the variables 'ret' and 'retval' to represent the same value. This patch removes 'retval' and replaces it with 'ret'. Further, it replaces the constant return value '-ENODEV' with the result returned by function video_register_device() in the event something went wrong. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/aim-v4l2/video.c b/drivers/staging/most/aim-v4l2/video.c index b55ab62..e0fee88 100644 --- a/drivers/staging/most/aim-v4l2/video.c +++ b/drivers/staging/most/aim-v4l2/video.c @@ -439,7 +439,6 @@ static int aim_rx_data(struct mbo *mbo) static int aim_register_videodev(struct most_video_dev *mdev) { - int retval = -ENOMEM; int ret; v4l2_info(&mdev->v4l2_dev, "aim_register_videodev()\n"); @@ -460,11 +459,10 @@ static int aim_register_videodev(struct most_video_dev *mdev) /* Register the v4l2 device */ video_set_drvdata(mdev->vdev, mdev); - retval = video_register_device(mdev->vdev, VFL_TYPE_GRABBER, -1); - if (retval != 0) { + ret = video_register_device(mdev->vdev, VFL_TYPE_GRABBER, -1); + if (ret) { v4l2_err(&mdev->v4l2_dev, "video_register_device failed (%d)\n", - retval); - ret = -ENODEV; + ret); goto err_vbi_dev; } -- cgit v0.10.2 From eab231c0398a91fbd294672bfe9e0ff45b368246 Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Mon, 6 Jun 2016 15:23:10 +0200 Subject: staging: most: v4l2-aim: remove unnecessary label err_vbi_dev For optimization purposes this patch removes the label err_vbi_dev. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/aim-v4l2/video.c b/drivers/staging/most/aim-v4l2/video.c index e0fee88..0cca9ce 100644 --- a/drivers/staging/most/aim-v4l2/video.c +++ b/drivers/staging/most/aim-v4l2/video.c @@ -463,13 +463,9 @@ static int aim_register_videodev(struct most_video_dev *mdev) if (ret) { v4l2_err(&mdev->v4l2_dev, "video_register_device failed (%d)\n", ret); - goto err_vbi_dev; + video_device_release(mdev->vdev); } - return 0; - -err_vbi_dev: - video_device_release(mdev->vdev); return ret; } -- cgit v0.10.2 From 908614be1604388236c2a1cc6048ec29893df5df Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Mon, 6 Jun 2016 15:23:11 +0200 Subject: staging: most: v4l2-aim: remove unnecessary spaces This patch removes the unnecessary spaces. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/aim-v4l2/video.c b/drivers/staging/most/aim-v4l2/video.c index 0cca9ce..150dc89 100644 --- a/drivers/staging/most/aim-v4l2/video.c +++ b/drivers/staging/most/aim-v4l2/video.c @@ -250,7 +250,7 @@ static int aim_set_format(struct most_video_dev *mdev, unsigned int cmd, return 0; } -static int vidioc_querycap(struct file *file, void *priv, +static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { struct aim_fh *fh = priv; @@ -270,7 +270,7 @@ static int vidioc_querycap(struct file *file, void *priv, return 0; } -static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { struct aim_fh *fh = priv; @@ -304,7 +304,7 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct aim_fh *fh = priv; + struct aim_fh *fh = priv; struct most_video_dev *mdev = fh->mdev; return aim_set_format(mdev, VIDIOC_TRY_FMT, f); @@ -313,7 +313,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct aim_fh *fh = priv; + struct aim_fh *fh = priv; struct most_video_dev *mdev = fh->mdev; return aim_set_format(mdev, VIDIOC_S_FMT, f); -- cgit v0.10.2 From 6df1dc05e73e5108d623c6a38dd24b30f0163657 Mon Sep 17 00:00:00 2001 From: Matt Ranostay <mranostay@gmail.com> Date: Mon, 1 Aug 2016 19:39:51 -0700 Subject: tools: iio: lsiio: enumerate processed channels Enumerate the processed channels (e.g. *_input) as well the raw channels. Signed-off-by: Matt Ranostay <mranostay@gmail.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/tools/iio/lsiio.c b/tools/iio/lsiio.c index 3d650e6..ab0f5cf 100644 --- a/tools/iio/lsiio.c +++ b/tools/iio/lsiio.c @@ -51,7 +51,8 @@ static int dump_channels(const char *dev_dir_name) while (ent = readdir(dp), ent) if (check_prefix(ent->d_name, "in_") && - check_postfix(ent->d_name, "_raw")) + (check_postfix(ent->d_name, "_raw") || + check_postfix(ent->d_name, "_input"))) printf(" %-10s\n", ent->d_name); return (closedir(dp) == -1) ? -errno : 0; -- cgit v0.10.2 From 6ebb3727ead795a4dc80f99d2e8065dbc041ccce Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Mon, 13 Jun 2016 16:24:23 +0200 Subject: staging: most: dim2-hdm: fix race condition when closing a channel This patch fixes race between the function poison_channel that clears the state is_initialized and the tasklet function dim2_tasklet_fn that checks the state is_initialized. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c index a364495..89a66bb 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hdm.c +++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c @@ -705,12 +705,14 @@ static int poison_channel(struct most_interface *most_iface, int ch_idx) if (!hdm_ch->is_initialized) return -EPERM; + tasklet_disable(&dim2_tasklet); spin_lock_irqsave(&dim_lock, flags); hal_ret = dim_destroy_channel(&hdm_ch->ch); hdm_ch->is_initialized = false; if (ch_idx == dev->atx_idx) dev->atx_idx = -1; spin_unlock_irqrestore(&dim_lock, flags); + tasklet_enable(&dim2_tasklet); if (hal_ret != DIM_NO_ERROR) { pr_err("HAL Failed to close channel %s\n", hdm_ch->name); ret = -EFAULT; -- cgit v0.10.2 From 63c87669c4ffbe6fa2687b48a871b054a8267265 Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Mon, 13 Jun 2016 16:24:24 +0200 Subject: staging: most: dim2-hdm: add configuration for fcnt This patch adds possibility to configure the DIM2-IP parameter representing the number of frames per sub-buffer for synchronous channels. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.c b/drivers/staging/most/hdm-dim2/dim2_hal.c index 3c52450..8783dbb 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hal.c +++ b/drivers/staging/most/hdm-dim2/dim2_hal.c @@ -20,18 +20,6 @@ #include <linux/stddef.h> /* - * The number of frames per sub-buffer for synchronous channels. - * Allowed values: 1, 2, 4, 8, 16, 32, 64. - */ -#define FRAMES_PER_SUBBUFF 16 - -/* - * Size factor for synchronous DBR buffer. - * Minimal value is 4*FRAMES_PER_SUBBUFF. - */ -#define SYNC_DBR_FACTOR (4u * (u16)FRAMES_PER_SUBBUFF) - -/* * Size factor for isochronous DBR buffer. * Minimal value is 3. */ @@ -64,9 +52,6 @@ /* -------------------------------------------------------------------------- */ /* generic helper functions and macros */ -#define MLBC0_FCNT_VAL_MACRO(n) MLBC0_FCNT_VAL_ ## n ## FPSB -#define MLBC0_FCNT_VAL(fpsb) MLBC0_FCNT_VAL_MACRO(fpsb) - static inline u32 bit_mask(u8 position) { return (u32)1 << position; @@ -85,6 +70,7 @@ struct lld_global_vars_t { bool dim_is_initialized; bool mcm_is_initialized; struct dim2_regs __iomem *dim2; /* DIM2 core base address */ + u32 fcnt; u32 dbr_map[DBR_MAP_SIZE]; }; @@ -398,7 +384,8 @@ static inline bool check_packet_length(u32 packet_length) static inline bool check_bytes_per_frame(u32 bytes_per_frame) { - u16 const max_size = ((u16)CDT3_BD_MASK + 1u) / SYNC_DBR_FACTOR; + u16 const bd_factor = g.fcnt + 2; + u16 const max_size = ((u16)CDT3_BD_MASK + 1u) >> bd_factor; if (bytes_per_frame <= 0) return false; /* too small */ @@ -439,7 +426,7 @@ static inline u16 norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame) { u16 n; u16 const max_size = (u16)ADT1_ISOC_SYNC_BD_MASK + 1u; - u32 const unit = bytes_per_frame * (u16)FRAMES_PER_SUBBUFF; + u32 const unit = bytes_per_frame << g.fcnt; if (buf_size > max_size) buf_size = max_size; @@ -479,7 +466,7 @@ static void dim2_initialize(bool enable_6pin, u8 mlb_clock) dimcb_io_write(&g.dim2->MLBC0, enable_6pin << MLBC0_MLBPEN_BIT | mlb_clock << MLBC0_MLBCLK_SHIFT | - MLBC0_FCNT_VAL(FRAMES_PER_SUBBUFF) << MLBC0_FCNT_SHIFT | + g.fcnt << MLBC0_FCNT_SHIFT | true << MLBC0_MLBEN_BIT); /* activate all HBI channels */ @@ -650,7 +637,8 @@ static bool channel_detach_buffers(struct dim_channel *ch, u16 buffers_number) /* -------------------------------------------------------------------------- */ /* API */ -u8 dim_startup(struct dim2_regs __iomem *dim_base_address, u32 mlb_clock) +u8 dim_startup(struct dim2_regs __iomem *dim_base_address, u32 mlb_clock, + u32 fcnt) { g.dim_is_initialized = false; @@ -662,7 +650,11 @@ u8 dim_startup(struct dim2_regs __iomem *dim_base_address, u32 mlb_clock) if (mlb_clock >= 8) return DIM_INIT_ERR_MLB_CLOCK; + if (fcnt > MLBC0_FCNT_MAX_VAL) + return DIM_INIT_ERR_MLB_CLOCK; + g.dim2 = dim_base_address; + g.fcnt = fcnt; g.dbr_map[0] = 0; g.dbr_map[1] = 0; @@ -781,6 +773,8 @@ u8 dim_init_isoc(struct dim_channel *ch, u8 is_tx, u16 ch_address, u8 dim_init_sync(struct dim_channel *ch, u8 is_tx, u16 ch_address, u16 bytes_per_frame) { + u16 bd_factor = g.fcnt + 2; + if (!g.dim_is_initialized || !ch) return DIM_ERR_DRIVER_NOT_INITIALIZED; @@ -790,7 +784,7 @@ u8 dim_init_sync(struct dim_channel *ch, u8 is_tx, u16 ch_address, if (!check_bytes_per_frame(bytes_per_frame)) return DIM_ERR_BAD_CONFIG; - ch->dbr_size = bytes_per_frame * SYNC_DBR_FACTOR; + ch->dbr_size = bytes_per_frame << bd_factor; ch->dbr_addr = alloc_dbr(ch->dbr_size); if (ch->dbr_addr >= DBR_SIZE) return DIM_INIT_ERR_OUT_OF_MEMORY; diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.h b/drivers/staging/most/hdm-dim2/dim2_hal.h index 1c924e8..62eb5e7 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hal.h +++ b/drivers/staging/most/hdm-dim2/dim2_hal.h @@ -60,7 +60,8 @@ struct dim_channel { u16 done_sw_buffers_number; /*< Done software buffers number. */ }; -u8 dim_startup(struct dim2_regs __iomem *dim_base_address, u32 mlb_clock); +u8 dim_startup(struct dim2_regs __iomem *dim_base_address, u32 mlb_clock, + u32 fcnt); void dim_shutdown(void); diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c index 89a66bb..87039d9 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hdm.c +++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c @@ -45,6 +45,17 @@ module_param(clock_speed, charp, 0); MODULE_PARM_DESC(clock_speed, "MediaLB Clock Speed"); /* + * The parameter representing the number of frames per sub-buffer for + * synchronous channels. Valid values: [0 .. 6]. + * + * The values 0, 1, 2, 3, 4, 5, 6 represent corresponding number of frames per + * sub-buffer 1, 2, 4, 8, 16, 32, 64. + */ +static u8 fcnt = 4; /* (1 << fcnt) frames per subbuffer */ +module_param(fcnt, byte, 0); +MODULE_PARM_DESC(fcnt, "Num of frames per sub-buffer for sync channels as a power of 2"); + +/* * ############################################################################# * * The define below activates an utility function used by HAL-simu @@ -212,7 +223,8 @@ static int startup_dim(struct platform_device *pdev) return ret; } - hal_ret = dim_startup(dev->io_base, dev->clk_speed); + pr_info("sync: num of frames per sub-buffer: %u\n", fcnt); + hal_ret = dim_startup(dev->io_base, dev->clk_speed, fcnt); if (hal_ret != DIM_NO_ERROR) { pr_err("dim_startup failed: %d\n", hal_ret); if (pdata && pdata->destroy) diff --git a/drivers/staging/most/hdm-dim2/dim2_reg.h b/drivers/staging/most/hdm-dim2/dim2_reg.h index e0837b6..3b1c200 100644 --- a/drivers/staging/most/hdm-dim2/dim2_reg.h +++ b/drivers/staging/most/hdm-dim2/dim2_reg.h @@ -77,13 +77,7 @@ enum { MLBC0_FCNT_SHIFT = 15, MLBC0_FCNT_MASK = 7, - MLBC0_FCNT_VAL_1FPSB = 0, - MLBC0_FCNT_VAL_2FPSB = 1, - MLBC0_FCNT_VAL_4FPSB = 2, - MLBC0_FCNT_VAL_8FPSB = 3, - MLBC0_FCNT_VAL_16FPSB = 4, - MLBC0_FCNT_VAL_32FPSB = 5, - MLBC0_FCNT_VAL_64FPSB = 6, + MLBC0_FCNT_MAX_VAL = 6, MLBC0_MLBEN_BIT = 0, -- cgit v0.10.2 From 1c88f8ff4290fd348de1cf27d403e0fc86474007 Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Mon, 13 Jun 2016 16:24:25 +0200 Subject: staging: most: dim2-hdm: fix possible kernel freeze when reusing a dim2 channel If a DIM2 channel is being closed while it is busy, the channels's status flag could possibly stay active for this very channel. This causes the kernel to freeze by the time the channel is opened again. This patch fixes the problem. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.c b/drivers/staging/most/hdm-dim2/dim2_hal.c index 8783dbb..a0b935c 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hal.c +++ b/drivers/staging/most/hdm-dim2/dim2_hal.c @@ -342,6 +342,9 @@ static void dim2_clear_channel(u8 ch_addr) dim2_clear_cat(MLB_CAT, ch_addr); dim2_clear_cdt(ch_addr); + + /* clear channel status bit */ + dimcb_io_write(&g.dim2->ACSR0, bit_mask(ch_addr)); } /* -------------------------------------------------------------------------- */ -- cgit v0.10.2 From 5a63e23a29cf9a45b9d5a37e20bb157bf48536ae Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Mon, 27 Jun 2016 15:00:32 +0200 Subject: staging: most: core: remove debug print This patch removes the debug print in case an HDM ran out of rx buffers. This is not needed since the status is reflected in the sysfs channel_starving flag. Additionally, it prevents the system form slowing down. Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index 7c619fe..cb4c6de 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -1468,10 +1468,8 @@ static void most_read_completion(struct mbo *mbo) return; } - if (atomic_sub_and_test(1, &c->mbo_nq_level)) { - pr_info("WARN: rx device out of buffers\n"); + if (atomic_sub_and_test(1, &c->mbo_nq_level)) c->is_starving = 1; - } if (c->aim0.refs && c->aim0.ptr->rx_completion && c->aim0.ptr->rx_completion(mbo) == 0) -- cgit v0.10.2 From 99d753463a9a504ec6bb73203b3a2b73baf75996 Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Mon, 27 Jun 2016 15:00:33 +0200 Subject: staging: most: core: rename device struct of core module This patch gives the struct device variable of the core a more meaningful name. Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index cb4c6de..b03cdc9 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -33,7 +33,7 @@ #define STRING_SIZE 80 static struct class *most_class; -static struct device *class_glue_dir; +static struct device *core_dev; static struct ida mdev_id; static int dummy_num_buffers; @@ -1877,22 +1877,19 @@ static int __init most_init(void) goto exit_class; } - class_glue_dir = - device_create(most_class, NULL, 0, NULL, "mostcore"); - if (IS_ERR(class_glue_dir)) { - err = PTR_ERR(class_glue_dir); + core_dev = device_create(most_class, NULL, 0, NULL, "mostcore"); + if (IS_ERR(core_dev)) { + err = PTR_ERR(core_dev); goto exit_driver; } - most_aim_kset = - kset_create_and_add("aims", NULL, &class_glue_dir->kobj); + most_aim_kset = kset_create_and_add("aims", NULL, &core_dev->kobj); if (!most_aim_kset) { err = -ENOMEM; goto exit_class_container; } - most_inst_kset = - kset_create_and_add("devices", NULL, &class_glue_dir->kobj); + most_inst_kset = kset_create_and_add("devices", NULL, &core_dev->kobj); if (!most_inst_kset) { err = -ENOMEM; goto exit_driver_kset; -- cgit v0.10.2 From ec7e0a189b3b3cab6c3dea72017683fccebee3dd Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Mon, 18 Jul 2016 17:25:27 +0200 Subject: staging: most: hdm-usb: reduce context of list_del mutex This patch reduces context of the list_del mutex for the function hdm_enqueue(). Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index 9ec2978..e63784d 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -663,15 +663,11 @@ static int hdm_enqueue(struct most_interface *iface, int channel, init_completion(&anchor->urb_compl); mbo->priv = anchor; - spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags); - list_add_tail(&anchor->list, &mdev->anchor_list[channel]); - spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags); - if ((mdev->padding_active[channel]) && (conf->direction & MOST_CH_TX)) if (hdm_add_padding(mdev, channel, mbo)) { retval = -EIO; - goto _error_1; + goto _error; } urb->transfer_dma = mbo->bus_address; @@ -699,6 +695,10 @@ static int hdm_enqueue(struct most_interface *iface, int channel, } urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags); + list_add_tail(&anchor->list, &mdev->anchor_list[channel]); + spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags); + retval = usb_submit_urb(urb, GFP_KERNEL); if (retval) { dev_err(dev, "URB submit failed with error %d.\n", retval); -- cgit v0.10.2 From ff13cf37fac6961c1c53886eb47753c82cc16963 Mon Sep 17 00:00:00 2001 From: Erik Arfvidson <erik.arfvidson@unisys.com> Date: Fri, 10 Jun 2016 21:47:59 -0400 Subject: staging: unisys: visorbus: remove return values for write_vbus functions This patch removes the return values from the write_vbus_* channel functions. Nobody was checking the return values and the value stored into the vbus info is not critical to the functioning of the device. Signed-off-by: Erik Arfvidson <erik.arfvidson@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Acked-By: Neil Horman <nhorman@tuxdriver.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index d32b898..2ed9628 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -866,9 +866,12 @@ get_vbus_header_info(struct visorchannel *chan, /* Write the contents of <info> to the struct * spar_vbus_channel_protocol.chp_info. + * + * Returns void since this is debug information and not needed for + * device functionality. */ -static int +static void write_vbus_chp_info(struct visorchannel *chan, struct spar_vbus_headerinfo *hdr_info, struct ultra_vbus_deviceinfo *info) @@ -876,18 +879,19 @@ write_vbus_chp_info(struct visorchannel *chan, int off = sizeof(struct channel_header) + hdr_info->chp_info_offset; if (hdr_info->chp_info_offset == 0) - return -EFAULT; + return; - if (visorchannel_write(chan, off, info, sizeof(*info)) < 0) - return -EFAULT; - return 0; + visorchannel_write(chan, off, info, sizeof(*info)); } /* Write the contents of <info> to the struct * spar_vbus_channel_protocol.bus_info. + * + * Returns void since this is debug information and not needed for + * device functionality. */ -static int +static void write_vbus_bus_info(struct visorchannel *chan, struct spar_vbus_headerinfo *hdr_info, struct ultra_vbus_deviceinfo *info) @@ -895,17 +899,18 @@ write_vbus_bus_info(struct visorchannel *chan, int off = sizeof(struct channel_header) + hdr_info->bus_info_offset; if (hdr_info->bus_info_offset == 0) - return -EFAULT; + return; - if (visorchannel_write(chan, off, info, sizeof(*info)) < 0) - return -EFAULT; - return 0; + visorchannel_write(chan, off, info, sizeof(*info)); } /* Write the contents of <info> to the * struct spar_vbus_channel_protocol.dev_info[<devix>]. + * + * Returns void since this is debug information and not needed for + * device functionality. */ -static int +static void write_vbus_dev_info(struct visorchannel *chan, struct spar_vbus_headerinfo *hdr_info, struct ultra_vbus_deviceinfo *info, int devix) @@ -915,11 +920,9 @@ write_vbus_dev_info(struct visorchannel *chan, (hdr_info->device_info_struct_bytes * devix); if (hdr_info->dev_info_offset == 0) - return -EFAULT; + return; - if (visorchannel_write(chan, off, info, sizeof(*info)) < 0) - return -EFAULT; - return 0; + visorchannel_write(chan, off, info, sizeof(*info)); } /* For a child device just created on a client bus, fill in -- cgit v0.10.2 From 80224f064ead5e73d1cf7aacd20a61b5999dfdd6 Mon Sep 17 00:00:00 2001 From: Erik Arfvidson <erik.arfvidson@unisys.com> Date: Fri, 10 Jun 2016 21:48:00 -0400 Subject: staging: unisys: visorbus: check parahotplug_request_complete_result This patch modifies the caller of parahotplug_request_complete() to check the return value and return appropriate result. Signed-off-by: Erik Arfvidson <erik.arfvidson@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Acked-By: Neil Horman <nhorman@tuxdriver.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index d248c94..7f44913 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -2036,11 +2036,14 @@ static ssize_t devicedisabled_store(struct device *dev, const char *buf, size_t count) { unsigned int id; + int err; if (kstrtouint(buf, 10, &id)) return -EINVAL; - parahotplug_request_complete(id, 0); + err = parahotplug_request_complete(id, 0); + if (err < 0) + return err; return count; } -- cgit v0.10.2 From f4211d1a6b3c77dced986aea4eb0023f1d6dc6c1 Mon Sep 17 00:00:00 2001 From: David Binder <david.binder@unisys.com> Date: Fri, 10 Jun 2016 21:48:01 -0400 Subject: staging: unisys: visorbus: remove unused module parameters Removes unused module parameters from visorbus_main.c, in response to findings by SonarQube. Signed-off-by: David Binder <david.binder@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Acked-By: Neil Horman <nhorman@tuxdriver.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 2ed9628..71bff07 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -27,10 +27,9 @@ #define MYDRVNAME "visorbus" /* module parameters */ -static int visorbus_debug; static int visorbus_forcematch; static int visorbus_forcenomatch; -static int visorbus_debugref; + #define SERIALLOOPBACKCHANADDR (100 * 1024 * 1024) /* Display string that is guaranteed to be no longer the 99 characters*/ @@ -1332,9 +1331,6 @@ visorbus_exit(void) remove_bus_type(); } -module_param_named(debug, visorbus_debug, int, S_IRUGO); -MODULE_PARM_DESC(visorbus_debug, "1 to debug"); - module_param_named(forcematch, visorbus_forcematch, int, S_IRUGO); MODULE_PARM_DESC(visorbus_forcematch, "1 to force a successful dev <--> drv match"); @@ -1342,6 +1338,3 @@ MODULE_PARM_DESC(visorbus_forcematch, module_param_named(forcenomatch, visorbus_forcenomatch, int, S_IRUGO); MODULE_PARM_DESC(visorbus_forcenomatch, "1 to force an UNsuccessful dev <--> drv match"); - -module_param_named(debugref, visorbus_debugref, int, S_IRUGO); -MODULE_PARM_DESC(visorbus_debugref, "1 to debug reference counting"); -- cgit v0.10.2 From cc9b8ed99e4b6e48ae9b28b295ce08fe18bc949c Mon Sep 17 00:00:00 2001 From: David Binder <david.binder@unisys.com> Date: Fri, 10 Jun 2016 21:48:02 -0400 Subject: staging: unisys: visorbus: remove unused struct Removes unused struct definition, channel_size_info, in response to findings by SonarQube. Signed-off-by: David Binder <david.binder@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Acked-By: Neil Horman <nhorman@tuxdriver.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 71bff07..08d560c 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -1260,12 +1260,6 @@ chipset_device_resume(struct visor_device *dev_info) initiate_chipset_device_pause_resume(dev_info, false); } -struct channel_size_info { - uuid_le guid; - unsigned long min_size; - unsigned long max_size; -}; - int visorbus_init(void) { -- cgit v0.10.2 From 7f71e48cad66f178e3ad5ad135d9c68d9a2a4c6a Mon Sep 17 00:00:00 2001 From: David Binder <david.binder@unisys.com> Date: Fri, 10 Jun 2016 21:48:03 -0400 Subject: staging: unisys: visorbus: modify format string to match argument Modifies the format string of snprintf to expect an unsigned int instead of a signed one, per the supplied argument. Signed-off-by: David Binder <david.binder@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Acked-By: Neil Horman <nhorman@tuxdriver.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 08d560c..756df41 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -433,7 +433,7 @@ static ssize_t client_bus_info_show(struct device *dev, if (vdev->name) partition_name = vdev->name; shift = snprintf(pos, remain, - "Client device / client driver info for %s eartition (vbus #%d):\n", + "Client device / client driver info for %s eartition (vbus #%u):\n", partition_name, vdev->chipset_dev_no); pos += shift; remain -= shift; -- cgit v0.10.2 From ab30126587086a95e6e94ea1c2a720c3344d226c Mon Sep 17 00:00:00 2001 From: David Binder <david.binder@unisys.com> Date: Fri, 10 Jun 2016 21:48:04 -0400 Subject: staging: unisys: visornic: Correct comment spelling mistake Fixes a comment spelling mistake in visornic. Signed-off-by: David Binder <david.binder@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Acked-By: Neil Horman <nhorman@tuxdriver.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index a28388d..4fbe703 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -1586,7 +1586,7 @@ drain_resp_queue(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata) * * Drain the respones queue of any responses from the IO partition. * Process the responses as we get them. - * Returns when response queue is empty or when the threadd stops. + * Returns when response queue is empty or when the thread stops. */ static void service_resp_queue(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata, -- cgit v0.10.2 From e54d0a3023c51867ad3d2bc0d57c47b569e14b7f Mon Sep 17 00:00:00 2001 From: David Binder <david.binder@unisys.com> Date: Fri, 10 Jun 2016 21:48:05 -0400 Subject: staging: unisys: include: Remove thread-related enum members Code relating to ktheads was previously removed from s-Par driver code. This patch cleans up lingering remnants of kthreads by removing thread- related enum types. Signed-off-by: David Binder <david.binder@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Acked-By: Neil Horman <nhorman@tuxdriver.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/include/guestlinuxdebug.h b/drivers/staging/unisys/include/guestlinuxdebug.h index b81287f..5af3f77 100644 --- a/drivers/staging/unisys/include/guestlinuxdebug.h +++ b/drivers/staging/unisys/include/guestlinuxdebug.h @@ -56,7 +56,7 @@ enum driver_pc { /* POSTCODE driver identifier tuples */ UISLIB_PC = 0xD0, UISLIB_PC_uislib_c = 0xD1, UISLIB_PC_uisqueue_c = 0xD2, - UISLIB_PC_uisthread_c = 0xD3, + /* 0xD3 RESERVED */ UISLIB_PC_uisutils_c = 0xD4, }; @@ -91,7 +91,7 @@ enum event_pc { /* POSTCODE event identifier tuples */ DRIVER_EXIT_PC = 0x0AC, MALLOC_FAILURE_PC = 0x0AD, QUEUE_DELAYED_WORK_PC = 0x0AE, - UISLIB_THREAD_FAILURE_PC = 0x0B7, + /* 0x0B7 RESERVED */ VBUS_CHANNEL_ENTRY_PC = 0x0B8, VBUS_CHANNEL_FAILURE_PC = 0x0B9, VBUS_CHANNEL_EXIT_PC = 0x0BA, -- cgit v0.10.2 From c3d4a970333fcece2376c865572e2f835f8f3f4d Mon Sep 17 00:00:00 2001 From: Tim Sell <Timothy.Sell@unisys.com> Date: Fri, 10 Jun 2016 21:48:06 -0400 Subject: staging: unisys: visorbus: removed unused periodic_test_workqueue periodic_test_workqueue was an unused relic from the past, and was removed. Signed-off-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Acked-By: Neil Horman <nhorman@tuxdriver.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 756df41..ebdd5de 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -116,14 +116,6 @@ struct bus_type visorbus_type = { .bus_groups = visorbus_bus_groups, }; -static struct delayed_work periodic_work; - -/* YES, we need 2 workqueues. - * The reason is, workitems on the test queue may need to cancel - * workitems on the other queue. You will be in for trouble if you try to - * do this with workitems queued on the same workqueue. - */ -static struct workqueue_struct *periodic_test_workqueue; static struct workqueue_struct *periodic_dev_workqueue; static long long bus_count; /** number of bus instances */ /** ever-increasing */ @@ -1309,13 +1301,6 @@ visorbus_exit(void) destroy_workqueue(periodic_dev_workqueue); periodic_dev_workqueue = NULL; - if (periodic_test_workqueue) { - cancel_delayed_work(&periodic_work); - flush_workqueue(periodic_test_workqueue); - destroy_workqueue(periodic_test_workqueue); - periodic_test_workqueue = NULL; - } - list_for_each_safe(listentry, listtmp, &list_all_bus_instances) { struct visor_device *dev = list_entry(listentry, struct visor_device, -- cgit v0.10.2 From 83011b6cbe7c597c73b31c41021dc71f78dcef7b Mon Sep 17 00:00:00 2001 From: Tim Sell <Timothy.Sell@unisys.com> Date: Fri, 10 Jun 2016 21:48:07 -0400 Subject: staging: unisys: visorinput: remove unnecessary locking Locking in the _interrupt() function is NOT necessary so long as we ensure that interrupts have been stopped whenever we need to pause or resume the device, which we now do. While a device is paused, we ensure that interrupts stay disabled, i.e. that the _interrupt() function will NOT be called, yet remember the desired state in devdata->interrupts_enabled if open() or close() are called are called while the device is paused. Then when the device is resumed, we restore the actual state of interrupts (i.e., whether _interrupt() is going to be called or not) to the desired state in devdata->interrupts_enabled. Signed-off-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Acked-By: Neil Horman <nhorman@tuxdriver.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorinput/visorinput.c b/drivers/staging/unisys/visorinput/visorinput.c index d67cd763..f633985 100644 --- a/drivers/staging/unisys/visorinput/visorinput.c +++ b/drivers/staging/unisys/visorinput/visorinput.c @@ -66,6 +66,7 @@ struct visorinput_devdata { struct rw_semaphore lock_visor_dev; /* lock for dev */ struct input_dev *visorinput_dev; bool paused; + bool interrupts_enabled; unsigned int keycode_table_bytes; /* size of following array */ /* for keyboard devices: visorkbd_keycode[] + visorkbd_ext_keycode[] */ unsigned char keycode_table[0]; @@ -228,7 +229,21 @@ static int visorinput_open(struct input_dev *visorinput_dev) return -EINVAL; } dev_dbg(&visorinput_dev->dev, "%s opened\n", __func__); + + /* + * If we're not paused, really enable interrupts. + * Regardless of whether we are paused, set a flag indicating + * interrupts should be enabled so when we resume, interrupts + * will really be enabled. + */ + down_write(&devdata->lock_visor_dev); + devdata->interrupts_enabled = true; + if (devdata->paused) + goto out_unlock; visorbus_enable_channel_interrupts(devdata->dev); + +out_unlock: + up_write(&devdata->lock_visor_dev); return 0; } @@ -243,7 +258,22 @@ static void visorinput_close(struct input_dev *visorinput_dev) return; } dev_dbg(&visorinput_dev->dev, "%s closed\n", __func__); + + /* + * If we're not paused, really disable interrupts. + * Regardless of whether we are paused, set a flag indicating + * interrupts should be disabled so when we resume we will + * not re-enable them. + */ + + down_write(&devdata->lock_visor_dev); + devdata->interrupts_enabled = false; + if (devdata->paused) + goto out_unlock; visorbus_disable_channel_interrupts(devdata->dev); + +out_unlock: + up_write(&devdata->lock_visor_dev); } /* @@ -438,10 +468,8 @@ visorinput_remove(struct visor_device *dev) * in visorinput_channel_interrupt() */ - down_write(&devdata->lock_visor_dev); dev_set_drvdata(&dev->device, NULL); unregister_client_input(devdata->visorinput_dev); - up_write(&devdata->lock_visor_dev); kfree(devdata); } @@ -529,13 +557,7 @@ visorinput_channel_interrupt(struct visor_device *dev) if (!devdata) return; - down_write(&devdata->lock_visor_dev); - if (devdata->paused) /* don't touch device/channel when paused */ - goto out_locked; - visorinput_dev = devdata->visorinput_dev; - if (!visorinput_dev) - goto out_locked; while (visorchannel_signalremove(dev->visorchannel, 0, &r)) { scancode = r.activity.arg1; @@ -611,8 +633,6 @@ visorinput_channel_interrupt(struct visor_device *dev) break; } } -out_locked: - up_write(&devdata->lock_visor_dev); } static int @@ -632,6 +652,14 @@ visorinput_pause(struct visor_device *dev, rc = -EBUSY; goto out_locked; } + if (devdata->interrupts_enabled) + visorbus_disable_channel_interrupts(dev); + + /* + * due to above, at this time no thread of execution will be + * in visorinput_channel_interrupt() + */ + devdata->paused = true; complete_func(dev, 0); rc = 0; @@ -659,6 +687,15 @@ visorinput_resume(struct visor_device *dev, } devdata->paused = false; complete_func(dev, 0); + + /* + * Re-establish calls to visorinput_channel_interrupt() if that is + * the desired state that we've kept track of in interrupts_enabled + * while the device was paused. + */ + if (devdata->interrupts_enabled) + visorbus_enable_channel_interrupts(dev); + rc = 0; out_locked: up_write(&devdata->lock_visor_dev); -- cgit v0.10.2 From 9ebab64952237f7b9b263d6dc0cdf31e83a2d5e7 Mon Sep 17 00:00:00 2001 From: Tim Sell <Timothy.Sell@unisys.com> Date: Fri, 10 Jun 2016 21:48:08 -0400 Subject: staging: unisys: visorbus: use kernel timer instead of workqueue A kernel timer is now used as the vehicle to periodically call the channel_interrupt function of registered visor drivers, instead of a workqueue. This simplifies a lot of things by making periodic_work.c and periodic_work.h no longer necessary. This change also means that the channel_interrupt() callbacks registered by visor drivers (via visorbus_register_visor_driver()) will now be called in atomic context (i.e., canNOT sleep) rather than kernel thread context (CAN sleep). Fortunately this did NOT necessitate any change to the existing channel_interrupt() callbacks, because none of them ever perform any operations that would be invalid in atomic context. Signed-off-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Acked-By: Neil Horman <nhorman@tuxdriver.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/include/visorbus.h b/drivers/staging/unisys/include/visorbus.h index 9baf1ec..9bb88bb 100644 --- a/drivers/staging/unisys/include/visorbus.h +++ b/drivers/staging/unisys/include/visorbus.h @@ -34,8 +34,9 @@ #include <linux/poll.h> #include <linux/kernel.h> #include <linux/uuid.h> +#include <linux/seq_file.h> +#include <linux/slab.h> -#include "periodic_work.h" #include "channel.h" struct visor_driver; @@ -126,8 +127,8 @@ struct visor_driver { * device: Device struct meant for use by the bus driver * only. * list_all: Used by the bus driver to enumerate devices. - * periodic_work: Device work queue. Private use by bus driver - * only. + * timer: Timer fired periodically to do interrupt-type + * activity. * being_removed: Indicates that the device is being removed from * the bus. Private bus driver use only. * visordriver_callback_lock: Used by the bus driver to lock when handling @@ -157,7 +158,8 @@ struct visor_device { /* These fields are for private use by the bus driver only. */ struct device device; struct list_head list_all; - struct periodic_work *periodic_work; + struct timer_list timer; + bool timer_active; bool being_removed; struct semaphore visordriver_callback_lock; bool pausing; diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index ebdd5de..e98e720 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -19,7 +19,6 @@ #include "visorbus.h" #include "visorbus_private.h" #include "version.h" -#include "periodic_work.h" #include "vbuschannel.h" #include "guestlinuxdebug.h" #include "vmcallinterface.h" @@ -116,7 +115,6 @@ struct bus_type visorbus_type = { .bus_groups = visorbus_bus_groups, }; -static struct workqueue_struct *periodic_dev_workqueue; static long long bus_count; /** number of bus instances */ /** ever-increasing */ @@ -222,10 +220,6 @@ visorbus_release_device(struct device *xdev) { struct visor_device *dev = to_visor_device(xdev); - if (dev->periodic_work) { - visor_periodic_work_destroy(dev->periodic_work); - dev->periodic_work = NULL; - } if (dev->visorchannel) { visorchannel_destroy(dev->visorchannel); dev->visorchannel = NULL; @@ -530,35 +524,36 @@ unregister_driver_attributes(struct visor_driver *drv) } static void -dev_periodic_work(void *xdev) +dev_periodic_work(unsigned long __opaque) { - struct visor_device *dev = xdev; + struct visor_device *dev = (struct visor_device *)__opaque; struct visor_driver *drv = to_visor_driver(dev->device.driver); - down(&dev->visordriver_callback_lock); if (drv->channel_interrupt) drv->channel_interrupt(dev); - up(&dev->visordriver_callback_lock); - if (!visor_periodic_work_nextperiod(dev->periodic_work)) - put_device(&dev->device); + mod_timer(&dev->timer, jiffies + POLLJIFFIES_NORMALCHANNEL); } static void dev_start_periodic_work(struct visor_device *dev) { - if (dev->being_removed) + if (dev->being_removed || dev->timer_active) return; /* now up by at least 2 */ get_device(&dev->device); - if (!visor_periodic_work_start(dev->periodic_work)) - put_device(&dev->device); + dev->timer.expires = jiffies + POLLJIFFIES_NORMALCHANNEL; + add_timer(&dev->timer); + dev->timer_active = true; } static void dev_stop_periodic_work(struct visor_device *dev) { - if (visor_periodic_work_stop(dev->periodic_work)) - put_device(&dev->device); + if (!dev->timer_active) + return; + del_timer_sync(&dev->timer); + dev->timer_active = false; + put_device(&dev->device); } /** This is called automatically upon adding a visor_device (device_add), or @@ -776,17 +771,9 @@ create_visor_device(struct visor_device *dev) dev->device.release = visorbus_release_device; /* keep a reference just for us (now 2) */ get_device(&dev->device); - dev->periodic_work = - visor_periodic_work_create(POLLJIFFIES_NORMALCHANNEL, - periodic_dev_workqueue, - dev_periodic_work, - dev, dev_name(&dev->device)); - if (!dev->periodic_work) { - POSTCODE_LINUX_3(DEVICE_CREATE_FAILURE_PC, chipset_dev_no, - DIAG_SEVERITY_ERR); - err = -EINVAL; - goto err_put; - } + init_timer(&dev->timer); + dev->timer.data = (unsigned long)(dev); + dev->timer.function = dev_periodic_work; /* bus_id must be a unique name with respect to this bus TYPE * (NOT bus instance). That's why we need to include the bus @@ -1268,13 +1255,6 @@ visorbus_init(void) goto error; } - periodic_dev_workqueue = create_singlethread_workqueue("visorbus_dev"); - if (!periodic_dev_workqueue) { - POSTCODE_LINUX_2(CREATE_WORKQUEUE_PC, DIAG_SEVERITY_ERR); - err = -ENOMEM; - goto error; - } - /* This enables us to receive notifications when devices appear for * which this service partition is to be a server for. */ @@ -1297,10 +1277,6 @@ visorbus_exit(void) visorchipset_register_busdev(NULL, NULL, NULL); remove_all_visor_devices(); - flush_workqueue(periodic_dev_workqueue); /* better not be any work! */ - destroy_workqueue(periodic_dev_workqueue); - periodic_dev_workqueue = NULL; - list_for_each_safe(listentry, listtmp, &list_all_bus_instances) { struct visor_device *dev = list_entry(listentry, struct visor_device, -- cgit v0.10.2 From 8a64f954a858558482464115885c68b0e4e4d479 Mon Sep 17 00:00:00 2001 From: Tim Sell <Timothy.Sell@unisys.com> Date: Fri, 10 Jun 2016 21:48:09 -0400 Subject: staging: unisys: visorbus: remove periodic_work.h/.c These files were made no-longer-necessary by recent commits. Signed-off-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Acked-By: Neil Horman <nhorman@tuxdriver.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/include/periodic_work.h b/drivers/staging/unisys/include/periodic_work.h deleted file mode 100644 index 0b3335a..0000000 --- a/drivers/staging/unisys/include/periodic_work.h +++ /dev/null @@ -1,40 +0,0 @@ -/* periodic_work.h - * - * Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#ifndef __PERIODIC_WORK_H__ -#define __PERIODIC_WORK_H__ - -#include <linux/seq_file.h> -#include <linux/slab.h> - -/* PERIODIC_WORK an opaque structure to users. - * Fields are declared only in the implementation .c files. - */ -struct periodic_work; - -struct periodic_work * -visor_periodic_work_create(ulong jiffy_interval, - struct workqueue_struct *workqueue, - void (*workfunc)(void *), - void *workfuncarg, - const char *devnam); -void visor_periodic_work_destroy(struct periodic_work *pw); -bool visor_periodic_work_nextperiod(struct periodic_work *pw); -bool visor_periodic_work_start(struct periodic_work *pw); -bool visor_periodic_work_stop(struct periodic_work *pw); - -#endif diff --git a/drivers/staging/unisys/visorbus/Makefile b/drivers/staging/unisys/visorbus/Makefile index fc790e7..f3730d8 100644 --- a/drivers/staging/unisys/visorbus/Makefile +++ b/drivers/staging/unisys/visorbus/Makefile @@ -7,6 +7,5 @@ obj-$(CONFIG_UNISYS_VISORBUS) += visorbus.o visorbus-y := visorbus_main.o visorbus-y += visorchannel.o visorbus-y += visorchipset.o -visorbus-y += periodic_work.o ccflags-y += -Idrivers/staging/unisys/include diff --git a/drivers/staging/unisys/visorbus/periodic_work.c b/drivers/staging/unisys/visorbus/periodic_work.c deleted file mode 100644 index 00b1527..0000000 --- a/drivers/staging/unisys/visorbus/periodic_work.c +++ /dev/null @@ -1,204 +0,0 @@ -/* periodic_work.c - * - * Copyright (C) 2010 - 2015 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -/* - * Helper functions to schedule periodic work in Linux kernel mode. - */ -#include <linux/sched.h> - -#include "periodic_work.h" - -#define MYDRVNAME "periodic_work" - -struct periodic_work { - rwlock_t lock; - struct delayed_work work; - void (*workfunc)(void *); - void *workfuncarg; - bool is_scheduled; - bool want_to_stop; - ulong jiffy_interval; - struct workqueue_struct *workqueue; - const char *devnam; -}; - -static void periodic_work_func(struct work_struct *work) -{ - struct periodic_work *pw; - - pw = container_of(work, struct periodic_work, work.work); - (*pw->workfunc)(pw->workfuncarg); -} - -struct periodic_work -*visor_periodic_work_create(ulong jiffy_interval, - struct workqueue_struct *workqueue, - void (*workfunc)(void *), - void *workfuncarg, - const char *devnam) -{ - struct periodic_work *pw; - - pw = kzalloc(sizeof(*pw), GFP_KERNEL | __GFP_NORETRY); - if (!pw) - return NULL; - - rwlock_init(&pw->lock); - pw->jiffy_interval = jiffy_interval; - pw->workqueue = workqueue; - pw->workfunc = workfunc; - pw->workfuncarg = workfuncarg; - pw->devnam = devnam; - return pw; -} -EXPORT_SYMBOL_GPL(visor_periodic_work_create); - -void visor_periodic_work_destroy(struct periodic_work *pw) -{ - kfree(pw); -} -EXPORT_SYMBOL_GPL(visor_periodic_work_destroy); - -/** Call this from your periodic work worker function to schedule the next - * call. - * If this function returns false, there was a failure and the - * periodic work is no longer scheduled - */ -bool visor_periodic_work_nextperiod(struct periodic_work *pw) -{ - bool rc = false; - - write_lock(&pw->lock); - if (pw->want_to_stop) { - pw->is_scheduled = false; - pw->want_to_stop = false; - rc = true; /* yes, true; see visor_periodic_work_stop() */ - goto unlock; - } else if (!queue_delayed_work(pw->workqueue, &pw->work, - pw->jiffy_interval)) { - pw->is_scheduled = false; - rc = false; - goto unlock; - } - rc = true; -unlock: - write_unlock(&pw->lock); - return rc; -} -EXPORT_SYMBOL_GPL(visor_periodic_work_nextperiod); - -/** This function returns true iff new periodic work was actually started. - * If this function returns false, then no work was started - * (either because it was already started, or because of a failure). - */ -bool visor_periodic_work_start(struct periodic_work *pw) -{ - bool rc = false; - - write_lock(&pw->lock); - if (pw->is_scheduled) { - rc = false; - goto unlock; - } - if (pw->want_to_stop) { - rc = false; - goto unlock; - } - INIT_DELAYED_WORK(&pw->work, &periodic_work_func); - if (!queue_delayed_work(pw->workqueue, &pw->work, - pw->jiffy_interval)) { - rc = false; - goto unlock; - } - pw->is_scheduled = true; - rc = true; -unlock: - write_unlock(&pw->lock); - return rc; -} -EXPORT_SYMBOL_GPL(visor_periodic_work_start); - -/** This function returns true iff your call actually stopped the periodic - * work. - * - * -- PAY ATTENTION... this is important -- - * - * NO NO #1 - * - * Do NOT call this function from some function that is running on the - * same workqueue as the work you are trying to stop might be running - * on! If you violate this rule, visor_periodic_work_stop() MIGHT work, - * but it also MIGHT get hung up in an infinite loop saying - * "waiting for delayed work...". This will happen if the delayed work - * you are trying to cancel has been put in the workqueue list, but can't - * run yet because we are running that same workqueue thread right now. - * - * Bottom line: If you need to call visor_periodic_work_stop() from a - * workitem, be sure the workitem is on a DIFFERENT workqueue than the - * workitem that you are trying to cancel. - * - * If I could figure out some way to check for this "no no" condition in - * the code, I would. It would have saved me the trouble of writing this - * long comment. And also, don't think this is some "theoretical" race - * condition. It is REAL, as I have spent the day chasing it. - * - * NO NO #2 - * - * Take close note of the locks that you own when you call this function. - * You must NOT own any locks that are needed by the periodic work - * function that is currently installed. If you DO, a deadlock may result, - * because stopping the periodic work often involves waiting for the last - * iteration of the periodic work function to complete. Again, if you hit - * this deadlock, you will get hung up in an infinite loop saying - * "waiting for delayed work...". - */ -bool visor_periodic_work_stop(struct periodic_work *pw) -{ - bool stopped_something = false; - - write_lock(&pw->lock); - stopped_something = pw->is_scheduled && (!pw->want_to_stop); - while (pw->is_scheduled) { - pw->want_to_stop = true; - if (cancel_delayed_work(&pw->work)) { - /* We get here if the delayed work was pending as - * delayed work, but was NOT run. - */ - WARN_ON(!pw->is_scheduled); - pw->is_scheduled = false; - } else { - /* If we get here, either the delayed work: - * - was run, OR, - * - is running RIGHT NOW on another processor, OR, - * - wasn't even scheduled (there is a miniscule - * timing window where this could be the case) - * flush_workqueue() would make sure it is finished - * executing, but that still isn't very useful, which - * explains the loop... - */ - } - if (pw->is_scheduled) { - write_unlock(&pw->lock); - schedule_timeout_interruptible(msecs_to_jiffies(10)); - write_lock(&pw->lock); - } else { - pw->want_to_stop = false; - } - } - write_unlock(&pw->lock); - return stopped_something; -} -EXPORT_SYMBOL_GPL(visor_periodic_work_stop); diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 7f44913..b668b80 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -29,7 +29,6 @@ #include "controlvmchannel.h" #include "controlvmcompletionstatus.h" #include "guestlinuxdebug.h" -#include "periodic_work.h" #include "version.h" #include "visorbus.h" #include "visorbus_private.h" -- cgit v0.10.2 From d505855e5f2022abc75d1a54bafeb80f25a955a7 Mon Sep 17 00:00:00 2001 From: Bryan Thompson <bryan.thompson@unisys.com> Date: Fri, 10 Jun 2016 21:48:10 -0400 Subject: staging: unisys: visorbus: Make visordriver_callback_lock a mutex visordriver_callback_lock is just a binary semaphore that logically makes more sense as a mutex. Signed-off-by: Bryan Thompson <bryan.thompson@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Acked-By: Neil Horman <nhorman@tuxdriver.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/include/visorbus.h b/drivers/staging/unisys/include/visorbus.h index 9bb88bb..3ba01cf 100644 --- a/drivers/staging/unisys/include/visorbus.h +++ b/drivers/staging/unisys/include/visorbus.h @@ -161,7 +161,7 @@ struct visor_device { struct timer_list timer; bool timer_active; bool being_removed; - struct semaphore visordriver_callback_lock; + struct mutex visordriver_callback_lock; bool pausing; bool resuming; u32 chipset_bus_no; diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index e98e720..2e0eb03 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -574,7 +574,7 @@ visordriver_probe_device(struct device *xdev) if (!drv->probe) return -ENODEV; - down(&dev->visordriver_callback_lock); + mutex_lock(&dev->visordriver_callback_lock); dev->being_removed = false; res = drv->probe(dev); @@ -584,7 +584,7 @@ visordriver_probe_device(struct device *xdev) fix_vbus_dev_info(dev); } - up(&dev->visordriver_callback_lock); + mutex_unlock(&dev->visordriver_callback_lock); return res; } @@ -600,11 +600,11 @@ visordriver_remove_device(struct device *xdev) dev = to_visor_device(xdev); drv = to_visor_driver(xdev->driver); - down(&dev->visordriver_callback_lock); + mutex_lock(&dev->visordriver_callback_lock); dev->being_removed = true; if (drv->remove) drv->remove(dev); - up(&dev->visordriver_callback_lock); + mutex_unlock(&dev->visordriver_callback_lock); dev_stop_periodic_work(dev); put_device(&dev->device); @@ -764,7 +764,7 @@ create_visor_device(struct visor_device *dev) POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, chipset_dev_no, chipset_bus_no, POSTCODE_SEVERITY_INFO); - sema_init(&dev->visordriver_callback_lock, 1); /* unlocked */ + mutex_init(&dev->visordriver_callback_lock); dev->device.bus = &visorbus_type; dev->device.groups = visorbus_channel_groups; device_initialize(&dev->device); -- cgit v0.10.2 From fe129f62164c3e8216d9a79741c86f2f9b72e475 Mon Sep 17 00:00:00 2001 From: Bryan Thompson <bryan.thompson@unisys.com> Date: Fri, 10 Jun 2016 21:48:11 -0400 Subject: staging: unisys: visorbus: Remove unnecessary EXPORT_SYMBOL statements The driver that is now visorbus started out as multiple separate drivers, and when they were merged the EXPORT_SYMBOL statements that were required for separate drivers were left in the code. This patch removes those now unnecessary exports. Signed-off-by: Bryan Thompson <bryan.thompson@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Acked-By: Neil Horman <nhorman@tuxdriver.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 2e0eb03..f7f5986 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -721,7 +721,6 @@ visorbus_clear_channel(struct visor_device *dev, unsigned long offset, u8 ch, { return visorchannel_clear(dev->visorchannel, offset, ch, nbytes); } -EXPORT_SYMBOL_GPL(visorbus_clear_channel); /** We don't really have a real interrupt, so for now we just call the * interrupt function periodically... diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c index 4337358..1f626c3 100644 --- a/drivers/staging/unisys/visorbus/visorchannel.c +++ b/drivers/staging/unisys/visorbus/visorchannel.c @@ -148,7 +148,6 @@ visorchannel_create(u64 physaddr, unsigned long channel_bytes, return visorchannel_create_guts(physaddr, channel_bytes, gfp, 0, guid, false); } -EXPORT_SYMBOL_GPL(visorchannel_create); struct visorchannel * visorchannel_create_with_lock(u64 physaddr, unsigned long channel_bytes, @@ -157,7 +156,6 @@ visorchannel_create_with_lock(u64 physaddr, unsigned long channel_bytes, return visorchannel_create_guts(physaddr, channel_bytes, gfp, 0, guid, true); } -EXPORT_SYMBOL_GPL(visorchannel_create_with_lock); void visorchannel_destroy(struct visorchannel *channel) @@ -171,21 +169,18 @@ visorchannel_destroy(struct visorchannel *channel) } kfree(channel); } -EXPORT_SYMBOL_GPL(visorchannel_destroy); u64 visorchannel_get_physaddr(struct visorchannel *channel) { return channel->physaddr; } -EXPORT_SYMBOL_GPL(visorchannel_get_physaddr); ulong visorchannel_get_nbytes(struct visorchannel *channel) { return channel->nbytes; } -EXPORT_SYMBOL_GPL(visorchannel_get_nbytes); char * visorchannel_uuid_id(uuid_le *guid, char *s) @@ -193,28 +188,24 @@ visorchannel_uuid_id(uuid_le *guid, char *s) sprintf(s, "%pUL", guid); return s; } -EXPORT_SYMBOL_GPL(visorchannel_uuid_id); char * visorchannel_id(struct visorchannel *channel, char *s) { return visorchannel_uuid_id(&channel->guid, s); } -EXPORT_SYMBOL_GPL(visorchannel_id); char * visorchannel_zoneid(struct visorchannel *channel, char *s) { return visorchannel_uuid_id(&channel->chan_hdr.zone_uuid, s); } -EXPORT_SYMBOL_GPL(visorchannel_zoneid); u64 visorchannel_get_clientpartition(struct visorchannel *channel) { return channel->chan_hdr.partition_handle; } -EXPORT_SYMBOL_GPL(visorchannel_get_clientpartition); int visorchannel_set_clientpartition(struct visorchannel *channel, @@ -223,7 +214,6 @@ visorchannel_set_clientpartition(struct visorchannel *channel, channel->chan_hdr.partition_handle = partition_handle; return 0; } -EXPORT_SYMBOL_GPL(visorchannel_set_clientpartition); uuid_le visorchannel_get_uuid(struct visorchannel *channel) @@ -243,7 +233,6 @@ visorchannel_read(struct visorchannel *channel, ulong offset, return 0; } -EXPORT_SYMBOL_GPL(visorchannel_read); int visorchannel_write(struct visorchannel *channel, ulong offset, @@ -265,7 +254,6 @@ visorchannel_write(struct visorchannel *channel, ulong offset, return 0; } -EXPORT_SYMBOL_GPL(visorchannel_write); int visorchannel_clear(struct visorchannel *channel, ulong offset, u8 ch, @@ -301,14 +289,12 @@ out_free_page: free_page((unsigned long)buf); return err; } -EXPORT_SYMBOL_GPL(visorchannel_clear); void __iomem * visorchannel_get_header(struct visorchannel *channel) { return (void __iomem *)&channel->chan_hdr; } -EXPORT_SYMBOL_GPL(visorchannel_get_header); /** Return offset of a specific SIGNAL_QUEUE_HEADER from the beginning of a * channel header @@ -522,7 +508,6 @@ visorchannel_signalqueue_slots_avail(struct visorchannel *channel, u32 queue) slots_avail = sig_hdr.max_signals - slots_used; return (int)slots_avail; } -EXPORT_SYMBOL_GPL(visorchannel_signalqueue_slots_avail); int visorchannel_signalqueue_max_slots(struct visorchannel *channel, u32 queue) @@ -533,7 +518,6 @@ visorchannel_signalqueue_max_slots(struct visorchannel *channel, u32 queue) return 0; return (int)sig_hdr.max_signals; } -EXPORT_SYMBOL_GPL(visorchannel_signalqueue_max_slots); static void sigqueue_debug(struct signal_queue_header *q, int which, struct seq_file *seq) @@ -632,4 +616,3 @@ visorchannel_debug(struct visorchannel *channel, int num_queues, seq_printf(seq, "--- End channel @0x%-16.16Lx for 0x%lx bytes ---\n", addr + off, nbytes); } -EXPORT_SYMBOL_GPL(visorchannel_debug); diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index b668b80..b5942c6 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -682,7 +682,6 @@ struct visor_device *visorbus_get_device_by_id(u32 bus_no, u32 dev_no, vdev = to_visor_device(dev); return vdev; } -EXPORT_SYMBOL(visorbus_get_device_by_id); void visorchipset_register_busdev( @@ -707,7 +706,6 @@ visorchipset_register_busdev( up(¬ifier_lock); } -EXPORT_SYMBOL_GPL(visorchipset_register_busdev); static void chipset_init(struct controlvm_message *inmsg) -- cgit v0.10.2 From 33f3a3cfac19c49e0f17d099bf7b3381681fa66a Mon Sep 17 00:00:00 2001 From: Bryan Thompson <bryan.thompson@unisys.com> Date: Fri, 10 Jun 2016 21:48:12 -0400 Subject: staging: unisys: visorbus: Remove unused functions Remove visorbus_clear_channel, visorchannel_signalqueue_slots_avail, visorchannel_signalqueue_max_slots, visorchannel_clear, and visorchannel_debug which are no longer called by any driver. Signed-off-by: Bryan Thompson <bryan.thompson@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Acked-By: Neil Horman <nhorman@tuxdriver.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/include/visorbus.h b/drivers/staging/unisys/include/visorbus.h index 3ba01cf..cbe240a 100644 --- a/drivers/staging/unisys/include/visorbus.h +++ b/drivers/staging/unisys/include/visorbus.h @@ -185,8 +185,6 @@ int visorbus_read_channel(struct visor_device *dev, int visorbus_write_channel(struct visor_device *dev, unsigned long offset, void *src, unsigned long nbytes); -int visorbus_clear_channel(struct visor_device *dev, - unsigned long offset, u8 ch, unsigned long nbytes); void visorbus_enable_channel_interrupts(struct visor_device *dev); void visorbus_disable_channel_interrupts(struct visor_device *dev); #endif @@ -206,17 +204,12 @@ int visorchannel_read(struct visorchannel *channel, ulong offset, void *local, ulong nbytes); int visorchannel_write(struct visorchannel *channel, ulong offset, void *local, ulong nbytes); -int visorchannel_clear(struct visorchannel *channel, ulong offset, - u8 ch, ulong nbytes); bool visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg); bool visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg); bool visorchannel_signalempty(struct visorchannel *channel, u32 queue); -int visorchannel_signalqueue_slots_avail(struct visorchannel *channel, - u32 queue); -int visorchannel_signalqueue_max_slots(struct visorchannel *channel, u32 queue); u64 visorchannel_get_physaddr(struct visorchannel *channel); ulong visorchannel_get_nbytes(struct visorchannel *channel); char *visorchannel_id(struct visorchannel *channel, char *s); @@ -226,8 +219,6 @@ int visorchannel_set_clientpartition(struct visorchannel *channel, u64 partition_handle); uuid_le visorchannel_get_uuid(struct visorchannel *channel); char *visorchannel_uuid_id(uuid_le *guid, char *s); -void visorchannel_debug(struct visorchannel *channel, int num_queues, - struct seq_file *seq, u32 off); void __iomem *visorchannel_get_header(struct visorchannel *channel); #define BUS_ROOT_DEVICE UINT_MAX diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index f7f5986..8c1754f9 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -715,13 +715,6 @@ visorbus_write_channel(struct visor_device *dev, unsigned long offset, } EXPORT_SYMBOL_GPL(visorbus_write_channel); -int -visorbus_clear_channel(struct visor_device *dev, unsigned long offset, u8 ch, - unsigned long nbytes) -{ - return visorchannel_clear(dev->visorchannel, offset, ch, nbytes); -} - /** We don't really have a real interrupt, so for now we just call the * interrupt function periodically... */ diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c index 1f626c3..43315c2 100644 --- a/drivers/staging/unisys/visorbus/visorchannel.c +++ b/drivers/staging/unisys/visorbus/visorchannel.c @@ -255,41 +255,6 @@ visorchannel_write(struct visorchannel *channel, ulong offset, return 0; } -int -visorchannel_clear(struct visorchannel *channel, ulong offset, u8 ch, - ulong nbytes) -{ - int err; - int bufsize = PAGE_SIZE; - int written = 0; - u8 *buf; - - buf = (u8 *)__get_free_page(GFP_KERNEL); - if (!buf) - return -ENOMEM; - - memset(buf, ch, bufsize); - - while (nbytes > 0) { - int thisbytes = bufsize; - - if (nbytes < thisbytes) - thisbytes = nbytes; - err = visorchannel_write(channel, offset + written, - buf, thisbytes); - if (err) - goto out_free_page; - - written += thisbytes; - nbytes -= thisbytes; - } - err = 0; - -out_free_page: - free_page((unsigned long)buf); - return err; -} - void __iomem * visorchannel_get_header(struct visorchannel *channel) { @@ -490,129 +455,3 @@ visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg) return rc; } EXPORT_SYMBOL_GPL(visorchannel_signalinsert); - -int -visorchannel_signalqueue_slots_avail(struct visorchannel *channel, u32 queue) -{ - struct signal_queue_header sig_hdr; - u32 slots_avail, slots_used; - u32 head, tail; - - if (!sig_read_header(channel, queue, &sig_hdr)) - return 0; - head = sig_hdr.head; - tail = sig_hdr.tail; - if (head < tail) - head = head + sig_hdr.max_slots; - slots_used = head - tail; - slots_avail = sig_hdr.max_signals - slots_used; - return (int)slots_avail; -} - -int -visorchannel_signalqueue_max_slots(struct visorchannel *channel, u32 queue) -{ - struct signal_queue_header sig_hdr; - - if (!sig_read_header(channel, queue, &sig_hdr)) - return 0; - return (int)sig_hdr.max_signals; -} - -static void -sigqueue_debug(struct signal_queue_header *q, int which, struct seq_file *seq) -{ - seq_printf(seq, "Signal Queue #%d\n", which); - seq_printf(seq, " VersionId = %lu\n", (ulong)q->version); - seq_printf(seq, " Type = %lu\n", (ulong)q->chtype); - seq_printf(seq, " oSignalBase = %llu\n", - (long long)q->sig_base_offset); - seq_printf(seq, " SignalSize = %lu\n", (ulong)q->signal_size); - seq_printf(seq, " MaxSignalSlots = %lu\n", - (ulong)q->max_slots); - seq_printf(seq, " MaxSignals = %lu\n", (ulong)q->max_signals); - seq_printf(seq, " FeatureFlags = %-16.16Lx\n", - (long long)q->features); - seq_printf(seq, " NumSignalsSent = %llu\n", - (long long)q->num_sent); - seq_printf(seq, " NumSignalsReceived = %llu\n", - (long long)q->num_received); - seq_printf(seq, " NumOverflows = %llu\n", - (long long)q->num_overflows); - seq_printf(seq, " Head = %lu\n", (ulong)q->head); - seq_printf(seq, " Tail = %lu\n", (ulong)q->tail); -} - -void -visorchannel_debug(struct visorchannel *channel, int num_queues, - struct seq_file *seq, u32 off) -{ - u64 addr = 0; - ulong nbytes = 0, nbytes_region = 0; - struct channel_header hdr; - struct channel_header *phdr = &hdr; - int i = 0; - int errcode = 0; - - if (!channel) - return; - - addr = visorchannel_get_physaddr(channel); - nbytes_region = visorchannel_get_nbytes(channel); - errcode = visorchannel_read(channel, off, - phdr, sizeof(struct channel_header)); - if (errcode < 0) { - seq_printf(seq, - "Read of channel header failed with errcode=%d)\n", - errcode); - if (off == 0) { - phdr = &channel->chan_hdr; - seq_puts(seq, "(following data may be stale)\n"); - } else { - return; - } - } - nbytes = (ulong)(phdr->size); - seq_printf(seq, "--- Begin channel @0x%-16.16Lx for 0x%lx bytes (region=0x%lx bytes) ---\n", - addr + off, nbytes, nbytes_region); - seq_printf(seq, "Type = %pUL\n", &phdr->chtype); - seq_printf(seq, "ZoneGuid = %pUL\n", &phdr->zone_uuid); - seq_printf(seq, "Signature = 0x%-16.16Lx\n", - (long long)phdr->signature); - seq_printf(seq, "LegacyState = %lu\n", (ulong)phdr->legacy_state); - seq_printf(seq, "SrvState = %lu\n", (ulong)phdr->srv_state); - seq_printf(seq, "CliStateBoot = %lu\n", (ulong)phdr->cli_state_boot); - seq_printf(seq, "CliStateOS = %lu\n", (ulong)phdr->cli_state_os); - seq_printf(seq, "HeaderSize = %lu\n", (ulong)phdr->header_size); - seq_printf(seq, "Size = %llu\n", (long long)phdr->size); - seq_printf(seq, "Features = 0x%-16.16llx\n", - (long long)phdr->features); - seq_printf(seq, "PartitionHandle = 0x%-16.16llx\n", - (long long)phdr->partition_handle); - seq_printf(seq, "Handle = 0x%-16.16llx\n", - (long long)phdr->handle); - seq_printf(seq, "VersionId = %lu\n", (ulong)phdr->version_id); - seq_printf(seq, "oChannelSpace = %llu\n", - (long long)phdr->ch_space_offset); - if ((phdr->ch_space_offset == 0) || (errcode < 0)) - ; - else - for (i = 0; i < num_queues; i++) { - struct signal_queue_header q; - - errcode = visorchannel_read(channel, - off + - phdr->ch_space_offset + - (i * sizeof(q)), - &q, sizeof(q)); - if (errcode < 0) { - seq_printf(seq, - "failed to read signal queue #%d from channel @0x%-16.16Lx errcode=%d\n", - i, addr, errcode); - continue; - } - sigqueue_debug(&q, i, seq); - } - seq_printf(seq, "--- End channel @0x%-16.16Lx for 0x%lx bytes ---\n", - addr + off, nbytes); -} -- cgit v0.10.2 From 5f084e278fe1d968ae2440478a021db3fcbc2ab2 Mon Sep 17 00:00:00 2001 From: Bryan Thompson <bryan.thompson@unisys.com> Date: Fri, 10 Jun 2016 21:48:13 -0400 Subject: staging: unisys: Remove reference to unused STANDALONE_CLIENT The STANDALONE_CLIENT define is no longer used by Unisys driver code. Signed-off-by: Bryan Thompson <bryan.thompson@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Acked-By: Neil Horman <nhorman@tuxdriver.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/include/visorbus.h b/drivers/staging/unisys/include/visorbus.h index cbe240a..fb53a65 100644 --- a/drivers/staging/unisys/include/visorbus.h +++ b/drivers/staging/unisys/include/visorbus.h @@ -176,7 +176,6 @@ struct visor_device { #define to_visor_device(x) container_of(x, struct visor_device, device) -#ifndef STANDALONE_CLIENT int visorbus_register_visor_driver(struct visor_driver *); void visorbus_unregister_visor_driver(struct visor_driver *); int visorbus_read_channel(struct visor_device *dev, @@ -187,7 +186,6 @@ int visorbus_write_channel(struct visor_device *dev, unsigned long nbytes); void visorbus_enable_channel_interrupts(struct visor_device *dev); void visorbus_disable_channel_interrupts(struct visor_device *dev); -#endif /* Note that for visorchannel_create() * <channel_bytes> and <guid> arguments may be 0 if we are a channel CLIENT. -- cgit v0.10.2 From 93e59bfc3bd0b4069b06cd42025e6735b9aecf5b Mon Sep 17 00:00:00 2001 From: Tim Sell <Timothy.Sell@unisys.com> Date: Fri, 10 Jun 2016 21:48:14 -0400 Subject: staging: unisys: visorbus: remove unused parameter from function The off parameter to visorchannel_create_guts() was never used, so it was removed. Signed-off-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Acked-By: Neil Horman <nhorman@tuxdriver.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c index 43315c2..1bfbc06 100644 --- a/drivers/staging/unisys/visorbus/visorchannel.c +++ b/drivers/staging/unisys/visorbus/visorchannel.c @@ -60,8 +60,7 @@ struct visorchannel { */ static struct visorchannel * visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes, - gfp_t gfp, unsigned long off, - uuid_le guid, bool needs_lock) + gfp_t gfp, uuid_le guid, bool needs_lock) { struct visorchannel *channel; int err; @@ -145,7 +144,7 @@ struct visorchannel * visorchannel_create(u64 physaddr, unsigned long channel_bytes, gfp_t gfp, uuid_le guid) { - return visorchannel_create_guts(physaddr, channel_bytes, gfp, 0, guid, + return visorchannel_create_guts(physaddr, channel_bytes, gfp, guid, false); } @@ -153,7 +152,7 @@ struct visorchannel * visorchannel_create_with_lock(u64 physaddr, unsigned long channel_bytes, gfp_t gfp, uuid_le guid) { - return visorchannel_create_guts(physaddr, channel_bytes, gfp, 0, guid, + return visorchannel_create_guts(physaddr, channel_bytes, gfp, guid, true); } -- cgit v0.10.2 From 0048be9e1ee99d6c63001aaf831d797c3fa8e345 Mon Sep 17 00:00:00 2001 From: David Binder <david.binder@unisys.com> Date: Fri, 10 Jun 2016 21:48:15 -0400 Subject: staging: unisys: visorbus: fix commenting in vbusdevinfo.h This patch ONLY touches comment lines, i.e., NO executable code is affected. * All functions worthy of documenting now use standard kerneldoc formatting. * Multi-line comments were tweaked so as to use appropriate conventions. * Minor typos were corrected. Signed-off-by: David Binder <david.binder@unisys.com> Signed-off-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Acked-By: Neil Horman <nhorman@tuxdriver.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/vbusdeviceinfo.h b/drivers/staging/unisys/visorbus/vbusdeviceinfo.h index abdab4a..e6bfed1 100644 --- a/drivers/staging/unisys/visorbus/vbusdeviceinfo.h +++ b/drivers/staging/unisys/visorbus/vbusdeviceinfo.h @@ -19,7 +19,8 @@ #pragma pack(push, 1) /* both GCC and VC now allow this pragma */ -/* An array of this struct is present in the channel area for each vbus. +/* + * An array of this struct is present in the channel area for each vbus. * (See vbuschannel.h.) * It is filled in by the client side to provide info about the device * and driver from the client's perspective. @@ -34,19 +35,28 @@ struct ultra_vbus_deviceinfo { #pragma pack(pop) -/* Reads chars from the buffer at <src> for <srcmax> bytes, and writes to - * the buffer at <p>, which is <remain> bytes long, ensuring never to - * overflow the buffer at <p>, using the following rules: - * - printable characters are simply copied from the buffer at <src> to the - * buffer at <p> - * - intervening streaks of non-printable characters in the buffer at <src> - * are replaced with a single space in the buffer at <p> +/** + * vbuschannel_sanitize_buffer() - remove non-printable chars from buffer + * @p: destination buffer where chars are written to + * @remain: number of bytes that can be written starting at #p + * @src: pointer to source buffer + * @srcmax: number of valid characters at #src + * + * Reads chars from the buffer at @src for @srcmax bytes, and writes to + * the buffer at @p, which is @remain bytes long, ensuring never to + * overflow the buffer at @p, using the following rules: + * - printable characters are simply copied from the buffer at @src to the + * buffer at @p + * - intervening streaks of non-printable characters in the buffer at @src + * are replaced with a single space in the buffer at @p * Note that we pay no attention to '\0'-termination. - * Returns the number of bytes written to <p>. * - * Pass <p> == NULL and <remain> == 0 for this special behavior. In this + * Pass @p == NULL and @remain == 0 for this special behavior -- In this * case, we simply return the number of bytes that WOULD HAVE been written - * to a buffer at <p>, had it been infinitely big. + * to a buffer at @p, had it been infinitely big. + * + * Return: the number of bytes written to @p (or WOULD HAVE been written to + * @p, as described in the previous paragraph) */ static inline int vbuschannel_sanitize_buffer(char *p, int remain, char *src, int srcmax) @@ -92,14 +102,18 @@ vbuschannel_sanitize_buffer(char *p, int remain, char *src, int srcmax) p++; chars++; remain--; \ } while (0) -/* Converts the non-negative value at <num> to an ascii decimal string - * at <p>, writing at most <remain> bytes. Note there is NO '\0' termination - * written to <p>. +/** + * vbuschannel_itoa() - convert non-negative int to string + * @p: destination string + * @remain: max number of bytes that can be written to @p + * @num: input int to convert + * + * Converts the non-negative value at @num to an ascii decimal string + * at @p, writing at most @remain bytes. Note there is NO '\0' termination + * written to @p. * - * Returns the number of bytes written to <p>. + * Return: number of bytes written to @p * - * Note that we create this function because we need to do this operation in - * an environment-independent way (since we are in a common header file). */ static inline int vbuschannel_itoa(char *p, int remain, int num) @@ -141,13 +155,20 @@ vbuschannel_itoa(char *p, int remain, int num) return digits; } -/* Reads <devInfo>, and converts its contents to a printable string at <p>, - * writing at most <remain> bytes. Note there is NO '\0' termination - * written to <p>. +/** + * vbuschannel_devinfo_to_string() - format a struct ultra_vbus_deviceinfo + * to a printable string + * @devinfo: the struct ultra_vbus_deviceinfo to format + * @p: destination string area + * @remain: size of destination string area in bytes + * @devix: the device index to be included in the output data, or -1 if no + * device index is to be included * - * Pass <devix> >= 0 if you want a device index presented. + * Reads @devInfo, and converts its contents to a printable string at @p, + * writing at most @remain bytes. Note there is NO '\0' termination + * written to @p. * - * Returns the number of bytes written to <p>. + * Return: number of bytes written to @p */ static inline int vbuschannel_devinfo_to_string(struct ultra_vbus_deviceinfo *devinfo, -- cgit v0.10.2 From 3fd1b3b6829c5ccbdc5af9a86e59d6360af9972b Mon Sep 17 00:00:00 2001 From: David Binder <david.binder@unisys.com> Date: Fri, 10 Jun 2016 21:48:16 -0400 Subject: staging: unisys: visorbus: fix commenting in visorbus_main.c This patch ONLY touches comment lines, i.e., NO executable code is affected. * All functions worthy of documenting now use standard kerneldoc formatting. * Improper uses of kerneldoc formatting were converted to standard multi-line comments. * Multi-line comments were tweaked so as to use appropriate conventions. Signed-off-by: David Binder <david.binder@unisys.com> Signed-off-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Acked-By: Neil Horman <nhorman@tuxdriver.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 8c1754f9..2468264 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -44,11 +44,11 @@ static int visorbus_uevent(struct device *xdev, struct kobj_uevent_env *env); static int visorbus_match(struct device *xdev, struct device_driver *xdrv); static void fix_vbus_dev_info(struct visor_device *visordev); -/* BUS type attributes - * - * define & implement display of bus attributes under - * /sys/bus/visorbus. +/* + * BUS type attributes * + * define & implement display of bus attributes under + * /sys/bus/visorbus. */ static ssize_t version_show(struct bus_type *bus, char *buf) @@ -104,7 +104,8 @@ static const struct attribute_group *visorbus_dev_groups[] = { NULL, }; -/** This describes the TYPE of bus. +/* + * This describes the TYPE of bus. * (Don't confuse this with an INSTANCE of the bus.) */ struct bus_type visorbus_type = { @@ -115,8 +116,8 @@ struct bus_type visorbus_type = { .bus_groups = visorbus_bus_groups, }; -static long long bus_count; /** number of bus instances */ - /** ever-increasing */ +static long long bus_count; /* number of bus instances */ + /* ever-increasing */ static void chipset_bus_create(struct visor_device *bus_info); static void chipset_bus_destroy(struct visor_device *bus_info); @@ -125,8 +126,9 @@ static void chipset_device_destroy(struct visor_device *dev_info); static void chipset_device_pause(struct visor_device *dev_info); static void chipset_device_resume(struct visor_device *dev_info); -/** These functions are implemented herein, and are called by the chipset - * driver to notify us about specific events. +/* + * These functions are implemented herein, and are called by the chipset + * driver to notify us about specific events. */ static struct visorchipset_busdev_notifiers chipset_notifiers = { .bus_create = chipset_bus_create, @@ -137,8 +139,9 @@ static struct visorchipset_busdev_notifiers chipset_notifiers = { .device_resume = chipset_device_resume, }; -/** These functions are implemented in the chipset driver, and we call them - * herein when we want to acknowledge a specific event. +/* + * These functions are implemented in the chipset driver, and we call them + * herein when we want to acknowledge a specific event. */ static struct visorchipset_busdev_responders chipset_responders; @@ -147,9 +150,9 @@ static struct ultra_vbus_deviceinfo chipset_driverinfo; /* filled in with info about this driver, wrt it servicing client busses */ static struct ultra_vbus_deviceinfo clientbus_driverinfo; -/** list of visor_device structs, linked via .list_all */ +/* list of visor_device structs, linked via .list_all */ static LIST_HEAD(list_all_bus_instances); -/** list of visor_device structs, linked via .list_all */ +/* list of visor_device structs, linked via .list_all */ static LIST_HEAD(list_all_device_instances); static int @@ -166,9 +169,14 @@ visorbus_uevent(struct device *xdev, struct kobj_uevent_env *env) return 0; } -/* This is called automatically upon adding a visor_device (device_add), or - * adding a visor_driver (visorbus_register_visor_driver), and returns 1 iff the - * provided driver can control the specified device. +/** + * visorbus_match() - called automatically upon adding a visor_device + * (device_add), or adding a visor_driver + * (visorbus_register_visor_driver) + * @xdev: struct device for the device being matched + * @xdrv: struct device_driver for driver to match device against + * + * Return: 1 iff the provided driver can control the specified device */ static int visorbus_match(struct device *xdev, struct device_driver *xdrv) @@ -200,9 +208,11 @@ visorbus_match(struct device *xdev, struct device_driver *xdrv) return 0; } -/** This is called when device_unregister() is called for the bus device - * instance, after all other tasks involved with destroying the device - * are complete. +/** + * visorbus_releae_busdevice() - called when device_unregister() is called for + * the bus device instance, after all other tasks + * involved with destroying the dev are complete + * @xdev: struct device for the bus being released */ static void visorbus_release_busdevice(struct device *xdev) @@ -212,8 +222,10 @@ visorbus_release_busdevice(struct device *xdev) kfree(dev); } -/** This is called when device_unregister() is called for each child - * device instance. +/** + * visorbus_release_device() - called when device_unregister() is called for + * each child device instance + * @xdev: struct device for the visor device being released */ static void visorbus_release_device(struct device *xdev) @@ -227,9 +239,11 @@ visorbus_release_device(struct device *xdev) kfree(dev); } -/* begin implementation of specific channel attributes to appear under -* /sys/bus/visorbus<x>/dev<y>/channel -*/ +/* + * begin implementation of specific channel attributes to appear under + * /sys/bus/visorbus<x>/dev<y>/channel + */ + static ssize_t physaddr_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -334,15 +348,11 @@ static const struct attribute_group *visorbus_channel_groups[] = { /* end implementation of specific channel attributes */ -/* BUS instance attributes +/* + * BUS instance attributes * * define & implement display of bus attributes under - * /sys/bus/visorbus/busses/visorbus<n>. - * - * This is a bit hoaky because the kernel does not yet have the infrastructure - * to separate bus INSTANCE attributes from bus TYPE attributes... - * so we roll our own. See businst.c / businst.h. - * + * /sys/bus/visorbus/devices/visorbus<n>. */ static ssize_t partition_handle_show(struct device *dev, @@ -493,11 +503,11 @@ static const struct attribute_group *visorbus_groups[] = { NULL }; -/* DRIVER attributes +/* + * DRIVER attributes * * define & implement display of driver attributes under * /sys/bus/visorbus/drivers/<drivername>. - * */ static ssize_t @@ -556,10 +566,20 @@ dev_stop_periodic_work(struct visor_device *dev) put_device(&dev->device); } -/** This is called automatically upon adding a visor_device (device_add), or - * adding a visor_driver (visorbus_register_visor_driver), but only after - * visorbus_match has returned 1 to indicate a successful match between - * driver and device. +/** + * visordriver_probe_device() - handle new visor device coming online + * @xdev: struct device for the visor device being probed + * + * This is called automatically upon adding a visor_device (device_add), or + * adding a visor_driver (visorbus_register_visor_driver), but only after + * visorbus_match() has returned 1 to indicate a successful match between + * driver and device. + * + * If successful, a reference to the device will be held onto via get_device(). + * + * Return: 0 if successful, meaning the function driver's probe() function + * was successful with this device, otherwise a negative errno + * value indicating failure reason */ static int visordriver_probe_device(struct device *xdev) @@ -588,9 +608,15 @@ visordriver_probe_device(struct device *xdev) return res; } -/** This is called when device_unregister() is called for each child device - * instance, to notify the appropriate visorbus_driver that the device is - * going away, and to decrease the reference count of the device. +/** + * visordriver_remove_device() - handle visor device going away + * @xdev: struct device for the visor device being removed + * + * This is called when device_unregister() is called for each child device + * instance, to notify the appropriate visorbus function driver that the device + * is going away, and to decrease the reference count of the device. + * + * Return: 0 iff successful */ static int visordriver_remove_device(struct device *xdev) @@ -611,47 +637,54 @@ visordriver_remove_device(struct device *xdev) return 0; } -/** A particular type of visor driver calls this function to register - * the driver. The caller MUST fill in the following fields within the - * #drv structure: - * name, version, owner, channel_types, probe, remove +/** + * visorbus_register_visor_driver() - registers the provided visor driver + * for handling one or more visor device + * types (channel_types) + * @drv: the driver to register * - * Here's how the whole Linux bus / driver / device model works. + * A visor function driver calls this function to register + * the driver. The caller MUST fill in the following fields within the + * #drv structure: + * name, version, owner, channel_types, probe, remove * - * At system start-up, the visorbus kernel module is loaded, which registers - * visorbus_type as a bus type, using bus_register(). + * Here's how the whole Linux bus / driver / device model works. * - * All kernel modules that support particular device types on a - * visorbus bus are loaded. Each of these kernel modules calls - * visorbus_register_visor_driver() in their init functions, passing a - * visor_driver struct. visorbus_register_visor_driver() in turn calls - * register_driver(&visor_driver.driver). This .driver member is - * initialized with generic methods (like probe), whose sole responsibility - * is to act as a broker for the real methods, which are within the - * visor_driver struct. (This is the way the subclass behavior is - * implemented, since visor_driver is essentially a subclass of the - * generic driver.) Whenever a driver_register() happens, core bus code in - * the kernel does (see device_attach() in drivers/base/dd.c): + * At system start-up, the visorbus kernel module is loaded, which registers + * visorbus_type as a bus type, using bus_register(). * - * for each dev associated with the bus (the bus that driver is on) that - * does not yet have a driver - * if bus.match(dev,newdriver) == yes_matched ** .match specified - * ** during bus_register(). - * newdriver.probe(dev) ** for visor drivers, this will call - * ** the generic driver.probe implemented in visorbus.c, - * ** which in turn calls the probe specified within the - * ** struct visor_driver (which was specified by the - * ** actual device driver as part of - * ** visorbus_register_visor_driver()). + * All kernel modules that support particular device types on a + * visorbus bus are loaded. Each of these kernel modules calls + * visorbus_register_visor_driver() in their init functions, passing a + * visor_driver struct. visorbus_register_visor_driver() in turn calls + * register_driver(&visor_driver.driver). This .driver member is + * initialized with generic methods (like probe), whose sole responsibility + * is to act as a broker for the real methods, which are within the + * visor_driver struct. (This is the way the subclass behavior is + * implemented, since visor_driver is essentially a subclass of the + * generic driver.) Whenever a driver_register() happens, core bus code in + * the kernel does (see device_attach() in drivers/base/dd.c): * - * The above dance also happens when a new device appears. - * So the question is, how are devices created within the system? - * Basically, just call device_add(dev). See pci_bus_add_devices(). - * pci_scan_device() shows an example of how to build a device struct. It - * returns the newly-created struct to pci_scan_single_device(), who adds it - * to the list of devices at PCIBUS.devices. That list of devices is what - * is traversed by pci_bus_add_devices(). + * for each dev associated with the bus (the bus that driver is on) that + * does not yet have a driver + * if bus.match(dev,newdriver) == yes_matched ** .match specified + * ** during bus_register(). + * newdriver.probe(dev) ** for visor drivers, this will call + * ** the generic driver.probe implemented in visorbus.c, + * ** which in turn calls the probe specified within the + * ** struct visor_driver (which was specified by the + * ** actual device driver as part of + * ** visorbus_register_visor_driver()). * + * The above dance also happens when a new device appears. + * So the question is, how are devices created within the system? + * Basically, just call device_add(dev). See pci_bus_add_devices(). + * pci_scan_device() shows an example of how to build a device struct. It + * returns the newly-created struct to pci_scan_single_device(), who adds it + * to the list of devices at PCIBUS.devices. That list of devices is what + * is traversed by pci_bus_add_devices(). + * + * Return: integer indicating success (zero) or failure (non-zero) */ int visorbus_register_visor_driver(struct visor_driver *drv) { @@ -666,7 +699,8 @@ int visorbus_register_visor_driver(struct visor_driver *drv) drv->driver.remove = visordriver_remove_device; drv->driver.owner = drv->owner; - /* driver_register does this: + /* + * driver_register does this: * bus_add_driver(drv) * ->if (drv.bus) ** (bus_type) ** * driver_attach(drv) @@ -688,8 +722,12 @@ int visorbus_register_visor_driver(struct visor_driver *drv) } EXPORT_SYMBOL_GPL(visorbus_register_visor_driver); -/** A particular type of visor driver calls this function to unregister - * the driver, i.e., within its module_exit function. +/** + * visorbus_unregister_visor_driver() - unregisters the provided driver + * @drv: the driver to unregister + * + * A visor function driver calls this function to unregister the driver, + * i.e., within its module_exit function. */ void visorbus_unregister_visor_driver(struct visor_driver *drv) @@ -699,6 +737,19 @@ visorbus_unregister_visor_driver(struct visor_driver *drv) } EXPORT_SYMBOL_GPL(visorbus_unregister_visor_driver); +/** + * visorbus_read_channel() - reads from the designated channel into + * the provided buffer + * @dev: the device whose channel is read from + * @offset: the offset into the channel at which reading starts + * @dest: the destination buffer that is written into from the channel + * @nbytes: the number of bytes to read from the channel + * + * If receiving a message, use the visorchannel_signalremove() + * function instead. + * + * Return: integer indicating success (zero) or failure (non-zero) + */ int visorbus_read_channel(struct visor_device *dev, unsigned long offset, void *dest, unsigned long nbytes) @@ -707,6 +758,19 @@ visorbus_read_channel(struct visor_device *dev, unsigned long offset, } EXPORT_SYMBOL_GPL(visorbus_read_channel); +/** + * visorbus_write_channel() - writes the provided buffer into the designated + * channel + * @dev: the device whose channel is written to + * @offset: the offset into the channel at which writing starts + * @src: the source buffer that is written into the channel + * @nbytes: the number of bytes to write into the channel + * + * If sending a message, use the visorchannel_signalinsert() + * function instead. + * + * Return: integer indicating success (zero) or failure (non-zero) + */ int visorbus_write_channel(struct visor_device *dev, unsigned long offset, void *src, unsigned long nbytes) @@ -715,8 +779,13 @@ visorbus_write_channel(struct visor_device *dev, unsigned long offset, } EXPORT_SYMBOL_GPL(visorbus_write_channel); -/** We don't really have a real interrupt, so for now we just call the - * interrupt function periodically... +/** + * visorbus_enable_channel_interrupts() - enables interrupts on the + * designated device + * @dev: the device on which to enable interrupts + * + * Currently we don't yet have a real interrupt, so for now we just call the + * interrupt function periodically via a timer. */ void visorbus_enable_channel_interrupts(struct visor_device *dev) @@ -725,6 +794,11 @@ visorbus_enable_channel_interrupts(struct visor_device *dev) } EXPORT_SYMBOL_GPL(visorbus_enable_channel_interrupts); +/** + * visorbus_disable_channel_interrupts() - disables interrupts on the + * designated device + * @dev: the device on which to disable interrupts + */ void visorbus_disable_channel_interrupts(struct visor_device *dev) { @@ -732,19 +806,28 @@ visorbus_disable_channel_interrupts(struct visor_device *dev) } EXPORT_SYMBOL_GPL(visorbus_disable_channel_interrupts); -/** This is how everything starts from the device end. - * This function is called when a channel first appears via a ControlVM - * message. In response, this function allocates a visor_device to - * correspond to the new channel, and attempts to connect it the appropriate - * driver. If the appropriate driver is found, the visor_driver.probe() - * function for that driver will be called, and will be passed the new - * visor_device that we just created. +/** + * create_visor_device() - create visor device as a result of receiving the + * controlvm device_create message for a new device + * @dev: a freshly-zeroed struct visor_device, containing only filled-in values + * for chipset_bus_no and chipset_dev_no, that will be initialized + * + * This is how everything starts from the device end. + * This function is called when a channel first appears via a ControlVM + * message. In response, this function allocates a visor_device to + * correspond to the new channel, and attempts to connect it the appropriate + * driver. If the appropriate driver is found, the visor_driver.probe() + * function for that driver will be called, and will be passed the new + * visor_device that we just created. * - * It's ok if the appropriate driver is not yet loaded, because in that case - * the new device struct will just stick around in the bus' list of devices. - * When the appropriate driver calls visorbus_register_visor_driver(), the - * visor_driver.probe() for the new driver will be called with the new - * device. + * It's ok if the appropriate driver is not yet loaded, because in that case + * the new device struct will just stick around in the bus' list of devices. + * When the appropriate driver calls visorbus_register_visor_driver(), the + * visor_driver.probe() for the new driver will be called with the new + * device. + * + * Return: 0 if successful, otherwise the negative value returned by + * device_add() indicating the reason for failure */ static int create_visor_device(struct visor_device *dev) @@ -767,14 +850,16 @@ create_visor_device(struct visor_device *dev) dev->timer.data = (unsigned long)(dev); dev->timer.function = dev_periodic_work; - /* bus_id must be a unique name with respect to this bus TYPE + /* + * bus_id must be a unique name with respect to this bus TYPE * (NOT bus instance). That's why we need to include the bus * number within the name. */ dev_set_name(&dev->device, "vbus%u:dev%u", chipset_bus_no, chipset_dev_no); - /* device_add does this: + /* + * device_add does this: * bus_add_device(dev) * ->device_attach(dev) * ->for each driver drv registered on the bus that dev is on @@ -834,13 +919,19 @@ get_vbus_header_info(struct visorchannel *chan, return 0; } -/* Write the contents of <info> to the struct - * spar_vbus_channel_protocol.chp_info. +/** + * write_vbus_chp_info() - write the contents of <info> to the struct + * spar_vbus_channel_protocol.chp_info + * @chan: indentifies the s-Par channel that will be updated + * @hdr_info: used to find appropriate channel offset to write data + * @info: contains the information to write + * + * Writes chipset info into the channel memory to be used for diagnostic + * purposes. * - * Returns void since this is debug information and not needed for + * Returns no value since this is debug information and not needed for * device functionality. */ - static void write_vbus_chp_info(struct visorchannel *chan, struct spar_vbus_headerinfo *hdr_info, @@ -854,13 +945,19 @@ write_vbus_chp_info(struct visorchannel *chan, visorchannel_write(chan, off, info, sizeof(*info)); } -/* Write the contents of <info> to the struct - * spar_vbus_channel_protocol.bus_info. +/** + * write_vbus_bus_info() - write the contents of <info> to the struct + * spar_vbus_channel_protocol.bus_info + * @chan: indentifies the s-Par channel that will be updated + * @hdr_info: used to find appropriate channel offset to write data + * @info: contains the information to write + * + * Writes bus info into the channel memory to be used for diagnostic + * purposes. * - * Returns void since this is debug information and not needed for + * Returns no value since this is debug information and not needed for * device functionality. */ - static void write_vbus_bus_info(struct visorchannel *chan, struct spar_vbus_headerinfo *hdr_info, @@ -874,10 +971,18 @@ write_vbus_bus_info(struct visorchannel *chan, visorchannel_write(chan, off, info, sizeof(*info)); } -/* Write the contents of <info> to the - * struct spar_vbus_channel_protocol.dev_info[<devix>]. +/** + * write_vbus_dev_info() - write the contents of <info> to the struct + * spar_vbus_channel_protocol.dev_info[<devix>] + * @chan: indentifies the s-Par channel that will be updated + * @hdr_info: used to find appropriate channel offset to write data + * @info: contains the information to write + * @devix: the relative device number (0..n-1) of the device on the bus * - * Returns void since this is debug information and not needed for + * Writes device info into the channel memory to be used for diagnostic + * purposes. + * + * Returns no value since this is debug information and not needed for * device functionality. */ static void @@ -895,10 +1000,12 @@ write_vbus_dev_info(struct visorchannel *chan, visorchannel_write(chan, off, info, sizeof(*info)); } -/* For a child device just created on a client bus, fill in - * information about the driver that is controlling this device into - * the the appropriate slot within the vbus channel of the bus - * instance. +/** + * fix_vbus_dev_info() - for a child device just created on a client bus, fill + * in information about the driver that is controlling + * this device into the the appropriate slot within the + * vbus channel of the bus instance + * @visordev: struct visor_device for the desired device */ static void fix_vbus_dev_info(struct visor_device *visordev) @@ -925,7 +1032,8 @@ fix_vbus_dev_info(struct visor_device *visordev) visordrv = to_visor_driver(visordev->device.driver); - /* Within the list of device types (by GUID) that the driver + /* + * Within the list of device types (by GUID) that the driver * says it supports, find out which one of those types matches * the type of this device, so that we can include the device * type name @@ -944,15 +1052,21 @@ fix_vbus_dev_info(struct visor_device *visordev) visordrv->vertag); write_vbus_dev_info(bdev->visorchannel, hdr_info, &dev_info, dev_no); - /* Re-write bus+chipset info, because it is possible that this - * was previously written by our evil counterpart, virtpci. - */ + /* + * Re-write bus+chipset info, because it is possible that this + * was previously written by our evil counterpart, virtpci. + */ write_vbus_chp_info(bdev->visorchannel, hdr_info, &chipset_driverinfo); write_vbus_bus_info(bdev->visorchannel, hdr_info, &clientbus_driverinfo); } -/** Create a device instance for the visor bus itself. +/** + * create_bus_instance() - create a device instance for the visor bus itself + * @dev: struct visor_device indicating the bus instance + * + * Return: 0 for success, otherwise negative errno value indicating reason for + * failure */ static int create_bus_instance(struct visor_device *dev) @@ -993,12 +1107,15 @@ create_bus_instance(struct visor_device *dev) return 0; } -/** Remove a device instance for the visor bus itself. +/** + * remove_bus_instance() - remove a device instance for the visor bus itself + * @dev: struct visor_device indentifying the bus to remove */ static void remove_bus_instance(struct visor_device *dev) { - /* Note that this will result in the release method for + /* + * Note that this will result in the release method for * dev->dev being called, which will call * visorbus_release_busdevice(). This has something to do with * the put_device() done in device_unregister(), but I have never @@ -1015,8 +1132,11 @@ remove_bus_instance(struct visor_device *dev) device_unregister(&dev->device); } -/** Create and register the one-and-only one instance of - * the visor bus type (visorbus_type). +/** + * create_bus_type() - create and register the one-and-only one instance of + * the visor bus type (visorbus_type) + * Return: 0 for success, otherwise negative errno value returned by + * bus_register() indicating the reason for failure */ static int create_bus_type(void) @@ -1025,7 +1145,9 @@ create_bus_type(void) return busreg_rc; } -/** Remove the one-and-only one instance of the visor bus type (visorbus_type). +/** + * remove_bus_type() - remove the one-and-only one instance of the visor bus + * type (visorbus_type) */ static void remove_bus_type(void) @@ -1033,7 +1155,8 @@ remove_bus_type(void) bus_unregister(&visorbus_type); } -/** Remove all child visor bus device instances. +/** + * remove_all_visor_devices() - remove all child visor bus device instances */ static void remove_all_visor_devices(void) @@ -1108,9 +1231,14 @@ chipset_device_destroy(struct visor_device *dev_info) (*chipset_responders.device_destroy) (dev_info, 0); } -/* This is the callback function specified for a function driver, to - * be called when a pending "pause device" operation has been - * completed. +/** + * pause_state_change_complete() - the callback function to be called by a + * visorbus function driver when a + * pending "pause device" operation has + * completed + * @dev: struct visor_device identifying the paused device + * @status: 0 iff the pause state change completed successfully, otherwise + * a negative errno value indicating the reason for failure */ static void pause_state_change_complete(struct visor_device *dev, int status) @@ -1129,9 +1257,14 @@ pause_state_change_complete(struct visor_device *dev, int status) (*chipset_responders.device_pause) (dev, status); } -/* This is the callback function specified for a function driver, to - * be called when a pending "resume device" operation has been - * completed. +/** + * resume_state_change_complete() - the callback function to be called by a + * visorbus function driver when a + * pending "resume device" operation has + * completed + * @dev: struct visor_device identifying the resumed device + * @status: 0 iff the resume state change completed successfully, otherwise + * a negative errno value indicating the reason for failure */ static void resume_state_change_complete(struct visor_device *dev, int status) @@ -1143,16 +1276,24 @@ resume_state_change_complete(struct visor_device *dev, int status) if (!chipset_responders.device_resume) /* this can never happen! */ return; - /* Notify the chipset driver that the resume is complete, + /* + * Notify the chipset driver that the resume is complete, * which will presumably want to send some sort of response to * the initiator. */ (*chipset_responders.device_resume) (dev, status); } -/* Tell the subordinate function driver for a specific device to pause - * or resume that device. Result is returned asynchronously via a - * callback function. +/** + * initiate_chipset_device_pause_resume() - start a pause or resume operation + * for a visor device + * @dev: struct visor_device identifying the device being paused or resumed + * @is_pause: true to indicate pause operation, false to indicate resume + * + * Tell the subordinate function driver for a specific device to pause + * or resume that device. Success/failure result is returned asynchronously + * via a callback function; see pause_state_change_complete() and + * resume_state_change_complete(). */ static void initiate_chipset_device_pause_resume(struct visor_device *dev, bool is_pause) @@ -1179,7 +1320,8 @@ initiate_chipset_device_pause_resume(struct visor_device *dev, bool is_pause) return; } - /* Note that even though both drv->pause() and drv->resume + /* + * Note that even though both drv->pause() and drv->resume * specify a callback function, it is NOT necessary for us to * increment our local module usage count. Reason is, there * is already a linkage dependency between child function @@ -1219,12 +1361,28 @@ initiate_chipset_device_pause_resume(struct visor_device *dev, bool is_pause) } } +/** + * chipset_device_pause() - start a pause operation for a visor device + * @dev_info: struct visor_device identifying the device being paused + * + * Tell the subordinate function driver for a specific device to pause + * that device. Success/failure result is returned asynchronously + * via a callback function; see pause_state_change_complete(). + */ static void chipset_device_pause(struct visor_device *dev_info) { initiate_chipset_device_pause_resume(dev_info, true); } +/** + * chipset_device_resume() - start a resume operation for a visor device + * @dev_info: struct visor_device identifying the device being resumed + * + * Tell the subordinate function driver for a specific device to resume + * that device. Success/failure result is returned asynchronously + * via a callback function; see resume_state_change_complete(). + */ static void chipset_device_resume(struct visor_device *dev_info) { -- cgit v0.10.2 From e19674ceb6f2b07d4c4433e0b805616f58b2983c Mon Sep 17 00:00:00 2001 From: David Binder <david.binder@unisys.com> Date: Fri, 10 Jun 2016 21:48:17 -0400 Subject: staging: unisys: visorbus: fix visorchannel.c comments This patch ONLY touches comment lines, i.e., NO executable code is affected. Comments were fixed in visorchannel.c: * All functions worthy of documenting now use standard kerneldoc formatting. * Multi-line comments were tweaked so as to use appropriate conventions. * Minor typos were corrected. * Useless comments were removed. Signed-off-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Signed-off-by: David Binder <david.binder@unisys.com> Acked-By: Neil Horman <nhorman@tuxdriver.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c index 1bfbc06..0ddfe05 100644 --- a/drivers/staging/unisys/visorbus/visorchannel.c +++ b/drivers/staging/unisys/visorbus/visorchannel.c @@ -15,7 +15,7 @@ */ /* - * This provides Supervisor channel communication primitives, which are + * This provides s-Par channel communication primitives, which are * independent of the mechanism used to access the channel data. */ @@ -55,8 +55,28 @@ struct visorchannel { uuid_le inst; }; -/* Creates the struct visorchannel abstraction for a data area in memory, - * but does NOT modify this data area. +/** + * visorchannel_create_guts() - creates the struct visorchannel abstraction + * for a data area in memory, but does NOT modify + * this data area + * @physaddr: physical address of start of channel + * @channel_bytes: size of the channel in bytes; this may 0 if the channel has + * already been initialized in memory (which is true for all + * channels provided to guest environments by the s-Par + * back-end), in which case the actual channel size will be + * read from the channel header in memory + * @gfp: gfp_t to use when allocating memory for the data struct + * @guid: uuid that identifies channel type; this may 0 if the channel + * has already been initialized in memory (which is true for all + * channels provided to guest environments by the s-Par + * back-end), in which case the actual channel guid will be + * read from the channel header in memory + * @needs_lock: must specify true if you have multiple threads of execution + * that will be calling visorchannel methods of this + * visorchannel at the same time + * + * Return: pointer to visorchannel that was created if successful, + * otherwise NULL */ static struct visorchannel * visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes, @@ -77,7 +97,8 @@ visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes, spin_lock_init(&channel->insert_lock); spin_lock_init(&channel->remove_lock); - /* Video driver constains the efi framebuffer so it will get a + /* + * Video driver constains the efi framebuffer so it will get a * conflict resource when requesting its full mem region. Since * we are only using the efi framebuffer for video we can ignore * this. Remember that we haven't requested it so we don't try to @@ -214,6 +235,12 @@ visorchannel_set_clientpartition(struct visorchannel *channel, return 0; } +/** + * visorchannel_get_uuid() - queries the UUID of the designated channel + * @channel: the channel to query + * + * Return: the UUID of the provided channel + */ uuid_le visorchannel_get_uuid(struct visorchannel *channel) { @@ -260,22 +287,25 @@ visorchannel_get_header(struct visorchannel *channel) return (void __iomem *)&channel->chan_hdr; } -/** Return offset of a specific SIGNAL_QUEUE_HEADER from the beginning of a - * channel header +/* + * Return offset of a specific SIGNAL_QUEUE_HEADER from the beginning of a + * channel header */ #define SIG_QUEUE_OFFSET(chan_hdr, q) \ ((chan_hdr)->ch_space_offset + \ ((q) * sizeof(struct signal_queue_header))) -/** Return offset of a specific queue entry (data) from the beginning of a - * channel header +/* + * Return offset of a specific queue entry (data) from the beginning of a + * channel header */ #define SIG_DATA_OFFSET(chan_hdr, q, sig_hdr, slot) \ (SIG_QUEUE_OFFSET(chan_hdr, q) + (sig_hdr)->sig_base_offset + \ ((slot) * (sig_hdr)->signal_size)) -/** Write the contents of a specific field within a SIGNAL_QUEUE_HEADER back - * into host memory +/* + * Write the contents of a specific field within a SIGNAL_QUEUE_HEADER back + * into host memory */ #define SIG_WRITE_FIELD(channel, queue, sig_hdr, FIELD) \ (visorchannel_write(channel, \ @@ -350,7 +380,8 @@ signalremove_inner(struct visorchannel *channel, u32 queue, void *msg) return false; sig_hdr.num_received++; - /* For each data field in SIGNAL_QUEUE_HEADER that was modified, + /* + * For each data field in SIGNAL_QUEUE_HEADER that was modified, * update host memory. */ mb(); /* required for channel synch */ @@ -361,6 +392,15 @@ signalremove_inner(struct visorchannel *channel, u32 queue, void *msg) return true; } +/** + * visorchannel_signalremove() - removes a message from the designated + * channel/queue + * @channel: the channel the message will be removed from + * @queue: the queue the message will be removed from + * @msg: the message to remove + * + * Return: boolean indicating whether the removal succeeded or failed + */ bool visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg) { @@ -379,6 +419,15 @@ visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg) } EXPORT_SYMBOL_GPL(visorchannel_signalremove); +/** + * visorchannel_signalempty() - checks if the designated channel/queue + * contains any messages + * @channel: the channel to query + * @queue: the queue in the channel to query + * + * Return: boolean indicating whether any messages in the designated + * channel/queue are present + */ bool visorchannel_signalempty(struct visorchannel *channel, u32 queue) { @@ -425,7 +474,8 @@ signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg) sig_hdr.num_sent++; - /* For each data field in SIGNAL_QUEUE_HEADER that was modified, + /* + * For each data field in SIGNAL_QUEUE_HEADER that was modified, * update host memory. */ mb(); /* required for channel synch */ @@ -437,6 +487,15 @@ signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg) return true; } +/** + * visorchannel_signalinsert() - inserts a message into the designated + * channel/queue + * @channel: the channel the message will be added to + * @queue: the queue the message will be added to + * @msg: the message to insert + * + * Return: boolean indicating whether the insertion succeeded or failed + */ bool visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg) { -- cgit v0.10.2 From ec17f452f4e9eb279d5dd52966b99c055a450028 Mon Sep 17 00:00:00 2001 From: David Binder <david.binder@unisys.com> Date: Fri, 10 Jun 2016 21:48:18 -0400 Subject: staging: unisys: visorbus: Rectify commenting in visorchipset.c Adds kerneldoc formatting to appropriate functions. Other multi-line comments now use proper formatting. Signed-off-by: David Binder <david.binder@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Acked-By: Neil Horman <nhorman@tuxdriver.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index b5942c6..f8e1fa5 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -78,10 +78,11 @@ visorchipset_release(struct inode *inode, struct file *file) return 0; } -/* When the controlvm channel is idle for at least MIN_IDLE_SECONDS, -* we switch to slow polling mode. As soon as we get a controlvm -* message, we switch back to fast polling mode. -*/ +/* + * When the controlvm channel is idle for at least MIN_IDLE_SECONDS, + * we switch to slow polling mode. As soon as we get a controlvm + * message, we switch back to fast polling mode. + */ #define MIN_IDLE_SECONDS 10 static unsigned long poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; /* when we got our last controlvm message */ @@ -112,7 +113,8 @@ static struct visorchannel *controlvm_channel; /* Manages the request payload in the controlvm channel */ struct visor_controlvm_payload_info { u8 *ptr; /* pointer to base address of payload pool */ - u64 offset; /* offset from beginning of controlvm + u64 offset; /* + * offset from beginning of controlvm * channel to beginning of payload * pool */ u32 bytes; /* number of bytes in payload pool */ @@ -120,15 +122,17 @@ struct visor_controlvm_payload_info { static struct visor_controlvm_payload_info controlvm_payload_info; -/* The following globals are used to handle the scenario where we are unable to - * offload the payload from a controlvm message due to memory requirements. In +/* + * The following globals are used to handle the scenario where we are unable to + * offload the payload from a controlvm message due to memory requirements. In * this scenario, we simply stash the controlvm message, then attempt to * process it again the next time controlvm_periodic_work() runs. */ static struct controlvm_message controlvm_pending_msg; static bool controlvm_pending_msg_valid; -/* This identifies a data buffer that has been received via a controlvm messages +/* + * This identifies a data buffer that has been received via a controlvm messages * in a remote --> local CONTROLVM_TRANSMIT_FILE conversation. */ struct putfile_buffer_entry { @@ -136,13 +140,15 @@ struct putfile_buffer_entry { struct parser_context *parser_ctx; /* points to input data buffer */ }; -/* List of struct putfile_request *, via next_putfile_request member. +/* + * List of struct putfile_request *, via next_putfile_request member. * Each entry in this list identifies an outstanding TRANSMIT_FILE * conversation. */ static LIST_HEAD(putfile_request_list); -/* This describes a buffer and its current state of transfer (e.g., how many +/* + * This describes a buffer and its current state of transfer (e.g., how many * bytes have already been supplied as putfile data, and how many bytes are * remaining) for a putfile_request. */ @@ -154,8 +160,9 @@ struct putfile_active_buffer { }; #define PUTFILE_REQUEST_SIG 0x0906101302281211 -/* This identifies a single remote --> local CONTROLVM_TRANSMIT_FILE - * conversation. Structs of this type are dynamically linked into +/* + * This identifies a single remote --> local CONTROLVM_TRANSMIT_FILE + * conversation. Structs of this type are dynamically linked into * <Putfile_request_list>. */ struct putfile_request { @@ -167,7 +174,8 @@ struct putfile_request { /* link to next struct putfile_request */ struct list_head next_putfile_request; - /* head of putfile_buffer_entry list, which describes the data to be + /* + * head of putfile_buffer_entry list, which describes the data to be * supplied as putfile data; * - this list is added to when controlvm messages come in that supply * file data @@ -183,11 +191,13 @@ struct putfile_request { /* data not yet read within current putfile_buffer_entry */ struct putfile_active_buffer active_buf; - /* <0 = failed, 0 = in-progress, >0 = successful; */ - /* note that this must be set with req_list_lock, and if you set <0, */ - /* it is your responsibility to also free up all of the other objects */ - /* in this struct (like input_buffer_list, active_buf.parser_ctx) */ - /* before releasing the lock */ + /* + * <0 = failed, 0 = in-progress, >0 = successful; + * note that this must be set with req_list_lock, and if you set <0, + * it is your responsibility to also free up all of the other objects + * in this struct (like input_buffer_list, active_buf.parser_ctx) + * before releasing the lock + */ int completion_status; }; @@ -202,9 +212,6 @@ static LIST_HEAD(parahotplug_request_list); static DEFINE_SPINLOCK(parahotplug_request_list_lock); /* lock for above */ static void parahotplug_process_list(void); -/* Manages the info for a CONTROLVM_DUMP_CAPTURESTATE / - * CONTROLVM_REPORTEVENT. - */ static struct visorchipset_busdev_notifiers busdev_notifiers; static void bus_create_response(struct visor_device *p, int response); @@ -226,7 +233,7 @@ static struct visorchipset_busdev_responders busdev_responders = { }; /* info for /dev/visorchipset */ -static dev_t major_dev = -1; /**< indicates major num for device */ +static dev_t major_dev = -1; /*< indicates major num for device */ /* prototypes for attributes */ static ssize_t toolaction_show(struct device *dev, @@ -396,8 +403,9 @@ parser_id_get(struct parser_context *ctx) return phdr->id; } -/** Describes the state from the perspective of which controlvm messages have - * been received for a bus or device. +/* + * Describes the state from the perspective of which controlvm messages have + * been received for a bus or device. */ enum PARSER_WHICH_STRING { @@ -722,14 +730,16 @@ chipset_init(struct controlvm_message *inmsg) chipset_inited = 1; POSTCODE_LINUX_2(CHIPSET_INIT_EXIT_PC, POSTCODE_SEVERITY_INFO); - /* Set features to indicate we support parahotplug (if Command + /* + * Set features to indicate we support parahotplug (if Command * also supports it). */ features = inmsg->cmd.init_chipset. features & ULTRA_CHIPSET_FEATURE_PARA_HOTPLUG; - /* Set the "reply" bit so Command knows this is a + /* + * Set the "reply" bit so Command knows this is a * features-aware driver. */ features |= ULTRA_CHIPSET_FEATURE_REPLY; @@ -920,8 +930,10 @@ bus_epilog(struct visor_device *bus_info, down(¬ifier_lock); if (!bus_info) { - /* relying on a valid passed in response code */ - /* be lazy and re-use msg_hdr for this failure, is this ok?? */ + /* + * relying on a valid passed in response code + * be lazy and re-use msg_hdr for this failure, is this ok?? + */ pmsg_hdr = msg_hdr; goto out_respond_and_unlock; } @@ -984,8 +996,10 @@ device_epilog(struct visor_device *dev_info, down(¬ifier_lock); if (!dev_info) { - /* relying on a valid passed in response code */ - /* be lazy and re-use msg_hdr for this failure, is this ok?? */ + /* + * relying on a valid passed in response code + * be lazy and re-use msg_hdr for this failure, is this ok?? + */ pmsg_hdr = msg_hdr; goto out_respond_and_unlock; } @@ -1031,7 +1045,8 @@ device_epilog(struct visor_device *dev_info, else if (state.alive == segment_state_standby.alive && state.operating == segment_state_standby.operating) { - /* technically this is standby case + /* + * technically this is standby case * where server is lost */ if (notifiers->device_pause) { @@ -1300,11 +1315,19 @@ my_device_destroy(struct controlvm_message *inmsg) inmsg->hdr.flags.response_expected == 1, 1); } -/* When provided with the physical address of the controlvm channel +/** + * initialize_controlvm_payload_info() - init controlvm_payload_info struct + * @phys_addr: the physical address of controlvm channel + * @offset: the offset to payload + * @bytes: the size of the payload in bytes + * @info: the returning valid struct + * + * When provided with the physical address of the controlvm channel * (phys_addr), the offset to the payload area we need to manage * (offset), and the size of this payload area (bytes), fills in the - * controlvm_payload_info struct. Returns true for success or false - * for failure. + * controlvm_payload_info struct. + * + * Return: CONTROLVM_RESP_SUCCESS for success or a negative for failure */ static int initialize_controlvm_payload_info(u64 phys_addr, u64 offset, u32 bytes, @@ -1368,8 +1391,12 @@ initialize_controlvm_payload(void) &controlvm_payload_info); } -/* Send ACTION=online for DEVPATH=/sys/devices/platform/visorchipset. - * Returns CONTROLVM_RESP_xxx code. +/** + * visorchipset_chipset_ready() - sends chipset_ready action + * + * Send ACTION=online for DEVPATH=/sys/devices/platform/visorchipset. + * + * Return: CONTROLVM_RESP_SUCCESS */ static int visorchipset_chipset_ready(void) @@ -1390,8 +1417,12 @@ visorchipset_chipset_selftest(void) return CONTROLVM_RESP_SUCCESS; } -/* Send ACTION=offline for DEVPATH=/sys/devices/platform/visorchipset. - * Returns CONTROLVM_RESP_xxx code. +/** + * visorchipset_chipset_notready() - sends chipset_notready action + * + * Send ACTION=offline for DEVPATH=/sys/devices/platform/visorchipset. + * + * Return: CONTROLVM_RESP_SUCCESS */ static int visorchipset_chipset_notready(void) @@ -1433,8 +1464,13 @@ chipset_notready(struct controlvm_message_header *msg_hdr) controlvm_respond(msg_hdr, rc); } -/* This is your "one-stop" shop for grabbing the next message from the - * CONTROLVM_QUEUE_EVENT queue in the controlvm channel. +/** + * read_controlvm_event() - retreives the next message from the + * CONTROLVM_QUEUE_EVENT queue in the controlvm + * channel + * @msg: pointer to the retrieved message + * + * Return: true if a valid message was retrieved or false otherwise */ static bool read_controlvm_event(struct controlvm_message *msg) @@ -1450,13 +1486,13 @@ read_controlvm_event(struct controlvm_message *msg) } /* - * The general parahotplug flow works as follows. The visorchipset + * The general parahotplug flow works as follows. The visorchipset * driver receives a DEVICE_CHANGESTATE message from Command - * specifying a physical device to enable or disable. The CONTROLVM + * specifying a physical device to enable or disable. The CONTROLVM * message handler calls parahotplug_process_message, which then adds * the message to a global list and kicks off a udev event which * causes a user level script to enable or disable the specified - * device. The udev script then writes to + * device. The udev script then writes to * /proc/visorchipset/parahotplug, which causes parahotplug_proc_write * to get called, at which point the appropriate CONTROLVM message is * retrieved from the list and responded to. @@ -1464,9 +1500,11 @@ read_controlvm_event(struct controlvm_message *msg) #define PARAHOTPLUG_TIMEOUT_MS 2000 -/* - * Generate unique int to match an outstanding CONTROLVM message with a - * udev script /proc response +/** + * parahotplug_next_id() - generate unique int to match an outstanding CONTROLVM + * message with a udev script /proc response + * + * Return: a unique integer value */ static int parahotplug_next_id(void) @@ -1476,9 +1514,12 @@ parahotplug_next_id(void) return atomic_inc_return(&id); } -/* - * Returns the time (in jiffies) when a CONTROLVM message on the list - * should expire -- PARAHOTPLUG_TIMEOUT_MS in the future +/** + * parahotplug_next_expiration() - returns the time (in jiffies) when a + * CONTROLVM message on the list should expire + * -- PARAHOTPLUG_TIMEOUT_MS in the future + * + * Return: expected expiration time (in jiffies) */ static unsigned long parahotplug_next_expiration(void) @@ -1486,9 +1527,13 @@ parahotplug_next_expiration(void) return jiffies + msecs_to_jiffies(PARAHOTPLUG_TIMEOUT_MS); } -/* - * Create a parahotplug_request, which is basically a wrapper for a - * CONTROLVM_MESSAGE that we can stick on a list +/** + * parahotplug_request_create() - create a parahotplug_request, which is + * basically a wrapper for a CONTROLVM_MESSAGE + * that we can stick on a list + * @msg: the message to insert in the request + * + * Return: the request containing the provided message */ static struct parahotplug_request * parahotplug_request_create(struct controlvm_message *msg) @@ -1506,8 +1551,9 @@ parahotplug_request_create(struct controlvm_message *msg) return req; } -/* - * Free a parahotplug_request. +/** + * parahotplug_request_destroy() - free a parahotplug_request + * @req: the request to deallocate */ static void parahotplug_request_destroy(struct parahotplug_request *req) @@ -1515,10 +1561,12 @@ parahotplug_request_destroy(struct parahotplug_request *req) kfree(req); } -/* - * Cause uevent to run the user level script to do the disable/enable - * specified in (the CONTROLVM message in) the specified - * parahotplug_request +/** + * parahotplug_request_kickoff() - initiate parahotplug request + * @req: the request to initiate + * + * Cause uevent to run the user level script to do the disable/enable specified + * in the parahotplug_request. */ static void parahotplug_request_kickoff(struct parahotplug_request *req) @@ -1545,9 +1593,9 @@ parahotplug_request_kickoff(struct parahotplug_request *req) envp); } -/* - * Remove any request from the list that's been on there too long and - * respond with an error. +/** + * parahotplug_process_list() - remove any request from the list that's been on + * there too long and respond with an error */ static void parahotplug_process_list(void) @@ -1576,10 +1624,16 @@ parahotplug_process_list(void) spin_unlock(¶hotplug_request_list_lock); } -/* +/** + * parahotplug_request_complete() - mark request as complete + * @id: the id of the request + * @active: indicates whether the request is assigned to active partition + * * Called from the /proc handler, which means the user script has - * finished the enable/disable. Find the matching identifier, and + * finished the enable/disable. Find the matching identifier, and * respond to the CONTROLVM message with success. + * + * Return: 0 on success or -EINVAL on failure */ static int parahotplug_request_complete(int id, u16 active) @@ -1594,7 +1648,8 @@ parahotplug_request_complete(int id, u16 active) struct parahotplug_request *req = list_entry(pos, struct parahotplug_request, list); if (req->id == id) { - /* Found a match. Remove it from the list and + /* + * Found a match. Remove it from the list and * respond. */ list_del(pos); @@ -1613,8 +1668,10 @@ parahotplug_request_complete(int id, u16 active) return -EINVAL; } -/* - * Enables or disables a PCI device by kicking off a udev script +/** + * parahotplug_process_message() - enables or disables a PCI device by kicking + * off a udev script + * @inmsg: the message indicating whether to enable or disable */ static void parahotplug_process_message(struct controlvm_message *inmsg) @@ -1627,14 +1684,16 @@ parahotplug_process_message(struct controlvm_message *inmsg) return; if (inmsg->cmd.device_change_state.state.active) { - /* For enable messages, just respond with success - * right away. This is a bit of a hack, but there are - * issues with the early enable messages we get (with - * either the udev script not detecting that the device - * is up, or not getting called at all). Fortunately - * the messages that get lost don't matter anyway, as - * devices are automatically enabled at - * initialization. + /* + * For enable messages, just respond with success + * right away. This is a bit of a hack, but there are + * issues with the early enable messages we get (with + * either the udev script not detecting that the device + * is up, or not getting called at all). Fortunately + * the messages that get lost don't matter anyway, as + * + * devices are automatically enabled at + * initialization. */ parahotplug_request_kickoff(req); controlvm_respond_physdev_changestate @@ -1643,11 +1702,12 @@ parahotplug_process_message(struct controlvm_message *inmsg) inmsg->cmd.device_change_state.state); parahotplug_request_destroy(req); } else { - /* For disable messages, add the request to the - * request list before kicking off the udev script. It - * won't get responded to until the script has - * indicated it's done. - */ + /* + * For disable messages, add the request to the + * request list before kicking off the udev script. It + * won't get responded to until the script has + * indicated it's done. + */ spin_lock(¶hotplug_request_list_lock); list_add_tail(&req->list, ¶hotplug_request_list); spin_unlock(¶hotplug_request_list_lock); @@ -1656,8 +1716,12 @@ parahotplug_process_message(struct controlvm_message *inmsg) } } -/* Process a controlvm message. - * Return result: +/** + * handle_command() - process a controlvm message + * @inmsg: the message to process + * @channel_addr: address of the controlvm channel + * + * Return: * false - this function will return false only in the case where the * controlvm message was NOT processed, but processing must be * retried before reading the next controlvm message; a @@ -1665,7 +1729,7 @@ parahotplug_process_message(struct controlvm_message *inmsg) * the allocation of memory in which to copy out controlvm * payload data * true - processing of the controlvm message completed, - * either successfully or with an error. + * either successfully or with an error */ static bool handle_command(struct controlvm_message inmsg, u64 channel_addr) @@ -1684,8 +1748,9 @@ handle_command(struct controlvm_message inmsg, u64 channel_addr) parm_addr = channel_addr + inmsg.hdr.payload_vm_offset; parm_bytes = inmsg.hdr.payload_bytes; - /* Parameter and channel addresses within test messages actually lie - * within our OS-controlled memory. We need to know that, because it + /* + * Parameter and channel addresses within test messages actually lie + * within our OS-controlled memory. We need to know that, because it * makes a difference in how we compute the virtual address. */ if (parm_addr && parm_bytes) { @@ -1726,8 +1791,10 @@ handle_command(struct controlvm_message inmsg, u64 channel_addr) if (cmd->device_change_state.flags.phys_device) { parahotplug_process_message(&inmsg); } else { - /* save the hdr and cmd structures for later use */ - /* when sending back the response to Command */ + /* + * save the hdr and cmd structures for later use + * when sending back the response to Command + */ my_device_changestate(&inmsg); g_devicechangestate_packet = inmsg.cmd; break; @@ -1809,10 +1876,11 @@ controlvm_periodic_work(struct work_struct *work) ; if (!got_command) { if (controlvm_pending_msg_valid) { - /* we throttled processing of a prior - * msg, so try to process it again - * rather than reading a new one - */ + /* + * we throttled processing of a prior + * msg, so try to process it again + * rather than reading a new one + */ inmsg = controlvm_pending_msg; controlvm_pending_msg_valid = false; got_command = true; @@ -1829,12 +1897,13 @@ controlvm_periodic_work(struct work_struct *work) (controlvm_channel))) got_command = read_controlvm_event(&inmsg); else { - /* this is a scenario where throttling - * is required, but probably NOT an - * error...; we stash the current - * controlvm msg so we will attempt to - * reprocess it on our next loop - */ + /* + * this is a scenario where throttling + * is required, but probably NOT an + * error...; we stash the current + * controlvm msg so we will attempt to + * reprocess it on our next loop + */ handle_command_failed = true; controlvm_pending_msg = inmsg; controlvm_pending_msg_valid = true; @@ -1848,10 +1917,11 @@ cleanup: if (time_after(jiffies, most_recent_message_jiffies + (HZ * MIN_IDLE_SECONDS))) { - /* it's been longer than MIN_IDLE_SECONDS since we - * processed our last controlvm message; slow down the - * polling - */ + /* + * it's been longer than MIN_IDLE_SECONDS since we + * processed our last controlvm message; slow down the + * polling + */ if (poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_SLOW) poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW; } else { @@ -2024,9 +2094,18 @@ device_resume_response(struct visor_device *dev_info, int response) dev_info->pending_msg_hdr = NULL; } -/* The parahotplug/devicedisabled interface gets called by our support script +/** + * devicedisabled_store() - disables the hotplug device + * @dev: sysfs interface variable not utilized in this function + * @attr: sysfs interface variable not utilized in this function + * @buf: buffer containing the device id + * @count: the size of the buffer + * + * The parahotplug/devicedisabled interface gets called by our support script * when an SR-IOV device has been shut down. The ID is passed to the script * and then passed back when the device has been removed. + * + * Return: the size of the buffer for success or negative for error */ static ssize_t devicedisabled_store(struct device *dev, struct device_attribute *attr, @@ -2044,9 +2123,18 @@ static ssize_t devicedisabled_store(struct device *dev, return count; } -/* The parahotplug/deviceenabled interface gets called by our support script +/** + * deviceenabled_store() - enables the hotplug device + * @dev: sysfs interface variable not utilized in this function + * @attr: sysfs interface variable not utilized in this function + * @buf: buffer containing the device id + * @count: the size of the buffer + * + * The parahotplug/deviceenabled interface gets called by our support script * when an SR-IOV device has been recovered. The ID is passed to the script * and then passed back when the device has been brought back up. + * + * Return: the size of the buffer for success or negative for error */ static ssize_t deviceenabled_store(struct device *dev, struct device_attribute *attr, -- cgit v0.10.2 From e9b18f3b865e32f927e9597a270e684a6984f0e5 Mon Sep 17 00:00:00 2001 From: David Binder <david.binder@unisys.com> Date: Fri, 10 Jun 2016 21:48:19 -0400 Subject: staging: unisys: visorbus: Move visorbus-unique functions to private header Moves function prototypes that are unique to visorbus from include/visorbus.h to visorbus/visorbus_private.h. Signed-off-by: David Binder <david.binder@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Acked-By: Neil Horman <nhorman@tuxdriver.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/include/visorbus.h b/drivers/staging/unisys/include/visorbus.h index fb53a65..666a04e 100644 --- a/drivers/staging/unisys/include/visorbus.h +++ b/drivers/staging/unisys/include/visorbus.h @@ -187,37 +187,12 @@ int visorbus_write_channel(struct visor_device *dev, void visorbus_enable_channel_interrupts(struct visor_device *dev); void visorbus_disable_channel_interrupts(struct visor_device *dev); -/* Note that for visorchannel_create() - * <channel_bytes> and <guid> arguments may be 0 if we are a channel CLIENT. - * In this case, the values can simply be read from the channel header. - */ -struct visorchannel *visorchannel_create(u64 physaddr, - unsigned long channel_bytes, - gfp_t gfp, uuid_le guid); -struct visorchannel *visorchannel_create_with_lock(u64 physaddr, - unsigned long channel_bytes, - gfp_t gfp, uuid_le guid); -void visorchannel_destroy(struct visorchannel *channel); -int visorchannel_read(struct visorchannel *channel, ulong offset, - void *local, ulong nbytes); -int visorchannel_write(struct visorchannel *channel, ulong offset, - void *local, ulong nbytes); bool visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg); bool visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg); bool visorchannel_signalempty(struct visorchannel *channel, u32 queue); - -u64 visorchannel_get_physaddr(struct visorchannel *channel); -ulong visorchannel_get_nbytes(struct visorchannel *channel); -char *visorchannel_id(struct visorchannel *channel, char *s); -char *visorchannel_zoneid(struct visorchannel *channel, char *s); -u64 visorchannel_get_clientpartition(struct visorchannel *channel); -int visorchannel_set_clientpartition(struct visorchannel *channel, - u64 partition_handle); uuid_le visorchannel_get_uuid(struct visorchannel *channel); -char *visorchannel_uuid_id(uuid_le *guid, char *s); -void __iomem *visorchannel_get_header(struct visorchannel *channel); #define BUS_ROOT_DEVICE UINT_MAX struct visor_device *visorbus_get_device_by_id(u32 bus_no, u32 dev_no, diff --git a/drivers/staging/unisys/visorbus/visorbus_private.h b/drivers/staging/unisys/visorbus/visorbus_private.h index 39edd20..31b5ca9 100644 --- a/drivers/staging/unisys/visorbus/visorbus_private.h +++ b/drivers/staging/unisys/visorbus/visorbus_private.h @@ -65,4 +65,31 @@ visorchipset_register_busdev( /* visorbus init and exit functions */ int visorbus_init(void); void visorbus_exit(void); + +/* Visorchannel access functions */ + +/* Note that for visorchannel_create() + * <channel_bytes> and <guid> arguments may be 0 if we are a channel CLIENT. + * In this case, the values can simply be read from the channel header. + */ +struct visorchannel *visorchannel_create(u64 physaddr, + unsigned long channel_bytes, + gfp_t gfp, uuid_le guid); +struct visorchannel *visorchannel_create_with_lock(u64 physaddr, + unsigned long channel_bytes, + gfp_t gfp, uuid_le guid); +void visorchannel_destroy(struct visorchannel *channel); +int visorchannel_read(struct visorchannel *channel, ulong offset, + void *local, ulong nbytes); +int visorchannel_write(struct visorchannel *channel, ulong offset, + void *local, ulong nbytes); +u64 visorchannel_get_physaddr(struct visorchannel *channel); +ulong visorchannel_get_nbytes(struct visorchannel *channel); +char *visorchannel_id(struct visorchannel *channel, char *s); +char *visorchannel_zoneid(struct visorchannel *channel, char *s); +u64 visorchannel_get_clientpartition(struct visorchannel *channel); +int visorchannel_set_clientpartition(struct visorchannel *channel, + u64 partition_handle); +char *visorchannel_uuid_id(uuid_le *guid, char *s); +void __iomem *visorchannel_get_header(struct visorchannel *channel); #endif diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c index 0ddfe05..fbae66e 100644 --- a/drivers/staging/unisys/visorbus/visorchannel.c +++ b/drivers/staging/unisys/visorbus/visorchannel.c @@ -25,6 +25,7 @@ #include "version.h" #include "visorbus.h" #include "controlvmchannel.h" +#include "visorbus_private.h" #define MYDRVNAME "visorchannel" -- cgit v0.10.2 From eafc6a94e93f642ba0e15fc4593b008c67c0cd10 Mon Sep 17 00:00:00 2001 From: David Binder <david.binder@unisys.com> Date: Fri, 10 Jun 2016 21:48:20 -0400 Subject: staging: unisys: visorbus: rectify kerneldoc comment for struct Fixes the kerneldoc comment for struct visor_device - the struct members were not listed with the appropriate @ prefix. Signed-off-by: David Binder <david.binder@unisys.com> Acked-By: Neil Horman <nhorman@tuxdriver.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/include/visorbus.h b/drivers/staging/unisys/include/visorbus.h index 666a04e..c836c8d 100644 --- a/drivers/staging/unisys/include/visorbus.h +++ b/drivers/staging/unisys/include/visorbus.h @@ -121,33 +121,33 @@ struct visor_driver { /** * struct visor_device - A device type for things "plugged" into the visorbus * bus - * visorchannel: Points to the channel that the device is + * @visorchannel: Points to the channel that the device is * associated with. - * channel_type_guid: Identifies the channel type to the bus driver. - * device: Device struct meant for use by the bus driver + * @channel_type_guid: Identifies the channel type to the bus driver. + * @device: Device struct meant for use by the bus driver * only. - * list_all: Used by the bus driver to enumerate devices. - * timer: Timer fired periodically to do interrupt-type + * @list_all: Used by the bus driver to enumerate devices. + * @timer: Timer fired periodically to do interrupt-type * activity. - * being_removed: Indicates that the device is being removed from + * @being_removed: Indicates that the device is being removed from * the bus. Private bus driver use only. - * visordriver_callback_lock: Used by the bus driver to lock when handling + * @visordriver_callback_lock: Used by the bus driver to lock when handling * channel events. - * pausing: Indicates that a change towards a paused state. + * @pausing: Indicates that a change towards a paused state. * is in progress. Only modified by the bus driver. - * resuming: Indicates that a change towards a running state + * @resuming: Indicates that a change towards a running state * is in progress. Only modified by the bus driver. - * chipset_bus_no: Private field used by the bus driver. - * chipset_dev_no: Private field used the bus driver. - * state: Used to indicate the current state of the + * @chipset_bus_no: Private field used by the bus driver. + * @chipset_dev_no: Private field used the bus driver. + * @state: Used to indicate the current state of the * device. - * inst: Unique GUID for this instance of the device. - * name: Name of the device. - * pending_msg_hdr: For private use by bus driver to respond to + * @inst: Unique GUID for this instance of the device. + * @name: Name of the device. + * @pending_msg_hdr: For private use by bus driver to respond to * hypervisor requests. - * vbus_hdr_info: A pointer to header info. Private use by bus + * @vbus_hdr_info: A pointer to header info. Private use by bus * driver. - * partition_uuid: Indicates client partion id. This should be the + * @partition_uuid: Indicates client partion id. This should be the * same across all visor_devices in the current * guest. Private use by bus driver only. */ -- cgit v0.10.2 From 87241ab85930519a962a567de58d959d3029b419 Mon Sep 17 00:00:00 2001 From: David Binder <david.binder@unisys.com> Date: Fri, 10 Jun 2016 21:48:21 -0400 Subject: staging: unisys: visorbus: Remove notifier-related code from visorbus When this functionality was first implemented, visorchipset and visorbus were separate drivers, which necessitated a registration mechanism for them to communicate. More-recently, visorchipset and visorbus were combined into a single driver, and now exist as separate source files within the same driver, known as 'visorbus'. This eliminated the need for a registration mechanism, but it has remained nevertheless until now. For the sake of simplification, this registration mechanism is now being removed. Signed-off-by: David Binder <david.binder@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <timothy.sell@unisys.com> Acked-By: Neil Horman <nhorman@tuxdriver.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 2468264..c361077 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -119,32 +119,6 @@ struct bus_type visorbus_type = { static long long bus_count; /* number of bus instances */ /* ever-increasing */ -static void chipset_bus_create(struct visor_device *bus_info); -static void chipset_bus_destroy(struct visor_device *bus_info); -static void chipset_device_create(struct visor_device *dev_info); -static void chipset_device_destroy(struct visor_device *dev_info); -static void chipset_device_pause(struct visor_device *dev_info); -static void chipset_device_resume(struct visor_device *dev_info); - -/* - * These functions are implemented herein, and are called by the chipset - * driver to notify us about specific events. - */ -static struct visorchipset_busdev_notifiers chipset_notifiers = { - .bus_create = chipset_bus_create, - .bus_destroy = chipset_bus_destroy, - .device_create = chipset_device_create, - .device_destroy = chipset_device_destroy, - .device_pause = chipset_device_pause, - .device_resume = chipset_device_resume, -}; - -/* - * These functions are implemented in the chipset driver, and we call them - * herein when we want to acknowledge a specific event. - */ -static struct visorchipset_busdev_responders chipset_responders; - /* filled in with info about parent chipset driver when we register with it */ static struct ultra_vbus_deviceinfo chipset_driverinfo; /* filled in with info about this driver, wrt it servicing client busses */ @@ -1171,7 +1145,7 @@ remove_all_visor_devices(void) } } -static void +void chipset_bus_create(struct visor_device *dev) { int rc; @@ -1188,19 +1162,17 @@ chipset_bus_create(struct visor_device *dev) POSTCODE_LINUX_3(CHIPSET_INIT_SUCCESS_PC, bus_no, POSTCODE_SEVERITY_INFO); - if (chipset_responders.bus_create) - (*chipset_responders.bus_create) (dev, rc); + bus_create_response(dev, rc); } -static void +void chipset_bus_destroy(struct visor_device *dev) { remove_bus_instance(dev); - if (chipset_responders.bus_destroy) - (*chipset_responders.bus_destroy)(dev, 0); + bus_destroy_response(dev, 0); } -static void +void chipset_device_create(struct visor_device *dev_info) { int rc; @@ -1211,8 +1183,7 @@ chipset_device_create(struct visor_device *dev_info) POSTCODE_SEVERITY_INFO); rc = create_visor_device(dev_info); - if (chipset_responders.device_create) - chipset_responders.device_create(dev_info, rc); + device_create_response(dev_info, rc); if (rc < 0) POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, @@ -1222,13 +1193,12 @@ chipset_device_create(struct visor_device *dev_info) POSTCODE_SEVERITY_INFO); } -static void +void chipset_device_destroy(struct visor_device *dev_info) { remove_visor_device(dev_info); - if (chipset_responders.device_destroy) - (*chipset_responders.device_destroy) (dev_info, 0); + device_destroy_response(dev_info, 0); } /** @@ -1247,14 +1217,8 @@ pause_state_change_complete(struct visor_device *dev, int status) return; dev->pausing = false; - if (!chipset_responders.device_pause) /* this can never happen! */ - return; - /* Notify the chipset driver that the pause is complete, which - * will presumably want to send some sort of response to the - * initiator. - */ - (*chipset_responders.device_pause) (dev, status); + visorchipset_device_pause_response(dev, status); } /** @@ -1273,15 +1237,13 @@ resume_state_change_complete(struct visor_device *dev, int status) return; dev->resuming = false; - if (!chipset_responders.device_resume) /* this can never happen! */ - return; /* * Notify the chipset driver that the resume is complete, * which will presumably want to send some sort of response to * the initiator. */ - (*chipset_responders.device_resume) (dev, status); + device_resume_response(dev, status); } /** @@ -1303,9 +1265,9 @@ initiate_chipset_device_pause_resume(struct visor_device *dev, bool is_pause) void (*notify_func)(struct visor_device *dev, int response) = NULL; if (is_pause) - notify_func = chipset_responders.device_pause; + notify_func = visorchipset_device_pause_response; else - notify_func = chipset_responders.device_resume; + notify_func = device_resume_response; if (!notify_func) return; @@ -1369,7 +1331,7 @@ initiate_chipset_device_pause_resume(struct visor_device *dev, bool is_pause) * that device. Success/failure result is returned asynchronously * via a callback function; see pause_state_change_complete(). */ -static void +void chipset_device_pause(struct visor_device *dev_info) { initiate_chipset_device_pause_resume(dev_info, true); @@ -1383,7 +1345,7 @@ chipset_device_pause(struct visor_device *dev_info) * that device. Success/failure result is returned asynchronously * via a callback function; see resume_state_change_complete(). */ -static void +void chipset_device_resume(struct visor_device *dev_info) { initiate_chipset_device_pause_resume(dev_info, false); @@ -1405,12 +1367,9 @@ visorbus_init(void) goto error; } - /* This enables us to receive notifications when devices appear for - * which this service partition is to be a server for. - */ - visorchipset_register_busdev(&chipset_notifiers, - &chipset_responders, - &chipset_driverinfo); + bus_device_info_init(&chipset_driverinfo, + "chipset", "visorchipset", + VERSION, NULL); return 0; @@ -1424,7 +1383,6 @@ visorbus_exit(void) { struct list_head *listentry, *listtmp; - visorchipset_register_busdev(NULL, NULL, NULL); remove_all_visor_devices(); list_for_each_safe(listentry, listtmp, &list_all_bus_instances) { diff --git a/drivers/staging/unisys/visorbus/visorbus_private.h b/drivers/staging/unisys/visorbus/visorbus_private.h index 31b5ca9..3b5a8f2 100644 --- a/drivers/staging/unisys/visorbus/visorbus_private.h +++ b/drivers/staging/unisys/visorbus/visorbus_private.h @@ -23,44 +23,20 @@ #include "vbusdeviceinfo.h" #include "vbushelper.h" -/* These functions will be called from within visorchipset when certain - * events happen. (The implementation of these functions is outside of - * visorchipset.) - */ -struct visorchipset_busdev_notifiers { - void (*bus_create)(struct visor_device *bus_info); - void (*bus_destroy)(struct visor_device *bus_info); - void (*device_create)(struct visor_device *bus_info); - void (*device_destroy)(struct visor_device *bus_info); - void (*device_pause)(struct visor_device *bus_info); - void (*device_resume)(struct visor_device *bus_info); -}; - -/* These functions live inside visorchipset, and will be called to indicate - * responses to specific events (by code outside of visorchipset). - * For now, the value for each response is simply either: - * 0 = it worked - * -1 = it failed - */ -struct visorchipset_busdev_responders { - void (*bus_create)(struct visor_device *p, int response); - void (*bus_destroy)(struct visor_device *p, int response); - void (*device_create)(struct visor_device *p, int response); - void (*device_destroy)(struct visor_device *p, int response); - void (*device_pause)(struct visor_device *p, int response); - void (*device_resume)(struct visor_device *p, int response); -}; +void chipset_bus_create(struct visor_device *bus_info); +void chipset_bus_destroy(struct visor_device *bus_info); +void chipset_device_create(struct visor_device *dev_info); +void chipset_device_destroy(struct visor_device *dev_info); +void chipset_device_pause(struct visor_device *dev_info); +void chipset_device_resume(struct visor_device *dev_info); -/** Register functions (in the bus driver) to get called by visorchipset - * whenever a bus or device appears for which this guest is to be the - * client for. visorchipset will fill in <responders>, to indicate - * functions the bus driver should call to indicate message responses. - */ -void -visorchipset_register_busdev( - struct visorchipset_busdev_notifiers *notifiers, - struct visorchipset_busdev_responders *responders, - struct ultra_vbus_deviceinfo *driver_info); +void bus_create_response(struct visor_device *p, int response); +void bus_destroy_response(struct visor_device *p, int response); +void device_create_response(struct visor_device *p, int response); +void device_destroy_response(struct visor_device *p, int response); +void device_resume_response(struct visor_device *p, int response); +void visorchipset_device_pause_response(struct visor_device *p, + int response); /* visorbus init and exit functions */ int visorbus_init(void); diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index f8e1fa5..ea548df 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -87,7 +87,6 @@ visorchipset_release(struct inode *inode, struct file *file) static unsigned long poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; /* when we got our last controlvm message */ static unsigned long most_recent_message_jiffies; -static int visorbusregistered; struct parser_context { unsigned long allocbytes; @@ -99,7 +98,6 @@ struct parser_context { }; static struct delayed_work periodic_controlvm_work; -static DEFINE_SEMAPHORE(notifier_lock); static struct cdev file_cdev; static struct visorchannel **file_controlvm_channel; @@ -212,26 +210,6 @@ static LIST_HEAD(parahotplug_request_list); static DEFINE_SPINLOCK(parahotplug_request_list_lock); /* lock for above */ static void parahotplug_process_list(void); -static struct visorchipset_busdev_notifiers busdev_notifiers; - -static void bus_create_response(struct visor_device *p, int response); -static void bus_destroy_response(struct visor_device *p, int response); -static void device_create_response(struct visor_device *p, int response); -static void device_destroy_response(struct visor_device *p, int response); -static void device_resume_response(struct visor_device *p, int response); - -static void visorchipset_device_pause_response(struct visor_device *p, - int response); - -static struct visorchipset_busdev_responders busdev_responders = { - .bus_create = bus_create_response, - .bus_destroy = bus_destroy_response, - .device_create = device_create_response, - .device_destroy = device_destroy_response, - .device_pause = visorchipset_device_pause_response, - .device_resume = device_resume_response, -}; - /* info for /dev/visorchipset */ static dev_t major_dev = -1; /*< indicates major num for device */ @@ -691,30 +669,6 @@ struct visor_device *visorbus_get_device_by_id(u32 bus_no, u32 dev_no, return vdev; } -void -visorchipset_register_busdev( - struct visorchipset_busdev_notifiers *notifiers, - struct visorchipset_busdev_responders *responders, - struct ultra_vbus_deviceinfo *driver_info) -{ - down(¬ifier_lock); - if (!notifiers) { - memset(&busdev_notifiers, 0, - sizeof(busdev_notifiers)); - visorbusregistered = 0; /* clear flag */ - } else { - busdev_notifiers = *notifiers; - visorbusregistered = 1; /* set flag */ - } - if (responders) - *responders = busdev_responders; - if (driver_info) - bus_device_info_init(driver_info, "chipset", "visorchipset", - VERSION, NULL); - - up(¬ifier_lock); -} - static void chipset_init(struct controlvm_message *inmsg) { @@ -927,22 +881,20 @@ bus_epilog(struct visor_device *bus_info, { struct controlvm_message_header *pmsg_hdr = NULL; - down(¬ifier_lock); - if (!bus_info) { /* * relying on a valid passed in response code * be lazy and re-use msg_hdr for this failure, is this ok?? */ pmsg_hdr = msg_hdr; - goto out_respond_and_unlock; + goto out_respond; } if (bus_info->pending_msg_hdr) { /* only non-NULL if dev is still waiting on a response */ response = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT; pmsg_hdr = bus_info->pending_msg_hdr; - goto out_respond_and_unlock; + goto out_respond; } if (need_response) { @@ -951,7 +903,7 @@ bus_epilog(struct visor_device *bus_info, POSTCODE_LINUX_4(MALLOC_FAILURE_PC, cmd, bus_info->chipset_bus_no, POSTCODE_SEVERITY_ERR); - goto out_unlock; + return; } memcpy(pmsg_hdr, msg_hdr, @@ -962,25 +914,16 @@ bus_epilog(struct visor_device *bus_info, if (response == CONTROLVM_RESP_SUCCESS) { switch (cmd) { case CONTROLVM_BUS_CREATE: - if (busdev_notifiers.bus_create) { - (*busdev_notifiers.bus_create) (bus_info); - goto out_unlock; - } + chipset_bus_create(bus_info); break; case CONTROLVM_BUS_DESTROY: - if (busdev_notifiers.bus_destroy) { - (*busdev_notifiers.bus_destroy) (bus_info); - goto out_unlock; - } + chipset_bus_destroy(bus_info); break; } } -out_respond_and_unlock: +out_respond: bus_responder(cmd, pmsg_hdr, response); - -out_unlock: - up(¬ifier_lock); } static void @@ -989,33 +932,29 @@ device_epilog(struct visor_device *dev_info, struct controlvm_message_header *msg_hdr, int response, bool need_response, bool for_visorbus) { - struct visorchipset_busdev_notifiers *notifiers; struct controlvm_message_header *pmsg_hdr = NULL; - notifiers = &busdev_notifiers; - - down(¬ifier_lock); if (!dev_info) { /* * relying on a valid passed in response code * be lazy and re-use msg_hdr for this failure, is this ok?? */ pmsg_hdr = msg_hdr; - goto out_respond_and_unlock; + goto out_respond; } if (dev_info->pending_msg_hdr) { /* only non-NULL if dev is still waiting on a response */ response = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT; pmsg_hdr = dev_info->pending_msg_hdr; - goto out_respond_and_unlock; + goto out_respond; } if (need_response) { pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL); if (!pmsg_hdr) { response = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED; - goto out_respond_and_unlock; + goto out_respond; } memcpy(pmsg_hdr, msg_hdr, @@ -1026,20 +965,14 @@ device_epilog(struct visor_device *dev_info, if (response >= 0) { switch (cmd) { case CONTROLVM_DEVICE_CREATE: - if (notifiers->device_create) { - (*notifiers->device_create) (dev_info); - goto out_unlock; - } + chipset_device_create(dev_info); break; case CONTROLVM_DEVICE_CHANGESTATE: /* ServerReady / ServerRunning / SegmentStateRunning */ if (state.alive == segment_state_running.alive && state.operating == segment_state_running.operating) { - if (notifiers->device_resume) { - (*notifiers->device_resume) (dev_info); - goto out_unlock; - } + chipset_device_resume(dev_info); } /* ServerNotReady / ServerLost / SegmentStateStandby */ else if (state.alive == segment_state_standby.alive && @@ -1049,26 +982,17 @@ device_epilog(struct visor_device *dev_info, * technically this is standby case * where server is lost */ - if (notifiers->device_pause) { - (*notifiers->device_pause) (dev_info); - goto out_unlock; - } + chipset_device_pause(dev_info); } break; case CONTROLVM_DEVICE_DESTROY: - if (notifiers->device_destroy) { - (*notifiers->device_destroy) (dev_info); - goto out_unlock; - } + chipset_device_destroy(dev_info); break; } } -out_respond_and_unlock: +out_respond: device_responder(cmd, pmsg_hdr, response); - -out_unlock: - up(¬ifier_lock); } static void @@ -1866,10 +1790,6 @@ controlvm_periodic_work(struct work_struct *work) bool got_command = false; bool handle_command_failed = false; - /* make sure visorbus server is registered for controlvm callbacks */ - if (visorchipset_visorbusregwait && !visorbusregistered) - goto cleanup; - while (visorchannel_signalremove(controlvm_channel, CONTROLVM_QUEUE_RESPONSE, &inmsg)) @@ -1913,8 +1833,6 @@ controlvm_periodic_work(struct work_struct *work) /* parahotplug_worker */ parahotplug_process_list(); -cleanup: - if (time_after(jiffies, most_recent_message_jiffies + (HZ * MIN_IDLE_SECONDS))) { /* @@ -1941,13 +1859,6 @@ setup_crash_devices_work_queue(struct work_struct *work) u32 local_crash_msg_offset; u16 local_crash_msg_count; - /* make sure visorbus is registered for controlvm callbacks */ - if (visorchipset_visorbusregwait && !visorbusregistered) { - poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW; - schedule_delayed_work(&periodic_controlvm_work, poll_jiffies); - return; - } - POSTCODE_LINUX_2(CRASH_DEV_ENTRY_PC, POSTCODE_SEVERITY_INFO); /* send init chipset msg */ @@ -2025,7 +1936,7 @@ setup_crash_devices_work_queue(struct work_struct *work) POSTCODE_LINUX_2(CRASH_DEV_EXIT_PC, POSTCODE_SEVERITY_INFO); } -static void +void bus_create_response(struct visor_device *bus_info, int response) { if (response >= 0) @@ -2038,7 +1949,7 @@ bus_create_response(struct visor_device *bus_info, int response) bus_info->pending_msg_hdr = NULL; } -static void +void bus_destroy_response(struct visor_device *bus_info, int response) { bus_responder(CONTROLVM_BUS_DESTROY, bus_info->pending_msg_hdr, @@ -2048,7 +1959,7 @@ bus_destroy_response(struct visor_device *bus_info, int response) bus_info->pending_msg_hdr = NULL; } -static void +void device_create_response(struct visor_device *dev_info, int response) { if (response >= 0) @@ -2061,7 +1972,7 @@ device_create_response(struct visor_device *dev_info, int response) dev_info->pending_msg_hdr = NULL; } -static void +void device_destroy_response(struct visor_device *dev_info, int response) { device_responder(CONTROLVM_DEVICE_DESTROY, dev_info->pending_msg_hdr, @@ -2071,7 +1982,7 @@ device_destroy_response(struct visor_device *dev_info, int response) dev_info->pending_msg_hdr = NULL; } -static void +void visorchipset_device_pause_response(struct visor_device *dev_info, int response) { @@ -2083,7 +1994,7 @@ visorchipset_device_pause_response(struct visor_device *dev_info, dev_info->pending_msg_hdr = NULL; } -static void +void device_resume_response(struct visor_device *dev_info, int response) { device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE, @@ -2290,7 +2201,6 @@ visorchipset_init(struct acpi_device *acpi_device) if (!addr) goto error; - memset(&busdev_notifiers, 0, sizeof(busdev_notifiers)); memset(&controlvm_payload_info, 0, sizeof(controlvm_payload_info)); controlvm_channel = visorchannel_create_with_lock(addr, 0, -- cgit v0.10.2 From ea3a5aafe0fbd2d10090ea9f0695d8700f89190b Mon Sep 17 00:00:00 2001 From: David Binder <david.binder@unisys.com> Date: Fri, 10 Jun 2016 21:48:22 -0400 Subject: staging: unisys: visorbus: Rename function to follow existing convention Renames visorchipset_device_pause_response to device_pause_response, thereby following the convention that other responder functions follow. Signed-off-by: David Binder <david.binder@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Acked-By: Neil Horman <nhorman@tuxdriver.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index c361077..293532f 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -1218,7 +1218,7 @@ pause_state_change_complete(struct visor_device *dev, int status) dev->pausing = false; - visorchipset_device_pause_response(dev, status); + device_pause_response(dev, status); } /** @@ -1265,7 +1265,7 @@ initiate_chipset_device_pause_resume(struct visor_device *dev, bool is_pause) void (*notify_func)(struct visor_device *dev, int response) = NULL; if (is_pause) - notify_func = visorchipset_device_pause_response; + notify_func = device_pause_response; else notify_func = device_resume_response; if (!notify_func) diff --git a/drivers/staging/unisys/visorbus/visorbus_private.h b/drivers/staging/unisys/visorbus/visorbus_private.h index 3b5a8f2..a7b1d4f 100644 --- a/drivers/staging/unisys/visorbus/visorbus_private.h +++ b/drivers/staging/unisys/visorbus/visorbus_private.h @@ -35,8 +35,7 @@ void bus_destroy_response(struct visor_device *p, int response); void device_create_response(struct visor_device *p, int response); void device_destroy_response(struct visor_device *p, int response); void device_resume_response(struct visor_device *p, int response); -void visorchipset_device_pause_response(struct visor_device *p, - int response); +void device_pause_response(struct visor_device *p, int response); /* visorbus init and exit functions */ int visorbus_init(void); diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index ea548df..0b4a138 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -1983,8 +1983,8 @@ device_destroy_response(struct visor_device *dev_info, int response) } void -visorchipset_device_pause_response(struct visor_device *dev_info, - int response) +device_pause_response(struct visor_device *dev_info, + int response) { device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE, dev_info, response, -- cgit v0.10.2 From 90bb5c1f27d2af7e0a8430c58fa83f8d910a9e44 Mon Sep 17 00:00:00 2001 From: Tim Sell <Timothy.Sell@unisys.com> Date: Fri, 10 Jun 2016 21:48:23 -0400 Subject: staging: unisys: visorbus: fix visorbus_private.h comments This patch ONLY touches comment lines, i.e., NO executable code is affected. Comments were fixed in visorbus_private.h: * Minor typos were corrected. * Useless comments were removed. Signed-off-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Acked-By: Neil Horman <nhorman@tuxdriver.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorbus_private.h b/drivers/staging/unisys/visorbus/visorbus_private.h index a7b1d4f..3f6ad52 100644 --- a/drivers/staging/unisys/visorbus/visorbus_private.h +++ b/drivers/staging/unisys/visorbus/visorbus_private.h @@ -37,16 +37,11 @@ void device_destroy_response(struct visor_device *p, int response); void device_resume_response(struct visor_device *p, int response); void device_pause_response(struct visor_device *p, int response); -/* visorbus init and exit functions */ int visorbus_init(void); void visorbus_exit(void); -/* Visorchannel access functions */ +/* visorchannel access functions */ -/* Note that for visorchannel_create() - * <channel_bytes> and <guid> arguments may be 0 if we are a channel CLIENT. - * In this case, the values can simply be read from the channel header. - */ struct visorchannel *visorchannel_create(u64 physaddr, unsigned long channel_bytes, gfp_t gfp, uuid_le guid); -- cgit v0.10.2 From 64088bd476be1a7abb6167f8fee4f0aa4d87598d Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Fri, 10 Jun 2016 21:48:24 -0400 Subject: staging: unisys: Move vbushelper.h to visorbus directory Only visorbus needs this header file so move it to visorbus directory. Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Acked-By: Neil Horman <nhorman@tuxdriver.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/include/vbushelper.h b/drivers/staging/unisys/include/vbushelper.h deleted file mode 100644 index f1b6aac..0000000 --- a/drivers/staging/unisys/include/vbushelper.h +++ /dev/null @@ -1,46 +0,0 @@ -/* vbushelper.h - * - * Copyright (C) 2011 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#ifndef __VBUSHELPER_H__ -#define __VBUSHELPER_H__ - -/* TARGET_HOSTNAME specified as -DTARGET_HOSTNAME=\"thename\" on the - * command line - */ - -#define TARGET_HOSTNAME "linuxguest" - -static inline void bus_device_info_init( - struct ultra_vbus_deviceinfo *bus_device_info_ptr, - const char *dev_type, const char *drv_name, - const char *ver, const char *ver_tag) -{ - memset(bus_device_info_ptr, 0, sizeof(struct ultra_vbus_deviceinfo)); - snprintf(bus_device_info_ptr->devtype, - sizeof(bus_device_info_ptr->devtype), - "%s", (dev_type) ? dev_type : "unknownType"); - snprintf(bus_device_info_ptr->drvname, - sizeof(bus_device_info_ptr->drvname), - "%s", (drv_name) ? drv_name : "unknownDriver"); - snprintf(bus_device_info_ptr->infostrs, - sizeof(bus_device_info_ptr->infostrs), "%s\t%s\t%s", - (ver) ? ver : "unknownVer", - (ver_tag) ? ver_tag : "unknownVerTag", - TARGET_HOSTNAME); -} - -#endif diff --git a/drivers/staging/unisys/visorbus/vbushelper.h b/drivers/staging/unisys/visorbus/vbushelper.h new file mode 100644 index 0000000..f1b6aac --- /dev/null +++ b/drivers/staging/unisys/visorbus/vbushelper.h @@ -0,0 +1,46 @@ +/* vbushelper.h + * + * Copyright (C) 2011 - 2013 UNISYS CORPORATION + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + */ + +#ifndef __VBUSHELPER_H__ +#define __VBUSHELPER_H__ + +/* TARGET_HOSTNAME specified as -DTARGET_HOSTNAME=\"thename\" on the + * command line + */ + +#define TARGET_HOSTNAME "linuxguest" + +static inline void bus_device_info_init( + struct ultra_vbus_deviceinfo *bus_device_info_ptr, + const char *dev_type, const char *drv_name, + const char *ver, const char *ver_tag) +{ + memset(bus_device_info_ptr, 0, sizeof(struct ultra_vbus_deviceinfo)); + snprintf(bus_device_info_ptr->devtype, + sizeof(bus_device_info_ptr->devtype), + "%s", (dev_type) ? dev_type : "unknownType"); + snprintf(bus_device_info_ptr->drvname, + sizeof(bus_device_info_ptr->drvname), + "%s", (drv_name) ? drv_name : "unknownDriver"); + snprintf(bus_device_info_ptr->infostrs, + sizeof(bus_device_info_ptr->infostrs), "%s\t%s\t%s", + (ver) ? ver : "unknownVer", + (ver_tag) ? ver_tag : "unknownVerTag", + TARGET_HOSTNAME); +} + +#endif -- cgit v0.10.2 From 24ce1b66619c499f5913eac5debf9170f7a9dcc3 Mon Sep 17 00:00:00 2001 From: Tim Sell <Timothy.Sell@unisys.com> Date: Fri, 10 Jun 2016 21:48:25 -0400 Subject: staging: unisys: visorinput: ensure proper locking wrt creation & ints Ensure we properly lock between visorinput_channel_interrupt(), visorinput_open(), and devdata_create(). We now guarantee that: * interrupts will be disabled and remain disabled during device creation, by setting 'paused = true' across device creation * we canNOT get into visorinput_open() until the device structure is totally initialized, by delaying the input_register_device() until the end of device initialization We also now ensure that lock_visor_dev is held across updates of devdata state, to ensure state consistency. Signed-off-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Acked-By: Neil Horman <nhorman@tuxdriver.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorinput/visorinput.c b/drivers/staging/unisys/visorinput/visorinput.c index f633985..c13e698 100644 --- a/drivers/staging/unisys/visorinput/visorinput.c +++ b/drivers/staging/unisys/visorinput/visorinput.c @@ -277,16 +277,16 @@ out_unlock: } /* - * register_client_keyboard() initializes and returns a Linux input node that + * setup_client_keyboard() initializes and returns a Linux input node that * we can use to deliver keyboard inputs to Linux. We of course do this when * we see keyboard inputs coming in on a keyboard channel. */ static struct input_dev * -register_client_keyboard(void *devdata, /* opaque on purpose */ - unsigned char *keycode_table) +setup_client_keyboard(void *devdata, /* opaque on purpose */ + unsigned char *keycode_table) { - int i, error; + int i; struct input_dev *visorinput_dev; visorinput_dev = input_allocate_device(); @@ -320,18 +320,12 @@ register_client_keyboard(void *devdata, /* opaque on purpose */ visorinput_dev->close = visorinput_close; input_set_drvdata(visorinput_dev, devdata); /* pre input_register! */ - error = input_register_device(visorinput_dev); - if (error) { - input_free_device(visorinput_dev); - return NULL; - } return visorinput_dev; } static struct input_dev * -register_client_mouse(void *devdata /* opaque on purpose */) +setup_client_mouse(void *devdata /* opaque on purpose */) { - int error; struct input_dev *visorinput_dev = NULL; int xres, yres; struct fb_info *fb0; @@ -366,13 +360,6 @@ register_client_mouse(void *devdata /* opaque on purpose */) visorinput_dev->open = visorinput_open; visorinput_dev->close = visorinput_close; input_set_drvdata(visorinput_dev, devdata); /* pre input_register! */ - - error = input_register_device(visorinput_dev); - if (error) { - input_free_device(visorinput_dev); - return NULL; - } - input_set_capability(visorinput_dev, EV_REL, REL_WHEEL); return visorinput_dev; @@ -390,9 +377,19 @@ devdata_create(struct visor_device *dev, enum visorinput_device_type devtype) devdata = kzalloc(sizeof(*devdata) + extra_bytes, GFP_KERNEL); if (!devdata) return NULL; + init_rwsem(&devdata->lock_visor_dev); + down_write(&devdata->lock_visor_dev); devdata->dev = dev; /* + * visorinput_open() can be called as soon as input_register_device() + * happens, and that will enable channel interrupts. Setting paused + * prevents us from getting into visorinput_channel_interrupt() prior + * to the device structure being totally initialized. + */ + devdata->paused = true; + + /* * This is an input device in a client guest partition, * so we need to create whatever input nodes are necessary to * deliver our inputs to the guest OS. @@ -404,23 +401,49 @@ devdata_create(struct visor_device *dev, enum visorinput_device_type devtype) KEYCODE_TABLE_BYTES); memcpy(devdata->keycode_table + KEYCODE_TABLE_BYTES, visorkbd_ext_keycode, KEYCODE_TABLE_BYTES); - devdata->visorinput_dev = register_client_keyboard + devdata->visorinput_dev = setup_client_keyboard (devdata, devdata->keycode_table); if (!devdata->visorinput_dev) goto cleanups_register; break; case visorinput_mouse: - devdata->visorinput_dev = register_client_mouse(devdata); + devdata->visorinput_dev = setup_client_mouse(devdata); if (!devdata->visorinput_dev) goto cleanups_register; break; } - init_rwsem(&devdata->lock_visor_dev); + dev_set_drvdata(&dev->device, devdata); + up_write(&devdata->lock_visor_dev); + + /* + * Device struct is completely set up now, with the exception of + * visorinput_dev being registered. + * We need to unlock before we register the device, because this + * can cause an on-stack call of visorinput_open(), which would + * deadlock if we had the lock. + */ + if (input_register_device(devdata->visorinput_dev)) { + input_free_device(devdata->visorinput_dev); + goto err_kfree_devdata; + } + + down_write(&devdata->lock_visor_dev); + /* + * Establish calls to visorinput_channel_interrupt() if that is + * the desired state that we've kept track of in interrupts_enabled + * while the device was being created. + */ + devdata->paused = false; + if (devdata->interrupts_enabled) + visorbus_enable_channel_interrupts(dev); + up_write(&devdata->lock_visor_dev); return devdata; cleanups_register: + up_write(&devdata->lock_visor_dev); +err_kfree_devdata: kfree(devdata); return NULL; } @@ -428,7 +451,6 @@ cleanups_register: static int visorinput_probe(struct visor_device *dev) { - struct visorinput_devdata *devdata = NULL; uuid_le guid; enum visorinput_device_type devtype; @@ -439,10 +461,9 @@ visorinput_probe(struct visor_device *dev) devtype = visorinput_keyboard; else return -ENODEV; - devdata = devdata_create(dev, devtype); - if (!devdata) + visorbus_disable_channel_interrupts(dev); + if (!devdata_create(dev, devtype)) return -ENOMEM; - dev_set_drvdata(&dev->device, devdata); return 0; } @@ -461,6 +482,7 @@ visorinput_remove(struct visor_device *dev) if (!devdata) return; + down_write(&devdata->lock_visor_dev); visorbus_disable_channel_interrupts(dev); /* @@ -469,6 +491,8 @@ visorinput_remove(struct visor_device *dev) */ dev_set_drvdata(&dev->device, NULL); + up_write(&devdata->lock_visor_dev); + unregister_client_input(devdata->visorinput_dev); kfree(devdata); } -- cgit v0.10.2 From 8dfb8fdbd2d1dd4facef6eef24a26b6bc1b33191 Mon Sep 17 00:00:00 2001 From: Tim Sell <Timothy.Sell@unisys.com> Date: Fri, 10 Jun 2016 21:48:26 -0400 Subject: staging: unisys: visorinput: make lock_visor_dev a mutex Since lock_visor_dev is a binary semaphore it makes more sense to use a mutex lock. Signed-off-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Acked-By: Neil Horman <nhorman@tuxdriver.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorinput/visorinput.c b/drivers/staging/unisys/visorinput/visorinput.c index c13e698..2aff945 100644 --- a/drivers/staging/unisys/visorinput/visorinput.c +++ b/drivers/staging/unisys/visorinput/visorinput.c @@ -63,7 +63,7 @@ enum visorinput_device_type { */ struct visorinput_devdata { struct visor_device *dev; - struct rw_semaphore lock_visor_dev; /* lock for dev */ + struct mutex lock_visor_dev; /* lock for dev */ struct input_dev *visorinput_dev; bool paused; bool interrupts_enabled; @@ -236,14 +236,14 @@ static int visorinput_open(struct input_dev *visorinput_dev) * interrupts should be enabled so when we resume, interrupts * will really be enabled. */ - down_write(&devdata->lock_visor_dev); + mutex_lock(&devdata->lock_visor_dev); devdata->interrupts_enabled = true; if (devdata->paused) goto out_unlock; visorbus_enable_channel_interrupts(devdata->dev); out_unlock: - up_write(&devdata->lock_visor_dev); + mutex_unlock(&devdata->lock_visor_dev); return 0; } @@ -266,14 +266,14 @@ static void visorinput_close(struct input_dev *visorinput_dev) * not re-enable them. */ - down_write(&devdata->lock_visor_dev); + mutex_lock(&devdata->lock_visor_dev); devdata->interrupts_enabled = false; if (devdata->paused) goto out_unlock; visorbus_disable_channel_interrupts(devdata->dev); out_unlock: - up_write(&devdata->lock_visor_dev); + mutex_unlock(&devdata->lock_visor_dev); } /* @@ -377,8 +377,8 @@ devdata_create(struct visor_device *dev, enum visorinput_device_type devtype) devdata = kzalloc(sizeof(*devdata) + extra_bytes, GFP_KERNEL); if (!devdata) return NULL; - init_rwsem(&devdata->lock_visor_dev); - down_write(&devdata->lock_visor_dev); + mutex_init(&devdata->lock_visor_dev); + mutex_lock(&devdata->lock_visor_dev); devdata->dev = dev; /* @@ -414,7 +414,7 @@ devdata_create(struct visor_device *dev, enum visorinput_device_type devtype) } dev_set_drvdata(&dev->device, devdata); - up_write(&devdata->lock_visor_dev); + mutex_unlock(&devdata->lock_visor_dev); /* * Device struct is completely set up now, with the exception of @@ -428,7 +428,7 @@ devdata_create(struct visor_device *dev, enum visorinput_device_type devtype) goto err_kfree_devdata; } - down_write(&devdata->lock_visor_dev); + mutex_lock(&devdata->lock_visor_dev); /* * Establish calls to visorinput_channel_interrupt() if that is * the desired state that we've kept track of in interrupts_enabled @@ -437,12 +437,12 @@ devdata_create(struct visor_device *dev, enum visorinput_device_type devtype) devdata->paused = false; if (devdata->interrupts_enabled) visorbus_enable_channel_interrupts(dev); - up_write(&devdata->lock_visor_dev); + mutex_unlock(&devdata->lock_visor_dev); return devdata; cleanups_register: - up_write(&devdata->lock_visor_dev); + mutex_unlock(&devdata->lock_visor_dev); err_kfree_devdata: kfree(devdata); return NULL; @@ -482,7 +482,7 @@ visorinput_remove(struct visor_device *dev) if (!devdata) return; - down_write(&devdata->lock_visor_dev); + mutex_lock(&devdata->lock_visor_dev); visorbus_disable_channel_interrupts(dev); /* @@ -491,7 +491,7 @@ visorinput_remove(struct visor_device *dev) */ dev_set_drvdata(&dev->device, NULL); - up_write(&devdata->lock_visor_dev); + mutex_unlock(&devdata->lock_visor_dev); unregister_client_input(devdata->visorinput_dev); kfree(devdata); @@ -671,7 +671,7 @@ visorinput_pause(struct visor_device *dev, goto out; } - down_write(&devdata->lock_visor_dev); + mutex_lock(&devdata->lock_visor_dev); if (devdata->paused) { rc = -EBUSY; goto out_locked; @@ -688,7 +688,7 @@ visorinput_pause(struct visor_device *dev, complete_func(dev, 0); rc = 0; out_locked: - up_write(&devdata->lock_visor_dev); + mutex_unlock(&devdata->lock_visor_dev); out: return rc; } @@ -704,7 +704,7 @@ visorinput_resume(struct visor_device *dev, rc = -ENODEV; goto out; } - down_write(&devdata->lock_visor_dev); + mutex_lock(&devdata->lock_visor_dev); if (!devdata->paused) { rc = -EBUSY; goto out_locked; @@ -722,7 +722,7 @@ visorinput_resume(struct visor_device *dev, rc = 0; out_locked: - up_write(&devdata->lock_visor_dev); + mutex_unlock(&devdata->lock_visor_dev); out: return rc; } -- cgit v0.10.2 From 5f62eab04ab7d78afd8acf00c48a7a1539794e1f Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 17 Aug 2016 15:43:32 +0200 Subject: greybus: es2: fix memory leak in probe error path In case a bulk-in transfer-buffer allocation failed during probe, we'd currently leak the corresponding URB. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 7f46f2a..8803bc9 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -1623,6 +1623,8 @@ static int ap_probe(struct usb_interface *interface, retval = -ENOMEM; goto error; } + cport_in->urb[i] = urb; + buffer = kmalloc(ES2_GBUF_MSG_SIZE_MAX, GFP_KERNEL); if (!buffer) { retval = -ENOMEM; @@ -1634,7 +1636,7 @@ static int ap_probe(struct usb_interface *interface, cport_in->endpoint), buffer, ES2_GBUF_MSG_SIZE_MAX, cport_in_callback, hd); - cport_in->urb[i] = urb; + cport_in->buffer[i] = buffer; } } @@ -1649,6 +1651,8 @@ static int ap_probe(struct usb_interface *interface, retval = -ENOMEM; goto error; } + es2->arpc_urb[i] = urb; + buffer = kmalloc(ARPC_IN_SIZE_MAX, GFP_KERNEL); if (!buffer) { retval = -ENOMEM; @@ -1661,7 +1665,6 @@ static int ap_probe(struct usb_interface *interface, buffer, ARPC_IN_SIZE_MAX, arpc_in_callback, es2); - es2->arpc_urb[i] = urb; es2->arpc_buffer[i] = buffer; } -- cgit v0.10.2 From 0900845ab741dd7b0b8b3f03ded0ffc6a348dd90 Mon Sep 17 00:00:00 2001 From: Ann Chen <chen_ann@projectara.com> Date: Wed, 17 Aug 2016 16:38:56 +0800 Subject: greybus: Add workqueue to handle vibrator timeout In the beginning, module side can control the vibrator timeout value, it can disable vibrator until timeout. But after Runtime PM control added in, AP side didn't know when module can be suspended, the vibrator task will be interrupted by suspending event. Because of this problem, the module can not be in charge of counting down the timeout value, it is now up to the AP to manage this. So add workqueue to handle the vibrator timeout. Signed-off-by: Ann Chen <chen_ann@projectara.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/vibrator.c b/drivers/staging/greybus/vibrator.c index db55839..7296a4d 100644 --- a/drivers/staging/greybus/vibrator.c +++ b/drivers/staging/greybus/vibrator.c @@ -21,36 +21,27 @@ struct gb_vibrator_device { struct gb_connection *connection; struct device *dev; int minor; /* vibrator minor number */ + struct delayed_work delayed_work; }; /* Greybus Vibrator operation types */ #define GB_VIBRATOR_TYPE_ON 0x02 #define GB_VIBRATOR_TYPE_OFF 0x03 -struct gb_vibrator_on_request { - __le16 timeout_ms; -}; - -static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms) +static int turn_off(struct gb_vibrator_device *vib) { - struct gb_vibrator_on_request request; struct gb_bundle *bundle = vib->connection->bundle; int ret; - ret = gb_pm_runtime_get_sync(bundle); - if (ret) - return ret; - - request.timeout_ms = cpu_to_le16(timeout_ms); - ret = gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_ON, - &request, sizeof(request), NULL, 0); + ret = gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_OFF, + NULL, 0, NULL, 0); gb_pm_runtime_put_autosuspend(bundle); return ret; } -static int turn_off(struct gb_vibrator_device *vib) +static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms) { struct gb_bundle *bundle = vib->connection->bundle; int ret; @@ -59,12 +50,29 @@ static int turn_off(struct gb_vibrator_device *vib) if (ret) return ret; - ret = gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_OFF, + /* Vibrator was switched ON earlier */ + if (cancel_delayed_work_sync(&vib->delayed_work)) + turn_off(vib); + + ret = gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_ON, NULL, 0, NULL, 0); + if (ret) { + gb_pm_runtime_put_autosuspend(bundle); + return ret; + } - gb_pm_runtime_put_autosuspend(bundle); + schedule_delayed_work(&vib->delayed_work, msecs_to_jiffies(timeout_ms)); - return ret; + return 0; +} + +static void gb_vibrator_worker(struct work_struct *work) +{ + struct delayed_work *delayed_work = to_delayed_work(work); + struct gb_vibrator_device *vib = + container_of(delayed_work, struct gb_vibrator_device, delayed_work); + + turn_off(vib); } static ssize_t timeout_store(struct device *dev, struct device_attribute *attr, @@ -174,6 +182,8 @@ static int gb_vibrator_probe(struct gb_bundle *bundle, } #endif + INIT_DELAYED_WORK(&vib->delayed_work, gb_vibrator_worker); + gb_pm_runtime_put_autosuspend(bundle); return 0; @@ -199,6 +209,9 @@ static void gb_vibrator_disconnect(struct gb_bundle *bundle) if (ret) gb_pm_runtime_get_noresume(bundle); + if (cancel_delayed_work_sync(&vib->delayed_work)) + turn_off(vib); + #if LINUX_VERSION_CODE <= KERNEL_VERSION(3,11,0) sysfs_remove_group(&vib->dev->kobj, vibrator_groups[0]); #endif -- cgit v0.10.2 From 9fe7aeaca7ffec24a821c493b272614bd153b9aa Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Thu, 18 Aug 2016 16:58:46 +0200 Subject: staging: most: dim2-hdm: initialize DBR memory of synchronous channels In the time after a synchronous DIM2 channel is enabled and before the first buffer travels this channel, the DIM2 macro is babbling random random data to the network. This patch initializes the internal DBR memory of the DIM2 that is used to transfer the synchronous data. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.c b/drivers/staging/most/hdm-dim2/dim2_hal.c index a0b935c..901f742 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hal.c +++ b/drivers/staging/most/hdm-dim2/dim2_hal.c @@ -135,6 +135,27 @@ static void free_dbr(int offs, int size) /* -------------------------------------------------------------------------- */ +static void dim2_clear_dbr(u16 addr, u16 size) +{ + enum { MADR_TB_BIT = 30, MADR_WNR_BIT = 31 }; + + u16 const end_addr = addr + size; + u32 const cmd = bit_mask(MADR_WNR_BIT) | bit_mask(MADR_TB_BIT); + + dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ + dimcb_io_write(&g.dim2->MDAT0, 0); + + for (; addr < end_addr; addr++) { + dimcb_io_write(&g.dim2->MADR, cmd | addr); + + /* wait till transfer is completed */ + while ((dimcb_io_read(&g.dim2->MCTL) & 1) != 1) + continue; + + dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ + } +} + static u32 dim2_read_ctr(u32 ctr_addr, u16 mdat_idx) { dimcb_io_write(&g.dim2->MADR, ctr_addr); @@ -794,6 +815,7 @@ u8 dim_init_sync(struct dim_channel *ch, u8 is_tx, u16 ch_address, sync_init(ch, ch_address / 2, bytes_per_frame); + dim2_clear_dbr(ch->dbr_addr, ch->dbr_size); dim2_configure_channel(ch->addr, CAT_CT_VAL_SYNC, is_tx, ch->dbr_addr, ch->dbr_size, 0, true); -- cgit v0.10.2 From 95a31ef173e7cad94e5cb381d7893f92cee788a1 Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Thu, 18 Aug 2016 16:58:47 +0200 Subject: staging: most: dim2-hdm: introduce function dim2_transfer_madr This patch removes duplicated code by putting it into the new function dim2_transfer_madr. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.c b/drivers/staging/most/hdm-dim2/dim2_hal.c index 901f742..20b6970 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hal.c +++ b/drivers/staging/most/hdm-dim2/dim2_hal.c @@ -135,6 +135,17 @@ static void free_dbr(int offs, int size) /* -------------------------------------------------------------------------- */ +static void dim2_transfer_madr(u32 val) +{ + dimcb_io_write(&g.dim2->MADR, val); + + /* wait for transfer completion */ + while ((dimcb_io_read(&g.dim2->MCTL) & 1) != 1) + continue; + + dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ +} + static void dim2_clear_dbr(u16 addr, u16 size) { enum { MADR_TB_BIT = 30, MADR_WNR_BIT = 31 }; @@ -145,26 +156,13 @@ static void dim2_clear_dbr(u16 addr, u16 size) dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ dimcb_io_write(&g.dim2->MDAT0, 0); - for (; addr < end_addr; addr++) { - dimcb_io_write(&g.dim2->MADR, cmd | addr); - - /* wait till transfer is completed */ - while ((dimcb_io_read(&g.dim2->MCTL) & 1) != 1) - continue; - - dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ - } + for (; addr < end_addr; addr++) + dim2_transfer_madr(cmd | addr); } static u32 dim2_read_ctr(u32 ctr_addr, u16 mdat_idx) { - dimcb_io_write(&g.dim2->MADR, ctr_addr); - - /* wait till transfer is completed */ - while ((dimcb_io_read(&g.dim2->MCTL) & 1) != 1) - continue; - - dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ + dim2_transfer_madr(ctr_addr); return dimcb_io_read((&g.dim2->MDAT0) + mdat_idx); } @@ -189,13 +187,7 @@ static void dim2_write_ctr_mask(u32 ctr_addr, const u32 *mask, const u32 *value) dimcb_io_write(&g.dim2->MDWE2, mask[2]); dimcb_io_write(&g.dim2->MDWE3, mask[3]); - dimcb_io_write(&g.dim2->MADR, bit_mask(MADR_WNR_BIT) | ctr_addr); - - /* wait till transfer is completed */ - while ((dimcb_io_read(&g.dim2->MCTL) & 1) != 1) - continue; - - dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ + dim2_transfer_madr(bit_mask(MADR_WNR_BIT) | ctr_addr); } static inline void dim2_write_ctr(u32 ctr_addr, const u32 *value) -- cgit v0.10.2 From 33a5956c2c8db6a7e44332838c3c4113d8bce1f2 Mon Sep 17 00:00:00 2001 From: Ben LeMasurier <ben@crypt.ly> Date: Tue, 16 Aug 2016 21:02:00 -0600 Subject: Staging: android: ion: ion_heap.c: fix parenthesis alignment This fixes the checkpatch.pl "Alignment should match open parenthesis" issues in ion_heap.c. Signed-off-by: Ben LeMasurier <ben@crypt.ly> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index ca15a87..4e5c0f1 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -93,7 +93,7 @@ int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, } len = min(len, remainder); ret = remap_pfn_range(vma, addr, page_to_pfn(page), len, - vma->vm_page_prot); + vma->vm_page_prot); if (ret) return ret; addr += len; @@ -116,7 +116,7 @@ static int ion_heap_clear_pages(struct page **pages, int num, pgprot_t pgprot) } static int ion_heap_sglist_zero(struct scatterlist *sgl, unsigned int nents, - pgprot_t pgprot) + pgprot_t pgprot) { int p = 0; int ret = 0; @@ -181,7 +181,7 @@ size_t ion_heap_freelist_size(struct ion_heap *heap) } static size_t _ion_heap_freelist_drain(struct ion_heap *heap, size_t size, - bool skip_pools) + bool skip_pools) { struct ion_buffer *buffer; size_t total_drained = 0; @@ -266,7 +266,7 @@ int ion_heap_init_deferred_free(struct ion_heap *heap) } static unsigned long ion_heap_shrink_count(struct shrinker *shrinker, - struct shrink_control *sc) + struct shrink_control *sc) { struct ion_heap *heap = container_of(shrinker, struct ion_heap, shrinker); @@ -279,7 +279,7 @@ static unsigned long ion_heap_shrink_count(struct shrinker *shrinker, } static unsigned long ion_heap_shrink_scan(struct shrinker *shrinker, - struct shrink_control *sc) + struct shrink_control *sc) { struct ion_heap *heap = container_of(shrinker, struct ion_heap, shrinker); -- cgit v0.10.2 From 4485842493fe5efca436b7a0fa1f1f34c286f77f Mon Sep 17 00:00:00 2001 From: Ben LeMasurier <ben@crypt.ly> Date: Tue, 16 Aug 2016 11:01:44 -0600 Subject: Staging: android: ion: ion_test.c: fix parenthesis alignment This fixes the checkpatch.pl "Alignment should match open parenthesis" issues in ion_test.c. Signed-off-by: Ben LeMasurier <ben@crypt.ly> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/ion_test.c b/drivers/staging/android/ion/ion_test.c index 5a396a1..5abf8320 100644 --- a/drivers/staging/android/ion/ion_test.c +++ b/drivers/staging/android/ion/ion_test.c @@ -42,7 +42,8 @@ struct ion_test_data { }; static int ion_handle_test_dma(struct device *dev, struct dma_buf *dma_buf, - void __user *ptr, size_t offset, size_t size, bool write) + void __user *ptr, size_t offset, size_t size, + bool write) { int ret = 0; struct dma_buf_attachment *attach; @@ -98,7 +99,7 @@ err: } static int ion_handle_test_kernel(struct dma_buf *dma_buf, void __user *ptr, - size_t offset, size_t size, bool write) + size_t offset, size_t size, bool write) { int ret; unsigned long page_offset = offset >> PAGE_SHIFT; @@ -144,7 +145,7 @@ err: } static long ion_test_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg) + unsigned long arg) { struct ion_test_data *test_data = filp->private_data; int ret = 0; @@ -179,17 +180,19 @@ static long ion_test_ioctl(struct file *filp, unsigned int cmd, case ION_IOC_TEST_DMA_MAPPING: { ret = ion_handle_test_dma(test_data->dev, test_data->dma_buf, - u64_to_uptr(data.test_rw.ptr), - data.test_rw.offset, data.test_rw.size, - data.test_rw.write); + u64_to_uptr(data.test_rw.ptr), + data.test_rw.offset, + data.test_rw.size, + data.test_rw.write); break; } case ION_IOC_TEST_KERNEL_MAPPING: { ret = ion_handle_test_kernel(test_data->dma_buf, - u64_to_uptr(data.test_rw.ptr), - data.test_rw.offset, data.test_rw.size, - data.test_rw.write); + u64_to_uptr(data.test_rw.ptr), + data.test_rw.offset, + data.test_rw.size, + data.test_rw.write); break; } default: @@ -242,7 +245,7 @@ static int __init ion_test_probe(struct platform_device *pdev) struct ion_test_device *testdev; testdev = devm_kzalloc(&pdev->dev, sizeof(struct ion_test_device), - GFP_KERNEL); + GFP_KERNEL); if (!testdev) return -ENOMEM; -- cgit v0.10.2 From a75c03126f93713e121ea90fbaa2eaf55063c236 Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Thu, 18 Aug 2016 15:28:27 +0200 Subject: staging: most: aim-network: fix interrupt unsafe spinlocks The networking AIM does not use the *_irqsave and *_irqrestore flavored spinlock functions. The rx_completion callback, however, can be called from an interrupt context. This patch is needed to fix this problem. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c index 2f42de4..4659a64 100644 --- a/drivers/staging/most/aim-network/networking.c +++ b/drivers/staging/most/aim-network/networking.c @@ -298,15 +298,16 @@ static struct net_dev_context *get_net_dev_context( struct most_interface *iface) { struct net_dev_context *nd, *tmp; + unsigned long flags; - spin_lock(&list_lock); + spin_lock_irqsave(&list_lock, flags); list_for_each_entry_safe(nd, tmp, &net_devices, list) { if (nd->iface == iface) { - spin_unlock(&list_lock); + spin_unlock_irqrestore(&list_lock, flags); return nd; } } - spin_unlock(&list_lock); + spin_unlock_irqrestore(&list_lock, flags); return NULL; } @@ -316,6 +317,7 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx, { struct net_dev_context *nd; struct net_dev_channel *ch; + unsigned long flags; if (!iface) return -EINVAL; @@ -332,9 +334,9 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx, nd->iface = iface; - spin_lock(&list_lock); + spin_lock_irqsave(&list_lock, flags); list_add(&nd->list, &net_devices); - spin_unlock(&list_lock); + spin_unlock_irqrestore(&list_lock, flags); } ch = ccfg->direction == MOST_CH_TX ? &nd->tx : &nd->rx; @@ -377,6 +379,7 @@ static int aim_disconnect_channel(struct most_interface *iface, { struct net_dev_context *nd; struct net_dev_channel *ch; + unsigned long flags; nd = get_net_dev_context(iface); if (!nd) @@ -398,9 +401,9 @@ static int aim_disconnect_channel(struct most_interface *iface, most_net_rm_netdev_safe(nd); if (!nd->rx.linked && !nd->tx.linked) { - spin_lock(&list_lock); + spin_lock_irqsave(&list_lock, flags); list_del(&nd->list); - spin_unlock(&list_lock); + spin_unlock_irqrestore(&list_lock, flags); kfree(nd); } @@ -514,20 +517,21 @@ static int __init most_net_init(void) static void __exit most_net_exit(void) { struct net_dev_context *nd, *tmp; + unsigned long flags; - spin_lock(&list_lock); + spin_lock_irqsave(&list_lock, flags); list_for_each_entry_safe(nd, tmp, &net_devices, list) { list_del(&nd->list); - spin_unlock(&list_lock); + spin_unlock_irqrestore(&list_lock, flags); /* * do not call most_stop_channel() here, because channels are * going to be closed in ndo_stop() after unregister_netdev() */ most_net_rm_netdev_safe(nd); kfree(nd); - spin_lock(&list_lock); + spin_lock_irqsave(&list_lock, flags); } - spin_unlock(&list_lock); + spin_unlock_irqrestore(&list_lock, flags); most_deregister_aim(&aim); pr_info("most_net_exit()\n"); -- cgit v0.10.2 From 15c726ea5218b4e40d2331bd8b25b85848f73c42 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Tue, 16 Aug 2016 12:36:50 +0530 Subject: greybus: audio: Add check for invalid index while mapping control While mapping control id to define DAPM routes, invalid control index may cause kernel oops. Add extra check to validate index while mapping names to control_id. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index 0de2ad9..0153809 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -132,6 +132,7 @@ struct gbaudio_control { char *name; char *wname; const char * const *texts; + int items; struct list_head list; }; diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index 9375296..5c5b813 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -64,6 +64,8 @@ static const char *gbaudio_map_controlid(struct gbaudio_module_info *module, if (control->id == control_id) { if (index == GBAUDIO_INVALID_ID) return control->name; + if (index >= control->items) + return NULL; return control->texts[index]; } } @@ -71,6 +73,8 @@ static const char *gbaudio_map_controlid(struct gbaudio_module_info *module, if (control->id == control_id) { if (index == GBAUDIO_INVALID_ID) return control->name; + if (index >= control->items) + return NULL; return control->texts[index]; } } @@ -1038,6 +1042,7 @@ static int gbaudio_tplg_create_widget(struct gbaudio_module_info *module, csize += gbenum->names_length; control->texts = (const char * const *) gb_generate_enum_strings(module, gbenum); + control->items = gbenum->items; } else csize = sizeof(struct gb_audio_control); *w_size += csize; @@ -1184,6 +1189,7 @@ static int gbaudio_tplg_process_kcontrols(struct gbaudio_module_info *module, csize += gbenum->names_length; control->texts = (const char * const *) gb_generate_enum_strings(module, gbenum); + control->items = gbenum->items; } else csize = sizeof(struct gb_audio_control); -- cgit v0.10.2 From 6198f892fafbb3e5875c8a410eb2229a9cbac6ca Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Tue, 16 Aug 2016 12:36:51 +0530 Subject: greybus: Use valid control pointer while freeing memory While releasing memory during error path exit, invalid memory pointer was used for dapm_routes. Use a valid one. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index 5c5b813..e54078a 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -1317,7 +1317,7 @@ static int gbaudio_tplg_process_routes(struct gbaudio_module_info *module, return 0; error: - devm_kfree(module->dev, dapm_routes); + devm_kfree(module->dev, module->dapm_routes); return ret; } -- cgit v0.10.2 From c4582f9d7969019dc67234e96340e21dd3712c46 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva <rui.silva@linaro.org> Date: Tue, 16 Aug 2016 22:31:55 +0100 Subject: greybus: power_supply: add callback to handle power supply changes When checking for property changes we may need to act upon that change besides reporting it using power_supply_changed. So, add a function that will be call if the specific property changed. As at it, adjust some indentation of the psy_props_changes array. Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c index 058fd3c..aeb6a07e 100644 --- a/drivers/staging/greybus/power_supply.c +++ b/drivers/staging/greybus/power_supply.c @@ -70,17 +70,22 @@ static unsigned int update_interval_max = 30 * HZ; struct gb_power_supply_changes { enum power_supply_property prop; u32 tolerance_change; + void (*prop_changed)(struct gb_power_supply *gbpsy, + struct gb_power_supply_prop *prop); }; static const struct gb_power_supply_changes psy_props_changes[] = { - { .prop = GB_POWER_SUPPLY_PROP_STATUS, - .tolerance_change = 0, + { .prop = GB_POWER_SUPPLY_PROP_STATUS, + .tolerance_change = 0, + .prop_changed = NULL, }, - { .prop = GB_POWER_SUPPLY_PROP_TEMP, - .tolerance_change = 500, + { .prop = GB_POWER_SUPPLY_PROP_TEMP, + .tolerance_change = 500, + .prop_changed = NULL, }, - { .prop = GB_POWER_SUPPLY_PROP_ONLINE, - .tolerance_change = 0, + { .prop = GB_POWER_SUPPLY_PROP_ONLINE, + .tolerance_change = 0, + .prop_changed = NULL, }, }; @@ -349,18 +354,25 @@ static void check_changed(struct gb_power_supply *gbpsy, const struct gb_power_supply_changes *psyc; int val = prop->val; int prev_val = prop->previous_val; + bool changed = false; int i; for (i = 0; i < ARRAY_SIZE(psy_props_changes); i++) { psyc = &psy_props_changes[i]; if (prop->prop == psyc->prop) { if (!psyc->tolerance_change) - gbpsy->changed = true; + changed = true; else if (val < prev_val && prev_val - val > psyc->tolerance_change) - gbpsy->changed = true; + changed = true; else if (val > prev_val && val - prev_val > psyc->tolerance_change) + changed = true; + + if (changed && psyc->prop_changed) + psyc->prop_changed(gbpsy, prop); + + if (changed) gbpsy->changed = true; break; } -- cgit v0.10.2 From 5f66d62e8372d8a9c97bd75d772a5a5788925218 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva <rui.silva@linaro.org> Date: Tue, 16 Aug 2016 22:31:56 +0100 Subject: greybus: power_supply: fix update interval check at request handler We use the update interval to control the remove path and we set it to zero when we do not want to have more updates in transit. That means that the check in the request handler needs to be for interval update zero to discard the newly received request and not the other way around like it is. This will fix the issue that all incoming requests were being discard. Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c index aeb6a07e..3d6f810 100644 --- a/drivers/staging/greybus/power_supply.c +++ b/drivers/staging/greybus/power_supply.c @@ -982,7 +982,7 @@ static int gb_supplies_request_handler(struct gb_operation *op) * running. For that just check update_interval. */ gbpsy = &supplies->supply[psy_id]; - if (gbpsy->update_interval) { + if (!gbpsy->update_interval) { ret = -ESHUTDOWN; goto out_unlock; } -- cgit v0.10.2 From b5fbe819af2f8d8dceb421635a976462bb6885b8 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva <rui.silva@linaro.org> Date: Tue, 16 Aug 2016 22:31:57 +0100 Subject: greybus: power_supply: invalidate cache at update request When we receive a update request we shall not trust the cache mechanism and for that we need a way to invalidate the cache. Add a field that will control the cache status and refactor the code to check if cache is valid in a helper function. This will fix the scenario where an update request is received within the cache expiration time after a previous update as happened and would be ignored. Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c index 3d6f810..199a19a 100644 --- a/drivers/staging/greybus/power_supply.c +++ b/drivers/staging/greybus/power_supply.c @@ -45,6 +45,7 @@ struct gb_power_supply { u8 properties_count; u8 properties_count_str; unsigned long last_update; + u8 cache_invalid; unsigned int update_interval; bool changed; struct gb_power_supply_prop *props; @@ -636,15 +637,28 @@ static int _gb_power_supply_property_get(struct gb_power_supply *gbpsy, return 0; } -static int gb_power_supply_status_get(struct gb_power_supply *gbpsy) +static int is_cache_valid(struct gb_power_supply *gbpsy) { - int ret = 0; - int i; + /* check if cache is good enough or it has expired */ + if (gbpsy->cache_invalid) { + gbpsy->cache_invalid = 0; + return 0; + } - /* check if cache is good enough */ if (gbpsy->last_update && time_is_after_jiffies(gbpsy->last_update + msecs_to_jiffies(cache_time))) + return 1; + + return 0; +} + +static int gb_power_supply_status_get(struct gb_power_supply *gbpsy) +{ + int ret = 0; + int i; + + if (is_cache_valid(gbpsy)) return 0; for (i = 0; i < gbpsy->properties_count; i++) { @@ -987,8 +1001,15 @@ static int gb_supplies_request_handler(struct gb_operation *op) goto out_unlock; } - if (event & GB_POWER_SUPPLY_UPDATE) + if (event & GB_POWER_SUPPLY_UPDATE) { + /* + * we need to make sure we invalidate cache, if not no new + * values for the properties will be fetch and the all propose + * of this event is missed + */ + gbpsy->cache_invalid = 1; gb_power_supply_status_update(gbpsy); + } out_unlock: mutex_unlock(&supplies->supplies_lock); -- cgit v0.10.2 From 6d13b6ff112b9a047f82d6cc01aa9d32c9133d8d Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Thu, 18 Aug 2016 17:43:22 +0200 Subject: greybus: svc: drop all symbol exports The svc functions are only supposed to be called by core and should not be exported. Most of these functions should never have been exported in the first place, while a few no longer needs to be (e.g. since core gained support for offloaded connections). Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index c5aedd5..162ba7c 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -447,7 +447,6 @@ int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, return 0; } -EXPORT_SYMBOL_GPL(gb_svc_dme_peer_get); int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, u32 value) @@ -480,7 +479,6 @@ int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, return 0; } -EXPORT_SYMBOL_GPL(gb_svc_dme_peer_set); int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, @@ -499,7 +497,6 @@ int gb_svc_connection_create(struct gb_svc *svc, return gb_operation_sync(svc->connection, GB_SVC_TYPE_CONN_CREATE, &request, sizeof(request), NULL, 0); } -EXPORT_SYMBOL_GPL(gb_svc_connection_create); void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id) @@ -520,7 +517,6 @@ void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, intf1_id, cport1_id, intf2_id, cport2_id, ret); } } -EXPORT_SYMBOL_GPL(gb_svc_connection_destroy); int gb_svc_timesync_enable(struct gb_svc *svc, u8 count, u64 frame_time, u32 strobe_delay, u32 refclk) @@ -536,7 +532,6 @@ int gb_svc_timesync_enable(struct gb_svc *svc, u8 count, u64 frame_time, GB_SVC_TYPE_TIMESYNC_ENABLE, &request, sizeof(request), NULL, 0); } -EXPORT_SYMBOL_GPL(gb_svc_timesync_enable); int gb_svc_timesync_disable(struct gb_svc *svc) { @@ -546,7 +541,6 @@ int gb_svc_timesync_disable(struct gb_svc *svc) GB_SVC_TYPE_TIMESYNC_DISABLE, NULL, 0, NULL, 0); } -EXPORT_SYMBOL_GPL(gb_svc_timesync_disable); int gb_svc_timesync_authoritative(struct gb_svc *svc, u64 *frame_time) { @@ -564,7 +558,6 @@ int gb_svc_timesync_authoritative(struct gb_svc *svc, u64 *frame_time) frame_time[i] = le64_to_cpu(response.frame_time[i]); return 0; } -EXPORT_SYMBOL_GPL(gb_svc_timesync_authoritative); int gb_svc_timesync_ping(struct gb_svc *svc, u64 *frame_time) { @@ -582,7 +575,6 @@ int gb_svc_timesync_ping(struct gb_svc *svc, u64 *frame_time) *frame_time = le64_to_cpu(response.frame_time); return 0; } -EXPORT_SYMBOL_GPL(gb_svc_timesync_ping); int gb_svc_timesync_wake_pins_acquire(struct gb_svc *svc, u32 strobe_mask) { @@ -595,7 +587,6 @@ int gb_svc_timesync_wake_pins_acquire(struct gb_svc *svc, u32 strobe_mask) &request, sizeof(request), NULL, 0); } -EXPORT_SYMBOL_GPL(gb_svc_timesync_wake_pins_acquire); int gb_svc_timesync_wake_pins_release(struct gb_svc *svc) { @@ -605,7 +596,6 @@ int gb_svc_timesync_wake_pins_release(struct gb_svc *svc) GB_SVC_TYPE_TIMESYNC_WAKE_PINS_RELEASE, NULL, 0, NULL, 0); } -EXPORT_SYMBOL_GPL(gb_svc_timesync_wake_pins_release); /* Creates bi-directional routes between the devices */ int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, @@ -685,7 +675,6 @@ int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series, return 0; } -EXPORT_SYMBOL_GPL(gb_svc_intf_set_power_mode); int gb_svc_intf_set_power_mode_hibernate(struct gb_svc *svc, u8 intf_id) { @@ -728,7 +717,6 @@ int gb_svc_ping(struct gb_svc *svc) NULL, 0, NULL, 0, GB_OPERATION_TIMEOUT_DEFAULT * 2); } -EXPORT_SYMBOL_GPL(gb_svc_ping); static int gb_svc_version_request(struct gb_operation *op) { -- cgit v0.10.2 From 46bb647b1ca0f136b991151e3dd365b751572f40 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Thu, 18 Aug 2016 21:30:19 +0200 Subject: greybus: Revert "svc: drop all symbol exports" This reverts commit a0e559d03bbb3f9774a091e31c0f77d98db1f60d. It breaks the camera driver :( Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 162ba7c..c5aedd5 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -447,6 +447,7 @@ int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, return 0; } +EXPORT_SYMBOL_GPL(gb_svc_dme_peer_get); int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, u32 value) @@ -479,6 +480,7 @@ int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, return 0; } +EXPORT_SYMBOL_GPL(gb_svc_dme_peer_set); int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, @@ -497,6 +499,7 @@ int gb_svc_connection_create(struct gb_svc *svc, return gb_operation_sync(svc->connection, GB_SVC_TYPE_CONN_CREATE, &request, sizeof(request), NULL, 0); } +EXPORT_SYMBOL_GPL(gb_svc_connection_create); void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id) @@ -517,6 +520,7 @@ void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, intf1_id, cport1_id, intf2_id, cport2_id, ret); } } +EXPORT_SYMBOL_GPL(gb_svc_connection_destroy); int gb_svc_timesync_enable(struct gb_svc *svc, u8 count, u64 frame_time, u32 strobe_delay, u32 refclk) @@ -532,6 +536,7 @@ int gb_svc_timesync_enable(struct gb_svc *svc, u8 count, u64 frame_time, GB_SVC_TYPE_TIMESYNC_ENABLE, &request, sizeof(request), NULL, 0); } +EXPORT_SYMBOL_GPL(gb_svc_timesync_enable); int gb_svc_timesync_disable(struct gb_svc *svc) { @@ -541,6 +546,7 @@ int gb_svc_timesync_disable(struct gb_svc *svc) GB_SVC_TYPE_TIMESYNC_DISABLE, NULL, 0, NULL, 0); } +EXPORT_SYMBOL_GPL(gb_svc_timesync_disable); int gb_svc_timesync_authoritative(struct gb_svc *svc, u64 *frame_time) { @@ -558,6 +564,7 @@ int gb_svc_timesync_authoritative(struct gb_svc *svc, u64 *frame_time) frame_time[i] = le64_to_cpu(response.frame_time[i]); return 0; } +EXPORT_SYMBOL_GPL(gb_svc_timesync_authoritative); int gb_svc_timesync_ping(struct gb_svc *svc, u64 *frame_time) { @@ -575,6 +582,7 @@ int gb_svc_timesync_ping(struct gb_svc *svc, u64 *frame_time) *frame_time = le64_to_cpu(response.frame_time); return 0; } +EXPORT_SYMBOL_GPL(gb_svc_timesync_ping); int gb_svc_timesync_wake_pins_acquire(struct gb_svc *svc, u32 strobe_mask) { @@ -587,6 +595,7 @@ int gb_svc_timesync_wake_pins_acquire(struct gb_svc *svc, u32 strobe_mask) &request, sizeof(request), NULL, 0); } +EXPORT_SYMBOL_GPL(gb_svc_timesync_wake_pins_acquire); int gb_svc_timesync_wake_pins_release(struct gb_svc *svc) { @@ -596,6 +605,7 @@ int gb_svc_timesync_wake_pins_release(struct gb_svc *svc) GB_SVC_TYPE_TIMESYNC_WAKE_PINS_RELEASE, NULL, 0, NULL, 0); } +EXPORT_SYMBOL_GPL(gb_svc_timesync_wake_pins_release); /* Creates bi-directional routes between the devices */ int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, @@ -675,6 +685,7 @@ int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series, return 0; } +EXPORT_SYMBOL_GPL(gb_svc_intf_set_power_mode); int gb_svc_intf_set_power_mode_hibernate(struct gb_svc *svc, u8 intf_id) { @@ -717,6 +728,7 @@ int gb_svc_ping(struct gb_svc *svc) NULL, 0, NULL, 0, GB_OPERATION_TIMEOUT_DEFAULT * 2); } +EXPORT_SYMBOL_GPL(gb_svc_ping); static int gb_svc_version_request(struct gb_operation *op) { -- cgit v0.10.2 From be67e7e54bb1c22e396285bd7b4721786cba1209 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 19 Aug 2016 09:42:21 +0200 Subject: greybus: svc: drop unnecessary symbol exports The svc functions are only supposed to be called by core and should not be exported. Most of these functions should never have been exported in the first place, while a few no longer needs to be (e.g. since core gained support for offloaded connections). The only remaining exception is gb_svc_intf_set_power_mode() which is needed by the camera driver until proper link management is in place. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index c5aedd5..6182e13 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -447,7 +447,6 @@ int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, return 0; } -EXPORT_SYMBOL_GPL(gb_svc_dme_peer_get); int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, u32 value) @@ -480,7 +479,6 @@ int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, return 0; } -EXPORT_SYMBOL_GPL(gb_svc_dme_peer_set); int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, @@ -499,7 +497,6 @@ int gb_svc_connection_create(struct gb_svc *svc, return gb_operation_sync(svc->connection, GB_SVC_TYPE_CONN_CREATE, &request, sizeof(request), NULL, 0); } -EXPORT_SYMBOL_GPL(gb_svc_connection_create); void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id) @@ -520,7 +517,6 @@ void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, intf1_id, cport1_id, intf2_id, cport2_id, ret); } } -EXPORT_SYMBOL_GPL(gb_svc_connection_destroy); int gb_svc_timesync_enable(struct gb_svc *svc, u8 count, u64 frame_time, u32 strobe_delay, u32 refclk) @@ -536,7 +532,6 @@ int gb_svc_timesync_enable(struct gb_svc *svc, u8 count, u64 frame_time, GB_SVC_TYPE_TIMESYNC_ENABLE, &request, sizeof(request), NULL, 0); } -EXPORT_SYMBOL_GPL(gb_svc_timesync_enable); int gb_svc_timesync_disable(struct gb_svc *svc) { @@ -546,7 +541,6 @@ int gb_svc_timesync_disable(struct gb_svc *svc) GB_SVC_TYPE_TIMESYNC_DISABLE, NULL, 0, NULL, 0); } -EXPORT_SYMBOL_GPL(gb_svc_timesync_disable); int gb_svc_timesync_authoritative(struct gb_svc *svc, u64 *frame_time) { @@ -564,7 +558,6 @@ int gb_svc_timesync_authoritative(struct gb_svc *svc, u64 *frame_time) frame_time[i] = le64_to_cpu(response.frame_time[i]); return 0; } -EXPORT_SYMBOL_GPL(gb_svc_timesync_authoritative); int gb_svc_timesync_ping(struct gb_svc *svc, u64 *frame_time) { @@ -582,7 +575,6 @@ int gb_svc_timesync_ping(struct gb_svc *svc, u64 *frame_time) *frame_time = le64_to_cpu(response.frame_time); return 0; } -EXPORT_SYMBOL_GPL(gb_svc_timesync_ping); int gb_svc_timesync_wake_pins_acquire(struct gb_svc *svc, u32 strobe_mask) { @@ -595,7 +587,6 @@ int gb_svc_timesync_wake_pins_acquire(struct gb_svc *svc, u32 strobe_mask) &request, sizeof(request), NULL, 0); } -EXPORT_SYMBOL_GPL(gb_svc_timesync_wake_pins_acquire); int gb_svc_timesync_wake_pins_release(struct gb_svc *svc) { @@ -605,7 +596,6 @@ int gb_svc_timesync_wake_pins_release(struct gb_svc *svc) GB_SVC_TYPE_TIMESYNC_WAKE_PINS_RELEASE, NULL, 0, NULL, 0); } -EXPORT_SYMBOL_GPL(gb_svc_timesync_wake_pins_release); /* Creates bi-directional routes between the devices */ int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, @@ -728,7 +718,6 @@ int gb_svc_ping(struct gb_svc *svc) NULL, 0, NULL, 0, GB_OPERATION_TIMEOUT_DEFAULT * 2); } -EXPORT_SYMBOL_GPL(gb_svc_ping); static int gb_svc_version_request(struct gb_operation *op) { -- cgit v0.10.2 From 0363dfc585c5c62659be48b6de4b0f8abef4c839 Mon Sep 17 00:00:00 2001 From: Aleksei Mamlin <mamlinav@gmail.com> Date: Mon, 25 Jul 2016 18:21:17 +0300 Subject: devicetree: bindings: Add vendor prefix for Domintech Co., Ltd. Add vendor-prefix for Domintech Co., Ltd. Signed-off-by: Aleksei Mamlin <mamlinav@gmail.com> Acked-by: Rob Herring <robh@kernel.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 2c2500d..7363916 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -75,6 +75,7 @@ digilent Diglent, Inc. dlg Dialog Semiconductor dlink D-Link Corporation dmo Data Modul AG +domintech Domintech Co., Ltd. dptechnics DPTechnics dragino Dragino Technology Co., Limited ea Embedded Artists AB -- cgit v0.10.2 From b1b79f53278f2e2ec07fc8a899068fcc04ca439b Mon Sep 17 00:00:00 2001 From: Aleksei Mamlin <mamlinav@gmail.com> Date: Mon, 25 Jul 2016 18:21:18 +0300 Subject: iio: accel: Add support for Domintech DMARD06 accelerometer This patch add support for Domintech DMARD05, DMARD06 and DMARD07 accelerometers. Signed-off-by: Aleksei Mamlin <mamlinav@gmail.com> Acked-by: Rob Herring <robh@kernel.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/Documentation/devicetree/bindings/iio/accel/dmard06.txt b/Documentation/devicetree/bindings/iio/accel/dmard06.txt new file mode 100644 index 0000000..ce105a1 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/accel/dmard06.txt @@ -0,0 +1,19 @@ +Device tree bindings for Domintech DMARD05, DMARD06, DMARD07 accelerometers + +Required properties: + - compatible : Should be "domintech,dmard05" + or "domintech,dmard06" + or "domintech,dmard07" + - reg : I2C address of the chip. Should be 0x1c + +Example: + &i2c1 { + /* ... */ + + accelerometer@1c { + compatible = "domintech,dmard06"; + reg = <0x1c>; + }; + + /* ... */ + }; diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index 89d7820..ee57eff 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -50,6 +50,17 @@ config BMC150_ACCEL_SPI tristate select REGMAP_SPI +config DMARD06 + tristate "Domintech DMARD06 Digital Accelerometer Driver" + depends on OF || COMPILE_TEST + depends on I2C + help + Say yes here to build support for the Domintech low-g tri-axial + digital accelerometers: DMARD05, DMARD06, DMARD07. + + To compile this driver as a module, choose M here: the + module will be called dmard06. + config HID_SENSOR_ACCEL_3D depends on HID_SENSOR_HUB select IIO_BUFFER diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile index 6cedbec..24eba65 100644 --- a/drivers/iio/accel/Makefile +++ b/drivers/iio/accel/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_BMA220) += bma220_spi.o obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o +obj-$(CONFIG_DMARD06) += dmard06.o obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o obj-$(CONFIG_KXSD9) += kxsd9.o diff --git a/drivers/iio/accel/dmard06.c b/drivers/iio/accel/dmard06.c new file mode 100644 index 0000000..656ca8e --- /dev/null +++ b/drivers/iio/accel/dmard06.c @@ -0,0 +1,241 @@ +/* + * IIO driver for Domintech DMARD06 accelerometer + * + * Copyright (C) 2016 Aleksei Mamlin <mamlinav@gmail.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/iio/iio.h> + +#define DMARD06_DRV_NAME "dmard06" + +/* Device data registers */ +#define DMARD06_CHIP_ID_REG 0x0f +#define DMARD06_TOUT_REG 0x40 +#define DMARD06_XOUT_REG 0x41 +#define DMARD06_YOUT_REG 0x42 +#define DMARD06_ZOUT_REG 0x43 +#define DMARD06_CTRL1_REG 0x44 + +/* Device ID value */ +#define DMARD05_CHIP_ID 0x05 +#define DMARD06_CHIP_ID 0x06 +#define DMARD07_CHIP_ID 0x07 + +/* Device values */ +#define DMARD05_AXIS_SCALE_VAL 15625 +#define DMARD06_AXIS_SCALE_VAL 31250 +#define DMARD06_TEMP_CENTER_VAL 25 +#define DMARD06_SIGN_BIT 7 + +/* Device power modes */ +#define DMARD06_MODE_NORMAL 0x27 +#define DMARD06_MODE_POWERDOWN 0x00 + +/* Device channels */ +#define DMARD06_ACCEL_CHANNEL(_axis, _reg) { \ + .type = IIO_ACCEL, \ + .address = _reg, \ + .channel2 = IIO_MOD_##_axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .modified = 1, \ +} + +#define DMARD06_TEMP_CHANNEL(_reg) { \ + .type = IIO_TEMP, \ + .address = _reg, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_OFFSET), \ +} + +struct dmard06_data { + struct i2c_client *client; + u8 chip_id; +}; + +static const struct iio_chan_spec dmard06_channels[] = { + DMARD06_ACCEL_CHANNEL(X, DMARD06_XOUT_REG), + DMARD06_ACCEL_CHANNEL(Y, DMARD06_YOUT_REG), + DMARD06_ACCEL_CHANNEL(Z, DMARD06_ZOUT_REG), + DMARD06_TEMP_CHANNEL(DMARD06_TOUT_REG), +}; + +static int dmard06_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct dmard06_data *dmard06 = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = i2c_smbus_read_byte_data(dmard06->client, + chan->address); + if (ret < 0) { + dev_err(&dmard06->client->dev, + "Error reading data: %d\n", ret); + return ret; + } + + *val = sign_extend32(ret, DMARD06_SIGN_BIT); + + if (dmard06->chip_id == DMARD06_CHIP_ID) + *val = *val >> 1; + + switch (chan->type) { + case IIO_ACCEL: + return IIO_VAL_INT; + case IIO_TEMP: + if (dmard06->chip_id != DMARD06_CHIP_ID) + *val = *val / 2; + return IIO_VAL_INT; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_OFFSET: + switch (chan->type) { + case IIO_TEMP: + *val = DMARD06_TEMP_CENTER_VAL; + return IIO_VAL_INT; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ACCEL: + *val = 0; + if (dmard06->chip_id == DMARD06_CHIP_ID) + *val2 = DMARD06_AXIS_SCALE_VAL; + else + *val2 = DMARD05_AXIS_SCALE_VAL; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static const struct iio_info dmard06_info = { + .driver_module = THIS_MODULE, + .read_raw = dmard06_read_raw, +}; + +static int dmard06_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret; + struct iio_dev *indio_dev; + struct dmard06_data *dmard06; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + dev_err(&client->dev, "I2C check functionality failed\n"); + return -ENXIO; + } + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*dmard06)); + if (!indio_dev) { + dev_err(&client->dev, "Failed to allocate iio device\n"); + return -ENOMEM; + } + + dmard06 = iio_priv(indio_dev); + dmard06->client = client; + + ret = i2c_smbus_read_byte_data(dmard06->client, DMARD06_CHIP_ID_REG); + if (ret < 0) { + dev_err(&client->dev, "Error reading chip id: %d\n", ret); + return ret; + } + + if (ret != DMARD05_CHIP_ID && ret != DMARD06_CHIP_ID && + ret != DMARD07_CHIP_ID) { + dev_err(&client->dev, "Invalid chip id: %02d\n", ret); + return -ENODEV; + } + + dmard06->chip_id = ret; + + i2c_set_clientdata(client, indio_dev); + indio_dev->dev.parent = &client->dev; + indio_dev->name = DMARD06_DRV_NAME; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = dmard06_channels; + indio_dev->num_channels = ARRAY_SIZE(dmard06_channels); + indio_dev->info = &dmard06_info; + + return devm_iio_device_register(&client->dev, indio_dev); +} + +#ifdef CONFIG_PM_SLEEP +static int dmard06_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct dmard06_data *dmard06 = iio_priv(indio_dev); + int ret; + + ret = i2c_smbus_write_byte_data(dmard06->client, DMARD06_CTRL1_REG, + DMARD06_MODE_POWERDOWN); + if (ret < 0) + return ret; + + return 0; +} + +static int dmard06_resume(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct dmard06_data *dmard06 = iio_priv(indio_dev); + int ret; + + ret = i2c_smbus_write_byte_data(dmard06->client, DMARD06_CTRL1_REG, + DMARD06_MODE_NORMAL); + if (ret < 0) + return ret; + + return 0; +} + +static SIMPLE_DEV_PM_OPS(dmard06_pm_ops, dmard06_suspend, dmard06_resume); +#define DMARD06_PM_OPS (&dmard06_pm_ops) +#else +#define DMARD06_PM_OPS NULL +#endif + +static const struct i2c_device_id dmard06_id[] = { + { "dmard05", 0 }, + { "dmard06", 0 }, + { "dmard07", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, dmard06_id); + +static const struct of_device_id dmard06_of_match[] = { + { .compatible = "domintech,dmard05" }, + { .compatible = "domintech,dmard06" }, + { .compatible = "domintech,dmard07" }, + { } +}; +MODULE_DEVICE_TABLE(of, dmard06_of_match); + +static struct i2c_driver dmard06_driver = { + .probe = dmard06_probe, + .id_table = dmard06_id, + .driver = { + .name = DMARD06_DRV_NAME, + .of_match_table = of_match_ptr(dmard06_of_match), + .pm = DMARD06_PM_OPS, + }, +}; +module_i2c_driver(dmard06_driver); + +MODULE_AUTHOR("Aleksei Mamlin <mamlinav@gmail.com>"); +MODULE_DESCRIPTION("Domintech DMARD06 accelerometer driver"); +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From a4fa6509dda47e51c3582409e8630b24702970c5 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa <jelle@vdwaa.nl> Date: Tue, 26 Jul 2016 23:23:48 +0200 Subject: iio: accel: add support for the Domintech DMARD09 3-axis accelerometer Minimal implementation of an IIO driver for the Domintech DMARD09 3-axis accelerometer. Only supports reading the x,y,z axes at the moment. Implementation based on the Android driver from the Acer Liquid E2 kernel sources. Signed-off-by: Jelle van der Waa <jelle@vdwaa.nl> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt index acc5cd6..0bc11e0 100644 --- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt +++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt @@ -38,6 +38,7 @@ dallas,ds4510 CPU Supervisor with Nonvolatile Memory and Programmable I/O dallas,ds75 Digital Thermometer and Thermostat dlg,da9053 DA9053: flexible system level PMIC with multicore support dlg,da9063 DA9063: system PMIC for quad-core application processors +domintech,dmard09 DMARD09: 3-axis Accelerometer epson,rx8010 I2C-BUS INTERFACE REAL TIME CLOCK MODULE epson,rx8025 High-Stability. I2C-Bus INTERFACE REAL TIME CLOCK MODULE epson,rx8581 I2C-BUS INTERFACE REAL TIME CLOCK MODULE diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index ee57eff..5630f23 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -61,6 +61,16 @@ config DMARD06 To compile this driver as a module, choose M here: the module will be called dmard06. +config DMARD09 + tristate "Domintech DMARD09 3-axis Accelerometer Driver" + depends on I2C + help + Say yes here to get support for the Domintech DMARD09 3-axis + accelerometer. + + Choosing M will build the driver as a module. If so, the module + will be called dmard09. + config HID_SENSOR_ACCEL_3D depends on HID_SENSOR_HUB select IIO_BUFFER diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile index 24eba65..e974841 100644 --- a/drivers/iio/accel/Makefile +++ b/drivers/iio/accel/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o obj-$(CONFIG_DMARD06) += dmard06.o +obj-$(CONFIG_DMARD09) += dmard09.o obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o obj-$(CONFIG_KXSD9) += kxsd9.o diff --git a/drivers/iio/accel/dmard09.c b/drivers/iio/accel/dmard09.c new file mode 100644 index 0000000..d3a28f9 --- /dev/null +++ b/drivers/iio/accel/dmard09.c @@ -0,0 +1,157 @@ +/* + * IIO driver for the 3-axis accelerometer Domintech DMARD09. + * + * Copyright (c) 2016, Jelle van der Waa <jelle@vdwaa.nl> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include <asm/unaligned.h> +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/iio/iio.h> + +#define DMARD09_DRV_NAME "dmard09" + +#define DMARD09_REG_CHIPID 0x18 +#define DMARD09_REG_STAT 0x0A +#define DMARD09_REG_X 0x0C +#define DMARD09_REG_Y 0x0E +#define DMARD09_REG_Z 0x10 +#define DMARD09_CHIPID 0x95 + +#define DMARD09_BUF_LEN 8 +#define DMARD09_AXIS_X 0 +#define DMARD09_AXIS_Y 1 +#define DMARD09_AXIS_Z 2 +#define DMARD09_AXIS_X_OFFSET ((DMARD09_AXIS_X + 1) * 2) +#define DMARD09_AXIS_Y_OFFSET ((DMARD09_AXIS_Y + 1 )* 2) +#define DMARD09_AXIS_Z_OFFSET ((DMARD09_AXIS_Z + 1) * 2) + +struct dmard09_data { + struct i2c_client *client; +}; + +#define DMARD09_CHANNEL(_axis, offset) { \ + .type = IIO_ACCEL, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .modified = 1, \ + .address = offset, \ + .channel2 = IIO_MOD_##_axis, \ +} + +static const struct iio_chan_spec dmard09_channels[] = { + DMARD09_CHANNEL(X, DMARD09_AXIS_X_OFFSET), + DMARD09_CHANNEL(Y, DMARD09_AXIS_Y_OFFSET), + DMARD09_CHANNEL(Z, DMARD09_AXIS_Z_OFFSET), +}; + +static int dmard09_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct dmard09_data *data = iio_priv(indio_dev); + u8 buf[DMARD09_BUF_LEN]; + int ret; + s16 accel; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + /* + * Read from the DMAR09_REG_STAT register, since the chip + * caches reads from the individual X, Y, Z registers. + */ + ret = i2c_smbus_read_i2c_block_data(data->client, + DMARD09_REG_STAT, + DMARD09_BUF_LEN, buf); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg %d\n", + DMARD09_REG_STAT); + return ret; + } + + accel = get_unaligned_le16(&buf[chan->address]); + + /* Remove lower 3 bits and sign extend */ + accel <<= 4; + accel >>= 7; + + *val = accel; + + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static const struct iio_info dmard09_info = { + .driver_module = THIS_MODULE, + .read_raw = dmard09_read_raw, +}; + +static int dmard09_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret; + struct iio_dev *indio_dev; + struct dmard09_data *data; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) { + dev_err(&client->dev, "iio allocation failed\n"); + return -ENOMEM; + } + + data = iio_priv(indio_dev); + data->client = client; + + ret = i2c_smbus_read_byte_data(data->client, DMARD09_REG_CHIPID); + if (ret < 0) { + dev_err(&client->dev, "Error reading chip id %d\n", ret); + return ret; + } + + if (ret != DMARD09_CHIPID) { + dev_err(&client->dev, "Invalid chip id %d\n", ret); + return -ENODEV; + } + + i2c_set_clientdata(client, indio_dev); + indio_dev->dev.parent = &client->dev; + indio_dev->name = DMARD09_DRV_NAME; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = dmard09_channels; + indio_dev->num_channels = ARRAY_SIZE(dmard09_channels); + indio_dev->info = &dmard09_info; + + return devm_iio_device_register(&client->dev, indio_dev); +} + +static const struct i2c_device_id dmard09_id[] = { + { "dmard09", 0}, + { }, +}; + +MODULE_DEVICE_TABLE(i2c, dmard09_id); + +static struct i2c_driver dmard09_driver = { + .driver = { + .name = DMARD09_DRV_NAME + }, + .probe = dmard09_probe, + .id_table = dmard09_id, +}; + +module_i2c_driver(dmard09_driver); + +MODULE_AUTHOR("Jelle van der Waa <jelle@vdwaa.nl>"); +MODULE_DESCRIPTION("DMARD09 3-axis accelerometer driver"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From adca058b56108eb3458165c6a9e5d78558be8b52 Mon Sep 17 00:00:00 2001 From: Matt Ranostay <mranostay@gmail.com> Date: Fri, 19 Aug 2016 20:17:02 -0700 Subject: iio: buffer-callback: allow getting underlying iio_dev Add iio_channel_cb_get_iio_dev function to allow getting the underlying iio_dev. This is useful for setting the trigger of the consumer ADC device. Signed-off-by: Matt Ranostay <mranostay@gmail.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/buffer/industrialio-buffer-cb.c b/drivers/iio/buffer/industrialio-buffer-cb.c index 323079c..b8f550e 100644 --- a/drivers/iio/buffer/industrialio-buffer-cb.c +++ b/drivers/iio/buffer/industrialio-buffer-cb.c @@ -18,6 +18,7 @@ struct iio_cb_buffer { int (*cb)(const void *data, void *private); void *private; struct iio_channel *channels; + struct iio_dev *indio_dev; }; static struct iio_cb_buffer *buffer_to_cb_buffer(struct iio_buffer *buffer) @@ -52,7 +53,6 @@ struct iio_cb_buffer *iio_channel_get_all_cb(struct device *dev, { int ret; struct iio_cb_buffer *cb_buff; - struct iio_dev *indio_dev; struct iio_channel *chan; cb_buff = kzalloc(sizeof(*cb_buff), GFP_KERNEL); @@ -72,17 +72,17 @@ struct iio_cb_buffer *iio_channel_get_all_cb(struct device *dev, goto error_free_cb_buff; } - indio_dev = cb_buff->channels[0].indio_dev; + cb_buff->indio_dev = cb_buff->channels[0].indio_dev; cb_buff->buffer.scan_mask - = kcalloc(BITS_TO_LONGS(indio_dev->masklength), sizeof(long), - GFP_KERNEL); + = kcalloc(BITS_TO_LONGS(cb_buff->indio_dev->masklength), + sizeof(long), GFP_KERNEL); if (cb_buff->buffer.scan_mask == NULL) { ret = -ENOMEM; goto error_release_channels; } chan = &cb_buff->channels[0]; while (chan->indio_dev) { - if (chan->indio_dev != indio_dev) { + if (chan->indio_dev != cb_buff->indio_dev) { ret = -EINVAL; goto error_free_scan_mask; } @@ -105,17 +105,14 @@ EXPORT_SYMBOL_GPL(iio_channel_get_all_cb); int iio_channel_start_all_cb(struct iio_cb_buffer *cb_buff) { - return iio_update_buffers(cb_buff->channels[0].indio_dev, - &cb_buff->buffer, + return iio_update_buffers(cb_buff->indio_dev, &cb_buff->buffer, NULL); } EXPORT_SYMBOL_GPL(iio_channel_start_all_cb); void iio_channel_stop_all_cb(struct iio_cb_buffer *cb_buff) { - iio_update_buffers(cb_buff->channels[0].indio_dev, - NULL, - &cb_buff->buffer); + iio_update_buffers(cb_buff->indio_dev, NULL, &cb_buff->buffer); } EXPORT_SYMBOL_GPL(iio_channel_stop_all_cb); @@ -133,6 +130,13 @@ struct iio_channel } EXPORT_SYMBOL_GPL(iio_channel_cb_get_channels); +struct iio_dev +*iio_channel_cb_get_iio_dev(const struct iio_cb_buffer *cb_buffer) +{ + return cb_buffer->indio_dev; +} +EXPORT_SYMBOL_GPL(iio_channel_cb_get_iio_dev); + MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>"); MODULE_DESCRIPTION("Industrial I/O callback buffer"); MODULE_LICENSE("GPL"); diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h index 3d672f7..9edccfb 100644 --- a/include/linux/iio/consumer.h +++ b/include/linux/iio/consumer.h @@ -165,6 +165,18 @@ struct iio_channel *iio_channel_cb_get_channels(const struct iio_cb_buffer *cb_buffer); /** + * iio_channel_cb_get_iio_dev() - get access to the underlying device. + * @cb_buffer: The callback buffer from whom we want the device + * information. + * + * This function allows one to obtain information about the device. + * The primary aim is to allow drivers that are consuming a device to query + * things like current trigger. + */ +struct iio_dev +*iio_channel_cb_get_iio_dev(const struct iio_cb_buffer *cb_buffer); + +/** * iio_read_channel_raw() - read from a given channel * @chan: The channel being queried. * @val: Value read back. -- cgit v0.10.2 From 4d671b71beefbfc145b971a11e0c3cabde94b673 Mon Sep 17 00:00:00 2001 From: Matt Ranostay <mranostay@gmail.com> Date: Fri, 19 Aug 2016 20:17:03 -0700 Subject: iio: adc: ti-adc161s626: add support for TI 1-channel differential ADCs Add support for Texas Instruments ADC141S626, and ADC161S626 chips. Signed-off-by: Matt Ranostay <mranostay@gmail.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/Documentation/devicetree/bindings/iio/adc/ti-adc161s626.txt b/Documentation/devicetree/bindings/iio/adc/ti-adc161s626.txt new file mode 100644 index 0000000..9ed2315 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/ti-adc161s626.txt @@ -0,0 +1,16 @@ +* Texas Instruments ADC141S626 and ADC161S626 chips + +Required properties: + - compatible: Should be "ti,adc141s626" or "ti,adc161s626" + - reg: spi chip select number for the device + +Recommended properties: + - spi-max-frequency: Definition as per + Documentation/devicetree/bindings/spi/spi-bus.txt + +Example: +adc@0 { + compatible = "ti,adc161s626"; + reg = <0>; + spi-max-frequency = <4300000>; +}; diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 1de31bd..f06cff7e 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -426,6 +426,18 @@ config TI_ADC128S052 This driver can also be built as a module. If so, the module will be called ti-adc128s052. +config TI_ADC161S626 + tristate "Texas Instruments ADC161S626 1-channel differential ADC" + depends on SPI + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + If you say yes here you get support for Texas Instruments ADC141S626, + and ADC161S626 chips. + + This driver can also be built as a module. If so, the module will be + called ti-adc161s626. + config TI_ADS1015 tristate "Texas Instruments ADS1015 ADC" depends on I2C && !SENSORS_ADS1015 diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 0ba0d50..1d80577 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -41,6 +41,7 @@ obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o obj-$(CONFIG_TI_ADC128S052) += ti-adc128s052.o +obj-$(CONFIG_TI_ADC161S626) += ti-adc161s626.o obj-$(CONFIG_TI_ADS1015) += ti-ads1015.o obj-$(CONFIG_TI_ADS8688) += ti-ads8688.o obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o diff --git a/drivers/iio/adc/ti-adc161s626.c b/drivers/iio/adc/ti-adc161s626.c new file mode 100644 index 0000000..f94b69f --- /dev/null +++ b/drivers/iio/adc/ti-adc161s626.c @@ -0,0 +1,248 @@ +/* + * ti-adc161s626.c - Texas Instruments ADC161S626 1-channel differential ADC + * + * ADC Devices Supported: + * adc141s626 - 14-bit ADC + * adc161s626 - 16-bit ADC + * + * Copyright (C) 2016 Matt Ranostay <mranostay@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/err.h> +#include <linux/spi/spi.h> +#include <linux/iio/iio.h> +#include <linux/iio/trigger.h> +#include <linux/iio/buffer.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/iio/triggered_buffer.h> + +#define TI_ADC_DRV_NAME "ti-adc161s626" + +enum { + TI_ADC141S626, + TI_ADC161S626, +}; + +static const struct iio_chan_spec ti_adc141s626_channels[] = { + { + .type = IIO_VOLTAGE, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .scan_index = 0, + .scan_type = { + .sign = 's', + .realbits = 14, + .storagebits = 16, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(1), +}; + +static const struct iio_chan_spec ti_adc161s626_channels[] = { + { + .type = IIO_VOLTAGE, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .scan_index = 0, + .scan_type = { + .sign = 's', + .realbits = 16, + .storagebits = 16, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(1), +}; + +struct ti_adc_data { + struct iio_dev *indio_dev; + struct spi_device *spi; + u8 read_size; + u8 shift; + + u8 buffer[16] ____cacheline_aligned; +}; + +static int ti_adc_read_measurement(struct ti_adc_data *data, + struct iio_chan_spec const *chan, int *val) +{ + int ret; + + switch (data->read_size) { + case 2: { + __be16 buf; + + ret = spi_read(data->spi, (void *) &buf, 2); + if (ret) + return ret; + + *val = be16_to_cpu(buf); + break; + } + case 3: { + __be32 buf; + + ret = spi_read(data->spi, (void *) &buf, 3); + if (ret) + return ret; + + *val = be32_to_cpu(buf) >> 8; + break; + } + default: + return -EINVAL; + } + + *val = sign_extend32(*val >> data->shift, chan->scan_type.realbits - 1); + + return 0; +} + +static irqreturn_t ti_adc_trigger_handler(int irq, void *private) +{ + struct iio_poll_func *pf = private; + struct iio_dev *indio_dev = pf->indio_dev; + struct ti_adc_data *data = iio_priv(indio_dev); + int ret; + + ret = ti_adc_read_measurement(data, &indio_dev->channels[0], + (int *) &data->buffer); + if (!ret) + iio_push_to_buffers_with_timestamp(indio_dev, + data->buffer, + iio_get_time_ns(indio_dev)); + + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static int ti_adc_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct ti_adc_data *data = iio_priv(indio_dev); + int ret; + + if (mask != IIO_CHAN_INFO_RAW) + return -EINVAL; + + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + + ret = ti_adc_read_measurement(data, chan, val); + iio_device_release_direct_mode(indio_dev); + + if (!ret) + return IIO_VAL_INT; + + return 0; +} + +static const struct iio_info ti_adc_info = { + .driver_module = THIS_MODULE, + .read_raw = ti_adc_read_raw, +}; + +static int ti_adc_probe(struct spi_device *spi) +{ + struct iio_dev *indio_dev; + struct ti_adc_data *data; + int ret; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + indio_dev->info = &ti_adc_info; + indio_dev->dev.parent = &spi->dev; + indio_dev->dev.of_node = spi->dev.of_node; + 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; + + switch (spi_get_device_id(spi)->driver_data) { + case TI_ADC141S626: + indio_dev->channels = ti_adc141s626_channels; + indio_dev->num_channels = ARRAY_SIZE(ti_adc141s626_channels); + data->shift = 0; + data->read_size = 2; + break; + case TI_ADC161S626: + indio_dev->channels = ti_adc161s626_channels; + indio_dev->num_channels = ARRAY_SIZE(ti_adc161s626_channels); + data->shift = 6; + data->read_size = 3; + break; + } + + ret = iio_triggered_buffer_setup(indio_dev, NULL, + ti_adc_trigger_handler, NULL); + if (ret) + return ret; + + ret = iio_device_register(indio_dev); + if (ret) + goto error_unreg_buffer; + + return 0; + +error_unreg_buffer: + iio_triggered_buffer_cleanup(indio_dev); + + return ret; +} + +static int ti_adc_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + + iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); + + return 0; +} + +static const struct of_device_id ti_adc_dt_ids[] = { + { .compatible = "ti,adc141s626", }, + { .compatible = "ti,adc161s626", }, + {} +}; +MODULE_DEVICE_TABLE(of, ti_adc_dt_ids); + +static const struct spi_device_id ti_adc_id[] = { + {"adc141s626", TI_ADC141S626}, + {"adc161s626", TI_ADC161S626}, + {}, +}; +MODULE_DEVICE_TABLE(spi, ti_adc_id); + +static struct spi_driver ti_adc_driver = { + .driver = { + .name = TI_ADC_DRV_NAME, + .of_match_table = of_match_ptr(ti_adc_dt_ids), + }, + .probe = ti_adc_probe, + .remove = ti_adc_remove, + .id_table = ti_adc_id, +}; +module_spi_driver(ti_adc_driver); + +MODULE_AUTHOR("Matt Ranostay <mranostay@gmail.com>"); +MODULE_DESCRIPTION("Texas Instruments ADC1x1S 1-channel differential ADC"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From b015b3e32187225ff1265c4b13f84559fd22ecd7 Mon Sep 17 00:00:00 2001 From: Matt Ranostay <mranostay@gmail.com> Date: Fri, 19 Aug 2016 13:36:09 -0700 Subject: iio: chemical: atlas-ph-sensor: switch to iio_device_*_direct_mode helpers Signed-off-by: Matt Ranostay <mranostay@gmail.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/chemical/atlas-ph-sensor.c b/drivers/iio/chemical/atlas-ph-sensor.c index ae038a5..6968754 100644 --- a/drivers/iio/chemical/atlas-ph-sensor.c +++ b/drivers/iio/chemical/atlas-ph-sensor.c @@ -402,15 +402,13 @@ static int atlas_read_raw(struct iio_dev *indio_dev, case IIO_PH: case IIO_CONCENTRATION: case IIO_ELECTRICALCONDUCTIVITY: - mutex_lock(&indio_dev->mlock); + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; - if (iio_buffer_enabled(indio_dev)) - ret = -EBUSY; - else - ret = atlas_read_measurement(data, - chan->address, ®); + ret = atlas_read_measurement(data, chan->address, ®); - mutex_unlock(&indio_dev->mlock); + iio_device_release_direct_mode(indio_dev); break; default: ret = -EINVAL; -- cgit v0.10.2 From d7c0e5ae70205be94809c887b8f621dd226ea2f2 Mon Sep 17 00:00:00 2001 From: Matt Ranostay <mranostay@gmail.com> Date: Fri, 19 Aug 2016 13:36:10 -0700 Subject: iio: chemical: atlas-ph-sensor: switch to REGCACHE_NONE regmap tree Since there are overlapping volatile regions between parts, and only register that isn't volatile is the temperature compensation provided from userspace. Signed-off-by: Matt Ranostay <mranostay@gmail.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/chemical/atlas-ph-sensor.c b/drivers/iio/chemical/atlas-ph-sensor.c index 6968754..c0a0ebb 100644 --- a/drivers/iio/chemical/atlas-ph-sensor.c +++ b/drivers/iio/chemical/atlas-ph-sensor.c @@ -84,26 +84,10 @@ struct atlas_data { __be32 buffer[6]; /* 96-bit data + 32-bit pad + 64-bit timestamp */ }; -static const struct regmap_range atlas_volatile_ranges[] = { - regmap_reg_range(ATLAS_REG_INT_CONTROL, ATLAS_REG_INT_CONTROL), - regmap_reg_range(ATLAS_REG_PH_DATA, ATLAS_REG_PH_DATA + 4), - regmap_reg_range(ATLAS_REG_EC_DATA, ATLAS_REG_PSS_DATA + 4), -}; - -static const struct regmap_access_table atlas_volatile_table = { - .yes_ranges = atlas_volatile_ranges, - .n_yes_ranges = ARRAY_SIZE(atlas_volatile_ranges), -}; - static const struct regmap_config atlas_regmap_config = { .name = ATLAS_REGMAP_NAME, - .reg_bits = 8, .val_bits = 8, - - .volatile_table = &atlas_volatile_table, - .max_register = ATLAS_REG_PSS_DATA + 4, - .cache_type = REGCACHE_RBTREE, }; static const struct iio_chan_spec atlas_ph_channels[] = { -- cgit v0.10.2 From ce08cc986ed6bcd43fcbef83ef6efc62a2d44eef Mon Sep 17 00:00:00 2001 From: Matt Ranostay <mranostay@gmail.com> Date: Fri, 19 Aug 2016 13:36:11 -0700 Subject: iio: chemical: atlas-ph-sensor: add ORP feature Signed-off-by: Matt Ranostay <mranostay@gmail.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/Documentation/devicetree/bindings/iio/chemical/atlas,orp-sm.txt b/Documentation/devicetree/bindings/iio/chemical/atlas,orp-sm.txt new file mode 100644 index 0000000..5d8b687 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/chemical/atlas,orp-sm.txt @@ -0,0 +1,22 @@ +* Atlas Scientific ORP-SM OEM sensor + +https://www.atlas-scientific.com/_files/_datasheets/_oem/ORP_oem_datasheet.pdf + +Required properties: + + - compatible: must be "atlas,orp-sm" + - reg: the I2C address of the sensor + - interrupt-parent: should be the phandle for the interrupt controller + - interrupts: the sole interrupt generated by the device + + Refer to interrupt-controller/interrupts.txt for generic interrupt client + node bindings. + +Example: + +atlas@66 { + compatible = "atlas,orp-sm"; + reg = <0x66>; + interrupt-parent = <&gpio1>; + interrupts = <16 2>; +}; diff --git a/drivers/iio/chemical/Kconfig b/drivers/iio/chemical/Kconfig index 4bcc025..cea7f98 100644 --- a/drivers/iio/chemical/Kconfig +++ b/drivers/iio/chemical/Kconfig @@ -16,6 +16,7 @@ config ATLAS_PH_SENSOR Atlas Scientific OEM SM sensors: * pH SM sensor * EC SM sensor + * ORP SM sensor To compile this driver as module, choose M here: the module will be called atlas-ph-sensor. diff --git a/drivers/iio/chemical/atlas-ph-sensor.c b/drivers/iio/chemical/atlas-ph-sensor.c index c0a0ebb..84fbff3 100644 --- a/drivers/iio/chemical/atlas-ph-sensor.c +++ b/drivers/iio/chemical/atlas-ph-sensor.c @@ -66,12 +66,17 @@ #define ATLAS_REG_TDS_DATA 0x1c #define ATLAS_REG_PSS_DATA 0x20 +#define ATLAS_REG_ORP_CALIB_STATUS 0x0d +#define ATLAS_REG_ORP_DATA 0x0e + #define ATLAS_PH_INT_TIME_IN_US 450000 #define ATLAS_EC_INT_TIME_IN_US 650000 +#define ATLAS_ORP_INT_TIME_IN_US 450000 enum { ATLAS_PH_SM, ATLAS_EC_SM, + ATLAS_ORP_SM, }; struct atlas_data { @@ -159,6 +164,23 @@ static const struct iio_chan_spec atlas_ec_channels[] = { }, }; +static const struct iio_chan_spec atlas_orp_channels[] = { + { + .type = IIO_VOLTAGE, + .address = ATLAS_REG_ORP_DATA, + .info_mask_separate = + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .scan_index = 0, + .scan_type = { + .sign = 's', + .realbits = 32, + .storagebits = 32, + .endianness = IIO_BE, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(1), +}; + static int atlas_check_ph_calibration(struct atlas_data *data) { struct device *dev = &data->client->dev; @@ -224,6 +246,22 @@ static int atlas_check_ec_calibration(struct atlas_data *data) return 0; } +static int atlas_check_orp_calibration(struct atlas_data *data) +{ + struct device *dev = &data->client->dev; + int ret; + unsigned int val; + + ret = regmap_read(data->regmap, ATLAS_REG_ORP_CALIB_STATUS, &val); + if (ret) + return ret; + + if (!val) + dev_warn(dev, "device has not been calibrated\n"); + + return 0; +}; + struct atlas_device { const struct iio_chan_spec *channels; int num_channels; @@ -248,7 +286,13 @@ static struct atlas_device atlas_devices[] = { .calibration = &atlas_check_ec_calibration, .delay = ATLAS_EC_INT_TIME_IN_US, }, - + [ATLAS_ORP_SM] = { + .channels = atlas_orp_channels, + .num_channels = 2, + .data_reg = ATLAS_REG_ORP_DATA, + .calibration = &atlas_check_orp_calibration, + .delay = ATLAS_ORP_INT_TIME_IN_US, + }, }; static int atlas_set_powermode(struct atlas_data *data, int on) @@ -386,6 +430,7 @@ static int atlas_read_raw(struct iio_dev *indio_dev, case IIO_PH: case IIO_CONCENTRATION: case IIO_ELECTRICALCONDUCTIVITY: + case IIO_VOLTAGE: ret = iio_device_claim_direct_mode(indio_dev); if (ret) return ret; @@ -422,6 +467,10 @@ static int atlas_read_raw(struct iio_dev *indio_dev, *val = 0; /* 0.000000001 */ *val2 = 1000; return IIO_VAL_INT_PLUS_NANO; + case IIO_VOLTAGE: + *val = 1; /* 0.1 */ + *val2 = 10; + break; default: return -EINVAL; } @@ -457,6 +506,7 @@ static const struct iio_info atlas_info = { static const struct i2c_device_id atlas_id[] = { { "atlas-ph-sm", ATLAS_PH_SM}, { "atlas-ec-sm", ATLAS_EC_SM}, + { "atlas-orp-sm", ATLAS_ORP_SM}, {} }; MODULE_DEVICE_TABLE(i2c, atlas_id); @@ -464,6 +514,7 @@ MODULE_DEVICE_TABLE(i2c, atlas_id); static const struct of_device_id atlas_dt_ids[] = { { .compatible = "atlas,ph-sm", .data = (void *)ATLAS_PH_SM, }, { .compatible = "atlas,ec-sm", .data = (void *)ATLAS_EC_SM, }, + { .compatible = "atlas,orp-sm", .data = (void *)ATLAS_ORP_SM, }, { } }; MODULE_DEVICE_TABLE(of, atlas_dt_ids); -- cgit v0.10.2 From d1682a9a7a2eac4b3b7541f25848f7b1d7286918 Mon Sep 17 00:00:00 2001 From: Johanna Abrahamsson <johanna@mjao.org> Date: Tue, 16 Aug 2016 15:02:58 +0200 Subject: staging: iio: ade7854: checkpatch fixes (alignment of parameters) CHECK: Alignment should match open parenthesis Signed-off-by: Johanna Abrahamsson <johanna@mjao.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/staging/iio/meter/ade7854.c b/drivers/staging/iio/meter/ade7854.c index 75e8685..24edbc3 100644 --- a/drivers/staging/iio/meter/ade7854.c +++ b/drivers/staging/iio/meter/ade7854.c @@ -23,8 +23,8 @@ #include "ade7854.h" static ssize_t ade7854_read_8bit(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { int ret; u8 val = 0; @@ -40,8 +40,8 @@ static ssize_t ade7854_read_8bit(struct device *dev, } static ssize_t ade7854_read_16bit(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { int ret; u16 val = 0; @@ -57,8 +57,8 @@ static ssize_t ade7854_read_16bit(struct device *dev, } static ssize_t ade7854_read_24bit(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { int ret; u32 val; @@ -74,8 +74,8 @@ static ssize_t ade7854_read_24bit(struct device *dev, } static ssize_t ade7854_read_32bit(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { int ret; u32 val = 0; @@ -91,9 +91,9 @@ static ssize_t ade7854_read_32bit(struct device *dev, } static ssize_t ade7854_write_8bit(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_attr *this_attr = to_iio_dev_attr(attr); struct iio_dev *indio_dev = dev_to_iio_dev(dev); @@ -112,9 +112,9 @@ error_ret: } static ssize_t ade7854_write_16bit(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_attr *this_attr = to_iio_dev_attr(attr); struct iio_dev *indio_dev = dev_to_iio_dev(dev); @@ -133,9 +133,9 @@ error_ret: } static ssize_t ade7854_write_24bit(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_attr *this_attr = to_iio_dev_attr(attr); struct iio_dev *indio_dev = dev_to_iio_dev(dev); @@ -154,9 +154,9 @@ error_ret: } static ssize_t ade7854_write_32bit(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_attr *this_attr = to_iio_dev_attr(attr); struct iio_dev *indio_dev = dev_to_iio_dev(dev); -- cgit v0.10.2 From 3978732f3c5bf23439f3c31c6c588d88a51591e9 Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Tue, 16 Aug 2016 16:18:14 -0400 Subject: staging: lustre: llite: add md_op_data parameter to ll_get_dir_page Pass in struct md_op_data for ll_get_dir_page function. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/7043 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3531 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 031c9e4..82c7f88 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -322,8 +322,8 @@ static struct page *ll_dir_page_locate(struct inode *dir, __u64 *hash, return page; } -struct page *ll_get_dir_page(struct inode *dir, __u64 hash, - struct ll_dir_chain *chain) +struct page *ll_get_dir_page(struct inode *dir, struct md_op_data *op_data, + __u64 hash, struct ll_dir_chain *chain) { ldlm_policy_data_t policy = {.l_inodebits = {MDS_INODELOCK_UPDATE} }; struct address_space *mapping = dir->i_mapping; @@ -503,7 +503,7 @@ int ll_dir_read(struct inode *inode, __u64 *ppos, struct md_op_data *op_data, ll_dir_chain_init(&chain); - page = ll_get_dir_page(inode, pos, &chain); + page = ll_get_dir_page(inode, op_data, pos, &chain); while (rc == 0 && !done) { struct lu_dirpage *dp; @@ -585,7 +585,7 @@ int ll_dir_read(struct inode *inode, __u64 *ppos, struct md_op_data *op_data, le32_to_cpu(dp->ldp_flags) & LDF_COLLIDE); next = pos; - page = ll_get_dir_page(inode, pos, + page = ll_get_dir_page(inode, op_data, pos, &chain); } } diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index dc15957..fc0c72c 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -651,8 +651,8 @@ void ll_rw_stats_tally(struct ll_sb_info *sbi, pid_t pid, void ll_release_page(struct page *page, int remove); extern const struct file_operations ll_dir_operations; extern const struct inode_operations ll_dir_inode_operations; -struct page *ll_get_dir_page(struct inode *dir, __u64 hash, - struct ll_dir_chain *chain); +struct page *ll_get_dir_page(struct inode *dir, struct md_op_data *op_data, + __u64 hash, struct ll_dir_chain *chain); int ll_dir_read(struct inode *inode, __u64 *ppos, struct md_op_data *op_data, struct dir_context *ctx); diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c index 54ed52e..1b222c7 100644 --- a/drivers/staging/lustre/lustre/llite/statahead.c +++ b/drivers/staging/lustre/lustre/llite/statahead.c @@ -1067,7 +1067,7 @@ static int ll_statahead_thread(void *arg) wake_up(&thread->t_ctl_waitq); ll_dir_chain_init(&chain); - page = ll_get_dir_page(dir, pos, &chain); + page = ll_get_dir_page(dir, op_data, pos, &chain); while (1) { struct lu_dirpage *dp; @@ -1232,7 +1232,7 @@ do_it: ll_release_page(page, le32_to_cpu(dp->ldp_flags) & LDF_COLLIDE); sai->sai_in_readpage = 1; - page = ll_get_dir_page(dir, pos, &chain); + page = ll_get_dir_page(dir, op_data, pos, &chain); sai->sai_in_readpage = 0; } } @@ -1344,13 +1344,19 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry) { struct ll_dir_chain chain; const struct qstr *target = &dentry->d_name; + struct md_op_data *op_data; struct page *page; __u64 pos = 0; int dot_de; int rc = LS_NONE_FIRST_DE; + op_data = ll_prep_md_op_data(NULL, dir, dir, NULL, 0, 0, + LUSTRE_OPC_ANY, dir); + if (IS_ERR(op_data)) + return PTR_ERR(op_data); + ll_dir_chain_init(&chain); - page = ll_get_dir_page(dir, pos, &chain); + page = ll_get_dir_page(dir, op_data, pos, &chain); while (1) { struct lu_dirpage *dp; @@ -1438,12 +1444,13 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry) */ ll_release_page(page, le32_to_cpu(dp->ldp_flags) & LDF_COLLIDE); - page = ll_get_dir_page(dir, pos, &chain); + page = ll_get_dir_page(dir, op_data, pos, &chain); } } out: ll_dir_chain_fini(&chain); + ll_finish_md_op_data(op_data); return rc; } -- cgit v0.10.2 From 6833c103cc962310f070837b6b4f3bf9e6b989cc Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Tue, 16 Aug 2016 16:18:15 -0400 Subject: staging: lustre: llite: remove comment from ll_dir_read Remove comment about fixing swabbing that is not needed. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/7043 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3531 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 82c7f88..d854edd 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -526,10 +526,6 @@ int ll_dir_read(struct inode *inode, __u64 *ppos, struct md_op_data *op_data, __u64 lhash; __u64 ino; - /* - * XXX: implement correct swabbing here. - */ - hash = le64_to_cpu(ent->lde_hash); if (hash < pos) /* -- cgit v0.10.2 From 5b8d9852315ca055c78fb94ea7c2354377f20090 Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Tue, 16 Aug 2016 16:18:16 -0400 Subject: staging: lustre: llite: style cleanup for llite_internal.h Group function prototypes together related to dir.c. Move ll_release_page to be with function declarations. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/7043 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3531 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index fc0c72c..1ced397 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -648,15 +648,15 @@ void ll_rw_stats_tally(struct ll_sb_info *sbi, pid_t pid, size_t count, int rw); /* llite/dir.c */ -void ll_release_page(struct page *page, int remove); extern const struct file_operations ll_dir_operations; extern const struct inode_operations ll_dir_inode_operations; -struct page *ll_get_dir_page(struct inode *dir, struct md_op_data *op_data, - __u64 hash, struct ll_dir_chain *chain); int ll_dir_read(struct inode *inode, __u64 *ppos, struct md_op_data *op_data, struct dir_context *ctx); - int ll_get_mdt_idx(struct inode *inode); +struct page *ll_get_dir_page(struct inode *dir, struct md_op_data *op_data, + __u64 hash, struct ll_dir_chain *chain); +void ll_release_page(struct page *page, int remove); + /* llite/namei.c */ extern const struct inode_operations ll_special_inode_operations; -- cgit v0.10.2 From 006e4dcd41b137554f38e1cd8fea893c2255cab3 Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Tue, 16 Aug 2016 16:18:17 -0400 Subject: staging: lustre: llite: pass inode to ll_release_page Add a inode parameter to ll_release_page. This will be used in the future. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/7043 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3531 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index d854edd..3a800b2 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -236,7 +236,7 @@ static int ll_dir_filler(void *_hash, struct page *page0) return rc; } -void ll_release_page(struct page *page, int remove) +void ll_release_page(struct inode *inode, struct page *page, int remove) { kunmap(page); if (remove) { @@ -297,7 +297,7 @@ static struct page *ll_dir_page_locate(struct inode *dir, __u64 *hash, CDEBUG(D_VFSTRACE, "page %lu [%llu %llu], hash %llu\n", offset, *start, *end, *hash); if (*hash > *end) { - ll_release_page(page, 0); + ll_release_page(dir, page, 0); page = NULL; } else if (*end != *start && *hash == *end) { /* @@ -306,8 +306,9 @@ static struct page *ll_dir_page_locate(struct inode *dir, __u64 *hash, * ll_get_dir_page() will issue RPC to fetch * the page we want. */ - ll_release_page(page, - le32_to_cpu(dp->ldp_flags) & LDF_COLLIDE); + ll_release_page(dir, page, + le32_to_cpu(dp->ldp_flags) & + LDF_COLLIDE); page = NULL; } } else { @@ -462,7 +463,7 @@ out_unlock: return page; fail: - ll_release_page(page, 1); + ll_release_page(dir, page, 1); page = ERR_PTR(-EIO); goto out_unlock; } @@ -560,7 +561,7 @@ int ll_dir_read(struct inode *inode, __u64 *ppos, struct md_op_data *op_data, if (done) { pos = hash; - ll_release_page(page, 0); + ll_release_page(inode, page, 0); break; } @@ -571,13 +572,13 @@ int ll_dir_read(struct inode *inode, __u64 *ppos, struct md_op_data *op_data, * End of directory reached. */ done = 1; - ll_release_page(page, 0); + ll_release_page(inode, page, 0); } else { /* * Normal case: continue to the next * page. */ - ll_release_page(page, + ll_release_page(inode, page, le32_to_cpu(dp->ldp_flags) & LDF_COLLIDE); next = pos; diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 1ced397..4b03a64 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -655,7 +655,7 @@ int ll_dir_read(struct inode *inode, __u64 *ppos, struct md_op_data *op_data, int ll_get_mdt_idx(struct inode *inode); struct page *ll_get_dir_page(struct inode *dir, struct md_op_data *op_data, __u64 hash, struct ll_dir_chain *chain); -void ll_release_page(struct page *page, int remove); +void ll_release_page(struct inode *inode, struct page *page, int remove); /* llite/namei.c */ extern const struct inode_operations ll_special_inode_operations; diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c index 1b222c7..2949ff6 100644 --- a/drivers/staging/lustre/lustre/llite/statahead.c +++ b/drivers/staging/lustre/lustre/llite/statahead.c @@ -1142,7 +1142,7 @@ interpret_it: ll_post_statahead(sai); if (unlikely(!thread_is_running(thread))) { - ll_release_page(page, 0); + ll_release_page(dir, page, 0); rc = 0; goto out; } @@ -1166,7 +1166,7 @@ interpret_it: if (unlikely( !thread_is_running(thread))) { - ll_release_page(page, 0); + ll_release_page(dir, page, 0); rc = 0; goto out; } @@ -1189,7 +1189,7 @@ do_it: /* * End of directory reached. */ - ll_release_page(page, 0); + ll_release_page(dir, page, 0); while (1) { l_wait_event(thread->t_ctl_waitq, !list_empty(&sai->sai_entries_received) || @@ -1229,8 +1229,9 @@ do_it: * chain is exhausted. * Normal case: continue to the next page. */ - ll_release_page(page, le32_to_cpu(dp->ldp_flags) & - LDF_COLLIDE); + ll_release_page(dir, page, + le32_to_cpu(dp->ldp_flags) & + LDF_COLLIDE); sai->sai_in_readpage = 1; page = ll_get_dir_page(dir, op_data, pos, &chain); sai->sai_in_readpage = 0; @@ -1427,7 +1428,7 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry) else rc = LS_FIRST_DOT_DE; - ll_release_page(page, 0); + ll_release_page(dir, page, 0); goto out; } pos = le64_to_cpu(dp->ldp_hash_end); @@ -1435,15 +1436,16 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry) /* * End of directory reached. */ - ll_release_page(page, 0); + ll_release_page(dir, page, 0); goto out; } else { /* * chain is exhausted * Normal case: continue to the next page. */ - ll_release_page(page, le32_to_cpu(dp->ldp_flags) & - LDF_COLLIDE); + ll_release_page(dir, page, + le32_to_cpu(dp->ldp_flags) & + LDF_COLLIDE); page = ll_get_dir_page(dir, op_data, pos, &chain); } } -- cgit v0.10.2 From 77a782ab70d3a35812f6ad0e13e5cea72b3b6694 Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Tue, 16 Aug 2016 16:18:18 -0400 Subject: staging: lustre: llite: change remove parameter to bool Change the 3rd parameter remove to a bool for ll_release_page function. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/7043 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3531 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 3a800b2..a72b486 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -236,7 +236,7 @@ static int ll_dir_filler(void *_hash, struct page *page0) return rc; } -void ll_release_page(struct inode *inode, struct page *page, int remove) +void ll_release_page(struct inode *inode, struct page *page, bool remove) { kunmap(page); if (remove) { @@ -297,7 +297,7 @@ static struct page *ll_dir_page_locate(struct inode *dir, __u64 *hash, CDEBUG(D_VFSTRACE, "page %lu [%llu %llu], hash %llu\n", offset, *start, *end, *hash); if (*hash > *end) { - ll_release_page(dir, page, 0); + ll_release_page(dir, page, false); page = NULL; } else if (*end != *start && *hash == *end) { /* @@ -463,7 +463,7 @@ out_unlock: return page; fail: - ll_release_page(dir, page, 1); + ll_release_page(dir, page, true); page = ERR_PTR(-EIO); goto out_unlock; } @@ -561,7 +561,7 @@ int ll_dir_read(struct inode *inode, __u64 *ppos, struct md_op_data *op_data, if (done) { pos = hash; - ll_release_page(inode, page, 0); + ll_release_page(inode, page, false); break; } @@ -572,7 +572,7 @@ int ll_dir_read(struct inode *inode, __u64 *ppos, struct md_op_data *op_data, * End of directory reached. */ done = 1; - ll_release_page(inode, page, 0); + ll_release_page(inode, page, false); } else { /* * Normal case: continue to the next diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 4b03a64..07b6918 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -655,7 +655,7 @@ int ll_dir_read(struct inode *inode, __u64 *ppos, struct md_op_data *op_data, int ll_get_mdt_idx(struct inode *inode); struct page *ll_get_dir_page(struct inode *dir, struct md_op_data *op_data, __u64 hash, struct ll_dir_chain *chain); -void ll_release_page(struct inode *inode, struct page *page, int remove); +void ll_release_page(struct inode *inode, struct page *page, bool remove); /* llite/namei.c */ extern const struct inode_operations ll_special_inode_operations; diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c index 2949ff6..6ce7442 100644 --- a/drivers/staging/lustre/lustre/llite/statahead.c +++ b/drivers/staging/lustre/lustre/llite/statahead.c @@ -1142,7 +1142,7 @@ interpret_it: ll_post_statahead(sai); if (unlikely(!thread_is_running(thread))) { - ll_release_page(dir, page, 0); + ll_release_page(dir, page, false); rc = 0; goto out; } @@ -1166,7 +1166,7 @@ interpret_it: if (unlikely( !thread_is_running(thread))) { - ll_release_page(dir, page, 0); + ll_release_page(dir, page, false); rc = 0; goto out; } @@ -1189,7 +1189,7 @@ do_it: /* * End of directory reached. */ - ll_release_page(dir, page, 0); + ll_release_page(dir, page, false); while (1) { l_wait_event(thread->t_ctl_waitq, !list_empty(&sai->sai_entries_received) || @@ -1428,7 +1428,7 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry) else rc = LS_FIRST_DOT_DE; - ll_release_page(dir, page, 0); + ll_release_page(dir, page, false); goto out; } pos = le64_to_cpu(dp->ldp_hash_end); @@ -1436,7 +1436,7 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry) /* * End of directory reached. */ - ll_release_page(dir, page, 0); + ll_release_page(dir, page, false); goto out; } else { /* -- cgit v0.10.2 From a0d73eb569cd4fee48d35b9ce636587fa05ed145 Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Tue, 16 Aug 2016 16:18:19 -0400 Subject: staging: lustre: mdc: don't take rpc lock for readdir case If the operation is IT_READDIR don't need to handle the mdc RPC lock. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/10761 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4906 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre_mdc.h b/drivers/staging/lustre/lustre/include/lustre_mdc.h index fa62b95..0a8c639 100644 --- a/drivers/staging/lustre/lustre/include/lustre_mdc.h +++ b/drivers/staging/lustre/lustre/include/lustre_mdc.h @@ -96,7 +96,7 @@ static inline void mdc_get_rpc_lock(struct mdc_rpc_lock *lck, struct lookup_intent *it) { if (it && (it->it_op == IT_GETATTR || it->it_op == IT_LOOKUP || - it->it_op == IT_LAYOUT)) + it->it_op == IT_LAYOUT || it->it_op == IT_READDIR)) return; /* This would normally block until the existing request finishes. @@ -136,7 +136,7 @@ static inline void mdc_put_rpc_lock(struct mdc_rpc_lock *lck, struct lookup_intent *it) { if (it && (it->it_op == IT_GETATTR || it->it_op == IT_LOOKUP || - it->it_op == IT_LAYOUT)) + it->it_op == IT_LAYOUT || it->it_op == IT_READDIR)) return; if (lck->rpcl_it == MDC_FAKE_RPCL_IT) { /* OBD_FAIL_MDC_RPCS_SEM */ -- cgit v0.10.2 From 53126787a2a969a45c049fbdfbab6f8ac225b8f3 Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Tue, 16 Aug 2016 16:18:20 -0400 Subject: staging: lustre: lmv: remove unused lmv_get_mea function The function lmv_get_mea() is not used so remove it. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/7043 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3531 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/lmv/lmv_internal.h b/drivers/staging/lustre/lustre/lmv/lmv_internal.h index 471470b..ab01560 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_internal.h +++ b/drivers/staging/lustre/lustre/lmv/lmv_internal.h @@ -55,30 +55,6 @@ int __lmv_fid_alloc(struct lmv_obd *lmv, struct lu_fid *fid, u32 mds); int lmv_fid_alloc(struct obd_export *exp, struct lu_fid *fid, struct md_op_data *op_data); -static inline struct lmv_stripe_md *lmv_get_mea(struct ptlrpc_request *req) -{ - struct mdt_body *body; - struct lmv_stripe_md *mea; - - LASSERT(req); - - body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); - - if (!body || !S_ISDIR(body->mode) || !body->eadatasize) - return NULL; - - mea = req_capsule_server_sized_get(&req->rq_pill, &RMF_MDT_MD, - body->eadatasize); - if (mea->mea_count == 0) - return NULL; - if (mea->mea_magic != MEA_MAGIC_LAST_CHAR && - mea->mea_magic != MEA_MAGIC_ALL_CHARS && - mea->mea_magic != MEA_MAGIC_HASH_SEGMENT) - return NULL; - - return mea; -} - static inline int lmv_get_easize(struct lmv_obd *lmv) { return sizeof(struct lmv_stripe_md) + -- cgit v0.10.2 From e7deb890c5f345fb2a685de342f364d1370c28ad Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Tue, 16 Aug 2016 16:18:21 -0400 Subject: staging: lustre: lmv: remove duplicate MAX_HASH_* The MAX_HASH_* macros already exist in obd.h. Remove the duplicated defines in lustre_idl.h. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/7043 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3531 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 32471a6..5f31724 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -2486,10 +2486,6 @@ struct lmv_desc { #define MEA_MAGIC_ALL_CHARS 0xb222a11c #define MEA_MAGIC_HASH_SEGMENT 0xb222a11b -#define MAX_HASH_SIZE_32 0x7fffffffUL -#define MAX_HASH_SIZE 0x7fffffffffffffffULL -#define MAX_HASH_HIGHEST_BIT 0x1000000000000000ULL - /* lmv structures */ #define LMV_MAGIC_V1 0x0CD10CD0 /* normal stripe lmv magic */ #define LMV_USER_MAGIC 0x0CD20CD0 /* default lmv magic*/ -- cgit v0.10.2 From fad3a392b42d6ea03a3254e21bca1fc7db5a8d6c Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Tue, 16 Aug 2016 16:18:22 -0400 Subject: staging: lustre: lmv: change handling of lmv striping information The lmv_[un]pack_md function are used to calculate the size of the data used to represent the LMV striping data. The original code was straight forward in its calculate with lmv_get_easize since only one type of data format could exist. We want to be able to support different version of this data in the future so this patch moves to generating the size of the data using the stripe count and which LMV_MAGIC_* version. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/7043 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3531 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 5f31724..0ad6605 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -2482,10 +2482,6 @@ struct lmv_desc { struct obd_uuid ld_uuid; }; -#define MEA_MAGIC_LAST_CHAR 0xb2221ca1 -#define MEA_MAGIC_ALL_CHARS 0xb222a11c -#define MEA_MAGIC_HASH_SEGMENT 0xb222a11b - /* lmv structures */ #define LMV_MAGIC_V1 0x0CD10CD0 /* normal stripe lmv magic */ #define LMV_USER_MAGIC 0x0CD20CD0 /* default lmv magic*/ diff --git a/drivers/staging/lustre/lustre/include/lustre_lmv.h b/drivers/staging/lustre/lustre/include/lustre_lmv.h index 0620c8c..784d67b 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lmv.h +++ b/drivers/staging/lustre/lustre/include/lustre_lmv.h @@ -41,12 +41,15 @@ struct lmv_oinfo { }; struct lmv_stripe_md { - __u32 mea_magic; - __u32 mea_count; - __u32 mea_master; - __u32 mea_padding; - char mea_pool_name[LOV_MAXPOOLNAME]; - struct lu_fid mea_ids[0]; + __u32 lsm_md_magic; + __u32 lsm_md_stripe_count; + __u32 lsm_md_master_mdt_index; + __u32 lsm_md_hash_type; + __u32 lsm_md_layout_version; + __u32 lsm_md_default_count; + __u32 lsm_md_default_index; + char lsm_md_pool_name[LOV_MAXPOOLNAME]; + struct lmv_oinfo lsm_md_oinfo[0]; }; union lmv_mds_md; diff --git a/drivers/staging/lustre/lustre/lmv/lmv_internal.h b/drivers/staging/lustre/lustre/lmv/lmv_internal.h index ab01560..90a9786 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_internal.h +++ b/drivers/staging/lustre/lustre/lmv/lmv_internal.h @@ -94,6 +94,13 @@ lmv_find_target(struct lmv_obd *lmv, const struct lu_fid *fid) return lmv_get_target(lmv, mds); } +static inline int lmv_stripe_md_size(int stripe_count) +{ + struct lmv_stripe_md *lsm; + + return sizeof(*lsm) + stripe_count * sizeof(lsm->lsm_md_oinfo[0]); +} + struct lmv_tgt_desc *lmv_locate_mds(struct lmv_obd *lmv, struct md_op_data *op_data, struct lu_fid *fid); diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 8e83263..1ba5900 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -2376,105 +2376,224 @@ static int lmv_set_info_async(const struct lu_env *env, struct obd_export *exp, return -EINVAL; } -static int lmv_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, - struct lov_stripe_md *lsm) +static int lmv_pack_md_v1(const struct lmv_stripe_md *lsm, + struct lmv_mds_md_v1 *lmm1) { - struct obd_device *obd = class_exp2obd(exp); - struct lmv_obd *lmv = &obd->u.lmv; - struct lmv_stripe_md *meap; - struct lmv_stripe_md *lsmp; - int mea_size; - int i; + int cplen; + int i; + + lmm1->lmv_magic = cpu_to_le32(lsm->lsm_md_magic); + lmm1->lmv_stripe_count = cpu_to_le32(lsm->lsm_md_stripe_count); + lmm1->lmv_master_mdt_index = cpu_to_le32(lsm->lsm_md_master_mdt_index); + lmm1->lmv_hash_type = cpu_to_le32(lsm->lsm_md_hash_type); + cplen = strlcpy(lmm1->lmv_pool_name, lsm->lsm_md_pool_name, + sizeof(lmm1->lmv_pool_name)); + if (cplen >= sizeof(lmm1->lmv_pool_name)) + return -E2BIG; + + for (i = 0; i < lsm->lsm_md_stripe_count; i++) + fid_cpu_to_le(&lmm1->lmv_stripe_fids[i], + &lsm->lsm_md_oinfo[i].lmo_fid); + return 0; +} + +int lmv_pack_md(union lmv_mds_md **lmmp, const struct lmv_stripe_md *lsm, + int stripe_count) +{ + int lmm_size = 0, rc = 0; + bool allocated = false; - mea_size = lmv_get_easize(lmv); - if (!lmmp) - return mea_size; + LASSERT(lmmp); + /* Free lmm */ if (*lmmp && !lsm) { + int stripe_cnt; + + stripe_cnt = lmv_mds_md_stripe_count_get(*lmmp); + lmm_size = lmv_mds_md_size(stripe_cnt, + le32_to_cpu((*lmmp)->lmv_magic)); + if (!lmm_size) + return -EINVAL; kvfree(*lmmp); *lmmp = NULL; return 0; } + /* Alloc lmm */ + if (!*lmmp && !lsm) { + lmm_size = lmv_mds_md_size(stripe_count, LMV_MAGIC); + LASSERT(lmm_size > 0); + *lmmp = libcfs_kvzalloc(lmm_size, GFP_NOFS); + if (!*lmmp) + return -ENOMEM; + lmv_mds_md_stripe_count_set(*lmmp, stripe_count); + (*lmmp)->lmv_magic = cpu_to_le32(LMV_MAGIC); + return lmm_size; + } + + /* pack lmm */ + LASSERT(lsm); + lmm_size = lmv_mds_md_size(lsm->lsm_md_stripe_count, + lsm->lsm_md_magic); if (!*lmmp) { - *lmmp = libcfs_kvzalloc(mea_size, GFP_NOFS); + *lmmp = libcfs_kvzalloc(lmm_size, GFP_NOFS); if (!*lmmp) return -ENOMEM; + allocated = true; } - if (!lsm) - return mea_size; + switch (lsm->lsm_md_magic) { + case LMV_MAGIC_V1: + rc = lmv_pack_md_v1(lsm, &(*lmmp)->lmv_md_v1); + break; + default: + rc = -EINVAL; + break; + } - lsmp = (struct lmv_stripe_md *)lsm; - meap = (struct lmv_stripe_md *)*lmmp; + if (rc && allocated) { + kvfree(*lmmp); + *lmmp = NULL; + } - if (lsmp->mea_magic != MEA_MAGIC_LAST_CHAR && - lsmp->mea_magic != MEA_MAGIC_ALL_CHARS) - return -EINVAL; + return lmm_size; +} +EXPORT_SYMBOL(lmv_pack_md); - meap->mea_magic = cpu_to_le32(lsmp->mea_magic); - meap->mea_count = cpu_to_le32(lsmp->mea_count); - meap->mea_master = cpu_to_le32(lsmp->mea_master); +static int lmv_unpack_md_v1(struct obd_export *exp, struct lmv_stripe_md *lsm, + const struct lmv_mds_md_v1 *lmm1) +{ + struct lmv_obd *lmv = &exp->exp_obd->u.lmv; + int stripe_count; + int rc = 0; + int cplen; + int i; - for (i = 0; i < lmv->desc.ld_tgt_count; i++) { - meap->mea_ids[i] = lsmp->mea_ids[i]; - fid_cpu_to_le(&meap->mea_ids[i], &lsmp->mea_ids[i]); + lsm->lsm_md_magic = le32_to_cpu(lmm1->lmv_magic); + lsm->lsm_md_stripe_count = le32_to_cpu(lmm1->lmv_stripe_count); + lsm->lsm_md_master_mdt_index = le32_to_cpu(lmm1->lmv_master_mdt_index); + lsm->lsm_md_hash_type = le32_to_cpu(lmm1->lmv_hash_type); + lsm->lsm_md_layout_version = le32_to_cpu(lmm1->lmv_layout_version); + cplen = strlcpy(lsm->lsm_md_pool_name, lmm1->lmv_pool_name, + sizeof(lsm->lsm_md_pool_name)); + + if (cplen >= sizeof(lsm->lsm_md_pool_name)) + return -E2BIG; + + CDEBUG(D_INFO, "unpack lsm count %d, master %d hash_type %d layout_version %d\n", + lsm->lsm_md_stripe_count, lsm->lsm_md_master_mdt_index, + lsm->lsm_md_hash_type, lsm->lsm_md_layout_version); + + stripe_count = le32_to_cpu(lmm1->lmv_stripe_count); + for (i = 0; i < le32_to_cpu(stripe_count); i++) { + fid_le_to_cpu(&lsm->lsm_md_oinfo[i].lmo_fid, + &lmm1->lmv_stripe_fids[i]); + rc = lmv_fld_lookup(lmv, &lsm->lsm_md_oinfo[i].lmo_fid, + &lsm->lsm_md_oinfo[i].lmo_mds); + if (rc) + return rc; + CDEBUG(D_INFO, "unpack fid #%d "DFID"\n", i, + PFID(&lsm->lsm_md_oinfo[i].lmo_fid)); } - return mea_size; + return rc; } -static int lmv_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, - struct lov_mds_md *lmm, int lmm_size) +int lmv_unpack_md(struct obd_export *exp, struct lmv_stripe_md **lsmp, + const union lmv_mds_md *lmm, int stripe_count) { - struct obd_device *obd = class_exp2obd(exp); - struct lmv_stripe_md **tmea = (struct lmv_stripe_md **)lsmp; - struct lmv_stripe_md *mea = (struct lmv_stripe_md *)lmm; - struct lmv_obd *lmv = &obd->u.lmv; - int mea_size; - int i; - __u32 magic; + struct lmv_stripe_md *lsm; + bool allocated = false; + int lsm_size, rc; + + LASSERT(lsmp); + + lsm = *lsmp; + /* Free memmd */ + if (lsm && !lmm) { + int i; - mea_size = lmv_get_easize(lmv); - if (!lsmp) - return mea_size; + for (i = 1; i < lsm->lsm_md_stripe_count; i++) { + if (lsm->lsm_md_oinfo[i].lmo_root) + iput(lsm->lsm_md_oinfo[i].lmo_root); + } - if (*lsmp && !lmm) { - kvfree(*tmea); + kvfree(lsm); *lsmp = NULL; return 0; } - LASSERT(mea_size == lmm_size); + /* Alloc memmd */ + if (!lsm && !lmm) { + lsm_size = lmv_stripe_md_size(stripe_count); + lsm = libcfs_kvzalloc(lsm_size, GFP_NOFS); + if (!lsm) + return -ENOMEM; + lsm->lsm_md_stripe_count = stripe_count; + *lsmp = lsm; + return 0; + } - *tmea = libcfs_kvzalloc(mea_size, GFP_NOFS); - if (!*tmea) - return -ENOMEM; + /* Unpack memmd */ + if (le32_to_cpu(lmm->lmv_magic) != LMV_MAGIC_V1) { + CERROR("%s: invalid magic %x.\n", exp->exp_obd->obd_name, + le32_to_cpu(lmm->lmv_magic)); + return -EINVAL; + } - if (!lmm) - return mea_size; + lsm_size = lmv_stripe_md_size(lmv_mds_md_stripe_count_get(lmm)); + if (!lsm) { + lsm = libcfs_kvzalloc(lsm_size, GFP_NOFS); + if (!lsm) + return -ENOMEM; + allocated = true; + *lsmp = lsm; + } - if (mea->mea_magic == MEA_MAGIC_LAST_CHAR || - mea->mea_magic == MEA_MAGIC_ALL_CHARS || - mea->mea_magic == MEA_MAGIC_HASH_SEGMENT) { - magic = le32_to_cpu(mea->mea_magic); - } else { - /* - * Old mea is not handled here. - */ - CERROR("Old not supportable EA is found\n"); - LBUG(); + switch (le32_to_cpu(lmm->lmv_magic)) { + case LMV_MAGIC_V1: + rc = lmv_unpack_md_v1(exp, lsm, &lmm->lmv_md_v1); + break; + default: + CERROR("%s: unrecognized magic %x\n", exp->exp_obd->obd_name, + le32_to_cpu(lmm->lmv_magic)); + rc = -EINVAL; + break; } - (*tmea)->mea_magic = magic; - (*tmea)->mea_count = le32_to_cpu(mea->mea_count); - (*tmea)->mea_master = le32_to_cpu(mea->mea_master); + if (rc && allocated) { + kvfree(lsm); + *lsmp = NULL; + lsm_size = rc; + } + return lsm_size; +} - for (i = 0; i < (*tmea)->mea_count; i++) { - (*tmea)->mea_ids[i] = mea->mea_ids[i]; - fid_le_to_cpu(&(*tmea)->mea_ids[i], &(*tmea)->mea_ids[i]); +int lmv_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, + struct lov_mds_md *lmm, int disk_len) +{ + return lmv_unpack_md(exp, (struct lmv_stripe_md **)lsmp, + (union lmv_mds_md *)lmm, disk_len); +} + +int lmv_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, + struct lov_stripe_md *lsm) +{ + const struct lmv_stripe_md *lmv = (struct lmv_stripe_md *)lsm; + struct obd_device *obd = exp->exp_obd; + struct lmv_obd *lmv_obd = &obd->u.lmv; + int stripe_count; + + if (!lmmp) { + if (lsm) + stripe_count = lmv->lsm_md_stripe_count; + else + stripe_count = lmv_obd->desc.ld_tgt_count; + + return lmv_mds_md_size(stripe_count, LMV_MAGIC_V1); } - return mea_size; + + return lmv_pack_md((union lmv_mds_md **)lmmp, lmv, 0); } static int lmv_cancel_unused(struct obd_export *exp, const struct lu_fid *fid, -- cgit v0.10.2 From 0bc6f19e54e337da39d9c5a1f7554ecdc8ed5ada Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Tue, 16 Aug 2016 16:18:23 -0400 Subject: staging: lustre: lmv: remove lmv_get_easize Completely replace lmv_get_easize with lmv_mds_md_size. With this change we can delete lmv_get_easize. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/7043 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3531 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/lmv/lmv_internal.h b/drivers/staging/lustre/lustre/lmv/lmv_internal.h index 90a9786..f4c917b 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_internal.h +++ b/drivers/staging/lustre/lustre/lmv/lmv_internal.h @@ -55,13 +55,6 @@ int __lmv_fid_alloc(struct lmv_obd *lmv, struct lu_fid *fid, u32 mds); int lmv_fid_alloc(struct obd_export *exp, struct lu_fid *fid, struct md_op_data *op_data); -static inline int lmv_get_easize(struct lmv_obd *lmv) -{ - return sizeof(struct lmv_stripe_md) + - lmv->desc.ld_tgt_count * - sizeof(struct lu_fid); -} - static inline struct lmv_tgt_desc * lmv_get_target(struct lmv_obd *lmv, u32 mds) { diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 1ba5900..0b1260d 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -558,7 +558,7 @@ int lmv_check_connect(struct obd_device *obd) lmv_set_timeouts(obd); class_export_put(lmv->exp); lmv->connected = 1; - easize = lmv_get_easize(lmv); + easize = lmv_mds_md_size(lmv->desc.ld_tgt_count, LMV_MAGIC); lmv_init_ea_size(obd->obd_self_export, easize, 0, 0, 0); mutex_unlock(&lmv->lmv_init_mutex); return 0; -- cgit v0.10.2 From 5ce536b336515781ed2f9f04a014a7fd1d27b594 Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Tue, 16 Aug 2016 16:18:24 -0400 Subject: staging: lustre: lmv: replace obd_free_memmd with lmv_free_memmd Use lmv_free_memmd for proper cleanup instead of the generic obd_free_memmd. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/7043 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3531 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 0b1260d..6be2afc 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -2692,7 +2692,7 @@ static int lmv_free_lustre_md(struct obd_export *exp, struct lustre_md *md) struct lmv_tgt_desc *tgt = lmv->tgts[0]; if (md->lmv) - obd_free_memmd(exp, (void *)&md->lmv); + lmv_free_memmd(md->lmv); if (!tgt || !tgt->ltd_exp) return -EINVAL; return md_free_lustre_md(tgt->ltd_exp, md); -- cgit v0.10.2 From 2de35386078259584911fc0e25e7555ffca12300 Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Tue, 16 Aug 2016 16:18:25 -0400 Subject: staging: lustre: create striped directory 1. client send create request to the master MDT, which will allocate FIDs and create slaves. for all of slaves. 2. Client needs to revalidate slaves during intent getattr and open request. 3. lmv_stripe_md will include attributes(size, nlink etc) from all of stripe, which will be protected by UPDATE lock. client needs to merge these attributes when update inode. 4. send create request to the MDT where the file is located, which can help creating master stripe of striped directory. Signed-off-by: wang di <di.wang@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3529 Reviewed-on: http://review.whamcloud.com/7196 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index 3cd4a25..0fa71a5 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -191,6 +191,9 @@ struct cl_attr { * Group identifier for quota purposes. */ gid_t cat_gid; + + /* nlink of the directory */ + __u64 cat_nlink; }; /** diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 0ad6605..a612080 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -1610,6 +1610,7 @@ static inline void lmm_oi_cpu_to_le(struct ost_id *dst_oi, #define XATTR_NAME_LOV "trusted.lov" #define XATTR_NAME_LMA "trusted.lma" #define XATTR_NAME_LMV "trusted.lmv" +#define XATTR_NAME_DEFAULT_LMV "trusted.dmv" #define XATTR_NAME_LINK "trusted.link" #define XATTR_NAME_FID "trusted.fid" #define XATTR_NAME_VERSION "trusted.version" @@ -2472,7 +2473,7 @@ struct lmv_desc { __u32 ld_tgt_count; /* how many MDS's */ __u32 ld_active_tgt_count; /* how many active */ __u32 ld_default_stripe_count; /* how many objects are used */ - __u32 ld_pattern; /* default MEA_MAGIC_* */ + __u32 ld_pattern; /* default hash pattern */ __u64 ld_default_hash_size; __u64 ld_padding_1; /* also fix lustre_swab_lmv_desc */ __u32 ld_padding_2; /* also fix lustre_swab_lmv_desc */ @@ -2486,6 +2487,43 @@ struct lmv_desc { #define LMV_MAGIC_V1 0x0CD10CD0 /* normal stripe lmv magic */ #define LMV_USER_MAGIC 0x0CD20CD0 /* default lmv magic*/ #define LMV_MAGIC LMV_MAGIC_V1 + +enum lmv_hash_type { + LMV_HASH_TYPE_ALL_CHARS = 1, + LMV_HASH_TYPE_FNV_1A_64 = 2, +}; + +#define LMV_HASH_NAME_ALL_CHARS "all_char" +#define LMV_HASH_NAME_FNV_1A_64 "fnv_1a_64" + +/** + * The FNV-1a hash algorithm is as follows: + * hash = FNV_offset_basis + * for each octet_of_data to be hashed + * hash = hash XOR octet_of_data + * hash = hash × FNV_prime + * return hash + * http://en.wikipedia.org/wiki/Fowler–Noll–Vo_hash_function#FNV-1a_hash + * + * http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-reference-source + * FNV_prime is 2^40 + 2^8 + 0xb3 = 0x100000001b3ULL + **/ +#define LUSTRE_FNV_1A_64_PRIME 0x100000001b3ULL +#define LUSTRE_FNV_1A_64_OFFSET_BIAS 0xcbf29ce484222325ULL +static inline __u64 lustre_hash_fnv_1a_64(const void *buf, size_t size) +{ + __u64 hash = LUSTRE_FNV_1A_64_OFFSET_BIAS; + const unsigned char *p = buf; + size_t i; + + for (i = 0; i < size; i++) { + hash ^= p[i]; + hash *= LUSTRE_FNV_1A_64_PRIME; + } + + return hash; +} + struct lmv_mds_md_v1 { __u32 lmv_magic; __u32 lmv_stripe_count; /* stripe count */ diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index ef6f38f..d496d0e 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -374,19 +374,17 @@ struct lov_user_mds_data_v3 { } __packed; #endif -/* keep this to be the same size as lov_user_ost_data_v1 */ struct lmv_user_mds_data { struct lu_fid lum_fid; __u32 lum_padding; __u32 lum_mds; }; -/* lum_type */ -enum { - LMV_STRIPE_TYPE = 0, - LMV_DEFAULT_TYPE = 1, -}; - +/* + * Got this according to how get LOV_MAX_STRIPE_COUNT, see above, + * (max buffer size - lmv+rpc header) / sizeof(struct lmv_user_mds_data) + */ +#define LMV_MAX_STRIPE_COUNT 2000 /* ((12 * 4096 - 256) / 24) */ #define lmv_user_md lmv_user_md_v1 struct lmv_user_md_v1 { __u32 lum_magic; /* must be the first field */ @@ -399,7 +397,7 @@ struct lmv_user_md_v1 { __u32 lum_padding3; char lum_pool_name[LOV_MAXPOOLNAME]; struct lmv_user_mds_data lum_objects[0]; -}; +} __packed; static inline int lmv_user_md_size(int stripes, int lmm_magic) { @@ -407,6 +405,8 @@ static inline int lmv_user_md_size(int stripes, int lmm_magic) stripes * sizeof(struct lmv_user_mds_data); } +void lustre_swab_lmv_user_md(struct lmv_user_md *lum); + struct ll_recreate_obj { __u64 lrc_id; __u32 lrc_ost_idx; diff --git a/drivers/staging/lustre/lustre/include/lustre_lib.h b/drivers/staging/lustre/lustre/include/lustre_lib.h index 06958f2..def0193 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lib.h +++ b/drivers/staging/lustre/lustre/include/lustre_lib.h @@ -391,6 +391,8 @@ static inline void obd_ioctl_freedata(char *buf, int len) #define LOVEA_DELETE_VALUES(size, count, offset) (size == 0 && count == 0 && \ offset == (typeof(offset))(-1)) +#define LMVEA_DELETE_VALUES(count, offset) ((count) == 0 && \ + (offset) == (typeof(offset))(-1)) /* #define POISON_BULK 0 */ /* diff --git a/drivers/staging/lustre/lustre/include/lustre_lmv.h b/drivers/staging/lustre/lustre/include/lustre_lmv.h index 784d67b..4036fce 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lmv.h +++ b/drivers/staging/lustre/lustre/include/lustre_lmv.h @@ -66,4 +66,63 @@ static inline void lmv_free_memmd(struct lmv_stripe_md *lsm) { lmv_unpack_md(NULL, &lsm, NULL, 0); } + +static inline void lmv1_cpu_to_le(struct lmv_mds_md_v1 *lmv_dst, + const struct lmv_mds_md_v1 *lmv_src) +{ + int i; + + lmv_dst->lmv_magic = cpu_to_le32(lmv_src->lmv_magic); + lmv_dst->lmv_stripe_count = cpu_to_le32(lmv_src->lmv_stripe_count); + lmv_dst->lmv_master_mdt_index = + cpu_to_le32(lmv_src->lmv_master_mdt_index); + lmv_dst->lmv_hash_type = cpu_to_le32(lmv_src->lmv_hash_type); + lmv_dst->lmv_layout_version = cpu_to_le32(lmv_src->lmv_layout_version); + + for (i = 0; i < lmv_src->lmv_stripe_count; i++) + fid_cpu_to_le(&lmv_dst->lmv_stripe_fids[i], + &lmv_src->lmv_stripe_fids[i]); +} + +static inline void lmv1_le_to_cpu(struct lmv_mds_md_v1 *lmv_dst, + const struct lmv_mds_md_v1 *lmv_src) +{ + int i; + + lmv_dst->lmv_magic = le32_to_cpu(lmv_src->lmv_magic); + lmv_dst->lmv_stripe_count = le32_to_cpu(lmv_src->lmv_stripe_count); + lmv_dst->lmv_master_mdt_index = + le32_to_cpu(lmv_src->lmv_master_mdt_index); + lmv_dst->lmv_hash_type = le32_to_cpu(lmv_src->lmv_hash_type); + lmv_dst->lmv_layout_version = le32_to_cpu(lmv_src->lmv_layout_version); + + for (i = 0; i < lmv_src->lmv_stripe_count; i++) + fid_le_to_cpu(&lmv_dst->lmv_stripe_fids[i], + &lmv_src->lmv_stripe_fids[i]); +} + +static inline void lmv_cpu_to_le(union lmv_mds_md *lmv_dst, + const union lmv_mds_md *lmv_src) +{ + switch (lmv_src->lmv_magic) { + case LMV_MAGIC_V1: + lmv1_cpu_to_le(&lmv_dst->lmv_md_v1, &lmv_src->lmv_md_v1); + break; + default: + break; + } +} + +static inline void lmv_le_to_cpu(union lmv_mds_md *lmv_dst, + const union lmv_mds_md *lmv_src) +{ + switch (le32_to_cpu(lmv_src->lmv_magic)) { + case LMV_MAGIC_V1: + lmv1_le_to_cpu(&lmv_dst->lmv_md_v1, &lmv_src->lmv_md_v1); + break; + default: + break; + } +} + #endif diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 17b8d22..a9f4e13 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -1022,14 +1022,6 @@ enum { }; /* lmv structures */ -#define MEA_MAGIC_LAST_CHAR 0xb2221ca1 -#define MEA_MAGIC_ALL_CHARS 0xb222a11c -#define MEA_MAGIC_HASH_SEGMENT 0xb222a11b - -#define MAX_HASH_SIZE_32 0x7fffffffUL -#define MAX_HASH_SIZE 0x7fffffffffffffffULL -#define MAX_HASH_HIGHEST_BIT 0x1000000000000000ULL - struct lustre_md { struct mdt_body *body; struct lov_stripe_md *lsm; @@ -1049,6 +1041,7 @@ struct md_open_data { }; struct lookup_intent; +struct cl_attr; struct md_ops { int (*getstatus)(struct obd_export *, struct lu_fid *); @@ -1109,6 +1102,13 @@ struct md_ops { int (*free_lustre_md)(struct obd_export *, struct lustre_md *); + int (*merge_attr)(struct obd_export *, + const struct lmv_stripe_md *lsm, + struct cl_attr *attr); + + int (*update_lsm_md)(struct obd_export *, struct lmv_stripe_md *lsm, + struct mdt_body *, ldlm_blocking_callback); + int (*set_open_replay_data)(struct obd_export *, struct obd_client_handle *, struct lookup_intent *); diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index 6482a93..2f111a8 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -1559,6 +1559,25 @@ static inline int md_free_lustre_md(struct obd_export *exp, return MDP(exp->exp_obd, free_lustre_md)(exp, md); } +static inline int md_update_lsm_md(struct obd_export *exp, + struct lmv_stripe_md *lsm, + struct mdt_body *body, + ldlm_blocking_callback cb) +{ + EXP_CHECK_MD_OP(exp, update_lsm_md); + EXP_MD_COUNTER_INCREMENT(exp, update_lsm_md); + return MDP(exp->exp_obd, update_lsm_md)(exp, lsm, body, cb); +} + +static inline int md_merge_attr(struct obd_export *exp, + const struct lmv_stripe_md *lsm, + struct cl_attr *attr) +{ + EXP_CHECK_MD_OP(exp, merge_attr); + EXP_MD_COUNTER_INCREMENT(exp, merge_attr); + return MDP(exp->exp_obd, merge_attr)(exp, lsm, attr); +} + static inline int md_setxattr(struct obd_export *exp, const struct lu_fid *fid, u64 valid, const char *name, const char *input, int input_size, diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index a72b486..a0560b6 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -668,7 +668,7 @@ static int ll_send_mgc_param(struct obd_export *mgc, char *string) } static int ll_dir_setdirstripe(struct inode *dir, struct lmv_user_md *lump, - char *filename) + const char *filename) { struct ptlrpc_request *request = NULL; struct md_op_data *op_data; @@ -676,6 +676,26 @@ static int ll_dir_setdirstripe(struct inode *dir, struct lmv_user_md *lump, int mode; int err; + if (unlikely(lump->lum_magic != LMV_USER_MAGIC)) + return -EINVAL; + + if (lump->lum_stripe_offset == (__u32)-1) { + int mdtidx; + + mdtidx = ll_get_mdt_idx(dir); + if (mdtidx < 0) + return mdtidx; + + lump->lum_stripe_offset = mdtidx; + } + + CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p) name %s stripe_offset %d, stripe_count: %u\n", + PFID(ll_inode2fid(dir)), dir, filename, + (int)lump->lum_stripe_offset, lump->lum_stripe_count); + + if (lump->lum_magic != cpu_to_le32(LMV_USER_MAGIC)) + lustre_swab_lmv_user_md(lump); + mode = (~current_umask() & 0755) | S_IFDIR; op_data = ll_prep_md_op_data(NULL, dir, NULL, filename, strlen(filename), mode, LUSTRE_OPC_MKDIR, @@ -745,9 +765,6 @@ int ll_dir_setstripe(struct inode *inode, struct lov_user_md *lump, if (IS_ERR(op_data)) return PTR_ERR(op_data); - if (lump && lump->lmm_magic == cpu_to_le32(LMV_USER_MAGIC)) - op_data->op_cli_flags |= CLI_SET_MEA; - /* swabbing is done in lov_setstripe() on server side */ rc = md_setattr(sbi->ll_md_exp, op_data, lump, lum_size, NULL, 0, &req, NULL); @@ -1424,7 +1441,6 @@ lmv_out_free: } *tmp = lum; - tmp->lum_type = LMV_STRIPE_TYPE; tmp->lum_stripe_count = 1; mdtindex = ll_get_mdt_idx(inode); if (mdtindex < 0) { diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 58a7401..18fb713 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -3015,6 +3015,27 @@ out: return rc; } +static int ll_merge_md_attr(struct inode *inode) +{ + struct cl_attr attr = { 0 }; + int rc; + + LASSERT(ll_i2info(inode)->lli_lsm_md); + rc = md_merge_attr(ll_i2mdexp(inode), ll_i2info(inode)->lli_lsm_md, + &attr); + if (rc) + return rc; + + ll_i2info(inode)->lli_stripe_dir_size = attr.cat_size; + ll_i2info(inode)->lli_stripe_dir_nlink = attr.cat_nlink; + + ll_i2info(inode)->lli_atime = attr.cat_atime; + ll_i2info(inode)->lli_mtime = attr.cat_mtime; + ll_i2info(inode)->lli_ctime = attr.cat_ctime; + + return 0; +} + static int ll_inode_revalidate(struct dentry *dentry, __u64 ibits) { struct inode *inode = d_inode(dentry); @@ -3026,6 +3047,13 @@ static int ll_inode_revalidate(struct dentry *dentry, __u64 ibits) /* if object isn't regular file, don't validate size */ if (!S_ISREG(inode->i_mode)) { + if (S_ISDIR(inode->i_mode) && + ll_i2info(inode)->lli_lsm_md) { + rc = ll_merge_md_attr(inode); + if (rc) + return rc; + } + LTIME_S(inode->i_atime) = ll_i2info(inode)->lli_atime; LTIME_S(inode->i_mtime) = ll_i2info(inode)->lli_mtime; LTIME_S(inode->i_ctime) = ll_i2info(inode)->lli_ctime; @@ -3063,7 +3091,6 @@ int ll_getattr(struct vfsmount *mnt, struct dentry *de, struct kstat *stat) else stat->ino = inode->i_ino; stat->mode = inode->i_mode; - stat->nlink = inode->i_nlink; stat->uid = inode->i_uid; stat->gid = inode->i_gid; stat->rdev = inode->i_rdev; @@ -3071,10 +3098,17 @@ int ll_getattr(struct vfsmount *mnt, struct dentry *de, struct kstat *stat) stat->mtime = inode->i_mtime; stat->ctime = inode->i_ctime; stat->blksize = 1 << inode->i_blkbits; - - stat->size = i_size_read(inode); stat->blocks = inode->i_blocks; + if (S_ISDIR(inode->i_mode) && + ll_i2info(inode)->lli_lsm_md) { + stat->nlink = lli->lli_stripe_dir_nlink; + stat->size = lli->lli_stripe_dir_size; + } else { + stat->nlink = inode->i_nlink; + stat->size = i_size_read(inode); + } + return 0; } diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 07b6918..f3b8504 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -39,6 +39,7 @@ /* for struct cl_lock_descr and struct cl_io */ #include "../include/cl_object.h" +#include "../include/lustre_lmv.h" #include "../include/lustre_mdc.h" #include "../include/lustre_intent.h" #include <linux/compat.h> @@ -174,7 +175,11 @@ struct ll_inode_info { */ pid_t d_opendir_pid; /* directory stripe information */ - struct lmv_stripe_md *d_lmv_md; + struct lmv_stripe_md *d_lsm_md; + /* striped directory size */ + loff_t d_stripe_size; + /* striped directory nlink */ + __u64 d_stripe_nlink; } d; #define lli_readdir_mutex u.d.d_readdir_mutex @@ -182,7 +187,9 @@ struct ll_inode_info { #define lli_sai u.d.d_sai #define lli_sa_lock u.d.d_sa_lock #define lli_opendir_pid u.d.d_opendir_pid -#define lli_lmv_md u.d.d_lmv_md +#define lli_lsm_md u.d.d_lsm_md +#define lli_stripe_dir_size u.d.d_stripe_size +#define lli_stripe_dir_nlink u.d.d_stripe_nlink /* for non-directory */ struct { @@ -664,6 +671,7 @@ int ll_objects_destroy(struct ptlrpc_request *request, struct inode *dir); struct inode *ll_iget(struct super_block *sb, ino_t hash, struct lustre_md *lic); +int ll_test_inode_by_fid(struct inode *inode, void *opaque); int ll_md_blocking_ast(struct ldlm_lock *, struct ldlm_lock_desc *, void *data, int flag); struct dentry *ll_splice_alias(struct inode *inode, struct dentry *de); diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index eb715be..ef8d87a 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -992,6 +992,188 @@ struct inode *ll_inode_from_resource_lock(struct ldlm_lock *lock) return inode; } +static void ll_dir_clear_lsm_md(struct inode *inode) +{ + struct ll_inode_info *lli = ll_i2info(inode); + + LASSERT(S_ISDIR(inode->i_mode)); + + if (lli->lli_lsm_md) { + lmv_free_memmd(lli->lli_lsm_md); + lli->lli_lsm_md = NULL; + } +} + +static struct inode *ll_iget_anon_dir(struct super_block *sb, + const struct lu_fid *fid, + struct lustre_md *md) +{ + struct ll_sb_info *sbi = ll_s2sbi(sb); + struct mdt_body *body = md->body; + struct inode *inode; + ino_t ino; + + ino = cl_fid_build_ino(fid, sbi->ll_flags & LL_SBI_32BIT_API); + inode = iget_locked(sb, ino); + if (!inode) { + CERROR("%s: failed get simple inode "DFID": rc = -ENOENT\n", + ll_get_fsname(sb, NULL, 0), PFID(fid)); + return ERR_PTR(-ENOENT); + } + + if (inode->i_state & I_NEW) { + struct ll_inode_info *lli = ll_i2info(inode); + struct lmv_stripe_md *lsm = md->lmv; + + inode->i_mode = (inode->i_mode & ~S_IFMT) | + (body->mode & S_IFMT); + LASSERTF(S_ISDIR(inode->i_mode), "Not slave inode "DFID"\n", + PFID(fid)); + + LTIME_S(inode->i_mtime) = 0; + LTIME_S(inode->i_atime) = 0; + LTIME_S(inode->i_ctime) = 0; + inode->i_rdev = 0; + + inode->i_op = &ll_dir_inode_operations; + inode->i_fop = &ll_dir_operations; + lli->lli_fid = *fid; + ll_lli_init(lli); + + LASSERT(lsm); + /* master stripe FID */ + lli->lli_pfid = lsm->lsm_md_oinfo[0].lmo_fid; + CDEBUG(D_INODE, "lli %p master "DFID" slave "DFID"\n", + lli, PFID(fid), PFID(&lli->lli_pfid)); + unlock_new_inode(inode); + } + + return inode; +} + +static int ll_init_lsm_md(struct inode *inode, struct lustre_md *md) +{ + struct lmv_stripe_md *lsm = md->lmv; + struct lu_fid *fid; + int i; + + LASSERT(lsm); + /* + * XXX sigh, this lsm_root initialization should be in + * LMV layer, but it needs ll_iget right now, so we + * put this here right now. + */ + for (i = 0; i < lsm->lsm_md_stripe_count; i++) { + fid = &lsm->lsm_md_oinfo[i].lmo_fid; + LASSERT(!lsm->lsm_md_oinfo[i].lmo_root); + if (!i) { + lsm->lsm_md_oinfo[i].lmo_root = inode; + } else { + /* + * Unfortunately ll_iget will call ll_update_inode, + * where the initialization of slave inode is slightly + * different, so it reset lsm_md to NULL to avoid + * initializing lsm for slave inode. + */ + lsm->lsm_md_oinfo[i].lmo_root = + ll_iget_anon_dir(inode->i_sb, fid, md); + if (IS_ERR(lsm->lsm_md_oinfo[i].lmo_root)) { + int rc = PTR_ERR(lsm->lsm_md_oinfo[i].lmo_root); + + lsm->lsm_md_oinfo[i].lmo_root = NULL; + return rc; + } + } + } + + /* + * Here is where the lsm is being initialized(fill lmo_info) after + * client retrieve MD stripe information from MDT. + */ + return md_update_lsm_md(ll_i2mdexp(inode), lsm, md->body, + ll_md_blocking_ast); +} + +static inline int lli_lsm_md_eq(const struct lmv_stripe_md *lsm_md1, + const struct lmv_stripe_md *lsm_md2) +{ + return lsm_md1->lsm_md_magic == lsm_md2->lsm_md_magic && + lsm_md1->lsm_md_stripe_count == lsm_md2->lsm_md_stripe_count && + lsm_md1->lsm_md_master_mdt_index == + lsm_md2->lsm_md_master_mdt_index && + lsm_md1->lsm_md_hash_type == lsm_md2->lsm_md_hash_type && + lsm_md1->lsm_md_layout_version == + lsm_md2->lsm_md_layout_version && + !strcmp(lsm_md1->lsm_md_pool_name, + lsm_md2->lsm_md_pool_name); +} + +static void ll_update_lsm_md(struct inode *inode, struct lustre_md *md) +{ + struct ll_inode_info *lli = ll_i2info(inode); + struct lmv_stripe_md *lsm = md->lmv; + int idx; + + LASSERT(lsm); + LASSERT(S_ISDIR(inode->i_mode)); + if (!lli->lli_lsm_md) { + int rc; + + rc = ll_init_lsm_md(inode, md); + if (rc) { + CERROR("%s: init "DFID" failed: rc = %d\n", + ll_get_fsname(inode->i_sb, NULL, 0), + PFID(&lli->lli_fid), rc); + return; + } + lli->lli_lsm_md = lsm; + /* + * set lsm_md to NULL, so the following free lustre_md + * will not free this lsm + */ + md->lmv = NULL; + return; + } + + /* Compare the old and new stripe information */ + if (!lli_lsm_md_eq(lli->lli_lsm_md, lsm)) { + CERROR("inode %p %lu mismatch\n" + " new(%p) vs lli_lsm_md(%p):\n" + " magic: %x %x\n" + " count: %x %x\n" + " master: %x %x\n" + " hash_type: %x %x\n" + " layout: %x %x\n" + " pool: %s %s\n", + inode, inode->i_ino, lsm, lli->lli_lsm_md, + lsm->lsm_md_magic, lli->lli_lsm_md->lsm_md_magic, + lsm->lsm_md_stripe_count, + lli->lli_lsm_md->lsm_md_stripe_count, + lsm->lsm_md_master_mdt_index, + lli->lli_lsm_md->lsm_md_master_mdt_index, + lsm->lsm_md_hash_type, lli->lli_lsm_md->lsm_md_hash_type, + lsm->lsm_md_layout_version, + lli->lli_lsm_md->lsm_md_layout_version, + lsm->lsm_md_pool_name, + lli->lli_lsm_md->lsm_md_pool_name); + return; + } + + for (idx = 0; idx < lli->lli_lsm_md->lsm_md_stripe_count; idx++) { + if (!lu_fid_eq(&lli->lli_lsm_md->lsm_md_oinfo[idx].lmo_fid, + &lsm->lsm_md_oinfo[idx].lmo_fid)) { + CERROR("%s: FID in lsm mismatch idx %d, old: "DFID" new:"DFID"\n", + ll_get_fsname(inode->i_sb, NULL, 0), idx, + PFID(&lli->lli_lsm_md->lsm_md_oinfo[idx].lmo_fid), + PFID(&lsm->lsm_md_oinfo[idx].lmo_fid)); + return; + } + } + + md_update_lsm_md(ll_i2mdexp(inode), ll_i2info(inode)->lli_lsm_md, + md->body, ll_md_blocking_ast); +} + void ll_clear_inode(struct inode *inode) { struct ll_inode_info *lli = ll_i2info(inode); @@ -1039,7 +1221,9 @@ void ll_clear_inode(struct inode *inode) #endif lli->lli_inode_magic = LLI_INODE_DEAD; - if (!S_ISDIR(inode->i_mode)) + if (S_ISDIR(inode->i_mode)) + ll_dir_clear_lsm_md(inode); + else LASSERT(list_empty(&lli->lli_agl_list)); /* @@ -1484,6 +1668,9 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) lli->lli_maxbytes = MAX_LFS_FILESIZE; } + if (S_ISDIR(inode->i_mode) && md->lmv) + ll_update_lsm_md(inode, md); + #ifdef CONFIG_FS_POSIX_ACL if (body->valid & OBD_MD_FLACL) { spin_lock(&lli->lli_lock); @@ -2091,12 +2278,12 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, ll_i2gids(op_data->op_suppgids, i1, i2); op_data->op_fid1 = *ll_inode2fid(i1); if (S_ISDIR(i1->i_mode)) - op_data->op_mea1 = ll_i2info(i1)->lli_lmv_md; + op_data->op_mea1 = ll_i2info(i1)->lli_lsm_md; if (i2) { op_data->op_fid2 = *ll_inode2fid(i2); if (S_ISDIR(i2->i_mode)) - op_data->op_mea2 = ll_i2info(i2)->lli_lmv_md; + op_data->op_mea2 = ll_i2info(i2)->lli_lsm_md; } else { fid_zero(&op_data->op_fid2); } diff --git a/drivers/staging/lustre/lustre/llite/llite_nfs.c b/drivers/staging/lustre/lustre/llite/llite_nfs.c index 74eb1fc..ab9d5cc 100644 --- a/drivers/staging/lustre/lustre/llite/llite_nfs.c +++ b/drivers/staging/lustre/lustre/llite/llite_nfs.c @@ -73,11 +73,6 @@ void get_uuid2fsid(const char *name, int len, __kernel_fsid_t *fsid) fsid->val[1] = key >> 32; } -static int ll_nfs_test_inode(struct inode *inode, void *opaque) -{ - return lu_fid_eq(&ll_i2info(inode)->lli_fid, opaque); -} - struct inode *search_inode_for_lustre(struct super_block *sb, const struct lu_fid *fid) { @@ -92,7 +87,7 @@ struct inode *search_inode_for_lustre(struct super_block *sb, CDEBUG(D_INFO, "searching inode for:(%lu,"DFID")\n", hash, PFID(fid)); - inode = ilookup5(sb, hash, ll_nfs_test_inode, (void *)fid); + inode = ilookup5(sb, hash, ll_test_inode_by_fid, (void *)fid); if (inode) return inode; diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index 1e75f5b..e32d08b 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -158,6 +158,11 @@ static void ll_invalidate_negative_children(struct inode *dir) spin_unlock(&dir->i_lock); } +int ll_test_inode_by_fid(struct inode *inode, void *opaque) +{ + return lu_fid_eq(&ll_i2info(inode)->lli_fid, opaque); +} + int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, void *data, int flag) { @@ -253,10 +258,41 @@ int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, } if ((bits & MDS_INODELOCK_UPDATE) && S_ISDIR(inode->i_mode)) { - CDEBUG(D_INODE, "invalidating inode "DFID"\n", - PFID(ll_inode2fid(inode))); + struct ll_inode_info *lli = ll_i2info(inode); + + CDEBUG(D_INODE, "invalidating inode "DFID" lli = %p, pfid = "DFID"\n", + PFID(ll_inode2fid(inode)), lli, + PFID(&lli->lli_pfid)); + truncate_inode_pages(inode->i_mapping, 0); - ll_invalidate_negative_children(inode); + + if (unlikely(!fid_is_zero(&lli->lli_pfid))) { + struct inode *master_inode = NULL; + unsigned long hash; + + /* + * This is slave inode, since all of the child + * dentry is connected on the master inode, so + * we have to invalidate the negative children + * on master inode + */ + CDEBUG(D_INODE, "Invalidate s"DFID" m"DFID"\n", + PFID(ll_inode2fid(inode)), + PFID(&lli->lli_pfid)); + + hash = cl_fid_build_ino(&lli->lli_pfid, + ll_need_32bit_api(ll_i2sbi(inode))); + + master_inode = ilookup5(inode->i_sb, hash, + ll_test_inode_by_fid, + (void *)&lli->lli_pfid); + if (master_inode && !IS_ERR(master_inode)) { + ll_invalidate_negative_children(master_inode); + iput(master_inode); + } + } else { + ll_invalidate_negative_children(inode); + } } if ((bits & (MDS_INODELOCK_LOOKUP | MDS_INODELOCK_PERM)) && diff --git a/drivers/staging/lustre/lustre/lmv/lmv_intent.c b/drivers/staging/lustre/lustre/lmv/lmv_intent.c index 2f58fda..1b9bbb2 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_intent.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_intent.c @@ -150,6 +150,160 @@ out: return rc; } +int lmv_revalidate_slaves(struct obd_export *exp, struct mdt_body *mbody, + struct lmv_stripe_md *lsm, + ldlm_blocking_callback cb_blocking, + int extra_lock_flags) +{ + struct obd_device *obd = exp->exp_obd; + struct lmv_obd *lmv = &obd->u.lmv; + struct mdt_body *body; + struct md_op_data *op_data; + unsigned long size = 0; + unsigned long nlink = 0; + __s64 atime = 0; + __s64 ctime = 0; + __s64 mtime = 0; + int rc = 0, i; + + /** + * revalidate slaves has some problems, temporarily return, + * we may not need that + */ + if (lsm->lsm_md_stripe_count <= 1) + return 0; + + op_data = kzalloc(sizeof(*op_data), GFP_NOFS); + if (!op_data) + return -ENOMEM; + + /** + * Loop over the stripe information, check validity and update them + * from MDS if needed. + */ + for (i = 0; i < lsm->lsm_md_stripe_count; i++) { + struct lookup_intent it = { .it_op = IT_GETATTR }; + struct ptlrpc_request *req = NULL; + struct lustre_handle *lockh = NULL; + struct lmv_tgt_desc *tgt = NULL; + struct inode *inode; + struct lu_fid fid; + + fid = lsm->lsm_md_oinfo[i].lmo_fid; + inode = lsm->lsm_md_oinfo[i].lmo_root; + if (!i) { + if (mbody) { + body = mbody; + goto update; + } else { + goto release_lock; + } + } + + /* + * Prepare op_data for revalidating. Note that @fid2 shluld be + * defined otherwise it will go to server and take new lock + * which is not needed here. + */ + memset(op_data, 0, sizeof(*op_data)); + op_data->op_fid1 = fid; + op_data->op_fid2 = fid; + + tgt = lmv_locate_mds(lmv, op_data, &fid); + if (IS_ERR(tgt)) { + rc = PTR_ERR(tgt); + goto cleanup; + } + + CDEBUG(D_INODE, "Revalidate slave "DFID" -> mds #%d\n", + PFID(&fid), tgt->ltd_idx); + + rc = md_intent_lock(tgt->ltd_exp, op_data, NULL, 0, &it, 0, + &req, cb_blocking, extra_lock_flags); + if (rc < 0) + goto cleanup; + + lockh = (struct lustre_handle *)&it.it_lock_handle; + if (rc > 0 && !req) { + /* slave inode is still valid */ + CDEBUG(D_INODE, "slave "DFID" is still valid.\n", + PFID(&fid)); + rc = 0; + } else { + /* refresh slave from server */ + body = req_capsule_server_get(&req->rq_pill, + &RMF_MDT_BODY); + LASSERT(body); +update: + if (unlikely(body->nlink < 2)) { + CERROR("%s: nlink %d < 2 corrupt stripe %d "DFID":" DFID"\n", + obd->obd_name, body->nlink, i, + PFID(&lsm->lsm_md_oinfo[i].lmo_fid), + PFID(&lsm->lsm_md_oinfo[0].lmo_fid)); + + if (req) + ptlrpc_req_finished(req); + + rc = -EIO; + goto cleanup; + } + + if (i) + md_set_lock_data(tgt->ltd_exp, &lockh->cookie, + inode, NULL); + + i_size_write(inode, body->size); + set_nlink(inode, body->nlink); + LTIME_S(inode->i_atime) = body->atime; + LTIME_S(inode->i_ctime) = body->ctime; + LTIME_S(inode->i_mtime) = body->mtime; + + if (req) + ptlrpc_req_finished(req); + } +release_lock: + size += i_size_read(inode); + + if (i != 0) + nlink += inode->i_nlink - 2; + else + nlink += inode->i_nlink; + + atime = LTIME_S(inode->i_atime) > atime ? + LTIME_S(inode->i_atime) : atime; + ctime = LTIME_S(inode->i_ctime) > ctime ? + LTIME_S(inode->i_ctime) : ctime; + mtime = LTIME_S(inode->i_mtime) > mtime ? + LTIME_S(inode->i_mtime) : mtime; + + if (it.it_lock_mode && lockh) { + ldlm_lock_decref(lockh, it.it_lock_mode); + it.it_lock_mode = 0; + } + + CDEBUG(D_INODE, "i %d "DFID" size %llu, nlink %u, atime %lu, mtime %lu, ctime %lu.\n", + i, PFID(&fid), i_size_read(inode), inode->i_nlink, + LTIME_S(inode->i_atime), LTIME_S(inode->i_mtime), + LTIME_S(inode->i_ctime)); + } + + /* + * update attr of master request. + */ + CDEBUG(D_INODE, "Return refreshed attrs: size = %lu nlink %lu atime %llu ctime %llu mtime %llu for " DFID"\n", + size, nlink, atime, ctime, mtime, + PFID(&lsm->lsm_md_oinfo[0].lmo_fid)); + + if (mbody) { + mbody->atime = atime; + mbody->ctime = ctime; + mbody->mtime = mtime; + } +cleanup: + kfree(op_data); + return rc; +} + /* * IT_OPEN is intended to open (and create, possible) an object. Parent (pid) * may be split dir. @@ -166,9 +320,26 @@ static int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data, struct mdt_body *body; int rc; - tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1); - if (IS_ERR(tgt)) - return PTR_ERR(tgt); + if (it->it_flags & MDS_OPEN_BY_FID && fid_is_sane(&op_data->op_fid2)) { + if (op_data->op_mea1) { + struct lmv_stripe_md *lsm = op_data->op_mea1; + const struct lmv_oinfo *oinfo; + + oinfo = lsm_name_to_stripe_info(lsm, op_data->op_name, + op_data->op_namelen); + op_data->op_fid1 = oinfo->lmo_fid; + } + + tgt = lmv_find_target(lmv, &op_data->op_fid2); + if (IS_ERR(tgt)) + return PTR_ERR(tgt); + + op_data->op_mds = tgt->ltd_idx; + } else { + tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1); + if (IS_ERR(tgt)) + return PTR_ERR(tgt); + } /* If it is ready to open the file by FID, do not need * allocate FID at all, otherwise it will confuse MDT @@ -205,31 +376,18 @@ static int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data, body = req_capsule_server_get(&(*reqp)->rq_pill, &RMF_MDT_BODY); if (!body) return -EPROTO; - /* - * Not cross-ref case, just get out of here. - */ - if (likely(!(body->valid & OBD_MD_MDS))) - return 0; - /* - * Okay, MDS has returned success. Probably name has been resolved in - * remote inode. - */ - rc = lmv_intent_remote(exp, lmm, lmmsize, it, &op_data->op_fid1, flags, - reqp, cb_blocking, extra_lock_flags); - if (rc != 0) { - LASSERT(rc < 0); - /* - * This is possible, that some userspace application will try to - * open file as directory and we will have -ENOTDIR here. As - * this is normal situation, we should not print error here, - * only debug info. - */ - CDEBUG(D_INODE, "Can't handle remote %s: dir " DFID "(" DFID "):%*s: %d\n", - LL_IT2STR(it), PFID(&op_data->op_fid2), - PFID(&op_data->op_fid1), op_data->op_namelen, - op_data->op_name, rc); - return rc; + /* Not cross-ref case, just get out of here. */ + if (unlikely((body->valid & OBD_MD_MDS))) { + rc = lmv_intent_remote(exp, lmm, lmmsize, it, &op_data->op_fid1, + flags, reqp, cb_blocking, + extra_lock_flags); + if (rc != 0) + return rc; + + body = req_capsule_server_get(&(*reqp)->rq_pill, &RMF_MDT_BODY); + if (!body) + return -EPROTO; } return rc; @@ -269,8 +427,23 @@ static int lmv_intent_lookup(struct obd_export *exp, rc = md_intent_lock(tgt->ltd_exp, op_data, lmm, lmmsize, it, flags, reqp, cb_blocking, extra_lock_flags); - if (rc < 0 || !*reqp) + if (rc < 0) + return rc; + + if (!*reqp) { + /* + * If RPC happens, lsm information will be revalidated + * during update_inode process (see ll_update_lsm_md) + */ + if (op_data->op_mea2) { + rc = lmv_revalidate_slaves(exp, NULL, op_data->op_mea2, + cb_blocking, + extra_lock_flags); + if (rc != 0) + return rc; + } return rc; + } /* * MDS has returned success. Probably name has been resolved in @@ -279,12 +452,17 @@ static int lmv_intent_lookup(struct obd_export *exp, body = req_capsule_server_get(&(*reqp)->rq_pill, &RMF_MDT_BODY); if (!body) return -EPROTO; - /* Not cross-ref case, just get out of here. */ - if (likely(!(body->valid & OBD_MD_MDS))) - return 0; - rc = lmv_intent_remote(exp, lmm, lmmsize, it, NULL, flags, reqp, - cb_blocking, extra_lock_flags); + /* Not cross-ref case, just get out of here. */ + if (unlikely((body->valid & OBD_MD_MDS))) { + rc = lmv_intent_remote(exp, lmm, lmmsize, it, NULL, flags, + reqp, cb_blocking, extra_lock_flags); + if (rc != 0) + return rc; + body = req_capsule_server_get(&(*reqp)->rq_pill, &RMF_MDT_BODY); + if (!body) + return -EPROTO; + } return rc; } diff --git a/drivers/staging/lustre/lustre/lmv/lmv_internal.h b/drivers/staging/lustre/lustre/lmv/lmv_internal.h index f4c917b..ed02927 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_internal.h +++ b/drivers/staging/lustre/lustre/lmv/lmv_internal.h @@ -55,6 +55,14 @@ int __lmv_fid_alloc(struct lmv_obd *lmv, struct lu_fid *fid, u32 mds); int lmv_fid_alloc(struct obd_export *exp, struct lu_fid *fid, struct md_op_data *op_data); +int lmv_unpack_md(struct obd_export *exp, struct lmv_stripe_md **lsmp, + const union lmv_mds_md *lmm, int stripe_count); + +int lmv_revalidate_slaves(struct obd_export *exp, struct mdt_body *mbody, + struct lmv_stripe_md *lsm, + ldlm_blocking_callback cb_blocking, + int extra_lock_flags); + static inline struct lmv_tgt_desc * lmv_get_target(struct lmv_obd *lmv, u32 mds) { @@ -94,6 +102,30 @@ static inline int lmv_stripe_md_size(int stripe_count) return sizeof(*lsm) + stripe_count * sizeof(lsm->lsm_md_oinfo[0]); } +int lmv_name_to_stripe_index(enum lmv_hash_type hashtype, + unsigned int max_mdt_index, + const char *name, int namelen); + +static inline const struct lmv_oinfo * +lsm_name_to_stripe_info(const struct lmv_stripe_md *lsm, const char *name, + int namelen) +{ + int stripe_index; + + stripe_index = lmv_name_to_stripe_index(lsm->lsm_md_hash_type, + lsm->lsm_md_stripe_count, + name, namelen); + if (stripe_index < 0) + return ERR_PTR(stripe_index); + + LASSERTF(stripe_index < lsm->lsm_md_stripe_count, + "stripe_index = %d, stripe_count = %d hash_type = %x name = %.*s\n", + stripe_index, lsm->lsm_md_stripe_count, + lsm->lsm_md_hash_type, namelen, name); + + return &lsm->lsm_md_oinfo[stripe_index]; +} + struct lmv_tgt_desc *lmv_locate_mds(struct lmv_obd *lmv, struct md_op_data *op_data, struct lu_fid *fid); diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 6be2afc..da4855d 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -48,11 +48,63 @@ #include "../include/obd_class.h" #include "../include/lustre_lmv.h" #include "../include/lprocfs_status.h" +#include "../include/cl_object.h" #include "../include/lustre_lite.h" #include "../include/lustre_fid.h" #include "../include/lustre_kernelcomm.h" #include "lmv_internal.h" +/* This hash is only for testing purpose */ +static inline unsigned int +lmv_hash_all_chars(unsigned int count, const char *name, int namelen) +{ + const unsigned char *p = (const unsigned char *)name; + unsigned int c = 0; + + while (--namelen >= 0) + c += p[namelen]; + + c = c % count; + + return c; +} + +static inline unsigned int +lmv_hash_fnv1a(unsigned int count, const char *name, int namelen) +{ + __u64 hash; + + hash = lustre_hash_fnv_1a_64(name, namelen); + + return do_div(hash, count); +} + +int lmv_name_to_stripe_index(enum lmv_hash_type hashtype, + unsigned int max_mdt_index, + const char *name, int namelen) +{ + int idx; + + LASSERT(namelen > 0); + if (max_mdt_index <= 1) + return 0; + + switch (hashtype) { + case LMV_HASH_TYPE_ALL_CHARS: + idx = lmv_hash_all_chars(max_mdt_index, name, namelen); + break; + case LMV_HASH_TYPE_FNV_1A_64: + idx = lmv_hash_fnv1a(max_mdt_index, name, namelen); + break; + default: + CERROR("Unknown hash type 0x%x\n", hashtype); + return -EINVAL; + } + + LASSERT(idx < max_mdt_index); + return idx; +} + static void lmv_activate_target(struct lmv_obd *lmv, struct lmv_tgt_desc *tgt, int activate) @@ -1174,28 +1226,19 @@ static int lmv_placement_policy(struct obd_device *obd, * If stripe_offset is provided during setdirstripe * (setdirstripe -i xx), xx MDS will be chosen. */ - if (op_data->op_cli_flags & CLI_SET_MEA) { + if (op_data->op_cli_flags & CLI_SET_MEA && op_data->op_data) { struct lmv_user_md *lum; - lum = (struct lmv_user_md *)op_data->op_data; - if (lum->lum_type == LMV_STRIPE_TYPE && - lum->lum_stripe_offset != -1) { - if (lum->lum_stripe_offset >= lmv->desc.ld_tgt_count) { - CERROR("%s: Stripe_offset %d > MDT count %d: rc = %d\n", - obd->obd_name, - lum->lum_stripe_offset, - lmv->desc.ld_tgt_count, -ERANGE); - return -ERANGE; - } - *mds = lum->lum_stripe_offset; - return 0; - } + lum = op_data->op_data; + *mds = lum->lum_stripe_offset; + } else { + /* + * Allocate new fid on target according to operation type and + * parent home mds. + */ + *mds = op_data->op_mds; } - /* Allocate new fid on target according to operation type and parent - * home mds. - */ - *mds = op_data->op_mds; return 0; } @@ -1597,17 +1640,38 @@ static int lmv_close(struct obd_export *exp, struct md_op_data *op_data, return rc; } +/** + * Choosing the MDT by name or FID in @op_data. + * For non-striped directory, it will locate MDT by fid. + * For striped-directory, it will locate MDT by name. And also + * it will reset op_fid1 with the FID of the chosen stripe. + **/ struct lmv_tgt_desc *lmv_locate_mds(struct lmv_obd *lmv, struct md_op_data *op_data, struct lu_fid *fid) { + struct lmv_stripe_md *lsm = op_data->op_mea1; + const struct lmv_oinfo *oinfo; struct lmv_tgt_desc *tgt; - tgt = lmv_find_target(lmv, fid); - if (IS_ERR(tgt)) + if (!lsm || lsm->lsm_md_stripe_count <= 1 || + !op_data->op_namelen) { + tgt = lmv_find_target(lmv, fid); + if (IS_ERR(tgt)) + return tgt; + + op_data->op_mds = tgt->ltd_idx; + return tgt; + } - op_data->op_mds = tgt->ltd_idx; + oinfo = lsm_name_to_stripe_info(lsm, op_data->op_name, + op_data->op_namelen); + *fid = oinfo->lmo_fid; + op_data->op_mds = oinfo->lmo_mds; + tgt = lmv_get_target(lmv, op_data->op_mds); + + CDEBUG(D_INFO, "locate on mds %u\n", op_data->op_mds); return tgt; } @@ -1633,13 +1697,26 @@ static int lmv_create(struct obd_export *exp, struct md_op_data *op_data, if (IS_ERR(tgt)) return PTR_ERR(tgt); + CDEBUG(D_INODE, "CREATE name '%.*s' on "DFID" -> mds #%x\n", + op_data->op_namelen, op_data->op_name, PFID(&op_data->op_fid1), + op_data->op_mds); + rc = lmv_fid_alloc(exp, &op_data->op_fid2, op_data); if (rc) return rc; - CDEBUG(D_INODE, "CREATE '%*s' on "DFID" -> mds #%x\n", - op_data->op_namelen, op_data->op_name, PFID(&op_data->op_fid1), - op_data->op_mds); + /* + * Send the create request to the MDT where the object + * will be located + */ + tgt = lmv_find_target(lmv, &op_data->op_fid2); + if (IS_ERR(tgt)) + return PTR_ERR(tgt); + + op_data->op_mds = tgt->ltd_idx; + + CDEBUG(D_INODE, "CREATE obj "DFID" -> mds #%x\n", + PFID(&op_data->op_fid1), op_data->op_mds); op_data->op_flags |= MF_MDC_CANCEL_FID1; rc = md_create(tgt->ltd_exp, op_data, data, datalen, mode, uid, gid, @@ -1889,6 +1966,15 @@ static int lmv_link(struct obd_export *exp, struct md_op_data *op_data, op_data->op_fsuid = from_kuid(&init_user_ns, current_fsuid()); op_data->op_fsgid = from_kgid(&init_user_ns, current_fsgid()); op_data->op_cap = cfs_curproc_cap_pack(); + if (op_data->op_mea2) { + struct lmv_stripe_md *lsm = op_data->op_mea2; + const struct lmv_oinfo *oinfo; + + oinfo = lsm_name_to_stripe_info(lsm, op_data->op_name, + op_data->op_namelen); + op_data->op_fid2 = oinfo->lmo_fid; + } + tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid2); if (IS_ERR(tgt)) return PTR_ERR(tgt); @@ -1914,14 +2000,15 @@ static int lmv_rename(struct obd_export *exp, struct md_op_data *op_data, struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *src_tgt; - struct lmv_tgt_desc *tgt_tgt; int rc; LASSERT(oldlen != 0); - CDEBUG(D_INODE, "RENAME %*s in "DFID" to %*s in "DFID"\n", + CDEBUG(D_INODE, "RENAME %.*s in "DFID":%d to %.*s in "DFID":%d\n", oldlen, old, PFID(&op_data->op_fid1), - newlen, new, PFID(&op_data->op_fid2)); + op_data->op_mea1 ? op_data->op_mea1->lsm_md_stripe_count : 0, + newlen, new, PFID(&op_data->op_fid2), + op_data->op_mea2 ? op_data->op_mea2->lsm_md_stripe_count : 0); rc = lmv_check_connect(obd); if (rc) @@ -1930,13 +2017,33 @@ static int lmv_rename(struct obd_export *exp, struct md_op_data *op_data, op_data->op_fsuid = from_kuid(&init_user_ns, current_fsuid()); op_data->op_fsgid = from_kgid(&init_user_ns, current_fsgid()); op_data->op_cap = cfs_curproc_cap_pack(); - src_tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1); - if (IS_ERR(src_tgt)) - return PTR_ERR(src_tgt); - tgt_tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid2); - if (IS_ERR(tgt_tgt)) - return PTR_ERR(tgt_tgt); + if (op_data->op_mea1) { + struct lmv_stripe_md *lsm = op_data->op_mea1; + const struct lmv_oinfo *oinfo; + + oinfo = lsm_name_to_stripe_info(lsm, old, oldlen); + op_data->op_fid1 = oinfo->lmo_fid; + op_data->op_mds = oinfo->lmo_mds; + src_tgt = lmv_get_target(lmv, op_data->op_mds); + if (IS_ERR(src_tgt)) + return PTR_ERR(src_tgt); + } else { + src_tgt = lmv_find_target(lmv, &op_data->op_fid1); + if (IS_ERR(src_tgt)) + return PTR_ERR(src_tgt); + + op_data->op_mds = src_tgt->ltd_idx; + } + + if (op_data->op_mea2) { + struct lmv_stripe_md *lsm = op_data->op_mea2; + const struct lmv_oinfo *oinfo; + + oinfo = lsm_name_to_stripe_info(lsm, new, newlen); + op_data->op_fid2 = oinfo->lmo_fid; + } + /* * LOOKUP lock on src child (fid3) should also be cancelled for * src_tgt in mdc_rename. @@ -2568,6 +2675,7 @@ int lmv_unpack_md(struct obd_export *exp, struct lmv_stripe_md **lsmp, } return lsm_size; } +EXPORT_SYMBOL(lmv_unpack_md); int lmv_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, struct lov_mds_md *lmm, int disk_len) @@ -2741,7 +2849,7 @@ static int lmv_intent_getattr_async(struct obd_export *exp, if (rc) return rc; - tgt = lmv_find_target(lmv, &op_data->op_fid1); + tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1); if (IS_ERR(tgt)) return PTR_ERR(tgt); @@ -2843,6 +2951,49 @@ static int lmv_quotacheck(struct obd_device *unused, struct obd_export *exp, return rc; } +int lmv_update_lsm_md(struct obd_export *exp, struct lmv_stripe_md *lsm, + struct mdt_body *body, ldlm_blocking_callback cb_blocking) +{ + if (lsm->lsm_md_stripe_count <= 1) + return 0; + + return lmv_revalidate_slaves(exp, body, lsm, cb_blocking, 0); +} + +int lmv_merge_attr(struct obd_export *exp, const struct lmv_stripe_md *lsm, + struct cl_attr *attr) +{ + int i; + + for (i = 0; i < lsm->lsm_md_stripe_count; i++) { + struct inode *inode = lsm->lsm_md_oinfo[i].lmo_root; + + CDEBUG(D_INFO, ""DFID" size %llu, nlink %u, atime %lu ctime %lu, mtime %lu.\n", + PFID(&lsm->lsm_md_oinfo[i].lmo_fid), + i_size_read(inode), inode->i_nlink, + LTIME_S(inode->i_atime), LTIME_S(inode->i_ctime), + LTIME_S(inode->i_mtime)); + + /* for slave stripe, it needs to subtract nlink for . and .. */ + if (i) + attr->cat_nlink += inode->i_nlink - 2; + else + attr->cat_nlink = inode->i_nlink; + + attr->cat_size += i_size_read(inode); + + if (attr->cat_atime < LTIME_S(inode->i_atime)) + attr->cat_atime = LTIME_S(inode->i_atime); + + if (attr->cat_ctime < LTIME_S(inode->i_ctime)) + attr->cat_ctime = LTIME_S(inode->i_ctime); + + if (attr->cat_mtime < LTIME_S(inode->i_mtime)) + attr->cat_mtime = LTIME_S(inode->i_mtime); + } + return 0; +} + static struct obd_ops lmv_obd_ops = { .owner = THIS_MODULE, .setup = lmv_setup, @@ -2888,6 +3039,8 @@ static struct md_ops lmv_md_ops = { .lock_match = lmv_lock_match, .get_lustre_md = lmv_get_lustre_md, .free_lustre_md = lmv_free_lustre_md, + .update_lsm_md = lmv_update_lsm_md, + .merge_attr = lmv_merge_attr, .set_open_replay_data = lmv_set_open_replay_data, .clear_open_replay_data = lmv_clear_open_replay_data, .intent_getattr_async = lmv_intent_getattr_async, diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index 06a1274..626fce5 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -325,6 +325,9 @@ static struct ptlrpc_request *mdc_intent_open_pack(struct obd_export *exp, mdc_open_pack(req, op_data, it->it_create_mode, 0, it->it_flags, lmm, lmmsize); + req_capsule_set_size(&req->rq_pill, &RMF_MDT_MD, RCL_SERVER, + obddev->u.cli.cl_max_mds_easize); + ptlrpc_request_set_replen(req); return req; } diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index b514f18..07e23d1 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -1878,6 +1878,17 @@ void lustre_swab_lov_desc(struct lov_desc *ld) } EXPORT_SYMBOL(lustre_swab_lov_desc); +void lustre_swab_lmv_user_md(struct lmv_user_md *lum) +{ + __swab32s(&lum->lum_magic); + __swab32s(&lum->lum_stripe_count); + __swab32s(&lum->lum_stripe_offset); + __swab32s(&lum->lum_hash_type); + __swab32s(&lum->lum_type); + CLASSERT(offsetof(typeof(*lum), lum_padding1)); +} +EXPORT_SYMBOL(lustre_swab_lmv_user_md); + static void print_lum(struct lov_user_md *lum) { CDEBUG(D_OTHER, "lov_user_md %p:\n", lum); -- cgit v0.10.2 From 6e23ea986bf550a8ba9f5fb797fead3c333665f9 Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Tue, 16 Aug 2016 16:18:26 -0400 Subject: staging: lustre: llite: fix "getdirstripe" to show stripe info Fix "lfs getdirstripe", so it can show layout information of striped directory [root@testnode tests]# ../utils/lfs getdirstripe /mnt/lustre/test1 /mnt/lustre/test1 lmv_stripe_count: 2 lmv_stripe_offset: 0 mdtidx FID[seq:oid:ver] 0 [0x280000400:0x1:0x0] 1 [0x2c0000400:0x1:0x0] Signed-off-by: wang di <di.wang@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3531 Reviewed-on: http://review.whamcloud.com/7228 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Alex Zhuravlev <alexey.zhuravlev@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index a612080..0ff30c6 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -1728,6 +1728,8 @@ lov_mds_md_max_stripe_count(size_t buf_size, __u32 lmm_magic) #define OBD_MD_FLDATAVERSION (0x0010000000000000ULL) /* iversion sum */ #define OBD_MD_FLRELEASED (0x0020000000000000ULL) /* file released */ +#define OBD_MD_DEFAULT_MEA (0x0040000000000000ULL) /* default MEA */ + #define OBD_MD_FLGETATTR (OBD_MD_FLID | OBD_MD_FLATIME | OBD_MD_FLMTIME | \ OBD_MD_FLCTIME | OBD_MD_FLSIZE | OBD_MD_FLBLKSZ | \ OBD_MD_FLMODE | OBD_MD_FLTYPE | OBD_MD_FLUID | \ @@ -2543,6 +2545,8 @@ union lmv_mds_md { struct lmv_user_md lmv_user_md; }; +void lustre_swab_lmv_mds_md(union lmv_mds_md *lmm); + static inline ssize_t lmv_mds_md_size(int stripe_count, unsigned int lmm_magic) { ssize_t len = -EINVAL; diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index d496d0e..26dbda0 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -242,6 +242,7 @@ struct ost_id { #define LL_IOC_SET_LEASE _IOWR('f', 243, long) #define LL_IOC_GET_LEASE _IO('f', 244) #define LL_IOC_HSM_IMPORT _IOWR('f', 245, struct hsm_user_import) +#define LL_IOC_LMV_SET_DEFAULT_STRIPE _IOWR('f', 246, struct lmv_user_md) #define LL_STATFS_LMV 1 #define LL_STATFS_LOV 2 diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index a0560b6..5288750 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -749,6 +749,13 @@ int ll_dir_setstripe(struct inode *inode, struct lov_user_md *lump, lum_size = sizeof(struct lov_user_md_v3); break; } + case LMV_USER_MAGIC: { + if (lump->lmm_magic != cpu_to_le32(LMV_USER_MAGIC)) + lustre_swab_lmv_user_md( + (struct lmv_user_md *)lump); + lum_size = sizeof(struct lmv_user_md); + break; + } default: { CDEBUG(D_IOCTL, "bad userland LOV MAGIC: %#08x != %#08x nor %#08x\n", lump->lmm_magic, LOV_USER_MAGIC_V1, @@ -819,8 +826,16 @@ end: return rc; } -int ll_dir_getstripe(struct inode *inode, struct lov_mds_md **lmmp, - int *lmm_size, struct ptlrpc_request **request) +/** + * This function will be used to get default LOV/LMV/Default LMV + * @valid will be used to indicate which stripe it will retrieve + * OBD_MD_MEA LMV stripe EA + * OBD_MD_DEFAULT_MEA Default LMV stripe EA + * otherwise Default LOV EA. + * Each time, it can only retrieve 1 stripe EA + **/ +int ll_dir_getstripe(struct inode *inode, void **plmm, int *plmm_size, + struct ptlrpc_request **request, u64 valid) { struct ll_sb_info *sbi = ll_i2sbi(inode); struct mdt_body *body; @@ -829,7 +844,7 @@ int ll_dir_getstripe(struct inode *inode, struct lov_mds_md **lmmp, int rc, lmmsize; struct md_op_data *op_data; - rc = ll_get_default_mdsize(sbi, &lmmsize); + rc = ll_get_max_mdsize(sbi, &lmmsize); if (rc) return rc; @@ -860,6 +875,7 @@ int ll_dir_getstripe(struct inode *inode, struct lov_mds_md **lmmp, lmm = req_capsule_server_sized_get(&req->rq_pill, &RMF_MDT_MD, lmmsize); + LASSERT(lmm); /* * This is coming from the MDS, so is probably in @@ -876,40 +892,48 @@ int ll_dir_getstripe(struct inode *inode, struct lov_mds_md **lmmp, if (cpu_to_le32(LOV_MAGIC) != LOV_MAGIC) lustre_swab_lov_user_md_v3((struct lov_user_md_v3 *)lmm); break; + case LMV_USER_MAGIC: + if (cpu_to_le32(LMV_USER_MAGIC) != LMV_USER_MAGIC) + lustre_swab_lmv_user_md((struct lmv_user_md *)lmm); + break; default: CERROR("unknown magic: %lX\n", (unsigned long)lmm->lmm_magic); rc = -EPROTO; } out: - *lmmp = lmm; - *lmm_size = lmmsize; + *plmm = lmm; + *plmm_size = lmmsize; *request = req; return rc; } -/* - * Get MDT index for the inode. - */ -int ll_get_mdt_idx(struct inode *inode) +static int ll_get_mdt_idx_by_fid(struct ll_sb_info *sbi, + const struct lu_fid *fid) { - struct ll_sb_info *sbi = ll_i2sbi(inode); struct md_op_data *op_data; - int rc, mdtidx; + int mdt_index, rc; - op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, - 0, LUSTRE_OPC_ANY, NULL); - if (IS_ERR(op_data)) - return PTR_ERR(op_data); + op_data = kzalloc(sizeof(*op_data), GFP_NOFS); + if (!op_data) + return -ENOMEM; op_data->op_flags |= MF_GET_MDT_IDX; + op_data->op_fid1 = *fid; rc = md_getattr(sbi->ll_md_exp, op_data, NULL); - mdtidx = op_data->op_mds; - ll_finish_md_op_data(op_data); - if (rc < 0) { - CDEBUG(D_INFO, "md_getattr_name: %d\n", rc); + mdt_index = op_data->op_mds; + kvfree(op_data); + if (rc < 0) return rc; - } - return mdtidx; + + return mdt_index; +} + +/* + * Get MDT index for the inode. + */ +int ll_get_mdt_idx(struct inode *inode) +{ + return ll_get_mdt_idx_by_fid(ll_i2sbi(inode), ll_inode2fid(inode)); } /** @@ -1391,6 +1415,22 @@ lmv_out_free: obd_ioctl_freedata(buf, len); return rc; } + case LL_IOC_LMV_SET_DEFAULT_STRIPE: { + struct lmv_user_md __user *ulump; + struct lmv_user_md lum; + int rc; + + ulump = (struct lmv_user_md __user *)arg; + if (copy_from_user(&lum, ulump, sizeof(lum))) + return -EFAULT; + + if (lum.lum_magic != LMV_USER_MAGIC) + return -EINVAL; + + rc = ll_dir_setstripe(inode, (struct lov_user_md *)&lum, 0); + + return rc; + } case LL_IOC_LOV_SETSTRIPE: { struct lov_user_md_v3 lumv3; struct lov_user_md_v1 *lumv1 = (struct lov_user_md_v1 *)&lumv3; @@ -1420,46 +1460,107 @@ lmv_out_free: return rc; } case LL_IOC_LMV_GETSTRIPE: { - struct lmv_user_md __user *lump = (void __user *)arg; + struct lmv_user_md __user *ulmv; struct lmv_user_md lum; - struct lmv_user_md *tmp; + struct ptlrpc_request *request = NULL; + struct lmv_user_md *tmp = NULL; + union lmv_mds_md *lmm = NULL; + u64 valid = 0; + int stripe_count; + int mdt_index; int lum_size; - int rc = 0; - int mdtindex; + int lmmsize; + int rc; + int i; - if (copy_from_user(&lum, lump, sizeof(struct lmv_user_md))) + ulmv = (struct lmv_user_md __user *)arg; + if (copy_from_user(&lum, ulmv, sizeof(*ulmv))) return -EFAULT; - if (lum.lum_magic != LMV_MAGIC_V1) + /* + * lum_magic will indicate which stripe the ioctl will like + * to get, LMV_MAGIC_V1 is for normal LMV stripe, LMV_USER_MAGIC + * is for default LMV stripe + */ + if (lum.lum_magic == LMV_MAGIC_V1) + valid |= OBD_MD_MEA; + else if (lum.lum_magic == LMV_USER_MAGIC) + valid |= OBD_MD_DEFAULT_MEA; + else return -EINVAL; - lum_size = lmv_user_md_size(1, LMV_MAGIC_V1); + rc = ll_dir_getstripe(inode, (void **)&lmm, &lmmsize, &request, + valid); + if (rc && rc != -ENODATA) + goto finish_req; + + /* Get default LMV EA */ + if (lum.lum_magic == LMV_USER_MAGIC) { + if (rc) + goto finish_req; + + if (lmmsize > sizeof(*ulmv)) { + rc = -EINVAL; + goto finish_req; + } + + if (copy_to_user(ulmv, lmm, lmmsize)) + rc = -EFAULT; + + goto finish_req; + } + + /* Get normal LMV EA */ + if (rc == -ENODATA) { + stripe_count = 1; + } else { + LASSERT(lmm); + stripe_count = lmv_mds_md_stripe_count_get(lmm); + } + + lum_size = lmv_user_md_size(stripe_count, LMV_MAGIC_V1); tmp = kzalloc(lum_size, GFP_NOFS); if (!tmp) { rc = -ENOMEM; - goto free_lmv; + goto finish_req; } - *tmp = lum; + tmp->lum_magic = LMV_MAGIC_V1; tmp->lum_stripe_count = 1; - mdtindex = ll_get_mdt_idx(inode); - if (mdtindex < 0) { + mdt_index = ll_get_mdt_idx(inode); + if (mdt_index < 0) { rc = -ENOMEM; - goto free_lmv; + goto out_tmp; + } + tmp->lum_stripe_offset = mdt_index; + tmp->lum_objects[0].lum_mds = mdt_index; + tmp->lum_objects[0].lum_fid = *ll_inode2fid(inode); + for (i = 1; i < stripe_count; i++) { + struct lmv_mds_md_v1 *lmm1; + + lmm1 = &lmm->lmv_md_v1; + mdt_index = ll_get_mdt_idx_by_fid(sbi, + &lmm1->lmv_stripe_fids[i]); + if (mdt_index < 0) { + rc = mdt_index; + goto out_tmp; + } + tmp->lum_objects[i].lum_mds = mdt_index; + tmp->lum_objects[i].lum_fid = lmm1->lmv_stripe_fids[i]; + tmp->lum_stripe_count++; } - tmp->lum_stripe_offset = mdtindex; - tmp->lum_objects[0].lum_mds = mdtindex; - memcpy(&tmp->lum_objects[0].lum_fid, ll_inode2fid(inode), - sizeof(struct lu_fid)); - if (copy_to_user((void __user *)arg, tmp, lum_size)) { + if (copy_to_user(ulmv, tmp, lum_size)) { rc = -EFAULT; - goto free_lmv; + goto out_tmp; } -free_lmv: +out_tmp: kfree(tmp); +finish_req: + ptlrpc_req_finished(request); return rc; } + case LL_IOC_LOV_SWAP_LAYOUTS: return -EPERM; case LL_IOC_OBD_STATFS: @@ -1484,7 +1585,8 @@ free_lmv: rc = ll_lov_getstripe_ea_info(inode, filename, &lmm, &lmmsize, &request); } else { - rc = ll_dir_getstripe(inode, &lmm, &lmmsize, &request); + rc = ll_dir_getstripe(inode, (void **)&lmm, &lmmsize, + &request, 0); } if (request) { diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index f3b8504..82c3a88 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -728,8 +728,8 @@ int ll_lov_getstripe_ea_info(struct inode *inode, const char *filename, struct ptlrpc_request **request); int ll_dir_setstripe(struct inode *inode, struct lov_user_md *lump, int set_default); -int ll_dir_getstripe(struct inode *inode, struct lov_mds_md **lmmp, - int *lmm_size, struct ptlrpc_request **request); +int ll_dir_getstripe(struct inode *inode, void **lmmp, int *lmm_size, + struct ptlrpc_request **request, u64 valid); int ll_fsync(struct file *file, loff_t start, loff_t end, int data); int ll_merge_attr(const struct lu_env *env, struct inode *inode); int ll_fid2path(struct inode *inode, void __user *arg); diff --git a/drivers/staging/lustre/lustre/llite/xattr.c b/drivers/staging/lustre/lustre/llite/xattr.c index a02b802..aa0738b 100644 --- a/drivers/staging/lustre/lustre/llite/xattr.c +++ b/drivers/staging/lustre/lustre/llite/xattr.c @@ -390,8 +390,8 @@ static int ll_xattr_get(const struct xattr_handler *handler, lsm = ccc_inode_lsm_get(inode); if (!lsm) { if (S_ISDIR(inode->i_mode)) { - rc = ll_dir_getstripe(inode, &lmm, - &lmmsize, &request); + rc = ll_dir_getstripe(inode, (void **)&lmm, + &lmmsize, &request, 0); } else { rc = -ENODATA; } @@ -491,7 +491,8 @@ ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size) if (!ll_i2info(inode)->lli_has_smd) rc2 = -1; } else if (S_ISDIR(inode->i_mode)) { - rc2 = ll_dir_getstripe(inode, &lmm, &lmmsize, &request); + rc2 = ll_dir_getstripe(inode, (void **)&lmm, &lmmsize, + &request, 0); } if (rc2 < 0) { diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index 07e23d1..6ddc9c7 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -1878,6 +1878,32 @@ void lustre_swab_lov_desc(struct lov_desc *ld) } EXPORT_SYMBOL(lustre_swab_lov_desc); +/* This structure is always in little-endian */ +static void lustre_swab_lmv_mds_md_v1(struct lmv_mds_md_v1 *lmm1) +{ + int i; + + __swab32s(&lmm1->lmv_magic); + __swab32s(&lmm1->lmv_stripe_count); + __swab32s(&lmm1->lmv_master_mdt_index); + __swab32s(&lmm1->lmv_hash_type); + __swab32s(&lmm1->lmv_layout_version); + for (i = 0; i < lmm1->lmv_stripe_count; i++) + lustre_swab_lu_fid(&lmm1->lmv_stripe_fids[i]); +} + +void lustre_swab_lmv_mds_md(union lmv_mds_md *lmm) +{ + switch (lmm->lmv_magic) { + case LMV_MAGIC_V1: + lustre_swab_lmv_mds_md_v1(&lmm->lmv_md_v1); + break; + default: + break; + } +} +EXPORT_SYMBOL(lustre_swab_lmv_mds_md); + void lustre_swab_lmv_user_md(struct lmv_user_md *lum) { __swab32s(&lum->lum_magic); -- cgit v0.10.2 From 75ac62fc3935d79f5051fa1c4d2b1051bf7d1a0e Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Tue, 16 Aug 2016 16:18:27 -0400 Subject: staging: lustre: delete striped directory Add delete striped directory, it includes 1. enable sync log between MDTs, so slave objects will be delete by unlink log, which is similar as deleting ost object. 2. retrieve layout information of striped directory on MDT, then lock all of the slave objects before unlink. Signed-off-by: wang di <di.wang@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3531 Reviewed-on: http://review.whamcloud.com/7445 Reviewed-by: Alex Zhuravlev <alexey.zhuravlev@intel.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre_dlm.h b/drivers/staging/lustre/lustre/include/lustre_dlm.h index 60051a5..f7805cc 100644 --- a/drivers/staging/lustre/lustre/include/lustre_dlm.h +++ b/drivers/staging/lustre/lustre/include/lustre_dlm.h @@ -968,6 +968,7 @@ struct ldlm_enqueue_info { void *ei_cb_cp; /** lock completion callback */ void *ei_cb_gl; /** lock glimpse callback */ void *ei_cbdata; /** Data to be passed into callbacks. */ + unsigned int ei_enq_slave:1; /* whether enqueue slave stripes */ }; extern struct obd_ops ldlm_obd_ops; diff --git a/drivers/staging/lustre/lustre/include/lustre_fid.h b/drivers/staging/lustre/lustre/include/lustre_fid.h index 743671a..61f3930 100644 --- a/drivers/staging/lustre/lustre/include/lustre_fid.h +++ b/drivers/staging/lustre/lustre/include/lustre_fid.h @@ -229,6 +229,7 @@ enum local_oid { MDD_LOV_OBJ_OSEQ = 4121UL, LFSCK_NAMESPACE_OID = 4122UL, REMOTE_PARENT_DIR_OID = 4123UL, + SLAVE_LLOG_CATALOGS_OID = 4124UL, }; static inline void lu_local_obj_fid(struct lu_fid *fid, __u32 oid) diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 5288750..96ae7d5 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -679,16 +679,6 @@ static int ll_dir_setdirstripe(struct inode *dir, struct lmv_user_md *lump, if (unlikely(lump->lum_magic != LMV_USER_MAGIC)) return -EINVAL; - if (lump->lum_stripe_offset == (__u32)-1) { - int mdtidx; - - mdtidx = ll_get_mdt_idx(dir); - if (mdtidx < 0) - return mdtidx; - - lump->lum_stripe_offset = mdtidx; - } - CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p) name %s stripe_offset %d, stripe_count: %u\n", PFID(ll_inode2fid(dir)), dir, filename, (int)lump->lum_stripe_offset, lump->lum_stripe_count); diff --git a/drivers/staging/lustre/lustre/lmv/lmv_intent.c b/drivers/staging/lustre/lustre/lmv/lmv_intent.c index 1b9bbb2..5313dfc 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_intent.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_intent.c @@ -244,6 +244,11 @@ update: if (req) ptlrpc_req_finished(req); + if (it.it_lock_mode && lockh) { + ldlm_lock_decref(lockh, it.it_lock_mode); + it.it_lock_mode = 0; + } + rc = -EIO; goto cleanup; } diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index da4855d..81dcc0a 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -101,6 +101,9 @@ int lmv_name_to_stripe_index(enum lmv_hash_type hashtype, return -EINVAL; } + CDEBUG(D_INFO, "name %.*s hash_type %d idx %d\n", namelen, name, + hashtype, idx); + LASSERT(idx < max_mdt_index); return idx; } @@ -1230,7 +1233,16 @@ static int lmv_placement_policy(struct obd_device *obd, struct lmv_user_md *lum; lum = op_data->op_data; - *mds = lum->lum_stripe_offset; + if (lum->lum_stripe_offset != (__u32)-1) { + *mds = lum->lum_stripe_offset; + } else { + /* + * -1 means default, which will be in the same MDT with + * the stripe + */ + *mds = op_data->op_mds; + lum->lum_stripe_offset = op_data->op_mds; + } } else { /* * Allocate new fid on target according to operation type and @@ -1646,12 +1658,28 @@ static int lmv_close(struct obd_export *exp, struct md_op_data *op_data, * For striped-directory, it will locate MDT by name. And also * it will reset op_fid1 with the FID of the chosen stripe. **/ +struct lmv_tgt_desc * +lmv_locate_target_for_name(struct lmv_obd *lmv, struct lmv_stripe_md *lsm, + const char *name, int namelen, struct lu_fid *fid, + u32 *mds) +{ + const struct lmv_oinfo *oinfo; + struct lmv_tgt_desc *tgt; + + oinfo = lsm_name_to_stripe_info(lsm, name, namelen); + *fid = oinfo->lmo_fid; + *mds = oinfo->lmo_mds; + tgt = lmv_get_target(lmv, *mds); + + CDEBUG(D_INFO, "locate on mds %u "DFID"\n", *mds, PFID(fid)); + return tgt; +} + struct lmv_tgt_desc *lmv_locate_mds(struct lmv_obd *lmv, struct md_op_data *op_data, struct lu_fid *fid) { struct lmv_stripe_md *lsm = op_data->op_mea1; - const struct lmv_oinfo *oinfo; struct lmv_tgt_desc *tgt; if (!lsm || lsm->lsm_md_stripe_count <= 1 || @@ -1665,15 +1693,9 @@ struct lmv_tgt_desc return tgt; } - oinfo = lsm_name_to_stripe_info(lsm, op_data->op_name, - op_data->op_namelen); - *fid = oinfo->lmo_fid; - op_data->op_mds = oinfo->lmo_mds; - tgt = lmv_get_target(lmv, op_data->op_mds); - - CDEBUG(D_INFO, "locate on mds %u\n", op_data->op_mds); - - return tgt; + return lmv_locate_target_for_name(lmv, lsm, op_data->op_name, + op_data->op_namelen, fid, + &op_data->op_mds); } static int lmv_create(struct obd_export *exp, struct md_op_data *op_data, @@ -2075,6 +2097,9 @@ static int lmv_rename(struct obd_export *exp, struct md_op_data *op_data, LCK_EX, MDS_INODELOCK_FULL, MF_MDC_CANCEL_FID4); + CDEBUG(D_INODE, DFID":m%d to "DFID"\n", PFID(&op_data->op_fid1), + op_data->op_mds, PFID(&op_data->op_fid2)); + if (rc == 0) rc = md_rename(src_tgt->ltd_exp, op_data, old, oldlen, new, newlen, request); @@ -2288,12 +2313,26 @@ static int lmv_unlink(struct obd_export *exp, struct md_op_data *op_data, return rc; retry: /* Send unlink requests to the MDT where the child is located */ - if (likely(!fid_is_zero(&op_data->op_fid2))) - tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid2); - else + if (likely(!fid_is_zero(&op_data->op_fid2))) { + tgt = lmv_find_target(lmv, &op_data->op_fid2); + if (IS_ERR(tgt)) + return PTR_ERR(tgt); + + /* For striped dir, we need to locate the parent as well */ + if (op_data->op_mea1 && + op_data->op_mea1->lsm_md_stripe_count > 1) { + LASSERT(op_data->op_name && op_data->op_namelen); + lmv_locate_target_for_name(lmv, op_data->op_mea1, + op_data->op_name, + op_data->op_namelen, + &op_data->op_fid1, + &op_data->op_mds); + } + } else { tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1); - if (IS_ERR(tgt)) - return PTR_ERR(tgt); + if (IS_ERR(tgt)) + return PTR_ERR(tgt); + } op_data->op_fsuid = from_kuid(&init_user_ns, current_fsuid()); op_data->op_fsgid = from_kgid(&init_user_ns, current_fsgid()); @@ -2799,8 +2838,10 @@ static int lmv_free_lustre_md(struct obd_export *exp, struct lustre_md *md) struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt = lmv->tgts[0]; - if (md->lmv) + if (md->lmv) { lmv_free_memmd(md->lmv); + md->lmv = NULL; + } if (!tgt || !tgt->ltd_exp) return -EINVAL; return md_free_lustre_md(tgt->ltd_exp, md); -- cgit v0.10.2 From f4ba0420278486a3fdddae1421ef48fdb5be9754 Mon Sep 17 00:00:00 2001 From: Jian Yu <jian.yu@intel.com> Date: Tue, 16 Aug 2016 16:18:28 -0400 Subject: staging: lustre: obdclass: fix lmd_parse() to handle comma-separated NIDs This patch handles the upgrade situation that old mountdata already contains comma-separated NIDs. The correct way to fix the original issue is to parse comma-separated NIDs in lmd_parse(). Signed-off-by: Jian Yu <jian.yu@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4460 Reviewed-on: http://review.whamcloud.com/8918 Reviewed-by: Niu Yawei <yawei.niu@intel.com> Reviewed-by: Bobi Jam <bobijam@gmail.com> Reviewed-by: Sebastien Buisson <sebastien.buisson@bull.net> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/obdclass/obd_mount.c b/drivers/staging/lustre/lustre/obdclass/obd_mount.c index aa84a50e..4931e37 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_mount.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_mount.c @@ -880,7 +880,7 @@ static int lmd_parse_mgs(struct lustre_mount_data *lmd, char **ptr) */ static int lmd_parse(char *options, struct lustre_mount_data *lmd) { - char *s1, *s2, *devname = NULL; + char *s1, *s2, *s3, *devname = NULL; struct lustre_mount_data *raw = (struct lustre_mount_data *)options; int rc = 0; @@ -913,6 +913,7 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd) /* Skip whitespace and extra commas */ while (*s1 == ' ' || *s1 == ',') s1++; + s3 = s1; /* Client options are parsed in ll_options: eg. flock, * user_xattr, acl @@ -970,6 +971,7 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd) rc = lmd_parse_mgssec(lmd, s1 + 7); if (rc) goto invalid; + s3 = s2; clear++; /* ost exclusion list */ } else if (strncmp(s1, "exclude=", 8) == 0) { @@ -990,10 +992,19 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd) size_t length, params_length; char *tail = strchr(s1 + 6, ','); - if (!tail) + if (!tail) { length = strlen(s1); - else - length = tail - s1; + } else { + lnet_nid_t nid; + char *param_str = tail + 1; + int supplementary = 1; + + while (!class_parse_nid_quiet(param_str, &nid, + ¶m_str)) { + supplementary = 0; + } + length = param_str - s1 - supplementary; + } length -= 6; params_length = strlen(lmd->lmd_params); if (params_length + length + 1 >= LMD_PARAMS_MAXLEN) @@ -1001,6 +1012,7 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd) strncat(lmd->lmd_params, s1 + 6, length); lmd->lmd_params[params_length + length] = '\0'; strlcat(lmd->lmd_params, " ", LMD_PARAMS_MAXLEN); + s3 = s1 + 6 + length; clear++; } else if (strncmp(s1, "osd=", 4) == 0) { rc = lmd_parse_string(&lmd->lmd_osd_type, s1 + 4); -- cgit v0.10.2 From a8610297ea8849fe47a9442291b38936e3d403cc Mon Sep 17 00:00:00 2001 From: Fan Yong <fan.yong@intel.com> Date: Tue, 16 Aug 2016 16:18:29 -0400 Subject: staging: lustre: obdclass: bug fixes for lu_device_type handling There was no protection when inc/dec lu_device_type::ldt_device_nr, which may caused the ldt_device_nr to be wrong and trigger assert. This patch redefine lu_device_type::ldt_device_nr as atomic type. There was no protection when add/del lu_device_type::ldt_linkage into/from the global lu_device_types list, which may caused bad address accessing. This patch uses the existing obd_types_lock to protect related operations. We do NOT need lu_types_stop() any longer. Such function scans the global lu_device_types list, and for each type item on it which has zerod lu_device_type::ldt_device_nr, call its stop() method. In fact, the lu_device_type::ldt_device_nr only will be zero when the last lu_device_fini() is called, and at that time, inside the lu_device_fini(), its stop() method will be called. So it is unnecessary to call the stop() again via lu_types_stop(). Signed-off-by: Fan Yong <fan.yong@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4604 Reviewed-on: http://review.whamcloud.com/8694 Reviewed-by: Jian Yu <jian.yu@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lu_object.h b/drivers/staging/lustre/lustre/include/lu_object.h index 6e25c1b..25c12d8 100644 --- a/drivers/staging/lustre/lustre/include/lu_object.h +++ b/drivers/staging/lustre/lustre/include/lu_object.h @@ -327,7 +327,7 @@ struct lu_device_type { /** * Number of existing device type instances. */ - unsigned ldt_device_nr; + atomic_t ldt_device_nr; /** * Linkage into a global list of all device types. * @@ -673,7 +673,6 @@ void lu_object_add(struct lu_object *before, struct lu_object *o); int lu_device_type_init(struct lu_device_type *ldt); void lu_device_type_fini(struct lu_device_type *ldt); -void lu_types_stop(void); /** @} ctors */ diff --git a/drivers/staging/lustre/lustre/llite/vvp_dev.c b/drivers/staging/lustre/lustre/llite/vvp_dev.c index e623216..771c0bd 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_dev.c +++ b/drivers/staging/lustre/lustre/llite/vvp_dev.c @@ -368,12 +368,6 @@ int cl_sb_fini(struct super_block *sb) CERROR("Cannot cleanup cl-stack due to memory shortage.\n"); result = PTR_ERR(env); } - /* - * If mount failed (sbi->ll_cl == NULL), and this there are no other - * mounts, stop device types manually (this usually happens - * automatically when last device is destroyed). - */ - lu_types_stop(); return result; } diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c index 9b03059..0c00bf8 100644 --- a/drivers/staging/lustre/lustre/obdclass/lu_object.c +++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c @@ -726,34 +726,31 @@ int lu_device_type_init(struct lu_device_type *ldt) { int result = 0; + atomic_set(&ldt->ldt_device_nr, 0); INIT_LIST_HEAD(&ldt->ldt_linkage); if (ldt->ldt_ops->ldto_init) result = ldt->ldt_ops->ldto_init(ldt); - if (result == 0) + + if (!result) { + spin_lock(&obd_types_lock); list_add(&ldt->ldt_linkage, &lu_device_types); + spin_unlock(&obd_types_lock); + } + return result; } EXPORT_SYMBOL(lu_device_type_init); void lu_device_type_fini(struct lu_device_type *ldt) { + spin_lock(&obd_types_lock); list_del_init(&ldt->ldt_linkage); + spin_unlock(&obd_types_lock); if (ldt->ldt_ops->ldto_fini) ldt->ldt_ops->ldto_fini(ldt); } EXPORT_SYMBOL(lu_device_type_fini); -void lu_types_stop(void) -{ - struct lu_device_type *ldt; - - list_for_each_entry(ldt, &lu_device_types, ldt_linkage) { - if (ldt->ldt_device_nr == 0 && ldt->ldt_ops->ldto_stop) - ldt->ldt_ops->ldto_stop(ldt); - } -} -EXPORT_SYMBOL(lu_types_stop); - /** * Global list of all sites on this node */ @@ -1082,8 +1079,10 @@ EXPORT_SYMBOL(lu_device_put); */ int lu_device_init(struct lu_device *d, struct lu_device_type *t) { - if (t->ldt_device_nr++ == 0 && t->ldt_ops->ldto_start) + if (atomic_inc_return(&t->ldt_device_nr) == 1 && + t->ldt_ops->ldto_start) t->ldt_ops->ldto_start(t); + memset(d, 0, sizeof(*d)); atomic_set(&d->ld_ref, 0); d->ld_type = t; @@ -1098,9 +1097,8 @@ EXPORT_SYMBOL(lu_device_init); */ void lu_device_fini(struct lu_device *d) { - struct lu_device_type *t; + struct lu_device_type *t = d->ld_type; - t = d->ld_type; if (d->ld_obd) { d->ld_obd->obd_lu_dev = NULL; d->ld_obd = NULL; @@ -1109,8 +1107,10 @@ void lu_device_fini(struct lu_device *d) lu_ref_fini(&d->ld_reference); LASSERTF(atomic_read(&d->ld_ref) == 0, "Refcount is %u\n", atomic_read(&d->ld_ref)); - LASSERT(t->ldt_device_nr > 0); - if (--t->ldt_device_nr == 0 && t->ldt_ops->ldto_stop) + LASSERT(atomic_read(&t->ldt_device_nr) > 0); + + if (atomic_dec_and_test(&t->ldt_device_nr) && + t->ldt_ops->ldto_stop) t->ldt_ops->ldto_stop(t); } EXPORT_SYMBOL(lu_device_fini); diff --git a/drivers/staging/lustre/lustre/obdclass/obd_mount.c b/drivers/staging/lustre/lustre/obdclass/obd_mount.c index 4931e37..33d6c42 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_mount.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_mount.c @@ -670,7 +670,6 @@ int lustre_common_put_super(struct super_block *sb) } /* Drop a ref to the mounted disk */ lustre_put_lsi(sb); - lu_types_stop(); return rc; } EXPORT_SYMBOL(lustre_common_put_super); -- cgit v0.10.2 From 7949684591cb51e5bc241fd491b59e829d910036 Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Tue, 16 Aug 2016 16:18:30 -0400 Subject: staging: lustre: add ability to migrate inodes. Add client support to migrate the individual inodes from one MDT to another MDT, and this functionality will only migrate inode layout on MDT but not touch data object on OST. The directory will be migrated from top to the bottom, i.e. migrating parent first, then migrating the child. Signed-off-by: wang di <di.wang@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2430 Reviewed-on: http://review.whamcloud.com/6662 Reviewed-by: Alex Zhuravlev <alexey.zhuravlev@intel.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 0ff30c6..6853f62 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -1482,6 +1482,7 @@ enum obdo_flags { #define LOV_MAGIC LOV_MAGIC_V1 #define LOV_MAGIC_JOIN_V1 0x0BD20BD0 #define LOV_MAGIC_V3 0x0BD30BD0 +#define LOV_MAGIC_MIGRATE 0x0BD40BD0 /* * magic for fully defined striping @@ -1987,7 +1988,7 @@ enum mdt_reint_cmd { REINT_OPEN = 6, REINT_SETXATTR = 7, REINT_RMENTRY = 8, -/* REINT_WRITE = 9, */ + REINT_MIGRATE = 9, REINT_MAX }; @@ -2280,6 +2281,7 @@ enum mds_op_bias { MDS_CREATE_VOLATILE = 1 << 10, MDS_OWNEROVERRIDE = 1 << 11, MDS_HSM_RELEASE = 1 << 12, + MDS_RENAME_MIGRATE = BIT(13), }; /* instance of mdt_reint_rec */ @@ -2488,11 +2490,13 @@ struct lmv_desc { /* lmv structures */ #define LMV_MAGIC_V1 0x0CD10CD0 /* normal stripe lmv magic */ #define LMV_USER_MAGIC 0x0CD20CD0 /* default lmv magic*/ +#define LMV_MAGIC_MIGRATE 0x0CD30CD0 /* migrate stripe lmv magic */ #define LMV_MAGIC LMV_MAGIC_V1 enum lmv_hash_type { LMV_HASH_TYPE_ALL_CHARS = 1, LMV_HASH_TYPE_FNV_1A_64 = 2, + LMV_HASH_TYPE_MIGRATION = 3, }; #define LMV_HASH_NAME_ALL_CHARS "all_char" @@ -2552,7 +2556,8 @@ static inline ssize_t lmv_mds_md_size(int stripe_count, unsigned int lmm_magic) ssize_t len = -EINVAL; switch (lmm_magic) { - case LMV_MAGIC_V1: { + case LMV_MAGIC_V1: + case LMV_MAGIC_MIGRATE: { struct lmv_mds_md_v1 *lmm1; len = sizeof(*lmm1); @@ -2568,6 +2573,7 @@ static inline int lmv_mds_md_stripe_count_get(const union lmv_mds_md *lmm) { switch (le32_to_cpu(lmm->lmv_magic)) { case LMV_MAGIC_V1: + case LMV_MAGIC_MIGRATE: return le32_to_cpu(lmm->lmv_md_v1.lmv_stripe_count); case LMV_USER_MAGIC: return le32_to_cpu(lmm->lmv_user_md.lum_stripe_count); @@ -2583,6 +2589,7 @@ static inline int lmv_mds_md_stripe_count_set(union lmv_mds_md *lmm, switch (le32_to_cpu(lmm->lmv_magic)) { case LMV_MAGIC_V1: + case LMV_MAGIC_MIGRATE: lmm->lmv_md_v1.lmv_stripe_count = cpu_to_le32(stripe_count); break; case LMV_USER_MAGIC: diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index 26dbda0..4746320 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -243,6 +243,7 @@ struct ost_id { #define LL_IOC_GET_LEASE _IO('f', 244) #define LL_IOC_HSM_IMPORT _IOWR('f', 245, struct hsm_user_import) #define LL_IOC_LMV_SET_DEFAULT_STRIPE _IOWR('f', 246, struct lmv_user_md) +#define LL_IOC_MIGRATE _IOR('f', 247, int) #define LL_STATFS_LMV 1 #define LL_STATFS_LOV 2 diff --git a/drivers/staging/lustre/lustre/include/lustre_lmv.h b/drivers/staging/lustre/lustre/include/lustre_lmv.h index 4036fce..feee981 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lmv.h +++ b/drivers/staging/lustre/lustre/include/lustre_lmv.h @@ -106,6 +106,7 @@ static inline void lmv_cpu_to_le(union lmv_mds_md *lmv_dst, { switch (lmv_src->lmv_magic) { case LMV_MAGIC_V1: + case LMV_MAGIC_MIGRATE: lmv1_cpu_to_le(&lmv_dst->lmv_md_v1, &lmv_src->lmv_md_v1); break; default: @@ -118,6 +119,7 @@ static inline void lmv_le_to_cpu(union lmv_mds_md *lmv_dst, { switch (le32_to_cpu(lmv_src->lmv_magic)) { case LMV_MAGIC_V1: + case LMV_MAGIC_MIGRATE: lmv1_le_to_cpu(&lmv_dst->lmv_md_v1, &lmv_src->lmv_md_v1); break; default: diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index a9f4e13..f5eeb05 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -847,9 +847,6 @@ struct md_op_data { /* Various operation flags. */ enum mds_op_bias op_bias; - /* Operation type */ - __u32 op_opc; - /* Used by readdir */ __u64 op_offset; @@ -871,6 +868,7 @@ enum op_cli_flags { CLI_RM_ENTRY = 1 << 1, CLI_HASH64 = BIT(2), CLI_API32 = BIT(3), + CLI_MIGRATE = BIT(4), }; struct md_enqueue_info; @@ -1013,14 +1011,6 @@ struct obd_ops { */ }; -enum { - LUSTRE_OPC_MKDIR = (1 << 0), - LUSTRE_OPC_SYMLINK = (1 << 1), - LUSTRE_OPC_MKNOD = (1 << 2), - LUSTRE_OPC_CREATE = (1 << 3), - LUSTRE_OPC_ANY = (1 << 4) -}; - /* lmv structures */ struct lustre_md { struct mdt_body *body; diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 96ae7d5..ef7322e 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -883,6 +883,7 @@ int ll_dir_getstripe(struct inode *inode, void **plmm, int *plmm_size, lustre_swab_lov_user_md_v3((struct lov_user_md_v3 *)lmm); break; case LMV_USER_MAGIC: + case LMV_MAGIC_MIGRATE: if (cpu_to_le32(LMV_USER_MAGIC) != LMV_USER_MAGIC) lustre_swab_lmv_user_md((struct lmv_user_md *)lmm); break; @@ -897,8 +898,7 @@ out: return rc; } -static int ll_get_mdt_idx_by_fid(struct ll_sb_info *sbi, - const struct lu_fid *fid) +int ll_get_mdt_idx_by_fid(struct ll_sb_info *sbi, const struct lu_fid *fid) { struct md_op_data *op_data; int mdt_index, rc; @@ -1960,6 +1960,45 @@ out_quotactl: kfree(copy); return rc; } + case LL_IOC_MIGRATE: { + char *buf = NULL; + const char *filename; + int namelen = 0; + int len; + int rc; + int mdtidx; + + rc = obd_ioctl_getdata(&buf, &len, (void __user *)arg); + if (rc < 0) + return rc; + + data = (struct obd_ioctl_data *)buf; + if (!data->ioc_inlbuf1 || !data->ioc_inlbuf2 || + !data->ioc_inllen1 || !data->ioc_inllen2) { + rc = -EINVAL; + goto migrate_free; + } + + filename = data->ioc_inlbuf1; + namelen = data->ioc_inllen1; + if (namelen < 1) { + rc = -EINVAL; + goto migrate_free; + } + + if (data->ioc_inllen2 != sizeof(mdtidx)) { + rc = -EINVAL; + goto migrate_free; + } + mdtidx = *(int *)data->ioc_inlbuf2; + + rc = ll_migrate(inode, file, mdtidx, filename, namelen); +migrate_free: + obd_ioctl_freedata(buf, len); + + return rc; + } + default: return obd_iocontrol(cmd, sbi->ll_dt_exp, 0, NULL, (void __user *)arg); diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 18fb713..8d98db6 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -364,7 +364,8 @@ int ll_file_release(struct inode *inode, struct file *file) } if (!S_ISDIR(inode->i_mode)) { - lov_read_and_clear_async_rc(lli->lli_clob); + if (lli->lli_clob) + lov_read_and_clear_async_rc(lli->lli_clob); lli->lli_async_rc = 0; } @@ -2593,9 +2594,11 @@ static int ll_flush(struct file *file, fl_owner_t id) */ rc = lli->lli_async_rc; lli->lli_async_rc = 0; - err = lov_read_and_clear_async_rc(lli->lli_clob); - if (rc == 0) - rc = err; + if (lli->lli_clob) { + err = lov_read_and_clear_async_rc(lli->lli_clob); + if (!rc) + rc = err; + } /* The application has been told about write failure already. * Do not report failure again. @@ -2825,6 +2828,108 @@ ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock) return rc; } +static int ll_get_fid_by_name(struct inode *parent, const char *name, + int namelen, struct lu_fid *fid) +{ + struct md_op_data *op_data = NULL; + struct ptlrpc_request *req; + struct mdt_body *body; + int rc; + + op_data = ll_prep_md_op_data(NULL, parent, NULL, name, namelen, 0, + LUSTRE_OPC_ANY, NULL); + if (IS_ERR(op_data)) + return PTR_ERR(op_data); + + op_data->op_valid = OBD_MD_FLID; + rc = md_getattr_name(ll_i2sbi(parent)->ll_md_exp, op_data, &req); + if (rc < 0) + goto out_free; + + body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); + if (!body) { + rc = -EFAULT; + goto out_req; + } + *fid = body->fid1; +out_req: + ptlrpc_req_finished(req); +out_free: + if (op_data) + ll_finish_md_op_data(op_data); + return rc; +} + +int ll_migrate(struct inode *parent, struct file *file, int mdtidx, + const char *name, int namelen) +{ + struct ptlrpc_request *request = NULL; + struct dentry *dchild = NULL; + struct md_op_data *op_data; + struct qstr qstr; + int rc; + + CDEBUG(D_VFSTRACE, "migrate %s under"DFID" to MDT%d\n", + name, PFID(ll_inode2fid(parent)), mdtidx); + + op_data = ll_prep_md_op_data(NULL, parent, NULL, name, namelen, + 0, LUSTRE_OPC_ANY, NULL); + if (IS_ERR(op_data)) + return PTR_ERR(op_data); + + /* Get child FID first */ + qstr.hash = full_name_hash(parent, name, namelen); + qstr.name = name; + qstr.len = namelen; + dchild = d_lookup(file_dentry(file), &qstr); + if (dchild && dchild->d_inode) { + op_data->op_fid3 = *ll_inode2fid(dchild->d_inode); + } else { + rc = ll_get_fid_by_name(parent, name, strnlen(name, namelen), + &op_data->op_fid3); + if (rc) + goto out_free; + } + + if (!fid_is_sane(&op_data->op_fid3)) { + CERROR("%s: migrate %s, but fid "DFID" is insane\n", + ll_get_fsname(parent->i_sb, NULL, 0), name, + PFID(&op_data->op_fid3)); + goto out_free; + } + + rc = ll_get_mdt_idx_by_fid(ll_i2sbi(parent), &op_data->op_fid3); + if (rc < 0) + goto out_free; + + if (rc == mdtidx) { + CDEBUG(D_INFO, "%s:"DFID" is already on MDT%d.\n", name, + PFID(&op_data->op_fid3), mdtidx); + rc = 0; + goto out_free; + } + + op_data->op_mds = mdtidx; + op_data->op_cli_flags = CLI_MIGRATE; + rc = md_rename(ll_i2sbi(parent)->ll_md_exp, op_data, name, + strnlen(name, namelen), name, strnlen(name, namelen), + &request); + if (!rc) + ll_update_times(request, parent); + + ptlrpc_req_finished(request); + +out_free: + if (dchild) { + if (dchild->d_inode) + ll_delete_inode(dchild->d_inode); + dput(dchild); + } + + ll_finish_md_op_data(op_data); + return rc; +} + static int ll_file_noflock(struct file *file, int cmd, struct file_lock *file_lock) { diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 82c3a88..69492f0 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -660,6 +660,7 @@ extern const struct inode_operations ll_dir_inode_operations; int ll_dir_read(struct inode *inode, __u64 *ppos, struct md_op_data *op_data, struct dir_context *ctx); int ll_get_mdt_idx(struct inode *inode); +int ll_get_mdt_idx_by_fid(struct ll_sb_info *sbi, const struct lu_fid *fid); struct page *ll_get_dir_page(struct inode *dir, struct md_op_data *op_data, __u64 hash, struct ll_dir_chain *chain); void ll_release_page(struct inode *inode, struct page *page, bool remove); @@ -675,6 +676,7 @@ int ll_test_inode_by_fid(struct inode *inode, void *opaque); int ll_md_blocking_ast(struct ldlm_lock *, struct ldlm_lock_desc *, void *data, int flag); struct dentry *ll_splice_alias(struct inode *inode, struct dentry *de); +void ll_update_times(struct ptlrpc_request *request, struct inode *inode); /* llite/rw.c */ int ll_writepage(struct page *page, struct writeback_control *wbc); @@ -717,7 +719,8 @@ void ll_pack_inode2opdata(struct inode *inode, struct md_op_data *op_data, struct lustre_handle *fh); int ll_getattr(struct vfsmount *mnt, struct dentry *de, struct kstat *stat); struct posix_acl *ll_get_acl(struct inode *inode, int type); - +int ll_migrate(struct inode *parent, struct file *file, int mdtidx, + const char *name, int namelen); int ll_inode_permission(struct inode *inode, int mask); int ll_lov_setstripe_ea_info(struct inode *inode, struct dentry *dentry, @@ -777,6 +780,15 @@ int ll_obd_statfs(struct inode *inode, void __user *arg); int ll_get_max_mdsize(struct ll_sb_info *sbi, int *max_mdsize); int ll_get_default_mdsize(struct ll_sb_info *sbi, int *default_mdsize); int ll_process_config(struct lustre_cfg *lcfg); + +enum { + LUSTRE_OPC_MKDIR = 0, + LUSTRE_OPC_SYMLINK = 1, + LUSTRE_OPC_MKNOD = 2, + LUSTRE_OPC_CREATE = 3, + LUSTRE_OPC_ANY = 5, +}; + struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, struct inode *i1, struct inode *i2, const char *name, int namelen, diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index ef8d87a..e320400 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -1114,8 +1114,34 @@ static void ll_update_lsm_md(struct inode *inode, struct lustre_md *md) struct lmv_stripe_md *lsm = md->lmv; int idx; - LASSERT(lsm); LASSERT(S_ISDIR(inode->i_mode)); + CDEBUG(D_INODE, "update lsm %p of "DFID"\n", lli->lli_lsm_md, + PFID(ll_inode2fid(inode))); + + /* no striped information from request. */ + if (!lsm) { + if (!lli->lli_lsm_md) { + return; + } else if (lli->lli_lsm_md->lsm_md_magic == LMV_MAGIC_MIGRATE) { + /* + * migration is done, the temporay MIGRATE layout has + * been removed + */ + CDEBUG(D_INODE, DFID" finish migration.\n", + PFID(ll_inode2fid(inode))); + lmv_free_memmd(lli->lli_lsm_md); + lli->lli_lsm_md = NULL; + return; + } else { + /* + * The lustre_md from req does not include stripeEA, + * see ll_md_setattr + */ + return; + } + } + + /* set the directory layout */ if (!lli->lli_lsm_md) { int rc; @@ -1132,6 +1158,8 @@ static void ll_update_lsm_md(struct inode *inode, struct lustre_md *md) * will not free this lsm */ md->lmv = NULL; + CDEBUG(D_INODE, "Set lsm %p magic %x to "DFID"\n", lsm, + lsm->lsm_md_magic, PFID(ll_inode2fid(inode))); return; } @@ -1668,7 +1696,7 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) lli->lli_maxbytes = MAX_LFS_FILESIZE; } - if (S_ISDIR(inode->i_mode) && md->lmv) + if (S_ISDIR(inode->i_mode)) ll_update_lsm_md(inode, md); #ifdef CONFIG_FS_POSIX_ACL @@ -2306,7 +2334,6 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, if ((opc == LUSTRE_OPC_CREATE) && name && filename_is_volatile(name, namelen, NULL)) op_data->op_bias |= MDS_CREATE_VOLATILE; - op_data->op_opc = opc; op_data->op_mds = 0; op_data->op_data = data; diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index e32d08b..f059882 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -752,8 +752,7 @@ static int ll_create_it(struct inode *dir, struct dentry *dentry, int mode, return 0; } -static void ll_update_times(struct ptlrpc_request *request, - struct inode *inode) +void ll_update_times(struct ptlrpc_request *request, struct inode *inode) { struct mdt_body *body = req_capsule_server_get(&request->rq_pill, &RMF_MDT_BODY); diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index 87393c4..01aee84 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -1015,6 +1015,10 @@ int ll_writepages(struct address_space *mapping, struct writeback_control *wbc) * is called later on. */ ignore_layout = 1; + + if (!ll_i2info(inode)->lli_clob) + return 0; + result = cl_sync_file_range(inode, start, end, mode, ignore_layout); if (result > 0) { wbc->nr_to_write -= result; diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c index 6ce7442..e8c1959 100644 --- a/drivers/staging/lustre/lustre/llite/statahead.c +++ b/drivers/staging/lustre/lustre/llite/statahead.c @@ -1607,6 +1607,7 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp, *dentryp, PFID(ll_inode2fid(d_inode(*dentryp))), PFID(ll_inode2fid(inode))); + ll_intent_release(&it); ll_sai_unplug(sai, entry); return -ESTALE; } else { diff --git a/drivers/staging/lustre/lustre/lmv/lmv_intent.c b/drivers/staging/lustre/lustre/lmv/lmv_intent.c index 5313dfc..2bc1098 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_intent.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_intent.c @@ -43,6 +43,7 @@ #include "../include/lustre_lib.h" #include "../include/lustre_net.h" #include "../include/lustre_dlm.h" +#include "../include/lustre_mdc.h" #include "../include/obd_class.h" #include "../include/lprocfs_status.h" #include "lmv_internal.h" @@ -332,6 +333,8 @@ static int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data, oinfo = lsm_name_to_stripe_info(lsm, op_data->op_name, op_data->op_namelen); + if (IS_ERR(oinfo)) + return PTR_ERR(oinfo); op_data->op_fid1 = oinfo->lmo_fid; } @@ -408,6 +411,7 @@ static int lmv_intent_lookup(struct obd_export *exp, ldlm_blocking_callback cb_blocking, __u64 extra_lock_flags) { + struct lmv_stripe_md *lsm = op_data->op_mea1; struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt = NULL; @@ -421,17 +425,15 @@ static int lmv_intent_lookup(struct obd_export *exp, if (!fid_is_sane(&op_data->op_fid2)) fid_zero(&op_data->op_fid2); - CDEBUG(D_INODE, "LOOKUP_INTENT with fid1="DFID", fid2="DFID - ", name='%s' -> mds #%d\n", PFID(&op_data->op_fid1), - PFID(&op_data->op_fid2), + CDEBUG(D_INODE, "LOOKUP_INTENT with fid1="DFID", fid2="DFID", name='%s' -> mds #%d lsm=%p lsm_magic=%x\n", + PFID(&op_data->op_fid1), PFID(&op_data->op_fid2), op_data->op_name ? op_data->op_name : "<NULL>", - tgt->ltd_idx); + tgt->ltd_idx, lsm, !lsm ? -1 : lsm->lsm_md_magic); op_data->op_bias &= ~MDS_CROSS_REF; rc = md_intent_lock(tgt->ltd_exp, op_data, lmm, lmmsize, it, flags, reqp, cb_blocking, extra_lock_flags); - if (rc < 0) return rc; @@ -448,6 +450,26 @@ static int lmv_intent_lookup(struct obd_export *exp, return rc; } return rc; + } else if (it_disposition(it, DISP_LOOKUP_NEG) && lsm && + lsm->lsm_md_magic == LMV_MAGIC_MIGRATE) { + /* + * For migrating directory, if it can not find the child in + * the source directory(master stripe), try the targeting + * directory(stripe 1) + */ + tgt = lmv_find_target(lmv, &lsm->lsm_md_oinfo[1].lmo_fid); + if (IS_ERR(tgt)) + return PTR_ERR(tgt); + + ptlrpc_req_finished(*reqp); + CDEBUG(D_INODE, "For migrating dir, try target dir "DFID"\n", + PFID(&lsm->lsm_md_oinfo[1].lmo_fid)); + + op_data->op_fid1 = lsm->lsm_md_oinfo[1].lmo_fid; + it->it_disposition &= ~DISP_ENQ_COMPLETE; + rc = md_intent_lock(tgt->ltd_exp, op_data, lmm, lmmsize, it, + flags, reqp, cb_blocking, extra_lock_flags); + return rc; } /* diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 81dcc0a..09b2efe 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -96,6 +96,15 @@ int lmv_name_to_stripe_index(enum lmv_hash_type hashtype, case LMV_HASH_TYPE_FNV_1A_64: idx = lmv_hash_fnv1a(max_mdt_index, name, namelen); break; + /* + * LMV_HASH_TYPE_MIGRATION means the file is being migrated, + * and the file should be accessed by client, except for + * lookup(see lmv_intent_lookup), return -EACCES here + */ + case LMV_HASH_TYPE_MIGRATION: + CERROR("%.*s is being migrated: rc = %d\n", namelen, + name, -EACCES); + return -EACCES; default: CERROR("Unknown hash type 0x%x\n", hashtype); return -EINVAL; @@ -1667,6 +1676,9 @@ lmv_locate_target_for_name(struct lmv_obd *lmv, struct lmv_stripe_md *lsm, struct lmv_tgt_desc *tgt; oinfo = lsm_name_to_stripe_info(lsm, name, namelen); + if (IS_ERR(oinfo)) + return ERR_CAST(oinfo); + *fid = oinfo->lmo_fid; *mds = oinfo->lmo_mds; tgt = lmv_get_target(lmv, *mds); @@ -1683,7 +1695,8 @@ struct lmv_tgt_desc struct lmv_tgt_desc *tgt; if (!lsm || lsm->lsm_md_stripe_count <= 1 || - !op_data->op_namelen) { + !op_data->op_namelen || + lsm->lsm_md_magic == LMV_MAGIC_MIGRATE) { tgt = lmv_find_target(lmv, fid); if (IS_ERR(tgt)) return tgt; @@ -1929,23 +1942,24 @@ lmv_getattr_name(struct obd_export *exp, struct md_op_data *op_data, fl == MF_MDC_CANCEL_FID4 ? &op_data->op_fid4 : \ NULL) -static int lmv_early_cancel(struct obd_export *exp, struct md_op_data *op_data, - int op_tgt, enum ldlm_mode mode, int bits, - int flag) +static int lmv_early_cancel(struct obd_export *exp, struct lmv_tgt_desc *tgt, + struct md_op_data *op_data, int op_tgt, + enum ldlm_mode mode, int bits, int flag) { struct lu_fid *fid = md_op_data_fid(op_data, flag); struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; - struct lmv_tgt_desc *tgt; ldlm_policy_data_t policy = { {0} }; int rc = 0; if (!fid_is_sane(fid)) return 0; - tgt = lmv_find_target(lmv, fid); - if (IS_ERR(tgt)) - return PTR_ERR(tgt); + if (!tgt) { + tgt = lmv_find_target(lmv, fid); + if (IS_ERR(tgt)) + return PTR_ERR(tgt); + } if (tgt->ltd_idx != op_tgt) { CDEBUG(D_INODE, "EARLY_CANCEL on "DFID"\n", PFID(fid)); @@ -1994,6 +2008,9 @@ static int lmv_link(struct obd_export *exp, struct md_op_data *op_data, oinfo = lsm_name_to_stripe_info(lsm, op_data->op_name, op_data->op_namelen); + if (IS_ERR(oinfo)) + return PTR_ERR(oinfo); + op_data->op_fid2 = oinfo->lmo_fid; } @@ -2005,7 +2022,7 @@ static int lmv_link(struct obd_export *exp, struct md_op_data *op_data, * Cancel UPDATE lock on child (fid1). */ op_data->op_flags |= MF_MDC_CANCEL_FID2; - rc = lmv_early_cancel(exp, op_data, tgt->ltd_idx, LCK_EX, + rc = lmv_early_cancel(exp, NULL, op_data, tgt->ltd_idx, LCK_EX, MDS_INODELOCK_UPDATE, MF_MDC_CANCEL_FID1); if (rc != 0) return rc; @@ -2040,31 +2057,44 @@ static int lmv_rename(struct obd_export *exp, struct md_op_data *op_data, op_data->op_fsgid = from_kgid(&init_user_ns, current_fsgid()); op_data->op_cap = cfs_curproc_cap_pack(); - if (op_data->op_mea1) { - struct lmv_stripe_md *lsm = op_data->op_mea1; - const struct lmv_oinfo *oinfo; - - oinfo = lsm_name_to_stripe_info(lsm, old, oldlen); - op_data->op_fid1 = oinfo->lmo_fid; - op_data->op_mds = oinfo->lmo_mds; - src_tgt = lmv_get_target(lmv, op_data->op_mds); - if (IS_ERR(src_tgt)) - return PTR_ERR(src_tgt); + if (op_data->op_cli_flags & CLI_MIGRATE) { + LASSERTF(fid_is_sane(&op_data->op_fid3), "invalid FID "DFID"\n", + PFID(&op_data->op_fid3)); + rc = lmv_fid_alloc(exp, &op_data->op_fid2, op_data); + if (rc) + return rc; + src_tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid3); } else { - src_tgt = lmv_find_target(lmv, &op_data->op_fid1); - if (IS_ERR(src_tgt)) - return PTR_ERR(src_tgt); + if (op_data->op_mea1) { + struct lmv_stripe_md *lsm = op_data->op_mea1; + + src_tgt = lmv_locate_target_for_name(lmv, lsm, old, + oldlen, + &op_data->op_fid1, + &op_data->op_mds); + if (IS_ERR(src_tgt)) + return PTR_ERR(src_tgt); + } else { + src_tgt = lmv_find_target(lmv, &op_data->op_fid1); + if (IS_ERR(src_tgt)) + return PTR_ERR(src_tgt); - op_data->op_mds = src_tgt->ltd_idx; - } + op_data->op_mds = src_tgt->ltd_idx; + } - if (op_data->op_mea2) { - struct lmv_stripe_md *lsm = op_data->op_mea2; - const struct lmv_oinfo *oinfo; + if (op_data->op_mea2) { + struct lmv_stripe_md *lsm = op_data->op_mea2; + const struct lmv_oinfo *oinfo; - oinfo = lsm_name_to_stripe_info(lsm, new, newlen); - op_data->op_fid2 = oinfo->lmo_fid; + oinfo = lsm_name_to_stripe_info(lsm, new, newlen); + if (IS_ERR(oinfo)) + return PTR_ERR(oinfo); + + op_data->op_fid2 = oinfo->lmo_fid; + } } + if (IS_ERR(src_tgt)) + return PTR_ERR(src_tgt); /* * LOOKUP lock on src child (fid3) should also be cancelled for @@ -2076,33 +2106,48 @@ static int lmv_rename(struct obd_export *exp, struct md_op_data *op_data, * Cancel UPDATE locks on tgt parent (fid2), tgt_tgt is its * own target. */ - rc = lmv_early_cancel(exp, op_data, src_tgt->ltd_idx, + rc = lmv_early_cancel(exp, NULL, op_data, src_tgt->ltd_idx, LCK_EX, MDS_INODELOCK_UPDATE, MF_MDC_CANCEL_FID2); - + if (rc) + return rc; /* - * Cancel LOOKUP locks on tgt child (fid4) for parent tgt_tgt. + * Cancel LOOKUP locks on source child (fid3) for parent tgt_tgt. */ - if (rc == 0) { - rc = lmv_early_cancel(exp, op_data, src_tgt->ltd_idx, + if (fid_is_sane(&op_data->op_fid3)) { + struct lmv_tgt_desc *tgt; + + tgt = lmv_find_target(lmv, &op_data->op_fid1); + if (IS_ERR(tgt)) + return PTR_ERR(tgt); + + /* Cancel LOOKUP lock on its parent */ + rc = lmv_early_cancel(exp, tgt, op_data, src_tgt->ltd_idx, LCK_EX, MDS_INODELOCK_LOOKUP, - MF_MDC_CANCEL_FID4); + MF_MDC_CANCEL_FID3); + if (rc) + return rc; + + rc = lmv_early_cancel(exp, NULL, op_data, src_tgt->ltd_idx, + LCK_EX, MDS_INODELOCK_FULL, + MF_MDC_CANCEL_FID3); + if (rc) + return rc; } /* * Cancel all the locks on tgt child (fid4). */ - if (rc == 0) - rc = lmv_early_cancel(exp, op_data, src_tgt->ltd_idx, + if (fid_is_sane(&op_data->op_fid4)) + rc = lmv_early_cancel(exp, NULL, op_data, src_tgt->ltd_idx, LCK_EX, MDS_INODELOCK_FULL, MF_MDC_CANCEL_FID4); CDEBUG(D_INODE, DFID":m%d to "DFID"\n", PFID(&op_data->op_fid1), op_data->op_mds, PFID(&op_data->op_fid2)); - if (rc == 0) - rc = md_rename(src_tgt->ltd_exp, op_data, old, oldlen, - new, newlen, request); + rc = md_rename(src_tgt->ltd_exp, op_data, old, oldlen, + new, newlen, request); return rc; } @@ -2304,6 +2349,7 @@ static int lmv_unlink(struct obd_export *exp, struct md_op_data *op_data, { struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; + struct lmv_tgt_desc *parent_tgt = NULL; struct lmv_tgt_desc *tgt = NULL; struct mdt_body *body; int rc; @@ -2321,12 +2367,16 @@ retry: /* For striped dir, we need to locate the parent as well */ if (op_data->op_mea1 && op_data->op_mea1->lsm_md_stripe_count > 1) { + struct lmv_tgt_desc *tmp; + LASSERT(op_data->op_name && op_data->op_namelen); - lmv_locate_target_for_name(lmv, op_data->op_mea1, - op_data->op_name, - op_data->op_namelen, - &op_data->op_fid1, - &op_data->op_mds); + tmp = lmv_locate_target_for_name(lmv, op_data->op_mea1, + op_data->op_name, + op_data->op_namelen, + &op_data->op_fid1, + &op_data->op_mds); + if (IS_ERR(tmp)) + return PTR_ERR(tmp); } } else { tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1); @@ -2350,9 +2400,18 @@ retry: /* * Cancel FULL locks on child (fid3). */ - rc = lmv_early_cancel(exp, op_data, tgt->ltd_idx, LCK_EX, - MDS_INODELOCK_FULL, MF_MDC_CANCEL_FID3); + parent_tgt = lmv_find_target(lmv, &op_data->op_fid1); + if (IS_ERR(parent_tgt)) + return PTR_ERR(parent_tgt); + + if (parent_tgt != tgt) { + rc = lmv_early_cancel(exp, parent_tgt, op_data, tgt->ltd_idx, + LCK_EX, MDS_INODELOCK_LOOKUP, + MF_MDC_CANCEL_FID3); + } + rc = lmv_early_cancel(exp, NULL, op_data, tgt->ltd_idx, LCK_EX, + MDS_INODELOCK_FULL, MF_MDC_CANCEL_FID3); if (rc != 0) return rc; @@ -2681,13 +2740,25 @@ int lmv_unpack_md(struct obd_export *exp, struct lmv_stripe_md **lsmp, } /* Unpack memmd */ - if (le32_to_cpu(lmm->lmv_magic) != LMV_MAGIC_V1) { - CERROR("%s: invalid magic %x.\n", exp->exp_obd->obd_name, - le32_to_cpu(lmm->lmv_magic)); - return -EINVAL; + if (le32_to_cpu(lmm->lmv_magic) != LMV_MAGIC_V1 && + le32_to_cpu(lmm->lmv_magic) != LMV_MAGIC_MIGRATE && + le32_to_cpu(lmm->lmv_magic) != LMV_USER_MAGIC) { + CERROR("%s: invalid lmv magic %x: rc = %d\n", + exp->exp_obd->obd_name, le32_to_cpu(lmm->lmv_magic), + -EIO); + return -EIO; } - lsm_size = lmv_stripe_md_size(lmv_mds_md_stripe_count_get(lmm)); + if (le32_to_cpu(lmm->lmv_magic) == LMV_MAGIC_V1 || + le32_to_cpu(lmm->lmv_magic) == LMV_MAGIC_MIGRATE) + lsm_size = lmv_stripe_md_size(lmv_mds_md_stripe_count_get(lmm)); + else + /** + * Unpack default dirstripe(lmv_user_md) to lmv_stripe_md, + * stripecount should be 0 then. + */ + lsm_size = lmv_stripe_md_size(0); + if (!lsm) { lsm = libcfs_kvzalloc(lsm_size, GFP_NOFS); if (!lsm) @@ -2698,6 +2769,7 @@ int lmv_unpack_md(struct obd_export *exp, struct lmv_stripe_md **lsmp, switch (le32_to_cpu(lmm->lmv_magic)) { case LMV_MAGIC_V1: + case LMV_MAGIC_MIGRATE: rc = lmv_unpack_md_v1(exp, lsm, &lmm->lmv_md_v1); break; default: diff --git a/drivers/staging/lustre/lustre/mdc/mdc_lib.c b/drivers/staging/lustre/lustre/mdc/mdc_lib.c index 143bd76..95c4550 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_lib.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_lib.c @@ -390,6 +390,8 @@ void mdc_rename_pack(struct ptlrpc_request *req, struct md_op_data *op_data, rec = req_capsule_client_get(&req->rq_pill, &RMF_REC_REINT); /* XXX do something about time, uid, gid */ + rec->rn_opcode = op_data->op_cli_flags & CLI_MIGRATE ? + REINT_MIGRATE : REINT_RENAME; rec->rn_opcode = REINT_RENAME; rec->rn_fsuid = op_data->op_fsuid; rec->rn_fsgid = op_data->op_fsgid; diff --git a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c index 4c500a9..bc27f8d 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c +++ b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c @@ -190,7 +190,9 @@ void lustre_assert_wire_constants(void) (long long)REINT_SETXATTR); LASSERTF(REINT_RMENTRY == 8, "found %lld\n", (long long)REINT_RMENTRY); - LASSERTF(REINT_MAX == 9, "found %lld\n", + LASSERTF(REINT_MIGRATE == 9, "found %lld\n", + (long long)REINT_MIGRATE); + LASSERTF(REINT_MAX == 10, "found %lld\n", (long long)REINT_MAX); LASSERTF(DISP_IT_EXECD == 0x00000001UL, "found 0x%.8xUL\n", (unsigned)DISP_IT_EXECD); -- cgit v0.10.2 From 503df2c4dfcfa32d6e0b03503a31ef76b3144450 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin <dmitry.eremin@intel.com> Date: Tue, 16 Aug 2016 16:18:31 -0400 Subject: staging: lustre: lmv: fix issue found by Klocwork Insight tool 'plock.cookie' might be used uninitialized in this function. sscanf format specification '%d' expects type 'int *' for 'd', but parameter 3 has a different type '__u32*' Signed-off-by: Dmitry Eremin <dmitry.eremin@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4629 Reviewed-on: http://review.whamcloud.com/9390 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/lmv/lmv_intent.c b/drivers/staging/lustre/lustre/lmv/lmv_intent.c index 2bc1098..51b7048 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_intent.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_intent.c @@ -137,8 +137,10 @@ static int lmv_intent_remote(struct obd_export *exp, void *lmm, it->it_remote_lock_mode = it->it_lock_mode; } - it->it_lock_handle = plock.cookie; - it->it_lock_mode = pmode; + if (pmode) { + it->it_lock_handle = plock.cookie; + it->it_lock_mode = pmode; + } out_free_op_data: kfree(op_data); diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 09b2efe..c005a66 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -1419,7 +1419,7 @@ static int lmv_process_config(struct obd_device *obd, u32 len, void *buf) obd_str2uuid(&obd_uuid, lustre_cfg_buf(lcfg, 1)); - if (sscanf(lustre_cfg_buf(lcfg, 2), "%d", &index) != 1) { + if (sscanf(lustre_cfg_buf(lcfg, 2), "%u", &index) != 1) { rc = -EINVAL; goto out; } -- cgit v0.10.2 From a9bcd881b27fc8a4e7e3eccf4bb834a9e20a7508 Mon Sep 17 00:00:00 2001 From: Ryan Haasken <haasken@cray.com> Date: Tue, 16 Aug 2016 16:18:32 -0400 Subject: staging: lustre: libcfs: Only dump log once per sec. to avoid EEXIST Since the log file name contains the current time in seconds, dumping the logs more than once per second causes EEXIST errors to be emitted. Add a static variable to libcfs_debug_dumplog_internal that records the time of the last Lustre log dump. If the current time in seconds is equal to the last time, do not dump logs again. Note that this is not thread-safe. However, in the rare case that two threads try to access last_dump_time simultaneously, the worst thing that could happen is that one of the threads will get an EEXIST error when trying to write the log file. This is no worse than the current situation, and it is not likely to happen. Signed-off-by: Ryan Haasken <haasken@cray.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4129 Reviewed-on: http://review.whamcloud.com/8964 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Bob Glossman <bob.glossman@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lnet/libcfs/debug.c b/drivers/staging/lustre/lnet/libcfs/debug.c index 42b15a7..23b36b8 100644 --- a/drivers/staging/lustre/lnet/libcfs/debug.c +++ b/drivers/staging/lustre/lnet/libcfs/debug.c @@ -328,15 +328,20 @@ libcfs_debug_str2mask(int *mask, const char *str, int is_subsys) */ void libcfs_debug_dumplog_internal(void *arg) { + static time64_t last_dump_time; + time64_t current_time; void *journal_info; journal_info = current->journal_info; current->journal_info = NULL; + current_time = ktime_get_real_seconds(); - if (strncmp(libcfs_debug_file_path_arr, "NONE", 4) != 0) { + if (strncmp(libcfs_debug_file_path_arr, "NONE", 4) && + current_time > last_dump_time) { + last_dump_time = current_time; snprintf(debug_file_name, sizeof(debug_file_name) - 1, "%s.%lld.%ld", libcfs_debug_file_path_arr, - (s64)ktime_get_real_seconds(), (long_ptr_t)arg); + (s64)current_time, (long_ptr_t)arg); pr_alert("LustreError: dumping log to %s\n", debug_file_name); cfs_tracefile_dump_all_pages(debug_file_name); libcfs_run_debug_log_upcall(debug_file_name); -- cgit v0.10.2 From 66bff4ade42c427d7b301e90f0e0cbe88db2ce27 Mon Sep 17 00:00:00 2001 From: Fan Yong <fan.yong@intel.com> Date: Tue, 16 Aug 2016 16:18:33 -0400 Subject: staging: lustre: llite: enable clients to inject error for lfsck This enables the client to inject an error by altering the parent FID in order to test if the server side file system checker behaves properly. Signed-off-by: Fan Yong <fan.yong@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3951 Reviewed-on: http://review.whamcloud.com/7667 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Alex Zhuravlev <alexey.zhuravlev@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd_support.h b/drivers/staging/lustre/lustre/include/obd_support.h index 845e64a..71bf844 100644 --- a/drivers/staging/lustre/lustre/include/obd_support.h +++ b/drivers/staging/lustre/lustre/include/obd_support.h @@ -474,6 +474,7 @@ extern char obd_jobid_var[]; #define OBD_FAIL_LFSCK_CRASH 0x160a #define OBD_FAIL_LFSCK_NO_AUTO 0x160b #define OBD_FAIL_LFSCK_NO_DOUBLESCAN 0x160c +#define OBD_FAIL_LFSCK_INVALID_PFID 0x1619 /* UPDATE */ #define OBD_FAIL_UPDATE_OBJ_NET 0x1700 diff --git a/drivers/staging/lustre/lustre/llite/vvp_req.c b/drivers/staging/lustre/lustre/llite/vvp_req.c index 9fe9d6c..0567a15 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_req.c +++ b/drivers/staging/lustre/lustre/llite/vvp_req.c @@ -83,6 +83,8 @@ static void vvp_req_attr_set(const struct lu_env *env, } obdo_from_inode(oa, inode, valid_flags & flags); obdo_set_parent_fid(oa, &ll_i2info(inode)->lli_fid); + if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_INVALID_PFID)) + oa->o_parent_oid++; memcpy(attr->cra_jobid, ll_i2info(inode)->lli_jobid, JOBSTATS_JOBID_SIZE); } -- cgit v0.10.2 From fa1cc96617adb982e11053545b9c2fdf63260065 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong <jinshan.xiong@intel.com> Date: Tue, 16 Aug 2016 16:18:34 -0400 Subject: staging: lustre: osc: allow to call brw_commit() multiple times Sometimes the rq_commit_cb of BRW RPC can be called twice if that RPC has already committed at reply time. This will cause inaccuracy of unstable pages accounting and then assertion. Signed-off-by: Jinshan Xiong <jinshan.xiong@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3274 Reviewed-on: http://review.whamcloud.com/8215 Reviewed-by: Prakash Surya <surya1@llnl.gov> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index 53b5d73..683b3c2 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -1875,11 +1875,6 @@ void osc_dec_unstable_pages(struct ptlrpc_request *req) atomic_sub(page_count, &obd_unstable_pages); LASSERT(atomic_read(&obd_unstable_pages) >= 0); - spin_lock(&req->rq_lock); - req->rq_committed = 1; - req->rq_unstable = 0; - spin_unlock(&req->rq_lock); - wake_up_all(&cli->cl_cache->ccc_unstable_waitq); } @@ -1909,27 +1904,21 @@ void osc_inc_unstable_pages(struct ptlrpc_request *req) LASSERT(atomic_read(&obd_unstable_pages) >= 0); atomic_add(page_count, &obd_unstable_pages); - spin_lock(&req->rq_lock); - /* * If the request has already been committed (i.e. brw_commit * called via rq_commit_cb), we need to undo the unstable page * increments we just performed because rq_commit_cb wont be - * called again. Otherwise, just set the commit callback so the - * unstable page accounting is properly updated when the request - * is committed + * called again. */ - if (req->rq_committed) { + spin_lock(&req->rq_lock); + if (unlikely(req->rq_committed)) { /* Drop lock before calling osc_dec_unstable_pages */ spin_unlock(&req->rq_lock); osc_dec_unstable_pages(req); - spin_lock(&req->rq_lock); } else { req->rq_unstable = 1; - req->rq_commit_cb = osc_dec_unstable_pages; + spin_unlock(&req->rq_lock); } - - spin_unlock(&req->rq_lock); } /* this must be called holding the loi list lock to give coverage to exit_cache, diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 536b868..a2d948f 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -1847,21 +1847,21 @@ static int brw_interpret(const struct lu_env *env, static void brw_commit(struct ptlrpc_request *req) { - spin_lock(&req->rq_lock); /* * If osc_inc_unstable_pages (via osc_extent_finish) races with * this called via the rq_commit_cb, I need to ensure * osc_dec_unstable_pages is still called. Otherwise unstable * pages may be leaked. */ - if (req->rq_unstable) { + spin_lock(&req->rq_lock); + if (unlikely(req->rq_unstable)) { + req->rq_unstable = 0; spin_unlock(&req->rq_lock); osc_dec_unstable_pages(req); - spin_lock(&req->rq_lock); } else { req->rq_committed = 1; + spin_unlock(&req->rq_lock); } - spin_unlock(&req->rq_lock); } /** -- cgit v0.10.2 From 1d82425fbd5831097369eff1a4b8dcb5205d3da0 Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Tue, 16 Aug 2016 16:18:35 -0400 Subject: staging: lustre: llite: a few fixes for migration. 1. Clear the client dentry cache before migrating file/directory to the remote MDT. 2. Do not return stripe information to client, if it did not get the layout lock. Signed-off-by: wang di <di.wang@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4682 Reviewed-on: http://review.whamcloud.com/9522 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index ef7322e..84bec03 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -1318,11 +1318,9 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return 0; } case IOC_MDC_LOOKUP: { - struct ptlrpc_request *request = NULL; int namelen, len = 0; char *buf = NULL; char *filename; - struct md_op_data *op_data; rc = obd_ioctl_getdata(&buf, &len, (void __user *)arg); if (rc) @@ -1338,21 +1336,13 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) goto out_free; } - op_data = ll_prep_md_op_data(NULL, inode, NULL, filename, namelen, - 0, LUSTRE_OPC_ANY, NULL); - if (IS_ERR(op_data)) { - rc = PTR_ERR(op_data); - goto out_free; - } - - op_data->op_valid = OBD_MD_FLID; - rc = md_getattr_name(sbi->ll_md_exp, op_data, &request); - ll_finish_md_op_data(op_data); + rc = ll_get_fid_by_name(inode, filename, namelen, NULL); if (rc < 0) { - CDEBUG(D_INFO, "md_getattr_name: %d\n", rc); + CERROR("%s: lookup %.*s failed: rc = %d\n", + ll_get_fsname(inode->i_sb, NULL, 0), namelen, + filename, rc); goto out_free; } - ptlrpc_req_finished(request); out_free: obd_ioctl_freedata(buf, len); return rc; @@ -1981,7 +1971,7 @@ out_quotactl: filename = data->ioc_inlbuf1; namelen = data->ioc_inllen1; - if (namelen < 1) { + if (namelen < 1 || namelen != strlen(filename) + 1) { rc = -EINVAL; goto migrate_free; } @@ -1992,7 +1982,7 @@ out_quotactl: } mdtidx = *(int *)data->ioc_inlbuf2; - rc = ll_migrate(inode, file, mdtidx, filename, namelen); + rc = ll_migrate(inode, file, mdtidx, filename, namelen - 1); migrate_free: obd_ioctl_freedata(buf, len); diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 8d98db6..769b028 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -2828,8 +2828,8 @@ ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock) return rc; } -static int ll_get_fid_by_name(struct inode *parent, const char *name, - int namelen, struct lu_fid *fid) +int ll_get_fid_by_name(struct inode *parent, const char *name, + int namelen, struct lu_fid *fid) { struct md_op_data *op_data = NULL; struct ptlrpc_request *req; @@ -2843,20 +2843,19 @@ static int ll_get_fid_by_name(struct inode *parent, const char *name, op_data->op_valid = OBD_MD_FLID; rc = md_getattr_name(ll_i2sbi(parent)->ll_md_exp, op_data, &req); + ll_finish_md_op_data(op_data); if (rc < 0) - goto out_free; + return rc; body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); if (!body) { rc = -EFAULT; goto out_req; } - *fid = body->fid1; + if (fid) + *fid = body->fid1; out_req: ptlrpc_req_finished(req); -out_free: - if (op_data) - ll_finish_md_op_data(op_data); return rc; } @@ -2864,12 +2863,13 @@ int ll_migrate(struct inode *parent, struct file *file, int mdtidx, const char *name, int namelen) { struct ptlrpc_request *request = NULL; + struct inode *child_inode = NULL; struct dentry *dchild = NULL; struct md_op_data *op_data; struct qstr qstr; int rc; - CDEBUG(D_VFSTRACE, "migrate %s under"DFID" to MDT%d\n", + CDEBUG(D_VFSTRACE, "migrate %s under "DFID" to MDT%d\n", name, PFID(ll_inode2fid(parent)), mdtidx); op_data = ll_prep_md_op_data(NULL, parent, NULL, name, namelen, @@ -2884,8 +2884,13 @@ int ll_migrate(struct inode *parent, struct file *file, int mdtidx, dchild = d_lookup(file_dentry(file), &qstr); if (dchild && dchild->d_inode) { op_data->op_fid3 = *ll_inode2fid(dchild->d_inode); + if (dchild->d_inode) { + child_inode = igrab(dchild->d_inode); + ll_invalidate_aliases(child_inode); + } + dput(dchild); } else { - rc = ll_get_fid_by_name(parent, name, strnlen(name, namelen), + rc = ll_get_fid_by_name(parent, name, namelen, &op_data->op_fid3); if (rc) goto out_free; @@ -2895,6 +2900,7 @@ int ll_migrate(struct inode *parent, struct file *file, int mdtidx, CERROR("%s: migrate %s, but fid "DFID" is insane\n", ll_get_fsname(parent->i_sb, NULL, 0), name, PFID(&op_data->op_fid3)); + rc = -EINVAL; goto out_free; } @@ -2912,18 +2918,16 @@ int ll_migrate(struct inode *parent, struct file *file, int mdtidx, op_data->op_mds = mdtidx; op_data->op_cli_flags = CLI_MIGRATE; rc = md_rename(ll_i2sbi(parent)->ll_md_exp, op_data, name, - strnlen(name, namelen), name, strnlen(name, namelen), - &request); + namelen, name, namelen, &request); if (!rc) ll_update_times(request, parent); ptlrpc_req_finished(request); out_free: - if (dchild) { - if (dchild->d_inode) - ll_delete_inode(dchild->d_inode); - dput(dchild); + if (child_inode) { + clear_nlink(child_inode); + iput(child_inode); } ll_finish_md_op_data(op_data); diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 69492f0..120aca3 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -721,6 +721,8 @@ int ll_getattr(struct vfsmount *mnt, struct dentry *de, struct kstat *stat); struct posix_acl *ll_get_acl(struct inode *inode, int type); int ll_migrate(struct inode *parent, struct file *file, int mdtidx, const char *name, int namelen); +int ll_get_fid_by_name(struct inode *parent, const char *name, + int namelen, struct lu_fid *fid); int ll_inode_permission(struct inode *inode, int mask); int ll_lov_setstripe_ea_info(struct inode *inode, struct dentry *dentry, diff --git a/drivers/staging/lustre/lustre/lov/lov_object.c b/drivers/staging/lustre/lustre/lov/lov_object.c index f9621b0..2a52d0c5 100644 --- a/drivers/staging/lustre/lustre/lov/lov_object.c +++ b/drivers/staging/lustre/lustre/lov/lov_object.c @@ -224,6 +224,7 @@ static int lov_init_raid0(const struct lu_env *env, LASSERT(!lov->lo_lsm); lov->lo_lsm = lsm_addref(lsm); + lov->lo_layout_invalid = true; r0->lo_nr = lsm->lsm_stripe_count; LASSERT(r0->lo_nr <= lov_targets_nr(dev)); -- cgit v0.10.2 From 29792c81f90ed85d94b23f3fc31e646c241bd44a Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Tue, 16 Aug 2016 16:18:36 -0400 Subject: staging: lustre: mdc: fixup MDS_SWAP_LAYOUTS ELC handling In mdc_ioc_swap_layouts() cancel *any* unused locks with LAYOUT or XATTR IBITS set on the two files. (This matches the locks acquired in mdt_swap_layouts(). Previously only locks that conflicted with a CR LAYOUT lock were cancelled.) Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4320 Reviewed-on: http://review.whamcloud.com/9329 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Faccini Bruno <bruno.faccini@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 702ced9..030295f 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -1670,9 +1670,11 @@ static int mdc_ioc_swap_layouts(struct obd_export *exp, * with the request RPC to avoid extra RPC round trips */ count = mdc_resource_get_unused(exp, &op_data->op_fid1, &cancels, - LCK_CR, MDS_INODELOCK_LAYOUT); + LCK_CR, MDS_INODELOCK_LAYOUT | + MDS_INODELOCK_XATTR); count += mdc_resource_get_unused(exp, &op_data->op_fid2, &cancels, - LCK_CR, MDS_INODELOCK_LAYOUT); + LCK_CR, MDS_INODELOCK_LAYOUT | + MDS_INODELOCK_XATTR); req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_MDS_SWAP_LAYOUTS); -- cgit v0.10.2 From f7ee4497275ed122d0df706de35a40635f08c3c2 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Tue, 16 Aug 2016 16:18:37 -0400 Subject: staging: lustre: don't need to const __u64 parameters for lustre_idl.h Remove the const for the __u64 parameters for inline functions in lustre_idl.h. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2675 Reviewed-on: http://review.whamcloud.com/8641 Reviewed-by: wangdi <di.wang@intel.com> Reviewed-by: Fan Yong <fan.yong@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 6853f62..87e79b9 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -442,7 +442,7 @@ static inline int fid_seq_is_mdt0(__u64 seq) return (seq == FID_SEQ_OST_MDT0); } -static inline int fid_seq_is_mdt(const __u64 seq) +static inline int fid_seq_is_mdt(__u64 seq) { return seq == FID_SEQ_OST_MDT0 || seq >= FID_SEQ_NORMAL; }; @@ -468,33 +468,33 @@ static inline int fid_is_llog(const struct lu_fid *fid) return fid_seq_is_llog(fid_seq(fid)) && fid_oid(fid) > 0; } -static inline int fid_seq_is_rsvd(const __u64 seq) +static inline int fid_seq_is_rsvd(__u64 seq) { return (seq > FID_SEQ_OST_MDT0 && seq <= FID_SEQ_RSVD); }; -static inline int fid_seq_is_special(const __u64 seq) +static inline int fid_seq_is_special(__u64 seq) { return seq == FID_SEQ_SPECIAL; }; -static inline int fid_seq_is_local_file(const __u64 seq) +static inline int fid_seq_is_local_file(__u64 seq) { return seq == FID_SEQ_LOCAL_FILE || seq == FID_SEQ_LOCAL_NAME; }; -static inline int fid_seq_is_root(const __u64 seq) +static inline int fid_seq_is_root(__u64 seq) { return seq == FID_SEQ_ROOT; } -static inline int fid_seq_is_dot(const __u64 seq) +static inline int fid_seq_is_dot(__u64 seq) { return seq == FID_SEQ_DOT_LUSTRE; } -static inline int fid_seq_is_default(const __u64 seq) +static inline int fid_seq_is_default(__u64 seq) { return seq == FID_SEQ_LOV_DEFAULT; } @@ -516,7 +516,7 @@ static inline void lu_root_fid(struct lu_fid *fid) * \param fid the fid to be tested. * \return true if the fid is a igif; otherwise false. */ -static inline int fid_seq_is_igif(const __u64 seq) +static inline int fid_seq_is_igif(__u64 seq) { return seq >= FID_SEQ_IGIF && seq <= FID_SEQ_IGIF_MAX; } @@ -531,7 +531,7 @@ static inline int fid_is_igif(const struct lu_fid *fid) * \param fid the fid to be tested. * \return true if the fid is a idif; otherwise false. */ -static inline int fid_seq_is_idif(const __u64 seq) +static inline int fid_seq_is_idif(__u64 seq) { return seq >= FID_SEQ_IDIF && seq <= FID_SEQ_IDIF_MAX; } @@ -546,7 +546,7 @@ static inline int fid_is_local_file(const struct lu_fid *fid) return fid_seq_is_local_file(fid_seq(fid)); } -static inline int fid_seq_is_norm(const __u64 seq) +static inline int fid_seq_is_norm(__u64 seq) { return (seq >= FID_SEQ_NORMAL); } -- cgit v0.10.2 From ac8f0a5c6aa5fd9bb30fba8433a9c843ee6fc0eb Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Tue, 16 Aug 2016 16:18:38 -0400 Subject: staging: lustre: const correct FID/OSTID/... helpers Add a const qualifier wherever possible to the pointer parameters of the inline helper functions in lustre_idl.h and lustre_fid.h. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2675 Reviewed-on: http://review.whamcloud.com/8641 Reviewed-by: wangdi <di.wang@intel.com> Reviewed-by: Fan Yong <fan.yong@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 87e79b9..c932e20 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -1033,7 +1033,7 @@ static inline int lu_dirent_calc_size(int namelen, __u16 attr) return (size + 7) & ~7; } -static inline int lu_dirent_size(struct lu_dirent *ent) +static inline int lu_dirent_size(const struct lu_dirent *ent) { if (le16_to_cpu(ent->lde_reclen) == 0) { return lu_dirent_calc_size(le16_to_cpu(ent->lde_namelen), @@ -1067,7 +1067,7 @@ struct lustre_handle { #define DEAD_HANDLE_MAGIC 0xdeadbeefcafebabeULL -static inline int lustre_handle_is_used(struct lustre_handle *lh) +static inline int lustre_handle_is_used(const struct lustre_handle *lh) { return lh->cookie != 0ull; } @@ -1079,7 +1079,7 @@ static inline int lustre_handle_equal(const struct lustre_handle *lh1, } static inline void lustre_handle_copy(struct lustre_handle *tgt, - struct lustre_handle *src) + const struct lustre_handle *src) { tgt->cookie = src->cookie; } @@ -1570,25 +1570,25 @@ static inline void lmm_oi_set_id(struct ost_id *oi, __u64 oid) oi->oi.oi_id = oid; } -static inline __u64 lmm_oi_id(struct ost_id *oi) +static inline __u64 lmm_oi_id(const struct ost_id *oi) { return oi->oi.oi_id; } -static inline __u64 lmm_oi_seq(struct ost_id *oi) +static inline __u64 lmm_oi_seq(const struct ost_id *oi) { return oi->oi.oi_seq; } static inline void lmm_oi_le_to_cpu(struct ost_id *dst_oi, - struct ost_id *src_oi) + const struct ost_id *src_oi) { dst_oi->oi.oi_id = le64_to_cpu(src_oi->oi.oi_id); dst_oi->oi.oi_seq = le64_to_cpu(src_oi->oi.oi_seq); } static inline void lmm_oi_cpu_to_le(struct ost_id *dst_oi, - struct ost_id *src_oi) + const struct ost_id *src_oi) { dst_oi->oi.oi_id = cpu_to_le64(src_oi->oi.oi_id); dst_oi->oi.oi_seq = cpu_to_le64(src_oi->oi.oi_seq); @@ -2724,15 +2724,15 @@ struct ldlm_extent { #define LDLM_GID_ANY ((__u64)-1) -static inline int ldlm_extent_overlap(struct ldlm_extent *ex1, - struct ldlm_extent *ex2) +static inline int ldlm_extent_overlap(const struct ldlm_extent *ex1, + const struct ldlm_extent *ex2) { return (ex1->start <= ex2->end) && (ex2->start <= ex1->end); } /* check if @ex1 contains @ex2 */ -static inline int ldlm_extent_contain(struct ldlm_extent *ex1, - struct ldlm_extent *ex2) +static inline int ldlm_extent_contain(const struct ldlm_extent *ex1, + const struct ldlm_extent *ex2) { return (ex1->start <= ex2->start) && (ex1->end >= ex2->end); } @@ -3092,7 +3092,7 @@ enum agent_req_status { ARS_SUCCEED, }; -static inline char *agent_req_status2name(enum agent_req_status ars) +static inline const char *agent_req_status2name(const enum agent_req_status ars) { switch (ars) { case ARS_WAITING: @@ -3268,7 +3268,7 @@ struct obdo { #define o_cksum o_nlink #define o_grant_used o_data_version -static inline void lustre_set_wire_obdo(struct obd_connect_data *ocd, +static inline void lustre_set_wire_obdo(const struct obd_connect_data *ocd, struct obdo *wobdo, const struct obdo *lobdo) { @@ -3287,7 +3287,7 @@ static inline void lustre_set_wire_obdo(struct obd_connect_data *ocd, } } -static inline void lustre_get_wire_obdo(struct obd_connect_data *ocd, +static inline void lustre_get_wire_obdo(const struct obd_connect_data *ocd, struct obdo *lobdo, const struct obdo *wobdo) { diff --git a/drivers/staging/lustre/lustre/include/lustre_fid.h b/drivers/staging/lustre/lustre/include/lustre_fid.h index 61f3930..a85183b 100644 --- a/drivers/staging/lustre/lustre/include/lustre_fid.h +++ b/drivers/staging/lustre/lustre/include/lustre_fid.h @@ -483,7 +483,7 @@ fid_build_pdo_res_name(const struct lu_fid *fid, unsigned int hash, * res will be built from normal FID directly, i.e. res[0] = f_seq, * res[1] = f_oid + f_ver. */ -static inline void ostid_build_res_name(struct ost_id *oi, +static inline void ostid_build_res_name(const struct ost_id *oi, struct ldlm_res_id *name) { memset(name, 0, sizeof(*name)); @@ -498,8 +498,8 @@ static inline void ostid_build_res_name(struct ost_id *oi, /** * Return true if the resource is for the object identified by this id & group. */ -static inline int ostid_res_name_eq(struct ost_id *oi, - struct ldlm_res_id *name) +static inline int ostid_res_name_eq(const struct ost_id *oi, + const struct ldlm_res_id *name) { /* Note: it is just a trick here to save some effort, probably the * correct way would be turn them into the FID and compare @@ -610,7 +610,8 @@ static inline __u32 fid_flatten32(const struct lu_fid *fid) return ino ? ino : fid_oid(fid); } -static inline int lu_fid_diff(struct lu_fid *fid1, struct lu_fid *fid2) +static inline int lu_fid_diff(const struct lu_fid *fid1, + const struct lu_fid *fid2) { LASSERTF(fid_seq(fid1) == fid_seq(fid2), "fid1:"DFID", fid2:"DFID"\n", PFID(fid1), PFID(fid2)); -- cgit v0.10.2 From d8f183b31341a97e07f5a3cd44499ea19a563ed1 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Tue, 16 Aug 2016 16:18:39 -0400 Subject: staging: lustre: use bool for several function in lustre_idl.h/lustre_fid.h Change the return type of several predicate functions from int to bool. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2675 Reviewed-on: http://review.whamcloud.com/8641 Reviewed-by: wangdi <di.wang@intel.com> Reviewed-by: Fan Yong <fan.yong@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index c932e20..d3a9db9 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -196,12 +196,12 @@ static inline unsigned fld_range_type(const struct lu_seq_range *range) return range->lsr_flags & LU_SEQ_RANGE_MASK; } -static inline int fld_range_is_ost(const struct lu_seq_range *range) +static inline bool fld_range_is_ost(const struct lu_seq_range *range) { return fld_range_type(range) == LU_SEQ_RANGE_OST; } -static inline int fld_range_is_mdt(const struct lu_seq_range *range) +static inline bool fld_range_is_mdt(const struct lu_seq_range *range) { return fld_range_type(range) == LU_SEQ_RANGE_MDT; } @@ -260,23 +260,23 @@ static inline void range_init(struct lu_seq_range *range) * check if given seq id \a s is within given range \a r */ -static inline int range_within(const struct lu_seq_range *range, - __u64 s) +static inline bool range_within(const struct lu_seq_range *range, + __u64 s) { return s >= range->lsr_start && s < range->lsr_end; } -static inline int range_is_sane(const struct lu_seq_range *range) +static inline bool range_is_sane(const struct lu_seq_range *range) { return (range->lsr_end >= range->lsr_start); } -static inline int range_is_zero(const struct lu_seq_range *range) +static inline bool range_is_zero(const struct lu_seq_range *range) { return (range->lsr_start == 0 && range->lsr_end == 0); } -static inline int range_is_exhausted(const struct lu_seq_range *range) +static inline bool range_is_exhausted(const struct lu_seq_range *range) { return range_space(range) == 0; @@ -437,69 +437,69 @@ enum dot_lustre_oid { FID_OID_DOT_LUSTRE_OBF = 2UL, }; -static inline int fid_seq_is_mdt0(__u64 seq) +static inline bool fid_seq_is_mdt0(__u64 seq) { return (seq == FID_SEQ_OST_MDT0); } -static inline int fid_seq_is_mdt(__u64 seq) +static inline bool fid_seq_is_mdt(__u64 seq) { return seq == FID_SEQ_OST_MDT0 || seq >= FID_SEQ_NORMAL; }; -static inline int fid_seq_is_echo(__u64 seq) +static inline bool fid_seq_is_echo(__u64 seq) { return (seq == FID_SEQ_ECHO); } -static inline int fid_is_echo(const struct lu_fid *fid) +static inline bool fid_is_echo(const struct lu_fid *fid) { return fid_seq_is_echo(fid_seq(fid)); } -static inline int fid_seq_is_llog(__u64 seq) +static inline bool fid_seq_is_llog(__u64 seq) { return (seq == FID_SEQ_LLOG); } -static inline int fid_is_llog(const struct lu_fid *fid) +static inline bool fid_is_llog(const struct lu_fid *fid) { /* file with OID == 0 is not llog but contains last oid */ return fid_seq_is_llog(fid_seq(fid)) && fid_oid(fid) > 0; } -static inline int fid_seq_is_rsvd(__u64 seq) +static inline bool fid_seq_is_rsvd(__u64 seq) { return (seq > FID_SEQ_OST_MDT0 && seq <= FID_SEQ_RSVD); }; -static inline int fid_seq_is_special(__u64 seq) +static inline bool fid_seq_is_special(__u64 seq) { return seq == FID_SEQ_SPECIAL; }; -static inline int fid_seq_is_local_file(__u64 seq) +static inline bool fid_seq_is_local_file(__u64 seq) { return seq == FID_SEQ_LOCAL_FILE || seq == FID_SEQ_LOCAL_NAME; }; -static inline int fid_seq_is_root(__u64 seq) +static inline bool fid_seq_is_root(__u64 seq) { return seq == FID_SEQ_ROOT; } -static inline int fid_seq_is_dot(__u64 seq) +static inline bool fid_seq_is_dot(__u64 seq) { return seq == FID_SEQ_DOT_LUSTRE; } -static inline int fid_seq_is_default(__u64 seq) +static inline bool fid_seq_is_default(__u64 seq) { return seq == FID_SEQ_LOV_DEFAULT; } -static inline int fid_is_mdt0(const struct lu_fid *fid) +static inline bool fid_is_mdt0(const struct lu_fid *fid) { return fid_seq_is_mdt0(fid_seq(fid)); } @@ -516,12 +516,12 @@ static inline void lu_root_fid(struct lu_fid *fid) * \param fid the fid to be tested. * \return true if the fid is a igif; otherwise false. */ -static inline int fid_seq_is_igif(__u64 seq) +static inline bool fid_seq_is_igif(__u64 seq) { return seq >= FID_SEQ_IGIF && seq <= FID_SEQ_IGIF_MAX; } -static inline int fid_is_igif(const struct lu_fid *fid) +static inline bool fid_is_igif(const struct lu_fid *fid) { return fid_seq_is_igif(fid_seq(fid)); } @@ -531,27 +531,27 @@ static inline int fid_is_igif(const struct lu_fid *fid) * \param fid the fid to be tested. * \return true if the fid is a idif; otherwise false. */ -static inline int fid_seq_is_idif(__u64 seq) +static inline bool fid_seq_is_idif(__u64 seq) { return seq >= FID_SEQ_IDIF && seq <= FID_SEQ_IDIF_MAX; } -static inline int fid_is_idif(const struct lu_fid *fid) +static inline bool fid_is_idif(const struct lu_fid *fid) { return fid_seq_is_idif(fid_seq(fid)); } -static inline int fid_is_local_file(const struct lu_fid *fid) +static inline bool fid_is_local_file(const struct lu_fid *fid) { return fid_seq_is_local_file(fid_seq(fid)); } -static inline int fid_seq_is_norm(__u64 seq) +static inline bool fid_seq_is_norm(__u64 seq) { return (seq >= FID_SEQ_NORMAL); } -static inline int fid_is_norm(const struct lu_fid *fid) +static inline bool fid_is_norm(const struct lu_fid *fid) { return fid_seq_is_norm(fid_seq(fid)); } @@ -769,7 +769,7 @@ static inline int fid_to_ostid(const struct lu_fid *fid, struct ost_id *ostid) } /* Check whether the fid is for LAST_ID */ -static inline int fid_is_last_id(const struct lu_fid *fid) +static inline bool fid_is_last_id(const struct lu_fid *fid) { return (fid_oid(fid) == 0); } @@ -838,7 +838,7 @@ static inline void fid_be_to_cpu(struct lu_fid *dst, const struct lu_fid *src) dst->f_ver = be32_to_cpu(fid_ver(src)); } -static inline int fid_is_sane(const struct lu_fid *fid) +static inline bool fid_is_sane(const struct lu_fid *fid) { return fid && ((fid_seq(fid) >= FID_SEQ_START && fid_ver(fid) == 0) || @@ -846,7 +846,7 @@ static inline int fid_is_sane(const struct lu_fid *fid) fid_seq_is_rsvd(fid_seq(fid))); } -static inline int fid_is_zero(const struct lu_fid *fid) +static inline bool fid_is_zero(const struct lu_fid *fid) { return fid_seq(fid) == 0 && fid_oid(fid) == 0; } @@ -854,7 +854,7 @@ static inline int fid_is_zero(const struct lu_fid *fid) void lustre_swab_lu_fid(struct lu_fid *fid); void lustre_swab_lu_seq_range(struct lu_seq_range *range); -static inline int lu_fid_eq(const struct lu_fid *f0, const struct lu_fid *f1) +static inline bool lu_fid_eq(const struct lu_fid *f0, const struct lu_fid *f1) { return memcmp(f0, f1, sizeof(*f0)) == 0; } @@ -1067,13 +1067,13 @@ struct lustre_handle { #define DEAD_HANDLE_MAGIC 0xdeadbeefcafebabeULL -static inline int lustre_handle_is_used(const struct lustre_handle *lh) +static inline bool lustre_handle_is_used(const struct lustre_handle *lh) { return lh->cookie != 0ull; } -static inline int lustre_handle_equal(const struct lustre_handle *lh1, - const struct lustre_handle *lh2) +static inline bool lustre_handle_equal(const struct lustre_handle *lh1, + const struct lustre_handle *lh2) { return lh1->cookie == lh2->cookie; } @@ -2684,8 +2684,8 @@ struct ldlm_res_id { #define PLDLMRES(res) (res)->lr_name.name[0], (res)->lr_name.name[1], \ (res)->lr_name.name[2], (res)->lr_name.name[3] -static inline int ldlm_res_eq(const struct ldlm_res_id *res0, - const struct ldlm_res_id *res1) +static inline bool ldlm_res_eq(const struct ldlm_res_id *res0, + const struct ldlm_res_id *res1) { return !memcmp(res0, res1, sizeof(*res0)); } diff --git a/drivers/staging/lustre/lustre/include/lustre_fid.h b/drivers/staging/lustre/lustre/include/lustre_fid.h index a85183b..6f7dc15 100644 --- a/drivers/staging/lustre/lustre/include/lustre_fid.h +++ b/drivers/staging/lustre/lustre/include/lustre_fid.h @@ -406,8 +406,8 @@ fid_build_reg_res_name(const struct lu_fid *fid, struct ldlm_res_id *res) /* * Return true if resource is for object identified by FID. */ -static inline int fid_res_name_eq(const struct lu_fid *fid, - const struct ldlm_res_id *res) +static inline bool fid_res_name_eq(const struct lu_fid *fid, + const struct ldlm_res_id *res) { return res->name[LUSTRE_RES_ID_SEQ_OFF] == fid_seq(fid) && res->name[LUSTRE_RES_ID_VER_OID_OFF] == fid_ver_oid(fid); -- cgit v0.10.2 From 5ec35d4538891c97ebfdb7f1a5db8984306aa310 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Tue, 16 Aug 2016 16:18:40 -0400 Subject: staging: lustre: simplify inline functions in lustre_fid.h Several inline functions return a structure that was passed in. Their is no need for this so just make these function void. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2675 Reviewed-on: http://review.whamcloud.com/8641 Reviewed-by: wangdi <di.wang@intel.com> Reviewed-by: Fan Yong <fan.yong@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre_fid.h b/drivers/staging/lustre/lustre/include/lustre_fid.h index 6f7dc15..f1d5bbd 100644 --- a/drivers/staging/lustre/lustre/include/lustre_fid.h +++ b/drivers/staging/lustre/lustre/include/lustre_fid.h @@ -393,14 +393,12 @@ struct ldlm_namespace; * but was moved into name[1] along with the OID to avoid consuming the * renaming name[2,3] fields that need to be used for the quota identifier. */ -static inline struct ldlm_res_id * +static inline void fid_build_reg_res_name(const struct lu_fid *fid, struct ldlm_res_id *res) { memset(res, 0, sizeof(*res)); res->name[LUSTRE_RES_ID_SEQ_OFF] = fid_seq(fid); res->name[LUSTRE_RES_ID_VER_OID_OFF] = fid_ver_oid(fid); - - return res; } /* @@ -416,29 +414,25 @@ static inline bool fid_res_name_eq(const struct lu_fid *fid, /* * Extract FID from LDLM resource. Reverse of fid_build_reg_res_name(). */ -static inline struct lu_fid * +static inline void fid_extract_from_res_name(struct lu_fid *fid, const struct ldlm_res_id *res) { fid->f_seq = res->name[LUSTRE_RES_ID_SEQ_OFF]; fid->f_oid = (__u32)(res->name[LUSTRE_RES_ID_VER_OID_OFF]); fid->f_ver = (__u32)(res->name[LUSTRE_RES_ID_VER_OID_OFF] >> 32); LASSERT(fid_res_name_eq(fid, res)); - - return fid; } /* * Build (DLM) resource identifier from global quota FID and quota ID. */ -static inline struct ldlm_res_id * +static inline void fid_build_quota_res_name(const struct lu_fid *glb_fid, union lquota_id *qid, struct ldlm_res_id *res) { fid_build_reg_res_name(glb_fid, res); res->name[LUSTRE_RES_ID_QUOTA_SEQ_OFF] = fid_seq(&qid->qid_fid); res->name[LUSTRE_RES_ID_QUOTA_VER_OID_OFF] = fid_ver_oid(&qid->qid_fid); - - return res; } /* @@ -455,14 +449,12 @@ static inline void fid_extract_from_quota_res(struct lu_fid *glb_fid, (__u32)(res->name[LUSTRE_RES_ID_QUOTA_VER_OID_OFF] >> 32); } -static inline struct ldlm_res_id * +static inline void fid_build_pdo_res_name(const struct lu_fid *fid, unsigned int hash, struct ldlm_res_id *res) { fid_build_reg_res_name(fid, res); res->name[LUSTRE_RES_ID_HSH_OFF] = hash; - - return res; } /** -- cgit v0.10.2 From 5e01c959b1ecf7d8bfa16d53ed2e010dd087c097 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Tue, 16 Aug 2016 16:18:41 -0400 Subject: staging: lustre: lmv: access lum_stripe_offset as little endian By the time that a struct lmv_user_md reaches lmv_placement_policy() it has already been converted to little endian. Therefore use the appropriate macros around accesses to this this field. This issue was found by rewriting the definition of struct lmv_user_md to use the __leXX typedefs and running sparse. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4738 Reviewed-on: http://review.whamcloud.com/9671 Reviewed-by: Dmitry Eremin <dmitry.eremin@intel.com> Reviewed-by: Swapnil Pimpale <spimpale@ddn.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index c005a66..5929994 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -1242,15 +1242,15 @@ static int lmv_placement_policy(struct obd_device *obd, struct lmv_user_md *lum; lum = op_data->op_data; - if (lum->lum_stripe_offset != (__u32)-1) { - *mds = lum->lum_stripe_offset; + if (le32_to_cpu(lum->lum_stripe_offset) != (__u32)-1) { + *mds = le32_to_cpu(lum->lum_stripe_offset); } else { /* * -1 means default, which will be in the same MDT with * the stripe */ *mds = op_data->op_mds; - lum->lum_stripe_offset = op_data->op_mds; + lum->lum_stripe_offset = cpu_to_le32(op_data->op_mds); } } else { /* -- cgit v0.10.2 From 32410f3e168b025f84cb3ab94252887d82e6e3ae Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Tue, 16 Aug 2016 16:18:42 -0400 Subject: staging: lustre: lmv: lookup remote migrating object in LMV If remote object is being found in a migrating directory, it should continue to lookup the object in remote MDT, instead of return. Signed-off-by: wang di <di.wang@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4805 Reviewed-on: http://review.whamcloud.com/9806 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Nathaniel Clark <nathaniel.l.clark@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/lmv/lmv_intent.c b/drivers/staging/lustre/lustre/lmv/lmv_intent.c index 51b7048..a38d343 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_intent.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_intent.c @@ -471,7 +471,6 @@ static int lmv_intent_lookup(struct obd_export *exp, it->it_disposition &= ~DISP_ENQ_COMPLETE; rc = md_intent_lock(tgt->ltd_exp, op_data, lmm, lmmsize, it, flags, reqp, cb_blocking, extra_lock_flags); - return rc; } /* -- cgit v0.10.2 From 9b58714f9ab4138dabcf7176fdc465bd00afeae9 Mon Sep 17 00:00:00 2001 From: Nathaniel Clark <nathaniel.l.clark@intel.com> Date: Tue, 16 Aug 2016 16:18:43 -0400 Subject: staging: lustre: lmv: Ensure lmv_intent_lookup cleans up reqp Ensure there aren't invalid pointers hanging around after ptlrpc_req_finished is called. Signed-off-by: Nathaniel Clark <nathaniel.l.clark@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4826 Reviewed-on: http://review.whamcloud.com/9841 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Bob Glossman <bob.glossman@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/lmv/lmv_intent.c b/drivers/staging/lustre/lustre/lmv/lmv_intent.c index a38d343..d7e165f 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_intent.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_intent.c @@ -464,6 +464,9 @@ static int lmv_intent_lookup(struct obd_export *exp, return PTR_ERR(tgt); ptlrpc_req_finished(*reqp); + it->it_request = NULL; + *reqp = NULL; + CDEBUG(D_INODE, "For migrating dir, try target dir "DFID"\n", PFID(&lsm->lsm_md_oinfo[1].lmo_fid)); -- cgit v0.10.2 From 91196c20a37bb5990e4358ff97dbeb2bd3007154 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong <jinshan.xiong@intel.com> Date: Tue, 16 Aug 2016 16:18:44 -0400 Subject: staging: lustre: llite: avoid a deadlock in page write For a partial page write, it will have to issue a READ RPC firstly to get a full uptodate page. If another page is already locked by this thread it can easily cause deadlock. Signed-off-by: Jinshan Xiong <jinshan.xiong@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4873 Reviewed-on: http://review.whamcloud.com/9928 Reviewed-by: Bobi Jam <bobijam@gmail.com> Reviewed-by: Niu Yawei <yawei.niu@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c index d98c7ac..c14a1b6 100644 --- a/drivers/staging/lustre/lustre/llite/rw26.c +++ b/drivers/staging/lustre/lustre/llite/rw26.c @@ -506,8 +506,9 @@ static int ll_write_begin(struct file *file, struct address_space *mapping, env = lcc->lcc_env; io = lcc->lcc_io; - /* To avoid deadlock, try to lock page first. */ - vmpage = grab_cache_page_nowait(mapping, index); + if (likely(to == PAGE_SIZE)) /* LU-4873 */ + /* To avoid deadlock, try to lock page first. */ + vmpage = grab_cache_page_nowait(mapping, index); if (unlikely(!vmpage || PageDirty(vmpage) || PageWriteback(vmpage))) { struct vvp_io *vio = vvp_env_io(env); struct cl_page_list *plist = &vio->u.write.vui_queue; -- cgit v0.10.2 From 87ffe02c20b2fa302f22754a28f530ab54eadac6 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong <jinshan.xiong@intel.com> Date: Tue, 16 Aug 2016 16:18:45 -0400 Subject: staging: lustre: lov: handle the case of stripe size is not power 2 Calculate the end of current stripe correctly when the stripe size is not power 2. Signed-off-by: Jinshan Xiong <jinshan.xiong@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4860 Reviewed-on: http://review.whamcloud.com/9882 Reviewed-by: Bobi Jam <bobijam@gmail.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/lov/lov_page.c b/drivers/staging/lustre/lustre/lov/lov_page.c index c17026f..45b5ae9 100644 --- a/drivers/staging/lustre/lustre/lov/lov_page.c +++ b/drivers/staging/lustre/lustre/lov/lov_page.c @@ -65,7 +65,9 @@ static int lov_raid0_page_is_under_lock(const struct lu_env *env, pgoff_t index = *max_index; unsigned int pps; /* pages per stripe */ - CDEBUG(D_READA, "*max_index = %lu, nr = %d\n", index, r0->lo_nr); + CDEBUG(D_READA, DFID "*max_index = %lu, nr = %d\n", + PFID(lu_object_fid(lov2lu(loo))), index, r0->lo_nr); + if (index == 0) /* the page is not covered by any lock */ return 0; @@ -80,7 +82,12 @@ static int lov_raid0_page_is_under_lock(const struct lu_env *env, /* calculate the end of current stripe */ pps = loo->lo_lsm->lsm_stripe_size >> PAGE_SHIFT; - index = ((slice->cpl_index + pps) & ~(pps - 1)) - 1; + index = slice->cpl_index + pps - slice->cpl_index % pps - 1; + + CDEBUG(D_READA, DFID "*max_index = %lu, index = %lu, pps = %u, stripe_size = %u, stripe no = %u, page index = %lu\n", + PFID(lu_object_fid(lov2lu(loo))), *max_index, index, pps, + loo->lo_lsm->lsm_stripe_size, lov_page_stripe(slice->cpl_page), + slice->cpl_index); /* never exceed the end of the stripe */ *max_index = min_t(pgoff_t, *max_index, index); -- cgit v0.10.2 From 29a85e250e791762d749024002957ef28e3c4ad5 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Tue, 16 Aug 2016 16:18:46 -0400 Subject: staging: lustre: lmv: cleanup req in lmv_getattr_name() In lmv_getattr_name() don't return a freed request in the error path. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4826 Reviewed-on: http://review.whamcloud.com/9863 Reviewed-by: Nathaniel Clark <nathaniel.l.clark@intel.com> Reviewed-by: Bob Glossman <bob.glossman@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 5929994..f1b8ae9 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -1920,6 +1920,7 @@ lmv_getattr_name(struct obd_export *exp, struct md_op_data *op_data, tgt = lmv_find_target(lmv, &rid); if (IS_ERR(tgt)) { ptlrpc_req_finished(*request); + *request = NULL; return PTR_ERR(tgt); } -- cgit v0.10.2 From 9ef3754cc257216db515b4830f64413af7160a4e Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Tue, 16 Aug 2016 16:18:47 -0400 Subject: staging: lustre: lmv: rename request to preq in lmv_getattr_name() Rename request to preq. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4826 Reviewed-on: http://review.whamcloud.com/9863 Reviewed-by: Nathaniel Clark <nathaniel.l.clark@intel.com> Reviewed-by: Bob Glossman <bob.glossman@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index f1b8ae9..d07fd17 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -1883,7 +1883,7 @@ lmv_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo, static int lmv_getattr_name(struct obd_export *exp, struct md_op_data *op_data, - struct ptlrpc_request **request) + struct ptlrpc_request **preq) { struct ptlrpc_request *req = NULL; struct obd_device *obd = exp->exp_obd; @@ -1904,13 +1904,11 @@ lmv_getattr_name(struct obd_export *exp, struct md_op_data *op_data, op_data->op_namelen, op_data->op_name, PFID(&op_data->op_fid1), tgt->ltd_idx); - rc = md_getattr_name(tgt->ltd_exp, op_data, request); + rc = md_getattr_name(tgt->ltd_exp, op_data, preq); if (rc != 0) return rc; - body = req_capsule_server_get(&(*request)->rq_pill, - &RMF_MDT_BODY); - + body = req_capsule_server_get(&(*preq)->rq_pill, &RMF_MDT_BODY); if (body->valid & OBD_MD_MDS) { struct lu_fid rid = body->fid1; @@ -1919,8 +1917,8 @@ lmv_getattr_name(struct obd_export *exp, struct md_op_data *op_data, tgt = lmv_find_target(lmv, &rid); if (IS_ERR(tgt)) { - ptlrpc_req_finished(*request); - *request = NULL; + ptlrpc_req_finished(*preq); + *preq = NULL; return PTR_ERR(tgt); } @@ -1929,8 +1927,8 @@ lmv_getattr_name(struct obd_export *exp, struct md_op_data *op_data, op_data->op_namelen = 0; op_data->op_name = NULL; rc = md_getattr_name(tgt->ltd_exp, op_data, &req); - ptlrpc_req_finished(*request); - *request = req; + ptlrpc_req_finished(*preq); + *preq = req; } return rc; -- cgit v0.10.2 From 1d5d5ec110113ce3a3a41adfc183a9e120240bd7 Mon Sep 17 00:00:00 2001 From: Fan Yong <fan.yong@intel.com> Date: Tue, 16 Aug 2016 16:18:48 -0400 Subject: staging: lustre: obdclass: unified flow control interfaces Unify the flow control interfaces for MDC RPC and FLD RPC. We allow to adjust the maximum inflight RPCs count via /sys interface. Signed-off-by: Fan Yong <fan.yong@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4687 Reviewed-on: http://review.whamcloud.com/9562 Reviewed-by: Niu Yawei <yawei.niu@intel.com> Reviewed-by: Alex Zhuravlev <alexey.zhuravlev@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/fld/fld_request.c b/drivers/staging/lustre/lustre/fld/fld_request.c index e59d626..ed7962e 100644 --- a/drivers/staging/lustre/lustre/fld/fld_request.c +++ b/drivers/staging/lustre/lustre/fld/fld_request.c @@ -53,57 +53,6 @@ #include "../include/lustre_mdc.h" #include "fld_internal.h" -/* TODO: these 3 functions are copies of flow-control code from mdc_lib.c - * It should be common thing. The same about mdc RPC lock - */ -static int fld_req_avail(struct client_obd *cli, struct mdc_cache_waiter *mcw) -{ - int rc; - - spin_lock(&cli->cl_loi_list_lock); - rc = list_empty(&mcw->mcw_entry); - spin_unlock(&cli->cl_loi_list_lock); - return rc; -}; - -static void fld_enter_request(struct client_obd *cli) -{ - struct mdc_cache_waiter mcw; - struct l_wait_info lwi = { 0 }; - - spin_lock(&cli->cl_loi_list_lock); - if (cli->cl_r_in_flight >= cli->cl_max_rpcs_in_flight) { - list_add_tail(&mcw.mcw_entry, &cli->cl_cache_waiters); - init_waitqueue_head(&mcw.mcw_waitq); - spin_unlock(&cli->cl_loi_list_lock); - l_wait_event(mcw.mcw_waitq, fld_req_avail(cli, &mcw), &lwi); - } else { - cli->cl_r_in_flight++; - spin_unlock(&cli->cl_loi_list_lock); - } -} - -static void fld_exit_request(struct client_obd *cli) -{ - struct list_head *l, *tmp; - struct mdc_cache_waiter *mcw; - - spin_lock(&cli->cl_loi_list_lock); - cli->cl_r_in_flight--; - list_for_each_safe(l, tmp, &cli->cl_cache_waiters) { - if (cli->cl_r_in_flight >= cli->cl_max_rpcs_in_flight) { - /* No free request slots anymore */ - break; - } - - mcw = list_entry(l, struct mdc_cache_waiter, mcw_entry); - list_del_init(&mcw->mcw_entry); - cli->cl_r_in_flight++; - wake_up(&mcw->mcw_waitq); - } - spin_unlock(&cli->cl_loi_list_lock); -} - static int fld_rrb_hash(struct lu_client_fld *fld, u64 seq) { LASSERT(fld->lcf_count > 0); @@ -439,9 +388,9 @@ int fld_client_rpc(struct obd_export *exp, req->rq_reply_portal = MDC_REPLY_PORTAL; ptlrpc_at_set_req_timeout(req); - fld_enter_request(&exp->exp_obd->u.cli); + obd_get_request_slot(&exp->exp_obd->u.cli); rc = ptlrpc_queue_wait(req); - fld_exit_request(&exp->exp_obd->u.cli); + obd_put_request_slot(&exp->exp_obd->u.cli); if (rc) goto out_req; diff --git a/drivers/staging/lustre/lustre/include/lustre_mdc.h b/drivers/staging/lustre/lustre/include/lustre_mdc.h index 0a8c639..bf6f87a 100644 --- a/drivers/staging/lustre/lustre/include/lustre_mdc.h +++ b/drivers/staging/lustre/lustre/include/lustre_mdc.h @@ -179,11 +179,6 @@ static inline void mdc_update_max_ea_from_body(struct obd_export *exp, } } -struct mdc_cache_waiter { - struct list_head mcw_entry; - wait_queue_head_t mcw_waitq; -}; - /* mdc/mdc_locks.c */ int it_open_error(int phase, struct lookup_intent *it); diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index f5eeb05..cacd472 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -211,11 +211,12 @@ struct timeout_item { struct list_head ti_chain; }; -#define OSC_MAX_RIF_DEFAULT 8 -#define OSC_MAX_RIF_MAX 256 -#define OSC_MAX_DIRTY_DEFAULT (OSC_MAX_RIF_DEFAULT * 4) -#define OSC_MAX_DIRTY_MB_MAX 2048 /* arbitrary, but < MAX_LONG bytes */ -#define OSC_DEFAULT_RESENDS 10 +#define OBD_MAX_RIF_DEFAULT 8 +#define OBD_MAX_RIF_MAX 512 +#define OSC_MAX_RIF_MAX 256 +#define OSC_MAX_DIRTY_DEFAULT (OBD_MAX_RIF_DEFAULT * 4) +#define OSC_MAX_DIRTY_MB_MAX 2048 /* arbitrary, but < MAX_LONG bytes */ +#define OSC_DEFAULT_RESENDS 10 /* possible values for fo_sync_lock_cancel */ enum { @@ -225,9 +226,6 @@ enum { NUM_SYNC_ON_CANCEL_STATES }; -#define MDC_MAX_RIF_DEFAULT 8 -#define MDC_MAX_RIF_MAX 512 - enum obd_cl_sem_lock_class { OBD_CLI_SEM_NORMAL, OBD_CLI_SEM_MGC, diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index 2f111a8..de808ee 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -97,6 +97,11 @@ int obd_zombie_impexp_init(void); void obd_zombie_impexp_stop(void); void obd_zombie_barrier(void); +int obd_get_request_slot(struct client_obd *cli); +void obd_put_request_slot(struct client_obd *cli); +__u32 obd_get_max_rpcs_in_flight(struct client_obd *cli); +int obd_set_max_rpcs_in_flight(struct client_obd *cli, __u32 max); + struct llog_handle; struct llog_rec_hdr; typedef int (*llog_cb_t)(const struct lu_env *, struct llog_handle *, diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c index 7c832aa..ee40006 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c @@ -360,7 +360,7 @@ int client_obd_setup(struct obd_device *obddev, struct lustre_cfg *lcfg) cli->cl_chunkbits = PAGE_SHIFT; if (!strcmp(name, LUSTRE_MDC_NAME)) { - cli->cl_max_rpcs_in_flight = MDC_MAX_RIF_DEFAULT; + cli->cl_max_rpcs_in_flight = OBD_MAX_RIF_DEFAULT; } else if (totalram_pages >> (20 - PAGE_SHIFT) <= 128 /* MB */) { cli->cl_max_rpcs_in_flight = 2; } else if (totalram_pages >> (20 - PAGE_SHIFT) <= 256 /* MB */) { @@ -368,7 +368,7 @@ int client_obd_setup(struct obd_device *obddev, struct lustre_cfg *lcfg) } else if (totalram_pages >> (20 - PAGE_SHIFT) <= 512 /* MB */) { cli->cl_max_rpcs_in_flight = 4; } else { - cli->cl_max_rpcs_in_flight = OSC_MAX_RIF_DEFAULT; + cli->cl_max_rpcs_in_flight = OBD_MAX_RIF_DEFAULT; } rc = ldlm_get_ref(); if (rc) { diff --git a/drivers/staging/lustre/lustre/mdc/lproc_mdc.c b/drivers/staging/lustre/lustre/mdc/lproc_mdc.c index 98d15fb..fca9450 100644 --- a/drivers/staging/lustre/lustre/mdc/lproc_mdc.c +++ b/drivers/staging/lustre/lustre/mdc/lproc_mdc.c @@ -43,11 +43,10 @@ static ssize_t max_rpcs_in_flight_show(struct kobject *kobj, int len; struct obd_device *dev = container_of(kobj, struct obd_device, obd_kobj); - struct client_obd *cli = &dev->u.cli; + __u32 max; - spin_lock(&cli->cl_loi_list_lock); - len = sprintf(buf, "%u\n", cli->cl_max_rpcs_in_flight); - spin_unlock(&cli->cl_loi_list_lock); + max = obd_get_max_rpcs_in_flight(&dev->u.cli); + len = sprintf(buf, "%u\n", max); return len; } @@ -59,7 +58,6 @@ static ssize_t max_rpcs_in_flight_store(struct kobject *kobj, { struct obd_device *dev = container_of(kobj, struct obd_device, obd_kobj); - struct client_obd *cli = &dev->u.cli; int rc; unsigned long val; @@ -67,12 +65,9 @@ static ssize_t max_rpcs_in_flight_store(struct kobject *kobj, if (rc) return rc; - if (val < 1 || val > MDC_MAX_RIF_MAX) - return -ERANGE; - - spin_lock(&cli->cl_loi_list_lock); - cli->cl_max_rpcs_in_flight = val; - spin_unlock(&cli->cl_loi_list_lock); + rc = obd_set_max_rpcs_in_flight(&dev->u.cli, val); + if (rc) + count = rc; return count; } diff --git a/drivers/staging/lustre/lustre/mdc/mdc_internal.h b/drivers/staging/lustre/lustre/mdc/mdc_internal.h index 58f2841..53b4063 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_internal.h +++ b/drivers/staging/lustre/lustre/mdc/mdc_internal.h @@ -61,8 +61,6 @@ void mdc_link_pack(struct ptlrpc_request *req, struct md_op_data *op_data); void mdc_rename_pack(struct ptlrpc_request *req, struct md_op_data *op_data, const char *old, int oldlen, const char *new, int newlen); void mdc_close_pack(struct ptlrpc_request *req, struct md_op_data *op_data); -int mdc_enter_request(struct client_obd *cli); -void mdc_exit_request(struct client_obd *cli); /* mdc/mdc_locks.c */ int mdc_set_lock_data(struct obd_export *exp, diff --git a/drivers/staging/lustre/lustre/mdc/mdc_lib.c b/drivers/staging/lustre/lustre/mdc/mdc_lib.c index 95c4550..b532623 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_lib.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_lib.c @@ -484,67 +484,3 @@ void mdc_close_pack(struct ptlrpc_request *req, struct md_op_data *op_data) mdc_ioepoch_pack(epoch, op_data); mdc_hsm_release_pack(req, op_data); } - -static int mdc_req_avail(struct client_obd *cli, struct mdc_cache_waiter *mcw) -{ - int rc; - - spin_lock(&cli->cl_loi_list_lock); - rc = list_empty(&mcw->mcw_entry); - spin_unlock(&cli->cl_loi_list_lock); - return rc; -}; - -/* We record requests in flight in cli->cl_r_in_flight here. - * There is only one write rpc possible in mdc anyway. If this to change - * in the future - the code may need to be revisited. - */ -int mdc_enter_request(struct client_obd *cli) -{ - int rc = 0; - struct mdc_cache_waiter mcw; - struct l_wait_info lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL); - - spin_lock(&cli->cl_loi_list_lock); - if (cli->cl_r_in_flight >= cli->cl_max_rpcs_in_flight) { - list_add_tail(&mcw.mcw_entry, &cli->cl_cache_waiters); - init_waitqueue_head(&mcw.mcw_waitq); - spin_unlock(&cli->cl_loi_list_lock); - rc = l_wait_event(mcw.mcw_waitq, mdc_req_avail(cli, &mcw), - &lwi); - if (rc) { - spin_lock(&cli->cl_loi_list_lock); - if (list_empty(&mcw.mcw_entry)) - cli->cl_r_in_flight--; - list_del_init(&mcw.mcw_entry); - spin_unlock(&cli->cl_loi_list_lock); - } - } else { - cli->cl_r_in_flight++; - spin_unlock(&cli->cl_loi_list_lock); - } - return rc; -} - -void mdc_exit_request(struct client_obd *cli) -{ - struct list_head *l, *tmp; - struct mdc_cache_waiter *mcw; - - spin_lock(&cli->cl_loi_list_lock); - cli->cl_r_in_flight--; - list_for_each_safe(l, tmp, &cli->cl_cache_waiters) { - if (cli->cl_r_in_flight >= cli->cl_max_rpcs_in_flight) { - /* No free request slots anymore */ - break; - } - - mcw = list_entry(l, struct mdc_cache_waiter, mcw_entry); - list_del_init(&mcw->mcw_entry); - cli->cl_r_in_flight++; - wake_up(&mcw->mcw_waitq); - } - /* Empty waiting list? Decrease reqs in-flight number */ - - spin_unlock(&cli->cl_loi_list_lock); -} diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index 626fce5..d8406d5 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -809,7 +809,7 @@ resend: */ if (it) { mdc_get_rpc_lock(obddev->u.cli.cl_rpc_lock, it); - rc = mdc_enter_request(&obddev->u.cli); + rc = obd_get_request_slot(&obddev->u.cli); if (rc != 0) { mdc_put_rpc_lock(obddev->u.cli.cl_rpc_lock, it); mdc_clear_replay_flag(req, 0); @@ -837,7 +837,7 @@ resend: return rc; } - mdc_exit_request(&obddev->u.cli); + obd_put_request_slot(&obddev->u.cli); mdc_put_rpc_lock(obddev->u.cli.cl_rpc_lock, it); if (rc < 0) { @@ -1179,7 +1179,7 @@ static int mdc_intent_getattr_async_interpret(const struct lu_env *env, obddev = class_exp2obd(exp); - mdc_exit_request(&obddev->u.cli); + obd_put_request_slot(&obddev->u.cli); if (OBD_FAIL_CHECK(OBD_FAIL_MDC_GETATTR_ENQUEUE)) rc = -ETIMEDOUT; @@ -1239,7 +1239,7 @@ int mdc_intent_getattr_async(struct obd_export *exp, if (IS_ERR(req)) return PTR_ERR(req); - rc = mdc_enter_request(&obddev->u.cli); + rc = obd_get_request_slot(&obddev->u.cli); if (rc != 0) { ptlrpc_req_finished(req); return rc; @@ -1248,7 +1248,7 @@ int mdc_intent_getattr_async(struct obd_export *exp, rc = ldlm_cli_enqueue(exp, &req, einfo, &res_id, &policy, &flags, NULL, 0, LVB_T_NONE, &minfo->mi_lockh, 1); if (rc < 0) { - mdc_exit_request(&obddev->u.cli); + obd_put_request_slot(&obddev->u.cli); ptlrpc_req_finished(req); return rc; } diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 030295f..558f33b 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -58,16 +58,16 @@ static inline int mdc_queue_wait(struct ptlrpc_request *req) struct client_obd *cli = &req->rq_import->imp_obd->u.cli; int rc; - /* mdc_enter_request() ensures that this client has no more + /* obd_get_request_slot() ensures that this client has no more * than cl_max_rpcs_in_flight RPCs simultaneously inf light * against an MDT. */ - rc = mdc_enter_request(cli); + rc = obd_get_request_slot(cli); if (rc != 0) return rc; rc = ptlrpc_queue_wait(req); - mdc_exit_request(cli); + obd_put_request_slot(cli); return rc; } diff --git a/drivers/staging/lustre/lustre/obdclass/genops.c b/drivers/staging/lustre/lustre/obdclass/genops.c index 99c2da6..be25434 100644 --- a/drivers/staging/lustre/lustre/obdclass/genops.c +++ b/drivers/staging/lustre/lustre/obdclass/genops.c @@ -1312,3 +1312,135 @@ void obd_zombie_impexp_stop(void) obd_zombie_impexp_notify(); wait_for_completion(&obd_zombie_stop); } + +struct obd_request_slot_waiter { + struct list_head orsw_entry; + wait_queue_head_t orsw_waitq; + bool orsw_signaled; +}; + +static bool obd_request_slot_avail(struct client_obd *cli, + struct obd_request_slot_waiter *orsw) +{ + bool avail; + + spin_lock(&cli->cl_loi_list_lock); + avail = !!list_empty(&orsw->orsw_entry); + spin_unlock(&cli->cl_loi_list_lock); + + return avail; +}; + +/* + * For network flow control, the RPC sponsor needs to acquire a credit + * before sending the RPC. The credits count for a connection is defined + * by the "cl_max_rpcs_in_flight". If all the credits are occpuied, then + * the subsequent RPC sponsors need to wait until others released their + * credits, or the administrator increased the "cl_max_rpcs_in_flight". + */ +int obd_get_request_slot(struct client_obd *cli) +{ + struct obd_request_slot_waiter orsw; + struct l_wait_info lwi; + int rc; + + spin_lock(&cli->cl_loi_list_lock); + if (cli->cl_r_in_flight < cli->cl_max_rpcs_in_flight) { + cli->cl_r_in_flight++; + spin_unlock(&cli->cl_loi_list_lock); + return 0; + } + + init_waitqueue_head(&orsw.orsw_waitq); + list_add_tail(&orsw.orsw_entry, &cli->cl_loi_read_list); + orsw.orsw_signaled = false; + spin_unlock(&cli->cl_loi_list_lock); + + lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL); + rc = l_wait_event(orsw.orsw_waitq, + obd_request_slot_avail(cli, &orsw) || + orsw.orsw_signaled, + &lwi); + + /* + * Here, we must take the lock to avoid the on-stack 'orsw' to be + * freed but other (such as obd_put_request_slot) is using it. + */ + spin_lock(&cli->cl_loi_list_lock); + if (rc) { + if (!orsw.orsw_signaled) { + if (list_empty(&orsw.orsw_entry)) + cli->cl_r_in_flight--; + else + list_del(&orsw.orsw_entry); + } + } + + if (orsw.orsw_signaled) { + LASSERT(list_empty(&orsw.orsw_entry)); + + rc = -EINTR; + } + spin_unlock(&cli->cl_loi_list_lock); + + return rc; +} +EXPORT_SYMBOL(obd_get_request_slot); + +void obd_put_request_slot(struct client_obd *cli) +{ + struct obd_request_slot_waiter *orsw; + + spin_lock(&cli->cl_loi_list_lock); + cli->cl_r_in_flight--; + + /* If there is free slot, wakeup the first waiter. */ + if (!list_empty(&cli->cl_loi_read_list) && + likely(cli->cl_r_in_flight < cli->cl_max_rpcs_in_flight)) { + orsw = list_entry(cli->cl_loi_read_list.next, + struct obd_request_slot_waiter, orsw_entry); + list_del_init(&orsw->orsw_entry); + cli->cl_r_in_flight++; + wake_up(&orsw->orsw_waitq); + } + spin_unlock(&cli->cl_loi_list_lock); +} +EXPORT_SYMBOL(obd_put_request_slot); + +__u32 obd_get_max_rpcs_in_flight(struct client_obd *cli) +{ + return cli->cl_max_rpcs_in_flight; +} +EXPORT_SYMBOL(obd_get_max_rpcs_in_flight); + +int obd_set_max_rpcs_in_flight(struct client_obd *cli, __u32 max) +{ + struct obd_request_slot_waiter *orsw; + __u32 old; + int diff; + int i; + + if (max > OBD_MAX_RIF_MAX || max < 1) + return -ERANGE; + + spin_lock(&cli->cl_loi_list_lock); + old = cli->cl_max_rpcs_in_flight; + cli->cl_max_rpcs_in_flight = max; + diff = max - old; + + /* We increase the max_rpcs_in_flight, then wakeup some waiters. */ + for (i = 0; i < diff; i++) { + if (list_empty(&cli->cl_loi_read_list)) + break; + + orsw = list_entry(cli->cl_loi_read_list.next, + struct obd_request_slot_waiter, orsw_entry); + list_del_init(&orsw->orsw_entry); + cli->cl_r_in_flight++; + wake_up(&orsw->orsw_waitq); + } + spin_unlock(&cli->cl_loi_list_lock); + + return 0; +} +EXPORT_SYMBOL(obd_set_max_rpcs_in_flight); -- cgit v0.10.2 From afebe4a531c1a03a5da3033ffd8984208fdc520c Mon Sep 17 00:00:00 2001 From: Fan Yong <fan.yong@intel.com> Date: Tue, 16 Aug 2016 16:18:49 -0400 Subject: staging: lustre: reorder LOV_MAGIC_* definition Since all the LOV_MAGIC_* definitions have the same postfix values break that value out into its own definition. With this we can check whether the magic's postfix match the LOV_MAGIC_MAGIC or not: if yes, then it is quite possible that the clients has encountered an newer LOV magic. This extra information can let us handle those cases more gracefully. Signed-off-by: Fan Yong <fan.yong@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4941 Reviewed-on: http://review.whamcloud.com/10045 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index d3a9db9..3444add 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -1478,11 +1478,21 @@ enum obdo_flags { OBD_FL_LOCAL_MASK = 0xF0000000, }; -#define LOV_MAGIC_V1 0x0BD10BD0 -#define LOV_MAGIC LOV_MAGIC_V1 -#define LOV_MAGIC_JOIN_V1 0x0BD20BD0 -#define LOV_MAGIC_V3 0x0BD30BD0 -#define LOV_MAGIC_MIGRATE 0x0BD40BD0 +/* + * All LOV EA magics should have the same postfix, if some new version + * Lustre instroduces new LOV EA magic, then when down-grade to an old + * Lustre, even though the old version system does not recognizes such + * new magic, it still can distinguish the corrupted cases by checking + * the magic's postfix. + */ +#define LOV_MAGIC_MAGIC 0x0BD0 +#define LOV_MAGIC_MASK 0xFFFF + +#define LOV_MAGIC_V1 (0x0BD10000 | LOV_MAGIC_MAGIC) +#define LOV_MAGIC_JOIN_V1 (0x0BD20000 | LOV_MAGIC_MAGIC) +#define LOV_MAGIC_V3 (0x0BD30000 | LOV_MAGIC_MAGIC) +#define LOV_MAGIC_MIGRATE (0x0BD40000 | LOV_MAGIC_MAGIC) +#define LOV_MAGIC LOV_MAGIC_V1 /* * magic for fully defined striping -- cgit v0.10.2 From c68c3fa4368fcb16b0bbff0808a64012a2d86640 Mon Sep 17 00:00:00 2001 From: Vitaly Fertman <vitaly_fertman@xyratex.com> Date: Tue, 16 Aug 2016 16:18:50 -0400 Subject: staging: lustre: ldlm: flock completion fixes. Move checks for FAILED, DESTROYED flags under ldlm spinlock, destroy flock atomically with the check it is not destroyed yet. Do not put the granted flock into the resource if this is UNLOCK, TEST, or DEADLOCK'ed flock. Later a regression for this patch was reported under LU-7626. The refcount nonzero (1) after lock cleanup errors was reported. The reason is that the case LCK_NL was not handled for obdecho. Patch 17791 resolved this issue which has been combined into this upstream patch. Signed-off-by: Vitaly Fertman <vitaly_fertman@xyratex.com> Signed-off-by: Andriy Skulysh <andriy.skulysh@seagate.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2177 Reviewed-by: Alexey Lyashkov <alexey_lyashkov@xyratex.com> Reviewed-by: Andriy Skulysh <andriy_skulysh@xyratex.com> Reviewed-by: Vitaly Fertman <vitaly_fertman@xyratex.com> Xyratex-bug-id: MRP-1588 Reviewed-on: http://review.whamcloud.com/10005 Reviewed-by: Bobi Jam <bobijam@gmail.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-7626 Reviewed-by: Mirza Arshad Mirza Hussain <arshad.hussain@seagate.com> Reviewed-by: Alexey Leonidovich Lyashkov <alexey.lyashkov@seagate.com> Reviewed-on: http://review.whamcloud.com/17791 Reviewed-by: Niu Yawei <yawei.niu@intel.com> Reviewed-by: Alex Zhuravlev <alexey.zhuravlev@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_fail.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_fail.h index d3f9a60..bdbbe93 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_fail.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_fail.h @@ -143,6 +143,9 @@ static inline int cfs_fail_timeout_set(__u32 id, __u32 value, int ms, int set) #define CFS_FAIL_TIMEOUT_ORSET(id, value, secs) \ cfs_fail_timeout_set(id, value, secs * 1000, CFS_FAIL_LOC_ORSET) +#define CFS_FAIL_TIMEOUT_RESET(id, value, secs) \ + cfs_fail_timeout_set(id, value, secs * 1000, CFS_FAIL_LOC_RESET) + #define CFS_FAIL_TIMEOUT_MS_ORSET(id, value, ms) \ cfs_fail_timeout_set(id, value, ms, CFS_FAIL_LOC_ORSET) diff --git a/drivers/staging/lustre/lnet/libcfs/fail.c b/drivers/staging/lustre/lnet/libcfs/fail.c index 9288ee0..e4b1a0a 100644 --- a/drivers/staging/lustre/lnet/libcfs/fail.c +++ b/drivers/staging/lustre/lnet/libcfs/fail.c @@ -90,8 +90,10 @@ int __cfs_fail_check_set(__u32 id, __u32 value, int set) } } - if ((set == CFS_FAIL_LOC_ORSET || set == CFS_FAIL_LOC_RESET) && - (value & CFS_FAIL_ONCE)) + /* Take into account the current call for FAIL_ONCE for ORSET only, + * as RESET is a new fail_loc, it does not change the current call + */ + if ((set == CFS_FAIL_LOC_ORSET) && (value & CFS_FAIL_ONCE)) set_bit(CFS_FAIL_ONCE_BIT, &cfs_fail_loc); /* Lost race to set CFS_FAILED_BIT. */ if (test_and_set_bit(CFS_FAILED_BIT, &cfs_fail_loc)) { diff --git a/drivers/staging/lustre/lustre/include/lustre_dlm_flags.h b/drivers/staging/lustre/lustre/include/lustre_dlm_flags.h index e7e0c21..a0f064d 100644 --- a/drivers/staging/lustre/lustre/include/lustre_dlm_flags.h +++ b/drivers/staging/lustre/lustre/include/lustre_dlm_flags.h @@ -28,21 +28,6 @@ /** l_flags bits marked as "all_flags" bits */ #define LDLM_FL_ALL_FLAGS_MASK 0x00FFFFFFC08F932FULL -/** l_flags bits marked as "ast" bits */ -#define LDLM_FL_AST_MASK 0x0000000080008000ULL - -/** l_flags bits marked as "blocked" bits */ -#define LDLM_FL_BLOCKED_MASK 0x000000000000000EULL - -/** l_flags bits marked as "gone" bits */ -#define LDLM_FL_GONE_MASK 0x0006004000000000ULL - -/** l_flags bits marked as "inherit" bits */ -#define LDLM_FL_INHERIT_MASK 0x0000000000800000ULL - -/** l_flags bits marked as "off_wire" bits */ -#define LDLM_FL_OFF_WIRE_MASK 0x00FFFFFF00000000ULL - /** extent, mode, or resource changed */ #define LDLM_FL_LOCK_CHANGED 0x0000000000000001ULL /* bit 0 */ #define ldlm_is_lock_changed(_l) LDLM_TEST_FLAG((_l), 1ULL << 0) @@ -372,6 +357,27 @@ #define ldlm_set_excl(_l) LDLM_SET_FLAG((_l), 1ULL << 55) #define ldlm_clear_excl(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 55) +/** l_flags bits marked as "ast" bits */ +#define LDLM_FL_AST_MASK (LDLM_FL_FLOCK_DEADLOCK |\ + LDLM_FL_AST_DISCARD_DATA) + +/** l_flags bits marked as "blocked" bits */ +#define LDLM_FL_BLOCKED_MASK (LDLM_FL_BLOCK_GRANTED |\ + LDLM_FL_BLOCK_CONV |\ + LDLM_FL_BLOCK_WAIT) + +/** l_flags bits marked as "gone" bits */ +#define LDLM_FL_GONE_MASK (LDLM_FL_DESTROYED |\ + LDLM_FL_FAILED) + +/** l_flags bits marked as "inherit" bits */ +/* Flags inherited from wire on enqueue/reply between client/server. */ +/* NO_TIMEOUT flag to force ldlm_lock_match() to wait with no timeout. */ +/* TEST_LOCK flag to not let TEST lock to be granted. */ +#define LDLM_FL_INHERIT_MASK (LDLM_FL_CANCEL_ON_BLOCK |\ + LDLM_FL_NO_TIMEOUT |\ + LDLM_FL_TEST_LOCK) + /** test for ldlm_lock flag bit set */ #define LDLM_TEST_FLAG(_l, _b) (((_l)->l_flags & (_b)) != 0) diff --git a/drivers/staging/lustre/lustre/include/obd_support.h b/drivers/staging/lustre/lustre/include/obd_support.h index 71bf844..26fdff6 100644 --- a/drivers/staging/lustre/lustre/include/obd_support.h +++ b/drivers/staging/lustre/lustre/include/obd_support.h @@ -318,6 +318,10 @@ extern char obd_jobid_var[]; #define OBD_FAIL_LDLM_AGL_NOLOCK 0x31b #define OBD_FAIL_LDLM_OST_LVB 0x31c #define OBD_FAIL_LDLM_ENQUEUE_HANG 0x31d +#define OBD_FAIL_LDLM_CP_CB_WAIT2 0x320 +#define OBD_FAIL_LDLM_CP_CB_WAIT3 0x321 +#define OBD_FAIL_LDLM_CP_CB_WAIT4 0x322 +#define OBD_FAIL_LDLM_CP_CB_WAIT5 0x323 /* LOCKLESS IO */ #define OBD_FAIL_LDLM_SET_CONTENTION 0x385 diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c index d6b61bc..65e8e14 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c @@ -97,7 +97,7 @@ ldlm_flock_destroy(struct ldlm_lock *lock, enum ldlm_mode mode, __u64 flags) LASSERT(hlist_unhashed(&lock->l_exp_flock_hash)); list_del_init(&lock->l_res_link); - if (flags == LDLM_FL_WAIT_NOREPROC && !ldlm_is_failed(lock)) { + if (flags == LDLM_FL_WAIT_NOREPROC) { /* client side - set a flag to prevent sending a CANCEL */ lock->l_flags |= LDLM_FL_LOCAL_ONLY | LDLM_FL_CBPENDING; @@ -455,27 +455,21 @@ ldlm_flock_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data) enum ldlm_error err; int rc = 0; + OBD_FAIL_TIMEOUT(OBD_FAIL_LDLM_CP_CB_WAIT2, 4); + if (OBD_FAIL_PRECHECK(OBD_FAIL_LDLM_CP_CB_WAIT3)) { + lock_res_and_lock(lock); + lock->l_flags |= LDLM_FL_FAIL_LOC; + unlock_res_and_lock(lock); + OBD_FAIL_TIMEOUT(OBD_FAIL_LDLM_CP_CB_WAIT3, 4); + } CDEBUG(D_DLMTRACE, "flags: 0x%llx data: %p getlk: %p\n", flags, data, getlk); - /* Import invalidation. We need to actually release the lock - * references being held, so that it can go away. No point in - * holding the lock even if app still believes it has it, since - * server already dropped it anyway. Only for granted locks too. - */ - if ((lock->l_flags & (LDLM_FL_FAILED|LDLM_FL_LOCAL_ONLY)) == - (LDLM_FL_FAILED|LDLM_FL_LOCAL_ONLY)) { - if (lock->l_req_mode == lock->l_granted_mode && - lock->l_granted_mode != LCK_NL && !data) - ldlm_lock_decref_internal(lock, lock->l_req_mode); - - /* Need to wake up the waiter if we were evicted */ - wake_up(&lock->l_waitq); - return 0; - } - LASSERT(flags != LDLM_FL_WAIT_NOREPROC); + if (flags & LDLM_FL_FAILED) + goto granted; + if (!(flags & (LDLM_FL_BLOCK_WAIT | LDLM_FL_BLOCK_GRANTED | LDLM_FL_BLOCK_CONV))) { if (!data) @@ -514,12 +508,21 @@ ldlm_flock_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data) granted: OBD_FAIL_TIMEOUT(OBD_FAIL_LDLM_CP_CB_WAIT, 10); - if (ldlm_is_failed(lock)) { - LDLM_DEBUG(lock, "client-side enqueue waking up: failed"); - return -EIO; + if (OBD_FAIL_PRECHECK(OBD_FAIL_LDLM_CP_CB_WAIT4)) { + lock_res_and_lock(lock); + /* DEADLOCK is always set with CBPENDING */ + lock->l_flags |= LDLM_FL_FLOCK_DEADLOCK | LDLM_FL_CBPENDING; + unlock_res_and_lock(lock); + OBD_FAIL_TIMEOUT(OBD_FAIL_LDLM_CP_CB_WAIT4, 4); + } + if (OBD_FAIL_PRECHECK(OBD_FAIL_LDLM_CP_CB_WAIT5)) { + lock_res_and_lock(lock); + /* DEADLOCK is always set with CBPENDING */ + lock->l_flags |= LDLM_FL_FAIL_LOC | + LDLM_FL_FLOCK_DEADLOCK | LDLM_FL_CBPENDING; + unlock_res_and_lock(lock); + OBD_FAIL_TIMEOUT(OBD_FAIL_LDLM_CP_CB_WAIT5, 4); } - - LDLM_DEBUG(lock, "client-side enqueue granted"); lock_res_and_lock(lock); @@ -530,20 +533,59 @@ granted: if (ldlm_is_destroyed(lock)) { unlock_res_and_lock(lock); LDLM_DEBUG(lock, "client-side enqueue waking up: destroyed"); - return 0; + /* + * An error is still to be returned, to propagate it up to + * ldlm_cli_enqueue_fini() caller. + */ + return -EIO; } /* ldlm_lock_enqueue() has already placed lock on the granted list. */ - list_del_init(&lock->l_res_link); + ldlm_resource_unlink_lock(lock); + + /* + * Import invalidation. We need to actually release the lock + * references being held, so that it can go away. No point in + * holding the lock even if app still believes it has it, since + * server already dropped it anyway. Only for granted locks too. + */ + /* Do the same for DEADLOCK'ed locks. */ + if (ldlm_is_failed(lock) || ldlm_is_flock_deadlock(lock)) { + int mode; + + if (flags & LDLM_FL_TEST_LOCK) + LASSERT(ldlm_is_test_lock(lock)); + + if (ldlm_is_test_lock(lock) || ldlm_is_flock_deadlock(lock)) + mode = getlk->fl_type; + else + mode = lock->l_granted_mode; + + if (ldlm_is_flock_deadlock(lock)) { + LDLM_DEBUG(lock, "client-side enqueue deadlock received"); + rc = -EDEADLK; + } + ldlm_flock_destroy(lock, mode, LDLM_FL_WAIT_NOREPROC); + unlock_res_and_lock(lock); + + /* Need to wake up the waiter if we were evicted */ + wake_up(&lock->l_waitq); + + /* + * An error is still to be returned, to propagate it up to + * ldlm_cli_enqueue_fini() caller. + */ + return rc ? : -EIO; + } + + LDLM_DEBUG(lock, "client-side enqueue granted"); - if (ldlm_is_flock_deadlock(lock)) { - LDLM_DEBUG(lock, "client-side enqueue deadlock received"); - rc = -EDEADLK; - } else if (flags & LDLM_FL_TEST_LOCK) { + if (flags & LDLM_FL_TEST_LOCK) { /* fcntl(F_GETLK) request */ /* The old mode was saved in getlk->fl_type so that if the mode * in the lock changes we can decref the appropriate refcount. */ + LASSERT(ldlm_is_test_lock(lock)); ldlm_flock_destroy(lock, getlk->fl_type, LDLM_FL_WAIT_NOREPROC); switch (lock->l_granted_mode) { case LCK_PR: diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c index a5993f7..1a0fce1 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c @@ -1028,15 +1028,28 @@ void ldlm_grant_lock(struct ldlm_lock *lock, struct list_head *work_list) check_res_locked(res); lock->l_granted_mode = lock->l_req_mode; + + if (work_list && lock->l_completion_ast) + ldlm_add_ast_work_item(lock, NULL, work_list); + if (res->lr_type == LDLM_PLAIN || res->lr_type == LDLM_IBITS) ldlm_grant_lock_with_skiplist(lock); else if (res->lr_type == LDLM_EXTENT) ldlm_extent_add_lock(res, lock); - else + else if (res->lr_type == LDLM_FLOCK) { + /* + * We should not add locks to granted list in the following cases: + * - this is an UNLOCK but not a real lock; + * - this is a TEST lock; + * - this is a F_CANCELLK lock (async flock has req_mode == 0) + * - this is a deadlock (flock cannot be granted) + */ + if (!lock->l_req_mode || lock->l_req_mode == LCK_NL || + ldlm_is_test_lock(lock) || ldlm_is_flock_deadlock(lock)) + return; ldlm_resource_add_lock(res, &res->lr_granted, lock); - - if (work_list && lock->l_completion_ast) - ldlm_add_ast_work_item(lock, NULL, work_list); + } else + LBUG(); ldlm_pool_add(&ldlm_res_to_ns(res)->ns_pool, lock); } @@ -1546,6 +1559,8 @@ enum ldlm_error ldlm_lock_enqueue(struct ldlm_namespace *ns, */ if (*flags & LDLM_FL_AST_DISCARD_DATA) ldlm_set_ast_discard_data(lock); + if (*flags & LDLM_FL_TEST_LOCK) + ldlm_set_test_lock(lock); /* * This distinction between local lock trees is very important; a client diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index af487f9..984a460 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -309,8 +309,6 @@ static void failed_lock_cleanup(struct ldlm_namespace *ns, else LDLM_DEBUG(lock, "lock was granted or failed in race"); - ldlm_lock_decref_internal(lock, mode); - /* XXX - HACK because we shouldn't call ldlm_lock_destroy() * from llite/file.c/ll_file_flock(). */ @@ -321,9 +319,14 @@ static void failed_lock_cleanup(struct ldlm_namespace *ns, */ if (lock->l_resource->lr_type == LDLM_FLOCK) { lock_res_and_lock(lock); - ldlm_resource_unlink_lock(lock); - ldlm_lock_destroy_nolock(lock); + if (!ldlm_is_destroyed(lock)) { + ldlm_resource_unlink_lock(lock); + ldlm_lock_decref_internal_nolock(lock, mode); + ldlm_lock_destroy_nolock(lock); + } unlock_res_and_lock(lock); + } else { + ldlm_lock_decref_internal(lock, mode); } } @@ -418,11 +421,6 @@ int ldlm_cli_enqueue_fini(struct obd_export *exp, struct ptlrpc_request *req, *flags = ldlm_flags_from_wire(reply->lock_flags); lock->l_flags |= ldlm_flags_from_wire(reply->lock_flags & LDLM_FL_INHERIT_MASK); - /* move NO_TIMEOUT flag to the lock to force ldlm_lock_match() - * to wait with no timeout as well - */ - lock->l_flags |= ldlm_flags_from_wire(reply->lock_flags & - LDLM_FL_NO_TIMEOUT); unlock_res_and_lock(lock); CDEBUG(D_INFO, "local: %p, remote cookie: %#llx, flags: 0x%llx\n", diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c index 51a28d9..5866b00 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c @@ -793,8 +793,14 @@ static void cleanup_resource(struct ldlm_resource *res, struct list_head *q, */ unlock_res(res); LDLM_DEBUG(lock, "setting FL_LOCAL_ONLY"); + if (lock->l_flags & LDLM_FL_FAIL_LOC) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(cfs_time_seconds(4)); + set_current_state(TASK_RUNNING); + } if (lock->l_completion_ast) - lock->l_completion_ast(lock, 0, NULL); + lock->l_completion_ast(lock, LDLM_FL_FAILED, + NULL); LDLM_LOCK_RELEASE(lock); continue; } diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 769b028..89e93dc 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -2717,6 +2717,7 @@ ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock) struct md_op_data *op_data; struct lustre_handle lockh = {0}; ldlm_policy_data_t flock = { {0} }; + int fl_type = file_lock->fl_type; __u64 flags = 0; int rc; int rc2 = 0; @@ -2747,7 +2748,7 @@ ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock) if (file_lock->fl_lmops && file_lock->fl_lmops->lm_compare_owner) flock.l_flock.owner = (unsigned long)file_lock->fl_pid; - switch (file_lock->fl_type) { + switch (fl_type) { case F_RDLCK: einfo.ei_mode = LCK_PR; break; @@ -2767,8 +2768,7 @@ ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock) einfo.ei_mode = LCK_PW; break; default: - CDEBUG(D_INFO, "Unknown fcntl lock type: %d\n", - file_lock->fl_type); + CDEBUG(D_INFO, "Unknown fcntl lock type: %d\n", fl_type); return -ENOTSUPP; } @@ -2790,16 +2790,18 @@ ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock) case F_GETLK64: #endif flags = LDLM_FL_TEST_LOCK; - /* Save the old mode so that if the mode in the lock changes we - * can decrement the appropriate reader or writer refcount. - */ - file_lock->fl_type = einfo.ei_mode; break; default: CERROR("unknown fcntl lock command: %d\n", cmd); return -EINVAL; } + /* + * Save the old mode so that if the mode in the lock changes we + * can decrement the appropriate reader or writer refcount. + */ + file_lock->fl_type = einfo.ei_mode; + op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0, LUSTRE_OPC_ANY, NULL); if (IS_ERR(op_data)) @@ -2812,6 +2814,10 @@ ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock) rc = md_enqueue(sbi->ll_md_exp, &einfo, NULL, op_data, &lockh, &flock, 0, NULL /* req */, flags); + /* Restore the file lock type if not TEST lock. */ + if (!(flags & LDLM_FL_TEST_LOCK)) + file_lock->fl_type = fl_type; + if ((rc == 0 || file_lock->fl_type == F_UNLCK) && !(flags & LDLM_FL_TEST_LOCK)) rc2 = locks_lock_file_wait(file, file_lock); -- cgit v0.10.2 From 8877d3bff10ab1d02794c43013be7e68b83ce7ea Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Tue, 16 Aug 2016 16:18:51 -0400 Subject: staging: lustre: move ioctls to lustre_ioctl.h Move ioctl definitions and related functions from lustre_dlm.h, lustre_lib.h, obd.h, to lustre_ioctl.h. Replace the definitions of retired ioctls with comment. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4961 Reviewed-on: http://review.whamcloud.com/10139 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Robert Read <robert.read@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_ioctl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_ioctl.h new file mode 100644 index 0000000..f3d7c94 --- /dev/null +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_ioctl.h @@ -0,0 +1,412 @@ +/* + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.gnu.org/licenses/gpl-2.0.html + * + * GPL HEADER END + */ +/* + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Use is subject to license terms. + * + * Copyright (c) 2011, 2015, Intel Corporation. + */ +#ifndef LUSTRE_IOCTL_H_ +#define LUSTRE_IOCTL_H_ + +#include <linux/types.h> +#include "../../../include/linux/libcfs/libcfs.h" +#include "lustre_idl.h" + +#ifdef __KERNEL__ +# include <linux/ioctl.h> +# include <linux/string.h> +# include "../obd_support.h" +#else /* __KERNEL__ */ +# include <malloc.h> +# include <string.h> +#include <libcfs/util/ioctl.h> +#endif /* !__KERNEL__ */ + +#if !defined(__KERNEL__) && !defined(LUSTRE_UTILS) +# error This file is for Lustre internal use only. +#endif + +enum md_echo_cmd { + ECHO_MD_CREATE = 1, /* Open/Create file on MDT */ + ECHO_MD_MKDIR = 2, /* Mkdir on MDT */ + ECHO_MD_DESTROY = 3, /* Unlink file on MDT */ + ECHO_MD_RMDIR = 4, /* Rmdir on MDT */ + ECHO_MD_LOOKUP = 5, /* Lookup on MDT */ + ECHO_MD_GETATTR = 6, /* Getattr on MDT */ + ECHO_MD_SETATTR = 7, /* Setattr on MDT */ + ECHO_MD_ALLOC_FID = 8, /* Get FIDs from MDT */ +}; + +#define OBD_DEV_ID 1 +#define OBD_DEV_NAME "obd" +#define OBD_DEV_PATH "/dev/" OBD_DEV_NAME +#define OBD_DEV_MAJOR 10 +#define OBD_DEV_MINOR 241 + +#define OBD_IOCTL_VERSION 0x00010004 +#define OBD_DEV_BY_DEVNAME 0xffffd0de +#define OBD_MAX_IOCTL_BUFFER CONFIG_LUSTRE_OBD_MAX_IOCTL_BUFFER + +struct obd_ioctl_data { + __u32 ioc_len; + __u32 ioc_version; + + union { + __u64 ioc_cookie; + __u64 ioc_u64_1; + }; + union { + __u32 ioc_conn1; + __u32 ioc_u32_1; + }; + union { + __u32 ioc_conn2; + __u32 ioc_u32_2; + }; + + struct obdo ioc_obdo1; + struct obdo ioc_obdo2; + + __u64 ioc_count; + __u64 ioc_offset; + __u32 ioc_dev; + __u32 ioc_command; + + __u64 ioc_nid; + __u32 ioc_nal; + __u32 ioc_type; + + /* buffers the kernel will treat as user pointers */ + __u32 ioc_plen1; + char __user *ioc_pbuf1; + __u32 ioc_plen2; + char __user *ioc_pbuf2; + + /* inline buffers for various arguments */ + __u32 ioc_inllen1; + char *ioc_inlbuf1; + __u32 ioc_inllen2; + char *ioc_inlbuf2; + __u32 ioc_inllen3; + char *ioc_inlbuf3; + __u32 ioc_inllen4; + char *ioc_inlbuf4; + + char ioc_bulk[0]; +}; + +struct obd_ioctl_hdr { + __u32 ioc_len; + __u32 ioc_version; +}; + +static inline __u32 obd_ioctl_packlen(struct obd_ioctl_data *data) +{ + __u32 len = cfs_size_round(sizeof(*data)); + + len += cfs_size_round(data->ioc_inllen1); + len += cfs_size_round(data->ioc_inllen2); + len += cfs_size_round(data->ioc_inllen3); + len += cfs_size_round(data->ioc_inllen4); + + return len; +} + +static inline int obd_ioctl_is_invalid(struct obd_ioctl_data *data) +{ + if (data->ioc_len > (1 << 30)) { + CERROR("OBD ioctl: ioc_len larger than 1<<30\n"); + return 1; + } + + if (data->ioc_inllen1 > (1 << 30)) { + CERROR("OBD ioctl: ioc_inllen1 larger than 1<<30\n"); + return 1; + } + + if (data->ioc_inllen2 > (1 << 30)) { + CERROR("OBD ioctl: ioc_inllen2 larger than 1<<30\n"); + return 1; + } + + if (data->ioc_inllen3 > (1 << 30)) { + CERROR("OBD ioctl: ioc_inllen3 larger than 1<<30\n"); + return 1; + } + + if (data->ioc_inllen4 > (1 << 30)) { + CERROR("OBD ioctl: ioc_inllen4 larger than 1<<30\n"); + return 1; + } + + if (data->ioc_inlbuf1 && !data->ioc_inllen1) { + CERROR("OBD ioctl: inlbuf1 pointer but 0 length\n"); + return 1; + } + + if (data->ioc_inlbuf2 && !data->ioc_inllen2) { + CERROR("OBD ioctl: inlbuf2 pointer but 0 length\n"); + return 1; + } + + if (data->ioc_inlbuf3 && !data->ioc_inllen3) { + CERROR("OBD ioctl: inlbuf3 pointer but 0 length\n"); + return 1; + } + + if (data->ioc_inlbuf4 && !data->ioc_inllen4) { + CERROR("OBD ioctl: inlbuf4 pointer but 0 length\n"); + return 1; + } + + if (data->ioc_pbuf1 && !data->ioc_plen1) { + CERROR("OBD ioctl: pbuf1 pointer but 0 length\n"); + return 1; + } + + if (data->ioc_pbuf2 && !data->ioc_plen2) { + CERROR("OBD ioctl: pbuf2 pointer but 0 length\n"); + return 1; + } + + if (!data->ioc_pbuf1 && data->ioc_plen1) { + CERROR("OBD ioctl: plen1 set but NULL pointer\n"); + return 1; + } + + if (!data->ioc_pbuf2 && data->ioc_plen2) { + CERROR("OBD ioctl: plen2 set but NULL pointer\n"); + return 1; + } + + if (obd_ioctl_packlen(data) > data->ioc_len) { + CERROR("OBD ioctl: packlen exceeds ioc_len (%d > %d)\n", + obd_ioctl_packlen(data), data->ioc_len); + return 1; + } + + return 0; +} + +#ifdef __KERNEL__ + +int obd_ioctl_getdata(char **buf, int *len, void __user *arg); +int obd_ioctl_popdata(void __user *arg, void *data, int len); + +static inline void obd_ioctl_freedata(char *buf, size_t len) +{ + kvfree(buf); +} + +#else /* __KERNEL__ */ + +static inline int obd_ioctl_pack(struct obd_ioctl_data *data, char **pbuf, + int max_len) +{ + char *ptr; + struct obd_ioctl_data *overlay; + + data->ioc_len = obd_ioctl_packlen(data); + data->ioc_version = OBD_IOCTL_VERSION; + + if (*pbuf && data->ioc_len > max_len) { + fprintf(stderr, "pbuf = %p, ioc_len = %u, max_len = %d\n", + *pbuf, data->ioc_len, max_len); + return -EINVAL; + } + + if (!*pbuf) + *pbuf = malloc(data->ioc_len); + + if (!*pbuf) + return -ENOMEM; + + overlay = (struct obd_ioctl_data *)*pbuf; + memcpy(*pbuf, data, sizeof(*data)); + + ptr = overlay->ioc_bulk; + if (data->ioc_inlbuf1) + LOGL(data->ioc_inlbuf1, data->ioc_inllen1, ptr); + + if (data->ioc_inlbuf2) + LOGL(data->ioc_inlbuf2, data->ioc_inllen2, ptr); + + if (data->ioc_inlbuf3) + LOGL(data->ioc_inlbuf3, data->ioc_inllen3, ptr); + + if (data->ioc_inlbuf4) + LOGL(data->ioc_inlbuf4, data->ioc_inllen4, ptr); + + if (obd_ioctl_is_invalid(overlay)) { + fprintf(stderr, "invalid ioctl data: ioc_len = %u, max_len = %d\n", + data->ioc_len, max_len); + return -EINVAL; + } + + return 0; +} + +static inline int +obd_ioctl_unpack(struct obd_ioctl_data *data, char *pbuf, int max_len) +{ + char *ptr; + struct obd_ioctl_data *overlay; + + if (!pbuf) + return 1; + + overlay = (struct obd_ioctl_data *)pbuf; + + /* Preserve the caller's buffer pointers */ + overlay->ioc_inlbuf1 = data->ioc_inlbuf1; + overlay->ioc_inlbuf2 = data->ioc_inlbuf2; + overlay->ioc_inlbuf3 = data->ioc_inlbuf3; + overlay->ioc_inlbuf4 = data->ioc_inlbuf4; + + memcpy(data, pbuf, sizeof(*data)); + + ptr = overlay->ioc_bulk; + if (data->ioc_inlbuf1) + LOGU(data->ioc_inlbuf1, data->ioc_inllen1, ptr); + + if (data->ioc_inlbuf2) + LOGU(data->ioc_inlbuf2, data->ioc_inllen2, ptr); + + if (data->ioc_inlbuf3) + LOGU(data->ioc_inlbuf3, data->ioc_inllen3, ptr); + + if (data->ioc_inlbuf4) + LOGU(data->ioc_inlbuf4, data->ioc_inllen4, ptr); + + return 0; +} + +#endif /* !__KERNEL__ */ + +/* + * OBD_IOC_DATA_TYPE is only for compatibility reasons with older + * Linux Lustre user tools. New ioctls should NOT use this macro as + * the ioctl "size". Instead the ioctl should get a "size" argument + * which is the actual data type used by the ioctl, to ensure the + * ioctl interface is versioned correctly. + */ +#define OBD_IOC_DATA_TYPE long + +/* IOC_LDLM_TEST _IOWR('f', 40, long) */ +/* IOC_LDLM_DUMP _IOWR('f', 41, long) */ +/* IOC_LDLM_REGRESS_START _IOWR('f', 42, long) */ +/* IOC_LDLM_REGRESS_STOP _IOWR('f', 43, long) */ + +#define OBD_IOC_CREATE _IOWR('f', 101, OBD_IOC_DATA_TYPE) +#define OBD_IOC_DESTROY _IOW('f', 104, OBD_IOC_DATA_TYPE) +/* OBD_IOC_PREALLOCATE _IOWR('f', 105, OBD_IOC_DATA_TYPE) */ + +#define OBD_IOC_SETATTR _IOW('f', 107, OBD_IOC_DATA_TYPE) +#define OBD_IOC_GETATTR _IOWR('f', 108, OBD_IOC_DATA_TYPE) +#define OBD_IOC_READ _IOWR('f', 109, OBD_IOC_DATA_TYPE) +#define OBD_IOC_WRITE _IOWR('f', 110, OBD_IOC_DATA_TYPE) + +#define OBD_IOC_STATFS _IOWR('f', 113, OBD_IOC_DATA_TYPE) +#define OBD_IOC_SYNC _IOW('f', 114, OBD_IOC_DATA_TYPE) +/* OBD_IOC_READ2 _IOWR('f', 115, OBD_IOC_DATA_TYPE) */ +/* OBD_IOC_FORMAT _IOWR('f', 116, OBD_IOC_DATA_TYPE) */ +/* OBD_IOC_PARTITION _IOWR('f', 117, OBD_IOC_DATA_TYPE) */ +/* OBD_IOC_COPY _IOWR('f', 120, OBD_IOC_DATA_TYPE) */ +/* OBD_IOC_MIGR _IOWR('f', 121, OBD_IOC_DATA_TYPE) */ +/* OBD_IOC_PUNCH _IOWR('f', 122, OBD_IOC_DATA_TYPE) */ + +/* OBD_IOC_MODULE_DEBUG _IOWR('f', 124, OBD_IOC_DATA_TYPE) */ +#define OBD_IOC_BRW_READ _IOWR('f', 125, OBD_IOC_DATA_TYPE) +#define OBD_IOC_BRW_WRITE _IOWR('f', 126, OBD_IOC_DATA_TYPE) +#define OBD_IOC_NAME2DEV _IOWR('f', 127, OBD_IOC_DATA_TYPE) +#define OBD_IOC_UUID2DEV _IOWR('f', 130, OBD_IOC_DATA_TYPE) +#define OBD_IOC_GETNAME _IOWR('f', 131, OBD_IOC_DATA_TYPE) +#define OBD_IOC_GETMDNAME _IOR('f', 131, char[MAX_OBD_NAME]) +#define OBD_IOC_GETDTNAME OBD_IOC_GETNAME +#define OBD_IOC_LOV_GET_CONFIG _IOWR('f', 132, OBD_IOC_DATA_TYPE) +#define OBD_IOC_CLIENT_RECOVER _IOW('f', 133, OBD_IOC_DATA_TYPE) +#define OBD_IOC_PING_TARGET _IOW('f', 136, OBD_IOC_DATA_TYPE) + +/* OBD_IOC_DEC_FS_USE_COUNT _IO('f', 139) */ +#define OBD_IOC_NO_TRANSNO _IOW('f', 140, OBD_IOC_DATA_TYPE) +#define OBD_IOC_SET_READONLY _IOW('f', 141, OBD_IOC_DATA_TYPE) +#define OBD_IOC_ABORT_RECOVERY _IOR('f', 142, OBD_IOC_DATA_TYPE) +/* OBD_IOC_ROOT_SQUASH _IOWR('f', 143, OBD_IOC_DATA_TYPE) */ +#define OBD_GET_VERSION _IOWR('f', 144, OBD_IOC_DATA_TYPE) +/* OBD_IOC_GSS_SUPPORT _IOWR('f', 145, OBD_IOC_DATA_TYPE) */ +/* OBD_IOC_CLOSE_UUID _IOWR('f', 147, OBD_IOC_DATA_TYPE) */ +#define OBD_IOC_CHANGELOG_SEND _IOW('f', 148, OBD_IOC_DATA_TYPE) +#define OBD_IOC_GETDEVICE _IOWR('f', 149, OBD_IOC_DATA_TYPE) +#define OBD_IOC_FID2PATH _IOWR('f', 150, OBD_IOC_DATA_TYPE) +/* lustre/lustre_user.h 151-153 */ +/* OBD_IOC_LOV_SETSTRIPE 154 LL_IOC_LOV_SETSTRIPE */ +/* OBD_IOC_LOV_GETSTRIPE 155 LL_IOC_LOV_GETSTRIPE */ +/* OBD_IOC_LOV_SETEA 156 LL_IOC_LOV_SETEA */ +/* lustre/lustre_user.h 157-159 */ +#define OBD_IOC_QUOTACHECK _IOW('f', 160, int) +#define OBD_IOC_POLL_QUOTACHECK _IOR('f', 161, struct if_quotacheck *) +#define OBD_IOC_QUOTACTL _IOWR('f', 162, struct if_quotactl) +/* lustre/lustre_user.h 163-176 */ +#define OBD_IOC_CHANGELOG_REG _IOW('f', 177, struct obd_ioctl_data) +#define OBD_IOC_CHANGELOG_DEREG _IOW('f', 178, struct obd_ioctl_data) +#define OBD_IOC_CHANGELOG_CLEAR _IOW('f', 179, struct obd_ioctl_data) +/* OBD_IOC_RECORD _IOWR('f', 180, OBD_IOC_DATA_TYPE) */ +/* OBD_IOC_ENDRECORD _IOWR('f', 181, OBD_IOC_DATA_TYPE) */ +/* OBD_IOC_PARSE _IOWR('f', 182, OBD_IOC_DATA_TYPE) */ +/* OBD_IOC_DORECORD _IOWR('f', 183, OBD_IOC_DATA_TYPE) */ +#define OBD_IOC_PROCESS_CFG _IOWR('f', 184, OBD_IOC_DATA_TYPE) +/* OBD_IOC_DUMP_LOG _IOWR('f', 185, OBD_IOC_DATA_TYPE) */ +/* OBD_IOC_CLEAR_LOG _IOWR('f', 186, OBD_IOC_DATA_TYPE) */ +#define OBD_IOC_PARAM _IOW('f', 187, OBD_IOC_DATA_TYPE) +#define OBD_IOC_POOL _IOWR('f', 188, OBD_IOC_DATA_TYPE) +#define OBD_IOC_REPLACE_NIDS _IOWR('f', 189, OBD_IOC_DATA_TYPE) + +#define OBD_IOC_CATLOGLIST _IOWR('f', 190, OBD_IOC_DATA_TYPE) +#define OBD_IOC_LLOG_INFO _IOWR('f', 191, OBD_IOC_DATA_TYPE) +#define OBD_IOC_LLOG_PRINT _IOWR('f', 192, OBD_IOC_DATA_TYPE) +#define OBD_IOC_LLOG_CANCEL _IOWR('f', 193, OBD_IOC_DATA_TYPE) +#define OBD_IOC_LLOG_REMOVE _IOWR('f', 194, OBD_IOC_DATA_TYPE) +#define OBD_IOC_LLOG_CHECK _IOWR('f', 195, OBD_IOC_DATA_TYPE) +/* OBD_IOC_LLOG_CATINFO _IOWR('f', 196, OBD_IOC_DATA_TYPE) */ +#define OBD_IOC_NODEMAP _IOWR('f', 197, OBD_IOC_DATA_TYPE) + +/* ECHO_IOC_GET_STRIPE _IOWR('f', 200, OBD_IOC_DATA_TYPE) */ +/* ECHO_IOC_SET_STRIPE _IOWR('f', 201, OBD_IOC_DATA_TYPE) */ +/* ECHO_IOC_ENQUEUE _IOWR('f', 202, OBD_IOC_DATA_TYPE) */ +/* ECHO_IOC_CANCEL _IOWR('f', 203, OBD_IOC_DATA_TYPE) */ + +#define OBD_IOC_GET_OBJ_VERSION _IOR('f', 210, OBD_IOC_DATA_TYPE) + +/* lustre/lustre_user.h 212-217 */ +#define OBD_IOC_GET_MNTOPT _IOW('f', 220, mntopt_t) +#define OBD_IOC_ECHO_MD _IOR('f', 221, struct obd_ioctl_data) +#define OBD_IOC_ECHO_ALLOC_SEQ _IOWR('f', 222, struct obd_ioctl_data) +#define OBD_IOC_START_LFSCK _IOWR('f', 230, OBD_IOC_DATA_TYPE) +#define OBD_IOC_STOP_LFSCK _IOW('f', 231, OBD_IOC_DATA_TYPE) +#define OBD_IOC_QUERY_LFSCK _IOR('f', 232, struct obd_ioctl_data) +/* lustre/lustre_user.h 240-249 */ +/* LIBCFS_IOC_DEBUG_MASK 250 */ + +#define IOC_OSC_SET_ACTIVE _IOWR('h', 21, void *) + +#endif /* LUSTRE_IOCTL_H_ */ diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index 4746320..75a78a3 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -188,26 +188,20 @@ struct ost_id { * *STRIPE* - set/get lov_user_md * *INFO - set/get lov_user_mds_data */ -/* see <lustre_lib.h> for ioctl numberss 101-150 */ +/* lustre_ioctl.h 101-150 */ #define LL_IOC_GETFLAGS _IOR('f', 151, long) #define LL_IOC_SETFLAGS _IOW('f', 152, long) #define LL_IOC_CLRFLAGS _IOW('f', 153, long) -/* LL_IOC_LOV_SETSTRIPE: See also OBD_IOC_LOV_SETSTRIPE */ #define LL_IOC_LOV_SETSTRIPE _IOW('f', 154, long) -/* LL_IOC_LOV_GETSTRIPE: See also OBD_IOC_LOV_GETSTRIPE */ #define LL_IOC_LOV_GETSTRIPE _IOW('f', 155, long) -/* LL_IOC_LOV_SETEA: See also OBD_IOC_LOV_SETEA */ #define LL_IOC_LOV_SETEA _IOW('f', 156, long) #define LL_IOC_RECREATE_OBJ _IOW('f', 157, long) #define LL_IOC_RECREATE_FID _IOW('f', 157, struct lu_fid) #define LL_IOC_GROUP_LOCK _IOW('f', 158, long) #define LL_IOC_GROUP_UNLOCK _IOW('f', 159, long) -/* LL_IOC_QUOTACHECK: See also OBD_IOC_QUOTACHECK */ -#define LL_IOC_QUOTACHECK _IOW('f', 160, int) -/* LL_IOC_POLL_QUOTACHECK: See also OBD_IOC_POLL_QUOTACHECK */ -#define LL_IOC_POLL_QUOTACHECK _IOR('f', 161, struct if_quotacheck *) -/* LL_IOC_QUOTACTL: See also OBD_IOC_QUOTACTL */ -#define LL_IOC_QUOTACTL _IOWR('f', 162, struct if_quotactl) +/* #define LL_IOC_QUOTACHECK 160 OBD_IOC_QUOTACHECK */ +/* #define LL_IOC_POLL_QUOTACHECK 161 OBD_IOC_POLL_QUOTACHECK */ +/* #define LL_IOC_QUOTACTL 162 OBD_IOC_QUOTACTL */ #define IOC_OBD_STATFS _IOWR('f', 164, struct obd_statfs *) #define IOC_LOV_GETINFO _IOWR('f', 165, struct lov_user_mds_data *) #define LL_IOC_FLUSHCTX _IOW('f', 166, long) @@ -221,8 +215,7 @@ struct ost_id { #define LL_IOC_GET_CONNECT_FLAGS _IOWR('f', 174, __u64 *) #define LL_IOC_GET_MDTIDX _IOR('f', 175, int) -/* see <lustre_lib.h> for ioctl numbers 177-210 */ - +/* lustre_ioctl.h 177-210 */ #define LL_IOC_HSM_STATE_GET _IOR('f', 211, struct hsm_user_state) #define LL_IOC_HSM_STATE_SET _IOW('f', 212, struct hsm_state_set) #define LL_IOC_HSM_CT_START _IOW('f', 213, struct lustre_kernelcomm) @@ -255,10 +248,6 @@ struct ost_id { #define IOC_MDC_GETFILEINFO _IOWR(IOC_MDC_TYPE, 22, struct lov_user_mds_data *) #define LL_IOC_MDC_GETINFO _IOWR(IOC_MDC_TYPE, 23, struct lov_user_mds_data *) -/* Keep these for backward compartability. */ -#define LL_IOC_OBD_STATFS IOC_OBD_STATFS -#define IOC_MDC_GETSTRIPE IOC_MDC_GETFILESTRIPE - #define MAX_OBD_NAME 128 /* If this changes, a NEW ioctl must be added */ /* Define O_LOV_DELAY_CREATE to be a mask that is not useful for regular diff --git a/drivers/staging/lustre/lustre/include/lustre_dlm.h b/drivers/staging/lustre/lustre/include/lustre_dlm.h index f7805cc..1ec4231 100644 --- a/drivers/staging/lustre/lustre/include/lustre_dlm.h +++ b/drivers/staging/lustre/lustre/include/lustre_dlm.h @@ -1282,16 +1282,6 @@ int ldlm_cli_cancel_list(struct list_head *head, int count, int intent_disposition(struct ldlm_reply *rep, int flag); void intent_set_disposition(struct ldlm_reply *rep, int flag); -/* ioctls for trying requests */ -#define IOC_LDLM_TYPE 'f' -#define IOC_LDLM_MIN_NR 40 - -#define IOC_LDLM_TEST _IOWR('f', 40, long) -#define IOC_LDLM_DUMP _IOWR('f', 41, long) -#define IOC_LDLM_REGRESS_START _IOWR('f', 42, long) -#define IOC_LDLM_REGRESS_STOP _IOWR('f', 43, long) -#define IOC_LDLM_MAX_NR 43 - /** * "Modes" of acquiring lock_res, necessary to tell lockdep that taking more * than one lock_res is dead-lock safe. diff --git a/drivers/staging/lustre/lustre/include/lustre_lib.h b/drivers/staging/lustre/lustre/include/lustre_lib.h index def0193..adb8c47 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lib.h +++ b/drivers/staging/lustre/lustre/include/lustre_lib.h @@ -75,7 +75,6 @@ int do_set_info_async(struct obd_import *imp, struct ptlrpc_request_set *set); #define OBD_RECOVERY_MAX_TIME (obd_timeout * 18) /* b13079 */ -#define OBD_MAX_IOCTL_BUFFER CONFIG_LUSTRE_OBD_MAX_IOCTL_BUFFER void target_send_reply(struct ptlrpc_request *req, int rc, int fail_id); @@ -99,289 +98,6 @@ struct obd_client_handle { /* statfs_pack.c */ void statfs_unpack(struct kstatfs *sfs, struct obd_statfs *osfs); -/* - * For md echo client - */ -enum md_echo_cmd { - ECHO_MD_CREATE = 1, /* Open/Create file on MDT */ - ECHO_MD_MKDIR = 2, /* Mkdir on MDT */ - ECHO_MD_DESTROY = 3, /* Unlink file on MDT */ - ECHO_MD_RMDIR = 4, /* Rmdir on MDT */ - ECHO_MD_LOOKUP = 5, /* Lookup on MDT */ - ECHO_MD_GETATTR = 6, /* Getattr on MDT */ - ECHO_MD_SETATTR = 7, /* Setattr on MDT */ - ECHO_MD_ALLOC_FID = 8, /* Get FIDs from MDT */ -}; - -/* - * OBD IOCTLS - */ -#define OBD_IOCTL_VERSION 0x00010004 - -struct obd_ioctl_data { - __u32 ioc_len; - __u32 ioc_version; - - union { - __u64 ioc_cookie; - __u64 ioc_u64_1; - }; - union { - __u32 ioc_conn1; - __u32 ioc_u32_1; - }; - union { - __u32 ioc_conn2; - __u32 ioc_u32_2; - }; - - struct obdo ioc_obdo1; - struct obdo ioc_obdo2; - - u64 ioc_count; - u64 ioc_offset; - __u32 ioc_dev; - __u32 ioc_command; - - __u64 ioc_nid; - __u32 ioc_nal; - __u32 ioc_type; - - /* buffers the kernel will treat as user pointers */ - __u32 ioc_plen1; - void __user *ioc_pbuf1; - __u32 ioc_plen2; - void __user *ioc_pbuf2; - - /* inline buffers for various arguments */ - __u32 ioc_inllen1; - char *ioc_inlbuf1; - __u32 ioc_inllen2; - char *ioc_inlbuf2; - __u32 ioc_inllen3; - char *ioc_inlbuf3; - __u32 ioc_inllen4; - char *ioc_inlbuf4; - - char ioc_bulk[0]; -}; - -struct obd_ioctl_hdr { - __u32 ioc_len; - __u32 ioc_version; -}; - -static inline int obd_ioctl_packlen(struct obd_ioctl_data *data) -{ - int len = cfs_size_round(sizeof(struct obd_ioctl_data)); - - len += cfs_size_round(data->ioc_inllen1); - len += cfs_size_round(data->ioc_inllen2); - len += cfs_size_round(data->ioc_inllen3); - len += cfs_size_round(data->ioc_inllen4); - return len; -} - -static inline int obd_ioctl_is_invalid(struct obd_ioctl_data *data) -{ - if (data->ioc_len > OBD_MAX_IOCTL_BUFFER) { - CERROR("OBD ioctl: ioc_len larger than %d\n", - OBD_MAX_IOCTL_BUFFER); - return 1; - } - if (data->ioc_inllen1 > OBD_MAX_IOCTL_BUFFER) { - CERROR("OBD ioctl: ioc_inllen1 larger than ioc_len\n"); - return 1; - } - if (data->ioc_inllen2 > OBD_MAX_IOCTL_BUFFER) { - CERROR("OBD ioctl: ioc_inllen2 larger than ioc_len\n"); - return 1; - } - if (data->ioc_inllen3 > OBD_MAX_IOCTL_BUFFER) { - CERROR("OBD ioctl: ioc_inllen3 larger than ioc_len\n"); - return 1; - } - if (data->ioc_inllen4 > OBD_MAX_IOCTL_BUFFER) { - CERROR("OBD ioctl: ioc_inllen4 larger than ioc_len\n"); - return 1; - } - if (data->ioc_inlbuf1 && !data->ioc_inllen1) { - CERROR("OBD ioctl: inlbuf1 pointer but 0 length\n"); - return 1; - } - if (data->ioc_inlbuf2 && !data->ioc_inllen2) { - CERROR("OBD ioctl: inlbuf2 pointer but 0 length\n"); - return 1; - } - if (data->ioc_inlbuf3 && !data->ioc_inllen3) { - CERROR("OBD ioctl: inlbuf3 pointer but 0 length\n"); - return 1; - } - if (data->ioc_inlbuf4 && !data->ioc_inllen4) { - CERROR("OBD ioctl: inlbuf4 pointer but 0 length\n"); - return 1; - } - if (data->ioc_pbuf1 && !data->ioc_plen1) { - CERROR("OBD ioctl: pbuf1 pointer but 0 length\n"); - return 1; - } - if (data->ioc_pbuf2 && !data->ioc_plen2) { - CERROR("OBD ioctl: pbuf2 pointer but 0 length\n"); - return 1; - } - if (data->ioc_plen1 && !data->ioc_pbuf1) { - CERROR("OBD ioctl: plen1 set but NULL pointer\n"); - return 1; - } - if (data->ioc_plen2 && !data->ioc_pbuf2) { - CERROR("OBD ioctl: plen2 set but NULL pointer\n"); - return 1; - } - if (obd_ioctl_packlen(data) > data->ioc_len) { - CERROR("OBD ioctl: packlen exceeds ioc_len (%d > %d)\n", - obd_ioctl_packlen(data), data->ioc_len); - return 1; - } - return 0; -} - -#include "obd_support.h" - -/* function defined in lustre/obdclass/<platform>/<platform>-module.c */ -int obd_ioctl_getdata(char **buf, int *len, void __user *arg); -int obd_ioctl_popdata(void __user *arg, void *data, int len); - -static inline void obd_ioctl_freedata(char *buf, int len) -{ - kvfree(buf); - return; -} - -/* - * BSD ioctl description: - * #define IOC_V1 _IOR(g, n1, long) - * #define IOC_V2 _IOW(g, n2, long) - * - * ioctl(f, IOC_V1, arg); - * arg will be treated as a long value, - * - * ioctl(f, IOC_V2, arg) - * arg will be treated as a pointer, bsd will call - * copyin(buf, arg, sizeof(long)) - * - * To make BSD ioctl handles argument correctly and simplely, - * we change _IOR to _IOWR so BSD will copyin obd_ioctl_data - * for us. Does this change affect Linux? (XXX Liang) - */ -#define OBD_IOC_DATA_TYPE long - -#define OBD_IOC_CREATE _IOWR('f', 101, OBD_IOC_DATA_TYPE) -#define OBD_IOC_DESTROY _IOW('f', 104, OBD_IOC_DATA_TYPE) -#define OBD_IOC_PREALLOCATE _IOWR('f', 105, OBD_IOC_DATA_TYPE) - -#define OBD_IOC_SETATTR _IOW('f', 107, OBD_IOC_DATA_TYPE) -#define OBD_IOC_GETATTR _IOWR ('f', 108, OBD_IOC_DATA_TYPE) -#define OBD_IOC_READ _IOWR('f', 109, OBD_IOC_DATA_TYPE) -#define OBD_IOC_WRITE _IOWR('f', 110, OBD_IOC_DATA_TYPE) - -#define OBD_IOC_STATFS _IOWR('f', 113, OBD_IOC_DATA_TYPE) -#define OBD_IOC_SYNC _IOW('f', 114, OBD_IOC_DATA_TYPE) -#define OBD_IOC_READ2 _IOWR('f', 115, OBD_IOC_DATA_TYPE) -#define OBD_IOC_FORMAT _IOWR('f', 116, OBD_IOC_DATA_TYPE) -#define OBD_IOC_PARTITION _IOWR('f', 117, OBD_IOC_DATA_TYPE) -#define OBD_IOC_COPY _IOWR('f', 120, OBD_IOC_DATA_TYPE) -#define OBD_IOC_MIGR _IOWR('f', 121, OBD_IOC_DATA_TYPE) -#define OBD_IOC_PUNCH _IOWR('f', 122, OBD_IOC_DATA_TYPE) - -#define OBD_IOC_MODULE_DEBUG _IOWR('f', 124, OBD_IOC_DATA_TYPE) -#define OBD_IOC_BRW_READ _IOWR('f', 125, OBD_IOC_DATA_TYPE) -#define OBD_IOC_BRW_WRITE _IOWR('f', 126, OBD_IOC_DATA_TYPE) -#define OBD_IOC_NAME2DEV _IOWR('f', 127, OBD_IOC_DATA_TYPE) -#define OBD_IOC_UUID2DEV _IOWR('f', 130, OBD_IOC_DATA_TYPE) - -#define OBD_IOC_GETNAME _IOWR('f', 131, OBD_IOC_DATA_TYPE) -#define OBD_IOC_GETMDNAME _IOR('f', 131, char[MAX_OBD_NAME]) -#define OBD_IOC_GETDTNAME OBD_IOC_GETNAME - -#define OBD_IOC_LOV_GET_CONFIG _IOWR('f', 132, OBD_IOC_DATA_TYPE) -#define OBD_IOC_CLIENT_RECOVER _IOW('f', 133, OBD_IOC_DATA_TYPE) -#define OBD_IOC_PING_TARGET _IOW('f', 136, OBD_IOC_DATA_TYPE) - -#define OBD_IOC_DEC_FS_USE_COUNT _IO ('f', 139) -#define OBD_IOC_NO_TRANSNO _IOW('f', 140, OBD_IOC_DATA_TYPE) -#define OBD_IOC_SET_READONLY _IOW('f', 141, OBD_IOC_DATA_TYPE) -#define OBD_IOC_ABORT_RECOVERY _IOR('f', 142, OBD_IOC_DATA_TYPE) - -#define OBD_IOC_ROOT_SQUASH _IOWR('f', 143, OBD_IOC_DATA_TYPE) - -#define OBD_GET_VERSION _IOWR ('f', 144, OBD_IOC_DATA_TYPE) - -#define OBD_IOC_GSS_SUPPORT _IOWR('f', 145, OBD_IOC_DATA_TYPE) - -#define OBD_IOC_CLOSE_UUID _IOWR ('f', 147, OBD_IOC_DATA_TYPE) - -#define OBD_IOC_CHANGELOG_SEND _IOW('f', 148, OBD_IOC_DATA_TYPE) -#define OBD_IOC_GETDEVICE _IOWR ('f', 149, OBD_IOC_DATA_TYPE) -#define OBD_IOC_FID2PATH _IOWR ('f', 150, OBD_IOC_DATA_TYPE) -/* see also <lustre/lustre_user.h> for ioctls 151-153 */ -/* OBD_IOC_LOV_SETSTRIPE: See also LL_IOC_LOV_SETSTRIPE */ -#define OBD_IOC_LOV_SETSTRIPE _IOW('f', 154, OBD_IOC_DATA_TYPE) -/* OBD_IOC_LOV_GETSTRIPE: See also LL_IOC_LOV_GETSTRIPE */ -#define OBD_IOC_LOV_GETSTRIPE _IOW('f', 155, OBD_IOC_DATA_TYPE) -/* OBD_IOC_LOV_SETEA: See also LL_IOC_LOV_SETEA */ -#define OBD_IOC_LOV_SETEA _IOW('f', 156, OBD_IOC_DATA_TYPE) -/* see <lustre/lustre_user.h> for ioctls 157-159 */ -/* OBD_IOC_QUOTACHECK: See also LL_IOC_QUOTACHECK */ -#define OBD_IOC_QUOTACHECK _IOW('f', 160, int) -/* OBD_IOC_POLL_QUOTACHECK: See also LL_IOC_POLL_QUOTACHECK */ -#define OBD_IOC_POLL_QUOTACHECK _IOR('f', 161, struct if_quotacheck *) -/* OBD_IOC_QUOTACTL: See also LL_IOC_QUOTACTL */ -#define OBD_IOC_QUOTACTL _IOWR('f', 162, struct if_quotactl) -/* see also <lustre/lustre_user.h> for ioctls 163-176 */ -#define OBD_IOC_CHANGELOG_REG _IOW('f', 177, struct obd_ioctl_data) -#define OBD_IOC_CHANGELOG_DEREG _IOW('f', 178, struct obd_ioctl_data) -#define OBD_IOC_CHANGELOG_CLEAR _IOW('f', 179, struct obd_ioctl_data) -#define OBD_IOC_RECORD _IOWR('f', 180, OBD_IOC_DATA_TYPE) -#define OBD_IOC_ENDRECORD _IOWR('f', 181, OBD_IOC_DATA_TYPE) -#define OBD_IOC_PARSE _IOWR('f', 182, OBD_IOC_DATA_TYPE) -#define OBD_IOC_DORECORD _IOWR('f', 183, OBD_IOC_DATA_TYPE) -#define OBD_IOC_PROCESS_CFG _IOWR('f', 184, OBD_IOC_DATA_TYPE) -#define OBD_IOC_DUMP_LOG _IOWR('f', 185, OBD_IOC_DATA_TYPE) -#define OBD_IOC_CLEAR_LOG _IOWR('f', 186, OBD_IOC_DATA_TYPE) -#define OBD_IOC_PARAM _IOW('f', 187, OBD_IOC_DATA_TYPE) -#define OBD_IOC_POOL _IOWR('f', 188, OBD_IOC_DATA_TYPE) -#define OBD_IOC_REPLACE_NIDS _IOWR('f', 189, OBD_IOC_DATA_TYPE) - -#define OBD_IOC_CATLOGLIST _IOWR('f', 190, OBD_IOC_DATA_TYPE) -#define OBD_IOC_LLOG_INFO _IOWR('f', 191, OBD_IOC_DATA_TYPE) -#define OBD_IOC_LLOG_PRINT _IOWR('f', 192, OBD_IOC_DATA_TYPE) -#define OBD_IOC_LLOG_CANCEL _IOWR('f', 193, OBD_IOC_DATA_TYPE) -#define OBD_IOC_LLOG_REMOVE _IOWR('f', 194, OBD_IOC_DATA_TYPE) -#define OBD_IOC_LLOG_CHECK _IOWR('f', 195, OBD_IOC_DATA_TYPE) -/* OBD_IOC_LLOG_CATINFO is deprecated */ -#define OBD_IOC_LLOG_CATINFO _IOWR('f', 196, OBD_IOC_DATA_TYPE) - -/* #define ECHO_IOC_GET_STRIPE _IOWR('f', 200, OBD_IOC_DATA_TYPE) */ -/* #define ECHO_IOC_SET_STRIPE _IOWR('f', 201, OBD_IOC_DATA_TYPE) */ -/* #define ECHO_IOC_ENQUEUE _IOWR('f', 202, OBD_IOC_DATA_TYPE) */ -/* #define ECHO_IOC_CANCEL _IOWR('f', 203, OBD_IOC_DATA_TYPE) */ - -#define OBD_IOC_GET_OBJ_VERSION _IOR('f', 210, OBD_IOC_DATA_TYPE) - -/* <lustre/lustre_user.h> defines ioctl number 218-219 */ -#define OBD_IOC_GET_MNTOPT _IOW('f', 220, mntopt_t) - -#define OBD_IOC_ECHO_MD _IOR('f', 221, struct obd_ioctl_data) -#define OBD_IOC_ECHO_ALLOC_SEQ _IOWR('f', 222, struct obd_ioctl_data) - -#define OBD_IOC_START_LFSCK _IOWR('f', 230, OBD_IOC_DATA_TYPE) -#define OBD_IOC_STOP_LFSCK _IOW('f', 231, OBD_IOC_DATA_TYPE) -#define OBD_IOC_PAUSE_LFSCK _IOW('f', 232, OBD_IOC_DATA_TYPE) - -/* XXX _IOWR('f', 250, long) has been defined in - * libcfs/include/libcfs/libcfs_private.h for debug, don't use it - */ - /* Until such time as we get_info the per-stripe maximum from the OST, * we define this to be 2T - 4k, which is the ext3 maxbytes. */ diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index cacd472..0dae273 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -35,15 +35,6 @@ #include <linux/spinlock.h> -#define IOC_OSC_TYPE 'h' -#define IOC_OSC_MIN_NR 20 -#define IOC_OSC_SET_ACTIVE _IOWR(IOC_OSC_TYPE, 21, struct obd_device *) -#define IOC_OSC_MAX_NR 50 - -#define IOC_MDC_TYPE 'i' -#define IOC_MDC_MIN_NR 20 -#define IOC_MDC_MAX_NR 50 - #include "lustre/lustre_idl.h" #include "lustre_lib.h" #include "lu_ref.h" @@ -623,7 +614,6 @@ struct obd_llog_group { /* corresponds to one of the obd's */ #define OBD_DEVICE_MAGIC 0XAB5CD6EF -#define OBD_DEV_BY_DEVNAME 0xffffd0de struct lvfs_run_ctxt { struct dt_device *dt; diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 84bec03..257c9a4 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -46,8 +46,8 @@ #include "../include/obd_support.h" #include "../include/obd_class.h" +#include "../include/lustre/lustre_ioctl.h" #include "../include/lustre_lib.h" -#include "../include/lustre/lustre_idl.h" #include "../include/lustre_lite.h" #include "../include/lustre_dlm.h" #include "../include/lustre_fid.h" @@ -1543,7 +1543,7 @@ finish_req: case LL_IOC_LOV_SWAP_LAYOUTS: return -EPERM; - case LL_IOC_OBD_STATFS: + case IOC_OBD_STATFS: return ll_obd_statfs(inode, (void __user *)arg); case LL_IOC_LOV_GETSTRIPE: case LL_IOC_MDC_GETINFO: @@ -1708,9 +1708,6 @@ free_lmm: kvfree(lmm); return rc; } - case OBD_IOC_LLOG_CATINFO: { - return -EOPNOTSUPP; - } case OBD_IOC_QUOTACHECK: { struct obd_quotactl *oqctl; int error = 0; @@ -1768,7 +1765,7 @@ out_poll: kfree(check); return rc; } - case LL_IOC_QUOTACTL: { + case OBD_IOC_QUOTACTL: { struct if_quotactl *qctl; qctl = kzalloc(sizeof(*qctl), GFP_NOFS); diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 89e93dc..519db53 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -44,6 +44,7 @@ #include <linux/mount.h> #include "llite_internal.h" #include "../include/lustre/ll_fiemap.h" +#include "../include/lustre/lustre_ioctl.h" #include "../include/cl_object.h" diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index e320400..111264e 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -41,6 +41,7 @@ #include <linux/types.h> #include <linux/mm.h> +#include "../include/lustre/lustre_ioctl.h" #include "../include/lustre_lite.h" #include "../include/lustre_ha.h" #include "../include/lustre_dlm.h" diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index d07fd17..e516a84 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -51,6 +51,7 @@ #include "../include/cl_object.h" #include "../include/lustre_lite.h" #include "../include/lustre_fid.h" +#include "../include/lustre/lustre_ioctl.h" #include "../include/lustre_kernelcomm.h" #include "lmv_internal.h" diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index 9b92d55..d904f44 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -41,6 +41,7 @@ #include "../../include/linux/libcfs/libcfs.h" #include "../include/obd_support.h" +#include "../include/lustre/lustre_ioctl.h" #include "../include/lustre_lib.h" #include "../include/lustre_net.h" #include "../include/lustre/lustre_idl.h" diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 558f33b..394ef3c 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -39,6 +39,7 @@ # include <linux/utsname.h> #include "../include/lustre_acl.h" +#include "../include/lustre/lustre_ioctl.h" #include "../include/obd_class.h" #include "../include/lustre_lmv.h" #include "../include/lustre_fid.h" diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c index d9d2a19..6edf53e 100644 --- a/drivers/staging/lustre/lustre/obdclass/class_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c @@ -40,6 +40,7 @@ #include "../include/lprocfs_status.h" #include <linux/list.h> #include "../include/cl_object.h" +#include "../include/lustre/lustre_ioctl.h" #include "llog_internal.h" struct obd_device *obd_devs[MAX_OBD_DEVICES]; @@ -287,13 +288,6 @@ int class_handle_ioctl(unsigned int cmd, unsigned long arg) goto out; } - case OBD_IOC_CLOSE_UUID: { - CDEBUG(D_IOCTL, "closing all connections to uuid %s (NOOP)\n", - data->ioc_inlbuf1); - err = 0; - goto out; - } - case OBD_IOC_GETDEVICE: { int index = data->ioc_count; char *status, *str; diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c index 33342bf..27a72d8 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c @@ -65,6 +65,7 @@ #include "../../include/obd_support.h" #include "../../include/obd_class.h" #include "../../include/lprocfs_status.h" +#include "../../include/lustre/lustre_ioctl.h" #include "../../include/lustre_ver.h" /* buffer MUST be at least the size of obd_ioctl_hdr */ diff --git a/drivers/staging/lustre/lustre/obdclass/obd_config.c b/drivers/staging/lustre/lustre/obdclass/obd_config.c index 0eab123..6d0890f 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_config.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_config.c @@ -37,6 +37,7 @@ #define DEBUG_SUBSYSTEM S_CLASS #include "../include/obd_class.h" #include <linux/string.h> +#include "../include/lustre/lustre_ioctl.h" #include "../include/lustre_log.h" #include "../include/lprocfs_status.h" #include "../include/lustre_param.h" diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index 5b29c4a..2cb487b 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -41,6 +41,7 @@ #include "../include/cl_object.h" #include "../include/lustre_fid.h" #include "../include/lustre_acl.h" +#include "../include/lustre/lustre_ioctl.h" #include "../include/lustre_net.h" #include "echo_internal.h" diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index a2d948f..d231827 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -41,6 +41,7 @@ #include "../include/lustre_ha.h" #include "../include/lprocfs_status.h" +#include "../include/lustre/lustre_ioctl.h" #include "../include/lustre_debug.h" #include "../include/lustre_param.h" #include "../include/lustre_fid.h" -- cgit v0.10.2 From c3397e7e677b1186f0442293de415f1c070b9d5d Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Tue, 16 Aug 2016 16:18:52 -0400 Subject: staging: lustre: llite: add error handler in inode prepare phase Add error handler during inode inialization, so inode will become bad inode if something bad happens during inode prepare phase, otherwise the striped directory will not get its layout and being mis-regarded as normal directory. Signed-off-by: wang di <di.wang@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4930 Reviewed-on: http://review.whamcloud.com/10170 Reviewed-by: Lai Siyao <lai.siyao@intel.com> Reviewed-by: Fan Yong <fan.yong@intel.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 120aca3..e101dd8 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -766,8 +766,8 @@ int ll_setattr(struct dentry *de, struct iattr *attr); int ll_statfs(struct dentry *de, struct kstatfs *sfs); int ll_statfs_internal(struct super_block *sb, struct obd_statfs *osfs, __u64 max_age, __u32 flags); -void ll_update_inode(struct inode *inode, struct lustre_md *md); -void ll_read_inode2(struct inode *inode, void *opaque); +int ll_update_inode(struct inode *inode, struct lustre_md *md); +int ll_read_inode2(struct inode *inode, void *opaque); void ll_delete_inode(struct inode *inode); int ll_iocontrol(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 111264e..ea79ca3 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -464,7 +464,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, md_free_lustre_md(sbi->ll_md_exp, &lmd); ptlrpc_req_finished(request); - if (!(root)) { + if (IS_ERR(root)) { if (lmd.lsm) obd_free_memmd(sbi->ll_dt_exp, &lmd.lsm); #ifdef CONFIG_FS_POSIX_ACL @@ -1109,11 +1109,11 @@ static inline int lli_lsm_md_eq(const struct lmv_stripe_md *lsm_md1, lsm_md2->lsm_md_pool_name); } -static void ll_update_lsm_md(struct inode *inode, struct lustre_md *md) +static int ll_update_lsm_md(struct inode *inode, struct lustre_md *md) { struct ll_inode_info *lli = ll_i2info(inode); struct lmv_stripe_md *lsm = md->lmv; - int idx; + int idx, rc; LASSERT(S_ISDIR(inode->i_mode)); CDEBUG(D_INODE, "update lsm %p of "DFID"\n", lli->lli_lsm_md, @@ -1122,7 +1122,7 @@ static void ll_update_lsm_md(struct inode *inode, struct lustre_md *md) /* no striped information from request. */ if (!lsm) { if (!lli->lli_lsm_md) { - return; + return 0; } else if (lli->lli_lsm_md->lsm_md_magic == LMV_MAGIC_MIGRATE) { /* * migration is done, the temporay MIGRATE layout has @@ -1132,27 +1132,22 @@ static void ll_update_lsm_md(struct inode *inode, struct lustre_md *md) PFID(ll_inode2fid(inode))); lmv_free_memmd(lli->lli_lsm_md); lli->lli_lsm_md = NULL; - return; + return 0; } else { /* * The lustre_md from req does not include stripeEA, * see ll_md_setattr */ - return; + return 0; } } /* set the directory layout */ if (!lli->lli_lsm_md) { - int rc; - rc = ll_init_lsm_md(inode, md); - if (rc) { - CERROR("%s: init "DFID" failed: rc = %d\n", - ll_get_fsname(inode->i_sb, NULL, 0), - PFID(&lli->lli_fid), rc); - return; - } + if (rc) + return rc; + lli->lli_lsm_md = lsm; /* * set lsm_md to NULL, so the following free lustre_md @@ -1161,7 +1156,7 @@ static void ll_update_lsm_md(struct inode *inode, struct lustre_md *md) md->lmv = NULL; CDEBUG(D_INODE, "Set lsm %p magic %x to "DFID"\n", lsm, lsm->lsm_md_magic, PFID(ll_inode2fid(inode))); - return; + return 0; } /* Compare the old and new stripe information */ @@ -1185,7 +1180,7 @@ static void ll_update_lsm_md(struct inode *inode, struct lustre_md *md) lli->lli_lsm_md->lsm_md_layout_version, lsm->lsm_md_pool_name, lli->lli_lsm_md->lsm_md_pool_name); - return; + return -EIO; } for (idx = 0; idx < lli->lli_lsm_md->lsm_md_stripe_count; idx++) { @@ -1195,12 +1190,13 @@ static void ll_update_lsm_md(struct inode *inode, struct lustre_md *md) ll_get_fsname(inode->i_sb, NULL, 0), idx, PFID(&lli->lli_lsm_md->lsm_md_oinfo[idx].lmo_fid), PFID(&lsm->lsm_md_oinfo[idx].lmo_fid)); - return; + return -EIO; } } - md_update_lsm_md(ll_i2mdexp(inode), ll_i2info(inode)->lli_lsm_md, - md->body, ll_md_blocking_ast); + rc = md_update_lsm_md(ll_i2mdexp(inode), ll_i2info(inode)->lli_lsm_md, + md->body, ll_md_blocking_ast); + return rc; } void ll_clear_inode(struct inode *inode) @@ -1252,7 +1248,7 @@ void ll_clear_inode(struct inode *inode) if (S_ISDIR(inode->i_mode)) ll_dir_clear_lsm_md(inode); - else + if (S_ISREG(inode->i_mode) && !is_bad_inode(inode)) LASSERT(list_empty(&lli->lli_agl_list)); /* @@ -1320,7 +1316,7 @@ static int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data, op_data->op_handle = md.body->handle; op_data->op_ioepoch = md.body->ioepoch; - ll_update_inode(inode, &md); + rc = ll_update_inode(inode, &md); ptlrpc_req_finished(request); return rc; @@ -1679,7 +1675,7 @@ void ll_inode_size_unlock(struct inode *inode) mutex_unlock(&lli->lli_size_mutex); } -void ll_update_inode(struct inode *inode, struct lustre_md *md) +int ll_update_inode(struct inode *inode, struct lustre_md *md) { struct ll_inode_info *lli = ll_i2info(inode); struct mdt_body *body = md->body; @@ -1697,8 +1693,13 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) lli->lli_maxbytes = MAX_LFS_FILESIZE; } - if (S_ISDIR(inode->i_mode)) - ll_update_lsm_md(inode, md); + if (S_ISDIR(inode->i_mode)) { + int rc; + + rc = ll_update_lsm_md(inode, md); + if (rc) + return rc; + } #ifdef CONFIG_FS_POSIX_ACL if (body->valid & OBD_MD_FLACL) { @@ -1819,12 +1820,15 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) if (body->t_state & MS_RESTORE) lli->lli_flags |= LLIF_FILE_RESTORING; } + + return 0; } -void ll_read_inode2(struct inode *inode, void *opaque) +int ll_read_inode2(struct inode *inode, void *opaque) { struct lustre_md *md = opaque; struct ll_inode_info *lli = ll_i2info(inode); + int rc; CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p)\n", PFID(&lli->lli_fid), inode); @@ -1840,7 +1844,9 @@ void ll_read_inode2(struct inode *inode, void *opaque) LTIME_S(inode->i_atime) = 0; LTIME_S(inode->i_ctime) = 0; inode->i_rdev = 0; - ll_update_inode(inode, md); + rc = ll_update_inode(inode, md); + if (rc) + return rc; /* OIDEBUG(inode); */ @@ -1861,6 +1867,8 @@ void ll_read_inode2(struct inode *inode, void *opaque) init_special_inode(inode, inode->i_mode, inode->i_rdev); } + + return 0; } void ll_delete_inode(struct inode *inode) @@ -2127,7 +2135,9 @@ int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, goto cleanup; if (*inode) { - ll_update_inode(*inode, &md); + rc = ll_update_inode(*inode, &md); + if (rc) + goto out; } else { LASSERT(sb); @@ -2146,7 +2156,7 @@ int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, *inode = ll_iget(sb, cl_fid_build_ino(&md.body->fid1, sbi->ll_flags & LL_SBI_32BIT_API), &md); - if (!*inode) { + if (IS_ERR(*inode)) { #ifdef CONFIG_FS_POSIX_ACL if (md.posix_acl) { posix_acl_release(md.posix_acl); diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index f059882..6e11b99 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -96,41 +96,46 @@ static int ll_set_inode(struct inode *inode, void *opaque) return 0; } -/* - * Get an inode by inode number (already instantiated by the intent lookup). - * Returns inode or NULL +/** + * Get an inode by inode number(@hash), which is already instantiated by + * the intent lookup). */ struct inode *ll_iget(struct super_block *sb, ino_t hash, struct lustre_md *md) { struct inode *inode; + int rc = 0; LASSERT(hash != 0); inode = iget5_locked(sb, hash, ll_test_inode, ll_set_inode, md); - - if (inode) { - if (inode->i_state & I_NEW) { - int rc = 0; - - ll_read_inode2(inode, md); - if (S_ISREG(inode->i_mode) && - !ll_i2info(inode)->lli_clob) { - CDEBUG(D_INODE, - "%s: apply lsm %p to inode " DFID ".\n", - ll_get_fsname(sb, NULL, 0), md->lsm, - PFID(ll_inode2fid(inode))); - rc = cl_file_inode_init(inode, md); - } - if (rc != 0) { - iget_failed(inode); - inode = NULL; - } else { - unlock_new_inode(inode); - } - } else if (!(inode->i_state & (I_FREEING | I_CLEAR))) { - ll_update_inode(inode, md); - CDEBUG(D_VFSTRACE, "got inode: "DFID"(%p)\n", - PFID(&md->body->fid1), inode); + if (!inode) + return ERR_PTR(-ENOMEM); + + if (inode->i_state & I_NEW) { + rc = ll_read_inode2(inode, md); + if (!rc && S_ISREG(inode->i_mode) && + !ll_i2info(inode)->lli_clob) { + CDEBUG(D_INODE, "%s: apply lsm %p to inode "DFID"\n", + ll_get_fsname(sb, NULL, 0), md->lsm, + PFID(ll_inode2fid(inode))); + rc = cl_file_inode_init(inode, md); + } + if (rc) { + make_bad_inode(inode); + unlock_new_inode(inode); + iput(inode); + inode = ERR_PTR(rc); + } else { + unlock_new_inode(inode); + } + } else if (!(inode->i_state & (I_FREEING | I_CLEAR))) { + rc = ll_update_inode(inode, md); + CDEBUG(D_VFSTRACE, "got inode: "DFID"(%p): rc = %d\n", + PFID(&md->body->fid1), inode, rc); + if (rc) { + make_bad_inode(inode); + iput(inode); + inode = ERR_PTR(rc); } } return inode; -- cgit v0.10.2 From 31c5e95e11eadef9a10b7b1833caf75d86fb147a Mon Sep 17 00:00:00 2001 From: Chris Horn <hornc@cray.com> Date: Tue, 16 Aug 2016 16:18:53 -0400 Subject: staging: lustre: ptlrpc: Early replies need to honor at_max When determining whether an early reply can be sent the server will calculate the new deadline based on an offset from the request arrival time. However, when actually setting the new deadline the server offsets the current time. This can result in deadlines being extended more than at_max seconds past the request arrival time. Instead, the server should offset the arrival time when updating its request timeout. When a client receives an early reply it doesn't know the server side arrival time so we use the original sent time as an approximation. Signed-off-by: Chris Horn <hornc@cray.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4578 Reviewed-on: http://review.whamcloud.com/9100 Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: Christopher J. Morrone <chris.morrone.llnl@gmail.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index 549c62c..f2e71b4 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -385,10 +385,12 @@ static int ptlrpc_at_recv_early_reply(struct ptlrpc_request *req) spin_lock(&req->rq_lock); olddl = req->rq_deadline; /* - * server assumes it now has rq_timeout from when it sent the - * early reply, so client should give it at least that long. + * server assumes it now has rq_timeout from when the request + * arrived, so the client should give it at least that long. + * since we don't know the arrival time we'll use the original + * sent time */ - req->rq_deadline = ktime_get_real_seconds() + req->rq_timeout + + req->rq_deadline = req->rq_sent + req->rq_timeout + ptlrpc_at_get_net_latency(req); DEBUG_REQ(D_ADAPTTO, req, diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c index 3292e6e..af8ffbc 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/import.c +++ b/drivers/staging/lustre/lustre/ptlrpc/import.c @@ -1497,10 +1497,13 @@ EXPORT_SYMBOL(ptlrpc_disconnect_import); /* Adaptive Timeout utils */ extern unsigned int at_min, at_max, at_history; -/* Bin into timeslices using AT_BINS bins. - * This gives us a max of the last binlimit*AT_BINS secs without the storage, - * but still smoothing out a return to normalcy from a slow response. - * (E.g. remember the maximum latency in each minute of the last 4 minutes.) +/* + *Update at_current with the specified value (bounded by at_min and at_max), + * as well as the AT history "bins". + * - Bin into timeslices using AT_BINS bins. + * - This gives us a max of the last at_history seconds without the storage, + * but still smoothing out a return to normalcy from a slow response. + * - (E.g. remember the maximum latency in each minute of the last 4 minutes.) */ int at_measured(struct adaptive_timeout *at, unsigned int val) { diff --git a/drivers/staging/lustre/lustre/ptlrpc/service.c b/drivers/staging/lustre/lustre/ptlrpc/service.c index 4788c49..30d8b72 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/service.c +++ b/drivers/staging/lustre/lustre/ptlrpc/service.c @@ -1005,13 +1005,16 @@ ptlrpc_at_remove_timed(struct ptlrpc_request *req) array->paa_count--; } +/* + * Attempt to extend the request deadline by sending an early reply to the + * client. + */ static int ptlrpc_at_send_early_reply(struct ptlrpc_request *req) { struct ptlrpc_service_part *svcpt = req->rq_rqbd->rqbd_svcpt; struct ptlrpc_request *reqcopy; struct lustre_msg *reqmsg; long olddl = req->rq_deadline - ktime_get_real_seconds(); - time64_t newdl; int rc; /* deadline is when the client expects us to reply, margin is the @@ -1039,8 +1042,13 @@ static int ptlrpc_at_send_early_reply(struct ptlrpc_request *req) return -ENOSYS; } - /* Fake our processing time into the future to ask the clients - * for some extra amount of time + /* + * We want to extend the request deadline by at_extra seconds, + * so we set our service estimate to reflect how much time has + * passed since this request arrived plus an additional + * at_extra seconds. The client will calculate the new deadline + * based on this service estimate (plus some additional time to + * account for network latency). See ptlrpc_at_recv_early_reply */ at_measured(&svcpt->scp_at_estimate, at_extra + ktime_get_real_seconds() - req->rq_arrival_time.tv_sec); @@ -1056,7 +1064,6 @@ static int ptlrpc_at_send_early_reply(struct ptlrpc_request *req) ktime_get_real_seconds()); return -ETIMEDOUT; } - newdl = ktime_get_real_seconds() + at_get(&svcpt->scp_at_estimate); reqcopy = ptlrpc_request_cache_alloc(GFP_NOFS); if (!reqcopy) @@ -1110,7 +1117,8 @@ static int ptlrpc_at_send_early_reply(struct ptlrpc_request *req) if (!rc) { /* Adjust our own deadline to what we told the client */ - req->rq_deadline = newdl; + req->rq_deadline = req->rq_arrival_time.tv_sec + + at_get(&svcpt->scp_at_estimate); req->rq_early_count++; /* number sent, server side */ } else { DEBUG_REQ(D_ERROR, req, "Early reply send failed %d", rc); -- cgit v0.10.2 From 8f18c8a48b736c2f731e3e2255189c98e79bc22a Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Tue, 16 Aug 2016 16:18:54 -0400 Subject: staging: lustre: lmv: separate master object with master stripe Separate master stripe with master object, so 1. stripeEA only exists on master object. 2. sub-stripe object will be inserted into master object as sub-directory, and it can get the master object by "..". By this, it will remove those specilities for stripe0 in LMV and LOD. And also simplify LFSCK, i.e. consistency check would be easier. When then master object becomes an orphan, we should mark all of its sub-stripes as dead object as well, otherwise client might still be able to create files under these stripes. A few fixes for striped directory layout lock: 1. stripe 0 should be locked as EX, same as other stripes. 2. Acquire the layout for directory, when it is being unliked. Signed-off-by: wang di <di.wang@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4690 Reviewed-on: http://review.whamcloud.com/9511 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 3444add..8736826 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -2497,18 +2497,52 @@ struct lmv_desc { struct obd_uuid ld_uuid; }; -/* lmv structures */ -#define LMV_MAGIC_V1 0x0CD10CD0 /* normal stripe lmv magic */ -#define LMV_USER_MAGIC 0x0CD20CD0 /* default lmv magic*/ -#define LMV_MAGIC_MIGRATE 0x0CD30CD0 /* migrate stripe lmv magic */ -#define LMV_MAGIC LMV_MAGIC_V1 +/* LMV layout EA, and it will be stored both in master and slave object */ +struct lmv_mds_md_v1 { + __u32 lmv_magic; + __u32 lmv_stripe_count; + __u32 lmv_master_mdt_index; /* On master object, it is master + * MDT index, on slave object, it + * is stripe index of the slave obj + */ + __u32 lmv_hash_type; /* dir stripe policy, i.e. indicate + * which hash function to be used, + * Note: only lower 16 bits is being + * used for now. Higher 16 bits will + * be used to mark the object status, + * for example migrating or dead. + */ + __u32 lmv_layout_version; /* Used for directory restriping */ + __u32 lmv_padding; + struct lu_fid lmv_master_fid; /* The FID of the master object, which + * is the namespace-visible dir FID + */ + char lmv_pool_name[LOV_MAXPOOLNAME]; /* pool name */ + struct lu_fid lmv_stripe_fids[0]; /* FIDs for each stripe */ +}; +#define LMV_MAGIC_V1 0x0CD20CD0 /* normal stripe lmv magic */ +#define LMV_MAGIC LMV_MAGIC_V1 + +/* #define LMV_USER_MAGIC 0x0CD30CD0 */ +#define LMV_MAGIC_STRIPE 0x0CD40CD0 /* magic for dir sub_stripe */ + +/* + *Right now only the lower part(0-16bits) of lmv_hash_type is being used, + * and the higher part will be the flag to indicate the status of object, + * for example the object is being migrated. And the hash function + * might be interpreted differently with different flags. + */ enum lmv_hash_type { LMV_HASH_TYPE_ALL_CHARS = 1, LMV_HASH_TYPE_FNV_1A_64 = 2, - LMV_HASH_TYPE_MIGRATION = 3, }; +#define LMV_HASH_TYPE_MASK 0x0000ffff + +#define LMV_HASH_FLAG_MIGRATION 0x80000000 +#define LMV_HASH_FLAG_DEAD 0x40000000 + #define LMV_HASH_NAME_ALL_CHARS "all_char" #define LMV_HASH_NAME_FNV_1A_64 "fnv_1a_64" @@ -2540,19 +2574,6 @@ static inline __u64 lustre_hash_fnv_1a_64(const void *buf, size_t size) return hash; } -struct lmv_mds_md_v1 { - __u32 lmv_magic; - __u32 lmv_stripe_count; /* stripe count */ - __u32 lmv_master_mdt_index; /* master MDT index */ - __u32 lmv_hash_type; /* dir stripe policy, i.e. indicate - * which hash function to be used - */ - __u32 lmv_layout_version; /* Used for directory restriping */ - __u32 lmv_padding; - char lmv_pool_name[LOV_MAXPOOLNAME]; /* pool name */ - struct lu_fid lmv_stripe_fids[0]; /* FIDs for each stripe */ -}; - union lmv_mds_md { __u32 lmv_magic; struct lmv_mds_md_v1 lmv_md_v1; @@ -2566,8 +2587,7 @@ static inline ssize_t lmv_mds_md_size(int stripe_count, unsigned int lmm_magic) ssize_t len = -EINVAL; switch (lmm_magic) { - case LMV_MAGIC_V1: - case LMV_MAGIC_MIGRATE: { + case LMV_MAGIC_V1: { struct lmv_mds_md_v1 *lmm1; len = sizeof(*lmm1); @@ -2583,7 +2603,6 @@ static inline int lmv_mds_md_stripe_count_get(const union lmv_mds_md *lmm) { switch (le32_to_cpu(lmm->lmv_magic)) { case LMV_MAGIC_V1: - case LMV_MAGIC_MIGRATE: return le32_to_cpu(lmm->lmv_md_v1.lmv_stripe_count); case LMV_USER_MAGIC: return le32_to_cpu(lmm->lmv_user_md.lum_stripe_count); @@ -2599,7 +2618,6 @@ static inline int lmv_mds_md_stripe_count_set(union lmv_mds_md *lmm, switch (le32_to_cpu(lmm->lmv_magic)) { case LMV_MAGIC_V1: - case LMV_MAGIC_MIGRATE: lmm->lmv_md_v1.lmv_stripe_count = cpu_to_le32(stripe_count); break; case LMV_USER_MAGIC: diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index 75a78a3..4b2553c 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -269,8 +269,7 @@ struct ost_id { #define LOV_USER_MAGIC_JOIN_V1 0x0BD20BD0 #define LOV_USER_MAGIC_V3 0x0BD30BD0 -#define LMV_MAGIC_V1 0x0CD10CD0 /*normal stripe lmv magic */ -#define LMV_USER_MAGIC 0x0CD20CD0 /*default lmv magic*/ +#define LMV_USER_MAGIC 0x0CD30CD0 /*default lmv magic*/ #define LOV_PATTERN_RAID0 0x001 #define LOV_PATTERN_RAID1 0x002 diff --git a/drivers/staging/lustre/lustre/include/lustre_lmv.h b/drivers/staging/lustre/lustre/include/lustre_lmv.h index feee981..1dd3e92 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lmv.h +++ b/drivers/staging/lustre/lustre/include/lustre_lmv.h @@ -48,10 +48,33 @@ struct lmv_stripe_md { __u32 lsm_md_layout_version; __u32 lsm_md_default_count; __u32 lsm_md_default_index; + struct lu_fid lsm_md_master_fid; char lsm_md_pool_name[LOV_MAXPOOLNAME]; struct lmv_oinfo lsm_md_oinfo[0]; }; +static inline bool +lsm_md_eq(const struct lmv_stripe_md *lsm1, const struct lmv_stripe_md *lsm2) +{ + int idx; + + if (lsm1->lsm_md_magic != lsm2->lsm_md_magic || + lsm1->lsm_md_stripe_count != lsm2->lsm_md_stripe_count || + lsm1->lsm_md_master_mdt_index != lsm2->lsm_md_master_mdt_index || + lsm1->lsm_md_hash_type != lsm2->lsm_md_hash_type || + lsm1->lsm_md_layout_version != lsm2->lsm_md_layout_version || + !strcmp(lsm1->lsm_md_pool_name, lsm2->lsm_md_pool_name)) + return false; + + for (idx = 0; idx < lsm1->lsm_md_stripe_count; idx++) { + if (!lu_fid_eq(&lsm1->lsm_md_oinfo[idx].lmo_fid, + &lsm2->lsm_md_oinfo[idx].lmo_fid)) + return false; + } + + return true; +} + union lmv_mds_md; int lmv_unpack_md(struct obd_export *exp, struct lmv_stripe_md **lsmp, @@ -106,7 +129,6 @@ static inline void lmv_cpu_to_le(union lmv_mds_md *lmv_dst, { switch (lmv_src->lmv_magic) { case LMV_MAGIC_V1: - case LMV_MAGIC_MIGRATE: lmv1_cpu_to_le(&lmv_dst->lmv_md_v1, &lmv_src->lmv_md_v1); break; default: @@ -119,7 +141,6 @@ static inline void lmv_le_to_cpu(union lmv_mds_md *lmv_dst, { switch (le32_to_cpu(lmv_src->lmv_magic)) { case LMV_MAGIC_V1: - case LMV_MAGIC_MIGRATE: lmv1_le_to_cpu(&lmv_dst->lmv_md_v1, &lmv_src->lmv_md_v1); break; default: diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 0dae273..52020a9 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -917,8 +917,8 @@ struct obd_ops { int (*fid_fini)(struct obd_device *obd); /* Allocate new fid according to passed @hint. */ - int (*fid_alloc)(struct obd_export *exp, struct lu_fid *fid, - struct md_op_data *op_data); + int (*fid_alloc)(const struct lu_env *env, struct obd_export *exp, + struct lu_fid *fid, struct md_op_data *op_data); /* * Object with @fid is getting deleted, we may want to do something diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index de808ee..a288995 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -930,7 +930,8 @@ static inline int obd_fid_fini(struct obd_device *obd) return rc; } -static inline int obd_fid_alloc(struct obd_export *exp, +static inline int obd_fid_alloc(const struct lu_env *env, + struct obd_export *exp, struct lu_fid *fid, struct md_op_data *op_data) { @@ -939,7 +940,7 @@ static inline int obd_fid_alloc(struct obd_export *exp, EXP_CHECK_DT_OP(exp, fid_alloc); EXP_COUNTER_INCREMENT(exp, fid_alloc); - rc = OBP(exp->exp_obd, fid_alloc)(exp, fid, op_data); + rc = OBP(exp->exp_obd, fid_alloc)(env, exp, fid, op_data); return rc; } diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 257c9a4..47fbcd2 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -883,7 +883,6 @@ int ll_dir_getstripe(struct inode *inode, void **plmm, int *plmm_size, lustre_swab_lov_user_md_v3((struct lov_user_md_v3 *)lmm); break; case LMV_USER_MAGIC: - case LMV_MAGIC_MIGRATE: if (cpu_to_le32(LMV_USER_MAGIC) != LMV_USER_MAGIC) lustre_swab_lmv_user_md((struct lmv_user_md *)lmm); break; @@ -1471,7 +1470,7 @@ lmv_out_free: rc = ll_dir_getstripe(inode, (void **)&lmm, &lmmsize, &request, valid); - if (rc && rc != -ENODATA) + if (rc) goto finish_req; /* Get default LMV EA */ @@ -1490,14 +1489,7 @@ lmv_out_free: goto finish_req; } - /* Get normal LMV EA */ - if (rc == -ENODATA) { - stripe_count = 1; - } else { - LASSERT(lmm); - stripe_count = lmv_mds_md_stripe_count_get(lmm); - } - + stripe_count = lmv_mds_md_stripe_count_get(lmm); lum_size = lmv_user_md_size(stripe_count, LMV_MAGIC_V1); tmp = kzalloc(lum_size, GFP_NOFS); if (!tmp) { @@ -1505,28 +1497,25 @@ lmv_out_free: goto finish_req; } - tmp->lum_magic = LMV_MAGIC_V1; - tmp->lum_stripe_count = 1; mdt_index = ll_get_mdt_idx(inode); if (mdt_index < 0) { rc = -ENOMEM; goto out_tmp; } + tmp->lum_magic = LMV_MAGIC_V1; + tmp->lum_stripe_count = 0; tmp->lum_stripe_offset = mdt_index; - tmp->lum_objects[0].lum_mds = mdt_index; - tmp->lum_objects[0].lum_fid = *ll_inode2fid(inode); - for (i = 1; i < stripe_count; i++) { - struct lmv_mds_md_v1 *lmm1; - - lmm1 = &lmm->lmv_md_v1; - mdt_index = ll_get_mdt_idx_by_fid(sbi, - &lmm1->lmv_stripe_fids[i]); + for (i = 0; i < stripe_count; i++) { + struct lu_fid *fid; + + fid = &lmm->lmv_md_v1.lmv_stripe_fids[i]; + mdt_index = ll_get_mdt_idx_by_fid(sbi, fid); if (mdt_index < 0) { rc = mdt_index; goto out_tmp; } tmp->lum_objects[i].lum_mds = mdt_index; - tmp->lum_objects[i].lum_fid = lmm1->lmv_stripe_fids[i]; + tmp->lum_objects[i].lum_fid = *fid; tmp->lum_stripe_count++; } diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index ea79ca3..2f6e770 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -1042,9 +1042,9 @@ static struct inode *ll_iget_anon_dir(struct super_block *sb, ll_lli_init(lli); LASSERT(lsm); - /* master stripe FID */ - lli->lli_pfid = lsm->lsm_md_oinfo[0].lmo_fid; - CDEBUG(D_INODE, "lli %p master "DFID" slave "DFID"\n", + /* master object FID */ + lli->lli_pfid = body->fid1; + CDEBUG(D_INODE, "lli %p slave "DFID" master "DFID"\n", lli, PFID(fid), PFID(&lli->lli_pfid)); unlock_new_inode(inode); } @@ -1067,23 +1067,24 @@ static int ll_init_lsm_md(struct inode *inode, struct lustre_md *md) for (i = 0; i < lsm->lsm_md_stripe_count; i++) { fid = &lsm->lsm_md_oinfo[i].lmo_fid; LASSERT(!lsm->lsm_md_oinfo[i].lmo_root); - if (!i) { + /* Unfortunately ll_iget will call ll_update_inode, + * where the initialization of slave inode is slightly + * different, so it reset lsm_md to NULL to avoid + * initializing lsm for slave inode. + */ + /* For migrating inode, master stripe and master object will + * be same, so we only need assign this inode + */ + if (lsm->lsm_md_hash_type & LMV_HASH_FLAG_MIGRATION && !i) lsm->lsm_md_oinfo[i].lmo_root = inode; - } else { - /* - * Unfortunately ll_iget will call ll_update_inode, - * where the initialization of slave inode is slightly - * different, so it reset lsm_md to NULL to avoid - * initializing lsm for slave inode. - */ + else lsm->lsm_md_oinfo[i].lmo_root = ll_iget_anon_dir(inode->i_sb, fid, md); - if (IS_ERR(lsm->lsm_md_oinfo[i].lmo_root)) { - int rc = PTR_ERR(lsm->lsm_md_oinfo[i].lmo_root); + if (IS_ERR(lsm->lsm_md_oinfo[i].lmo_root)) { + int rc = PTR_ERR(lsm->lsm_md_oinfo[i].lmo_root); - lsm->lsm_md_oinfo[i].lmo_root = NULL; - return rc; - } + lsm->lsm_md_oinfo[i].lmo_root = NULL; + return rc; } } @@ -1113,7 +1114,7 @@ static int ll_update_lsm_md(struct inode *inode, struct lustre_md *md) { struct ll_inode_info *lli = ll_i2info(inode); struct lmv_stripe_md *lsm = md->lmv; - int idx, rc; + int rc; LASSERT(S_ISDIR(inode->i_mode)); CDEBUG(D_INODE, "update lsm %p of "DFID"\n", lli->lli_lsm_md, @@ -1123,7 +1124,8 @@ static int ll_update_lsm_md(struct inode *inode, struct lustre_md *md) if (!lsm) { if (!lli->lli_lsm_md) { return 0; - } else if (lli->lli_lsm_md->lsm_md_magic == LMV_MAGIC_MIGRATE) { + } else if (lli->lli_lsm_md->lsm_md_hash_type & + LMV_HASH_FLAG_MIGRATION) { /* * migration is done, the temporay MIGRATE layout has * been removed @@ -1160,43 +1162,40 @@ static int ll_update_lsm_md(struct inode *inode, struct lustre_md *md) } /* Compare the old and new stripe information */ - if (!lli_lsm_md_eq(lli->lli_lsm_md, lsm)) { - CERROR("inode %p %lu mismatch\n" - " new(%p) vs lli_lsm_md(%p):\n" - " magic: %x %x\n" - " count: %x %x\n" - " master: %x %x\n" - " hash_type: %x %x\n" - " layout: %x %x\n" - " pool: %s %s\n", - inode, inode->i_ino, lsm, lli->lli_lsm_md, - lsm->lsm_md_magic, lli->lli_lsm_md->lsm_md_magic, + if (!lsm_md_eq(lli->lli_lsm_md, lsm)) { + struct lmv_stripe_md *old_lsm = lli->lli_lsm_md; + int idx; + + CERROR("%s: inode "DFID"(%p)'s lmv layout mismatch (%p)/(%p) magic:0x%x/0x%x stripe count: %d/%d master_mdt: %d/%d hash_type:0x%x/0x%x layout: 0x%x/0x%x pool:%s/%s\n", + ll_get_fsname(inode->i_sb, NULL, 0), PFID(&lli->lli_fid), + inode, lsm, old_lsm, + lsm->lsm_md_magic, old_lsm->lsm_md_magic, lsm->lsm_md_stripe_count, - lli->lli_lsm_md->lsm_md_stripe_count, + old_lsm->lsm_md_stripe_count, lsm->lsm_md_master_mdt_index, - lli->lli_lsm_md->lsm_md_master_mdt_index, - lsm->lsm_md_hash_type, lli->lli_lsm_md->lsm_md_hash_type, + old_lsm->lsm_md_master_mdt_index, + lsm->lsm_md_hash_type, old_lsm->lsm_md_hash_type, lsm->lsm_md_layout_version, - lli->lli_lsm_md->lsm_md_layout_version, + old_lsm->lsm_md_layout_version, lsm->lsm_md_pool_name, - lli->lli_lsm_md->lsm_md_pool_name); - return -EIO; - } + old_lsm->lsm_md_pool_name); + + for (idx = 0; idx < old_lsm->lsm_md_stripe_count; idx++) { + CERROR("%s: sub FIDs in old lsm idx %d, old: "DFID"\n", + ll_get_fsname(inode->i_sb, NULL, 0), idx, + PFID(&old_lsm->lsm_md_oinfo[idx].lmo_fid)); + } - for (idx = 0; idx < lli->lli_lsm_md->lsm_md_stripe_count; idx++) { - if (!lu_fid_eq(&lli->lli_lsm_md->lsm_md_oinfo[idx].lmo_fid, - &lsm->lsm_md_oinfo[idx].lmo_fid)) { - CERROR("%s: FID in lsm mismatch idx %d, old: "DFID" new:"DFID"\n", + for (idx = 0; idx < lsm->lsm_md_stripe_count; idx++) { + CERROR("%s: sub FIDs in new lsm idx %d, new: "DFID"\n", ll_get_fsname(inode->i_sb, NULL, 0), idx, - PFID(&lli->lli_lsm_md->lsm_md_oinfo[idx].lmo_fid), PFID(&lsm->lsm_md_oinfo[idx].lmo_fid)); - return -EIO; } + + return -EIO; } - rc = md_update_lsm_md(ll_i2mdexp(inode), ll_i2info(inode)->lli_lsm_md, - md->body, ll_md_blocking_ast); - return rc; + return 0; } void ll_clear_inode(struct inode *inode) diff --git a/drivers/staging/lustre/lustre/lmv/lmv_intent.c b/drivers/staging/lustre/lustre/lmv/lmv_intent.c index d7e165f..7f81e78 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_intent.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_intent.c @@ -173,9 +173,6 @@ int lmv_revalidate_slaves(struct obd_export *exp, struct mdt_body *mbody, * revalidate slaves has some problems, temporarily return, * we may not need that */ - if (lsm->lsm_md_stripe_count <= 1) - return 0; - op_data = kzalloc(sizeof(*op_data), GFP_NOFS); if (!op_data) return -ENOMEM; @@ -194,14 +191,6 @@ int lmv_revalidate_slaves(struct obd_export *exp, struct mdt_body *mbody, fid = lsm->lsm_md_oinfo[i].lmo_fid; inode = lsm->lsm_md_oinfo[i].lmo_root; - if (!i) { - if (mbody) { - body = mbody; - goto update; - } else { - goto release_lock; - } - } /* * Prepare op_data for revalidating. Note that @fid2 shluld be @@ -237,7 +226,7 @@ int lmv_revalidate_slaves(struct obd_export *exp, struct mdt_body *mbody, body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); LASSERT(body); -update: + if (unlikely(body->nlink < 2)) { CERROR("%s: nlink %d < 2 corrupt stripe %d "DFID":" DFID"\n", obd->obd_name, body->nlink, i, @@ -256,10 +245,6 @@ update: goto cleanup; } - if (i) - md_set_lock_data(tgt->ltd_exp, &lockh->cookie, - inode, NULL); - i_size_write(inode, body->size); set_nlink(inode, body->nlink); LTIME_S(inode->i_atime) = body->atime; @@ -269,8 +254,8 @@ update: if (req) ptlrpc_req_finished(req); } -release_lock: - size += i_size_read(inode); + + md_set_lock_data(tgt->ltd_exp, &lockh->cookie, inode, NULL); if (i != 0) nlink += inode->i_nlink - 2; @@ -361,7 +346,7 @@ static int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data, * fid and setup FLD for it. */ op_data->op_fid3 = op_data->op_fid2; - rc = lmv_fid_alloc(exp, &op_data->op_fid2, op_data); + rc = lmv_fid_alloc(NULL, exp, &op_data->op_fid2, op_data); if (rc != 0) return rc; } @@ -453,7 +438,7 @@ static int lmv_intent_lookup(struct obd_export *exp, } return rc; } else if (it_disposition(it, DISP_LOOKUP_NEG) && lsm && - lsm->lsm_md_magic == LMV_MAGIC_MIGRATE) { + lsm->lsm_md_magic & LMV_HASH_FLAG_MIGRATION) { /* * For migrating directory, if it can not find the child in * the source directory(master stripe), try the targeting diff --git a/drivers/staging/lustre/lustre/lmv/lmv_internal.h b/drivers/staging/lustre/lustre/lmv/lmv_internal.h index ed02927..dbd1da6 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_internal.h +++ b/drivers/staging/lustre/lustre/lmv/lmv_internal.h @@ -52,8 +52,8 @@ int lmv_intent_lock(struct obd_export *exp, struct md_op_data *op_data, int lmv_fld_lookup(struct lmv_obd *lmv, const struct lu_fid *fid, u32 *mds); int __lmv_fid_alloc(struct lmv_obd *lmv, struct lu_fid *fid, u32 mds); -int lmv_fid_alloc(struct obd_export *exp, struct lu_fid *fid, - struct md_op_data *op_data); +int lmv_fid_alloc(const struct lu_env *env, struct obd_export *exp, + struct lu_fid *fid, struct md_op_data *op_data); int lmv_unpack_md(struct obd_export *exp, struct lmv_stripe_md **lsmp, const union lmv_mds_md *lmm, int stripe_count); diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index e516a84..03594f0 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -80,41 +80,35 @@ lmv_hash_fnv1a(unsigned int count, const char *name, int namelen) return do_div(hash, count); } -int lmv_name_to_stripe_index(enum lmv_hash_type hashtype, - unsigned int max_mdt_index, +int lmv_name_to_stripe_index(__u32 lmv_hash_type, unsigned int stripe_count, const char *name, int namelen) { + __u32 hash_type = lmv_hash_type & LMV_HASH_TYPE_MASK; int idx; LASSERT(namelen > 0); - if (max_mdt_index <= 1) + if (stripe_count <= 1) return 0; - switch (hashtype) { + /* for migrating object, always start from 0 stripe */ + if (lmv_hash_type & LMV_HASH_FLAG_MIGRATION) + return 0; + + switch (hash_type) { case LMV_HASH_TYPE_ALL_CHARS: - idx = lmv_hash_all_chars(max_mdt_index, name, namelen); + idx = lmv_hash_all_chars(stripe_count, name, namelen); break; case LMV_HASH_TYPE_FNV_1A_64: - idx = lmv_hash_fnv1a(max_mdt_index, name, namelen); + idx = lmv_hash_fnv1a(stripe_count, name, namelen); break; - /* - * LMV_HASH_TYPE_MIGRATION means the file is being migrated, - * and the file should be accessed by client, except for - * lookup(see lmv_intent_lookup), return -EACCES here - */ - case LMV_HASH_TYPE_MIGRATION: - CERROR("%.*s is being migrated: rc = %d\n", namelen, - name, -EACCES); - return -EACCES; default: - CERROR("Unknown hash type 0x%x\n", hashtype); + CERROR("Unknown hash type 0x%x\n", hash_type); return -EINVAL; } CDEBUG(D_INFO, "name %.*s hash_type %d idx %d\n", namelen, name, - hashtype, idx); + hash_type, idx); - LASSERT(idx < max_mdt_index); return idx; } @@ -1287,7 +1281,7 @@ int __lmv_fid_alloc(struct lmv_obd *lmv, struct lu_fid *fid, u32 mds) /* * Asking underlaying tgt layer to allocate new fid. */ - rc = obd_fid_alloc(tgt->ltd_exp, fid, NULL); + rc = obd_fid_alloc(NULL, tgt->ltd_exp, fid, NULL); if (rc > 0) { LASSERT(fid_is_sane(fid)); rc = 0; @@ -1298,8 +1292,8 @@ out: return rc; } -int lmv_fid_alloc(struct obd_export *exp, struct lu_fid *fid, - struct md_op_data *op_data) +int lmv_fid_alloc(const struct lu_env *env, struct obd_export *exp, + struct lu_fid *fid, struct md_op_data *op_data) { struct obd_device *obd = class_exp2obd(exp); struct lmv_obd *lmv = &obd->u.lmv; @@ -1695,9 +1689,7 @@ struct lmv_tgt_desc struct lmv_stripe_md *lsm = op_data->op_mea1; struct lmv_tgt_desc *tgt; - if (!lsm || lsm->lsm_md_stripe_count <= 1 || - !op_data->op_namelen || - lsm->lsm_md_magic == LMV_MAGIC_MIGRATE) { + if (!lsm || !op_data->op_namelen) { tgt = lmv_find_target(lmv, fid); if (IS_ERR(tgt)) return tgt; @@ -1737,7 +1729,7 @@ static int lmv_create(struct obd_export *exp, struct md_op_data *op_data, op_data->op_namelen, op_data->op_name, PFID(&op_data->op_fid1), op_data->op_mds); - rc = lmv_fid_alloc(exp, &op_data->op_fid2, op_data); + rc = lmv_fid_alloc(NULL, exp, &op_data->op_fid2, op_data); if (rc) return rc; @@ -2060,7 +2052,7 @@ static int lmv_rename(struct obd_export *exp, struct md_op_data *op_data, if (op_data->op_cli_flags & CLI_MIGRATE) { LASSERTF(fid_is_sane(&op_data->op_fid3), "invalid FID "DFID"\n", PFID(&op_data->op_fid3)); - rc = lmv_fid_alloc(exp, &op_data->op_fid2, op_data); + rc = lmv_fid_alloc(NULL, exp, &op_data->op_fid2, op_data); if (rc) return rc; src_tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid3); @@ -2365,8 +2357,7 @@ retry: return PTR_ERR(tgt); /* For striped dir, we need to locate the parent as well */ - if (op_data->op_mea1 && - op_data->op_mea1->lsm_md_stripe_count > 1) { + if (op_data->op_mea1) { struct lmv_tgt_desc *tmp; LASSERT(op_data->op_name && op_data->op_namelen); @@ -2679,9 +2670,13 @@ static int lmv_unpack_md_v1(struct obd_export *exp, struct lmv_stripe_md *lsm, lsm->lsm_md_master_mdt_index = le32_to_cpu(lmm1->lmv_master_mdt_index); lsm->lsm_md_hash_type = le32_to_cpu(lmm1->lmv_hash_type); lsm->lsm_md_layout_version = le32_to_cpu(lmm1->lmv_layout_version); + fid_le_to_cpu(&lsm->lsm_md_master_fid, &lmm1->lmv_master_fid); cplen = strlcpy(lsm->lsm_md_pool_name, lmm1->lmv_pool_name, sizeof(lsm->lsm_md_pool_name)); + if (!fid_is_sane(&lsm->lsm_md_master_fid)) + return -EPROTO; + if (cplen >= sizeof(lsm->lsm_md_pool_name)) return -E2BIG; @@ -2719,7 +2714,13 @@ int lmv_unpack_md(struct obd_export *exp, struct lmv_stripe_md **lsmp, int i; for (i = 1; i < lsm->lsm_md_stripe_count; i++) { - if (lsm->lsm_md_oinfo[i].lmo_root) + /* + * For migrating inode, the master stripe and master + * object will be the same, so do not need iput, see + * ll_update_lsm_md + */ + if (!(lsm->lsm_md_hash_type & LMV_HASH_FLAG_MIGRATION && + !i) && lsm->lsm_md_oinfo[i].lmo_root) iput(lsm->lsm_md_oinfo[i].lmo_root); } @@ -2739,9 +2740,11 @@ int lmv_unpack_md(struct obd_export *exp, struct lmv_stripe_md **lsmp, return 0; } + if (le32_to_cpu(lmm->lmv_magic) == LMV_MAGIC_STRIPE) + return -EPERM; + /* Unpack memmd */ if (le32_to_cpu(lmm->lmv_magic) != LMV_MAGIC_V1 && - le32_to_cpu(lmm->lmv_magic) != LMV_MAGIC_MIGRATE && le32_to_cpu(lmm->lmv_magic) != LMV_USER_MAGIC) { CERROR("%s: invalid lmv magic %x: rc = %d\n", exp->exp_obd->obd_name, le32_to_cpu(lmm->lmv_magic), @@ -2749,8 +2752,7 @@ int lmv_unpack_md(struct obd_export *exp, struct lmv_stripe_md **lsmp, return -EIO; } - if (le32_to_cpu(lmm->lmv_magic) == LMV_MAGIC_V1 || - le32_to_cpu(lmm->lmv_magic) == LMV_MAGIC_MIGRATE) + if (le32_to_cpu(lmm->lmv_magic) == LMV_MAGIC_V1) lsm_size = lmv_stripe_md_size(lmv_mds_md_stripe_count_get(lmm)); else /** @@ -2769,7 +2771,6 @@ int lmv_unpack_md(struct obd_export *exp, struct lmv_stripe_md **lsmp, switch (le32_to_cpu(lmm->lmv_magic)) { case LMV_MAGIC_V1: - case LMV_MAGIC_MIGRATE: rc = lmv_unpack_md_v1(exp, lsm, &lmm->lmv_md_v1); break; default: @@ -3067,9 +3068,6 @@ static int lmv_quotacheck(struct obd_device *unused, struct obd_export *exp, int lmv_update_lsm_md(struct obd_export *exp, struct lmv_stripe_md *lsm, struct mdt_body *body, ldlm_blocking_callback cb_blocking) { - if (lsm->lsm_md_stripe_count <= 1) - return 0; - return lmv_revalidate_slaves(exp, body, lsm, cb_blocking, 0); } diff --git a/drivers/staging/lustre/lustre/mdc/mdc_internal.h b/drivers/staging/lustre/lustre/mdc/mdc_internal.h index 53b4063..00e8435 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_internal.h +++ b/drivers/staging/lustre/lustre/mdc/mdc_internal.h @@ -87,8 +87,8 @@ int mdc_resource_get_unused(struct obd_export *exp, const struct lu_fid *fid, struct list_head *cancels, enum ldlm_mode mode, __u64 bits); /* mdc/mdc_request.c */ -int mdc_fid_alloc(struct obd_export *exp, struct lu_fid *fid, - struct md_op_data *op_data); +int mdc_fid_alloc(const struct lu_env *env, struct obd_export *exp, + struct lu_fid *fid, struct md_op_data *op_data); struct obd_client_handle; int mdc_set_open_replay_data(struct obd_export *exp, diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index d8406d5..20b15f6 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -1144,7 +1144,7 @@ int mdc_intent_lock(struct obd_export *exp, struct md_op_data *op_data, /* For case if upper layer did not alloc fid, do it now. */ if (!fid_is_sane(&op_data->op_fid2) && it->it_op & IT_CREAT) { - rc = mdc_fid_alloc(exp, &op_data->op_fid2, op_data); + rc = mdc_fid_alloc(NULL, exp, &op_data->op_fid2, op_data); if (rc < 0) { CERROR("Can't alloc new fid, rc %d\n", rc); return rc; diff --git a/drivers/staging/lustre/lustre/mdc/mdc_reint.c b/drivers/staging/lustre/lustre/mdc/mdc_reint.c index 5dba2c8..c3781a6 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_reint.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_reint.c @@ -214,11 +214,9 @@ int mdc_create(struct obd_export *exp, struct md_op_data *op_data, * mdc_fid_alloc() may return errno 1 in case of switch to new * sequence, handle this. */ - rc = mdc_fid_alloc(exp, &op_data->op_fid2, op_data); - if (rc < 0) { - CERROR("Can't alloc new fid, rc %d\n", rc); + rc = mdc_fid_alloc(NULL, exp, &op_data->op_fid2, op_data); + if (rc < 0) return rc; - } } rebuild: diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 394ef3c..e26d0d7 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -765,7 +765,7 @@ static int mdc_close(struct obd_export *exp, struct md_op_data *op_data, req_fmt = &RQF_MDS_RELEASE_CLOSE; /* allocate a FID for volatile file */ - rc = mdc_fid_alloc(exp, &op_data->op_fid2, op_data); + rc = mdc_fid_alloc(NULL, exp, &op_data->op_fid2, op_data); if (rc < 0) { CERROR("%s: "DFID" failed to allocate FID: %d\n", obd->obd_name, PFID(&op_data->op_fid1), rc); @@ -2203,13 +2203,13 @@ static int mdc_import_event(struct obd_device *obd, struct obd_import *imp, return rc; } -int mdc_fid_alloc(struct obd_export *exp, struct lu_fid *fid, - struct md_op_data *op_data) +int mdc_fid_alloc(const struct lu_env *env, struct obd_export *exp, + struct lu_fid *fid, struct md_op_data *op_data) { struct client_obd *cli = &exp->exp_obd->u.cli; struct lu_client_seq *seq = cli->cl_seq; - return seq_client_alloc_fid(NULL, seq, fid); + return seq_client_alloc_fid(env, seq, fid); } static struct obd_uuid *mdc_get_uuid(struct obd_export *exp) -- cgit v0.10.2 From d097d67b7f093032cd0f64d05e92eba9a025b82e Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Tue, 16 Aug 2016 16:18:55 -0400 Subject: staging: lustre: llite: validate names In ll_prep_md_op_data() validate names according to the same formula used in mdd_name_check(). Add mdc_pack_name() to validate the name actually packed in the request. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4992 Reviewed-on: http://review.whamcloud.com/10198 Reviewed-by: wangdi <di.wang@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h index 4daa382..d401ae1 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h @@ -360,13 +360,4 @@ do { \ ptr += cfs_size_round(len); \ } while (0) -#define LOGL0(var, len, ptr) \ -do { \ - if (!len) \ - break; \ - memcpy((char *)ptr, (const char *)var, len); \ - *((char *)(ptr) + len) = 0; \ - ptr += cfs_size_round(len + 1); \ -} while (0) - #endif diff --git a/drivers/staging/lustre/lustre/include/lu_object.h b/drivers/staging/lustre/lustre/include/lu_object.h index 25c12d8..6ab1782 100644 --- a/drivers/staging/lustre/lustre/include/lu_object.h +++ b/drivers/staging/lustre/lustre/include/lu_object.h @@ -1263,6 +1263,22 @@ struct lu_name { }; /** + * Validate names (path components) + * + * To be valid \a name must be non-empty, '\0' terminated of length \a + * name_len, and not contain '/'. The maximum length of a name (before + * say -ENAMETOOLONG will be returned) is really controlled by llite + * and the server. We only check for something insane coming from bad + * integer handling here. + */ +static inline bool lu_name_is_valid_2(const char *name, size_t name_len) +{ + return name && name_len > 0 && name_len < INT_MAX && + name[name_len] == '\0' && strlen(name) == name_len && + !memchr(name, '/', name_len); +} + +/** * Common buffer structure to be passed around for various xattr_{s,g}et() * methods. */ diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 2f6e770..a3b4c97 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -2304,8 +2304,17 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, const char *name, int namelen, int mode, __u32 opc, void *data) { - if (namelen > ll_i2sbi(i1)->ll_namelen) - return ERR_PTR(-ENAMETOOLONG); + if (!name) { + /* Do not reuse namelen for something else. */ + if (namelen) + return ERR_PTR(-EINVAL); + } else { + if (namelen > ll_i2sbi(i1)->ll_namelen) + return ERR_PTR(-ENAMETOOLONG); + + if (!lu_name_is_valid_2(name, namelen)) + return ERR_PTR(-EINVAL); + } if (!op_data) op_data = kzalloc(sizeof(*op_data), GFP_NOFS); diff --git a/drivers/staging/lustre/lustre/mdc/mdc_lib.c b/drivers/staging/lustre/lustre/mdc/mdc_lib.c index b532623..16c3571 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_lib.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_lib.c @@ -87,6 +87,37 @@ void mdc_pack_body(struct ptlrpc_request *req, const struct lu_fid *fid, } } +/** + * Pack a name (path component) into a request + * + * \param[in] req request + * \param[in] field request field (usually RMF_NAME) + * \param[in] name path component + * \param[in] name_len length of path component + * + * \a field must be present in \a req and of size \a name_len + 1. + * + * \a name must be '\0' terminated of length \a name_len and represent + * a single path component (not contain '/'). + */ +static void mdc_pack_name(struct ptlrpc_request *req, + const struct req_msg_field *field, + const char *name, size_t name_len) +{ + size_t buf_size; + size_t cpy_len; + char *buf; + + buf = req_capsule_client_get(&req->rq_pill, field); + buf_size = req_capsule_get_size(&req->rq_pill, field, RCL_CLIENT); + + LASSERT(name && name_len && buf && buf_size == name_len + 1); + + cpy_len = strlcpy(buf, name, buf_size); + + LASSERT(cpy_len == name_len && lu_name_is_valid_2(buf, cpy_len)); +} + void mdc_readdir_pack(struct ptlrpc_request *req, __u64 pgoff, __u32 size, const struct lu_fid *fid) { @@ -130,9 +161,7 @@ void mdc_create_pack(struct ptlrpc_request *req, struct md_op_data *op_data, rec->cr_bias = op_data->op_bias; rec->cr_umask = current_umask(); - tmp = req_capsule_client_get(&req->rq_pill, &RMF_NAME); - LOGL0(op_data->op_name, op_data->op_namelen, tmp); - + mdc_pack_name(req, &RMF_NAME, op_data->op_name, op_data->op_namelen); if (data) { tmp = req_capsule_client_get(&req->rq_pill, &RMF_EADATA); memcpy(tmp, data, datalen); @@ -200,8 +229,9 @@ void mdc_open_pack(struct ptlrpc_request *req, struct md_op_data *op_data, rec->cr_old_handle = op_data->op_handle; if (op_data->op_name) { - tmp = req_capsule_client_get(&req->rq_pill, &RMF_NAME); - LOGL0(op_data->op_name, op_data->op_namelen, tmp); + mdc_pack_name(req, &RMF_NAME, op_data->op_name, + op_data->op_namelen); + if (op_data->op_bias & MDS_CREATE_VOLATILE) cr_flags |= MDS_OPEN_VOLATILE; } @@ -334,7 +364,6 @@ void mdc_setattr_pack(struct ptlrpc_request *req, struct md_op_data *op_data, void mdc_unlink_pack(struct ptlrpc_request *req, struct md_op_data *op_data) { struct mdt_rec_unlink *rec; - char *tmp; CLASSERT(sizeof(struct mdt_rec_reint) == sizeof(struct mdt_rec_unlink)); rec = req_capsule_client_get(&req->rq_pill, &RMF_REC_REINT); @@ -352,15 +381,12 @@ void mdc_unlink_pack(struct ptlrpc_request *req, struct md_op_data *op_data) rec->ul_time = op_data->op_mod_time; rec->ul_bias = op_data->op_bias; - tmp = req_capsule_client_get(&req->rq_pill, &RMF_NAME); - LASSERT(tmp); - LOGL0(op_data->op_name, op_data->op_namelen, tmp); + mdc_pack_name(req, &RMF_NAME, op_data->op_name, op_data->op_namelen); } void mdc_link_pack(struct ptlrpc_request *req, struct md_op_data *op_data) { struct mdt_rec_link *rec; - char *tmp; CLASSERT(sizeof(struct mdt_rec_reint) == sizeof(struct mdt_rec_link)); rec = req_capsule_client_get(&req->rq_pill, &RMF_REC_REINT); @@ -376,15 +402,13 @@ void mdc_link_pack(struct ptlrpc_request *req, struct md_op_data *op_data) rec->lk_time = op_data->op_mod_time; rec->lk_bias = op_data->op_bias; - tmp = req_capsule_client_get(&req->rq_pill, &RMF_NAME); - LOGL0(op_data->op_name, op_data->op_namelen, tmp); + mdc_pack_name(req, &RMF_NAME, op_data->op_name, op_data->op_namelen); } void mdc_rename_pack(struct ptlrpc_request *req, struct md_op_data *op_data, const char *old, int oldlen, const char *new, int newlen) { struct mdt_rec_rename *rec; - char *tmp; CLASSERT(sizeof(struct mdt_rec_reint) == sizeof(struct mdt_rec_rename)); rec = req_capsule_client_get(&req->rq_pill, &RMF_REC_REINT); @@ -404,13 +428,10 @@ void mdc_rename_pack(struct ptlrpc_request *req, struct md_op_data *op_data, rec->rn_mode = op_data->op_mode; rec->rn_bias = op_data->op_bias; - tmp = req_capsule_client_get(&req->rq_pill, &RMF_NAME); - LOGL0(old, oldlen, tmp); + mdc_pack_name(req, &RMF_NAME, old, oldlen); - if (new) { - tmp = req_capsule_client_get(&req->rq_pill, &RMF_SYMTGT); - LOGL0(new, newlen, tmp); - } + if (new) + mdc_pack_name(req, &RMF_SYMTGT, new, newlen); } void mdc_getattr_pack(struct ptlrpc_request *req, __u64 valid, int flags, @@ -432,11 +453,9 @@ void mdc_getattr_pack(struct ptlrpc_request *req, __u64 valid, int flags, b->fid2 = op_data->op_fid2; b->valid |= OBD_MD_FLID; - if (op_data->op_name) { - char *tmp = req_capsule_client_get(&req->rq_pill, &RMF_NAME); - - LOGL0(op_data->op_name, op_data->op_namelen, tmp); - } + if (op_data->op_name) + mdc_pack_name(req, &RMF_NAME, op_data->op_name, + op_data->op_namelen); } static void mdc_hsm_release_pack(struct ptlrpc_request *req, -- cgit v0.10.2 From c948390f10ccc7ba67dcc17c9e5b313744f554aa Mon Sep 17 00:00:00 2001 From: Gregoire Pichon <gregoire.pichon@bull.net> Date: Tue, 16 Aug 2016 16:18:56 -0400 Subject: staging: lustre: llite: fix inconsistencies of root squash feature Root squash exhibits inconsistent behaviour on a client when enabled. If a file is not cached on the client, then root will get a permission denied error when accessing the file. When the file has recently been accessed by a regular user and is still in cache, root will be able to access the file without error because the permission check is only done by the client that isn't aware of root squash. While the only real security benefit from root squash is to deny clients access to files owned by root itself, it also makes sense to treat file access on the client in a consistent manner regardless of whether the file is in cache or not. This patch adds root squash settings to llite so that client is able to apply root squashing when it is relevant. Configuration of MDT root squash settings will automatically be applied to llite config log as well. Update cfs_str2num_check() routine by removing any modification of the specified string parameter. Since string can come from ls_str field of a lstr structure, this avoids inconsistent ls_len field. Signed-off-by: Gregoire Pichon <gregoire.pichon@bull.net> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-1778 Reviewed-on: http://review.whamcloud.com/5700 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Niu Yawei <yawei.niu@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lnet/libcfs/libcfs_string.c b/drivers/staging/lustre/lnet/libcfs/libcfs_string.c index fc697cd..56a614d 100644 --- a/drivers/staging/lustre/lnet/libcfs/libcfs_string.c +++ b/drivers/staging/lustre/lnet/libcfs/libcfs_string.c @@ -229,8 +229,6 @@ cfs_str2num_check(char *str, int nob, unsigned *num, char *endp, cache; int rc; - str = cfs_trimwhite(str); - /** * kstrouint can only handle strings composed * of only numbers. We need to scan the string diff --git a/drivers/staging/lustre/lustre/include/lprocfs_status.h b/drivers/staging/lustre/lustre/include/lprocfs_status.h index d68e60e..ff35e63 100644 --- a/drivers/staging/lustre/lustre/include/lprocfs_status.h +++ b/drivers/staging/lustre/lustre/include/lprocfs_status.h @@ -681,6 +681,12 @@ static struct lustre_attr lustre_attr_##name = __ATTR(name, mode, show, store) extern const struct sysfs_ops lustre_sysfs_ops; +struct root_squash_info; +int lprocfs_wr_root_squash(const char *buffer, unsigned long count, + struct root_squash_info *squash, char *name); +int lprocfs_wr_nosquash_nids(const char *buffer, unsigned long count, + struct root_squash_info *squash, char *name); + /* all quota proc functions */ int lprocfs_quota_rd_bunit(char *page, char **start, loff_t off, int count, diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index a288995..e86961c 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -1759,4 +1759,13 @@ extern spinlock_t obd_types_lock; /* prng.c */ #define ll_generate_random_uuid(uuid_out) cfs_get_random_bytes(uuid_out, sizeof(class_uuid_t)) +/* root squash info */ +struct rw_semaphore; +struct root_squash_info { + uid_t rsi_uid; + gid_t rsi_gid; + struct list_head rsi_nosquash_nids; + struct rw_semaphore rsi_sem; +}; + #endif /* __LINUX_OBD_CLASS_H */ diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 519db53..90a7170 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -41,6 +41,7 @@ #include "../include/lustre_lite.h" #include <linux/pagemap.h> #include <linux/file.h> +#include <linux/sched.h> #include <linux/mount.h> #include "llite_internal.h" #include "../include/lustre/ll_fiemap.h" @@ -3289,6 +3290,12 @@ struct posix_acl *ll_get_acl(struct inode *inode, int type) int ll_inode_permission(struct inode *inode, int mask) { + struct ll_sb_info *sbi; + struct root_squash_info *squash; + const struct cred *old_cred = NULL; + struct cred *cred = NULL; + bool squash_id = false; + cfs_cap_t cap; int rc = 0; if (mask & MAY_NOT_BLOCK) @@ -3308,9 +3315,46 @@ int ll_inode_permission(struct inode *inode, int mask) CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), inode mode %x mask %o\n", PFID(ll_inode2fid(inode)), inode, inode->i_mode, mask); + /* squash fsuid/fsgid if needed */ + sbi = ll_i2sbi(inode); + squash = &sbi->ll_squash; + if (unlikely(squash->rsi_uid && + uid_eq(current_fsuid(), GLOBAL_ROOT_UID) && + !(sbi->ll_flags & LL_SBI_NOROOTSQUASH))) { + squash_id = true; + } + + if (squash_id) { + CDEBUG(D_OTHER, "squash creds (%d:%d)=>(%d:%d)\n", + __kuid_val(current_fsuid()), __kgid_val(current_fsgid()), + squash->rsi_uid, squash->rsi_gid); + + /* + * update current process's credentials + * and FS capability + */ + cred = prepare_creds(); + if (!cred) + return -ENOMEM; + + cred->fsuid = make_kuid(&init_user_ns, squash->rsi_uid); + cred->fsgid = make_kgid(&init_user_ns, squash->rsi_gid); + for (cap = 0; cap < sizeof(cfs_cap_t) * 8; cap++) { + if ((1 << cap) & CFS_CAP_FS_MASK) + cap_lower(cred->cap_effective, cap); + } + old_cred = override_creds(cred); + } + ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_INODE_PERM, 1); rc = generic_permission(inode, mask); + /* restore current process's credentials and FS capability */ + if (squash_id) { + revert_creds(old_cred); + put_cred(cred); + } + return rc; } diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index e101dd8..500b5ec 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -412,6 +412,7 @@ enum stats_track_type { #define LL_SBI_LAYOUT_LOCK 0x20000 /* layout lock support */ #define LL_SBI_USER_FID2PATH 0x40000 /* allow fid2path by unprivileged users */ #define LL_SBI_XATTR_CACHE 0x80000 /* support for xattr cache */ +#define LL_SBI_NOROOTSQUASH 0x100000 /* do not apply root squash */ #define LL_SBI_FLAGS { \ "nolck", \ @@ -434,6 +435,7 @@ enum stats_track_type { "layout", \ "user_fid2path",\ "xattr", \ + "norootsquash", \ } struct ll_sb_info { @@ -500,6 +502,9 @@ struct ll_sb_info { dev_t ll_sdev_orig; /* save s_dev before assign for * clustered nfs */ + /* root squash */ + struct root_squash_info ll_squash; + __kernel_fsid_t ll_fsid; struct kobject ll_kobj; /* sysfs object */ struct super_block *ll_sb; /* struct super_block (for sysfs code)*/ @@ -798,6 +803,7 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, void ll_finish_md_op_data(struct md_op_data *op_data); int ll_get_obd_name(struct inode *inode, unsigned int cmd, unsigned long arg); char *ll_get_fsname(struct super_block *sb, char *buf, int buflen); +void ll_compute_rootsquash_state(struct ll_sb_info *sbi); void ll_open_cleanup(struct super_block *sb, struct ptlrpc_request *open_req); /* llite/llite_nfs.c */ diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index a3b4c97..0a28925 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -119,6 +119,12 @@ static struct ll_sb_info *ll_init_sbi(struct super_block *sb) atomic_set(&sbi->ll_agl_total, 0); sbi->ll_flags |= LL_SBI_AGL_ENABLED; + /* root squash */ + sbi->ll_squash.rsi_uid = 0; + sbi->ll_squash.rsi_gid = 0; + INIT_LIST_HEAD(&sbi->ll_squash.rsi_nosquash_nids); + init_rwsem(&sbi->ll_squash.rsi_sem); + sbi->ll_sb = sb; return sbi; @@ -129,6 +135,8 @@ static void ll_free_sbi(struct super_block *sb) struct ll_sb_info *sbi = ll_s2sbi(sb); if (sbi->ll_cache) { + if (!list_empty(&sbi->ll_squash.rsi_nosquash_nids)) + cfs_free_nidlist(&sbi->ll_squash.rsi_nosquash_nids); cl_cache_decref(sbi->ll_cache); sbi->ll_cache = NULL; } @@ -2496,3 +2504,42 @@ void ll_dirty_page_discard_warn(struct page *page, int ioret) if (buf) free_page((unsigned long)buf); } + +/* + * Compute llite root squash state after a change of root squash + * configuration setting or add/remove of a lnet nid + */ +void ll_compute_rootsquash_state(struct ll_sb_info *sbi) +{ + struct root_squash_info *squash = &sbi->ll_squash; + lnet_process_id_t id; + bool matched; + int i; + + /* Update norootsquash flag */ + down_write(&squash->rsi_sem); + if (list_empty(&squash->rsi_nosquash_nids)) { + sbi->ll_flags &= ~LL_SBI_NOROOTSQUASH; + } else { + /* + * Do not apply root squash as soon as one of our NIDs is + * in the nosquash_nids list + */ + matched = false; + i = 0; + + while (LNetGetId(i++, &id) != -ENOENT) { + if (LNET_NETTYP(LNET_NIDNET(id.nid)) == LOLND) + continue; + if (cfs_match_nid(id.nid, &squash->rsi_nosquash_nids)) { + matched = true; + break; + } + } + if (matched) + sbi->ll_flags |= LL_SBI_NOROOTSQUASH; + else + sbi->ll_flags &= ~LL_SBI_NOROOTSQUASH; + } + up_write(&squash->rsi_sem); +} diff --git a/drivers/staging/lustre/lustre/llite/lproc_llite.c b/drivers/staging/lustre/lustre/llite/lproc_llite.c index e86bf3c..2f1f389 100644 --- a/drivers/staging/lustre/lustre/llite/lproc_llite.c +++ b/drivers/staging/lustre/lustre/llite/lproc_llite.c @@ -833,6 +833,71 @@ static ssize_t unstable_stats_show(struct kobject *kobj, } LUSTRE_RO_ATTR(unstable_stats); +static ssize_t root_squash_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info, + ll_kobj); + struct root_squash_info *squash = &sbi->ll_squash; + + return sprintf(buf, "%u:%u\n", squash->rsi_uid, squash->rsi_gid); +} + +static ssize_t root_squash_store(struct kobject *kobj, struct attribute *attr, + const char *buffer, size_t count) +{ + struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info, + ll_kobj); + struct root_squash_info *squash = &sbi->ll_squash; + + return lprocfs_wr_root_squash(buffer, count, squash, + ll_get_fsname(sbi->ll_sb, NULL, 0)); +} +LUSTRE_RW_ATTR(root_squash); + +static int ll_nosquash_nids_seq_show(struct seq_file *m, void *v) +{ + struct super_block *sb = m->private; + struct ll_sb_info *sbi = ll_s2sbi(sb); + struct root_squash_info *squash = &sbi->ll_squash; + int len; + + down_read(&squash->rsi_sem); + if (!list_empty(&squash->rsi_nosquash_nids)) { + len = cfs_print_nidlist(m->buf + m->count, m->size - m->count, + &squash->rsi_nosquash_nids); + m->count += len; + seq_puts(m, "\n"); + } else { + seq_puts(m, "NONE\n"); + } + up_read(&squash->rsi_sem); + + return 0; +} + +static ssize_t ll_nosquash_nids_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) +{ + struct seq_file *m = file->private_data; + struct super_block *sb = m->private; + struct ll_sb_info *sbi = ll_s2sbi(sb); + struct root_squash_info *squash = &sbi->ll_squash; + int rc; + + rc = lprocfs_wr_nosquash_nids(buffer, count, squash, + ll_get_fsname(sb, NULL, 0)); + if (rc < 0) + return rc; + + ll_compute_rootsquash_state(sbi); + + return rc; +} + +LPROC_SEQ_FOPS(ll_nosquash_nids); + static struct lprocfs_vars lprocfs_llite_obd_vars[] = { /* { "mntpt_path", ll_rd_path, 0, 0 }, */ { "site", &ll_site_stats_fops, NULL, 0 }, @@ -840,6 +905,8 @@ static struct lprocfs_vars lprocfs_llite_obd_vars[] = { { "max_cached_mb", &ll_max_cached_mb_fops, NULL }, { "statahead_stats", &ll_statahead_stats_fops, NULL, 0 }, { "sbi_flags", &ll_sbi_flags_fops, NULL, 0 }, + { .name = "nosquash_nids", + .fops = &ll_nosquash_nids_fops }, { NULL } }; @@ -869,6 +936,7 @@ static struct attribute *llite_attrs[] = { &lustre_attr_default_easize.attr, &lustre_attr_xattr_cache.attr, &lustre_attr_unstable_stats.attr, + &lustre_attr_root_squash.attr, NULL, }; diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c index 279b625..c83d28e 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c @@ -1547,6 +1547,146 @@ void lprocfs_oh_clear(struct obd_histogram *oh) } EXPORT_SYMBOL(lprocfs_oh_clear); +int lprocfs_wr_root_squash(const char __user *buffer, unsigned long count, + struct root_squash_info *squash, char *name) +{ + char kernbuf[64], *tmp, *errmsg; + unsigned long uid, gid; + int rc; + + if (count >= sizeof(kernbuf)) { + errmsg = "string too long"; + rc = -EINVAL; + goto failed_noprint; + } + if (copy_from_user(kernbuf, buffer, count)) { + errmsg = "bad address"; + rc = -EFAULT; + goto failed_noprint; + } + kernbuf[count] = '\0'; + + /* look for uid gid separator */ + tmp = strchr(kernbuf, ':'); + if (!tmp) { + errmsg = "needs uid:gid format"; + rc = -EINVAL; + goto failed; + } + *tmp = '\0'; + tmp++; + + /* parse uid */ + if (kstrtoul(kernbuf, 0, &uid) != 0) { + errmsg = "bad uid"; + rc = -EINVAL; + goto failed; + } + /* parse gid */ + if (kstrtoul(tmp, 0, &gid) != 0) { + errmsg = "bad gid"; + rc = -EINVAL; + goto failed; + } + + squash->rsi_uid = uid; + squash->rsi_gid = gid; + + LCONSOLE_INFO("%s: root_squash is set to %u:%u\n", + name, squash->rsi_uid, squash->rsi_gid); + return count; + +failed: + if (tmp) { + tmp--; + *tmp = ':'; + } + CWARN("%s: failed to set root_squash to \"%s\", %s, rc = %d\n", + name, kernbuf, errmsg, rc); + return rc; +failed_noprint: + CWARN("%s: failed to set root_squash due to %s, rc = %d\n", + name, errmsg, rc); + return rc; +} +EXPORT_SYMBOL(lprocfs_wr_root_squash); + +int lprocfs_wr_nosquash_nids(const char __user *buffer, unsigned long count, + struct root_squash_info *squash, char *name) +{ + char *kernbuf = NULL, *errmsg; + struct list_head tmp; + int len = count; + int rc; + + if (count > 4096) { + errmsg = "string too long"; + rc = -EINVAL; + goto failed; + } + + kernbuf = kzalloc(count + 1, GFP_NOFS); + if (!kernbuf) { + errmsg = "no memory"; + rc = -ENOMEM; + goto failed; + } + + if (copy_from_user(kernbuf, buffer, count)) { + errmsg = "bad address"; + rc = -EFAULT; + goto failed; + } + kernbuf[count] = '\0'; + + if (count > 0 && kernbuf[count - 1] == '\n') + len = count - 1; + + if ((len == 4 && !strncmp(kernbuf, "NONE", len)) || + (len == 5 && !strncmp(kernbuf, "clear", len))) { + /* empty string is special case */ + down_write(&squash->rsi_sem); + if (!list_empty(&squash->rsi_nosquash_nids)) + cfs_free_nidlist(&squash->rsi_nosquash_nids); + up_write(&squash->rsi_sem); + LCONSOLE_INFO("%s: nosquash_nids is cleared\n", name); + kfree(kernbuf); + return count; + } + + INIT_LIST_HEAD(&tmp); + if (cfs_parse_nidlist(kernbuf, count, &tmp) <= 0) { + errmsg = "can't parse"; + rc = -EINVAL; + goto failed; + } + LCONSOLE_INFO("%s: nosquash_nids set to %s\n", + name, kernbuf); + kfree(kernbuf); + kernbuf = NULL; + + down_write(&squash->rsi_sem); + if (!list_empty(&squash->rsi_nosquash_nids)) + cfs_free_nidlist(&squash->rsi_nosquash_nids); + list_splice(&tmp, &squash->rsi_nosquash_nids); + up_write(&squash->rsi_sem); + + return count; + +failed: + if (kernbuf) { + CWARN("%s: failed to set nosquash_nids to \"%s\", %s rc = %d\n", + name, kernbuf, errmsg, rc); + kfree(kernbuf); + kernbuf = NULL; + } else { + CWARN("%s: failed to set nosquash_nids due to %s rc = %d\n", + name, errmsg, rc); + } + return rc; +} +EXPORT_SYMBOL(lprocfs_wr_nosquash_nids); + static ssize_t lustre_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) { -- cgit v0.10.2 From d6099af20a148d705a16da2aed25b605ba0a162c Mon Sep 17 00:00:00 2001 From: "Christopher J. Morrone" <morrone2@llnl.gov> Date: Tue, 16 Aug 2016 16:18:57 -0400 Subject: staging: lustre: Remove static declaration in anonymous union It is not permitted in C++ to have a static declaration inside of an anonymous union. The g++ compiler will complaine with an error like this: error: struct ost_id::<anonymous union>::ostid invalid; an anonymous union can only have non-static data members [-fpermissive] This patch changes the code to use an unnamed struct in place of "struct ostid" inside of the anonymous union. That name declaration was completely unnecessary anyway, since it was not used anywhere else. Signed-off-by: Christopher J. Morrone <morrone2@llnl.gov> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4987 Reviewed-on: http://review.whamcloud.com/10176 Reviewed-by: Robert Read <robert.read@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index 4b2553c..59d45de 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -167,7 +167,7 @@ struct lustre_mdt_attrs { */ struct ost_id { union { - struct ostid { + struct { __u64 oi_id; __u64 oi_seq; } oi; -- cgit v0.10.2 From 297e908f08cb40c4bbe11b06c30ff1de1a3740c0 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong <jinshan.xiong@intel.com> Date: Tue, 16 Aug 2016 16:18:58 -0400 Subject: staging: lustre: llite: Fix the deadlock in balance_dirty_pages() If the page is already dirtied in ll_write_end() and kernel tries to call balance_dirty_pages() to write back dirty pages in the same thread, this is deadlock case if the page is already held by clio. This can also fix the issue of LU-4873. Signed-off-by: Jinshan Xiong <jinshan.xiong@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4977 Reviewed-on: http://review.whamcloud.com/10149 Reviewed-by: Bobi Jam <bobijam@gmail.com> Reviewed-by: Lai Siyao <lai.siyao@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c index c14a1b6..8c8c100 100644 --- a/drivers/staging/lustre/lustre/llite/rw26.c +++ b/drivers/staging/lustre/lustre/llite/rw26.c @@ -506,9 +506,8 @@ static int ll_write_begin(struct file *file, struct address_space *mapping, env = lcc->lcc_env; io = lcc->lcc_io; - if (likely(to == PAGE_SIZE)) /* LU-4873 */ - /* To avoid deadlock, try to lock page first. */ - vmpage = grab_cache_page_nowait(mapping, index); + /* To avoid deadlock, try to lock page first. */ + vmpage = grab_cache_page_nowait(mapping, index); if (unlikely(!vmpage || PageDirty(vmpage) || PageWriteback(vmpage))) { struct vvp_io *vio = vvp_env_io(env); struct cl_page_list *plist = &vio->u.write.vui_queue; @@ -617,6 +616,13 @@ static int ll_write_end(struct file *file, struct address_space *mapping, LASSERT(from == 0); vio->u.write.vui_to = from + copied; + /* + * To address the deadlock in balance_dirty_pages() where + * this dirty page may be written back in the same thread. + */ + if (PageDirty(vmpage)) + unplug = true; + /* We may have one full RPC, commit it soon */ if (plist->pl_nr >= PTLRPC_MAX_BRW_PAGES) unplug = true; -- cgit v0.10.2 From d8c0b0a9e6500131938d92bcd6213af520c10401 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong <jinshan.xiong@intel.com> Date: Tue, 16 Aug 2016 16:18:59 -0400 Subject: staging: lustre: llite: Change readdir BRW metrics To simplify the code, change the metrics from bytes to pages. Signed-off-by: Andreas Dilger <andreas.dilger@intel.com> Signed-off-by: Jinshan Xiong <jinshan.xiong@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5034 Reviewed-on: http://review.whamcloud.com/10275 Reviewed-by: wangdi <di.wang@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 47fbcd2..924b5df 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -148,7 +148,7 @@ static int ll_dir_filler(void *_hash, struct page *page0) struct page **page_pool; struct page *page; struct lu_dirpage *dp; - int max_pages = ll_i2sbi(inode)->ll_md_brw_size >> PAGE_SHIFT; + int max_pages = ll_i2sbi(inode)->ll_md_brw_pages; int nrdpgs = 0; /* number of pages read actually */ int npages; int i; diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 500b5ec..3d7fa9a 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -474,7 +474,7 @@ struct ll_sb_info { unsigned int ll_namelen; struct file_operations *ll_fop; - unsigned int ll_md_brw_size; /* used by readdir */ + unsigned int ll_md_brw_pages; /* readdir pages per RPC */ struct lu_site *ll_site; struct cl_device *ll_cl; diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 0a28925..ac59cd6 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -319,9 +319,9 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, sbi->ll_flags |= LL_SBI_64BIT_HASH; if (data->ocd_connect_flags & OBD_CONNECT_BRW_SIZE) - sbi->ll_md_brw_size = data->ocd_brw_size; + sbi->ll_md_brw_pages = data->ocd_brw_size >> PAGE_SHIFT; else - sbi->ll_md_brw_size = PAGE_SIZE; + sbi->ll_md_brw_pages = 1; if (data->ocd_connect_flags & OBD_CONNECT_LAYOUTLOCK) sbi->ll_flags |= LL_SBI_LAYOUT_LOCK; -- cgit v0.10.2 From 00c0a6aea0d0ab2c11594616244d787ad7bf64dc Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Tue, 16 Aug 2016 16:19:00 -0400 Subject: staging: lustre: uapi: reduce scope of lustre_idl.h Move the definition of OBD_OCD_VERSION() and similar macros from lustre_idl.h to lustre_ver.h. These macros are primarily used in comparisons to LUSTRE_VERSION_CODE which is defined in lustre_ver.h and so should be defined there as well. Move a few definitions (related to FIDs, quota and striping) from lustre_idl.h to lustre_user.h. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5065 Reviewed-on: http://review.whamcloud.com/10336 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Bob Glossman <bob.glossman@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 8736826..69bed64 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -93,6 +93,7 @@ /* Defn's shared with user-space. */ #include "lustre_user.h" #include "lustre_errno.h" +#include "../lustre_ver.h" /* * GENERAL STUFF @@ -846,11 +847,6 @@ static inline bool fid_is_sane(const struct lu_fid *fid) fid_seq_is_rsvd(fid_seq(fid))); } -static inline bool fid_is_zero(const struct lu_fid *fid) -{ - return fid_seq(fid) == 0 && fid_oid(fid) == 0; -} - void lustre_swab_lu_fid(struct lu_fid *fid); void lustre_swab_lu_seq_range(struct lu_seq_range *range); @@ -1318,14 +1314,6 @@ void lustre_swab_ptlrpc_body(struct ptlrpc_body *pb); #define CLIENT_CONNECT_MDT_REQD (OBD_CONNECT_IBITS | OBD_CONNECT_FID | \ OBD_CONNECT_FULL20) -#define OBD_OCD_VERSION(major, minor, patch, fix) (((major)<<24) + \ - ((minor)<<16) + \ - ((patch)<<8) + (fix)) -#define OBD_OCD_VERSION_MAJOR(version) ((int)((version)>>24)&255) -#define OBD_OCD_VERSION_MINOR(version) ((int)((version)>>16)&255) -#define OBD_OCD_VERSION_PATCH(version) ((int)((version)>>8)&255) -#define OBD_OCD_VERSION_FIX(version) ((int)(version)&255) - /* This structure is used for both request and reply. * * If we eventually have separate connect data for different types, which we @@ -1509,14 +1497,6 @@ enum obdo_flags { #define LOV_MAGIC_V1_DEF 0x0CD10BD0 #define LOV_MAGIC_V3_DEF 0x0CD30BD0 -#define LOV_PATTERN_RAID0 0x001 /* stripes are used round-robin */ -#define LOV_PATTERN_RAID1 0x002 /* stripes are mirrors of each other */ -#define LOV_PATTERN_FIRST 0x100 /* first stripe is not in round-robin */ -#define LOV_PATTERN_CMOBD 0x200 - -#define LOV_PATTERN_F_MASK 0xffff0000 -#define LOV_PATTERN_F_RELEASED 0x80000000 /* HSM released file */ - #define lov_pattern(pattern) (pattern & ~LOV_PATTERN_F_MASK) #define lov_pattern_flags(pattern) (pattern & LOV_PATTERN_F_MASK) @@ -1796,7 +1776,7 @@ void lustre_swab_obd_statfs(struct obd_statfs *os); * it to sync quickly */ -#define OBD_OBJECT_EOF 0xffffffffffffffffULL +#define OBD_OBJECT_EOF LUSTRE_EOF #define OST_MIN_PRECREATE 32 #define OST_MAX_PRECREATE 20000 @@ -1892,12 +1872,6 @@ struct obd_quotactl { void lustre_swab_obd_quotactl(struct obd_quotactl *q); -#define Q_QUOTACHECK 0x800100 /* deprecated as of 2.4 */ -#define Q_INITQUOTA 0x800101 /* deprecated as of 2.4 */ -#define Q_GETOINFO 0x800102 /* get obd quota info */ -#define Q_GETOQUOTA 0x800103 /* get obd quotas */ -#define Q_FINVALIDATE 0x800104 /* deprecated as of 2.4 */ - #define Q_COPY(out, in, member) (out)->member = (in)->member #define QCTL_COPY(out, in) \ @@ -2533,19 +2507,11 @@ struct lmv_mds_md_v1 { * for example the object is being migrated. And the hash function * might be interpreted differently with different flags. */ -enum lmv_hash_type { - LMV_HASH_TYPE_ALL_CHARS = 1, - LMV_HASH_TYPE_FNV_1A_64 = 2, -}; - #define LMV_HASH_TYPE_MASK 0x0000ffff #define LMV_HASH_FLAG_MIGRATION 0x80000000 #define LMV_HASH_FLAG_DEAD 0x40000000 -#define LMV_HASH_NAME_ALL_CHARS "all_char" -#define LMV_HASH_NAME_FNV_1A_64 "fnv_1a_64" - /** * The FNV-1a hash algorithm is as follows: * hash = FNV_offset_basis diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index 59d45de..8398c4f 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -45,6 +45,8 @@ #include "ll_fiemap.h" #include "../linux/lustre_user.h" +#define LUSTRE_EOF 0xffffffffffffffffULL + /* for statfs() */ #define LL_SUPER_MAGIC 0x0BD00BD0 @@ -117,6 +119,11 @@ struct lu_fid { __u32 f_ver; }; +static inline bool fid_is_zero(const struct lu_fid *fid) +{ + return !fid->f_seq && !fid->f_oid; +} + struct filter_fid { struct lu_fid ff_parent; /* ff_parent.f_ver == file stripe number */ }; @@ -271,9 +278,14 @@ struct ost_id { #define LMV_USER_MAGIC 0x0CD30CD0 /*default lmv magic*/ -#define LOV_PATTERN_RAID0 0x001 -#define LOV_PATTERN_RAID1 0x002 -#define LOV_PATTERN_FIRST 0x100 +#define LOV_PATTERN_RAID0 0x001 +#define LOV_PATTERN_RAID1 0x002 +#define LOV_PATTERN_FIRST 0x100 +#define LOV_PATTERN_CMOBD 0x200 + +#define LOV_PATTERN_F_MASK 0xffff0000 +#define LOV_PATTERN_F_RELEASED 0x80000000 /* HSM released file */ + #define LOV_MAXPOOLNAME 16 #define LOV_POOLNAMEF "%.16s" @@ -370,6 +382,14 @@ struct lmv_user_mds_data { __u32 lum_mds; }; +enum lmv_hash_type { + LMV_HASH_TYPE_ALL_CHARS = 1, + LMV_HASH_TYPE_FNV_1A_64 = 2, +}; + +#define LMV_HASH_NAME_ALL_CHARS "all_char" +#define LMV_HASH_NAME_FNV_1A_64 "fnv_1a_64" + /* * Got this according to how get LOV_MAX_STRIPE_COUNT, see above, * (max buffer size - lmv+rpc header) / sizeof(struct lmv_user_mds_data) @@ -488,6 +508,12 @@ static inline void obd_uuid2fsname(char *buf, char *uuid, int buflen) /********* Quotas **********/ +#define Q_QUOTACHECK 0x800100 /* deprecated as of 2.4 */ +#define Q_INITQUOTA 0x800101 /* deprecated as of 2.4 */ +#define Q_GETOINFO 0x800102 /* get obd quota info */ +#define Q_GETOQUOTA 0x800103 /* get obd quotas */ +#define Q_FINVALIDATE 0x800104 /* deprecated as of 2.4 */ + /* these must be explicitly translated into linux Q_* in ll_dir_ioctl */ #define LUSTRE_Q_QUOTAON 0x800002 /* turn quotas on */ #define LUSTRE_Q_QUOTAOFF 0x800003 /* turn quotas off */ diff --git a/drivers/staging/lustre/lustre/include/lustre_ver.h b/drivers/staging/lustre/lustre/include/lustre_ver.h index 64559a1..2bb59b2 100644 --- a/drivers/staging/lustre/lustre/include/lustre_ver.h +++ b/drivers/staging/lustre/lustre/include/lustre_ver.h @@ -7,9 +7,16 @@ #define LUSTRE_FIX 0 #define LUSTRE_VERSION_STRING "2.4.60" -#define LUSTRE_VERSION_CODE OBD_OCD_VERSION(LUSTRE_MAJOR, \ - LUSTRE_MINOR, LUSTRE_PATCH, \ - LUSTRE_FIX) +#define OBD_OCD_VERSION(major, minor, patch, fix) \ + (((major) << 24) + ((minor) << 16) + ((patch) << 8) + (fix)) + +#define OBD_OCD_VERSION_MAJOR(version) ((int)((version) >> 24) & 255) +#define OBD_OCD_VERSION_MINOR(version) ((int)((version) >> 16) & 255) +#define OBD_OCD_VERSION_PATCH(version) ((int)((version) >> 8) & 255) +#define OBD_OCD_VERSION_FIX(version) ((int)((version) >> 0) & 255) + +#define LUSTRE_VERSION_CODE \ + OBD_OCD_VERSION(LUSTRE_MAJOR, LUSTRE_MINOR, LUSTRE_PATCH, LUSTRE_FIX) /* * If lustre version of client and servers it connects to differs by more -- cgit v0.10.2 From ef21b1fb8348eede7f62ea0ab89e1af191f6041e Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Tue, 16 Aug 2016 16:19:01 -0400 Subject: staging: lustre: llite: a few fixes about readdir of striped dir. Normally we know the value of op_mea1 when ll_readdir is called. In the case of '.' or '..' op_mea1 is unknown so for that case fetch the real parents FID. Signed-off-by: wang di <di.wang@intel.com> Signed-off-by: Li Xi <lixi@ddn.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4603 Reviewed-on: http://review.whamcloud.com/9191 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Fan Yong <fan.yong@intel.com> Reviewed-by: Li Xi <pkuelelixi@gmail.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 924b5df..3fed80d 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -622,6 +622,33 @@ static int ll_readdir(struct file *filp, struct dir_context *ctx) goto out; } + if (unlikely(op_data->op_mea1)) { + /* + * This is only needed for striped dir to fill .., + * see lmv_read_page + */ + if (file_dentry(filp)->d_parent && + file_dentry(filp)->d_parent->d_inode) { + __u64 ibits = MDS_INODELOCK_UPDATE; + struct inode *parent; + + parent = file_dentry(filp)->d_parent->d_inode; + if (ll_have_md_lock(parent, &ibits, LCK_MINMODE)) + op_data->op_fid3 = *ll_inode2fid(parent); + } + + /* + * If it can not find in cache, do lookup .. on the master + * object + */ + if (fid_is_zero(&op_data->op_fid3)) { + rc = ll_dir_get_parent_fid(inode, &op_data->op_fid3); + if (rc) { + ll_finish_md_op_data(op_data); + return rc; + } + } + } ctx->pos = pos; rc = ll_dir_read(inode, &pos, op_data, ctx); pos = ctx->pos; diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 3d7fa9a..43269aa 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -812,6 +812,7 @@ __u32 get_uuid2int(const char *name, int len); void get_uuid2fsid(const char *name, int len, __kernel_fsid_t *fsid); struct inode *search_inode_for_lustre(struct super_block *sb, const struct lu_fid *fid); +int ll_dir_get_parent_fid(struct inode *dir, struct lu_fid *parent_fid); /* llite/symlink.c */ extern const struct inode_operations ll_fast_symlink_inode_operations; diff --git a/drivers/staging/lustre/lustre/llite/llite_nfs.c b/drivers/staging/lustre/lustre/llite/llite_nfs.c index ab9d5cc..06a8199 100644 --- a/drivers/staging/lustre/lustre/llite/llite_nfs.c +++ b/drivers/staging/lustre/lustre/llite/llite_nfs.c @@ -302,14 +302,12 @@ static struct dentry *ll_fh_to_parent(struct super_block *sb, struct fid *fid, return ll_iget_for_nfs(sb, &nfs_fid->lnf_parent, NULL); } -static struct dentry *ll_get_parent(struct dentry *dchild) +int ll_dir_get_parent_fid(struct inode *dir, struct lu_fid *parent_fid) { struct ptlrpc_request *req = NULL; - struct inode *dir = d_inode(dchild); struct ll_sb_info *sbi; - struct dentry *result = NULL; struct mdt_body *body; - static char dotdot[] = ".."; + static const char dotdot[] = ".."; struct md_op_data *op_data; int rc; int lmmsize; @@ -324,13 +322,13 @@ static struct dentry *ll_get_parent(struct dentry *dchild) rc = ll_get_default_mdsize(sbi, &lmmsize); if (rc != 0) - return ERR_PTR(rc); + return rc; op_data = ll_prep_md_op_data(NULL, dir, NULL, dotdot, strlen(dotdot), lmmsize, LUSTRE_OPC_ANY, NULL); if (IS_ERR(op_data)) - return (void *)op_data; + return PTR_ERR(op_data); rc = md_getattr_name(sbi->ll_md_exp, op_data, &req); ll_finish_md_op_data(op_data); @@ -338,7 +336,7 @@ static struct dentry *ll_get_parent(struct dentry *dchild) CERROR("%s: failure inode "DFID" get parent: rc = %d\n", ll_get_fsname(dir->i_sb, NULL, 0), PFID(ll_inode2fid(dir)), rc); - return ERR_PTR(rc); + return rc; } body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); /* @@ -348,11 +346,26 @@ static struct dentry *ll_get_parent(struct dentry *dchild) if (body->valid & OBD_MD_FLID) { CDEBUG(D_INFO, "parent for " DFID " is " DFID "\n", PFID(ll_inode2fid(dir)), PFID(&body->fid1)); + *parent_fid = body->fid1; } - result = ll_iget_for_nfs(dir->i_sb, &body->fid1, NULL); ptlrpc_req_finished(req); - return result; + return 0; +} + +static struct dentry *ll_get_parent(struct dentry *dchild) +{ + struct lu_fid parent_fid = { 0 }; + struct dentry *dentry; + int rc; + + rc = ll_dir_get_parent_fid(dchild->d_inode, &parent_fid); + if (rc) + return ERR_PTR(rc); + + dentry = ll_iget_for_nfs(dchild->d_inode->i_sb, &parent_fid, NULL); + + return dentry; } const struct export_operations lustre_export_operations = { -- cgit v0.10.2 From a609c393707848dda71c4287f432c19a9b09a566 Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Tue, 16 Aug 2016 16:19:02 -0400 Subject: staging: lustre: lmv: validate lock with correct stripe FID In ll_lookup_it_finish, we need use the real parent(stripe) FID to validate the parent UPDATE lock. Signed-off-by: wang di <di.wang@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4925 Reviewed-on: http://review.whamcloud.com/10026 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 52020a9..b7bdd07 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -1103,6 +1103,11 @@ struct md_ops { ldlm_policy_data_t *, enum ldlm_mode, enum ldlm_cancel_flags flags, void *opaque); + int (*get_fid_from_lsm)(struct obd_export *, + const struct lmv_stripe_md *, + const char *name, int namelen, + struct lu_fid *fid); + int (*intent_getattr_async)(struct obd_export *, struct md_enqueue_info *, struct ldlm_enqueue_info *); diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index e86961c..69b628b 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -1699,6 +1699,19 @@ static inline int md_revalidate_lock(struct obd_export *exp, return rc; } +static inline int md_get_fid_from_lsm(struct obd_export *exp, + const struct lmv_stripe_md *lsm, + const char *name, int namelen, + struct lu_fid *fid) +{ + int rc; + + EXP_CHECK_MD_OP(exp, get_fid_from_lsm); + EXP_MD_COUNTER_INCREMENT(exp, get_fid_from_lsm); + rc = MDP(exp->exp_obd, get_fid_from_lsm)(exp, lsm, name, namelen, fid); + return rc; +} + /* OBD Metadata Support */ int obd_init_caches(void); diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index 6e11b99..581b083 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -487,9 +487,20 @@ static int ll_lookup_it_finish(struct ptlrpc_request *request, struct lookup_intent parent_it = { .it_op = IT_GETATTR, .it_lock_handle = 0 }; + struct lu_fid fid = ll_i2info(parent)->lli_fid; + + /* If it is striped directory, get the real stripe parent */ + if (unlikely(ll_i2info(parent)->lli_lsm_md)) { + rc = md_get_fid_from_lsm(ll_i2mdexp(parent), + ll_i2info(parent)->lli_lsm_md, + (*de)->d_name.name, + (*de)->d_name.len, &fid); + if (rc) + return rc; + } - if (md_revalidate_lock(ll_i2mdexp(parent), &parent_it, - &ll_i2info(parent)->lli_fid, NULL)) { + if (md_revalidate_lock(ll_i2mdexp(parent), &parent_it, &fid, + NULL)) { d_lustre_revalidate(*de); ll_intent_release(&parent_it); } diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 03594f0..9821f69 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -2991,6 +2991,22 @@ static int lmv_revalidate_lock(struct obd_export *exp, struct lookup_intent *it, return rc; } +int lmv_get_fid_from_lsm(struct obd_export *exp, + const struct lmv_stripe_md *lsm, + const char *name, int namelen, struct lu_fid *fid) +{ + const struct lmv_oinfo *oinfo; + + LASSERT(lsm); + oinfo = lsm_name_to_stripe_info(lsm, name, namelen); + if (IS_ERR(oinfo)) + return PTR_ERR(oinfo); + + *fid = oinfo->lmo_fid; + + return 0; +} + /** * For lmv, only need to send request to master MDT, and the master MDT will * process with other slave MDTs. The only exception is Q_GETOQUOTA for which @@ -3155,7 +3171,8 @@ static struct md_ops lmv_md_ops = { .set_open_replay_data = lmv_set_open_replay_data, .clear_open_replay_data = lmv_clear_open_replay_data, .intent_getattr_async = lmv_intent_getattr_async, - .revalidate_lock = lmv_revalidate_lock + .revalidate_lock = lmv_revalidate_lock, + .get_fid_from_lsm = lmv_get_fid_from_lsm, }; static int __init lmv_init(void) -- cgit v0.10.2 From 865b734e8db3f27bf2e58e597c8833a423bd9326 Mon Sep 17 00:00:00 2001 From: Fan Yong <fan.yong@intel.com> Date: Tue, 16 Aug 2016 16:19:03 -0400 Subject: staging: lustre: lov: new pattern flag for partially repaired file When the layout LFSCK repairs orphan OST-object, if the parent MDT-object was lost, then it will re-create the MDT-object and regenerate the LOV EA and fill the target LOV EA slot with the orphan information, and fill other slots with zero (LOV hole); if related LOV EA slot is invalid or hole, then it will refill the target LOV EA slot; if the target slot exceeds current LOV EA tail, then extend the LOV EA, and fill the gaps as zero. Some of the LOV EA holes may cannot be re-filled finally because of lost some OST-objects. And even if they can be re-filled, but there are still some possible race accessings from client before the re-filling. If the client access the LOV EA with hole(s), it may cause some strange behaviour, such as trigger LBUG()/LASSERT() on the client. So we will make the client to be aware of the LOV EA is incomplete. We introduce a new LOV EA pattern flag LOV_PATTERN_F_HOLE for that: any time when the LFSCK repairs the LOV EA with hole(s), the LOV EA will be marked as LOV_PATTERN_F_HOLE; when all the holes in the LOV EA are refilled, the LOV_PATTERN_F_HOLE will be dropped. For a new client, it recongizes the pattern flag LOV_PATTERN_F_HOLE, then it can permit/forbid some opertions on the file with LOV holes: 1) Normal read/write the file with LOV EA hole is permitted, but the application will get EIO error when read data from the dummy slot or write data to the dummy slot. 2) The users can dump the recovered data via some common read tools, such as "dd conv=sync,noerror". 3) Append data to the file which has LOV EA hole will get EIO failure. 4) Other operations will skip the LOV EA hole(s), and will not get failures, such as {s,g}etattr, {s,g}getxattr, stat, chown/chgrp, chmod, touch, unlink, and so on. For an old client, since it will not recognize the new pattern flag LOV_PATTERN_F_HOLE. So the LOV EA with hole will be dicarded with failure, but it will not cause the client to be crashed. Signed-off-by: Fan Yong <fan.yong@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4675 Reviewed-on: http://review.whamcloud.com/10042 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Alex Zhuravlev <alexey.zhuravlev@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 69bed64..87eef4c 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -1289,6 +1289,7 @@ void lustre_swab_ptlrpc_body(struct ptlrpc_body *pb); #define OBD_CONNECT_OPEN_BY_FID 0x20000000000000ULL /* open by fid won't pack * name in request */ +#define OBD_CONNECT_LFSCK 0x40000000000000ULL/* support online LFSCK */ /* XXX README XXX: * Please DO NOT add flag values here before first ensuring that this same diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index 8398c4f..9e38ed3 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -284,9 +284,9 @@ struct ost_id { #define LOV_PATTERN_CMOBD 0x200 #define LOV_PATTERN_F_MASK 0xffff0000 +#define LOV_PATTERN_F_HOLE 0x40000000 /* there is hole in LOV EA */ #define LOV_PATTERN_F_RELEASED 0x80000000 /* HSM released file */ - #define LOV_MAXPOOLNAME 16 #define LOV_POOLNAMEF "%.16s" diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index ac59cd6..dd44ee8 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -189,7 +189,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, OBD_CONNECT_PINGLESS | OBD_CONNECT_MAX_EASIZE | OBD_CONNECT_FLOCK_DEAD | - OBD_CONNECT_DISP_STRIPE; + OBD_CONNECT_DISP_STRIPE | OBD_CONNECT_LFSCK; if (sbi->ll_flags & LL_SBI_SOM_PREVIEW) data->ocd_connect_flags |= OBD_CONNECT_SOM; diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c index 84032a5..95126c3 100644 --- a/drivers/staging/lustre/lustre/lov/lov_io.c +++ b/drivers/staging/lustre/lustre/lov/lov_io.c @@ -298,8 +298,8 @@ static int lov_io_subio_init(const struct lu_env *env, struct lov_io *lio, return result; } -static void lov_io_slice_init(struct lov_io *lio, - struct lov_object *obj, struct cl_io *io) +static int lov_io_slice_init(struct lov_io *lio, struct lov_object *obj, + struct cl_io *io) { io->ci_result = 0; lio->lis_object = obj; @@ -314,6 +314,15 @@ static void lov_io_slice_init(struct lov_io *lio, lio->lis_io_endpos = lio->lis_endpos; if (cl_io_is_append(io)) { LASSERT(io->ci_type == CIT_WRITE); + + /* + * If there is LOV EA hole, then we may cannot locate + * the current file-tail exactly. + */ + if (unlikely(obj->lo_lsm->lsm_pattern & + LOV_PATTERN_F_HOLE)) + return -EIO; + lio->lis_pos = 0; lio->lis_endpos = OBD_OBJECT_EOF; } @@ -349,6 +358,7 @@ static void lov_io_slice_init(struct lov_io *lio, default: LBUG(); } + return 0; } static void lov_io_fini(const struct lu_env *env, const struct cl_io_slice *ios) @@ -870,7 +880,7 @@ int lov_io_init_raid0(const struct lu_env *env, struct cl_object *obj, struct lov_object *lov = cl2lov(obj); INIT_LIST_HEAD(&lio->lis_active); - lov_io_slice_init(lio, lov, io); + io->ci_result = lov_io_slice_init(lio, lov, io); if (io->ci_result == 0) { io->ci_result = lov_io_subio_init(env, lio, io); if (io->ci_result == 0) { diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c index c83d28e..f42ed17 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c @@ -97,6 +97,8 @@ static const char * const obd_connect_names[] = { "flock_deadlock", "disp_stripe", "unknown", + "lfsck", + "unknown", NULL }; diff --git a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c index bc27f8d..9d5d2c8c 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c +++ b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c @@ -1071,6 +1071,8 @@ void lustre_assert_wire_constants(void) "found 0x%.16llxULL\n", OBD_CONNECT_FLOCK_DEAD); LASSERTF(OBD_CONNECT_OPEN_BY_FID == 0x20000000000000ULL, "found 0x%.16llxULL\n", OBD_CONNECT_OPEN_BY_FID); + LASSERTF(OBD_CONNECT_LFSCK == 0x40000000000000ULL, "found 0x%.16llxULL\n", + OBD_CONNECT_LFSCK); LASSERTF(OBD_CKSUM_CRC32 == 0x00000001UL, "found 0x%.8xUL\n", (unsigned)OBD_CKSUM_CRC32); LASSERTF(OBD_CKSUM_ADLER == 0x00000002UL, "found 0x%.8xUL\n", -- cgit v0.10.2 From 711942df9593229b0a2c71895d2058573844f305 Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Tue, 16 Aug 2016 16:19:04 -0400 Subject: staging: lustre: lmv: Match MDT where the FID locates first With DNE every object can have two locks in different namespaces: lookup lock in space of MDT storing direntry and update/open lock in space of MDT storing inode. In lmv_find_cbdata/lmv_lock_lock, it should try the MDT that the FID maps to first, since this can be easily found, and only try others if that fails. In the error handler of lmv_add_targets, it should check whether ld_tgt_count is being increased before ld_tgt_count is being -1. Signed-off-by: wang di <di.wang@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4098 Reviewed-on: http://review.whamcloud.com/8019 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Fan Yong <fan.yong@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/lmv/lmv_internal.h b/drivers/staging/lustre/lustre/lmv/lmv_internal.h index dbd1da6..faf6a7b 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_internal.h +++ b/drivers/staging/lustre/lustre/lmv/lmv_internal.h @@ -64,35 +64,56 @@ int lmv_revalidate_slaves(struct obd_export *exp, struct mdt_body *mbody, int extra_lock_flags); static inline struct lmv_tgt_desc * -lmv_get_target(struct lmv_obd *lmv, u32 mds) +lmv_get_target(struct lmv_obd *lmv, u32 mdt_idx, int *index) { - int count = lmv->desc.ld_tgt_count; int i; - for (i = 0; i < count; i++) { + for (i = 0; i < lmv->desc.ld_tgt_count; i++) { if (!lmv->tgts[i]) continue; - if (lmv->tgts[i]->ltd_idx == mds) + if (lmv->tgts[i]->ltd_idx == mdt_idx) { + if (index) + *index = i; return lmv->tgts[i]; + } } return ERR_PTR(-ENODEV); } -static inline struct lmv_tgt_desc * -lmv_find_target(struct lmv_obd *lmv, const struct lu_fid *fid) +static inline int +lmv_find_target_index(struct lmv_obd *lmv, const struct lu_fid *fid) { - u32 mds = 0; - int rc; + struct lmv_tgt_desc *ltd; + u32 mdt_idx = 0; + int index = 0; if (lmv->desc.ld_tgt_count > 1) { - rc = lmv_fld_lookup(lmv, fid, &mds); - if (rc) - return ERR_PTR(rc); + int rc; + + rc = lmv_fld_lookup(lmv, fid, &mdt_idx); + if (rc < 0) + return rc; } - return lmv_get_target(lmv, mds); + ltd = lmv_get_target(lmv, mdt_idx, &index); + if (IS_ERR(ltd)) + return PTR_ERR(ltd); + + return index; +} + +static inline struct lmv_tgt_desc * +lmv_find_target(struct lmv_obd *lmv, const struct lu_fid *fid) +{ + int index; + + index = lmv_find_target_index(lmv, fid); + if (index < 0) + return ERR_PTR(index); + + return lmv->tgts[index]; } static inline int lmv_stripe_md_size(int stripe_count) diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 9821f69..6917a03 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -480,6 +480,7 @@ static int lmv_add_target(struct obd_device *obd, struct obd_uuid *uuidp, { struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt; + int orig_tgt_count = 0; int rc = 0; CDEBUG(D_CONFIG, "Target uuid: %s. index %d\n", uuidp->uuid, index); @@ -549,14 +550,17 @@ static int lmv_add_target(struct obd_device *obd, struct obd_uuid *uuidp, tgt->ltd_uuid = *uuidp; tgt->ltd_active = 0; lmv->tgts[index] = tgt; - if (index >= lmv->desc.ld_tgt_count) + if (index >= lmv->desc.ld_tgt_count) { + orig_tgt_count = lmv->desc.ld_tgt_count; lmv->desc.ld_tgt_count = index + 1; + } if (lmv->connected) { rc = lmv_connect_mdc(obd, tgt); if (rc) { spin_lock(&lmv->lmv_lock); - lmv->desc.ld_tgt_count--; + if (lmv->desc.ld_tgt_count == index + 1) + lmv->desc.ld_tgt_count = orig_tgt_count; memset(tgt, 0, sizeof(*tgt)); spin_unlock(&lmv->lmv_lock); } else { @@ -1263,7 +1267,7 @@ int __lmv_fid_alloc(struct lmv_obd *lmv, struct lu_fid *fid, u32 mds) struct lmv_tgt_desc *tgt; int rc; - tgt = lmv_get_target(lmv, mds); + tgt = lmv_get_target(lmv, mds, NULL); if (IS_ERR(tgt)) return PTR_ERR(tgt); @@ -1610,6 +1614,7 @@ static int lmv_find_cbdata(struct obd_export *exp, const struct lu_fid *fid, { struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; + int tgt; int i; int rc; @@ -1622,12 +1627,22 @@ static int lmv_find_cbdata(struct obd_export *exp, const struct lu_fid *fid, /* * With DNE every object can have two locks in different namespaces: * lookup lock in space of MDT storing direntry and update/open lock in - * space of MDT storing inode. + * space of MDT storing inode. Try the MDT that the FID maps to first, + * since this can be easily found, and only try others if that fails. */ - for (i = 0; i < lmv->desc.ld_tgt_count; i++) { - if (!lmv->tgts[i] || !lmv->tgts[i]->ltd_exp) + for (i = 0, tgt = lmv_find_target_index(lmv, fid); + i < lmv->desc.ld_tgt_count; + i++, tgt = (tgt + 1) % lmv->desc.ld_tgt_count) { + if (tgt < 0) { + CDEBUG(D_HA, "%s: "DFID" is inaccessible: rc = %d\n", + obd->obd_name, PFID(fid), tgt); + tgt = 0; + } + + if (!lmv->tgts[tgt] || !lmv->tgts[tgt]->ltd_exp) continue; - rc = md_find_cbdata(lmv->tgts[i]->ltd_exp, fid, it, data); + + rc = md_find_cbdata(lmv->tgts[tgt]->ltd_exp, fid, it, data); if (rc) return rc; } @@ -1676,7 +1691,7 @@ lmv_locate_target_for_name(struct lmv_obd *lmv, struct lmv_stripe_md *lsm, *fid = oinfo->lmo_fid; *mds = oinfo->lmo_mds; - tgt = lmv_get_target(lmv, *mds); + tgt = lmv_get_target(lmv, *mds, NULL); CDEBUG(D_INFO, "locate on mds %u "DFID"\n", *mds, PFID(fid)); return tgt; @@ -2866,24 +2881,32 @@ static enum ldlm_mode lmv_lock_match(struct obd_export *exp, __u64 flags, struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; enum ldlm_mode rc; + int tgt; int i; CDEBUG(D_INODE, "Lock match for "DFID"\n", PFID(fid)); /* - * With CMD every object can have two locks in different namespaces: - * lookup lock in space of mds storing direntry and update/open lock in - * space of mds storing inode. Thus we check all targets, not only that - * one fid was created in. + * With DNE every object can have two locks in different namespaces: + * lookup lock in space of MDT storing direntry and update/open lock in + * space of MDT storing inode. Try the MDT that the FID maps to first, + * since this can be easily found, and only try others if that fails. */ - for (i = 0; i < lmv->desc.ld_tgt_count; i++) { - struct lmv_tgt_desc *tgt = lmv->tgts[i]; + for (i = 0, tgt = lmv_find_target_index(lmv, fid); + i < lmv->desc.ld_tgt_count; + i++, tgt = (tgt + 1) % lmv->desc.ld_tgt_count) { + if (tgt < 0) { + CDEBUG(D_HA, "%s: "DFID" is inaccessible: rc = %d\n", + obd->obd_name, PFID(fid), tgt); + tgt = 0; + } - if (!tgt || !tgt->ltd_exp || !tgt->ltd_active) + if (!lmv->tgts[tgt] || !lmv->tgts[tgt]->ltd_exp || + !lmv->tgts[tgt]->ltd_active) continue; - rc = md_lock_match(tgt->ltd_exp, flags, fid, type, policy, mode, - lockh); + rc = md_lock_match(lmv->tgts[tgt]->ltd_exp, flags, fid, + type, policy, mode, lockh); if (rc) return rc; } -- cgit v0.10.2 From d07d4cb829dba5b08ee99b6b072245456f0078eb Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Tue, 16 Aug 2016 16:19:05 -0400 Subject: staging: lustre: llite: use the correct mode for striped directory Create striped directory with correct mode, which should be handling same as mkdir. Signed-off-by: wang di <di.wang@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4929 Reviewed-on: http://review.whamcloud.com/10028 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 3fed80d..a1b5143 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -694,28 +694,40 @@ static int ll_send_mgc_param(struct obd_export *mgc, char *string) return rc; } -static int ll_dir_setdirstripe(struct inode *dir, struct lmv_user_md *lump, - const char *filename) +/** + * Create striped directory with specified stripe(@lump) + * + * param[in] parent the parent of the directory. + * param[in] lump the specified stripes. + * param[in] dirname the name of the directory. + * param[in] mode the specified mode of the directory. + * + * retval =0 if striped directory is being created successfully. + * <0 if the creation is failed. + */ +static int ll_dir_setdirstripe(struct inode *parent, struct lmv_user_md *lump, + const char *dirname, umode_t mode) { struct ptlrpc_request *request = NULL; struct md_op_data *op_data; - struct ll_sb_info *sbi = ll_i2sbi(dir); - int mode; + struct ll_sb_info *sbi = ll_i2sbi(parent); int err; if (unlikely(lump->lum_magic != LMV_USER_MAGIC)) return -EINVAL; CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p) name %s stripe_offset %d, stripe_count: %u\n", - PFID(ll_inode2fid(dir)), dir, filename, + PFID(ll_inode2fid(parent)), parent, dirname, (int)lump->lum_stripe_offset, lump->lum_stripe_count); if (lump->lum_magic != cpu_to_le32(LMV_USER_MAGIC)) lustre_swab_lmv_user_md(lump); - mode = (~current_umask() & 0755) | S_IFDIR; - op_data = ll_prep_md_op_data(NULL, dir, NULL, filename, - strlen(filename), mode, LUSTRE_OPC_MKDIR, + if (!IS_POSIXACL(parent) || !exp_connect_umask(ll_i2mdexp(parent))) + mode &= ~current_umask(); + mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR; + op_data = ll_prep_md_op_data(NULL, parent, NULL, dirname, + strlen(dirname), mode, LUSTRE_OPC_MKDIR, lump); if (IS_ERR(op_data)) { err = PTR_ERR(op_data); @@ -1379,6 +1391,7 @@ out_free: char *filename; int namelen = 0; int lumlen = 0; + umode_t mode; int len; int rc; @@ -1412,11 +1425,12 @@ out_free: goto lmv_out_free; } - /** - * ll_dir_setdirstripe will be used to set dir stripe - * mdc_create--->mdt_reint_create (with dirstripe) - */ - rc = ll_dir_setdirstripe(inode, lum, filename); +#if OBD_OCD_VERSION(2, 9, 50, 0) > LUSTRE_VERSION_CODE + mode = data->ioc_type != 0 ? data->ioc_type : S_IRWXUGO; +#else + mode = data->ioc_type; +#endif + rc = ll_dir_setdirstripe(inode, lum, filename, mode); lmv_out_free: obd_ioctl_freedata(buf, len); return rc; -- cgit v0.10.2 From f7aafa7cadd618d16cfe0e4bb16eed15eb69e6d1 Mon Sep 17 00:00:00 2001 From: Niu Yawei <yawei.niu@intel.com> Date: Tue, 16 Aug 2016 16:19:06 -0400 Subject: staging: lustre: obd: rename lsr_padding to lsr_valid Simple variable rename. Signed-off-by: Niu Yawei <yawei.niu@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4345 Reviewed-on: http://review.whamcloud.com/10223 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Mike Pershin <mike.pershin@intel.com> Reviewed-by: Alex Zhuravlev <alexey.zhuravlev@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 87eef4c..bbf0c8d 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -3036,7 +3036,7 @@ struct llog_setattr64_rec { __u32 lsr_uid_h; __u32 lsr_gid; __u32 lsr_gid_h; - __u64 lsr_padding; + __u64 lsr_valid; struct llog_rec_tail lsr_tail; } __packed; diff --git a/drivers/staging/lustre/lustre/obdclass/llog_swab.c b/drivers/staging/lustre/lustre/obdclass/llog_swab.c index f7b9b19..0ec6361 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_swab.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_swab.c @@ -224,6 +224,7 @@ void lustre_swab_llog_rec(struct llog_rec_hdr *rec) __swab32s(&lsr->lsr_uid_h); __swab32s(&lsr->lsr_gid); __swab32s(&lsr->lsr_gid_h); + __swab64s(&lsr->lsr_valid); tail = &lsr->lsr_tail; break; } diff --git a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c index 9d5d2c8c..8dbaf32 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c +++ b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c @@ -3170,10 +3170,10 @@ void lustre_assert_wire_constants(void) (long long)(int)offsetof(struct llog_setattr64_rec, lsr_gid_h)); LASSERTF((int)sizeof(((struct llog_setattr64_rec *)0)->lsr_gid_h) == 4, "found %lld\n", (long long)(int)sizeof(((struct llog_setattr64_rec *)0)->lsr_gid_h)); - LASSERTF((int)offsetof(struct llog_setattr64_rec, lsr_padding) == 48, "found %lld\n", - (long long)(int)offsetof(struct llog_setattr64_rec, lsr_padding)); - LASSERTF((int)sizeof(((struct llog_setattr64_rec *)0)->lsr_padding) == 8, "found %lld\n", - (long long)(int)sizeof(((struct llog_setattr64_rec *)0)->lsr_padding)); + LASSERTF((int)offsetof(struct llog_setattr64_rec, lsr_valid) == 48, "found %lld\n", + (long long)(int)offsetof(struct llog_setattr64_rec, lsr_valid)); + LASSERTF((int)sizeof(((struct llog_setattr64_rec *)0)->lsr_valid) == 8, "found %lld\n", + (long long)(int)sizeof(((struct llog_setattr64_rec *)0)->lsr_valid)); LASSERTF((int)offsetof(struct llog_setattr64_rec, lsr_tail) == 56, "found %lld\n", (long long)(int)offsetof(struct llog_setattr64_rec, lsr_tail)); LASSERTF((int)sizeof(((struct llog_setattr64_rec *)0)->lsr_tail) == 8, "found %lld\n", -- cgit v0.10.2 From 50ccd16ea29af542fc61aed0f0311cb287234a83 Mon Sep 17 00:00:00 2001 From: Hongchao Zhang <hongchao.zhang@intel.com> Date: Tue, 16 Aug 2016 16:19:07 -0400 Subject: staging: lustre: llite: set dir LOV xattr length variable the LOV xattr of directory could be either lov_user_md_v1 (size is 32) or lov_user_md_v3 (size is 48), then the actual size of the LOV xattr should be return. Signed-off-by: Hongchao Zhang <hongchao.zhang@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5100 Reviewed-on: http://review.whamcloud.com/10453 Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: Alex Zhuravlev <alexey.zhuravlev@intel.com> Reviewed-by: jacques-Charles Lafoucriere <jacques-charles.lafoucriere@cea.fr> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/xattr.c b/drivers/staging/lustre/lustre/llite/xattr.c index aa0738b..146da6b 100644 --- a/drivers/staging/lustre/lustre/llite/xattr.c +++ b/drivers/staging/lustre/lustre/llite/xattr.c @@ -379,14 +379,6 @@ static int ll_xattr_get(const struct xattr_handler *handler, if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode)) return -ENODATA; - if (size == 0 && S_ISDIR(inode->i_mode)) { - /* XXX directory EA is fix for now, optimize to save - * RPC transfer - */ - rc = sizeof(struct lov_user_md); - goto out; - } - lsm = ccc_inode_lsm_get(inode); if (!lsm) { if (S_ISDIR(inode->i_mode)) { -- cgit v0.10.2 From 2e1b5b8b350528201c43f2af59f5e9e805432ace Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Tue, 16 Aug 2016 16:19:08 -0400 Subject: staging: lustre: mdt: add mbo_ prefix to members of struct mdt_body Rename each member of struct mdt_body, adding the prefix mbo_. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2675 Reviewed-on: http://review.whamcloud.com/10202 Reviewed-by: Bob Glossman <bob.glossman@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Mike Pershin <mike.pershin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index bbf0c8d..400ab3c 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -2097,43 +2097,43 @@ enum md_transient_state { }; struct mdt_body { - struct lu_fid fid1; - struct lu_fid fid2; - struct lustre_handle handle; - __u64 valid; - __u64 size; /* Offset, in the case of MDS_READPAGE */ - __s64 mtime; - __s64 atime; - __s64 ctime; - __u64 blocks; /* XID, in the case of MDS_READPAGE */ - __u64 ioepoch; - __u64 t_state; /* transient file state defined in - * enum md_transient_state - * was "ino" until 2.4.0 - */ - __u32 fsuid; - __u32 fsgid; - __u32 capability; - __u32 mode; - __u32 uid; - __u32 gid; - __u32 flags; /* from vfs for pin/unpin, LUSTRE_BFLAG close */ - __u32 rdev; - __u32 nlink; /* #bytes to read in the case of MDS_READPAGE */ - __u32 unused2; /* was "generation" until 2.4.0 */ - __u32 suppgid; - __u32 eadatasize; - __u32 aclsize; - __u32 max_mdsize; - __u32 max_cookiesize; - __u32 uid_h; /* high 32-bits of uid, for FUID */ - __u32 gid_h; /* high 32-bits of gid, for FUID */ - __u32 padding_5; /* also fix lustre_swab_mdt_body */ - __u64 padding_6; - __u64 padding_7; - __u64 padding_8; - __u64 padding_9; - __u64 padding_10; + struct lu_fid mbo_fid1; + struct lu_fid mbo_fid2; + struct lustre_handle mbo_handle; + __u64 mbo_valid; + __u64 mbo_size; /* Offset, in the case of MDS_READPAGE */ + __s64 mbo_mtime; + __s64 mbo_atime; + __s64 mbo_ctime; + __u64 mbo_blocks; /* XID, in the case of MDS_READPAGE */ + __u64 mbo_ioepoch; + __u64 mbo_t_state; /* transient file state defined in + * enum md_transient_state + * was "ino" until 2.4.0 + */ + __u32 mbo_fsuid; + __u32 mbo_fsgid; + __u32 mbo_capability; + __u32 mbo_mode; + __u32 mbo_uid; + __u32 mbo_gid; + __u32 mbo_flags; + __u32 mbo_rdev; + __u32 mbo_nlink; /* #bytes to read in the case of MDS_READPAGE */ + __u32 mbo_unused2; /* was "generation" until 2.4.0 */ + __u32 mbo_suppgid; + __u32 mbo_eadatasize; + __u32 mbo_aclsize; + __u32 mbo_max_mdsize; + __u32 mbo_max_cookiesize; + __u32 mbo_uid_h; /* high 32-bits of uid, for FUID */ + __u32 mbo_gid_h; /* high 32-bits of gid, for FUID */ + __u32 mbo_padding_5; /* also fix lustre_swab_mdt_body */ + __u64 mbo_padding_6; + __u64 mbo_padding_7; + __u64 mbo_padding_8; + __u64 mbo_padding_9; + __u64 mbo_padding_10; }; /* 216 */ void lustre_swab_mdt_body(struct mdt_body *b); diff --git a/drivers/staging/lustre/lustre/include/lustre_mdc.h b/drivers/staging/lustre/lustre/include/lustre_mdc.h index bf6f87a..9549fb4 100644 --- a/drivers/staging/lustre/lustre/include/lustre_mdc.h +++ b/drivers/staging/lustre/lustre/include/lustre_mdc.h @@ -163,18 +163,18 @@ static inline void mdc_put_rpc_lock(struct mdc_rpc_lock *lck, static inline void mdc_update_max_ea_from_body(struct obd_export *exp, struct mdt_body *body) { - if (body->valid & OBD_MD_FLMODEASIZE) { + if (body->mbo_valid & OBD_MD_FLMODEASIZE) { struct client_obd *cli = &exp->exp_obd->u.cli; - if (cli->cl_max_mds_easize < body->max_mdsize) { - cli->cl_max_mds_easize = body->max_mdsize; + if (cli->cl_max_mds_easize < body->mbo_max_mdsize) { + cli->cl_max_mds_easize = body->mbo_max_mdsize; cli->cl_default_mds_easize = - min_t(__u32, body->max_mdsize, PAGE_SIZE); + min_t(__u32, body->mbo_max_mdsize, PAGE_SIZE); } - if (cli->cl_max_mds_cookiesize < body->max_cookiesize) { - cli->cl_max_mds_cookiesize = body->max_cookiesize; + if (cli->cl_max_mds_cookiesize < body->mbo_max_cookiesize) { + cli->cl_max_mds_cookiesize = body->mbo_max_cookiesize; cli->cl_default_mds_cookiesize = - min_t(__u32, body->max_cookiesize, PAGE_SIZE); + min_t(__u32, body->mbo_max_cookiesize, PAGE_SIZE); } } } diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index a1b5143..9c7fa8f 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -188,8 +188,8 @@ static int ll_dir_filler(void *_hash, struct page *page0) } else if (rc == 0) { body = req_capsule_server_get(&request->rq_pill, &RMF_MDT_BODY); /* Checked by mdc_readpage() */ - if (body->valid & OBD_MD_FLSIZE) - i_size_write(inode, body->size); + if (body->mbo_valid & OBD_MD_FLSIZE) + i_size_write(inode, body->mbo_size); nrdpgs = (request->rq_bulk->bd_nob_transferred+PAGE_SIZE-1) >> PAGE_SHIFT; @@ -894,9 +894,9 @@ int ll_dir_getstripe(struct inode *inode, void **plmm, int *plmm_size, body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); - lmmsize = body->eadatasize; + lmmsize = body->mbo_eadatasize; - if (!(body->valid & (OBD_MD_FLEASIZE | OBD_MD_FLDIREA)) || + if (!(body->mbo_valid & (OBD_MD_FLEASIZE | OBD_MD_FLDIREA)) || lmmsize == 0) { rc = -ENODATA; goto out; @@ -1639,18 +1639,18 @@ skip_lmm: lstat_t st = { 0 }; st.st_dev = inode->i_sb->s_dev; - st.st_mode = body->mode; - st.st_nlink = body->nlink; - st.st_uid = body->uid; - st.st_gid = body->gid; - st.st_rdev = body->rdev; - st.st_size = body->size; + st.st_mode = body->mbo_mode; + st.st_nlink = body->mbo_nlink; + st.st_uid = body->mbo_uid; + st.st_gid = body->mbo_gid; + st.st_rdev = body->mbo_rdev; + st.st_size = body->mbo_size; st.st_blksize = PAGE_SIZE; - st.st_blocks = body->blocks; - st.st_atime = body->atime; - st.st_mtime = body->mtime; - st.st_ctime = body->ctime; - st.st_ino = cl_fid_build_ino(&body->fid1, + st.st_blocks = body->mbo_blocks; + st.st_atime = body->mbo_atime; + st.st_mtime = body->mbo_mtime; + st.st_ctime = body->mbo_ctime; + st.st_ino = cl_fid_build_ino(&body->mbo_fid1, sbi->ll_flags & LL_SBI_32BIT_API); diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 90a7170..563cdf6 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -200,7 +200,7 @@ static int ll_close_inode_openhandle(struct obd_export *md_exp, struct mdt_body *body; body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); - if (!(body->valid & OBD_MD_FLRELEASED)) + if (!(body->mbo_valid & OBD_MD_FLRELEASED)) rc = -EBUSY; } @@ -482,8 +482,8 @@ static int ll_och_fill(struct obd_export *md_exp, struct lookup_intent *it, struct mdt_body *body; body = req_capsule_server_get(&it->it_request->rq_pill, &RMF_MDT_BODY); - och->och_fh = body->handle; - och->och_fid = body->fid1; + och->och_fh = body->mbo_handle; + och->och_fid = body->mbo_fid1; och->och_lease_handle.cookie = it->it_lock_handle; och->och_magic = OBD_CLIENT_HANDLE_MAGIC; och->och_flags = it->it_flags; @@ -511,7 +511,7 @@ static int ll_local_open(struct file *file, struct lookup_intent *it, body = req_capsule_server_get(&it->it_request->rq_pill, &RMF_MDT_BODY); - ll_ioepoch_open(lli, body->ioepoch); + ll_ioepoch_open(lli, body->mbo_ioepoch); } LUSTRE_FPRIVATE(file) = fd; @@ -1451,9 +1451,9 @@ int ll_lov_getstripe_ea_info(struct inode *inode, const char *filename, body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); - lmmsize = body->eadatasize; + lmmsize = body->mbo_eadatasize; - if (!(body->valid & (OBD_MD_FLEASIZE | OBD_MD_FLDIREA)) || + if (!(body->mbo_valid & (OBD_MD_FLEASIZE | OBD_MD_FLDIREA)) || lmmsize == 0) { rc = -ENODATA; goto out; @@ -1484,13 +1484,13 @@ int ll_lov_getstripe_ea_info(struct inode *inode, const char *filename, */ if (lmm->lmm_magic == cpu_to_le32(LOV_MAGIC_V1)) { lustre_swab_lov_user_md_v1((struct lov_user_md_v1 *)lmm); - if (S_ISREG(body->mode)) + if (S_ISREG(body->mbo_mode)) lustre_swab_lov_user_md_objects( ((struct lov_user_md_v1 *)lmm)->lmm_objects, stripe_count); } else if (lmm->lmm_magic == cpu_to_le32(LOV_MAGIC_V3)) { lustre_swab_lov_user_md_v3((struct lov_user_md_v3 *)lmm); - if (S_ISREG(body->mode)) + if (S_ISREG(body->mbo_mode)) lustre_swab_lov_user_md_objects( ((struct lov_user_md_v3 *)lmm)->lmm_objects, stripe_count); @@ -2861,7 +2861,7 @@ int ll_get_fid_by_name(struct inode *parent, const char *name, goto out_req; } if (fid) - *fid = body->fid1; + *fid = body->mbo_fid1; out_req: ptlrpc_req_finished(req); return rc; @@ -3583,7 +3583,7 @@ static int ll_layout_fetch(struct inode *inode, struct ldlm_lock *lock) goto out; } - lmmsize = body->eadatasize; + lmmsize = body->mbo_eadatasize; if (lmmsize == 0) /* empty layout */ { rc = 0; goto out; diff --git a/drivers/staging/lustre/lustre/llite/lcommon_cl.c b/drivers/staging/lustre/lustre/llite/lcommon_cl.c index 396e4e4f..eed464b 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_cl.c @@ -154,7 +154,7 @@ int cl_file_inode_init(struct inode *inode, struct lustre_md *md) int result = 0; int refcheck; - LASSERT(md->body->valid & OBD_MD_FLID); + LASSERT(md->body->mbo_valid & OBD_MD_FLID); LASSERT(S_ISREG(inode->i_mode)); env = cl_env_get(&refcheck); diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index dd44ee8..5f6343a 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -1035,7 +1035,7 @@ static struct inode *ll_iget_anon_dir(struct super_block *sb, struct lmv_stripe_md *lsm = md->lmv; inode->i_mode = (inode->i_mode & ~S_IFMT) | - (body->mode & S_IFMT); + (body->mbo_mode & S_IFMT); LASSERTF(S_ISDIR(inode->i_mode), "Not slave inode "DFID"\n", PFID(fid)); @@ -1051,7 +1051,7 @@ static struct inode *ll_iget_anon_dir(struct super_block *sb, LASSERT(lsm); /* master object FID */ - lli->lli_pfid = body->fid1; + lli->lli_pfid = body->mbo_fid1; CDEBUG(D_INODE, "lli %p slave "DFID" master "DFID"\n", lli, PFID(fid), PFID(&lli->lli_pfid)); unlock_new_inode(inode); @@ -1320,8 +1320,8 @@ static int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data, op_data->op_attr.ia_valid = ia_valid; /* Extract epoch data if obtained. */ - op_data->op_handle = md.body->handle; - op_data->op_ioepoch = md.body->ioepoch; + op_data->op_handle = md.body->mbo_handle; + op_data->op_ioepoch = md.body->mbo_ioepoch; rc = ll_update_inode(inode, &md); ptlrpc_req_finished(request); @@ -1689,7 +1689,7 @@ int ll_update_inode(struct inode *inode, struct lustre_md *md) struct lov_stripe_md *lsm = md->lsm; struct ll_sb_info *sbi = ll_i2sbi(inode); - LASSERT((lsm != NULL) == ((body->valid & OBD_MD_FLEASIZE) != 0)); + LASSERT((lsm != NULL) == ((body->mbo_valid & OBD_MD_FLEASIZE) != 0)); if (lsm) { if (!lli->lli_has_smd && !(sbi->ll_flags & LL_SBI_LAYOUT_LOCK)) @@ -1709,7 +1709,7 @@ int ll_update_inode(struct inode *inode, struct lustre_md *md) } #ifdef CONFIG_FS_POSIX_ACL - if (body->valid & OBD_MD_FLACL) { + if (body->mbo_valid & OBD_MD_FLACL) { spin_lock(&lli->lli_lock); if (lli->lli_posix_acl) posix_acl_release(lli->lli_posix_acl); @@ -1717,65 +1717,65 @@ int ll_update_inode(struct inode *inode, struct lustre_md *md) spin_unlock(&lli->lli_lock); } #endif - inode->i_ino = cl_fid_build_ino(&body->fid1, + inode->i_ino = cl_fid_build_ino(&body->mbo_fid1, sbi->ll_flags & LL_SBI_32BIT_API); - inode->i_generation = cl_fid_build_gen(&body->fid1); + inode->i_generation = cl_fid_build_gen(&body->mbo_fid1); - if (body->valid & OBD_MD_FLATIME) { - if (body->atime > LTIME_S(inode->i_atime)) - LTIME_S(inode->i_atime) = body->atime; - lli->lli_atime = body->atime; + if (body->mbo_valid & OBD_MD_FLATIME) { + if (body->mbo_atime > LTIME_S(inode->i_atime)) + LTIME_S(inode->i_atime) = body->mbo_atime; + lli->lli_atime = body->mbo_atime; } - if (body->valid & OBD_MD_FLMTIME) { - if (body->mtime > LTIME_S(inode->i_mtime)) { + if (body->mbo_valid & OBD_MD_FLMTIME) { + if (body->mbo_mtime > LTIME_S(inode->i_mtime)) { CDEBUG(D_INODE, "setting ino %lu mtime from %lu to %llu\n", inode->i_ino, LTIME_S(inode->i_mtime), - body->mtime); - LTIME_S(inode->i_mtime) = body->mtime; + body->mbo_mtime); + LTIME_S(inode->i_mtime) = body->mbo_mtime; } - lli->lli_mtime = body->mtime; + lli->lli_mtime = body->mbo_mtime; } - if (body->valid & OBD_MD_FLCTIME) { - if (body->ctime > LTIME_S(inode->i_ctime)) - LTIME_S(inode->i_ctime) = body->ctime; - lli->lli_ctime = body->ctime; + if (body->mbo_valid & OBD_MD_FLCTIME) { + if (body->mbo_ctime > LTIME_S(inode->i_ctime)) + LTIME_S(inode->i_ctime) = body->mbo_ctime; + lli->lli_ctime = body->mbo_ctime; } - if (body->valid & OBD_MD_FLMODE) - inode->i_mode = (inode->i_mode & S_IFMT)|(body->mode & ~S_IFMT); - if (body->valid & OBD_MD_FLTYPE) - inode->i_mode = (inode->i_mode & ~S_IFMT)|(body->mode & S_IFMT); + if (body->mbo_valid & OBD_MD_FLMODE) + inode->i_mode = (inode->i_mode & S_IFMT)|(body->mbo_mode & ~S_IFMT); + if (body->mbo_valid & OBD_MD_FLTYPE) + inode->i_mode = (inode->i_mode & ~S_IFMT)|(body->mbo_mode & S_IFMT); LASSERT(inode->i_mode != 0); if (S_ISREG(inode->i_mode)) inode->i_blkbits = min(PTLRPC_MAX_BRW_BITS + 1, LL_MAX_BLKSIZE_BITS); else inode->i_blkbits = inode->i_sb->s_blocksize_bits; - if (body->valid & OBD_MD_FLUID) - inode->i_uid = make_kuid(&init_user_ns, body->uid); - if (body->valid & OBD_MD_FLGID) - inode->i_gid = make_kgid(&init_user_ns, body->gid); - if (body->valid & OBD_MD_FLFLAGS) - inode->i_flags = ll_ext_to_inode_flags(body->flags); - if (body->valid & OBD_MD_FLNLINK) - set_nlink(inode, body->nlink); - if (body->valid & OBD_MD_FLRDEV) - inode->i_rdev = old_decode_dev(body->rdev); - - if (body->valid & OBD_MD_FLID) { + if (body->mbo_valid & OBD_MD_FLUID) + inode->i_uid = make_kuid(&init_user_ns, body->mbo_uid); + if (body->mbo_valid & OBD_MD_FLGID) + inode->i_gid = make_kgid(&init_user_ns, body->mbo_gid); + if (body->mbo_valid & OBD_MD_FLFLAGS) + inode->i_flags = ll_ext_to_inode_flags(body->mbo_flags); + if (body->mbo_valid & OBD_MD_FLNLINK) + set_nlink(inode, body->mbo_nlink); + if (body->mbo_valid & OBD_MD_FLRDEV) + inode->i_rdev = old_decode_dev(body->mbo_rdev); + + if (body->mbo_valid & OBD_MD_FLID) { /* FID shouldn't be changed! */ if (fid_is_sane(&lli->lli_fid)) { - LASSERTF(lu_fid_eq(&lli->lli_fid, &body->fid1), + LASSERTF(lu_fid_eq(&lli->lli_fid, &body->mbo_fid1), "Trying to change FID "DFID" to the "DFID", inode "DFID"(%p)\n", - PFID(&lli->lli_fid), PFID(&body->fid1), + PFID(&lli->lli_fid), PFID(&body->mbo_fid1), PFID(ll_inode2fid(inode)), inode); } else { - lli->lli_fid = body->fid1; + lli->lli_fid = body->mbo_fid1; } } LASSERT(fid_seq(&lli->lli_fid) != 0); - if (body->valid & OBD_MD_FLSIZE) { + if (body->mbo_valid & OBD_MD_FLSIZE) { if (exp_connect_som(ll_i2mdexp(inode)) && S_ISREG(inode->i_mode)) { struct lustre_handle lockh; @@ -1802,7 +1802,7 @@ int ll_update_inode(struct inode *inode, struct lustre_md *md) /* Use old size assignment to avoid * deadlock bz14138 & bz14326 */ - i_size_write(inode, body->size); + i_size_write(inode, body->mbo_size); spin_lock(&lli->lli_lock); lli->lli_flags |= LLIF_MDS_SIZE_LOCK; spin_unlock(&lli->lli_lock); @@ -1813,18 +1813,18 @@ int ll_update_inode(struct inode *inode, struct lustre_md *md) /* Use old size assignment to avoid * deadlock bz14138 & bz14326 */ - i_size_write(inode, body->size); + i_size_write(inode, body->mbo_size); CDEBUG(D_VFSTRACE, "inode=%lu, updating i_size %llu\n", - inode->i_ino, (unsigned long long)body->size); + inode->i_ino, (unsigned long long)body->mbo_size); } - if (body->valid & OBD_MD_FLBLOCKS) - inode->i_blocks = body->blocks; + if (body->mbo_valid & OBD_MD_FLBLOCKS) + inode->i_blocks = body->mbo_blocks; } - if (body->valid & OBD_MD_TSTATE) { - if (body->t_state & MS_RESTORE) + if (body->mbo_valid & OBD_MD_TSTATE) { + if (body->mbo_t_state & MS_RESTORE) lli->lli_flags |= LLIF_FILE_RESTORING; } @@ -1936,7 +1936,7 @@ int ll_iocontrol(struct inode *inode, struct file *file, body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); - flags = body->flags; + flags = body->mbo_flags; ptlrpc_req_finished(req); @@ -2118,9 +2118,9 @@ void ll_open_cleanup(struct super_block *sb, struct ptlrpc_request *open_req) if (!op_data) return; - op_data->op_fid1 = body->fid1; - op_data->op_ioepoch = body->ioepoch; - op_data->op_handle = body->handle; + op_data->op_fid1 = body->mbo_fid1; + op_data->op_ioepoch = body->mbo_ioepoch; + op_data->op_handle = body->mbo_handle; op_data->op_mod_time = get_seconds(); md_close(exp, op_data, NULL, &close_req); ptlrpc_req_finished(close_req); @@ -2152,15 +2152,15 @@ int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, * At this point server returns to client's same fid as client * generated for creating. So using ->fid1 is okay here. */ - if (!fid_is_sane(&md.body->fid1)) { + if (!fid_is_sane(&md.body->mbo_fid1)) { CERROR("%s: Fid is insane " DFID "\n", ll_get_fsname(sb, NULL, 0), - PFID(&md.body->fid1)); + PFID(&md.body->mbo_fid1)); rc = -EINVAL; goto out; } - *inode = ll_iget(sb, cl_fid_build_ino(&md.body->fid1, + *inode = ll_iget(sb, cl_fid_build_ino(&md.body->mbo_fid1, sbi->ll_flags & LL_SBI_32BIT_API), &md); if (IS_ERR(*inode)) { diff --git a/drivers/staging/lustre/lustre/llite/llite_nfs.c b/drivers/staging/lustre/lustre/llite/llite_nfs.c index 06a8199..ac96d89 100644 --- a/drivers/staging/lustre/lustre/llite/llite_nfs.c +++ b/drivers/staging/lustre/lustre/llite/llite_nfs.c @@ -343,10 +343,10 @@ int ll_dir_get_parent_fid(struct inode *dir, struct lu_fid *parent_fid) * LU-3952: MDT may lost the FID of its parent, we should not crash * the NFS server, ll_iget_for_nfs() will handle the error. */ - if (body->valid & OBD_MD_FLID) { + if (body->mbo_valid & OBD_MD_FLID) { CDEBUG(D_INFO, "parent for " DFID " is " DFID "\n", - PFID(ll_inode2fid(dir)), PFID(&body->fid1)); - *parent_fid = body->fid1; + PFID(ll_inode2fid(dir)), PFID(&body->mbo_fid1)); + *parent_fid = body->mbo_fid1; } ptlrpc_req_finished(req); diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index 581b083..ac0f442 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -56,12 +56,12 @@ static int ll_test_inode(struct inode *inode, void *opaque) struct ll_inode_info *lli = ll_i2info(inode); struct lustre_md *md = opaque; - if (unlikely(!(md->body->valid & OBD_MD_FLID))) { + if (unlikely(!(md->body->mbo_valid & OBD_MD_FLID))) { CERROR("MDS body missing FID\n"); return 0; } - if (!lu_fid_eq(&lli->lli_fid, &md->body->fid1)) + if (!lu_fid_eq(&lli->lli_fid, &md->body->mbo_fid1)) return 0; return 1; @@ -72,20 +72,20 @@ static int ll_set_inode(struct inode *inode, void *opaque) struct ll_inode_info *lli = ll_i2info(inode); struct mdt_body *body = ((struct lustre_md *)opaque)->body; - if (unlikely(!(body->valid & OBD_MD_FLID))) { + if (unlikely(!(body->mbo_valid & OBD_MD_FLID))) { CERROR("MDS body missing FID\n"); return -EINVAL; } - lli->lli_fid = body->fid1; - if (unlikely(!(body->valid & OBD_MD_FLTYPE))) { + lli->lli_fid = body->mbo_fid1; + if (unlikely(!(body->mbo_valid & OBD_MD_FLTYPE))) { CERROR("Can not initialize inode " DFID " without object type: valid = %#llx\n", - PFID(&lli->lli_fid), body->valid); + PFID(&lli->lli_fid), body->mbo_valid); return -EINVAL; } - inode->i_mode = (inode->i_mode & ~S_IFMT) | (body->mode & S_IFMT); + inode->i_mode = (inode->i_mode & ~S_IFMT) | (body->mbo_mode & S_IFMT); if (unlikely(inode->i_mode == 0)) { CERROR("Invalid inode "DFID" type\n", PFID(&lli->lli_fid)); return -EINVAL; @@ -131,7 +131,7 @@ struct inode *ll_iget(struct super_block *sb, ino_t hash, } else if (!(inode->i_state & (I_FREEING | I_CLEAR))) { rc = ll_update_inode(inode, md); CDEBUG(D_VFSTRACE, "got inode: "DFID"(%p): rc = %d\n", - PFID(&md->body->fid1), inode, rc); + PFID(&md->body->mbo_fid1), inode, rc); if (rc) { make_bad_inode(inode); iput(inode); @@ -774,16 +774,16 @@ void ll_update_times(struct ptlrpc_request *request, struct inode *inode) &RMF_MDT_BODY); LASSERT(body); - if (body->valid & OBD_MD_FLMTIME && - body->mtime > LTIME_S(inode->i_mtime)) { + if (body->mbo_valid & OBD_MD_FLMTIME && + body->mbo_mtime > LTIME_S(inode->i_mtime)) { CDEBUG(D_INODE, "setting fid "DFID" mtime from %lu to %llu\n", PFID(ll_inode2fid(inode)), LTIME_S(inode->i_mtime), - body->mtime); - LTIME_S(inode->i_mtime) = body->mtime; + body->mbo_mtime); + LTIME_S(inode->i_mtime) = body->mbo_mtime; } - if (body->valid & OBD_MD_FLCTIME && - body->ctime > LTIME_S(inode->i_ctime)) - LTIME_S(inode->i_ctime) = body->ctime; + if (body->mbo_valid & OBD_MD_FLCTIME && + body->mbo_ctime > LTIME_S(inode->i_ctime)) + LTIME_S(inode->i_ctime) = body->mbo_ctime; } static int ll_new_node(struct inode *dir, struct dentry *dentry, @@ -899,10 +899,10 @@ int ll_objects_destroy(struct ptlrpc_request *request, struct inode *dir) /* req is swabbed so this is safe */ body = req_capsule_server_get(&request->rq_pill, &RMF_MDT_BODY); - if (!(body->valid & OBD_MD_FLEASIZE)) + if (!(body->mbo_valid & OBD_MD_FLEASIZE)) return 0; - if (body->eadatasize == 0) { + if (body->mbo_eadatasize == 0) { CERROR("OBD_MD_FLEASIZE set but eadatasize zero\n"); rc = -EPROTO; goto out; @@ -914,10 +914,10 @@ int ll_objects_destroy(struct ptlrpc_request *request, struct inode *dir) * check it is complete and sensible. */ eadata = req_capsule_server_sized_get(&request->rq_pill, &RMF_MDT_MD, - body->eadatasize); + body->mbo_eadatasize); LASSERT(eadata); - rc = obd_unpackmd(ll_i2dtexp(dir), &lsm, eadata, body->eadatasize); + rc = obd_unpackmd(ll_i2dtexp(dir), &lsm, eadata, body->mbo_eadatasize); if (rc < 0) { CERROR("obd_unpackmd: %d\n", rc); goto out; @@ -931,10 +931,10 @@ int ll_objects_destroy(struct ptlrpc_request *request, struct inode *dir) } oa->o_oi = lsm->lsm_oi; - oa->o_mode = body->mode & S_IFMT; + oa->o_mode = body->mbo_mode & S_IFMT; oa->o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLGROUP; - if (body->valid & OBD_MD_FLCOOKIE) { + if (body->mbo_valid & OBD_MD_FLCOOKIE) { oa->o_valid |= OBD_MD_FLCOOKIE; oti.oti_logcookies = req_capsule_server_sized_get(&request->rq_pill, @@ -943,7 +943,7 @@ int ll_objects_destroy(struct ptlrpc_request *request, struct inode *dir) lsm->lsm_stripe_count); if (!oti.oti_logcookies) { oa->o_valid &= ~OBD_MD_FLCOOKIE; - body->valid &= ~OBD_MD_FLCOOKIE; + body->mbo_valid &= ~OBD_MD_FLCOOKIE; } } diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c index e8c1959..46b8faf 100644 --- a/drivers/staging/lustre/lustre/llite/statahead.c +++ b/drivers/staging/lustre/lustre/llite/statahead.c @@ -632,7 +632,7 @@ static void ll_post_statahead(struct ll_statahead_info *sai) /* XXX: No fid in reply, this is probably cross-ref case. * SA can't handle it yet. */ - if (body->valid & OBD_MD_MDS) { + if (body->mbo_valid & OBD_MD_MDS) { rc = -EAGAIN; goto out; } @@ -641,7 +641,7 @@ static void ll_post_statahead(struct ll_statahead_info *sai) * revalidate. */ /* unlinked and re-created with the same name */ - if (unlikely(!lu_fid_eq(&minfo->mi_data.op_fid2, &body->fid1))) { + if (unlikely(!lu_fid_eq(&minfo->mi_data.op_fid2, &body->mbo_fid1))) { entry->se_inode = NULL; iput(child); child = NULL; diff --git a/drivers/staging/lustre/lustre/llite/symlink.c b/drivers/staging/lustre/lustre/llite/symlink.c index 4601be9..47fb799 100644 --- a/drivers/staging/lustre/lustre/llite/symlink.c +++ b/drivers/staging/lustre/lustre/llite/symlink.c @@ -80,17 +80,17 @@ static int ll_readlink_internal(struct inode *inode, } body = req_capsule_server_get(&(*request)->rq_pill, &RMF_MDT_BODY); - if ((body->valid & OBD_MD_LINKNAME) == 0) { + if ((body->mbo_valid & OBD_MD_LINKNAME) == 0) { CERROR("OBD_MD_LINKNAME not set on reply\n"); rc = -EPROTO; goto failed; } LASSERT(symlen != 0); - if (body->eadatasize != symlen) { + if (body->mbo_eadatasize != symlen) { CERROR("%s: inode "DFID": symlink length %d not expected %d\n", ll_get_fsname(inode->i_sb, NULL, 0), - PFID(ll_inode2fid(inode)), body->eadatasize - 1, + PFID(ll_inode2fid(inode)), body->mbo_eadatasize - 1, symlen - 1); rc = -EPROTO; goto failed; diff --git a/drivers/staging/lustre/lustre/llite/xattr.c b/drivers/staging/lustre/lustre/llite/xattr.c index 146da6b..f252c26 100644 --- a/drivers/staging/lustre/lustre/llite/xattr.c +++ b/drivers/staging/lustre/lustre/llite/xattr.c @@ -263,32 +263,32 @@ getxattr_nocache: /* only detect the xattr size */ if (size == 0) { - rc = body->eadatasize; + rc = body->mbo_eadatasize; goto out; } - if (size < body->eadatasize) { + if (size < body->mbo_eadatasize) { CERROR("server bug: replied size %u > %u\n", - body->eadatasize, (int)size); + body->mbo_eadatasize, (int)size); rc = -ERANGE; goto out; } - if (body->eadatasize == 0) { + if (body->mbo_eadatasize == 0) { rc = -ENODATA; goto out; } /* do not need swab xattr data */ xdata = req_capsule_server_sized_get(&req->rq_pill, &RMF_EADATA, - body->eadatasize); + body->mbo_eadatasize); if (!xdata) { rc = -EFAULT; goto out; } - memcpy(buffer, xdata, body->eadatasize); - rc = body->eadatasize; + memcpy(buffer, xdata, body->mbo_eadatasize); + rc = body->mbo_eadatasize; } out_xattr: diff --git a/drivers/staging/lustre/lustre/llite/xattr_cache.c b/drivers/staging/lustre/lustre/llite/xattr_cache.c index 8089da8..b66542c 100644 --- a/drivers/staging/lustre/lustre/llite/xattr_cache.c +++ b/drivers/staging/lustre/lustre/llite/xattr_cache.c @@ -380,25 +380,25 @@ static int ll_xattr_cache_refill(struct inode *inode, struct lookup_intent *oit) } /* do not need swab xattr data */ xdata = req_capsule_server_sized_get(&req->rq_pill, &RMF_EADATA, - body->eadatasize); + body->mbo_eadatasize); xval = req_capsule_server_sized_get(&req->rq_pill, &RMF_EAVALS, - body->aclsize); + body->mbo_aclsize); xsizes = req_capsule_server_sized_get(&req->rq_pill, &RMF_EAVALS_LENS, - body->max_mdsize * sizeof(__u32)); + body->mbo_max_mdsize * sizeof(__u32)); if (!xdata || !xval || !xsizes) { CERROR("wrong setxattr reply\n"); rc = -EPROTO; goto out_destroy; } - xtail = xdata + body->eadatasize; - xvtail = xval + body->aclsize; + xtail = xdata + body->mbo_eadatasize; + xvtail = xval + body->mbo_aclsize; CDEBUG(D_CACHE, "caching: xdata=%p xtail=%p\n", xdata, xtail); ll_xattr_cache_init(lli); - for (i = 0; i < body->max_mdsize; i++) { + for (i = 0; i < body->mbo_max_mdsize; i++) { CDEBUG(D_CACHE, "caching [%s]=%.*s\n", xdata, *xsizes, xval); /* Perform consistency checks: attr names and vals in pill */ if (!memchr(xdata, 0, xtail - xdata)) { diff --git a/drivers/staging/lustre/lustre/lmv/lmv_intent.c b/drivers/staging/lustre/lustre/lmv/lmv_intent.c index 7f81e78..761ab24 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_intent.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_intent.c @@ -69,7 +69,7 @@ static int lmv_intent_remote(struct obd_export *exp, void *lmm, if (!body) return -EPROTO; - LASSERT((body->valid & OBD_MD_MDS)); + LASSERT((body->mbo_valid & OBD_MD_MDS)); /* * Unfortunately, we have to lie to MDC/MDS to retrieve @@ -88,9 +88,9 @@ static int lmv_intent_remote(struct obd_export *exp, void *lmm, it->it_request = NULL; } - LASSERT(fid_is_sane(&body->fid1)); + LASSERT(fid_is_sane(&body->mbo_fid1)); - tgt = lmv_find_target(lmv, &body->fid1); + tgt = lmv_find_target(lmv, &body->mbo_fid1); if (IS_ERR(tgt)) { rc = PTR_ERR(tgt); goto out; @@ -102,7 +102,7 @@ static int lmv_intent_remote(struct obd_export *exp, void *lmm, goto out; } - op_data->op_fid1 = body->fid1; + op_data->op_fid1 = body->mbo_fid1; /* Sent the parent FID to the remote MDT */ if (parent_fid) { /* The parent fid is only for remote open to @@ -114,12 +114,12 @@ static int lmv_intent_remote(struct obd_export *exp, void *lmm, /* Add object FID to op_fid3, in case it needs to check stale * (M_CHECK_STALE), see mdc_finish_intent_lock */ - op_data->op_fid3 = body->fid1; + op_data->op_fid3 = body->mbo_fid1; } op_data->op_bias = MDS_CROSS_REF; CDEBUG(D_INODE, "REMOTE_INTENT with fid="DFID" -> mds #%d\n", - PFID(&body->fid1), tgt->ltd_idx); + PFID(&body->mbo_fid1), tgt->ltd_idx); rc = md_intent_lock(tgt->ltd_exp, op_data, lmm, lmmsize, it, flags, &req, cb_blocking, extra_lock_flags); @@ -227,9 +227,9 @@ int lmv_revalidate_slaves(struct obd_export *exp, struct mdt_body *mbody, &RMF_MDT_BODY); LASSERT(body); - if (unlikely(body->nlink < 2)) { + if (unlikely(body->mbo_nlink < 2)) { CERROR("%s: nlink %d < 2 corrupt stripe %d "DFID":" DFID"\n", - obd->obd_name, body->nlink, i, + obd->obd_name, body->mbo_nlink, i, PFID(&lsm->lsm_md_oinfo[i].lmo_fid), PFID(&lsm->lsm_md_oinfo[0].lmo_fid)); @@ -245,11 +245,11 @@ int lmv_revalidate_slaves(struct obd_export *exp, struct mdt_body *mbody, goto cleanup; } - i_size_write(inode, body->size); - set_nlink(inode, body->nlink); - LTIME_S(inode->i_atime) = body->atime; - LTIME_S(inode->i_ctime) = body->ctime; - LTIME_S(inode->i_mtime) = body->mtime; + i_size_write(inode, body->mbo_size); + set_nlink(inode, body->mbo_nlink); + LTIME_S(inode->i_atime) = body->mbo_atime; + LTIME_S(inode->i_ctime) = body->mbo_ctime; + LTIME_S(inode->i_mtime) = body->mbo_mtime; if (req) ptlrpc_req_finished(req); @@ -288,9 +288,9 @@ int lmv_revalidate_slaves(struct obd_export *exp, struct mdt_body *mbody, PFID(&lsm->lsm_md_oinfo[0].lmo_fid)); if (mbody) { - mbody->atime = atime; - mbody->ctime = ctime; - mbody->mtime = mtime; + mbody->mbo_atime = atime; + mbody->mbo_ctime = ctime; + mbody->mbo_mtime = mtime; } cleanup: kfree(op_data); @@ -360,7 +360,7 @@ static int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data, if (rc != 0) return rc; /* - * Nothing is found, do not access body->fid1 as it is zero and thus + * Nothing is found, do not access body->mbo_fid1 as it is zero and thus * pointless. */ if ((it->it_disposition & DISP_LOOKUP_NEG) && @@ -373,7 +373,7 @@ static int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data, return -EPROTO; /* Not cross-ref case, just get out of here. */ - if (unlikely((body->valid & OBD_MD_MDS))) { + if (unlikely((body->mbo_valid & OBD_MD_MDS))) { rc = lmv_intent_remote(exp, lmm, lmmsize, it, &op_data->op_fid1, flags, reqp, cb_blocking, extra_lock_flags); @@ -470,7 +470,7 @@ static int lmv_intent_lookup(struct obd_export *exp, return -EPROTO; /* Not cross-ref case, just get out of here. */ - if (unlikely((body->valid & OBD_MD_MDS))) { + if (unlikely((body->mbo_valid & OBD_MD_MDS))) { rc = lmv_intent_remote(exp, lmm, lmmsize, it, NULL, flags, reqp, cb_blocking, extra_lock_flags); if (rc != 0) diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 6917a03..27a6be1 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -1813,11 +1813,11 @@ lmv_enqueue_remote(struct obd_export *exp, struct ldlm_enqueue_info *einfo, body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); - if (!(body->valid & OBD_MD_MDS)) + if (!(body->mbo_valid & OBD_MD_MDS)) return 0; CDEBUG(D_INODE, "REMOTE_ENQUEUE '%s' on "DFID" -> "DFID"\n", - LL_IT2STR(it), PFID(&op_data->op_fid1), PFID(&body->fid1)); + LL_IT2STR(it), PFID(&op_data->op_fid1), PFID(&body->mbo_fid1)); /* * We got LOOKUP lock, but we really need attrs. @@ -1827,7 +1827,7 @@ lmv_enqueue_remote(struct obd_export *exp, struct ldlm_enqueue_info *einfo, memcpy(&plock, lockh, sizeof(plock)); it->it_lock_mode = 0; it->it_request = NULL; - fid1 = body->fid1; + fid1 = body->mbo_fid1; ptlrpc_req_finished(req); @@ -1917,8 +1917,8 @@ lmv_getattr_name(struct obd_export *exp, struct md_op_data *op_data, return rc; body = req_capsule_server_get(&(*preq)->rq_pill, &RMF_MDT_BODY); - if (body->valid & OBD_MD_MDS) { - struct lu_fid rid = body->fid1; + if (body->mbo_valid & OBD_MD_MDS) { + struct lu_fid rid = body->mbo_fid1; CDEBUG(D_INODE, "Request attrs for "DFID"\n", PFID(&rid)); @@ -2433,11 +2433,11 @@ retry: return -EPROTO; /* Not cross-ref case, just get out of here. */ - if (likely(!(body->valid & OBD_MD_MDS))) + if (likely(!(body->mbo_valid & OBD_MD_MDS))) return 0; CDEBUG(D_INODE, "%s: try unlink to another MDT for "DFID"\n", - exp->exp_obd->obd_name, PFID(&body->fid1)); + exp->exp_obd->obd_name, PFID(&body->mbo_fid1)); /* This is a remote object, try remote MDT, Note: it may * try more than 1 time here, Considering following case @@ -2459,7 +2459,7 @@ retry: * In theory, it might try unlimited time here, but it should * be very rare case. */ - op_data->op_fid2 = body->fid1; + op_data->op_fid2 = body->mbo_fid1; ptlrpc_req_finished(*request); *request = NULL; diff --git a/drivers/staging/lustre/lustre/mdc/mdc_lib.c b/drivers/staging/lustre/lustre/mdc/mdc_lib.c index 16c3571..813f923 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_lib.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_lib.c @@ -37,12 +37,12 @@ static void __mdc_pack_body(struct mdt_body *b, __u32 suppgid) { - b->suppgid = suppgid; - b->uid = from_kuid(&init_user_ns, current_uid()); - b->gid = from_kgid(&init_user_ns, current_gid()); - b->fsuid = from_kuid(&init_user_ns, current_fsuid()); - b->fsgid = from_kgid(&init_user_ns, current_fsgid()); - b->capability = cfs_curproc_cap_pack(); + b->mbo_suppgid = suppgid; + b->mbo_uid = from_kuid(&init_user_ns, current_uid()); + b->mbo_gid = from_kgid(&init_user_ns, current_gid()); + b->mbo_fsuid = from_kuid(&init_user_ns, current_fsuid()); + b->mbo_fsgid = from_kgid(&init_user_ns, current_fsgid()); + b->mbo_capability = cfs_curproc_cap_pack(); } void mdc_is_subdir_pack(struct ptlrpc_request *req, const struct lu_fid *pfid, @@ -52,12 +52,12 @@ void mdc_is_subdir_pack(struct ptlrpc_request *req, const struct lu_fid *pfid, &RMF_MDT_BODY); if (pfid) { - b->fid1 = *pfid; - b->valid = OBD_MD_FLID; + b->mbo_fid1 = *pfid; + b->mbo_valid = OBD_MD_FLID; } if (cfid) - b->fid2 = *cfid; - b->flags = flags; + b->mbo_fid2 = *cfid; + b->mbo_flags = flags; } void mdc_swap_layouts_pack(struct ptlrpc_request *req, @@ -67,9 +67,9 @@ void mdc_swap_layouts_pack(struct ptlrpc_request *req, &RMF_MDT_BODY); __mdc_pack_body(b, op_data->op_suppgids[0]); - b->fid1 = op_data->op_fid1; - b->fid2 = op_data->op_fid2; - b->valid |= OBD_MD_FLID; + b->mbo_fid1 = op_data->op_fid1; + b->mbo_fid2 = op_data->op_fid2; + b->mbo_valid |= OBD_MD_FLID; } void mdc_pack_body(struct ptlrpc_request *req, const struct lu_fid *fid, @@ -77,13 +77,13 @@ void mdc_pack_body(struct ptlrpc_request *req, const struct lu_fid *fid, { struct mdt_body *b = req_capsule_client_get(&req->rq_pill, &RMF_MDT_BODY); - b->valid = valid; - b->eadatasize = ea_size; - b->flags = flags; + b->mbo_valid = valid; + b->mbo_eadatasize = ea_size; + b->mbo_flags = flags; __mdc_pack_body(b, suppgid); if (fid) { - b->fid1 = *fid; - b->valid |= OBD_MD_FLID; + b->mbo_fid1 = *fid; + b->mbo_valid |= OBD_MD_FLID; } } @@ -123,12 +123,12 @@ void mdc_readdir_pack(struct ptlrpc_request *req, __u64 pgoff, { struct mdt_body *b = req_capsule_client_get(&req->rq_pill, &RMF_MDT_BODY); - b->fid1 = *fid; - b->valid |= OBD_MD_FLID; - b->size = pgoff; /* !! */ - b->nlink = size; /* !! */ + b->mbo_fid1 = *fid; + b->mbo_valid |= OBD_MD_FLID; + b->mbo_size = pgoff; /* !! */ + b->mbo_nlink = size; /* !! */ __mdc_pack_body(b, -1); - b->mode = LUDA_FID | LUDA_TYPE; + b->mbo_mode = LUDA_FID | LUDA_TYPE; } /* packing of MDS records */ @@ -440,18 +440,18 @@ void mdc_getattr_pack(struct ptlrpc_request *req, __u64 valid, int flags, struct mdt_body *b = req_capsule_client_get(&req->rq_pill, &RMF_MDT_BODY); - b->valid = valid; + b->mbo_valid = valid; if (op_data->op_bias & MDS_CHECK_SPLIT) - b->valid |= OBD_MD_FLCKSPLIT; + b->mbo_valid |= OBD_MD_FLCKSPLIT; if (op_data->op_bias & MDS_CROSS_REF) - b->valid |= OBD_MD_FLCROSSREF; - b->eadatasize = ea_size; - b->flags = flags; + b->mbo_valid |= OBD_MD_FLCROSSREF; + b->mbo_eadatasize = ea_size; + b->mbo_flags = flags; __mdc_pack_body(b, op_data->op_suppgids[0]); - b->fid1 = op_data->op_fid1; - b->fid2 = op_data->op_fid2; - b->valid |= OBD_MD_FLID; + b->mbo_fid1 = op_data->op_fid1; + b->mbo_fid2 = op_data->op_fid2; + b->mbo_valid |= OBD_MD_FLID; if (op_data->op_name) mdc_pack_name(req, &RMF_NAME, op_data->op_name, diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index 20b15f6..551f3d9 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -240,12 +240,12 @@ static void mdc_realloc_openmsg(struct ptlrpc_request *req, /* FIXME: remove this explicit offset. */ rc = sptlrpc_cli_enlarge_reqbuf(req, DLM_INTENT_REC_OFF + 4, - body->eadatasize); + body->mbo_eadatasize); if (rc) { CERROR("Can't enlarge segment %d size to %d\n", - DLM_INTENT_REC_OFF + 4, body->eadatasize); - body->valid &= ~OBD_MD_FLEASIZE; - body->eadatasize = 0; + DLM_INTENT_REC_OFF + 4, body->mbo_eadatasize); + body->mbo_valid &= ~OBD_MD_FLEASIZE; + body->mbo_eadatasize = 0; } } @@ -608,7 +608,7 @@ static int mdc_finish_enqueue(struct obd_export *exp, mdc_set_open_replay_data(NULL, NULL, it); } - if ((body->valid & (OBD_MD_FLDIREA | OBD_MD_FLEASIZE)) != 0) { + if ((body->mbo_valid & (OBD_MD_FLDIREA | OBD_MD_FLEASIZE)) != 0) { void *eadata; mdc_update_max_ea_from_body(exp, body); @@ -618,7 +618,7 @@ static int mdc_finish_enqueue(struct obd_export *exp, * Eventually, obd_unpackmd() will check the contents. */ eadata = req_capsule_server_sized_get(pill, &RMF_MDT_MD, - body->eadatasize); + body->mbo_eadatasize); if (!eadata) return -EPROTO; @@ -626,7 +626,7 @@ static int mdc_finish_enqueue(struct obd_export *exp, * lock */ lvb_data = eadata; - lvb_len = body->eadatasize; + lvb_len = body->mbo_eadatasize; /* * We save the reply LOV EA in case we have to replay a @@ -642,20 +642,20 @@ static int mdc_finish_enqueue(struct obd_export *exp, if (req_capsule_get_size(pill, &RMF_EADATA, RCL_CLIENT) < - body->eadatasize) + body->mbo_eadatasize) mdc_realloc_openmsg(req, body); else req_capsule_shrink(pill, &RMF_EADATA, - body->eadatasize, + body->mbo_eadatasize, RCL_CLIENT); req_capsule_set_size(pill, &RMF_EADATA, RCL_CLIENT, - body->eadatasize); + body->mbo_eadatasize); lmm = req_capsule_client_get(pill, &RMF_EADATA); if (lmm) - memcpy(lmm, eadata, body->eadatasize); + memcpy(lmm, eadata, body->mbo_eadatasize); } } } else if (it->it_op & IT_LAYOUT) { @@ -935,11 +935,11 @@ static int mdc_finish_intent_lock(struct obd_export *exp, * op_fid3 - existent fid - if file only open. * op_fid3 is saved in lmv_intent_open */ - if ((!lu_fid_eq(&op_data->op_fid2, &mdt_body->fid1)) && - (!lu_fid_eq(&op_data->op_fid3, &mdt_body->fid1))) { + if ((!lu_fid_eq(&op_data->op_fid2, &mdt_body->mbo_fid1)) && + (!lu_fid_eq(&op_data->op_fid3, &mdt_body->mbo_fid1))) { CDEBUG(D_DENTRY, "Found stale data "DFID"("DFID")/"DFID "\n", PFID(&op_data->op_fid2), - PFID(&op_data->op_fid2), PFID(&mdt_body->fid1)); + PFID(&op_data->op_fid2), PFID(&mdt_body->mbo_fid1)); return -ESTALE; } } @@ -986,10 +986,10 @@ static int mdc_finish_intent_lock(struct obd_export *exp, LDLM_DEBUG(lock, "matching against this"); - LASSERTF(fid_res_name_eq(&mdt_body->fid1, + LASSERTF(fid_res_name_eq(&mdt_body->mbo_fid1, &lock->l_resource->lr_name), "Lock res_id: "DLDLMRES", fid: "DFID"\n", - PLDLMRES(lock->l_resource), PFID(&mdt_body->fid1)); + PLDLMRES(lock->l_resource), PFID(&mdt_body->mbo_fid1)); LDLM_LOCK_PUT(lock); memcpy(&old_lock, lockh, sizeof(*lockh)); diff --git a/drivers/staging/lustre/lustre/mdc/mdc_reint.c b/drivers/staging/lustre/lustre/mdc/mdc_reint.c index c3781a6..9bec049 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_reint.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_reint.c @@ -177,8 +177,8 @@ int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data, epoch = req_capsule_client_get(&req->rq_pill, &RMF_MDT_EPOCH); body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); - epoch->handle = body->handle; - epoch->ioepoch = body->ioepoch; + epoch->handle = body->mbo_handle; + epoch->ioepoch = body->mbo_ioepoch; req->rq_replay_cb = mdc_replay_open; /** bug 3633, open may be committed and estale answer is not error */ } else if (rc == -ESTALE && (op_data->op_flags & MF_SOM_CHANGE)) { diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index e26d0d7..74ddec3 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -100,7 +100,7 @@ static int mdc_getstatus(struct obd_export *exp, struct lu_fid *rootfid) goto out; } - *rootfid = body->fid1; + *rootfid = body->mbo_fid1; CDEBUG(D_NET, "root fid="DFID", last_committed=%llu\n", PFID(rootfid), @@ -138,12 +138,12 @@ static int mdc_getattr_common(struct obd_export *exp, if (!body) return -EPROTO; - CDEBUG(D_NET, "mode: %o\n", body->mode); + CDEBUG(D_NET, "mode: %o\n", body->mbo_mode); mdc_update_max_ea_from_body(exp, body); - if (body->eadatasize != 0) { + if (body->mbo_eadatasize != 0) { eadata = req_capsule_server_sized_get(pill, &RMF_MDT_MD, - body->eadatasize); + body->mbo_eadatasize); if (!eadata) return -EPROTO; } @@ -399,15 +399,15 @@ static int mdc_unpack_acl(struct ptlrpc_request *req, struct lustre_md *md) void *buf; int rc; - if (!body->aclsize) + if (!body->mbo_aclsize) return 0; - buf = req_capsule_server_sized_get(pill, &RMF_ACL, body->aclsize); + buf = req_capsule_server_sized_get(pill, &RMF_ACL, body->mbo_aclsize); if (!buf) return -EPROTO; - acl = posix_acl_from_xattr(&init_user_ns, buf, body->aclsize); + acl = posix_acl_from_xattr(&init_user_ns, buf, body->mbo_aclsize); if (!acl) return 0; @@ -445,24 +445,24 @@ static int mdc_get_lustre_md(struct obd_export *exp, md->body = req_capsule_server_get(pill, &RMF_MDT_BODY); - if (md->body->valid & OBD_MD_FLEASIZE) { + if (md->body->mbo_valid & OBD_MD_FLEASIZE) { int lmmsize; struct lov_mds_md *lmm; - if (!S_ISREG(md->body->mode)) { + if (!S_ISREG(md->body->mbo_mode)) { CDEBUG(D_INFO, "OBD_MD_FLEASIZE set, should be a regular file, but is not\n"); rc = -EPROTO; goto out; } - if (md->body->eadatasize == 0) { + if (md->body->mbo_eadatasize == 0) { CDEBUG(D_INFO, "OBD_MD_FLEASIZE set, but eadatasize 0\n"); rc = -EPROTO; goto out; } - lmmsize = md->body->eadatasize; + lmmsize = md->body->mbo_eadatasize; lmm = req_capsule_server_sized_get(pill, &RMF_MDT_MD, lmmsize); if (!lmm) { rc = -EPROTO; @@ -481,24 +481,24 @@ static int mdc_get_lustre_md(struct obd_export *exp, goto out; } - } else if (md->body->valid & OBD_MD_FLDIREA) { + } else if (md->body->mbo_valid & OBD_MD_FLDIREA) { int lmvsize; struct lov_mds_md *lmv; - if (!S_ISDIR(md->body->mode)) { + if (!S_ISDIR(md->body->mbo_mode)) { CDEBUG(D_INFO, "OBD_MD_FLDIREA set, should be a directory, but is not\n"); rc = -EPROTO; goto out; } - if (md->body->eadatasize == 0) { + if (md->body->mbo_eadatasize == 0) { CDEBUG(D_INFO, "OBD_MD_FLDIREA is set, but eadatasize 0\n"); return -EPROTO; } - if (md->body->valid & OBD_MD_MEA) { - lmvsize = md->body->eadatasize; + if (md->body->mbo_valid & OBD_MD_MEA) { + lmvsize = md->body->mbo_eadatasize; lmv = req_capsule_server_sized_get(pill, &RMF_MDT_MD, lmvsize); if (!lmv) { @@ -522,12 +522,12 @@ static int mdc_get_lustre_md(struct obd_export *exp, } rc = 0; - if (md->body->valid & OBD_MD_FLACL) { + if (md->body->mbo_valid & OBD_MD_FLACL) { /* for ACL, it's possible that FLACL is set but aclsize is zero. * only when aclsize != 0 there's an actual segment for ACL * in reply buffer. */ - if (md->body->aclsize) { + if (md->body->mbo_aclsize) { rc = mdc_unpack_acl(req, md); if (rc) goto out; @@ -582,9 +582,9 @@ void mdc_replay_open(struct ptlrpc_request *req) file_fh = &och->och_fh; CDEBUG(D_HA, "updating handle from %#llx to %#llx\n", - file_fh->cookie, body->handle.cookie); + file_fh->cookie, body->mbo_handle.cookie); old = *file_fh; - *file_fh = body->handle; + *file_fh = body->mbo_handle; } close_req = mod->mod_close_req; if (close_req) { @@ -599,7 +599,7 @@ void mdc_replay_open(struct ptlrpc_request *req) if (och) LASSERT(!memcmp(&old, &epoch->handle, sizeof(old))); DEBUG_REQ(D_HA, close_req, "updating close body with new fh"); - epoch->handle = body->handle; + epoch->handle = body->mbo_handle; } } @@ -681,11 +681,11 @@ int mdc_set_open_replay_data(struct obd_export *exp, spin_unlock(&open_req->rq_lock); } - rec->cr_fid2 = body->fid1; - rec->cr_ioepoch = body->ioepoch; - rec->cr_old_handle.cookie = body->handle.cookie; + rec->cr_fid2 = body->mbo_fid1; + rec->cr_ioepoch = body->mbo_ioepoch; + rec->cr_old_handle.cookie = body->mbo_handle.cookie; open_req->rq_replay_cb = mdc_replay_open; - if (!fid_is_sane(&body->fid1)) { + if (!fid_is_sane(&body->mbo_fid1)) { DEBUG_REQ(D_ERROR, open_req, "Saving replay request with insane fid"); LBUG(); @@ -746,7 +746,7 @@ static void mdc_close_handle_reply(struct ptlrpc_request *req, epoch = req_capsule_client_get(&req->rq_pill, &RMF_MDT_EPOCH); epoch->flags |= MF_SOM_AU; - if (repbody->valid & OBD_MD_FLGETATTRLOCK) + if (repbody->mbo_valid & OBD_MD_FLGETATTRLOCK) op_data->op_flags |= MF_GETATTR_LOCK; } } diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index 6ddc9c7..465698b 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -1674,35 +1674,35 @@ EXPORT_SYMBOL(lustre_swab_lquota_lvb); void lustre_swab_mdt_body(struct mdt_body *b) { - lustre_swab_lu_fid(&b->fid1); - lustre_swab_lu_fid(&b->fid2); + lustre_swab_lu_fid(&b->mbo_fid1); + lustre_swab_lu_fid(&b->mbo_fid2); /* handle is opaque */ - __swab64s(&b->valid); - __swab64s(&b->size); - __swab64s(&b->mtime); - __swab64s(&b->atime); - __swab64s(&b->ctime); - __swab64s(&b->blocks); - __swab64s(&b->ioepoch); - __swab64s(&b->t_state); - __swab32s(&b->fsuid); - __swab32s(&b->fsgid); - __swab32s(&b->capability); - __swab32s(&b->mode); - __swab32s(&b->uid); - __swab32s(&b->gid); - __swab32s(&b->flags); - __swab32s(&b->rdev); - __swab32s(&b->nlink); - CLASSERT(offsetof(typeof(*b), unused2) != 0); - __swab32s(&b->suppgid); - __swab32s(&b->eadatasize); - __swab32s(&b->aclsize); - __swab32s(&b->max_mdsize); - __swab32s(&b->max_cookiesize); - __swab32s(&b->uid_h); - __swab32s(&b->gid_h); - CLASSERT(offsetof(typeof(*b), padding_5) != 0); + __swab64s(&b->mbo_valid); + __swab64s(&b->mbo_size); + __swab64s(&b->mbo_mtime); + __swab64s(&b->mbo_atime); + __swab64s(&b->mbo_ctime); + __swab64s(&b->mbo_blocks); + __swab64s(&b->mbo_ioepoch); + __swab64s(&b->mbo_t_state); + __swab32s(&b->mbo_fsuid); + __swab32s(&b->mbo_fsgid); + __swab32s(&b->mbo_capability); + __swab32s(&b->mbo_mode); + __swab32s(&b->mbo_uid); + __swab32s(&b->mbo_gid); + __swab32s(&b->mbo_flags); + __swab32s(&b->mbo_rdev); + __swab32s(&b->mbo_nlink); + CLASSERT(offsetof(typeof(*b), mbo_unused2) != 0); + __swab32s(&b->mbo_suppgid); + __swab32s(&b->mbo_eadatasize); + __swab32s(&b->mbo_aclsize); + __swab32s(&b->mbo_max_mdsize); + __swab32s(&b->mbo_max_cookiesize); + __swab32s(&b->mbo_uid_h); + __swab32s(&b->mbo_gid_h); + CLASSERT(offsetof(typeof(*b), mbo_padding_5) != 0); } EXPORT_SYMBOL(lustre_swab_mdt_body); diff --git a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c index 8dbaf32..60d03dd 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c +++ b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c @@ -1350,7 +1350,7 @@ void lustre_assert_wire_constants(void) (long long)(int)offsetof(struct lov_mds_md_v1, lmm_objects[0])); LASSERTF((int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_objects[0]) == 24, "found %lld\n", (long long)(int)sizeof(((struct lov_mds_md_v1 *)0)->lmm_objects[0])); - CLASSERT(LOV_MAGIC_V1 == 0x0BD10BD0); + CLASSERT(LOV_MAGIC_V1 == (0x0BD10000 | 0x0BD0)); /* Checks for struct lov_mds_md_v3 */ LASSERTF((int)sizeof(struct lov_mds_md_v3) == 48, "found %lld\n", @@ -1388,7 +1388,7 @@ void lustre_assert_wire_constants(void) (long long)(int)offsetof(struct lov_mds_md_v3, lmm_objects[0])); LASSERTF((int)sizeof(((struct lov_mds_md_v3 *)0)->lmm_objects[0]) == 24, "found %lld\n", (long long)(int)sizeof(((struct lov_mds_md_v3 *)0)->lmm_objects[0])); - CLASSERT(LOV_MAGIC_V3 == 0x0BD30BD0); + CLASSERT(LOV_MAGIC_V3 == (0x0BD30000 | 0x0BD0)); LASSERTF(LOV_PATTERN_RAID0 == 0x00000001UL, "found 0x%.8xUL\n", (unsigned)LOV_PATTERN_RAID0); LASSERTF(LOV_PATTERN_RAID1 == 0x00000002UL, "found 0x%.8xUL\n", @@ -1667,139 +1667,139 @@ void lustre_assert_wire_constants(void) /* Checks for struct mdt_body */ LASSERTF((int)sizeof(struct mdt_body) == 216, "found %lld\n", (long long)(int)sizeof(struct mdt_body)); - LASSERTF((int)offsetof(struct mdt_body, fid1) == 0, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, fid1)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->fid1) == 16, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->fid1)); - LASSERTF((int)offsetof(struct mdt_body, fid2) == 16, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, fid2)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->fid2) == 16, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->fid2)); - LASSERTF((int)offsetof(struct mdt_body, handle) == 32, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, handle)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->handle) == 8, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->handle)); - LASSERTF((int)offsetof(struct mdt_body, valid) == 40, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, valid)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->valid) == 8, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->valid)); - LASSERTF((int)offsetof(struct mdt_body, size) == 48, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, size)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->size) == 8, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->size)); - LASSERTF((int)offsetof(struct mdt_body, mtime) == 56, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, mtime)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->mtime) == 8, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->mtime)); - LASSERTF((int)offsetof(struct mdt_body, atime) == 64, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, atime)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->atime) == 8, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->atime)); - LASSERTF((int)offsetof(struct mdt_body, ctime) == 72, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, ctime)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->ctime) == 8, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->ctime)); - LASSERTF((int)offsetof(struct mdt_body, blocks) == 80, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, blocks)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->blocks) == 8, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->blocks)); - LASSERTF((int)offsetof(struct mdt_body, t_state) == 96, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, t_state)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->t_state) == 8, + LASSERTF((int)offsetof(struct mdt_body, mbo_fid1) == 0, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_fid1)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_fid1) == 16, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_fid1)); + LASSERTF((int)offsetof(struct mdt_body, mbo_fid2) == 16, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_fid2)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_fid2) == 16, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_fid2)); + LASSERTF((int)offsetof(struct mdt_body, mbo_handle) == 32, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_handle)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_handle) == 8, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_handle)); + LASSERTF((int)offsetof(struct mdt_body, mbo_valid) == 40, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_valid)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_valid) == 8, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_valid)); + LASSERTF((int)offsetof(struct mdt_body, mbo_size) == 48, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_size)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_size) == 8, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_size)); + LASSERTF((int)offsetof(struct mdt_body, mbo_mtime) == 56, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_mtime)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_mtime) == 8, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_mtime)); + LASSERTF((int)offsetof(struct mdt_body, mbo_atime) == 64, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_atime)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_atime) == 8, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_atime)); + LASSERTF((int)offsetof(struct mdt_body, mbo_ctime) == 72, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_ctime)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_ctime) == 8, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_ctime)); + LASSERTF((int)offsetof(struct mdt_body, mbo_blocks) == 80, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_blocks)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_blocks) == 8, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_blocks)); + LASSERTF((int)offsetof(struct mdt_body, mbo_t_state) == 96, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_t_state)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_t_state) == 8, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->t_state)); - LASSERTF((int)offsetof(struct mdt_body, fsuid) == 104, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, fsuid)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->fsuid) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->fsuid)); - LASSERTF((int)offsetof(struct mdt_body, fsgid) == 108, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, fsgid)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->fsgid) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->fsgid)); - LASSERTF((int)offsetof(struct mdt_body, capability) == 112, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, capability)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->capability) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->capability)); - LASSERTF((int)offsetof(struct mdt_body, mode) == 116, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, mode)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->mode) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->mode)); - LASSERTF((int)offsetof(struct mdt_body, uid) == 120, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, uid)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->uid) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->uid)); - LASSERTF((int)offsetof(struct mdt_body, gid) == 124, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, gid)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->gid) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->gid)); - LASSERTF((int)offsetof(struct mdt_body, flags) == 128, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, flags)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->flags) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->flags)); - LASSERTF((int)offsetof(struct mdt_body, rdev) == 132, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, rdev)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->rdev) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->rdev)); - LASSERTF((int)offsetof(struct mdt_body, nlink) == 136, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, nlink)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->nlink) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->nlink)); - LASSERTF((int)offsetof(struct mdt_body, unused2) == 140, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, unused2)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->unused2) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->unused2)); - LASSERTF((int)offsetof(struct mdt_body, suppgid) == 144, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, suppgid)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->suppgid) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->suppgid)); - LASSERTF((int)offsetof(struct mdt_body, eadatasize) == 148, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, eadatasize)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->eadatasize) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->eadatasize)); - LASSERTF((int)offsetof(struct mdt_body, aclsize) == 152, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, aclsize)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->aclsize) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->aclsize)); - LASSERTF((int)offsetof(struct mdt_body, max_mdsize) == 156, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, max_mdsize)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->max_mdsize) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->max_mdsize)); - LASSERTF((int)offsetof(struct mdt_body, max_cookiesize) == 160, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, max_cookiesize)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->max_cookiesize) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->max_cookiesize)); - LASSERTF((int)offsetof(struct mdt_body, uid_h) == 164, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, uid_h)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->uid_h) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->uid_h)); - LASSERTF((int)offsetof(struct mdt_body, gid_h) == 168, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, gid_h)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->gid_h) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->gid_h)); - LASSERTF((int)offsetof(struct mdt_body, padding_5) == 172, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, padding_5)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->padding_5) == 4, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->padding_5)); - LASSERTF((int)offsetof(struct mdt_body, padding_6) == 176, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, padding_6)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->padding_6) == 8, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->padding_6)); - LASSERTF((int)offsetof(struct mdt_body, padding_7) == 184, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, padding_7)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->padding_7) == 8, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->padding_7)); - LASSERTF((int)offsetof(struct mdt_body, padding_8) == 192, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, padding_8)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->padding_8) == 8, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->padding_8)); - LASSERTF((int)offsetof(struct mdt_body, padding_9) == 200, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, padding_9)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->padding_9) == 8, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->padding_9)); - LASSERTF((int)offsetof(struct mdt_body, padding_10) == 208, "found %lld\n", - (long long)(int)offsetof(struct mdt_body, padding_10)); - LASSERTF((int)sizeof(((struct mdt_body *)0)->padding_10) == 8, "found %lld\n", - (long long)(int)sizeof(((struct mdt_body *)0)->padding_10)); + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_t_state)); + LASSERTF((int)offsetof(struct mdt_body, mbo_fsuid) == 104, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_fsuid)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_fsuid) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_fsuid)); + LASSERTF((int)offsetof(struct mdt_body, mbo_fsgid) == 108, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_fsgid)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_fsgid) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_fsgid)); + LASSERTF((int)offsetof(struct mdt_body, mbo_capability) == 112, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_capability)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_capability) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_capability)); + LASSERTF((int)offsetof(struct mdt_body, mbo_mode) == 116, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_mode)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_mode) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_mode)); + LASSERTF((int)offsetof(struct mdt_body, mbo_uid) == 120, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_uid)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_uid) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_uid)); + LASSERTF((int)offsetof(struct mdt_body, mbo_gid) == 124, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_gid)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_gid) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_gid)); + LASSERTF((int)offsetof(struct mdt_body, mbo_flags) == 128, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_flags)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_flags) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_flags)); + LASSERTF((int)offsetof(struct mdt_body, mbo_rdev) == 132, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_rdev)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_rdev) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_rdev)); + LASSERTF((int)offsetof(struct mdt_body, mbo_nlink) == 136, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_nlink)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_nlink) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_nlink)); + LASSERTF((int)offsetof(struct mdt_body, mbo_unused2) == 140, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_unused2)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_unused2) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_unused2)); + LASSERTF((int)offsetof(struct mdt_body, mbo_suppgid) == 144, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_suppgid)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_suppgid) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_suppgid)); + LASSERTF((int)offsetof(struct mdt_body, mbo_eadatasize) == 148, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_eadatasize)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_eadatasize) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_eadatasize)); + LASSERTF((int)offsetof(struct mdt_body, mbo_aclsize) == 152, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_aclsize)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_aclsize) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_aclsize)); + LASSERTF((int)offsetof(struct mdt_body, mbo_max_mdsize) == 156, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_max_mdsize)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_max_mdsize) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_max_mdsize)); + LASSERTF((int)offsetof(struct mdt_body, mbo_max_cookiesize) == 160, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_max_cookiesize)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_max_cookiesize) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_max_cookiesize)); + LASSERTF((int)offsetof(struct mdt_body, mbo_uid_h) == 164, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_uid_h)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_uid_h) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_uid_h)); + LASSERTF((int)offsetof(struct mdt_body, mbo_gid_h) == 168, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_gid_h)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_gid_h) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_gid_h)); + LASSERTF((int)offsetof(struct mdt_body, mbo_padding_5) == 172, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_padding_5)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_padding_5) == 4, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_padding_5)); + LASSERTF((int)offsetof(struct mdt_body, mbo_padding_6) == 176, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_padding_6)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_padding_6) == 8, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_padding_6)); + LASSERTF((int)offsetof(struct mdt_body, mbo_padding_7) == 184, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_padding_7)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_padding_7) == 8, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_padding_7)); + LASSERTF((int)offsetof(struct mdt_body, mbo_padding_8) == 192, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_padding_8)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_padding_8) == 8, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_padding_8)); + LASSERTF((int)offsetof(struct mdt_body, mbo_padding_9) == 200, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_padding_9)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_padding_9) == 8, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_padding_9)); + LASSERTF((int)offsetof(struct mdt_body, mbo_padding_10) == 208, "found %lld\n", + (long long)(int)offsetof(struct mdt_body, mbo_padding_10)); + LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_padding_10) == 8, "found %lld\n", + (long long)(int)sizeof(((struct mdt_body *)0)->mbo_padding_10)); LASSERTF(MDS_FMODE_CLOSED == 000000000000UL, "found 0%.11oUL\n", MDS_FMODE_CLOSED); LASSERTF(MDS_FMODE_EXEC == 000000000004UL, "found 0%.11oUL\n", -- cgit v0.10.2 From 96c53363d8e56f31b450f6b7cdc0e6ae748e1481 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong <jinshan.xiong@intel.com> Date: Tue, 16 Aug 2016 16:19:09 -0400 Subject: staging: lustre: clio: Reduce memory overhead of per-page allocation A page in clio used to occupy 584 bytes, which will use size-1024 slab cache. This patch reduces the per-page overhead to 512 bytes so it can use size-512 instead. Signed-off-by: Jinshan Xiong <jinshan.xiong@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4793 Reviewed-on: http://review.whamcloud.com/10070 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Bobi Jam <bobijam@gmail.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index 0fa71a5..d269b32 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -690,17 +690,6 @@ enum cl_page_type { }; /** - * Flags maintained for every cl_page. - */ -enum cl_page_flags { - /** - * Set when pagein completes. Used for debugging (read completes at - * most once for a page). - */ - CPF_READ_COMPLETED = 1 << 0 -}; - -/** * Fields are protected by the lock on struct page, except for atomics and * immutables. * @@ -712,26 +701,23 @@ enum cl_page_flags { struct cl_page { /** Reference counter. */ atomic_t cp_ref; + /** Transfer error. */ + int cp_error; /** An object this page is a part of. Immutable after creation. */ struct cl_object *cp_obj; - /** List of slices. Immutable after creation. */ - struct list_head cp_layers; /** vmpage */ struct page *cp_vmpage; + /** Linkage of pages within group. Pages must be owned */ + struct list_head cp_batch; + /** List of slices. Immutable after creation. */ + struct list_head cp_layers; + /** Linkage of pages within cl_req. */ + struct list_head cp_flight; /** * Page state. This field is const to avoid accidental update, it is * modified only internally within cl_page.c. Protected by a VM lock. */ const enum cl_page_state cp_state; - /** Linkage of pages within group. Protected by cl_page::cp_mutex. */ - struct list_head cp_batch; - /** Mutex serializing membership of a page in a batch. */ - struct mutex cp_mutex; - /** Linkage of pages within cl_req. */ - struct list_head cp_flight; - /** Transfer error. */ - int cp_error; - /** * Page type. Only CPT_TRANSIENT is used so far. Immutable after * creation. @@ -744,10 +730,6 @@ struct cl_page { */ struct cl_io *cp_owner; /** - * Debug information, the task is owning the page. - */ - struct task_struct *cp_task; - /** * Owning IO request in cl_page_state::CPS_PAGEOUT and * cl_page_state::CPS_PAGEIN states. This field is maintained only in * the top-level pages. Protected by a VM lock. @@ -759,8 +741,6 @@ struct cl_page { struct lu_ref_link cp_obj_ref; /** Link to a queue, for debugging. */ struct lu_ref_link cp_queue_ref; - /** Per-page flags from enum cl_page_flags. Protected by a VM lock. */ - unsigned cp_flags; /** Assigned if doing a sync_io */ struct cl_sync_io *cp_sync_io; }; @@ -2200,6 +2180,7 @@ static inline void cl_object_page_init(struct cl_object *clob, int size) { clob->co_slice_off = cl_object_header(clob)->coh_page_bufsize; cl_object_header(clob)->coh_page_bufsize += cfs_size_round(size); + WARN_ON(cl_object_header(clob)->coh_page_bufsize > 512); } static inline void *cl_object_page_slice(struct cl_object *clob, diff --git a/drivers/staging/lustre/lustre/llite/vvp_internal.h b/drivers/staging/lustre/lustre/llite/vvp_internal.h index 79fc428..99437b8 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_internal.h +++ b/drivers/staging/lustre/lustre/llite/vvp_internal.h @@ -247,9 +247,9 @@ struct vvp_object { */ struct vvp_page { struct cl_page_slice vpg_cl; - int vpg_defer_uptodate; - int vpg_ra_used; - int vpg_write_queued; + unsigned int vpg_defer_uptodate:1, + vpg_ra_used:1, + vpg_write_queued:1; /** * Non-empty iff this page is already counted in * vvp_object::vob_pending_list. This list is only used as a flag, diff --git a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h index 9740568..43d1a3f 100644 --- a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h +++ b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h @@ -289,8 +289,8 @@ struct lov_lock { }; struct lov_page { - struct cl_page_slice lps_cl; - int lps_invalid; + struct cl_page_slice lps_cl; + unsigned int lps_stripe; /* stripe index */ }; /* diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c index 95126c3..5d47a5a 100644 --- a/drivers/staging/lustre/lustre/lov/lov_io.c +++ b/drivers/staging/lustre/lustre/lov/lov_io.c @@ -244,14 +244,12 @@ void lov_sub_put(struct lov_io_sub *sub) int lov_page_stripe(const struct cl_page *page) { - struct lovsub_object *subobj; const struct cl_page_slice *slice; - slice = cl_page_at(page, &lovsub_device_type); + slice = cl_page_at(page, &lov_device_type); LASSERT(slice->cpl_obj); - subobj = cl2lovsub(slice->cpl_obj); - return subobj->lso_index; + return cl2lov_page(slice)->lps_stripe; } struct lov_io_sub *lov_page_subio(const struct lu_env *env, struct lov_io *lio, diff --git a/drivers/staging/lustre/lustre/lov/lov_page.c b/drivers/staging/lustre/lustre/lov/lov_page.c index 45b5ae9..00bfaba 100644 --- a/drivers/staging/lustre/lustre/lov/lov_page.c +++ b/drivers/staging/lustre/lustre/lov/lov_page.c @@ -129,6 +129,7 @@ int lov_page_init_raid0(const struct lu_env *env, struct cl_object *obj, rc = lov_stripe_offset(loo->lo_lsm, offset, stripe, &suboff); LASSERT(rc == 0); + lpg->lps_stripe = stripe; cl_page_slice_add(page, &lpg->lps_cl, obj, index, &lov_raid0_page_ops); sub = lov_sub_get(env, lio, stripe); diff --git a/drivers/staging/lustre/lustre/obdclass/cl_io.c b/drivers/staging/lustre/lustre/obdclass/cl_io.c index e72f1fc..4516fff 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_io.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_io.c @@ -859,9 +859,6 @@ void cl_page_list_add(struct cl_page_list *plist, struct cl_page *page) LASSERT(page->cp_owner); LINVRNT(plist->pl_owner == current); - lockdep_off(); - mutex_lock(&page->cp_mutex); - lockdep_on(); LASSERT(list_empty(&page->cp_batch)); list_add_tail(&page->cp_batch, &plist->pl_pages); ++plist->pl_nr; @@ -877,12 +874,10 @@ void cl_page_list_del(const struct lu_env *env, struct cl_page_list *plist, struct cl_page *page) { LASSERT(plist->pl_nr > 0); + LASSERT(cl_page_is_vmlocked(env, page)); LINVRNT(plist->pl_owner == current); list_del_init(&page->cp_batch); - lockdep_off(); - mutex_unlock(&page->cp_mutex); - lockdep_on(); --plist->pl_nr; lu_ref_del_at(&page->cp_reference, &page->cp_queue_ref, "queue", plist); cl_page_put(env, page); @@ -959,9 +954,6 @@ void cl_page_list_disown(const struct lu_env *env, LASSERT(plist->pl_nr > 0); list_del_init(&page->cp_batch); - lockdep_off(); - mutex_unlock(&page->cp_mutex); - lockdep_on(); --plist->pl_nr; /* * cl_page_disown0 rather than usual cl_page_disown() is used, diff --git a/drivers/staging/lustre/lustre/obdclass/cl_page.c b/drivers/staging/lustre/lustre/obdclass/cl_page.c index db2dc6b..bd71859 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_page.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_page.c @@ -151,7 +151,6 @@ struct cl_page *cl_page_alloc(const struct lu_env *env, INIT_LIST_HEAD(&page->cp_layers); INIT_LIST_HEAD(&page->cp_batch); INIT_LIST_HEAD(&page->cp_flight); - mutex_init(&page->cp_mutex); lu_ref_init(&page->cp_reference); head = o->co_lu.lo_header; list_for_each_entry(o, &head->loh_layers, co_lu.lo_linkage) { @@ -478,7 +477,6 @@ static void cl_page_owner_clear(struct cl_page *page) LASSERT(page->cp_owner->ci_owned_nr > 0); page->cp_owner->ci_owned_nr--; page->cp_owner = NULL; - page->cp_task = NULL; } } @@ -562,7 +560,6 @@ static int cl_page_own0(const struct lu_env *env, struct cl_io *io, PASSERT(env, pg, !pg->cp_owner); PASSERT(env, pg, !pg->cp_req); pg->cp_owner = cl_io_top(io); - pg->cp_task = current; cl_page_owner_set(pg); if (pg->cp_state != CPS_FREEING) { cl_page_state_set(env, pg, CPS_OWNED); @@ -619,7 +616,6 @@ void cl_page_assume(const struct lu_env *env, cl_page_invoid(env, io, pg, CL_PAGE_OP(cpo_assume)); PASSERT(env, pg, !pg->cp_owner); pg->cp_owner = cl_io_top(io); - pg->cp_task = current; cl_page_owner_set(pg); cl_page_state_set(env, pg, CPS_OWNED); } @@ -860,10 +856,6 @@ void cl_page_completion(const struct lu_env *env, PASSERT(env, pg, pg->cp_state == cl_req_type_state(crt)); CL_PAGE_HEADER(D_TRACE, env, pg, "%d %d\n", crt, ioret); - if (crt == CRT_READ && ioret == 0) { - PASSERT(env, pg, !(pg->cp_flags & CPF_READ_COMPLETED)); - pg->cp_flags |= CPF_READ_COMPLETED; - } cl_page_state_set(env, pg, CPS_CACHED); if (crt >= CRT_NR) @@ -989,10 +981,10 @@ void cl_page_header_print(const struct lu_env *env, void *cookie, lu_printer_t printer, const struct cl_page *pg) { (*printer)(env, cookie, - "page@%p[%d %p %d %d %d %p %p %#x]\n", + "page@%p[%d %p %d %d %d %p %p]\n", pg, atomic_read(&pg->cp_ref), pg->cp_obj, pg->cp_state, pg->cp_error, pg->cp_type, - pg->cp_owner, pg->cp_req, pg->cp_flags); + pg->cp_owner, pg->cp_req); } EXPORT_SYMBOL(cl_page_header_print); diff --git a/drivers/staging/lustre/lustre/osc/osc_internal.h b/drivers/staging/lustre/lustre/osc/osc_internal.h index 7a27f09..2038885 100644 --- a/drivers/staging/lustre/lustre/osc/osc_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_internal.h @@ -71,7 +71,6 @@ struct osc_async_page { struct client_obd *oap_cli; struct osc_object *oap_obj; - struct ldlm_lock *oap_ldlm_lock; spinlock_t oap_lock; }; diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c index 6e3dcd3..69424ea 100644 --- a/drivers/staging/lustre/lustre/osc/osc_io.c +++ b/drivers/staging/lustre/lustre/osc/osc_io.c @@ -163,7 +163,6 @@ static int osc_io_submit(const struct lu_env *env, continue; } - cl_page_list_move(qout, qin, page); spin_lock(&oap->oap_lock); oap->oap_async_flags = ASYNC_URGENT|ASYNC_READY; oap->oap_async_flags |= ASYNC_COUNT_STABLE; @@ -171,6 +170,12 @@ static int osc_io_submit(const struct lu_env *env, osc_page_submit(env, opg, crt, brw_flags); list_add_tail(&oap->oap_pending_item, &list); + + if (page->cp_sync_io) + cl_page_list_move(qout, qin, page); + else /* async IO */ + cl_page_list_del(env, qin, page); + if (++queued == max_pages) { queued = 0; result = osc_queue_sync_pages(env, osc, &list, cmd, diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index d231827..042a081 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -1882,7 +1882,6 @@ int osc_build_rpc(const struct lu_env *env, struct client_obd *cli, struct osc_async_page *tmp; struct cl_req *clerq = NULL; enum cl_req_type crt = (cmd & OBD_BRW_WRITE) ? CRT_WRITE : CRT_READ; - struct ldlm_lock *lock = NULL; struct cl_req_attr *crattr = NULL; u64 starting_offset = OBD_OBJECT_EOF; u64 ending_offset = 0; @@ -1948,7 +1947,6 @@ int osc_build_rpc(const struct lu_env *env, struct client_obd *cli, rc = PTR_ERR(clerq); goto out; } - lock = oap->oap_ldlm_lock; } if (mem_tight) oap->oap_brw_flags |= OBD_BRW_MEMALLOC; @@ -1965,10 +1963,6 @@ int osc_build_rpc(const struct lu_env *env, struct client_obd *cli, LASSERT(clerq); crattr->cra_oa = oa; cl_req_attr_set(env, clerq, crattr, ~0ULL); - if (lock) { - oa->o_handle = lock->l_remote_handle; - oa->o_valid |= OBD_MD_FLHANDLE; - } rc = cl_req_prep(env, clerq); if (rc != 0) { -- cgit v0.10.2 From d806f30e639b0ff5abeb012b08932691be795342 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong <jinshan.xiong@intel.com> Date: Tue, 16 Aug 2016 16:19:10 -0400 Subject: staging: lustre: osc: revise unstable pages accounting A few changes are made in this patch for unstable pages tracking: 1. Remove kernel NFS unstable pages tracking because it killed performance 2. Track unstable pages as part of LRU cache. Otherwise Lustre can use much more memory than max_cached_mb 3. Remove obd_unstable_pages tracking to avoid using global atomic counter 4. Make unstable pages track optional. Tracking unstable pages is turned off by default, and can be controlled by llite.*.unstable_stats. Signed-off-by: Jinshan Xiong <jinshan.xiong@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4841 Reviewed-on: http://review.whamcloud.com/10003 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Lai Siyao <lai.siyao@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index d269b32..ec6cf7c 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -1039,23 +1039,32 @@ do { \ } \ } while (0) -static inline int __page_in_use(const struct cl_page *page, int refc) -{ - if (page->cp_type == CPT_CACHEABLE) - ++refc; - LASSERT(atomic_read(&page->cp_ref) > 0); - return (atomic_read(&page->cp_ref) > refc); -} - -#define cl_page_in_use(pg) __page_in_use(pg, 1) -#define cl_page_in_use_noref(pg) __page_in_use(pg, 0) - static inline struct page *cl_page_vmpage(struct cl_page *page) { LASSERT(page->cp_vmpage); return page->cp_vmpage; } +/** + * Check if a cl_page is in use. + * + * Client cache holds a refcount, this refcount will be dropped when + * the page is taken out of cache, see vvp_page_delete(). + */ +static inline bool __page_in_use(const struct cl_page *page, int refc) +{ + return (atomic_read(&page->cp_ref) > refc + 1); +} + +/** + * Caller itself holds a refcount of cl_page. + */ +#define cl_page_in_use(pg) __page_in_use(pg, 1) +/** + * Caller doesn't hold a refcount. + */ +#define cl_page_in_use_noref(pg) __page_in_use(pg, 0) + /** @} cl_page */ /** \addtogroup cl_lock cl_lock @@ -2331,6 +2340,10 @@ struct cl_client_cache { */ spinlock_t ccc_lru_lock; /** + * Set if unstable check is enabled + */ + unsigned int ccc_unstable_check:1; + /** * # of unstable pages for this mount point */ atomic_t ccc_unstable_nr; diff --git a/drivers/staging/lustre/lustre/include/obd_support.h b/drivers/staging/lustre/lustre/include/obd_support.h index 26fdff6..a11fff1 100644 --- a/drivers/staging/lustre/lustre/include/obd_support.h +++ b/drivers/staging/lustre/lustre/include/obd_support.h @@ -54,7 +54,6 @@ extern int at_early_margin; extern int at_extra; extern unsigned int obd_sync_filter; extern unsigned int obd_max_dirty_pages; -extern atomic_t obd_unstable_pages; extern atomic_t obd_dirty_pages; extern atomic_t obd_dirty_transit_pages; extern char obd_jobid_var[]; diff --git a/drivers/staging/lustre/lustre/llite/lproc_llite.c b/drivers/staging/lustre/lustre/llite/lproc_llite.c index 2f1f389..5f8e78d 100644 --- a/drivers/staging/lustre/lustre/llite/lproc_llite.c +++ b/drivers/staging/lustre/lustre/llite/lproc_llite.c @@ -828,10 +828,45 @@ static ssize_t unstable_stats_show(struct kobject *kobj, pages = atomic_read(&cache->ccc_unstable_nr); mb = (pages * PAGE_SIZE) >> 20; - return sprintf(buf, "unstable_pages: %8d\n" - "unstable_mb: %8d\n", pages, mb); + return sprintf(buf, "unstable_check: %8d\n" + "unstable_pages: %8d\n" + "unstable_mb: %8d\n", + cache->ccc_unstable_check, pages, mb); } -LUSTRE_RO_ATTR(unstable_stats); + +static ssize_t unstable_stats_store(struct kobject *kobj, + struct attribute *attr, + const char *buffer, + size_t count) +{ + struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info, + ll_kobj); + char kernbuf[128]; + int val, rc; + + if (!count) + return 0; + if (count < 0 || count >= sizeof(kernbuf)) + return -EINVAL; + + if (copy_from_user(kernbuf, buffer, count)) + return -EFAULT; + kernbuf[count] = 0; + + buffer += lprocfs_find_named_value(kernbuf, "unstable_check:", &count) - + kernbuf; + rc = lprocfs_write_helper(buffer, count, &val); + if (rc < 0) + return rc; + + /* borrow lru lock to set the value */ + spin_lock(&sbi->ll_cache->ccc_lru_lock); + sbi->ll_cache->ccc_unstable_check = !!val; + spin_unlock(&sbi->ll_cache->ccc_lru_lock); + + return count; +} +LUSTRE_RW_ATTR(unstable_stats); static ssize_t root_squash_show(struct kobject *kobj, struct attribute *attr, char *buf) diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c index 6edf53e..90a365b 100644 --- a/drivers/staging/lustre/lustre/obdclass/class_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c @@ -57,8 +57,6 @@ unsigned int obd_dump_on_eviction; EXPORT_SYMBOL(obd_dump_on_eviction); unsigned int obd_max_dirty_pages = 256; EXPORT_SYMBOL(obd_max_dirty_pages); -atomic_t obd_unstable_pages; -EXPORT_SYMBOL(obd_unstable_pages); atomic_t obd_dirty_pages; EXPORT_SYMBOL(obd_dirty_pages); unsigned int obd_timeout = OBD_TIMEOUT_DEFAULT; /* seconds */ diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index 683b3c2..deaf912 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -1384,13 +1384,11 @@ static int osc_completion(const struct lu_env *env, struct osc_async_page *oap, #define OSC_DUMP_GRANT(lvl, cli, fmt, args...) do { \ struct client_obd *__tmp = (cli); \ CDEBUG(lvl, "%s: grant { dirty: %ld/%ld dirty_pages: %d/%d " \ - "unstable_pages: %d/%d dropped: %ld avail: %ld, " \ - "reserved: %ld, flight: %d } lru {in list: %d, " \ - "left: %d, waiters: %d }" fmt, \ + "dropped: %ld avail: %ld, reserved: %ld, flight: %d }" \ + "lru {in list: %d, left: %d, waiters: %d }" fmt, \ __tmp->cl_import->imp_obd->obd_name, \ __tmp->cl_dirty, __tmp->cl_dirty_max, \ atomic_read(&obd_dirty_pages), obd_max_dirty_pages, \ - atomic_read(&obd_unstable_pages), obd_max_dirty_pages, \ __tmp->cl_lost_grant, __tmp->cl_avail_grant, \ __tmp->cl_reserved_grant, __tmp->cl_w_in_flight, \ atomic_read(&__tmp->cl_lru_in_list), \ @@ -1542,8 +1540,7 @@ static int osc_enter_cache_try(struct client_obd *cli, return 0; if (cli->cl_dirty + PAGE_SIZE <= cli->cl_dirty_max && - atomic_read(&obd_unstable_pages) + 1 + - atomic_read(&obd_dirty_pages) <= obd_max_dirty_pages) { + atomic_read(&obd_dirty_pages) + 1 <= obd_max_dirty_pages) { osc_consume_write_grant(cli, &oap->oap_brw_page); if (transient) { cli->cl_dirty_transit += PAGE_SIZE; @@ -1671,8 +1668,7 @@ void osc_wake_cache_waiters(struct client_obd *cli) ocw->ocw_rc = -EDQUOT; /* we can't dirty more */ if ((cli->cl_dirty + PAGE_SIZE > cli->cl_dirty_max) || - (atomic_read(&obd_unstable_pages) + 1 + - atomic_read(&obd_dirty_pages) > obd_max_dirty_pages)) { + (atomic_read(&obd_dirty_pages) + 1 > obd_max_dirty_pages)) { CDEBUG(D_CACHE, "no dirty room: dirty: %ld osc max %ld, sys max %d\n", cli->cl_dirty, cli->cl_dirty_max, obd_max_dirty_pages); @@ -1843,84 +1839,6 @@ static void osc_process_ar(struct osc_async_rc *ar, __u64 xid, ar->ar_force_sync = 0; } -/** - * Performs "unstable" page accounting. This function balances the - * increment operations performed in osc_inc_unstable_pages. It is - * registered as the RPC request callback, and is executed when the - * bulk RPC is committed on the server. Thus at this point, the pages - * involved in the bulk transfer are no longer considered unstable. - */ -void osc_dec_unstable_pages(struct ptlrpc_request *req) -{ - struct client_obd *cli = &req->rq_import->imp_obd->u.cli; - struct ptlrpc_bulk_desc *desc = req->rq_bulk; - int page_count = desc->bd_iov_count; - int i; - - /* No unstable page tracking */ - if (!cli->cl_cache) - return; - - LASSERT(page_count >= 0); - - for (i = 0; i < page_count; i++) - dec_node_page_state(desc->bd_iov[i].bv_page, NR_UNSTABLE_NFS); - - atomic_sub(page_count, &cli->cl_cache->ccc_unstable_nr); - LASSERT(atomic_read(&cli->cl_cache->ccc_unstable_nr) >= 0); - - atomic_sub(page_count, &cli->cl_unstable_count); - LASSERT(atomic_read(&cli->cl_unstable_count) >= 0); - - atomic_sub(page_count, &obd_unstable_pages); - LASSERT(atomic_read(&obd_unstable_pages) >= 0); - - wake_up_all(&cli->cl_cache->ccc_unstable_waitq); -} - -/* "unstable" page accounting. See: osc_dec_unstable_pages. */ -void osc_inc_unstable_pages(struct ptlrpc_request *req) -{ - struct client_obd *cli = &req->rq_import->imp_obd->u.cli; - struct ptlrpc_bulk_desc *desc = req->rq_bulk; - long page_count = desc->bd_iov_count; - int i; - - /* No unstable page tracking */ - if (!cli->cl_cache) - return; - - LASSERT(page_count >= 0); - - for (i = 0; i < page_count; i++) - inc_node_page_state(desc->bd_iov[i].bv_page, NR_UNSTABLE_NFS); - - LASSERT(atomic_read(&cli->cl_cache->ccc_unstable_nr) >= 0); - atomic_add(page_count, &cli->cl_cache->ccc_unstable_nr); - - LASSERT(atomic_read(&cli->cl_unstable_count) >= 0); - atomic_add(page_count, &cli->cl_unstable_count); - - LASSERT(atomic_read(&obd_unstable_pages) >= 0); - atomic_add(page_count, &obd_unstable_pages); - - /* - * If the request has already been committed (i.e. brw_commit - * called via rq_commit_cb), we need to undo the unstable page - * increments we just performed because rq_commit_cb wont be - * called again. - */ - spin_lock(&req->rq_lock); - if (unlikely(req->rq_committed)) { - /* Drop lock before calling osc_dec_unstable_pages */ - spin_unlock(&req->rq_lock); - osc_dec_unstable_pages(req); - } else { - req->rq_unstable = 1; - spin_unlock(&req->rq_lock); - } -} - /* this must be called holding the loi list lock to give coverage to exit_cache, * async_flag maintenance, and oap_request */ @@ -1932,9 +1850,6 @@ static void osc_ap_completion(const struct lu_env *env, struct client_obd *cli, __u64 xid = 0; if (oap->oap_request) { - if (!rc) - osc_inc_unstable_pages(oap->oap_request); - xid = ptlrpc_req_xid(oap->oap_request); ptlrpc_req_finished(oap->oap_request); oap->oap_request = NULL; @@ -2421,9 +2336,6 @@ int osc_queue_async_io(const struct lu_env *env, struct cl_io *io, return rc; } - if (osc_over_unstable_soft_limit(cli)) - brw_flags |= OBD_BRW_SOFT_SYNC; - oap->oap_cmd = cmd; oap->oap_page_off = ops->ops_from; oap->oap_count = ops->ops_to - ops->ops_from; diff --git a/drivers/staging/lustre/lustre/osc/osc_internal.h b/drivers/staging/lustre/lustre/osc/osc_internal.h index 2038885..eca5fef 100644 --- a/drivers/staging/lustre/lustre/osc/osc_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_internal.h @@ -197,7 +197,7 @@ int osc_quotacheck(struct obd_device *unused, struct obd_export *exp, int osc_quota_poll_check(struct obd_export *exp, struct if_quotacheck *qchk); void osc_inc_unstable_pages(struct ptlrpc_request *req); void osc_dec_unstable_pages(struct ptlrpc_request *req); -int osc_over_unstable_soft_limit(struct client_obd *cli); +bool osc_over_unstable_soft_limit(struct client_obd *cli); struct ldlm_lock *osc_dlmlock_at_pgoff(const struct lu_env *env, struct osc_object *obj, pgoff_t index, diff --git a/drivers/staging/lustre/lustre/osc/osc_page.c b/drivers/staging/lustre/lustre/osc/osc_page.c index 355f496..583a0af 100644 --- a/drivers/staging/lustre/lustre/osc/osc_page.c +++ b/drivers/staging/lustre/lustre/osc/osc_page.c @@ -323,32 +323,6 @@ int osc_page_init(const struct lu_env *env, struct cl_object *obj, return result; } -int osc_over_unstable_soft_limit(struct client_obd *cli) -{ - long obd_upages, obd_dpages, osc_upages; - - /* Can't check cli->cl_unstable_count, therefore, no soft limit */ - if (!cli) - return 0; - - obd_upages = atomic_read(&obd_unstable_pages); - obd_dpages = atomic_read(&obd_dirty_pages); - - osc_upages = atomic_read(&cli->cl_unstable_count); - - /* - * obd_max_dirty_pages is the max number of (dirty + unstable) - * pages allowed at any given time. To simulate an unstable page - * only limit, we subtract the current number of dirty pages - * from this max. This difference is roughly the amount of pages - * currently available for unstable pages. Thus, the soft limit - * is half of that difference. Check osc_upages to ensure we don't - * set SOFT_SYNC for OSCs without any outstanding unstable pages. - */ - return osc_upages && - obd_upages >= (obd_max_dirty_pages - obd_dpages) / 2; -} - /** * Helper function called by osc_io_submit() for every page in an immediate * transfer (i.e., transferred synchronously). @@ -368,9 +342,6 @@ void osc_page_submit(const struct lu_env *env, struct osc_page *opg, oap->oap_count = opg->ops_to - opg->ops_from; oap->oap_brw_flags = brw_flags | OBD_BRW_SYNC; - if (osc_over_unstable_soft_limit(oap->oap_cli)) - oap->oap_brw_flags |= OBD_BRW_SOFT_SYNC; - if (capable(CFS_CAP_SYS_RESOURCE)) { oap->oap_brw_flags |= OBD_BRW_NOQUOTA; oap->oap_cmd |= OBD_BRW_NOQUOTA; @@ -540,6 +511,28 @@ static void discard_pagevec(const struct lu_env *env, struct cl_io *io, } /** + * Check if a cl_page can be released, i.e, it's not being used. + * + * If unstable account is turned on, bulk transfer may hold one refcount + * for recovery so we need to check vmpage refcount as well; otherwise, + * even we can destroy cl_page but the corresponding vmpage can't be reused. + */ +static inline bool lru_page_busy(struct client_obd *cli, struct cl_page *page) +{ + if (cl_page_in_use_noref(page)) + return true; + + if (cli->cl_cache->ccc_unstable_check) { + struct page *vmpage = cl_page_vmpage(page); + + /* vmpage have two known users: cl_page and VM page cache */ + if (page_count(vmpage) - page_mapcount(vmpage) > 2) + return true; + } + return false; +} + +/** * Drop @target of pages from LRU at most. */ int osc_lru_shrink(const struct lu_env *env, struct client_obd *cli, @@ -584,7 +577,7 @@ int osc_lru_shrink(const struct lu_env *env, struct client_obd *cli, break; page = opg->ops_cl.cpl_page; - if (cl_page_in_use_noref(page)) { + if (lru_page_busy(cli, page)) { list_move_tail(&opg->ops_lru, &cli->cl_lru_list); continue; } @@ -620,7 +613,7 @@ int osc_lru_shrink(const struct lu_env *env, struct client_obd *cli, } if (cl_page_own_try(env, io, page) == 0) { - if (!cl_page_in_use_noref(page)) { + if (!lru_page_busy(cli, page)) { /* remove it from lru list earlier to avoid * lock contention */ @@ -742,6 +735,13 @@ out: return rc; } +/** + * osc_lru_reserve() is called to reserve an LRU slot for a cl_page. + * + * Usually the LRU slots are reserved in osc_io_iter_rw_init(). + * Only in the case that the LRU slots are in extreme shortage, it should + * have reserved enough slots for an IO. + */ static int osc_lru_reserve(const struct lu_env *env, struct osc_object *obj, struct osc_page *opg) { @@ -787,4 +787,150 @@ out: return rc; } +/** + * Atomic operations are expensive. We accumulate the accounting for the + * same page zone to get better performance. + * In practice this can work pretty good because the pages in the same RPC + * are likely from the same page zone. + */ +static inline void unstable_page_accounting(struct ptlrpc_bulk_desc *desc, + int factor) +{ + int page_count = desc->bd_iov_count; + void *zone = NULL; + int count = 0; + int i; + + for (i = 0; i < page_count; i++) { + void *pz = page_zone(desc->bd_iov[i].bv_page); + + if (likely(pz == zone)) { + ++count; + continue; + } + + if (count > 0) { + mod_zone_page_state(zone, NR_UNSTABLE_NFS, + factor * count); + count = 0; + } + zone = pz; + ++count; + } + if (count > 0) + mod_zone_page_state(zone, NR_UNSTABLE_NFS, factor * count); +} + +static inline void add_unstable_page_accounting(struct ptlrpc_bulk_desc *desc) +{ + unstable_page_accounting(desc, 1); +} + +static inline void dec_unstable_page_accounting(struct ptlrpc_bulk_desc *desc) +{ + unstable_page_accounting(desc, -1); +} + +/** + * Performs "unstable" page accounting. This function balances the + * increment operations performed in osc_inc_unstable_pages. It is + * registered as the RPC request callback, and is executed when the + * bulk RPC is committed on the server. Thus at this point, the pages + * involved in the bulk transfer are no longer considered unstable. + * + * If this function is called, the request should have been committed + * or req:rq_unstable must have been set; it implies that the unstable + * statistic have been added. + */ +void osc_dec_unstable_pages(struct ptlrpc_request *req) +{ + struct client_obd *cli = &req->rq_import->imp_obd->u.cli; + struct ptlrpc_bulk_desc *desc = req->rq_bulk; + int page_count = desc->bd_iov_count; + int unstable_count; + + LASSERT(page_count >= 0); + dec_unstable_page_accounting(desc); + + unstable_count = atomic_sub_return(page_count, &cli->cl_unstable_count); + LASSERT(unstable_count >= 0); + + unstable_count = atomic_sub_return(page_count, + &cli->cl_cache->ccc_unstable_nr); + LASSERT(unstable_count >= 0); + if (!unstable_count) + wake_up_all(&cli->cl_cache->ccc_unstable_waitq); + + if (osc_cache_too_much(cli)) + (void)ptlrpcd_queue_work(cli->cl_lru_work); +} + +/** + * "unstable" page accounting. See: osc_dec_unstable_pages. + */ +void osc_inc_unstable_pages(struct ptlrpc_request *req) +{ + struct client_obd *cli = &req->rq_import->imp_obd->u.cli; + struct ptlrpc_bulk_desc *desc = req->rq_bulk; + int page_count = desc->bd_iov_count; + + /* No unstable page tracking */ + if (!cli->cl_cache || !cli->cl_cache->ccc_unstable_check) + return; + + add_unstable_page_accounting(desc); + atomic_add(page_count, &cli->cl_unstable_count); + atomic_add(page_count, &cli->cl_cache->ccc_unstable_nr); + + /* + * If the request has already been committed (i.e. brw_commit + * called via rq_commit_cb), we need to undo the unstable page + * increments we just performed because rq_commit_cb wont be + * called again. + */ + spin_lock(&req->rq_lock); + if (unlikely(req->rq_committed)) { + spin_unlock(&req->rq_lock); + + osc_dec_unstable_pages(req); + } else { + req->rq_unstable = 1; + spin_unlock(&req->rq_lock); + } +} + +/** + * Check if it piggybacks SOFT_SYNC flag to OST from this OSC. + * This function will be called by every BRW RPC so it's critical + * to make this function fast. + */ +bool osc_over_unstable_soft_limit(struct client_obd *cli) +{ + long unstable_nr, osc_unstable_count; + + /* Can't check cli->cl_unstable_count, therefore, no soft limit */ + if (!cli->cl_cache || !cli->cl_cache->ccc_unstable_check) + return false; + + osc_unstable_count = atomic_read(&cli->cl_unstable_count); + unstable_nr = atomic_read(&cli->cl_cache->ccc_unstable_nr); + + CDEBUG(D_CACHE, + "%s: cli: %p unstable pages: %lu, osc unstable pages: %lu\n", + cli->cl_import->imp_obd->obd_name, cli, + unstable_nr, osc_unstable_count); + + /* + * If the LRU slots are in shortage - 25% remaining AND this OSC + * has one full RPC window of unstable pages, it's a good chance + * to piggyback a SOFT_SYNC flag. + * Please notice that the OST won't take immediate response for the + * SOFT_SYNC request so active OSCs will have more chance to carry + * the flag, this is reasonable. + */ + return unstable_nr > cli->cl_cache->ccc_lru_max >> 2 && + osc_unstable_count > cli->cl_max_pages_per_rpc * + cli->cl_max_rpcs_in_flight; +} + /** @} osc */ diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 042a081..e5669e2 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -807,17 +807,15 @@ static void osc_announce_cached(struct client_obd *cli, struct obdo *oa, CERROR("dirty %lu - %lu > dirty_max %lu\n", cli->cl_dirty, cli->cl_dirty_transit, cli->cl_dirty_max); oa->o_undirty = 0; - } else if (unlikely(atomic_read(&obd_unstable_pages) + - atomic_read(&obd_dirty_pages) - + } else if (unlikely(atomic_read(&obd_dirty_pages) - atomic_read(&obd_dirty_transit_pages) > (long)(obd_max_dirty_pages + 1))) { /* The atomic_read() allowing the atomic_inc() are * not covered by a lock thus they may safely race and trip * this CERROR() unless we add in a small fudge factor (+1). */ - CERROR("%s: dirty %d + %d - %d > system dirty_max %d\n", + CERROR("%s: dirty %d + %d > system dirty_max %d\n", cli->cl_import->imp_obd->obd_name, - atomic_read(&obd_unstable_pages), atomic_read(&obd_dirty_pages), atomic_read(&obd_dirty_transit_pages), obd_max_dirty_pages); @@ -1818,6 +1816,9 @@ static int brw_interpret(const struct lu_env *env, } kmem_cache_free(obdo_cachep, aa->aa_oa); + if (lustre_msg_get_opc(req->rq_reqmsg) == OST_WRITE && rc == 0) + osc_inc_unstable_pages(req); + list_for_each_entry_safe(ext, tmp, &aa->aa_exts, oe_link) { list_del_init(&ext->oe_link); osc_extent_finish(env, ext, 1, rc); @@ -1888,6 +1889,7 @@ int osc_build_rpc(const struct lu_env *env, struct client_obd *cli, int mpflag = 0; int mem_tight = 0; int page_count = 0; + bool soft_sync = false; int i; int rc; struct ost_body *body; @@ -1915,6 +1917,7 @@ int osc_build_rpc(const struct lu_env *env, struct client_obd *cli, } } + soft_sync = osc_over_unstable_soft_limit(cli); if (mem_tight) mpflag = cfs_memory_pressure_get_and_set(); @@ -1950,6 +1953,8 @@ int osc_build_rpc(const struct lu_env *env, struct client_obd *cli, } if (mem_tight) oap->oap_brw_flags |= OBD_BRW_MEMALLOC; + if (soft_sync) + oap->oap_brw_flags |= OBD_BRW_SOFT_SYNC; pga[i] = &oap->oap_brw_page; pga[i]->off = oap->oap_obj_off + oap->oap_page_off; CDEBUG(0, "put page %p index %lu oap %p flg %x to pga\n", -- cgit v0.10.2 From 7aca4ae34c22c57f09d01695b956aac88ad3006c Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Tue, 16 Aug 2016 16:19:11 -0400 Subject: staging: lustre: mdc: always use D_INFO for debug info when mdc_put_rpc_lock fails Also use D_INFO no matter what the error returned from mdc_put_rpc_lock. Signed-off-by: Andreas Dilger <andreas.dilger@intel.com> Signed-off-by: wang di <di.wang@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4973 Reviewed-on: http://review.whamcloud.com/10150 Reviewed-by: Mike Pershin <mike.pershin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index 551f3d9..3291201 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -841,9 +841,8 @@ resend: mdc_put_rpc_lock(obddev->u.cli.cl_rpc_lock, it); if (rc < 0) { - CDEBUG_LIMIT((rc == -EACCES || rc == -EIDRM) ? D_INFO : D_ERROR, - "%s: ldlm_cli_enqueue failed: rc = %d\n", - obddev->obd_name, rc); + CDEBUG(D_INFO, "%s: ldlm_cli_enqueue failed: rc = %d\n", + obddev->obd_name, rc); mdc_clear_replay_flag(req, rc); ptlrpc_req_finished(req); -- cgit v0.10.2 From aa08b0e3c7ae977ed9384f63ded2743e0aee1c7e Mon Sep 17 00:00:00 2001 From: Patrick Farrell <paf@cray.com> Date: Tue, 16 Aug 2016 16:19:12 -0400 Subject: staging: lustre: fld: add fld description documentation Add subsystem description from Di Wang to header file. Signed-off-by: Patrick Farrell <paf@cray.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5153 Reviewed-on: http://review.whamcloud.com/10631 Reviewed-by: wangdi <di.wang@intel.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/fld/fld_internal.h b/drivers/staging/lustre/lustre/fld/fld_internal.h index f0efe5b..08eaec7 100644 --- a/drivers/staging/lustre/lustre/fld/fld_internal.h +++ b/drivers/staging/lustre/lustre/fld/fld_internal.h @@ -31,6 +31,25 @@ * * lustre/fld/fld_internal.h * + * Subsystem Description: + * FLD is FID Location Database, which stores where (IE, on which MDT) + * FIDs are located. + * The database is basically a record file, each record consists of a FID + * sequence range, MDT/OST index, and flags. The FLD for the whole FS + * is only stored on the sequence controller(MDT0) right now, but each target + * also has its local FLD, which only stores the local sequence. + * + * The FLD subsystem usually has two tasks: + * 1. maintain the database, i.e. when the sequence controller allocates + * new sequence ranges to some nodes, it will call the FLD API to insert the + * location information <sequence_range, node_index> in FLDB. + * + * 2. Handle requests from other nodes, i.e. if client needs to know where + * the FID is located, if it can not find the information in the local cache, + * it will send a FLD lookup RPC to the FLD service, and the FLD service will + * look up the FLDB entry and return the location information to client. + * + * * Author: Yury Umanets <umka@clusterfs.com> * Author: Tom WangDi <wangdi@clusterfs.com> */ -- cgit v0.10.2 From 099d5adf1ebb1d9d60097ece334930d9dab1bbc9 Mon Sep 17 00:00:00 2001 From: Emoly Liu <emoly.liu@intel.com> Date: Tue, 16 Aug 2016 16:19:13 -0400 Subject: staging: lustre: ldlm: improve ldlm_lock_create() return value ldlm_lock_create() and ldlm_resource_get() always return NULL as error reporting and "NULL" is interpretted as ENOMEM incorrectly sometimes. This patch fixes this problem by using ERR_PTR() rather than NULL. Signed-off-by: Emoly Liu <emoly.liu@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4524 Reviewed-on: http://review.whamcloud.com/9004 Reviewed-by: Bobi Jam <bobijam@gmail.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c index 65e8e14..61d649f 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c @@ -339,10 +339,10 @@ reprocess: lock->l_granted_mode, &null_cbs, NULL, 0, LVB_T_NONE); lock_res_and_lock(req); - if (!new2) { + if (IS_ERR(new2)) { ldlm_flock_destroy(req, lock->l_granted_mode, *flags); - *err = -ENOLCK; + *err = PTR_ERR(new2); return LDLM_ITER_STOP; } goto reprocess; diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c index 1a0fce1..a91cdb4 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c @@ -481,8 +481,8 @@ int ldlm_lock_change_resource(struct ldlm_namespace *ns, struct ldlm_lock *lock, unlock_res_and_lock(lock); newres = ldlm_resource_get(ns, NULL, new_resid, type, 1); - if (!newres) - return -ENOMEM; + if (IS_ERR(newres)) + return PTR_ERR(newres); lu_ref_add(&newres->lr_reference, "lock", lock); /* @@ -1227,7 +1227,7 @@ enum ldlm_mode ldlm_lock_match(struct ldlm_namespace *ns, __u64 flags, } res = ldlm_resource_get(ns, NULL, res_id, type, 0); - if (!res) { + if (IS_ERR(res)) { LASSERT(!old_lock); return 0; } @@ -1475,15 +1475,15 @@ struct ldlm_lock *ldlm_lock_create(struct ldlm_namespace *ns, { struct ldlm_lock *lock; struct ldlm_resource *res; + int rc; res = ldlm_resource_get(ns, NULL, res_id, type, 1); - if (!res) - return NULL; + if (IS_ERR(res)) + return ERR_CAST(res); lock = ldlm_lock_new(res); - if (!lock) - return NULL; + return ERR_PTR(-ENOMEM); lock->l_req_mode = mode; lock->l_ast_data = data; @@ -1497,27 +1497,33 @@ struct ldlm_lock *ldlm_lock_create(struct ldlm_namespace *ns, lock->l_tree_node = NULL; /* if this is the extent lock, allocate the interval tree node */ if (type == LDLM_EXTENT) { - if (!ldlm_interval_alloc(lock)) + if (!ldlm_interval_alloc(lock)) { + rc = -ENOMEM; goto out; + } } if (lvb_len) { lock->l_lvb_len = lvb_len; lock->l_lvb_data = kzalloc(lvb_len, GFP_NOFS); - if (!lock->l_lvb_data) + if (!lock->l_lvb_data) { + rc = -ENOMEM; goto out; + } } lock->l_lvb_type = lvb_type; - if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_NEW_LOCK)) + if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_NEW_LOCK)) { + rc = -ENOENT; goto out; + } return lock; out: ldlm_lock_destroy(lock); LDLM_LOCK_RELEASE(lock); - return NULL; + return ERR_PTR(rc); } /** diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index 984a460..048214c 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -694,8 +694,8 @@ int ldlm_cli_enqueue(struct obd_export *exp, struct ptlrpc_request **reqp, lock = ldlm_lock_create(ns, res_id, einfo->ei_type, einfo->ei_mode, &cbs, einfo->ei_cbdata, lvb_len, lvb_type); - if (!lock) - return -ENOMEM; + if (IS_ERR(lock)) + return PTR_ERR(lock); /* for the local lock, add the reference */ ldlm_lock_addref_internal(lock, einfo->ei_mode); ldlm_lock2handle(lock, lockh); @@ -1658,7 +1658,7 @@ int ldlm_cli_cancel_unused_resource(struct ldlm_namespace *ns, int rc; res = ldlm_resource_get(ns, NULL, res_id, 0, 0); - if (!res) { + if (IS_ERR(res)) { /* This is not a problem. */ CDEBUG(D_INFO, "No resource %llu\n", res_id->name[0]); return 0; @@ -1809,13 +1809,10 @@ int ldlm_resource_iterate(struct ldlm_namespace *ns, struct ldlm_resource *res; int rc; - if (!ns) { - CERROR("must pass in namespace\n"); - LBUG(); - } + LASSERTF(ns, "must pass in namespace\n"); res = ldlm_resource_get(ns, NULL, res_id, 0, 0); - if (!res) + if (IS_ERR(res)) return 0; LDLM_RESOURCE_ADDREF(res); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c index 5866b00..c37a7b0 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c @@ -1088,7 +1088,7 @@ ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent, int create) { struct hlist_node *hnode; - struct ldlm_resource *res; + struct ldlm_resource *res = NULL; struct cfs_hash_bd bd; __u64 version; int ns_refcount = 0; @@ -1101,31 +1101,20 @@ ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent, hnode = cfs_hash_bd_lookup_locked(ns->ns_rs_hash, &bd, (void *)name); if (hnode) { cfs_hash_bd_unlock(ns->ns_rs_hash, &bd, 0); - res = hlist_entry(hnode, struct ldlm_resource, lr_hash); - /* Synchronize with regard to resource creation. */ - if (ns->ns_lvbo && ns->ns_lvbo->lvbo_init) { - mutex_lock(&res->lr_lvb_mutex); - mutex_unlock(&res->lr_lvb_mutex); - } - - if (unlikely(res->lr_lvb_len < 0)) { - ldlm_resource_putref(res); - res = NULL; - } - return res; + goto lvbo_init; } version = cfs_hash_bd_version_get(&bd); cfs_hash_bd_unlock(ns->ns_rs_hash, &bd, 0); if (create == 0) - return NULL; + return ERR_PTR(-ENOENT); LASSERTF(type >= LDLM_MIN_TYPE && type < LDLM_MAX_TYPE, "type: %d\n", type); res = ldlm_resource_new(); if (!res) - return NULL; + return ERR_PTR(-ENOMEM); res->lr_ns_bucket = cfs_hash_bd_extra_get(ns->ns_rs_hash, &bd); res->lr_name = *name; @@ -1143,7 +1132,7 @@ ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent, /* We have taken lr_lvb_mutex. Drop it. */ mutex_unlock(&res->lr_lvb_mutex); kmem_cache_free(ldlm_resource_slab, res); - +lvbo_init: res = hlist_entry(hnode, struct ldlm_resource, lr_hash); /* Synchronize with regard to resource creation. */ if (ns->ns_lvbo && ns->ns_lvbo->lvbo_init) { @@ -1153,7 +1142,7 @@ ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent, if (unlikely(res->lr_lvb_len < 0)) { ldlm_resource_putref(res); - res = NULL; + res = ERR_PTR(res->lr_lvb_len); } return res; } @@ -1175,7 +1164,7 @@ ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent, res->lr_lvb_len = rc; mutex_unlock(&res->lr_lvb_mutex); ldlm_resource_putref(res); - return NULL; + return ERR_PTR(rc); } } diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index 3291201..fab83dd 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -174,7 +174,7 @@ int mdc_null_inode(struct obd_export *exp, fid_build_reg_res_name(fid, &res_id); res = ldlm_resource_get(ns, NULL, &res_id, 0, 0); - if (!res) + if (IS_ERR(res)) return 0; lock_res(res); diff --git a/drivers/staging/lustre/lustre/mdc/mdc_reint.c b/drivers/staging/lustre/lustre/mdc/mdc_reint.c index 9bec049..0f71392 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_reint.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_reint.c @@ -86,7 +86,7 @@ int mdc_resource_get_unused(struct obd_export *exp, const struct lu_fid *fid, fid_build_reg_res_name(fid, &res_id); res = ldlm_resource_get(exp->exp_obd->obd_namespace, NULL, &res_id, 0, 0); - if (!res) + if (IS_ERR(res)) return 0; LDLM_RESOURCE_ADDREF(res); /* Initialize ibits lock policy. */ diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index e5669e2..90c8416 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -650,7 +650,7 @@ static int osc_resource_get_unused(struct obd_export *exp, struct obdo *oa, ostid_build_res_name(&oa->o_oi, &res_id); res = ldlm_resource_get(ns, NULL, &res_id, 0, 0); - if (!res) + if (IS_ERR(res)) return 0; LDLM_RESOURCE_ADDREF(res); -- cgit v0.10.2 From b4e40299f6b90ce9d65224513a1c07e8fd128fc3 Mon Sep 17 00:00:00 2001 From: James Simmons <jsimmons@infradead.org> Date: Tue, 16 Aug 2016 16:19:14 -0400 Subject: staging: lustre: obdclass: compile issues with variable not being initialized One of the versions of gcc I have refuses to build obd_mount.c due to index not be initialized in function lmd_make_exclusion before it is used. Signed-off-by: James Simmons <uja.ornl@gmail.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4629 Reviewed-on: http://review.whamcloud.com/10705 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Bob Glossman <bob.glossman@intel.com> Reviewed-by: Dmitry Eremin <dmitry.eremin@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/obdclass/obd_mount.c b/drivers/staging/lustre/lustre/obdclass/obd_mount.c index 33d6c42..595ea1f 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_mount.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_mount.c @@ -730,7 +730,7 @@ int lustre_check_exclusion(struct super_block *sb, char *svname) static int lmd_make_exclusion(struct lustre_mount_data *lmd, const char *ptr) { const char *s1 = ptr, *s2; - __u32 index, *exclude_list; + __u32 index = 0, *exclude_list; int rc = 0, devmax; /* The shortest an ost name can be is 8 chars: -OST0000. -- cgit v0.10.2 From be191af9f571c3a4a9b05e49bfb970c79ca623e9 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf <behlendorf1@llnl.gov> Date: Tue, 16 Aug 2016 16:19:15 -0400 Subject: staging: lustre: obd: limit lu_object cache As the LU cache grows it can consume large enough chunks of memory that ends up preventing buffers for other objects, such as the OIs, from being cached and severely impacting the performance for FID lookups. Limit the lu_object cache to a maximum of lu_cache_nr objects. NOTES: * In order to be able to quickly determine the number of objects in the hash table the CFS_HASH_COUNTER flag is added. This adds an atomic_inc/dec to the hash insert/remove paths but is not expected to have any measurable impact of performance. Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5164 Reviewed-on: http://review.whamcloud.com/10237 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Alex Zhuravlev <alexey.zhuravlev@intel.com> Reviewed-by: Isaac Huang <he.huang@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c index 0c00bf8..9d1c96b 100644 --- a/drivers/staging/lustre/lustre/obdclass/lu_object.c +++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c @@ -55,6 +55,34 @@ #include "../include/lu_ref.h" #include <linux/list.h> +enum { + LU_CACHE_PERCENT_MAX = 50, + LU_CACHE_PERCENT_DEFAULT = 20 +}; + +#define LU_CACHE_NR_MAX_ADJUST 128 +#define LU_CACHE_NR_UNLIMITED -1 +#define LU_CACHE_NR_DEFAULT LU_CACHE_NR_UNLIMITED +#define LU_CACHE_NR_LDISKFS_LIMIT LU_CACHE_NR_UNLIMITED +#define LU_CACHE_NR_ZFS_LIMIT 256 + +#define LU_SITE_BITS_MIN 12 +#define LU_SITE_BITS_MAX 24 +/** + * total 256 buckets, we don't want too many buckets because: + * - consume too much memory + * - avoid unbalanced LRU list + */ +#define LU_SITE_BKT_BITS 8 + +static unsigned int lu_cache_percent = LU_CACHE_PERCENT_DEFAULT; +module_param(lu_cache_percent, int, 0644); +MODULE_PARM_DESC(lu_cache_percent, "Percentage of memory to be used as lu_object cache"); + +static long lu_cache_nr = LU_CACHE_NR_DEFAULT; +module_param(lu_cache_nr, long, 0644); +MODULE_PARM_DESC(lu_cache_nr, "Maximum number of objects in lu_object cache"); + static void lu_object_free(const struct lu_env *env, struct lu_object *o); static __u32 ls_stats_read(struct lprocfs_stats *stats, int idx); @@ -573,6 +601,27 @@ static struct lu_object *lu_object_find(const struct lu_env *env, return lu_object_find_at(env, dev->ld_site->ls_top_dev, f, conf); } +/* + * Limit the lu_object cache to a maximum of lu_cache_nr objects. Because + * the calculation for the number of objects to reclaim is not covered by + * a lock the maximum number of objects is capped by LU_CACHE_MAX_ADJUST. + * This ensures that many concurrent threads will not accidentally purge + * the entire cache. + */ +static void lu_object_limit(const struct lu_env *env, struct lu_device *dev) +{ + __u64 size, nr; + + if (lu_cache_nr == LU_CACHE_NR_UNLIMITED) + return; + + size = cfs_hash_size_get(dev->ld_site->ls_obj_hash); + nr = (__u64)lu_cache_nr; + if (size > nr) + lu_site_purge(env, dev->ld_site, + min_t(__u64, size - nr, LU_CACHE_NR_MAX_ADJUST)); +} + static struct lu_object *lu_object_new(const struct lu_env *env, struct lu_device *dev, const struct lu_fid *f, @@ -590,6 +639,9 @@ static struct lu_object *lu_object_new(const struct lu_env *env, cfs_hash_bd_get_and_lock(hs, (void *)f, &bd, 1); cfs_hash_bd_add_locked(hs, &bd, &o->lo_header->loh_hash); cfs_hash_bd_unlock(hs, &bd, 1); + + lu_object_limit(env, dev); + return o; } @@ -656,6 +708,9 @@ static struct lu_object *lu_object_find_try(const struct lu_env *env, if (likely(PTR_ERR(shadow) == -ENOENT)) { cfs_hash_bd_add_locked(hs, &bd, &o->lo_header->loh_hash); cfs_hash_bd_unlock(hs, &bd, 1); + + lu_object_limit(env, dev); + return o; } @@ -805,20 +860,12 @@ void lu_site_print(const struct lu_env *env, struct lu_site *s, void *cookie, } EXPORT_SYMBOL(lu_site_print); -enum { - LU_CACHE_PERCENT_MAX = 50, - LU_CACHE_PERCENT_DEFAULT = 20 -}; - -static unsigned int lu_cache_percent = LU_CACHE_PERCENT_DEFAULT; -module_param(lu_cache_percent, int, 0644); -MODULE_PARM_DESC(lu_cache_percent, "Percentage of memory to be used as lu_object cache"); - /** * Return desired hash table order. */ -static int lu_htable_order(void) +static int lu_htable_order(struct lu_device *top) { + unsigned long bits_max = LU_SITE_BITS_MAX; unsigned long cache_size; int bits; @@ -851,7 +898,7 @@ static int lu_htable_order(void) for (bits = 1; (1 << bits) < cache_size; ++bits) { ; } - return bits; + return clamp_t(typeof(bits), bits, LU_SITE_BITS_MIN, bits_max); } static unsigned lu_obj_hop_hash(struct cfs_hash *hs, @@ -927,28 +974,17 @@ static void lu_dev_add_linkage(struct lu_site *s, struct lu_device *d) /** * Initialize site \a s, with \a d as the top level device. */ -#define LU_SITE_BITS_MIN 12 -#define LU_SITE_BITS_MAX 19 -/** - * total 256 buckets, we don't want too many buckets because: - * - consume too much memory - * - avoid unbalanced LRU list - */ -#define LU_SITE_BKT_BITS 8 - int lu_site_init(struct lu_site *s, struct lu_device *top) { struct lu_site_bkt_data *bkt; struct cfs_hash_bd bd; + unsigned long bits; + unsigned long i; char name[16]; - int bits; - int i; memset(s, 0, sizeof(*s)); - bits = lu_htable_order(); snprintf(name, 16, "lu_site_%s", top->ld_type->ldt_name); - for (bits = min(max(LU_SITE_BITS_MIN, bits), LU_SITE_BITS_MAX); - bits >= LU_SITE_BITS_MIN; bits--) { + for (bits = lu_htable_order(top); bits >= LU_SITE_BITS_MIN; bits--) { s->ls_obj_hash = cfs_hash_create(name, bits, bits, bits - LU_SITE_BKT_BITS, sizeof(*bkt), 0, 0, @@ -956,13 +992,14 @@ int lu_site_init(struct lu_site *s, struct lu_device *top) CFS_HASH_SPIN_BKTLOCK | CFS_HASH_NO_ITEMREF | CFS_HASH_DEPTH | - CFS_HASH_ASSERT_EMPTY); + CFS_HASH_ASSERT_EMPTY | + CFS_HASH_COUNTER); if (s->ls_obj_hash) break; } if (!s->ls_obj_hash) { - CERROR("failed to create lu_site hash with bits: %d\n", bits); + CERROR("failed to create lu_site hash with bits: %lu\n", bits); return -ENOMEM; } -- cgit v0.10.2 From c1b66fccf9866fe5938be1fea12643a45bef7640 Mon Sep 17 00:00:00 2001 From: Lai Siyao <lai.siyao@intel.com> Date: Tue, 16 Aug 2016 16:19:16 -0400 Subject: staging: lustre: fid: do open-by-fid by default Currently client open-by-fid often packs name into the request, but the name may be invalid, eg. NFS export, and even if it's valid, it may cause inconsistency because this operation is done on this fid, which is globally unique, but name not. Since open-by-fid doesn't pack name, for striped dir we can't know parent stripe fid on client, so we set parent fid the same as child fid, and MDT has to find its parent fid from linkea (this is already supported by MDT). M_CHECK_STALE becomes obsolete. Unset MDS_OPEN_FL_INTERNAL from open syscall flags, because these flags are internally used, and should not be set from user space. It's not necessary to store parent fid in lli_pfid, because MDT can get it's parent fid from linkea, and now that DNE stripe directory stores master inode fid in lli_pfid, stop storing parent fid to avoid conflict. Signed-off-by: Lai Siyao <lai.siyao@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3544 Reviewed-on: http://review.whamcloud.com/7476 Reviewed-on: http://review.whamcloud.com/10692 Reviewed-by: Fan Yong <fan.yong@intel.com> Reviewed-by: Nathaniel Clark <nathaniel.l.clark@intel.com> Reviewed-by: wangdi <di.wang@intel.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 400ab3c..a9661c0 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -2252,6 +2252,11 @@ void lustre_swab_mdt_rec_setattr(struct mdt_rec_setattr *sa); */ #define MDS_OPEN_RELEASE 02000000000000ULL /* Open the file for HSM release */ +#define MDS_OPEN_FL_INTERNAL (MDS_OPEN_HAS_EA | MDS_OPEN_HAS_OBJS | \ + MDS_OPEN_OWNEROVERRIDE | MDS_OPEN_LOCK | \ + MDS_OPEN_BY_FID | MDS_OPEN_LEASE | \ + MDS_OPEN_RELEASE) + enum mds_op_bias { MDS_CHECK_SPLIT = 1 << 0, MDS_CROSS_REF = 1 << 1, diff --git a/drivers/staging/lustre/lustre/include/lustre_lite.h b/drivers/staging/lustre/lustre/include/lustre_lite.h index b168977..a3d7573 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lite.h +++ b/drivers/staging/lustre/lustre/include/lustre_lite.h @@ -42,7 +42,6 @@ #include "obd_class.h" #include "lustre_net.h" -#include "lustre_mds.h" #include "lustre_ha.h" /* 4UL * 1024 * 1024 */ diff --git a/drivers/staging/lustre/lustre/include/lustre_mds.h b/drivers/staging/lustre/lustre/include/lustre_mds.h index 4104bd9..23a7e4f 100644 --- a/drivers/staging/lustre/lustre/include/lustre_mds.h +++ b/drivers/staging/lustre/lustre/include/lustre_mds.h @@ -58,9 +58,6 @@ struct mds_group_info { #define MDD_OBD_NAME "mdd_obd" #define MDD_OBD_UUID "mdd_obd_uuid" -/* these are local flags, used only on the client, private */ -#define M_CHECK_STALE 0200000000 - /** @} mds */ #endif diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 563cdf6..015b0ab 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -379,53 +379,35 @@ int ll_file_release(struct inode *inode, struct file *file) return rc; } -static int ll_intent_file_open(struct dentry *dentry, void *lmm, - int lmmsize, struct lookup_intent *itp) +static int ll_intent_file_open(struct dentry *de, void *lmm, int lmmsize, + struct lookup_intent *itp) { - struct inode *inode = d_inode(dentry); + struct inode *inode = d_inode(de); struct ll_sb_info *sbi = ll_i2sbi(inode); - struct dentry *parent = dentry->d_parent; - const char *name = dentry->d_name.name; - const int len = dentry->d_name.len; + struct dentry *parent = de->d_parent; + const char *name = NULL; struct md_op_data *op_data; struct ptlrpc_request *req; - __u32 opc = LUSTRE_OPC_ANY; - int rc; + int len = 0, rc; - /* Usually we come here only for NFSD, and we want open lock. */ - /* We can also get here if there was cached open handle in revalidate_it - * but it disappeared while we were getting from there to ll_file_open. - * But this means this file was closed and immediately opened which - * makes a good candidate for using OPEN lock - */ - /* If lmmsize & lmm are not 0, we are just setting stripe info - * parameters. No need for the open lock + LASSERT(parent); + LASSERT(itp->it_flags & MDS_OPEN_BY_FID); + + /* + * if server supports open-by-fid, or file name is invalid, don't pack + * name in open request */ - if (!lmm && lmmsize == 0) { - struct ll_dentry_data *ldd = ll_d2d(dentry); - /* - * If we came via ll_iget_for_nfs, then we need to request - * struct ll_dentry_data *ldd = ll_d2d(file->f_dentry); - * - * NB: when ldd is NULL, it must have come via normal - * lookup path only, since ll_iget_for_nfs always calls - * ll_d_init(). - */ - if (ldd && ldd->lld_nfs_dentry) { - ldd->lld_nfs_dentry = 0; - itp->it_flags |= MDS_OPEN_LOCK; - } - if (itp->it_flags & FMODE_WRITE) - opc = LUSTRE_OPC_CREATE; + if (!(exp_connect_flags(sbi->ll_md_exp) & OBD_CONNECT_OPEN_BY_FID) && + lu_name_is_valid_2(de->d_name.name, de->d_name.len)) { + name = de->d_name.name; + len = de->d_name.len; } - op_data = ll_prep_md_op_data(NULL, d_inode(parent), - inode, name, len, - O_RDWR, opc, NULL); + op_data = ll_prep_md_op_data(NULL, d_inode(parent), inode, name, len, + O_RDWR, LUSTRE_OPC_ANY, NULL); if (IS_ERR(op_data)) return PTR_ERR(op_data); - itp->it_flags |= MDS_OPEN_BY_FID; rc = md_intent_lock(sbi->ll_md_exp, op_data, lmm, lmmsize, itp, 0 /*unused */, &req, ll_md_blocking_ast, 0); ll_finish_md_op_data(op_data); @@ -655,9 +637,19 @@ restart: * result in a deadlock */ mutex_unlock(&lli->lli_och_mutex); - it->it_create_mode |= M_CHECK_STALE; + /* + * Normally called under two situations: + * 1. NFS export. + * 2. revalidate with IT_OPEN (revalidate doesn't + * execute this intent any more). + * + * Always fetch MDS_OPEN_LOCK if this is not setstripe. + * + * Always specify MDS_OPEN_BY_FID because we don't want + * to get file with different fid. + */ + it->it_flags |= MDS_OPEN_LOCK | MDS_OPEN_BY_FID; rc = ll_intent_file_open(file->f_path.dentry, NULL, 0, it); - it->it_create_mode &= ~M_CHECK_STALE; if (rc) goto out_openerr; @@ -1399,6 +1391,7 @@ int ll_lov_setstripe_ea_info(struct inode *inode, struct dentry *dentry, } ll_inode_size_lock(inode); + oit.it_flags |= MDS_OPEN_BY_FID; rc = ll_intent_file_open(dentry, lum, lum_size, &oit); if (rc) goto out_unlock; @@ -3066,7 +3059,6 @@ static int __ll_inode_revalidate(struct dentry *dentry, __u64 ibits) if (IS_ERR(op_data)) return PTR_ERR(op_data); - oit.it_create_mode |= M_CHECK_STALE; rc = md_intent_lock(exp, op_data, NULL, 0, /* we are not interested in name * based lookup @@ -3074,7 +3066,6 @@ static int __ll_inode_revalidate(struct dentry *dentry, __u64 ibits) &oit, 0, &req, ll_md_blocking_ast, 0); ll_finish_md_op_data(op_data); - oit.it_create_mode &= ~M_CHECK_STALE; if (rc < 0) { rc = ll_inode_revalidate_fini(inode, rc); goto out; diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 43269aa..b4e843a 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -118,9 +118,7 @@ struct ll_inode_info { /* identifying fields for both metadata and data stacks. */ struct lu_fid lli_fid; - /* Parent fid for accessing default stripe data on parent directory - * for allocating OST objects after a mknod() and later open-by-FID. - */ + /* master inode fid for stripe directory */ struct lu_fid lli_pfid; struct list_head lli_close_list; diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 5f6343a..da00fbd 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -189,7 +189,8 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, OBD_CONNECT_PINGLESS | OBD_CONNECT_MAX_EASIZE | OBD_CONNECT_FLOCK_DEAD | - OBD_CONNECT_DISP_STRIPE | OBD_CONNECT_LFSCK; + OBD_CONNECT_DISP_STRIPE | OBD_CONNECT_LFSCK | + OBD_CONNECT_OPEN_BY_FID; if (sbi->ll_flags & LL_SBI_SOM_PREVIEW) data->ocd_connect_flags |= OBD_CONNECT_SOM; @@ -2364,20 +2365,6 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, op_data->op_mds = 0; op_data->op_data = data; - /* If the file is being opened after mknod() (normally due to NFS) - * try to use the default stripe data from parent directory for - * allocating OST objects. Try to pass the parent FID to MDS. - */ - if (opc == LUSTRE_OPC_CREATE && i1 == i2 && S_ISREG(i2->i_mode) && - !ll_i2info(i2)->lli_has_smd) { - struct ll_inode_info *lli = ll_i2info(i2); - - spin_lock(&lli->lli_lock); - if (likely(!lli->lli_has_smd && !fid_is_zero(&lli->lli_pfid))) - op_data->op_fid1 = lli->lli_pfid; - spin_unlock(&lli->lli_lock); - } - /* When called by ll_setattr_raw, file is i1. */ if (ll_i2info(i1)->lli_flags & LLIF_DATA_MODIFIED) op_data->op_bias |= MDS_DATA_MODIFIED; diff --git a/drivers/staging/lustre/lustre/llite/llite_nfs.c b/drivers/staging/lustre/lustre/llite/llite_nfs.c index ac96d89..2b65240 100644 --- a/drivers/staging/lustre/lustre/llite/llite_nfs.c +++ b/drivers/staging/lustre/lustre/llite/llite_nfs.c @@ -148,12 +148,18 @@ ll_iget_for_nfs(struct super_block *sb, struct lu_fid *fid, struct lu_fid *paren return ERR_PTR(-ESTALE); } + result = d_obtain_alias(inode); + if (IS_ERR(result)) { + iput(inode); + return result; + } + /** - * It is an anonymous dentry without OST objects created yet. - * We have to find the parent to tell MDS how to init lov objects. + * In case d_obtain_alias() found a disconnected dentry, always update + * lli_pfid to allow later operation (normally open) have parent fid, + * which may be used by MDS to create data. */ - if (S_ISREG(inode->i_mode) && !ll_i2info(inode)->lli_has_smd && - parent && !fid_is_zero(parent)) { + if (parent) { struct ll_inode_info *lli = ll_i2info(inode); spin_lock(&lli->lli_lock); diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index ac0f442..ee5a42e 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -650,6 +650,7 @@ static int ll_atomic_open(struct inode *dir, struct dentry *dentry, } it->it_create_mode = (mode & S_IALLUGO) | S_IFREG; it->it_flags = (open_flags & ~O_ACCMODE) | OPEN_FMODE(open_flags); + it->it_flags &= ~MDS_OPEN_FL_INTERNAL; /* Dentry added to dcache tree in ll_lookup_it */ de = ll_lookup_it(dir, dentry, it, lookup_flags); diff --git a/drivers/staging/lustre/lustre/lmv/lmv_intent.c b/drivers/staging/lustre/lustre/lmv/lmv_intent.c index 761ab24..cde1d7b 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_intent.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_intent.c @@ -111,10 +111,6 @@ static int lmv_intent_remote(struct obd_export *exp, void *lmm, */ LASSERT(it->it_op & IT_OPEN); op_data->op_fid2 = *parent_fid; - /* Add object FID to op_fid3, in case it needs to check stale - * (M_CHECK_STALE), see mdc_finish_intent_lock - */ - op_data->op_fid3 = body->mbo_fid1; } op_data->op_bias = MDS_CROSS_REF; @@ -313,17 +309,16 @@ static int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data, struct mdt_body *body; int rc; - if (it->it_flags & MDS_OPEN_BY_FID && fid_is_sane(&op_data->op_fid2)) { - if (op_data->op_mea1) { - struct lmv_stripe_md *lsm = op_data->op_mea1; - const struct lmv_oinfo *oinfo; + if (it->it_flags & MDS_OPEN_BY_FID) { + LASSERT(fid_is_sane(&op_data->op_fid2)); - oinfo = lsm_name_to_stripe_info(lsm, op_data->op_name, - op_data->op_namelen); - if (IS_ERR(oinfo)) - return PTR_ERR(oinfo); - op_data->op_fid1 = oinfo->lmo_fid; - } + /* + * for striped directory, we can't know parent stripe fid + * without name, but we can set it to child fid, and MDT + * will obtain it from linkea in open in such case. + */ + if (op_data->op_mea1) + op_data->op_fid1 = op_data->op_fid2; tgt = lmv_find_target(lmv, &op_data->op_fid2); if (IS_ERR(tgt)) @@ -331,6 +326,10 @@ static int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data, op_data->op_mds = tgt->ltd_idx; } else { + LASSERT(fid_is_sane(&op_data->op_fid1)); + LASSERT(fid_is_zero(&op_data->op_fid2)); + LASSERT(op_data->op_name); + tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1); if (IS_ERR(tgt)) return PTR_ERR(tgt); @@ -339,13 +338,11 @@ static int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data, /* If it is ready to open the file by FID, do not need * allocate FID at all, otherwise it will confuse MDT */ - if ((it->it_op & IT_CREAT) && - !(it->it_flags & MDS_OPEN_BY_FID)) { + if ((it->it_op & IT_CREAT) && !(it->it_flags & MDS_OPEN_BY_FID)) { /* - * For open with IT_CREATE and for IT_CREATE cases allocate new - * fid and setup FLD for it. + * For lookup(IT_CREATE) cases allocate new fid and setup FLD + * for it. */ - op_data->op_fid3 = op_data->op_fid2; rc = lmv_fid_alloc(NULL, exp, &op_data->op_fid2, op_data); if (rc != 0) return rc; @@ -494,9 +491,9 @@ int lmv_intent_lock(struct obd_export *exp, struct md_op_data *op_data, LASSERT(fid_is_sane(&op_data->op_fid1)); - CDEBUG(D_INODE, "INTENT LOCK '%s' for '%*s' on "DFID"\n", - LL_IT2STR(it), op_data->op_namelen, op_data->op_name, - PFID(&op_data->op_fid1)); + CDEBUG(D_INODE, "INTENT LOCK '%s' for "DFID" '%*s' on "DFID"\n", + LL_IT2STR(it), PFID(&op_data->op_fid2), op_data->op_namelen, + op_data->op_name, PFID(&op_data->op_fid1)); rc = lmv_check_connect(obd); if (rc) diff --git a/drivers/staging/lustre/lustre/mdc/mdc_internal.h b/drivers/staging/lustre/lustre/mdc/mdc_internal.h index 00e8435..1901b93 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_internal.h +++ b/drivers/staging/lustre/lustre/mdc/mdc_internal.h @@ -34,7 +34,6 @@ #define _MDC_INTERNAL_H #include "../include/lustre_mdc.h" -#include "../include/lustre_mds.h" void lprocfs_mdc_init_vars(struct lprocfs_static_vars *lvars); diff --git a/drivers/staging/lustre/lustre/mdc/mdc_lib.c b/drivers/staging/lustre/lustre/mdc/mdc_lib.c index 813f923..aa496f3 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_lib.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_lib.c @@ -171,10 +171,7 @@ void mdc_create_pack(struct ptlrpc_request *req, struct md_op_data *op_data, static __u64 mds_pack_open_flags(__u64 flags, __u32 mode) { __u64 cr_flags = (flags & (FMODE_READ | FMODE_WRITE | - MDS_OPEN_HAS_EA | MDS_OPEN_HAS_OBJS | - MDS_OPEN_OWNEROVERRIDE | MDS_OPEN_LOCK | - MDS_OPEN_BY_FID | MDS_OPEN_LEASE | - MDS_OPEN_RELEASE)); + MDS_OPEN_FL_INTERNAL)); if (flags & O_CREAT) cr_flags |= MDS_OPEN_CREAT; if (flags & O_EXCL) diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index fab83dd..1c3b78d 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -922,27 +922,6 @@ static int mdc_finish_intent_lock(struct obd_export *exp, mdt_body = req_capsule_server_get(&request->rq_pill, &RMF_MDT_BODY); LASSERT(mdt_body); /* mdc_enqueue checked */ - /* If we were revalidating a fid/name pair, mark the intent in - * case we fail and get called again from lookup - */ - if (fid_is_sane(&op_data->op_fid2) && - it->it_create_mode & M_CHECK_STALE && - it->it_op != IT_GETATTR) { - /* Also: did we find the same inode? */ - /* sever can return one of two fids: - * op_fid2 - new allocated fid - if file is created. - * op_fid3 - existent fid - if file only open. - * op_fid3 is saved in lmv_intent_open - */ - if ((!lu_fid_eq(&op_data->op_fid2, &mdt_body->mbo_fid1)) && - (!lu_fid_eq(&op_data->op_fid3, &mdt_body->mbo_fid1))) { - CDEBUG(D_DENTRY, "Found stale data "DFID"("DFID")/"DFID - "\n", PFID(&op_data->op_fid2), - PFID(&op_data->op_fid2), PFID(&mdt_body->mbo_fid1)); - return -ESTALE; - } - } - rc = it_open_error(DISP_LOOKUP_EXECD, it); if (rc) return rc; diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c index f42ed17..fbb0851 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c @@ -96,7 +96,7 @@ static const char * const obd_connect_names[] = { "pingless", "flock_deadlock", "disp_stripe", - "unknown", + "open_by_fid", "lfsck", "unknown", NULL -- cgit v0.10.2 From ac094f382f7e20df5fd1c9ad021652c9e9199ec6 Mon Sep 17 00:00:00 2001 From: Lai Siyao <lai.siyao@intel.com> Date: Tue, 16 Aug 2016 16:19:17 -0400 Subject: staging: lustre: ptlrpc: add OBD_CONNECT_UNLINK_CLOSE flag Add OBD_CONNECT_UNLINK_CLOSE flag for interop, once this is supported, client packs file handle in unlink RPC, and MDT will close file before unlink. Signed-off-by: Lai Siyao <lai.siyao@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4367 Reviewed-on: http://review.whamcloud.com/10426 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index a9661c0..4a7ccc8 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -1290,6 +1290,7 @@ void lustre_swab_ptlrpc_body(struct ptlrpc_body *pb); * name in request */ #define OBD_CONNECT_LFSCK 0x40000000000000ULL/* support online LFSCK */ +#define OBD_CONNECT_UNLINK_CLOSE 0x100000000000000ULL/* close file in unlink */ /* XXX README XXX: * Please DO NOT add flag values here before first ensuring that this same diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c index fbb0851..45e3c4a 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c @@ -99,6 +99,8 @@ static const char * const obd_connect_names[] = { "open_by_fid", "lfsck", "unknown", + "unlink_close", + "unknown", NULL }; diff --git a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c index 60d03dd..2c718e0 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c +++ b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c @@ -1073,6 +1073,8 @@ void lustre_assert_wire_constants(void) "found 0x%.16llxULL\n", OBD_CONNECT_OPEN_BY_FID); LASSERTF(OBD_CONNECT_LFSCK == 0x40000000000000ULL, "found 0x%.16llxULL\n", OBD_CONNECT_LFSCK); + LASSERTF(OBD_CONNECT_UNLINK_CLOSE == 0x100000000000000ULL, "found 0x%.16llxULL\n", + OBD_CONNECT_UNLINK_CLOSE); LASSERTF(OBD_CKSUM_CRC32 == 0x00000001UL, "found 0x%.8xUL\n", (unsigned)OBD_CKSUM_CRC32); LASSERTF(OBD_CKSUM_ADLER == 0x00000002UL, "found 0x%.8xUL\n", -- cgit v0.10.2 From b14b3ba5775452bdfde0067031fde94a7c18e027 Mon Sep 17 00:00:00 2001 From: Mikhail Pershin <mike.pershin@intel.com> Date: Tue, 16 Aug 2016 16:19:18 -0400 Subject: staging: lustre: llog: keep llog ctxt indices constant The llog context id table cannot be shrunk easily because that will cause index shifting and incompatibility between old client and new server and vice versa. Patch moves llog_ctxt_id table to the lustre_idl.h because this is wire protocol data, these values are added to the wirecheck. Signed-off-by: Mikhail Pershin <mike.pershin@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5218 Reviewed-on: http://review.whamcloud.com/10758 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 4a7ccc8..05fe359 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -2936,7 +2936,29 @@ enum obd_cmd { }; #define OBD_FIRST_OPC OBD_PING -/* catalog of log objects */ +/** + * llog contexts indices. + * + * There is compatibility problem with indexes below, they are not + * continuous and must keep their numbers for compatibility needs. + * See LU-5218 for details. + */ +enum llog_ctxt_id { + LLOG_CONFIG_ORIG_CTXT = 0, + LLOG_CONFIG_REPL_CTXT = 1, + LLOG_MDS_OST_ORIG_CTXT = 2, + LLOG_MDS_OST_REPL_CTXT = 3, /* kept just to avoid re-assignment */ + LLOG_SIZE_ORIG_CTXT = 4, + LLOG_SIZE_REPL_CTXT = 5, + LLOG_TEST_ORIG_CTXT = 8, + LLOG_TEST_REPL_CTXT = 9, /* kept just to avoid re-assignment */ + LLOG_CHANGELOG_ORIG_CTXT = 12, /**< changelog generation on mdd */ + LLOG_CHANGELOG_REPL_CTXT = 13, /**< changelog access on clients */ + /* for multiple changelog consumers */ + LLOG_CHANGELOG_USER_ORIG_CTXT = 14, + LLOG_AGENT_ORIG_CTXT = 15, /**< agent requests generation on cdt */ + LLOG_MAX_CTXTS +}; /** Identifier for a single log object */ struct llog_logid { diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index b7bdd07..e7e03be 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -172,27 +172,6 @@ struct brw_page { u32 flag; }; -/* llog contexts */ -enum llog_ctxt_id { - LLOG_CONFIG_ORIG_CTXT = 0, - LLOG_CONFIG_REPL_CTXT, - LLOG_MDS_OST_ORIG_CTXT, - LLOG_MDS_OST_REPL_CTXT, - LLOG_SIZE_ORIG_CTXT, - LLOG_SIZE_REPL_CTXT, - LLOG_RD1_ORIG_CTXT, - LLOG_RD1_REPL_CTXT, - LLOG_TEST_ORIG_CTXT, - LLOG_TEST_REPL_CTXT, - LLOG_LOVEA_ORIG_CTXT, - LLOG_LOVEA_REPL_CTXT, - LLOG_CHANGELOG_ORIG_CTXT, /**< changelog generation on mdd */ - LLOG_CHANGELOG_REPL_CTXT, /**< changelog access on clients */ - LLOG_CHANGELOG_USER_ORIG_CTXT, /**< for multiple changelog consumers */ - LLOG_AGENT_ORIG_CTXT, /**< agent requests generation on cdt */ - LLOG_MAX_CTXTS -}; - struct timeout_item { enum timeout_event ti_event; unsigned long ti_timeout; diff --git a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c index 2c718e0..31d3326 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c +++ b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c @@ -3483,6 +3483,19 @@ void lustre_assert_wire_constants(void) CLASSERT(LLOG_ORIGIN_HANDLE_DESTROY == 509); CLASSERT(LLOG_FIRST_OPC == 501); CLASSERT(LLOG_LAST_OPC == 510); + CLASSERT(LLOG_CONFIG_ORIG_CTXT == 0); + CLASSERT(LLOG_CONFIG_REPL_CTXT == 1); + CLASSERT(LLOG_MDS_OST_ORIG_CTXT == 2); + CLASSERT(LLOG_MDS_OST_REPL_CTXT == 3); + CLASSERT(LLOG_SIZE_ORIG_CTXT == 4); + CLASSERT(LLOG_SIZE_REPL_CTXT == 5); + CLASSERT(LLOG_TEST_ORIG_CTXT == 8); + CLASSERT(LLOG_TEST_REPL_CTXT == 9); + CLASSERT(LLOG_CHANGELOG_ORIG_CTXT == 12); + CLASSERT(LLOG_CHANGELOG_REPL_CTXT == 13); + CLASSERT(LLOG_CHANGELOG_USER_ORIG_CTXT == 14); + CLASSERT(LLOG_AGENT_ORIG_CTXT == 15); + CLASSERT(LLOG_MAX_CTXTS == 16); /* Checks for struct llogd_conn_body */ LASSERTF((int)sizeof(struct llogd_conn_body) == 40, "found %lld\n", -- cgit v0.10.2 From 893ab74792632cca7c49382fd80c6304df51294e Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Tue, 16 Aug 2016 16:19:19 -0400 Subject: staging: lustre: lmv: try all stripes for unknown hash functions For unknown hash type, LMV should try all stripes to locate the name entry. But it will only for lookup and unlink, i.e. we can only list and unlink entries under striped dir with unknown hash type. Signed-off-by: wang di <di.wang@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4921 Reviewed-on: http://review.whamcloud.com/10041 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index 9e38ed3..52cd585 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -383,6 +383,7 @@ struct lmv_user_mds_data { }; enum lmv_hash_type { + LMV_HASH_TYPE_UNKNOWN = 0, /* 0 is reserved for testing purpose */ LMV_HASH_TYPE_ALL_CHARS = 1, LMV_HASH_TYPE_FNV_1A_64 = 2, }; diff --git a/drivers/staging/lustre/lustre/include/obd_support.h b/drivers/staging/lustre/lustre/include/obd_support.h index a11fff1..f747bca 100644 --- a/drivers/staging/lustre/lustre/include/obd_support.h +++ b/drivers/staging/lustre/lustre/include/obd_support.h @@ -483,6 +483,9 @@ extern char obd_jobid_var[]; #define OBD_FAIL_UPDATE_OBJ_NET 0x1700 #define OBD_FAIL_UPDATE_OBJ_NET_REP 0x1701 +/* LMV */ +#define OBD_FAIL_UNKNOWN_LMV_STRIPE 0x1901 + /* Assign references to moved code to reduce code changes */ #define OBD_FAIL_PRECHECK(id) CFS_FAIL_PRECHECK(id) #define OBD_FAIL_CHECK(id) CFS_FAIL_CHECK(id) diff --git a/drivers/staging/lustre/lustre/lmv/lmv_intent.c b/drivers/staging/lustre/lustre/lmv/lmv_intent.c index cde1d7b..0559445 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_intent.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_intent.c @@ -402,10 +402,28 @@ static int lmv_intent_lookup(struct obd_export *exp, struct mdt_body *body; int rc = 0; + /* + * If it returns ERR_PTR(-EBADFD) then it is an unknown hash type + * it will try all stripes to locate the object + */ tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1); - if (IS_ERR(tgt)) + if (IS_ERR(tgt) && (PTR_ERR(tgt) != -EBADFD)) return PTR_ERR(tgt); + /* + * Both migrating dir and unknown hash dir need to try + * all of sub-stripes + */ + if (lsm && !lmv_is_known_hash_type(lsm)) { + struct lmv_oinfo *oinfo = &lsm->lsm_md_oinfo[0]; + + op_data->op_fid1 = oinfo->lmo_fid; + op_data->op_mds = oinfo->lmo_mds; + tgt = lmv_get_target(lmv, oinfo->lmo_mds, NULL); + if (IS_ERR(tgt)) + return PTR_ERR(tgt); + } + if (!fid_is_sane(&op_data->op_fid2)) fid_zero(&op_data->op_fid2); @@ -435,27 +453,39 @@ static int lmv_intent_lookup(struct obd_export *exp, } return rc; } else if (it_disposition(it, DISP_LOOKUP_NEG) && lsm && - lsm->lsm_md_magic & LMV_HASH_FLAG_MIGRATION) { + lmv_need_try_all_stripes(lsm)) { /* - * For migrating directory, if it can not find the child in - * the source directory(master stripe), try the targeting - * directory(stripe 1) + * For migrating and unknown hash type directory, it will + * try to target the entry on other stripes */ - tgt = lmv_find_target(lmv, &lsm->lsm_md_oinfo[1].lmo_fid); - if (IS_ERR(tgt)) - return PTR_ERR(tgt); - - ptlrpc_req_finished(*reqp); - it->it_request = NULL; - *reqp = NULL; - - CDEBUG(D_INODE, "For migrating dir, try target dir "DFID"\n", - PFID(&lsm->lsm_md_oinfo[1].lmo_fid)); - - op_data->op_fid1 = lsm->lsm_md_oinfo[1].lmo_fid; - it->it_disposition &= ~DISP_ENQ_COMPLETE; - rc = md_intent_lock(tgt->ltd_exp, op_data, lmm, lmmsize, it, - flags, reqp, cb_blocking, extra_lock_flags); + int stripe_index; + + for (stripe_index = 1; + stripe_index < lsm->lsm_md_stripe_count && + it_disposition(it, DISP_LOOKUP_NEG); stripe_index++) { + struct lmv_oinfo *oinfo; + + /* release the previous request */ + ptlrpc_req_finished(*reqp); + it->it_request = NULL; + *reqp = NULL; + + oinfo = &lsm->lsm_md_oinfo[stripe_index]; + tgt = lmv_find_target(lmv, &oinfo->lmo_fid); + if (IS_ERR(tgt)) + return PTR_ERR(tgt); + + CDEBUG(D_INODE, "Try other stripes " DFID"\n", + PFID(&oinfo->lmo_fid)); + + op_data->op_fid1 = oinfo->lmo_fid; + it->it_disposition &= ~DISP_ENQ_COMPLETE; + rc = md_intent_lock(tgt->ltd_exp, op_data, lmm, + lmmsize, it, flags, reqp, + cb_blocking, extra_lock_flags); + if (rc) + return rc; + } } /* diff --git a/drivers/staging/lustre/lustre/lmv/lmv_internal.h b/drivers/staging/lustre/lustre/lmv/lmv_internal.h index faf6a7b..ea528ae 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_internal.h +++ b/drivers/staging/lustre/lustre/lmv/lmv_internal.h @@ -147,6 +147,18 @@ lsm_name_to_stripe_info(const struct lmv_stripe_md *lsm, const char *name, return &lsm->lsm_md_oinfo[stripe_index]; } +static inline bool lmv_is_known_hash_type(const struct lmv_stripe_md *lsm) +{ + return lsm->lsm_md_hash_type == LMV_HASH_TYPE_FNV_1A_64 || + lsm->lsm_md_hash_type == LMV_HASH_TYPE_ALL_CHARS; +} + +static inline bool lmv_need_try_all_stripes(const struct lmv_stripe_md *lsm) +{ + return !lmv_is_known_hash_type(lsm) || + lsm->lsm_md_hash_type & LMV_HASH_FLAG_MIGRATION; +} + struct lmv_tgt_desc *lmv_locate_mds(struct lmv_obd *lmv, struct md_op_data *op_data, struct lu_fid *fid); diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 27a6be1..e9f4e9a 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -102,8 +102,8 @@ int lmv_name_to_stripe_index(__u32 lmv_hash_type, unsigned int stripe_count, idx = lmv_hash_fnv1a(stripe_count, name, namelen); break; default: - CERROR("Unknown hash type 0x%x\n", hash_type); - return -EINVAL; + idx = -EBADFD; + break; } CDEBUG(D_INFO, "name %.*s hash_type %d idx %d\n", namelen, name, @@ -1697,6 +1697,23 @@ lmv_locate_target_for_name(struct lmv_obd *lmv, struct lmv_stripe_md *lsm, return tgt; } +/** + * Locate mds by fid or name + * + * For striped directory (lsm != NULL), it will locate the stripe + * by name hash (see lsm_name_to_stripe_info()). Note: if the hash_type + * is unknown, it will return -EBADFD, and lmv_intent_lookup might need + * walk through all of stripes to locate the entry. + * + * For normal direcotry, it will locate MDS by FID directly. + * \param[in] lmv LMV device + * \param[in] op_data client MD stack parameters, name, namelen + * mds_num etc. + * \param[in] fid object FID used to locate MDS. + * + * retval pointer to the lmv_tgt_desc if succeed. + * ERR_PTR(errno) if failed. + */ struct lmv_tgt_desc *lmv_locate_mds(struct lmv_obd *lmv, struct md_op_data *op_data, struct lu_fid *fid) @@ -2351,45 +2368,94 @@ static int lmv_readpage(struct obd_export *exp, struct md_op_data *op_data, return rc; } +/** + * Unlink a file/directory + * + * Unlink a file or directory under the parent dir. The unlink request + * usually will be sent to the MDT where the child is located, but if + * the client does not have the child FID then request will be sent to the + * MDT where the parent is located. + * + * If the parent is a striped directory then it also needs to locate which + * stripe the name of the child is located, and replace the parent FID + * (@op->op_fid1) with the stripe FID. Note: if the stripe is unknown, + * it will walk through all of sub-stripes until the child is being + * unlinked finally. + * + * \param[in] exp export refer to LMV + * \param[in] op_data different parameters transferred beween client + * MD stacks, name, namelen, FIDs etc. + * op_fid1 is the parent FID, op_fid2 is the child + * FID. + * \param[out] request point to the request of unlink. + * + * retval 0 if succeed + * negative errno if failed. + */ static int lmv_unlink(struct obd_export *exp, struct md_op_data *op_data, struct ptlrpc_request **request) { - struct obd_device *obd = exp->exp_obd; + struct lmv_stripe_md *lsm = op_data->op_mea1; + struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *parent_tgt = NULL; struct lmv_tgt_desc *tgt = NULL; struct mdt_body *body; + int stripe_index = 0; int rc; rc = lmv_check_connect(obd); if (rc) return rc; -retry: - /* Send unlink requests to the MDT where the child is located */ - if (likely(!fid_is_zero(&op_data->op_fid2))) { - tgt = lmv_find_target(lmv, &op_data->op_fid2); - if (IS_ERR(tgt)) - return PTR_ERR(tgt); +retry_unlink: + /* For striped dir, we need to locate the parent as well */ + if (lsm) { + struct lmv_tgt_desc *tmp; - /* For striped dir, we need to locate the parent as well */ - if (op_data->op_mea1) { - struct lmv_tgt_desc *tmp; - - LASSERT(op_data->op_name && op_data->op_namelen); - tmp = lmv_locate_target_for_name(lmv, op_data->op_mea1, - op_data->op_name, - op_data->op_namelen, - &op_data->op_fid1, - &op_data->op_mds); - if (IS_ERR(tmp)) - return PTR_ERR(tmp); + LASSERT(op_data->op_name && op_data->op_namelen); + + tmp = lmv_locate_target_for_name(lmv, lsm, + op_data->op_name, + op_data->op_namelen, + &op_data->op_fid1, + &op_data->op_mds); + + /* + * return -EBADFD means unknown hash type, might + * need try all sub-stripe here + */ + if (IS_ERR(tmp) && PTR_ERR(tmp) != -EBADFD) + return PTR_ERR(tmp); + + /* + * Note: both migrating dir and unknown hash dir need to + * try all of sub-stripes, so we need start search the + * name from stripe 0, but migrating dir is already handled + * inside lmv_locate_target_for_name(), so we only check + * unknown hash type directory here + */ + if (!lmv_is_known_hash_type(lsm)) { + struct lmv_oinfo *oinfo; + + oinfo = &lsm->lsm_md_oinfo[stripe_index]; + + op_data->op_fid1 = oinfo->lmo_fid; + op_data->op_mds = oinfo->lmo_mds; } - } else { - tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1); - if (IS_ERR(tgt)) - return PTR_ERR(tgt); } +try_next_stripe: + /* Send unlink requests to the MDT where the child is located */ + if (likely(!fid_is_zero(&op_data->op_fid2))) + tgt = lmv_find_target(lmv, &op_data->op_fid2); + else if (lsm) + tgt = lmv_get_target(lmv, op_data->op_mds, NULL); + else + tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1); + + if (IS_ERR(tgt)) + return PTR_ERR(tgt); + op_data->op_fsuid = from_kuid(&init_user_ns, current_fsuid()); op_data->op_fsgid = from_kgid(&init_user_ns, current_fsgid()); op_data->op_cap = cfs_curproc_cap_pack(); @@ -2425,9 +2491,28 @@ retry: PFID(&op_data->op_fid1), PFID(&op_data->op_fid2), tgt->ltd_idx); rc = md_unlink(tgt->ltd_exp, op_data, request); - if (rc != 0 && rc != -EREMOTE) + if (rc != 0 && rc != -EREMOTE && rc != -ENOENT) return rc; + /* Try next stripe if it is needed. */ + if (rc == -ENOENT && lsm && lmv_need_try_all_stripes(lsm)) { + struct lmv_oinfo *oinfo; + + stripe_index++; + if (stripe_index >= lsm->lsm_md_stripe_count) + return rc; + + oinfo = &lsm->lsm_md_oinfo[stripe_index]; + + op_data->op_fid1 = oinfo->lmo_fid; + op_data->op_mds = oinfo->lmo_mds; + + ptlrpc_req_finished(*request); + *request = NULL; + + goto try_next_stripe; + } + body = req_capsule_server_get(&(*request)->rq_pill, &RMF_MDT_BODY); if (!body) return -EPROTO; @@ -2463,7 +2548,7 @@ retry: ptlrpc_req_finished(*request); *request = NULL; - goto retry; + goto retry_unlink; } static int lmv_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage) @@ -2683,7 +2768,10 @@ static int lmv_unpack_md_v1(struct obd_export *exp, struct lmv_stripe_md *lsm, lsm->lsm_md_magic = le32_to_cpu(lmm1->lmv_magic); lsm->lsm_md_stripe_count = le32_to_cpu(lmm1->lmv_stripe_count); lsm->lsm_md_master_mdt_index = le32_to_cpu(lmm1->lmv_master_mdt_index); - lsm->lsm_md_hash_type = le32_to_cpu(lmm1->lmv_hash_type); + if (OBD_FAIL_CHECK(OBD_FAIL_UNKNOWN_LMV_STRIPE)) + lsm->lsm_md_hash_type = LMV_HASH_TYPE_UNKNOWN; + else + lsm->lsm_md_hash_type = le32_to_cpu(lmm1->lmv_hash_type); lsm->lsm_md_layout_version = le32_to_cpu(lmm1->lmv_layout_version); fid_le_to_cpu(&lsm->lsm_md_master_fid, &lmm1->lmv_master_fid); cplen = strlcpy(lsm->lsm_md_pool_name, lmm1->lmv_pool_name, -- cgit v0.10.2 From 36c6607c7934c45c0a0e07d4f38fb843122798f2 Mon Sep 17 00:00:00 2001 From: Andriy Skulysh <Andriy_Skulysh@xyratex.com> Date: Tue, 16 Aug 2016 16:19:20 -0400 Subject: staging: lustre: ptlrpc: request gets stuck in UNREGISTERING phase Exit condition from UNREGISTERING phase is releasing of both reply and bulk buffers. Call ptlrpc_unregister_bulk() if ptlrpc_unregister_reply() wasn't completed in async mode before switching to UNREGISTERING phase. Signed-off-by: Andriy Skulysh <Andriy_Skulysh@xyratex.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5259 Xyratex-bug-id: MRP-1960 Reviewed-on: http://review.whamcloud.com/10846 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Ann Koehler <amk@cray.com> Reviewed-by: Liang Zhen <liang.zhen@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index f2e71b4..bae91bd 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -1630,8 +1630,10 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set) req->rq_waiting || req->rq_wait_ctx) { int status; - if (!ptlrpc_unregister_reply(req, 1)) + if (!ptlrpc_unregister_reply(req, 1)) { + ptlrpc_unregister_bulk(req, 1); continue; + } spin_lock(&imp->imp_lock); if (ptlrpc_import_delay_req(imp, req, -- cgit v0.10.2 From c8deb3cb5f9f4fd1239912d3ac1bec3a3d05e73a Mon Sep 17 00:00:00 2001 From: Fan Yong <fan.yong@intel.com> Date: Tue, 16 Aug 2016 16:19:21 -0400 Subject: staging: lustre: lmv: build master LMV EA dynamically build via readdir When creating a striped directory, the master object saves the slave objects (or shards) as internal sub-directories. The sub-directory's name is composed of ${shard_FID}:${shard_idx}. With the name, we can easily to know what the shard is and where it should be. On the other hand, we need to store some information related with the striped directory, such as magic, hash type, shards count, and so on. That is the LMV EA (header). We do NOT store the FID of each shard in the LMV EA. Instead, when we need the shards' FIDs (such as readdir() on client-side), we can build the entrie LMV EA on the MDT (in RAM) by iterating the sub-directory entries that are contained in the master object of the striped directroy. Above mechanism can simplify the striped directory create operation. For very large striped directory, logging the FIDs array in the LMV EA will be trouble. It also simplify the LFSCK for verifying striped directory, because it reduces the inconsistency sources. Another fixing is about the lmv_master_fid in master LMV EA header, it is redundant information, and may become one of the inconsistency sources. So replace it with two __u64 padding fields. Signed-off-by: Fan Yong <fan.yong@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5223 Reviewed-on: http://review.whamcloud.com/10751 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Alex Zhuravlev <alexey.zhuravlev@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 05fe359..17581ba 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -2494,10 +2494,9 @@ struct lmv_mds_md_v1 { * for example migrating or dead. */ __u32 lmv_layout_version; /* Used for directory restriping */ - __u32 lmv_padding; - struct lu_fid lmv_master_fid; /* The FID of the master object, which - * is the namespace-visible dir FID - */ + __u32 lmv_padding1; + __u64 lmv_padding2; + __u64 lmv_padding3; char lmv_pool_name[LOV_MAXPOOLNAME]; /* pool name */ struct lu_fid lmv_stripe_fids[0]; /* FIDs for each stripe */ }; diff --git a/drivers/staging/lustre/lustre/include/lustre_lmv.h b/drivers/staging/lustre/lustre/include/lustre_lmv.h index 1dd3e92..085e596 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lmv.h +++ b/drivers/staging/lustre/lustre/include/lustre_lmv.h @@ -48,7 +48,6 @@ struct lmv_stripe_md { __u32 lsm_md_layout_version; __u32 lsm_md_default_count; __u32 lsm_md_default_index; - struct lu_fid lsm_md_master_fid; char lsm_md_pool_name[LOV_MAXPOOLNAME]; struct lmv_oinfo lsm_md_oinfo[0]; }; @@ -90,23 +89,6 @@ static inline void lmv_free_memmd(struct lmv_stripe_md *lsm) lmv_unpack_md(NULL, &lsm, NULL, 0); } -static inline void lmv1_cpu_to_le(struct lmv_mds_md_v1 *lmv_dst, - const struct lmv_mds_md_v1 *lmv_src) -{ - int i; - - lmv_dst->lmv_magic = cpu_to_le32(lmv_src->lmv_magic); - lmv_dst->lmv_stripe_count = cpu_to_le32(lmv_src->lmv_stripe_count); - lmv_dst->lmv_master_mdt_index = - cpu_to_le32(lmv_src->lmv_master_mdt_index); - lmv_dst->lmv_hash_type = cpu_to_le32(lmv_src->lmv_hash_type); - lmv_dst->lmv_layout_version = cpu_to_le32(lmv_src->lmv_layout_version); - - for (i = 0; i < lmv_src->lmv_stripe_count; i++) - fid_cpu_to_le(&lmv_dst->lmv_stripe_fids[i], - &lmv_src->lmv_stripe_fids[i]); -} - static inline void lmv1_le_to_cpu(struct lmv_mds_md_v1 *lmv_dst, const struct lmv_mds_md_v1 *lmv_src) { @@ -124,18 +106,6 @@ static inline void lmv1_le_to_cpu(struct lmv_mds_md_v1 *lmv_dst, &lmv_src->lmv_stripe_fids[i]); } -static inline void lmv_cpu_to_le(union lmv_mds_md *lmv_dst, - const union lmv_mds_md *lmv_src) -{ - switch (lmv_src->lmv_magic) { - case LMV_MAGIC_V1: - lmv1_cpu_to_le(&lmv_dst->lmv_md_v1, &lmv_src->lmv_md_v1); - break; - default: - break; - } -} - static inline void lmv_le_to_cpu(union lmv_mds_md *lmv_dst, const union lmv_mds_md *lmv_src) { diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index e9f4e9a..b8275e1 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -2773,13 +2773,9 @@ static int lmv_unpack_md_v1(struct obd_export *exp, struct lmv_stripe_md *lsm, else lsm->lsm_md_hash_type = le32_to_cpu(lmm1->lmv_hash_type); lsm->lsm_md_layout_version = le32_to_cpu(lmm1->lmv_layout_version); - fid_le_to_cpu(&lsm->lsm_md_master_fid, &lmm1->lmv_master_fid); cplen = strlcpy(lsm->lsm_md_pool_name, lmm1->lmv_pool_name, sizeof(lsm->lsm_md_pool_name)); - if (!fid_is_sane(&lsm->lsm_md_master_fid)) - return -EPROTO; - if (cplen >= sizeof(lsm->lsm_md_pool_name)) return -E2BIG; diff --git a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c index 31d3326..b428528 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c +++ b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c @@ -1400,6 +1400,55 @@ void lustre_assert_wire_constants(void) LASSERTF(LOV_PATTERN_CMOBD == 0x00000200UL, "found 0x%.8xUL\n", (unsigned)LOV_PATTERN_CMOBD); + /* Checks for struct lmv_mds_md_v1 */ + LASSERTF((int)sizeof(struct lmv_mds_md_v1) == 56, "found %lld\n", + (long long)(int)sizeof(struct lmv_mds_md_v1)); + LASSERTF((int)offsetof(struct lmv_mds_md_v1, lmv_magic) == 0, "found %lld\n", + (long long)(int)offsetof(struct lmv_mds_md_v1, lmv_magic)); + LASSERTF((int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_magic) == 4, "found %lld\n", + (long long)(int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_magic)); + LASSERTF((int)offsetof(struct lmv_mds_md_v1, lmv_stripe_count) == 4, "found %lld\n", + (long long)(int)offsetof(struct lmv_mds_md_v1, lmv_stripe_count)); + LASSERTF((int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_stripe_count) == 4, "found %lld\n", + (long long)(int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_stripe_count)); + LASSERTF((int)offsetof(struct lmv_mds_md_v1, lmv_master_mdt_index) == 8, "found %lld\n", + (long long)(int)offsetof(struct lmv_mds_md_v1, lmv_master_mdt_index)); + LASSERTF((int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_master_mdt_index) == 4, "found %lld\n", + (long long)(int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_master_mdt_index)); + LASSERTF((int)offsetof(struct lmv_mds_md_v1, lmv_hash_type) == 12, "found %lld\n", + (long long)(int)offsetof(struct lmv_mds_md_v1, lmv_hash_type)); + LASSERTF((int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_hash_type) == 4, "found %lld\n", + (long long)(int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_hash_type)); + LASSERTF((int)offsetof(struct lmv_mds_md_v1, lmv_layout_version) == 16, "found %lld\n", + (long long)(int)offsetof(struct lmv_mds_md_v1, lmv_layout_version)); + LASSERTF((int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_layout_version) == 4, "found %lld\n", + (long long)(int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_layout_version)); + LASSERTF((int)offsetof(struct lmv_mds_md_v1, lmv_padding1) == 20, "found %lld\n", + (long long)(int)offsetof(struct lmv_mds_md_v1, lmv_padding1)); + LASSERTF((int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_padding1) == 4, "found %lld\n", + (long long)(int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_padding1)); + LASSERTF((int)offsetof(struct lmv_mds_md_v1, lmv_padding2) == 24, "found %lld\n", + (long long)(int)offsetof(struct lmv_mds_md_v1, lmv_padding2)); + LASSERTF((int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_padding2) == 8, "found %lld\n", + (long long)(int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_padding2)); + LASSERTF((int)offsetof(struct lmv_mds_md_v1, lmv_padding3) == 32, "found %lld\n", + (long long)(int)offsetof(struct lmv_mds_md_v1, lmv_padding3)); + LASSERTF((int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_padding3) == 8, "found %lld\n", + (long long)(int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_padding3)); + LASSERTF((int)offsetof(struct lmv_mds_md_v1, lmv_pool_name[16]) == 56, "found %lld\n", + (long long)(int)offsetof(struct lmv_mds_md_v1, lmv_pool_name[16])); + LASSERTF((int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_pool_name[16]) == 1, "found %lld\n", + (long long)(int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_pool_name[16])); + LASSERTF((int)offsetof(struct lmv_mds_md_v1, lmv_stripe_fids[0]) == 56, "found %lld\n", + (long long)(int)offsetof(struct lmv_mds_md_v1, lmv_stripe_fids[0])); + LASSERTF((int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_stripe_fids[0]) == 16, "found %lld\n", + (long long)(int)sizeof(((struct lmv_mds_md_v1 *)0)->lmv_stripe_fids[0])); + CLASSERT(LMV_MAGIC_V1 == 0x0CD20CD0); + CLASSERT(LMV_MAGIC_STRIPE == 0x0CD40CD0); + CLASSERT(LMV_HASH_TYPE_MASK == 0x0000ffff); + CLASSERT(LMV_HASH_FLAG_MIGRATION == 0x80000000); + CLASSERT(LMV_HASH_FLAG_DEAD == 0x40000000); + /* Checks for struct obd_statfs */ LASSERTF((int)sizeof(struct obd_statfs) == 144, "found %lld\n", (long long)(int)sizeof(struct obd_statfs)); -- cgit v0.10.2 From 3147b268400adeec63b6253534a6176c99b8af80 Mon Sep 17 00:00:00 2001 From: Hongchao Zhang <hongchao.zhang@intel.com> Date: Tue, 16 Aug 2016 16:19:22 -0400 Subject: staging: lustre: osc: Automatically increase the max_dirty_mb When RPC size or the max RPCs in flight is increased, the actual limit might be max_dirty_mb. This patch automatically increases the max_dirty_mb value at connection time and when the related values are tuned manually by proc file system. this patch also changes the unit of "cl_dirty" and "cl_dirty_max" in client_obd from byte to page. Signed-off-by: Li Xi <lixi@ddn.com> Signed-off-by: Hongchao Zhang <hongchao.zhang@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4933 Reviewed-on: http://review.whamcloud.com/10446 Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index e7e03be..e91f65a 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -222,8 +222,8 @@ struct client_obd { struct sptlrpc_flavor cl_flvr_mgc; /* fixed flavor of mgc->mgs */ /* the grant values are protected by loi_list_lock below */ - long cl_dirty; /* all _dirty_ in bytes */ - long cl_dirty_max; /* allowed w/o rpc */ + long cl_dirty_pages; /* all _dirty_ in pahges */ + long cl_dirty_max_pages;/* allowed w/o rpc */ long cl_dirty_transit; /* dirty synchronous */ long cl_avail_grant; /* bytes of credit for ost */ long cl_lost_grant; /* lost credits (trunc) */ @@ -1225,4 +1225,28 @@ static inline int cli_brw_size(struct obd_device *obd) return obd->u.cli.cl_max_pages_per_rpc << PAGE_SHIFT; } +/* + * when RPC size or the max RPCs in flight is increased, the max dirty pages + * of the client should be increased accordingly to avoid sending fragmented + * RPCs over the network when the client runs out of the maximum dirty space + * when so many RPCs are being generated. + */ +static inline void client_adjust_max_dirty(struct client_obd *cli) +{ + /* initializing */ + if (cli->cl_dirty_max_pages <= 0) + cli->cl_dirty_max_pages = + (OSC_MAX_DIRTY_DEFAULT * 1024 * 1024) >> PAGE_SHIFT; + else { + long dirty_max = cli->cl_max_rpcs_in_flight * + cli->cl_max_pages_per_rpc; + + if (dirty_max > cli->cl_dirty_max_pages) + cli->cl_dirty_max_pages = dirty_max; + } + + if (cli->cl_dirty_max_pages > totalram_pages / 8) + cli->cl_dirty_max_pages = totalram_pages / 8; +} + #endif /* __OBD_H */ diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c index ee40006..3c98ce2 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c @@ -299,12 +299,14 @@ int client_obd_setup(struct obd_device *obddev, struct lustre_cfg *lcfg) min_t(unsigned int, LUSTRE_CFG_BUFLEN(lcfg, 2), sizeof(server_uuid))); - cli->cl_dirty = 0; + cli->cl_dirty_pages = 0; cli->cl_avail_grant = 0; - /* FIXME: Should limit this for the sum of all cl_dirty_max. */ - cli->cl_dirty_max = OSC_MAX_DIRTY_DEFAULT * 1024 * 1024; - if (cli->cl_dirty_max >> PAGE_SHIFT > totalram_pages / 8) - cli->cl_dirty_max = totalram_pages << (PAGE_SHIFT - 3); + /* FIXME: Should limit this for the sum of all cl_dirty_max_pages. */ + /* + * cl_dirty_max_pages may be changed at connect time in + * ptlrpc_connect_interpret(). + */ + client_adjust_max_dirty(cli); INIT_LIST_HEAD(&cli->cl_cache_waiters); INIT_LIST_HEAD(&cli->cl_loi_ready_list); INIT_LIST_HEAD(&cli->cl_loi_hp_ready_list); diff --git a/drivers/staging/lustre/lustre/osc/lproc_osc.c b/drivers/staging/lustre/lustre/osc/lproc_osc.c index 7e83d39..9172b78 100644 --- a/drivers/staging/lustre/lustre/osc/lproc_osc.c +++ b/drivers/staging/lustre/lustre/osc/lproc_osc.c @@ -119,6 +119,7 @@ static ssize_t max_rpcs_in_flight_store(struct kobject *kobj, spin_lock(&cli->cl_loi_list_lock); cli->cl_max_rpcs_in_flight = val; + client_adjust_max_dirty(cli); spin_unlock(&cli->cl_loi_list_lock); return count; @@ -136,10 +137,10 @@ static ssize_t max_dirty_mb_show(struct kobject *kobj, int mult; spin_lock(&cli->cl_loi_list_lock); - val = cli->cl_dirty_max; + val = cli->cl_dirty_max_pages; spin_unlock(&cli->cl_loi_list_lock); - mult = 1 << 20; + mult = 1 << (20 - PAGE_SHIFT); return lprocfs_read_frac_helper(buf, PAGE_SIZE, val, mult); } @@ -166,7 +167,7 @@ static ssize_t max_dirty_mb_store(struct kobject *kobj, return -ERANGE; spin_lock(&cli->cl_loi_list_lock); - cli->cl_dirty_max = (u32)(pages_number << PAGE_SHIFT); + cli->cl_dirty_max_pages = pages_number; osc_wake_cache_waiters(cli); spin_unlock(&cli->cl_loi_list_lock); @@ -244,7 +245,7 @@ static ssize_t cur_dirty_bytes_show(struct kobject *kobj, int len; spin_lock(&cli->cl_loi_list_lock); - len = sprintf(buf, "%lu\n", cli->cl_dirty); + len = sprintf(buf, "%lu\n", cli->cl_dirty_pages << PAGE_SHIFT); spin_unlock(&cli->cl_loi_list_lock); return len; @@ -583,6 +584,7 @@ static ssize_t max_pages_per_rpc_store(struct kobject *kobj, } spin_lock(&cli->cl_loi_list_lock); cli->cl_max_pages_per_rpc = val; + client_adjust_max_dirty(cli); spin_unlock(&cli->cl_loi_list_lock); return count; diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index deaf912..c6e37c0 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -1387,7 +1387,7 @@ static int osc_completion(const struct lu_env *env, struct osc_async_page *oap, "dropped: %ld avail: %ld, reserved: %ld, flight: %d }" \ "lru {in list: %d, left: %d, waiters: %d }" fmt, \ __tmp->cl_import->imp_obd->obd_name, \ - __tmp->cl_dirty, __tmp->cl_dirty_max, \ + __tmp->cl_dirty_pages, __tmp->cl_dirty_max_pages, \ atomic_read(&obd_dirty_pages), obd_max_dirty_pages, \ __tmp->cl_lost_grant, __tmp->cl_avail_grant, \ __tmp->cl_reserved_grant, __tmp->cl_w_in_flight, \ @@ -1403,7 +1403,7 @@ static void osc_consume_write_grant(struct client_obd *cli, assert_spin_locked(&cli->cl_loi_list_lock); LASSERT(!(pga->flag & OBD_BRW_FROM_GRANT)); atomic_inc(&obd_dirty_pages); - cli->cl_dirty += PAGE_SIZE; + cli->cl_dirty_pages++; pga->flag |= OBD_BRW_FROM_GRANT; CDEBUG(D_CACHE, "using %lu grant credits for brw %p page %p\n", PAGE_SIZE, pga, pga->pg); @@ -1423,11 +1423,11 @@ static void osc_release_write_grant(struct client_obd *cli, pga->flag &= ~OBD_BRW_FROM_GRANT; atomic_dec(&obd_dirty_pages); - cli->cl_dirty -= PAGE_SIZE; + cli->cl_dirty_pages--; if (pga->flag & OBD_BRW_NOCACHE) { pga->flag &= ~OBD_BRW_NOCACHE; atomic_dec(&obd_dirty_transit_pages); - cli->cl_dirty_transit -= PAGE_SIZE; + cli->cl_dirty_transit--; } } @@ -1496,7 +1496,7 @@ static void osc_free_grant(struct client_obd *cli, unsigned int nr_pages, spin_lock(&cli->cl_loi_list_lock); atomic_sub(nr_pages, &obd_dirty_pages); - cli->cl_dirty -= nr_pages << PAGE_SHIFT; + cli->cl_dirty_pages -= nr_pages; cli->cl_lost_grant += lost_grant; if (cli->cl_avail_grant < grant && cli->cl_lost_grant >= grant) { /* borrow some grant from truncate to avoid the case that @@ -1509,7 +1509,7 @@ static void osc_free_grant(struct client_obd *cli, unsigned int nr_pages, spin_unlock(&cli->cl_loi_list_lock); CDEBUG(D_CACHE, "lost %u grant: %lu avail: %lu dirty: %lu\n", lost_grant, cli->cl_lost_grant, - cli->cl_avail_grant, cli->cl_dirty); + cli->cl_avail_grant, cli->cl_dirty_pages << PAGE_SHIFT); } /** @@ -1539,11 +1539,11 @@ static int osc_enter_cache_try(struct client_obd *cli, if (rc < 0) return 0; - if (cli->cl_dirty + PAGE_SIZE <= cli->cl_dirty_max && + if (cli->cl_dirty_pages <= cli->cl_dirty_max_pages && atomic_read(&obd_dirty_pages) + 1 <= obd_max_dirty_pages) { osc_consume_write_grant(cli, &oap->oap_brw_page); if (transient) { - cli->cl_dirty_transit += PAGE_SIZE; + cli->cl_dirty_transit++; atomic_inc(&obd_dirty_transit_pages); oap->oap_brw_flags |= OBD_BRW_NOCACHE; } @@ -1590,8 +1590,8 @@ static int osc_enter_cache(const struct lu_env *env, struct client_obd *cli, * of queued writes and create a discontiguous rpc stream */ if (OBD_FAIL_CHECK(OBD_FAIL_OSC_NO_GRANT) || - cli->cl_dirty_max < PAGE_SIZE || - cli->cl_ar.ar_force_sync || loi->loi_ar.ar_force_sync) { + !cli->cl_dirty_max_pages || cli->cl_ar.ar_force_sync || + loi->loi_ar.ar_force_sync) { rc = -EDQUOT; goto out; } @@ -1612,7 +1612,7 @@ static int osc_enter_cache(const struct lu_env *env, struct client_obd *cli, init_waitqueue_head(&ocw.ocw_waitq); ocw.ocw_oap = oap; ocw.ocw_grant = bytes; - while (cli->cl_dirty > 0 || cli->cl_w_in_flight > 0) { + while (cli->cl_dirty_pages > 0 || cli->cl_w_in_flight > 0) { list_add_tail(&ocw.ocw_entry, &cli->cl_cache_waiters); ocw.ocw_rc = 0; spin_unlock(&cli->cl_loi_list_lock); @@ -1667,11 +1667,11 @@ void osc_wake_cache_waiters(struct client_obd *cli) ocw->ocw_rc = -EDQUOT; /* we can't dirty more */ - if ((cli->cl_dirty + PAGE_SIZE > cli->cl_dirty_max) || + if ((cli->cl_dirty_pages > cli->cl_dirty_max_pages) || (atomic_read(&obd_dirty_pages) + 1 > obd_max_dirty_pages)) { CDEBUG(D_CACHE, "no dirty room: dirty: %ld osc max %ld, sys max %d\n", - cli->cl_dirty, - cli->cl_dirty_max, obd_max_dirty_pages); + cli->cl_dirty_pages, cli->cl_dirty_max_pages, + obd_max_dirty_pages); goto wakeup; } diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 90c8416..c618337 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -801,11 +801,12 @@ static void osc_announce_cached(struct client_obd *cli, struct obdo *oa, oa->o_valid |= bits; spin_lock(&cli->cl_loi_list_lock); - oa->o_dirty = cli->cl_dirty; - if (unlikely(cli->cl_dirty - cli->cl_dirty_transit > - cli->cl_dirty_max)) { + oa->o_dirty = cli->cl_dirty_pages << PAGE_SHIFT; + if (unlikely(cli->cl_dirty_pages - cli->cl_dirty_transit > + cli->cl_dirty_max_pages)) { CERROR("dirty %lu - %lu > dirty_max %lu\n", - cli->cl_dirty, cli->cl_dirty_transit, cli->cl_dirty_max); + cli->cl_dirty_pages, cli->cl_dirty_transit, + cli->cl_dirty_max_pages); oa->o_undirty = 0; } else if (unlikely(atomic_read(&obd_dirty_pages) - atomic_read(&obd_dirty_transit_pages) > @@ -820,15 +821,17 @@ static void osc_announce_cached(struct client_obd *cli, struct obdo *oa, atomic_read(&obd_dirty_transit_pages), obd_max_dirty_pages); oa->o_undirty = 0; - } else if (unlikely(cli->cl_dirty_max - cli->cl_dirty > 0x7fffffff)) { + } else if (unlikely(cli->cl_dirty_max_pages - cli->cl_dirty_pages > + 0x7fffffff)) { CERROR("dirty %lu - dirty_max %lu too big???\n", - cli->cl_dirty, cli->cl_dirty_max); + cli->cl_dirty_pages, cli->cl_dirty_max_pages); oa->o_undirty = 0; } else { long max_in_flight = (cli->cl_max_pages_per_rpc << PAGE_SHIFT)* (cli->cl_max_rpcs_in_flight + 1); - oa->o_undirty = max(cli->cl_dirty_max, max_in_flight); + oa->o_undirty = max(cli->cl_dirty_max_pages << PAGE_SHIFT, + max_in_flight); } oa->o_grant = cli->cl_avail_grant + cli->cl_reserved_grant; oa->o_dropped = cli->cl_lost_grant; @@ -1028,22 +1031,24 @@ static void osc_init_grant(struct client_obd *cli, struct obd_connect_data *ocd) { /* * ocd_grant is the total grant amount we're expect to hold: if we've - * been evicted, it's the new avail_grant amount, cl_dirty will drop - * to 0 as inflight RPCs fail out; otherwise, it's avail_grant + dirty. + * been evicted, it's the new avail_grant amount, cl_dirty_pages will + * drop to 0 as inflight RPCs fail out; otherwise, it's avail_grant + + * dirty. * * race is tolerable here: if we're evicted, but imp_state already - * left EVICTED state, then cl_dirty must be 0 already. + * left EVICTED state, then cl_dirty_pages must be 0 already. */ spin_lock(&cli->cl_loi_list_lock); if (cli->cl_import->imp_state == LUSTRE_IMP_EVICTED) cli->cl_avail_grant = ocd->ocd_grant; else - cli->cl_avail_grant = ocd->ocd_grant - cli->cl_dirty; + cli->cl_avail_grant = ocd->ocd_grant - + (cli->cl_dirty_pages << PAGE_SHIFT); if (cli->cl_avail_grant < 0) { CWARN("%s: available grant < 0: avail/ocd/dirty %ld/%u/%ld\n", cli->cl_import->imp_obd->obd_name, cli->cl_avail_grant, - ocd->ocd_grant, cli->cl_dirty); + ocd->ocd_grant, cli->cl_dirty_pages << PAGE_SHIFT); /* workaround for servers which do not have the patch from * LU-2679 */ @@ -3014,8 +3019,9 @@ static int osc_reconnect(const struct lu_env *env, long lost_grant; spin_lock(&cli->cl_loi_list_lock); - data->ocd_grant = (cli->cl_avail_grant + cli->cl_dirty) ?: - 2 * cli_brw_size(obd); + data->ocd_grant = (cli->cl_avail_grant + + (cli->cl_dirty_pages << PAGE_SHIFT)) ?: + 2 * cli_brw_size(obd); lost_grant = cli->cl_lost_grant; cli->cl_lost_grant = 0; spin_unlock(&cli->cl_loi_list_lock); diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c index af8ffbc..c0122ef 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/import.c +++ b/drivers/staging/lustre/lustre/ptlrpc/import.c @@ -1132,6 +1132,7 @@ finish: LASSERT((cli->cl_max_pages_per_rpc <= PTLRPC_MAX_BRW_PAGES) && (cli->cl_max_pages_per_rpc > 0)); + client_adjust_max_dirty(cli); } out: -- cgit v0.10.2 From a5c954eff652359aeecb4d822e8e8cef86abcb9b Mon Sep 17 00:00:00 2001 From: James Simmons <jsimmons@infradead.org> Date: Tue, 16 Aug 2016 16:19:23 -0400 Subject: staging: lustre: include: fix one off errors in lustre_id.h During inspection of another patch Dan Carpenter noticed some one off errors in lustre_id.h. Fix the condition test for OBIF_MAX_OID. Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 17581ba..9545451 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -659,7 +659,7 @@ static inline void ostid_set_id(struct ost_id *oi, __u64 oid) oi->oi_fid.f_oid = oid; oi->oi_fid.f_ver = oid >> 48; } else { - if (oid > OBIF_MAX_OID) { + if (oid >= OBIF_MAX_OID) { CERROR("Bad %llu to set " DOSTID "\n", oid, POSTID(oi)); return; } @@ -684,7 +684,7 @@ static inline int fid_set_id(struct lu_fid *fid, __u64 oid) fid->f_oid = oid; fid->f_ver = oid >> 48; } else { - if (oid > OBIF_MAX_OID) { + if (oid >= OBIF_MAX_OID) { CERROR("Too large OID %#llx to set REG "DFID"\n", (unsigned long long)oid, PFID(fid)); return -EBADF; -- cgit v0.10.2 From 6a42e615a28bad49f2e04829486e94190c066390 Mon Sep 17 00:00:00 2001 From: James Simmons <jsimmons@infradead.org> Date: Tue, 16 Aug 2016 16:19:24 -0400 Subject: staging: lustre: llite: remove assert for acl refcount The purpose of this asssert to was to ensure lustre was properly managing its posix_acl access. This test is invalid due to the VFS layer also taking references on the posix_acl. In reality their is no simple way to detect this class of mistakes. Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index da00fbd..64c8a2b 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -1247,7 +1247,6 @@ void ll_clear_inode(struct inode *inode) #ifdef CONFIG_FS_POSIX_ACL if (lli->lli_posix_acl) { - LASSERT(atomic_read(&lli->lli_posix_acl->a_refcount) == 1); posix_acl_release(lli->lli_posix_acl); lli->lli_posix_acl = NULL; } -- cgit v0.10.2 From 8015e1808718ffd3d8bb983d7148f5782db297f2 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Tue, 16 Aug 2016 16:19:25 -0400 Subject: staging: lustre: obd: validate open handle cookies Add a const void *h_owner member to struct portals_handle. Add a const void *owner parameter to class_handle2object() which must be matched by the h_owner member of the handle in addition to the cookie. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3233 Reviewed-on: http://review.whamcloud.com/6938 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Fan Yong <fan.yong@intel.com> Reviewed-by: Mike Pershin <mike.pershin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre_handles.h b/drivers/staging/lustre/lustre/include/lustre_handles.h index 1a63a6b..bc1dd46 100644 --- a/drivers/staging/lustre/lustre/include/lustre_handles.h +++ b/drivers/staging/lustre/lustre/include/lustre_handles.h @@ -66,6 +66,7 @@ struct portals_handle_ops { struct portals_handle { struct list_head h_link; __u64 h_cookie; + const void *h_owner; struct portals_handle_ops *h_ops; /* newly added fields to handle the RCU issue. -jxiong */ @@ -83,7 +84,7 @@ struct portals_handle { void class_handle_hash(struct portals_handle *, struct portals_handle_ops *ops); void class_handle_unhash(struct portals_handle *); -void *class_handle2object(__u64 cookie); +void *class_handle2object(__u64 cookie, const void *owner); void class_handle_free_cb(struct rcu_head *rcu); int class_handle_init(void); void class_handle_cleanup(void); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c index a91cdb4..7a34caf 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c @@ -542,7 +542,7 @@ struct ldlm_lock *__ldlm_handle2lock(const struct lustre_handle *handle, LASSERT(handle); - lock = class_handle2object(handle->cookie); + lock = class_handle2object(handle->cookie, NULL); if (!lock) return NULL; diff --git a/drivers/staging/lustre/lustre/obdclass/genops.c b/drivers/staging/lustre/lustre/obdclass/genops.c index be25434..a739eb1 100644 --- a/drivers/staging/lustre/lustre/obdclass/genops.c +++ b/drivers/staging/lustre/lustre/obdclass/genops.c @@ -618,7 +618,7 @@ struct obd_export *class_conn2export(struct lustre_handle *conn) } CDEBUG(D_INFO, "looking for export cookie %#llx\n", conn->cookie); - export = class_handle2object(conn->cookie); + export = class_handle2object(conn->cookie, NULL); return export; } EXPORT_SYMBOL(class_conn2export); diff --git a/drivers/staging/lustre/lustre/obdclass/lustre_handles.c b/drivers/staging/lustre/lustre/obdclass/lustre_handles.c index 082f530..7ca68ae 100644 --- a/drivers/staging/lustre/lustre/obdclass/lustre_handles.c +++ b/drivers/staging/lustre/lustre/obdclass/lustre_handles.c @@ -130,7 +130,7 @@ void class_handle_unhash(struct portals_handle *h) } EXPORT_SYMBOL(class_handle_unhash); -void *class_handle2object(__u64 cookie) +void *class_handle2object(__u64 cookie, const void *owner) { struct handle_bucket *bucket; struct portals_handle *h; @@ -145,7 +145,7 @@ void *class_handle2object(__u64 cookie) rcu_read_lock(); list_for_each_entry_rcu(h, &bucket->head, h_link) { - if (h->h_cookie != cookie) + if (h->h_cookie != cookie || h->h_owner != owner) continue; spin_lock(&h->h_lock); -- cgit v0.10.2 From a043a1020f26d400c8f5d195308466813df969a7 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin <dmitry.eremin@intel.com> Date: Tue, 16 Aug 2016 16:19:26 -0400 Subject: staging: lustre: lmv: build error with gcc 4.7.0 20110509 Fixed comparison between signed and unsigned indexes. Signed-off-by: Dmitry Eremin <dmitry.eremin@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3775 Reviewed-on: http://review.whamcloud.com/7382 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index b8275e1..3e41f49 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -130,12 +130,12 @@ static void lmv_activate_target(struct lmv_obd *lmv, * -ENOTCONN: The UUID is found, but the target connection is bad (!) * -EBADF : The UUID is found, but the OBD of the wrong type (!) */ -static int lmv_set_mdc_active(struct lmv_obd *lmv, struct obd_uuid *uuid, +static int lmv_set_mdc_active(struct lmv_obd *lmv, const struct obd_uuid *uuid, int activate) { struct lmv_tgt_desc *uninitialized_var(tgt); struct obd_device *obd; - int i; + u32 i; int rc = 0; CDEBUG(D_INFO, "Searching in lmv %p for uuid %s (activate=%d)\n", @@ -307,7 +307,7 @@ static int lmv_connect(const struct lu_env *env, static void lmv_set_timeouts(struct obd_device *obd) { struct lmv_obd *lmv; - int i; + u32 i; lmv = &obd->u.lmv; if (lmv->server_timeout == 0) @@ -333,7 +333,7 @@ static int lmv_init_ea_size(struct obd_export *exp, int easize, { struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; - int i; + u32 i; int rc = 0; int change = 0; @@ -578,7 +578,7 @@ int lmv_check_connect(struct obd_device *obd) { struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt; - int i; + u32 i; int rc; int easize; @@ -693,7 +693,7 @@ static int lmv_disconnect(struct obd_export *exp) struct obd_device *obd = class_exp2obd(exp); struct lmv_obd *lmv = &obd->u.lmv; int rc; - int i; + u32 i; if (!lmv->tgts) goto out_local; @@ -822,7 +822,7 @@ static int lmv_hsm_req_count(struct lmv_obd *lmv, const struct hsm_user_request *hur, const struct lmv_tgt_desc *tgt_mds) { - int i, nr = 0; + u32 i, nr = 0; struct lmv_tgt_desc *curr_tgt; /* count how many requests must be sent to the given target */ @@ -963,10 +963,10 @@ static int lmv_iocontrol(unsigned int cmd, struct obd_export *exp, struct obd_device *obddev = class_exp2obd(exp); struct lmv_obd *lmv = &obddev->u.lmv; struct lmv_tgt_desc *tgt = NULL; - int i = 0; + u32 i = 0; int rc = 0; int set = 0; - int count = lmv->desc.ld_tgt_count; + u32 count = lmv->desc.ld_tgt_count; if (count == 0) return -ENOTTY; @@ -1444,7 +1444,7 @@ static int lmv_statfs(const struct lu_env *env, struct obd_export *exp, struct lmv_obd *lmv = &obd->u.lmv; struct obd_statfs *temp; int rc = 0; - int i; + u32 i; rc = lmv_check_connect(obd); if (rc) @@ -1586,7 +1586,7 @@ static int lmv_null_inode(struct obd_export *exp, const struct lu_fid *fid) { struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; - int i; + u32 i; int rc; rc = lmv_check_connect(obd); @@ -1615,7 +1615,7 @@ static int lmv_find_cbdata(struct obd_export *exp, const struct lu_fid *fid, struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; int tgt; - int i; + u32 i; int rc; rc = lmv_check_connect(obd); @@ -2923,7 +2923,7 @@ static int lmv_cancel_unused(struct obd_export *exp, const struct lu_fid *fid, struct lmv_obd *lmv = &obd->u.lmv; int rc = 0; int err; - int i; + u32 i; LASSERT(fid); @@ -2966,7 +2966,7 @@ static enum ldlm_mode lmv_lock_match(struct obd_export *exp, __u64 flags, struct lmv_obd *lmv = &obd->u.lmv; enum ldlm_mode rc; int tgt; - int i; + u32 i; CDEBUG(D_INODE, "Lock match for "DFID"\n", PFID(fid)); @@ -3125,8 +3125,9 @@ static int lmv_quotactl(struct obd_device *unused, struct obd_export *exp, struct obd_device *obd = class_exp2obd(exp); struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt = lmv->tgts[0]; - int rc = 0, i; + int rc = 0; __u64 curspace = 0, curinodes = 0; + u32 i; if (!tgt || !tgt->ltd_exp || !tgt->ltd_active || !lmv->desc.ld_tgt_count) { @@ -3169,7 +3170,8 @@ static int lmv_quotacheck(struct obd_device *unused, struct obd_export *exp, struct obd_device *obd = class_exp2obd(exp); struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt; - int i, rc = 0; + int rc = 0; + u32 i; for (i = 0; i < lmv->desc.ld_tgt_count; i++) { int err; -- cgit v0.10.2 From 049e215e0e2b9855c4ccfd9d559be127355b570f Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Tue, 16 Aug 2016 16:19:27 -0400 Subject: staging: lustre: obd: implement md_read_page This patch adds md_read_page which is a new more flexiable api that will replace md_readpage. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/10761 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4906 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index e91f65a..92eebff 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -830,6 +830,15 @@ struct md_op_data { struct lustre_handle op_lease_handle; }; +#define op_stripe_offset op_ioepoch +#define op_max_pages op_valid + +struct md_callback { + int (*md_blocking_ast)(struct ldlm_lock *lock, + struct ldlm_lock_desc *desc, + void *data, int flag); +}; + enum op_cli_flags { CLI_SET_MEA = 1 << 0, CLI_RM_ENTRY = 1 << 1, @@ -1039,7 +1048,9 @@ struct md_ops { struct ptlrpc_request **); int (*readpage)(struct obd_export *, struct md_op_data *, struct page **, struct ptlrpc_request **); - + int (*read_page)(struct obd_export *, struct md_op_data *, + struct md_callback *cb_op, __u64 hash_offset, + struct page **ppage); int (*unlink)(struct obd_export *, struct md_op_data *, struct ptlrpc_request **); diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index 69b628b..daca5a0 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -1535,6 +1535,21 @@ static inline int md_readpage(struct obd_export *exp, struct md_op_data *opdata, return rc; } +static inline int md_read_page(struct obd_export *exp, + struct md_op_data *op_data, + struct md_callback *cb_op, + __u64 hash_offset, + struct page **ppage) +{ + int rc; + + EXP_CHECK_MD_OP(exp, read_page); + EXP_MD_COUNTER_INCREMENT(exp, read_page); + rc = MDP(exp->exp_obd, read_page)(exp, op_data, cb_op, hash_offset, + ppage); + return rc; +} + static inline int md_unlink(struct obd_export *exp, struct md_op_data *op_data, struct ptlrpc_request **request) { -- cgit v0.10.2 From bce1bbf4b8903d557fd01dc1f7e01fab71b306d1 Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Tue, 16 Aug 2016 16:19:28 -0400 Subject: staging: lustre: llite: set op_max_pages Cache the maximum allowed pages supported by the llite layer. This value will be used in the mdc and lmv layer. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/7043 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3531 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 9c7fa8f..ed09015 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -649,6 +649,7 @@ static int ll_readdir(struct file *filp, struct dir_context *ctx) } } } + op_data->op_max_pages = sbi->ll_md_brw_pages; ctx->pos = pos; rc = ll_dir_read(inode, &pos, op_data, ctx); pos = ctx->pos; diff --git a/drivers/staging/lustre/lustre/llite/llite_nfs.c b/drivers/staging/lustre/lustre/llite/llite_nfs.c index 2b65240..1e156dc 100644 --- a/drivers/staging/lustre/lustre/llite/llite_nfs.c +++ b/drivers/staging/lustre/lustre/llite/llite_nfs.c @@ -276,6 +276,7 @@ static int ll_get_name(struct dentry *dentry, char *name, goto out; } + op_data->op_max_pages = ll_i2sbi(dir)->ll_md_brw_pages; inode_lock(dir); rc = ll_dir_read(dir, &pos, op_data, &lgd.ctx); inode_unlock(dir); diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c index 46b8faf..454c33e 100644 --- a/drivers/staging/lustre/lustre/llite/statahead.c +++ b/drivers/staging/lustre/lustre/llite/statahead.c @@ -1052,6 +1052,8 @@ static int ll_statahead_thread(void *arg) if (IS_ERR(op_data)) return PTR_ERR(op_data); + op_data->op_max_pages = ll_i2sbi(dir)->ll_md_brw_pages; + if (sbi->ll_flags & LL_SBI_AGL_ENABLED) ll_start_agl(parent, sai); @@ -1355,6 +1357,10 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry) LUSTRE_OPC_ANY, dir); if (IS_ERR(op_data)) return PTR_ERR(op_data); + /** + * FIXME choose the start offset of the readdir + */ + op_data->op_max_pages = ll_i2sbi(dir)->ll_md_brw_pages; ll_dir_chain_init(&chain); page = ll_get_dir_page(dir, op_data, pos, &chain); -- cgit v0.10.2 From e426f0d24e1c92f54098758cc83eb16989c48855 Mon Sep 17 00:00:00 2001 From: Doug Oucharek <doug.s.oucharek@intel.com> Date: Tue, 16 Aug 2016 16:19:29 -0400 Subject: staging: lustre: lnet: Do not drop message when shutting down LNet There is a case in lnet_parse() where we discover that LNet is shutting down but we continue to use the NI when we drop the message and end up calling ko2iblnd_check_send_locked() which tries to allocate from the Tx pool which has been cleaned up already. This triggers a NULL pointer dereference. This fix just returns from lnet_parse() when we disover LNet is shutting down. Signed-off-by: Doug Oucharek <doug.s.oucharek@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-8106 Reviewed-on: http://review.whamcloud.com/19993 Reviewed-by: James Simmons <uja.ornl@yahoo.com> Reviewed-by: Liang Zhen <liang.zhen@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lnet/lnet/lib-move.c b/drivers/staging/lustre/lnet/lnet/lib-move.c index 6a3f2e1..5598fa8 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-move.c +++ b/drivers/staging/lustre/lnet/lnet/lib-move.c @@ -2002,6 +2002,9 @@ lnet_parse(lnet_ni_t *ni, lnet_hdr_t *hdr, lnet_nid_t from_nid, libcfs_nid2str(from_nid), libcfs_nid2str(src_nid), lnet_msgtyp2str(type), rc); lnet_msg_free(msg); + if (rc == -ESHUTDOWN) + /* We are shutting down. Don't do anything more */ + return 0; goto drop; } -- cgit v0.10.2 From af96bab11b4cdc009fa78e55c328a0baccd7db90 Mon Sep 17 00:00:00 2001 From: Doug Oucharek <doug.s.oucharek@intel.com> Date: Tue, 16 Aug 2016 16:19:30 -0400 Subject: staging: lustre: lnet: Correct position of lnet_ni_decref() In fix http://review.whamcloud.com/#/c/19614/, the call to lnet_ni_decref() should have followed the routines which are using the NI. This patch correct that. Signed-off-by: Doug Oucharek <doug.s.oucharek@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-8022 Reviewed-on: http://review.whamcloud.com/21001 Reviewed-by: James Simmons <uja.ornl@yahoo.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Dmitry Eremin <dmitry.eremin@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index 9eb1db6..19c90fc 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -2526,9 +2526,9 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob) failed: if (ni) { - lnet_ni_decref(ni); rej.ibr_cp.ibcp_queue_depth = kiblnd_msg_queue_size(version, ni); rej.ibr_cp.ibcp_max_frags = kiblnd_rdma_frags(version, ni); + lnet_ni_decref(ni); } rej.ibr_version = version; -- cgit v0.10.2 From d04c0943c1d3bb4b8d8b8814c717c7a7059b8434 Mon Sep 17 00:00:00 2001 From: Alexander Boyko <alexander.boyko@seagate.com> Date: Tue, 16 Aug 2016 16:19:31 -0400 Subject: staging: lustre: lnet: make connection more stable with packet loss IB network may lose last connection handshake packet. This problem isn't Lustre specific and described at https://oss.oracle.com/pipermail/rds-devel/2007-December/000271.html for example. Solution is to make conection established if any packet is received for it. Signed-off-by: Alexander Boyko <alexander.boyko@seagate.com> Signed-off-by: Alexey Lyashkov <alexey.lyashkov@seagate.com> Seagate-bug-id: MRP-2883 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-8303 Reviewed-on: http://review.whamcloud.com/20874 Reviewed-by: Doug Oucharek <doug.s.oucharek@intel.com> Reviewed-by: Alexander Zarochentsev <alexander.zarochentsev@seagate.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index 19c90fc..6cd78ea 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -3419,6 +3419,12 @@ kiblnd_qp_event(struct ib_event *event, void *arg) case IB_EVENT_COMM_EST: CDEBUG(D_NET, "%s established\n", libcfs_nid2str(conn->ibc_peer->ibp_nid)); + /* + * We received a packet but connection isn't established + * probably handshake packet was lost, so free to + * force make connection established + */ + rdma_notify(conn->ibc_cmid, IB_EVENT_COMM_EST); return; default: -- cgit v0.10.2 From ba5301428e4536fdb8844507c62a1c7289556525 Mon Sep 17 00:00:00 2001 From: Liang Zhen <liang.zhen@intel.com> Date: Tue, 16 Aug 2016 16:19:32 -0400 Subject: staging: lustre: lnet: lock improvement for ko2iblnd kiblnd_check_sends() takes conn::ibc_lock at the begin and release this lock at the end, this is inefficient because most use-case needs to explicitly release ibc_lock before caling this function. This patches changes it to kiblnd_check_sends_locked() and avoid unnecessary lock dances. Signed-off-by: Liang Zhen <liang.zhen@intel.com> Signed-off-by: Doug Oucharek <doug.s.oucharek@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-7099 Reviewed-on: http://review.whamcloud.com/20322 Reviewed-by: Amir Shehata <amir.shehata@intel.com> Reviewed-by: Dmitry Eremin <dmitry.eremin@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index 6cd78ea..6d1b14a 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -38,7 +38,6 @@ static void kiblnd_peer_alive(struct kib_peer *peer); static void kiblnd_peer_connect_failed(struct kib_peer *peer, int active, int error); -static void kiblnd_check_sends(struct kib_conn *conn); static void kiblnd_init_tx_msg(lnet_ni_t *ni, struct kib_tx *tx, int type, int body_nob); static int kiblnd_init_rdma(struct kib_conn *conn, struct kib_tx *tx, int type, @@ -46,6 +45,7 @@ static int kiblnd_init_rdma(struct kib_conn *conn, struct kib_tx *tx, int type, static void kiblnd_queue_tx_locked(struct kib_tx *tx, struct kib_conn *conn); static void kiblnd_queue_tx(struct kib_tx *tx, struct kib_conn *conn); static void kiblnd_unmap_tx(lnet_ni_t *ni, struct kib_tx *tx); +static void kiblnd_check_sends_locked(struct kib_conn *conn); static void kiblnd_tx_done(lnet_ni_t *ni, struct kib_tx *tx) @@ -211,9 +211,9 @@ kiblnd_post_rx(struct kib_rx *rx, int credit) conn->ibc_outstanding_credits++; else conn->ibc_reserved_credits++; + kiblnd_check_sends_locked(conn); spin_unlock(&conn->ibc_lock); - kiblnd_check_sends(conn); out: kiblnd_conn_decref(conn); return rc; @@ -344,8 +344,8 @@ kiblnd_handle_rx(struct kib_rx *rx) !IBLND_OOB_CAPABLE(conn->ibc_version)) /* v1 only */ conn->ibc_outstanding_credits++; + kiblnd_check_sends_locked(conn); spin_unlock(&conn->ibc_lock); - kiblnd_check_sends(conn); } switch (msg->ibm_type) { @@ -800,7 +800,7 @@ kiblnd_post_tx_locked(struct kib_conn *conn, struct kib_tx *tx, int credit) conn->ibc_noops_posted == IBLND_OOB_MSGS(ver)))) { /* * OK to drop when posted enough NOOPs, since - * kiblnd_check_sends will queue NOOP again when + * kiblnd_check_sends_locked will queue NOOP again when * posted NOOPs complete */ spin_unlock(&conn->ibc_lock); @@ -905,7 +905,7 @@ kiblnd_post_tx_locked(struct kib_conn *conn, struct kib_tx *tx, int credit) } static void -kiblnd_check_sends(struct kib_conn *conn) +kiblnd_check_sends_locked(struct kib_conn *conn) { int ver = conn->ibc_version; lnet_ni_t *ni = conn->ibc_peer->ibp_ni; @@ -918,8 +918,6 @@ kiblnd_check_sends(struct kib_conn *conn) return; } - spin_lock(&conn->ibc_lock); - LASSERT(conn->ibc_nsends_posted <= kiblnd_concurrent_sends(ver, ni)); LASSERT(!IBLND_OOB_CAPABLE(ver) || conn->ibc_noops_posted <= IBLND_OOB_MSGS(ver)); @@ -969,8 +967,6 @@ kiblnd_check_sends(struct kib_conn *conn) if (kiblnd_post_tx_locked(conn, tx, credit)) break; } - - spin_unlock(&conn->ibc_lock); } static void @@ -1016,16 +1012,11 @@ kiblnd_tx_complete(struct kib_tx *tx, int status) if (idle) list_del(&tx->tx_list); - kiblnd_conn_addref(conn); /* 1 ref for me.... */ - + kiblnd_check_sends_locked(conn); spin_unlock(&conn->ibc_lock); if (idle) kiblnd_tx_done(conn->ibc_peer->ibp_ni, tx); - - kiblnd_check_sends(conn); - - kiblnd_conn_decref(conn); /* ...until here */ } static void @@ -1204,9 +1195,8 @@ kiblnd_queue_tx(struct kib_tx *tx, struct kib_conn *conn) { spin_lock(&conn->ibc_lock); kiblnd_queue_tx_locked(tx, conn); + kiblnd_check_sends_locked(conn); spin_unlock(&conn->ibc_lock); - - kiblnd_check_sends(conn); } static int kiblnd_resolve_addr(struct rdma_cm_id *cmid, @@ -2183,14 +2173,11 @@ kiblnd_connreq_done(struct kib_conn *conn, int status) return; } - /** - * refcount taken by cmid is not reliable after I released the glock - * because this connection is visible to other threads now, another - * thread can find and close this connection right after I released - * the glock, if kiblnd_cm_callback for RDMA_CM_EVENT_DISCONNECTED is - * called, it can release the connection refcount taken by cmid. - * It means the connection could be destroyed before I finish my - * operations on it. + /* + * +1 ref for myself, this connection is visible to other threads + * now, refcount of peer:ibp_conns can be released by connection + * close from either a different thread, or the calling of + * kiblnd_check_sends_locked() below. See bz21911 for details. */ kiblnd_conn_addref(conn); write_unlock_irqrestore(&kiblnd_data.kib_global_lock, flags); @@ -2202,10 +2189,9 @@ kiblnd_connreq_done(struct kib_conn *conn, int status) kiblnd_queue_tx_locked(tx, conn); } + kiblnd_check_sends_locked(conn); spin_unlock(&conn->ibc_lock); - kiblnd_check_sends(conn); - /* schedule blocked rxs */ kiblnd_handle_early_rxs(conn); @@ -3233,7 +3219,11 @@ kiblnd_check_conns(int idx) */ list_for_each_entry_safe(conn, temp, &checksends, ibc_connd_list) { list_del(&conn->ibc_connd_list); - kiblnd_check_sends(conn); + + spin_lock(&conn->ibc_lock); + kiblnd_check_sends_locked(conn); + spin_unlock(&conn->ibc_lock); + kiblnd_conn_decref(conn); } } -- cgit v0.10.2 From 72e62b6c7cebf894738a8e49bb62492717bde4f5 Mon Sep 17 00:00:00 2001 From: Doug Oucharek <doug.s.oucharek@intel.com> Date: Tue, 16 Aug 2016 16:19:33 -0400 Subject: staging: lustre: lnet: Stop Infinite CON RACE Condition In current code, when a CON RACE occurs, the passive side will let the node with the higher NID value win the race. We have a field case where a node can have a "stuck" connection which never goes away and is the trigger of a never-ending loop of re-connections. This patch introduces a counter to how many times a connection in a connecting state has been the cause of a CON RACE rejection. After 20 times (constant MAX_CONN_RACES_BEFORE_ABORT), we assume the connection is stuck and let the other side (with lower NID) win. Signed-off-by: Doug Oucharek <doug.s.oucharek@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-7646 Reviewed-on: http://review.whamcloud.com/19430 Reviewed-by: Amir Shehata <amir.shehata@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h index 078a0c3..fbc4f68 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h @@ -582,6 +582,8 @@ struct kib_peer { unsigned short ibp_connecting; /* reconnect this peer later */ unsigned short ibp_reconnecting:1; + /* counter of how many times we triggered a conn race */ + unsigned char ibp_races; /* # consecutive reconnection attempts to this peer */ unsigned int ibp_reconnected; /* errno on closing this peer */ diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index 6d1b14a..430ff85 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -36,6 +36,8 @@ #include "o2iblnd.h" +#define MAX_CONN_RACES_BEFORE_ABORT 20 + static void kiblnd_peer_alive(struct kib_peer *peer); static void kiblnd_peer_connect_failed(struct kib_peer *peer, int active, int error); static void kiblnd_init_tx_msg(lnet_ni_t *ni, struct kib_tx *tx, @@ -2405,23 +2407,37 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob) goto failed; } - /* tie-break connection race in favour of the higher NID */ + /* + * Tie-break connection race in favour of the higher NID. + * If we keep running into a race condition multiple times, + * we have to assume that the connection attempt with the + * higher NID is stuck in a connecting state and will never + * recover. As such, we pass through this if-block and let + * the lower NID connection win so we can move forward. + */ if (peer2->ibp_connecting && - nid < ni->ni_nid) { + nid < ni->ni_nid && peer2->ibp_races < + MAX_CONN_RACES_BEFORE_ABORT) { + peer2->ibp_races++; write_unlock_irqrestore(g_lock, flags); - CWARN("Conn race %s\n", libcfs_nid2str(peer2->ibp_nid)); + CDEBUG(D_NET, "Conn race %s\n", + libcfs_nid2str(peer2->ibp_nid)); kiblnd_peer_decref(peer); rej.ibr_why = IBLND_REJECT_CONN_RACE; goto failed; } - + if (peer2->ibp_races >= MAX_CONN_RACES_BEFORE_ABORT) + CNETERR("Conn race %s: unresolved after %d attempts, letting lower NID win\n", + libcfs_nid2str(peer2->ibp_nid), + MAX_CONN_RACES_BEFORE_ABORT); /** * passive connection is allowed even this peer is waiting for * reconnection. */ peer2->ibp_reconnecting = 0; + peer2->ibp_races = 0; peer2->ibp_accepting++; kiblnd_peer_addref(peer2); -- cgit v0.10.2 From 8040ddfb683247a73cb0f8e183aa80310c6c4b30 Mon Sep 17 00:00:00 2001 From: Al Viro <viro@zeniv.linux.org.uk> Date: Sat, 20 Aug 2016 17:34:18 -0400 Subject: staging: lustre: ksocknal_lib_recv_iov(): recvmsg doesn't bugger iovec anymore... Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Oleg Drokin <green@linuxhacker.ru> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c index fe7b9f9..77bb29ff 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c @@ -201,14 +201,7 @@ ksocknal_lib_eager_ack(struct ksock_conn *conn) int ksocknal_lib_recv_iov(struct ksock_conn *conn) { -#if SOCKNAL_SINGLE_FRAG_RX - struct kvec scratch; - struct kvec *scratchiov = &scratch; - unsigned int niov = 1; -#else - struct kvec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov; unsigned int niov = conn->ksnc_rx_niov; -#endif struct kvec *iov = conn->ksnc_rx_iov; struct msghdr msg = { .msg_flags = 0 @@ -220,20 +213,15 @@ ksocknal_lib_recv_iov(struct ksock_conn *conn) int sum; __u32 saved_csum; - /* - * NB we can't trust socket ops to either consume our iovs - * or leave them alone. - */ LASSERT(niov > 0); - for (nob = i = 0; i < niov; i++) { - scratchiov[i] = iov[i]; - nob += scratchiov[i].iov_len; - } + for (nob = i = 0; i < niov; i++) + nob += iov[i].iov_len; + LASSERT(nob <= conn->ksnc_rx_nob_wanted); - rc = kernel_recvmsg(conn->ksnc_sock, &msg, scratchiov, niov, nob, - MSG_DONTWAIT); + iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, iov, niov, nob); + rc = sock_recvmsg(conn->ksnc_sock, &msg, MSG_DONTWAIT); saved_csum = 0; if (conn->ksnc_proto == &ksocknal_protocol_v2x) { -- cgit v0.10.2 From 805560e8f12c693f78f8e914757f725c6ef05a6d Mon Sep 17 00:00:00 2001 From: Al Viro <viro@zeniv.linux.org.uk> Date: Sat, 20 Aug 2016 17:34:19 -0400 Subject: staging: lustre: ksocknal_lib_send_iov(): sendmsg doesn't bugger iovec... Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Oleg Drokin <green@linuxhacker.ru> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c index 77bb29ff..8eb4a68 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c @@ -73,9 +73,9 @@ ksocknal_lib_zc_capable(struct ksock_conn *conn) int ksocknal_lib_send_iov(struct ksock_conn *conn, struct ksock_tx *tx) { + struct msghdr msg = {.msg_flags = MSG_DONTWAIT}; struct socket *sock = conn->ksnc_sock; - int nob; - int rc; + int nob, i; if (*ksocknal_tunables.ksnd_enable_csum && /* checksum enabled */ conn->ksnc_proto == &ksocknal_protocol_v2x && /* V2.x connection */ @@ -83,34 +83,16 @@ ksocknal_lib_send_iov(struct ksock_conn *conn, struct ksock_tx *tx) !tx->tx_msg.ksm_csum) /* not checksummed */ ksocknal_lib_csum_tx(tx); - /* - * NB we can't trust socket ops to either consume our iovs - * or leave them alone. - */ - { -#if SOCKNAL_SINGLE_FRAG_TX - struct kvec scratch; - struct kvec *scratchiov = &scratch; - unsigned int niov = 1; -#else - struct kvec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov; - unsigned int niov = tx->tx_niov; -#endif - struct msghdr msg = {.msg_flags = MSG_DONTWAIT}; - int i; - - for (nob = i = 0; i < niov; i++) { - scratchiov[i] = tx->tx_iov[i]; - nob += scratchiov[i].iov_len; - } + for (nob = i = 0; i < tx->tx_niov; i++) + nob += tx->tx_iov[i].iov_len; - if (!list_empty(&conn->ksnc_tx_queue) || - nob < tx->tx_resid) - msg.msg_flags |= MSG_MORE; + if (!list_empty(&conn->ksnc_tx_queue) || + nob < tx->tx_resid) + msg.msg_flags |= MSG_MORE; - rc = kernel_sendmsg(sock, &msg, scratchiov, niov, nob); - } - return rc; + iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, + tx->tx_iov, tx->tx_niov, nob); + return sock_sendmsg(sock, &msg); } int -- cgit v0.10.2 From 1b4e992f50e1bcaf12cec7358e7b388984bc4ea9 Mon Sep 17 00:00:00 2001 From: Al Viro <viro@zeniv.linux.org.uk> Date: Sat, 20 Aug 2016 17:34:20 -0400 Subject: staging: lustre: ksocknal_lib_send_kiov(): sendmsg doesn't bugger iovec... Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Oleg Drokin <green@linuxhacker.ru> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c index 8eb4a68..6c95e98 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c @@ -106,10 +106,6 @@ ksocknal_lib_send_kiov(struct ksock_conn *conn, struct ksock_tx *tx) /* Not NOOP message */ LASSERT(tx->tx_lnetmsg); - /* - * NB we can't trust socket ops to either consume our iovs - * or leave them alone. - */ if (tx->tx_msg.ksm_zc_cookies[0]) { /* Zero copy is enabled */ struct sock *sk = sock->sk; @@ -132,34 +128,19 @@ ksocknal_lib_send_kiov(struct ksock_conn *conn, struct ksock_tx *tx) rc = tcp_sendpage(sk, page, offset, fragsize, msgflg); } } else { -#if SOCKNAL_SINGLE_FRAG_TX || !SOCKNAL_RISK_KMAP_DEADLOCK - struct kvec scratch; - struct kvec *scratchiov = &scratch; - unsigned int niov = 1; -#else -#ifdef CONFIG_HIGHMEM -#warning "XXX risk of kmap deadlock on multiple frags..." -#endif - struct kvec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov; - unsigned int niov = tx->tx_nkiov; -#endif struct msghdr msg = {.msg_flags = MSG_DONTWAIT}; int i; - for (nob = i = 0; i < niov; i++) { - scratchiov[i].iov_base = kmap(kiov[i].bv_page) + - kiov[i].bv_offset; - nob += scratchiov[i].iov_len = kiov[i].bv_len; - } + for (nob = i = 0; i < tx->tx_nkiov; i++) + nob += kiov[i].bv_len; if (!list_empty(&conn->ksnc_tx_queue) || nob < tx->tx_resid) msg.msg_flags |= MSG_MORE; - rc = kernel_sendmsg(sock, &msg, (struct kvec *)scratchiov, niov, nob); - - for (i = 0; i < niov; i++) - kunmap(kiov[i].bv_page); + iov_iter_bvec(&msg.msg_iter, WRITE | ITER_BVEC, + kiov, tx->tx_nkiov, nob); + rc = sock_sendmsg(sock, &msg); } return rc; } -- cgit v0.10.2 From a48228486532471f568f4c490dfe853dfa273774 Mon Sep 17 00:00:00 2001 From: Al Viro <viro@zeniv.linux.org.uk> Date: Sat, 20 Aug 2016 17:34:21 -0400 Subject: lustre: ->kss_scratch... are unused now Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Oleg Drokin <green@linuxhacker.ru> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h index d5efb42..84a915c 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h @@ -86,10 +86,6 @@ struct ksock_sched { /* per scheduler state */ int kss_nconns; /* # connections assigned to * this scheduler */ struct ksock_sched_info *kss_info; /* owner of it */ - union { - struct bio_vec kss_scratch_bvec[LNET_MAX_IOV]; - struct kvec kss_scratch_iov[LNET_MAX_IOV]; - }; }; struct ksock_sched_info { -- cgit v0.10.2 From 03766dca629d03c631417ecdbe1c760f3ec92878 Mon Sep 17 00:00:00 2001 From: Al Viro <viro@zeniv.linux.org.uk> Date: Sat, 20 Aug 2016 17:34:22 -0400 Subject: lustre: constify lib-move.c stuff Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Oleg Drokin <green@linuxhacker.ru> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h index 513a822..1c5418e 100644 --- a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h +++ b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h @@ -605,34 +605,34 @@ void lnet_counters_reset(void); unsigned int lnet_iov_nob(unsigned int niov, struct kvec *iov); int lnet_extract_iov(int dst_niov, struct kvec *dst, - int src_niov, struct kvec *src, + int src_niov, const struct kvec *src, unsigned int offset, unsigned int len); unsigned int lnet_kiov_nob(unsigned int niov, lnet_kiov_t *iov); int lnet_extract_kiov(int dst_niov, lnet_kiov_t *dst, - int src_niov, lnet_kiov_t *src, + int src_niov, const lnet_kiov_t *src, unsigned int offset, unsigned int len); -void lnet_copy_iov2iov(unsigned int ndiov, struct kvec *diov, +void lnet_copy_iov2iov(unsigned int ndiov, const struct kvec *diov, unsigned int doffset, - unsigned int nsiov, struct kvec *siov, + unsigned int nsiov, const struct kvec *siov, unsigned int soffset, unsigned int nob); -void lnet_copy_kiov2iov(unsigned int niov, struct kvec *iov, +void lnet_copy_kiov2iov(unsigned int niov, const struct kvec *iov, unsigned int iovoffset, - unsigned int nkiov, lnet_kiov_t *kiov, + unsigned int nkiov, const lnet_kiov_t *kiov, unsigned int kiovoffset, unsigned int nob); -void lnet_copy_iov2kiov(unsigned int nkiov, lnet_kiov_t *kiov, +void lnet_copy_iov2kiov(unsigned int nkiov, const lnet_kiov_t *kiov, unsigned int kiovoffset, - unsigned int niov, struct kvec *iov, + unsigned int niov, const struct kvec *iov, unsigned int iovoffset, unsigned int nob); -void lnet_copy_kiov2kiov(unsigned int ndkiov, lnet_kiov_t *dkiov, +void lnet_copy_kiov2kiov(unsigned int ndkiov, const lnet_kiov_t *dkiov, unsigned int doffset, - unsigned int nskiov, lnet_kiov_t *skiov, + unsigned int nskiov, const lnet_kiov_t *skiov, unsigned int soffset, unsigned int nob); static inline void lnet_copy_iov2flat(int dlen, void *dest, unsigned int doffset, - unsigned int nsiov, struct kvec *siov, unsigned int soffset, + unsigned int nsiov, const struct kvec *siov, unsigned int soffset, unsigned int nob) { struct kvec diov = {/*.iov_base = */ dest, /*.iov_len = */ dlen}; @@ -643,7 +643,7 @@ lnet_copy_iov2flat(int dlen, void *dest, unsigned int doffset, static inline void lnet_copy_kiov2flat(int dlen, void *dest, unsigned int doffset, - unsigned int nsiov, lnet_kiov_t *skiov, + unsigned int nsiov, const lnet_kiov_t *skiov, unsigned int soffset, unsigned int nob) { struct kvec diov = {/* .iov_base = */ dest, /* .iov_len = */ dlen}; @@ -653,7 +653,7 @@ lnet_copy_kiov2flat(int dlen, void *dest, unsigned int doffset, } static inline void -lnet_copy_flat2iov(unsigned int ndiov, struct kvec *diov, unsigned int doffset, +lnet_copy_flat2iov(unsigned int ndiov, const struct kvec *diov, unsigned int doffset, int slen, void *src, unsigned int soffset, unsigned int nob) { struct kvec siov = {/*.iov_base = */ src, /*.iov_len = */slen}; @@ -663,7 +663,7 @@ lnet_copy_flat2iov(unsigned int ndiov, struct kvec *diov, unsigned int doffset, } static inline void -lnet_copy_flat2kiov(unsigned int ndiov, lnet_kiov_t *dkiov, +lnet_copy_flat2kiov(unsigned int ndiov, const lnet_kiov_t *dkiov, unsigned int doffset, int slen, void *src, unsigned int soffset, unsigned int nob) { diff --git a/drivers/staging/lustre/lnet/lnet/lib-move.c b/drivers/staging/lustre/lnet/lnet/lib-move.c index 5598fa8..9a8a571 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-move.c +++ b/drivers/staging/lustre/lnet/lnet/lib-move.c @@ -166,8 +166,8 @@ lnet_iov_nob(unsigned int niov, struct kvec *iov) EXPORT_SYMBOL(lnet_iov_nob); void -lnet_copy_iov2iov(unsigned int ndiov, struct kvec *diov, unsigned int doffset, - unsigned int nsiov, struct kvec *siov, unsigned int soffset, +lnet_copy_iov2iov(unsigned int ndiov, const struct kvec *diov, unsigned int doffset, + unsigned int nsiov, const struct kvec *siov, unsigned int soffset, unsigned int nob) { /* NB diov, siov are READ-ONLY */ @@ -226,7 +226,7 @@ EXPORT_SYMBOL(lnet_copy_iov2iov); int lnet_extract_iov(int dst_niov, struct kvec *dst, - int src_niov, struct kvec *src, + int src_niov, const struct kvec *src, unsigned int offset, unsigned int len) { /* @@ -287,8 +287,8 @@ lnet_kiov_nob(unsigned int niov, lnet_kiov_t *kiov) EXPORT_SYMBOL(lnet_kiov_nob); void -lnet_copy_kiov2kiov(unsigned int ndiov, lnet_kiov_t *diov, unsigned int doffset, - unsigned int nsiov, lnet_kiov_t *siov, unsigned int soffset, +lnet_copy_kiov2kiov(unsigned int ndiov, const lnet_kiov_t *diov, unsigned int doffset, + unsigned int nsiov, const lnet_kiov_t *siov, unsigned int soffset, unsigned int nob) { /* NB diov, siov are READ-ONLY */ @@ -370,8 +370,8 @@ lnet_copy_kiov2kiov(unsigned int ndiov, lnet_kiov_t *diov, unsigned int doffset, EXPORT_SYMBOL(lnet_copy_kiov2kiov); void -lnet_copy_kiov2iov(unsigned int niov, struct kvec *iov, unsigned int iovoffset, - unsigned int nkiov, lnet_kiov_t *kiov, +lnet_copy_kiov2iov(unsigned int niov, const struct kvec *iov, unsigned int iovoffset, + unsigned int nkiov, const lnet_kiov_t *kiov, unsigned int kiovoffset, unsigned int nob) { /* NB iov, kiov are READ-ONLY */ @@ -440,9 +440,9 @@ lnet_copy_kiov2iov(unsigned int niov, struct kvec *iov, unsigned int iovoffset, EXPORT_SYMBOL(lnet_copy_kiov2iov); void -lnet_copy_iov2kiov(unsigned int nkiov, lnet_kiov_t *kiov, +lnet_copy_iov2kiov(unsigned int nkiov, const lnet_kiov_t *kiov, unsigned int kiovoffset, unsigned int niov, - struct kvec *iov, unsigned int iovoffset, + const struct kvec *iov, unsigned int iovoffset, unsigned int nob) { /* NB kiov, iov are READ-ONLY */ @@ -511,7 +511,7 @@ EXPORT_SYMBOL(lnet_copy_iov2kiov); int lnet_extract_kiov(int dst_niov, lnet_kiov_t *dst, - int src_niov, lnet_kiov_t *src, + int src_niov, const lnet_kiov_t *src, unsigned int offset, unsigned int len) { /* -- cgit v0.10.2 From c1b7b8eb86583eae68814c4993c916fc61b5e03b Mon Sep 17 00:00:00 2001 From: Al Viro <viro@zeniv.linux.org.uk> Date: Sat, 20 Aug 2016 17:34:23 -0400 Subject: lustre: pass iov_iter to ->lnd_recv() Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Oleg Drokin <green@linuxhacker.ru> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/include/linux/lnet/lib-types.h b/drivers/staging/lustre/include/linux/lnet/lib-types.h index 7967b01..640ff72 100644 --- a/drivers/staging/lustre/include/linux/lnet/lib-types.h +++ b/drivers/staging/lustre/include/linux/lnet/lib-types.h @@ -220,10 +220,7 @@ typedef struct lnet_lnd { * credit if the LND does flow control. */ int (*lnd_recv)(struct lnet_ni *ni, void *private, lnet_msg_t *msg, - int delayed, unsigned int niov, - struct kvec *iov, lnet_kiov_t *kiov, - unsigned int offset, unsigned int mlen, - unsigned int rlen); + int delayed, struct iov_iter *to, unsigned int rlen); /* * lnet_parse() has had to delay processing of this message diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h index fbc4f68..3cf8942 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h @@ -1036,5 +1036,4 @@ int kiblnd_post_rx(struct kib_rx *rx, int credit); int kiblnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg); int kiblnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, - unsigned int niov, struct kvec *iov, lnet_kiov_t *kiov, - unsigned int offset, unsigned int mlen, unsigned int rlen); + struct iov_iter *to, unsigned int rlen); diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index 430ff85..ae55418 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -650,7 +650,7 @@ static int kiblnd_map_tx(lnet_ni_t *ni, struct kib_tx *tx, struct kib_rdma_desc static int kiblnd_setup_rd_iov(lnet_ni_t *ni, struct kib_tx *tx, struct kib_rdma_desc *rd, - unsigned int niov, struct kvec *iov, int offset, int nob) + unsigned int niov, const struct kvec *iov, int offset, int nob) { struct kib_net *net = ni->ni_data; struct page *page; @@ -707,7 +707,7 @@ kiblnd_setup_rd_iov(lnet_ni_t *ni, struct kib_tx *tx, struct kib_rdma_desc *rd, static int kiblnd_setup_rd_kiov(lnet_ni_t *ni, struct kib_tx *tx, struct kib_rdma_desc *rd, - int nkiov, lnet_kiov_t *kiov, int offset, int nob) + int nkiov, const lnet_kiov_t *kiov, int offset, int nob) { struct kib_net *net = ni->ni_data; struct scatterlist *sg; @@ -1711,8 +1711,7 @@ kiblnd_reply(lnet_ni_t *ni, struct kib_rx *rx, lnet_msg_t *lntmsg) int kiblnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, - unsigned int niov, struct kvec *iov, lnet_kiov_t *kiov, - unsigned int offset, unsigned int mlen, unsigned int rlen) + struct iov_iter *to, unsigned int rlen) { struct kib_rx *rx = private; struct kib_msg *rxmsg = rx->rx_msg; @@ -1722,10 +1721,9 @@ kiblnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, int post_credit = IBLND_POSTRX_PEER_CREDIT; int rc = 0; - LASSERT(mlen <= rlen); + LASSERT(iov_iter_count(to) <= rlen); LASSERT(!in_interrupt()); /* Either all pages or all vaddrs */ - LASSERT(!(kiov && iov)); switch (rxmsg->ibm_type) { default: @@ -1741,16 +1739,16 @@ kiblnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, break; } - if (kiov) - lnet_copy_flat2kiov(niov, kiov, offset, + if (to->type & ITER_BVEC) + lnet_copy_flat2kiov(to->nr_segs, to->bvec, to->iov_offset, IBLND_MSG_SIZE, rxmsg, offsetof(struct kib_msg, ibm_u.immediate.ibim_payload), - mlen); + iov_iter_count(to)); else - lnet_copy_flat2iov(niov, iov, offset, + lnet_copy_flat2iov(to->nr_segs, to->kvec, to->iov_offset, IBLND_MSG_SIZE, rxmsg, offsetof(struct kib_msg, ibm_u.immediate.ibim_payload), - mlen); + iov_iter_count(to)); lnet_finalize(ni, lntmsg, 0); break; @@ -1758,7 +1756,7 @@ kiblnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, struct kib_msg *txmsg; struct kib_rdma_desc *rd; - if (!mlen) { + if (!iov_iter_count(to)) { lnet_finalize(ni, lntmsg, 0); kiblnd_send_completion(rx->rx_conn, IBLND_MSG_PUT_NAK, 0, rxmsg->ibm_u.putreq.ibprm_cookie); @@ -1776,12 +1774,16 @@ kiblnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, txmsg = tx->tx_msg; rd = &txmsg->ibm_u.putack.ibpam_rd; - if (!kiov) + if (!(to->type & ITER_BVEC)) rc = kiblnd_setup_rd_iov(ni, tx, rd, - niov, iov, offset, mlen); + to->nr_segs, to->kvec, + to->iov_offset, + iov_iter_count(to)); else rc = kiblnd_setup_rd_kiov(ni, tx, rd, - niov, kiov, offset, mlen); + to->nr_segs, to->bvec, + to->iov_offset, + iov_iter_count(to)); if (rc) { CERROR("Can't setup PUT sink for %s: %d\n", libcfs_nid2str(conn->ibc_peer->ibp_nid), rc); diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h index 84a915c..068440e 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h @@ -614,9 +614,7 @@ void ksocknal_shutdown(lnet_ni_t *ni); int ksocknal_ctl(lnet_ni_t *ni, unsigned int cmd, void *arg); int ksocknal_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg); int ksocknal_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, - int delayed, unsigned int niov, - struct kvec *iov, lnet_kiov_t *kiov, - unsigned int offset, unsigned int mlen, unsigned int rlen); + int delayed, struct iov_iter *to, unsigned int rlen); int ksocknal_accept(lnet_ni_t *ni, struct socket *sock); int ksocknal_add_peer(lnet_ni_t *ni, lnet_process_id_t id, __u32 ip, int port); diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c index f8573ed..1bdf962 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c @@ -1325,39 +1325,36 @@ ksocknal_process_receive(struct ksock_conn *conn) int ksocknal_recv(lnet_ni_t *ni, void *private, lnet_msg_t *msg, int delayed, - unsigned int niov, struct kvec *iov, lnet_kiov_t *kiov, - unsigned int offset, unsigned int mlen, unsigned int rlen) + struct iov_iter *to, unsigned int rlen) { struct ksock_conn *conn = private; struct ksock_sched *sched = conn->ksnc_scheduler; - LASSERT(mlen <= rlen); - LASSERT(niov <= LNET_MAX_IOV); + LASSERT(iov_iter_count(to) <= rlen); + LASSERT(to->nr_segs <= LNET_MAX_IOV); conn->ksnc_cookie = msg; - conn->ksnc_rx_nob_wanted = mlen; + conn->ksnc_rx_nob_wanted = iov_iter_count(to); conn->ksnc_rx_nob_left = rlen; - if (!mlen || iov) { + if (to->type & ITER_KVEC) { conn->ksnc_rx_nkiov = 0; conn->ksnc_rx_kiov = NULL; conn->ksnc_rx_iov = conn->ksnc_rx_iov_space.iov; conn->ksnc_rx_niov = lnet_extract_iov(LNET_MAX_IOV, conn->ksnc_rx_iov, - niov, iov, offset, mlen); + to->nr_segs, to->kvec, + to->iov_offset, iov_iter_count(to)); } else { conn->ksnc_rx_niov = 0; conn->ksnc_rx_iov = NULL; conn->ksnc_rx_kiov = conn->ksnc_rx_iov_space.kiov; conn->ksnc_rx_nkiov = lnet_extract_kiov(LNET_MAX_IOV, conn->ksnc_rx_kiov, - niov, kiov, offset, mlen); + to->nr_segs, to->bvec, + to->iov_offset, iov_iter_count(to)); } - LASSERT(mlen == - lnet_iov_nob(conn->ksnc_rx_niov, conn->ksnc_rx_iov) + - lnet_kiov_nob(conn->ksnc_rx_nkiov, conn->ksnc_rx_kiov)); - LASSERT(conn->ksnc_rx_scheduled); spin_lock_bh(&sched->kss_lock); diff --git a/drivers/staging/lustre/lnet/lnet/lib-move.c b/drivers/staging/lustre/lnet/lnet/lib-move.c index 9a8a571..7614e02 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-move.c +++ b/drivers/staging/lustre/lnet/lnet/lib-move.c @@ -569,6 +569,7 @@ lnet_ni_recv(lnet_ni_t *ni, void *private, lnet_msg_t *msg, int delayed, unsigned int niov = 0; struct kvec *iov = NULL; lnet_kiov_t *kiov = NULL; + struct iov_iter to; int rc; LASSERT(!in_interrupt()); @@ -594,8 +595,14 @@ lnet_ni_recv(lnet_ni_t *ni, void *private, lnet_msg_t *msg, int delayed, } } - rc = ni->ni_lnd->lnd_recv(ni, private, msg, delayed, - niov, iov, kiov, offset, mlen, rlen); + if (iov) { + iov_iter_kvec(&to, ITER_KVEC | READ, iov, niov, mlen + offset); + iov_iter_advance(&to, offset); + } else { + iov_iter_bvec(&to, ITER_BVEC | READ, kiov, niov, mlen + offset); + iov_iter_advance(&to, offset); + } + rc = ni->ni_lnd->lnd_recv(ni, private, msg, delayed, &to, rlen); if (rc < 0) lnet_finalize(ni, msg, rc); } diff --git a/drivers/staging/lustre/lnet/lnet/lo.c b/drivers/staging/lustre/lnet/lnet/lo.c index 08402712..131f84d 100644 --- a/drivers/staging/lustre/lnet/lnet/lo.c +++ b/drivers/staging/lustre/lnet/lnet/lo.c @@ -42,35 +42,33 @@ lolnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) static int lolnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, - int delayed, unsigned int niov, - struct kvec *iov, lnet_kiov_t *kiov, - unsigned int offset, unsigned int mlen, unsigned int rlen) + int delayed, struct iov_iter *to, unsigned int rlen) { lnet_msg_t *sendmsg = private; if (lntmsg) { /* not discarding */ if (sendmsg->msg_iov) { - if (iov) - lnet_copy_iov2iov(niov, iov, offset, + if (to->type & ITER_KVEC) + lnet_copy_iov2iov(to->nr_segs, to->kvec, to->iov_offset, sendmsg->msg_niov, sendmsg->msg_iov, - sendmsg->msg_offset, mlen); + sendmsg->msg_offset, iov_iter_count(to)); else - lnet_copy_iov2kiov(niov, kiov, offset, + lnet_copy_iov2kiov(to->nr_segs, to->bvec, to->iov_offset, sendmsg->msg_niov, sendmsg->msg_iov, - sendmsg->msg_offset, mlen); + sendmsg->msg_offset, iov_iter_count(to)); } else { - if (iov) - lnet_copy_kiov2iov(niov, iov, offset, + if (to->type & ITER_KVEC) + lnet_copy_kiov2iov(to->nr_segs, to->kvec, to->iov_offset, sendmsg->msg_niov, sendmsg->msg_kiov, - sendmsg->msg_offset, mlen); + sendmsg->msg_offset, iov_iter_count(to)); else - lnet_copy_kiov2kiov(niov, kiov, offset, + lnet_copy_kiov2kiov(to->nr_segs, to->bvec, to->iov_offset, sendmsg->msg_niov, sendmsg->msg_kiov, - sendmsg->msg_offset, mlen); + sendmsg->msg_offset, iov_iter_count(to)); } lnet_finalize(ni, lntmsg, 0); -- cgit v0.10.2 From 4cae780e54db3a8d75752bda812547db9f1c1c45 Mon Sep 17 00:00:00 2001 From: Al Viro <viro@zeniv.linux.org.uk> Date: Sat, 20 Aug 2016 17:34:24 -0400 Subject: lustre: introduce lnet_copy_{k, }iov2iter(), kill lnet_copy_{k, }iov2{k, }iov() Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Oleg Drokin <green@linuxhacker.ru> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h index 1c5418e..a59c5e99c 100644 --- a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h +++ b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h @@ -613,65 +613,12 @@ int lnet_extract_kiov(int dst_niov, lnet_kiov_t *dst, int src_niov, const lnet_kiov_t *src, unsigned int offset, unsigned int len); -void lnet_copy_iov2iov(unsigned int ndiov, const struct kvec *diov, - unsigned int doffset, +void lnet_copy_iov2iter(struct iov_iter *to, unsigned int nsiov, const struct kvec *siov, unsigned int soffset, unsigned int nob); -void lnet_copy_kiov2iov(unsigned int niov, const struct kvec *iov, - unsigned int iovoffset, +void lnet_copy_kiov2iter(struct iov_iter *to, unsigned int nkiov, const lnet_kiov_t *kiov, unsigned int kiovoffset, unsigned int nob); -void lnet_copy_iov2kiov(unsigned int nkiov, const lnet_kiov_t *kiov, - unsigned int kiovoffset, - unsigned int niov, const struct kvec *iov, - unsigned int iovoffset, unsigned int nob); -void lnet_copy_kiov2kiov(unsigned int ndkiov, const lnet_kiov_t *dkiov, - unsigned int doffset, - unsigned int nskiov, const lnet_kiov_t *skiov, - unsigned int soffset, unsigned int nob); - -static inline void -lnet_copy_iov2flat(int dlen, void *dest, unsigned int doffset, - unsigned int nsiov, const struct kvec *siov, unsigned int soffset, - unsigned int nob) -{ - struct kvec diov = {/*.iov_base = */ dest, /*.iov_len = */ dlen}; - - lnet_copy_iov2iov(1, &diov, doffset, - nsiov, siov, soffset, nob); -} - -static inline void -lnet_copy_kiov2flat(int dlen, void *dest, unsigned int doffset, - unsigned int nsiov, const lnet_kiov_t *skiov, - unsigned int soffset, unsigned int nob) -{ - struct kvec diov = {/* .iov_base = */ dest, /* .iov_len = */ dlen}; - - lnet_copy_kiov2iov(1, &diov, doffset, - nsiov, skiov, soffset, nob); -} - -static inline void -lnet_copy_flat2iov(unsigned int ndiov, const struct kvec *diov, unsigned int doffset, - int slen, void *src, unsigned int soffset, unsigned int nob) -{ - struct kvec siov = {/*.iov_base = */ src, /*.iov_len = */slen}; - - lnet_copy_iov2iov(ndiov, diov, doffset, - 1, &siov, soffset, nob); -} - -static inline void -lnet_copy_flat2kiov(unsigned int ndiov, const lnet_kiov_t *dkiov, - unsigned int doffset, int slen, void *src, - unsigned int soffset, unsigned int nob) -{ - struct kvec siov = {/* .iov_base = */ src, /* .iov_len = */ slen}; - - lnet_copy_iov2kiov(ndiov, dkiov, doffset, - 1, &siov, soffset, nob); -} void lnet_me_unlink(lnet_me_t *me); diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index ae55418..25f87e5 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -1491,6 +1491,7 @@ kiblnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) lnet_kiov_t *payload_kiov = lntmsg->msg_kiov; unsigned int payload_offset = lntmsg->msg_offset; unsigned int payload_nob = lntmsg->msg_len; + struct iov_iter from; struct kib_msg *ibmsg; struct kib_rdma_desc *rd; struct kib_tx *tx; @@ -1510,6 +1511,17 @@ kiblnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) /* payload is either all vaddrs or all pages */ LASSERT(!(payload_kiov && payload_iov)); + if (payload_kiov) + iov_iter_bvec(&from, ITER_BVEC | WRITE, + payload_kiov, payload_niov, + payload_nob + payload_offset); + else + iov_iter_kvec(&from, ITER_KVEC | WRITE, + payload_iov, payload_niov, + payload_nob + payload_offset); + + iov_iter_advance(&from, payload_offset); + switch (type) { default: LBUG(); @@ -1629,17 +1641,8 @@ kiblnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) ibmsg = tx->tx_msg; ibmsg->ibm_u.immediate.ibim_hdr = *hdr; - if (payload_kiov) - lnet_copy_kiov2flat(IBLND_MSG_SIZE, ibmsg, - offsetof(struct kib_msg, ibm_u.immediate.ibim_payload), - payload_niov, payload_kiov, - payload_offset, payload_nob); - else - lnet_copy_iov2flat(IBLND_MSG_SIZE, ibmsg, - offsetof(struct kib_msg, ibm_u.immediate.ibim_payload), - payload_niov, payload_iov, - payload_offset, payload_nob); - + copy_from_iter(&ibmsg->ibm_u.immediate.ibim_payload, IBLND_MSG_SIZE, + &from); nob = offsetof(struct kib_immediate_msg, ibim_payload[payload_nob]); kiblnd_init_tx_msg(ni, tx, IBLND_MSG_IMMEDIATE, nob); @@ -1739,16 +1742,8 @@ kiblnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, break; } - if (to->type & ITER_BVEC) - lnet_copy_flat2kiov(to->nr_segs, to->bvec, to->iov_offset, - IBLND_MSG_SIZE, rxmsg, - offsetof(struct kib_msg, ibm_u.immediate.ibim_payload), - iov_iter_count(to)); - else - lnet_copy_flat2iov(to->nr_segs, to->kvec, to->iov_offset, - IBLND_MSG_SIZE, rxmsg, - offsetof(struct kib_msg, ibm_u.immediate.ibim_payload), - iov_iter_count(to)); + copy_to_iter(&rxmsg->ibm_u.immediate.ibim_payload, + IBLND_MSG_SIZE, to); lnet_finalize(ni, lntmsg, 0); break; diff --git a/drivers/staging/lustre/lnet/lnet/lib-move.c b/drivers/staging/lustre/lnet/lnet/lib-move.c index 7614e02..f89c9fe 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-move.c +++ b/drivers/staging/lustre/lnet/lnet/lib-move.c @@ -166,25 +166,17 @@ lnet_iov_nob(unsigned int niov, struct kvec *iov) EXPORT_SYMBOL(lnet_iov_nob); void -lnet_copy_iov2iov(unsigned int ndiov, const struct kvec *diov, unsigned int doffset, - unsigned int nsiov, const struct kvec *siov, unsigned int soffset, - unsigned int nob) +lnet_copy_iov2iter(struct iov_iter *to, + unsigned int nsiov, const struct kvec *siov, + unsigned int soffset, unsigned int nob) { /* NB diov, siov are READ-ONLY */ - unsigned int this_nob; + const char *s; + size_t left; if (!nob) return; - /* skip complete frags before 'doffset' */ - LASSERT(ndiov > 0); - while (doffset >= diov->iov_len) { - doffset -= diov->iov_len; - diov++; - ndiov--; - LASSERT(ndiov > 0); - } - /* skip complete frags before 'soffset' */ LASSERT(nsiov > 0); while (soffset >= siov->iov_len) { @@ -194,35 +186,64 @@ lnet_copy_iov2iov(unsigned int ndiov, const struct kvec *diov, unsigned int doff LASSERT(nsiov > 0); } + s = (char *)siov->iov_base + soffset; + left = siov->iov_len - soffset; do { - LASSERT(ndiov > 0); + size_t n, copy = left; LASSERT(nsiov > 0); - this_nob = min(diov->iov_len - doffset, - siov->iov_len - soffset); - this_nob = min(this_nob, nob); - memcpy((char *)diov->iov_base + doffset, - (char *)siov->iov_base + soffset, this_nob); - nob -= this_nob; + if (copy > nob) + copy = nob; + n = copy_to_iter(s, copy, to); + if (n != copy) + return; + nob -= n; - if (diov->iov_len > doffset + this_nob) { - doffset += this_nob; - } else { - diov++; - ndiov--; - doffset = 0; - } + siov++; + s = (char *)siov->iov_base; + left = siov->iov_len; + nsiov--; + } while (nob > 0); +} +EXPORT_SYMBOL(lnet_copy_iov2iter); - if (siov->iov_len > soffset + this_nob) { - soffset += this_nob; - } else { - siov++; - nsiov--; - soffset = 0; - } +void +lnet_copy_kiov2iter(struct iov_iter *to, + unsigned int nsiov, const lnet_kiov_t *siov, + unsigned int soffset, unsigned int nob) +{ + if (!nob) + return; + + LASSERT(!in_interrupt()); + + LASSERT(nsiov > 0); + while (soffset >= siov->bv_len) { + soffset -= siov->bv_len; + siov++; + nsiov--; + LASSERT(nsiov > 0); + } + + do { + size_t copy = siov->bv_len - soffset, n; + + LASSERT(nsiov > 0); + + if (copy > nob) + copy = nob; + n = copy_page_to_iter(siov->bv_page, + siov->bv_offset + soffset, + copy, to); + if (n != copy) + return; + nob -= n; + siov++; + nsiov--; + soffset = 0; } while (nob > 0); } -EXPORT_SYMBOL(lnet_copy_iov2iov); +EXPORT_SYMBOL(lnet_copy_kiov2iter); int lnet_extract_iov(int dst_niov, struct kvec *dst, @@ -286,229 +307,6 @@ lnet_kiov_nob(unsigned int niov, lnet_kiov_t *kiov) } EXPORT_SYMBOL(lnet_kiov_nob); -void -lnet_copy_kiov2kiov(unsigned int ndiov, const lnet_kiov_t *diov, unsigned int doffset, - unsigned int nsiov, const lnet_kiov_t *siov, unsigned int soffset, - unsigned int nob) -{ - /* NB diov, siov are READ-ONLY */ - unsigned int this_nob; - char *daddr = NULL; - char *saddr = NULL; - - if (!nob) - return; - - LASSERT(!in_interrupt()); - - LASSERT(ndiov > 0); - while (doffset >= diov->bv_len) { - doffset -= diov->bv_len; - diov++; - ndiov--; - LASSERT(ndiov > 0); - } - - LASSERT(nsiov > 0); - while (soffset >= siov->bv_len) { - soffset -= siov->bv_len; - siov++; - nsiov--; - LASSERT(nsiov > 0); - } - - do { - LASSERT(ndiov > 0); - LASSERT(nsiov > 0); - this_nob = min(diov->bv_len - doffset, - siov->bv_len - soffset); - this_nob = min(this_nob, nob); - - if (!daddr) - daddr = ((char *)kmap(diov->bv_page)) + - diov->bv_offset + doffset; - if (!saddr) - saddr = ((char *)kmap(siov->bv_page)) + - siov->bv_offset + soffset; - - /* - * Vanishing risk of kmap deadlock when mapping 2 pages. - * However in practice at least one of the kiovs will be mapped - * kernel pages and the map/unmap will be NOOPs - */ - memcpy(daddr, saddr, this_nob); - nob -= this_nob; - - if (diov->bv_len > doffset + this_nob) { - daddr += this_nob; - doffset += this_nob; - } else { - kunmap(diov->bv_page); - daddr = NULL; - diov++; - ndiov--; - doffset = 0; - } - - if (siov->bv_len > soffset + this_nob) { - saddr += this_nob; - soffset += this_nob; - } else { - kunmap(siov->bv_page); - saddr = NULL; - siov++; - nsiov--; - soffset = 0; - } - } while (nob > 0); - - if (daddr) - kunmap(diov->bv_page); - if (saddr) - kunmap(siov->bv_page); -} -EXPORT_SYMBOL(lnet_copy_kiov2kiov); - -void -lnet_copy_kiov2iov(unsigned int niov, const struct kvec *iov, unsigned int iovoffset, - unsigned int nkiov, const lnet_kiov_t *kiov, - unsigned int kiovoffset, unsigned int nob) -{ - /* NB iov, kiov are READ-ONLY */ - unsigned int this_nob; - char *addr = NULL; - - if (!nob) - return; - - LASSERT(!in_interrupt()); - - LASSERT(niov > 0); - while (iovoffset >= iov->iov_len) { - iovoffset -= iov->iov_len; - iov++; - niov--; - LASSERT(niov > 0); - } - - LASSERT(nkiov > 0); - while (kiovoffset >= kiov->bv_len) { - kiovoffset -= kiov->bv_len; - kiov++; - nkiov--; - LASSERT(nkiov > 0); - } - - do { - LASSERT(niov > 0); - LASSERT(nkiov > 0); - this_nob = min(iov->iov_len - iovoffset, - (__kernel_size_t)kiov->bv_len - kiovoffset); - this_nob = min(this_nob, nob); - - if (!addr) - addr = ((char *)kmap(kiov->bv_page)) + - kiov->bv_offset + kiovoffset; - - memcpy((char *)iov->iov_base + iovoffset, addr, this_nob); - nob -= this_nob; - - if (iov->iov_len > iovoffset + this_nob) { - iovoffset += this_nob; - } else { - iov++; - niov--; - iovoffset = 0; - } - - if (kiov->bv_len > kiovoffset + this_nob) { - addr += this_nob; - kiovoffset += this_nob; - } else { - kunmap(kiov->bv_page); - addr = NULL; - kiov++; - nkiov--; - kiovoffset = 0; - } - - } while (nob > 0); - - if (addr) - kunmap(kiov->bv_page); -} -EXPORT_SYMBOL(lnet_copy_kiov2iov); - -void -lnet_copy_iov2kiov(unsigned int nkiov, const lnet_kiov_t *kiov, - unsigned int kiovoffset, unsigned int niov, - const struct kvec *iov, unsigned int iovoffset, - unsigned int nob) -{ - /* NB kiov, iov are READ-ONLY */ - unsigned int this_nob; - char *addr = NULL; - - if (!nob) - return; - - LASSERT(!in_interrupt()); - - LASSERT(nkiov > 0); - while (kiovoffset >= kiov->bv_len) { - kiovoffset -= kiov->bv_len; - kiov++; - nkiov--; - LASSERT(nkiov > 0); - } - - LASSERT(niov > 0); - while (iovoffset >= iov->iov_len) { - iovoffset -= iov->iov_len; - iov++; - niov--; - LASSERT(niov > 0); - } - - do { - LASSERT(nkiov > 0); - LASSERT(niov > 0); - this_nob = min((__kernel_size_t)kiov->bv_len - kiovoffset, - iov->iov_len - iovoffset); - this_nob = min(this_nob, nob); - - if (!addr) - addr = ((char *)kmap(kiov->bv_page)) + - kiov->bv_offset + kiovoffset; - - memcpy(addr, (char *)iov->iov_base + iovoffset, this_nob); - nob -= this_nob; - - if (kiov->bv_len > kiovoffset + this_nob) { - addr += this_nob; - kiovoffset += this_nob; - } else { - kunmap(kiov->bv_page); - addr = NULL; - kiov++; - nkiov--; - kiovoffset = 0; - } - - if (iov->iov_len > iovoffset + this_nob) { - iovoffset += this_nob; - } else { - iov++; - niov--; - iovoffset = 0; - } - } while (nob > 0); - - if (addr) - kunmap(kiov->bv_page); -} -EXPORT_SYMBOL(lnet_copy_iov2kiov); - int lnet_extract_kiov(int dst_niov, lnet_kiov_t *dst, int src_niov, const lnet_kiov_t *src, diff --git a/drivers/staging/lustre/lnet/lnet/lo.c b/drivers/staging/lustre/lnet/lnet/lo.c index 131f84d..cb213b8 100644 --- a/drivers/staging/lustre/lnet/lnet/lo.c +++ b/drivers/staging/lustre/lnet/lnet/lo.c @@ -47,29 +47,18 @@ lolnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, lnet_msg_t *sendmsg = private; if (lntmsg) { /* not discarding */ - if (sendmsg->msg_iov) { - if (to->type & ITER_KVEC) - lnet_copy_iov2iov(to->nr_segs, to->kvec, to->iov_offset, - sendmsg->msg_niov, - sendmsg->msg_iov, - sendmsg->msg_offset, iov_iter_count(to)); - else - lnet_copy_iov2kiov(to->nr_segs, to->bvec, to->iov_offset, - sendmsg->msg_niov, - sendmsg->msg_iov, - sendmsg->msg_offset, iov_iter_count(to)); - } else { - if (to->type & ITER_KVEC) - lnet_copy_kiov2iov(to->nr_segs, to->kvec, to->iov_offset, - sendmsg->msg_niov, - sendmsg->msg_kiov, - sendmsg->msg_offset, iov_iter_count(to)); - else - lnet_copy_kiov2kiov(to->nr_segs, to->bvec, to->iov_offset, - sendmsg->msg_niov, - sendmsg->msg_kiov, - sendmsg->msg_offset, iov_iter_count(to)); - } + if (sendmsg->msg_iov) + lnet_copy_iov2iter(to, + sendmsg->msg_niov, + sendmsg->msg_iov, + sendmsg->msg_offset, + iov_iter_count(to)); + else + lnet_copy_kiov2iter(to, + sendmsg->msg_niov, + sendmsg->msg_kiov, + sendmsg->msg_offset, + iov_iter_count(to)); lnet_finalize(ni, lntmsg, 0); } -- cgit v0.10.2 From 3a77df1180acf1cbe2276a0cbe91e5d07fbf3c47 Mon Sep 17 00:00:00 2001 From: Oleg Drokin <green@linuxhacker.ru> Date: Sat, 20 Aug 2016 17:34:25 -0400 Subject: staging/lustre: Always return EEXIST on mkdir for existing names if the name already exists, but we don't have write permissions in the parent, force talking to the MDS to determine what more sensical error code to return. This also happens to fix matlab and other such programs that assume that EEXIST is the only valid error code for mkdir of an existing directory. Signed-off-by: Oleg Drokin <green@linuxhacker.ru> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index ee5a42e..d13debb 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -606,8 +606,12 @@ static struct dentry *ll_lookup_nd(struct inode *parent, struct dentry *dentry, CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir="DFID"(%p),flags=%u\n", dentry, PFID(ll_inode2fid(parent)), parent, flags); - /* Optimize away (CREATE && !OPEN). Let .create handle the race. */ - if ((flags & LOOKUP_CREATE) && !(flags & LOOKUP_OPEN)) + /* Optimize away (CREATE && !OPEN). Let .create handle the race. + * but only if we have write permissions there, otherwise we need + * to proceed with lookup. LU-4185 + */ + if ((flags & LOOKUP_CREATE) && !(flags & LOOKUP_OPEN) && + (inode_permission(parent, MAY_WRITE | MAY_EXEC) == 0)) return NULL; if (flags & (LOOKUP_PARENT|LOOKUP_OPEN|LOOKUP_CREATE)) -- cgit v0.10.2 From 7ccb7c8f17213a4a7638555958e763befdf5a167 Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Fri, 19 Aug 2016 14:07:25 -0400 Subject: staging: lustre: lmv: implement lmv version of read_page All the code needed to implement read_page. This will eventually replace lmv_readpage. Signed-off-by: wang di <di.wang@intel.com> Reviewed-on: http://review.whamcloud.com/10761 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4906 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 3e41f49..1f01be4 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -2369,6 +2369,334 @@ static int lmv_readpage(struct obd_export *exp, struct md_op_data *op_data, } /** + * Get current minimum entry from striped directory + * + * This function will search the dir entry, whose hash value is the + * closest(>=) to @hash_offset, from all of sub-stripes, and it is + * only being called for striped directory. + * + * \param[in] exp export of LMV + * \param[in] op_data parameters transferred beween client MD stack + * stripe_information will be included in this + * parameter + * \param[in] cb_op ldlm callback being used in enqueue in + * mdc_read_page + * \param[in] hash_offset the hash value, which is used to locate + * minum(closet) dir entry + * \param[in|out] stripe_offset the caller use this to indicate the stripe + * index of last entry, so to avoid hash conflict + * between stripes. It will also be used to + * return the stripe index of current dir entry. + * \param[in|out] entp the minum entry and it also is being used + * to input the last dir entry to resolve the + * hash conflict + * + * \param[out] ppage the page which holds the minum entry + * + * \retval = 0 get the entry successfully + * negative errno (< 0) does not get the entry + */ +static int lmv_get_min_striped_entry(struct obd_export *exp, + struct md_op_data *op_data, + struct md_callback *cb_op, + __u64 hash_offset, int *stripe_offset, + struct lu_dirent **entp, + struct page **ppage) +{ + struct lmv_stripe_md *lsm = op_data->op_mea1; + struct obd_device *obd = exp->exp_obd; + struct lmv_obd *lmv = &obd->u.lmv; + struct lu_dirent *min_ent = NULL; + struct page *min_page = NULL; + struct lmv_tgt_desc *tgt; + int stripe_count; + int min_idx = 0; + int rc = 0; + int i; + + stripe_count = lsm->lsm_md_stripe_count; + for (i = 0; i < stripe_count; i++) { + __u64 stripe_hash = hash_offset; + struct lu_dirent *ent = NULL; + struct page *page = NULL; + struct lu_dirpage *dp; + + tgt = lmv_get_target(lmv, lsm->lsm_md_oinfo[i].lmo_mds, NULL); + if (IS_ERR(tgt)) { + rc = PTR_ERR(tgt); + goto out; + } + + /* + * op_data will be shared by each stripe, so we need + * reset these value for each stripe + */ + op_data->op_fid1 = lsm->lsm_md_oinfo[i].lmo_fid; + op_data->op_fid2 = lsm->lsm_md_oinfo[i].lmo_fid; + op_data->op_data = lsm->lsm_md_oinfo[i].lmo_root; +next: + rc = md_read_page(tgt->ltd_exp, op_data, cb_op, stripe_hash, + &page); + if (rc) + goto out; + + dp = page_address(page); + for (ent = lu_dirent_start(dp); ent; + ent = lu_dirent_next(ent)) { + /* Skip dummy entry */ + if (!le16_to_cpu(ent->lde_namelen)) + continue; + + if (le64_to_cpu(ent->lde_hash) < hash_offset) + continue; + + if (le64_to_cpu(ent->lde_hash) == hash_offset && + (*entp == ent || i < *stripe_offset)) + continue; + + /* skip . and .. for other stripes */ + if (i && (!strncmp(ent->lde_name, ".", + le16_to_cpu(ent->lde_namelen)) || + !strncmp(ent->lde_name, "..", + le16_to_cpu(ent->lde_namelen)))) + continue; + break; + } + + if (!ent) { + stripe_hash = le64_to_cpu(dp->ldp_hash_end); + + kunmap(page); + put_page(page); + page = NULL; + + /* + * reach the end of current stripe, go to next stripe + */ + if (stripe_hash == MDS_DIR_END_OFF) + continue; + else + goto next; + } + + if (min_ent) { + if (le64_to_cpu(min_ent->lde_hash) > + le64_to_cpu(ent->lde_hash)) { + min_ent = ent; + kunmap(min_page); + put_page(min_page); + min_idx = i; + min_page = page; + } else { + kunmap(page); + put_page(page); + page = NULL; + } + } else { + min_ent = ent; + min_page = page; + min_idx = i; + } + } + +out: + if (*ppage) { + kunmap(*ppage); + put_page(*ppage); + } + *stripe_offset = min_idx; + *entp = min_ent; + *ppage = min_page; + return rc; +} + +/** + * Build dir entry page from a striped directory + * + * This function gets one entry by @offset from a striped directory. It will + * read entries from all of stripes, and choose one closest to the required + * offset(&offset). A few notes + * 1. skip . and .. for non-zero stripes, because there can only have one . + * and .. in a directory. + * 2. op_data will be shared by all of stripes, instead of allocating new + * one, so need to restore before reusing. + * 3. release the entry page if that is not being chosen. + * + * \param[in] exp obd export refer to LMV + * \param[in] op_data hold those MD parameters of read_entry + * \param[in] cb_op ldlm callback being used in enqueue in mdc_read_entry + * \param[out] ldp the entry being read + * \param[out] ppage the page holding the entry. Note: because the entry + * will be accessed in upper layer, so we need hold the + * page until the usages of entry is finished, see + * ll_dir_entry_next. + * + * retval =0 if get entry successfully + * <0 cannot get entry + */ +static int lmv_read_striped_page(struct obd_export *exp, + struct md_op_data *op_data, + struct md_callback *cb_op, + __u64 offset, struct page **ppage) +{ + struct inode *master_inode = op_data->op_data; + struct lu_fid master_fid = op_data->op_fid1; + struct obd_device *obd = exp->exp_obd; + __u64 hash_offset = offset; + struct page *min_ent_page = NULL; + struct page *ent_page = NULL; + struct lu_dirent *min_ent = NULL; + struct lu_dirent *last_ent; + struct lu_dirent *ent; + struct lu_dirpage *dp; + size_t left_bytes; + int ent_idx = 0; + void *area; + int rc; + + rc = lmv_check_connect(obd); + if (rc) + return rc; + + /* + * Allocate a page and read entries from all of stripes and fill + * the page by hash order + */ + ent_page = alloc_page(GFP_KERNEL); + if (!ent_page) + return -ENOMEM; + + /* Initialize the entry page */ + dp = kmap(ent_page); + memset(dp, 0, sizeof(*dp)); + dp->ldp_hash_start = cpu_to_le64(offset); + dp->ldp_flags |= LDF_COLLIDE; + + area = dp + 1; + left_bytes = PAGE_SIZE - sizeof(*dp); + ent = area; + last_ent = ent; + do { + __u16 ent_size; + + /* Find the minum entry from all sub-stripes */ + rc = lmv_get_min_striped_entry(exp, op_data, cb_op, hash_offset, + &ent_idx, &min_ent, + &min_ent_page); + if (rc) + goto out; + + /* + * If it can not get minum entry, it means it already reaches + * the end of this directory + */ + if (!min_ent) { + last_ent->lde_reclen = 0; + hash_offset = MDS_DIR_END_OFF; + goto out; + } + + ent_size = le16_to_cpu(min_ent->lde_reclen); + + /* + * the last entry lde_reclen is 0, but it might not + * the end of this entry of this temporay entry + */ + if (!ent_size) + ent_size = lu_dirent_calc_size( + le16_to_cpu(min_ent->lde_namelen), + le32_to_cpu(min_ent->lde_attrs)); + if (ent_size > left_bytes) { + last_ent->lde_reclen = cpu_to_le16(0); + hash_offset = le64_to_cpu(min_ent->lde_hash); + goto out; + } + + memcpy(ent, min_ent, ent_size); + + /* + * Replace . with master FID and Replace .. with the parent FID + * of master object + */ + if (!strncmp(ent->lde_name, ".", + le16_to_cpu(ent->lde_namelen)) && + le16_to_cpu(ent->lde_namelen) == 1) + fid_cpu_to_le(&ent->lde_fid, &master_fid); + else if (!strncmp(ent->lde_name, "..", + le16_to_cpu(ent->lde_namelen)) && + le16_to_cpu(ent->lde_namelen) == 2) + fid_cpu_to_le(&ent->lde_fid, &op_data->op_fid3); + + left_bytes -= ent_size; + ent->lde_reclen = cpu_to_le16(ent_size); + last_ent = ent; + ent = (void *)ent + ent_size; + hash_offset = le64_to_cpu(min_ent->lde_hash); + if (hash_offset == MDS_DIR_END_OFF) { + last_ent->lde_reclen = 0; + break; + } + } while (1); +out: + if (min_ent_page) { + kunmap(min_ent_page); + put_page(min_ent_page); + } + + if (unlikely(rc)) { + __free_page(ent_page); + ent_page = NULL; + } else { + if (ent == area) + dp->ldp_flags |= LDF_EMPTY; + dp->ldp_flags = cpu_to_le32(dp->ldp_flags); + dp->ldp_hash_end = cpu_to_le64(hash_offset); + } + + /* + * We do not want to allocate md_op_data during each + * dir entry reading, so op_data will be shared by every stripe, + * then we need to restore it back to original value before + * return to the upper layer + */ + op_data->op_fid1 = master_fid; + op_data->op_fid2 = master_fid; + op_data->op_data = master_inode; + + *ppage = ent_page; + + return rc; +} + +int lmv_read_page(struct obd_export *exp, struct md_op_data *op_data, + struct md_callback *cb_op, __u64 offset, + struct page **ppage) +{ + struct lmv_stripe_md *lsm = op_data->op_mea1; + struct obd_device *obd = exp->exp_obd; + struct lmv_obd *lmv = &obd->u.lmv; + struct lmv_tgt_desc *tgt; + int rc; + + rc = lmv_check_connect(obd); + if (rc) + return rc; + + if (unlikely(lsm)) { + rc = lmv_read_striped_page(exp, op_data, cb_op, offset, ppage); + return rc; + } + + tgt = lmv_find_target(lmv, &op_data->op_fid1); + if (IS_ERR(tgt)) + return PTR_ERR(tgt); + + rc = md_read_page(tgt->ltd_exp, op_data, cb_op, offset, ppage); + + return rc; +} + +/** * Unlink a file/directory * * Unlink a file or directory under the parent dir. The unlink request @@ -3268,6 +3596,7 @@ static struct md_ops lmv_md_ops = { .setxattr = lmv_setxattr, .sync = lmv_sync, .readpage = lmv_readpage, + .read_page = lmv_read_page, .unlink = lmv_unlink, .init_ea_size = lmv_init_ea_size, .cancel_unused = lmv_cancel_unused, -- cgit v0.10.2 From 4f76f0ec093c2f9ef049495c78d486bfb48e4de0 Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Fri, 19 Aug 2016 14:07:26 -0400 Subject: staging: lustre: llite: move dir cache to MDC layer Move directory entries cache from llite to MDC, so client side dir stripe will use independent hash function(in LMV), which does not need to be tightly coupled with the backend storage dir-entry hash function. With striped directory, it will be 2-tier hash, LMV calculate hash value according to the name and hash-type in layout, then each MDT will store these entry in disk by its own hash. Signed-off-by: wang di <di.wang@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3531 Reviewed-on: http://review.whamcloud.com/7043 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre_lite.h b/drivers/staging/lustre/lustre/include/lustre_lite.h index a3d7573..e2f3767 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lite.h +++ b/drivers/staging/lustre/lustre/include/lustre_lite.h @@ -80,17 +80,6 @@ static inline void ll_dir_chain_fini(struct ll_dir_chain *chain) { } -static inline unsigned long hash_x_index(__u64 hash, int hash64) -{ - if (BITS_PER_LONG == 32 && hash64) - hash >>= 32; - /* save hash 0 as index 0 because otherwise we'll save it at - * page index end (~0UL) and it causes truncate_inode_pages_range() - * to loop forever. - */ - return ~0UL - (hash + !hash); -} - /** @} lite */ #endif diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index ed09015..532047b 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -134,111 +134,35 @@ * for this integrated page will be adjusted. See lmv_adjust_dirpages(). * */ - -/* returns the page unlocked, but with a reference */ -static int ll_dir_filler(void *_hash, struct page *page0) +struct page *ll_get_dir_page(struct inode *dir, struct md_op_data *op_data, + __u64 offset, struct ll_dir_chain *chain) { - struct inode *inode = page0->mapping->host; - int hash64 = ll_i2sbi(inode)->ll_flags & LL_SBI_64BIT_HASH; - struct obd_export *exp = ll_i2sbi(inode)->ll_md_exp; - struct ptlrpc_request *request; - struct mdt_body *body; - struct md_op_data *op_data; - __u64 hash = *((__u64 *)_hash); - struct page **page_pool; + struct md_callback cb_op; struct page *page; - struct lu_dirpage *dp; - int max_pages = ll_i2sbi(inode)->ll_md_brw_pages; - int nrdpgs = 0; /* number of pages read actually */ - int npages; - int i; int rc; - CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p) hash %llu\n", - PFID(ll_inode2fid(inode)), inode, hash); - - LASSERT(max_pages > 0 && max_pages <= MD_MAX_BRW_PAGES); - - op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0, - LUSTRE_OPC_ANY, NULL); - if (IS_ERR(op_data)) - return PTR_ERR(op_data); - - page_pool = kcalloc(max_pages, sizeof(page), GFP_NOFS); - if (page_pool) { - page_pool[0] = page0; - } else { - page_pool = &page0; - max_pages = 1; - } - for (npages = 1; npages < max_pages; npages++) { - page = page_cache_alloc_cold(inode->i_mapping); - if (!page) - break; - page_pool[npages] = page; - } - - op_data->op_npages = npages; - op_data->op_offset = hash; - rc = md_readpage(exp, op_data, page_pool, &request); - ll_finish_md_op_data(op_data); - if (rc < 0) { - /* page0 is special, which was added into page cache early */ - delete_from_page_cache(page0); - } else if (rc == 0) { - body = req_capsule_server_get(&request->rq_pill, &RMF_MDT_BODY); - /* Checked by mdc_readpage() */ - if (body->mbo_valid & OBD_MD_FLSIZE) - i_size_write(inode, body->mbo_size); - - nrdpgs = (request->rq_bulk->bd_nob_transferred+PAGE_SIZE-1) - >> PAGE_SHIFT; - SetPageUptodate(page0); - } - unlock_page(page0); - ptlrpc_req_finished(request); - - CDEBUG(D_VFSTRACE, "read %d/%d pages\n", nrdpgs, npages); - - for (i = 1; i < npages; i++) { - unsigned long offset; - int ret; - - page = page_pool[i]; - - if (rc < 0 || i >= nrdpgs) { - put_page(page); - continue; - } - - SetPageUptodate(page); - - dp = kmap(page); - hash = le64_to_cpu(dp->ldp_hash_start); - kunmap(page); - - offset = hash_x_index(hash, hash64); - - prefetchw(&page->flags); - ret = add_to_page_cache_lru(page, inode->i_mapping, offset, - GFP_NOFS); - if (ret == 0) { - unlock_page(page); - } else { - CDEBUG(D_VFSTRACE, "page %lu add to page cache failed: %d\n", - offset, ret); - } - put_page(page); - } + cb_op.md_blocking_ast = ll_md_blocking_ast; + rc = md_read_page(ll_i2mdexp(dir), op_data, &cb_op, offset, &page); + if (rc) + return ERR_PTR(rc); - if (page_pool != &page0) - kfree(page_pool); - return rc; + return page; } void ll_release_page(struct inode *inode, struct page *page, bool remove) { kunmap(page); + + /* + * Always remove the page for striped dir, because the page is + * built from temporarily in LMV layer + */ + if (inode && S_ISDIR(inode->i_mode) && + ll_i2info(inode)->lli_lsm_md) { + __free_page(page); + return; + } + if (remove) { lock_page(page); if (likely(page->mapping)) @@ -248,226 +172,6 @@ void ll_release_page(struct inode *inode, struct page *page, bool remove) put_page(page); } -/* - * Find, kmap and return page that contains given hash. - */ -static struct page *ll_dir_page_locate(struct inode *dir, __u64 *hash, - __u64 *start, __u64 *end) -{ - int hash64 = ll_i2sbi(dir)->ll_flags & LL_SBI_64BIT_HASH; - struct address_space *mapping = dir->i_mapping; - /* - * Complement of hash is used as an index so that - * radix_tree_gang_lookup() can be used to find a page with starting - * hash _smaller_ than one we are looking for. - */ - unsigned long offset = hash_x_index(*hash, hash64); - struct page *page; - int found; - - spin_lock_irq(&mapping->tree_lock); - found = radix_tree_gang_lookup(&mapping->page_tree, - (void **)&page, offset, 1); - if (found > 0 && !radix_tree_exceptional_entry(page)) { - struct lu_dirpage *dp; - - get_page(page); - spin_unlock_irq(&mapping->tree_lock); - /* - * In contrast to find_lock_page() we are sure that directory - * page cannot be truncated (while DLM lock is held) and, - * hence, can avoid restart. - * - * In fact, page cannot be locked here at all, because - * ll_dir_filler() does synchronous io. - */ - wait_on_page_locked(page); - if (PageUptodate(page)) { - dp = kmap(page); - if (BITS_PER_LONG == 32 && hash64) { - *start = le64_to_cpu(dp->ldp_hash_start) >> 32; - *end = le64_to_cpu(dp->ldp_hash_end) >> 32; - *hash = *hash >> 32; - } else { - *start = le64_to_cpu(dp->ldp_hash_start); - *end = le64_to_cpu(dp->ldp_hash_end); - } - LASSERTF(*start <= *hash, "start = %#llx,end = %#llx,hash = %#llx\n", - *start, *end, *hash); - CDEBUG(D_VFSTRACE, "page %lu [%llu %llu], hash %llu\n", - offset, *start, *end, *hash); - if (*hash > *end) { - ll_release_page(dir, page, false); - page = NULL; - } else if (*end != *start && *hash == *end) { - /* - * upon hash collision, remove this page, - * otherwise put page reference, and - * ll_get_dir_page() will issue RPC to fetch - * the page we want. - */ - ll_release_page(dir, page, - le32_to_cpu(dp->ldp_flags) & - LDF_COLLIDE); - page = NULL; - } - } else { - put_page(page); - page = ERR_PTR(-EIO); - } - - } else { - spin_unlock_irq(&mapping->tree_lock); - page = NULL; - } - return page; -} - -struct page *ll_get_dir_page(struct inode *dir, struct md_op_data *op_data, - __u64 hash, struct ll_dir_chain *chain) -{ - ldlm_policy_data_t policy = {.l_inodebits = {MDS_INODELOCK_UPDATE} }; - struct address_space *mapping = dir->i_mapping; - struct lustre_handle lockh; - struct lu_dirpage *dp; - struct page *page; - enum ldlm_mode mode; - int rc; - __u64 start = 0; - __u64 end = 0; - __u64 lhash = hash; - struct ll_inode_info *lli = ll_i2info(dir); - int hash64 = ll_i2sbi(dir)->ll_flags & LL_SBI_64BIT_HASH; - - mode = LCK_PR; - rc = md_lock_match(ll_i2sbi(dir)->ll_md_exp, LDLM_FL_BLOCK_GRANTED, - ll_inode2fid(dir), LDLM_IBITS, &policy, mode, &lockh); - if (!rc) { - struct ldlm_enqueue_info einfo = { - .ei_type = LDLM_IBITS, - .ei_mode = mode, - .ei_cb_bl = ll_md_blocking_ast, - .ei_cb_cp = ldlm_completion_ast, - }; - struct lookup_intent it = { .it_op = IT_READDIR }; - struct ptlrpc_request *request; - struct md_op_data *op_data; - - op_data = ll_prep_md_op_data(NULL, dir, dir, NULL, 0, 0, - LUSTRE_OPC_ANY, NULL); - if (IS_ERR(op_data)) - return (void *)op_data; - - rc = md_enqueue(ll_i2sbi(dir)->ll_md_exp, &einfo, &it, - op_data, &lockh, NULL, 0, NULL, 0); - - ll_finish_md_op_data(op_data); - - request = (struct ptlrpc_request *)it.it_request; - if (request) - ptlrpc_req_finished(request); - if (rc < 0) { - CERROR("lock enqueue: " DFID " at %llu: rc %d\n", - PFID(ll_inode2fid(dir)), hash, rc); - return ERR_PTR(rc); - } - - CDEBUG(D_INODE, "setting lr_lvb_inode to inode "DFID"(%p)\n", - PFID(ll_inode2fid(dir)), dir); - md_set_lock_data(ll_i2sbi(dir)->ll_md_exp, - &it.it_lock_handle, dir, NULL); - } else { - /* for cross-ref object, l_ast_data of the lock may not be set, - * we reset it here - */ - md_set_lock_data(ll_i2sbi(dir)->ll_md_exp, &lockh.cookie, - dir, NULL); - } - ldlm_lock_dump_handle(D_OTHER, &lockh); - - mutex_lock(&lli->lli_readdir_mutex); - page = ll_dir_page_locate(dir, &lhash, &start, &end); - if (IS_ERR(page)) { - CERROR("dir page locate: "DFID" at %llu: rc %ld\n", - PFID(ll_inode2fid(dir)), lhash, PTR_ERR(page)); - goto out_unlock; - } else if (page) { - /* - * XXX nikita: not entirely correct handling of a corner case: - * suppose hash chain of entries with hash value HASH crosses - * border between pages P0 and P1. First both P0 and P1 are - * cached, seekdir() is called for some entry from the P0 part - * of the chain. Later P0 goes out of cache. telldir(HASH) - * happens and finds P1, as it starts with matching hash - * value. Remaining entries from P0 part of the chain are - * skipped. (Is that really a bug?) - * - * Possible solutions: 0. don't cache P1 is such case, handle - * it as an "overflow" page. 1. invalidate all pages at - * once. 2. use HASH|1 as an index for P1. - */ - goto hash_collision; - } - - page = read_cache_page(mapping, hash_x_index(hash, hash64), - ll_dir_filler, &lhash); - if (IS_ERR(page)) { - CERROR("read cache page: "DFID" at %llu: rc %ld\n", - PFID(ll_inode2fid(dir)), hash, PTR_ERR(page)); - goto out_unlock; - } - - wait_on_page_locked(page); - (void)kmap(page); - if (!PageUptodate(page)) { - CERROR("page not updated: "DFID" at %llu: rc %d\n", - PFID(ll_inode2fid(dir)), hash, -5); - goto fail; - } - if (!PageChecked(page)) - /* XXX: check page format later */ - SetPageChecked(page); - if (PageError(page)) { - CERROR("page error: "DFID" at %llu: rc %d\n", - PFID(ll_inode2fid(dir)), hash, -5); - goto fail; - } -hash_collision: - dp = page_address(page); - if (BITS_PER_LONG == 32 && hash64) { - start = le64_to_cpu(dp->ldp_hash_start) >> 32; - end = le64_to_cpu(dp->ldp_hash_end) >> 32; - lhash = hash >> 32; - } else { - start = le64_to_cpu(dp->ldp_hash_start); - end = le64_to_cpu(dp->ldp_hash_end); - lhash = hash; - } - if (end == start) { - LASSERT(start == lhash); - CWARN("Page-wide hash collision: %llu\n", end); - if (BITS_PER_LONG == 32 && hash64) - CWARN("Real page-wide hash collision at [%llu %llu] with hash %llu\n", - le64_to_cpu(dp->ldp_hash_start), - le64_to_cpu(dp->ldp_hash_end), hash); - /* - * Fetch whole overflow chain... - * - * XXX not yet. - */ - goto fail; - } -out_unlock: - mutex_unlock(&lli->lli_readdir_mutex); - ldlm_lock_decref(&lockh, mode); - return page; - -fail: - ll_release_page(dir, page, true); - page = ERR_PTR(-EIO); - goto out_unlock; -} - /** * return IF_* type for given lu_dirent entry. * IF_* flag shld be converted to particular OS file type in diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index b4e843a..a5a3023 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -665,7 +665,7 @@ int ll_dir_read(struct inode *inode, __u64 *ppos, struct md_op_data *op_data, int ll_get_mdt_idx(struct inode *inode); int ll_get_mdt_idx_by_fid(struct ll_sb_info *sbi, const struct lu_fid *fid); struct page *ll_get_dir_page(struct inode *dir, struct md_op_data *op_data, - __u64 hash, struct ll_dir_chain *chain); + __u64 offset, struct ll_dir_chain *chain); void ll_release_page(struct inode *inode, struct page *page, bool remove); /* llite/namei.c */ diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c index 454c33e..dfd51af 100644 --- a/drivers/staging/lustre/lustre/llite/statahead.c +++ b/drivers/staging/lustre/lustre/llite/statahead.c @@ -1035,7 +1035,7 @@ static int ll_statahead_thread(void *arg) struct ll_statahead_info *sai = ll_sai_get(plli->lli_sai); struct ptlrpc_thread *thread = &sai->sai_thread; struct ptlrpc_thread *agl_thread = &sai->sai_agl_thread; - struct page *page; + struct page *page = NULL; __u64 pos = 0; int first = 0; int rc = 0; @@ -1166,8 +1166,7 @@ interpret_it: if (!list_empty(&sai->sai_entries_received)) goto interpret_it; - if (unlikely( - !thread_is_running(thread))) { + if (unlikely(!thread_is_running(thread))) { ll_release_page(dir, page, false); rc = 0; goto out; @@ -1182,10 +1181,10 @@ interpret_it: goto keep_it; } - do_it: ll_statahead_one(parent, name, namelen); } + pos = le64_to_cpu(dp->ldp_hash_end); if (pos == MDS_DIR_END_OFF) { /* @@ -1232,14 +1231,12 @@ do_it: * Normal case: continue to the next page. */ ll_release_page(dir, page, - le32_to_cpu(dp->ldp_flags) & - LDF_COLLIDE); + le32_to_cpu(dp->ldp_flags) & LDF_COLLIDE); sai->sai_in_readpage = 1; page = ll_get_dir_page(dir, op_data, pos, &chain); sai->sai_in_readpage = 0; } } - out: ll_finish_md_op_data(op_data); if (sai->sai_agl_valid) { @@ -1455,7 +1452,6 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry) page = ll_get_dir_page(dir, op_data, pos, &chain); } } - out: ll_dir_chain_fini(&chain); ll_finish_md_op_data(op_data); diff --git a/drivers/staging/lustre/lustre/mdc/mdc_internal.h b/drivers/staging/lustre/lustre/mdc/mdc_internal.h index 1901b93..492ebbc 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_internal.h +++ b/drivers/staging/lustre/lustre/mdc/mdc_internal.h @@ -135,4 +135,12 @@ static inline int mdc_prep_elc_req(struct obd_export *exp, count); } +static inline unsigned long hash_x_index(__u64 hash, int hash64) +{ + if (BITS_PER_LONG == 32 && hash64) + hash >>= 32; + /* save hash 0 with hash 1 */ + return ~0UL - (hash + !hash); +} + #endif diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 74ddec3..9ad855f 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -1019,6 +1019,536 @@ restart_bulk: return 0; } +static int mdc_getpage(struct obd_export *exp, const struct lu_fid *fid, + u64 offset, struct page **pages, int npages, + struct ptlrpc_request **request) +{ + struct ptlrpc_bulk_desc *desc; + struct ptlrpc_request *req; + wait_queue_head_t waitq; + struct l_wait_info lwi; + int resends = 0; + int rc; + int i; + + *request = NULL; + init_waitqueue_head(&waitq); + +restart_bulk: + req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_MDS_READPAGE); + if (!req) + return -ENOMEM; + + rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION, MDS_READPAGE); + if (rc) { + ptlrpc_request_free(req); + return rc; + } + + req->rq_request_portal = MDS_READPAGE_PORTAL; + ptlrpc_at_set_req_timeout(req); + + desc = ptlrpc_prep_bulk_imp(req, npages, 1, BULK_PUT_SINK, + MDS_BULK_PORTAL); + if (!desc) { + ptlrpc_request_free(req); + return -ENOMEM; + } + + /* NB req now owns desc and will free it when it gets freed */ + for (i = 0; i < npages; i++) + ptlrpc_prep_bulk_page_pin(desc, pages[i], 0, PAGE_SIZE); + + mdc_readdir_pack(req, offset, PAGE_SIZE * npages, fid); + + ptlrpc_request_set_replen(req); + rc = ptlrpc_queue_wait(req); + if (rc) { + ptlrpc_req_finished(req); + if (rc != -ETIMEDOUT) + return rc; + + resends++; + if (!client_should_resend(resends, &exp->exp_obd->u.cli)) { + CERROR("%s: too many resend retries: rc = %d\n", + exp->exp_obd->obd_name, -EIO); + return -EIO; + } + lwi = LWI_TIMEOUT_INTR(cfs_time_seconds(resends), NULL, NULL, + NULL); + l_wait_event(waitq, 0, &lwi); + + goto restart_bulk; + } + + rc = sptlrpc_cli_unwrap_bulk_read(req, req->rq_bulk, + req->rq_bulk->bd_nob_transferred); + if (rc < 0) { + ptlrpc_req_finished(req); + return rc; + } + + if (req->rq_bulk->bd_nob_transferred & ~LU_PAGE_MASK) { + CERROR("%s: unexpected bytes transferred: %d (%ld expected)\n", + exp->exp_obd->obd_name, req->rq_bulk->bd_nob_transferred, + PAGE_SIZE * npages); + ptlrpc_req_finished(req); + return -EPROTO; + } + + *request = req; + return 0; +} + +static void mdc_release_page(struct page *page, int remove) +{ + if (remove) { + lock_page(page); + if (likely(page->mapping)) + truncate_complete_page(page->mapping, page); + unlock_page(page); + } + put_page(page); +} + +static struct page *mdc_page_locate(struct address_space *mapping, __u64 *hash, + __u64 *start, __u64 *end, int hash64) +{ + /* + * Complement of hash is used as an index so that + * radix_tree_gang_lookup() can be used to find a page with starting + * hash _smaller_ than one we are looking for. + */ + unsigned long offset = hash_x_index(*hash, hash64); + struct page *page; + int found; + + spin_lock_irq(&mapping->tree_lock); + found = radix_tree_gang_lookup(&mapping->page_tree, + (void **)&page, offset, 1); + if (found > 0 && !radix_tree_exceptional_entry(page)) { + struct lu_dirpage *dp; + + get_page(page); + spin_unlock_irq(&mapping->tree_lock); + /* + * In contrast to find_lock_page() we are sure that directory + * page cannot be truncated (while DLM lock is held) and, + * hence, can avoid restart. + * + * In fact, page cannot be locked here at all, because + * mdc_read_page_remote does synchronous io. + */ + wait_on_page_locked(page); + if (PageUptodate(page)) { + dp = kmap(page); + if (BITS_PER_LONG == 32 && hash64) { + *start = le64_to_cpu(dp->ldp_hash_start) >> 32; + *end = le64_to_cpu(dp->ldp_hash_end) >> 32; + *hash = *hash >> 32; + } else { + *start = le64_to_cpu(dp->ldp_hash_start); + *end = le64_to_cpu(dp->ldp_hash_end); + } + if (unlikely(*start == 1 && *hash == 0)) + *hash = *start; + else + LASSERTF(*start <= *hash, "start = %#llx,end = %#llx,hash = %#llx\n", + *start, *end, *hash); + CDEBUG(D_VFSTRACE, "offset %lx [%#llx %#llx], hash %#llx\n", + offset, *start, *end, *hash); + if (*hash > *end) { + kunmap(page); + mdc_release_page(page, 0); + page = NULL; + } else if (*end != *start && *hash == *end) { + /* + * upon hash collision, remove this page, + * otherwise put page reference, and + * mdc_read_page_remote() will issue RPC to + * fetch the page we want. + */ + kunmap(page); + mdc_release_page(page, + le32_to_cpu(dp->ldp_flags) & LDF_COLLIDE); + page = NULL; + } + } else { + put_page(page); + page = ERR_PTR(-EIO); + } + } else { + spin_unlock_irq(&mapping->tree_lock); + page = NULL; + } + return page; +} + +/* + * Adjust a set of pages, each page containing an array of lu_dirpages, + * so that each page can be used as a single logical lu_dirpage. + * + * A lu_dirpage is laid out as follows, where s = ldp_hash_start, + * e = ldp_hash_end, f = ldp_flags, p = padding, and each "ent" is a + * struct lu_dirent. It has size up to LU_PAGE_SIZE. The ldp_hash_end + * value is used as a cookie to request the next lu_dirpage in a + * directory listing that spans multiple pages (two in this example): + * ________ + * | | + * .|--------v------- -----. + * |s|e|f|p|ent|ent| ... |ent| + * '--|-------------- -----' Each PAGE contains a single + * '------. lu_dirpage. + * .---------v------- -----. + * |s|e|f|p|ent| 0 | ... | 0 | + * '----------------- -----' + * + * However, on hosts where the native VM page size (PAGE_SIZE) is + * larger than LU_PAGE_SIZE, a single host page may contain multiple + * lu_dirpages. After reading the lu_dirpages from the MDS, the + * ldp_hash_end of the first lu_dirpage refers to the one immediately + * after it in the same PAGE (arrows simplified for brevity, but + * in general e0==s1, e1==s2, etc.): + * + * .-------------------- -----. + * |s0|e0|f0|p|ent|ent| ... |ent| + * |---v---------------- -----| + * |s1|e1|f1|p|ent|ent| ... |ent| + * |---v---------------- -----| Here, each PAGE contains + * ... multiple lu_dirpages. + * |---v---------------- -----| + * |s'|e'|f'|p|ent|ent| ... |ent| + * '---|---------------- -----' + * v + * .----------------------------. + * | next PAGE | + * + * This structure is transformed into a single logical lu_dirpage as follows: + * + * - Replace e0 with e' so the request for the next lu_dirpage gets the page + * labeled 'next PAGE'. + * + * - Copy the LDF_COLLIDE flag from f' to f0 to correctly reflect whether + * a hash collision with the next page exists. + * + * - Adjust the lde_reclen of the ending entry of each lu_dirpage to span + * to the first entry of the next lu_dirpage. + */ +#if PAGE_SIZE > LU_PAGE_SIZE +static void mdc_adjust_dirpages(struct page **pages, int cfs_pgs, int lu_pgs) +{ + int i; + + for (i = 0; i < cfs_pgs; i++) { + __u64 hash_end = le64_to_cpu(dp->ldp_hash_end); + __u32 flags = le32_to_cpu(dp->ldp_flags); + struct lu_dirpage *dp = kmap(pages[i]); + struct lu_dirpage *first = dp; + struct lu_dirent *end_dirent = NULL; + struct lu_dirent *ent; + + while (--lu_pgs > 0) { + ent = lu_dirent_start(dp); + for (end_dirent = ent; ent; + end_dirent = ent, ent = lu_dirent_next(ent)); + + /* Advance dp to next lu_dirpage. */ + dp = (struct lu_dirpage *)((char *)dp + LU_PAGE_SIZE); + + /* Check if we've reached the end of the CFS_PAGE. */ + if (!((unsigned long)dp & ~PAGE_MASK)) + break; + + /* Save the hash and flags of this lu_dirpage. */ + hash_end = le64_to_cpu(dp->ldp_hash_end); + flags = le32_to_cpu(dp->ldp_flags); + + /* Check if lu_dirpage contains no entries. */ + if (!end_dirent) + break; + + /* + * Enlarge the end entry lde_reclen from 0 to + * first entry of next lu_dirpage. + */ + LASSERT(!le16_to_cpu(end_dirent->lde_reclen)); + end_dirent->lde_reclen = + cpu_to_le16((char *)(dp->ldp_entries) - + (char *)end_dirent); + } + + first->ldp_hash_end = hash_end; + first->ldp_flags &= ~cpu_to_le32(LDF_COLLIDE); + first->ldp_flags |= flags & cpu_to_le32(LDF_COLLIDE); + + kunmap(pages[i]); + } + LASSERTF(lu_pgs == 0, "left = %d", lu_pgs); +} +#else +#define mdc_adjust_dirpages(pages, cfs_pgs, lu_pgs) do {} while (0) +#endif /* PAGE_SIZE > LU_PAGE_SIZE */ + +/* parameters for readdir page */ +struct readpage_param { + struct md_op_data *rp_mod; + __u64 rp_off; + int rp_hash64; + struct obd_export *rp_exp; + struct md_callback *rp_cb; +}; + +/** + * Read pages from server. + * + * Page in MDS_READPAGE RPC is packed in LU_PAGE_SIZE, and each page contains + * a header lu_dirpage which describes the start/end hash, and whether this + * page is empty (contains no dir entry) or hash collide with next page. + * After client receives reply, several pages will be integrated into dir page + * in PAGE_SIZE (if PAGE_SIZE greater than LU_PAGE_SIZE), and the + * lu_dirpage for this integrated page will be adjusted. + **/ +static int mdc_read_page_remote(void *data, struct page *page0) +{ + struct readpage_param *rp = data; + struct page **page_pool; + struct page *page; + struct lu_dirpage *dp; + int rd_pgs = 0; /* number of pages read actually */ + int npages; + struct md_op_data *op_data = rp->rp_mod; + struct ptlrpc_request *req; + int max_pages = op_data->op_max_pages; + struct inode *inode; + struct lu_fid *fid; + int i; + int rc; + + LASSERT(max_pages > 0 && max_pages <= PTLRPC_MAX_BRW_PAGES); + inode = op_data->op_data; + fid = &op_data->op_fid1; + LASSERT(inode); + + page_pool = kcalloc(max_pages, sizeof(page), GFP_NOFS); + if (page_pool) { + page_pool[0] = page0; + } else { + page_pool = &page0; + max_pages = 1; + } + + for (npages = 1; npages < max_pages; npages++) { + page = page_cache_alloc_cold(inode->i_mapping); + if (!page) + break; + page_pool[npages] = page; + } + + rc = mdc_getpage(rp->rp_exp, fid, rp->rp_off, page_pool, npages, &req); + if (!rc) { + int lu_pgs = req->rq_bulk->bd_nob_transferred; + + rd_pgs = (req->rq_bulk->bd_nob_transferred + + PAGE_SIZE - 1) >> PAGE_SHIFT; + lu_pgs >>= LU_PAGE_SHIFT; + LASSERT(!(req->rq_bulk->bd_nob_transferred & ~LU_PAGE_MASK)); + + CDEBUG(D_INODE, "read %d(%d)/%d pages\n", rd_pgs, lu_pgs, + op_data->op_npages); + + mdc_adjust_dirpages(page_pool, rd_pgs, lu_pgs); + + SetPageUptodate(page0); + } + + unlock_page(page0); + ptlrpc_req_finished(req); + CDEBUG(D_CACHE, "read %d/%d pages\n", rd_pgs, npages); + for (i = 1; i < npages; i++) { + unsigned long offset; + __u64 hash; + int ret; + + page = page_pool[i]; + + if (rc < 0 || i >= rd_pgs) { + put_page(page); + continue; + } + + SetPageUptodate(page); + + dp = kmap(page); + hash = le64_to_cpu(dp->ldp_hash_start); + kunmap(page); + + offset = hash_x_index(hash, rp->rp_hash64); + + prefetchw(&page->flags); + ret = add_to_page_cache_lru(page, inode->i_mapping, offset, + GFP_KERNEL); + if (!ret) + unlock_page(page); + else + CDEBUG(D_VFSTRACE, "page %lu add to page cache failed: rc = %d\n", + offset, ret); + put_page(page); + } + + if (page_pool != &page0) + kfree(page_pool); + + return rc; +} + +/** + * Read dir page from cache first, if it can not find it, read it from + * server and add into the cache. + * + * \param[in] exp MDC export + * \param[in] op_data client MD stack parameters, transferring parameters + * between different layers on client MD stack. + * \param[in] cb_op callback required for ldlm lock enqueue during + * read page + * \param[in] hash_offset the hash offset of the page to be read + * \param[in] ppage the page to be read + * + * retval = 0 get the page successfully + * errno(<0) get the page failed + */ +static int mdc_read_page(struct obd_export *exp, struct md_op_data *op_data, + struct md_callback *cb_op, __u64 hash_offset, + struct page **ppage) +{ + struct lookup_intent it = { .it_op = IT_READDIR }; + struct page *page; + struct inode *dir = op_data->op_data; + struct address_space *mapping; + struct lu_dirpage *dp; + __u64 start = 0; + __u64 end = 0; + struct lustre_handle lockh; + struct ptlrpc_request *enq_req = NULL; + struct readpage_param rp_param; + int rc; + + *ppage = NULL; + + LASSERT(dir); + mapping = dir->i_mapping; + + rc = mdc_intent_lock(exp, op_data, NULL, 0, &it, 0, &enq_req, + cb_op->md_blocking_ast, 0); + if (enq_req) + ptlrpc_req_finished(enq_req); + + if (rc < 0) { + CERROR("%s: "DFID" lock enqueue fails: rc = %d\n", + exp->exp_obd->obd_name, PFID(&op_data->op_fid1), rc); + return rc; + } + + rc = 0; + mdc_set_lock_data(exp, &it.it_lock_handle, dir, NULL); + + rp_param.rp_off = hash_offset; + rp_param.rp_hash64 = op_data->op_cli_flags & CLI_HASH64; + page = mdc_page_locate(mapping, &rp_param.rp_off, &start, &end, + rp_param.rp_hash64); + if (IS_ERR(page)) { + CERROR("%s: dir page locate: "DFID" at %llu: rc %ld\n", + exp->exp_obd->obd_name, PFID(&op_data->op_fid1), + rp_param.rp_off, PTR_ERR(page)); + rc = PTR_ERR(page); + goto out_unlock; + } else if (page) { + /* + * XXX nikita: not entirely correct handling of a corner case: + * suppose hash chain of entries with hash value HASH crosses + * border between pages P0 and P1. First both P0 and P1 are + * cached, seekdir() is called for some entry from the P0 part + * of the chain. Later P0 goes out of cache. telldir(HASH) + * happens and finds P1, as it starts with matching hash + * value. Remaining entries from P0 part of the chain are + * skipped. (Is that really a bug?) + * + * Possible solutions: 0. don't cache P1 is such case, handle + * it as an "overflow" page. 1. invalidate all pages at + * once. 2. use HASH|1 as an index for P1. + */ + goto hash_collision; + } + + rp_param.rp_exp = exp; + rp_param.rp_mod = op_data; + page = read_cache_page(mapping, + hash_x_index(rp_param.rp_off, + rp_param.rp_hash64), + mdc_read_page_remote, &rp_param); + if (IS_ERR(page)) { + CERROR("%s: read cache page: "DFID" at %llu: rc %ld\n", + exp->exp_obd->obd_name, PFID(&op_data->op_fid1), + rp_param.rp_off, PTR_ERR(page)); + rc = PTR_ERR(page); + goto out_unlock; + } + + wait_on_page_locked(page); + (void)kmap(page); + if (!PageUptodate(page)) { + CERROR("%s: page not updated: "DFID" at %llu: rc %d\n", + exp->exp_obd->obd_name, PFID(&op_data->op_fid1), + rp_param.rp_off, -5); + goto fail; + } + if (!PageChecked(page)) + SetPageChecked(page); + if (PageError(page)) { + CERROR("%s: page error: "DFID" at %llu: rc %d\n", + exp->exp_obd->obd_name, PFID(&op_data->op_fid1), + rp_param.rp_off, -5); + goto fail; + } + +hash_collision: + dp = page_address(page); + if (BITS_PER_LONG == 32 && rp_param.rp_hash64) { + start = le64_to_cpu(dp->ldp_hash_start) >> 32; + end = le64_to_cpu(dp->ldp_hash_end) >> 32; + rp_param.rp_off = hash_offset >> 32; + } else { + start = le64_to_cpu(dp->ldp_hash_start); + end = le64_to_cpu(dp->ldp_hash_end); + rp_param.rp_off = hash_offset; + } + if (end == start) { + LASSERT(start == rp_param.rp_off); + CWARN("Page-wide hash collision: %#lx\n", (unsigned long)end); +#if BITS_PER_LONG == 32 + CWARN("Real page-wide hash collision at [%llu %llu] with hash %llu\n", + le64_to_cpu(dp->ldp_hash_start), + le64_to_cpu(dp->ldp_hash_end), hash_offset); +#endif + /* + * Fetch whole overflow chain... + * + * XXX not yet. + */ + goto fail; + } + *ppage = page; +out_unlock: + lockh.cookie = it.it_lock_handle; + ldlm_lock_decref(&lockh, it.it_lock_mode); + it.it_lock_handle = 0; + return rc; +fail: + kunmap(page); + mdc_release_page(page, 1); + rc = -EIO; + goto out_unlock; +} + static int mdc_statfs(const struct lu_env *env, struct obd_export *exp, struct obd_statfs *osfs, __u64 max_age, __u32 flags) @@ -2450,6 +2980,7 @@ static struct md_ops mdc_md_ops = { .getxattr = mdc_getxattr, .sync = mdc_sync, .readpage = mdc_readpage, + .read_page = mdc_read_page, .unlink = mdc_unlink, .cancel_unused = mdc_cancel_unused, .init_ea_size = mdc_init_ea_size, -- cgit v0.10.2 From 5ef5ee255581f9322f69fe66659fcc8b45a991dd Mon Sep 17 00:00:00 2001 From: Jian Yu <jian.yu@intel.com> Date: Fri, 19 Aug 2016 14:07:27 -0400 Subject: staging: lustre: obd: remove unused lmv_readpages()/mdc_readpage() This patch fixes the following compile error by removing the dead codes: "error: 'xxx_readpages' defined but not used". Now that we have md_read_page functionality we can remove all the *_readpage implementations. Signed-off-by: Jian Yu <jian.yu@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4669 Reviewed-on: http://review.whamcloud.com/9810 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 1f01be4..44a334a 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -2223,151 +2223,6 @@ static int lmv_sync(struct obd_export *exp, const struct lu_fid *fid, return rc; } -/* - * Adjust a set of pages, each page containing an array of lu_dirpages, - * so that each page can be used as a single logical lu_dirpage. - * - * A lu_dirpage is laid out as follows, where s = ldp_hash_start, - * e = ldp_hash_end, f = ldp_flags, p = padding, and each "ent" is a - * struct lu_dirent. It has size up to LU_PAGE_SIZE. The ldp_hash_end - * value is used as a cookie to request the next lu_dirpage in a - * directory listing that spans multiple pages (two in this example): - * ________ - * | | - * .|--------v------- -----. - * |s|e|f|p|ent|ent| ... |ent| - * '--|-------------- -----' Each CFS_PAGE contains a single - * '------. lu_dirpage. - * .---------v------- -----. - * |s|e|f|p|ent| 0 | ... | 0 | - * '----------------- -----' - * - * However, on hosts where the native VM page size (PAGE_SIZE) is - * larger than LU_PAGE_SIZE, a single host page may contain multiple - * lu_dirpages. After reading the lu_dirpages from the MDS, the - * ldp_hash_end of the first lu_dirpage refers to the one immediately - * after it in the same CFS_PAGE (arrows simplified for brevity, but - * in general e0==s1, e1==s2, etc.): - * - * .-------------------- -----. - * |s0|e0|f0|p|ent|ent| ... |ent| - * |---v---------------- -----| - * |s1|e1|f1|p|ent|ent| ... |ent| - * |---v---------------- -----| Here, each CFS_PAGE contains - * ... multiple lu_dirpages. - * |---v---------------- -----| - * |s'|e'|f'|p|ent|ent| ... |ent| - * '---|---------------- -----' - * v - * .----------------------------. - * | next CFS_PAGE | - * - * This structure is transformed into a single logical lu_dirpage as follows: - * - * - Replace e0 with e' so the request for the next lu_dirpage gets the page - * labeled 'next CFS_PAGE'. - * - * - Copy the LDF_COLLIDE flag from f' to f0 to correctly reflect whether - * a hash collision with the next page exists. - * - * - Adjust the lde_reclen of the ending entry of each lu_dirpage to span - * to the first entry of the next lu_dirpage. - */ -#if PAGE_SIZE > LU_PAGE_SIZE -static void lmv_adjust_dirpages(struct page **pages, int ncfspgs, int nlupgs) -{ - int i; - - for (i = 0; i < ncfspgs; i++) { - struct lu_dirpage *dp = kmap(pages[i]); - struct lu_dirpage *first = dp; - struct lu_dirent *end_dirent = NULL; - struct lu_dirent *ent; - __u64 hash_end = dp->ldp_hash_end; - __u32 flags = dp->ldp_flags; - - while (--nlupgs > 0) { - ent = lu_dirent_start(dp); - for (end_dirent = ent; ent; - end_dirent = ent, ent = lu_dirent_next(ent)) - ; - - /* Advance dp to next lu_dirpage. */ - dp = (struct lu_dirpage *)((char *)dp + LU_PAGE_SIZE); - - /* Check if we've reached the end of the CFS_PAGE. */ - if (!((unsigned long)dp & ~PAGE_MASK)) - break; - - /* Save the hash and flags of this lu_dirpage. */ - hash_end = dp->ldp_hash_end; - flags = dp->ldp_flags; - - /* Check if lu_dirpage contains no entries. */ - if (!end_dirent) - break; - - /* Enlarge the end entry lde_reclen from 0 to - * first entry of next lu_dirpage. - */ - LASSERT(le16_to_cpu(end_dirent->lde_reclen) == 0); - end_dirent->lde_reclen = - cpu_to_le16((char *)(dp->ldp_entries) - - (char *)end_dirent); - } - - first->ldp_hash_end = hash_end; - first->ldp_flags &= ~cpu_to_le32(LDF_COLLIDE); - first->ldp_flags |= flags & cpu_to_le32(LDF_COLLIDE); - - kunmap(pages[i]); - } - LASSERTF(nlupgs == 0, "left = %d", nlupgs); -} -#else -#define lmv_adjust_dirpages(pages, ncfspgs, nlupgs) do {} while (0) -#endif /* PAGE_SIZE > LU_PAGE_SIZE */ - -static int lmv_readpage(struct obd_export *exp, struct md_op_data *op_data, - struct page **pages, struct ptlrpc_request **request) -{ - struct obd_device *obd = exp->exp_obd; - struct lmv_obd *lmv = &obd->u.lmv; - __u64 offset = op_data->op_offset; - int rc; - int ncfspgs; /* pages read in PAGE_SIZE */ - int nlupgs; /* pages read in LU_PAGE_SIZE */ - struct lmv_tgt_desc *tgt; - - rc = lmv_check_connect(obd); - if (rc) - return rc; - - CDEBUG(D_INODE, "READPAGE at %#llx from "DFID"\n", - offset, PFID(&op_data->op_fid1)); - - tgt = lmv_find_target(lmv, &op_data->op_fid1); - if (IS_ERR(tgt)) - return PTR_ERR(tgt); - - rc = md_readpage(tgt->ltd_exp, op_data, pages, request); - if (rc != 0) - return rc; - - ncfspgs = ((*request)->rq_bulk->bd_nob_transferred + PAGE_SIZE - 1) - >> PAGE_SHIFT; - nlupgs = (*request)->rq_bulk->bd_nob_transferred >> LU_PAGE_SHIFT; - LASSERT(!((*request)->rq_bulk->bd_nob_transferred & ~LU_PAGE_MASK)); - LASSERT(ncfspgs > 0 && ncfspgs <= op_data->op_npages); - - CDEBUG(D_INODE, "read %d(%d)/%d pages\n", ncfspgs, nlupgs, - op_data->op_npages); - - lmv_adjust_dirpages(pages, ncfspgs, nlupgs); - - return rc; -} - /** * Get current minimum entry from striped directory * @@ -3595,7 +3450,6 @@ static struct md_ops lmv_md_ops = { .setattr = lmv_setattr, .setxattr = lmv_setxattr, .sync = lmv_sync, - .readpage = lmv_readpage, .read_page = lmv_read_page, .unlink = lmv_unlink, .init_ea_size = lmv_init_ea_size, diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 9ad855f..5520819 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -938,87 +938,6 @@ static int mdc_done_writing(struct obd_export *exp, struct md_op_data *op_data, return rc; } -static int mdc_readpage(struct obd_export *exp, struct md_op_data *op_data, - struct page **pages, struct ptlrpc_request **request) -{ - struct ptlrpc_request *req; - struct ptlrpc_bulk_desc *desc; - int i; - wait_queue_head_t waitq; - int resends = 0; - struct l_wait_info lwi; - int rc; - - *request = NULL; - init_waitqueue_head(&waitq); - -restart_bulk: - req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_MDS_READPAGE); - if (!req) - return -ENOMEM; - - rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION, MDS_READPAGE); - if (rc) { - ptlrpc_request_free(req); - return rc; - } - - req->rq_request_portal = MDS_READPAGE_PORTAL; - ptlrpc_at_set_req_timeout(req); - - desc = ptlrpc_prep_bulk_imp(req, op_data->op_npages, 1, BULK_PUT_SINK, - MDS_BULK_PORTAL); - if (!desc) { - ptlrpc_request_free(req); - return -ENOMEM; - } - - /* NB req now owns desc and will free it when it gets freed */ - for (i = 0; i < op_data->op_npages; i++) - ptlrpc_prep_bulk_page_pin(desc, pages[i], 0, PAGE_SIZE); - - mdc_readdir_pack(req, op_data->op_offset, - PAGE_SIZE * op_data->op_npages, - &op_data->op_fid1); - - ptlrpc_request_set_replen(req); - rc = ptlrpc_queue_wait(req); - if (rc) { - ptlrpc_req_finished(req); - if (rc != -ETIMEDOUT) - return rc; - - resends++; - if (!client_should_resend(resends, &exp->exp_obd->u.cli)) { - CERROR("too many resend retries, returning error\n"); - return -EIO; - } - lwi = LWI_TIMEOUT_INTR(cfs_time_seconds(resends), - NULL, NULL, NULL); - l_wait_event(waitq, 0, &lwi); - - goto restart_bulk; - } - - rc = sptlrpc_cli_unwrap_bulk_read(req, req->rq_bulk, - req->rq_bulk->bd_nob_transferred); - if (rc < 0) { - ptlrpc_req_finished(req); - return rc; - } - - if (req->rq_bulk->bd_nob_transferred & ~LU_PAGE_MASK) { - CERROR("Unexpected # bytes transferred: %d (%ld expected)\n", - req->rq_bulk->bd_nob_transferred, - PAGE_SIZE * op_data->op_npages); - ptlrpc_req_finished(req); - return -EPROTO; - } - - *request = req; - return 0; -} - static int mdc_getpage(struct obd_export *exp, const struct lu_fid *fid, u64 offset, struct page **pages, int npages, struct ptlrpc_request **request) @@ -2979,7 +2898,6 @@ static struct md_ops mdc_md_ops = { .setxattr = mdc_setxattr, .getxattr = mdc_getxattr, .sync = mdc_sync, - .readpage = mdc_readpage, .read_page = mdc_read_page, .unlink = mdc_unlink, .cancel_unused = mdc_cancel_unused, -- cgit v0.10.2 From 4edc630ae98de2cf22310d49f8b012ab915dfaf4 Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Fri, 19 Aug 2016 14:07:28 -0400 Subject: staging: lustre: mdt: add OBD_CONNECT_DIR_STRIPE flag Add OBD_CONNECT_DIR_STRIPE to tell if the client supports striped dir, so only new client (>= 2.6) can access striped directory. Signed-off-by: wang di <di.wang@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4843 Reviewed-on: http://review.whamcloud.com/10773 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Bob Glossman <bob.glossman@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 9545451..c57231b 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -1291,6 +1291,7 @@ void lustre_swab_ptlrpc_body(struct ptlrpc_body *pb); */ #define OBD_CONNECT_LFSCK 0x40000000000000ULL/* support online LFSCK */ #define OBD_CONNECT_UNLINK_CLOSE 0x100000000000000ULL/* close file in unlink */ +#define OBD_CONNECT_DIR_STRIPE 0x400000000000000ULL/* striped DNE dir */ /* XXX README XXX: * Please DO NOT add flag values here before first ensuring that this same diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 64c8a2b..49ed3df 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -190,7 +190,8 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, OBD_CONNECT_MAX_EASIZE | OBD_CONNECT_FLOCK_DEAD | OBD_CONNECT_DISP_STRIPE | OBD_CONNECT_LFSCK | - OBD_CONNECT_OPEN_BY_FID; + OBD_CONNECT_OPEN_BY_FID | + OBD_CONNECT_DIR_STRIPE; if (sbi->ll_flags & LL_SBI_SOM_PREVIEW) data->ocd_connect_flags |= OBD_CONNECT_SOM; diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c index 45e3c4a..3d6da74 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c @@ -101,6 +101,8 @@ static const char * const obd_connect_names[] = { "unknown", "unlink_close", "unknown", + "dir_stripe", + "unknown", NULL }; diff --git a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c index b428528..3748f71 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c +++ b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c @@ -1075,6 +1075,8 @@ void lustre_assert_wire_constants(void) OBD_CONNECT_LFSCK); LASSERTF(OBD_CONNECT_UNLINK_CLOSE == 0x100000000000000ULL, "found 0x%.16llxULL\n", OBD_CONNECT_UNLINK_CLOSE); + LASSERTF(OBD_CONNECT_DIR_STRIPE == 0x400000000000000ULL, "found 0x%.16llxULL\n", + OBD_CONNECT_DIR_STRIPE); LASSERTF(OBD_CKSUM_CRC32 == 0x00000001UL, "found 0x%.8xUL\n", (unsigned)OBD_CKSUM_CRC32); LASSERTF(OBD_CKSUM_ADLER == 0x00000002UL, "found 0x%.8xUL\n", -- cgit v0.10.2 From 58c78cd2be958ffb97df6dd6dcef34e376162852 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Fri, 19 Aug 2016 14:07:29 -0400 Subject: staging: lustre: obd: remove dead code Remove unused OBD functions: oti_alloc_cookies(), oti_free_cookies(), class_observe_import(), class_unobserve_import(), md_is_subdir(), md_readpage(), obdo2fid(), fid2obdo(). Remove several unused, get-only, and set-only structure members. Signed-off-by: John L. Hammond <john.hammond@intel.com> Signed-off-by: James Simmons <uja.ornl@gmail.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2675 Reviewed-on: http://review.whamcloud.com/9784 Reviewed-by: Bob Glossman <bob.glossman@intel.com> Reviewed-by: Dmitry Eremin <dmitry.eremin@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index c57231b..35af07e 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -1937,8 +1937,8 @@ enum mds_cmd { MDS_DISCONNECT = 39, MDS_GETSTATUS = 40, MDS_STATFS = 41, - MDS_PIN = 42, - MDS_UNPIN = 43, + MDS_PIN = 42, /* obsolete, never used in a release */ + MDS_UNPIN = 43, /* obsolete, never used in a release */ MDS_SYNC = 44, MDS_DONE_WRITING = 45, MDS_SET_INFO = 46, @@ -1947,7 +1947,7 @@ enum mds_cmd { MDS_GETXATTR = 49, MDS_SETXATTR = 50, /* obsolete, now it's MDS_REINT op */ MDS_WRITEPAGE = 51, - MDS_IS_SUBDIR = 52, + MDS_IS_SUBDIR = 52, /* obsolete, never used in a release */ MDS_GET_INFO = 53, MDS_HSM_STATE_GET = 54, MDS_HSM_STATE_SET = 55, diff --git a/drivers/staging/lustre/lustre/include/lustre_import.h b/drivers/staging/lustre/lustre/include/lustre_import.h index 4445be7..b7a7a74 100644 --- a/drivers/staging/lustre/lustre/include/lustre_import.h +++ b/drivers/staging/lustre/lustre/include/lustre_import.h @@ -305,28 +305,6 @@ struct obd_import { time64_t imp_last_reply_time; /* for health check */ }; -typedef void (*obd_import_callback)(struct obd_import *imp, void *closure, - int event, void *event_arg, void *cb_data); - -/** - * Structure for import observer. - * It is possible to register "observer" on an import and every time - * something happens to an import (like connect/evict/disconnect) - * obderver will get its callback called with event type - */ -struct obd_import_observer { - struct list_head oio_chain; - obd_import_callback oio_cb; - void *oio_cb_data; -}; - -void class_observe_import(struct obd_import *imp, obd_import_callback cb, - void *cb_data); -void class_unobserve_import(struct obd_import *imp, obd_import_callback cb, - void *cb_data); -void class_notify_import_observers(struct obd_import *imp, int event, - void *event_arg); - /* import.c */ static inline unsigned int at_est2timeout(unsigned int val) { diff --git a/drivers/staging/lustre/lustre/include/lustre_log.h b/drivers/staging/lustre/lustre/include/lustre_log.h index b96e023..995b266 100644 --- a/drivers/staging/lustre/lustre/include/lustre_log.h +++ b/drivers/staging/lustre/lustre/include/lustre_log.h @@ -277,12 +277,11 @@ static inline void llog_ctxt_put(struct llog_ctxt *ctxt) __llog_ctxt_put(NULL, ctxt); } -static inline void llog_group_init(struct obd_llog_group *olg, int group) +static inline void llog_group_init(struct obd_llog_group *olg) { init_waitqueue_head(&olg->olg_waitq); spin_lock_init(&olg->olg_lock); mutex_init(&olg->olg_cat_processing); - olg->olg_seq = group; } static inline int llog_group_set_ctxt(struct obd_llog_group *olg, diff --git a/drivers/staging/lustre/lustre/include/lustre_req_layout.h b/drivers/staging/lustre/lustre/include/lustre_req_layout.h index 544a43c..ca0e683 100644 --- a/drivers/staging/lustre/lustre/include/lustre_req_layout.h +++ b/drivers/staging/lustre/lustre/include/lustre_req_layout.h @@ -149,14 +149,11 @@ extern struct req_format RQF_MDS_GETATTR; extern struct req_format RQF_MDS_GETATTR_NAME; extern struct req_format RQF_MDS_CLOSE; extern struct req_format RQF_MDS_RELEASE_CLOSE; -extern struct req_format RQF_MDS_PIN; -extern struct req_format RQF_MDS_UNPIN; extern struct req_format RQF_MDS_CONNECT; extern struct req_format RQF_MDS_DISCONNECT; extern struct req_format RQF_MDS_GET_INFO; extern struct req_format RQF_MDS_READPAGE; extern struct req_format RQF_MDS_WRITEPAGE; -extern struct req_format RQF_MDS_IS_SUBDIR; extern struct req_format RQF_MDS_DONE_WRITING; extern struct req_format RQF_MDS_REINT; extern struct req_format RQF_MDS_REINT_CREATE; diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 92eebff..6fc0bcc 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -243,7 +243,6 @@ struct client_obd { * the extent size. A chunk is max(PAGE_SIZE, OST block size) */ int cl_chunkbits; - int cl_chunk; int cl_extent_tax; /* extent overhead, by bytes */ /* keep track of objects that have lois that contain pages which @@ -442,7 +441,6 @@ struct niobuf_local { __u32 flags; struct page *page; struct dentry *dentry; - int lnb_grant_used; int rc; }; @@ -485,7 +483,6 @@ struct niobuf_local { #define N_LOCAL_TEMP_PAGE 0x10000000 struct obd_trans_info { - __u64 oti_transno; __u64 oti_xid; /* Only used on the server side for tracking acks. */ struct oti_req_ack_lock { @@ -495,50 +492,11 @@ struct obd_trans_info { void *oti_handle; struct llog_cookie oti_onecookie; struct llog_cookie *oti_logcookies; - int oti_numcookies; - /** synchronous write is needed */ - unsigned long oti_sync_write:1; - /* initial thread handling transaction */ - struct ptlrpc_thread *oti_thread; - __u32 oti_conn_cnt; /** VBR: versions */ __u64 oti_pre_version; - /** JobID */ - char *oti_jobid; - - struct obd_uuid *oti_ost_uuid; }; -static inline void oti_alloc_cookies(struct obd_trans_info *oti, - int num_cookies) -{ - if (!oti) - return; - - if (num_cookies == 1) - oti->oti_logcookies = &oti->oti_onecookie; - else - oti->oti_logcookies = libcfs_kvzalloc(num_cookies * sizeof(oti->oti_onecookie), - GFP_NOFS); - - oti->oti_numcookies = num_cookies; -} - -static inline void oti_free_cookies(struct obd_trans_info *oti) -{ - if (!oti || !oti->oti_logcookies) - return; - - if (oti->oti_logcookies == &oti->oti_onecookie) - LASSERT(oti->oti_numcookies == 1); - else - kvfree(oti->oti_logcookies); - - oti->oti_logcookies = NULL; - oti->oti_numcookies = 0; -} - /* * Events signalled through obd_notify() upcall-chain. */ @@ -584,7 +542,6 @@ struct target_recovery_data { }; struct obd_llog_group { - int olg_seq; struct llog_ctxt *olg_ctxts[LLOG_MAX_CTXTS]; wait_queue_head_t olg_waitq; spinlock_t olg_lock; @@ -620,7 +577,6 @@ struct obd_device { obd_starting:1, /* started setup */ obd_force:1, /* cleanup with > 0 obd refcount */ obd_fail:1, /* cleanup with failover */ - obd_async_recov:1, /* allow asynchronous orphan cleanup */ obd_no_conn:1, /* deny new connections */ obd_inactive:1, /* device active/inactive * (for sysfs status only!!) @@ -695,9 +651,6 @@ struct obd_device { struct completion obd_kobj_unregister; }; -#define OBD_LLOG_FL_SENDNOW 0x0001 -#define OBD_LLOG_FL_EXIT 0x0002 - enum obd_cleanup_stage { /* Special case hack for MDS LOVs */ OBD_CLEANUP_EARLY, @@ -707,8 +660,6 @@ enum obd_cleanup_stage { /* get/set_info keys */ #define KEY_ASYNC "async" -#define KEY_BLOCKSIZE_BITS "blocksize_bits" -#define KEY_BLOCKSIZE "blocksize" #define KEY_CHANGELOG_CLEAR "changelog_clear" #define KEY_FID2PATH "fid2path" #define KEY_CHECKSUM "checksum" @@ -720,13 +671,11 @@ enum obd_cleanup_stage { #define KEY_GRANT_SHRINK "grant_shrink" #define KEY_HSM_COPYTOOL_SEND "hsm_send" #define KEY_INIT_RECOV_BACKUP "init_recov_bk" -#define KEY_INIT_RECOV "initial_recov" #define KEY_INTERMDS "inter_mds" #define KEY_LAST_ID "last_id" #define KEY_LAST_FID "last_fid" #define KEY_LOCK_TO_STRIPE "lock_to_stripe" #define KEY_LOVDESC "lovdesc" -#define KEY_LOV_IDX "lov_idx" #define KEY_MAX_EASIZE "max_easize" #define KEY_DEFAULT_EASIZE "default_easize" #define KEY_MDS_CONN "mds_conn" @@ -739,11 +688,9 @@ enum obd_cleanup_stage { /* KEY_SET_INFO in lustre_idl.h */ #define KEY_SPTLRPC_CONF "sptlrpc_conf" #define KEY_CONNECT_FLAG "connect_flags" -#define KEY_SYNC_LOCK_CANCEL "sync_lock_cancel" #define KEY_CACHE_SET "cache_set" #define KEY_CACHE_LRU_SHRINK "cache_lru_shrink" -#define KEY_CHANGELOG_INDEX "changelog_index" struct lu_context; @@ -872,8 +819,6 @@ struct obd_ops { __u32 keylen, void *key, __u32 vallen, void *val, struct ptlrpc_request_set *set); - int (*attach)(struct obd_device *dev, u32 len, void *data); - int (*detach)(struct obd_device *dev); int (*setup)(struct obd_device *dev, struct lustre_cfg *cfg); int (*precleanup)(struct obd_device *dev, enum obd_cleanup_stage cleanup_stage); @@ -1038,16 +983,11 @@ struct md_ops { int (*rename)(struct obd_export *, struct md_op_data *, const char *, int, const char *, int, struct ptlrpc_request **); - int (*is_subdir)(struct obd_export *, const struct lu_fid *, - const struct lu_fid *, - struct ptlrpc_request **); int (*setattr)(struct obd_export *, struct md_op_data *, void *, int, void *, int, struct ptlrpc_request **, struct md_open_data **mod); int (*sync)(struct obd_export *, const struct lu_fid *, struct ptlrpc_request **); - int (*readpage)(struct obd_export *, struct md_op_data *, - struct page **, struct ptlrpc_request **); int (*read_page)(struct obd_export *, struct md_op_data *, struct md_callback *cb_op, __u64 hash_offset, struct page **ppage); @@ -1141,10 +1081,6 @@ static inline const struct lsm_operations *lsm_op_find(int magic) } } -/* Requests for obd_extent_calc() */ -#define OBD_CALC_STRIPE_START 1 -#define OBD_CALC_STRIPE_END 2 - static inline struct md_open_data *obd_mod_alloc(void) { struct md_open_data *mod; diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index daca5a0..fe1af94 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -56,7 +56,6 @@ #define OBD_STATFS_FOR_MDT0 0x0008 /* The statfs is only for retrieving * information from MDT0. */ -#define OBD_FL_PUNCH 0x00000001 /* To indicate it is punch operation */ /* OBD Device Declarations */ extern struct obd_device *obd_devs[MAX_OBD_DEVICES]; @@ -270,10 +269,10 @@ static inline int lprocfs_climp_check(struct obd_device *obd) struct inode; struct lu_attr; struct obdo; -void obdo_refresh_inode(struct inode *dst, struct obdo *src, u32 valid); +void obdo_refresh_inode(struct inode *dst, const struct obdo *src, u32 valid); -void obdo_to_ioobj(struct obdo *oa, struct obd_ioobj *ioobj); -void md_from_obdo(struct md_op_data *op_data, struct obdo *oa, u32 valid); +void obdo_to_ioobj(const struct obdo *oa, struct obd_ioobj *ioobj); +void md_from_obdo(struct md_op_data *op_data, const struct obdo *oa, u32 valid); #define OBT(dev) (dev)->obd_type #define OBP(dev, op) (dev)->obd_type->typ_dt_ops->op @@ -1216,12 +1215,7 @@ static inline int obd_notify(struct obd_device *obd, if (rc) return rc; - /* the check for async_recov is a complete hack - I'm hereby - * overloading the meaning to also mean "this was called from - * mds_postsetup". I know that my mds is able to handle notifies - * by this point, and it needs to get them to execute mds_postrecov. - */ - if (!obd->obd_set_up && !obd->obd_async_recov) { + if (!obd->obd_set_up) { CDEBUG(D_HA, "obd %s not set up\n", obd->obd_name); return -EINVAL; } @@ -1485,19 +1479,6 @@ static inline int md_rename(struct obd_export *exp, struct md_op_data *op_data, return rc; } -static inline int md_is_subdir(struct obd_export *exp, - const struct lu_fid *pfid, - const struct lu_fid *cfid, - struct ptlrpc_request **request) -{ - int rc; - - EXP_CHECK_MD_OP(exp, is_subdir); - EXP_MD_COUNTER_INCREMENT(exp, is_subdir); - rc = MDP(exp->exp_obd, is_subdir)(exp, pfid, cfid, request); - return rc; -} - static inline int md_setattr(struct obd_export *exp, struct md_op_data *op_data, void *ea, int ealen, void *ea2, int ea2len, struct ptlrpc_request **request, @@ -1523,18 +1504,6 @@ static inline int md_sync(struct obd_export *exp, const struct lu_fid *fid, return rc; } -static inline int md_readpage(struct obd_export *exp, struct md_op_data *opdata, - struct page **pages, - struct ptlrpc_request **request) -{ - int rc; - - EXP_CHECK_MD_OP(exp, readpage); - EXP_MD_COUNTER_INCREMENT(exp, readpage); - rc = MDP(exp->exp_obd, readpage)(exp, opdata, pages, request); - return rc; -} - static inline int md_read_page(struct obd_export *exp, struct md_op_data *op_data, struct md_callback *cb_op, @@ -1735,16 +1704,6 @@ void obd_cleanup_caches(void); /* support routines */ extern struct kmem_cache *obdo_cachep; -static inline void obdo2fid(struct obdo *oa, struct lu_fid *fid) -{ - /* something here */ -} - -static inline void fid2obdo(struct lu_fid *fid, struct obdo *oa) -{ - /* something here */ -} - typedef int (*register_lwp_cb)(void *data); struct lwp_register_item { diff --git a/drivers/staging/lustre/lustre/include/obd_support.h b/drivers/staging/lustre/lustre/include/obd_support.h index f747bca..5ef798f 100644 --- a/drivers/staging/lustre/lustre/include/obd_support.h +++ b/drivers/staging/lustre/lustre/include/obd_support.h @@ -52,7 +52,6 @@ extern unsigned int at_max; extern unsigned int at_history; extern int at_early_margin; extern int at_extra; -extern unsigned int obd_sync_filter; extern unsigned int obd_max_dirty_pages; extern atomic_t obd_dirty_pages; extern atomic_t obd_dirty_transit_pages; diff --git a/drivers/staging/lustre/lustre/mdc/mdc_internal.h b/drivers/staging/lustre/lustre/mdc/mdc_internal.h index 492ebbc..f4d0c36 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_internal.h +++ b/drivers/staging/lustre/lustre/mdc/mdc_internal.h @@ -39,8 +39,6 @@ void lprocfs_mdc_init_vars(struct lprocfs_static_vars *lvars); void mdc_pack_body(struct ptlrpc_request *req, const struct lu_fid *fid, __u64 valid, int ea_size, __u32 suppgid, int flags); -void mdc_is_subdir_pack(struct ptlrpc_request *req, const struct lu_fid *pfid, - const struct lu_fid *cfid, int flags); void mdc_swap_layouts_pack(struct ptlrpc_request *req, struct md_op_data *op_data); void mdc_readdir_pack(struct ptlrpc_request *req, __u64 pgoff, __u32 size, diff --git a/drivers/staging/lustre/lustre/mdc/mdc_lib.c b/drivers/staging/lustre/lustre/mdc/mdc_lib.c index aa496f3..ecfe13e 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_lib.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_lib.c @@ -45,21 +45,6 @@ static void __mdc_pack_body(struct mdt_body *b, __u32 suppgid) b->mbo_capability = cfs_curproc_cap_pack(); } -void mdc_is_subdir_pack(struct ptlrpc_request *req, const struct lu_fid *pfid, - const struct lu_fid *cfid, int flags) -{ - struct mdt_body *b = req_capsule_client_get(&req->rq_pill, - &RMF_MDT_BODY); - - if (pfid) { - b->mbo_fid1 = *pfid; - b->mbo_valid = OBD_MD_FLID; - } - if (cfid) - b->mbo_fid2 = *cfid; - b->mbo_flags = flags; -} - void mdc_swap_layouts_pack(struct ptlrpc_request *req, struct md_op_data *op_data) { diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 5520819..213f31b 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -232,32 +232,6 @@ static int mdc_getattr_name(struct obd_export *exp, struct md_op_data *op_data, return rc; } -static int mdc_is_subdir(struct obd_export *exp, - const struct lu_fid *pfid, - const struct lu_fid *cfid, - struct ptlrpc_request **request) -{ - struct ptlrpc_request *req; - int rc; - - *request = NULL; - req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp), - &RQF_MDS_IS_SUBDIR, LUSTRE_MDS_VERSION, - MDS_IS_SUBDIR); - if (!req) - return -ENOMEM; - - mdc_is_subdir_pack(req, pfid, cfid, 0); - ptlrpc_request_set_replen(req); - - rc = ptlrpc_queue_wait(req); - if (rc && rc != -EREMOTE) - ptlrpc_req_finished(req); - else - *request = req; - return rc; -} - static int mdc_xattr_common(struct obd_export *exp, const struct req_format *fmt, const struct lu_fid *fid, @@ -2892,7 +2866,6 @@ static struct md_ops mdc_md_ops = { .getattr_name = mdc_getattr_name, .intent_lock = mdc_intent_lock, .link = mdc_link, - .is_subdir = mdc_is_subdir, .rename = mdc_rename, .setattr = mdc_setattr, .setxattr = mdc_setxattr, diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c index 90a365b..6700167 100644 --- a/drivers/staging/lustre/lustre/obdclass/class_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c @@ -115,19 +115,6 @@ int lustre_get_jobid(char *jobid) } EXPORT_SYMBOL(lustre_get_jobid); -static inline void obd_data2conn(struct lustre_handle *conn, - struct obd_ioctl_data *data) -{ - memset(conn, 0, sizeof(*conn)); - conn->cookie = data->ioc_cookie; -} - -static inline void obd_conn2data(struct obd_ioctl_data *data, - struct lustre_handle *conn) -{ - data->ioc_cookie = conn->cookie; -} - static int class_resolve_dev_name(__u32 len, const char *name) { int rc; @@ -534,23 +521,11 @@ static int __init obdclass_init(void) static void obdclass_exit(void) { - int i; - int lustre_unregister_fs(void); lustre_unregister_fs(); misc_deregister(&obd_psdev); - for (i = 0; i < class_devno_max(); i++) { - struct obd_device *obd = class_num2obd(i); - - if (obd && obd->obd_set_up && - OBT(obd) && OBP(obd, detach)) { - /* XXX should this call generic detach otherwise? */ - LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC); - OBP(obd, detach)(obd); - } - } llog_info_fini(); cl_global_fini(); lu_global_fini(); diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-obdo.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-obdo.c index c6cc6a7..41b77a3 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-obdo.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-obdo.c @@ -44,7 +44,7 @@ #include <linux/fs.h> -void obdo_refresh_inode(struct inode *dst, struct obdo *src, u32 valid) +void obdo_refresh_inode(struct inode *dst, const struct obdo *src, u32 valid) { valid &= src->o_valid; diff --git a/drivers/staging/lustre/lustre/obdclass/obd_config.c b/drivers/staging/lustre/lustre/obdclass/obd_config.c index 6d0890f..01034b5 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_config.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_config.c @@ -238,7 +238,7 @@ static int class_attach(struct lustre_cfg *lcfg) /* recovery data */ init_waitqueue_head(&obd->obd_evict_inprogress_waitq); - llog_group_init(&obd->obd_olg, FID_SEQ_LLOG); + llog_group_init(&obd->obd_olg); obd->obd_conn_inprogress = 0; @@ -251,15 +251,6 @@ static int class_attach(struct lustre_cfg *lcfg) } memcpy(obd->obd_uuid.uuid, uuid, len); - /* do the attach */ - if (OBP(obd, attach)) { - rc = OBP(obd, attach)(obd, sizeof(*lcfg), lcfg); - if (rc) { - rc = -EINVAL; - goto out; - } - } - /* Detach drops this */ spin_lock(&obd->obd_dev_lock); atomic_set(&obd->obd_refcount, 1); @@ -527,11 +518,6 @@ void class_decref(struct obd_device *obd, const char *scope, const void *source) CERROR("Cleanup %s returned %d\n", obd->obd_name, err); } - if (OBP(obd, detach)) { - err = OBP(obd, detach)(obd); - if (err) - CERROR("Detach returned %d\n", err); - } class_release_dev(obd); } } diff --git a/drivers/staging/lustre/lustre/obdclass/obdo.c b/drivers/staging/lustre/lustre/obdclass/obdo.c index 8583a4a..4454764 100644 --- a/drivers/staging/lustre/lustre/obdclass/obdo.c +++ b/drivers/staging/lustre/lustre/obdclass/obdo.c @@ -112,7 +112,7 @@ void obdo_from_inode(struct obdo *dst, struct inode *src, u32 valid) } EXPORT_SYMBOL(obdo_from_inode); -void obdo_to_ioobj(struct obdo *oa, struct obd_ioobj *ioobj) +void obdo_to_ioobj(const struct obdo *oa, struct obd_ioobj *ioobj) { ioobj->ioo_oid = oa->o_oi; if (unlikely(!(oa->o_valid & OBD_MD_FLGROUP))) @@ -125,7 +125,8 @@ void obdo_to_ioobj(struct obdo *oa, struct obd_ioobj *ioobj) } EXPORT_SYMBOL(obdo_to_ioobj); -static void iattr_from_obdo(struct iattr *attr, struct obdo *oa, u32 valid) +static void iattr_from_obdo(struct iattr *attr, const struct obdo *oa, + u32 valid) { valid &= oa->o_valid; @@ -173,7 +174,7 @@ static void iattr_from_obdo(struct iattr *attr, struct obdo *oa, u32 valid) } } -void md_from_obdo(struct md_op_data *op_data, struct obdo *oa, u32 valid) +void md_from_obdo(struct md_op_data *op_data, const struct obdo *oa, u32 valid) { iattr_from_obdo(&op_data->op_attr, oa, valid); if (valid & OBD_MD_FLBLOCKS) { diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index 2cb487b..7527112 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -1443,7 +1443,6 @@ static int echo_client_prep_commit(const struct lu_env *env, } ioo.ioo_bufcnt = npages; - oti->oti_transno = 0; lpages = npages; ret = obd_preprw(env, rw, exp, oa, 1, &ioo, rnb, &lpages, diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index c618337..2a4056a 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -498,14 +498,10 @@ static int osc_real_create(struct obd_export *exp, struct obdo *oa, lsm->lsm_oi = oa->o_oi; *ea = lsm; - if (oti) { - oti->oti_transno = lustre_msg_get_transno(req->rq_repmsg); - - if (oa->o_valid & OBD_MD_FLCOOKIE) { - if (!oti->oti_logcookies) - oti_alloc_cookies(oti, 1); - *oti->oti_logcookies = oa->o_lcookie; - } + if (oti && oa->o_valid & OBD_MD_FLCOOKIE) { + if (!oti->oti_logcookies) + oti->oti_logcookies = &oti->oti_onecookie; + *oti->oti_logcookies = oa->o_lcookie; } CDEBUG(D_HA, "transno: %lld\n", diff --git a/drivers/staging/lustre/lustre/ptlrpc/layout.c b/drivers/staging/lustre/lustre/ptlrpc/layout.c index ab5d851..101ac87 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/layout.c +++ b/drivers/staging/lustre/lustre/ptlrpc/layout.c @@ -667,11 +667,8 @@ static struct req_format *req_formats[] = { &RQF_MDS_SYNC, &RQF_MDS_CLOSE, &RQF_MDS_RELEASE_CLOSE, - &RQF_MDS_PIN, - &RQF_MDS_UNPIN, &RQF_MDS_READPAGE, &RQF_MDS_WRITEPAGE, - &RQF_MDS_IS_SUBDIR, &RQF_MDS_DONE_WRITING, &RQF_MDS_REINT, &RQF_MDS_REINT_CREATE, @@ -1389,15 +1386,6 @@ struct req_format RQF_MDS_RELEASE_CLOSE = mdt_release_close_client, mds_last_unlink_server); EXPORT_SYMBOL(RQF_MDS_RELEASE_CLOSE); -struct req_format RQF_MDS_PIN = - DEFINE_REQ_FMT0("MDS_PIN", - mdt_body_capa, mdt_body_only); -EXPORT_SYMBOL(RQF_MDS_PIN); - -struct req_format RQF_MDS_UNPIN = - DEFINE_REQ_FMT0("MDS_UNPIN", mdt_body_only, empty); -EXPORT_SYMBOL(RQF_MDS_UNPIN); - struct req_format RQF_MDS_DONE_WRITING = DEFINE_REQ_FMT0("MDS_DONE_WRITING", mdt_close_client, mdt_body_only); @@ -1448,11 +1436,6 @@ struct req_format RQF_MDS_WRITEPAGE = mdt_body_capa, mdt_body_only); EXPORT_SYMBOL(RQF_MDS_WRITEPAGE); -struct req_format RQF_MDS_IS_SUBDIR = - DEFINE_REQ_FMT0("MDS_IS_SUBDIR", - mdt_body_only, mdt_body_only); -EXPORT_SYMBOL(RQF_MDS_IS_SUBDIR); - struct req_format RQF_LLOG_ORIGIN_HANDLE_CREATE = DEFINE_REQ_FMT0("LLOG_ORIGIN_HANDLE_CREATE", llog_origin_handle_create_client, llogd_body_only); -- cgit v0.10.2 From 70a251f68dea16eab3c502261f3a2e957751e2ab Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Fri, 19 Aug 2016 14:07:30 -0400 Subject: staging: lustre: obd: decruft md_enqueue() and md_intent_lock() Remove the lmm and lmmsize parameters from both functions, storing that data in md_op_data when needed. Remove the unused lookup_flags parameter from md_intent_lock(), and the unused reqp parameter from md_enqueue(). Add a union ldlm_policy_data * parameter to md_enqueue(). Remove the unused function lmv_enqueue_remote(). Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2675 Reviewed-on: http://review.whamcloud.com/10205 Reviewed-by: wangdi <di.wang@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 6fc0bcc..ac620fd 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -747,6 +747,7 @@ struct md_op_data { __u32 op_fsgid; cfs_cap_t op_cap; void *op_data; + size_t op_data_size; /* iattr fields and blocks. */ struct iattr op_attr; @@ -967,15 +968,15 @@ struct md_ops { int (*done_writing)(struct obd_export *, struct md_op_data *, struct md_open_data *); int (*enqueue)(struct obd_export *, struct ldlm_enqueue_info *, + const ldlm_policy_data_t *, struct lookup_intent *, struct md_op_data *, - struct lustre_handle *, void *, int, - struct ptlrpc_request **, __u64); + struct lustre_handle *, __u64); int (*getattr)(struct obd_export *, struct md_op_data *, struct ptlrpc_request **); int (*getattr_name)(struct obd_export *, struct md_op_data *, struct ptlrpc_request **); int (*intent_lock)(struct obd_export *, struct md_op_data *, - void *, int, struct lookup_intent *, int, + struct lookup_intent *, struct ptlrpc_request **, ldlm_blocking_callback, __u64); int (*link)(struct obd_export *, struct md_op_data *, diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index fe1af94..79fc041 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -1410,19 +1410,18 @@ static inline int md_done_writing(struct obd_export *exp, static inline int md_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo, + const ldlm_policy_data_t *policy, struct lookup_intent *it, struct md_op_data *op_data, struct lustre_handle *lockh, - void *lmm, int lmmsize, - struct ptlrpc_request **req, __u64 extra_lock_flags) { int rc; EXP_CHECK_MD_OP(exp, enqueue); EXP_MD_COUNTER_INCREMENT(exp, enqueue); - rc = MDP(exp->exp_obd, enqueue)(exp, einfo, it, op_data, lockh, - lmm, lmmsize, req, extra_lock_flags); + rc = MDP(exp->exp_obd, enqueue)(exp, einfo, policy, it, op_data, lockh, + extra_lock_flags); return rc; } @@ -1439,9 +1438,9 @@ static inline int md_getattr_name(struct obd_export *exp, } static inline int md_intent_lock(struct obd_export *exp, - struct md_op_data *op_data, void *lmm, - int lmmsize, struct lookup_intent *it, - int lookup_flags, struct ptlrpc_request **reqp, + struct md_op_data *op_data, + struct lookup_intent *it, + struct ptlrpc_request **reqp, ldlm_blocking_callback cb_blocking, __u64 extra_lock_flags) { @@ -1449,9 +1448,8 @@ static inline int md_intent_lock(struct obd_export *exp, EXP_CHECK_MD_OP(exp, intent_lock); EXP_MD_COUNTER_INCREMENT(exp, intent_lock); - rc = MDP(exp->exp_obd, intent_lock)(exp, op_data, lmm, lmmsize, - it, lookup_flags, reqp, cb_blocking, - extra_lock_flags); + rc = MDP(exp->exp_obd, intent_lock)(exp, op_data, it, reqp, + cb_blocking, extra_lock_flags); return rc; } diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 015b0ab..b680618 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -387,7 +387,7 @@ static int ll_intent_file_open(struct dentry *de, void *lmm, int lmmsize, struct dentry *parent = de->d_parent; const char *name = NULL; struct md_op_data *op_data; - struct ptlrpc_request *req; + struct ptlrpc_request *req = NULL; int len = 0, rc; LASSERT(parent); @@ -407,9 +407,11 @@ static int ll_intent_file_open(struct dentry *de, void *lmm, int lmmsize, O_RDWR, LUSTRE_OPC_ANY, NULL); if (IS_ERR(op_data)) return PTR_ERR(op_data); + op_data->op_data = lmm; + op_data->op_data_size = lmmsize; - rc = md_intent_lock(sbi->ll_md_exp, op_data, lmm, lmmsize, itp, - 0 /*unused */, &req, ll_md_blocking_ast, 0); + rc = md_intent_lock(sbi->ll_md_exp, op_data, itp, &req, + &ll_md_blocking_ast, 0); ll_finish_md_op_data(op_data); if (rc == -ESTALE) { /* reason for keep own exit path - don`t flood log @@ -759,7 +761,7 @@ ll_lease_open(struct inode *inode, struct file *file, fmode_t fmode, struct lookup_intent it = { .it_op = IT_OPEN }; struct ll_sb_info *sbi = ll_i2sbi(inode); struct md_op_data *op_data; - struct ptlrpc_request *req; + struct ptlrpc_request *req = NULL; struct lustre_handle old_handle = { 0 }; struct obd_client_handle *och = NULL; int rc; @@ -826,8 +828,8 @@ ll_lease_open(struct inode *inode, struct file *file, fmode_t fmode, it.it_flags = fmode | open_flags; it.it_flags |= MDS_OPEN_LOCK | MDS_OPEN_BY_FID | MDS_OPEN_LEASE; - rc = md_intent_lock(sbi->ll_md_exp, op_data, NULL, 0, &it, 0, &req, - ll_md_blocking_lease_ast, + rc = md_intent_lock(sbi->ll_md_exp, op_data, &it, &req, + &ll_md_blocking_lease_ast, /* LDLM_FL_NO_LRU: To not put the lease lock into LRU list, otherwise * it can be cancelled which may mislead applications that the lease is * broken; @@ -835,7 +837,7 @@ ll_lease_open(struct inode *inode, struct file *file, fmode_t fmode, * open in ll_md_blocking_ast(). Otherwise as ll_md_blocking_lease_ast * doesn't deal with openhandle, so normal openhandle will be leaked. */ - LDLM_FL_NO_LRU | LDLM_FL_EXCL); + LDLM_FL_NO_LRU | LDLM_FL_EXCL); ll_finish_md_op_data(op_data); ptlrpc_req_finished(req); if (rc < 0) @@ -2806,8 +2808,8 @@ ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock) PFID(ll_inode2fid(inode)), flock.l_flock.pid, flags, einfo.ei_mode, flock.l_flock.start, flock.l_flock.end); - rc = md_enqueue(sbi->ll_md_exp, &einfo, NULL, - op_data, &lockh, &flock, 0, NULL /* req */, flags); + rc = md_enqueue(sbi->ll_md_exp, &einfo, &flock, NULL, op_data, &lockh, + flags); /* Restore the file lock type if not TEST lock. */ if (!(flags & LDLM_FL_TEST_LOCK)) @@ -2819,8 +2821,8 @@ ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock) if (rc2 && file_lock->fl_type != F_UNLCK) { einfo.ei_mode = LCK_NL; - md_enqueue(sbi->ll_md_exp, &einfo, NULL, - op_data, &lockh, &flock, 0, NULL /* req */, flags); + md_enqueue(sbi->ll_md_exp, &einfo, &flock, NULL, op_data, + &lockh, flags); rc = rc2; } @@ -3059,12 +3061,8 @@ static int __ll_inode_revalidate(struct dentry *dentry, __u64 ibits) if (IS_ERR(op_data)) return PTR_ERR(op_data); - rc = md_intent_lock(exp, op_data, NULL, 0, - /* we are not interested in name - * based lookup - */ - &oit, 0, &req, - ll_md_blocking_ast, 0); + rc = md_intent_lock(exp, op_data, &oit, &req, + &ll_md_blocking_ast, 0); ll_finish_md_op_data(op_data); if (rc < 0) { rc = ll_inode_revalidate_fini(inode, rc); @@ -3742,8 +3740,8 @@ int ll_layout_refresh(struct inode *inode, __u32 *gen) struct ldlm_enqueue_info einfo = { .ei_type = LDLM_IBITS, .ei_mode = LCK_CR, - .ei_cb_bl = ll_md_blocking_ast, - .ei_cb_cp = ldlm_completion_ast, + .ei_cb_bl = &ll_md_blocking_ast, + .ei_cb_cp = &ldlm_completion_ast, }; int rc; @@ -3789,8 +3787,7 @@ again: ll_get_fsname(inode->i_sb, NULL, 0), PFID(&lli->lli_fid), inode); - rc = md_enqueue(sbi->ll_md_exp, &einfo, &it, op_data, &lockh, - NULL, 0, NULL, 0); + rc = md_enqueue(sbi->ll_md_exp, &einfo, NULL, &it, op_data, &lockh, 0); ptlrpc_req_finished(it.it_request); it.it_request = NULL; diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index d13debb..8066f0d 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -562,8 +562,8 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry, if (!IS_POSIXACL(parent) || !exp_connect_umask(ll_i2mdexp(parent))) it->it_create_mode &= ~current_umask(); - rc = md_intent_lock(ll_i2mdexp(parent), op_data, NULL, 0, it, - lookup_flags, &req, ll_md_blocking_ast, 0); + rc = md_intent_lock(ll_i2mdexp(parent), op_data, it, &req, + &ll_md_blocking_ast, 0); ll_finish_md_op_data(op_data); if (rc < 0) { retval = ERR_PTR(rc); diff --git a/drivers/staging/lustre/lustre/llite/xattr_cache.c b/drivers/staging/lustre/lustre/llite/xattr_cache.c index b66542c..0330d1a 100644 --- a/drivers/staging/lustre/lustre/llite/xattr_cache.c +++ b/drivers/staging/lustre/lustre/llite/xattr_cache.c @@ -270,10 +270,12 @@ static int ll_xattr_find_get_lock(struct inode *inode, struct lustre_handle lockh = { 0 }; struct md_op_data *op_data; struct ll_inode_info *lli = ll_i2info(inode); - struct ldlm_enqueue_info einfo = { .ei_type = LDLM_IBITS, - .ei_mode = it_to_lock_mode(oit), - .ei_cb_bl = ll_md_blocking_ast, - .ei_cb_cp = ldlm_completion_ast }; + struct ldlm_enqueue_info einfo = { + .ei_type = LDLM_IBITS, + .ei_mode = it_to_lock_mode(oit), + .ei_cb_bl = &ll_md_blocking_ast, + .ei_cb_cp = &ldlm_completion_ast, + }; struct ll_sb_info *sbi = ll_i2sbi(inode); struct obd_export *exp = sbi->ll_md_exp; int rc; @@ -304,7 +306,7 @@ static int ll_xattr_find_get_lock(struct inode *inode, op_data->op_valid = OBD_MD_FLXATTR | OBD_MD_FLXATTRLS; - rc = md_enqueue(exp, &einfo, oit, op_data, &lockh, NULL, 0, NULL, 0); + rc = md_enqueue(exp, &einfo, NULL, oit, op_data, &lockh, 0); ll_finish_md_op_data(op_data); if (rc < 0) { diff --git a/drivers/staging/lustre/lustre/lmv/lmv_intent.c b/drivers/staging/lustre/lustre/lmv/lmv_intent.c index 0559445..62f6bd0 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_intent.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_intent.c @@ -48,9 +48,8 @@ #include "../include/lprocfs_status.h" #include "lmv_internal.h" -static int lmv_intent_remote(struct obd_export *exp, void *lmm, - int lmmsize, struct lookup_intent *it, - const struct lu_fid *parent_fid, int flags, +static int lmv_intent_remote(struct obd_export *exp, struct lookup_intent *it, + const struct lu_fid *parent_fid, struct ptlrpc_request **reqp, ldlm_blocking_callback cb_blocking, __u64 extra_lock_flags) @@ -117,8 +116,8 @@ static int lmv_intent_remote(struct obd_export *exp, void *lmm, CDEBUG(D_INODE, "REMOTE_INTENT with fid="DFID" -> mds #%d\n", PFID(&body->mbo_fid1), tgt->ltd_idx); - rc = md_intent_lock(tgt->ltd_exp, op_data, lmm, lmmsize, it, - flags, &req, cb_blocking, extra_lock_flags); + rc = md_intent_lock(tgt->ltd_exp, op_data, it, &req, cb_blocking, + extra_lock_flags); if (rc) goto out_free_op_data; @@ -206,8 +205,8 @@ int lmv_revalidate_slaves(struct obd_export *exp, struct mdt_body *mbody, CDEBUG(D_INODE, "Revalidate slave "DFID" -> mds #%d\n", PFID(&fid), tgt->ltd_idx); - rc = md_intent_lock(tgt->ltd_exp, op_data, NULL, 0, &it, 0, - &req, cb_blocking, extra_lock_flags); + rc = md_intent_lock(tgt->ltd_exp, op_data, &it, &req, + cb_blocking, extra_lock_flags); if (rc < 0) goto cleanup; @@ -298,8 +297,8 @@ cleanup: * may be split dir. */ static int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data, - void *lmm, int lmmsize, struct lookup_intent *it, - int flags, struct ptlrpc_request **reqp, + struct lookup_intent *it, + struct ptlrpc_request **reqp, ldlm_blocking_callback cb_blocking, __u64 extra_lock_flags) { @@ -352,8 +351,8 @@ static int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data, PFID(&op_data->op_fid1), PFID(&op_data->op_fid2), op_data->op_name, tgt->ltd_idx); - rc = md_intent_lock(tgt->ltd_exp, op_data, lmm, lmmsize, it, flags, - reqp, cb_blocking, extra_lock_flags); + rc = md_intent_lock(tgt->ltd_exp, op_data, it, reqp, cb_blocking, + extra_lock_flags); if (rc != 0) return rc; /* @@ -371,9 +370,8 @@ static int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data, /* Not cross-ref case, just get out of here. */ if (unlikely((body->mbo_valid & OBD_MD_MDS))) { - rc = lmv_intent_remote(exp, lmm, lmmsize, it, &op_data->op_fid1, - flags, reqp, cb_blocking, - extra_lock_flags); + rc = lmv_intent_remote(exp, it, &op_data->op_fid1, reqp, + cb_blocking, extra_lock_flags); if (rc != 0) return rc; @@ -390,8 +388,8 @@ static int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data, */ static int lmv_intent_lookup(struct obd_export *exp, struct md_op_data *op_data, - void *lmm, int lmmsize, struct lookup_intent *it, - int flags, struct ptlrpc_request **reqp, + struct lookup_intent *it, + struct ptlrpc_request **reqp, ldlm_blocking_callback cb_blocking, __u64 extra_lock_flags) { @@ -434,8 +432,8 @@ static int lmv_intent_lookup(struct obd_export *exp, op_data->op_bias &= ~MDS_CROSS_REF; - rc = md_intent_lock(tgt->ltd_exp, op_data, lmm, lmmsize, it, - flags, reqp, cb_blocking, extra_lock_flags); + rc = md_intent_lock(tgt->ltd_exp, op_data, it, reqp, cb_blocking, + extra_lock_flags); if (rc < 0) return rc; @@ -480,8 +478,7 @@ static int lmv_intent_lookup(struct obd_export *exp, op_data->op_fid1 = oinfo->lmo_fid; it->it_disposition &= ~DISP_ENQ_COMPLETE; - rc = md_intent_lock(tgt->ltd_exp, op_data, lmm, - lmmsize, it, flags, reqp, + rc = md_intent_lock(tgt->ltd_exp, op_data, it, reqp, cb_blocking, extra_lock_flags); if (rc) return rc; @@ -498,8 +495,8 @@ static int lmv_intent_lookup(struct obd_export *exp, /* Not cross-ref case, just get out of here. */ if (unlikely((body->mbo_valid & OBD_MD_MDS))) { - rc = lmv_intent_remote(exp, lmm, lmmsize, it, NULL, flags, - reqp, cb_blocking, extra_lock_flags); + rc = lmv_intent_remote(exp, it, NULL, reqp, cb_blocking, + extra_lock_flags); if (rc != 0) return rc; body = req_capsule_server_get(&(*reqp)->rq_pill, &RMF_MDT_BODY); @@ -511,8 +508,7 @@ static int lmv_intent_lookup(struct obd_export *exp, } int lmv_intent_lock(struct obd_export *exp, struct md_op_data *op_data, - void *lmm, int lmmsize, struct lookup_intent *it, - int flags, struct ptlrpc_request **reqp, + struct lookup_intent *it, struct ptlrpc_request **reqp, ldlm_blocking_callback cb_blocking, __u64 extra_lock_flags) { @@ -530,12 +526,10 @@ int lmv_intent_lock(struct obd_export *exp, struct md_op_data *op_data, return rc; if (it->it_op & (IT_LOOKUP | IT_GETATTR | IT_LAYOUT)) - rc = lmv_intent_lookup(exp, op_data, lmm, lmmsize, it, - flags, reqp, cb_blocking, + rc = lmv_intent_lookup(exp, op_data, it, reqp, cb_blocking, extra_lock_flags); else if (it->it_op & IT_OPEN) - rc = lmv_intent_open(exp, op_data, lmm, lmmsize, it, - flags, reqp, cb_blocking, + rc = lmv_intent_open(exp, op_data, it, reqp, cb_blocking, extra_lock_flags); else LBUG(); diff --git a/drivers/staging/lustre/lustre/lmv/lmv_internal.h b/drivers/staging/lustre/lustre/lmv/lmv_internal.h index ea528ae..3ce17da 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_internal.h +++ b/drivers/staging/lustre/lustre/lmv/lmv_internal.h @@ -45,8 +45,7 @@ int lmv_check_connect(struct obd_device *obd); int lmv_intent_lock(struct obd_export *exp, struct md_op_data *op_data, - void *lmm, int lmmsize, struct lookup_intent *it, - int flags, struct ptlrpc_request **reqp, + struct lookup_intent *it, struct ptlrpc_request **reqp, ldlm_blocking_callback cb_blocking, __u64 extra_lock_flags); diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 44a334a..72249bb 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -1812,70 +1812,10 @@ static int lmv_done_writing(struct obd_export *exp, } static int -lmv_enqueue_remote(struct obd_export *exp, struct ldlm_enqueue_info *einfo, - struct lookup_intent *it, struct md_op_data *op_data, - struct lustre_handle *lockh, void *lmm, int lmmsize, - __u64 extra_lock_flags) -{ - struct ptlrpc_request *req = it->it_request; - struct obd_device *obd = exp->exp_obd; - struct lmv_obd *lmv = &obd->u.lmv; - struct lustre_handle plock; - struct lmv_tgt_desc *tgt; - struct md_op_data *rdata; - struct lu_fid fid1; - struct mdt_body *body; - int rc = 0; - int pmode; - - body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); - - if (!(body->mbo_valid & OBD_MD_MDS)) - return 0; - - CDEBUG(D_INODE, "REMOTE_ENQUEUE '%s' on "DFID" -> "DFID"\n", - LL_IT2STR(it), PFID(&op_data->op_fid1), PFID(&body->mbo_fid1)); - - /* - * We got LOOKUP lock, but we really need attrs. - */ - pmode = it->it_lock_mode; - LASSERT(pmode != 0); - memcpy(&plock, lockh, sizeof(plock)); - it->it_lock_mode = 0; - it->it_request = NULL; - fid1 = body->mbo_fid1; - - ptlrpc_req_finished(req); - - tgt = lmv_find_target(lmv, &fid1); - if (IS_ERR(tgt)) { - rc = PTR_ERR(tgt); - goto out; - } - - rdata = kzalloc(sizeof(*rdata), GFP_NOFS); - if (!rdata) { - rc = -ENOMEM; - goto out; - } - - rdata->op_fid1 = fid1; - rdata->op_bias = MDS_CROSS_REF; - - rc = md_enqueue(tgt->ltd_exp, einfo, it, rdata, lockh, - lmm, lmmsize, NULL, extra_lock_flags); - kfree(rdata); -out: - ldlm_lock_decref(&plock, pmode); - return rc; -} - -static int lmv_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo, + const ldlm_policy_data_t *policy, struct lookup_intent *it, struct md_op_data *op_data, - struct lustre_handle *lockh, void *lmm, int lmmsize, - struct ptlrpc_request **req, __u64 extra_lock_flags) + struct lustre_handle *lockh, __u64 extra_lock_flags) { struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; @@ -1896,13 +1836,9 @@ lmv_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo, CDEBUG(D_INODE, "ENQUEUE '%s' on "DFID" -> mds #%d\n", LL_IT2STR(it), PFID(&op_data->op_fid1), tgt->ltd_idx); - rc = md_enqueue(tgt->ltd_exp, einfo, it, op_data, lockh, - lmm, lmmsize, req, extra_lock_flags); + rc = md_enqueue(tgt->ltd_exp, einfo, policy, it, op_data, lockh, + extra_lock_flags); - if (rc == 0 && it && it->it_op == IT_OPEN) { - rc = lmv_enqueue_remote(exp, einfo, it, op_data, lockh, - lmm, lmmsize, extra_lock_flags); - } return rc; } diff --git a/drivers/staging/lustre/lustre/mdc/mdc_internal.h b/drivers/staging/lustre/lustre/mdc/mdc_internal.h index f4d0c36..9e65cdb 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_internal.h +++ b/drivers/staging/lustre/lustre/mdc/mdc_internal.h @@ -69,16 +69,16 @@ int mdc_find_cbdata(struct obd_export *exp, const struct lu_fid *fid, ldlm_iterator_t it, void *data); int mdc_intent_lock(struct obd_export *exp, - struct md_op_data *, - void *lmm, int lmmsize, - struct lookup_intent *, int, + struct md_op_data *op_data, + struct lookup_intent *it, struct ptlrpc_request **reqp, ldlm_blocking_callback cb_blocking, __u64 extra_lock_flags); + int mdc_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo, + const ldlm_policy_data_t *policy, struct lookup_intent *it, struct md_op_data *op_data, - struct lustre_handle *lockh, void *lmm, int lmmsize, - struct ptlrpc_request **req, __u64 extra_lock_flags); + struct lustre_handle *lockh, __u64 extra_lock_flags); int mdc_resource_get_unused(struct obd_export *exp, const struct lu_fid *fid, struct list_head *cancels, enum ldlm_mode mode, diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index 1c3b78d..89b4ae7 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -249,15 +249,15 @@ static void mdc_realloc_openmsg(struct ptlrpc_request *req, } } -static struct ptlrpc_request *mdc_intent_open_pack(struct obd_export *exp, - struct lookup_intent *it, - struct md_op_data *op_data, - void *lmm, int lmmsize, - void *cb_data) +static struct ptlrpc_request * +mdc_intent_open_pack(struct obd_export *exp, struct lookup_intent *it, + struct md_op_data *op_data) { struct ptlrpc_request *req; struct obd_device *obddev = class_exp2obd(exp); struct ldlm_intent *lit; + const void *lmm = op_data->op_data; + int lmmsize = op_data->op_data_size; LIST_HEAD(cancels); int count = 0; int mode; @@ -708,9 +708,9 @@ static int mdc_finish_enqueue(struct obd_export *exp, * we don't know in advance the file type. */ int mdc_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo, + const ldlm_policy_data_t *policy, struct lookup_intent *it, struct md_op_data *op_data, - struct lustre_handle *lockh, void *lmm, int lmmsize, - struct ptlrpc_request **reqp, u64 extra_lock_flags) + struct lustre_handle *lockh, u64 extra_lock_flags) { static const ldlm_policy_data_t lookup_policy = { .l_inodebits = { MDS_INODELOCK_LOOKUP } @@ -724,9 +724,8 @@ int mdc_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo, static const ldlm_policy_data_t getxattr_policy = { .l_inodebits = { MDS_INODELOCK_XATTR } }; - ldlm_policy_data_t const *policy = &lookup_policy; struct obd_device *obddev = class_exp2obd(exp); - struct ptlrpc_request *req; + struct ptlrpc_request *req = NULL; u64 flags, saved_flags = extra_lock_flags; struct ldlm_res_id res_id; int generation, resends = 0; @@ -736,40 +735,32 @@ int mdc_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo, LASSERTF(!it || einfo->ei_type == LDLM_IBITS, "lock type %d\n", einfo->ei_type); - fid_build_reg_res_name(&op_data->op_fid1, &res_id); if (it) { + LASSERT(!policy); + saved_flags |= LDLM_FL_HAS_INTENT; - if (it->it_op & (IT_UNLINK | IT_GETATTR | IT_READDIR)) + if (it->it_op & (IT_OPEN | IT_UNLINK | IT_GETATTR | IT_READDIR)) policy = &update_policy; else if (it->it_op & IT_LAYOUT) policy = &layout_policy; else if (it->it_op & (IT_GETXATTR | IT_SETXATTR)) policy = &getxattr_policy; + else + policy = &lookup_policy; } - LASSERT(!reqp); - generation = obddev->u.cli.cl_import->imp_generation; resend: flags = saved_flags; if (!it) { - /* The only way right now is FLOCK, in this case we hide flock - * policy as lmm, but lmmsize is 0 - */ - LASSERT(lmm && lmmsize == 0); + /* The only way right now is FLOCK. */ LASSERTF(einfo->ei_type == LDLM_FLOCK, "lock type %d\n", einfo->ei_type); - policy = lmm; res_id.name[3] = LDLM_FLOCK; - req = NULL; } else if (it->it_op & IT_OPEN) { - req = mdc_intent_open_pack(exp, it, op_data, lmm, lmmsize, - einfo->ei_cbdata); - policy = &update_policy; - einfo->ei_cbdata = NULL; - lmm = NULL; + req = mdc_intent_open_pack(exp, it, op_data); } else if (it->it_op & IT_UNLINK) { req = mdc_intent_unlink_pack(exp, it, op_data); } else if (it->it_op & (IT_GETATTR | IT_LOOKUP)) { @@ -1082,10 +1073,8 @@ int mdc_revalidate_lock(struct obd_export *exp, struct lookup_intent *it, * child lookup. */ int mdc_intent_lock(struct obd_export *exp, struct md_op_data *op_data, - void *lmm, int lmmsize, struct lookup_intent *it, - int lookup_flags, struct ptlrpc_request **reqp, - ldlm_blocking_callback cb_blocking, - __u64 extra_lock_flags) + struct lookup_intent *it, struct ptlrpc_request **reqp, + ldlm_blocking_callback cb_blocking, __u64 extra_lock_flags) { struct ldlm_enqueue_info einfo = { .ei_type = LDLM_IBITS, @@ -1128,7 +1117,7 @@ int mdc_intent_lock(struct obd_export *exp, struct md_op_data *op_data, return rc; } } - rc = mdc_enqueue(exp, &einfo, it, op_data, &lockh, lmm, lmmsize, NULL, + rc = mdc_enqueue(exp, &einfo, NULL, it, op_data, &lockh, extra_lock_flags); if (rc < 0) return rc; diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 213f31b..88848d8 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -1330,7 +1330,7 @@ static int mdc_read_page(struct obd_export *exp, struct md_op_data *op_data, LASSERT(dir); mapping = dir->i_mapping; - rc = mdc_intent_lock(exp, op_data, NULL, 0, &it, 0, &enq_req, + rc = mdc_intent_lock(exp, op_data, &it, &enq_req, cb_op->md_blocking_ast, 0); if (enq_req) ptlrpc_req_finished(enq_req); -- cgit v0.10.2 From 182ae52ddbe6acf99d876ebef9723240b1a662fb Mon Sep 17 00:00:00 2001 From: James Simmons <jsimmons@infradead.org> Date: Fri, 19 Aug 2016 14:07:31 -0400 Subject: staging: lustre: update version to 2.5.99 With all but one of the the missing patches from the lustre 2.6 version merged upstream its time to update the upstream clients version. Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre_ver.h b/drivers/staging/lustre/lustre/include/lustre_ver.h index 2bb59b2..414075f 100644 --- a/drivers/staging/lustre/lustre/include/lustre_ver.h +++ b/drivers/staging/lustre/lustre/include/lustre_ver.h @@ -2,10 +2,10 @@ #define _LUSTRE_VER_H_ #define LUSTRE_MAJOR 2 -#define LUSTRE_MINOR 4 +#define LUSTRE_MINOR 5 #define LUSTRE_PATCH 60 #define LUSTRE_FIX 0 -#define LUSTRE_VERSION_STRING "2.4.60" +#define LUSTRE_VERSION_STRING "2.5.99" #define OBD_OCD_VERSION(major, minor, patch, fix) \ (((major) << 24) + ((minor) << 16) + ((patch) << 8) + (fix)) -- cgit v0.10.2 From 49880263163547bf8fe526d1006052729afb29e2 Mon Sep 17 00:00:00 2001 From: Emoly Liu <emoly.liu@intel.com> Date: Sat, 20 Aug 2016 17:34:27 -0400 Subject: staging/lustre: Fix unnecessary parentheses around variables This patch fixes all checkpatch occurences of "CHECK: Unnecessary parentheses around xxx" in Lustre code. Signed-off-by: Emoly Liu <emoly.liu@intel.com> Signed-off-by: Oleg Drokin <green@linuxhacker.ru> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index 52cd585..229aecb 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -995,7 +995,7 @@ struct hsm_user_request { /** Return pointer to data field in a hsm user request */ static inline void *hur_data(struct hsm_user_request *hur) { - return &(hur->hur_user_item[hur->hur_request.hr_itemcount]); + return &hur->hur_user_item[hur->hur_request.hr_itemcount]; } /** diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index d904f44..49b1050 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -941,7 +941,7 @@ int lov_process_config_base(struct obd_device *obd, struct lustre_cfg *lcfg, } case LCFG_PARAM: { struct lprocfs_static_vars lvars = { NULL }; - struct lov_desc *desc = &(obd->u.lov.desc); + struct lov_desc *desc = &obd->u.lov.desc; if (!desc) { rc = -EINVAL; @@ -1461,7 +1461,7 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len, } desc = (struct lov_desc *)data->ioc_inlbuf1; - memcpy(desc, &(lov->desc), sizeof(*desc)); + memcpy(desc, &lov->desc, sizeof(*desc)); uuidp = (struct obd_uuid *)data->ioc_inlbuf2; genp = (__u32 *)data->ioc_inlbuf3; diff --git a/drivers/staging/lustre/lustre/lov/lov_pool.c b/drivers/staging/lustre/lustre/lov/lov_pool.c index 4c2d217..8bfa101 100644 --- a/drivers/staging/lustre/lustre/lov/lov_pool.c +++ b/drivers/staging/lustre/lustre/lov/lov_pool.c @@ -61,7 +61,7 @@ void lov_pool_putref(struct pool_desc *pool) LASSERT(hlist_unhashed(&pool->pool_hash)); LASSERT(list_empty(&pool->pool_list)); LASSERT(!pool->pool_debugfs_entry); - lov_ost_pool_free(&(pool->pool_obds)); + lov_ost_pool_free(&pool->pool_obds); kfree(pool); } } @@ -260,7 +260,7 @@ static int pool_proc_show(struct seq_file *s, void *v) tgt = pool_tgt(iter->pool, iter->idx); up_read(&pool_tgt_rw_sem(iter->pool)); if (tgt) - seq_printf(s, "%s\n", obd_uuid2str(&(tgt->ltd_uuid))); + seq_printf(s, "%s\n", obd_uuid2str(&tgt->ltd_uuid)); return 0; } @@ -400,7 +400,7 @@ int lov_pool_new(struct obd_device *obd, char *poolname) struct pool_desc *new_pool; int rc; - lov = &(obd->u.lov); + lov = &obd->u.lov; if (strlen(poolname) > LOV_MAXPOOLNAME) return -ENAMETOOLONG; @@ -471,7 +471,7 @@ int lov_pool_del(struct obd_device *obd, char *poolname) struct lov_obd *lov; struct pool_desc *pool; - lov = &(obd->u.lov); + lov = &obd->u.lov; /* lookup and kill hash reference */ pool = cfs_hash_del_key(lov->lov_pools_hash_body, poolname); @@ -503,7 +503,7 @@ int lov_pool_add(struct obd_device *obd, char *poolname, char *ostname) unsigned int lov_idx; int rc; - lov = &(obd->u.lov); + lov = &obd->u.lov; pool = cfs_hash_lookup(lov->lov_pools_hash_body, poolname); if (!pool) @@ -517,7 +517,7 @@ int lov_pool_add(struct obd_device *obd, char *poolname, char *ostname) if (!lov->lov_tgts[lov_idx]) continue; if (obd_uuid_equals(&ost_uuid, - &(lov->lov_tgts[lov_idx]->ltd_uuid))) + &lov->lov_tgts[lov_idx]->ltd_uuid)) break; } /* test if ost found in lov */ @@ -547,7 +547,7 @@ int lov_pool_remove(struct obd_device *obd, char *poolname, char *ostname) unsigned int lov_idx; int rc = 0; - lov = &(obd->u.lov); + lov = &obd->u.lov; pool = cfs_hash_lookup(lov->lov_pools_hash_body, poolname); if (!pool) @@ -562,7 +562,7 @@ int lov_pool_remove(struct obd_device *obd, char *poolname, char *ostname) continue; if (obd_uuid_equals(&ost_uuid, - &(lov->lov_tgts[lov_idx]->ltd_uuid))) + &lov->lov_tgts[lov_idx]->ltd_uuid)) break; } diff --git a/drivers/staging/lustre/lustre/obdclass/genops.c b/drivers/staging/lustre/lustre/obdclass/genops.c index a739eb1..6356870 100644 --- a/drivers/staging/lustre/lustre/obdclass/genops.c +++ b/drivers/staging/lustre/lustre/obdclass/genops.c @@ -166,10 +166,10 @@ int class_register_type(struct obd_ops *dt_ops, struct md_ops *md_ops, !type->typ_name) goto failed; - *(type->typ_dt_ops) = *dt_ops; + *type->typ_dt_ops = *dt_ops; /* md_ops is optional */ if (md_ops) - *(type->typ_md_ops) = *md_ops; + *type->typ_md_ops = *md_ops; strcpy(type->typ_name, name); spin_lock_init(&type->obd_type_lock); diff --git a/drivers/staging/lustre/lustre/obdclass/llog.c b/drivers/staging/lustre/lustre/obdclass/llog.c index 1784ca0..8f06141 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog.c +++ b/drivers/staging/lustre/lustre/obdclass/llog.c @@ -80,7 +80,7 @@ static void llog_free_handle(struct llog_handle *loghandle) LASSERT(list_empty(&loghandle->u.phd.phd_entry)); else if (loghandle->lgh_hdr->llh_flags & LLOG_F_IS_CAT) LASSERT(list_empty(&loghandle->u.chd.chd_head)); - LASSERT(sizeof(*(loghandle->lgh_hdr)) == LLOG_CHUNK_SIZE); + LASSERT(sizeof(*loghandle->lgh_hdr) == LLOG_CHUNK_SIZE); kfree(loghandle->lgh_hdr); out: kfree(loghandle); diff --git a/drivers/staging/lustre/lustre/obdclass/lustre_handles.c b/drivers/staging/lustre/lustre/obdclass/lustre_handles.c index 7ca68ae..8faa318 100644 --- a/drivers/staging/lustre/lustre/obdclass/lustre_handles.c +++ b/drivers/staging/lustre/lustre/obdclass/lustre_handles.c @@ -214,7 +214,7 @@ static int cleanup_all_handles(void) struct portals_handle *h; spin_lock(&handle_hash[i].lock); - list_for_each_entry_rcu(h, &(handle_hash[i].head), h_link) { + list_for_each_entry_rcu(h, &handle_hash[i].head, h_link) { CERROR("force clean handle %#llx addr %p ops %p\n", h->h_cookie, h, h->h_ops); diff --git a/drivers/staging/lustre/lustre/obdclass/obd_config.c b/drivers/staging/lustre/lustre/obdclass/obd_config.c index 01034b5..220fda7 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_config.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_config.c @@ -1013,7 +1013,7 @@ int class_process_proc_param(char *prefix, struct lprocfs_vars *lvars, oldfs = get_fs(); set_fs(KERNEL_DS); - rc = (var->fops->write)(&fakefile, sval, + rc = var->fops->write(&fakefile, sval, vallen, NULL); set_fs(oldfs); } diff --git a/drivers/staging/lustre/lustre/obdclass/obd_mount.c b/drivers/staging/lustre/lustre/obdclass/obd_mount.c index 595ea1f..b838194 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_mount.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_mount.c @@ -394,7 +394,7 @@ int lustre_start_mgc(struct super_block *sb) lsi->lsi_lmd->lmd_flags & LMD_FLG_NOIR) data->ocd_connect_flags &= ~OBD_CONNECT_IMP_RECOV; data->ocd_version = LUSTRE_VERSION_CODE; - rc = obd_connect(NULL, &exp, obd, &(obd->obd_uuid), data, NULL); + rc = obd_connect(NULL, &exp, obd, &obd->obd_uuid, data, NULL); if (rc) { CERROR("connect failed %d\n", rc); goto out; diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 2a4056a..3709440 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -2633,7 +2633,7 @@ static int osc_getstripe(struct lov_stripe_md *lsm, lmm_objects = &(((struct lov_user_md_v1 *)lumk)->lmm_objects[0]); else - lmm_objects = &(lumk->lmm_objects[0]); + lmm_objects = &lumk->lmm_objects[0]; lmm_objects->l_ost_oi = lsm->lsm_oi; } else { lum_size = lov_mds_md_size(0, lum.lmm_magic); diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index 465698b..9c03a9a 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -1978,9 +1978,9 @@ void lustre_swab_lov_user_md_objects(struct lov_user_ost_data *lod, int i; for (i = 0; i < stripe_count; i++) { - lustre_swab_ost_id(&(lod[i].l_ost_oi)); - __swab32s(&(lod[i].l_ost_gen)); - __swab32s(&(lod[i].l_ost_idx)); + lustre_swab_ost_id(&lod[i].l_ost_oi); + __swab32s(&lod[i].l_ost_gen); + __swab32s(&lod[i].l_ost_idx); } } EXPORT_SYMBOL(lustre_swab_lov_user_md_objects); -- cgit v0.10.2 From 8701dbf9acb9475caf94dc738796ae5465af9561 Mon Sep 17 00:00:00 2001 From: Oleg Drokin <green@linuxhacker.ru> Date: Sat, 20 Aug 2016 17:34:30 -0400 Subject: Add James Simmons as another Lustre maintainer James Simmons is also spendign a lot of efforts on cleaning up staging tree Lustre code and also helps to sync up all the missing changes from the other tree. Signed-off-by: Oleg Drokin <green@linuxhacker.ru> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/MAINTAINERS b/MAINTAINERS index a306795..f277cfd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11154,6 +11154,7 @@ F: drivers/staging/media/lirc/ STAGING - LUSTRE PARALLEL FILESYSTEM M: Oleg Drokin <oleg.drokin@intel.com> M: Andreas Dilger <andreas.dilger@intel.com> +M: James Simmons <jsimmons@infradead.org> L: lustre-devel@lists.lustre.org (moderated for non-subscribers) W: http://wiki.lustre.org/ S: Maintained -- cgit v0.10.2 From 550982ccdb8710e2b28e4ad7211fcca8694a1282 Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Tue, 16 Aug 2016 15:20:00 -0400 Subject: staging: lustre: fix checkpatch error convert spaces to tab fix the following error messages from checkpatch.pl ERROR: code indent should use tabs where possible WARNING: please, no spaces at the start of a line Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index ec6cf7c..db9466a 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -2351,7 +2351,7 @@ struct cl_client_cache { * Waitq for awaiting unstable pages to reach zero. * Used at umounting time and signaled on BRW commit */ - wait_queue_head_t ccc_unstable_waitq; + wait_queue_head_t ccc_unstable_waitq; }; -- cgit v0.10.2 From 18c6e2d60263022ee82953de6a66d171db0377fd Mon Sep 17 00:00:00 2001 From: Shawn Lin <shawn.lin@rock-chips.com> Date: Sun, 21 Aug 2016 10:44:37 +0800 Subject: staging: lustre: llite: don't clean in_data again We have got a zero buffer for in_data as we use kzalloc here. So let's remove it anyway. Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com> Acked-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index b680618..2f48f7e 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -3434,7 +3434,6 @@ void *ll_iocontrol_register(llioc_callback_t cb, int count, unsigned int *cmd) if (!in_data) return NULL; - memset(in_data, 0, sizeof(*in_data)); in_data->iocd_size = size; in_data->iocd_cb = cb; in_data->iocd_count = count; -- cgit v0.10.2 From 9b28e14818ad959516e99b7ba3d1fc2e5500ca51 Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Fri, 19 Aug 2016 13:09:33 +0200 Subject: staging: most: aim-cdev: fix reported error codes Currently, the aim-cdev is returning different error codes for the same root cause. This patch is needed to get rid of the module's inconsistency when reporting errors. Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index de4f76a..6ca2440 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -130,7 +130,7 @@ static int aim_open(struct inode *inode, struct file *filp) if (!c->dev) { pr_info("WARN: Device is destroyed\n"); mutex_unlock(&c->io_mutex); - return -EBUSY; + return -ENODEV; } if (c->access_ref) { @@ -201,7 +201,7 @@ static ssize_t aim_write(struct file *filp, const char __user *buf, } if (unlikely(!c->dev)) { - ret = -EPIPE; + ret = -ENODEV; goto unlock; } @@ -256,7 +256,7 @@ aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) /* make sure we don't submit to gone devices */ if (unlikely(!c->dev)) { mutex_unlock(&c->io_mutex); - return -EIO; + return -ENODEV; } to_copy = min_t(size_t, @@ -366,7 +366,7 @@ static int aim_rx_completion(struct mbo *mbo) spin_lock(&c->unlink); if (!c->access_ref || !c->dev) { spin_unlock(&c->unlink); - return -EFAULT; + return -ENODEV; } kfifo_in(&c->fifo, &mbo, 1); spin_unlock(&c->unlink); @@ -499,6 +499,8 @@ static struct most_aim cdev_aim = { static int __init mod_init(void) { + int err; + pr_info("init()\n"); INIT_LIST_HEAD(&channel_list); @@ -506,16 +508,17 @@ static int __init mod_init(void) ida_init(&minor_id); if (alloc_chrdev_region(&aim_devno, 0, 50, "cdev") < 0) - return -EIO; + return -ENOMEM; major = MAJOR(aim_devno); aim_class = class_create(THIS_MODULE, "most_cdev_aim"); if (IS_ERR(aim_class)) { pr_err("no udev support\n"); + err = PTR_ERR(aim_class); goto free_cdev; } - - if (most_register_aim(&cdev_aim)) + err = most_register_aim(&cdev_aim); + if (err) goto dest_class; return 0; @@ -523,7 +526,7 @@ dest_class: class_destroy(aim_class); free_cdev: unregister_chrdev_region(aim_devno, 1); - return -EIO; + return err; } static void __exit mod_exit(void) -- cgit v0.10.2 From 324e87b7e135c01725a9cef02cb8436f65e65f07 Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Fri, 19 Aug 2016 13:09:34 +0200 Subject: staging: most: aim-cdev: report error returned by alloc_chrdev_region This patch forwards the error code returned by function alloc_chrdev_region(). It is needed to stop the module from hiding the actual cause of failure. Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index 6ca2440..db6f458 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -507,8 +507,9 @@ static int __init mod_init(void) spin_lock_init(&ch_list_lock); ida_init(&minor_id); - if (alloc_chrdev_region(&aim_devno, 0, 50, "cdev") < 0) - return -ENOMEM; + err = alloc_chrdev_region(&aim_devno, 0, 50, "cdev"); + if (err < 0) + return err; major = MAJOR(aim_devno); aim_class = class_create(THIS_MODULE, "most_cdev_aim"); -- cgit v0.10.2 From cce930193778f6f3bb0f57b871080da0ca3d1f88 Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Fri, 19 Aug 2016 11:12:45 +0200 Subject: staging: most: hdm-usb: remove unused macro HW_RESYNC This patch removes the macro HW_RESYNC that is not used anymore. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index e63784d..79277dd 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -44,7 +44,6 @@ #define USB_VENDOR_ID_SMSC 0x0424 /* VID: SMSC */ #define USB_DEV_ID_BRDG 0xC001 /* PID: USB Bridge */ #define USB_DEV_ID_INIC 0xCF18 /* PID: USB INIC */ -#define HW_RESYNC 0x0000 /* DRCI Addresses */ #define DRCI_REG_NI_STATE 0x0100 #define DRCI_REG_PACKET_BW 0x0101 -- cgit v0.10.2 From 9ed745ff8e80fbb600f386013bab9c361202866c Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Fri, 19 Aug 2016 11:12:46 +0200 Subject: staging: most: hdm-usb: provide MBO status when freeing buffers This patch adds the additional status parameter to function free_anchored_buffers. This allows to dispatch further processing based on this flag. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index 79277dd..bc2d174 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -190,8 +190,10 @@ static inline int drci_wr_reg(struct usb_device *dev, u16 reg, u16 data) * free_anchored_buffers - free device's anchored items * @mdev: the device * @channel: channel ID + * @status: status of MBO termination */ -static void free_anchored_buffers(struct most_dev *mdev, unsigned int channel) +static void free_anchored_buffers(struct most_dev *mdev, unsigned int channel, + enum mbo_status_flags status) { struct mbo *mbo; struct buf_anchor *anchor, *tmp; @@ -212,7 +214,7 @@ static void free_anchored_buffers(struct most_dev *mdev, unsigned int channel) wait_for_completion(&anchor->urb_compl); } if ((mbo) && (mbo->complete)) { - mbo->status = MBO_E_CLOSE; + mbo->status = status; mbo->processed_length = 0; mbo->complete(mbo); } @@ -288,7 +290,7 @@ static int hdm_poison_channel(struct most_interface *iface, int channel) mdev->is_channel_healthy[channel] = false; mutex_lock(&mdev->io_mutex); - free_anchored_buffers(mdev, channel); + free_anchored_buffers(mdev, channel, MBO_E_CLOSE); if (mdev->padding_active[channel]) mdev->padding_active[channel] = false; -- cgit v0.10.2 From cc28983c322030ce7a3d748833186eab86a41570 Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Fri, 19 Aug 2016 11:12:47 +0200 Subject: staging: most: hdm-usb: fix clear halt processing This patch is needed to ensure that submitted URBs get unlinked before the driver calls usb_clear_halt(). Since the halt condition of an USB endpoint is channel related, the work_struct is moved from a buffer basis to a channel basis. Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index bc2d174..8f1c096 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -65,19 +65,15 @@ /** * struct buf_anchor - used to create a list of pending URBs * @urb: pointer to USB request block - * @clear_work_obj: * @list: linked list * @urb_completion: */ struct buf_anchor { struct urb *urb; - struct work_struct clear_work_obj; struct list_head list; struct completion urb_compl; }; -#define to_buf_anchor(w) container_of(w, struct buf_anchor, clear_work_obj) - /** * struct most_dci_obj - Direct Communication Interface * @kobj:position in sysfs @@ -90,6 +86,17 @@ struct most_dci_obj { #define to_dci_obj(p) container_of(p, struct most_dci_obj, kobj) +struct most_dev; + +struct clear_hold_work { + struct work_struct ws; + struct most_dev *mdev; + unsigned int channel; + int pipe; +}; + +#define to_clear_hold_work(w) container_of(w, struct clear_hold_work, ws) + /** * struct most_dev - holds all usb interface specific stuff * @parent: parent object in sysfs @@ -126,6 +133,7 @@ struct most_dev { spinlock_t anchor_list_lock[MAX_NUM_ENDPOINTS]; bool padding_active[MAX_NUM_ENDPOINTS]; bool is_channel_healthy[MAX_NUM_ENDPOINTS]; + struct clear_hold_work clear_work[MAX_NUM_ENDPOINTS]; struct list_head *anchor_list; struct mutex io_mutex; struct timer_list link_stat_timer; @@ -222,7 +230,6 @@ static void free_anchored_buffers(struct most_dev *mdev, unsigned int channel, } spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags); list_del(&anchor->list); - cancel_work_sync(&anchor->clear_work_obj); kfree(anchor); } spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags); @@ -289,6 +296,8 @@ static int hdm_poison_channel(struct most_interface *iface, int channel) mdev->is_channel_healthy[channel] = false; + cancel_work_sync(&mdev->clear_work[channel].ws); + mutex_lock(&mdev->io_mutex); free_anchored_buffers(mdev, channel, MBO_E_CLOSE); if (mdev->padding_active[channel]) @@ -409,9 +418,8 @@ static void hdm_write_completion(struct urb *urb) dev_warn(dev, "Broken OUT pipe detected\n"); most_stop_enqueue(&mdev->iface, channel); mbo->status = MBO_E_INVAL; - usb_unlink_urb(urb); - INIT_WORK(&anchor->clear_work_obj, wq_clear_halt); - schedule_work(&anchor->clear_work_obj); + mdev->clear_work[channel].pipe = urb->pipe; + schedule_work(&mdev->clear_work[channel].ws); return; case -ENODEV: case -EPROTO: @@ -573,9 +581,8 @@ static void hdm_read_completion(struct urb *urb) case -EPIPE: dev_warn(dev, "Broken IN pipe detected\n"); mbo->status = MBO_E_INVAL; - usb_unlink_urb(urb); - INIT_WORK(&anchor->clear_work_obj, wq_clear_halt); - schedule_work(&anchor->clear_work_obj); + mdev->clear_work[channel].pipe = urb->pipe; + schedule_work(&mdev->clear_work[channel].ws); return; case -ENODEV: case -EPROTO: @@ -735,6 +742,9 @@ static int hdm_configure_channel(struct most_interface *iface, int channel, mdev = to_mdev(iface); mdev->is_channel_healthy[channel] = true; + mdev->clear_work[channel].channel = channel; + mdev->clear_work[channel].mdev = mdev; + INIT_WORK(&mdev->clear_work[channel].ws, wq_clear_halt); dev = &mdev->usb_device->dev; if (unlikely(!iface || !conf)) { @@ -916,33 +926,19 @@ static void wq_netinfo(struct work_struct *wq_obj) */ static void wq_clear_halt(struct work_struct *wq_obj) { - struct buf_anchor *anchor; - struct most_dev *mdev; - struct mbo *mbo; - struct urb *urb; - unsigned int channel; - unsigned long flags; + struct clear_hold_work *clear_work = to_clear_hold_work(wq_obj); + struct most_dev *mdev = clear_work->mdev; + unsigned int channel = clear_work->channel; + int pipe = clear_work->pipe; - anchor = to_buf_anchor(wq_obj); - urb = anchor->urb; - mbo = urb->context; - mdev = to_mdev(mbo->ifp); - channel = mbo->hdm_channel_id; - - if (usb_clear_halt(urb->dev, urb->pipe)) + mutex_lock(&mdev->io_mutex); + free_anchored_buffers(mdev, channel, MBO_E_INVAL); + if (usb_clear_halt(mdev->usb_device, pipe)) dev_warn(&mdev->usb_device->dev, "Failed to reset endpoint.\n"); - usb_free_urb(urb); - spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags); - list_del(&anchor->list); - spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags); - - if (likely(mbo->complete)) - mbo->complete(mbo); if (mdev->conf[channel].direction & MOST_CH_TX) most_resume_enqueue(&mdev->iface, channel); - - kfree(anchor); + mutex_unlock(&mdev->io_mutex); } /** -- cgit v0.10.2 From 72df4a55e9ab955d2143e638d9b24343e7658d6f Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Fri, 19 Aug 2016 11:12:48 +0200 Subject: staging: most: hdm-usb: stop core from submitting buffers in case of broken pipe This patch ensures that no more packets are submitted by the core in case an USB endpoint has reported a broken pipe (-EPIPE). Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index 8f1c096..03cdd0d 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -580,6 +580,7 @@ static void hdm_read_completion(struct urb *urb) switch (urb->status) { case -EPIPE: dev_warn(dev, "Broken IN pipe detected\n"); + most_stop_enqueue(&mdev->iface, channel); mbo->status = MBO_E_INVAL; mdev->clear_work[channel].pipe = urb->pipe; schedule_work(&mdev->clear_work[channel].ws); @@ -936,8 +937,7 @@ static void wq_clear_halt(struct work_struct *wq_obj) if (usb_clear_halt(mdev->usb_device, pipe)) dev_warn(&mdev->usb_device->dev, "Failed to reset endpoint.\n"); - if (mdev->conf[channel].direction & MOST_CH_TX) - most_resume_enqueue(&mdev->iface, channel); + most_resume_enqueue(&mdev->iface, channel); mutex_unlock(&mdev->io_mutex); } -- cgit v0.10.2 From b50762eaf853999c0ab51730858b07196ec7530d Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Fri, 19 Aug 2016 11:12:49 +0200 Subject: staging: most: hdm-usb: add USB product id This patch adds support for the OS81119 MOST network interface controller to the driver. Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index 03cdd0d..beb50cd 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -44,6 +44,7 @@ #define USB_VENDOR_ID_SMSC 0x0424 /* VID: SMSC */ #define USB_DEV_ID_BRDG 0xC001 /* PID: USB Bridge */ #define USB_DEV_ID_INIC 0xCF18 /* PID: USB INIC */ +#define USB_DEV_ID_OS81119 0xCF19 /* PID: USB OS81119 */ /* DRCI Addresses */ #define DRCI_REG_NI_STATE 0x0100 #define DRCI_REG_PACKET_BW 0x0101 @@ -954,6 +955,7 @@ static const struct file_operations hdm_usb_fops = { static struct usb_device_id usbid[] = { { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_BRDG), }, { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_INIC), }, + { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_OS81119), }, { } /* Terminating entry */ }; @@ -1327,7 +1329,8 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) } mutex_lock(&mdev->io_mutex); - if (le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_INIC) { + if (le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_INIC || + le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81119) { /* this increments the reference count of the instance * object of the core */ -- cgit v0.10.2 From 654f7ec4b3b8aca70fc7215651b6c45066bf74c1 Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Fri, 19 Aug 2016 11:12:50 +0200 Subject: staging: most: hdm-usb: rename ID_INIC for consistency In order to have a consistent naming convention this patch renames USB_DEV_ID_INIC to USB_DEV_ID_OS81118. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index beb50cd..c2ba5a1 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -43,7 +43,7 @@ #define USB_VENDOR_ID_SMSC 0x0424 /* VID: SMSC */ #define USB_DEV_ID_BRDG 0xC001 /* PID: USB Bridge */ -#define USB_DEV_ID_INIC 0xCF18 /* PID: USB INIC */ +#define USB_DEV_ID_OS81118 0xCF18 /* PID: USB OS81118 */ #define USB_DEV_ID_OS81119 0xCF19 /* PID: USB OS81119 */ /* DRCI Addresses */ #define DRCI_REG_NI_STATE 0x0100 @@ -954,7 +954,7 @@ static const struct file_operations hdm_usb_fops = { */ static struct usb_device_id usbid[] = { { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_BRDG), }, - { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_INIC), }, + { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_OS81118), }, { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_OS81119), }, { } /* Terminating entry */ }; @@ -1329,7 +1329,7 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) } mutex_lock(&mdev->io_mutex); - if (le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_INIC || + if (le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81118 || le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81119) { /* this increments the reference count of the instance * object of the core -- cgit v0.10.2 From 879c93fefd3dcbce414ffccdf5cbd5685b18afed Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Fri, 19 Aug 2016 11:12:51 +0200 Subject: staging: most: hdm-usb: make use of is_channel_healthy flag This patch makes the write completion handler use the is_channel_healthy flag to prevent the hdm from scheduling a second clear_halt workqueue in case an endpoint reported a STALL condition. Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index c2ba5a1..57d6c6d 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -418,6 +418,7 @@ static void hdm_write_completion(struct urb *urb) case -EPIPE: dev_warn(dev, "Broken OUT pipe detected\n"); most_stop_enqueue(&mdev->iface, channel); + mdev->is_channel_healthy[channel] = false; mbo->status = MBO_E_INVAL; mdev->clear_work[channel].pipe = urb->pipe; schedule_work(&mdev->clear_work[channel].ws); @@ -582,6 +583,7 @@ static void hdm_read_completion(struct urb *urb) case -EPIPE: dev_warn(dev, "Broken IN pipe detected\n"); most_stop_enqueue(&mdev->iface, channel); + mdev->is_channel_healthy[channel] = false; mbo->status = MBO_E_INVAL; mdev->clear_work[channel].pipe = urb->pipe; schedule_work(&mdev->clear_work[channel].ws); @@ -938,6 +940,7 @@ static void wq_clear_halt(struct work_struct *wq_obj) if (usb_clear_halt(mdev->usb_device, pipe)) dev_warn(&mdev->usb_device->dev, "Failed to reset endpoint.\n"); + mdev->is_channel_healthy[channel] = true; most_resume_enqueue(&mdev->iface, channel); mutex_unlock(&mdev->io_mutex); } -- cgit v0.10.2 From 4246501e23be88383fed31ba0df6f0af7b91e176 Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Fri, 19 Aug 2016 11:12:52 +0200 Subject: staging: most: hdm-usb: remove redundant conditions This patch removes the duplication of the expression (urb->status == -ENOENT || urb->status == -ECONNRESET). Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index 57d6c6d..ddee281 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -410,9 +410,7 @@ static void hdm_write_completion(struct urb *urb) return; } - if (unlikely(urb->status && !(urb->status == -ENOENT || - urb->status == -ECONNRESET || - urb->status == -ESHUTDOWN))) { + if (unlikely(urb->status && urb->status != -ESHUTDOWN)) { mbo->processed_length = 0; switch (urb->status) { case -EPIPE: @@ -575,9 +573,7 @@ static void hdm_read_completion(struct urb *urb) return; } - if (unlikely(urb->status && !(urb->status == -ENOENT || - urb->status == -ECONNRESET || - urb->status == -ESHUTDOWN))) { + if (unlikely(urb->status && urb->status != -ESHUTDOWN)) { mbo->processed_length = 0; switch (urb->status) { case -EPIPE: -- cgit v0.10.2 From cf05918370006fbdb6dc5708ca9951ee8093b8ef Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Fri, 19 Aug 2016 11:12:53 +0200 Subject: staging: most: hdm-usb: simplify initialization of mbo->status. This patch simplifies the code that initializes mbo->status. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index ddee281..7f00aaf 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -596,15 +596,11 @@ static void hdm_read_completion(struct urb *urb) } } else { mbo->processed_length = urb->actual_length; - if (!mdev->padding_active[channel]) { - mbo->status = MBO_SUCCESS; - } else { - if (hdm_remove_padding(mdev, channel, mbo)) { - mbo->processed_length = 0; - mbo->status = MBO_E_INVAL; - } else { - mbo->status = MBO_SUCCESS; - } + mbo->status = MBO_SUCCESS; + if (mdev->padding_active[channel] && + hdm_remove_padding(mdev, channel, mbo)) { + mbo->processed_length = 0; + mbo->status = MBO_E_INVAL; } } spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags); -- cgit v0.10.2 From bf9503f11dedf40158a8a5847f2d482bc15cd82b Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Fri, 19 Aug 2016 11:12:54 +0200 Subject: staging: most: hdm-usb: fix race between enqueue and most_stop_enqueue The "broken in pipe" handler of the USB-HDM calls most_stop_enqueue() to stop the MBO traffic before returning all MBOs back to the Mostcore. As the enqueue() call from the Mostcore may run in parallel with the most_stop_enqueue(), the HDM may run into the inconsistent state and crash the kernel. This patch synchronizes enqueue(), most_stop_enqueue() and most_resume_enqueue() with a mutex, hence avoiding the race condition. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index 7f00aaf..8d8c72c 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -415,7 +415,6 @@ static void hdm_write_completion(struct urb *urb) switch (urb->status) { case -EPIPE: dev_warn(dev, "Broken OUT pipe detected\n"); - most_stop_enqueue(&mdev->iface, channel); mdev->is_channel_healthy[channel] = false; mbo->status = MBO_E_INVAL; mdev->clear_work[channel].pipe = urb->pipe; @@ -578,7 +577,6 @@ static void hdm_read_completion(struct urb *urb) switch (urb->status) { case -EPIPE: dev_warn(dev, "Broken IN pipe detected\n"); - most_stop_enqueue(&mdev->iface, channel); mdev->is_channel_healthy[channel] = false; mbo->status = MBO_E_INVAL; mdev->clear_work[channel].pipe = urb->pipe; @@ -928,6 +926,7 @@ static void wq_clear_halt(struct work_struct *wq_obj) int pipe = clear_work->pipe; mutex_lock(&mdev->io_mutex); + most_stop_enqueue(&mdev->iface, channel); free_anchored_buffers(mdev, channel, MBO_E_INVAL); if (usb_clear_halt(mdev->usb_device, pipe)) dev_warn(&mdev->usb_device->dev, "Failed to reset endpoint.\n"); diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index b03cdc9..db0606ca 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -51,6 +51,7 @@ struct most_c_obj { u16 channel_id; bool is_poisoned; struct mutex start_mutex; + struct mutex nq_mutex; /* nq thread synchronization */ int is_starving; struct most_interface *iface; struct most_inst_obj *inst; @@ -1131,18 +1132,18 @@ static inline void trash_mbo(struct mbo *mbo) spin_unlock_irqrestore(&c->fifo_lock, flags); } -static struct mbo *get_hdm_mbo(struct most_c_obj *c) +static bool hdm_mbo_ready(struct most_c_obj *c) { - unsigned long flags; - struct mbo *mbo; + bool empty; - spin_lock_irqsave(&c->fifo_lock, flags); - if (c->enqueue_halt || list_empty(&c->halt_fifo)) - mbo = NULL; - else - mbo = list_pop_mbo(&c->halt_fifo); - spin_unlock_irqrestore(&c->fifo_lock, flags); - return mbo; + if (c->enqueue_halt) + return false; + + spin_lock_irq(&c->fifo_lock); + empty = list_empty(&c->halt_fifo); + spin_unlock_irq(&c->fifo_lock); + + return !empty; } static void nq_hdm_mbo(struct mbo *mbo) @@ -1160,20 +1161,32 @@ static int hdm_enqueue_thread(void *data) { struct most_c_obj *c = data; struct mbo *mbo; + int ret; typeof(c->iface->enqueue) enqueue = c->iface->enqueue; while (likely(!kthread_should_stop())) { wait_event_interruptible(c->hdm_fifo_wq, - (mbo = get_hdm_mbo(c)) || + hdm_mbo_ready(c) || kthread_should_stop()); - if (unlikely(!mbo)) + mutex_lock(&c->nq_mutex); + spin_lock_irq(&c->fifo_lock); + if (unlikely(c->enqueue_halt || list_empty(&c->halt_fifo))) { + spin_unlock_irq(&c->fifo_lock); + mutex_unlock(&c->nq_mutex); continue; + } + + mbo = list_pop_mbo(&c->halt_fifo); + spin_unlock_irq(&c->fifo_lock); if (c->cfg.direction == MOST_CH_RX) mbo->buffer_length = c->cfg.buffer_size; - if (unlikely(enqueue(mbo->ifp, mbo->hdm_channel_id, mbo))) { + ret = enqueue(mbo->ifp, mbo->hdm_channel_id, mbo); + mutex_unlock(&c->nq_mutex); + + if (unlikely(ret)) { pr_err("hdm enqueue failed\n"); nq_hdm_mbo(mbo); c->hdm_enqueue_task = NULL; @@ -1759,6 +1772,7 @@ struct kobject *most_register_interface(struct most_interface *iface) init_completion(&c->cleanup); atomic_set(&c->mbo_ref, 0); mutex_init(&c->start_mutex); + mutex_init(&c->nq_mutex); list_add_tail(&c->list, &inst->channel_list); } pr_info("registered new MOST device mdev%d (%s)\n", @@ -1824,8 +1838,12 @@ void most_stop_enqueue(struct most_interface *iface, int id) { struct most_c_obj *c = get_channel_by_iface(iface, id); - if (likely(c)) - c->enqueue_halt = true; + if (!c) + return; + + mutex_lock(&c->nq_mutex); + c->enqueue_halt = true; + mutex_unlock(&c->nq_mutex); } EXPORT_SYMBOL_GPL(most_stop_enqueue); @@ -1841,9 +1859,12 @@ void most_resume_enqueue(struct most_interface *iface, int id) { struct most_c_obj *c = get_channel_by_iface(iface, id); - if (unlikely(!c)) + if (!c) return; + + mutex_lock(&c->nq_mutex); c->enqueue_halt = false; + mutex_unlock(&c->nq_mutex); wake_up_interruptible(&c->hdm_fifo_wq); } -- cgit v0.10.2 From cf6a599ef700914d9237f4dcf7afe01dd2ca6368 Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Fri, 19 Aug 2016 11:12:55 +0200 Subject: staging: most: hdm-usb: assign spinlock to local variable This patch assigns the spinlock of struct mdev to local spinlock_t variable to get rid of all the ugly dereferencing. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index 8d8c72c..4156a30 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -206,14 +206,15 @@ static void free_anchored_buffers(struct most_dev *mdev, unsigned int channel, { struct mbo *mbo; struct buf_anchor *anchor, *tmp; + spinlock_t *lock = mdev->anchor_list_lock + channel; /* temp. lock */ unsigned long flags; - spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags); + spin_lock_irqsave(lock, flags); list_for_each_entry_safe(anchor, tmp, &mdev->anchor_list[channel], list) { struct urb *urb = anchor->urb; - spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags); + spin_unlock_irqrestore(lock, flags); if (likely(urb)) { mbo = urb->context; if (!irqs_disabled()) { @@ -229,11 +230,11 @@ static void free_anchored_buffers(struct most_dev *mdev, unsigned int channel, } usb_free_urb(urb); } - spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags); + spin_lock_irqsave(lock, flags); list_del(&anchor->list); kfree(anchor); } - spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags); + spin_unlock_irqrestore(lock, flags); } /** @@ -397,12 +398,14 @@ static void hdm_write_completion(struct urb *urb) struct device *dev; unsigned int channel; unsigned long flags; + spinlock_t *lock; /* temp. lock */ mbo = urb->context; anchor = mbo->priv; mdev = to_mdev(mbo->ifp); channel = mbo->hdm_channel_id; dev = &mdev->usb_device->dev; + lock = mdev->anchor_list_lock + channel; if ((urb->status == -ENOENT) || (urb->status == -ECONNRESET) || (!mdev->is_channel_healthy[channel])) { @@ -433,9 +436,9 @@ static void hdm_write_completion(struct urb *urb) mbo->processed_length = urb->actual_length; } - spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags); + spin_lock_irqsave(lock, flags); list_del(&anchor->list); - spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags); + spin_unlock_irqrestore(lock, flags); kfree(anchor); if (likely(mbo->complete)) @@ -559,12 +562,14 @@ static void hdm_read_completion(struct urb *urb) struct device *dev; unsigned long flags; unsigned int channel; + spinlock_t *lock; /* temp. lock */ mbo = urb->context; anchor = mbo->priv; mdev = to_mdev(mbo->ifp); channel = mbo->hdm_channel_id; dev = &mdev->usb_device->dev; + lock = mdev->anchor_list_lock + channel; if ((urb->status == -ENOENT) || (urb->status == -ECONNRESET) || (!mdev->is_channel_healthy[channel])) { @@ -601,9 +606,9 @@ static void hdm_read_completion(struct urb *urb) mbo->status = MBO_E_INVAL; } } - spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags); + spin_lock_irqsave(lock, flags); list_del(&anchor->list); - spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags); + spin_unlock_irqrestore(lock, flags); kfree(anchor); if (likely(mbo->complete)) @@ -638,6 +643,7 @@ static int hdm_enqueue(struct most_interface *iface, int channel, unsigned long flags; unsigned long length; void *virt_address; + spinlock_t *lock; /* temp. lock */ if (unlikely(!iface || !mbo)) return -EIO; @@ -697,9 +703,10 @@ static int hdm_enqueue(struct most_interface *iface, int channel, } urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags); + lock = mdev->anchor_list_lock + channel; + spin_lock_irqsave(lock, flags); list_add_tail(&anchor->list, &mdev->anchor_list[channel]); - spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags); + spin_unlock_irqrestore(lock, flags); retval = usb_submit_urb(urb, GFP_KERNEL); if (retval) { @@ -709,9 +716,9 @@ static int hdm_enqueue(struct most_interface *iface, int channel, return 0; _error_1: - spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags); + spin_lock_irqsave(lock, flags); list_del(&anchor->list); - spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags); + spin_unlock_irqrestore(lock, flags); kfree(anchor); _error: usb_free_urb(urb); -- cgit v0.10.2 From b24c9fe9fcf9c7a04fa08e5c1da7d156011e6b63 Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Fri, 19 Aug 2016 11:12:56 +0200 Subject: staging: most: hdm-usb: synchronize release of struct buf_anchor In case a channel that is going to be destroyed has been tagged as not "healthy" by the function hdm_poison_channel() while the functions hdm_write_completion() or hdm_read_completion() are being executed, they race for destruction of buf_anchor. This patch fixes the problem. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index 4156a30..26b5c1b 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -285,6 +285,8 @@ static unsigned int get_stream_frame_size(struct most_channel_config *cfg) static int hdm_poison_channel(struct most_interface *iface, int channel) { struct most_dev *mdev; + unsigned long flags; + spinlock_t *lock; /* temp. lock */ mdev = to_mdev(iface); if (unlikely(!iface)) { @@ -296,7 +298,10 @@ static int hdm_poison_channel(struct most_interface *iface, int channel) return -ECHRNG; } + lock = mdev->anchor_list_lock + channel; + spin_lock_irqsave(lock, flags); mdev->is_channel_healthy[channel] = false; + spin_unlock_irqrestore(lock, flags); cancel_work_sync(&mdev->clear_work[channel].ws); @@ -407,8 +412,10 @@ static void hdm_write_completion(struct urb *urb) dev = &mdev->usb_device->dev; lock = mdev->anchor_list_lock + channel; + spin_lock_irqsave(lock, flags); if ((urb->status == -ENOENT) || (urb->status == -ECONNRESET) || (!mdev->is_channel_healthy[channel])) { + spin_unlock_irqrestore(lock, flags); complete(&anchor->urb_compl); return; } @@ -419,6 +426,7 @@ static void hdm_write_completion(struct urb *urb) case -EPIPE: dev_warn(dev, "Broken OUT pipe detected\n"); mdev->is_channel_healthy[channel] = false; + spin_unlock_irqrestore(lock, flags); mbo->status = MBO_E_INVAL; mdev->clear_work[channel].pipe = urb->pipe; schedule_work(&mdev->clear_work[channel].ws); @@ -436,7 +444,6 @@ static void hdm_write_completion(struct urb *urb) mbo->processed_length = urb->actual_length; } - spin_lock_irqsave(lock, flags); list_del(&anchor->list); spin_unlock_irqrestore(lock, flags); kfree(anchor); @@ -571,8 +578,10 @@ static void hdm_read_completion(struct urb *urb) dev = &mdev->usb_device->dev; lock = mdev->anchor_list_lock + channel; + spin_lock_irqsave(lock, flags); if ((urb->status == -ENOENT) || (urb->status == -ECONNRESET) || (!mdev->is_channel_healthy[channel])) { + spin_unlock_irqrestore(lock, flags); complete(&anchor->urb_compl); return; } @@ -583,6 +592,7 @@ static void hdm_read_completion(struct urb *urb) case -EPIPE: dev_warn(dev, "Broken IN pipe detected\n"); mdev->is_channel_healthy[channel] = false; + spin_unlock_irqrestore(lock, flags); mbo->status = MBO_E_INVAL; mdev->clear_work[channel].pipe = urb->pipe; schedule_work(&mdev->clear_work[channel].ws); @@ -606,7 +616,7 @@ static void hdm_read_completion(struct urb *urb) mbo->status = MBO_E_INVAL; } } - spin_lock_irqsave(lock, flags); + list_del(&anchor->list); spin_unlock_irqrestore(lock, flags); kfree(anchor); -- cgit v0.10.2 From 4b1a7cf1cc6aa0ae1a946be8ddddefcd61ff49f1 Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Fri, 19 Aug 2016 11:12:57 +0200 Subject: staging: most: hdm-usb: remove completion object Waiting for the urb_compl object to complete evaluates always as false. This patch removes this unnecessary completion object. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index 26b5c1b..29e98dc 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -72,7 +72,6 @@ struct buf_anchor { struct urb *urb; struct list_head list; - struct completion urb_compl; }; /** @@ -217,12 +216,7 @@ static void free_anchored_buffers(struct most_dev *mdev, unsigned int channel, spin_unlock_irqrestore(lock, flags); if (likely(urb)) { mbo = urb->context; - if (!irqs_disabled()) { - usb_kill_urb(urb); - } else { - usb_unlink_urb(urb); - wait_for_completion(&anchor->urb_compl); - } + usb_kill_urb(urb); if ((mbo) && (mbo->complete)) { mbo->status = status; mbo->processed_length = 0; @@ -416,7 +410,6 @@ static void hdm_write_completion(struct urb *urb) if ((urb->status == -ENOENT) || (urb->status == -ECONNRESET) || (!mdev->is_channel_healthy[channel])) { spin_unlock_irqrestore(lock, flags); - complete(&anchor->urb_compl); return; } @@ -582,7 +575,6 @@ static void hdm_read_completion(struct urb *urb) if ((urb->status == -ENOENT) || (urb->status == -ECONNRESET) || (!mdev->is_channel_healthy[channel])) { spin_unlock_irqrestore(lock, flags); - complete(&anchor->urb_compl); return; } @@ -678,7 +670,6 @@ static int hdm_enqueue(struct most_interface *iface, int channel, } anchor->urb = urb; - init_completion(&anchor->urb_compl); mbo->priv = anchor; if ((mdev->padding_active[channel]) && -- cgit v0.10.2 From dd53ecbace23f61d10bf13cc678e36e85290a28b Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Fri, 19 Aug 2016 11:12:58 +0200 Subject: staging: most: hdm-usb: remove redundant parenthesis This patch removes unnecessary parenthesis in boolean expressions. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index 29e98dc..ffe1519 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -217,7 +217,7 @@ static void free_anchored_buffers(struct most_dev *mdev, unsigned int channel, if (likely(urb)) { mbo = urb->context; usb_kill_urb(urb); - if ((mbo) && (mbo->complete)) { + if (mbo && mbo->complete) { mbo->status = status; mbo->processed_length = 0; mbo->complete(mbo); @@ -287,7 +287,7 @@ static int hdm_poison_channel(struct most_interface *iface, int channel) dev_warn(&mdev->usb_device->dev, "Poison: Bad interface.\n"); return -EIO; } - if (unlikely((channel < 0) || (channel >= iface->num_channels))) { + if (unlikely(channel < 0 || channel >= iface->num_channels)) { dev_warn(&mdev->usb_device->dev, "Channel ID out of range.\n"); return -ECHRNG; } @@ -407,8 +407,8 @@ static void hdm_write_completion(struct urb *urb) lock = mdev->anchor_list_lock + channel; spin_lock_irqsave(lock, flags); - if ((urb->status == -ENOENT) || (urb->status == -ECONNRESET) || - (!mdev->is_channel_healthy[channel])) { + if (urb->status == -ENOENT || urb->status == -ECONNRESET || + !mdev->is_channel_healthy[channel]) { spin_unlock_irqrestore(lock, flags); return; } @@ -572,8 +572,8 @@ static void hdm_read_completion(struct urb *urb) lock = mdev->anchor_list_lock + channel; spin_lock_irqsave(lock, flags); - if ((urb->status == -ENOENT) || (urb->status == -ECONNRESET) || - (!mdev->is_channel_healthy[channel])) { + if (urb->status == -ENOENT || urb->status == -ECONNRESET || + !mdev->is_channel_healthy[channel]) { spin_unlock_irqrestore(lock, flags); return; } @@ -649,7 +649,7 @@ static int hdm_enqueue(struct most_interface *iface, int channel, if (unlikely(!iface || !mbo)) return -EIO; - if (unlikely(iface->num_channels <= channel) || (channel < 0)) + if (unlikely(iface->num_channels <= channel || channel < 0)) return -ECHRNG; mdev = to_mdev(iface); @@ -672,12 +672,11 @@ static int hdm_enqueue(struct most_interface *iface, int channel, anchor->urb = urb; mbo->priv = anchor; - if ((mdev->padding_active[channel]) && - (conf->direction & MOST_CH_TX)) - if (hdm_add_padding(mdev, channel, mbo)) { - retval = -EIO; - goto _error; - } + if ((conf->direction & MOST_CH_TX) && mdev->padding_active[channel] && + hdm_add_padding(mdev, channel, mbo)) { + retval = -EIO; + goto _error; + } urb->transfer_dma = mbo->bus_address; virt_address = mbo->virt_address; @@ -753,18 +752,18 @@ static int hdm_configure_channel(struct most_interface *iface, int channel, dev_err(dev, "Bad interface or config pointer.\n"); return -EINVAL; } - if (unlikely((channel < 0) || (channel >= iface->num_channels))) { + if (unlikely(channel < 0 || channel >= iface->num_channels)) { dev_err(dev, "Channel ID out of range.\n"); return -EINVAL; } - if ((!conf->num_buffers) || (!conf->buffer_size)) { + if (!conf->num_buffers || !conf->buffer_size) { dev_err(dev, "Misconfig: buffer size or #buffers zero.\n"); return -EINVAL; } - if (!(conf->data_type == MOST_CH_SYNC) && - !((conf->data_type == MOST_CH_ISOC_AVP) && - (conf->packets_per_xact != 0xFF))) { + if (conf->data_type != MOST_CH_SYNC && + !(conf->data_type == MOST_CH_ISOC_AVP && + conf->packets_per_xact != 0xFF)) { mdev->padding_active[channel] = false; goto exit; } @@ -773,7 +772,7 @@ static int hdm_configure_channel(struct most_interface *iface, int channel, temp_size = conf->buffer_size; frame_size = get_stream_frame_size(conf); - if ((frame_size == 0) || (frame_size > USB_MTU)) { + if (frame_size == 0 || frame_size > USB_MTU) { dev_warn(dev, "Misconfig: frame size wrong\n"); return -EINVAL; } @@ -909,13 +908,13 @@ static void wq_netinfo(struct work_struct *wq_obj) if (hdm_update_netinfo(mdev) < 0) return; - if ((prev_link_stat != mdev->link_stat) || - (prev_hw_addr[0] != mdev->hw_addr[0]) || - (prev_hw_addr[1] != mdev->hw_addr[1]) || - (prev_hw_addr[2] != mdev->hw_addr[2]) || - (prev_hw_addr[3] != mdev->hw_addr[3]) || - (prev_hw_addr[4] != mdev->hw_addr[4]) || - (prev_hw_addr[5] != mdev->hw_addr[5])) + if (prev_link_stat != mdev->link_stat || + prev_hw_addr[0] != mdev->hw_addr[0] || + prev_hw_addr[1] != mdev->hw_addr[1] || + prev_hw_addr[2] != mdev->hw_addr[2] || + prev_hw_addr[3] != mdev->hw_addr[3] || + prev_hw_addr[4] != mdev->hw_addr[4] || + prev_hw_addr[5] != mdev->hw_addr[5]) most_deliver_netinfo(&mdev->iface, mdev->link_stat, &mdev->hw_addr[0]); } -- cgit v0.10.2 From 089612f183efb488c10e98c11feb12a2ed8c31f0 Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Fri, 19 Aug 2016 11:12:59 +0200 Subject: staging: most: hdm-usb: init variables at declaration time This patch initializes variables by the time they are declared. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index ffe1519..453b641 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -278,11 +278,10 @@ static unsigned int get_stream_frame_size(struct most_channel_config *cfg) */ static int hdm_poison_channel(struct most_interface *iface, int channel) { - struct most_dev *mdev; + struct most_dev *mdev = to_mdev(iface); unsigned long flags; spinlock_t *lock; /* temp. lock */ - mdev = to_mdev(iface); if (unlikely(!iface)) { dev_warn(&mdev->usb_device->dev, "Poison: Bad interface.\n"); return -EIO; @@ -391,20 +390,13 @@ static int hdm_remove_padding(struct most_dev *mdev, int channel, */ static void hdm_write_completion(struct urb *urb) { - struct mbo *mbo; - struct buf_anchor *anchor; - struct most_dev *mdev; - struct device *dev; - unsigned int channel; + struct mbo *mbo = urb->context; + struct buf_anchor *anchor = mbo->priv; + struct most_dev *mdev = to_mdev(mbo->ifp); + unsigned int channel = mbo->hdm_channel_id; + struct device *dev = &mdev->usb_device->dev; + spinlock_t *lock = mdev->anchor_list_lock + channel; /* temp. lock */ unsigned long flags; - spinlock_t *lock; /* temp. lock */ - - mbo = urb->context; - anchor = mbo->priv; - mdev = to_mdev(mbo->ifp); - channel = mbo->hdm_channel_id; - dev = &mdev->usb_device->dev; - lock = mdev->anchor_list_lock + channel; spin_lock_irqsave(lock, flags); if (urb->status == -ENOENT || urb->status == -ECONNRESET || @@ -556,20 +548,13 @@ static void hdm_write_completion(struct urb *urb) */ static void hdm_read_completion(struct urb *urb) { - struct mbo *mbo; - struct buf_anchor *anchor; - struct most_dev *mdev; - struct device *dev; + struct mbo *mbo = urb->context; + struct buf_anchor *anchor = mbo->priv; + struct most_dev *mdev = to_mdev(mbo->ifp); + unsigned int channel = mbo->hdm_channel_id; + struct device *dev = &mdev->usb_device->dev; + spinlock_t *lock = mdev->anchor_list_lock + channel; /* temp. lock */ unsigned long flags; - unsigned int channel; - spinlock_t *lock; /* temp. lock */ - - mbo = urb->context; - anchor = mbo->priv; - mdev = to_mdev(mbo->ifp); - channel = mbo->hdm_channel_id; - dev = &mdev->usb_device->dev; - lock = mdev->anchor_list_lock + channel; spin_lock_irqsave(lock, flags); if (urb->status == -ENOENT || urb->status == -ECONNRESET || @@ -738,15 +723,13 @@ static int hdm_configure_channel(struct most_interface *iface, int channel, unsigned int frame_size; unsigned int temp_size; unsigned int tail_space; - struct most_dev *mdev; - struct device *dev; + struct most_dev *mdev = to_mdev(iface); + struct device *dev = &mdev->usb_device->dev; - mdev = to_mdev(iface); mdev->is_channel_healthy[channel] = true; mdev->clear_work[channel].channel = channel; mdev->clear_work[channel].mdev = mdev; INIT_WORK(&mdev->clear_work[channel].ws, wq_clear_halt); - dev = &mdev->usb_device->dev; if (unlikely(!iface || !conf)) { dev_err(dev, "Bad interface or config pointer.\n"); @@ -896,13 +879,10 @@ static void link_stat_timer_handler(unsigned long data) */ static void wq_netinfo(struct work_struct *wq_obj) { - struct most_dev *mdev; - int i, prev_link_stat; + struct most_dev *mdev = to_mdev_from_work(wq_obj); + int i, prev_link_stat = mdev->link_stat; u8 prev_hw_addr[6]; - mdev = to_mdev_from_work(wq_obj); - prev_link_stat = mdev->link_stat; - for (i = 0; i < 6; i++) prev_hw_addr[i] = mdev->hw_addr[i]; @@ -1174,10 +1154,9 @@ static struct kobj_type most_dci_ktype = { static struct most_dci_obj *create_most_dci_obj(struct kobject *parent) { - struct most_dci_obj *most_dci; + struct most_dci_obj *most_dci = kzalloc(sizeof(*most_dci), GFP_KERNEL); int retval; - most_dci = kzalloc(sizeof(*most_dci), GFP_KERNEL); if (!most_dci) return NULL; @@ -1214,21 +1193,17 @@ static void destroy_most_dci_obj(struct most_dci_obj *p) static int hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) { + struct usb_host_interface *usb_iface_desc = interface->cur_altsetting; + struct usb_device *usb_dev = interface_to_usbdev(interface); + struct device *dev = &usb_dev->dev; + struct most_dev *mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); unsigned int i; unsigned int num_endpoints; struct most_channel_capability *tmp_cap; - struct most_dev *mdev; - struct usb_device *usb_dev; - struct device *dev; - struct usb_host_interface *usb_iface_desc; struct usb_endpoint_descriptor *ep_desc; int ret = 0; int err; - usb_iface_desc = interface->cur_altsetting; - usb_dev = interface_to_usbdev(interface); - dev = &usb_dev->dev; - mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); if (!mdev) goto exit_ENOMEM; @@ -1378,9 +1353,8 @@ exit_ENOMEM: */ static void hdm_disconnect(struct usb_interface *interface) { - struct most_dev *mdev; + struct most_dev *mdev = usb_get_intfdata(interface); - mdev = usb_get_intfdata(interface); mutex_lock(&mdev->io_mutex); usb_set_intfdata(interface, NULL); mdev->usb_device = NULL; -- cgit v0.10.2 From 9736fc0434f4b6ad257ae1a212e4e82336b66615 Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Fri, 19 Aug 2016 11:13:00 +0200 Subject: staging: most: hdm-usb: remove unnecessary status assignment The USB completion callbacks set the status field of an MBO object before scheduling the clear_work. This patch removes this redundant assignment as the work_struct does the same for all MBOs. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index 453b641..f44f27e 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -412,7 +412,6 @@ static void hdm_write_completion(struct urb *urb) dev_warn(dev, "Broken OUT pipe detected\n"); mdev->is_channel_healthy[channel] = false; spin_unlock_irqrestore(lock, flags); - mbo->status = MBO_E_INVAL; mdev->clear_work[channel].pipe = urb->pipe; schedule_work(&mdev->clear_work[channel].ws); return; @@ -570,7 +569,6 @@ static void hdm_read_completion(struct urb *urb) dev_warn(dev, "Broken IN pipe detected\n"); mdev->is_channel_healthy[channel] = false; spin_unlock_irqrestore(lock, flags); - mbo->status = MBO_E_INVAL; mdev->clear_work[channel].pipe = urb->pipe; schedule_work(&mdev->clear_work[channel].ws); return; -- cgit v0.10.2 From 5bf9bd8d19834f9ace200af06a58a032542fc427 Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Fri, 19 Aug 2016 11:13:01 +0200 Subject: staging: most: hdm-usb: add support for new USB gadget This patch is needed to make the driver support Microchip's OS81210 USB MOST network interface controller. It simply adds the gadget's product ID to the driver's ID table. Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index f44f27e..08c4a3b 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -45,6 +45,7 @@ #define USB_DEV_ID_BRDG 0xC001 /* PID: USB Bridge */ #define USB_DEV_ID_OS81118 0xCF18 /* PID: USB OS81118 */ #define USB_DEV_ID_OS81119 0xCF19 /* PID: USB OS81119 */ +#define USB_DEV_ID_OS81210 0xCF30 /* PID: USB OS81210 */ /* DRCI Addresses */ #define DRCI_REG_NI_STATE 0x0100 #define DRCI_REG_PACKET_BW 0x0101 @@ -935,6 +936,7 @@ static struct usb_device_id usbid[] = { { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_BRDG), }, { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_OS81118), }, { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_OS81119), }, + { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_OS81210), }, { } /* Terminating entry */ }; @@ -1304,7 +1306,8 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) mutex_lock(&mdev->io_mutex); if (le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81118 || - le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81119) { + le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81119 || + le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81210) { /* this increments the reference count of the instance * object of the core */ -- cgit v0.10.2 From 6ad124d53a761b01b5b2ab78e6e77f0cef7a2b9e Mon Sep 17 00:00:00 2001 From: Ian Abbott <abbotti@mev.co.uk> Date: Mon, 20 Jun 2016 14:05:48 +0100 Subject: staging: comedi: plx9080.h: define PLX_<REG>_TO_<FIELD>(r) macros Various macros in "plx9080.h" take the form `PLX_<REG>_<FIELD>(x)`, where `<REG>` is a register name, `<FIELD>` is a field within the register, and `x` is a value for the field specified by the caller. The macros construct a partial register register with the specified field value placed in the appropriate bits of the register value, and other bits of the register value zeroed. Add corresponding macros of the form `PLX_<REG>_TO_<FIELD>(r)` that extract a field value from a specified register values. Remove macros of the form `PLX_<REG>_<FIELD>_SHIFT` that specified the bit position of a field within a register value as they are no longer useful. Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/drivers/plx9080.h b/drivers/staging/comedi/drivers/plx9080.h index 0e20cc5..072a91b 100644 --- a/drivers/staging/comedi/drivers/plx9080.h +++ b/drivers/staging/comedi/drivers/plx9080.h @@ -89,11 +89,11 @@ struct plx_dma_desc { /* Local Bus Latency Timer */ #define PLX_MARBR_LT(x) (BIT(0) * ((x) & 0xff)) #define PLX_MARBR_LT_MASK GENMASK(7, 0) -#define PLX_MARBR_LT_SHIFT 0 +#define PLX_MARBR_TO_LT(r) ((r) & PLX_MARBR_LT_MASK) /* Local Bus Pause Timer */ #define PLX_MARBR_PT(x) (BIT(8) * ((x) & 0xff)) #define PLX_MARBR_PT_MASK GENMASK(15, 8) -#define PLX_MARBR_PT_SHIFT 8 +#define PLX_MARBR_TO_PT(r) (((r) & PLX_MARBR_PT_MASK) >> 8) /* Local Bus Latency Timer Enable */ #define PLX_MARBR_LTEN BIT(16) /* Local Bus Pause Timer Enable */ @@ -171,11 +171,10 @@ struct plx_dma_desc { #define PLX_LBRD_MSWIDTH32 (BIT(0) * 2) /* 32 bits wide */ #define PLX_LBRD_MSWIDTH32A (BIT(0) * 3) /* 32 bits wide */ #define PLX_LBRD_MSWIDTH_MASK GENMASK(1, 0) -#define PLX_LBRD_MSWIDTH_SHIFT 0 /* Memory Space Internal Wait States */ #define PLX_LBRD_MSIWS(x) (BIT(2) * ((x) & 0xf)) #define PLX_LBRD_MSIWS_MASK GENMASK(5, 2) -#define PLX_LBRD_MSIWS_SHIFT 2 +#define PLX_LBRD_TO_MSIWS(r) (((r) & PLS_LBRD_MSIWS_MASK) >> 2) /* Memory Space Ready Input Enable */ #define PLX_LBRD_MSREADYIEN BIT(6) /* Memory Space BTERM# Input Enable */ @@ -193,18 +192,17 @@ struct plx_dma_desc { /* Prefetch Counter */ #define PLX_LBRD_PFCOUNT(x) (BIT(11) * ((x) & 0xf)) #define PLX_LBRD_PFCOUNT_MASK GENMASK(14, 11) -#define PLX_LBRD_PFCOUNT_SHIFT 11 +#define PLX_LBRD_TO_PFCOUNT(r) (((r) & PLX_LBRD_PFCOUNT_MASK) >> 11) /* Expansion ROM Space Local Bus Width (LBRD0 only) */ #define PLX_LBRD0_EROMWIDTH8 (BIT(16) * 0) /* 8 bits wide */ #define PLX_LBRD0_EROMWIDTH16 (BIT(16) * 1) /* 16 bits wide */ #define PLX_LBRD0_EROMWIDTH32 (BIT(16) * 2) /* 32 bits wide */ #define PLX_LBRD0_EROMWIDTH32A (BIT(16) * 3) /* 32 bits wide */ #define PLX_LBRD0_EROMWIDTH_MASK GENMASK(17, 16) -#define PLX_LBRD0_EROMWIDTH_SHIFT 16 /* Expansion ROM Space Internal Wait States (LBRD0 only) */ #define PLX_LBRD0_EROMIWS(x) (BIT(18) * ((x) & 0xf)) #define PLX_LBRD0_EROMIWS_MASK GENMASK(21, 18) -#define PLX_LBRD0_EROMIWS_SHIFT 18 +#define PLX_LBRD0_TO_EROMIWS(r) (((r) & PLX_LBRD0_EROMIWS_MASK) >> 18) /* Expansion ROM Space Ready Input Enable (LBDR0 only) */ #define PLX_LBRD0_EROMREADYIEN BIT(22) /* Expansion ROM Space BTERM# Input Enable (LBRD0 only) */ @@ -220,7 +218,7 @@ struct plx_dma_desc { /* PCI Target Retry Delay Clocks / 8 (LBRD0 only) */ #define PLX_LBRD0_TRDELAY(x) (BIT(28) * ((x) & 0xF)) #define PLX_LBRD0_TRDELAY_MASK GENMASK(31, 28) -#define PLX_LBRD0_TRDELAY_SHIFT 28 +#define PLX_LBRD0_TO_TRDELAY(r) (((r) & PLX_LBRD0_TRDELAY_MASK) >> 28) /* Local Range Register for Direct Master to PCI */ #define PLX_REG_DMRR 0x001c @@ -279,19 +277,19 @@ struct plx_dma_desc { /* Register Number */ #define PLX_DMCFGA_REGNUM(x) (BIT(2) * ((x) & 0x3f)) #define PLX_DMCFGA_REGNUM_MASK GENMASK(7, 2) -#define PLX_DMCFGA_REGNUM_SHIFT 2 +#define PLX_DMCFGA_TO_REGNUM(r) (((r) & PLX_DMCFGA_REGNUM_MASK) >> 2) /* Function Number */ #define PLX_DMCFGA_FUNCNUM(x) (BIT(8) * ((x) & 0x7)) #define PLX_DMCFGA_FUNCNUM_MASK GENMASK(10, 8) -#define PLX_DMCFGA_FUNCNUM_SHIFT 8 +#define PLX_DMCFGA_TO_FUNCNUM(r) (((r) & PLX_DMCFGA_FUNCNUM_MASK) >> 8) /* Device Number */ #define PLX_DMCFGA_DEVNUM(x) (BIT(11) * ((x) & 0x1f)) #define PLX_DMCFGA_DEVNUM_MASK GENMASK(15, 11) -#define PLX_DMCFGA_DEVNUM_SHIFT 11 +#define PLX_DMCFGA_TO_DEVNUM(r) (((r) & PLX_DMCFGA_DEVNUM_MASK) >> 11) /* Bus Number */ #define PLX_DMCFGA_BUSNUM(x) (BIT(16) * ((x) & 0xff)) #define PLX_DMCFGA_BUSNUM_MASK GENMASK(23, 16) -#define PLX_DMCFGA_BUSNUM_SHIFT 16 +#define PLX_DMCFGA_TO_BUSNUM(r) (((r) & PLX_DMCFGA_BUSNUM_MASK) >> 16) /* Configuration Enable */ #define PLX_DMCFGA_CONFIGEN BIT(31) @@ -402,22 +400,22 @@ struct plx_dma_desc { /* PCI Read Command Code For DMA */ #define PLX_CNTRL_CCRDMA(x) (BIT(0) * ((x) & 0xf)) #define PLX_CNTRL_CCRDMA_MASK GENMASK(3, 0) -#define PLX_CNTRL_CCRDMA_SHIFT 0 +#define PLX_CNTRL_TO_CCRDMA(r) ((r) & PLX_CNTRL_CCRDMA_MASK) #define PLX_CNTRL_CCRDMA_NORMAL PLX_CNTRL_CCRDMA(14) /* value after reset */ /* PCI Write Command Code For DMA 0 */ #define PLX_CNTRL_CCWDMA(x) (BIT(4) * ((x) & 0xf)) #define PLX_CNTRL_CCWDMA_MASK GENMASK(7, 4) -#define PLX_CNTRL_CCWDMA_SHIFT 4 +#define PLX_CNTRL_TO_CCWDMA(r) (((r) & PLX_CNTRL_CCWDMA_MASK) >> 4) #define PLX_CNTRL_CCWDMA_NORMAL PLX_CNTRL_CCWDMA(7) /* value after reset */ /* PCI Memory Read Command Code For Direct Master */ #define PLX_CNTRL_CCRDM(x) (BIT(8) * ((x) & 0xf)) #define PLX_CNTRL_CCRDM_MASK GENMASK(11, 8) -#define PLX_CNTRL_CCRDM_SHIFT 8 +#define PLX_CNTRL_TO_CCRDM(r) (((r) & PLX_CNTRL_CCRDM_MASK) >> 8) #define PLX_CNTRL_CCRDM_NORMAL PLX_CNTRL_CCRDM(6) /* value after reset */ /* PCI Memory Write Command Code For Direct Master */ #define PLX_CNTRL_CCWDM(x) (BIT(12) * ((x) & 0xf)) #define PLX_CNTRL_CCWDM_MASK GENMASK(15, 12) -#define PLX_CNTRL_CCWDM_SHIFT 12 +#define PLX_CNTRL_TO_CCWDM(r) (((r) & PLX_CNTRL_CCWDM_MASK) >> 12) #define PLX_CNTRL_CCWDM_NORMAL PLX_CNTRL_CCWDM(7) /* value after reset */ /* General Purpose Output (USERO) */ #define PLX_CNTRL_USERO BIT(16) @@ -469,11 +467,10 @@ struct plx_dma_desc { #define PLX_DMAMODE_WIDTH32 (BIT(0) * 2) /* 32 bits wide */ #define PLX_DMAMODE_WIDTH32A (BIT(0) * 3) /* 32 bits wide */ #define PLX_DMAMODE_WIDTH_MASK GENMASK(1, 0) -#define PLX_DMAMODE_WIDTH_SHIFT 0 /* Internal Wait States */ #define PLX_DMAMODE_IWS(x) (BIT(2) * ((x) & 0xf)) #define PLX_DMAMODE_IWS_MASK GENMASK(5, 2) -#define PLX_DMAMODE_SHIFT 2 +#define PLX_DMAMODE_TO_IWS(r) (((r) & PLX_DMAMODE_IWS_MASK) >> 2) /* Ready Input Enable */ #define PLX_DMAMODE_READYIEN BIT(6) /* BTERM# Input Enable */ @@ -560,35 +557,35 @@ struct plx_dma_desc { /* DMA Channel 0 PCI-to-Local Almost Full (divided by 2, minus 1) */ #define PLX_DMATHR_C0PLAF(x) (BIT(0) * ((x) & 0xf)) #define PLX_DMATHR_C0PLAF_MASK GENMASK(3, 0) -#define PLX_DMATHR_C0PLAF_SHIFT 0 +#define PLX_DMATHR_TO_C0PLAF(r) ((r) & PLX_DMATHR_C0PLAF_MASK) /* DMA Channel 0 Local-to-PCI Almost Empty (divided by 2, minus 1) */ #define PLX_DMATHR_C0LPAE(x) (BIT(4) * ((x) & 0xf)) #define PLX_DMATHR_C0LPAE_MASK GENMASK(7, 4) -#define PLX_DMATHR_C0LPAE_SHIFT 4 +#define PLX_DMATHR_TO_C0LPAE(r) (((r) & PLX_DMATHR_C0LPAE_MASK) >> 4) /* DMA Channel 0 Local-to-PCI Almost Full (divided by 2, minus 1) */ #define PLX_DMATHR_C0LPAF(x) (BIT(8) * ((x) & 0xf)) #define PLX_DMATHR_C0LPAF_MASK GENMASK(11, 8) -#define PLX_DMATHR_C0LPAF_SHIFT 8 +#define PLX_DMATHR_TO_C0LPAF(r) (((r) & PLX_DMATHR_C0LPAF_MASK) >> 8) /* DMA Channel 0 PCI-to-Local Almost Empty (divided by 2, minus 1) */ #define PLX_DMATHR_C0PLAE(x) (BIT(12) * ((x) & 0xf)) #define PLX_DMATHR_C0PLAE_MASK GENMASK(15, 12) -#define PLX_DMATHR_C0PLAE_SHIFT 12 +#define PLX_DMATHR_TO_C0PLAE(r) (((r) & PLX_DMATHR_C0PLAE_MASK) >> 12) /* DMA Channel 1 PCI-to-Local Almost Full (divided by 2, minus 1) */ #define PLX_DMATHR_C1PLAF(x) (BIT(16) * ((x) & 0xf)) #define PLX_DMATHR_C1PLAF_MASK GENMASK(19, 16) -#define PLX_DMATHR_C1PLAF_SHIFT 16 +#define PLX_DMATHR_TO_C1PLAF(r) (((r) & PLX_DMATHR_C1PLAF_MASK) >> 16) /* DMA Channel 1 Local-to-PCI Almost Empty (divided by 2, minus 1) */ #define PLX_DMATHR_C1LPAE(x) (BIT(20) * ((x) & 0xf)) #define PLX_DMATHR_C1LPAE_MASK GENMASK(23, 20) -#define PLX_DMATHR_C1LPAE_SHIFT 20 +#define PLX_DMATHR_TO_C1LPAE(r) (((r) & PLX_DMATHR_C1LPAE_MASK) >> 20) /* DMA Channel 1 Local-to-PCI Almost Full (divided by 2, minus 1) */ #define PLX_DMATHR_C1LPAF(x) (BIT(24) * ((x) & 0xf)) #define PLX_DMATHR_C1LPAF_MASK GENMASK(27, 24) -#define PLX_DMATHR_C1LPAF_SHIFT 24 +#define PLX_DMATHR_TO_C1LPAF(r) (((r) & PLX_DMATHR_C1LPAF_MASK) >> 24) /* DMA Channel 1 PCI-to-Local Almost Empty (divided by 2, minus 1) */ #define PLX_DMATHR_C1PLAE(x) (BIT(28) * ((x) & 0xf)) #define PLX_DMATHR_C1PLAE_MASK GENMASK(31, 28) -#define PLX_DMATHR_C1PLAE_SHIFT 28 +#define PLX_DMATHR_TO_C1PLAE(r) (((r) & PLX_DMATHR_C1PLAE_MASK) >> 28) /* * Messaging Queue Registers OPLFIS, OPLFIM, IQP, OQP, MQCR, QBAR, IFHPR, -- cgit v0.10.2 From 686869b451b0b106cf6b365361fd577080fbca7a Mon Sep 17 00:00:00 2001 From: Ian Abbott <abbotti@mev.co.uk> Date: Mon, 20 Jun 2016 14:05:49 +0100 Subject: staging: comedi: plx9080.h: rename some macros for consistency Most of the macros in "plx9080.h" that define register values are single-bits flags of the form `PLX_<REG>_<FLAG>`, or are constant, multi-bit values of the form `PLX_<REG>_<FIELD>_<VAL>`, or are non-constant, function-like macros of the form `PLX_<REG>_<FIELD>(x)`. Some of the macros for constant, multi-bit values do not currently fit the pattern, so rename them for consistency. Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index 1f9c08a..aae839e 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -1327,9 +1327,9 @@ static void init_plx9080(struct comedi_device *dev) bits |= PLX_DMAMODE_BURSTEN; /* 4020 uses 32 bit dma */ if (board->layout == LAYOUT_4020) - bits |= PLX_DMAMODE_WIDTH32; + bits |= PLX_DMAMODE_WIDTH_32; else /* localspace0 bus is 16 bits wide */ - bits |= PLX_DMAMODE_WIDTH16; + bits |= PLX_DMAMODE_WIDTH_16; writel(bits, plx_iobase + PLX_REG_DMAMODE1); if (ao_cmd_is_supported(board)) writel(bits, plx_iobase + PLX_REG_DMAMODE0); diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c index af4b417..e5b9484 100644 --- a/drivers/staging/comedi/drivers/gsc_hpdi.c +++ b/drivers/staging/comedi/drivers/gsc_hpdi.c @@ -582,7 +582,7 @@ static void gsc_hpdi_init_plx9080(struct comedi_device *dev) bits |= PLX_DMAMODE_DEMAND; /* enable local burst mode */ bits |= PLX_DMAMODE_BURSTEN; - bits |= PLX_DMAMODE_WIDTH32; + bits |= PLX_DMAMODE_WIDTH_32; writel(bits, plx_iobase + PLX_REG_DMAMODE0); } diff --git a/drivers/staging/comedi/drivers/plx9080.h b/drivers/staging/comedi/drivers/plx9080.h index 072a91b..e23e63a 100644 --- a/drivers/staging/comedi/drivers/plx9080.h +++ b/drivers/staging/comedi/drivers/plx9080.h @@ -60,9 +60,9 @@ struct plx_dma_desc { #define PLX_REG_LAS1RR 0x00f0 #define PLX_LASRR_IO BIT(0) /* Map to: 1=I/O, 0=Mem */ -#define PLX_LASRR_ANY32 (BIT(1) * 0) /* Locate anywhere in 32 bit */ -#define PLX_LASRR_LT1MB (BIT(1) * 1) /* Locate in 1st meg */ -#define PLX_LASRR_ANY64 (BIT(1) * 2) /* Locate anywhere in 64 bit */ +#define PLX_LASRR_MLOC_ANY32 (BIT(1) * 0) /* Locate anywhere in 32 bit */ +#define PLX_LASRR_MLOC_LT1MB (BIT(1) * 1) /* Locate in 1st meg */ +#define PLX_LASRR_MLOC_ANY64 (BIT(1) * 2) /* Locate anywhere in 64 bit */ #define PLX_LASRR_MLOC_MASK GENMASK(2, 1) /* Memory location bits */ #define PLX_LASRR_PREFETCH BIT(3) /* Memory is prefetchable */ /* bits that specify range for memory space decode bits */ @@ -166,10 +166,10 @@ struct plx_dma_desc { #define PLX_REG_LBRD1 0x00f8 /* Memory Space Local Bus Width */ -#define PLX_LBRD_MSWIDTH8 (BIT(0) * 0) /* 8 bits wide */ -#define PLX_LBRD_MSWIDTH16 (BIT(0) * 1) /* 16 bits wide */ -#define PLX_LBRD_MSWIDTH32 (BIT(0) * 2) /* 32 bits wide */ -#define PLX_LBRD_MSWIDTH32A (BIT(0) * 3) /* 32 bits wide */ +#define PLX_LBRD_MSWIDTH_8 (BIT(0) * 0) /* 8 bits wide */ +#define PLX_LBRD_MSWIDTH_16 (BIT(0) * 1) /* 16 bits wide */ +#define PLX_LBRD_MSWIDTH_32 (BIT(0) * 2) /* 32 bits wide */ +#define PLX_LBRD_MSWIDTH_32A (BIT(0) * 3) /* 32 bits wide */ #define PLX_LBRD_MSWIDTH_MASK GENMASK(1, 0) /* Memory Space Internal Wait States */ #define PLX_LBRD_MSIWS(x) (BIT(2) * ((x) & 0xf)) @@ -194,10 +194,10 @@ struct plx_dma_desc { #define PLX_LBRD_PFCOUNT_MASK GENMASK(14, 11) #define PLX_LBRD_TO_PFCOUNT(r) (((r) & PLX_LBRD_PFCOUNT_MASK) >> 11) /* Expansion ROM Space Local Bus Width (LBRD0 only) */ -#define PLX_LBRD0_EROMWIDTH8 (BIT(16) * 0) /* 8 bits wide */ -#define PLX_LBRD0_EROMWIDTH16 (BIT(16) * 1) /* 16 bits wide */ -#define PLX_LBRD0_EROMWIDTH32 (BIT(16) * 2) /* 32 bits wide */ -#define PLX_LBRD0_EROMWIDTH32A (BIT(16) * 3) /* 32 bits wide */ +#define PLX_LBRD0_EROMWIDTH_8 (BIT(16) * 0) /* 8 bits wide */ +#define PLX_LBRD0_EROMWIDTH_16 (BIT(16) * 1) /* 16 bits wide */ +#define PLX_LBRD0_EROMWIDTH_32 (BIT(16) * 2) /* 32 bits wide */ +#define PLX_LBRD0_EROMWIDTH_32A (BIT(16) * 3) /* 32 bits wide */ #define PLX_LBRD0_EROMWIDTH_MASK GENMASK(17, 16) /* Expansion ROM Space Internal Wait States (LBRD0 only) */ #define PLX_LBRD0_EROMIWS(x) (BIT(18) * ((x) & 0xf)) @@ -239,10 +239,10 @@ struct plx_dma_desc { /* LLOCK# Input Enable */ #define PLX_DMPBAM_LLOCKIEN BIT(2) /* Direct Master Read Prefetch Size Control (bits 12, 3) */ -#define PLX_DMPBAM_RPSIZECONT ((BIT(12) * 0) | (BIT(3) * 0)) -#define PLX_DMPBAM_RPSIZE4 ((BIT(12) * 0) | (BIT(3) * 1)) -#define PLX_DMPBAM_RPSIZE8 ((BIT(12) * 1) | (BIT(3) * 0)) -#define PLX_DMPBAM_RPSIZE16 ((BIT(12) * 1) | (BIT(3) * 1)) +#define PLX_DMPBAM_RPSIZE_CONT ((BIT(12) * 0) | (BIT(3) * 0)) +#define PLX_DMPBAM_RPSIZE_4 ((BIT(12) * 0) | (BIT(3) * 1)) +#define PLX_DMPBAM_RPSIZE_8 ((BIT(12) * 1) | (BIT(3) * 0)) +#define PLX_DMPBAM_RPSIZE_16 ((BIT(12) * 1) | (BIT(3) * 1)) #define PLX_DMPBAM_RPSIZE_MASK (BIT(12) | BIT(3)) /* Direct Master PCI Read Mode - deassert IRDY when FIFO full */ #define PLX_DMPBAM_RMIRDY BIT(4) @@ -259,10 +259,10 @@ struct plx_dma_desc { /* I/O Remap Select */ #define PLX_DMPBAM_IOREMAPSEL BIT(13) /* Direct Master Write Delay */ -#define PLX_DMPBAM_WDELAYNONE (BIT(14) * 0) -#define PLX_DMPBAM_WDELAY4 (BIT(14) * 1) -#define PLX_DMPBAM_WDELAY8 (BIT(14) * 2) -#define PLX_DMPBAM_WDELAY16 (BIT(14) * 3) +#define PLX_DMPBAM_WDELAY_NONE (BIT(14) * 0) +#define PLX_DMPBAM_WDELAY_4 (BIT(14) * 1) +#define PLX_DMPBAM_WDELAY_8 (BIT(14) * 2) +#define PLX_DMPBAM_WDELAY_16 (BIT(14) * 3) #define PLX_DMPBAM_WDELAY_MASK GENMASK(15, 14) /* Remap of Local-to-PCI Space Into PCI Address Space */ #define PLX_DMPBAM_REMAP_MASK GENMASK(31, 16) @@ -462,10 +462,10 @@ struct plx_dma_desc { #define PLX_REG_DMAMODE1 0x0094 /* Local Bus Width */ -#define PLX_DMAMODE_WIDTH8 (BIT(0) * 0) /* 8 bits wide */ -#define PLX_DMAMODE_WIDTH16 (BIT(0) * 1) /* 16 bits wide */ -#define PLX_DMAMODE_WIDTH32 (BIT(0) * 2) /* 32 bits wide */ -#define PLX_DMAMODE_WIDTH32A (BIT(0) * 3) /* 32 bits wide */ +#define PLX_DMAMODE_WIDTH_8 (BIT(0) * 0) /* 8 bits wide */ +#define PLX_DMAMODE_WIDTH_16 (BIT(0) * 1) /* 16 bits wide */ +#define PLX_DMAMODE_WIDTH_32 (BIT(0) * 2) /* 32 bits wide */ +#define PLX_DMAMODE_WIDTH_32A (BIT(0) * 3) /* 32 bits wide */ #define PLX_DMAMODE_WIDTH_MASK GENMASK(1, 0) /* Internal Wait States */ #define PLX_DMAMODE_IWS(x) (BIT(2) * ((x) & 0xf)) -- cgit v0.10.2 From a6672530f6fc57e182a6f66d2017589b5b056994 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten <hsweeten@visionengravers.com> Date: Mon, 20 Jun 2016 11:12:32 -0700 Subject: staging: comedi: addi_apci_3501: remove timer/counter subdevice support This driver is for a simple 4/8 channel analog output board with 2 isolated digital inputs and 2 isolated digital outputs. Support for these subdevices is provided by the driver. The boards also has a watchdog timer that can be used to reset the analog outputs. It can also be used as a general purpose 12-bit timer when the watchdog function is not necessary. The current support code for this subdevice is broken. It does not follow the comedi API and requires some out-of-tree patches in order to even work. Remove the subdevice support. If a proper register map can be located for this board we can add support back later. Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Reviewed-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c deleted file mode 100644 index 3757074..0000000 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c +++ /dev/null @@ -1,141 +0,0 @@ -/* Watchdog Related Defines */ - -#define ADDIDATA_TIMER 0 -#define ADDIDATA_WATCHDOG 2 - -/* - * (*insn_config) for the timer subdevice - * - * Configures The Timer, Counter or Watchdog - * Data Pointer contains configuration parameters as below - * data[0] : 0 Configure As Timer - * 1 Configure As Counter - * 2 Configure As Watchdog - * data[1] : 1 Enable Interrupt - * 0 Disable Interrupt - * data[2] : Time Unit - * data[3] : Reload Value - */ -static int apci3501_config_insn_timer(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct apci3501_private *devpriv = dev->private; - unsigned int ctrl; - - if (data[0] != ADDIDATA_WATCHDOG && - data[0] != ADDIDATA_TIMER) - return -EINVAL; - - devpriv->tsk_Current = current; - - devpriv->timer_mode = data[0]; - - /* first, disable the watchdog or stop the timer */ - if (devpriv->timer_mode == ADDIDATA_WATCHDOG) { - ctrl = 0; - } else { - ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG); - ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG | - ADDI_TCW_CTRL_ENA); - } - outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG); - - /* enable/disable the timer interrupt */ - ctrl = (data[1] == 1) ? ADDI_TCW_CTRL_IRQ_ENA : 0; - outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG); - - outl(data[2], devpriv->tcw + ADDI_TCW_TIMEBASE_REG); - outl(data[3], devpriv->tcw + ADDI_TCW_RELOAD_REG); - - ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG); - if (devpriv->timer_mode == ADDIDATA_WATCHDOG) { - /* Set the mode (e2->e0) NOTE: this doesn't look correct */ - ctrl |= ~(ADDI_TCW_CTRL_CNT_UP | ADDI_TCW_CTRL_EXT_CLK_MASK | - ADDI_TCW_CTRL_MODE_MASK | ADDI_TCW_CTRL_GATE | - ADDI_TCW_CTRL_TRIG | ADDI_TCW_CTRL_TIMER_ENA | - ADDI_TCW_CTRL_RESET_ENA | ADDI_TCW_CTRL_WARN_ENA | - ADDI_TCW_CTRL_IRQ_ENA | ADDI_TCW_CTRL_ENA); - } else { - /* mode 2 */ - ctrl &= ~(ADDI_TCW_CTRL_CNTR_ENA | ADDI_TCW_CTRL_MODE_MASK | - ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG | - ADDI_TCW_CTRL_TIMER_ENA | ADDI_TCW_CTRL_RESET_ENA | - ADDI_TCW_CTRL_WARN_ENA | ADDI_TCW_CTRL_ENA); - ctrl |= ADDI_TCW_CTRL_MODE(2) | ADDI_TCW_CTRL_TIMER_ENA; - } - outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG); - - return insn->n; -} - -/* - * (*insn_write) for the timer subdevice - * - * Start / Stop The Selected Timer , Counter or Watchdog - * Data Pointer contains configuration parameters as below - * data[0] : 0 Timer - * 1 Counter - * 2 Watchdog - * data[1] : 1 Start - * 0 Stop - * 2 Trigger - */ -static int apci3501_write_insn_timer(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct apci3501_private *devpriv = dev->private; - unsigned int ctrl; - - if (devpriv->timer_mode == ADDIDATA_WATCHDOG || - devpriv->timer_mode == ADDIDATA_TIMER) { - ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG); - ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG); - - if (data[1] == 1) { /* enable */ - ctrl |= ADDI_TCW_CTRL_ENA; - } else if (data[1] == 0) { /* stop */ - if (devpriv->timer_mode == ADDIDATA_WATCHDOG) - ctrl = 0; - else - ctrl &= ~ADDI_TCW_CTRL_ENA; - } else if (data[1] == 2) { /* trigger */ - ctrl |= ADDI_TCW_CTRL_TRIG; - } - outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG); - } - - inl(devpriv->tcw + ADDI_TCW_STATUS_REG); - return insn->n; -} - -/* - * (*insn_read) for the timer subdevice - * - * Read The Selected Timer, Counter or Watchdog - * Data Pointer contains configuration parameters as below - * data[0] : 0 Timer - * 1 Counter - * 2 Watchdog - * data[1] : Timer Counter Watchdog Number - */ -static int apci3501_read_insn_timer(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct apci3501_private *devpriv = dev->private; - - if (devpriv->timer_mode != ADDIDATA_TIMER && - devpriv->timer_mode != ADDIDATA_WATCHDOG) - return -EINVAL; - - data[0] = inl(devpriv->tcw + ADDI_TCW_STATUS_REG) & - ADDI_TCW_STATUS_OVERFLOW; - data[1] = inl(devpriv->tcw + ADDI_TCW_VAL_REG); - - return insn->n; -} diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c index 40ff914..fc03f4a 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3501.c +++ b/drivers/staging/comedi/drivers/addi_apci_3501.c @@ -23,11 +23,8 @@ */ #include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/sched.h> #include "../comedi_pci.h" -#include "addi_tcw.h" #include "amcc_s5933.h" /* @@ -67,8 +64,6 @@ struct apci3501_private { unsigned long amcc; - unsigned long tcw; - struct task_struct *tsk_Current; unsigned char timer_mode; }; @@ -139,8 +134,6 @@ static int apci3501_ao_insn_write(struct comedi_device *dev, return insn->n; } -#include "addi-data/hwdrv_apci3501.c" - static int apci3501_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, @@ -253,37 +246,6 @@ static int apci3501_eeprom_insn_read(struct comedi_device *dev, return insn->n; } -static irqreturn_t apci3501_interrupt(int irq, void *d) -{ - struct comedi_device *dev = d; - struct apci3501_private *devpriv = dev->private; - unsigned int status; - unsigned int ctrl; - - /* Disable Interrupt */ - ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG); - ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG | - ADDI_TCW_CTRL_IRQ_ENA); - outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG); - - status = inl(devpriv->tcw + ADDI_TCW_IRQ_REG); - if (!(status & ADDI_TCW_IRQ)) { - dev_err(dev->class_dev, "IRQ from unknown source\n"); - return IRQ_NONE; - } - - /* Enable Interrupt Send a signal to from kernel to user space */ - send_sig(SIGIO, devpriv->tsk_Current, 0); - ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG); - ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG | - ADDI_TCW_CTRL_IRQ_ENA); - ctrl |= ADDI_TCW_CTRL_IRQ_ENA; - outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG); - inl(devpriv->tcw + ADDI_TCW_STATUS_REG); - - return IRQ_HANDLED; -} - static int apci3501_reset(struct comedi_device *dev) { unsigned int val; @@ -333,17 +295,9 @@ static int apci3501_auto_attach(struct comedi_device *dev, devpriv->amcc = pci_resource_start(pcidev, 0); dev->iobase = pci_resource_start(pcidev, 1); - devpriv->tcw = dev->iobase + APCI3501_TIMER_BASE; ao_n_chan = apci3501_eeprom_get_ao_n_chan(dev); - if (pcidev->irq > 0) { - ret = request_irq(pcidev->irq, apci3501_interrupt, IRQF_SHARED, - dev->board_name, dev); - if (ret == 0) - dev->irq = pcidev->irq; - } - ret = comedi_alloc_subdevices(dev, 5); if (ret) return ret; @@ -383,17 +337,9 @@ static int apci3501_auto_attach(struct comedi_device *dev, s->range_table = &range_digital; s->insn_bits = apci3501_do_insn_bits; - /* Initialize the timer/watchdog subdevice */ + /* Timer/Watchdog subdevice */ s = &dev->subdevices[3]; - s->type = COMEDI_SUBD_TIMER; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 1; - s->maxdata = 0; - s->len_chanlist = 1; - s->range_table = &range_digital; - s->insn_write = apci3501_write_insn_timer; - s->insn_read = apci3501_read_insn_timer; - s->insn_config = apci3501_config_insn_timer; + s->type = COMEDI_SUBD_UNUSED; /* Initialize the eeprom subdevice */ s = &dev->subdevices[4]; -- cgit v0.10.2 From 741a9c1c3a047667d0f969096bacea8e93febe6d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten <hsweeten@visionengravers.com> Date: Mon, 20 Jun 2016 11:12:33 -0700 Subject: staging: comedi: addi_apci_3501: add a comedi driver comment block This comment block is used to automatically generate documentation in Comedi and Comedilib. Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Reviewed-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c index fc03f4a..57f0f46 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3501.c +++ b/drivers/staging/comedi/drivers/addi_apci_3501.c @@ -22,6 +22,33 @@ * more details. */ +/* + * Driver: addi_apci_3501 + * Description: ADDI-DATA APCI-3501 Analog output board + * Devices: [ADDI-DATA] APCI-3501 (addi_apci_3501) + * Author: H Hartley Sweeten <hsweeten@visionengravers.com> + * Updated: Mon, 20 Jun 2016 10:57:01 -0700 + * Status: untested + * + * Configuration Options: not applicable, uses comedi PCI auto config + * + * This board has the following features: + * - 4 or 8 analog output channels + * - 2 optically isolated digital inputs + * - 2 optically isolated digital outputs + * - 1 12-bit watchdog/timer + * + * There are 2 versions of the APCI-3501: + * - APCI-3501-4 4 analog output channels + * - APCI-3501-8 8 analog output channels + * + * These boards use the same PCI Vendor/Device IDs. The number of output + * channels used by this driver is determined by reading the EEPROM on + * the board. + * + * The watchdog/timer subdevice is not currently supported. + */ + #include <linux/module.h> #include "../comedi_pci.h" -- cgit v0.10.2 From b4a7c742f41764b152e7f4c0e4bb090b3e612152 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten <hsweeten@visionengravers.com> Date: Mon, 20 Jun 2016 11:39:28 -0700 Subject: staging: comedi: das08_cs: fix block comments Fix the checkpatch.pl issue: WARNING: Block comments use * on subsequent lines Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Reviewed-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index 9c02b17..317a9b5 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -1,43 +1,42 @@ /* - comedi/drivers/das08_cs.c - DAS08 driver + * Comedi driver for DAS008 PCMCIA boards + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 2000 David A. Schleef <ds@schleef.org> + * Copyright (C) 2001,2002,2003 Frank Mori Hess <fmhess@users.sourceforge.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * PCMCIA support code for this driver is adapted from the dummy_cs.c + * driver of the Linux PCMCIA Card Services package. + * + * The initial developer of the original code is David A. Hinds + * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds + * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + */ - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 2000 David A. Schleef <ds@schleef.org> - Copyright (C) 2001,2002,2003 Frank Mori Hess <fmhess@users.sourceforge.net> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - PCMCIA support code for this driver is adapted from the dummy_cs.c - driver of the Linux PCMCIA Card Services package. - - The initial developer of the original code is David A. Hinds - <dahinds@users.sourceforge.net>. Portions created by David A. Hinds - are Copyright (C) 1999 David A. Hinds. All Rights Reserved. -*/ /* -Driver: das08_cs -Description: DAS-08 PCMCIA boards -Author: Warren Jasper, ds, Frank Hess -Devices: [ComputerBoards] PCM-DAS08 (pcm-das08) -Status: works - -This is the PCMCIA-specific support split off from the -das08 driver. - -Options (for pcm-das08): - NONE - -Command support does not exist, but could be added for this board. -*/ + * Driver: das08_cs + * Description: DAS-08 PCMCIA boards + * Author: Warren Jasper, ds, Frank Hess + * Devices: [ComputerBoards] PCM-DAS08 (pcm-das08) + * Status: works + * + * This is the PCMCIA-specific support split off from the + * das08 driver. + * + * Configuration Options: none, uses PCMCIA auto config + * + * Command support does not exist, but could be added for this board. + */ #include <linux/module.h> -- cgit v0.10.2 From 15203e5a79e5988b7bd7a3542ee8f0c83b37b8c7 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten <hsweeten@visionengravers.com> Date: Mon, 20 Jun 2016 11:39:29 -0700 Subject: staging: comedi: ni_670x: fix block comment issues Fix the checkpatch.pl issues: WARNING: Block comments use * on subsequent lines Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Reviewed-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c index 3e7271880..74911db 100644 --- a/drivers/staging/comedi/drivers/ni_670x.c +++ b/drivers/staging/comedi/drivers/ni_670x.c @@ -1,40 +1,34 @@ /* - comedi/drivers/ni_670x.c - Hardware driver for NI 670x devices - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1997-2001 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ -/* -Driver: ni_670x -Description: National Instruments 670x -Author: Bart Joris <bjoris@advalvas.be> -Updated: Wed, 11 Dec 2002 18:25:35 -0800 -Devices: [National Instruments] PCI-6703 (ni_670x), PCI-6704 -Status: unknown - -Commands are not supported. -*/ + * Comedi driver for NI 670x devices + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-2001 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ /* - Bart Joris <bjoris@advalvas.be> Last updated on 20/08/2001 - - Manuals: - - 322110a.pdf PCI/PXI-6704 User Manual - 322110b.pdf PCI/PXI-6703/6704 User Manual - -*/ + * Driver: ni_670x + * Description: National Instruments 670x + * Author: Bart Joris <bjoris@advalvas.be> + * Updated: Wed, 11 Dec 2002 18:25:35 -0800 + * Devices: [National Instruments] PCI-6703 (ni_670x), PCI-6704 + * Status: unknown + * + * Commands are not supported. + * + * Manuals: + * 322110a.pdf PCI/PXI-6704 User Manual + * 322110b.pdf PCI/PXI-6703/6704 User Manual + */ #include <linux/module.h> #include <linux/interrupt.h> -- cgit v0.10.2 From 8b1bb11d63b8f8a159ecd90bdcae6cf6bd99a943 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten <hsweeten@visionengravers.com> Date: Mon, 20 Jun 2016 11:39:30 -0700 Subject: staging: comedi: ni_pcimio: fix block comments Fix the checkpatch.pl issues: WARNING: Block comments use * on subsequent lines Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Reviewed-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c index d891739..f13a2f7 100644 --- a/drivers/staging/comedi/drivers/ni_pcimio.c +++ b/drivers/staging/comedi/drivers/ni_pcimio.c @@ -1,111 +1,106 @@ /* - comedi/drivers/ni_pcimio.c - Hardware driver for NI PCI-MIO E series cards + * Comedi driver for NI PCI-MIO E series cards + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-8 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1997-8 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ /* -Driver: ni_pcimio -Description: National Instruments PCI-MIO-E series and M series (all boards) -Author: ds, John Hallen, Frank Mori Hess, Rolf Mueller, Herbert Peremans, - Herman Bruyninckx, Terry Barnaby -Status: works -Devices: [National Instruments] PCI-MIO-16XE-50 (ni_pcimio), - PCI-MIO-16XE-10, PXI-6030E, PCI-MIO-16E-1, PCI-MIO-16E-4, PCI-6014, PCI-6040E, - PXI-6040E, PCI-6030E, PCI-6031E, PCI-6032E, PCI-6033E, PCI-6071E, PCI-6023E, - PCI-6024E, PCI-6025E, PXI-6025E, PCI-6034E, PCI-6035E, PCI-6052E, - PCI-6110, PCI-6111, PCI-6220, PCI-6221, PCI-6224, PXI-6224, - PCI-6225, PXI-6225, PCI-6229, PCI-6250, - PCI-6251, PXI-6251, PCIe-6251, PXIe-6251, - PCI-6254, PCI-6259, PCIe-6259, - PCI-6280, PCI-6281, PXI-6281, PCI-6284, PCI-6289, - PCI-6711, PXI-6711, PCI-6713, PXI-6713, - PXI-6071E, PCI-6070E, PXI-6070E, - PXI-6052E, PCI-6036E, PCI-6731, PCI-6733, PXI-6733, - PCI-6143, PXI-6143 -Updated: Mon, 09 Jan 2012 14:52:48 +0000 - -These boards are almost identical to the AT-MIO E series, except that -they use the PCI bus instead of ISA (i.e., AT). See the notes for -the ni_atmio.o driver for additional information about these boards. - -Autocalibration is supported on many of the devices, using the -comedi_calibrate (or comedi_soft_calibrate for m-series) utility. -M-Series boards do analog input and analog output calibration entirely -in software. The software calibration corrects -the analog input for offset, gain and -nonlinearity. The analog outputs are corrected for offset and gain. -See the comedilib documentation on comedi_get_softcal_converter() for -more information. - -By default, the driver uses DMA to transfer analog input data to -memory. When DMA is enabled, not all triggering features are -supported. - -Digital I/O may not work on 673x. - -Note that the PCI-6143 is a simultaineous sampling device with 8 convertors. -With this board all of the convertors perform one simultaineous sample during -a scan interval. The period for a scan is used for the convert time in a -Comedi cmd. The convert trigger source is normally set to TRIG_NOW by default. - -The RTSI trigger bus is supported on these cards on -subdevice 10. See the comedilib documentation for details. - -Information (number of channels, bits, etc.) for some devices may be -incorrect. Please check this and submit a bug if there are problems -for your device. - -SCXI is probably broken for m-series boards. - -Bugs: - - When DMA is enabled, COMEDI_EV_CONVERT does - not work correctly. + * Driver: ni_pcimio + * Description: National Instruments PCI-MIO-E series and M series (all boards) + * Author: ds, John Hallen, Frank Mori Hess, Rolf Mueller, Herbert Peremans, + * Herman Bruyninckx, Terry Barnaby + * Status: works + * Devices: [National Instruments] PCI-MIO-16XE-50 (ni_pcimio), + * PCI-MIO-16XE-10, PXI-6030E, PCI-MIO-16E-1, PCI-MIO-16E-4, PCI-6014, + * PCI-6040E, PXI-6040E, PCI-6030E, PCI-6031E, PCI-6032E, PCI-6033E, + * PCI-6071E, PCI-6023E, PCI-6024E, PCI-6025E, PXI-6025E, PCI-6034E, + * PCI-6035E, PCI-6052E, + * PCI-6110, PCI-6111, PCI-6220, PCI-6221, PCI-6224, PXI-6224, + * PCI-6225, PXI-6225, PCI-6229, PCI-6250, + * PCI-6251, PXI-6251, PCIe-6251, PXIe-6251, + * PCI-6254, PCI-6259, PCIe-6259, + * PCI-6280, PCI-6281, PXI-6281, PCI-6284, PCI-6289, + * PCI-6711, PXI-6711, PCI-6713, PXI-6713, + * PXI-6071E, PCI-6070E, PXI-6070E, + * PXI-6052E, PCI-6036E, PCI-6731, PCI-6733, PXI-6733, + * PCI-6143, PXI-6143 + * Updated: Mon, 09 Jan 2012 14:52:48 +0000 + * + * These boards are almost identical to the AT-MIO E series, except that + * they use the PCI bus instead of ISA (i.e., AT). See the notes for the + * ni_atmio.o driver for additional information about these boards. + * + * Autocalibration is supported on many of the devices, using the + * comedi_calibrate (or comedi_soft_calibrate for m-series) utility. + * M-Series boards do analog input and analog output calibration entirely + * in software. The software calibration corrects the analog input for + * offset, gain and nonlinearity. The analog outputs are corrected for + * offset and gain. See the comedilib documentation on + * comedi_get_softcal_converter() for more information. + * + * By default, the driver uses DMA to transfer analog input data to + * memory. When DMA is enabled, not all triggering features are + * supported. + * + * Digital I/O may not work on 673x. + * + * Note that the PCI-6143 is a simultaineous sampling device with 8 + * convertors. With this board all of the convertors perform one + * simultaineous sample during a scan interval. The period for a scan + * is used for the convert time in a Comedi cmd. The convert trigger + * source is normally set to TRIG_NOW by default. + * + * The RTSI trigger bus is supported on these cards on subdevice 10. + * See the comedilib documentation for details. + * + * Information (number of channels, bits, etc.) for some devices may be + * incorrect. Please check this and submit a bug if there are problems + * for your device. + * + * SCXI is probably broken for m-series boards. + * + * Bugs: + * - When DMA is enabled, COMEDI_EV_CONVERT does not work correctly. + */ -*/ /* - The PCI-MIO E series driver was originally written by - Tomasz Motylewski <...>, and ported to comedi by ds. - - References: - - 341079b.pdf PCI E Series Register-Level Programmer Manual - 340934b.pdf DAQ-STC reference manual - - 322080b.pdf 6711/6713/6715 User Manual - - 320945c.pdf PCI E Series User Manual - 322138a.pdf PCI-6052E and DAQPad-6052E User Manual - - ISSUES: - - need to deal with external reference for DAC, and other DAC - properties in board properties - - deal with at-mio-16de-10 revision D to N changes, etc. - - need to add other CALDAC type - - need to slow down DAC loading. I don't trust NI's claim that - two writes to the PCI bus slows IO enough. I would prefer to - use udelay(). Timing specs: (clock) - AD8522 30ns - DAC8043 120ns - DAC8800 60ns - MB88341 ? - -*/ + * The PCI-MIO E series driver was originally written by + * Tomasz Motylewski <...>, and ported to comedi by ds. + * + * References: + * 341079b.pdf PCI E Series Register-Level Programmer Manual + * 340934b.pdf DAQ-STC reference manual + * + * 322080b.pdf 6711/6713/6715 User Manual + * + * 320945c.pdf PCI E Series User Manual + * 322138a.pdf PCI-6052E and DAQPad-6052E User Manual + * + * ISSUES: + * - need to deal with external reference for DAC, and other DAC + * properties in board properties + * - deal with at-mio-16de-10 revision D to N changes, etc. + * - need to add other CALDAC type + * - need to slow down DAC loading. I don't trust NI's claim that + * two writes to the PCI bus slows IO enough. I would prefer to + * use udelay(). + * Timing specs: (clock) + * AD8522 30ns + * DAC8043 120ns + * DAC8800 60ns + * MB88341 ? + */ #include <linux/module.h> #include <linux/delay.h> @@ -119,13 +114,14 @@ Bugs: #define PCIDMA -/* These are not all the possible ao ranges for 628x boards. - They can do OFFSET +- REFERENCE where OFFSET can be - 0V, 5V, APFI<0,1>, or AO<0...3> and RANGE can - be 10V, 5V, 2V, 1V, APFI<0,1>, AO<0...3>. That's - 63 different possibilities. An AO channel - can not act as it's own OFFSET or REFERENCE. -*/ +/* + * These are not all the possible ao ranges for 628x boards. + * They can do OFFSET +- REFERENCE where OFFSET can be + * 0V, 5V, APFI<0,1>, or AO<0...3> and RANGE can + * be 10V, 5V, 2V, 1V, APFI<0,1>, AO<0...3>. That's + * 63 different possibilities. An AO channel + * can not act as it's own OFFSET or REFERENCE. + */ static const struct comedi_lrange range_ni_M_628x_ao = { 8, { BIP_RANGE(10), -- cgit v0.10.2 From a3310f385f8bb87866bc8990d2fb8318cb0ce666 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten <hsweeten@visionengravers.com> Date: Mon, 20 Jun 2016 11:39:31 -0700 Subject: staging: comedi: ni_mio_cs: fix block comments Fix the checkpatch.pl issues: WARNING: Block comments use * on subsequent lines Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Reviewed-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c index e3d821b..21f8231 100644 --- a/drivers/staging/comedi/drivers/ni_mio_cs.c +++ b/drivers/staging/comedi/drivers/ni_mio_cs.c @@ -1,40 +1,39 @@ /* - comedi/drivers/ni_mio_cs.c - Hardware driver for NI PCMCIA MIO E series cards - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ -/* -Driver: ni_mio_cs -Description: National Instruments DAQCard E series -Author: ds -Status: works -Devices: [National Instruments] DAQCard-AI-16XE-50 (ni_mio_cs), - DAQCard-AI-16E-4, DAQCard-6062E, DAQCard-6024E, DAQCard-6036E -Updated: Thu Oct 23 19:43:17 CDT 2003 - -See the notes in the ni_atmio.o driver. -*/ -/* - The real guts of the driver is in ni_mio_common.c, which is - included by all the E series drivers. - - References for specifications: + * Comedi driver for NI PCMCIA MIO E series cards + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ - 341080a.pdf DAQCard E Series Register Level Programmer Manual +/* + * Driver: ni_mio_cs + * Description: National Instruments DAQCard E series + * Author: ds + * Status: works + * Devices: [National Instruments] DAQCard-AI-16XE-50 (ni_mio_cs), + * DAQCard-AI-16E-4, DAQCard-6062E, DAQCard-6024E, DAQCard-6036E + * Updated: Thu Oct 23 19:43:17 CDT 2003 + * + * See the notes in the ni_atmio.o driver. + */ -*/ +/* + * The real guts of the driver is in ni_mio_common.c, which is + * included by all the E series drivers. + * + * References for specifications: + * 341080a.pdf DAQCard E Series Register Level Programmer Manual + */ #include <linux/module.h> #include <linux/delay.h> -- cgit v0.10.2 From 26994fd520871103e961717726dc25a07a831e53 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten <hsweeten@visionengravers.com> Date: Mon, 20 Jun 2016 11:39:32 -0700 Subject: staging: comedi: ni_daq_dio24: fix block comments Fix the checkpatch.pl issues: WARNING: Block comments use * on subsequent lines Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Reviewed-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c index d9de83a..733d3fb 100644 --- a/drivers/staging/comedi/drivers/ni_daq_dio24.c +++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c @@ -1,35 +1,35 @@ /* - comedi/drivers/ni_daq_dio24.c - Driver for National Instruments PCMCIA DAQ-Card DIO-24 - Copyright (C) 2002 Daniel Vecino Castel <dvecino@able.es> + * Comedi driver for National Instruments PCMCIA DAQ-Card DIO-24 + * Copyright (C) 2002 Daniel Vecino Castel <dvecino@able.es> + * + * PCMCIA crap at end of file is adapted from dummy_cs.c 1.31 + * 2001/08/24 12:13:13 from the pcmcia package. + * The initial developer of the pcmcia dummy_cs.c code is David A. Hinds + * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds + * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ - PCMCIA crap at end of file is adapted from dummy_cs.c 1.31 - 2001/08/24 12:13:13 from the pcmcia package. - The initial developer of the pcmcia dummy_cs.c code is David A. Hinds - <dahinds@users.sourceforge.net>. Portions created by David A. Hinds - are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ /* -Driver: ni_daq_dio24 -Description: National Instruments PCMCIA DAQ-Card DIO-24 -Author: Daniel Vecino Castel <dvecino@able.es> -Devices: [National Instruments] PCMCIA DAQ-Card DIO-24 (ni_daq_dio24) -Status: ? -Updated: Thu, 07 Nov 2002 21:53:06 -0800 - -This is just a wrapper around the 8255.o driver to properly handle -the PCMCIA interface. -*/ + * Driver: ni_daq_dio24 + * Description: National Instruments PCMCIA DAQ-Card DIO-24 + * Author: Daniel Vecino Castel <dvecino@able.es> + * Devices: [National Instruments] PCMCIA DAQ-Card DIO-24 (ni_daq_dio24) + * Status: ? + * Updated: Thu, 07 Nov 2002 21:53:06 -0800 + * + * This is just a wrapper around the 8255.o driver to properly handle + * the PCMCIA interface. + */ #include <linux/module.h> #include "../comedi_pcmcia.h" -- cgit v0.10.2 From 44a678b9665bba452458427400a30ac5d3ebd00d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten <hsweeten@visionengravers.com> Date: Mon, 20 Jun 2016 11:39:33 -0700 Subject: staging: comedi: ni_atmio: fix block comments Fix the checkpatch.pl issues: WARNING: Block comments use * on subsequent lines Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Reviewed-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c index 95435b8..162a000 100644 --- a/drivers/staging/comedi/drivers/ni_atmio.c +++ b/drivers/staging/comedi/drivers/ni_atmio.c @@ -1,93 +1,84 @@ /* - comedi/drivers/ni_atmio.c - Hardware driver for NI AT-MIO E series cards - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1997-2001 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ -/* -Driver: ni_atmio -Description: National Instruments AT-MIO-E series -Author: ds -Devices: [National Instruments] AT-MIO-16E-1 (ni_atmio), - AT-MIO-16E-2, AT-MIO-16E-10, AT-MIO-16DE-10, AT-MIO-64E-3, - AT-MIO-16XE-50, AT-MIO-16XE-10, AT-AI-16XE-10 -Status: works -Updated: Thu May 1 20:03:02 CDT 2003 - -The driver has 2.6 kernel isapnp support, and -will automatically probe for a supported board if the -I/O base is left unspecified with comedi_config. -However, many of -the isapnp id numbers are unknown. If your board is not -recognized, please send the output of 'cat /proc/isapnp' -(you may need to modprobe the isa-pnp module for -/proc/isapnp to exist) so the -id numbers for your board can be added to the driver. - -Otherwise, you can use the isapnptools package to configure -your board. Use isapnp to -configure the I/O base and IRQ for the board, and then pass -the same values as -parameters in comedi_config. A sample isapnp.conf file is included -in the etc/ directory of Comedilib. - -Comedilib includes a utility to autocalibrate these boards. The -boards seem to boot into a state where the all calibration DACs -are at one extreme of their range, thus the default calibration -is terrible. Calibration at boot is strongly encouraged. - -To use the extended digital I/O on some of the boards, enable the -8255 driver when configuring the Comedi source tree. - -External triggering is supported for some events. The channel index -(scan_begin_arg, etc.) maps to PFI0 - PFI9. - -Some of the more esoteric triggering possibilities of these boards -are not supported. -*/ -/* - The real guts of the driver is in ni_mio_common.c, which is included - both here and in ni_pcimio.c - - Interrupt support added by Truxton Fulton <trux@truxton.com> - - References for specifications: - - 340747b.pdf Register Level Programmer Manual (obsolete) - 340747c.pdf Register Level Programmer Manual (new) - DAQ-STC reference manual - - Other possibly relevant info: - - 320517c.pdf User manual (obsolete) - 320517f.pdf User manual (new) - 320889a.pdf delete - 320906c.pdf maximum signal ratings - 321066a.pdf about 16x - 321791a.pdf discontinuation of at-mio-16e-10 rev. c - 321808a.pdf about at-mio-16e-10 rev P - 321837a.pdf discontinuation of at-mio-16de-10 rev d - 321838a.pdf about at-mio-16de-10 rev N - - ISSUES: - - need to deal with external reference for DAC, and other DAC - properties in board properties + * Comedi driver for NI AT-MIO E series cards + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-2001 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ - deal with at-mio-16de-10 revision D to N changes, etc. +/* + * Driver: ni_atmio + * Description: National Instruments AT-MIO-E series + * Author: ds + * Devices: [National Instruments] AT-MIO-16E-1 (ni_atmio), + * AT-MIO-16E-2, AT-MIO-16E-10, AT-MIO-16DE-10, AT-MIO-64E-3, + * AT-MIO-16XE-50, AT-MIO-16XE-10, AT-AI-16XE-10 + * Status: works + * Updated: Thu May 1 20:03:02 CDT 2003 + * + * The driver has 2.6 kernel isapnp support, and will automatically probe for + * a supported board if the I/O base is left unspecified with comedi_config. + * However, many of the isapnp id numbers are unknown. If your board is not + * recognized, please send the output of 'cat /proc/isapnp' (you may need to + * modprobe the isa-pnp module for /proc/isapnp to exist) so the id numbers + * for your board can be added to the driver. + * + * Otherwise, you can use the isapnptools package to configure your board. + * Use isapnp to configure the I/O base and IRQ for the board, and then pass + * the same values as parameters in comedi_config. A sample isapnp.conf file + * is included in the etc/ directory of Comedilib. + * + * Comedilib includes a utility to autocalibrate these boards. The boards + * seem to boot into a state where the all calibration DACs are at one + * extreme of their range, thus the default calibration is terrible. + * Calibration at boot is strongly encouraged. + * + * To use the extended digital I/O on some of the boards, enable the + * 8255 driver when configuring the Comedi source tree. + * + * External triggering is supported for some events. The channel index + * (scan_begin_arg, etc.) maps to PFI0 - PFI9. + * + * Some of the more esoteric triggering possibilities of these boards are + * not supported. + */ -*/ +/* + * The real guts of the driver is in ni_mio_common.c, which is included + * both here and in ni_pcimio.c + * + * Interrupt support added by Truxton Fulton <trux@truxton.com> + * + * References for specifications: + * 340747b.pdf Register Level Programmer Manual (obsolete) + * 340747c.pdf Register Level Programmer Manual (new) + * DAQ-STC reference manual + * + * Other possibly relevant info: + * 320517c.pdf User manual (obsolete) + * 320517f.pdf User manual (new) + * 320889a.pdf delete + * 320906c.pdf maximum signal ratings + * 321066a.pdf about 16x + * 321791a.pdf discontinuation of at-mio-16e-10 rev. c + * 321808a.pdf about at-mio-16e-10 rev P + * 321837a.pdf discontinuation of at-mio-16de-10 rev d + * 321838a.pdf about at-mio-16de-10 rev N + * + * ISSUES: + * - need to deal with external reference for DAC, and other DAC + * properties in board properties + * - deal with at-mio-16de-10 revision D to N changes, etc. + */ #include <linux/module.h> #include <linux/interrupt.h> -- cgit v0.10.2 From 28e0721e3367d227fdf00fdbac1a54416cf88222 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten <hsweeten@visionengravers.com> Date: Mon, 20 Jun 2016 11:39:34 -0700 Subject: staging: comedi: ni_atmio16d: fix block comments Fix the checkpatch.pl issues: WARNING: Block comments use * on subsequent lines Move the configuration options comment into the comedi driver comment block. That's were they typically are listed. Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Reviewed-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c index c3eb546..fb59b0f 100644 --- a/drivers/staging/comedi/drivers/ni_atmio16d.c +++ b/drivers/staging/comedi/drivers/ni_atmio16d.c @@ -1,25 +1,41 @@ /* - comedi/drivers/ni_atmio16d.c - Hardware driver for National Instruments AT-MIO16D board - Copyright (C) 2000 Chris R. Baugher <baugher@enteract.com> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + * Comedi driver for National Instruments AT-MIO16D board + * Copyright (C) 2000 Chris R. Baugher <baugher@enteract.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. */ + /* -Driver: ni_atmio16d -Description: National Instruments AT-MIO-16D -Author: Chris R. Baugher <baugher@enteract.com> -Status: unknown -Devices: [National Instruments] AT-MIO-16 (atmio16), AT-MIO-16D (atmio16d) -*/ + * Driver: ni_atmio16d + * Description: National Instruments AT-MIO-16D + * Author: Chris R. Baugher <baugher@enteract.com> + * Status: unknown + * Devices: [National Instruments] AT-MIO-16 (atmio16), AT-MIO-16D (atmio16d) + * + * Configuration options: + * [0] - I/O port + * [1] - MIO irq (0 == no irq; or 3,4,5,6,7,9,10,11,12,14,15) + * [2] - DIO irq (0 == no irq; or 3,4,5,6,7,9) + * [3] - DMA1 channel (0 == no DMA; or 5,6,7) + * [4] - DMA2 channel (0 == no DMA; or 5,6,7) + * [5] - a/d mux (0=differential; 1=single) + * [6] - a/d range (0=bipolar10; 1=bipolar5; 2=unipolar10) + * [7] - dac0 range (0=bipolar; 1=unipolar) + * [8] - dac0 reference (0=internal; 1=external) + * [9] - dac0 coding (0=2's comp; 1=straight binary) + * [10] - dac1 range (same as dac0 options) + * [11] - dac1 reference (same as dac0 options) + * [12] - dac1 coding (same as dac0 options) + */ + /* * I must give credit here to Michal Dobes <dobes@tesnet.cz> who * wrote the driver for Advantec's pcl812 boards. I used the interrupt @@ -295,8 +311,10 @@ static int atmio16d_ai_cmd(struct comedi_device *dev, unsigned int sample_count, tmp, chan, gain; int i; - /* This is slowly becoming a working command interface. * - * It is still uber-experimental */ + /* + * This is slowly becoming a working command interface. + * It is still uber-experimental + */ reset_counters(dev); @@ -322,9 +340,10 @@ static int atmio16d_ai_cmd(struct comedi_device *dev, outw(tmp, dev->iobase + MUX_GAIN_REG); } - /* Now program the sample interval timer */ - /* Figure out which clock to use then get an - * appropriate timer value */ + /* + * Now program the sample interval timer. + * Figure out which clock to use then get an appropriate timer value. + */ if (cmd->convert_arg < 65536000) { base_clock = CLOCK_1_MHZ; timer = cmd->convert_arg / 1000; @@ -386,9 +405,10 @@ static int atmio16d_ai_cmd(struct comedi_device *dev, outw(devpriv->com_reg_1_state, dev->iobase + COM_REG_1); } - /* Program the scan interval timer ONLY IF SCANNING IS ENABLED */ - /* Figure out which clock to use then get an - * appropriate timer value */ + /* + * Program the scan interval timer ONLY IF SCANNING IS ENABLED. + * Figure out which clock to use then get an appropriate timer value. + */ if (cmd->chanlist_len > 1) { if (cmd->scan_begin_arg < 65536000) { base_clock = CLOCK_1_MHZ; @@ -566,38 +586,6 @@ static int atmio16d_dio_insn_config(struct comedi_device *dev, return insn->n; } -/* - options[0] - I/O port - options[1] - MIO irq - 0 == no irq - N == irq N {3,4,5,6,7,9,10,11,12,14,15} - options[2] - DIO irq - 0 == no irq - N == irq N {3,4,5,6,7,9} - options[3] - DMA1 channel - 0 == no DMA - N == DMA N {5,6,7} - options[4] - DMA2 channel - 0 == no DMA - N == DMA N {5,6,7} - - options[5] - a/d mux - 0=differential, 1=single - options[6] - a/d range - 0=bipolar10, 1=bipolar5, 2=unipolar10 - - options[7] - dac0 range - 0=bipolar, 1=unipolar - options[8] - dac0 reference - 0=internal, 1=external - options[9] - dac0 coding - 0=2's comp, 1=straight binary - - options[10] - dac1 range - options[11] - dac1 reference - options[12] - dac1 coding - */ - static int atmio16d_attach(struct comedi_device *dev, struct comedi_devconfig *it) { -- cgit v0.10.2 From 8c0740cade3ce290bcbcef524a285863f6de0c94 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten <hsweeten@visionengravers.com> Date: Mon, 20 Jun 2016 11:39:35 -0700 Subject: staging: comedi: ni_pcidio: fix block comments Fix the checkpatch.pl issues: WARNING: Block comments use * on subsequent lines WARNING: Block comments use a trailing */ on a separate line Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Reviewed-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index 35ef192..deaa7f2 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -1,50 +1,49 @@ /* - comedi/drivers/ni_pcidio.c - driver for National Instruments PCI-DIO-32HS - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1999,2002 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * Comedi driver for National Instruments PCI-DIO-32HS + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1999,2002 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + /* -Driver: ni_pcidio -Description: National Instruments PCI-DIO32HS, PCI-6533 -Author: ds -Status: works -Devices: [National Instruments] PCI-DIO-32HS (ni_pcidio) - [National Instruments] PXI-6533, PCI-6533 (pxi-6533) - [National Instruments] PCI-6534 (pci-6534) -Updated: Mon, 09 Jan 2012 14:27:23 +0000 - -The DIO32HS board appears as one subdevice, with 32 channels. -Each channel is individually I/O configurable. The channel order -is 0=A0, 1=A1, 2=A2, ... 8=B0, 16=C0, 24=D0. The driver only -supports simple digital I/O; no handshaking is supported. - -DMA mostly works for the PCI-DIO32HS, but only in timed input mode. - -The PCI-DIO-32HS/PCI-6533 has a configurable external trigger. Setting -scan_begin_arg to 0 or CR_EDGE triggers on the leading edge. Setting -scan_begin_arg to CR_INVERT or (CR_EDGE | CR_INVERT) triggers on the -trailing edge. - -This driver could be easily modified to support AT-MIO32HS and -AT-MIO96. - -The PCI-6534 requires a firmware upload after power-up to work, the -firmware data and instructions for loading it with comedi_config -it are contained in the -comedi_nonfree_firmware tarball available from http://www.comedi.org -*/ + * Driver: ni_pcidio + * Description: National Instruments PCI-DIO32HS, PCI-6533 + * Author: ds + * Status: works + * Devices: [National Instruments] PCI-DIO-32HS (ni_pcidio) + * [National Instruments] PXI-6533, PCI-6533 (pxi-6533) + * [National Instruments] PCI-6534 (pci-6534) + * Updated: Mon, 09 Jan 2012 14:27:23 +0000 + * + * The DIO32HS board appears as one subdevice, with 32 channels. Each + * channel is individually I/O configurable. The channel order is 0=A0, + * 1=A1, 2=A2, ... 8=B0, 16=C0, 24=D0. The driver only supports simple + * digital I/O; no handshaking is supported. + * + * DMA mostly works for the PCI-DIO32HS, but only in timed input mode. + * + * The PCI-DIO-32HS/PCI-6533 has a configurable external trigger. Setting + * scan_begin_arg to 0 or CR_EDGE triggers on the leading edge. Setting + * scan_begin_arg to CR_INVERT or (CR_EDGE | CR_INVERT) triggers on the + * trailing edge. + * + * This driver could be easily modified to support AT-MIO32HS and AT-MIO96. + * + * The PCI-6534 requires a firmware upload after power-up to work, the + * firmware data and instructions for loading it with comedi_config + * it are contained in the comedi_nonfree_firmware tarball available from + * http://www.comedi.org + */ #define USE_DMA @@ -649,8 +648,10 @@ static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) writeb(1, dev->mmio + AckDelay); writeb(0x0b, dev->mmio + AckNotDelay); writeb(0x01, dev->mmio + Data1Delay); - /* manual, page 4-5: ClockSpeed comment is incorrectly listed - * on DAQOptions */ + /* + * manual, page 4-5: + * ClockSpeed comment is incorrectly listed on DAQOptions + */ writew(0, dev->mmio + ClockSpeed); writeb(0, dev->mmio + DAQOptions); } else { -- cgit v0.10.2 From 27fa082b33b92285b8f38e73c838f224d2038c7b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten <hsweeten@visionengravers.com> Date: Mon, 20 Jun 2016 11:39:36 -0700 Subject: staging: comedi: ni_at_a2150: fix block comments Fix the checkpatch.pl issues: WARNING: Block comments use * on subsequent lines WARNING: Block comments use a trailing */ on a separate line Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Reviewed-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index 9b444f8..957fb9f 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -1,62 +1,47 @@ /* - comedi/drivers/ni_at_a2150.c - Driver for National Instruments AT-A2150 boards - Copyright (C) 2001, 2002 Frank Mori Hess <fmhess@users.sourceforge.net> - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 2000 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ -/* -Driver: ni_at_a2150 -Description: National Instruments AT-A2150 -Author: Frank Mori Hess -Status: works -Devices: [National Instruments] AT-A2150C (at_a2150c), AT-2150S (at_a2150s) - -If you want to ac couple the board's inputs, use AREF_OTHER. - -Configuration options: - [0] - I/O port base address - [1] - IRQ (optional, required for timed conversions) - [2] - DMA (optional, required for timed conversions) + * Comedi driver for National Instruments AT-A2150 boards + * Copyright (C) 2001, 2002 Frank Mori Hess <fmhess@users.sourceforge.net> + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 2000 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ -*/ /* -Yet another driver for obsolete hardware brought to you by Frank Hess. -Testing and debugging help provided by Dave Andruczyk. - -This driver supports the boards: - -AT-A2150C -AT-A2150S - -The only difference is their master clock frequencies. - -Options: - [0] - base io address - [1] - irq - [2] - dma channel - -References (from ftp://ftp.natinst.com/support/manuals): - - 320360.pdf AT-A2150 User Manual - -TODO: - -analog level triggering -TRIG_WAKE_EOS - -*/ + * Driver: ni_at_a2150 + * Description: National Instruments AT-A2150 + * Author: Frank Mori Hess + * Status: works + * Devices: [National Instruments] AT-A2150C (at_a2150c), AT-2150S (at_a2150s) + * + * Configuration options: + * [0] - I/O port base address + * [1] - IRQ (optional, required for timed conversions) + * [2] - DMA (optional, required for timed conversions) + * + * Yet another driver for obsolete hardware brought to you by Frank Hess. + * Testing and debugging help provided by Dave Andruczyk. + * + * If you want to ac couple the board's inputs, use AREF_OTHER. + * + * The only difference in the boards is their master clock frequencies. + * + * References (from ftp://ftp.natinst.com/support/manuals): + * 320360.pdf AT-A2150 User Manual + * + * TODO: + * - analog level triggering + * - TRIG_WAKE_EOS + */ #include <linux/module.h> #include <linux/delay.h> @@ -536,8 +521,10 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) comedi_isadma_program(desc); - /* clear dma interrupt before enabling it, to try and get rid of that - * one spurious interrupt that has been happening */ + /* + * Clear dma interrupt before enabling it, to try and get rid of + * that one spurious interrupt that has been happening. + */ outw(0x00, dev->iobase + DMA_TC_CLEAR_REG); /* enable dma on card */ -- cgit v0.10.2 From 49c9d6ad68aed76314fc69d3c07e25079e37bc04 Mon Sep 17 00:00:00 2001 From: Nayeemahmed Badebade <itachi.opsrc@gmail.com> Date: Sat, 30 Jul 2016 22:08:15 +0530 Subject: staging: comedi/drivers: Fixed sparse warnings Fixed below sparse warnings in dt2811.c warning: symbol 'dt2811_clk_dividers' was not declared. Should it be static? warning: symbol 'dt2811_clk_multipliers' was not declared. Should it be static? Signed-off-by: Nayeemahmed Badebade <itachi.opsrc@gmail.com> Reviewed-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c index 904f6377..07f99c0 100644 --- a/drivers/staging/comedi/drivers/dt2811.c +++ b/drivers/staging/comedi/drivers/dt2811.c @@ -96,11 +96,11 @@ * 6 6 100 kHz 6 1000000 * 7 12 50 kHz 7 10000000 */ -const unsigned int dt2811_clk_dividers[] = { +static const unsigned int dt2811_clk_dividers[] = { 1, 10, 2, 3, 4, 5, 6, 12 }; -const unsigned int dt2811_clk_multipliers[] = { +static const unsigned int dt2811_clk_multipliers[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000 }; -- cgit v0.10.2 From 62190d498c1d1cee970176840f24822fc14d27d1 Mon Sep 17 00:00:00 2001 From: Cheah Kok Cheong <thrust73@gmail.com> Date: Fri, 22 Jul 2016 23:29:39 +0800 Subject: staging: comedi: drivers: replace le16_to_cpu() with usb_endpoint_maxp() Use macro introduced in commit 939f325f4a0f ("usb: add usb_endpoint_maxp() macro") Signed-off-by: Cheah Kok Cheong <thrust73@gmail.com> Reviewed-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c index 3295bb4..7ebca86 100644 --- a/drivers/staging/comedi/drivers/dt9812.c +++ b/drivers/staging/comedi/drivers/dt9812.c @@ -660,12 +660,12 @@ static int dt9812_find_endpoints(struct comedi_device *dev) case 1: dir = USB_DIR_OUT; devpriv->cmd_wr.addr = ep->bEndpointAddress; - devpriv->cmd_wr.size = le16_to_cpu(ep->wMaxPacketSize); + devpriv->cmd_wr.size = usb_endpoint_maxp(ep); break; case 2: dir = USB_DIR_IN; devpriv->cmd_rd.addr = ep->bEndpointAddress; - devpriv->cmd_rd.size = le16_to_cpu(ep->wMaxPacketSize); + devpriv->cmd_rd.size = usb_endpoint_maxp(ep); break; case 3: /* unused write stream */ diff --git a/drivers/staging/comedi/drivers/ni_usb6501.c b/drivers/staging/comedi/drivers/ni_usb6501.c index 95b537a..5036eeb 100644 --- a/drivers/staging/comedi/drivers/ni_usb6501.c +++ b/drivers/staging/comedi/drivers/ni_usb6501.c @@ -465,12 +465,12 @@ static int ni6501_alloc_usb_buffers(struct comedi_device *dev) struct ni6501_private *devpriv = dev->private; size_t size; - size = le16_to_cpu(devpriv->ep_rx->wMaxPacketSize); + size = usb_endpoint_maxp(devpriv->ep_rx); devpriv->usb_rx_buf = kzalloc(size, GFP_KERNEL); if (!devpriv->usb_rx_buf) return -ENOMEM; - size = le16_to_cpu(devpriv->ep_tx->wMaxPacketSize); + size = usb_endpoint_maxp(devpriv->ep_tx); devpriv->usb_tx_buf = kzalloc(size, GFP_KERNEL); if (!devpriv->usb_tx_buf) { kfree(devpriv->usb_rx_buf); diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c index 8c7393e..a004aed 100644 --- a/drivers/staging/comedi/drivers/vmk80xx.c +++ b/drivers/staging/comedi/drivers/vmk80xx.c @@ -177,7 +177,7 @@ static void vmk80xx_do_bulk_msg(struct comedi_device *dev) * The max packet size attributes of the K8061 * input/output endpoints are identical */ - size = le16_to_cpu(devpriv->ep_tx->wMaxPacketSize); + size = usb_endpoint_maxp(devpriv->ep_tx); usb_bulk_msg(usb, tx_pipe, devpriv->usb_tx_buf, size, NULL, devpriv->ep_tx->bInterval); @@ -199,7 +199,7 @@ static int vmk80xx_read_packet(struct comedi_device *dev) ep = devpriv->ep_rx; pipe = usb_rcvintpipe(usb, ep->bEndpointAddress); return usb_interrupt_msg(usb, pipe, devpriv->usb_rx_buf, - le16_to_cpu(ep->wMaxPacketSize), NULL, + usb_endpoint_maxp(ep), NULL, HZ * 10); } @@ -220,7 +220,7 @@ static int vmk80xx_write_packet(struct comedi_device *dev, int cmd) ep = devpriv->ep_tx; pipe = usb_sndintpipe(usb, ep->bEndpointAddress); return usb_interrupt_msg(usb, pipe, devpriv->usb_tx_buf, - le16_to_cpu(ep->wMaxPacketSize), NULL, + usb_endpoint_maxp(ep), NULL, HZ * 10); } @@ -230,7 +230,7 @@ static int vmk80xx_reset_device(struct comedi_device *dev) size_t size; int retval; - size = le16_to_cpu(devpriv->ep_tx->wMaxPacketSize); + size = usb_endpoint_maxp(devpriv->ep_tx); memset(devpriv->usb_tx_buf, 0, size); retval = vmk80xx_write_packet(dev, VMK8055_CMD_RST); if (retval) @@ -684,12 +684,12 @@ static int vmk80xx_alloc_usb_buffers(struct comedi_device *dev) struct vmk80xx_private *devpriv = dev->private; size_t size; - size = le16_to_cpu(devpriv->ep_rx->wMaxPacketSize); + size = usb_endpoint_maxp(devpriv->ep_rx); devpriv->usb_rx_buf = kzalloc(size, GFP_KERNEL); if (!devpriv->usb_rx_buf) return -ENOMEM; - size = le16_to_cpu(devpriv->ep_tx->wMaxPacketSize); + size = usb_endpoint_maxp(devpriv->ep_tx); devpriv->usb_tx_buf = kzalloc(size, GFP_KERNEL); if (!devpriv->usb_tx_buf) { kfree(devpriv->usb_rx_buf); -- cgit v0.10.2 From 2061d410616785e68c3f53d48f3df3ad7564d2cb Mon Sep 17 00:00:00 2001 From: Ravishankar Karkala Mallikarjunayya <ravishankarkm32@gmail.com> Date: Tue, 21 Jun 2016 12:14:44 +0530 Subject: Staging: comedi: s626: fix line over 80 characters issue This fixes up a line over 80 characters issues found by the checkpatch.pl tool. Signed-off-by: Ravishankar Karkala Mallikarjunayya <ravishankarkm32@gmail.com> Reviewed-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index 4a87b4b..6d89ca0 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -2500,7 +2500,8 @@ static int s626_initialize(struct comedi_device *dev) for (i = 0; i < 2; i++) { writel(S626_I2C_CLKSEL, dev->mmio + S626_P_I2CSTAT); s626_mc_enable(dev, S626_MC2_UPLD_IIC, S626_P_MC2); - ret = comedi_timeout(dev, NULL, NULL, s626_i2c_handshake_eoc, 0); + ret = comedi_timeout(dev, NULL, + NULL, s626_i2c_handshake_eoc, 0); if (ret) return ret; } -- cgit v0.10.2 From fd2b75d88811b4fb25406cd60a0fb3c2644e785d Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani <falakreyaz@gmail.com> Date: Wed, 11 May 2016 19:24:59 +0530 Subject: staging: i4l: pcbit: drv: use setup_timer() and mod_timer(). Use setup_timer() instead of init_timer(), being the preferred/standard way to set a timer up. Also, quoting the mod_timer() function comment: -> mod_timer() is a more efficient way to update the expire field of an active timer (if the timer is inactive it will be activated). Use setup_timer and mod_timer to setup and arm a timer, to make the code cleaner and easier to read. Signed-off-by: Muhammad Falak R Wani <falakreyaz@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/i4l/pcbit/drv.c b/drivers/staging/i4l/pcbit/drv.c index c5270e2..d417df5 100644 --- a/drivers/staging/i4l/pcbit/drv.c +++ b/drivers/staging/i4l/pcbit/drv.c @@ -359,11 +359,9 @@ static int pcbit_xmit(int driver, int chnum, int ack, struct sk_buff *skb) */ #ifdef BLOCK_TIMER if (chan->block_timer.function == NULL) { - init_timer(&chan->block_timer); - chan->block_timer.function = &pcbit_block_timer; - chan->block_timer.data = (long) chan; - chan->block_timer.expires = jiffies + 1 * HZ; - add_timer(&chan->block_timer); + setup_timer(&chan->block_timer, &pcbit_block_timer, + (long)chan); + mod_timer(&chan->block_timer, jiffies + 1 * HZ); } #endif return 0; @@ -804,11 +802,7 @@ static int set_protocol_running(struct pcbit_dev *dev) { isdn_ctrl ctl; - init_timer(&dev->set_running_timer); - - dev->set_running_timer.function = &set_running_timeout; - dev->set_running_timer.data = (ulong) dev; - dev->set_running_timer.expires = jiffies + SET_RUN_TIMEOUT; + setup_timer(&dev->set_running_timer, &set_running_timeout, (ulong)dev); /* kick it */ @@ -817,7 +811,7 @@ static int set_protocol_running(struct pcbit_dev *dev) writeb((0x80U | ((dev->rcv_seq & 0x07) << 3) | (dev->send_seq & 0x07)), dev->sh_mem + BANK4); - add_timer(&dev->set_running_timer); + mod_timer(&dev->set_running_timer, jiffies + SET_RUN_TIMEOUT); wait_event(dev->set_running_wq, dev->l2_state == L2_RUNNING || dev->l2_state == L2_DOWN); -- cgit v0.10.2 From 8df7a2221ccfcfdb25c2d4668cd51d25e9b3e134 Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani <falakreyaz@gmail.com> Date: Wed, 11 May 2016 19:25:00 +0530 Subject: staging: i4l: pcbit: edss1: use setup_timer() and mod_timer(). Use setup_timer() instead of init_timer(), being the preferred/standard way to set a timer up. Also, quoting the mod_timer() function comment: -> mod_timer() is a more efficient way to update the expire field of an active timer (if the timer is inactive it will be activated). Use setup_timer and mod_timer to setup and arm a timer, to make the code cleaner and easier to read. Signed-off-by: Muhammad Falak R Wani <falakreyaz@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/i4l/pcbit/edss1.c b/drivers/staging/i4l/pcbit/edss1.c index e72c164..6d291d5 100644 --- a/drivers/staging/i4l/pcbit/edss1.c +++ b/drivers/staging/i4l/pcbit/edss1.c @@ -298,11 +298,8 @@ void pcbit_fsm_event(struct pcbit_dev *dev, struct pcbit_chan *chan, break; if (tentry->init != 0xff) { - init_timer(&chan->fsm_timer); - chan->fsm_timer.function = &pcbit_fsm_timer; - chan->fsm_timer.data = (ulong) chan; - chan->fsm_timer.expires = jiffies + tentry->timeout * HZ; - add_timer(&chan->fsm_timer); + setup_timer(&chan->fsm_timer, &pcbit_fsm_timer, (ulong)chan); + mod_timer(&chan->fsm_timer, jiffies + tentry->timeout * HZ); } spin_unlock_irqrestore(&dev->lock, flags); -- cgit v0.10.2 From 1735d9e97c66f867d3a45a2303bb3c59398d20f8 Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani <falakreyaz@gmail.com> Date: Wed, 11 May 2016 19:25:01 +0530 Subject: staging: i4l: pcbit: layer2: use setup_timer() and mod_timer(). Use setup_timer() instead of init_timer(), being the preferred/standard way to set a timer up. Also, quoting the mod_timer() function comment: -> mod_timer() is a more efficient way to update the expire field of an active timer (if the timer is inactive it will be activated). Use setup_timer and mod_timer to setup and arm a timer, to make the code cleaner and easier to read. Signed-off-by: Muhammad Falak R Wani <falakreyaz@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/i4l/pcbit/layer2.c b/drivers/staging/i4l/pcbit/layer2.c index 46e1240..a136c72 100644 --- a/drivers/staging/i4l/pcbit/layer2.c +++ b/drivers/staging/i4l/pcbit/layer2.c @@ -645,11 +645,9 @@ pcbit_l2_error(struct pcbit_dev *dev) dev->l2_state = L2_DOWN; - init_timer(&dev->error_recover_timer); - dev->error_recover_timer.function = &pcbit_l2_err_recover; - dev->error_recover_timer.data = (ulong) dev; - dev->error_recover_timer.expires = jiffies + ERRTIME; - add_timer(&dev->error_recover_timer); + setup_timer(&dev->error_recover_timer, &pcbit_l2_err_recover, + (ulong)dev); + mod_timer(&dev->error_recover_timer, jiffies + ERRTIME); } } -- cgit v0.10.2 From e9c43a75cda0e23910c77e585c8397efeeaddda8 Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani <falakreyaz@gmail.com> Date: Wed, 11 May 2016 18:59:53 +0530 Subject: staging: i4l: icn: use setup_timer() and mod_timer(). Use setup_timer() instead of init_timer(), being the preferred/standard way to set a timer up. Also, quoting the mod_timer() function comment: -> mod_timer() is a more efficient way to update the expire field of an active timer (if the timer is inactive it will be activated). Use setup_timer and mod_timer to setup and arm a timer, to make the code cleaner and easier to read. Signed-off-by: Muhammad Falak R Wani <falakreyaz@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/i4l/icn/icn.c b/drivers/staging/i4l/icn/icn.c index 46d957c..4cc5a7f 100644 --- a/drivers/staging/i4l/icn/icn.c +++ b/drivers/staging/i4l/icn/icn.c @@ -980,18 +980,17 @@ icn_loadproto(u_char __user *buffer, icn_card *card) card->secondhalf); #endif spin_lock_irqsave(&card->lock, flags); - init_timer(&card->st_timer); - card->st_timer.expires = jiffies + ICN_TIMER_DCREAD; - card->st_timer.function = icn_polldchan; - card->st_timer.data = (unsigned long) card; - add_timer(&card->st_timer); + setup_timer(&card->st_timer, icn_polldchan, + (unsigned long)card); + mod_timer(&card->st_timer, + jiffies + ICN_TIMER_DCREAD); card->flags |= ICN_FLAGS_RUNNING; if (card->doubleS0) { - init_timer(&card->other->st_timer); - card->other->st_timer.expires = jiffies + ICN_TIMER_DCREAD; - card->other->st_timer.function = icn_polldchan; - card->other->st_timer.data = (unsigned long) card->other; - add_timer(&card->other->st_timer); + setup_timer(&card->other->st_timer, + icn_polldchan, + (unsigned long)card->other); + mod_timer(&card->other->st_timer, + jiffies + ICN_TIMER_DCREAD); card->other->flags |= ICN_FLAGS_RUNNING; } spin_unlock_irqrestore(&card->lock, flags); -- cgit v0.10.2 From 3fe7034e8a7ba8a564d90edd517c65e24e3df715 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Date: Sat, 11 Jun 2016 22:10:50 +0100 Subject: staging: i4l: icn: do not use return as a function return is not a function so no need to use the parenthesis. Signed-off-by: Sudip Mukherjee <sudip.mukherjee@codethink.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/i4l/icn/icn.c b/drivers/staging/i4l/icn/icn.c index 4cc5a7f..f687e04 100644 --- a/drivers/staging/i4l/icn/icn.c +++ b/drivers/staging/i4l/icn/icn.c @@ -1245,7 +1245,7 @@ icn_command(isdn_ctrl *c, icn_card *card) dev.firstload = 0; } icn_stopcard(card); - return (icn_loadboot(arg, card)); + return icn_loadboot(arg, card); case ICN_IOCTL_LOADPROTO: icn_stopcard(card); if ((i = (icn_loadproto(arg, card)))) @@ -1261,7 +1261,7 @@ icn_command(isdn_ctrl *c, icn_card *card) arg, sizeof(cdef))) return -EFAULT; - return (icn_addcard(cdef.port, cdef.id1, cdef.id2)); + return icn_addcard(cdef.port, cdef.id1, cdef.id2); break; case ICN_IOCTL_LEASEDCFG: if (a) { @@ -1457,7 +1457,7 @@ if_command(isdn_ctrl *c) icn_card *card = icn_findcard(c->driver); if (card) - return (icn_command(c, card)); + return icn_command(c, card); printk(KERN_ERR "icn: if_command %d called with invalid driverId %d!\n", c->command, c->driver); @@ -1472,7 +1472,7 @@ if_writecmd(const u_char __user *buf, int len, int id, int channel) if (card) { if (!(card->flags & ICN_FLAGS_RUNNING)) return -ENODEV; - return (icn_writecmd(buf, len, 1, card)); + return icn_writecmd(buf, len, 1, card); } printk(KERN_ERR "icn: if_writecmd called with invalid driverId!\n"); @@ -1487,7 +1487,7 @@ if_readstatus(u_char __user *buf, int len, int id, int channel) if (card) { if (!(card->flags & ICN_FLAGS_RUNNING)) return -ENODEV; - return (icn_readstatus(buf, len, card)); + return icn_readstatus(buf, len, card); } printk(KERN_ERR "icn: if_readstatus called with invalid driverId!\n"); @@ -1502,7 +1502,7 @@ if_sendbuf(int id, int channel, int ack, struct sk_buff *skb) if (card) { if (!(card->flags & ICN_FLAGS_RUNNING)) return -ENODEV; - return (icn_sendbuf(channel, ack, skb, card)); + return icn_sendbuf(channel, ack, skb, card); } printk(KERN_ERR "icn: if_sendbuf called with invalid driverId!\n"); @@ -1616,7 +1616,7 @@ icn_setup(char *line) icn_id2 = sid2; } } - return (1); + return 1; } __setup("icn=", icn_setup); #endif /* MODULE */ @@ -1643,7 +1643,7 @@ static int __init icn_init(void) strcpy(rev, " ??? "); printk(KERN_NOTICE "ICN-ISDN-driver Rev%smem=0x%08lx\n", rev, dev.memaddr); - return (icn_addcard(portbase, icn_id, icn_id2)); + return icn_addcard(portbase, icn_id, icn_id2); } static void __exit icn_exit(void) -- cgit v0.10.2 From ee05e5f7113ea0b0db7eff7011a534c92fec2648 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Date: Sat, 11 Jun 2016 22:10:51 +0100 Subject: staging: i4l: icn: donot assign in if statement It is not the kernel coding style to make assignments in the if statement and checkpatch was warning us about it. Signed-off-by: Sudip Mukherjee <sudip.mukherjee@codethink.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/i4l/icn/icn.c b/drivers/staging/i4l/icn/icn.c index f687e04..f858206 100644 --- a/drivers/staging/i4l/icn/icn.c +++ b/drivers/staging/i4l/icn/icn.c @@ -62,7 +62,8 @@ icn_free_queue(icn_card *card, int channel) skb_queue_purge(queue); card->xlen[channel] = 0; card->sndcount[channel] = 0; - if ((skb = card->xskb[channel])) { + skb = card->xskb[channel]; + if (skb) { card->xskb[channel] = NULL; dev_kfree_skb(skb); } @@ -272,8 +273,10 @@ icn_pollbchan_receive(int channel, icn_card *card) rbnext; icn_maprelease_channel(card, mch & 2); if (!eflag) { - if ((cnt = card->rcvidx[channel])) { - if (!(skb = dev_alloc_skb(cnt))) { + cnt = card->rcvidx[channel]; + if (cnt) { + skb = dev_alloc_skb(cnt); + if (!skb) { printk(KERN_WARNING "icn: receive out of memory\n"); break; } @@ -807,7 +810,8 @@ icn_loadboot(u_char __user *buffer, icn_card *card) #ifdef BOOT_DEBUG printk(KERN_DEBUG "icn_loadboot called, buffaddr=%08lx\n", (ulong) buffer); #endif - if (!(codebuf = kmalloc(ICN_CODE_STAGE1, GFP_KERNEL))) { + codebuf = kmalloc(ICN_CODE_STAGE1, GFP_KERNEL); + if (!codebuf) { printk(KERN_WARNING "icn: Could not allocate code buffer\n"); ret = -ENOMEM; goto out; @@ -878,7 +882,8 @@ icn_loadboot(u_char __user *buffer, icn_card *card) } SLEEP(1); OUTB_P(0xff, ICN_RUN); /* Start Boot-Code */ - if ((ret = icn_check_loader(card->doubleS0 ? 2 : 1))) { + ret = icn_check_loader(card->doubleS0 ? 2 : 1); + if (ret) { goto out_kfree; } if (!card->doubleS0) { @@ -1248,7 +1253,8 @@ icn_command(isdn_ctrl *c, icn_card *card) return icn_loadboot(arg, card); case ICN_IOCTL_LOADPROTO: icn_stopcard(card); - if ((i = (icn_loadproto(arg, card)))) + i = (icn_loadproto(arg, card)); + if (i) return i; if (card->doubleS0) i = icn_loadproto(arg + ICN_CODE_STAGE2, card->other); @@ -1519,7 +1525,8 @@ icn_initcard(int port, char *id) icn_card *card; int i; - if (!(card = kzalloc(sizeof(icn_card), GFP_KERNEL))) { + card = kzalloc(sizeof(icn_card), GFP_KERNEL); + if (!card) { printk(KERN_WARNING "icn: (%s) Could not allocate card-struct.\n", id); return (icn_card *) 0; @@ -1567,7 +1574,8 @@ icn_addcard(int port, char *id1, char *id2) icn_card *card; icn_card *card2; - if (!(card = icn_initcard(port, id1))) { + card = icn_initcard(port, id1); + if (!card) { return -EIO; } if (!strlen(id2)) { @@ -1576,7 +1584,8 @@ icn_addcard(int port, char *id1, char *id2) card->interface.id, port); return 0; } - if (!(card2 = icn_initcard(port, id2))) { + card2 = icn_initcard(port, id2); + if (!card2) { printk(KERN_INFO "icn: (%s) half ICN-4B, port 0x%x added\n", id2, port); return 0; @@ -1610,7 +1619,8 @@ icn_setup(char *line) if (str && *str) { strlcpy(sid, str, sizeof(sid)); icn_id = sid; - if ((p = strchr(sid, ','))) { + p = strchr(sid, ','); + if (p) { *p++ = 0; strcpy(sid2, p); icn_id2 = sid2; @@ -1633,7 +1643,8 @@ static int __init icn_init(void) dev.firstload = 1; spin_lock_init(&dev.devlock); - if ((p = strchr(revision, ':'))) { + p = strchr(revision, ':'); + if (p) { strncpy(rev, p + 1, 20); rev[20] = '\0'; p = strchr(rev, '$'); -- cgit v0.10.2 From 4ea288e11163aec8688509e42eecd114daba1e1d Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Date: Sat, 11 Jun 2016 22:10:53 +0100 Subject: staging: i4l: icn: remove braces Braces are not required in a single statement block. Signed-off-by: Sudip Mukherjee <sudip.mukherjee@codethink.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/i4l/icn/icn.c b/drivers/staging/i4l/icn/icn.c index f858206..b2f4055 100644 --- a/drivers/staging/i4l/icn/icn.c +++ b/drivers/staging/i4l/icn/icn.c @@ -883,9 +883,8 @@ icn_loadboot(u_char __user *buffer, icn_card *card) SLEEP(1); OUTB_P(0xff, ICN_RUN); /* Start Boot-Code */ ret = icn_check_loader(card->doubleS0 ? 2 : 1); - if (ret) { + if (ret) goto out_kfree; - } if (!card->doubleS0) { ret = 0; goto out_kfree; @@ -1273,9 +1272,8 @@ icn_command(isdn_ctrl *c, icn_card *card) if (a) { if (!card->leased) { card->leased = 1; - while (card->ptype == ISDN_PTYPE_UNKNOWN) { + while (card->ptype == ISDN_PTYPE_UNKNOWN) msleep_interruptible(ICN_BOOT_TIMEOUT1); - } msleep_interruptible(ICN_BOOT_TIMEOUT1); sprintf(cbuf, "00;FV2ON\n01;EAZ%c\n02;EAZ%c\n", (a & 1) ? '1' : 'C', (a & 2) ? '2' : 'C'); @@ -1575,9 +1573,8 @@ icn_addcard(int port, char *id1, char *id2) icn_card *card2; card = icn_initcard(port, id1); - if (!card) { + if (!card) return -EIO; - } if (!strlen(id2)) { printk(KERN_INFO "icn: (%s) ICN-2B, port 0x%x added\n", -- cgit v0.10.2 From aec8755d9d7a72a2fb74dfcb95d709710d5be44a Mon Sep 17 00:00:00 2001 From: Anthony Sheldon <sheldon.anthony.sheldon@gmail.com> Date: Fri, 19 Aug 2016 16:42:13 +0100 Subject: staging: i4l: Reformat braces around else As suggested by Documentation/CodingStyle move braces onto same line as else. Signed-off-by: Anthony Sheldon <sheldon.anthony.sheldon@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/i4l/pcbit/capi.c b/drivers/staging/i4l/pcbit/capi.c index 4e3cbf8..373f90f 100644 --- a/drivers/staging/i4l/pcbit/capi.c +++ b/drivers/staging/i4l/pcbit/capi.c @@ -92,9 +92,7 @@ int capi_conn_req(const char *calledPN, struct sk_buff **skb, int proto) *(skb_put(*skb, 1)) = 0x80; /* Speech */ *(skb_put(*skb, 1)) = 0x10; /* Circuit Mode */ *(skb_put(*skb, 1)) = 0x23; /* A-law */ - } - else - { + } else { /* Bearer Capability - Mandatory*/ *(skb_put(*skb, 1)) = 2; /* BC0.Length */ *(skb_put(*skb, 1)) = 0x88; /* Digital Information */ -- cgit v0.10.2 From eeeb5fb9323c75663da5a8d1d068cd7176aa77b4 Mon Sep 17 00:00:00 2001 From: Joshua Houghton <josh@awful.name> Date: Mon, 1 Aug 2016 19:17:25 +0000 Subject: drivers: wilc1000: remove references to semaphores * Update the comments that refer to semaphores * Remove redundant includes to semphore.h Signed-off-by: Joshua Houghton <josh@awful.name> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wilc1000/TODO b/drivers/staging/wilc1000/TODO index ec93b2e..ae61b55 100644 --- a/drivers/staging/wilc1000/TODO +++ b/drivers/staging/wilc1000/TODO @@ -3,7 +3,6 @@ TODO: - remove OS wrapper functions - remove custom debug and tracing functions - rework comments and function headers(also coding style) -- replace all semaphores with mutexes or completions - Move handling for each individual members of 'union message_body' out into a separate 'struct work_struct' and completely remove the multiplexer that is currently part of host_if_work(), allowing movement of the diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 3a66255..315ed2e 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -21,7 +21,6 @@ #include <linux/kernel.h> #include <linux/skbuff.h> #include <linux/mutex.h> -#include <linux/semaphore.h> #include <linux/completion.h> static int dev_state_ev_handler(struct notifier_block *this, diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index 5cc6a82..ec6b167 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -131,7 +131,7 @@ struct wilc_priv { struct wilc_wfi_key *wilc_gtk[MAX_NUM_STA]; struct wilc_wfi_key *wilc_ptk[MAX_NUM_STA]; u8 wilc_groupkey; - /* semaphores */ + /* mutexes */ struct mutex scan_req_lock; /* */ bool gbAutoRateAdjusted; diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index 30e5312..de6c4dd 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -192,7 +192,7 @@ #define ENABLE_RX_VMM (SEL_VMM_TBL1 | EN_VMM) #define ENABLE_TX_VMM (SEL_VMM_TBL0 | EN_VMM) -/*time for expiring the semaphores of cfg packets*/ +/*time for expiring the completion of cfg packets*/ #define CFG_PKTS_TIMEOUT 2000 /******************************************** * diff --git a/drivers/staging/wilc1000/wilc_wlan_if.h b/drivers/staging/wilc1000/wilc_wlan_if.h index 410bfc0..439ac6f 100644 --- a/drivers/staging/wilc1000/wilc_wlan_if.h +++ b/drivers/staging/wilc1000/wilc_wlan_if.h @@ -10,7 +10,6 @@ #ifndef WILC_WLAN_IF_H #define WILC_WLAN_IF_H -#include <linux/semaphore.h> #include <linux/netdevice.h> /******************************************** -- cgit v0.10.2 From ef6687c627a5338f1fbea134efca6e7f479cd70c Mon Sep 17 00:00:00 2001 From: Luis de Bethencourt <luisbg@osg.samsung.com> Date: Mon, 27 Jun 2016 14:00:20 +0100 Subject: staging: wilc1000: fix error handling in wilc_debugfs_init() We can just ignore the return value from debugfs_create_dir() and debugfs_create_file(). The second one already interanlly checks the dentry created by the first before creating the file. debugfs was written so it would be easy to use, no need for error checking. Signed-off-by: Luis de Bethencourt <luisbg@osg.samsung.com> Suggested-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wilc1000/wilc_debugfs.c b/drivers/staging/wilc1000/wilc_debugfs.c index fcbc95d..b052628 100644 --- a/drivers/staging/wilc1000/wilc_debugfs.c +++ b/drivers/staging/wilc1000/wilc_debugfs.c @@ -102,35 +102,16 @@ static struct wilc_debugfs_info_t debugfs_info[] = { static int __init wilc_debugfs_init(void) { int i; - - struct dentry *debugfs_files; struct wilc_debugfs_info_t *info; wilc_dir = debugfs_create_dir("wilc_wifi", NULL); - if (wilc_dir == ERR_PTR(-ENODEV)) { - /* it's not error. the debugfs is just not being enabled. */ - printk("ERR, kernel has built without debugfs support\n"); - return 0; - } - - if (!wilc_dir) { - printk("ERR, debugfs create dir\n"); - return -1; - } - for (i = 0; i < ARRAY_SIZE(debugfs_info); i++) { info = &debugfs_info[i]; - debugfs_files = debugfs_create_file(info->name, - info->perm, - wilc_dir, - &info->data, - &info->fops); - - if (!debugfs_files) { - printk("ERR fail to create the debugfs file, %s\n", info->name); - debugfs_remove_recursive(wilc_dir); - return -1; - } + debugfs_create_file(info->name, + info->perm, + wilc_dir, + &info->data, + &info->fops); } return 0; } -- cgit v0.10.2 From 410478415c10777ee86aef50a998ab3db4d1fe73 Mon Sep 17 00:00:00 2001 From: YU Bo <tsu.yubo@gmail.com> Date: Wed, 11 May 2016 22:29:44 +0800 Subject: Staging: wlan-ng: Fix trailing */ in block comments. Fix checkpatch.pl warning: WARNING: Block comments use a trailing */ on a separate line. Signed-off-by: Bo Yu <tsu.yubo@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c index fe914b1..4dd4cdf 100644 --- a/drivers/staging/wlan-ng/prism2mib.c +++ b/drivers/staging/wlan-ng/prism2mib.c @@ -237,25 +237,25 @@ static struct mibrec mibtab[] = { {0, 0, 0, 0, 0, NULL} }; -/*---------------------------------------------------------------- -* prism2mgmt_mibset_mibget -* -* Set the value of a mib item. -* -* Arguments: -* wlandev wlan device structure -* msgp ptr to msg buffer -* -* Returns: -* 0 success and done -* <0 success, but we're waiting for something to finish. -* >0 an error occurred while handling the message. -* Side effects: -* -* Call context: -* process thread (usually) -* interrupt -----------------------------------------------------------------*/ +/* + * prism2mgmt_mibset_mibget + * + * Set the value of a mib item. + * + * Arguments: + * wlandev wlan device structure + * msgp ptr to msg buffer + * + * Returns: + * 0 success and done + * <0 success, but we're waiting for something to finish. + * >0 an error occurred while handling the message. + * Side effects: + * + * Call context: + * process thread (usually) + * interrupt + */ int prism2mgmt_mibset_mibget(wlandevice_t *wlandev, void *msgp) { @@ -346,30 +346,30 @@ done: return 0; } -/*---------------------------------------------------------------- -* prism2mib_bytearea2pstr -* -* Get/set pstr data to/from a byte area. -* -* MIB record parameters: -* parm1 Prism2 RID value. -* parm2 Number of bytes of RID data. -* parm3 Not used. -* -* Arguments: -* mib MIB record. -* isget MIBGET/MIBSET flag. -* wlandev wlan device structure. -* priv "priv" structure. -* hw "hw" structure. -* msg Message structure. -* data Data buffer. -* -* Returns: -* 0 - Success. -* ~0 - Error. -* -----------------------------------------------------------------*/ +/* + * prism2mib_bytearea2pstr + * + * Get/set pstr data to/from a byte area. + * + * MIB record parameters: + * parm1 Prism2 RID value. + * parm2 Number of bytes of RID data. + * parm3 Not used. + * + * Arguments: + * mib MIB record. + * isget MIBGET/MIBSET flag. + * wlandev wlan device structure. + * priv "priv" structure. + * hw "hw" structure. + * msg Message structure. + * data Data buffer. + * + * Returns: + * 0 - Success. + * ~0 - Error. + * + */ static int prism2mib_bytearea2pstr(struct mibrec *mib, int isget, @@ -396,30 +396,30 @@ static int prism2mib_bytearea2pstr(struct mibrec *mib, return result; } -/*---------------------------------------------------------------- -* prism2mib_uint32 -* -* Get/set uint32 data. -* -* MIB record parameters: -* parm1 Prism2 RID value. -* parm2 Not used. -* parm3 Not used. -* -* Arguments: -* mib MIB record. -* isget MIBGET/MIBSET flag. -* wlandev wlan device structure. -* priv "priv" structure. -* hw "hw" structure. -* msg Message structure. -* data Data buffer. -* -* Returns: -* 0 - Success. -* ~0 - Error. -* -----------------------------------------------------------------*/ +/* + * prism2mib_uint32 + * + * Get/set uint32 data. + * + * MIB record parameters: + * parm1 Prism2 RID value. + * parm2 Not used. + * parm3 Not used. + * + * Arguments: + * mib MIB record. + * isget MIBGET/MIBSET flag. + * wlandev wlan device structure. + * priv "priv" structure. + * hw "hw" structure. + * msg Message structure. + * data Data buffer. + * + * Returns: + * 0 - Success. + * ~0 - Error. + * + */ static int prism2mib_uint32(struct mibrec *mib, int isget, @@ -443,30 +443,30 @@ static int prism2mib_uint32(struct mibrec *mib, return result; } -/*---------------------------------------------------------------- -* prism2mib_flag -* -* Get/set a flag. -* -* MIB record parameters: -* parm1 Prism2 RID value. -* parm2 Bit to get/set. -* parm3 Not used. -* -* Arguments: -* mib MIB record. -* isget MIBGET/MIBSET flag. -* wlandev wlan device structure. -* priv "priv" structure. -* hw "hw" structure. -* msg Message structure. -* data Data buffer. -* -* Returns: -* 0 - Success. -* ~0 - Error. -* -----------------------------------------------------------------*/ +/* + * prism2mib_flag + * + * Get/set a flag. + * + * MIB record parameters: + * parm1 Prism2 RID value. + * parm2 Bit to get/set. + * parm3 Not used. + * + * Arguments: + * mib MIB record. + * isget MIBGET/MIBSET flag. + * wlandev wlan device structure. + * priv "priv" structure. + * hw "hw" structure. + * msg Message structure. + * data Data buffer. + * + * Returns: + * 0 - Success. + * ~0 - Error. + * + */ static int prism2mib_flag(struct mibrec *mib, int isget, @@ -500,30 +500,30 @@ static int prism2mib_flag(struct mibrec *mib, return result; } -/*---------------------------------------------------------------- -* prism2mib_wepdefaultkey -* -* Get/set WEP default keys. -* -* MIB record parameters: -* parm1 Prism2 RID value. -* parm2 Number of bytes of RID data. -* parm3 Not used. -* -* Arguments: -* mib MIB record. -* isget MIBGET/MIBSET flag. -* wlandev wlan device structure. -* priv "priv" structure. -* hw "hw" structure. -* msg Message structure. -* data Data buffer. -* -* Returns: -* 0 - Success. -* ~0 - Error. -* -----------------------------------------------------------------*/ +/* + * prism2mib_wepdefaultkey + * + * Get/set WEP default keys. + * + * MIB record parameters: + * parm1 Prism2 RID value. + * parm2 Number of bytes of RID data. + * parm3 Not used. + * + * Arguments: + * mib MIB record. + * isget MIBGET/MIBSET flag. + * wlandev wlan device structure. + * priv "priv" structure. + * hw "hw" structure. + * msg Message structure. + * data Data buffer. + * + * Returns: + * 0 - Success. + * ~0 - Error. + * + */ static int prism2mib_wepdefaultkey(struct mibrec *mib, int isget, @@ -550,30 +550,30 @@ static int prism2mib_wepdefaultkey(struct mibrec *mib, return result; } -/*---------------------------------------------------------------- -* prism2mib_privacyinvoked -* -* Get/set the dot11PrivacyInvoked value. -* -* MIB record parameters: -* parm1 Prism2 RID value. -* parm2 Bit value for PrivacyInvoked flag. -* parm3 Not used. -* -* Arguments: -* mib MIB record. -* isget MIBGET/MIBSET flag. -* wlandev wlan device structure. -* priv "priv" structure. -* hw "hw" structure. -* msg Message structure. -* data Data buffer. -* -* Returns: -* 0 - Success. -* ~0 - Error. -* -----------------------------------------------------------------*/ +/* + * prism2mib_privacyinvoked + * + * Get/set the dot11PrivacyInvoked value. + * + * MIB record parameters: + * parm1 Prism2 RID value. + * parm2 Bit value for PrivacyInvoked flag. + * parm3 Not used. + * + * Arguments: + * mib MIB record. + * isget MIBGET/MIBSET flag. + * wlandev wlan device structure. + * priv "priv" structure. + * hw "hw" structure. + * msg Message structure. + * data Data buffer. + * + * Returns: + * 0 - Success. + * ~0 - Error. + * + */ static int prism2mib_privacyinvoked(struct mibrec *mib, int isget, @@ -592,30 +592,30 @@ static int prism2mib_privacyinvoked(struct mibrec *mib, return prism2mib_flag(mib, isget, wlandev, hw, msg, data); } -/*---------------------------------------------------------------- -* prism2mib_excludeunencrypted -* -* Get/set the dot11ExcludeUnencrypted value. -* -* MIB record parameters: -* parm1 Prism2 RID value. -* parm2 Bit value for ExcludeUnencrypted flag. -* parm3 Not used. -* -* Arguments: -* mib MIB record. -* isget MIBGET/MIBSET flag. -* wlandev wlan device structure. -* priv "priv" structure. -* hw "hw" structure. -* msg Message structure. -* data Data buffer. -* -* Returns: -* 0 - Success. -* ~0 - Error. -* -----------------------------------------------------------------*/ +/* + * prism2mib_excludeunencrypted + * + * Get/set the dot11ExcludeUnencrypted value. + * + * MIB record parameters: + * parm1 Prism2 RID value. + * parm2 Bit value for ExcludeUnencrypted flag. + * parm3 Not used. + * + * Arguments: + * mib MIB record. + * isget MIBGET/MIBSET flag. + * wlandev wlan device structure. + * priv "priv" structure. + * hw "hw" structure. + * msg Message structure. + * data Data buffer. + * + * Returns: + * 0 - Success. + * ~0 - Error. + * + */ static int prism2mib_excludeunencrypted(struct mibrec *mib, int isget, @@ -628,30 +628,30 @@ static int prism2mib_excludeunencrypted(struct mibrec *mib, return prism2mib_flag(mib, isget, wlandev, hw, msg, data); } -/*---------------------------------------------------------------- -* prism2mib_fragmentationthreshold -* -* Get/set the fragmentation threshold. -* -* MIB record parameters: -* parm1 Prism2 RID value. -* parm2 Not used. -* parm3 Not used. -* -* Arguments: -* mib MIB record. -* isget MIBGET/MIBSET flag. -* wlandev wlan device structure. -* priv "priv" structure. -* hw "hw" structure. -* msg Message structure. -* data Data buffer. -* -* Returns: -* 0 - Success. -* ~0 - Error. -* -----------------------------------------------------------------*/ +/* + * prism2mib_fragmentationthreshold + * + * Get/set the fragmentation threshold. + * + * MIB record parameters: + * parm1 Prism2 RID value. + * parm2 Not used. + * parm3 Not used. + * + * Arguments: + * mib MIB record. + * isget MIBGET/MIBSET flag. + * wlandev wlan device structure. + * priv "priv" structure. + * hw "hw" structure. + * msg Message structure. + * data Data buffer. + * + * Returns: + * 0 - Success. + * ~0 - Error. + * + */ static int prism2mib_fragmentationthreshold(struct mibrec *mib, int isget, @@ -674,30 +674,30 @@ static int prism2mib_fragmentationthreshold(struct mibrec *mib, return prism2mib_uint32(mib, isget, wlandev, hw, msg, data); } -/*---------------------------------------------------------------- -* prism2mib_priv -* -* Get/set values in the "priv" data structure. -* -* MIB record parameters: -* parm1 Not used. -* parm2 Not used. -* parm3 Not used. -* -* Arguments: -* mib MIB record. -* isget MIBGET/MIBSET flag. -* wlandev wlan device structure. -* priv "priv" structure. -* hw "hw" structure. -* msg Message structure. -* data Data buffer. -* -* Returns: -* 0 - Success. -* ~0 - Error. -* -----------------------------------------------------------------*/ +/* + * prism2mib_priv + * + * Get/set values in the "priv" data structure. + * + * MIB record parameters: + * parm1 Not used. + * parm2 Not used. + * parm3 Not used. + * + * Arguments: + * mib MIB record. + * isget MIBGET/MIBSET flag. + * wlandev wlan device structure. + * priv "priv" structure. + * hw "hw" structure. + * msg Message structure. + * data Data buffer. + * + * Returns: + * 0 - Success. + * ~0 - Error. + * + */ static int prism2mib_priv(struct mibrec *mib, int isget, @@ -736,20 +736,20 @@ static int prism2mib_priv(struct mibrec *mib, return 0; } -/*---------------------------------------------------------------- -* prism2mgmt_pstr2bytestr -* -* Convert the pstr data in the WLAN message structure into an hfa384x -* byte string format. -* -* Arguments: -* bytestr hfa384x byte string data type -* pstr wlan message data -* -* Returns: -* Nothing -* -----------------------------------------------------------------*/ +/* + * prism2mgmt_pstr2bytestr + * + * Convert the pstr data in the WLAN message structure into an hfa384x + * byte string format. + * + * Arguments: + * bytestr hfa384x byte string data type + * pstr wlan message data + * + * Returns: + * Nothing + * + */ void prism2mgmt_pstr2bytestr(struct hfa384x_bytestr *bytestr, p80211pstrd_t *pstr) @@ -758,20 +758,20 @@ void prism2mgmt_pstr2bytestr(struct hfa384x_bytestr *bytestr, memcpy(bytestr->data, pstr->data, pstr->len); } -/*---------------------------------------------------------------- -* prism2mgmt_bytestr2pstr -* -* Convert the data in an hfa384x byte string format into a -* pstr in the WLAN message. -* -* Arguments: -* bytestr hfa384x byte string data type -* msg wlan message -* -* Returns: -* Nothing -* -----------------------------------------------------------------*/ +/* + * prism2mgmt_bytestr2pstr + * + * Convert the data in an hfa384x byte string format into a + * pstr in the WLAN message. + * + * Arguments: + * bytestr hfa384x byte string data type + * msg wlan message + * + * Returns: + * Nothing + * + */ void prism2mgmt_bytestr2pstr(struct hfa384x_bytestr *bytestr, p80211pstrd_t *pstr) @@ -780,20 +780,20 @@ void prism2mgmt_bytestr2pstr(struct hfa384x_bytestr *bytestr, memcpy(pstr->data, bytestr->data, pstr->len); } -/*---------------------------------------------------------------- -* prism2mgmt_bytearea2pstr -* -* Convert the data in an hfa384x byte area format into a pstr -* in the WLAN message. -* -* Arguments: -* bytearea hfa384x byte area data type -* msg wlan message -* -* Returns: -* Nothing -* -----------------------------------------------------------------*/ +/* + * prism2mgmt_bytearea2pstr + * + * Convert the data in an hfa384x byte area format into a pstr + * in the WLAN message. + * + * Arguments: + * bytearea hfa384x byte area data type + * msg wlan message + * + * Returns: + * Nothing + * + */ void prism2mgmt_bytearea2pstr(u8 *bytearea, p80211pstrd_t *pstr, int len) { -- cgit v0.10.2 From 8d215eadf6728ce31a84e830a5b7bf8c284b39bf Mon Sep 17 00:00:00 2001 From: Kevin McKinney <klmckinney1@gmail.com> Date: Wed, 25 May 2016 23:22:05 -0400 Subject: Staging: wlan-ng: fix alignment not matching. This patch fixes alignment should match open parenthesis found by checkpatch.pl tool in prism2usb.c. Signed-off-by: Kevin McKinney <klmckinney1@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/prism2usb.c b/drivers/staging/wlan-ng/prism2usb.c index b26d09f..43123f3 100644 --- a/drivers/staging/wlan-ng/prism2usb.c +++ b/drivers/staging/wlan-ng/prism2usb.c @@ -47,11 +47,11 @@ static const struct usb_device_id usb_prism_tbl[] = { PRISM_DEV(0x0bb2, 0x0302, "Ambit Microsystems Corp."), PRISM_DEV(0x9016, 0x182d, "Sitecom WL-022 802.11b USB Adapter"), PRISM_DEV(0x0543, 0x0f01, - "ViewSonic Airsync USB Adapter 11Mbps (Prism2.5)"), + "ViewSonic Airsync USB Adapter 11Mbps (Prism2.5)"), PRISM_DEV(0x067c, 0x1022, - "Siemens SpeedStream 1022 11Mbps WLAN USB Adapter"), + "Siemens SpeedStream 1022 11Mbps WLAN USB Adapter"), PRISM_DEV(0x049f, 0x0033, - "Compaq/Intel W100 PRO/Wireless 11Mbps multiport WLAN Adapter"), + "Compaq/Intel W100 PRO/Wireless 11Mbps multiport WLAN Adapter"), { } /* terminator */ }; MODULE_DEVICE_TABLE(usb, usb_prism_tbl); @@ -216,7 +216,7 @@ exit: #ifdef CONFIG_PM static int prism2sta_suspend(struct usb_interface *interface, - pm_message_t message) + pm_message_t message) { hfa384x_t *hw = NULL; wlandevice_t *wlandev; -- cgit v0.10.2 From d03c075dda97884bb79c206fc9804f07017b7bd4 Mon Sep 17 00:00:00 2001 From: Kevin McKinney <klmckinney1@gmail.com> Date: Wed, 25 May 2016 23:22:06 -0400 Subject: Staging: wlan-ng: fix unnecessary parentheses. This patch fixes Unnecessary parentheses around interface->dev found by checkpatch.pl tool. Signed-off-by: Kevin McKinney <klmckinney1@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/prism2usb.c b/drivers/staging/wlan-ng/prism2usb.c index 43123f3..82be343 100644 --- a/drivers/staging/wlan-ng/prism2usb.c +++ b/drivers/staging/wlan-ng/prism2usb.c @@ -74,7 +74,7 @@ static int prism2sta_probe_usb(struct usb_interface *interface, } hw = wlandev->priv; - if (wlan_setup(wlandev, &(interface->dev)) != 0) { + if (wlan_setup(wlandev, &interface->dev) != 0) { dev_err(&interface->dev, "wlan_setup() failed.\n"); result = -EIO; goto failed; @@ -87,7 +87,7 @@ static int prism2sta_probe_usb(struct usb_interface *interface, /* Register the wlandev, this gets us a name and registers the * linux netdevice. */ - SET_NETDEV_DEV(wlandev->netdev, &(interface->dev)); + SET_NETDEV_DEV(wlandev->netdev, &interface->dev); /* Do a chip-level reset on the MAC */ if (prism2_doreset) { -- cgit v0.10.2 From 1f0c9efe5627ed12b469dae7434795ed625936bf Mon Sep 17 00:00:00 2001 From: Kevin McKinney <klmckinney1@gmail.com> Date: Wed, 25 May 2016 23:22:07 -0400 Subject: Staging: wlan-ng: fix comparison to NULL issue. This patch fixes comparison to NULL could be written "wlandev" found by checkpatch.pl tool. Signed-off-by: Kevin McKinney <klmckinney1@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/prism2usb.c b/drivers/staging/wlan-ng/prism2usb.c index 82be343..0463ec1 100644 --- a/drivers/staging/wlan-ng/prism2usb.c +++ b/drivers/staging/wlan-ng/prism2usb.c @@ -137,7 +137,7 @@ static void prism2sta_disconnect_usb(struct usb_interface *interface) wlandevice_t *wlandev; wlandev = (wlandevice_t *)usb_get_intfdata(interface); - if (wlandev != NULL) { + if (wlandev) { LIST_HEAD(cleanlist); hfa384x_usbctlx_t *ctlx, *temp; unsigned long flags; -- cgit v0.10.2 From e7f63771b60e7802c5a9b437c5ab1a8e33a0bb35 Mon Sep 17 00:00:00 2001 From: Chen Feng <puck.chen@hisilicon.com> Date: Thu, 19 May 2016 11:03:16 +0800 Subject: ION: Sys_heap: Add cached pool to spead up cached buffer alloc Add ion cached pool in system heap. This patch add a cached pool in system heap. It has a great improvement of alloc for cached buffer. With memory pressue alloc test 800MB in userspace used iontest. The result avg is 577ms. Without patch it's avg is about 883ms. v1: Makes the cached buffer zeroed before going to pool v2: Add cached param in pool to distinguish wheather need to flush cache at a fresh alloc. Rework the shrink function. Signed-off-by: Chen Feng <puck.chen@hisilicon.com> Signed-off-by: Xia Qing <saberlily.xia@hisilicon.com> Reviewed-by: Fu Jun <oliver.fu@hisilicon.com> Acked-by: Laura Abbott <labbott@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index 1fe8016..2c5e5c5 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -30,8 +30,9 @@ static void *ion_page_pool_alloc_pages(struct ion_page_pool *pool) if (!page) return NULL; - ion_pages_sync_for_device(NULL, page, PAGE_SIZE << pool->order, - DMA_BIDIRECTIONAL); + if (!pool->cached) + ion_pages_sync_for_device(NULL, page, PAGE_SIZE << pool->order, + DMA_BIDIRECTIONAL); return page; } @@ -147,7 +148,8 @@ int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, return freed; } -struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order) +struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order, + bool cached) { struct ion_page_pool *pool = kmalloc(sizeof(*pool), GFP_KERNEL); @@ -161,6 +163,8 @@ struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order) pool->order = order; mutex_init(&pool->mutex); plist_node_init(&pool->list, order); + if (cached) + pool->cached = true; return pool; } diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index 25e4bb2..5eed5e2 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -332,6 +332,7 @@ void ion_cma_heap_destroy(struct ion_heap *); * @gfp_mask: gfp_mask to use from alloc * @order: order of pages in the pool * @list: plist node for list of pools + * @cached: it's cached pool or not * * Allows you to keep a pool of pre allocated pages to use from your heap. * Keeping a pool of pages that is ready for dma, ie any cached mapping have @@ -341,6 +342,7 @@ void ion_cma_heap_destroy(struct ion_heap *); struct ion_page_pool { int high_count; int low_count; + bool cached; struct list_head high_items; struct list_head low_items; struct mutex mutex; @@ -349,7 +351,8 @@ struct ion_page_pool { struct plist_node list; }; -struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order); +struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order, + bool cached); void ion_page_pool_destroy(struct ion_page_pool *); struct page *ion_page_pool_alloc(struct ion_page_pool *); void ion_page_pool_free(struct ion_page_pool *, struct page *); diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index b697c6d..269e776 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -26,16 +26,18 @@ #include "ion.h" #include "ion_priv.h" +#define NUM_ORDERS ARRAY_SIZE(orders) + static gfp_t high_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN | __GFP_NORETRY) & ~__GFP_RECLAIM; static gfp_t low_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN); static const unsigned int orders[] = {8, 4, 0}; -static const int num_orders = ARRAY_SIZE(orders); + static int order_to_index(unsigned int order) { int i; - for (i = 0; i < num_orders; i++) + for (i = 0; i < NUM_ORDERS; i++) if (order == orders[i]) return i; BUG(); @@ -49,47 +51,55 @@ static inline unsigned int order_to_size(int order) struct ion_system_heap { struct ion_heap heap; - struct ion_page_pool *pools[0]; + struct ion_page_pool *uncached_pools[NUM_ORDERS]; + struct ion_page_pool *cached_pools[NUM_ORDERS]; }; +/** + * The page from page-pool are all zeroed before. We need do cache + * clean for cached buffer. The uncached buffer are always non-cached + * since it's allocated. So no need for non-cached pages. + */ static struct page *alloc_buffer_page(struct ion_system_heap *heap, struct ion_buffer *buffer, unsigned long order) { bool cached = ion_buffer_cached(buffer); - struct ion_page_pool *pool = heap->pools[order_to_index(order)]; + struct ion_page_pool *pool; struct page *page; - if (!cached) { - page = ion_page_pool_alloc(pool); - } else { - gfp_t gfp_flags = low_order_gfp_flags; + if (!cached) + pool = heap->uncached_pools[order_to_index(order)]; + else + pool = heap->cached_pools[order_to_index(order)]; - if (order > 4) - gfp_flags = high_order_gfp_flags; - page = alloc_pages(gfp_flags | __GFP_COMP, order); - if (!page) - return NULL; - ion_pages_sync_for_device(NULL, page, PAGE_SIZE << order, - DMA_BIDIRECTIONAL); - } + page = ion_page_pool_alloc(pool); + if (cached) + ion_pages_sync_for_device(NULL, page, PAGE_SIZE << order, + DMA_BIDIRECTIONAL); return page; } static void free_buffer_page(struct ion_system_heap *heap, struct ion_buffer *buffer, struct page *page) { + struct ion_page_pool *pool; unsigned int order = compound_order(page); bool cached = ion_buffer_cached(buffer); - if (!cached && !(buffer->private_flags & ION_PRIV_FLAG_SHRINKER_FREE)) { - struct ion_page_pool *pool = heap->pools[order_to_index(order)]; - - ion_page_pool_free(pool, page); - } else { + /* go to system */ + if (buffer->private_flags & ION_PRIV_FLAG_SHRINKER_FREE) { __free_pages(page, order); + return; } + + if (!cached) + pool = heap->uncached_pools[order_to_index(order)]; + else + pool = heap->cached_pools[order_to_index(order)]; + + ion_page_pool_free(pool, page); } @@ -101,7 +111,7 @@ static struct page *alloc_largest_available(struct ion_system_heap *heap, struct page *page; int i; - for (i = 0; i < num_orders; i++) { + for (i = 0; i < NUM_ORDERS; i++) { if (size < order_to_size(orders[i])) continue; if (max_order < orders[i]) @@ -181,16 +191,11 @@ static void ion_system_heap_free(struct ion_buffer *buffer) struct ion_system_heap, heap); struct sg_table *table = buffer->sg_table; - bool cached = ion_buffer_cached(buffer); struct scatterlist *sg; int i; - /* - * uncached pages come from the page pools, zero them before returning - * for security purposes (other allocations are zerod at - * alloc time - */ - if (!cached && !(buffer->private_flags & ION_PRIV_FLAG_SHRINKER_FREE)) + /* zero the buffer before goto page pool */ + if (!(buffer->private_flags & ION_PRIV_FLAG_SHRINKER_FREE)) ion_heap_buffer_zero(buffer); for_each_sg(table->sgl, sg, table->nents, i) @@ -202,6 +207,8 @@ static void ion_system_heap_free(struct ion_buffer *buffer) static int ion_system_heap_shrink(struct ion_heap *heap, gfp_t gfp_mask, int nr_to_scan) { + struct ion_page_pool *uncached_pool; + struct ion_page_pool *cached_pool; struct ion_system_heap *sys_heap; int nr_total = 0; int i, nr_freed; @@ -212,20 +219,35 @@ static int ion_system_heap_shrink(struct ion_heap *heap, gfp_t gfp_mask, if (!nr_to_scan) only_scan = 1; - for (i = 0; i < num_orders; i++) { - struct ion_page_pool *pool = sys_heap->pools[i]; - - nr_freed = ion_page_pool_shrink(pool, gfp_mask, nr_to_scan); - nr_total += nr_freed; - - if (!only_scan) { + for (i = 0; i < NUM_ORDERS; i++) { + uncached_pool = sys_heap->uncached_pools[i]; + cached_pool = sys_heap->cached_pools[i]; + + if (only_scan) { + nr_total += ion_page_pool_shrink(uncached_pool, + gfp_mask, + nr_to_scan); + + nr_total += ion_page_pool_shrink(cached_pool, + gfp_mask, + nr_to_scan); + } else { + nr_freed = ion_page_pool_shrink(uncached_pool, + gfp_mask, + nr_to_scan); nr_to_scan -= nr_freed; - /* shrink completed */ + nr_total += nr_freed; + if (nr_to_scan <= 0) + break; + nr_freed = ion_page_pool_shrink(cached_pool, + gfp_mask, + nr_to_scan); + nr_to_scan -= nr_freed; + nr_total += nr_freed; if (nr_to_scan <= 0) break; } } - return nr_total; } @@ -246,52 +268,89 @@ static int ion_system_heap_debug_show(struct ion_heap *heap, struct seq_file *s, struct ion_system_heap, heap); int i; + struct ion_page_pool *pool; - for (i = 0; i < num_orders; i++) { - struct ion_page_pool *pool = sys_heap->pools[i]; + for (i = 0; i < NUM_ORDERS; i++) { + pool = sys_heap->uncached_pools[i]; - seq_printf(s, "%d order %u highmem pages in pool = %lu total\n", + seq_printf(s, "%d order %u highmem pages uncached %lu total\n", pool->high_count, pool->order, (PAGE_SIZE << pool->order) * pool->high_count); - seq_printf(s, "%d order %u lowmem pages in pool = %lu total\n", + seq_printf(s, "%d order %u lowmem pages uncached %lu total\n", + pool->low_count, pool->order, + (PAGE_SIZE << pool->order) * pool->low_count); + } + + for (i = 0; i < NUM_ORDERS; i++) { + pool = sys_heap->cached_pools[i]; + + seq_printf(s, "%d order %u highmem pages cached %lu total\n", + pool->high_count, pool->order, + (PAGE_SIZE << pool->order) * pool->high_count); + seq_printf(s, "%d order %u lowmem pages cached %lu total\n", pool->low_count, pool->order, (PAGE_SIZE << pool->order) * pool->low_count); } return 0; } +static void ion_system_heap_destroy_pools(struct ion_page_pool **pools) +{ + int i; + + for (i = 0; i < NUM_ORDERS; i++) + if (pools[i]) + ion_page_pool_destroy(pools[i]); +} + +static int ion_system_heap_create_pools(struct ion_page_pool **pools, + bool cached) +{ + int i; + gfp_t gfp_flags = low_order_gfp_flags; + + for (i = 0; i < NUM_ORDERS; i++) { + struct ion_page_pool *pool; + + if (orders[i] > 4) + gfp_flags = high_order_gfp_flags; + + pool = ion_page_pool_create(gfp_flags, orders[i], cached); + if (!pool) + goto err_create_pool; + pools[i] = pool; + } + return 0; + +err_create_pool: + ion_system_heap_destroy_pools(pools); + return -ENOMEM; +} + struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused) { struct ion_system_heap *heap; - int i; - heap = kzalloc(sizeof(struct ion_system_heap) + - sizeof(struct ion_page_pool *) * num_orders, - GFP_KERNEL); + heap = kzalloc(sizeof(*heap), GFP_KERNEL); if (!heap) return ERR_PTR(-ENOMEM); heap->heap.ops = &system_heap_ops; heap->heap.type = ION_HEAP_TYPE_SYSTEM; heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE; - for (i = 0; i < num_orders; i++) { - struct ion_page_pool *pool; - gfp_t gfp_flags = low_order_gfp_flags; + if (ion_system_heap_create_pools(heap->uncached_pools, false)) + goto free_heap; - if (orders[i] > 4) - gfp_flags = high_order_gfp_flags; - pool = ion_page_pool_create(gfp_flags, orders[i]); - if (!pool) - goto destroy_pools; - heap->pools[i] = pool; - } + if (ion_system_heap_create_pools(heap->cached_pools, true)) + goto destroy_uncached_pools; heap->heap.debug_show = ion_system_heap_debug_show; return &heap->heap; -destroy_pools: - while (i--) - ion_page_pool_destroy(heap->pools[i]); +destroy_uncached_pools: + ion_system_heap_destroy_pools(heap->uncached_pools); + +free_heap: kfree(heap); return ERR_PTR(-ENOMEM); } @@ -303,8 +362,10 @@ void ion_system_heap_destroy(struct ion_heap *heap) heap); int i; - for (i = 0; i < num_orders; i++) - ion_page_pool_destroy(sys_heap->pools[i]); + for (i = 0; i < NUM_ORDERS; i++) { + ion_page_pool_destroy(sys_heap->uncached_pools[i]); + ion_page_pool_destroy(sys_heap->cached_pools[i]); + } kfree(sys_heap); } -- cgit v0.10.2 From d2805d7fff5ba1db3accd5ef010f9fdbb1925f08 Mon Sep 17 00:00:00 2001 From: Chen Feng <puck.chen@hisilicon.com> Date: Sat, 30 Jul 2016 10:09:11 +0800 Subject: staging: ion: remove __GFP_NOWARN when use low order gfp flags It's useful to show the current memory in detail when alloc failed. And, there may be a lot of high order alloc failed, just show memory when an order 0 alloc failed. Signed-off-by: Chen Feng <puck.chen@hisilicon.com> Acked-by: Laura Abbott <labbott@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 269e776..f1cef2b 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -30,7 +30,7 @@ static gfp_t high_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN | __GFP_NORETRY) & ~__GFP_RECLAIM; -static gfp_t low_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN); +static gfp_t low_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO); static const unsigned int orders[] = {8, 4, 0}; static int order_to_index(unsigned int order) -- cgit v0.10.2 From 175f5a4130b20e25b34d9f9b0bb4cfe80ee49d88 Mon Sep 17 00:00:00 2001 From: Michal Suchanek <hramrach@gmail.com> Date: Thu, 9 Jun 2016 15:08:42 +0000 Subject: staging: fbtft: do not allocate huge txbuf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit txbuflen can be set to arbitrary value by user and it is also set automagically to the maximum transfer size of the SPI master controller. Do not allocate the buffer when larger than vmem. When my SPI master controller reports maximum transfer size 16M the probe of fbtft fails. Signed-off-by: Michal Suchanek <hramrach@gmail.com> Acked-by: Noralf Trønnes <noralf@tronnes.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c index 0c1a77c..ce4fd37 100644 --- a/drivers/staging/fbtft/fbtft-core.c +++ b/drivers/staging/fbtft/fbtft-core.c @@ -820,6 +820,8 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display, /* Transmit buffer */ if (txbuflen == -1) txbuflen = vmem_size + 2; /* add in case startbyte is used */ + if (txbuflen >= vmem_size + 2) + txbuflen = 0; #ifdef __LITTLE_ENDIAN if ((!txbuflen) && (bpp > 8)) -- cgit v0.10.2 From 1c41494adf7aa6c9ca309fcdc558d7fb47903538 Mon Sep 17 00:00:00 2001 From: Ming Yang <minos.future@gmail.com> Date: Sun, 17 Jul 2016 19:13:18 -0700 Subject: Staging: fbtft: fixed unsigned type warnings Replace unsigned by unsigned int in fbtft driver. Issue found by checkpatch. Signed-off-by: Ming Yang <minos.future@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fbtft/fb_ili9320.c b/drivers/staging/fbtft/fb_ili9320.c index 6ff222d..278e4c7 100644 --- a/drivers/staging/fbtft/fb_ili9320.c +++ b/drivers/staging/fbtft/fb_ili9320.c @@ -29,7 +29,7 @@ #define DEFAULT_GAMMA "07 07 6 0 0 0 5 5 4 0\n" \ "07 08 4 7 5 1 2 0 7 7" -static unsigned read_devicecode(struct fbtft_par *par) +static unsigned int read_devicecode(struct fbtft_par *par) { int ret; u8 rxbuf[8] = {0, }; @@ -41,7 +41,7 @@ static unsigned read_devicecode(struct fbtft_par *par) static int init_display(struct fbtft_par *par) { - unsigned devcode; + unsigned int devcode; par->fbtftops.reset(par); diff --git a/drivers/staging/fbtft/fb_ili9325.c b/drivers/staging/fbtft/fb_ili9325.c index fdf98d3..c31e2e0 100644 --- a/drivers/staging/fbtft/fb_ili9325.c +++ b/drivers/staging/fbtft/fb_ili9325.c @@ -32,26 +32,26 @@ #define DEFAULT_GAMMA "0F 00 7 2 0 0 6 5 4 1\n" \ "04 16 2 7 6 3 2 1 7 7" -static unsigned bt = 6; /* VGL=Vci*4 , VGH=Vci*4 */ +static unsigned int bt = 6; /* VGL=Vci*4 , VGH=Vci*4 */ module_param(bt, uint, 0); MODULE_PARM_DESC(bt, "Sets the factor used in the step-up circuits"); -static unsigned vc = 0x03; /* Vci1=Vci*0.80 */ +static unsigned int vc = 0x03; /* Vci1=Vci*0.80 */ module_param(vc, uint, 0); MODULE_PARM_DESC(vc, "Sets the ratio factor of Vci to generate the reference voltages Vci1"); -static unsigned vrh = 0x0d; /* VREG1OUT=Vci*1.85 */ +static unsigned int vrh = 0x0d; /* VREG1OUT=Vci*1.85 */ module_param(vrh, uint, 0); MODULE_PARM_DESC(vrh, "Set the amplifying rate (1.6 ~ 1.9) of Vci applied to output the VREG1OUT"); -static unsigned vdv = 0x12; /* VCOMH amplitude=VREG1OUT*0.98 */ +static unsigned int vdv = 0x12; /* VCOMH amplitude=VREG1OUT*0.98 */ module_param(vdv, uint, 0); MODULE_PARM_DESC(vdv, "Select the factor of VREG1OUT to set the amplitude of Vcom"); -static unsigned vcm = 0x0a; /* VCOMH=VREG1OUT*0.735 */ +static unsigned int vcm = 0x0a; /* VCOMH=VREG1OUT*0.735 */ module_param(vcm, uint, 0); MODULE_PARM_DESC(vcm, "Set the internal VcomH voltage"); diff --git a/drivers/staging/fbtft/fb_pcd8544.c b/drivers/staging/fbtft/fb_pcd8544.c index a6b4332..a4710dc 100644 --- a/drivers/staging/fbtft/fb_pcd8544.c +++ b/drivers/staging/fbtft/fb_pcd8544.c @@ -32,11 +32,11 @@ #define TXBUFLEN (84 * 6) #define DEFAULT_GAMMA "40" /* gamma controls the contrast in this driver */ -static unsigned tc; +static unsigned int tc; module_param(tc, uint, 0); MODULE_PARM_DESC(tc, "TC[1:0] Temperature coefficient: 0-3 (default: 0)"); -static unsigned bs = 4; +static unsigned int bs = 4; module_param(bs, uint, 0); MODULE_PARM_DESC(bs, "BS[2:0] Bias voltage level: 0-7 (default: 4)"); diff --git a/drivers/staging/fbtft/fb_ssd1289.c b/drivers/staging/fbtft/fb_ssd1289.c index 1162c08..5d5f280 100644 --- a/drivers/staging/fbtft/fb_ssd1289.c +++ b/drivers/staging/fbtft/fb_ssd1289.c @@ -29,7 +29,7 @@ #define DEFAULT_GAMMA "02 03 2 5 7 7 4 2 4 2\n" \ "02 03 2 5 7 5 4 2 4 2" -static unsigned reg11 = 0x6040; +static unsigned int reg11 = 0x6040; module_param(reg11, uint, 0); MODULE_PARM_DESC(reg11, "Register 11h value"); diff --git a/drivers/staging/fbtft/fb_ssd1351.c b/drivers/staging/fbtft/fb_ssd1351.c index cef33e4..8267bbbc 100644 --- a/drivers/staging/fbtft/fb_ssd1351.c +++ b/drivers/staging/fbtft/fb_ssd1351.c @@ -66,7 +66,7 @@ static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) static int set_var(struct fbtft_par *par) { - unsigned remap; + unsigned int remap; if (par->fbtftops.init_display != init_display) { /* don't risk messing up register A0h */ diff --git a/drivers/staging/fbtft/fb_tls8204.c b/drivers/staging/fbtft/fb_tls8204.c index 2183f98..545f7cb 100644 --- a/drivers/staging/fbtft/fb_tls8204.c +++ b/drivers/staging/fbtft/fb_tls8204.c @@ -35,7 +35,7 @@ /* gamma is used to control contrast in this driver */ #define DEFAULT_GAMMA "40" -static unsigned bs = 4; +static unsigned int bs = 4; module_param(bs, uint, 0); MODULE_PARM_DESC(bs, "BS[2:0] Bias voltage level: 0-7 (default: 4)"); diff --git a/drivers/staging/fbtft/fb_uc1611.c b/drivers/staging/fbtft/fb_uc1611.c index e87401a..b33b73f 100644 --- a/drivers/staging/fbtft/fb_uc1611.c +++ b/drivers/staging/fbtft/fb_uc1611.c @@ -41,30 +41,30 @@ */ /* BR -> actual ratio: 0-3 -> 5, 10, 11, 13 */ -static unsigned ratio = 2; +static unsigned int ratio = 2; module_param(ratio, uint, 0); MODULE_PARM_DESC(ratio, "BR[1:0] Bias voltage ratio: 0-3 (default: 2)"); -static unsigned gain = 3; +static unsigned int gain = 3; module_param(gain, uint, 0); MODULE_PARM_DESC(gain, "GN[1:0] Bias voltage gain: 0-3 (default: 3)"); -static unsigned pot = 16; +static unsigned int pot = 16; module_param(pot, uint, 0); MODULE_PARM_DESC(pot, "PM[6:0] Bias voltage pot.: 0-63 (default: 16)"); /* TC -> % compensation per deg C: 0-3 -> -.05, -.10, -.015, -.20 */ -static unsigned temp; +static unsigned int temp; module_param(temp, uint, 0); MODULE_PARM_DESC(temp, "TC[1:0] Temperature compensation: 0-3 (default: 0)"); /* PC[1:0] -> LCD capacitance: 0-3 -> <20nF, 20-28 nF, 29-40 nF, 40-56 nF */ -static unsigned load = 1; +static unsigned int load = 1; module_param(load, uint, 0); MODULE_PARM_DESC(load, "PC[1:0] Panel Loading: 0-3 (default: 1)"); /* PC[3:2] -> V_LCD: 0, 1, 3 -> ext., int. with ratio = 5, int. standard */ -static unsigned pump = 3; +static unsigned int pump = 3; module_param(pump, uint, 0); MODULE_PARM_DESC(pump, "PC[3:2] Pump control: 0,1,3 (default: 3)"); diff --git a/drivers/staging/fbtft/fb_watterott.c b/drivers/staging/fbtft/fb_watterott.c index f8cb610..a52e28a 100644 --- a/drivers/staging/fbtft/fb_watterott.c +++ b/drivers/staging/fbtft/fb_watterott.c @@ -67,7 +67,7 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...) static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) { - unsigned start_line, end_line; + unsigned int start_line, end_line; u16 *vmem16 = (u16 *)(par->info->screen_buffer + offset); u16 *pos = par->txbuf.buf + 1; u16 *buf16 = par->txbuf.buf + 10; @@ -104,7 +104,7 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) static int write_vmem_8bit(struct fbtft_par *par, size_t offset, size_t len) { - unsigned start_line, end_line; + unsigned int start_line, end_line; u16 *vmem16 = (u16 *)(par->info->screen_buffer + offset); u16 *pos = par->txbuf.buf + 1; u8 *buf8 = par->txbuf.buf + 10; @@ -137,7 +137,7 @@ static int write_vmem_8bit(struct fbtft_par *par, size_t offset, size_t len) return 0; } -static unsigned firmware_version(struct fbtft_par *par) +static unsigned int firmware_version(struct fbtft_par *par) { u8 rxbuf[4] = {0, }; @@ -152,7 +152,7 @@ static unsigned firmware_version(struct fbtft_par *par) static int init_display(struct fbtft_par *par) { int ret; - unsigned version; + unsigned int version; u8 save_mode; /* enable SPI interface by having CS and MOSI low during reset */ diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c index ce4fd37..d9046162 100644 --- a/drivers/staging/fbtft/fbtft-core.c +++ b/drivers/staging/fbtft/fbtft-core.c @@ -341,8 +341,8 @@ static void fbtft_reset(struct fbtft_par *par) mdelay(120); } -static void fbtft_update_display(struct fbtft_par *par, unsigned start_line, - unsigned end_line) +static void fbtft_update_display(struct fbtft_par *par, unsigned int start_line, + unsigned int end_line) { size_t offset, len; ktime_t ts_start, ts_end; @@ -435,10 +435,10 @@ static void fbtft_mkdirty(struct fb_info *info, int y, int height) static void fbtft_deferred_io(struct fb_info *info, struct list_head *pagelist) { struct fbtft_par *par = info->par; - unsigned dirty_lines_start, dirty_lines_end; + unsigned int dirty_lines_start, dirty_lines_end; struct page *page; unsigned long index; - unsigned y_low = 0, y_high = 0; + unsigned int y_low = 0, y_high = 0; int count = 0; spin_lock(&par->dirty_lock); @@ -526,18 +526,18 @@ static ssize_t fbtft_fb_write(struct fb_info *info, const char __user *buf, } /* from pxafb.c */ -static unsigned int chan_to_field(unsigned chan, struct fb_bitfield *bf) +static unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf) { chan &= 0xffff; chan >>= 16 - bf->length; return chan << bf->offset; } -static int fbtft_fb_setcolreg(unsigned regno, unsigned red, unsigned green, - unsigned blue, unsigned transp, +static int fbtft_fb_setcolreg(unsigned int regno, unsigned int red, unsigned int green, + unsigned int blue, unsigned int transp, struct fb_info *info) { - unsigned val; + unsigned int val; int ret = 1; dev_dbg(info->dev, @@ -654,11 +654,11 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display, u8 *vmem = NULL; void *txbuf = NULL; void *buf = NULL; - unsigned width; - unsigned height; + unsigned int width; + unsigned int height; int txbuflen = display->txbuflen; - unsigned bpp = display->bpp; - unsigned fps = display->fps; + unsigned int bpp = display->bpp; + unsigned int fps = display->fps; int vmem_size, i; int *init_sequence = display->init_sequence; char *gamma = display->gamma; diff --git a/drivers/staging/fbtft/fbtft.h b/drivers/staging/fbtft/fbtft.h index d3bc394..89c4b5b 100644 --- a/drivers/staging/fbtft/fbtft.h +++ b/drivers/staging/fbtft/fbtft.h @@ -38,7 +38,7 @@ */ struct fbtft_gpio { char name[FBTFT_GPIO_NAME_SIZE]; - unsigned gpio; + unsigned int gpio; }; struct fbtft_par; @@ -79,7 +79,7 @@ struct fbtft_ops { void (*reset)(struct fbtft_par *par); void (*mkdirty)(struct fb_info *info, int from, int to); void (*update_display)(struct fbtft_par *par, - unsigned start_line, unsigned end_line); + unsigned int start_line, unsigned int end_line); int (*init_display)(struct fbtft_par *par); int (*blank)(struct fbtft_par *par, bool on); @@ -115,14 +115,14 @@ struct fbtft_ops { * This structure is not stored by FBTFT except for init_sequence. */ struct fbtft_display { - unsigned width; - unsigned height; - unsigned regwidth; - unsigned buswidth; - unsigned backlight; + unsigned int width; + unsigned int height; + unsigned int regwidth; + unsigned int buswidth; + unsigned int backlight; struct fbtft_ops fbtftops; - unsigned bpp; - unsigned fps; + unsigned int bpp; + unsigned int fps; int txbuflen; int *init_sequence; char *gamma; @@ -146,9 +146,9 @@ struct fbtft_display { struct fbtft_platform_data { struct fbtft_display display; const struct fbtft_gpio *gpios; - unsigned rotate; + unsigned int rotate; bool bgr; - unsigned fps; + unsigned int fps; int txbuflen; u8 startbyte; char *gamma; @@ -216,8 +216,8 @@ struct fbtft_par { u8 startbyte; struct fbtft_ops fbtftops; spinlock_t dirty_lock; - unsigned dirty_lines_start; - unsigned dirty_lines_end; + unsigned int dirty_lines_start; + unsigned int dirty_lines_end; struct { int reset; int dc; diff --git a/drivers/staging/fbtft/fbtft_device.c b/drivers/staging/fbtft/fbtft_device.c index e4a355a..4d1f1e9 100644 --- a/drivers/staging/fbtft/fbtft_device.c +++ b/drivers/staging/fbtft/fbtft_device.c @@ -32,20 +32,20 @@ static char *name; module_param(name, charp, 0); MODULE_PARM_DESC(name, "Devicename (required). name=list => list all supported devices."); -static unsigned rotate; +static unsigned int rotate; module_param(rotate, uint, 0); MODULE_PARM_DESC(rotate, "Angle to rotate display counter clockwise: 0, 90, 180, 270"); -static unsigned busnum; +static unsigned int busnum; module_param(busnum, uint, 0); MODULE_PARM_DESC(busnum, "SPI bus number (default=0)"); -static unsigned cs; +static unsigned int cs; module_param(cs, uint, 0); MODULE_PARM_DESC(cs, "SPI chip select (default=0)"); -static unsigned speed; +static unsigned int speed; module_param(speed, uint, 0); MODULE_PARM_DESC(speed, "SPI speed (override device default)"); @@ -58,7 +58,7 @@ module_param(gpios, charp, 0); MODULE_PARM_DESC(gpios, "List of gpios. Comma separated with the form: reset:23,dc:24 (when overriding the default, all gpios must be specified)"); -static unsigned fps; +static unsigned int fps; module_param(fps, uint, 0); MODULE_PARM_DESC(fps, "Frames per second (override driver default)"); @@ -76,7 +76,7 @@ module_param(bgr, int, 0); MODULE_PARM_DESC(bgr, "BGR bit (supported by some drivers)."); -static unsigned startbyte; +static unsigned int startbyte; module_param(startbyte, uint, 0); MODULE_PARM_DESC(startbyte, "Sets the Start byte used by some SPI displays."); @@ -84,15 +84,15 @@ static bool custom; module_param(custom, bool, 0); MODULE_PARM_DESC(custom, "Add a custom display device. Use speed= argument to make it a SPI device, else platform_device"); -static unsigned width; +static unsigned int width; module_param(width, uint, 0); MODULE_PARM_DESC(width, "Display width, used with the custom argument"); -static unsigned height; +static unsigned int height; module_param(height, uint, 0); MODULE_PARM_DESC(height, "Display height, used with the custom argument"); -static unsigned buswidth = 8; +static unsigned int buswidth = 8; module_param(buswidth, uint, 0); MODULE_PARM_DESC(buswidth, "Display bus width, used with the custom argument"); @@ -106,7 +106,7 @@ module_param(debug, ulong, 0); MODULE_PARM_DESC(debug, "level: 0-7 (the remaining 29 bits is for advanced usage)"); -static unsigned verbose = 3; +static unsigned int verbose = 3; module_param(verbose, uint, 0); MODULE_PARM_DESC(verbose, "0 silent, >0 show gpios, >1 show devices, >2 show devices before (default=3)"); @@ -1346,7 +1346,7 @@ static void pr_p_devices(void) } #ifdef MODULE -static void fbtft_device_spi_delete(struct spi_master *master, unsigned cs) +static void fbtft_device_spi_delete(struct spi_master *master, unsigned int cs) { struct device *dev; char str[32]; -- cgit v0.10.2 From ea40d674e5e6e008f7f157dc675004498dc8d143 Mon Sep 17 00:00:00 2001 From: Prit Raj <prit.adra@gmail.com> Date: Sun, 31 Jul 2016 08:35:16 +0530 Subject: staging: fbtft: This patch fixes the checkpatch.pl warning WARNING: Statements should start on a tabstop Signed-off-by: Prit Raj <prit.adra@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fbtft/fb_agm1264k-fl.c b/drivers/staging/fbtft/fb_agm1264k-fl.c index 82b46cd..7561385 100644 --- a/drivers/staging/fbtft/fb_agm1264k-fl.c +++ b/drivers/staging/fbtft/fb_agm1264k-fl.c @@ -350,8 +350,8 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) } } - /* 1 string = 2 pages */ - for (y = addr_win.ys_page; y <= addr_win.ye_page; ++y) { + /* 1 string = 2 pages */ + for (y = addr_win.ys_page; y <= addr_win.ye_page; ++y) { /* left half of display */ if (addr_win.xs < par->info->var.xres / 2) { construct_line_bitmap(par, buf, convert_buf, -- cgit v0.10.2 From f56edd42ee69ea73e1ca755614ed6c0e1a6ccef8 Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Tue, 16 Aug 2016 14:56:12 -0400 Subject: staging: dgnc: fix 'line over 80 characters' fix checkpatch.pl warning about 'line over 80 characters'. Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_driver.h b/drivers/staging/dgnc/dgnc_driver.h index 3092abe..88d2696 100644 --- a/drivers/staging/dgnc/dgnc_driver.h +++ b/drivers/staging/dgnc/dgnc_driver.h @@ -390,7 +390,7 @@ extern uint dgnc_major; /* Our driver/mgmt major */ extern int dgnc_poll_tick; /* Poll interval - 20 ms */ extern spinlock_t dgnc_global_lock; /* Driver global spinlock */ extern spinlock_t dgnc_poll_lock; /* Poll scheduling lock */ -extern uint dgnc_num_boards; /* Total number of boards */ +extern uint dgnc_num_boards; /* Total number of boards */ extern struct dgnc_board *dgnc_board[MAXBOARDS]; /* Array of board * structs */ -- cgit v0.10.2 From 7ed4eb5168325e52b5d6be277555b36877955c66 Mon Sep 17 00:00:00 2001 From: Lino Sanfilippo <LinoSanfilippo@gmx.de> Date: Fri, 15 Jul 2016 00:13:56 +0200 Subject: staging: slicoss: handle allocation failure in slic_init_adapter The memory allocation in slic_init_adapter() can fail. Return an error in this case and unwind properly. Also make sure that the allocated memory is properly freed in case of an error in the calling probe() function. By doing this also replace the alloc() followed by memset to zero the memory with a zalloc() version. Signed-off-by: Lino Sanfilippo <LinoSanfilippo@gmx.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index ac126d4..dae07410 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -2896,10 +2896,10 @@ static void slic_init_driver(void) } } -static void slic_init_adapter(struct net_device *netdev, - struct pci_dev *pcidev, - const struct pci_device_id *pci_tbl_entry, - void __iomem *memaddr, int chip_idx) +static int slic_init_adapter(struct net_device *netdev, + struct pci_dev *pcidev, + const struct pci_device_id *pci_tbl_entry, + void __iomem *memaddr, int chip_idx) { ushort index; struct slic_handle *pslic_handle; @@ -2938,13 +2938,13 @@ static void slic_init_adapter(struct net_device *netdev, pslic_handle->next = adapter->pfree_slic_handles; adapter->pfree_slic_handles = pslic_handle; } - adapter->pshmem = (struct slic_shmem *) - pci_alloc_consistent(adapter->pcidev, - sizeof(struct slic_shmem), - &adapter-> - phys_shmem); - if (adapter->pshmem) - memset(adapter->pshmem, 0, sizeof(struct slic_shmem)); + adapter->pshmem = pci_zalloc_consistent(adapter->pcidev, + sizeof(struct slic_shmem), + &adapter->phys_shmem); + if (!adapter->pshmem) + return -ENOMEM; + + return 0; } static const struct net_device_ops slic_netdev_ops = { @@ -3142,13 +3142,17 @@ static int slic_entry_probe(struct pci_dev *pcidev, slic_init_driver(); - slic_init_adapter(netdev, - pcidev, pci_tbl_entry, memmapped_ioaddr, cards_found); + err = slic_init_adapter(netdev, pcidev, pci_tbl_entry, memmapped_ioaddr, + cards_found); + if (err) { + dev_err(&pcidev->dev, "failed to init adapter: %i\n", err); + goto err_out_unmap; + } err = slic_card_locate(adapter); if (err) { dev_err(&pcidev->dev, "cannot locate card\n"); - goto err_out_unmap; + goto err_clean_init; } card = adapter->card; @@ -3160,7 +3164,7 @@ static int slic_entry_probe(struct pci_dev *pcidev, err = slic_card_init(card, adapter); if (err) - goto err_out_unmap; + goto err_clean_init; slic_adapter_set_hwaddr(adapter); @@ -3172,13 +3176,15 @@ static int slic_entry_probe(struct pci_dev *pcidev, err = register_netdev(netdev); if (err) { dev_err(&pcidev->dev, "Cannot register net device, aborting.\n"); - goto err_out_unmap; + goto err_clean_init; } cards_found++; return 0; +err_clean_init: + slic_init_cleanup(adapter); err_out_unmap: iounmap(memmapped_ioaddr); err_out_free_netdev: -- cgit v0.10.2 From da169754096c48281c75cbc5fd21e62e2cbb780b Mon Sep 17 00:00:00 2001 From: Lino Sanfilippo <LinoSanfilippo@gmx.de> Date: Fri, 22 Jul 2016 23:09:12 +0200 Subject: staging: slicoss: notifiy network stack about change in link state Notify the network stack about link states via netif_carrier_[off|on](). Also set the link state off initially and when the interface is brought down. Signed-off-by: Lino Sanfilippo <LinoSanfilippo@gmx.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index dae07410..a9323a9 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -1016,6 +1016,7 @@ static void slic_link_upr_complete(struct adapter *adapter, u32 isr) /* link has gone from up to down */ if (linkup == LINK_DOWN) { adapter->linkstate = LINK_DOWN; + netif_carrier_off(adapter->netdev); return; } @@ -1028,6 +1029,7 @@ static void slic_link_upr_complete(struct adapter *adapter, u32 isr) slic_config_set(adapter, true); adapter->linkstate = LINK_UP; netif_start_queue(adapter->netdev); + netif_carrier_on(adapter->netdev); } } @@ -2418,6 +2420,7 @@ static int slic_entry_open(struct net_device *dev) int status; netif_stop_queue(adapter->netdev); + netif_carrier_off(dev); spin_lock_irqsave(&slic_global.driver_lock, flags); if (!adapter->activated) { @@ -2530,6 +2533,9 @@ static int slic_entry_halt(struct net_device *dev) #endif spin_unlock_irqrestore(&slic_global.driver_lock, flags); + + netif_carrier_off(dev); + return 0; } @@ -3172,6 +3178,8 @@ static int slic_entry_probe(struct pci_dev *pcidev, netdev->irq = adapter->irq; netdev->netdev_ops = &slic_netdev_ops; + netif_carrier_off(netdev); + strcpy(netdev->name, "eth%d"); err = register_netdev(netdev); if (err) { -- cgit v0.10.2 From 6d5f2ea7418d054721f8331ec2c2c0825e0ff52e Mon Sep 17 00:00:00 2001 From: Lino Sanfilippo <lsanfil@marvell.com> Date: Fri, 22 Jul 2016 23:09:13 +0200 Subject: staging: slicoss: ensure mapping of io-memory is uncached Writes to registers should be done uncached for various reasons. Ensure this by replacing ioremap() with ioremap_nocache(). Signed-off-by: Lino Sanfilippo <LinoSanfilippo@gmx.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index a9323a9..4dba080 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -3136,7 +3136,7 @@ static int slic_entry_probe(struct pci_dev *pcidev, mmio_start = pci_resource_start(pcidev, 0); mmio_len = pci_resource_len(pcidev, 0); - memmapped_ioaddr = ioremap(mmio_start, mmio_len); + memmapped_ioaddr = ioremap_nocache(mmio_start, mmio_len); if (!memmapped_ioaddr) { dev_err(&pcidev->dev, "cannot remap MMIO region %lx @ %lx\n", mmio_len, mmio_start); -- cgit v0.10.2 From a5e32e74076b8dc0bd05ba011b9ba4903001f89d Mon Sep 17 00:00:00 2001 From: Lino Sanfilippo <LinoSanfilippo@gmx.de> Date: Fri, 22 Jul 2016 23:09:14 +0200 Subject: staging: slicoss: start tx queue when interface is brought up There is no reason to delay tx queue activation until a link is detected. So start the queue when the interface is brought up and stop it when the interface is brought down. Signed-off-by: Lino Sanfilippo <LinoSanfilippo@gmx.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index 4dba080..577c2d2 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -1028,7 +1028,6 @@ static void slic_link_upr_complete(struct adapter *adapter, u32 isr) /* setup the mac */ slic_config_set(adapter, true); adapter->linkstate = LINK_UP; - netif_start_queue(adapter->netdev); netif_carrier_on(adapter->netdev); } } @@ -2419,7 +2418,6 @@ static int slic_entry_open(struct net_device *dev) unsigned long flags; int status; - netif_stop_queue(adapter->netdev); netif_carrier_off(dev); spin_lock_irqsave(&slic_global.driver_lock, flags); @@ -2443,6 +2441,9 @@ static int slic_entry_open(struct net_device *dev) spin_unlock: spin_unlock_irqrestore(&slic_global.driver_lock, flags); + + netif_start_queue(adapter->netdev); + return status; } -- cgit v0.10.2 From b200da6744addf5c1ed7dbb8a70cfff8c4e2368e Mon Sep 17 00:00:00 2001 From: Lino Sanfilippo <LinoSanfilippo@gmx.de> Date: Fri, 22 Jul 2016 23:09:15 +0200 Subject: staging: slicoss: introduce register accessors that use register offsets Introduce accessor functions that read and write registers by using a register offset. This is in preparation to replace the register addressing by means of the slic_regs struct with an addressing by means of offsets. Signed-off-by: Lino Sanfilippo <LinoSanfilippo@gmx.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/slicoss/slic.h b/drivers/staging/slicoss/slic.h index cc0afee..08d9f5b 100644 --- a/drivers/staging/slicoss/slic.h +++ b/drivers/staging/slicoss/slic.h @@ -418,6 +418,7 @@ struct adapter { dma_addr_t phys_shmem; u32 isrcopy; __iomem struct slic_regs *slic_regs; + void __iomem *regs; unsigned char state; unsigned char linkstate; unsigned char linkspeed; @@ -487,6 +488,29 @@ struct adapter { struct slicnet_stats slic_stats; }; +static inline u32 slic_read32(struct adapter *adapter, unsigned int reg) +{ + return ioread32(adapter->regs + reg); +} + +static inline void slic_write32(struct adapter *adapter, unsigned int reg, + u32 val) +{ + iowrite32(val, adapter->regs + reg); +} + +static inline void slic_write64(struct adapter *adapter, unsigned int reg, + u32 val, u32 hiaddr) +{ + unsigned long flags; + + spin_lock_irqsave(&adapter->bit64reglock, flags); + slic_write32(adapter, SLIC_REG_ADDR_UPPER, hiaddr); + slic_write32(adapter, reg, val); + mmiowb(); + spin_unlock_irqrestore(&adapter->bit64reglock, flags); +} + #define UPDATE_STATS(largestat, newstat, oldstat) \ { \ if ((newstat) < (oldstat)) \ diff --git a/drivers/staging/slicoss/slichw.h b/drivers/staging/slicoss/slichw.h index 9723b4a..f06450e 100644 --- a/drivers/staging/slicoss/slichw.h +++ b/drivers/staging/slicoss/slichw.h @@ -289,6 +289,119 @@ struct slic_rspbuf { u32 pad2[4]; }; +/* Reset Register */ +#define SLIC_REG_RESET 0x0000 +/* Interrupt Control Register */ +#define SLIC_REG_ICR 0x0008 +/* Interrupt status pointer */ +#define SLIC_REG_ISP 0x0010 +/* Interrupt status */ +#define SLIC_REG_ISR 0x0018 +/* + * Header buffer address reg + * 31-8 - phy addr of set of contiguous hdr buffers + * 7-0 - number of buffers passed + * Buffers are 256 bytes long on 256-byte boundaries. + */ +#define SLIC_REG_HBAR 0x0020 +/* + * Data buffer handle & address reg + * 4 sets of registers; Buffers are 2K bytes long 2 per 4K page. + */ +#define SLIC_REG_DBAR 0x0028 +/* + * Xmt Cmd buf addr regs. + * 1 per XMT interface + * 31-5 - phy addr of host command buffer + * 4-0 - length of cmd in multiples of 32 bytes + * Buffers are 32 bytes up to 512 bytes long + */ +#define SLIC_REG_CBAR 0x0030 +/* Write control store */ +#define SLIC_REG_WCS 0x0034 +/* + * Response buffer address reg. + * 31-8 - phy addr of set of contiguous response buffers + * 7-0 - number of buffers passed + * Buffers are 32 bytes long on 32-byte boundaries. + */ +#define SLIC_REG_RBAR 0x0038 +/* Read statistics (UPR) */ +#define SLIC_REG_RSTAT 0x0040 +/* Read link status */ +#define SLIC_REG_LSTAT 0x0048 +/* Write Mac Config */ +#define SLIC_REG_WMCFG 0x0050 +/* Write phy register */ +#define SLIC_REG_WPHY 0x0058 +/* Rcv Cmd buf addr reg */ +#define SLIC_REG_RCBAR 0x0060 +/* Read SLIC Config*/ +#define SLIC_REG_RCONFIG 0x0068 +/* Interrupt aggregation time */ +#define SLIC_REG_INTAGG 0x0070 +/* Write XMIT config reg */ +#define SLIC_REG_WXCFG 0x0078 +/* Write RCV config reg */ +#define SLIC_REG_WRCFG 0x0080 +/* Write rcv addr a low */ +#define SLIC_REG_WRADDRAL 0x0088 +/* Write rcv addr a high */ +#define SLIC_REG_WRADDRAH 0x0090 +/* Write rcv addr b low */ +#define SLIC_REG_WRADDRBL 0x0098 +/* Write rcv addr b high */ +#define SLIC_REG_WRADDRBH 0x00a0 +/* Low bits of mcast mask */ +#define SLIC_REG_MCASTLOW 0x00a8 +/* High bits of mcast mask */ +#define SLIC_REG_MCASTHIGH 0x00b0 +/* Ping the card */ +#define SLIC_REG_PING 0x00b8 +/* Dump command */ +#define SLIC_REG_DUMP_CMD 0x00c0 +/* Dump data pointer */ +#define SLIC_REG_DUMP_DATA 0x00c8 +/* Read card's pci_status register */ +#define SLIC_REG_PCISTATUS 0x00d0 +/* Write hostid field */ +#define SLIC_REG_WRHOSTID 0x00d8 +/* Put card in a low power state */ +#define SLIC_REG_LOW_POWER 0x00e0 +/* Force slic into quiescent state before soft reset */ +#define SLIC_REG_QUIESCE 0x00e8 +/* Reset interface queues */ +#define SLIC_REG_RESET_IFACE 0x00f0 +/* + * Register is only written when it has changed. + * Bits 63-32 for host i/f addrs. + */ +#define SLIC_REG_ADDR_UPPER 0x00f8 +/* 64 bit Header buffer address reg */ +#define SLIC_REG_HBAR64 0x0100 +/* 64 bit Data buffer handle & address reg */ +#define SLIC_REG_DBAR64 0x0108 +/* 64 bit Xmt Cmd buf addr regs. */ +#define SLIC_REG_CBAR64 0x0110 +/* 64 bit Response buffer address reg.*/ +#define SLIC_REG_RBAR64 0x0118 +/* 64 bit Rcv Cmd buf addr reg*/ +#define SLIC_REG_RCBAR64 0x0120 +/* Read statistics (64 bit UPR) */ +#define SLIC_REG_RSTAT64 0x0128 +/* Download Gigabit RCV sequencer ucode */ +#define SLIC_REG_RCV_WCS 0x0130 +/* Write VlanId field */ +#define SLIC_REG_WRVLANID 0x0138 +/* Read Transformer info */ +#define SLIC_REG_READ_XF_INFO 0x0140 +/* Write Transformer info */ +#define SLIC_REG_WRITE_XF_INFO 0x0148 +/* Write card ticks per second */ +#define SLIC_REG_TICKS_PER_SEC 0x0170 + +#define SLIC_REG_HOSTID 0x1554 + struct slic_regs { u32 slic_reset; /* Reset Register */ u32 pad0; diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index 577c2d2..edae0f7 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -2920,6 +2920,7 @@ static int slic_init_adapter(struct net_device *netdev, adapter->slotnumber = ((pcidev->devfn >> 3) & 0x1F); adapter->functionnumber = (pcidev->devfn & 0x7); adapter->slic_regs = memaddr; + adapter->regs = memaddr; adapter->irq = pcidev->irq; adapter->chipid = chip_idx; adapter->port = 0; -- cgit v0.10.2 From bc894318e8ea9fbfd2cffe3f003d6e3c50112f3d Mon Sep 17 00:00:00 2001 From: Lino Sanfilippo <LinoSanfilippo@gmx.de> Date: Fri, 22 Jul 2016 23:09:16 +0200 Subject: staging: slicoss: avoid PCI write posting Introduce the function slic_flush_write() which reads from the HOSTID register and can be used to avoid PCI write posting. Use the function at several critical places in the code. Signed-off-by: Lino Sanfilippo <LinoSanfilippo@gmx.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/slicoss/slic.h b/drivers/staging/slicoss/slic.h index 08d9f5b..230d30b 100644 --- a/drivers/staging/slicoss/slic.h +++ b/drivers/staging/slicoss/slic.h @@ -511,6 +511,11 @@ static inline void slic_write64(struct adapter *adapter, unsigned int reg, spin_unlock_irqrestore(&adapter->bit64reglock, flags); } +static inline void slic_flush_write(struct adapter *adapter) +{ + ioread32(adapter->regs + SLIC_REG_HOSTID); +} + #define UPDATE_STATS(largestat, newstat, oldstat) \ { \ if ((newstat) < (oldstat)) \ diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index edae0f7..0c2f86a0 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -268,6 +268,7 @@ static void slic_link_config(struct adapter *adapter, */ phy_config = (MIICR_REG_PCR | PCR_POWERDOWN); slic_reg32_write(wphy, phy_config, FLUSH); + slic_flush_write(adapter); /* * wait, Marvell says 1 sec, * try to get away with 10 ms @@ -360,7 +361,7 @@ static void slic_link_config(struct adapter *adapter, /* power down phy to break link (this may not work) */ phy_config = (MIICR_REG_PCR | (PCR_POWERDOWN | speed | duplex)); slic_reg32_write(wphy, phy_config, FLUSH); - + slic_flush_write(adapter); /* wait, Marvell says 1 sec, try to get away with 10 ms */ mdelay(10); @@ -448,6 +449,8 @@ static int slic_card_download_gbrcv(struct adapter *adapter) /* download finished */ release_firmware(fw); slic_reg32_write(&slic_regs->slic_rcv_wcs, SLIC_RCVWCS_FINISH, FLUSH); + slic_flush_write(adapter); + return 0; } @@ -551,6 +554,7 @@ static int slic_card_download(struct adapter *adapter) /* Everything OK, kick off the card */ mdelay(10); slic_reg32_write(&slic_regs->slic_wcs, SLIC_WCS_START, FLUSH); + slic_flush_write(adapter); /* * stall for 20 ms, long enough for ucode to init card @@ -591,11 +595,13 @@ static void slic_soft_reset(struct adapter *adapter) { if (adapter->card->state == CARD_UP) { slic_reg32_write(&adapter->slic_regs->slic_quiesce, 0, FLUSH); + slic_flush_write(adapter); mdelay(1); } slic_reg32_write(&adapter->slic_regs->slic_reset, SLIC_RESET_MAGIC, FLUSH); + slic_flush_write(adapter); mdelay(1); } @@ -934,6 +940,7 @@ static void slic_upr_start(struct adapter *adapter) slic_reg32_write(&slic_regs->slic_ping, 1, FLUSH); break; } + slic_flush_write(adapter); } static int slic_upr_request(struct adapter *adapter, @@ -2153,6 +2160,7 @@ static irqreturn_t slic_interrupt(int irq, void *dev_id) if ((adapter->pshmem) && (adapter->pshmem->isr)) { slic_reg32_write(&adapter->slic_regs->slic_icr, ICR_INT_MASK, FLUSH); + slic_flush_write(adapter); isr = adapter->isrcopy = adapter->pshmem->isr; adapter->pshmem->isr = 0; adapter->num_isrs++; @@ -2337,6 +2345,7 @@ static int slic_if_init(struct adapter *adapter, unsigned long *flags) } slic_reg32_write(&slic_regs->slic_icr, ICR_INT_OFF, FLUSH); + slic_flush_write(adapter); mdelay(1); if (!adapter->isp_initialized) { @@ -2390,11 +2399,13 @@ static int slic_if_init(struct adapter *adapter, unsigned long *flags) slic_reg32_write(&slic_regs->slic_icr, ICR_INT_ON, FLUSH); slic_link_config(adapter, LINK_AUTOSPEED, LINK_AUTOD); + slic_flush_write(adapter); rc = slic_link_event_handler(adapter); if (rc) { /* disable interrupts then clear pending events */ slic_reg32_write(&slic_regs->slic_icr, ICR_INT_OFF, FLUSH); slic_reg32_write(&slic_regs->slic_isr, 0, FLUSH); + slic_flush_write(adapter); if (adapter->pingtimerset) { del_timer(&adapter->pingtimer); adapter->pingtimerset = 0; @@ -2523,6 +2534,7 @@ static int slic_entry_halt(struct net_device *dev) #ifdef AUTOMATIC_RESET slic_reg32_write(&slic_regs->slic_reset_iface, 0, FLUSH); #endif + slic_flush_write(adapter); /* * Reset the adapter's cmd queues */ @@ -2714,6 +2726,7 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter) memset(peeprom, 0, sizeof(struct slic_eeprom)); slic_reg32_write(&slic_regs->slic_icr, ICR_INT_OFF, FLUSH); + slic_flush_write(adapter); mdelay(1); pshmem = (struct slic_shmem *)(unsigned long) adapter->phys_shmem; @@ -2742,6 +2755,7 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter) 0, FLUSH); slic_reg32_write(&slic_regs->slic_isr, 0, FLUSH); + slic_flush_write(adapter); slic_upr_request_complete(adapter, 0); break; @@ -2750,6 +2764,7 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter) adapter->pshmem->isr = 0; slic_reg32_write(&slic_regs->slic_isr, 0, FLUSH); + slic_flush_write(adapter); } else { mdelay(1); i++; @@ -2760,6 +2775,7 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter) &slic_regs->slic_isp, 0, &slic_regs->slic_addr_upper, 0, FLUSH); + slic_flush_write(adapter); status = -EINVAL; goto card_init_err; } @@ -2840,6 +2856,7 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter) slic_reg64_write(adapter, &slic_regs->slic_isp, 0, &slic_regs->slic_addr_upper, 0, FLUSH); + slic_flush_write(adapter); dev_err(&adapter->pcidev->dev, "EEPROM invalid.\n"); return -EINVAL; } -- cgit v0.10.2 From c6d6a9a076968633313f61e8067edbe37290c270 Mon Sep 17 00:00:00 2001 From: Lino Sanfilippo <LinoSanfilippo@gmx.de> Date: Fri, 22 Jul 2016 23:09:17 +0200 Subject: staging: slicoss: dont use a structure but offsets for register accesses Use the new register accessors that use offsets instead of the slic_regs structure to read/write registers. Since not longer needed remove the structure completley. Signed-off-by: Lino Sanfilippo <LinoSanfilippo@gmx.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/slicoss/slic.h b/drivers/staging/slicoss/slic.h index 230d30b..3bba82a 100644 --- a/drivers/staging/slicoss/slic.h +++ b/drivers/staging/slicoss/slic.h @@ -417,7 +417,6 @@ struct adapter { struct slic_shmem *pshmem; dma_addr_t phys_shmem; u32 isrcopy; - __iomem struct slic_regs *slic_regs; void __iomem *regs; unsigned char state; unsigned char linkstate; diff --git a/drivers/staging/slicoss/slichw.h b/drivers/staging/slicoss/slichw.h index f06450e..ae04bf6 100644 --- a/drivers/staging/slicoss/slichw.h +++ b/drivers/staging/slicoss/slichw.h @@ -402,225 +402,6 @@ struct slic_rspbuf { #define SLIC_REG_HOSTID 0x1554 -struct slic_regs { - u32 slic_reset; /* Reset Register */ - u32 pad0; - - u32 slic_icr; /* Interrupt Control Register */ - u32 pad2; -#define SLIC_ICR 0x0008 - - u32 slic_isp; /* Interrupt status pointer */ - u32 pad1; -#define SLIC_ISP 0x0010 - - u32 slic_isr; /* Interrupt status */ - u32 pad3; -#define SLIC_ISR 0x0018 - - u32 slic_hbar; /* Header buffer address reg */ - u32 pad4; - /* - * 31-8 - phy addr of set of contiguous hdr buffers - * 7-0 - number of buffers passed - * Buffers are 256 bytes long on 256-byte boundaries. - */ -#define SLIC_HBAR 0x0020 -#define SLIC_HBAR_CNT_MSK 0x000000FF - - u32 slic_dbar; /* Data buffer handle & address reg */ - u32 pad5; - - /* 4 sets of registers; Buffers are 2K bytes long 2 per 4K page. */ -#define SLIC_DBAR 0x0028 -#define SLIC_DBAR_SIZE 2048 - - u32 slic_cbar; /* Xmt Cmd buf addr regs.*/ - /* - * 1 per XMT interface - * 31-5 - phy addr of host command buffer - * 4-0 - length of cmd in multiples of 32 bytes - * Buffers are 32 bytes up to 512 bytes long - */ -#define SLIC_CBAR 0x0030 -#define SLIC_CBAR_LEN_MSK 0x0000001F -#define SLIC_CBAR_ALIGN 0x00000020 - - u32 slic_wcs; /* write control store*/ -#define SLIC_WCS 0x0034 -#define SLIC_WCS_START 0x80000000 /*Start the SLIC (Jump to WCS)*/ -#define SLIC_WCS_COMPARE 0x40000000 /* Compare with value in WCS*/ - - u32 slic_rbar; /* Response buffer address reg.*/ - u32 pad7; - /* - * 31-8 - phy addr of set of contiguous response buffers - * 7-0 - number of buffers passed - * Buffers are 32 bytes long on 32-byte boundaries. - */ -#define SLIC_RBAR 0x0038 -#define SLIC_RBAR_CNT_MSK 0x000000FF -#define SLIC_RBAR_SIZE 32 - - u32 slic_stats; /* read statistics (UPR) */ - u32 pad8; -#define SLIC_RSTAT 0x0040 - - u32 slic_rlsr; /* read link status */ - u32 pad9; -#define SLIC_LSTAT 0x0048 - - u32 slic_wmcfg; /* Write Mac Config */ - u32 pad10; -#define SLIC_WMCFG 0x0050 - - u32 slic_wphy; /* Write phy register */ - u32 pad11; -#define SLIC_WPHY 0x0058 - - u32 slic_rcbar; /* Rcv Cmd buf addr reg */ - u32 pad12; -#define SLIC_RCBAR 0x0060 - - u32 slic_rconfig; /* Read SLIC Config*/ - u32 pad13; -#define SLIC_RCONFIG 0x0068 - - u32 slic_intagg; /* Interrupt aggregation time */ - u32 pad14; -#define SLIC_INTAGG 0x0070 - - u32 slic_wxcfg; /* Write XMIT config reg*/ - u32 pad16; -#define SLIC_WXCFG 0x0078 - - u32 slic_wrcfg; /* Write RCV config reg*/ - u32 pad17; -#define SLIC_WRCFG 0x0080 - - u32 slic_wraddral; /* Write rcv addr a low*/ - u32 pad18; -#define SLIC_WRADDRAL 0x0088 - - u32 slic_wraddrah; /* Write rcv addr a high*/ - u32 pad19; -#define SLIC_WRADDRAH 0x0090 - - u32 slic_wraddrbl; /* Write rcv addr b low*/ - u32 pad20; -#define SLIC_WRADDRBL 0x0098 - - u32 slic_wraddrbh; /* Write rcv addr b high*/ - u32 pad21; -#define SLIC_WRADDRBH 0x00a0 - - u32 slic_mcastlow; /* Low bits of mcast mask*/ - u32 pad22; -#define SLIC_MCASTLOW 0x00a8 - - u32 slic_mcasthigh; /* High bits of mcast mask*/ - u32 pad23; -#define SLIC_MCASTHIGH 0x00b0 - - u32 slic_ping; /* Ping the card*/ - u32 pad24; -#define SLIC_PING 0x00b8 - - u32 slic_dump_cmd; /* Dump command */ - u32 pad25; -#define SLIC_DUMP_CMD 0x00c0 - - u32 slic_dump_data; /* Dump data pointer */ - u32 pad26; -#define SLIC_DUMP_DATA 0x00c8 - - u32 slic_pcistatus; /* Read card's pci_status register */ - u32 pad27; -#define SLIC_PCISTATUS 0x00d0 - - u32 slic_wrhostid; /* Write hostid field */ - u32 pad28; -#define SLIC_WRHOSTID 0x00d8 -#define SLIC_RDHOSTID_1GB 0x1554 -#define SLIC_RDHOSTID_2GB 0x1554 - - u32 slic_low_power; /* Put card in a low power state */ - u32 pad29; -#define SLIC_LOW_POWER 0x00e0 - - u32 slic_quiesce; /* force slic into quiescent state - * before soft reset - */ - u32 pad30; -#define SLIC_QUIESCE 0x00e8 - - u32 slic_reset_iface;/* reset interface queues */ - u32 pad31; -#define SLIC_RESET_IFACE 0x00f0 - - u32 slic_addr_upper;/* Bits 63-32 for host i/f addrs */ - u32 pad32; -#define SLIC_ADDR_UPPER 0x00f8 /*Register is only written when it has changed*/ - - u32 slic_hbar64; /* 64 bit Header buffer address reg */ - u32 pad33; -#define SLIC_HBAR64 0x0100 - - u32 slic_dbar64; /* 64 bit Data buffer handle & address reg */ - u32 pad34; -#define SLIC_DBAR64 0x0108 - - u32 slic_cbar64; /* 64 bit Xmt Cmd buf addr regs. */ - u32 pad35; -#define SLIC_CBAR64 0x0110 - - u32 slic_rbar64; /* 64 bit Response buffer address reg.*/ - u32 pad36; -#define SLIC_RBAR64 0x0118 - - u32 slic_rcbar64; /* 64 bit Rcv Cmd buf addr reg*/ - u32 pad37; -#define SLIC_RCBAR64 0x0120 - - u32 slic_stats64; /* read statistics (64 bit UPR) */ - u32 pad38; -#define SLIC_RSTAT64 0x0128 - - u32 slic_rcv_wcs; /*Download Gigabit RCV sequencer ucode*/ - u32 pad39; -#define SLIC_RCV_WCS 0x0130 -#define SLIC_RCVWCS_BEGIN 0x40000000 -#define SLIC_RCVWCS_FINISH 0x80000000 - - u32 slic_wrvlanid; /* Write VlanId field */ - u32 pad40; -#define SLIC_WRVLANID 0x0138 - - u32 slic_read_xf_info; /* Read Transformer info */ - u32 pad41; -#define SLIC_READ_XF_INFO 0x0140 - - u32 slic_write_xf_info; /* Write Transformer info */ - u32 pad42; -#define SLIC_WRITE_XF_INFO 0x0148 - - u32 RSVD1; /* TOE Only */ - u32 pad43; - - u32 RSVD2; /* TOE Only */ - u32 pad44; - - u32 RSVD3; /* TOE Only */ - u32 pad45; - - u32 RSVD4; /* TOE Only */ - u32 pad46; - - u32 slic_ticks_per_sec; /* Write card ticks per second */ - u32 pad47; -#define SLIC_TICKS_PER_SEC 0x0170 -}; - enum UPR_REQUEST { SLIC_UPR_STATS, SLIC_UPR_RLSR, diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index 0c2f86a0..8e978e7 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -128,27 +128,6 @@ static struct ethtool_ops slic_ethtool_ops; MODULE_DEVICE_TABLE(pci, slic_pci_tbl); -static inline void slic_reg32_write(void __iomem *reg, u32 value, bool flush) -{ - writel(value, reg); - if (flush) - mb(); -} - -static inline void slic_reg64_write(struct adapter *adapter, void __iomem *reg, - u32 value, void __iomem *regh, u32 paddrh, - bool flush) -{ - unsigned long flags; - - spin_lock_irqsave(&adapter->bit64reglock, flags); - writel(paddrh, regh); - writel(value, reg); - if (flush) - mb(); - spin_unlock_irqrestore(&adapter->bit64reglock, flags); -} - static void slic_mcast_set_bit(struct adapter *adapter, char *address) { unsigned char crcpoly; @@ -172,8 +151,6 @@ static void slic_mcast_set_bit(struct adapter *adapter, char *address) static void slic_mcast_set_mask(struct adapter *adapter) { - __iomem struct slic_regs *slic_regs = adapter->slic_regs; - if (adapter->macopts & (MAC_ALLMCAST | MAC_PROMISC)) { /* * Turn on all multicast addresses. We have to do this for @@ -181,18 +158,17 @@ static void slic_mcast_set_mask(struct adapter *adapter) * Microcode from having to keep state about the MAC * configuration. */ - slic_reg32_write(&slic_regs->slic_mcastlow, 0xFFFFFFFF, FLUSH); - slic_reg32_write(&slic_regs->slic_mcasthigh, 0xFFFFFFFF, - FLUSH); + slic_write32(adapter, SLIC_REG_MCASTLOW, 0xFFFFFFFF); + slic_write32(adapter, SLIC_REG_MCASTHIGH, 0xFFFFFFFF); } else { /* * Commit our multicast mast to the SLIC by writing to the * multicast address mask registers */ - slic_reg32_write(&slic_regs->slic_mcastlow, - (u32)(adapter->mcastmask & 0xFFFFFFFF), FLUSH); - slic_reg32_write(&slic_regs->slic_mcasthigh, - (u32)((adapter->mcastmask >> 32) & 0xFFFFFFFF), FLUSH); + slic_write32(adapter, SLIC_REG_MCASTLOW, + (u32)(adapter->mcastmask & 0xFFFFFFFF)); + slic_write32(adapter, SLIC_REG_MCASTHIGH, + (u32)((adapter->mcastmask >> 32) & 0xFFFFFFFF)); } } @@ -208,13 +184,6 @@ static void slic_timer_ping(ulong dev) add_timer(&adapter->pingtimer); } -static void slic_unmap_mmio_space(struct adapter *adapter) -{ - if (adapter->slic_regs) - iounmap(adapter->slic_regs); - adapter->slic_regs = NULL; -} - /* * slic_link_config * @@ -224,7 +193,6 @@ static void slic_unmap_mmio_space(struct adapter *adapter) static void slic_link_config(struct adapter *adapter, u32 linkspeed, u32 linkduplex) { - u32 __iomem *wphy; u32 speed; u32 duplex; u32 phy_config; @@ -239,8 +207,6 @@ static void slic_link_config(struct adapter *adapter, if (linkduplex > LINK_AUTOD) linkduplex = LINK_AUTOD; - wphy = &adapter->slic_regs->slic_wphy; - if ((linkspeed == LINK_AUTOSPEED) || (linkspeed == LINK_1000MB)) { if (adapter->flags & ADAPT_FLAGS_FIBERMEDIA) { /* @@ -252,7 +218,7 @@ static void slic_link_config(struct adapter *adapter, phy_advreg = (MIICR_REG_4 | (PAR_ADV1000XFD)); /* enable PAUSE frames */ phy_advreg |= PAR_ASYMPAUSE_FIBER; - slic_reg32_write(wphy, phy_advreg, FLUSH); + slic_write32(adapter, SLIC_REG_WPHY, phy_advreg); if (linkspeed == LINK_AUTOSPEED) { /* reset phy, enable auto-neg */ @@ -260,14 +226,16 @@ static void slic_link_config(struct adapter *adapter, (MIICR_REG_PCR | (PCR_RESET | PCR_AUTONEG | PCR_AUTONEG_RST)); - slic_reg32_write(wphy, phy_config, FLUSH); + slic_write32(adapter, SLIC_REG_WPHY, + phy_config); } else { /* forced 1000 Mb FD*/ /* * power down phy to break link * this may not work) */ phy_config = (MIICR_REG_PCR | PCR_POWERDOWN); - slic_reg32_write(wphy, phy_config, FLUSH); + slic_write32(adapter, SLIC_REG_WPHY, + phy_config); slic_flush_write(adapter); /* * wait, Marvell says 1 sec, @@ -283,7 +251,8 @@ static void slic_link_config(struct adapter *adapter, (MIICR_REG_PCR | (PCR_RESET | PCR_SPEED_1000 | PCR_DUPLEX_FULL)); - slic_reg32_write(wphy, phy_config, FLUSH); + slic_write32(adapter, SLIC_REG_WPHY, + phy_config); } } else { /* copper gigabit */ @@ -310,10 +279,10 @@ static void slic_link_config(struct adapter *adapter, phy_advreg |= PAR_ASYMPAUSE; /* required by the Cicada PHY */ phy_advreg |= PAR_802_3; - slic_reg32_write(wphy, phy_advreg, FLUSH); + slic_write32(adapter, SLIC_REG_WPHY, phy_advreg); /* advertise FD only @1000 Mb */ phy_gctlreg = (MIICR_REG_9 | (PGC_ADV1000FD)); - slic_reg32_write(wphy, phy_gctlreg, FLUSH); + slic_write32(adapter, SLIC_REG_WPHY, phy_gctlreg); if (adapter->subsysid != SLIC_1GB_CICADA_SUBSYS_ID) { /* @@ -322,20 +291,23 @@ static void slic_link_config(struct adapter *adapter, */ phy_config = (MIICR_REG_16 | (MRV_REG16_XOVERON)); - slic_reg32_write(wphy, phy_config, FLUSH); + slic_write32(adapter, SLIC_REG_WPHY, + phy_config); /* reset phy, enable auto-neg */ phy_config = (MIICR_REG_PCR | (PCR_RESET | PCR_AUTONEG | PCR_AUTONEG_RST)); - slic_reg32_write(wphy, phy_config, FLUSH); + slic_write32(adapter, SLIC_REG_WPHY, + phy_config); } else { /* it's a Cicada PHY */ /* enable and restart auto-neg (don't reset) */ phy_config = (MIICR_REG_PCR | (PCR_AUTONEG | PCR_AUTONEG_RST)); - slic_reg32_write(wphy, phy_config, FLUSH); + slic_write32(adapter, SLIC_REG_WPHY, + phy_config); } } } else { @@ -355,12 +327,12 @@ static void slic_link_config(struct adapter *adapter, * disable auto crossover */ phy_config = (MIICR_REG_16 | (MRV_REG16_XOVEROFF)); - slic_reg32_write(wphy, phy_config, FLUSH); + slic_write32(adapter, SLIC_REG_WPHY, phy_config); } /* power down phy to break link (this may not work) */ phy_config = (MIICR_REG_PCR | (PCR_POWERDOWN | speed | duplex)); - slic_reg32_write(wphy, phy_config, FLUSH); + slic_write32(adapter, SLIC_REG_WPHY, phy_config); slic_flush_write(adapter); /* wait, Marvell says 1 sec, try to get away with 10 ms */ mdelay(10); @@ -373,11 +345,11 @@ static void slic_link_config(struct adapter *adapter, */ phy_config = (MIICR_REG_PCR | (PCR_RESET | speed | duplex)); - slic_reg32_write(wphy, phy_config, FLUSH); + slic_write32(adapter, SLIC_REG_WPHY, phy_config); } else { /* it's a Cicada PHY */ /* disable auto-neg, set speed, powerup */ phy_config = (MIICR_REG_PCR | (speed | duplex)); - slic_reg32_write(wphy, phy_config, FLUSH); + slic_write32(adapter, SLIC_REG_WPHY, phy_config); } } } @@ -387,7 +359,6 @@ static int slic_card_download_gbrcv(struct adapter *adapter) const struct firmware *fw; const char *file = ""; int ret; - __iomem struct slic_regs *slic_regs = adapter->slic_regs; u32 codeaddr; u32 instruction; int index = 0; @@ -428,27 +399,26 @@ static int slic_card_download_gbrcv(struct adapter *adapter) break; } /* start download */ - slic_reg32_write(&slic_regs->slic_rcv_wcs, SLIC_RCVWCS_BEGIN, FLUSH); + slic_write32(adapter, SLIC_REG_RCV_WCS, SLIC_RCVWCS_BEGIN); /* download the rcv sequencer ucode */ for (codeaddr = 0; codeaddr < rcvucodelen; codeaddr++) { /* write out instruction address */ - slic_reg32_write(&slic_regs->slic_rcv_wcs, codeaddr, FLUSH); + slic_write32(adapter, SLIC_REG_RCV_WCS, codeaddr); instruction = *(u32 *)(fw->data + index); index += 4; /* write out the instruction data low addr */ - slic_reg32_write(&slic_regs->slic_rcv_wcs, instruction, FLUSH); + slic_write32(adapter, SLIC_REG_RCV_WCS, instruction); instruction = *(u8 *)(fw->data + index); index++; /* write out the instruction data high addr */ - slic_reg32_write(&slic_regs->slic_rcv_wcs, (u8)instruction, - FLUSH); + slic_write32(adapter, SLIC_REG_RCV_WCS, instruction); } /* download finished */ release_firmware(fw); - slic_reg32_write(&slic_regs->slic_rcv_wcs, SLIC_RCVWCS_FINISH, FLUSH); + slic_write32(adapter, SLIC_REG_RCV_WCS, SLIC_RCVWCS_FINISH); slic_flush_write(adapter); return 0; @@ -465,7 +435,6 @@ static int slic_card_download(struct adapter *adapter) u32 section; int thissectionsize; int codeaddr; - __iomem struct slic_regs *slic_regs = adapter->slic_regs; u32 instruction; u32 baseaddress; u32 i; @@ -509,17 +478,17 @@ static int slic_card_download(struct adapter *adapter) for (codeaddr = 0; codeaddr < thissectionsize; codeaddr++) { /* Write out instruction address */ - slic_reg32_write(&slic_regs->slic_wcs, - baseaddress + codeaddr, FLUSH); + slic_write32(adapter, SLIC_REG_WCS, + baseaddress + codeaddr); /* Write out instruction to low addr */ - slic_reg32_write(&slic_regs->slic_wcs, - instruction, FLUSH); + slic_write32(adapter, SLIC_REG_WCS, + instruction); instruction = *(u32 *)(fw->data + index); index += 4; /* Write out instruction to high addr */ - slic_reg32_write(&slic_regs->slic_wcs, - instruction, FLUSH); + slic_write32(adapter, SLIC_REG_WCS, + instruction); instruction = *(u32 *)(fw->data + index); index += 4; } @@ -534,17 +503,15 @@ static int slic_card_download(struct adapter *adapter) for (codeaddr = 0; codeaddr < thissectionsize; codeaddr++) { /* Write out instruction address */ - slic_reg32_write(&slic_regs->slic_wcs, - SLIC_WCS_COMPARE | (baseaddress + codeaddr), - FLUSH); + slic_write32(adapter, SLIC_REG_WCS, + SLIC_WCS_COMPARE | (baseaddress + + codeaddr)); /* Write out instruction to low addr */ - slic_reg32_write(&slic_regs->slic_wcs, instruction, - FLUSH); + slic_write32(adapter, SLIC_REG_WCS, instruction); instruction = *(u32 *)(fw->data + index); index += 4; /* Write out instruction to high addr */ - slic_reg32_write(&slic_regs->slic_wcs, instruction, - FLUSH); + slic_write32(adapter, SLIC_REG_WCS, instruction); instruction = *(u32 *)(fw->data + index); index += 4; @@ -553,9 +520,9 @@ static int slic_card_download(struct adapter *adapter) release_firmware(fw); /* Everything OK, kick off the card */ mdelay(10); - slic_reg32_write(&slic_regs->slic_wcs, SLIC_WCS_START, FLUSH); - slic_flush_write(adapter); + slic_write32(adapter, SLIC_REG_WCS, SLIC_WCS_START); + slic_flush_write(adapter); /* * stall for 20 ms, long enough for ucode to init card * and reach mainloop @@ -587,21 +554,21 @@ static void slic_adapter_set_hwaddr(struct adapter *adapter) static void slic_intagg_set(struct adapter *adapter, u32 value) { - slic_reg32_write(&adapter->slic_regs->slic_intagg, value, FLUSH); + slic_write32(adapter, SLIC_REG_INTAGG, value); adapter->card->loadlevel_current = value; } static void slic_soft_reset(struct adapter *adapter) { if (adapter->card->state == CARD_UP) { - slic_reg32_write(&adapter->slic_regs->slic_quiesce, 0, FLUSH); + slic_write32(adapter, SLIC_REG_QUIESCE, 0); slic_flush_write(adapter); mdelay(1); } - slic_reg32_write(&adapter->slic_regs->slic_reset, SLIC_RESET_MAGIC, - FLUSH); + slic_write32(adapter, SLIC_REG_RESET, SLIC_RESET_MAGIC); slic_flush_write(adapter); + mdelay(1); } @@ -609,17 +576,16 @@ static void slic_mac_address_config(struct adapter *adapter) { u32 value; u32 value2; - __iomem struct slic_regs *slic_regs = adapter->slic_regs; value = ntohl(*(__be32 *)&adapter->currmacaddr[2]); - slic_reg32_write(&slic_regs->slic_wraddral, value, FLUSH); - slic_reg32_write(&slic_regs->slic_wraddrbl, value, FLUSH); + slic_write32(adapter, SLIC_REG_WRADDRAL, value); + slic_write32(adapter, SLIC_REG_WRADDRBL, value); value2 = (u32)((adapter->currmacaddr[0] << 8 | adapter->currmacaddr[1]) & 0xFFFF); - slic_reg32_write(&slic_regs->slic_wraddrah, value2, FLUSH); - slic_reg32_write(&slic_regs->slic_wraddrbh, value2, FLUSH); + slic_write32(adapter, SLIC_REG_WRADDRAH, value2); + slic_write32(adapter, SLIC_REG_WRADDRBH, value2); /* * Write our multicast mask out to the card. This is done @@ -632,7 +598,6 @@ static void slic_mac_address_config(struct adapter *adapter) static void slic_mac_config(struct adapter *adapter) { u32 value; - __iomem struct slic_regs *slic_regs = adapter->slic_regs; /* Setup GMAC gaps */ if (adapter->linkspeed == LINK_1000MB) { @@ -656,7 +621,7 @@ static void slic_mac_config(struct adapter *adapter) } /* write mac config */ - slic_reg32_write(&slic_regs->slic_wmcfg, value, FLUSH); + slic_write32(adapter, SLIC_REG_WMCFG, value); /* setup mac addresses */ slic_mac_address_config(adapter); @@ -666,7 +631,6 @@ static void slic_config_set(struct adapter *adapter, bool linkchange) { u32 value; u32 RcrReset; - __iomem struct slic_regs *slic_regs = adapter->slic_regs; if (linkchange) { /* Setup MAC */ @@ -683,7 +647,7 @@ static void slic_config_set(struct adapter *adapter, bool linkchange) GXCR_XMTEN | /* Enable transmit */ GXCR_PAUSEEN); /* Enable pause */ - slic_reg32_write(&slic_regs->slic_wxcfg, value, FLUSH); + slic_write32(adapter, SLIC_REG_WXCFG, value); /* Setup rcvcfg last */ value = (RcrReset | /* Reset, if linkchange */ @@ -696,7 +660,7 @@ static void slic_config_set(struct adapter *adapter, bool linkchange) value = (GXCR_RESET | /* Always reset */ GXCR_XMTEN); /* Enable transmit */ - slic_reg32_write(&slic_regs->slic_wxcfg, value, FLUSH); + slic_write32(adapter, SLIC_REG_WXCFG, value); /* Setup rcvcfg last */ value = (RcrReset | /* Reset, if linkchange */ @@ -713,7 +677,7 @@ static void slic_config_set(struct adapter *adapter, bool linkchange) if (adapter->macopts & MAC_PROMISC) value |= GRCR_RCVALL; - slic_reg32_write(&slic_regs->slic_wrcfg, value, FLUSH); + slic_write32(adapter, SLIC_REG_WRCFG, value); } /* @@ -723,24 +687,23 @@ static void slic_config_clear(struct adapter *adapter) { u32 value; u32 phy_config; - __iomem struct slic_regs *slic_regs = adapter->slic_regs; /* Setup xmtcfg */ value = (GXCR_RESET | /* Always reset */ GXCR_PAUSEEN); /* Enable pause */ - slic_reg32_write(&slic_regs->slic_wxcfg, value, FLUSH); + slic_write32(adapter, SLIC_REG_WXCFG, value); value = (GRCR_RESET | /* Always reset */ GRCR_CTLEN | /* Enable CTL frames */ GRCR_ADDRAEN | /* Address A enable */ (GRCR_HASHSIZE << GRCR_HASHSIZE_SHIFT)); - slic_reg32_write(&slic_regs->slic_wrcfg, value, FLUSH); + slic_write32(adapter, SLIC_REG_WRCFG, value); /* power down phy */ phy_config = (MIICR_REG_PCR | (PCR_POWERDOWN)); - slic_reg32_write(&slic_regs->slic_wphy, phy_config, FLUSH); + slic_write32(adapter, SLIC_REG_WPHY, phy_config); } static bool slic_mac_filter(struct adapter *adapter, @@ -816,13 +779,11 @@ static void slic_timer_load_check(ulong cardaddr) { struct sliccard *card = (struct sliccard *)cardaddr; struct adapter *adapter = card->master; - u32 __iomem *intagg; u32 load = card->events; u32 level = 0; if ((adapter) && (adapter->state == ADAPT_UP) && (card->state == CARD_UP) && (slic_global.dynamic_intagg)) { - intagg = &adapter->slic_regs->slic_intagg; if (adapter->devid == SLIC_1GB_DEVICE_ID) { if (adapter->linkspeed == LINK_1000MB) level = 100; @@ -842,7 +803,7 @@ static void slic_timer_load_check(ulong cardaddr) } if (card->loadlevel_current != level) { card->loadlevel_current = level; - slic_reg32_write(intagg, level, FLUSH); + slic_write32(adapter, SLIC_REG_INTAGG, level); } } else { if (load > SLIC_LOAD_5) @@ -859,7 +820,7 @@ static void slic_timer_load_check(ulong cardaddr) level = SLIC_INTAGG_0; if (card->loadlevel_current != level) { card->loadlevel_current = level; - slic_reg32_write(intagg, level, FLUSH); + slic_write32(adapter, SLIC_REG_INTAGG, level); } } } @@ -903,7 +864,6 @@ static int slic_upr_queue_request(struct adapter *adapter, static void slic_upr_start(struct adapter *adapter) { struct slic_upr *upr; - __iomem struct slic_regs *slic_regs = adapter->slic_regs; upr = adapter->upr_list; if (!upr) @@ -915,29 +875,24 @@ static void slic_upr_start(struct adapter *adapter) switch (upr->upr_request) { case SLIC_UPR_STATS: if (upr->upr_data_h == 0) { - slic_reg32_write(&slic_regs->slic_stats, upr->upr_data, - FLUSH); + slic_write32(adapter, SLIC_REG_RSTAT, upr->upr_data); } else { - slic_reg64_write(adapter, &slic_regs->slic_stats64, - upr->upr_data, - &slic_regs->slic_addr_upper, - upr->upr_data_h, FLUSH); + slic_write64(adapter, SLIC_REG_RSTAT64, upr->upr_data, + upr->upr_data_h); } break; case SLIC_UPR_RLSR: - slic_reg64_write(adapter, &slic_regs->slic_rlsr, upr->upr_data, - &slic_regs->slic_addr_upper, upr->upr_data_h, - FLUSH); + slic_write64(adapter, SLIC_REG_LSTAT, upr->upr_data, + upr->upr_data_h); break; case SLIC_UPR_RCONFIG: - slic_reg64_write(adapter, &slic_regs->slic_rconfig, - upr->upr_data, &slic_regs->slic_addr_upper, - upr->upr_data_h, FLUSH); + slic_write64(adapter, SLIC_REG_RCONFIG, upr->upr_data, + upr->upr_data_h); break; case SLIC_UPR_PING: - slic_reg32_write(&slic_regs->slic_ping, 1, FLUSH); + slic_write32(adapter, SLIC_REG_PING, 1); break; } slic_flush_write(adapter); @@ -1194,7 +1149,6 @@ static int slic_rspqueue_init(struct adapter *adapter) { int i; struct slic_rspqueue *rspq = &adapter->rspqueue; - __iomem struct slic_regs *slic_regs = adapter->slic_regs; u32 paddrh = 0; memset(rspq, 0, sizeof(struct slic_rspqueue)); @@ -1213,14 +1167,12 @@ static int slic_rspqueue_init(struct adapter *adapter) } if (paddrh == 0) { - slic_reg32_write(&slic_regs->slic_rbar, - (rspq->paddr[i] | SLIC_RSPQ_BUFSINPAGE), - DONT_FLUSH); + slic_write32(adapter, SLIC_REG_RBAR, + rspq->paddr[i] | SLIC_RSPQ_BUFSINPAGE); } else { - slic_reg64_write(adapter, &slic_regs->slic_rbar64, - (rspq->paddr[i] | SLIC_RSPQ_BUFSINPAGE), - &slic_regs->slic_addr_upper, - paddrh, DONT_FLUSH); + slic_write64(adapter, SLIC_REG_RBAR64, + rspq->paddr[i] | SLIC_RSPQ_BUFSINPAGE, + paddrh); } } rspq->offset = 0; @@ -1241,9 +1193,9 @@ static struct slic_rspbuf *slic_rspqueue_getnext(struct adapter *adapter) if (++rspq->offset < SLIC_RSPQ_BUFSINPAGE) { rspq->rspbuf++; } else { - slic_reg64_write(adapter, &adapter->slic_regs->slic_rbar64, - (rspq->paddr[rspq->pageindex] | SLIC_RSPQ_BUFSINPAGE), - &adapter->slic_regs->slic_addr_upper, 0, DONT_FLUSH); + slic_write64(adapter, SLIC_REG_RBAR64, + rspq->paddr[rspq->pageindex] | + SLIC_RSPQ_BUFSINPAGE, 0); rspq->pageindex = (rspq->pageindex + 1) % rspq->num_pages; rspq->offset = 0; rspq->rspbuf = (struct slic_rspbuf *) @@ -1577,14 +1529,11 @@ retry_rcvqfill: } #endif if (paddrh == 0) { - slic_reg32_write(&adapter->slic_regs->slic_hbar, - (u32)paddrl, DONT_FLUSH); + slic_write32(adapter, SLIC_REG_HBAR, + (u32)paddrl); } else { - slic_reg64_write(adapter, - &adapter->slic_regs->slic_hbar64, - paddrl, - &adapter->slic_regs->slic_addr_upper, - paddrh, DONT_FLUSH); + slic_write64(adapter, SLIC_REG_HBAR64, paddrl, + paddrh); } if (rcvq->head) rcvq->tail->next = skb; @@ -1707,12 +1656,9 @@ static u32 slic_rcvqueue_reinsert(struct adapter *adapter, struct sk_buff *skb) dev_err(dev, " rcvq->count[%x]\n", rcvq->count); } if (paddrh == 0) { - slic_reg32_write(&adapter->slic_regs->slic_hbar, (u32)paddrl, - DONT_FLUSH); + slic_write32(adapter, SLIC_REG_HBAR, (u32)paddrl); } else { - slic_reg64_write(adapter, &adapter->slic_regs->slic_hbar64, - paddrl, &adapter->slic_regs->slic_addr_upper, - paddrh, DONT_FLUSH); + slic_write64(adapter, SLIC_REG_HBAR64, paddrl, paddrh); } if (rcvq->head) rcvq->tail->next = skb; @@ -2158,9 +2104,9 @@ static irqreturn_t slic_interrupt(int irq, void *dev_id) u32 isr; if ((adapter->pshmem) && (adapter->pshmem->isr)) { - slic_reg32_write(&adapter->slic_regs->slic_icr, - ICR_INT_MASK, FLUSH); + slic_write32(adapter, SLIC_REG_ICR, ICR_INT_MASK); slic_flush_write(adapter); + isr = adapter->isrcopy = adapter->pshmem->isr; adapter->pshmem->isr = 0; adapter->num_isrs++; @@ -2181,7 +2127,7 @@ static irqreturn_t slic_interrupt(int irq, void *dev_id) adapter->isrcopy = 0; adapter->all_reg_writes += 2; adapter->isr_reg_writes++; - slic_reg32_write(&adapter->slic_regs->slic_isr, 0, FLUSH); + slic_write32(adapter, SLIC_REG_ISR, 0); } else { adapter->false_interrupts++; } @@ -2233,13 +2179,11 @@ static netdev_tx_t slic_xmit_start(struct sk_buff *skb, struct net_device *dev) } #endif if (hcmd->paddrh == 0) { - slic_reg32_write(&adapter->slic_regs->slic_cbar, - (hcmd->paddrl | hcmd->cmdsize), DONT_FLUSH); + slic_write32(adapter, SLIC_REG_CBAR, (hcmd->paddrl | + hcmd->cmdsize)); } else { - slic_reg64_write(adapter, &adapter->slic_regs->slic_cbar64, - (hcmd->paddrl | hcmd->cmdsize), - &adapter->slic_regs->slic_addr_upper, - hcmd->paddrh, DONT_FLUSH); + slic_write64(adapter, SLIC_REG_CBAR64, + hcmd->paddrl | hcmd->cmdsize, hcmd->paddrh); } xmit_done: return NETDEV_TX_OK; @@ -2299,7 +2243,6 @@ static int slic_if_init(struct adapter *adapter, unsigned long *flags) { struct sliccard *card = adapter->card; struct net_device *dev = adapter->netdev; - __iomem struct slic_regs *slic_regs = adapter->slic_regs; struct slic_shmem *pshmem; int rc; @@ -2344,7 +2287,7 @@ static int slic_if_init(struct adapter *adapter, unsigned long *flags) adapter->queues_initialized = 1; } - slic_reg32_write(&slic_regs->slic_icr, ICR_INT_OFF, FLUSH); + slic_write32(adapter, SLIC_REG_ICR, ICR_INT_OFF); slic_flush_write(adapter); mdelay(1); @@ -2357,14 +2300,13 @@ static int slic_if_init(struct adapter *adapter, unsigned long *flags) spin_lock_irqsave(&adapter->bit64reglock, flags); #if BITS_PER_LONG == 64 - slic_reg32_write(&slic_regs->slic_addr_upper, - SLIC_GET_ADDR_HIGH(&pshmem->isr), DONT_FLUSH); - slic_reg32_write(&slic_regs->slic_isp, - SLIC_GET_ADDR_LOW(&pshmem->isr), FLUSH); + slic_write32(adapter, SLIC_REG_ADDR_UPPER, + SLIC_GET_ADDR_HIGH(&pshmem->isr)); + slic_write32(adapter, SLIC_REG_ISP, + SLIC_GET_ADDR_LOW(&pshmem->isr)); #else - slic_reg32_write(&slic_regs->slic_addr_upper, 0, DONT_FLUSH); - slic_reg32_write(&slic_regs->slic_isp, (u32)&pshmem->isr, - FLUSH); + slic_write32(adapter, SLIC_REG_ADDR_UPPER, 0); + slic_write32(adapter, SLIC_REG_ISP, (u32)&pshmem->isr); #endif spin_unlock_irqrestore(&adapter->bit64reglock, flags); adapter->isp_initialized = 1; @@ -2395,17 +2337,19 @@ static int slic_if_init(struct adapter *adapter, unsigned long *flags) */ adapter->isrcopy = 0; adapter->pshmem->isr = 0; - slic_reg32_write(&slic_regs->slic_isr, 0, FLUSH); - slic_reg32_write(&slic_regs->slic_icr, ICR_INT_ON, FLUSH); + slic_write32(adapter, SLIC_REG_ISR, 0); + slic_write32(adapter, SLIC_REG_ICR, ICR_INT_ON); slic_link_config(adapter, LINK_AUTOSPEED, LINK_AUTOD); slic_flush_write(adapter); + rc = slic_link_event_handler(adapter); if (rc) { /* disable interrupts then clear pending events */ - slic_reg32_write(&slic_regs->slic_icr, ICR_INT_OFF, FLUSH); - slic_reg32_write(&slic_regs->slic_isr, 0, FLUSH); + slic_write32(adapter, SLIC_REG_ICR, ICR_INT_OFF); + slic_write32(adapter, SLIC_REG_ISR, 0); slic_flush_write(adapter); + if (adapter->pingtimerset) { del_timer(&adapter->pingtimer); adapter->pingtimerset = 0; @@ -2478,7 +2422,7 @@ static void slic_entry_remove(struct pci_dev *pcidev) unregister_netdev(dev); slic_adapter_freeresources(adapter); - slic_unmap_mmio_space(adapter); + iounmap(adapter->regs); /* free multicast addresses */ mlist = adapter->mcastaddrs; @@ -2512,7 +2456,6 @@ static int slic_entry_halt(struct net_device *dev) { struct adapter *adapter = netdev_priv(dev); struct sliccard *card = adapter->card; - __iomem struct slic_regs *slic_regs = adapter->slic_regs; unsigned long flags; spin_lock_irqsave(&slic_global.driver_lock, flags); @@ -2522,7 +2465,7 @@ static int slic_entry_halt(struct net_device *dev) adapter->upr_list = NULL; adapter->upr_busy = 0; adapter->devflags_prev = 0; - slic_reg32_write(&slic_regs->slic_icr, ICR_INT_OFF, FLUSH); + slic_write32(adapter, SLIC_REG_ICR, ICR_INT_OFF); adapter->all_reg_writes++; adapter->icr_reg_writes++; slic_config_clear(adapter); @@ -2532,9 +2475,10 @@ static int slic_entry_halt(struct net_device *dev) adapter->activated = 0; } #ifdef AUTOMATIC_RESET - slic_reg32_write(&slic_regs->slic_reset_iface, 0, FLUSH); + slic_write32(adapter, SLIC_REG_RESET_IFACE, 0); #endif slic_flush_write(adapter); + /* * Reset the adapter's cmd queues */ @@ -2680,7 +2624,6 @@ static void slic_config_pci(struct pci_dev *pcidev) static int slic_card_init(struct sliccard *card, struct adapter *adapter) { - __iomem struct slic_regs *slic_regs = adapter->slic_regs; struct slic_eeprom *peeprom; struct oslic_eeprom *pOeeprom; dma_addr_t phys_config; @@ -2725,17 +2668,17 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter) memset(peeprom, 0, sizeof(struct slic_eeprom)); - slic_reg32_write(&slic_regs->slic_icr, ICR_INT_OFF, FLUSH); + slic_write32(adapter, SLIC_REG_ICR, ICR_INT_OFF); slic_flush_write(adapter); mdelay(1); pshmem = (struct slic_shmem *)(unsigned long) adapter->phys_shmem; spin_lock_irqsave(&adapter->bit64reglock, flags); - slic_reg32_write(&slic_regs->slic_addr_upper, - SLIC_GET_ADDR_HIGH(&pshmem->isr), DONT_FLUSH); - slic_reg32_write(&slic_regs->slic_isp, - SLIC_GET_ADDR_LOW(&pshmem->isr), FLUSH); + slic_write32(adapter, SLIC_REG_ADDR_UPPER, + SLIC_GET_ADDR_HIGH(&pshmem->isr)); + slic_write32(adapter, SLIC_REG_ISP, + SLIC_GET_ADDR_LOW(&pshmem->isr)); spin_unlock_irqrestore(&adapter->bit64reglock, flags); status = slic_config_get(adapter, phys_configl, phys_configh); @@ -2749,12 +2692,9 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter) if (adapter->pshmem->isr) { if (adapter->pshmem->isr & ISR_UPC) { adapter->pshmem->isr = 0; - slic_reg64_write(adapter, - &slic_regs->slic_isp, 0, - &slic_regs->slic_addr_upper, - 0, FLUSH); - slic_reg32_write(&slic_regs->slic_isr, - 0, FLUSH); + slic_write64(adapter, SLIC_REG_ISP, 0, + 0); + slic_write32(adapter, SLIC_REG_ISR, 0); slic_flush_write(adapter); slic_upr_request_complete(adapter, 0); @@ -2762,8 +2702,7 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter) } adapter->pshmem->isr = 0; - slic_reg32_write(&slic_regs->slic_isr, - 0, FLUSH); + slic_write32(adapter, SLIC_REG_ISR, 0); slic_flush_write(adapter); } else { mdelay(1); @@ -2771,11 +2710,10 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter) if (i > 5000) { dev_err(&adapter->pcidev->dev, "Fetch of config data timed out.\n"); - slic_reg64_write(adapter, - &slic_regs->slic_isp, 0, - &slic_regs->slic_addr_upper, - 0, FLUSH); + slic_write64(adapter, SLIC_REG_ISP, + 0, 0); slic_flush_write(adapter); + status = -EINVAL; goto card_init_err; } @@ -2853,9 +2791,7 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter) peeprom, phys_config); if (!card->config.EepromValid) { - slic_reg64_write(adapter, &slic_regs->slic_isp, 0, - &slic_regs->slic_addr_upper, - 0, FLUSH); + slic_write64(adapter, SLIC_REG_ISP, 0, 0); slic_flush_write(adapter); dev_err(&adapter->pcidev->dev, "EEPROM invalid.\n"); return -EINVAL; @@ -2936,7 +2872,6 @@ static int slic_init_adapter(struct net_device *netdev, adapter->busnumber = pcidev->bus->number; adapter->slotnumber = ((pcidev->devfn >> 3) & 0x1F); adapter->functionnumber = (pcidev->devfn & 0x7); - adapter->slic_regs = memaddr; adapter->regs = memaddr; adapter->irq = pcidev->irq; adapter->chipid = chip_idx; @@ -2989,27 +2924,9 @@ static u32 slic_card_locate(struct adapter *adapter) struct sliccard *card = slic_global.slic_card; struct physcard *physcard = slic_global.phys_card; ushort card_hostid; - u16 __iomem *hostid_reg; uint i; - uint rdhostid_offset = 0; - - switch (adapter->devid) { - case SLIC_2GB_DEVICE_ID: - rdhostid_offset = SLIC_RDHOSTID_2GB; - break; - case SLIC_1GB_DEVICE_ID: - rdhostid_offset = SLIC_RDHOSTID_1GB; - break; - default: - return -ENODEV; - } - - hostid_reg = - (u16 __iomem *)(((u8 __iomem *)(adapter->slic_regs)) + - rdhostid_offset); - /* read the 16 bit hostid from SRAM */ - card_hostid = (ushort)readw(hostid_reg); + card_hostid = slic_read32(adapter, SLIC_REG_HOSTID); /* Initialize a new card structure if need be */ if (card_hostid == SLIC_HOSTID_DEFAULT) { -- cgit v0.10.2 From fdb7777512785f90e712a7cb665a9adbaf673bd0 Mon Sep 17 00:00:00 2001 From: Lino Sanfilippo <LinoSanfilippo@gmx.de> Date: Fri, 22 Jul 2016 23:09:18 +0200 Subject: staging: slicoss: improve implementation concerning the shared memory Remove the volatile specifiers of struct slic_shmem. Furthermore store the bus addresses for the isr pointer, link status and statistics separately and access the upper and lower word of these addresses by means of [lower|upper]_32_bits(). By doing this take the endianness into account. Signed-off-by: Lino Sanfilippo <LinoSanfilippo@gmx.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/slicoss/slic.h b/drivers/staging/slicoss/slic.h index 3bba82a..4ac1fd2 100644 --- a/drivers/staging/slicoss/slic.h +++ b/drivers/staging/slicoss/slic.h @@ -351,10 +351,17 @@ struct base_driver { uint cardnuminuse[SLIC_MAX_CARDS]; }; -struct slic_shmem { - volatile u32 isr; - volatile u32 linkstatus; - volatile struct slic_stats inicstats; +struct slic_shmem_data { + u32 isr; + u32 lnkstatus; + struct slic_stats stats; +}; + +struct slic_shmemory { + dma_addr_t isr_phaddr; + dma_addr_t lnkstatus_phaddr; + dma_addr_t stats_phaddr; + struct slic_shmem_data __iomem *shmem_data; }; struct slic_upr { @@ -414,9 +421,8 @@ struct adapter { u32 intrregistered; uint isp_initialized; uint gennumber; - struct slic_shmem *pshmem; + struct slic_shmemory shmem; dma_addr_t phys_shmem; - u32 isrcopy; void __iomem *regs; unsigned char state; unsigned char linkstate; diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index 8e978e7..9a8c6f9 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -923,42 +923,34 @@ err_unlock_irq: static void slic_link_upr_complete(struct adapter *adapter, u32 isr) { - u32 linkstatus = adapter->pshmem->linkstatus; + struct slic_shmemory *sm = &adapter->shmem; + struct slic_shmem_data *sm_data = sm->shmem_data; + u32 lst = sm_data->lnkstatus; uint linkup; unsigned char linkspeed; unsigned char linkduplex; if ((isr & ISR_UPCERR) || (isr & ISR_UPCBSY)) { - struct slic_shmem *pshmem; + dma_addr_t phaddr = sm->lnkstatus_phaddr; - pshmem = (struct slic_shmem *)(unsigned long) - adapter->phys_shmem; -#if BITS_PER_LONG == 64 - slic_upr_queue_request(adapter, - SLIC_UPR_RLSR, - SLIC_GET_ADDR_LOW(&pshmem->linkstatus), - SLIC_GET_ADDR_HIGH(&pshmem->linkstatus), + slic_upr_queue_request(adapter, SLIC_UPR_RLSR, + cpu_to_le32(lower_32_bits(phaddr)), + cpu_to_le32(upper_32_bits(phaddr)), 0, 0); -#else - slic_upr_queue_request(adapter, - SLIC_UPR_RLSR, - (u32)&pshmem->linkstatus, - SLIC_GET_ADDR_HIGH(pshmem), 0, 0); -#endif return; } if (adapter->state != ADAPT_UP) return; - linkup = linkstatus & GIG_LINKUP ? LINK_UP : LINK_DOWN; - if (linkstatus & GIG_SPEED_1000) + linkup = lst & GIG_LINKUP ? LINK_UP : LINK_DOWN; + if (lst & GIG_SPEED_1000) linkspeed = LINK_1000MB; - else if (linkstatus & GIG_SPEED_100) + else if (lst & GIG_SPEED_100) linkspeed = LINK_100MB; else linkspeed = LINK_10MB; - if (linkstatus & GIG_FULLDUPLEX) + if (lst & GIG_FULLDUPLEX) linkduplex = LINK_FULLD; else linkduplex = LINK_HALFD; @@ -1010,81 +1002,77 @@ static void slic_upr_request_complete(struct adapter *adapter, u32 isr) upr->next = NULL; adapter->upr_busy = 0; switch (upr->upr_request) { - case SLIC_UPR_STATS: - { - struct slic_stats *slicstats = - (struct slic_stats *)&adapter->pshmem->inicstats; - struct slic_stats *newstats = slicstats; - struct slic_stats *old = &adapter->inicstats_prev; - struct slicnet_stats *stst = &adapter->slic_stats; - - if (isr & ISR_UPCERR) { - dev_err(&adapter->netdev->dev, - "SLIC_UPR_STATS command failed isr[%x]\n", - isr); - - break; - } - UPDATE_STATS_GB(stst->tcp.xmit_tcp_segs, - newstats->xmit_tcp_segs_gb, - old->xmit_tcp_segs_gb); - - UPDATE_STATS_GB(stst->tcp.xmit_tcp_bytes, - newstats->xmit_tcp_bytes_gb, - old->xmit_tcp_bytes_gb); - - UPDATE_STATS_GB(stst->tcp.rcv_tcp_segs, - newstats->rcv_tcp_segs_gb, - old->rcv_tcp_segs_gb); - - UPDATE_STATS_GB(stst->tcp.rcv_tcp_bytes, - newstats->rcv_tcp_bytes_gb, - old->rcv_tcp_bytes_gb); - - UPDATE_STATS_GB(stst->iface.xmt_bytes, - newstats->xmit_bytes_gb, - old->xmit_bytes_gb); - - UPDATE_STATS_GB(stst->iface.xmt_ucast, - newstats->xmit_unicasts_gb, - old->xmit_unicasts_gb); - - UPDATE_STATS_GB(stst->iface.rcv_bytes, - newstats->rcv_bytes_gb, - old->rcv_bytes_gb); - - UPDATE_STATS_GB(stst->iface.rcv_ucast, - newstats->rcv_unicasts_gb, - old->rcv_unicasts_gb); - - UPDATE_STATS_GB(stst->iface.xmt_errors, - newstats->xmit_collisions_gb, - old->xmit_collisions_gb); - - UPDATE_STATS_GB(stst->iface.xmt_errors, - newstats->xmit_excess_collisions_gb, - old->xmit_excess_collisions_gb); - - UPDATE_STATS_GB(stst->iface.xmt_errors, - newstats->xmit_other_error_gb, - old->xmit_other_error_gb); - - UPDATE_STATS_GB(stst->iface.rcv_errors, - newstats->rcv_other_error_gb, - old->rcv_other_error_gb); - - UPDATE_STATS_GB(stst->iface.rcv_discards, - newstats->rcv_drops_gb, - old->rcv_drops_gb); - - if (newstats->rcv_drops_gb > old->rcv_drops_gb) { - adapter->rcv_drops += - (newstats->rcv_drops_gb - - old->rcv_drops_gb); - } - memcpy(old, newstats, sizeof(struct slic_stats)); + case SLIC_UPR_STATS: { + struct slic_shmemory *sm = &adapter->shmem; + struct slic_shmem_data *sm_data = sm->shmem_data; + struct slic_stats *stats = &sm_data->stats; + struct slic_stats *old = &adapter->inicstats_prev; + struct slicnet_stats *stst = &adapter->slic_stats; + + if (isr & ISR_UPCERR) { + dev_err(&adapter->netdev->dev, + "SLIC_UPR_STATS command failed isr[%x]\n", isr); break; } + + UPDATE_STATS_GB(stst->tcp.xmit_tcp_segs, + stats->xmit_tcp_segs_gb, + old->xmit_tcp_segs_gb); + + UPDATE_STATS_GB(stst->tcp.xmit_tcp_bytes, + stats->xmit_tcp_bytes_gb, + old->xmit_tcp_bytes_gb); + + UPDATE_STATS_GB(stst->tcp.rcv_tcp_segs, + stats->rcv_tcp_segs_gb, + old->rcv_tcp_segs_gb); + + UPDATE_STATS_GB(stst->tcp.rcv_tcp_bytes, + stats->rcv_tcp_bytes_gb, + old->rcv_tcp_bytes_gb); + + UPDATE_STATS_GB(stst->iface.xmt_bytes, + stats->xmit_bytes_gb, + old->xmit_bytes_gb); + + UPDATE_STATS_GB(stst->iface.xmt_ucast, + stats->xmit_unicasts_gb, + old->xmit_unicasts_gb); + + UPDATE_STATS_GB(stst->iface.rcv_bytes, + stats->rcv_bytes_gb, + old->rcv_bytes_gb); + + UPDATE_STATS_GB(stst->iface.rcv_ucast, + stats->rcv_unicasts_gb, + old->rcv_unicasts_gb); + + UPDATE_STATS_GB(stst->iface.xmt_errors, + stats->xmit_collisions_gb, + old->xmit_collisions_gb); + + UPDATE_STATS_GB(stst->iface.xmt_errors, + stats->xmit_excess_collisions_gb, + old->xmit_excess_collisions_gb); + + UPDATE_STATS_GB(stst->iface.xmt_errors, + stats->xmit_other_error_gb, + old->xmit_other_error_gb); + + UPDATE_STATS_GB(stst->iface.rcv_errors, + stats->rcv_other_error_gb, + old->rcv_other_error_gb); + + UPDATE_STATS_GB(stst->iface.rcv_discards, + stats->rcv_drops_gb, + old->rcv_drops_gb); + + if (stats->rcv_drops_gb > old->rcv_drops_gb) + adapter->rcv_drops += (stats->rcv_drops_gb - + old->rcv_drops_gb); + memcpy_fromio(old, stats, sizeof(*stats)); + break; + } case SLIC_UPR_RLSR: slic_link_upr_complete(adapter, isr); break; @@ -1682,26 +1670,18 @@ static u32 slic_rcvqueue_reinsert(struct adapter *adapter, struct sk_buff *skb) static int slic_link_event_handler(struct adapter *adapter) { int status; - struct slic_shmem *pshmem; + struct slic_shmemory *sm = &adapter->shmem; + dma_addr_t phaddr = sm->lnkstatus_phaddr; + if (adapter->state != ADAPT_UP) { /* Adapter is not operational. Ignore. */ return -ENODEV; } - - pshmem = (struct slic_shmem *)(unsigned long)adapter->phys_shmem; - -#if BITS_PER_LONG == 64 - status = slic_upr_request(adapter, - SLIC_UPR_RLSR, - SLIC_GET_ADDR_LOW(&pshmem->linkstatus), - SLIC_GET_ADDR_HIGH(&pshmem->linkstatus), - 0, 0); -#else + /* no 4GB wrap guaranteed */ status = slic_upr_request(adapter, SLIC_UPR_RLSR, - (u32)&pshmem->linkstatus, /* no 4GB wrap guaranteed */ - 0, 0, 0); -#endif + cpu_to_le32(lower_32_bits(phaddr)), + cpu_to_le32(upper_32_bits(phaddr)), 0, 0); return status; } @@ -1711,12 +1691,13 @@ static void slic_init_cleanup(struct adapter *adapter) adapter->intrregistered = 0; free_irq(adapter->netdev->irq, adapter->netdev); } - if (adapter->pshmem) { - pci_free_consistent(adapter->pcidev, - sizeof(struct slic_shmem), - adapter->pshmem, adapter->phys_shmem); - adapter->pshmem = NULL; - adapter->phys_shmem = (dma_addr_t)(unsigned long)NULL; + + if (adapter->shmem.shmem_data) { + struct slic_shmemory *sm = &adapter->shmem; + struct slic_shmem_data *sm_data = sm->shmem_data; + + pci_free_consistent(adapter->pcidev, sizeof(*sm_data), sm_data, + sm->isr_phaddr); } if (adapter->pingtimerset) { @@ -2101,14 +2082,16 @@ static irqreturn_t slic_interrupt(int irq, void *dev_id) { struct net_device *dev = dev_id; struct adapter *adapter = netdev_priv(dev); + struct slic_shmemory *sm = &adapter->shmem; + struct slic_shmem_data *sm_data = sm->shmem_data; u32 isr; - if ((adapter->pshmem) && (adapter->pshmem->isr)) { + if (sm_data->isr) { slic_write32(adapter, SLIC_REG_ICR, ICR_INT_MASK); slic_flush_write(adapter); - isr = adapter->isrcopy = adapter->pshmem->isr; - adapter->pshmem->isr = 0; + isr = sm_data->isr; + sm_data->isr = 0; adapter->num_isrs++; switch (adapter->card->state) { case CARD_UP: @@ -2124,7 +2107,6 @@ static irqreturn_t slic_interrupt(int irq, void *dev_id) break; } - adapter->isrcopy = 0; adapter->all_reg_writes += 2; adapter->isr_reg_writes++; slic_write32(adapter, SLIC_REG_ISR, 0); @@ -2243,7 +2225,8 @@ static int slic_if_init(struct adapter *adapter, unsigned long *flags) { struct sliccard *card = adapter->card; struct net_device *dev = adapter->netdev; - struct slic_shmem *pshmem; + struct slic_shmemory *sm = &adapter->shmem; + struct slic_shmem_data *sm_data = sm->shmem_data; int rc; /* adapter should be down at this point */ @@ -2294,21 +2277,13 @@ static int slic_if_init(struct adapter *adapter, unsigned long *flags) if (!adapter->isp_initialized) { unsigned long flags; - pshmem = (struct slic_shmem *)(unsigned long) - adapter->phys_shmem; - spin_lock_irqsave(&adapter->bit64reglock, flags); - -#if BITS_PER_LONG == 64 slic_write32(adapter, SLIC_REG_ADDR_UPPER, - SLIC_GET_ADDR_HIGH(&pshmem->isr)); + cpu_to_le32(upper_32_bits(sm->isr_phaddr))); slic_write32(adapter, SLIC_REG_ISP, - SLIC_GET_ADDR_LOW(&pshmem->isr)); -#else - slic_write32(adapter, SLIC_REG_ADDR_UPPER, 0); - slic_write32(adapter, SLIC_REG_ISP, (u32)&pshmem->isr); -#endif + cpu_to_le32(lower_32_bits(sm->isr_phaddr))); spin_unlock_irqrestore(&adapter->bit64reglock, flags); + adapter->isp_initialized = 1; } @@ -2335,8 +2310,7 @@ static int slic_if_init(struct adapter *adapter, unsigned long *flags) /* * clear any pending events, then enable interrupts */ - adapter->isrcopy = 0; - adapter->pshmem->isr = 0; + sm_data->isr = 0; slic_write32(adapter, SLIC_REG_ISR, 0); slic_write32(adapter, SLIC_REG_ICR, ICR_INT_ON); @@ -2624,13 +2598,14 @@ static void slic_config_pci(struct pci_dev *pcidev) static int slic_card_init(struct sliccard *card, struct adapter *adapter) { + struct slic_shmemory *sm = &adapter->shmem; + struct slic_shmem_data *sm_data = sm->shmem_data; struct slic_eeprom *peeprom; struct oslic_eeprom *pOeeprom; dma_addr_t phys_config; u32 phys_configh; u32 phys_configl; u32 i = 0; - struct slic_shmem *pshmem; int status; uint macaddrs = card->card_size; ushort eecodesize; @@ -2671,14 +2646,12 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter) slic_write32(adapter, SLIC_REG_ICR, ICR_INT_OFF); slic_flush_write(adapter); mdelay(1); - pshmem = (struct slic_shmem *)(unsigned long) - adapter->phys_shmem; spin_lock_irqsave(&adapter->bit64reglock, flags); slic_write32(adapter, SLIC_REG_ADDR_UPPER, - SLIC_GET_ADDR_HIGH(&pshmem->isr)); + cpu_to_le32(upper_32_bits(sm->isr_phaddr))); slic_write32(adapter, SLIC_REG_ISP, - SLIC_GET_ADDR_LOW(&pshmem->isr)); + cpu_to_le32(lower_32_bits(sm->isr_phaddr))); spin_unlock_irqrestore(&adapter->bit64reglock, flags); status = slic_config_get(adapter, phys_configl, phys_configh); @@ -2689,9 +2662,9 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter) } for (;;) { - if (adapter->pshmem->isr) { - if (adapter->pshmem->isr & ISR_UPC) { - adapter->pshmem->isr = 0; + if (sm_data->isr) { + if (sm_data->isr & ISR_UPC) { + sm_data->isr = 0; slic_write64(adapter, SLIC_REG_ISP, 0, 0); slic_write32(adapter, SLIC_REG_ISR, 0); @@ -2701,7 +2674,7 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter) break; } - adapter->pshmem->isr = 0; + sm_data->isr = 0; slic_write32(adapter, SLIC_REG_ISR, 0); slic_flush_write(adapter); } else { @@ -2864,6 +2837,9 @@ static int slic_init_adapter(struct net_device *netdev, ushort index; struct slic_handle *pslic_handle; struct adapter *adapter = netdev_priv(netdev); + struct slic_shmemory *sm = &adapter->shmem; + struct slic_shmem_data *sm_data; + dma_addr_t phaddr; /* adapter->pcidev = pcidev;*/ adapter->vendid = pci_tbl_entry->vendor; @@ -2898,12 +2874,17 @@ static int slic_init_adapter(struct net_device *netdev, pslic_handle->next = adapter->pfree_slic_handles; adapter->pfree_slic_handles = pslic_handle; } - adapter->pshmem = pci_zalloc_consistent(adapter->pcidev, - sizeof(struct slic_shmem), - &adapter->phys_shmem); - if (!adapter->pshmem) + sm_data = pci_zalloc_consistent(adapter->pcidev, sizeof(*sm_data), + &phaddr); + if (!sm_data) return -ENOMEM; + sm->shmem_data = sm_data; + sm->isr_phaddr = phaddr; + sm->lnkstatus_phaddr = phaddr + offsetof(struct slic_shmem_data, + lnkstatus); + sm->stats_phaddr = phaddr + offsetof(struct slic_shmem_data, stats); + return 0; } -- cgit v0.10.2 From 473256b0aea4e69a99afb21c9243e5cd544ac9ad Mon Sep 17 00:00:00 2001 From: Lino Sanfilippo <LinoSanfilippo@gmx.de> Date: Fri, 22 Jul 2016 23:09:19 +0200 Subject: staging: slicoss: simplify struct for statistics Merge several structures for statistics to one structure and remove unnecessary union nesting. Signed-off-by: Lino Sanfilippo <LinoSanfilippo@gmx.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/slicoss/slic.h b/drivers/staging/slicoss/slic.h index 4ac1fd2..fe1d2ce 100644 --- a/drivers/staging/slicoss/slic.h +++ b/drivers/staging/slicoss/slic.h @@ -351,6 +351,24 @@ struct base_driver { uint cardnuminuse[SLIC_MAX_CARDS]; }; +struct slic_stats { + /* xmit stats */ + u64 xmit_tcp_bytes; + u64 xmit_tcp_segs; + u64 xmit_bytes; + u64 xmit_collisions; + u64 xmit_unicasts; + u64 xmit_other_error; + u64 xmit_excess_collisions; + /* rcv stats */ + u64 rcv_tcp_bytes; + u64 rcv_tcp_segs; + u64 rcv_bytes; + u64 rcv_unicasts; + u64 rcv_other_error; + u64 rcv_drops; +}; + struct slic_shmem_data { u32 isr; u32 lnkstatus; diff --git a/drivers/staging/slicoss/slichw.h b/drivers/staging/slicoss/slichw.h index ae04bf6..49cb91a 100644 --- a/drivers/staging/slicoss/slichw.h +++ b/drivers/staging/slicoss/slichw.h @@ -459,85 +459,6 @@ struct slic_pnp_capabilities { struct slicpm_wakeup_capabilities wakeup_capabilities; }; -struct xmt_stats { - u32 xmit_tcp_bytes; - u32 xmit_tcp_segs; - u32 xmit_bytes; - u32 xmit_collisions; - u32 xmit_unicasts; - u32 xmit_other_error; - u32 xmit_excess_collisions; -}; - -struct rcv_stats { - u32 rcv_tcp_bytes; - u32 rcv_tcp_segs; - u32 rcv_bytes; - u32 rcv_unicasts; - u32 rcv_other_error; - u32 rcv_drops; -}; - -struct xmt_statsgb { - u64 xmit_tcp_bytes; - u64 xmit_tcp_segs; - u64 xmit_bytes; - u64 xmit_collisions; - u64 xmit_unicasts; - u64 xmit_other_error; - u64 xmit_excess_collisions; -}; - -struct rcv_statsgb { - u64 rcv_tcp_bytes; - u64 rcv_tcp_segs; - u64 rcv_bytes; - u64 rcv_unicasts; - u64 rcv_other_error; - u64 rcv_drops; -}; - -struct slic_stats { - union { - struct { - struct xmt_stats xmt100; - struct rcv_stats rcv100; - } stats_100; - struct { - struct xmt_statsgb xmtGB; - struct rcv_statsgb rcvGB; - } stats_GB; - } u; -}; - -#define xmit_tcp_segs100 u.stats_100.xmt100.xmit_tcp_segs -#define xmit_tcp_bytes100 u.stats_100.xmt100.xmit_tcp_bytes -#define xmit_bytes100 u.stats_100.xmt100.xmit_bytes -#define xmit_collisions100 u.stats_100.xmt100.xmit_collisions -#define xmit_unicasts100 u.stats_100.xmt100.xmit_unicasts -#define xmit_other_error100 u.stats_100.xmt100.xmit_other_error -#define xmit_excess_collisions100 u.stats_100.xmt100.xmit_excess_collisions -#define rcv_tcp_segs100 u.stats_100.rcv100.rcv_tcp_segs -#define rcv_tcp_bytes100 u.stats_100.rcv100.rcv_tcp_bytes -#define rcv_bytes100 u.stats_100.rcv100.rcv_bytes -#define rcv_unicasts100 u.stats_100.rcv100.rcv_unicasts -#define rcv_other_error100 u.stats_100.rcv100.rcv_other_error -#define rcv_drops100 u.stats_100.rcv100.rcv_drops -#define xmit_tcp_segs_gb u.stats_GB.xmtGB.xmit_tcp_segs -#define xmit_tcp_bytes_gb u.stats_GB.xmtGB.xmit_tcp_bytes -#define xmit_bytes_gb u.stats_GB.xmtGB.xmit_bytes -#define xmit_collisions_gb u.stats_GB.xmtGB.xmit_collisions -#define xmit_unicasts_gb u.stats_GB.xmtGB.xmit_unicasts -#define xmit_other_error_gb u.stats_GB.xmtGB.xmit_other_error -#define xmit_excess_collisions_gb u.stats_GB.xmtGB.xmit_excess_collisions - -#define rcv_tcp_segs_gb u.stats_GB.rcvGB.rcv_tcp_segs -#define rcv_tcp_bytes_gb u.stats_GB.rcvGB.rcv_tcp_bytes -#define rcv_bytes_gb u.stats_GB.rcvGB.rcv_bytes -#define rcv_unicasts_gb u.stats_GB.rcvGB.rcv_unicasts -#define rcv_other_error_gb u.stats_GB.rcvGB.rcv_other_error -#define rcv_drops_gb u.stats_GB.rcvGB.rcv_drops - struct slic_config_mac { u8 macaddrA[6]; }; diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index 9a8c6f9..7834bda 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -1015,61 +1015,49 @@ static void slic_upr_request_complete(struct adapter *adapter, u32 isr) break; } - UPDATE_STATS_GB(stst->tcp.xmit_tcp_segs, - stats->xmit_tcp_segs_gb, - old->xmit_tcp_segs_gb); + UPDATE_STATS_GB(stst->tcp.xmit_tcp_segs, stats->xmit_tcp_segs, + old->xmit_tcp_segs); - UPDATE_STATS_GB(stst->tcp.xmit_tcp_bytes, - stats->xmit_tcp_bytes_gb, - old->xmit_tcp_bytes_gb); + UPDATE_STATS_GB(stst->tcp.xmit_tcp_bytes, stats->xmit_tcp_bytes, + old->xmit_tcp_bytes); - UPDATE_STATS_GB(stst->tcp.rcv_tcp_segs, - stats->rcv_tcp_segs_gb, - old->rcv_tcp_segs_gb); + UPDATE_STATS_GB(stst->tcp.rcv_tcp_segs, stats->rcv_tcp_segs, + old->rcv_tcp_segs); - UPDATE_STATS_GB(stst->tcp.rcv_tcp_bytes, - stats->rcv_tcp_bytes_gb, - old->rcv_tcp_bytes_gb); + UPDATE_STATS_GB(stst->tcp.rcv_tcp_bytes, stats->rcv_tcp_bytes, + old->rcv_tcp_bytes); - UPDATE_STATS_GB(stst->iface.xmt_bytes, - stats->xmit_bytes_gb, - old->xmit_bytes_gb); + UPDATE_STATS_GB(stst->iface.xmt_bytes, stats->xmit_bytes, + old->xmit_bytes); - UPDATE_STATS_GB(stst->iface.xmt_ucast, - stats->xmit_unicasts_gb, - old->xmit_unicasts_gb); + UPDATE_STATS_GB(stst->iface.xmt_ucast, stats->xmit_unicasts, + old->xmit_unicasts); - UPDATE_STATS_GB(stst->iface.rcv_bytes, - stats->rcv_bytes_gb, - old->rcv_bytes_gb); + UPDATE_STATS_GB(stst->iface.rcv_bytes, stats->rcv_bytes, + old->rcv_bytes); - UPDATE_STATS_GB(stst->iface.rcv_ucast, - stats->rcv_unicasts_gb, - old->rcv_unicasts_gb); + UPDATE_STATS_GB(stst->iface.rcv_ucast, stats->rcv_unicasts, + old->rcv_unicasts); - UPDATE_STATS_GB(stst->iface.xmt_errors, - stats->xmit_collisions_gb, - old->xmit_collisions_gb); + UPDATE_STATS_GB(stst->iface.xmt_errors, stats->xmit_collisions, + old->xmit_collisions); UPDATE_STATS_GB(stst->iface.xmt_errors, - stats->xmit_excess_collisions_gb, - old->xmit_excess_collisions_gb); + stats->xmit_excess_collisions, + old->xmit_excess_collisions); - UPDATE_STATS_GB(stst->iface.xmt_errors, - stats->xmit_other_error_gb, - old->xmit_other_error_gb); + UPDATE_STATS_GB(stst->iface.xmt_errors, stats->xmit_other_error, + old->xmit_other_error); - UPDATE_STATS_GB(stst->iface.rcv_errors, - stats->rcv_other_error_gb, - old->rcv_other_error_gb); + UPDATE_STATS_GB(stst->iface.rcv_errors, stats->rcv_other_error, + old->rcv_other_error); - UPDATE_STATS_GB(stst->iface.rcv_discards, - stats->rcv_drops_gb, - old->rcv_drops_gb); + UPDATE_STATS_GB(stst->iface.rcv_discards, stats->rcv_drops, + old->rcv_drops); - if (stats->rcv_drops_gb > old->rcv_drops_gb) - adapter->rcv_drops += (stats->rcv_drops_gb - - old->rcv_drops_gb); + if (stats->rcv_drops > old->rcv_drops) + adapter->rcv_drops += (stats->rcv_drops - + old->rcv_drops); memcpy_fromio(old, stats, sizeof(*stats)); break; } -- cgit v0.10.2 From 0ad1ed99d6ce86bc76b8768a49a65155281aad44 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen <aaro.koskinen@nokia.com> Date: Wed, 29 Jun 2016 15:20:44 +0300 Subject: staging: octeon: validate interface before calling INDEX Some helper functions call INDEX before checking if the interface is valid. Since pow0 is not a real interface, we get the following errors: cvmx_helper_get_interface_index_num: Illegal IPD port number Fix by using INDEX only when needed with real interfaces. Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index e9cd5f2..190afde 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -237,7 +237,6 @@ static int cvm_oct_common_change_mtu(struct net_device *dev, int new_mtu) { struct octeon_ethernet *priv = netdev_priv(dev); int interface = INTERFACE(priv->port); - int index = INDEX(priv->port); #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) int vlan_bytes = 4; #else @@ -259,6 +258,7 @@ static int cvm_oct_common_change_mtu(struct net_device *dev, int new_mtu) if ((interface < 2) && (cvmx_helper_interface_get_mode(interface) != CVMX_HELPER_INTERFACE_MODE_SPI)) { + int index = INDEX(priv->port); /* Add ethernet header and FCS, and VLAN if configured. */ int max_packet = new_mtu + 14 + 4 + vlan_bytes; @@ -300,12 +300,12 @@ static void cvm_oct_common_set_multicast_list(struct net_device *dev) union cvmx_gmxx_prtx_cfg gmx_cfg; struct octeon_ethernet *priv = netdev_priv(dev); int interface = INTERFACE(priv->port); - int index = INDEX(priv->port); if ((interface < 2) && (cvmx_helper_interface_get_mode(interface) != CVMX_HELPER_INTERFACE_MODE_SPI)) { union cvmx_gmxx_rxx_adr_ctl control; + int index = INDEX(priv->port); control.u64 = 0; control.s.bcst = 1; /* Allow broadcast MAC addresses */ @@ -352,7 +352,6 @@ static int cvm_oct_set_mac_filter(struct net_device *dev) struct octeon_ethernet *priv = netdev_priv(dev); union cvmx_gmxx_prtx_cfg gmx_cfg; int interface = INTERFACE(priv->port); - int index = INDEX(priv->port); if ((interface < 2) && (cvmx_helper_interface_get_mode(interface) != @@ -360,6 +359,7 @@ static int cvm_oct_set_mac_filter(struct net_device *dev) int i; u8 *ptr = dev->dev_addr; u64 mac = 0; + int index = INDEX(priv->port); for (i = 0; i < 6; i++) mac = (mac << 8) | (u64)ptr[i]; -- cgit v0.10.2 From 9eca4993dcfa17d21f28fae773c21b04d47b117d Mon Sep 17 00:00:00 2001 From: Aaro Koskinen <aaro.koskinen@nokia.com> Date: Wed, 29 Jun 2016 15:20:45 +0300 Subject: staging: octeon: check for pow0 before calling interface helper Check for pow0 port first before calling the interface helper. This avoids the following error log when setting up pow0 interface: cvmx_helper_get_interface_num: Illegal IPD port number Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/octeon/ethernet-util.h b/drivers/staging/octeon/ethernet-util.h index 45f024b..617da80 100644 --- a/drivers/staging/octeon/ethernet-util.h +++ b/drivers/staging/octeon/ethernet-util.h @@ -32,12 +32,13 @@ static inline void *cvm_oct_get_buffer_ptr(union cvmx_buf_ptr packet_ptr) */ static inline int INTERFACE(int ipd_port) { - int interface = cvmx_helper_get_interface_num(ipd_port); + int interface; + if (ipd_port == CVMX_PIP_NUM_INPUT_PORTS) + return 10; + interface = cvmx_helper_get_interface_num(ipd_port); if (interface >= 0) return interface; - else if (ipd_port == CVMX_PIP_NUM_INPUT_PORTS) - return 10; panic("Illegal ipd_port %d passed to INTERFACE\n", ipd_port); } -- cgit v0.10.2 From 0048a44c36db045071dcb1bb4844140cd3712e1d Mon Sep 17 00:00:00 2001 From: Aaro Koskinen <aaro.koskinen@nokia.com> Date: Wed, 29 Jun 2016 15:20:46 +0300 Subject: staging: octeon: delete redundant log message There will be a separate banner message after pow0 is set up (or an error message if it failed). Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index 190afde..48f2adb 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -705,7 +705,6 @@ static int cvm_oct_probe(struct platform_device *pdev) if ((pow_send_group != -1)) { struct net_device *dev; - pr_info("\tConfiguring device for POW only access\n"); dev = alloc_etherdev(sizeof(struct octeon_ethernet)); if (dev) { /* Initialize the device private structure. */ -- cgit v0.10.2 From 5d99db13b77e301fcd839310d47392053db35562 Mon Sep 17 00:00:00 2001 From: Philippe Reynes <tremyfr@gmail.com> Date: Sat, 16 Jul 2016 01:13:34 +0200 Subject: net: ethernet: octeon: use phydev from struct net_device The private structure contain a pointer to phydev, but the structure net_device already contain such pointer. So we can remove the pointer phydev in the private structure, and update the driver to use the one contained in struct net_device. Signed-off-by: Philippe Reynes <tremyfr@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c index e13a4ab..661b97b 100644 --- a/drivers/staging/octeon/ethernet-mdio.c +++ b/drivers/staging/octeon/ethernet-mdio.c @@ -36,36 +36,30 @@ static void cvm_oct_get_drvinfo(struct net_device *dev, static int cvm_oct_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - struct octeon_ethernet *priv = netdev_priv(dev); - - if (priv->phydev) - return phy_ethtool_gset(priv->phydev, cmd); + if (dev->phydev) + return phy_ethtool_gset(dev->phydev, cmd); return -EINVAL; } static int cvm_oct_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - struct octeon_ethernet *priv = netdev_priv(dev); - if (!capable(CAP_NET_ADMIN)) return -EPERM; - if (priv->phydev) - return phy_ethtool_sset(priv->phydev, cmd); + if (dev->phydev) + return phy_ethtool_sset(dev->phydev, cmd); return -EINVAL; } static int cvm_oct_nway_reset(struct net_device *dev) { - struct octeon_ethernet *priv = netdev_priv(dev); - if (!capable(CAP_NET_ADMIN)) return -EPERM; - if (priv->phydev) - return phy_start_aneg(priv->phydev); + if (dev->phydev) + return phy_start_aneg(dev->phydev); return -EINVAL; } @@ -88,15 +82,13 @@ const struct ethtool_ops cvm_oct_ethtool_ops = { */ int cvm_oct_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { - struct octeon_ethernet *priv = netdev_priv(dev); - if (!netif_running(dev)) return -EINVAL; - if (!priv->phydev) + if (!dev->phydev) return -EINVAL; - return phy_mii_ioctl(priv->phydev, rq, cmd); + return phy_mii_ioctl(dev->phydev, rq, cmd); } void cvm_oct_note_carrier(struct octeon_ethernet *priv, @@ -119,9 +111,9 @@ void cvm_oct_adjust_link(struct net_device *dev) cvmx_helper_link_info_t link_info; link_info.u64 = 0; - link_info.s.link_up = priv->phydev->link ? 1 : 0; - link_info.s.full_duplex = priv->phydev->duplex ? 1 : 0; - link_info.s.speed = priv->phydev->speed; + link_info.s.link_up = dev->phydev->link ? 1 : 0; + link_info.s.full_duplex = dev->phydev->duplex ? 1 : 0; + link_info.s.speed = dev->phydev->speed; priv->link_info = link_info.u64; /* @@ -130,8 +122,8 @@ void cvm_oct_adjust_link(struct net_device *dev) if (priv->poll) priv->poll(dev); - if (priv->last_link != priv->phydev->link) { - priv->last_link = priv->phydev->link; + if (priv->last_link != dev->phydev->link) { + priv->last_link = dev->phydev->link; cvmx_helper_link_set(priv->port, link_info); cvm_oct_note_carrier(priv, link_info); } @@ -151,9 +143,8 @@ int cvm_oct_common_stop(struct net_device *dev) priv->poll = NULL; - if (priv->phydev) - phy_disconnect(priv->phydev); - priv->phydev = NULL; + if (dev->phydev) + phy_disconnect(dev->phydev); if (priv->last_link) { link_info.u64 = 0; @@ -176,6 +167,7 @@ int cvm_oct_phy_setup_device(struct net_device *dev) { struct octeon_ethernet *priv = netdev_priv(dev); struct device_node *phy_node; + struct phy_device *phydev = NULL; if (!priv->of_node) goto no_phy; @@ -193,14 +185,14 @@ int cvm_oct_phy_setup_device(struct net_device *dev) if (!phy_node) goto no_phy; - priv->phydev = of_phy_connect(dev, phy_node, cvm_oct_adjust_link, 0, - PHY_INTERFACE_MODE_GMII); + phydev = of_phy_connect(dev, phy_node, cvm_oct_adjust_link, 0, + PHY_INTERFACE_MODE_GMII); - if (!priv->phydev) + if (!phydev) return -ENODEV; priv->last_link = 0; - phy_start_aneg(priv->phydev); + phy_start_aneg(phydev); return 0; no_phy: diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c index 91b148c..48846df 100644 --- a/drivers/staging/octeon/ethernet-rgmii.c +++ b/drivers/staging/octeon/ethernet-rgmii.c @@ -145,7 +145,7 @@ int cvm_oct_rgmii_open(struct net_device *dev) if (ret) return ret; - if (priv->phydev) { + if (dev->phydev) { /* * In phydev mode, we need still periodic polling for the * preamble error checking, and we also need to call this diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index 48f2adb..2eb9731 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -457,10 +457,8 @@ int cvm_oct_common_init(struct net_device *dev) void cvm_oct_common_uninit(struct net_device *dev) { - struct octeon_ethernet *priv = netdev_priv(dev); - - if (priv->phydev) - phy_disconnect(priv->phydev); + if (dev->phydev) + phy_disconnect(dev->phydev); } int cvm_oct_common_open(struct net_device *dev, @@ -484,10 +482,10 @@ int cvm_oct_common_open(struct net_device *dev, if (octeon_is_simulation()) return 0; - if (priv->phydev) { - int r = phy_read_status(priv->phydev); + if (dev->phydev) { + int r = phy_read_status(dev->phydev); - if (r == 0 && priv->phydev->link == 0) + if (r == 0 && dev->phydev->link == 0) netif_carrier_off(dev); cvm_oct_adjust_link(dev); } else { diff --git a/drivers/staging/octeon/octeon-ethernet.h b/drivers/staging/octeon/octeon-ethernet.h index 6275c15..d533aef 100644 --- a/drivers/staging/octeon/octeon-ethernet.h +++ b/drivers/staging/octeon/octeon-ethernet.h @@ -40,7 +40,6 @@ struct octeon_ethernet { struct sk_buff_head tx_free_list[16]; /* Device statistics */ struct net_device_stats stats; - struct phy_device *phydev; unsigned int last_speed; unsigned int last_link; /* Last negotiated link state */ -- cgit v0.10.2 From de55b42d8d0d5853b0d2118ca8741d0dc232ea0b Mon Sep 17 00:00:00 2001 From: Philippe Reynes <tremyfr@gmail.com> Date: Sat, 16 Jul 2016 01:13:35 +0200 Subject: net: ethernet: octeon: use phy_ethtool_{get|set}_link_ksettings There are two generics functions phy_ethtool_{get|set}_link_ksettings, so we can use them instead of defining the same code in the driver. There was a check on CAP_NET_ADMIN in cvm_oct_set_settings, but this check is already done in dev_ethtool, so no need to repeat it before calling the generic function. Signed-off-by: Philippe Reynes <tremyfr@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c index 661b97b..1fde9c8 100644 --- a/drivers/staging/octeon/ethernet-mdio.c +++ b/drivers/staging/octeon/ethernet-mdio.c @@ -34,25 +34,6 @@ static void cvm_oct_get_drvinfo(struct net_device *dev, strlcpy(info->bus_info, "Builtin", sizeof(info->bus_info)); } -static int cvm_oct_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - if (dev->phydev) - return phy_ethtool_gset(dev->phydev, cmd); - - return -EINVAL; -} - -static int cvm_oct_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (dev->phydev) - return phy_ethtool_sset(dev->phydev, cmd); - - return -EINVAL; -} - static int cvm_oct_nway_reset(struct net_device *dev) { if (!capable(CAP_NET_ADMIN)) @@ -66,10 +47,10 @@ static int cvm_oct_nway_reset(struct net_device *dev) const struct ethtool_ops cvm_oct_ethtool_ops = { .get_drvinfo = cvm_oct_get_drvinfo, - .get_settings = cvm_oct_get_settings, - .set_settings = cvm_oct_set_settings, .nway_reset = cvm_oct_nway_reset, .get_link = ethtool_op_get_link, + .get_link_ksettings = phy_ethtool_get_link_ksettings, + .set_link_ksettings = phy_ethtool_set_link_ksettings, }; /** -- cgit v0.10.2 From 49bb9af0783143d2b0d419069cf331542326ec6d Mon Sep 17 00:00:00 2001 From: Luis de Bethencourt <luisbg@osg.samsung.com> Date: Tue, 31 May 2016 15:39:13 +0100 Subject: staging: gdm724x: gdm_usb: Remove ignored value The value assigned to ret will be overwritten before it could be read in a future iteration of the loop. Removing the unnecessary assignment. Signed-off-by: Luis de Bethencourt <luisbg@osg.samsung.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/gdm724x/gdm_usb.c b/drivers/staging/gdm724x/gdm_usb.c index d650d77..15a7e81 100644 --- a/drivers/staging/gdm724x/gdm_usb.c +++ b/drivers/staging/gdm724x/gdm_usb.c @@ -415,10 +415,10 @@ static void do_rx(struct work_struct *work) switch (cmd_evt) { case LTE_GET_INFORMATION_RESULT: if (set_mac_address(hci->data, r->cb_data) == 0) { - ret = r->callback(r->cb_data, - r->buf, - r->urb->actual_length, - KERNEL_THREAD); + r->callback(r->cb_data, + r->buf, + r->urb->actual_length, + KERNEL_THREAD); } break; -- cgit v0.10.2 From bf5cad613a627aec6d2a64fc294595cdd7c6a045 Mon Sep 17 00:00:00 2001 From: Binoy Jayan <binoy.jayan@linaro.org> Date: Wed, 15 Jun 2016 11:10:03 +0530 Subject: staging: gdm724x: Replace semaphore netlink with mutex Replace semaphore netlink_mutex with mutex. Semaphores are going away in the future. Signed-off-by: Binoy Jayan <binoy.jayan@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/gdm724x/netlink_k.c b/drivers/staging/gdm724x/netlink_k.c index a0232e8..abe2425 100644 --- a/drivers/staging/gdm724x/netlink_k.c +++ b/drivers/staging/gdm724x/netlink_k.c @@ -14,6 +14,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/export.h> +#include <linux/mutex.h> #include <linux/etherdevice.h> #include <linux/netlink.h> #include <asm/byteorder.h> @@ -21,13 +22,7 @@ #include "netlink_k.h" -#if defined(DEFINE_MUTEX) static DEFINE_MUTEX(netlink_mutex); -#else -static struct semaphore netlink_mutex; -#define mutex_lock(x) down(x) -#define mutex_unlock(x) up(x) -#endif #define ND_MAX_GROUP 30 #define ND_IFINDEX_LEN sizeof(int) @@ -96,10 +91,6 @@ struct sock *netlink_init(int unit, .input = netlink_rcv, }; -#if !defined(DEFINE_MUTEX) - init_MUTEX(&netlink_mutex); -#endif - sock = netlink_kernel_create(&init_net, unit, &cfg); if (sock) -- cgit v0.10.2 From 02875bd93220a0ff209437b7ca1286aaa2b475dc Mon Sep 17 00:00:00 2001 From: Samuele Baisi <ciccio87@gmail.com> Date: Tue, 5 Jul 2016 13:33:59 +0200 Subject: Staging: gdm724x: gdm_tty: Fixed a checkpatch check issue. Removed a blankline after an opening bracket. Signed-off-by: Samuele Baisi <ciccio87@gmail.com> Acked-by: Luis de Bethencourt <luisbg@osg.samsung.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/gdm724x/gdm_tty.c b/drivers/staging/gdm724x/gdm_tty.c index eb7e252..ae39663 100644 --- a/drivers/staging/gdm724x/gdm_tty.c +++ b/drivers/staging/gdm724x/gdm_tty.c @@ -225,7 +225,6 @@ int register_lte_tty_device(struct tty_dev *tty_dev, struct device *device) int j; for (i = 0; i < TTY_MAX_COUNT; i++) { - gdm = kmalloc(sizeof(*gdm), GFP_KERNEL); if (!gdm) return -ENOMEM; -- cgit v0.10.2 From 83d628315d56bf78971235babf27db38df21eec8 Mon Sep 17 00:00:00 2001 From: Moshe Green <paledirac@gmail.com> Date: Wed, 1 Jun 2016 23:34:21 +0300 Subject: Staging: sm750fb: fix a line length coding style warning in ddk750_chip.c This is a patch to the ddk750_chip.c file that fixes up a line length warning found by the checkpatch.pl tool. Signed-off-by: Moshe Green <paledirac@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index f80ee77..e6bb504 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -133,7 +133,9 @@ static void setMasterClock(unsigned int frequency) { unsigned int reg, divisor; - /* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */ + /* Cheok_0509: For SM750LE, the memory clock is fixed. + * Nothing to set. + */ if (getChipType() == SM750LE) return; -- cgit v0.10.2 From f90416df64a156cfe0708e1305dce5f23399cd18 Mon Sep 17 00:00:00 2001 From: Moshe Green <mgmoshes@gmail.com> Date: Sun, 5 Jun 2016 22:09:24 +0300 Subject: Staging: sm750fb: fix line length coding style issue in ddk750_chip.c This is a patch to the ddk750_chip.c file that fixes up a line length warning found by the checkpatch.pl tool Signed-off-by: Moshe Green <mgmoshes@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index e6bb504..4db80db 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -86,7 +86,9 @@ static void setMemoryClock(unsigned int frequency) { unsigned int reg, divisor; - /* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */ + /* Cheok_0509: For SM750LE, the memory clock is fixed. + * Nothing to set. + */ if (getChipType() == SM750LE) return; -- cgit v0.10.2 From d943005ac0902dade9d6641b3d9d5c959bc77a07 Mon Sep 17 00:00:00 2001 From: Moshe Green <mgmoshes@gmail.com> Date: Mon, 6 Jun 2016 22:04:32 +0300 Subject: Staging: sm750fb: fix block comment coding style issue in ddk750_chip.c This is a patch to the ddk750_chip.c file that fixes up two block comment coding style warnings found by the checkpatch.pl tool Signed-off-by: Moshe Green <mgmoshes@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index 4db80db..c1356bb 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -93,8 +93,10 @@ static void setMemoryClock(unsigned int frequency) return; if (frequency) { - /* Set the frequency to the maximum frequency that the DDR Memory can take - which is 336MHz. */ + /* + * Set the frequency to the maximum frequency that the DDR Memory can take + * which is 336MHz. + */ if (frequency > MHz(336)) frequency = MHz(336); -- cgit v0.10.2 From c9d67dc41d2e808d0a4ed9d5ba48974dba7868e0 Mon Sep 17 00:00:00 2001 From: yeongjun Kim <iam.yeongjunkim@gmail.com> Date: Wed, 15 Jun 2016 00:36:07 +0900 Subject: staging: sm750fb: fix block comments errors in ddk750_display.c WARNING: Block comments use * on subsequent lines WARNING: Block comments use a trailing */ on a separate line WARNING: Block comments use * on subsequent lines WARNING: Block comments use a trailing */ on a separate line Signed-off-by: yeongjun Kim <iam.yeongjunkim@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/sm750fb/ddk750_display.c b/drivers/staging/sm750fb/ddk750_display.c index ca4973e..a040042 100644 --- a/drivers/staging/sm750fb/ddk750_display.c +++ b/drivers/staging/sm750fb/ddk750_display.c @@ -68,8 +68,10 @@ static void waitNextVerticalSync(int ctrl, int delay) if (!ctrl) { /* primary controller */ - /* Do not wait when the Primary PLL is off or display control is already off. - This will prevent the software to wait forever. */ + /* + * Do not wait when the Primary PLL is off or display control is + * already off. This will prevent the software to wait forever. + */ if (!(PEEK32(PANEL_PLL_CTRL) & PLL_CTRL_POWER) || !(PEEK32(PANEL_DISPLAY_CTRL) & DISPLAY_CTRL_TIMING)) { return; @@ -88,9 +90,10 @@ static void waitNextVerticalSync(int ctrl, int delay) } } else { - - /* Do not wait when the Primary PLL is off or display control is already off. - This will prevent the software to wait forever. */ + /* + * Do not wait when the Primary PLL is off or display control is + * already off. This will prevent the software to wait forever. + */ if (!(PEEK32(CRT_PLL_CTRL) & PLL_CTRL_POWER) || !(PEEK32(CRT_DISPLAY_CTRL) & DISPLAY_CTRL_TIMING)) { return; -- cgit v0.10.2 From bfbeb71c092f4baab5d0e3ea24fb49bd758f95e6 Mon Sep 17 00:00:00 2001 From: Stefan Wolz <wolzstefan@web.de> Date: Thu, 23 Jun 2016 14:00:10 +0200 Subject: sm750fb/sm750_hw.c: corrected alignment Fixed alignment in multiline declarations. Signed-off-by: Stefan Wolz <wolzstefan@web.de> Signed-off-by: Christian Halder <christian.halder@fau.de> Signed-off-by: Sebastian Handwerker <sebastian.handwerker@posteo.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index 2daeedd..72380a8 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -173,7 +173,8 @@ int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev) } int hw_sm750_output_setMode(struct lynxfb_output *output, - struct fb_var_screeninfo *var, struct fb_fix_screeninfo *fix) + struct fb_var_screeninfo *var, + struct fb_fix_screeninfo *fix) { int ret; disp_output_t dispSet; @@ -244,8 +245,8 @@ int hw_sm750_crtc_checkMode(struct lynxfb_crtc *crtc, struct fb_var_screeninfo * set the controller's mode for @crtc charged with @var and @fix parameters */ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc, - struct fb_var_screeninfo *var, - struct fb_fix_screeninfo *fix) + struct fb_var_screeninfo *var, + struct fb_fix_screeninfo *fix) { int ret, fmt; u32 reg; @@ -361,7 +362,7 @@ exit: } int hw_sm750_setColReg(struct lynxfb_crtc *crtc, ushort index, - ushort red, ushort green, ushort blue) + ushort red, ushort green, ushort blue) { static unsigned int add[] = {PANEL_PALETTE_RAM, CRT_PALETTE_RAM}; @@ -529,8 +530,8 @@ int hw_sm750_deWait(void) } int hw_sm750_pan_display(struct lynxfb_crtc *crtc, - const struct fb_var_screeninfo *var, - const struct fb_info *info) + const struct fb_var_screeninfo *var, + const struct fb_info *info) { uint32_t total; /* check params */ -- cgit v0.10.2 From 1f24c865ea8539bf18fdef2bc7a0ce7c2974a087 Mon Sep 17 00:00:00 2001 From: Stefan Wolz <wolzstefan@web.de> Date: Thu, 23 Jun 2016 14:00:11 +0200 Subject: sm750fb/sm750_hw.c: fixed whitespacing Deleted unnecessary newlines and added whitespaces around operators. Signed-off-by: Stefan Wolz <wolzstefan@web.de> Signed-off-by: Christian Halder <christian.halder@fau.de> Signed-off-by: Sebastian Handwerker <sebastian.handwerker@posteo.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index 72380a8..052f113 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -56,7 +56,6 @@ int hw_sm750_map(struct sm750_dev *sm750_dev, struct pci_dev *pdev) pr_info("mmio virtual addr = %p\n", sm750_dev->pvReg); } - sm750_dev->accel.dprBase = sm750_dev->pvReg + DE_BASE_ADDR_TYPE1; sm750_dev->accel.dpPortBase = sm750_dev->pvReg + DE_PORT_ADDR_TYPE1; @@ -86,8 +85,6 @@ exit: return ret; } - - int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev) { struct init_status *parm; @@ -101,7 +98,7 @@ int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev) if (parm->mem_clk == 0) parm->mem_clk = parm->chip_clk; if (parm->master_clk == 0) - parm->master_clk = parm->chip_clk/3; + parm->master_clk = parm->chip_clk / 3; ddk750_initHw((initchip_param_t *)&sm750_dev->initParm); /* for sm718,open pci burst */ @@ -184,7 +181,6 @@ int hw_sm750_output_setMode(struct lynxfb_output *output, dispSet = 0; channel = *output->channel; - if (getChipType() != SM750LE) { if (channel == sm750_primary) { pr_info("primary channel\n"); @@ -199,7 +195,6 @@ int hw_sm750_output_setMode(struct lynxfb_output *output, dispSet |= do_LCD1_SEC; if (output->paths & sm750_crt) dispSet |= do_CRT_SEC; - } ddk750_setLogicalDispOut(dispSet); } else { @@ -234,13 +229,11 @@ int hw_sm750_crtc_checkMode(struct lynxfb_crtc *crtc, struct fb_var_screeninfo * break; default: return -EINVAL; - } return 0; } - /* set the controller's mode for @crtc charged with @var and @fix parameters */ @@ -255,7 +248,6 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc, struct sm750_dev *sm750_dev; struct lynxfb_par *par; - ret = 0; par = container_of(crtc, struct lynxfb_par, crtc); sm750_dev = par->dev; @@ -279,9 +271,12 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc, /* set timing */ modparm.pixel_clock = ps_to_hz(var->pixclock); - modparm.vertical_sync_polarity = (var->sync & FB_SYNC_HOR_HIGH_ACT) ? POS:NEG; - modparm.horizontal_sync_polarity = (var->sync & FB_SYNC_VERT_HIGH_ACT) ? POS:NEG; - modparm.clock_phase_polarity = (var->sync & FB_SYNC_COMP_HIGH_ACT) ? POS:NEG; + modparm.vertical_sync_polarity = (var->sync & FB_SYNC_HOR_HIGH_ACT) + ? POS : NEG; + modparm.horizontal_sync_polarity = (var->sync & FB_SYNC_VERT_HIGH_ACT) + ? POS : NEG; + modparm.clock_phase_polarity = (var->sync & FB_SYNC_COMP_HIGH_ACT) + ? POS : NEG; modparm.horizontal_display_end = var->xres; modparm.horizontal_sync_width = var->hsync_len; modparm.horizontal_sync_start = var->xres + var->right_margin; @@ -353,10 +348,8 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc, reg |= ((var->bits_per_pixel >> 4) & CRT_DISPLAY_CTRL_FORMAT_MASK); POKE32(CRT_DISPLAY_CTRL, reg); - } - exit: return ret; } @@ -366,7 +359,8 @@ int hw_sm750_setColReg(struct lynxfb_crtc *crtc, ushort index, { static unsigned int add[] = {PANEL_PALETTE_RAM, CRT_PALETTE_RAM}; - POKE32(add[crtc->channel] + index*4, (red<<16)|(green<<8)|blue); + POKE32(add[crtc->channel] + index * 4, + (red << 16) | (green << 8) | blue); return 0; } @@ -462,7 +456,6 @@ int hw_sm750_setBLANK(struct lynxfb_output *output, int blank) return 0; } - void hw_sm750_initAccel(struct sm750_dev *sm750_dev) { u32 reg; @@ -510,7 +503,6 @@ int hw_sm750le_deWait(void) return -1; } - int hw_sm750_deWait(void) { int i = 0x10000000; -- cgit v0.10.2 From 878336c3362d0948f0fa91c3457af29e8880cfa2 Mon Sep 17 00:00:00 2001 From: Stefan Wolz <wolzstefan@web.de> Date: Thu, 23 Jun 2016 14:00:12 +0200 Subject: sm750fb/sm750_hw.c: fixed comments Fixed multiline comments to meet style standards, fixed typos and split comment lines over 80 characters. Signed-off-by: Stefan Wolz <wolzstefan@web.de> Signed-off-by: Christian Halder <christian.halder@fau.de> Signed-off-by: Sebastian Handwerker <sebastian.handwerker@posteo.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index 052f113..f2ed82e 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -35,17 +35,17 @@ int hw_sm750_map(struct sm750_dev *sm750_dev, struct pci_dev *pdev) pr_info("mmio phyAddr = %lx\n", sm750_dev->vidreg_start); /* reserve the vidreg space of smi adaptor - * if you do this, u need to add release region code + * if you do this, you need to add release region code * in lynxfb_remove, or memory will not be mapped again * successfully - * */ + */ ret = pci_request_region(pdev, 1, "sm750fb"); if (ret) { pr_err("Can not request PCI regions.\n"); goto exit; } - /* now map mmio and vidmem*/ + /* now map mmio and vidmem */ sm750_dev->pvReg = ioremap_nocache(sm750_dev->vidreg_start, sm750_dev->vidreg_size); if (!sm750_dev->pvReg) { @@ -63,10 +63,10 @@ int hw_sm750_map(struct sm750_dev *sm750_dev, struct pci_dev *pdev) sm750_dev->vidmem_start = pci_resource_start(pdev, 0); /* don't use pdev_resource[x].end - resource[x].start to - * calculate the resource size,its only the maximum available - * size but not the actual size,use + * calculate the resource size, it's only the maximum available + * size but not the actual size, using * @ddk750_getVMSize function can be safe. - * */ + */ sm750_dev->vidmem_size = ddk750_getVMSize(); pr_info("video memory phyAddr = %lx, size = %u bytes\n", sm750_dev->vidmem_start, sm750_dev->vidmem_size); @@ -101,7 +101,7 @@ int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev) parm->master_clk = parm->chip_clk / 3; ddk750_initHw((initchip_param_t *)&sm750_dev->initParm); - /* for sm718,open pci burst */ + /* for sm718, open pci burst */ if (sm750_dev->devid == 0x718) { POKE32(SYSTEM_CTRL, PEEK32(SYSTEM_CTRL) | SYSTEM_CTRL_PCI_BURST); @@ -109,7 +109,7 @@ int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev) if (getChipType() != SM750LE) { unsigned int val; - /* does user need CRT ?*/ + /* does user need CRT? */ if (sm750_dev->nocrt) { POKE32(MISC_CTRL, PEEK32(MISC_CTRL) | MISC_CTRL_DAC_POWER_OFF); @@ -141,19 +141,21 @@ int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev) } POKE32(PANEL_DISPLAY_CTRL, val); } else { - /* for 750LE ,no DVI chip initialization makes Monitor no signal */ - /* Set up GPIO for software I2C to program DVI chip in the - Xilinx SP605 board, in order to have video signal. + /* for 750LE, no DVI chip initialization + * makes Monitor no signal + * + * Set up GPIO for software I2C to program DVI chip in the + * Xilinx SP605 board, in order to have video signal. */ sm750_sw_i2c_init(0, 1); /* Customer may NOT use CH7301 DVI chip, which has to be - initialized differently. - */ + * initialized differently. + */ if (sm750_sw_i2c_read_reg(0xec, 0x4a) == 0x95) { /* The following register values for CH7301 are from - Chrontel app note and our experiment. - */ + * Chrontel app note and our experiment. + */ pr_info("yes,CH7301 DVI chip found\n"); sm750_sw_i2c_write_reg(0xec, 0x1d, 0x16); sm750_sw_i2c_write_reg(0xec, 0x21, 0x9); @@ -198,7 +200,7 @@ int hw_sm750_output_setMode(struct lynxfb_output *output, } ddk750_setLogicalDispOut(dispSet); } else { - /* just open DISPLAY_CONTROL_750LE register bit 3:0*/ + /* just open DISPLAY_CONTROL_750LE register bit 3:0 */ u32 reg; reg = PEEK32(DISPLAY_CONTROL_750LE); @@ -234,9 +236,7 @@ int hw_sm750_crtc_checkMode(struct lynxfb_crtc *crtc, struct fb_var_screeninfo * return 0; } -/* - set the controller's mode for @crtc charged with @var and @fix parameters -*/ +/* set the controller's mode for @crtc charged with @var and @fix parameters */ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc, struct fb_var_screeninfo *var, struct fb_fix_screeninfo *fix) @@ -300,12 +300,14 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc, } if (crtc->channel != sm750_secondary) { - /* set pitch, offset ,width,start address ,etc... */ + /* set pitch, offset, width, start address, etc... */ POKE32(PANEL_FB_ADDRESS, crtc->oScreen & PANEL_FB_ADDRESS_ADDRESS_MASK); reg = var->xres * (var->bits_per_pixel >> 3); - /* crtc->channel is not equal to par->index on numeric,be aware of that */ + /* crtc->channel is not equal to par->index on numeric, + * be aware of that + */ reg = ALIGN(reg, crtc->line_pad); reg = (reg << PANEL_FB_WIDTH_WIDTH_SHIFT) & PANEL_FB_WIDTH_WIDTH_MASK; @@ -337,7 +339,9 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc, /* not implemented now */ POKE32(CRT_FB_ADDRESS, crtc->oScreen); reg = var->xres * (var->bits_per_pixel >> 3); - /* crtc->channel is not equal to par->index on numeric,be aware of that */ + /* crtc->channel is not equal to par->index on numeric, + * be aware of that + */ reg = ALIGN(reg, crtc->line_pad) << CRT_FB_WIDTH_WIDTH_SHIFT; reg &= CRT_FB_WIDTH_WIDTH_MASK; reg |= (fix->line_length & CRT_FB_WIDTH_OFFSET_MASK); -- cgit v0.10.2 From ec48944786719d8b475a2ab9155c6a3d82d30e48 Mon Sep 17 00:00:00 2001 From: Stefan Wolz <wolzstefan@web.de> Date: Thu, 23 Jun 2016 14:00:13 +0200 Subject: sm750fb/sm750_hw.c: split assignment & long lines Split lines over 80 characters and separated assignments. Signed-off-by: Stefan Wolz <wolzstefan@web.de> Signed-off-by: Christian Halder <christian.halder@fau.de> Signed-off-by: Sebastian Handwerker <sebastian.handwerker@posteo.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index f2ed82e..1de9f81 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -212,7 +212,8 @@ int hw_sm750_output_setMode(struct lynxfb_output *output, return ret; } -int hw_sm750_crtc_checkMode(struct lynxfb_crtc *crtc, struct fb_var_screeninfo *var) +int hw_sm750_crtc_checkMode(struct lynxfb_crtc *crtc, + struct fb_var_screeninfo *var) { struct sm750_dev *sm750_dev; struct lynxfb_par *par = container_of(crtc, struct lynxfb_par, crtc); @@ -280,11 +281,13 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc, modparm.horizontal_display_end = var->xres; modparm.horizontal_sync_width = var->hsync_len; modparm.horizontal_sync_start = var->xres + var->right_margin; - modparm.horizontal_total = var->xres + var->left_margin + var->right_margin + var->hsync_len; + modparm.horizontal_total = var->xres + var->left_margin + + var->right_margin + var->hsync_len; modparm.vertical_display_end = var->yres; modparm.vertical_sync_height = var->vsync_len; modparm.vertical_sync_start = var->yres + var->lower_margin; - modparm.vertical_total = var->yres + var->upper_margin + var->lower_margin + var->vsync_len; + modparm.vertical_total = var->yres + var->upper_margin + + var->lower_margin + var->vsync_len; /* choose pll */ if (crtc->channel != sm750_secondary) @@ -413,7 +416,9 @@ int hw_sm750_setBLANK(struct lynxfb_output *output, int blank) { unsigned int dpms, pps, crtdb; - dpms = pps = crtdb = 0; + dpms = 0; + pps = 0; + crtdb = 0; switch (blank) { case FB_BLANK_UNBLANK: -- cgit v0.10.2 From 2d17105ed5cde0932f08a80052e756cff217e6a0 Mon Sep 17 00:00:00 2001 From: Edward Lipinsky <ellipinsky@gmail.com> Date: Sat, 23 Jul 2016 11:57:25 -0700 Subject: staging: sm750fb: Fix block comment style This patch fixes the checkpatch.pl warning: WARNING: Block comments use * on subsequent lines Signed-off-by: Edward Lipinsky <ellipinsky@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/sm750fb/ddk750_dvi.c b/drivers/staging/sm750fb/ddk750_dvi.c index a4a2550..8252f77 100644 --- a/drivers/staging/sm750fb/ddk750_dvi.c +++ b/drivers/staging/sm750fb/ddk750_dvi.c @@ -6,9 +6,11 @@ #include "ddk750_sii164.h" -/* This global variable contains all the supported driver and its corresponding - function API. Please set the function pointer to NULL whenever the function - is not supported. */ +/* + * This global variable contains all the supported driver and its corresponding + * function API. Please set the function pointer to NULL whenever the function + * is not supported. + */ static dvi_ctrl_device_t g_dcftSupportedDviController[] = { #ifdef DVI_CTRL_SII164 { -- cgit v0.10.2 From b01a5d716053cbc48d255c3b3815d360cc2f3592 Mon Sep 17 00:00:00 2001 From: Rithvik Patibandla <rithvikp98@gmail.com> Date: Sun, 12 Jun 2016 01:38:58 +0530 Subject: staging:vt6656:card.c:Fix comment block issue Fix "Block comments use * on subsequent lines" and "Block comments use */ on trailing lines" warnings thrown by checkpatch.pl Signed-off-by: Rithvik Patibandla <rithvikp98@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/vt6656/card.c b/drivers/staging/vt6656/card.c index a382fc6..607834c 100644 --- a/drivers/staging/vt6656/card.c +++ b/drivers/staging/vt6656/card.c @@ -47,7 +47,8 @@ #include "usbpipe.h" /* const u16 cwRXBCNTSFOff[MAX_RATE] = - {17, 34, 96, 192, 34, 23, 17, 11, 8, 5, 4, 3}; */ + * {17, 34, 96, 192, 34, 23, 17, 11, 8, 5, 4, 3}; + */ static const u16 cwRXBCNTSFOff[MAX_RATE] = { 192, 96, 34, 17, 34, 23, 17, 11, 8, 5, 4, 3 -- cgit v0.10.2 From a9f47a456ae56c82d6259631c55d32d8b99ca512 Mon Sep 17 00:00:00 2001 From: Rithvik Patibandla <rithvikp98@gmail.com> Date: Fri, 17 Jun 2016 09:57:31 +0530 Subject: staging:vt6656:card.c:fix alignment checks Fix "Alignment should match with open paranthesis" check thrown by checkpatch.pl Signed-off-by: Rithvik Patibandla <rithvikp98@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/vt6656/card.c b/drivers/staging/vt6656/card.c index 607834c..fde48e5 100644 --- a/drivers/staging/vt6656/card.c +++ b/drivers/staging/vt6656/card.c @@ -77,10 +77,10 @@ void vnt_set_channel(struct vnt_private *priv, u32 connection_channel) vnt_mac_reg_bits_off(priv, MAC_REG_CHANNEL, 0xb0); vnt_control_out(priv, MESSAGE_TYPE_SELECT_CHANNEL, - connection_channel, 0, 0, NULL); + connection_channel, 0, 0, NULL); vnt_control_out_u8(priv, MESSAGE_REQUEST_MACREG, MAC_REG_CHANNEL, - (u8)(connection_channel | 0x80)); + (u8)(connection_channel | 0x80)); } /* @@ -127,11 +127,11 @@ static u16 vnt_get_ofdm_rate(struct vnt_private *priv, u16 rate_idx) u16 ui = rate_idx; dev_dbg(&priv->usb->dev, "%s basic rate: %d\n", - __func__, priv->basic_rates); + __func__, priv->basic_rates); if (!vnt_ofdm_min_rate(priv)) { dev_dbg(&priv->usb->dev, "%s (NO OFDM) %d\n", - __func__, rate_idx); + __func__, rate_idx); if (rate_idx > RATE_24M) rate_idx = RATE_24M; return rate_idx; @@ -140,7 +140,7 @@ static u16 vnt_get_ofdm_rate(struct vnt_private *priv, u16 rate_idx) while (ui > RATE_11M) { if (priv->basic_rates & (1 << ui)) { dev_dbg(&priv->usb->dev, "%s rate: %d\n", - __func__, ui); + __func__, ui); return ui; } ui--; @@ -166,7 +166,7 @@ static u16 vnt_get_ofdm_rate(struct vnt_private *priv, u16 rate_idx) * */ static void vnt_calculate_ofdm_rate(u16 rate, u8 bb_type, - u8 *tx_rate, u8 *rsv_time) + u8 *tx_rate, u8 *rsv_time) { switch (rate) { @@ -268,20 +268,20 @@ void vnt_set_rspinf(struct vnt_private *priv, u8 bb_type) int i; /*RSPINF_b_1*/ - vnt_get_phy_field(priv, 14, - vnt_get_cck_rate(priv, RATE_1M), PK_TYPE_11B, &phy[0]); + vnt_get_phy_field(priv, 14, vnt_get_cck_rate(priv, RATE_1M), + PK_TYPE_11B, &phy[0]); /*RSPINF_b_2*/ - vnt_get_phy_field(priv, 14, - vnt_get_cck_rate(priv, RATE_2M), PK_TYPE_11B, &phy[1]); + vnt_get_phy_field(priv, 14, vnt_get_cck_rate(priv, RATE_2M), + PK_TYPE_11B, &phy[1]); /*RSPINF_b_5*/ - vnt_get_phy_field(priv, 14, - vnt_get_cck_rate(priv, RATE_5M), PK_TYPE_11B, &phy[2]); + vnt_get_phy_field(priv, 14, vnt_get_cck_rate(priv, RATE_5M), + PK_TYPE_11B, &phy[2]); /*RSPINF_b_11*/ - vnt_get_phy_field(priv, 14, - vnt_get_cck_rate(priv, RATE_11M), PK_TYPE_11B, &phy[3]); + vnt_get_phy_field(priv, 14, vnt_get_cck_rate(priv, RATE_11M), + PK_TYPE_11B, &phy[3]); /*RSPINF_a_6*/ vnt_calculate_ofdm_rate(RATE_6M, bb_type, &tx_rate[0], &rsv_time[0]); @@ -300,19 +300,19 @@ void vnt_set_rspinf(struct vnt_private *priv, u8 bb_type) /*RSPINF_a_36*/ vnt_calculate_ofdm_rate(vnt_get_ofdm_rate(priv, RATE_36M), - bb_type, &tx_rate[5], &rsv_time[5]); + bb_type, &tx_rate[5], &rsv_time[5]); /*RSPINF_a_48*/ vnt_calculate_ofdm_rate(vnt_get_ofdm_rate(priv, RATE_48M), - bb_type, &tx_rate[6], &rsv_time[6]); + bb_type, &tx_rate[6], &rsv_time[6]); /*RSPINF_a_54*/ vnt_calculate_ofdm_rate(vnt_get_ofdm_rate(priv, RATE_54M), - bb_type, &tx_rate[7], &rsv_time[7]); + bb_type, &tx_rate[7], &rsv_time[7]); /*RSPINF_a_72*/ vnt_calculate_ofdm_rate(vnt_get_ofdm_rate(priv, RATE_54M), - bb_type, &tx_rate[8], &rsv_time[8]); + bb_type, &tx_rate[8], &rsv_time[8]); put_unaligned(phy[0].len, (u16 *)&data[0]); data[2] = phy[0].signal; @@ -335,8 +335,8 @@ void vnt_set_rspinf(struct vnt_private *priv, u8 bb_type) data[16 + i * 2 + 1] = rsv_time[i]; } - vnt_control_out(priv, MESSAGE_TYPE_WRITE, - MAC_REG_RSPINF_B_1, MESSAGE_REQUEST_MACREG, 34, &data[0]); + vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_RSPINF_B_1, + MESSAGE_REQUEST_MACREG, 34, &data[0]); } /* @@ -430,12 +430,12 @@ void vnt_update_ifs(struct vnt_private *priv) data[3] = (u8)priv->slot; vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_SIFS, - MESSAGE_REQUEST_MACREG, 4, &data[0]); + MESSAGE_REQUEST_MACREG, 4, &data[0]); max_min |= 0xa0; vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_CWMAXMIN0, - MESSAGE_REQUEST_MACREG, 1, &max_min); + MESSAGE_REQUEST_MACREG, 1, &max_min); } void vnt_update_top_rates(struct vnt_private *priv) @@ -532,7 +532,7 @@ u64 vnt_get_tsf_offset(u8 rx_rate, u64 tsf1, u64 tsf2) * */ void vnt_adjust_tsf(struct vnt_private *priv, u8 rx_rate, - u64 time_stamp, u64 local_tsf) + u64 time_stamp, u64 local_tsf) { u64 tsf_offset = 0; u8 data[8]; @@ -549,7 +549,7 @@ void vnt_adjust_tsf(struct vnt_private *priv, u8 rx_rate, data[7] = (u8)(tsf_offset >> 56); vnt_control_out(priv, MESSAGE_TYPE_SET_TSFTBTT, - MESSAGE_REQUEST_TSF, 0, 8, data); + MESSAGE_REQUEST_TSF, 0, 8, data); } /* * Description: Read NIC TSF counter @@ -658,7 +658,7 @@ void vnt_reset_next_tbtt(struct vnt_private *priv, u16 beacon_interval) data[7] = (u8)(next_tbtt >> 56); vnt_control_out(priv, MESSAGE_TYPE_SET_TSFTBTT, - MESSAGE_REQUEST_TBTT, 0, 8, data); + MESSAGE_REQUEST_TBTT, 0, 8, data); } /* @@ -677,7 +677,7 @@ void vnt_reset_next_tbtt(struct vnt_private *priv, u16 beacon_interval) * */ void vnt_update_next_tbtt(struct vnt_private *priv, u64 tsf, - u16 beacon_interval) + u16 beacon_interval) { u8 data[8]; @@ -722,7 +722,7 @@ int vnt_radio_power_off(struct vnt_private *priv) case RF_VT3226D0: case RF_VT3342A0: vnt_mac_reg_bits_off(priv, MAC_REG_SOFTPWRCTL, - (SOFTPWRCTL_SWPE2 | SOFTPWRCTL_SWPE3)); + (SOFTPWRCTL_SWPE2 | SOFTPWRCTL_SWPE3)); break; } @@ -763,7 +763,7 @@ int vnt_radio_power_on(struct vnt_private *priv) case RF_VT3226D0: case RF_VT3342A0: vnt_mac_reg_bits_on(priv, MAC_REG_SOFTPWRCTL, - (SOFTPWRCTL_SWPE2 | SOFTPWRCTL_SWPE3)); + (SOFTPWRCTL_SWPE2 | SOFTPWRCTL_SWPE3)); break; } @@ -796,7 +796,7 @@ void vnt_set_bss_mode(struct vnt_private *priv) priv->bb_vga[0] = 0x20; vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, - 0xe7, priv->bb_vga[0]); + 0xe7, priv->bb_vga[0]); } priv->bb_vga[2] = 0x10; @@ -806,7 +806,7 @@ void vnt_set_bss_mode(struct vnt_private *priv) priv->bb_vga[0] = 0x1c; vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, - 0xe7, priv->bb_vga[0]); + 0xe7, priv->bb_vga[0]); } priv->bb_vga[2] = 0x0; -- cgit v0.10.2 From 7b25c75e55979e4cd3381734719cfc1e62543f05 Mon Sep 17 00:00:00 2001 From: Rithvik Patibandla <rithvikp98@gmail.com> Date: Fri, 17 Jun 2016 09:21:28 +0530 Subject: staging:vt6656:card.c: fix blank lines issue Fix "Blank lines aren't necessary after an open brace" check thrown by checkpatch.pl Signed-off-by: Rithvik Patibandla <rithvikp98@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/vt6656/card.c b/drivers/staging/vt6656/card.c index fde48e5..7a10e8f 100644 --- a/drivers/staging/vt6656/card.c +++ b/drivers/staging/vt6656/card.c @@ -66,7 +66,6 @@ static const u16 cwRXBCNTSFOff[MAX_RATE] = { */ void vnt_set_channel(struct vnt_private *priv, u32 connection_channel) { - if (connection_channel > CB_MAX_CHANNEL || !connection_channel) return; @@ -168,7 +167,6 @@ static u16 vnt_get_ofdm_rate(struct vnt_private *priv, u16 rate_idx) static void vnt_calculate_ofdm_rate(u16 rate, u8 bb_type, u8 *tx_rate, u8 *rsv_time) { - switch (rate) { case RATE_6M: if (bb_type == BB_TYPE_11A) { @@ -479,7 +477,6 @@ int vnt_ofdm_min_rate(struct vnt_private *priv) u8 vnt_get_pkt_type(struct vnt_private *priv) { - if (priv->bb_type == BB_TYPE_11A || priv->bb_type == BB_TYPE_11B) return (u8)priv->bb_type; else if (vnt_ofdm_min_rate(priv)) @@ -566,7 +563,6 @@ void vnt_adjust_tsf(struct vnt_private *priv, u8 rx_rate, */ bool vnt_get_current_tsf(struct vnt_private *priv, u64 *current_tsf) { - *current_tsf = priv->current_tsf; return true; @@ -585,7 +581,6 @@ bool vnt_get_current_tsf(struct vnt_private *priv, u64 *current_tsf) */ bool vnt_clear_current_tsf(struct vnt_private *priv) { - vnt_mac_reg_bits_on(priv, MAC_REG_TFTCTL, TFTCTL_TSFCNTRST); priv->current_tsf = 0; -- cgit v0.10.2 From 6d898d6958bbe7bdc17192f1d825b0a0e55dc748 Mon Sep 17 00:00:00 2001 From: Rithvik Patibandla <rithvikp98@gmail.com> Date: Fri, 17 Jun 2016 09:23:42 +0530 Subject: staging:vt6656:card.c: fix blank line issue Fix "Please use a blank line after function declaration" check thrown by checkpatch.pl Signed-off-by: Rithvik Patibandla <rithvikp98@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/vt6656/card.c b/drivers/staging/vt6656/card.c index 7a10e8f..a3fa6d8 100644 --- a/drivers/staging/vt6656/card.c +++ b/drivers/staging/vt6656/card.c @@ -548,6 +548,7 @@ void vnt_adjust_tsf(struct vnt_private *priv, u8 rx_rate, vnt_control_out(priv, MESSAGE_TYPE_SET_TSFTBTT, MESSAGE_REQUEST_TSF, 0, 8, data); } + /* * Description: Read NIC TSF counter * Get local TSF counter -- cgit v0.10.2 From e7c856556aecea8fb560709fcdc3c188872ab474 Mon Sep 17 00:00:00 2001 From: Rithvik Patibandla <rithvikp98@gmail.com> Date: Fri, 17 Jun 2016 09:26:47 +0530 Subject: staging:vt6656:card.c: fix camel case issue Fix "Avoid camel case" issue thrown by checkpatch.pl Signed-off-by: Rithvik Patibandla <rithvikp98@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/vt6656/card.c b/drivers/staging/vt6656/card.c index a3fa6d8..53b469c 100644 --- a/drivers/staging/vt6656/card.c +++ b/drivers/staging/vt6656/card.c @@ -46,11 +46,11 @@ #include "key.h" #include "usbpipe.h" -/* const u16 cwRXBCNTSFOff[MAX_RATE] = +/* const u16 cw_rxbcntsf_off[MAX_RATE] = * {17, 34, 96, 192, 34, 23, 17, 11, 8, 5, 4, 3}; */ -static const u16 cwRXBCNTSFOff[MAX_RATE] = { +static const u16 cw_rxbcntsf_off[MAX_RATE] = { 192, 96, 34, 17, 34, 23, 17, 11, 8, 5, 4, 3 }; @@ -504,7 +504,7 @@ u64 vnt_get_tsf_offset(u8 rx_rate, u64 tsf1, u64 tsf2) u64 tsf_offset = 0; u16 rx_bcn_offset; - rx_bcn_offset = cwRXBCNTSFOff[rx_rate % MAX_RATE]; + rx_bcn_offset = cw_rxbcntsf_off[rx_rate % MAX_RATE]; tsf2 += (u64)rx_bcn_offset; -- cgit v0.10.2 From 1322739849a885fdf6733d85fd130996cdd586be Mon Sep 17 00:00:00 2001 From: Rithvik Patibandla <rithvikp98@gmail.com> Date: Fri, 17 Jun 2016 12:25:42 +0530 Subject: staging:vt6656:baseband.h: Fix alignment issue Fix "Alignment should match open paranthesis" check thrown by checkpatch.pl Signed-off-by: Rithvik Patibandla <rithvikp98@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/vt6656/baseband.h b/drivers/staging/vt6656/baseband.h index 807a580..7cc1387 100644 --- a/drivers/staging/vt6656/baseband.h +++ b/drivers/staging/vt6656/baseband.h @@ -84,10 +84,10 @@ struct vnt_phy_field { } __packed; unsigned int vnt_get_frame_time(u8 preamble_type, u8 pkt_type, - unsigned int frame_length, u16 tx_rate); + unsigned int frame_length, u16 tx_rate); void vnt_get_phy_field(struct vnt_private *, u32 frame_length, - u16 tx_rate, u8 pkt_type, struct vnt_phy_field *); + u16 tx_rate, u8 pkt_type, struct vnt_phy_field *); void vnt_set_short_slot_time(struct vnt_private *); void vnt_set_vga_gain_offset(struct vnt_private *, u8); -- cgit v0.10.2 From 87c3caa2e2b184264581589345a2611b337c1e85 Mon Sep 17 00:00:00 2001 From: Rithvik Patibandla <rithvikp98@gmail.com> Date: Mon, 27 Jun 2016 19:21:28 +0530 Subject: staging:vt6656:dpc.c:Fix parantheses alignment This patch fixes "Alignment should match open parantheses" check thrown by checkpatch.pl Signed-off-by: Rithvik Patibandla <rithvikp98@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c index 6019aac..2de6982 100644 --- a/drivers/staging/vt6656/dpc.c +++ b/drivers/staging/vt6656/dpc.c @@ -34,7 +34,7 @@ #include "rf.h" int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb, - unsigned long bytes_received) + unsigned long bytes_received) { struct ieee80211_hw *hw = priv->hw; struct ieee80211_supported_band *sband; @@ -87,10 +87,10 @@ int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb, /*Fix hardware bug => PLCP_Length error */ if (((bytes_received - (*pay_load_len)) > 27) || - ((bytes_received - (*pay_load_len)) < 24) || - (bytes_received < (*pay_load_len))) { + ((bytes_received - (*pay_load_len)) < 24) || + (bytes_received < (*pay_load_len))) { dev_dbg(&priv->usb->dev, "Wrong PLCP Length %x\n", - *pay_load_len); + *pay_load_len); return false; } -- cgit v0.10.2 From 0da18e48390bc84f6592efd8134c37a4e1f81d4f Mon Sep 17 00:00:00 2001 From: Rithvik Patibandla <rithvikp98@gmail.com> Date: Mon, 27 Jun 2016 19:26:55 +0530 Subject: staging:vt6656:dpc.c:Fix spaces The following patch fixes two checks thrown by checkpatch.pl, "Spaces preferred around '+'" and "No space is necessary after a cast" Signed-off-by: Rithvik Patibandla <rithvikp98@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c index 2de6982..c352c70 100644 --- a/drivers/staging/vt6656/dpc.c +++ b/drivers/staging/vt6656/dpc.c @@ -75,15 +75,15 @@ int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb, skb_data = (u8 *)skb->data; - rx_sts = skb_data+4; - rx_rate = skb_data+5; + rx_sts = skb_data + 4; + rx_rate = skb_data + 5; /* real Frame Size = USBframe_size -4WbkStatus - 4RxStatus */ /* -8TSF - 4RSR - 4SQ3 - ?Padding */ /* if SQ3 the range is 24~27, if no SQ3 the range is 20~23 */ - pay_load_len = (u16 *) (skb_data + 6); + pay_load_len = (u16 *)(skb_data + 6); /*Fix hardware bug => PLCP_Length error */ if (((bytes_received - (*pay_load_len)) > 27) || -- cgit v0.10.2 From 555d7a3ada1355981b897c159d7a2737863e876b Mon Sep 17 00:00:00 2001 From: Rithvik Patibandla <rithvikp98@gmail.com> Date: Mon, 27 Jun 2016 20:22:04 +0530 Subject: staging:vt6656:dpc.h:fix parantheses alignment The following patch fixes "Alignment should match open parantheses" check thrown by checkpatch.pl Signed-off-by: Rithvik Patibandla <rithvikp98@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/vt6656/dpc.h b/drivers/staging/vt6656/dpc.h index 5a92bd8..ff1850c 100644 --- a/drivers/staging/vt6656/dpc.h +++ b/drivers/staging/vt6656/dpc.h @@ -29,6 +29,6 @@ #include "device.h" int vnt_rx_data(struct vnt_private *, struct vnt_rcb *, - unsigned long bytes_received); + unsigned long bytes_received); #endif /* __RXTX_H__ */ -- cgit v0.10.2 From dd19b918f7b143ea4cf3c4fccd83be06cbc6122f Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Fri, 8 Jul 2016 18:22:37 -0400 Subject: staging: vt6655: channel.c: Fix block comments usage warning by checkpatch.pl This patch fixes the following checkpatch.pl warnings: WARNING: Block comments use * on subsequent lines + /* TX_PE will reserve 3 us for MAX2829 A mode only, + it is for better TX throughput */ WARNING: Block comments use a trailing */ on a separate line + it is for better TX throughput */ Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/vt6655/channel.c b/drivers/staging/vt6655/channel.c index b7d43a5..029a8df 100644 --- a/drivers/staging/vt6655/channel.c +++ b/drivers/staging/vt6655/channel.c @@ -193,7 +193,8 @@ bool set_channel(struct vnt_private *priv, struct ieee80211_channel *ch) MACvRegBitsOn(priv->PortOffset, MAC_REG_MACCR, MACCR_CLRNAV); /* TX_PE will reserve 3 us for MAX2829 A mode only, - it is for better TX throughput */ + * it is for better TX throughput + */ if (priv->byRFType == RF_AIROHA7230) RFbAL7230SelectChannelPostProcess(priv, priv->byCurrentCh, -- cgit v0.10.2 From 9877f9de5046309dd96af18585dbcfac4f4ab440 Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Fri, 8 Jul 2016 21:27:05 -0400 Subject: staging: vt6655: Fix checkpatch warning Fix warning by checkpatch.pl Add * for block comments on subsequent lines Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 4941640..ed12b5c 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -113,10 +113,10 @@ DEVICE_PARAM(ShortRetryLimit, "Short frame retry limits"); DEVICE_PARAM(LongRetryLimit, "long frame retry limits"); /* BasebandType[] baseband type selected - 0: indicate 802.11a type - 1: indicate 802.11b type - 2: indicate 802.11g type -*/ + * 0: indicate 802.11a type + * 1: indicate 802.11b type + * 2: indicate 802.11g type + */ #define BBP_TYPE_MIN 0 #define BBP_TYPE_MAX 2 #define BBP_TYPE_DEF 2 -- cgit v0.10.2 From bda457d42771e790c2f9be0b483f749b1f22eb2c Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Fri, 8 Jul 2016 21:33:08 -0400 Subject: staging: vt6655: power.c: Fix checkpatch warning Fix checkpatch.pl warning for trailing */ on a separate line Remove '+' postfix and '-' prefix from the start and end of block comments Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/vt6655/power.c b/drivers/staging/vt6655/power.c index bc8ca98..7d6e746 100644 --- a/drivers/staging/vt6655/power.c +++ b/drivers/staging/vt6655/power.c @@ -52,7 +52,7 @@ /*--------------------- Export Functions --------------------------*/ -/*+ +/* * * Routine Description: * Enable hw power saving functions @@ -60,7 +60,7 @@ * Return Value: * None. * - -*/ + */ void PSvEnablePowerSaving( @@ -104,7 +104,7 @@ PSvEnablePowerSaving( pr_debug("PS:Power Saving Mode Enable...\n"); } -/*+ +/* * * Routine Description: * Disable hw power saving functions @@ -112,7 +112,7 @@ PSvEnablePowerSaving( * Return Value: * None. * - -*/ + */ void PSvDisablePowerSaving( @@ -134,7 +134,7 @@ PSvDisablePowerSaving( } -/*+ +/* * * Routine Description: * Check if Next TBTT must wake up @@ -142,7 +142,7 @@ PSvDisablePowerSaving( * Return Value: * None. * - -*/ + */ bool PSbIsNextTBTTWakeUp( -- cgit v0.10.2 From 9d29f14db1095f52ca00b8162b242d6fce07d19f Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire <hofrat@osadl.org> Date: Mon, 25 Jul 2016 21:21:50 +0200 Subject: staging: ks7010: fix wait_for_completion_interruptible_timeout return handling wait_for_completion_interruptible_timeout return 0 on timeout and -ERESTARTSYS if interrupted. The check for !wait_for_completion_interruptible_timeout() would report an interrupt as timeout. Further, while HZ/50 will work most of the time it could fail for HZ < 50, so this is switched to msecs_to_jiffies(20). Fixes: 13a9930d15b4 ("staging: ks7010: add driver from Nanonote extra-repository") Signed-off-by: Nicholas Mc Guire <hofrat@osadl.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c index a8822fe..6deee46 100644 --- a/drivers/staging/ks7010/ks_hostif.c +++ b/drivers/staging/ks7010/ks_hostif.c @@ -74,11 +74,15 @@ void ks_wlan_hw_wakeup_task(struct work_struct *work) struct ks_wlan_private *priv = container_of(work, struct ks_wlan_private, ks_wlan_wakeup_task); int ps_status = atomic_read(&priv->psstatus.status); + long time_left; if (ps_status == PS_SNOOZE) { ks_wlan_hw_wakeup_request(priv); - if (!wait_for_completion_interruptible_timeout(&priv->psstatus.wakeup_wait, HZ / 50)) { /* 20ms timeout */ - DPRINTK(1, "wake up timeout !!!\n"); + time_left = wait_for_completion_interruptible_timeout( + &priv->psstatus.wakeup_wait, + msecs_to_jiffies(20)); + if (time_left <= 0) { + DPRINTK(1, "wake up timeout or interrupted !!!\n"); schedule_work(&priv->ks_wlan_wakeup_task); return; } -- cgit v0.10.2 From 9afe11e956766eaac4643adaaf49f223dd536c92 Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire <hofrat@osadl.org> Date: Mon, 25 Jul 2016 21:22:27 +0200 Subject: staging: ks7010: declare private functions static Private functions in ks_hostif.c can be declared static. Fixes: 13a9930d15b4 ("staging: ks7010: add driver from Nanonote extra-repository") Signed-off-by: Nicholas Mc Guire <hofrat@osadl.org> Reviewed-by: Wolfram Sang <wsa@the-dreams.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c index 6deee46..f4cee81 100644 --- a/drivers/staging/ks7010/ks_hostif.c +++ b/drivers/staging/ks7010/ks_hostif.c @@ -69,7 +69,7 @@ inline u32 get_DWORD(struct ks_wlan_private *priv) return data; } -void ks_wlan_hw_wakeup_task(struct work_struct *work) +static void ks_wlan_hw_wakeup_task(struct work_struct *work) { struct ks_wlan_private *priv = container_of(work, struct ks_wlan_private, ks_wlan_wakeup_task); @@ -1509,7 +1509,7 @@ void hostif_infrastructure_set_request(struct ks_wlan_private *priv) ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL); } -void hostif_infrastructure_set2_request(struct ks_wlan_private *priv) +static void hostif_infrastructure_set2_request(struct ks_wlan_private *priv) { struct hostif_infrastructure_set2_request_t *pp; uint16_t capability; -- cgit v0.10.2 From 95d2a324660ac46420b64481507dcedab7341dad Mon Sep 17 00:00:00 2001 From: Colin Ian King <colin.king@canonical.com> Date: Mon, 15 Aug 2016 15:45:04 +0100 Subject: staging: ks7010: don't print skb->dev->name if skb is null A null pointer dereference will occur when skb is null and skb->dev->name is printed. Replace the skb->dev->name with plain text "ks_wlan" to fix this. Signed-off-by: Colin Ian King <colin.king@canonical.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c index f4cee81..c5fc31c 100644 --- a/drivers/staging/ks7010/ks_hostif.c +++ b/drivers/staging/ks7010/ks_hostif.c @@ -485,8 +485,7 @@ void hostif_data_indication(struct ks_wlan_private *priv) netif_rx(skb); } else { printk(KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - skb->dev->name); + "ks_wlan: Memory squeeze, dropping packet.\n"); priv->nstats.rx_dropped++; } break; @@ -521,8 +520,7 @@ void hostif_data_indication(struct ks_wlan_private *priv) netif_rx(skb); } else { printk(KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - skb->dev->name); + "ks_wlan: Memory squeeze, dropping packet.\n"); priv->nstats.rx_dropped++; } break; -- cgit v0.10.2 From c84f5e2872c93fb78d3eb931a113cda42275ceae Mon Sep 17 00:00:00 2001 From: Binoy Jayan <binoy.jayan@linaro.org> Date: Mon, 6 Jun 2016 10:08:04 +0530 Subject: rtl8188eu: Replace semaphore cmd_queue_sema with completion The semaphore 'cmd_queue_sema' is used as completion, so convert it to struct completion. Signed-off-by: Binoy Jayan <binoy.jayan@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_cmd.c b/drivers/staging/rtl8188eu/core/rtw_cmd.c index 7748523..a2937e7 100644 --- a/drivers/staging/rtl8188eu/core/rtw_cmd.c +++ b/drivers/staging/rtl8188eu/core/rtw_cmd.c @@ -27,7 +27,7 @@ No irqsave is necessary. int rtw_init_cmd_priv(struct cmd_priv *pcmdpriv) { - sema_init(&(pcmdpriv->cmd_queue_sema), 0); + init_completion(&pcmdpriv->cmd_queue_comp); sema_init(&(pcmdpriv->terminate_cmdthread_sema), 0); _rtw_init_queue(&(pcmdpriv->cmd_queue)); @@ -122,7 +122,7 @@ u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) res = _rtw_enqueue_cmd(&pcmdpriv->cmd_queue, cmd_obj); if (res == _SUCCESS) - up(&pcmdpriv->cmd_queue_sema); + complete(&pcmdpriv->cmd_queue_comp); exit: @@ -167,7 +167,7 @@ int rtw_cmd_thread(void *context) RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("start r871x rtw_cmd_thread !!!!\n")); while (1) { - if (_rtw_down_sema(&pcmdpriv->cmd_queue_sema) == _FAIL) + if (wait_for_completion_interruptible(&pcmdpriv->cmd_queue_comp)) break; if (padapter->bDriverStopped || diff --git a/drivers/staging/rtl8188eu/include/rtw_cmd.h b/drivers/staging/rtl8188eu/include/rtw_cmd.h index 08ca592..3532dd1 100644 --- a/drivers/staging/rtl8188eu/include/rtw_cmd.h +++ b/drivers/staging/rtl8188eu/include/rtw_cmd.h @@ -39,7 +39,7 @@ struct cmd_obj { }; struct cmd_priv { - struct semaphore cmd_queue_sema; + struct completion cmd_queue_comp; struct semaphore terminate_cmdthread_sema; struct __queue cmd_queue; u8 cmdthd_running; diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c index ae2caff..a696d2b 100644 --- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c +++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c @@ -772,7 +772,7 @@ void rtw_stop_drv_threads(struct adapter *padapter) RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+rtw_stop_drv_threads\n")); /* Below is to terminate rtw_cmd_thread & event_thread... */ - up(&padapter->cmdpriv.cmd_queue_sema); + complete(&padapter->cmdpriv.cmd_queue_comp); if (padapter->cmdThread) _rtw_down_sema(&padapter->cmdpriv.terminate_cmdthread_sema); -- cgit v0.10.2 From 16677cca770d659434aaa860f12d418b68adac31 Mon Sep 17 00:00:00 2001 From: Binoy Jayan <binoy.jayan@linaro.org> Date: Mon, 6 Jun 2016 10:08:05 +0530 Subject: rtl8188eu: Replace semaphore terminate_cmdthread_sema with completion The semaphore 'terminate_cmdthread_sema' is used as completion, so convert it to struct completion. Signed-off-by: Binoy Jayan <binoy.jayan@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_cmd.c b/drivers/staging/rtl8188eu/core/rtw_cmd.c index a2937e7..9e12588 100644 --- a/drivers/staging/rtl8188eu/core/rtw_cmd.c +++ b/drivers/staging/rtl8188eu/core/rtw_cmd.c @@ -28,7 +28,7 @@ No irqsave is necessary. int rtw_init_cmd_priv(struct cmd_priv *pcmdpriv) { init_completion(&pcmdpriv->cmd_queue_comp); - sema_init(&(pcmdpriv->terminate_cmdthread_sema), 0); + init_completion(&pcmdpriv->terminate_cmdthread_comp); _rtw_init_queue(&(pcmdpriv->cmd_queue)); return _SUCCESS; @@ -162,7 +162,7 @@ int rtw_cmd_thread(void *context) allow_signal(SIGTERM); pcmdpriv->cmdthd_running = true; - up(&pcmdpriv->terminate_cmdthread_sema); + complete(&pcmdpriv->terminate_cmdthread_comp); RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("start r871x rtw_cmd_thread !!!!\n")); @@ -234,7 +234,7 @@ _next: rtw_free_cmd_obj(pcmd); } - up(&pcmdpriv->terminate_cmdthread_sema); + complete(&pcmdpriv->terminate_cmdthread_comp); complete_and_exit(NULL, 0); diff --git a/drivers/staging/rtl8188eu/include/rtw_cmd.h b/drivers/staging/rtl8188eu/include/rtw_cmd.h index 3532dd1..2b53f58 100644 --- a/drivers/staging/rtl8188eu/include/rtw_cmd.h +++ b/drivers/staging/rtl8188eu/include/rtw_cmd.h @@ -40,7 +40,7 @@ struct cmd_obj { struct cmd_priv { struct completion cmd_queue_comp; - struct semaphore terminate_cmdthread_sema; + struct completion terminate_cmdthread_comp; struct __queue cmd_queue; u8 cmdthd_running; struct adapter *padapter; diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c index a696d2b..c494845 100644 --- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c +++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c @@ -762,7 +762,7 @@ static int rtw_start_drv_threads(struct adapter *padapter) err = PTR_ERR(padapter->cmdThread); else /* wait for cmd_thread to run */ - _rtw_down_sema(&padapter->cmdpriv.terminate_cmdthread_sema); + wait_for_completion_interruptible(&padapter->cmdpriv.terminate_cmdthread_comp); return err; } @@ -774,7 +774,7 @@ void rtw_stop_drv_threads(struct adapter *padapter) /* Below is to terminate rtw_cmd_thread & event_thread... */ complete(&padapter->cmdpriv.cmd_queue_comp); if (padapter->cmdThread) - _rtw_down_sema(&padapter->cmdpriv.terminate_cmdthread_sema); + wait_for_completion_interruptible(&padapter->cmdpriv.terminate_cmdthread_comp); } -- cgit v0.10.2 From f18c566e4e1b9c95367d4f997c3c2d51a3559395 Mon Sep 17 00:00:00 2001 From: Binoy Jayan <binoy.jayan@linaro.org> Date: Mon, 6 Jun 2016 10:08:06 +0530 Subject: rtl8188eu: pwrctrl_priv: Replace semaphore 'lock' with mutex The semaphore 'lock' in pwrctrl_priv is a simple mutex, so it should be written as one. Semaphores are going away in the future. _enter_pwrlock was using down_interruptible(), so the lock could be broken by sending a signal. This could be a bug, because nothing checks the return code here. Hence, using mutex_lock instead of the interruptible version. Also, remove the now unused wrappers _init_pwrlock, _enter_pwrlock, _exit_pwrlock and _rtw_down_sema. Signed-off-by: Binoy Jayan <binoy.jayan@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c index 59c6d8a..0b70fe7 100644 --- a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c +++ b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c @@ -38,7 +38,7 @@ static int rtw_hw_suspend(struct adapter *padapter) LeaveAllPowerSaveMode(padapter); DBG_88E("==> rtw_hw_suspend\n"); - _enter_pwrlock(&pwrpriv->lock); + mutex_lock(&pwrpriv->mutex_lock); pwrpriv->bips_processing = true; /* s1. */ if (pnetdev) { @@ -73,7 +73,7 @@ static int rtw_hw_suspend(struct adapter *padapter) pwrpriv->rf_pwrstate = rf_off; pwrpriv->bips_processing = false; - _exit_pwrlock(&pwrpriv->lock); + mutex_unlock(&pwrpriv->mutex_lock); return 0; @@ -90,12 +90,12 @@ static int rtw_hw_resume(struct adapter *padapter) /* system resume */ DBG_88E("==> rtw_hw_resume\n"); - _enter_pwrlock(&pwrpriv->lock); + mutex_lock(&pwrpriv->mutex_lock); pwrpriv->bips_processing = true; rtw_reset_drv_sw(padapter); if (pm_netdev_open(pnetdev, false) != 0) { - _exit_pwrlock(&pwrpriv->lock); + mutex_unlock(&pwrpriv->mutex_lock); goto error_exit; } @@ -113,7 +113,7 @@ static int rtw_hw_resume(struct adapter *padapter) pwrpriv->rf_pwrstate = rf_on; pwrpriv->bips_processing = false; - _exit_pwrlock(&pwrpriv->lock); + mutex_unlock(&pwrpriv->mutex_lock); return 0; @@ -138,7 +138,7 @@ void ips_enter(struct adapter *padapter) return; } - _enter_pwrlock(&pwrpriv->lock); + mutex_lock(&pwrpriv->mutex_lock); pwrpriv->bips_processing = true; @@ -159,7 +159,7 @@ void ips_enter(struct adapter *padapter) } pwrpriv->bips_processing = false; - _exit_pwrlock(&pwrpriv->lock); + mutex_unlock(&pwrpriv->mutex_lock); } int ips_leave(struct adapter *padapter) @@ -171,7 +171,7 @@ int ips_leave(struct adapter *padapter) int keyid; - _enter_pwrlock(&pwrpriv->lock); + mutex_lock(&pwrpriv->mutex_lock); if ((pwrpriv->rf_pwrstate == rf_off) && (!pwrpriv->bips_processing)) { pwrpriv->bips_processing = true; @@ -205,7 +205,7 @@ int ips_leave(struct adapter *padapter) pwrpriv->bpower_saving = false; } - _exit_pwrlock(&pwrpriv->lock); + mutex_unlock(&pwrpriv->mutex_lock); return result; } @@ -504,7 +504,7 @@ void rtw_init_pwrctrl_priv(struct adapter *padapter) { struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; - _init_pwrlock(&pwrctrlpriv->lock); + mutex_init(&pwrctrlpriv->mutex_lock); pwrctrlpriv->rf_pwrstate = rf_on; pwrctrlpriv->ips_enter_cnts = 0; pwrctrlpriv->ips_leave_cnts = 0; diff --git a/drivers/staging/rtl8188eu/include/osdep_service.h b/drivers/staging/rtl8188eu/include/osdep_service.h index 5475956..c53c9ea 100644 --- a/drivers/staging/rtl8188eu/include/osdep_service.h +++ b/drivers/staging/rtl8188eu/include/osdep_service.h @@ -36,6 +36,7 @@ #include <linux/atomic.h> #include <linux/io.h> #include <linux/semaphore.h> +#include <linux/mutex.h> #include <linux/sem.h> #include <linux/sched.h> #include <linux/etherdevice.h> @@ -78,8 +79,6 @@ u8 *_rtw_malloc(u32 sz); void *rtw_malloc2d(int h, int w, int size); -u32 _rtw_down_sema(struct semaphore *sema); - void _rtw_init_queue(struct __queue *pqueue); struct rtw_netdev_priv_indicator { diff --git a/drivers/staging/rtl8188eu/include/rtw_event.h b/drivers/staging/rtl8188eu/include/rtw_event.h index 5c34e56..0dc63f2 100644 --- a/drivers/staging/rtl8188eu/include/rtw_event.h +++ b/drivers/staging/rtl8188eu/include/rtw_event.h @@ -19,6 +19,7 @@ #include <wlan_bssdef.h> #include <linux/semaphore.h> +#include <linux/mutex.h> #include <linux/sem.h> /* diff --git a/drivers/staging/rtl8188eu/include/rtw_pwrctrl.h b/drivers/staging/rtl8188eu/include/rtw_pwrctrl.h index 9680e2e..18a9e74 100644 --- a/drivers/staging/rtl8188eu/include/rtw_pwrctrl.h +++ b/drivers/staging/rtl8188eu/include/rtw_pwrctrl.h @@ -92,21 +92,6 @@ struct reportpwrstate_parm { unsigned short rsvd; }; -static inline void _init_pwrlock(struct semaphore *plock) -{ - sema_init(plock, 1); -} - -static inline void _enter_pwrlock(struct semaphore *plock) -{ - _rtw_down_sema(plock); -} - -static inline void _exit_pwrlock(struct semaphore *plock) -{ - up(plock); -} - #define LPS_DELAY_TIME 1*HZ /* 1 sec */ #define EXE_PWR_NONE 0x01 @@ -157,7 +142,7 @@ enum { /* for ips_mode */ }; struct pwrctrl_priv { - struct semaphore lock; + struct mutex mutex_lock; volatile u8 rpwm; /* requested power state for fw */ volatile u8 cpwm; /* fw current power state. updated when * 1. read from HCPWM 2. driver lowers power level */ diff --git a/drivers/staging/rtl8188eu/os_dep/osdep_service.c b/drivers/staging/rtl8188eu/os_dep/osdep_service.c index 764250b..24d1774 100644 --- a/drivers/staging/rtl8188eu/os_dep/osdep_service.c +++ b/drivers/staging/rtl8188eu/os_dep/osdep_service.c @@ -55,13 +55,6 @@ void *rtw_malloc2d(int h, int w, int size) return a; } -u32 _rtw_down_sema(struct semaphore *sema) -{ - if (down_interruptible(sema)) - return _FAIL; - return _SUCCESS; -} - void _rtw_init_queue(struct __queue *pqueue) { INIT_LIST_HEAD(&(pqueue->queue)); diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c index 11d51a3..a5ba1e4 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c @@ -238,7 +238,7 @@ static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message) rtw_cancel_all_timer(padapter); LeaveAllPowerSaveMode(padapter); - _enter_pwrlock(&pwrpriv->lock); + mutex_lock(&pwrpriv->mutex_lock); /* s1. */ if (pnetdev) { netif_carrier_off(pnetdev); @@ -267,7 +267,7 @@ static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message) rtw_free_network_queue(padapter, true); rtw_dev_unload(padapter); - _exit_pwrlock(&pwrpriv->lock); + mutex_unlock(&pwrpriv->mutex_lock); if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) rtw_indicate_scan_done(padapter, 1); @@ -298,7 +298,7 @@ static int rtw_resume_process(struct adapter *padapter) goto exit; } - _enter_pwrlock(&pwrpriv->lock); + mutex_lock(&pwrpriv->mutex_lock); rtw_reset_drv_sw(padapter); pwrpriv->bkeepfwalive = false; @@ -309,7 +309,7 @@ static int rtw_resume_process(struct adapter *padapter) netif_device_attach(pnetdev); netif_carrier_on(pnetdev); - _exit_pwrlock(&pwrpriv->lock); + mutex_unlock(&pwrpriv->mutex_lock); rtw_roaming(padapter, NULL); -- cgit v0.10.2 From 7fbf8f73edb147d9ce35f2f077a59c3283d5d6c2 Mon Sep 17 00:00:00 2001 From: Binoy Jayan <binoy.jayan@linaro.org> Date: Mon, 6 Jun 2016 10:08:07 +0530 Subject: rtl8188eu: Remove unused semaphores The semaphores xmit_sema, terminate_xmitthread_sema and tx_retevt have no users, hence remove all references to them. Signed-off-by: Binoy Jayan <binoy.jayan@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c index e0a5567..1e1b6d8 100644 --- a/drivers/staging/rtl8188eu/core/rtw_xmit.c +++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c @@ -57,8 +57,6 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) /* We don't need to memset padapter->XXX to zero, because adapter is allocated by vzalloc(). */ spin_lock_init(&pxmitpriv->lock); - sema_init(&pxmitpriv->xmit_sema, 0); - sema_init(&pxmitpriv->terminate_xmitthread_sema, 0); /* Please insert all the queue initializaiton using _rtw_init_queue below @@ -199,8 +197,6 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) pxmitpriv->txirp_cnt = 1; - sema_init(&(pxmitpriv->tx_retevt), 0); - /* per AC pending irp */ pxmitpriv->beq_cnt = 0; pxmitpriv->bkq_cnt = 0; diff --git a/drivers/staging/rtl8188eu/include/osdep_service.h b/drivers/staging/rtl8188eu/include/osdep_service.h index c53c9ea..6f6a8f8 100644 --- a/drivers/staging/rtl8188eu/include/osdep_service.h +++ b/drivers/staging/rtl8188eu/include/osdep_service.h @@ -35,7 +35,6 @@ #include <asm/byteorder.h> #include <linux/atomic.h> #include <linux/io.h> -#include <linux/semaphore.h> #include <linux/mutex.h> #include <linux/sem.h> #include <linux/sched.h> diff --git a/drivers/staging/rtl8188eu/include/rtw_event.h b/drivers/staging/rtl8188eu/include/rtw_event.h index 0dc63f2..2a45581 100644 --- a/drivers/staging/rtl8188eu/include/rtw_event.h +++ b/drivers/staging/rtl8188eu/include/rtw_event.h @@ -18,7 +18,6 @@ #include <osdep_service.h> #include <wlan_bssdef.h> -#include <linux/semaphore.h> #include <linux/mutex.h> #include <linux/sem.h> diff --git a/drivers/staging/rtl8188eu/include/rtw_xmit.h b/drivers/staging/rtl8188eu/include/rtw_xmit.h index a0853ba..7895008 100644 --- a/drivers/staging/rtl8188eu/include/rtw_xmit.h +++ b/drivers/staging/rtl8188eu/include/rtw_xmit.h @@ -263,8 +263,6 @@ struct agg_pkt_info { struct xmit_priv { spinlock_t lock; - struct semaphore xmit_sema; - struct semaphore terminate_xmitthread_sema; struct __queue be_pending; struct __queue bk_pending; struct __queue vi_pending; @@ -289,7 +287,6 @@ struct xmit_priv { u8 wmm_para_seq[4];/* sequence for wmm ac parameter strength * from large to small. it's value is 0->vo, * 1->vi, 2->be, 3->bk. */ - struct semaphore tx_retevt;/* all tx return event; */ u8 txirp_cnt;/* */ struct tasklet_struct xmit_tasklet; /* per AC pending irp */ -- cgit v0.10.2 From 0cdec5a4508398870b5c361a0aa993ee7fcd572c Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Mon, 20 Jun 2016 12:26:51 +0700 Subject: staging: rtl8188eu: replace EFUSE_GetEfuseDefinition(..., TYPE_EFUSE_MAP_LEN, ...) call with it's result (EFUSE_MAP_LEN_88E) This makes the code easier to read. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c index fbce1f7..eee0e13 100644 --- a/drivers/staging/rtl8188eu/core/rtw_efuse.c +++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c @@ -846,12 +846,7 @@ hal_EfusePgCheckAvailableAddr( u8 efuseType ) { - u16 efuse_max_available_len = 0; - - /* Change to check TYPE_EFUSE_MAP_LEN , because 8188E raw 256, logic map over 256. */ - EFUSE_GetEfuseDefinition(pAdapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&efuse_max_available_len); - - if (Efuse_GetCurrentSize(pAdapter) >= efuse_max_available_len) + if (Efuse_GetCurrentSize(pAdapter) >= EFUSE_MAP_LEN_88E) return false; return true; } @@ -977,13 +972,9 @@ void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata) */ static void Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse) { - u16 mapLen = 0; - Efuse_PowerSwitch(pAdapter, false, true); - EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen); - - efuse_ReadEFuse(pAdapter, efuseType, 0, mapLen, Efuse); + efuse_ReadEFuse(pAdapter, efuseType, 0, EFUSE_MAP_LEN_88E, Efuse); Efuse_PowerSwitch(pAdapter, false, false); } @@ -996,12 +987,9 @@ void EFUSE_ShadowMapUpdate( u8 efuseType) { struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter); - u16 mapLen = 0; - - EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen); if (pEEPROM->bautoload_fail_flag) - memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen); + memset(pEEPROM->efuse_eeprom_data, 0xFF, EFUSE_MAP_LEN_88E); else Efuse_ReadAllMap(pAdapter, efuseType, pEEPROM->efuse_eeprom_data); } -- cgit v0.10.2 From 28d040fb7243926a1e485dc5f6dee1a2ea8cb6ab Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Mon, 20 Jun 2016 12:27:37 +0700 Subject: staging: rtl8188eu: remove efuse_max variable in hal_EfusePartialWriteCheck This variable does not used after assigning value. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c index eee0e13..d18ea6c 100644 --- a/drivers/staging/rtl8188eu/core/rtw_efuse.c +++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c @@ -769,11 +769,10 @@ static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u bool bRet = false; u8 i, efuse_data = 0, cur_header = 0; u8 matched_wden = 0, badworden = 0; - u16 startAddr = 0, efuse_max_available_len = 0, efuse_max = 0; + u16 startAddr = 0, efuse_max_available_len = 0; struct pgpkt curPkt; EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_BANK, (void *)&efuse_max_available_len); - EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&efuse_max); rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&startAddr); startAddr %= EFUSE_REAL_CONTENT_LEN; -- cgit v0.10.2 From f573fed71213aec86c0b8ef6941a45a5e9dee7f1 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Mon, 20 Jun 2016 12:28:20 +0700 Subject: staging: rtl8188eu: replace EFUSE_GetEfuseDefinition(..., TYPE_EFUSE_MAX_SECTION, &a) with a = EFUSE_MAX_SECTION_88E This makes the code easier to read. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c index d18ea6c..550a89d 100644 --- a/drivers/staging/rtl8188eu/core/rtw_efuse.c +++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c @@ -483,14 +483,11 @@ int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data) u8 hoffset = 0, hworden = 0; u8 tmpidx = 0; u8 tmpdata[8]; - u8 max_section = 0; u8 tmp_header = 0; - EFUSE_GetEfuseDefinition(pAdapter, EFUSE_WIFI, TYPE_EFUSE_MAX_SECTION, (void *)&max_section); - if (!data) return false; - if (offset > max_section) + if (offset > EFUSE_MAX_SECTION_88E) return false; memset(data, 0xff, sizeof(u8) * PGPKT_DATA_SIZE); -- cgit v0.10.2 From 054bf87c90e75a0187fbb08e6c9b281286e7a039 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Mon, 20 Jun 2016 12:28:43 +0700 Subject: staging: rtl8188eu: replace EFUSE_GetEfuseDefinition(..., TYPE_AVAILABLE_EFUSE_BYTES_BANK, &a) call with a = (EFUSE_REAL_CONTENT_LEN_88E - EFUSE_OOB_PROTECT_BYTES_88E) This makes the code easier to read. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c index 550a89d..b161b43 100644 --- a/drivers/staging/rtl8188eu/core/rtw_efuse.c +++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c @@ -588,12 +588,12 @@ static bool hal_EfuseFixHeaderProcess(struct adapter *pAdapter, u8 efuseType, st static bool hal_EfusePgPacketWrite2ByteHeader(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt) { bool bRet = false; - u16 efuse_addr = *pAddr, efuse_max_available_len = 0; + u16 efuse_addr = *pAddr; + u16 efuse_max_available_len = + EFUSE_REAL_CONTENT_LEN_88E - EFUSE_OOB_PROTECT_BYTES_88E; u8 pg_header = 0, tmp_header = 0, pg_header_temp = 0; u8 repeatcnt = 0; - EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_BANK, (void *)&efuse_max_available_len); - while (efuse_addr < efuse_max_available_len) { pg_header = ((pTargetPkt->offset & 0x07) << 5) | 0x0F; efuse_OneByteWrite(pAdapter, efuse_addr, pg_header); @@ -766,11 +766,11 @@ static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u bool bRet = false; u8 i, efuse_data = 0, cur_header = 0; u8 matched_wden = 0, badworden = 0; - u16 startAddr = 0, efuse_max_available_len = 0; + u16 startAddr = 0; + u16 efuse_max_available_len = + EFUSE_REAL_CONTENT_LEN_88E - EFUSE_OOB_PROTECT_BYTES_88E; struct pgpkt curPkt; - EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_BANK, (void *)&efuse_max_available_len); - rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&startAddr); startAddr %= EFUSE_REAL_CONTENT_LEN; -- cgit v0.10.2 From 9de204cd59d597c558443afebef937a081a512ca Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Mon, 20 Jun 2016 12:29:02 +0700 Subject: staging: rtl8188eu: remove EFUSE_GetEfuseDefinition function This function does not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c index b161b43..16cc770 100644 --- a/drivers/staging/rtl8188eu/core/rtw_efuse.c +++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c @@ -317,69 +317,6 @@ void efuse_ReadEFuse(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _si } } -/* Do not support BT */ -void EFUSE_GetEfuseDefinition(struct adapter *pAdapter, u8 efuseType, u8 type, void *pOut) -{ - switch (type) { - case TYPE_EFUSE_MAX_SECTION: - { - u8 *pMax_section; - pMax_section = pOut; - *pMax_section = EFUSE_MAX_SECTION_88E; - } - break; - case TYPE_EFUSE_REAL_CONTENT_LEN: - { - u16 *pu2Tmp; - pu2Tmp = pOut; - *pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E; - } - break; - case TYPE_EFUSE_CONTENT_LEN_BANK: - { - u16 *pu2Tmp; - pu2Tmp = pOut; - *pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E; - } - break; - case TYPE_AVAILABLE_EFUSE_BYTES_BANK: - { - u16 *pu2Tmp; - pu2Tmp = pOut; - *pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E-EFUSE_OOB_PROTECT_BYTES_88E); - } - break; - case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL: - { - u16 *pu2Tmp; - pu2Tmp = pOut; - *pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E-EFUSE_OOB_PROTECT_BYTES_88E); - } - break; - case TYPE_EFUSE_MAP_LEN: - { - u16 *pu2Tmp; - pu2Tmp = pOut; - *pu2Tmp = (u16)EFUSE_MAP_LEN_88E; - } - break; - case TYPE_EFUSE_PROTECT_BYTES_BANK: - { - u8 *pu1Tmp; - pu1Tmp = pOut; - *pu1Tmp = (u8)(EFUSE_OOB_PROTECT_BYTES_88E); - } - break; - default: - { - u8 *pu1Tmp; - pu1Tmp = pOut; - *pu1Tmp = 0; - } - break; - } -} - u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data) { u16 tmpaddr = 0; diff --git a/drivers/staging/rtl8188eu/include/rtw_efuse.h b/drivers/staging/rtl8188eu/include/rtw_efuse.h index 9bfb10c..9e7d135 100644 --- a/drivers/staging/rtl8188eu/include/rtw_efuse.h +++ b/drivers/staging/rtl8188eu/include/rtw_efuse.h @@ -95,8 +95,6 @@ struct efuse_hal { }; u8 Efuse_CalculateWordCnts(u8 word_en); -void EFUSE_GetEfuseDefinition(struct adapter *adapt, u8 type, u8 type1, - void *out); u8 efuse_OneByteRead(struct adapter *adapter, u16 addr, u8 *data); u8 efuse_OneByteWrite(struct adapter *adapter, u16 addr, u8 data); -- cgit v0.10.2 From a0693e22d1a300a950f35edea6039fa0cf441414 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Mon, 20 Jun 2016 12:29:30 +0700 Subject: staging: rtl8188eu: remove _EFUSE_DEF_TYPE enum This enumeration does not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/rtw_efuse.h b/drivers/staging/rtl8188eu/include/rtw_efuse.h index 9e7d135..168c12d 100644 --- a/drivers/staging/rtl8188eu/include/rtw_efuse.h +++ b/drivers/staging/rtl8188eu/include/rtw_efuse.h @@ -34,16 +34,6 @@ #define EFUSE_WIFI 0 #define EFUSE_BT 1 -enum _EFUSE_DEF_TYPE { - TYPE_EFUSE_MAX_SECTION = 0, - TYPE_EFUSE_REAL_CONTENT_LEN = 1, - TYPE_AVAILABLE_EFUSE_BYTES_BANK = 2, - TYPE_AVAILABLE_EFUSE_BYTES_TOTAL = 3, - TYPE_EFUSE_MAP_LEN = 4, - TYPE_EFUSE_PROTECT_BYTES_BANK = 5, - TYPE_EFUSE_CONTENT_LEN_BANK = 6, -}; - /* E-Fuse */ #define EFUSE_MAP_SIZE 512 #define EFUSE_MAX_SIZE 256 -- cgit v0.10.2 From f352a9eeb15e696cbfc470a26e1cc9d44b4df092 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann <arnd@arndb.de> Date: Wed, 20 Jul 2016 17:13:58 +0200 Subject: staging/rtl8192u: use s8 instead of char Compiling the rtlwifi drivers for ARM with gcc -Wextra warns about lots of incorrect code that results from 'char' being unsigned here, e.g. staging/rtl8192u/r8192U_core.c:4150:16: error: comparison is always false due to limited range of data type [-Werror=type-limits] staging/rtl8192u/r8192U_dm.c:646:50: error: comparison is always false due to limited range of data type [-Werror=type-limits] This patch changes all uses of 'char' in this driver that refer to 8-bit integers to use 's8' instead, which is signed on all architectures. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Jes Sorensen <Jes.Sorensen@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h index 09e9499..077ea13 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h @@ -746,7 +746,7 @@ struct ieee80211_rx_stats { bool bisrxaggrsubframe; bool bPacketBeacon; //cosa add for rssi bool bToSelfBA; //cosa add for rssi - char cck_adc_pwdb[4]; //cosa add for rx path selection + s8 cck_adc_pwdb[4]; //cosa add for rx path selection u16 Seq_Num; }; @@ -1814,7 +1814,7 @@ struct ieee80211_device { u32 wpax_type_notify; //{added by David, 2006.9.26} /* QoS related flag */ - char init_wmmparam_flag; + s8 init_wmmparam_flag; /* set on initialization */ u8 qos_support; diff --git a/drivers/staging/rtl8192u/r8192U.h b/drivers/staging/rtl8192u/r8192U.h index 821afc0..0b7b04e 100644 --- a/drivers/staging/rtl8192u/r8192U.h +++ b/drivers/staging/rtl8192u/r8192U.h @@ -533,7 +533,7 @@ typedef struct _rt_9x_tx_rate_history { u32 ht_mcs[4][16]; } rt_tx_rahis_t, *prt_tx_rahis_t; typedef struct _RT_SMOOTH_DATA_4RF { - char elements[4][100]; /* array to store values */ + s8 elements[4][100]; /* array to store values */ u32 index; /* index to current array to store */ u32 TotalNum; /* num of valid elements */ u32 TotalVal[4]; /* sum of valid elements */ @@ -1031,7 +1031,7 @@ typedef struct r8192_priv { s8 cck_present_attentuation; u8 cck_present_attentuation_20Mdefault; u8 cck_present_attentuation_40Mdefault; - char cck_present_attentuation_difference; + s8 cck_present_attentuation_difference; bool btxpower_tracking; bool bcck_in_ch14; bool btxpowerdata_readfromEEPORM; diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c index 7af1af8..b86b28a 100644 --- a/drivers/staging/rtl8192u/r8192U_core.c +++ b/drivers/staging/rtl8192u/r8192U_core.c @@ -4206,7 +4206,7 @@ static void rtl8192_process_phyinfo(struct r8192_priv *priv, u8 *buffer, * * Return: 0-100 percentage *---------------------------------------------------------------------------*/ -static u8 rtl819x_query_rxpwrpercentage(char antpower) +static u8 rtl819x_query_rxpwrpercentage(s8 antpower) { if ((antpower <= -100) || (antpower >= 20)) return 0; @@ -4217,9 +4217,9 @@ static u8 rtl819x_query_rxpwrpercentage(char antpower) } /* QueryRxPwrPercentage */ -static u8 rtl819x_evm_dbtopercentage(char value) +static u8 rtl819x_evm_dbtopercentage(s8 value) { - char ret_val; + s8 ret_val; ret_val = value; @@ -4294,8 +4294,8 @@ static void rtl8192_query_rxphystatus(struct r8192_priv *priv, phy_ofdm_rx_status_rxsc_sgien_exintfflag *prxsc; u8 *prxpkt; u8 i, max_spatial_stream, tmp_rxsnr, tmp_rxevm, rxsc_sgien_exflg; - char rx_pwr[4], rx_pwr_all = 0; - char rx_snrX, rx_evmX; + s8 rx_pwr[4], rx_pwr_all = 0; + s8 rx_snrX, rx_evmX; u8 evm, pwdb_all; u32 RSSI, total_rssi = 0; u8 is_cck_rate = 0; @@ -4420,7 +4420,7 @@ static void rtl8192_query_rxphystatus(struct r8192_priv *priv, /* Get Rx snr value in DB */ tmp_rxsnr = pofdm_buf->rxsnr_X[i]; - rx_snrX = (char)(tmp_rxsnr); + rx_snrX = (s8)(tmp_rxsnr); rx_snrX /= 2; priv->stats.rxSNRdB[i] = (long)rx_snrX; @@ -4454,7 +4454,7 @@ static void rtl8192_query_rxphystatus(struct r8192_priv *priv, for (i = 0; i < max_spatial_stream; i++) { tmp_rxevm = pofdm_buf->rxevm_X[i]; - rx_evmX = (char)(tmp_rxevm); + rx_evmX = (s8)(tmp_rxevm); /* Do not use shift operation like "rx_evmX >>= 1" * because the compiler of free build environment will -- cgit v0.10.2 From 5d5fd353740ffe30bfb2797bc8534d7f95871c93 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann <arnd@arndb.de> Date: Wed, 20 Jul 2016 17:26:05 +0200 Subject: staging/rtl8192e: use s8 instead of char Compiling the rtlwifi drivers for ARM with gcc -Wextra warns about lots of incorrect code that results from 'char' being unsigned here, e.g. staging/rtl8192e/rtl8192e/r8192E_phy.c:1072:36: error: comparison is always false due to limited range of data type [-Werror=type-limits] staging/rtl8192e/rtl8192e/r8192E_phy.c:1104:36: error: comparison is always false due to limited range of data type [-Werror=type-limits] staging/rtl8192e/rtl8192e/rtl_core.c:1987:16: error: comparison is always false due to limited range of data type [-Werror=type-limits] staging/rtl8192e/rtl8192e/rtl_dm.c:782:37: error: comparison is always false due to limited range of data type [-Werror=type-limits] staging/rtl8192e/rtllib_softmac_wx.c:465:16: error: comparison is always false due to limited range of data type [-Werror=type-limits] This patch changes all uses of 'char' in this driver that refer to 8-bit integers to use 's8' instead, which is signed on all architectures. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Jes Sorensen <Jes.Sorensen@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c index ba64a4f..8d6bca6 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c @@ -1487,8 +1487,8 @@ static void _rtl92e_query_rxphystatus( struct phy_ofdm_rx_status_rxsc_sgien_exintfflag *prxsc; u8 *prxpkt; u8 i, max_spatial_stream, tmp_rxsnr, tmp_rxevm, rxsc_sgien_exflg; - char rx_pwr[4], rx_pwr_all = 0; - char rx_snrX, rx_evmX; + s8 rx_pwr[4], rx_pwr_all = 0; + s8 rx_snrX, rx_evmX; u8 evm, pwdb_all; u32 RSSI, total_rssi = 0; u8 is_cck_rate = 0; @@ -1613,7 +1613,7 @@ static void _rtl92e_query_rxphystatus( 2) - 110; tmp_rxsnr = pofdm_buf->rxsnr_X[i]; - rx_snrX = (char)(tmp_rxsnr); + rx_snrX = (s8)(tmp_rxsnr); rx_snrX /= 2; priv->stats.rxSNRdB[i] = (long)rx_snrX; @@ -1643,7 +1643,7 @@ static void _rtl92e_query_rxphystatus( for (i = 0; i < max_spatial_stream; i++) { tmp_rxevm = pofdm_buf->rxevm_X[i]; - rx_evmX = (char)(tmp_rxevm); + rx_evmX = (s8)(tmp_rxevm); rx_evmX /= 2; diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c index 5e3bbe5..0698131 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c @@ -630,7 +630,7 @@ void rtl92e_set_tx_power(struct net_device *dev, u8 channel) { struct r8192_priv *priv = rtllib_priv(dev); u8 powerlevel = 0, powerlevelOFDM24G = 0; - char ant_pwr_diff; + s8 ant_pwr_diff; u32 u4RegValue; if (priv->epromtype == EEPROM_93C46) { diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c index 13a5ddc..41e05f2 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c @@ -1982,7 +1982,7 @@ void rtl92e_update_rx_statistics(struct r8192_priv *priv, weighting) / 6; } -u8 rtl92e_rx_db_to_percent(char antpower) +u8 rtl92e_rx_db_to_percent(s8 antpower) { if ((antpower <= -100) || (antpower >= 20)) return 0; @@ -1993,9 +1993,9 @@ u8 rtl92e_rx_db_to_percent(char antpower) } /* QueryRxPwrPercentage */ -u8 rtl92e_evm_db_to_percent(char value) +u8 rtl92e_evm_db_to_percent(s8 value) { - char ret_val; + s8 ret_val; ret_val = value; diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h index f627fdc..6921125 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h @@ -503,8 +503,8 @@ struct r8192_priv { u32 Pwr_Track; u8 CCKPresentAttentuation_20Mdefault; u8 CCKPresentAttentuation_40Mdefault; - char CCKPresentAttentuation_difference; - char CCKPresentAttentuation; + s8 CCKPresentAttentuation_difference; + s8 CCKPresentAttentuation; long undecorated_smoothed_pwdb; u32 MCSTxPowerLevelOriginalOffset[6]; @@ -604,8 +604,8 @@ void rtl92e_update_rx_pkt_timestamp(struct net_device *dev, long rtl92e_translate_to_dbm(struct r8192_priv *priv, u8 signal_strength_index); void rtl92e_update_rx_statistics(struct r8192_priv *priv, struct rtllib_rx_stats *pprevious_stats); -u8 rtl92e_evm_db_to_percent(char value); -u8 rtl92e_rx_db_to_percent(char antpower); +u8 rtl92e_evm_db_to_percent(s8 value); +u8 rtl92e_rx_db_to_percent(s8 antpower); void rtl92e_copy_mpdu_stats(struct rtllib_rx_stats *psrc_stats, struct rtllib_rx_stats *ptarget_stats); bool rtl92e_enable_nic(struct net_device *dev); -- cgit v0.10.2 From fd181f7d5a53eb73ba7276d95ecdaff9605d63c2 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann <arnd@arndb.de> Date: Wed, 20 Jul 2016 17:26:06 +0200 Subject: staging/rtl8192e: avoid comparing unsigned type >= 0 There is one remaining warning about a type limit check in rtl8192e: staging/rtl8192e/rtl819x_TSProc.c:326:14: error: comparison is always true due to limited range of data type [-Werror=type-limits] This changes a macro into a local function to clarify the types and simplify the check while removing the warning. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Jes Sorensen <Jes.Sorensen@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8192e/rtl819x_Qos.h b/drivers/staging/rtl8192e/rtl819x_Qos.h index 463122d..61da8f7 100644 --- a/drivers/staging/rtl8192e/rtl819x_Qos.h +++ b/drivers/staging/rtl8192e/rtl819x_Qos.h @@ -169,9 +169,6 @@ union qos_tclas { } TYPE2_8021Q; }; -#define IsACValid(ac) ((ac >= 0 && ac <= 7) ? true : false) - - union aci_aifsn { u8 charData; diff --git a/drivers/staging/rtl8192e/rtl819x_TSProc.c b/drivers/staging/rtl8192e/rtl819x_TSProc.c index 2c8a526..a966a8e 100644 --- a/drivers/staging/rtl8192e/rtl819x_TSProc.c +++ b/drivers/staging/rtl8192e/rtl819x_TSProc.c @@ -306,6 +306,11 @@ static void MakeTSEntry(struct ts_common_info *pTsCommonInfo, u8 *Addr, pTsCommonInfo->TClasNum = TCLAS_Num; } +static bool IsACValid(unsigned int tid) +{ + return tid < 7; +} + bool GetTs(struct rtllib_device *ieee, struct ts_common_info **ppTS, u8 *Addr, u8 TID, enum tr_select TxRxSelect, bool bAddNewTs) { -- cgit v0.10.2 From 9afa937047b5c3dca3ed0bb6361eac06073c3efa Mon Sep 17 00:00:00 2001 From: Binoy Jayan <binoy.jayan@linaro.org> Date: Wed, 1 Jun 2016 14:56:52 +0530 Subject: rtl8192e: rtllib_device: Replace semaphore wx_sem with mutex The semaphore 'wx_sem' in the rtllib_device is a simple mutex, so it should be written as one. Semaphores are going away in the future. Signed-off-by: Binoy Jayan <binoy.jayan@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c index 41e05f2..f9e7a51 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c @@ -1277,14 +1277,14 @@ RESET_START: rtllib_stop_scan_syncro(ieee); if (ieee->state == RTLLIB_LINKED) { - SEM_DOWN_IEEE_WX(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); netdev_info(dev, "ieee->state is RTLLIB_LINKED\n"); rtllib_stop_send_beacons(priv->rtllib); del_timer_sync(&ieee->associate_timer); cancel_delayed_work(&ieee->associate_retry_wq); rtllib_stop_scan(ieee); netif_carrier_off(dev); - SEM_UP_IEEE_WX(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); } else { netdev_info(dev, "ieee->state is NOT LINKED\n"); rtllib_softmac_stop_protocol(priv->rtllib, 0, true); diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h index 776e179..513dd61 100644 --- a/drivers/staging/rtl8192e/rtllib.h +++ b/drivers/staging/rtl8192e/rtllib.h @@ -31,6 +31,7 @@ #include <linux/timer.h> #include <linux/sched.h> #include <linux/semaphore.h> +#include <linux/mutex.h> #include <linux/delay.h> #include <linux/wireless.h> @@ -1651,7 +1652,7 @@ struct rtllib_device { short proto_started; short proto_stoppping; - struct semaphore wx_sem; + struct mutex wx_mutex; struct semaphore scan_sem; struct semaphore ips_sem; @@ -2212,7 +2213,5 @@ void rtllib_indicate_packets(struct rtllib_device *ieee, void HTUseDefaultSetting(struct rtllib_device *ieee); #define RT_ASOC_RETRY_LIMIT 5 u8 MgntQuery_TxRateExcludeCCKRates(struct rtllib_device *ieee); -#define SEM_DOWN_IEEE_WX(psem) down(psem) -#define SEM_UP_IEEE_WX(psem) up(psem) #endif /* RTLLIB_H */ diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c index 62154e3..901cc50 100644 --- a/drivers/staging/rtl8192e/rtllib_softmac.c +++ b/drivers/staging/rtl8192e/rtllib_softmac.c @@ -753,7 +753,7 @@ static void rtllib_start_scan(struct rtllib_device *ieee) } } -/* called with wx_sem held */ +/* called with wx_mutex held */ void rtllib_start_scan_syncro(struct rtllib_device *ieee, u8 is_mesh) { if (IS_DOT11D_ENABLE(ieee)) { @@ -1590,7 +1590,7 @@ static void rtllib_associate_procedure_wq(void *data) rtllib_stop_scan_syncro(ieee); if (ieee->rtllib_ips_leave != NULL) ieee->rtllib_ips_leave(ieee->dev); - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); if (ieee->data_hard_stop) ieee->data_hard_stop(ieee->dev); @@ -1605,14 +1605,14 @@ static void rtllib_associate_procedure_wq(void *data) __func__); if (ieee->rtllib_ips_leave_wq != NULL) ieee->rtllib_ips_leave_wq(ieee->dev); - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); return; } ieee->associate_seq = 1; rtllib_associate_step1(ieee, ieee->current_network.bssid); - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); } inline void rtllib_softmac_new_net(struct rtllib_device *ieee, @@ -2582,16 +2582,16 @@ static void rtllib_start_ibss_wq(void *data) struct rtllib_device, start_ibss_wq); /* iwconfig mode ad-hoc will schedule this and return * on the other hand this will block further iwconfig SET - * operations because of the wx_sem hold. + * operations because of the wx_mutex hold. * Anyway some most set operations set a flag to speed-up * (abort) this wq (when syncro scanning) before sleeping - * on the semaphore + * on the mutex */ if (!ieee->proto_started) { netdev_info(ieee->dev, "==========oh driver down return\n"); return; } - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); if (ieee->current_network.ssid_len == 0) { strcpy(ieee->current_network.ssid, RTLLIB_DEFAULT_TX_ESSID); @@ -2703,7 +2703,7 @@ static void rtllib_start_ibss_wq(void *data) netif_carrier_on(ieee->dev); - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); } inline void rtllib_start_ibss(struct rtllib_device *ieee) @@ -2711,7 +2711,7 @@ inline void rtllib_start_ibss(struct rtllib_device *ieee) schedule_delayed_work(&ieee->start_ibss_wq, msecs_to_jiffies(150)); } -/* this is called only in user context, with wx_sem held */ +/* this is called only in user context, with wx_mutex held */ static void rtllib_start_bss(struct rtllib_device *ieee) { unsigned long flags; @@ -2773,7 +2773,7 @@ static void rtllib_associate_retry_wq(void *data) struct rtllib_device, associate_retry_wq); unsigned long flags; - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); if (!ieee->proto_started) goto exit; @@ -2806,7 +2806,7 @@ static void rtllib_associate_retry_wq(void *data) ieee->beinretry = false; exit: - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); } static struct sk_buff *rtllib_get_beacon_(struct rtllib_device *ieee) @@ -2853,9 +2853,9 @@ void rtllib_softmac_stop_protocol(struct rtllib_device *ieee, u8 mesh_flag, u8 shutdown) { rtllib_stop_scan_syncro(ieee); - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); rtllib_stop_protocol(ieee, shutdown); - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); } EXPORT_SYMBOL(rtllib_softmac_stop_protocol); @@ -2902,9 +2902,9 @@ void rtllib_stop_protocol(struct rtllib_device *ieee, u8 shutdown) void rtllib_softmac_start_protocol(struct rtllib_device *ieee, u8 mesh_flag) { - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); rtllib_start_protocol(ieee); - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); } EXPORT_SYMBOL(rtllib_softmac_start_protocol); @@ -3034,7 +3034,7 @@ void rtllib_softmac_init(struct rtllib_device *ieee) INIT_WORK_RSL(&ieee->wx_sync_scan_wq, (void *)rtllib_wx_sync_scan_wq, ieee); - sema_init(&ieee->wx_sem, 1); + mutex_init(&ieee->wx_mutex); sema_init(&ieee->scan_sem, 1); sema_init(&ieee->ips_sem, 1); @@ -3049,7 +3049,7 @@ void rtllib_softmac_init(struct rtllib_device *ieee) void rtllib_softmac_free(struct rtllib_device *ieee) { - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); kfree(ieee->pDot11dInfo); ieee->pDot11dInfo = NULL; del_timer_sync(&ieee->associate_timer); @@ -3064,7 +3064,7 @@ void rtllib_softmac_free(struct rtllib_device *ieee) cancel_work_sync(&ieee->associate_complete_wq); cancel_work_sync(&ieee->ips_leave_wq); cancel_work_sync(&ieee->wx_sync_scan_wq); - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); tasklet_kill(&ieee->ps_task); } @@ -3499,7 +3499,7 @@ int rtllib_wpa_supplicant_ioctl(struct rtllib_device *ieee, struct iw_point *p, struct ieee_param *param; int ret = 0; - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); if (p->length < sizeof(struct ieee_param) || !p->pointer) { ret = -EINVAL; @@ -3543,7 +3543,7 @@ int rtllib_wpa_supplicant_ioctl(struct rtllib_device *ieee, struct iw_point *p, kfree(param); out: - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); return ret; } diff --git a/drivers/staging/rtl8192e/rtllib_softmac_wx.c b/drivers/staging/rtl8192e/rtllib_softmac_wx.c index 61ed8b0..5f1412f 100644 --- a/drivers/staging/rtl8192e/rtllib_softmac_wx.c +++ b/drivers/staging/rtl8192e/rtllib_softmac_wx.c @@ -35,7 +35,7 @@ int rtllib_wx_set_freq(struct rtllib_device *ieee, struct iw_request_info *a, int ret; struct iw_freq *fwrq = &wrqu->freq; - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); if (ieee->iw_mode == IW_MODE_INFRA) { ret = 0; @@ -81,7 +81,7 @@ int rtllib_wx_set_freq(struct rtllib_device *ieee, struct iw_request_info *a, ret = 0; out: - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); return ret; } EXPORT_SYMBOL(rtllib_wx_set_freq); @@ -146,7 +146,7 @@ int rtllib_wx_set_wap(struct rtllib_device *ieee, rtllib_stop_scan_syncro(ieee); - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); /* use ifconfig hw ether */ if (ieee->iw_mode == IW_MODE_MASTER) { ret = -1; @@ -185,7 +185,7 @@ int rtllib_wx_set_wap(struct rtllib_device *ieee, if (ifup) rtllib_start_protocol(ieee); out: - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); return ret; } EXPORT_SYMBOL(rtllib_wx_set_wap); @@ -287,7 +287,7 @@ int rtllib_wx_set_mode(struct rtllib_device *ieee, struct iw_request_info *a, int set_mode_status = 0; rtllib_stop_scan_syncro(ieee); - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); switch (wrqu->mode) { case IW_MODE_MONITOR: case IW_MODE_ADHOC: @@ -322,7 +322,7 @@ int rtllib_wx_set_mode(struct rtllib_device *ieee, struct iw_request_info *a, } out: - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); return set_mode_status; } EXPORT_SYMBOL(rtllib_wx_set_mode); @@ -412,7 +412,7 @@ void rtllib_wx_sync_scan_wq(void *data) rtllib_wake_all_queues(ieee); out: - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); } @@ -421,7 +421,7 @@ int rtllib_wx_set_scan(struct rtllib_device *ieee, struct iw_request_info *a, { int ret = 0; - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); if (ieee->iw_mode == IW_MODE_MONITOR || !(ieee->proto_started)) { ret = -1; @@ -435,7 +435,7 @@ int rtllib_wx_set_scan(struct rtllib_device *ieee, struct iw_request_info *a, } out: - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); return ret; } EXPORT_SYMBOL(rtllib_wx_set_scan); @@ -450,7 +450,7 @@ int rtllib_wx_set_essid(struct rtllib_device *ieee, unsigned long flags; rtllib_stop_scan_syncro(ieee); - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); proto_started = ieee->proto_started; @@ -492,7 +492,7 @@ int rtllib_wx_set_essid(struct rtllib_device *ieee, if (proto_started) rtllib_start_protocol(ieee); out: - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); return ret; } EXPORT_SYMBOL(rtllib_wx_set_essid); @@ -514,7 +514,7 @@ int rtllib_wx_set_rawtx(struct rtllib_device *ieee, int enable = (parms[0] > 0); short prev = ieee->raw_tx; - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); if (enable) ieee->raw_tx = 1; @@ -536,7 +536,7 @@ int rtllib_wx_set_rawtx(struct rtllib_device *ieee, netif_carrier_off(ieee->dev); } - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); return 0; } @@ -575,7 +575,7 @@ int rtllib_wx_set_power(struct rtllib_device *ieee, return -1; } - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); if (wrqu->power.disabled) { RT_TRACE(COMP_DBG, "===>%s(): power disable\n", __func__); @@ -611,7 +611,7 @@ int rtllib_wx_set_power(struct rtllib_device *ieee, } exit: - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); return ret; } @@ -622,7 +622,7 @@ int rtllib_wx_get_power(struct rtllib_device *ieee, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); if (ieee->ps == RTLLIB_PS_DISABLED) { wrqu->power.disabled = 1; @@ -648,7 +648,7 @@ int rtllib_wx_get_power(struct rtllib_device *ieee, wrqu->power.flags |= IW_POWER_UNICAST_R; exit: - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); return 0; } diff --git a/drivers/staging/rtl8192e/rtllib_wx.c b/drivers/staging/rtl8192e/rtllib_wx.c index 84e6272..b1500ee 100644 --- a/drivers/staging/rtl8192e/rtllib_wx.c +++ b/drivers/staging/rtl8192e/rtllib_wx.c @@ -263,7 +263,7 @@ int rtllib_wx_get_scan(struct rtllib_device *ieee, int err = 0; netdev_dbg(ieee->dev, "Getting scan\n"); - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); spin_lock_irqsave(&ieee->lock, flags); list_for_each_entry(network, &ieee->network_list, list) { @@ -287,7 +287,7 @@ int rtllib_wx_get_scan(struct rtllib_device *ieee, } spin_unlock_irqrestore(&ieee->lock, flags); - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); wrqu->data.length = ev - extra; wrqu->data.flags = 0; @@ -689,7 +689,7 @@ int rtllib_wx_set_mlme(struct rtllib_device *ieee, if (ieee->state != RTLLIB_LINKED) return -ENOLINK; - down(&ieee->wx_sem); + mutex_lock(&ieee->wx_mutex); switch (mlme->cmd) { case IW_MLME_DEAUTH: @@ -716,11 +716,11 @@ int rtllib_wx_set_mlme(struct rtllib_device *ieee, ieee->current_network.ssid_len = 0; break; default: - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); return -EOPNOTSUPP; } - up(&ieee->wx_sem); + mutex_unlock(&ieee->wx_mutex); return 0; } -- cgit v0.10.2 From 3044975feddfa0dfa4325610fbd822f473366d8a Mon Sep 17 00:00:00 2001 From: Binoy Jayan <binoy.jayan@linaro.org> Date: Wed, 1 Jun 2016 14:56:53 +0530 Subject: rtl8192e: r8192_priv: Replace semaphore wx_sem with mutex The semaphore 'wx_sem' in the r8192_priv is a simple mutex, so it should be written as one. Semaphores are going away in the future. Signed-off-by: Binoy Jayan <binoy.jayan@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c index f9e7a51..4692028 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c @@ -993,7 +993,7 @@ static void _rtl92e_init_priv_lock(struct r8192_priv *priv) spin_lock_init(&priv->irq_th_lock); spin_lock_init(&priv->rf_ps_lock); spin_lock_init(&priv->ps_lock); - sema_init(&priv->wx_sem, 1); + mutex_init(&priv->wx_mutex); sema_init(&priv->rf_sem, 1); mutex_init(&priv->mutex); } @@ -1247,7 +1247,7 @@ static void _rtl92e_if_silent_reset(struct net_device *dev) RESET_START: - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); if (priv->rtllib->state == RTLLIB_LINKED) rtl92e_leisure_ps_leave(dev); @@ -1255,7 +1255,7 @@ RESET_START: if (priv->up) { netdev_info(dev, "%s():the driver is not up.\n", __func__); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return; } priv->up = 0; @@ -1292,7 +1292,7 @@ RESET_START: rtl92e_dm_backup_state(dev); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); RT_TRACE(COMP_RESET, "%s():<==========down process is finished\n", __func__); @@ -2179,9 +2179,9 @@ static int _rtl92e_open(struct net_device *dev) struct r8192_priv *priv = rtllib_priv(dev); int ret; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); ret = _rtl92e_try_up(dev); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; } @@ -2206,11 +2206,11 @@ static int _rtl92e_close(struct net_device *dev) rtllib_stop_scan(priv->rtllib); } - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); ret = _rtl92e_down(dev, true); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; @@ -2242,11 +2242,11 @@ static void _rtl92e_restart(void *data) reset_wq); struct net_device *dev = priv->rtllib->dev; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); rtl92e_commit(dev); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); } static void _rtl92e_set_multicast(struct net_device *dev) @@ -2265,12 +2265,12 @@ static int _rtl92e_set_mac_adr(struct net_device *dev, void *mac) struct r8192_priv *priv = rtllib_priv(dev); struct sockaddr *addr = mac; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); ether_addr_copy(dev->dev_addr, addr->sa_data); schedule_work(&priv->reset_wq); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return 0; } @@ -2287,7 +2287,7 @@ static int _rtl92e_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) struct iw_point *p = &wrq->u.data; struct ieee_param *ipw = NULL; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); switch (cmd) { case RTL_IOCTL_WPA_SUPPLICANT: @@ -2393,7 +2393,7 @@ static int _rtl92e_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) } out: - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; } diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h index 6921125..16378e6 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h @@ -375,7 +375,7 @@ struct r8192_priv { struct tasklet_struct irq_tx_tasklet; struct tasklet_struct irq_prepare_beacon_tasklet; - struct semaphore wx_sem; + struct mutex wx_mutex; struct semaphore rf_sem; struct mutex mutex; diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c index 70df6a1..78fe833 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c @@ -65,11 +65,11 @@ static int _rtl92e_wx_set_rate(struct net_device *dev, if (priv->bHwRadioOff) return 0; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); ret = rtllib_wx_set_rate(priv->rtllib, info, wrqu, extra); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; } @@ -84,11 +84,11 @@ static int _rtl92e_wx_set_rts(struct net_device *dev, if (priv->bHwRadioOff) return 0; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); ret = rtllib_wx_set_rts(priv->rtllib, info, wrqu, extra); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; } @@ -114,11 +114,11 @@ static int _rtl92e_wx_set_power(struct net_device *dev, __func__); return 0; } - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); ret = rtllib_wx_set_power(priv->rtllib, info, wrqu, extra); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; } @@ -142,11 +142,11 @@ static int _rtl92e_wx_set_rawtx(struct net_device *dev, if (priv->bHwRadioOff) return 0; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); ret = rtllib_wx_set_rawtx(priv->rtllib, info, wrqu, extra); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; @@ -158,12 +158,12 @@ static int _rtl92e_wx_force_reset(struct net_device *dev, { struct r8192_priv *priv = rtllib_priv(dev); - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); RT_TRACE(COMP_DBG, "%s(): force reset ! extra is %d\n", __func__, *extra); priv->force_reset = *extra; - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return 0; } @@ -177,7 +177,7 @@ static int _rtl92e_wx_adapter_power_status(struct net_device *dev, (&(priv->rtllib->PowerSaveControl)); struct rtllib_device *ieee = priv->rtllib; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); RT_TRACE(COMP_POWER, "%s(): %s\n", __func__, (*extra == 6) ? "DC power" : "AC power"); @@ -193,7 +193,7 @@ static int _rtl92e_wx_adapter_power_status(struct net_device *dev, ieee->ps = *extra; } - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return 0; } @@ -207,13 +207,13 @@ static int _rtl92e_wx_set_lps_awake_interval(struct net_device *dev, struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *) (&(priv->rtllib->PowerSaveControl)); - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); netdev_info(dev, "%s(): set lps awake interval ! extra is %d\n", __func__, *extra); pPSC->RegMaxLPSAwakeIntvl = *extra; - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return 0; } @@ -223,13 +223,13 @@ static int _rtl92e_wx_set_force_lps(struct net_device *dev, { struct r8192_priv *priv = rtllib_priv(dev); - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); netdev_info(dev, "%s(): force LPS ! extra is %d (1 is open 0 is close)\n", __func__, *extra); priv->force_lps = *extra; - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return 0; } @@ -266,7 +266,7 @@ static int _rtl92e_wx_set_mode(struct net_device *dev, if (priv->bHwRadioOff) return 0; rtState = priv->rtllib->eRFPowerState; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); if (wrqu->mode == IW_MODE_ADHOC || wrqu->mode == IW_MODE_MONITOR || ieee->bNetPromiscuousMode) { if (priv->rtllib->PowerSaveControl.bInactivePs) { @@ -275,7 +275,7 @@ static int _rtl92e_wx_set_mode(struct net_device *dev, RF_CHANGE_BY_IPS) { netdev_warn(dev, "%s(): RF is OFF.\n", __func__); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return -1; } netdev_info(dev, @@ -289,7 +289,7 @@ static int _rtl92e_wx_set_mode(struct net_device *dev, } ret = rtllib_wx_set_mode(priv->rtllib, a, wrqu, b); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; } @@ -425,7 +425,7 @@ static int _rtl92e_wx_set_scan(struct net_device *dev, } } - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); priv->rtllib->FirstIe_InScan = true; @@ -436,7 +436,7 @@ static int _rtl92e_wx_set_scan(struct net_device *dev, RF_CHANGE_BY_IPS) { netdev_warn(dev, "%s(): RF is OFF.\n", __func__); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return -1; } RT_TRACE(COMP_PS, @@ -471,7 +471,7 @@ static int _rtl92e_wx_set_scan(struct net_device *dev, ret = rtllib_wx_set_scan(priv->rtllib, a, wrqu, b); } - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; } @@ -491,11 +491,11 @@ static int _rtl92e_wx_get_scan(struct net_device *dev, return 0; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); ret = rtllib_wx_get_scan(priv->rtllib, a, wrqu, b); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; } @@ -513,10 +513,10 @@ static int _rtl92e_wx_set_essid(struct net_device *dev, __func__); return 0; } - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); ret = rtllib_wx_set_essid(priv->rtllib, a, wrqu, b); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; } @@ -528,11 +528,11 @@ static int _rtl92e_wx_get_essid(struct net_device *dev, int ret; struct r8192_priv *priv = rtllib_priv(dev); - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); ret = rtllib_wx_get_essid(priv->rtllib, a, wrqu, b); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; } @@ -545,12 +545,12 @@ static int _rtl92e_wx_set_nick(struct net_device *dev, if (wrqu->data.length > IW_ESSID_MAX_SIZE) return -E2BIG; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); wrqu->data.length = min_t(size_t, wrqu->data.length, sizeof(priv->nick)); memset(priv->nick, 0, sizeof(priv->nick)); memcpy(priv->nick, extra, wrqu->data.length); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return 0; } @@ -561,11 +561,11 @@ static int _rtl92e_wx_get_nick(struct net_device *dev, { struct r8192_priv *priv = rtllib_priv(dev); - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); wrqu->data.length = strlen(priv->nick); memcpy(extra, priv->nick, wrqu->data.length); wrqu->data.flags = 1; /* active */ - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return 0; } @@ -579,11 +579,11 @@ static int _rtl92e_wx_set_freq(struct net_device *dev, if (priv->bHwRadioOff) return 0; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); ret = rtllib_wx_set_freq(priv->rtllib, a, wrqu, b); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; } @@ -644,11 +644,11 @@ static int _rtl92e_wx_set_wap(struct net_device *dev, if (priv->bHwRadioOff) return 0; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); ret = rtllib_wx_set_wap(priv->rtllib, info, awrq, extra); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; @@ -701,11 +701,11 @@ static int _rtl92e_wx_set_enc(struct net_device *dev, down(&priv->rtllib->ips_sem); rtl92e_ips_leave(dev); up(&priv->rtllib->ips_sem); - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); RT_TRACE(COMP_SEC, "Setting SW wep key"); ret = rtllib_wx_set_encode(priv->rtllib, info, wrqu, key); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); if (wrqu->encoding.flags & IW_ENCODE_DISABLED) { @@ -799,7 +799,7 @@ static int _rtl92e_wx_set_retry(struct net_device *dev, if (priv->bHwRadioOff) return 0; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); if (wrqu->retry.flags & IW_RETRY_LIFETIME || wrqu->retry.disabled) { @@ -822,7 +822,7 @@ static int _rtl92e_wx_set_retry(struct net_device *dev, rtl92e_commit(dev); exit: - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return err; } @@ -875,7 +875,7 @@ static int _rtl92e_wx_set_sens(struct net_device *dev, if (priv->bHwRadioOff) return 0; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); if (priv->rf_set_sens == NULL) { err = -1; /* we have not this support for this radio */ goto exit; @@ -886,7 +886,7 @@ static int _rtl92e_wx_set_sens(struct net_device *dev, err = -EINVAL; exit: - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return err; } @@ -902,7 +902,7 @@ static int _rtl92e_wx_set_encode_ext(struct net_device *dev, if (priv->bHwRadioOff) return 0; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); priv->rtllib->wx_set_enc = 1; down(&priv->rtllib->ips_sem); @@ -969,7 +969,7 @@ static int _rtl92e_wx_set_encode_ext(struct net_device *dev, end_hw_sec: priv->rtllib->wx_set_enc = 0; - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; } @@ -985,9 +985,9 @@ static int _rtl92e_wx_set_auth(struct net_device *dev, if (priv->bHwRadioOff) return 0; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); ret = rtllib_wx_set_auth(priv->rtllib, info, &(data->param), extra); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; } @@ -1003,9 +1003,9 @@ static int _rtl92e_wx_set_mlme(struct net_device *dev, if (priv->bHwRadioOff) return 0; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); ret = rtllib_wx_set_mlme(priv->rtllib, info, wrqu, extra); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; } @@ -1020,9 +1020,9 @@ static int _rtl92e_wx_set_gen_ie(struct net_device *dev, if (priv->bHwRadioOff) return 0; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); ret = rtllib_wx_set_gen_ie(priv->rtllib, extra, data->data.length); - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return ret; } @@ -1097,14 +1097,14 @@ static int _rtl92e_wx_get_promisc_mode(struct net_device *dev, struct r8192_priv *priv = rtllib_priv(dev); struct rtllib_device *ieee = priv->rtllib; - down(&priv->wx_sem); + mutex_lock(&priv->wx_mutex); snprintf(extra, 45, "PromiscuousMode:%d, FilterSrcSTAFrame:%d", ieee->IntelPromiscuousModeInfo.bPromiscuousOn, ieee->IntelPromiscuousModeInfo.bFilterSourceStationFrame); wrqu->data.length = strlen(extra) + 1; - up(&priv->wx_sem); + mutex_unlock(&priv->wx_mutex); return 0; } -- cgit v0.10.2 From 5333496cb01ab216ba638976846531344bc3c4b9 Mon Sep 17 00:00:00 2001 From: Binoy Jayan <binoy.jayan@linaro.org> Date: Wed, 1 Jun 2016 14:56:54 +0530 Subject: rtl8192e: Replace semaphore rf_sem with mutex The semaphore 'rf_sem' in the rtl8192e is a simple mutex, so it should be written as one. Semaphores are going away in the future. Signed-off-by: Binoy Jayan <binoy.jayan@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c index 0698131..dde4922 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c @@ -256,7 +256,7 @@ u32 rtl92e_get_rf_reg(struct net_device *dev, enum rf90_radio_path eRFPath, return 0; if (priv->rtllib->eRFPowerState != eRfOn && !priv->being_init_adapter) return 0; - down(&priv->rf_sem); + mutex_lock(&priv->rf_mutex); if (priv->Rf_Mode == RF_OP_By_FW) { Original_Value = _rtl92e_phy_rf_fw_read(dev, eRFPath, RegAddr); udelay(200); @@ -265,7 +265,7 @@ u32 rtl92e_get_rf_reg(struct net_device *dev, enum rf90_radio_path eRFPath, } BitShift = _rtl92e_calculate_bit_shift(BitMask); Readback_Value = (Original_Value & BitMask) >> BitShift; - up(&priv->rf_sem); + mutex_unlock(&priv->rf_mutex); return Readback_Value; } diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c index 4692028..e01fff0 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c @@ -994,7 +994,7 @@ static void _rtl92e_init_priv_lock(struct r8192_priv *priv) spin_lock_init(&priv->rf_ps_lock); spin_lock_init(&priv->ps_lock); mutex_init(&priv->wx_mutex); - sema_init(&priv->rf_sem, 1); + mutex_init(&priv->rf_mutex); mutex_init(&priv->mutex); } diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h index 16378e6..babc0b3 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h @@ -376,7 +376,7 @@ struct r8192_priv { struct tasklet_struct irq_prepare_beacon_tasklet; struct mutex wx_mutex; - struct semaphore rf_sem; + struct mutex rf_mutex; struct mutex mutex; struct rt_stats stats; -- cgit v0.10.2 From be10ceea4f0920975df35c23d50f8eed157ef72b Mon Sep 17 00:00:00 2001 From: Binoy Jayan <binoy.jayan@linaro.org> Date: Wed, 1 Jun 2016 14:56:55 +0530 Subject: rtl8192e: Replace semaphore scan_sem with mutex The semaphore 'scan_sem' in the rtl8192e is a simple mutex, so it should be written as one. Semaphores are going away in the future. Signed-off-by: Binoy Jayan <binoy.jayan@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h index 513dd61..5bdc378 100644 --- a/drivers/staging/rtl8192e/rtllib.h +++ b/drivers/staging/rtl8192e/rtllib.h @@ -1653,7 +1653,7 @@ struct rtllib_device { short proto_stoppping; struct mutex wx_mutex; - struct semaphore scan_sem; + struct mutex scan_mutex; struct semaphore ips_sem; spinlock_t mgmt_tx_lock; diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c index 901cc50..858eae2 100644 --- a/drivers/staging/rtl8192e/rtllib_softmac.c +++ b/drivers/staging/rtl8192e/rtllib_softmac.c @@ -513,7 +513,7 @@ static void rtllib_softmac_scan_syncro(struct rtllib_device *ieee, u8 is_mesh) ieee->be_scan_inprogress = true; - down(&ieee->scan_sem); + mutex_lock(&ieee->scan_mutex); while (1) { do { @@ -566,7 +566,7 @@ out: if (IS_DOT11D_ENABLE(ieee)) DOT11D_ScanComplete(ieee); } - up(&ieee->scan_sem); + mutex_unlock(&ieee->scan_mutex); ieee->be_scan_inprogress = false; @@ -587,7 +587,7 @@ static void rtllib_softmac_scan_wq(void *data) if (rtllib_act_scanning(ieee, true)) return; - down(&ieee->scan_sem); + mutex_lock(&ieee->scan_mutex); if (ieee->eRFPowerState == eRfOff) { netdev_info(ieee->dev, @@ -618,7 +618,7 @@ static void rtllib_softmac_scan_wq(void *data) schedule_delayed_work(&ieee->softmac_scan_wq, msecs_to_jiffies(RTLLIB_SOFTMAC_SCAN_TIME)); - up(&ieee->scan_sem); + mutex_unlock(&ieee->scan_mutex); return; out: @@ -630,7 +630,7 @@ out1: ieee->actscanning = false; ieee->scan_watch_dog = 0; ieee->scanning_continue = 0; - up(&ieee->scan_sem); + mutex_unlock(&ieee->scan_mutex); } @@ -683,7 +683,7 @@ EXPORT_SYMBOL(rtllib_start_send_beacons); static void rtllib_softmac_stop_scan(struct rtllib_device *ieee) { - down(&ieee->scan_sem); + mutex_lock(&ieee->scan_mutex); ieee->scan_watch_dog = 0; if (ieee->scanning_continue == 1) { ieee->scanning_continue = 0; @@ -692,7 +692,7 @@ static void rtllib_softmac_stop_scan(struct rtllib_device *ieee) cancel_delayed_work_sync(&ieee->softmac_scan_wq); } - up(&ieee->scan_sem); + mutex_unlock(&ieee->scan_mutex); } void rtllib_stop_scan(struct rtllib_device *ieee) @@ -3035,7 +3035,7 @@ void rtllib_softmac_init(struct rtllib_device *ieee) ieee); mutex_init(&ieee->wx_mutex); - sema_init(&ieee->scan_sem, 1); + mutex_init(&ieee->scan_mutex); sema_init(&ieee->ips_sem, 1); spin_lock_init(&ieee->mgmt_tx_lock); -- cgit v0.10.2 From 38bee763bd6d1f77ca3d10639e9bb3f1a1a53443 Mon Sep 17 00:00:00 2001 From: Binoy Jayan <binoy.jayan@linaro.org> Date: Wed, 1 Jun 2016 14:56:56 +0530 Subject: rtl8192e: Replace semaphore ips_sem with mutex The semaphore 'ips_sem' in the rtl8192e is a simple mutex, so it should be written as one. Semaphores are going away in the future. Signed-off-by: Binoy Jayan <binoy.jayan@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c index 803c8b0..30f65af 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c @@ -107,9 +107,9 @@ void rtl92e_set_key(struct net_device *dev, u8 EntryNo, u8 KeyIndex, __func__); return; } - down(&priv->rtllib->ips_sem); + mutex_lock(&priv->rtllib->ips_mutex); rtl92e_ips_leave(dev); - up(&priv->rtllib->ips_sem); + mutex_unlock(&priv->rtllib->ips_mutex); } } priv->rtllib->is_set_key = true; diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c b/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c index 98e4d88..aa4b015 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c @@ -179,9 +179,9 @@ void rtl92e_ips_leave_wq(void *data) struct net_device *dev = ieee->dev; struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); - down(&priv->rtllib->ips_sem); + mutex_lock(&priv->rtllib->ips_mutex); rtl92e_ips_leave(dev); - up(&priv->rtllib->ips_sem); + mutex_unlock(&priv->rtllib->ips_mutex); } void rtl92e_rtllib_ips_leave_wq(struct net_device *dev) @@ -209,9 +209,9 @@ void rtl92e_rtllib_ips_leave(struct net_device *dev) { struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); - down(&priv->rtllib->ips_sem); + mutex_lock(&priv->rtllib->ips_mutex); rtl92e_ips_leave(dev); - up(&priv->rtllib->ips_sem); + mutex_unlock(&priv->rtllib->ips_mutex); } static bool _rtl92e_ps_set_mode(struct net_device *dev, u8 rtPsMode) diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c index 78fe833..7413a10 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c @@ -281,9 +281,9 @@ static int _rtl92e_wx_set_mode(struct net_device *dev, netdev_info(dev, "=========>%s(): rtl92e_ips_leave\n", __func__); - down(&priv->rtllib->ips_sem); + mutex_lock(&priv->rtllib->ips_mutex); rtl92e_ips_leave(dev); - up(&priv->rtllib->ips_sem); + mutex_unlock(&priv->rtllib->ips_mutex); } } } @@ -442,9 +442,9 @@ static int _rtl92e_wx_set_scan(struct net_device *dev, RT_TRACE(COMP_PS, "=========>%s(): rtl92e_ips_leave\n", __func__); - down(&priv->rtllib->ips_sem); + mutex_lock(&priv->rtllib->ips_mutex); rtl92e_ips_leave(dev); - up(&priv->rtllib->ips_sem); + mutex_unlock(&priv->rtllib->ips_mutex); } } rtllib_stop_scan(priv->rtllib); @@ -698,9 +698,9 @@ static int _rtl92e_wx_set_enc(struct net_device *dev, return -ENETDOWN; priv->rtllib->wx_set_enc = 1; - down(&priv->rtllib->ips_sem); + mutex_lock(&priv->rtllib->ips_mutex); rtl92e_ips_leave(dev); - up(&priv->rtllib->ips_sem); + mutex_unlock(&priv->rtllib->ips_mutex); mutex_lock(&priv->wx_mutex); RT_TRACE(COMP_SEC, "Setting SW wep key"); @@ -905,9 +905,9 @@ static int _rtl92e_wx_set_encode_ext(struct net_device *dev, mutex_lock(&priv->wx_mutex); priv->rtllib->wx_set_enc = 1; - down(&priv->rtllib->ips_sem); + mutex_lock(&priv->rtllib->ips_mutex); rtl92e_ips_leave(dev); - up(&priv->rtllib->ips_sem); + mutex_unlock(&priv->rtllib->ips_mutex); ret = rtllib_wx_set_encode_ext(ieee, info, wrqu, extra); { diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h index 5bdc378..38247fa 100644 --- a/drivers/staging/rtl8192e/rtllib.h +++ b/drivers/staging/rtl8192e/rtllib.h @@ -30,7 +30,6 @@ #include <linux/jiffies.h> #include <linux/timer.h> #include <linux/sched.h> -#include <linux/semaphore.h> #include <linux/mutex.h> #include <linux/delay.h> @@ -1654,7 +1653,7 @@ struct rtllib_device { struct mutex wx_mutex; struct mutex scan_mutex; - struct semaphore ips_sem; + struct mutex ips_mutex; spinlock_t mgmt_tx_lock; spinlock_t beacon_lock; diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c index 858eae2..e84ffc8 100644 --- a/drivers/staging/rtl8192e/rtllib_softmac.c +++ b/drivers/staging/rtl8192e/rtllib_softmac.c @@ -3036,7 +3036,7 @@ void rtllib_softmac_init(struct rtllib_device *ieee) mutex_init(&ieee->wx_mutex); mutex_init(&ieee->scan_mutex); - sema_init(&ieee->ips_sem, 1); + mutex_init(&ieee->ips_mutex); spin_lock_init(&ieee->mgmt_tx_lock); spin_lock_init(&ieee->beacon_lock); -- cgit v0.10.2 From 0f89054a0f6b44bdb7fd84de7fa80fa651a6f930 Mon Sep 17 00:00:00 2001 From: Binoy Jayan <binoy.jayan@linaro.org> Date: Thu, 2 Jun 2016 09:54:07 +0530 Subject: rtl8712: Replace semaphore cmd_queue_sema with completion The semaphore 'cmd_queue_sema' is used as completion, so convert it to a struct completion type. Signed-off-by: Binoy Jayan <binoy.jayan@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Tested-by: Larry Finger <Larry.Finger@lwfinger.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c index 57211f7..4430125 100644 --- a/drivers/staging/rtl8712/os_intfs.c +++ b/drivers/staging/rtl8712/os_intfs.c @@ -243,7 +243,7 @@ static u32 start_drv_threads(struct _adapter *padapter) void r8712_stop_drv_threads(struct _adapter *padapter) { /*Below is to terminate r8712_cmd_thread & event_thread...*/ - up(&padapter->cmdpriv.cmd_queue_sema); + complete(&padapter->cmdpriv.cmd_queue_comp); if (padapter->cmdThread) _down_sema(&padapter->cmdpriv.terminate_cmdthread_sema); padapter->cmdpriv.cmd_seq = 1; diff --git a/drivers/staging/rtl8712/rtl8712_cmd.c b/drivers/staging/rtl8712/rtl8712_cmd.c index 13c0183..08f3f49 100644 --- a/drivers/staging/rtl8712/rtl8712_cmd.c +++ b/drivers/staging/rtl8712/rtl8712_cmd.c @@ -322,7 +322,7 @@ int r8712_cmd_thread(void *context) allow_signal(SIGTERM); while (1) { - if ((_down_sema(&(pcmdpriv->cmd_queue_sema))) == _FAIL) + if (wait_for_completion_interruptible(&pcmdpriv->cmd_queue_comp)) break; if (padapter->bDriverStopped || padapter->bSurpriseRemoved) break; diff --git a/drivers/staging/rtl8712/rtl871x_cmd.c b/drivers/staging/rtl8712/rtl871x_cmd.c index aed03cf..82854ec 100644 --- a/drivers/staging/rtl8712/rtl871x_cmd.c +++ b/drivers/staging/rtl8712/rtl871x_cmd.c @@ -57,7 +57,7 @@ No irqsave is necessary. static sint _init_cmd_priv(struct cmd_priv *pcmdpriv) { - sema_init(&(pcmdpriv->cmd_queue_sema), 0); + init_completion(&pcmdpriv->cmd_queue_comp); sema_init(&(pcmdpriv->terminate_cmdthread_sema), 0); _init_queue(&(pcmdpriv->cmd_queue)); @@ -172,7 +172,7 @@ u32 r8712_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *obj) if (pcmdpriv->padapter->eeprompriv.bautoload_fail_flag) return _FAIL; res = _enqueue_cmd(&pcmdpriv->cmd_queue, obj); - up(&pcmdpriv->cmd_queue_sema); + complete(&pcmdpriv->cmd_queue_comp); return res; } @@ -189,7 +189,7 @@ u32 r8712_enqueue_cmd_ex(struct cmd_priv *pcmdpriv, struct cmd_obj *obj) spin_lock_irqsave(&queue->lock, irqL); list_add_tail(&obj->list, &queue->queue); spin_unlock_irqrestore(&queue->lock, irqL); - up(&pcmdpriv->cmd_queue_sema); + complete(&pcmdpriv->cmd_queue_comp); return _SUCCESS; } diff --git a/drivers/staging/rtl8712/rtl871x_cmd.h b/drivers/staging/rtl8712/rtl871x_cmd.h index e4a2a50..1907bc9 100644 --- a/drivers/staging/rtl8712/rtl871x_cmd.h +++ b/drivers/staging/rtl8712/rtl871x_cmd.h @@ -50,7 +50,7 @@ struct cmd_obj { }; struct cmd_priv { - struct semaphore cmd_queue_sema; + struct completion cmd_queue_comp; struct semaphore terminate_cmdthread_sema; struct __queue cmd_queue; u8 cmd_seq; diff --git a/drivers/staging/rtl8712/rtl871x_pwrctrl.c b/drivers/staging/rtl8712/rtl871x_pwrctrl.c index bf10d6d..98a5e74 100644 --- a/drivers/staging/rtl8712/rtl871x_pwrctrl.c +++ b/drivers/staging/rtl8712/rtl871x_pwrctrl.c @@ -107,7 +107,7 @@ void r8712_cpwm_int_hdl(struct _adapter *padapter, pwrpriv->cpwm = (preportpwrstate->state) & 0xf; if (pwrpriv->cpwm >= PS_STATE_S2) { if (pwrpriv->alives & CMD_ALIVE) - up(&(pcmdpriv->cmd_queue_sema)); + complete(&(pcmdpriv->cmd_queue_comp)); } pwrpriv->cpwm_tog = (preportpwrstate->state) & 0x80; up(&pwrpriv->lock); -- cgit v0.10.2 From 204a8ac1db424d6873c450828eb837c7d4158294 Mon Sep 17 00:00:00 2001 From: Binoy Jayan <binoy.jayan@linaro.org> Date: Thu, 2 Jun 2016 09:54:08 +0530 Subject: rtl8712: Replace semaphore terminate_cmdthread_sema with completion The semaphore 'terminate_cmdthread_sema' is used as completion, so convert it to a struct completion type. Signed-off-by: Binoy Jayan <binoy.jayan@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Tested-by: Larry Finger <Larry.Finger@lwfinger.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c index 4430125..b615fbf 100644 --- a/drivers/staging/rtl8712/os_intfs.c +++ b/drivers/staging/rtl8712/os_intfs.c @@ -245,7 +245,7 @@ void r8712_stop_drv_threads(struct _adapter *padapter) /*Below is to terminate r8712_cmd_thread & event_thread...*/ complete(&padapter->cmdpriv.cmd_queue_comp); if (padapter->cmdThread) - _down_sema(&padapter->cmdpriv.terminate_cmdthread_sema); + wait_for_completion_interruptible(&padapter->cmdpriv.terminate_cmdthread_comp); padapter->cmdpriv.cmd_seq = 1; } diff --git a/drivers/staging/rtl8712/rtl8712_cmd.c b/drivers/staging/rtl8712/rtl8712_cmd.c index 08f3f49..3877fcf 100644 --- a/drivers/staging/rtl8712/rtl8712_cmd.c +++ b/drivers/staging/rtl8712/rtl8712_cmd.c @@ -420,7 +420,7 @@ _next: break; r8712_free_cmd_obj(pcmd); } while (1); - up(&pcmdpriv->terminate_cmdthread_sema); + complete(&pcmdpriv->terminate_cmdthread_comp); thread_exit(); } diff --git a/drivers/staging/rtl8712/rtl871x_cmd.c b/drivers/staging/rtl8712/rtl871x_cmd.c index 82854ec..5838696 100644 --- a/drivers/staging/rtl8712/rtl871x_cmd.c +++ b/drivers/staging/rtl8712/rtl871x_cmd.c @@ -58,7 +58,7 @@ No irqsave is necessary. static sint _init_cmd_priv(struct cmd_priv *pcmdpriv) { init_completion(&pcmdpriv->cmd_queue_comp); - sema_init(&(pcmdpriv->terminate_cmdthread_sema), 0); + init_completion(&pcmdpriv->terminate_cmdthread_comp); _init_queue(&(pcmdpriv->cmd_queue)); diff --git a/drivers/staging/rtl8712/rtl871x_cmd.h b/drivers/staging/rtl8712/rtl871x_cmd.h index 1907bc9..ebd2e1d 100644 --- a/drivers/staging/rtl8712/rtl871x_cmd.h +++ b/drivers/staging/rtl8712/rtl871x_cmd.h @@ -51,7 +51,7 @@ struct cmd_obj { struct cmd_priv { struct completion cmd_queue_comp; - struct semaphore terminate_cmdthread_sema; + struct completion terminate_cmdthread_comp; struct __queue cmd_queue; u8 cmd_seq; u8 *cmd_buf; /*shall be non-paged, and 4 bytes aligned*/ -- cgit v0.10.2 From 7c2bb7aff9b5ef83c5b1fd3a9ef0af39bbbf1f7a Mon Sep 17 00:00:00 2001 From: Binoy Jayan <binoy.jayan@linaro.org> Date: Thu, 2 Jun 2016 09:54:09 +0530 Subject: rtl8712: intf_priv: Replace semaphore lock with completion The semaphore 'lock' in 'intf_priv' is used as completion, so convert it to a struct completion type. Signed-off-by: Binoy Jayan <binoy.jayan@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Tested-by: Larry Finger <Larry.Finger@lwfinger.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8712/osdep_intf.h b/drivers/staging/rtl8712/osdep_intf.h index aa0ec74..5d37e1f 100644 --- a/drivers/staging/rtl8712/osdep_intf.h +++ b/drivers/staging/rtl8712/osdep_intf.h @@ -36,7 +36,7 @@ struct intf_priv { /* when in USB, IO is through interrupt in/out endpoints */ struct usb_device *udev; struct urb *piorw_urb; - struct semaphore io_retevt; + struct completion io_retevt_comp; }; int r871x_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); diff --git a/drivers/staging/rtl8712/usb_ops_linux.c b/drivers/staging/rtl8712/usb_ops_linux.c index 6f12345..1af7f5f 100644 --- a/drivers/staging/rtl8712/usb_ops_linux.c +++ b/drivers/staging/rtl8712/usb_ops_linux.c @@ -50,7 +50,7 @@ uint r8712_usb_init_intf_priv(struct intf_priv *pintfpriv) pintfpriv->piorw_urb = usb_alloc_urb(0, GFP_ATOMIC); if (!pintfpriv->piorw_urb) return _FAIL; - sema_init(&(pintfpriv->io_retevt), 0); + init_completion(&pintfpriv->io_retevt_comp); return _SUCCESS; } @@ -163,7 +163,7 @@ static void usb_write_mem_complete(struct urb *purb) else padapter->bSurpriseRemoved = true; } - up(&pintfpriv->io_retevt); + complete(&pintfpriv->io_retevt_comp); } void r8712_usb_write_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem) @@ -187,7 +187,7 @@ void r8712_usb_write_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem) wmem, cnt, usb_write_mem_complete, pio_queue); usb_submit_urb(piorw_urb, GFP_ATOMIC); - _down_sema(&pintfpriv->io_retevt); + wait_for_completion_interruptible(&pintfpriv->io_retevt_comp); } static void r8712_usb_read_port_complete(struct urb *purb) -- cgit v0.10.2 From af07477f594d131c8e9bda419ea3d9c38b950ee5 Mon Sep 17 00:00:00 2001 From: Anuradha Weeraman <anuradha@weeraman.com> Date: Mon, 27 Jun 2016 13:12:16 +0530 Subject: Staging: rtl8712: Fixed brace and comment style issue Fixed issues with coding style. Signed-off-by: Anuradha Weeraman <anuradha@weeraman.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8712/xmit_linux.c b/drivers/staging/rtl8712/xmit_linux.c index 695f9b9..1e86133 100644 --- a/drivers/staging/rtl8712/xmit_linux.c +++ b/drivers/staging/rtl8712/xmit_linux.c @@ -91,7 +91,8 @@ void r8712_set_qos(struct pkt_file *ppktfile, struct pkt_attrib *pattrib) } else { /* "When priority processing of data frames is supported, * a STA's SME should send EAPOL-Key frames at the highest - * priority." */ + * priority." + */ if (pattrib->ether_type == 0x888e) UserPriority = 7; @@ -162,16 +163,16 @@ int r8712_xmit_entry(_pkt *pkt, struct net_device *pnetdev) struct _adapter *padapter = netdev_priv(pnetdev); struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); - if (!r8712_if_up(padapter)) { + if (!r8712_if_up(padapter)) goto _xmit_entry_drop; - } + pxmitframe = r8712_alloc_xmitframe(pxmitpriv); - if (!pxmitframe) { + if (!pxmitframe) goto _xmit_entry_drop; - } - if ((!r8712_update_attrib(padapter, pkt, &pxmitframe->attrib))) { + + if ((!r8712_update_attrib(padapter, pkt, &pxmitframe->attrib))) goto _xmit_entry_drop; - } + padapter->ledpriv.LedControlHandler(padapter, LED_CTL_TX); pxmitframe->pkt = pkt; if (r8712_pre_xmit(padapter, pxmitframe)) { -- cgit v0.10.2 From d25f658df2664d24b0a0af5578fd1744fa56e9aa Mon Sep 17 00:00:00 2001 From: Parth Sane <laerdevstudios@gmail.com> Date: Wed, 8 Jun 2016 16:57:45 +0530 Subject: staging: rtl8712: Fixed multiple parenthesis alignment warnings in ieee80211.c Multiple parenthesis alignment warnings were thrown by checkpatch in ieee80211.c This patch effectively fixes that. Signed-off-by: Parth Sane <laerdevstudios@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8712/ieee80211.c b/drivers/staging/rtl8712/ieee80211.c index 8918654..5dc3b5b 100644 --- a/drivers/staging/rtl8712/ieee80211.c +++ b/drivers/staging/rtl8712/ieee80211.c @@ -145,7 +145,7 @@ static void set_supported_rate(u8 *rates, uint mode) case WIRELESS_11BG: memcpy(rates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN); memcpy(rates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES, - IEEE80211_NUM_OFDM_RATESLEN); + IEEE80211_NUM_OFDM_RATESLEN); break; } } @@ -188,24 +188,24 @@ int r8712_generate_ie(struct registry_priv *pregistrypriv) ie += 2; /*SSID*/ ie = r8712_set_ie(ie, _SSID_IE_, pdev_network->Ssid.SsidLength, - pdev_network->Ssid.Ssid, &sz); + pdev_network->Ssid.Ssid, &sz); /*supported rates*/ set_supported_rate(pdev_network->rates, pregistrypriv->wireless_mode); rateLen = r8712_get_rateset_len(pdev_network->rates); if (rateLen > 8) { ie = r8712_set_ie(ie, _SUPPORTEDRATES_IE_, 8, - pdev_network->rates, &sz); + pdev_network->rates, &sz); ie = r8712_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), - (pdev_network->rates + 8), &sz); + (pdev_network->rates + 8), &sz); } else ie = r8712_set_ie(ie, _SUPPORTEDRATES_IE_, - rateLen, pdev_network->rates, &sz); + rateLen, pdev_network->rates, &sz); /*DS parameter set*/ ie = r8712_set_ie(ie, _DSSET_IE_, 1, - (u8 *)&(pdev_network->Configuration.DSConfig), &sz); + (u8 *)&(pdev_network->Configuration.DSConfig), &sz); /*IBSS Parameter Set*/ ie = r8712_set_ie(ie, _IBSS_PARA_IE_, 2, - (u8 *)&(pdev_network->Configuration.ATIMWindow), &sz); + (u8 *)&(pdev_network->Configuration.ATIMWindow), &sz); return sz; } @@ -220,8 +220,7 @@ unsigned char *r8712_get_wpa_ie(unsigned char *pie, int *wpa_ie_len, int limit) pbuf = r8712_get_ie(pbuf, _WPA_IE_ID_, &len, limit); if (pbuf) { /*check if oui matches...*/ - if (memcmp((pbuf + 2), wpa_oui_type, - sizeof(wpa_oui_type))) + if (memcmp((pbuf + 2), wpa_oui_type, sizeof(wpa_oui_type))) goto check_next_ie; /*check version...*/ memcpy((u8 *)&val16, (pbuf + 6), sizeof(val16)); @@ -279,7 +278,7 @@ static int r8712_get_wpa2_cipher_suite(u8 *s) } int r8712_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher, - int *pairwise_cipher) + int *pairwise_cipher) { int i; int left, count; @@ -322,7 +321,7 @@ int r8712_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher, } int r8712_parse_wpa2_ie(u8 *rsn_ie, int rsn_ie_len, int *group_cipher, - int *pairwise_cipher) + int *pairwise_cipher) { int i; int left, count; @@ -365,7 +364,7 @@ int r8712_parse_wpa2_ie(u8 *rsn_ie, int rsn_ie_len, int *group_cipher, } int r8712_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len, - u8 *wpa_ie, u16 *wpa_len) + u8 *wpa_ie, u16 *wpa_len) { u8 authmode; u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01}; @@ -383,7 +382,7 @@ int r8712_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len, } else { if (authmode == _WPA2_IE_ID_) { memcpy(rsn_ie, &in_ie[cnt], - in_ie[cnt + 1] + 2); + in_ie[cnt + 1] + 2); *rsn_len = in_ie[cnt + 1] + 2; cnt += in_ie[cnt + 1] + 2; /*get next*/ } else { -- cgit v0.10.2 From 74a3b060bc29851d7caf42b9c8c3c1129fd50553 Mon Sep 17 00:00:00 2001 From: Larry Finger <Larry.Finger@lwfinger.net> Date: Fri, 3 Jun 2016 20:17:35 -0500 Subject: staging: r8712u: Check pointer before use Routine r8712_usb_read_port() dereferences "precvbuf" before testing it for NULL. Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8712/usb_ops_linux.c b/drivers/staging/rtl8712/usb_ops_linux.c index 1af7f5f..0f39ea8 100644 --- a/drivers/staging/rtl8712/usb_ops_linux.c +++ b/drivers/staging/rtl8712/usb_ops_linux.c @@ -270,51 +270,47 @@ u32 r8712_usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem) struct usb_device *pusbd = pdvobj->pusbdev; if (adapter->bDriverStopped || adapter->bSurpriseRemoved || - adapter->pwrctrlpriv.pnp_bstop_trx) + adapter->pwrctrlpriv.pnp_bstop_trx || !precvbuf) return _FAIL; if (precvbuf->reuse || !precvbuf->pskb) { precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue); if (precvbuf->pskb != NULL) precvbuf->reuse = true; } - if (precvbuf != NULL) { - r8712_init_recvbuf(adapter, precvbuf); - /* re-assign for linux based on skb */ - if (!precvbuf->reuse || !precvbuf->pskb) { - precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev, - MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ); - if (!precvbuf->pskb) - return _FAIL; - tmpaddr = (addr_t)precvbuf->pskb->data; - alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1); - skb_reserve(precvbuf->pskb, - (RECVBUFF_ALIGN_SZ - alignment)); - precvbuf->phead = precvbuf->pskb->head; - precvbuf->pdata = precvbuf->pskb->data; - precvbuf->ptail = skb_tail_pointer(precvbuf->pskb); - precvbuf->pend = skb_end_pointer(precvbuf->pskb); - precvbuf->pbuf = precvbuf->pskb->data; - } else { /* reuse skb */ - precvbuf->phead = precvbuf->pskb->head; - precvbuf->pdata = precvbuf->pskb->data; - precvbuf->ptail = skb_tail_pointer(precvbuf->pskb); - precvbuf->pend = skb_end_pointer(precvbuf->pskb); - precvbuf->pbuf = precvbuf->pskb->data; - precvbuf->reuse = false; - } - purb = precvbuf->purb; - /* translate DMA FIFO addr to pipehandle */ - pipe = ffaddr2pipehdl(pdvobj, addr); - usb_fill_bulk_urb(purb, pusbd, pipe, - precvbuf->pbuf, MAX_RECVBUF_SZ, - r8712_usb_read_port_complete, - precvbuf); - err = usb_submit_urb(purb, GFP_ATOMIC); - if ((err) && (err != (-EPERM))) - ret = _FAIL; - } else { - ret = _FAIL; + r8712_init_recvbuf(adapter, precvbuf); + /* re-assign for linux based on skb */ + if (!precvbuf->reuse || !precvbuf->pskb) { + precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev, + MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ); + if (!precvbuf->pskb) + return _FAIL; + tmpaddr = (addr_t)precvbuf->pskb->data; + alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1); + skb_reserve(precvbuf->pskb, + (RECVBUFF_ALIGN_SZ - alignment)); + precvbuf->phead = precvbuf->pskb->head; + precvbuf->pdata = precvbuf->pskb->data; + precvbuf->ptail = skb_tail_pointer(precvbuf->pskb); + precvbuf->pend = skb_end_pointer(precvbuf->pskb); + precvbuf->pbuf = precvbuf->pskb->data; + } else { /* reuse skb */ + precvbuf->phead = precvbuf->pskb->head; + precvbuf->pdata = precvbuf->pskb->data; + precvbuf->ptail = skb_tail_pointer(precvbuf->pskb); + precvbuf->pend = skb_end_pointer(precvbuf->pskb); + precvbuf->pbuf = precvbuf->pskb->data; + precvbuf->reuse = false; } + purb = precvbuf->purb; + /* translate DMA FIFO addr to pipehandle */ + pipe = ffaddr2pipehdl(pdvobj, addr); + usb_fill_bulk_urb(purb, pusbd, pipe, + precvbuf->pbuf, MAX_RECVBUF_SZ, + r8712_usb_read_port_complete, + precvbuf); + err = usb_submit_urb(purb, GFP_ATOMIC); + if ((err) && (err != (-EPERM))) + ret = _FAIL; return ret; } -- cgit v0.10.2 From 78ece0b94518816f08f4e60fae62d078aa4cb63d Mon Sep 17 00:00:00 2001 From: Larry Finger <Larry.Finger@lwfinger.net> Date: Fri, 3 Jun 2016 20:17:36 -0500 Subject: staging: r8712u: Fix leak of skb There are two types of messages queued for RX. The major type, which does I/O on the device, was being handled properly. The skbs that communicated with the firmware were being leaked. While rewriting the code that sets up the skb, it was possible to remove the private variable indicating that the old skb could be reused. Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8712/recv_linux.c b/drivers/staging/rtl8712/recv_linux.c index 735a0ea..576c15d 100644 --- a/drivers/staging/rtl8712/recv_linux.c +++ b/drivers/staging/rtl8712/recv_linux.c @@ -60,7 +60,6 @@ int r8712_os_recvbuf_resource_alloc(struct _adapter *padapter, if (!precvbuf->purb) res = _FAIL; precvbuf->pskb = NULL; - precvbuf->reuse = false; precvbuf->pallocated_buf = NULL; precvbuf->pbuf = NULL; precvbuf->pdata = NULL; diff --git a/drivers/staging/rtl8712/rtl8712_recv.h b/drivers/staging/rtl8712/rtl8712_recv.h index fd9e3fc..925ec74 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.h +++ b/drivers/staging/rtl8712/rtl8712_recv.h @@ -103,7 +103,6 @@ struct recv_buf { struct _adapter *adapter; struct urb *purb; _pkt *pskb; - u8 reuse; u8 irp_pending; u32 transfer_len; uint len; diff --git a/drivers/staging/rtl8712/usb_ops_linux.c b/drivers/staging/rtl8712/usb_ops_linux.c index 0f39ea8..fc6bb0b 100644 --- a/drivers/staging/rtl8712/usb_ops_linux.c +++ b/drivers/staging/rtl8712/usb_ops_linux.c @@ -202,26 +202,23 @@ static void r8712_usb_read_port_complete(struct urb *purb) if (purb->status == 0) { /* SUCCESS */ if ((purb->actual_length > (MAX_RECVBUF_SZ)) || (purb->actual_length < RXDESC_SIZE)) { - precvbuf->reuse = true; r8712_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf); } else { + _pkt *pskb = precvbuf->pskb; + precvbuf->transfer_len = purb->actual_length; pbuf = (uint *)precvbuf->pbuf; isevt = le32_to_cpu(*(pbuf + 1)) & 0x1ff; if ((isevt & 0x1ff) == 0x1ff) { r8712_rxcmd_event_hdl(padapter, pbuf); - precvbuf->reuse = true; + skb_queue_tail(&precvpriv->rx_skb_queue, pskb); r8712_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf); } else { - _pkt *pskb = precvbuf->pskb; - skb_put(pskb, purb->actual_length); skb_queue_tail(&precvpriv->rx_skb_queue, pskb); tasklet_hi_schedule(&precvpriv->recv_tasklet); - precvbuf->pskb = NULL; - precvbuf->reuse = false; r8712_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf); } @@ -241,7 +238,6 @@ static void r8712_usb_read_port_complete(struct urb *purb) } /* Fall through. */ case -EPROTO: - precvbuf->reuse = true; r8712_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf); break; @@ -272,14 +268,11 @@ u32 r8712_usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem) if (adapter->bDriverStopped || adapter->bSurpriseRemoved || adapter->pwrctrlpriv.pnp_bstop_trx || !precvbuf) return _FAIL; - if (precvbuf->reuse || !precvbuf->pskb) { - precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue); - if (precvbuf->pskb != NULL) - precvbuf->reuse = true; - } r8712_init_recvbuf(adapter, precvbuf); - /* re-assign for linux based on skb */ - if (!precvbuf->reuse || !precvbuf->pskb) { + /* Try to use skb from the free queue */ + precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue); + + if (!precvbuf->pskb) { precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev, MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ); if (!precvbuf->pskb) @@ -293,13 +286,12 @@ u32 r8712_usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem) precvbuf->ptail = skb_tail_pointer(precvbuf->pskb); precvbuf->pend = skb_end_pointer(precvbuf->pskb); precvbuf->pbuf = precvbuf->pskb->data; - } else { /* reuse skb */ + } else { /* skb is reused */ precvbuf->phead = precvbuf->pskb->head; precvbuf->pdata = precvbuf->pskb->data; precvbuf->ptail = skb_tail_pointer(precvbuf->pskb); precvbuf->pend = skb_end_pointer(precvbuf->pskb); precvbuf->pbuf = precvbuf->pskb->data; - precvbuf->reuse = false; } purb = precvbuf->purb; /* translate DMA FIFO addr to pipehandle */ -- cgit v0.10.2 From 580b4105530796b63bbbf6a093678c60144275e9 Mon Sep 17 00:00:00 2001 From: Larry Finger <Larry.Finger@lwfinger.net> Date: Fri, 3 Jun 2016 20:17:37 -0500 Subject: staging: r8712u: Handle some false positives from kmemleak When this driver preallocates some URBs, kmemleak is unable to find that allocated memory when it scans. When the driver is unloaded, that memory is reclaimed, therefore, the report is a false positive. Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8712/xmit_linux.c b/drivers/staging/rtl8712/xmit_linux.c index 1e86133..4ee4136 100644 --- a/drivers/staging/rtl8712/xmit_linux.c +++ b/drivers/staging/rtl8712/xmit_linux.c @@ -31,6 +31,7 @@ #include <linux/usb.h> #include <linux/ip.h> #include <linux/if_ether.h> +#include <linux/kmemleak.h> #include "osdep_service.h" #include "drv_types.h" @@ -133,6 +134,7 @@ int r8712_xmit_resource_alloc(struct _adapter *padapter, netdev_err(padapter->pnetdev, "pxmitbuf->pxmit_urb[i] == NULL\n"); return _FAIL; } + kmemleak_not_leak(pxmitbuf->pxmit_urb[i]); } return _SUCCESS; } -- cgit v0.10.2 From bc83c4cfc2e643d7f053318f4bd2f6bae8936643 Mon Sep 17 00:00:00 2001 From: Larry Finger <Larry.Finger@lwfinger.net> Date: Sun, 5 Jun 2016 10:20:59 -0500 Subject: staging: r8188eu: Remove some false positives from kmemleak When this driver preallocates some SKBs, kmemleak is unable to find that allocated memory when it scans. When the driver is unloaded, that memory is released; therefore, the report is a false positive. Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c index 255d6f2..093a998 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c @@ -13,6 +13,7 @@ * ******************************************************************************/ #define _RTL8188EU_RECV_C_ +#include <linux/kmemleak.h> #include <osdep_service.h> #include <drv_types.h> #include <recv_osdep.h> @@ -72,6 +73,7 @@ int rtl8188eu_init_recv_priv(struct adapter *padapter) MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ, GFP_KERNEL); if (pskb) { + kmemleak_not_leak(pskb); pskb->dev = padapter->pnetdev; tmpaddr = (size_t)pskb->data; alignm = tmpaddr & (RECVBUFF_ALIGN_SZ-1); -- cgit v0.10.2 From 1335a9516d3d52f157ad87456efdd8dc9ae1747b Mon Sep 17 00:00:00 2001 From: Larry Finger <Larry.Finger@lwfinger.net> Date: Sun, 5 Jun 2016 14:11:19 -0500 Subject: staging: r8188eu: Fix scheduling while atomic splat Commit fadbe0cd5292851608e2e01b91d9295fa287b9fe ("staging: rtl8188eu: Remove rtw_zmalloc(), wrapper for kzalloc()") changed all allocation calls to be GFP_KERNEL even though the original wrapper was testing to determine if the caller was in atomic mode. Most of the mistakes were corrected with commit 33dc85c3c667209c930b2dac5ccbc2a365e06b7a ("staging: r8188eu: Fix scheduling while atomic error introduced in commit fadbe0cd"); however, two kzalloc calls were missed as the call only happens when the driver is shutting down. Fixes: fadbe0cd5292851608e2e01b91d9295fa287b9fe ("staging: rtl8188eu: Remove rtw_zmalloc(), wrapper for kzalloc()") Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net> Cc: navin patidar <navin.patidar@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_cmd.c b/drivers/staging/rtl8188eu/core/rtw_cmd.c index 9e12588..c0af5ab 100644 --- a/drivers/staging/rtl8188eu/core/rtw_cmd.c +++ b/drivers/staging/rtl8188eu/core/rtw_cmd.c @@ -670,13 +670,13 @@ u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr) u8 res = _SUCCESS; - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); + ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); if (!ph2c) { res = _FAIL; goto exit; } - paddbareq_parm = kzalloc(sizeof(struct addBaReq_parm), GFP_KERNEL); + paddbareq_parm = kzalloc(sizeof(struct addBaReq_parm), GFP_ATOMIC); if (!paddbareq_parm) { kfree(ph2c); res = _FAIL; -- cgit v0.10.2 From 394850666885b56e5a058f1bc1bb9983e6aba7ae Mon Sep 17 00:00:00 2001 From: Binoy Jayan <binoy.jayan@linaro.org> Date: Wed, 8 Jun 2016 13:10:54 +0530 Subject: staging: r8723au: pwrctrl_priv: Replace semaphore lock with mutex The semaphore 'lock' in pwrctrl_priv is a simple mutex, so it should be written as one. Semaphores are going away in the future. Signed-off-by: Binoy Jayan <binoy.jayan@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8723au/core/rtw_pwrctrl.c b/drivers/staging/rtl8723au/core/rtw_pwrctrl.c index 7488a10..2d43958 100644 --- a/drivers/staging/rtl8723au/core/rtw_pwrctrl.c +++ b/drivers/staging/rtl8723au/core/rtw_pwrctrl.c @@ -14,6 +14,7 @@ ******************************************************************************/ #define _RTW_PWRCTRL_C_ +#include <linux/mutex.h> #include <osdep_service.h> #include <drv_types.h> #include <osdep_intf.h> @@ -27,7 +28,7 @@ void ips_enter23a(struct rtw_adapter *padapter) { struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - down(&pwrpriv->lock); + mutex_lock(&pwrpriv->mutex_lock); pwrpriv->bips_processing = true; @@ -50,7 +51,7 @@ void ips_enter23a(struct rtw_adapter *padapter) } pwrpriv->bips_processing = false; - up(&pwrpriv->lock); + mutex_unlock(&pwrpriv->mutex_lock); } int ips_leave23a(struct rtw_adapter *padapter) @@ -61,7 +62,7 @@ int ips_leave23a(struct rtw_adapter *padapter) int result = _SUCCESS; int keyid; - down(&pwrpriv->lock); + mutex_lock(&pwrpriv->mutex_lock); if (pwrpriv->rf_pwrstate == rf_off && !pwrpriv->bips_processing) { pwrpriv->bips_processing = true; @@ -106,7 +107,7 @@ int ips_leave23a(struct rtw_adapter *padapter) pwrpriv->bpower_saving = false; } - up(&pwrpriv->lock); + mutex_unlock(&pwrpriv->mutex_lock); return result; } @@ -423,7 +424,7 @@ void rtw_init_pwrctrl_priv23a(struct rtw_adapter *padapter) { struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; - sema_init(&pwrctrlpriv->lock, 1); + mutex_init(&pwrctrlpriv->mutex_lock); pwrctrlpriv->rf_pwrstate = rf_on; pwrctrlpriv->ips_enter23a_cnts = 0; pwrctrlpriv->ips_leave23a_cnts = 0; diff --git a/drivers/staging/rtl8723au/include/rtw_pwrctrl.h b/drivers/staging/rtl8723au/include/rtw_pwrctrl.h index 599fed9..699b9f3 100644 --- a/drivers/staging/rtl8723au/include/rtw_pwrctrl.h +++ b/drivers/staging/rtl8723au/include/rtw_pwrctrl.h @@ -15,6 +15,7 @@ #ifndef __RTW_PWRCTRL_H_ #define __RTW_PWRCTRL_H_ +#include <linux/mutex.h> #include <osdep_service.h> #include <drv_types.h> @@ -149,7 +150,7 @@ enum { /* for ips_mode */ }; struct pwrctrl_priv { - struct semaphore lock; + struct mutex mutex_lock; volatile u8 rpwm; /* requested power state for fw */ volatile u8 cpwm; /* fw current power state. updated when 1. * read from HCPWM 2. driver lowers power level diff --git a/drivers/staging/rtl8723au/os_dep/usb_intf.c b/drivers/staging/rtl8723au/os_dep/usb_intf.c index cf83eff..fa7dda5 100644 --- a/drivers/staging/rtl8723au/os_dep/usb_intf.c +++ b/drivers/staging/rtl8723au/os_dep/usb_intf.c @@ -14,6 +14,7 @@ ******************************************************************************/ #define _HCI_INTF_C_ +#include <linux/mutex.h> #include <osdep_service.h> #include <drv_types.h> #include <recv_osdep.h> @@ -291,7 +292,7 @@ static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message) rtw_cancel_all_timer23a(padapter); LeaveAllPowerSaveMode23a(padapter); - down(&pwrpriv->lock); + mutex_lock(&pwrpriv->mutex_lock); /* padapter->net_closed = true; */ /* s1. */ if (pnetdev) { @@ -321,7 +322,7 @@ static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message) rtw_free_network_queue23a(padapter); rtw_dev_unload(padapter); - up(&pwrpriv->lock); + mutex_unlock(&pwrpriv->mutex_lock); if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) rtw_cfg80211_indicate_scan_done( @@ -353,20 +354,20 @@ static int rtw_resume(struct usb_interface *pusb_intf) pnetdev = padapter->pnetdev; pwrpriv = &padapter->pwrctrlpriv; - down(&pwrpriv->lock); + mutex_lock(&pwrpriv->mutex_lock); rtw_reset_drv_sw23a(padapter); pwrpriv->bkeepfwalive = false; DBG_8723A("bkeepfwalive(%x)\n", pwrpriv->bkeepfwalive); if (pm_netdev_open23a(pnetdev, true) != 0) { - up(&pwrpriv->lock); + mutex_unlock(&pwrpriv->mutex_lock); goto exit; } netif_device_attach(pnetdev); netif_carrier_on(pnetdev); - up(&pwrpriv->lock); + mutex_unlock(&pwrpriv->mutex_lock); if (padapter->pid[1] != 0) { DBG_8723A("pid[1]:%d\n", padapter->pid[1]); -- cgit v0.10.2 From 243d38aab204bfd1c33ad6f412b654c9f7eed8cb Mon Sep 17 00:00:00 2001 From: Binoy Jayan <binoy.jayan@linaro.org> Date: Wed, 8 Jun 2016 13:10:55 +0530 Subject: staging: r8723au: Remove unused semaphores The semaphores xmit_sema, terminate_xmitthread_sema, tx_retevt and io_req have no users, hence remove all references to them. Semaphores are going away in the future. Signed-off-by: Binoy Jayan <binoy.jayan@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8723au/core/rtw_xmit.c b/drivers/staging/rtl8723au/core/rtw_xmit.c index 3de40cf..003576d 100644 --- a/drivers/staging/rtl8723au/core/rtw_xmit.c +++ b/drivers/staging/rtl8723au/core/rtw_xmit.c @@ -60,8 +60,6 @@ int _rtw_init_xmit_priv23a(struct xmit_priv *pxmitpriv, spin_lock_init(&pxmitpriv->lock); spin_lock_init(&pxmitpriv->lock_sctx); - sema_init(&pxmitpriv->xmit_sema, 0); - sema_init(&pxmitpriv->terminate_xmitthread_sema, 0); pxmitpriv->adapter = padapter; @@ -177,8 +175,6 @@ int _rtw_init_xmit_priv23a(struct xmit_priv *pxmitpriv, for (i = 0; i < 4; i ++) pxmitpriv->wmm_para_seq[i] = i; - sema_init(&pxmitpriv->tx_retevt, 0); - pxmitpriv->ack_tx = false; mutex_init(&pxmitpriv->ack_tx_mutex); rtw_sctx_init23a(&pxmitpriv->ack_tx_ops, 0); diff --git a/drivers/staging/rtl8723au/include/osdep_service.h b/drivers/staging/rtl8723au/include/osdep_service.h index 98250b1..33ecb9c 100644 --- a/drivers/staging/rtl8723au/include/osdep_service.h +++ b/drivers/staging/rtl8723au/include/osdep_service.h @@ -33,7 +33,6 @@ #include <asm/byteorder.h> #include <linux/atomic.h> #include <linux/io.h> -#include <linux/semaphore.h> #include <linux/sem.h> #include <linux/sched.h> #include <linux/etherdevice.h> diff --git a/drivers/staging/rtl8723au/include/rtw_io.h b/drivers/staging/rtl8723au/include/rtw_io.h index c8119e2..d875e9e 100644 --- a/drivers/staging/rtl8723au/include/rtw_io.h +++ b/drivers/staging/rtl8723au/include/rtw_io.h @@ -20,7 +20,6 @@ #include <osdep_intf.h> #include <asm/byteorder.h> -#include <linux/semaphore.h> #include <linux/list.h> /* include <linux/smp_lock.h> */ #include <linux/spinlock.h> @@ -105,7 +104,6 @@ struct io_req { u32 command; u32 status; u8 *pbuf; - struct semaphore sema; void (*_async_io_callback)(struct rtw_adapter *padater, struct io_req *pio_req, u8 *cnxt); u8 *cnxt; diff --git a/drivers/staging/rtl8723au/include/rtw_xmit.h b/drivers/staging/rtl8723au/include/rtw_xmit.h index 2b7d6d0..24f326b 100644 --- a/drivers/staging/rtl8723au/include/rtw_xmit.h +++ b/drivers/staging/rtl8723au/include/rtw_xmit.h @@ -275,9 +275,6 @@ struct agg_pkt_info { struct xmit_priv { spinlock_t lock; - struct semaphore xmit_sema; - struct semaphore terminate_xmitthread_sema; - struct rtw_queue be_pending; struct rtw_queue bk_pending; struct rtw_queue vi_pending; @@ -310,8 +307,6 @@ struct xmit_priv { * 2->be, 3->bk. */ - struct semaphore tx_retevt;/* all tx return event; */ - struct tasklet_struct xmit_tasklet; struct rtw_queue free_xmitbuf_queue; -- cgit v0.10.2 From df5e9b5fbc4e68a0f0345fbc0f65e60d7440279f Mon Sep 17 00:00:00 2001 From: Nipun Gupta <nipun.gupta@nxp.com> Date: Wed, 29 Jun 2016 22:44:39 +0530 Subject: fsl-mc: add helper macro to determine if a device is of fsl_mc type Add a helper macro to return if a device has a bus type of fsl_mc. This makes the bus driver code more readable and provides a way for drivers like the SMMU driver to easily check the bus type. Signed-off-by: Nipun Gupta <nipun.gupta@nxp.com> Signed-off-by: Bharat Bhushan <bharat.bhushan@nxp.com> Acked-by: Stuart Yoder <stuart.yoder@nxp.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c index d2a71f1..0523ba8 100644 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c +++ b/drivers/staging/fsl-mc/bus/dprc-driver.c @@ -649,7 +649,7 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) /* * This is a child DPRC: */ - if (WARN_ON(parent_dev->bus != &fsl_mc_bus_type)) + if (WARN_ON(!dev_is_fsl_mc(parent_dev))) return -EINVAL; if (WARN_ON(mc_dev->obj_desc.region_count == 0)) @@ -681,7 +681,7 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) */ struct irq_domain *mc_msi_domain; - if (WARN_ON(parent_dev->bus == &fsl_mc_bus_type)) + if (WARN_ON(dev_is_fsl_mc(parent_dev))) return -EINVAL; error = fsl_mc_find_msi_domain(parent_dev, diff --git a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c index 720e2b0..d0c20d6 100644 --- a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c +++ b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c @@ -35,7 +35,7 @@ static int its_fsl_mc_msi_prepare(struct irq_domain *msi_domain, struct fsl_mc_device *mc_bus_dev; struct msi_domain_info *msi_info; - if (WARN_ON(dev->bus != &fsl_mc_bus_type)) + if (WARN_ON(!dev_is_fsl_mc(dev))) return -EINVAL; mc_bus_dev = to_fsl_mc_device(dev); diff --git a/drivers/staging/fsl-mc/bus/mc-allocator.c b/drivers/staging/fsl-mc/bus/mc-allocator.c index e59d850..0f50a07 100644 --- a/drivers/staging/fsl-mc/bus/mc-allocator.c +++ b/drivers/staging/fsl-mc/bus/mc-allocator.c @@ -281,7 +281,7 @@ int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, if (mc_dev->flags & FSL_MC_IS_DPRC) { mc_bus_dev = mc_dev; } else { - if (WARN_ON(mc_dev->dev.parent->bus != &fsl_mc_bus_type)) + if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent))) return error; mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); @@ -420,7 +420,7 @@ int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev, if (WARN_ON(mc_dev->flags & FSL_MC_IS_DPRC)) goto error; - if (WARN_ON(mc_dev->dev.parent->bus != &fsl_mc_bus_type)) + if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent))) goto error; if (WARN_ON(pool_type == FSL_MC_POOL_DPMCP)) @@ -678,7 +678,7 @@ static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev) return -EINVAL; mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); - if (WARN_ON(mc_bus_dev->dev.bus != &fsl_mc_bus_type)) + if (WARN_ON(!dev_is_fsl_mc(&mc_bus_dev->dev))) return -EINVAL; mc_bus = to_fsl_mc_bus(mc_bus_dev); diff --git a/drivers/staging/fsl-mc/bus/mc-bus.c b/drivers/staging/fsl-mc/bus/mc-bus.c index db3afdb..b549005 100644 --- a/drivers/staging/fsl-mc/bus/mc-bus.c +++ b/drivers/staging/fsl-mc/bus/mc-bus.c @@ -236,11 +236,11 @@ static void fsl_mc_get_root_dprc(struct device *dev, { if (WARN_ON(!dev)) { *root_dprc_dev = NULL; - } else if (WARN_ON(dev->bus != &fsl_mc_bus_type)) { + } else if (WARN_ON(!dev_is_fsl_mc(dev))) { *root_dprc_dev = NULL; } else { *root_dprc_dev = dev; - while ((*root_dprc_dev)->parent->bus == &fsl_mc_bus_type) + while (dev_is_fsl_mc((*root_dprc_dev)->parent)) *root_dprc_dev = (*root_dprc_dev)->parent; } } @@ -434,7 +434,7 @@ int fsl_mc_device_add(struct dprc_obj_desc *obj_desc, struct fsl_mc_bus *mc_bus = NULL; struct fsl_mc_device *parent_mc_dev; - if (parent_dev->bus == &fsl_mc_bus_type) + if (dev_is_fsl_mc(parent_dev)) parent_mc_dev = to_fsl_mc_device(parent_dev); else parent_mc_dev = NULL; diff --git a/drivers/staging/fsl-mc/include/mc.h b/drivers/staging/fsl-mc/include/mc.h index 853cbf3..2d67535 100644 --- a/drivers/staging/fsl-mc/include/mc.h +++ b/drivers/staging/fsl-mc/include/mc.h @@ -166,6 +166,13 @@ struct fsl_mc_device { #define to_fsl_mc_device(_dev) \ container_of(_dev, struct fsl_mc_device, dev) +#ifdef CONFIG_FSL_MC_BUS +#define dev_is_fsl_mc(_dev) ((_dev)->bus == &fsl_mc_bus_type) +#else +/* If fsl-mc bus is not present device cannot belong to fsl-mc bus */ +#define dev_is_fsl_mc(_dev) (0) +#endif + /* * module_fsl_mc_driver() - Helper macro for drivers that don't do * anything special in module init/exit. This eliminates a lot of -- cgit v0.10.2 From 37f144008a36bd8394ebc00ac562a1bbf426c7a5 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker <paul.gortmaker@windriver.com> Date: Sat, 2 Jul 2016 19:48:51 -0400 Subject: staging: fsl-mc: make bus/mc-bus explicitly non-modular The Kconfig currently controlling compilation of this code is: config FSL_MC_BUS bool "Freescale Management Complex (MC) bus driver" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since the code was already not using module_init, we don't have to change the initcall and the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag etc. since all that information is already contained at the top of the file in the comments. We don't replace module.h with init.h since the file does make some references to "struct *module" for processing other modules. Cc: "J. German Rivera" <German.Rivera@freescale.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: devel@driverdev.osuosl.org Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fsl-mc/bus/mc-bus.c b/drivers/staging/fsl-mc/bus/mc-bus.c index b549005..fe20c5d 100644 --- a/drivers/staging/fsl-mc/bus/mc-bus.c +++ b/drivers/staging/fsl-mc/bus/mc-bus.c @@ -887,25 +887,4 @@ error_cleanup_cache: kmem_cache_destroy(mc_dev_cache); return error; } - postcore_initcall(fsl_mc_bus_driver_init); - -static void __exit fsl_mc_bus_driver_exit(void) -{ - if (WARN_ON(!mc_dev_cache)) - return; - - its_fsl_mc_msi_cleanup(); - fsl_mc_allocator_driver_exit(); - dprc_driver_exit(); - platform_driver_unregister(&fsl_mc_bus_driver); - bus_unregister(&fsl_mc_bus_type); - kmem_cache_destroy(mc_dev_cache); - pr_info("MC bus unregistered\n"); -} - -module_exit(fsl_mc_bus_driver_exit); - -MODULE_AUTHOR("Freescale Semiconductor Inc."); -MODULE_DESCRIPTION("Freescale Management Complex (MC) bus driver"); -MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 9731ee897356c9077995b0c454fe19f7fa93ea5d Mon Sep 17 00:00:00 2001 From: Colin Ian King <colin.king@canonical.com> Date: Thu, 14 Jul 2016 11:21:28 +0100 Subject: staging: rtl8723au: hal: check BT_Active and BT_State with correct bit pattern BT_Active and BT_State are being masked with 0x00ffffff so it the subsequent comparisons with 0xffffffff are therefore a buggy check. Instead, check them against 0x00ffffff. Unfortunately I couldn't find a datasheet or hardware to see if 0xffffffff is an expected invalid bit pattern that should be checked before BT_Active and BT_State are masked with 0x00ffffff, so for now, this fix seems like the least risky approach. Signed-off-by: Colin Ian King <colin.king@canonical.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c b/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c index bfcbd7a..6989580 100644 --- a/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c +++ b/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c @@ -9824,7 +9824,7 @@ void BTDM_CheckBTIdleChange1Ant(struct rtw_adapter *padapter) BT_Polling = rtl8723au_read32(padapter, regBTPolling); RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT_Polling(0x%x) =%x\n", regBTPolling, BT_Polling)); - if (BT_Active == 0xffffffff && BT_State == 0xffffffff && BT_Polling == 0xffffffff) + if (BT_Active == 0x00ffffff && BT_State == 0x00ffffff && BT_Polling == 0xffffffff) return; if (BT_Polling == 0) return; -- cgit v0.10.2 From 22274c15e2be896e7ed166e609b383393e7cc18c Mon Sep 17 00:00:00 2001 From: Shiva Kerdel <shiva@exdev.nl> Date: Fri, 5 Aug 2016 22:14:41 +0200 Subject: Staging: rtl8723au: rtw_ieee80211: Fixed operators spacing style issues Fixed spaces around operators to fix their coding style issues. Signed-off-by: Shiva Kerdel <shiva@exdev.nl> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8723au/core/rtw_ieee80211.c b/drivers/staging/rtl8723au/core/rtw_ieee80211.c index 07a6490..9fa0ef1 100644 --- a/drivers/staging/rtl8723au/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8723au/core/rtw_ieee80211.c @@ -65,7 +65,7 @@ static u8 WIFI_OFDMRATES[] = { int rtw_get_bit_value_from_ieee_value23a(u8 val) { - unsigned char dot11_rate_table[]= + unsigned char dot11_rate_table[] = {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 0}; int i = 0; @@ -140,7 +140,7 @@ u8 *rtw_set_ie23a(u8 *pbuf, int index, uint len, const u8 *source, uint *frlen) return pbuf + len + 2; } -inline u8 *rtw_set_ie23a_ch_switch (u8 *buf, u32 *buf_len, u8 ch_switch_mode, +inline u8 *rtw_set_ie23a_ch_switch(u8 *buf, u32 *buf_len, u8 ch_switch_mode, u8 new_ch, u8 ch_switch_cnt) { u8 ie_data[3]; @@ -230,14 +230,14 @@ u8 *rtw_get_ie23a_ex(u8 *in_ie, uint in_len, u8 eid, u8 *oui, u8 oui_len, while (cnt < in_len) { if (eid == in_ie[cnt] && - (!oui || !memcmp(&in_ie[cnt+2], oui, oui_len))) { + (!oui || !memcmp(&in_ie[cnt + 2], oui, oui_len))) { target_ie = &in_ie[cnt]; if (ie) - memcpy(ie, &in_ie[cnt], in_ie[cnt+1]+2); + memcpy(ie, &in_ie[cnt], in_ie[cnt + 1] + 2); if (ielen) - *ielen = in_ie[cnt+1]+2; + *ielen = in_ie[cnt + 1] + 2; break; } else { cnt += in_ie[cnt + 1] + 2; /* goto next */ @@ -331,7 +331,7 @@ uint rtw_get_rateset_len23a(u8 *rateset) { uint i = 0; - while(1) { + while (1) { if (rateset[i] == 0) break; @@ -378,7 +378,7 @@ int rtw_generate_ie23a(struct registry_priv *pregistrypriv) wireless_mode = pregistrypriv->wireless_mode; } - rtw_set_supported_rate23a(pdev_network->SupportedRates, wireless_mode) ; + rtw_set_supported_rate23a(pdev_network->SupportedRates, wireless_mode); rateLen = rtw_get_rateset_len23a(pdev_network->SupportedRates); @@ -533,7 +533,7 @@ int rtw_parse_wpa2_ie23a(const u8 *rsn_ie, int rsn_ie_len, int *group_cipher, return _FAIL; } - if (*rsn_ie != WLAN_EID_RSN || *(rsn_ie+1) != (u8)(rsn_ie_len - 2)) { + if (*rsn_ie != WLAN_EID_RSN || *(rsn_ie + 1) != (u8)(rsn_ie_len - 2)) { return _FAIL; } @@ -791,64 +791,64 @@ u16 rtw_mcs_rate23a(u8 rf_type, u8 bw_40MHz, u8 short_GI_20, u8 short_GI_40, if (rf_type == RF_1T1R) { if (mcs->rx_mask[0] & BIT(7)) - max_rate = (bw_40MHz) ? ((short_GI_40)?1500:1350): - ((short_GI_20)?722:650); + max_rate = (bw_40MHz) ? ((short_GI_40) ? 1500 : 1350) : + ((short_GI_20) ? 722 : 650); else if (mcs->rx_mask[0] & BIT(6)) - max_rate = (bw_40MHz) ? ((short_GI_40)?1350:1215): - ((short_GI_20)?650:585); + max_rate = (bw_40MHz) ? ((short_GI_40) ? 1350 : 1215) : + ((short_GI_20) ? 650 : 585); else if (mcs->rx_mask[0] & BIT(5)) - max_rate = (bw_40MHz) ? ((short_GI_40)?1200:1080): - ((short_GI_20)?578:520); + max_rate = (bw_40MHz) ? ((short_GI_40) ? 1200 : 1080) : + ((short_GI_20) ? 578 : 520); else if (mcs->rx_mask[0] & BIT(4)) - max_rate = (bw_40MHz) ? ((short_GI_40)?900:810): - ((short_GI_20)?433:390); + max_rate = (bw_40MHz) ? ((short_GI_40) ? 900 : 810) : + ((short_GI_20) ? 433 : 390); else if (mcs->rx_mask[0] & BIT(3)) - max_rate = (bw_40MHz) ? ((short_GI_40)?600:540): - ((short_GI_20)?289:260); + max_rate = (bw_40MHz) ? ((short_GI_40) ? 600 : 540) : + ((short_GI_20) ? 289 : 260); else if (mcs->rx_mask[0] & BIT(2)) - max_rate = (bw_40MHz) ? ((short_GI_40)?450:405): - ((short_GI_20)?217:195); + max_rate = (bw_40MHz) ? ((short_GI_40) ? 450 : 405) : + ((short_GI_20) ? 217 : 195); else if (mcs->rx_mask[0] & BIT(1)) - max_rate = (bw_40MHz) ? ((short_GI_40)?300:270): - ((short_GI_20)?144:130); + max_rate = (bw_40MHz) ? ((short_GI_40) ? 300 : 270) : + ((short_GI_20) ? 144 : 130); else if (mcs->rx_mask[0] & BIT(0)) - max_rate = (bw_40MHz) ? ((short_GI_40)?150:135): - ((short_GI_20)?72:65); + max_rate = (bw_40MHz) ? ((short_GI_40) ? 150 : 135) : + ((short_GI_20) ? 72 : 65); } else { if (mcs->rx_mask[1]) { if (mcs->rx_mask[1] & BIT(7)) - max_rate = (bw_40MHz) ? ((short_GI_40)?3000:2700):((short_GI_20)?1444:1300); + max_rate = (bw_40MHz) ? ((short_GI_40) ? 3000 : 2700) : ((short_GI_20) ? 1444 : 1300); else if (mcs->rx_mask[1] & BIT(6)) - max_rate = (bw_40MHz) ? ((short_GI_40)?2700:2430):((short_GI_20)?1300:1170); + max_rate = (bw_40MHz) ? ((short_GI_40) ? 2700 : 2430) : ((short_GI_20) ? 1300 : 1170); else if (mcs->rx_mask[1] & BIT(5)) - max_rate = (bw_40MHz) ? ((short_GI_40)?2400:2160):((short_GI_20)?1156:1040); + max_rate = (bw_40MHz) ? ((short_GI_40) ? 2400 : 2160) : ((short_GI_20) ? 1156 : 1040); else if (mcs->rx_mask[1] & BIT(4)) - max_rate = (bw_40MHz) ? ((short_GI_40)?1800:1620):((short_GI_20)?867:780); + max_rate = (bw_40MHz) ? ((short_GI_40) ? 1800 : 1620) : ((short_GI_20) ? 867 : 780); else if (mcs->rx_mask[1] & BIT(3)) - max_rate = (bw_40MHz) ? ((short_GI_40)?1200:1080):((short_GI_20)?578:520); + max_rate = (bw_40MHz) ? ((short_GI_40) ? 1200 : 1080) : ((short_GI_20) ? 578 : 520); else if (mcs->rx_mask[1] & BIT(2)) - max_rate = (bw_40MHz) ? ((short_GI_40)?900:810):((short_GI_20)?433:390); + max_rate = (bw_40MHz) ? ((short_GI_40) ? 900 : 810) : ((short_GI_20) ? 433 : 390); else if (mcs->rx_mask[1] & BIT(1)) - max_rate = (bw_40MHz) ? ((short_GI_40)?600:540):((short_GI_20)?289:260); + max_rate = (bw_40MHz) ? ((short_GI_40) ? 600 : 540) : ((short_GI_20) ? 289 : 260); else if (mcs->rx_mask[1] & BIT(0)) - max_rate = (bw_40MHz) ? ((short_GI_40)?300:270):((short_GI_20)?144:130); + max_rate = (bw_40MHz) ? ((short_GI_40) ? 300 : 270) : ((short_GI_20) ? 144 : 130); } else { if (mcs->rx_mask[0] & BIT(7)) - max_rate = (bw_40MHz) ? ((short_GI_40)?1500:1350):((short_GI_20)?722:650); + max_rate = (bw_40MHz) ? ((short_GI_40) ? 1500 : 1350) : ((short_GI_20) ? 722 : 650); else if (mcs->rx_mask[0] & BIT(6)) - max_rate = (bw_40MHz) ? ((short_GI_40)?1350:1215):((short_GI_20)?650:585); + max_rate = (bw_40MHz) ? ((short_GI_40) ? 1350 : 1215) : ((short_GI_20) ? 650 : 585); else if (mcs->rx_mask[0] & BIT(5)) - max_rate = (bw_40MHz) ? ((short_GI_40)?1200:1080):((short_GI_20)?578:520); + max_rate = (bw_40MHz) ? ((short_GI_40) ? 1200 : 1080) : ((short_GI_20) ? 578 : 520); else if (mcs->rx_mask[0] & BIT(4)) - max_rate = (bw_40MHz) ? ((short_GI_40)?900:810):((short_GI_20)?433:390); + max_rate = (bw_40MHz) ? ((short_GI_40) ? 900 : 810) : ((short_GI_20) ? 433 : 390); else if (mcs->rx_mask[0] & BIT(3)) - max_rate = (bw_40MHz) ? ((short_GI_40)?600:540):((short_GI_20)?289:260); + max_rate = (bw_40MHz) ? ((short_GI_40) ? 600 : 540) : ((short_GI_20) ? 289 : 260); else if (mcs->rx_mask[0] & BIT(2)) - max_rate = (bw_40MHz) ? ((short_GI_40)?450:405):((short_GI_20)?217:195); + max_rate = (bw_40MHz) ? ((short_GI_40) ? 450 : 405) : ((short_GI_20) ? 217 : 195); else if (mcs->rx_mask[0] & BIT(1)) - max_rate = (bw_40MHz) ? ((short_GI_40)?300:270):((short_GI_20)?144:130); + max_rate = (bw_40MHz) ? ((short_GI_40) ? 300 : 270) : ((short_GI_20) ? 144 : 130); else if (mcs->rx_mask[0] & BIT(0)) - max_rate = (bw_40MHz) ? ((short_GI_40)?150:135):((short_GI_20)?72:65); + max_rate = (bw_40MHz) ? ((short_GI_40) ? 150 : 135) : ((short_GI_20) ? 72 : 65); } } return max_rate; -- cgit v0.10.2 From d5b7d2b02c31591714c2833a37fb2f65690374f5 Mon Sep 17 00:00:00 2001 From: Jonas Rickert <jrickertkc@gmail.com> Date: Sat, 30 Jul 2016 13:27:58 +0200 Subject: Staging: rts5208: fix double blank line coding style issues This is a patch for double blank lines and a missing blank line reported by checkpatch.pl Signed-off-by: Jonas Rickert <jrickertkc@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c index 0f0cd4a..4b3c212 100644 --- a/drivers/staging/rts5208/ms.c +++ b/drivers/staging/rts5208/ms.c @@ -1417,7 +1417,6 @@ static int ms_read_status_reg(struct rtsx_chip *chip) return STATUS_SUCCESS; } - static int ms_read_extra_data(struct rtsx_chip *chip, u16 block_addr, u8 page_num, u8 *buf, int buf_len) { @@ -1582,7 +1581,6 @@ static int ms_write_extra_data(struct rtsx_chip *chip, return STATUS_SUCCESS; } - static int ms_read_page(struct rtsx_chip *chip, u16 block_addr, u8 page_num) { struct ms_info *ms_card = &chip->ms_card; @@ -1667,7 +1665,6 @@ static int ms_read_page(struct rtsx_chip *chip, u16 block_addr, u8 page_num) return STATUS_SUCCESS; } - static int ms_set_bad_block(struct rtsx_chip *chip, u16 phy_blk) { struct ms_info *ms_card = &chip->ms_card; @@ -1738,7 +1735,6 @@ static int ms_set_bad_block(struct rtsx_chip *chip, u16 phy_blk) return STATUS_SUCCESS; } - static int ms_erase_block(struct rtsx_chip *chip, u16 phy_blk) { struct ms_info *ms_card = &chip->ms_card; @@ -1808,7 +1804,6 @@ ERASE_RTY: return STATUS_SUCCESS; } - static void ms_set_page_status(u16 log_blk, u8 type, u8 *extra, int extra_len) { if (!extra || (extra_len < MS_EXTRA_SIZE)) @@ -2152,7 +2147,6 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, return STATUS_SUCCESS; } - static int reset_ms(struct rtsx_chip *chip) { struct ms_info *ms_card = &chip->ms_card; @@ -2809,7 +2803,6 @@ BUILD_FAIL: return STATUS_FAIL; } - int reset_ms_card(struct rtsx_chip *chip) { struct ms_info *ms_card = &chip->ms_card; @@ -2896,7 +2889,6 @@ static int mspro_set_rw_cmd(struct rtsx_chip *chip, return STATUS_SUCCESS; } - void mspro_stop_seq_mode(struct rtsx_chip *chip) { struct ms_info *ms_card = &chip->ms_card; @@ -3312,7 +3304,6 @@ int mspro_format(struct scsi_cmnd *srb, struct rtsx_chip *chip, return STATUS_FAIL; } - static int ms_read_multiple_pages(struct rtsx_chip *chip, u16 phy_blk, u16 log_blk, u8 start_page, u8 end_page, u8 *buf, unsigned int *index, @@ -3719,7 +3710,6 @@ static int ms_write_multiple_pages(struct rtsx_chip *chip, u16 old_blk, return STATUS_SUCCESS; } - static int ms_finish_write(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, u16 log_blk, u8 page_off) { @@ -4082,7 +4072,6 @@ int ms_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, return retval; } - void ms_free_l2p_tbl(struct rtsx_chip *chip) { struct ms_info *ms_card = &chip->ms_card; diff --git a/drivers/staging/rts5208/ms.h b/drivers/staging/rts5208/ms.h index d919170..d768639 100644 --- a/drivers/staging/rts5208/ms.h +++ b/drivers/staging/rts5208/ms.h @@ -125,7 +125,6 @@ #define Pro_CatagoryReg 0x06 #define Pro_ClassReg 0x07 - #define Pro_SystemParm 0x10 #define Pro_DataCount1 0x11 #define Pro_DataCount0 0x12 diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index 25d095a..e992e03 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -111,7 +111,6 @@ static int slave_configure(struct scsi_device *sdev) return 0; } - /*********************************************************************** * /proc/scsi/ functions ***********************************************************************/ @@ -209,7 +208,6 @@ static int bus_reset(struct scsi_cmnd *srb) return result < 0 ? FAILED : SUCCESS; } - /* * this defines our host template, with which we'll allocate hosts */ @@ -259,7 +257,6 @@ static struct scsi_host_template rtsx_host_template = { .module = THIS_MODULE }; - static int rtsx_acquire_irq(struct rtsx_dev *dev) { struct rtsx_chip *chip = dev->chip; @@ -282,7 +279,6 @@ static int rtsx_acquire_irq(struct rtsx_dev *dev) return 0; } - int rtsx_read_pci_cfg_byte(u8 bus, u8 dev, u8 func, u8 offset, u8 *val) { struct pci_dev *pdev; @@ -515,7 +511,6 @@ SkipForAbort: complete_and_exit(&dev->control_exit, 0); } - static int rtsx_polling_thread(void *__dev) { struct rtsx_dev *dev = __dev; @@ -625,7 +620,6 @@ Exit: return IRQ_HANDLED; } - /* Release all our dynamic resources */ static void rtsx_release_resources(struct rtsx_dev *dev) { @@ -994,7 +988,6 @@ errout: return err; } - static void rtsx_remove(struct pci_dev *pci) { struct rtsx_dev *dev = pci_get_drvdata(pci); diff --git a/drivers/staging/rts5208/rtsx.h b/drivers/staging/rts5208/rtsx.h index 1396263..2f902d5 100644 --- a/drivers/staging/rts5208/rtsx.h +++ b/drivers/staging/rts5208/rtsx.h @@ -77,7 +77,6 @@ do { \ } while (0) #define wait_timeout(msecs) wait_timeout_x(TASK_INTERRUPTIBLE, (msecs)) - #define STATE_TRANS_NONE 0 #define STATE_TRANS_CMD 1 #define STATE_TRANS_BUF 2 @@ -138,6 +137,7 @@ static inline struct Scsi_Host *rtsx_to_host(struct rtsx_dev *dev) { return container_of((void *) dev, struct Scsi_Host, hostdata); } + static inline struct rtsx_dev *host_to_rtsx(struct Scsi_Host *host) { return (struct rtsx_dev *) host->hostdata; diff --git a/drivers/staging/rts5208/rtsx_card.c b/drivers/staging/rts5208/rtsx_card.c index 231833a..9a5cd63 100644 --- a/drivers/staging/rts5208/rtsx_card.c +++ b/drivers/staging/rts5208/rtsx_card.c @@ -1065,7 +1065,6 @@ int card_share_mode(struct rtsx_chip *chip, int card) return STATUS_SUCCESS; } - int select_card(struct rtsx_chip *chip, int card) { int retval; diff --git a/drivers/staging/rts5208/rtsx_chip.h b/drivers/staging/rts5208/rtsx_chip.h index c08164f..79d1df6 100644 --- a/drivers/staging/rts5208/rtsx_chip.h +++ b/drivers/staging/rts5208/rtsx_chip.h @@ -101,7 +101,6 @@ #define TRANSPORT_NO_SENSE 2 /* Command failed, no auto-sense */ #define TRANSPORT_ERROR 3 /* Transport bad (i.e. device dead) */ - /*----------------------------------- Start-Stop-Unit -----------------------------------*/ @@ -228,7 +227,6 @@ #define ASCQ_LOAD_EJCT_ERR 0x00 #define ASCQ_WRITE_PROTECT 0x00 - struct sense_data_t { unsigned char err_code; /* error code */ /* bit7 : valid */ @@ -305,7 +303,6 @@ struct sense_data_t { #define MS_OC_INT_EN (1 << 23) #define SD_OC_INT_EN (1 << 22) - #define READ_REG_CMD 0 #define WRITE_REG_CMD 1 #define CHECK_REG_CMD 2 @@ -313,7 +310,6 @@ struct sense_data_t { #define HOST_TO_DEVICE 0 #define DEVICE_TO_HOST 1 - #define RTSX_RESV_BUF_LEN 4096 #define HOST_CMDS_BUF_LEN 1024 #define HOST_SG_TBL_BUF_LEN (RTSX_RESV_BUF_LEN - HOST_CMDS_BUF_LEN) @@ -332,7 +328,6 @@ struct sense_data_t { #define XD_FREE_TABLE_CNT 1200 #define MS_FREE_TABLE_CNT 512 - /* Bit Operation */ #define SET_BIT(data, idx) ((data) |= 1 << (idx)) #define CLR_BIT(data, idx) ((data) &= ~(1 << (idx))) @@ -618,7 +613,6 @@ struct spi_info { int spi_clock; }; - #ifdef _MSG_TRACE struct trace_msg_t { u16 line; diff --git a/drivers/staging/rts5208/rtsx_scsi.c b/drivers/staging/rts5208/rtsx_scsi.c index d203104..9818e5d 100644 --- a/drivers/staging/rts5208/rtsx_scsi.c +++ b/drivers/staging/rts5208/rtsx_scsi.c @@ -558,7 +558,6 @@ static int inquiry(struct scsi_cmnd *srb, struct rtsx_chip *chip) return TRANSPORT_GOOD; } - static int start_stop_unit(struct scsi_cmnd *srb, struct rtsx_chip *chip) { unsigned int lun = SCSI_LUN(srb); @@ -594,7 +593,6 @@ static int start_stop_unit(struct scsi_cmnd *srb, struct rtsx_chip *chip) return TRANSPORT_ERROR; } - static int allow_medium_removal(struct scsi_cmnd *srb, struct rtsx_chip *chip) { int prevent; @@ -613,7 +611,6 @@ static int allow_medium_removal(struct scsi_cmnd *srb, struct rtsx_chip *chip) return TRANSPORT_GOOD; } - static int request_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip) { struct sense_data_t *sense; @@ -2604,7 +2601,6 @@ static int app_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip) return result; } - static int read_status(struct scsi_cmnd *srb, struct rtsx_chip *chip) { u8 rtsx_status[16]; diff --git a/drivers/staging/rts5208/rtsx_transport.h b/drivers/staging/rts5208/rtsx_transport.h index 899bc20..4791373 100644 --- a/drivers/staging/rts5208/rtsx_transport.h +++ b/drivers/staging/rts5208/rtsx_transport.h @@ -38,7 +38,6 @@ void rtsx_stor_get_xfer_buf(unsigned char *buffer, unsigned int buflen, struct scsi_cmnd *srb); void rtsx_invoke_transport(struct scsi_cmnd *srb, struct rtsx_chip *chip); - #define rtsx_init_cmd(chip) ((chip)->ci = 0) void rtsx_add_cmd(struct rtsx_chip *chip, diff --git a/drivers/staging/rts5208/sd.c b/drivers/staging/rts5208/sd.c index 6219e04..345313a 100644 --- a/drivers/staging/rts5208/sd.c +++ b/drivers/staging/rts5208/sd.c @@ -1428,7 +1428,6 @@ static int sd_switch_function(struct rtsx_chip *chip, u8 bus_width) continue; } - if (func_to_switch) break; @@ -2975,7 +2974,6 @@ SD_UNLOCK_ENTRY: return STATUS_SUCCESS; } - static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width) { struct sd_info *sd_card = &(chip->sd_card); @@ -3105,7 +3103,6 @@ static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width) return SWITCH_FAIL; } - static int mmc_switch_timing_bus(struct rtsx_chip *chip, bool switch_ddr) { struct sd_info *sd_card = &(chip->sd_card); @@ -3230,7 +3227,6 @@ static int mmc_switch_timing_bus(struct rtsx_chip *chip, bool switch_ddr) return STATUS_SUCCESS; } - static int reset_mmc(struct rtsx_chip *chip) { struct sd_info *sd_card = &(chip->sd_card); diff --git a/drivers/staging/rts5208/spi.h b/drivers/staging/rts5208/spi.h index fc824b5..c8d2bea 100644 --- a/drivers/staging/rts5208/spi.h +++ b/drivers/staging/rts5208/spi.h @@ -61,5 +61,4 @@ int spi_write_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip); int spi_erase_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip); int spi_write_flash_status(struct scsi_cmnd *srb, struct rtsx_chip *chip); - #endif /* __REALTEK_RTSX_SPI_H */ diff --git a/drivers/staging/rts5208/xd.c b/drivers/staging/rts5208/xd.c index fc1dfe0..126a2dc 100644 --- a/drivers/staging/rts5208/xd.c +++ b/drivers/staging/rts5208/xd.c @@ -834,7 +834,6 @@ static int xd_check_data_blank(u8 *redunt) != (XD_ECC1_ALL1 | XD_ECC2_ALL1)) return 0; - for (i = 0; i < 4; i++) { if (redunt[RESERVED0 + i] != 0xFF) return 0; @@ -1402,7 +1401,6 @@ static int xd_erase_block(struct rtsx_chip *chip, u32 phy_blk) return STATUS_FAIL; } - static int xd_build_l2p_tbl(struct rtsx_chip *chip, int zone_no) { struct xd_info *xd_card = &(chip->xd_card); @@ -1830,7 +1828,6 @@ static int xd_prepare_write(struct rtsx_chip *chip, return STATUS_SUCCESS; } - static int xd_write_multiple_pages(struct rtsx_chip *chip, u32 old_blk, u32 new_blk, u32 log_blk, u8 start_page, u8 end_page, u8 *buf, unsigned int *index, @@ -2000,7 +1997,6 @@ int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, return STATUS_FAIL; } - if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) { chip->card_fail |= XD_CARD; set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); -- cgit v0.10.2 From 541e4d2d1d99c51a3bbc887b88ac3d65534b0fc9 Mon Sep 17 00:00:00 2001 From: Quentin Lambert <lambert.quentin@gmail.com> Date: Fri, 12 Aug 2016 16:15:17 +0200 Subject: staging: rts5208/ms.c: change the label name to respect the coding style This patch changes label names using camel case to snake case as well as giving a new name representing what will be done after the label. Signed-off-by: Quentin Lambert <lambert.quentin@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c index 4b3c212..a055036 100644 --- a/drivers/staging/rts5208/ms.c +++ b/drivers/staging/rts5208/ms.c @@ -4302,7 +4302,7 @@ int mg_get_local_EKB(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (retval != STATUS_SUCCESS) { set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); rtsx_trace(chip); - goto GetEKBFinish; + goto free_buffer; } retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA, @@ -4311,7 +4311,7 @@ int mg_get_local_EKB(struct scsi_cmnd *srb, struct rtsx_chip *chip) set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); rtsx_clear_ms_error(chip); rtsx_trace(chip); - goto GetEKBFinish; + goto free_buffer; } if (check_ms_err(chip)) { set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); @@ -4323,7 +4323,7 @@ int mg_get_local_EKB(struct scsi_cmnd *srb, struct rtsx_chip *chip) bufflen = min_t(int, 1052, scsi_bufflen(srb)); rtsx_stor_set_xfer_buf(buf, bufflen, srb); -GetEKBFinish: +free_buffer: kfree(buf); return retval; } @@ -4555,7 +4555,7 @@ int mg_get_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip) if (retval != STATUS_SUCCESS) { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); rtsx_trace(chip); - goto GetICVFinish; + goto free_buffer; } retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA, @@ -4564,7 +4564,7 @@ int mg_get_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip) set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); rtsx_clear_ms_error(chip); rtsx_trace(chip); - goto GetICVFinish; + goto free_buffer; } if (check_ms_err(chip)) { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); @@ -4576,7 +4576,7 @@ int mg_get_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip) bufflen = min_t(int, 1028, scsi_bufflen(srb)); rtsx_stor_set_xfer_buf(buf, bufflen, srb); -GetICVFinish: +free_buffer: kfree(buf); return retval; } -- cgit v0.10.2 From 0b25e9fa01fc9ed333d266172128ba37d44cd7be Mon Sep 17 00:00:00 2001 From: Quentin Lambert <lambert.quentin@gmail.com> Date: Fri, 12 Aug 2016 16:15:18 +0200 Subject: staging: rts5208/ms.c: add missing releases in mg_get_local_EKB and mg_get_ICV mg_get_local_EKB and mg_get_ICV used to return with an error code before releasing all resources. This patch add a jump to the appropriate label ensuring that the resources are properly released before returning. This issue was found with Hector. Signed-off-by: Quentin Lambert <lambert.quentin@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c index a055036..f927ba6 100644 --- a/drivers/staging/rts5208/ms.c +++ b/drivers/staging/rts5208/ms.c @@ -4317,7 +4317,8 @@ int mg_get_local_EKB(struct scsi_cmnd *srb, struct rtsx_chip *chip) set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); rtsx_clear_ms_error(chip); rtsx_trace(chip); - return STATUS_FAIL; + retval = STATUS_FAIL; + goto free_buffer; } bufflen = min_t(int, 1052, scsi_bufflen(srb)); @@ -4570,7 +4571,8 @@ int mg_get_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip) set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); rtsx_clear_ms_error(chip); rtsx_trace(chip); - return STATUS_FAIL; + retval = STATUS_FAIL; + goto free_buffer; } bufflen = min_t(int, 1028, scsi_bufflen(srb)); -- cgit v0.10.2 From 10adcce696da141739ab93768169b3783ab0bab3 Mon Sep 17 00:00:00 2001 From: Louie Lu <louie.lu@hopebaytech.com> Date: Mon, 15 Aug 2016 18:44:41 +0800 Subject: staging: rts5208: Change data type to unsigned int. This patch fixes a minor checkpatch warning: "WARNING: Prefer 'unsigned int' to bare use of 'unsigned'" Signed-off-by: Louie Lu <louie.lu@hopebaytech.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rts5208/rtsx_scsi.c b/drivers/staging/rts5208/rtsx_scsi.c index 9818e5d..def53d9 100644 --- a/drivers/staging/rts5208/rtsx_scsi.c +++ b/drivers/staging/rts5208/rtsx_scsi.c @@ -1518,7 +1518,7 @@ static int write_host_reg(struct scsi_cmnd *srb, struct rtsx_chip *chip) static int set_variable(struct scsi_cmnd *srb, struct rtsx_chip *chip) { - unsigned lun = SCSI_LUN(srb); + unsigned int lun = SCSI_LUN(srb); if (srb->cmnd[3] == 1) { /* Variable Clock */ -- cgit v0.10.2 From 197399dcd7726b6b86d2c46700c9be05f5b85425 Mon Sep 17 00:00:00 2001 From: Alison Schofield <amsfield22@gmail.com> Date: Thu, 18 Aug 2016 09:09:00 -0700 Subject: iio: magnetometer: mag3110: claim direct mode during raw reads Driver was checking for direct mode but not locking it. Use claim/release helper functions to guarantee the device stays in direct mode during raw reads. Signed-off-by: Alison Schofield <amsfield22@gmail.com> Cc: Daniel Baluta <daniel.baluta@gmail.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/magnetometer/mag3110.c b/drivers/iio/magnetometer/mag3110.c index f2be4a0..f2b3bd7 100644 --- a/drivers/iio/magnetometer/mag3110.c +++ b/drivers/iio/magnetometer/mag3110.c @@ -154,34 +154,41 @@ static int mag3110_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - if (iio_buffer_enabled(indio_dev)) - return -EBUSY; + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; switch (chan->type) { case IIO_MAGN: /* in 0.1 uT / LSB */ ret = mag3110_read(data, buffer); if (ret < 0) - return ret; + goto release; *val = sign_extend32( be16_to_cpu(buffer[chan->scan_index]), 15); - return IIO_VAL_INT; + ret = IIO_VAL_INT; + break; case IIO_TEMP: /* in 1 C / LSB */ mutex_lock(&data->lock); ret = mag3110_request(data); if (ret < 0) { mutex_unlock(&data->lock); - return ret; + goto release; } ret = i2c_smbus_read_byte_data(data->client, MAG3110_DIE_TEMP); mutex_unlock(&data->lock); if (ret < 0) - return ret; + goto release; *val = sign_extend32(ret, 7); - return IIO_VAL_INT; + ret = IIO_VAL_INT; + break; default: - return -EINVAL; + ret = -EINVAL; } +release: + iio_device_release_direct_mode(indio_dev); + return ret; + case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_MAGN: -- cgit v0.10.2 From e24544553b0830ce91e723099868723b6531c4b2 Mon Sep 17 00:00:00 2001 From: Alison Schofield <amsfield22@gmail.com> Date: Mon, 15 Aug 2016 16:09:36 -0700 Subject: iio: temperature: add Kconfig selects for triggered buffer Select IIO_BUFFER and IIO_TRIGGERED_BUFFER to compile maxim_thermocouple. Signed-off-by: Alison Schofield <amsfield22@gmail.com> Cc: Daniel Baluta <daniel.baluta@gmail.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/temperature/Kconfig b/drivers/iio/temperature/Kconfig index 1d3da05..5ea77a7 100644 --- a/drivers/iio/temperature/Kconfig +++ b/drivers/iio/temperature/Kconfig @@ -6,6 +6,8 @@ menu "Temperature sensors" config MAXIM_THERMOCOUPLE tristate "Maxim thermocouple sensors" depends on SPI + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER help If you say yes here you get support for the Maxim series of thermocouple sensors connected via SPI. -- cgit v0.10.2 From 3ad16a39eda5a77510475f2c0d384312f1db105f Mon Sep 17 00:00:00 2001 From: Zhiyong Tao <zhiyong.tao@mediatek.com> Date: Thu, 18 Aug 2016 15:11:35 +0800 Subject: dt-bindings: auxadc: Add binding document for Mediatek auxadc. The commit adds the device tree binding documentation for the mediatek auxadc found on Mediatek MT2701. Thermal gets auxadc sample data by iio device. So the commit changes auxadc device tree binding documentation from /soc/mediatek/auxadc.txt to /iio/adc/mt6577_auxadc.txt. Acked-by: Rob Herring <robh@kernel.org> Signed-off-by: Zhiyong Tao <zhiyong.tao@mediatek.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/Documentation/devicetree/bindings/iio/adc/mt6577_auxadc.txt b/Documentation/devicetree/bindings/iio/adc/mt6577_auxadc.txt new file mode 100644 index 0000000..68c45cb --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/mt6577_auxadc.txt @@ -0,0 +1,29 @@ +* Mediatek AUXADC - Analog to Digital Converter on Mediatek mobile soc (mt65xx/mt81xx/mt27xx) +=============== + +The Auxiliary Analog/Digital Converter (AUXADC) is an ADC found +in some Mediatek SoCs which among other things measures the temperatures +in the SoC. It can be used directly with register accesses, but it is also +used by thermal controller which reads the temperatures from the AUXADC +directly via its own bus interface. See +Documentation/devicetree/bindings/thermal/mediatek-thermal.txt +for the Thermal Controller which holds a phandle to the AUXADC. + +Required properties: + - compatible: Should be one of: + - "mediatek,mt2701-auxadc": For MT2701 family of SoCs + - "mediatek,mt8173-auxadc": For MT8173 family of SoCs + - reg: Address range of the AUXADC unit. + - clocks: Should contain a clock specifier for each entry in clock-names + - clock-names: Should contain "main". + - #io-channel-cells: Should be 1, see ../iio-bindings.txt + +Example: + +auxadc: adc@11001000 { + compatible = "mediatek,mt2701-auxadc"; + reg = <0 0x11001000 0 0x1000>; + clocks = <&pericfg CLK_PERI_AUXADC>; + clock-names = "main"; + #io-channel-cells = <1>; +}; diff --git a/Documentation/devicetree/bindings/soc/mediatek/auxadc.txt b/Documentation/devicetree/bindings/soc/mediatek/auxadc.txt deleted file mode 100644 index bdb7829..0000000 --- a/Documentation/devicetree/bindings/soc/mediatek/auxadc.txt +++ /dev/null @@ -1,21 +0,0 @@ -MediaTek AUXADC -=============== - -The Auxiliary Analog/Digital Converter (AUXADC) is an ADC found -in some Mediatek SoCs which among other things measures the temperatures -in the SoC. It can be used directly with register accesses, but it is also -used by thermal controller which reads the temperatures from the AUXADC -directly via its own bus interface. See -Documentation/devicetree/bindings/thermal/mediatek-thermal.txt -for the Thermal Controller which holds a phandle to the AUXADC. - -Required properties: -- compatible: Must be "mediatek,mt8173-auxadc" -- reg: Address range of the AUXADC unit - -Example: - -auxadc: auxadc@11001000 { - compatible = "mediatek,mt8173-auxadc"; - reg = <0 0x11001000 0 0x1000>; -}; -- cgit v0.10.2 From ace4cdfe67be24463ad694105533e5319674f022 Mon Sep 17 00:00:00 2001 From: Zhiyong Tao <zhiyong.tao@mediatek.com> Date: Thu, 18 Aug 2016 15:11:36 +0800 Subject: iio: adc: mt2701: Add Mediatek auxadc driver for mt2701. Add Mediatek auxadc driver based on iio. It will register a device in iio and support iio. So thermal can read auxadc channel to sample data by iio device. It is tested successfully on mt2701 platform. Mt8173 and mt6577 platforms are not tested. But the expectation is compatible. Signed-off-by: Zhiyong Tao <zhiyong.tao@mediatek.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index f06cff7e..e4022fd 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -317,6 +317,19 @@ config MCP3422 This driver can also be built as a module. If so, the module will be called mcp3422. +config MEDIATEK_MT6577_AUXADC + tristate "MediaTek AUXADC driver" + depends on ARCH_MEDIATEK || COMPILE_TEST + depends on HAS_IOMEM + help + Say yes here to enable support for MediaTek mt65xx AUXADC. + + The driver supports immediate mode operation to read from one of sixteen + channels (external or internal). + + This driver can also be built as a module. If so, the module will be + called mt6577_auxadc. + config MEN_Z188_ADC tristate "MEN 16z188 ADC IP Core support" depends on MCB diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 1d80577..33254eb 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_MAX1027) += max1027.o obj-$(CONFIG_MAX1363) += max1363.o obj-$(CONFIG_MCP320X) += mcp320x.o obj-$(CONFIG_MCP3422) += mcp3422.o +obj-$(CONFIG_MEDIATEK_MT6577_AUXADC) += mt6577_auxadc.o obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o obj-$(CONFIG_MXS_LRADC) += mxs-lradc.o obj-$(CONFIG_NAU7802) += nau7802.o diff --git a/drivers/iio/adc/mt6577_auxadc.c b/drivers/iio/adc/mt6577_auxadc.c new file mode 100644 index 0000000..2d104c8 --- /dev/null +++ b/drivers/iio/adc/mt6577_auxadc.c @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2016 MediaTek Inc. + * Author: Zhiyong Tao <zhiyong.tao@mediatek.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/iopoll.h> +#include <linux/io.h> +#include <linux/iio/iio.h> + +/* Register definitions */ +#define MT6577_AUXADC_CON0 0x00 +#define MT6577_AUXADC_CON1 0x04 +#define MT6577_AUXADC_CON2 0x10 +#define MT6577_AUXADC_STA BIT(0) + +#define MT6577_AUXADC_DAT0 0x14 +#define MT6577_AUXADC_RDY0 BIT(12) + +#define MT6577_AUXADC_MISC 0x94 +#define MT6577_AUXADC_PDN_EN BIT(14) + +#define MT6577_AUXADC_DAT_MASK 0xfff +#define MT6577_AUXADC_SLEEP_US 1000 +#define MT6577_AUXADC_TIMEOUT_US 10000 +#define MT6577_AUXADC_POWER_READY_MS 1 +#define MT6577_AUXADC_SAMPLE_READY_US 25 + +struct mt6577_auxadc_device { + void __iomem *reg_base; + struct clk *adc_clk; + struct mutex lock; +}; + +#define MT6577_AUXADC_CHANNEL(idx) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = (idx), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \ +} + +static const struct iio_chan_spec mt6577_auxadc_iio_channels[] = { + MT6577_AUXADC_CHANNEL(0), + MT6577_AUXADC_CHANNEL(1), + MT6577_AUXADC_CHANNEL(2), + MT6577_AUXADC_CHANNEL(3), + MT6577_AUXADC_CHANNEL(4), + MT6577_AUXADC_CHANNEL(5), + MT6577_AUXADC_CHANNEL(6), + MT6577_AUXADC_CHANNEL(7), + MT6577_AUXADC_CHANNEL(8), + MT6577_AUXADC_CHANNEL(9), + MT6577_AUXADC_CHANNEL(10), + MT6577_AUXADC_CHANNEL(11), + MT6577_AUXADC_CHANNEL(12), + MT6577_AUXADC_CHANNEL(13), + MT6577_AUXADC_CHANNEL(14), + MT6577_AUXADC_CHANNEL(15), +}; + +static inline void mt6577_auxadc_mod_reg(void __iomem *reg, + u32 or_mask, u32 and_mask) +{ + u32 val; + + val = readl(reg); + val |= or_mask; + val &= ~and_mask; + writel(val, reg); +} + +static int mt6577_auxadc_read(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan) +{ + u32 val; + void __iomem *reg_channel; + int ret; + struct mt6577_auxadc_device *adc_dev = iio_priv(indio_dev); + + reg_channel = adc_dev->reg_base + MT6577_AUXADC_DAT0 + + chan->channel * 0x04; + + mutex_lock(&adc_dev->lock); + + mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_CON1, + 0, 1 << chan->channel); + + /* read channel and make sure old ready bit == 0 */ + ret = readl_poll_timeout(reg_channel, val, + ((val & MT6577_AUXADC_RDY0) == 0), + MT6577_AUXADC_SLEEP_US, + MT6577_AUXADC_TIMEOUT_US); + if (ret < 0) { + dev_err(indio_dev->dev.parent, + "wait for channel[%d] ready bit clear time out\n", + chan->channel); + goto err_timeout; + } + + /* set bit to trigger sample */ + mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_CON1, + 1 << chan->channel, 0); + + /* we must delay here for hardware sample channel data */ + udelay(MT6577_AUXADC_SAMPLE_READY_US); + + /* check MTK_AUXADC_CON2 if auxadc is idle */ + ret = readl_poll_timeout(adc_dev->reg_base + MT6577_AUXADC_CON2, val, + ((val & MT6577_AUXADC_STA) == 0), + MT6577_AUXADC_SLEEP_US, + MT6577_AUXADC_TIMEOUT_US); + if (ret < 0) { + dev_err(indio_dev->dev.parent, + "wait for auxadc idle time out\n"); + goto err_timeout; + } + + /* read channel and make sure ready bit == 1 */ + ret = readl_poll_timeout(reg_channel, val, + ((val & MT6577_AUXADC_RDY0) != 0), + MT6577_AUXADC_SLEEP_US, + MT6577_AUXADC_TIMEOUT_US); + if (ret < 0) { + dev_err(indio_dev->dev.parent, + "wait for channel[%d] data ready time out\n", + chan->channel); + goto err_timeout; + } + + /* read data */ + val = readl(reg_channel) & MT6577_AUXADC_DAT_MASK; + + mutex_unlock(&adc_dev->lock); + + return val; + +err_timeout: + + mutex_unlock(&adc_dev->lock); + + return -ETIMEDOUT; +} + +static int mt6577_auxadc_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long info) +{ + switch (info) { + case IIO_CHAN_INFO_PROCESSED: + *val = mt6577_auxadc_read(indio_dev, chan); + if (*val < 0) { + dev_err(indio_dev->dev.parent, + "failed to sample data on channel[%d]\n", + chan->channel); + return *val; + } + return IIO_VAL_INT; + + default: + return -EINVAL; + } +} + +static const struct iio_info mt6577_auxadc_info = { + .driver_module = THIS_MODULE, + .read_raw = &mt6577_auxadc_read_raw, +}; + +static int mt6577_auxadc_probe(struct platform_device *pdev) +{ + struct mt6577_auxadc_device *adc_dev; + unsigned long adc_clk_rate; + struct resource *res; + struct iio_dev *indio_dev; + int ret; + + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc_dev)); + if (!indio_dev) + return -ENOMEM; + + adc_dev = iio_priv(indio_dev); + indio_dev->dev.parent = &pdev->dev; + indio_dev->name = dev_name(&pdev->dev); + indio_dev->info = &mt6577_auxadc_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = mt6577_auxadc_iio_channels; + indio_dev->num_channels = ARRAY_SIZE(mt6577_auxadc_iio_channels); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + adc_dev->reg_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(adc_dev->reg_base)) { + dev_err(&pdev->dev, "failed to get auxadc base address\n"); + return PTR_ERR(adc_dev->reg_base); + } + + adc_dev->adc_clk = devm_clk_get(&pdev->dev, "main"); + if (IS_ERR(adc_dev->adc_clk)) { + dev_err(&pdev->dev, "failed to get auxadc clock\n"); + return PTR_ERR(adc_dev->adc_clk); + } + + ret = clk_prepare_enable(adc_dev->adc_clk); + if (ret) { + dev_err(&pdev->dev, "failed to enable auxadc clock\n"); + return ret; + } + + adc_clk_rate = clk_get_rate(adc_dev->adc_clk); + if (!adc_clk_rate) { + ret = -EINVAL; + dev_err(&pdev->dev, "null clock rate\n"); + goto err_disable_clk; + } + + mutex_init(&adc_dev->lock); + + mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC, + MT6577_AUXADC_PDN_EN, 0); + mdelay(MT6577_AUXADC_POWER_READY_MS); + + platform_set_drvdata(pdev, indio_dev); + + ret = iio_device_register(indio_dev); + if (ret < 0) { + dev_err(&pdev->dev, "failed to register iio device\n"); + goto err_power_off; + } + + return 0; + +err_power_off: + mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC, + 0, MT6577_AUXADC_PDN_EN); +err_disable_clk: + clk_disable_unprepare(adc_dev->adc_clk); + return ret; +} + +static int mt6577_auxadc_remove(struct platform_device *pdev) +{ + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct mt6577_auxadc_device *adc_dev = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC, + 0, MT6577_AUXADC_PDN_EN); + + clk_disable_unprepare(adc_dev->adc_clk); + + return 0; +} + +static const struct of_device_id mt6577_auxadc_of_match[] = { + { .compatible = "mediatek,mt2701-auxadc", }, + { .compatible = "mediatek,mt8173-auxadc", }, + { } +}; +MODULE_DEVICE_TABLE(of, mt6577_auxadc_of_match); + +static struct platform_driver mt6577_auxadc_driver = { + .driver = { + .name = "mt6577-auxadc", + .of_match_table = mt6577_auxadc_of_match, + }, + .probe = mt6577_auxadc_probe, + .remove = mt6577_auxadc_remove, +}; +module_platform_driver(mt6577_auxadc_driver); + +MODULE_AUTHOR("Zhiyong Tao <zhiyong.tao@mediatek.com>"); +MODULE_DESCRIPTION("MTK AUXADC Device Driver"); +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 7f6cf7414538181f4091b06e905d19a23a451108 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Date: Mon, 15 Aug 2016 12:12:47 -0700 Subject: iio: hid-sensors: use asynchronous resume Some platforms power off sensor hubs during S3 suspend, which will require longer time to resume. This hurts system resume time, so resume asynchronously. Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c index 5b41f9d..5264ed6 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c @@ -122,6 +122,14 @@ int hid_sensor_power_state(struct hid_sensor_common *st, bool state) #endif } +static void hid_sensor_set_power_work(struct work_struct *work) +{ + struct hid_sensor_common *attrb = container_of(work, + struct hid_sensor_common, + work); + _hid_sensor_power_state(attrb, true); +} + static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, bool state) { @@ -130,6 +138,7 @@ static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, void hid_sensor_remove_trigger(struct hid_sensor_common *attrb) { + cancel_work_sync(&attrb->work); iio_trigger_unregister(attrb->trigger); iio_trigger_free(attrb->trigger); } @@ -170,6 +179,9 @@ int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name, goto error_unreg_trigger; iio_device_set_drvdata(indio_dev, attrb); + + INIT_WORK(&attrb->work, hid_sensor_set_power_work); + pm_suspend_ignore_children(&attrb->pdev->dev, true); pm_runtime_enable(&attrb->pdev->dev); /* Default to 3 seconds, but can be changed from sysfs */ @@ -202,7 +214,15 @@ static int hid_sensor_resume(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct iio_dev *indio_dev = platform_get_drvdata(pdev); struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev); + schedule_work(&attrb->work); + return 0; +} +static int hid_sensor_runtime_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev); return _hid_sensor_power_state(attrb, true); } @@ -211,7 +231,7 @@ static int hid_sensor_resume(struct device *dev) const struct dev_pm_ops hid_sensor_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(hid_sensor_suspend, hid_sensor_resume) SET_RUNTIME_PM_OPS(hid_sensor_suspend, - hid_sensor_resume, NULL) + hid_sensor_runtime_resume, NULL) }; EXPORT_SYMBOL(hid_sensor_pm_ops); diff --git a/include/linux/hid-sensor-hub.h b/include/linux/hid-sensor-hub.h index c02b5ce..dd85f35 100644 --- a/include/linux/hid-sensor-hub.h +++ b/include/linux/hid-sensor-hub.h @@ -236,6 +236,7 @@ struct hid_sensor_common { struct hid_sensor_hub_attribute_info report_state; struct hid_sensor_hub_attribute_info power_state; struct hid_sensor_hub_attribute_info sensitivity; + struct work_struct work; }; /* Convert from hid unit expo to regular exponent */ -- cgit v0.10.2 From 87557ade38f3d465f4935d63d74a7590e7d69e1a Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Tue, 16 Aug 2016 15:33:27 +0200 Subject: iio: accel: kxsd9: Add device tree bindings This accelerometer can be probed from the device tree, so it needs to have proper documentation of it's device tree bindings. Cc: devicetree@vger.kernel.org Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Acked-by: Rob Herring <robh@kernel.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/Documentation/devicetree/bindings/iio/accel/kionix,kxsd9.txt b/Documentation/devicetree/bindings/iio/accel/kionix,kxsd9.txt new file mode 100644 index 0000000..b25bf3a --- /dev/null +++ b/Documentation/devicetree/bindings/iio/accel/kionix,kxsd9.txt @@ -0,0 +1,22 @@ +Kionix KXSD9 Accelerometer device tree bindings + +Required properties: + - compatible: should be set to "kionix,kxsd9" + - reg: i2c slave address + +Optional properties: + - vdd-supply: The input supply for VDD + - iovdd-supply: The input supply for IOVDD + - interrupts: The movement detection interrupt + - mount-matrix: See mount-matrix.txt + +Example: + +kxsd9@18 { + compatible = "kionix,kxsd9"; + reg = <0x18>; + interrupt-parent = <&foo>; + interrupts = <57 IRQ_TYPE_EDGE_FALLING>; + iovdd-supply = <&bar>; + vdd-supply = <&baz>; +}; -- cgit v0.10.2 From cd94f231a73efb237e3da16ba83e8226431cdfcb Mon Sep 17 00:00:00 2001 From: Oleg Drokin <green@linuxhacker.ru> Date: Sun, 21 Aug 2016 18:04:34 -0400 Subject: staging/lustre: Add spaces preferred around that '{+, -, *, /, |, <<, >>, &}' This patch fixes all checkpatch occurences of "CHECK: spaces preferred around that '{+,-,*,/,|,<<,>>,&}' (ctx:VxV)" in Lustre code. Signed-off-by: Emoly Liu <emoly.liu@intel.com> Signed-off-by: Oleg Drokin <green@linuxhacker.ru> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lu_object.h b/drivers/staging/lustre/lustre/include/lu_object.h index 6ab1782..502bc41 100644 --- a/drivers/staging/lustre/lustre/include/lu_object.h +++ b/drivers/staging/lustre/lustre/include/lu_object.h @@ -1024,7 +1024,8 @@ enum lu_context_tag { /** * Contexts usable in cache shrinker thread. */ - LCT_SHRINKER = LCT_MD_THREAD|LCT_DT_THREAD|LCT_CL_THREAD|LCT_NOREF + LCT_SHRINKER = LCT_MD_THREAD | LCT_DT_THREAD | LCT_CL_THREAD | + LCT_NOREF }; /** diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 35af07e..3a0feac 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -2019,7 +2019,7 @@ void lustre_swab_generic_32s(__u32 *val); #define MDS_INODELOCK_MAXSHIFT 5 /* This FULL lock is useful to take on unlink sort of operations */ -#define MDS_INODELOCK_FULL ((1<<(MDS_INODELOCK_MAXSHIFT+1))-1) +#define MDS_INODELOCK_FULL ((1 << (MDS_INODELOCK_MAXSHIFT + 1)) - 1) /* NOTE: until Lustre 1.8.7/2.1.1 the fid_ver() was packed into name[2], * but was moved into name[1] along with the OID to avoid consuming the @@ -3193,8 +3193,8 @@ struct llog_log_hdr { __u32 llh_cat_idx; /* for a catalog the first plain slot is next to it */ struct obd_uuid llh_tgtuuid; - __u32 llh_reserved[LLOG_HEADER_SIZE/sizeof(__u32) - 23]; - __u32 llh_bitmap[LLOG_BITMAP_BYTES/sizeof(__u32)]; + __u32 llh_reserved[LLOG_HEADER_SIZE / sizeof(__u32) - 23]; + __u32 llh_bitmap[LLOG_BITMAP_BYTES / sizeof(__u32)]; struct llog_rec_tail llh_tail; } __packed; @@ -3409,17 +3409,17 @@ void lustre_swab_lustre_capa(struct lustre_capa *c); /** lustre_capa::lc_opc */ enum { - CAPA_OPC_BODY_WRITE = 1<<0, /**< write object data */ - CAPA_OPC_BODY_READ = 1<<1, /**< read object data */ - CAPA_OPC_INDEX_LOOKUP = 1<<2, /**< lookup object fid */ - CAPA_OPC_INDEX_INSERT = 1<<3, /**< insert object fid */ - CAPA_OPC_INDEX_DELETE = 1<<4, /**< delete object fid */ - CAPA_OPC_OSS_WRITE = 1<<5, /**< write oss object data */ - CAPA_OPC_OSS_READ = 1<<6, /**< read oss object data */ - CAPA_OPC_OSS_TRUNC = 1<<7, /**< truncate oss object */ - CAPA_OPC_OSS_DESTROY = 1<<8, /**< destroy oss object */ - CAPA_OPC_META_WRITE = 1<<9, /**< write object meta data */ - CAPA_OPC_META_READ = 1<<10, /**< read object meta data */ + CAPA_OPC_BODY_WRITE = 1 << 0, /**< write object data */ + CAPA_OPC_BODY_READ = 1 << 1, /**< read object data */ + CAPA_OPC_INDEX_LOOKUP = 1 << 2, /**< lookup object fid */ + CAPA_OPC_INDEX_INSERT = 1 << 3, /**< insert object fid */ + CAPA_OPC_INDEX_DELETE = 1 << 4, /**< delete object fid */ + CAPA_OPC_OSS_WRITE = 1 << 5, /**< write oss object data */ + CAPA_OPC_OSS_READ = 1 << 6, /**< read oss object data */ + CAPA_OPC_OSS_TRUNC = 1 << 7, /**< truncate oss object */ + CAPA_OPC_OSS_DESTROY = 1 << 8, /**< destroy oss object */ + CAPA_OPC_META_WRITE = 1 << 9, /**< write object meta data */ + CAPA_OPC_META_READ = 1 << 10, /**< read object meta data */ }; #define CAPA_OPC_OSS_RW (CAPA_OPC_OSS_READ | CAPA_OPC_OSS_WRITE) diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index 229aecb..351fb4c 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -753,7 +753,7 @@ static inline void hsm_set_cl_error(int *flags, int error) *flags |= (error << CLF_HSM_ERR_L); } -#define CR_MAXSIZE cfs_size_round(2*NAME_MAX + 1 + \ +#define CR_MAXSIZE cfs_size_round(2 * NAME_MAX + 1 + \ sizeof(struct changelog_ext_rec)) struct changelog_rec { diff --git a/drivers/staging/lustre/lustre/include/lustre_fid.h b/drivers/staging/lustre/lustre/include/lustre_fid.h index f1d5bbd..3167806 100644 --- a/drivers/staging/lustre/lustre/include/lustre_fid.h +++ b/drivers/staging/lustre/lustre/include/lustre_fid.h @@ -596,7 +596,7 @@ static inline __u32 fid_flatten32(const struct lu_fid *fid) * (from OID), or up to 128M inodes without collisions for new files. */ ino = ((seq & 0x000fffffULL) << 12) + ((seq >> 8) & 0xfffff000) + - (seq >> (64 - (40-8)) & 0xffffff00) + + (seq >> (64 - (40 - 8)) & 0xffffff00) + (fid_oid(fid) & 0xff000fff) + ((fid_oid(fid) & 0x00fff000) << 8); return ino ? ino : fid_oid(fid); diff --git a/drivers/staging/lustre/lustre/include/lustre_lite.h b/drivers/staging/lustre/lustre/include/lustre_lite.h index e2f3767..8333d76 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lite.h +++ b/drivers/staging/lustre/lustre/include/lustre_lite.h @@ -46,7 +46,7 @@ /* 4UL * 1024 * 1024 */ #define LL_MAX_BLKSIZE_BITS (22) -#define LL_MAX_BLKSIZE (1UL<<LL_MAX_BLKSIZE_BITS) +#define LL_MAX_BLKSIZE (1UL << LL_MAX_BLKSIZE_BITS) /* * This is embedded into llite super-blocks to keep track of diff --git a/drivers/staging/lustre/lustre/include/obd_support.h b/drivers/staging/lustre/lustre/include/obd_support.h index 5ef798f..0c29a33 100644 --- a/drivers/staging/lustre/lustre/include/obd_support.h +++ b/drivers/staging/lustre/lustre/include/obd_support.h @@ -115,17 +115,17 @@ extern char obd_jobid_var[]; * running on a backup server. (If it's too low, import_select_connection * will increase the timeout anyhow.) */ -#define INITIAL_CONNECT_TIMEOUT max(CONNECTION_SWITCH_MIN, obd_timeout/20) +#define INITIAL_CONNECT_TIMEOUT max(CONNECTION_SWITCH_MIN, obd_timeout / 20) /* The max delay between connects is SWITCH_MAX + SWITCH_INC + INITIAL */ #define RECONNECT_DELAY_MAX (CONNECTION_SWITCH_MAX + CONNECTION_SWITCH_INC + \ INITIAL_CONNECT_TIMEOUT) /* The min time a target should wait for clients to reconnect in recovery */ -#define OBD_RECOVERY_TIME_MIN (2*RECONNECT_DELAY_MAX) +#define OBD_RECOVERY_TIME_MIN (2 * RECONNECT_DELAY_MAX) #define OBD_IR_FACTOR_MIN 1 #define OBD_IR_FACTOR_MAX 10 -#define OBD_IR_FACTOR_DEFAULT (OBD_IR_FACTOR_MAX/2) +#define OBD_IR_FACTOR_DEFAULT (OBD_IR_FACTOR_MAX / 2) /* default timeout for the MGS to become IR_FULL */ -#define OBD_IR_MGS_TIMEOUT (4*obd_timeout) +#define OBD_IR_MGS_TIMEOUT (4 * obd_timeout) #define LONG_UNLINK 300 /* Unlink should happen before now */ /** @@ -526,7 +526,8 @@ do { \ POISON_PTR(ptr); \ } while (0) -#define KEY_IS(str) \ - (keylen >= (sizeof(str)-1) && memcmp(key, str, (sizeof(str)-1)) == 0) +#define KEY_IS(str) \ + (keylen >= (sizeof(str) - 1) && \ + memcmp(key, str, (sizeof(str) - 1)) == 0) #endif diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index 048214c..ce579a2 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -817,7 +817,7 @@ static __u64 ldlm_cli_cancel_local(struct ldlm_lock *lock) lock_res_and_lock(lock); ldlm_set_cbpending(lock); local_only = !!(lock->l_flags & - (LDLM_FL_LOCAL_ONLY|LDLM_FL_CANCEL_ON_BLOCK)); + (LDLM_FL_LOCAL_ONLY | LDLM_FL_CANCEL_ON_BLOCK)); ldlm_cancel_callback(lock); rc = ldlm_is_bl_ast(lock) ? LDLM_FL_BL_AST : LDLM_FL_CANCELING; unlock_res_and_lock(lock); @@ -1838,7 +1838,7 @@ static int ldlm_chain_lock_for_replay(struct ldlm_lock *lock, void *closure) * bug 17614: locks being actively cancelled. Get a reference * on a lock so that it does not disappear under us (e.g. due to cancel) */ - if (!(lock->l_flags & (LDLM_FL_FAILED|LDLM_FL_CANCELING))) { + if (!(lock->l_flags & (LDLM_FL_FAILED | LDLM_FL_CANCELING))) { list_add(&lock->l_pending_chain, list); LDLM_LOCK_GET(lock); } diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 2f48f7e..55ccd84 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -2472,7 +2472,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (och) { mode = och->och_flags & - (FMODE_READ|FMODE_WRITE); + (FMODE_READ | FMODE_WRITE); rc = ll_lease_close(och, inode, &lease_broken); if (rc == 0 && lease_broken) mode = 0; @@ -2959,7 +2959,7 @@ int ll_have_md_lock(struct inode *inode, __u64 *bits, struct lustre_handle lockh; ldlm_policy_data_t policy; enum ldlm_mode mode = (l_req_mode == LCK_MINMODE) ? - (LCK_CR|LCK_CW|LCK_PR|LCK_PW) : l_req_mode; + (LCK_CR | LCK_CW | LCK_PR | LCK_PW) : l_req_mode; struct lu_fid *fid; __u64 flags; int i; diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 49ed3df..b7f399e 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -659,7 +659,8 @@ static int ll_options(char *options, int *flags) *flags |= tmp; goto next; } - tmp = ll_set_opt("noflock", s1, LL_SBI_FLOCK|LL_SBI_LOCALFLOCK); + tmp = ll_set_opt("noflock", s1, + LL_SBI_FLOCK | LL_SBI_LOCALFLOCK); if (tmp) { *flags &= ~tmp; goto next; @@ -1549,14 +1550,14 @@ int ll_setattr(struct dentry *de, struct iattr *attr) { int mode = d_inode(de)->i_mode; - if ((attr->ia_valid & (ATTR_CTIME|ATTR_SIZE|ATTR_MODE)) == - (ATTR_CTIME|ATTR_SIZE|ATTR_MODE)) + if ((attr->ia_valid & (ATTR_CTIME | ATTR_SIZE | ATTR_MODE)) == + (ATTR_CTIME | ATTR_SIZE | ATTR_MODE)) attr->ia_valid |= MDS_OPEN_OWNEROVERRIDE; - if (((attr->ia_valid & (ATTR_MODE|ATTR_FORCE|ATTR_SIZE)) == - (ATTR_SIZE|ATTR_MODE)) && + if (((attr->ia_valid & (ATTR_MODE | ATTR_FORCE | ATTR_SIZE)) == + (ATTR_SIZE | ATTR_MODE)) && (((mode & S_ISUID) && !(attr->ia_mode & S_ISUID)) || - (((mode & (S_ISGID|S_IXGRP)) == (S_ISGID|S_IXGRP)) && + (((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) && !(attr->ia_mode & S_ISGID)))) attr->ia_valid |= ATTR_FORCE; @@ -1567,7 +1568,7 @@ int ll_setattr(struct dentry *de, struct iattr *attr) attr->ia_valid |= ATTR_KILL_SUID; if ((attr->ia_valid & ATTR_MODE) && - ((mode & (S_ISGID|S_IXGRP)) == (S_ISGID|S_IXGRP)) && + ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) && !(attr->ia_mode & S_ISGID) && !(attr->ia_valid & ATTR_KILL_SGID)) attr->ia_valid |= ATTR_KILL_SGID; @@ -1742,9 +1743,11 @@ int ll_update_inode(struct inode *inode, struct lustre_md *md) lli->lli_ctime = body->mbo_ctime; } if (body->mbo_valid & OBD_MD_FLMODE) - inode->i_mode = (inode->i_mode & S_IFMT)|(body->mbo_mode & ~S_IFMT); + inode->i_mode = (inode->i_mode & S_IFMT) | + (body->mbo_mode & ~S_IFMT); if (body->mbo_valid & OBD_MD_FLTYPE) - inode->i_mode = (inode->i_mode & ~S_IFMT)|(body->mbo_mode & S_IFMT); + inode->i_mode = (inode->i_mode & ~S_IFMT) | + (body->mbo_mode & S_IFMT); LASSERT(inode->i_mode != 0); if (S_ISREG(inode->i_mode)) inode->i_blkbits = min(PTLRPC_MAX_BRW_BITS + 1, diff --git a/drivers/staging/lustre/lustre/llite/llite_mmap.c b/drivers/staging/lustre/lustre/llite/llite_mmap.c index 66ee5db..9d03e79 100644 --- a/drivers/staging/lustre/lustre/llite/llite_mmap.c +++ b/drivers/staging/lustre/lustre/llite/llite_mmap.c @@ -126,7 +126,7 @@ restart: fio = &io->u.ci_fault; fio->ft_index = index; - fio->ft_executable = vma->vm_flags&VM_EXEC; + fio->ft_executable = vma->vm_flags & VM_EXEC; /* * disable VM_SEQ_READ and use VM_RAND_READ to make sure that @@ -134,7 +134,7 @@ restart: * filemap_nopage. we do our readahead in ll_readpage. */ if (ra_flags) - *ra_flags = vma->vm_flags & (VM_RAND_READ|VM_SEQ_READ); + *ra_flags = vma->vm_flags & (VM_RAND_READ | VM_SEQ_READ); vma->vm_flags &= ~VM_SEQ_READ; vma->vm_flags |= VM_RAND_READ; diff --git a/drivers/staging/lustre/lustre/llite/lproc_llite.c b/drivers/staging/lustre/lustre/llite/lproc_llite.c index 5f8e78d..4e82db8 100644 --- a/drivers/staging/lustre/lustre/llite/lproc_llite.c +++ b/drivers/staging/lustre/lustre/llite/lproc_llite.c @@ -996,17 +996,17 @@ static const struct llite_file_opcode { /* file operation */ { LPROC_LL_DIRTY_HITS, LPROCFS_TYPE_REGS, "dirty_pages_hits" }, { LPROC_LL_DIRTY_MISSES, LPROCFS_TYPE_REGS, "dirty_pages_misses" }, - { LPROC_LL_READ_BYTES, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_BYTES, + { LPROC_LL_READ_BYTES, LPROCFS_CNTR_AVGMINMAX | LPROCFS_TYPE_BYTES, "read_bytes" }, - { LPROC_LL_WRITE_BYTES, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_BYTES, + { LPROC_LL_WRITE_BYTES, LPROCFS_CNTR_AVGMINMAX | LPROCFS_TYPE_BYTES, "write_bytes" }, - { LPROC_LL_BRW_READ, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_PAGES, + { LPROC_LL_BRW_READ, LPROCFS_CNTR_AVGMINMAX | LPROCFS_TYPE_PAGES, "brw_read" }, - { LPROC_LL_BRW_WRITE, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_PAGES, + { LPROC_LL_BRW_WRITE, LPROCFS_CNTR_AVGMINMAX | LPROCFS_TYPE_PAGES, "brw_write" }, - { LPROC_LL_OSC_READ, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_BYTES, + { LPROC_LL_OSC_READ, LPROCFS_CNTR_AVGMINMAX | LPROCFS_TYPE_BYTES, "osc_read" }, - { LPROC_LL_OSC_WRITE, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_BYTES, + { LPROC_LL_OSC_WRITE, LPROCFS_CNTR_AVGMINMAX | LPROCFS_TYPE_BYTES, "osc_write" }, { LPROC_LL_IOCTL, LPROCFS_TYPE_REGS, "ioctl" }, { LPROC_LL_OPEN, LPROCFS_TYPE_REGS, "open" }, @@ -1253,7 +1253,7 @@ static void ll_display_extents_info(struct ll_rw_extents_info *io_extents, r, pct(r, read_tot), pct(read_cum, read_tot), w, pct(w, write_tot), pct(write_cum, write_tot)); start = end; - if (start == 1<<10) { + if (start == 1 << 10) { start = 1; units += 10; unitp++; diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index 8066f0d..7495c0f 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -614,7 +614,7 @@ static struct dentry *ll_lookup_nd(struct inode *parent, struct dentry *dentry, (inode_permission(parent, MAY_WRITE | MAY_EXEC) == 0)) return NULL; - if (flags & (LOOKUP_PARENT|LOOKUP_OPEN|LOOKUP_CREATE)) + if (flags & (LOOKUP_PARENT | LOOKUP_OPEN | LOOKUP_CREATE)) itp = NULL; else itp = ⁢ @@ -1012,7 +1012,7 @@ static int ll_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) if (!IS_POSIXACL(dir) || !exp_connect_umask(ll_i2mdexp(dir))) mode &= ~current_umask(); - mode = (mode & (S_IRWXUGO|S_ISVTX)) | S_IFDIR; + mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR; err = ll_new_node(dir, dentry, NULL, mode, 0, LUSTRE_OPC_MKDIR); if (!err) diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index 01aee84..f053f55 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -651,7 +651,8 @@ static void ras_update_stride_detector(struct ll_readahead_state *ras, if (!stride_io_mode(ras) && (stride_gap != 0 || ras->ras_consecutive_stride_requests == 0)) { ras->ras_stride_pages = ras->ras_consecutive_pages; - ras->ras_stride_length = stride_gap+ras->ras_consecutive_pages; + ras->ras_stride_length = ras->ras_consecutive_pages + + stride_gap; } LASSERT(ras->ras_request_index == 0); LASSERT(ras->ras_consecutive_stride_requests == 0); @@ -663,7 +664,7 @@ static void ras_update_stride_detector(struct ll_readahead_state *ras, } ras->ras_stride_pages = ras->ras_consecutive_pages; - ras->ras_stride_length = stride_gap+ras->ras_consecutive_pages; + ras->ras_stride_length = stride_gap + ras->ras_consecutive_pages; RAS_CDEBUG(ras); return; diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c index 8c8c100..2f8ef54 100644 --- a/drivers/staging/lustre/lustre/llite/rw26.c +++ b/drivers/staging/lustre/lustre/llite/rw26.c @@ -161,7 +161,7 @@ static int ll_releasepage(struct page *vmpage, gfp_t gfp_mask) return result; } -#define MAX_DIRECTIO_SIZE (2*1024*1024*1024UL) +#define MAX_DIRECTIO_SIZE (2 * 1024 * 1024 * 1024UL) static inline int ll_get_user_pages(int rw, unsigned long user_addr, size_t size, struct page ***pages, diff --git a/drivers/staging/lustre/lustre/llite/super25.c b/drivers/staging/lustre/lustre/llite/super25.c index 3dd7e0e..883084e 100644 --- a/drivers/staging/lustre/lustre/llite/super25.c +++ b/drivers/staging/lustre/lustre/llite/super25.c @@ -102,8 +102,8 @@ static int __init lustre_init(void) rc = -ENOMEM; ll_inode_cachep = kmem_cache_create("lustre_inode_cache", - sizeof(struct ll_inode_info), - 0, SLAB_HWCACHE_ALIGN|SLAB_ACCOUNT, + sizeof(struct ll_inode_info), 0, + SLAB_HWCACHE_ALIGN | SLAB_ACCOUNT, NULL); if (!ll_inode_cachep) goto out_cache; diff --git a/drivers/staging/lustre/lustre/llite/vvp_object.c b/drivers/staging/lustre/lustre/llite/vvp_object.c index 2c520b0..e4080ba 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_object.c +++ b/drivers/staging/lustre/lustre/llite/vvp_object.c @@ -120,7 +120,7 @@ static int vvp_attr_set(const struct lu_env *env, struct cl_object *obj, if (0 && valid & CAT_SIZE) i_size_write(inode, attr->cat_size); /* not currently necessary */ - if (0 && valid & (CAT_UID|CAT_GID|CAT_SIZE)) + if (0 && valid & (CAT_UID | CAT_GID | CAT_SIZE)) mark_inode_dirty(inode); return 0; } diff --git a/drivers/staging/lustre/lustre/lov/lov_ea.c b/drivers/staging/lustre/lustre/lov/lov_ea.c index 5053dea..d88b81d 100644 --- a/drivers/staging/lustre/lustre/lov/lov_ea.c +++ b/drivers/staging/lustre/lustre/lov/lov_ea.c @@ -66,7 +66,8 @@ static int lsm_lmm_verify_common(struct lov_mds_md *lmm, int lmm_bytes, } if (lmm->lmm_stripe_size == 0 || - (le32_to_cpu(lmm->lmm_stripe_size)&(LOV_MIN_STRIPE_SIZE-1)) != 0) { + (le32_to_cpu(lmm->lmm_stripe_size) & + (LOV_MIN_STRIPE_SIZE - 1)) != 0) { CERROR("bad stripe size %u\n", le32_to_cpu(lmm->lmm_stripe_size)); lov_dump_lmm_common(D_WARNING, lmm); diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index 49b1050..1f8a0fc 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -1917,8 +1917,9 @@ inactive_tgt: break; } - len_mapped_single_call = lcl_fm_ext[ext_count-1].fe_logical - - lun_start + lcl_fm_ext[ext_count - 1].fe_length; + len_mapped_single_call = + lcl_fm_ext[ext_count - 1].fe_logical - + lun_start + lcl_fm_ext[ext_count - 1].fe_length; /* Have we finished mapping on this device? */ if (req_fm_len <= len_mapped_single_call) @@ -1927,14 +1928,15 @@ inactive_tgt: /* Clear the EXTENT_LAST flag which can be present on * last extent */ - if (lcl_fm_ext[ext_count-1].fe_flags & FIEMAP_EXTENT_LAST) + if (lcl_fm_ext[ext_count - 1].fe_flags & + FIEMAP_EXTENT_LAST) lcl_fm_ext[ext_count - 1].fe_flags &= ~FIEMAP_EXTENT_LAST; curr_loc = lov_stripe_size(lsm, - lcl_fm_ext[ext_count - 1].fe_logical+ - lcl_fm_ext[ext_count - 1].fe_length, - cur_stripe); + lcl_fm_ext[ext_count - 1].fe_logical + + lcl_fm_ext[ext_count - 1].fe_length, + cur_stripe); if (curr_loc >= fm_key->oa.o_size) ost_eof = 1; diff --git a/drivers/staging/lustre/lustre/lov/lov_pool.c b/drivers/staging/lustre/lustre/lov/lov_pool.c index 8bfa101..f8c8a36 100644 --- a/drivers/staging/lustre/lustre/lov/lov_pool.c +++ b/drivers/staging/lustre/lustre/lov/lov_pool.c @@ -92,7 +92,7 @@ static __u32 pool_hashfn(struct cfs_hash *hash_body, const void *key, unsigned m for (i = 0; i < LOV_MAXPOOLNAME; i++) { if (poolname[i] == '\0') break; - result = (result << 4)^(result >> 28) ^ poolname[i]; + result = (result << 4) ^ (result >> 28) ^ poolname[i]; } return (result % mask); } diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index 89b4ae7..c234e35 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -274,7 +274,7 @@ mdc_intent_open_pack(struct obd_export *exp, struct lookup_intent *it, else mode = LCK_PR; } else { - if (it->it_flags & (FMODE_WRITE|MDS_OPEN_TRUNC)) + if (it->it_flags & (FMODE_WRITE | MDS_OPEN_TRUNC)) mode = LCK_CW; else if (it->it_flags & __FMODE_EXEC) mode = LCK_PR; diff --git a/drivers/staging/lustre/lustre/mdc/mdc_reint.c b/drivers/staging/lustre/lustre/mdc/mdc_reint.c index 0f71392..c018e3b 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_reint.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_reint.c @@ -110,7 +110,7 @@ int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data, __u64 bits; bits = MDS_INODELOCK_UPDATE; - if (op_data->op_attr.ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) + if (op_data->op_attr.ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) bits |= MDS_INODELOCK_LOOKUP; if ((op_data->op_flags & MF_MDC_CANCEL_FID1) && (fid_is_sane(&op_data->op_fid1)) && @@ -429,7 +429,8 @@ int mdc_rename(struct obd_export *exp, struct md_op_data *op_data, } req_capsule_set_size(&req->rq_pill, &RMF_NAME, RCL_CLIENT, oldlen + 1); - req_capsule_set_size(&req->rq_pill, &RMF_SYMTGT, RCL_CLIENT, newlen+1); + req_capsule_set_size(&req->rq_pill, &RMF_SYMTGT, RCL_CLIENT, + newlen + 1); rc = mdc_prep_elc_req(exp, req, MDS_REINT, &cancels, count); if (rc) { diff --git a/drivers/staging/lustre/lustre/obdclass/debug.c b/drivers/staging/lustre/lustre/obdclass/debug.c index 8acf672..0bd4ad2 100644 --- a/drivers/staging/lustre/lustre/obdclass/debug.c +++ b/drivers/staging/lustre/lustre/obdclass/debug.c @@ -48,10 +48,10 @@ int block_debug_setup(void *addr, int len, __u64 off, __u64 id) LASSERT(addr); put_unaligned_le64(off, addr); - put_unaligned_le64(id, addr+LPDS); + put_unaligned_le64(id, addr + LPDS); addr += len - LPDS - LPDS; put_unaligned_le64(off, addr); - put_unaligned_le64(id, addr+LPDS); + put_unaligned_le64(id, addr + LPDS); return 0; } diff --git a/drivers/staging/lustre/lustre/obdclass/genops.c b/drivers/staging/lustre/lustre/obdclass/genops.c index 6356870..0bc623e 100644 --- a/drivers/staging/lustre/lustre/obdclass/genops.c +++ b/drivers/staging/lustre/lustre/obdclass/genops.c @@ -509,7 +509,7 @@ struct obd_device *class_devices_in_group(struct obd_uuid *grp_uuid, int *next) continue; if (obd_uuid_equals(grp_uuid, &obd->obd_uuid)) { if (next) - *next = i+1; + *next = i + 1; read_unlock(&obd_dev_lock); return obd; } diff --git a/drivers/staging/lustre/lustre/obdclass/obd_config.c b/drivers/staging/lustre/lustre/obdclass/obd_config.c index 220fda7..b7dcadb 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_config.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_config.c @@ -1304,33 +1304,33 @@ static int class_config_parse_rec(struct llog_rec_hdr *rec, char *buf, if (rc < 0) return rc; - ptr += snprintf(ptr, end-ptr, "cmd=%05x ", lcfg->lcfg_command); + ptr += snprintf(ptr, end - ptr, "cmd=%05x ", lcfg->lcfg_command); if (lcfg->lcfg_flags) - ptr += snprintf(ptr, end-ptr, "flags=%#08x ", + ptr += snprintf(ptr, end - ptr, "flags=%#08x ", lcfg->lcfg_flags); if (lcfg->lcfg_num) - ptr += snprintf(ptr, end-ptr, "num=%#08x ", lcfg->lcfg_num); + ptr += snprintf(ptr, end - ptr, "num=%#08x ", lcfg->lcfg_num); if (lcfg->lcfg_nid) { char nidstr[LNET_NIDSTR_SIZE]; libcfs_nid2str_r(lcfg->lcfg_nid, nidstr, sizeof(nidstr)); - ptr += snprintf(ptr, end-ptr, "nid=%s(%#llx)\n ", + ptr += snprintf(ptr, end - ptr, "nid=%s(%#llx)\n ", nidstr, lcfg->lcfg_nid); } if (lcfg->lcfg_command == LCFG_MARKER) { struct cfg_marker *marker = lustre_cfg_buf(lcfg, 1); - ptr += snprintf(ptr, end-ptr, "marker=%d(%#x)%s '%s'", + ptr += snprintf(ptr, end - ptr, "marker=%d(%#x)%s '%s'", marker->cm_step, marker->cm_flags, marker->cm_tgtname, marker->cm_comment); } else { int i; for (i = 0; i < lcfg->lcfg_bufcount; i++) { - ptr += snprintf(ptr, end-ptr, "%d:%s ", i, + ptr += snprintf(ptr, end - ptr, "%d:%s ", i, lustre_cfg_string(lcfg, i)); } } diff --git a/drivers/staging/lustre/lustre/obdclass/obd_mount.c b/drivers/staging/lustre/lustre/obdclass/obd_mount.c index b838194..0c48257 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_mount.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_mount.c @@ -37,7 +37,7 @@ */ #define DEBUG_SUBSYSTEM S_CLASS -#define D_MOUNT (D_SUPER|D_CONFIG/*|D_WARNING */) +#define D_MOUNT (D_SUPER | D_CONFIG/*|D_WARNING */) #define PRINT_CMD CDEBUG #include "../include/obd.h" @@ -757,7 +757,7 @@ static int lmd_make_exclusion(struct lustre_mount_data *lmd, const char *ptr) exclude_list[lmd->lmd_exclude_count++] = index; else CDEBUG(D_MOUNT, "ignoring exclude %.*s: type = %#x\n", - (uint)(s2-s1), s1, rc); + (uint)(s2 - s1), s1, rc); s1 = s2; /* now we are pointing at ':' (next exclude) * or ',' (end of excludes) @@ -1108,7 +1108,7 @@ static int lustre_fill_super(struct super_block *sb, void *data, int silent) struct lustre_sb_info *lsi; int rc; - CDEBUG(D_MOUNT|D_VFSTRACE, "VFS Op: sb %p\n", sb); + CDEBUG(D_MOUNT | D_VFSTRACE, "VFS Op: sb %p\n", sb); lsi = lustre_init_lsi(sb); if (!lsi) diff --git a/drivers/staging/lustre/lustre/obdclass/obdo.c b/drivers/staging/lustre/lustre/obdclass/obdo.c index 4454764..79104a6 100644 --- a/drivers/staging/lustre/lustre/obdclass/obdo.c +++ b/drivers/staging/lustre/lustre/obdclass/obdo.c @@ -153,12 +153,14 @@ static void iattr_from_obdo(struct iattr *attr, const struct obdo *oa, } #if 0 /* you shouldn't be able to change a file's type with setattr */ if (valid & OBD_MD_FLTYPE) { - attr->ia_mode = (attr->ia_mode & ~S_IFMT)|(oa->o_mode & S_IFMT); + attr->ia_mode = (attr->ia_mode & ~S_IFMT) | + (oa->o_mode & S_IFMT); attr->ia_valid |= ATTR_MODE; } #endif if (valid & OBD_MD_FLMODE) { - attr->ia_mode = (attr->ia_mode & S_IFMT)|(oa->o_mode & ~S_IFMT); + attr->ia_mode = (attr->ia_mode & S_IFMT) | + (oa->o_mode & ~S_IFMT); attr->ia_valid |= ATTR_MODE; if (!in_group_p(make_kgid(&init_user_ns, oa->o_gid)) && !capable(CFS_CAP_FSETID)) diff --git a/drivers/staging/lustre/lustre/obdecho/echo_internal.h b/drivers/staging/lustre/lustre/obdecho/echo_internal.h index f5034a2..966414f 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_internal.h +++ b/drivers/staging/lustre/lustre/obdecho/echo_internal.h @@ -33,9 +33,9 @@ /* The persistent object (i.e. actually stores stuff!) */ #define ECHO_PERSISTENT_OBJID 1ULL -#define ECHO_PERSISTENT_SIZE ((__u64)(1<<20)) +#define ECHO_PERSISTENT_SIZE ((__u64)(1 << 20)) /* block size to use for data verification */ -#define OBD_ECHO_BLOCK_SIZE (4<<10) +#define OBD_ECHO_BLOCK_SIZE (4 << 10) #endif diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index c6e37c0..ebcebe8 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -2544,7 +2544,7 @@ int osc_flush_async_page(const struct lu_env *env, struct cl_io *io, goto out; spin_lock(&oap->oap_lock); - oap->oap_async_flags |= ASYNC_READY|ASYNC_URGENT; + oap->oap_async_flags |= ASYNC_READY | ASYNC_URGENT; spin_unlock(&oap->oap_lock); if (memory_pressure_get()) diff --git a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h index c8c3f1c..d41680b 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h @@ -389,7 +389,7 @@ extern struct lu_device_type osc_device_type; extern struct lu_context_key osc_key; extern struct lu_context_key osc_session_key; -#define OSC_FLAGS (ASYNC_URGENT|ASYNC_READY) +#define OSC_FLAGS (ASYNC_URGENT | ASYNC_READY) int osc_lock_init(const struct lu_env *env, struct cl_object *obj, struct cl_lock *lock, diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c index 69424ea..f6db60c 100644 --- a/drivers/staging/lustre/lustre/osc/osc_io.c +++ b/drivers/staging/lustre/lustre/osc/osc_io.c @@ -164,7 +164,7 @@ static int osc_io_submit(const struct lu_env *env, } spin_lock(&oap->oap_lock); - oap->oap_async_flags = ASYNC_URGENT|ASYNC_READY; + oap->oap_async_flags = ASYNC_URGENT | ASYNC_READY; oap->oap_async_flags |= ASYNC_COUNT_STABLE; spin_unlock(&oap->oap_lock); diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 3709440..53c191d 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -791,7 +791,7 @@ static int osc_destroy(const struct lu_env *env, struct obd_export *exp, static void osc_announce_cached(struct client_obd *cli, struct obdo *oa, long writing_bytes) { - u32 bits = OBD_MD_FLBLOCKS|OBD_MD_FLGRANT; + u32 bits = OBD_MD_FLBLOCKS | OBD_MD_FLGRANT; LASSERT(!(oa->o_valid & bits)); @@ -824,7 +824,7 @@ static void osc_announce_cached(struct client_obd *cli, struct obdo *oa, oa->o_undirty = 0; } else { long max_in_flight = (cli->cl_max_pages_per_rpc << - PAGE_SHIFT)* + PAGE_SHIFT) * (cli->cl_max_rpcs_in_flight + 1); oa->o_undirty = max(cli->cl_dirty_max_pages << PAGE_SHIFT, max_in_flight); @@ -1463,7 +1463,8 @@ static int check_write_checksum(struct obdo *oa, const lnet_process_id_t *peer, oa->o_valid & OBD_MD_FLFID ? oa->o_parent_oid : 0, oa->o_valid & OBD_MD_FLFID ? oa->o_parent_ver : 0, POSTID(&oa->o_oi), pga[0]->off, - pga[page_count-1]->off + pga[page_count-1]->count - 1); + pga[page_count - 1]->off + + pga[page_count - 1]->count - 1); CERROR("original client csum %x (type %x), server csum %x (type %x), client csum now %x\n", client_cksum, client_cksum_type, server_cksum, cksum_type, new_cksum); @@ -1565,7 +1566,8 @@ static int osc_brw_fini_request(struct ptlrpc_request *req, int rc) char *router = ""; enum cksum_type cksum_type; - cksum_type = cksum_type_unpack(body->oa.o_valid&OBD_MD_FLFLAGS ? + cksum_type = cksum_type_unpack(body->oa.o_valid & + OBD_MD_FLFLAGS ? body->oa.o_flags : 0); client_cksum = osc_checksum_bulk(rc, aa->aa_page_count, aa->aa_ppga, OST_READ, @@ -1999,7 +2001,7 @@ int osc_build_rpc(const struct lu_env *env, struct client_obd *cli, body = req_capsule_client_get(&req->rq_pill, &RMF_OST_BODY); crattr->cra_oa = &body->oa; cl_req_attr_set(env, clerq, crattr, - OBD_MD_FLMTIME|OBD_MD_FLCTIME|OBD_MD_FLATIME); + OBD_MD_FLMTIME | OBD_MD_FLCTIME | OBD_MD_FLATIME); lustre_msg_set_jobid(req->rq_reqmsg, crattr->cra_jobid); diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c index c0122ef..93b1e78 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/import.c +++ b/drivers/staging/lustre/lustre/ptlrpc/import.c @@ -307,7 +307,8 @@ void ptlrpc_invalidate_import(struct obd_import *imp) */ lwi = LWI_TIMEOUT_INTERVAL( cfs_timeout_cap(cfs_time_seconds(timeout)), - (timeout > 1)?cfs_time_seconds(1):cfs_time_seconds(1)/2, + (timeout > 1) ? cfs_time_seconds(1) : + cfs_time_seconds(1) / 2, NULL, NULL); rc = l_wait_event(imp->imp_recovery_waitq, (atomic_read(&imp->imp_inflight) == 0), @@ -698,7 +699,8 @@ int ptlrpc_connect_import(struct obd_import *imp) request->rq_send_state = LUSTRE_IMP_CONNECTING; /* Allow a slightly larger reply for future growth compatibility */ req_capsule_set_size(&request->rq_pill, &RMF_CONNECT_DATA, RCL_SERVER, - sizeof(struct obd_connect_data)+16*sizeof(__u64)); + sizeof(struct obd_connect_data) + + 16 * sizeof(__u64)); ptlrpc_request_set_replen(request); request->rq_interpret_reply = ptlrpc_connect_interpret; diff --git a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c index bc93b75..327cf63 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c +++ b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c @@ -191,7 +191,7 @@ ptlrpc_ldebugfs_register(struct dentry *root, char *dir, LASSERT(!*debugfs_root_ret); LASSERT(!*stats_ret); - svc_stats = lprocfs_alloc_stats(EXTRA_MAX_OPCODES+LUSTRE_MAX_OPCODES, + svc_stats = lprocfs_alloc_stats(EXTRA_MAX_OPCODES + LUSTRE_MAX_OPCODES, 0); if (!svc_stats) return; diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c index 0a374b6..1f55d64 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c @@ -412,7 +412,7 @@ static int ptlrpcd(void *arg) * an argument, describing its "scope". */ rc = lu_context_init(&env.le_ctx, - LCT_CL_THREAD|LCT_REMEMBER|LCT_NOREF); + LCT_CL_THREAD | LCT_REMEMBER | LCT_NOREF); if (rc == 0) { rc = lu_context_init(env.le_ses, LCT_SESSION | LCT_REMEMBER | LCT_NOREF); @@ -567,7 +567,7 @@ int ptlrpcd_start(struct ptlrpcd_ctl *pc) * ptlrpcd thread (or a thread-set) has to be given an argument, * describing its "scope". */ - rc = lu_context_init(&pc->pc_env.le_ctx, LCT_CL_THREAD|LCT_REMEMBER); + rc = lu_context_init(&pc->pc_env.le_ctx, LCT_CL_THREAD | LCT_REMEMBER); if (rc != 0) goto out; diff --git a/drivers/staging/lustre/lustre/ptlrpc/service.c b/drivers/staging/lustre/lustre/ptlrpc/service.c index 30d8b72..be3c96c 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/service.c +++ b/drivers/staging/lustre/lustre/ptlrpc/service.c @@ -2057,7 +2057,7 @@ static int ptlrpc_main(void *arg) } rc = lu_context_init(&env->le_ctx, - svc->srv_ctx_tags|LCT_REMEMBER|LCT_NOREF); + svc->srv_ctx_tags | LCT_REMEMBER | LCT_NOREF); if (rc) goto out_srv_fini; -- cgit v0.10.2 From 24c198e9569b8a014ee8d10bc724e908d3814ec8 Mon Sep 17 00:00:00 2001 From: Oleg Drokin <green@linuxhacker.ru> Date: Sun, 21 Aug 2016 18:04:35 -0400 Subject: staging/lustre: Make alignment match open parenthesis This patch fixes most of checkpatch occurences of "CHECK: Alignment should match open parenthesis" in Lustre code. Signed-off-by: Emoly Liu <emoly.liu@intel.com> Signed-off-by: Oleg Drokin <green@linuxhacker.ru> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs.h b/drivers/staging/lustre/include/linux/libcfs/libcfs.h index 3f6447c..3b92d38 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs.h @@ -138,8 +138,8 @@ struct lnet_debugfs_symlink_def { void lustre_insert_debugfs(struct ctl_table *table, const struct lnet_debugfs_symlink_def *symlinks); int lprocfs_call_handler(void *data, int write, loff_t *ppos, - void __user *buffer, size_t *lenp, - int (*handler)(void *data, int write, - loff_t pos, void __user *buffer, int len)); + void __user *buffer, size_t *lenp, + int (*handler)(void *data, int write, loff_t pos, + void __user *buffer, int len)); #endif /* _LIBCFS_H */ diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h index 25adab1..b7bd6e8 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h @@ -247,19 +247,19 @@ do { \ #define LCONSOLE_EMERG(format, ...) CDEBUG(D_CONSOLE | D_EMERG, format, ## __VA_ARGS__) int libcfs_debug_msg(struct libcfs_debug_msg_data *msgdata, - const char *format1, ...) + const char *format1, ...) __printf(2, 3); int libcfs_debug_vmsg2(struct libcfs_debug_msg_data *msgdata, - const char *format1, - va_list args, const char *format2, ...) + const char *format1, + va_list args, const char *format2, ...) __printf(4, 5); /* other external symbols that tracefile provides: */ int cfs_trace_copyin_string(char *knl_buffer, int knl_buffer_nob, - const char __user *usr_buffer, int usr_buffer_nob); + const char __user *usr_buffer, int usr_buffer_nob); int cfs_trace_copyout_string(char __user *usr_buffer, int usr_buffer_nob, - const char *knl_buffer, char *append); + const char *knl_buffer, char *append); #define LIBCFS_DEBUG_FILE_PATH_DEFAULT "/tmp/lustre-log" diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c index 4f5978b..e93dbeb 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c @@ -618,7 +618,7 @@ static int kiblnd_get_completion_vector(struct kib_conn *conn, int cpt) } struct kib_conn *kiblnd_create_conn(struct kib_peer *peer, struct rdma_cm_id *cmid, - int state, int version) + int state, int version) { /* * CAVEAT EMPTOR: diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index 25f87e5..1563428 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -41,9 +41,10 @@ static void kiblnd_peer_alive(struct kib_peer *peer); static void kiblnd_peer_connect_failed(struct kib_peer *peer, int active, int error); static void kiblnd_init_tx_msg(lnet_ni_t *ni, struct kib_tx *tx, - int type, int body_nob); + int type, int body_nob); static int kiblnd_init_rdma(struct kib_conn *conn, struct kib_tx *tx, int type, - int resid, struct kib_rdma_desc *dstrd, __u64 dstcookie); + int resid, struct kib_rdma_desc *dstrd, + __u64 dstcookie); static void kiblnd_queue_tx_locked(struct kib_tx *tx, struct kib_conn *conn); static void kiblnd_queue_tx(struct kib_tx *tx, struct kib_conn *conn); static void kiblnd_unmap_tx(lnet_ni_t *ni, struct kib_tx *tx); diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h index 068440e..e6ca0cf 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h @@ -631,7 +631,7 @@ int ksocknal_close_peer_conns_locked(struct ksock_peer *peer, int ksocknal_close_conn_and_siblings(struct ksock_conn *conn, int why); int ksocknal_close_matching_conns(lnet_process_id_t id, __u32 ipaddr); struct ksock_conn *ksocknal_find_conn_locked(struct ksock_peer *peer, - struct ksock_tx *tx, int nonblk); + struct ksock_tx *tx, int nonblk); int ksocknal_launch_packet(lnet_ni_t *ni, struct ksock_tx *tx, lnet_process_id_t id); diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c index 5c0116a..7f56d2c 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto.c @@ -95,8 +95,8 @@ static int cfs_crypto_hash_alloc(enum cfs_crypto_hash_alg hash_alg, err = crypto_ahash_setkey(tfm, key, key_len); else if ((*type)->cht_key != 0) err = crypto_ahash_setkey(tfm, - (unsigned char *)&((*type)->cht_key), - (*type)->cht_size); + (unsigned char *)&((*type)->cht_key), + (*type)->cht_size); if (err != 0) { ahash_request_free(*req); diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index db9466a..4c00be2 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -323,7 +323,7 @@ struct cl_object_operations { * to be used instead of newly created. */ int (*coo_page_init)(const struct lu_env *env, struct cl_object *obj, - struct cl_page *page, pgoff_t index); + struct cl_page *page, pgoff_t index); /** * Initialize lock slice for this layer. Called top-to-bottom through * every object layer when a new cl_lock is instantiated. Layer diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_extent.c b/drivers/staging/lustre/lustre/ldlm/ldlm_extent.c index f5023d9..ecf472e 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_extent.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_extent.c @@ -221,7 +221,7 @@ void ldlm_extent_unlink_lock(struct ldlm_lock *lock) } void ldlm_extent_policy_wire_to_local(const ldlm_wire_policy_data_t *wpolicy, - ldlm_policy_data_t *lpolicy) + ldlm_policy_data_t *lpolicy) { memset(lpolicy, 0, sizeof(*lpolicy)); lpolicy->l_extent.start = wpolicy->l_extent.start; @@ -230,7 +230,7 @@ void ldlm_extent_policy_wire_to_local(const ldlm_wire_policy_data_t *wpolicy, } void ldlm_extent_policy_local_to_wire(const ldlm_policy_data_t *lpolicy, - ldlm_wire_policy_data_t *wpolicy) + ldlm_wire_policy_data_t *wpolicy) { memset(wpolicy, 0, sizeof(*wpolicy)); wpolicy->l_extent.start = lpolicy->l_extent.start; diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c index 61d649f..78a8450 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c @@ -166,7 +166,7 @@ reprocess: */ list_for_each(tmp, &res->lr_granted) { lock = list_entry(tmp, struct ldlm_lock, - l_res_link); + l_res_link); if (ldlm_same_flock_owner(lock, req)) { ownlocks = tmp; break; @@ -182,7 +182,7 @@ reprocess: */ list_for_each(tmp, &res->lr_granted) { lock = list_entry(tmp, struct ldlm_lock, - l_res_link); + l_res_link); if (ldlm_same_flock_owner(lock, req)) { if (!ownlocks) diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h b/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h index e4cf65d..dc0e4af 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h @@ -100,8 +100,8 @@ enum { int ldlm_cancel_lru(struct ldlm_namespace *ns, int nr, enum ldlm_cancel_flags sync, int flags); int ldlm_cancel_lru_local(struct ldlm_namespace *ns, - struct list_head *cancels, int count, int max, - enum ldlm_cancel_flags cancel_flags, int flags); + struct list_head *cancels, int count, int max, + enum ldlm_cancel_flags cancel_flags, int flags); extern int ldlm_enqueue_min; /* ldlm_resource.c */ @@ -200,8 +200,7 @@ ldlm_interval_extent(struct ldlm_interval *node) LASSERT(!list_empty(&node->li_group)); - lock = list_entry(node->li_group.next, struct ldlm_lock, - l_sl_policy); + lock = list_entry(node->li_group.next, struct ldlm_lock, l_sl_policy); return &lock->l_policy_data.l_extent; } @@ -302,7 +301,7 @@ static inline int is_granted_or_cancelled(struct ldlm_lock *lock) lock_res_and_lock(lock); if ((lock->l_req_mode == lock->l_granted_mode) && - !ldlm_is_cp_reqd(lock)) + !ldlm_is_cp_reqd(lock)) ret = 1; else if (ldlm_is_failed(lock) || ldlm_is_cancel(lock)) ret = 1; @@ -326,13 +325,13 @@ void ldlm_ibits_policy_wire_to_local(const ldlm_wire_policy_data_t *wpolicy, void ldlm_ibits_policy_local_to_wire(const ldlm_policy_data_t *lpolicy, ldlm_wire_policy_data_t *wpolicy); void ldlm_extent_policy_wire_to_local(const ldlm_wire_policy_data_t *wpolicy, - ldlm_policy_data_t *lpolicy); + ldlm_policy_data_t *lpolicy); void ldlm_extent_policy_local_to_wire(const ldlm_policy_data_t *lpolicy, - ldlm_wire_policy_data_t *wpolicy); + ldlm_wire_policy_data_t *wpolicy); void ldlm_flock_policy_wire18_to_local(const ldlm_wire_policy_data_t *wpolicy, - ldlm_policy_data_t *lpolicy); + ldlm_policy_data_t *lpolicy); void ldlm_flock_policy_wire21_to_local(const ldlm_wire_policy_data_t *wpolicy, - ldlm_policy_data_t *lpolicy); + ldlm_policy_data_t *lpolicy); void ldlm_flock_policy_local_to_wire(const ldlm_policy_data_t *lpolicy, ldlm_wire_policy_data_t *wpolicy); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c index 3c98ce2..0d466e2 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c @@ -82,7 +82,7 @@ static int import_set_conn(struct obd_import *imp, struct obd_uuid *uuid, if (priority) { list_del(&item->oic_item); list_add(&item->oic_item, - &imp->imp_conn_list); + &imp->imp_conn_list); item->oic_last_attempt = 0; } CDEBUG(D_HA, "imp %p@%s: found existing conn %s%s\n", @@ -102,7 +102,7 @@ static int import_set_conn(struct obd_import *imp, struct obd_uuid *uuid, list_add(&imp_conn->oic_item, &imp->imp_conn_list); else list_add_tail(&imp_conn->oic_item, - &imp->imp_conn_list); + &imp->imp_conn_list); CDEBUG(D_HA, "imp %p@%s: add connection %s at %s\n", imp, imp->imp_obd->obd_name, uuid->uuid, (priority ? "head" : "tail")); @@ -692,7 +692,7 @@ void target_send_reply(struct ptlrpc_request *req, int rc, int fail_id) if (rs->rs_transno > exp->exp_last_committed) { /* not committed already */ list_add_tail(&rs->rs_obd_list, - &exp->exp_uncommitted_replies); + &exp->exp_uncommitted_replies); } spin_unlock(&exp->exp_uncommitted_replies_lock); @@ -797,7 +797,7 @@ void ldlm_dump_export_locks(struct obd_export *exp) CERROR("dumping locks for export %p,ignore if the unmount doesn't hang\n", exp); list_for_each_entry(lock, &exp->exp_locks_list, - l_exp_refs_link) + l_exp_refs_link) LDLM_ERROR(lock, "lock:"); } spin_unlock(&exp->exp_locks_list_guard); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c index 7a34caf..55b7460 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c @@ -937,7 +937,7 @@ static void search_granted_lock(struct list_head *queue, /* go to next policy group within mode group */ tmp = policy_end->l_res_link.next; lock = list_entry(tmp, struct ldlm_lock, - l_res_link); + l_res_link); } /* loop over policy groups within the mode group */ /* insert point is last lock of the mode group, @@ -1116,7 +1116,7 @@ static struct ldlm_lock *search_queue(struct list_head *queue, * of bits. */ if (lock->l_resource->lr_type == LDLM_IBITS && - ((lock->l_policy_data.l_inodebits.bits & + ((lock->l_policy_data.l_inodebits.bits & policy->l_inodebits.bits) != policy->l_inodebits.bits)) continue; @@ -1376,12 +1376,12 @@ int ldlm_fill_lvb(struct ldlm_lock *lock, struct req_capsule *pill, if (size == sizeof(struct ost_lvb)) { if (loc == RCL_CLIENT) lvb = req_capsule_client_swab_get(pill, - &RMF_DLM_LVB, - lustre_swab_ost_lvb); + &RMF_DLM_LVB, + lustre_swab_ost_lvb); else lvb = req_capsule_server_swab_get(pill, - &RMF_DLM_LVB, - lustre_swab_ost_lvb); + &RMF_DLM_LVB, + lustre_swab_ost_lvb); if (unlikely(!lvb)) { LDLM_ERROR(lock, "no LVB"); return -EPROTO; @@ -1393,8 +1393,8 @@ int ldlm_fill_lvb(struct ldlm_lock *lock, struct req_capsule *pill, if (loc == RCL_CLIENT) lvb = req_capsule_client_swab_get(pill, - &RMF_DLM_LVB, - lustre_swab_ost_lvb_v1); + &RMF_DLM_LVB, + lustre_swab_ost_lvb_v1); else lvb = req_capsule_server_sized_swab_get(pill, &RMF_DLM_LVB, size, @@ -1418,12 +1418,12 @@ int ldlm_fill_lvb(struct ldlm_lock *lock, struct req_capsule *pill, if (size == sizeof(struct lquota_lvb)) { if (loc == RCL_CLIENT) lvb = req_capsule_client_swab_get(pill, - &RMF_DLM_LVB, - lustre_swab_lquota_lvb); + &RMF_DLM_LVB, + lustre_swab_lquota_lvb); else lvb = req_capsule_server_swab_get(pill, - &RMF_DLM_LVB, - lustre_swab_lquota_lvb); + &RMF_DLM_LVB, + lustre_swab_lquota_lvb); if (unlikely(!lvb)) { LDLM_ERROR(lock, "no LVB"); return -EPROTO; @@ -1709,7 +1709,7 @@ static int ldlm_work_gl_ast_lock(struct ptlrpc_request_set *rqset, void *opaq) return -ENOENT; gl_work = list_entry(arg->list->next, struct ldlm_glimpse_work, - gl_list); + gl_list); list_del_init(&gl_work->gl_list); lock = gl_work->gl_lock; diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c index 821939f..b91b26d 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c @@ -706,12 +706,12 @@ static struct ldlm_bl_work_item *ldlm_bl_get_work(struct ldlm_bl_pool *blp) if (!list_empty(&blp->blp_list) && (list_empty(&blp->blp_prio_list) || num_bl == 0)) blwi = list_entry(blp->blp_list.next, - struct ldlm_bl_work_item, blwi_entry); + struct ldlm_bl_work_item, blwi_entry); else if (!list_empty(&blp->blp_prio_list)) blwi = list_entry(blp->blp_prio_list.next, - struct ldlm_bl_work_item, - blwi_entry); + struct ldlm_bl_work_item, + blwi_entry); if (blwi) { if (++num_bl >= atomic_read(&blp->blp_num_threads)) @@ -741,7 +741,7 @@ static int ldlm_bl_thread_start(struct ldlm_bl_pool *blp) init_completion(&bltd.bltd_comp); bltd.bltd_num = atomic_read(&blp->blp_num_threads); snprintf(bltd.bltd_name, sizeof(bltd.bltd_name), - "ldlm_bl_%02d", bltd.bltd_num); + "ldlm_bl_%02d", bltd.bltd_num); task = kthread_run(ldlm_bl_thread_main, &bltd, "%s", bltd.bltd_name); if (IS_ERR(task)) { CERROR("cannot start LDLM thread ldlm_bl_%02d: rc %ld\n", @@ -786,8 +786,8 @@ static int ldlm_bl_thread_main(void *arg) if (!blwi) { atomic_dec(&blp->blp_busy_threads); l_wait_event_exclusive(blp->blp_waitq, - (blwi = ldlm_bl_get_work(blp)), - &lwi); + (blwi = ldlm_bl_get_work(blp)), + &lwi); busy = atomic_inc_return(&blp->blp_busy_threads); } else { busy = atomic_read(&blp->blp_busy_threads); @@ -1094,16 +1094,17 @@ int ldlm_init(void) return -ENOMEM; ldlm_lock_slab = kmem_cache_create("ldlm_locks", - sizeof(struct ldlm_lock), 0, - SLAB_HWCACHE_ALIGN | SLAB_DESTROY_BY_RCU, NULL); + sizeof(struct ldlm_lock), 0, + SLAB_HWCACHE_ALIGN | + SLAB_DESTROY_BY_RCU, NULL); if (!ldlm_lock_slab) { kmem_cache_destroy(ldlm_resource_slab); return -ENOMEM; } ldlm_interval_slab = kmem_cache_create("interval_node", - sizeof(struct ldlm_interval), - 0, SLAB_HWCACHE_ALIGN, NULL); + sizeof(struct ldlm_interval), + 0, SLAB_HWCACHE_ALIGN, NULL); if (!ldlm_interval_slab) { kmem_cache_destroy(ldlm_resource_slab); kmem_cache_destroy(ldlm_lock_slab); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c index 657ed40..2fc319e 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c @@ -995,7 +995,7 @@ static int ldlm_pools_thread_main(void *arg) wake_up(&thread->t_ctl_waitq); CDEBUG(D_DLMTRACE, "%s: pool thread starting, process %d\n", - "ldlm_poold", current_pid()); + "ldlm_poold", current_pid()); while (1) { struct l_wait_info lwi; @@ -1025,7 +1025,7 @@ static int ldlm_pools_thread_main(void *arg) wake_up(&thread->t_ctl_waitq); CDEBUG(D_DLMTRACE, "%s: pool thread exiting, process %d\n", - "ldlm_poold", current_pid()); + "ldlm_poold", current_pid()); complete_and_exit(&ldlm_pools_comp, 0); } diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index ce579a2..1dc8d21 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -1178,8 +1178,7 @@ static enum ldlm_policy_res ldlm_cancel_lrur_policy(struct ldlm_namespace *ns, slv = ldlm_pool_get_slv(pl); lvf = ldlm_pool_get_lvf(pl); - la = cfs_duration_sec(cfs_time_sub(cur, - lock->l_last_used)); + la = cfs_duration_sec(cfs_time_sub(cur, lock->l_last_used)); lv = lvf * la * unused; /* Inform pool about current CLV to see it via debugfs. */ @@ -1372,7 +1371,7 @@ static int ldlm_prepare_lru_list(struct ldlm_namespace *ns, break; list_for_each_entry_safe(lock, next, &ns->ns_unused_list, - l_lru) { + l_lru) { /* No locks which got blocking requests. */ LASSERT(!ldlm_is_bl_ast(lock)); @@ -1608,8 +1607,7 @@ int ldlm_cli_cancel_list(struct list_head *cancels, int count, */ while (count > 0) { LASSERT(!list_empty(cancels)); - lock = list_entry(cancels->next, struct ldlm_lock, - l_bl_ast); + lock = list_entry(cancels->next, struct ldlm_lock, l_bl_ast); LASSERT(lock->l_conn_export); if (exp_connect_cancelset(lock->l_conn_export)) { @@ -2008,7 +2006,7 @@ static void ldlm_cancel_unused_locks_for_replay(struct ldlm_namespace *ns) LCF_LOCAL, LDLM_CANCEL_NO_WAIT); CDEBUG(D_DLMTRACE, "Canceled %d unused locks from namespace %s\n", - canceled, ldlm_ns_name(ns)); + canceled, ldlm_ns_name(ns)); } int ldlm_replay_locks(struct obd_import *imp) diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c index c37a7b0..e2c2587 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c @@ -758,8 +758,7 @@ static void cleanup_resource(struct ldlm_resource *res, struct list_head *q, */ lock_res(res); list_for_each(tmp, q) { - lock = list_entry(tmp, struct ldlm_lock, - l_res_link); + lock = list_entry(tmp, struct ldlm_lock, l_res_link); if (ldlm_is_cleaned(lock)) { lock = NULL; continue; @@ -1381,7 +1380,7 @@ void ldlm_resource_dump(int level, struct ldlm_resource *res) if (!list_empty(&res->lr_granted)) { CDEBUG(level, "Granted locks (in reverse order):\n"); list_for_each_entry_reverse(lock, &res->lr_granted, - l_res_link) { + l_res_link) { LDLM_DEBUG_LIMIT(level, lock, "###"); if (!(level & D_CANTMASK) && ++granted > ldlm_dump_granted_max) { diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index b7f399e..72ff7c4 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -1357,8 +1357,8 @@ static int ll_setattr_done_writing(struct inode *inode, rc = ll_som_update(inode, op_data); else if (rc) { CERROR("%s: inode "DFID" mdc truncate failed: rc = %d\n", - ll_i2sbi(inode)->ll_md_exp->exp_obd->obd_name, - PFID(ll_inode2fid(inode)), rc); + ll_i2sbi(inode)->ll_md_exp->exp_obd->obd_name, + PFID(ll_inode2fid(inode)), rc); } return rc; } diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index f053f55..bb85d16 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -648,8 +648,8 @@ static void ras_update_stride_detector(struct ll_readahead_state *ras, { unsigned long stride_gap = index - ras->ras_last_readpage - 1; - if (!stride_io_mode(ras) && (stride_gap != 0 || - ras->ras_consecutive_stride_requests == 0)) { + if ((stride_gap != 0 || ras->ras_consecutive_stride_requests == 0) && + !stride_io_mode(ras)) { ras->ras_stride_pages = ras->ras_consecutive_pages; ras->ras_stride_length = ras->ras_consecutive_pages + stride_gap; diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c index dfd51af..4ac0d6a 100644 --- a/drivers/staging/lustre/lustre/llite/statahead.c +++ b/drivers/staging/lustre/lustre/llite/statahead.c @@ -918,7 +918,8 @@ static void ll_statahead_one(struct dentry *parent, const char *entry_name, if (rc) { rc1 = ll_sa_entry_to_stated(sai, entry, - rc < 0 ? SA_ENTRY_INVA : SA_ENTRY_SUCC); + rc < 0 ? SA_ENTRY_INVA : + SA_ENTRY_SUCC); if (rc1 == 0 && entry->se_index == sai->sai_index_wait) wake_up(&sai->sai_waitq); } else { diff --git a/drivers/staging/lustre/lustre/llite/vvp_page.c b/drivers/staging/lustre/lustre/llite/vvp_page.c index 2e566d9..2818a68 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_page.c +++ b/drivers/staging/lustre/lustre/llite/vvp_page.c @@ -249,7 +249,7 @@ static void vvp_vmpage_error(struct inode *inode, struct page *vmpage, int ioret set_bit(AS_EIO, &inode->i_mapping->flags); if ((ioret == -ESHUTDOWN || ioret == -EINTR) && - obj->vob_discard_page_warned == 0) { + obj->vob_discard_page_warned == 0) { obj->vob_discard_page_warned = 1; ll_dirty_page_discard_warn(vmpage, ioret); } @@ -549,7 +549,7 @@ static const struct cl_page_operations vvp_transient_page_ops = { }; int vvp_page_init(const struct lu_env *env, struct cl_object *obj, - struct cl_page *page, pgoff_t index) + struct cl_page *page, pgoff_t index) { struct vvp_page *vpg = cl_object_page_slice(obj, page); struct page *vmpage = page->cp_vmpage; diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index 1f8a0fc..2817f38 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -2162,8 +2162,8 @@ static int lov_set_info_async(const struct lu_env *env, struct obd_export *exp, &mgi->group, set); } else if (next_id) { err = obd_set_info_async(env, tgt->ltd_exp, - keylen, key, vallen, - ((struct obd_id_info *)val)->data, set); + keylen, key, vallen, + ((struct obd_id_info *)val)->data, set); } else { /* Only want a specific OSC */ if (check_uuid && diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index c234e35..f38339a 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -665,7 +665,8 @@ static int mdc_finish_enqueue(struct obd_export *exp, lvb_len = req_capsule_get_size(pill, &RMF_DLM_LVB, RCL_SERVER); if (lvb_len > 0) { lvb_data = req_capsule_server_sized_get(pill, - &RMF_DLM_LVB, lvb_len); + &RMF_DLM_LVB, + lvb_len); if (!lvb_data) return -EPROTO; } diff --git a/drivers/staging/lustre/lustre/obdclass/obd_mount.c b/drivers/staging/lustre/lustre/obdclass/obd_mount.c index 0c48257..ae702ce 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_mount.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_mount.c @@ -68,7 +68,7 @@ static void (*kill_super_cb)(struct super_block *sb); * this log, and is added to the mgc's list of logs to follow. */ int lustre_process_log(struct super_block *sb, char *logname, - struct config_llog_instance *cfg) + struct config_llog_instance *cfg) { struct lustre_cfg *lcfg; struct lustre_cfg_bufs *bufs; diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index ebcebe8..97f936e 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -958,8 +958,8 @@ static int osc_extent_wait(const struct lu_env *env, struct osc_extent *ext, rc = l_wait_event(ext->oe_waitq, extent_wait_cb(ext, state), &lwi); if (rc == -ETIMEDOUT) { OSC_EXTENT_DUMP(D_ERROR, ext, - "%s: wait ext to %d timedout, recovery in progress?\n", - osc_export(obj)->exp_obd->obd_name, state); + "%s: wait ext to %d timedout, recovery in progress?\n", + osc_export(obj)->exp_obd->obd_name, state); lwi = LWI_INTR(NULL, NULL); rc = l_wait_event(ext->oe_waitq, extent_wait_cb(ext, state), diff --git a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c index 11ec825..44f4eae 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c +++ b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c @@ -398,7 +398,8 @@ int ptlrpc_send_reply(struct ptlrpc_request *req, int flags) lustre_msg_set_status(req->rq_repmsg, ptlrpc_status_hton(req->rq_status)); lustre_msg_set_opc(req->rq_repmsg, - req->rq_reqmsg ? lustre_msg_get_opc(req->rq_reqmsg) : 0); + req->rq_reqmsg ? + lustre_msg_get_opc(req->rq_reqmsg) : 0); target_pack_pool_reply(req); diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index 9c03a9a..2cf3a51 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -1203,8 +1203,9 @@ __u32 lustre_msg_calc_cksum(struct lustre_msg *msg) unsigned int hsize = 4; cfs_crypto_hash_digest(CFS_HASH_ALG_CRC32, (unsigned char *)pb, - lustre_msg_buflen(msg, MSG_PTLRPC_BODY_OFF), - NULL, 0, (unsigned char *)&crc, &hsize); + lustre_msg_buflen(msg, + MSG_PTLRPC_BODY_OFF), + NULL, 0, (unsigned char *)&crc, &hsize); return crc; } default: diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c index bb00185..fdb32d5 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c @@ -523,8 +523,9 @@ int sptlrpc_get_bulk_checksum(struct ptlrpc_bulk_desc *desc, __u8 alg, for (i = 0; i < desc->bd_iov_count; i++) { cfs_crypto_hash_update_page(hdesc, desc->bd_iov[i].bv_page, - desc->bd_iov[i].bv_offset & ~PAGE_MASK, - desc->bd_iov[i].bv_len); + desc->bd_iov[i].bv_offset & + ~PAGE_MASK, + desc->bd_iov[i].bv_len); } if (hashsize > buflen) { diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c b/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c index 8322550..cd305bc 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c @@ -249,9 +249,12 @@ int plain_ctx_verify(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req) unsigned int hsize = 4; cfs_crypto_hash_digest(CFS_HASH_ALG_CRC32, - lustre_msg_buf(msg, PLAIN_PACK_MSG_OFF, 0), - lustre_msg_buflen(msg, PLAIN_PACK_MSG_OFF), - NULL, 0, (unsigned char *)&cksum, &hsize); + lustre_msg_buf(msg, PLAIN_PACK_MSG_OFF, + 0), + lustre_msg_buflen(msg, + PLAIN_PACK_MSG_OFF), + NULL, 0, (unsigned char *)&cksum, + &hsize); if (cksum != msg->lm_cksum) { CDEBUG(D_SEC, "early reply checksum mismatch: %08x != %08x\n", @@ -869,9 +872,12 @@ int plain_authorize(struct ptlrpc_request *req) unsigned int hsize = 4; cfs_crypto_hash_digest(CFS_HASH_ALG_CRC32, - lustre_msg_buf(msg, PLAIN_PACK_MSG_OFF, 0), - lustre_msg_buflen(msg, PLAIN_PACK_MSG_OFF), - NULL, 0, (unsigned char *)&msg->lm_cksum, &hsize); + lustre_msg_buf(msg, PLAIN_PACK_MSG_OFF, + 0), + lustre_msg_buflen(msg, + PLAIN_PACK_MSG_OFF), + NULL, 0, (unsigned char *)&msg->lm_cksum, + &hsize); req->rq_reply_off = 0; } diff --git a/drivers/staging/lustre/lustre/ptlrpc/service.c b/drivers/staging/lustre/lustre/ptlrpc/service.c index be3c96c..a2fce66 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/service.c +++ b/drivers/staging/lustre/lustre/ptlrpc/service.c @@ -1990,11 +1990,12 @@ ptlrpc_wait_event(struct ptlrpc_service_part *svcpt, cond_resched(); l_wait_event_exclusive_head(svcpt->scp_waitq, - ptlrpc_thread_stopping(thread) || - ptlrpc_server_request_incoming(svcpt) || - ptlrpc_server_request_pending(svcpt, false) || - ptlrpc_rqbd_pending(svcpt) || - ptlrpc_at_check(svcpt), &lwi); + ptlrpc_thread_stopping(thread) || + ptlrpc_server_request_incoming(svcpt) || + ptlrpc_server_request_pending(svcpt, + false) || + ptlrpc_rqbd_pending(svcpt) || + ptlrpc_at_check(svcpt), &lwi); if (ptlrpc_thread_stopping(thread)) return -EINTR; @@ -2357,7 +2358,7 @@ static void ptlrpc_svcpt_stop_threads(struct ptlrpc_service_part *svcpt) while (!list_empty(&zombie)) { thread = list_entry(zombie.next, - struct ptlrpc_thread, t_link); + struct ptlrpc_thread, t_link); list_del(&thread->t_link); kfree(thread); } @@ -2547,8 +2548,8 @@ int ptlrpc_hr_init(void) LASSERT(hrp->hrp_nthrs > 0); hrp->hrp_thrs = kzalloc_node(hrp->hrp_nthrs * sizeof(*hrt), GFP_NOFS, - cfs_cpt_spread_node(ptlrpc_hr.hr_cpt_table, - i)); + cfs_cpt_spread_node(ptlrpc_hr.hr_cpt_table, + i)); if (!hrp->hrp_thrs) { rc = -ENOMEM; goto out; @@ -2601,7 +2602,8 @@ static void ptlrpc_wait_replies(struct ptlrpc_service_part *svcpt) NULL, NULL); rc = l_wait_event(svcpt->scp_waitq, - atomic_read(&svcpt->scp_nreps_difficult) == 0, &lwi); + atomic_read(&svcpt->scp_nreps_difficult) == 0, + &lwi); if (rc == 0) break; CWARN("Unexpectedly long timeout %s %p\n", @@ -2647,7 +2649,7 @@ ptlrpc_service_unlink_rqbd(struct ptlrpc_service *svc) * event with its 'unlink' flag set for each posted rqbd */ list_for_each_entry(rqbd, &svcpt->scp_rqbd_posted, - rqbd_list) { + rqbd_list) { rc = LNetMDUnlink(rqbd->rqbd_md_h); LASSERT(rc == 0 || rc == -ENOENT); } diff --git a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c index 3748f71..eb6d88e 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c +++ b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c @@ -195,25 +195,25 @@ void lustre_assert_wire_constants(void) LASSERTF(REINT_MAX == 10, "found %lld\n", (long long)REINT_MAX); LASSERTF(DISP_IT_EXECD == 0x00000001UL, "found 0x%.8xUL\n", - (unsigned)DISP_IT_EXECD); + (unsigned)DISP_IT_EXECD); LASSERTF(DISP_LOOKUP_EXECD == 0x00000002UL, "found 0x%.8xUL\n", - (unsigned)DISP_LOOKUP_EXECD); + (unsigned)DISP_LOOKUP_EXECD); LASSERTF(DISP_LOOKUP_NEG == 0x00000004UL, "found 0x%.8xUL\n", - (unsigned)DISP_LOOKUP_NEG); + (unsigned)DISP_LOOKUP_NEG); LASSERTF(DISP_LOOKUP_POS == 0x00000008UL, "found 0x%.8xUL\n", - (unsigned)DISP_LOOKUP_POS); + (unsigned)DISP_LOOKUP_POS); LASSERTF(DISP_OPEN_CREATE == 0x00000010UL, "found 0x%.8xUL\n", - (unsigned)DISP_OPEN_CREATE); + (unsigned)DISP_OPEN_CREATE); LASSERTF(DISP_OPEN_OPEN == 0x00000020UL, "found 0x%.8xUL\n", - (unsigned)DISP_OPEN_OPEN); + (unsigned)DISP_OPEN_OPEN); LASSERTF(DISP_ENQ_COMPLETE == 0x00400000UL, "found 0x%.8xUL\n", - (unsigned)DISP_ENQ_COMPLETE); + (unsigned)DISP_ENQ_COMPLETE); LASSERTF(DISP_ENQ_OPEN_REF == 0x00800000UL, "found 0x%.8xUL\n", - (unsigned)DISP_ENQ_OPEN_REF); + (unsigned)DISP_ENQ_OPEN_REF); LASSERTF(DISP_ENQ_CREATE_REF == 0x01000000UL, "found 0x%.8xUL\n", - (unsigned)DISP_ENQ_CREATE_REF); + (unsigned)DISP_ENQ_CREATE_REF); LASSERTF(DISP_OPEN_LOCK == 0x02000000UL, "found 0x%.8xUL\n", - (unsigned)DISP_OPEN_LOCK); + (unsigned)DISP_OPEN_LOCK); LASSERTF(MDS_STATUS_CONN == 1, "found %lld\n", (long long)MDS_STATUS_CONN); LASSERTF(MDS_STATUS_LOV == 2, "found %lld\n", @@ -221,55 +221,55 @@ void lustre_assert_wire_constants(void) LASSERTF(LUSTRE_BFLAG_UNCOMMITTED_WRITES == 1, "found %lld\n", (long long)LUSTRE_BFLAG_UNCOMMITTED_WRITES); LASSERTF(MF_SOM_CHANGE == 0x00000001UL, "found 0x%.8xUL\n", - (unsigned)MF_SOM_CHANGE); + (unsigned)MF_SOM_CHANGE); LASSERTF(MF_EPOCH_OPEN == 0x00000002UL, "found 0x%.8xUL\n", - (unsigned)MF_EPOCH_OPEN); + (unsigned)MF_EPOCH_OPEN); LASSERTF(MF_EPOCH_CLOSE == 0x00000004UL, "found 0x%.8xUL\n", - (unsigned)MF_EPOCH_CLOSE); + (unsigned)MF_EPOCH_CLOSE); LASSERTF(MF_MDC_CANCEL_FID1 == 0x00000008UL, "found 0x%.8xUL\n", - (unsigned)MF_MDC_CANCEL_FID1); + (unsigned)MF_MDC_CANCEL_FID1); LASSERTF(MF_MDC_CANCEL_FID2 == 0x00000010UL, "found 0x%.8xUL\n", - (unsigned)MF_MDC_CANCEL_FID2); + (unsigned)MF_MDC_CANCEL_FID2); LASSERTF(MF_MDC_CANCEL_FID3 == 0x00000020UL, "found 0x%.8xUL\n", - (unsigned)MF_MDC_CANCEL_FID3); + (unsigned)MF_MDC_CANCEL_FID3); LASSERTF(MF_MDC_CANCEL_FID4 == 0x00000040UL, "found 0x%.8xUL\n", - (unsigned)MF_MDC_CANCEL_FID4); + (unsigned)MF_MDC_CANCEL_FID4); LASSERTF(MF_SOM_AU == 0x00000080UL, "found 0x%.8xUL\n", - (unsigned)MF_SOM_AU); + (unsigned)MF_SOM_AU); LASSERTF(MF_GETATTR_LOCK == 0x00000100UL, "found 0x%.8xUL\n", - (unsigned)MF_GETATTR_LOCK); + (unsigned)MF_GETATTR_LOCK); LASSERTF(MDS_ATTR_MODE == 0x0000000000000001ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_MODE); + (long long)MDS_ATTR_MODE); LASSERTF(MDS_ATTR_UID == 0x0000000000000002ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_UID); + (long long)MDS_ATTR_UID); LASSERTF(MDS_ATTR_GID == 0x0000000000000004ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_GID); + (long long)MDS_ATTR_GID); LASSERTF(MDS_ATTR_SIZE == 0x0000000000000008ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_SIZE); + (long long)MDS_ATTR_SIZE); LASSERTF(MDS_ATTR_ATIME == 0x0000000000000010ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_ATIME); + (long long)MDS_ATTR_ATIME); LASSERTF(MDS_ATTR_MTIME == 0x0000000000000020ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_MTIME); + (long long)MDS_ATTR_MTIME); LASSERTF(MDS_ATTR_CTIME == 0x0000000000000040ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_CTIME); + (long long)MDS_ATTR_CTIME); LASSERTF(MDS_ATTR_ATIME_SET == 0x0000000000000080ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_ATIME_SET); + (long long)MDS_ATTR_ATIME_SET); LASSERTF(MDS_ATTR_MTIME_SET == 0x0000000000000100ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_MTIME_SET); + (long long)MDS_ATTR_MTIME_SET); LASSERTF(MDS_ATTR_FORCE == 0x0000000000000200ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_FORCE); + (long long)MDS_ATTR_FORCE); LASSERTF(MDS_ATTR_ATTR_FLAG == 0x0000000000000400ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_ATTR_FLAG); + (long long)MDS_ATTR_ATTR_FLAG); LASSERTF(MDS_ATTR_KILL_SUID == 0x0000000000000800ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_KILL_SUID); + (long long)MDS_ATTR_KILL_SUID); LASSERTF(MDS_ATTR_KILL_SGID == 0x0000000000001000ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_KILL_SGID); + (long long)MDS_ATTR_KILL_SGID); LASSERTF(MDS_ATTR_CTIME_SET == 0x0000000000002000ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_CTIME_SET); + (long long)MDS_ATTR_CTIME_SET); LASSERTF(MDS_ATTR_FROM_OPEN == 0x0000000000004000ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_FROM_OPEN); + (long long)MDS_ATTR_FROM_OPEN); LASSERTF(MDS_ATTR_BLOCKS == 0x0000000000008000ULL, "found 0x%.16llxULL\n", - (long long)MDS_ATTR_BLOCKS); + (long long)MDS_ATTR_BLOCKS); LASSERTF(FLD_QUERY == 900, "found %lld\n", (long long)FLD_QUERY); LASSERTF(FLD_FIRST_OPC == 900, "found %lld\n", @@ -420,15 +420,15 @@ void lustre_assert_wire_constants(void) LASSERTF((int)sizeof(((struct lustre_mdt_attrs *)0)->lma_self_fid) == 16, "found %lld\n", (long long)(int)sizeof(((struct lustre_mdt_attrs *)0)->lma_self_fid)); LASSERTF(LMAI_RELEASED == 0x00000001UL, "found 0x%.8xUL\n", - (unsigned)LMAI_RELEASED); + (unsigned)LMAI_RELEASED); LASSERTF(LMAC_HSM == 0x00000001UL, "found 0x%.8xUL\n", - (unsigned)LMAC_HSM); + (unsigned)LMAC_HSM); LASSERTF(LMAC_SOM == 0x00000002UL, "found 0x%.8xUL\n", - (unsigned)LMAC_SOM); + (unsigned)LMAC_SOM); LASSERTF(LMAC_NOT_IN_OI == 0x00000004UL, "found 0x%.8xUL\n", - (unsigned)LMAC_NOT_IN_OI); + (unsigned)LMAC_NOT_IN_OI); LASSERTF(LMAC_FID_ON_OST == 0x00000008UL, "found 0x%.8xUL\n", - (unsigned)LMAC_FID_ON_OST); + (unsigned)LMAC_FID_ON_OST); /* Checks for struct ost_id */ LASSERTF((int)sizeof(struct ost_id) == 16, "found %lld\n", @@ -454,35 +454,35 @@ void lustre_assert_wire_constants(void) LASSERTF(FID_SEQ_IGIF == 12, "found %lld\n", (long long)FID_SEQ_IGIF); LASSERTF(FID_SEQ_IGIF_MAX == 0x00000000ffffffffULL, "found 0x%.16llxULL\n", - (long long)FID_SEQ_IGIF_MAX); + (long long)FID_SEQ_IGIF_MAX); LASSERTF(FID_SEQ_IDIF == 0x0000000100000000ULL, "found 0x%.16llxULL\n", - (long long)FID_SEQ_IDIF); + (long long)FID_SEQ_IDIF); LASSERTF(FID_SEQ_IDIF_MAX == 0x00000001ffffffffULL, "found 0x%.16llxULL\n", - (long long)FID_SEQ_IDIF_MAX); + (long long)FID_SEQ_IDIF_MAX); LASSERTF(FID_SEQ_START == 0x0000000200000000ULL, "found 0x%.16llxULL\n", - (long long)FID_SEQ_START); + (long long)FID_SEQ_START); LASSERTF(FID_SEQ_LOCAL_FILE == 0x0000000200000001ULL, "found 0x%.16llxULL\n", - (long long)FID_SEQ_LOCAL_FILE); + (long long)FID_SEQ_LOCAL_FILE); LASSERTF(FID_SEQ_DOT_LUSTRE == 0x0000000200000002ULL, "found 0x%.16llxULL\n", - (long long)FID_SEQ_DOT_LUSTRE); + (long long)FID_SEQ_DOT_LUSTRE); LASSERTF(FID_SEQ_SPECIAL == 0x0000000200000004ULL, "found 0x%.16llxULL\n", - (long long)FID_SEQ_SPECIAL); + (long long)FID_SEQ_SPECIAL); LASSERTF(FID_SEQ_QUOTA == 0x0000000200000005ULL, "found 0x%.16llxULL\n", - (long long)FID_SEQ_QUOTA); + (long long)FID_SEQ_QUOTA); LASSERTF(FID_SEQ_QUOTA_GLB == 0x0000000200000006ULL, "found 0x%.16llxULL\n", - (long long)FID_SEQ_QUOTA_GLB); + (long long)FID_SEQ_QUOTA_GLB); LASSERTF(FID_SEQ_ROOT == 0x0000000200000007ULL, "found 0x%.16llxULL\n", - (long long)FID_SEQ_ROOT); + (long long)FID_SEQ_ROOT); LASSERTF(FID_SEQ_NORMAL == 0x0000000200000400ULL, "found 0x%.16llxULL\n", - (long long)FID_SEQ_NORMAL); + (long long)FID_SEQ_NORMAL); LASSERTF(FID_SEQ_LOV_DEFAULT == 0xffffffffffffffffULL, "found 0x%.16llxULL\n", - (long long)FID_SEQ_LOV_DEFAULT); + (long long)FID_SEQ_LOV_DEFAULT); LASSERTF(FID_OID_SPECIAL_BFL == 0x00000001UL, "found 0x%.8xUL\n", - (unsigned)FID_OID_SPECIAL_BFL); + (unsigned)FID_OID_SPECIAL_BFL); LASSERTF(FID_OID_DOT_LUSTRE == 0x00000001UL, "found 0x%.8xUL\n", - (unsigned)FID_OID_DOT_LUSTRE); + (unsigned)FID_OID_DOT_LUSTRE); LASSERTF(FID_OID_DOT_LUSTRE_OBF == 0x00000002UL, "found 0x%.8xUL\n", - (unsigned)FID_OID_DOT_LUSTRE_OBF); + (unsigned)FID_OID_DOT_LUSTRE_OBF); /* Checks for struct lu_dirent */ LASSERTF((int)sizeof(struct lu_dirent) == 32, "found %lld\n", @@ -512,11 +512,11 @@ void lustre_assert_wire_constants(void) LASSERTF((int)sizeof(((struct lu_dirent *)0)->lde_name[0]) == 1, "found %lld\n", (long long)(int)sizeof(((struct lu_dirent *)0)->lde_name[0])); LASSERTF(LUDA_FID == 0x00000001UL, "found 0x%.8xUL\n", - (unsigned)LUDA_FID); + (unsigned)LUDA_FID); LASSERTF(LUDA_TYPE == 0x00000002UL, "found 0x%.8xUL\n", - (unsigned)LUDA_TYPE); + (unsigned)LUDA_TYPE); LASSERTF(LUDA_64BITHASH == 0x00000004UL, "found 0x%.8xUL\n", - (unsigned)LUDA_64BITHASH); + (unsigned)LUDA_64BITHASH); /* Checks for struct luda_type */ LASSERTF((int)sizeof(struct luda_type) == 2, "found %lld\n", @@ -604,9 +604,9 @@ void lustre_assert_wire_constants(void) LASSERTF((int)sizeof(((struct lustre_msg_v2 *)0)->lm_buflens[0]) == 4, "found %lld\n", (long long)(int)sizeof(((struct lustre_msg_v2 *)0)->lm_buflens[0])); LASSERTF(LUSTRE_MSG_MAGIC_V2 == 0x0BD00BD3, "found 0x%.8x\n", - LUSTRE_MSG_MAGIC_V2); + LUSTRE_MSG_MAGIC_V2); LASSERTF(LUSTRE_MSG_MAGIC_V2_SWABBED == 0xD30BD00B, "found 0x%.8x\n", - LUSTRE_MSG_MAGIC_V2_SWABBED); + LUSTRE_MSG_MAGIC_V2_SWABBED); /* Checks for struct ptlrpc_body */ LASSERTF((int)sizeof(struct ptlrpc_body_v3) == 184, "found %lld\n", @@ -782,61 +782,61 @@ void lustre_assert_wire_constants(void) LASSERTF(MSG_PTLRPC_HEADER_OFF == 31, "found %lld\n", (long long)MSG_PTLRPC_HEADER_OFF); LASSERTF(PTLRPC_MSG_VERSION == 0x00000003, "found 0x%.8x\n", - PTLRPC_MSG_VERSION); + PTLRPC_MSG_VERSION); LASSERTF(LUSTRE_VERSION_MASK == 0xffff0000, "found 0x%.8x\n", - LUSTRE_VERSION_MASK); + LUSTRE_VERSION_MASK); LASSERTF(LUSTRE_OBD_VERSION == 0x00010000, "found 0x%.8x\n", - LUSTRE_OBD_VERSION); + LUSTRE_OBD_VERSION); LASSERTF(LUSTRE_MDS_VERSION == 0x00020000, "found 0x%.8x\n", - LUSTRE_MDS_VERSION); + LUSTRE_MDS_VERSION); LASSERTF(LUSTRE_OST_VERSION == 0x00030000, "found 0x%.8x\n", - LUSTRE_OST_VERSION); + LUSTRE_OST_VERSION); LASSERTF(LUSTRE_DLM_VERSION == 0x00040000, "found 0x%.8x\n", - LUSTRE_DLM_VERSION); + LUSTRE_DLM_VERSION); LASSERTF(LUSTRE_LOG_VERSION == 0x00050000, "found 0x%.8x\n", - LUSTRE_LOG_VERSION); + LUSTRE_LOG_VERSION); LASSERTF(LUSTRE_MGS_VERSION == 0x00060000, "found 0x%.8x\n", - LUSTRE_MGS_VERSION); + LUSTRE_MGS_VERSION); LASSERTF(MSGHDR_AT_SUPPORT == 1, "found %lld\n", (long long)MSGHDR_AT_SUPPORT); LASSERTF(MSGHDR_CKSUM_INCOMPAT18 == 2, "found %lld\n", (long long)MSGHDR_CKSUM_INCOMPAT18); LASSERTF(MSG_OP_FLAG_MASK == 0xffff0000UL, "found 0x%.8xUL\n", - (unsigned)MSG_OP_FLAG_MASK); + (unsigned)MSG_OP_FLAG_MASK); LASSERTF(MSG_OP_FLAG_SHIFT == 16, "found %lld\n", (long long)MSG_OP_FLAG_SHIFT); LASSERTF(MSG_GEN_FLAG_MASK == 0x0000ffffUL, "found 0x%.8xUL\n", - (unsigned)MSG_GEN_FLAG_MASK); + (unsigned)MSG_GEN_FLAG_MASK); LASSERTF(MSG_LAST_REPLAY == 0x00000001UL, "found 0x%.8xUL\n", - (unsigned)MSG_LAST_REPLAY); + (unsigned)MSG_LAST_REPLAY); LASSERTF(MSG_RESENT == 0x00000002UL, "found 0x%.8xUL\n", - (unsigned)MSG_RESENT); + (unsigned)MSG_RESENT); LASSERTF(MSG_REPLAY == 0x00000004UL, "found 0x%.8xUL\n", - (unsigned)MSG_REPLAY); + (unsigned)MSG_REPLAY); LASSERTF(MSG_DELAY_REPLAY == 0x00000010UL, "found 0x%.8xUL\n", - (unsigned)MSG_DELAY_REPLAY); + (unsigned)MSG_DELAY_REPLAY); LASSERTF(MSG_VERSION_REPLAY == 0x00000020UL, "found 0x%.8xUL\n", - (unsigned)MSG_VERSION_REPLAY); + (unsigned)MSG_VERSION_REPLAY); LASSERTF(MSG_REQ_REPLAY_DONE == 0x00000040UL, "found 0x%.8xUL\n", - (unsigned)MSG_REQ_REPLAY_DONE); + (unsigned)MSG_REQ_REPLAY_DONE); LASSERTF(MSG_LOCK_REPLAY_DONE == 0x00000080UL, "found 0x%.8xUL\n", - (unsigned)MSG_LOCK_REPLAY_DONE); + (unsigned)MSG_LOCK_REPLAY_DONE); LASSERTF(MSG_CONNECT_RECOVERING == 0x00000001UL, "found 0x%.8xUL\n", - (unsigned)MSG_CONNECT_RECOVERING); + (unsigned)MSG_CONNECT_RECOVERING); LASSERTF(MSG_CONNECT_RECONNECT == 0x00000002UL, "found 0x%.8xUL\n", - (unsigned)MSG_CONNECT_RECONNECT); + (unsigned)MSG_CONNECT_RECONNECT); LASSERTF(MSG_CONNECT_REPLAYABLE == 0x00000004UL, "found 0x%.8xUL\n", - (unsigned)MSG_CONNECT_REPLAYABLE); + (unsigned)MSG_CONNECT_REPLAYABLE); LASSERTF(MSG_CONNECT_LIBCLIENT == 0x00000010UL, "found 0x%.8xUL\n", - (unsigned)MSG_CONNECT_LIBCLIENT); + (unsigned)MSG_CONNECT_LIBCLIENT); LASSERTF(MSG_CONNECT_INITIAL == 0x00000020UL, "found 0x%.8xUL\n", - (unsigned)MSG_CONNECT_INITIAL); + (unsigned)MSG_CONNECT_INITIAL); LASSERTF(MSG_CONNECT_ASYNC == 0x00000040UL, "found 0x%.8xUL\n", - (unsigned)MSG_CONNECT_ASYNC); + (unsigned)MSG_CONNECT_ASYNC); LASSERTF(MSG_CONNECT_NEXT_VER == 0x00000080UL, "found 0x%.8xUL\n", - (unsigned)MSG_CONNECT_NEXT_VER); + (unsigned)MSG_CONNECT_NEXT_VER); LASSERTF(MSG_CONNECT_TRANSNO == 0x00000100UL, "found 0x%.8xUL\n", - (unsigned)MSG_CONNECT_TRANSNO); + (unsigned)MSG_CONNECT_TRANSNO); /* Checks for struct obd_connect_data */ LASSERTF((int)sizeof(struct obd_connect_data) == 192, "found %lld\n", @@ -1078,11 +1078,11 @@ void lustre_assert_wire_constants(void) LASSERTF(OBD_CONNECT_DIR_STRIPE == 0x400000000000000ULL, "found 0x%.16llxULL\n", OBD_CONNECT_DIR_STRIPE); LASSERTF(OBD_CKSUM_CRC32 == 0x00000001UL, "found 0x%.8xUL\n", - (unsigned)OBD_CKSUM_CRC32); + (unsigned)OBD_CKSUM_CRC32); LASSERTF(OBD_CKSUM_ADLER == 0x00000002UL, "found 0x%.8xUL\n", - (unsigned)OBD_CKSUM_ADLER); + (unsigned)OBD_CKSUM_ADLER); LASSERTF(OBD_CKSUM_CRC32C == 0x00000004UL, "found 0x%.8xUL\n", - (unsigned)OBD_CKSUM_CRC32C); + (unsigned)OBD_CKSUM_CRC32C); /* Checks for struct obdo */ LASSERTF((int)sizeof(struct obdo) == 208, "found %lld\n", @@ -1394,13 +1394,13 @@ void lustre_assert_wire_constants(void) (long long)(int)sizeof(((struct lov_mds_md_v3 *)0)->lmm_objects[0])); CLASSERT(LOV_MAGIC_V3 == (0x0BD30000 | 0x0BD0)); LASSERTF(LOV_PATTERN_RAID0 == 0x00000001UL, "found 0x%.8xUL\n", - (unsigned)LOV_PATTERN_RAID0); + (unsigned)LOV_PATTERN_RAID0); LASSERTF(LOV_PATTERN_RAID1 == 0x00000002UL, "found 0x%.8xUL\n", - (unsigned)LOV_PATTERN_RAID1); + (unsigned)LOV_PATTERN_RAID1); LASSERTF(LOV_PATTERN_FIRST == 0x00000100UL, "found 0x%.8xUL\n", - (unsigned)LOV_PATTERN_FIRST); + (unsigned)LOV_PATTERN_FIRST); LASSERTF(LOV_PATTERN_CMOBD == 0x00000200UL, "found 0x%.8xUL\n", - (unsigned)LOV_PATTERN_CMOBD); + (unsigned)LOV_PATTERN_CMOBD); /* Checks for struct lmv_mds_md_v1 */ LASSERTF((int)sizeof(struct lmv_mds_md_v1) == 56, "found %lld\n", @@ -1639,15 +1639,15 @@ void lustre_assert_wire_constants(void) LASSERTF((int)sizeof(((struct obd_dqblk *)0)->dqb_padding) == 4, "found %lld\n", (long long)(int)sizeof(((struct obd_dqblk *)0)->dqb_padding)); LASSERTF(Q_QUOTACHECK == 0x800100, "found 0x%.8x\n", - Q_QUOTACHECK); + Q_QUOTACHECK); LASSERTF(Q_INITQUOTA == 0x800101, "found 0x%.8x\n", - Q_INITQUOTA); + Q_INITQUOTA); LASSERTF(Q_GETOINFO == 0x800102, "found 0x%.8x\n", - Q_GETOINFO); + Q_GETOINFO); LASSERTF(Q_GETOQUOTA == 0x800103, "found 0x%.8x\n", - Q_GETOQUOTA); + Q_GETOQUOTA); LASSERTF(Q_FINVALIDATE == 0x800104, "found 0x%.8x\n", - Q_FINVALIDATE); + Q_FINVALIDATE); /* Checks for struct niobuf_remote */ LASSERTF((int)sizeof(struct niobuf_remote) == 16, "found %lld\n", @@ -1665,27 +1665,27 @@ void lustre_assert_wire_constants(void) LASSERTF((int)sizeof(((struct niobuf_remote *)0)->flags) == 4, "found %lld\n", (long long)(int)sizeof(((struct niobuf_remote *)0)->flags)); LASSERTF(OBD_BRW_READ == 0x01, "found 0x%.8x\n", - OBD_BRW_READ); + OBD_BRW_READ); LASSERTF(OBD_BRW_WRITE == 0x02, "found 0x%.8x\n", - OBD_BRW_WRITE); + OBD_BRW_WRITE); LASSERTF(OBD_BRW_SYNC == 0x08, "found 0x%.8x\n", - OBD_BRW_SYNC); + OBD_BRW_SYNC); LASSERTF(OBD_BRW_CHECK == 0x10, "found 0x%.8x\n", - OBD_BRW_CHECK); + OBD_BRW_CHECK); LASSERTF(OBD_BRW_FROM_GRANT == 0x20, "found 0x%.8x\n", - OBD_BRW_FROM_GRANT); + OBD_BRW_FROM_GRANT); LASSERTF(OBD_BRW_GRANTED == 0x40, "found 0x%.8x\n", - OBD_BRW_GRANTED); + OBD_BRW_GRANTED); LASSERTF(OBD_BRW_NOCACHE == 0x80, "found 0x%.8x\n", - OBD_BRW_NOCACHE); + OBD_BRW_NOCACHE); LASSERTF(OBD_BRW_NOQUOTA == 0x100, "found 0x%.8x\n", - OBD_BRW_NOQUOTA); + OBD_BRW_NOQUOTA); LASSERTF(OBD_BRW_SRVLOCK == 0x200, "found 0x%.8x\n", - OBD_BRW_SRVLOCK); + OBD_BRW_SRVLOCK); LASSERTF(OBD_BRW_ASYNC == 0x400, "found 0x%.8x\n", - OBD_BRW_ASYNC); + OBD_BRW_ASYNC); LASSERTF(OBD_BRW_MEMALLOC == 0x800, "found 0x%.8x\n", - OBD_BRW_MEMALLOC); + OBD_BRW_MEMALLOC); LASSERTF(OBD_BRW_OVER_USRQUOTA == 0x1000, "found 0x%.8x\n", OBD_BRW_OVER_USRQUOTA); LASSERTF(OBD_BRW_OVER_GRPQUOTA == 0x2000, "found 0x%.8x\n", @@ -1854,69 +1854,69 @@ void lustre_assert_wire_constants(void) LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_padding_10) == 8, "found %lld\n", (long long)(int)sizeof(((struct mdt_body *)0)->mbo_padding_10)); LASSERTF(MDS_FMODE_CLOSED == 000000000000UL, "found 0%.11oUL\n", - MDS_FMODE_CLOSED); + MDS_FMODE_CLOSED); LASSERTF(MDS_FMODE_EXEC == 000000000004UL, "found 0%.11oUL\n", - MDS_FMODE_EXEC); + MDS_FMODE_EXEC); LASSERTF(MDS_FMODE_EPOCH == 000001000000UL, "found 0%.11oUL\n", - MDS_FMODE_EPOCH); + MDS_FMODE_EPOCH); LASSERTF(MDS_FMODE_TRUNC == 000002000000UL, "found 0%.11oUL\n", - MDS_FMODE_TRUNC); + MDS_FMODE_TRUNC); LASSERTF(MDS_FMODE_SOM == 000004000000UL, "found 0%.11oUL\n", - MDS_FMODE_SOM); + MDS_FMODE_SOM); LASSERTF(MDS_OPEN_CREATED == 000000000010UL, "found 0%.11oUL\n", - MDS_OPEN_CREATED); + MDS_OPEN_CREATED); LASSERTF(MDS_OPEN_CROSS == 000000000020UL, "found 0%.11oUL\n", - MDS_OPEN_CROSS); + MDS_OPEN_CROSS); LASSERTF(MDS_OPEN_CREAT == 000000000100UL, "found 0%.11oUL\n", - MDS_OPEN_CREAT); + MDS_OPEN_CREAT); LASSERTF(MDS_OPEN_EXCL == 000000000200UL, "found 0%.11oUL\n", - MDS_OPEN_EXCL); + MDS_OPEN_EXCL); LASSERTF(MDS_OPEN_TRUNC == 000000001000UL, "found 0%.11oUL\n", - MDS_OPEN_TRUNC); + MDS_OPEN_TRUNC); LASSERTF(MDS_OPEN_APPEND == 000000002000UL, "found 0%.11oUL\n", - MDS_OPEN_APPEND); + MDS_OPEN_APPEND); LASSERTF(MDS_OPEN_SYNC == 000000010000UL, "found 0%.11oUL\n", - MDS_OPEN_SYNC); + MDS_OPEN_SYNC); LASSERTF(MDS_OPEN_DIRECTORY == 000000200000UL, "found 0%.11oUL\n", - MDS_OPEN_DIRECTORY); + MDS_OPEN_DIRECTORY); LASSERTF(MDS_OPEN_BY_FID == 000040000000UL, "found 0%.11oUL\n", - MDS_OPEN_BY_FID); + MDS_OPEN_BY_FID); LASSERTF(MDS_OPEN_DELAY_CREATE == 000100000000UL, "found 0%.11oUL\n", - MDS_OPEN_DELAY_CREATE); + MDS_OPEN_DELAY_CREATE); LASSERTF(MDS_OPEN_OWNEROVERRIDE == 000200000000UL, "found 0%.11oUL\n", - MDS_OPEN_OWNEROVERRIDE); + MDS_OPEN_OWNEROVERRIDE); LASSERTF(MDS_OPEN_JOIN_FILE == 000400000000UL, "found 0%.11oUL\n", - MDS_OPEN_JOIN_FILE); + MDS_OPEN_JOIN_FILE); LASSERTF(MDS_OPEN_LOCK == 004000000000UL, "found 0%.11oUL\n", - MDS_OPEN_LOCK); + MDS_OPEN_LOCK); LASSERTF(MDS_OPEN_HAS_EA == 010000000000UL, "found 0%.11oUL\n", - MDS_OPEN_HAS_EA); + MDS_OPEN_HAS_EA); LASSERTF(MDS_OPEN_HAS_OBJS == 020000000000UL, "found 0%.11oUL\n", - MDS_OPEN_HAS_OBJS); + MDS_OPEN_HAS_OBJS); LASSERTF(MDS_OPEN_NORESTORE == 00000000000100000000000ULL, "found 0%.22lloULL\n", - (long long)MDS_OPEN_NORESTORE); + (long long)MDS_OPEN_NORESTORE); LASSERTF(MDS_OPEN_NEWSTRIPE == 00000000000200000000000ULL, "found 0%.22lloULL\n", - (long long)MDS_OPEN_NEWSTRIPE); + (long long)MDS_OPEN_NEWSTRIPE); LASSERTF(MDS_OPEN_VOLATILE == 00000000000400000000000ULL, "found 0%.22lloULL\n", - (long long)MDS_OPEN_VOLATILE); + (long long)MDS_OPEN_VOLATILE); LASSERTF(LUSTRE_SYNC_FL == 0x00000008, "found 0x%.8x\n", - LUSTRE_SYNC_FL); + LUSTRE_SYNC_FL); LASSERTF(LUSTRE_IMMUTABLE_FL == 0x00000010, "found 0x%.8x\n", - LUSTRE_IMMUTABLE_FL); + LUSTRE_IMMUTABLE_FL); LASSERTF(LUSTRE_APPEND_FL == 0x00000020, "found 0x%.8x\n", - LUSTRE_APPEND_FL); + LUSTRE_APPEND_FL); LASSERTF(LUSTRE_NOATIME_FL == 0x00000080, "found 0x%.8x\n", - LUSTRE_NOATIME_FL); + LUSTRE_NOATIME_FL); LASSERTF(LUSTRE_DIRSYNC_FL == 0x00010000, "found 0x%.8x\n", - LUSTRE_DIRSYNC_FL); + LUSTRE_DIRSYNC_FL); LASSERTF(MDS_INODELOCK_LOOKUP == 0x000001, "found 0x%.8x\n", - MDS_INODELOCK_LOOKUP); + MDS_INODELOCK_LOOKUP); LASSERTF(MDS_INODELOCK_UPDATE == 0x000002, "found 0x%.8x\n", - MDS_INODELOCK_UPDATE); + MDS_INODELOCK_UPDATE); LASSERTF(MDS_INODELOCK_OPEN == 0x000004, "found 0x%.8x\n", - MDS_INODELOCK_OPEN); + MDS_INODELOCK_OPEN); LASSERTF(MDS_INODELOCK_LAYOUT == 0x000008, "found 0x%.8x\n", - MDS_INODELOCK_LAYOUT); + MDS_INODELOCK_LAYOUT); /* Checks for struct mdt_ioepoch */ LASSERTF((int)sizeof(struct mdt_ioepoch) == 24, "found %lld\n", @@ -3984,9 +3984,9 @@ void lustre_assert_wire_constants(void) LASSERTF((int)sizeof(((struct hsm_progress *)0)->padding) == 4, "found %lld\n", (long long)(int)sizeof(((struct hsm_progress *)0)->padding)); LASSERTF(HP_FLAG_COMPLETED == 0x01, "found 0x%.8x\n", - HP_FLAG_COMPLETED); + HP_FLAG_COMPLETED); LASSERTF(HP_FLAG_RETRY == 0x02, "found 0x%.8x\n", - HP_FLAG_RETRY); + HP_FLAG_RETRY); LASSERTF((int)offsetof(struct hsm_copy, hc_data_version) == 0, "found %lld\n", (long long)(int)offsetof(struct hsm_copy, hc_data_version)); @@ -4141,9 +4141,9 @@ void lustre_assert_wire_constants(void) LASSERTF((int)sizeof(((struct hsm_request *)0)->hr_data_len) == 4, "found %lld\n", (long long)(int)sizeof(((struct hsm_request *)0)->hr_data_len)); LASSERTF(HSM_FORCE_ACTION == 0x00000001UL, "found 0x%.8xUL\n", - (unsigned)HSM_FORCE_ACTION); + (unsigned)HSM_FORCE_ACTION); LASSERTF(HSM_GHOST_COPY == 0x00000002UL, "found 0x%.8xUL\n", - (unsigned)HSM_GHOST_COPY); + (unsigned)HSM_GHOST_COPY); /* Checks for struct hsm_user_request */ LASSERTF((int)sizeof(struct hsm_user_request) == 24, "found %lld\n", -- cgit v0.10.2 From f5a9a15f8fd4168e415e94f5dce367f3cef08e03 Mon Sep 17 00:00:00 2001 From: Oleg Drokin <green@linuxhacker.ru> Date: Sun, 21 Aug 2016 18:04:36 -0400 Subject: staging/lustre: Remove unused cp_error from struct cl_page cp_error member is not really set anywhere, so kill it and the only printing user of it too. Signed-off-by: Oleg Drokin <green@linuxhacker.ru> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index 4c00be2..5e63a27 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -701,8 +701,6 @@ enum cl_page_type { struct cl_page { /** Reference counter. */ atomic_t cp_ref; - /** Transfer error. */ - int cp_error; /** An object this page is a part of. Immutable after creation. */ struct cl_object *cp_obj; /** vmpage */ diff --git a/drivers/staging/lustre/lustre/obdclass/cl_page.c b/drivers/staging/lustre/lustre/obdclass/cl_page.c index bd71859..80c6e0e 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_page.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_page.c @@ -981,9 +981,9 @@ void cl_page_header_print(const struct lu_env *env, void *cookie, lu_printer_t printer, const struct cl_page *pg) { (*printer)(env, cookie, - "page@%p[%d %p %d %d %d %p %p]\n", + "page@%p[%d %p %d %d %p %p]\n", pg, atomic_read(&pg->cp_ref), pg->cp_obj, - pg->cp_state, pg->cp_error, pg->cp_type, + pg->cp_state, pg->cp_type, pg->cp_owner, pg->cp_req); } EXPORT_SYMBOL(cl_page_header_print); -- cgit v0.10.2 From 88b090e3c020bfeac13d5c52984a03775808cb67 Mon Sep 17 00:00:00 2001 From: James Simmons <jsimmons@infradead.org> Date: Mon, 22 Aug 2016 12:57:43 -0400 Subject: staging: lustre: mdc: fix NULL pointer dereference in mdc_adjust_dirpages The function mdc_adjust_dirpages is only called on platforms which don't have pages 4K in size which is why kbuild only reported this for platforms like the Alpha. The problem was a typo in ordering of variables in the beginning of a while loop. We were accessing the dp pointer before it was kmapped. Signed-off-by: James Simmons <jsimmons@infradead.org> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 88848d8..7a182be 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -1133,9 +1133,9 @@ static void mdc_adjust_dirpages(struct page **pages, int cfs_pgs, int lu_pgs) int i; for (i = 0; i < cfs_pgs; i++) { + struct lu_dirpage *dp = kmap(pages[i]); __u64 hash_end = le64_to_cpu(dp->ldp_hash_end); __u32 flags = le32_to_cpu(dp->ldp_flags); - struct lu_dirpage *dp = kmap(pages[i]); struct lu_dirpage *first = dp; struct lu_dirent *end_dirent = NULL; struct lu_dirent *ent; -- cgit v0.10.2 From 1d9e3a07cb80ca7c8f4efcfcc6c4ca10790d9645 Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Mon, 22 Aug 2016 16:46:24 +0200 Subject: staging: most: aim-cdev: destroy ida struct in case of exception This patch is needed to clean up the initialized ida structure in case the function exits with an exception. Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index db6f458..1c20ae6 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -509,7 +509,7 @@ static int __init mod_init(void) err = alloc_chrdev_region(&aim_devno, 0, 50, "cdev"); if (err < 0) - return err; + goto dest_ida; major = MAJOR(aim_devno); aim_class = class_create(THIS_MODULE, "most_cdev_aim"); @@ -527,6 +527,8 @@ dest_class: class_destroy(aim_class); free_cdev: unregister_chrdev_region(aim_devno, 1); +dest_ida: + ida_destroy(&minor_id); return err; } -- cgit v0.10.2 From f0ec8cd5eb49e0360ce6ba865d5f2267b28d1f84 Mon Sep 17 00:00:00 2001 From: Mark Greer <mgreer@animalcreek.com> Date: Sat, 20 Aug 2016 16:25:06 -0700 Subject: greybus: audio: Fix incorrect direction value when enabling RX The direction value passed to gb_audio_apbridgea_register_cport() in the gbaudio_module_enable_rx() routine is TX and not RX like it should be so fix it. Testing Done: Recorded microphone data from a headset. Signed-off-by: Mark Greer <mgreer@animalcreek.com> Fixes: c80e7c6fafa5 ("audio: Split helper APIs based on stream direction") Tested-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewd-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 3eb3d2c..6ebde18 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -207,7 +207,7 @@ static int gbaudio_module_enable_rx(struct gbaudio_codec_info *codec, cportid = data->connection->hd_cport_id; ret = gb_audio_apbridgea_register_cport(data->connection, i2s_port, cportid, - AUDIO_APBRIDGEA_DIRECTION_TX); + AUDIO_APBRIDGEA_DIRECTION_RX); if (ret) { dev_err_ratelimited(module->dev, "reg_cport failed:%d\n", ret); -- cgit v0.10.2 From 0e352343c2e371ad618d8850f542e9ca230e3aa6 Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@google.com> Date: Mon, 22 Aug 2016 15:51:11 -0700 Subject: greybus: light: fix incorrect led attribute files allocation Fix incorrect attribute size when the channel supports fader, as well as fixing the issue that the attribute list is not null terminated. Testing Done: - Verified by setting brightness and color on red/green/blue leds of the device class test board. Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Rui Miguel Silva <rui.silva@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index a57d593..85bf555 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -293,13 +293,14 @@ static int channel_attr_groups_set(struct gb_channel *channel, if (channel->flags & GB_LIGHT_CHANNEL_MULTICOLOR) size++; if (channel->flags & GB_LIGHT_CHANNEL_FADER) - size++; + size += 2; if (!size) return 0; /* Set attributes based in the channel flags */ - channel->attrs = kcalloc(size, sizeof(**channel->attrs), GFP_KERNEL); + channel->attrs = kcalloc(size + 1, sizeof(**channel->attrs), + GFP_KERNEL); if (!channel->attrs) return -ENOMEM; channel->attr_group = kcalloc(1, sizeof(*channel->attr_group), -- cgit v0.10.2 From cc43368a3cde151739ad20cbf71139530bd53f1a Mon Sep 17 00:00:00 2001 From: Kris Huang <huang_kris@projectara.com> Date: Thu, 25 Aug 2016 16:57:14 +0800 Subject: greybus: lights: Control runtime pm suspend/resume on AP side According to runtime pm architecture, the kernel side driver should be as smart as needed to know when the module is idle or active, so that it can issue the suspend/resume operations to the firmware side at the right time. To add logics prevents AP from issuing the suspend request to the firmware when a channel turning to active state, and put it to suspend if the state is going to inactive with still holding a reference. Testing Done: Compiled and verified on EVT2 and gpbridge-test module with device class daughter board. Signed-off-by: Kris Huang <huang_kris@projectara.com> Reviewed-by: Rui Miguel Silva <rui.silva@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index 85bf555..71db077 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -45,6 +45,8 @@ struct gb_channel { bool is_registered; bool releasing; bool strobe_state; + bool active; + struct mutex lock; }; struct gb_light { @@ -384,11 +386,15 @@ static int __gb_lights_led_brightness_set(struct gb_channel *channel) struct gb_lights_set_brightness_request req; struct gb_connection *connection = get_conn_from_channel(channel); struct gb_bundle *bundle = connection->bundle; + bool old_active; int ret; + mutex_lock(&channel->lock); ret = gb_pm_runtime_get_sync(bundle); if (ret < 0) - return ret; + goto out_unlock; + + old_active = channel->active; req.light_id = channel->light->id; req.channel_id = channel->id; @@ -396,8 +402,29 @@ static int __gb_lights_led_brightness_set(struct gb_channel *channel) ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_BRIGHTNESS, &req, sizeof(req), NULL, 0); + if (ret < 0) + goto out_pm_put; + + if (channel->led->brightness) + channel->active = true; + else + channel->active = false; + /* we need to keep module alive when turning to active state */ + if (!old_active && channel->active) + goto out_unlock; + + /* + * on the other hand if going to inactive we still hold a reference and + * need to put it, so we could go to suspend. + */ + if (old_active && !channel->active) + gb_pm_runtime_put_autosuspend(bundle); + +out_pm_put: gb_pm_runtime_put_autosuspend(bundle); +out_unlock: + mutex_unlock(&channel->lock); return ret; } @@ -476,14 +503,18 @@ static int gb_blink_set(struct led_classdev *cdev, unsigned long *delay_on, struct gb_connection *connection = get_conn_from_channel(channel); struct gb_bundle *bundle = connection->bundle; struct gb_lights_blink_request req; + bool old_active; int ret; if (channel->releasing) return -ESHUTDOWN; + mutex_lock(&channel->lock); ret = gb_pm_runtime_get_sync(bundle); if (ret < 0) - return ret; + goto out_unlock; + + old_active = channel->active; req.light_id = channel->light->id; req.channel_id = channel->id; @@ -492,8 +523,29 @@ static int gb_blink_set(struct led_classdev *cdev, unsigned long *delay_on, ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_BLINK, &req, sizeof(req), NULL, 0); + if (ret < 0) + goto out_pm_put; + + if (delay_on) + channel->active = true; + else + channel->active = false; + + /* we need to keep module alive when turning to active state */ + if (!old_active && channel->active) + goto out_unlock; + /* + * on the other hand if going to inactive we still hold a reference and + * need to put it, so we could go to suspend. + */ + if (old_active && !channel->active) + gb_pm_runtime_put_autosuspend(bundle); + +out_pm_put: gb_pm_runtime_put_autosuspend(bundle); +out_unlock: + mutex_unlock(&channel->lock); return ret; } @@ -1061,6 +1113,8 @@ static int gb_lights_light_register(struct gb_light *light) ret = gb_lights_channel_register(&light->channels[i]); if (ret < 0) return ret; + + mutex_init(&light->channels[i].lock); } light->ready = true; @@ -1086,6 +1140,7 @@ static void gb_lights_channel_free(struct gb_channel *channel) kfree(channel->attr_groups); kfree(channel->color_name); kfree(channel->mode_name); + mutex_destroy(&channel->lock); } static void gb_lights_channel_release(struct gb_channel *channel) -- cgit v0.10.2 From 6ac9166d4e91a6dea03b64b64f128e0f927aa7ec Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva <rui.silva@linaro.org> Date: Fri, 26 Aug 2016 11:52:05 +0100 Subject: greybus: power_supply: fix name setting location We were checking for existing power supply names in the wrong place, i.e, we were checking before any of the module power supply were registered, because of that of course no name collision was detected. Move the check to the register loop and with that we guarantee that this mechanism works for greybus power supply naming. Tested: using gbsim and using power supply with the same name and check that: 1. no problems creating sysfs entries; 2. naming is done following the desired rules. Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c index 199a19a..578d38b 100644 --- a/drivers/staging/greybus/power_supply.c +++ b/drivers/staging/greybus/power_supply.c @@ -870,19 +870,19 @@ static int gb_power_supply_config(struct gb_power_supplies *supplies, int id) if (ret < 0) return ret; - ret = gb_power_supply_prop_descriptors_get(gbpsy); - if (ret < 0) - return ret; - - /* guarantee that we have an unique name, before register */ - return __gb_power_supply_set_name(gbpsy->model_name, gbpsy->name, - sizeof(gbpsy->name)); + return gb_power_supply_prop_descriptors_get(gbpsy); } static int gb_power_supply_enable(struct gb_power_supply *gbpsy) { int ret; + /* guarantee that we have an unique name, before register */ + ret = __gb_power_supply_set_name(gbpsy->model_name, gbpsy->name, + sizeof(gbpsy->name)); + if (ret < 0) + return ret; + ret = gb_power_supply_register(gbpsy); if (ret < 0) return ret; -- cgit v0.10.2 From d2dee94b66162d0839dcccee663c90400492fd1b Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 26 Aug 2016 12:55:47 +0200 Subject: greybus: es2: implement flush callback Implement the flush callback which is called as part of connection tear down to flush host-device queues and stop any ongoing transfers. Note that this should be considered an optimisation of sort since if the CPort is stuck waiting for credit, the CPort is likely still stuck when we try to send the cport_shutdown request over it after the callback returns. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/arpc.h b/drivers/staging/greybus/arpc.h index 6d27769..d44434f 100644 --- a/drivers/staging/greybus/arpc.h +++ b/drivers/staging/greybus/arpc.h @@ -80,6 +80,7 @@ struct arpc_response_message { #define ARPC_TYPE_CPORT_CONNECTED 0x01 #define ARPC_TYPE_CPORT_QUIESCE 0x02 #define ARPC_TYPE_CPORT_CLEAR 0x03 +#define ARPC_TYPE_CPORT_FLUSH 0x04 struct arpc_cport_reset_req { __le16 cport_id; @@ -99,5 +100,8 @@ struct arpc_cport_clear_req { __le16 cport_id; } __packed; +struct arpc_cport_flush_req { + __le16 cport_id; +} __packed; #endif /* __ARPC_H */ diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 8803bc9..1817c35 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -765,6 +765,24 @@ static int es2_cport_connected(struct gb_host_device *hd, u16 cport_id) return 0; } +static int es2_cport_flush(struct gb_host_device *hd, u16 cport_id) +{ + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct device *dev = &es2->usb_dev->dev; + struct arpc_cport_flush_req req; + int ret; + + req.cport_id = cpu_to_le16(cport_id); + ret = arpc_sync(es2, ARPC_TYPE_CPORT_FLUSH, &req, sizeof(req), + NULL, ES2_ARPC_CPORT_TIMEOUT); + if (ret) { + dev_err(dev, "failed to flush cport %u: %d\n", cport_id, ret); + return ret; + } + + return 0; +} + static int es2_cport_quiesce(struct gb_host_device *hd, u16 cport_id, size_t peer_space, unsigned int timeout) { @@ -997,6 +1015,7 @@ static struct gb_hd_driver es2_driver = { .cport_enable = cport_enable, .cport_disable = cport_disable, .cport_connected = es2_cport_connected, + .cport_flush = es2_cport_flush, .cport_quiesce = es2_cport_quiesce, .cport_clear = es2_cport_clear, .latency_tag_enable = latency_tag_enable, -- cgit v0.10.2 From 77e52b3b0b6489968fa7d230052afca47c556ad6 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 26 Aug 2016 12:55:48 +0200 Subject: greybus: es2: implement shutdown callback Implement the shutdown callback which is used to execute shutdown operations on offloaded connections. This adds a new shutdown ARPC. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/arpc.h b/drivers/staging/greybus/arpc.h index d44434f..d0230ab 100644 --- a/drivers/staging/greybus/arpc.h +++ b/drivers/staging/greybus/arpc.h @@ -81,6 +81,7 @@ struct arpc_response_message { #define ARPC_TYPE_CPORT_QUIESCE 0x02 #define ARPC_TYPE_CPORT_CLEAR 0x03 #define ARPC_TYPE_CPORT_FLUSH 0x04 +#define ARPC_TYPE_CPORT_SHUTDOWN 0x05 struct arpc_cport_reset_req { __le16 cport_id; @@ -104,4 +105,10 @@ struct arpc_cport_flush_req { __le16 cport_id; } __packed; +struct arpc_cport_shutdown_req { + __le16 cport_id; + __le16 timeout; + __u8 phase; +} __packed; + #endif /* __ARPC_H */ diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 1817c35..123dc9d 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -783,6 +783,32 @@ static int es2_cport_flush(struct gb_host_device *hd, u16 cport_id) return 0; } +static int es2_cport_shutdown(struct gb_host_device *hd, u16 cport_id, + u8 phase, unsigned int timeout) +{ + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct device *dev = &es2->usb_dev->dev; + struct arpc_cport_shutdown_req req; + int result; + int ret; + + if (timeout > U16_MAX) + return -EINVAL; + + req.cport_id = cpu_to_le16(cport_id); + req.timeout = cpu_to_le16(timeout); + req.phase = phase; + ret = arpc_sync(es2, ARPC_TYPE_CPORT_SHUTDOWN, &req, sizeof(req), + &result, ES2_ARPC_CPORT_TIMEOUT + timeout); + if (ret) { + dev_err(dev, "failed to send shutdown over cport %u: %d (%d)\n", + cport_id, ret, result); + return ret; + } + + return 0; +} + static int es2_cport_quiesce(struct gb_host_device *hd, u16 cport_id, size_t peer_space, unsigned int timeout) { @@ -1016,6 +1042,7 @@ static struct gb_hd_driver es2_driver = { .cport_disable = cport_disable, .cport_connected = es2_cport_connected, .cport_flush = es2_cport_flush, + .cport_shutdown = es2_cport_shutdown, .cport_quiesce = es2_cport_quiesce, .cport_clear = es2_cport_clear, .latency_tag_enable = latency_tag_enable, -- cgit v0.10.2 From aac0839ea20306401f6e18cf8ea97d98fd42bcb5 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 26 Aug 2016 12:55:49 +0200 Subject: greybus: connection: implement new connection handling Implement the new connection setup and tear-down sequences for control connections and bundle connections (offloaded and non-offloaded). Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index ce8ba9c..5570751 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -13,6 +13,9 @@ #include "greybus_trace.h" +#define GB_CONNECTION_CPORT_QUIESCE_TIMEOUT 1000 + + static void gb_connection_kref_release(struct kref *kref); @@ -312,6 +315,24 @@ static void gb_connection_hd_cport_disable(struct gb_connection *connection) } } +static int gb_connection_hd_cport_connected(struct gb_connection *connection) +{ + struct gb_host_device *hd = connection->hd; + int ret; + + if (!hd->driver->cport_connected) + return 0; + + ret = hd->driver->cport_connected(hd, connection->hd_cport_id); + if (ret) { + dev_err(&hd->dev, "%s: failed to set connected state: %d\n", + connection->name, ret); + return ret; + } + + return 0; +} + static int gb_connection_hd_cport_flush(struct gb_connection *connection) { struct gb_host_device *hd = connection->hd; @@ -330,34 +351,43 @@ static int gb_connection_hd_cport_flush(struct gb_connection *connection) return 0; } -static int -gb_connection_hd_cport_features_enable(struct gb_connection *connection) +static int gb_connection_hd_cport_quiesce(struct gb_connection *connection) { struct gb_host_device *hd = connection->hd; + size_t peer_space; int ret; - if (!hd->driver->cport_features_enable) - return 0; + peer_space = sizeof(struct gb_operation_msg_hdr) + + sizeof(struct gb_cport_shutdown_request); - ret = hd->driver->cport_features_enable(hd, connection->hd_cport_id); + if (connection->mode_switch) + peer_space += sizeof(struct gb_operation_msg_hdr); + + ret = hd->driver->cport_quiesce(hd, connection->hd_cport_id, + peer_space, + GB_CONNECTION_CPORT_QUIESCE_TIMEOUT); if (ret) { - dev_err(&hd->dev, "%s: failed to enable CPort features: %d\n", - connection->name, ret); + dev_err(&hd->dev, "%s: failed to quiesce host cport: %d\n", + connection->name, ret); return ret; } return 0; } -static void -gb_connection_hd_cport_features_disable(struct gb_connection *connection) +static int gb_connection_hd_cport_clear(struct gb_connection *connection) { struct gb_host_device *hd = connection->hd; + int ret; - if (!hd->driver->cport_features_disable) - return; + ret = hd->driver->cport_clear(hd, connection->hd_cport_id); + if (ret) { + dev_err(&hd->dev, "%s: failed to clear host cport: %d\n", + connection->name, ret); + return ret; + } - hd->driver->cport_features_disable(hd, connection->hd_cport_id); + return 0; } /* @@ -496,18 +526,23 @@ gb_connection_control_disconnected(struct gb_connection *connection) } } -static int gb_connection_ping_operation(struct gb_connection *connection) +static int gb_connection_shutdown_operation(struct gb_connection *connection, + u8 phase) { + struct gb_cport_shutdown_request *req; struct gb_operation *operation; int ret; operation = gb_operation_create_core(connection, - GB_REQUEST_TYPE_PING, - 0, 0, 0, + GB_REQUEST_TYPE_CPORT_SHUTDOWN, + sizeof(*req), 0, 0, GFP_KERNEL); if (!operation) return -ENOMEM; + req = operation->request->payload; + req->phase = phase; + ret = gb_operation_request_send_sync(operation); gb_operation_put(operation); @@ -515,32 +550,47 @@ static int gb_connection_ping_operation(struct gb_connection *connection) return ret; } -static int gb_connection_ping(struct gb_connection *connection) +static int gb_connection_cport_shutdown(struct gb_connection *connection, + u8 phase) { struct gb_host_device *hd = connection->hd; + const struct gb_hd_driver *drv = hd->driver; int ret; if (gb_connection_is_static(connection)) return 0; if (gb_connection_is_offloaded(connection)) { - if (!hd->driver->cport_ping) + if (!drv->cport_shutdown) return 0; - ret = hd->driver->cport_ping(hd, connection->hd_cport_id); + ret = drv->cport_shutdown(hd, connection->hd_cport_id, phase, + GB_OPERATION_TIMEOUT_DEFAULT); } else { - ret = gb_connection_ping_operation(connection); + ret = gb_connection_shutdown_operation(connection, phase); } if (ret) { - dev_err(&hd->dev, "%s: failed to send ping: %d\n", - connection->name, ret); + dev_err(&hd->dev, "%s: failed to send cport shutdown (phase %d): %d\n", + connection->name, phase, ret); return ret; } return 0; } +static int +gb_connection_cport_shutdown_phase_1(struct gb_connection *connection) +{ + return gb_connection_cport_shutdown(connection, 1); +} + +static int +gb_connection_cport_shutdown_phase_2(struct gb_connection *connection) +{ + return gb_connection_cport_shutdown(connection, 2); +} + /* * Cancel all active operations on a connection. * @@ -639,9 +689,9 @@ static int _gb_connection_enable(struct gb_connection *connection, bool rx) ret = gb_connection_svc_connection_create(connection); if (ret) - goto err_hd_cport_disable; + goto err_hd_cport_clear; - ret = gb_connection_hd_cport_features_enable(connection); + ret = gb_connection_hd_cport_connected(connection); if (ret) goto err_svc_connection_destroy; @@ -659,8 +709,6 @@ static int _gb_connection_enable(struct gb_connection *connection, bool rx) return 0; err_control_disconnecting: - gb_connection_control_disconnecting(connection); - spin_lock_irq(&connection->lock); connection->state = GB_CONNECTION_STATE_DISCONNECTING; gb_connection_cancel_operations(connection, -ESHUTDOWN); @@ -669,13 +717,17 @@ err_control_disconnecting: /* Transmit queue should already be empty. */ gb_connection_hd_cport_flush(connection); - gb_connection_ping(connection); - gb_connection_hd_cport_features_disable(connection); + gb_connection_control_disconnecting(connection); + gb_connection_cport_shutdown_phase_1(connection); + gb_connection_hd_cport_quiesce(connection); + gb_connection_cport_shutdown_phase_2(connection); gb_connection_control_disconnected(connection); connection->state = GB_CONNECTION_STATE_DISABLED; err_svc_connection_destroy: gb_connection_svc_connection_destroy(connection); -err_hd_cport_disable: +err_hd_cport_clear: + gb_connection_hd_cport_clear(connection); + gb_connection_hd_cport_disable(connection); return ret; @@ -754,7 +806,10 @@ void gb_connection_mode_switch_prepare(struct gb_connection *connection) void gb_connection_mode_switch_complete(struct gb_connection *connection) { gb_connection_svc_connection_destroy(connection); + gb_connection_hd_cport_clear(connection); + gb_connection_hd_cport_disable(connection); + connection->mode_switch = false; } @@ -767,8 +822,6 @@ void gb_connection_disable(struct gb_connection *connection) trace_gb_connection_disable(connection); - gb_connection_control_disconnecting(connection); - spin_lock_irq(&connection->lock); connection->state = GB_CONNECTION_STATE_DISCONNECTING; gb_connection_cancel_operations(connection, -ESHUTDOWN); @@ -776,9 +829,10 @@ void gb_connection_disable(struct gb_connection *connection) gb_connection_hd_cport_flush(connection); - gb_connection_ping(connection); - gb_connection_hd_cport_features_disable(connection); - + gb_connection_control_disconnecting(connection); + gb_connection_cport_shutdown_phase_1(connection); + gb_connection_hd_cport_quiesce(connection); + gb_connection_cport_shutdown_phase_2(connection); gb_connection_control_disconnected(connection); connection->state = GB_CONNECTION_STATE_DISABLED; @@ -786,6 +840,8 @@ void gb_connection_disable(struct gb_connection *connection) /* control-connection tear down is deferred when mode switching */ if (!connection->mode_switch) { gb_connection_svc_connection_destroy(connection); + gb_connection_hd_cport_clear(connection); + gb_connection_hd_cport_disable(connection); } @@ -810,10 +866,11 @@ void gb_connection_disable_forced(struct gb_connection *connection) spin_unlock_irq(&connection->lock); gb_connection_hd_cport_flush(connection); - gb_connection_hd_cport_features_disable(connection); + gb_connection_svc_connection_destroy(connection); - gb_connection_hd_cport_disable(connection); + gb_connection_hd_cport_clear(connection); + gb_connection_hd_cport_disable(connection); out_unlock: mutex_unlock(&connection->mutex); } diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index dd84e75..b8ce99c 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -96,9 +96,13 @@ struct gb_operation_msg_hdr { /* Generic request types */ -#define GB_REQUEST_TYPE_PING 0x00 +#define GB_REQUEST_TYPE_CPORT_SHUTDOWN 0x00 #define GB_REQUEST_TYPE_INVALID 0x7f +struct gb_cport_shutdown_request { + __u8 phase; +} __packed; + /* Control Protocol */ -- cgit v0.10.2 From 2045c9f265a1ed882a8d773da916460697c51ffc Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 26 Aug 2016 12:55:50 +0200 Subject: greybus: hd/es2: remove obsolete callbacks Remove the now obsolete ping and cport_features_enable/disable callbacks. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 123dc9d..b225fc3 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -892,41 +892,6 @@ static int latency_tag_disable(struct gb_host_device *hd, u16 cport_id) return retval; } -static int cport_features_enable(struct gb_host_device *hd, u16 cport_id) -{ - int retval; - struct es2_ap_dev *es2 = hd_to_es2(hd); - struct usb_device *udev = es2->usb_dev; - - retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - GB_APB_REQUEST_CPORT_FEAT_EN, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_INTERFACE, cport_id, 0, NULL, - 0, ES2_USB_CTRL_TIMEOUT); - if (retval < 0) - dev_err(&udev->dev, "Cannot enable CPort features for cport %u: %d\n", - cport_id, retval); - return retval; -} - -static int cport_features_disable(struct gb_host_device *hd, u16 cport_id) -{ - int retval; - struct es2_ap_dev *es2 = hd_to_es2(hd); - struct usb_device *udev = es2->usb_dev; - - retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - GB_APB_REQUEST_CPORT_FEAT_DIS, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_INTERFACE, cport_id, 0, NULL, - 0, ES2_USB_CTRL_TIMEOUT); - if (retval < 0) - dev_err(&udev->dev, - "Cannot disable CPort features for cport %u: %d\n", - cport_id, retval); - return retval; -} - static int timesync_enable(struct gb_host_device *hd, u8 count, u64 frame_time, u32 strobe_delay, u32 refclk) { @@ -1048,8 +1013,6 @@ static struct gb_hd_driver es2_driver = { .latency_tag_enable = latency_tag_enable, .latency_tag_disable = latency_tag_disable, .output = output, - .cport_features_enable = cport_features_enable, - .cport_features_disable = cport_features_disable, .timesync_enable = timesync_enable, .timesync_disable = timesync_disable, .timesync_authoritative = timesync_authoritative, diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index b8ce99c..c4ef005 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -250,10 +250,6 @@ struct gb_control_intf_pm_response { /* request to control audio streaming */ #define GB_APB_REQUEST_AUDIO_CONTROL 0x09 -/* vendor requests to enable/disable CPort features */ -#define GB_APB_REQUEST_CPORT_FEAT_EN 0x0b -#define GB_APB_REQUEST_CPORT_FEAT_DIS 0x0c - /* TimeSync requests */ #define GB_APB_REQUEST_TIMESYNC_ENABLE 0x0d #define GB_APB_REQUEST_TIMESYNC_DISABLE 0x0e diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h index 1274224..c4250cfe 100644 --- a/drivers/staging/greybus/hd.h +++ b/drivers/staging/greybus/hd.h @@ -24,7 +24,6 @@ struct gb_hd_driver { int (*cport_disable)(struct gb_host_device *hd, u16 cport_id); int (*cport_connected)(struct gb_host_device *hd, u16 cport_id); int (*cport_flush)(struct gb_host_device *hd, u16 cport_id); - int (*cport_ping)(struct gb_host_device *hd, u16 cport_id); int (*cport_shutdown)(struct gb_host_device *hd, u16 cport_id, u8 phase, unsigned int timeout); int (*cport_quiesce)(struct gb_host_device *hd, u16 cport_id, @@ -38,8 +37,6 @@ struct gb_hd_driver { int (*latency_tag_disable)(struct gb_host_device *hd, u16 cport_id); int (*output)(struct gb_host_device *hd, void *req, u16 size, u8 cmd, bool async); - int (*cport_features_enable)(struct gb_host_device *hd, u16 cport_id); - int (*cport_features_disable)(struct gb_host_device *hd, u16 cport_id); int (*timesync_enable)(struct gb_host_device *hd, u8 count, u64 frame_time, u32 strobe_delay, u32 refclk); int (*timesync_disable)(struct gb_host_device *hd); -- cgit v0.10.2 From 1b1732c4c473ba59901cf5cc5c6ef2d3578cce14 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 26 Aug 2016 12:55:51 +0200 Subject: greybus: es2: remove obsolete cport-reset ARPC Remove the now obsolete and redundant cport-reset ARPC, along with the consequently unused cport_disable callback. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/arpc.h b/drivers/staging/greybus/arpc.h index d0230ab..7fbddfc 100644 --- a/drivers/staging/greybus/arpc.h +++ b/drivers/staging/greybus/arpc.h @@ -76,17 +76,12 @@ struct arpc_response_message { /* ARPC requests */ -#define ARPC_TYPE_CPORT_RESET 0x00 #define ARPC_TYPE_CPORT_CONNECTED 0x01 #define ARPC_TYPE_CPORT_QUIESCE 0x02 #define ARPC_TYPE_CPORT_CLEAR 0x03 #define ARPC_TYPE_CPORT_FLUSH 0x04 #define ARPC_TYPE_CPORT_SHUTDOWN 0x05 -struct arpc_cport_reset_req { - __le16 cport_id; -} __packed; - struct arpc_cport_connected_req { __le16 cport_id; } __packed; diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index b225fc3..df10479 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -611,32 +611,6 @@ static void message_cancel(struct gb_message *message) usb_free_urb(urb); } -static int cport_reset(struct gb_host_device *hd, u16 cport_id) -{ - struct es2_ap_dev *es2 = hd_to_es2(hd); - struct usb_device *udev = es2->usb_dev; - struct arpc_cport_reset_req req; - int retval; - int result; - - switch (cport_id) { - case GB_SVC_CPORT_ID: - case ES2_CPORT_CDSI0: - case ES2_CPORT_CDSI1: - return 0; - } - - req.cport_id = cpu_to_le16(cport_id); - retval = arpc_sync(es2, ARPC_TYPE_CPORT_RESET, &req, sizeof(req), - &result, ES2_ARPC_CPORT_TIMEOUT); - if (retval == -EREMOTEIO) { - dev_err(&udev->dev, "failed to reset cport %u: %d\n", cport_id, - result); - } - - return retval; -} - static int es2_cport_allocate(struct gb_host_device *hd, int cport_id, unsigned long flags) { @@ -735,17 +709,6 @@ out: return ret; } -static int cport_disable(struct gb_host_device *hd, u16 cport_id) -{ - int retval; - - retval = cport_reset(hd, cport_id); - if (retval) - return retval; - - return 0; -} - static int es2_cport_connected(struct gb_host_device *hd, u16 cport_id) { struct es2_ap_dev *es2 = hd_to_es2(hd); @@ -1004,7 +967,6 @@ static struct gb_hd_driver es2_driver = { .cport_allocate = es2_cport_allocate, .cport_release = es2_cport_release, .cport_enable = cport_enable, - .cport_disable = cport_disable, .cport_connected = es2_cport_connected, .cport_flush = es2_cport_flush, .cport_shutdown = es2_cport_shutdown, -- cgit v0.10.2 From 1f3e09e759061f803b03039070605b5a524da547 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Fri, 26 Aug 2016 12:59:45 +0200 Subject: greybus: svc: fix timeout indentation Make sure the timeout values are aligned. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 6182e13..550055e 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -14,7 +14,7 @@ #define SVC_INTF_EJECT_TIMEOUT 9000 #define SVC_INTF_ACTIVATE_TIMEOUT 6000 -#define SVC_INTF_RESUME_TIMEOUT 3000 +#define SVC_INTF_RESUME_TIMEOUT 3000 struct gb_svc_deferred_request { struct work_struct work; -- cgit v0.10.2 From 9d47964bfd471f0dd4c89f28556aec68bffa0020 Mon Sep 17 00:00:00 2001 From: Colin Ian King <colin.king@canonical.com> Date: Mon, 25 Jul 2016 23:40:01 +0100 Subject: iio: ad5755: fix off-by-one on devnr limit check The comparison for devnr limits is off-by-one, the current check allows 0 to AD5755_NUM_CHANNELS and the limit should be in fact 0 to AD5755_NUM_CHANNELS - 1. This can lead to an out of bounds write to pdata->dac[devnr]. Fix this by replacing > with >= on the comparison. Signed-off-by: Colin Ian King <colin.king@canonical.com> Fixes: c947459979c6 ("iio: ad5755: add support for dt bindings") Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/dac/ad5755.c b/drivers/iio/dac/ad5755.c index 0fde593..5f79682 100644 --- a/drivers/iio/dac/ad5755.c +++ b/drivers/iio/dac/ad5755.c @@ -655,7 +655,7 @@ static struct ad5755_platform_data *ad5755_parse_dt(struct device *dev) devnr = 0; for_each_child_of_node(np, pp) { - if (devnr > AD5755_NUM_CHANNELS) { + if (devnr >= AD5755_NUM_CHANNELS) { dev_err(dev, "There is to many channels defined in DT\n"); goto error_out; -- cgit v0.10.2 From 6356f1b9b7e3ccd24bec93c7ed4e226464f44774 Mon Sep 17 00:00:00 2001 From: Matt Ranostay <mranostay@gmail.com> Date: Mon, 22 Aug 2016 15:19:37 -0700 Subject: iio: iio-utils: use channel modifier scaling if it exists Now there are channel modifiers with their own scaling those should be used when possible over the generic channel type scaling. Examples are of IIO_TEMP channel having a generic scaling value, and another having IIO_MOD_TEMP_AMBIENT modifier with another scaling value. Previously the first scaling value for a channel type would be applied to all channels of like type in iio_generic_buffer Signed-off-by: Matt Ranostay <mranostay@gmail.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/tools/iio/iio_utils.c b/tools/iio/iio_utils.c index 5eb6793..7a6d61c 100644 --- a/tools/iio/iio_utils.c +++ b/tools/iio/iio_utils.c @@ -121,10 +121,6 @@ int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used, ret = -ENOENT; while (ent = readdir(dp), ent) - /* - * Do we allow devices to override a generic name with - * a specific one? - */ if ((strcmp(builtname, ent->d_name) == 0) || (strcmp(builtname_generic, ent->d_name) == 0)) { ret = asprintf(&filename, @@ -178,6 +174,13 @@ int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used, sysfsfp = 0; free(filename); filename = 0; + + /* + * Avoid having a more generic entry overwriting + * the settings. + */ + if (strcmp(builtname, ent->d_name) == 0) + break; } error_close_sysfsfp: -- cgit v0.10.2 From a5211b0d061644b48c80cfa1303413e79ace781e Mon Sep 17 00:00:00 2001 From: Clifton Barnes <clifton.a.barnes@gmail.com> Date: Mon, 22 Aug 2016 22:45:05 -0400 Subject: staging: iio: accel: sca3000: remove extra space fix checkpatch.pl warning about 'Statements should start on a tabstop' Signed-off-by: Clifton Barnes <clifton.a.barnes@gmail.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c index b5625f5..61f3241 100644 --- a/drivers/staging/iio/accel/sca3000_core.c +++ b/drivers/staging/iio/accel/sca3000_core.c @@ -412,7 +412,7 @@ static const struct iio_event_spec sca3000_event = { }, \ .event_spec = &sca3000_event, \ .num_event_specs = 1, \ - } + } static const struct iio_chan_spec sca3000_channels[] = { SCA3000_CHAN(0, IIO_MOD_X), -- cgit v0.10.2 From 8c9e7b1bf42af845f83350e5141fbc4181dc7f98 Mon Sep 17 00:00:00 2001 From: Alison Schofield <amsfield22@gmail.com> Date: Wed, 24 Aug 2016 22:48:43 -0700 Subject: iio: adc: ltc2485: add support for Linear Technology LTC2485 ADC Adds basic support for the LTC2485 ADC - a delta-sigma analog-to-digital converter with an I2C interface that operates in single shot conversion mode. The driver supports an on board 5V reference and the power-on default configuration which rejects both 50hz & 60hz line frequencies and operates in 1x speed mode. Signed-off-by: Alison Schofield <amsfield22@gmail.com> Cc: Daniel Baluta <daniel.baluta@gmail.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index e4022fd..6eac923 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -264,6 +264,15 @@ config LPC18XX_ADC To compile this driver as a module, choose M here: the module will be called lpc18xx_adc. +config LTC2485 + tristate "Linear Technology LTC2485 ADC driver" + depends on I2C + help + Say yes here to build support for Linear Technology LTC2485 ADC. + + To compile this driver as a module, choose M here: the module will be + called ltc2485. + config MAX1027 tristate "Maxim max1027 ADC driver" depends on SPI diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 33254eb..f46dd1f 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o +obj-$(CONFIG_LTC2485) += ltc2485.o obj-$(CONFIG_MAX1027) += max1027.o obj-$(CONFIG_MAX1363) += max1363.o obj-$(CONFIG_MCP320X) += mcp320x.o diff --git a/drivers/iio/adc/ltc2485.c b/drivers/iio/adc/ltc2485.c new file mode 100644 index 0000000..eab91f12 --- /dev/null +++ b/drivers/iio/adc/ltc2485.c @@ -0,0 +1,148 @@ +/* + * ltc2485.c - Driver for Linear Technology LTC2485 ADC + * + * Copyright (C) 2016 Alison Schofield <amsfield22@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Datasheet: http://cds.linear.com/docs/en/datasheet/2485fd.pdf + */ + +#include <linux/delay.h> +#include <linux/i2c.h> +#include <linux/module.h> + +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> + +/* Power-on configuration: rejects both 50/60Hz, operates at 1x speed */ +#define LTC2485_CONFIG_DEFAULT 0 + +struct ltc2485_data { + struct i2c_client *client; + ktime_t time_prev; /* last conversion */ +}; + +static void ltc2485_wait_conv(struct ltc2485_data *data) +{ + const unsigned int conv_time = 147; /* conversion time ms */ + unsigned int time_elapsed; + + /* delay if conversion time not passed since last read or write */ + time_elapsed = ktime_ms_delta(ktime_get(), data->time_prev); + + if (time_elapsed < conv_time) + msleep(conv_time - time_elapsed); +} + +static int ltc2485_read(struct ltc2485_data *data, int *val) +{ + struct i2c_client *client = data->client; + __be32 buf = 0; + int ret; + + ltc2485_wait_conv(data); + + ret = i2c_master_recv(client, (char *)&buf, 4); + if (ret < 0) { + dev_err(&client->dev, "i2c_master_recv failed\n"); + return ret; + } + data->time_prev = ktime_get(); + *val = sign_extend32(be32_to_cpu(buf) >> 6, 24); + + return ret; +} + +static int ltc2485_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct ltc2485_data *data = iio_priv(indio_dev); + int ret; + + if (mask == IIO_CHAN_INFO_RAW) { + ret = ltc2485_read(data, val); + if (ret < 0) + return ret; + + return IIO_VAL_INT; + + } else if (mask == IIO_CHAN_INFO_SCALE) { + *val = 5000; /* on board vref millivolts */ + *val2 = 25; /* 25 (24 + sign) data bits */ + return IIO_VAL_FRACTIONAL_LOG2; + + } else { + return -EINVAL; + } +} + +static const struct iio_chan_spec ltc2485_channel[] = { + { + .type = IIO_VOLTAGE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) + }, +}; + +static const struct iio_info ltc2485_info = { + .read_raw = ltc2485_read_raw, + .driver_module = THIS_MODULE, +}; + +static int ltc2485_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct iio_dev *indio_dev; + struct ltc2485_data *data; + int ret; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C | + I2C_FUNC_SMBUS_WRITE_BYTE)) + return -EOPNOTSUPP; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + data->client = client; + + indio_dev->dev.parent = &client->dev; + indio_dev->name = id->name; + indio_dev->info = <c2485_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = ltc2485_channel; + indio_dev->num_channels = ARRAY_SIZE(ltc2485_channel); + + ret = i2c_smbus_write_byte(data->client, LTC2485_CONFIG_DEFAULT); + if (ret < 0) + return ret; + + data->time_prev = ktime_get(); + + return devm_iio_device_register(&client->dev, indio_dev); +} + +static const struct i2c_device_id ltc2485_id[] = { + { "ltc2485", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ltc2485_id); + +static struct i2c_driver ltc2485_driver = { + .driver = { + .name = "ltc2485", + }, + .probe = ltc2485_probe, + .id_table = ltc2485_id, +}; +module_i2c_driver(ltc2485_driver); + +MODULE_AUTHOR("Alison Schofield <amsfield22@gmail.com>"); +MODULE_DESCRIPTION("Linear Technology LTC2485 ADC driver"); +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 8376882f167be87aa44acc105020417532ac3c51 Mon Sep 17 00:00:00 2001 From: Matt Ranostay <mranostay@gmail.com> Date: Wed, 24 Aug 2016 23:44:47 -0700 Subject: iio: chemical: vz89x: abstract chip configuration Abstract chip configuration data to allow supporting multiple variants of the VZ89 chemical sensor line. Signed-off-by: Matt Ranostay <mranostay@gmail.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/chemical/vz89x.c b/drivers/iio/chemical/vz89x.c index 652649d..aa6ebc0 100644 --- a/drivers/iio/chemical/vz89x.c +++ b/drivers/iio/chemical/vz89x.c @@ -19,25 +19,45 @@ #include <linux/mutex.h> #include <linux/init.h> #include <linux/i2c.h> +#include <linux/of.h> +#include <linux/of_device.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> #define VZ89X_REG_MEASUREMENT 0x09 -#define VZ89X_REG_MEASUREMENT_SIZE 6 +#define VZ89X_REG_MEASUREMENT_RD_SIZE 6 +#define VZ89X_REG_MEASUREMENT_WR_SIZE 3 #define VZ89X_VOC_CO2_IDX 0 #define VZ89X_VOC_SHORT_IDX 1 #define VZ89X_VOC_TVOC_IDX 2 #define VZ89X_VOC_RESISTANCE_IDX 3 +enum { + VZ89X, +}; + +struct vz89x_chip_data; + struct vz89x_data { struct i2c_client *client; + const struct vz89x_chip_data *chip; struct mutex lock; int (*xfer)(struct vz89x_data *data, u8 cmd); unsigned long last_update; - u8 buffer[VZ89X_REG_MEASUREMENT_SIZE]; + u8 buffer[VZ89X_REG_MEASUREMENT_RD_SIZE]; +}; + +struct vz89x_chip_data { + bool (*valid)(struct vz89x_data *data); + const struct iio_chan_spec *channels; + u8 num_channels; + + u8 cmd; + u8 read_size; + u8 write_size; }; static const struct iio_chan_spec vz89x_channels[] = { @@ -93,16 +113,17 @@ static const struct attribute_group vz89x_attrs_group = { * always zero, and by also confirming the VOC_short isn't zero. */ -static int vz89x_measurement_is_valid(struct vz89x_data *data) +static bool vz89x_measurement_is_valid(struct vz89x_data *data) { if (data->buffer[VZ89X_VOC_SHORT_IDX] == 0) return 1; - return !!(data->buffer[VZ89X_REG_MEASUREMENT_SIZE - 1] > 0); + return !!(data->buffer[data->chip->read_size - 1] > 0); } static int vz89x_i2c_xfer(struct vz89x_data *data, u8 cmd) { + const struct vz89x_chip_data *chip = data->chip; struct i2c_client *client = data->client; struct i2c_msg msg[2]; int ret; @@ -110,12 +131,12 @@ static int vz89x_i2c_xfer(struct vz89x_data *data, u8 cmd) msg[0].addr = client->addr; msg[0].flags = client->flags; - msg[0].len = 3; + msg[0].len = chip->write_size; msg[0].buf = (char *) &buf; msg[1].addr = client->addr; msg[1].flags = client->flags | I2C_M_RD; - msg[1].len = VZ89X_REG_MEASUREMENT_SIZE; + msg[1].len = chip->read_size; msg[1].buf = (char *) &data->buffer; ret = i2c_transfer(client->adapter, msg, 2); @@ -133,7 +154,7 @@ static int vz89x_smbus_xfer(struct vz89x_data *data, u8 cmd) if (ret < 0) return ret; - for (i = 0; i < VZ89X_REG_MEASUREMENT_SIZE; i++) { + for (i = 0; i < data->chip->read_size; i++) { ret = i2c_smbus_read_byte(client); if (ret < 0) return ret; @@ -145,17 +166,18 @@ static int vz89x_smbus_xfer(struct vz89x_data *data, u8 cmd) static int vz89x_get_measurement(struct vz89x_data *data) { + const struct vz89x_chip_data *chip = data->chip; int ret; /* sensor can only be polled once a second max per datasheet */ if (!time_after(jiffies, data->last_update + HZ)) return 0; - ret = data->xfer(data, VZ89X_REG_MEASUREMENT); + ret = data->xfer(data, chip->cmd); if (ret < 0) return ret; - ret = vz89x_measurement_is_valid(data); + ret = chip->valid(data); if (ret) return -EAGAIN; @@ -232,11 +254,32 @@ static const struct iio_info vz89x_info = { .driver_module = THIS_MODULE, }; +static const struct vz89x_chip_data vz89x_chips[] = { + { + .valid = vz89x_measurement_is_valid, + + .cmd = VZ89X_REG_MEASUREMENT, + .read_size = VZ89X_REG_MEASUREMENT_RD_SIZE, + .write_size = VZ89X_REG_MEASUREMENT_WR_SIZE, + + .channels = vz89x_channels, + .num_channels = ARRAY_SIZE(vz89x_channels), + }, +}; + +static const struct of_device_id vz89x_dt_ids[] = { + { .compatible = "sgx,vz89x", .data = (void *) VZ89X }, + { } +}; +MODULE_DEVICE_TABLE(of, vz89x_dt_ids); + static int vz89x_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct iio_dev *indio_dev; struct vz89x_data *data; + const struct of_device_id *of_id; + int chip_id; indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); if (!indio_dev) @@ -251,8 +294,15 @@ static int vz89x_probe(struct i2c_client *client, else return -EOPNOTSUPP; + of_id = of_match_device(vz89x_dt_ids, &client->dev); + if (!of_id) + chip_id = id->driver_data; + else + chip_id = (unsigned long)of_id->data; + i2c_set_clientdata(client, indio_dev); data->client = client; + data->chip = &vz89x_chips[chip_id]; data->last_update = jiffies - HZ; mutex_init(&data->lock); @@ -261,24 +311,18 @@ static int vz89x_probe(struct i2c_client *client, indio_dev->name = dev_name(&client->dev); indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = vz89x_channels; - indio_dev->num_channels = ARRAY_SIZE(vz89x_channels); + indio_dev->channels = data->chip->channels; + indio_dev->num_channels = data->chip->num_channels; return devm_iio_device_register(&client->dev, indio_dev); } static const struct i2c_device_id vz89x_id[] = { - { "vz89x", 0 }, + { "vz89x", VZ89X }, { } }; MODULE_DEVICE_TABLE(i2c, vz89x_id); -static const struct of_device_id vz89x_dt_ids[] = { - { .compatible = "sgx,vz89x" }, - { } -}; -MODULE_DEVICE_TABLE(of, vz89x_dt_ids); - static struct i2c_driver vz89x_driver = { .driver = { .name = "vz89x", -- cgit v0.10.2 From 0a735aa07f2eb5bcb04fb022b463c70cd1cf1399 Mon Sep 17 00:00:00 2001 From: Matt Ranostay <mranostay@gmail.com> Date: Wed, 24 Aug 2016 23:44:48 -0700 Subject: iio: chemical: vz89x: add support for VZ89TE part Add support the VZ89TE variant which removes the voc_short channel, and has CRC check for data transactions. Signed-off-by: Matt Ranostay <mranostay@gmail.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/chemical/vz89x.c b/drivers/iio/chemical/vz89x.c index aa6ebc0..289d291 100644 --- a/drivers/iio/chemical/vz89x.c +++ b/drivers/iio/chemical/vz89x.c @@ -34,8 +34,17 @@ #define VZ89X_VOC_TVOC_IDX 2 #define VZ89X_VOC_RESISTANCE_IDX 3 +#define VZ89TE_REG_MEASUREMENT 0x0c +#define VZ89TE_REG_MEASUREMENT_RD_SIZE 7 +#define VZ89TE_REG_MEASUREMENT_WR_SIZE 6 + +#define VZ89TE_VOC_TVOC_IDX 0 +#define VZ89TE_VOC_CO2_IDX 1 +#define VZ89TE_VOC_RESISTANCE_IDX 2 + enum { VZ89X, + VZ89TE, }; struct vz89x_chip_data; @@ -47,7 +56,7 @@ struct vz89x_data { int (*xfer)(struct vz89x_data *data, u8 cmd); unsigned long last_update; - u8 buffer[VZ89X_REG_MEASUREMENT_RD_SIZE]; + u8 buffer[VZ89TE_REG_MEASUREMENT_RD_SIZE]; }; struct vz89x_chip_data { @@ -90,6 +99,40 @@ static const struct iio_chan_spec vz89x_channels[] = { .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), .address = VZ89X_VOC_RESISTANCE_IDX, + .scan_index = -1, + .scan_type = { + .endianness = IIO_LE, + }, + }, +}; + +static const struct iio_chan_spec vz89te_channels[] = { + { + .type = IIO_CONCENTRATION, + .channel2 = IIO_MOD_VOC, + .modified = 1, + .info_mask_separate = + BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_RAW), + .address = VZ89TE_VOC_TVOC_IDX, + }, + + { + .type = IIO_CONCENTRATION, + .channel2 = IIO_MOD_CO2, + .modified = 1, + .info_mask_separate = + BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_RAW), + .address = VZ89TE_VOC_CO2_IDX, + }, + { + .type = IIO_RESISTANCE, + .info_mask_separate = + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .address = VZ89TE_VOC_RESISTANCE_IDX, + .scan_index = -1, + .scan_type = { + .endianness = IIO_BE, + }, }, }; @@ -121,13 +164,28 @@ static bool vz89x_measurement_is_valid(struct vz89x_data *data) return !!(data->buffer[data->chip->read_size - 1] > 0); } +/* VZ89TE device has a modified CRC-8 two complement check */ +static bool vz89te_measurement_is_valid(struct vz89x_data *data) +{ + u8 crc = 0; + int i, sum = 0; + + for (i = 0; i < (data->chip->read_size - 1); i++) { + sum = crc + data->buffer[i]; + crc = sum; + crc += sum / 256; + } + + return !((0xff - crc) == data->buffer[data->chip->read_size - 1]); +} + static int vz89x_i2c_xfer(struct vz89x_data *data, u8 cmd) { const struct vz89x_chip_data *chip = data->chip; struct i2c_client *client = data->client; struct i2c_msg msg[2]; int ret; - u8 buf[3] = { cmd, 0, 0}; + u8 buf[6] = { cmd, 0, 0, 0, 0, 0xf3 }; msg[0].addr = client->addr; msg[0].flags = client->flags; @@ -186,11 +244,24 @@ static int vz89x_get_measurement(struct vz89x_data *data) return 0; } -static int vz89x_get_resistance_reading(struct vz89x_data *data) +static int vz89x_get_resistance_reading(struct vz89x_data *data, + struct iio_chan_spec const *chan, + int *val) { - u8 *buf = &data->buffer[VZ89X_VOC_RESISTANCE_IDX]; + u8 *tmp = (u8 *) &data->buffer[chan->address]; - return buf[0] | (buf[1] << 8); + switch (chan->scan_type.endianness) { + case IIO_LE: + *val = le32_to_cpup((__le32 *) tmp) & GENMASK(23, 0); + break; + case IIO_BE: + *val = be32_to_cpup((__be32 *) tmp) >> 8; + break; + default: + return -EINVAL; + } + + return 0; } static int vz89x_read_raw(struct iio_dev *indio_dev, @@ -209,15 +280,15 @@ static int vz89x_read_raw(struct iio_dev *indio_dev, if (ret) return ret; - switch (chan->address) { - case VZ89X_VOC_CO2_IDX: - case VZ89X_VOC_SHORT_IDX: - case VZ89X_VOC_TVOC_IDX: + switch (chan->type) { + case IIO_CONCENTRATION: *val = data->buffer[chan->address]; return IIO_VAL_INT; - case VZ89X_VOC_RESISTANCE_IDX: - *val = vz89x_get_resistance_reading(data); - return IIO_VAL_INT; + case IIO_RESISTANCE: + ret = vz89x_get_resistance_reading(data, chan, val); + if (!ret) + return IIO_VAL_INT; + break; default: return -EINVAL; } @@ -232,12 +303,12 @@ static int vz89x_read_raw(struct iio_dev *indio_dev, } break; case IIO_CHAN_INFO_OFFSET: - switch (chan->address) { - case VZ89X_VOC_CO2_IDX: + switch (chan->channel2) { + case IIO_MOD_CO2: *val = 44; *val2 = 250000; return IIO_VAL_INT_PLUS_MICRO; - case VZ89X_VOC_TVOC_IDX: + case IIO_MOD_VOC: *val = -13; return IIO_VAL_INT; default: @@ -265,10 +336,21 @@ static const struct vz89x_chip_data vz89x_chips[] = { .channels = vz89x_channels, .num_channels = ARRAY_SIZE(vz89x_channels), }, + { + .valid = vz89te_measurement_is_valid, + + .cmd = VZ89TE_REG_MEASUREMENT, + .read_size = VZ89TE_REG_MEASUREMENT_RD_SIZE, + .write_size = VZ89TE_REG_MEASUREMENT_WR_SIZE, + + .channels = vz89te_channels, + .num_channels = ARRAY_SIZE(vz89te_channels), + }, }; static const struct of_device_id vz89x_dt_ids[] = { { .compatible = "sgx,vz89x", .data = (void *) VZ89X }, + { .compatible = "sgx,vz89te", .data = (void *) VZ89TE }, { } }; MODULE_DEVICE_TABLE(of, vz89x_dt_ids); @@ -319,6 +401,7 @@ static int vz89x_probe(struct i2c_client *client, static const struct i2c_device_id vz89x_id[] = { { "vz89x", VZ89X }, + { "vz89te", VZ89TE }, { } }; MODULE_DEVICE_TABLE(i2c, vz89x_id); -- cgit v0.10.2 From 9d1894cd197e297c9ced5393fde6416324b7706d Mon Sep 17 00:00:00 2001 From: Matt Ranostay <mranostay@gmail.com> Date: Wed, 24 Aug 2016 23:44:49 -0700 Subject: iio: chemical: vz89x: prevent corrupted buffer from being read Signed-off-by: Matt Ranostay <mranostay@gmail.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/chemical/vz89x.c b/drivers/iio/chemical/vz89x.c index 289d291..cd3870e 100644 --- a/drivers/iio/chemical/vz89x.c +++ b/drivers/iio/chemical/vz89x.c @@ -55,6 +55,7 @@ struct vz89x_data { struct mutex lock; int (*xfer)(struct vz89x_data *data, u8 cmd); + bool is_valid; unsigned long last_update; u8 buffer[VZ89TE_REG_MEASUREMENT_RD_SIZE]; }; @@ -229,7 +230,10 @@ static int vz89x_get_measurement(struct vz89x_data *data) /* sensor can only be polled once a second max per datasheet */ if (!time_after(jiffies, data->last_update + HZ)) - return 0; + return data->is_valid ? 0 : -EAGAIN; + + data->is_valid = false; + data->last_update = jiffies; ret = data->xfer(data, chip->cmd); if (ret < 0) @@ -239,7 +243,7 @@ static int vz89x_get_measurement(struct vz89x_data *data) if (ret) return -EAGAIN; - data->last_update = jiffies; + data->is_valid = true; return 0; } -- cgit v0.10.2 From 7f270bc9a2d95967c09e759776a28a8d2a345c74 Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou <gwenhael.goavec-merou@trabucayre.com> Date: Wed, 24 Aug 2016 16:44:20 +0200 Subject: iio: dac: AD8801: add Analog Devices AD8801/AD8803 support Add support for Analog Devices AD8801/AD8803, 8 channels 8bits, Digital to Analog converters. Signed-off-by: Gwenhael Goavec-Merou <gwenhael.goavec-merou@trabucayre.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index b9f0442..e8656ba 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig @@ -190,6 +190,16 @@ config CIO_DAC base port addresses for the devices may be configured via the base array module parameter. +config AD8801 + tristate "Analog Devices AD8801/AD8803 DAC driver" + depends on SPI_MASTER + help + Say yes here to build support for Analog Devices AD8801, AD8803 Digital to + Analog Converters (DAC). + + To compile this driver as a module choose M here: the module will be called + ad8801. + config LPC18XX_DAC tristate "NXP LPC18xx DAC driver" depends on ARCH_LPC18XX || COMPILE_TEST diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile index b1a1206..c50dbe0 100644 --- a/drivers/iio/dac/Makefile +++ b/drivers/iio/dac/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_AD5764) += ad5764.o obj-$(CONFIG_AD5791) += ad5791.o obj-$(CONFIG_AD5686) += ad5686.o obj-$(CONFIG_AD7303) += ad7303.o +obj-$(CONFIG_AD8801) += ad8801.o obj-$(CONFIG_CIO_DAC) += cio-dac.o obj-$(CONFIG_LPC18XX_DAC) += lpc18xx_dac.o obj-$(CONFIG_M62332) += m62332.o diff --git a/drivers/iio/dac/ad8801.c b/drivers/iio/dac/ad8801.c new file mode 100644 index 0000000..f06faa1 --- /dev/null +++ b/drivers/iio/dac/ad8801.c @@ -0,0 +1,239 @@ +/* + * IIO DAC driver for Analog Devices AD8801 DAC + * + * Copyright (C) 2016 Gwenhael Goavec-Merou + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ + +#include <linux/iio/iio.h> +#include <linux/module.h> +#include <linux/regulator/consumer.h> +#include <linux/spi/spi.h> +#include <linux/sysfs.h> + +#define AD8801_CFG_ADDR_OFFSET 8 + +enum ad8801_device_ids { + ID_AD8801, + ID_AD8803, +}; + +struct ad8801_state { + struct spi_device *spi; + unsigned char dac_cache[8]; /* Value write on each channel */ + unsigned int vrefh_mv; + unsigned int vrefl_mv; + struct regulator *vrefh_reg; + struct regulator *vrefl_reg; + + __be16 data ____cacheline_aligned; +}; + +static int ad8801_spi_write(struct ad8801_state *state, + u8 channel, unsigned char value) +{ + state->data = cpu_to_be16((channel << AD8801_CFG_ADDR_OFFSET) | value); + return spi_write(state->spi, &state->data, sizeof(state->data)); +} + +static int ad8801_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, int val2, long mask) +{ + struct ad8801_state *state = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (val >= 256 || val < 0) + return -EINVAL; + + ret = ad8801_spi_write(state, chan->channel, val); + if (ret == 0) + state->dac_cache[chan->channel] = val; + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static int ad8801_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, int *val2, long info) +{ + struct ad8801_state *state = iio_priv(indio_dev); + + switch (info) { + case IIO_CHAN_INFO_RAW: + *val = state->dac_cache[chan->channel]; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = state->vrefh_mv - state->vrefl_mv; + *val2 = 8; + return IIO_VAL_FRACTIONAL_LOG2; + case IIO_CHAN_INFO_OFFSET: + *val = state->vrefl_mv; + return IIO_VAL_INT; + default: + return -EINVAL; + } + + return -EINVAL; +} + +static const struct iio_info ad8801_info = { + .read_raw = ad8801_read_raw, + .write_raw = ad8801_write_raw, + .driver_module = THIS_MODULE, +}; + +#define AD8801_CHANNEL(chan) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .output = 1, \ + .channel = chan, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_OFFSET), \ +} + +static const struct iio_chan_spec ad8801_channels[] = { + AD8801_CHANNEL(0), + AD8801_CHANNEL(1), + AD8801_CHANNEL(2), + AD8801_CHANNEL(3), + AD8801_CHANNEL(4), + AD8801_CHANNEL(5), + AD8801_CHANNEL(6), + AD8801_CHANNEL(7), +}; + +static int ad8801_probe(struct spi_device *spi) +{ + struct iio_dev *indio_dev; + struct ad8801_state *state; + const struct spi_device_id *id; + int ret; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*state)); + if (indio_dev == NULL) + return -ENOMEM; + + state = iio_priv(indio_dev); + state->spi = spi; + id = spi_get_device_id(spi); + + state->vrefh_reg = devm_regulator_get(&spi->dev, "vrefh"); + if (IS_ERR(state->vrefh_reg)) { + dev_err(&spi->dev, "Vrefh regulator not specified\n"); + return PTR_ERR(state->vrefh_reg); + } + + ret = regulator_enable(state->vrefh_reg); + if (ret) { + dev_err(&spi->dev, "Failed to enable vrefh regulator: %d\n", + ret); + return ret; + } + + ret = regulator_get_voltage(state->vrefh_reg); + if (ret < 0) { + dev_err(&spi->dev, "Failed to read vrefh regulator: %d\n", + ret); + goto error_disable_vrefh_reg; + } + state->vrefh_mv = ret / 1000; + + if (id->driver_data == ID_AD8803) { + state->vrefl_reg = devm_regulator_get(&spi->dev, "vrefl"); + if (IS_ERR(state->vrefl_reg)) { + dev_err(&spi->dev, "Vrefl regulator not specified\n"); + ret = PTR_ERR(state->vrefl_reg); + goto error_disable_vrefh_reg; + } + + ret = regulator_enable(state->vrefl_reg); + if (ret) { + dev_err(&spi->dev, "Failed to enable vrefl regulator: %d\n", + ret); + goto error_disable_vrefh_reg; + } + + ret = regulator_get_voltage(state->vrefl_reg); + if (ret < 0) { + dev_err(&spi->dev, "Failed to read vrefl regulator: %d\n", + ret); + goto error_disable_vrefl_reg; + } + state->vrefl_mv = ret / 1000; + } else { + state->vrefl_mv = 0; + state->vrefl_reg = NULL; + } + + spi_set_drvdata(spi, indio_dev); + indio_dev->dev.parent = &spi->dev; + indio_dev->info = &ad8801_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = ad8801_channels; + indio_dev->num_channels = ARRAY_SIZE(ad8801_channels); + indio_dev->name = id->name; + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(&spi->dev, "Failed to register iio device: %d\n", + ret); + goto error_disable_vrefl_reg; + } + + return 0; + +error_disable_vrefl_reg: + if (state->vrefl_reg) + regulator_disable(state->vrefl_reg); +error_disable_vrefh_reg: + regulator_disable(state->vrefh_reg); + return ret; +} + +static int ad8801_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct ad8801_state *state = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + if (state->vrefl_reg) + regulator_disable(state->vrefl_reg); + regulator_disable(state->vrefh_reg); + + return 0; +} + +static const struct spi_device_id ad8801_ids[] = { + {"ad8801", ID_AD8801}, + {"ad8803", ID_AD8803}, + {} +}; +MODULE_DEVICE_TABLE(spi, ad8801_ids); + +static struct spi_driver ad8801_driver = { + .driver = { + .name = "ad8801", + }, + .probe = ad8801_probe, + .remove = ad8801_remove, + .id_table = ad8801_ids, +}; +module_spi_driver(ad8801_driver); + +MODULE_AUTHOR("Gwenhael Goavec-Merou <gwenhael.goavec-merou@trabucayre.com>"); +MODULE_DESCRIPTION("Analog Devices AD8801/AD8803 DAC"); +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From aeb55fff3891834e07a3144159a7298a19696af8 Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Fri, 26 Aug 2016 00:10:08 +0200 Subject: iio: st_sensors: fetch and enable regulators unconditionally These sensors all have Vdd and Vdd_IO lines. This means the supplies are *not* optional (optional means that the supply is optional in the electrical sense, not the software sense) so we need to get the and enable them at all times. If the device tree or board file does not define suitable regulators for the component, it will be substituted by a dummy regulator, or, if regulators are disabled altogether, by stubs. There is no need to use the IS_ERR_OR_NULL() check that is considered harmful. Cc: Giuseppe Barba <giuseppe.barba@st.com> Cc: Denis Ciocca <denis.ciocca@st.com> Cc: Crestez Dan Leonard <leonard.crestez@intel.com> Cc: Gregor Boirie <gregor.boirie@parrot.com> Cc: Mark Brown <broonie@kernel.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c index 2d5282e..41bfe1c 100644 --- a/drivers/iio/common/st_sensors/st_sensors_core.c +++ b/drivers/iio/common/st_sensors/st_sensors_core.c @@ -234,39 +234,35 @@ int st_sensors_power_enable(struct iio_dev *indio_dev) int err; /* Regulators not mandatory, but if requested we should enable them. */ - pdata->vdd = devm_regulator_get_optional(indio_dev->dev.parent, "vdd"); - if (!IS_ERR(pdata->vdd)) { - err = regulator_enable(pdata->vdd); - if (err != 0) { - dev_warn(&indio_dev->dev, - "Failed to enable specified Vdd supply\n"); - return err; - } - } else { - err = PTR_ERR(pdata->vdd); - if (err != -ENODEV) - return err; + pdata->vdd = devm_regulator_get(indio_dev->dev.parent, "vdd"); + if (IS_ERR(pdata->vdd)) { + dev_err(&indio_dev->dev, "unable to get Vdd supply\n"); + return PTR_ERR(pdata->vdd); + } + err = regulator_enable(pdata->vdd); + if (err != 0) { + dev_warn(&indio_dev->dev, + "Failed to enable specified Vdd supply\n"); + return err; } - pdata->vdd_io = devm_regulator_get_optional(indio_dev->dev.parent, "vddio"); - if (!IS_ERR(pdata->vdd_io)) { - err = regulator_enable(pdata->vdd_io); - if (err != 0) { - dev_warn(&indio_dev->dev, - "Failed to enable specified Vdd_IO supply\n"); - goto st_sensors_disable_vdd; - } - } else { - err = PTR_ERR(pdata->vdd_io); - if (err != -ENODEV) - goto st_sensors_disable_vdd; + pdata->vdd_io = devm_regulator_get(indio_dev->dev.parent, "vddio"); + if (IS_ERR(pdata->vdd)) { + dev_err(&indio_dev->dev, "unable to get Vdd_IO supply\n"); + err = PTR_ERR(pdata->vdd); + goto st_sensors_disable_vdd; + } + err = regulator_enable(pdata->vdd_io); + if (err != 0) { + dev_warn(&indio_dev->dev, + "Failed to enable specified Vdd_IO supply\n"); + goto st_sensors_disable_vdd; } return 0; st_sensors_disable_vdd: - if (!IS_ERR_OR_NULL(pdata->vdd)) - regulator_disable(pdata->vdd); + regulator_disable(pdata->vdd); return err; } EXPORT_SYMBOL(st_sensors_power_enable); @@ -275,11 +271,8 @@ void st_sensors_power_disable(struct iio_dev *indio_dev) { struct st_sensor_data *pdata = iio_priv(indio_dev); - if (!IS_ERR_OR_NULL(pdata->vdd)) - regulator_disable(pdata->vdd); - - if (!IS_ERR_OR_NULL(pdata->vdd_io)) - regulator_disable(pdata->vdd_io); + regulator_disable(pdata->vdd); + regulator_disable(pdata->vdd_io); } EXPORT_SYMBOL(st_sensors_power_disable); -- cgit v0.10.2 From 16335bcbf920d9903778d942ec5e579b25984b4b Mon Sep 17 00:00:00 2001 From: Wei Yongjun <weiyongjun1@huawei.com> Date: Fri, 26 Aug 2016 14:33:20 +0000 Subject: iio: temperature: fix non static symbol warnings Fixes the following sparse warnings: drivers/iio/temperature/maxim_thermocouple.c:35:28: warning: symbol 'max6675_channels' was not declared. Should it be static? drivers/iio/temperature/maxim_thermocouple.c:52:28: warning: symbol 'max31855_channels' was not declared. Should it be static? drivers/iio/temperature/maxim_thermocouple.c:98:38: warning: symbol 'maxim_thermocouple_chips' was not declared. Should it be static? Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com> Reviewed-By: Matt Ranostay <mranostay@gmail.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/temperature/maxim_thermocouple.c b/drivers/iio/temperature/maxim_thermocouple.c index 030827e..39dd202 100644 --- a/drivers/iio/temperature/maxim_thermocouple.c +++ b/drivers/iio/temperature/maxim_thermocouple.c @@ -32,7 +32,7 @@ enum { MAX31855, }; -const struct iio_chan_spec max6675_channels[] = { +static const struct iio_chan_spec max6675_channels[] = { { /* thermocouple temperature */ .type = IIO_TEMP, .info_mask_separate = @@ -49,7 +49,7 @@ const struct iio_chan_spec max6675_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(1), }; -const struct iio_chan_spec max31855_channels[] = { +static const struct iio_chan_spec max31855_channels[] = { { /* thermocouple temperature */ .type = IIO_TEMP, .address = 2, @@ -95,7 +95,7 @@ struct maxim_thermocouple_chip { u32 status_bit; }; -const struct maxim_thermocouple_chip maxim_thermocouple_chips[] = { +static const struct maxim_thermocouple_chip maxim_thermocouple_chips[] = { [MAX6675] = { .channels = max6675_channels, .num_channels = ARRAY_SIZE(max6675_channels), -- cgit v0.10.2 From 943bbe743ce4c2846c41812186411841b0c9d7a1 Mon Sep 17 00:00:00 2001 From: Wei Yongjun <weiyongjun1@huawei.com> Date: Fri, 26 Aug 2016 14:31:50 +0000 Subject: iio: adc: ti-ads1015: add missing of_node_put() in ads1015_get_channels_config_of() When terminating for_each_child_of_node() iteration with break or return, of_node_put() should be used to prevent stale device node references from being left behind. This is detected by Coccinelle semantic patch. Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c index 1ef39877..565e843 100644 --- a/drivers/iio/adc/ti-ads1015.c +++ b/drivers/iio/adc/ti-ads1015.c @@ -521,6 +521,7 @@ static int ads1015_get_channels_config_of(struct i2c_client *client) if (pga > 6) { dev_err(&client->dev, "invalid gain on %s\n", node->full_name); + of_node_put(node); return -EINVAL; } } @@ -531,6 +532,7 @@ static int ads1015_get_channels_config_of(struct i2c_client *client) dev_err(&client->dev, "invalid data_rate on %s\n", node->full_name); + of_node_put(node); return -EINVAL; } } -- cgit v0.10.2 From 2e1f44d8a7724e889f1a4f211aad13320cb80f1f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann <arnd@arndb.de> Date: Fri, 26 Aug 2016 17:29:35 +0200 Subject: iio: hid-sensors: avoid unused function warning A small rework of the PM code in this driver introduced a harmless warning when CONFIG_PM_SLEEP is not set: drivers/iio/common/hid-sensors/hid-sensor-trigger.c:212:12: error: 'hid_sensor_resume' defined but not used [-Werror=unused-function] This removes the #ifdef and instead marks all three PM functions as __maybe_unused, which covers all possible cases and is harder to get wrong. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Fixes: 7f6cf7414538 ("iio: hid-sensors: use asynchronous resume") Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c index 5264ed6..a3cce3a 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c @@ -199,8 +199,7 @@ error_ret: } EXPORT_SYMBOL(hid_sensor_setup_trigger); -#ifdef CONFIG_PM -static int hid_sensor_suspend(struct device *dev) +static int __maybe_unused hid_sensor_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct iio_dev *indio_dev = platform_get_drvdata(pdev); @@ -209,7 +208,7 @@ static int hid_sensor_suspend(struct device *dev) return _hid_sensor_power_state(attrb, false); } -static int hid_sensor_resume(struct device *dev) +static int __maybe_unused hid_sensor_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct iio_dev *indio_dev = platform_get_drvdata(pdev); @@ -218,7 +217,7 @@ static int hid_sensor_resume(struct device *dev) return 0; } -static int hid_sensor_runtime_resume(struct device *dev) +static int __maybe_unused hid_sensor_runtime_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct iio_dev *indio_dev = platform_get_drvdata(pdev); @@ -226,8 +225,6 @@ static int hid_sensor_runtime_resume(struct device *dev) return _hid_sensor_power_state(attrb, true); } -#endif - const struct dev_pm_ops hid_sensor_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(hid_sensor_suspend, hid_sensor_resume) SET_RUNTIME_PM_OPS(hid_sensor_suspend, -- cgit v0.10.2 From 5bc55ef31f710326f541e6a3c726526815dd48e6 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann <arnd@arndb.de> Date: Fri, 26 Aug 2016 17:31:19 +0200 Subject: iio: magn/ak8974: avoid unused function warning The ak8974_configure() function is used only from the PM code, but that can be hidden when CONFIG_PM is disabled: drivers/iio/magnetometer/ak8974.c:201:12: error: 'ak8974_configure' defined but not used [-Werror=unused-function] This replaces the #ifdef with a __maybe_unused annotation, which will work correctly in all configurations and avoid the warning, as the compiler can now see where ak8974_configure is called from. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Fixes: 7c94a8b2ee8c ("iio: magn: add a driver for AK8974") Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/magnetometer/ak8974.c b/drivers/iio/magnetometer/ak8974.c index e70e4e2..12bd17b 100644 --- a/drivers/iio/magnetometer/ak8974.c +++ b/drivers/iio/magnetometer/ak8974.c @@ -783,8 +783,7 @@ static int __exit ak8974_remove(struct i2c_client *i2c) return 0; } -#ifdef CONFIG_PM -static int ak8974_runtime_suspend(struct device *dev) +static int __maybe_unused ak8974_runtime_suspend(struct device *dev) { struct ak8974 *ak8974 = iio_priv(i2c_get_clientdata(to_i2c_client(dev))); @@ -795,7 +794,7 @@ static int ak8974_runtime_suspend(struct device *dev) return 0; } -static int ak8974_runtime_resume(struct device *dev) +static int __maybe_unused ak8974_runtime_resume(struct device *dev) { struct ak8974 *ak8974 = iio_priv(i2c_get_clientdata(to_i2c_client(dev))); @@ -822,7 +821,6 @@ out_regulator_disable: return ret; } -#endif /* CONFIG_PM */ static const struct dev_pm_ops ak8974_dev_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, -- cgit v0.10.2 From 96303e20270af6e7ac9d7d98b9c68e3288d4b6ba Mon Sep 17 00:00:00 2001 From: Wei Yongjun <weiyongjun1@huawei.com> Date: Fri, 26 Aug 2016 14:32:29 +0000 Subject: iio: magn: ak8974: remove .owner field for driver Remove .owner field if calls are used which set it automatically. Generated by: scripts/coccinelle/api/platform_no_drv_owner.cocci Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com> Acked-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/magnetometer/ak8974.c b/drivers/iio/magnetometer/ak8974.c index 12bd17b..2173531 100644 --- a/drivers/iio/magnetometer/ak8974.c +++ b/drivers/iio/magnetometer/ak8974.c @@ -845,7 +845,6 @@ MODULE_DEVICE_TABLE(of, ak8974_of_match); static struct i2c_driver ak8974_driver = { .driver = { .name = "ak8974", - .owner = THIS_MODULE, .pm = &ak8974_dev_pm_ops, .of_match_table = of_match_ptr(ak8974_of_match), }, -- cgit v0.10.2 From a565a03faff90b634bf523f104389b540cfcb226 Mon Sep 17 00:00:00 2001 From: Baoyou Xie <baoyou.xie@linaro.org> Date: Sat, 27 Aug 2016 14:26:30 +0800 Subject: fix:iio:common:st_sensors:st_sensors_trigger:mark symbols static where possible We get 2 warnings when biuld kernel with W=1: drivers/iio/common/st_sensors/st_sensors_trigger.c:69:13: warning: no previous prototype for 'st_sensors_irq_handler' [-Wmissing-prototypes] drivers/iio/common/st_sensors/st_sensors_trigger.c:85:13: warning: no previous prototype for 'st_sensors_irq_thread' [-Wmissing-prototypes] In fact, these functions are only used in the file in which they are declared and don't need a declaration, but can be made static. so this patch marks these functions with 'static'. Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/common/st_sensors/st_sensors_trigger.c b/drivers/iio/common/st_sensors/st_sensors_trigger.c index e66f12e..fa73e67 100644 --- a/drivers/iio/common/st_sensors/st_sensors_trigger.c +++ b/drivers/iio/common/st_sensors/st_sensors_trigger.c @@ -66,7 +66,7 @@ static int st_sensors_new_samples_available(struct iio_dev *indio_dev, * @irq: irq number * @p: private handler data */ -irqreturn_t st_sensors_irq_handler(int irq, void *p) +static irqreturn_t st_sensors_irq_handler(int irq, void *p) { struct iio_trigger *trig = p; struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); @@ -82,7 +82,7 @@ irqreturn_t st_sensors_irq_handler(int irq, void *p) * @irq: irq number * @p: private handler data */ -irqreturn_t st_sensors_irq_thread(int irq, void *p) +static irqreturn_t st_sensors_irq_thread(int irq, void *p) { struct iio_trigger *trig = p; struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); -- cgit v0.10.2 From 2d6d840a5a93c9493554d36cacabac797b441972 Mon Sep 17 00:00:00 2001 From: Vlad Dogaru <vlad.dogaru@intel.com> Date: Mon, 29 Aug 2016 13:31:13 +0300 Subject: mailmap: update Vlad Dogaru email address Replace my previous employer address. Signed-off-by: Vlad Dogaru <vlad.dogaru@intel.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/.mailmap b/.mailmap index 2a91c14..89a2f94 100644 --- a/.mailmap +++ b/.mailmap @@ -158,6 +158,7 @@ Valdis Kletnieks <Valdis.Kletnieks@vt.edu> Viresh Kumar <vireshk@kernel.org> <viresh.kumar@st.com> Viresh Kumar <vireshk@kernel.org> <viresh.linux@gmail.com> Viresh Kumar <vireshk@kernel.org> <viresh.kumar2@arm.com> +Vlad Dogaru <ddvlad@gmail.com> <vlad.dogaru@intel.com> Takashi YOSHII <takashi.yoshii.zj@renesas.com> Yusuke Goda <goda.yusuke@renesas.com> Gustavo Padovan <gustavo@las.ic.unicamp.br> -- cgit v0.10.2 From e7a69540e11ba30458f28764758f372d9d80abb4 Mon Sep 17 00:00:00 2001 From: Randy Dunlap <rdunlap@infradead.org> Date: Tue, 23 Aug 2016 13:07:52 -0700 Subject: staging: octeon-usb: correct driver name in Kconfig help text The module name in the Makefile and in the driver source file is octeon-hcd, so correct the Kconfig text to be the same. Signed-off-by: Randy Dunlap <rdunlap@infradead.org> Cc: Aaro Koskinen <aaro.koskinen@iki.fi> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/octeon-usb/Kconfig b/drivers/staging/octeon-usb/Kconfig index 16ea17f..0b8f1d9 100644 --- a/drivers/staging/octeon-usb/Kconfig +++ b/drivers/staging/octeon-usb/Kconfig @@ -6,5 +6,5 @@ config OCTEON_USB Networks' products in the Octeon family. To compile this driver as a module, choose M here. The module - will be called octeon-usb. + will be called octeon-hcd. -- cgit v0.10.2 From 3b1d75332ea7e397d8127b8d39d1f59ed60e49d2 Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Mon, 22 Aug 2016 13:11:03 -0400 Subject: staging: vt6656: usbpipe.c: Fix checkpatch warning Fix checkpatch.pl warning for line over 80 characters Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c index f546553..e9b6b21 100644 --- a/drivers/staging/vt6656/usbpipe.c +++ b/drivers/staging/vt6656/usbpipe.c @@ -28,8 +28,9 @@ * vnt_control_in_u8 - Read one byte from MEM/BB/MAC/EEPROM * * Revision History: - * 04-05-2004 Jerry Chen: Initial release - * 11-24-2004 Warren Hsu: Add ControlvWriteByte,ControlvReadByte,ControlvMaskByte + * 04-05-2004 Jerry Chen: Initial release + * 11-24-2004 Warren Hsu: Add ControlvWriteByte,ControlvReadByte, + * ControlvMaskByte * */ -- cgit v0.10.2 From b91796e86b30ffa8e01f4b06f7a81e724c760b6d Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Date: Tue, 23 Aug 2016 19:43:21 +0530 Subject: staging: i4l: icn: use memdup_user Its better to use memdup_user which does the same thing which this code has implemented. Also removed a related warning as we will be warned if allocation fails. Suggested-by: Fengguang Wu <fengguang.wu@intel.com> Signed-off-by: Sudip Mukherjee <sudip.mukherjee@codethink.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/i4l/icn/icn.c b/drivers/staging/i4l/icn/icn.c index b2f4055..415124f 100644 --- a/drivers/staging/i4l/icn/icn.c +++ b/drivers/staging/i4l/icn/icn.c @@ -810,16 +810,10 @@ icn_loadboot(u_char __user *buffer, icn_card *card) #ifdef BOOT_DEBUG printk(KERN_DEBUG "icn_loadboot called, buffaddr=%08lx\n", (ulong) buffer); #endif - codebuf = kmalloc(ICN_CODE_STAGE1, GFP_KERNEL); - if (!codebuf) { - printk(KERN_WARNING "icn: Could not allocate code buffer\n"); - ret = -ENOMEM; - goto out; - } - if (copy_from_user(codebuf, buffer, ICN_CODE_STAGE1)) { - ret = -EFAULT; - goto out_kfree; - } + codebuf = memdup_user(buffer, ICN_CODE_STAGE1); + if (IS_ERR(codebuf)) + return PTR_ERR(codebuf); + if (!card->rvalid) { if (!request_region(card->port, ICN_PORTLEN, card->regname)) { printk(KERN_WARNING @@ -902,7 +896,6 @@ icn_loadboot(u_char __user *buffer, icn_card *card) out_kfree: kfree(codebuf); -out: return ret; } -- cgit v0.10.2 From f775252f4bae4123e5e76ad4ccefa6e42d1856b9 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Date: Mon, 22 Aug 2016 22:04:54 +0530 Subject: staging: i4l: act2000: remove unused argument The macro EVAL_NCCI was only being used in capi.c and the argument controller was not used. Remove the argument and at the same time remove the variable which now becomes unused. Signed-off-by: Sudip Mukherjee <sudip.mukherjee@codethink.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/i4l/act2000/capi.c b/drivers/staging/i4l/act2000/capi.c index 3f66ca2..41b4d19 100644 --- a/drivers/staging/i4l/act2000/capi.c +++ b/drivers/staging/i4l/act2000/capi.c @@ -547,12 +547,11 @@ static int actcapi_data_b3_ind(act2000_card *card, struct sk_buff *skb) { __u16 plci; __u16 ncci; - __u16 controller; __u8 blocknr; int chan; actcapi_msg *msg = (actcapi_msg *)skb->data; - EVAL_NCCI(msg->msg.data_b3_ind.fakencci, plci, controller, ncci); + EVAL_NCCI(msg->msg.data_b3_ind.fakencci, plci, ncci); chan = find_ncci(card, ncci); if (chan < 0) return 0; diff --git a/drivers/staging/i4l/act2000/capi.h b/drivers/staging/i4l/act2000/capi.h index 01ccdec..7d0f52d 100644 --- a/drivers/staging/i4l/act2000/capi.h +++ b/drivers/staging/i4l/act2000/capi.h @@ -114,9 +114,8 @@ typedef struct actcapi_ncpd { #define MAKE_NCCI(plci, contr, ncci) \ ((plci & 0x1f) | ((contr & 0x7) << 5) | ((ncci & 0xff) << 8)) -#define EVAL_NCCI(fakencci, plci, contr, ncci) { \ +#define EVAL_NCCI(fakencci, plci, ncci) { \ plci = fakencci & 0x1f; \ - contr = (fakencci >> 5) & 0x7; \ ncci = (fakencci >> 8) & 0xff; \ } -- cgit v0.10.2 From eb07d11ea215027426d60b7d0604acf92bc27799 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Date: Mon, 22 Aug 2016 22:04:55 +0530 Subject: staging: i4l: act2000: remove unused macro The macro EVAL_PLCI and MAKE_PLCI are not being used. Remove them. But keep the comment preceding them as it contains information regarding message format. Signed-off-by: Sudip Mukherjee <sudip.mukherjee@codethink.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/i4l/act2000/capi.h b/drivers/staging/i4l/act2000/capi.h index 7d0f52d..34884a5 100644 --- a/drivers/staging/i4l/act2000/capi.h +++ b/drivers/staging/i4l/act2000/capi.h @@ -127,13 +127,6 @@ typedef struct actcapi_ncpd { * Bit 5-7 = Controller * Bit 8-15 = reserved (must be 0) */ -#define MAKE_PLCI(plci, contr) \ - ((plci & 0x1f) | ((contr & 0x7) << 5)) - -#define EVAL_PLCI(fakeplci, plci, contr) { \ - plci = fakeplci & 0x1f; \ - contr = (fakeplci >> 5) & 0x7; \ - } typedef struct actcapi_msg { actcapi_msghdr hdr; -- cgit v0.10.2 From bd70aef0a8b776bba206f693c3d1078f944d825b Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Date: Mon, 22 Aug 2016 22:04:56 +0530 Subject: staging: i4l: icn: space not needed after cast No need provide a space after a typecast. Signed-off-by: Sudip Mukherjee <sudip.mukherjee@codethink.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/i4l/icn/icn.c b/drivers/staging/i4l/icn/icn.c index 415124f..6f84eea 100644 --- a/drivers/staging/i4l/icn/icn.c +++ b/drivers/staging/i4l/icn/icn.c @@ -87,7 +87,7 @@ icn_shiftout(unsigned short port, register u_char c; for (s = firstbit, c = bitcount; c > 0; s--, c--) - OUTB_P((u_char) ((val >> s) & 1) ? 0xff : 0, port); + OUTB_P((u_char)((val >> s) & 1) ? 0xff : 0, port); } /* @@ -385,7 +385,7 @@ icn_pollbchan_send(int channel, icn_card *card) static void icn_pollbchan(unsigned long data) { - icn_card *card = (icn_card *) data; + icn_card *card = (icn_card *)data; unsigned long flags; if (card->flags & ICN_FLAGS_B1ACTIVE) { @@ -547,7 +547,7 @@ icn_parse_status(u_char *status, int channel, icn_card *card) break; case 6: snprintf(cmd.parm.num, sizeof(cmd.parm.num), "%d", - (int) simple_strtoul(status + 7, NULL, 16)); + (int)simple_strtoul(status + 7, NULL, 16)); break; case 7: status += 3; @@ -607,7 +607,7 @@ icn_putmsg(icn_card *card, unsigned char c) static void icn_polldchan(unsigned long data) { - icn_card *card = (icn_card *) data; + icn_card *card = (icn_card *)data; int mch = card->secondhalf ? 2 : 0; int avail = 0; int left; @@ -659,7 +659,7 @@ icn_polldchan(unsigned long data) *q = '\0'; strcat(vstr, "000"); vstr[3] = '\0'; - card->fw_rev = (int) simple_strtoul(vstr, NULL, 10); + card->fw_rev = (int)simple_strtoul(vstr, NULL, 10); continue; } @@ -686,7 +686,7 @@ icn_polldchan(unsigned long data) card->flags |= ICN_FLAGS_RBTIMER; del_timer(&card->rb_timer); card->rb_timer.function = icn_pollbchan; - card->rb_timer.data = (unsigned long) card; + card->rb_timer.data = (unsigned long)card; card->rb_timer.expires = jiffies + ICN_TIMER_BCREAD; add_timer(&card->rb_timer); } @@ -808,7 +808,7 @@ icn_loadboot(u_char __user *buffer, icn_card *card) unsigned long flags; #ifdef BOOT_DEBUG - printk(KERN_DEBUG "icn_loadboot called, buffaddr=%08lx\n", (ulong) buffer); + printk(KERN_DEBUG "icn_loadboot called, buffaddr=%08lx\n", (ulong)buffer); #endif codebuf = memdup_user(buffer, ICN_CODE_STAGE1); if (IS_ERR(codebuf)) @@ -1186,28 +1186,28 @@ icn_command(isdn_ctrl *c, icn_card *card) } break; case ICN_IOCTL_GETMMIO: - return (long) dev.memaddr; + return (long)dev.memaddr; case ICN_IOCTL_SETPORT: if (a == 0x300 || a == 0x310 || a == 0x320 || a == 0x330 || a == 0x340 || a == 0x350 || a == 0x360 || a == 0x308 || a == 0x318 || a == 0x328 || a == 0x338 || a == 0x348 || a == 0x358 || a == 0x368) { - if (card->port != (unsigned short) a) { - if (!request_region((unsigned short) a, ICN_PORTLEN, "icn-isdn")) { + if (card->port != (unsigned short)a) { + if (!request_region((unsigned short)a, ICN_PORTLEN, "icn-isdn")) { printk(KERN_WARNING "icn: (%s) ports 0x%03x-0x%03x in use.\n", - CID, (int) a, (int) a + ICN_PORTLEN); + CID, (int)a, (int)a + ICN_PORTLEN); return -EINVAL; } - release_region((unsigned short) a, ICN_PORTLEN); + release_region((unsigned short)a, ICN_PORTLEN); icn_stopcard(card); spin_lock_irqsave(&card->lock, flags); if (card->rvalid) release_region(card->port, ICN_PORTLEN); - card->port = (unsigned short) a; + card->port = (unsigned short)a; card->rvalid = 0; if (card->doubleS0) { - card->other->port = (unsigned short) a; + card->other->port = (unsigned short)a; card->other->rvalid = 0; } spin_unlock_irqrestore(&card->lock, flags); @@ -1219,9 +1219,9 @@ icn_command(isdn_ctrl *c, icn_card *card) return -EINVAL; break; case ICN_IOCTL_GETPORT: - return (int) card->port; + return (int)card->port; case ICN_IOCTL_GETDOUBLE: - return (int) card->doubleS0; + return (int)card->doubleS0; case ICN_IOCTL_DEBUGVAR: if (copy_to_user(arg, &card, @@ -1317,7 +1317,7 @@ icn_command(isdn_ctrl *c, icn_card *card) /* Normal Dial */ strcpy(dcode, "CAL"); snprintf(cbuf, sizeof(cbuf), - "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1), + "%02d;D%s_R%s,%02d,%02d,%s\n", (int)(a + 1), dcode, p, c->parm.setup.si1, c->parm.setup.si2, c->parm.setup.eazmsn); i = icn_writecmd(cbuf, strlen(cbuf), 0, card); @@ -1331,15 +1331,15 @@ icn_command(isdn_ctrl *c, icn_card *card) if (card->fw_rev >= 300) { switch (card->l2_proto[a - 1]) { case ISDN_PROTO_L2_X75I: - sprintf(cbuf, "%02d;BX75\n", (int) a); + sprintf(cbuf, "%02d;BX75\n", (int)a); break; case ISDN_PROTO_L2_HDLC: - sprintf(cbuf, "%02d;BTRA\n", (int) a); + sprintf(cbuf, "%02d;BTRA\n", (int)a); break; } i = icn_writecmd(cbuf, strlen(cbuf), 0, card); } - sprintf(cbuf, "%02d;DCON_R\n", (int) a); + sprintf(cbuf, "%02d;DCON_R\n", (int)a); i = icn_writecmd(cbuf, strlen(cbuf), 0, card); } break; @@ -1351,13 +1351,13 @@ icn_command(isdn_ctrl *c, icn_card *card) if (card->fw_rev >= 300) switch (card->l2_proto[a - 1]) { case ISDN_PROTO_L2_X75I: - sprintf(cbuf, "%02d;BCON_R,BX75\n", (int) a); + sprintf(cbuf, "%02d;BCON_R,BX75\n", (int)a); break; case ISDN_PROTO_L2_HDLC: - sprintf(cbuf, "%02d;BCON_R,BTRA\n", (int) a); + sprintf(cbuf, "%02d;BCON_R,BTRA\n", (int)a); break; } else - sprintf(cbuf, "%02d;BCON_R\n", (int) a); + sprintf(cbuf, "%02d;BCON_R\n", (int)a); i = icn_writecmd(cbuf, strlen(cbuf), 0, card); } break; @@ -1366,7 +1366,7 @@ icn_command(isdn_ctrl *c, icn_card *card) return -ENODEV; if (c->arg < ICN_BCH) { a = c->arg + 1; - sprintf(cbuf, "%02d;BDIS_R\n%02d;DDIS_R\n", (int) a, (int) a); + sprintf(cbuf, "%02d;BDIS_R\n%02d;DDIS_R\n", (int)a, (int)a); i = icn_writecmd(cbuf, strlen(cbuf), 0, card); } break; @@ -1378,10 +1378,10 @@ icn_command(isdn_ctrl *c, icn_card *card) if (c->arg < ICN_BCH) { a = c->arg + 1; if (card->ptype == ISDN_PTYPE_EURO) { - sprintf(cbuf, "%02d;MS%s%s\n", (int) a, + sprintf(cbuf, "%02d;MS%s%s\n", (int)a, c->parm.num[0] ? "N" : "ALL", c->parm.num); } else - sprintf(cbuf, "%02d;EAZ%s\n", (int) a, + sprintf(cbuf, "%02d;EAZ%s\n", (int)a, c->parm.num[0] ? (char *)(c->parm.num) : "0123456789"); i = icn_writecmd(cbuf, strlen(cbuf), 0, card); } @@ -1394,9 +1394,9 @@ icn_command(isdn_ctrl *c, icn_card *card) if (c->arg < ICN_BCH) { a = c->arg + 1; if (card->ptype == ISDN_PTYPE_EURO) - sprintf(cbuf, "%02d;MSNC\n", (int) a); + sprintf(cbuf, "%02d;MSNC\n", (int)a); else - sprintf(cbuf, "%02d;EAZC\n", (int) a); + sprintf(cbuf, "%02d;EAZC\n", (int)a); i = icn_writecmd(cbuf, strlen(cbuf), 0, card); } break; @@ -1407,10 +1407,10 @@ icn_command(isdn_ctrl *c, icn_card *card) a = c->arg; switch (a >> 8) { case ISDN_PROTO_L2_X75I: - sprintf(cbuf, "%02d;BX75\n", (int) (a & 255) + 1); + sprintf(cbuf, "%02d;BX75\n", (int)(a & 255) + 1); break; case ISDN_PROTO_L2_HDLC: - sprintf(cbuf, "%02d;BTRA\n", (int) (a & 255) + 1); + sprintf(cbuf, "%02d;BTRA\n", (int)(a & 255) + 1); break; default: return -EINVAL; @@ -1442,7 +1442,7 @@ icn_findcard(int driverid) return p; p = p->next; } - return (icn_card *) 0; + return (icn_card *)0; } /* @@ -1520,7 +1520,7 @@ icn_initcard(int port, char *id) if (!card) { printk(KERN_WARNING "icn: (%s) Could not allocate card-struct.\n", id); - return (icn_card *) 0; + return (icn_card *)0; } spin_lock_init(&card->lock); card->port = port; @@ -1552,7 +1552,7 @@ icn_initcard(int port, char *id) printk(KERN_WARNING "icn: Unable to register %s\n", id); kfree(card); - return (icn_card *) 0; + return (icn_card *)0; } card->myid = card->interface.channels; sprintf(card->regname, "icn-isdn (%s)", card->interface.id); -- cgit v0.10.2 From 1b30c21fd8abeb58e852c2a4dbaf6b4f45addb64 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Date: Mon, 22 Aug 2016 22:04:57 +0530 Subject: staging: i4l: icn: remove blank lines Blank lines are not needed after starting brace or before a closing brace. Signed-off-by: Sudip Mukherjee <sudip.mukherjee@codethink.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/i4l/icn/icn.c b/drivers/staging/i4l/icn/icn.c index 6f84eea..25c9de5 100644 --- a/drivers/staging/i4l/icn/icn.c +++ b/drivers/staging/i4l/icn/icn.c @@ -82,7 +82,6 @@ icn_shiftout(unsigned short port, int firstbit, int bitcount) { - register u_char s; register u_char c; @@ -475,7 +474,6 @@ icn_parse_status(u_char *status, int channel, icn_card *card) if (card->flags & ((channel) ? ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE)) { - isdn_ctrl ncmd; card->flags &= ~((channel) ? @@ -661,7 +659,6 @@ icn_polldchan(unsigned long data) vstr[3] = '\0'; card->fw_rev = (int)simple_strtoul(vstr, NULL, 10); continue; - } } } else { -- cgit v0.10.2 From 8a0b09d90574aef3bf6269f03a5c7a9d005474de Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Date: Mon, 22 Aug 2016 22:04:58 +0530 Subject: staging: i4l: icn: fix incorrect type of arguments sparse was warning about incorrect type of argument: drivers/staging/i4l/icn/icn.c:1048:49: warning: incorrect type in argument 2 (different address spaces) drivers/staging/i4l/icn/icn.c:1048:49: expected void const [noderef] <asn:1>*from drivers/staging/i4l/icn/icn.c:1048:49: got unsigned char const [usertype] *buf drivers/staging/i4l/icn/icn.c:1476:38: warning: incorrect type in argument 1 (different address spaces) drivers/staging/i4l/icn/icn.c:1476:38: expected unsigned char const [usertype] *buf drivers/staging/i4l/icn/icn.c:1476:38: got unsigned char const [noderef] [usertype] <asn:1>*buf The function icn_writecmd() was used to copy from userspace and also from the kernelspace. Add another argument to the function to have two separate pointers, one for the userspace and one for the kernelspace. Based on the value of user as passed from the caller we use one of the two pointers. Signed-off-by: Sudip Mukherjee <sudip.mukherjee@codethink.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/i4l/icn/icn.c b/drivers/staging/i4l/icn/icn.c index 25c9de5..514bfc2 100644 --- a/drivers/staging/i4l/icn/icn.c +++ b/drivers/staging/i4l/icn/icn.c @@ -1015,7 +1015,8 @@ icn_readstatus(u_char __user *buf, int len, icn_card *card) /* Put command-strings into the command-queue of the Interface */ static int -icn_writecmd(const u_char *buf, int len, int user, icn_card *card) +icn_writecmd(const u_char __user *ubuf, const u_char *kbuf, int len, + int user, icn_card *card) { int mch = card->secondhalf ? 2 : 0; int pp; @@ -1038,10 +1039,10 @@ icn_writecmd(const u_char *buf, int len, int user, icn_card *card) if (count > len) count = len; if (user) { - if (copy_from_user(msg, buf, count)) + if (copy_from_user(msg, ubuf, count)) return -EFAULT; } else - memcpy(msg, buf, count); + memcpy(msg, kbuf, count); spin_lock_irqsave(&dev.devlock, flags); lastmap_card = dev.mcard; @@ -1267,7 +1268,9 @@ icn_command(isdn_ctrl *c, icn_card *card) msleep_interruptible(ICN_BOOT_TIMEOUT1); sprintf(cbuf, "00;FV2ON\n01;EAZ%c\n02;EAZ%c\n", (a & 1) ? '1' : 'C', (a & 2) ? '2' : 'C'); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); + i = icn_writecmd(NULL, cbuf, + strlen(cbuf), + 0, card); printk(KERN_INFO "icn: (%s) Leased-line mode enabled\n", CID); @@ -1280,7 +1283,9 @@ icn_command(isdn_ctrl *c, icn_card *card) if (card->leased) { card->leased = 0; sprintf(cbuf, "00;FV2OFF\n"); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); + i = icn_writecmd(NULL, cbuf, + strlen(cbuf), + 0, card); printk(KERN_INFO "icn: (%s) Leased-line mode disabled\n", CID); @@ -1317,7 +1322,7 @@ icn_command(isdn_ctrl *c, icn_card *card) "%02d;D%s_R%s,%02d,%02d,%s\n", (int)(a + 1), dcode, p, c->parm.setup.si1, c->parm.setup.si2, c->parm.setup.eazmsn); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); + i = icn_writecmd(NULL, cbuf, strlen(cbuf), 0, card); } break; case ISDN_CMD_ACCEPTD: @@ -1334,10 +1339,12 @@ icn_command(isdn_ctrl *c, icn_card *card) sprintf(cbuf, "%02d;BTRA\n", (int)a); break; } - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); + i = icn_writecmd(NULL, cbuf, + strlen(cbuf), 0, + card); } sprintf(cbuf, "%02d;DCON_R\n", (int)a); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); + i = icn_writecmd(NULL, cbuf, strlen(cbuf), 0, card); } break; case ISDN_CMD_ACCEPTB: @@ -1355,7 +1362,7 @@ icn_command(isdn_ctrl *c, icn_card *card) break; } else sprintf(cbuf, "%02d;BCON_R\n", (int)a); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); + i = icn_writecmd(NULL, cbuf, strlen(cbuf), 0, card); } break; case ISDN_CMD_HANGUP: @@ -1364,7 +1371,7 @@ icn_command(isdn_ctrl *c, icn_card *card) if (c->arg < ICN_BCH) { a = c->arg + 1; sprintf(cbuf, "%02d;BDIS_R\n%02d;DDIS_R\n", (int)a, (int)a); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); + i = icn_writecmd(NULL, cbuf, strlen(cbuf), 0, card); } break; case ISDN_CMD_SETEAZ: @@ -1380,7 +1387,7 @@ icn_command(isdn_ctrl *c, icn_card *card) } else sprintf(cbuf, "%02d;EAZ%s\n", (int)a, c->parm.num[0] ? (char *)(c->parm.num) : "0123456789"); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); + i = icn_writecmd(NULL, cbuf, strlen(cbuf), 0, card); } break; case ISDN_CMD_CLREAZ: @@ -1394,7 +1401,7 @@ icn_command(isdn_ctrl *c, icn_card *card) sprintf(cbuf, "%02d;MSNC\n", (int)a); else sprintf(cbuf, "%02d;EAZC\n", (int)a); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); + i = icn_writecmd(NULL, cbuf, strlen(cbuf), 0, card); } break; case ISDN_CMD_SETL2: @@ -1412,7 +1419,7 @@ icn_command(isdn_ctrl *c, icn_card *card) default: return -EINVAL; } - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); + i = icn_writecmd(NULL, cbuf, strlen(cbuf), 0, card); card->l2_proto[a & 255] = (a >> 8); } break; @@ -1466,7 +1473,7 @@ if_writecmd(const u_char __user *buf, int len, int id, int channel) if (card) { if (!(card->flags & ICN_FLAGS_RUNNING)) return -ENODEV; - return icn_writecmd(buf, len, 1, card); + return icn_writecmd(buf, NULL, len, 1, card); } printk(KERN_ERR "icn: if_writecmd called with invalid driverId!\n"); -- cgit v0.10.2 From 5d2b7c4a9dd649316e00bd320a05341d4b00ee33 Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Fri, 26 Aug 2016 23:23:57 -0400 Subject: staging: i4l: act2000: capi: Fix checkpatch warning Fix checkpath.pl warning: trailing statements should be on next line open brace '{' following function declarations go on the next line Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/i4l/act2000/capi.c b/drivers/staging/i4l/act2000/capi.c index 41b4d19..bf04e6f 100644 --- a/drivers/staging/i4l/act2000/capi.c +++ b/drivers/staging/i4l/act2000/capi.c @@ -113,7 +113,9 @@ actcapi_chkhdr(act2000_card *card, actcapi_msghdr *hdr) m->hdr.cmd.cmd = c; \ m->hdr.cmd.subcmd = s; \ m->hdr.msgnum = actcapi_nextsmsg(card); \ - } else m = NULL; \ + } else { \ + m = NULL; \ + } \ } #define ACTCAPI_CHKSKB if (!skb) { \ @@ -989,7 +991,8 @@ actcapi_debug_dlpd(actcapi_dlpd *dlpd) } #ifdef DEBUG_DUMP_SKB -static void dump_skb(struct sk_buff *skb) { +static void dump_skb(struct sk_buff *skb) +{ char tmp[80]; char *p = skb->data; char *t = tmp; -- cgit v0.10.2 From 50a6edb1b6e08643442386e8f81acc8123d17931 Mon Sep 17 00:00:00 2001 From: Akinobu Mita <akinobu.mita@gmail.com> Date: Sun, 28 Aug 2016 23:52:49 +0900 Subject: iio: adc: add ADC12130/ADC12132/ADC12138 ADC driver This adds Texas Instruments' ADC12130/ADC12132/ADC12138 12-bit plus sign ADC driver. I have tested with the ADC12138. The ADC12130 and ADC12132 are not tested but these are similar to ADC12138 except that the mode programming instruction is a bit different. Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com> Acked-by: Rob Herring <robh@kernel.org> Cc: Jonathan Cameron <jic23@kernel.org> Cc: Hartmut Knaack <knaack.h@gmx.de> Cc: Lars-Peter Clausen <lars@metafoo.de> Cc: Peter Meerwald <pmeerw@pmeerw.net> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/Documentation/devicetree/bindings/iio/adc/ti-adc12138.txt b/Documentation/devicetree/bindings/iio/adc/ti-adc12138.txt new file mode 100644 index 0000000..049a1d3 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/ti-adc12138.txt @@ -0,0 +1,37 @@ +* Texas Instruments' ADC12130/ADC12132/ADC12138 + +Required properties: + - compatible: Should be one of + * "ti,adc12130" + * "ti,adc12132" + * "ti,adc12138" + - reg: SPI chip select number for the device + - interrupts: Should contain interrupt for EOC (end of conversion) + - clocks: phandle to conversion clock input + - spi-max-frequency: Definision as per + Documentation/devicetree/bindings/spi/spi-bus.txt + - vref-p-supply: The regulator supply for positive analog voltage reference + +Optional properties: + - vref-n-supply: The regulator supply for negative analog voltage reference + (Note that this must not go below GND or exceed vref-p) + If not specified, this is assumed to be analog ground. + - ti,acquisition-time: The number of conversion clock periods for the S/H's + acquisition time. Should be one of 6, 10, 18, 34. If not specified, + default value of 10 is used. + For high source impedances, this value can be increased to 18 or 34. + For less ADC accuracy and/or slower CCLK frequencies this value may be + decreased to 6. See section 6.0 INPUT SOURCE RESISTANCE in the + datasheet for details. + +Example: +adc@0 { + compatible = "ti,adc12138"; + reg = <0>; + interrupts = <28 IRQ_TYPE_EDGE_RISING>; + interrupt-parent = <&gpio1>; + clocks = <&cclk>; + vref-p-supply = <&ldo4_reg>; + spi-max-frequency = <5000000>; + ti,acquisition-time = <6>; +}; diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 6eac923..9f8e381 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -438,6 +438,18 @@ config TI_ADC0832 This driver can also be built as a module. If so, the module will be called ti-adc0832. +config TI_ADC12138 + tristate "Texas Instruments ADC12130/ADC12132/ADC12138" + depends on SPI + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + If you say yes here you get support for Texas Instruments ADC12130, + ADC12132 and ADC12138 chips. + + This driver can also be built as a module. If so, the module will be + called ti-adc12138. + config TI_ADC128S052 tristate "Texas Instruments ADC128S052/ADC122S021/ADC124S021" depends on SPI diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index f46dd1f..d1a20b6 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -42,6 +42,7 @@ obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o +obj-$(CONFIG_TI_ADC12138) += ti-adc12138.o obj-$(CONFIG_TI_ADC128S052) += ti-adc128s052.o obj-$(CONFIG_TI_ADC161S626) += ti-adc161s626.o obj-$(CONFIG_TI_ADS1015) += ti-ads1015.o diff --git a/drivers/iio/adc/ti-adc12138.c b/drivers/iio/adc/ti-adc12138.c new file mode 100644 index 0000000..072f03b --- /dev/null +++ b/drivers/iio/adc/ti-adc12138.c @@ -0,0 +1,552 @@ +/* + * ADC12130/ADC12132/ADC12138 12-bit plus sign ADC driver + * + * Copyright (c) 2016 Akinobu Mita <akinobu.mita@gmail.com> + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + * + * Datasheet: http://www.ti.com/lit/ds/symlink/adc12138.pdf + */ + +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/completion.h> +#include <linux/clk.h> +#include <linux/spi/spi.h> +#include <linux/iio/iio.h> +#include <linux/iio/buffer.h> +#include <linux/iio/trigger.h> +#include <linux/iio/triggered_buffer.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/regulator/consumer.h> + +#define ADC12138_MODE_AUTO_CAL 0x08 +#define ADC12138_MODE_READ_STATUS 0x0c +#define ADC12138_MODE_ACQUISITION_TIME_6 0x0e +#define ADC12138_MODE_ACQUISITION_TIME_10 0x4e +#define ADC12138_MODE_ACQUISITION_TIME_18 0x8e +#define ADC12138_MODE_ACQUISITION_TIME_34 0xce + +#define ADC12138_STATUS_CAL BIT(6) + +enum { + adc12130, + adc12132, + adc12138, +}; + +struct adc12138 { + struct spi_device *spi; + unsigned int id; + /* conversion clock */ + struct clk *cclk; + /* positive analog voltage reference */ + struct regulator *vref_p; + /* negative analog voltage reference */ + struct regulator *vref_n; + struct mutex lock; + struct completion complete; + /* The number of cclk periods for the S/H's acquisition time */ + unsigned int acquisition_time; + + u8 tx_buf[2] ____cacheline_aligned; + u8 rx_buf[2]; +}; + +#define ADC12138_VOLTAGE_CHANNEL(chan) \ + { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = chan, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \ + | BIT(IIO_CHAN_INFO_OFFSET), \ + .scan_index = chan, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 13, \ + .storagebits = 16, \ + .shift = 3, \ + .endianness = IIO_BE, \ + }, \ + } + +#define ADC12138_VOLTAGE_CHANNEL_DIFF(chan1, chan2, si) \ + { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = (chan1), \ + .channel2 = (chan2), \ + .differential = 1, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \ + | BIT(IIO_CHAN_INFO_OFFSET), \ + .scan_index = si, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 13, \ + .storagebits = 16, \ + .shift = 3, \ + .endianness = IIO_BE, \ + }, \ + } + +static const struct iio_chan_spec adc12132_channels[] = { + ADC12138_VOLTAGE_CHANNEL(0), + ADC12138_VOLTAGE_CHANNEL(1), + ADC12138_VOLTAGE_CHANNEL_DIFF(0, 1, 2), + ADC12138_VOLTAGE_CHANNEL_DIFF(1, 0, 3), + IIO_CHAN_SOFT_TIMESTAMP(4), +}; + +static const struct iio_chan_spec adc12138_channels[] = { + ADC12138_VOLTAGE_CHANNEL(0), + ADC12138_VOLTAGE_CHANNEL(1), + ADC12138_VOLTAGE_CHANNEL(2), + ADC12138_VOLTAGE_CHANNEL(3), + ADC12138_VOLTAGE_CHANNEL(4), + ADC12138_VOLTAGE_CHANNEL(5), + ADC12138_VOLTAGE_CHANNEL(6), + ADC12138_VOLTAGE_CHANNEL(7), + ADC12138_VOLTAGE_CHANNEL_DIFF(0, 1, 8), + ADC12138_VOLTAGE_CHANNEL_DIFF(1, 0, 9), + ADC12138_VOLTAGE_CHANNEL_DIFF(2, 3, 10), + ADC12138_VOLTAGE_CHANNEL_DIFF(3, 2, 11), + ADC12138_VOLTAGE_CHANNEL_DIFF(4, 5, 12), + ADC12138_VOLTAGE_CHANNEL_DIFF(5, 4, 13), + ADC12138_VOLTAGE_CHANNEL_DIFF(6, 7, 14), + ADC12138_VOLTAGE_CHANNEL_DIFF(7, 6, 15), + IIO_CHAN_SOFT_TIMESTAMP(16), +}; + +static int adc12138_mode_programming(struct adc12138 *adc, u8 mode, + void *rx_buf, int len) +{ + struct spi_transfer xfer = { + .tx_buf = adc->tx_buf, + .rx_buf = adc->rx_buf, + .len = len, + }; + int ret; + + /* Skip unused bits for ADC12130 and ADC12132 */ + if (adc->id != adc12138) + mode = (mode & 0xc0) | ((mode & 0x0f) << 2); + + adc->tx_buf[0] = mode; + + ret = spi_sync_transfer(adc->spi, &xfer, 1); + if (ret) + return ret; + + memcpy(rx_buf, adc->rx_buf, len); + + return 0; +} + +static int adc12138_read_status(struct adc12138 *adc) +{ + u8 rx_buf[2]; + int ret; + + ret = adc12138_mode_programming(adc, ADC12138_MODE_READ_STATUS, + rx_buf, 2); + if (ret) + return ret; + + return (rx_buf[0] << 1) | (rx_buf[1] >> 7); +} + +static int __adc12138_start_conv(struct adc12138 *adc, + struct iio_chan_spec const *channel, + void *data, int len) + +{ + const u8 ch_to_mux[] = { 0, 4, 1, 5, 2, 6, 3, 7 }; + u8 mode = (ch_to_mux[channel->channel] << 4) | + (channel->differential ? 0 : 0x80); + + return adc12138_mode_programming(adc, mode, data, len); +} + +static int adc12138_start_conv(struct adc12138 *adc, + struct iio_chan_spec const *channel) +{ + u8 trash; + + return __adc12138_start_conv(adc, channel, &trash, 1); +} + +static int adc12138_start_and_read_conv(struct adc12138 *adc, + struct iio_chan_spec const *channel, + __be16 *data) +{ + return __adc12138_start_conv(adc, channel, data, 2); +} + +static int adc12138_read_conv_data(struct adc12138 *adc, __be16 *value) +{ + /* Issue a read status instruction and read previous conversion data */ + return adc12138_mode_programming(adc, ADC12138_MODE_READ_STATUS, + value, sizeof(*value)); +} + +static int adc12138_wait_eoc(struct adc12138 *adc, unsigned long timeout) +{ + if (!wait_for_completion_timeout(&adc->complete, timeout)) + return -ETIMEDOUT; + + return 0; +} + +static int adc12138_adc_conversion(struct adc12138 *adc, + struct iio_chan_spec const *channel, + __be16 *value) +{ + int ret; + + reinit_completion(&adc->complete); + + ret = adc12138_start_conv(adc, channel); + if (ret) + return ret; + + ret = adc12138_wait_eoc(adc, msecs_to_jiffies(100)); + if (ret) + return ret; + + return adc12138_read_conv_data(adc, value); +} + +static int adc12138_read_raw(struct iio_dev *iio, + struct iio_chan_spec const *channel, int *value, + int *shift, long mask) +{ + struct adc12138 *adc = iio_priv(iio); + int ret; + __be16 data; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + mutex_lock(&adc->lock); + ret = adc12138_adc_conversion(adc, channel, &data); + mutex_unlock(&adc->lock); + if (ret) + return ret; + + *value = sign_extend32(be16_to_cpu(data) >> 3, 12); + + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + ret = regulator_get_voltage(adc->vref_p); + if (ret < 0) + return ret; + *value = ret; + + if (!IS_ERR(adc->vref_n)) { + ret = regulator_get_voltage(adc->vref_n); + if (ret < 0) + return ret; + *value -= ret; + } + + /* convert regulator output voltage to mV */ + *value /= 1000; + *shift = channel->scan_type.realbits - 1; + + return IIO_VAL_FRACTIONAL_LOG2; + case IIO_CHAN_INFO_OFFSET: + if (!IS_ERR(adc->vref_n)) { + *value = regulator_get_voltage(adc->vref_n); + if (*value < 0) + return *value; + } else { + *value = 0; + } + + /* convert regulator output voltage to mV */ + *value /= 1000; + + return IIO_VAL_INT; + } + + return -EINVAL; +} + +static const struct iio_info adc12138_info = { + .read_raw = adc12138_read_raw, + .driver_module = THIS_MODULE, +}; + +static int adc12138_init(struct adc12138 *adc) +{ + int ret; + int status; + u8 mode; + u8 trash; + + reinit_completion(&adc->complete); + + ret = adc12138_mode_programming(adc, ADC12138_MODE_AUTO_CAL, &trash, 1); + if (ret) + return ret; + + /* data output at this time has no significance */ + status = adc12138_read_status(adc); + if (status < 0) + return status; + + adc12138_wait_eoc(adc, msecs_to_jiffies(100)); + + status = adc12138_read_status(adc); + if (status & ADC12138_STATUS_CAL) { + dev_warn(&adc->spi->dev, + "Auto Cal sequence is still in progress: %#x\n", + status); + return -EIO; + } + + switch (adc->acquisition_time) { + case 6: + mode = ADC12138_MODE_ACQUISITION_TIME_6; + break; + case 10: + mode = ADC12138_MODE_ACQUISITION_TIME_10; + break; + case 18: + mode = ADC12138_MODE_ACQUISITION_TIME_18; + break; + case 34: + mode = ADC12138_MODE_ACQUISITION_TIME_34; + break; + default: + return -EINVAL; + } + + return adc12138_mode_programming(adc, mode, &trash, 1); +} + +static irqreturn_t adc12138_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct adc12138 *adc = iio_priv(indio_dev); + __be16 data[20] = { }; /* 16x 2 bytes ADC data + 8 bytes timestamp */ + __be16 trash; + int ret; + int scan_index; + int i = 0; + + mutex_lock(&adc->lock); + + for_each_set_bit(scan_index, indio_dev->active_scan_mask, + indio_dev->masklength) { + const struct iio_chan_spec *scan_chan = + &indio_dev->channels[scan_index]; + + reinit_completion(&adc->complete); + + ret = adc12138_start_and_read_conv(adc, scan_chan, + i ? &data[i - 1] : &trash); + if (ret) { + dev_warn(&adc->spi->dev, + "failed to start conversion\n"); + goto out; + } + + ret = adc12138_wait_eoc(adc, msecs_to_jiffies(100)); + if (ret) { + dev_warn(&adc->spi->dev, "wait eoc timeout\n"); + goto out; + } + + i++; + } + + if (i) { + ret = adc12138_read_conv_data(adc, &data[i - 1]); + if (ret) { + dev_warn(&adc->spi->dev, + "failed to get conversion data\n"); + goto out; + } + } + + iio_push_to_buffers_with_timestamp(indio_dev, data, + iio_get_time_ns(indio_dev)); +out: + mutex_unlock(&adc->lock); + + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static irqreturn_t adc12138_eoc_handler(int irq, void *p) +{ + struct iio_dev *indio_dev = p; + struct adc12138 *adc = iio_priv(indio_dev); + + complete(&adc->complete); + + return IRQ_HANDLED; +} + +static int adc12138_probe(struct spi_device *spi) +{ + struct iio_dev *indio_dev; + struct adc12138 *adc; + int ret; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc)); + if (!indio_dev) + return -ENOMEM; + + adc = iio_priv(indio_dev); + adc->spi = spi; + adc->id = spi_get_device_id(spi)->driver_data; + mutex_init(&adc->lock); + init_completion(&adc->complete); + + indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->dev.parent = &spi->dev; + indio_dev->info = &adc12138_info; + indio_dev->modes = INDIO_DIRECT_MODE; + + switch (adc->id) { + case adc12130: + case adc12132: + indio_dev->channels = adc12132_channels; + indio_dev->num_channels = ARRAY_SIZE(adc12132_channels); + break; + case adc12138: + indio_dev->channels = adc12138_channels; + indio_dev->num_channels = ARRAY_SIZE(adc12138_channels); + break; + default: + return -EINVAL; + } + + ret = of_property_read_u32(spi->dev.of_node, "ti,acquisition-time", + &adc->acquisition_time); + if (ret) + adc->acquisition_time = 10; + + adc->cclk = devm_clk_get(&spi->dev, NULL); + if (IS_ERR(adc->cclk)) + return PTR_ERR(adc->cclk); + + adc->vref_p = devm_regulator_get(&spi->dev, "vref-p"); + if (IS_ERR(adc->vref_p)) + return PTR_ERR(adc->vref_p); + + adc->vref_n = devm_regulator_get_optional(&spi->dev, "vref-n"); + if (IS_ERR(adc->vref_n)) { + /* + * Assume vref_n is 0V if an optional regulator is not + * specified, otherwise return the error code. + */ + ret = PTR_ERR(adc->vref_n); + if (ret != -ENODEV) + return ret; + } + + ret = devm_request_irq(&spi->dev, spi->irq, adc12138_eoc_handler, + IRQF_TRIGGER_RISING, indio_dev->name, indio_dev); + if (ret) + return ret; + + ret = clk_prepare_enable(adc->cclk); + if (ret) + return ret; + + ret = regulator_enable(adc->vref_p); + if (ret) + goto err_clk_disable; + + if (!IS_ERR(adc->vref_n)) { + ret = regulator_enable(adc->vref_n); + if (ret) + goto err_vref_p_disable; + } + + ret = adc12138_init(adc); + if (ret) + goto err_vref_n_disable; + + spi_set_drvdata(spi, indio_dev); + + ret = iio_triggered_buffer_setup(indio_dev, NULL, + adc12138_trigger_handler, NULL); + if (ret) + goto err_vref_n_disable; + + ret = iio_device_register(indio_dev); + if (ret) + goto err_buffer_cleanup; + + return 0; +err_buffer_cleanup: + iio_triggered_buffer_cleanup(indio_dev); +err_vref_n_disable: + if (!IS_ERR(adc->vref_n)) + regulator_disable(adc->vref_n); +err_vref_p_disable: + regulator_disable(adc->vref_p); +err_clk_disable: + clk_disable_unprepare(adc->cclk); + + return ret; +} + +static int adc12138_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct adc12138 *adc = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); + if (!IS_ERR(adc->vref_n)) + regulator_disable(adc->vref_n); + regulator_disable(adc->vref_p); + clk_disable_unprepare(adc->cclk); + + return 0; +} + +#ifdef CONFIG_OF + +static const struct of_device_id adc12138_dt_ids[] = { + { .compatible = "ti,adc12130", }, + { .compatible = "ti,adc12132", }, + { .compatible = "ti,adc12138", }, + {} +}; +MODULE_DEVICE_TABLE(of, adc12138_dt_ids); + +#endif + +static const struct spi_device_id adc12138_id[] = { + { "adc12130", adc12130 }, + { "adc12132", adc12132 }, + { "adc12138", adc12138 }, + {} +}; +MODULE_DEVICE_TABLE(spi, adc12138_id); + +static struct spi_driver adc12138_driver = { + .driver = { + .name = "adc12138", + .of_match_table = of_match_ptr(adc12138_dt_ids), + }, + .probe = adc12138_probe, + .remove = adc12138_remove, + .id_table = adc12138_id, +}; +module_spi_driver(adc12138_driver); + +MODULE_AUTHOR("Akinobu Mita <akinobu.mita@gmail.com>"); +MODULE_DESCRIPTION("ADC12130/ADC12132/ADC12138 driver"); +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 107b40ad04a902f3a70957134979bfb51118d440 Mon Sep 17 00:00:00 2001 From: Daeseok Youn <daeseok.youn@gmail.com> Date: Mon, 22 Aug 2016 10:43:59 +0900 Subject: staging: dgnc: check the type of print before calling The dgnc_maxcps_room() function must be called only for print device. The if-statement for checking print device checks before calling dgnc_maxcps_room() and also this function doesn't need to have any data except channel_t. Signed-off-by: Daeseok Youn <daeseok.youn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index e4c6c3f..31b18e6 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -1492,18 +1492,8 @@ static int dgnc_tty_chars_in_buffer(struct tty_struct *tty) * returns the new bytes_available. This only affects printer * output. */ -static int dgnc_maxcps_room(struct tty_struct *tty, int bytes_available) +static int dgnc_maxcps_room(struct channel_t *ch, int bytes_available) { - struct un_t *un = tty->driver_data; - struct channel_t *ch = un->un_ch; - - /* - * If its not the Transparent print device, return - * the full data amount. - */ - if (un->un_type != DGNC_PRINT) - return bytes_available; - if (ch->ch_digi.digi_maxcps > 0 && ch->ch_digi.digi_bufsize > 0) { int cps_limit = 0; unsigned long current_time = jiffies; @@ -1567,7 +1557,8 @@ static int dgnc_tty_write_room(struct tty_struct *tty) ret += WQUEUESIZE; /* Limit printer to maxcps */ - ret = dgnc_maxcps_room(tty, ret); + if (un->un_type != DGNC_PRINT) + ret = dgnc_maxcps_room(ch, ret); /* * If we are printer device, leave space for @@ -1659,7 +1650,8 @@ static int dgnc_tty_write(struct tty_struct *tty, * Limit printer output to maxcps overall, with bursts allowed * up to bufsize characters. */ - bufcount = dgnc_maxcps_room(tty, bufcount); + if (un->un_type != DGNC_PRINT) + bufcount = dgnc_maxcps_room(ch, bufcount); /* * Take minimum of what the user wants to send, and the -- cgit v0.10.2 From bc30c172cf2fd476f10380446ae12c35921082fa Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Wed, 24 Aug 2016 11:11:51 -0400 Subject: staging/lustre: const correct set_lock_data() Change the __u64 *cookie parameter of md_ops->set_lock_data() to const struct lustre_handle *lockh. Signed-off-by: John L. Hammond <john.hammond@intel.com> Reviewed-on: http://review.whamcloud.com/17072 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-7403 Reviewed-by: Frank Zago <fzago@cray.com> Reviewed-by: James Simmons <uja.ornl@yahoo.com> Signed-off-by: Oleg Drokin <green@linuxhacker.ru> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index ac620fd..ed0fd41 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -1023,7 +1023,8 @@ struct md_ops { struct lookup_intent *); int (*clear_open_replay_data)(struct obd_export *, struct obd_client_handle *); - int (*set_lock_data)(struct obd_export *, __u64 *, void *, __u64 *); + int (*set_lock_data)(struct obd_export *, const struct lustre_handle *, + void *, __u64 *); enum ldlm_mode (*lock_match)(struct obd_export *, __u64, const struct lu_fid *, enum ldlm_type, diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index 79fc041..4f48968 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -1610,7 +1610,8 @@ static inline int md_clear_open_replay_data(struct obd_export *exp, } static inline int md_set_lock_data(struct obd_export *exp, - __u64 *lockh, void *data, __u64 *bits) + const struct lustre_handle *lockh, + void *data, __u64 *bits) { EXP_CHECK_MD_OP(exp, set_lock_data); EXP_MD_COUNTER_INCREMENT(exp, set_lock_data); diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 55ccd84..13ff212 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -3629,7 +3629,7 @@ static int ll_layout_lock_set(struct lustre_handle *lockh, enum ldlm_mode mode, PFID(&lli->lli_fid), inode, reconf); /* in case this is a caching lock and reinstate with new inode */ - md_set_lock_data(sbi->ll_md_exp, &lockh->cookie, inode, NULL); + md_set_lock_data(sbi->ll_md_exp, lockh, inode, NULL); lock_res_and_lock(lock); lvb_ready = ldlm_is_lvb_ready(lock); diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index a5a3023..cbd5bc5 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -1243,7 +1243,7 @@ static inline void ll_set_lock_data(struct obd_export *exp, struct inode *inode, CDEBUG(D_DLMTRACE, "setting l_data to inode "DFID"%p for remote lock %#llx\n", PFID(ll_inode2fid(inode)), inode, handle.cookie); - md_set_lock_data(exp, &handle.cookie, inode, NULL); + md_set_lock_data(exp, &handle, inode, NULL); } handle.cookie = it->it_lock_handle; @@ -1251,8 +1251,7 @@ static inline void ll_set_lock_data(struct obd_export *exp, struct inode *inode, CDEBUG(D_DLMTRACE, "setting l_data to inode "DFID"%p for lock %#llx\n", PFID(ll_inode2fid(inode)), inode, handle.cookie); - md_set_lock_data(exp, &handle.cookie, inode, - &it->it_lock_bits); + md_set_lock_data(exp, &handle, inode, &it->it_lock_bits); it->it_lock_set = 1; } diff --git a/drivers/staging/lustre/lustre/lmv/lmv_intent.c b/drivers/staging/lustre/lustre/lmv/lmv_intent.c index 62f6bd0..85cc5cb 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_intent.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_intent.c @@ -250,7 +250,7 @@ int lmv_revalidate_slaves(struct obd_export *exp, struct mdt_body *mbody, ptlrpc_req_finished(req); } - md_set_lock_data(tgt->ltd_exp, &lockh->cookie, inode, NULL); + md_set_lock_data(tgt->ltd_exp, lockh, inode, NULL); if (i != 0) nlink += inode->i_nlink - 2; diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 72249bb..22b7896 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -3060,8 +3060,9 @@ static int lmv_cancel_unused(struct obd_export *exp, const struct lu_fid *fid, return rc; } -static int lmv_set_lock_data(struct obd_export *exp, __u64 *lockh, void *data, - __u64 *bits) +static int lmv_set_lock_data(struct obd_export *exp, + const struct lustre_handle *lockh, + void *data, __u64 *bits) { struct lmv_obd *lmv = &exp->exp_obd->u.lmv; struct lmv_tgt_desc *tgt = lmv->tgts[0]; diff --git a/drivers/staging/lustre/lustre/mdc/mdc_internal.h b/drivers/staging/lustre/lustre/mdc/mdc_internal.h index 9e65cdb..f778a92 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_internal.h +++ b/drivers/staging/lustre/lustre/mdc/mdc_internal.h @@ -61,7 +61,8 @@ void mdc_close_pack(struct ptlrpc_request *req, struct md_op_data *op_data); /* mdc/mdc_locks.c */ int mdc_set_lock_data(struct obd_export *exp, - __u64 *lockh, void *data, __u64 *bits); + const struct lustre_handle *lockh, + void *data, __u64 *bits); int mdc_null_inode(struct obd_export *exp, const struct lu_fid *fid); diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index f38339a..95dd291 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -93,8 +93,8 @@ int it_open_error(int phase, struct lookup_intent *it) EXPORT_SYMBOL(it_open_error); /* this must be called on a lockh that is known to have a referenced lock */ -int mdc_set_lock_data(struct obd_export *exp, __u64 *lockh, void *data, - __u64 *bits) +int mdc_set_lock_data(struct obd_export *exp, const struct lustre_handle *lockh, + void *data, __u64 *bits) { struct ldlm_lock *lock; struct inode *new_inode = data; @@ -102,10 +102,10 @@ int mdc_set_lock_data(struct obd_export *exp, __u64 *lockh, void *data, if (bits) *bits = 0; - if (!*lockh) + if (!lustre_handle_is_used(lockh)) return 0; - lock = ldlm_handle2lock((struct lustre_handle *)lockh); + lock = ldlm_handle2lock(lockh); LASSERT(lock); lock_res_and_lock(lock); diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 7a182be..91c0b45 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -1342,7 +1342,8 @@ static int mdc_read_page(struct obd_export *exp, struct md_op_data *op_data, } rc = 0; - mdc_set_lock_data(exp, &it.it_lock_handle, dir, NULL); + lockh.cookie = it.it_lock_handle; + mdc_set_lock_data(exp, &lockh, dir, NULL); rp_param.rp_off = hash_offset; rp_param.rp_hash64 = op_data->op_cli_flags & CLI_HASH64; @@ -1431,9 +1432,7 @@ hash_collision: } *ppage = page; out_unlock: - lockh.cookie = it.it_lock_handle; ldlm_lock_decref(&lockh, it.it_lock_mode); - it.it_lock_handle = 0; return rc; fail: kunmap(page); -- cgit v0.10.2 From 371991353af424559eaeae147d094c8612099d73 Mon Sep 17 00:00:00 2001 From: Alexander Boyko <alexander.boyko@seagate.com> Date: Wed, 24 Aug 2016 11:11:52 -0400 Subject: staging/lustre/mdc: fix panic at mdc_free_open() Assertion was happened for open request when rq_replay is set to 1. ASSERTION(mod->mod_open_req->rq_replay == 0) But this situation is not fatal for client, and could happened when mdc_close() failed. The fix allow to free such requests. If mdc_close fail, MDS doesn`t receive close request from client. And in a worst case client would be evicted. The test recreates issue when mdc_close failed and client asserts: ASSERTION( mod->mod_open_req->rq_replay == 0 ) failed Signed-off-by: Alexander Boyko <alexander.boyko@seagate.com> Seagate-bug-id: MRP-3156 Reviewed-on: http://review.whamcloud.com/17495 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5282 Reviewed-by: Alex Zhuravlev <alexey.zhuravlev@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Signed-off-by: Oleg Drokin <green@linuxhacker.ru> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd_support.h b/drivers/staging/lustre/lustre/include/obd_support.h index 0c29a33..4a9fe88 100644 --- a/drivers/staging/lustre/lustre/include/obd_support.h +++ b/drivers/staging/lustre/lustre/include/obd_support.h @@ -402,6 +402,7 @@ extern char obd_jobid_var[]; #define OBD_FAIL_MDC_GETATTR_ENQUEUE 0x803 #define OBD_FAIL_MDC_RPCS_SEM 0x804 #define OBD_FAIL_MDC_LIGHTWEIGHT 0x805 +#define OBD_FAIL_MDC_CLOSE 0x806 #define OBD_FAIL_MGS 0x900 #define OBD_FAIL_MGS_ALL_REQUEST_NET 0x901 diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 91c0b45..313889a 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -677,9 +677,15 @@ static void mdc_free_open(struct md_open_data *mod) imp_connect_disp_stripe(mod->mod_open_req->rq_import)) committed = 1; - LASSERT(mod->mod_open_req->rq_replay == 0); - - DEBUG_REQ(D_RPCTRACE, mod->mod_open_req, "free open request\n"); + /* + * No reason to asssert here if the open request has + * rq_replay == 1. It means that mdc_close failed, and + * close request wasn`t sent. It is not fatal to client. + * The worst thing is eviction if the client gets open lock + */ + DEBUG_REQ(D_RPCTRACE, mod->mod_open_req, + "free open request rq_replay = %d\n", + mod->mod_open_req->rq_replay); ptlrpc_request_committed(mod->mod_open_req, committed); if (mod->mod_close_req) @@ -749,22 +755,10 @@ static int mdc_close(struct obd_export *exp, struct md_op_data *op_data, } *request = NULL; - req = ptlrpc_request_alloc(class_exp2cliimp(exp), req_fmt); - if (!req) - return -ENOMEM; - - rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION, MDS_CLOSE); - if (rc) { - ptlrpc_request_free(req); - return rc; - } - - /* To avoid a livelock (bug 7034), we need to send CLOSE RPCs to a - * portal whose threads are not taking any DLM locks and are therefore - * always progressing - */ - req->rq_request_portal = MDS_READPAGE_PORTAL; - ptlrpc_at_set_req_timeout(req); + if (OBD_FAIL_CHECK(OBD_FAIL_MDC_CLOSE)) + req = NULL; + else + req = ptlrpc_request_alloc(class_exp2cliimp(exp), req_fmt); /* Ensure that this close's handle is fixed up during replay. */ if (likely(mod)) { @@ -785,6 +779,29 @@ static int mdc_close(struct obd_export *exp, struct md_op_data *op_data, CDEBUG(D_HA, "couldn't find open req; expecting close error\n"); } + if (!req) { + /* + * TODO: repeat close after errors + */ + CWARN("%s: close of FID "DFID" failed, file reference will be dropped when this client unmounts or is evicted\n", + obd->obd_name, PFID(&op_data->op_fid1)); + rc = -ENOMEM; + goto out; + } + + rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION, MDS_CLOSE); + if (rc) { + ptlrpc_request_free(req); + goto out; + } + + /* + * To avoid a livelock (bug 7034), we need to send CLOSE RPCs to a + * portal whose threads are not taking any DLM locks and are therefore + * always progressing + */ + req->rq_request_portal = MDS_READPAGE_PORTAL; + ptlrpc_at_set_req_timeout(req); mdc_close_pack(req, op_data); @@ -830,6 +847,7 @@ static int mdc_close(struct obd_export *exp, struct md_op_data *op_data, } } +out: if (mod) { if (rc != 0) mod->mod_close_req = NULL; -- cgit v0.10.2 From 3da76276127dc6cd78ba98f1cefe9e95faf17863 Mon Sep 17 00:00:00 2001 From: Andrew Perepechko <andrew.perepechko@seagate.com> Date: Wed, 24 Aug 2016 11:11:53 -0400 Subject: staging/lustre: avoid clearing i_nlink for inodes in use The patch removes find_cbdata callbacks and clear_nlink from dentry_iput path, since this piece of code makes a few races possible. The test case reproduces one of the possible races described in LU-7925: 1) two hard links are created for the same file 2) the test calls stat(2) for link #1 3) in the middle of 2) the test opens and closes link #2 4) in the middle of 2) the test drops the ldlm locks and forces dentry reclaim via vm.drop_caches=2 5) in the middle of 2) ll_d_iput() clears i_nlink for the inode 6) the initial stat(2) continues and copies the wrong i_nlink value into st_nlink Signed-off-by: Andrew Perepechko <andrew.perepechko@seagate.com> Seagate-bug-id: MRP-3271 Reviewed-on: http://review.whamcloud.com/19164 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-7925 Reviewed-by: Wally Wang <wang@cray.com> Reviewed-by: Lai Siyao <lai.siyao@intel.com> Signed-off-by: Oleg Drokin <green@linuxhacker.ru> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index ed0fd41..f3d141b 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -896,8 +896,6 @@ struct obd_ops { struct niobuf_remote *remote, int pages, struct niobuf_local *local, struct obd_trans_info *oti, int rc); - int (*find_cbdata)(struct obd_export *, struct lov_stripe_md *, - ldlm_iterator_t it, void *data); int (*init_export)(struct obd_export *exp); int (*destroy_export)(struct obd_export *exp); @@ -958,8 +956,6 @@ struct cl_attr; struct md_ops { int (*getstatus)(struct obd_export *, struct lu_fid *); int (*null_inode)(struct obd_export *, const struct lu_fid *); - int (*find_cbdata)(struct obd_export *, const struct lu_fid *, - ldlm_iterator_t, void *); int (*close)(struct obd_export *, struct md_op_data *, struct md_open_data *, struct ptlrpc_request **); int (*create)(struct obd_export *, struct md_op_data *, diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index 4f48968..9702ad4 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -1177,19 +1177,6 @@ static inline int obd_iocontrol(unsigned int cmd, struct obd_export *exp, return rc; } -static inline int obd_find_cbdata(struct obd_export *exp, - struct lov_stripe_md *lsm, - ldlm_iterator_t it, void *data) -{ - int rc; - - EXP_CHECK_DT_OP(exp, find_cbdata); - EXP_COUNTER_INCREMENT(exp, find_cbdata); - - rc = OBP(exp->exp_obd, find_cbdata)(exp, lsm, it, data); - return rc; -} - static inline void obd_import_event(struct obd_device *obd, struct obd_import *imp, enum obd_import_event event) @@ -1358,18 +1345,6 @@ static inline int md_null_inode(struct obd_export *exp, return rc; } -static inline int md_find_cbdata(struct obd_export *exp, - const struct lu_fid *fid, - ldlm_iterator_t it, void *data) -{ - int rc; - - EXP_CHECK_MD_OP(exp, find_cbdata); - EXP_MD_COUNTER_INCREMENT(exp, find_cbdata); - rc = MDP(exp->exp_obd, find_cbdata)(exp, fid, it, data); - return rc; -} - static inline int md_close(struct obd_export *exp, struct md_op_data *op_data, struct md_open_data *mod, struct ptlrpc_request **request) diff --git a/drivers/staging/lustre/lustre/include/obd_support.h b/drivers/staging/lustre/lustre/include/obd_support.h index 4a9fe88..4d7a5c8 100644 --- a/drivers/staging/lustre/lustre/include/obd_support.h +++ b/drivers/staging/lustre/lustre/include/obd_support.h @@ -458,6 +458,7 @@ extern char obd_jobid_var[]; #define OBD_FAIL_LOV_INIT 0x1403 #define OBD_FAIL_GLIMPSE_DELAY 0x1404 #define OBD_FAIL_LLITE_XATTR_ENOMEM 0x1405 +#define OBD_FAIL_GETATTR_DELAY 0x1409 #define OBD_FAIL_FID_INDIR 0x1501 #define OBD_FAIL_FID_INLMA 0x1502 diff --git a/drivers/staging/lustre/lustre/llite/dcache.c b/drivers/staging/lustre/lustre/llite/dcache.c index 463b1a3..f4b6f38 100644 --- a/drivers/staging/lustre/lustre/llite/dcache.c +++ b/drivers/staging/lustre/lustre/llite/dcache.c @@ -102,39 +102,6 @@ static int ll_dcompare(const struct dentry *dentry, return 0; } -static inline int return_if_equal(struct ldlm_lock *lock, void *data) -{ - return (ldlm_is_canceling(lock) && ldlm_is_discard_data(lock)) ? - LDLM_ITER_CONTINUE : LDLM_ITER_STOP; -} - -/* find any ldlm lock of the inode in mdc and lov - * return 0 not find - * 1 find one - * < 0 error - */ -static int find_cbdata(struct inode *inode) -{ - struct ll_sb_info *sbi = ll_i2sbi(inode); - struct lov_stripe_md *lsm; - int rc = 0; - - LASSERT(inode); - rc = md_find_cbdata(sbi->ll_md_exp, ll_inode2fid(inode), - return_if_equal, NULL); - if (rc != 0) - return rc; - - lsm = ccc_inode_lsm_get(inode); - if (!lsm) - return rc; - - rc = obd_find_cbdata(sbi->ll_dt_exp, lsm, return_if_equal, NULL); - ccc_inode_lsm_put(inode, lsm); - - return rc; -} - /** * Called when last reference to a dentry is dropped and dcache wants to know * whether or not it should cache it: @@ -155,19 +122,6 @@ static int ll_ddelete(const struct dentry *de) /* kernel >= 2.6.38 last refcount is decreased after this function. */ LASSERT(d_count(de) == 1); - /* Disable this piece of code temporarily because this is called - * inside dcache_lock so it's not appropriate to do lots of work - * here. ATTENTION: Before this piece of code enabling, LU-2487 must be - * resolved. - */ -#if 0 - /* if not ldlm lock for this inode, set i_nlink to 0 so that - * this inode can be recycled later b=20433 - */ - if (d_really_is_positive(de) && !find_cbdata(d_inode(de))) - clear_nlink(d_inode(de)); -#endif - if (d_lustre_invalid((struct dentry *)de)) return 1; return 0; @@ -347,18 +301,9 @@ static int ll_revalidate_nd(struct dentry *dentry, unsigned int flags) return ll_revalidate_dentry(dentry, flags); } -static void ll_d_iput(struct dentry *de, struct inode *inode) -{ - LASSERT(inode); - if (!find_cbdata(inode)) - clear_nlink(inode); - iput(inode); -} - const struct dentry_operations ll_d_ops = { .d_revalidate = ll_revalidate_nd, .d_release = ll_release, .d_delete = ll_ddelete, - .d_iput = ll_d_iput, .d_compare = ll_dcompare, }; diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 13ff212..e2e81bf 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -3191,6 +3191,8 @@ int ll_getattr(struct vfsmount *mnt, struct dentry *de, struct kstat *stat) if (res) return res; + OBD_FAIL_TIMEOUT(OBD_FAIL_GETATTR_DELAY, 30); + stat->dev = inode->i_sb->s_dev; if (ll_need_32bit_api(sbi)) stat->ino = cl_fid_build_ino(&lli->lli_fid, 1); diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 22b7896..dc752d5 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -1609,47 +1609,6 @@ static int lmv_null_inode(struct obd_export *exp, const struct lu_fid *fid) return 0; } -static int lmv_find_cbdata(struct obd_export *exp, const struct lu_fid *fid, - ldlm_iterator_t it, void *data) -{ - struct obd_device *obd = exp->exp_obd; - struct lmv_obd *lmv = &obd->u.lmv; - int tgt; - u32 i; - int rc; - - rc = lmv_check_connect(obd); - if (rc) - return rc; - - CDEBUG(D_INODE, "CBDATA for "DFID"\n", PFID(fid)); - - /* - * With DNE every object can have two locks in different namespaces: - * lookup lock in space of MDT storing direntry and update/open lock in - * space of MDT storing inode. Try the MDT that the FID maps to first, - * since this can be easily found, and only try others if that fails. - */ - for (i = 0, tgt = lmv_find_target_index(lmv, fid); - i < lmv->desc.ld_tgt_count; - i++, tgt = (tgt + 1) % lmv->desc.ld_tgt_count) { - if (tgt < 0) { - CDEBUG(D_HA, "%s: "DFID" is inaccessible: rc = %d\n", - obd->obd_name, PFID(fid), tgt); - tgt = 0; - } - - if (!lmv->tgts[tgt] || !lmv->tgts[tgt]->ltd_exp) - continue; - - rc = md_find_cbdata(lmv->tgts[tgt]->ltd_exp, fid, it, data); - if (rc) - return rc; - } - - return rc; -} - static int lmv_close(struct obd_export *exp, struct md_op_data *op_data, struct md_open_data *mod, struct ptlrpc_request **request) { @@ -3373,7 +3332,6 @@ static struct obd_ops lmv_obd_ops = { static struct md_ops lmv_md_ops = { .getstatus = lmv_getstatus, .null_inode = lmv_null_inode, - .find_cbdata = lmv_find_cbdata, .close = lmv_close, .create = lmv_create, .done_writing = lmv_done_writing, diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index 2817f38..265be08 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -1268,46 +1268,6 @@ static int lov_setattr_async(struct obd_export *exp, struct obd_info *oinfo, return 0; } -/* find any ldlm lock of the inode in lov - * return 0 not find - * 1 find one - * < 0 error - */ -static int lov_find_cbdata(struct obd_export *exp, - struct lov_stripe_md *lsm, ldlm_iterator_t it, - void *data) -{ - struct lov_obd *lov; - int rc = 0, i; - - ASSERT_LSM_MAGIC(lsm); - - if (!exp || !exp->exp_obd) - return -ENODEV; - - lov = &exp->exp_obd->u.lov; - for (i = 0; i < lsm->lsm_stripe_count; i++) { - struct lov_stripe_md submd; - struct lov_oinfo *loi = lsm->lsm_oinfo[i]; - - if (lov_oinfo_is_dummy(loi)) - continue; - - if (!lov->lov_tgts[loi->loi_ost_idx]) { - CDEBUG(D_HA, "lov idx %d NULL\n", loi->loi_ost_idx); - continue; - } - - submd.lsm_oi = loi->loi_oi; - submd.lsm_stripe_count = 0; - rc = obd_find_cbdata(lov->lov_tgts[loi->loi_ost_idx]->ltd_exp, - &submd, it, data); - if (rc != 0) - return rc; - } - return rc; -} - int lov_statfs_interpret(struct ptlrpc_request_set *rqset, void *data, int rc) { struct lov_request_set *lovset = (struct lov_request_set *)data; @@ -2326,7 +2286,6 @@ static struct obd_ops lov_obd_ops = { .getattr_async = lov_getattr_async, .setattr_async = lov_setattr_async, .adjust_kms = lov_adjust_kms, - .find_cbdata = lov_find_cbdata, .iocontrol = lov_iocontrol, .get_info = lov_get_info, .set_info_async = lov_set_info_async, diff --git a/drivers/staging/lustre/lustre/mdc/mdc_internal.h b/drivers/staging/lustre/lustre/mdc/mdc_internal.h index f778a92..c10441d 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_internal.h +++ b/drivers/staging/lustre/lustre/mdc/mdc_internal.h @@ -66,9 +66,6 @@ int mdc_set_lock_data(struct obd_export *exp, int mdc_null_inode(struct obd_export *exp, const struct lu_fid *fid); -int mdc_find_cbdata(struct obd_export *exp, const struct lu_fid *fid, - ldlm_iterator_t it, void *data); - int mdc_intent_lock(struct obd_export *exp, struct md_op_data *op_data, struct lookup_intent *it, diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index 95dd291..54de46b 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -185,28 +185,6 @@ int mdc_null_inode(struct obd_export *exp, return 0; } -/* find any ldlm lock of the inode in mdc - * return 0 not find - * 1 find one - * < 0 error - */ -int mdc_find_cbdata(struct obd_export *exp, - const struct lu_fid *fid, - ldlm_iterator_t it, void *data) -{ - struct ldlm_res_id res_id; - int rc = 0; - - fid_build_reg_res_name((struct lu_fid *)fid, &res_id); - rc = ldlm_resource_iterate(class_exp2obd(exp)->obd_namespace, &res_id, - it, data); - if (rc == LDLM_ITER_STOP) - return 1; - else if (rc == LDLM_ITER_CONTINUE) - return 0; - return rc; -} - static inline void mdc_clear_replay_flag(struct ptlrpc_request *req, int rc) { /* Don't hold error requests for replay. */ diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 313889a..5bf95f9 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -2874,7 +2874,6 @@ static struct obd_ops mdc_obd_ops = { static struct md_ops mdc_md_ops = { .getstatus = mdc_getstatus, .null_inode = mdc_null_inode, - .find_cbdata = mdc_find_cbdata, .close = mdc_close, .create = mdc_create, .done_writing = mdc_done_writing, diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 53c191d..bdb329d 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -2119,27 +2119,6 @@ static int osc_set_data_with_check(struct lustre_handle *lockh, return set; } -/* find any ldlm lock of the inode in osc - * return 0 not find - * 1 find one - * < 0 error - */ -static int osc_find_cbdata(struct obd_export *exp, struct lov_stripe_md *lsm, - ldlm_iterator_t replace, void *data) -{ - struct ldlm_res_id res_id; - struct obd_device *obd = class_exp2obd(exp); - int rc = 0; - - ostid_build_res_name(&lsm->lsm_oi, &res_id); - rc = ldlm_resource_iterate(obd->obd_namespace, &res_id, replace, data); - if (rc == LDLM_ITER_STOP) - return 1; - if (rc == LDLM_ITER_CONTINUE) - return 0; - return rc; -} - static int osc_enqueue_fini(struct ptlrpc_request *req, osc_enqueue_upcall_f upcall, void *cookie, struct lustre_handle *lockh, enum ldlm_mode mode, @@ -3358,7 +3337,6 @@ static struct obd_ops osc_obd_ops = { .getattr_async = osc_getattr_async, .setattr = osc_setattr, .setattr_async = osc_setattr_async, - .find_cbdata = osc_find_cbdata, .iocontrol = osc_iocontrol, .get_info = osc_get_info, .set_info_async = osc_set_info_async, -- cgit v0.10.2 From 76cc3abe44744f6e694ce09a73781114e0ecf475 Mon Sep 17 00:00:00 2001 From: Yang Sheng <yang.sheng@intel.com> Date: Wed, 24 Aug 2016 11:11:54 -0400 Subject: staging/lustre/llite: check return value for obd_set_info_async The return value is ignored in client_common_fill_super. Restore to check it and error out. Signed-off-by: Yang Sheng <yang.sheng@intel.com> Reviewed-on: http://review.whamcloud.com/21125 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-8360 Reviewed-by: Emoly Liu <emoly.liu@intel.com> Reviewed-by: Bob Glossman <bob.glossman@intel.com> Signed-off-by: Oleg Drokin <green@linuxhacker.ru> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 72ff7c4..1ff788e 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -498,11 +498,21 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, err = obd_set_info_async(NULL, sbi->ll_dt_exp, sizeof(KEY_CHECKSUM), KEY_CHECKSUM, sizeof(checksum), &checksum, NULL); + if (err) { + CERROR("%s: Set checksum failed: rc = %d\n", + sbi->ll_dt_exp->exp_obd->obd_name, err); + goto out_root; + } cl_sb_init(sb); err = obd_set_info_async(NULL, sbi->ll_dt_exp, sizeof(KEY_CACHE_SET), KEY_CACHE_SET, sizeof(*sbi->ll_cache), sbi->ll_cache, NULL); + if (err) { + CERROR("%s: Set cache_set failed: rc = %d\n", + sbi->ll_dt_exp->exp_obd->obd_name, err); + goto out_root; + } sb->s_root = d_make_root(root); if (!sb->s_root) { -- cgit v0.10.2 From 8d897d2540ff7f97941f1f3cb065ce4a9d808774 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin <dmitry.eremin@intel.com> Date: Wed, 24 Aug 2016 11:11:55 -0400 Subject: staging/lustre/llite: Fix suspicious dereference of pointer 'vma->vm_file' Remove useless LASSERT(vma->vm_file) because of if it's NULL it will crash early in file_inode(vma->vm_file). Signed-off-by: Dmitry Eremin <dmitry.eremin@intel.com> Reviewed-on: http://review.whamcloud.com/21171 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-8372 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Bob Glossman <bob.glossman@intel.com> Signed-off-by: Oleg Drokin <green@linuxhacker.ru> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/llite_mmap.c b/drivers/staging/lustre/lustre/llite/llite_mmap.c index 9d03e79..37f82ed 100644 --- a/drivers/staging/lustre/lustre/llite/llite_mmap.c +++ b/drivers/staging/lustre/lustre/llite/llite_mmap.c @@ -429,7 +429,6 @@ static void ll_vm_open(struct vm_area_struct *vma) struct inode *inode = file_inode(vma->vm_file); struct vvp_object *vob = cl_inode2vvp(inode); - LASSERT(vma->vm_file); LASSERT(atomic_read(&vob->vob_mmap_cnt) >= 0); atomic_inc(&vob->vob_mmap_cnt); } @@ -442,7 +441,6 @@ static void ll_vm_close(struct vm_area_struct *vma) struct inode *inode = file_inode(vma->vm_file); struct vvp_object *vob = cl_inode2vvp(inode); - LASSERT(vma->vm_file); atomic_dec(&vob->vob_mmap_cnt); LASSERT(atomic_read(&vob->vob_mmap_cnt) >= 0); } -- cgit v0.10.2 From f736814418084d43e6098bcb49937dbb757e9ec1 Mon Sep 17 00:00:00 2001 From: Lokesh Nagappa Jaliminche <lokesh.jaliminche@seagate.com> Date: Wed, 24 Aug 2016 11:11:56 -0400 Subject: staging/lustre/llite: changes to avoid cache corruption ll_find_alias is responsible for getting alias for inode which can be reused. Directories are assumed to have unique alias, where in case of non-directories there can be multiple aliases. In case of lustre there can be two type of aliases i.e. discon_alias and invalid_alias. Usage of discon_alias in case of non-directories may corrupt dcache and leads to kernel crash. Changes made to avoid use of discon_alias in case of non-directories. Seagate-bug-id: MRP-2739, MRP-3601 Signed-off-by: Lokesh Nagappa Jaliminche <lokesh.jaliminche@seagate.com> Reviewed-by: Ujjwal Lanjewar <ujjwal.lanjewar@seagate.com> Reviewed-by: Ashish Purkar <ashish.purkar@seagate.com> Reviewed-by: Andrew Perepechko <andrew.perepechko@seagate.com> Tested-by: Parinay Vijayprakash Kondekar <parinay.kondekar@seagate.com> Reviewed-on: http://review.whamcloud.com/17732 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-7613 Reviewed-by: Niu Yawei <yawei.niu@intel.com> Signed-off-by: Oleg Drokin <green@linuxhacker.ru> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index 7495c0f..6ca545d 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -363,7 +363,8 @@ static struct dentry *ll_find_alias(struct inode *inode, struct dentry *dentry) LASSERT(alias != dentry); spin_lock(&alias->d_lock); - if (alias->d_flags & DCACHE_DISCONNECTED) + if ((alias->d_flags & DCACHE_DISCONNECTED) && + S_ISDIR(inode->i_mode)) /* LASSERT(last_discon == NULL); LU-405, bz 20055 */ discon_alias = alias; else if (alias->d_parent == dentry->d_parent && -- cgit v0.10.2 From 7f93fce9660158ea0b690af225dcc22b31a845ac Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Wed, 24 Aug 2016 11:11:57 -0400 Subject: staging/lustre: release MGC device if connect fails In lustre_fill_super() if lustre_start_mgc() fails then call lustre_common_put_super() to release a reference on the MGC device attached to the LSI. Signed-off-by: John L. Hammond <john.hammond@intel.com> Reviewed-on: http://review.whamcloud.com/20851 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-8297 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Mike Pershin <mike.pershin@intel.com> Signed-off-by: Oleg Drokin <green@linuxhacker.ru> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/obdclass/obd_mount.c b/drivers/staging/lustre/lustre/obdclass/obd_mount.c index ae702ce..0273768 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_mount.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_mount.c @@ -1144,7 +1144,7 @@ static int lustre_fill_super(struct super_block *sb, void *data, int silent) } else { rc = lustre_start_mgc(sb); if (rc) { - lustre_put_lsi(sb); + lustre_common_put_super(sb); goto out; } /* Connect and start */ -- cgit v0.10.2 From bbc2d82f1cc931f4287c716000ded8c4613249f2 Mon Sep 17 00:00:00 2001 From: James Simmons <uja.ornl@yahoo.com> Date: Wed, 24 Aug 2016 11:11:58 -0400 Subject: staging/lustre/o2iblnd: handle mixed page size configurations. Currently it is not possible to send LNet traffic between two nodes using infiniband hardware that have different page sizes for the case when RDMA fragments are used. When two nodes establish a connection they tell the other node the maximum number of RDMA fragments they support. The issue is that the units are pages, and 256 64K pages corresponds to 16MB of data, whereas a 4K page system is limited to messages with 1MB of data. The solution is to report over the wire the maximum number of fragments in 4K unites regardless of the native page size. The recipient then uses its native page size to translate into the maximum number of pages sized fragments it can send to the other node. Signed-off-by: James Simmons <uja.ornl@yahoo.com> Reviewed-on: http://review.whamcloud.com/21304 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-7650 Reviewed-by: Doug Oucharek <doug.s.oucharek@intel.com> Reviewed-by: Olaf Weber <olaf@sgi.com> Signed-off-by: Oleg Drokin <green@linuxhacker.ru> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c index e93dbeb..c7a5d49 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c @@ -128,6 +128,7 @@ static int kiblnd_msgtype2size(int type) static int kiblnd_unpack_rd(struct kib_msg *msg, int flip) { struct kib_rdma_desc *rd; + int msg_size; int nob; int n; int i; @@ -146,12 +147,6 @@ static int kiblnd_unpack_rd(struct kib_msg *msg, int flip) n = rd->rd_nfrags; - if (n <= 0 || n > IBLND_MAX_RDMA_FRAGS) { - CERROR("Bad nfrags: %d, should be 0 < n <= %d\n", - n, IBLND_MAX_RDMA_FRAGS); - return 1; - } - nob = offsetof(struct kib_msg, ibm_u) + kiblnd_rd_msg_size(rd, msg->ibm_type, n); @@ -161,6 +156,13 @@ static int kiblnd_unpack_rd(struct kib_msg *msg, int flip) return 1; } + msg_size = kiblnd_rd_size(rd); + if (msg_size <= 0 || msg_size > LNET_MAX_PAYLOAD) { + CERROR("Bad msg_size: %d, should be 0 < n <= %d\n", + msg_size, LNET_MAX_PAYLOAD); + return 1; + } + if (!flip) return 0; diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h index 3cf8942..1457697 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h @@ -113,8 +113,9 @@ extern struct kib_tunables kiblnd_tunables; #define IBLND_OOB_CAPABLE(v) ((v) != IBLND_MSG_VERSION_1) #define IBLND_OOB_MSGS(v) (IBLND_OOB_CAPABLE(v) ? 2 : 0) -#define IBLND_MSG_SIZE (4 << 10) /* max size of queued messages (inc hdr) */ -#define IBLND_MAX_RDMA_FRAGS LNET_MAX_IOV /* max # of fragments supported */ +#define IBLND_FRAG_SHIFT (PAGE_SHIFT - 12) /* frag size on wire is in 4K units */ +#define IBLND_MSG_SIZE (4 << 10) /* max size of queued messages (inc hdr) */ +#define IBLND_MAX_RDMA_FRAGS (LNET_MAX_PAYLOAD >> 12)/* max # of fragments supported in 4K size */ /************************/ /* derived constants... */ @@ -133,8 +134,8 @@ extern struct kib_tunables kiblnd_tunables; /* WRs and CQEs (per connection) */ #define IBLND_RECV_WRS(c) IBLND_RX_MSGS(c) #define IBLND_SEND_WRS(c) \ - ((c->ibc_max_frags + 1) * kiblnd_concurrent_sends(c->ibc_version, \ - c->ibc_peer->ibp_ni)) + (((c->ibc_max_frags + 1) << IBLND_FRAG_SHIFT) * \ + kiblnd_concurrent_sends(c->ibc_version, c->ibc_peer->ibp_ni)) #define IBLND_CQ_ENTRIES(c) (IBLND_RECV_WRS(c) + IBLND_SEND_WRS(c)) struct kib_hca_dev; @@ -609,14 +610,14 @@ kiblnd_cfg_rdma_frags(struct lnet_ni *ni) tunables = &ni->ni_lnd_tunables->lt_tun_u.lt_o2ib; mod = tunables->lnd_map_on_demand; - return mod ? mod : IBLND_MAX_RDMA_FRAGS; + return mod ? mod : IBLND_MAX_RDMA_FRAGS >> IBLND_FRAG_SHIFT; } static inline int kiblnd_rdma_frags(int version, struct lnet_ni *ni) { return version == IBLND_MSG_VERSION_1 ? - IBLND_MAX_RDMA_FRAGS : + (IBLND_MAX_RDMA_FRAGS >> IBLND_FRAG_SHIFT) : kiblnd_cfg_rdma_frags(ni); } diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index 1563428..3a86879 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -764,7 +764,6 @@ kiblnd_post_tx_locked(struct kib_conn *conn, struct kib_tx *tx, int credit) LASSERT(tx->tx_queued); /* We rely on this for QP sizing */ LASSERT(tx->tx_nwrq > 0); - LASSERT(tx->tx_nwrq <= 1 + conn->ibc_max_frags); LASSERT(!credit || credit == 1); LASSERT(conn->ibc_outstanding_credits >= 0); @@ -1072,6 +1071,15 @@ kiblnd_init_rdma(struct kib_conn *conn, struct kib_tx *tx, int type, LASSERT(type == IBLND_MSG_GET_DONE || type == IBLND_MSG_PUT_DONE); + if (kiblnd_rd_size(srcrd) > conn->ibc_max_frags << PAGE_SHIFT) { + CERROR("RDMA is too large for peer %s (%d), src size: %d dst size: %d\n", + libcfs_nid2str(conn->ibc_peer->ibp_nid), + conn->ibc_max_frags << PAGE_SHIFT, + kiblnd_rd_size(srcrd), kiblnd_rd_size(dstrd)); + rc = -EMSGSIZE; + goto too_big; + } + while (resid > 0) { if (srcidx >= srcrd->rd_nfrags) { CERROR("Src buffer exhausted: %d frags\n", srcidx); @@ -1085,16 +1093,6 @@ kiblnd_init_rdma(struct kib_conn *conn, struct kib_tx *tx, int type, break; } - if (tx->tx_nwrq >= conn->ibc_max_frags) { - CERROR("RDMA has too many fragments for peer %s (%d), src idx/frags: %d/%d dst idx/frags: %d/%d\n", - libcfs_nid2str(conn->ibc_peer->ibp_nid), - conn->ibc_max_frags, - srcidx, srcrd->rd_nfrags, - dstidx, dstrd->rd_nfrags); - rc = -EMSGSIZE; - break; - } - wrknob = min(min(kiblnd_rd_frag_size(srcrd, srcidx), kiblnd_rd_frag_size(dstrd, dstidx)), (__u32)resid); @@ -1126,7 +1124,7 @@ kiblnd_init_rdma(struct kib_conn *conn, struct kib_tx *tx, int type, wrq++; sge++; } - +too_big: if (rc < 0) /* no RDMA if completing with failure */ tx->tx_nwrq = 0; @@ -2226,6 +2224,7 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob) struct kib_rej rej; int version = IBLND_MSG_VERSION; unsigned long flags; + int max_frags; int rc; struct sockaddr_in *peer_addr; @@ -2332,22 +2331,20 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob) goto failed; } - if (reqmsg->ibm_u.connparams.ibcp_max_frags > - kiblnd_rdma_frags(version, ni)) { - CWARN("Can't accept conn from %s (version %x): max_frags %d too large (%d wanted)\n", - libcfs_nid2str(nid), version, - reqmsg->ibm_u.connparams.ibcp_max_frags, + max_frags = reqmsg->ibm_u.connparams.ibcp_max_frags >> IBLND_FRAG_SHIFT; + if (max_frags > kiblnd_rdma_frags(version, ni)) { + CWARN("Can't accept conn from %s (version %x): max message size %d is too large (%d wanted)\n", + libcfs_nid2str(nid), version, max_frags, kiblnd_rdma_frags(version, ni)); if (version >= IBLND_MSG_VERSION) rej.ibr_why = IBLND_REJECT_RDMA_FRAGS; goto failed; - } else if (reqmsg->ibm_u.connparams.ibcp_max_frags < - kiblnd_rdma_frags(version, ni) && !net->ibn_fmr_ps) { - CWARN("Can't accept conn from %s (version %x): max_frags %d incompatible without FMR pool (%d wanted)\n", - libcfs_nid2str(nid), version, - reqmsg->ibm_u.connparams.ibcp_max_frags, + } else if (max_frags < kiblnd_rdma_frags(version, ni) && + !net->ibn_fmr_ps) { + CWARN("Can't accept conn from %s (version %x): max message size %d incompatible without FMR pool (%d wanted)\n", + libcfs_nid2str(nid), version, max_frags, kiblnd_rdma_frags(version, ni)); if (version == IBLND_MSG_VERSION) @@ -2373,7 +2370,7 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob) } /* We have validated the peer's parameters so use those */ - peer->ibp_max_frags = reqmsg->ibm_u.connparams.ibcp_max_frags; + peer->ibp_max_frags = max_frags; peer->ibp_queue_depth = reqmsg->ibm_u.connparams.ibcp_queue_depth; write_lock_irqsave(g_lock, flags); @@ -2494,7 +2491,7 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob) kiblnd_init_msg(ackmsg, IBLND_MSG_CONNACK, sizeof(ackmsg->ibm_u.connparams)); ackmsg->ibm_u.connparams.ibcp_queue_depth = conn->ibc_queue_depth; - ackmsg->ibm_u.connparams.ibcp_max_frags = conn->ibc_max_frags; + ackmsg->ibm_u.connparams.ibcp_max_frags = conn->ibc_max_frags << IBLND_FRAG_SHIFT; ackmsg->ibm_u.connparams.ibcp_max_msg_size = IBLND_MSG_SIZE; kiblnd_pack_msg(ni, ackmsg, version, 0, nid, reqmsg->ibm_srcstamp); @@ -2556,7 +2553,7 @@ kiblnd_check_reconnect(struct kib_conn *conn, int version, if (cp) { msg_size = cp->ibcp_max_msg_size; - frag_num = cp->ibcp_max_frags; + frag_num = cp->ibcp_max_frags << IBLND_FRAG_SHIFT; queue_dep = cp->ibcp_queue_depth; } @@ -2821,11 +2818,11 @@ kiblnd_check_connreply(struct kib_conn *conn, void *priv, int priv_nob) goto failed; } - if (msg->ibm_u.connparams.ibcp_max_frags > + if ((msg->ibm_u.connparams.ibcp_max_frags >> IBLND_FRAG_SHIFT) > conn->ibc_max_frags) { CERROR("%s has incompatible max_frags %d (<=%d wanted)\n", libcfs_nid2str(peer->ibp_nid), - msg->ibm_u.connparams.ibcp_max_frags, + msg->ibm_u.connparams.ibcp_max_frags >> IBLND_FRAG_SHIFT, conn->ibc_max_frags); rc = -EPROTO; goto failed; @@ -2859,7 +2856,7 @@ kiblnd_check_connreply(struct kib_conn *conn, void *priv, int priv_nob) conn->ibc_credits = msg->ibm_u.connparams.ibcp_queue_depth; conn->ibc_reserved_credits = msg->ibm_u.connparams.ibcp_queue_depth; conn->ibc_queue_depth = msg->ibm_u.connparams.ibcp_queue_depth; - conn->ibc_max_frags = msg->ibm_u.connparams.ibcp_max_frags; + conn->ibc_max_frags = msg->ibm_u.connparams.ibcp_max_frags >> IBLND_FRAG_SHIFT; LASSERT(conn->ibc_credits + conn->ibc_reserved_credits + IBLND_OOB_MSGS(ver) <= IBLND_RX_MSGS(conn)); @@ -2916,7 +2913,7 @@ kiblnd_active_connect(struct rdma_cm_id *cmid) memset(msg, 0, sizeof(*msg)); kiblnd_init_msg(msg, IBLND_MSG_CONNREQ, sizeof(msg->ibm_u.connparams)); msg->ibm_u.connparams.ibcp_queue_depth = conn->ibc_queue_depth; - msg->ibm_u.connparams.ibcp_max_frags = conn->ibc_max_frags; + msg->ibm_u.connparams.ibcp_max_frags = conn->ibc_max_frags << IBLND_FRAG_SHIFT; msg->ibm_u.connparams.ibcp_max_msg_size = IBLND_MSG_SIZE; kiblnd_pack_msg(peer->ibp_ni, msg, version, -- cgit v0.10.2 From 7894c263f200aea33b0be3f8408adc93e3129f0f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann <arnd@arndb.de> Date: Mon, 29 Aug 2016 14:20:00 +0200 Subject: staging: lustre: fix unstable pages tracking A patch to change to page accounting code (in v4.8-rc1) conflicts with a change to lustre (in staging-next for v4.9), and fortunately gets detected using a gcc warning: In file included from /git/arm-soc/include/linux/mm.h:1001:0, from /git/arm-soc/include/linux/highmem.h:7, from /git/arm-soc/drivers/staging/lustre/lustre/osc/../../include/linux/libcfs/linux/libcfs.h:46, from /git/arm-soc/drivers/staging/lustre/lustre/osc/../../include/linux/libcfs/libcfs.h:36, from /git/arm-soc/drivers/staging/lustre/lustre/osc/osc_cl_internal.h:45, from /git/arm-soc/drivers/staging/lustre/lustre/osc/osc_page.c:40: drivers/staging/lustre/lustre/osc/osc_page.c: In function 'unstable_page_accounting': include/linux/vmstat.h:117:2: error: array subscript is above array bounds [-Werror=array-bounds] atomic_long_add(x, &vm_zone_stat[item]); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/vmstat.h:117:2: error: array subscript is above array bounds [-Werror=array-bounds] atomic_long_add(x, &vm_zone_stat[item]); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This changes the function to use the correct interface for accounting in the "node" rather than the "zone". Signed-off-by: Arnd Bergmann <arnd@arndb.de> Fixes: d806f30e639b ("staging: lustre: osc: revise unstable pages accounting") Fixes: 11fb998986a7 ("mm: move most file-based accounting to the node") Reviewed-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/osc/osc_page.c b/drivers/staging/lustre/lustre/osc/osc_page.c index 583a0af..c8889ea 100644 --- a/drivers/staging/lustre/lustre/osc/osc_page.c +++ b/drivers/staging/lustre/lustre/osc/osc_page.c @@ -789,7 +789,7 @@ out: /** * Atomic operations are expensive. We accumulate the accounting for the - * same page zone to get better performance. + * same page pgdat to get better performance. * In practice this can work pretty good because the pages in the same RPC * are likely from the same page zone. */ @@ -797,28 +797,28 @@ static inline void unstable_page_accounting(struct ptlrpc_bulk_desc *desc, int factor) { int page_count = desc->bd_iov_count; - void *zone = NULL; + pg_data_t *last = NULL; int count = 0; int i; for (i = 0; i < page_count; i++) { - void *pz = page_zone(desc->bd_iov[i].bv_page); + pg_data_t *pgdat = page_pgdat(desc->bd_iov[i].bv_page); - if (likely(pz == zone)) { + if (likely(pgdat == last)) { ++count; continue; } if (count > 0) { - mod_zone_page_state(zone, NR_UNSTABLE_NFS, + mod_node_page_state(pgdat, NR_UNSTABLE_NFS, factor * count); count = 0; } - zone = pz; + last = pgdat; ++count; } if (count > 0) - mod_zone_page_state(zone, NR_UNSTABLE_NFS, factor * count); + mod_node_page_state(last, NR_UNSTABLE_NFS, factor * count); } static inline void add_unstable_page_accounting(struct ptlrpc_bulk_desc *desc) -- cgit v0.10.2 From d6a80699bad7abb5c05860e3f021a34357a3b4c5 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann <arnd@arndb.de> Date: Mon, 29 Aug 2016 14:20:01 +0200 Subject: staging: lustre: hide unused variable After a code cleanup, we get a harmless warning about a variable that is unused when CONFIG_FS_POSIX_ACL is disabled: drivers/staging/lustre/lustre/llite/xattr.c: In function 'll_xattr_get_common': drivers/staging/lustre/lustre/llite/xattr.c:312:24: error: unused variable 'lli' [-Werror=unused-variable] This puts the variable declaration into the same #ifdef. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Fixes: 1e1f9ff406fd ("staging: lustre: llite: break ll_getxattr_common into 2 functions") Reviewed-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/xattr.c b/drivers/staging/lustre/lustre/llite/xattr.c index f252c26..7b8d469 100644 --- a/drivers/staging/lustre/lustre/llite/xattr.c +++ b/drivers/staging/lustre/lustre/llite/xattr.c @@ -309,7 +309,9 @@ static int ll_xattr_get_common(const struct xattr_handler *handler, { char fullname[strlen(handler->prefix) + strlen(name) + 1]; struct ll_sb_info *sbi = ll_i2sbi(inode); +#ifdef CONFIG_FS_POSIX_ACL struct ll_inode_info *lli = ll_i2info(inode); +#endif int rc; CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p)\n", -- cgit v0.10.2 From 495ea0d99355e550a120b706515d6be55d198ac2 Mon Sep 17 00:00:00 2001 From: Julia Lawall <Julia.Lawall@lip6.fr> Date: Sun, 28 Aug 2016 23:45:11 +0200 Subject: staging: lustre: obdclass: constify obd_psdev_fops structure obd_psdev_fops, of type struct file_operations, is never modified, so declare it as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c index 27a72d8..2b691d8 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c @@ -192,7 +192,7 @@ static long obd_class_ioctl(struct file *filp, unsigned int cmd, } /* declare character device */ -static struct file_operations obd_psdev_fops = { +static const struct file_operations obd_psdev_fops = { .owner = THIS_MODULE, .unlocked_ioctl = obd_class_ioctl, /* unlocked_ioctl */ .open = obd_class_open, /* open */ -- cgit v0.10.2 From a1cd3dd535cbc1ff84935b73cee1a053bf19a210 Mon Sep 17 00:00:00 2001 From: Julia Lawall <Julia.Lawall@lip6.fr> Date: Sun, 28 Aug 2016 23:38:27 +0200 Subject: staging: lustre: constify lprocfs_generic_fops structure lprocfs_generic_fops, of type struct file_operations, is never modified, so declare it as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c index 3d6da74..be6b6af 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c @@ -315,7 +315,7 @@ struct dentry *ldebugfs_add_simple(struct dentry *root, } EXPORT_SYMBOL_GPL(ldebugfs_add_simple); -static struct file_operations lprocfs_generic_fops = { }; +static const struct file_operations lprocfs_generic_fops = { }; int ldebugfs_add_vars(struct dentry *parent, struct lprocfs_vars *list, -- cgit v0.10.2 From faac7a8dca7634591fd8e694d0746fae32cdf98d Mon Sep 17 00:00:00 2001 From: Julia Lawall <Julia.Lawall@lip6.fr> Date: Sun, 28 Aug 2016 23:27:06 +0200 Subject: staging/lustre: constify sops structure sops, of type struct seq_operations, is never modified, so declare it as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c index 327cf63..9bad57d 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c +++ b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c @@ -937,7 +937,7 @@ static int ptlrpc_lprocfs_svc_req_history_show(struct seq_file *s, void *iter) static int ptlrpc_lprocfs_svc_req_history_open(struct inode *inode, struct file *file) { - static struct seq_operations sops = { + static const struct seq_operations sops = { .start = ptlrpc_lprocfs_svc_req_history_start, .stop = ptlrpc_lprocfs_svc_req_history_stop, .next = ptlrpc_lprocfs_svc_req_history_next, -- cgit v0.10.2 From d6e7a2fe932643bc44f7463881969b14e8f4db38 Mon Sep 17 00:00:00 2001 From: Julia Lawall <Julia.Lawall@lip6.fr> Date: Sun, 28 Aug 2016 23:16:07 +0200 Subject: staging: lustre: constify lmv_proc_target_fops structure lmv_proc_target_fops, of type struct file_operations, is never modified, so declare it as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/lmv/lmv_internal.h b/drivers/staging/lustre/lustre/lmv/lmv_internal.h index 3ce17da..c4961d9 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_internal.h +++ b/drivers/staging/lustre/lustre/lmv/lmv_internal.h @@ -164,6 +164,6 @@ struct lmv_tgt_desc /* lproc_lmv.c */ void lprocfs_lmv_init_vars(struct lprocfs_static_vars *lvars); -extern struct file_operations lmv_proc_target_fops; +extern const struct file_operations lmv_proc_target_fops; #endif diff --git a/drivers/staging/lustre/lustre/lmv/lproc_lmv.c b/drivers/staging/lustre/lustre/lmv/lproc_lmv.c index c29c361..d2316c0 100644 --- a/drivers/staging/lustre/lustre/lmv/lproc_lmv.c +++ b/drivers/staging/lustre/lustre/lmv/lproc_lmv.c @@ -202,7 +202,7 @@ static struct lprocfs_vars lprocfs_lmv_obd_vars[] = { { NULL } }; -struct file_operations lmv_proc_target_fops = { +const struct file_operations lmv_proc_target_fops = { .owner = THIS_MODULE, .open = lmv_target_seq_open, .read = seq_read, -- cgit v0.10.2 From 44fae22b36e218ed30d3f4debba9b0c1d3d6fdf1 Mon Sep 17 00:00:00 2001 From: Oleg Drokin <green@linuxhacker.ru> Date: Thu, 25 Aug 2016 13:50:59 -0400 Subject: staging/lustre: Fix max_dirty_mb output in sysfs %ul definitely was supposed to be %lu in the format string, so we print long unsigned int value, not just unsigned int with a letter l added at the end. Signed-off-by: Oleg Drokin <green@linuxhacker.ru> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c index 8f70dd2..bcf005d 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c @@ -95,8 +95,9 @@ LUSTRE_STATIC_UINT_ATTR(timeout, &obd_timeout); static ssize_t max_dirty_mb_show(struct kobject *kobj, struct attribute *attr, char *buf) { - return sprintf(buf, "%ul\n", - obd_max_dirty_pages / (1 << (20 - PAGE_SHIFT))); + return sprintf(buf, "%lu\n", + (unsigned long)obd_max_dirty_pages / + (1 << (20 - PAGE_SHIFT))); } static ssize_t max_dirty_mb_store(struct kobject *kobj, struct attribute *attr, -- cgit v0.10.2 From 608bc9562a4633eb9b0068246384858ea3862618 Mon Sep 17 00:00:00 2001 From: Julia Lawall <Julia.Lawall@lip6.fr> Date: Thu, 1 Sep 2016 00:21:20 +0200 Subject: staging: netlogic: constify ethtool_ops structures Check for ethtool_ops structures that are only stored in the ethtool_ops field of a net_device structure or passed as the second argument to netdev_set_default_ethtool_ops. These contexts are declared const, so ethtool_ops structures that have these properties can be declared as const also. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // <smpl> @r disable optional_qualifier@ identifier i; position p; @@ static struct ethtool_ops i@p = { ... }; @ok1@ identifier r.i; struct net_device e; position p; @@ e.ethtool_ops = &i@p; @ok2@ identifier r.i; expression e; position p; @@ netdev_set_default_ethtool_ops(e, &i@p) @bad@ position p != {r.p,ok1.p,ok2.p}; identifier r.i; @@ i@p @depends on !bad disable optional_qualifier@ identifier r.i; @@ static +const struct ethtool_ops i = { ... }; // </smpl> Suggested-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/netlogic/xlr_net.c b/drivers/staging/netlogic/xlr_net.c index 99445d0..595ac1b 100644 --- a/drivers/staging/netlogic/xlr_net.c +++ b/drivers/staging/netlogic/xlr_net.c @@ -192,7 +192,7 @@ static int xlr_set_settings(struct net_device *ndev, struct ethtool_cmd *ecmd) return phy_ethtool_sset(phydev, ecmd); } -static struct ethtool_ops xlr_ethtool_ops = { +static const struct ethtool_ops xlr_ethtool_ops = { .get_settings = xlr_get_settings, .set_settings = xlr_set_settings, }; -- cgit v0.10.2 From 2218b8fc90a9f6c57de3b1bde6c6c6c30eee07c6 Mon Sep 17 00:00:00 2001 From: Colin Ian King <colin.king@canonical.com> Date: Sun, 28 Aug 2016 12:28:41 +0100 Subject: staging: wilc1000: fix spelling mistake: "retyring" -> "retrying" trivial fix to spelling mistake in dev_err message Signed-off-by: Colin Ian King <colin.king@canonical.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wilc1000/wilc_spi.c b/drivers/staging/wilc1000/wilc_spi.c index 22cf4b7..0f8d625 100644 --- a/drivers/staging/wilc1000/wilc_spi.c +++ b/drivers/staging/wilc1000/wilc_spi.c @@ -871,7 +871,7 @@ static int wilc_spi_init(struct wilc *wilc, bool resume) /* Read failed. Try with CRC off. This might happen when module * is removed but chip isn't reset*/ g_spi.crc_off = 1; - dev_err(&spi->dev, "Failed internal read protocol with CRC on, retyring with CRC off...\n"); + dev_err(&spi->dev, "Failed internal read protocol with CRC on, retrying with CRC off...\n"); if (!spi_internal_read(wilc, WILC_SPI_PROTOCOL_OFFSET, ®)) { /* Reaad failed with both CRC on and off, something went bad */ dev_err(&spi->dev, -- cgit v0.10.2 From 0210737c85860756efa7d936156e8a94412f5d5c Mon Sep 17 00:00:00 2001 From: Johanna Abrahamsson <johanna@mjao.org> Date: Wed, 24 Aug 2016 00:02:27 +0200 Subject: staging: android: ion: Do not BUG on handle client mismatch The ion_free_nolock() function should not BUG on a handle client mismatch. Signed-off-by: Johanna Abrahamsson <johanna@mjao.org> Acked-by: Laura Abbott <labbott@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 88dd17e..bbf13be 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -550,8 +550,6 @@ static void ion_free_nolock(struct ion_client *client, { bool valid_handle; - BUG_ON(client != handle->client); - valid_handle = ion_handle_validate(client, handle); if (!valid_handle) { -- cgit v0.10.2 From c2bbedf01fe7a9901828911c7a2d8c27f48a5f16 Mon Sep 17 00:00:00 2001 From: Johanna Abrahamsson <johanna@mjao.org> Date: Wed, 24 Aug 2016 00:02:45 +0200 Subject: staging: android: ion: Remove valid_handle variable in ion_free_nolock It is not neccessary to save the value of ion_handle_validate since it is only used once. Signed-off-by: Johanna Abrahamsson <johanna@mjao.org> Acked-by: Laura Abbott <labbott@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index bbf13be..4622142 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -548,11 +548,7 @@ EXPORT_SYMBOL(ion_alloc); static void ion_free_nolock(struct ion_client *client, struct ion_handle *handle) { - bool valid_handle; - - valid_handle = ion_handle_validate(client, handle); - - if (!valid_handle) { + if (!ion_handle_validate(client, handle)) { WARN(1, "%s: invalid handle passed to free.\n", __func__); return; } -- cgit v0.10.2 From ef2d4f6c1b8b23639b6f4996a714d642f39facfc Mon Sep 17 00:00:00 2001 From: Aaro Koskinen <aaro.koskinen@iki.fi> Date: Tue, 30 Aug 2016 21:28:11 +0300 Subject: staging: octeon: configure rx-delay/tx-delay Configure rx-delay/tx-delay when available. Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index 2eb9731..073a1e3 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -35,7 +35,7 @@ #include <asm/octeon/cvmx-fau.h> #include <asm/octeon/cvmx-ipd.h> #include <asm/octeon/cvmx-helper.h> - +#include <asm/octeon/cvmx-asxx-defs.h> #include <asm/octeon/cvmx-gmxx-defs.h> #include <asm/octeon/cvmx-smix-defs.h> @@ -647,6 +647,16 @@ static struct device_node *cvm_oct_node_for_port(struct device_node *pip, return np; } +static void cvm_set_rgmii_delay(struct device_node *np, int iface, int port) +{ + u32 delay_value; + + if (!of_property_read_u32(np, "rx-delay", &delay_value)) + cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(port, iface), delay_value); + if (!of_property_read_u32(np, "tx-delay", &delay_value)) + cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(port, iface), delay_value); +} + static int cvm_oct_probe(struct platform_device *pdev) { int num_interfaces; @@ -805,6 +815,8 @@ static int cvm_oct_probe(struct platform_device *pdev) case CVMX_HELPER_INTERFACE_MODE_GMII: dev->netdev_ops = &cvm_oct_rgmii_netdev_ops; strcpy(dev->name, "eth%d"); + cvm_set_rgmii_delay(priv->of_node, interface, + port_index); break; } -- cgit v0.10.2 From 121ca0c64f69d552a9aa27d2bce49f835030ec8b Mon Sep 17 00:00:00 2001 From: Johanna Abrahamsson <johanna@mjao.org> Date: Mon, 22 Aug 2016 12:16:58 +0200 Subject: staging: android: ion: Fix alignment Alignment should match open parenthesis as per checkpatch.pl. Signed-off-by: Johanna Abrahamsson <johanna@mjao.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 4622142..deaa93a 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -174,10 +174,10 @@ static void ion_buffer_add(struct ion_device *dev, /* this function should only be called while dev->lock is held */ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, - struct ion_device *dev, - unsigned long len, - unsigned long align, - unsigned long flags) + struct ion_device *dev, + unsigned long len, + unsigned long align, + unsigned long flags) { struct ion_buffer *buffer; struct sg_table *table; @@ -331,7 +331,7 @@ static void ion_buffer_remove_from_handle(struct ion_buffer *buffer) } static struct ion_handle *ion_handle_create(struct ion_client *client, - struct ion_buffer *buffer) + struct ion_buffer *buffer) { struct ion_handle *handle; @@ -421,7 +421,7 @@ static struct ion_handle *ion_handle_lookup(struct ion_client *client, } static struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client, - int id) + int id) { struct ion_handle *handle; @@ -575,7 +575,7 @@ static void *ion_buffer_kmap_get(struct ion_buffer *buffer) } vaddr = buffer->heap->ops->map_kernel(buffer->heap, buffer); if (WARN_ONCE(vaddr == NULL, - "heap->ops->map_kernel should return ERR_PTR on error")) + "heap->ops->map_kernel should return ERR_PTR on error")) return ERR_PTR(-EINVAL); if (IS_ERR(vaddr)) return vaddr; @@ -744,7 +744,7 @@ static const struct file_operations debug_client_fops = { }; static int ion_get_client_serial(const struct rb_root *root, - const unsigned char *name) + const unsigned char *name) { int serial = -1; struct rb_node *node; @@ -833,7 +833,7 @@ struct ion_client *ion_client_create(struct ion_device *dev, path = dentry_path(dev->clients_debug_root, buf, 256); pr_err("Failed to create client debugfs at %s/%s\n", - path, client->display_name); + path, client->display_name); } up_write(&dev->lock); @@ -901,7 +901,7 @@ static void ion_unmap_dma_buf(struct dma_buf_attachment *attachment, } void ion_pages_sync_for_device(struct device *dev, struct page *page, - size_t size, enum dma_data_direction dir) + size_t size, enum dma_data_direction dir) { struct scatterlist sg; @@ -941,7 +941,7 @@ static void ion_buffer_sync_for_device(struct ion_buffer *buffer, if (ion_buffer_page_is_dirty(page)) ion_pages_sync_for_device(dev, ion_buffer_page(page), - PAGE_SIZE, dir); + PAGE_SIZE, dir); ion_buffer_page_clean(buffer->pages + i); } @@ -1019,7 +1019,7 @@ static int ion_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) if (!buffer->heap->ops->map_user) { pr_err("%s: this heap does not define a method for mapping to userspace\n", - __func__); + __func__); return -EINVAL; } @@ -1110,7 +1110,7 @@ static struct dma_buf_ops dma_buf_ops = { }; struct dma_buf *ion_share_dma_buf(struct ion_client *client, - struct ion_handle *handle) + struct ion_handle *handle) { DEFINE_DMA_BUF_EXPORT_INFO(exp_info); struct ion_buffer *buffer; @@ -1285,9 +1285,9 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) struct ion_handle *handle; handle = ion_alloc(client, data.allocation.len, - data.allocation.align, - data.allocation.heap_id_mask, - data.allocation.flags); + data.allocation.align, + data.allocation.heap_id_mask, + data.allocation.flags); if (IS_ERR(handle)) return PTR_ERR(handle); @@ -1472,7 +1472,7 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused) seq_printf(s, "%16s %16zu\n", "total ", total_size); if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) seq_printf(s, "%16s %16zu\n", "deferred free", - heap->free_list_size); + heap->free_list_size); seq_puts(s, "----------------------------------------------------\n"); if (heap->debug_show) @@ -1554,15 +1554,15 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) plist_node_init(&heap->node, -heap->id); plist_add(&heap->node, &dev->heaps); debug_file = debugfs_create_file(heap->name, 0664, - dev->heaps_debug_root, heap, - &debug_heap_fops); + dev->heaps_debug_root, heap, + &debug_heap_fops); if (!debug_file) { char buf[256], *path; path = dentry_path(dev->heaps_debug_root, buf, 256); pr_err("Failed to create heap debugfs at %s/%s\n", - path, heap->name); + path, heap->name); } if (heap->shrinker.count_objects && heap->shrinker.scan_objects) { @@ -1577,7 +1577,7 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) path = dentry_path(dev->heaps_debug_root, buf, 256); pr_err("Failed to create heap shrinker debugfs at %s/%s\n", - path, debug_name); + path, debug_name); } } -- cgit v0.10.2 From 679011bd69efd7d9a3d4984fadbe0bc544773455 Mon Sep 17 00:00:00 2001 From: Ben LeMasurier <ben@crypt.ly> Date: Mon, 22 Aug 2016 07:45:53 -0600 Subject: Staging: android: ion: fix parenthesis alignment This fixes remaining checkpatch.pl "Alignment should match open parenthesis" issues. Signed-off-by: Ben LeMasurier <ben@crypt.ly> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index 560cf90..70495dc 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -34,9 +34,9 @@ struct ion_chunk_heap { }; static int ion_chunk_heap_allocate(struct ion_heap *heap, - struct ion_buffer *buffer, - unsigned long size, unsigned long align, - unsigned long flags) + struct ion_buffer *buffer, + unsigned long size, unsigned long align, + unsigned long flags) { struct ion_chunk_heap *chunk_heap = container_of(heap, struct ion_chunk_heap, heap); @@ -71,7 +71,7 @@ static int ion_chunk_heap_allocate(struct ion_heap *heap, if (!paddr) goto err; sg_set_page(sg, pfn_to_page(PFN_DOWN(paddr)), - chunk_heap->chunk_size, 0); + chunk_heap->chunk_size, 0); sg = sg_next(sg); } @@ -106,7 +106,7 @@ static void ion_chunk_heap_free(struct ion_buffer *buffer) if (ion_buffer_cached(buffer)) dma_sync_sg_for_device(NULL, table->sgl, table->nents, - DMA_BIDIRECTIONAL); + DMA_BIDIRECTIONAL); for_each_sg(table->sgl, sg, table->nents, i) { gen_pool_free(chunk_heap->pool, page_to_phys(sg_page(sg)), @@ -161,7 +161,7 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data) chunk_heap->heap.type = ION_HEAP_TYPE_CHUNK; chunk_heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE; pr_debug("%s: base %lu size %zu align %ld\n", __func__, - chunk_heap->base, heap_data->size, heap_data->align); + chunk_heap->base, heap_data->size, heap_data->align); return &chunk_heap->heap; diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c index d5ff3a2..6c7de74 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -126,7 +126,7 @@ static void *ion_cma_map_kernel(struct ion_heap *heap, } static void ion_cma_unmap_kernel(struct ion_heap *heap, - struct ion_buffer *buffer) + struct ion_buffer *buffer) { } diff --git a/drivers/staging/android/ion/ion_dummy_driver.c b/drivers/staging/android/ion/ion_dummy_driver.c index 814a3c9..b23f2c7 100644 --- a/drivers/staging/android/ion/ion_dummy_driver.c +++ b/drivers/staging/android/ion/ion_dummy_driver.c @@ -99,7 +99,7 @@ static int __init ion_dummy_init(void) struct ion_platform_heap *heap_data = &dummy_ion_pdata.heaps[i]; if (heap_data->type == ION_HEAP_TYPE_CARVEOUT && - !heap_data->base) + !heap_data->base) continue; if (heap_data->type == ION_HEAP_TYPE_CHUNK && !heap_data->base) @@ -120,12 +120,12 @@ err: if (carveout_ptr) { free_pages_exact(carveout_ptr, - dummy_heaps[ION_HEAP_TYPE_CARVEOUT].size); + dummy_heaps[ION_HEAP_TYPE_CARVEOUT].size); carveout_ptr = NULL; } if (chunk_ptr) { free_pages_exact(chunk_ptr, - dummy_heaps[ION_HEAP_TYPE_CHUNK].size); + dummy_heaps[ION_HEAP_TYPE_CHUNK].size); chunk_ptr = NULL; } return err; @@ -144,12 +144,12 @@ static void __exit ion_dummy_exit(void) if (carveout_ptr) { free_pages_exact(carveout_ptr, - dummy_heaps[ION_HEAP_TYPE_CARVEOUT].size); + dummy_heaps[ION_HEAP_TYPE_CARVEOUT].size); carveout_ptr = NULL; } if (chunk_ptr) { free_pages_exact(chunk_ptr, - dummy_heaps[ION_HEAP_TYPE_CHUNK].size); + dummy_heaps[ION_HEAP_TYPE_CHUNK].size); chunk_ptr = NULL; } } diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index 2c5e5c5..aea89c1 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -115,7 +115,7 @@ static int ion_page_pool_total(struct ion_page_pool *pool, bool high) } int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, - int nr_to_scan) + int nr_to_scan) { int freed = 0; bool high; diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index f1cef2b..7e023d5 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -128,9 +128,9 @@ static struct page *alloc_largest_available(struct ion_system_heap *heap, } static int ion_system_heap_allocate(struct ion_heap *heap, - struct ion_buffer *buffer, - unsigned long size, unsigned long align, - unsigned long flags) + struct ion_buffer *buffer, + unsigned long size, unsigned long align, + unsigned long flags) { struct ion_system_heap *sys_heap = container_of(heap, struct ion_system_heap, @@ -152,7 +152,7 @@ static int ion_system_heap_allocate(struct ion_heap *heap, INIT_LIST_HEAD(&pages); while (size_remaining > 0) { page = alloc_largest_available(sys_heap, buffer, size_remaining, - max_order); + max_order); if (!page) goto free_pages; list_add_tail(&page->lru, &pages); @@ -205,7 +205,7 @@ static void ion_system_heap_free(struct ion_buffer *buffer) } static int ion_system_heap_shrink(struct ion_heap *heap, gfp_t gfp_mask, - int nr_to_scan) + int nr_to_scan) { struct ion_page_pool *uncached_pool; struct ion_page_pool *cached_pool; -- cgit v0.10.2 From 450524614bd2fc05239dd6186eb6d0deec483c24 Mon Sep 17 00:00:00 2001 From: Johanna Abrahamsson <johanna@mjao.org> Date: Wed, 24 Aug 2016 00:41:54 +0200 Subject: staging: android: ion: Remove ret variable in ion_handle_put_nolock It is not necessary to save the return value of kref_put since it is directly returned. Signed-off-by: Johanna Abrahamsson <johanna@mjao.org> Acked-by: Laura Abbott <labbott@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index deaa93a..2671f9f 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -383,11 +383,7 @@ static void ion_handle_get(struct ion_handle *handle) static int ion_handle_put_nolock(struct ion_handle *handle) { - int ret; - - ret = kref_put(&handle->ref, ion_handle_destroy); - - return ret; + return kref_put(&handle->ref, ion_handle_destroy); } static int ion_handle_put(struct ion_handle *handle) -- cgit v0.10.2 From 95eab3910da8590842869a58495d4b145cbb8321 Mon Sep 17 00:00:00 2001 From: Johanna Abrahamsson <johanna@mjao.org> Date: Wed, 24 Aug 2016 00:42:39 +0200 Subject: staging: android: ion: Remove unnused function ion_handle_buffer Remove the function ion_handle_buffer since it is not used anywhere. Signed-off-by: Johanna Abrahamsson <johanna@mjao.org> Acked-by: Laura Abbott <labbott@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 2671f9f..3d2a79b 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -371,11 +371,6 @@ static void ion_handle_destroy(struct kref *kref) kfree(handle); } -struct ion_buffer *ion_handle_buffer(struct ion_handle *handle) -{ - return handle->buffer; -} - static void ion_handle_get(struct ion_handle *handle) { kref_get(&handle->ref); diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index 5eed5e2..fcbc231 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -29,8 +29,6 @@ #include "ion.h" -struct ion_buffer *ion_handle_buffer(struct ion_handle *handle); - /** * struct ion_buffer - metadata for a particular buffer * @ref: reference count -- cgit v0.10.2 From 9924e5de313eb3348a6896b67ea930e92a408936 Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Thu, 25 Aug 2016 11:10:25 -0400 Subject: staging: android: lowmemorykiller.c: Fix checkpatch warning Fix checkpatch.pl 'line over 80 characters' warning Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index 45a1b4e..80d7adf 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -92,8 +92,8 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) int array_size = ARRAY_SIZE(lowmem_adj); int other_free = global_page_state(NR_FREE_PAGES) - totalreserve_pages; int other_file = global_node_page_state(NR_FILE_PAGES) - - global_node_page_state(NR_SHMEM) - - total_swapcache_pages(); + global_node_page_state(NR_SHMEM) - + total_swapcache_pages(); if (lowmem_adj_size < array_size) array_size = lowmem_adj_size; -- cgit v0.10.2 From b2bcdadcf926c6048553530b00826018c2f39481 Mon Sep 17 00:00:00 2001 From: Didik Setiawan <ds@didiksetiawan.com> Date: Wed, 24 Aug 2016 16:08:01 +0700 Subject: staging: android: ion: ion.c fix parenthesis alignment Fix checkpatch.pl warning about "Alignment should match open parenthesis". Signed-off-by: Didik Setiawan <ds@didiksetiawan.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 3d2a79b..47de11a 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -742,7 +742,7 @@ static int ion_get_client_serial(const struct rb_root *root, for (node = rb_first(root); node; node = rb_next(node)) { struct ion_client *client = rb_entry(node, struct ion_client, - node); + node); if (strcmp(client->name, name)) continue; @@ -817,8 +817,8 @@ struct ion_client *ion_client_create(struct ion_device *dev, rb_insert_color(&client->node, &dev->clients); client->debug_root = debugfs_create_file(client->display_name, 0664, - dev->clients_debug_root, - client, &debug_client_fops); + dev->clients_debug_root, + client, &debug_client_fops); if (!client->debug_root) { char buf[256], *path; @@ -1636,4 +1636,3 @@ void ion_device_destroy(struct ion_device *dev) kfree(dev); } EXPORT_SYMBOL(ion_device_destroy); - -- cgit v0.10.2 From 5c2ba8b85e350678b96db57cc8972deb9e47c497 Mon Sep 17 00:00:00 2001 From: Binoy Jayan <binoy.jayan@linaro.org> Date: Mon, 22 Aug 2016 10:09:42 +0530 Subject: rtl8712: pwrctrl_priv: Replace semaphore lock with mutex The semaphore 'lock' in 'pwrctrl_priv' is used as a simple mutex, so it should be written as one. Semaphores are going away in the future. _enter_pwrlock was using down_interruptible(), so the lock could be broken by sending a signal. This could be a bug, because nothing checks the return code here. Hence, using mutex_lock instead of the interruptible version. Removing the now unused _enter_pwrlock and _down_sema. Signed-off-by: Binoy Jayan <binoy.jayan@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Tested-by: Larry Finger <Larry.Finger@lwfinger.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8712/osdep_service.h b/drivers/staging/rtl8712/osdep_service.h index ad041c9..c9ea50d 100644 --- a/drivers/staging/rtl8712/osdep_service.h +++ b/drivers/staging/rtl8712/osdep_service.h @@ -57,13 +57,6 @@ struct __queue { spin_lock_init(&((pqueue)->lock)); \ } while (0) -static inline u32 _down_sema(struct semaphore *sema) -{ - if (down_interruptible(sema)) - return _FAIL; - return _SUCCESS; -} - static inline u32 end_of_queue_search(struct list_head *head, struct list_head *plist) { diff --git a/drivers/staging/rtl8712/rtl8712_cmd.c b/drivers/staging/rtl8712/rtl8712_cmd.c index 3877fcf..9f61583 100644 --- a/drivers/staging/rtl8712/rtl8712_cmd.c +++ b/drivers/staging/rtl8712/rtl8712_cmd.c @@ -264,9 +264,9 @@ static struct cmd_obj *cmd_hdl_filter(struct _adapter *padapter, */ if (padapter->pwrctrlpriv.pwr_mode > PS_MODE_ACTIVE) { padapter->pwrctrlpriv.pwr_mode = PS_MODE_ACTIVE; - _enter_pwrlock(&(padapter->pwrctrlpriv.lock)); + mutex_lock(&padapter->pwrctrlpriv.mutex_lock); r8712_set_rpwm(padapter, PS_STATE_S4); - up(&(padapter->pwrctrlpriv.lock)); + mutex_unlock(&padapter->pwrctrlpriv.mutex_lock); } pcmd_r = pcmd; break; @@ -395,10 +395,10 @@ _next: } if (pcmd->cmdcode == GEN_CMD_CODE(_SetPwrMode)) { if (padapter->pwrctrlpriv.bSleep) { - _enter_pwrlock(&(padapter-> - pwrctrlpriv.lock)); + mutex_lock(&padapter-> + pwrctrlpriv.mutex_lock); r8712_set_rpwm(padapter, PS_STATE_S2); - up(&padapter->pwrctrlpriv.lock); + mutex_unlock(&padapter->pwrctrlpriv.mutex_lock); } } r8712_free_cmd_obj(pcmd); diff --git a/drivers/staging/rtl8712/rtl871x_pwrctrl.c b/drivers/staging/rtl8712/rtl871x_pwrctrl.c index 98a5e74..8d7ead6 100644 --- a/drivers/staging/rtl8712/rtl871x_pwrctrl.c +++ b/drivers/staging/rtl8712/rtl871x_pwrctrl.c @@ -103,14 +103,14 @@ void r8712_cpwm_int_hdl(struct _adapter *padapter, if (pwrpriv->cpwm_tog == ((preportpwrstate->state) & 0x80)) return; del_timer(&padapter->pwrctrlpriv.rpwm_check_timer); - _enter_pwrlock(&pwrpriv->lock); + mutex_lock(&pwrpriv->mutex_lock); pwrpriv->cpwm = (preportpwrstate->state) & 0xf; if (pwrpriv->cpwm >= PS_STATE_S2) { if (pwrpriv->alives & CMD_ALIVE) complete(&(pcmdpriv->cmd_queue_comp)); } pwrpriv->cpwm_tog = (preportpwrstate->state) & 0x80; - up(&pwrpriv->lock); + mutex_unlock(&pwrpriv->mutex_lock); } static inline void register_task_alive(struct pwrctrl_priv *pwrctrl, uint tag) @@ -141,10 +141,10 @@ static void SetPSModeWorkItemCallback(struct work_struct *work) struct _adapter *padapter = container_of(pwrpriv, struct _adapter, pwrctrlpriv); if (!pwrpriv->bSleep) { - _enter_pwrlock(&pwrpriv->lock); + mutex_lock(&pwrpriv->mutex_lock); if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) r8712_set_rpwm(padapter, PS_STATE_S4); - up(&pwrpriv->lock); + mutex_lock(&pwrpriv->mutex_lock); } } @@ -155,11 +155,11 @@ static void rpwm_workitem_callback(struct work_struct *work) struct _adapter *padapter = container_of(pwrpriv, struct _adapter, pwrctrlpriv); if (pwrpriv->cpwm != pwrpriv->rpwm) { - _enter_pwrlock(&pwrpriv->lock); + mutex_lock(&pwrpriv->mutex_lock); r8712_read8(padapter, SDIO_HCPWM); pwrpriv->rpwm_retry = 1; r8712_set_rpwm(padapter, pwrpriv->rpwm); - up(&pwrpriv->lock); + mutex_unlock(&pwrpriv->mutex_lock); } } @@ -175,7 +175,7 @@ void r8712_init_pwrctrl_priv(struct _adapter *padapter) struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; memset((unsigned char *)pwrctrlpriv, 0, sizeof(struct pwrctrl_priv)); - sema_init(&pwrctrlpriv->lock, 1); + mutex_init(&pwrctrlpriv->mutex_lock); pwrctrlpriv->cpwm = PS_STATE_S4; pwrctrlpriv->pwr_mode = PS_MODE_ACTIVE; pwrctrlpriv->smart_ps = 0; @@ -207,13 +207,13 @@ sint r8712_register_cmd_alive(struct _adapter *padapter) uint res = _SUCCESS; struct pwrctrl_priv *pwrctrl = &padapter->pwrctrlpriv; - _enter_pwrlock(&pwrctrl->lock); + mutex_lock(&pwrctrl->mutex_lock); register_task_alive(pwrctrl, CMD_ALIVE); if (pwrctrl->cpwm < PS_STATE_S2) { r8712_set_rpwm(padapter, PS_STATE_S3); res = _FAIL; } - up(&pwrctrl->lock); + mutex_unlock(&pwrctrl->mutex_lock); return res; } @@ -229,7 +229,7 @@ void r8712_unregister_cmd_alive(struct _adapter *padapter) { struct pwrctrl_priv *pwrctrl = &padapter->pwrctrlpriv; - _enter_pwrlock(&pwrctrl->lock); + mutex_lock(&pwrctrl->mutex_lock); unregister_task_alive(pwrctrl, CMD_ALIVE); if ((pwrctrl->cpwm > PS_STATE_S2) && (pwrctrl->pwr_mode > PS_MODE_ACTIVE)) { @@ -239,5 +239,5 @@ void r8712_unregister_cmd_alive(struct _adapter *padapter) r8712_set_rpwm(padapter, PS_STATE_S0); } } - up(&pwrctrl->lock); + mutex_unlock(&pwrctrl->mutex_lock); } diff --git a/drivers/staging/rtl8712/rtl871x_pwrctrl.h b/drivers/staging/rtl8712/rtl871x_pwrctrl.h index dbfb555..231445e 100644 --- a/drivers/staging/rtl8712/rtl871x_pwrctrl.h +++ b/drivers/staging/rtl8712/rtl871x_pwrctrl.h @@ -87,13 +87,8 @@ struct reportpwrstate_parm { unsigned short rsvd; }; -static inline void _enter_pwrlock(struct semaphore *plock) -{ - _down_sema(plock); -} - struct pwrctrl_priv { - struct semaphore lock; + struct mutex mutex_lock; /*volatile*/ u8 rpwm; /* requested power state for fw */ /* fw current power state. updated when 1. read from HCPWM or * 2. driver lowers power level */ -- cgit v0.10.2 From db0c12744f8d7ab3d5cbeb80c6705bc8134d5f53 Mon Sep 17 00:00:00 2001 From: Matthias Beyer <mail@beyermatthias.de> Date: Tue, 23 Aug 2016 21:44:17 +0200 Subject: drivers: staging: rtl8723au: hal: Remove pointless test This patch removes the pointless `else if` test. Signed-off-by: Matthias Beyer <mail@beyermatthias.de> Reported-by: David Binderman <linuxdev.baldrick@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c b/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c index 6989580..47e8d69 100644 --- a/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c +++ b/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c @@ -3530,7 +3530,7 @@ bthci_CmdLinkStatusNotify( pBtMgnt->ExtConfig.linkInfo[i].BTProfile, pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec)); pTriple += 4; - } else if (pBtMgnt->ExtConfig.HCIExtensionVer >= 1) { + } else { pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle = *((u16 *)&pTriple[0]); pBtMgnt->ExtConfig.linkInfo[i].BTProfile = pTriple[2]; pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec = pTriple[3]; -- cgit v0.10.2 From 228fc25904587826f99e6fb2275b3553cf4f74ed Mon Sep 17 00:00:00 2001 From: MingChia Chung <quexint@gmail.com> Date: Sun, 28 Aug 2016 09:04:36 +0800 Subject: staging: rts5208: Add two blank lines in comments. This patch fixes a minor checkpatch warnings: "WARNING: Block comments use a trailing */ on a separate line" Signed-off-by: Ming-Chia Chung <Quexint@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index e992e03..d75fa8d 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -81,14 +81,16 @@ static int slave_alloc(struct scsi_device *sdev) static int slave_configure(struct scsi_device *sdev) { - /* Scatter-gather buffers (all but the last) must have a length + /* + * Scatter-gather buffers (all but the last) must have a length * divisible by the bulk maxpacket size. Otherwise a data packet * would end up being short, causing a premature end to the data * transfer. Since high-speed bulk pipes have a maxpacket size * of 512, we'll use that as the scsi device queue's DMA alignment * mask. Guaranteeing proper alignment of the first buffer will * have the desired effect because, except at the beginning and - * the end, scatter-gather buffers follow page boundaries. */ + * the end, scatter-gather buffers follow page boundaries. + */ blk_queue_dma_alignment(sdev->request_queue, (512 - 1)); /* Set the SCSI level to at least 2. We'll leave it at 3 if that's @@ -185,8 +187,10 @@ static int command_abort(struct scsi_cmnd *srb) return SUCCESS; } -/* This invokes the transport reset mechanism to reset the state of the - * device */ +/* + * This invokes the transport reset mechanism to reset the state of the + * device + */ static int device_reset(struct scsi_cmnd *srb) { int result = 0; @@ -654,15 +658,19 @@ static void rtsx_release_resources(struct rtsx_dev *dev) kfree(dev->chip); } -/* First stage of disconnect processing: stop all commands and remove - * the host */ +/* + * First stage of disconnect processing: stop all commands and remove + * the host + */ static void quiesce_and_remove_host(struct rtsx_dev *dev) { struct Scsi_Host *host = rtsx_to_host(dev); struct rtsx_chip *chip = dev->chip; - /* Prevent new transfers, stop the current command, and - * interrupt a SCSI-scan or device-reset delay */ + /* + * Prevent new transfers, stop the current command, and + * interrupt a SCSI-scan or device-reset delay + */ mutex_lock(&dev->dev_mutex); scsi_lock(host); rtsx_set_stat(chip, RTSX_STAT_DISCONNECT); @@ -674,9 +682,11 @@ static void quiesce_and_remove_host(struct rtsx_dev *dev) /* Wait some time to let other threads exist */ wait_timeout(100); - /* queuecommand won't accept any new commands and the control + /* + * queuecommand won't accept any new commands and the control * thread won't execute a previously-queued command. If there - * is such a command pending, complete it with an error. */ + * is such a command pending, complete it with an error. + */ mutex_lock(&dev->dev_mutex); if (chip->srb) { chip->srb->result = DID_NO_CONNECT << 16; @@ -696,8 +706,10 @@ static void release_everything(struct rtsx_dev *dev) { rtsx_release_resources(dev); - /* Drop our reference to the host; the SCSI core will free it - * when the refcount becomes 0. */ + /* + * Drop our reference to the host; the SCSI core will free it + * when the refcount becomes 0. + */ scsi_host_put(rtsx_to_host(dev)); } @@ -936,8 +948,10 @@ static int rtsx_probe(struct pci_dev *pci, rtsx_init_chip(dev->chip); - /* set the supported max_lun and max_id for the scsi host - * NOTE: the minimal value of max_id is 1 */ + /* + * set the supported max_lun and max_id for the scsi host + * NOTE: the minimal value of max_id is 1 + */ host->max_id = 1; host->max_lun = dev->chip->max_lun; -- cgit v0.10.2 From 371fbcf6736a751256bf1cc6110fcba610a7c4c4 Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Mon, 22 Aug 2016 17:12:15 -0400 Subject: staging: vt6655: rf.c: Fix checkpatch warning Fix checkpatch.pl warning for trailing */ on a separate line Remove '+' postfix and '-' prefix from the start and end of block comments Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c index ae10da2..447882c 100644 --- a/drivers/staging/vt6655/rf.c +++ b/drivers/staging/vt6655/rf.c @@ -169,7 +169,8 @@ static unsigned long dwAL2230PowerTable[AL2230_PWR_IDX_LEN] = { }; /* 40MHz reference frequency - * Need to Pull PLLON(PE3) low when writing channel registers through 3-wire.*/ + * Need to Pull PLLON(PE3) low when writing channel registers through 3-wire. + */ static const unsigned long dwAL7230InitTable[CB_AL7230_INIT_SEQ] = { 0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Channel1 // Need modify for 11a */ 0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Channel1 // Need modify for 11a */ @@ -463,7 +464,8 @@ static bool s_bAL7230Init(struct vnt_private *priv) } /* Need to Pull PLLON low when writing channel registers through - * 3-wire interface */ + * 3-wire interface + */ static bool s_bAL7230SelectChannel(struct vnt_private *priv, unsigned char byChannel) { void __iomem *dwIoBase = priv->PortOffset; @@ -873,7 +875,8 @@ bool RFbRawSetPower( case RF_AIROHA7230: /* 0x080F1B00 for 3 wire control TxGain(D10) - * and 0x31 as TX Gain value */ + * and 0x31 as TX Gain value + */ dwMax7230Pwr = 0x080C0B00 | ((byPwr) << 12) | (BY_AL7230_REG_LEN << 3) | IFREGCTL_REGW; @@ -886,7 +889,7 @@ bool RFbRawSetPower( return ret; } -/*+ +/* * * Routine Description: * Translate RSSI to dBm @@ -900,7 +903,7 @@ bool RFbRawSetPower( * * Return Value: none * - -*/ + */ void RFvRSSITodBm( struct vnt_private *priv, @@ -927,7 +930,8 @@ RFvRSSITodBm( } /* Post processing for the 11b/g and 11a. - * for save time on changing Reg2,3,5,7,10,12,15 */ + * for save time on changing Reg2,3,5,7,10,12,15 + */ bool RFbAL7230SelectChannelPostProcess(struct vnt_private *priv, u16 byOldChannel, u16 byNewChannel) @@ -938,7 +942,8 @@ bool RFbAL7230SelectChannelPostProcess(struct vnt_private *priv, /* if change between 11 b/g and 11a need to update the following * register - * Channel Index 1~14 */ + * Channel Index 1~14 + */ if ((byOldChannel <= CB_MAX_CHANNEL_24G) && (byNewChannel > CB_MAX_CHANNEL_24G)) { /* Change from 2.4G to 5G [Reg] */ ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[2]); -- cgit v0.10.2 From f46e041a20dd9c3b4fa6f07e3246424aec7f1752 Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Mon, 22 Aug 2016 17:12:35 -0400 Subject: staging: vt6655: rxtx.c: Fix checkpatch warning Fix checkpatch.pl warning for trailing */ on a separate line Remove '+' postfix and '-' prefix from the start and end of block comments Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c index e4c3165..890d108 100644 --- a/drivers/staging/vt6655/rxtx.c +++ b/drivers/staging/vt6655/rxtx.c @@ -64,8 +64,10 @@ /*--------------------- Static Functions --------------------------*/ /*--------------------- Static Definitions -------------------------*/ -#define CRITICAL_PACKET_LEN 256 /* if packet size < 256 -> in-direct send - packet size >= 256 -> direct send */ +/* if packet size < 256 -> in-direct send + * vpacket size >= 256 -> direct send + */ +#define CRITICAL_PACKET_LEN 256 static const unsigned short wTimeStampOff[2][MAX_RATE] = { {384, 288, 226, 209, 54, 43, 37, 31, 28, 25, 24, 23}, /* Long Preamble */ @@ -158,11 +160,11 @@ static __le16 vnt_time_stamp_off(struct vnt_private *priv, u16 rate) [rate % MAX_RATE]); } -/*byPktType : PK_TYPE_11A 0 - PK_TYPE_11B 1 - PK_TYPE_11GB 2 - PK_TYPE_11GA 3 -*/ +/* byPktType : PK_TYPE_11A 0 + * PK_TYPE_11B 1 + * PK_TYPE_11GB 2 + * PK_TYPE_11GA 3 + */ static unsigned int s_uGetTxRsvTime( @@ -650,13 +652,16 @@ s_vFillRTSHead( return; if (bDisCRC) { - /* When CRCDIS bit is on, H/W forgot to generate FCS for RTS frame, - in this case we need to decrease its length by 4. */ + /* When CRCDIS bit is on, H/W forgot to generate FCS for + * RTS frame, in this case we need to decrease its length by 4. + */ uRTSFrameLen -= 4; } - /* Note: So far RTSHead doesn't appear in ATIM & Beacom DMA, so we don't need to take them into account. - Otherwise, we need to modify codes for them. */ + /* Note: So far RTSHead doesn't appear in ATIM & Beacom DMA, + * so we don't need to take them into account. + * Otherwise, we need to modify codes for them. + */ if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) { if (byFBOption == AUTO_FB_NONE) { struct vnt_rts_g *buf = pvRTS; @@ -842,8 +847,9 @@ s_vFillCTSHead( return; if (bDisCRC) { - /* When CRCDIS bit is on, H/W forgot to generate FCS for CTS frame, - in this case we need to decrease its length by 4. */ + /* When CRCDIS bit is on, H/W forgot to generate FCS for + * CTS frame, in this case we need to decrease its length by 4. + */ uCTSFrameLen -= 4; } @@ -915,7 +921,7 @@ s_vFillCTSHead( } } -/*+ +/* * * Description: * Generate FIFO control for MAC & Baseband controller @@ -937,7 +943,8 @@ s_vFillCTSHead( * Return Value: none * - - * unsigned int cbFrameSize, Hdr+Payload+FCS */ + * unsigned int cbFrameSize, Hdr+Payload+FCS + */ static void s_vGenerateTxParameter( @@ -972,8 +979,8 @@ s_vGenerateTxParameter( return; if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) { - if (pvRTS != NULL) { /* RTS_need - Fill RsvTime */ + if (pvRTS != NULL) { /* RTS_need */ + /* Fill RsvTime */ struct vnt_rrv_time_rts *buf = pvRrvTime; buf->rts_rrv_time_aa = s_uGetRTSCTSRsvTime(pDevice, 2, byPktType, cbFrameSize, wCurrentRate); -- cgit v0.10.2 From cb14a0b4a13ee743bbe40299ce46790ee9ef7f1d Mon Sep 17 00:00:00 2001 From: Colin Ian King <colin.king@canonical.com> Date: Mon, 22 Aug 2016 19:40:05 +0100 Subject: Staging: comedi: fix spelling mistake "Firmare" -> "Firmware" Trivial fix to spelling mistake in dev_dbg message. Signed-off-by: Colin Ian King <colin.king@canonical.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c index 6c4ff02..b9b686e 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.c +++ b/drivers/staging/comedi/drivers/jr3_pci.c @@ -739,7 +739,7 @@ static int jr3_pci_auto_attach(struct comedi_device *dev, ret = comedi_load_firmware(dev, &comedi_to_pci_dev(dev)->dev, "comedi/jr3pci.idm", jr3_download_firmware, 0); - dev_dbg(dev->class_dev, "Firmare load %d\n", ret); + dev_dbg(dev->class_dev, "Firmware load %d\n", ret); if (ret < 0) return ret; /* -- cgit v0.10.2 From 37f92cf0a5b82be433b8b24b7105bb9f878f7153 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea <claudiu.beznea@gmail.com> Date: Tue, 23 Aug 2016 21:26:42 +0300 Subject: Staging: wlan-ng: Improved case statements in p80211req_mibset_mibget() This patch improves code from p80211req_mibset_mibget() function by taking into account that every DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKeyX with X in {0, 1, 2, 3} is a bit mask where the (P80211DID_MASK_ITEM << P80211DID_LSB_ITEM) mask aka 0x0x0003f000 mask keeps bits representing the DID item number. To get this item number use P80211DID_ITEM(). Signed-off-by: Claudiu Beznea <claudiu.beznea@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/p80211req.c b/drivers/staging/wlan-ng/p80211req.c index 4b84b56..3849637 100644 --- a/drivers/staging/wlan-ng/p80211req.c +++ b/drivers/staging/wlan-ng/p80211req.c @@ -185,26 +185,16 @@ static void p80211req_mibset_mibget(wlandevice_t *wlandev, u8 *key = mibitem->data + sizeof(p80211pstrd_t); switch (mibitem->did) { - case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0:{ + case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0: + case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1: + case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2: + case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3: if (!isget) - wep_change_key(wlandev, 0, key, pstr->len); - break; - } - case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1:{ - if (!isget) - wep_change_key(wlandev, 1, key, pstr->len); - break; - } - case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2:{ - if (!isget) - wep_change_key(wlandev, 2, key, pstr->len); - break; - } - case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3:{ - if (!isget) - wep_change_key(wlandev, 3, key, pstr->len); - break; - } + wep_change_key(wlandev, + P80211DID_ITEM(mibitem->did) - 1, + key, pstr->len); + break; + case DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID:{ u32 *data = (u32 *) mibitem->data; -- cgit v0.10.2 From 2f4791255808bd0d258400b4cf230c16ea8bdeae Mon Sep 17 00:00:00 2001 From: Claudiu Beznea <claudiu.beznea@gmail.com> Date: Thu, 25 Aug 2016 20:03:25 +0300 Subject: Staging: wlan-ng: removed duplicate code in p80211req.c This patch removes duplicate code in p80211req_mibset_mibget() by adding p80211req_handle_action() function. Changes since v1: Removed prototype of p80211req_handle_action() from the prototype list and add directly the function definition. Signed-off-by: Claudiu Beznea <claudiu.beznea@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/p80211req.c b/drivers/staging/wlan-ng/p80211req.c index 3849637..5c2b801 100644 --- a/drivers/staging/wlan-ng/p80211req.c +++ b/drivers/staging/wlan-ng/p80211req.c @@ -77,6 +77,21 @@ static void p80211req_mibset_mibget(wlandevice_t *wlandev, struct p80211msg_dot11req_mibget *mib_msg, int isget); +static void p80211req_handle_action(struct wlandevice *wlandev, u32 *data, + int isget, u32 flag) +{ + if (isget) { + if (wlandev->hostwep & flag) + *data = P80211ENUM_truth_true; + else + *data = P80211ENUM_truth_false; + } else { + wlandev->hostwep &= ~flag; + if (*data == P80211ENUM_truth_true) + wlandev->hostwep |= flag; + } +} + /*---------------------------------------------------------------- * p80211req_dorequest * @@ -209,31 +224,15 @@ static void p80211req_mibset_mibget(wlandevice_t *wlandev, case DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked:{ u32 *data = (u32 *) mibitem->data; - if (isget) { - if (wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) - *data = P80211ENUM_truth_true; - else - *data = P80211ENUM_truth_false; - } else { - wlandev->hostwep &= ~(HOSTWEP_PRIVACYINVOKED); - if (*data == P80211ENUM_truth_true) - wlandev->hostwep |= HOSTWEP_PRIVACYINVOKED; - } + p80211req_handle_action(wlandev, data, isget, + HOSTWEP_PRIVACYINVOKED); break; } case DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted:{ u32 *data = (u32 *) mibitem->data; - if (isget) { - if (wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED) - *data = P80211ENUM_truth_true; - else - *data = P80211ENUM_truth_false; - } else { - wlandev->hostwep &= ~(HOSTWEP_EXCLUDEUNENCRYPTED); - if (*data == P80211ENUM_truth_true) - wlandev->hostwep |= HOSTWEP_EXCLUDEUNENCRYPTED; - } + p80211req_handle_action(wlandev, data, isget, + HOSTWEP_EXCLUDEUNENCRYPTED); break; } } -- cgit v0.10.2 From 0ca6d8e74489b08aa34108fe00fc1ba1667301a7 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea <claudiu.beznea@gmail.com> Date: Fri, 26 Aug 2016 20:58:17 +0300 Subject: Staging: wlan-ng: replace switch-case statements with macro This patch removes multiple switch-case statements with a new macro. The macro will generate the corresponding bit mask based on the key index received as input. Chances since v1: Corrected patch title Signed-off-by: Claudiu Beznea <claudiu.beznea@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index f46dfe6..a36e40d 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -150,6 +150,9 @@ static int prism2_add_key(struct wiphy *wiphy, struct net_device *dev, int err = 0; int result = 0; + if (key_index >= NUM_WEPKEYS) + return -EINVAL; + switch (params->cipher) { case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: @@ -160,27 +163,7 @@ static int prism2_add_key(struct wiphy *wiphy, struct net_device *dev, goto exit; /* send key to driver */ - switch (key_index) { - case 0: - did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0; - break; - - case 1: - did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1; - break; - - case 2: - did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2; - break; - - case 3: - did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3; - break; - - default: - err = -EINVAL; - goto exit; - } + did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(key_index + 1); result = prism2_domibset_pstr32(wlandev, did, params->key_len, params->key); @@ -242,36 +225,13 @@ static int prism2_del_key(struct wiphy *wiphy, struct net_device *dev, * a key, so we will cheat by setting the key to a bogus value */ - /* send key to driver */ - switch (key_index) { - case 0: - did = - DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0; - break; - - case 1: - did = - DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1; - break; - - case 2: - did = - DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2; - break; - - case 3: - did = - DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3; - break; - - default: - err = -EINVAL; - goto exit; - } + if (key_index >= NUM_WEPKEYS) + return -EINVAL; + /* send key to driver */ + did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(key_index + 1); result = prism2_domibset_pstr32(wlandev, did, 13, "0000000000000"); -exit: if (result) err = -EFAULT; @@ -529,6 +489,11 @@ static int prism2_connect(struct wiphy *wiphy, struct net_device *dev, /* Set the encryption - we only support wep */ if (is_wep) { if (sme->key) { + if (sme->key_idx >= NUM_WEPKEYS) { + err = -EINVAL; + goto exit; + } + result = prism2_domibset_uint32(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, sme->key_idx); @@ -536,28 +501,8 @@ static int prism2_connect(struct wiphy *wiphy, struct net_device *dev, goto exit; /* send key to driver */ - switch (sme->key_idx) { - case 0: - did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0; - break; - - case 1: - did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1; - break; - - case 2: - did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2; - break; - - case 3: - did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3; - break; - - default: - err = -EINVAL; - goto exit; - } - + did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_key( + sme->key_idx + 1); result = prism2_domibset_pstr32(wlandev, did, sme->key_len, (u8 *)sme->key); diff --git a/drivers/staging/wlan-ng/p80211metadef.h b/drivers/staging/wlan-ng/p80211metadef.h index 0ccfba1..98fda3d 100644 --- a/drivers/staging/wlan-ng/p80211metadef.h +++ b/drivers/staging/wlan-ng/p80211metadef.h @@ -171,6 +171,10 @@ (P80211DID_MKSECTION(1) | \ P80211DID_MKGROUP(4) | \ P80211DID_MKITEM(4) | 0x0c000000) +#define DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(_i) \ + (P80211DID_MKSECTION(1) | \ + P80211DID_MKGROUP(4) | \ + P80211DID_MKITEM(_i) | 0x0c000000) #define DIDmib_dot11smt_dot11PrivacyTable \ (P80211DID_MKSECTION(1) | \ P80211DID_MKGROUP(6)) -- cgit v0.10.2 From dda3e26501b153757ad0adbb9f2360612e1edf24 Mon Sep 17 00:00:00 2001 From: Julia Lawall <Julia.Lawall@lip6.fr> Date: Wed, 31 Aug 2016 09:30:43 +0200 Subject: staging: slicoss: constify ethtool_ops structures Check for ethtool_ops structures that are only stored in the ethtool_ops field of a net_device structure or passed as the second argument to netdev_set_default_ethtool_ops. These contexts are declared const, so ethtool_ops structures that have these properties can be declared as const also. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // <smpl> @r disable optional_qualifier@ identifier i; position p; @@ static struct ethtool_ops i@p = { ... }; @ok1@ identifier r.i; struct net_device e; position p; @@ e.ethtool_ops = &i@p; @ok2@ identifier r.i; expression e; position p; @@ netdev_set_default_ethtool_ops(e, &i@p) @bad@ position p != {r.p,ok1.p,ok2.p}; identifier r.i; @@ i@p @depends on !bad disable optional_qualifier@ identifier r.i; @@ static +const struct ethtool_ops i = { ... }; // </smpl> Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index 7834bda..21280a3 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -124,7 +124,7 @@ static const struct pci_device_id slic_pci_tbl[] = { { 0 } }; -static struct ethtool_ops slic_ethtool_ops; +static const struct ethtool_ops slic_ethtool_ops; MODULE_DEVICE_TABLE(pci, slic_pci_tbl); @@ -3128,7 +3128,7 @@ static void __exit slic_module_cleanup(void) pci_unregister_driver(&slic_driver); } -static struct ethtool_ops slic_ethtool_ops = { +static const struct ethtool_ops slic_ethtool_ops = { .get_coalesce = slic_get_coalesce, .set_coalesce = slic_set_coalesce }; -- cgit v0.10.2 From 8e02a3fd03d5391a83ba05b12f5f8d1a0e4e31a4 Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Thu, 25 Aug 2016 11:18:42 -0400 Subject: staging: emxx_udc: Fix checkpatch warning Fix checkpatch.pl warning Block comments use * on subsequent lines Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/emxx_udc/emxx_udc.c b/drivers/staging/emxx_udc/emxx_udc.c index 3b56b28..f4d9000 100644 --- a/drivers/staging/emxx_udc/emxx_udc.c +++ b/drivers/staging/emxx_udc/emxx_udc.c @@ -2264,9 +2264,7 @@ static int _nbu2ss_enable_controller(struct nbu2ss_udc *udc) if (udc->udc_enabled) return 0; - /* - Reset - */ + /* Reset */ _nbu2ss_bitset(&udc->p_regs->EPCTR, (DIRPD | EPC_RST)); udelay(EPC_RST_DISABLE_TIME); /* 1us wait */ -- cgit v0.10.2 From eaf47b713b602e7d0129ed8d18d2818246a17e49 Mon Sep 17 00:00:00 2001 From: Wei Yongjun <weiyongjun1@huawei.com> Date: Fri, 26 Aug 2016 14:45:05 +0000 Subject: staging: rtl8188eu: fix missing unlock on error in rtw_resume_process() Add the missing unlock before return from function rtw_resume_process() in the error handling case. Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c index a5ba1e4..7da3534 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c @@ -315,8 +315,10 @@ static int rtw_resume_process(struct adapter *padapter) ret = 0; exit: - if (pwrpriv) + if (pwrpriv) { pwrpriv->bInSuspend = false; + mutex_unlock(&pwrpriv->mutex_lock); + } pr_debug("<=== %s return %d.............. in %dms\n", __func__, ret, jiffies_to_msecs(jiffies - start_time)); -- cgit v0.10.2 From c37ebf8c3da2b0ae6a2b7942c0d61d04f541ab2d Mon Sep 17 00:00:00 2001 From: Stuart Yoder <stuart.yoder@nxp.com> Date: Tue, 23 Aug 2016 17:13:04 -0500 Subject: staging: fsl-mc: rename mc-private.h to mc-bus.h The definitions in mc-private.h are not strictly speaking 'private', they are bus-related definitions expected to be referenced by bus driver components as well as system components (gic, smmu, vfio). Rename mc-private.h to mc-bus.h to more accurately reflect expected use. Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c index 0523ba8..83e72b3 100644 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c +++ b/drivers/staging/fsl-mc/bus/dprc-driver.c @@ -9,7 +9,7 @@ * warranty of any kind, whether express or implied. */ -#include "../include/mc-private.h" +#include "../include/mc-bus.h" #include "../include/mc-sys.h" #include <linux/module.h> #include <linux/slab.h> diff --git a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c index d0c20d6..aac4379 100644 --- a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c +++ b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c @@ -9,7 +9,7 @@ * warranty of any kind, whether express or implied. */ -#include "../include/mc-private.h" +#include "../include/mc-bus.h" #include <linux/of_device.h> #include <linux/of_address.h> #include <linux/irqchip/arm-gic-v3.h> diff --git a/drivers/staging/fsl-mc/bus/mc-allocator.c b/drivers/staging/fsl-mc/bus/mc-allocator.c index 0f50a07..3ebaecb 100644 --- a/drivers/staging/fsl-mc/bus/mc-allocator.c +++ b/drivers/staging/fsl-mc/bus/mc-allocator.c @@ -8,7 +8,7 @@ * warranty of any kind, whether express or implied. */ -#include "../include/mc-private.h" +#include "../include/mc-bus.h" #include "../include/mc-sys.h" #include <linux/module.h> #include "../include/dpbp-cmd.h" diff --git a/drivers/staging/fsl-mc/bus/mc-bus.c b/drivers/staging/fsl-mc/bus/mc-bus.c index fe20c5d..975d30b 100644 --- a/drivers/staging/fsl-mc/bus/mc-bus.c +++ b/drivers/staging/fsl-mc/bus/mc-bus.c @@ -9,7 +9,7 @@ * warranty of any kind, whether express or implied. */ -#include "../include/mc-private.h" +#include "../include/mc-bus.h" #include <linux/module.h> #include <linux/of_device.h> #include <linux/of_address.h> diff --git a/drivers/staging/fsl-mc/bus/mc-msi.c b/drivers/staging/fsl-mc/bus/mc-msi.c index c7be156..6e39a98 100644 --- a/drivers/staging/fsl-mc/bus/mc-msi.c +++ b/drivers/staging/fsl-mc/bus/mc-msi.c @@ -9,7 +9,7 @@ * warranty of any kind, whether express or implied. */ -#include "../include/mc-private.h" +#include "../include/mc-bus.h" #include <linux/of_device.h> #include <linux/of_address.h> #include <linux/irqchip/arm-gic-v3.h> diff --git a/drivers/staging/fsl-mc/include/mc-bus.h b/drivers/staging/fsl-mc/include/mc-bus.h new file mode 100644 index 0000000..7f847e6 --- /dev/null +++ b/drivers/staging/fsl-mc/include/mc-bus.h @@ -0,0 +1,158 @@ +/* + * Freescale Management Complex (MC) bus declarations + * + * Copyright (C) 2014 Freescale Semiconductor, Inc. + * Author: German Rivera <German.Rivera@freescale.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ +#ifndef _FSL_MC_MCBUS_H_ +#define _FSL_MC_MCBUS_H_ + +#include "../include/mc.h" +#include <linux/mutex.h> +#include <linux/stringify.h> + +#define FSL_MC_DPRC_DRIVER_NAME "fsl_mc_dprc" + +#define FSL_MC_DEVICE_MATCH(_mc_dev, _obj_desc) \ + (strcmp((_mc_dev)->obj_desc.type, (_obj_desc)->type) == 0 && \ + (_mc_dev)->obj_desc.id == (_obj_desc)->id) + +#define FSL_MC_IS_ALLOCATABLE(_obj_type) \ + (strcmp(_obj_type, "dpbp") == 0 || \ + strcmp(_obj_type, "dpmcp") == 0 || \ + strcmp(_obj_type, "dpcon") == 0) + +struct irq_domain; +struct msi_domain_info; + +/** + * Maximum number of total IRQs that can be pre-allocated for an MC bus' + * IRQ pool + */ +#define FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS 256 + +struct device_node; +struct irq_domain; +struct msi_domain_info; + +/** + * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device + * @root_mc_bus_dev: MC object device representing the root DPRC + * @num_translation_ranges: number of entries in addr_translation_ranges + * @translation_ranges: array of bus to system address translation ranges + */ +struct fsl_mc { + struct fsl_mc_device *root_mc_bus_dev; + u8 num_translation_ranges; + struct fsl_mc_addr_translation_range *translation_ranges; +}; + +/** + * struct fsl_mc_addr_translation_range - bus to system address translation + * range + * @mc_region_type: Type of MC region for the range being translated + * @start_mc_offset: Start MC offset of the range being translated + * @end_mc_offset: MC offset of the first byte after the range (last MC + * offset of the range is end_mc_offset - 1) + * @start_phys_addr: system physical address corresponding to start_mc_addr + */ +struct fsl_mc_addr_translation_range { + enum dprc_region_type mc_region_type; + u64 start_mc_offset; + u64 end_mc_offset; + phys_addr_t start_phys_addr; +}; + +/** + * struct fsl_mc_resource_pool - Pool of MC resources of a given + * type + * @type: type of resources in the pool + * @max_count: maximum number of resources in the pool + * @free_count: number of free resources in the pool + * @mutex: mutex to serialize access to the pool's free list + * @free_list: anchor node of list of free resources in the pool + * @mc_bus: pointer to the MC bus that owns this resource pool + */ +struct fsl_mc_resource_pool { + enum fsl_mc_pool_type type; + int16_t max_count; + int16_t free_count; + struct mutex mutex; /* serializes access to free_list */ + struct list_head free_list; + struct fsl_mc_bus *mc_bus; +}; + +/** + * struct fsl_mc_bus - logical bus that corresponds to a physical DPRC + * @mc_dev: fsl-mc device for the bus device itself. + * @resource_pools: array of resource pools (one pool per resource type) + * for this MC bus. These resources represent allocatable entities + * from the physical DPRC. + * @irq_resources: Pointer to array of IRQ objects for the IRQ pool + * @scan_mutex: Serializes bus scanning + * @dprc_attr: DPRC attributes + */ +struct fsl_mc_bus { + struct fsl_mc_device mc_dev; + struct fsl_mc_resource_pool resource_pools[FSL_MC_NUM_POOL_TYPES]; + struct fsl_mc_device_irq *irq_resources; + struct mutex scan_mutex; /* serializes bus scanning */ + struct dprc_attributes dprc_attr; +}; + +#define to_fsl_mc_bus(_mc_dev) \ + container_of(_mc_dev, struct fsl_mc_bus, mc_dev) + +int __must_check fsl_mc_device_add(struct dprc_obj_desc *obj_desc, + struct fsl_mc_io *mc_io, + struct device *parent_dev, + struct fsl_mc_device **new_mc_dev); + +void fsl_mc_device_remove(struct fsl_mc_device *mc_dev); + +int dprc_scan_container(struct fsl_mc_device *mc_bus_dev); + +int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, + unsigned int *total_irq_count); + +int __init dprc_driver_init(void); + +void dprc_driver_exit(void); + +int __init fsl_mc_allocator_driver_init(void); + +void fsl_mc_allocator_driver_exit(void); + +int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, + enum fsl_mc_pool_type pool_type, + struct fsl_mc_resource + **new_resource); + +void fsl_mc_resource_free(struct fsl_mc_resource *resource); + +struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode, + struct msi_domain_info *info, + struct irq_domain *parent); + +int fsl_mc_find_msi_domain(struct device *mc_platform_dev, + struct irq_domain **mc_msi_domain); + +int fsl_mc_msi_domain_alloc_irqs(struct device *dev, + unsigned int irq_count); + +void fsl_mc_msi_domain_free_irqs(struct device *dev); + +int __init its_fsl_mc_msi_init(void); + +void its_fsl_mc_msi_cleanup(void); + +int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, + unsigned int irq_count); + +void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus); + +#endif /* _FSL_MC_MCBUS_H_ */ diff --git a/drivers/staging/fsl-mc/include/mc-private.h b/drivers/staging/fsl-mc/include/mc-private.h deleted file mode 100644 index cab1ae9..0000000 --- a/drivers/staging/fsl-mc/include/mc-private.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Freescale Management Complex (MC) bus private declarations - * - * Copyright (C) 2014 Freescale Semiconductor, Inc. - * Author: German Rivera <German.Rivera@freescale.com> - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ -#ifndef _FSL_MC_PRIVATE_H_ -#define _FSL_MC_PRIVATE_H_ - -#include "../include/mc.h" -#include <linux/mutex.h> -#include <linux/stringify.h> - -#define FSL_MC_DPRC_DRIVER_NAME "fsl_mc_dprc" - -#define FSL_MC_DEVICE_MATCH(_mc_dev, _obj_desc) \ - (strcmp((_mc_dev)->obj_desc.type, (_obj_desc)->type) == 0 && \ - (_mc_dev)->obj_desc.id == (_obj_desc)->id) - -#define FSL_MC_IS_ALLOCATABLE(_obj_type) \ - (strcmp(_obj_type, "dpbp") == 0 || \ - strcmp(_obj_type, "dpmcp") == 0 || \ - strcmp(_obj_type, "dpcon") == 0) - -struct irq_domain; -struct msi_domain_info; - -/** - * Maximum number of total IRQs that can be pre-allocated for an MC bus' - * IRQ pool - */ -#define FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS 256 - -struct device_node; -struct irq_domain; -struct msi_domain_info; - -/** - * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device - * @root_mc_bus_dev: MC object device representing the root DPRC - * @num_translation_ranges: number of entries in addr_translation_ranges - * @translation_ranges: array of bus to system address translation ranges - */ -struct fsl_mc { - struct fsl_mc_device *root_mc_bus_dev; - u8 num_translation_ranges; - struct fsl_mc_addr_translation_range *translation_ranges; -}; - -/** - * struct fsl_mc_addr_translation_range - bus to system address translation - * range - * @mc_region_type: Type of MC region for the range being translated - * @start_mc_offset: Start MC offset of the range being translated - * @end_mc_offset: MC offset of the first byte after the range (last MC - * offset of the range is end_mc_offset - 1) - * @start_phys_addr: system physical address corresponding to start_mc_addr - */ -struct fsl_mc_addr_translation_range { - enum dprc_region_type mc_region_type; - u64 start_mc_offset; - u64 end_mc_offset; - phys_addr_t start_phys_addr; -}; - -/** - * struct fsl_mc_resource_pool - Pool of MC resources of a given - * type - * @type: type of resources in the pool - * @max_count: maximum number of resources in the pool - * @free_count: number of free resources in the pool - * @mutex: mutex to serialize access to the pool's free list - * @free_list: anchor node of list of free resources in the pool - * @mc_bus: pointer to the MC bus that owns this resource pool - */ -struct fsl_mc_resource_pool { - enum fsl_mc_pool_type type; - int16_t max_count; - int16_t free_count; - struct mutex mutex; /* serializes access to free_list */ - struct list_head free_list; - struct fsl_mc_bus *mc_bus; -}; - -/** - * struct fsl_mc_bus - logical bus that corresponds to a physical DPRC - * @mc_dev: fsl-mc device for the bus device itself. - * @resource_pools: array of resource pools (one pool per resource type) - * for this MC bus. These resources represent allocatable entities - * from the physical DPRC. - * @irq_resources: Pointer to array of IRQ objects for the IRQ pool - * @scan_mutex: Serializes bus scanning - * @dprc_attr: DPRC attributes - */ -struct fsl_mc_bus { - struct fsl_mc_device mc_dev; - struct fsl_mc_resource_pool resource_pools[FSL_MC_NUM_POOL_TYPES]; - struct fsl_mc_device_irq *irq_resources; - struct mutex scan_mutex; /* serializes bus scanning */ - struct dprc_attributes dprc_attr; -}; - -#define to_fsl_mc_bus(_mc_dev) \ - container_of(_mc_dev, struct fsl_mc_bus, mc_dev) - -int __must_check fsl_mc_device_add(struct dprc_obj_desc *obj_desc, - struct fsl_mc_io *mc_io, - struct device *parent_dev, - struct fsl_mc_device **new_mc_dev); - -void fsl_mc_device_remove(struct fsl_mc_device *mc_dev); - -int dprc_scan_container(struct fsl_mc_device *mc_bus_dev); - -int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, - unsigned int *total_irq_count); - -int __init dprc_driver_init(void); - -void dprc_driver_exit(void); - -int __init fsl_mc_allocator_driver_init(void); - -void fsl_mc_allocator_driver_exit(void); - -int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, - enum fsl_mc_pool_type pool_type, - struct fsl_mc_resource - **new_resource); - -void fsl_mc_resource_free(struct fsl_mc_resource *resource); - -struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode, - struct msi_domain_info *info, - struct irq_domain *parent); - -int fsl_mc_find_msi_domain(struct device *mc_platform_dev, - struct irq_domain **mc_msi_domain); - -int fsl_mc_msi_domain_alloc_irqs(struct device *dev, - unsigned int irq_count); - -void fsl_mc_msi_domain_free_irqs(struct device *dev); - -int __init its_fsl_mc_msi_init(void); - -void its_fsl_mc_msi_cleanup(void); - -int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, - unsigned int irq_count); - -void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus); - -#endif /* _FSL_MC_PRIVATE_H_ */ -- cgit v0.10.2 From 46d669daa36b85fbe0ca3d5c11fbf5a97b784c84 Mon Sep 17 00:00:00 2001 From: Stuart Yoder <stuart.yoder@nxp.com> Date: Tue, 23 Aug 2016 17:13:12 -0500 Subject: staging: fsl-mc: improve naming of source files The mc- prefix on the source files names of some internal components of the fsl-mc bus driver makes things less clear that they could be. The string "mc" generally refers to hardware-- the physical DPAA 'management complex'. Names like "mc-allocator.c" have nothing to with the "MC" hardware per se. Improve clarity by using the prefix string "fsl-mc" instead which is what we are calling this bus. Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fsl-mc/bus/Makefile b/drivers/staging/fsl-mc/bus/Makefile index e731517..5fb4c14 100644 --- a/drivers/staging/fsl-mc/bus/Makefile +++ b/drivers/staging/fsl-mc/bus/Makefile @@ -7,13 +7,13 @@ # obj-$(CONFIG_FSL_MC_BUS) += mc-bus-driver.o -mc-bus-driver-objs := mc-bus.o \ +mc-bus-driver-objs := fsl-mc-bus.o \ mc-sys.o \ dprc.o \ dpmng.o \ dprc-driver.o \ - mc-allocator.o \ - mc-msi.o \ + fsl-mc-allocator.o \ + fsl-mc-msi.o \ irq-gic-v3-its-fsl-mc-msi.o \ dpmcp.o \ dpbp.o diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c new file mode 100644 index 0000000..3ebaecb --- /dev/null +++ b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c @@ -0,0 +1,755 @@ +/* + * Freescale MC object device allocator driver + * + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include "../include/mc-bus.h" +#include "../include/mc-sys.h" +#include <linux/module.h> +#include "../include/dpbp-cmd.h" +#include "../include/dpcon-cmd.h" +#include "dpmcp-cmd.h" +#include "dpmcp.h" +#include <linux/msi.h> + +/** + * fsl_mc_resource_pool_add_device - add allocatable device to a resource + * pool of a given MC bus + * + * @mc_bus: pointer to the MC bus + * @pool_type: MC bus pool type + * @mc_dev: Pointer to allocatable MC object device + * + * It adds an allocatable MC object device to a container's resource pool of + * the given resource type + */ +static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus + *mc_bus, + enum fsl_mc_pool_type + pool_type, + struct fsl_mc_device + *mc_dev) +{ + struct fsl_mc_resource_pool *res_pool; + struct fsl_mc_resource *resource; + struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; + int error = -EINVAL; + + if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)) + goto out; + if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type))) + goto out; + if (WARN_ON(mc_dev->resource)) + goto out; + + res_pool = &mc_bus->resource_pools[pool_type]; + if (WARN_ON(res_pool->type != pool_type)) + goto out; + if (WARN_ON(res_pool->mc_bus != mc_bus)) + goto out; + + mutex_lock(&res_pool->mutex); + + if (WARN_ON(res_pool->max_count < 0)) + goto out_unlock; + if (WARN_ON(res_pool->free_count < 0 || + res_pool->free_count > res_pool->max_count)) + goto out_unlock; + + resource = devm_kzalloc(&mc_bus_dev->dev, sizeof(*resource), + GFP_KERNEL); + if (!resource) { + error = -ENOMEM; + dev_err(&mc_bus_dev->dev, + "Failed to allocate memory for fsl_mc_resource\n"); + goto out_unlock; + } + + resource->type = pool_type; + resource->id = mc_dev->obj_desc.id; + resource->data = mc_dev; + resource->parent_pool = res_pool; + INIT_LIST_HEAD(&resource->node); + list_add_tail(&resource->node, &res_pool->free_list); + mc_dev->resource = resource; + res_pool->free_count++; + res_pool->max_count++; + error = 0; +out_unlock: + mutex_unlock(&res_pool->mutex); +out: + return error; +} + +/** + * fsl_mc_resource_pool_remove_device - remove an allocatable device from a + * resource pool + * + * @mc_dev: Pointer to allocatable MC object device + * + * It permanently removes an allocatable MC object device from the resource + * pool, the device is currently in, as long as it is in the pool's free list. + */ +static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device + *mc_dev) +{ + struct fsl_mc_device *mc_bus_dev; + struct fsl_mc_bus *mc_bus; + struct fsl_mc_resource_pool *res_pool; + struct fsl_mc_resource *resource; + int error = -EINVAL; + + if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type))) + goto out; + + resource = mc_dev->resource; + if (WARN_ON(!resource || resource->data != mc_dev)) + goto out; + + mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); + mc_bus = to_fsl_mc_bus(mc_bus_dev); + res_pool = resource->parent_pool; + if (WARN_ON(res_pool != &mc_bus->resource_pools[resource->type])) + goto out; + + mutex_lock(&res_pool->mutex); + + if (WARN_ON(res_pool->max_count <= 0)) + goto out_unlock; + if (WARN_ON(res_pool->free_count <= 0 || + res_pool->free_count > res_pool->max_count)) + goto out_unlock; + + /* + * If the device is currently allocated, its resource is not + * in the free list and thus, the device cannot be removed. + */ + if (list_empty(&resource->node)) { + error = -EBUSY; + dev_err(&mc_bus_dev->dev, + "Device %s cannot be removed from resource pool\n", + dev_name(&mc_dev->dev)); + goto out_unlock; + } + + list_del(&resource->node); + INIT_LIST_HEAD(&resource->node); + res_pool->free_count--; + res_pool->max_count--; + + devm_kfree(&mc_bus_dev->dev, resource); + mc_dev->resource = NULL; + error = 0; +out_unlock: + mutex_unlock(&res_pool->mutex); +out: + return error; +} + +static const char *const fsl_mc_pool_type_strings[] = { + [FSL_MC_POOL_DPMCP] = "dpmcp", + [FSL_MC_POOL_DPBP] = "dpbp", + [FSL_MC_POOL_DPCON] = "dpcon", + [FSL_MC_POOL_IRQ] = "irq", +}; + +static int __must_check object_type_to_pool_type(const char *object_type, + enum fsl_mc_pool_type + *pool_type) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(fsl_mc_pool_type_strings); i++) { + if (strcmp(object_type, fsl_mc_pool_type_strings[i]) == 0) { + *pool_type = i; + return 0; + } + } + + return -EINVAL; +} + +int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, + enum fsl_mc_pool_type pool_type, + struct fsl_mc_resource **new_resource) +{ + struct fsl_mc_resource_pool *res_pool; + struct fsl_mc_resource *resource; + struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; + int error = -EINVAL; + + BUILD_BUG_ON(ARRAY_SIZE(fsl_mc_pool_type_strings) != + FSL_MC_NUM_POOL_TYPES); + + *new_resource = NULL; + if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)) + goto out; + + res_pool = &mc_bus->resource_pools[pool_type]; + if (WARN_ON(res_pool->mc_bus != mc_bus)) + goto out; + + mutex_lock(&res_pool->mutex); + resource = list_first_entry_or_null(&res_pool->free_list, + struct fsl_mc_resource, node); + + if (!resource) { + WARN_ON(res_pool->free_count != 0); + error = -ENXIO; + dev_err(&mc_bus_dev->dev, + "No more resources of type %s left\n", + fsl_mc_pool_type_strings[pool_type]); + goto out_unlock; + } + + if (WARN_ON(resource->type != pool_type)) + goto out_unlock; + if (WARN_ON(resource->parent_pool != res_pool)) + goto out_unlock; + if (WARN_ON(res_pool->free_count <= 0 || + res_pool->free_count > res_pool->max_count)) + goto out_unlock; + + list_del(&resource->node); + INIT_LIST_HEAD(&resource->node); + + res_pool->free_count--; + error = 0; +out_unlock: + mutex_unlock(&res_pool->mutex); + *new_resource = resource; +out: + return error; +} +EXPORT_SYMBOL_GPL(fsl_mc_resource_allocate); + +void fsl_mc_resource_free(struct fsl_mc_resource *resource) +{ + struct fsl_mc_resource_pool *res_pool; + + res_pool = resource->parent_pool; + if (WARN_ON(resource->type != res_pool->type)) + return; + + mutex_lock(&res_pool->mutex); + if (WARN_ON(res_pool->free_count < 0 || + res_pool->free_count >= res_pool->max_count)) + goto out_unlock; + + if (WARN_ON(!list_empty(&resource->node))) + goto out_unlock; + + list_add_tail(&resource->node, &res_pool->free_list); + res_pool->free_count++; +out_unlock: + mutex_unlock(&res_pool->mutex); +} +EXPORT_SYMBOL_GPL(fsl_mc_resource_free); + +/** + * fsl_mc_portal_allocate - Allocates an MC portal + * + * @mc_dev: MC device for which the MC portal is to be allocated + * @mc_io_flags: Flags for the fsl_mc_io object that wraps the allocated + * MC portal. + * @new_mc_io: Pointer to area where the pointer to the fsl_mc_io object + * that wraps the allocated MC portal is to be returned + * + * This function allocates an MC portal from the device's parent DPRC, + * from the corresponding MC bus' pool of MC portals and wraps + * it in a new fsl_mc_io object. If 'mc_dev' is a DPRC itself, the + * portal is allocated from its own MC bus. + */ +int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, + u16 mc_io_flags, + struct fsl_mc_io **new_mc_io) +{ + struct fsl_mc_device *mc_bus_dev; + struct fsl_mc_bus *mc_bus; + phys_addr_t mc_portal_phys_addr; + size_t mc_portal_size; + struct fsl_mc_device *dpmcp_dev; + int error = -EINVAL; + struct fsl_mc_resource *resource = NULL; + struct fsl_mc_io *mc_io = NULL; + + if (mc_dev->flags & FSL_MC_IS_DPRC) { + mc_bus_dev = mc_dev; + } else { + if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent))) + return error; + + mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); + } + + mc_bus = to_fsl_mc_bus(mc_bus_dev); + *new_mc_io = NULL; + error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_DPMCP, &resource); + if (error < 0) + return error; + + error = -EINVAL; + dpmcp_dev = resource->data; + if (WARN_ON(!dpmcp_dev)) + goto error_cleanup_resource; + + if (dpmcp_dev->obj_desc.ver_major < DPMCP_MIN_VER_MAJOR || + (dpmcp_dev->obj_desc.ver_major == DPMCP_MIN_VER_MAJOR && + dpmcp_dev->obj_desc.ver_minor < DPMCP_MIN_VER_MINOR)) { + dev_err(&dpmcp_dev->dev, + "ERROR: Version %d.%d of DPMCP not supported.\n", + dpmcp_dev->obj_desc.ver_major, + dpmcp_dev->obj_desc.ver_minor); + error = -ENOTSUPP; + goto error_cleanup_resource; + } + + if (WARN_ON(dpmcp_dev->obj_desc.region_count == 0)) + goto error_cleanup_resource; + + mc_portal_phys_addr = dpmcp_dev->regions[0].start; + mc_portal_size = dpmcp_dev->regions[0].end - + dpmcp_dev->regions[0].start + 1; + + if (WARN_ON(mc_portal_size != mc_bus_dev->mc_io->portal_size)) + goto error_cleanup_resource; + + error = fsl_create_mc_io(&mc_bus_dev->dev, + mc_portal_phys_addr, + mc_portal_size, dpmcp_dev, + mc_io_flags, &mc_io); + if (error < 0) + goto error_cleanup_resource; + + *new_mc_io = mc_io; + return 0; + +error_cleanup_resource: + fsl_mc_resource_free(resource); + return error; +} +EXPORT_SYMBOL_GPL(fsl_mc_portal_allocate); + +/** + * fsl_mc_portal_free - Returns an MC portal to the pool of free MC portals + * of a given MC bus + * + * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free + */ +void fsl_mc_portal_free(struct fsl_mc_io *mc_io) +{ + struct fsl_mc_device *dpmcp_dev; + struct fsl_mc_resource *resource; + + /* + * Every mc_io obtained by calling fsl_mc_portal_allocate() is supposed + * to have a DPMCP object associated with. + */ + dpmcp_dev = mc_io->dpmcp_dev; + if (WARN_ON(!dpmcp_dev)) + return; + + resource = dpmcp_dev->resource; + if (WARN_ON(!resource || resource->type != FSL_MC_POOL_DPMCP)) + return; + + if (WARN_ON(resource->data != dpmcp_dev)) + return; + + fsl_destroy_mc_io(mc_io); + fsl_mc_resource_free(resource); +} +EXPORT_SYMBOL_GPL(fsl_mc_portal_free); + +/** + * fsl_mc_portal_reset - Resets the dpmcp object for a given fsl_mc_io object + * + * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free + */ +int fsl_mc_portal_reset(struct fsl_mc_io *mc_io) +{ + int error; + struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; + + if (WARN_ON(!dpmcp_dev)) + return -EINVAL; + + error = dpmcp_reset(mc_io, 0, dpmcp_dev->mc_handle); + if (error < 0) { + dev_err(&dpmcp_dev->dev, "dpmcp_reset() failed: %d\n", error); + return error; + } + + return 0; +} +EXPORT_SYMBOL_GPL(fsl_mc_portal_reset); + +/** + * fsl_mc_object_allocate - Allocates a MC object device of the given + * pool type from a given MC bus + * + * @mc_dev: MC device for which the MC object device is to be allocated + * @pool_type: MC bus resource pool type + * @new_mc_dev: Pointer to area where the pointer to the allocated + * MC object device is to be returned + * + * This function allocates a MC object device from the device's parent DPRC, + * from the corresponding MC bus' pool of allocatable MC object devices of + * the given resource type. mc_dev cannot be a DPRC itself. + * + * NOTE: pool_type must be different from FSL_MC_POOL_MCP, since MC + * portals are allocated using fsl_mc_portal_allocate(), instead of + * this function. + */ +int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev, + enum fsl_mc_pool_type pool_type, + struct fsl_mc_device **new_mc_adev) +{ + struct fsl_mc_device *mc_bus_dev; + struct fsl_mc_bus *mc_bus; + struct fsl_mc_device *mc_adev; + int error = -EINVAL; + struct fsl_mc_resource *resource = NULL; + + *new_mc_adev = NULL; + if (WARN_ON(mc_dev->flags & FSL_MC_IS_DPRC)) + goto error; + + if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent))) + goto error; + + if (WARN_ON(pool_type == FSL_MC_POOL_DPMCP)) + goto error; + + mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); + mc_bus = to_fsl_mc_bus(mc_bus_dev); + error = fsl_mc_resource_allocate(mc_bus, pool_type, &resource); + if (error < 0) + goto error; + + mc_adev = resource->data; + if (WARN_ON(!mc_adev)) + goto error; + + *new_mc_adev = mc_adev; + return 0; +error: + if (resource) + fsl_mc_resource_free(resource); + + return error; +} +EXPORT_SYMBOL_GPL(fsl_mc_object_allocate); + +/** + * fsl_mc_object_free - Returns an allocatable MC object device to the + * corresponding resource pool of a given MC bus. + * + * @mc_adev: Pointer to the MC object device + */ +void fsl_mc_object_free(struct fsl_mc_device *mc_adev) +{ + struct fsl_mc_resource *resource; + + resource = mc_adev->resource; + if (WARN_ON(resource->type == FSL_MC_POOL_DPMCP)) + return; + if (WARN_ON(resource->data != mc_adev)) + return; + + fsl_mc_resource_free(resource); +} +EXPORT_SYMBOL_GPL(fsl_mc_object_free); + +/* + * Initialize the interrupt pool associated with a MC bus. + * It allocates a block of IRQs from the GIC-ITS + */ +int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, + unsigned int irq_count) +{ + unsigned int i; + struct msi_desc *msi_desc; + struct fsl_mc_device_irq *irq_resources; + struct fsl_mc_device_irq *mc_dev_irq; + int error; + struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; + struct fsl_mc_resource_pool *res_pool = + &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; + + if (WARN_ON(irq_count == 0 || + irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS)) + return -EINVAL; + + error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count); + if (error < 0) + return error; + + irq_resources = devm_kzalloc(&mc_bus_dev->dev, + sizeof(*irq_resources) * irq_count, + GFP_KERNEL); + if (!irq_resources) { + error = -ENOMEM; + goto cleanup_msi_irqs; + } + + for (i = 0; i < irq_count; i++) { + mc_dev_irq = &irq_resources[i]; + + /* + * NOTE: This mc_dev_irq's MSI addr/value pair will be set + * by the fsl_mc_msi_write_msg() callback + */ + mc_dev_irq->resource.type = res_pool->type; + mc_dev_irq->resource.data = mc_dev_irq; + mc_dev_irq->resource.parent_pool = res_pool; + INIT_LIST_HEAD(&mc_dev_irq->resource.node); + list_add_tail(&mc_dev_irq->resource.node, &res_pool->free_list); + } + + for_each_msi_entry(msi_desc, &mc_bus_dev->dev) { + mc_dev_irq = &irq_resources[msi_desc->fsl_mc.msi_index]; + mc_dev_irq->msi_desc = msi_desc; + mc_dev_irq->resource.id = msi_desc->irq; + } + + res_pool->max_count = irq_count; + res_pool->free_count = irq_count; + mc_bus->irq_resources = irq_resources; + return 0; + +cleanup_msi_irqs: + fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev); + return error; +} +EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool); + +/** + * Teardown the interrupt pool associated with an MC bus. + * It frees the IRQs that were allocated to the pool, back to the GIC-ITS. + */ +void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus) +{ + struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; + struct fsl_mc_resource_pool *res_pool = + &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; + + if (WARN_ON(!mc_bus->irq_resources)) + return; + + if (WARN_ON(res_pool->max_count == 0)) + return; + + if (WARN_ON(res_pool->free_count != res_pool->max_count)) + return; + + INIT_LIST_HEAD(&res_pool->free_list); + res_pool->max_count = 0; + res_pool->free_count = 0; + mc_bus->irq_resources = NULL; + fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev); +} +EXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool); + +/** + * It allocates the IRQs required by a given MC object device. The + * IRQs are allocated from the interrupt pool associated with the + * MC bus that contains the device, if the device is not a DPRC device. + * Otherwise, the IRQs are allocated from the interrupt pool associated + * with the MC bus that represents the DPRC device itself. + */ +int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev) +{ + int i; + int irq_count; + int res_allocated_count = 0; + int error = -EINVAL; + struct fsl_mc_device_irq **irqs = NULL; + struct fsl_mc_bus *mc_bus; + struct fsl_mc_resource_pool *res_pool; + + if (WARN_ON(mc_dev->irqs)) + return -EINVAL; + + irq_count = mc_dev->obj_desc.irq_count; + if (WARN_ON(irq_count == 0)) + return -EINVAL; + + if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) + mc_bus = to_fsl_mc_bus(mc_dev); + else + mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); + + if (WARN_ON(!mc_bus->irq_resources)) + return -EINVAL; + + res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; + if (res_pool->free_count < irq_count) { + dev_err(&mc_dev->dev, + "Not able to allocate %u irqs for device\n", irq_count); + return -ENOSPC; + } + + irqs = devm_kzalloc(&mc_dev->dev, irq_count * sizeof(irqs[0]), + GFP_KERNEL); + if (!irqs) + return -ENOMEM; + + for (i = 0; i < irq_count; i++) { + struct fsl_mc_resource *resource; + + error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_IRQ, + &resource); + if (error < 0) + goto error_resource_alloc; + + irqs[i] = to_fsl_mc_irq(resource); + res_allocated_count++; + + WARN_ON(irqs[i]->mc_dev); + irqs[i]->mc_dev = mc_dev; + irqs[i]->dev_irq_index = i; + } + + mc_dev->irqs = irqs; + return 0; + +error_resource_alloc: + for (i = 0; i < res_allocated_count; i++) { + irqs[i]->mc_dev = NULL; + fsl_mc_resource_free(&irqs[i]->resource); + } + + return error; +} +EXPORT_SYMBOL_GPL(fsl_mc_allocate_irqs); + +/* + * It frees the IRQs that were allocated for a MC object device, by + * returning them to the corresponding interrupt pool. + */ +void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev) +{ + int i; + int irq_count; + struct fsl_mc_bus *mc_bus; + struct fsl_mc_device_irq **irqs = mc_dev->irqs; + + if (WARN_ON(!irqs)) + return; + + irq_count = mc_dev->obj_desc.irq_count; + + if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) + mc_bus = to_fsl_mc_bus(mc_dev); + else + mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); + + if (WARN_ON(!mc_bus->irq_resources)) + return; + + for (i = 0; i < irq_count; i++) { + WARN_ON(!irqs[i]->mc_dev); + irqs[i]->mc_dev = NULL; + fsl_mc_resource_free(&irqs[i]->resource); + } + + mc_dev->irqs = NULL; +} +EXPORT_SYMBOL_GPL(fsl_mc_free_irqs); + +/** + * fsl_mc_allocator_probe - callback invoked when an allocatable device is + * being added to the system + */ +static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev) +{ + enum fsl_mc_pool_type pool_type; + struct fsl_mc_device *mc_bus_dev; + struct fsl_mc_bus *mc_bus; + int error; + + if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type))) + return -EINVAL; + + mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); + if (WARN_ON(!dev_is_fsl_mc(&mc_bus_dev->dev))) + return -EINVAL; + + mc_bus = to_fsl_mc_bus(mc_bus_dev); + error = object_type_to_pool_type(mc_dev->obj_desc.type, &pool_type); + if (error < 0) + return error; + + error = fsl_mc_resource_pool_add_device(mc_bus, pool_type, mc_dev); + if (error < 0) + return error; + + dev_dbg(&mc_dev->dev, + "Allocatable MC object device bound to fsl_mc_allocator driver"); + return 0; +} + +/** + * fsl_mc_allocator_remove - callback invoked when an allocatable device is + * being removed from the system + */ +static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev) +{ + int error; + + if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type))) + return -EINVAL; + + if (mc_dev->resource) { + error = fsl_mc_resource_pool_remove_device(mc_dev); + if (error < 0) + return error; + } + + dev_dbg(&mc_dev->dev, + "Allocatable MC object device unbound from fsl_mc_allocator driver"); + return 0; +} + +static const struct fsl_mc_device_id match_id_table[] = { + { + .vendor = FSL_MC_VENDOR_FREESCALE, + .obj_type = "dpbp", + }, + { + .vendor = FSL_MC_VENDOR_FREESCALE, + .obj_type = "dpmcp", + }, + { + .vendor = FSL_MC_VENDOR_FREESCALE, + .obj_type = "dpcon", + }, + {.vendor = 0x0}, +}; + +static struct fsl_mc_driver fsl_mc_allocator_driver = { + .driver = { + .name = "fsl_mc_allocator", + .owner = THIS_MODULE, + .pm = NULL, + }, + .match_id_table = match_id_table, + .probe = fsl_mc_allocator_probe, + .remove = fsl_mc_allocator_remove, +}; + +int __init fsl_mc_allocator_driver_init(void) +{ + return fsl_mc_driver_register(&fsl_mc_allocator_driver); +} + +void fsl_mc_allocator_driver_exit(void) +{ + fsl_mc_driver_unregister(&fsl_mc_allocator_driver); +} diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c new file mode 100644 index 0000000..975d30b --- /dev/null +++ b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c @@ -0,0 +1,890 @@ +/* + * Freescale Management Complex (MC) bus driver + * + * Copyright (C) 2014 Freescale Semiconductor, Inc. + * Author: German Rivera <German.Rivera@freescale.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include "../include/mc-bus.h" +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/of_address.h> +#include <linux/ioport.h> +#include <linux/slab.h> +#include <linux/limits.h> +#include <linux/bitops.h> +#include <linux/msi.h> +#include "../include/dpmng.h" +#include "../include/mc-sys.h" +#include "dprc-cmd.h" + +static struct kmem_cache *mc_dev_cache; + +/** + * fsl_mc_bus_match - device to driver matching callback + * @dev: the MC object device structure to match against + * @drv: the device driver to search for matching MC object device id + * structures + * + * Returns 1 on success, 0 otherwise. + */ +static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv) +{ + const struct fsl_mc_device_id *id; + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); + struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(drv); + bool found = false; + + if (WARN_ON(!fsl_mc_bus_exists())) + goto out; + + if (!mc_drv->match_id_table) + goto out; + + /* + * If the object is not 'plugged' don't match. + * Only exception is the root DPRC, which is a special case. + */ + if ((mc_dev->obj_desc.state & DPRC_OBJ_STATE_PLUGGED) == 0 && + !fsl_mc_is_root_dprc(&mc_dev->dev)) + goto out; + + /* + * Traverse the match_id table of the given driver, trying to find + * a matching for the given MC object device. + */ + for (id = mc_drv->match_id_table; id->vendor != 0x0; id++) { + if (id->vendor == mc_dev->obj_desc.vendor && + strcmp(id->obj_type, mc_dev->obj_desc.type) == 0) { + found = true; + + break; + } + } + +out: + dev_dbg(dev, "%smatched\n", found ? "" : "not "); + 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) +{ + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); + + if (add_uevent_var(env, "MODALIAS=fsl-mc:v%08Xd%s", + mc_dev->obj_desc.vendor, + mc_dev->obj_desc.type)) + return -ENOMEM; + + return 0; +} + +static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); + + return sprintf(buf, "fsl-mc:v%08Xd%s\n", mc_dev->obj_desc.vendor, + mc_dev->obj_desc.type); +} +static DEVICE_ATTR_RO(modalias); + +static struct attribute *fsl_mc_dev_attrs[] = { + &dev_attr_modalias.attr, + NULL, +}; + +static const struct attribute_group fsl_mc_dev_group = { + .attrs = fsl_mc_dev_attrs, +}; + +static const struct attribute_group *fsl_mc_dev_groups[] = { + &fsl_mc_dev_group, + NULL, +}; + +struct bus_type fsl_mc_bus_type = { + .name = "fsl-mc", + .match = fsl_mc_bus_match, + .uevent = fsl_mc_bus_uevent, + .dev_groups = fsl_mc_dev_groups, +}; +EXPORT_SYMBOL_GPL(fsl_mc_bus_type); + +static atomic_t root_dprc_count = ATOMIC_INIT(0); + +static int fsl_mc_driver_probe(struct device *dev) +{ + struct fsl_mc_driver *mc_drv; + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); + int error; + + if (WARN_ON(!dev->driver)) + return -EINVAL; + + mc_drv = to_fsl_mc_driver(dev->driver); + if (WARN_ON(!mc_drv->probe)) + return -EINVAL; + + error = mc_drv->probe(mc_dev); + if (error < 0) { + dev_err(dev, "MC object device probe callback failed: %d\n", + error); + return error; + } + + return 0; +} + +static int fsl_mc_driver_remove(struct device *dev) +{ + struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver); + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); + int error; + + if (WARN_ON(!dev->driver)) + return -EINVAL; + + error = mc_drv->remove(mc_dev); + if (error < 0) { + dev_err(dev, + "MC object device remove callback failed: %d\n", + error); + return error; + } + + return 0; +} + +static void fsl_mc_driver_shutdown(struct device *dev) +{ + struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver); + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); + + mc_drv->shutdown(mc_dev); +} + +/** + * __fsl_mc_driver_register - registers a child device driver with the + * MC bus + * + * This function is implicitly invoked from the registration function of + * fsl_mc device drivers, which is generated by the + * module_fsl_mc_driver() macro. + */ +int __fsl_mc_driver_register(struct fsl_mc_driver *mc_driver, + struct module *owner) +{ + int error; + + mc_driver->driver.owner = owner; + mc_driver->driver.bus = &fsl_mc_bus_type; + + if (mc_driver->probe) + mc_driver->driver.probe = fsl_mc_driver_probe; + + if (mc_driver->remove) + mc_driver->driver.remove = fsl_mc_driver_remove; + + if (mc_driver->shutdown) + mc_driver->driver.shutdown = fsl_mc_driver_shutdown; + + error = driver_register(&mc_driver->driver); + if (error < 0) { + pr_err("driver_register() failed for %s: %d\n", + mc_driver->driver.name, error); + return error; + } + + pr_info("MC object device driver %s registered\n", + mc_driver->driver.name); + return 0; +} +EXPORT_SYMBOL_GPL(__fsl_mc_driver_register); + +/** + * fsl_mc_driver_unregister - unregisters a device driver from the + * MC bus + */ +void fsl_mc_driver_unregister(struct fsl_mc_driver *mc_driver) +{ + driver_unregister(&mc_driver->driver); +} +EXPORT_SYMBOL_GPL(fsl_mc_driver_unregister); + +/** + * fsl_mc_bus_exists - check if a root dprc exists + */ +bool fsl_mc_bus_exists(void) +{ + return atomic_read(&root_dprc_count) > 0; +} +EXPORT_SYMBOL_GPL(fsl_mc_bus_exists); + +/** +* fsl_mc_get_root_dprc - function to traverse to the root dprc +*/ +static void fsl_mc_get_root_dprc(struct device *dev, + struct device **root_dprc_dev) +{ + if (WARN_ON(!dev)) { + *root_dprc_dev = NULL; + } else if (WARN_ON(!dev_is_fsl_mc(dev))) { + *root_dprc_dev = NULL; + } else { + *root_dprc_dev = dev; + while (dev_is_fsl_mc((*root_dprc_dev)->parent)) + *root_dprc_dev = (*root_dprc_dev)->parent; + } +} + +static int get_dprc_attr(struct fsl_mc_io *mc_io, + int container_id, struct dprc_attributes *attr) +{ + u16 dprc_handle; + int error; + + error = dprc_open(mc_io, 0, container_id, &dprc_handle); + if (error < 0) { + dev_err(mc_io->dev, "dprc_open() failed: %d\n", error); + return error; + } + + memset(attr, 0, sizeof(struct dprc_attributes)); + error = dprc_get_attributes(mc_io, 0, dprc_handle, attr); + if (error < 0) { + dev_err(mc_io->dev, "dprc_get_attributes() failed: %d\n", + error); + goto common_cleanup; + } + + error = 0; + +common_cleanup: + (void)dprc_close(mc_io, 0, dprc_handle); + return error; +} + +static int get_dprc_icid(struct fsl_mc_io *mc_io, + int container_id, u16 *icid) +{ + struct dprc_attributes attr; + int error; + + error = get_dprc_attr(mc_io, container_id, &attr); + if (error == 0) + *icid = attr.icid; + + return error; +} + +static int get_dprc_version(struct fsl_mc_io *mc_io, + int container_id, u16 *major, u16 *minor) +{ + struct dprc_attributes attr; + int error; + + error = get_dprc_attr(mc_io, container_id, &attr); + if (error == 0) { + *major = attr.version.major; + *minor = attr.version.minor; + } + + return error; +} + +static int translate_mc_addr(struct fsl_mc_device *mc_dev, + enum dprc_region_type mc_region_type, + u64 mc_offset, phys_addr_t *phys_addr) +{ + int i; + struct device *root_dprc_dev; + struct fsl_mc *mc; + + fsl_mc_get_root_dprc(&mc_dev->dev, &root_dprc_dev); + if (WARN_ON(!root_dprc_dev)) + return -EINVAL; + mc = dev_get_drvdata(root_dprc_dev->parent); + + if (mc->num_translation_ranges == 0) { + /* + * Do identity mapping: + */ + *phys_addr = mc_offset; + return 0; + } + + for (i = 0; i < mc->num_translation_ranges; i++) { + struct fsl_mc_addr_translation_range *range = + &mc->translation_ranges[i]; + + if (mc_region_type == range->mc_region_type && + mc_offset >= range->start_mc_offset && + mc_offset < range->end_mc_offset) { + *phys_addr = range->start_phys_addr + + (mc_offset - range->start_mc_offset); + return 0; + } + } + + return -EFAULT; +} + +static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev, + struct fsl_mc_device *mc_bus_dev) +{ + int i; + int error; + struct resource *regions; + struct dprc_obj_desc *obj_desc = &mc_dev->obj_desc; + struct device *parent_dev = mc_dev->dev.parent; + enum dprc_region_type mc_region_type; + + if (strcmp(obj_desc->type, "dprc") == 0 || + strcmp(obj_desc->type, "dpmcp") == 0) { + mc_region_type = DPRC_REGION_TYPE_MC_PORTAL; + } else if (strcmp(obj_desc->type, "dpio") == 0) { + mc_region_type = DPRC_REGION_TYPE_QBMAN_PORTAL; + } else { + /* + * This function should not have been called for this MC object + * type, as this object type is not supposed to have MMIO + * regions + */ + WARN_ON(true); + return -EINVAL; + } + + regions = kmalloc_array(obj_desc->region_count, + sizeof(regions[0]), GFP_KERNEL); + if (!regions) + return -ENOMEM; + + for (i = 0; i < obj_desc->region_count; i++) { + struct dprc_region_desc region_desc; + + error = dprc_get_obj_region(mc_bus_dev->mc_io, + 0, + mc_bus_dev->mc_handle, + obj_desc->type, + obj_desc->id, i, ®ion_desc); + if (error < 0) { + dev_err(parent_dev, + "dprc_get_obj_region() failed: %d\n", error); + goto error_cleanup_regions; + } + + WARN_ON(region_desc.size == 0); + error = translate_mc_addr(mc_dev, mc_region_type, + region_desc.base_offset, + ®ions[i].start); + if (error < 0) { + dev_err(parent_dev, + "Invalid MC offset: %#x (for %s.%d\'s region %d)\n", + region_desc.base_offset, + obj_desc->type, obj_desc->id, i); + goto error_cleanup_regions; + } + + regions[i].end = regions[i].start + region_desc.size - 1; + regions[i].name = "fsl-mc object MMIO region"; + regions[i].flags = IORESOURCE_IO; + if (region_desc.flags & DPRC_REGION_CACHEABLE) + regions[i].flags |= IORESOURCE_CACHEABLE; + } + + mc_dev->regions = regions; + return 0; + +error_cleanup_regions: + kfree(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) +{ + struct device *root_dprc_dev; + + fsl_mc_get_root_dprc(dev, &root_dprc_dev); + if (!root_dprc_dev) + return false; + return dev == root_dprc_dev; +} + +/** + * Add a newly discovered MC object device to be visible in Linux + */ +int fsl_mc_device_add(struct dprc_obj_desc *obj_desc, + struct fsl_mc_io *mc_io, + struct device *parent_dev, + struct fsl_mc_device **new_mc_dev) +{ + int error; + struct fsl_mc_device *mc_dev = NULL; + struct fsl_mc_bus *mc_bus = NULL; + struct fsl_mc_device *parent_mc_dev; + + if (dev_is_fsl_mc(parent_dev)) + parent_mc_dev = to_fsl_mc_device(parent_dev); + else + parent_mc_dev = NULL; + + if (strcmp(obj_desc->type, "dprc") == 0) { + /* + * Allocate an MC bus device object: + */ + mc_bus = devm_kzalloc(parent_dev, sizeof(*mc_bus), GFP_KERNEL); + if (!mc_bus) + return -ENOMEM; + + mc_dev = &mc_bus->mc_dev; + } else { + /* + * Allocate a regular fsl_mc_device object: + */ + mc_dev = kmem_cache_zalloc(mc_dev_cache, GFP_KERNEL); + if (!mc_dev) + return -ENOMEM; + } + + mc_dev->obj_desc = *obj_desc; + mc_dev->mc_io = mc_io; + device_initialize(&mc_dev->dev); + mc_dev->dev.parent = parent_dev; + mc_dev->dev.bus = &fsl_mc_bus_type; + dev_set_name(&mc_dev->dev, "%s.%d", obj_desc->type, obj_desc->id); + + if (strcmp(obj_desc->type, "dprc") == 0) { + struct fsl_mc_io *mc_io2; + + mc_dev->flags |= FSL_MC_IS_DPRC; + + /* + * To get the DPRC's ICID, we need to open the DPRC + * in get_dprc_icid(). For child DPRCs, we do so using the + * parent DPRC's MC portal instead of the child DPRC's MC + * portal, in case the child DPRC is already opened with + * its own portal (e.g., the DPRC used by AIOP). + * + * NOTE: There cannot be more than one active open for a + * given MC object, using the same MC portal. + */ + if (parent_mc_dev) { + /* + * device being added is a child DPRC device + */ + mc_io2 = parent_mc_dev->mc_io; + } else { + /* + * device being added is the root DPRC device + */ + if (WARN_ON(!mc_io)) { + error = -EINVAL; + goto error_cleanup_dev; + } + + mc_io2 = mc_io; + + atomic_inc(&root_dprc_count); + } + + error = get_dprc_icid(mc_io2, obj_desc->id, &mc_dev->icid); + if (error < 0) + goto error_cleanup_dev; + } else { + /* + * A non-DPRC MC object device has to be a child of another + * MC object (specifically a DPRC object) + */ + mc_dev->icid = parent_mc_dev->icid; + mc_dev->dma_mask = FSL_MC_DEFAULT_DMA_MASK; + mc_dev->dev.dma_mask = &mc_dev->dma_mask; + dev_set_msi_domain(&mc_dev->dev, + dev_get_msi_domain(&parent_mc_dev->dev)); + } + + /* + * Get MMIO regions for the device from the MC: + * + * NOTE: the root DPRC is a special case as its MMIO region is + * obtained from the device tree + */ + if (parent_mc_dev && obj_desc->region_count != 0) { + error = fsl_mc_device_get_mmio_regions(mc_dev, + parent_mc_dev); + if (error < 0) + goto error_cleanup_dev; + } + + /* Objects are coherent, unless 'no shareability' flag set. */ + if (!(obj_desc->flags & DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY)) + arch_setup_dma_ops(&mc_dev->dev, 0, 0, NULL, true); + + /* + * The device-specific probe callback will get invoked by device_add() + */ + error = device_add(&mc_dev->dev); + if (error < 0) { + dev_err(parent_dev, + "device_add() failed for device %s: %d\n", + dev_name(&mc_dev->dev), error); + goto error_cleanup_dev; + } + + (void)get_device(&mc_dev->dev); + dev_dbg(parent_dev, "Added MC object device %s\n", + dev_name(&mc_dev->dev)); + + *new_mc_dev = mc_dev; + return 0; + +error_cleanup_dev: + kfree(mc_dev->regions); + if (mc_bus) + devm_kfree(parent_dev, mc_bus); + else + kmem_cache_free(mc_dev_cache, mc_dev); + + return error; +} +EXPORT_SYMBOL_GPL(fsl_mc_device_add); + +/** + * fsl_mc_device_remove - Remove a MC object device from being visible to + * Linux + * + * @mc_dev: Pointer to a MC object device object + */ +void fsl_mc_device_remove(struct fsl_mc_device *mc_dev) +{ + struct fsl_mc_bus *mc_bus = NULL; + + kfree(mc_dev->regions); + + /* + * The device-specific remove callback will get invoked by device_del() + */ + device_del(&mc_dev->dev); + put_device(&mc_dev->dev); + + if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) { + mc_bus = to_fsl_mc_bus(mc_dev); + + if (fsl_mc_is_root_dprc(&mc_dev->dev)) { + if (atomic_read(&root_dprc_count) > 0) + atomic_dec(&root_dprc_count); + else + WARN_ON(1); + } + } + + if (mc_bus) + devm_kfree(mc_dev->dev.parent, mc_bus); + else + kmem_cache_free(mc_dev_cache, mc_dev); +} +EXPORT_SYMBOL_GPL(fsl_mc_device_remove); + +static int parse_mc_ranges(struct device *dev, + int *paddr_cells, + int *mc_addr_cells, + int *mc_size_cells, + const __be32 **ranges_start, + u8 *num_ranges) +{ + const __be32 *prop; + int range_tuple_cell_count; + int ranges_len; + int tuple_len; + struct device_node *mc_node = dev->of_node; + + *ranges_start = of_get_property(mc_node, "ranges", &ranges_len); + if (!(*ranges_start) || !ranges_len) { + dev_warn(dev, + "missing or empty ranges property for device tree node '%s'\n", + mc_node->name); + + *num_ranges = 0; + return 0; + } + + *paddr_cells = of_n_addr_cells(mc_node); + + prop = of_get_property(mc_node, "#address-cells", NULL); + if (prop) + *mc_addr_cells = be32_to_cpup(prop); + else + *mc_addr_cells = *paddr_cells; + + prop = of_get_property(mc_node, "#size-cells", NULL); + if (prop) + *mc_size_cells = be32_to_cpup(prop); + else + *mc_size_cells = of_n_size_cells(mc_node); + + range_tuple_cell_count = *paddr_cells + *mc_addr_cells + + *mc_size_cells; + + tuple_len = range_tuple_cell_count * sizeof(__be32); + if (ranges_len % tuple_len != 0) { + dev_err(dev, "malformed ranges property '%s'\n", mc_node->name); + return -EINVAL; + } + + *num_ranges = ranges_len / tuple_len; + return 0; +} + +static int get_mc_addr_translation_ranges(struct device *dev, + struct fsl_mc_addr_translation_range + **ranges, + u8 *num_ranges) +{ + int error; + int paddr_cells; + int mc_addr_cells; + int mc_size_cells; + int i; + const __be32 *ranges_start; + const __be32 *cell; + + error = parse_mc_ranges(dev, + &paddr_cells, + &mc_addr_cells, + &mc_size_cells, + &ranges_start, + num_ranges); + if (error < 0) + return error; + + if (!(*num_ranges)) { + /* + * Missing or empty ranges property ("ranges;") for the + * 'fsl,qoriq-mc' node. In this case, identity mapping + * will be used. + */ + *ranges = NULL; + return 0; + } + + *ranges = devm_kcalloc(dev, *num_ranges, + sizeof(struct fsl_mc_addr_translation_range), + GFP_KERNEL); + if (!(*ranges)) + return -ENOMEM; + + cell = ranges_start; + for (i = 0; i < *num_ranges; ++i) { + struct fsl_mc_addr_translation_range *range = &(*ranges)[i]; + + range->mc_region_type = of_read_number(cell, 1); + range->start_mc_offset = of_read_number(cell + 1, + mc_addr_cells - 1); + cell += mc_addr_cells; + range->start_phys_addr = of_read_number(cell, paddr_cells); + cell += paddr_cells; + range->end_mc_offset = range->start_mc_offset + + of_read_number(cell, mc_size_cells); + + cell += mc_size_cells; + } + + return 0; +} + +/** + * fsl_mc_bus_probe - callback invoked when the root MC bus is being + * added + */ +static int fsl_mc_bus_probe(struct platform_device *pdev) +{ + struct dprc_obj_desc obj_desc; + int error; + struct fsl_mc *mc; + struct fsl_mc_device *mc_bus_dev = NULL; + struct fsl_mc_io *mc_io = NULL; + int container_id; + phys_addr_t mc_portal_phys_addr; + u32 mc_portal_size; + struct mc_version mc_version; + struct resource res; + + dev_info(&pdev->dev, "Root MC bus device probed"); + + mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL); + if (!mc) + return -ENOMEM; + + platform_set_drvdata(pdev, mc); + + /* + * Get physical address of MC portal for the root DPRC: + */ + error = of_address_to_resource(pdev->dev.of_node, 0, &res); + if (error < 0) { + dev_err(&pdev->dev, + "of_address_to_resource() failed for %s\n", + pdev->dev.of_node->full_name); + return error; + } + + mc_portal_phys_addr = res.start; + mc_portal_size = resource_size(&res); + error = fsl_create_mc_io(&pdev->dev, mc_portal_phys_addr, + mc_portal_size, NULL, + FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, &mc_io); + if (error < 0) + return error; + + error = mc_get_version(mc_io, 0, &mc_version); + if (error != 0) { + dev_err(&pdev->dev, + "mc_get_version() failed with error %d\n", error); + goto error_cleanup_mc_io; + } + + dev_info(&pdev->dev, + "Freescale Management Complex Firmware version: %u.%u.%u\n", + mc_version.major, mc_version.minor, mc_version.revision); + + error = get_mc_addr_translation_ranges(&pdev->dev, + &mc->translation_ranges, + &mc->num_translation_ranges); + if (error < 0) + goto error_cleanup_mc_io; + + error = dpmng_get_container_id(mc_io, 0, &container_id); + if (error < 0) { + dev_err(&pdev->dev, + "dpmng_get_container_id() failed: %d\n", error); + goto error_cleanup_mc_io; + } + + memset(&obj_desc, 0, sizeof(struct dprc_obj_desc)); + error = get_dprc_version(mc_io, container_id, + &obj_desc.ver_major, &obj_desc.ver_minor); + if (error < 0) + goto error_cleanup_mc_io; + + obj_desc.vendor = FSL_MC_VENDOR_FREESCALE; + strcpy(obj_desc.type, "dprc"); + obj_desc.id = container_id; + obj_desc.irq_count = 1; + obj_desc.region_count = 0; + + error = fsl_mc_device_add(&obj_desc, mc_io, &pdev->dev, &mc_bus_dev); + if (error < 0) + goto error_cleanup_mc_io; + + mc->root_mc_bus_dev = mc_bus_dev; + return 0; + +error_cleanup_mc_io: + fsl_destroy_mc_io(mc_io); + return error; +} + +/** + * fsl_mc_bus_remove - callback invoked when the root MC bus is being + * removed + */ +static int fsl_mc_bus_remove(struct platform_device *pdev) +{ + struct fsl_mc *mc = platform_get_drvdata(pdev); + + if (WARN_ON(!fsl_mc_is_root_dprc(&mc->root_mc_bus_dev->dev))) + return -EINVAL; + + fsl_mc_device_remove(mc->root_mc_bus_dev); + + fsl_destroy_mc_io(mc->root_mc_bus_dev->mc_io); + mc->root_mc_bus_dev->mc_io = NULL; + + dev_info(&pdev->dev, "Root MC bus device removed"); + return 0; +} + +static const struct of_device_id fsl_mc_bus_match_table[] = { + {.compatible = "fsl,qoriq-mc",}, + {}, +}; + +MODULE_DEVICE_TABLE(of, fsl_mc_bus_match_table); + +static struct platform_driver fsl_mc_bus_driver = { + .driver = { + .name = "fsl_mc_bus", + .pm = NULL, + .of_match_table = fsl_mc_bus_match_table, + }, + .probe = fsl_mc_bus_probe, + .remove = fsl_mc_bus_remove, +}; + +static int __init fsl_mc_bus_driver_init(void) +{ + int error; + + mc_dev_cache = kmem_cache_create("fsl_mc_device", + sizeof(struct fsl_mc_device), 0, 0, + NULL); + if (!mc_dev_cache) { + pr_err("Could not create fsl_mc_device cache\n"); + return -ENOMEM; + } + + error = bus_register(&fsl_mc_bus_type); + if (error < 0) { + pr_err("fsl-mc bus type registration failed: %d\n", error); + goto error_cleanup_cache; + } + + pr_info("fsl-mc bus type registered\n"); + + error = platform_driver_register(&fsl_mc_bus_driver); + if (error < 0) { + pr_err("platform_driver_register() failed: %d\n", error); + goto error_cleanup_bus; + } + + error = dprc_driver_init(); + if (error < 0) + goto error_cleanup_driver; + + error = fsl_mc_allocator_driver_init(); + if (error < 0) + goto error_cleanup_dprc_driver; + + error = its_fsl_mc_msi_init(); + if (error < 0) + goto error_cleanup_mc_allocator; + + return 0; + +error_cleanup_mc_allocator: + fsl_mc_allocator_driver_exit(); + +error_cleanup_dprc_driver: + dprc_driver_exit(); + +error_cleanup_driver: + platform_driver_unregister(&fsl_mc_bus_driver); + +error_cleanup_bus: + bus_unregister(&fsl_mc_bus_type); + +error_cleanup_cache: + kmem_cache_destroy(mc_dev_cache); + return error; +} +postcore_initcall(fsl_mc_bus_driver_init); diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-msi.c b/drivers/staging/fsl-mc/bus/fsl-mc-msi.c new file mode 100644 index 0000000..6e39a98 --- /dev/null +++ b/drivers/staging/fsl-mc/bus/fsl-mc-msi.c @@ -0,0 +1,287 @@ +/* + * Freescale Management Complex (MC) bus driver MSI support + * + * Copyright (C) 2015 Freescale Semiconductor, Inc. + * Author: German Rivera <German.Rivera@freescale.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include "../include/mc-bus.h" +#include <linux/of_device.h> +#include <linux/of_address.h> +#include <linux/irqchip/arm-gic-v3.h> +#include <linux/of_irq.h> +#include <linux/irq.h> +#include <linux/irqdomain.h> +#include <linux/msi.h> +#include "../include/mc-sys.h" +#include "dprc-cmd.h" + +/* + * Generate a unique ID identifying the interrupt (only used within the MSI + * irqdomain. Combine the icid with the interrupt index. + */ +static irq_hw_number_t fsl_mc_domain_calc_hwirq(struct fsl_mc_device *dev, + struct msi_desc *desc) +{ + /* + * Make the base hwirq value for ICID*10000 so it is readable + * as a decimal value in /proc/interrupts. + */ + return (irq_hw_number_t)(desc->fsl_mc.msi_index + (dev->icid * 10000)); +} + +static void fsl_mc_msi_set_desc(msi_alloc_info_t *arg, + struct msi_desc *desc) +{ + arg->desc = desc; + arg->hwirq = fsl_mc_domain_calc_hwirq(to_fsl_mc_device(desc->dev), + desc); +} + +static void fsl_mc_msi_update_dom_ops(struct msi_domain_info *info) +{ + struct msi_domain_ops *ops = info->ops; + + if (WARN_ON(!ops)) + return; + + /* + * set_desc should not be set by the caller + */ + if (ops->set_desc == NULL) + ops->set_desc = fsl_mc_msi_set_desc; +} + +static void __fsl_mc_msi_write_msg(struct fsl_mc_device *mc_bus_dev, + struct fsl_mc_device_irq *mc_dev_irq) +{ + int error; + struct fsl_mc_device *owner_mc_dev = mc_dev_irq->mc_dev; + struct msi_desc *msi_desc = mc_dev_irq->msi_desc; + struct dprc_irq_cfg irq_cfg; + + /* + * msi_desc->msg.address is 0x0 when this function is invoked in + * the free_irq() code path. In this case, for the MC, we don't + * really need to "unprogram" the MSI, so we just return. + */ + if (msi_desc->msg.address_lo == 0x0 && msi_desc->msg.address_hi == 0x0) + return; + + if (WARN_ON(!owner_mc_dev)) + return; + + irq_cfg.paddr = ((u64)msi_desc->msg.address_hi << 32) | + msi_desc->msg.address_lo; + irq_cfg.val = msi_desc->msg.data; + irq_cfg.irq_num = msi_desc->irq; + + if (owner_mc_dev == mc_bus_dev) { + /* + * IRQ is for the mc_bus_dev's DPRC itself + */ + error = dprc_set_irq(mc_bus_dev->mc_io, + MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI, + mc_bus_dev->mc_handle, + mc_dev_irq->dev_irq_index, + &irq_cfg); + if (error < 0) { + dev_err(&owner_mc_dev->dev, + "dprc_set_irq() failed: %d\n", error); + } + } else { + /* + * IRQ is for for a child device of mc_bus_dev + */ + error = dprc_set_obj_irq(mc_bus_dev->mc_io, + MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI, + mc_bus_dev->mc_handle, + owner_mc_dev->obj_desc.type, + owner_mc_dev->obj_desc.id, + mc_dev_irq->dev_irq_index, + &irq_cfg); + if (error < 0) { + dev_err(&owner_mc_dev->dev, + "dprc_obj_set_irq() failed: %d\n", error); + } + } +} + +/* + * NOTE: This function is invoked with interrupts disabled + */ +static void fsl_mc_msi_write_msg(struct irq_data *irq_data, + struct msi_msg *msg) +{ + struct msi_desc *msi_desc = irq_data_get_msi_desc(irq_data); + struct fsl_mc_device *mc_bus_dev = to_fsl_mc_device(msi_desc->dev); + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); + struct fsl_mc_device_irq *mc_dev_irq = + &mc_bus->irq_resources[msi_desc->fsl_mc.msi_index]; + + WARN_ON(mc_dev_irq->msi_desc != msi_desc); + msi_desc->msg = *msg; + + /* + * Program the MSI (paddr, value) pair in the device: + */ + __fsl_mc_msi_write_msg(mc_bus_dev, mc_dev_irq); +} + +static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info) +{ + struct irq_chip *chip = info->chip; + + if (WARN_ON((!chip))) + return; + + /* + * irq_write_msi_msg should not be set by the caller + */ + if (chip->irq_write_msi_msg == NULL) + chip->irq_write_msi_msg = fsl_mc_msi_write_msg; +} + +/** + * fsl_mc_msi_create_irq_domain - Create a fsl-mc MSI interrupt domain + * @np: Optional device-tree node of the interrupt controller + * @info: MSI domain info + * @parent: Parent irq domain + * + * Updates the domain and chip ops and creates a fsl-mc MSI + * interrupt domain. + * + * Returns: + * A domain pointer or NULL in case of failure. + */ +struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode, + struct msi_domain_info *info, + struct irq_domain *parent) +{ + struct irq_domain *domain; + + if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS) + fsl_mc_msi_update_dom_ops(info); + if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS) + fsl_mc_msi_update_chip_ops(info); + + domain = msi_create_irq_domain(fwnode, info, parent); + if (domain) + domain->bus_token = DOMAIN_BUS_FSL_MC_MSI; + + return domain; +} + +int fsl_mc_find_msi_domain(struct device *mc_platform_dev, + struct irq_domain **mc_msi_domain) +{ + struct irq_domain *msi_domain; + struct device_node *mc_of_node = mc_platform_dev->of_node; + + msi_domain = of_msi_get_domain(mc_platform_dev, mc_of_node, + DOMAIN_BUS_FSL_MC_MSI); + if (!msi_domain) { + pr_err("Unable to find fsl-mc MSI domain for %s\n", + mc_of_node->full_name); + + return -ENOENT; + } + + *mc_msi_domain = msi_domain; + return 0; +} + +static void fsl_mc_msi_free_descs(struct device *dev) +{ + struct msi_desc *desc, *tmp; + + list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) { + list_del(&desc->list); + free_msi_entry(desc); + } +} + +static int fsl_mc_msi_alloc_descs(struct device *dev, unsigned int irq_count) + +{ + unsigned int i; + int error; + struct msi_desc *msi_desc; + + for (i = 0; i < irq_count; i++) { + msi_desc = alloc_msi_entry(dev); + if (!msi_desc) { + dev_err(dev, "Failed to allocate msi entry\n"); + error = -ENOMEM; + goto cleanup_msi_descs; + } + + msi_desc->fsl_mc.msi_index = i; + msi_desc->nvec_used = 1; + INIT_LIST_HEAD(&msi_desc->list); + list_add_tail(&msi_desc->list, dev_to_msi_list(dev)); + } + + return 0; + +cleanup_msi_descs: + fsl_mc_msi_free_descs(dev); + return error; +} + +int fsl_mc_msi_domain_alloc_irqs(struct device *dev, + unsigned int irq_count) +{ + struct irq_domain *msi_domain; + int error; + + if (WARN_ON(!list_empty(dev_to_msi_list(dev)))) + return -EINVAL; + + error = fsl_mc_msi_alloc_descs(dev, irq_count); + if (error < 0) + return error; + + msi_domain = dev_get_msi_domain(dev); + if (WARN_ON(!msi_domain)) { + error = -EINVAL; + goto cleanup_msi_descs; + } + + /* + * NOTE: Calling this function will trigger the invocation of the + * its_fsl_mc_msi_prepare() callback + */ + error = msi_domain_alloc_irqs(msi_domain, dev, irq_count); + + if (error) { + dev_err(dev, "Failed to allocate IRQs\n"); + goto cleanup_msi_descs; + } + + return 0; + +cleanup_msi_descs: + fsl_mc_msi_free_descs(dev); + return error; +} + +void fsl_mc_msi_domain_free_irqs(struct device *dev) +{ + struct irq_domain *msi_domain; + + msi_domain = dev_get_msi_domain(dev); + if (WARN_ON(!msi_domain)) + return; + + msi_domain_free_irqs(msi_domain, dev); + + if (WARN_ON(list_empty(dev_to_msi_list(dev)))) + return; + + fsl_mc_msi_free_descs(dev); +} diff --git a/drivers/staging/fsl-mc/bus/mc-allocator.c b/drivers/staging/fsl-mc/bus/mc-allocator.c deleted file mode 100644 index 3ebaecb..0000000 --- a/drivers/staging/fsl-mc/bus/mc-allocator.c +++ /dev/null @@ -1,755 +0,0 @@ -/* - * Freescale MC object device allocator driver - * - * Copyright (C) 2013 Freescale Semiconductor, Inc. - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include "../include/mc-bus.h" -#include "../include/mc-sys.h" -#include <linux/module.h> -#include "../include/dpbp-cmd.h" -#include "../include/dpcon-cmd.h" -#include "dpmcp-cmd.h" -#include "dpmcp.h" -#include <linux/msi.h> - -/** - * fsl_mc_resource_pool_add_device - add allocatable device to a resource - * pool of a given MC bus - * - * @mc_bus: pointer to the MC bus - * @pool_type: MC bus pool type - * @mc_dev: Pointer to allocatable MC object device - * - * It adds an allocatable MC object device to a container's resource pool of - * the given resource type - */ -static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus - *mc_bus, - enum fsl_mc_pool_type - pool_type, - struct fsl_mc_device - *mc_dev) -{ - struct fsl_mc_resource_pool *res_pool; - struct fsl_mc_resource *resource; - struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; - int error = -EINVAL; - - if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)) - goto out; - if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type))) - goto out; - if (WARN_ON(mc_dev->resource)) - goto out; - - res_pool = &mc_bus->resource_pools[pool_type]; - if (WARN_ON(res_pool->type != pool_type)) - goto out; - if (WARN_ON(res_pool->mc_bus != mc_bus)) - goto out; - - mutex_lock(&res_pool->mutex); - - if (WARN_ON(res_pool->max_count < 0)) - goto out_unlock; - if (WARN_ON(res_pool->free_count < 0 || - res_pool->free_count > res_pool->max_count)) - goto out_unlock; - - resource = devm_kzalloc(&mc_bus_dev->dev, sizeof(*resource), - GFP_KERNEL); - if (!resource) { - error = -ENOMEM; - dev_err(&mc_bus_dev->dev, - "Failed to allocate memory for fsl_mc_resource\n"); - goto out_unlock; - } - - resource->type = pool_type; - resource->id = mc_dev->obj_desc.id; - resource->data = mc_dev; - resource->parent_pool = res_pool; - INIT_LIST_HEAD(&resource->node); - list_add_tail(&resource->node, &res_pool->free_list); - mc_dev->resource = resource; - res_pool->free_count++; - res_pool->max_count++; - error = 0; -out_unlock: - mutex_unlock(&res_pool->mutex); -out: - return error; -} - -/** - * fsl_mc_resource_pool_remove_device - remove an allocatable device from a - * resource pool - * - * @mc_dev: Pointer to allocatable MC object device - * - * It permanently removes an allocatable MC object device from the resource - * pool, the device is currently in, as long as it is in the pool's free list. - */ -static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device - *mc_dev) -{ - struct fsl_mc_device *mc_bus_dev; - struct fsl_mc_bus *mc_bus; - struct fsl_mc_resource_pool *res_pool; - struct fsl_mc_resource *resource; - int error = -EINVAL; - - if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type))) - goto out; - - resource = mc_dev->resource; - if (WARN_ON(!resource || resource->data != mc_dev)) - goto out; - - mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); - mc_bus = to_fsl_mc_bus(mc_bus_dev); - res_pool = resource->parent_pool; - if (WARN_ON(res_pool != &mc_bus->resource_pools[resource->type])) - goto out; - - mutex_lock(&res_pool->mutex); - - if (WARN_ON(res_pool->max_count <= 0)) - goto out_unlock; - if (WARN_ON(res_pool->free_count <= 0 || - res_pool->free_count > res_pool->max_count)) - goto out_unlock; - - /* - * If the device is currently allocated, its resource is not - * in the free list and thus, the device cannot be removed. - */ - if (list_empty(&resource->node)) { - error = -EBUSY; - dev_err(&mc_bus_dev->dev, - "Device %s cannot be removed from resource pool\n", - dev_name(&mc_dev->dev)); - goto out_unlock; - } - - list_del(&resource->node); - INIT_LIST_HEAD(&resource->node); - res_pool->free_count--; - res_pool->max_count--; - - devm_kfree(&mc_bus_dev->dev, resource); - mc_dev->resource = NULL; - error = 0; -out_unlock: - mutex_unlock(&res_pool->mutex); -out: - return error; -} - -static const char *const fsl_mc_pool_type_strings[] = { - [FSL_MC_POOL_DPMCP] = "dpmcp", - [FSL_MC_POOL_DPBP] = "dpbp", - [FSL_MC_POOL_DPCON] = "dpcon", - [FSL_MC_POOL_IRQ] = "irq", -}; - -static int __must_check object_type_to_pool_type(const char *object_type, - enum fsl_mc_pool_type - *pool_type) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(fsl_mc_pool_type_strings); i++) { - if (strcmp(object_type, fsl_mc_pool_type_strings[i]) == 0) { - *pool_type = i; - return 0; - } - } - - return -EINVAL; -} - -int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, - enum fsl_mc_pool_type pool_type, - struct fsl_mc_resource **new_resource) -{ - struct fsl_mc_resource_pool *res_pool; - struct fsl_mc_resource *resource; - struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; - int error = -EINVAL; - - BUILD_BUG_ON(ARRAY_SIZE(fsl_mc_pool_type_strings) != - FSL_MC_NUM_POOL_TYPES); - - *new_resource = NULL; - if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)) - goto out; - - res_pool = &mc_bus->resource_pools[pool_type]; - if (WARN_ON(res_pool->mc_bus != mc_bus)) - goto out; - - mutex_lock(&res_pool->mutex); - resource = list_first_entry_or_null(&res_pool->free_list, - struct fsl_mc_resource, node); - - if (!resource) { - WARN_ON(res_pool->free_count != 0); - error = -ENXIO; - dev_err(&mc_bus_dev->dev, - "No more resources of type %s left\n", - fsl_mc_pool_type_strings[pool_type]); - goto out_unlock; - } - - if (WARN_ON(resource->type != pool_type)) - goto out_unlock; - if (WARN_ON(resource->parent_pool != res_pool)) - goto out_unlock; - if (WARN_ON(res_pool->free_count <= 0 || - res_pool->free_count > res_pool->max_count)) - goto out_unlock; - - list_del(&resource->node); - INIT_LIST_HEAD(&resource->node); - - res_pool->free_count--; - error = 0; -out_unlock: - mutex_unlock(&res_pool->mutex); - *new_resource = resource; -out: - return error; -} -EXPORT_SYMBOL_GPL(fsl_mc_resource_allocate); - -void fsl_mc_resource_free(struct fsl_mc_resource *resource) -{ - struct fsl_mc_resource_pool *res_pool; - - res_pool = resource->parent_pool; - if (WARN_ON(resource->type != res_pool->type)) - return; - - mutex_lock(&res_pool->mutex); - if (WARN_ON(res_pool->free_count < 0 || - res_pool->free_count >= res_pool->max_count)) - goto out_unlock; - - if (WARN_ON(!list_empty(&resource->node))) - goto out_unlock; - - list_add_tail(&resource->node, &res_pool->free_list); - res_pool->free_count++; -out_unlock: - mutex_unlock(&res_pool->mutex); -} -EXPORT_SYMBOL_GPL(fsl_mc_resource_free); - -/** - * fsl_mc_portal_allocate - Allocates an MC portal - * - * @mc_dev: MC device for which the MC portal is to be allocated - * @mc_io_flags: Flags for the fsl_mc_io object that wraps the allocated - * MC portal. - * @new_mc_io: Pointer to area where the pointer to the fsl_mc_io object - * that wraps the allocated MC portal is to be returned - * - * This function allocates an MC portal from the device's parent DPRC, - * from the corresponding MC bus' pool of MC portals and wraps - * it in a new fsl_mc_io object. If 'mc_dev' is a DPRC itself, the - * portal is allocated from its own MC bus. - */ -int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, - u16 mc_io_flags, - struct fsl_mc_io **new_mc_io) -{ - struct fsl_mc_device *mc_bus_dev; - struct fsl_mc_bus *mc_bus; - phys_addr_t mc_portal_phys_addr; - size_t mc_portal_size; - struct fsl_mc_device *dpmcp_dev; - int error = -EINVAL; - struct fsl_mc_resource *resource = NULL; - struct fsl_mc_io *mc_io = NULL; - - if (mc_dev->flags & FSL_MC_IS_DPRC) { - mc_bus_dev = mc_dev; - } else { - if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent))) - return error; - - mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); - } - - mc_bus = to_fsl_mc_bus(mc_bus_dev); - *new_mc_io = NULL; - error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_DPMCP, &resource); - if (error < 0) - return error; - - error = -EINVAL; - dpmcp_dev = resource->data; - if (WARN_ON(!dpmcp_dev)) - goto error_cleanup_resource; - - if (dpmcp_dev->obj_desc.ver_major < DPMCP_MIN_VER_MAJOR || - (dpmcp_dev->obj_desc.ver_major == DPMCP_MIN_VER_MAJOR && - dpmcp_dev->obj_desc.ver_minor < DPMCP_MIN_VER_MINOR)) { - dev_err(&dpmcp_dev->dev, - "ERROR: Version %d.%d of DPMCP not supported.\n", - dpmcp_dev->obj_desc.ver_major, - dpmcp_dev->obj_desc.ver_minor); - error = -ENOTSUPP; - goto error_cleanup_resource; - } - - if (WARN_ON(dpmcp_dev->obj_desc.region_count == 0)) - goto error_cleanup_resource; - - mc_portal_phys_addr = dpmcp_dev->regions[0].start; - mc_portal_size = dpmcp_dev->regions[0].end - - dpmcp_dev->regions[0].start + 1; - - if (WARN_ON(mc_portal_size != mc_bus_dev->mc_io->portal_size)) - goto error_cleanup_resource; - - error = fsl_create_mc_io(&mc_bus_dev->dev, - mc_portal_phys_addr, - mc_portal_size, dpmcp_dev, - mc_io_flags, &mc_io); - if (error < 0) - goto error_cleanup_resource; - - *new_mc_io = mc_io; - return 0; - -error_cleanup_resource: - fsl_mc_resource_free(resource); - return error; -} -EXPORT_SYMBOL_GPL(fsl_mc_portal_allocate); - -/** - * fsl_mc_portal_free - Returns an MC portal to the pool of free MC portals - * of a given MC bus - * - * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free - */ -void fsl_mc_portal_free(struct fsl_mc_io *mc_io) -{ - struct fsl_mc_device *dpmcp_dev; - struct fsl_mc_resource *resource; - - /* - * Every mc_io obtained by calling fsl_mc_portal_allocate() is supposed - * to have a DPMCP object associated with. - */ - dpmcp_dev = mc_io->dpmcp_dev; - if (WARN_ON(!dpmcp_dev)) - return; - - resource = dpmcp_dev->resource; - if (WARN_ON(!resource || resource->type != FSL_MC_POOL_DPMCP)) - return; - - if (WARN_ON(resource->data != dpmcp_dev)) - return; - - fsl_destroy_mc_io(mc_io); - fsl_mc_resource_free(resource); -} -EXPORT_SYMBOL_GPL(fsl_mc_portal_free); - -/** - * fsl_mc_portal_reset - Resets the dpmcp object for a given fsl_mc_io object - * - * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free - */ -int fsl_mc_portal_reset(struct fsl_mc_io *mc_io) -{ - int error; - struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; - - if (WARN_ON(!dpmcp_dev)) - return -EINVAL; - - error = dpmcp_reset(mc_io, 0, dpmcp_dev->mc_handle); - if (error < 0) { - dev_err(&dpmcp_dev->dev, "dpmcp_reset() failed: %d\n", error); - return error; - } - - return 0; -} -EXPORT_SYMBOL_GPL(fsl_mc_portal_reset); - -/** - * fsl_mc_object_allocate - Allocates a MC object device of the given - * pool type from a given MC bus - * - * @mc_dev: MC device for which the MC object device is to be allocated - * @pool_type: MC bus resource pool type - * @new_mc_dev: Pointer to area where the pointer to the allocated - * MC object device is to be returned - * - * This function allocates a MC object device from the device's parent DPRC, - * from the corresponding MC bus' pool of allocatable MC object devices of - * the given resource type. mc_dev cannot be a DPRC itself. - * - * NOTE: pool_type must be different from FSL_MC_POOL_MCP, since MC - * portals are allocated using fsl_mc_portal_allocate(), instead of - * this function. - */ -int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev, - enum fsl_mc_pool_type pool_type, - struct fsl_mc_device **new_mc_adev) -{ - struct fsl_mc_device *mc_bus_dev; - struct fsl_mc_bus *mc_bus; - struct fsl_mc_device *mc_adev; - int error = -EINVAL; - struct fsl_mc_resource *resource = NULL; - - *new_mc_adev = NULL; - if (WARN_ON(mc_dev->flags & FSL_MC_IS_DPRC)) - goto error; - - if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent))) - goto error; - - if (WARN_ON(pool_type == FSL_MC_POOL_DPMCP)) - goto error; - - mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); - mc_bus = to_fsl_mc_bus(mc_bus_dev); - error = fsl_mc_resource_allocate(mc_bus, pool_type, &resource); - if (error < 0) - goto error; - - mc_adev = resource->data; - if (WARN_ON(!mc_adev)) - goto error; - - *new_mc_adev = mc_adev; - return 0; -error: - if (resource) - fsl_mc_resource_free(resource); - - return error; -} -EXPORT_SYMBOL_GPL(fsl_mc_object_allocate); - -/** - * fsl_mc_object_free - Returns an allocatable MC object device to the - * corresponding resource pool of a given MC bus. - * - * @mc_adev: Pointer to the MC object device - */ -void fsl_mc_object_free(struct fsl_mc_device *mc_adev) -{ - struct fsl_mc_resource *resource; - - resource = mc_adev->resource; - if (WARN_ON(resource->type == FSL_MC_POOL_DPMCP)) - return; - if (WARN_ON(resource->data != mc_adev)) - return; - - fsl_mc_resource_free(resource); -} -EXPORT_SYMBOL_GPL(fsl_mc_object_free); - -/* - * Initialize the interrupt pool associated with a MC bus. - * It allocates a block of IRQs from the GIC-ITS - */ -int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, - unsigned int irq_count) -{ - unsigned int i; - struct msi_desc *msi_desc; - struct fsl_mc_device_irq *irq_resources; - struct fsl_mc_device_irq *mc_dev_irq; - int error; - struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; - struct fsl_mc_resource_pool *res_pool = - &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; - - if (WARN_ON(irq_count == 0 || - irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS)) - return -EINVAL; - - error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count); - if (error < 0) - return error; - - irq_resources = devm_kzalloc(&mc_bus_dev->dev, - sizeof(*irq_resources) * irq_count, - GFP_KERNEL); - if (!irq_resources) { - error = -ENOMEM; - goto cleanup_msi_irqs; - } - - for (i = 0; i < irq_count; i++) { - mc_dev_irq = &irq_resources[i]; - - /* - * NOTE: This mc_dev_irq's MSI addr/value pair will be set - * by the fsl_mc_msi_write_msg() callback - */ - mc_dev_irq->resource.type = res_pool->type; - mc_dev_irq->resource.data = mc_dev_irq; - mc_dev_irq->resource.parent_pool = res_pool; - INIT_LIST_HEAD(&mc_dev_irq->resource.node); - list_add_tail(&mc_dev_irq->resource.node, &res_pool->free_list); - } - - for_each_msi_entry(msi_desc, &mc_bus_dev->dev) { - mc_dev_irq = &irq_resources[msi_desc->fsl_mc.msi_index]; - mc_dev_irq->msi_desc = msi_desc; - mc_dev_irq->resource.id = msi_desc->irq; - } - - res_pool->max_count = irq_count; - res_pool->free_count = irq_count; - mc_bus->irq_resources = irq_resources; - return 0; - -cleanup_msi_irqs: - fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev); - return error; -} -EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool); - -/** - * Teardown the interrupt pool associated with an MC bus. - * It frees the IRQs that were allocated to the pool, back to the GIC-ITS. - */ -void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus) -{ - struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; - struct fsl_mc_resource_pool *res_pool = - &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; - - if (WARN_ON(!mc_bus->irq_resources)) - return; - - if (WARN_ON(res_pool->max_count == 0)) - return; - - if (WARN_ON(res_pool->free_count != res_pool->max_count)) - return; - - INIT_LIST_HEAD(&res_pool->free_list); - res_pool->max_count = 0; - res_pool->free_count = 0; - mc_bus->irq_resources = NULL; - fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev); -} -EXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool); - -/** - * It allocates the IRQs required by a given MC object device. The - * IRQs are allocated from the interrupt pool associated with the - * MC bus that contains the device, if the device is not a DPRC device. - * Otherwise, the IRQs are allocated from the interrupt pool associated - * with the MC bus that represents the DPRC device itself. - */ -int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev) -{ - int i; - int irq_count; - int res_allocated_count = 0; - int error = -EINVAL; - struct fsl_mc_device_irq **irqs = NULL; - struct fsl_mc_bus *mc_bus; - struct fsl_mc_resource_pool *res_pool; - - if (WARN_ON(mc_dev->irqs)) - return -EINVAL; - - irq_count = mc_dev->obj_desc.irq_count; - if (WARN_ON(irq_count == 0)) - return -EINVAL; - - if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) - mc_bus = to_fsl_mc_bus(mc_dev); - else - mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); - - if (WARN_ON(!mc_bus->irq_resources)) - return -EINVAL; - - res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; - if (res_pool->free_count < irq_count) { - dev_err(&mc_dev->dev, - "Not able to allocate %u irqs for device\n", irq_count); - return -ENOSPC; - } - - irqs = devm_kzalloc(&mc_dev->dev, irq_count * sizeof(irqs[0]), - GFP_KERNEL); - if (!irqs) - return -ENOMEM; - - for (i = 0; i < irq_count; i++) { - struct fsl_mc_resource *resource; - - error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_IRQ, - &resource); - if (error < 0) - goto error_resource_alloc; - - irqs[i] = to_fsl_mc_irq(resource); - res_allocated_count++; - - WARN_ON(irqs[i]->mc_dev); - irqs[i]->mc_dev = mc_dev; - irqs[i]->dev_irq_index = i; - } - - mc_dev->irqs = irqs; - return 0; - -error_resource_alloc: - for (i = 0; i < res_allocated_count; i++) { - irqs[i]->mc_dev = NULL; - fsl_mc_resource_free(&irqs[i]->resource); - } - - return error; -} -EXPORT_SYMBOL_GPL(fsl_mc_allocate_irqs); - -/* - * It frees the IRQs that were allocated for a MC object device, by - * returning them to the corresponding interrupt pool. - */ -void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev) -{ - int i; - int irq_count; - struct fsl_mc_bus *mc_bus; - struct fsl_mc_device_irq **irqs = mc_dev->irqs; - - if (WARN_ON(!irqs)) - return; - - irq_count = mc_dev->obj_desc.irq_count; - - if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) - mc_bus = to_fsl_mc_bus(mc_dev); - else - mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); - - if (WARN_ON(!mc_bus->irq_resources)) - return; - - for (i = 0; i < irq_count; i++) { - WARN_ON(!irqs[i]->mc_dev); - irqs[i]->mc_dev = NULL; - fsl_mc_resource_free(&irqs[i]->resource); - } - - mc_dev->irqs = NULL; -} -EXPORT_SYMBOL_GPL(fsl_mc_free_irqs); - -/** - * fsl_mc_allocator_probe - callback invoked when an allocatable device is - * being added to the system - */ -static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev) -{ - enum fsl_mc_pool_type pool_type; - struct fsl_mc_device *mc_bus_dev; - struct fsl_mc_bus *mc_bus; - int error; - - if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type))) - return -EINVAL; - - mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); - if (WARN_ON(!dev_is_fsl_mc(&mc_bus_dev->dev))) - return -EINVAL; - - mc_bus = to_fsl_mc_bus(mc_bus_dev); - error = object_type_to_pool_type(mc_dev->obj_desc.type, &pool_type); - if (error < 0) - return error; - - error = fsl_mc_resource_pool_add_device(mc_bus, pool_type, mc_dev); - if (error < 0) - return error; - - dev_dbg(&mc_dev->dev, - "Allocatable MC object device bound to fsl_mc_allocator driver"); - return 0; -} - -/** - * fsl_mc_allocator_remove - callback invoked when an allocatable device is - * being removed from the system - */ -static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev) -{ - int error; - - if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type))) - return -EINVAL; - - if (mc_dev->resource) { - error = fsl_mc_resource_pool_remove_device(mc_dev); - if (error < 0) - return error; - } - - dev_dbg(&mc_dev->dev, - "Allocatable MC object device unbound from fsl_mc_allocator driver"); - return 0; -} - -static const struct fsl_mc_device_id match_id_table[] = { - { - .vendor = FSL_MC_VENDOR_FREESCALE, - .obj_type = "dpbp", - }, - { - .vendor = FSL_MC_VENDOR_FREESCALE, - .obj_type = "dpmcp", - }, - { - .vendor = FSL_MC_VENDOR_FREESCALE, - .obj_type = "dpcon", - }, - {.vendor = 0x0}, -}; - -static struct fsl_mc_driver fsl_mc_allocator_driver = { - .driver = { - .name = "fsl_mc_allocator", - .owner = THIS_MODULE, - .pm = NULL, - }, - .match_id_table = match_id_table, - .probe = fsl_mc_allocator_probe, - .remove = fsl_mc_allocator_remove, -}; - -int __init fsl_mc_allocator_driver_init(void) -{ - return fsl_mc_driver_register(&fsl_mc_allocator_driver); -} - -void fsl_mc_allocator_driver_exit(void) -{ - fsl_mc_driver_unregister(&fsl_mc_allocator_driver); -} diff --git a/drivers/staging/fsl-mc/bus/mc-bus.c b/drivers/staging/fsl-mc/bus/mc-bus.c deleted file mode 100644 index 975d30b..0000000 --- a/drivers/staging/fsl-mc/bus/mc-bus.c +++ /dev/null @@ -1,890 +0,0 @@ -/* - * Freescale Management Complex (MC) bus driver - * - * Copyright (C) 2014 Freescale Semiconductor, Inc. - * Author: German Rivera <German.Rivera@freescale.com> - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include "../include/mc-bus.h" -#include <linux/module.h> -#include <linux/of_device.h> -#include <linux/of_address.h> -#include <linux/ioport.h> -#include <linux/slab.h> -#include <linux/limits.h> -#include <linux/bitops.h> -#include <linux/msi.h> -#include "../include/dpmng.h" -#include "../include/mc-sys.h" -#include "dprc-cmd.h" - -static struct kmem_cache *mc_dev_cache; - -/** - * fsl_mc_bus_match - device to driver matching callback - * @dev: the MC object device structure to match against - * @drv: the device driver to search for matching MC object device id - * structures - * - * Returns 1 on success, 0 otherwise. - */ -static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv) -{ - const struct fsl_mc_device_id *id; - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); - struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(drv); - bool found = false; - - if (WARN_ON(!fsl_mc_bus_exists())) - goto out; - - if (!mc_drv->match_id_table) - goto out; - - /* - * If the object is not 'plugged' don't match. - * Only exception is the root DPRC, which is a special case. - */ - if ((mc_dev->obj_desc.state & DPRC_OBJ_STATE_PLUGGED) == 0 && - !fsl_mc_is_root_dprc(&mc_dev->dev)) - goto out; - - /* - * Traverse the match_id table of the given driver, trying to find - * a matching for the given MC object device. - */ - for (id = mc_drv->match_id_table; id->vendor != 0x0; id++) { - if (id->vendor == mc_dev->obj_desc.vendor && - strcmp(id->obj_type, mc_dev->obj_desc.type) == 0) { - found = true; - - break; - } - } - -out: - dev_dbg(dev, "%smatched\n", found ? "" : "not "); - 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) -{ - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); - - if (add_uevent_var(env, "MODALIAS=fsl-mc:v%08Xd%s", - mc_dev->obj_desc.vendor, - mc_dev->obj_desc.type)) - return -ENOMEM; - - return 0; -} - -static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); - - return sprintf(buf, "fsl-mc:v%08Xd%s\n", mc_dev->obj_desc.vendor, - mc_dev->obj_desc.type); -} -static DEVICE_ATTR_RO(modalias); - -static struct attribute *fsl_mc_dev_attrs[] = { - &dev_attr_modalias.attr, - NULL, -}; - -static const struct attribute_group fsl_mc_dev_group = { - .attrs = fsl_mc_dev_attrs, -}; - -static const struct attribute_group *fsl_mc_dev_groups[] = { - &fsl_mc_dev_group, - NULL, -}; - -struct bus_type fsl_mc_bus_type = { - .name = "fsl-mc", - .match = fsl_mc_bus_match, - .uevent = fsl_mc_bus_uevent, - .dev_groups = fsl_mc_dev_groups, -}; -EXPORT_SYMBOL_GPL(fsl_mc_bus_type); - -static atomic_t root_dprc_count = ATOMIC_INIT(0); - -static int fsl_mc_driver_probe(struct device *dev) -{ - struct fsl_mc_driver *mc_drv; - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); - int error; - - if (WARN_ON(!dev->driver)) - return -EINVAL; - - mc_drv = to_fsl_mc_driver(dev->driver); - if (WARN_ON(!mc_drv->probe)) - return -EINVAL; - - error = mc_drv->probe(mc_dev); - if (error < 0) { - dev_err(dev, "MC object device probe callback failed: %d\n", - error); - return error; - } - - return 0; -} - -static int fsl_mc_driver_remove(struct device *dev) -{ - struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver); - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); - int error; - - if (WARN_ON(!dev->driver)) - return -EINVAL; - - error = mc_drv->remove(mc_dev); - if (error < 0) { - dev_err(dev, - "MC object device remove callback failed: %d\n", - error); - return error; - } - - return 0; -} - -static void fsl_mc_driver_shutdown(struct device *dev) -{ - struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver); - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); - - mc_drv->shutdown(mc_dev); -} - -/** - * __fsl_mc_driver_register - registers a child device driver with the - * MC bus - * - * This function is implicitly invoked from the registration function of - * fsl_mc device drivers, which is generated by the - * module_fsl_mc_driver() macro. - */ -int __fsl_mc_driver_register(struct fsl_mc_driver *mc_driver, - struct module *owner) -{ - int error; - - mc_driver->driver.owner = owner; - mc_driver->driver.bus = &fsl_mc_bus_type; - - if (mc_driver->probe) - mc_driver->driver.probe = fsl_mc_driver_probe; - - if (mc_driver->remove) - mc_driver->driver.remove = fsl_mc_driver_remove; - - if (mc_driver->shutdown) - mc_driver->driver.shutdown = fsl_mc_driver_shutdown; - - error = driver_register(&mc_driver->driver); - if (error < 0) { - pr_err("driver_register() failed for %s: %d\n", - mc_driver->driver.name, error); - return error; - } - - pr_info("MC object device driver %s registered\n", - mc_driver->driver.name); - return 0; -} -EXPORT_SYMBOL_GPL(__fsl_mc_driver_register); - -/** - * fsl_mc_driver_unregister - unregisters a device driver from the - * MC bus - */ -void fsl_mc_driver_unregister(struct fsl_mc_driver *mc_driver) -{ - driver_unregister(&mc_driver->driver); -} -EXPORT_SYMBOL_GPL(fsl_mc_driver_unregister); - -/** - * fsl_mc_bus_exists - check if a root dprc exists - */ -bool fsl_mc_bus_exists(void) -{ - return atomic_read(&root_dprc_count) > 0; -} -EXPORT_SYMBOL_GPL(fsl_mc_bus_exists); - -/** -* fsl_mc_get_root_dprc - function to traverse to the root dprc -*/ -static void fsl_mc_get_root_dprc(struct device *dev, - struct device **root_dprc_dev) -{ - if (WARN_ON(!dev)) { - *root_dprc_dev = NULL; - } else if (WARN_ON(!dev_is_fsl_mc(dev))) { - *root_dprc_dev = NULL; - } else { - *root_dprc_dev = dev; - while (dev_is_fsl_mc((*root_dprc_dev)->parent)) - *root_dprc_dev = (*root_dprc_dev)->parent; - } -} - -static int get_dprc_attr(struct fsl_mc_io *mc_io, - int container_id, struct dprc_attributes *attr) -{ - u16 dprc_handle; - int error; - - error = dprc_open(mc_io, 0, container_id, &dprc_handle); - if (error < 0) { - dev_err(mc_io->dev, "dprc_open() failed: %d\n", error); - return error; - } - - memset(attr, 0, sizeof(struct dprc_attributes)); - error = dprc_get_attributes(mc_io, 0, dprc_handle, attr); - if (error < 0) { - dev_err(mc_io->dev, "dprc_get_attributes() failed: %d\n", - error); - goto common_cleanup; - } - - error = 0; - -common_cleanup: - (void)dprc_close(mc_io, 0, dprc_handle); - return error; -} - -static int get_dprc_icid(struct fsl_mc_io *mc_io, - int container_id, u16 *icid) -{ - struct dprc_attributes attr; - int error; - - error = get_dprc_attr(mc_io, container_id, &attr); - if (error == 0) - *icid = attr.icid; - - return error; -} - -static int get_dprc_version(struct fsl_mc_io *mc_io, - int container_id, u16 *major, u16 *minor) -{ - struct dprc_attributes attr; - int error; - - error = get_dprc_attr(mc_io, container_id, &attr); - if (error == 0) { - *major = attr.version.major; - *minor = attr.version.minor; - } - - return error; -} - -static int translate_mc_addr(struct fsl_mc_device *mc_dev, - enum dprc_region_type mc_region_type, - u64 mc_offset, phys_addr_t *phys_addr) -{ - int i; - struct device *root_dprc_dev; - struct fsl_mc *mc; - - fsl_mc_get_root_dprc(&mc_dev->dev, &root_dprc_dev); - if (WARN_ON(!root_dprc_dev)) - return -EINVAL; - mc = dev_get_drvdata(root_dprc_dev->parent); - - if (mc->num_translation_ranges == 0) { - /* - * Do identity mapping: - */ - *phys_addr = mc_offset; - return 0; - } - - for (i = 0; i < mc->num_translation_ranges; i++) { - struct fsl_mc_addr_translation_range *range = - &mc->translation_ranges[i]; - - if (mc_region_type == range->mc_region_type && - mc_offset >= range->start_mc_offset && - mc_offset < range->end_mc_offset) { - *phys_addr = range->start_phys_addr + - (mc_offset - range->start_mc_offset); - return 0; - } - } - - return -EFAULT; -} - -static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev, - struct fsl_mc_device *mc_bus_dev) -{ - int i; - int error; - struct resource *regions; - struct dprc_obj_desc *obj_desc = &mc_dev->obj_desc; - struct device *parent_dev = mc_dev->dev.parent; - enum dprc_region_type mc_region_type; - - if (strcmp(obj_desc->type, "dprc") == 0 || - strcmp(obj_desc->type, "dpmcp") == 0) { - mc_region_type = DPRC_REGION_TYPE_MC_PORTAL; - } else if (strcmp(obj_desc->type, "dpio") == 0) { - mc_region_type = DPRC_REGION_TYPE_QBMAN_PORTAL; - } else { - /* - * This function should not have been called for this MC object - * type, as this object type is not supposed to have MMIO - * regions - */ - WARN_ON(true); - return -EINVAL; - } - - regions = kmalloc_array(obj_desc->region_count, - sizeof(regions[0]), GFP_KERNEL); - if (!regions) - return -ENOMEM; - - for (i = 0; i < obj_desc->region_count; i++) { - struct dprc_region_desc region_desc; - - error = dprc_get_obj_region(mc_bus_dev->mc_io, - 0, - mc_bus_dev->mc_handle, - obj_desc->type, - obj_desc->id, i, ®ion_desc); - if (error < 0) { - dev_err(parent_dev, - "dprc_get_obj_region() failed: %d\n", error); - goto error_cleanup_regions; - } - - WARN_ON(region_desc.size == 0); - error = translate_mc_addr(mc_dev, mc_region_type, - region_desc.base_offset, - ®ions[i].start); - if (error < 0) { - dev_err(parent_dev, - "Invalid MC offset: %#x (for %s.%d\'s region %d)\n", - region_desc.base_offset, - obj_desc->type, obj_desc->id, i); - goto error_cleanup_regions; - } - - regions[i].end = regions[i].start + region_desc.size - 1; - regions[i].name = "fsl-mc object MMIO region"; - regions[i].flags = IORESOURCE_IO; - if (region_desc.flags & DPRC_REGION_CACHEABLE) - regions[i].flags |= IORESOURCE_CACHEABLE; - } - - mc_dev->regions = regions; - return 0; - -error_cleanup_regions: - kfree(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) -{ - struct device *root_dprc_dev; - - fsl_mc_get_root_dprc(dev, &root_dprc_dev); - if (!root_dprc_dev) - return false; - return dev == root_dprc_dev; -} - -/** - * Add a newly discovered MC object device to be visible in Linux - */ -int fsl_mc_device_add(struct dprc_obj_desc *obj_desc, - struct fsl_mc_io *mc_io, - struct device *parent_dev, - struct fsl_mc_device **new_mc_dev) -{ - int error; - struct fsl_mc_device *mc_dev = NULL; - struct fsl_mc_bus *mc_bus = NULL; - struct fsl_mc_device *parent_mc_dev; - - if (dev_is_fsl_mc(parent_dev)) - parent_mc_dev = to_fsl_mc_device(parent_dev); - else - parent_mc_dev = NULL; - - if (strcmp(obj_desc->type, "dprc") == 0) { - /* - * Allocate an MC bus device object: - */ - mc_bus = devm_kzalloc(parent_dev, sizeof(*mc_bus), GFP_KERNEL); - if (!mc_bus) - return -ENOMEM; - - mc_dev = &mc_bus->mc_dev; - } else { - /* - * Allocate a regular fsl_mc_device object: - */ - mc_dev = kmem_cache_zalloc(mc_dev_cache, GFP_KERNEL); - if (!mc_dev) - return -ENOMEM; - } - - mc_dev->obj_desc = *obj_desc; - mc_dev->mc_io = mc_io; - device_initialize(&mc_dev->dev); - mc_dev->dev.parent = parent_dev; - mc_dev->dev.bus = &fsl_mc_bus_type; - dev_set_name(&mc_dev->dev, "%s.%d", obj_desc->type, obj_desc->id); - - if (strcmp(obj_desc->type, "dprc") == 0) { - struct fsl_mc_io *mc_io2; - - mc_dev->flags |= FSL_MC_IS_DPRC; - - /* - * To get the DPRC's ICID, we need to open the DPRC - * in get_dprc_icid(). For child DPRCs, we do so using the - * parent DPRC's MC portal instead of the child DPRC's MC - * portal, in case the child DPRC is already opened with - * its own portal (e.g., the DPRC used by AIOP). - * - * NOTE: There cannot be more than one active open for a - * given MC object, using the same MC portal. - */ - if (parent_mc_dev) { - /* - * device being added is a child DPRC device - */ - mc_io2 = parent_mc_dev->mc_io; - } else { - /* - * device being added is the root DPRC device - */ - if (WARN_ON(!mc_io)) { - error = -EINVAL; - goto error_cleanup_dev; - } - - mc_io2 = mc_io; - - atomic_inc(&root_dprc_count); - } - - error = get_dprc_icid(mc_io2, obj_desc->id, &mc_dev->icid); - if (error < 0) - goto error_cleanup_dev; - } else { - /* - * A non-DPRC MC object device has to be a child of another - * MC object (specifically a DPRC object) - */ - mc_dev->icid = parent_mc_dev->icid; - mc_dev->dma_mask = FSL_MC_DEFAULT_DMA_MASK; - mc_dev->dev.dma_mask = &mc_dev->dma_mask; - dev_set_msi_domain(&mc_dev->dev, - dev_get_msi_domain(&parent_mc_dev->dev)); - } - - /* - * Get MMIO regions for the device from the MC: - * - * NOTE: the root DPRC is a special case as its MMIO region is - * obtained from the device tree - */ - if (parent_mc_dev && obj_desc->region_count != 0) { - error = fsl_mc_device_get_mmio_regions(mc_dev, - parent_mc_dev); - if (error < 0) - goto error_cleanup_dev; - } - - /* Objects are coherent, unless 'no shareability' flag set. */ - if (!(obj_desc->flags & DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY)) - arch_setup_dma_ops(&mc_dev->dev, 0, 0, NULL, true); - - /* - * The device-specific probe callback will get invoked by device_add() - */ - error = device_add(&mc_dev->dev); - if (error < 0) { - dev_err(parent_dev, - "device_add() failed for device %s: %d\n", - dev_name(&mc_dev->dev), error); - goto error_cleanup_dev; - } - - (void)get_device(&mc_dev->dev); - dev_dbg(parent_dev, "Added MC object device %s\n", - dev_name(&mc_dev->dev)); - - *new_mc_dev = mc_dev; - return 0; - -error_cleanup_dev: - kfree(mc_dev->regions); - if (mc_bus) - devm_kfree(parent_dev, mc_bus); - else - kmem_cache_free(mc_dev_cache, mc_dev); - - return error; -} -EXPORT_SYMBOL_GPL(fsl_mc_device_add); - -/** - * fsl_mc_device_remove - Remove a MC object device from being visible to - * Linux - * - * @mc_dev: Pointer to a MC object device object - */ -void fsl_mc_device_remove(struct fsl_mc_device *mc_dev) -{ - struct fsl_mc_bus *mc_bus = NULL; - - kfree(mc_dev->regions); - - /* - * The device-specific remove callback will get invoked by device_del() - */ - device_del(&mc_dev->dev); - put_device(&mc_dev->dev); - - if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) { - mc_bus = to_fsl_mc_bus(mc_dev); - - if (fsl_mc_is_root_dprc(&mc_dev->dev)) { - if (atomic_read(&root_dprc_count) > 0) - atomic_dec(&root_dprc_count); - else - WARN_ON(1); - } - } - - if (mc_bus) - devm_kfree(mc_dev->dev.parent, mc_bus); - else - kmem_cache_free(mc_dev_cache, mc_dev); -} -EXPORT_SYMBOL_GPL(fsl_mc_device_remove); - -static int parse_mc_ranges(struct device *dev, - int *paddr_cells, - int *mc_addr_cells, - int *mc_size_cells, - const __be32 **ranges_start, - u8 *num_ranges) -{ - const __be32 *prop; - int range_tuple_cell_count; - int ranges_len; - int tuple_len; - struct device_node *mc_node = dev->of_node; - - *ranges_start = of_get_property(mc_node, "ranges", &ranges_len); - if (!(*ranges_start) || !ranges_len) { - dev_warn(dev, - "missing or empty ranges property for device tree node '%s'\n", - mc_node->name); - - *num_ranges = 0; - return 0; - } - - *paddr_cells = of_n_addr_cells(mc_node); - - prop = of_get_property(mc_node, "#address-cells", NULL); - if (prop) - *mc_addr_cells = be32_to_cpup(prop); - else - *mc_addr_cells = *paddr_cells; - - prop = of_get_property(mc_node, "#size-cells", NULL); - if (prop) - *mc_size_cells = be32_to_cpup(prop); - else - *mc_size_cells = of_n_size_cells(mc_node); - - range_tuple_cell_count = *paddr_cells + *mc_addr_cells + - *mc_size_cells; - - tuple_len = range_tuple_cell_count * sizeof(__be32); - if (ranges_len % tuple_len != 0) { - dev_err(dev, "malformed ranges property '%s'\n", mc_node->name); - return -EINVAL; - } - - *num_ranges = ranges_len / tuple_len; - return 0; -} - -static int get_mc_addr_translation_ranges(struct device *dev, - struct fsl_mc_addr_translation_range - **ranges, - u8 *num_ranges) -{ - int error; - int paddr_cells; - int mc_addr_cells; - int mc_size_cells; - int i; - const __be32 *ranges_start; - const __be32 *cell; - - error = parse_mc_ranges(dev, - &paddr_cells, - &mc_addr_cells, - &mc_size_cells, - &ranges_start, - num_ranges); - if (error < 0) - return error; - - if (!(*num_ranges)) { - /* - * Missing or empty ranges property ("ranges;") for the - * 'fsl,qoriq-mc' node. In this case, identity mapping - * will be used. - */ - *ranges = NULL; - return 0; - } - - *ranges = devm_kcalloc(dev, *num_ranges, - sizeof(struct fsl_mc_addr_translation_range), - GFP_KERNEL); - if (!(*ranges)) - return -ENOMEM; - - cell = ranges_start; - for (i = 0; i < *num_ranges; ++i) { - struct fsl_mc_addr_translation_range *range = &(*ranges)[i]; - - range->mc_region_type = of_read_number(cell, 1); - range->start_mc_offset = of_read_number(cell + 1, - mc_addr_cells - 1); - cell += mc_addr_cells; - range->start_phys_addr = of_read_number(cell, paddr_cells); - cell += paddr_cells; - range->end_mc_offset = range->start_mc_offset + - of_read_number(cell, mc_size_cells); - - cell += mc_size_cells; - } - - return 0; -} - -/** - * fsl_mc_bus_probe - callback invoked when the root MC bus is being - * added - */ -static int fsl_mc_bus_probe(struct platform_device *pdev) -{ - struct dprc_obj_desc obj_desc; - int error; - struct fsl_mc *mc; - struct fsl_mc_device *mc_bus_dev = NULL; - struct fsl_mc_io *mc_io = NULL; - int container_id; - phys_addr_t mc_portal_phys_addr; - u32 mc_portal_size; - struct mc_version mc_version; - struct resource res; - - dev_info(&pdev->dev, "Root MC bus device probed"); - - mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL); - if (!mc) - return -ENOMEM; - - platform_set_drvdata(pdev, mc); - - /* - * Get physical address of MC portal for the root DPRC: - */ - error = of_address_to_resource(pdev->dev.of_node, 0, &res); - if (error < 0) { - dev_err(&pdev->dev, - "of_address_to_resource() failed for %s\n", - pdev->dev.of_node->full_name); - return error; - } - - mc_portal_phys_addr = res.start; - mc_portal_size = resource_size(&res); - error = fsl_create_mc_io(&pdev->dev, mc_portal_phys_addr, - mc_portal_size, NULL, - FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, &mc_io); - if (error < 0) - return error; - - error = mc_get_version(mc_io, 0, &mc_version); - if (error != 0) { - dev_err(&pdev->dev, - "mc_get_version() failed with error %d\n", error); - goto error_cleanup_mc_io; - } - - dev_info(&pdev->dev, - "Freescale Management Complex Firmware version: %u.%u.%u\n", - mc_version.major, mc_version.minor, mc_version.revision); - - error = get_mc_addr_translation_ranges(&pdev->dev, - &mc->translation_ranges, - &mc->num_translation_ranges); - if (error < 0) - goto error_cleanup_mc_io; - - error = dpmng_get_container_id(mc_io, 0, &container_id); - if (error < 0) { - dev_err(&pdev->dev, - "dpmng_get_container_id() failed: %d\n", error); - goto error_cleanup_mc_io; - } - - memset(&obj_desc, 0, sizeof(struct dprc_obj_desc)); - error = get_dprc_version(mc_io, container_id, - &obj_desc.ver_major, &obj_desc.ver_minor); - if (error < 0) - goto error_cleanup_mc_io; - - obj_desc.vendor = FSL_MC_VENDOR_FREESCALE; - strcpy(obj_desc.type, "dprc"); - obj_desc.id = container_id; - obj_desc.irq_count = 1; - obj_desc.region_count = 0; - - error = fsl_mc_device_add(&obj_desc, mc_io, &pdev->dev, &mc_bus_dev); - if (error < 0) - goto error_cleanup_mc_io; - - mc->root_mc_bus_dev = mc_bus_dev; - return 0; - -error_cleanup_mc_io: - fsl_destroy_mc_io(mc_io); - return error; -} - -/** - * fsl_mc_bus_remove - callback invoked when the root MC bus is being - * removed - */ -static int fsl_mc_bus_remove(struct platform_device *pdev) -{ - struct fsl_mc *mc = platform_get_drvdata(pdev); - - if (WARN_ON(!fsl_mc_is_root_dprc(&mc->root_mc_bus_dev->dev))) - return -EINVAL; - - fsl_mc_device_remove(mc->root_mc_bus_dev); - - fsl_destroy_mc_io(mc->root_mc_bus_dev->mc_io); - mc->root_mc_bus_dev->mc_io = NULL; - - dev_info(&pdev->dev, "Root MC bus device removed"); - return 0; -} - -static const struct of_device_id fsl_mc_bus_match_table[] = { - {.compatible = "fsl,qoriq-mc",}, - {}, -}; - -MODULE_DEVICE_TABLE(of, fsl_mc_bus_match_table); - -static struct platform_driver fsl_mc_bus_driver = { - .driver = { - .name = "fsl_mc_bus", - .pm = NULL, - .of_match_table = fsl_mc_bus_match_table, - }, - .probe = fsl_mc_bus_probe, - .remove = fsl_mc_bus_remove, -}; - -static int __init fsl_mc_bus_driver_init(void) -{ - int error; - - mc_dev_cache = kmem_cache_create("fsl_mc_device", - sizeof(struct fsl_mc_device), 0, 0, - NULL); - if (!mc_dev_cache) { - pr_err("Could not create fsl_mc_device cache\n"); - return -ENOMEM; - } - - error = bus_register(&fsl_mc_bus_type); - if (error < 0) { - pr_err("fsl-mc bus type registration failed: %d\n", error); - goto error_cleanup_cache; - } - - pr_info("fsl-mc bus type registered\n"); - - error = platform_driver_register(&fsl_mc_bus_driver); - if (error < 0) { - pr_err("platform_driver_register() failed: %d\n", error); - goto error_cleanup_bus; - } - - error = dprc_driver_init(); - if (error < 0) - goto error_cleanup_driver; - - error = fsl_mc_allocator_driver_init(); - if (error < 0) - goto error_cleanup_dprc_driver; - - error = its_fsl_mc_msi_init(); - if (error < 0) - goto error_cleanup_mc_allocator; - - return 0; - -error_cleanup_mc_allocator: - fsl_mc_allocator_driver_exit(); - -error_cleanup_dprc_driver: - dprc_driver_exit(); - -error_cleanup_driver: - platform_driver_unregister(&fsl_mc_bus_driver); - -error_cleanup_bus: - bus_unregister(&fsl_mc_bus_type); - -error_cleanup_cache: - kmem_cache_destroy(mc_dev_cache); - return error; -} -postcore_initcall(fsl_mc_bus_driver_init); diff --git a/drivers/staging/fsl-mc/bus/mc-msi.c b/drivers/staging/fsl-mc/bus/mc-msi.c deleted file mode 100644 index 6e39a98..0000000 --- a/drivers/staging/fsl-mc/bus/mc-msi.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Freescale Management Complex (MC) bus driver MSI support - * - * Copyright (C) 2015 Freescale Semiconductor, Inc. - * Author: German Rivera <German.Rivera@freescale.com> - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include "../include/mc-bus.h" -#include <linux/of_device.h> -#include <linux/of_address.h> -#include <linux/irqchip/arm-gic-v3.h> -#include <linux/of_irq.h> -#include <linux/irq.h> -#include <linux/irqdomain.h> -#include <linux/msi.h> -#include "../include/mc-sys.h" -#include "dprc-cmd.h" - -/* - * Generate a unique ID identifying the interrupt (only used within the MSI - * irqdomain. Combine the icid with the interrupt index. - */ -static irq_hw_number_t fsl_mc_domain_calc_hwirq(struct fsl_mc_device *dev, - struct msi_desc *desc) -{ - /* - * Make the base hwirq value for ICID*10000 so it is readable - * as a decimal value in /proc/interrupts. - */ - return (irq_hw_number_t)(desc->fsl_mc.msi_index + (dev->icid * 10000)); -} - -static void fsl_mc_msi_set_desc(msi_alloc_info_t *arg, - struct msi_desc *desc) -{ - arg->desc = desc; - arg->hwirq = fsl_mc_domain_calc_hwirq(to_fsl_mc_device(desc->dev), - desc); -} - -static void fsl_mc_msi_update_dom_ops(struct msi_domain_info *info) -{ - struct msi_domain_ops *ops = info->ops; - - if (WARN_ON(!ops)) - return; - - /* - * set_desc should not be set by the caller - */ - if (ops->set_desc == NULL) - ops->set_desc = fsl_mc_msi_set_desc; -} - -static void __fsl_mc_msi_write_msg(struct fsl_mc_device *mc_bus_dev, - struct fsl_mc_device_irq *mc_dev_irq) -{ - int error; - struct fsl_mc_device *owner_mc_dev = mc_dev_irq->mc_dev; - struct msi_desc *msi_desc = mc_dev_irq->msi_desc; - struct dprc_irq_cfg irq_cfg; - - /* - * msi_desc->msg.address is 0x0 when this function is invoked in - * the free_irq() code path. In this case, for the MC, we don't - * really need to "unprogram" the MSI, so we just return. - */ - if (msi_desc->msg.address_lo == 0x0 && msi_desc->msg.address_hi == 0x0) - return; - - if (WARN_ON(!owner_mc_dev)) - return; - - irq_cfg.paddr = ((u64)msi_desc->msg.address_hi << 32) | - msi_desc->msg.address_lo; - irq_cfg.val = msi_desc->msg.data; - irq_cfg.irq_num = msi_desc->irq; - - if (owner_mc_dev == mc_bus_dev) { - /* - * IRQ is for the mc_bus_dev's DPRC itself - */ - error = dprc_set_irq(mc_bus_dev->mc_io, - MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI, - mc_bus_dev->mc_handle, - mc_dev_irq->dev_irq_index, - &irq_cfg); - if (error < 0) { - dev_err(&owner_mc_dev->dev, - "dprc_set_irq() failed: %d\n", error); - } - } else { - /* - * IRQ is for for a child device of mc_bus_dev - */ - error = dprc_set_obj_irq(mc_bus_dev->mc_io, - MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI, - mc_bus_dev->mc_handle, - owner_mc_dev->obj_desc.type, - owner_mc_dev->obj_desc.id, - mc_dev_irq->dev_irq_index, - &irq_cfg); - if (error < 0) { - dev_err(&owner_mc_dev->dev, - "dprc_obj_set_irq() failed: %d\n", error); - } - } -} - -/* - * NOTE: This function is invoked with interrupts disabled - */ -static void fsl_mc_msi_write_msg(struct irq_data *irq_data, - struct msi_msg *msg) -{ - struct msi_desc *msi_desc = irq_data_get_msi_desc(irq_data); - struct fsl_mc_device *mc_bus_dev = to_fsl_mc_device(msi_desc->dev); - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); - struct fsl_mc_device_irq *mc_dev_irq = - &mc_bus->irq_resources[msi_desc->fsl_mc.msi_index]; - - WARN_ON(mc_dev_irq->msi_desc != msi_desc); - msi_desc->msg = *msg; - - /* - * Program the MSI (paddr, value) pair in the device: - */ - __fsl_mc_msi_write_msg(mc_bus_dev, mc_dev_irq); -} - -static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info) -{ - struct irq_chip *chip = info->chip; - - if (WARN_ON((!chip))) - return; - - /* - * irq_write_msi_msg should not be set by the caller - */ - if (chip->irq_write_msi_msg == NULL) - chip->irq_write_msi_msg = fsl_mc_msi_write_msg; -} - -/** - * fsl_mc_msi_create_irq_domain - Create a fsl-mc MSI interrupt domain - * @np: Optional device-tree node of the interrupt controller - * @info: MSI domain info - * @parent: Parent irq domain - * - * Updates the domain and chip ops and creates a fsl-mc MSI - * interrupt domain. - * - * Returns: - * A domain pointer or NULL in case of failure. - */ -struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode, - struct msi_domain_info *info, - struct irq_domain *parent) -{ - struct irq_domain *domain; - - if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS) - fsl_mc_msi_update_dom_ops(info); - if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS) - fsl_mc_msi_update_chip_ops(info); - - domain = msi_create_irq_domain(fwnode, info, parent); - if (domain) - domain->bus_token = DOMAIN_BUS_FSL_MC_MSI; - - return domain; -} - -int fsl_mc_find_msi_domain(struct device *mc_platform_dev, - struct irq_domain **mc_msi_domain) -{ - struct irq_domain *msi_domain; - struct device_node *mc_of_node = mc_platform_dev->of_node; - - msi_domain = of_msi_get_domain(mc_platform_dev, mc_of_node, - DOMAIN_BUS_FSL_MC_MSI); - if (!msi_domain) { - pr_err("Unable to find fsl-mc MSI domain for %s\n", - mc_of_node->full_name); - - return -ENOENT; - } - - *mc_msi_domain = msi_domain; - return 0; -} - -static void fsl_mc_msi_free_descs(struct device *dev) -{ - struct msi_desc *desc, *tmp; - - list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) { - list_del(&desc->list); - free_msi_entry(desc); - } -} - -static int fsl_mc_msi_alloc_descs(struct device *dev, unsigned int irq_count) - -{ - unsigned int i; - int error; - struct msi_desc *msi_desc; - - for (i = 0; i < irq_count; i++) { - msi_desc = alloc_msi_entry(dev); - if (!msi_desc) { - dev_err(dev, "Failed to allocate msi entry\n"); - error = -ENOMEM; - goto cleanup_msi_descs; - } - - msi_desc->fsl_mc.msi_index = i; - msi_desc->nvec_used = 1; - INIT_LIST_HEAD(&msi_desc->list); - list_add_tail(&msi_desc->list, dev_to_msi_list(dev)); - } - - return 0; - -cleanup_msi_descs: - fsl_mc_msi_free_descs(dev); - return error; -} - -int fsl_mc_msi_domain_alloc_irqs(struct device *dev, - unsigned int irq_count) -{ - struct irq_domain *msi_domain; - int error; - - if (WARN_ON(!list_empty(dev_to_msi_list(dev)))) - return -EINVAL; - - error = fsl_mc_msi_alloc_descs(dev, irq_count); - if (error < 0) - return error; - - msi_domain = dev_get_msi_domain(dev); - if (WARN_ON(!msi_domain)) { - error = -EINVAL; - goto cleanup_msi_descs; - } - - /* - * NOTE: Calling this function will trigger the invocation of the - * its_fsl_mc_msi_prepare() callback - */ - error = msi_domain_alloc_irqs(msi_domain, dev, irq_count); - - if (error) { - dev_err(dev, "Failed to allocate IRQs\n"); - goto cleanup_msi_descs; - } - - return 0; - -cleanup_msi_descs: - fsl_mc_msi_free_descs(dev); - return error; -} - -void fsl_mc_msi_domain_free_irqs(struct device *dev) -{ - struct irq_domain *msi_domain; - - msi_domain = dev_get_msi_domain(dev); - if (WARN_ON(!msi_domain)) - return; - - msi_domain_free_irqs(msi_domain, dev); - - if (WARN_ON(list_empty(dev_to_msi_list(dev)))) - return; - - fsl_mc_msi_free_descs(dev); -} -- cgit v0.10.2 From e267dddd212e62190bcc42441ed189dfa323724c Mon Sep 17 00:00:00 2001 From: Stuart Yoder <stuart.yoder@nxp.com> Date: Tue, 23 Aug 2016 17:13:17 -0500 Subject: staging: fsl-mc: move allocator private definitions out of mc-bus.h move definitions private to the allocator out of mc-bus.h and into allocator.c Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c index 3ebaecb..6550564 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c @@ -17,6 +17,11 @@ #include "dpmcp.h" #include <linux/msi.h> +#define FSL_MC_IS_ALLOCATABLE(_obj_type) \ + (strcmp(_obj_type, "dpbp") == 0 || \ + strcmp(_obj_type, "dpmcp") == 0 || \ + strcmp(_obj_type, "dpcon") == 0) + /** * fsl_mc_resource_pool_add_device - add allocatable device to a resource * pool of a given MC bus diff --git a/drivers/staging/fsl-mc/include/mc-bus.h b/drivers/staging/fsl-mc/include/mc-bus.h index 7f847e6..f192aa8 100644 --- a/drivers/staging/fsl-mc/include/mc-bus.h +++ b/drivers/staging/fsl-mc/include/mc-bus.h @@ -21,11 +21,6 @@ (strcmp((_mc_dev)->obj_desc.type, (_obj_desc)->type) == 0 && \ (_mc_dev)->obj_desc.id == (_obj_desc)->id) -#define FSL_MC_IS_ALLOCATABLE(_obj_type) \ - (strcmp(_obj_type, "dpbp") == 0 || \ - strcmp(_obj_type, "dpmcp") == 0 || \ - strcmp(_obj_type, "dpcon") == 0) - struct irq_domain; struct msi_domain_info; -- cgit v0.10.2 From 3640695569016dd9a1734df2fe3692d49cffb7ba Mon Sep 17 00:00:00 2001 From: Stuart Yoder <stuart.yoder@nxp.com> Date: Tue, 23 Aug 2016 17:13:24 -0500 Subject: staging: fsl-mc: move resource pool init/cleanup into allocator The resource pool init/cleanup functions logically belong in the allocator. Move them to the allocator and rename to reflect the move out of the dprc-driver. Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c index 83e72b3..89d53da 100644 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c +++ b/drivers/staging/fsl-mc/bus/dprc-driver.c @@ -190,55 +190,6 @@ static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev, } } -static void dprc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev) -{ - int pool_type; - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); - - for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) { - struct fsl_mc_resource_pool *res_pool = - &mc_bus->resource_pools[pool_type]; - - res_pool->type = pool_type; - res_pool->max_count = 0; - res_pool->free_count = 0; - res_pool->mc_bus = mc_bus; - INIT_LIST_HEAD(&res_pool->free_list); - mutex_init(&res_pool->mutex); - } -} - -static void dprc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev, - enum fsl_mc_pool_type pool_type) -{ - struct fsl_mc_resource *resource; - struct fsl_mc_resource *next; - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); - struct fsl_mc_resource_pool *res_pool = - &mc_bus->resource_pools[pool_type]; - int free_count = 0; - - WARN_ON(res_pool->type != pool_type); - WARN_ON(res_pool->free_count != res_pool->max_count); - - list_for_each_entry_safe(resource, next, &res_pool->free_list, node) { - free_count++; - WARN_ON(resource->type != res_pool->type); - WARN_ON(resource->parent_pool != res_pool); - devm_kfree(&mc_bus_dev->dev, resource); - } - - WARN_ON(free_count != res_pool->free_count); -} - -static void dprc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev) -{ - int pool_type; - - for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) - dprc_cleanup_resource_pool(mc_bus_dev, pool_type); -} - /** * dprc_scan_objects - Discover objects in a DPRC * @@ -363,7 +314,7 @@ int dprc_scan_container(struct fsl_mc_device *mc_bus_dev) unsigned int irq_count; struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); - dprc_init_all_resource_pools(mc_bus_dev); + fsl_mc_init_all_resource_pools(mc_bus_dev); /* * Discover objects in the DPRC: @@ -390,7 +341,7 @@ int dprc_scan_container(struct fsl_mc_device *mc_bus_dev) return 0; error: - dprc_cleanup_all_resource_pools(mc_bus_dev); + fsl_mc_cleanup_all_resource_pools(mc_bus_dev); return error; } EXPORT_SYMBOL_GPL(dprc_scan_container); @@ -802,7 +753,7 @@ static int dprc_remove(struct fsl_mc_device *mc_dev) dev_set_msi_domain(&mc_dev->dev, NULL); } - dprc_cleanup_all_resource_pools(mc_dev); + fsl_mc_cleanup_all_resource_pools(mc_dev); error = dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); if (error < 0) diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c index 6550564..9695f44 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c @@ -668,6 +668,55 @@ void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev) } EXPORT_SYMBOL_GPL(fsl_mc_free_irqs); +void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev) +{ + int pool_type; + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); + + for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) { + struct fsl_mc_resource_pool *res_pool = + &mc_bus->resource_pools[pool_type]; + + res_pool->type = pool_type; + res_pool->max_count = 0; + res_pool->free_count = 0; + res_pool->mc_bus = mc_bus; + INIT_LIST_HEAD(&res_pool->free_list); + mutex_init(&res_pool->mutex); + } +} + +static void fsl_mc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev, + enum fsl_mc_pool_type pool_type) +{ + struct fsl_mc_resource *resource; + struct fsl_mc_resource *next; + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); + struct fsl_mc_resource_pool *res_pool = + &mc_bus->resource_pools[pool_type]; + int free_count = 0; + + WARN_ON(res_pool->type != pool_type); + WARN_ON(res_pool->free_count != res_pool->max_count); + + list_for_each_entry_safe(resource, next, &res_pool->free_list, node) { + free_count++; + WARN_ON(resource->type != res_pool->type); + WARN_ON(resource->parent_pool != res_pool); + devm_kfree(&mc_bus_dev->dev, resource); + } + + WARN_ON(free_count != res_pool->free_count); +} + +void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev) +{ + int pool_type; + + for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) + 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 diff --git a/drivers/staging/fsl-mc/include/mc-bus.h b/drivers/staging/fsl-mc/include/mc-bus.h index f192aa8..2098b3c 100644 --- a/drivers/staging/fsl-mc/include/mc-bus.h +++ b/drivers/staging/fsl-mc/include/mc-bus.h @@ -150,4 +150,8 @@ int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus); +void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev); + +void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev); + #endif /* _FSL_MC_MCBUS_H_ */ -- cgit v0.10.2 From 243444fb8cc0d066be81aee379f450a111f05dbd Mon Sep 17 00:00:00 2001 From: Stuart Yoder <stuart.yoder@nxp.com> Date: Tue, 23 Aug 2016 17:13:30 -0500 Subject: staging: fsl-mc: create private include for fsl-mc bus components The mc-bus.h header file is intended to be public for system related drivers that may need to make fsl-mc bus specific calls-- gic its, smmu, vfio. But, currently it contains definitions private/internal to the fsl-mc bus itself. Split those definitions out into a new fsl-mc bus private header. Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c index 89d53da..576244b 100644 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c +++ b/drivers/staging/fsl-mc/bus/dprc-driver.c @@ -16,6 +16,7 @@ #include <linux/interrupt.h> #include <linux/msi.h> #include "dprc-cmd.h" +#include "fsl-mc-private.h" struct dprc_child_objs { int child_count; diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c index 9695f44..e865375 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c @@ -15,6 +15,7 @@ #include "../include/dpcon-cmd.h" #include "dpmcp-cmd.h" #include "dpmcp.h" +#include "fsl-mc-private.h" #include <linux/msi.h> #define FSL_MC_IS_ALLOCATABLE(_obj_type) \ diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c index 975d30b..180ff07 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c @@ -20,6 +20,7 @@ #include <linux/msi.h> #include "../include/dpmng.h" #include "../include/mc-sys.h" +#include "fsl-mc-private.h" #include "dprc-cmd.h" static struct kmem_cache *mc_dev_cache; diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-private.h b/drivers/staging/fsl-mc/bus/fsl-mc-private.h new file mode 100644 index 0000000..1479934 --- /dev/null +++ b/drivers/staging/fsl-mc/bus/fsl-mc-private.h @@ -0,0 +1,44 @@ +/* + * Freescale Management Complex (MC) bus private declarations + * + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ +#ifndef _FSL_MC_PRIVATE_H_ +#define _FSL_MC_PRIVATE_H_ + +int __must_check fsl_mc_device_add(struct dprc_obj_desc *obj_desc, + struct fsl_mc_io *mc_io, + struct device *parent_dev, + struct fsl_mc_device **new_mc_dev); + +void fsl_mc_device_remove(struct fsl_mc_device *mc_dev); + +int __init dprc_driver_init(void); + +void dprc_driver_exit(void); + +int __init fsl_mc_allocator_driver_init(void); + +void fsl_mc_allocator_driver_exit(void); + +int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, + enum fsl_mc_pool_type pool_type, + struct fsl_mc_resource + **new_resource); + +void fsl_mc_resource_free(struct fsl_mc_resource *resource); + +int fsl_mc_msi_domain_alloc_irqs(struct device *dev, + unsigned int irq_count); + +void fsl_mc_msi_domain_free_irqs(struct device *dev); + +int __init its_fsl_mc_msi_init(void); + +void its_fsl_mc_msi_cleanup(void); + +#endif /* _FSL_MC_PRIVATE_H_ */ diff --git a/drivers/staging/fsl-mc/include/mc-bus.h b/drivers/staging/fsl-mc/include/mc-bus.h index 2098b3c..8a32e55 100644 --- a/drivers/staging/fsl-mc/include/mc-bus.h +++ b/drivers/staging/fsl-mc/include/mc-bus.h @@ -102,13 +102,6 @@ struct fsl_mc_bus { #define to_fsl_mc_bus(_mc_dev) \ container_of(_mc_dev, struct fsl_mc_bus, mc_dev) -int __must_check fsl_mc_device_add(struct dprc_obj_desc *obj_desc, - struct fsl_mc_io *mc_io, - struct device *parent_dev, - struct fsl_mc_device **new_mc_dev); - -void fsl_mc_device_remove(struct fsl_mc_device *mc_dev); - int dprc_scan_container(struct fsl_mc_device *mc_bus_dev); int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, @@ -122,13 +115,6 @@ int __init fsl_mc_allocator_driver_init(void); void fsl_mc_allocator_driver_exit(void); -int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, - enum fsl_mc_pool_type pool_type, - struct fsl_mc_resource - **new_resource); - -void fsl_mc_resource_free(struct fsl_mc_resource *resource); - struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode, struct msi_domain_info *info, struct irq_domain *parent); @@ -136,15 +122,6 @@ struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode, int fsl_mc_find_msi_domain(struct device *mc_platform_dev, struct irq_domain **mc_msi_domain); -int fsl_mc_msi_domain_alloc_irqs(struct device *dev, - unsigned int irq_count); - -void fsl_mc_msi_domain_free_irqs(struct device *dev); - -int __init its_fsl_mc_msi_init(void); - -void its_fsl_mc_msi_cleanup(void); - int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, unsigned int irq_count); -- cgit v0.10.2 From 2b0011d2bf5924f1509903f15bcb3359521c42bb Mon Sep 17 00:00:00 2001 From: Stuart Yoder <stuart.yoder@nxp.com> Date: Tue, 23 Aug 2016 17:13:35 -0500 Subject: staging: fsl-mc: move dprc-driver private definitions out of mc-bus.h Move definitions that are private to dprc-driver.c out of the public mc-bus.h header. Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c index 576244b..5e34720 100644 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c +++ b/drivers/staging/fsl-mc/bus/dprc-driver.c @@ -18,6 +18,12 @@ #include "dprc-cmd.h" #include "fsl-mc-private.h" +#define FSL_MC_DPRC_DRIVER_NAME "fsl_mc_dprc" + +#define FSL_MC_DEVICE_MATCH(_mc_dev, _obj_desc) \ + (strcmp((_mc_dev)->obj_desc.type, (_obj_desc)->type) == 0 && \ + (_mc_dev)->obj_desc.id == (_obj_desc)->id) + struct dprc_child_objs { int child_count; struct dprc_obj_desc *child_array; diff --git a/drivers/staging/fsl-mc/include/mc-bus.h b/drivers/staging/fsl-mc/include/mc-bus.h index 8a32e55..3f80506 100644 --- a/drivers/staging/fsl-mc/include/mc-bus.h +++ b/drivers/staging/fsl-mc/include/mc-bus.h @@ -15,12 +15,6 @@ #include <linux/mutex.h> #include <linux/stringify.h> -#define FSL_MC_DPRC_DRIVER_NAME "fsl_mc_dprc" - -#define FSL_MC_DEVICE_MATCH(_mc_dev, _obj_desc) \ - (strcmp((_mc_dev)->obj_desc.type, (_obj_desc)->type) == 0 && \ - (_mc_dev)->obj_desc.id == (_obj_desc)->id) - struct irq_domain; struct msi_domain_info; -- cgit v0.10.2 From e730d86d7462c304f62596f8dd619f2ac9458f6a Mon Sep 17 00:00:00 2001 From: Stuart Yoder <stuart.yoder@nxp.com> Date: Tue, 23 Aug 2016 17:13:40 -0500 Subject: staging: fsl-mc: move bus private definitions into fsl-mc-bus.c Move definitions that are private to fsl-mc-bus.c out of the public mc-bus.h and mc.h headers. Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c index 180ff07..08363f8 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c @@ -26,6 +26,39 @@ static struct kmem_cache *mc_dev_cache; /** + * Default DMA mask for devices on a fsl-mc bus + */ +#define FSL_MC_DEFAULT_DMA_MASK (~0ULL) + +/** + * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device + * @root_mc_bus_dev: MC object 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 + */ +struct fsl_mc { + struct fsl_mc_device *root_mc_bus_dev; + u8 num_translation_ranges; + struct fsl_mc_addr_translation_range *translation_ranges; +}; + +/** + * struct fsl_mc_addr_translation_range - bus to system address translation + * range + * @mc_region_type: Type of MC region for the range being translated + * @start_mc_offset: Start MC offset of the range being translated + * @end_mc_offset: MC offset of the first byte after the range (last MC + * offset of the range is end_mc_offset - 1) + * @start_phys_addr: system physical address corresponding to start_mc_addr + */ +struct fsl_mc_addr_translation_range { + enum dprc_region_type mc_region_type; + u64 start_mc_offset; + u64 end_mc_offset; + phys_addr_t start_phys_addr; +}; + +/** * fsl_mc_bus_match - device to driver matching callback * @dev: the MC object device structure to match against * @drv: the device driver to search for matching MC object device id diff --git a/drivers/staging/fsl-mc/include/mc-bus.h b/drivers/staging/fsl-mc/include/mc-bus.h index 3f80506..9ea023b 100644 --- a/drivers/staging/fsl-mc/include/mc-bus.h +++ b/drivers/staging/fsl-mc/include/mc-bus.h @@ -29,34 +29,6 @@ struct irq_domain; struct msi_domain_info; /** - * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device - * @root_mc_bus_dev: MC object device representing the root DPRC - * @num_translation_ranges: number of entries in addr_translation_ranges - * @translation_ranges: array of bus to system address translation ranges - */ -struct fsl_mc { - struct fsl_mc_device *root_mc_bus_dev; - u8 num_translation_ranges; - struct fsl_mc_addr_translation_range *translation_ranges; -}; - -/** - * struct fsl_mc_addr_translation_range - bus to system address translation - * range - * @mc_region_type: Type of MC region for the range being translated - * @start_mc_offset: Start MC offset of the range being translated - * @end_mc_offset: MC offset of the first byte after the range (last MC - * offset of the range is end_mc_offset - 1) - * @start_phys_addr: system physical address corresponding to start_mc_addr - */ -struct fsl_mc_addr_translation_range { - enum dprc_region_type mc_region_type; - u64 start_mc_offset; - u64 end_mc_offset; - phys_addr_t start_phys_addr; -}; - -/** * struct fsl_mc_resource_pool - Pool of MC resources of a given * type * @type: type of resources in the pool diff --git a/drivers/staging/fsl-mc/include/mc.h b/drivers/staging/fsl-mc/include/mc.h index 2d67535..ab439fa 100644 --- a/drivers/staging/fsl-mc/include/mc.h +++ b/drivers/staging/fsl-mc/include/mc.h @@ -112,11 +112,6 @@ struct fsl_mc_device_irq { #define FSL_MC_IS_DPRC 0x0001 /** - * Default DMA mask for devices on a fsl-mc bus - */ -#define FSL_MC_DEFAULT_DMA_MASK (~0ULL) - -/** * struct fsl_mc_device - MC object device object * @dev: Linux driver model device object * @dma_mask: Default DMA mask -- cgit v0.10.2 From 27365d85cfb6cdf8e584764bfdca747d3087b21d Mon Sep 17 00:00:00 2001 From: Stuart Yoder <stuart.yoder@nxp.com> Date: Tue, 23 Aug 2016 17:13:46 -0500 Subject: staging: fsl-mc: make fsl_mc_get_root_dprc public fsl_mc_get_root_dprc is needed by other components (e.g. vfio) to find the root dprc Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c index 08363f8..fda6a98 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c @@ -265,8 +265,8 @@ EXPORT_SYMBOL_GPL(fsl_mc_bus_exists); /** * fsl_mc_get_root_dprc - function to traverse to the root dprc */ -static void fsl_mc_get_root_dprc(struct device *dev, - struct device **root_dprc_dev) +void fsl_mc_get_root_dprc(struct device *dev, + struct device **root_dprc_dev) { if (WARN_ON(!dev)) { *root_dprc_dev = NULL; @@ -278,6 +278,7 @@ static void fsl_mc_get_root_dprc(struct device *dev, *root_dprc_dev = (*root_dprc_dev)->parent; } } +EXPORT_SYMBOL_GPL(fsl_mc_get_root_dprc); static int get_dprc_attr(struct fsl_mc_io *mc_io, int container_id, struct dprc_attributes *attr) diff --git a/drivers/staging/fsl-mc/include/mc.h b/drivers/staging/fsl-mc/include/mc.h index ab439fa..a71342d 100644 --- a/drivers/staging/fsl-mc/include/mc.h +++ b/drivers/staging/fsl-mc/include/mc.h @@ -191,6 +191,9 @@ void fsl_mc_driver_unregister(struct fsl_mc_driver *driver); bool fsl_mc_bus_exists(void); +void fsl_mc_get_root_dprc(struct device *dev, + struct device **root_dprc_dev); + int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, u16 mc_io_flags, struct fsl_mc_io **new_mc_io); -- cgit v0.10.2 From c7743b423300abea99fafb7d7d897e558bf160cc Mon Sep 17 00:00:00 2001 From: Stuart Yoder <stuart.yoder@nxp.com> Date: Tue, 23 Aug 2016 17:13:51 -0500 Subject: staging: fsl-mc: remove unneeded forward declarations Remove unneeded and duplicated forward declarations. Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fsl-mc/include/mc-bus.h b/drivers/staging/fsl-mc/include/mc-bus.h index 9ea023b..7eba588 100644 --- a/drivers/staging/fsl-mc/include/mc-bus.h +++ b/drivers/staging/fsl-mc/include/mc-bus.h @@ -24,10 +24,6 @@ struct msi_domain_info; */ #define FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS 256 -struct device_node; -struct irq_domain; -struct msi_domain_info; - /** * struct fsl_mc_resource_pool - Pool of MC resources of a given * type diff --git a/drivers/staging/fsl-mc/include/mc.h b/drivers/staging/fsl-mc/include/mc.h index a71342d..b093aba 100644 --- a/drivers/staging/fsl-mc/include/mc.h +++ b/drivers/staging/fsl-mc/include/mc.h @@ -21,7 +21,6 @@ struct fsl_mc_device; struct fsl_mc_io; -struct fsl_mc_bus; /** * struct fsl_mc_driver - MC object device driver object -- cgit v0.10.2 From e744e45ab92ede6932b55298e9657f878c73fbb4 Mon Sep 17 00:00:00 2001 From: Stuart Yoder <stuart.yoder@nxp.com> Date: Tue, 23 Aug 2016 17:13:59 -0500 Subject: staging: fsl-mc: move bus definitions from mc.h to mc-bus.h move public bus-related definitions to the proper mc-bus.h header. Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fsl-mc/include/mc-bus.h b/drivers/staging/fsl-mc/include/mc-bus.h index 7eba588..2cdb538 100644 --- a/drivers/staging/fsl-mc/include/mc-bus.h +++ b/drivers/staging/fsl-mc/include/mc-bus.h @@ -24,6 +24,13 @@ struct msi_domain_info; */ #define FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS 256 +#ifdef CONFIG_FSL_MC_BUS +#define dev_is_fsl_mc(_dev) ((_dev)->bus == &fsl_mc_bus_type) +#else +/* If fsl-mc bus is not present device cannot belong to fsl-mc bus */ +#define dev_is_fsl_mc(_dev) (0) +#endif + /** * struct fsl_mc_resource_pool - Pool of MC resources of a given * type @@ -93,4 +100,13 @@ void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev); void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev); +bool fsl_mc_bus_exists(void); + +void fsl_mc_get_root_dprc(struct device *dev, + struct device **root_dprc_dev); + +bool fsl_mc_is_root_dprc(struct device *dev); + +extern struct bus_type fsl_mc_bus_type; + #endif /* _FSL_MC_MCBUS_H_ */ diff --git a/drivers/staging/fsl-mc/include/mc.h b/drivers/staging/fsl-mc/include/mc.h index b093aba..789e6a8 100644 --- a/drivers/staging/fsl-mc/include/mc.h +++ b/drivers/staging/fsl-mc/include/mc.h @@ -160,13 +160,6 @@ struct fsl_mc_device { #define to_fsl_mc_device(_dev) \ container_of(_dev, struct fsl_mc_device, dev) -#ifdef CONFIG_FSL_MC_BUS -#define dev_is_fsl_mc(_dev) ((_dev)->bus == &fsl_mc_bus_type) -#else -/* If fsl-mc bus is not present device cannot belong to fsl-mc bus */ -#define dev_is_fsl_mc(_dev) (0) -#endif - /* * module_fsl_mc_driver() - Helper macro for drivers that don't do * anything special in module init/exit. This eliminates a lot of @@ -188,11 +181,6 @@ int __must_check __fsl_mc_driver_register(struct fsl_mc_driver *fsl_mc_driver, void fsl_mc_driver_unregister(struct fsl_mc_driver *driver); -bool fsl_mc_bus_exists(void); - -void fsl_mc_get_root_dprc(struct device *dev, - struct device **root_dprc_dev); - int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, u16 mc_io_flags, struct fsl_mc_io **new_mc_io); @@ -211,8 +199,4 @@ int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev); void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev); -bool fsl_mc_is_root_dprc(struct device *dev); - -extern struct bus_type fsl_mc_bus_type; - #endif /* _FSL_MC_H_ */ -- cgit v0.10.2 From 693c5a9d432d8f87ae494096189b209f75532d9a Mon Sep 17 00:00:00 2001 From: Stuart Yoder <stuart.yoder@nxp.com> Date: Tue, 23 Aug 2016 17:14:08 -0500 Subject: staging: fsl-mc: remove unneeded includes Over time we've accumulated some includes that are no longer needed. Remove them. Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-msi.c b/drivers/staging/fsl-mc/bus/fsl-mc-msi.c index 6e39a98..7c20f60 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-msi.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-msi.c @@ -17,8 +17,6 @@ #include <linux/irq.h> #include <linux/irqdomain.h> #include <linux/msi.h> -#include "../include/mc-sys.h" -#include "dprc-cmd.h" /* * Generate a unique ID identifying the interrupt (only used within the MSI diff --git a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c index aac4379..2586328 100644 --- a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c +++ b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c @@ -17,8 +17,6 @@ #include <linux/msi.h> #include <linux/of.h> #include <linux/of_irq.h> -#include "../include/mc-sys.h" -#include "dprc-cmd.h" static struct irq_chip its_msi_irq_chip = { .name = "fsl-mc-bus-msi", diff --git a/drivers/staging/fsl-mc/include/mc-bus.h b/drivers/staging/fsl-mc/include/mc-bus.h index 2cdb538..170684a 100644 --- a/drivers/staging/fsl-mc/include/mc-bus.h +++ b/drivers/staging/fsl-mc/include/mc-bus.h @@ -13,7 +13,6 @@ #include "../include/mc.h" #include <linux/mutex.h> -#include <linux/stringify.h> struct irq_domain; struct msi_domain_info; diff --git a/drivers/staging/fsl-mc/include/mc.h b/drivers/staging/fsl-mc/include/mc.h index 789e6a8..f6e720e 100644 --- a/drivers/staging/fsl-mc/include/mc.h +++ b/drivers/staging/fsl-mc/include/mc.h @@ -13,7 +13,6 @@ #include <linux/device.h> #include <linux/mod_devicetable.h> -#include <linux/list.h> #include <linux/interrupt.h> #include "../include/dprc.h" -- cgit v0.10.2 From 7f59f4c71d727bd34dd604f368530cc36f4bfc93 Mon Sep 17 00:00:00 2001 From: Stuart Yoder <stuart.yoder@nxp.com> Date: Tue, 23 Aug 2016 17:14:14 -0500 Subject: staging: fsl-mc: split mc-io definitions into a separate file An mc-io is a software abstraction of a dpmcp object (an MC portal). Routines to create/initialize/reset this portal abstraction were split between the allocator and mc-sys.c (MC command interface). Move mc-io/portal related definitions into one source file. Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fsl-mc/bus/Makefile b/drivers/staging/fsl-mc/bus/Makefile index 5fb4c14..38716fd 100644 --- a/drivers/staging/fsl-mc/bus/Makefile +++ b/drivers/staging/fsl-mc/bus/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_FSL_MC_BUS) += mc-bus-driver.o mc-bus-driver-objs := fsl-mc-bus.o \ mc-sys.o \ + mc-io.o \ dprc.o \ dpmng.o \ dprc-driver.o \ diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c index e865375..edcb5cc 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c @@ -13,8 +13,6 @@ #include <linux/module.h> #include "../include/dpbp-cmd.h" #include "../include/dpcon-cmd.h" -#include "dpmcp-cmd.h" -#include "dpmcp.h" #include "fsl-mc-private.h" #include <linux/msi.h> @@ -258,144 +256,6 @@ out_unlock: EXPORT_SYMBOL_GPL(fsl_mc_resource_free); /** - * fsl_mc_portal_allocate - Allocates an MC portal - * - * @mc_dev: MC device for which the MC portal is to be allocated - * @mc_io_flags: Flags for the fsl_mc_io object that wraps the allocated - * MC portal. - * @new_mc_io: Pointer to area where the pointer to the fsl_mc_io object - * that wraps the allocated MC portal is to be returned - * - * This function allocates an MC portal from the device's parent DPRC, - * from the corresponding MC bus' pool of MC portals and wraps - * it in a new fsl_mc_io object. If 'mc_dev' is a DPRC itself, the - * portal is allocated from its own MC bus. - */ -int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, - u16 mc_io_flags, - struct fsl_mc_io **new_mc_io) -{ - struct fsl_mc_device *mc_bus_dev; - struct fsl_mc_bus *mc_bus; - phys_addr_t mc_portal_phys_addr; - size_t mc_portal_size; - struct fsl_mc_device *dpmcp_dev; - int error = -EINVAL; - struct fsl_mc_resource *resource = NULL; - struct fsl_mc_io *mc_io = NULL; - - if (mc_dev->flags & FSL_MC_IS_DPRC) { - mc_bus_dev = mc_dev; - } else { - if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent))) - return error; - - mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); - } - - mc_bus = to_fsl_mc_bus(mc_bus_dev); - *new_mc_io = NULL; - error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_DPMCP, &resource); - if (error < 0) - return error; - - error = -EINVAL; - dpmcp_dev = resource->data; - if (WARN_ON(!dpmcp_dev)) - goto error_cleanup_resource; - - if (dpmcp_dev->obj_desc.ver_major < DPMCP_MIN_VER_MAJOR || - (dpmcp_dev->obj_desc.ver_major == DPMCP_MIN_VER_MAJOR && - dpmcp_dev->obj_desc.ver_minor < DPMCP_MIN_VER_MINOR)) { - dev_err(&dpmcp_dev->dev, - "ERROR: Version %d.%d of DPMCP not supported.\n", - dpmcp_dev->obj_desc.ver_major, - dpmcp_dev->obj_desc.ver_minor); - error = -ENOTSUPP; - goto error_cleanup_resource; - } - - if (WARN_ON(dpmcp_dev->obj_desc.region_count == 0)) - goto error_cleanup_resource; - - mc_portal_phys_addr = dpmcp_dev->regions[0].start; - mc_portal_size = dpmcp_dev->regions[0].end - - dpmcp_dev->regions[0].start + 1; - - if (WARN_ON(mc_portal_size != mc_bus_dev->mc_io->portal_size)) - goto error_cleanup_resource; - - error = fsl_create_mc_io(&mc_bus_dev->dev, - mc_portal_phys_addr, - mc_portal_size, dpmcp_dev, - mc_io_flags, &mc_io); - if (error < 0) - goto error_cleanup_resource; - - *new_mc_io = mc_io; - return 0; - -error_cleanup_resource: - fsl_mc_resource_free(resource); - return error; -} -EXPORT_SYMBOL_GPL(fsl_mc_portal_allocate); - -/** - * fsl_mc_portal_free - Returns an MC portal to the pool of free MC portals - * of a given MC bus - * - * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free - */ -void fsl_mc_portal_free(struct fsl_mc_io *mc_io) -{ - struct fsl_mc_device *dpmcp_dev; - struct fsl_mc_resource *resource; - - /* - * Every mc_io obtained by calling fsl_mc_portal_allocate() is supposed - * to have a DPMCP object associated with. - */ - dpmcp_dev = mc_io->dpmcp_dev; - if (WARN_ON(!dpmcp_dev)) - return; - - resource = dpmcp_dev->resource; - if (WARN_ON(!resource || resource->type != FSL_MC_POOL_DPMCP)) - return; - - if (WARN_ON(resource->data != dpmcp_dev)) - return; - - fsl_destroy_mc_io(mc_io); - fsl_mc_resource_free(resource); -} -EXPORT_SYMBOL_GPL(fsl_mc_portal_free); - -/** - * fsl_mc_portal_reset - Resets the dpmcp object for a given fsl_mc_io object - * - * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free - */ -int fsl_mc_portal_reset(struct fsl_mc_io *mc_io) -{ - int error; - struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; - - if (WARN_ON(!dpmcp_dev)) - return -EINVAL; - - error = dpmcp_reset(mc_io, 0, dpmcp_dev->mc_handle); - if (error < 0) { - dev_err(&dpmcp_dev->dev, "dpmcp_reset() failed: %d\n", error); - return error; - } - - return 0; -} -EXPORT_SYMBOL_GPL(fsl_mc_portal_reset); - -/** * fsl_mc_object_allocate - Allocates a MC object device of the given * pool type from a given MC bus * diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-private.h b/drivers/staging/fsl-mc/bus/fsl-mc-private.h index 1479934..d459c26 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-private.h +++ b/drivers/staging/fsl-mc/bus/fsl-mc-private.h @@ -41,4 +41,12 @@ int __init its_fsl_mc_msi_init(void); void its_fsl_mc_msi_cleanup(void); +int __must_check fsl_create_mc_io(struct device *dev, + phys_addr_t mc_portal_phys_addr, + u32 mc_portal_size, + struct fsl_mc_device *dpmcp_dev, + u32 flags, struct fsl_mc_io **new_mc_io); + +void fsl_destroy_mc_io(struct fsl_mc_io *mc_io); + #endif /* _FSL_MC_PRIVATE_H_ */ diff --git a/drivers/staging/fsl-mc/bus/mc-io.c b/drivers/staging/fsl-mc/bus/mc-io.c new file mode 100644 index 0000000..c5edfc8 --- /dev/null +++ b/drivers/staging/fsl-mc/bus/mc-io.c @@ -0,0 +1,318 @@ +/* Copyright 2013-2016 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the above-listed copyright holders nor the + * names of any contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * 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 HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "../include/mc-bus.h" +#include "../include/mc-sys.h" +#include "fsl-mc-private.h" +#include "dpmcp.h" +#include "dpmcp-cmd.h" + +static int fsl_mc_io_set_dpmcp(struct fsl_mc_io *mc_io, + struct fsl_mc_device *dpmcp_dev) +{ + int error; + + if (WARN_ON(!dpmcp_dev)) + return -EINVAL; + + if (WARN_ON(mc_io->dpmcp_dev)) + return -EINVAL; + + if (WARN_ON(dpmcp_dev->mc_io)) + return -EINVAL; + + error = dpmcp_open(mc_io, + 0, + dpmcp_dev->obj_desc.id, + &dpmcp_dev->mc_handle); + if (error < 0) + return error; + + mc_io->dpmcp_dev = dpmcp_dev; + dpmcp_dev->mc_io = mc_io; + return 0; +} + +static void fsl_mc_io_unset_dpmcp(struct fsl_mc_io *mc_io) +{ + int error; + struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; + + if (WARN_ON(!dpmcp_dev)) + return; + + if (WARN_ON(dpmcp_dev->mc_io != mc_io)) + return; + + error = dpmcp_close(mc_io, + 0, + dpmcp_dev->mc_handle); + if (error < 0) { + dev_err(&dpmcp_dev->dev, "dpmcp_close() failed: %d\n", + error); + } + + mc_io->dpmcp_dev = NULL; + dpmcp_dev->mc_io = NULL; +} + +/** + * 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 + * 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 + * + * Returns '0' on Success; Error code otherwise. + */ +int __must_check fsl_create_mc_io(struct device *dev, + phys_addr_t mc_portal_phys_addr, + u32 mc_portal_size, + struct fsl_mc_device *dpmcp_dev, + u32 flags, struct fsl_mc_io **new_mc_io) +{ + int error; + struct fsl_mc_io *mc_io; + void __iomem *mc_portal_virt_addr; + struct resource *res; + + mc_io = devm_kzalloc(dev, sizeof(*mc_io), GFP_KERNEL); + if (!mc_io) + return -ENOMEM; + + mc_io->dev = dev; + mc_io->flags = flags; + mc_io->portal_phys_addr = mc_portal_phys_addr; + mc_io->portal_size = mc_portal_size; + if (flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL) + spin_lock_init(&mc_io->spinlock); + else + mutex_init(&mc_io->mutex); + + res = devm_request_mem_region(dev, + mc_portal_phys_addr, + mc_portal_size, + "mc_portal"); + if (!res) { + dev_err(dev, + "devm_request_mem_region failed for MC portal %#llx\n", + mc_portal_phys_addr); + return -EBUSY; + } + + mc_portal_virt_addr = devm_ioremap_nocache(dev, + mc_portal_phys_addr, + mc_portal_size); + if (!mc_portal_virt_addr) { + dev_err(dev, + "devm_ioremap_nocache failed for MC portal %#llx\n", + mc_portal_phys_addr); + return -ENXIO; + } + + mc_io->portal_virt_addr = mc_portal_virt_addr; + if (dpmcp_dev) { + error = fsl_mc_io_set_dpmcp(mc_io, dpmcp_dev); + if (error < 0) + goto error_destroy_mc_io; + } + + *new_mc_io = mc_io; + return 0; + +error_destroy_mc_io: + fsl_destroy_mc_io(mc_io); + return error; +} + +/** + * Destroys an MC I/O object + * + * @mc_io: MC I/O object to destroy + */ +void fsl_destroy_mc_io(struct fsl_mc_io *mc_io) +{ + struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; + + if (dpmcp_dev) + fsl_mc_io_unset_dpmcp(mc_io); + + devm_iounmap(mc_io->dev, mc_io->portal_virt_addr); + devm_release_mem_region(mc_io->dev, + mc_io->portal_phys_addr, + mc_io->portal_size); + + mc_io->portal_virt_addr = NULL; + devm_kfree(mc_io->dev, mc_io); +} + +/** + * fsl_mc_portal_allocate - Allocates an MC portal + * + * @mc_dev: MC device for which the MC portal is to be allocated + * @mc_io_flags: Flags for the fsl_mc_io object that wraps the allocated + * MC portal. + * @new_mc_io: Pointer to area where the pointer to the fsl_mc_io object + * that wraps the allocated MC portal is to be returned + * + * This function allocates an MC portal from the device's parent DPRC, + * from the corresponding MC bus' pool of MC portals and wraps + * it in a new fsl_mc_io object. If 'mc_dev' is a DPRC itself, the + * portal is allocated from its own MC bus. + */ +int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, + u16 mc_io_flags, + struct fsl_mc_io **new_mc_io) +{ + struct fsl_mc_device *mc_bus_dev; + struct fsl_mc_bus *mc_bus; + phys_addr_t mc_portal_phys_addr; + size_t mc_portal_size; + struct fsl_mc_device *dpmcp_dev; + int error = -EINVAL; + struct fsl_mc_resource *resource = NULL; + struct fsl_mc_io *mc_io = NULL; + + if (mc_dev->flags & FSL_MC_IS_DPRC) { + mc_bus_dev = mc_dev; + } else { + if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent))) + return error; + + mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); + } + + mc_bus = to_fsl_mc_bus(mc_bus_dev); + *new_mc_io = NULL; + error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_DPMCP, &resource); + if (error < 0) + return error; + + error = -EINVAL; + dpmcp_dev = resource->data; + if (WARN_ON(!dpmcp_dev)) + goto error_cleanup_resource; + + if (dpmcp_dev->obj_desc.ver_major < DPMCP_MIN_VER_MAJOR || + (dpmcp_dev->obj_desc.ver_major == DPMCP_MIN_VER_MAJOR && + dpmcp_dev->obj_desc.ver_minor < DPMCP_MIN_VER_MINOR)) { + dev_err(&dpmcp_dev->dev, + "ERROR: Version %d.%d of DPMCP not supported.\n", + dpmcp_dev->obj_desc.ver_major, + dpmcp_dev->obj_desc.ver_minor); + error = -ENOTSUPP; + goto error_cleanup_resource; + } + + if (WARN_ON(dpmcp_dev->obj_desc.region_count == 0)) + goto error_cleanup_resource; + + mc_portal_phys_addr = dpmcp_dev->regions[0].start; + mc_portal_size = dpmcp_dev->regions[0].end - + dpmcp_dev->regions[0].start + 1; + + if (WARN_ON(mc_portal_size != mc_bus_dev->mc_io->portal_size)) + goto error_cleanup_resource; + + error = fsl_create_mc_io(&mc_bus_dev->dev, + mc_portal_phys_addr, + mc_portal_size, dpmcp_dev, + mc_io_flags, &mc_io); + if (error < 0) + goto error_cleanup_resource; + + *new_mc_io = mc_io; + return 0; + +error_cleanup_resource: + fsl_mc_resource_free(resource); + return error; +} +EXPORT_SYMBOL_GPL(fsl_mc_portal_allocate); + +/** + * fsl_mc_portal_free - Returns an MC portal to the pool of free MC portals + * of a given MC bus + * + * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free + */ +void fsl_mc_portal_free(struct fsl_mc_io *mc_io) +{ + struct fsl_mc_device *dpmcp_dev; + struct fsl_mc_resource *resource; + + /* + * Every mc_io obtained by calling fsl_mc_portal_allocate() is supposed + * to have a DPMCP object associated with. + */ + dpmcp_dev = mc_io->dpmcp_dev; + if (WARN_ON(!dpmcp_dev)) + return; + + resource = dpmcp_dev->resource; + if (WARN_ON(!resource || resource->type != FSL_MC_POOL_DPMCP)) + return; + + if (WARN_ON(resource->data != dpmcp_dev)) + return; + + fsl_destroy_mc_io(mc_io); + fsl_mc_resource_free(resource); +} +EXPORT_SYMBOL_GPL(fsl_mc_portal_free); + +/** + * fsl_mc_portal_reset - Resets the dpmcp object for a given fsl_mc_io object + * + * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free + */ +int fsl_mc_portal_reset(struct fsl_mc_io *mc_io) +{ + int error; + struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; + + if (WARN_ON(!dpmcp_dev)) + return -EINVAL; + + error = dpmcp_reset(mc_io, 0, dpmcp_dev->mc_handle); + if (error < 0) { + dev_err(&dpmcp_dev->dev, "dpmcp_reset() failed: %d\n", error); + return error; + } + + return 0; +} +EXPORT_SYMBOL_GPL(fsl_mc_portal_reset); diff --git a/drivers/staging/fsl-mc/bus/mc-sys.c b/drivers/staging/fsl-mc/bus/mc-sys.c index 0c185ab..23e82e4a 100644 --- a/drivers/staging/fsl-mc/bus/mc-sys.c +++ b/drivers/staging/fsl-mc/bus/mc-sys.c @@ -68,153 +68,6 @@ static u16 mc_cmd_hdr_read_cmdid(struct mc_command *cmd) return (cmd_id & MC_CMD_HDR_CMDID_MASK) >> MC_CMD_HDR_CMDID_SHIFT; } -/** - * 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 - * 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 - * - * Returns '0' on Success; Error code otherwise. - */ -int __must_check fsl_create_mc_io(struct device *dev, - phys_addr_t mc_portal_phys_addr, - u32 mc_portal_size, - struct fsl_mc_device *dpmcp_dev, - u32 flags, struct fsl_mc_io **new_mc_io) -{ - int error; - struct fsl_mc_io *mc_io; - void __iomem *mc_portal_virt_addr; - struct resource *res; - - mc_io = devm_kzalloc(dev, sizeof(*mc_io), GFP_KERNEL); - if (!mc_io) - return -ENOMEM; - - mc_io->dev = dev; - mc_io->flags = flags; - mc_io->portal_phys_addr = mc_portal_phys_addr; - mc_io->portal_size = mc_portal_size; - if (flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL) - spin_lock_init(&mc_io->spinlock); - else - mutex_init(&mc_io->mutex); - - res = devm_request_mem_region(dev, - mc_portal_phys_addr, - mc_portal_size, - "mc_portal"); - if (!res) { - dev_err(dev, - "devm_request_mem_region failed for MC portal %#llx\n", - mc_portal_phys_addr); - return -EBUSY; - } - - mc_portal_virt_addr = devm_ioremap_nocache(dev, - mc_portal_phys_addr, - mc_portal_size); - if (!mc_portal_virt_addr) { - dev_err(dev, - "devm_ioremap_nocache failed for MC portal %#llx\n", - mc_portal_phys_addr); - return -ENXIO; - } - - mc_io->portal_virt_addr = mc_portal_virt_addr; - if (dpmcp_dev) { - error = fsl_mc_io_set_dpmcp(mc_io, dpmcp_dev); - if (error < 0) - goto error_destroy_mc_io; - } - - *new_mc_io = mc_io; - return 0; - -error_destroy_mc_io: - fsl_destroy_mc_io(mc_io); - return error; -} -EXPORT_SYMBOL_GPL(fsl_create_mc_io); - -/** - * Destroys an MC I/O object - * - * @mc_io: MC I/O object to destroy - */ -void fsl_destroy_mc_io(struct fsl_mc_io *mc_io) -{ - struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; - - if (dpmcp_dev) - fsl_mc_io_unset_dpmcp(mc_io); - - devm_iounmap(mc_io->dev, mc_io->portal_virt_addr); - devm_release_mem_region(mc_io->dev, - mc_io->portal_phys_addr, - mc_io->portal_size); - - mc_io->portal_virt_addr = NULL; - devm_kfree(mc_io->dev, mc_io); -} -EXPORT_SYMBOL_GPL(fsl_destroy_mc_io); - -int fsl_mc_io_set_dpmcp(struct fsl_mc_io *mc_io, - struct fsl_mc_device *dpmcp_dev) -{ - int error; - - if (WARN_ON(!dpmcp_dev)) - return -EINVAL; - - if (WARN_ON(mc_io->dpmcp_dev)) - return -EINVAL; - - if (WARN_ON(dpmcp_dev->mc_io)) - return -EINVAL; - - error = dpmcp_open(mc_io, - 0, - dpmcp_dev->obj_desc.id, - &dpmcp_dev->mc_handle); - if (error < 0) - return error; - - mc_io->dpmcp_dev = dpmcp_dev; - dpmcp_dev->mc_io = mc_io; - return 0; -} -EXPORT_SYMBOL_GPL(fsl_mc_io_set_dpmcp); - -void fsl_mc_io_unset_dpmcp(struct fsl_mc_io *mc_io) -{ - int error; - struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; - - if (WARN_ON(!dpmcp_dev)) - return; - - if (WARN_ON(dpmcp_dev->mc_io != mc_io)) - return; - - error = dpmcp_close(mc_io, - 0, - dpmcp_dev->mc_handle); - if (error < 0) { - dev_err(&dpmcp_dev->dev, "dpmcp_close() failed: %d\n", - error); - } - - mc_io->dpmcp_dev = NULL; - dpmcp_dev->mc_io = NULL; -} -EXPORT_SYMBOL_GPL(fsl_mc_io_unset_dpmcp); - static int mc_status_to_error(enum mc_cmd_status status) { static const int mc_status_to_error_map[] = { diff --git a/drivers/staging/fsl-mc/include/mc-sys.h b/drivers/staging/fsl-mc/include/mc-sys.h index c5038cc..7a73cf6 100644 --- a/drivers/staging/fsl-mc/include/mc-sys.h +++ b/drivers/staging/fsl-mc/include/mc-sys.h @@ -95,19 +95,6 @@ struct fsl_mc_io { }; }; -int __must_check fsl_create_mc_io(struct device *dev, - phys_addr_t mc_portal_phys_addr, - u32 mc_portal_size, - struct fsl_mc_device *dpmcp_dev, - u32 flags, struct fsl_mc_io **new_mc_io); - -void fsl_destroy_mc_io(struct fsl_mc_io *mc_io); - -int fsl_mc_io_set_dpmcp(struct fsl_mc_io *mc_io, - struct fsl_mc_device *dpmcp_dev); - -void fsl_mc_io_unset_dpmcp(struct fsl_mc_io *mc_io); - int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd); #endif /* _FSL_MC_SYS_H */ -- cgit v0.10.2 From 5143ecf6db0a97b5d5028c0e9ac3a430b51ebb13 Mon Sep 17 00:00:00 2001 From: Stuart Yoder <stuart.yoder@nxp.com> Date: Tue, 23 Aug 2016 17:14:18 -0500 Subject: staging: fsl-mc: explicitly include files where they are needed Instead of relying on mc-sys.h to include misc system headers, have the source files that need them explicitly do it themselves. Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c index fda6a98..9023df3 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c @@ -18,6 +18,7 @@ #include <linux/limits.h> #include <linux/bitops.h> #include <linux/msi.h> +#include <linux/dma-mapping.h> #include "../include/dpmng.h" #include "../include/mc-sys.h" #include "fsl-mc-private.h" diff --git a/drivers/staging/fsl-mc/bus/mc-io.c b/drivers/staging/fsl-mc/bus/mc-io.c index c5edfc8..fd032c1 100644 --- a/drivers/staging/fsl-mc/bus/mc-io.c +++ b/drivers/staging/fsl-mc/bus/mc-io.c @@ -32,6 +32,8 @@ #include "../include/mc-bus.h" #include "../include/mc-sys.h" +#include <linux/io.h> + #include "fsl-mc-private.h" #include "dpmcp.h" #include "dpmcp-cmd.h" diff --git a/drivers/staging/fsl-mc/bus/mc-sys.c b/drivers/staging/fsl-mc/bus/mc-sys.c index 23e82e4a..461abaa 100644 --- a/drivers/staging/fsl-mc/bus/mc-sys.c +++ b/drivers/staging/fsl-mc/bus/mc-sys.c @@ -39,6 +39,8 @@ #include <linux/slab.h> #include <linux/ioport.h> #include <linux/device.h> +#include <linux/io.h> + #include "dpmcp.h" /** diff --git a/drivers/staging/fsl-mc/include/mc-sys.h b/drivers/staging/fsl-mc/include/mc-sys.h index 7a73cf6..89ad0cf 100644 --- a/drivers/staging/fsl-mc/include/mc-sys.h +++ b/drivers/staging/fsl-mc/include/mc-sys.h @@ -37,8 +37,6 @@ #include <linux/types.h> #include <linux/errno.h> -#include <linux/io.h> -#include <linux/dma-mapping.h> #include <linux/mutex.h> #include <linux/spinlock.h> -- cgit v0.10.2 From d4e75132bde743780084690b34da875b4402bd63 Mon Sep 17 00:00:00 2001 From: Stuart Yoder <stuart.yoder@nxp.com> Date: Tue, 23 Aug 2016 17:14:23 -0500 Subject: staging: fsl-mc: make order of includes consistent There are 3 kinds of headers included in the bus driver components-- misc linux/include files, public bus driver includes, and includes private to the bus driver. Cleanup the order and formatting of includes in the bus driver to be consistent: #include <linux/include/[file].h> #include ../include/[file].h // public bus driver includes (eventually // destined for: linux/include/fsl) [blank line] #include "[file].h" // private bus driver includes Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fsl-mc/bus/dpmcp.c b/drivers/staging/fsl-mc/bus/dpmcp.c index 0644017..bd63baa 100644 --- a/drivers/staging/fsl-mc/bus/dpmcp.c +++ b/drivers/staging/fsl-mc/bus/dpmcp.c @@ -31,6 +31,7 @@ */ #include "../include/mc-sys.h" #include "../include/mc-cmd.h" + #include "dpmcp.h" #include "dpmcp-cmd.h" diff --git a/drivers/staging/fsl-mc/bus/dpmng.c b/drivers/staging/fsl-mc/bus/dpmng.c index 660bbe7..669f604 100644 --- a/drivers/staging/fsl-mc/bus/dpmng.c +++ b/drivers/staging/fsl-mc/bus/dpmng.c @@ -32,6 +32,7 @@ #include "../include/mc-sys.h" #include "../include/mc-cmd.h" #include "../include/dpmng.h" + #include "dpmng-cmd.h" /** diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c index 5e34720..c5ee463 100644 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c +++ b/drivers/staging/fsl-mc/bus/dprc-driver.c @@ -9,12 +9,13 @@ * warranty of any kind, whether express or implied. */ -#include "../include/mc-bus.h" -#include "../include/mc-sys.h" #include <linux/module.h> #include <linux/slab.h> #include <linux/interrupt.h> #include <linux/msi.h> +#include "../include/mc-bus.h" +#include "../include/mc-sys.h" + #include "dprc-cmd.h" #include "fsl-mc-private.h" diff --git a/drivers/staging/fsl-mc/bus/dprc.c b/drivers/staging/fsl-mc/bus/dprc.c index c260549..ac4ed35 100644 --- a/drivers/staging/fsl-mc/bus/dprc.c +++ b/drivers/staging/fsl-mc/bus/dprc.c @@ -32,6 +32,7 @@ #include "../include/mc-sys.h" #include "../include/mc-cmd.h" #include "../include/dprc.h" + #include "dprc-cmd.h" /** diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c index edcb5cc..2004fa7 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c @@ -8,13 +8,14 @@ * warranty of any kind, whether express or implied. */ +#include <linux/module.h> +#include <linux/msi.h> #include "../include/mc-bus.h" #include "../include/mc-sys.h" -#include <linux/module.h> #include "../include/dpbp-cmd.h" #include "../include/dpcon-cmd.h" + #include "fsl-mc-private.h" -#include <linux/msi.h> #define FSL_MC_IS_ALLOCATABLE(_obj_type) \ (strcmp(_obj_type, "dpbp") == 0 || \ diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c index 9023df3..03ebab8 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c @@ -9,7 +9,6 @@ * warranty of any kind, whether express or implied. */ -#include "../include/mc-bus.h" #include <linux/module.h> #include <linux/of_device.h> #include <linux/of_address.h> @@ -19,8 +18,10 @@ #include <linux/bitops.h> #include <linux/msi.h> #include <linux/dma-mapping.h> +#include "../include/mc-bus.h" #include "../include/dpmng.h" #include "../include/mc-sys.h" + #include "fsl-mc-private.h" #include "dprc-cmd.h" diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-msi.c b/drivers/staging/fsl-mc/bus/fsl-mc-msi.c index 7c20f60..cc19092 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-msi.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-msi.c @@ -9,7 +9,6 @@ * warranty of any kind, whether express or implied. */ -#include "../include/mc-bus.h" #include <linux/of_device.h> #include <linux/of_address.h> #include <linux/irqchip/arm-gic-v3.h> @@ -17,6 +16,7 @@ #include <linux/irq.h> #include <linux/irqdomain.h> #include <linux/msi.h> +#include "../include/mc-bus.h" /* * Generate a unique ID identifying the interrupt (only used within the MSI diff --git a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c index 2586328..7a6ac64 100644 --- a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c +++ b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c @@ -9,7 +9,6 @@ * warranty of any kind, whether express or implied. */ -#include "../include/mc-bus.h" #include <linux/of_device.h> #include <linux/of_address.h> #include <linux/irqchip/arm-gic-v3.h> @@ -17,6 +16,7 @@ #include <linux/msi.h> #include <linux/of.h> #include <linux/of_irq.h> +#include "../include/mc-bus.h" static struct irq_chip its_msi_irq_chip = { .name = "fsl-mc-bus-msi", diff --git a/drivers/staging/fsl-mc/bus/mc-io.c b/drivers/staging/fsl-mc/bus/mc-io.c index fd032c1..798c965 100644 --- a/drivers/staging/fsl-mc/bus/mc-io.c +++ b/drivers/staging/fsl-mc/bus/mc-io.c @@ -30,9 +30,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include <linux/io.h> #include "../include/mc-bus.h" #include "../include/mc-sys.h" -#include <linux/io.h> #include "fsl-mc-private.h" #include "dpmcp.h" diff --git a/drivers/staging/fsl-mc/bus/mc-sys.c b/drivers/staging/fsl-mc/bus/mc-sys.c index 461abaa..285917c 100644 --- a/drivers/staging/fsl-mc/bus/mc-sys.c +++ b/drivers/staging/fsl-mc/bus/mc-sys.c @@ -32,14 +32,14 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "../include/mc-sys.h" -#include "../include/mc-cmd.h" -#include "../include/mc.h" #include <linux/delay.h> #include <linux/slab.h> #include <linux/ioport.h> #include <linux/device.h> #include <linux/io.h> +#include "../include/mc-sys.h" +#include "../include/mc-cmd.h" +#include "../include/mc.h" #include "dpmcp.h" -- cgit v0.10.2 From 695b4adc326cc00808a96b2e8c3628de533a643a Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Fri, 26 Aug 2016 22:59:58 -0400 Subject: staging: fsl-mc: dpmng-cmd: Fix checkpatch warning Fix checkpatch.pl warning: Block comments use * on subsequent lines Fix Commenting Style Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fsl-mc/bus/dpmng-cmd.h b/drivers/staging/fsl-mc/bus/dpmng-cmd.h index 779bf9c..a7b77d5 100644 --- a/drivers/staging/fsl-mc/bus/dpmng-cmd.h +++ b/drivers/staging/fsl-mc/bus/dpmng-cmd.h @@ -1,4 +1,5 @@ -/* Copyright 2013-2016 Freescale Semiconductor Inc. +/* + * Copyright 2013-2016 Freescale Semiconductor Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -30,12 +31,12 @@ * POSSIBILITY OF SUCH DAMAGE. */ -/*************************************************************************//* - dpmng-cmd.h - - defines portal commands - - *//**************************************************************************/ +/* + * dpmng-cmd.h + * + * defines portal commands + * + */ #ifndef __FSL_DPMNG_CMD_H #define __FSL_DPMNG_CMD_H -- cgit v0.10.2 From be1edb857ea48e7b7f5dd1ff278e79d4152def9e Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Fri, 26 Aug 2016 22:59:59 -0400 Subject: staging: fsl-mc: dprc-cmd: Fix checkpatch warning Fix checkpatch.pl warning: Block comments use * on subsequent lines Fix Commenting Style Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fsl-mc/bus/dprc-cmd.h b/drivers/staging/fsl-mc/bus/dprc-cmd.h index bb127f4..009d656 100644 --- a/drivers/staging/fsl-mc/bus/dprc-cmd.h +++ b/drivers/staging/fsl-mc/bus/dprc-cmd.h @@ -1,4 +1,5 @@ -/* Copyright 2013-2016 Freescale Semiconductor Inc. +/* + * Copyright 2013-2016 Freescale Semiconductor Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -30,12 +31,12 @@ * POSSIBILITY OF SUCH DAMAGE. */ -/*************************************************************************//* - dprc-cmd.h - - defines dprc portal commands - - *//**************************************************************************/ +/* + * dprc-cmd.h + * + * defines dprc portal commands + * + */ #ifndef _FSL_DPRC_CMD_H #define _FSL_DPRC_CMD_H -- cgit v0.10.2 From a71a6d96a4d663c4e0a28128bba1b2febf0fe10c Mon Sep 17 00:00:00 2001 From: Wei Yongjun <weiyongjun1@huawei.com> Date: Sun, 28 Aug 2016 16:19:29 +0000 Subject: staging: fsl-mc: convert to use ATTRIBUTE_GROUPS macro Use ATTRIBUTE_GROUPS macro to reduce the number of lines of code. Generated by Coccinelle semantic patch. Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c index 03ebab8..3d687b5 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c @@ -137,14 +137,8 @@ static struct attribute *fsl_mc_dev_attrs[] = { NULL, }; -static const struct attribute_group fsl_mc_dev_group = { - .attrs = fsl_mc_dev_attrs, -}; +ATTRIBUTE_GROUPS(fsl_mc_dev); -static const struct attribute_group *fsl_mc_dev_groups[] = { - &fsl_mc_dev_group, - NULL, -}; struct bus_type fsl_mc_bus_type = { .name = "fsl-mc", -- cgit v0.10.2 From f0fde4f867aadea8169fe806cffdb355b196853b Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:19:21 +0700 Subject: staging: r8188eu: remove rtw_ies_remove_ie function Driver does not use this function. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c index 0b0d78f..b8ba90a 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c @@ -280,53 +280,6 @@ u8 *rtw_get_ie_ex(u8 *in_ie, uint in_len, u8 eid, u8 *oui, u8 oui_len, u8 *ie, u return target_ie; } -/** - * rtw_ies_remove_ie - Find matching IEs and remove - * @ies: Address of IEs to search - * @ies_len: Pointer of length of ies, will update to new length - * @offset: The offset to start scarch - * @eid: Element ID to match - * @oui: OUI to match - * @oui_len: OUI length - * - * Returns: _SUCCESS: ies is updated, _FAIL: not updated - */ -int rtw_ies_remove_ie(u8 *ies, uint *ies_len, uint offset, u8 eid, u8 *oui, u8 oui_len) -{ - int ret = _FAIL; - u8 *target_ie; - u32 target_ielen; - u8 *start; - uint search_len; - - if (!ies || !ies_len || *ies_len <= offset) - goto exit; - - start = ies + offset; - search_len = *ies_len - offset; - - 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); - *ies_len = *ies_len - target_ielen; - ret = _SUCCESS; - - start = target_ie; - search_len = remain_len; - } else { - break; - } - } -exit: - return ret; -} - void rtw_set_supported_rate(u8 *SupportedRates, uint mode) { diff --git a/drivers/staging/rtl8188eu/include/ieee80211.h b/drivers/staging/rtl8188eu/include/ieee80211.h index d8284c8..a62077b 100644 --- a/drivers/staging/rtl8188eu/include/ieee80211.h +++ b/drivers/staging/rtl8188eu/include/ieee80211.h @@ -1108,8 +1108,6 @@ u8 *rtw_set_ie_mesh_ch_switch_parm(u8 *buf, u32 *buf_len, u8 ttl, u8 *rtw_get_ie(u8 *pbuf, int index, int *len, int limit); u8 *rtw_get_ie_ex(u8 *in_ie, uint in_len, u8 eid, u8 *oui, u8 oui_len, u8 *ie, uint *ielen); -int rtw_ies_remove_ie(u8 *ies, uint *ies_len, uint offset, - u8 eid, u8 *oui, u8 oui_len); void rtw_set_supported_rate(u8 *SupportedRates, uint mode); -- cgit v0.10.2 From d7335dc9ababd8c18a4debc9c83764719d9e499f Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:19:31 +0700 Subject: staging: r8188eu: remove rtw_get_ie_ex function Driver does not use this function. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c index b8ba90a..a37d847 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c @@ -236,50 +236,6 @@ u8 *rtw_get_ie(u8 *pbuf, int index, int *len, int limit) return NULL; } -/** - * rtw_get_ie_ex - Search specific IE from a series of IEs - * @in_ie: Address of IEs to search - * @in_len: Length limit from in_ie - * @eid: Element ID to match - * @oui: OUI to match - * @oui_len: OUI length - * @ie: If not NULL and the specific IE is found, the IE will be copied to the buf starting from the specific IE - * @ielen: If not NULL and the specific IE is found, will set to the length of the entire IE - * - * Returns: The address of the specific IE found, or NULL - */ -u8 *rtw_get_ie_ex(u8 *in_ie, uint in_len, u8 eid, u8 *oui, u8 oui_len, u8 *ie, uint *ielen) -{ - uint cnt; - u8 *target_ie = NULL; - - - if (ielen) - *ielen = 0; - - if (!in_ie || in_len <= 0) - return target_ie; - - cnt = 0; - - while (cnt < in_len) { - if (eid == in_ie[cnt] && (!oui || !memcmp(&in_ie[cnt + 2], oui, oui_len))) { - target_ie = &in_ie[cnt]; - - if (ie) - memcpy(ie, &in_ie[cnt], in_ie[cnt + 1] + 2); - - if (ielen) - *ielen = in_ie[cnt + 1] + 2; - - break; - } else { - cnt += in_ie[cnt + 1] + 2; /* goto next */ - } - } - return target_ie; -} - void rtw_set_supported_rate(u8 *SupportedRates, uint mode) { diff --git a/drivers/staging/rtl8188eu/include/ieee80211.h b/drivers/staging/rtl8188eu/include/ieee80211.h index a62077b..8afef17 100644 --- a/drivers/staging/rtl8188eu/include/ieee80211.h +++ b/drivers/staging/rtl8188eu/include/ieee80211.h @@ -1106,8 +1106,6 @@ u8 *rtw_set_ie_mesh_ch_switch_parm(u8 *buf, u32 *buf_len, u8 ttl, u8 flags, u16 reason, u16 precedence); u8 *rtw_get_ie(u8 *pbuf, int index, int *len, int limit); -u8 *rtw_get_ie_ex(u8 *in_ie, uint in_len, u8 eid, u8 *oui, - u8 oui_len, u8 *ie, uint *ielen); void rtw_set_supported_rate(u8 *SupportedRates, uint mode); -- cgit v0.10.2 From fd0a793a0bec21ba12323e1b05a9bb24bf60e418 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:19:39 +0700 Subject: staging: r8188eu: remove rtw_ap_inform_ch_switch function Driver does not use this function. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c index a575535..bbb1aa7 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ap.c +++ b/drivers/staging/rtl8188eu/core/rtw_ap.c @@ -1710,40 +1710,6 @@ u8 ap_free_sta(struct adapter *padapter, struct sta_info *psta, return beacon_updated; } -int rtw_ap_inform_ch_switch(struct adapter *padapter, u8 new_ch, u8 ch_offset) -{ - struct list_head *phead, *plist; - struct sta_info *psta = NULL; - 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}; - - if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) - return 0; - - DBG_88E(FUNC_NDEV_FMT" with ch:%u, offset:%u\n", - FUNC_NDEV_ARG(padapter->pnetdev), new_ch, ch_offset); - - spin_lock_bh(&pstapriv->asoc_list_lock); - phead = &pstapriv->asoc_list; - plist = phead->next; - - /* for each sta in asoc_queue */ - while (phead != plist) { - psta = container_of(plist, struct sta_info, asoc_list); - plist = plist->next; - - issue_action_spct_ch_switch(padapter, psta->hwaddr, new_ch, ch_offset); - psta->expire_to = min_t(unsigned int, pstapriv->expire_to * 2, 5); - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - issue_action_spct_ch_switch(padapter, bc_addr, new_ch, ch_offset); - - return 0; -} - int rtw_sta_flush(struct adapter *padapter) { struct list_head *phead, *plist; diff --git a/drivers/staging/rtl8188eu/include/rtw_ap.h b/drivers/staging/rtl8188eu/include/rtw_ap.h index b820684..e8dd6d4 100644 --- a/drivers/staging/rtl8188eu/include/rtw_ap.h +++ b/drivers/staging/rtl8188eu/include/rtw_ap.h @@ -50,7 +50,6 @@ void ap_sta_info_defer_update(struct adapter *padapter, struct sta_info *psta); u8 ap_free_sta(struct adapter *padapter, struct sta_info *psta, bool active, u16 reason); int rtw_sta_flush(struct adapter *padapter); -int rtw_ap_inform_ch_switch(struct adapter *padapter, u8 new_ch, u8 ch_offset); void start_ap_mode(struct adapter *padapter); void stop_ap_mode(struct adapter *padapter); #endif /* end of CONFIG_88EU_AP_MODE */ -- cgit v0.10.2 From f92dcecacecf0fd1ffb436182089d2bd56baa1d0 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:19:47 +0700 Subject: staging: r8188eu: remove secondary_ch_offset_to_hal_ch_offset function Driver does not use this function. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c index a37d847..641c874 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c @@ -166,18 +166,6 @@ inline u8 *rtw_set_ie_ch_switch(u8 *buf, u32 *buf_len, u8 ch_switch_mode, return rtw_set_ie(buf, WLAN_EID_CHANNEL_SWITCH, 3, ie_data, buf_len); } -inline u8 secondary_ch_offset_to_hal_ch_offset(u8 ch_offset) -{ - if (ch_offset == SCN) - return HAL_PRIME_CHNL_OFFSET_DONT_CARE; - else if (ch_offset == SCA) - return HAL_PRIME_CHNL_OFFSET_UPPER; - else if (ch_offset == SCB) - return HAL_PRIME_CHNL_OFFSET_LOWER; - - return HAL_PRIME_CHNL_OFFSET_DONT_CARE; -} - inline u8 hal_ch_offset_to_secondary_ch_offset(u8 ch_offset) { if (ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) diff --git a/drivers/staging/rtl8188eu/include/ieee80211.h b/drivers/staging/rtl8188eu/include/ieee80211.h index 8afef17..976bb63 100644 --- a/drivers/staging/rtl8188eu/include/ieee80211.h +++ b/drivers/staging/rtl8188eu/include/ieee80211.h @@ -1096,7 +1096,6 @@ enum secondary_ch_offset { SCA = 1, /* secondary channel above */ SCB = 3, /* secondary channel below */ }; -u8 secondary_ch_offset_to_hal_ch_offset(u8 ch_offset); u8 hal_ch_offset_to_secondary_ch_offset(u8 ch_offset); u8 *rtw_set_ie_ch_switch(u8 *buf, u32 *buf_len, u8 ch_switch_mode, u8 new_ch, u8 ch_switch_cnt); -- cgit v0.10.2 From d02463e06ee54d7fed848cbada1573e1201c1492 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:19:57 +0700 Subject: staging: r8188eu: remove issue_action_spct_ch_switch function Driver does not use this function. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 7f32b39..40e0b60 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -1559,66 +1559,6 @@ exit: return ret; } -void issue_action_spct_ch_switch(struct adapter *padapter, u8 *ra, u8 new_ch, u8 ch_offset) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; - __le16 *fctrl; - struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - - - DBG_88E(FUNC_NDEV_FMT" ra =%pM, ch:%u, offset:%u\n", - FUNC_NDEV_ARG(padapter->pnetdev), ra, new_ch, ch_offset); - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (pmgntframe == NULL) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; - - fctrl = &(pwlanhdr->frame_ctl); - *(fctrl) = 0; - - memcpy(pwlanhdr->addr1, ra, ETH_ALEN); /* RA */ - memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); /* TA */ - memcpy(pwlanhdr->addr3, ra, ETH_ALEN); /* DA = RA */ - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - SetFrameSubType(pframe, WIFI_ACTION); - - pframe += sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); - - /* category, action */ - { - u8 category, action; - category = RTW_WLAN_CATEGORY_SPECTRUM_MGMT; - action = RTW_WLAN_ACTION_SPCT_CHL_SWITCH; - - pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen)); - } - - pframe = rtw_set_ie_ch_switch(pframe, &(pattrib->pktlen), 0, new_ch, 0); - pframe = rtw_set_ie_secondary_ch_offset(pframe, &(pattrib->pktlen), - hal_ch_offset_to_secondary_ch_offset(ch_offset)); - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe(padapter, pmgntframe); -} - static void issue_action_BA(struct adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short status) { diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h index 27382ff..9c2447e 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h @@ -562,8 +562,6 @@ int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int try_cnt, int wait_ms); int issue_deauth(struct adapter *padapter, unsigned char *da, unsigned short reason); -void issue_action_spct_ch_switch(struct adapter *padapter, u8 *ra, u8 new_ch, - u8 ch_offset); unsigned int send_delba(struct adapter *padapter, u8 initiator, u8 *addr); unsigned int send_beacon(struct adapter *padapter); -- cgit v0.10.2 From d5b80f94575737aaa7d8df80f575bc0f09fa2ff3 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:20:13 +0700 Subject: staging: r8188eu: remove hal_ch_offset_to_secondary_ch_offset function Driver does not use this function. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c index 641c874..557832f8 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c @@ -166,18 +166,6 @@ inline u8 *rtw_set_ie_ch_switch(u8 *buf, u32 *buf_len, u8 ch_switch_mode, return rtw_set_ie(buf, WLAN_EID_CHANNEL_SWITCH, 3, ie_data, buf_len); } -inline u8 hal_ch_offset_to_secondary_ch_offset(u8 ch_offset) -{ - if (ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) - return SCN; - else if (ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER) - return SCB; - else if (ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER) - return SCA; - - return SCN; -} - inline u8 *rtw_set_ie_secondary_ch_offset(u8 *buf, u32 *buf_len, u8 secondary_ch_offset) { return rtw_set_ie(buf, WLAN_EID_SECONDARY_CHANNEL_OFFSET, 1, &secondary_ch_offset, buf_len); diff --git a/drivers/staging/rtl8188eu/include/ieee80211.h b/drivers/staging/rtl8188eu/include/ieee80211.h index 976bb63..ba634df 100644 --- a/drivers/staging/rtl8188eu/include/ieee80211.h +++ b/drivers/staging/rtl8188eu/include/ieee80211.h @@ -1096,7 +1096,6 @@ enum secondary_ch_offset { SCA = 1, /* secondary channel above */ SCB = 3, /* secondary channel below */ }; -u8 hal_ch_offset_to_secondary_ch_offset(u8 ch_offset); u8 *rtw_set_ie_ch_switch(u8 *buf, u32 *buf_len, u8 ch_switch_mode, u8 new_ch, u8 ch_switch_cnt); u8 *rtw_set_ie_secondary_ch_offset(u8 *buf, u32 *buf_len, -- cgit v0.10.2 From b02b573fcf4d27b98f2e867b0f9bdbd415b2e508 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:20:22 +0700 Subject: staging: r8188eu: remove rtw_set_ie_secondary_ch_offset function Driver does not use this function. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c index 557832f8..13080d1 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c @@ -166,11 +166,6 @@ inline u8 *rtw_set_ie_ch_switch(u8 *buf, u32 *buf_len, u8 ch_switch_mode, return rtw_set_ie(buf, WLAN_EID_CHANNEL_SWITCH, 3, ie_data, buf_len); } -inline u8 *rtw_set_ie_secondary_ch_offset(u8 *buf, u32 *buf_len, u8 secondary_ch_offset) -{ - return rtw_set_ie(buf, WLAN_EID_SECONDARY_CHANNEL_OFFSET, 1, &secondary_ch_offset, buf_len); -} - inline u8 *rtw_set_ie_mesh_ch_switch_parm(u8 *buf, u32 *buf_len, u8 ttl, u8 flags, u16 reason, u16 precedence) { diff --git a/drivers/staging/rtl8188eu/include/ieee80211.h b/drivers/staging/rtl8188eu/include/ieee80211.h index ba634df..d957caa 100644 --- a/drivers/staging/rtl8188eu/include/ieee80211.h +++ b/drivers/staging/rtl8188eu/include/ieee80211.h @@ -1098,8 +1098,6 @@ enum secondary_ch_offset { }; u8 *rtw_set_ie_ch_switch(u8 *buf, u32 *buf_len, u8 ch_switch_mode, u8 new_ch, u8 ch_switch_cnt); -u8 *rtw_set_ie_secondary_ch_offset(u8 *buf, u32 *buf_len, - u8 secondary_ch_offset); u8 *rtw_set_ie_mesh_ch_switch_parm(u8 *buf, u32 *buf_len, u8 ttl, u8 flags, u16 reason, u16 precedence); -- cgit v0.10.2 From 798d8c2a8c73485adf0d194dabcbd48c52a2c808 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:20:29 +0700 Subject: staging: r8188eu: remove rtw_set_ie_mesh_ch_switch_parm function Driver does not use this function. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c index 13080d1..25226b2 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c @@ -166,19 +166,6 @@ inline u8 *rtw_set_ie_ch_switch(u8 *buf, u32 *buf_len, u8 ch_switch_mode, return rtw_set_ie(buf, WLAN_EID_CHANNEL_SWITCH, 3, ie_data, buf_len); } -inline u8 *rtw_set_ie_mesh_ch_switch_parm(u8 *buf, u32 *buf_len, u8 ttl, - u8 flags, u16 reason, u16 precedence) -{ - u8 ie_data[6]; - - ie_data[0] = ttl; - ie_data[1] = flags; - *(u16 *)(ie_data + 2) = cpu_to_le16(reason); - *(u16 *)(ie_data + 4) = cpu_to_le16(precedence); - - return rtw_set_ie(buf, 0x118, 6, ie_data, buf_len); -} - /*---------------------------------------------------------------------------- index: the information element id index, limit is the limit for search -----------------------------------------------------------------------------*/ diff --git a/drivers/staging/rtl8188eu/include/ieee80211.h b/drivers/staging/rtl8188eu/include/ieee80211.h index d957caa..cd0f9b3 100644 --- a/drivers/staging/rtl8188eu/include/ieee80211.h +++ b/drivers/staging/rtl8188eu/include/ieee80211.h @@ -1098,8 +1098,6 @@ enum secondary_ch_offset { }; u8 *rtw_set_ie_ch_switch(u8 *buf, u32 *buf_len, u8 ch_switch_mode, u8 new_ch, u8 ch_switch_cnt); -u8 *rtw_set_ie_mesh_ch_switch_parm(u8 *buf, u32 *buf_len, u8 ttl, - u8 flags, u16 reason, u16 precedence); u8 *rtw_get_ie(u8 *pbuf, int index, int *len, int limit); -- cgit v0.10.2 From ec4eb6e146a9b0bdedd5c904d645836e0cd50915 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:20:41 +0700 Subject: staging: r8188eu: remove rtw_set_ie_ch_switch function Driver does not use this function. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c index 25226b2..a54dafa 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c @@ -155,17 +155,6 @@ u8 *rtw_set_ie return pbuf + len + 2; } -inline u8 *rtw_set_ie_ch_switch(u8 *buf, u32 *buf_len, u8 ch_switch_mode, - u8 new_ch, u8 ch_switch_cnt) -{ - u8 ie_data[3]; - - ie_data[0] = ch_switch_mode; - ie_data[1] = new_ch; - ie_data[2] = ch_switch_cnt; - return rtw_set_ie(buf, WLAN_EID_CHANNEL_SWITCH, 3, ie_data, buf_len); -} - /*---------------------------------------------------------------------------- index: the information element id index, limit is the limit for search -----------------------------------------------------------------------------*/ diff --git a/drivers/staging/rtl8188eu/include/ieee80211.h b/drivers/staging/rtl8188eu/include/ieee80211.h index cd0f9b3..4a8504d 100644 --- a/drivers/staging/rtl8188eu/include/ieee80211.h +++ b/drivers/staging/rtl8188eu/include/ieee80211.h @@ -1096,8 +1096,6 @@ enum secondary_ch_offset { SCA = 1, /* secondary channel above */ SCB = 3, /* secondary channel below */ }; -u8 *rtw_set_ie_ch_switch(u8 *buf, u32 *buf_len, u8 ch_switch_mode, - u8 new_ch, u8 ch_switch_cnt); u8 *rtw_get_ie(u8 *pbuf, int index, int *len, int limit); -- cgit v0.10.2 From 92224ac300f1faf7ed8a705404e6b945bec6fef4 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:20:47 +0700 Subject: staging: r8188eu: remove dump_ies function Driver does not use this function. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c index a54dafa..1df25ff 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c @@ -952,22 +952,6 @@ void rtw_macaddr_cfg(u8 *mac_addr) DBG_88E("rtw_macaddr_cfg MAC Address = %pM\n", (mac_addr)); } -void dump_ies(u8 *buf, u32 buf_len) -{ - u8 *pos = buf; - u8 id, len; - - while (pos - buf <= buf_len) { - id = *pos; - len = *(pos + 1); - - DBG_88E("%s ID:%u, LEN:%u\n", __func__, id, len); - dump_wps_ie(pos, len); - - pos += (2 + len); - } -} - void dump_wps_ie(u8 *ie, u32 ie_len) { u8 *pos = ie; diff --git a/drivers/staging/rtl8188eu/include/ieee80211.h b/drivers/staging/rtl8188eu/include/ieee80211.h index 4a8504d..79ae555 100644 --- a/drivers/staging/rtl8188eu/include/ieee80211.h +++ b/drivers/staging/rtl8188eu/include/ieee80211.h @@ -1131,7 +1131,6 @@ u8 *rtw_get_wps_attr_content(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, for (ie = (void *)buf; (((u8 *)ie) - ((u8 *)buf) + 1) < buf_len; \ ie = (void *)(((u8 *)ie) + *(((u8 *)ie)+1) + 2)) -void dump_ies(u8 *buf, u32 buf_len); void dump_wps_ie(u8 *ie, u32 ie_len); uint rtw_get_rateset_len(u8 *rateset); -- cgit v0.10.2 From c9735cb6ea0f3beddeae15fa139d908a686000b3 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:20:52 +0700 Subject: staging: r8188eu: remove dump_wps_ie function Driver does not use this function. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c index 1df25ff..f3e9f7e 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c @@ -952,27 +952,6 @@ void rtw_macaddr_cfg(u8 *mac_addr) DBG_88E("rtw_macaddr_cfg MAC Address = %pM\n", (mac_addr)); } -void dump_wps_ie(u8 *ie, u32 ie_len) -{ - u8 *pos = ie; - u16 id; - u16 len; - u8 *wps_ie; - uint wps_ielen; - - wps_ie = rtw_get_wps_ie(ie, ie_len, NULL, &wps_ielen); - if (wps_ie != ie || wps_ielen == 0) - return; - - pos += 6; - while (pos - ie < ie_len) { - id = get_unaligned_be16(pos); - len = get_unaligned_be16(pos + 2); - DBG_88E("%s ID:0x%04x, LEN:%u\n", __func__, id, len); - pos += (4 + len); - } -} - /* Baron adds to avoid FreeBSD warning */ int ieee80211_is_empty_essid(const char *essid, int essid_len) { diff --git a/drivers/staging/rtl8188eu/include/ieee80211.h b/drivers/staging/rtl8188eu/include/ieee80211.h index 79ae555..375a7a4 100644 --- a/drivers/staging/rtl8188eu/include/ieee80211.h +++ b/drivers/staging/rtl8188eu/include/ieee80211.h @@ -1131,8 +1131,6 @@ u8 *rtw_get_wps_attr_content(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, for (ie = (void *)buf; (((u8 *)ie) - ((u8 *)buf) + 1) < buf_len; \ ie = (void *)(((u8 *)ie) + *(((u8 *)ie)+1) + 2)) -void dump_wps_ie(u8 *ie, u32 ie_len); - uint rtw_get_rateset_len(u8 *rateset); struct registry_priv; -- cgit v0.10.2 From 86d54a7b782e68f6148b73d97428cfbfcea7d6e1 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:20:56 +0700 Subject: staging: r8188eu: remove rtw_action_frame_parse function Driver does not use this function. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c index f3e9f7e..fac1241 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c @@ -1155,35 +1155,6 @@ u16 rtw_mcs_rate(u8 rf_type, u8 bw_40MHz, u8 short_GI_20, u8 short_GI_40, unsign return max_rate; } -int rtw_action_frame_parse(const u8 *frame, u32 frame_len, u8 *category, u8 *action) -{ - const u8 *frame_body = frame + sizeof(struct rtw_ieee80211_hdr_3addr); - u16 fc; - u8 c, a = 0; - - fc = le16_to_cpu(((struct rtw_ieee80211_hdr_3addr *)frame)->frame_ctl); - - if ((fc & (RTW_IEEE80211_FCTL_FTYPE | RTW_IEEE80211_FCTL_STYPE)) != - (RTW_IEEE80211_FTYPE_MGMT | RTW_IEEE80211_STYPE_ACTION)) - return false; - - c = frame_body[0]; - - switch (c) { - case RTW_WLAN_CATEGORY_P2P: /* vendor-specific */ - break; - default: - a = frame_body[1]; - } - - if (category) - *category = c; - if (action) - *action = a; - - return true; -} - static const char *_action_public_str[] = { "ACT_PUB_BSSCOEXIST", "ACT_PUB_DSE_ENABLE", diff --git a/drivers/staging/rtl8188eu/include/ieee80211.h b/drivers/staging/rtl8188eu/include/ieee80211.h index 375a7a4..8a3176f 100644 --- a/drivers/staging/rtl8188eu/include/ieee80211.h +++ b/drivers/staging/rtl8188eu/include/ieee80211.h @@ -1152,8 +1152,6 @@ void rtw_macaddr_cfg(u8 *mac_addr); u16 rtw_mcs_rate(u8 rf_type, u8 bw_40MHz, u8 short_GI_20, u8 short_GI_40, unsigned char *MCS_rate); -int rtw_action_frame_parse(const u8 *frame, u32 frame_len, u8 *category, - u8 *action); const char *action_public_str(u8 action); #endif /* IEEE80211_H */ -- cgit v0.10.2 From 1b9e6df5169b36b3242e2e28c39f9bbfc01863e8 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:21:01 +0700 Subject: staging: r8188eu: remove action_public_str function Driver does not use this function. Also _action_public_str array removed. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c index fac1241..0c616bc 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c @@ -1154,29 +1154,3 @@ u16 rtw_mcs_rate(u8 rf_type, u8 bw_40MHz, u8 short_GI_20, u8 short_GI_40, unsign } return max_rate; } - -static const char *_action_public_str[] = { - "ACT_PUB_BSSCOEXIST", - "ACT_PUB_DSE_ENABLE", - "ACT_PUB_DSE_DEENABLE", - "ACT_PUB_DSE_REG_LOCATION", - "ACT_PUB_EXT_CHL_SWITCH", - "ACT_PUB_DSE_MSR_REQ", - "ACT_PUB_DSE_MSR_RPRT", - "ACT_PUB_MP", - "ACT_PUB_DSE_PWR_CONSTRAINT", - "ACT_PUB_VENDOR", - "ACT_PUB_GAS_INITIAL_REQ", - "ACT_PUB_GAS_INITIAL_RSP", - "ACT_PUB_GAS_COMEBACK_REQ", - "ACT_PUB_GAS_COMEBACK_RSP", - "ACT_PUB_TDLS_DISCOVERY_RSP", - "ACT_PUB_LOCATION_TRACK", - "ACT_PUB_RSVD", -}; - -const char *action_public_str(u8 action) -{ - action = min_t(u8, action, ACT_PUBLIC_MAX); - return _action_public_str[action]; -} diff --git a/drivers/staging/rtl8188eu/include/ieee80211.h b/drivers/staging/rtl8188eu/include/ieee80211.h index 8a3176f..ddb9db4 100644 --- a/drivers/staging/rtl8188eu/include/ieee80211.h +++ b/drivers/staging/rtl8188eu/include/ieee80211.h @@ -1152,6 +1152,4 @@ void rtw_macaddr_cfg(u8 *mac_addr); u16 rtw_mcs_rate(u8 rf_type, u8 bw_40MHz, u8 short_GI_20, u8 short_GI_40, unsigned char *MCS_rate); -const char *action_public_str(u8 action); - #endif /* IEEE80211_H */ -- cgit v0.10.2 From be98624d1446dd2ef58d72f1e5c0417346710a27 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:21:05 +0700 Subject: staging: r8188eu: remove for_each_ie macro for_each_ie does not used in the driver code. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/ieee80211.h b/drivers/staging/rtl8188eu/include/ieee80211.h index ddb9db4..e45ef14 100644 --- a/drivers/staging/rtl8188eu/include/ieee80211.h +++ b/drivers/staging/rtl8188eu/include/ieee80211.h @@ -1121,16 +1121,6 @@ u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, u8 *rtw_get_wps_attr_content(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, u8 *buf_content, uint *len_content); -/** - * for_each_ie - iterate over continuous IEs - * @ie: - * @buf: - * @buf_len: - */ -#define for_each_ie(ie, buf, buf_len) \ - for (ie = (void *)buf; (((u8 *)ie) - ((u8 *)buf) + 1) < buf_len; \ - ie = (void *)(((u8 *)ie) + *(((u8 *)ie)+1) + 2)) - uint rtw_get_rateset_len(u8 *rateset); struct registry_priv; -- cgit v0.10.2 From 042ca34b9ab19d0a52c3b01862a6c07fcb032e86 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:21:10 +0700 Subject: staging: r8188eu: replace rtw_ieee80211_ht_cap with ieee80211_ht_cap type in rtw_check_beacon_data function rtw_ieee80211_ht_cap is reimplementation of the ieee80211_ht_cap. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c index bbb1aa7..1bccd0a 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ap.c +++ b/drivers/staging/rtl8188eu/core/rtw_ap.c @@ -1032,7 +1032,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) (pbss_network->IELength - _BEACON_IE_OFFSET_)); if (p && ie_len > 0) { u8 rf_type; - struct rtw_ieee80211_ht_cap *pht_cap = (struct rtw_ieee80211_ht_cap *)(p+2); + struct ieee80211_ht_cap *pht_cap = (struct ieee80211_ht_cap *)(p + 2); pHT_caps_ie = p; ht_cap = true; @@ -1050,8 +1050,8 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_FACTOR & 0x03); if (rf_type == RF_1T1R) { - pht_cap->supp_mcs_set[0] = 0xff; - pht_cap->supp_mcs_set[1] = 0x0; + pht_cap->mcs.rx_mask[0] = 0xff; + pht_cap->mcs.rx_mask[1] = 0x0; } memcpy(&pmlmepriv->htpriv.ht_cap, p+2, ie_len); } -- cgit v0.10.2 From da9090adb7052c3f544beda80a56b4eb46175adf Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:21:14 +0700 Subject: staging: r8188eu: replace rtw_ieee80211_ht_cap with ieee80211_ht_cap type in translate_scan function rtw_ieee80211_ht_cap is reimplementation of the ieee80211_ht_cap. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c index 5672f01..a2b3552 100644 --- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c @@ -132,12 +132,15 @@ static char *translate_scan(struct adapter *padapter, p = rtw_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.IELength-12); if (p && ht_ielen > 0) { - struct rtw_ieee80211_ht_cap *pht_capie; + struct ieee80211_ht_cap *pht_capie; ht_cap = true; - pht_capie = (struct rtw_ieee80211_ht_cap *)(p+2); - memcpy(&mcs_rate, pht_capie->supp_mcs_set, 2); - bw_40MHz = (pht_capie->cap_info&IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0; - short_GI = (pht_capie->cap_info&(IEEE80211_HT_CAP_SGI_20|IEEE80211_HT_CAP_SGI_40)) ? 1 : 0; + pht_capie = (struct ieee80211_ht_cap *)(p + 2); + memcpy(&mcs_rate, pht_capie->mcs.rx_mask, 2); + bw_40MHz = !!(le16_to_cpu(pht_capie->cap_info) & + IEEE80211_HT_CAP_SUP_WIDTH); + short_GI = !!(le16_to_cpu(pht_capie->cap_info) & + (IEEE80211_HT_CAP_SGI_20 | + IEEE80211_HT_CAP_SGI_40)); } /* Add the protocol name */ -- cgit v0.10.2 From 81a2b8e4bb629054d414cec297068f23813b8e50 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:21:18 +0700 Subject: staging: r8188eu: replace sizeof(struct rtw_ieee80211_ht_cap) with sizeof(struct ieee80211_ht_cap) Values of this expressions are equal, but ieee80211_ht_cap is library type. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c index 1456499..a4e3bde 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c @@ -1958,7 +1958,7 @@ unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_ out_len = *pout_len; - memset(&ht_capie, 0, sizeof(struct rtw_ieee80211_ht_cap)); + memset(&ht_capie, 0, sizeof(struct ieee80211_ht_cap)); ht_capie.cap_info = IEEE80211_HT_CAP_SUP_WIDTH | IEEE80211_HT_CAP_SGI_20 | @@ -1984,7 +1984,8 @@ unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_ rtw_set_ie(out_ie+out_len, _HT_CAPABILITY_IE_, - sizeof(struct rtw_ieee80211_ht_cap), (unsigned char *)&ht_capie, pout_len); + sizeof(struct ieee80211_ht_cap), + (unsigned char *)&ht_capie, pout_len); phtpriv->ht_option = true; diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 40e0b60..91e7b36 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -3236,13 +3236,15 @@ static unsigned int OnAssocReq(struct adapter *padapter, } /* save HT capabilities in the sta object */ - memset(&pstat->htpriv.ht_cap, 0, sizeof(struct rtw_ieee80211_ht_cap)); - if (elems.ht_capabilities && elems.ht_capabilities_len >= sizeof(struct rtw_ieee80211_ht_cap)) { + memset(&pstat->htpriv.ht_cap, 0, sizeof(struct ieee80211_ht_cap)); + if (elems.ht_capabilities && + elems.ht_capabilities_len >= sizeof(struct ieee80211_ht_cap)) { pstat->flags |= WLAN_STA_HT; pstat->flags |= WLAN_STA_WME; - memcpy(&pstat->htpriv.ht_cap, elems.ht_capabilities, sizeof(struct rtw_ieee80211_ht_cap)); + memcpy(&pstat->htpriv.ht_cap, + elems.ht_capabilities, sizeof(struct ieee80211_ht_cap)); } else { pstat->flags &= ~WLAN_STA_HT; } diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c index a2b3552..44d3ed6 100644 --- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c @@ -2531,7 +2531,8 @@ static int rtw_add_sta(struct net_device *dev, struct ieee_param *param) if (WLAN_STA_HT&flags) { psta->htpriv.ht_option = true; psta->qos_option = 1; - memcpy((void *)&psta->htpriv.ht_cap, (void *)¶m->u.add_sta.ht_cap, sizeof(struct rtw_ieee80211_ht_cap)); + memcpy(&psta->htpriv.ht_cap, ¶m->u.add_sta.ht_cap, + sizeof(struct ieee80211_ht_cap)); } else { psta->htpriv.ht_option = false; } @@ -2627,7 +2628,8 @@ static int rtw_ioctl_get_sta_data(struct net_device *dev, struct ieee_param *par (psta->ht_20mhz_set << 5)); psta_data->tx_supp_rates_len = psta->bssratelen; memcpy(psta_data->tx_supp_rates, psta->bssrateset, psta->bssratelen); - memcpy(&psta_data->ht_cap, &psta->htpriv.ht_cap, sizeof(struct rtw_ieee80211_ht_cap)); + memcpy(&psta_data->ht_cap, + &psta->htpriv.ht_cap, sizeof(struct ieee80211_ht_cap)); psta_data->rx_pkts = psta->sta_stats.rx_data_pkts; psta_data->rx_bytes = psta->sta_stats.rx_bytes; psta_data->rx_drops = psta->sta_stats.rx_drops; -- cgit v0.10.2 From 7f98038a39024e90cbbdc807ce4b3d7ef72babf6 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:21:24 +0700 Subject: staging: r8188eu: remove dead code from rtw_get_cur_max_rate function Values assugned to pht_capie and mcs_rate variables, but variables does not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c index f85a6ab..62b2f71 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c +++ b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c @@ -14,7 +14,6 @@ ******************************************************************************/ #define _RTW_IOCTL_SET_C_ - #include <osdep_service.h> #include <drv_types.h> #include <rtw_ioctl_set.h> @@ -570,10 +569,8 @@ u16 rtw_get_cur_max_rate(struct adapter *adapter) struct registry_priv *pregistrypriv = &adapter->registrypriv; struct mlme_priv *pmlmepriv = &adapter->mlmepriv; struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; - struct rtw_ieee80211_ht_cap *pht_capie; u8 rf_type = 0; u8 bw_40MHz = 0, short_GI_20 = 0, short_GI_40 = 0; - u16 mcs_rate = 0; u32 ht_ielen = 0; if (adapter->registrypriv.mp_mode == 1) { @@ -588,10 +585,6 @@ u16 rtw_get_cur_max_rate(struct adapter *adapter) if (pmlmeext->cur_wireless_mode & (WIRELESS_11_24N|WIRELESS_11_5N)) { p = rtw_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->IELength-12); if (p && ht_ielen > 0) { - pht_capie = (struct rtw_ieee80211_ht_cap *)(p+2); - - memcpy(&mcs_rate, pht_capie->supp_mcs_set, 2); - /* cur_bwmod is updated by beacon, pmlmeinfo is updated by association response */ bw_40MHz = (pmlmeext->cur_bwmode && (HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH & pmlmeinfo->HT_info.infos[0])) ? 1 : 0; -- cgit v0.10.2 From c7873d8bad59be2886046548e0e0b16d2529dce1 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:21:28 +0700 Subject: staging: r8188eu: change rtw_ieee80211_ht_cap type of local variables to ieee80211_ht_cap rtw_ieee80211_ht_cap is reimplementation of the ieee80211_ht_cap. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c index 0c616bc..914c492 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c @@ -1042,7 +1042,6 @@ void rtw_get_bcn_info(struct wlan_network *pnetwork) __le16 le_tmp; u16 wpa_len = 0, rsn_len = 0; struct HT_info_element *pht_info = NULL; - struct rtw_ieee80211_ht_cap *pht_cap = NULL; unsigned int len; unsigned char *p; @@ -1078,10 +1077,12 @@ void rtw_get_bcn_info(struct wlan_network *pnetwork) /* parsing HT_CAP_IE */ p = rtw_get_ie(pnetwork->network.IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pnetwork->network.IELength - _FIXED_IE_LENGTH_); if (p && len > 0) { - pht_cap = (struct rtw_ieee80211_ht_cap *)(p + 2); - pnetwork->BcnInfo.ht_cap_info = pht_cap->cap_info; + struct ieee80211_ht_cap *ht_cap = + (struct ieee80211_ht_cap *)(p + 2); + + pnetwork->BcnInfo.ht_cap_info = le16_to_cpu(ht_cap->cap_info); } else { - pnetwork->BcnInfo.ht_cap_info = 0; + pnetwork->BcnInfo.ht_cap_info = 0; } /* parsing HT_INFO_IE */ p = rtw_get_ie(pnetwork->network.IEs + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, pnetwork->network.IELength - _FIXED_IE_LENGTH_); diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c index a4e3bde..4979c61 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c @@ -1935,7 +1935,6 @@ unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_ u32 ielen, out_len; enum ht_cap_ampdu_factor max_rx_ampdu_factor; unsigned char *p; - struct rtw_ieee80211_ht_cap ht_capie; unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00}; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct qos_priv *pqospriv = &pmlmepriv->qospriv; @@ -1948,6 +1947,8 @@ unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_ p = rtw_get_ie(in_ie+12, _HT_CAPABILITY_IE_, &ielen, in_len-12); if (p && ielen > 0) { + struct ieee80211_ht_cap ht_cap; + if (pqospriv->qos_option == 0) { out_len = *pout_len; rtw_set_ie(out_ie+out_len, _VENDOR_SPECIFIC_IE_, @@ -1958,13 +1959,13 @@ unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_ out_len = *pout_len; - memset(&ht_capie, 0, sizeof(struct ieee80211_ht_cap)); + memset(&ht_cap, 0, sizeof(struct ieee80211_ht_cap)); - ht_capie.cap_info = IEEE80211_HT_CAP_SUP_WIDTH | - IEEE80211_HT_CAP_SGI_20 | - IEEE80211_HT_CAP_SGI_40 | - IEEE80211_HT_CAP_TX_STBC | - IEEE80211_HT_CAP_DSSSCCK40; + ht_cap.cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH | + IEEE80211_HT_CAP_SGI_20 | + IEEE80211_HT_CAP_SGI_40 | + IEEE80211_HT_CAP_TX_STBC | + IEEE80211_HT_CAP_DSSSCCK40); rtw_hal_get_def_var(padapter, HAL_DEF_RX_PACKET_OFFSET, &rx_packet_offset); rtw_hal_get_def_var(padapter, HAL_DEF_MAX_RECVBUF_SZ, &max_recvbuf_sz); @@ -1975,17 +1976,16 @@ unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_ */ rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor); - ht_capie.ampdu_params_info = (max_rx_ampdu_factor&0x03); + ht_cap.ampdu_params_info = max_rx_ampdu_factor & 0x03; if (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_) - ht_capie.ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&(0x07<<2)); + ht_cap.ampdu_params_info |= IEEE80211_HT_CAP_AMPDU_DENSITY & (0x07 << 2); else - ht_capie.ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&0x00); - + ht_cap.ampdu_params_info |= IEEE80211_HT_CAP_AMPDU_DENSITY & 0x00; rtw_set_ie(out_ie+out_len, _HT_CAPABILITY_IE_, sizeof(struct ieee80211_ht_cap), - (unsigned char *)&ht_capie, pout_len); + (unsigned char *)&ht_cap, pout_len); phtpriv->ht_option = true; @@ -2003,7 +2003,6 @@ void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len) { u8 *p, max_ampdu_sz; int len; - struct rtw_ieee80211_ht_cap *pht_capie; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct ht_priv *phtpriv = &pmlmepriv->htpriv; struct registry_priv *pregistrypriv = &padapter->registrypriv; @@ -2033,8 +2032,10 @@ void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len) len = 0; p = rtw_get_ie(pie+sizeof(struct ndis_802_11_fixed_ie), _HT_CAPABILITY_IE_, &len, ie_len-sizeof(struct ndis_802_11_fixed_ie)); if (p && len > 0) { - pht_capie = (struct rtw_ieee80211_ht_cap *)(p+2); - max_ampdu_sz = pht_capie->ampdu_params_info & IEEE80211_HT_CAP_AMPDU_FACTOR; + struct ieee80211_ht_cap *ht_cap = + (struct ieee80211_ht_cap *)(p + 2); + + max_ampdu_sz = ht_cap->ampdu_params_info & IEEE80211_HT_CAP_AMPDU_FACTOR; max_ampdu_sz = 1 << (max_ampdu_sz+3); /* max_ampdu_sz (kbytes); */ phtpriv->rx_ampdu_maxlen = max_ampdu_sz; } diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c index 4410fe8..548db72 100644 --- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c @@ -872,7 +872,6 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len) u32 wpa_ielen = 0; u8 *pbssid = GetAddr3Ptr(pframe); struct HT_info_element *pht_info = NULL; - struct rtw_ieee80211_ht_cap *pht_cap = NULL; u32 bcn_channel; unsigned short ht_cap_info; unsigned char ht_info_infos_0; @@ -913,8 +912,10 @@ 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_, _HT_CAPABILITY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_); if (p && len > 0) { - pht_cap = (struct rtw_ieee80211_ht_cap *)(p + 2); - ht_cap_info = pht_cap->cap_info; + struct ieee80211_ht_cap *ht_cap = + (struct ieee80211_ht_cap *)(p + 2); + + ht_cap_info = le16_to_cpu(ht_cap->cap_info); } else { ht_cap_info = 0; } -- cgit v0.10.2 From cfecac2e22ddae7437893da84552da2f4236be92 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:21:33 +0700 Subject: staging: r8188eu: change rtw_ieee80211_ht_cap type of structures members to ieee80211_ht_cap Also cap_info member of ieee80211_ht_cap wrapped by le16_to_cpu function. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c index 1bccd0a..a148e7d 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ap.c +++ b/drivers/staging/rtl8188eu/core/rtw_ap.c @@ -481,7 +481,7 @@ void add_RATid(struct adapter *padapter, struct sta_info *psta, u8 rssi_level) limit = 8;/* 1R */ for (i = 0; i < limit; i++) { - if (psta_ht->ht_cap.supp_mcs_set[i/8] & BIT(i%8)) + if (psta_ht->ht_cap.mcs.rx_mask[i / 8] & BIT(i % 8)) tx_ra_bitmap |= BIT(i+12); } @@ -658,11 +658,15 @@ void update_sta_info_apmode(struct adapter *padapter, struct sta_info *psta) phtpriv_sta->ampdu_enable = phtpriv_ap->ampdu_enable; /* check if sta support s Short GI */ - if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40)) + if (le16_to_cpu(phtpriv_sta->ht_cap.cap_info & + phtpriv_ap->ht_cap.cap_info) & + (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40)) phtpriv_sta->sgi = true; /* bwmode */ - if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & IEEE80211_HT_CAP_SUP_WIDTH) { + if (le16_to_cpu(phtpriv_sta->ht_cap.cap_info & + phtpriv_ap->ht_cap.cap_info) & + IEEE80211_HT_CAP_SUP_WIDTH) { phtpriv_sta->bwmode = pmlmeext->cur_bwmode; phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset; } @@ -1422,7 +1426,8 @@ static int rtw_ht_operation_update(struct adapter *padapter) if (pmlmepriv->num_sta_no_ht || (pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)) new_op_mode = OP_MODE_MIXED; - else if ((phtpriv_ap->ht_cap.cap_info & IEEE80211_HT_CAP_SUP_WIDTH) && + else if ((le16_to_cpu(phtpriv_ap->ht_cap.cap_info) & + IEEE80211_HT_CAP_SUP_WIDTH) && pmlmepriv->num_sta_ht_20mhz) new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED; else if (pmlmepriv->olbc_ht) @@ -1552,7 +1557,7 @@ void bss_cap_update_on_sta_join(struct adapter *padapter, struct sta_info *psta) } if (psta->flags & WLAN_STA_HT) { - u16 ht_capab = psta->htpriv.ht_cap.cap_info; + 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); diff --git a/drivers/staging/rtl8188eu/include/ieee80211.h b/drivers/staging/rtl8188eu/include/ieee80211.h index e45ef14..b57f5d7 100644 --- a/drivers/staging/rtl8188eu/include/ieee80211.h +++ b/drivers/staging/rtl8188eu/include/ieee80211.h @@ -239,7 +239,7 @@ struct ieee_param { u16 capability; int flags; u8 tx_supp_rates[16]; - struct rtw_ieee80211_ht_cap ht_cap; + struct ieee80211_ht_cap ht_cap; } add_sta; struct { u8 reserved[2];/* for set max_num_sta */ @@ -264,7 +264,7 @@ struct sta_data { u32 sta_set; u8 tx_supp_rates[16]; u32 tx_supp_rates_len; - struct rtw_ieee80211_ht_cap ht_cap; + struct ieee80211_ht_cap ht_cap; u64 rx_pkts; u64 rx_bytes; u64 rx_drops; diff --git a/drivers/staging/rtl8188eu/include/rtw_ht.h b/drivers/staging/rtl8188eu/include/rtw_ht.h index b45483f..7beb0b1 100644 --- a/drivers/staging/rtl8188eu/include/rtw_ht.h +++ b/drivers/staging/rtl8188eu/include/rtw_ht.h @@ -15,8 +15,8 @@ #ifndef _RTW_HT_H_ #define _RTW_HT_H_ +#include <linux/ieee80211.h> #include <osdep_service.h> -#include "wifi.h" struct ht_priv { u32 ht_option; @@ -33,7 +33,7 @@ struct ht_priv { u8 agg_enable_bitmap; u8 candidate_tid_bitmap; - struct rtw_ieee80211_ht_cap ht_cap; + struct ieee80211_ht_cap ht_cap; }; #endif /* _RTL871X_HT_H_ */ -- cgit v0.10.2 From 7494b27f659552b9ddc2085b2946939aab0e84ef Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:21:38 +0700 Subject: staging: r8188eu: remove rtw_ieee80211_ht_cap structure rtw_ieee80211_ht_cap does not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/wifi.h b/drivers/staging/rtl8188eu/include/wifi.h index e7c5121..e049eed 100644 --- a/drivers/staging/rtl8188eu/include/wifi.h +++ b/drivers/staging/rtl8188eu/include/wifi.h @@ -508,22 +508,6 @@ struct rtw_ieee80211_bar { #define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000 #define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA 0x0004 - /** - * struct rtw_ieee80211_ht_cap - HT capabilities - * - * This structure refers to "HT capabilities element" as - * described in 802.11n draft section 7.3.2.52 - */ - -struct rtw_ieee80211_ht_cap { - unsigned short cap_info; - unsigned char ampdu_params_info; - unsigned char supp_mcs_set[16]; - unsigned short extended_ht_cap_info; - unsigned int tx_BF_cap_info; - unsigned char antenna_selection_info; -} __packed; - /** * struct rtw_ieee80211_ht_cap - HT additional information * -- cgit v0.10.2 From 16d475cb47f005cbc330c14ba94604af518cd018 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:21:43 +0700 Subject: staging: r8188eu: remove HT_cap member of HT_caps_element structure This member used only once and can be replaced with address of HT_caps_element. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c index 548db72..c07e4cb 100644 --- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c @@ -716,6 +716,7 @@ void HT_caps_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE) struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct ht_priv *phtpriv = &pmlmepriv->htpriv; + u8 *HT_cap = (u8 *)(&pmlmeinfo->HT_caps.u.HT_cap_element); if (pIE == NULL) return; @@ -728,7 +729,7 @@ void HT_caps_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE) for (i = 0; i < (pIE->Length); i++) { if (i != 2) { /* Got the endian issue here. */ - pmlmeinfo->HT_caps.u.HT_cap[i] &= (pIE->data[i]); + HT_cap[i] &= (pIE->data[i]); } else { /* modify from fw by Thomas 2010/11/17 */ if ((pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3) > (pIE->data[i] & 0x3)) diff --git a/drivers/staging/rtl8188eu/include/wifi.h b/drivers/staging/rtl8188eu/include/wifi.h index e049eed..27276fe 100644 --- a/drivers/staging/rtl8188eu/include/wifi.h +++ b/drivers/staging/rtl8188eu/include/wifi.h @@ -532,7 +532,6 @@ struct HT_caps_element { unsigned int Beamforming_caps; unsigned char ASEL_caps; } HT_cap_element; - unsigned char HT_cap[26]; } u; } __packed; -- cgit v0.10.2 From ad0ca5903cfc45389c71ff88d310641f49a1391c Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:21:50 +0700 Subject: staging: r8188eu: simplify HT_caps_element structure Now HT_caps_element structure is similar to ieee80211_ht_caps. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c index a148e7d..be4d624 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ap.c +++ b/drivers/staging/rtl8188eu/core/rtw_ap.c @@ -709,9 +709,9 @@ static void update_hw_ht_param(struct adapter *padapter) AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k AMPDU_para [4:2]:Min MPDU Start Spacing */ - max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03; + max_AMPDU_len = pmlmeinfo->HT_caps.AMPDU_para & 0x03; - min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2; + min_MPDU_spacing = (pmlmeinfo->HT_caps.AMPDU_para & 0x1c) >> 2; rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing)); @@ -720,7 +720,7 @@ static void update_hw_ht_param(struct adapter *padapter) /* */ /* Config SM Power Save setting */ /* */ - pmlmeinfo->SM_PS = (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) & 0x0C) >> 2; + pmlmeinfo->SM_PS = (le16_to_cpu(pmlmeinfo->HT_caps.HT_caps_info) & 0x0C) >> 2; if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC) DBG_88E("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__); } diff --git a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c index 62b2f71..a830752 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c +++ b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c @@ -588,8 +588,8 @@ u16 rtw_get_cur_max_rate(struct adapter *adapter) /* cur_bwmod is updated by beacon, pmlmeinfo is updated by association response */ bw_40MHz = (pmlmeext->cur_bwmode && (HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH & pmlmeinfo->HT_info.infos[0])) ? 1 : 0; - short_GI_20 = (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) & IEEE80211_HT_CAP_SGI_20) ? 1 : 0; - short_GI_40 = (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) & IEEE80211_HT_CAP_SGI_40) ? 1 : 0; + short_GI_20 = (le16_to_cpu(pmlmeinfo->HT_caps.HT_caps_info) & IEEE80211_HT_CAP_SGI_20) ? 1 : 0; + short_GI_40 = (le16_to_cpu(pmlmeinfo->HT_caps.HT_caps_info) & IEEE80211_HT_CAP_SGI_40) ? 1 : 0; rtw_hal_get_hwreg(adapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type)); max_rate = rtw_mcs_rate( @@ -597,7 +597,7 @@ u16 rtw_get_cur_max_rate(struct adapter *adapter) bw_40MHz & (pregistrypriv->cbw40_enable), short_GI_20, short_GI_40, - pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate + pmlmeinfo->HT_caps.MCS_rate ); } } else { diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c index 4979c61..03baaa1 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c @@ -2044,7 +2044,7 @@ void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len) /* update cur_bwmode & cur_ch_offset */ if ((pregistrypriv->cbw40_enable) && - (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) & BIT(1)) && + (le16_to_cpu(pmlmeinfo->HT_caps.HT_caps_info) & BIT(1)) && (pmlmeinfo->HT_info.infos[0] & BIT(2))) { int i; u8 rf_type; @@ -2054,9 +2054,9 @@ void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len) /* update the MCS rates */ for (i = 0; i < 16; i++) { if ((rf_type == RF_1T1R) || (rf_type == RF_1T2R)) - pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_1R[i]; + pmlmeinfo->HT_caps.MCS_rate[i] &= MCS_rate_1R[i]; else - pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_2R[i]; + pmlmeinfo->HT_caps.MCS_rate[i] &= MCS_rate_2R[i]; } /* switch to the 40M Hz mode according to the AP */ pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40; @@ -2074,7 +2074,7 @@ 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.u.HT_cap_element.HT_caps_info) & 0x0C) >> 2; + pmlmeinfo->SM_PS = (le16_to_cpu(pmlmeinfo->HT_caps.HT_caps_info) & 0x0C) >> 2; if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC) DBG_88E("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__); diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 91e7b36..5b7cb48 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -1136,19 +1136,19 @@ static void issue_assocreq(struct adapter *padapter) /* to disable 40M Hz support while gd_bw_40MHz_en = 0 */ if (pregpriv->cbw40_enable == 0) - pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info &= cpu_to_le16(~(BIT(6) | BIT(1))); + pmlmeinfo->HT_caps.HT_caps_info &= cpu_to_le16(~(BIT(6) | BIT(1))); else - pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(BIT(1)); + pmlmeinfo->HT_caps.HT_caps_info |= cpu_to_le16(BIT(1)); /* todo: disable SM power save mode */ - pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x000c); + pmlmeinfo->HT_caps.HT_caps_info |= cpu_to_le16(0x000c); rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type)); switch (rf_type) { case RF_1T1R: if (pregpriv->rx_stbc) - pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x0100);/* RX STBC One spatial stream */ - memcpy(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_rate_1R, 16); + pmlmeinfo->HT_caps.HT_caps_info |= cpu_to_le16(0x0100);/* RX STBC One spatial stream */ + memcpy(pmlmeinfo->HT_caps.MCS_rate, MCS_rate_1R, 16); break; case RF_2T2R: case RF_1T2R: @@ -1157,9 +1157,9 @@ static void issue_assocreq(struct adapter *padapter) ((pmlmeext->cur_wireless_mode & WIRELESS_11_24N) && (pregpriv->rx_stbc == 0x1)) || /* enable for 2.4GHz */ (pregpriv->wifi_spec == 1)) { DBG_88E("declare supporting RX STBC\n"); - pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x0200);/* RX STBC two spatial stream */ + pmlmeinfo->HT_caps.HT_caps_info |= cpu_to_le16(0x0200);/* RX STBC two spatial stream */ } - memcpy(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_rate_2R, 16); + memcpy(pmlmeinfo->HT_caps.MCS_rate, MCS_rate_2R, 16); break; } pframe = rtw_set_ie(pframe, _HT_CAPABILITY_IE_, ie_len , (u8 *)(&(pmlmeinfo->HT_caps)), &(pattrib->pktlen)); @@ -2192,7 +2192,7 @@ static u8 collect_bss_info(struct adapter *padapter, struct HT_caps_element *pHT_caps; pHT_caps = (struct HT_caps_element *)(p + 2); - if (le16_to_cpu(pHT_caps->u.HT_cap_element.HT_caps_info)&BIT(14)) + if (le16_to_cpu(pHT_caps->HT_caps_info) & BIT(14)) pmlmepriv->num_FortyMHzIntolerant++; } else { pmlmepriv->num_sta_no_ht++; @@ -4479,7 +4479,7 @@ void update_sta_info(struct adapter *padapter, struct sta_info *psta) psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable; - if (support_short_GI(padapter, &(pmlmeinfo->HT_caps))) + if (support_short_GI(padapter, &pmlmeinfo->HT_caps)) psta->htpriv.sgi = true; psta->qos_option = true; diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c index c07e4cb..8994e45 100644 --- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c @@ -716,7 +716,7 @@ void HT_caps_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE) struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct ht_priv *phtpriv = &pmlmepriv->htpriv; - u8 *HT_cap = (u8 *)(&pmlmeinfo->HT_caps.u.HT_cap_element); + u8 *HT_cap = (u8 *)(&pmlmeinfo->HT_caps); if (pIE == NULL) return; @@ -732,17 +732,17 @@ void HT_caps_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE) HT_cap[i] &= (pIE->data[i]); } else { /* modify from fw by Thomas 2010/11/17 */ - if ((pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3) > (pIE->data[i] & 0x3)) + if ((pmlmeinfo->HT_caps.AMPDU_para & 0x3) > (pIE->data[i] & 0x3)) max_AMPDU_len = pIE->data[i] & 0x3; else - max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3; + max_AMPDU_len = pmlmeinfo->HT_caps.AMPDU_para & 0x3; - if ((pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) > (pIE->data[i] & 0x1c)) - min_MPDU_spacing = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c; + if ((pmlmeinfo->HT_caps.AMPDU_para & 0x1c) > (pIE->data[i] & 0x1c)) + min_MPDU_spacing = pmlmeinfo->HT_caps.AMPDU_para & 0x1c; else min_MPDU_spacing = pIE->data[i] & 0x1c; - pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para = max_AMPDU_len | min_MPDU_spacing; + pmlmeinfo->HT_caps.AMPDU_para = max_AMPDU_len | min_MPDU_spacing; } } @@ -751,9 +751,9 @@ void HT_caps_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE) /* update the MCS rates */ for (i = 0; i < 16; i++) { if ((rf_type == RF_1T1R) || (rf_type == RF_1T2R)) - pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_1R[i]; + pmlmeinfo->HT_caps.MCS_rate[i] &= MCS_rate_1R[i]; else - pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_2R[i]; + pmlmeinfo->HT_caps.MCS_rate[i] &= MCS_rate_2R[i]; } } @@ -799,9 +799,9 @@ void HTOnAssocRsp(struct adapter *padapter) AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k AMPDU_para [4:2]:Min MPDU Start Spacing */ - max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03; + max_AMPDU_len = pmlmeinfo->HT_caps.AMPDU_para & 0x03; - min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2; + min_MPDU_spacing = (pmlmeinfo->HT_caps.AMPDU_para & 0x1c) >> 2; rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing)); @@ -1249,7 +1249,7 @@ unsigned int update_MSC_rate(struct HT_caps_element *pHT_caps) { unsigned int mask = 0; - mask = (pHT_caps->u.HT_cap_element.MCS_rate[0] << 12) | (pHT_caps->u.HT_cap_element.MCS_rate[1] << 20); + mask = (pHT_caps->MCS_rate[0] << 12) | (pHT_caps->MCS_rate[1] << 20); return mask; } @@ -1268,7 +1268,7 @@ int support_short_GI(struct adapter *padapter, struct HT_caps_element *pHT_caps) bit_offset = (pmlmeext->cur_bwmode & HT_CHANNEL_WIDTH_40) ? 6 : 5; - if (__le16_to_cpu(pHT_caps->u.HT_cap_element.HT_caps_info) & (0x1 << bit_offset)) + if (__le16_to_cpu(pHT_caps->HT_caps_info) & (0x1 << bit_offset)) return _SUCCESS; else return _FAIL; diff --git a/drivers/staging/rtl8188eu/include/wifi.h b/drivers/staging/rtl8188eu/include/wifi.h index 27276fe..28e1dde 100644 --- a/drivers/staging/rtl8188eu/include/wifi.h +++ b/drivers/staging/rtl8188eu/include/wifi.h @@ -523,16 +523,12 @@ struct ieee80211_ht_addt_info { } __packed; struct HT_caps_element { - union { - struct { - __le16 HT_caps_info; - unsigned char AMPDU_para; - unsigned char MCS_rate[16]; - unsigned short HT_ext_caps; - unsigned int Beamforming_caps; - unsigned char ASEL_caps; - } HT_cap_element; - } u; + __le16 HT_caps_info; + unsigned char AMPDU_para; + unsigned char MCS_rate[16]; + unsigned short HT_ext_caps; + unsigned int Beamforming_caps; + unsigned char ASEL_caps; } __packed; struct HT_info_element { -- cgit v0.10.2 From 3d3cd94d0d695292ba29a918669faca8ecf368cd Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:21:55 +0700 Subject: staging: r8188eu: replace HT_caps_element with ieee80211_ht_cap structure HT_caps_element is reimplementation of ieee80211_ht_cap. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c index be4d624..3562f11 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ap.c +++ b/drivers/staging/rtl8188eu/core/rtw_ap.c @@ -706,12 +706,12 @@ static void update_hw_ht_param(struct adapter *padapter) /* handle A-MPDU parameter field */ /* - AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k - AMPDU_para [4:2]:Min MPDU Start Spacing + ampdu_params_info [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k + ampdu_params_info [4:2]:Min MPDU Start Spacing */ - max_AMPDU_len = pmlmeinfo->HT_caps.AMPDU_para & 0x03; + max_AMPDU_len = pmlmeinfo->HT_caps.ampdu_params_info & 0x03; - min_MPDU_spacing = (pmlmeinfo->HT_caps.AMPDU_para & 0x1c) >> 2; + min_MPDU_spacing = (pmlmeinfo->HT_caps.ampdu_params_info & 0x1c) >> 2; rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing)); @@ -720,7 +720,7 @@ static void update_hw_ht_param(struct adapter *padapter) /* */ /* Config SM Power Save setting */ /* */ - pmlmeinfo->SM_PS = (le16_to_cpu(pmlmeinfo->HT_caps.HT_caps_info) & 0x0C) >> 2; + 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__); } diff --git a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c index a830752..6ed23f4 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c +++ b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c @@ -588,8 +588,8 @@ u16 rtw_get_cur_max_rate(struct adapter *adapter) /* cur_bwmod is updated by beacon, pmlmeinfo is updated by association response */ bw_40MHz = (pmlmeext->cur_bwmode && (HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH & pmlmeinfo->HT_info.infos[0])) ? 1 : 0; - short_GI_20 = (le16_to_cpu(pmlmeinfo->HT_caps.HT_caps_info) & IEEE80211_HT_CAP_SGI_20) ? 1 : 0; - short_GI_40 = (le16_to_cpu(pmlmeinfo->HT_caps.HT_caps_info) & IEEE80211_HT_CAP_SGI_40) ? 1 : 0; + short_GI_20 = (le16_to_cpu(pmlmeinfo->HT_caps.cap_info) & IEEE80211_HT_CAP_SGI_20) ? 1 : 0; + short_GI_40 = (le16_to_cpu(pmlmeinfo->HT_caps.cap_info) & IEEE80211_HT_CAP_SGI_40) ? 1 : 0; rtw_hal_get_hwreg(adapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type)); max_rate = rtw_mcs_rate( @@ -597,7 +597,7 @@ u16 rtw_get_cur_max_rate(struct adapter *adapter) bw_40MHz & (pregistrypriv->cbw40_enable), short_GI_20, short_GI_40, - pmlmeinfo->HT_caps.MCS_rate + pmlmeinfo->HT_caps.mcs.rx_mask ); } } else { diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c index 03baaa1..a16d951 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c @@ -1971,8 +1971,8 @@ unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_ rtw_hal_get_def_var(padapter, HAL_DEF_MAX_RECVBUF_SZ, &max_recvbuf_sz); /* - AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k - AMPDU_para [4:2]:Min MPDU Start Spacing + ampdu_params_info [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k + ampdu_params_info [4:2]:Min MPDU Start Spacing */ rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor); @@ -2044,7 +2044,7 @@ void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len) /* update cur_bwmode & cur_ch_offset */ if ((pregistrypriv->cbw40_enable) && - (le16_to_cpu(pmlmeinfo->HT_caps.HT_caps_info) & BIT(1)) && + (le16_to_cpu(pmlmeinfo->HT_caps.cap_info) & BIT(1)) && (pmlmeinfo->HT_info.infos[0] & BIT(2))) { int i; u8 rf_type; @@ -2054,9 +2054,9 @@ void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len) /* update the MCS rates */ for (i = 0; i < 16; i++) { if ((rf_type == RF_1T1R) || (rf_type == RF_1T2R)) - pmlmeinfo->HT_caps.MCS_rate[i] &= MCS_rate_1R[i]; + ((u8 *)&pmlmeinfo->HT_caps.mcs)[i] &= MCS_rate_1R[i]; else - pmlmeinfo->HT_caps.MCS_rate[i] &= MCS_rate_2R[i]; + ((u8 *)&pmlmeinfo->HT_caps.mcs)[i] &= MCS_rate_2R[i]; } /* switch to the 40M Hz mode according to the AP */ pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40; @@ -2074,7 +2074,7 @@ 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.HT_caps_info) & 0x0C) >> 2; + 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__); diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 5b7cb48..ed026f7 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -1132,23 +1132,23 @@ static void issue_assocreq(struct adapter *padapter) if (padapter->mlmepriv.htpriv.ht_option) { p = rtw_get_ie((pmlmeinfo->network.IEs + sizeof(struct ndis_802_11_fixed_ie)), _HT_CAPABILITY_IE_, &ie_len, (pmlmeinfo->network.IELength - sizeof(struct ndis_802_11_fixed_ie))); if ((p != NULL) && (!(is_ap_in_tkip(padapter)))) { - memcpy(&(pmlmeinfo->HT_caps), (p + 2), sizeof(struct HT_caps_element)); + memcpy(&pmlmeinfo->HT_caps, p + 2, sizeof(struct ieee80211_ht_cap)); /* to disable 40M Hz support while gd_bw_40MHz_en = 0 */ if (pregpriv->cbw40_enable == 0) - pmlmeinfo->HT_caps.HT_caps_info &= cpu_to_le16(~(BIT(6) | BIT(1))); + pmlmeinfo->HT_caps.cap_info &= cpu_to_le16(~(BIT(6) | BIT(1))); else - pmlmeinfo->HT_caps.HT_caps_info |= cpu_to_le16(BIT(1)); + pmlmeinfo->HT_caps.cap_info |= cpu_to_le16(BIT(1)); /* todo: disable SM power save mode */ - pmlmeinfo->HT_caps.HT_caps_info |= cpu_to_le16(0x000c); + pmlmeinfo->HT_caps.cap_info |= cpu_to_le16(0x000c); rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type)); switch (rf_type) { case RF_1T1R: if (pregpriv->rx_stbc) - pmlmeinfo->HT_caps.HT_caps_info |= cpu_to_le16(0x0100);/* RX STBC One spatial stream */ - memcpy(pmlmeinfo->HT_caps.MCS_rate, MCS_rate_1R, 16); + pmlmeinfo->HT_caps.cap_info |= cpu_to_le16(0x0100);/* RX STBC One spatial stream */ + memcpy((u8 *)&pmlmeinfo->HT_caps.mcs, MCS_rate_1R, 16); break; case RF_2T2R: case RF_1T2R: @@ -1157,9 +1157,9 @@ static void issue_assocreq(struct adapter *padapter) ((pmlmeext->cur_wireless_mode & WIRELESS_11_24N) && (pregpriv->rx_stbc == 0x1)) || /* enable for 2.4GHz */ (pregpriv->wifi_spec == 1)) { DBG_88E("declare supporting RX STBC\n"); - pmlmeinfo->HT_caps.HT_caps_info |= cpu_to_le16(0x0200);/* RX STBC two spatial stream */ + pmlmeinfo->HT_caps.cap_info |= cpu_to_le16(0x0200);/* RX STBC two spatial stream */ } - memcpy(pmlmeinfo->HT_caps.MCS_rate, MCS_rate_2R, 16); + memcpy(&pmlmeinfo->HT_caps.mcs, MCS_rate_2R, 16); break; } pframe = rtw_set_ie(pframe, _HT_CAPABILITY_IE_, ie_len , (u8 *)(&(pmlmeinfo->HT_caps)), &(pattrib->pktlen)); @@ -2189,10 +2189,10 @@ static u8 collect_bss_info(struct adapter *padapter, struct mlme_priv *pmlmepriv = &padapter->mlmepriv; p = rtw_get_ie(bssid->IEs + ie_offset, _HT_CAPABILITY_IE_, &len, bssid->IELength - ie_offset); if (p && len > 0) { - struct HT_caps_element *pHT_caps; - pHT_caps = (struct HT_caps_element *)(p + 2); + struct ieee80211_ht_cap *pHT_caps = + (struct ieee80211_ht_cap *)(p + 2); - if (le16_to_cpu(pHT_caps->HT_caps_info) & BIT(14)) + if (le16_to_cpu(pHT_caps->cap_info) & BIT(14)) pmlmepriv->num_FortyMHzIntolerant++; } else { pmlmepriv->num_sta_no_ht++; diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c index 8994e45..2d115d7 100644 --- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c @@ -732,17 +732,17 @@ void HT_caps_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE) HT_cap[i] &= (pIE->data[i]); } else { /* modify from fw by Thomas 2010/11/17 */ - if ((pmlmeinfo->HT_caps.AMPDU_para & 0x3) > (pIE->data[i] & 0x3)) + if ((pmlmeinfo->HT_caps.ampdu_params_info & 0x3) > (pIE->data[i] & 0x3)) max_AMPDU_len = pIE->data[i] & 0x3; else - max_AMPDU_len = pmlmeinfo->HT_caps.AMPDU_para & 0x3; + max_AMPDU_len = pmlmeinfo->HT_caps.ampdu_params_info & 0x3; - if ((pmlmeinfo->HT_caps.AMPDU_para & 0x1c) > (pIE->data[i] & 0x1c)) - min_MPDU_spacing = pmlmeinfo->HT_caps.AMPDU_para & 0x1c; + if ((pmlmeinfo->HT_caps.ampdu_params_info & 0x1c) > (pIE->data[i] & 0x1c)) + min_MPDU_spacing = pmlmeinfo->HT_caps.ampdu_params_info & 0x1c; else min_MPDU_spacing = pIE->data[i] & 0x1c; - pmlmeinfo->HT_caps.AMPDU_para = max_AMPDU_len | min_MPDU_spacing; + pmlmeinfo->HT_caps.ampdu_params_info = max_AMPDU_len | min_MPDU_spacing; } } @@ -751,9 +751,9 @@ void HT_caps_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE) /* update the MCS rates */ for (i = 0; i < 16; i++) { if ((rf_type == RF_1T1R) || (rf_type == RF_1T2R)) - pmlmeinfo->HT_caps.MCS_rate[i] &= MCS_rate_1R[i]; + ((u8 *)&pmlmeinfo->HT_caps.mcs)[i] &= MCS_rate_1R[i]; else - pmlmeinfo->HT_caps.MCS_rate[i] &= MCS_rate_2R[i]; + ((u8 *)&pmlmeinfo->HT_caps.mcs)[i] &= MCS_rate_2R[i]; } } @@ -799,9 +799,9 @@ void HTOnAssocRsp(struct adapter *padapter) AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k AMPDU_para [4:2]:Min MPDU Start Spacing */ - max_AMPDU_len = pmlmeinfo->HT_caps.AMPDU_para & 0x03; + max_AMPDU_len = pmlmeinfo->HT_caps.ampdu_params_info & 0x03; - min_MPDU_spacing = (pmlmeinfo->HT_caps.AMPDU_para & 0x1c) >> 2; + min_MPDU_spacing = (pmlmeinfo->HT_caps.ampdu_params_info & 0x1c) >> 2; rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing)); @@ -1245,16 +1245,17 @@ unsigned int update_supported_rate(unsigned char *ptn, unsigned int ptn_sz) return mask; } -unsigned int update_MSC_rate(struct HT_caps_element *pHT_caps) +unsigned int update_MSC_rate(struct ieee80211_ht_cap *pHT_caps) { unsigned int mask = 0; - mask = (pHT_caps->MCS_rate[0] << 12) | (pHT_caps->MCS_rate[1] << 20); + mask = (pHT_caps->mcs.rx_mask[0] << 12) | + (pHT_caps->mcs.rx_mask[1] << 20); return mask; } -int support_short_GI(struct adapter *padapter, struct HT_caps_element *pHT_caps) +int support_short_GI(struct adapter *padapter, struct ieee80211_ht_cap *pHT_caps) { unsigned char bit_offset; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; @@ -1268,7 +1269,7 @@ int support_short_GI(struct adapter *padapter, struct HT_caps_element *pHT_caps) bit_offset = (pmlmeext->cur_bwmode & HT_CHANNEL_WIDTH_40) ? 6 : 5; - if (__le16_to_cpu(pHT_caps->HT_caps_info) & (0x1 << bit_offset)) + if (__le16_to_cpu(pHT_caps->cap_info) & (0x1 << bit_offset)) return _SUCCESS; else return _FAIL; diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h index 9c2447e..5ee6366 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h @@ -349,7 +349,7 @@ struct mlme_ext_info { struct ADDBA_request ADDBA_req; struct WMM_para_element WMM_param; - struct HT_caps_element HT_caps; + struct ieee80211_ht_cap HT_caps; struct HT_info_element HT_info; struct wlan_bssid_ex network;/* join network or bss_network, * if in ap mode, it is the same @@ -529,12 +529,12 @@ int update_sta_support_rate(struct adapter *padapter, u8 *pvar_ie, void update_sta_info(struct adapter *padapter, struct sta_info *psta); unsigned int update_basic_rate(unsigned char *ptn, unsigned int ptn_sz); unsigned int update_supported_rate(unsigned char *ptn, unsigned int ptn_sz); -unsigned int update_MSC_rate(struct HT_caps_element *pHT_caps); +unsigned int update_MSC_rate(struct ieee80211_ht_cap *pHT_caps); void Update_RA_Entry(struct adapter *padapter, u32 mac_id); void set_sta_rate(struct adapter *padapter, struct sta_info *psta); unsigned char get_highest_rate_idx(u32 mask); -int support_short_GI(struct adapter *padapter, struct HT_caps_element *caps); +int support_short_GI(struct adapter *padapter, struct ieee80211_ht_cap *caps); unsigned int is_ap_in_tkip(struct adapter *padapter); unsigned int is_ap_in_wep(struct adapter *padapter); unsigned int should_forbid_n_rate(struct adapter *padapter); -- cgit v0.10.2 From 2976f0a5bc2a3a50c84de49f0a14c5d84439ae2b Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:22:01 +0700 Subject: staging: r8188eu: remove HT_caps_element structure This type does not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/wifi.h b/drivers/staging/rtl8188eu/include/wifi.h index 28e1dde..9e08e68 100644 --- a/drivers/staging/rtl8188eu/include/wifi.h +++ b/drivers/staging/rtl8188eu/include/wifi.h @@ -522,15 +522,6 @@ struct ieee80211_ht_addt_info { unsigned char basic_set[16]; } __packed; -struct HT_caps_element { - __le16 HT_caps_info; - unsigned char AMPDU_para; - unsigned char MCS_rate[16]; - unsigned short HT_ext_caps; - unsigned int Beamforming_caps; - unsigned char ASEL_caps; -} __packed; - struct HT_info_element { unsigned char primary_channel; unsigned char infos[5]; -- cgit v0.10.2 From 3c6ccb8094bfefb5db01026ff7a810878a58fb1b Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:22:05 +0700 Subject: staging: r8188eu: remove unused members of ht_priv structure tx_amsdu_enable and tx_amdsu_maxlen are not used in driver code. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/rtw_ht.h b/drivers/staging/rtl8188eu/include/rtw_ht.h index 7beb0b1..2b03b11 100644 --- a/drivers/staging/rtl8188eu/include/rtw_ht.h +++ b/drivers/staging/rtl8188eu/include/rtw_ht.h @@ -21,8 +21,6 @@ struct ht_priv { u32 ht_option; u32 ampdu_enable;/* for enable Tx A-MPDU */ - u32 tx_amsdu_enable;/* for enable Tx A-MSDU */ - u32 tx_amdsu_maxlen; /* 1: 8k, 0:4k ; default:8k, for tx */ u32 rx_ampdu_maxlen; /* for rx reordering ctrl win_sz, * updated when join_callback. */ u8 bwmode;/* */ -- cgit v0.10.2 From 8e5e7647b9db6991057f523b7266052c8235d09e Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:22:11 +0700 Subject: staging: r8188eu: remove rx_ampdu_maxlen member of ht_priv rx_ampdu_maxlen used only once for assigning value. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c index a16d951..9eccadc 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c @@ -2037,7 +2037,6 @@ void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len) max_ampdu_sz = ht_cap->ampdu_params_info & IEEE80211_HT_CAP_AMPDU_FACTOR; max_ampdu_sz = 1 << (max_ampdu_sz+3); /* max_ampdu_sz (kbytes); */ - phtpriv->rx_ampdu_maxlen = max_ampdu_sz; } len = 0; p = rtw_get_ie(pie+sizeof(struct ndis_802_11_fixed_ie), _HT_ADD_INFO_IE_, &len, ie_len-sizeof(struct ndis_802_11_fixed_ie)); diff --git a/drivers/staging/rtl8188eu/include/rtw_ht.h b/drivers/staging/rtl8188eu/include/rtw_ht.h index 2b03b11..0ee11ef 100644 --- a/drivers/staging/rtl8188eu/include/rtw_ht.h +++ b/drivers/staging/rtl8188eu/include/rtw_ht.h @@ -21,8 +21,6 @@ struct ht_priv { u32 ht_option; u32 ampdu_enable;/* for enable Tx A-MPDU */ - u32 rx_ampdu_maxlen; /* for rx reordering ctrl win_sz, - * updated when join_callback. */ u8 bwmode;/* */ u8 ch_offset;/* PRIME_CHNL_OFFSET */ u8 sgi;/* short GI */ -- cgit v0.10.2 From 8204ba143f3d28e22a548881b0edb0e78aac1f8d Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:22:17 +0700 Subject: staging: r8188eu: remove dead code from rtw_update_ht_cap function This code affect only to local variables that does not used later. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c index 9eccadc..4b63979 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c @@ -2001,8 +2001,6 @@ unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_ /* the function is > passive_level (in critical_section) */ void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len) { - u8 *p, max_ampdu_sz; - int len; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct ht_priv *phtpriv = &pmlmepriv->htpriv; struct registry_priv *pregistrypriv = &padapter->registrypriv; @@ -2027,20 +2025,6 @@ void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len) phtpriv->ampdu_enable = true; } - - /* check Max Rx A-MPDU Size */ - len = 0; - p = rtw_get_ie(pie+sizeof(struct ndis_802_11_fixed_ie), _HT_CAPABILITY_IE_, &len, ie_len-sizeof(struct ndis_802_11_fixed_ie)); - if (p && len > 0) { - struct ieee80211_ht_cap *ht_cap = - (struct ieee80211_ht_cap *)(p + 2); - - max_ampdu_sz = ht_cap->ampdu_params_info & IEEE80211_HT_CAP_AMPDU_FACTOR; - max_ampdu_sz = 1 << (max_ampdu_sz+3); /* max_ampdu_sz (kbytes); */ - } - len = 0; - p = rtw_get_ie(pie+sizeof(struct ndis_802_11_fixed_ie), _HT_ADD_INFO_IE_, &len, ie_len-sizeof(struct ndis_802_11_fixed_ie)); - /* update cur_bwmode & cur_ch_offset */ if ((pregistrypriv->cbw40_enable) && (le16_to_cpu(pmlmeinfo->HT_caps.cap_info) & BIT(1)) && -- cgit v0.10.2 From 7326be59671d9c62513d56a9daf031a482eeb531 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:22:24 +0700 Subject: staging:r8188eu: remove unnecessary include from include/rtw_ht.h osdep_service.h does not required in include/rtw_ht.h. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/rtw_ht.h b/drivers/staging/rtl8188eu/include/rtw_ht.h index 0ee11ef..d842ead 100644 --- a/drivers/staging/rtl8188eu/include/rtw_ht.h +++ b/drivers/staging/rtl8188eu/include/rtw_ht.h @@ -16,7 +16,6 @@ #define _RTW_HT_H_ #include <linux/ieee80211.h> -#include <osdep_service.h> struct ht_priv { u32 ht_option; -- cgit v0.10.2 From 36eb7d108e8de3097f373eb8629d8739d4fa3e74 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:22:28 +0700 Subject: staging: r8188eu: remove some structure definitions from include/ieee80211.h ieee_ibss_seq, rtw_ieee80211_hdr_qos, eapol, ieee80211_rx_stats, ieee80211_frag_entry, ieee80211_stats, ieee80211_softmac_stats, ieee80211_security, ieee80211_header_data, ieee80211_info_element_hdr, ieee80211_info_element, ieee80211_authentication, ieee80211_probe_response, ieee80211_probe_request, ieee80211_assoc_request_frame, ieee80211_assoc_response_frame structures are not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/ieee80211.h b/drivers/staging/rtl8188eu/include/ieee80211.h index b57f5d7..37a6f9d 100644 --- a/drivers/staging/rtl8188eu/include/ieee80211.h +++ b/drivers/staging/rtl8188eu/include/ieee80211.h @@ -291,14 +291,6 @@ struct sta_data { /* this is stolen from ipw2200 driver */ #define IEEE_IBSS_MAC_HASH_SIZE 31 -struct ieee_ibss_seq { - u8 mac[ETH_ALEN]; - u16 seq_num; - u16 frag_num; - unsigned long packet_time; - struct list_head list; -}; - struct rtw_ieee80211_hdr { __le16 frame_ctl; __le16 duration_id; @@ -318,17 +310,6 @@ struct rtw_ieee80211_hdr_3addr { u16 seq_ctl; } __packed; -struct rtw_ieee80211_hdr_qos { - __le16 frame_ctl; - __le16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - u16 seq_ctl; - u8 addr4[ETH_ALEN]; - u16 qc; -} __packed; - struct rtw_ieee80211_hdr_3addr_qos { __le16 frame_ctl; __le16 duration_id; @@ -339,14 +320,6 @@ struct rtw_ieee80211_hdr_3addr_qos { u16 qc; } __packed; -struct eapol { - u8 snap[6]; - u16 ethertype; - u8 version; - u8 type; - u16 length; -} __packed; - enum eap_type { EAP_PACKET = 0, EAPOL_START, @@ -552,83 +525,12 @@ struct ieee80211_snap_hdr { #define IEEE80211_NUM_CCK_RATES 4 #define IEEE80211_OFDM_SHIFT_MASK_A 4 -/* NOTE: This data is for statistical purposes; not all hardware provides this - * information for frames received. Not setting these will not cause - * any adverse affects. */ -struct ieee80211_rx_stats { - /* u32 mac_time[2]; */ - s8 rssi; - u8 signal; - u8 noise; - u8 received_channel; - u16 rate; /* in 100 kbps */ - /* u8 control; */ - u8 mask; - u8 freq; - u16 len; -}; - /* IEEE 802.11 requires that STA supports concurrent reception of at least * three fragmented frames. This define can be increased to support more * concurrent frames, but it should be noted that each entry can consume about * 2 kB of RAM and increasing cache size will slow down frame reassembly. */ #define IEEE80211_FRAG_CACHE_LEN 4 -struct ieee80211_frag_entry { - u32 first_frag_time; - uint seq; - uint last_frag; - uint qos; /* jackson */ - uint tid; /* jackson */ - struct sk_buff *skb; - u8 src_addr[ETH_ALEN]; - u8 dst_addr[ETH_ALEN]; -}; - -struct ieee80211_stats { - uint tx_unicast_frames; - uint tx_multicast_frames; - uint tx_fragments; - uint tx_unicast_octets; - uint tx_multicast_octets; - uint tx_deferred_transmissions; - uint tx_single_retry_frames; - uint tx_multiple_retry_frames; - uint tx_retry_limit_exceeded; - uint tx_discards; - uint rx_unicast_frames; - uint rx_multicast_frames; - uint rx_fragments; - uint rx_unicast_octets; - uint rx_multicast_octets; - uint rx_fcs_errors; - uint rx_discards_no_buffer; - uint tx_discards_wrong_sa; - uint rx_discards_undecryptable; - uint rx_message_in_msg_fragments; - uint rx_message_in_bad_msg_fragments; -}; - -struct ieee80211_softmac_stats { - uint rx_ass_ok; - uint rx_ass_err; - uint rx_probe_rq; - uint tx_probe_rs; - uint tx_beacons; - uint rx_auth_rq; - uint rx_auth_rs_ok; - uint rx_auth_rs_err; - uint tx_auth_rq; - uint no_auth_rs; - uint no_ass_rs; - uint tx_ass_rq; - uint rx_ass_rq; - uint tx_probe_rq; - uint reassoc; - uint swtxstop; - uint swtxawake; -}; - #define SEC_KEY_1 (1<<0) #define SEC_KEY_2 (1<<1) #define SEC_KEY_3 (1<<2) @@ -648,42 +550,6 @@ struct ieee80211_softmac_stats { #define WEP_KEYS 4 #define WEP_KEY_LEN 13 -struct ieee80211_security { - u16 active_key:2, - enabled:1, - auth_mode:2, - auth_algo:4, - unicast_uses_group:1; - u8 key_sizes[WEP_KEYS]; - u8 keys[WEP_KEYS][WEP_KEY_LEN]; - u8 level; - u16 flags; -} __packed; - -/* - - 802.11 data frame from AP - - ,-------------------------------------------------------------------. -Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 | - |------|------|---------|---------|---------|------|---------|------| -Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | frame | fcs | - | | tion | (BSSID) | | | ence | data | | - `-------------------------------------------------------------------' - -Total: 28-2340 bytes - -*/ - -struct ieee80211_header_data { - u16 frame_ctl; - u16 duration_id; - u8 addr1[6]; - u8 addr2[6]; - u8 addr3[6]; - u16 seq_ctrl; -}; - #define BEACON_PROBE_SSID_ID_POSITION 12 /* Management Frame Information Element Types */ @@ -700,71 +566,9 @@ struct ieee80211_header_data { #define MFIE_TYPE_RATES_EX 50 #define MFIE_TYPE_GENERIC 221 -struct ieee80211_info_element_hdr { - u8 id; - u8 len; -} __packed; - -struct ieee80211_info_element { - u8 id; - u8 len; - u8 data[0]; -} __packed; - -/* - * These are the data types that can make up management packets - * - u16 auth_algorithm; - u16 auth_sequence; - u16 beacon_interval; - u16 capability; - u8 current_ap[ETH_ALEN]; - u16 listen_interval; - struct { - u16 association_id:14, reserved:2; - } __packed; - u32 time_stamp[2]; - u16 reason; - u16 status; -*/ - #define IEEE80211_DEFAULT_TX_ESSID "Penguin" #define IEEE80211_DEFAULT_BASIC_RATE 10 -struct ieee80211_authentication { - struct ieee80211_header_data header; - u16 algorithm; - u16 transaction; - u16 status; - /* struct ieee80211_info_element_hdr info_element; */ -} __packed; - -struct ieee80211_probe_response { - struct ieee80211_header_data header; - u32 time_stamp[2]; - u16 beacon_interval; - u16 capability; - struct ieee80211_info_element info_element; -} __packed; - -struct ieee80211_probe_request { - struct ieee80211_header_data header; -} __packed; - -struct ieee80211_assoc_request_frame { - struct rtw_ieee80211_hdr_3addr header; - u16 capability; - u16 listen_interval; - struct ieee80211_info_element_hdr info_element; -} __packed; - -struct ieee80211_assoc_response_frame { - struct rtw_ieee80211_hdr_3addr header; - u16 capability; - u16 status; - u16 aid; -} __packed; - struct ieee80211_txb { u8 nr_frags; u8 encrypted; -- cgit v0.10.2 From 603c562096e1a0e4a6481c4d34dfc52a4e8c1c1b Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:22:32 +0700 Subject: staging: r8188eu: remove some structure definitions from Hal8188EPhyCfg.h ant_sel_ofdm and ant_sel_cck structures are not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h b/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h index 8990748..0976a76 100644 --- a/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h +++ b/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h @@ -158,24 +158,6 @@ struct bb_reg_def { * Path A and B */ }; -struct ant_sel_ofdm { - u32 r_tx_antenna:4; - u32 r_ant_l:4; - u32 r_ant_non_ht:4; - u32 r_ant_ht1:4; - u32 r_ant_ht2:4; - u32 r_ant_ht_s1:4; - u32 r_ant_non_ht_s1:4; - u32 OFDM_TXSC:2; - u32 reserved:2; -}; - -struct ant_sel_cck { - u8 r_cckrx_enable_2:2; - u8 r_cckrx_enable:2; - u8 r_ccktx_enable:4; -}; - /*------------------------------Define structure----------------------------*/ -- cgit v0.10.2 From 50a619d52c4c4d16a12d56bd40dd6d1b52f31395 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:22:37 +0700 Subject: staging: r8188eu: remove include/HalHWImg8188E_FW.h This file does not included to other sources. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/HalHWImg8188E_FW.h b/drivers/staging/rtl8188eu/include/HalHWImg8188E_FW.h deleted file mode 100644 index dbb5524..0000000 --- a/drivers/staging/rtl8188eu/include/HalHWImg8188E_FW.h +++ /dev/null @@ -1,29 +0,0 @@ -/****************************************************************************** -* -* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms of version 2 of the GNU General Public License as -* published by the Free Software Foundation. -* -* This program is distributed in the hope that it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -******************************************************************************/ - -#ifndef __INC_FW_8188E_HW_IMG_H -#define __INC_FW_8188E_HW_IMG_H - - -/****************************************************************************** -* FW_AP.TXT -******************************************************************************/ -/****************************************************************************** -* FW_WoWLAN.TXT -******************************************************************************/ -#define ArrayLength_8188E_FW_WoWLAN 15764 -extern const u8 Array_8188E_FW_WoWLAN[ArrayLength_8188E_FW_WoWLAN]; - -#endif -- cgit v0.10.2 From 21b8461f8033ec6d6e27a45cdbd70522f9cd74c6 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:22:44 +0700 Subject: staging: r8188eu: remove some structure definitions from wlan_bssdef.h ndis_802_11_ai_reqfi, ndis_802_11_ai_resfi, ndis_802_11_assoc_info, ndis_802_11_remove_key, ndis_802_11_auth_req, ndis_802_11_status_ind, ndis_802_11_auth_evt, ndis_802_11_test, pmkid_candidate, ndis_802_11_pmkid_list, ndis_802_11_auth_encrypt and ndis_802_11_cap structures are not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/wlan_bssdef.h b/drivers/staging/rtl8188eu/include/wlan_bssdef.h index 560966c..e1931dd 100644 --- a/drivers/staging/rtl8188eu/include/wlan_bssdef.h +++ b/drivers/staging/rtl8188eu/include/wlan_bssdef.h @@ -123,40 +123,10 @@ enum ndis_802_11_wep_status { #define NDIS_802_11_AI_RESFI_STATUSCODE 2 #define NDIS_802_11_AI_RESFI_ASSOCIATIONID 4 -struct ndis_802_11_ai_reqfi { - u16 Capabilities; - u16 ListenInterval; - unsigned char CurrentAPAddress[ETH_ALEN]; -}; - -struct ndis_802_11_ai_resfi { - u16 Capabilities; - u16 StatusCode; - u16 AssociationId; -}; - -struct ndis_802_11_assoc_info { - u32 Length; - u16 AvailableRequestFixedIEs; - struct ndis_802_11_ai_reqfi RequestFixedIEs; - u32 RequestIELength; - u32 OffsetRequestIEs; - u16 AvailableResponseFixedIEs; - struct ndis_802_11_ai_resfi ResponseFixedIEs; - u32 ResponseIELength; - u32 OffsetResponseIEs; -}; - enum ndis_802_11_reload_def { Ndis802_11ReloadWEPKeys }; -struct ndis_802_11_remove_key { - u32 Length; /* Length */ - u32 KeyIndex; - unsigned char BSSID[ETH_ALEN]; -}; - struct ndis_802_11_wep { u32 Length; /* Length of this structure */ u32 KeyIndex; /* 0 is the per-client key, @@ -165,12 +135,6 @@ struct ndis_802_11_wep { u8 KeyMaterial[16];/* variable len depending on above field */ }; -struct ndis_802_11_auth_req { - u32 Length; /* Length of structure */ - unsigned char Bssid[ETH_ALEN]; - u32 Flags; -}; - enum ndis_802_11_status_type { Ndis802_11StatusType_Authentication, Ndis802_11StatusType_MediaStreamMode, @@ -179,10 +143,6 @@ enum ndis_802_11_status_type { * an upper bound */ }; -struct ndis_802_11_status_ind { - enum ndis_802_11_status_type StatusType; -}; - /* mask for authentication/integrity fields */ #define NDIS_802_11_AUTH_REQUEST_AUTH_FIELDS 0x0f #define NDIS_802_11_AUTH_REQUEST_REAUTH 0x01 @@ -193,21 +153,6 @@ struct ndis_802_11_status_ind { /* MIC check time, 60 seconds. */ #define MIC_CHECK_TIME 60000000 -struct ndis_802_11_auth_evt { - struct ndis_802_11_status_ind Status; - struct ndis_802_11_auth_req Request[1]; -}; - -struct ndis_802_11_test { - u32 Length; - u32 Type; - union { - struct ndis_802_11_auth_evt AuthenticationEvent; - NDIS_802_11_RSSI RssiTrigger; - } tt; -}; - - #ifndef Ndis802_11APMode #define Ndis802_11APMode (Ndis802_11InfrastructureMax+1) #endif @@ -297,32 +242,4 @@ enum UAPSD_MAX_SP { #define NUM_PRE_AUTH_KEY 16 #define NUM_PMKID_CACHE NUM_PRE_AUTH_KEY -/* -* WPA2 -*/ - -struct pmkid_candidate { - unsigned char BSSID[ETH_ALEN]; - u32 Flags; -}; - -struct ndis_802_11_pmkid_list { - u32 Version; /* Version of the structure */ - u32 NumCandidates; /* No. of pmkid candidates */ - struct pmkid_candidate CandidateList[1]; -}; - -struct ndis_802_11_auth_encrypt { - enum ndis_802_11_auth_mode AuthModeSupported; - enum ndis_802_11_wep_status EncryptStatusSupported; -}; - -struct ndis_802_11_cap { - u32 Length; - u32 Version; - u32 NoOfPMKIDs; - u32 NoOfAuthEncryptPairsSupported; - struct ndis_802_11_auth_encrypt AuthenticationEncryptionSupported[1]; -}; - #endif /* ifndef WLAN_BSSDEF_H_ */ -- cgit v0.10.2 From c56b9a3aac9da342a1b8ff1850d64aa19ff57a8e Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:22:53 +0700 Subject: staging: r8188eu: remove agg_pkt_info structure This structure does not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/rtw_xmit.h b/drivers/staging/rtl8188eu/include/rtw_xmit.h index 7895008..cb49aca 100644 --- a/drivers/staging/rtl8188eu/include/rtw_xmit.h +++ b/drivers/staging/rtl8188eu/include/rtw_xmit.h @@ -256,11 +256,6 @@ struct hw_txqueue { int ac_tag; }; -struct agg_pkt_info { - u16 offset; - u16 pkt_len; -}; - struct xmit_priv { spinlock_t lock; struct __queue be_pending; -- cgit v0.10.2 From 87b05ed81fe26b97941e632ac07b871b23f347f9 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:22:58 +0700 Subject: staging: r8188eu: remove sha256_state structure This structure does not used in driver code. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/rtw_security.h b/drivers/staging/rtl8188eu/include/rtw_security.h index ca1247b..2663e60 100644 --- a/drivers/staging/rtl8188eu/include/rtw_security.h +++ b/drivers/staging/rtl8188eu/include/rtw_security.h @@ -164,12 +164,6 @@ struct security_priv { u8 bWepDefaultKeyIdxSet; }; -struct sha256_state { - u64 length; - u32 state[8], curlen; - u8 buf[64]; -}; - #define GET_ENCRY_ALGO(psecuritypriv, psta, encry_algo, bmcst) \ do { \ switch (psecuritypriv->dot11AuthAlgrthm) { \ -- cgit v0.10.2 From 2e9ae71939bedb6a1d28c8756c8224eedc52096f Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:23:04 +0700 Subject: staging: r8188eu: remove smooth_rssi_data structure This structure does not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/rtw_recv.h b/drivers/staging/rtl8188eu/include/rtw_recv.h index b0373b6..758cd16 100644 --- a/drivers/staging/rtl8188eu/include/rtw_recv.h +++ b/drivers/staging/rtl8188eu/include/rtw_recv.h @@ -65,13 +65,6 @@ struct stainfo_rxcache { */ }; -struct smooth_rssi_data { - u32 elements[100]; /* array to store values */ - u32 index; /* index to current array to store */ - u32 total_num; /* num of valid elements */ - u32 total_val; /* sum of valid elements */ -}; - struct signal_stat { u8 update_req; /* used to indicate */ u8 avg_val; /* avg of valid elements */ -- cgit v0.10.2 From 36b010d0087aefd7d6f06a919ecd7d1511d05f57 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:23:12 +0700 Subject: staging: r8188eu: remove odm_sta_info structure odm_sta_info structure does not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/odm.h b/drivers/staging/rtl8188eu/include/odm.h index dbebf17..21fb4225 100644 --- a/drivers/staging/rtl8188eu/include/odm.h +++ b/drivers/staging/rtl8188eu/include/odm.h @@ -315,22 +315,6 @@ enum odm_ability { ODM_PSD2AFH = 0x00000800 }; -/* 2011/20/20 MH For MP driver RT_WLAN_STA = struct sta_info */ -/* Please declare below ODM relative info in your STA info structure. */ - -struct odm_sta_info { - /* Driver Write */ - bool bUsed; /* record the sta status link or not? */ - u8 IOTPeer; /* Enum value. HT_IOT_PEER_E */ - - /* ODM Write */ - /* 1 PHY_STATUS_INFO */ - u8 RSSI_Path[4]; /* */ - u8 RSSI_Ave; - u8 RXEVM[4]; - u8 RXSNR[4]; -}; - /* 2011/10/20 MH Define Common info enum for all team. */ enum odm_common_info_def { -- cgit v0.10.2 From a24b964d1adb353622b9c93f85bb639b25cb5d08 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:23:17 +0700 Subject: staging: r8188eu: remove some structure definitions from wlan_bssdef.h cmd_msg_parm, H2C_SS_RFOFF_PARAM, joinbssrpt_parm, P2P_PS_Offload_t and P2P_PS_CTWPeriod_t structures are not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h b/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h index 4d7d804..820c045 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h @@ -49,12 +49,6 @@ enum RTL8188E_H2C_CMD_ID { H2C_RESET_TSF = 0xc0, }; -struct cmd_msg_parm { - u8 eid; /* element id */ - u8 sz; /* sz */ - u8 buf[6]; -}; - enum { PWRS }; @@ -67,15 +61,6 @@ struct setpwrmode_parm { u8 PwrState;/* AllON(0x0c),RFON(0x04),RFOFF(0x00) */ }; -struct H2C_SS_RFOFF_PARAM { - u8 ROFOn; /* 1: on, 0:off */ - u16 gpio_period; /* unit: 1024 us */ -} __packed; - -struct joinbssrpt_parm { - u8 OpMode; /* RT_MEDIA_STATUS */ -}; - struct rsvdpage_loc { u8 LocProbeRsp; u8 LocPsPoll; @@ -84,21 +69,6 @@ struct rsvdpage_loc { u8 LocBTQosNull; }; -struct P2P_PS_Offload_t { - u8 Offload_En:1; - u8 role:1; /* 1: Owner, 0: Client */ - u8 CTWindow_En:1; - u8 NoA0_En:1; - u8 NoA1_En:1; - u8 AllStaSleep:1; /* Only valid in Owner */ - u8 discovery:1; - u8 rsvd:1; -}; - -struct P2P_PS_CTWPeriod_t { - u8 CTWPeriod; /* TU */ -}; - /* host message to firmware cmd */ void rtl8188e_set_FwPwrMode_cmd(struct adapter *padapter, u8 Mode); void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *padapter, u8 mstatus); -- cgit v0.10.2 From 962bbaaf9004d701a158962a121c870c9fb5b490 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:23:26 +0700 Subject: staging: r8188eu: remove some structure definitions from rtw_cmd.h del_assocsta_parm and setstapwrstate_parm structures are not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/rtw_cmd.h b/drivers/staging/rtl8188eu/include/rtw_cmd.h index 2b53f58..e8e75f3 100644 --- a/drivers/staging/rtl8188eu/include/rtw_cmd.h +++ b/drivers/staging/rtl8188eu/include/rtw_cmd.h @@ -210,34 +210,6 @@ struct set_assocsta_rsp { }; /* - Caller Ad-Hoc/AP - - Command mode - - This is to force fw to del an sta_data entry per driver's request - - FW will invalidate the cam entry associated with it. - -*/ -struct del_assocsta_parm { - u8 addr[ETH_ALEN]; -}; - -/* -Caller Mode: AP/Ad-HoC(M) - -Notes: To notify fw that given staid has changed its power state - -Command Mode - -*/ -struct setstapwrstate_parm { - u8 staid; - u8 status; - u8 hwaddr[6]; -}; - -/* Notes: This command is used for H2C/C2H loopback testing mac[0] == 0 -- cgit v0.10.2 From 46d64dc40be544568bc547a6ffa1dfe33a88112c Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:23:36 +0700 Subject: staging: r8188eu: remove some structure definitions from rtw_event.h addba_event, event_node and c2hevent_queue structures are not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/rtw_event.h b/drivers/staging/rtl8188eu/include/rtw_event.h index 2a45581..df68948 100644 --- a/drivers/staging/rtl8188eu/include/rtw_event.h +++ b/drivers/staging/rtl8188eu/include/rtw_event.h @@ -71,10 +71,6 @@ struct stadel_event { int mac_id; }; -struct addba_event { - unsigned int tid; -}; - #define GEN_EVT_CODE(event) event ## _EVT_ struct fwevent { @@ -84,21 +80,6 @@ struct fwevent { #define C2HEVENT_SZ 32 -struct event_node { - unsigned char *node; - unsigned char evt_code; - unsigned short evt_sz; - int *caller_ff_tail; - int caller_ff_sz; -}; - -struct c2hevent_queue { - int head; - int tail; - struct event_node nodes[C2HEVENT_SZ]; - unsigned char seq; -}; - #define NETWORK_QUEUE_SZ 4 struct network_queue { -- cgit v0.10.2 From bd83585d2db1085831f744264c7db5da46896485 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Wed, 24 Aug 2016 15:23:40 +0700 Subject: staging: r8188eu: remove some structures definitions from rtw_ioctl.h oid_funs_node and oid_obj_priv structures are not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/rtw_ioctl.h b/drivers/staging/rtl8188eu/include/rtw_ioctl.h index 3a652df..a6b1c85 100644 --- a/drivers/staging/rtl8188eu/include/rtw_ioctl.h +++ b/drivers/staging/rtl8188eu/include/rtw_ioctl.h @@ -69,15 +69,6 @@ enum oid_type { SET_OID }; -struct oid_funs_node { - unsigned int oid_start; /* the starting number for OID */ - unsigned int oid_end; /* the ending number for OID */ - struct oid_obj_priv *node_array; - unsigned int array_sz; /* the size of node_array */ - int query_counter; /* count the number of query hits for this segment */ - int set_counter; /* count the number of set hits for this segment */ -}; - struct oid_par_priv { void *adapter_context; NDIS_OID oid; @@ -89,12 +80,6 @@ struct oid_par_priv { u32 dbg; }; -struct oid_obj_priv { - unsigned char dbg; /* 0: without OID debug message - * 1: with OID debug message */ - int (*oidfuns)(struct oid_par_priv *poid_par_priv); -}; - #if defined(_RTW_MP_IOCTL_C_) static int oid_null_function(struct oid_par_priv *poid_par_priv) { return NDIS_STATUS_SUCCESS; -- cgit v0.10.2 From 8c21f39cb53f1ed909e875cbab3a537b57eb97a2 Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Thu, 25 Aug 2016 11:23:08 -0400 Subject: staging: fbtft: fb_s6d02a1.c: Fix checkpatch warning Fix checkpatch.pl warning: Block comments use * on subsequent lines Block comments use a trailing */ on a separate line Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fbtft/fb_s6d02a1.c b/drivers/staging/fbtft/fb_s6d02a1.c index 3113355..774b0ff 100644 --- a/drivers/staging/fbtft/fb_s6d02a1.c +++ b/drivers/staging/fbtft/fb_s6d02a1.c @@ -113,12 +113,14 @@ static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) #define MV BIT(5) static int set_var(struct fbtft_par *par) { - /* Memory data access control (0x36h) - RGB/BGR: - 1. Mode selection pin SRGB - RGB H/W pin for color filter setting: 0=RGB, 1=BGR - 2. MADCTL RGB bit - RGB-BGR ORDER color filter panel: 0=RGB, 1=BGR */ + /* + * Memory data access control (0x36h) + * RGB/BGR: + * 1. Mode selection pin SRGB + * RGB H/W pin for color filter setting: 0=RGB, 1=BGR + * 2. MADCTL RGB bit + * RGB-BGR ORDER color filter panel: 0=RGB, 1=BGR + */ switch (par->info->var.rotate) { case 0: write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, -- cgit v0.10.2 From a40fe1555b080703907f91d4f22c059eda3f40ef Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Thu, 25 Aug 2016 11:23:27 -0400 Subject: staging: fbtft: fb_s6d1121.c: Fix checkpatch warning Fix checkpatch.pl warning: Block comments use * on subsequent lines Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fbtft/fb_s6d1121.c b/drivers/staging/fbtft/fb_s6d1121.c index d6ae76b..9b1d70b 100644 --- a/drivers/staging/fbtft/fb_s6d1121.c +++ b/drivers/staging/fbtft/fb_s6d1121.c @@ -125,10 +125,10 @@ static int set_var(struct fbtft_par *par) } /* - Gamma string format: - PKP0 PKP1 PKP2 PKP3 PKP4 PKP5 PKP6 PKP7 PKP8 PKP9 PKP10 PKP11 VRP0 VRP1 - PKN0 PKN1 PKN2 PKN3 PKN4 PKN5 PKN6 PKN7 PRN8 PRN9 PRN10 PRN11 VRN0 VRN1 -*/ + * Gamma string format: + * PKP0 PKP1 PKP2 PKP3 PKP4 PKP5 PKP6 PKP7 PKP8 PKP9 PKP10 PKP11 VRP0 VRP1 + * PKN0 PKN1 PKN2 PKN3 PKN4 PKN5 PKN6 PKN7 PRN8 PRN9 PRN10 PRN11 VRN0 VRN1 + */ #define CURVE(num, idx) curves[num * par->gamma.num_values + idx] static int set_gamma(struct fbtft_par *par, unsigned long *curves) { -- cgit v0.10.2 From b2a8bb77490e6b10244f7c94c263ed859eb9033c Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Thu, 25 Aug 2016 11:23:41 -0400 Subject: staging: fbtft: fb_ssd1289: Fix checkpatch warning Fix checkpatch.pl warning: Block comments use * on subsequent lines Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fbtft/fb_ssd1289.c b/drivers/staging/fbtft/fb_ssd1289.c index 5d5f280..25f9fbe 100644 --- a/drivers/staging/fbtft/fb_ssd1289.c +++ b/drivers/staging/fbtft/fb_ssd1289.c @@ -131,10 +131,10 @@ static int set_var(struct fbtft_par *par) } /* - Gamma string format: - VRP0 VRP1 PRP0 PRP1 PKP0 PKP1 PKP2 PKP3 PKP4 PKP5 - VRN0 VRN1 PRN0 PRN1 PKN0 PKN1 PKN2 PKN3 PKN4 PKN5 -*/ + * Gamma string format: + * VRP0 VRP1 PRP0 PRP1 PKP0 PKP1 PKP2 PKP3 PKP4 PKP5 + * VRN0 VRN1 PRN0 PRN1 PKN0 PKN1 PKN2 PKN3 PKN4 PKN5 + */ #define CURVE(num, idx) curves[num * par->gamma.num_values + idx] static int set_gamma(struct fbtft_par *par, unsigned long *curves) { -- cgit v0.10.2 From d0b6ecbedd2c247e367de3659ccf251ad3c62b9c Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Thu, 25 Aug 2016 11:23:54 -0400 Subject: staging: fbtft: fb_ssd1306: Fix checkpatch warning Fix checkpatch.pl warning: Block comments use * on subsequent lines Block comments use a trailing */ on a separate line Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fbtft/fb_ssd1306.c b/drivers/staging/fbtft/fb_ssd1306.c index e0b34a4..80fc570 100644 --- a/drivers/staging/fbtft/fb_ssd1306.c +++ b/drivers/staging/fbtft/fb_ssd1306.c @@ -27,15 +27,15 @@ #define HEIGHT 64 /* - write_reg() caveat: - - This doesn't work because D/C has to be LOW for both values: - write_reg(par, val1, val2); - - Do it like this: - write_reg(par, val1); - write_reg(par, val2); -*/ + * write_reg() caveat: + * + * This doesn't work because D/C has to be LOW for both values: + * write_reg(par, val1, val2); + * + * Do it like this: + * write_reg(par, val1); + * write_reg(par, val2); + */ /* Init sequence taken from the Adafruit SSD1306 Arduino library */ static int init_display(struct fbtft_par *par) @@ -113,8 +113,9 @@ static int init_display(struct fbtft_par *par) write_reg(par, 0xA4); /* Set Normal Display - 0 in RAM: OFF in display panel - 1 in RAM: ON in display panel */ + * 0 in RAM: OFF in display panel + * 1 in RAM: ON in display panel + */ write_reg(par, 0xA6); /* Set Display ON */ -- cgit v0.10.2 From ba6ed6431b37deaadc4f222948c8ea58b4974635 Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Thu, 25 Aug 2016 11:25:59 -0400 Subject: staging: fbtft: fb_ssd1331: Fix checkpatch warning Fix checkpatch.pl warning: Block comments use * on subsequent lines Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fbtft/fb_ssd1331.c b/drivers/staging/fbtft/fb_ssd1331.c index bd294f8..1d74ac1 100644 --- a/drivers/staging/fbtft/fb_ssd1331.c +++ b/drivers/staging/fbtft/fb_ssd1331.c @@ -102,26 +102,26 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...) } /* - Grayscale Lookup Table - GS1 - GS63 - The driver Gamma curve contains the relative values between the entries - in the Lookup table. - - From datasheet: - 8.8 Gray Scale Decoder - - there are total 180 Gamma Settings (Setting 0 to Setting 180) - available for the Gray Scale table. - - The gray scale is defined in incremental way, with reference - to the length of previous table entry: - Setting of GS1 has to be >= 0 - Setting of GS2 has to be > Setting of GS1 +1 - Setting of GS3 has to be > Setting of GS2 +1 - : - Setting of GS63 has to be > Setting of GS62 +1 - -*/ + * Grayscale Lookup Table + * GS1 - GS63 + * The driver Gamma curve contains the relative values between the entries + * in the Lookup table. + * + * From datasheet: + * 8.8 Gray Scale Decoder + * + * there are total 180 Gamma Settings (Setting 0 to Setting 180) + * available for the Gray Scale table. + * + * The gray scale is defined in incremental way, with reference + * to the length of previous table entry: + * Setting of GS1 has to be >= 0 + * Setting of GS2 has to be > Setting of GS1 +1 + * Setting of GS3 has to be > Setting of GS2 +1 + * : + * Setting of GS63 has to be > Setting of GS62 +1 + * + */ static int set_gamma(struct fbtft_par *par, unsigned long *curves) { unsigned long tmp[GAMMA_NUM * GAMMA_LEN]; -- cgit v0.10.2 From a4f368dcaf6e966389511497208c31ddbfede1cf Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Thu, 25 Aug 2016 11:26:13 -0400 Subject: staging: fbtft: fb_st7735r: Fix checkpatch warning Fix checkpatch.pl warning: Block comments use * on subsequent lines Block comments use a trailing */ on a separate line Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fbtft/fb_st7735r.c b/drivers/staging/fbtft/fb_st7735r.c index c5e51fe..6670f2b 100644 --- a/drivers/staging/fbtft/fb_st7735r.c +++ b/drivers/staging/fbtft/fb_st7735r.c @@ -33,35 +33,43 @@ static int default_init_sequence[] = { -2, 500, /* delay */ /* FRMCTR1 - frame rate control: normal mode - frame rate = fosc / (1 x 2 + 40) * (LINE + 2C + 2D) */ + * frame rate = fosc / (1 x 2 + 40) * (LINE + 2C + 2D) + */ -1, 0xB1, 0x01, 0x2C, 0x2D, /* FRMCTR2 - frame rate control: idle mode - frame rate = fosc / (1 x 2 + 40) * (LINE + 2C + 2D) */ + * frame rate = fosc / (1 x 2 + 40) * (LINE + 2C + 2D) + */ -1, 0xB2, 0x01, 0x2C, 0x2D, /* FRMCTR3 - frame rate control - partial mode - dot inversion mode, line inversion mode */ + * dot inversion mode, line inversion mode + */ -1, 0xB3, 0x01, 0x2C, 0x2D, 0x01, 0x2C, 0x2D, /* INVCTR - display inversion control - no inversion */ + * no inversion + */ -1, 0xB4, 0x07, /* PWCTR1 - Power Control - -4.6V, AUTO mode */ + * -4.6V, AUTO mode + */ -1, 0xC0, 0xA2, 0x02, 0x84, /* PWCTR2 - Power Control - VGH25 = 2.4C VGSEL = -10 VGH = 3 * AVDD */ + * VGH25 = 2.4C VGSEL = -10 VGH = 3 * AVDD + */ -1, 0xC1, 0xC5, /* PWCTR3 - Power Control - Opamp current small, Boost frequency */ + * Opamp current small, Boost frequency + */ -1, 0xC2, 0x0A, 0x00, /* PWCTR4 - Power Control - BCLK/2, Opamp current small & Medium low */ + * BCLK/2, Opamp current small & Medium low + */ -1, 0xC3, 0x8A, 0x2A, /* PWCTR5 - Power Control */ @@ -101,11 +109,12 @@ static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) static int set_var(struct fbtft_par *par) { /* MADCTL - Memory data access control - RGB/BGR: - 1. Mode selection pin SRGB - RGB H/W pin for color filter setting: 0=RGB, 1=BGR - 2. MADCTL RGB bit - RGB-BGR ORDER color filter panel: 0=RGB, 1=BGR */ + * RGB/BGR: + * 1. Mode selection pin SRGB + * RGB H/W pin for color filter setting: 0=RGB, 1=BGR + * 2. MADCTL RGB bit + * RGB-BGR ORDER color filter panel: 0=RGB, 1=BGR + */ switch (par->info->var.rotate) { case 0: write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, @@ -129,10 +138,10 @@ static int set_var(struct fbtft_par *par) } /* - Gamma string format: - VRF0P VOS0P PK0P PK1P PK2P PK3P PK4P PK5P PK6P PK7P PK8P PK9P SELV0P SELV1P SELV62P SELV63P - VRF0N VOS0N PK0N PK1N PK2N PK3N PK4N PK5N PK6N PK7N PK8N PK9N SELV0N SELV1N SELV62N SELV63N -*/ + * Gamma string format: + * VRF0P VOS0P PK0P PK1P PK2P PK3P PK4P PK5P PK6P PK7P PK8P PK9P SELV0P SELV1P SELV62P SELV63P + * VRF0N VOS0N PK0N PK1N PK2N PK3N PK4N PK5N PK6N PK7N PK8N PK9N SELV0N SELV1N SELV62N SELV63N + */ #define CURVE(num, idx) curves[num * par->gamma.num_values + idx] static int set_gamma(struct fbtft_par *par, unsigned long *curves) { -- cgit v0.10.2 From b2ac4a927034d0159714b8bb660e7841a80bc517 Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Thu, 25 Aug 2016 11:27:19 -0400 Subject: staging: fbtft: fbtft-bus: Fix checkpatch warning Fix checkpatch.pl warning: Block comments use * on subsequent lines Block comments use a trailing */ on a separate line Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fbtft/fbtft-bus.c b/drivers/staging/fbtft/fbtft-bus.c index 83505bc..ec45043 100644 --- a/drivers/staging/fbtft/fbtft-bus.c +++ b/drivers/staging/fbtft/fbtft-bus.c @@ -92,7 +92,8 @@ void fbtft_write_reg8_bus9(struct fbtft_par *par, int len, ...) if (par->spi && (par->spi->bits_per_word == 8)) { /* we're emulating 9-bit, pad start of buffer with no-ops - (assuming here that zero is a no-op) */ + * (assuming here that zero is a no-op) + */ pad = (len % 4) ? 4 - (len % 4) : 0; for (i = 0; i < pad; i++) *buf++ = 0x000; -- cgit v0.10.2 From fe9b610b375b9c3c1088b9e330b07dd1aac14418 Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Thu, 25 Aug 2016 11:31:58 -0400 Subject: staging: fbtft: fbtft_device: Fix checkpatch warning Fix checkpatch.pl warning: Block comments use * on subsequent lines Block comments use a trailing */ on a separate line Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fbtft/fbtft_device.c b/drivers/staging/fbtft/fbtft_device.c index 4d1f1e9..924abd3 100644 --- a/drivers/staging/fbtft/fbtft_device.c +++ b/drivers/staging/fbtft/fbtft_device.c @@ -1215,7 +1215,8 @@ static struct fbtft_device_display displays[] = { } }, { /* This should be the last item. - Used with the custom argument */ + * Used with the custom argument + */ .name = "", .spi = &(struct spi_board_info) { .modalias = "", @@ -1306,8 +1307,9 @@ static struct fbtft_gpio fbtft_device_param_gpios[MAX_GPIOS + 1] = { }; static void fbtft_device_pdev_release(struct device *dev) { /* Needed to silence this message: -Device 'xxx' does not have a release() function, it is broken and must be fixed -*/ + * Device 'xxx' does not have a release() function, + * it is broken and must be fixed + */ } static int spi_device_found(struct device *dev, void *data) -- cgit v0.10.2 From 7bba53e9c2d2540dcb23ad3d6c24cbd1c310068c Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Thu, 25 Aug 2016 11:32:11 -0400 Subject: staging: fbtft: fb_tls8204: Fix checkpatch warning Fix checkpatch.pl warning: Block comments use * on subsequent lines Block comments use a trailing */ on a separate line Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fbtft/fb_tls8204.c b/drivers/staging/fbtft/fb_tls8204.c index 545f7cb..ea2ddac 100644 --- a/drivers/staging/fbtft/fb_tls8204.c +++ b/drivers/staging/fbtft/fb_tls8204.c @@ -44,21 +44,21 @@ static int init_display(struct fbtft_par *par) par->fbtftops.reset(par); /* Enter extended command mode */ - write_reg(par, 0x21); /* 5:1 1 - 2:0 PD - Powerdown control: chip is active - 1:0 V - Entry mode: horizontal addressing - 0:1 H - Extended instruction set control: - extended - */ + write_reg(par, 0x21); /* 5:1 1 + * 2:0 PD - Powerdown control: chip is active + * 1:0 V - Entry mode: horizontal addressing + * 0:1 H - Extended instruction set control: + * extended + */ /* H=1 Bias system */ - write_reg(par, 0x10 | (bs & 0x7)); /* - 4:1 1 - 3:0 0 - 2:x BS2 - Bias System - 1:x BS1 - 0:x BS0 - */ + write_reg(par, 0x10 | (bs & 0x7)); + /* 4:1 1 + * 3:0 0 + * 2:x BS2 - Bias System + * 1:x BS1 + * 0:x BS0 + */ /* Set the address of the first display line. */ write_reg(par, 0x04 | (64 >> 6)); @@ -68,12 +68,12 @@ static int init_display(struct fbtft_par *par) write_reg(par, 0x20); /* H=0 Display control */ - write_reg(par, 0x08 | 4); /* - 3:1 1 - 2:1 D - DE: 10=normal mode - 1:0 0 - 0:0 E - */ + write_reg(par, 0x08 | 4); + /* 3:1 1 + * 2:1 D - DE: 10=normal mode + * 1:0 0 + * 0:0 E + */ return 0; } @@ -81,15 +81,15 @@ static int init_display(struct fbtft_par *par) static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) { /* H=0 Set X address of RAM */ - write_reg(par, 0x80); /* 7:1 1 - 6-0: X[6:0] - 0x00 - */ + write_reg(par, 0x80); /* 7:1 1 + * 6-0: X[6:0] - 0x00 + */ /* H=0 Set Y address of RAM */ - write_reg(par, 0x40); /* 7:0 0 - 6:1 1 - 2-0: Y[2:0] - 0x0 - */ + write_reg(par, 0x40); /* 7:0 0 + * 6:1 1 + * 2-0: Y[2:0] - 0x0 + */ } static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) @@ -100,8 +100,9 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) for (y = 0; y < HEIGHT / 8; y++) { u8 *buf = par->txbuf.buf; - /* The display is 102x68 but the LCD is 84x48. Set - the write pointer at the start of each row. */ + /* The display is 102x68 but the LCD is 84x48. + * Set the write pointer at the start of each row. + */ gpio_set_value(par->gpio.dc, 0); write_reg(par, 0x80 | 0); write_reg(par, 0x40 | y); -- cgit v0.10.2 From 79c222bcb72789456076a26a9bad2acc62cb2cdc Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Thu, 1 Sep 2016 11:38:38 +0530 Subject: greybus: audio: Remove unnecessary num_jack field from module_info snd_jack will be registered based on real capabilities shared by module's FW instead of parsing widgets and register it with fixed capabilities. Remove module_info->num_jack, since it is no more required. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 6ebde18..810ac62 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -707,15 +707,6 @@ static int gbaudio_init_jack(struct gbaudio_module_info *module, { int ret; - if (!module->num_jacks) - return 0; - - /* register jack(s) in case any */ - if (module->num_jacks > 1) { - dev_err(module->dev, "Currently supports max=1 jack\n"); - return -EINVAL; - } - snprintf(module->jack_name, NAME_SIZE, "GB %d Headset Jack", module->dev_id); ret = snd_soc_jack_new(codec, module->jack_name, GBCODEC_JACK_MASK, diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index 0153809..5a397b0 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -175,7 +175,6 @@ struct gbaudio_module_info { /* jack related */ char jack_name[NAME_SIZE]; char button_name[NAME_SIZE]; - int num_jacks; int jack_type; int button_status; struct snd_soc_jack headset_jack; diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index e54078a..e2fc186 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -1065,7 +1065,6 @@ static int gbaudio_tplg_create_widget(struct gbaudio_module_info *module, case snd_soc_dapm_hp: *dw = (struct snd_soc_dapm_widget) SND_SOC_DAPM_HP(w->name, gbcodec_event_hp); - module->num_jacks++; module->op_devices |= (GBAUDIO_DEVICE_OUT_WIRED_HEADSET | GBAUDIO_DEVICE_OUT_WIRED_HEADPHONE); module->ip_devices |= GBAUDIO_DEVICE_IN_WIRED_HEADSET; -- cgit v0.10.2 From a695c302b49c8bf10b5336585a533d363d6436db Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Thu, 1 Sep 2016 11:38:39 +0530 Subject: greybus: audio: Added jack_type support in topology struct This patch adds extra field jack_type to gb_audio_topology struct. Also, it defines bit fields to be used by module while defining it's jack and jack-button capabilities. Currently, module can populate a single jack and associated buttons. In case multiple jacks are supported data routing (say duplicating, etc.) should be handled within module's FW. It can populate additional mixer controls to do so. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index c4ef005..b407a26 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -2030,6 +2030,29 @@ struct gb_lights_get_flash_fault_response { #define GB_AUDIO_INVALID_INDEX 0xff +/* enum snd_jack_types */ +#define GB_AUDIO_JACK_HEADPHONE 0x0000001 +#define GB_AUDIO_JACK_MICROPHONE 0x0000002 +#define GB_AUDIO_JACK_HEADSET (GB_AUDIO_JACK_HEADPHONE | \ + GB_AUDIO_JACK_MICROPHONE) +#define GB_AUDIO_JACK_LINEOUT 0x0000004 +#define GB_AUDIO_JACK_MECHANICAL 0x0000008 +#define GB_AUDIO_JACK_VIDEOOUT 0x0000010 +#define GB_AUDIO_JACK_AVOUT (GB_AUDIO_JACK_LINEOUT | \ + GB_AUDIO_JACK_VIDEOOUT) +#define GB_AUDIO_JACK_LINEIN 0x0000020 +#define GB_AUDIO_JACK_OC_HPHL 0x0000040 +#define GB_AUDIO_JACK_OC_HPHR 0x0000080 +#define GB_AUDIO_JACK_MICROPHONE2 0x0000200 +#define GB_AUDIO_JACK_ANC_HEADPHONE (GB_AUDIO_JACK_HEADPHONE | \ + GB_AUDIO_JACK_MICROPHONE | \ + GB_AUDIO_JACK_MICROPHONE2) +/* Kept separate from switches to facilitate implementation */ +#define GB_AUDIO_JACK_BTN_0 0x4000000 +#define GB_AUDIO_JACK_BTN_1 0x2000000 +#define GB_AUDIO_JACK_BTN_2 0x1000000 +#define GB_AUDIO_JACK_BTN_3 0x0800000 + struct gb_audio_pcm { __u8 stream_name[GB_AUDIO_PCM_NAME_MAX]; __le32 formats; /* GB_AUDIO_PCM_FMT_* */ @@ -2120,6 +2143,7 @@ struct gb_audio_topology { __le32 size_controls; __le32 size_widgets; __le32 size_routes; + __le32 jack_type; /* * struct gb_audio_dai dai[num_dais]; * struct gb_audio_control controls[num_controls]; -- cgit v0.10.2 From 847175e8e660045f9366e7efd091969e8f32cc0c Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Thu, 1 Sep 2016 11:38:40 +0530 Subject: greybus: audio: Fetch jack_mask, button_mask from module's topology data Added extra fields namely jack_mask & button_mask for each module_info. These fields are required while registering jack & reporting jack events. Earlier, these were hard coded values assuming fixed capabilities say HEADSET, LINEOUT, etc. supported by GB-codec driver. Now these are computed dynamically based on module's jack capability shared via topology data. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 810ac62..2f70295 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -707,50 +707,72 @@ static int gbaudio_init_jack(struct gbaudio_module_info *module, { int ret; + if (!module->jack_mask) + return 0; + snprintf(module->jack_name, NAME_SIZE, "GB %d Headset Jack", module->dev_id); - ret = snd_soc_jack_new(codec, module->jack_name, GBCODEC_JACK_MASK, + ret = snd_soc_jack_new(codec, module->jack_name, module->jack_mask, &module->headset_jack); if (ret) { dev_err(module->dev, "Failed to create new jack\n"); return ret; } + if (!module->button_mask) + return 0; + snprintf(module->button_name, NAME_SIZE, "GB %d Button Jack", module->dev_id); - ret = snd_soc_jack_new(codec, module->button_name, - GBCODEC_JACK_BUTTON_MASK, &module->button_jack); + ret = snd_soc_jack_new(codec, module->button_name, module->button_mask, + &module->button_jack); if (ret) { dev_err(module->dev, "Failed to create button jack\n"); return ret; } - ret = snd_jack_set_key(module->button_jack.jack, SND_JACK_BTN_0, - KEY_MEDIA); - if (ret) { - dev_err(module->dev, "Failed to set BTN_0\n"); - return ret; + /* + * Currently, max 4 buttons are supported with following key mapping + * BTN_0 = KEY_MEDIA + * BTN_1 = KEY_VOICECOMMAND + * BTN_2 = KEY_VOLUMEUP + * BTN_3 = KEY_VOLUMEDOWN + */ + + if (module->button_mask & SND_JACK_BTN_0) { + ret = snd_jack_set_key(module->button_jack.jack, SND_JACK_BTN_0, + KEY_MEDIA); + if (ret) { + dev_err(module->dev, "Failed to set BTN_0\n"); + return ret; + } } - ret = snd_jack_set_key(module->button_jack.jack, SND_JACK_BTN_1, - KEY_VOICECOMMAND); - if (ret) { - dev_err(module->dev, "Failed to set BTN_1\n"); - return ret; + if (module->button_mask & SND_JACK_BTN_1) { + ret = snd_jack_set_key(module->button_jack.jack, SND_JACK_BTN_1, + KEY_VOICECOMMAND); + if (ret) { + dev_err(module->dev, "Failed to set BTN_1\n"); + return ret; + } } - ret = snd_jack_set_key(module->button_jack.jack, SND_JACK_BTN_2, - KEY_VOLUMEUP); - if (ret) { - dev_err(module->dev, "Failed to set BTN_2\n"); - return ret; + if (module->button_mask & SND_JACK_BTN_2) { + ret = snd_jack_set_key(module->button_jack.jack, SND_JACK_BTN_2, + KEY_VOLUMEUP); + if (ret) { + dev_err(module->dev, "Failed to set BTN_2\n"); + return ret; + } } - ret = snd_jack_set_key(module->button_jack.jack, SND_JACK_BTN_3, - KEY_VOLUMEDOWN); - if (ret) { - dev_err(module->dev, "Failed to set BTN_0\n"); - return ret; + if (module->button_mask & SND_JACK_BTN_3) { + ret = snd_jack_set_key(module->button_jack.jack, SND_JACK_BTN_3, + KEY_VOLUMEDOWN); + if (ret) { + dev_err(module->dev, "Failed to set BTN_0\n"); + return ret; + } } /* FIXME diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index 5a397b0..0a86459 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -73,10 +73,8 @@ enum { #define GBCODEC_APB1_MUX_REG_DEFAULT 0x00 #define GBCODEC_APB2_MUX_REG_DEFAULT 0x00 -#define GBCODEC_JACK_MASK (SND_JACK_HEADSET | SND_JACK_LINEOUT | \ - SND_JACK_LINEIN | SND_JACK_UNSUPPORTED) -#define GBCODEC_JACK_BUTTON_MASK (SND_JACK_BTN_0 | SND_JACK_BTN_1 | \ - SND_JACK_BTN_2 | SND_JACK_BTN_3) +#define GBCODEC_JACK_MASK 0x0000FFFF +#define GBCODEC_JACK_BUTTON_MASK 0xFFFF0000 static const u8 gbcodec_reg_defaults[GBCODEC_REG_COUNT] = { GBCODEC_CTL_REG_DEFAULT, @@ -176,6 +174,8 @@ struct gbaudio_module_info { char jack_name[NAME_SIZE]; char button_name[NAME_SIZE]; int jack_type; + int jack_mask; + int button_mask; int button_status; struct snd_soc_jack headset_jack; struct snd_soc_jack button_jack; diff --git a/drivers/staging/greybus/audio_module.c b/drivers/staging/greybus/audio_module.c index c217271..f764f00 100644 --- a/drivers/staging/greybus/audio_module.c +++ b/drivers/staging/greybus/audio_module.c @@ -33,22 +33,22 @@ static int gbaudio_request_jack(struct gbaudio_module_info *module, module->button_status = 0; if (button_status) snd_soc_jack_report(&module->button_jack, 0, - GBCODEC_JACK_BUTTON_MASK); + module->button_mask); snd_soc_jack_report(&module->headset_jack, 0, - GBCODEC_JACK_MASK); + module->jack_mask); return 0; } /* currently supports Headphone, Headset & Lineout only */ - report &= ~GBCODEC_JACK_MASK; - report |= req->jack_attribute & GBCODEC_JACK_MASK; + report &= ~module->jack_mask; + report |= req->jack_attribute & module->jack_mask; if (module->jack_type) dev_warn_ratelimited(module->dev, "Modifying jack from %d to %d\n", module->jack_type, report); module->jack_type = report; - snd_soc_jack_report(&module->headset_jack, report, GBCODEC_JACK_MASK); + snd_soc_jack_report(&module->headset_jack, report, module->jack_mask); return 0; } @@ -69,7 +69,7 @@ static int gbaudio_request_button(struct gbaudio_module_info *module, return -EINVAL; } - report = module->button_status & GBCODEC_JACK_BUTTON_MASK; + report = module->button_status & module->button_mask; switch (req->button_id) { case 1: @@ -100,8 +100,7 @@ static int gbaudio_request_button(struct gbaudio_module_info *module, module->button_status = report; - snd_soc_jack_report(&module->button_jack, report, - GBCODEC_JACK_BUTTON_MASK); + snd_soc_jack_report(&module->button_jack, report, module->button_mask); return 0; } diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index e2fc186..5eef536 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -1393,6 +1393,13 @@ int gbaudio_tplg_parse_data(struct gbaudio_module_info *module, } dev_dbg(module->dev, "Route parsing finished\n"); + /* parse jack capabilities */ + if (tplg_data->jack_type) { + module->jack_mask = tplg_data->jack_type & GBCODEC_JACK_MASK; + module->button_mask = tplg_data->jack_type & + GBCODEC_JACK_BUTTON_MASK; + } + return ret; } -- cgit v0.10.2 From cec89df44692fa8cff2a52542b11878ee49b0d69 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Thu, 1 Sep 2016 11:38:41 +0530 Subject: greybus: audio: Report jack events conditionally Now jack & jack-buttons are registered to snd_jack framework based on the capability shared by module's topology data. Thus, jack events should be reported to above snd framework only in case corresponding jack type is registered. This patch adds additional checks to avoid reporting fake jack events. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_module.c b/drivers/staging/greybus/audio_module.c index f764f00..d3284ab 100644 --- a/drivers/staging/greybus/audio_module.c +++ b/drivers/staging/greybus/audio_module.c @@ -21,7 +21,16 @@ static int gbaudio_request_jack(struct gbaudio_module_info *module, struct gb_audio_jack_event_request *req) { - int report, button_status; + int report; + struct snd_jack *jack = module->headset_jack.jack; + struct snd_jack *btn_jack = module->button_jack.jack; + + if (!jack) { + dev_err_ratelimited(module->dev, + "Invalid jack event received:type: %u, event: %u\n", + req->jack_attribute, req->event); + return -EINVAL; + } dev_warn_ratelimited(module->dev, "Jack Event received: type: %u, event: %u\n", @@ -29,19 +38,24 @@ static int gbaudio_request_jack(struct gbaudio_module_info *module, if (req->event == GB_AUDIO_JACK_EVENT_REMOVAL) { module->jack_type = 0; - button_status = module->button_status; - module->button_status = 0; - if (button_status) + if (btn_jack && module->button_status) { snd_soc_jack_report(&module->button_jack, 0, module->button_mask); + module->button_status = 0; + } snd_soc_jack_report(&module->headset_jack, 0, module->jack_mask); return 0; } - /* currently supports Headphone, Headset & Lineout only */ - report &= ~module->jack_mask; - report |= req->jack_attribute & module->jack_mask; + report = req->jack_attribute & module->jack_mask; + if (!report) { + dev_err_ratelimited(module->dev, + "Invalid jack event received:type: %u, event: %u\n", + req->jack_attribute, req->event); + return -EINVAL; + } + if (module->jack_type) dev_warn_ratelimited(module->dev, "Modifying jack from %d to %d\n", @@ -57,6 +71,14 @@ static int gbaudio_request_button(struct gbaudio_module_info *module, struct gb_audio_button_event_request *req) { int soc_button_id, report; + struct snd_jack *btn_jack = module->button_jack.jack; + + if (!btn_jack) { + dev_err_ratelimited(module->dev, + "Invalid button event received:type: %u, event: %u\n", + req->button_id, req->event); + return -EINVAL; + } dev_warn_ratelimited(module->dev, "Button Event received: id: %u, event: %u\n", -- cgit v0.10.2 From 6a57ddc97acb2a1d37ce94a237dc0fab2e5a3f5b Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Date: Thu, 1 Sep 2016 11:38:42 +0530 Subject: greybus: audio: Avoid reporting spurious button events Now jack-button are registered to snd framework based on capabilities populated by codec module's topology data. Thus, valid ids for button events can also vary for different modules. This patch modifies existing button reporting mechanism to avoid reporting spurious button events for invalid button ids. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_module.c b/drivers/staging/greybus/audio_module.c index d3284ab..411735d 100644 --- a/drivers/staging/greybus/audio_module.c +++ b/drivers/staging/greybus/audio_module.c @@ -92,24 +92,27 @@ static int gbaudio_request_button(struct gbaudio_module_info *module, } report = module->button_status & module->button_mask; + soc_button_id = 0; switch (req->button_id) { case 1: - soc_button_id = SND_JACK_BTN_0; + soc_button_id = SND_JACK_BTN_0 & module->button_mask; break; case 2: - soc_button_id = SND_JACK_BTN_1; + soc_button_id = SND_JACK_BTN_1 & module->button_mask; break; case 3: - soc_button_id = SND_JACK_BTN_2; + soc_button_id = SND_JACK_BTN_2 & module->button_mask; break; case 4: - soc_button_id = SND_JACK_BTN_3; + soc_button_id = SND_JACK_BTN_3 & module->button_mask; break; - default: + } + + if (!soc_button_id) { dev_err_ratelimited(module->dev, "Invalid button request received\n"); return -EINVAL; -- cgit v0.10.2 From 4e013b64c1ee3a60438caa0df6bf79664e0272bc Mon Sep 17 00:00:00 2001 From: Philip Yang <yang_philip@projectara.com> Date: Wed, 31 Aug 2016 11:11:18 +0800 Subject: greybus: power_supply: Add runtime pm support Modify Power_supply greybus driver to support runtime PM framework. During charging state, the driver will block remote device of suspending, and then enables runtime suspend when remote device is in none chargin state. Testing Done: Compiled and verified on EVT2, EVT2 1x2 GPB test module and Device class daughter board. Signed-off-by: Philip Yang <yang_philip@projectara.com> Reviewed-by: Rui Miguel Silva <rui.silva@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c index 578d38b..68dd3d2 100644 --- a/drivers/staging/greybus/power_supply.c +++ b/drivers/staging/greybus/power_supply.c @@ -50,6 +50,8 @@ struct gb_power_supply { bool changed; struct gb_power_supply_prop *props; enum power_supply_property *props_raw; + bool pm_acquired; + struct mutex supply_lock; }; struct gb_power_supplies { @@ -75,10 +77,13 @@ struct gb_power_supply_changes { struct gb_power_supply_prop *prop); }; +static void gb_power_supply_state_change(struct gb_power_supply *gbpsy, + struct gb_power_supply_prop *prop); + static const struct gb_power_supply_changes psy_props_changes[] = { { .prop = GB_POWER_SUPPLY_PROP_STATUS, .tolerance_change = 0, - .prop_changed = NULL, + .prop_changed = gb_power_supply_state_change, }, { .prop = GB_POWER_SUPPLY_PROP_TEMP, .tolerance_change = 500, @@ -349,6 +354,40 @@ static void __gb_power_supply_changed(struct gb_power_supply *gbpsy) } #endif +static void gb_power_supply_state_change(struct gb_power_supply *gbpsy, + struct gb_power_supply_prop *prop) +{ + struct gb_connection *connection = get_conn_from_psy(gbpsy); + int ret; + + /* + * Check gbpsy->pm_acquired to make sure only one pair of 'get_sync' + * and 'put_autosuspend' runtime pm call for state property change. + */ + mutex_lock(&gbpsy->supply_lock); + + if ((prop->val == GB_POWER_SUPPLY_STATUS_CHARGING) && + !gbpsy->pm_acquired) { + ret = gb_pm_runtime_get_sync(connection->bundle); + if (ret) + dev_err(&connection->bundle->dev, + "Fail to set wake lock for charging state\n"); + else + gbpsy->pm_acquired = true; + } else { + if (gbpsy->pm_acquired) { + ret = gb_pm_runtime_put_autosuspend(connection->bundle); + if (ret) + dev_err(&connection->bundle->dev, + "Fail to set wake unlock for none charging\n"); + else + gbpsy->pm_acquired = false; + } + } + + mutex_unlock(&gbpsy->supply_lock); +} + static void check_changed(struct gb_power_supply *gbpsy, struct gb_power_supply_prop *prop) { @@ -655,12 +694,17 @@ static int is_cache_valid(struct gb_power_supply *gbpsy) static int gb_power_supply_status_get(struct gb_power_supply *gbpsy) { + struct gb_connection *connection = get_conn_from_psy(gbpsy); int ret = 0; int i; if (is_cache_valid(gbpsy)) return 0; + ret = gb_pm_runtime_get_sync(connection->bundle); + if (ret) + return ret; + for (i = 0; i < gbpsy->properties_count; i++) { ret = __gb_power_supply_property_update(gbpsy, gbpsy->props[i].prop); @@ -671,6 +715,7 @@ static int gb_power_supply_status_get(struct gb_power_supply *gbpsy) if (ret == 0) gbpsy->last_update = jiffies; + gb_pm_runtime_put_autosuspend(connection->bundle); return ret; } @@ -725,9 +770,16 @@ static int gb_power_supply_property_set(struct gb_power_supply *gbpsy, struct gb_power_supply_set_property_request req; int ret; + ret = gb_pm_runtime_get_sync(connection->bundle); + if (ret) + return ret; + prop = get_psy_prop(gbpsy, psp); - if (!prop) - return -EINVAL; + if (!prop) { + ret = -EINVAL; + goto out; + } + req.psy_id = gbpsy->id; req.property = prop->gb_prop; req.prop_val = cpu_to_le32((s32)val); @@ -741,6 +793,7 @@ static int gb_power_supply_property_set(struct gb_power_supply *gbpsy, prop->val = val; out: + gb_pm_runtime_put_autosuspend(connection->bundle); return ret; } @@ -883,6 +936,8 @@ static int gb_power_supply_enable(struct gb_power_supply *gbpsy) if (ret < 0) return ret; + mutex_init(&gbpsy->supply_lock); + ret = gb_power_supply_register(gbpsy); if (ret < 0) return ret; @@ -1067,6 +1122,7 @@ static int gb_power_supply_probe(struct gb_bundle *bundle, if (ret < 0) goto error_connection_disable; + gb_pm_runtime_put_autosuspend(bundle); return 0; error_connection_disable: -- cgit v0.10.2 From 6fa4d3d5bbbd32dd7d70868c48abd7818134efa7 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@hovoldconsulting.com> Date: Wed, 31 Aug 2016 10:58:53 +0200 Subject: greybus: greybus_protocols: remove svc key-event type Remove the deprecated svc key-event type, which has already been removed from the specification. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index b407a26..6395783 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -998,7 +998,6 @@ struct gb_spi_transfer_response { #define GB_SVC_TYPE_TIMESYNC_AUTHORITATIVE 0x0f #define GB_SVC_TYPE_INTF_SET_PWRM 0x10 #define GB_SVC_TYPE_INTF_EJECT 0x11 -#define GB_SVC_TYPE_KEY_EVENT 0x12 #define GB_SVC_TYPE_PING 0x13 #define GB_SVC_TYPE_PWRMON_RAIL_COUNT_GET 0x14 #define GB_SVC_TYPE_PWRMON_RAIL_NAMES_GET 0x15 -- cgit v0.10.2 From 4de02894a28bfc0e3315fc364b3310aacd8cd48a Mon Sep 17 00:00:00 2001 From: Sandeep Patil <sspatil@google.com> Date: Mon, 15 Aug 2016 14:20:54 -0700 Subject: greybus: es2: use a single bulk ep pair for all greybus data This matches a corresponding firmware change to declare a single BULK EP pair for all greybus traffic and 1 BULK IN ep for ARPC. Thus, avoiding URB submittions for all the other unused BULK IN endpoints on the HOST side that took considerable amount of bus time. Testing Done: Tested with modified AP<->APB1 loopback test and also with GPBridge modules to ensure there are no regressions Signed-off-by: Sandeep Patil <sspatil@google.com> Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index df10479..97a3343 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -47,7 +47,7 @@ MODULE_DEVICE_TABLE(usb, id_table); #define APB1_LOG_SIZE SZ_16K /* Number of bulk in and bulk out couple */ -#define NUM_BULKS 7 +#define NUM_BULKS 1 /* Expected number of bulk out endpoints */ #define NUM_BULKS_OUT NUM_BULKS -- cgit v0.10.2 From b6c1bd3a8e466759fbfd2a649a9058d51ff136c0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Wed, 17 Aug 2016 11:07:28 +0200 Subject: greybus: es2: remove #if 0 code These functions were never used, and we are about to remove the structures it was trying to reference, so let's remove it to get it out of the way. Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 97a3343..cef6510 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -208,65 +208,6 @@ static int cport_to_ep_pair(struct es2_ap_dev *es2, u16 cport_id) return es2->cport_to_ep[cport_id]; } -/* Disable for now until we work all of this out to keep a warning-free build */ -#if 0 -/* Test if the endpoints pair is already mapped to a cport */ -static int ep_pair_in_use(struct es2_ap_dev *es2, int ep_pair) -{ - int i; - - for (i = 0; i < es2->hd->num_cports; i++) { - if (es2->cport_to_ep[i] == ep_pair) - return 1; - } - return 0; -} - -/* Configure the endpoint mapping and send the request to APBridge */ -static int map_cport_to_ep(struct es2_ap_dev *es2, - u16 cport_id, int ep_pair) -{ - int retval; - struct cport_to_ep *cport_to_ep; - - if (ep_pair < 0 || ep_pair >= NUM_BULKS) - return -EINVAL; - if (cport_id >= es2->hd->num_cports) - return -EINVAL; - if (ep_pair && ep_pair_in_use(es2, ep_pair)) - return -EINVAL; - - cport_to_ep = kmalloc(sizeof(*cport_to_ep), GFP_KERNEL); - if (!cport_to_ep) - return -ENOMEM; - - es2->cport_to_ep[cport_id] = ep_pair; - cport_to_ep->cport_id = cpu_to_le16(cport_id); - cport_to_ep->endpoint_in = es2->cport_in[ep_pair].endpoint; - cport_to_ep->endpoint_out = es2->cport_out[ep_pair].endpoint; - - retval = usb_control_msg(es2->usb_dev, - usb_sndctrlpipe(es2->usb_dev, 0), - GB_APB_REQUEST_EP_MAPPING, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - 0x00, 0x00, - (char *)cport_to_ep, - sizeof(*cport_to_ep), - ES2_USB_CTRL_TIMEOUT); - if (retval == sizeof(*cport_to_ep)) - retval = 0; - kfree(cport_to_ep); - - return retval; -} - -/* Unmap a cport: use the muxed endpoints pair */ -static int unmap_cport(struct es2_ap_dev *es2, u16 cport_id) -{ - return map_cport_to_ep(es2, cport_id, 0); -} -#endif - static int output_sync(struct es2_ap_dev *es2, void *req, u16 size, u8 cmd) { struct usb_device *udev = es2->usb_dev; -- cgit v0.10.2 From 84d5077cae3e00611b7da6491f363e6ed95e073a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Wed, 17 Aug 2016 11:10:37 +0200 Subject: greybus: es2: remove struct cport_to_ep We were not really using this structure at all, it was only returning '0' when asked what cport matched to what pair, so remove it all. Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index cef6510..8560102 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -130,8 +130,6 @@ struct es2_ap_dev { bool cdsi1_in_use; - int *cport_to_ep; - struct task_struct *apb_log_task; struct dentry *apb_log_dentry; struct dentry *apb_log_enable_dentry; @@ -147,18 +145,6 @@ struct es2_ap_dev { }; /** - * cport_to_ep - information about cport to endpoints mapping - * @cport_id: the id of cport to map to endpoints - * @endpoint_in: the endpoint number to use for in transfer - * @endpoint_out: he endpoint number to use for out transfer - */ -struct cport_to_ep { - __le16 cport_id; - __u8 endpoint_in; - __u8 endpoint_out; -}; - -/** * timesync_enable_request - Enable timesync in an APBridge * @count: number of TimeSync Pulses to expect * @frame_time: the initial FrameTime at the first TimeSync Pulse @@ -200,14 +186,6 @@ static void usb_log_disable(struct es2_ap_dev *es2); static int arpc_sync(struct es2_ap_dev *es2, u8 type, void *payload, size_t size, int *result, unsigned int timeout); -/* Get the endpoints pair mapped to the cport */ -static int cport_to_ep_pair(struct es2_ap_dev *es2, u16 cport_id) -{ - if (cport_id >= es2->hd->num_cports) - return 0; - return es2->cport_to_ep[cport_id]; -} - static int output_sync(struct es2_ap_dev *es2, void *req, u16 size, u8 cmd) { struct usb_device *udev = es2->usb_dev; @@ -460,7 +438,6 @@ static int message_send(struct gb_host_device *hd, u16 cport_id, size_t buffer_size; int retval; struct urb *urb; - int ep_pair; unsigned long flags; /* @@ -487,10 +464,9 @@ static int message_send(struct gb_host_device *hd, u16 cport_id, buffer_size = sizeof(*message->header) + message->payload_size; - ep_pair = cport_to_ep_pair(es2, cport_id); usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, - es2->cport_out[ep_pair].endpoint), + es2->cport_out[0].endpoint), message->buffer, buffer_size, cport_out_callback, message); urb->transfer_flags |= URB_ZERO_PACKET; @@ -993,8 +969,6 @@ static void es2_destroy(struct es2_ap_dev *es2) } } - kfree(es2->cport_to_ep); - /* release reserved CDSI0 and CDSI1 cports */ gb_hd_cport_release_reserved(es2->hd, ES2_CPORT_CDSI1); gb_hd_cport_release_reserved(es2->hd, ES2_CPORT_CDSI0); @@ -1487,13 +1461,6 @@ static int ap_probe(struct usb_interface *interface, if (retval) goto error; - es2->cport_to_ep = kcalloc(hd->num_cports, sizeof(*es2->cport_to_ep), - GFP_KERNEL); - if (!es2->cport_to_ep) { - retval = -ENOMEM; - goto error; - } - /* find all bulk endpoints */ iface_desc = interface->cur_altsetting; for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { -- cgit v0.10.2 From 403074b50b66f1a6cd038bd9f60119d69916a928 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Wed, 17 Aug 2016 16:27:49 +0200 Subject: greybus: es2: remove bulk_out array We only care about one bulk out endpoint, the first one, so remove the pretense of keeping an array of these things. Just grab the first one in the list and run away! Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 8560102..c6c0786 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -83,13 +83,6 @@ struct es2_cport_in { u8 *buffer[NUM_CPORT_IN_URB]; }; -/* - * @endpoint: bulk out endpoint for CPort data - */ -struct es2_cport_out { - __u8 endpoint; -}; - /** * es2_ap_dev - ES2 USB Bridge to AP structure * @usb_dev: pointer to the USB device we are. @@ -97,7 +90,7 @@ struct es2_cport_out { * @hd: pointer to our gb_host_device structure * @cport_in: endpoint, urbs and buffer for cport in messages - * @cport_out: endpoint for for cport out messages + * @cport_out_endpoint: endpoint for for cport out messages * @cport_out_urb: array of urbs for the CPort out messages * @cport_out_urb_busy: array of flags to see if the @cport_out_urb is busy or * not. @@ -122,7 +115,7 @@ struct es2_ap_dev { struct gb_host_device *hd; struct es2_cport_in cport_in[NUM_BULKS]; - struct es2_cport_out cport_out[NUM_BULKS]; + __u8 cport_out_endpoint; struct urb *cport_out_urb[NUM_CPORT_OUT_URB]; bool cport_out_urb_busy[NUM_CPORT_OUT_URB]; bool cport_out_urb_cancelled[NUM_CPORT_OUT_URB]; @@ -466,7 +459,7 @@ static int message_send(struct gb_host_device *hd, u16 cport_id, usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, - es2->cport_out[0].endpoint), + es2->cport_out_endpoint), message->buffer, buffer_size, cport_out_callback, message); urb->transfer_flags |= URB_ZERO_PACKET; @@ -1420,10 +1413,10 @@ static int ap_probe(struct usb_interface *interface, struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; int bulk_in = 0; - int bulk_out = 0; int retval; int i; int num_cports; + bool bulk_out_found = false; udev = usb_get_dev(interface_to_usbdev(interface)); @@ -1474,16 +1467,17 @@ static int ap_probe(struct usb_interface *interface, es2->arpc_endpoint_in = endpoint->bEndpointAddress; bulk_in++; - } else if (usb_endpoint_is_bulk_out(endpoint)) { - es2->cport_out[bulk_out++].endpoint = - endpoint->bEndpointAddress; + } else if (usb_endpoint_is_bulk_out(endpoint) && + (!bulk_out_found)) { + es2->cport_out_endpoint = endpoint->bEndpointAddress; + bulk_out_found = true; } else { dev_err(&udev->dev, "Unknown endpoint type found, address 0x%02x\n", endpoint->bEndpointAddress); } } - if (bulk_in != NUM_BULKS_IN || bulk_out != NUM_BULKS_OUT) { + if (bulk_in != NUM_BULKS_IN || !bulk_out_found) { dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n"); retval = -ENODEV; goto error; -- cgit v0.10.2 From 7330c48ec09367e8da65e3ebf642b6c37bf244e3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Wed, 17 Aug 2016 16:37:39 +0200 Subject: greybus: es2: remove bulk_in array We only care about one bulk IN endpoint for cports, and one for ARPC, so drop the array of bulk IN endpoints to simplify things. Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index c6c0786..69123b7 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -114,7 +114,7 @@ struct es2_ap_dev { struct usb_interface *usb_intf; struct gb_host_device *hd; - struct es2_cport_in cport_in[NUM_BULKS]; + struct es2_cport_in cport_in; __u8 cport_out_endpoint; struct urb *cport_out_urb[NUM_CPORT_OUT_URB]; bool cport_out_urb_busy[NUM_CPORT_OUT_URB]; @@ -920,7 +920,6 @@ static int check_urb_status(struct urb *urb) static void es2_destroy(struct es2_ap_dev *es2) { struct usb_device *udev; - int bulk_in; int i; debugfs_remove(es2->apb_log_enable_dentry); @@ -948,18 +947,10 @@ static void es2_destroy(struct es2_ap_dev *es2) es2->arpc_buffer[i] = NULL; } - for (bulk_in = 0; bulk_in < NUM_BULKS; bulk_in++) { - struct es2_cport_in *cport_in = &es2->cport_in[bulk_in]; - - for (i = 0; i < NUM_CPORT_IN_URB; ++i) { - struct urb *urb = cport_in->urb[i]; - - if (!urb) - break; - usb_free_urb(urb); - kfree(cport_in->buffer[i]); - cport_in->buffer[i] = NULL; - } + for (i = 0; i < NUM_CPORT_IN_URB; ++i) { + usb_free_urb(es2->cport_in.urb[i]); + kfree(es2->cport_in.buffer[i]); + es2->cport_in.buffer[i] = NULL; } /* release reserved CDSI0 and CDSI1 cports */ @@ -1412,11 +1403,12 @@ static int ap_probe(struct usb_interface *interface, struct usb_device *udev; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; - int bulk_in = 0; int retval; int i; int num_cports; bool bulk_out_found = false; + bool bulk_in_found = false; + bool arpc_in_found = false; udev = usb_get_dev(interface_to_usbdev(interface)); @@ -1460,13 +1452,15 @@ static int ap_probe(struct usb_interface *interface, endpoint = &iface_desc->endpoint[i].desc; if (usb_endpoint_is_bulk_in(endpoint)) { - if (bulk_in < NUM_BULKS) - es2->cport_in[bulk_in].endpoint = + if (!bulk_in_found) { + es2->cport_in.endpoint = endpoint->bEndpointAddress; - else + bulk_in_found = true; + } else if (!arpc_in_found) { es2->arpc_endpoint_in = endpoint->bEndpointAddress; - bulk_in++; + arpc_in_found = true; + } } else if (usb_endpoint_is_bulk_out(endpoint) && (!bulk_out_found)) { es2->cport_out_endpoint = endpoint->bEndpointAddress; @@ -1477,41 +1471,36 @@ static int ap_probe(struct usb_interface *interface, endpoint->bEndpointAddress); } } - if (bulk_in != NUM_BULKS_IN || !bulk_out_found) { + if (!bulk_in_found || !arpc_in_found || !bulk_out_found) { dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n"); retval = -ENODEV; goto error; } /* Allocate buffers for our cport in messages */ - for (bulk_in = 0; bulk_in < NUM_BULKS; bulk_in++) { - struct es2_cport_in *cport_in = &es2->cport_in[bulk_in]; - - for (i = 0; i < NUM_CPORT_IN_URB; ++i) { - struct urb *urb; - u8 *buffer; + for (i = 0; i < NUM_CPORT_IN_URB; ++i) { + struct urb *urb; + u8 *buffer; - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - retval = -ENOMEM; - goto error; - } - cport_in->urb[i] = urb; + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + retval = -ENOMEM; + goto error; + } + es2->cport_in.urb[i] = urb; - buffer = kmalloc(ES2_GBUF_MSG_SIZE_MAX, GFP_KERNEL); - if (!buffer) { - retval = -ENOMEM; - goto error; - } + buffer = kmalloc(ES2_GBUF_MSG_SIZE_MAX, GFP_KERNEL); + if (!buffer) { + retval = -ENOMEM; + goto error; + } - usb_fill_bulk_urb(urb, udev, - usb_rcvbulkpipe(udev, - cport_in->endpoint), - buffer, ES2_GBUF_MSG_SIZE_MAX, - cport_in_callback, hd); + usb_fill_bulk_urb(urb, udev, + usb_rcvbulkpipe(udev, es2->cport_in.endpoint), + buffer, ES2_GBUF_MSG_SIZE_MAX, + cport_in_callback, hd); - cport_in->buffer[i] = buffer; - } + es2->cport_in.buffer[i] = buffer; } /* Allocate buffers for ARPC in messages */ @@ -1571,17 +1560,13 @@ static int ap_probe(struct usb_interface *interface, if (retval) goto err_disable_arpc_in; - for (i = 0; i < NUM_BULKS; ++i) { - retval = es2_cport_in_enable(es2, &es2->cport_in[i]); - if (retval) - goto err_disable_cport_in; - } + retval = es2_cport_in_enable(es2, &es2->cport_in); + if (retval) + goto err_hd_del; return 0; -err_disable_cport_in: - for (--i; i >= 0; --i) - es2_cport_in_disable(es2, &es2->cport_in[i]); +err_hd_del: gb_hd_del(hd); err_disable_arpc_in: es2_arpc_in_disable(es2); @@ -1594,12 +1579,10 @@ error: static void ap_disconnect(struct usb_interface *interface) { struct es2_ap_dev *es2 = usb_get_intfdata(interface); - int i; gb_hd_del(es2->hd); - for (i = 0; i < NUM_BULKS; ++i) - es2_cport_in_disable(es2, &es2->cport_in[i]); + es2_cport_in_disable(es2, &es2->cport_in); es2_arpc_in_disable(es2); es2_destroy(es2); -- cgit v0.10.2 From fc994f0f8363eb4c50361800c7d2217eb0306014 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Wed, 17 Aug 2016 13:21:51 +0200 Subject: greybus: es2: remove unneeded BULK_* #defines We don't need the defines for the number of bulk in or out endpoints anymore, as the driver just grabs the first ones it finds and runs with it. Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 69123b7..4f10acc 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -46,15 +46,6 @@ MODULE_DEVICE_TABLE(usb, id_table); #define APB1_LOG_SIZE SZ_16K -/* Number of bulk in and bulk out couple */ -#define NUM_BULKS 1 - -/* Expected number of bulk out endpoints */ -#define NUM_BULKS_OUT NUM_BULKS - -/* Expected number of bulk in endpoints (including ARPC endpoint) */ -#define NUM_BULKS_IN (NUM_BULKS + 1) - /* * Number of CPort IN urbs in flight at any point in time. * Adjust if we are having stalls in the USB buffer due to not enough urbs in @@ -65,7 +56,7 @@ MODULE_DEVICE_TABLE(usb, id_table); /* Number of CPort OUT urbs in flight at any point in time. * Adjust if we get messages saying we are out of urbs in the system log. */ -#define NUM_CPORT_OUT_URB (8 * NUM_BULKS) +#define NUM_CPORT_OUT_URB 8 /* * Number of ARPC in urbs in flight at any point in time. -- cgit v0.10.2 From 1521eb6b6995dd8db57c96d36bc3c64b2a7da3b1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Wed, 17 Aug 2016 16:44:11 +0200 Subject: greybus: es2: No need to check before freeing an urb usb_kill_urb() and usb_free_urb() can be called with NULL pointers, so no need to check before calling them. Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 4f10acc..6cd3a64 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -911,6 +911,7 @@ static int check_urb_status(struct urb *urb) static void es2_destroy(struct es2_ap_dev *es2) { struct usb_device *udev; + struct urb *urb; int i; debugfs_remove(es2->apb_log_enable_dentry); @@ -918,10 +919,7 @@ static void es2_destroy(struct es2_ap_dev *es2) /* Tear down everything! */ for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - struct urb *urb = es2->cport_out_urb[i]; - - if (!urb) - break; + urb = es2->cport_out_urb[i]; usb_kill_urb(urb); usb_free_urb(urb); es2->cport_out_urb[i] = NULL; @@ -929,11 +927,7 @@ static void es2_destroy(struct es2_ap_dev *es2) } for (i = 0; i < NUM_ARPC_IN_URB; ++i) { - struct urb *urb = es2->arpc_urb[i]; - - if (!urb) - break; - usb_free_urb(urb); + usb_free_urb(es2->arpc_urb[i]); kfree(es2->arpc_buffer[i]); es2->arpc_buffer[i] = NULL; } -- cgit v0.10.2 From 272291008fc55e7692f3219b0f85ee1e6ffdea71 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Wed, 17 Aug 2016 17:11:04 +0200 Subject: greybus: es2: fix up usb probe error messages Properly report which endpoints are being ignored and which ones are "unknown" to the driver. Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 6cd3a64..6cb13fc 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -1388,6 +1388,7 @@ static int ap_probe(struct usb_interface *interface, struct usb_device *udev; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; + __u8 ep_addr; int retval; int i; int num_cports; @@ -1435,26 +1436,36 @@ static int ap_probe(struct usb_interface *interface, iface_desc = interface->cur_altsetting; for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; + ep_addr = endpoint->bEndpointAddress; if (usb_endpoint_is_bulk_in(endpoint)) { if (!bulk_in_found) { - es2->cport_in.endpoint = - endpoint->bEndpointAddress; + es2->cport_in.endpoint = ep_addr; bulk_in_found = true; } else if (!arpc_in_found) { - es2->arpc_endpoint_in = - endpoint->bEndpointAddress; + es2->arpc_endpoint_in = ep_addr; arpc_in_found = true; + } else { + dev_warn(&udev->dev, + "Unused bulk IN endpoint found: 0x%02x\n", + ep_addr); } - } else if (usb_endpoint_is_bulk_out(endpoint) && - (!bulk_out_found)) { - es2->cport_out_endpoint = endpoint->bEndpointAddress; - bulk_out_found = true; - } else { - dev_err(&udev->dev, - "Unknown endpoint type found, address 0x%02x\n", - endpoint->bEndpointAddress); + continue; } + if (usb_endpoint_is_bulk_out(endpoint)) { + if (!bulk_out_found) { + es2->cport_out_endpoint = ep_addr; + bulk_out_found = true; + } else { + dev_warn(&udev->dev, + "Unused bulk OUT endpoint found: 0x%02x\n", + ep_addr); + } + continue; + } + dev_warn(&udev->dev, + "Unknown endpoint type found, address 0x%02x\n", + ep_addr); } if (!bulk_in_found || !arpc_in_found || !bulk_out_found) { dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n"); -- cgit v0.10.2 From 28fec2e65f70a20082834f6f6cdbfa94545d2668 Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Fri, 26 Aug 2016 19:12:52 -0400 Subject: staging: comedi: cb_pcidas64.c: Fix checkpatch warning Fix checkpatch.pl warning: Block comments use * on subsequent lines Block comments use a trailing */ on a separate line Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index aae839e..281dc56 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -1,34 +1,34 @@ /* - comedi/drivers/cb_pcidas64.c - This is a driver for the ComputerBoards/MeasurementComputing PCI-DAS - 64xx, 60xx, and 4020 cards. - - Author: Frank Mori Hess <fmhess@users.sourceforge.net> - Copyright (C) 2001, 2002 Frank Mori Hess - - Thanks also go to the following people: - - Steve Rosenbluth, for providing the source code for - his pci-das6402 driver, and source code for working QNX pci-6402 - drivers by Greg Laird and Mariusz Bogacz. None of the code was - used directly here, but it was useful as an additional source of - documentation on how to program the boards. - - John Sims, for much testing and feedback on pcidas-4020 support. - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1997-8 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * comedi/drivers/cb_pcidas64.c + * This is a driver for the ComputerBoards/MeasurementComputing PCI-DAS + * 64xx, 60xx, and 4020 cards. + * + * Author: Frank Mori Hess <fmhess@users.sourceforge.net> + * Copyright (C) 2001, 2002 Frank Mori Hess + * + * Thanks also go to the following people: + * + * Steve Rosenbluth, for providing the source code for + * his pci-das6402 driver, and source code for working QNX pci-6402 + * drivers by Greg Laird and Mariusz Bogacz. None of the code was + * used directly here, but it was useful as an additional source of + * documentation on how to program the boards. + * + * John Sims, for much testing and feedback on pcidas-4020 support. + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-8 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ /* * Driver: cb_pcidas64 @@ -66,19 +66,18 @@ */ /* - -TODO: - make it return error if user attempts an ai command that uses the - external queue, and an ao command simultaneously user counter subdevice - there are a number of boards this driver will support when they are - fully released, but does not yet since the pci device id numbers - are not yet available. - - support prescaled 100khz clock for slow pacing (not available on 6000 - series?) - - make ao fifo size adjustable like ai fifo -*/ + * TODO: + * make it return error if user attempts an ai command that uses the + * external queue, and an ao command simultaneously user counter subdevice + * there are a number of boards this driver will support when they are + * fully released, but does not yet since the pci device id numbers + * are not yet available. + * + * support prescaled 100khz clock for slow pacing (not available on 6000 + * series?) + * + * make ao fifo size adjustable like ai fifo + */ #include <linux/module.h> #include <linux/delay.h> @@ -90,53 +89,55 @@ TODO: #include "plx9080.h" #define TIMER_BASE 25 /* 40MHz master clock */ -/* 100kHz 'prescaled' clock for slow acquisition, - * maybe I'll support this someday */ +/* + * 100kHz 'prescaled' clock for slow acquisition, + * maybe I'll support this someday + */ #define PRESCALED_TIMER_BASE 10000 #define DMA_BUFFER_SIZE 0x1000 -/* maximum value that can be loaded into board's 24-bit counters*/ +/* maximum value that can be loaded into board's 24-bit counters */ static const int max_counter_value = 0xffffff; /* PCI-DAS64xxx base addresses */ /* devpriv->main_iobase registers */ enum write_only_registers { - INTR_ENABLE_REG = 0x0, /* interrupt enable register */ - HW_CONFIG_REG = 0x2, /* hardware config register */ + INTR_ENABLE_REG = 0x0, /* interrupt enable register */ + HW_CONFIG_REG = 0x2, /* hardware config register */ DAQ_SYNC_REG = 0xc, DAQ_ATRIG_LOW_4020_REG = 0xc, - ADC_CONTROL0_REG = 0x10, /* adc control register 0 */ - ADC_CONTROL1_REG = 0x12, /* adc control register 1 */ + ADC_CONTROL0_REG = 0x10, /* adc control register 0 */ + ADC_CONTROL1_REG = 0x12, /* adc control register 1 */ CALIBRATION_REG = 0x14, - /* lower 16 bits of adc sample interval counter */ + /* lower 16 bits of adc sample interval counter */ ADC_SAMPLE_INTERVAL_LOWER_REG = 0x16, - /* upper 8 bits of adc sample interval counter */ + /* upper 8 bits of adc sample interval counter */ ADC_SAMPLE_INTERVAL_UPPER_REG = 0x18, - /* lower 16 bits of delay interval counter */ + /* lower 16 bits of delay interval counter */ ADC_DELAY_INTERVAL_LOWER_REG = 0x1a, - /* upper 8 bits of delay interval counter */ + /* upper 8 bits of delay interval counter */ ADC_DELAY_INTERVAL_UPPER_REG = 0x1c, - /* lower 16 bits of hardware conversion/scan counter */ + /* lower 16 bits of hardware conversion/scan counter */ ADC_COUNT_LOWER_REG = 0x1e, - /* upper 8 bits of hardware conversion/scan counter */ + /* upper 8 bits of hardware conversion/scan counter */ ADC_COUNT_UPPER_REG = 0x20, - ADC_START_REG = 0x22, /* software trigger to start acquisition */ - ADC_CONVERT_REG = 0x24, /* initiates single conversion */ - ADC_QUEUE_CLEAR_REG = 0x26, /* clears adc queue */ - ADC_QUEUE_LOAD_REG = 0x28, /* loads adc queue */ + ADC_START_REG = 0x22, /* software trigger to start acquisition */ + ADC_CONVERT_REG = 0x24, /* initiates single conversion */ + ADC_QUEUE_CLEAR_REG = 0x26, /* clears adc queue */ + ADC_QUEUE_LOAD_REG = 0x28, /* loads adc queue */ ADC_BUFFER_CLEAR_REG = 0x2a, - /* high channel for internal queue, use adc_chan_bits() inline above */ + /* high channel for internal queue, use adc_chan_bits() inline above */ ADC_QUEUE_HIGH_REG = 0x2c, - DAC_CONTROL0_REG = 0x50, /* dac control register 0 */ - DAC_CONTROL1_REG = 0x52, /* dac control register 0 */ - /* lower 16 bits of dac sample interval counter */ + DAC_CONTROL0_REG = 0x50, /* dac control register 0 */ + DAC_CONTROL1_REG = 0x52, /* dac control register 0 */ + /* lower 16 bits of dac sample interval counter */ DAC_SAMPLE_INTERVAL_LOWER_REG = 0x54, - /* upper 8 bits of dac sample interval counter */ + /* upper 8 bits of dac sample interval counter */ DAC_SAMPLE_INTERVAL_UPPER_REG = 0x56, DAC_SELECT_REG = 0x60, DAC_START_REG = 0x64, - DAC_BUFFER_CLEAR_REG = 0x66, /* clear dac buffer */ + DAC_BUFFER_CLEAR_REG = 0x66, /* clear dac buffer */ }; static inline unsigned int dac_convert_reg(unsigned int channel) @@ -216,7 +217,8 @@ enum hw_config_contents { /* use 225 nanosec strobe when loading dac instead of 50 nanosec */ SLOW_DAC_BIT = 0x400, /* bit with unknown function yet given as default value in pci-das64 - * manual */ + * manual + */ HW_CONFIG_DUMMY_BITS = 0x2000, /* bit selects channels 1/0 for analog input/output, otherwise 0/1 */ DMA_CH_SELECT_BIT = 0x8000, @@ -1138,12 +1140,14 @@ struct pcidas64_private { /* physical addresses of ai dma buffers */ dma_addr_t ai_buffer_bus_addr[MAX_AI_DMA_RING_COUNT]; /* array of ai dma descriptors read by plx9080, - * allocated to get proper alignment */ + * allocated to get proper alignment + */ struct plx_dma_desc *ai_dma_desc; /* physical address of ai dma descriptor array */ dma_addr_t ai_dma_desc_bus_addr; /* index of the ai dma descriptor/buffer - * that is currently being used */ + * that is currently being used + */ unsigned int ai_dma_index; /* dma buffers for analog output */ uint16_t *ao_buffer[AO_DMA_RING_COUNT]; @@ -1314,10 +1318,12 @@ static void init_plx9080(struct comedi_device *dev) /* enable dma chaining */ bits |= PLX_DMAMODE_CHAINEN; /* enable interrupt on dma done - * (probably don't need this, since chain never finishes) */ + * (probably don't need this, since chain never finishes) + */ bits |= PLX_DMAMODE_DONEIEN; /* don't increment local address during transfers - * (we are transferring from a fixed fifo register) */ + * (we are transferring from a fixed fifo register) + */ bits |= PLX_DMAMODE_LACONST; /* route dma interrupt to pci bus */ bits |= PLX_DMAMODE_INTRPCI; -- cgit v0.10.2 From 12f992adeb6bb1b3cc8c7190cb5b927c8ed9cc33 Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Fri, 26 Aug 2016 19:13:04 -0400 Subject: staging: comedi: cb_pcidas64: Fix commenting style Remove additional space after /* Convert single line block comment into single line comment Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index 281dc56..ac24c10 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -169,8 +169,8 @@ enum read_only_registers { }; enum read_write_registers { - I8255_4020_REG = 0x48, /* 8255 offset, for 4020 only */ - /* external channel/gain queue, uses same bits as ADC_QUEUE_LOAD_REG */ + I8255_4020_REG = 0x48, /* 8255 offset, for 4020 only */ + /* external channel/gain queue, uses same bits as ADC_QUEUE_LOAD_REG */ ADC_QUEUE_FIFO_REG = 0x100, ADC_FIFO_REG = 0x200, /* adc data fifo */ /* dac data fifo, has weird interactions with external channel queue */ @@ -189,51 +189,52 @@ enum dio_counter_registers { /* bit definitions for write-only registers */ enum intr_enable_contents { - ADC_INTR_SRC_MASK = 0x3, /* adc interrupt source mask */ - ADC_INTR_QFULL_BITS = 0x0, /* interrupt fifo quarter full */ - ADC_INTR_EOC_BITS = 0x1, /* interrupt end of conversion */ - ADC_INTR_EOSCAN_BITS = 0x2, /* interrupt end of scan */ - ADC_INTR_EOSEQ_BITS = 0x3, /* interrupt end of sequence mask */ - EN_ADC_INTR_SRC_BIT = 0x4, /* enable adc interrupt source */ - EN_ADC_DONE_INTR_BIT = 0x8, /* enable adc acquisition done intr */ + ADC_INTR_SRC_MASK = 0x3, /* adc interrupt source mask */ + ADC_INTR_QFULL_BITS = 0x0, /* interrupt fifo quarter full */ + ADC_INTR_EOC_BITS = 0x1, /* interrupt end of conversion */ + ADC_INTR_EOSCAN_BITS = 0x2, /* interrupt end of scan */ + ADC_INTR_EOSEQ_BITS = 0x3, /* interrupt end of sequence mask */ + EN_ADC_INTR_SRC_BIT = 0x4, /* enable adc interrupt source */ + EN_ADC_DONE_INTR_BIT = 0x8, /* enable adc acquisition done intr */ DAC_INTR_SRC_MASK = 0x30, DAC_INTR_QEMPTY_BITS = 0x0, DAC_INTR_HIGH_CHAN_BITS = 0x10, - EN_DAC_INTR_SRC_BIT = 0x40, /* enable dac interrupt source */ + EN_DAC_INTR_SRC_BIT = 0x40, /* enable dac interrupt source */ EN_DAC_DONE_INTR_BIT = 0x80, - EN_ADC_ACTIVE_INTR_BIT = 0x200, /* enable adc active interrupt */ - EN_ADC_STOP_INTR_BIT = 0x400, /* enable adc stop trigger interrupt */ - EN_DAC_ACTIVE_INTR_BIT = 0x800, /* enable dac active interrupt */ - EN_DAC_UNDERRUN_BIT = 0x4000, /* enable dac underrun status bit */ - EN_ADC_OVERRUN_BIT = 0x8000, /* enable adc overrun status bit */ + EN_ADC_ACTIVE_INTR_BIT = 0x200, /* enable adc active interrupt */ + EN_ADC_STOP_INTR_BIT = 0x400, /* enable adc stop trigger interrupt */ + EN_DAC_ACTIVE_INTR_BIT = 0x800, /* enable dac active interrupt */ + EN_DAC_UNDERRUN_BIT = 0x4000, /* enable dac underrun status bit */ + EN_ADC_OVERRUN_BIT = 0x8000, /* enable adc overrun status bit */ }; enum hw_config_contents { - MASTER_CLOCK_4020_MASK = 0x3, /* master clock source mask for 4020 */ - INTERNAL_CLOCK_4020_BITS = 0x1, /* use 40 MHz internal master clock */ - BNC_CLOCK_4020_BITS = 0x2, /* use BNC input for master clock */ - EXT_CLOCK_4020_BITS = 0x3, /* use dio input for master clock */ - EXT_QUEUE_BIT = 0x200, /* use external channel/gain queue */ - /* use 225 nanosec strobe when loading dac instead of 50 nanosec */ + MASTER_CLOCK_4020_MASK = 0x3, /* master clock source mask for 4020 */ + INTERNAL_CLOCK_4020_BITS = 0x1, /* use 40 MHz internal master clock */ + BNC_CLOCK_4020_BITS = 0x2, /* use BNC input for master clock */ + EXT_CLOCK_4020_BITS = 0x3, /* use dio input for master clock */ + EXT_QUEUE_BIT = 0x200, /* use external channel/gain queue */ + /* use 225 nanosec strobe when loading dac instead of 50 nanosec */ SLOW_DAC_BIT = 0x400, - /* bit with unknown function yet given as default value in pci-das64 - * manual + /* + * bit with unknown function yet given as default value in pci-das64 + * manual */ HW_CONFIG_DUMMY_BITS = 0x2000, - /* bit selects channels 1/0 for analog input/output, otherwise 0/1 */ + /* bit selects channels 1/0 for analog input/output, otherwise 0/1 */ DMA_CH_SELECT_BIT = 0x8000, - FIFO_SIZE_REG = 0x4, /* allows adjustment of fifo sizes */ - DAC_FIFO_SIZE_MASK = 0xff00, /* bits that set dac fifo size */ - DAC_FIFO_BITS = 0xf800, /* 8k sample ao fifo */ + FIFO_SIZE_REG = 0x4, /* allows adjustment of fifo sizes */ + DAC_FIFO_SIZE_MASK = 0xff00, /* bits that set dac fifo size */ + DAC_FIFO_BITS = 0xf800, /* 8k sample ao fifo */ }; #define DAC_FIFO_SIZE 0x2000 enum daq_atrig_low_4020_contents { - /* use trig/ext clk bnc input for analog gate signal */ + /* use trig/ext clk bnc input for analog gate signal */ EXT_AGATE_BNC_BIT = 0x8000, - /* use trig/ext clk bnc input for external stop trigger signal */ + /* use trig/ext clk bnc input for external stop trigger signal */ EXT_STOP_TRIG_BNC_BIT = 0x4000, - /* use trig/ext clk bnc input for external start trigger signal */ + /* use trig/ext clk bnc input for external start trigger signal */ EXT_START_TRIG_BNC_BIT = 0x2000, }; @@ -243,38 +244,38 @@ static inline uint16_t analog_trig_low_threshold_bits(uint16_t threshold) } enum adc_control0_contents { - ADC_GATE_SRC_MASK = 0x3, /* bits that select gate */ - ADC_SOFT_GATE_BITS = 0x1, /* software gate */ - ADC_EXT_GATE_BITS = 0x2, /* external digital gate */ - ADC_ANALOG_GATE_BITS = 0x3, /* analog level gate */ - /* level-sensitive gate (for digital) */ + ADC_GATE_SRC_MASK = 0x3, /* bits that select gate */ + ADC_SOFT_GATE_BITS = 0x1, /* software gate */ + ADC_EXT_GATE_BITS = 0x2, /* external digital gate */ + ADC_ANALOG_GATE_BITS = 0x3, /* analog level gate */ + /* level-sensitive gate (for digital) */ ADC_GATE_LEVEL_BIT = 0x4, - ADC_GATE_POLARITY_BIT = 0x8, /* gate active low */ + ADC_GATE_POLARITY_BIT = 0x8, /* gate active low */ ADC_START_TRIG_SOFT_BITS = 0x10, ADC_START_TRIG_EXT_BITS = 0x20, ADC_START_TRIG_ANALOG_BITS = 0x30, ADC_START_TRIG_MASK = 0x30, - ADC_START_TRIG_FALLING_BIT = 0x40, /* trig 1 uses falling edge */ - /* external pacing uses falling edge */ + ADC_START_TRIG_FALLING_BIT = 0x40, /* trig 1 uses falling edge */ + /* external pacing uses falling edge */ ADC_EXT_CONV_FALLING_BIT = 0x800, - /* enable hardware scan counter */ + /* enable hardware scan counter */ ADC_SAMPLE_COUNTER_EN_BIT = 0x1000, - ADC_DMA_DISABLE_BIT = 0x4000, /* disables dma */ - ADC_ENABLE_BIT = 0x8000, /* master adc enable */ + ADC_DMA_DISABLE_BIT = 0x4000, /* disables dma */ + ADC_ENABLE_BIT = 0x8000, /* master adc enable */ }; enum adc_control1_contents { - /* should be set for boards with > 16 channels */ + /* should be set for boards with > 16 channels */ ADC_QUEUE_CONFIG_BIT = 0x1, CONVERT_POLARITY_BIT = 0x10, EOC_POLARITY_BIT = 0x20, - ADC_SW_GATE_BIT = 0x40, /* software gate of adc */ - ADC_DITHER_BIT = 0x200, /* turn on extra noise for dithering */ + ADC_SW_GATE_BIT = 0x40, /* software gate of adc */ + ADC_DITHER_BIT = 0x200, /* turn on extra noise for dithering */ RETRIGGER_BIT = 0x800, ADC_LO_CHANNEL_4020_MASK = 0x300, ADC_HI_CHANNEL_4020_MASK = 0xc00, - TWO_CHANNEL_4020_BITS = 0x1000, /* two channel mode for 4020 */ - FOUR_CHANNEL_4020_BITS = 0x2000, /* four channel mode for 4020 */ + TWO_CHANNEL_4020_BITS = 0x1000, /* two channel mode for 4020 */ + FOUR_CHANNEL_4020_BITS = 0x2000, /* four channel mode for 4020 */ CHANNEL_MODE_4020_MASK = 0x3000, ADC_MODE_MASK = 0xf000, }; @@ -298,10 +299,10 @@ enum calibration_contents { SELECT_8800_BIT = 0x1, SELECT_8402_64XX_BIT = 0x2, SELECT_1590_60XX_BIT = 0x2, - CAL_EN_64XX_BIT = 0x40, /* calibration enable for 64xx series */ + CAL_EN_64XX_BIT = 0x40, /* calibration enable for 64xx series */ SERIAL_DATA_IN_BIT = 0x80, SERIAL_CLOCK_BIT = 0x100, - CAL_EN_60XX_BIT = 0x200, /* calibration enable for 60xx series */ + CAL_EN_60XX_BIT = 0x200, /* calibration enable for 60xx series */ CAL_GAIN_BIT = 0x800, }; @@ -328,12 +329,12 @@ static inline uint16_t adc_convert_chan_4020_bits(unsigned int channel) }; enum adc_queue_load_contents { - UNIP_BIT = 0x800, /* unipolar/bipolar bit */ - ADC_SE_DIFF_BIT = 0x1000, /* single-ended/ differential bit */ - /* non-referenced single-ended (common-mode input) */ + UNIP_BIT = 0x800, /* unipolar/bipolar bit */ + ADC_SE_DIFF_BIT = 0x1000, /* single-ended/ differential bit */ + /* non-referenced single-ended (common-mode input) */ ADC_COMMON_BIT = 0x2000, - QUEUE_EOSEQ_BIT = 0x4000, /* queue end of sequence */ - QUEUE_EOSCAN_BIT = 0x8000, /* queue end of scan */ + QUEUE_EOSEQ_BIT = 0x4000, /* queue end of sequence */ + QUEUE_EOSCAN_BIT = 0x8000, /* queue end of scan */ }; static inline uint16_t adc_chan_bits(unsigned int channel) @@ -342,7 +343,7 @@ static inline uint16_t adc_chan_bits(unsigned int channel) }; enum dac_control0_contents { - DAC_ENABLE_BIT = 0x8000, /* dac controller enable bit */ + DAC_ENABLE_BIT = 0x8000, /* dac controller enable bit */ DAC_CYCLIC_STOP_BIT = 0x4000, DAC_WAVEFORM_MODE_BIT = 0x100, DAC_EXT_UPDATE_FALLING_BIT = 0x80, @@ -362,7 +363,7 @@ enum dac_control1_contents { DAC_WRITE_POLARITY_BIT = 0x800, /* board-dependent setting */ DAC1_EXT_REF_BIT = 0x200, DAC0_EXT_REF_BIT = 0x100, - DAC_OUTPUT_ENABLE_BIT = 0x80, /* dac output enable bit */ + DAC_OUTPUT_ENABLE_BIT = 0x80, /* dac output enable bit */ DAC_UPDATE_POLARITY_BIT = 0x40, /* board-dependent setting */ DAC_SW_GATE_BIT = 0x20, DAC1_UNIPOLAR_BIT = 0x8, @@ -411,9 +412,9 @@ enum i2c_addresses { }; enum range_cal_i2c_contents { - /* bits that set what source the adc converter measures */ + /* bits that set what source the adc converter measures */ ADC_SRC_4020_MASK = 0x70, - /* make bnc trig/ext clock threshold 0V instead of 2.5V */ + /* make bnc trig/ext clock threshold 0V instead of 2.5V */ BNC_TRIG_THRESHOLD_0V_BIT = 0x80, }; @@ -424,7 +425,7 @@ static inline uint8_t adc_src_4020_bits(unsigned int source) static inline uint8_t attenuate_bit(unsigned int channel) { - /* attenuate channel (+-5V input range) */ + /* attenuate channel (+-5V input range) */ return 1 << (channel & 0x3); }; @@ -629,18 +630,18 @@ enum pcidas64_boardid { struct pcidas64_board { const char *name; - int ai_se_chans; /* number of ai inputs in single-ended mode */ - int ai_bits; /* analog input resolution */ - int ai_speed; /* fastest conversion period in ns */ + int ai_se_chans; /* number of ai inputs in single-ended mode */ + int ai_bits; /* analog input resolution */ + int ai_speed; /* fastest conversion period in ns */ const struct comedi_lrange *ai_range_table; const uint8_t *ai_range_code; - int ao_nchan; /* number of analog out channels */ - int ao_bits; /* analog output resolution */ - int ao_scan_speed; /* analog output scan speed */ + int ao_nchan; /* number of analog out channels */ + int ao_bits; /* analog output resolution */ + int ao_scan_speed; /* analog output scan speed */ const struct comedi_lrange *ao_range_table; const int *ao_range_code; const struct hw_fifo_info *const ai_fifo; - /* different board families have slightly different registers */ + /* different board families have slightly different registers */ enum register_layout layout; unsigned has_8255:1; }; @@ -701,7 +702,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .has_8255 = 1, }, [BOARD_PCIDAS6402_12] = { - .name = "pci-das6402/12", /* XXX check */ + .name = "pci-das6402/12", /* XXX check */ .ai_se_chans = 64, .ai_bits = 12, .ai_speed = 5000, @@ -998,7 +999,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ai_speed = 50, .ao_bits = 12, .ao_nchan = 2, - .ao_scan_speed = 0, /* no hardware pacing on ao */ + .ao_scan_speed = 0, /* no hardware pacing on ao */ .layout = LAYOUT_4020, .ai_range_table = &ai_ranges_4020, .ao_range_table = &ao_ranges_4020, @@ -1007,9 +1008,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .has_8255 = 1, }, #if 0 - /* - * The device id for these boards is unknown - */ + /* The device id for these boards is unknown */ [BOARD_PCIDAS6402_16_JR] = { .name = "pci-das6402/16/jr", @@ -1118,64 +1117,66 @@ static inline unsigned short se_diff_bit_6xxx(struct comedi_device *dev, } struct ext_clock_info { - /* master clock divisor to use for scans with external master clock */ + /* master clock divisor to use for scans with external master clock */ unsigned int divisor; - /* chanspec for master clock input when used as scan begin src */ + /* chanspec for master clock input when used as scan begin src */ unsigned int chanspec; }; /* this structure is for data unique to this hardware driver. */ struct pcidas64_private { - /* base addresses (physical) */ + /* base addresses (physical) */ resource_size_t main_phys_iobase; resource_size_t dio_counter_phys_iobase; - /* base addresses (ioremapped) */ + /* base addresses (ioremapped) */ void __iomem *plx9080_iobase; void __iomem *main_iobase; - /* local address (used by dma controller) */ + /* local address (used by dma controller) */ uint32_t local0_iobase; uint32_t local1_iobase; - /* dma buffers for analog input */ + /* dma buffers for analog input */ uint16_t *ai_buffer[MAX_AI_DMA_RING_COUNT]; - /* physical addresses of ai dma buffers */ + /* physical addresses of ai dma buffers */ dma_addr_t ai_buffer_bus_addr[MAX_AI_DMA_RING_COUNT]; - /* array of ai dma descriptors read by plx9080, - * allocated to get proper alignment + /* + * array of ai dma descriptors read by plx9080, + * allocated to get proper alignment */ struct plx_dma_desc *ai_dma_desc; - /* physical address of ai dma descriptor array */ + /* physical address of ai dma descriptor array */ dma_addr_t ai_dma_desc_bus_addr; - /* index of the ai dma descriptor/buffer - * that is currently being used + /* + * index of the ai dma descriptor/buffer + * that is currently being used */ unsigned int ai_dma_index; - /* dma buffers for analog output */ + /* dma buffers for analog output */ uint16_t *ao_buffer[AO_DMA_RING_COUNT]; - /* physical addresses of ao dma buffers */ + /* physical addresses of ao dma buffers */ dma_addr_t ao_buffer_bus_addr[AO_DMA_RING_COUNT]; struct plx_dma_desc *ao_dma_desc; dma_addr_t ao_dma_desc_bus_addr; - /* keeps track of buffer where the next ao sample should go */ + /* keeps track of buffer where the next ao sample should go */ unsigned int ao_dma_index; - unsigned int hw_revision; /* stc chip hardware revision number */ - /* last bits sent to INTR_ENABLE_REG register */ + unsigned int hw_revision; /* stc chip hardware revision number */ + /* last bits sent to INTR_ENABLE_REG register */ unsigned int intr_enable_bits; - /* last bits sent to ADC_CONTROL1_REG register */ + /* last bits sent to ADC_CONTROL1_REG register */ uint16_t adc_control1_bits; - /* last bits sent to FIFO_SIZE_REG register */ + /* last bits sent to FIFO_SIZE_REG register */ uint16_t fifo_size_bits; - /* last bits sent to HW_CONFIG_REG register */ + /* last bits sent to HW_CONFIG_REG register */ uint16_t hw_config_bits; uint16_t dac_control1_bits; - /* last bits written to plx9080 control register */ + /* last bits written to plx9080 control register */ uint32_t plx_control_bits; - /* last bits written to plx interrupt control and status register */ + /* last bits written to plx interrupt control and status register */ uint32_t plx_intcsr_bits; - /* index of calibration source readable through ai ch0 */ + /* index of calibration source readable through ai ch0 */ int calibration_source; - /* bits written to i2c calibration/range register */ + /* bits written to i2c calibration/range register */ uint8_t i2c_cal_range_bits; - /* configure digital triggers to trigger on falling edge */ + /* configure digital triggers to trigger on falling edge */ unsigned int ext_trig_falling; short ai_cmd_running; unsigned int ai_fifo_segment_length; @@ -1228,7 +1229,7 @@ static void abort_dma(struct comedi_device *dev, unsigned int channel) struct pcidas64_private *devpriv = dev->private; unsigned long flags; - /* spinlock for plx dma control/status reg */ + /* spinlock for plx dma control/status reg */ spin_lock_irqsave(&dev->spinlock, flags); plx9080_abort_dma(devpriv->plx9080_iobase, channel); @@ -1275,7 +1276,7 @@ static void enable_ai_interrupts(struct comedi_device *dev, * if CMDF_WAKE_EOS flag is set. */ if (cmd->flags & CMDF_WAKE_EOS) { - /* 4020 doesn't support pio transfers except for fifo dregs */ + /* 4020 doesn't support pio transfers except for fifo dregs */ if (board->layout != LAYOUT_4020) bits |= ADC_INTR_EOSCAN_BITS | EN_ADC_INTR_SRC_BIT; } @@ -1309,38 +1310,40 @@ static void init_plx9080(struct comedi_device *dev) abort_dma(dev, 0); abort_dma(dev, 1); - /* configure dma0 mode */ + /* configure dma0 mode */ bits = 0; - /* enable ready input, not sure if this is necessary */ + /* enable ready input, not sure if this is necessary */ bits |= PLX_DMAMODE_READYIEN; - /* enable bterm, not sure if this is necessary */ + /* enable bterm, not sure if this is necessary */ bits |= PLX_DMAMODE_BTERMIEN; - /* enable dma chaining */ + /* enable dma chaining */ bits |= PLX_DMAMODE_CHAINEN; - /* enable interrupt on dma done - * (probably don't need this, since chain never finishes) + /* + * enable interrupt on dma done + * (probably don't need this, since chain never finishes) */ bits |= PLX_DMAMODE_DONEIEN; - /* don't increment local address during transfers - * (we are transferring from a fixed fifo register) + /* + * don't increment local address during transfers + * (we are transferring from a fixed fifo register) */ bits |= PLX_DMAMODE_LACONST; - /* route dma interrupt to pci bus */ + /* route dma interrupt to pci bus */ bits |= PLX_DMAMODE_INTRPCI; - /* enable demand mode */ + /* enable demand mode */ bits |= PLX_DMAMODE_DEMAND; - /* enable local burst mode */ + /* enable local burst mode */ bits |= PLX_DMAMODE_BURSTEN; - /* 4020 uses 32 bit dma */ + /* 4020 uses 32 bit dma */ if (board->layout == LAYOUT_4020) bits |= PLX_DMAMODE_WIDTH_32; - else /* localspace0 bus is 16 bits wide */ + else /* localspace0 bus is 16 bits wide */ bits |= PLX_DMAMODE_WIDTH_16; writel(bits, plx_iobase + PLX_REG_DMAMODE1); if (ao_cmd_is_supported(board)) writel(bits, plx_iobase + PLX_REG_DMAMODE0); - /* enable interrupts on plx 9080 */ + /* enable interrupts on plx 9080 */ devpriv->plx_intcsr_bits |= PLX_INTCSR_LSEABORTEN | PLX_INTCSR_LSEPARITYEN | PLX_INTCSR_PIEN | PLX_INTCSR_PLIEN | PLX_INTCSR_PABORTIEN | PLX_INTCSR_LIOEN | @@ -1382,7 +1385,7 @@ static int set_ai_fifo_segment_length(struct comedi_device *dev, if (num_entries > fifo->max_segment_length) num_entries = fifo->max_segment_length; - /* 1 == 256 entries, 2 == 512 entries, etc */ + /* 1 == 256 entries, 2 == 512 entries, etc */ num_increments = DIV_ROUND_CLOSEST(num_entries, increment_size); bits = (~(num_increments - 1)) & fifo->fifo_size_reg_mask; @@ -1448,7 +1451,7 @@ static void init_stc_registers(struct comedi_device *dev) writew(devpriv->adc_control1_bits, devpriv->main_iobase + ADC_CONTROL1_REG); - /* 6402/16 manual says this register must be initialized to 0xff? */ + /* 6402/16 manual says this register must be initialized to 0xff? */ writew(0xff, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG); bits = SLOW_DAC_BIT | DMA_CH_SELECT_BIT; @@ -1463,7 +1466,7 @@ static void init_stc_registers(struct comedi_device *dev) spin_unlock_irqrestore(&dev->spinlock, flags); - /* set fifos to maximum size */ + /* set fifos to maximum size */ devpriv->fifo_size_bits |= DAC_FIFO_BITS; set_ai_fifo_segment_length(dev, board->ai_fifo->max_segment_length); @@ -1484,7 +1487,7 @@ static int alloc_and_init_dma_members(struct comedi_device *dev) struct pcidas64_private *devpriv = dev->private; int i; - /* allocate pci dma buffers */ + /* allocate pci dma buffers */ for (i = 0; i < ai_dma_ring_count(board); i++) { devpriv->ai_buffer[i] = dma_alloc_coherent(&pcidev->dev, DMA_BUFFER_SIZE, @@ -1505,7 +1508,7 @@ static int alloc_and_init_dma_members(struct comedi_device *dev) return -ENOMEM; } } - /* allocate dma descriptors */ + /* allocate dma descriptors */ devpriv->ai_dma_desc = dma_alloc_coherent(&pcidev->dev, sizeof(struct plx_dma_desc) * ai_dma_ring_count(board), @@ -1523,7 +1526,7 @@ static int alloc_and_init_dma_members(struct comedi_device *dev) if (!devpriv->ao_dma_desc) return -ENOMEM; } - /* initialize dma descriptors */ + /* initialize dma descriptors */ for (i = 0; i < ai_dma_ring_count(board); i++) { devpriv->ai_dma_desc[i].pci_start_addr = cpu_to_le32(devpriv->ai_buffer_bus_addr[i]); @@ -1624,13 +1627,11 @@ static void i2c_set_sda(struct comedi_device *dev, int state) void __iomem *plx_control_addr = devpriv->plx9080_iobase + PLX_REG_CNTRL; - if (state) { - /* set data line high */ + if (state) { /* set data line high */ devpriv->plx_control_bits &= ~data_bit; writel(devpriv->plx_control_bits, plx_control_addr); udelay(i2c_high_udelay); - } else { /* set data line low */ - + } else { /* set data line low */ devpriv->plx_control_bits |= data_bit; writel(devpriv->plx_control_bits, plx_control_addr); udelay(i2c_low_udelay); @@ -1645,13 +1646,11 @@ static void i2c_set_scl(struct comedi_device *dev, int state) void __iomem *plx_control_addr = devpriv->plx9080_iobase + PLX_REG_CNTRL; - if (state) { - /* set clock line high */ + if (state) { /* set clock line high */ devpriv->plx_control_bits &= ~clock_bit; writel(devpriv->plx_control_bits, plx_control_addr); udelay(i2c_high_udelay); - } else { /* set clock line low */ - + } else { /* set clock line low */ devpriv->plx_control_bits |= clock_bit; writel(devpriv->plx_control_bits, plx_control_addr); udelay(i2c_low_udelay); @@ -1680,7 +1679,7 @@ static int i2c_read_ack(struct comedi_device *dev) i2c_set_sda(dev, 1); i2c_set_scl(dev, 1); - return 0; /* return fake acknowledge bit */ + return 0; /* return fake acknowledge bit */ } /* send start bit */ @@ -1713,23 +1712,23 @@ static void i2c_write(struct comedi_device *dev, unsigned int address, * eeprom and i2c bus */ - /* make sure we dont send anything to eeprom */ + /* make sure we dont send anything to eeprom */ devpriv->plx_control_bits &= ~PLX_CNTRL_EECS; i2c_stop(dev); i2c_start(dev); - /* send address and write bit */ + /* send address and write bit */ bitstream = (address << 1) & ~read_bit; i2c_write_byte(dev, bitstream); - /* get acknowledge */ + /* get acknowledge */ if (i2c_read_ack(dev) != 0) { dev_err(dev->class_dev, "failed: no acknowledge\n"); i2c_stop(dev); return; } - /* write data bytes */ + /* write data bytes */ for (i = 0; i < length; i++) { i2c_write_byte(dev, data[i]); if (i2c_read_ack(dev) != 0) { @@ -1776,8 +1775,8 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, range = CR_RANGE(insn->chanspec); aref = CR_AREF(insn->chanspec); - /* disable card's analog input interrupt sources and pacing */ - /* 4020 generates dac done interrupts even though they are disabled */ + /* disable card's analog input interrupt sources and pacing */ + /* 4020 generates dac done interrupts even though they are disabled */ disable_ai_pacing(dev); spin_lock_irqsave(&dev->spinlock, flags); @@ -1790,12 +1789,12 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, spin_unlock_irqrestore(&dev->spinlock, flags); if (board->layout != LAYOUT_4020) { - /* use internal queue */ + /* use internal queue */ devpriv->hw_config_bits &= ~EXT_QUEUE_BIT; writew(devpriv->hw_config_bits, devpriv->main_iobase + HW_CONFIG_REG); - /* ALT_SOURCE is internal calibration reference */ + /* ALT_SOURCE is internal calibration reference */ if (insn->chanspec & CR_ALT_SOURCE) { unsigned int cal_en_bit; @@ -1817,19 +1816,19 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, */ writew(0, devpriv->main_iobase + CALIBRATION_REG); } - /* load internal queue */ + /* load internal queue */ bits = 0; - /* set gain */ + /* set gain */ bits |= ai_range_bits_6xxx(dev, CR_RANGE(insn->chanspec)); - /* set single-ended / differential */ + /* set single-ended / differential */ bits |= se_diff_bit_6xxx(dev, aref == AREF_DIFF); if (aref == AREF_COMMON) bits |= ADC_COMMON_BIT; bits |= adc_chan_bits(channel); - /* set stop channel */ + /* set stop channel */ writew(adc_chan_bits(channel), devpriv->main_iobase + ADC_QUEUE_HIGH_REG); - /* set start channel, and rest of settings */ + /* set start channel, and rest of settings */ writew(bits, devpriv->main_iobase + ADC_QUEUE_LOAD_REG); } else { uint8_t old_cal_range_bits = devpriv->i2c_cal_range_bits; @@ -1841,7 +1840,7 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, } else { /* select BNC inputs */ devpriv->i2c_cal_range_bits |= adc_src_4020_bits(4); } - /* select range */ + /* select range */ if (range == 0) devpriv->i2c_cal_range_bits |= attenuate_bit(channel); else @@ -1868,14 +1867,14 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, } for (n = 0; n < insn->n; n++) { - /* clear adc buffer (inside loop for 4020 sake) */ + /* clear adc buffer (inside loop for 4020 sake) */ writew(0, devpriv->main_iobase + ADC_BUFFER_CLEAR_REG); /* trigger conversion, bits sent only matter for 4020 */ writew(adc_convert_chan_4020_bits(CR_CHAN(insn->chanspec)), devpriv->main_iobase + ADC_CONVERT_REG); - /* wait for data */ + /* wait for data */ ret = comedi_timeout(dev, s, insn, cb_pcidas64_ai_eoc, 0); if (ret) return ret; @@ -2255,7 +2254,7 @@ static void setup_sample_counters(struct comedi_device *dev, { struct pcidas64_private *devpriv = dev->private; - /* load hardware conversion counter */ + /* load hardware conversion counter */ if (use_hw_sample_counter(cmd)) { writew(cmd->stop_arg & 0xffff, devpriv->main_iobase + ADC_COUNT_LOWER_REG); @@ -2283,7 +2282,7 @@ static inline unsigned int dma_transfer_size(struct comedi_device *dev) static uint32_t ai_convert_counter_6xxx(const struct comedi_device *dev, const struct comedi_cmd *cmd) { - /* supposed to load counter with desired divisor minus 3 */ + /* supposed to load counter with desired divisor minus 3 */ return cmd->convert_arg / TIMER_BASE - 3; } @@ -2292,7 +2291,7 @@ static uint32_t ai_scan_counter_6xxx(struct comedi_device *dev, { uint32_t count; - /* figure out how long we need to delay at end of scan */ + /* figure out how long we need to delay at end of scan */ switch (cmd->scan_begin_src) { case TRIG_TIMER: count = (cmd->scan_begin_arg - @@ -2321,13 +2320,13 @@ static uint32_t ai_convert_counter_4020(struct comedi_device *dev, case TRIG_OTHER: divisor = devpriv->ext_clock.divisor; break; - default: /* should never happen */ + default: /* should never happen */ dev_err(dev->class_dev, "bug! failed to set ai pacing!\n"); divisor = 1000; break; } - /* supposed to load counter with desired divisor minus 2 for 4020 */ + /* supposed to load counter with desired divisor minus 2 for 4020 */ return divisor - 2; } @@ -2336,7 +2335,7 @@ static void select_master_clock_4020(struct comedi_device *dev, { struct pcidas64_private *devpriv = dev->private; - /* select internal/external master clock */ + /* select internal/external master clock */ devpriv->hw_config_bits &= ~MASTER_CLOCK_4020_MASK; if (cmd->scan_begin_src == TRIG_OTHER) { int chanspec = devpriv->ext_clock.chanspec; @@ -2372,7 +2371,7 @@ static inline void dma_start_sync(struct comedi_device *dev, struct pcidas64_private *devpriv = dev->private; unsigned long flags; - /* spinlock for plx dma control/status reg */ + /* spinlock for plx dma control/status reg */ spin_lock_irqsave(&dev->spinlock, flags); writeb(PLX_DMACSR_ENABLE | PLX_DMACSR_START | PLX_DMACSR_CLEARINTR, devpriv->plx9080_iobase + PLX_REG_DMACSR(channel)); @@ -2396,16 +2395,16 @@ static void set_ai_pacing(struct comedi_device *dev, struct comedi_cmd *cmd) scan_counter = ai_scan_counter_6xxx(dev, cmd); } - /* load lower 16 bits of convert interval */ + /* load lower 16 bits of convert interval */ writew(convert_counter & 0xffff, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_LOWER_REG); - /* load upper 8 bits of convert interval */ + /* load upper 8 bits of convert interval */ writew((convert_counter >> 16) & 0xff, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG); - /* load lower 16 bits of scan delay */ + /* load lower 16 bits of scan delay */ writew(scan_counter & 0xffff, devpriv->main_iobase + ADC_DELAY_INTERVAL_LOWER_REG); - /* load upper 8 bits of scan delay */ + /* load upper 8 bits of scan delay */ writew((scan_counter >> 16) & 0xff, devpriv->main_iobase + ADC_DELAY_INTERVAL_UPPER_REG); } @@ -2441,26 +2440,26 @@ static int setup_channel_queue(struct comedi_device *dev, writew(devpriv->hw_config_bits, devpriv->main_iobase + HW_CONFIG_REG); bits = 0; - /* set channel */ + /* set channel */ bits |= adc_chan_bits(CR_CHAN(cmd->chanlist[0])); - /* set gain */ + /* set gain */ bits |= ai_range_bits_6xxx(dev, CR_RANGE(cmd->chanlist[0])); - /* set single-ended / differential */ + /* set single-ended / differential */ bits |= se_diff_bit_6xxx(dev, CR_AREF(cmd->chanlist[0]) == AREF_DIFF); if (CR_AREF(cmd->chanlist[0]) == AREF_COMMON) bits |= ADC_COMMON_BIT; - /* set stop channel */ + /* set stop channel */ writew(adc_chan_bits (CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1])), devpriv->main_iobase + ADC_QUEUE_HIGH_REG); - /* set start channel, and rest of settings */ + /* set start channel, and rest of settings */ writew(bits, devpriv->main_iobase + ADC_QUEUE_LOAD_REG); } else { - /* use external queue */ + /* use external queue */ if (dev->write_subdev && dev->write_subdev->busy) { warn_external_queue(dev); return -EBUSY; @@ -2468,30 +2467,30 @@ static int setup_channel_queue(struct comedi_device *dev, devpriv->hw_config_bits |= EXT_QUEUE_BIT; writew(devpriv->hw_config_bits, devpriv->main_iobase + HW_CONFIG_REG); - /* clear DAC buffer to prevent weird interactions */ + /* clear DAC buffer to prevent weird interactions */ writew(0, devpriv->main_iobase + DAC_BUFFER_CLEAR_REG); - /* clear queue pointer */ + /* clear queue pointer */ writew(0, devpriv->main_iobase + ADC_QUEUE_CLEAR_REG); - /* load external queue */ + /* load external queue */ for (i = 0; i < cmd->chanlist_len; i++) { bits = 0; - /* set channel */ + /* set channel */ bits |= adc_chan_bits(CR_CHAN(cmd-> chanlist[i])); - /* set gain */ + /* set gain */ bits |= ai_range_bits_6xxx(dev, CR_RANGE(cmd-> chanlist [i])); - /* set single-ended / differential */ + /* set single-ended / differential */ bits |= se_diff_bit_6xxx(dev, CR_AREF(cmd-> chanlist[i]) == AREF_DIFF); if (CR_AREF(cmd->chanlist[i]) == AREF_COMMON) bits |= ADC_COMMON_BIT; - /* mark end of queue */ + /* mark end of queue */ if (i == cmd->chanlist_len - 1) bits |= QUEUE_EOSCAN_BIT | QUEUE_EOSEQ_BIT; @@ -2504,7 +2503,7 @@ static int setup_channel_queue(struct comedi_device *dev, * but required for reliable operation */ writew(0, devpriv->main_iobase + ADC_QUEUE_CLEAR_REG); - /* prime queue holding register */ + /* prime queue holding register */ writew(0, devpriv->main_iobase + ADC_QUEUE_LOAD_REG); } } else { @@ -2513,7 +2512,7 @@ static int setup_channel_queue(struct comedi_device *dev, devpriv->i2c_cal_range_bits &= ~ADC_SRC_4020_MASK; /* select BNC inputs */ devpriv->i2c_cal_range_bits |= adc_src_4020_bits(4); - /* select ranges */ + /* select ranges */ for (i = 0; i < cmd->chanlist_len; i++) { unsigned int channel = CR_CHAN(cmd->chanlist[i]); unsigned int range = CR_RANGE(cmd->chanlist[i]); @@ -2585,7 +2584,7 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if (retval < 0) return retval; - /* make sure internal calibration source is turned off */ + /* make sure internal calibration source is turned off */ writew(0, devpriv->main_iobase + CALIBRATION_REG); set_ai_pacing(dev, cmd); @@ -2601,10 +2600,10 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if (board->layout != LAYOUT_4020) { devpriv->adc_control1_bits &= ~ADC_MODE_MASK; if (cmd->convert_src == TRIG_EXT) - /* good old mode 13 */ + /* good old mode 13 */ devpriv->adc_control1_bits |= adc_mode_bits(13); else - /* mode 8. What else could you need? */ + /* mode 8. What else could you need? */ devpriv->adc_control1_bits |= adc_mode_bits(8); } else { devpriv->adc_control1_bits &= ~CHANNEL_MODE_4020_MASK; @@ -2624,20 +2623,20 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->main_iobase + ADC_CONTROL1_REG); spin_unlock_irqrestore(&dev->spinlock, flags); - /* clear adc buffer */ + /* clear adc buffer */ writew(0, devpriv->main_iobase + ADC_BUFFER_CLEAR_REG); if ((cmd->flags & CMDF_WAKE_EOS) == 0 || board->layout == LAYOUT_4020) { devpriv->ai_dma_index = 0; - /* set dma transfer size */ + /* set dma transfer size */ for (i = 0; i < ai_dma_ring_count(board); i++) devpriv->ai_dma_desc[i].transfer_size = cpu_to_le32(dma_transfer_size(dev) * sizeof(uint16_t)); - /* give location of first dma descriptor */ + /* give location of first dma descriptor */ load_first_dma_descriptor(dev, 1, devpriv->ai_dma_desc_bus_addr | PLX_DMADPR_DESCPCI | @@ -2663,7 +2662,7 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) bits = ADC_ENABLE_BIT | ADC_SOFT_GATE_BITS | ADC_GATE_LEVEL_BIT; if (cmd->flags & CMDF_WAKE_EOS) bits |= ADC_DMA_DISABLE_BIT; - /* set start trigger */ + /* set start trigger */ if (cmd->start_src == TRIG_EXT) { bits |= ADC_START_TRIG_EXT_BITS; if (cmd->start_arg & CR_INVERT) @@ -2679,7 +2678,7 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) spin_unlock_irqrestore(&dev->spinlock, flags); - /* start acquisition */ + /* start acquisition */ if (cmd->start_src == TRIG_NOW) writew(0, devpriv->main_iobase + ADC_START_REG); @@ -2697,7 +2696,7 @@ static void pio_drain_ai_fifo_16(struct comedi_device *dev) int num_samples; do { - /* get least significant 15 bits */ + /* get least significant 15 bits */ read_index = readw(devpriv->main_iobase + ADC_READ_PNTR_REG) & 0x7fff; write_index = readw(devpriv->main_iobase + ADC_WRITE_PNTR_REG) & @@ -2802,14 +2801,14 @@ static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel) pci_addr_reg = devpriv->plx9080_iobase + PLX_REG_DMAPADR(channel); - /* loop until we have read all the full buffers */ + /* loop until we have read all the full buffers */ for (j = 0, next_transfer_addr = readl(pci_addr_reg); (next_transfer_addr < devpriv->ai_buffer_bus_addr[devpriv->ai_dma_index] || next_transfer_addr >= devpriv->ai_buffer_bus_addr[devpriv->ai_dma_index] + DMA_BUFFER_SIZE) && j < ai_dma_ring_count(board); j++) { - /* transfer data from dma buffer to comedi buffer */ + /* transfer data from dma buffer to comedi buffer */ num_samples = comedi_nsamples_left(s, dma_transfer_size(dev)); comedi_buf_write_samples(s, devpriv->ai_buffer[devpriv->ai_dma_index], @@ -2835,15 +2834,15 @@ static void handle_ai_interrupt(struct comedi_device *dev, uint8_t dma1_status; unsigned long flags; - /* check for fifo overrun */ + /* check for fifo overrun */ if (status & ADC_OVERRUN_BIT) { dev_err(dev->class_dev, "fifo overrun\n"); async->events |= COMEDI_CB_ERROR; } - /* spin lock makes sure no one else changes plx dma control reg */ + /* spin lock makes sure no one else changes plx dma control reg */ spin_lock_irqsave(&dev->spinlock, flags); dma1_status = readb(devpriv->plx9080_iobase + PLX_REG_DMACSR1); - if (plx_status & PLX_INTCSR_DMA1IA) { /* dma chan 1 interrupt */ + if (plx_status & PLX_INTCSR_DMA1IA) { /* dma chan 1 interrupt */ writeb((dma1_status & PLX_DMACSR_ENABLE) | PLX_DMACSR_CLEARINTR, devpriv->plx9080_iobase + PLX_REG_DMACSR1); @@ -2852,7 +2851,7 @@ static void handle_ai_interrupt(struct comedi_device *dev, } spin_unlock_irqrestore(&dev->spinlock, flags); - /* drain fifo with pio */ + /* drain fifo with pio */ if ((status & ADC_DONE_BIT) || ((cmd->flags & CMDF_WAKE_EOS) && (status & ADC_INTR_PENDING_BIT) && @@ -2865,7 +2864,7 @@ static void handle_ai_interrupt(struct comedi_device *dev, spin_unlock_irqrestore(&dev->spinlock, flags); } } - /* if we are have all the data, then quit */ + /* if we are have all the data, then quit */ if ((cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg) || (cmd->stop_src == TRIG_EXT && (status & ADC_STOP_BIT))) @@ -3018,7 +3017,7 @@ static void handle_ao_interrupt(struct comedi_device *dev, async = s->async; cmd = &async->cmd; - /* spin lock makes sure no one else changes plx dma control reg */ + /* spin lock makes sure no one else changes plx dma control reg */ spin_lock_irqsave(&dev->spinlock, flags); dma0_status = readb(devpriv->plx9080_iobase + PLX_REG_DMACSR0); if (plx_status & PLX_INTCSR_DMA0IA) { /* dma chan 0 interrupt */ @@ -3112,15 +3111,15 @@ static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, int chan = CR_CHAN(insn->chanspec); int range = CR_RANGE(insn->chanspec); - /* do some initializing */ + /* do some initializing */ writew(0, devpriv->main_iobase + DAC_CONTROL0_REG); - /* set range */ + /* set range */ set_dac_range_bits(dev, &devpriv->dac_control1_bits, chan, range); writew(devpriv->dac_control1_bits, devpriv->main_iobase + DAC_CONTROL1_REG); - /* write to channel */ + /* write to channel */ if (board->layout == LAYOUT_4020) { writew(data[0] & 0xff, devpriv->main_iobase + dac_lsb_4020_reg(chan)); @@ -3130,7 +3129,7 @@ static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, writew(data[0], devpriv->main_iobase + dac_convert_reg(chan)); } - /* remember output value */ + /* remember output value */ s->readback[chan] = data[0]; return 1; @@ -3562,7 +3561,7 @@ static int caldac_i2c_write(struct comedi_device *dev, uint8_t serial_bytes[3]; uint8_t i2c_addr; enum pointer_bits { - /* manual has gain and offset bits switched */ + /* manual has gain and offset bits switched */ OFFSET_0_2 = 0x1, GAIN_0_2 = 0x2, OFFSET_1_3 = 0x4, @@ -3573,35 +3572,35 @@ static int caldac_i2c_write(struct comedi_device *dev, }; switch (caldac_channel) { - case 0: /* chan 0 offset */ + case 0: /* chan 0 offset */ i2c_addr = CALDAC0_I2C_ADDR; serial_bytes[0] = OFFSET_0_2; break; - case 1: /* chan 1 offset */ + case 1: /* chan 1 offset */ i2c_addr = CALDAC0_I2C_ADDR; serial_bytes[0] = OFFSET_1_3; break; - case 2: /* chan 2 offset */ + case 2: /* chan 2 offset */ i2c_addr = CALDAC1_I2C_ADDR; serial_bytes[0] = OFFSET_0_2; break; - case 3: /* chan 3 offset */ + case 3: /* chan 3 offset */ i2c_addr = CALDAC1_I2C_ADDR; serial_bytes[0] = OFFSET_1_3; break; - case 4: /* chan 0 gain */ + case 4: /* chan 0 gain */ i2c_addr = CALDAC0_I2C_ADDR; serial_bytes[0] = GAIN_0_2; break; - case 5: /* chan 1 gain */ + case 5: /* chan 1 gain */ i2c_addr = CALDAC0_I2C_ADDR; serial_bytes[0] = GAIN_1_3; break; - case 6: /* chan 2 gain */ + case 6: /* chan 2 gain */ i2c_addr = CALDAC1_I2C_ADDR; serial_bytes[0] = GAIN_0_2; break; - case 7: /* chan 3 gain */ + case 7: /* chan 3 gain */ i2c_addr = CALDAC1_I2C_ADDR; serial_bytes[0] = GAIN_1_3; break; @@ -3724,24 +3723,24 @@ static uint16_t read_eeprom(struct comedi_device *dev, uint8_t address) udelay(eeprom_udelay); devpriv->plx_control_bits &= ~PLX_CNTRL_EESK & ~PLX_CNTRL_EECS; - /* make sure we don't send anything to the i2c bus on 4020 */ + /* make sure we don't send anything to the i2c bus on 4020 */ devpriv->plx_control_bits |= PLX_CNTRL_USERO; writel(devpriv->plx_control_bits, plx_control_addr); - /* activate serial eeprom */ + /* activate serial eeprom */ udelay(eeprom_udelay); devpriv->plx_control_bits |= PLX_CNTRL_EECS; writel(devpriv->plx_control_bits, plx_control_addr); - /* write read command and desired memory address */ + /* write read command and desired memory address */ for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) { - /* set bit to be written */ + /* set bit to be written */ udelay(eeprom_udelay); if (bitstream & bit) devpriv->plx_control_bits |= PLX_CNTRL_EEWB; else devpriv->plx_control_bits &= ~PLX_CNTRL_EEWB; writel(devpriv->plx_control_bits, plx_control_addr); - /* clock in bit */ + /* clock in bit */ udelay(eeprom_udelay); devpriv->plx_control_bits |= PLX_CNTRL_EESK; writel(devpriv->plx_control_bits, plx_control_addr); @@ -3749,10 +3748,10 @@ static uint16_t read_eeprom(struct comedi_device *dev, uint8_t address) devpriv->plx_control_bits &= ~PLX_CNTRL_EESK; writel(devpriv->plx_control_bits, plx_control_addr); } - /* read back value from eeprom memory location */ + /* read back value from eeprom memory location */ value = 0; for (bit = 1 << (value_length - 1); bit; bit >>= 1) { - /* clock out bit */ + /* clock out bit */ udelay(eeprom_udelay); devpriv->plx_control_bits |= PLX_CNTRL_EESK; writel(devpriv->plx_control_bits, plx_control_addr); @@ -3764,7 +3763,7 @@ static uint16_t read_eeprom(struct comedi_device *dev, uint8_t address) value |= bit; } - /* deactivate eeprom serial input */ + /* deactivate eeprom serial input */ udelay(eeprom_udelay); devpriv->plx_control_bits &= ~PLX_CNTRL_EECS; writel(devpriv->plx_control_bits, plx_control_addr); @@ -3781,9 +3780,7 @@ static int eeprom_read_insn(struct comedi_device *dev, return 1; } -/* - * Allocate and initialize the subdevice structures. - */ +/* Allocate and initialize the subdevice structures. */ static int setup_subdevices(struct comedi_device *dev) { const struct pcidas64_board *board = dev->board_ptr; @@ -3822,7 +3819,7 @@ static int setup_subdevices(struct comedi_device *dev) * (not internal calibration sources) */ devpriv->i2c_cal_range_bits = adc_src_4020_bits(4); - /* set channels to +-5 volt input ranges */ + /* set channels to +-5 volt input ranges */ for (i = 0; i < s->n_chan; i++) devpriv->i2c_cal_range_bits |= attenuate_bit(i); data = devpriv->i2c_cal_range_bits; @@ -3855,7 +3852,7 @@ static int setup_subdevices(struct comedi_device *dev) s->type = COMEDI_SUBD_UNUSED; } - /* digital input */ + /* digital input */ s = &dev->subdevices[2]; if (board->layout == LAYOUT_64XX) { s->type = COMEDI_SUBD_DI; @@ -3868,7 +3865,7 @@ static int setup_subdevices(struct comedi_device *dev) s->type = COMEDI_SUBD_UNUSED; } - /* digital output */ + /* digital output */ if (board->layout == LAYOUT_64XX) { s = &dev->subdevices[3]; s->type = COMEDI_SUBD_DO; @@ -3897,7 +3894,7 @@ static int setup_subdevices(struct comedi_device *dev) s->type = COMEDI_SUBD_UNUSED; } - /* 8 channel dio for 60xx */ + /* 8 channel dio for 60xx */ s = &dev->subdevices[5]; if (board->layout == LAYOUT_60XX) { s->type = COMEDI_SUBD_DIO; @@ -3911,7 +3908,7 @@ static int setup_subdevices(struct comedi_device *dev) s->type = COMEDI_SUBD_UNUSED; } - /* caldac */ + /* caldac */ s = &dev->subdevices[6]; s->type = COMEDI_SUBD_CALIB; s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; @@ -3931,7 +3928,7 @@ static int setup_subdevices(struct comedi_device *dev) s->readback[i] = s->maxdata / 2; } - /* 2 channel ad8402 potentiometer */ + /* 2 channel ad8402 potentiometer */ s = &dev->subdevices[7]; if (board->layout == LAYOUT_64XX) { s->type = COMEDI_SUBD_CALIB; @@ -3965,7 +3962,7 @@ static int setup_subdevices(struct comedi_device *dev) s->type = COMEDI_SUBD_UNUSED; } - /* user counter subd XXX */ + /* user counter subd XXX */ s = &dev->subdevices[9]; s->type = COMEDI_SUBD_UNUSED; @@ -4011,7 +4008,7 @@ static int auto_attach(struct comedi_device *dev, return -ENOMEM; } - /* figure out what local addresses are */ + /* figure out what local addresses are */ local_range = readl(devpriv->plx9080_iobase + PLX_REG_LAS0RR) & PLX_LASRR_MEM_MASK; local_decode = readl(devpriv->plx9080_iobase + PLX_REG_LAS0BA) & -- cgit v0.10.2 From f8d791f2abfee69d47a2d4596e909e83acdec2b4 Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Fri, 26 Aug 2016 19:13:36 -0400 Subject: staging: comedi: jr3_pci.h: Fix checkpatch warning Fix checkpatch.pl warning: Block comments use * on subsequent lines Block comments use a trailing */ on a separate line Block comments starts with /* followed by comments on the next line Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/drivers/jr3_pci.h b/drivers/staging/comedi/drivers/jr3_pci.h index 356811d..f10a84f 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.h +++ b/drivers/staging/comedi/drivers/jr3_pci.h @@ -1,4 +1,5 @@ -/* Helper types to take care of the fact that the DSP card memory +/* + * Helper types to take care of the fact that the DSP card memory * is 16 bits, but aligned on a 32 bit PCI boundary */ @@ -22,7 +23,8 @@ static inline void set_s16(s32 __iomem *p, s16 val) writel(val, p); } -/* The raw data is stored in a format which facilitates rapid +/* + * The raw data is stored in a format which facilitates rapid * processing by the JR3 DSP chip. The raw_channel structure shows the * format for a single channel of data. Each channel takes four, * two-byte words. @@ -47,7 +49,8 @@ struct raw_channel { s32 reserved[2]; }; -/* The force_array structure shows the layout for the decoupled and +/* + * The force_array structure shows the layout for the decoupled and * filtered force data. */ struct force_array { @@ -61,7 +64,8 @@ struct force_array { s32 v2; }; -/* The six_axis_array structure shows the layout for the offsets and +/* + * The six_axis_array structure shows the layout for the offsets and * the full scales. */ struct six_axis_array { @@ -74,7 +78,8 @@ struct six_axis_array { }; /* VECT_BITS */ -/* The vect_bits structure shows the layout for indicating +/* + * The vect_bits structure shows the layout for indicating * which axes to use in computing the vectors. Each bit signifies * selection of a single axis. The V1x axis bit corresponds to a hex * value of 0x0001 and the V2z bit corresponds to a hex value of @@ -100,12 +105,14 @@ enum { }; /* WARNING_BITS */ -/* The warning_bits structure shows the bit pattern for the warning +/* + * The warning_bits structure shows the bit pattern for the warning * word. The bit fields are shown from bit 0 (lsb) to bit 15 (msb). */ -/* XX_NEAR_SET */ -/* The xx_near_sat bits signify that the indicated axis has reached or +/* XX_NEAR_SET */ +/* + * The xx_near_sat bits signify that the indicated axis has reached or * exceeded the near saturation value. */ @@ -118,12 +125,13 @@ enum { mz_near_sat = 0x0020 }; -/* ERROR_BITS */ -/* XX_SAT */ -/* MEMORY_ERROR */ -/* SENSOR_CHANGE */ +/* ERROR_BITS */ +/* XX_SAT */ +/* MEMORY_ERROR */ +/* SENSOR_CHANGE */ -/* The error_bits structure shows the bit pattern for the error word. +/* + * The error_bits structure shows the bit pattern for the error word. * The bit fields are shown from bit 0 (lsb) to bit 15 (msb). The * xx_sat bits signify that the indicated axis has reached or exceeded * the saturation value. The memory_error bit indicates that a problem @@ -134,9 +142,10 @@ enum { * */ -/* SYSTEM_BUSY */ +/* SYSTEM_BUSY */ -/* The system_busy bit indicates that the JR3 DSP is currently busy +/* + * The system_busy bit indicates that the JR3 DSP is currently busy * and is not calculating force data. This occurs when a new * coordinate transformation, or new sensor full scale is set by the * user. A very fast system using the force data for feedback might @@ -146,9 +155,10 @@ enum { * calibration CRC. */ -/* CAL_CRC_BAD */ +/* CAL_CRC_BAD */ -/* The cal_crc_bad bit indicates that the calibration CRC has not +/* + * The cal_crc_bad bit indicates that the calibration CRC has not * calculated to zero. CRC is short for cyclic redundancy code. It is * a method for determining the integrity of messages in data * communication. The calibration data stored inside the sensor is @@ -168,7 +178,8 @@ enum { /* WATCH_DOG */ /* WATCH_DOG2 */ -/* The watch_dog and watch_dog2 bits are sensor, not processor, watch +/* + * The watch_dog and watch_dog2 bits are sensor, not processor, watch * dog bits. Watch_dog indicates that the sensor data line seems to be * acting correctly, while watch_dog2 indicates that sensor data and * clock are being received. It is possible for watch_dog2 to go off @@ -192,9 +203,10 @@ enum error_bits_t { watch_dog = 0x8000 }; -/* THRESH_STRUCT */ +/* THRESH_STRUCT */ -/* This structure shows the layout for a single threshold packet inside of a +/* + * This structure shows the layout for a single threshold packet inside of a * load envelope. Each load envelope can contain several threshold structures. * 1. data_address contains the address of the data for that threshold. This * includes filtered, unfiltered, raw, rate, counters, error and warning data @@ -210,9 +222,10 @@ struct thresh_struct { s32 bit_pattern; }; -/* LE_STRUCT */ +/* LE_STRUCT */ -/* Layout of a load enveloped packet. Four thresholds are showed ... for more +/* + * Layout of a load enveloped packet. Four thresholds are showed ... for more * see manual (pag.25) * 1. latch_bits is a bit pattern that show which bits the user wants to latch. * The latched bits will not be reset once the threshold which set them is @@ -228,8 +241,9 @@ struct le_struct { s32 reserved; }; -/* LINK_TYPES */ -/* Link types is an enumerated value showing the different possible transform +/* LINK_TYPES */ +/* + * Link types is an enumerated value showing the different possible transform * link types. * 0 - end transform packet * 1 - translate along X axis (TX) @@ -252,8 +266,8 @@ enum link_types { neg }; -/* TRANSFORM */ -/* Structure used to describe a transform. */ +/* TRANSFORM */ +/* Structure used to describe a transform. */ struct intern_transform { struct { u32 link_type; @@ -261,23 +275,29 @@ struct intern_transform { } link[8]; }; -/* JR3 force/torque sensor data definition. For more information see sensor - * and hardware manuals. +/* + * JR3 force/torque sensor data definition. For more information see sensor + * and hardware manuals. */ struct jr3_channel { - /* Raw_channels is the area used to store the raw data coming from */ - /* the sensor. */ + /* + * Raw_channels is the area used to store the raw data coming from + * the sensor. + */ struct raw_channel raw_channels[16]; /* offset 0x0000 */ - /* Copyright is a null terminated ASCII string containing the JR3 */ - /* copyright notice. */ + /* + * Copyright is a null terminated ASCII string containing the JR3 + * copyright notice. + */ u32 copyright[0x0018]; /* offset 0x0040 */ s32 reserved1[0x0008]; /* offset 0x0058 */ - /* Shunts contains the sensor shunt readings. Some JR3 sensors have + /* + * Shunts contains the sensor shunt readings. Some JR3 sensors have * the ability to have their gains adjusted. This allows the * hardware full scales to be adjusted to potentially allow * better resolution or dynamic range. For sensors that have @@ -298,25 +318,29 @@ struct jr3_channel { * command (10) set new full scales (pg. 38). */ - struct six_axis_array shunts; /* offset 0x0060 */ - s32 reserved2[2]; /* offset 0x0066 */ + struct six_axis_array shunts; /* offset 0x0060 */ + s32 reserved2[2]; /* offset 0x0066 */ - /* Default_FS contains the full scale that is used if the user does */ - /* not set a full scale. */ + /* + * Default_FS contains the full scale that is used if the user does + * not set a full scale. + */ struct six_axis_array default_FS; /* offset 0x0068 */ - s32 reserved3; /* offset 0x006e */ + s32 reserved3; /* offset 0x006e */ - /* Load_envelope_num is the load envelope number that is currently + /* + * Load_envelope_num is the load envelope number that is currently * in use. This value is set by the user after one of the load * envelopes has been initialized. */ - s32 load_envelope_num; /* offset 0x006f */ + s32 load_envelope_num; /* offset 0x006f */ /* Min_full_scale is the recommend minimum full scale. */ - /* These values in conjunction with max_full_scale (pg. 9) helps + /* + * These values in conjunction with max_full_scale (pg. 9) helps * determine the appropriate value for setting the full scales. The * software allows the user to set the sensor full scale to an * arbitrary value. But setting the full scales has some hazards. If @@ -342,30 +366,35 @@ struct jr3_channel { */ struct six_axis_array min_full_scale; /* offset 0x0070 */ - s32 reserved4; /* offset 0x0076 */ + s32 reserved4; /* offset 0x0076 */ - /* Transform_num is the transform number that is currently in use. + /* + * Transform_num is the transform number that is currently in use. * This value is set by the JR3 DSP after the user has used command * (5) use transform # (pg. 33). */ - s32 transform_num; /* offset 0x0077 */ + s32 transform_num; /* offset 0x0077 */ - /* Max_full_scale is the recommended maximum full scale. See */ - /* min_full_scale (pg. 9) for more details. */ + /* + * Max_full_scale is the recommended maximum full scale. + * See min_full_scale (pg. 9) for more details. + */ struct six_axis_array max_full_scale; /* offset 0x0078 */ - s32 reserved5; /* offset 0x007e */ + s32 reserved5; /* offset 0x007e */ - /* Peak_address is the address of the data which will be monitored + /* + * Peak_address is the address of the data which will be monitored * by the peak routine. This value is set by the user. The peak * routine will monitor any 8 contiguous addresses for peak values. * (ex. to watch filter3 data for peaks, set this value to 0x00a8). */ - s32 peak_address; /* offset 0x007f */ + s32 peak_address; /* offset 0x007f */ - /* Full_scale is the sensor full scales which are currently in use. + /* + * Full_scale is the sensor full scales which are currently in use. * Decoupled and filtered data is scaled so that +/- 16384 is equal * to the full scales. The engineering units used are indicated by * the units value discussed on page 16. The full scales for Fx, Fy, @@ -377,9 +406,10 @@ struct jr3_channel { * axes used for each vector respectively. */ - struct force_array full_scale; /* offset 0x0080 */ + struct force_array full_scale; /* offset 0x0080 */ - /* Offsets contains the sensor offsets. These values are subtracted from + /* + * Offsets contains the sensor offsets. These values are subtracted from * the sensor data to obtain the decoupled data. The offsets are set a * few seconds (< 10) after the calibration data has been received. * They are set so that the output data will be zero. These values @@ -392,23 +422,26 @@ struct jr3_channel { * about Z by 90 degrees, FY would be 5 and all others would be zero. */ - struct six_axis_array offsets; /* offset 0x0088 */ + struct six_axis_array offsets; /* offset 0x0088 */ - /* Offset_num is the number of the offset currently in use. This + /* + * Offset_num is the number of the offset currently in use. This * value is set by the JR3 DSP after the user has executed the use * offset # command (pg. 34). It can vary between 0 and 15. */ - s32 offset_num; /* offset 0x008e */ + s32 offset_num; /* offset 0x008e */ - /* Vect_axes is a bit map showing which of the axes are being used + /* + * Vect_axes is a bit map showing which of the axes are being used * in the vector calculations. This value is set by the JR3 DSP * after the user has executed the set vector axes command (pg. 37). */ - u32 vect_axes; /* offset 0x008f */ + u32 vect_axes; /* offset 0x008f */ - /* Filter0 is the decoupled, unfiltered data from the JR3 sensor. + /* + * Filter0 is the decoupled, unfiltered data from the JR3 sensor. * This data has had the offsets removed. * * These force_arrays hold the filtered data. The decoupled data is @@ -420,23 +453,27 @@ struct jr3_channel { * cutoff at 125 Hz, 31.25 Hz, 7.813 Hz, 1.953 Hz and 0.4883 Hz. */ - struct force_array filter[7]; /* offset 0x0090, - offset 0x0098, - offset 0x00a0, - offset 0x00a8, - offset 0x00b0, - offset 0x00b8 , - offset 0x00c0 */ - - /* Rate_data is the calculated rate data. It is a first derivative + struct force_array filter[7]; /* + * offset 0x0090, + * offset 0x0098, + * offset 0x00a0, + * offset 0x00a8, + * offset 0x00b0, + * offset 0x00b8, + * offset 0x00c0 + */ + + /* + * Rate_data is the calculated rate data. It is a first derivative * calculation. It is calculated at a frequency specified by the * variable rate_divisor (pg. 12). The data on which the rate is * calculated is specified by the variable rate_address (pg. 12). */ - struct force_array rate_data; /* offset 0x00c8 */ + struct force_array rate_data; /* offset 0x00c8 */ - /* Minimum_data & maximum_data are the minimum and maximum (peak) + /* + * Minimum_data & maximum_data are the minimum and maximum (peak) * data values. The JR3 DSP can monitor any 8 contiguous data items * for minimums and maximums at full sensor bandwidth. This area is * only updated at user request. This is done so that the user does @@ -451,7 +488,8 @@ struct jr3_channel { struct force_array minimum_data; /* offset 0x00d0 */ struct force_array maximum_data; /* offset 0x00d8 */ - /* Near_sat_value & sat_value contain the value used to determine if + /* + * Near_sat_value & sat_value contain the value used to determine if * the raw sensor is saturated. Because of decoupling and offset * removal, it is difficult to tell from the processed data if the * sensor is saturated. These values, in conjunction with the error @@ -465,10 +503,11 @@ struct jr3_channel { * sat_value = 32768 - 2^(16 - ADC bits) */ - s32 near_sat_value; /* offset 0x00e0 */ - s32 sat_value; /* offset 0x00e1 */ + s32 near_sat_value; /* offset 0x00e0 */ + s32 sat_value; /* offset 0x00e1 */ - /* Rate_address, rate_divisor & rate_count contain the data used to + /* + * Rate_address, rate_divisor & rate_count contain the data used to * control the calculations of the rates. Rate_address is the * address of the data used for the rate calculation. The JR3 DSP * will calculate rates for any 8 contiguous values (ex. to @@ -485,11 +524,12 @@ struct jr3_channel { * will minimize the time necessary to start the rate calculations. */ - s32 rate_address; /* offset 0x00e2 */ - u32 rate_divisor; /* offset 0x00e3 */ - u32 rate_count; /* offset 0x00e4 */ + s32 rate_address; /* offset 0x00e2 */ + u32 rate_divisor; /* offset 0x00e3 */ + u32 rate_count; /* offset 0x00e4 */ - /* Command_word2 through command_word0 are the locations used to + /* + * Command_word2 through command_word0 are the locations used to * send commands to the JR3 DSP. Their usage varies with the command * and is detailed later in the Command Definitions section (pg. * 29). In general the user places values into various memory @@ -502,11 +542,12 @@ struct jr3_channel { * command_word1). */ - s32 command_word2; /* offset 0x00e5 */ - s32 command_word1; /* offset 0x00e6 */ - s32 command_word0; /* offset 0x00e7 */ + s32 command_word2; /* offset 0x00e5 */ + s32 command_word1; /* offset 0x00e6 */ + s32 command_word0; /* offset 0x00e7 */ - /* Count1 through count6 are unsigned counters which are incremented + /* + * Count1 through count6 are unsigned counters which are incremented * every time the matching filters are calculated. Filter1 is * calculated at the sensor data bandwidth. So this counter would * increment at 8 kHz for a typical sensor. The rest of the counters @@ -518,14 +559,15 @@ struct jr3_channel { * once. */ - u32 count1; /* offset 0x00e8 */ - u32 count2; /* offset 0x00e9 */ - u32 count3; /* offset 0x00ea */ - u32 count4; /* offset 0x00eb */ - u32 count5; /* offset 0x00ec */ - u32 count6; /* offset 0x00ed */ + u32 count1; /* offset 0x00e8 */ + u32 count2; /* offset 0x00e9 */ + u32 count3; /* offset 0x00ea */ + u32 count4; /* offset 0x00eb */ + u32 count5; /* offset 0x00ec */ + u32 count6; /* offset 0x00ed */ - /* Error_count is a running count of data reception errors. If this + /* + * Error_count is a running count of data reception errors. If this * counter is changing rapidly, it probably indicates a bad sensor * cable connection or other hardware problem. In most installations * error_count should not change at all. But it is possible in an @@ -535,75 +577,84 @@ struct jr3_channel { * where this counter counts a bad sample, that sample is ignored. */ - u32 error_count; /* offset 0x00ee */ + u32 error_count; /* offset 0x00ee */ - /* Count_x is a counter which is incremented every time the JR3 DSP + /* + * Count_x is a counter which is incremented every time the JR3 DSP * searches its job queues and finds nothing to do. It indicates the * amount of idle time the JR3 DSP has available. It can also be * used to determine if the JR3 DSP is alive. See the Performance * Issues section on pg. 49 for more details. */ - u32 count_x; /* offset 0x00ef */ + u32 count_x; /* offset 0x00ef */ - /* Warnings & errors contain the warning and error bits + /* + * Warnings & errors contain the warning and error bits * respectively. The format of these two words is discussed on page * 21 under the headings warnings_bits and error_bits. */ - u32 warnings; /* offset 0x00f0 */ - u32 errors; /* offset 0x00f1 */ + u32 warnings; /* offset 0x00f0 */ + u32 errors; /* offset 0x00f1 */ - /* Threshold_bits is a word containing the bits that are set by the + /* + * Threshold_bits is a word containing the bits that are set by the * load envelopes. See load_envelopes (pg. 17) and thresh_struct * (pg. 23) for more details. */ - s32 threshold_bits; /* offset 0x00f2 */ + s32 threshold_bits; /* offset 0x00f2 */ - /* Last_crc is the value that shows the actual calculated CRC. CRC + /* + * Last_crc is the value that shows the actual calculated CRC. CRC * is short for cyclic redundancy code. It should be zero. See the * description for cal_crc_bad (pg. 21) for more information. */ - s32 last_CRC; /* offset 0x00f3 */ + s32 last_CRC; /* offset 0x00f3 */ - /* EEProm_ver_no contains the version number of the sensor EEProm. + /* + * EEProm_ver_no contains the version number of the sensor EEProm. * EEProm version numbers can vary between 0 and 255. * Software_ver_no contains the software version number. Version * 3.02 would be stored as 302. */ - s32 eeprom_ver_no; /* offset 0x00f4 */ - s32 software_ver_no; /* offset 0x00f5 */ + s32 eeprom_ver_no; /* offset 0x00f4 */ + s32 software_ver_no; /* offset 0x00f5 */ - /* Software_day & software_year are the release date of the software + /* + * Software_day & software_year are the release date of the software * the JR3 DSP is currently running. Day is the day of the year, * with January 1 being 1, and December 31, being 365 for non leap * years. */ - s32 software_day; /* offset 0x00f6 */ - s32 software_year; /* offset 0x00f7 */ + s32 software_day; /* offset 0x00f6 */ + s32 software_year; /* offset 0x00f7 */ - /* Serial_no & model_no are the two values which uniquely identify a + /* + * Serial_no & model_no are the two values which uniquely identify a * sensor. This model number does not directly correspond to the JR3 * model number, but it will provide a unique identifier for * different sensor configurations. */ - u32 serial_no; /* offset 0x00f8 */ - u32 model_no; /* offset 0x00f9 */ + u32 serial_no; /* offset 0x00f8 */ + u32 model_no; /* offset 0x00f9 */ - /* Cal_day & cal_year are the sensor calibration date. Day is the + /* + * Cal_day & cal_year are the sensor calibration date. Day is the * day of the year, with January 1 being 1, and December 31, being * 366 for leap years. */ - s32 cal_day; /* offset 0x00fa */ - s32 cal_year; /* offset 0x00fb */ + s32 cal_day; /* offset 0x00fa */ + s32 cal_year; /* offset 0x00fb */ - /* Units is an enumerated read only value defining the engineering + /* + * Units is an enumerated read only value defining the engineering * units used in the sensor full scale. The meanings of particular * values are discussed in the section detailing the force_units * structure on page 22. The engineering units are setto customer @@ -626,20 +677,22 @@ struct jr3_channel { * received. */ - u32 units; /* offset 0x00fc */ - s32 bits; /* offset 0x00fd */ - s32 channels; /* offset 0x00fe */ + u32 units; /* offset 0x00fc */ + s32 bits; /* offset 0x00fd */ + s32 channels; /* offset 0x00fe */ - /* Thickness specifies the overall thickness of the sensor from + /* + * Thickness specifies the overall thickness of the sensor from * flange to flange. The engineering units for this value are * contained in units (pg. 16). The sensor calibration is relative * to the center of the sensor. This value allows easy coordinate * transformation from the center of the sensor to either flange. */ - s32 thickness; /* offset 0x00ff */ + s32 thickness; /* offset 0x00ff */ - /* Load_envelopes is a table containing the load envelope + /* + * Load_envelopes is a table containing the load envelope * descriptions. There are 16 possible load envelope slots in the * table. The slots are on 16 word boundaries and are numbered 0-15. * Each load envelope needs to start at the beginning of a slot but @@ -655,7 +708,8 @@ struct jr3_channel { struct le_struct load_envelopes[0x10]; /* offset 0x0100 */ - /* Transforms is a table containing the transform descriptions. + /* + * Transforms is a table containing the transform descriptions. * There are 16 possible transform slots in the table. The slots are * on 16 word boundaries and are numbered 0-15. Each transform needs * to start at the beginning of a slot but need not be fully -- cgit v0.10.2 From da91a80a946f903ac71e0b93cd21f9448d9c692d Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Fri, 26 Aug 2016 19:13:49 -0400 Subject: staging: comedi: ni_atmio.c: Fix checkpatch warning Fix checkpatch.pl warning for 'Statements should start on a tabstop' Convert single line block comment to single line comment Align single line comment Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c index 162a000..ffcf7af 100644 --- a/drivers/staging/comedi/drivers/ni_atmio.c +++ b/drivers/staging/comedi/drivers/ni_atmio.c @@ -89,10 +89,7 @@ #include "ni_stc.h" #include "8255.h" -/* - * AT specific setup - */ - +/* AT specific setup */ static const struct ni_board_struct ni_boards[] = { { .name = "at-mio-16e-1", @@ -206,7 +203,7 @@ static const struct ni_board_struct ni_boards[] = { .n_adchan = 16, .ai_maxdata = 0xffff, .ai_fifo_depth = 512, - .alwaysdither = 1, /* unknown */ + .alwaysdither = 1, /* unknown */ .gainlkup = ai_gain_14, .ai_speed = 10000, .caldac = { dac8800, dac8043, ad8522 }, @@ -278,10 +275,10 @@ static const struct ni_board_struct *ni_atmio_probe(struct comedi_device *dev) } if (device_id == 255) dev_err(dev->class_dev, "can't find board\n"); - else if (device_id == 0) + else if (device_id == 0) dev_err(dev->class_dev, "EEPROM read error (?) or device not found\n"); - else + else dev_err(dev->class_dev, "unknown device ID %d -- contact author\n", device_id); -- cgit v0.10.2 From 1c454fabc215ec247f540e9b94d6a70cbe469c17 Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Fri, 26 Aug 2016 19:14:00 -0400 Subject: staging: comedi: s626.h: Fix checkpatch warning Fix checkpatch.pl warning for Comparisons should place the constant on the right side of the test Remove extra space after /* Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/drivers/s626.h b/drivers/staging/comedi/drivers/s626.h index 6a00a64..4cef452 100644 --- a/drivers/staging/comedi/drivers/s626.h +++ b/drivers/staging/comedi/drivers/s626.h @@ -79,7 +79,7 @@ /* Address offsets, in DWORDS, from base of DMA buffer. */ #define S626_DAC_WDMABUF_OS S626_ADC_DMABUF_DWORDS -/* Interrupt enable bit in ISR and IER. */ +/* Interrupt enable bit in ISR and IER. */ #define S626_IRQ_GPIO3 0x00000040 /* IRQ enable for GPIO3. */ #define S626_IRQ_RPS1 0x10000000 #define S626_ISR_AFOU 0x00000800 @@ -329,7 +329,7 @@ * WS1-WS4 = CS* outputs. */ -#if S626_PLATFORM == S626_INTEL /* +#if (S626_PLATFORM == S626_INTEL) /* * Base ACON1 config: always run * A1 based on TSL1. */ -- cgit v0.10.2 From d5e59c967830f99eb10100039cdc2e2d7e12f9c8 Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Fri, 26 Aug 2016 19:14:13 -0400 Subject: staging: comedi: jr3_pci.c: Fix checkpatch warning Fix checkpatch.pl warning 'line over 80 characters' Remove extra space after /* Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c index b9b686e..70390de 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.c +++ b/drivers/staging/comedi/drivers/jr3_pci.c @@ -141,7 +141,7 @@ static void set_transforms(struct jr3_channel __iomem *channel, { int i; - num &= 0x000f; /* Make sure that 0 <= num <= 15 */ + num &= 0x000f; /* Make sure that 0 <= num <= 15 */ for (i = 0; i < 8; i++) { set_u16(&channel->transforms[num].link[i].link_type, transf.link[i].link_type); @@ -323,10 +323,10 @@ static int read_idm_word(const u8 *data, size_t size, int *pos, int value; if (pos && val) { - /* Skip over non hex */ + /* Skip over non hex */ for (; *pos < size && !isxdigit(data[*pos]); (*pos)++) ; - /* Collect value */ + /* Collect value */ *val = 0; for (; *pos < size; (*pos)++) { value = hex_to_bin(data[*pos]); @@ -448,7 +448,8 @@ static int jr3_download_firmware(struct comedi_device *dev, return 0; } -static struct jr3_pci_poll_delay jr3_pci_poll_subdevice(struct comedi_subdevice *s) +static struct jr3_pci_poll_delay +jr3_pci_poll_subdevice(struct comedi_subdevice *s) { struct jr3_pci_subdev_private *spriv = s->private; struct jr3_pci_poll_delay result = poll_delay_min_max(1000, 2000); @@ -733,7 +734,7 @@ static int jr3_pci_auto_attach(struct comedi_device *dev, } } - /* Reset DSP card */ + /* Reset DSP card */ writel(0, &devpriv->iobase->channel[0].reset); ret = comedi_load_firmware(dev, &comedi_to_pci_dev(dev)->dev, @@ -763,7 +764,7 @@ static int jr3_pci_auto_attach(struct comedi_device *dev, data.copyright[i]) >> 8); } - /* Start card timer */ + /* Start card timer */ for (i = 0; i < dev->n_subdevices; i++) { s = &dev->subdevices[i]; spriv = s->private; -- cgit v0.10.2 From 4281c748d6dfe81fe6a8d9b06847a11545b71000 Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Fri, 26 Aug 2016 19:14:23 -0400 Subject: staging: comedi: ni_at_a2150: Fix checkpatch warning Fix checkpatch.pl warning 'line over 80 characters' Remove extra space after /* Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index 957fb9f..5a4dcc6 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -58,48 +58,52 @@ /* Registers and bits */ #define CONFIG_REG 0x0 -#define CHANNEL_BITS(x) ((x) & 0x7) +#define CHANNEL_BITS(x) ((x) & 0x7) #define CHANNEL_MASK 0x7 -#define CLOCK_SELECT_BITS(x) (((x) & 0x3) << 3) -#define CLOCK_DIVISOR_BITS(x) (((x) & 0x3) << 5) +#define CLOCK_SELECT_BITS(x) (((x) & 0x3) << 3) +#define CLOCK_DIVISOR_BITS(x) (((x) & 0x3) << 5) #define CLOCK_MASK (0xf << 3) -#define ENABLE0_BIT 0x80 /* enable (don't internally ground) channels 0 and 1 */ -#define ENABLE1_BIT 0x100 /* enable (don't internally ground) channels 2 and 3 */ -#define AC0_BIT 0x200 /* ac couple channels 0,1 */ -#define AC1_BIT 0x400 /* ac couple channels 2,3 */ -#define APD_BIT 0x800 /* analog power down */ -#define DPD_BIT 0x1000 /* digital power down */ -#define TRIGGER_REG 0x2 /* trigger config register */ -#define POST_TRIGGER_BITS 0x2 -#define DELAY_TRIGGER_BITS 0x3 -#define HW_TRIG_EN 0x10 /* enable hardware trigger */ -#define FIFO_START_REG 0x6 /* software start aquistion trigger */ -#define FIFO_RESET_REG 0x8 /* clears fifo + fifo flags */ -#define FIFO_DATA_REG 0xa /* read data */ -#define DMA_TC_CLEAR_REG 0xe /* clear dma terminal count interrupt */ -#define STATUS_REG 0x12 /* read only */ -#define FNE_BIT 0x1 /* fifo not empty */ -#define OVFL_BIT 0x8 /* fifo overflow */ -#define EDAQ_BIT 0x10 /* end of acquisition interrupt */ -#define DCAL_BIT 0x20 /* offset calibration in progress */ -#define INTR_BIT 0x40 /* interrupt has occurred */ -#define DMA_TC_BIT 0x80 /* dma terminal count interrupt has occurred */ -#define ID_BITS(x) (((x) >> 8) & 0x3) -#define IRQ_DMA_CNTRL_REG 0x12 /* write only */ -#define DMA_CHAN_BITS(x) ((x) & 0x7) /* sets dma channel */ -#define DMA_EN_BIT 0x8 /* enables dma */ -#define IRQ_LVL_BITS(x) (((x) & 0xf) << 4) /* sets irq level */ -#define FIFO_INTR_EN_BIT 0x100 /* enable fifo interrupts */ -#define FIFO_INTR_FHF_BIT 0x200 /* interrupt fifo half full */ -#define DMA_INTR_EN_BIT 0x800 /* enable interrupt on dma terminal count */ -#define DMA_DEM_EN_BIT 0x1000 /* enables demand mode dma */ +/* enable (don't internally ground) channels 0 and 1 */ +#define ENABLE0_BIT 0x80 +/* enable (don't internally ground) channels 2 and 3 */ +#define ENABLE1_BIT 0x100 +#define AC0_BIT 0x200 /* ac couple channels 0,1 */ +#define AC1_BIT 0x400 /* ac couple channels 2,3 */ +#define APD_BIT 0x800 /* analog power down */ +#define DPD_BIT 0x1000 /* digital power down */ +#define TRIGGER_REG 0x2 /* trigger config register */ +#define POST_TRIGGER_BITS 0x2 +#define DELAY_TRIGGER_BITS 0x3 +#define HW_TRIG_EN 0x10 /* enable hardware trigger */ +#define FIFO_START_REG 0x6 /* software start aquistion trigger */ +#define FIFO_RESET_REG 0x8 /* clears fifo + fifo flags */ +#define FIFO_DATA_REG 0xa /* read data */ +#define DMA_TC_CLEAR_REG 0xe /* clear dma terminal count interrupt */ +#define STATUS_REG 0x12 /* read only */ +#define FNE_BIT 0x1 /* fifo not empty */ +#define OVFL_BIT 0x8 /* fifo overflow */ +#define EDAQ_BIT 0x10 /* end of acquisition interrupt */ +#define DCAL_BIT 0x20 /* offset calibration in progress */ +#define INTR_BIT 0x40 /* interrupt has occurred */ +/* dma terminal count interrupt has occurred */ +#define DMA_TC_BIT 0x80 +#define ID_BITS(x) (((x) >> 8) & 0x3) +#define IRQ_DMA_CNTRL_REG 0x12 /* write only */ +#define DMA_CHAN_BITS(x) ((x) & 0x7) /* sets dma channel */ +#define DMA_EN_BIT 0x8 /* enables dma */ +#define IRQ_LVL_BITS(x) (((x) & 0xf) << 4) /* sets irq level */ +#define FIFO_INTR_EN_BIT 0x100 /* enable fifo interrupts */ +#define FIFO_INTR_FHF_BIT 0x200 /* interrupt fifo half full */ +/* enable interrupt on dma terminal count */ +#define DMA_INTR_EN_BIT 0x800 +#define DMA_DEM_EN_BIT 0x1000 /* enables demand mode dma */ #define I8253_BASE_REG 0x14 struct a2150_board { const char *name; - int clock[4]; /* master clock periods, in nanoseconds */ - int num_clocks; /* number of available master clock speeds */ - int ai_speed; /* maximum conversion rate in nanoseconds */ + int clock[4]; /* master clock periods, in nanoseconds */ + int num_clocks; /* number of available master clock speeds */ + int ai_speed; /* maximum conversion rate in nanoseconds */ }; /* analog input range */ @@ -129,8 +133,8 @@ static const struct a2150_board a2150_boards[] = { struct a2150_private { struct comedi_isadma *dma; unsigned int count; /* number of data points left to be taken */ - int irq_dma_bits; /* irq/dma register bits */ - int config_bits; /* config register bits */ + int irq_dma_bits; /* irq/dma register bits */ + int config_bits; /* config register bits */ }; /* interrupt service routine */ @@ -174,13 +178,13 @@ static irqreturn_t a2150_interrupt(int irq, void *d) */ residue = comedi_isadma_disable(desc->chan); - /* figure out how many points to read */ + /* figure out how many points to read */ max_points = comedi_bytes_to_samples(s, desc->size); num_points = max_points - comedi_bytes_to_samples(s, residue); if (devpriv->count < num_points && cmd->stop_src == TRIG_COUNT) num_points = devpriv->count; - /* figure out how many points will be stored next time */ + /* figure out how many points will be stored next time */ leftover = 0; if (cmd->stop_src == TRIG_NONE) { leftover = comedi_bytes_to_samples(s, desc->size); @@ -189,7 +193,8 @@ static irqreturn_t a2150_interrupt(int irq, void *d) if (leftover > max_points) leftover = max_points; } - /* there should only be a residue if collection was stopped by having + /* + * There should only be a residue if collection was stopped by having * the stop_src set to an external trigger, in which case there * will be no more data */ @@ -199,7 +204,7 @@ static irqreturn_t a2150_interrupt(int irq, void *d) for (i = 0; i < num_points; i++) { /* write data point to comedi buffer */ dpnt = buf[i]; - /* convert from 2's complement to unsigned coding */ + /* convert from 2's complement to unsigned coding */ dpnt ^= 0x8000; comedi_buf_write_samples(s, &dpnt, 1); if (cmd->stop_src == TRIG_COUNT) { @@ -229,14 +234,14 @@ static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s) struct comedi_isadma *dma = devpriv->dma; struct comedi_isadma_desc *desc = &dma->desc[0]; - /* disable dma on card */ + /* disable dma on card */ devpriv->irq_dma_bits &= ~DMA_INTR_EN_BIT & ~DMA_EN_BIT; outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG); - /* disable computer's dma */ + /* disable computer's dma */ comedi_isadma_disable(desc->chan); - /* clear fifo and reset triggering circuitry */ + /* clear fifo and reset triggering circuitry */ outw(0, dev->iobase + FIFO_RESET_REG); return 0; @@ -255,7 +260,7 @@ static int a2150_get_timing(struct comedi_device *dev, unsigned int *period, int lub_divisor_shift, lub_index, glb_divisor_shift, glb_index; int i, j; - /* initialize greatest lower and least upper bounds */ + /* initialize greatest lower and least upper bounds */ lub_divisor_shift = 3; lub_index = 0; lub = board->clock[lub_index] * (1 << lub_divisor_shift); @@ -263,19 +268,19 @@ static int a2150_get_timing(struct comedi_device *dev, unsigned int *period, glb_index = board->num_clocks - 1; glb = board->clock[glb_index] * (1 << glb_divisor_shift); - /* make sure period is in available range */ + /* make sure period is in available range */ if (*period < glb) *period = glb; if (*period > lub) *period = lub; - /* we can multiply period by 1, 2, 4, or 8, using (1 << i) */ + /* we can multiply period by 1, 2, 4, or 8, using (1 << i) */ for (i = 0; i < 4; i++) { - /* there are a maximum of 4 master clocks */ + /* there are a maximum of 4 master clocks */ for (j = 0; j < board->num_clocks; j++) { - /* temp is the period in nanosec we are evaluating */ + /* temp is the period in nanosec we are evaluating */ temp = board->clock[j] * (1 << i); - /* if it is the best match yet */ + /* if it is the best match yet */ if (temp < lub && temp >= *period) { lub_divisor_shift = i; lub_index = j; @@ -291,7 +296,7 @@ static int a2150_get_timing(struct comedi_device *dev, unsigned int *period, switch (flags & CMDF_ROUND_MASK) { case CMDF_ROUND_NEAREST: default: - /* if least upper bound is better approximation */ + /* if least upper bound is better approximation */ if (lub - *period < *period - glb) *period = lub; else @@ -305,7 +310,7 @@ static int a2150_get_timing(struct comedi_device *dev, unsigned int *period, break; } - /* set clock bits for config register appropriately */ + /* set clock bits for config register appropriately */ devpriv->config_bits &= ~CLOCK_MASK; if (*period == lub) { devpriv->config_bits |= @@ -480,7 +485,7 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) "dma incompatible with hard real-time interrupt (CMDF_PRIORITY), aborting\n"); return -1; } - /* clear fifo and reset triggering circuitry */ + /* clear fifo and reset triggering circuitry */ outw(0, dev->iobase + FIFO_RESET_REG); /* setup chanlist */ @@ -488,7 +493,7 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) cmd->chanlist_len) < 0) return -1; - /* setup ac/dc coupling */ + /* setup ac/dc coupling */ if (CR_AREF(cmd->chanlist[0]) == AREF_OTHER) devpriv->config_bits |= AC0_BIT; else @@ -498,18 +503,18 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) else devpriv->config_bits &= ~AC1_BIT; - /* setup timing */ + /* setup timing */ a2150_get_timing(dev, &cmd->scan_begin_arg, cmd->flags); - /* send timing, channel, config bits */ + /* send timing, channel, config bits */ outw(devpriv->config_bits, dev->iobase + CONFIG_REG); - /* initialize number of samples remaining */ + /* initialize number of samples remaining */ devpriv->count = cmd->stop_arg * cmd->chanlist_len; comedi_isadma_disable(desc->chan); - /* set size of transfer to fill in 1/3 second */ + /* set size of transfer to fill in 1/3 second */ #define ONE_THIRD_SECOND 333333333 desc->size = comedi_bytes_per_sample(s) * cmd->chanlist_len * ONE_THIRD_SECOND / cmd->scan_begin_arg; @@ -527,36 +532,39 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) */ outw(0x00, dev->iobase + DMA_TC_CLEAR_REG); - /* enable dma on card */ + /* enable dma on card */ devpriv->irq_dma_bits |= DMA_INTR_EN_BIT | DMA_EN_BIT; outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG); - /* may need to wait 72 sampling periods if timing was changed */ + /* may need to wait 72 sampling periods if timing was changed */ comedi_8254_load(dev->pacer, 2, 72, I8254_MODE0 | I8254_BINARY); - /* setup start triggering */ + /* setup start triggering */ trigger_bits = 0; - /* decide if we need to wait 72 periods for valid data */ + /* decide if we need to wait 72 periods for valid data */ if (cmd->start_src == TRIG_NOW && (old_config_bits & CLOCK_MASK) != (devpriv->config_bits & CLOCK_MASK)) { - /* set trigger source to delay trigger */ + /* set trigger source to delay trigger */ trigger_bits |= DELAY_TRIGGER_BITS; } else { - /* otherwise no delay */ + /* otherwise no delay */ trigger_bits |= POST_TRIGGER_BITS; } - /* enable external hardware trigger */ + /* enable external hardware trigger */ if (cmd->start_src == TRIG_EXT) { trigger_bits |= HW_TRIG_EN; } else if (cmd->start_src == TRIG_OTHER) { - /* XXX add support for level/slope start trigger using TRIG_OTHER */ + /* + * XXX add support for level/slope start trigger + * using TRIG_OTHER + */ dev_err(dev->class_dev, "you shouldn't see this?\n"); } - /* send trigger config bits */ + /* send trigger config bits */ outw(trigger_bits, dev->iobase + TRIGGER_REG); - /* start acquisition for soft trigger */ + /* start acquisition for soft trigger */ if (cmd->start_src == TRIG_NOW) outw(0, dev->iobase + FIFO_START_REG); @@ -583,28 +591,28 @@ static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int n; int ret; - /* clear fifo and reset triggering circuitry */ + /* clear fifo and reset triggering circuitry */ outw(0, dev->iobase + FIFO_RESET_REG); /* setup chanlist */ if (a2150_set_chanlist(dev, CR_CHAN(insn->chanspec), 1) < 0) return -1; - /* set dc coupling */ + /* set dc coupling */ devpriv->config_bits &= ~AC0_BIT; devpriv->config_bits &= ~AC1_BIT; - /* send timing, channel, config bits */ + /* send timing, channel, config bits */ outw(devpriv->config_bits, dev->iobase + CONFIG_REG); - /* disable dma on card */ + /* disable dma on card */ devpriv->irq_dma_bits &= ~DMA_INTR_EN_BIT & ~DMA_EN_BIT; outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG); - /* setup start triggering */ + /* setup start triggering */ outw(0, dev->iobase + TRIGGER_REG); - /* start acquisition for soft trigger */ + /* start acquisition for soft trigger */ outw(0, dev->iobase + FIFO_START_REG); /* @@ -619,7 +627,7 @@ static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, inw(dev->iobase + FIFO_DATA_REG); } - /* read data */ + /* read data */ for (n = 0; n < insn->n; n++) { ret = comedi_timeout(dev, s, insn, a2150_ai_eoc, 0); if (ret) @@ -629,7 +637,7 @@ static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, data[n] ^= 0x8000; } - /* clear fifo and reset triggering circuitry */ + /* clear fifo and reset triggering circuitry */ outw(0, dev->iobase + FIFO_RESET_REG); return n; @@ -736,16 +744,16 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->cancel = a2150_cancel; } - /* set card's irq and dma levels */ + /* set card's irq and dma levels */ outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG); - /* reset and sync adc clock circuitry */ + /* reset and sync adc clock circuitry */ outw_p(DPD_BIT | APD_BIT, dev->iobase + CONFIG_REG); outw_p(DPD_BIT, dev->iobase + CONFIG_REG); - /* initialize configuration register */ + /* initialize configuration register */ devpriv->config_bits = 0; outw(devpriv->config_bits, dev->iobase + CONFIG_REG); - /* wait until offset calibration is done, then enable analog inputs */ + /* wait until offset calibration is done, then enable analog inputs */ for (i = 0; i < timeout; i++) { if ((DCAL_BIT & inw(dev->iobase + STATUS_REG)) == 0) break; -- cgit v0.10.2 From 9f963096984d0296ce821727310e3cf923b1ef8d Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Fri, 26 Aug 2016 19:14:35 -0400 Subject: staging: comedi: cb_pcidas64: Fix checkpath warning Fix checkpatch.pl warning: Please use a blank line after function/struct/union/enum declarations Move macro definition to the top of the file Aligne macro definitions Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index ac24c10..cb9c269 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -94,7 +94,8 @@ * maybe I'll support this someday */ #define PRESCALED_TIMER_BASE 10000 -#define DMA_BUFFER_SIZE 0x1000 +#define DMA_BUFFER_SIZE 0x1000 +#define DAC_FIFO_SIZE 0x2000 /* maximum value that can be loaded into board's 24-bit counters */ static const int max_counter_value = 0xffffff; @@ -227,7 +228,6 @@ enum hw_config_contents { DAC_FIFO_SIZE_MASK = 0xff00, /* bits that set dac fifo size */ DAC_FIFO_BITS = 0xf800, /* 8k sample ao fifo */ }; -#define DAC_FIFO_SIZE 0x2000 enum daq_atrig_low_4020_contents { /* use trig/ext clk bnc input for analog gate signal */ -- cgit v0.10.2 From e994608150803215f01adc2c699dabee9d295191 Mon Sep 17 00:00:00 2001 From: Laura Abbott <labbott@redhat.com> Date: Thu, 1 Sep 2016 15:40:41 -0700 Subject: staging: android: ion: Drop heap type masks There is no advantage to having heap types be a mask. The ion client has long since dropped the mask. Drop the notion of heap type masks as well. Signed-off-by: Laura Abbott <labbott@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/uapi/ion.h b/drivers/staging/android/uapi/ion.h index 0a8e40f..a9c4e8b 100644 --- a/drivers/staging/android/uapi/ion.h +++ b/drivers/staging/android/uapi/ion.h @@ -44,14 +44,8 @@ enum ion_heap_type { * must be last so device specific heaps always * are at the end of this enum */ - ION_NUM_HEAPS = 16, }; -#define ION_HEAP_SYSTEM_MASK (1 << ION_HEAP_TYPE_SYSTEM) -#define ION_HEAP_SYSTEM_CONTIG_MASK (1 << ION_HEAP_TYPE_SYSTEM_CONTIG) -#define ION_HEAP_CARVEOUT_MASK (1 << ION_HEAP_TYPE_CARVEOUT) -#define ION_HEAP_TYPE_DMA_MASK (1 << ION_HEAP_TYPE_DMA) - #define ION_NUM_HEAP_IDS (sizeof(unsigned int) * 8) /** -- cgit v0.10.2 From a554d48a063be2a0d85af3f5cebc23c5ffbad85e Mon Sep 17 00:00:00 2001 From: Anson Jacob <ansonjacob.aj@gmail.com> Date: Fri, 2 Sep 2016 01:08:42 -0400 Subject: staging: i4l: act2000: Remove braces for single statement Fix checkpatch.pl warning: braces {} are not necessary for single statement blocks Signed-off-by: Anson Jacob <ansonjacob.aj@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/i4l/act2000/act2000_isa.c b/drivers/staging/i4l/act2000/act2000_isa.c index f0eb844..1d93151 100644 --- a/drivers/staging/i4l/act2000/act2000_isa.c +++ b/drivers/staging/i4l/act2000/act2000_isa.c @@ -134,9 +134,9 @@ act2000_isa_config_irq(act2000_card *card, short irq) { int old_irq; - if (card->flags & ACT2000_FLAGS_IVALID) { + if (card->flags & ACT2000_FLAGS_IVALID) free_irq(card->irq, card); - } + card->flags &= ~ACT2000_FLAGS_IVALID; outb(ISA_COR_IRQOFF, ISA_PORT_COR); if (!irq) -- cgit v0.10.2 From 287faa5e6bce2123dd28eafe7876dd56e9091bfa Mon Sep 17 00:00:00 2001 From: Aaro Koskinen <aaro.koskinen@iki.fi> Date: Wed, 31 Aug 2016 23:57:36 +0300 Subject: staging: octeon: disable rx interrupts in oct_rx_shutdown Disable RX interrupts in oct_rx_shutdown(). This way we don't need to expose the RX IRQ numbers outside the RX module. Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c index a10fe3a..5b26f2a 100644 --- a/drivers/staging/octeon/ethernet-rx.c +++ b/drivers/staging/octeon/ethernet-rx.c @@ -495,5 +495,14 @@ void cvm_oct_rx_initialize(void) void cvm_oct_rx_shutdown(void) { + /* Disable POW interrupt */ + if (OCTEON_IS_MODEL(OCTEON_CN68XX)) + cvmx_write_csr(CVMX_SSO_WQ_INT_THRX(pow_receive_group), 0); + else + cvmx_write_csr(CVMX_POW_WQ_INT_THRX(pow_receive_group), 0); + + /* Free the interrupt handler */ + free_irq(OCTEON_IRQ_WORKQ0 + pow_receive_group, cvm_oct_device); + netif_napi_del(&cvm_oct_napi); } diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index 073a1e3..1e2e1ef 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -853,17 +853,8 @@ static int cvm_oct_remove(struct platform_device *pdev) { int port; - /* Disable POW interrupt */ - if (OCTEON_IS_MODEL(OCTEON_CN68XX)) - cvmx_write_csr(CVMX_SSO_WQ_INT_THRX(pow_receive_group), 0); - else - cvmx_write_csr(CVMX_POW_WQ_INT_THRX(pow_receive_group), 0); - cvmx_ipd_disable(); - /* Free the interrupt handler */ - free_irq(OCTEON_IRQ_WORKQ0 + pow_receive_group, cvm_oct_device); - atomic_inc_return(&cvm_oct_poll_queue_stopping); cancel_delayed_work_sync(&cvm_oct_rx_refill_work); -- cgit v0.10.2 From 513ff86386f6ba2ea5769f1ab3383036ab53d9f0 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen <aaro.koskinen@iki.fi> Date: Wed, 31 Aug 2016 23:57:37 +0300 Subject: staging: octeon: use passed interrupt number in the handler Use passed interrupt number in the handler, so we can avoid using the global variable. Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c index 5b26f2a..808c415 100644 --- a/drivers/staging/octeon/ethernet-rx.c +++ b/drivers/staging/octeon/ethernet-rx.c @@ -47,16 +47,16 @@ static struct napi_struct cvm_oct_napi; /** * cvm_oct_do_interrupt - interrupt handler. - * @cpl: Interrupt number. Unused + * @irq: Interrupt number. * @dev_id: Cookie to identify the device. Unused * * The interrupt occurs whenever the POW has packets in our group. * */ -static irqreturn_t cvm_oct_do_interrupt(int cpl, void *dev_id) +static irqreturn_t cvm_oct_do_interrupt(int irq, void *dev_id) { /* Disable the IRQ and start napi_poll. */ - disable_irq_nosync(OCTEON_IRQ_WORKQ0 + pow_receive_group); + disable_irq_nosync(irq); napi_schedule(&cvm_oct_napi); return IRQ_HANDLED; -- cgit v0.10.2 From 08712f9de1013ed360d489fc185d962dfd6be7cf Mon Sep 17 00:00:00 2001 From: Aaro Koskinen <aaro.koskinen@iki.fi> Date: Wed, 31 Aug 2016 23:57:38 +0300 Subject: staging: octeon: pass the NAPI instance reference to irq handler Pass the NAPI instance reference to the interrupt handler. This is preparation for having multiple NAPI instances. Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c index 808c415..27e3459 100644 --- a/drivers/staging/octeon/ethernet-rx.c +++ b/drivers/staging/octeon/ethernet-rx.c @@ -48,16 +48,16 @@ static struct napi_struct cvm_oct_napi; /** * cvm_oct_do_interrupt - interrupt handler. * @irq: Interrupt number. - * @dev_id: Cookie to identify the device. Unused + * @napi_id: Cookie to identify the NAPI instance. * * The interrupt occurs whenever the POW has packets in our group. * */ -static irqreturn_t cvm_oct_do_interrupt(int irq, void *dev_id) +static irqreturn_t cvm_oct_do_interrupt(int irq, void *napi_id) { /* Disable the IRQ and start napi_poll. */ disable_irq_nosync(irq); - napi_schedule(&cvm_oct_napi); + napi_schedule(napi_id); return IRQ_HANDLED; } @@ -452,7 +452,7 @@ void cvm_oct_rx_initialize(void) /* Register an IRQ handler to receive POW interrupts */ i = request_irq(OCTEON_IRQ_WORKQ0 + pow_receive_group, - cvm_oct_do_interrupt, 0, "Ethernet", cvm_oct_device); + cvm_oct_do_interrupt, 0, "Ethernet", &cvm_oct_napi); if (i) panic("Could not acquire Ethernet IRQ %d\n", -- cgit v0.10.2 From b7d7dee5bf136010fae44209daf6675dc4c5c4c6 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen <aaro.koskinen@iki.fi> Date: Wed, 31 Aug 2016 23:57:39 +0300 Subject: staging: octeon: move common poll code into a separate function Move common poll code into a separate function. Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c index 27e3459..140e8af 100644 --- a/drivers/staging/octeon/ethernet-rx.c +++ b/drivers/staging/octeon/ethernet-rx.c @@ -143,14 +143,7 @@ static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work) return 0; } -/** - * cvm_oct_napi_poll - the NAPI poll function. - * @napi: The NAPI instance, or null if called from cvm_oct_poll_controller - * @budget: Maximum number of packets to receive. - * - * Returns the number of packets processed. - */ -static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) +static int cvm_oct_poll(int budget) { const int coreid = cvmx_get_core_num(); u64 old_group_mask; @@ -410,7 +403,23 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) } cvm_oct_rx_refill_pool(0); - if (rx_count < budget && napi) { + return rx_count; +} + +/** + * cvm_oct_napi_poll - the NAPI poll function. + * @napi: The NAPI instance. + * @budget: Maximum number of packets to receive. + * + * Returns the number of packets processed. + */ +static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) +{ + int rx_count; + + rx_count = cvm_oct_poll(budget); + + if (rx_count < budget) { /* No more work */ napi_complete(napi); enable_irq(OCTEON_IRQ_WORKQ0 + pow_receive_group); @@ -427,7 +436,7 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) */ void cvm_oct_poll_controller(struct net_device *dev) { - cvm_oct_napi_poll(NULL, 16); + cvm_oct_poll(16); } #endif -- cgit v0.10.2 From 785e9b7d3febcfeb461efe528320c753640d6fb4 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen <aaro.koskinen@iki.fi> Date: Wed, 31 Aug 2016 23:57:40 +0300 Subject: staging: octeon: create a struct for rx group specific data Create a struct for RX group specific data. Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c index 140e8af..65f6013 100644 --- a/drivers/staging/octeon/ethernet-rx.c +++ b/drivers/staging/octeon/ethernet-rx.c @@ -43,7 +43,9 @@ #include <asm/octeon/cvmx-gmxx-defs.h> -static struct napi_struct cvm_oct_napi; +static struct oct_rx_group { + struct napi_struct napi; +} oct_rx_group; /** * cvm_oct_do_interrupt - interrupt handler. @@ -455,13 +457,14 @@ void cvm_oct_rx_initialize(void) if (!dev_for_napi) panic("No net_devices were allocated."); - netif_napi_add(dev_for_napi, &cvm_oct_napi, cvm_oct_napi_poll, + netif_napi_add(dev_for_napi, &oct_rx_group.napi, cvm_oct_napi_poll, rx_napi_weight); - napi_enable(&cvm_oct_napi); + napi_enable(&oct_rx_group.napi); /* Register an IRQ handler to receive POW interrupts */ i = request_irq(OCTEON_IRQ_WORKQ0 + pow_receive_group, - cvm_oct_do_interrupt, 0, "Ethernet", &cvm_oct_napi); + cvm_oct_do_interrupt, 0, "Ethernet", + &oct_rx_group.napi); if (i) panic("Could not acquire Ethernet IRQ %d\n", @@ -499,7 +502,7 @@ void cvm_oct_rx_initialize(void) } /* Schedule NAPI now. This will indirectly enable the interrupt. */ - napi_schedule(&cvm_oct_napi); + napi_schedule(&oct_rx_group.napi); } void cvm_oct_rx_shutdown(void) @@ -513,5 +516,5 @@ void cvm_oct_rx_shutdown(void) /* Free the interrupt handler */ free_irq(OCTEON_IRQ_WORKQ0 + pow_receive_group, cvm_oct_device); - netif_napi_del(&cvm_oct_napi); + netif_napi_del(&oct_rx_group.napi); } -- cgit v0.10.2 From 9382cfe1338289f40ed1af479b358103f56f5eec Mon Sep 17 00:00:00 2001 From: Aaro Koskinen <aaro.koskinen@iki.fi> Date: Wed, 31 Aug 2016 23:57:41 +0300 Subject: staging: octeon: move irq into rx group specific data Move IRQ number into RX group specific data. Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c index 65f6013..776003c 100644 --- a/drivers/staging/octeon/ethernet-rx.c +++ b/drivers/staging/octeon/ethernet-rx.c @@ -44,6 +44,7 @@ #include <asm/octeon/cvmx-gmxx-defs.h> static struct oct_rx_group { + int irq; struct napi_struct napi; } oct_rx_group; @@ -417,6 +418,8 @@ static int cvm_oct_poll(int budget) */ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) { + struct oct_rx_group *rx_group = container_of(napi, struct oct_rx_group, + napi); int rx_count; rx_count = cvm_oct_poll(budget); @@ -424,7 +427,7 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) if (rx_count < budget) { /* No more work */ napi_complete(napi); - enable_irq(OCTEON_IRQ_WORKQ0 + pow_receive_group); + enable_irq(rx_group->irq); } return rx_count; } @@ -461,16 +464,16 @@ void cvm_oct_rx_initialize(void) rx_napi_weight); napi_enable(&oct_rx_group.napi); + oct_rx_group.irq = OCTEON_IRQ_WORKQ0 + pow_receive_group; + /* Register an IRQ handler to receive POW interrupts */ - i = request_irq(OCTEON_IRQ_WORKQ0 + pow_receive_group, - cvm_oct_do_interrupt, 0, "Ethernet", + i = request_irq(oct_rx_group.irq, cvm_oct_do_interrupt, 0, "Ethernet", &oct_rx_group.napi); if (i) - panic("Could not acquire Ethernet IRQ %d\n", - OCTEON_IRQ_WORKQ0 + pow_receive_group); + panic("Could not acquire Ethernet IRQ %d\n", oct_rx_group.irq); - disable_irq_nosync(OCTEON_IRQ_WORKQ0 + pow_receive_group); + disable_irq_nosync(oct_rx_group.irq); /* Enable POW interrupt when our port has at least one packet */ if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { @@ -514,7 +517,7 @@ void cvm_oct_rx_shutdown(void) cvmx_write_csr(CVMX_POW_WQ_INT_THRX(pow_receive_group), 0); /* Free the interrupt handler */ - free_irq(OCTEON_IRQ_WORKQ0 + pow_receive_group, cvm_oct_device); + free_irq(oct_rx_group.irq, cvm_oct_device); netif_napi_del(&oct_rx_group.napi); } -- cgit v0.10.2 From 942bab48e6165fa8eb8949b73b9ff6ba8608adf2 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen <aaro.koskinen@iki.fi> Date: Wed, 31 Aug 2016 23:57:42 +0300 Subject: staging: octeon: move group number into rx group data Move group number into RX group data. Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c index 776003c..80d5f24 100644 --- a/drivers/staging/octeon/ethernet-rx.c +++ b/drivers/staging/octeon/ethernet-rx.c @@ -45,6 +45,7 @@ static struct oct_rx_group { int irq; + int group; struct napi_struct napi; } oct_rx_group; @@ -146,7 +147,7 @@ static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work) return 0; } -static int cvm_oct_poll(int budget) +static int cvm_oct_poll(struct oct_rx_group *rx_group, int budget) { const int coreid = cvmx_get_core_num(); u64 old_group_mask; @@ -168,13 +169,13 @@ static int cvm_oct_poll(int budget) if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { old_group_mask = cvmx_read_csr(CVMX_SSO_PPX_GRP_MSK(coreid)); cvmx_write_csr(CVMX_SSO_PPX_GRP_MSK(coreid), - 1ull << pow_receive_group); + BIT(rx_group->group)); cvmx_read_csr(CVMX_SSO_PPX_GRP_MSK(coreid)); /* Flush */ } else { old_group_mask = cvmx_read_csr(CVMX_POW_PP_GRP_MSKX(coreid)); cvmx_write_csr(CVMX_POW_PP_GRP_MSKX(coreid), (old_group_mask & ~0xFFFFull) | - 1 << pow_receive_group); + BIT(rx_group->group)); } if (USE_ASYNC_IOBDMA) { @@ -199,15 +200,15 @@ static int cvm_oct_poll(int budget) if (!work) { if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { cvmx_write_csr(CVMX_SSO_WQ_IQ_DIS, - 1ull << pow_receive_group); + BIT(rx_group->group)); cvmx_write_csr(CVMX_SSO_WQ_INT, - 1ull << pow_receive_group); + BIT(rx_group->group)); } else { union cvmx_pow_wq_int wq_int; wq_int.u64 = 0; - wq_int.s.iq_dis = 1 << pow_receive_group; - wq_int.s.wq_int = 1 << pow_receive_group; + wq_int.s.iq_dis = BIT(rx_group->group); + wq_int.s.wq_int = BIT(rx_group->group); cvmx_write_csr(CVMX_POW_WQ_INT, wq_int.u64); } break; @@ -422,7 +423,7 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) napi); int rx_count; - rx_count = cvm_oct_poll(budget); + rx_count = cvm_oct_poll(rx_group, budget); if (rx_count < budget) { /* No more work */ @@ -441,7 +442,7 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) */ void cvm_oct_poll_controller(struct net_device *dev) { - cvm_oct_poll(16); + cvm_oct_poll(&oct_rx_group, 16); } #endif @@ -465,6 +466,7 @@ void cvm_oct_rx_initialize(void) napi_enable(&oct_rx_group.napi); oct_rx_group.irq = OCTEON_IRQ_WORKQ0 + pow_receive_group; + oct_rx_group.group = pow_receive_group; /* Register an IRQ handler to receive POW interrupts */ i = request_irq(oct_rx_group.irq, cvm_oct_do_interrupt, 0, "Ethernet", -- cgit v0.10.2 From e971a119f713ae3bedbd7fb45efb1121537d9f26 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen <aaro.koskinen@iki.fi> Date: Wed, 31 Aug 2016 23:57:43 +0300 Subject: staging: octeon: support enabling multiple rx groups Support enabling multiple RX groups. Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c index 80d5f24..4f32fa3 100644 --- a/drivers/staging/octeon/ethernet-rx.c +++ b/drivers/staging/octeon/ethernet-rx.c @@ -47,7 +47,7 @@ static struct oct_rx_group { int irq; int group; struct napi_struct napi; -} oct_rx_group; +} oct_rx_group[16]; /** * cvm_oct_do_interrupt - interrupt handler. @@ -442,7 +442,16 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) */ void cvm_oct_poll_controller(struct net_device *dev) { - cvm_oct_poll(&oct_rx_group, 16); + int i; + + for (i = 0; i < ARRAY_SIZE(oct_rx_group); i++) { + + if (!(pow_receive_groups & BIT(i))) + continue; + + cvm_oct_poll(&oct_rx_group[i], 16); + + } } #endif @@ -461,65 +470,80 @@ void cvm_oct_rx_initialize(void) if (!dev_for_napi) panic("No net_devices were allocated."); - netif_napi_add(dev_for_napi, &oct_rx_group.napi, cvm_oct_napi_poll, - rx_napi_weight); - napi_enable(&oct_rx_group.napi); + for (i = 0; i < ARRAY_SIZE(oct_rx_group); i++) { + int ret; - oct_rx_group.irq = OCTEON_IRQ_WORKQ0 + pow_receive_group; - oct_rx_group.group = pow_receive_group; + if (!(pow_receive_groups & BIT(i))) + continue; - /* Register an IRQ handler to receive POW interrupts */ - i = request_irq(oct_rx_group.irq, cvm_oct_do_interrupt, 0, "Ethernet", - &oct_rx_group.napi); + netif_napi_add(dev_for_napi, &oct_rx_group[i].napi, + cvm_oct_napi_poll, rx_napi_weight); + napi_enable(&oct_rx_group[i].napi); - if (i) - panic("Could not acquire Ethernet IRQ %d\n", oct_rx_group.irq); + oct_rx_group[i].irq = OCTEON_IRQ_WORKQ0 + i; + oct_rx_group[i].group = i; - disable_irq_nosync(oct_rx_group.irq); + /* Register an IRQ handler to receive POW interrupts */ + ret = request_irq(oct_rx_group[i].irq, cvm_oct_do_interrupt, 0, + "Ethernet", &oct_rx_group[i].napi); + if (ret) + panic("Could not acquire Ethernet IRQ %d\n", + oct_rx_group[i].irq); - /* Enable POW interrupt when our port has at least one packet */ - if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { - union cvmx_sso_wq_int_thrx int_thr; - union cvmx_pow_wq_int_pc int_pc; - - int_thr.u64 = 0; - int_thr.s.tc_en = 1; - int_thr.s.tc_thr = 1; - cvmx_write_csr(CVMX_SSO_WQ_INT_THRX(pow_receive_group), - int_thr.u64); - - int_pc.u64 = 0; - int_pc.s.pc_thr = 5; - cvmx_write_csr(CVMX_SSO_WQ_INT_PC, int_pc.u64); - } else { - union cvmx_pow_wq_int_thrx int_thr; - union cvmx_pow_wq_int_pc int_pc; - - int_thr.u64 = 0; - int_thr.s.tc_en = 1; - int_thr.s.tc_thr = 1; - cvmx_write_csr(CVMX_POW_WQ_INT_THRX(pow_receive_group), - int_thr.u64); - - int_pc.u64 = 0; - int_pc.s.pc_thr = 5; - cvmx_write_csr(CVMX_POW_WQ_INT_PC, int_pc.u64); - } + disable_irq_nosync(oct_rx_group[i].irq); + + /* Enable POW interrupt when our port has at least one packet */ + if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { + union cvmx_sso_wq_int_thrx int_thr; + union cvmx_pow_wq_int_pc int_pc; + + int_thr.u64 = 0; + int_thr.s.tc_en = 1; + int_thr.s.tc_thr = 1; + cvmx_write_csr(CVMX_SSO_WQ_INT_THRX(i), int_thr.u64); + + int_pc.u64 = 0; + int_pc.s.pc_thr = 5; + cvmx_write_csr(CVMX_SSO_WQ_INT_PC, int_pc.u64); + } else { + union cvmx_pow_wq_int_thrx int_thr; + union cvmx_pow_wq_int_pc int_pc; - /* Schedule NAPI now. This will indirectly enable the interrupt. */ - napi_schedule(&oct_rx_group.napi); + int_thr.u64 = 0; + int_thr.s.tc_en = 1; + int_thr.s.tc_thr = 1; + cvmx_write_csr(CVMX_POW_WQ_INT_THRX(i), int_thr.u64); + + int_pc.u64 = 0; + int_pc.s.pc_thr = 5; + cvmx_write_csr(CVMX_POW_WQ_INT_PC, int_pc.u64); + } + + /* Schedule NAPI now. This will indirectly enable the + * interrupt. + */ + napi_schedule(&oct_rx_group[i].napi); + } } void cvm_oct_rx_shutdown(void) { - /* Disable POW interrupt */ - if (OCTEON_IS_MODEL(OCTEON_CN68XX)) - cvmx_write_csr(CVMX_SSO_WQ_INT_THRX(pow_receive_group), 0); - else - cvmx_write_csr(CVMX_POW_WQ_INT_THRX(pow_receive_group), 0); + int i; + + for (i = 0; i < ARRAY_SIZE(oct_rx_group); i++) { + + if (!(pow_receive_groups & BIT(i))) + continue; - /* Free the interrupt handler */ - free_irq(oct_rx_group.irq, cvm_oct_device); + /* Disable POW interrupt */ + if (OCTEON_IS_MODEL(OCTEON_CN68XX)) + cvmx_write_csr(CVMX_SSO_WQ_INT_THRX(i), 0); + else + cvmx_write_csr(CVMX_POW_WQ_INT_THRX(i), 0); + + /* Free the interrupt handler */ + free_irq(oct_rx_group[i].irq, cvm_oct_device); - netif_napi_del(&oct_rx_group.napi); + netif_napi_del(&oct_rx_group[i].napi); + } } diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index 1e2e1ef..7d48745 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -45,7 +45,7 @@ MODULE_PARM_DESC(num_packet_buffers, "\n" "\tNumber of packet buffers to allocate and store in the\n" "\tFPA. By default, 1024 packet buffers are used.\n"); -int pow_receive_group = 15; +static int pow_receive_group = 15; module_param(pow_receive_group, int, 0444); MODULE_PARM_DESC(pow_receive_group, "\n" "\tPOW group to receive packets from. All ethernet hardware\n" @@ -86,6 +86,8 @@ int rx_napi_weight = 32; module_param(rx_napi_weight, int, 0444); MODULE_PARM_DESC(rx_napi_weight, "The NAPI WEIGHT parameter."); +/* Mask indicating which receive groups are in use. */ +int pow_receive_groups; /* * cvm_oct_poll_queue_stopping - flag to indicate polling should stop. @@ -678,6 +680,8 @@ static int cvm_oct_probe(struct platform_device *pdev) cvmx_helper_initialize_packet_io_global(); + pow_receive_groups = BIT(pow_receive_group); + /* Change the input group for all ports before input is enabled */ num_interfaces = cvmx_helper_get_number_of_interfaces(); for (interface = 0; interface < num_interfaces; interface++) { diff --git a/drivers/staging/octeon/octeon-ethernet.h b/drivers/staging/octeon/octeon-ethernet.h index d533aef..9c6852d 100644 --- a/drivers/staging/octeon/octeon-ethernet.h +++ b/drivers/staging/octeon/octeon-ethernet.h @@ -72,7 +72,7 @@ void cvm_oct_link_poll(struct net_device *dev); extern int always_use_pow; extern int pow_send_group; -extern int pow_receive_group; +extern int pow_receive_groups; extern char pow_send_list[]; extern struct net_device *cvm_oct_device[]; extern atomic_t cvm_oct_poll_queue_stopping; -- cgit v0.10.2 From 5cf9b1ca7be93f6e92dee955eeb274575e5ab40e Mon Sep 17 00:00:00 2001 From: Aaro Koskinen <aaro.koskinen@iki.fi> Date: Wed, 31 Aug 2016 23:57:44 +0300 Subject: staging: octeon: enable taking multiple rx groups into use Enable taking multiple RX groups into use. Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index 7d48745..8d51f05 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -53,6 +53,15 @@ MODULE_PARM_DESC(pow_receive_group, "\n" "\tgroup. Also any other software can submit packets to this\n" "\tgroup for the kernel to process."); +static int receive_group_order; +module_param(receive_group_order, int, 0444); +MODULE_PARM_DESC(receive_group_order, "\n" + "\tOrder (0..4) of receive groups to take into use. Ethernet hardware\n" + "\twill be configured to send incoming packets to multiple POW\n" + "\tgroups. pow_receive_group parameter is ignored when multiple\n" + "\tgroups are taken into use and groups are allocated starting\n" + "\tfrom 0. By default, a single group is used.\n"); + int pow_send_group = -1; module_param(pow_send_group, int, 0644); MODULE_PARM_DESC(pow_send_group, "\n" @@ -680,7 +689,13 @@ static int cvm_oct_probe(struct platform_device *pdev) cvmx_helper_initialize_packet_io_global(); - pow_receive_groups = BIT(pow_receive_group); + if (receive_group_order) { + if (receive_group_order > 4) + receive_group_order = 4; + pow_receive_groups = (1 << (1 << receive_group_order)) - 1; + } else { + pow_receive_groups = BIT(pow_receive_group); + } /* Change the input group for all ports before input is enabled */ num_interfaces = cvmx_helper_get_number_of_interfaces(); @@ -695,7 +710,37 @@ static int cvm_oct_probe(struct platform_device *pdev) pip_prt_tagx.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(port)); - pip_prt_tagx.s.grp = pow_receive_group; + + if (receive_group_order) { + int tag_mask; + + /* We support only 16 groups at the moment, so + * always disable the two additional "hidden" + * tag_mask bits on CN68XX. + */ + if (OCTEON_IS_MODEL(OCTEON_CN68XX)) + pip_prt_tagx.u64 |= 0x3ull << 44; + + tag_mask = ~((1 << receive_group_order) - 1); + pip_prt_tagx.s.grptagbase = 0; + pip_prt_tagx.s.grptagmask = tag_mask; + pip_prt_tagx.s.grptag = 1; + pip_prt_tagx.s.tag_mode = 0; + pip_prt_tagx.s.inc_prt_flag = 1; + pip_prt_tagx.s.ip6_dprt_flag = 1; + pip_prt_tagx.s.ip4_dprt_flag = 1; + pip_prt_tagx.s.ip6_sprt_flag = 1; + pip_prt_tagx.s.ip4_sprt_flag = 1; + pip_prt_tagx.s.ip6_dst_flag = 1; + pip_prt_tagx.s.ip4_dst_flag = 1; + pip_prt_tagx.s.ip6_src_flag = 1; + pip_prt_tagx.s.ip4_src_flag = 1; + pip_prt_tagx.s.grp = 0; + } else { + pip_prt_tagx.s.grptag = 0; + pip_prt_tagx.s.grp = pow_receive_group; + } + cvmx_write_csr(CVMX_PIP_PRT_TAGX(port), pip_prt_tagx.u64); } -- cgit v0.10.2 From ce060d8af33c0dee3c20510a39f6284f8d90614e Mon Sep 17 00:00:00 2001 From: Aaro Koskinen <aaro.koskinen@iki.fi> Date: Wed, 31 Aug 2016 23:57:45 +0300 Subject: staging: octeon: set up pknd for all interfaces RX path uses pknd to find the correct device, and we maintain 1:1 port to pknd mapping. However, this is only set for XAUI interfaces (in the arch code). But it should be set for all interface types. Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index 8d51f05..5497fac 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -488,6 +488,8 @@ int cvm_oct_common_open(struct net_device *dev, gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); gmx_cfg.s.en = 1; + if (octeon_has_feature(OCTEON_FEATURE_PKND)) + gmx_cfg.s.pknd = priv->port; cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); if (octeon_is_simulation()) -- cgit v0.10.2 From d48f10fc616a82c8e761753fd6edf6b6f6b66bec Mon Sep 17 00:00:00 2001 From: Aaro Koskinen <aaro.koskinen@iki.fi> Date: Wed, 31 Aug 2016 23:57:46 +0300 Subject: staging: octeon: prevent poll during rx init Prevent poll before the RX init has been completed. Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c index 4f32fa3..ce1e2a3 100644 --- a/drivers/staging/octeon/ethernet-rx.c +++ b/drivers/staging/octeon/ethernet-rx.c @@ -43,6 +43,8 @@ #include <asm/octeon/cvmx-gmxx-defs.h> +static atomic_t oct_rx_ready = ATOMIC_INIT(0); + static struct oct_rx_group { int irq; int group; @@ -444,6 +446,9 @@ void cvm_oct_poll_controller(struct net_device *dev) { int i; + if (!atomic_read(&oct_rx_ready)) + return; + for (i = 0; i < ARRAY_SIZE(oct_rx_group); i++) { if (!(pow_receive_groups & BIT(i))) @@ -524,6 +529,7 @@ void cvm_oct_rx_initialize(void) */ napi_schedule(&oct_rx_group[i].napi); } + atomic_inc(&oct_rx_ready); } void cvm_oct_rx_shutdown(void) -- cgit v0.10.2 From 8f8064e4ccc0579dae927246dd00b7ac6d6ffd89 Mon Sep 17 00:00:00 2001 From: Louie Lu <louie.lu@hopebaytech.com> Date: Fri, 2 Sep 2016 18:15:07 +0800 Subject: staging: rtl8712: delete one space before if statement This patch fixed minor checkpatch warning: WARNING: Statements should start on a tabstop Signed-off-by: Louie Lu <louie.lu@hopebaytech.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c index b615fbf..cbe4de0 100644 --- a/drivers/staging/rtl8712/os_intfs.c +++ b/drivers/staging/rtl8712/os_intfs.c @@ -425,7 +425,7 @@ static int netdev_open(struct net_device *pnetdev) else netif_wake_queue(pnetdev); - if (video_mode) + if (video_mode) enable_video_mode(padapter, cbw40_enable); /* start driver mlme relation timer */ start_drv_timers(padapter); -- cgit v0.10.2 From 8292b4de4ee67aa4524b05c7980b94a8b2ce2f80 Mon Sep 17 00:00:00 2001 From: Louie Lu <louie.lu@hopebaytech.com> Date: Fri, 2 Sep 2016 18:15:40 +0800 Subject: staging: rtl8172: fixed comment style in rts871x_cmd.c Fixed comment style warning by checkpatch: * Block comments use * on subsequent lines * Block comments use a trailing */ on a separate line Signed-off-by: Louie Lu <louie.lu@hopebaytech.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8712/rtl871x_cmd.c b/drivers/staging/rtl8712/rtl871x_cmd.c index 5838696..51b6959 100644 --- a/drivers/staging/rtl8712/rtl871x_cmd.c +++ b/drivers/staging/rtl8712/rtl871x_cmd.c @@ -51,9 +51,9 @@ #include "mlme_osdep.h" /* -Caller and the r8712_cmd_thread can protect cmd_q by spin_lock. -No irqsave is necessary. -*/ + * Caller and the r8712_cmd_thread can protect cmd_q by spin_lock. + * No irqsave is necessary. + */ static sint _init_cmd_priv(struct cmd_priv *pcmdpriv) { @@ -110,14 +110,14 @@ static void _free_cmd_priv(struct cmd_priv *pcmdpriv) } /* -Calling Context: - -_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: + * + * _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. + * + */ static sint _enqueue_cmd(struct __queue *queue, struct cmd_obj *obj) { @@ -211,11 +211,11 @@ void r8712_free_cmd_obj(struct cmd_obj *pcmd) } /* -r8712_sitesurvey_cmd(~) - ### NOTE:#### (!!!!) - MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, - YOU SHOULD HAVE LOCKED pmlmepriv->lock -*/ + * r8712_sitesurvey_cmd(~) + * ### NOTE:#### (!!!!) + * MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, + * YOU SHOULD HAVE LOCKED pmlmepriv->lock + */ u8 r8712_sitesurvey_cmd(struct _adapter *padapter, struct ndis_802_11_ssid *pssid) { @@ -491,8 +491,9 @@ u8 r8712_joinbss_cmd(struct _adapter *padapter, struct wlan_network *pnetwork) memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], (256 - 1)); psecnetwork->IELength = 0; - /* If the driver wants to use the bssid to create the connection. - * If not, we copy the connecting AP's MAC address to it so that + /* + * If the driver wants to use the bssid to create the connection. + * If not, we copy the connecting AP's MAC address to it so that * the driver just has the bssid information for PMKIDList searching. */ if (!pmlmepriv->assoc_by_bssid) @@ -519,7 +520,8 @@ u8 r8712_joinbss_cmd(struct _adapter *padapter, struct wlan_network *pnetwork) } } if (pregistrypriv->ht_enable) { - /* For WEP mode, we will use the bg mode to do the connection + /* + * For WEP mode, we will use the bg mode to do the connection * to avoid some IOT issues, especially for Realtek 8192u * SoftAP. */ @@ -904,8 +906,10 @@ void r8712_createbss_cmd_callback(struct _adapter *padapter, (r8712_get_wlan_bssid_ex_sz(pnetwork))); if (pmlmepriv->fw_state & _FW_UNDER_LINKING) pmlmepriv->fw_state ^= _FW_UNDER_LINKING; - /* we will set _FW_LINKED when there is one more sat to - * join us (stassoc_event_callback) */ + /* + * we will set _FW_LINKED when there is one more sat to + * join us (stassoc_event_callback) + */ } createbss_cmd_fail: spin_unlock_irqrestore(&pmlmepriv->lock, irqL); -- cgit v0.10.2 From aa652b1ccbd0d3a9cd4ecdec6d36935f78c838da Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas <javier@osg.samsung.com> Date: Fri, 2 Sep 2016 01:46:34 +0200 Subject: staging: octeon: Use IS_ENABLED() instead of checking for built-in or module The IS_ENABLED() macro checks if a Kconfig symbol has been enabled either built-in or as a module, use that macro instead of open coding the same. Using the macro makes the code more readable by helping abstract away some of the Kconfig built-in and module enable details. Signed-off-by: Javier Martinez Canillas <javier@osg.samsung.com> Acked-by: David Daney <david.daney@cavium.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index 5497fac..0bd5c18 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -248,7 +248,7 @@ static int cvm_oct_common_change_mtu(struct net_device *dev, int new_mtu) { struct octeon_ethernet *priv = netdev_priv(dev); int interface = INTERFACE(priv->port); -#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) +#if IS_ENABLED(CONFIG_VLAN_8021Q) int vlan_bytes = 4; #else int vlan_bytes = 0; -- cgit v0.10.2 From a5c8b11a361065db028721c62aa880bfe0736aa6 Mon Sep 17 00:00:00 2001 From: Christoph Fritz <chf.fritz@googlemail.com> Date: Sat, 3 Sep 2016 12:30:00 +0200 Subject: iio: sx9500: add final devicetree support This makes sx9500 driver usable on devicetree based platforms too. Signed-off-by: Christoph Fritz <chf.fritz@googlemail.com> Reviewed-by: Fabio Estevam <fabio.estevam@nxp.com> Reviewed-by: Vlad Dogaru <ddvlad@gmail.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/Documentation/devicetree/bindings/iio/proximity/sx9500.txt b/Documentation/devicetree/bindings/iio/proximity/sx9500.txt new file mode 100644 index 0000000..b301dd2 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/proximity/sx9500.txt @@ -0,0 +1,24 @@ +Semtech's SX9500 capacitive proximity button device driver + +Required properties: + - compatible: must be "semtech,sx9500" + - reg: i2c address where to find the device + - interrupt-parent : should be the phandle for the interrupt controller + - interrupts : the sole interrupt generated by the device + + Refer to interrupt-controller/interrupts.txt for generic + interrupt client node bindings. + +Optional properties: + - reset-gpios: Reference to the GPIO connected to the device's active + low reset pin. + +Example: + +sx9500@28 { + compatible = "semtech,sx9500"; + reg = <0x28>; + interrupt-parent = <&gpio2>; + interrupts = <16 IRQ_TYPE_LEVEL_LOW>; + reset-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>; +}; diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c index 6f84f53..1f06282 100644 --- a/drivers/iio/proximity/sx9500.c +++ b/drivers/iio/proximity/sx9500.c @@ -1025,6 +1025,12 @@ static const struct acpi_device_id sx9500_acpi_match[] = { }; MODULE_DEVICE_TABLE(acpi, sx9500_acpi_match); +static const struct of_device_id sx9500_of_match[] = { + { .compatible = "semtech,sx9500", }, + { } +}; +MODULE_DEVICE_TABLE(of, sx9500_of_match); + static const struct i2c_device_id sx9500_id[] = { {"sx9500", 0}, { }, @@ -1035,6 +1041,7 @@ static struct i2c_driver sx9500_driver = { .driver = { .name = SX9500_DRIVER_NAME, .acpi_match_table = ACPI_PTR(sx9500_acpi_match), + .of_match_table = of_match_ptr(sx9500_of_match), .pm = &sx9500_pm_ops, }, .probe = sx9500_probe, -- cgit v0.10.2 From c8cdf70890d89c07c9e890b103106d58999f0ce4 Mon Sep 17 00:00:00 2001 From: Matt Ranostay <mranostay@gmail.com> Date: Fri, 2 Sep 2016 23:36:15 -0700 Subject: iio: trigger: allow immutable triggers to be assigned There are times when an assigned trigger to a device shouldn't ever change after intialization. Examples of this being used is when an provider device has a trigger that is assigned to an ADC, which uses it populate data into a callback buffer. Signed-off-by: Matt Ranostay <matt@ranostay.consulting> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c index 7ad82fd..3dde81e 100644 --- a/drivers/iio/industrialio-trigger.c +++ b/drivers/iio/industrialio-trigger.c @@ -119,6 +119,22 @@ void iio_trigger_unregister(struct iio_trigger *trig_info) } EXPORT_SYMBOL(iio_trigger_unregister); +int iio_trigger_set_immutable(struct iio_dev *indio_dev, struct iio_trigger *trig) +{ + if (!indio_dev || !trig) + return -EINVAL; + + mutex_lock(&indio_dev->mlock); + WARN_ON(indio_dev->trig_readonly); + + indio_dev->trig = iio_trigger_get(trig); + indio_dev->trig_readonly = true; + mutex_unlock(&indio_dev->mlock); + + return 0; +} +EXPORT_SYMBOL(iio_trigger_set_immutable); + /* Search for trigger by name, assuming iio_trigger_list_lock held */ static struct iio_trigger *__iio_trigger_find_by_name(const char *name) { @@ -384,6 +400,10 @@ static ssize_t iio_trigger_write_current(struct device *dev, mutex_unlock(&indio_dev->mlock); return -EBUSY; } + if (indio_dev->trig_readonly) { + mutex_unlock(&indio_dev->mlock); + return -EPERM; + } mutex_unlock(&indio_dev->mlock); trig = iio_trigger_find_by_name(buf, len); diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 854e2da..786952c 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -483,6 +483,7 @@ struct iio_buffer_setup_ops { * @scan_timestamp: [INTERN] set if any buffers have requested timestamp * @scan_index_timestamp:[INTERN] cache of the index to the timestamp * @trig: [INTERN] current device trigger (buffer modes) + * @trig_readonly [INTERN] mark the current trigger immutable * @pollfunc: [DRIVER] function run on trigger being received * @pollfunc_event: [DRIVER] function run on events trigger being received * @channels: [DRIVER] channel specification structure table @@ -523,6 +524,7 @@ struct iio_dev { bool scan_timestamp; unsigned scan_index_timestamp; struct iio_trigger *trig; + bool trig_readonly; struct iio_poll_func *pollfunc; struct iio_poll_func *pollfunc_event; diff --git a/include/linux/iio/trigger.h b/include/linux/iio/trigger.h index 1c9e028..a122bdd 100644 --- a/include/linux/iio/trigger.h +++ b/include/linux/iio/trigger.h @@ -132,6 +132,15 @@ int iio_trigger_register(struct iio_trigger *trig_info); void iio_trigger_unregister(struct iio_trigger *trig_info); /** + * iio_trigger_set_immutable() - set an immutable trigger on destination + * + * @indio_dev - IIO device structure containing the device + * @trig - trigger to assign to device + * + **/ +int iio_trigger_set_immutable(struct iio_dev *indio_dev, struct iio_trigger *trig); + +/** * iio_trigger_poll() - called on a trigger occurring * @trig: trigger which occurred * -- cgit v0.10.2 From c060991912f8e71f6214204a2019ceceb315c17b Mon Sep 17 00:00:00 2001 From: Alison Schofield <amsfield22@gmail.com> Date: Fri, 2 Sep 2016 19:54:21 -0700 Subject: iio: adc: ina2xx: remove unused debug field from chip global data commit 1961bce76452 "iio: ina2xx: Remove trace_printk debug statements" removed the code that used the chip->prev_ns field. This patch cleans it up further by removing the unused field and assignments. Signed-off-by: Alison Schofield <amsfield22@gmail.com> Cc: Daniel Baluta <daniel.baluta@gmail.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c index 955f3fd..59b7d76 100644 --- a/drivers/iio/adc/ina2xx-adc.c +++ b/drivers/iio/adc/ina2xx-adc.c @@ -114,7 +114,6 @@ struct ina2xx_chip_info { struct mutex state_lock; unsigned int shunt_resistor; int avg; - s64 prev_ns; /* track buffer capture time, check for underruns */ int int_time_vbus; /* Bus voltage integration time uS */ int int_time_vshunt; /* Shunt voltage integration time uS */ bool allow_async_readout; @@ -509,8 +508,6 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev) iio_push_to_buffers_with_timestamp(indio_dev, (unsigned int *)data, time_a); - chip->prev_ns = time_a; - return (unsigned long)(time_b - time_a) / 1000; }; @@ -554,8 +551,6 @@ static int ina2xx_buffer_enable(struct iio_dev *indio_dev) dev_dbg(&indio_dev->dev, "Async readout mode: %d\n", chip->allow_async_readout); - chip->prev_ns = iio_get_time_ns(indio_dev); - chip->task = kthread_run(ina2xx_capture_thread, (void *)indio_dev, "%s:%d-%uus", indio_dev->name, indio_dev->id, sampling_us); -- cgit v0.10.2 From 4075a283ae83f49f923a2a92935aa72be2c1ca85 Mon Sep 17 00:00:00 2001 From: William Breathitt Gray <vilhelm.gray@gmail.com> Date: Mon, 29 Aug 2016 16:22:56 -0400 Subject: iio: stx104: Add IIO support for the ADC channels The Apex Embedded Systems STX104 features 16 channels of single-ended (8 channels of true differential) 16-bit analog input. Differential input configuration may be selected via a physical jumper on the device. Similarly, input polarity (unipolar/bipolar) is configured via a physical jumper on the device. Input gain selection is available to the user via software, thus allowing eight possible input ranges: +-10V, +-5V, +-2.5V, +-1.25V, 0 to 10V, 0 to 5V, 0 to 2.5V, and 0 to 1.25V. Four input gain configurations are supported: x1, x2, x4, and x8. This ADC resolution is 16-bits (1/65536 of full scale). Analog input samples are taken on software trigger; neither FIFO sampling nor interrupt triggering is supported by this driver. The Apex Embedded Systems STX104 is primarily an analog-to-digital converter device. The STX104 IIO driver was initially placed in the DAC directory because only the DAC portion of the STX104 was supported at the time. Now that ADC support has been added to the STX104 IIO driver, the driver should be moved to the more appropriate ADC directory. Signed-off-by: William Breathitt Gray <vilhelm.gray@gmail.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/MAINTAINERS b/MAINTAINERS index ae09eb4..6f0ff72 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -809,11 +809,11 @@ L: alsa-devel@alsa-project.org (moderated for non-subscribers) S: Maintained F: sound/aoa/ -APEX EMBEDDED SYSTEMS STX104 DAC DRIVER +APEX EMBEDDED SYSTEMS STX104 IIO DRIVER M: William Breathitt Gray <vilhelm.gray@gmail.com> L: linux-iio@vger.kernel.org S: Maintained -F: drivers/iio/dac/stx104.c +F: drivers/iio/adc/stx104.c APM DRIVER M: Jiri Kosina <jikos@kernel.org> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 9f8e381..ee7ab81 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -418,6 +418,21 @@ config ROCKCHIP_SARADC To compile this driver as a module, choose M here: the module will be called rockchip_saradc. +config STX104 + tristate "Apex Embedded Systems STX104 driver" + depends on X86 && ISA_BUS_API + select GPIOLIB + help + Say yes here to build support for the Apex Embedded Systems STX104 + integrated analog PC/104 card. + + This driver supports the 16 channels of single-ended (8 channels of + differential) analog inputs, 2 channels of analog output, 4 digital + inputs, and 4 digital outputs provided by the STX104. + + The base port addresses for the devices may be configured via the base + array module parameter. + config TI_ADC081C tristate "Texas Instruments ADC081C/ADC101C/ADC121C family" depends on I2C diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index d1a20b6..7a40c04 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -40,6 +40,7 @@ obj-$(CONFIG_PALMAS_GPADC) += palmas_gpadc.o obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o +obj-$(CONFIG_STX104) += stx104.o obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o obj-$(CONFIG_TI_ADC12138) += ti-adc12138.o diff --git a/drivers/iio/adc/stx104.c b/drivers/iio/adc/stx104.c new file mode 100644 index 0000000..7ca12d5 --- /dev/null +++ b/drivers/iio/adc/stx104.c @@ -0,0 +1,360 @@ +/* + * IIO driver for the Apex Embedded Systems STX104 + * Copyright (C) 2016 William Breathitt Gray + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ +#include <linux/bitops.h> +#include <linux/device.h> +#include <linux/errno.h> +#include <linux/gpio/driver.h> +#include <linux/iio/iio.h> +#include <linux/iio/types.h> +#include <linux/io.h> +#include <linux/ioport.h> +#include <linux/isa.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/spinlock.h> + +#define STX104_OUT_CHAN(chan) { \ + .type = IIO_VOLTAGE, \ + .channel = chan, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .indexed = 1, \ + .output = 1 \ +} +#define STX104_IN_CHAN(chan, diff) { \ + .type = IIO_VOLTAGE, \ + .channel = chan, \ + .channel2 = chan, \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_HARDWAREGAIN) | \ + BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .indexed = 1, \ + .differential = diff \ +} + +#define STX104_NUM_OUT_CHAN 2 + +#define STX104_EXTENT 16 + +static unsigned int base[max_num_isa_dev(STX104_EXTENT)]; +static unsigned int num_stx104; +module_param_array(base, uint, &num_stx104, 0); +MODULE_PARM_DESC(base, "Apex Embedded Systems STX104 base addresses"); + +/** + * struct stx104_iio - IIO device private data structure + * @chan_out_states: channels' output states + * @base: base port address of the IIO device + */ +struct stx104_iio { + unsigned int chan_out_states[STX104_NUM_OUT_CHAN]; + unsigned int base; +}; + +/** + * struct stx104_gpio - GPIO device private data structure + * @chip: instance of the gpio_chip + * @lock: synchronization lock to prevent I/O race conditions + * @base: base port address of the GPIO device + * @out_state: output bits state + */ +struct stx104_gpio { + struct gpio_chip chip; + spinlock_t lock; + unsigned int base; + unsigned int out_state; +}; + +static int stx104_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, int *val2, long mask) +{ + struct stx104_iio *const priv = iio_priv(indio_dev); + unsigned int adc_config; + int adbu; + int gain; + + switch (mask) { + case IIO_CHAN_INFO_HARDWAREGAIN: + /* get gain configuration */ + adc_config = inb(priv->base + 11); + gain = adc_config & 0x3; + + *val = 1 << gain; + return IIO_VAL_INT; + case IIO_CHAN_INFO_RAW: + if (chan->output) { + *val = priv->chan_out_states[chan->channel]; + return IIO_VAL_INT; + } + + /* select ADC channel */ + outb(chan->channel | (chan->channel << 4), priv->base + 2); + + /* trigger ADC sample capture and wait for completion */ + outb(0, priv->base); + while (inb(priv->base + 8) & BIT(7)); + + *val = inw(priv->base); + return IIO_VAL_INT; + case IIO_CHAN_INFO_OFFSET: + /* get ADC bipolar/unipolar configuration */ + adc_config = inb(priv->base + 11); + adbu = !(adc_config & BIT(2)); + + *val = -32768 * adbu; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + /* get ADC bipolar/unipolar and gain configuration */ + adc_config = inb(priv->base + 11); + adbu = !(adc_config & BIT(2)); + gain = adc_config & 0x3; + + *val = 5; + *val2 = 15 - adbu + gain; + return IIO_VAL_FRACTIONAL_LOG2; + } + + return -EINVAL; +} + +static int stx104_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, int val2, long mask) +{ + struct stx104_iio *const priv = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_HARDWAREGAIN: + /* Only four gain states (x1, x2, x4, x8) */ + switch (val) { + case 1: + outb(0, priv->base + 11); + break; + case 2: + outb(1, priv->base + 11); + break; + case 4: + outb(2, priv->base + 11); + break; + case 8: + outb(3, priv->base + 11); + break; + default: + return -EINVAL; + } + + return 0; + case IIO_CHAN_INFO_RAW: + if (chan->output) { + /* DAC can only accept up to a 16-bit value */ + if ((unsigned int)val > 65535) + return -EINVAL; + + priv->chan_out_states[chan->channel] = val; + outw(val, priv->base + 4 + 2 * chan->channel); + + return 0; + } + return -EINVAL; + } + + return -EINVAL; +} + +static const struct iio_info stx104_info = { + .driver_module = THIS_MODULE, + .read_raw = stx104_read_raw, + .write_raw = stx104_write_raw +}; + +/* single-ended input channels configuration */ +static const struct iio_chan_spec stx104_channels_sing[] = { + STX104_OUT_CHAN(0), STX104_OUT_CHAN(1), + STX104_IN_CHAN(0, 0), STX104_IN_CHAN(1, 0), STX104_IN_CHAN(2, 0), + STX104_IN_CHAN(3, 0), STX104_IN_CHAN(4, 0), STX104_IN_CHAN(5, 0), + STX104_IN_CHAN(6, 0), STX104_IN_CHAN(7, 0), STX104_IN_CHAN(8, 0), + STX104_IN_CHAN(9, 0), STX104_IN_CHAN(10, 0), STX104_IN_CHAN(11, 0), + STX104_IN_CHAN(12, 0), STX104_IN_CHAN(13, 0), STX104_IN_CHAN(14, 0), + STX104_IN_CHAN(15, 0) +}; +/* differential input channels configuration */ +static const struct iio_chan_spec stx104_channels_diff[] = { + STX104_OUT_CHAN(0), STX104_OUT_CHAN(1), + STX104_IN_CHAN(0, 1), STX104_IN_CHAN(1, 1), STX104_IN_CHAN(2, 1), + STX104_IN_CHAN(3, 1), STX104_IN_CHAN(4, 1), STX104_IN_CHAN(5, 1), + STX104_IN_CHAN(6, 1), STX104_IN_CHAN(7, 1) +}; + +static int stx104_gpio_get_direction(struct gpio_chip *chip, + unsigned int offset) +{ + if (offset < 4) + return 1; + + return 0; +} + +static int stx104_gpio_direction_input(struct gpio_chip *chip, + unsigned int offset) +{ + if (offset >= 4) + return -EINVAL; + + return 0; +} + +static int stx104_gpio_direction_output(struct gpio_chip *chip, + unsigned int offset, int value) +{ + if (offset < 4) + return -EINVAL; + + chip->set(chip, offset, value); + return 0; +} + +static int stx104_gpio_get(struct gpio_chip *chip, unsigned int offset) +{ + struct stx104_gpio *const stx104gpio = gpiochip_get_data(chip); + + if (offset >= 4) + return -EINVAL; + + return !!(inb(stx104gpio->base) & BIT(offset)); +} + +static void stx104_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) +{ + struct stx104_gpio *const stx104gpio = gpiochip_get_data(chip); + const unsigned int mask = BIT(offset) >> 4; + unsigned long flags; + + if (offset < 4) + return; + + spin_lock_irqsave(&stx104gpio->lock, flags); + + if (value) + stx104gpio->out_state |= mask; + else + stx104gpio->out_state &= ~mask; + + outb(stx104gpio->out_state, stx104gpio->base); + + spin_unlock_irqrestore(&stx104gpio->lock, flags); +} + +static int stx104_probe(struct device *dev, unsigned int id) +{ + struct iio_dev *indio_dev; + struct stx104_iio *priv; + struct stx104_gpio *stx104gpio; + int err; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*priv)); + if (!indio_dev) + return -ENOMEM; + + stx104gpio = devm_kzalloc(dev, sizeof(*stx104gpio), GFP_KERNEL); + if (!stx104gpio) + return -ENOMEM; + + if (!devm_request_region(dev, base[id], STX104_EXTENT, + dev_name(dev))) { + dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", + base[id], base[id] + STX104_EXTENT); + return -EBUSY; + } + + indio_dev->info = &stx104_info; + indio_dev->modes = INDIO_DIRECT_MODE; + + /* determine if differential inputs */ + if (inb(base[id] + 8) & BIT(5)) { + indio_dev->num_channels = ARRAY_SIZE(stx104_channels_diff); + indio_dev->channels = stx104_channels_diff; + } else { + indio_dev->num_channels = ARRAY_SIZE(stx104_channels_sing); + indio_dev->channels = stx104_channels_sing; + } + + indio_dev->name = dev_name(dev); + + priv = iio_priv(indio_dev); + priv->base = base[id]; + + /* configure device for software trigger operation */ + outb(0, base[id] + 9); + + /* initialize gain setting to x1 */ + outb(0, base[id] + 11); + + /* initialize DAC output to 0V */ + outw(0, base[id] + 4); + outw(0, base[id] + 6); + + err = devm_iio_device_register(dev, indio_dev); + if (err) { + dev_err(dev, "IIO device registering failed (%d)\n", err); + return err; + } + + stx104gpio->chip.label = dev_name(dev); + stx104gpio->chip.parent = dev; + stx104gpio->chip.owner = THIS_MODULE; + stx104gpio->chip.base = -1; + stx104gpio->chip.ngpio = 8; + stx104gpio->chip.get_direction = stx104_gpio_get_direction; + stx104gpio->chip.direction_input = stx104_gpio_direction_input; + stx104gpio->chip.direction_output = stx104_gpio_direction_output; + stx104gpio->chip.get = stx104_gpio_get; + stx104gpio->chip.set = stx104_gpio_set; + stx104gpio->base = base[id] + 3; + stx104gpio->out_state = 0x0; + + spin_lock_init(&stx104gpio->lock); + + dev_set_drvdata(dev, stx104gpio); + + err = gpiochip_add_data(&stx104gpio->chip, stx104gpio); + if (err) { + dev_err(dev, "GPIO registering failed (%d)\n", err); + return err; + } + + return 0; +} + +static int stx104_remove(struct device *dev, unsigned int id) +{ + struct stx104_gpio *const stx104gpio = dev_get_drvdata(dev); + + gpiochip_remove(&stx104gpio->chip); + + return 0; +} + +static struct isa_driver stx104_driver = { + .probe = stx104_probe, + .driver = { + .name = "stx104" + }, + .remove = stx104_remove +}; + +module_isa_driver(stx104_driver, num_stx104); + +MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); +MODULE_DESCRIPTION("Apex Embedded Systems STX104 IIO driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index e8656ba..120b244 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig @@ -264,16 +264,6 @@ config MCP4922 To compile this driver as a module, choose M here: the module will be called mcp4922. -config STX104 - tristate "Apex Embedded Systems STX104 DAC driver" - depends on X86 && ISA_BUS_API - select GPIOLIB - help - Say yes here to build support for the 2-channel DAC and GPIO on the - Apex Embedded Systems STX104 integrated analog PC/104 card. The base - port addresses for the devices may be configured via the base array - module parameter. - config VF610_DAC tristate "Vybrid vf610 DAC driver" depends on OF diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile index c50dbe0..27642bb 100644 --- a/drivers/iio/dac/Makefile +++ b/drivers/iio/dac/Makefile @@ -28,5 +28,4 @@ obj-$(CONFIG_MAX517) += max517.o obj-$(CONFIG_MAX5821) += max5821.o obj-$(CONFIG_MCP4725) += mcp4725.o obj-$(CONFIG_MCP4922) += mcp4922.o -obj-$(CONFIG_STX104) += stx104.o obj-$(CONFIG_VF610_DAC) += vf610_dac.o diff --git a/drivers/iio/dac/stx104.c b/drivers/iio/dac/stx104.c deleted file mode 100644 index 792a971..0000000 --- a/drivers/iio/dac/stx104.c +++ /dev/null @@ -1,255 +0,0 @@ -/* - * DAC driver for the Apex Embedded Systems STX104 - * Copyright (C) 2016 William Breathitt Gray - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2, as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - */ -#include <linux/bitops.h> -#include <linux/device.h> -#include <linux/errno.h> -#include <linux/gpio/driver.h> -#include <linux/iio/iio.h> -#include <linux/iio/types.h> -#include <linux/io.h> -#include <linux/ioport.h> -#include <linux/isa.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/spinlock.h> - -#define STX104_NUM_CHAN 2 - -#define STX104_CHAN(chan) { \ - .type = IIO_VOLTAGE, \ - .channel = chan, \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .indexed = 1, \ - .output = 1 \ -} - -#define STX104_EXTENT 16 - -static unsigned int base[max_num_isa_dev(STX104_EXTENT)]; -static unsigned int num_stx104; -module_param_array(base, uint, &num_stx104, 0); -MODULE_PARM_DESC(base, "Apex Embedded Systems STX104 base addresses"); - -/** - * struct stx104_iio - IIO device private data structure - * @chan_out_states: channels' output states - * @base: base port address of the IIO device - */ -struct stx104_iio { - unsigned chan_out_states[STX104_NUM_CHAN]; - unsigned base; -}; - -/** - * struct stx104_gpio - GPIO device private data structure - * @chip: instance of the gpio_chip - * @lock: synchronization lock to prevent I/O race conditions - * @base: base port address of the GPIO device - * @out_state: output bits state - */ -struct stx104_gpio { - struct gpio_chip chip; - spinlock_t lock; - unsigned int base; - unsigned int out_state; -}; - -static int stx104_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, int *val, int *val2, long mask) -{ - struct stx104_iio *const priv = iio_priv(indio_dev); - - if (mask != IIO_CHAN_INFO_RAW) - return -EINVAL; - - *val = priv->chan_out_states[chan->channel]; - - return IIO_VAL_INT; -} - -static int stx104_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, int val, int val2, long mask) -{ - struct stx104_iio *const priv = iio_priv(indio_dev); - const unsigned chan_addr_offset = 2 * chan->channel; - - if (mask != IIO_CHAN_INFO_RAW) - return -EINVAL; - - priv->chan_out_states[chan->channel] = val; - outw(val, priv->base + 4 + chan_addr_offset); - - return 0; -} - -static const struct iio_info stx104_info = { - .driver_module = THIS_MODULE, - .read_raw = stx104_read_raw, - .write_raw = stx104_write_raw -}; - -static const struct iio_chan_spec stx104_channels[STX104_NUM_CHAN] = { - STX104_CHAN(0), - STX104_CHAN(1) -}; - -static int stx104_gpio_get_direction(struct gpio_chip *chip, - unsigned int offset) -{ - if (offset < 4) - return 1; - - return 0; -} - -static int stx104_gpio_direction_input(struct gpio_chip *chip, - unsigned int offset) -{ - if (offset >= 4) - return -EINVAL; - - return 0; -} - -static int stx104_gpio_direction_output(struct gpio_chip *chip, - unsigned int offset, int value) -{ - if (offset < 4) - return -EINVAL; - - chip->set(chip, offset, value); - return 0; -} - -static int stx104_gpio_get(struct gpio_chip *chip, unsigned int offset) -{ - struct stx104_gpio *const stx104gpio = gpiochip_get_data(chip); - - if (offset >= 4) - return -EINVAL; - - return !!(inb(stx104gpio->base) & BIT(offset)); -} - -static void stx104_gpio_set(struct gpio_chip *chip, unsigned int offset, - int value) -{ - struct stx104_gpio *const stx104gpio = gpiochip_get_data(chip); - const unsigned int mask = BIT(offset) >> 4; - unsigned long flags; - - if (offset < 4) - return; - - spin_lock_irqsave(&stx104gpio->lock, flags); - - if (value) - stx104gpio->out_state |= mask; - else - stx104gpio->out_state &= ~mask; - - outb(stx104gpio->out_state, stx104gpio->base); - - spin_unlock_irqrestore(&stx104gpio->lock, flags); -} - -static int stx104_probe(struct device *dev, unsigned int id) -{ - struct iio_dev *indio_dev; - struct stx104_iio *priv; - struct stx104_gpio *stx104gpio; - int err; - - indio_dev = devm_iio_device_alloc(dev, sizeof(*priv)); - if (!indio_dev) - return -ENOMEM; - - stx104gpio = devm_kzalloc(dev, sizeof(*stx104gpio), GFP_KERNEL); - if (!stx104gpio) - return -ENOMEM; - - if (!devm_request_region(dev, base[id], STX104_EXTENT, - dev_name(dev))) { - dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", - base[id], base[id] + STX104_EXTENT); - return -EBUSY; - } - - indio_dev->info = &stx104_info; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = stx104_channels; - indio_dev->num_channels = STX104_NUM_CHAN; - indio_dev->name = dev_name(dev); - - priv = iio_priv(indio_dev); - priv->base = base[id]; - - /* initialize DAC output to 0V */ - outw(0, base[id] + 4); - outw(0, base[id] + 6); - - err = devm_iio_device_register(dev, indio_dev); - if (err) { - dev_err(dev, "IIO device registering failed (%d)\n", err); - return err; - } - - stx104gpio->chip.label = dev_name(dev); - stx104gpio->chip.parent = dev; - stx104gpio->chip.owner = THIS_MODULE; - stx104gpio->chip.base = -1; - stx104gpio->chip.ngpio = 8; - stx104gpio->chip.get_direction = stx104_gpio_get_direction; - stx104gpio->chip.direction_input = stx104_gpio_direction_input; - stx104gpio->chip.direction_output = stx104_gpio_direction_output; - stx104gpio->chip.get = stx104_gpio_get; - stx104gpio->chip.set = stx104_gpio_set; - stx104gpio->base = base[id] + 3; - stx104gpio->out_state = 0x0; - - spin_lock_init(&stx104gpio->lock); - - dev_set_drvdata(dev, stx104gpio); - - err = gpiochip_add_data(&stx104gpio->chip, stx104gpio); - if (err) { - dev_err(dev, "GPIO registering failed (%d)\n", err); - return err; - } - - return 0; -} - -static int stx104_remove(struct device *dev, unsigned int id) -{ - struct stx104_gpio *const stx104gpio = dev_get_drvdata(dev); - - gpiochip_remove(&stx104gpio->chip); - - return 0; -} - -static struct isa_driver stx104_driver = { - .probe = stx104_probe, - .driver = { - .name = "stx104" - }, - .remove = stx104_remove -}; - -module_isa_driver(stx104_driver, num_stx104); - -MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); -MODULE_DESCRIPTION("Apex Embedded Systems STX104 DAC driver"); -MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 1b246fca4adaa0bf440b604366f2227cc4cde702 Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Tue, 30 Aug 2016 10:18:39 +0200 Subject: iio: st_sensors: fix errorcheck for regulators We were checking the return code of vdd when we should be checking vdd_io. My mistake, mea culpa. Cc: Giuseppe BARBA <giuseppe.barba@st.com> Reported-by: Giuseppe BARBA <giuseppe.barba@st.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c index 41bfe1c..285a64a 100644 --- a/drivers/iio/common/st_sensors/st_sensors_core.c +++ b/drivers/iio/common/st_sensors/st_sensors_core.c @@ -247,9 +247,9 @@ int st_sensors_power_enable(struct iio_dev *indio_dev) } pdata->vdd_io = devm_regulator_get(indio_dev->dev.parent, "vddio"); - if (IS_ERR(pdata->vdd)) { + if (IS_ERR(pdata->vdd_io)) { dev_err(&indio_dev->dev, "unable to get Vdd_IO supply\n"); - err = PTR_ERR(pdata->vdd); + err = PTR_ERR(pdata->vdd_io); goto st_sensors_disable_vdd; } err = regulator_enable(pdata->vdd_io); -- cgit v0.10.2 From 2535cc7ae02bc1e4dc6b6d3771ba8d18cd824e10 Mon Sep 17 00:00:00 2001 From: kbuild test robot <fengguang.wu@intel.com> Date: Thu, 1 Sep 2016 08:38:38 +0800 Subject: iio: chemical: vz89x: fix boolreturn.cocci warnings drivers/iio/chemical/vz89x.c:119:9-10: WARNING: return of 0/1 in function 'vz89x_measurement_is_valid' with return type bool Return statements in functions returning bool should use true/false instead of 1/0. Generated by: scripts/coccinelle/misc/boolreturn.cocci CC: Matt Ranostay <mranostay@gmail.com> Signed-off-by: Fengguang Wu <fengguang.wu@intel.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/chemical/vz89x.c b/drivers/iio/chemical/vz89x.c index cd3870e..8e0e441 100644 --- a/drivers/iio/chemical/vz89x.c +++ b/drivers/iio/chemical/vz89x.c @@ -160,7 +160,7 @@ static const struct attribute_group vz89x_attrs_group = { static bool vz89x_measurement_is_valid(struct vz89x_data *data) { if (data->buffer[VZ89X_VOC_SHORT_IDX] == 0) - return 1; + return true; return !!(data->buffer[data->chip->read_size - 1] > 0); } -- cgit v0.10.2 From 9083325f1197a6956db17809d74dbe3578dc1005 Mon Sep 17 00:00:00 2001 From: Gregor Boirie <gregor.boirie@parrot.com> Date: Fri, 2 Sep 2016 20:47:54 +0200 Subject: iio:trigger: add resource managed (un)register Add resource managed devm_iio_trigger_register() and devm_iio_triger_unregister() to automatically clean up registered triggers allocated by IIO drivers, thus leading to simplified IIO drivers code. Signed-off-by: Gregor Boirie <gregor.boirie@parrot.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index b0d775d..6a2138a 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt @@ -268,6 +268,8 @@ IIO devm_iio_kfifo_free() devm_iio_trigger_alloc() devm_iio_trigger_free() + devm_iio_trigger_register() + devm_iio_trigger_unregister() devm_iio_channel_get() devm_iio_channel_release() devm_iio_channel_get_all() diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c index 3dde81e..ba584b5 100644 --- a/drivers/iio/industrialio-trigger.c +++ b/drivers/iio/industrialio-trigger.c @@ -642,6 +642,65 @@ void devm_iio_trigger_free(struct device *dev, struct iio_trigger *iio_trig) } EXPORT_SYMBOL_GPL(devm_iio_trigger_free); +static void devm_iio_trigger_unreg(struct device *dev, void *res) +{ + iio_trigger_unregister(*(struct iio_trigger **)res); +} + +/** + * devm_iio_trigger_register - Resource-managed iio_trigger_register() + * @dev: device this trigger was allocated for + * @trig_info: trigger to register + * + * Managed iio_trigger_register(). The IIO trigger registered with this + * function is automatically unregistered on driver detach. This function + * calls iio_trigger_register() internally. Refer to that function for more + * information. + * + * If an iio_trigger registered with this function needs to be unregistered + * separately, devm_iio_trigger_unregister() must be used. + * + * RETURNS: + * 0 on success, negative error number on failure. + */ +int devm_iio_trigger_register(struct device *dev, struct iio_trigger *trig_info) +{ + 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); + if (!ret) + devres_add(dev, ptr); + else + devres_free(ptr); + + return ret; +} +EXPORT_SYMBOL_GPL(devm_iio_trigger_register); + +/** + * devm_iio_trigger_unregister - Resource-managed iio_trigger_unregister() + * @dev: device this iio_trigger belongs to + * @trig_info: the trigger associated with the device + * + * Unregister trigger registered with devm_iio_trigger_register(). + */ +void devm_iio_trigger_unregister(struct device *dev, + struct iio_trigger *trig_info) +{ + int rc; + + rc = devres_release(dev, devm_iio_trigger_unreg, devm_iio_trigger_match, + trig_info); + WARN_ON(rc); +} +EXPORT_SYMBOL_GPL(devm_iio_trigger_unregister); + void iio_device_register_trigger_consumer(struct iio_dev *indio_dev) { indio_dev->groups[indio_dev->groupcounter++] = diff --git a/include/linux/iio/trigger.h b/include/linux/iio/trigger.h index a122bdd..f0890a5 100644 --- a/include/linux/iio/trigger.h +++ b/include/linux/iio/trigger.h @@ -125,12 +125,18 @@ static inline void *iio_trigger_get_drvdata(struct iio_trigger *trig) **/ int iio_trigger_register(struct iio_trigger *trig_info); +int devm_iio_trigger_register(struct device *dev, + struct iio_trigger *trig_info); + /** * iio_trigger_unregister() - unregister a trigger from the core * @trig_info: trigger to be unregistered **/ void iio_trigger_unregister(struct iio_trigger *trig_info); +void devm_iio_trigger_unregister(struct device *dev, + struct iio_trigger *trig_info); + /** * iio_trigger_set_immutable() - set an immutable trigger on destination * -- cgit v0.10.2 From 70e483487db787b152da756d4be0fef917378142 Mon Sep 17 00:00:00 2001 From: Gregor Boirie <gregor.boirie@parrot.com> Date: Fri, 2 Sep 2016 20:47:55 +0200 Subject: iio: add resource managed triggered buffer init helpers Add resource managed devm_iio_triggered_buffer_setup() and devm_iio_triggered_buffer_cleanup() to automatically clean up triggered buffers setup by IIO drivers, thus leading to simplified IIO drivers code. Signed-off-by: Gregor Boirie <gregor.boirie@parrot.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index 6a2138a..75bc5b8 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt @@ -266,6 +266,8 @@ IIO devm_iio_device_unregister() devm_iio_kfifo_allocate() devm_iio_kfifo_free() + devm_iio_triggered_buffer_setup() + devm_iio_triggered_buffer_cleanup() devm_iio_trigger_alloc() devm_iio_trigger_free() devm_iio_trigger_register() diff --git a/drivers/iio/buffer/industrialio-triggered-buffer.c b/drivers/iio/buffer/industrialio-triggered-buffer.c index 4b2858b..d3db1fc 100644 --- a/drivers/iio/buffer/industrialio-triggered-buffer.c +++ b/drivers/iio/buffer/industrialio-triggered-buffer.c @@ -98,6 +98,48 @@ 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) +{ + iio_triggered_buffer_cleanup(*(struct iio_dev **)res); +} + +int devm_iio_triggered_buffer_setup(struct device *dev, + struct iio_dev *indio_dev, + irqreturn_t (*h)(int irq, void *p), + irqreturn_t (*thread)(int irq, void *p), + const struct iio_buffer_setup_ops *ops) +{ + 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(indio_dev, h, thread, ops); + if (!ret) + devres_add(dev, ptr); + else + devres_free(ptr); + + return ret; +} +EXPORT_SYMBOL_GPL(devm_iio_triggered_buffer_setup); + +void devm_iio_triggered_buffer_cleanup(struct device *dev, + struct iio_dev *indio_dev) +{ + int rc; + + rc = devres_release(dev, devm_iio_triggered_buffer_clean, + devm_iio_device_match, indio_dev); + WARN_ON(rc); +} +EXPORT_SYMBOL_GPL(devm_iio_triggered_buffer_cleanup); + MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); MODULE_DESCRIPTION("IIO helper functions for setting up triggered buffers"); MODULE_LICENSE("GPL"); diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index f914d5d..0528a0c 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -1309,7 +1309,7 @@ static void devm_iio_device_release(struct device *dev, void *res) iio_device_free(*(struct iio_dev **)res); } -static int devm_iio_device_match(struct device *dev, void *res, void *data) +int devm_iio_device_match(struct device *dev, void *res, void *data) { struct iio_dev **r = res; if (!r || !*r) { @@ -1318,6 +1318,7 @@ static int devm_iio_device_match(struct device *dev, void *res, void *data) } return *r == data; } +EXPORT_SYMBOL_GPL(devm_iio_device_match); /** * devm_iio_device_alloc - Resource-managed iio_device_alloc() diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 786952c..b4a0679 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -644,6 +644,7 @@ static inline struct iio_dev *iio_priv_to_dev(void *priv) } void iio_device_free(struct iio_dev *indio_dev); +int devm_iio_device_match(struct device *dev, void *res, void *data); struct iio_dev *devm_iio_device_alloc(struct device *dev, int sizeof_priv); void devm_iio_device_free(struct device *dev, struct iio_dev *indio_dev); struct iio_trigger *devm_iio_trigger_alloc(struct device *dev, diff --git a/include/linux/iio/triggered_buffer.h b/include/linux/iio/triggered_buffer.h index f72f70d..3014561 100644 --- a/include/linux/iio/triggered_buffer.h +++ b/include/linux/iio/triggered_buffer.h @@ -12,4 +12,12 @@ int iio_triggered_buffer_setup(struct iio_dev *indio_dev, const struct iio_buffer_setup_ops *setup_ops); void iio_triggered_buffer_cleanup(struct iio_dev *indio_dev); +int devm_iio_triggered_buffer_setup(struct device *dev, + struct iio_dev *indio_dev, + irqreturn_t (*h)(int irq, void *p), + irqreturn_t (*thread)(int irq, void *p), + const struct iio_buffer_setup_ops *ops); +void devm_iio_triggered_buffer_cleanup(struct device *dev, + struct iio_dev *indio_dev); + #endif -- cgit v0.10.2 From 88f6ba61f25bfe6eb92cb8f511b0879cdfbb64d3 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Wed, 3 Aug 2016 15:52:10 -0700 Subject: greybus: gpio: create irqdomain before registering gpio controller If a gpio line is getting used for an irq, gpio core will create /proc/irq/X/gpiolib/ directory for it. This directory gets removed while the gpio controller is unregistered. In case of greybus, gb_gpio_irqchip_add() creates an irqdomain and creates irq mappings for the gpio lines. Currently they are added after registering the gpio controller and removed before the gpio controller is removed. On the removal path, while the core tries to remove the irq directory (/proc/irq/X), it finds that the irq is still getting used and a "gpiolib" directory is present within it and so it gives this warning: Steps to reproduce: $ cd /sys/class/gpio $ echo X > export $ echo both > gpioX/edge $ echo <interface-number> > /sys/bus/greybus/devices/1-svc/intf_eject [ 139.171436] ------------[ cut here ]------------ [ 139.171468] WARNING: at /home/vireshk/all/work/repos/ara/arche/kernel/arche/fs/proc/generic.c:552 remove_proc_entry+0x154/0x188() [ 139.171476] remove_proc_entry: removing non-empty directory 'irq/683', leaking at least 'gpiolib' [ 139.171589] Modules linked in: gb_vibrator(O) gb_usb(O) gb_uart(O) gb_spi(O) gb_sdio(O) gb_raw(O) gb_pwm(O) gb_power_supply(O) gb_loopback(O) gb_log(O) gb_light(O) gb_i2c(O) gb_hid(O) gb_gpio(O) gb_gbphy(O) gb_firmware(O) gb_spilib(O) gb_es2(O) gb_camera(O) gb_bootrom(O) gb_audio_module(O) gb_audio_manager(O) gb_audio_codec(O) gb_audio_gb(O) gb_audio_apbridgea(O) gb_arche(O) greybus(O) [ 139.171605] CPU: 1 PID: 280 Comm: kworker/u16:4 Tainted: G W O 3.10.83-g9771b10cbeed #107 [ 139.171652] Workqueue: greybus1:svc gb_svc_intf_set_power_mode [greybus] [ 139.171657] Call trace: [ 139.171677] [<ffffffc000207b40>] dump_backtrace+0x0/0x268 [ 139.171689] [<ffffffc000207db8>] show_stack+0x10/0x1c [ 139.171707] [<ffffffc000ccad78>] dump_stack+0x1c/0x28 [ 139.171723] [<ffffffc00021f9dc>] warn_slowpath_common+0x74/0x9c [ 139.171735] [<ffffffc00021fa60>] warn_slowpath_fmt+0x5c/0x80 [ 139.171747] [<ffffffc00035fa38>] remove_proc_entry+0x150/0x188 [ 139.171763] [<ffffffc00027464c>] unregister_irq_proc+0xb4/0xdc [ 139.171779] [<ffffffc00026e3f4>] free_desc+0x2c/0x70 [ 139.171791] [<ffffffc00026e48c>] irq_free_descs+0x54/0x9c [ 139.171802] [<ffffffc000273448>] irq_dispose_mapping+0x54/0x64 [ 139.171814] [<ffffffbffc0621e8>] 0xffffffbffc0621e8 [ 139.171825] [<ffffffbffc05e01c>] 0xffffffbffc05e01c [ 139.171843] [<ffffffc0005d4e30>] __device_release_driver+0x90/0xe4 [ 139.171854] [<ffffffc0005d4ea4>] device_release_driver+0x20/0x38 [ 139.171867] [<ffffffc0005d4634>] bus_remove_device+0x12c/0x148 [ 139.171878] [<ffffffc0005d1cb0>] device_del+0x108/0x16c [ 139.171888] [<ffffffc0005d1d64>] device_unregister+0x50/0x68 [ 139.171901] [<ffffffbffc05e2bc>] gb_gbphy_deregister_driver+0xf0/0x4ec [gb_gbphy] [ 139.171924] [<ffffffbffc0014c4>] greybus_disabled+0x14c4/0x1760 [greybus] [ 139.171936] [<ffffffc0005d4e30>] __device_release_driver+0x90/0xe4 [ 139.171948] [<ffffffc0005d4ea4>] device_release_driver+0x20/0x38 [ 139.171959] [<ffffffc0005d4634>] bus_remove_device+0x12c/0x148 [ 139.171969] [<ffffffc0005d1cb0>] device_del+0x108/0x16c [ 139.171992] [<ffffffbffc004cec>] gb_bundle_destroy+0x7c/0x1b0 [greybus] [ 139.172017] [<ffffffbffc004074>] gb_interface_disable+0xb4/0x178 [greybus] [ 139.172040] [<ffffffbffc002ae4>] gb_module_del+0x5c/0xf8 [greybus] [ 139.172063] [<ffffffbffc008418>] gb_svc_intf_set_power_mode+0xea0/0xfe8 [greybus] [ 139.172078] [<ffffffc00023888c>] process_one_work+0x268/0x3c8 [ 139.172089] [<ffffffc000239a64>] worker_thread+0x204/0x358 [ 139.172108] [<ffffffc00023f43c>] kthread+0xb8/0xc4 [ 139.172114] ---[ end trace 6fa3314e8c6157ca ]--- Also note that registering the gpio controller before creating irqdomain is incorrect as well and may lead to kernel panic, as a gpio may get requested as an interrupt source right after the controller is registered, and the greybus gpio driver wouldn't be fully ready by then. This patch changes the sequence in both probe() and remove() to fix it. Fixes: 426e88a47d39 ("greybus: gpio: add interrupt handling support") Reported-by: David Hsu <davidhsu@google.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 8fa9998..294e2f5 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -708,26 +708,26 @@ static int gb_gpio_probe(struct gbphy_device *gbphy_dev, if (ret) goto exit_line_free; - ret = gpiochip_add(gpio); + ret = gb_gpio_irqchip_add(gpio, irqc, 0, + handle_level_irq, IRQ_TYPE_NONE); if (ret) { dev_err(&connection->bundle->dev, - "failed to add gpio chip: %d\n", ret); + "failed to add irq chip: %d\n", ret); goto exit_line_free; } - ret = gb_gpio_irqchip_add(gpio, irqc, 0, - handle_level_irq, IRQ_TYPE_NONE); + ret = gpiochip_add(gpio); if (ret) { dev_err(&connection->bundle->dev, - "failed to add irq chip: %d\n", ret); - goto exit_gpiochip_remove; + "failed to add gpio chip: %d\n", ret); + goto exit_gpio_irqchip_remove; } gbphy_runtime_put_autosuspend(gbphy_dev); return 0; -exit_gpiochip_remove: - gb_gpiochip_remove(gpio); +exit_gpio_irqchip_remove: + gb_gpio_irqchip_remove(ggc); exit_line_free: kfree(ggc->lines); exit_connection_disable: @@ -750,8 +750,8 @@ static void gb_gpio_remove(struct gbphy_device *gbphy_dev) gbphy_runtime_get_noresume(gbphy_dev); gb_connection_disable_rx(connection); - gb_gpio_irqchip_remove(ggc); gb_gpiochip_remove(&ggc->chip); + gb_gpio_irqchip_remove(ggc); gb_connection_disable(connection); gb_connection_destroy(connection); kfree(ggc->lines); -- cgit v0.10.2 From 67516074884b4bde71ca8ca4724544669935cc5d Mon Sep 17 00:00:00 2001 From: Crt Mori <cmo@melexis.com> Date: Mon, 5 Sep 2016 11:14:48 +0200 Subject: iio: fetch and enable regulators unconditionally This patch is inspired by a comment of Jonathan Cameron on patch of Linus Walleij commit aeb55fff3891834e07a3144159a7298a19696af8 ("iio: st_sensors: fetch and enable regulators unconditionally"). The explanation for this change is same as in that patch: "Supplies are *not* optional (optional means that the supply is optional in the electrical sense, not the software sense) so we need to get the and enable them at all times. If the device tree or board file does not define suitable regulators for the component, it will be substituted by a dummy regulator, or, if regulators are disabled altogether, by stubs. There is no need to use the IS_ERR_OR_NULL() check that is considered harmful. Reported-by: Linus Wallerij <linus.walleij@linaro.org> Suggested-by: Jonathan Cameron <jic23@kernel.org> Signed-off-by: Crt Mori <cmo@melexis.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/pressure/ms5611_core.c b/drivers/iio/pressure/ms5611_core.c index feb41f8..a74ed1f 100644 --- a/drivers/iio/pressure/ms5611_core.c +++ b/drivers/iio/pressure/ms5611_core.c @@ -416,8 +416,7 @@ static int ms5611_init(struct iio_dev *indio_dev) return 0; err_regulator_disable: - if (!IS_ERR_OR_NULL(st->vdd)) - regulator_disable(st->vdd); + regulator_disable(st->vdd); return ret; } @@ -425,8 +424,7 @@ static void ms5611_fini(const struct iio_dev *indio_dev) { const struct ms5611_state *st = iio_priv(indio_dev); - if (!IS_ERR_OR_NULL(st->vdd)) - regulator_disable(st->vdd); + regulator_disable(st->vdd); } int ms5611_probe(struct iio_dev *indio_dev, struct device *dev, -- cgit v0.10.2 From fbe84bd4803eb6c96376af5530ce69e1db873b5f Mon Sep 17 00:00:00 2001 From: Crt Mori <cmo@melexis.com> Date: Mon, 5 Sep 2016 11:14:49 +0200 Subject: iio: devm_regulator_get_optional never returns NULL This patch is inspired by a comment of Jonathan Cameron on patch of Linus Walleij commit aeb55fff3891834e07a3144159a7298a19696af8 ("iio: st_sensors: fetch and enable regulators unconditionally"). Because changes made in this patch are actually reference generators they should be using devm_regulator_get_optional, but if they do not explicitly set the reference to NULL they should not be using IS_ERR_OR_NULL, but simple IS_ERR check. Suggested-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Crt Mori <cmo@melexis.com> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Acked-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c index c0f6a98..b8d5cfd 100644 --- a/drivers/iio/adc/ad7266.c +++ b/drivers/iio/adc/ad7266.c @@ -481,7 +481,7 @@ error_free_gpios: if (!st->fixed_addr) gpio_free_array(st->gpios, ARRAY_SIZE(st->gpios)); error_disable_reg: - if (!IS_ERR_OR_NULL(st->reg)) + if (!IS_ERR(st->reg)) regulator_disable(st->reg); return ret; @@ -496,7 +496,7 @@ static int ad7266_remove(struct spi_device *spi) iio_triggered_buffer_cleanup(indio_dev); if (!st->fixed_addr) gpio_free_array(st->gpios, ARRAY_SIZE(st->gpios)); - if (!IS_ERR_OR_NULL(st->reg)) + if (!IS_ERR(st->reg)) regulator_disable(st->reg); return 0; diff --git a/drivers/iio/adc/ti-ads8688.c b/drivers/iio/adc/ti-ads8688.c index c400439..4a16349 100644 --- a/drivers/iio/adc/ti-ads8688.c +++ b/drivers/iio/adc/ti-ads8688.c @@ -438,7 +438,7 @@ static int ads8688_probe(struct spi_device *spi) return 0; error_out: - if (!IS_ERR_OR_NULL(st->reg)) + if (!IS_ERR(st->reg)) regulator_disable(st->reg); return ret; @@ -451,7 +451,7 @@ static int ads8688_remove(struct spi_device *spi) iio_device_unregister(indio_dev); - if (!IS_ERR_OR_NULL(st->reg)) + if (!IS_ERR(st->reg)) regulator_disable(st->reg); return 0; -- cgit v0.10.2 From ede63aaf7cda21bc265edb928f01363784cbf3fc Mon Sep 17 00:00:00 2001 From: Nicolas Ferre <nicolas.ferre@atmel.com> Date: Tue, 30 Aug 2016 14:27:01 +0200 Subject: iio: adc: at91: Add support for Touchscreen Switches Closure Time On newer components compatible with the at91sam9x5, the Touchscreen Switches Closure Time or TSSCTIM value of the Touchscreen Mode Register is not filled at all. On some hardware, having no time indicated for it may lead to incoherent values and jitter. We fix this time to 10us as it is usually difficult to retrieve impedance values from LCD manufacturers. Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 52430ba..0331c7a 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -113,6 +113,7 @@ #define AT91_ADC_TSMR_TSAV (3 << 4) /* Averages samples */ #define AT91_ADC_TSMR_TSAV_(x) ((x) << 4) #define AT91_ADC_TSMR_SCTIM (0x0f << 16) /* Switch closure time */ +#define AT91_ADC_TSMR_SCTIM_(x) ((x) << 16) #define AT91_ADC_TSMR_PENDBC (0x0f << 28) /* Pen Debounce time */ #define AT91_ADC_TSMR_PENDBC_(x) ((x) << 28) #define AT91_ADC_TSMR_NOTSDMA (1 << 22) /* No Touchscreen DMA */ @@ -150,6 +151,7 @@ #define MAX_RLPOS_BITS 10 #define TOUCH_SAMPLE_PERIOD_US_RL 10000 /* 10ms, the SoC can't keep up with 2ms */ #define TOUCH_SHTIM 0xa +#define TOUCH_SCTIM_US 10 /* 10us for the Touchscreen Switches Closure Time */ /** * struct at91_adc_reg_desc - Various informations relative to registers @@ -1001,7 +1003,9 @@ static void atmel_ts_close(struct input_dev *dev) static int at91_ts_hw_init(struct at91_adc_state *st, u32 adc_clk_khz) { + struct iio_dev *idev = iio_priv_to_dev(st); u32 reg = 0; + u32 tssctim = 0; int i = 0; /* a Pen Detect Debounce Time is necessary for the ADC Touch to avoid @@ -1034,11 +1038,20 @@ static int at91_ts_hw_init(struct at91_adc_state *st, u32 adc_clk_khz) return 0; } + /* Touchscreen Switches Closure time needed for allowing the value to + * stabilize. + * Switch Closure Time = (TSSCTIM * 4) ADCClock periods + */ + tssctim = DIV_ROUND_UP(TOUCH_SCTIM_US * adc_clk_khz / 1000, 4); + dev_dbg(&idev->dev, "adc_clk at: %d KHz, tssctim at: %d\n", + adc_clk_khz, tssctim); + if (st->touchscreen_type == ATMEL_ADC_TOUCHSCREEN_4WIRE) reg = AT91_ADC_TSMR_TSMODE_4WIRE_PRESS; else reg = AT91_ADC_TSMR_TSMODE_5WIRE; + reg |= AT91_ADC_TSMR_SCTIM_(tssctim) & AT91_ADC_TSMR_SCTIM; reg |= AT91_ADC_TSMR_TSAV_(st->caps->ts_filter_average) & AT91_ADC_TSMR_TSAV; reg |= AT91_ADC_TSMR_PENDBC_(st->ts_pendbc) & AT91_ADC_TSMR_PENDBC; -- cgit v0.10.2 From 06777c562a50a09c4a2becfb2bf63c762a45df17 Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Sun, 4 Sep 2016 19:35:32 +0200 Subject: iio: accel: mxc6255 add support for the mxc6225 The mxc6225 is fully compatible with the existing mxc6255 driver, add support for it. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/accel/mxc6255.c b/drivers/iio/accel/mxc6255.c index 97ccde7..50343a7 100644 --- a/drivers/iio/accel/mxc6255.c +++ b/drivers/iio/accel/mxc6255.c @@ -26,6 +26,7 @@ #define MXC6255_REG_YOUT 0x01 #define MXC6255_REG_CHIP_ID 0x08 +#define MXC6225_CHIP_ID 0xe5 #define MXC6255_CHIP_ID 0x05 /* @@ -154,7 +155,11 @@ static int mxc6255_probe(struct i2c_client *client, return ret; } - if (chip_id != MXC6255_CHIP_ID) { + switch (chip_id) { + case MXC6225_CHIP_ID: + case MXC6255_CHIP_ID: + break; + default: dev_err(&client->dev, "Invalid chip id %x\n", chip_id); return -ENODEV; } @@ -171,12 +176,14 @@ static int mxc6255_probe(struct i2c_client *client, } static const struct acpi_device_id mxc6255_acpi_match[] = { + {"MXC6225", 0}, {"MXC6255", 0}, { } }; MODULE_DEVICE_TABLE(acpi, mxc6255_acpi_match); static const struct i2c_device_id mxc6255_id[] = { + {"mxc6225", 0}, {"mxc6255", 0}, { } }; -- cgit v0.10.2 From b1fa6d8acb50c8e90f50fb262e5d4b7d478592bf Mon Sep 17 00:00:00 2001 From: Laura Abbott <labbott@redhat.com> Date: Wed, 7 Sep 2016 11:49:58 -0700 Subject: staging: android: ion: Pull out ion ioctls to a separate file The number of Ion ioctls may continue to grow along with necessary validation. Pull it out into a separate file for easier management and review. Signed-off-by: Laura Abbott <labbott@redhat.com> Acked-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile index 18cc2aa..376c2b2 100644 --- a/drivers/staging/android/ion/Makefile +++ b/drivers/staging/android/ion/Makefile @@ -1,4 +1,5 @@ -obj-$(CONFIG_ION) += ion.o ion_heap.o ion_page_pool.o ion_system_heap.o \ +obj-$(CONFIG_ION) += ion.o ion-ioctl.o ion_heap.o \ + ion_page_pool.o ion_system_heap.o \ ion_carveout_heap.o ion_chunk_heap.o ion_cma_heap.o obj-$(CONFIG_ION_TEST) += ion_test.o ifdef CONFIG_COMPAT diff --git a/drivers/staging/android/ion/ion-ioctl.c b/drivers/staging/android/ion/ion-ioctl.c new file mode 100644 index 0000000..341ba7d --- /dev/null +++ b/drivers/staging/android/ion/ion-ioctl.c @@ -0,0 +1,144 @@ +/* + * + * Copyright (C) 2011 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/kernel.h> +#include <linux/file.h> +#include <linux/fs.h> +#include <linux/uaccess.h> + +#include "ion.h" +#include "ion_priv.h" +#include "compat_ion.h" + +/* fix up the cases where the ioctl direction bits are incorrect */ +static unsigned int ion_ioctl_dir(unsigned int cmd) +{ + switch (cmd) { + case ION_IOC_SYNC: + case ION_IOC_FREE: + case ION_IOC_CUSTOM: + return _IOC_WRITE; + default: + return _IOC_DIR(cmd); + } +} + +long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct ion_client *client = filp->private_data; + struct ion_device *dev = client->dev; + struct ion_handle *cleanup_handle = NULL; + int ret = 0; + unsigned int dir; + + union { + struct ion_fd_data fd; + struct ion_allocation_data allocation; + struct ion_handle_data handle; + struct ion_custom_data custom; + } data; + + dir = ion_ioctl_dir(cmd); + + if (_IOC_SIZE(cmd) > sizeof(data)) + return -EINVAL; + + if (dir & _IOC_WRITE) + if (copy_from_user(&data, (void __user *)arg, _IOC_SIZE(cmd))) + return -EFAULT; + + switch (cmd) { + case ION_IOC_ALLOC: + { + struct ion_handle *handle; + + handle = ion_alloc(client, data.allocation.len, + data.allocation.align, + data.allocation.heap_id_mask, + data.allocation.flags); + if (IS_ERR(handle)) + return PTR_ERR(handle); + + data.allocation.handle = handle->id; + + cleanup_handle = handle; + break; + } + case ION_IOC_FREE: + { + struct ion_handle *handle; + + mutex_lock(&client->lock); + handle = ion_handle_get_by_id_nolock(client, data.handle.handle); + if (IS_ERR(handle)) { + mutex_unlock(&client->lock); + return PTR_ERR(handle); + } + ion_free_nolock(client, handle); + ion_handle_put_nolock(handle); + mutex_unlock(&client->lock); + break; + } + case ION_IOC_SHARE: + case ION_IOC_MAP: + { + struct ion_handle *handle; + + handle = ion_handle_get_by_id(client, data.handle.handle); + if (IS_ERR(handle)) + return PTR_ERR(handle); + data.fd.fd = ion_share_dma_buf_fd(client, handle); + ion_handle_put(handle); + if (data.fd.fd < 0) + ret = data.fd.fd; + break; + } + case ION_IOC_IMPORT: + { + struct ion_handle *handle; + + handle = ion_import_dma_buf_fd(client, data.fd.fd); + if (IS_ERR(handle)) + ret = PTR_ERR(handle); + else + data.handle.handle = handle->id; + break; + } + case ION_IOC_SYNC: + { + ret = ion_sync_for_device(client, data.fd.fd); + break; + } + case ION_IOC_CUSTOM: + { + if (!dev->custom_ioctl) + return -ENOTTY; + ret = dev->custom_ioctl(client, data.custom.cmd, + data.custom.arg); + break; + } + default: + return -ENOTTY; + } + + if (dir & _IOC_READ) { + if (copy_to_user((void __user *)arg, &data, _IOC_SIZE(cmd))) { + if (cleanup_handle) + ion_free(client, cleanup_handle); + return -EFAULT; + } + } + return ret; +} diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 47de11a..a92804f 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -41,80 +41,6 @@ #include "ion_priv.h" #include "compat_ion.h" -/** - * struct ion_device - the metadata of the ion device node - * @dev: the actual misc device - * @buffers: an rb tree of all the existing buffers - * @buffer_lock: lock protecting the tree of buffers - * @lock: rwsem protecting the tree of heaps and clients - * @heaps: list of all the heaps in the system - * @user_clients: list of all the clients created from userspace - */ -struct ion_device { - struct miscdevice dev; - struct rb_root buffers; - struct mutex buffer_lock; - struct rw_semaphore lock; - struct plist_head heaps; - long (*custom_ioctl)(struct ion_client *client, unsigned int cmd, - unsigned long arg); - struct rb_root clients; - struct dentry *debug_root; - struct dentry *heaps_debug_root; - struct dentry *clients_debug_root; -}; - -/** - * struct ion_client - a process/hw block local address space - * @node: node in the tree of all clients - * @dev: backpointer to ion device - * @handles: an rb tree of all the handles in this client - * @idr: an idr space for allocating handle ids - * @lock: lock protecting the tree of handles - * @name: used for debugging - * @display_name: used for debugging (unique version of @name) - * @display_serial: used for debugging (to make display_name unique) - * @task: used for debugging - * - * A client represents a list of buffers this client may access. - * The mutex stored here is used to protect both handles tree - * as well as the handles themselves, and should be held while modifying either. - */ -struct ion_client { - struct rb_node node; - struct ion_device *dev; - struct rb_root handles; - struct idr idr; - struct mutex lock; - const char *name; - char *display_name; - int display_serial; - struct task_struct *task; - pid_t pid; - struct dentry *debug_root; -}; - -/** - * ion_handle - a client local reference to a buffer - * @ref: reference count - * @client: back pointer to the client the buffer resides in - * @buffer: pointer to the buffer - * @node: node in the client's handle rbtree - * @kmap_cnt: count of times this client has mapped to kernel - * @id: client-unique id allocated by client->idr - * - * Modifications to node, map_cnt or mapping should be protected by the - * lock in the client. Other fields are never changed after initialization. - */ -struct ion_handle { - struct kref ref; - struct ion_client *client; - struct ion_buffer *buffer; - struct rb_node node; - unsigned int kmap_cnt; - int id; -}; - bool ion_buffer_fault_user_mappings(struct ion_buffer *buffer) { return (buffer->flags & ION_FLAG_CACHED) && @@ -376,12 +302,12 @@ static void ion_handle_get(struct ion_handle *handle) kref_get(&handle->ref); } -static int ion_handle_put_nolock(struct ion_handle *handle) +int ion_handle_put_nolock(struct ion_handle *handle) { return kref_put(&handle->ref, ion_handle_destroy); } -static int ion_handle_put(struct ion_handle *handle) +int ion_handle_put(struct ion_handle *handle) { struct ion_client *client = handle->client; int ret; @@ -411,8 +337,8 @@ static struct ion_handle *ion_handle_lookup(struct ion_client *client, return ERR_PTR(-EINVAL); } -static struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client, - int id) +struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client, + int id) { struct ion_handle *handle; @@ -423,7 +349,7 @@ static struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client, return handle ? handle : ERR_PTR(-EINVAL); } -static struct ion_handle *ion_handle_get_by_id(struct ion_client *client, +struct ion_handle *ion_handle_get_by_id(struct ion_client *client, int id) { struct ion_handle *handle; @@ -536,8 +462,8 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, } EXPORT_SYMBOL(ion_alloc); -static void ion_free_nolock(struct ion_client *client, - struct ion_handle *handle) +void ion_free_nolock(struct ion_client *client, + struct ion_handle *handle) { if (!ion_handle_validate(client, handle)) { WARN(1, "%s: invalid handle passed to free.\n", __func__); @@ -1209,7 +1135,7 @@ struct ion_handle *ion_import_dma_buf_fd(struct ion_client *client, int fd) } EXPORT_SYMBOL(ion_import_dma_buf_fd); -static int ion_sync_for_device(struct ion_client *client, int fd) +int ion_sync_for_device(struct ion_client *client, int fd) { struct dma_buf *dmabuf; struct ion_buffer *buffer; @@ -1233,128 +1159,6 @@ static int ion_sync_for_device(struct ion_client *client, int fd) return 0; } -/* fix up the cases where the ioctl direction bits are incorrect */ -static unsigned int ion_ioctl_dir(unsigned int cmd) -{ - switch (cmd) { - case ION_IOC_SYNC: - case ION_IOC_FREE: - case ION_IOC_CUSTOM: - return _IOC_WRITE; - default: - return _IOC_DIR(cmd); - } -} - -static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - struct ion_client *client = filp->private_data; - struct ion_device *dev = client->dev; - struct ion_handle *cleanup_handle = NULL; - int ret = 0; - unsigned int dir; - - union { - struct ion_fd_data fd; - struct ion_allocation_data allocation; - struct ion_handle_data handle; - struct ion_custom_data custom; - } data; - - dir = ion_ioctl_dir(cmd); - - if (_IOC_SIZE(cmd) > sizeof(data)) - return -EINVAL; - - if (dir & _IOC_WRITE) - if (copy_from_user(&data, (void __user *)arg, _IOC_SIZE(cmd))) - return -EFAULT; - - switch (cmd) { - case ION_IOC_ALLOC: - { - struct ion_handle *handle; - - handle = ion_alloc(client, data.allocation.len, - data.allocation.align, - data.allocation.heap_id_mask, - data.allocation.flags); - if (IS_ERR(handle)) - return PTR_ERR(handle); - - data.allocation.handle = handle->id; - - cleanup_handle = handle; - break; - } - case ION_IOC_FREE: - { - struct ion_handle *handle; - - mutex_lock(&client->lock); - handle = ion_handle_get_by_id_nolock(client, - data.handle.handle); - if (IS_ERR(handle)) { - mutex_unlock(&client->lock); - return PTR_ERR(handle); - } - ion_free_nolock(client, handle); - ion_handle_put_nolock(handle); - mutex_unlock(&client->lock); - break; - } - case ION_IOC_SHARE: - case ION_IOC_MAP: - { - struct ion_handle *handle; - - handle = ion_handle_get_by_id(client, data.handle.handle); - if (IS_ERR(handle)) - return PTR_ERR(handle); - data.fd.fd = ion_share_dma_buf_fd(client, handle); - ion_handle_put(handle); - if (data.fd.fd < 0) - ret = data.fd.fd; - break; - } - case ION_IOC_IMPORT: - { - struct ion_handle *handle; - - handle = ion_import_dma_buf_fd(client, data.fd.fd); - if (IS_ERR(handle)) - ret = PTR_ERR(handle); - else - data.handle.handle = handle->id; - break; - } - case ION_IOC_SYNC: - { - ret = ion_sync_for_device(client, data.fd.fd); - break; - } - case ION_IOC_CUSTOM: - { - if (!dev->custom_ioctl) - return -ENOTTY; - ret = dev->custom_ioctl(client, data.custom.cmd, - data.custom.arg); - break; - } - default: - return -ENOTTY; - } - - if (dir & _IOC_READ) { - if (copy_to_user((void __user *)arg, &data, _IOC_SIZE(cmd))) { - if (cleanup_handle) - ion_free(client, cleanup_handle); - return -EFAULT; - } - } - return ret; -} - static int ion_release(struct inode *inode, struct file *file) { struct ion_client *client = file->private_data; diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index fcbc231..4a78fab 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -26,6 +26,7 @@ #include <linux/sched.h> #include <linux/shrinker.h> #include <linux/types.h> +#include <linux/miscdevice.h> #include "ion.h" @@ -81,6 +82,80 @@ struct ion_buffer { void ion_buffer_destroy(struct ion_buffer *buffer); /** + * struct ion_device - the metadata of the ion device node + * @dev: the actual misc device + * @buffers: an rb tree of all the existing buffers + * @buffer_lock: lock protecting the tree of buffers + * @lock: rwsem protecting the tree of heaps and clients + * @heaps: list of all the heaps in the system + * @user_clients: list of all the clients created from userspace + */ +struct ion_device { + struct miscdevice dev; + struct rb_root buffers; + struct mutex buffer_lock; + struct rw_semaphore lock; + struct plist_head heaps; + long (*custom_ioctl)(struct ion_client *client, unsigned int cmd, + unsigned long arg); + struct rb_root clients; + struct dentry *debug_root; + struct dentry *heaps_debug_root; + struct dentry *clients_debug_root; +}; + +/** + * struct ion_client - a process/hw block local address space + * @node: node in the tree of all clients + * @dev: backpointer to ion device + * @handles: an rb tree of all the handles in this client + * @idr: an idr space for allocating handle ids + * @lock: lock protecting the tree of handles + * @name: used for debugging + * @display_name: used for debugging (unique version of @name) + * @display_serial: used for debugging (to make display_name unique) + * @task: used for debugging + * + * A client represents a list of buffers this client may access. + * The mutex stored here is used to protect both handles tree + * as well as the handles themselves, and should be held while modifying either. + */ +struct ion_client { + struct rb_node node; + struct ion_device *dev; + struct rb_root handles; + struct idr idr; + struct mutex lock; + const char *name; + char *display_name; + int display_serial; + struct task_struct *task; + pid_t pid; + struct dentry *debug_root; +}; + +/** + * ion_handle - a client local reference to a buffer + * @ref: reference count + * @client: back pointer to the client the buffer resides in + * @buffer: pointer to the buffer + * @node: node in the client's handle rbtree + * @kmap_cnt: count of times this client has mapped to kernel + * @id: client-unique id allocated by client->idr + * + * Modifications to node, map_cnt or mapping should be protected by the + * lock in the client. Other fields are never changed after initialization. + */ +struct ion_handle { + struct kref ref; + struct ion_client *client; + struct ion_buffer *buffer; + struct rb_node node; + unsigned int kmap_cnt; + int id; +}; + +/** * struct ion_heap_ops - ops to operate on a given heap * @allocate: allocate memory * @free: free memory @@ -376,4 +451,20 @@ int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, void ion_pages_sync_for_device(struct device *dev, struct page *page, size_t size, enum dma_data_direction dir); +long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); + +int ion_sync_for_device(struct ion_client *client, int fd); + +struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client, + int id); + +void ion_free_nolock(struct ion_client *client, struct ion_handle *handle); + +int ion_handle_put_nolock(struct ion_handle *handle); + +struct ion_handle *ion_handle_get_by_id(struct ion_client *client, + int id); + +int ion_handle_put(struct ion_handle *handle); + #endif /* _ION_PRIV_H */ -- cgit v0.10.2 From 7398a66f10fc81403009120760b129f1e4ec7e52 Mon Sep 17 00:00:00 2001 From: Axel Haslam <ahaslam@baylibre.com> Date: Thu, 8 Sep 2016 18:48:43 +0200 Subject: greybus: gbphy: fix compile error with CONFIG_PM_RUNTIME disabled gb_phy runtime functions use struct gbphy_device *gbphy_dev, and not struct device. When CONFIG_PM_RUNTIME is not enabled a compile error will show. Fix this by passing struct gbphy_device * as parameter Testing Done: compile with CONFIG_PM_RUNTIME disabled Signed-off-by: Axel Haslam <ahaslam@baylibre.com> Reviewed-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/gbphy.h b/drivers/staging/greybus/gbphy.h index 57c6f65..e251186 100644 --- a/drivers/staging/greybus/gbphy.h +++ b/drivers/staging/greybus/gbphy.h @@ -100,8 +100,8 @@ static inline void gbphy_runtime_put_noidle(struct gbphy_device *gbphy_dev) pm_runtime_put_noidle(&gbphy_dev->dev); } #else -static inline int gbphy_runtime_get_sync(struct device *dev) { return 0; } -static inline void gbphy_runtime_put_autosuspend(struct device *dev) {} +static inline int gbphy_runtime_get_sync(struct gbphy_device *gbphy_dev) { return 0; } +static inline void gbphy_runtime_put_autosuspend(struct gbphy_device *gbphy_dev) {} static inline void gbphy_runtime_get_noresume(struct gbphy_device *gbphy_dev) {} static inline void gbphy_runtime_put_noidle(struct gbphy_device *gbphy_dev) {} #endif -- cgit v0.10.2 From b49f6ab951113cd2263a9d72b420e725e1cbfcf4 Mon Sep 17 00:00:00 2001 From: Jes Sorensen <Jes.Sorensen@redhat.com> Date: Sat, 10 Sep 2016 08:21:57 -0400 Subject: staging: Remove rtl8723au driver This driver is superseded by rtl8xxxu and has been marked as scheduled for deletion since 4.6 Signed-off-by: Jes Sorensen <Jes.Sorensen@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/MAINTAINERS b/MAINTAINERS index b53c828..0c554b5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11210,13 +11210,6 @@ M: Florian Schilhabel <florian.c.schilhabel@googlemail.com>. S: Odd Fixes F: drivers/staging/rtl8712/ -STAGING - REALTEK RTL8723U WIRELESS DRIVER -M: Larry Finger <Larry.Finger@lwfinger.net> -M: Jes Sorensen <Jes.Sorensen@redhat.com> -L: linux-wireless@vger.kernel.org -S: Maintained -F: drivers/staging/rtl8723au/ - STAGING - SILICON MOTION SM750 FRAME BUFFER DRIVER M: Sudip Mukherjee <sudipm.mukherjee@gmail.com> M: Teddy Wang <teddy.wang@siliconmotion.com> diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index af94764..5ebaf00 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -40,8 +40,6 @@ source "drivers/staging/rtl8712/Kconfig" source "drivers/staging/rtl8188eu/Kconfig" -source "drivers/staging/rtl8723au/Kconfig" - source "drivers/staging/rts5208/Kconfig" source "drivers/staging/octeon/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 9f6009d..29a1672 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -9,7 +9,6 @@ obj-$(CONFIG_RTL8192U) += rtl8192u/ obj-$(CONFIG_RTL8192E) += rtl8192e/ obj-$(CONFIG_R8712U) += rtl8712/ obj-$(CONFIG_R8188EU) += rtl8188eu/ -obj-$(CONFIG_R8723AU) += rtl8723au/ obj-$(CONFIG_RTS5208) += rts5208/ obj-$(CONFIG_NETLOGIC_XLR_NET) += netlogic/ obj-$(CONFIG_OCTEON_ETHERNET) += octeon/ diff --git a/drivers/staging/rtl8723au/Kconfig b/drivers/staging/rtl8723au/Kconfig deleted file mode 100644 index 277c1ab..0000000 --- a/drivers/staging/rtl8723au/Kconfig +++ /dev/null @@ -1,33 +0,0 @@ -config R8723AU - tristate "Realtek RTL8723AU Wireless LAN NIC driver (deprecated)" - depends on USB && WLAN && RFKILL - select WIRELESS_EXT - select WEXT_PRIV - select CFG80211 - default n - ---help--- - This option adds the Realtek RTL8723AU USB device such as found in - the Lenovo Yoga 13 tablet. If built as a module, it will be called r8723au. - - Note: This driver is deprecated and scheduled to be removed in a - future kernel release. Please use rtl8xxxu instead. - -if R8723AU - -config 8723AU_AP_MODE - bool "Realtek RTL8723AU AP mode" - default y - ---help--- - This option enables Access Point mode. Unless you know that your system - will never be used as an AP, or the target system has limited memory, - "Y" should be selected. - -config 8723AU_BT_COEXIST - bool "Realtek RTL8723AU BlueTooth Coexistence" - default y - ---help--- - This option enables icoexistence with BlueTooth communications for the r8723au driver. - Unless you know that this driver will never by used with BT, or the target system has - limited memory, "Y" should be selected. - -endif diff --git a/drivers/staging/rtl8723au/Makefile b/drivers/staging/rtl8723au/Makefile deleted file mode 100644 index 3e89890..0000000 --- a/drivers/staging/rtl8723au/Makefile +++ /dev/null @@ -1,53 +0,0 @@ -r8723au-y := \ - core/rtw_cmd.o \ - core/rtw_efuse.o \ - core/rtw_ieee80211.o \ - core/rtw_mlme.o \ - core/rtw_mlme_ext.o \ - core/rtw_pwrctrl.o \ - core/rtw_recv.o \ - core/rtw_security.o \ - core/rtw_sreset.o \ - core/rtw_sta_mgt.o \ - core/rtw_xmit.o \ - core/rtw_wlan_util.o \ - hal/hal_com.o \ - hal/hal_intf.o \ - hal/Hal8723PwrSeq.o \ - hal/Hal8723UHWImg_CE.o \ - hal/HalDMOutSrc8723A_CE.o \ - hal/HalHWImg8723A_BB.o \ - hal/HalHWImg8723A_MAC.o \ - hal/HalHWImg8723A_RF.o \ - hal/HalPwrSeqCmd.o \ - hal/odm_RegConfig8723A.o \ - hal/odm_debug.o \ - hal/odm_interface.o \ - hal/odm_HWConfig.o \ - hal/odm.o \ - hal/rtl8723a_cmd.o \ - hal/rtl8723a_dm.o \ - hal/rtl8723a_hal_init.o \ - hal/rtl8723a_phycfg.o \ - hal/rtl8723a_rf6052.o \ - hal/rtl8723a_rxdesc.o \ - hal/rtl8723a_sreset.o \ - hal/rtl8723au_recv.o \ - hal/rtl8723au_xmit.o \ - hal/usb_halinit.o \ - hal/usb_ops_linux.o \ - os_dep/ioctl_cfg80211.o \ - os_dep/mlme_linux.o \ - os_dep/os_intfs.o \ - os_dep/recv_linux.o \ - os_dep/usb_intf.o \ - os_dep/usb_ops_linux.o \ - os_dep/xmit_linux.o - -r8723au-$(CONFIG_8723AU_BT_COEXIST) += hal/rtl8723a_bt-coexist.o -r8723au-$(CONFIG_8723AU_AP_MODE) += core/rtw_ap.o - -obj-$(CONFIG_R8723AU) := r8723au.o - -ccflags-y += $(call cc-option,-Wtype-limits,) -ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/include diff --git a/drivers/staging/rtl8723au/TODO b/drivers/staging/rtl8723au/TODO deleted file mode 100644 index 42b86e4..0000000 --- a/drivers/staging/rtl8723au/TODO +++ /dev/null @@ -1,16 +0,0 @@ -TODO: -- find and remove code valid only for 5 HGz. Many 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 -- checkpatch.pl fixes - most of the remaining ones are lines too long. Many - of them will require refactoring -- merge Realtek's bugfixes and new features into the driver -- switch to use MAC80211 - -A mac80211 driver for this hardware already was integrated at -drivers/net/wireless/realtek/rtl8xxxu/ - -Please send any patches to Greg Kroah-Hartman <gregkh@linuxfoundation.org>, -Jes Sorensen <Jes.Sorensen@redhat.com>, and Larry Finger <Larry.Finger@lwfinger.net>. diff --git a/drivers/staging/rtl8723au/core/rtw_ap.c b/drivers/staging/rtl8723au/core/rtw_ap.c deleted file mode 100644 index aad686d..0000000 --- a/drivers/staging/rtl8723au/core/rtw_ap.c +++ /dev/null @@ -1,1738 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RTW_AP_C_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <linux/ieee80211.h> -#include <wifi.h> -#include <rtl8723a_cmd.h> -#include <rtl8723a_hal.h> -#include <asm/unaligned.h> -#include <rtw_mlme_ext.h> - -void init_mlme_ap_info23a(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct sta_priv *pstapriv = &padapter->stapriv; - struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; - - spin_lock_init(&pmlmepriv->bcn_update_lock); - - /* for ACL */ - _rtw_init_queue23a(&pacl_list->acl_node_q); - - start_ap_mode23a(padapter); -} - -void free_mlme_ap_info23a(struct rtw_adapter *padapter) -{ - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - pmlmepriv->update_bcn = false; - pmlmeext->bstart_bss = false; - - rtw_sta_flush23a(padapter); - - pmlmeinfo->state = MSR_NOLINK; - - /* free_assoc_sta_resources */ - rtw_free_all_stainfo23a(padapter); - - /* free bc/mc sta_info */ - psta = rtw_get_bcmc_stainfo23a(padapter); - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo23a(padapter, psta); - spin_unlock_bh(&pstapriv->sta_hash_lock); -} - -static void update_BCNTIM(struct rtw_adapter *padapter) -{ - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork_mlmeext = &pmlmeinfo->network; - unsigned char *pie = pnetwork_mlmeext->IEs; - u8 *p, *dst_ie, *premainder_ie = NULL, *pbackup_remainder_ie = NULL; - uint offset, tmp_len, tim_ielen, tim_ie_offset, remainder_ielen; - - p = rtw_get_ie23a(pie, WLAN_EID_TIM, &tim_ielen, - pnetwork_mlmeext->IELength); - if (p != NULL && tim_ielen > 0) { - tim_ielen += 2; - - premainder_ie = p+tim_ielen; - - tim_ie_offset = (int)(p - pie); - - remainder_ielen = pnetwork_mlmeext->IELength - tim_ie_offset - tim_ielen; - - /* append TIM IE from dst_ie offset */ - dst_ie = p; - } else { - tim_ielen = 0; - - /* calculate head_len */ - offset = 0; - - /* get ssid_ie len */ - p = rtw_get_ie23a(pie, WLAN_EID_SSID, - &tmp_len, pnetwork_mlmeext->IELength); - if (p != NULL) - offset += tmp_len+2; - - /* get supported rates len */ - p = rtw_get_ie23a(pie, WLAN_EID_SUPP_RATES, - &tmp_len, pnetwork_mlmeext->IELength); - if (p != NULL) - offset += tmp_len+2; - - /* DS Parameter Set IE, len = 3 */ - offset += 3; - - premainder_ie = pie + offset; - - remainder_ielen = pnetwork_mlmeext->IELength - offset - tim_ielen; - - /* append TIM IE from offset */ - dst_ie = pie + offset; - } - - if (remainder_ielen > 0) { - pbackup_remainder_ie = kmalloc(remainder_ielen, GFP_ATOMIC); - if (pbackup_remainder_ie && premainder_ie) - memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen); - } - - *dst_ie++ = WLAN_EID_TIM; - - if ((pstapriv->tim_bitmap&0xff00) && (pstapriv->tim_bitmap&0x00fc)) - tim_ielen = 5; - else - tim_ielen = 4; - - *dst_ie++ = tim_ielen; - - *dst_ie++ = 0; /* DTIM count */ - *dst_ie++ = 1; /* DTIM period */ - - if (pstapriv->tim_bitmap & BIT(0)) /* for bc/mc frames */ - *dst_ie++ = BIT(0); /* bitmap ctrl */ - else - *dst_ie++ = 0; - - if (tim_ielen == 4) { - *dst_ie++ = pstapriv->tim_bitmap & 0xff; - } else if (tim_ielen == 5) { - put_unaligned_le16(pstapriv->tim_bitmap, dst_ie); - dst_ie += 2; - } - - /* copy remainder IE */ - if (pbackup_remainder_ie) { - memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen); - - kfree(pbackup_remainder_ie); - } - - offset = (uint)(dst_ie - pie); - pnetwork_mlmeext->IELength = offset + remainder_ielen; - - set_tx_beacon_cmd23a(padapter); -} - -static u8 chk_sta_is_alive(struct sta_info *psta) -{ - u8 ret = false; - - if ((psta->sta_stats.last_rx_data_pkts + - psta->sta_stats.last_rx_ctrl_pkts) != - (psta->sta_stats.rx_data_pkts + psta->sta_stats.rx_ctrl_pkts)) - ret = true; - - sta_update_last_rx_pkts(psta); - - return ret; -} - -void expire_timeout_chk23a(struct rtw_adapter *padapter) -{ - struct list_head *phead; - u8 updated = 0; - struct sta_info *psta, *ptmp; - struct sta_priv *pstapriv = &padapter->stapriv; - u8 chk_alive_num = 0; - struct sta_info *chk_alive_list[NUM_STA]; - int i; - - spin_lock_bh(&pstapriv->auth_list_lock); - phead = &pstapriv->auth_list; - /* check auth_queue */ - list_for_each_entry_safe(psta, ptmp, 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_8723A("auth expire %pM\n", psta->hwaddr); - - spin_unlock_bh(&pstapriv->auth_list_lock); - - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo23a(padapter, psta); - spin_unlock_bh(&pstapriv->sta_hash_lock); - - spin_lock_bh(&pstapriv->auth_list_lock); - } - } - } - spin_unlock_bh(&pstapriv->auth_list_lock); - - spin_lock_bh(&pstapriv->asoc_list_lock); - phead = &pstapriv->asoc_list; - /* check asoc_queue */ - list_for_each_entry_safe(psta, ptmp, phead, asoc_list) { - if (chk_sta_is_alive(psta) || !psta->expire_to) { - psta->expire_to = pstapriv->expire_to; - psta->keep_alive_trycnt = 0; - } else { - psta->expire_to--; - } - - if (psta->expire_to <= 0) { - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (padapter->registrypriv.wifi_spec == 1) { - psta->expire_to = pstapriv->expire_to; - continue; - } - - if (psta->state & WIFI_SLEEP_STATE) { - if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) { - /* - * check if alive by another method - * if station is at ps mode. - */ - psta->expire_to = pstapriv->expire_to; - psta->state |= WIFI_STA_ALIVE_CHK_STATE; - /* - * update bcn with tim_bitmap - * for this station - */ - pstapriv->tim_bitmap |= CHKBIT(psta->aid); - update_beacon23a(padapter, WLAN_EID_TIM, NULL, false); - - if (!pmlmeext->active_keep_alive_check) - continue; - } - } - - if (pmlmeext->active_keep_alive_check) { - chk_alive_list[chk_alive_num++] = psta; - continue; - } - - list_del_init(&psta->asoc_list); - pstapriv->asoc_list_cnt--; - - DBG_8723A("asoc expire %pM, state = 0x%x\n", - psta->hwaddr, psta->state); - updated = ap_free_sta23a(padapter, psta, false, 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_8723A("%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); - wakeup_sta_to_xmit23a(padapter, psta); - } - } - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - if (chk_alive_num) { - - u8 backup_oper_channel = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - /* - * switch to correct channel of current - * network before issue keep-alive frames - */ - if (rtw_get_oper_ch23a(padapter) != pmlmeext->cur_channel) { - backup_oper_channel = rtw_get_oper_ch23a(padapter); - SelectChannel23a(padapter, pmlmeext->cur_channel); - } - - /* issue null data to check sta alive */ - for (i = 0; i < chk_alive_num; i++) { - - int ret = _FAIL; - - psta = chk_alive_list[i]; - if (!(psta->state & _FW_LINKED)) - continue; - - if (psta->state & WIFI_SLEEP_STATE) - ret = issue_nulldata23a(padapter, psta->hwaddr, 0, 1, 50); - else - ret = issue_nulldata23a(padapter, psta->hwaddr, 0, 3, 50); - - psta->keep_alive_trycnt++; - if (ret == _SUCCESS) { - DBG_8723A("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_8723A("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_8723A("asoc expire %pM, state = 0x%x\n", - psta->hwaddr, psta->state); - spin_lock_bh(&pstapriv->asoc_list_lock); - if (!list_empty(&psta->asoc_list)) { - list_del_init(&psta->asoc_list); - pstapriv->asoc_list_cnt--; - updated = ap_free_sta23a(padapter, psta, false, WLAN_REASON_DEAUTH_LEAVING); - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - } - - if (backup_oper_channel > 0) /* back to original operation channel */ - SelectChannel23a(padapter, backup_oper_channel); -} - - associated_clients_update23a(padapter, updated); -} - -void add_RATid23a(struct rtw_adapter *padapter, struct sta_info *psta, u8 rssi_level) -{ - int i; - u8 rf_type; - u32 init_rate = 0; - unsigned char sta_band = 0, raid, shortGIrate = false; - unsigned char limit; - unsigned int tx_ra_bitmap = 0; - struct ht_priv *psta_ht = NULL; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *pcur_network = &pmlmepriv->cur_network.network; - - if (psta) - psta_ht = &psta->htpriv; - else - return; - - if (!(psta->state & _FW_LINKED)) - return; - - /* b/g mode ra_bitmap */ - for (i = 0; i < sizeof(psta->bssrateset); i++) { - if (psta->bssrateset[i]) - tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value23a(psta->bssrateset[i]&0x7f); - } - /* n mode ra_bitmap */ - if (psta_ht->ht_option) { - rf_type = rtl8723a_get_rf_type(padapter); - - if (rf_type == RF_2T2R) - limit = 16; /* 2R */ - else - limit = 8; /* 1R */ - - for (i = 0; i < limit; i++) { - if (psta_ht->ht_cap.mcs.rx_mask[i / 8] & BIT(i % 8)) - tx_ra_bitmap |= BIT(i + 12); - } - - /* max short GI rate */ - shortGIrate = psta_ht->sgi; - } - - if (pcur_network->DSConfig > 14) { - /* 5G band */ - if (tx_ra_bitmap & 0xffff000) - sta_band |= WIRELESS_11_5N | WIRELESS_11A; - else - sta_band |= WIRELESS_11A; - } else { - if (tx_ra_bitmap & 0xffff000) - sta_band |= WIRELESS_11_24N | WIRELESS_11G | WIRELESS_11B; - else if (tx_ra_bitmap & 0xff0) - sta_band |= WIRELESS_11G | WIRELESS_11B; - else - sta_band |= WIRELESS_11B; - } - - psta->wireless_mode = sta_band; - - raid = networktype_to_raid23a(sta_band); - init_rate = get_highest_rate_idx23a(tx_ra_bitmap&0x0fffffff)&0x3f; - - if (psta->aid < NUM_STA) { - u8 arg; - - arg = psta->mac_id&0x1f; - - arg |= BIT(7); /* support entry 2~31 */ - - if (shortGIrate == true) - arg |= BIT(5); - - tx_ra_bitmap |= ((raid<<28)&0xf0000000); - - DBG_8723A("%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 */ - /* arg[5] = Short GI */ - rtl8723a_add_rateatid(padapter, tx_ra_bitmap, arg, rssi_level); - - if (shortGIrate == true) - init_rate |= BIT(6); - - /* set ra_id, init_rate */ - psta->raid = raid; - psta->init_rate = init_rate; - - } else - DBG_8723A("station aid %d exceed the max number\n", psta->aid); -} - -static void update_bmc_sta(struct rtw_adapter *padapter) -{ - u32 init_rate = 0; - unsigned char network_type, raid; - int i, supportRateNum = 0; - unsigned int tx_ra_bitmap = 0; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *pcur_network = &pmlmepriv->cur_network.network; - struct sta_info *psta = rtw_get_bcmc_stainfo23a(padapter); - - if (psta) { - psta->aid = 0; /* default set to 0 */ - psta->mac_id = psta->aid + 1; - - psta->qos_option = 0; - psta->htpriv.ht_option = false; - - psta->ieee8021x_blocked = 0; - - memset((void *)&psta->sta_stats, 0, - sizeof(struct stainfo_stats)); - - /* prepare for add_RATid23a */ - supportRateNum = rtw_get_rateset_len23a((u8 *)&pcur_network->SupportedRates); - network_type = rtw_check_network_type23a((u8 *)&pcur_network->SupportedRates, supportRateNum, 1); - - memcpy(psta->bssrateset, &pcur_network->SupportedRates, supportRateNum); - psta->bssratelen = supportRateNum; - - /* b/g mode ra_bitmap */ - for (i = 0; i < supportRateNum; i++) { - if (psta->bssrateset[i]) - tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value23a(psta->bssrateset[i]&0x7f); - } - - if (pcur_network->DSConfig > 14) { - /* force to A mode. 5G doesn't support CCK rates */ - network_type = WIRELESS_11A; - tx_ra_bitmap = 0x150; /* 6, 12, 24 Mbps */ - } else { - /* force to b mode */ - network_type = WIRELESS_11B; - tx_ra_bitmap = 0xf; - } - - raid = networktype_to_raid23a(network_type); - init_rate = get_highest_rate_idx23a(tx_ra_bitmap&0x0fffffff)&0x3f; - - /* ap mode */ - rtl8723a_SetHalODMVar(padapter, HAL_ODM_STA_INFO, psta, true); - - { - u8 arg; - - arg = psta->mac_id&0x1f; - - arg |= BIT(7); - - tx_ra_bitmap |= ((raid<<28)&0xf0000000); - - DBG_8723A("update_bmc_sta, mask = 0x%x, arg = 0x%x\n", tx_ra_bitmap, arg); - - /* bitmap[0:27] = tx_rate_bitmap */ - /* bitmap[28:31]= Rate Adaptive id */ - /* arg[0:4] = macid */ - /* arg[5] = Short GI */ - rtl8723a_add_rateatid(padapter, tx_ra_bitmap, arg, 0); - } - - /* set ra_id, init_rate */ - psta->raid = raid; - psta->init_rate = init_rate; - - spin_lock_bh(&psta->lock); - psta->state = _FW_LINKED; - spin_unlock_bh(&psta->lock); - - } else - DBG_8723A("add_RATid23a_bmc_sta error!\n"); -} - -/* - * AID: 1~MAX for sta and 0 for bc/mc in ap/adhoc mode - * MAC_ID = AID+1 for sta in ap/adhoc mode - * MAC_ID = 1 for bc/mc for sta/ap/adhoc - * MAC_ID = 0 for bssid for sta/ap/adhoc - * CAM_ID = 0~3 for default key, cmd_id = macid + 3, macid = aid + 1; - */ -void update_sta_info23a_apmode23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv; - struct ht_priv *phtpriv_sta = &psta->htpriv; - /* set intf_tag to if1 */ - - psta->mac_id = psta->aid+1; - DBG_8723A("%s\n", __func__); - - /* ap mode */ - rtl8723a_SetHalODMVar(padapter, HAL_ODM_STA_INFO, psta, true); - - if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) - psta->ieee8021x_blocked = true; - else - psta->ieee8021x_blocked = false; - - /* update sta's cap */ - - /* ERP */ - VCS_update23a(padapter, psta); - /* HT related cap */ - if (phtpriv_sta->ht_option) { - /* check if sta supports rx ampdu */ - phtpriv_sta->ampdu_enable = phtpriv_ap->ampdu_enable; - - /* check if sta support s Short GI */ - if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20|IEEE80211_HT_CAP_SGI_40)) - phtpriv_sta->sgi = true; - - /* bwmode */ - if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40)) { - /* phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_40; */ - phtpriv_sta->bwmode = pmlmeext->cur_bwmode; - phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset; - - } - - psta->qos_option = true; - - } else { - phtpriv_sta->ampdu_enable = false; - - phtpriv_sta->sgi = false; - phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_20; - phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - } - - /* Rx AMPDU */ - send_delba23a(padapter, 0, psta->hwaddr); /* recipient */ - - /* TX AMPDU */ - send_delba23a(padapter, 1, psta->hwaddr); /* originator */ - phtpriv_sta->agg_enable_bitmap = 0x0;/* reset */ - phtpriv_sta->candidate_tid_bitmap = 0x0;/* reset */ - - /* todo: init other variables */ - - memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats)); - - spin_lock_bh(&psta->lock); - psta->state |= _FW_LINKED; - spin_unlock_bh(&psta->lock); -} - -static void update_hw_ht_param(struct rtw_adapter *padapter) -{ - unsigned char max_AMPDU_len; - unsigned char min_MPDU_spacing; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - DBG_8723A("%s\n", __func__); - /* - * handle A-MPDU parameter field - * AMPDU_para [1:0]:Max AMPDU Len => 0:8k, 1:16k, 2:32k, 3:64k - * AMPDU_para [4:2]:Min MPDU Start Spacing - */ - max_AMPDU_len = pmlmeinfo->ht_cap.ampdu_params_info & - IEEE80211_HT_AMPDU_PARM_FACTOR; - - min_MPDU_spacing = (pmlmeinfo->ht_cap.ampdu_params_info & - IEEE80211_HT_AMPDU_PARM_DENSITY) >> 2; - - rtl8723a_set_ampdu_min_space(padapter, min_MPDU_spacing); - rtl8723a_set_ampdu_factor(padapter, max_AMPDU_len); - - /* Config SM Power Save setting */ - pmlmeinfo->SM_PS = (le16_to_cpu(pmlmeinfo->ht_cap.cap_info) & - IEEE80211_HT_CAP_SM_PS) >> 2; - if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC) - DBG_8723A("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__); -} - -static void start_bss_network(struct rtw_adapter *padapter, u8 *pbuf) -{ - const u8 *p; - u8 val8, cur_channel, cur_bwmode, cur_ch_offset; - u16 bcn_interval; - u32 acparm; - struct registry_priv *pregpriv = &padapter->registrypriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct wlan_bssid_ex *pnetwork = &pmlmepriv->cur_network.network; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork_mlmeext = &pmlmeinfo->network; - struct ieee80211_ht_operation *pht_info = NULL; - - bcn_interval = (u16)pnetwork->beacon_interval; - cur_channel = pnetwork->DSConfig; - cur_bwmode = HT_CHANNEL_WIDTH_20; - cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - - /* - * check if there is wps ie - * if there is wpsie in beacon the hostapd will - * update beacon twice when stating hostapd - * and at first time the security - * ie (RSN/WPA IE) will not include in beacon - */ - if (!cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPS, - pnetwork->IEs, - pnetwork->IELength)) - pmlmeext->bstart_bss = true; - - /* todo: update wmm, ht cap */ - /* pmlmeinfo->WMM_enable; */ - /* pmlmeinfo->HT_enable; */ - if (pmlmepriv->qos_option) - pmlmeinfo->WMM_enable = true; - if (pmlmepriv->htpriv.ht_option) { - pmlmeinfo->WMM_enable = true; - pmlmeinfo->HT_enable = true; - - update_hw_ht_param(padapter); - } - - if (pmlmepriv->cur_network.join_res != true) { - /* - * setting only at first time - * WEP Key will be set before this - * function, do not clear CAM. - */ - if (psecuritypriv->dot11PrivacyAlgrthm != - WLAN_CIPHER_SUITE_WEP40 && - psecuritypriv->dot11PrivacyAlgrthm != - WLAN_CIPHER_SUITE_WEP104) - flush_all_cam_entry23a(padapter); /* clear CAM */ - } - - /* set MSR to AP_Mode */ - rtl8723a_set_media_status(padapter, MSR_AP); - - /* Set BSSID REG */ - hw_var_set_bssid(padapter, pnetwork->MacAddress); - - /* Set EDCA param reg */ - acparm = 0x002F3217; /* VO */ - rtl8723a_set_ac_param_vo(padapter, acparm); - acparm = 0x005E4317; /* VI */ - rtl8723a_set_ac_param_vi(padapter, acparm); - acparm = 0x005ea42b; - rtl8723a_set_ac_param_be(padapter, acparm); - acparm = 0x0000A444; /* BK */ - rtl8723a_set_ac_param_bk(padapter, acparm); - - /* Set Security */ - val8 = (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) ? - 0xcc : 0xcf; - rtl8723a_set_sec_cfg(padapter, val8); - - /* Beacon Control related register */ - rtl8723a_set_beacon_interval(padapter, bcn_interval); - - UpdateBrateTbl23a(padapter, pnetwork->SupportedRates); - HalSetBrateCfg23a(padapter, pnetwork->SupportedRates); - - if (!pmlmepriv->cur_network.join_res) { - /* setting only at first time */ - - /* disable dynamic functions, such as high power, DIG */ - - /* turn on all dynamic functions */ - rtl8723a_odm_support_ability_set(padapter, - DYNAMIC_ALL_FUNC_ENABLE); - } - /* set channel, bwmode */ - - p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, pnetwork->IEs, - pnetwork->IELength); - if (p && p[1]) { - pht_info = (struct ieee80211_ht_operation *)(p + 2); - - if (pregpriv->cbw40_enable && pht_info->ht_param & - IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) { - /* switch to the 40M Hz mode */ - cur_bwmode = HT_CHANNEL_WIDTH_40; - switch (pht_info->ht_param & - IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { - case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: - /* - * pmlmeext->cur_ch_offset = - * HAL_PRIME_CHNL_OFFSET_LOWER; - */ - cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER; - break; - case IEEE80211_HT_PARAM_CHA_SEC_BELOW: - cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER; - break; - default: - cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - break; - } - } - } - /* - * TODO: need to judge the phy parameters - * on concurrent mode for single phy - */ - set_channel_bwmode23a(padapter, cur_channel, cur_ch_offset, cur_bwmode); - - DBG_8723A("CH =%d, BW =%d, offset =%d\n", cur_channel, cur_bwmode, - cur_ch_offset); - - pmlmeext->cur_channel = cur_channel; - pmlmeext->cur_bwmode = cur_bwmode; - pmlmeext->cur_ch_offset = cur_ch_offset; - pmlmeext->cur_wireless_mode = pmlmepriv->cur_network.network_type; - - /* update cur_wireless_mode */ - update_wireless_mode23a(padapter); - - /* update capability after cur_wireless_mode updated */ - update_capinfo23a(padapter, pnetwork->capability); - - /* let pnetwork_mlmeext == pnetwork_mlme. */ - memcpy(pnetwork_mlmeext, pnetwork, pnetwork->Length); - - if (pmlmeext->bstart_bss) { - update_beacon23a(padapter, WLAN_EID_TIM, NULL, false); - - /* issue beacon frame */ - if (send_beacon23a(padapter) == _FAIL) - DBG_8723A("issue_beacon23a, fail!\n"); - } - - /* update bc/mc sta_info */ - update_bmc_sta(padapter); -} - -int rtw_check_beacon_data23a(struct rtw_adapter *padapter, - struct ieee80211_mgmt *mgmt, unsigned int len) -{ - int ret = _SUCCESS; - u8 *p; - u8 *pHT_caps_ie = NULL; - u8 *pHT_info_ie = NULL; - struct sta_info *psta = NULL; - u16 ht_cap = false; - uint ie_len = 0; - int group_cipher, pairwise_cipher; - u8 channel, network_type, supportRate[NDIS_802_11_LENGTH_RATES_EX]; - int supportRateNum = 0; - u8 WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *pbss_network = &pmlmepriv->cur_network.network; - u8 *ie = pbss_network->IEs; - u8 *pbuf = mgmt->u.beacon.variable; - - len -= offsetof(struct ieee80211_mgmt, u.beacon.variable); - /* SSID */ - /* Supported rates */ - /* DS Params */ - /* WLAN_EID_COUNTRY */ - /* ERP Information element */ - /* Extended supported rates */ - /* WPA/WPA2 */ - /* Wi-Fi Wireless Multimedia Extensions */ - /* ht_capab, ht_oper */ - /* WPS IE */ - - DBG_8723A("%s, len =%d\n", __func__, len); - - if (!check_fwstate(pmlmepriv, WIFI_AP_STATE)) - return _FAIL; - - if (len > MAX_IE_SZ) - return _FAIL; - - pbss_network->IELength = len; - - memset(ie, 0, MAX_IE_SZ); - - memcpy(ie, pbuf, pbss_network->IELength); - - if (pbss_network->ifmode != NL80211_IFTYPE_AP && - pbss_network->ifmode != NL80211_IFTYPE_P2P_GO) - return _FAIL; - - pbss_network->Rssi = 0; - - memcpy(pbss_network->MacAddress, myid(&padapter->eeprompriv), ETH_ALEN); - - /* SSID */ - p = rtw_get_ie23a(ie, WLAN_EID_SSID, &ie_len, pbss_network->IELength); - if (p && ie_len > 0) { - memset(&pbss_network->Ssid, 0, sizeof(struct cfg80211_ssid)); - memcpy(pbss_network->Ssid.ssid, (p + 2), ie_len); - pbss_network->Ssid.ssid_len = ie_len; - } - - /* channel */ - channel = 0; - p = rtw_get_ie23a(ie, WLAN_EID_DS_PARAMS, &ie_len, - pbss_network->IELength); - if (p && ie_len > 0) - channel = *(p + 2); - - pbss_network->DSConfig = channel; - - memset(supportRate, 0, NDIS_802_11_LENGTH_RATES_EX); - /* get supported rates */ - p = rtw_get_ie23a(ie, WLAN_EID_SUPP_RATES, &ie_len, - pbss_network->IELength); - if (p) { - memcpy(supportRate, p+2, ie_len); - supportRateNum = ie_len; - } - - /* get ext_supported rates */ - p = rtw_get_ie23a(ie, WLAN_EID_EXT_SUPP_RATES, - &ie_len, pbss_network->IELength); - if (p) { - memcpy(supportRate+supportRateNum, p+2, ie_len); - supportRateNum += ie_len; - } - - network_type = rtw_check_network_type23a(supportRate, - supportRateNum, channel); - - rtw_set_supported_rate23a(pbss_network->SupportedRates, network_type); - - /* parsing ERP_IE */ - p = rtw_get_ie23a(ie, WLAN_EID_ERP_INFO, &ie_len, - pbss_network->IELength); - if (p && ie_len > 0) - ERP_IE_handler23a(padapter, p); - - /* update privacy/security */ - if (pbss_network->capability & BIT(4)) - pbss_network->Privacy = 1; - else - pbss_network->Privacy = 0; - - psecuritypriv->wpa_psk = 0; - - /* wpa2 */ - group_cipher = 0; pairwise_cipher = 0; - psecuritypriv->wpa2_group_cipher = 0; - psecuritypriv->wpa2_pairwise_cipher = 0; - p = rtw_get_ie23a(ie, WLAN_EID_RSN, &ie_len, - pbss_network->IELength); - if (p && ie_len > 0) { - if (rtw_parse_wpa2_ie23a(p, ie_len+2, &group_cipher, - &pairwise_cipher, NULL) == _SUCCESS) { - psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; - - psecuritypriv->dot8021xalg = 1; /* psk, todo:802.1x */ - psecuritypriv->wpa_psk |= BIT(1); - - psecuritypriv->wpa2_group_cipher = group_cipher; - psecuritypriv->wpa2_pairwise_cipher = pairwise_cipher; - } - } - - /* wpa */ - ie_len = 0; - group_cipher = 0; - pairwise_cipher = 0; - psecuritypriv->wpa_group_cipher = 0; - psecuritypriv->wpa_pairwise_cipher = 0; - for (p = ie; ; p += (ie_len + 2)) { - p = rtw_get_ie23a(p, WLAN_EID_VENDOR_SPECIFIC, &ie_len, - pbss_network->IELength - (ie_len + 2)); - if ((p) && (!memcmp(p+2, RTW_WPA_OUI23A_TYPE, 4))) { - if (rtw_parse_wpa_ie23a(p, ie_len+2, &group_cipher, - &pairwise_cipher, NULL) == _SUCCESS) { - psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; - - /* psk, todo:802.1x */ - psecuritypriv->dot8021xalg = 1; - - psecuritypriv->wpa_psk |= BIT(0); - - psecuritypriv->wpa_group_cipher = group_cipher; - psecuritypriv->wpa_pairwise_cipher = pairwise_cipher; - } - break; - } - - if (!p || !ie_len) - break; - } - - /* wmm */ - ie_len = 0; - pmlmepriv->qos_option = 0; - if (pregistrypriv->wmm_enable) { - for (p = ie; ; p += (ie_len + 2)) { - p = rtw_get_ie23a(p, WLAN_EID_VENDOR_SPECIFIC, &ie_len, - (pbss_network->IELength - - (ie_len + 2))); - if ((p) && !memcmp(p+2, WMM_PARA_IE, 6)) { - pmlmepriv->qos_option = 1; - - *(p + 8) |= BIT(7);/* QoS Info:support U-APSD */ - - /* disable all ACM bits since the WMM admission - * control is not supported - */ - *(p + 10) &= ~BIT(4); /* BE */ - *(p + 14) &= ~BIT(4); /* BK */ - *(p + 18) &= ~BIT(4); /* VI */ - *(p + 22) &= ~BIT(4); /* VO */ - break; - } - if ((p == NULL) || (ie_len == 0)) - break; - } - } - /* parsing HT_CAP_IE */ - p = rtw_get_ie23a(ie, WLAN_EID_HT_CAPABILITY, &ie_len, - pbss_network->IELength); - if (p && ie_len > 0) { - u8 rf_type; - - struct ieee80211_ht_cap *pht_cap = (struct ieee80211_ht_cap *)(p+2); - - pHT_caps_ie = p; - - ht_cap = true; - network_type |= WIRELESS_11_24N; - - rf_type = rtl8723a_get_rf_type(padapter); - - if ((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) || - (psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP)) - pht_cap->ampdu_params_info |= (IEEE80211_HT_AMPDU_PARM_DENSITY & (0x07<<2)); - else - pht_cap->ampdu_params_info |= (IEEE80211_HT_AMPDU_PARM_DENSITY&0x00); - - /* set Max Rx AMPDU size to 64K */ - pht_cap->ampdu_params_info |= (IEEE80211_HT_AMPDU_PARM_FACTOR & 0x03); - - if (rf_type == RF_1T1R) { - pht_cap->mcs.rx_mask[0] = 0xff; - pht_cap->mcs.rx_mask[1] = 0x0; - } - - memcpy(&pmlmepriv->htpriv.ht_cap, p+2, ie_len); - } - - /* parsing HT_INFO_IE */ - p = rtw_get_ie23a(ie, WLAN_EID_HT_OPERATION, &ie_len, - pbss_network->IELength); - if (p && ie_len > 0) - pHT_info_ie = p; - - pmlmepriv->cur_network.network_type = network_type; - - pmlmepriv->htpriv.ht_option = false; - - /* ht_cap */ - if (pregistrypriv->ht_enable && ht_cap) { - pmlmepriv->htpriv.ht_option = true; - pmlmepriv->qos_option = 1; - - if (pregistrypriv->ampdu_enable == 1) - pmlmepriv->htpriv.ampdu_enable = true; - - HT_caps_handler23a(padapter, pHT_caps_ie); - - HT_info_handler23a(padapter, pHT_info_ie); - } - - pbss_network->Length = get_wlan_bssid_ex_sz(pbss_network); - - /* issue beacon to start bss network */ - start_bss_network(padapter, (u8 *)pbss_network); - - /* alloc sta_info for ap itself */ - psta = rtw_get_stainfo23a(&padapter->stapriv, pbss_network->MacAddress); - if (!psta) { - psta = rtw_alloc_stainfo23a(&padapter->stapriv, - pbss_network->MacAddress, - GFP_KERNEL); - if (!psta) - return _FAIL; - } - /* fix bug of flush_cam_entry at STOP AP mode */ - psta->state |= WIFI_AP_STATE; - rtw_indicate_connect23a(padapter); - - /* for check if already set beacon */ - pmlmepriv->cur_network.join_res = true; - - return ret; -} - -void rtw_set_macaddr_acl23a(struct rtw_adapter *padapter, int mode) -{ - struct sta_priv *pstapriv = &padapter->stapriv; - struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; - - DBG_8723A("%s, mode =%d\n", __func__, mode); - - pacl_list->mode = mode; -} - -static void update_bcn_erpinfo_ie(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; - unsigned char *p, *ie = pnetwork->IEs; - u32 len = 0; - - DBG_8723A("%s, ERP_enable =%d\n", __func__, pmlmeinfo->ERP_enable); - - if (!pmlmeinfo->ERP_enable) - return; - - /* parsing ERP_IE */ - p = rtw_get_ie23a(ie, WLAN_EID_ERP_INFO, &len, pnetwork->IELength); - if (p && len > 0) { - if (pmlmepriv->num_sta_non_erp == 1) - p[2] |= WLAN_ERP_NON_ERP_PRESENT | - WLAN_ERP_USE_PROTECTION; - else - p[2] &= ~(WLAN_ERP_NON_ERP_PRESENT | - WLAN_ERP_USE_PROTECTION); - - if (pmlmepriv->num_sta_no_short_preamble > 0) - p[2] |= WLAN_ERP_BARKER_PREAMBLE; - else - p[2] &= ~(WLAN_ERP_BARKER_PREAMBLE); - - ERP_IE_handler23a(padapter, p); - } -} - -static void update_bcn_wpa_ie(struct rtw_adapter *padapter) -{ - DBG_8723A("%s\n", __func__); -} - -static void update_bcn_wmm_ie(struct rtw_adapter *padapter) -{ - DBG_8723A("%s\n", __func__); -} - -static void update_bcn_wps_ie(struct rtw_adapter *padapter) -{ - DBG_8723A("%s\n", __func__); -} - -static void update_bcn_p2p_ie(struct rtw_adapter *padapter) -{ -} - -static void update_bcn_vendor_spec_ie(struct rtw_adapter *padapter, u8 *oui) -{ - DBG_8723A("%s\n", __func__); - - if (!memcmp(RTW_WPA_OUI23A_TYPE, oui, 4)) - update_bcn_wpa_ie(padapter); - else if (!memcmp(WMM_OUI23A, oui, 4)) - update_bcn_wmm_ie(padapter); - else if (!memcmp(WPS_OUI23A, oui, 4)) - update_bcn_wps_ie(padapter); - else if (!memcmp(P2P_OUI23A, oui, 4)) - update_bcn_p2p_ie(padapter); - else - DBG_8723A("unknown OUI type!\n"); -} - -void update_beacon23a(struct rtw_adapter *padapter, u8 ie_id, u8 *oui, u8 tx) -{ - struct mlme_priv *pmlmepriv; - struct mlme_ext_priv *pmlmeext; - /* struct mlme_ext_info *pmlmeinfo; */ - - /* DBG_8723A("%s\n", __func__); */ - - if (!padapter) - return; - - pmlmepriv = &padapter->mlmepriv; - pmlmeext = &padapter->mlmeextpriv; - /* pmlmeinfo = &pmlmeext->mlmext_info; */ - - if (false == pmlmeext->bstart_bss) - return; - - spin_lock_bh(&pmlmepriv->bcn_update_lock); - - switch (ie_id) { - case WLAN_EID_TIM: - update_BCNTIM(padapter); - break; - - case WLAN_EID_ERP_INFO: - update_bcn_erpinfo_ie(padapter); - break; - - case WLAN_EID_VENDOR_SPECIFIC: - update_bcn_vendor_spec_ie(padapter, oui); - break; - - default: - break; - } - - pmlmepriv->update_bcn = true; - - spin_unlock_bh(&pmlmepriv->bcn_update_lock); - - if (tx) - set_tx_beacon_cmd23a(padapter); -} - -/* - * op_mode - * Set to 0 (HT pure) under the following conditions - * - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or - * - all STAs in the BSS are 20 MHz HT in 20 MHz BSS - * Set to 1 (HT non-member protection) if there may be non-HT STAs - * in both the primary and the secondary channel - * Set to 2 if only HT STAs are associated in BSS, - * however and at least one 20 MHz HT STA is associated - * Set to 3 (HT mixed mode) when one or more non-HT STAs are associated - * (currently non-GF HT station is considered as non-HT STA also) -*/ -static int rtw_ht_operation_update(struct rtw_adapter *padapter) -{ - u16 cur_op_mode, new_op_mode; - int op_mode_changes = 0; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv; - - if (pmlmepriv->htpriv.ht_option) - return 0; - - /* if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed) */ - /* return 0; */ - - DBG_8723A("%s current operation mode = 0x%X\n", - __func__, pmlmepriv->ht_op_mode); - - if (!(pmlmepriv->ht_op_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT) - && pmlmepriv->num_sta_ht_no_gf) { - pmlmepriv->ht_op_mode |= - IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT; - op_mode_changes++; - } else if ((pmlmepriv->ht_op_mode & - IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT) && - pmlmepriv->num_sta_ht_no_gf == 0) { - pmlmepriv->ht_op_mode &= - ~IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT; - op_mode_changes++; - } - - if (!(pmlmepriv->ht_op_mode & IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT) && - (pmlmepriv->num_sta_no_ht || pmlmepriv->olbc_ht)) { - pmlmepriv->ht_op_mode |= IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT; - op_mode_changes++; - } else if ((pmlmepriv->ht_op_mode & - IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT) && - (pmlmepriv->num_sta_no_ht == 0 && !pmlmepriv->olbc_ht)) { - pmlmepriv->ht_op_mode &= - ~IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT; - op_mode_changes++; - } - - /* - * Note: currently we switch to the MIXED op mode if HT non-greenfield - * station is associated. Probably it's a theoretical case, since - * it looks like all known HT STAs support greenfield. - */ - if (pmlmepriv->num_sta_no_ht || - (pmlmepriv->ht_op_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT)) - new_op_mode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED; - else if ((le16_to_cpu(phtpriv_ap->ht_cap.cap_info) & - IEEE80211_HT_CAP_SUP_WIDTH_20_40) && - pmlmepriv->num_sta_ht_20mhz) - new_op_mode = IEEE80211_HT_OP_MODE_PROTECTION_20MHZ; - else if (pmlmepriv->olbc_ht) - new_op_mode = IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER; - else - new_op_mode = IEEE80211_HT_OP_MODE_PROTECTION_NONE; - - cur_op_mode = pmlmepriv->ht_op_mode & IEEE80211_HT_OP_MODE_PROTECTION; - if (cur_op_mode != new_op_mode) { - pmlmepriv->ht_op_mode &= ~IEEE80211_HT_OP_MODE_PROTECTION; - pmlmepriv->ht_op_mode |= new_op_mode; - op_mode_changes++; - } - - DBG_8723A("%s new operation mode = 0x%X changes =%d\n", - __func__, pmlmepriv->ht_op_mode, op_mode_changes); - - return op_mode_changes; -} - -void associated_clients_update23a(struct rtw_adapter *padapter, u8 updated) -{ - /* update associated stations cap. */ - if (updated == true) { - struct list_head *phead; - struct sta_info *psta, *ptmp; - struct sta_priv *pstapriv = &padapter->stapriv; - - spin_lock_bh(&pstapriv->asoc_list_lock); - phead = &pstapriv->asoc_list; - list_for_each_entry_safe(psta, ptmp, phead, asoc_list) - VCS_update23a(padapter, psta); - spin_unlock_bh(&pstapriv->asoc_list_lock); - } -} - -/* called > TSR LEVEL for USB or SDIO Interface */ -void bss_cap_update_on_sta_join23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - u8 beacon_updated = false; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (!(psta->flags & WLAN_STA_SHORT_PREAMBLE)) { - if (!psta->no_short_preamble_set) { - psta->no_short_preamble_set = 1; - - pmlmepriv->num_sta_no_short_preamble++; - - if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && - (pmlmepriv->num_sta_no_short_preamble == 1)) { - beacon_updated = true; - update_beacon23a(padapter, 0xFF, NULL, true); - } - - } - } else { - if (psta->no_short_preamble_set) { - psta->no_short_preamble_set = 0; - - pmlmepriv->num_sta_no_short_preamble--; - - if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && - (pmlmepriv->num_sta_no_short_preamble == 0)) { - beacon_updated = true; - update_beacon23a(padapter, 0xFF, NULL, true); - } - - } - } - - if (psta->flags & WLAN_STA_NONERP) { - if (!psta->nonerp_set) { - psta->nonerp_set = 1; - - pmlmepriv->num_sta_non_erp++; - - if (pmlmepriv->num_sta_non_erp == 1) { - beacon_updated = true; - update_beacon23a(padapter, WLAN_EID_ERP_INFO, NULL, true); - } - } - - } else { - if (psta->nonerp_set) { - psta->nonerp_set = 0; - - pmlmepriv->num_sta_non_erp--; - - if (pmlmepriv->num_sta_non_erp == 0) { - beacon_updated = true; - update_beacon23a(padapter, WLAN_EID_ERP_INFO, NULL, true); - } - } - - } - - if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)) { - if (!psta->no_short_slot_time_set) { - psta->no_short_slot_time_set = 1; - - pmlmepriv->num_sta_no_short_slot_time++; - - if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && - (pmlmepriv->num_sta_no_short_slot_time == 1)) { - beacon_updated = true; - update_beacon23a(padapter, 0xFF, NULL, true); - } - - } - } else { - if (psta->no_short_slot_time_set) { - psta->no_short_slot_time_set = 0; - - pmlmepriv->num_sta_no_short_slot_time--; - - if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && - (pmlmepriv->num_sta_no_short_slot_time == 0)) { - beacon_updated = true; - update_beacon23a(padapter, 0xFF, NULL, true); - } - } - } - - if (psta->flags & WLAN_STA_HT) { - u16 ht_capab = le16_to_cpu(psta->htpriv.ht_cap.cap_info); - - DBG_8723A("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--; - } - - if ((ht_capab & IEEE80211_HT_CAP_GRN_FLD) == 0) { - if (!psta->no_ht_gf_set) { - psta->no_ht_gf_set = 1; - pmlmepriv->num_sta_ht_no_gf++; - } - DBG_8723A("%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) { - if (!psta->ht_20mhz_set) { - psta->ht_20mhz_set = 1; - pmlmepriv->num_sta_ht_20mhz++; - } - DBG_8723A("%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_8723A("%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) { - update_beacon23a(padapter, WLAN_EID_HT_CAPABILITY, NULL, false); - update_beacon23a(padapter, WLAN_EID_HT_OPERATION, NULL, true); - } - - /* update associated stations cap. */ - associated_clients_update23a(padapter, beacon_updated); - - DBG_8723A("%s, updated =%d\n", __func__, beacon_updated); -} - -u8 bss_cap_update_on_sta_leave23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - u8 beacon_updated = false; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (!psta) - return beacon_updated; - - if (psta->no_short_preamble_set) { - psta->no_short_preamble_set = 0; - pmlmepriv->num_sta_no_short_preamble--; - if (pmlmeext->cur_wireless_mode > WIRELESS_11B - && pmlmepriv->num_sta_no_short_preamble == 0) { - beacon_updated = true; - update_beacon23a(padapter, 0xFF, NULL, true); - } - } - - if (psta->nonerp_set) { - psta->nonerp_set = 0; - pmlmepriv->num_sta_non_erp--; - if (pmlmepriv->num_sta_non_erp == 0) { - beacon_updated = true; - update_beacon23a(padapter, WLAN_EID_ERP_INFO, - NULL, true); - } - } - - if (psta->no_short_slot_time_set) { - psta->no_short_slot_time_set = 0; - pmlmepriv->num_sta_no_short_slot_time--; - if (pmlmeext->cur_wireless_mode > WIRELESS_11B - && pmlmepriv->num_sta_no_short_slot_time == 0) { - beacon_updated = true; - update_beacon23a(padapter, 0xFF, NULL, true); - } - } - - if (psta->no_ht_gf_set) { - psta->no_ht_gf_set = 0; - pmlmepriv->num_sta_ht_no_gf--; - } - - if (psta->no_ht_set) { - psta->no_ht_set = 0; - pmlmepriv->num_sta_no_ht--; - } - - if (psta->ht_20mhz_set) { - psta->ht_20mhz_set = 0; - pmlmepriv->num_sta_ht_20mhz--; - } - - if (rtw_ht_operation_update(padapter) > 0) { - update_beacon23a(padapter, WLAN_EID_HT_CAPABILITY, NULL, false); - update_beacon23a(padapter, WLAN_EID_HT_OPERATION, NULL, true); - } - - /* update associated stations cap. */ - - DBG_8723A("%s, updated =%d\n", __func__, beacon_updated); - - return beacon_updated; -} - -u8 ap_free_sta23a(struct rtw_adapter *padapter, struct sta_info *psta, bool active, u16 reason) -{ - struct sta_priv *pstapriv = &padapter->stapriv; - u8 beacon_updated = false; - - if (!psta) - return beacon_updated; - - if (active) { - /* tear down Rx AMPDU */ - send_delba23a(padapter, 0, psta->hwaddr); /* recipient */ - - /* tear down TX AMPDU */ - send_delba23a(padapter, 1, psta->hwaddr); /* originator */ - - issue_deauth23a(padapter, psta->hwaddr, reason); - } - - psta->htpriv.agg_enable_bitmap = 0x0; /* reset */ - psta->htpriv.candidate_tid_bitmap = 0x0; /* reset */ - - /* report_del_sta_event23a(padapter, psta->hwaddr, reason); */ - - /* clear cam entry / key */ - /* clear_cam_entry23a(padapter, (psta->mac_id + 3)); */ - rtw_clearstakey_cmd23a(padapter, (u8 *)psta, (u8)(psta->mac_id + 3), - true); - - spin_lock_bh(&psta->lock); - psta->state &= ~_FW_LINKED; - spin_unlock_bh(&psta->lock); - - rtw_cfg80211_indicate_sta_disassoc(padapter, psta->hwaddr, reason); - - report_del_sta_event23a(padapter, psta->hwaddr, reason); - - beacon_updated = bss_cap_update_on_sta_leave23a(padapter, psta); - - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo23a(padapter, psta); - spin_unlock_bh(&pstapriv->sta_hash_lock); - - return beacon_updated; -} - -int rtw_sta_flush23a(struct rtw_adapter *padapter) -{ - struct list_head *phead; - struct sta_info *psta, *ptmp; - 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}; - u8 chk_alive_num = 0; - struct sta_info *chk_alive_list[NUM_STA]; - int i; - - DBG_8723A("%s(%s)\n", __func__, padapter->pnetdev->name); - - if ((pmlmeinfo->state&0x03) != MSR_AP) - return 0; - - spin_lock_bh(&pstapriv->asoc_list_lock); - phead = &pstapriv->asoc_list; - list_for_each_entry_safe(psta, ptmp, phead, asoc_list) { - /* Remove sta from asoc_list */ - list_del_init(&psta->asoc_list); - pstapriv->asoc_list_cnt--; - - /* Keep sta for ap_free_sta23a() beyond this asoc_list loop */ - chk_alive_list[chk_alive_num++] = psta; - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - /* For each sta in chk_alive_list, call ap_free_sta23a */ - for (i = 0; i < chk_alive_num; i++) - ap_free_sta23a(padapter, chk_alive_list[i], true, - WLAN_REASON_DEAUTH_LEAVING); - - issue_deauth23a(padapter, bc_addr, WLAN_REASON_DEAUTH_LEAVING); - - associated_clients_update23a(padapter, true); - - return 0; -} - -/* called > TSR LEVEL for USB or SDIO Interface */ -void sta_info_update23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - int flags = psta->flags; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - /* update wmm cap. */ - if (WLAN_STA_WME&flags) - psta->qos_option = 1; - else - psta->qos_option = 0; - - if (pmlmepriv->qos_option == 0) - psta->qos_option = 0; - - /* update 802.11n ht cap. */ - if (WLAN_STA_HT&flags) { - psta->htpriv.ht_option = true; - psta->qos_option = 1; - } else { - psta->htpriv.ht_option = false; - } - - if (!pmlmepriv->htpriv.ht_option) - psta->htpriv.ht_option = false; - - update_sta_info23a_apmode23a(padapter, psta); -} - -/* called >= TSR LEVEL for USB or SDIO Interface */ -void ap_sta_info_defer_update23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - if (psta->state & _FW_LINKED) { - /* add ratid */ - add_RATid23a(padapter, psta, 0);/* DM_RATR_STA_INIT */ - } -} - -/* restore hw setting from sw data structures */ -void rtw_ap_restore_network(struct rtw_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, *ptmp; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct list_head *phead; - u8 chk_alive_num = 0; - struct sta_info *chk_alive_list[NUM_STA]; - int i; - - rtw_setopmode_cmd23a(padapter, NL80211_IFTYPE_AP); - - set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - - start_bss_network(padapter, (u8 *)&mlmepriv->cur_network.network); - - if (padapter->securitypriv.dot11PrivacyAlgrthm == - WLAN_CIPHER_SUITE_TKIP || - padapter->securitypriv.dot11PrivacyAlgrthm == - WLAN_CIPHER_SUITE_CCMP) { - /* restore group key, WEP keys is restored in ips_leave23a() */ - rtw_set_key23a(padapter, psecuritypriv, - psecuritypriv->dot118021XGrpKeyid, 0); - } - - /* per sta pairwise key and settings */ - if (padapter->securitypriv.dot11PrivacyAlgrthm != - WLAN_CIPHER_SUITE_TKIP && - padapter->securitypriv.dot11PrivacyAlgrthm != - WLAN_CIPHER_SUITE_CCMP) { - return; - } - - spin_lock_bh(&pstapriv->asoc_list_lock); - phead = &pstapriv->asoc_list; - list_for_each_entry_safe(psta, ptmp, phead, asoc_list) - chk_alive_list[chk_alive_num++] = psta; - spin_unlock_bh(&pstapriv->asoc_list_lock); - - for (i = 0; i < chk_alive_num; i++) { - psta = chk_alive_list[i]; - - if (psta->state & _FW_LINKED) { - Update_RA_Entry23a(padapter, psta); - /* pairwise key */ - rtw_setstakey_cmd23a(padapter, (unsigned char *)psta, true); - } - } -} - -void start_ap_mode23a(struct rtw_adapter *padapter) -{ - int i; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; - - pmlmepriv->update_bcn = false; - - /* init_mlme_ap_info23a(padapter); */ - pmlmeext->bstart_bss = false; - - pmlmepriv->num_sta_non_erp = 0; - - pmlmepriv->num_sta_no_short_slot_time = 0; - - pmlmepriv->num_sta_no_short_preamble = 0; - - pmlmepriv->num_sta_ht_no_gf = 0; - pmlmepriv->num_sta_no_ht = 0; - pmlmepriv->num_sta_ht_20mhz = 0; - - pmlmepriv->olbc = false; - - pmlmepriv->olbc_ht = false; - - pmlmepriv->ht_op_mode = 0; - - for (i = 0; i < NUM_STA; i++) - pstapriv->sta_aid[i] = NULL; - - /* for ACL */ - INIT_LIST_HEAD(&pacl_list->acl_node_q.queue); - pacl_list->num = 0; - pacl_list->mode = 0; - for (i = 0; i < NUM_ACL; i++) { - INIT_LIST_HEAD(&pacl_list->aclnode[i].list); - pacl_list->aclnode[i].valid = false; - } -} - -void stop_ap_mode23a(struct rtw_adapter *padapter) -{ - struct list_head *phead; - struct rtw_wlan_acl_node *paclnode, *ptmp; - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; - struct rtw_queue *pacl_node_q = &pacl_list->acl_node_q; - - pmlmepriv->update_bcn = false; - pmlmeext->bstart_bss = false; - - /* - * reset and init security priv , this can - * refine with rtw_reset_securitypriv23a - */ - memset((unsigned char *)&padapter->securitypriv, 0, sizeof(struct security_priv)); - padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen; - padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled; - - /* for ACL */ - spin_lock_bh(&pacl_node_q->lock); - phead = get_list_head(pacl_node_q); - list_for_each_entry_safe(paclnode, ptmp, phead, list) { - if (paclnode->valid == true) { - paclnode->valid = false; - list_del_init(&paclnode->list); - pacl_list->num--; - } - } - spin_unlock_bh(&pacl_node_q->lock); - - DBG_8723A("%s, free acl_node_queue, num =%d\n", - __func__, pacl_list->num); - - rtw_sta_flush23a(padapter); - - /* free_assoc_sta_resources */ - rtw_free_all_stainfo23a(padapter); - - psta = rtw_get_bcmc_stainfo23a(padapter); - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo23a(padapter, psta); - spin_unlock_bh(&pstapriv->sta_hash_lock); - - rtw_init_bcmc_stainfo23a(padapter); - - rtw23a_free_mlme_priv_ie_data(pmlmepriv); -} diff --git a/drivers/staging/rtl8723au/core/rtw_cmd.c b/drivers/staging/rtl8723au/core/rtw_cmd.c deleted file mode 100644 index cd4e0f0..0000000 --- a/drivers/staging/rtl8723au/core/rtw_cmd.c +++ /dev/null @@ -1,1470 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RTW_CMD_C_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <recv_osdep.h> -#include <mlme_osdep.h> -#include <rtl8723a_cmd.h> -#include <rtw_sreset.h> - -static struct cmd_hdl wlancmds[] = { - GEN_DRV_CMD_HANDLER(0, NULL) /*0*/ - GEN_DRV_CMD_HANDLER(0, NULL) - GEN_DRV_CMD_HANDLER(0, NULL) - GEN_DRV_CMD_HANDLER(0, NULL) - GEN_DRV_CMD_HANDLER(0, NULL) - GEN_DRV_CMD_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) /*10*/ - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct wlan_bssid_ex), join_cmd_hdl23a) /*14*/ - GEN_MLME_EXT_HANDLER(sizeof(struct disconnect_parm), disconnect_hdl23a) - GEN_MLME_EXT_HANDLER(sizeof(struct wlan_bssid_ex), createbss_hdl23a) - GEN_MLME_EXT_HANDLER(sizeof(struct setopmode_parm), setopmode_hdl23a) - GEN_MLME_EXT_HANDLER(sizeof(struct sitesurvey_parm), sitesurvey_cmd_hdl23a) /*18*/ - GEN_MLME_EXT_HANDLER(sizeof(struct setauth_parm), setauth_hdl23a) - GEN_MLME_EXT_HANDLER(sizeof(struct setkey_parm), setkey_hdl23a) /*20*/ - GEN_MLME_EXT_HANDLER(sizeof(struct set_stakey_parm), set_stakey_hdl23a) - GEN_MLME_EXT_HANDLER(sizeof(struct set_assocsta_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct del_assocsta_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct setstapwrstate_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct setbasicrate_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct getbasicrate_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct setdatarate_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct getdatarate_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct setphyinfo_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct getphyinfo_parm), NULL) /*30*/ - GEN_MLME_EXT_HANDLER(sizeof(struct setphy_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct getphy_parm), NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) /*40*/ - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct addBaReq_parm), add_ba_hdl23a) - GEN_MLME_EXT_HANDLER(sizeof(struct set_ch_parm), set_ch_hdl23a) /* 46 */ - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) /*50*/ - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct Tx_Beacon_param), tx_beacon_hdl23a) /*55*/ - - GEN_MLME_EXT_HANDLER(0, mlme_evt_hdl23a) /*56*/ - GEN_MLME_EXT_HANDLER(0, rtw_drvextra_cmd_hdl23a) /*57*/ - - GEN_MLME_EXT_HANDLER(0, h2c_msg_hdl23a) /*58*/ - GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelPlan_param), set_chplan_hdl23a) /*59*/ - GEN_MLME_EXT_HANDLER(sizeof(struct LedBlink_param), led_blink_hdl23a) /*60*/ - - GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelSwitch_param), set_csa_hdl23a) /*61*/ - GEN_MLME_EXT_HANDLER(sizeof(struct TDLSoption_param), tdls_hdl23a) /*62*/ -}; - -struct _cmd_callback rtw_cmd_callback[] = { - {GEN_CMD_CODE(_Read_MACREG), NULL}, /*0*/ - {GEN_CMD_CODE(_Write_MACREG), NULL}, - {GEN_CMD_CODE(_Read_BBREG), &rtw_getbbrfreg_cmdrsp_callback23a}, - {GEN_CMD_CODE(_Write_BBREG), NULL}, - {GEN_CMD_CODE(_Read_RFREG), &rtw_getbbrfreg_cmdrsp_callback23a}, - {GEN_CMD_CODE(_Write_RFREG), NULL}, /*5*/ - {GEN_CMD_CODE(_Read_EEPROM), NULL}, - {GEN_CMD_CODE(_Write_EEPROM), NULL}, - {GEN_CMD_CODE(_Read_EFUSE), NULL}, - {GEN_CMD_CODE(_Write_EFUSE), NULL}, - - {GEN_CMD_CODE(_Read_CAM), NULL}, /*10*/ - {GEN_CMD_CODE(_Write_CAM), NULL}, - {GEN_CMD_CODE(_setBCNITV), NULL}, - {GEN_CMD_CODE(_setMBIDCFG), NULL}, - {GEN_CMD_CODE(_JoinBss), &rtw_joinbss_cmd23a_callback}, /*14*/ - {GEN_CMD_CODE(_DisConnect), &rtw_disassoc_cmd23a_callback}, /*15*/ - {GEN_CMD_CODE(_CreateBss), &rtw_createbss_cmd23a_callback}, - {GEN_CMD_CODE(_SetOpMode), NULL}, - {GEN_CMD_CODE(_SiteSurvey), &rtw_survey_cmd_callback23a}, /*18*/ - {GEN_CMD_CODE(_SetAuth), NULL}, - - {GEN_CMD_CODE(_SetKey), NULL}, /*20*/ - {GEN_CMD_CODE(_SetStaKey), &rtw_setstaKey_cmdrsp_callback23a}, - {GEN_CMD_CODE(_SetAssocSta), &rtw_setassocsta_cmdrsp_callback23a}, - {GEN_CMD_CODE(_DelAssocSta), NULL}, - {GEN_CMD_CODE(_SetStaPwrState), NULL}, - {GEN_CMD_CODE(_SetBasicRate), NULL}, /*25*/ - {GEN_CMD_CODE(_GetBasicRate), NULL}, - {GEN_CMD_CODE(_SetDataRate), NULL}, - {GEN_CMD_CODE(_GetDataRate), NULL}, - {GEN_CMD_CODE(_SetPhyInfo), NULL}, - - {GEN_CMD_CODE(_GetPhyInfo), NULL}, /*30*/ - {GEN_CMD_CODE(_SetPhy), NULL}, - {GEN_CMD_CODE(_GetPhy), NULL}, - {GEN_CMD_CODE(_readRssi), NULL}, - {GEN_CMD_CODE(_readGain), NULL}, - {GEN_CMD_CODE(_SetAtim), NULL}, /*35*/ - {GEN_CMD_CODE(_SetPwrMode), NULL}, - {GEN_CMD_CODE(_JoinbssRpt), NULL}, - {GEN_CMD_CODE(_SetRaTable), NULL}, - {GEN_CMD_CODE(_GetRaTable), NULL}, - - {GEN_CMD_CODE(_GetCCXReport), NULL}, /*40*/ - {GEN_CMD_CODE(_GetDTMReport), NULL}, - {GEN_CMD_CODE(_GetTXRateStatistics), NULL}, - {GEN_CMD_CODE(_SetUsbSuspend), NULL}, - {GEN_CMD_CODE(_SetH2cLbk), NULL}, - {GEN_CMD_CODE(_AddBAReq), NULL}, /*45*/ - {GEN_CMD_CODE(_SetChannel), NULL}, /*46*/ - {GEN_CMD_CODE(_SetTxPower), NULL}, - {GEN_CMD_CODE(_SwitchAntenna), NULL}, - {GEN_CMD_CODE(_SetCrystalCap), NULL}, - {GEN_CMD_CODE(_SetSingleCarrierTx), NULL}, /*50*/ - - {GEN_CMD_CODE(_SetSingleToneTx), NULL}, /*51*/ - {GEN_CMD_CODE(_SetCarrierSuppressionTx), NULL}, - {GEN_CMD_CODE(_SetContinuousTx), NULL}, - {GEN_CMD_CODE(_SwitchBandwidth), NULL}, /*54*/ - {GEN_CMD_CODE(_TX_Beacon), NULL},/*55*/ - - {GEN_CMD_CODE(_Set_MLME_EVT), NULL},/*56*/ - {GEN_CMD_CODE(_Set_Drv_Extra), NULL},/*57*/ - {GEN_CMD_CODE(_Set_H2C_MSG), NULL},/*58*/ - {GEN_CMD_CODE(_SetChannelPlan), NULL},/*59*/ - {GEN_CMD_CODE(_LedBlink), NULL},/*60*/ - - {GEN_CMD_CODE(_SetChannelSwitch), NULL},/*61*/ - {GEN_CMD_CODE(_TDLS), NULL},/*62*/ -}; - -/* -Caller and the rtw_cmd_thread23a can protect cmd_q by spin_lock. -No irqsave is necessary. -*/ - -int rtw_init_cmd_priv23a(struct cmd_priv *pcmdpriv) -{ - int res = _SUCCESS; - - pcmdpriv->cmd_issued_cnt = 0; - pcmdpriv->cmd_done_cnt = 0; - pcmdpriv->rsp_cnt = 0; - - pcmdpriv->wq = alloc_workqueue("rtl8723au_cmd", 0, 1); - if (!pcmdpriv->wq) - res = _FAIL; - - return res; -} - -/* forward definition */ - -static void rtw_irq_work(struct work_struct *work); - -u32 rtw_init_evt_priv23a(struct evt_priv *pevtpriv) -{ - pevtpriv->wq = alloc_workqueue("rtl8723au_evt", 0, 1); - - INIT_WORK(&pevtpriv->irq_wk, rtw_irq_work); - - return _SUCCESS; -} - -void rtw_free_evt_priv23a(struct evt_priv *pevtpriv) -{ - cancel_work_sync(&pevtpriv->irq_wk); -} - -static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) -{ - /* set to true to allow enqueuing cmd when hw_init_completed is false */ - u8 bAllow = false; - - if (cmd_obj->cmdcode == GEN_CMD_CODE(_SetChannelPlan)) - bAllow = true; - - if (pcmdpriv->padapter->hw_init_completed == false && bAllow == false) - return _FAIL; - return _SUCCESS; -} - -static void rtw_cmd_work(struct work_struct *work); - -int rtw_enqueue_cmd23a(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) -{ - int res = _FAIL; - - if (!cmd_obj) - goto exit; - - cmd_obj->padapter = pcmdpriv->padapter; - - res = rtw_cmd_filter(pcmdpriv, cmd_obj); - if (res == _FAIL) { - rtw_free_cmd_obj23a(cmd_obj); - goto exit; - } - - INIT_WORK(&cmd_obj->work, rtw_cmd_work); - - res = queue_work(pcmdpriv->wq, &cmd_obj->work); - - if (!res) { - netdev_err(pcmdpriv->padapter->pnetdev, - "%s: Call to queue_work() failed\n", __func__); - res = _FAIL; - } else - res = _SUCCESS; -exit: - - return res; -} - -void rtw_free_cmd_obj23a(struct cmd_obj *pcmd) -{ - - if (pcmd->cmdcode != _JoinBss_CMD_ && - pcmd->cmdcode != _CreateBss_CMD_) { - /* free parmbuf in cmd_obj */ - kfree(pcmd->parmbuf); - } - - if (pcmd->rsp) { - if (pcmd->rspsz != 0) { - /* free rsp in cmd_obj */ - kfree(pcmd->rsp); - } - } - - kfree(pcmd); -} - -static void rtw_cmd_work(struct work_struct *work) -{ - int (*cmd_hdl)(struct rtw_adapter *padapter, const u8 *pbuf); - void (*pcmd_callback)(struct rtw_adapter *dev, struct cmd_obj *pcmd); - struct cmd_priv *pcmdpriv; - struct cmd_obj *pcmd = container_of(work, struct cmd_obj, work); - - pcmdpriv = &pcmd->padapter->cmdpriv; - - if (rtw_cmd_filter(pcmdpriv, pcmd) == _FAIL) { - pcmd->res = H2C_DROPPED; - goto post_process; - } - - pcmdpriv->cmd_issued_cnt++; - - pcmd->cmdsz = ALIGN(pcmd->cmdsz, 4); - - if (pcmd->cmdcode < (sizeof(wlancmds)/sizeof(struct cmd_hdl))) { - cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns; - - if (cmd_hdl) - pcmd->res = cmd_hdl(pcmd->padapter, pcmd->parmbuf); - else - pcmd->res = H2C_DROPPED; - } else - pcmd->res = H2C_PARAMETERS_ERROR; - -post_process: - /* 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); - rtw_free_cmd_obj23a(pcmd); - } else { - /* need consider that free cmd_obj in - rtw_cmd_callback */ - 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_obj23a(pcmd); - } -} - - -int rtw_sitesurvey_cmd23a(struct rtw_adapter *padapter, - struct cfg80211_ssid *ssid, int ssid_num, - struct rtw_ieee80211_channel *ch, int ch_num) -{ - int res = _FAIL; - struct cmd_obj *ph2c; - struct sitesurvey_parm *psurveyPara; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (check_fwstate(pmlmepriv, _FW_LINKED)) - rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_SCAN, 1); - - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!ph2c) - return _FAIL; - - psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), GFP_ATOMIC); - if (!psurveyPara) { - kfree(ph2c); - return _FAIL; - } - - rtw_free_network_queue23a(padapter); - - RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, - "%s: flush network queue\n", __func__); - - init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, - GEN_CMD_CODE(_SiteSurvey)); - - /* psurveyPara->bsslimit = 48; */ - psurveyPara->scan_mode = pmlmepriv->scan_mode; - - /* prepare ssid list */ - if (ssid) { - int i; - - for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) { - if (ssid[i].ssid_len) { - memcpy(&psurveyPara->ssid[i], &ssid[i], - sizeof(struct cfg80211_ssid)); - psurveyPara->ssid_num++; - } - } - } - - /* 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 & IEEE80211_CHAN_DISABLED)) { - memcpy(&psurveyPara->ch[i], &ch[i], - sizeof(struct rtw_ieee80211_channel)); - psurveyPara->ch_num++; - } - } - } - - set_fwstate(pmlmepriv, _FW_UNDER_SURVEY); - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); - - if (res == _SUCCESS) { - mod_timer(&pmlmepriv->scan_to_timer, jiffies + - msecs_to_jiffies(SCANNING_TIMEOUT)); - - pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */ - } else - _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY); - - return res; -} - -void rtw_getbbrfreg_cmdrsp_callback23a(struct rtw_adapter *padapter, - struct cmd_obj *pcmd) -{ - kfree(pcmd->parmbuf); - kfree(pcmd); -} - -int rtw_createbss_cmd23a(struct rtw_adapter *padapter) -{ - struct cmd_obj *pcmd; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *pdev_network; - u8 res = _SUCCESS; - - pdev_network = &padapter->registrypriv.dev_network; - - if (pmlmepriv->assoc_ssid.ssid_len == 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(struct cmd_obj), GFP_ATOMIC); - if (!pcmd) { - res = _FAIL; - goto exit; - } - - pcmd->cmdcode = _CreateBss_CMD_; - pcmd->parmbuf = (unsigned char *)pdev_network; - pcmd->cmdsz = get_wlan_bssid_ex_sz(pdev_network); - pcmd->rsp = NULL; - pcmd->rspsz = 0; - - pdev_network->Length = pcmd->cmdsz; - - res = rtw_enqueue_cmd23a(pcmdpriv, pcmd); - -exit: - - return res; -} - -int rtw_joinbss_cmd23a(struct rtw_adapter *padapter, - struct wlan_network *pnetwork) -{ - int res = _SUCCESS; - struct wlan_bssid_ex *psecnetwork; - struct cmd_obj *pcmd; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - enum nl80211_iftype ifmode; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - ifmode = pnetwork->network.ifmode; - - if (pmlmepriv->assoc_ssid.ssid_len == 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(struct cmd_obj), GFP_ATOMIC); - if (!pcmd) { - res = _FAIL; - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "rtw_joinbss_cmd23a: memory allocate for cmd_obj fail!!!\n"); - goto exit; - } - - /* for hidden ap to set fw_state here */ - if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE)) { - switch (ifmode) { - case NL80211_IFTYPE_ADHOC: - set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); - break; - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_STATION: - set_fwstate(pmlmepriv, WIFI_STATION_STATE); - break; - default: - break; - } - } - - psecnetwork = &psecuritypriv->sec_bss; - if (!psecnetwork) { - kfree(pcmd); - res = _FAIL; - - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "rtw_joinbss_cmd23a :psecnetwork == NULL!!!\n"); - - goto exit; - } - - memset(psecnetwork, 0, sizeof(struct wlan_bssid_ex)); - - memcpy(psecnetwork, &pnetwork->network, - get_wlan_bssid_ex_sz(&pnetwork->network)); - - psecnetwork->IELength = 0; - /* Added by Albert 2009/02/18 */ - /* If the the driver wants to use the bssid to create the - * connection. If not, we have to copy the connecting AP's - * MAC address to it so that the driver just has the bssid - * information for PMKIDList searching. */ - - if (pmlmepriv->assoc_by_bssid == false) - ether_addr_copy(&pmlmepriv->assoc_bssid[0], - &pnetwork->network.MacAddress[0]); - - psecnetwork->IELength = - rtw_restruct_sec_ie23a(padapter, &pnetwork->network.IEs[0], - &psecnetwork->IEs[0], - pnetwork->network.IELength); - - pmlmepriv->qos_option = 0; - - if (pregistrypriv->wmm_enable) { - u32 tmp_len; - - tmp_len = rtw_restruct_wmm_ie23a(padapter, - &pnetwork->network.IEs[0], - &psecnetwork->IEs[0], - pnetwork->network.IELength, - psecnetwork->IELength); - - if (psecnetwork->IELength != tmp_len) { - psecnetwork->IELength = tmp_len; - /* There is WMM IE in this corresp. beacon */ - pmlmepriv->qos_option = 1; - } else { - /* There is no WMM IE in this corresp. beacon */ - pmlmepriv->qos_option = 0; - } - } - - phtpriv->ht_option = false; - if (pregistrypriv->ht_enable) { - u32 algo = padapter->securitypriv.dot11PrivacyAlgrthm; - /* Added by Albert 2010/06/23 */ - /* For the WEP mode, we will use the bg mode to do - the connection to avoid some IOT issue. */ - /* Especially for Realtek 8192u SoftAP. */ - if (algo != WLAN_CIPHER_SUITE_WEP40 && - algo != WLAN_CIPHER_SUITE_WEP104 && - algo != WLAN_CIPHER_SUITE_TKIP) { - /* rtw_restructure_ht_ie23a */ - rtw_restructure_ht_ie23a(padapter, - &pnetwork->network.IEs[0], - &psecnetwork->IEs[0], - pnetwork->network.IELength, - &psecnetwork->IELength); - } - } - - pmlmeinfo->assoc_AP_vendor = - check_assoc_AP23a(pnetwork->network.IEs, - pnetwork->network.IELength); - - if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_TENDA) - padapter->pwrctrlpriv.smart_ps = 0; - else - padapter->pwrctrlpriv.smart_ps = - padapter->registrypriv.smart_ps; - - DBG_8723A("%s: smart_ps =%d\n", __func__, - padapter->pwrctrlpriv.smart_ps); - - /* get cmdsz before endian conversion */ - pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork); - - pcmd->cmdcode = _JoinBss_CMD_;/* GEN_CMD_CODE(_JoinBss) */ - pcmd->parmbuf = (unsigned char *)psecnetwork; - pcmd->rsp = NULL; - pcmd->rspsz = 0; - - res = rtw_enqueue_cmd23a(pcmdpriv, pcmd); -exit: - - return res; -} - -int rtw_disassoc_cmd23a(struct rtw_adapter *padapter, u32 deauth_timeout_ms, - bool enqueue) -{ - struct cmd_obj *cmdobj = NULL; - struct disconnect_parm *param = NULL; - struct cmd_priv *cmdpriv = &padapter->cmdpriv; - int res = _SUCCESS; - - RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, - "+rtw_disassoc_cmd23a\n"); - - /* prepare cmd parameter */ - param = kzalloc(sizeof(*param), GFP_ATOMIC); - if (param == NULL) { - res = _FAIL; - goto exit; - } - param->deauth_timeout_ms = deauth_timeout_ms; - - if (enqueue) { - /* need enqueue, prepare cmd_obj and enqueue */ - cmdobj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!cmdobj) { - res = _FAIL; - kfree(param); - goto exit; - } - init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_); - res = rtw_enqueue_cmd23a(cmdpriv, cmdobj); - } else { - /* no need to enqueue, do the cmd hdl directly and - free cmd parameter */ - if (disconnect_hdl23a(padapter, (u8 *)param) != H2C_SUCCESS) - res = _FAIL; - kfree(param); - } - -exit: - return res; -} - -int rtw_setopmode_cmd23a(struct rtw_adapter *padapter, - enum nl80211_iftype ifmode) -{ - struct cmd_obj *ph2c; - struct setopmode_parm *psetop; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - int res = _SUCCESS; - - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (!ph2c) { - res = false; - goto exit; - } - psetop = kzalloc(sizeof(struct setopmode_parm), GFP_KERNEL); - - if (!psetop) { - kfree(ph2c); - res = false; - goto exit; - } - - init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_); - psetop->mode = ifmode; - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); -exit: - return res; -} - -int rtw_setstakey_cmd23a(struct rtw_adapter *padapter, u8 *psta, u8 unicast_key) -{ - struct cmd_obj *ph2c; - struct set_stakey_parm *psetstakey_para; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct set_stakey_rsp *psetstakey_rsp = NULL; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct sta_info *sta = (struct sta_info *)psta; - int res = _SUCCESS; - - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL); - if (!psetstakey_para) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - psetstakey_rsp = kzalloc(sizeof(struct set_stakey_rsp), GFP_KERNEL); - if (!psetstakey_rsp) { - kfree(ph2c); - kfree(psetstakey_para); - res = _FAIL; - goto exit; - } - - init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_); - ph2c->rsp = (u8 *) psetstakey_rsp; - ph2c->rspsz = sizeof(struct set_stakey_rsp); - - ether_addr_copy(psetstakey_para->addr, sta->hwaddr); - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - psetstakey_para->algorithm = - (unsigned char)psecuritypriv->dot11PrivacyAlgrthm; - } else { - GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, - false); - } - - if (unicast_key == true) { - memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16); - } else { - int idx = psecuritypriv->dot118021XGrpKeyid; - - memcpy(&psetstakey_para->key, - &psecuritypriv->dot118021XGrpKey[idx].skey, 16); - } - - /* jeff: set this because at least sw key is ready */ - padapter->securitypriv.busetkipkey = 1; - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); - -exit: - - return res; -} - -int rtw_clearstakey_cmd23a(struct rtw_adapter *padapter, u8 *psta, u8 entry, - u8 enqueue) -{ - struct cmd_obj *ph2c; - struct set_stakey_parm *psetstakey_para; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct set_stakey_rsp *psetstakey_rsp = NULL; - struct sta_info *sta = (struct sta_info *)psta; - int res = _SUCCESS; - - if (!enqueue) { - clear_cam_entry23a(padapter, entry); - } else { - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), - GFP_KERNEL); - if (!psetstakey_para) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - psetstakey_rsp = kzalloc(sizeof(struct set_stakey_rsp), - GFP_KERNEL); - if (!psetstakey_rsp) { - kfree(ph2c); - kfree(psetstakey_para); - res = _FAIL; - goto exit; - } - - init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, - _SetStaKey_CMD_); - ph2c->rsp = (u8 *) psetstakey_rsp; - ph2c->rspsz = sizeof(struct set_stakey_rsp); - - ether_addr_copy(psetstakey_para->addr, sta->hwaddr); - - psetstakey_para->algorithm = 0; - - psetstakey_para->id = entry; - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); - } -exit: - return res; -} - -int rtw_addbareq_cmd23a(struct rtw_adapter *padapter, u8 tid, u8 *addr) -{ - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct cmd_obj *ph2c; - struct addBaReq_parm *paddbareq_parm; - int res = _SUCCESS; - - if (tid >= MAXTID) { - res = _FAIL; - goto exit; - } - - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - paddbareq_parm = kzalloc(sizeof(struct addBaReq_parm), GFP_ATOMIC); - if (!paddbareq_parm) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - paddbareq_parm->tid = tid; - ether_addr_copy(paddbareq_parm->addr, addr); - - init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, - GEN_CMD_CODE(_AddBAReq)); - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); -exit: - return res; -} - -int rtw_dynamic_chk_wk_cmd23a(struct rtw_adapter *padapter) -{ - struct cmd_obj *ph2c; - struct drvextra_cmd_parm *pdrvextra_cmd_parm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - int res = _SUCCESS; - - ph2c = kzalloc(sizeof(struct cmd_obj), 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 = DYNAMIC_CHK_WK_CID; - pdrvextra_cmd_parm->type_size = 0; - pdrvextra_cmd_parm->pbuf = (u8 *)padapter; - - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, - GEN_CMD_CODE(_Set_Drv_Extra)); - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); -exit: - - return res; -} - -static void traffic_status_watchdog(struct rtw_adapter *padapter) -{ - u8 bEnterPS; - u8 bBusyTraffic = false, bTxBusyTraffic = false, bRxBusyTraffic = false; - u8 bHigherBusyTraffic = false, bHigherBusyRxTraffic = false; - u8 bHigherBusyTxTraffic = false; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - int BusyThreshold = 100; - struct rt_link_detect *ldi = &pmlmepriv->LinkDetectInfo; - - /* */ - /* Determine if our traffic is busy now */ - /* */ - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - if (rtl8723a_BT_coexist(padapter)) - BusyThreshold = 50; - else if (ldi->bBusyTraffic) - BusyThreshold = 75; - /* if we raise bBusyTraffic in last watchdog, using - lower threshold. */ - if (ldi->NumRxOkInPeriod > BusyThreshold || - ldi->NumTxOkInPeriod > BusyThreshold) { - bBusyTraffic = true; - - if (ldi->NumRxOkInPeriod > ldi->NumTxOkInPeriod) - bRxBusyTraffic = true; - else - bTxBusyTraffic = true; - } - - /* Higher Tx/Rx data. */ - if (ldi->NumRxOkInPeriod > 4000 || - ldi->NumTxOkInPeriod > 4000) { - bHigherBusyTraffic = true; - - if (ldi->NumRxOkInPeriod > ldi->NumTxOkInPeriod) - bHigherBusyRxTraffic = true; - else - bHigherBusyTxTraffic = true; - } - - if (!rtl8723a_BT_coexist(padapter) || - !rtl8723a_BT_using_antenna_1(padapter)) { - /* check traffic for powersaving. */ - if (((ldi->NumRxUnicastOkInPeriod + - ldi->NumTxOkInPeriod) > 8) || - ldi->NumRxUnicastOkInPeriod > 2) - bEnterPS = false; - else - bEnterPS = true; - - /* LeisurePS only work in infra mode. */ - if (bEnterPS) - LPS_Enter23a(padapter); - else - LPS_Leave23a(padapter); - } - } else - LPS_Leave23a(padapter); - - ldi->NumRxOkInPeriod = 0; - ldi->NumTxOkInPeriod = 0; - ldi->NumRxUnicastOkInPeriod = 0; - ldi->bBusyTraffic = bBusyTraffic; - ldi->bTxBusyTraffic = bTxBusyTraffic; - ldi->bRxBusyTraffic = bRxBusyTraffic; - ldi->bHigherBusyTraffic = bHigherBusyTraffic; - ldi->bHigherBusyRxTraffic = bHigherBusyRxTraffic; - ldi->bHigherBusyTxTraffic = bHigherBusyTxTraffic; -} - -static void dynamic_chk_wk_hdl(struct rtw_adapter *padapter, u8 *pbuf, int sz) -{ - struct mlme_priv *pmlmepriv; - - padapter = (struct rtw_adapter *)pbuf; - pmlmepriv = &padapter->mlmepriv; - -#ifdef CONFIG_8723AU_AP_MODE - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) - expire_timeout_chk23a(padapter); -#endif - - rtl8723a_sreset_xmit_status_check(padapter); - - linked_status_chk23a(padapter); - traffic_status_watchdog(padapter); - - rtl8723a_HalDmWatchDog(padapter); - - /* */ - /* BT-Coexist */ - /* */ - rtl8723a_BT_do_coexist(padapter); -} - -static void lps_ctrl_wk_hdl(struct rtw_adapter *padapter, u8 lps_ctrl_type) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - u8 mstatus; - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) - return; - - switch (lps_ctrl_type) { - case LPS_CTRL_SCAN: - rtl8723a_BT_wifiscan_notify(padapter, true); - if (!rtl8723a_BT_using_antenna_1(padapter)) { - if (check_fwstate(pmlmepriv, _FW_LINKED)) - LPS_Leave23a(padapter); - } - break; - case LPS_CTRL_JOINBSS: - LPS_Leave23a(padapter); - break; - case LPS_CTRL_CONNECT: - mstatus = 1;/* connect */ - /* Reset LPS Setting */ - padapter->pwrctrlpriv.LpsIdleCount = 0; - rtl8723a_set_FwJoinBssReport_cmd(padapter, 1); - rtl8723a_BT_mediastatus_notify(padapter, mstatus); - break; - case LPS_CTRL_DISCONNECT: - mstatus = 0;/* disconnect */ - rtl8723a_BT_mediastatus_notify(padapter, mstatus); - if (!rtl8723a_BT_using_antenna_1(padapter)) - LPS_Leave23a(padapter); - rtl8723a_set_FwJoinBssReport_cmd(padapter, 0); - break; - case LPS_CTRL_SPECIAL_PACKET: - pwrpriv->DelayLPSLastTimeStamp = jiffies; - rtl8723a_BT_specialpacket_notify(padapter); - if (!rtl8723a_BT_using_antenna_1(padapter)) - LPS_Leave23a(padapter); - break; - case LPS_CTRL_LEAVE: - rtl8723a_BT_lps_leave(padapter); - if (!rtl8723a_BT_using_antenna_1(padapter)) - LPS_Leave23a(padapter); - break; - - default: - break; - } -} - -int rtw_lps_ctrl_wk_cmd23a(struct rtw_adapter *padapter, - u8 lps_ctrl_type, u8 enqueue) -{ - struct cmd_obj *ph2c; - struct drvextra_cmd_parm *pdrvextra_cmd_parm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - int res = _SUCCESS; - - if (enqueue) { - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_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, - GEN_CMD_CODE(_Set_Drv_Extra)); - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); - } else - lps_ctrl_wk_hdl(padapter, lps_ctrl_type); -exit: - - return res; -} - -int rtw_ps_cmd23a(struct rtw_adapter *padapter) -{ - struct cmd_obj *ppscmd; - struct drvextra_cmd_parm *pdrvextra_cmd_parm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - int res = _SUCCESS; - - ppscmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!ppscmd) { - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), - GFP_ATOMIC); - if (!pdrvextra_cmd_parm) { - kfree(ppscmd); - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID; - pdrvextra_cmd_parm->pbuf = NULL; - init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, - GEN_CMD_CODE(_Set_Drv_Extra)); - - res = rtw_enqueue_cmd23a(pcmdpriv, ppscmd); -exit: - - return res; -} - -#ifdef CONFIG_8723AU_AP_MODE - -static void rtw_chk_hi_queue_hdl(struct rtw_adapter *padapter) -{ - int cnt = 0; - struct sta_info *psta_bmc; - struct sta_priv *pstapriv = &padapter->stapriv; - - psta_bmc = rtw_get_bcmc_stainfo23a(padapter); - if (!psta_bmc) - return; - - if (psta_bmc->sleepq_len == 0) { - bool val; - - val = rtl8723a_chk_hi_queue_empty(padapter); - - while (!val) { - msleep(100); - - cnt++; - - if (cnt > 10) - break; - - val = rtl8723a_chk_hi_queue_empty(padapter); - } - - if (cnt <= 10) { - pstapriv->tim_bitmap &= ~BIT(0); - pstapriv->sta_dz_bitmap &= ~BIT(0); - - update_beacon23a(padapter, WLAN_EID_TIM, NULL, false); - } else /* re check again */ - rtw_chk_hi_queue_cmd23a(padapter); - } -} - -int rtw_chk_hi_queue_cmd23a(struct rtw_adapter *padapter) -{ - struct cmd_obj *ph2c; - struct drvextra_cmd_parm *pdrvextra_cmd_parm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - int res = _SUCCESS; - - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), - GFP_ATOMIC); - if (!pdrvextra_cmd_parm) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID; - pdrvextra_cmd_parm->type_size = 0; - pdrvextra_cmd_parm->pbuf = NULL; - - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, - GEN_CMD_CODE(_Set_Drv_Extra)); - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); -exit: - - return res; -} -#endif - -int rtw_c2h_wk_cmd23a(struct rtw_adapter *padapter, u8 *c2h_evt) -{ - struct cmd_obj *ph2c; - struct drvextra_cmd_parm *pdrvextra_cmd_parm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - int res = _SUCCESS; - - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), - GFP_ATOMIC); - if (!pdrvextra_cmd_parm) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm->ec_id = C2H_WK_CID; - pdrvextra_cmd_parm->type_size = c2h_evt?16:0; - pdrvextra_cmd_parm->pbuf = c2h_evt; - - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, - GEN_CMD_CODE(_Set_Drv_Extra)); - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); - -exit: - - return res; -} - -static int c2h_evt_hdl(struct rtw_adapter *adapter, struct c2h_evt_hdr *c2h_evt) -{ - int ret = _FAIL; - u8 buf[16]; - - if (!c2h_evt) { - /* No c2h event in cmd_obj, read c2h event before handling*/ - if (c2h_evt_read23a(adapter, buf) == _SUCCESS) { - c2h_evt = (struct c2h_evt_hdr *)buf; - - ret = c2h_handler_8723a(adapter, c2h_evt); - } - } else - ret = c2h_handler_8723a(adapter, c2h_evt); - - return ret; -} - -static void rtw_irq_work(struct work_struct *work) -{ - struct evt_priv *evtpriv; - struct rtw_adapter *adapter; - - evtpriv = container_of(work, struct evt_priv, irq_wk); - adapter = container_of(evtpriv, struct rtw_adapter, evtpriv); - - c2h_evt_clear23a(adapter); -} - -void rtw_evt_work(struct work_struct *work) -{ - struct evt_work *ework; - struct rtw_adapter *adapter; - - ework = container_of(work, struct evt_work, work); - adapter = ework->adapter; - - c2h_evt_clear23a(adapter); - - if (!c2h_evt_exist(&ework->u.c2h_evt)) { - kfree(ework); - return; - } - - if (c2h_id_filter_ccx_8723a(ework->u.c2h_evt.id) == true) { - /* Handle CCX report here */ - c2h_handler_8723a(adapter, &ework->u.c2h_evt); - kfree(ework); - } else { - /* - * Enqueue into cmd_thread for others. - * ework will be turned into a c2h_evt and freed once it - * has been consumed. - */ - rtw_c2h_wk_cmd23a(adapter, (u8 *)&ework->u.c2h_evt); - } -} - -int rtw_drvextra_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - const struct drvextra_cmd_parm *pdrvextra_cmd; - - if (!pbuf) - return H2C_PARAMETERS_ERROR; - - pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf; - - switch (pdrvextra_cmd->ec_id) { - case DYNAMIC_CHK_WK_CID: - dynamic_chk_wk_hdl(padapter, pdrvextra_cmd->pbuf, - pdrvextra_cmd->type_size); - break; - case POWER_SAVING_CTRL_WK_CID: - rtw_ps_processor23a(padapter); - break; - case LPS_CTRL_WK_CID: - lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type_size); - break; -#ifdef CONFIG_8723AU_AP_MODE - case CHECK_HIQ_WK_CID: - rtw_chk_hi_queue_hdl(padapter); - break; -#endif /* CONFIG_8723AU_AP_MODE */ - case C2H_WK_CID: - c2h_evt_hdl(padapter, - (struct c2h_evt_hdr *)pdrvextra_cmd->pbuf); - break; - - default: - break; - } - - if (pdrvextra_cmd->pbuf && (pdrvextra_cmd->type_size > 0)) { - kfree(pdrvextra_cmd->pbuf); - /* - * No need to set pdrvextra_cmd->pbuf = NULL as we were - * operating on a copy of the original pcmd->parmbuf - * created in rtw_cmd_work(). - */ - } - - return H2C_SUCCESS; -} - -void rtw_survey_cmd_callback23a(struct rtw_adapter *padapter, - struct cmd_obj *pcmd) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (pcmd->res == H2C_DROPPED) { - /* TODO: cancel timer and do timeout handler directly... */ - /* need to make timeout handlerOS independent */ - mod_timer(&pmlmepriv->scan_to_timer, - jiffies + msecs_to_jiffies(1)); - } 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_, - "********Error: MgntActrtw_set_802_11_bssid23a_LIST_SCAN Fail ************\n"); - } - - /* free cmd */ - rtw_free_cmd_obj23a(pcmd); -} - -void rtw_disassoc_cmd23a_callback(struct rtw_adapter *padapter, - struct cmd_obj *pcmd) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (pcmd->res != H2C_SUCCESS) { - spin_lock_bh(&pmlmepriv->lock); - set_fwstate(pmlmepriv, _FW_LINKED); - spin_unlock_bh(&pmlmepriv->lock); - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "***Error: disconnect_cmd_callback Fail ***\n"); - return; - } - - /* free cmd */ - rtw_free_cmd_obj23a(pcmd); -} - -void rtw_joinbss_cmd23a_callback(struct rtw_adapter *padapter, - struct cmd_obj *pcmd) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (pcmd->res == H2C_DROPPED) { - /* TODO: cancel timer and do timeout handler directly... */ - /* need to make timeout handlerOS independent */ - 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)); - } - - rtw_free_cmd_obj23a(pcmd); -} - -void rtw_createbss_cmd23a_callback(struct rtw_adapter *padapter, - struct cmd_obj *pcmd) -{ - struct sta_info *psta; - struct wlan_network *pwlan; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf; - struct wlan_network *tgt_network = &pmlmepriv->cur_network; - struct rtw_queue *scanned_queue = &pmlmepriv->scanned_queue; - - if (pcmd->res != H2C_SUCCESS) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "********Error: rtw_createbss_cmd23a_callback Fail ************\n"); - mod_timer(&pmlmepriv->assoc_timer, - jiffies + msecs_to_jiffies(1)); - } - - del_timer_sync(&pmlmepriv->assoc_timer); - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - psta = rtw_get_stainfo23a(&padapter->stapriv, - pnetwork->MacAddress); - if (!psta) { - psta = rtw_alloc_stainfo23a(&padapter->stapriv, - pnetwork->MacAddress, - GFP_KERNEL); - if (!psta) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "Can't alloc sta_info when createbss_cmd_callback\n"); - goto createbss_cmd_fail; - } - } - - spin_lock_bh(&pmlmepriv->lock); - rtw_indicate_connect23a(padapter); - spin_unlock_bh(&pmlmepriv->lock); - } else { - pwlan = rtw_alloc_network(pmlmepriv, GFP_KERNEL); - spin_lock_bh(&scanned_queue->lock); - if (!pwlan) { - pwlan = rtw_get_oldest_wlan_network23a(scanned_queue); - if (!pwlan) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "Error: can't get pwlan in rtw23a_joinbss_event_cb\n"); - spin_unlock_bh(&scanned_queue->lock); - goto createbss_cmd_fail; - } - pwlan->last_scanned = jiffies; - } else { - list_add_tail(&pwlan->list, - &scanned_queue->queue); - } - - pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork); - memcpy(&pwlan->network, pnetwork, pnetwork->Length); - /* pwlan->fixed = true; */ - - /* list_add_tail(&pwlan->list, - &pmlmepriv->scanned_queue.queue); */ - - /* copy pdev_network information to - pmlmepriv->cur_network */ - memcpy(&tgt_network->network, pnetwork, - get_wlan_bssid_ex_sz(pnetwork)); - - /* reset DSConfig */ - - clr_fwstate(pmlmepriv, _FW_UNDER_LINKING); - - /* we will set _FW_LINKED when there is one more sat to - join us (rtw_stassoc_event_callback23a) */ - spin_unlock_bh(&scanned_queue->lock); - } - -createbss_cmd_fail: - - rtw_free_cmd_obj23a(pcmd); -} - -void rtw_setstaKey_cmdrsp_callback23a(struct rtw_adapter *padapter, - struct cmd_obj *pcmd) -{ - struct sta_priv *pstapriv; - struct set_stakey_rsp *psetstakey_rsp; - struct sta_info *psta; - - pstapriv = &padapter->stapriv; - psetstakey_rsp = (struct set_stakey_rsp *) (pcmd->rsp); - psta = rtw_get_stainfo23a(pstapriv, psetstakey_rsp->addr); - - if (!psta) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "ERROR: rtw_setstaKey_cmdrsp_callback23a => can't get sta_info\n"); - goto exit; - } - -exit: - - rtw_free_cmd_obj23a(pcmd); -} - -void rtw_setassocsta_cmdrsp_callback23a(struct rtw_adapter *padapter, - struct cmd_obj *pcmd) -{ - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct set_assocsta_parm *passocsta_parm; - struct set_assocsta_rsp *passocsta_rsp; - struct sta_info *psta; - - passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf); - passocsta_rsp = (struct set_assocsta_rsp *) (pcmd->rsp); - psta = rtw_get_stainfo23a(pstapriv, passocsta_parm->addr); - - if (psta == NULL) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "ERROR: setassocsta_cmdrsp_callbac => can't get sta_info\n"); - goto exit; - } - - psta->aid = psta->mac_id = passocsta_rsp->cam_id; - - spin_lock_bh(&pmlmepriv->lock); - - if (check_fwstate(pmlmepriv, WIFI_MP_STATE) && - check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); - - set_fwstate(pmlmepriv, _FW_LINKED); - spin_unlock_bh(&pmlmepriv->lock); - -exit: - rtw_free_cmd_obj23a(pcmd); -} diff --git a/drivers/staging/rtl8723au/core/rtw_efuse.c b/drivers/staging/rtl8723au/core/rtw_efuse.c deleted file mode 100644 index 359ef41..0000000 --- a/drivers/staging/rtl8723au/core/rtw_efuse.c +++ /dev/null @@ -1,538 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RTW_EFUSE_C_ - -#include <osdep_service.h> -#include <drv_types.h> - -#include <rtw_efuse.h> -#include <rtl8723a_hal.h> -#include <usb_ops_linux.h> - -#define REG_EFUSE_CTRL 0x0030 -#define EFUSE_CTRL REG_EFUSE_CTRL /* E-Fuse Control */ - -#define VOLTAGE_V25 0x03 -#define LDOE25_SHIFT 28 - -/* - * When we want to enable write operation, we should change to - * pwr on state. When we stop write, we should switch to 500k mode - * and disable LDO 2.5V. - */ -static void Efuse_PowerSwitch(struct rtw_adapter *padapter, - u8 bWrite, u8 PwrState) -{ - u8 tempval; - u16 tmpV16; - - if (PwrState == true) { - rtl8723au_write8(padapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON); - - /* - * 1.2V Power: From VDDON with Power - * Cut(0x0000h[15]), default valid - */ - tmpV16 = rtl8723au_read16(padapter, REG_SYS_ISO_CTRL); - if (!(tmpV16 & PWC_EV12V)) { - tmpV16 |= PWC_EV12V; - rtl8723au_write16(padapter, REG_SYS_ISO_CTRL, tmpV16); - } - /* Reset: 0x0000h[28], default valid */ - tmpV16 = rtl8723au_read16(padapter, REG_SYS_FUNC_EN); - if (!(tmpV16 & FEN_ELDR)) { - tmpV16 |= FEN_ELDR; - rtl8723au_write16(padapter, REG_SYS_FUNC_EN, tmpV16); - } - - /* - * Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) - * clock from ANA, default valid - */ - tmpV16 = rtl8723au_read16(padapter, REG_SYS_CLKR); - if ((!(tmpV16 & LOADER_CLK_EN)) || (!(tmpV16 & ANA8M))) { - tmpV16 |= (LOADER_CLK_EN | ANA8M); - rtl8723au_write16(padapter, REG_SYS_CLKR, tmpV16); - } - - if (bWrite == true) { - /* Enable LDO 2.5V before read/write action */ - tempval = rtl8723au_read8(padapter, EFUSE_TEST + 3); - tempval &= 0x0F; - tempval |= (VOLTAGE_V25 << 4); - rtl8723au_write8(padapter, EFUSE_TEST + 3, - tempval | 0x80); - } - } else { - rtl8723au_write8(padapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF); - - if (bWrite == true) { - /* Disable LDO 2.5V after read/write action */ - tempval = rtl8723au_read8(padapter, EFUSE_TEST + 3); - rtl8723au_write8(padapter, EFUSE_TEST + 3, - tempval & 0x7F); - } - } -} - -u16 Efuse_GetCurrentSize23a(struct rtw_adapter *pAdapter, u8 efuseType) -{ - u16 ret = 0; - - if (efuseType == EFUSE_WIFI) - ret = rtl8723a_EfuseGetCurrentSize_WiFi(pAdapter); - else - ret = rtl8723a_EfuseGetCurrentSize_BT(pAdapter); - - return ret; -} - -/* Get current efuse area enabled word */ -u8 Efuse_CalculateWordCnts23a(u8 word_en) -{ - return hweight8((~word_en) & 0xf); -} - -/* - * Description: Execute E-Fuse read byte operation. - * - * Assumptions: 1. Boot from E-Fuse and successfully auto-load. - * 2. PASSIVE_LEVEL (USB interface) - */ -void ReadEFuseByte23a(struct rtw_adapter *Adapter, u16 _offset, u8 *pbuf) -{ - u32 value32; - u8 readbyte; - u16 retry; - - /* Write Address */ - rtl8723au_write8(Adapter, EFUSE_CTRL+1, (_offset & 0xff)); - readbyte = rtl8723au_read8(Adapter, EFUSE_CTRL+2); - rtl8723au_write8(Adapter, EFUSE_CTRL+2, - ((_offset >> 8) & 0x03) | (readbyte & 0xfc)); - - /* Write bit 32 0 */ - readbyte = rtl8723au_read8(Adapter, EFUSE_CTRL+3); - rtl8723au_write8(Adapter, EFUSE_CTRL+3, readbyte & 0x7f); - - /* Check bit 32 read-ready */ - retry = 0; - value32 = rtl8723au_read32(Adapter, EFUSE_CTRL); - while (!((value32 >> 24) & 0x80) && retry < 10000) { - value32 = rtl8723au_read32(Adapter, EFUSE_CTRL); - retry++; - } - - /* - * Added suggested delay. This fixes the problem that - * Efuse read error in high temperature condition. - * Designer says that there shall be some delay after - * ready bit is set, or the result will always stay - * on last data we read. - */ - udelay(50); - value32 = rtl8723au_read32(Adapter, EFUSE_CTRL); - - *pbuf = (u8)(value32 & 0xff); -} - -void EFUSE_GetEfuseDefinition23a(struct rtw_adapter *pAdapter, u8 efuseType, - u8 type, void *pOut) -{ - u8 *pu1Tmp; - u16 *pu2Tmp; - u8 *pMax_section; - - switch (type) { - case TYPE_EFUSE_MAX_SECTION: - pMax_section = pOut; - - if (efuseType == EFUSE_WIFI) - *pMax_section = EFUSE_MAX_SECTION_8723A; - else - *pMax_section = EFUSE_BT_MAX_SECTION; - break; - - case TYPE_EFUSE_REAL_CONTENT_LEN: - pu2Tmp = pOut; - - if (efuseType == EFUSE_WIFI) - *pu2Tmp = EFUSE_REAL_CONTENT_LEN_8723A; - else - *pu2Tmp = EFUSE_BT_REAL_CONTENT_LEN; - break; - - case TYPE_AVAILABLE_EFUSE_BYTES_BANK: - pu2Tmp = pOut; - - if (efuseType == EFUSE_WIFI) - *pu2Tmp = (EFUSE_REAL_CONTENT_LEN_8723A - - EFUSE_OOB_PROTECT_BYTES); - else - *pu2Tmp = (EFUSE_BT_REAL_BANK_CONTENT_LEN - - EFUSE_PROTECT_BYTES_BANK); - break; - - case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL: - pu2Tmp = pOut; - - if (efuseType == EFUSE_WIFI) - *pu2Tmp = (EFUSE_REAL_CONTENT_LEN_8723A - - EFUSE_OOB_PROTECT_BYTES); - else - *pu2Tmp = (EFUSE_BT_REAL_CONTENT_LEN - - (EFUSE_PROTECT_BYTES_BANK * 3)); - break; - - case TYPE_EFUSE_MAP_LEN: - pu2Tmp = pOut; - - if (efuseType == EFUSE_WIFI) - *pu2Tmp = EFUSE_MAP_LEN_8723A; - else - *pu2Tmp = EFUSE_BT_MAP_LEN; - break; - - case TYPE_EFUSE_PROTECT_BYTES_BANK: - pu1Tmp = pOut; - - if (efuseType == EFUSE_WIFI) - *pu1Tmp = EFUSE_OOB_PROTECT_BYTES; - else - *pu1Tmp = EFUSE_PROTECT_BYTES_BANK; - break; - - case TYPE_EFUSE_CONTENT_LEN_BANK: - pu2Tmp = pOut; - - if (efuseType == EFUSE_WIFI) - *pu2Tmp = EFUSE_REAL_CONTENT_LEN_8723A; - else - *pu2Tmp = EFUSE_BT_REAL_BANK_CONTENT_LEN; - break; - - default: - pu1Tmp = pOut; - *pu1Tmp = 0; - break; - } -} - -/* Copy from WMAC for EFUSE read 1 byte. */ -u8 EFUSE_Read1Byte23a(struct rtw_adapter *Adapter, u16 Address) -{ - u8 data; - u8 Bytetemp = {0x00}; - u8 temp = {0x00}; - u32 k = 0; - u16 contentLen = 0; - - EFUSE_GetEfuseDefinition23a(Adapter, EFUSE_WIFI, - TYPE_EFUSE_REAL_CONTENT_LEN, - (void *)&contentLen); - - if (Address < contentLen) { /* E-fuse 512Byte */ - /* Write E-fuse Register address bit0~7 */ - temp = Address & 0xFF; - rtl8723au_write8(Adapter, EFUSE_CTRL+1, temp); - Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+2); - /* Write E-fuse Register address bit8~9 */ - temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC); - rtl8723au_write8(Adapter, EFUSE_CTRL+2, temp); - - /* Write 0x30[31]= 0 */ - Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3); - temp = Bytetemp & 0x7F; - rtl8723au_write8(Adapter, EFUSE_CTRL+3, temp); - - /* Wait Write-ready (0x30[31]= 1) */ - Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3); - while (!(Bytetemp & 0x80)) { - Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3); - k++; - if (k == 1000) { - k = 0; - break; - } - } - data = rtl8723au_read8(Adapter, EFUSE_CTRL); - return data; - } - return 0xFF; -} - -/* Read one byte from real Efuse. */ -int efuse_OneByteRead23a(struct rtw_adapter *pAdapter, u16 addr, u8 *data) -{ - u8 tmpidx = 0; - int bResult; - - /* -----------------e-fuse reg ctrl ---------------------------- */ - /* address */ - rtl8723au_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff)); - rtl8723au_write8(pAdapter, EFUSE_CTRL + 2, - ((u8)((addr >> 8) & 0x03)) | - (rtl8723au_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC)); - - rtl8723au_write8(pAdapter, EFUSE_CTRL + 3, 0x72); /* read cmd */ - - while (!(0x80 & rtl8723au_read8(pAdapter, EFUSE_CTRL + 3)) && - (tmpidx < 100)) - tmpidx++; - if (tmpidx < 100) { - *data = rtl8723au_read8(pAdapter, EFUSE_CTRL); - bResult = _SUCCESS; - } else { - *data = 0xff; - bResult = _FAIL; - } - return bResult; -} - -/* Write one byte to reald Efuse. */ -int efuse_OneByteWrite23a(struct rtw_adapter *pAdapter, u16 addr, u8 data) -{ - u8 tmpidx = 0; - int bResult; - - /* return 0; */ - - /* -----------------e-fuse reg ctrl ------------------------- */ - /* address */ - rtl8723au_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff)); - rtl8723au_write8(pAdapter, EFUSE_CTRL + 2, - (rtl8723au_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC) | - (u8)((addr >> 8) & 0x03)); - rtl8723au_write8(pAdapter, EFUSE_CTRL, data); /* data */ - - rtl8723au_write8(pAdapter, EFUSE_CTRL + 3, 0xF2); /* write cmd */ - - while ((0x80 & rtl8723au_read8(pAdapter, EFUSE_CTRL + 3)) && - (tmpidx < 100)) { - tmpidx++; - } - - if (tmpidx < 100) - bResult = _SUCCESS; - else - bResult = _FAIL; - - return bResult; -} - -/* Read allowed word in current efuse section data. */ -void efuse_WordEnableDataRead23a(u8 word_en, u8 *sourdata, u8 *targetdata) -{ - if (!(word_en&BIT(0))) { - targetdata[0] = sourdata[0]; - targetdata[1] = sourdata[1]; - } - if (!(word_en&BIT(1))) { - targetdata[2] = sourdata[2]; - targetdata[3] = sourdata[3]; - } - if (!(word_en&BIT(2))) { - targetdata[4] = sourdata[4]; - targetdata[5] = sourdata[5]; - } - if (!(word_en&BIT(3))) { - targetdata[6] = sourdata[6]; - targetdata[7] = sourdata[7]; - } -} - -static int efuse_read8(struct rtw_adapter *padapter, u16 address, u8 *value) -{ - return efuse_OneByteRead23a(padapter, address, value); -} - -static int efuse_write8(struct rtw_adapter *padapter, u16 address, u8 *value) -{ - return efuse_OneByteWrite23a(padapter, address, *value); -} - -/* read/write raw efuse data */ -int rtw_efuse_access23a(struct rtw_adapter *padapter, u8 bWrite, u16 start_addr, - u16 cnts, u8 *data) -{ - int i = 0; - u16 real_content_len = 0, max_available_size = 0; - int res = _FAIL; - int (*rw8)(struct rtw_adapter *, u16, u8*); - - EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI, - TYPE_EFUSE_REAL_CONTENT_LEN, - (void *)&real_content_len); - EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI, - TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, - (void *)&max_available_size); - - if (start_addr > real_content_len) - return _FAIL; - - if (true == bWrite) { - if ((start_addr + cnts) > max_available_size) - return _FAIL; - rw8 = &efuse_write8; - } else - rw8 = &efuse_read8; - - Efuse_PowerSwitch(padapter, bWrite, true); - - /* e-fuse one byte read/write */ - for (i = 0; i < cnts; i++) { - if (start_addr >= real_content_len) { - res = _FAIL; - break; - } - - res = rw8(padapter, start_addr++, data++); - if (res == _FAIL) - break; - } - - Efuse_PowerSwitch(padapter, bWrite, false); - - return res; -} - -u16 efuse_GetMaxSize23a(struct rtw_adapter *padapter) -{ - u16 max_size; - - EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI, - TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, - (void *)&max_size); - return max_size; -} - -int rtw_efuse_map_read23a(struct rtw_adapter *padapter, - u16 addr, u16 cnts, u8 *data) -{ - u16 mapLen = 0; - - EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI, - TYPE_EFUSE_MAP_LEN, (void *)&mapLen); - - if ((addr + cnts) > mapLen) - return _FAIL; - - Efuse_PowerSwitch(padapter, false, true); - - rtl8723a_readefuse(padapter, EFUSE_WIFI, addr, cnts, data); - - Efuse_PowerSwitch(padapter, false, false); - - return _SUCCESS; -} - -int rtw_BT_efuse_map_read23a(struct rtw_adapter *padapter, - u16 addr, u16 cnts, u8 *data) -{ - u16 mapLen = 0; - - EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT, - TYPE_EFUSE_MAP_LEN, (void *)&mapLen); - - if ((addr + cnts) > mapLen) - return _FAIL; - - Efuse_PowerSwitch(padapter, false, true); - - rtl8723a_readefuse(padapter, EFUSE_BT, addr, cnts, data); - - Efuse_PowerSwitch(padapter, false, false); - - return _SUCCESS; -} - -/* Read All Efuse content */ -static void Efuse_ReadAllMap(struct rtw_adapter *pAdapter, u8 efuseType, - u8 *Efuse) -{ - u16 mapLen = 0; - - Efuse_PowerSwitch(pAdapter, false, true); - - EFUSE_GetEfuseDefinition23a(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, - (void *)&mapLen); - - rtl8723a_readefuse(pAdapter, efuseType, 0, mapLen, Efuse); - - Efuse_PowerSwitch(pAdapter, false, false); -} - -/* - * Functions: efuse_ShadowRead1Byte - * efuse_ShadowRead2Byte - * efuse_ShadowRead4Byte - * - * Read from efuse init map by one/two/four bytes - */ -static void efuse_ShadowRead1Byte(struct rtw_adapter *pAdapter, u16 Offset, - u8 *Value) -{ - struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter); - - *Value = pEEPROM->efuse_eeprom_data[Offset]; -} - -static void efuse_ShadowRead2Byte(struct rtw_adapter *pAdapter, u16 Offset, - u16 *Value) -{ - struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter); - - *Value = pEEPROM->efuse_eeprom_data[Offset]; - *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8; -} - -static void efuse_ShadowRead4Byte(struct rtw_adapter *pAdapter, u16 Offset, - u32 *Value) -{ - struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter); - - *Value = pEEPROM->efuse_eeprom_data[Offset]; - *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8; - *Value |= pEEPROM->efuse_eeprom_data[Offset+2]<<16; - *Value |= pEEPROM->efuse_eeprom_data[Offset+3]<<24; -} - -/* Transfer current EFUSE content to shadow init and modify map. */ -void EFUSE_ShadowMapUpdate23a(struct rtw_adapter *pAdapter, u8 efuseType) -{ - struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter); - u16 mapLen = 0; - - EFUSE_GetEfuseDefinition23a(pAdapter, efuseType, - TYPE_EFUSE_MAP_LEN, (void *)&mapLen); - - if (pEEPROM->bautoload_fail_flag == true) - memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen); - else - Efuse_ReadAllMap(pAdapter, efuseType, - pEEPROM->efuse_eeprom_data); -} - -/* Read from efuse init map */ -void EFUSE_ShadowRead23a(struct rtw_adapter *pAdapter, u8 Type, - u16 Offset, u32 *Value) -{ - if (Type == 1) - efuse_ShadowRead1Byte(pAdapter, Offset, (u8 *)Value); - else if (Type == 2) - efuse_ShadowRead2Byte(pAdapter, Offset, (u16 *)Value); - else if (Type == 4) - efuse_ShadowRead4Byte(pAdapter, Offset, (u32 *)Value); -} diff --git a/drivers/staging/rtl8723au/core/rtw_ieee80211.c b/drivers/staging/rtl8723au/core/rtw_ieee80211.c deleted file mode 100644 index 9fa0ef1..0000000 --- a/drivers/staging/rtl8723au/core/rtw_ieee80211.c +++ /dev/null @@ -1,855 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _IEEE80211_C - -#include <drv_types.h> -#include <linux/ieee80211.h> -#include <ieee80211.h> -#include <wifi.h> -#include <osdep_service.h> -#include <wlan_bssdef.h> - -u8 RTW_WPA_OUI23A_TYPE[] = { 0x00, 0x50, 0xf2, 1 }; -u16 RTW_WPA_VERSION23A = 1; -u8 WPA_AUTH_KEY_MGMT_NONE23A[] = { 0x00, 0x50, 0xf2, 0 }; -u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X23A[] = { 0x00, 0x50, 0xf2, 1 }; -u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X23A[] = { 0x00, 0x50, 0xf2, 2 }; -u8 WPA_CIPHER_SUITE_NONE23A[] = { 0x00, 0x50, 0xf2, 0 }; -u8 WPA_CIPHER_SUITE_WEP4023A[] = { 0x00, 0x50, 0xf2, 1 }; -u8 WPA_CIPHER_SUITE_TKIP23A[] = { 0x00, 0x50, 0xf2, 2 }; -u8 WPA_CIPHER_SUITE_WRAP23A[] = { 0x00, 0x50, 0xf2, 3 }; -u8 WPA_CIPHER_SUITE_CCMP23A[] = { 0x00, 0x50, 0xf2, 4 }; -u8 WPA_CIPHER_SUITE_WEP10423A[] = { 0x00, 0x50, 0xf2, 5 }; - -u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X23A[] = { 0x00, 0x0f, 0xac, 1 }; -u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X23A[] = { 0x00, 0x0f, 0xac, 2 }; -u8 RSN_CIPHER_SUITE_NONE23A[] = { 0x00, 0x0f, 0xac, 0 }; -u8 RSN_CIPHER_SUITE_WEP4023A[] = { 0x00, 0x0f, 0xac, 1 }; -u8 RSN_CIPHER_SUITE_TKIP23A[] = { 0x00, 0x0f, 0xac, 2 }; -u8 RSN_CIPHER_SUITE_WRAP23A[] = { 0x00, 0x0f, 0xac, 3 }; -u8 RSN_CIPHER_SUITE_CCMP23A[] = { 0x00, 0x0f, 0xac, 4 }; -u8 RSN_CIPHER_SUITE_WEP10423A[] = { 0x00, 0x0f, 0xac, 5 }; -/* */ -/* for adhoc-master to generate ie and provide supported-rate to fw */ -/* */ - -static u8 WIFI_CCKRATES[] = { - IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK -}; - -static u8 WIFI_OFDMRATES[] = { - IEEE80211_OFDM_RATE_6MB, - IEEE80211_OFDM_RATE_9MB, - IEEE80211_OFDM_RATE_12MB, - IEEE80211_OFDM_RATE_18MB, - IEEE80211_OFDM_RATE_24MB, - IEEE80211_OFDM_RATE_36MB, - IEEE80211_OFDM_RATE_48MB, - IEEE80211_OFDM_RATE_54MB -}; - -int rtw_get_bit_value_from_ieee_value23a(u8 val) -{ - unsigned char dot11_rate_table[] = - {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 0}; - - int i = 0; - - while (dot11_rate_table[i] != 0) { - if (dot11_rate_table[i] == val) - return BIT(i); - i++; - } - return 0; -} - -static bool rtw_is_cckrates_included(u8 *rate) -{ - u32 i = 0; - - while (rate[i]) { - if ((rate[i] & 0x7f) == 2 || (rate[i] & 0x7f) == 4 || - (rate[i] & 0x7f) == 11 || (rate[i] & 0x7f) == 22) - return true; - i++; - } - - return false; -} - -static bool rtw_is_cckratesonly_included(u8 *rate) -{ - u32 i = 0; - - while (rate[i]) { - if ((rate[i] & 0x7f) != 2 && (rate[i] & 0x7f) != 4 && - (rate[i] & 0x7f) != 11 && (rate[i] & 0x7f) != 22) - return false; - - i++; - } - - return true; -} - -int rtw_check_network_type23a(unsigned char *rate, int ratelen, int channel) -{ - if (channel > 14) { - if (rtw_is_cckrates_included(rate)) - return WIRELESS_INVALID; - else - return WIRELESS_11A; - } else { /* could be pure B, pure G, or B/G */ - if (rtw_is_cckratesonly_included(rate)) - return WIRELESS_11B; - else if (rtw_is_cckrates_included(rate)) - return WIRELESS_11BG; - else - return WIRELESS_11G; - } -} - -/* rtw_set_ie23a will update frame length */ -u8 *rtw_set_ie23a(u8 *pbuf, int index, uint len, const u8 *source, uint *frlen) -{ - - *pbuf = (u8)index; - - *(pbuf + 1) = (u8)len; - - if (len > 0) - memcpy((void *)(pbuf + 2), (void *)source, len); - - *frlen = *frlen + (len + 2); - - return pbuf + len + 2; -} - -inline u8 *rtw_set_ie23a_ch_switch(u8 *buf, u32 *buf_len, u8 ch_switch_mode, - u8 new_ch, u8 ch_switch_cnt) -{ - u8 ie_data[3]; - - ie_data[0] = ch_switch_mode; - ie_data[1] = new_ch; - ie_data[2] = ch_switch_cnt; - return rtw_set_ie23a(buf, WLAN_EID_CHANNEL_SWITCH, 3, ie_data, buf_len); -} - -inline u8 hal_ch_offset_to_secondary_ch_offset23a(u8 ch_offset) -{ - if (ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER) - return IEEE80211_HT_PARAM_CHA_SEC_BELOW; - else if (ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER) - return IEEE80211_HT_PARAM_CHA_SEC_ABOVE; - - return IEEE80211_HT_PARAM_CHA_SEC_NONE; -} - -inline u8 *rtw_set_ie23a_secondary_ch_offset(u8 *buf, u32 *buf_len, - u8 secondary_ch_offset) -{ - return rtw_set_ie23a(buf, WLAN_EID_SECONDARY_CHANNEL_OFFSET, - 1, &secondary_ch_offset, buf_len); -} - -/*---------------------------------------------------------------------------- -index: the information element id index, limit is the limit for search ------------------------------------------------------------------------------*/ -u8 *rtw_get_ie23a(u8 *pbuf, int index, int *len, int limit) -{ - int tmp, i; - u8 *p; - - if (limit < 1) { - - return NULL; - } - - p = pbuf; - i = 0; - *len = 0; - while (1) { - if (*p == index) { - *len = *(p + 1); - return p; - } else { - tmp = *(p + 1); - p += (tmp + 2); - i += (tmp + 2); - } - if (i >= limit) - break; - } - - return NULL; -} - -/** - * rtw_get_ie23a_ex - Search specific IE from a series of IEs - * @in_ie: Address of IEs to search - * @in_len: Length limit from in_ie - * @eid: Element ID to match - * @oui: OUI to match - * @oui_len: OUI length - * @ie: If not NULL and the specific IE is found, the IE will be copied - * to the buf starting from the specific IE - * @ielen: If not NULL and the specific IE is found, will set to the length - * of the entire IE - * - * Returns: The address of the specific IE found, or NULL - */ -u8 *rtw_get_ie23a_ex(u8 *in_ie, uint in_len, u8 eid, u8 *oui, u8 oui_len, - u8 *ie, uint *ielen) -{ - uint cnt; - u8 *target_ie = NULL; - - if (ielen) - *ielen = 0; - - if (!in_ie || in_len <= 0) - return target_ie; - - cnt = 0; - - while (cnt < in_len) { - if (eid == in_ie[cnt] && - (!oui || !memcmp(&in_ie[cnt + 2], oui, oui_len))) { - target_ie = &in_ie[cnt]; - - if (ie) - memcpy(ie, &in_ie[cnt], in_ie[cnt + 1] + 2); - - if (ielen) - *ielen = in_ie[cnt + 1] + 2; - break; - } else { - cnt += in_ie[cnt + 1] + 2; /* goto next */ - } - } - - return target_ie; -} - -/** - * rtw_ies_remove_ie23a - Find matching IEs and remove - * @ies: Address of IEs to search - * @ies_len: Pointer of length of ies, will update to new length - * @offset: The offset to start search - * @eid: Element ID to match - * @oui: OUI to match - * @oui_len: OUI length - * - * Returns: _SUCCESS: ies is updated, _FAIL: not updated - */ -int rtw_ies_remove_ie23a(u8 *ies, uint *ies_len, uint offset, u8 eid, - u8 *oui, u8 oui_len) -{ - int ret = _FAIL; - u8 *target_ie; - u32 target_ielen; - u8 *start; - uint search_len; - - if (!ies || !ies_len || *ies_len <= offset) - goto exit; - - start = ies + offset; - search_len = *ies_len - offset; - - while (1) { - target_ie = rtw_get_ie23a_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); - *ies_len = *ies_len - target_ielen; - ret = _SUCCESS; - - start = target_ie; - search_len = remain_len; - } else { - break; - } - } -exit: - return ret; -} - -void rtw_set_supported_rate23a(u8 *SupportedRates, uint mode) -{ - - - memset(SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX); - - switch (mode) { - case WIRELESS_11B: - memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN); - break; - - case WIRELESS_11G: - case WIRELESS_11A: - case WIRELESS_11_5N: - case WIRELESS_11A_5N:/* Todo: no basic rate for ofdm ? */ - memcpy(SupportedRates, WIFI_OFDMRATES, - IEEE80211_NUM_OFDM_RATESLEN); - break; - - case WIRELESS_11BG: - case WIRELESS_11G_24N: - case WIRELESS_11_24N: - case WIRELESS_11BG_24N: - memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN); - memcpy(SupportedRates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES, - IEEE80211_NUM_OFDM_RATESLEN); - break; - } - -} - -uint rtw_get_rateset_len23a(u8 *rateset) -{ - uint i = 0; - - while (1) { - if (rateset[i] == 0) - break; - - if (i > 12) - break; - - i++; - } - - return i; -} - -int rtw_generate_ie23a(struct registry_priv *pregistrypriv) -{ - u8 wireless_mode; - int sz = 0, rateLen; - struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network; - u8 *ie = pdev_network->IEs; - u16 cap; - - pdev_network->tsf = 0; - - cap = WLAN_CAPABILITY_IBSS; - - if (pregistrypriv->preamble == PREAMBLE_SHORT) - cap |= WLAN_CAPABILITY_SHORT_PREAMBLE; - - if (pdev_network->Privacy) - cap |= WLAN_CAPABILITY_PRIVACY; - - pdev_network->capability = cap; - - /* SSID */ - ie = rtw_set_ie23a(ie, WLAN_EID_SSID, pdev_network->Ssid.ssid_len, - pdev_network->Ssid.ssid, &sz); - - /* supported rates */ - if (pregistrypriv->wireless_mode == WIRELESS_11ABGN) { - if (pdev_network->DSConfig > 14) - wireless_mode = WIRELESS_11A_5N; - else - wireless_mode = WIRELESS_11BG_24N; - } else { - wireless_mode = pregistrypriv->wireless_mode; - } - - rtw_set_supported_rate23a(pdev_network->SupportedRates, wireless_mode); - - rateLen = rtw_get_rateset_len23a(pdev_network->SupportedRates); - - if (rateLen > 8) { - ie = rtw_set_ie23a(ie, WLAN_EID_SUPP_RATES, 8, - pdev_network->SupportedRates, &sz); - /* ie = rtw_set_ie23a(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz); */ - } else { - ie = rtw_set_ie23a(ie, WLAN_EID_SUPP_RATES, rateLen, - pdev_network->SupportedRates, &sz); - } - - /* DS parameter set */ - ie = rtw_set_ie23a(ie, WLAN_EID_DS_PARAMS, 1, - (u8 *)&pdev_network->DSConfig, &sz); - - /* IBSS Parameter Set */ - - ie = rtw_set_ie23a(ie, WLAN_EID_IBSS_PARAMS, 2, - (u8 *)&pdev_network->ATIMWindow, &sz); - - if (rateLen > 8) { - ie = rtw_set_ie23a(ie, WLAN_EID_EXT_SUPP_RATES, (rateLen - 8), - (pdev_network->SupportedRates + 8), &sz); - } - - - - /* return _SUCCESS; */ - - return sz; -} - -static int rtw_get_wpa_cipher_suite(const u8 *s) -{ - if (!memcmp(s, WPA_CIPHER_SUITE_NONE23A, WPA_SELECTOR_LEN)) - return WPA_CIPHER_NONE; - if (!memcmp(s, WPA_CIPHER_SUITE_WEP4023A, WPA_SELECTOR_LEN)) - return WPA_CIPHER_WEP40; - if (!memcmp(s, WPA_CIPHER_SUITE_TKIP23A, WPA_SELECTOR_LEN)) - return WPA_CIPHER_TKIP; - if (!memcmp(s, WPA_CIPHER_SUITE_CCMP23A, WPA_SELECTOR_LEN)) - return WPA_CIPHER_CCMP; - if (!memcmp(s, WPA_CIPHER_SUITE_WEP10423A, WPA_SELECTOR_LEN)) - return WPA_CIPHER_WEP104; - - return 0; -} - -static int rtw_get_wpa2_cipher_suite(const u8 *s) -{ - if (!memcmp(s, RSN_CIPHER_SUITE_NONE23A, RSN_SELECTOR_LEN)) - return WPA_CIPHER_NONE; - if (!memcmp(s, RSN_CIPHER_SUITE_WEP4023A, RSN_SELECTOR_LEN)) - return WPA_CIPHER_WEP40; - if (!memcmp(s, RSN_CIPHER_SUITE_TKIP23A, RSN_SELECTOR_LEN)) - return WPA_CIPHER_TKIP; - if (!memcmp(s, RSN_CIPHER_SUITE_CCMP23A, RSN_SELECTOR_LEN)) - return WPA_CIPHER_CCMP; - if (!memcmp(s, RSN_CIPHER_SUITE_WEP10423A, RSN_SELECTOR_LEN)) - return WPA_CIPHER_WEP104; - - return 0; -} - -int rtw_parse_wpa_ie23a(const u8 *wpa_ie, int wpa_ie_len, int *group_cipher, - int *pairwise_cipher, int *is_8021x) -{ - int i, ret = _SUCCESS; - int left, count; - const u8 *pos; - - if (wpa_ie_len <= 0) { - /* No WPA IE - fail silently */ - return _FAIL; - } - - if (wpa_ie[1] != (u8)(wpa_ie_len - 2)) - return _FAIL; - - pos = wpa_ie; - - pos += 8; - left = wpa_ie_len - 8; - - /* group_cipher */ - if (left >= WPA_SELECTOR_LEN) { - - *group_cipher = rtw_get_wpa_cipher_suite(pos); - - 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\n", - __func__, left); - - return _FAIL; - } - - /* pairwise_cipher */ - if (left >= 2) { - /* count = le16_to_cpu(*(u16*)pos); */ - count = get_unaligned_le16(pos); - 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\n", - __func__, count, left); - return _FAIL; - } - - for (i = 0; i < count; i++) { - *pairwise_cipher |= rtw_get_wpa_cipher_suite(pos); - - pos += WPA_SELECTOR_LEN; - left -= WPA_SELECTOR_LEN; - } - } else if (left == 1) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "%s: ie too short (for key mgmt)\n", __func__); - return _FAIL; - } - - if (is_8021x) { - if (left >= 6) { - pos += 2; - if (!memcmp(pos, RTW_WPA_OUI23A_TYPE, 4)) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "%s : there has 802.1x auth\n", - __func__); - *is_8021x = 1; - } - } - } - - return ret; -} - -int rtw_parse_wpa2_ie23a(const u8 *rsn_ie, int rsn_ie_len, int *group_cipher, - int *pairwise_cipher, int *is_8021x) -{ - int i, ret = _SUCCESS; - int left, count; - const u8 *pos; - u8 SUITE_1X[4] = {0x00, 0x0f, 0xac, 0x01}; - - if (rsn_ie_len <= 0) { - /* No RSN IE - fail silently */ - return _FAIL; - } - - if (*rsn_ie != WLAN_EID_RSN || *(rsn_ie + 1) != (u8)(rsn_ie_len - 2)) { - return _FAIL; - } - - pos = rsn_ie; - pos += 4; - left = rsn_ie_len - 4; - - /* group_cipher */ - if (left >= RSN_SELECTOR_LEN) { - *group_cipher = rtw_get_wpa2_cipher_suite(pos); - - pos += RSN_SELECTOR_LEN; - left -= RSN_SELECTOR_LEN; - } else if (left > 0) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "%s: ie length mismatch, %u too much\n", - __func__, left); - return _FAIL; - } - - /* pairwise_cipher */ - if (left >= 2) { - /* count = le16_to_cpu(*(u16*)pos); */ - count = get_unaligned_le16(pos); - 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\n", - __func__, count, left); - return _FAIL; - } - - for (i = 0; i < count; i++) { - *pairwise_cipher |= rtw_get_wpa2_cipher_suite(pos); - - pos += RSN_SELECTOR_LEN; - left -= RSN_SELECTOR_LEN; - } - } else if (left == 1) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "%s: ie too short (for key mgmt)\n", __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__); - *is_8021x = 1; - } - } - } - - return ret; -} - -/** - * rtw_get_wps_attr23a - Search a specific WPS attribute from a given WPS IE - * @wps_ie: Address of WPS IE to search - * @wps_ielen: Length limit from wps_ie - * @target_attr_id: The attribute ID of WPS attribute to search - * @buf_attr: If not NULL and the WPS attribute is found, WPS attribute - * will be copied to the buf starting from buf_attr - * @len_attr: If not NULL and the WPS attribute is found, will set to the - * length of the entire WPS attribute - * - * Returns: the address of the specific WPS attribute found, or NULL - */ -const u8 *rtw_get_wps_attr23a(const u8 *wps_ie, uint wps_ielen, - u16 target_attr_id, u8 *buf_attr, u32 *len_attr) -{ - const u8 *attr_ptr = NULL; - const u8 *target_attr_ptr = NULL; - u8 wps_oui[4] = {0x00, 0x50, 0xF2, 0x04}; - - if (len_attr) - *len_attr = 0; - - if (wps_ie[0] != WLAN_EID_VENDOR_SPECIFIC || - memcmp(wps_ie + 2, wps_oui, 4)) { - return attr_ptr; - } - - /* 6 = 1(Element ID) + 1(Length) + 4(WPS OUI) */ - attr_ptr = wps_ie + 6; /* goto first attr */ - - while (attr_ptr - wps_ie < wps_ielen) { - /* 4 = 2(Attribute ID) + 2(Length) */ - u16 attr_id = get_unaligned_be16(attr_ptr); - u16 attr_data_len = get_unaligned_be16(attr_ptr + 2); - u16 attr_len = attr_data_len + 4; - - /* DBG_8723A("%s attr_ptr:%p, id:%u, length:%u\n", __func__, attr_ptr, attr_id, attr_data_len); */ - if (attr_id == target_attr_id) { - target_attr_ptr = attr_ptr; - - if (buf_attr) - memcpy(buf_attr, attr_ptr, attr_len); - - if (len_attr) - *len_attr = attr_len; - - break; - } else { - attr_ptr += attr_len; /* goto next */ - } - } - - return target_attr_ptr; -} - -/** - * rtw_get_wps_attr_content23a - Search a specific WPS attribute content - * from a given WPS IE - * @wps_ie: Address of WPS IE to search - * @wps_ielen: Length limit from wps_ie - * @target_attr_id: The attribute ID of WPS attribute to search - * @buf_content: If not NULL and the WPS attribute is found, WPS attribute - * content will be copied to the buf starting from buf_content - * @len_content: If not NULL and the WPS attribute is found, will set to the - * length of the WPS attribute content - * - * Returns: the address of the specific WPS attribute content found, or NULL - */ -const u8 *rtw_get_wps_attr_content23a(const u8 *wps_ie, uint wps_ielen, - u16 target_attr_id, u8 *buf_content) -{ - const u8 *attr_ptr; - u32 attr_len; - - attr_ptr = rtw_get_wps_attr23a(wps_ie, wps_ielen, target_attr_id, - NULL, &attr_len); - - if (attr_ptr && attr_len) { - if (buf_content) - memcpy(buf_content, attr_ptr + 4, attr_len - 4); - - return attr_ptr + 4; - } - - return NULL; -} - -static int rtw_get_cipher_info(struct wlan_network *pnetwork) -{ - const u8 *pbuf; - int group_cipher = 0, pairwise_cipher = 0, is8021x = 0; - int ret = _FAIL; - int r, plen; - char *pie; - - pie = pnetwork->network.IEs; - plen = pnetwork->network.IELength; - - pbuf = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPA, pie, plen); - - if (pbuf && pbuf[1] > 0) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "rtw_get_cipher_info: wpa_ielen: %d\n", pbuf[1]); - r = rtw_parse_wpa_ie23a(pbuf, pbuf[1] + 2, &group_cipher, - &pairwise_cipher, &is8021x); - if (r == _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\n", - __func__, pnetwork->BcnInfo.pairwise_cipher, - pnetwork->BcnInfo.is_8021x); - ret = _SUCCESS; - } - } else { - pbuf = cfg80211_find_ie(WLAN_EID_RSN, pie, plen); - - if (pbuf && pbuf[1] > 0) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "get RSN IE\n"); - r = rtw_parse_wpa2_ie23a(pbuf, pbuf[1] + 2, - &group_cipher, &pairwise_cipher, - &is8021x); - if (r == _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\n", - __func__, - pnetwork->BcnInfo.pairwise_cipher, - pnetwork->BcnInfo.group_cipher, - pnetwork->BcnInfo.is_8021x); - ret = _SUCCESS; - } - } - } - - return ret; -} - -void rtw_get_bcn_info23a(struct wlan_network *pnetwork) -{ - u8 bencrypt = 0; - int pie_len; - u8 *pie; - const u8 *p; - - if (pnetwork->network.capability & WLAN_CAPABILITY_PRIVACY) { - bencrypt = 1; - pnetwork->network.Privacy = 1; - } else - pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_OPENSYS; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "%s: ssid =%s\n", __func__, pnetwork->network.Ssid.ssid); - - pie = pnetwork->network.IEs; - pie_len = pnetwork->network.IELength; - - p = cfg80211_find_ie(WLAN_EID_RSN, pie, pie_len); - if (p && p[1]) { - pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA2; - } else if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPA, - pie, pie_len)) { - pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA; - } else { - 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 */ -} - -/* show MCS rate, unit: 100Kbps */ -u16 rtw_mcs_rate23a(u8 rf_type, u8 bw_40MHz, u8 short_GI_20, u8 short_GI_40, - struct ieee80211_mcs_info *mcs) -{ - u16 max_rate = 0; - - if (rf_type == RF_1T1R) { - if (mcs->rx_mask[0] & BIT(7)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 1500 : 1350) : - ((short_GI_20) ? 722 : 650); - else if (mcs->rx_mask[0] & BIT(6)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 1350 : 1215) : - ((short_GI_20) ? 650 : 585); - else if (mcs->rx_mask[0] & BIT(5)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 1200 : 1080) : - ((short_GI_20) ? 578 : 520); - else if (mcs->rx_mask[0] & BIT(4)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 900 : 810) : - ((short_GI_20) ? 433 : 390); - else if (mcs->rx_mask[0] & BIT(3)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 600 : 540) : - ((short_GI_20) ? 289 : 260); - else if (mcs->rx_mask[0] & BIT(2)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 450 : 405) : - ((short_GI_20) ? 217 : 195); - else if (mcs->rx_mask[0] & BIT(1)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 300 : 270) : - ((short_GI_20) ? 144 : 130); - else if (mcs->rx_mask[0] & BIT(0)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 150 : 135) : - ((short_GI_20) ? 72 : 65); - } else { - if (mcs->rx_mask[1]) { - if (mcs->rx_mask[1] & BIT(7)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 3000 : 2700) : ((short_GI_20) ? 1444 : 1300); - else if (mcs->rx_mask[1] & BIT(6)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 2700 : 2430) : ((short_GI_20) ? 1300 : 1170); - else if (mcs->rx_mask[1] & BIT(5)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 2400 : 2160) : ((short_GI_20) ? 1156 : 1040); - else if (mcs->rx_mask[1] & BIT(4)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 1800 : 1620) : ((short_GI_20) ? 867 : 780); - else if (mcs->rx_mask[1] & BIT(3)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 1200 : 1080) : ((short_GI_20) ? 578 : 520); - else if (mcs->rx_mask[1] & BIT(2)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 900 : 810) : ((short_GI_20) ? 433 : 390); - else if (mcs->rx_mask[1] & BIT(1)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 600 : 540) : ((short_GI_20) ? 289 : 260); - else if (mcs->rx_mask[1] & BIT(0)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 300 : 270) : ((short_GI_20) ? 144 : 130); - } else { - if (mcs->rx_mask[0] & BIT(7)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 1500 : 1350) : ((short_GI_20) ? 722 : 650); - else if (mcs->rx_mask[0] & BIT(6)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 1350 : 1215) : ((short_GI_20) ? 650 : 585); - else if (mcs->rx_mask[0] & BIT(5)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 1200 : 1080) : ((short_GI_20) ? 578 : 520); - else if (mcs->rx_mask[0] & BIT(4)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 900 : 810) : ((short_GI_20) ? 433 : 390); - else if (mcs->rx_mask[0] & BIT(3)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 600 : 540) : ((short_GI_20) ? 289 : 260); - else if (mcs->rx_mask[0] & BIT(2)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 450 : 405) : ((short_GI_20) ? 217 : 195); - else if (mcs->rx_mask[0] & BIT(1)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 300 : 270) : ((short_GI_20) ? 144 : 130); - else if (mcs->rx_mask[0] & BIT(0)) - max_rate = (bw_40MHz) ? ((short_GI_40) ? 150 : 135) : ((short_GI_20) ? 72 : 65); - } - } - return max_rate; -} diff --git a/drivers/staging/rtl8723au/core/rtw_mlme.c b/drivers/staging/rtl8723au/core/rtw_mlme.c deleted file mode 100644 index a786fc4..0000000 --- a/drivers/staging/rtl8723au/core/rtw_mlme.c +++ /dev/null @@ -1,2314 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RTW_MLME_C_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <recv_osdep.h> -#include <xmit_osdep.h> -#include <hal_intf.h> -#include <mlme_osdep.h> -#include <sta_info.h> -#include <linux/ieee80211.h> -#include <wifi.h> -#include <wlan_bssdef.h> -#include <rtw_sreset.h> - -static struct wlan_network * -rtw_select_candidate_from_queue(struct mlme_priv *pmlmepriv); -static int rtw_do_join(struct rtw_adapter *padapter); - -static void rtw_init_mlme_timer(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - setup_timer(&pmlmepriv->assoc_timer, rtw23a_join_to_handler, - (unsigned long)padapter); - - setup_timer(&pmlmepriv->scan_to_timer, rtw_scan_timeout_handler23a, - (unsigned long)padapter); - - setup_timer(&pmlmepriv->dynamic_chk_timer, - rtw_dynamic_check_timer_handler, (unsigned long)padapter); - - setup_timer(&pmlmepriv->set_scan_deny_timer, - rtw_set_scan_deny_timer_hdl, (unsigned long)padapter); -} - -int rtw_init_mlme_priv23a(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - pmlmepriv->nic_hdl = padapter; - - pmlmepriv->fw_state = 0; - pmlmepriv->cur_network.network.ifmode = NL80211_IFTYPE_UNSPECIFIED; - /* 1: active, 0: pasive. Maybe someday we should rename this - varable to "active_mode" (Jeff) */ - pmlmepriv->scan_mode = SCAN_ACTIVE; - - spin_lock_init(&pmlmepriv->lock); - _rtw_init_queue23a(&pmlmepriv->scanned_queue); - - memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct cfg80211_ssid)); - - rtw_clear_scan_deny(padapter); - - rtw_init_mlme_timer(padapter); - return _SUCCESS; -} - -#ifdef CONFIG_8723AU_AP_MODE -static void rtw_free_mlme_ie_data(u8 **ppie, u32 *plen) -{ - if (*ppie) { - kfree(*ppie); - *plen = 0; - *ppie = NULL; - } -} -#endif - -void rtw23a_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv) -{ -#ifdef CONFIG_8723AU_AP_MODE - kfree(pmlmepriv->assoc_req); - kfree(pmlmepriv->assoc_rsp); - rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_req_ie, - &pmlmepriv->wps_probe_req_ie_len); -#endif -} - -void rtw_free_mlme_priv23a(struct mlme_priv *pmlmepriv) -{ - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "rtw_free_mlme_priv23a\n"); - - rtw23a_free_mlme_priv_ie_data(pmlmepriv); -} - -struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv, gfp_t gfp) -{ - struct wlan_network *pnetwork; - - pnetwork = kzalloc(sizeof(struct wlan_network), gfp); - if (pnetwork) { - INIT_LIST_HEAD(&pnetwork->list); - pnetwork->network_type = 0; - pnetwork->fixed = false; - pnetwork->last_scanned = jiffies; - pnetwork->join_res = 0; - } - - return pnetwork; -} - -static void _rtw_free_network23a(struct mlme_priv *pmlmepriv, - struct wlan_network *pnetwork) -{ - if (!pnetwork) - return; - - if (pnetwork->fixed == true) - return; - - list_del_init(&pnetwork->list); - - kfree(pnetwork); -} - -/* - return the wlan_network with the matching addr - - Shall be called under atomic context... to avoid possible racing condition... -*/ -struct wlan_network * -rtw_find_network23a(struct rtw_queue *scanned_queue, u8 *addr) -{ - struct list_head *phead, *plist; - struct wlan_network *pnetwork = NULL; - - if (is_zero_ether_addr(addr)) { - pnetwork = NULL; - goto exit; - } - - /* spin_lock_bh(&scanned_queue->lock); */ - - phead = get_list_head(scanned_queue); - plist = phead->next; - - while (plist != phead) { - pnetwork = container_of(plist, struct wlan_network, list); - - if (ether_addr_equal(addr, pnetwork->network.MacAddress)) - break; - - plist = plist->next; - } - - if (plist == phead) - pnetwork = NULL; - - /* spin_unlock_bh(&scanned_queue->lock); */ - -exit: - - return pnetwork; -} - -void rtw_free_network_queue23a(struct rtw_adapter *padapter) -{ - struct list_head *phead; - struct wlan_network *pnetwork, *ptmp; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct rtw_queue *scanned_queue = &pmlmepriv->scanned_queue; - - spin_lock_bh(&scanned_queue->lock); - phead = get_list_head(scanned_queue); - list_for_each_entry_safe(pnetwork, ptmp, phead, list) - _rtw_free_network23a(pmlmepriv, pnetwork); - spin_unlock_bh(&scanned_queue->lock); -} - -int rtw_if_up23a(struct rtw_adapter *padapter) -{ - int res; - - if (padapter->bDriverStopped || padapter->bSurpriseRemoved || - !check_fwstate(&padapter->mlmepriv, _FW_LINKED)) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "rtw_if_up23a:bDriverStopped(%d) OR bSurpriseRemoved(%d)\n", - padapter->bDriverStopped, padapter->bSurpriseRemoved); - res = false; - } else - res = true; - - return res; -} - -void rtw_generate_random_ibss23a(u8 *pibss) -{ - unsigned long curtime = jiffies; - - pibss[0] = 0x02; /* in ad-hoc mode bit1 must set to 1 */ - pibss[1] = 0x11; - pibss[2] = 0x87; - pibss[3] = curtime & 0xff;/* p[0]; */ - pibss[4] = (curtime >> 8) & 0xff;/* p[1]; */ - pibss[5] = (curtime >> 16) & 0xff;/* p[2]; */ -} - -void rtw_set_roaming(struct rtw_adapter *adapter, u8 to_roaming) -{ - if (to_roaming == 0) - adapter->mlmepriv.to_join = false; - adapter->mlmepriv.to_roaming = to_roaming; -} - -static void _rtw_roaming(struct rtw_adapter *padapter, - struct wlan_network *tgt_network) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_network *pnetwork; - int do_join_r; - - if (tgt_network) - pnetwork = tgt_network; - else - pnetwork = &pmlmepriv->cur_network; - - if (padapter->mlmepriv.to_roaming > 0) { - DBG_8723A("roaming from %s(%pM), length:%d\n", - pnetwork->network.Ssid.ssid, - pnetwork->network.MacAddress, - pnetwork->network.Ssid.ssid_len); - memcpy(&pmlmepriv->assoc_ssid, &pnetwork->network.Ssid, - sizeof(struct cfg80211_ssid)); - - pmlmepriv->assoc_by_bssid = false; - - while (1) { - do_join_r = rtw_do_join(padapter); - if (do_join_r == _SUCCESS) - break; - else { - DBG_8723A("roaming do_join return %d\n", - do_join_r); - pmlmepriv->to_roaming--; - - if (padapter->mlmepriv.to_roaming > 0) - continue; - else { - DBG_8723A("%s(%d) -to roaming fail, " - "indicate_disconnect\n", - __func__, __LINE__); - rtw_indicate_disconnect23a(padapter); - break; - } - } - } - } -} - -void rtw23a_roaming(struct rtw_adapter *padapter, - struct wlan_network *tgt_network) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - spin_lock_bh(&pmlmepriv->lock); - _rtw_roaming(padapter, tgt_network); - spin_unlock_bh(&pmlmepriv->lock); -} - -static void rtw_free_network_nolock(struct mlme_priv *pmlmepriv, - struct wlan_network *pnetwork) -{ - _rtw_free_network23a(pmlmepriv, pnetwork); -} - -bool rtw_is_same_ibss23a(struct rtw_adapter *adapter, - struct wlan_network *pnetwork) -{ - int ret; - struct security_priv *psecuritypriv = &adapter->securitypriv; - - if (psecuritypriv->dot11PrivacyAlgrthm != 0 && - pnetwork->network.Privacy == 0) - ret = false; - else if (psecuritypriv->dot11PrivacyAlgrthm == 0 && - pnetwork->network.Privacy == 1) - ret = false; - else - ret = true; - - return ret; -} - -inline int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b); -inline int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b) -{ - return (a->Ssid.ssid_len == b->Ssid.ssid_len) && - !memcmp(a->Ssid.ssid, b->Ssid.ssid, a->Ssid.ssid_len); -} - -int is_same_network23a(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst) -{ - u16 s_cap, d_cap; - - s_cap = src->capability; - d_cap = dst->capability; - - return ((src->Ssid.ssid_len == dst->Ssid.ssid_len) && - /* (src->DSConfig == dst->DSConfig) && */ - ether_addr_equal(src->MacAddress, dst->MacAddress) && - !memcmp(src->Ssid.ssid, dst->Ssid.ssid, src->Ssid.ssid_len) && - (s_cap & WLAN_CAPABILITY_IBSS) == - (d_cap & WLAN_CAPABILITY_IBSS) && - (s_cap & WLAN_CAPABILITY_ESS) == (d_cap & WLAN_CAPABILITY_ESS)); -} - -struct wlan_network * -rtw_get_oldest_wlan_network23a(struct rtw_queue *scanned_queue) -{ - struct list_head *phead; - struct wlan_network *pwlan; - struct wlan_network *oldest = NULL; - - phead = get_list_head(scanned_queue); - list_for_each_entry(pwlan, phead, list) { - if (pwlan->fixed != true) { - if (!oldest || time_after(oldest->last_scanned, - pwlan->last_scanned)) - oldest = pwlan; - } - } - - return oldest; -} - -void update_network23a(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src, - struct rtw_adapter *padapter, bool update_ie) -{ - u8 ss_ori = dst->SignalStrength; - u8 sq_ori = dst->SignalQuality; - long rssi_ori = dst->Rssi; - - u8 ss_smp = src->SignalStrength; - u8 sq_smp = src->SignalQuality; - long rssi_smp = src->Rssi; - - u8 ss_final; - u8 sq_final; - long rssi_final; - - DBG_8723A("%s %s(%pM, ch%u) ss_ori:%3u, sq_ori:%3u, rssi_ori:%3ld, " - "ss_smp:%3u, sq_smp:%3u, rssi_smp:%3ld\n", - __func__, src->Ssid.ssid, src->MacAddress, - src->DSConfig, ss_ori, sq_ori, rssi_ori, - ss_smp, sq_smp, rssi_smp - ); - - /* The rule below is 1/5 for sample value, 4/5 for history value */ - if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) && - is_same_network23a(&padapter->mlmepriv.cur_network.network, src)) { - /* Take the recvpriv's value for the connected AP*/ - ss_final = padapter->recvpriv.signal_strength; - sq_final = padapter->recvpriv.signal_qual; - /* the rssi value here is undecorated, and will be - used for antenna diversity */ - if (sq_smp != 101) /* from the right channel */ - rssi_final = (src->Rssi+dst->Rssi*4)/5; - else - rssi_final = rssi_ori; - } else { - if (sq_smp != 101) { /* from the right channel */ - ss_final = ((u32)src->SignalStrength + - (u32)dst->SignalStrength * 4) / 5; - sq_final = ((u32)src->SignalQuality + - (u32)dst->SignalQuality * 4) / 5; - rssi_final = src->Rssi+dst->Rssi * 4 / 5; - } else { - /* bss info not receiving from the right channel, use - the original RX signal infos */ - ss_final = dst->SignalStrength; - sq_final = dst->SignalQuality; - rssi_final = dst->Rssi; - } - - } - - if (update_ie) - memcpy(dst, src, get_wlan_bssid_ex_sz(src)); - - dst->SignalStrength = ss_final; - dst->SignalQuality = sq_final; - dst->Rssi = rssi_final; - - DBG_8723A("%s %s(%pM), SignalStrength:%u, SignalQuality:%u, " - "RawRSSI:%ld\n", __func__, dst->Ssid.ssid, dst->MacAddress, - dst->SignalStrength, dst->SignalQuality, dst->Rssi); -} - -static void update_current_network(struct rtw_adapter *adapter, - struct wlan_bssid_ex *pnetwork) -{ - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - - if (check_fwstate(pmlmepriv, _FW_LINKED) && - is_same_network23a(&pmlmepriv->cur_network.network, pnetwork)) { - update_network23a(&pmlmepriv->cur_network.network, - pnetwork, adapter, true); - - rtw_update_protection23a(adapter, - pmlmepriv->cur_network.network.IEs, - pmlmepriv->cur_network.network.IELength); - } -} - -/* - -Caller must hold pmlmepriv->lock first. - -*/ -static void rtw_update_scanned_network(struct rtw_adapter *adapter, - struct wlan_bssid_ex *target) -{ - struct list_head *plist, *phead; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct wlan_network *pnetwork = NULL; - struct wlan_network *oldest = NULL; - struct rtw_queue *queue = &pmlmepriv->scanned_queue; - u32 bssid_ex_sz; - int found = 0; - - spin_lock_bh(&queue->lock); - phead = get_list_head(queue); - list_for_each(plist, phead) { - pnetwork = container_of(plist, struct wlan_network, list); - - if (is_same_network23a(&pnetwork->network, target)) { - found = 1; - break; - } - if (!oldest || time_after(oldest->last_scanned, - pnetwork->last_scanned)) - oldest = pnetwork; - } - - /* If we didn't find a match, then get a new network slot to initialize - * with this beacon's information */ - if (!found) { - pnetwork = rtw_alloc_network(pmlmepriv, GFP_ATOMIC); - if (!pnetwork) { - if (!oldest) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "something wrong here\n"); - goto exit; - } - pnetwork = oldest; - } else - list_add_tail(&pnetwork->list, &queue->queue); - - bssid_ex_sz = get_wlan_bssid_ex_sz(target); - target->Length = bssid_ex_sz; - memcpy(&pnetwork->network, target, bssid_ex_sz); - - /* variable initialize */ - pnetwork->fixed = false; - pnetwork->last_scanned = jiffies; - - pnetwork->network_type = 0; - pnetwork->join_res = 0; - - /* bss info not receiving from the right channel */ - if (pnetwork->network.SignalQuality == 101) - pnetwork->network.SignalQuality = 0; - } else { - /* - * we have an entry and we are going to update it. But - * this entry may be already expired. In this case we - * do the same as we found a new net and call the - * new_net handler - */ - bool update_ie = true; - - pnetwork->last_scanned = jiffies; - - /* target.reserved == 1, means that scanned network is - * a bcn frame. */ - if (pnetwork->network.IELength > target->IELength && - target->reserved == 1) - update_ie = false; - - update_network23a(&pnetwork->network, target, adapter, - update_ie); - } - -exit: - spin_unlock_bh(&queue->lock); -} - -static void rtw_add_network(struct rtw_adapter *adapter, - struct wlan_bssid_ex *pnetwork) -{ - update_current_network(adapter, pnetwork); - rtw_update_scanned_network(adapter, pnetwork); -} - -/* select the desired network based on the capability of the (i)bss. */ -/* check items: (1) security */ -/* (2) network_type */ -/* (3) WMM */ -/* (4) HT */ -/* (5) others */ -static int rtw_is_desired_network(struct rtw_adapter *adapter, - struct wlan_network *pnetwork) -{ - struct security_priv *psecuritypriv = &adapter->securitypriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - u32 desired_encmode; - u32 privacy; - int bselected = true; - - desired_encmode = psecuritypriv->ndisencryptstatus; - privacy = pnetwork->network.Privacy; - - if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) { - if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPA, - pnetwork->network.IEs, - pnetwork->network.IELength)) - return true; - else - return false; - } - if (adapter->registrypriv.wifi_spec == 1) { - /* for correct flow of 8021X to do.... */ - if (desired_encmode == Ndis802_11EncryptionDisabled && - privacy != 0) - bselected = false; - } - - if (desired_encmode != Ndis802_11EncryptionDisabled && privacy == 0) { - DBG_8723A("desired_encmode: %d, privacy: %d\n", - desired_encmode, privacy); - bselected = false; - } - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { - if (pnetwork->network.ifmode != - pmlmepriv->cur_network.network.ifmode) - bselected = false; - } - - return bselected; -} - -void rtw_survey_event_cb23a(struct rtw_adapter *adapter, const u8 *pbuf) -{ - u32 len; - struct wlan_bssid_ex *pnetwork; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct survey_event *survey = (struct survey_event *)pbuf; - - pnetwork = survey->bss; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "rtw_survey_event_cb23a, ssid=%s\n", 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_, - "****rtw_survey_event_cb23a: return a wrong bss ***\n"); - return; - } - - spin_lock_bh(&pmlmepriv->lock); - - /* update IBSS_network 's timestamp */ - if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { - if (ether_addr_equal(pmlmepriv->cur_network.network.MacAddress, - pnetwork->MacAddress)) { - struct wlan_network *ibss_wlan; - - pmlmepriv->cur_network.network.beacon_interval = - pnetwork->beacon_interval; - pmlmepriv->cur_network.network.capability = - pnetwork->capability; - pmlmepriv->cur_network.network.tsf = pnetwork->tsf; - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - ibss_wlan = rtw_find_network23a( - &pmlmepriv->scanned_queue, - pnetwork->MacAddress); - if (ibss_wlan) { - pmlmepriv->cur_network.network.beacon_interval = - ibss_wlan->network.beacon_interval; - pmlmepriv->cur_network.network.capability = - ibss_wlan->network.capability; - pmlmepriv->cur_network.network.tsf = - ibss_wlan->network.tsf; - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - goto exit; - } - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - } - } - - /* lock pmlmepriv->lock when you accessing network_q */ - if (!check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) { - if (pnetwork->Ssid.ssid[0] == 0) - pnetwork->Ssid.ssid_len = 0; - - rtw_add_network(adapter, pnetwork); - } - -exit: - - spin_unlock_bh(&pmlmepriv->lock); - - kfree(survey->bss); - survey->bss = NULL; -} - -void -rtw_surveydone_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf) -{ - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; - int ret; - - spin_lock_bh(&pmlmepriv->lock); - - if (pmlmepriv->wps_probe_req_ie) { - pmlmepriv->wps_probe_req_ie_len = 0; - kfree(pmlmepriv->wps_probe_req_ie); - pmlmepriv->wps_probe_req_ie = NULL; - } - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "rtw_surveydone_event_callback23a: fw_state:%x\n", - 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); - - if (pmlmepriv->to_join == true) { - set_fwstate(pmlmepriv, _FW_UNDER_LINKING); - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { - ret = rtw_select_and_join_from_scanned_queue23a( - pmlmepriv); - if (ret != _SUCCESS) - rtw_do_join_adhoc(adapter); - } else { - pmlmepriv->to_join = false; - ret = rtw_select_and_join_from_scanned_queue23a( - pmlmepriv); - if (ret != _SUCCESS) { - DBG_8723A("try_to_join, but select scanning " - "queue fail, to_roaming:%d\n", - adapter->mlmepriv.to_roaming); - if (adapter->mlmepriv.to_roaming) { - if (--pmlmepriv->to_roaming == 0 || - rtw_sitesurvey_cmd23a( - adapter, - &pmlmepriv->assoc_ssid, 1, - NULL, 0) != _SUCCESS) { - rtw_set_roaming(adapter, 0); - rtw_free_assoc_resources23a( - adapter, 1); - rtw_indicate_disconnect23a( - adapter); - } else - pmlmepriv->to_join = true; - } - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); - } - } - } - - spin_unlock_bh(&pmlmepriv->lock); - - rtw_os_xmit_schedule23a(adapter); - - if (pmlmeext->sitesurvey_res.bss_cnt == 0) - rtw_sreset_reset(adapter); - - rtw_cfg80211_surveydone_event_callback(adapter); -} - -static void free_scanqueue(struct mlme_priv *pmlmepriv) -{ - struct wlan_network *pnetwork, *ptemp; - struct rtw_queue *scan_queue = &pmlmepriv->scanned_queue; - struct list_head *phead; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, "+free_scanqueue\n"); - spin_lock_bh(&scan_queue->lock); - phead = get_list_head(scan_queue); - list_for_each_entry_safe(pnetwork, ptemp, phead, list) { - pnetwork->fixed = false; - _rtw_free_network23a(pmlmepriv, pnetwork); - } - spin_unlock_bh(&scan_queue->lock); -} - -/* - *rtw_free_assoc_resources23a: the caller has to lock pmlmepriv->lock - */ -void rtw_free_assoc_resources23a(struct rtw_adapter *adapter, - int lock_scanned_queue) -{ - struct wlan_network *pwlan; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct sta_priv *pstapriv = &adapter->stapriv; - struct wlan_network *tgt_network = &pmlmepriv->cur_network; - struct sta_info *psta; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, - "+rtw_free_assoc_resources23a\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)) { - psta = rtw_get_stainfo23a(&adapter->stapriv, - tgt_network->network.MacAddress); - - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo23a(adapter, psta); - spin_unlock_bh(&pstapriv->sta_hash_lock); - } - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE | - WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE)) { - rtw_free_all_stainfo23a(adapter); - - psta = rtw_get_bcmc_stainfo23a(adapter); - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo23a(adapter, psta); - spin_unlock_bh(&pstapriv->sta_hash_lock); - - rtw_init_bcmc_stainfo23a(adapter); - } - - if (lock_scanned_queue) - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - - pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue, - tgt_network->network.MacAddress); - if (pwlan) - pwlan->fixed = false; - else - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "rtw_free_assoc_resources23a : pwlan== NULL\n"); - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) && - adapter->stapriv.asoc_sta_count == 1) - rtw_free_network_nolock(pmlmepriv, pwlan); - - if (lock_scanned_queue) - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - - pmlmepriv->key_mask = 0; -} - -/* -*rtw_indicate_connect23a: the caller has to lock pmlmepriv->lock -*/ -void rtw_indicate_connect23a(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "+rtw_indicate_connect23a\n"); - - pmlmepriv->to_join = false; - - if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) { - set_fwstate(pmlmepriv, _FW_LINKED); - - rtw_cfg80211_indicate_connect(padapter); - - netif_carrier_on(padapter->pnetdev); - - if (padapter->pid[2] != 0) - kill_pid(find_vpid(padapter->pid[2]), SIGALRM, 1); - } - - rtw_set_roaming(padapter, 0); - - rtw_set_scan_deny(padapter, 3000); - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "-rtw_indicate_connect23a: fw_state=0x%08x\n", - get_fwstate(pmlmepriv)); -} - -/* - *rtw_indicate_disconnect23a: the caller has to lock pmlmepriv->lock - */ -void rtw_indicate_disconnect23a(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "+rtw_indicate_disconnect23a\n"); - - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING|WIFI_UNDER_WPS); - - /* DBG_8723A("clear wps when %s\n", __func__); */ - - if (padapter->mlmepriv.to_roaming > 0) - _clr_fwstate_(pmlmepriv, _FW_LINKED); - - if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) || - padapter->mlmepriv.to_roaming <= 0) { - rtw_os_indicate_disconnect23a(padapter); - - /* set ips_deny_time to avoid enter IPS before LPS leave */ - padapter->pwrctrlpriv.ips_deny_time = - jiffies + msecs_to_jiffies(3000); - - _clr_fwstate_(pmlmepriv, _FW_LINKED); - - rtw_clear_scan_deny(padapter); - } - - rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_DISCONNECT, 1); -} - -void rtw_scan_abort23a(struct rtw_adapter *adapter) -{ - unsigned long start; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; - - start = jiffies; - pmlmeext->scan_abort = true; - while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) && - jiffies_to_msecs(jiffies - start) <= 200) { - if (adapter->bDriverStopped || adapter->bSurpriseRemoved) - break; - - DBG_8723A("%s(%s): fw_state = _FW_UNDER_SURVEY!\n", - __func__, adapter->pnetdev->name); - msleep(20); - } - - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) { - if (!adapter->bDriverStopped && !adapter->bSurpriseRemoved) - DBG_8723A("%s(%s): waiting for scan_abort time out!\n", - __func__, adapter->pnetdev->name); - rtw_cfg80211_indicate_scan_done(wdev_to_priv(adapter->rtw_wdev), - true); - } - pmlmeext->scan_abort = false; -} - -static struct sta_info * -rtw_joinbss_update_stainfo(struct rtw_adapter *padapter, - struct wlan_network *pnetwork) -{ - int i; - struct sta_info *bmc_sta, *psta; - struct recv_reorder_ctrl *preorder_ctrl; - struct sta_priv *pstapriv = &padapter->stapriv; - - psta = rtw_get_stainfo23a(pstapriv, pnetwork->network.MacAddress); - if (!psta) - psta = rtw_alloc_stainfo23a(pstapriv, - pnetwork->network.MacAddress, - GFP_ATOMIC); - - if (psta) { /* update ptarget_sta */ - DBG_8723A("%s\n", __func__); - - psta->aid = pnetwork->join_res; - psta->mac_id = 0; - - /* sta mode */ - rtl8723a_SetHalODMVar(padapter, HAL_ODM_STA_INFO, psta, true); - - /* security related */ - if (padapter->securitypriv.dot11AuthAlgrthm == - dot11AuthAlgrthm_8021X) { - padapter->securitypriv.binstallGrpkey = 0; - padapter->securitypriv.busetkipkey = 0; - - psta->ieee8021x_blocked = true; - psta->dot118021XPrivacy = - padapter->securitypriv.dot11PrivacyAlgrthm; - - memset(&psta->dot118021x_UncstKey, 0, - sizeof (union Keytype)); - - memset(&psta->dot11tkiprxmickey, 0, - sizeof (union Keytype)); - memset(&psta->dot11tkiptxmickey, 0, - sizeof (union Keytype)); - - memset(&psta->dot11txpn, 0, sizeof (union pn48)); - memset(&psta->dot11rxpn, 0, sizeof (union pn48)); - } - - /* Commented by Albert 2012/07/21 */ - /* When doing the WPS, the wps_ie_len won't equal to 0 */ - /* And the Wi-Fi driver shouldn't allow the data packet - to be transmitted. */ - if (padapter->securitypriv.wps_ie_len != 0) { - psta->ieee8021x_blocked = true; - padapter->securitypriv.wps_ie_len = 0; - } - - /* for A-MPDU Rx reordering buffer control for bmc_sta & - * sta_info */ - /* if A-MPDU Rx is enabled, resetting - rx_ordering_ctrl wstart_b(indicate_seq) to default - value = 0xffff */ - /* todo: check if AP can send A-MPDU packets */ - for (i = 0; i < 16 ; i++) { - /* preorder_ctrl = &precvpriv->recvreorder_ctrl[i]; */ - preorder_ctrl = &psta->recvreorder_ctrl[i]; - preorder_ctrl->enable = false; - preorder_ctrl->indicate_seq = 0xffff; - preorder_ctrl->wend_b = 0xffff; - /* max_ampdu_sz; ex. 32(kbytes) -> wsize_b = 32 */ - preorder_ctrl->wsize_b = 64; - } - - bmc_sta = rtw_get_bcmc_stainfo23a(padapter); - if (bmc_sta) { - for (i = 0; i < 16 ; i++) { - preorder_ctrl = &bmc_sta->recvreorder_ctrl[i]; - preorder_ctrl->enable = false; - preorder_ctrl->indicate_seq = 0xffff; - preorder_ctrl->wend_b = 0xffff; - /* max_ampdu_sz; ex. 32(kbytes) -> - wsize_b = 32 */ - preorder_ctrl->wsize_b = 64; - } - } - - /* misc. */ - update_sta_info23a(padapter, psta); - - } - - return psta; -} - -/* pnetwork : returns from rtw23a_joinbss_event_cb */ -/* ptarget_wlan: found from scanned_queue */ -static void -rtw_joinbss_update_network23a(struct rtw_adapter *padapter, - struct wlan_network *ptarget_wlan, - struct wlan_network *pnetwork) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_network *cur_network = &pmlmepriv->cur_network; - - DBG_8723A("%s\n", __func__); - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "fw_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 */ - cur_network->network.IELength = ptarget_wlan->network.IELength; - memcpy(&cur_network->network.IEs[0], &ptarget_wlan->network.IEs[0], - MAX_IE_SZ); - - cur_network->network.capability = ptarget_wlan->network.capability; - cur_network->network.beacon_interval = - ptarget_wlan->network.beacon_interval; - cur_network->network.tsf = ptarget_wlan->network.tsf; - - rtw_set_signal_stat_timer(&padapter->recvpriv); - padapter->recvpriv.signal_strength = - ptarget_wlan->network.SignalStrength; - padapter->recvpriv.signal_qual = ptarget_wlan->network.SignalQuality; - /* - * the ptarget_wlan->network.Rssi is raw data, we use - * ptarget_wlan->network.SignalStrength instead (has scaled) - */ - DBG_8723A("%s signal_strength:%3u, signal_qual:%3u\n", - __func__, padapter->recvpriv.signal_strength, - padapter->recvpriv.signal_qual); - rtw_set_signal_stat_timer(&padapter->recvpriv); - - /* update fw_state will clr _FW_UNDER_LINKING here indirectly */ - switch (pnetwork->network.ifmode) { - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_STATION: - if (pmlmepriv->fw_state & WIFI_UNDER_WPS) - pmlmepriv->fw_state = WIFI_STATION_STATE|WIFI_UNDER_WPS; - else - pmlmepriv->fw_state = WIFI_STATION_STATE; - break; - case NL80211_IFTYPE_ADHOC: - pmlmepriv->fw_state = WIFI_ADHOC_STATE; - break; - default: - pmlmepriv->fw_state = WIFI_NULL_STATE; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "Invalid network_mode\n"); - break; - } - - rtw_update_protection23a(padapter, cur_network->network.IEs, - cur_network->network.IELength); - - rtw_update_ht_cap23a(padapter, cur_network->network.IEs, - cur_network->network.IELength); -} - -/* - * Notes: - * the function could be > passive_level (the same context as Rx tasklet) - * pnetwork : returns from rtw23a_joinbss_event_cb - * ptarget_wlan: found from scanned_queue - * if join_res > 0, for (fw_state==WIFI_STATION_STATE), - * we check if "ptarget_sta" & "ptarget_wlan" exist. - * if join_res > 0, for (fw_state==WIFI_ADHOC_STATE), - * we only check if "ptarget_wlan" exist. - * if join_res > 0, update "cur_network->network" from "pnetwork->network" - * if (ptarget_wlan !=NULL). - */ - -void rtw_joinbss_event_prehandle23a(struct rtw_adapter *adapter, u8 *pbuf) -{ - struct sta_info *ptarget_sta, *pcur_sta; - struct sta_priv *pstapriv = &adapter->stapriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct wlan_network *pnetwork = (struct wlan_network *)pbuf; - struct wlan_network *cur_network = &pmlmepriv->cur_network; - struct wlan_network *pcur_wlan, *ptarget_wlan = NULL; - bool the_same_macaddr; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "joinbss event call back received with res=%d\n", - pnetwork->join_res); - - if (pmlmepriv->assoc_ssid.ssid_len == 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_, - "@@@@@ rtw23a_joinbss_event_cb for SSid:%s\n", - pmlmepriv->assoc_ssid.ssid); - } - - if (ether_addr_equal(pnetwork->network.MacAddress, - cur_network->network.MacAddress)) - the_same_macaddr = true; - else - the_same_macaddr = false; - - 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_, - "***joinbss_evt_callback return a wrong bss ***\n"); - return; - } - - spin_lock_bh(&pmlmepriv->lock); - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "rtw23a_joinbss_event_cb !! _enter_critical\n"); - - if (pnetwork->join_res > 0) { - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) { - /* s1. find ptarget_wlan */ - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - if (the_same_macaddr) { - ptarget_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, cur_network->network.MacAddress); - } else { - pcur_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, cur_network->network.MacAddress); - if (pcur_wlan) - pcur_wlan->fixed = false; - - pcur_sta = rtw_get_stainfo23a(pstapriv, cur_network->network.MacAddress); - if (pcur_sta) { - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo23a(adapter, - pcur_sta); - spin_unlock_bh(&pstapriv->sta_hash_lock); - } - - ptarget_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, pnetwork->network.MacAddress); - if (check_fwstate(pmlmepriv, - WIFI_STATION_STATE)) { - if (ptarget_wlan) - ptarget_wlan->fixed = - true; - } - } - - } else { - ptarget_wlan = rtw_find_network23a( - &pmlmepriv->scanned_queue, - pnetwork->network.MacAddress); - if (check_fwstate(pmlmepriv, - WIFI_STATION_STATE)) { - if (ptarget_wlan) - ptarget_wlan->fixed = true; - } - } - - /* s2. update cur_network */ - if (ptarget_wlan) - rtw_joinbss_update_network23a(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; - } - - /* s3. find ptarget_sta & update ptarget_sta after - update cur_network only for station mode */ - 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; - } - } - - /* s4. indicate connect */ - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) - rtw_indicate_connect23a(adapter); - else { - /* adhoc mode will rtw_indicate_connect23a - when rtw_stassoc_event_callback23a */ - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "adhoc mode, fw_state:%x\n", - get_fwstate(pmlmepriv)); - } - - /* s5. Cancle assoc_timer */ - del_timer_sync(&pmlmepriv->assoc_timer); - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "Cancle assoc_timer\n"); - } else { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "rtw23a_joinbss_event_cb err: fw_state:%x\n", - get_fwstate(pmlmepriv)); - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - goto ignore_joinbss_callback; - } - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - } else if (pnetwork->join_res == -4) { - rtw_reset_securitypriv23a(adapter); - mod_timer(&pmlmepriv->assoc_timer, - jiffies + msecs_to_jiffies(1)); - - /* rtw_free_assoc_resources23a(adapter, 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)); - _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)); - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); - } - -ignore_joinbss_callback: - - spin_unlock_bh(&pmlmepriv->lock); -} - -void rtw23a_joinbss_event_cb(struct rtw_adapter *adapter, const u8 *pbuf) -{ - struct wlan_network *pnetwork = (struct wlan_network *)pbuf; - - mlmeext_joinbss_event_callback23a(adapter, pnetwork->join_res); - - rtw_os_xmit_schedule23a(adapter); -} - -void rtw_stassoc_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf) -{ - struct sta_info *psta; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct stassoc_event *pstassoc = (struct stassoc_event *)pbuf; - struct wlan_network *cur_network = &pmlmepriv->cur_network; - struct wlan_network *ptarget_wlan; - - if (rtw_access_ctrl23a(adapter, pstassoc->macaddr) == false) - return; - -#ifdef CONFIG_8723AU_AP_MODE - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - psta = rtw_get_stainfo23a(&adapter->stapriv, pstassoc->macaddr); - if (psta) { - /* bss_cap_update_on_sta_join23a(adapter, psta); */ - /* sta_info_update23a(adapter, psta); */ - ap_sta_info_defer_update23a(adapter, psta); - } - return; - } -#endif - /* for AD-HOC mode */ - psta = rtw_get_stainfo23a(&adapter->stapriv, pstassoc->macaddr); - if (psta != NULL) { - /* the sta have been in sta_info_queue => do nothing */ - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "Error: rtw_stassoc_event_callback23a: sta has been in sta_hash_queue\n"); - /* between drv has received this event before and - fw have not yet to set key to CAM_ENTRY) */ - return; - } - - psta = rtw_alloc_stainfo23a(&adapter->stapriv, pstassoc->macaddr, - GFP_KERNEL); - if (!psta) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "Can't alloc sta_info when rtw_stassoc_event_callback23a\n"); - return; - } - - /* to do : init sta_info variable */ - psta->qos_option = 0; - psta->mac_id = (uint)pstassoc->cam_id; - /* psta->aid = (uint)pstassoc->cam_id; */ - DBG_8723A("%s\n", __func__); - /* for ad-hoc mode */ - rtl8723a_SetHalODMVar(adapter, HAL_ODM_STA_INFO, psta, true); - - if (adapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) - psta->dot118021XPrivacy = - adapter->securitypriv.dot11PrivacyAlgrthm; - - psta->ieee8021x_blocked = false; - - spin_lock_bh(&pmlmepriv->lock); - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { - if (adapter->stapriv.asoc_sta_count == 2) { - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - ptarget_wlan = - rtw_find_network23a(&pmlmepriv->scanned_queue, - cur_network->network.MacAddress); - if (ptarget_wlan) - ptarget_wlan->fixed = true; - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - /* a sta + bc/mc_stainfo (not Ibss_stainfo) */ - rtw_indicate_connect23a(adapter); - } - } - - spin_unlock_bh(&pmlmepriv->lock); - - mlmeext_sta_add_event_callback23a(adapter, psta); -} - -void rtw_stadel_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf) -{ - int mac_id; - struct sta_info *psta; - struct wlan_network *pwlan; - struct wlan_bssid_ex *pdev_network; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct stadel_event *pstadel = (struct stadel_event *)pbuf; - struct sta_priv *pstapriv = &adapter->stapriv; - struct wlan_network *tgt_network = &pmlmepriv->cur_network; - - psta = rtw_get_stainfo23a(&adapter->stapriv, pstadel->macaddr); - if (psta) - mac_id = psta->mac_id; - else - mac_id = pstadel->mac_id; - - DBG_8723A("%s(mac_id=%d)=%pM\n", __func__, mac_id, pstadel->macaddr); - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) - return; - - mlmeext_sta_del_event_callback23a(adapter); - - spin_lock_bh(&pmlmepriv->lock); - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - if (adapter->mlmepriv.to_roaming > 0) { - /* this stadel_event is caused by roaming, - decrease to_roaming */ - pmlmepriv->to_roaming--; - } else if (adapter->mlmepriv.to_roaming == 0) - rtw_set_roaming(adapter, adapter->registrypriv.max_roaming_times); - if (*((u16 *)pstadel->rsvd) != WLAN_REASON_EXPIRATION_CHK) - rtw_set_roaming(adapter, 0); /* don't roam */ - - rtw_free_uc_swdec_pending_queue23a(adapter); - - rtw_free_assoc_resources23a(adapter, 1); - rtw_indicate_disconnect23a(adapter); - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - /* remove the network entry in scanned_queue */ - pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue, - tgt_network->network.MacAddress); - if (pwlan) { - pwlan->fixed = false; - rtw_free_network_nolock(pmlmepriv, pwlan); - } - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - - _rtw_roaming(adapter, tgt_network); - } - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { - - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo23a(adapter, psta); - spin_unlock_bh(&pstapriv->sta_hash_lock); - - /* a sta + bc/mc_stainfo (not Ibss_stainfo) */ - if (adapter->stapriv.asoc_sta_count == 1) { - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - /* free old ibss network */ - /* pwlan = rtw_find_network23a( - &pmlmepriv->scanned_queue, pstadel->macaddr); */ - pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue, - tgt_network->network.MacAddress); - if (pwlan) { - pwlan->fixed = false; - rtw_free_network_nolock(pmlmepriv, pwlan); - } - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - /* re-create ibss */ - pdev_network = &adapter->registrypriv.dev_network; - - memcpy(pdev_network, &tgt_network->network, - get_wlan_bssid_ex_sz(&tgt_network->network)); - - rtw_do_join_adhoc(adapter); - } - } - - spin_unlock_bh(&pmlmepriv->lock); -} - -/* -* rtw23a_join_to_handler - Timeout/failure handler for CMD JoinBss -* @adapter: pointer to _adapter structure -*/ -void rtw23a_join_to_handler (unsigned long data) -{ - struct rtw_adapter *adapter = (struct rtw_adapter *)data; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - int do_join_r; - - DBG_8723A("%s, fw_state=%x\n", __func__, get_fwstate(pmlmepriv)); - - if (adapter->bDriverStopped || adapter->bSurpriseRemoved) - return; - - spin_lock_bh(&pmlmepriv->lock); - - if (adapter->mlmepriv.to_roaming > 0) { - /* join timeout caused by roaming */ - while (1) { - pmlmepriv->to_roaming--; - if (adapter->mlmepriv.to_roaming != 0) { - /* try another */ - DBG_8723A("%s try another roaming\n", __func__); - do_join_r = rtw_do_join(adapter); - if (do_join_r != _SUCCESS) { - DBG_8723A("%s roaming do_join return " - "%d\n", __func__ , do_join_r); - continue; - } - break; - } else { - DBG_8723A("%s We've try roaming but fail\n", - __func__); - rtw_indicate_disconnect23a(adapter); - break; - } - } - } else { - rtw_indicate_disconnect23a(adapter); - free_scanqueue(pmlmepriv);/* */ - - /* indicate disconnect for the case that join_timeout and - check_fwstate != FW_LINKED */ - rtw_cfg80211_indicate_disconnect(adapter); - } - - spin_unlock_bh(&pmlmepriv->lock); - -} - -/* -* rtw_scan_timeout_handler23a - Timeout/Failure handler for CMD SiteSurvey -* @data: pointer to _adapter structure -*/ -void rtw_scan_timeout_handler23a(unsigned long data) -{ - struct rtw_adapter *adapter = (struct rtw_adapter *)data; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - - DBG_8723A("%s(%s): fw_state =%x\n", __func__, adapter->pnetdev->name, - get_fwstate(pmlmepriv)); - - spin_lock_bh(&pmlmepriv->lock); - - _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY); - - spin_unlock_bh(&pmlmepriv->lock); - - rtw_cfg80211_indicate_scan_done(wdev_to_priv(adapter->rtw_wdev), true); -} - -void rtw_dynamic_check_timer_handler(unsigned long data) -{ - struct rtw_adapter *adapter = (struct rtw_adapter *)data; - - if (adapter->hw_init_completed == false) - goto out; - - if (adapter->bDriverStopped == true || - adapter->bSurpriseRemoved == true) - goto out; - - if (adapter->net_closed == true) - goto out; - - rtw_dynamic_chk_wk_cmd23a(adapter); - -out: - mod_timer(&adapter->mlmepriv.dynamic_chk_timer, - jiffies + msecs_to_jiffies(2000)); -} - -inline bool rtw_is_scan_deny(struct rtw_adapter *adapter) -{ - struct mlme_priv *mlmepriv = &adapter->mlmepriv; - - return (atomic_read(&mlmepriv->set_scan_deny) != 0) ? true : false; -} - -void rtw_clear_scan_deny(struct rtw_adapter *adapter) -{ - struct mlme_priv *mlmepriv = &adapter->mlmepriv; - - atomic_set(&mlmepriv->set_scan_deny, 0); -} - -void rtw_set_scan_deny_timer_hdl(unsigned long data) -{ - struct rtw_adapter *adapter = (struct rtw_adapter *)data; - - rtw_clear_scan_deny(adapter); -} - -void rtw_set_scan_deny(struct rtw_adapter *adapter, u32 ms) -{ - struct mlme_priv *mlmepriv = &adapter->mlmepriv; - - atomic_set(&mlmepriv->set_scan_deny, 1); - mod_timer(&mlmepriv->set_scan_deny_timer, - jiffies + msecs_to_jiffies(ms)); -} - -#if defined(IEEE80211_SCAN_RESULT_EXPIRE) -#define RTW_SCAN_RESULT_EXPIRE \ - ((IEEE80211_SCAN_RESULT_EXPIRE / (HZ*1000)) - 1000) /* 3000 -1000 */ -#else -#define RTW_SCAN_RESULT_EXPIRE 2000 -#endif - -/* -* Select a new join candidate from the original @param candidate and -* @param competitor -* @return true: candidate is updated -* @return false: candidate is not updated -*/ -static int rtw_check_join_candidate(struct mlme_priv *pmlmepriv, - struct wlan_network **candidate, - struct wlan_network *competitor) -{ - int updated = false; - struct rtw_adapter *adapter; - - adapter = container_of(pmlmepriv, struct rtw_adapter, mlmepriv); - - /* check bssid, if needed */ - if (pmlmepriv->assoc_by_bssid == true) { - if (!ether_addr_equal(competitor->network.MacAddress, - pmlmepriv->assoc_bssid)) - goto exit; - } - - /* check ssid, if needed */ - if (pmlmepriv->assoc_ssid.ssid_len) { - if (competitor->network.Ssid.ssid_len != - pmlmepriv->assoc_ssid.ssid_len || - memcmp(competitor->network.Ssid.ssid, - pmlmepriv->assoc_ssid.ssid, - pmlmepriv->assoc_ssid.ssid_len)) - goto exit; - } - - if (rtw_is_desired_network(adapter, competitor) == false) - goto exit; - - if (adapter->mlmepriv.to_roaming > 0) { - unsigned int passed; - - passed = jiffies_to_msecs(jiffies - competitor->last_scanned); - if (passed >= RTW_SCAN_RESULT_EXPIRE || - is_same_ess(&competitor->network, - &pmlmepriv->cur_network.network) == false) - goto exit; - } - - if (!*candidate || - (*candidate)->network.Rssi<competitor->network.Rssi) { - *candidate = competitor; - updated = true; - } - - if (updated) { - DBG_8723A("[by_bssid:%u][assoc_ssid:%s][to_roaming:%u] new candidate: %s(%pM) rssi:%d\n", - pmlmepriv->assoc_by_bssid, - pmlmepriv->assoc_ssid.ssid, - adapter->mlmepriv.to_roaming, - (*candidate)->network.Ssid.ssid, - (*candidate)->network.MacAddress, - (int)(*candidate)->network.Rssi); - } - -exit: - return updated; -} - -/* -Calling context: -The caller of the sub-routine will be in critical section... - -The caller must hold the following spinlock - -pmlmepriv->lock - -*/ - -static int rtw_do_join(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - int ret; - - pmlmepriv->cur_network.join_res = -2; - - set_fwstate(pmlmepriv, _FW_UNDER_LINKING); - - pmlmepriv->to_join = true; - - ret = rtw_select_and_join_from_scanned_queue23a(pmlmepriv); - if (ret == _SUCCESS) { - pmlmepriv->to_join = false; - } else { - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { - /* switch to ADHOC_MASTER */ - ret = rtw_do_join_adhoc(padapter); - if (ret != _SUCCESS) - goto exit; - } else { - /* can't associate ; reset under-linking */ - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); - - ret = _FAIL; - pmlmepriv->to_join = false; - } - } - -exit: - return ret; -} - -static struct wlan_network * -rtw_select_candidate_from_queue(struct mlme_priv *pmlmepriv) -{ - struct wlan_network *pnetwork, *ptmp, *candidate = NULL; - struct rtw_queue *queue = &pmlmepriv->scanned_queue; - struct list_head *phead; - - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - phead = get_list_head(queue); - list_for_each_entry_safe(pnetwork, ptmp, phead, list) - rtw_check_join_candidate(pmlmepriv, &candidate, pnetwork); - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - - return candidate; -} - - -int rtw_do_join_adhoc(struct rtw_adapter *adapter) -{ - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct wlan_bssid_ex *pdev_network; - u8 *ibss; - int ret; - - pdev_network = &adapter->registrypriv.dev_network; - ibss = adapter->registrypriv.dev_network.MacAddress; - - _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 cfg80211_ssid)); - - rtw_update_registrypriv_dev_network23a(adapter); - rtw_generate_random_ibss23a(ibss); - - pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE; - - ret = rtw_createbss_cmd23a(adapter); - if (ret != _SUCCESS) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "Error =>rtw_createbss_cmd23a status FAIL\n"); - } else { - pmlmepriv->to_join = false; - } - - return ret; -} - -int rtw_do_join_network(struct rtw_adapter *adapter, - struct wlan_network *candidate) -{ - int ret; - - /* check for situation of _FW_LINKED */ - if (check_fwstate(&adapter->mlmepriv, _FW_LINKED)) { - DBG_8723A("%s: _FW_LINKED while ask_for_joinbss!\n", __func__); - - rtw_disassoc_cmd23a(adapter, 0, true); - rtw_indicate_disconnect23a(adapter); - rtw_free_assoc_resources23a(adapter, 0); - } - set_fwstate(&adapter->mlmepriv, _FW_UNDER_LINKING); - - ret = rtw_joinbss_cmd23a(adapter, candidate); - - if (ret == _SUCCESS) - mod_timer(&adapter->mlmepriv.assoc_timer, - jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT)); - - return ret; -} - -int rtw_select_and_join_from_scanned_queue23a(struct mlme_priv *pmlmepriv) -{ - struct rtw_adapter *adapter; - struct wlan_network *candidate = NULL; - int ret; - - adapter = pmlmepriv->nic_hdl; - - candidate = rtw_select_candidate_from_queue(pmlmepriv); - if (!candidate) { - DBG_8723A("%s: return _FAIL(candidate == NULL)\n", __func__); - ret = _FAIL; - goto exit; - } else { - DBG_8723A("%s: candidate: %s(%pM, ch:%u)\n", - __func__, - candidate->network.Ssid.ssid, - candidate->network.MacAddress, - candidate->network.DSConfig); - } - - ret = rtw_do_join_network(adapter, candidate); - -exit: - return ret; -} - -int rtw_set_auth23a(struct rtw_adapter *adapter, - struct security_priv *psecuritypriv) -{ - struct cmd_obj *pcmd; - struct setauth_parm *psetauthparm; - struct cmd_priv *pcmdpriv = &adapter->cmdpriv; - int res = _SUCCESS; - - pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (!pcmd) { - res = _FAIL; /* try again */ - goto exit; - } - - psetauthparm = kzalloc(sizeof(struct setauth_parm), GFP_KERNEL); - if (!psetauthparm) { - kfree(pcmd); - res = _FAIL; - goto exit; - } - - psetauthparm->mode = (unsigned char)psecuritypriv->dot11AuthAlgrthm; - - pcmd->cmdcode = _SetAuth_CMD_; - pcmd->parmbuf = (unsigned char *)psetauthparm; - pcmd->cmdsz = (sizeof(struct setauth_parm)); - pcmd->rsp = NULL; - pcmd->rspsz = 0; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "after enqueue set_auth_cmd, auth_mode=%x\n", - psecuritypriv->dot11AuthAlgrthm); - - res = rtw_enqueue_cmd23a(pcmdpriv, pcmd); - -exit: - - return res; -} - -int rtw_set_key23a(struct rtw_adapter *adapter, - struct security_priv *psecuritypriv, int keyid, u8 set_tx) -{ - u8 keylen; - struct cmd_obj *pcmd; - struct setkey_parm *psetkeyparm; - struct cmd_priv *pcmdpriv = &adapter->cmdpriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - int res = _SUCCESS; - - if (keyid >= 4) { - res = _FAIL; - goto exit; - } - - pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (!pcmd) { - res = _FAIL; /* try again */ - goto exit; - } - psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL); - if (!psetkeyparm) { - kfree(pcmd); - res = _FAIL; - goto exit; - } - - if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { - psetkeyparm->algorithm = (unsigned char) - psecuritypriv->dot118021XGrpPrivacy; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "rtw_set_key23a: psetkeyparm->algorithm = (unsigned char)psecuritypriv->dot118021XGrpPrivacy =%d\n", - psetkeyparm->algorithm); - } else { - psetkeyparm->algorithm = (u8)psecuritypriv->dot11PrivacyAlgrthm; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "rtw_set_key23a: psetkeyparm->algorithm = (u8)psecuritypriv->dot11PrivacyAlgrthm =%d\n", - psetkeyparm->algorithm); - } - psetkeyparm->keyid = keyid;/* 0~3 */ - psetkeyparm->set_tx = set_tx; - if (is_wep_enc(psetkeyparm->algorithm)) - pmlmepriv->key_mask |= BIT(psetkeyparm->keyid); - - DBG_8723A("==> rtw_set_key23a algorithm(%x), keyid(%x), key_mask(%x)\n", - psetkeyparm->algorithm, psetkeyparm->keyid, - pmlmepriv->key_mask); - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "rtw_set_key23a: psetkeyparm->algorithm =%d psetkeyparm->keyid = (u8)keyid =%d\n", - psetkeyparm->algorithm, keyid); - - switch (psetkeyparm->algorithm) { - case WLAN_CIPHER_SUITE_WEP40: - keylen = 5; - memcpy(&psetkeyparm->key[0], - &psecuritypriv->wep_key[keyid].key, keylen); - break; - case WLAN_CIPHER_SUITE_WEP104: - keylen = 13; - memcpy(&psetkeyparm->key[0], - &psecuritypriv->wep_key[keyid].key, keylen); - break; - case WLAN_CIPHER_SUITE_TKIP: - keylen = 16; - memcpy(&psetkeyparm->key, - &psecuritypriv->dot118021XGrpKey[keyid], keylen); - psetkeyparm->grpkey = 1; - break; - case WLAN_CIPHER_SUITE_CCMP: - keylen = 16; - memcpy(&psetkeyparm->key, - &psecuritypriv->dot118021XGrpKey[keyid], keylen); - psetkeyparm->grpkey = 1; - break; - default: - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "rtw_set_key23a:psecuritypriv->dot11PrivacyAlgrthm = %x (must be 1 or 2 or 4 or 5)\n", - psecuritypriv->dot11PrivacyAlgrthm); - res = _FAIL; - kfree(pcmd); - kfree(psetkeyparm); - goto exit; - } - - pcmd->cmdcode = _SetKey_CMD_; - pcmd->parmbuf = (u8 *)psetkeyparm; - pcmd->cmdsz = (sizeof(struct setkey_parm)); - pcmd->rsp = NULL; - pcmd->rspsz = 0; - - /* sema_init(&pcmd->cmd_sem, 0); */ - - res = rtw_enqueue_cmd23a(pcmdpriv, pcmd); - -exit: - - return res; -} - -/* adjust IEs for rtw_joinbss_cmd23a in WMM */ -int rtw_restruct_wmm_ie23a(struct rtw_adapter *adapter, u8 *in_ie, - u8 *out_ie, uint in_len, uint initial_out_len) -{ - int ielength; - const u8 *p; - - ielength = initial_out_len; - - p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WMM, - in_ie, in_len); - - if (p && p[1]) { - memcpy(out_ie + initial_out_len, p, 9); - - out_ie[initial_out_len + 1] = 7; - out_ie[initial_out_len + 6] = 0; - out_ie[initial_out_len + 8] = 0; - - ielength += 9; - } - - return ielength; -} - -/* */ -/* Ported from 8185: IsInPreAuthKeyList(). - (Renamed from SecIsInPreAuthKeyList(), 2006-10-13.) */ -/* Added by Annie, 2006-05-07. */ -/* */ -/* Search by BSSID, */ -/* Return Value: */ -/* -1 :if there is no pre-auth key in the table */ -/* >= 0 :if there is pre-auth key, and return the entry id */ -/* */ -/* */ - -static int SecIsInPMKIDList(struct rtw_adapter *Adapter, u8 *bssid) -{ - struct security_priv *psecuritypriv = &Adapter->securitypriv; - int i = 0; - - do { - if (psecuritypriv->PMKIDList[i].bUsed && - ether_addr_equal(psecuritypriv->PMKIDList[i].Bssid, bssid)) { - break; - } else { - i++; - /* continue; */ - } - } while (i < NUM_PMKID_CACHE); - - if (i == NUM_PMKID_CACHE) - i = -1;/* Could not find. */ - else { - /* There is one Pre-Authentication Key for - the specific BSSID. */ - } - - return i; -} - -/* */ -/* Check the RSN IE length */ -/* If the RSN IE length <= 20, the RSN IE didn't include - the PMKID information */ -/* 0-11th element in the array are the fixed IE */ -/* 12th element in the array is the IE */ -/* 13th element in the array is the IE length */ -/* */ - -static int rtw_append_pmkid(struct rtw_adapter *Adapter, int iEntry, - u8 *ie, uint ie_len) -{ - struct security_priv *psecuritypriv = &Adapter->securitypriv; - - if (ie[1] <= 20) { - /* The RSN IE didn't include the PMK ID, - append the PMK information */ - ie[ie_len] = 1; - ie_len++; - ie[ie_len] = 0; /* PMKID count = 0x0100 */ - ie_len++; - memcpy(&ie[ie_len], - &psecuritypriv->PMKIDList[iEntry].PMKID, 16); - - ie_len += 16; - ie[1] += 18;/* PMKID length = 2+16 */ - } - return ie_len; -} - -int rtw_restruct_sec_ie23a(struct rtw_adapter *adapter, u8 *in_ie, u8 *out_ie, - uint in_len) -{ - u8 authmode; - uint ielength; - int iEntry; - 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_, - "+rtw_restruct_sec_ie23a: ndisauthmode=%d ndissecuritytype=%d\n", - ndisauthmode, ndissecuritytype); - - ielength = 0; - if (ndisauthmode == Ndis802_11AuthModeWPA || - ndisauthmode == Ndis802_11AuthModeWPAPSK) - authmode = WLAN_EID_VENDOR_SPECIFIC; - if (ndisauthmode == Ndis802_11AuthModeWPA2 || - ndisauthmode == Ndis802_11AuthModeWPA2PSK) - authmode = WLAN_EID_RSN; - - if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) { - memcpy(out_ie + ielength, psecuritypriv->wps_ie, - psecuritypriv->wps_ie_len); - - ielength += psecuritypriv->wps_ie_len; - } else if (authmode == WLAN_EID_VENDOR_SPECIFIC || - authmode == WLAN_EID_RSN) { - /* copy RSN or SSN */ - memcpy(&out_ie[ielength], &psecuritypriv->supplicant_ie[0], - psecuritypriv->supplicant_ie[1] + 2); - ielength += psecuritypriv->supplicant_ie[1] + 2; - } - - iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid); - if (iEntry < 0) - return ielength; - else { - if (authmode == WLAN_EID_RSN) - ielength = rtw_append_pmkid(adapter, iEntry, - out_ie, ielength); - } - - return ielength; -} - -void rtw_init_registrypriv_dev_network23a(struct rtw_adapter *adapter) -{ - struct registry_priv *pregistrypriv = &adapter->registrypriv; - struct eeprom_priv *peepriv = &adapter->eeprompriv; - struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network; - u8 *myhwaddr = myid(peepriv); - - ether_addr_copy(pdev_network->MacAddress, myhwaddr); - - memcpy(&pdev_network->Ssid, &pregistrypriv->ssid, - sizeof(struct cfg80211_ssid)); - - pdev_network->beacon_interval = 100; -} - -void rtw_update_registrypriv_dev_network23a(struct rtw_adapter *adapter) -{ - int sz = 0; - struct registry_priv *pregistrypriv = &adapter->registrypriv; - struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network; - struct security_priv *psecuritypriv = &adapter->securitypriv; - struct wlan_network *cur_network = &adapter->mlmepriv.cur_network; - /* struct xmit_priv *pxmitpriv = &adapter->xmitpriv; */ - - pdev_network->Privacy = - (psecuritypriv->dot11PrivacyAlgrthm > 0 ? 1 : 0); - - pdev_network->Rssi = 0; - - pdev_network->DSConfig = pregistrypriv->channel; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "pregistrypriv->channel =%d, pdev_network->DSConfig = 0x%x\n", - pregistrypriv->channel, pdev_network->DSConfig); - - if (cur_network->network.ifmode == NL80211_IFTYPE_ADHOC) - pdev_network->ATIMWindow = 0; - - pdev_network->ifmode = cur_network->network.ifmode; - - /* 1. Supported rates */ - /* 2. IE */ - - sz = rtw_generate_ie23a(pregistrypriv); - - pdev_network->IELength = sz; - - pdev_network->Length = - get_wlan_bssid_ex_sz(pdev_network); - - /* notes: translate IELength & Length after assign the - Length to cmdsz in createbss_cmd(); */ - /* pdev_network->IELength = cpu_to_le32(sz); */ -} - -/* the function is at passive_level */ -void rtw_joinbss_reset23a(struct rtw_adapter *padapter) -{ - u8 threshold; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - - /* todo: if you want to do something io/reg/hw setting - before join_bss, please add code here */ - - pmlmepriv->num_FortyMHzIntolerant = 0; - - pmlmepriv->num_sta_no_ht = 0; - - phtpriv->ampdu_enable = false;/* reset to disabled */ - - /* TH = 1 => means that invalidate usb rx aggregation */ - /* TH = 0 => means that validate usb rx aggregation, use init value. */ - if (phtpriv->ht_option) { - if (padapter->registrypriv.wifi_spec == 1) - threshold = 1; - else - threshold = 0; - } else - threshold = 1; - - rtl8723a_set_rxdma_agg_pg_th(padapter, threshold); -} - -/* the function is >= passive_level */ -bool rtw_restructure_ht_ie23a(struct rtw_adapter *padapter, u8 *in_ie, - u8 *out_ie, uint in_len, uint *pout_len) -{ - u32 out_len; - int max_rx_ampdu_factor; - unsigned char *pframe; - const u8 *p; - struct ieee80211_ht_cap ht_capie; - u8 WMM_IE[7] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00}; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - - phtpriv->ht_option = false; - - p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, in_ie, in_len); - - if (p && p[1] > 0) { - u32 rx_packet_offset, max_recvbuf_sz; - - if (pmlmepriv->qos_option == 0) { - out_len = *pout_len; - pframe = rtw_set_ie23a(out_ie + out_len, - WLAN_EID_VENDOR_SPECIFIC, - sizeof(WMM_IE), WMM_IE, - pout_len); - - pmlmepriv->qos_option = 1; - } - - out_len = *pout_len; - - memset(&ht_capie, 0, sizeof(struct ieee80211_ht_cap)); - - ht_capie.cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 | - IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | - IEEE80211_HT_CAP_TX_STBC | IEEE80211_HT_CAP_DSSSCCK40); - - GetHalDefVar8192CUsb(padapter, HAL_DEF_RX_PACKET_OFFSET, - &rx_packet_offset); - GetHalDefVar8192CUsb(padapter, HAL_DEF_MAX_RECVBUF_SZ, - &max_recvbuf_sz); - - GetHalDefVar8192CUsb(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, - &max_rx_ampdu_factor); - ht_capie.ampdu_params_info = max_rx_ampdu_factor & 0x03; - - if (padapter->securitypriv.dot11PrivacyAlgrthm == - WLAN_CIPHER_SUITE_CCMP) - ht_capie.ampdu_params_info |= - (IEEE80211_HT_AMPDU_PARM_DENSITY& (0x07 << 2)); - else - ht_capie.ampdu_params_info |= - (IEEE80211_HT_AMPDU_PARM_DENSITY & 0x00); - - pframe = rtw_set_ie23a(out_ie + out_len, WLAN_EID_HT_CAPABILITY, - sizeof(struct ieee80211_ht_cap), - (unsigned char *)&ht_capie, pout_len); - - phtpriv->ht_option = true; - - p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, in_ie, in_len); - if (p && (p[1] == sizeof(struct ieee80211_ht_operation))) { - out_len = *pout_len; - pframe = rtw_set_ie23a(out_ie + out_len, - WLAN_EID_HT_OPERATION, - p[1], p + 2 , pout_len); - } - } - - return phtpriv->ht_option; -} - -/* the function is > passive_level (in critical_section) */ -void rtw_update_ht_cap23a(struct rtw_adapter *padapter, u8 *pie, uint ie_len) -{ - u8 max_ampdu_sz; - const u8 *p; - struct ieee80211_ht_cap *pht_capie; - struct ieee80211_ht_operation *pht_addtinfo; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (!phtpriv->ht_option) - return; - - if ((!pmlmeinfo->HT_info_enable) || (!pmlmeinfo->HT_caps_enable)) - return; - - DBG_8723A("+rtw_update_ht_cap23a()\n"); - - /* maybe needs check if ap supports rx ampdu. */ - if (!phtpriv->ampdu_enable && pregistrypriv->ampdu_enable == 1) { - if (pregistrypriv->wifi_spec == 1) - phtpriv->ampdu_enable = false; - else - phtpriv->ampdu_enable = true; - } else if (pregistrypriv->ampdu_enable == 2) - phtpriv->ampdu_enable = true; - - /* check Max Rx A-MPDU Size */ - p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pie, ie_len); - - if (p && p[1] > 0) { - pht_capie = (struct ieee80211_ht_cap *)(p + 2); - max_ampdu_sz = pht_capie->ampdu_params_info & - IEEE80211_HT_AMPDU_PARM_FACTOR; - /* max_ampdu_sz (kbytes); */ - max_ampdu_sz = 1 << (max_ampdu_sz + 3); - - phtpriv->rx_ampdu_maxlen = max_ampdu_sz; - } - - p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, pie, ie_len); - if (p && p[1] > 0) { - pht_addtinfo = (struct ieee80211_ht_operation *)(p + 2); - /* todo: */ - } - - /* update cur_bwmode & cur_ch_offset */ - if (pregistrypriv->cbw40_enable && - pmlmeinfo->ht_cap.cap_info & - cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40) && - pmlmeinfo->HT_info.ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) { - int i; - u8 rf_type; - - rf_type = rtl8723a_get_rf_type(padapter); - - /* update the MCS rates */ - for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) { - if (rf_type == RF_1T1R || rf_type == RF_1T2R) - pmlmeinfo->ht_cap.mcs.rx_mask[i] &= - MCS_rate_1R23A[i]; - else - pmlmeinfo->ht_cap.mcs.rx_mask[i] &= - MCS_rate_2R23A[i]; - } - /* switch to the 40M Hz mode according to the AP */ - pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40; - switch (pmlmeinfo->HT_info.ht_param & - IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { - case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER; - break; - - case IEEE80211_HT_PARAM_CHA_SEC_BELOW: - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER; - break; - - default: - pmlmeext->cur_ch_offset = - HAL_PRIME_CHNL_OFFSET_DONT_CARE; - break; - } - } - - /* */ - /* Config SM Power Save setting */ - /* */ - pmlmeinfo->SM_PS = - (le16_to_cpu(pmlmeinfo->ht_cap.cap_info) & - IEEE80211_HT_CAP_SM_PS) >> IEEE80211_HT_CAP_SM_PS_SHIFT; - if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC) - DBG_8723A("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__); - - /* */ - /* Config current HT Protection mode. */ - /* */ - pmlmeinfo->HT_protection = - le16_to_cpu(pmlmeinfo->HT_info.operation_mode) & - IEEE80211_HT_OP_MODE_PROTECTION; -} - -void rtw_issue_addbareq_cmd23a(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - u8 issued; - int priority; - struct sta_info *psta; - struct ht_priv *phtpriv; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - s32 bmcst = is_multicast_ether_addr(pattrib->ra); - - if (bmcst || padapter->mlmepriv.LinkDetectInfo.NumTxOkInPeriod < 100) - return; - - priority = pattrib->priority; - - if (pattrib->psta) - psta = pattrib->psta; - else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - psta = rtw_get_stainfo23a(&padapter->stapriv, pattrib->ra); - } - - if (!psta) { - DBG_8723A("%s, psta == NUL\n", __func__); - return; - } - - if (!(psta->state &_FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", - __func__, psta->state); - return; - } - - phtpriv = &psta->htpriv; - - if (phtpriv->ht_option && phtpriv->ampdu_enable) { - issued = (phtpriv->agg_enable_bitmap>>priority)&0x1; - issued |= (phtpriv->candidate_tid_bitmap>>priority)&0x1; - - if (issued == 0) { - DBG_8723A("rtw_issue_addbareq_cmd23a, p =%d\n", - priority); - psta->htpriv.candidate_tid_bitmap |= BIT(priority); - rtw_addbareq_cmd23a(padapter, (u8) priority, - pattrib->ra); - } - } -} - -int rtw_linked_check(struct rtw_adapter *padapter) -{ - if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) || - check_fwstate(&padapter->mlmepriv, - WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE)) { - if (padapter->stapriv.asoc_sta_count > 2) - return true; - } else { /* Station mode */ - if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) - return true; - } - return false; -} diff --git a/drivers/staging/rtl8723au/core/rtw_mlme_ext.c b/drivers/staging/rtl8723au/core/rtw_mlme_ext.c deleted file mode 100644 index 7dd1540..0000000 --- a/drivers/staging/rtl8723au/core/rtw_mlme_ext.c +++ /dev/null @@ -1,6187 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RTW_MLME_EXT_C_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <wifi.h> -#include <rtw_mlme_ext.h> -#include <wlan_bssdef.h> -#include <mlme_osdep.h> -#include <recv_osdep.h> -#include <linux/ieee80211.h> -#include <rtl8723a_hal.h> - -static int OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnAssocRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnProbeReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnProbeRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int DoReserved23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnBeacon23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnAtim23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnDisassoc23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnAuth23aClient23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnDeAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnAction23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); - -static int on_action_spct23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnAction23a_qos(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnAction23a_dls(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnAction23a_back23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int on_action_public23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnAction23a_ht(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnAction23a_wmm(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnAction23a_p2p(struct rtw_adapter *padapter, struct recv_frame *precv_frame); - -static void issue_assocreq(struct rtw_adapter *padapter); -static void issue_probereq(struct rtw_adapter *padapter, - struct cfg80211_ssid *pssid, u8 *da); -static int issue_probereq_ex(struct rtw_adapter *padapter, - struct cfg80211_ssid *pssid, - u8 *da, int try_cnt, int wait_ms); -static void issue_probersp(struct rtw_adapter *padapter, unsigned char *da); -static void issue_auth(struct rtw_adapter *padapter, struct sta_info *psta, - unsigned short status); -static int issue_deauth_ex(struct rtw_adapter *padapter, u8 *da, - unsigned short reason, int try_cnt, int wait_ms); -static void start_clnt_assoc(struct rtw_adapter *padapter); -static void start_clnt_auth(struct rtw_adapter *padapter); -static void start_clnt_join(struct rtw_adapter *padapter); -static void start_create_ibss(struct rtw_adapter *padapter); -static struct wlan_bssid_ex *collect_bss_info(struct rtw_adapter *padapter, - struct recv_frame *precv_frame); - -#ifdef CONFIG_8723AU_AP_MODE -static int OnAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static void issue_assocrsp(struct rtw_adapter *padapter, unsigned short status, - struct sta_info *pstat, u16 pkt_type); -#endif - -static struct mlme_handler mlme_sta_tbl[]={ - {"OnAssocReq23a", &OnAssocReq23a}, - {"OnAssocRsp23a", &OnAssocRsp23a}, - {"OnReAssocReq", &OnAssocReq23a}, - {"OnReAssocRsp", &OnAssocRsp23a}, - {"OnProbeReq23a", &OnProbeReq23a}, - {"OnProbeRsp23a", &OnProbeRsp23a}, - - /*---------------------------------------------------------- - below 2 are reserved - -----------------------------------------------------------*/ - {"DoReserved23a", &DoReserved23a}, - {"DoReserved23a", &DoReserved23a}, - {"OnBeacon23a", &OnBeacon23a}, - {"OnATIM", &OnAtim23a}, - {"OnDisassoc23a", &OnDisassoc23a}, - {"OnAuth23a", &OnAuth23aClient23a}, - {"OnDeAuth23a", &OnDeAuth23a}, - {"OnAction23a", &OnAction23a}, -}; - -static struct action_handler OnAction23a_tbl[]={ - {WLAN_CATEGORY_SPECTRUM_MGMT, "ACTION_SPECTRUM_MGMT", on_action_spct23a}, - {WLAN_CATEGORY_QOS, "ACTION_QOS", &OnAction23a_qos}, - {WLAN_CATEGORY_DLS, "ACTION_DLS", &OnAction23a_dls}, - {WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction23a_back23a}, - {WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public23a}, - {WLAN_CATEGORY_HT, "ACTION_HT", &OnAction23a_ht}, - {WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &DoReserved23a}, - {WLAN_CATEGORY_WMM, "ACTION_WMM", &OnAction23a_wmm}, - {WLAN_CATEGORY_VENDOR_SPECIFIC, "ACTION_P2P", &OnAction23a_p2p}, -}; - -static u8 null_addr[ETH_ALEN]= {0, 0, 0, 0, 0, 0}; - -/************************************************** -OUI definitions for the vendor specific IE -***************************************************/ -unsigned char WMM_OUI23A[] = {0x00, 0x50, 0xf2, 0x02}; -unsigned char WPS_OUI23A[] = {0x00, 0x50, 0xf2, 0x04}; -unsigned char P2P_OUI23A[] = {0x50, 0x6F, 0x9A, 0x09}; -unsigned char WFD_OUI23A[] = {0x50, 0x6F, 0x9A, 0x0A}; - -unsigned char WMM_INFO_OUI23A[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01}; -unsigned char WMM_PARA_OUI23A[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; - -static unsigned char REALTEK_96B_IE[] = {0x00, 0xe0, 0x4c, 0x02, 0x01, 0x20}; - -/******************************************************** -MCS rate definitions -*********************************************************/ -unsigned char MCS_rate_2R23A[16] = { - 0xff, 0xff, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; -unsigned char MCS_rate_1R23A[16] = { - 0xff, 0x00, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; - -/******************************************************** -ChannelPlan definitions -*********************************************************/ - -static struct rt_channel_plan_2g RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = { - /* 0x00, RT_CHANNEL_DOMAIN_2G_WORLD , Passive scan CH 12, 13 */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, - /* 0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, - /* 0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11}, - /* 0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14}, - /* 0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */ - {{10, 11, 12, 13}, 4}, - /* 0x05, RT_CHANNEL_DOMAIN_2G_NULL */ - {{}, 0}, -}; - -static struct rt_channel_plan_5g RTW_ChannelPlan5G[RT_CHANNEL_DOMAIN_5G_MAX] = { - /* 0x00, RT_CHANNEL_DOMAIN_5G_NULL */ - {{}, 0}, - /* 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}, 19}, - /* 0x02, RT_CHANNEL_DOMAIN_5G_ETSI2 */ - {{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}, - /* 0x03, RT_CHANNEL_DOMAIN_5G_ETSI3 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, - 116, 120, 124, 128, 132, 149, 153, 157, 161, 165}, 22}, - /* 0x04, RT_CHANNEL_DOMAIN_5G_FCC1 */ - {{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}, - /* 0x05, RT_CHANNEL_DOMAIN_5G_FCC2 */ - {{36, 40, 44, 48, 149, 153, 157, 161, 165}, 9}, - /* 0x06, RT_CHANNEL_DOMAIN_5G_FCC3 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 13}, - /* 0x07, RT_CHANNEL_DOMAIN_5G_FCC4 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161}, 12}, - /* 0x08, RT_CHANNEL_DOMAIN_5G_FCC5 */ - {{149, 153, 157, 161, 165}, 5}, - /* 0x09, RT_CHANNEL_DOMAIN_5G_FCC6 */ - {{36, 40, 44, 48, 52, 56, 60, 64}, 8}, - /* 0x0A, RT_CHANNEL_DOMAIN_5G_FCC7_IC1 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, - 116, 136, 140, 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, 149, 153, 157, 161, 165}, 20}, - /* 0x0C, RT_CHANNEL_DOMAIN_5G_MKK1 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, - 116, 120, 124, 128, 132, 136, 140}, 19}, - /* 0x0D, RT_CHANNEL_DOMAIN_5G_MKK2 */ - {{36, 40, 44, 48, 52, 56, 60, 64}, 8}, - /* 0x0E, RT_CHANNEL_DOMAIN_5G_MKK3 */ - {{100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 11}, - /* 0x0F, RT_CHANNEL_DOMAIN_5G_NCC1 */ - {{56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, - 153, 157, 161, 165}, 15}, - /* 0x10, RT_CHANNEL_DOMAIN_5G_NCC2 */ - {{56, 60, 64, 149, 153, 157, 161, 165}, 8}, - - /* Driver self defined for old channel plan Compatible, - Remember to modify if have new channel plan definition ===== */ - /* 0x11, RT_CHANNEL_DOMAIN_5G_FCC */ - {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, - 116, 132, 136, 140, 149, 153, 157, 161, 165}, 21}, - /* 0x12, RT_CHANNEL_DOMAIN_5G_JAPAN_NO_DFS */ - {{36, 40, 44, 48}, 4}, - /* 0x13, RT_CHANNEL_DOMAIN_5G_FCC4_NO_DFS */ - {{36, 40, 44, 48, 149, 153, 157, 161}, 8}, -}; - -static struct rt_channel_plan_map RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = { - /* 0x00 ~ 0x1F , Old Define ===== */ - {0x02, 0x11}, /* 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, 0x12}, /* 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, 0x12}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */ - {0x00, 0x13}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */ - {0x03, 0x12}, /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */ - {0x05, 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, */ - {0x05, 0x04}, /* 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 */ - {0x03, 0x00}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G */ -}; - -static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = -{0x03, 0x02}; /* use the conbination for max channel numbers */ - -static void dummy_event_callback(struct rtw_adapter *adapter, const u8 *pbuf) -{ -} - -static struct fwevent wlanevents[] = -{ - {0, &dummy_event_callback}, /*0*/ - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, &rtw_survey_event_cb23a}, /*8*/ - {sizeof (struct surveydone_event), &rtw_surveydone_event_callback23a}, - {0, &rtw23a_joinbss_event_cb}, /*10*/ - {sizeof(struct stassoc_event), &rtw_stassoc_event_callback23a}, - {sizeof(struct stadel_event), &rtw_stadel_event_callback23a}, - {0, &dummy_event_callback}, - {0, &dummy_event_callback}, - {0, NULL}, /*15*/ - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, &dummy_event_callback}, - {0, NULL}, /*20*/ - {0, NULL}, - {0, NULL}, - {0, &dummy_event_callback}, - {0, NULL}, -}; - - -static void rtw_correct_TSF(struct rtw_adapter *padapter) -{ - hw_var_set_correct_tsf(padapter); -} - -static void -rtw_update_TSF(struct mlme_ext_priv *pmlmeext, struct ieee80211_mgmt *mgmt) -{ - pmlmeext->TSFValue = get_unaligned_le64(&mgmt->u.beacon.timestamp); -} - -/* - * Search the @param channel_num in given @param channel_set - * @ch_set: the given channel set - * @ch: the given channel number - * - * return the index of channel_num in channel_set, -1 if not found - */ -int rtw_ch_set_search_ch23a(struct rt_channel_info *ch_set, const u32 ch) -{ - int i; - - for (i = 0; ch_set[i]. ChannelNum != 0; i++) { - if (ch == ch_set[i].ChannelNum) - break; - } - - if (i >= ch_set[i].ChannelNum) - return -1; - return i; -} - -/**************************************************************************** - -Following are the initialization functions for WiFi MLME - -*****************************************************************************/ - -int init_hw_mlme_ext23a(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - set_channel_bwmode23a(padapter, pmlmeext->cur_channel, - pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - return _SUCCESS; -} - -static void init_mlme_ext_priv23a_value(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - unsigned char mixed_datarate[NumRates] = { - _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_, - _9M_RATE_, _12M_RATE_, _18M_RATE_, _24M_RATE_, _36M_RATE_, - _48M_RATE_, _54M_RATE_, 0xff}; - unsigned char mixed_basicrate[NumRates] = { - _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_, - _12M_RATE_, _24M_RATE_, 0xff,}; - - atomic_set(&pmlmeext->event_seq, 0); - /* reset to zero when disconnect at client mode */ - pmlmeext->mgnt_seq = 0; - - pmlmeext->cur_channel = padapter->registrypriv.channel; - pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20; - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - - pmlmeext->retry = 0; - - pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode; - - memcpy(pmlmeext->datarate, mixed_datarate, NumRates); - memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates); - - if (pmlmeext->cur_channel > 14) - pmlmeext->tx_rate = IEEE80211_OFDM_RATE_6MB; - else - pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB; - - pmlmeext->sitesurvey_res.state = SCAN_DISABLE; - pmlmeext->sitesurvey_res.channel_idx = 0; - pmlmeext->sitesurvey_res.bss_cnt = 0; - pmlmeext->scan_abort = false; - - pmlmeinfo->state = MSR_NOLINK; - pmlmeinfo->reauth_count = 0; - pmlmeinfo->reassoc_count = 0; - pmlmeinfo->link_count = 0; - pmlmeinfo->auth_seq = 0; - pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open; - pmlmeinfo->key_index = 0; - pmlmeinfo->iv = 0; - - pmlmeinfo->enc_algo = 0; - pmlmeinfo->authModeToggle = 0; - - memset(pmlmeinfo->chg_txt, 0, 128); - - pmlmeinfo->slotTime = SHORT_SLOT_TIME; - pmlmeinfo->preamble_mode = PREAMBLE_AUTO; - - pmlmeinfo->dialogToken = 0; - - pmlmeext->action_public_rxseq = 0xffff; - pmlmeext->action_public_dialog_token = 0xff; -} - -static int has_channel(struct rt_channel_info *channel_set, - u8 chanset_size, u8 chan) { - int i; - - for (i = 0; i < chanset_size; i++) { - if (channel_set[i].ChannelNum == chan) - return 1; - } - - return 0; -} - -static void init_channel_list(struct rtw_adapter *padapter, - struct rt_channel_info *channel_set, - u8 chanset_size, - struct p2p_channels *channel_list) -{ - struct p2p_oper_class_map op_class[] = { - { IEEE80211G, 81, 1, 13, 1, BW20 }, - { IEEE80211G, 82, 14, 14, 1, BW20 }, - { IEEE80211A, 115, 36, 48, 4, BW20 }, - { IEEE80211A, 116, 36, 44, 8, BW40PLUS }, - { IEEE80211A, 117, 40, 48, 8, BW40MINUS }, - { IEEE80211A, 124, 149, 161, 4, BW20 }, - { IEEE80211A, 125, 149, 169, 4, BW20 }, - { IEEE80211A, 126, 149, 157, 8, BW40PLUS }, - { IEEE80211A, 127, 153, 161, 8, BW40MINUS }, - { -1, 0, 0, 0, 0, BW20 } - }; - - int cla, op; - - cla = 0; - - for (op = 0; op_class[op].op_class; op++) { - u8 ch; - struct p2p_oper_class_map *o = &op_class[op]; - struct p2p_reg_class *reg = NULL; - - for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) { - if (!has_channel(channel_set, chanset_size, ch)) - continue; - - if ((0 == padapter->registrypriv.ht_enable) && - (o->inc == 8)) - continue; - - if ((0 == (padapter->registrypriv.cbw40_enable & BIT(1))) && - ((BW40MINUS == o->bw) || (BW40PLUS == o->bw))) - continue; - - if (reg == NULL) { - reg = &channel_list->reg_class[cla]; - cla++; - reg->reg_class = o->op_class; - reg->channels = 0; - } - reg->channel[reg->channels] = ch; - reg->channels++; - } - } - channel_list->reg_classes = cla; -} - -static u8 init_channel_set(struct rtw_adapter *padapter, u8 cplan, - struct rt_channel_info *c_set) -{ - u8 i, ch_size = 0; - u8 b5GBand = false, b2_4GBand = false; - u8 Index2G = 0, Index5G = 0; - - memset(c_set, 0, sizeof(struct rt_channel_info) * MAX_CHANNEL_NUM); - - if (cplan >= RT_CHANNEL_DOMAIN_MAX && - cplan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) { - DBG_8723A("ChannelPlan ID %x error !!!!!\n", cplan); - return ch_size; - } - - if (padapter->registrypriv.wireless_mode & WIRELESS_11G) { - b2_4GBand = true; - if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == cplan) - Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G; - else - Index2G = RTW_ChannelPlanMap[cplan].Index2G; - } - - if (padapter->registrypriv.wireless_mode & WIRELESS_11A) { - b5GBand = true; - if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == cplan) - Index5G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index5G; - else - Index5G = RTW_ChannelPlanMap[cplan].Index5G; - } - - if (b2_4GBand) { - for (i = 0; i < RTW_ChannelPlan2G[Index2G].Len; i++) { - c_set[ch_size].ChannelNum = - RTW_ChannelPlan2G[Index2G].Channel[i]; - - if ((RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN == cplan) || - /* Channel 1~11 is active, and 12~14 is passive */ - RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G == cplan) { - if (c_set[ch_size].ChannelNum >= 1 && - c_set[ch_size].ChannelNum <= 11) - c_set[ch_size].ScanType = SCAN_ACTIVE; - else if (c_set[ch_size].ChannelNum >= 12 && - c_set[ch_size].ChannelNum <= 14) - c_set[ch_size].ScanType = SCAN_PASSIVE; - } else if (RT_CHANNEL_DOMAIN_WORLD_WIDE_13 == cplan || - RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == cplan || - RT_CHANNEL_DOMAIN_2G_WORLD == Index2G) { - /* channel 12~13, passive scan */ - if (c_set[ch_size].ChannelNum <= 11) - c_set[ch_size].ScanType = SCAN_ACTIVE; - else - c_set[ch_size].ScanType = SCAN_PASSIVE; - } else - c_set[ch_size].ScanType = SCAN_ACTIVE; - - ch_size++; - } - } - - if (b5GBand) { - for (i = 0; i < RTW_ChannelPlan5G[Index5G].Len; i++) { - if (RTW_ChannelPlan5G[Index5G].Channel[i] <= 48 || - RTW_ChannelPlan5G[Index5G].Channel[i] >= 149) { - c_set[ch_size].ChannelNum = - RTW_ChannelPlan5G[Index5G].Channel[i]; - if (RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == cplan) { - /* passive scan for all 5G channels */ - c_set[ch_size].ScanType = - SCAN_PASSIVE; - } else - c_set[ch_size].ScanType = - SCAN_ACTIVE; - DBG_8723A("%s(): channel_set[%d].ChannelNum = " - "%d\n", __func__, ch_size, - c_set[ch_size].ChannelNum); - ch_size++; - } - } - } - - return ch_size; -} - -int init_mlme_ext_priv23a(struct rtw_adapter *padapter) -{ - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - pmlmeext->padapter = padapter; - - init_mlme_ext_priv23a_value(padapter); - pmlmeinfo->bAcceptAddbaReq = pregistrypriv->bAcceptAddbaReq; - - init_mlme_ext_timer23a(padapter); - -#ifdef CONFIG_8723AU_AP_MODE - init_mlme_ap_info23a(padapter); -#endif - - pmlmeext->max_chan_nums = init_channel_set(padapter, - pmlmepriv->ChannelPlan, - pmlmeext->channel_set); - init_channel_list(padapter, pmlmeext->channel_set, - pmlmeext->max_chan_nums, &pmlmeext->channel_list); - - pmlmeext->chan_scan_time = SURVEY_TO; - pmlmeext->mlmeext_init = true; - - pmlmeext->active_keep_alive_check = true; - return _SUCCESS; -} - -void free_mlme_ext_priv23a (struct mlme_ext_priv *pmlmeext) -{ - struct rtw_adapter *padapter = pmlmeext->padapter; - - if (!padapter) - return; - - if (padapter->bDriverStopped == true) { - del_timer_sync(&pmlmeext->survey_timer); - del_timer_sync(&pmlmeext->link_timer); - /* del_timer_sync(&pmlmeext->ADDBA_timer); */ - } -} - -static void -_mgt_dispatcher23a(struct rtw_adapter *padapter, struct mlme_handler *ptable, - struct recv_frame *precv_frame) -{ - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - - if (ptable->func) { - /* receive the frames that ra(a1) is my address - or ra(a1) is bc address. */ - if (!ether_addr_equal(hdr->addr1, myid(&padapter->eeprompriv))&& - !is_broadcast_ether_addr(hdr->addr1)) - return; - - ptable->func(padapter, precv_frame); - } -} - -void mgt_dispatcher23a(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ - struct mlme_handler *ptable; -#ifdef CONFIG_8723AU_AP_MODE - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; -#endif /* CONFIG_8723AU_AP_MODE */ - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - struct sta_info *psta; - u16 stype; - int index; - - if (!ieee80211_is_mgmt(mgmt->frame_control)) - return; - - /* receive the frames that ra(a1) is my address or ra(a1) is - bc address. */ - if (!ether_addr_equal(mgmt->da, myid(&padapter->eeprompriv)) && - !is_broadcast_ether_addr(mgmt->da)) - return; - - ptable = mlme_sta_tbl; - - stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE; - index = stype >> 4; - - if (index > 13) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "Currently we do not support reserved sub-fr-type =%d\n", - index); - return; - } - ptable += index; - - psta = rtw_get_stainfo23a(&padapter->stapriv, mgmt->sa); - - if (psta) { - if (ieee80211_has_retry(mgmt->frame_control)) { - if (precv_frame->attrib.seq_num == - psta->RxMgmtFrameSeqNum) { - /* drop the duplicate management frame */ - DBG_8723A("Drop duplicate management frame " - "with seq_num = %d.\n", - precv_frame->attrib.seq_num); - return; - } - } - psta->RxMgmtFrameSeqNum = precv_frame->attrib.seq_num; - } - -#ifdef CONFIG_8723AU_AP_MODE - switch (stype) { - case IEEE80211_STYPE_AUTH: - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) - ptable->func = &OnAuth23a; - else - ptable->func = &OnAuth23aClient23a; - /* pass through */ - case IEEE80211_STYPE_ASSOC_REQ: - case IEEE80211_STYPE_REASSOC_REQ: - _mgt_dispatcher23a(padapter, ptable, precv_frame); - break; - case IEEE80211_STYPE_PROBE_REQ: - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) - _mgt_dispatcher23a(padapter, ptable, precv_frame); - else - _mgt_dispatcher23a(padapter, ptable, precv_frame); - break; - case IEEE80211_STYPE_BEACON: - _mgt_dispatcher23a(padapter, ptable, precv_frame); - break; - case IEEE80211_STYPE_ACTION: - /* if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) */ - _mgt_dispatcher23a(padapter, ptable, precv_frame); - break; - default: - _mgt_dispatcher23a(padapter, ptable, precv_frame); - break; - } -#else - _mgt_dispatcher23a(padapter, ptable, precv_frame); -#endif -} - -/**************************************************************************** - -Following are the callback functions for each subtype of the management frames - -*****************************************************************************/ - -static int -OnProbeReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - const u8 *ie; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur = &pmlmeinfo->network; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - int len = skb->len; - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) - return _SUCCESS; - - if (!check_fwstate(pmlmepriv, _FW_LINKED) && - !check_fwstate(pmlmepriv, - WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE)) - return _SUCCESS; - - if (unlikely(!ieee80211_is_probe_req(mgmt->frame_control))) { - printk(KERN_WARNING "%s: Received non probe request frame\n", - __func__); - return _FAIL; - } - - len -= offsetof(struct ieee80211_mgmt, u.probe_req.variable); - - ie = cfg80211_find_ie(WLAN_EID_SSID, mgmt->u.probe_req.variable, len); - - /* check (wildcard) SSID */ - if (!ie) - goto out; - - if ((ie[1] && memcmp(ie + 2, cur->Ssid.ssid, cur->Ssid.ssid_len)) || - (ie[1] == 0 && pmlmeinfo->hidden_ssid_mode)) { - return _SUCCESS; - } - - if (check_fwstate(pmlmepriv, _FW_LINKED) && - pmlmepriv->cur_network.join_res) - issue_probersp(padapter, mgmt->sa); - -out: - return _SUCCESS; -} - -static int -OnProbeRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { - report_survey_event23a(padapter, precv_frame); - return _SUCCESS; - } - - return _SUCCESS; -} - -static int -OnBeacon23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - int cam_idx; - struct sta_info *psta; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - int pkt_len = skb->len; - struct wlan_bssid_ex *pbss; - int ret = _SUCCESS; - u8 *p, *pie; - int pie_len; - u32 ielen = 0; - - pie = mgmt->u.beacon.variable; - pie_len = pkt_len - offsetof(struct ieee80211_mgmt, u.beacon.variable); - p = rtw_get_ie23a(pie, WLAN_EID_EXT_SUPP_RATES, &ielen, pie_len); - if (p && ielen > 0) { - if (p[1 + ielen] == 0x2D && p[2 + ielen] != 0x2D) { - /* Invalid value 0x2D is detected in Extended Supported - * Rates (ESR) IE. Try to fix the IE length to avoid - * failed Beacon parsing. - */ - DBG_8723A("[WIFIDBG] Error in ESR IE is detected in " - "Beacon of BSSID: %pM. Fix the length of " - "ESR IE to avoid failed Beacon parsing.\n", - mgmt->bssid); - p[1] = ielen - 1; - } - } - - if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { - report_survey_event23a(padapter, precv_frame); - return _SUCCESS; - } - - if (!ether_addr_equal(mgmt->bssid, - get_my_bssid23a(&pmlmeinfo->network))) - goto out; - - if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) { - /* we should update current network before auth, - or some IE is wrong */ - pbss = collect_bss_info(padapter, precv_frame); - if (pbss) { - update_network23a(&pmlmepriv->cur_network.network, pbss, - padapter, true); - rtw_get_bcn_info23a(&pmlmepriv->cur_network); - kfree(pbss); - } - - /* check the vendor of the assoc AP */ - pmlmeinfo->assoc_AP_vendor = - check_assoc_AP23a((u8 *)&mgmt->u.beacon, pkt_len - - offsetof(struct ieee80211_mgmt, u)); - - /* update TSF Value */ - rtw_update_TSF(pmlmeext, mgmt); - - /* start auth */ - start_clnt_auth(padapter); - - return _SUCCESS; - } - - if (((pmlmeinfo->state & 0x03) == MSR_AP) && - (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) { - psta = rtw_get_stainfo23a(pstapriv, mgmt->sa); - if (psta) { - ret = rtw_check_bcn_info23a(padapter, mgmt, pkt_len); - if (ret != _SUCCESS) { - DBG_8723A_LEVEL(_drv_always_, "ap has changed, " - "disconnect now\n"); - receive_disconnect23a(padapter, pmlmeinfo->network.MacAddress, 65535); - return _SUCCESS; - } - /* update WMM, ERP in the beacon */ - /* todo: the timer is used instead of - the number of the beacon received */ - if ((sta_rx_pkts(psta) & 0xf) == 0) { - /* DBG_8723A("update_bcn_info\n"); */ - update_beacon23a_info(padapter, mgmt, - pkt_len, psta); - } - } - } else if ((pmlmeinfo->state&0x03) == MSR_ADHOC) { - psta = rtw_get_stainfo23a(pstapriv, mgmt->sa); - if (psta) { - /* update WMM, ERP in the beacon */ - /* todo: the timer is used instead of the - number of the beacon received */ - if ((sta_rx_pkts(psta) & 0xf) == 0) { - /* DBG_8723A("update_bcn_info\n"); */ - update_beacon23a_info(padapter, mgmt, - pkt_len, psta); - } - } else { - /* allocate a new CAM entry for IBSS station */ - cam_idx = allocate_fw_sta_entry23a(padapter); - if (cam_idx == NUM_STA) - goto out; - - /* get supported rate */ - if (update_sta_support_rate23a(padapter, pie, pie_len, - cam_idx) == _FAIL) { - pmlmeinfo->FW_sta_info[cam_idx].status = 0; - goto out; - } - - /* update TSF Value */ - rtw_update_TSF(pmlmeext, mgmt); - - /* report sta add event */ - report_add_sta_event23a(padapter, mgmt->sa, - cam_idx); - } - } - -out: - - return _SUCCESS; -} - -#ifdef CONFIG_8723AU_AP_MODE -static int -OnAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - static struct sta_info stat; - struct sta_info *pstat = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - u8 *pframe; - const u8 *p; - unsigned char *sa; - u16 auth_mode, seq, algorithm; - int status, len = skb->len; - - if ((pmlmeinfo->state & 0x03) != MSR_AP) - return _FAIL; - - DBG_8723A("+OnAuth23a\n"); - - sa = mgmt->sa; - - auth_mode = psecuritypriv->dot11AuthAlgrthm; - - pframe = mgmt->u.auth.variable; - len = skb->len - offsetof(struct ieee80211_mgmt, u.auth.variable); - - seq = le16_to_cpu(mgmt->u.auth.auth_transaction); - algorithm = le16_to_cpu(mgmt->u.auth.auth_alg); - - DBG_8723A("auth alg =%x, seq =%X\n", algorithm, seq); - - if (auth_mode == 2 && - psecuritypriv->dot11PrivacyAlgrthm != WLAN_CIPHER_SUITE_WEP40 && - psecuritypriv->dot11PrivacyAlgrthm != WLAN_CIPHER_SUITE_WEP104) - auth_mode = 0; - - /* rx a shared-key auth but shared not enabled, or */ - /* rx a open-system auth but shared-key is enabled */ - if ((algorithm != WLAN_AUTH_OPEN && auth_mode == 0) || - (algorithm == WLAN_AUTH_OPEN && auth_mode == 1)) { - DBG_8723A("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; - } - - if (rtw_access_ctrl23a(padapter, sa) == false) { - status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; - goto auth_fail; - } - - pstat = rtw_get_stainfo23a(pstapriv, sa); - if (!pstat) { - /* allocate a new one */ - DBG_8723A("going to alloc stainfo for sa =%pM\n", sa); - pstat = rtw_alloc_stainfo23a(pstapriv, sa, GFP_ATOMIC); - if (!pstat) { - DBG_8723A(" Exceed the upper limit of supported " - "clients...\n"); - status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; - goto auth_fail; - } - - pstat->state = WIFI_FW_AUTH_NULL; - pstat->auth_seq = 0; - - /* pstat->flags = 0; */ - /* pstat->capability = 0; */ - } else { - spin_lock_bh(&pstapriv->asoc_list_lock); - if (!list_empty(&pstat->asoc_list)) { - list_del_init(&pstat->asoc_list); - pstapriv->asoc_list_cnt--; - if (pstat->expire_to > 0) { - /* TODO: STA re_auth within expire_to */ - } - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - if (seq == 1) { - /* TODO: STA re_auth and auth timeout */ - } - } - - spin_lock_bh(&pstapriv->auth_list_lock); - if (list_empty(&pstat->auth_list)) { - list_add_tail(&pstat->auth_list, &pstapriv->auth_list); - pstapriv->auth_list_cnt++; - } - spin_unlock_bh(&pstapriv->auth_list_lock); - - if (pstat->auth_seq == 0) - pstat->expire_to = pstapriv->auth_to; - - if ((pstat->auth_seq + 1) != seq) { - DBG_8723A("(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; - } - - if (algorithm == WLAN_AUTH_OPEN && (auth_mode == 0 || auth_mode == 2)) { - if (seq == 1) { - pstat->state &= ~WIFI_FW_AUTH_NULL; - pstat->state |= WIFI_FW_AUTH_SUCCESS; - pstat->expire_to = pstapriv->assoc_to; - pstat->authalg = algorithm; - } else { - DBG_8723A("(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; - } - } else { /* shared system or auto authentication */ - if (seq == 1) { - /* prepare for the challenging txt... */ - pstat->state &= ~WIFI_FW_AUTH_NULL; - pstat->state |= WIFI_FW_AUTH_STATE; - pstat->authalg = algorithm; - pstat->auth_seq = 2; - } else if (seq == 3) { - /* checking for challenging txt... */ - DBG_8723A("checking for challenging txt...\n"); - - p = cfg80211_find_ie(WLAN_EID_CHALLENGE, pframe, len); - if (!p || p[1] <= 0) { - DBG_8723A("auth rejected because challenge " - "failure!(1)\n"); - status = WLAN_STATUS_CHALLENGE_FAIL; - goto auth_fail; - } - - if (!memcmp(p + 2, pstat->chg_txt, 128)) { - pstat->state &= ~WIFI_FW_AUTH_STATE; - pstat->state |= WIFI_FW_AUTH_SUCCESS; - /* challenging txt is correct... */ - pstat->expire_to = pstapriv->assoc_to; - } else { - DBG_8723A("auth rejected because challenge " - "failure!\n"); - status = WLAN_STATUS_CHALLENGE_FAIL; - goto auth_fail; - } - } else { - DBG_8723A("(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; - } - } - - /* Now, we are going to issue_auth... */ - pstat->auth_seq = seq + 1; - - issue_auth(padapter, pstat, WLAN_STATUS_SUCCESS); - - if (pstat->state & WIFI_FW_AUTH_SUCCESS) - pstat->auth_seq = 0; - - return _SUCCESS; - -auth_fail: - - if (pstat) - rtw_free_stainfo23a(padapter, pstat); - - pstat = &stat; - memset((char *)pstat, '\0', sizeof(stat)); - pstat->auth_seq = 2; - ether_addr_copy(pstat->hwaddr, sa); - - issue_auth(padapter, pstat, (unsigned short)status); - - return _FAIL; -} -#endif - -static int -OnAuth23aClient23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - unsigned int seq, status, algthm; - unsigned int go2asoc = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - const u8 *p; - u8 *pie; - int plen = skb->len; - - DBG_8723A("%s\n", __func__); - - /* check A1 matches or not */ - if (!ether_addr_equal(myid(&padapter->eeprompriv), mgmt->da)) - return _SUCCESS; - - if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE)) - return _SUCCESS; - - pie = mgmt->u.auth.variable; - plen -= offsetof(struct ieee80211_mgmt, u.auth.variable); - - algthm = le16_to_cpu(mgmt->u.auth.auth_alg); - seq = le16_to_cpu(mgmt->u.auth.auth_transaction); - status = le16_to_cpu(mgmt->u.auth.status_code); - - if (status) { - DBG_8723A("clnt auth fail, status: %d\n", status); - /* pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */ - if (status == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) { - if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) - pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open; - else - pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; - /* pmlmeinfo->reauth_count = 0; */ - } - - set_link_timer(pmlmeext, 1); - goto authclnt_fail; - } - - if (seq == 2) { - if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) { - /* legendary shared system */ - p = cfg80211_find_ie(WLAN_EID_CHALLENGE, pie, plen); - - if (!p) { - /* DBG_8723A("marc: no challenge text?\n"); */ - goto authclnt_fail; - } - - memcpy((void *)(pmlmeinfo->chg_txt), p + 2, p[1]); - pmlmeinfo->auth_seq = 3; - issue_auth(padapter, NULL, 0); - set_link_timer(pmlmeext, REAUTH_TO); - - return _SUCCESS; - } else { - /* open system */ - go2asoc = 1; - } - } else if (seq == 4) { - if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) - go2asoc = 1; - else - goto authclnt_fail; - } else { - /* this is also illegal */ - /* DBG_8723A("marc: clnt auth failed due to illegal seq =%x\n", - seq); */ - goto authclnt_fail; - } - - if (go2asoc) { - DBG_8723A_LEVEL(_drv_always_, "auth success, start assoc\n"); - start_clnt_assoc(padapter); - return _SUCCESS; - } - -authclnt_fail: - - /* pmlmeinfo->state &= ~(WIFI_FW_AUTH_STATE); */ - - return _FAIL; -} - -#ifdef CONFIG_8723AU_AP_MODE -static int rtw_validate_vendor_specific_ies(const u8 *pos, int elen) -{ - unsigned int oui; - - /* first 3 bytes in vendor specific information element are the IEEE - * OUI of the vendor. The following byte is used a vendor specific - * sub-type. */ - if (elen < 4) { - DBG_8723A("short vendor specific information element " - "ignored (len =%i)\n", elen); - return -EINVAL; - } - - oui = RTW_GET_BE24(pos); - switch (oui) { - case WLAN_OUI_MICROSOFT: - /* Microsoft/Wi-Fi information elements are further typed and - * subtyped */ - switch (pos[3]) { - case WLAN_OUI_TYPE_MICROSOFT_WPA: - /* Microsoft OUI (00:50:F2) with OUI Type 1: - * real WPA information element */ - break; - case WLAN_OUI_TYPE_MICROSOFT_WMM: - if (elen < 5) { - DBG_8723A("short WME information element " - "ignored (len =%i)\n", elen); - return -EINVAL; - } - switch (pos[4]) { - case WME_OUI_SUBTYPE_INFORMATION_ELEMENT: - case WME_OUI_SUBTYPE_PARAMETER_ELEMENT: - break; - case WME_OUI_SUBTYPE_TSPEC_ELEMENT: - break; - default: - DBG_8723A("unknown WME information element " - "ignored (subtype =%d len =%i)\n", - pos[4], elen); - return -EINVAL; - } - break; - case WLAN_OUI_TYPE_MICROSOFT_WPS: - /* Wi-Fi Protected Setup (WPS) IE */ - break; - default: - DBG_8723A("Unknown Microsoft information element " - "ignored (type =%d len =%i)\n", - pos[3], elen); - return -EINVAL; - } - break; - - case OUI_BROADCOM: - switch (pos[3]) { - case VENDOR_HT_CAPAB_OUI_TYPE: - break; - default: - DBG_8723A("Unknown Broadcom information element " - "ignored (type =%d len =%i)\n", pos[3], elen); - return -EINVAL; - } - break; - - default: - DBG_8723A("unknown vendor specific information element " - "ignored (vendor OUI %02x:%02x:%02x len =%i)\n", - pos[0], pos[1], pos[2], elen); - return -EINVAL; - } - - return 0; -} - -static int rtw_validate_frame_ies(const u8 *start, uint len) -{ - const u8 *pos = start; - int left = len; - int unknown = 0; - - while (left >= 2) { - u8 id, elen; - - id = *pos++; - elen = *pos++; - left -= 2; - - if (elen > left) { - DBG_8723A("%s: IEEE 802.11 failed (id =%d elen =%d " - "left =%i)\n", __func__, id, elen, left); - return -EINVAL; - } - - switch (id) { - case WLAN_EID_SSID: - case WLAN_EID_SUPP_RATES: - case WLAN_EID_FH_PARAMS: - case WLAN_EID_DS_PARAMS: - case WLAN_EID_CF_PARAMS: - case WLAN_EID_TIM: - case WLAN_EID_IBSS_PARAMS: - case WLAN_EID_CHALLENGE: - case WLAN_EID_ERP_INFO: - case WLAN_EID_EXT_SUPP_RATES: - break; - case WLAN_EID_VENDOR_SPECIFIC: - if (rtw_validate_vendor_specific_ies(pos, elen)) - unknown++; - break; - case WLAN_EID_RSN: - case WLAN_EID_PWR_CAPABILITY: - case WLAN_EID_SUPPORTED_CHANNELS: - case WLAN_EID_MOBILITY_DOMAIN: - case WLAN_EID_FAST_BSS_TRANSITION: - case WLAN_EID_TIMEOUT_INTERVAL: - case WLAN_EID_HT_CAPABILITY: - case WLAN_EID_HT_OPERATION: - default: - unknown++; - DBG_8723A("%s IEEE 802.11 ignored unknown element " - "(id =%d elen =%d)\n", __func__, id, elen); - break; - } - - left -= elen; - pos += elen; - } - - if (left) - return -EINVAL; - - return 0; -} -#endif - -static int -OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ -#ifdef CONFIG_8723AU_AP_MODE - u16 capab_info, listen_interval; - struct sta_info *pstat; - unsigned char reassoc; - int i, wpa_ie_len, left; - unsigned char supportRate[16]; - int supportRateNum; - unsigned short status = WLAN_STATUS_SUCCESS; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur = &pmlmeinfo->network; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - const u8 *pos, *p, *wpa_ie, *wps_ie; - u8 *pframe = skb->data; - uint pkt_len = skb->len; - int r; - - if ((pmlmeinfo->state & 0x03) != MSR_AP) - return _FAIL; - - left = pkt_len - sizeof(struct ieee80211_hdr_3addr); - if (ieee80211_is_assoc_req(mgmt->frame_control)) { - reassoc = 0; - pos = mgmt->u.assoc_req.variable; - left -= offsetof(struct ieee80211_mgmt, u.assoc_req.variable); - } else { /* WIFI_REASSOCREQ */ - reassoc = 1; - pos = mgmt->u.reassoc_req.variable; - left -= offsetof(struct ieee80211_mgmt, u.reassoc_req.variable); - } - - if (left < 0) { - DBG_8723A("handle_assoc(reassoc =%d) - too short payload " - "(len =%lu)\n", reassoc, (unsigned long)pkt_len); - return _FAIL; - } - - pstat = rtw_get_stainfo23a(pstapriv, mgmt->sa); - if (!pstat) { - status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA; - goto asoc_class2_error; - } - - /* These two are located at the same offsets whether it's an - * assoc_req or a reassoc_req */ - capab_info = get_unaligned_le16(&mgmt->u.assoc_req.capab_info); - listen_interval = - get_unaligned_le16(&mgmt->u.assoc_req.listen_interval); - - DBG_8723A("%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)) { - status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA; - goto asoc_class2_error; - } else { - pstat->state &= (~WIFI_FW_ASSOC_SUCCESS); - pstat->state |= WIFI_FW_ASSOC_STATE; - } - } else { - pstat->state &= (~WIFI_FW_AUTH_SUCCESS); - pstat->state |= WIFI_FW_ASSOC_STATE; - } - - pstat->capability = capab_info; - - /* now parse all ieee802_11 ie to point to elems */ - - if (rtw_validate_frame_ies(pos, left)) { - DBG_8723A("STA %pM sent invalid association request\n", - pstat->hwaddr); - status = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto OnAssocReq23aFail; - } - - /* now we should check all the fields... */ - /* checking SSID */ - p = cfg80211_find_ie(WLAN_EID_SSID, pos, left); - if (!p || p[1] == 0) { - /* broadcast ssid, however it is not allowed in assocreq */ - DBG_8723A("STA %pM sent invalid association request lacking an SSID\n", - pstat->hwaddr); - status = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto OnAssocReq23aFail; - } else { - /* check if ssid match */ - if (memcmp(p + 2, cur->Ssid.ssid, cur->Ssid.ssid_len)) - status = WLAN_STATUS_UNSPECIFIED_FAILURE; - - if (p[1] != cur->Ssid.ssid_len) - status = WLAN_STATUS_UNSPECIFIED_FAILURE; - } - - if (status != WLAN_STATUS_SUCCESS) - goto OnAssocReq23aFail; - - /* check if the supported rate is ok */ - p = cfg80211_find_ie(WLAN_EID_SUPP_RATES, pos, left); - if (!p) { - DBG_8723A("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; */ - - status = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto OnAssocReq23aFail; - } else { - memcpy(supportRate, p + 2, p[1]); - supportRateNum = p[1]; - - p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, pos, left); - if (p) { - if (supportRateNum <= sizeof(supportRate)) { - memcpy(supportRate+supportRateNum, p + 2, p[1]); - supportRateNum += p[1]; - } - } - } - - /* todo: mask supportRate between AP & STA -> move to update raid */ - /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */ - - /* update station supportRate */ - pstat->bssratelen = supportRateNum; - memcpy(pstat->bssrateset, supportRate, supportRateNum); - Update23aTblForSoftAP(pstat->bssrateset, pstat->bssratelen); - - /* check RSN/WPA/WPS */ - pstat->dot8021xalg = 0; - pstat->wpa_psk = 0; - pstat->wpa_group_cipher = 0; - pstat->wpa2_group_cipher = 0; - pstat->wpa_pairwise_cipher = 0; - pstat->wpa2_pairwise_cipher = 0; - memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie)); - - wpa_ie = cfg80211_find_ie(WLAN_EID_RSN, pos, left); - if (!wpa_ie) - wpa_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPA, - pos, left); - if (wpa_ie) { - int group_cipher = 0, pairwise_cipher = 0; - - wpa_ie_len = wpa_ie[1]; - if (psecuritypriv->wpa_psk & BIT(1)) { - r = rtw_parse_wpa2_ie23a(wpa_ie, wpa_ie_len + 2, - &group_cipher, - &pairwise_cipher, NULL); - if (r == _SUCCESS) { - pstat->dot8021xalg = 1;/* psk, todo:802.1x */ - pstat->wpa_psk |= BIT(1); - - pstat->wpa2_group_cipher = group_cipher & - psecuritypriv->wpa2_group_cipher; - pstat->wpa2_pairwise_cipher = pairwise_cipher & - psecuritypriv->wpa2_pairwise_cipher; - } else - status = WLAN_STATUS_INVALID_IE; - } else if (psecuritypriv->wpa_psk & BIT(0)) { - r = rtw_parse_wpa_ie23a(wpa_ie, wpa_ie_len + 2, - &group_cipher, &pairwise_cipher, - NULL); - if (r == _SUCCESS) { - pstat->dot8021xalg = 1;/* psk, todo:802.1x */ - pstat->wpa_psk |= BIT(0); - - pstat->wpa_group_cipher = group_cipher & - psecuritypriv->wpa_group_cipher; - pstat->wpa_pairwise_cipher = pairwise_cipher & - psecuritypriv->wpa_pairwise_cipher; - } else - status = WLAN_STATUS_INVALID_IE; - } else { - wpa_ie = NULL; - wpa_ie_len = 0; - } - if (wpa_ie && status == WLAN_STATUS_SUCCESS) { - if (!pstat->wpa_group_cipher) - status = WLAN_STATUS_INVALID_GROUP_CIPHER; - - if (!pstat->wpa_pairwise_cipher) - status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER; - } - } - - if (status != WLAN_STATUS_SUCCESS) - goto OnAssocReq23aFail; - - pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS); - - wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPS, - pos, left); - - if (!wpa_ie) { - if (wps_ie) { - DBG_8723A("STA included WPS IE in (Re)Association " - "Request - assume WPS is used\n"); - pstat->flags |= WLAN_STA_WPS; - } else { - DBG_8723A("STA did not include WPA/RSN IE in (Re)" - "Association Request - possible WPS use\n"); - pstat->flags |= WLAN_STA_MAYBE_WPS; - } - } else { - int copy_len; - - if (psecuritypriv->wpa_psk == 0) { - DBG_8723A("STA %pM: WPA/RSN IE in association request, but AP don't support WPA/RSN\n", - pstat->hwaddr); - - status = WLAN_STATUS_INVALID_IE; - - goto OnAssocReq23aFail; - } - - if (wps_ie) { - DBG_8723A("STA included WPS IE in (Re)Association " - "Request - WPS is used\n"); - pstat->flags |= WLAN_STA_WPS; - copy_len = 0; - } else { - copy_len = ((wpa_ie_len + 2) > sizeof(pstat->wpa_ie)) ? - sizeof(pstat->wpa_ie) : (wpa_ie_len + 2); - } - - if (copy_len > 0) - memcpy(pstat->wpa_ie, wpa_ie - 2, copy_len); - } - - /* check if there is WMM IE & support WWM-PS */ - pstat->flags &= ~WLAN_STA_WME; - pstat->qos_option = 0; - pstat->qos_info = 0; - pstat->has_legacy_ac = true; - pstat->uapsd_vo = 0; - pstat->uapsd_vi = 0; - pstat->uapsd_be = 0; - pstat->uapsd_bk = 0; - if (pmlmepriv->qos_option) { - const u8 *end = pos + left; - - p = pos; - - for (;;) { - left = end - p; - p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WMM, - p, left); - if (p) { - pstat->flags |= WLAN_STA_WME; - - pstat->qos_option = 1; - pstat->qos_info = *(p + 8); - - pstat->max_sp_len = - (pstat->qos_info >> 5) & 0x3; - - if ((pstat->qos_info & 0xf) != 0xf) - pstat->has_legacy_ac = true; - else - pstat->has_legacy_ac = false; - - if (pstat->qos_info & 0xf) { - if (pstat->qos_info & BIT(0)) - pstat->uapsd_vo = BIT(0)|BIT(1); - else - pstat->uapsd_vo = 0; - - if (pstat->qos_info & BIT(1)) - pstat->uapsd_vi = BIT(0)|BIT(1); - else - pstat->uapsd_vi = 0; - - if (pstat->qos_info & BIT(2)) - pstat->uapsd_bk = BIT(0)|BIT(1); - else - pstat->uapsd_bk = 0; - - if (pstat->qos_info & BIT(3)) - pstat->uapsd_be = BIT(0)|BIT(1); - else - pstat->uapsd_be = 0; - - break; - } - } else { - break; - } - p = p + p[1] + 2; - } - } - - /* save HT capabilities in the sta object */ - memset(&pstat->htpriv.ht_cap, 0, sizeof(struct ieee80211_ht_cap)); - p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pos, left); - - if (p && p[1] >= sizeof(struct ieee80211_ht_cap)) { - pstat->flags |= WLAN_STA_HT; - - pstat->flags |= WLAN_STA_WME; - - memcpy(&pstat->htpriv.ht_cap, p + 2, - sizeof(struct ieee80211_ht_cap)); - } else - pstat->flags &= ~WLAN_STA_HT; - - if (!pmlmepriv->htpriv.ht_option && pstat->flags & WLAN_STA_HT){ - status = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto OnAssocReq23aFail; - } - - if (pstat->flags & WLAN_STA_HT && - (pstat->wpa2_pairwise_cipher & WPA_CIPHER_TKIP || - pstat->wpa_pairwise_cipher & WPA_CIPHER_TKIP)) { - DBG_8723A("HT: %pM tried to use TKIP with HT association\n", - pstat->hwaddr); - - /* status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; */ - /* goto OnAssocReq23aFail; */ - } - - pstat->flags |= WLAN_STA_NONERP; - for (i = 0; i < pstat->bssratelen; i++) { - if ((pstat->bssrateset[i] & 0x7f) > 22) { - pstat->flags &= ~WLAN_STA_NONERP; - break; - } - } - - if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) - pstat->flags |= WLAN_STA_SHORT_PREAMBLE; - else - pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE; - - if (status != WLAN_STATUS_SUCCESS) - goto OnAssocReq23aFail; - - /* TODO: identify_proprietary_vendor_ie(); */ - /* Realtek proprietary IE */ - /* identify if this is Broadcom sta */ - /* identify if this is ralink sta */ - /* Customer proprietary IE */ - - /* get a unique AID */ - if (pstat->aid > 0) { - DBG_8723A(" old AID %d\n", pstat->aid); - } else { - for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++) - if (pstapriv->sta_aid[pstat->aid - 1] == NULL) - break; - - if (pstat->aid > NUM_STA) - pstat->aid = NUM_STA; - if (pstat->aid > pstapriv->max_num_sta) { - - pstat->aid = 0; - - DBG_8723A(" no room for more AIDs\n"); - - status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; - - goto OnAssocReq23aFail; - } else { - pstapriv->sta_aid[pstat->aid - 1] = pstat; - DBG_8723A("allocate new AID = (%d)\n", pstat->aid); - } - } - - pstat->state &= ~WIFI_FW_ASSOC_STATE; - pstat->state |= WIFI_FW_ASSOC_SUCCESS; - - spin_lock_bh(&pstapriv->auth_list_lock); - if (!list_empty(&pstat->auth_list)) { - list_del_init(&pstat->auth_list); - pstapriv->auth_list_cnt--; - } - spin_unlock_bh(&pstapriv->auth_list_lock); - - spin_lock_bh(&pstapriv->asoc_list_lock); - if (list_empty(&pstat->asoc_list)) { - pstat->expire_to = pstapriv->expire_to; - list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list); - pstapriv->asoc_list_cnt++; - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - /* now the station is qualified to join our BSS... */ - if (pstat->state & WIFI_FW_ASSOC_SUCCESS && - status == WLAN_STATUS_SUCCESS) { - /* 1 bss_cap_update & sta_info_update23a */ - bss_cap_update_on_sta_join23a(padapter, pstat); - sta_info_update23a(padapter, pstat); - - /* issue assoc rsp before notify station join event. */ - if (ieee80211_is_assoc_req(mgmt->frame_control)) - issue_assocrsp(padapter, status, pstat, - IEEE80211_STYPE_ASSOC_RESP); - else - issue_assocrsp(padapter, status, pstat, - IEEE80211_STYPE_REASSOC_RESP); - - /* 2 - report to upper layer */ - DBG_8723A("indicate_sta_join_event to upper layer - hostapd\n"); - rtw_cfg80211_indicate_sta_assoc(padapter, pframe, pkt_len); - - /* 3-(1) report sta add event */ - report_add_sta_event23a(padapter, pstat->hwaddr, pstat->aid); - } - - return _SUCCESS; - -asoc_class2_error: - - issue_deauth23a(padapter, mgmt->sa, status); - return _FAIL; - -OnAssocReq23aFail: - - pstat->aid = 0; - if (ieee80211_is_assoc_req(mgmt->frame_control)) - issue_assocrsp(padapter, status, pstat, - IEEE80211_STYPE_ASSOC_RESP); - else - issue_assocrsp(padapter, status, pstat, - IEEE80211_STYPE_REASSOC_RESP); - -#endif /* CONFIG_8723AU_AP_MODE */ - - return _FAIL; -} - -static int -OnAssocRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *pmgmt = (struct ieee80211_mgmt *) skb->data; - int res; - unsigned short status; - const u8 *p, *pie; - u8 *pframe = skb->data; - int pkt_len = skb->len; - int pielen; - - DBG_8723A("%s\n", __func__); - - /* check A1 matches or not */ - if (!ether_addr_equal(myid(&padapter->eeprompriv), pmgmt->da)) - return _SUCCESS; - - if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE))) - return _SUCCESS; - - if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) - return _SUCCESS; - - del_timer_sync(&pmlmeext->link_timer); - - /* status */ - status = le16_to_cpu(pmgmt->u.assoc_resp.status_code); - if (status > 0) { - DBG_8723A("assoc reject, status code: %d\n", status); - pmlmeinfo->state = MSR_NOLINK; - res = -4; - goto report_assoc_result; - } - - /* get capabilities */ - pmlmeinfo->capability = le16_to_cpu(pmgmt->u.assoc_resp.capab_info); - - /* set slot time */ - pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10))? 9: 20; - - /* AID */ - res = pmlmeinfo->aid = le16_to_cpu(pmgmt->u.assoc_resp.aid) & 0x3fff; - - pie = pframe + offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); - pielen = pkt_len - - offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); - - p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, - pmgmt->u.assoc_resp.variable, pielen); - if (p && p[1]) - HT_caps_handler23a(padapter, p); - - p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, - pmgmt->u.assoc_resp.variable, pielen); - if (p && p[1]) - HT_info_handler23a(padapter, p); - - p = cfg80211_find_ie(WLAN_EID_ERP_INFO, - pmgmt->u.assoc_resp.variable, pielen); - if (p && p[1]) - ERP_IE_handler23a(padapter, p); - - pie = pframe + offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); - while (true) { - p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WMM, - pie, pframe + pkt_len - pie); - if (!p) - break; - - pie = p + p[1] + 2; - /* if this IE is too short, try the next */ - if (p[1] <= 4) - continue; - /* if this IE is WMM params, we found what we wanted */ - if (p[6] == 1) - break; - } - - if (p && p[1]) - WMM_param_handler23a(padapter, p); - - pmlmeinfo->state &= ~WIFI_FW_ASSOC_STATE; - pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; - - /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */ - UpdateBrateTbl23a(padapter, pmlmeinfo->network.SupportedRates); - -report_assoc_result: - pmlmepriv->assoc_rsp_len = 0; - if (res > 0) { - kfree(pmlmepriv->assoc_rsp); - pmlmepriv->assoc_rsp = kmalloc(pkt_len, GFP_ATOMIC); - if (pmlmepriv->assoc_rsp) { - memcpy(pmlmepriv->assoc_rsp, pframe, pkt_len); - pmlmepriv->assoc_rsp_len = pkt_len; - } - } else - kfree(pmlmepriv->assoc_rsp); - - report_join_res23a(padapter, res); - - return _SUCCESS; -} - -static int -OnDeAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - unsigned short reason; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - - if (!ether_addr_equal(mgmt->bssid, - get_my_bssid23a(&pmlmeinfo->network))) - return _SUCCESS; - - reason = le16_to_cpu(mgmt->u.deauth.reason_code); - - DBG_8723A("%s Reason code(%d)\n", __func__, reason); - -#ifdef CONFIG_8723AU_AP_MODE - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - - DBG_8723A_LEVEL(_drv_always_, "ap recv deauth reason code(%d) " - "sta:%pM\n", reason, mgmt->sa); - - psta = rtw_get_stainfo23a(pstapriv, mgmt->sa); - if (psta) { - u8 updated = 0; - - spin_lock_bh(&pstapriv->asoc_list_lock); - if (!list_empty(&psta->asoc_list)) { - list_del_init(&psta->asoc_list); - pstapriv->asoc_list_cnt--; - updated = ap_free_sta23a(padapter, psta, - false, reason); - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - associated_clients_update23a(padapter, updated); - } - - return _SUCCESS; - } else -#endif - { - DBG_8723A_LEVEL(_drv_always_, "sta recv deauth reason code(%d) " - "sta:%pM\n", reason, mgmt->bssid); - - receive_disconnect23a(padapter, mgmt->bssid, reason); - } - pmlmepriv->LinkDetectInfo.bBusyTraffic = false; - - return _SUCCESS; -} - -static int -OnDisassoc23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - unsigned short reason; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - - if (!ether_addr_equal(mgmt->bssid, - get_my_bssid23a(&pmlmeinfo->network))) - return _SUCCESS; - - reason = le16_to_cpu(mgmt->u.disassoc.reason_code); - - DBG_8723A("%s Reason code(%d)\n", __func__, reason); - -#ifdef CONFIG_8723AU_AP_MODE - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - - DBG_8723A_LEVEL(_drv_always_, "ap recv disassoc reason code(%d)" - " sta:%pM\n", reason, mgmt->sa); - - psta = rtw_get_stainfo23a(pstapriv, mgmt->sa); - if (psta) { - u8 updated = 0; - - spin_lock_bh(&pstapriv->asoc_list_lock); - if (!list_empty(&psta->asoc_list)) { - list_del_init(&psta->asoc_list); - pstapriv->asoc_list_cnt--; - updated = ap_free_sta23a(padapter, psta, - false, reason); - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - associated_clients_update23a(padapter, updated); - } - - return _SUCCESS; - } else -#endif - { - DBG_8723A_LEVEL(_drv_always_, "ap recv disassoc reason " - "code(%d) sta:%pM\n", reason, mgmt->bssid); - - receive_disconnect23a(padapter, mgmt->bssid, reason); - } - pmlmepriv->LinkDetectInfo.bBusyTraffic = false; - return _SUCCESS; -} - -static int -OnAtim23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - DBG_8723A("%s\n", __func__); - return _SUCCESS; -} - -static int -on_action_spct23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - return _FAIL; -} - -static int -OnAction23a_qos(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - return _SUCCESS; -} - -static int -OnAction23a_dls(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - return _SUCCESS; -} - -static int OnAction23a_back23a(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ - u8 *addr; - struct sta_info *psta = NULL; - struct recv_reorder_ctrl *preorder_ctrl; - unsigned char category, action; - unsigned short tid, status, capab, params, reason_code = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - struct sta_priv *pstapriv = &padapter->stapriv; - - /* check RA matches or not */ - if (!ether_addr_equal(myid(&padapter->eeprompriv), mgmt->da)) - return _SUCCESS; - - DBG_8723A("%s\n", __func__); - - if ((pmlmeinfo->state&0x03) != MSR_AP) - if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) - return _SUCCESS; - - addr = mgmt->sa; - psta = rtw_get_stainfo23a(pstapriv, addr); - - if (!psta) - return _SUCCESS; - - category = mgmt->u.action.category; - if (category == WLAN_CATEGORY_BACK) { /* representing Block Ack */ - if (!pmlmeinfo->HT_enable) - return _SUCCESS; - /* action_code is located in the same place for all - action events, so pick any */ - action = mgmt->u.action.u.wme_action.action_code; - DBG_8723A("%s, action =%d\n", __func__, action); - switch (action) { - case WLAN_ACTION_ADDBA_REQ: /* ADDBA request */ - memcpy(&pmlmeinfo->ADDBA_req, - &mgmt->u.action.u.addba_req.dialog_token, - sizeof(struct ADDBA_request)); - process_addba_req23a(padapter, - (u8 *)&pmlmeinfo->ADDBA_req, addr); - if (pmlmeinfo->bAcceptAddbaReq == true) - issue_action_BA23a(padapter, addr, - WLAN_ACTION_ADDBA_RESP, 0); - else { - /* reject ADDBA Req */ - issue_action_BA23a(padapter, addr, - WLAN_ACTION_ADDBA_RESP, 37); - } - break; - case WLAN_ACTION_ADDBA_RESP: /* ADDBA response */ - status = get_unaligned_le16( - &mgmt->u.action.u.addba_resp.status); - capab = get_unaligned_le16( - &mgmt->u.action.u.addba_resp.capab); - tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; - if (status == 0) { /* successful */ - DBG_8723A("agg_enable for TID =%d\n", tid); - psta->htpriv.agg_enable_bitmap |= BIT(tid); - psta->htpriv.candidate_tid_bitmap &= ~BIT(tid); - } else - psta->htpriv.agg_enable_bitmap &= ~BIT(tid); - break; - - case WLAN_ACTION_DELBA: /* DELBA */ - params = get_unaligned_le16( - &mgmt->u.action.u.delba.params); - tid = params >> 12; - - if (params & IEEE80211_DELBA_PARAM_INITIATOR_MASK) { - preorder_ctrl = &psta->recvreorder_ctrl[tid]; - preorder_ctrl->enable = false; - preorder_ctrl->indicate_seq = 0xffff; - } else { - psta->htpriv.agg_enable_bitmap &= ~BIT(tid); - psta->htpriv.candidate_tid_bitmap &= ~BIT(tid); - } - reason_code = get_unaligned_le16( - &mgmt->u.action.u.delba.reason_code); - /* todo: how to notify the host while receiving - DELETE BA */ - break; - default: - break; - } - } - return _SUCCESS; -} - -static int on_action_public23a(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - u8 *pframe = skb->data; - int freq, channel; - - /* check RA matches or not */ - if (!ether_addr_equal(myid(&padapter->eeprompriv), hdr->addr1)) - return _FAIL; - - channel = rtw_get_oper_ch23a(padapter); - - if (channel <= RTW_CH_MAX_2G_CHANNEL) - freq = ieee80211_channel_to_frequency(channel, - NL80211_BAND_2GHZ); - else - freq = ieee80211_channel_to_frequency(channel, - NL80211_BAND_5GHZ); - - if (cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, pframe, - skb->len, 0)) - return _SUCCESS; - - return _FAIL; -} - -static int -OnAction23a_ht(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - return _SUCCESS; -} - -static int -OnAction23a_wmm(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - return _SUCCESS; -} - -static int -OnAction23a_p2p(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - return _SUCCESS; -} - -static int -OnAction23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - int i; - u8 category; - struct action_handler *ptable; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - - category = mgmt->u.action.category; - - for (i = 0; i < ARRAY_SIZE(OnAction23a_tbl); i++) { - ptable = &OnAction23a_tbl[i]; - - if (category == ptable->num) - ptable->func(padapter, precv_frame); - } - - return _SUCCESS; -} - -static int DoReserved23a(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ - return _SUCCESS; -} - -struct xmit_frame *alloc_mgtxmitframe23a(struct xmit_priv *pxmitpriv) -{ - struct xmit_frame *pmgntframe; - struct xmit_buf *pxmitbuf; - - pmgntframe = rtw_alloc_xmitframe23a_ext(pxmitpriv); - - if (!pmgntframe) { - DBG_8723A("%s(%s): alloc xmitframe fail\n", __func__, - pxmitpriv->adapter->pnetdev->name); - goto exit; - } - - pxmitbuf = rtw_alloc_xmitbuf23a_ext(pxmitpriv); - if (!pxmitbuf) { - DBG_8723A("%s(%s): alloc xmitbuf fail\n", __func__, - pxmitpriv->adapter->pnetdev->name); - rtw_free_xmitframe23a(pxmitpriv, pmgntframe); - pmgntframe = NULL; - goto exit; - } - - pmgntframe->frame_tag = MGNT_FRAMETAG; - pmgntframe->pxmitbuf = pxmitbuf; - pmgntframe->buf_addr = pxmitbuf->pbuf; - pxmitbuf->priv_data = pmgntframe; - -exit: - return pmgntframe; -} - -/**************************************************************************** - -Following are some TX functions for WiFi MLME - -*****************************************************************************/ - -void update_mgnt_tx_rate23a(struct rtw_adapter *padapter, u8 rate) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - pmlmeext->tx_rate = rate; - DBG_8723A("%s(): rate = %x\n", __func__, rate); -} - -void update_mgntframe_attrib23a(struct rtw_adapter *padapter, - struct pkt_attrib *pattrib) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - memset((u8 *)pattrib, 0, sizeof(struct pkt_attrib)); - - pattrib->hdrlen = 24; - pattrib->nr_frags = 1; - pattrib->priority = 7; - pattrib->mac_id = 0; - pattrib->qsel = 0x12; - - pattrib->pktlen = 0; - - if (pmlmeext->cur_wireless_mode & WIRELESS_11B) - pattrib->raid = 6;/* b mode */ - else - pattrib->raid = 5;/* a/g mode */ - - pattrib->encrypt = 0; - pattrib->bswenc = false; - - pattrib->qos_en = false; - pattrib->ht_en = false; - pattrib->bwmode = HT_CHANNEL_WIDTH_20; - pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - pattrib->sgi = false; - - pattrib->seqnum = pmlmeext->mgnt_seq; - - pattrib->retry_ctrl = true; -} - -void dump_mgntframe23a(struct rtw_adapter *padapter, - struct xmit_frame *pmgntframe) -{ - if (padapter->bSurpriseRemoved == true || - padapter->bDriverStopped == true) - return; - - rtl8723au_mgnt_xmit(padapter, pmgntframe); -} - -int dump_mgntframe23a_and_wait(struct rtw_adapter *padapter, - struct xmit_frame *pmgntframe, int timeout_ms) -{ - int ret = _FAIL; - unsigned long irqL; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf; - struct submit_ctx sctx; - - if (padapter->bSurpriseRemoved == true || - padapter->bDriverStopped == true) - return ret; - - rtw_sctx_init23a(&sctx, timeout_ms); - pxmitbuf->sctx = &sctx; - - ret = rtl8723au_mgnt_xmit(padapter, pmgntframe); - - if (ret == _SUCCESS) - ret = rtw_sctx_wait23a(&sctx); - - spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL); - pxmitbuf->sctx = NULL; - spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL); - - return ret; -} - -int dump_mgntframe23a_and_wait_ack23a(struct rtw_adapter *padapter, - struct xmit_frame *pmgntframe) -{ - int ret = _FAIL; - u32 timeout_ms = 500;/* 500ms */ - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - if (padapter->bSurpriseRemoved == true || - padapter->bDriverStopped == true) - return _FAIL; - - mutex_lock(&pxmitpriv->ack_tx_mutex); - pxmitpriv->ack_tx = true; - - pmgntframe->ack_report = 1; - if (rtl8723au_mgnt_xmit(padapter, pmgntframe) == _SUCCESS) - ret = rtw_ack_tx_wait23a(pxmitpriv, timeout_ms); - - pxmitpriv->ack_tx = false; - mutex_unlock(&pxmitpriv->ack_tx_mutex); - - return ret; -} - -static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode) -{ - u8 *ssid_ie; - int ssid_len_ori; - int len_diff = 0; - u8 *next_ie; - u32 remain_len; - - ssid_ie = rtw_get_ie23a(ies, WLAN_EID_SSID, &ssid_len_ori, ies_len); - - /* DBG_8723A("%s hidden_ssid_mode:%u, ssid_ie:%p, ssid_len_ori:%d\n", - __func__, hidden_ssid_mode, ssid_ie, ssid_len_ori); */ - - if (ssid_ie && ssid_len_ori > 0) { - switch (hidden_ssid_mode) { - case 1: - next_ie = ssid_ie + 2 + ssid_len_ori; - remain_len = ies_len -(next_ie-ies); - - ssid_ie[1] = 0; - memcpy(ssid_ie+2, next_ie, remain_len); - len_diff -= ssid_len_ori; - - break; - case 2: - memset(&ssid_ie[2], 0, ssid_len_ori); - break; - default: - break; - } - } - - return len_diff; -} - -void issue_beacon23a(struct rtw_adapter *padapter, int timeout_ms) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_mgmt *mgmt; - unsigned int rate_len; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - 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}; - const u8 *wps_ie; - u8 sr = 0; - int len_diff; - - /* DBG_8723A("%s\n", __func__); */ - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) { - DBG_8723A("%s, alloc mgnt frame fail\n", __func__); - return; - } -#ifdef CONFIG_8723AU_AP_MODE - spin_lock_bh(&pmlmepriv->bcn_update_lock); -#endif - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - pattrib->qsel = 0x10; - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - mgmt = (struct ieee80211_mgmt *)pframe; - - mgmt->frame_control = - cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); - mgmt->seq_ctrl = 0; - - ether_addr_copy(mgmt->da, bc_addr); - ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); - ether_addr_copy(mgmt->bssid, get_my_bssid23a(cur_network)); - - /* timestamp will be inserted by hardware */ - - put_unaligned_le16(cur_network->beacon_interval, - &mgmt->u.beacon.beacon_int); - - put_unaligned_le16(cur_network->capability, - &mgmt->u.beacon.capab_info); - - pframe = mgmt->u.beacon.variable; - pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.beacon.variable); - - if ((pmlmeinfo->state & 0x03) == MSR_AP) { - u8 *iebuf; - int buflen; - /* DBG_8723A("ie len =%d\n", cur_network->IELength); */ - memcpy(pframe, cur_network->IEs, cur_network->IELength); - len_diff = update_hidden_ssid(pframe, cur_network->IELength, - pmlmeinfo->hidden_ssid_mode); - pframe += (cur_network->IELength+len_diff); - pattrib->pktlen += (cur_network->IELength+len_diff); - - iebuf = mgmt->u.beacon.variable; - buflen = pattrib->pktlen - - offsetof(struct ieee80211_mgmt, u.beacon.variable); - wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPS, - iebuf, buflen); - - if (wps_ie && wps_ie[1] > 0) { - rtw_get_wps_attr_content23a(wps_ie, wps_ie[1], - WPS_ATTR_SELECTED_REGISTRAR, - (u8 *)&sr); - } - if (sr != 0) - set_fwstate(pmlmepriv, WIFI_UNDER_WPS); - else - _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS); - - goto _issue_bcn; - } - - /* SSID */ - pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, - cur_network->Ssid.ssid_len, - cur_network->Ssid.ssid, &pattrib->pktlen); - - /* supported rates... */ - rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates); - pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, - ((rate_len > 8)? 8: rate_len), - cur_network->SupportedRates, &pattrib->pktlen); - - /* DS parameter set */ - pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *) - &cur_network->DSConfig, &pattrib->pktlen); - - /* if ((pmlmeinfo->state&0x03) == MSR_ADHOC) */ - { - u8 erpinfo = 0; - u32 ATIMWindow; - /* IBSS Parameter Set... */ - /* ATIMWindow = cur->ATIMWindow; */ - ATIMWindow = 0; - pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2, - (unsigned char *)&ATIMWindow, - &pattrib->pktlen); - - /* ERP IE */ - pframe = rtw_set_ie23a(pframe, WLAN_EID_ERP_INFO, 1, - &erpinfo, &pattrib->pktlen); - } - - /* EXTERNDED SUPPORTED RATE */ - if (rate_len > 8) - pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES, - rate_len - 8, - cur_network->SupportedRates + 8, - &pattrib->pktlen); - - /* todo:HT for adhoc */ - -_issue_bcn: - -#ifdef CONFIG_8723AU_AP_MODE - pmlmepriv->update_bcn = false; - - spin_unlock_bh(&pmlmepriv->bcn_update_lock); -#endif - - if ((pattrib->pktlen + TXDESC_SIZE) > 512) { - DBG_8723A("beacon frame too large\n"); - return; - } - - pattrib->last_txcmdsz = pattrib->pktlen; - - /* DBG_8723A("issue bcn_sz =%d\n", pattrib->last_txcmdsz); */ - if (timeout_ms > 0) - dump_mgntframe23a_and_wait(padapter, pmgntframe, timeout_ms); - else - dump_mgntframe23a(padapter, pmgntframe); -} - -static void issue_probersp(struct rtw_adapter *padapter, unsigned char *da) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_mgmt *mgmt; - unsigned char *mac, *bssid; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; -#ifdef CONFIG_8723AU_AP_MODE - const u8 *pwps_ie; - u8 *ssid_ie; - int ssid_ielen; - int ssid_ielen_diff; - u8 buf[MAX_IE_SZ]; -#endif - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - unsigned int rate_len; - - /* DBG_8723A("%s\n", __func__); */ - - if (cur_network->IELength > MAX_IE_SZ) - return; - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) { - DBG_8723A("%s, alloc mgnt frame fail\n", __func__); - return; - } - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET; - mgmt = (struct ieee80211_mgmt *)pframe; - - mac = myid(&padapter->eeprompriv); - bssid = cur_network->MacAddress; - - mgmt->frame_control = - cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP); - - ether_addr_copy(mgmt->da, da); - ether_addr_copy(mgmt->sa, mac); - ether_addr_copy(mgmt->bssid, bssid); - - mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - pmlmeext->mgnt_seq++; - - pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); - - /* timestamp will be inserted by hardware */ - put_unaligned_le16(cur_network->beacon_interval, - &mgmt->u.probe_resp.beacon_int); - - put_unaligned_le16(cur_network->capability, - &mgmt->u.probe_resp.capab_info); - - pframe = mgmt->u.probe_resp.variable; - pattrib->pktlen = - offsetof(struct ieee80211_mgmt, u.probe_resp.variable); - - /* below for ad-hoc mode */ - -#ifdef CONFIG_8723AU_AP_MODE - if ((pmlmeinfo->state & 0x03) == MSR_AP) { - pwps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPS, - cur_network->IEs, - cur_network->IELength); - - memcpy(pframe, cur_network->IEs, cur_network->IELength); - pframe += cur_network->IELength; - pattrib->pktlen += cur_network->IELength; - - /* retrieve SSID IE from cur_network->Ssid */ - - ssid_ie = rtw_get_ie23a(mgmt->u.probe_resp.variable, - WLAN_EID_SSID, &ssid_ielen, - pframe - mgmt->u.probe_resp.variable); - - ssid_ielen_diff = cur_network->Ssid.ssid_len - ssid_ielen; - - if (ssid_ie && cur_network->Ssid.ssid_len) { - uint remainder_ielen; - u8 *remainder_ie; - - remainder_ie = ssid_ie + 2; - - remainder_ielen = pframe - remainder_ie; - - DBG_8723A_LEVEL(_drv_warning_, "%s(%s): " - "remainder_ielen > MAX_IE_SZ\n", - __func__, padapter->pnetdev->name); - if (remainder_ielen > MAX_IE_SZ) - remainder_ielen = MAX_IE_SZ; - - memcpy(buf, remainder_ie, remainder_ielen); - memcpy(remainder_ie + ssid_ielen_diff, buf, - remainder_ielen); - *(ssid_ie + 1) = cur_network->Ssid.ssid_len; - memcpy(ssid_ie + 2, cur_network->Ssid.ssid, - cur_network->Ssid.ssid_len); - - pframe += ssid_ielen_diff; - pattrib->pktlen += ssid_ielen_diff; - } - } else -#endif - { - /* SSID */ - pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, - cur_network->Ssid.ssid_len, - cur_network->Ssid.ssid, - &pattrib->pktlen); - - /* supported rates... */ - rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates); - pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, - ((rate_len > 8)? 8: rate_len), - cur_network->SupportedRates, - &pattrib->pktlen); - - /* DS parameter set */ - pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1, - (unsigned char *)&cur_network->DSConfig, - &pattrib->pktlen); - - if ((pmlmeinfo->state & 0x03) == MSR_ADHOC) { - u8 erpinfo = 0; - u32 ATIMWindow; - /* IBSS Parameter Set... */ - /* ATIMWindow = cur->ATIMWindow; */ - ATIMWindow = 0; - pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2, - (unsigned char *)&ATIMWindow, - &pattrib->pktlen); - - /* ERP IE */ - pframe = rtw_set_ie23a(pframe, WLAN_EID_ERP_INFO, 1, - &erpinfo, &pattrib->pktlen); - } - - /* EXTERNDED SUPPORTED RATE */ - if (rate_len > 8) - pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES, - rate_len - 8, - cur_network->SupportedRates + 8, - &pattrib->pktlen); - - /* todo:HT for adhoc */ - } - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe23a(padapter, pmgntframe); -} - -static int _issue_probereq(struct rtw_adapter *padapter, - struct cfg80211_ssid *pssid, u8 *da, int wait_ack) -{ - int ret = _FAIL; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_hdr *pwlanhdr; - unsigned char *mac; - unsigned char bssrate[NumRates]; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - 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_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) - goto exit; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_hdr *)pframe; - - mac = myid(&padapter->eeprompriv); - - pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_PROBE_REQ); - - if (da) { - /* unicast probe request frame */ - ether_addr_copy(pwlanhdr->addr1, da); - 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); - } - - ether_addr_copy(pwlanhdr->addr2, mac); - - pwlanhdr->seq_ctrl = - cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - - pmlmeext->mgnt_seq++; - - pframe += sizeof (struct ieee80211_hdr_3addr); - pattrib->pktlen = sizeof (struct ieee80211_hdr_3addr); - - if (pssid) - pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, pssid->ssid_len, - pssid->ssid, &pattrib->pktlen); - else - pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, 0, NULL, - &pattrib->pktlen); - - get_rate_set23a(padapter, bssrate, &bssrate_len); - - if (bssrate_len > 8) { - pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8, - bssrate, &pattrib->pktlen); - pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES, - (bssrate_len - 8), (bssrate + 8), - &pattrib->pktlen); - } else { - pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, - bssrate_len, bssrate, &pattrib->pktlen); - } - - /* add wps_ie for wps2.0 */ - if (pmlmepriv->wps_probe_req_ie_len>0 && pmlmepriv->wps_probe_req_ie) { - memcpy(pframe, pmlmepriv->wps_probe_req_ie, - pmlmepriv->wps_probe_req_ie_len); - pframe += pmlmepriv->wps_probe_req_ie_len; - pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len; - } - - 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_mgntframe23a_and_wait_ack23a(padapter, pmgntframe); - } else { - dump_mgntframe23a(padapter, pmgntframe); - ret = _SUCCESS; - } - -exit: - return ret; -} - -static inline void issue_probereq(struct rtw_adapter *padapter, - struct cfg80211_ssid *pssid, u8 *da) -{ - _issue_probereq(padapter, pssid, da, false); -} - -static int issue_probereq_ex(struct rtw_adapter *padapter, - struct cfg80211_ssid *pssid, u8 *da, - int try_cnt, int wait_ms) -{ - int ret; - int i = 0; - unsigned long start = jiffies; - - do { - ret = _issue_probereq(padapter, pssid, da, - wait_ms > 0 ? true : false); - - i++; - - if (padapter->bDriverStopped || padapter->bSurpriseRemoved) - break; - - if (i < try_cnt && wait_ms > 0 && ret == _FAIL) - msleep(wait_ms); - - } while((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); - - if (ret != _FAIL) { - ret = _SUCCESS; - goto exit; - } - - if (try_cnt && wait_ms) { - if (da) - DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n", - __func__, padapter->pnetdev->name, - da, rtw_get_oper_ch23a(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - else - DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n", - __func__, padapter->pnetdev->name, - rtw_get_oper_ch23a(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - } -exit: - return ret; -} - -/* if psta == NULL, indiate we are station(client) now... */ -static void issue_auth(struct rtw_adapter *padapter, struct sta_info *psta, - unsigned short status) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_mgmt *mgmt; - unsigned int val32; - u16 auth_algo; - int use_shared_key = 0; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - mgmt = (struct ieee80211_mgmt *)pframe; - - mgmt->frame_control = - cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH); - mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - pmlmeext->mgnt_seq++; - - pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.auth.variable); - - if (psta) { /* for AP mode */ -#ifdef CONFIG_8723AU_AP_MODE - unsigned short val16; - - ether_addr_copy(mgmt->da, psta->hwaddr); - ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); - ether_addr_copy(mgmt->bssid, myid(&padapter->eeprompriv)); - - /* setting auth algo number */ - val16 = (u16)psta->authalg; - - if (status != WLAN_STATUS_SUCCESS) - val16 = 0; - - if (val16) - use_shared_key = 1; - - mgmt->u.auth.auth_alg = cpu_to_le16(val16); - - /* setting auth seq number */ - mgmt->u.auth.auth_transaction = - cpu_to_le16((u16)psta->auth_seq); - - /* setting status code... */ - mgmt->u.auth.status_code = cpu_to_le16(status); - - pframe = mgmt->u.auth.variable; - /* added challenging text... */ - if ((psta->auth_seq == 2) && - (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) - pframe = rtw_set_ie23a(pframe, WLAN_EID_CHALLENGE, 128, - psta->chg_txt, &pattrib->pktlen); -#endif - } else { - struct ieee80211_mgmt *iv_mgmt; - - ether_addr_copy(mgmt->da, get_my_bssid23a(&pmlmeinfo->network)); - ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); - ether_addr_copy(mgmt->bssid, - get_my_bssid23a(&pmlmeinfo->network)); - - /* setting auth algo number */ - /* 0:OPEN System, 1:Shared key */ - if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) { - use_shared_key = 1; - auth_algo = WLAN_AUTH_SHARED_KEY; - } else - auth_algo = WLAN_AUTH_OPEN; - - /* DBG_8723A("%s auth_algo = %s auth_seq =%d\n", __func__, - (pmlmeinfo->auth_algo == 0)?"OPEN":"SHARED", - pmlmeinfo->auth_seq); */ - - /* setting IV for auth seq #3 */ - if ((pmlmeinfo->auth_seq == 3) && - (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && - (use_shared_key == 1)) { - u32 *piv = (u32 *)&mgmt->u.auth; - - iv_mgmt = (struct ieee80211_mgmt *)(pframe + 4); - /* DBG_8723A("==> iv(%d), key_index(%d)\n", - pmlmeinfo->iv, pmlmeinfo->key_index); */ - val32 = (pmlmeinfo->iv & 0x3fffffff) | - (pmlmeinfo->key_index << 30); - pmlmeinfo->iv++; - put_unaligned_le32(val32, piv); - - pattrib->pktlen += 4; - - pattrib->iv_len = IEEE80211_WEP_IV_LEN; - } else - iv_mgmt = mgmt; - - iv_mgmt->u.auth.auth_alg = cpu_to_le16(auth_algo); - - /* setting auth seq number */ - iv_mgmt->u.auth.auth_transaction = - cpu_to_le16(pmlmeinfo->auth_seq); - - /* setting status code... */ - iv_mgmt->u.auth.status_code = cpu_to_le16(status); - - pframe = iv_mgmt->u.auth.variable; - - /* then checking to see if sending challenging text... */ - if ((pmlmeinfo->auth_seq == 3) && - (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && - (use_shared_key == 1)) { - pframe = rtw_set_ie23a(pframe, WLAN_EID_CHALLENGE, 128, - pmlmeinfo->chg_txt, - &pattrib->pktlen); - - mgmt->frame_control |= - cpu_to_le16(IEEE80211_FCTL_PROTECTED); - - pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); - - pattrib->encrypt = WLAN_CIPHER_SUITE_WEP40; - - pattrib->icv_len = IEEE80211_WEP_ICV_LEN; - - pattrib->pktlen += pattrib->icv_len; - } - } - - pattrib->last_txcmdsz = pattrib->pktlen; - - rtw_wep_encrypt23a(padapter, pmgntframe); - DBG_8723A("%s\n", __func__); - dump_mgntframe23a(padapter, pmgntframe); -} - -#ifdef CONFIG_8723AU_AP_MODE -static void issue_assocrsp(struct rtw_adapter *padapter, unsigned short status, - struct sta_info *pstat, u16 pkt_type) -{ - struct xmit_frame *pmgntframe; - struct ieee80211_mgmt *mgmt; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; - const u8 *p; - u8 *ie = pnetwork->IEs; - - DBG_8723A("%s\n", __func__); - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - mgmt = (struct ieee80211_mgmt *)pframe; - - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | pkt_type); - - ether_addr_copy(mgmt->da, pstat->hwaddr); - ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); - ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network)); - - mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - - pmlmeext->mgnt_seq++; - - pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); - pattrib->pktlen = - offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); - - mgmt->u.assoc_resp.capab_info = cpu_to_le16(pnetwork->capability); - mgmt->u.assoc_resp.status_code = cpu_to_le16(status); - mgmt->u.assoc_resp.aid = cpu_to_le16(pstat->aid | BIT(14) | BIT(15)); - - pframe = mgmt->u.assoc_resp.variable; - - if (pstat->bssratelen <= 8) { - pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, - pstat->bssratelen, pstat->bssrateset, - &pattrib->pktlen); - } else { - pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8, - pstat->bssrateset, &pattrib->pktlen); - pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES, - pstat->bssratelen - 8, - pstat->bssrateset + 8, &pattrib->pktlen); - } - - if (pstat->flags & WLAN_STA_HT && pmlmepriv->htpriv.ht_option) { - /* FILL HT CAP INFO IE */ - /* p = hostapd_eid_ht_capabilities_info(hapd, p); */ - p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ie, - pnetwork->IELength); - if (p && p[1]) { - memcpy(pframe, p, p[1] + 2); - pframe += (p[1] + 2); - pattrib->pktlen += (p[1] + 2); - } - - /* FILL HT ADD INFO IE */ - /* p = hostapd_eid_ht_operation(hapd, p); */ - p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, ie, - pnetwork->IELength); - if (p && p[1] > 0) { - memcpy(pframe, p, p[1] + 2); - pframe += (p[1] + 2); - pattrib->pktlen += (p[1] + 2); - } - } - - /* FILL WMM IE */ - if (pstat->flags & WLAN_STA_WME && pmlmepriv->qos_option) { - unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, - 0x01, 0x01}; - int ie_len = 0; - - for (p = ie; ; p += (ie_len + 2)) { - p = cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC, p, - pnetwork->IELength - (ie_len + 2)); - if (p) - ie_len = p[1]; - else - ie_len = 0; - if (p && !memcmp(p + 2, WMM_PARA_IE, 6)) { - memcpy(pframe, p, ie_len + 2); - pframe += (ie_len + 2); - pattrib->pktlen += (ie_len + 2); - - break; - } - - if (!p || ie_len == 0) - break; - } - } - - if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) { - pframe = rtw_set_ie23a(pframe, WLAN_EID_VENDOR_SPECIFIC, 6, - REALTEK_96B_IE, &pattrib->pktlen); - } - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe23a(padapter, pmgntframe); -} -#endif - -static void issue_assocreq(struct rtw_adapter *padapter) -{ - int ret = _FAIL; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - const u8 *p; - struct ieee80211_mgmt *mgmt; - unsigned int i, j, index = 0; - unsigned char rf_type, bssrate[NumRates], sta_bssrate[NumRates]; - struct registry_priv *pregpriv = &padapter->registrypriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - int bssrate_len = 0, sta_bssrate_len = 0, pie_len; - u8 *pie; - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) - goto exit; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET; - mgmt = (struct ieee80211_mgmt *)pframe; - - mgmt->frame_control = - cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ASSOC_REQ); - - ether_addr_copy(mgmt->da, get_my_bssid23a(&pmlmeinfo->network)); - ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); - ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network)); - - mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - pmlmeext->mgnt_seq++; - - /* caps */ - put_unaligned_le16(pmlmeinfo->network.capability, - &mgmt->u.assoc_req.capab_info); - /* todo: listen interval for power saving */ - put_unaligned_le16(3, &mgmt->u.assoc_req.listen_interval); - - pframe = mgmt->u.assoc_req.variable; - pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.assoc_req.variable); - - /* SSID */ - pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, - pmlmeinfo->network.Ssid.ssid_len, - pmlmeinfo->network.Ssid.ssid, &pattrib->pktlen); - - /* supported rate & extended supported rate */ - - get_rate_set23a(padapter, sta_bssrate, &sta_bssrate_len); - /* DBG_8723A("sta_bssrate_len =%d\n", sta_bssrate_len); */ - - /* for JAPAN, channel 14 can only uses B Mode(CCK) */ - if (pmlmeext->cur_channel == 14) - sta_bssrate_len = 4; - - /* for (i = 0; i < sta_bssrate_len; i++) { */ - /* DBG_8723A("sta_bssrate[%d]=%02X\n", i, sta_bssrate[i]); */ - /* */ - - for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) { - if (pmlmeinfo->network.SupportedRates[i] == 0) - break; - DBG_8723A("network.SupportedRates[%d]=%02X\n", i, - pmlmeinfo->network.SupportedRates[i]); - } - - for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) { - if (pmlmeinfo->network.SupportedRates[i] == 0) - break; - - /* Check if the AP's supported rates are also - supported by STA. */ - for (j = 0; j < sta_bssrate_len; j++) { - /* Avoid the proprietary data rate (22Mbps) of - Handlink WSG-4000 AP */ - if ((pmlmeinfo->network.SupportedRates[i] | - IEEE80211_BASIC_RATE_MASK) == - (sta_bssrate[j] | IEEE80211_BASIC_RATE_MASK)) { - /* DBG_8723A("match i = %d, j =%d\n", i, j); */ - break; - } - } - - if (j == sta_bssrate_len) { - /* the rate is not supported by STA */ - DBG_8723A("%s(): the rate[%d]=%02X is not supported by " - "STA!\n", __func__, i, - pmlmeinfo->network.SupportedRates[i]); - } else { - /* the rate is supported by STA */ - bssrate[index++] = pmlmeinfo->network.SupportedRates[i]; - } - } - - bssrate_len = index; - DBG_8723A("bssrate_len = %d\n", bssrate_len); - - if (bssrate_len == 0) { - rtw_free_xmitbuf23a(pxmitpriv, pmgntframe->pxmitbuf); - rtw_free_xmitframe23a(pxmitpriv, pmgntframe); - goto exit; /* don't connect to AP if no joint supported rate */ - } - - if (bssrate_len > 8) { - pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8, - bssrate, &pattrib->pktlen); - pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES, - (bssrate_len - 8), (bssrate + 8), - &pattrib->pktlen); - } else - pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, - bssrate_len, bssrate, &pattrib->pktlen); - - /* RSN */ - - pie = pmlmeinfo->network.IEs; - pie_len = pmlmeinfo->network.IELength; - - p = cfg80211_find_ie(WLAN_EID_RSN, pie, pie_len); - if (p) - pframe = rtw_set_ie23a(pframe, WLAN_EID_RSN, p[1], p + 2, - &pattrib->pktlen); - - /* HT caps */ - if (padapter->mlmepriv.htpriv.ht_option) { - p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pie, pie_len); - - if (p && !is_ap_in_tkip23a(padapter)) { - struct ieee80211_ht_cap *cap = &pmlmeinfo->ht_cap; - - memcpy(cap, p + 2, sizeof(struct ieee80211_ht_cap)); - - /* to disable 40M Hz support while gd_bw_40MHz_en = 0 */ - if (pregpriv->cbw40_enable == 0) { - cap->cap_info &= ~cpu_to_le16( - IEEE80211_HT_CAP_SGI_40 | - IEEE80211_HT_CAP_SUP_WIDTH_20_40); - } else { - cap->cap_info |= cpu_to_le16( - IEEE80211_HT_CAP_SUP_WIDTH_20_40); - } - - /* todo: disable SM power save mode */ - cap->cap_info |= cpu_to_le16(IEEE80211_HT_CAP_SM_PS); - - rf_type = rtl8723a_get_rf_type(padapter); - /* switch (pregpriv->rf_config) */ - switch (rf_type) { - case RF_1T1R: - /* RX STBC One spatial stream */ - if (pregpriv->rx_stbc) - cap->cap_info |= cpu_to_le16(1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); - - memcpy(&cap->mcs, MCS_rate_1R23A, 16); - break; - - case RF_2T2R: - case RF_1T2R: - default: - /* enable for 2.4/5 GHz */ - if (pregpriv->rx_stbc == 0x3 || - (pmlmeext->cur_wireless_mode & - WIRELESS_11_24N && - /* enable for 2.4GHz */ - pregpriv->rx_stbc == 0x1) || - (pmlmeext->cur_wireless_mode & - WIRELESS_11_5N && - pregpriv->rx_stbc == 0x2) || - /* enable for 5GHz */ - pregpriv->wifi_spec == 1) { - DBG_8723A("declare supporting RX " - "STBC\n"); - /* RX STBC two spatial stream */ - cap->cap_info |= cpu_to_le16(2 << IEEE80211_HT_CAP_RX_STBC_SHIFT); - } - memcpy(&cap->mcs, MCS_rate_2R23A, 16); - break; - } - - if (rtl8723a_BT_coexist(padapter) && - rtl8723a_BT_using_antenna_1(padapter)) { - /* set to 8K */ - cap->ampdu_params_info &= - ~IEEE80211_HT_AMPDU_PARM_FACTOR; -/* cap->ampdu_params_info |= MAX_AMPDU_FACTOR_8K */ - } - - pframe = rtw_set_ie23a(pframe, WLAN_EID_HT_CAPABILITY, - p[1], (u8 *)&pmlmeinfo->ht_cap, - &pattrib->pktlen); - } - } - - /* vendor specific IE, such as WPA, WMM, WPS */ - for (i = 0; i < pmlmeinfo->network.IELength;) { - p = pmlmeinfo->network.IEs + i; - - switch (p[0]) { - case WLAN_EID_VENDOR_SPECIFIC: - if (!memcmp(p + 2, RTW_WPA_OUI23A_TYPE, 4) || - !memcmp(p + 2, WMM_OUI23A, 4) || - !memcmp(p + 2, WPS_OUI23A, 4)) { - u8 plen = p[1]; - - if (!padapter->registrypriv.wifi_spec) { - /* Commented by Kurt 20110629 */ - /* In some older APs, WPS handshake */ - /* would be fail if we append vender - extensions informations to AP */ - if (!memcmp(p + 2, WPS_OUI23A, 4)) - plen = 14; - } - pframe = rtw_set_ie23a(pframe, - WLAN_EID_VENDOR_SPECIFIC, - plen, p + 2, - &pattrib->pktlen); - } - break; - - default: - break; - } - - i += p[1] + 2; - } - - if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) - pframe = rtw_set_ie23a(pframe, WLAN_EID_VENDOR_SPECIFIC, 6, - REALTEK_96B_IE, &pattrib->pktlen); - - pattrib->last_txcmdsz = pattrib->pktlen; - dump_mgntframe23a(padapter, pmgntframe); - - ret = _SUCCESS; - -exit: - pmlmepriv->assoc_req_len = 0; - if (ret == _SUCCESS) { - kfree(pmlmepriv->assoc_req); - pmlmepriv->assoc_req = kmalloc(pattrib->pktlen, GFP_ATOMIC); - if (pmlmepriv->assoc_req) { - memcpy(pmlmepriv->assoc_req, mgmt, pattrib->pktlen); - pmlmepriv->assoc_req_len = pattrib->pktlen; - } - } else - kfree(pmlmepriv->assoc_req); -} - -/* when wait_ack is true, this function should be called at process context */ -static int _issue_nulldata23a(struct rtw_adapter *padapter, unsigned char *da, - unsigned int power_mode, int wait_ack) -{ - int ret = _FAIL; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_hdr *pwlanhdr; - struct xmit_priv *pxmitpriv; - struct mlme_ext_priv *pmlmeext; - struct mlme_ext_info *pmlmeinfo; - - /* DBG_8723A("%s:%d\n", __func__, power_mode); */ - - if (!padapter) - goto exit; - - pxmitpriv = &padapter->xmitpriv; - pmlmeext = &padapter->mlmeextpriv; - pmlmeinfo = &pmlmeext->mlmext_info; - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) - goto exit; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - pattrib->retry_ctrl = false; - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_hdr *)pframe; - - pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | - IEEE80211_STYPE_NULLFUNC); - - if ((pmlmeinfo->state&0x03) == MSR_AP) - pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_FROMDS); - else if ((pmlmeinfo->state&0x03) == MSR_INFRA) - pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_TODS); - - if (power_mode) - pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); - - ether_addr_copy(pwlanhdr->addr1, da); - ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv)); - ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network)); - - pwlanhdr->seq_ctrl = - cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - pmlmeext->mgnt_seq++; - - pframe += sizeof(struct ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); - - pattrib->last_txcmdsz = pattrib->pktlen; - - if (wait_ack) - ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe); - else { - dump_mgntframe23a(padapter, pmgntframe); - ret = _SUCCESS; - } - -exit: - return ret; -} - -/* when wait_ms >0 , this function should be called at process context */ -/* da == NULL for station mode */ -int issue_nulldata23a(struct rtw_adapter *padapter, unsigned char *da, - unsigned int power_mode, int try_cnt, int wait_ms) -{ - int ret; - int i = 0; - unsigned long start = jiffies; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - /* da == NULL, assume it's null data for sta to ap*/ - if (da == NULL) - da = get_my_bssid23a(&pmlmeinfo->network); - - do { - ret = _issue_nulldata23a(padapter, da, power_mode, - wait_ms > 0 ? true : false); - - i++; - - if (padapter->bDriverStopped || padapter->bSurpriseRemoved) - break; - - if (i < try_cnt && wait_ms > 0 && ret == _FAIL) - msleep(wait_ms); - - } while((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); - - if (ret != _FAIL) { - ret = _SUCCESS; - goto exit; - } - - if (try_cnt && wait_ms) { - if (da) - DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n", - __func__, padapter->pnetdev->name, - da, rtw_get_oper_ch23a(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - else - DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n", - __func__, padapter->pnetdev->name, - rtw_get_oper_ch23a(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - } -exit: - return ret; -} - -/* when wait_ack is true, this function should be called at process context */ -static int _issue_qos_nulldata23a(struct rtw_adapter *padapter, - unsigned char *da, u16 tid, int wait_ack) -{ - int ret = _FAIL; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_qos_hdr *pwlanhdr; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - DBG_8723A("%s\n", __func__); - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) - goto exit; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - - pattrib->hdrlen += 2; - pattrib->qos_en = true; - pattrib->eosp = 1; - pattrib->ack_policy = 0; - pattrib->mdata = 0; - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_qos_hdr *)pframe; - - pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | - IEEE80211_STYPE_QOS_NULLFUNC); - - if ((pmlmeinfo->state&0x03) == MSR_AP) - pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_FROMDS); - else if ((pmlmeinfo->state&0x03) == MSR_INFRA) - pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_TODS); - - if (pattrib->mdata) - pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); - - pwlanhdr->qos_ctrl = cpu_to_le16(tid & IEEE80211_QOS_CTL_TID_MASK); - pwlanhdr->qos_ctrl |= cpu_to_le16((pattrib->ack_policy << 5) & - IEEE80211_QOS_CTL_ACK_POLICY_MASK); - if (pattrib->eosp) - pwlanhdr->qos_ctrl |= cpu_to_le16(IEEE80211_QOS_CTL_EOSP); - - ether_addr_copy(pwlanhdr->addr1, da); - ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv)); - ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network)); - - pwlanhdr->seq_ctrl = - cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - pmlmeext->mgnt_seq++; - - pframe += sizeof(struct ieee80211_qos_hdr); - pattrib->pktlen = sizeof(struct ieee80211_qos_hdr); - - pattrib->last_txcmdsz = pattrib->pktlen; - - if (wait_ack) - ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe); - else { - dump_mgntframe23a(padapter, pmgntframe); - ret = _SUCCESS; - } - -exit: - return ret; -} - -/* when wait_ms >0 , this function should be called at process context */ -/* da == NULL for station mode */ -int issue_qos_nulldata23a(struct rtw_adapter *padapter, unsigned char *da, - u16 tid, int try_cnt, int wait_ms) -{ - int ret; - int i = 0; - unsigned long start = jiffies; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - /* da == NULL, assume it's null data for sta to ap*/ - if (da == NULL) - da = get_my_bssid23a(&pmlmeinfo->network); - - do { - ret = _issue_qos_nulldata23a(padapter, da, tid, - wait_ms > 0 ? true : false); - - i++; - - if (padapter->bDriverStopped || padapter->bSurpriseRemoved) - break; - - if (i < try_cnt && wait_ms > 0 && ret == _FAIL) - msleep(wait_ms); - } while((i < try_cnt) && ((ret == _FAIL)||(wait_ms == 0))); - - if (ret != _FAIL) { - ret = _SUCCESS; - goto exit; - } - - if (try_cnt && wait_ms) { - if (da) - DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n", - __func__, padapter->pnetdev->name, - da, rtw_get_oper_ch23a(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - else - DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n", - __func__, padapter->pnetdev->name, - rtw_get_oper_ch23a(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - } -exit: - return ret; -} - -static int _issue_deauth(struct rtw_adapter *padapter, unsigned char *da, - unsigned short reason, u8 wait_ack) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - struct ieee80211_mgmt *mgmt; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - int ret = _FAIL; - - /* DBG_8723A("%s to %pM\n", __func__, da); */ - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) - goto exit; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - pattrib->retry_ctrl = false; - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET); - - mgmt->frame_control = - cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH); - - ether_addr_copy(mgmt->da, da); - ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); - ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network)); - - mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - pmlmeext->mgnt_seq++; - - pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr) + 2; - - mgmt->u.deauth.reason_code = cpu_to_le16(reason); - - pattrib->last_txcmdsz = pattrib->pktlen; - - if (wait_ack) - ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe); - else { - dump_mgntframe23a(padapter, pmgntframe); - ret = _SUCCESS; - } - -exit: - return ret; -} - -int issue_deauth23a(struct rtw_adapter *padapter, unsigned char *da, - unsigned short reason) -{ - DBG_8723A("%s to %pM\n", __func__, da); - return _issue_deauth(padapter, da, reason, false); -} - -static int issue_deauth_ex(struct rtw_adapter *padapter, u8 *da, - unsigned short reason, int try_cnt, int wait_ms) -{ - int ret; - int i = 0; - unsigned long start = jiffies; - - do { - ret = _issue_deauth(padapter, da, reason, - wait_ms >0 ? true : false); - - i++; - - if (padapter->bDriverStopped || padapter->bSurpriseRemoved) - break; - - if (i < try_cnt && wait_ms > 0 && ret == _FAIL) - msleep(wait_ms); - - } while((i < try_cnt) && ((ret == _FAIL)||(wait_ms == 0))); - - if (ret != _FAIL) { - ret = _SUCCESS; - goto exit; - } - - if (try_cnt && wait_ms) { - if (da) - DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n", - __func__, padapter->pnetdev->name, - da, rtw_get_oper_ch23a(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - else - DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n", - __func__, padapter->pnetdev->name, - rtw_get_oper_ch23a(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - } -exit: - return ret; -} - -void issue_action_spct_ch_switch23a(struct rtw_adapter *padapter, - u8 *ra, u8 new_ch, u8 ch_offset) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_mgmt *mgmt; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - DBG_8723A("%s(%s): ra=%pM, ch:%u, offset:%u\n", - __func__, padapter->pnetdev->name, ra, new_ch, ch_offset); - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET); - - mgmt->frame_control = - cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); - - ether_addr_copy(mgmt->da, ra); /* RA */ - ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); /* TA */ - ether_addr_copy(mgmt->bssid, ra); /* DA = RA */ - - mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - pmlmeext->mgnt_seq++; - - mgmt->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT; - mgmt->u.action.u.chan_switch.action_code = WLAN_ACTION_SPCT_CHL_SWITCH; - - pframe = mgmt->u.action.u.chan_switch.variable; - pattrib->pktlen = offsetof(struct ieee80211_mgmt, - u.action.u.chan_switch.variable); - - pframe = rtw_set_ie23a_ch_switch (pframe, &pattrib->pktlen, 0, - new_ch, 0); - pframe = rtw_set_ie23a_secondary_ch_offset(pframe, &pattrib->pktlen, - hal_ch_offset_to_secondary_ch_offset23a(ch_offset)); - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe23a(padapter, pmgntframe); -} - -void issue_action_BA23a(struct rtw_adapter *padapter, - const unsigned char *raddr, - unsigned char action, unsigned short status) -{ - u16 start_seq; - u16 BA_para_set; - u16 BA_starting_seqctrl; - u16 BA_para; - int max_rx_ampdu_factor; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - struct ieee80211_mgmt *mgmt; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - struct registry_priv *pregpriv = &padapter->registrypriv; - u8 tendaAPMac[] = {0xC8, 0x3A, 0x35}; - - DBG_8723A("%s, action =%d, status =%d\n", __func__, action, status); - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET); - - mgmt->frame_control = - cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); - - ether_addr_copy(mgmt->da, raddr); - ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); - ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network)); - - mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - pmlmeext->mgnt_seq++; - - mgmt->u.action.category = WLAN_CATEGORY_BACK; - - pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr) + 1; - - switch (action) { - case WLAN_ACTION_ADDBA_REQ: - pattrib->pktlen += sizeof(mgmt->u.action.u.addba_req); - - mgmt->u.action.u.addba_req.action_code = action; - - do { - pmlmeinfo->dialogToken++; - } while (pmlmeinfo->dialogToken == 0); - - mgmt->u.action.u.addba_req.dialog_token = - pmlmeinfo->dialogToken; - - if (rtl8723a_BT_coexist(padapter) && - rtl8723a_BT_using_antenna_1(padapter) && - (pmlmeinfo->assoc_AP_vendor != broadcomAP || - memcmp(raddr, tendaAPMac, 3))) { - /* A-MSDU NOT Supported */ - BA_para_set = 0; - /* immediate Block Ack */ - BA_para_set |= (1 << 1) & - IEEE80211_ADDBA_PARAM_POLICY_MASK; - /* TID */ - BA_para_set |= (status << 2) & - IEEE80211_ADDBA_PARAM_TID_MASK; - /* max buffer size is 8 MSDU */ - BA_para_set |= (8 << 6) & - IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; - } else { - /* immediate ack & 64 buffer size */ - BA_para_set = 0x1002 | ((status & 0xf) << 2); - } - - put_unaligned_le16(BA_para_set, - &mgmt->u.action.u.addba_req.capab); - - /* 5ms */ - put_unaligned_le16(5000, &mgmt->u.action.u.addba_req.timeout); - - psta = rtw_get_stainfo23a(pstapriv, raddr); - if (psta) { - int idx; - - idx = status & 0x07; - start_seq = - (psta->sta_xmitpriv.txseq_tid[idx] & 0xfff) + 1; - - DBG_8723A("BA_starting_seqctrl = %d for TID =%d\n", - start_seq, idx); - - psta->BA_starting_seqctrl[idx] = start_seq; - - BA_starting_seqctrl = start_seq << 4; - } else - BA_starting_seqctrl = 0; - - put_unaligned_le16(BA_starting_seqctrl, - &mgmt->u.action.u.addba_req.start_seq_num); - - break; - - case WLAN_ACTION_ADDBA_RESP: - pattrib->pktlen += sizeof(mgmt->u.action.u.addba_resp); - - mgmt->u.action.u.addba_resp.action_code = action; - mgmt->u.action.u.addba_resp.dialog_token = - pmlmeinfo->ADDBA_req.dialog_token; - put_unaligned_le16(status, - &mgmt->u.action.u.addba_resp.status); - - GetHalDefVar8192CUsb(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, - &max_rx_ampdu_factor); - - BA_para = le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f; - if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_64K) - BA_para_set = BA_para | 0x1000; /* 64 buffer size */ - else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_32K) - BA_para_set = BA_para | 0x0800; /* 32 buffer size */ - else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_16K) - BA_para_set = BA_para | 0x0400; /* 16 buffer size */ - else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_8K) - BA_para_set = BA_para | 0x0200; /* 8 buffer size */ - else - BA_para_set = BA_para | 0x1000; /* 64 buffer size */ - - if (rtl8723a_BT_coexist(padapter) && - rtl8723a_BT_using_antenna_1(padapter) && - (pmlmeinfo->assoc_AP_vendor != broadcomAP || - memcmp(raddr, tendaAPMac, 3))) { - /* max buffer size is 8 MSDU */ - BA_para_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; - BA_para_set |= (8 << 6) & - IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; - } - - if (pregpriv->ampdu_amsdu == 0)/* disabled */ - BA_para_set &= ~BIT(0); - else if (pregpriv->ampdu_amsdu == 1)/* enabled */ - BA_para_set |= BIT(0); - - put_unaligned_le16(BA_para_set, - &mgmt->u.action.u.addba_resp.capab); - - mgmt->u.action.u.addba_resp.timeout - = pmlmeinfo->ADDBA_req.BA_timeout_value; - - pattrib->pktlen += 8; - break; - case WLAN_ACTION_DELBA: - pattrib->pktlen += sizeof(mgmt->u.action.u.delba); - - mgmt->u.action.u.delba.action_code = action; - BA_para_set = (status & 0x1F) << 3; - mgmt->u.action.u.delba.params = cpu_to_le16(BA_para_set); - mgmt->u.action.u.delba.reason_code = - cpu_to_le16(WLAN_REASON_QSTA_NOT_USE); - - pattrib->pktlen += 5; - break; - default: - break; - } - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe23a(padapter, pmgntframe); -} - -int send_delba23a(struct rtw_adapter *padapter, u8 initiator, u8 *addr) -{ - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *psta = NULL; - /* struct recv_reorder_ctrl *preorder_ctrl; */ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - u16 tid; - - if ((pmlmeinfo->state&0x03) != MSR_AP) - if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) - return _SUCCESS; - - psta = rtw_get_stainfo23a(pstapriv, addr); - if (psta == NULL) - return _SUCCESS; - - if (initiator == 0) { /* recipient */ - for (tid = 0; tid < MAXTID; tid++) { - if (psta->recvreorder_ctrl[tid].enable == true) { - DBG_8723A("rx agg disable tid(%d)\n", tid); - issue_action_BA23a(padapter, addr, WLAN_ACTION_DELBA, (((tid <<1) |initiator)&0x1F)); - psta->recvreorder_ctrl[tid].enable = false; - psta->recvreorder_ctrl[tid].indicate_seq = 0xffff; - } - } - } else if (initiator == 1) { /* originator */ - for (tid = 0; tid < MAXTID; tid++) { - if (psta->htpriv.agg_enable_bitmap & BIT(tid)) { - DBG_8723A("tx agg disable tid(%d)\n", tid); - issue_action_BA23a(padapter, addr, WLAN_ACTION_DELBA, (((tid <<1) |initiator)&0x1F)); - psta->htpriv.agg_enable_bitmap &= ~BIT(tid); - psta->htpriv.candidate_tid_bitmap &= ~BIT(tid); - - } - } - } - return _SUCCESS; -} - -int send_beacon23a(struct rtw_adapter *padapter) -{ - bool bxmitok; - int issue = 0; - int poll = 0; - unsigned long start = jiffies; - unsigned int passing_time; - - rtl8723a_bcn_valid(padapter); - do { - issue_beacon23a(padapter, 100); - issue++; - do { - yield(); - bxmitok = rtl8723a_get_bcn_valid(padapter); - poll++; - } while ((poll % 10) != 0 && !bxmitok && - !padapter->bSurpriseRemoved && - !padapter->bDriverStopped); - - } while (!bxmitok && issue<100 && !padapter->bSurpriseRemoved && - !padapter->bDriverStopped); - - if (padapter->bSurpriseRemoved || padapter->bDriverStopped) - return _FAIL; - - passing_time = jiffies_to_msecs(jiffies - start); - - if (!bxmitok) { - DBG_8723A("%s fail! %u ms\n", __func__, passing_time); - return _FAIL; - } else { - - if (passing_time > 100 || issue > 3) - DBG_8723A("%s success, issue:%d, poll:%d, %u ms\n", - __func__, issue, poll, passing_time); - return _SUCCESS; - } -} - -/**************************************************************************** - -Following are some utitity functions for WiFi MLME - -*****************************************************************************/ - -bool IsLegal5GChannel(struct rtw_adapter *Adapter, u8 channel) -{ - - int i = 0; - u8 Channel_5G[45] = {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, 149, 151, 153, 155, 157, 159, - 161, 163, 165}; - for (i = 0; i < sizeof(Channel_5G); i++) - if (channel == Channel_5G[i]) - return true; - return false; -} - -static void rtw_site_survey(struct rtw_adapter *padapter) -{ - unsigned char survey_channel = 0; - enum rt_scan_type ScanType = SCAN_PASSIVE; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct rtw_ieee80211_channel *ch; - - if (pmlmeext->sitesurvey_res.channel_idx < - pmlmeext->sitesurvey_res.ch_num) { - ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx]; - survey_channel = ch->hw_value; - ScanType = (ch->flags & IEEE80211_CHAN_NO_IR) ? - SCAN_PASSIVE : SCAN_ACTIVE; - } - - if (survey_channel != 0) { - /* PAUSE 4-AC Queue when site_survey */ - if (pmlmeext->sitesurvey_res.channel_idx == 0) - set_channel_bwmode23a(padapter, survey_channel, - HAL_PRIME_CHNL_OFFSET_DONT_CARE, - HT_CHANNEL_WIDTH_20); - else - SelectChannel23a(padapter, survey_channel); - - if (ScanType == SCAN_ACTIVE) /* obey the channel plan setting... */ - { - int i; - - for (i = 0;i<RTW_SSID_SCAN_AMOUNT;i++) { - if (pmlmeext->sitesurvey_res.ssid[i].ssid_len) { - /* todo: to issue two probe req??? */ - issue_probereq(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL); - /* msleep(SURVEY_TO>>1); */ - issue_probereq(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL); - } - } - - if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) { - /* todo: to issue two probe req??? */ - issue_probereq(padapter, NULL, NULL); - /* msleep(SURVEY_TO>>1); */ - issue_probereq(padapter, NULL, NULL); - } - } - - set_survey_timer(pmlmeext, pmlmeext->chan_scan_time); - } else { - /* channel number is 0 or this channel is not valid. */ - pmlmeext->sitesurvey_res.state = SCAN_COMPLETE; - - /* switch back to the original channel */ - - set_channel_bwmode23a(padapter, pmlmeext->cur_channel, - pmlmeext->cur_ch_offset, - pmlmeext->cur_bwmode); - - /* flush 4-AC Queue after rtw_site_survey */ - /* val8 = 0; */ - - /* config MSR */ - rtl8723a_set_media_status(padapter, pmlmeinfo->state & 0x3); - - /* restore RX GAIN */ - rtl8723a_set_initial_gain(padapter, 0xff); - /* turn on dynamic functions */ - rtl8723a_odm_support_ability_restore(padapter); - - if (is_client_associated_to_ap23a(padapter) == true) - issue_nulldata23a(padapter, NULL, 0, 3, 500); - - rtl8723a_mlme_sitesurvey(padapter, 0); - - report_surveydone_event23a(padapter); - - pmlmeext->chan_scan_time = SURVEY_TO; - pmlmeext->sitesurvey_res.state = SCAN_DISABLE; - } -} - -/* collect bss info from Beacon and Probe request/response frames. */ -static struct wlan_bssid_ex *collect_bss_info(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *bssid; - const u8 *p; - u8 *pie; - unsigned int length; - int i; - - length = skb->len; - - bssid = kzalloc(sizeof(struct wlan_bssid_ex), GFP_ATOMIC); - if (!bssid) - return NULL; - - if (ieee80211_is_beacon(mgmt->frame_control)) { - length -= offsetof(struct ieee80211_mgmt, u.beacon.variable); - pie = mgmt->u.beacon.variable; - bssid->reserved = 1; - bssid->capability = - get_unaligned_le16(&mgmt->u.beacon.capab_info); - bssid->beacon_interval = - get_unaligned_le16(&mgmt->u.beacon.beacon_int); - bssid->tsf = get_unaligned_le64(&mgmt->u.beacon.timestamp); - } else if (ieee80211_is_probe_req(mgmt->frame_control)) { - length -= offsetof(struct ieee80211_mgmt, u.probe_req.variable); - pie = mgmt->u.probe_req.variable; - bssid->reserved = 2; - bssid->capability = 0; - bssid->beacon_interval = - padapter->registrypriv.dev_network.beacon_interval; - bssid->tsf = 0; - } else if (ieee80211_is_probe_resp(mgmt->frame_control)) { - length -= - offsetof(struct ieee80211_mgmt, u.probe_resp.variable); - pie = mgmt->u.probe_resp.variable; - bssid->reserved = 3; - bssid->capability = - get_unaligned_le16(&mgmt->u.probe_resp.capab_info); - bssid->beacon_interval = - get_unaligned_le16(&mgmt->u.probe_resp.beacon_int); - bssid->tsf = get_unaligned_le64(&mgmt->u.probe_resp.timestamp); - } else { - length -= offsetof(struct ieee80211_mgmt, u.beacon.variable); - pie = mgmt->u.beacon.variable; - bssid->reserved = 0; - bssid->capability = - get_unaligned_le16(&mgmt->u.beacon.capab_info); - bssid->beacon_interval = - padapter->registrypriv.dev_network.beacon_interval; - bssid->tsf = 0; - } - - if (length > MAX_IE_SZ) { - /* DBG_8723A("IE too long for survey event\n"); */ - kfree(bssid); - return NULL; - } - - bssid->Length = offsetof(struct wlan_bssid_ex, IEs) + length; - - /* below is to copy the information element */ - bssid->IELength = length; - memcpy(bssid->IEs, pie, bssid->IELength); - - /* get the signal strength */ - /* in dBM.raw data */ - bssid->Rssi = precv_frame->attrib.phy_info.RecvSignalPower; - bssid->SignalQuality = - precv_frame->attrib.phy_info.SignalQuality;/* in percentage */ - bssid->SignalStrength = - precv_frame->attrib.phy_info.SignalStrength;/* in percentage */ - - /* checking SSID */ - p = cfg80211_find_ie(WLAN_EID_SSID, bssid->IEs, bssid->IELength); - - if (!p) { - DBG_8723A("marc: cannot find SSID for survey event\n"); - goto fail; - } - - if (p[1] > IEEE80211_MAX_SSID_LEN) { - DBG_8723A("%s()-%d: IE too long (%d) for survey " - "event\n", __func__, __LINE__, p[1]); - goto fail; - } - memcpy(bssid->Ssid.ssid, p + 2, p[1]); - bssid->Ssid.ssid_len = p[1]; - - /* checking rate info... */ - i = 0; - p = cfg80211_find_ie(WLAN_EID_SUPP_RATES, bssid->IEs, bssid->IELength); - if (p) { - if (p[1] > NDIS_802_11_LENGTH_RATES_EX) { - DBG_8723A("%s()-%d: IE too long (%d) for survey " - "event\n", __func__, __LINE__, p[1]); - goto fail; - } - memcpy(bssid->SupportedRates, p + 2, p[1]); - i = p[1]; - } - - p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, bssid->IEs, - bssid->IELength); - if (p) { - if (p[1] > (NDIS_802_11_LENGTH_RATES_EX-i)) { - DBG_8723A("%s()-%d: IE too long (%d) for survey " - "event\n", __func__, __LINE__, p[1]); - goto fail; - } - memcpy(bssid->SupportedRates + i, p + 2, p[1]); - } - - /* Checking for DSConfig */ - p = cfg80211_find_ie(WLAN_EID_DS_PARAMS, bssid->IEs, bssid->IELength); - - bssid->DSConfig = 0; - - if (p) { - bssid->DSConfig = p[2]; - } else {/* In 5G, some ap do not have DSSET IE */ - /* checking HT info for channel */ - p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, bssid->IEs, - bssid->IELength); - if (p) { - struct ieee80211_ht_operation *HT_info = - (struct ieee80211_ht_operation *)(p + 2); - bssid->DSConfig = HT_info->primary_chan; - } else /* use current channel */ - bssid->DSConfig = rtw_get_oper_ch23a(padapter); - } - - if (ieee80211_is_probe_req(mgmt->frame_control)) { - /* FIXME */ - bssid->ifmode = NL80211_IFTYPE_STATION; - ether_addr_copy(bssid->MacAddress, mgmt->sa); - bssid->Privacy = 1; - return bssid; - } - - if (bssid->capability & WLAN_CAPABILITY_ESS) { - bssid->ifmode = NL80211_IFTYPE_STATION; - ether_addr_copy(bssid->MacAddress, mgmt->sa); - } else { - bssid->ifmode = NL80211_IFTYPE_ADHOC; - ether_addr_copy(bssid->MacAddress, mgmt->bssid); - } - - if (bssid->capability & WLAN_CAPABILITY_PRIVACY) - bssid->Privacy = 1; - else - bssid->Privacy = 0; - - bssid->ATIMWindow = 0; - - /* 20/40 BSS Coexistence check */ - if (pregistrypriv->wifi_spec == 1 && - pmlmeinfo->bwmode_updated == false) { - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, bssid->IEs, - bssid->IELength); - if (p && p[1] > 0) { - struct ieee80211_ht_cap *pHT_caps; - - pHT_caps = (struct ieee80211_ht_cap *)(p + 2); - - if (pHT_caps->cap_info & - cpu_to_le16(IEEE80211_HT_CAP_40MHZ_INTOLERANT)) - pmlmepriv->num_FortyMHzIntolerant++; - } else - pmlmepriv->num_sta_no_ht++; - } - - - /* mark bss info receiving from nearby channel as SignalQuality 101 */ - if (bssid->DSConfig != rtw_get_oper_ch23a(padapter)) - bssid->SignalQuality = 101; - - return bssid; -fail: - kfree (bssid); - return NULL; -} - -static void start_create_ibss(struct rtw_adapter *padapter) -{ - unsigned short caps; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; - - pmlmeext->cur_channel = (u8)pnetwork->DSConfig; - pmlmeinfo->bcn_interval = pnetwork->beacon_interval; - - /* update wireless mode */ - update_wireless_mode23a(padapter); - - /* update capability */ - caps = pnetwork->capability; - update_capinfo23a(padapter, caps); - if (caps & WLAN_CAPABILITY_IBSS) { /* adhoc master */ - rtl8723a_set_sec_cfg(padapter, 0xcf); - - /* switch channel */ - /* SelectChannel23a(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */ - set_channel_bwmode23a(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); - - rtl8723a_SetBeaconRelatedRegisters(padapter); - - /* set msr to MSR_ADHOC */ - pmlmeinfo->state = MSR_ADHOC; - rtl8723a_set_media_status(padapter, pmlmeinfo->state & 0x3); - - /* issue beacon */ - if (send_beacon23a(padapter) == _FAIL) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "issuing beacon frame fail....\n"); - - report_join_res23a(padapter, -1); - pmlmeinfo->state = MSR_NOLINK; - } else { - hw_var_set_bssid(padapter, padapter->registrypriv.dev_network.MacAddress); - hw_var_set_mlme_join(padapter, 0); - - report_join_res23a(padapter, 1); - pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; - } - } else { - DBG_8723A("%s: invalid cap:%x\n", __func__, caps); - return; - } -} - -static void start_clnt_join(struct rtw_adapter *padapter) -{ - unsigned short caps; - u8 val8; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; - int beacon_timeout; - - pmlmeext->cur_channel = (u8)pnetwork->DSConfig; - pmlmeinfo->bcn_interval = pnetwork->beacon_interval; - - /* update wireless mode */ - update_wireless_mode23a(padapter); - - /* update capability */ - caps = pnetwork->capability; - update_capinfo23a(padapter, caps); - if (caps & WLAN_CAPABILITY_ESS) { - /* switch channel */ - set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - - rtl8723a_set_media_status(padapter, MSR_INFRA); - - val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ? - 0xcc: 0xcf; - - rtl8723a_set_sec_cfg(padapter, val8); - - /* switch channel */ - /* set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */ - - /* here wait for receiving the beacon to start auth */ - /* and enable a timer */ - beacon_timeout = decide_wait_for_beacon_timeout23a(pmlmeinfo->bcn_interval); - set_link_timer(pmlmeext, beacon_timeout); - mod_timer(&padapter->mlmepriv.assoc_timer, jiffies + - msecs_to_jiffies((REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) + beacon_timeout)); - pmlmeinfo->state = WIFI_FW_AUTH_NULL | MSR_INFRA; - } else if (caps & WLAN_CAPABILITY_IBSS) { /* adhoc client */ - rtl8723a_set_media_status(padapter, MSR_ADHOC); - - rtl8723a_set_sec_cfg(padapter, 0xcf); - - /* switch channel */ - set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - - rtl8723a_SetBeaconRelatedRegisters(padapter); - - pmlmeinfo->state = MSR_ADHOC; - - report_join_res23a(padapter, 1); - } else { - /* DBG_8723A("marc: invalid cap:%x\n", caps); */ - return; - } -} - -static void start_clnt_auth(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - del_timer_sync(&pmlmeext->link_timer); - - pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL); - pmlmeinfo->state |= WIFI_FW_AUTH_STATE; - - pmlmeinfo->auth_seq = 1; - pmlmeinfo->reauth_count = 0; - pmlmeinfo->reassoc_count = 0; - pmlmeinfo->link_count = 0; - pmlmeext->retry = 0; - - /* Because of AP's not receiving deauth before */ - /* AP may: 1)not response auth or 2)deauth us after link is complete */ - /* issue deauth before issuing auth to deal with the situation */ - /* Commented by Albert 2012/07/21 */ - /* For the Win8 P2P connection, it will be hard to have a - successful connection if this Wi-Fi doesn't connect to it. */ - issue_deauth23a(padapter, (&pmlmeinfo->network)->MacAddress, - WLAN_REASON_DEAUTH_LEAVING); - - DBG_8723A_LEVEL(_drv_always_, "start auth\n"); - issue_auth(padapter, NULL, 0); - - set_link_timer(pmlmeext, REAUTH_TO); -} - -static void start_clnt_assoc(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - del_timer_sync(&pmlmeext->link_timer); - - pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE)); - pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE); - - issue_assocreq(padapter); - - set_link_timer(pmlmeext, REASSOC_TO); -} - -int receive_disconnect23a(struct rtw_adapter *padapter, - unsigned char *MacAddr, unsigned short reason) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - /* check A3 */ - if (!ether_addr_equal(MacAddr, get_my_bssid23a(&pmlmeinfo->network))) - return _SUCCESS; - - DBG_8723A("%s\n", __func__); - - if ((pmlmeinfo->state&0x03) == MSR_INFRA) { - if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { - pmlmeinfo->state = MSR_NOLINK; - report_del_sta_event23a(padapter, MacAddr, reason); - - } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) { - pmlmeinfo->state = MSR_NOLINK; - report_join_res23a(padapter, -2); - } - } - - return _SUCCESS; -} - -static void process_80211d(struct rtw_adapter *padapter, - struct wlan_bssid_ex *bssid) -{ - struct registry_priv *pregistrypriv; - struct mlme_ext_priv *pmlmeext; - struct rt_channel_info *chplan_new; - u8 channel; - u8 i; - - pregistrypriv = &padapter->registrypriv; - pmlmeext = &padapter->mlmeextpriv; - - /* Adjust channel plan by AP Country IE */ - if (pregistrypriv->enable80211d && - !pmlmeext->update_channel_plan_by_ap_done) { - const u8 *ie, *p; - struct rt_channel_plan chplan_ap; - struct rt_channel_info chplan_sta[MAX_CHANNEL_NUM]; - u8 country[4]; - u8 fcn; /* first channel number */ - u8 noc; /* number of channel */ - u8 j, k; - - ie = cfg80211_find_ie(WLAN_EID_COUNTRY, bssid->IEs, - bssid->IELength); - if (!ie || ie[1] < IEEE80211_COUNTRY_IE_MIN_LEN) - return; - - p = ie + 2; - ie += ie[1]; - ie += 2; - - memcpy(country, p, 3); - country[3] = '\0'; - - 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++); - noc = *(p++); - p++; - - for (j = 0; j < noc; j++) { - if (fcn <= 14) - channel = fcn + j; /* 2.4 GHz */ - else - channel = fcn + j * 4; /* 5 GHz */ - - chplan_ap.Channel[i++] = channel; - } - } - chplan_ap.Len = i; - - memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta)); - memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set)); - chplan_new = pmlmeext->channel_set; - - i = j = k = 0; - if (pregistrypriv->wireless_mode & WIRELESS_11G) { - do { - if (i == MAX_CHANNEL_NUM || - chplan_sta[i].ChannelNum == 0 || - chplan_sta[i].ChannelNum > 14) - break; - - if (j == chplan_ap.Len || - chplan_ap.Channel[j] > 14) - 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 = - 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_sta[i].ChannelNum <= 14) { - chplan_new[k].ChannelNum = - chplan_sta[i].ChannelNum; - chplan_new[k].ScanType = SCAN_PASSIVE; - i++; - k++; - } - - /* add channel AP supported */ - while (j < chplan_ap.Len && chplan_ap.Channel[j] <= 14){ - chplan_new[k].ChannelNum = chplan_ap.Channel[j]; - chplan_new[k].ScanType = SCAN_ACTIVE; - j++; - k++; - } - } else { - /* keep original STA 2.4G channel plan */ - while (i < MAX_CHANNEL_NUM && - chplan_sta[i].ChannelNum != 0 && - chplan_sta[i].ChannelNum <= 14) { - chplan_new[k].ChannelNum = - chplan_sta[i].ChannelNum; - chplan_new[k].ScanType = chplan_sta[i].ScanType; - i++; - k++; - } - - /* skip AP 2.4G channel plan */ - while (j < chplan_ap.Len && chplan_ap.Channel[j] <= 14) - j++; - } - - 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 = 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 = 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; - } - - /* If channel is used by AP, set channel scan type to active */ - channel = bssid->DSConfig; - chplan_new = pmlmeext->channel_set; - 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) { - /* 5G Bnad 2, 3 (DFS) doesn't change - to active scan */ - if (channel >= 52 && channel <= 144) - break; - - 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++; - } -} - -/**************************************************************************** - -Following are the functions to report events - -*****************************************************************************/ - -void report_survey_event23a(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ - struct cmd_obj *pcmd_obj; - u8 *pevtcmd; - u32 cmdsz; - struct survey_event *psurvey_evt; - struct C2HEvent_Header *pc2h_evt_hdr; - struct mlme_ext_priv *pmlmeext; - struct cmd_priv *pcmdpriv; - - if (!padapter) - return; - - pmlmeext = &padapter->mlmeextpriv; - pcmdpriv = &padapter->cmdpriv; - - pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!pcmd_obj) - return; - - cmdsz = sizeof(struct survey_event) + sizeof(struct C2HEvent_Header); - pevtcmd = kzalloc(cmdsz, GFP_ATOMIC); - if (!pevtcmd) { - kfree(pcmd_obj); - return; - } - - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); - pcmd_obj->cmdsz = cmdsz; - pcmd_obj->parmbuf = pevtcmd; - - pcmd_obj->rsp = NULL; - pcmd_obj->rspsz = 0; - - pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); - pc2h_evt_hdr->len = sizeof(struct survey_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey); - pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); - - psurvey_evt = (struct survey_event*)(pevtcmd + sizeof(struct C2HEvent_Header)); - - psurvey_evt->bss = collect_bss_info(padapter, precv_frame); - if (!psurvey_evt->bss) { - kfree(pcmd_obj); - kfree(pevtcmd); - return; - } - - process_80211d(padapter, psurvey_evt->bss); - - rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj); - - pmlmeext->sitesurvey_res.bss_cnt++; -} - -void report_surveydone_event23a(struct rtw_adapter *padapter) -{ - struct cmd_obj *pcmd_obj; - u8 *pevtcmd; - u32 cmdsz; - struct surveydone_event *psurveydone_evt; - struct C2HEvent_Header *pc2h_evt_hdr; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!pcmd_obj) - return; - - cmdsz = sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header); - pevtcmd = kzalloc(cmdsz, GFP_ATOMIC); - if (!pevtcmd) { - kfree(pcmd_obj); - return; - } - - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); - pcmd_obj->cmdsz = cmdsz; - pcmd_obj->parmbuf = pevtcmd; - - pcmd_obj->rsp = NULL; - pcmd_obj->rspsz = 0; - - pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); - pc2h_evt_hdr->len = sizeof(struct surveydone_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone); - pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); - - psurveydone_evt = (struct surveydone_event*)(pevtcmd + sizeof(struct C2HEvent_Header)); - psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt; - - DBG_8723A("survey done event(%x)\n", psurveydone_evt->bss_cnt); - - rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj); -} - -void report_join_res23a(struct rtw_adapter *padapter, int res) -{ - struct cmd_obj *pcmd_obj; - u8 *pevtcmd; - u32 cmdsz; - struct joinbss_event *pjoinbss_evt; - struct C2HEvent_Header *pc2h_evt_hdr; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!pcmd_obj) - return; - - cmdsz = sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header); - pevtcmd = kzalloc(cmdsz, GFP_ATOMIC); - if (!pevtcmd) { - kfree(pcmd_obj); - return; - } - - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); - pcmd_obj->cmdsz = cmdsz; - pcmd_obj->parmbuf = pevtcmd; - - pcmd_obj->rsp = NULL; - pcmd_obj->rspsz = 0; - - pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); - pc2h_evt_hdr->len = sizeof(struct joinbss_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss); - pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); - - pjoinbss_evt = (struct joinbss_event*)(pevtcmd + sizeof(struct C2HEvent_Header)); - memcpy((unsigned char *)&pjoinbss_evt->network.network, - &pmlmeinfo->network, sizeof(struct wlan_bssid_ex)); - pjoinbss_evt->network.join_res = res; - - DBG_8723A("report_join_res23a(%d)\n", res); - - rtw_joinbss_event_prehandle23a(padapter, (u8 *)&pjoinbss_evt->network); - - rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj); -} - -void report_del_sta_event23a(struct rtw_adapter *padapter, - unsigned char *MacAddr, unsigned short reason) -{ - struct cmd_obj *pcmd_obj; - u8 *pevtcmd; - u32 cmdsz; - struct sta_info *psta; - int mac_id; - struct stadel_event *pdel_sta_evt; - struct C2HEvent_Header *pc2h_evt_hdr; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!pcmd_obj) - return; - - cmdsz = sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header); - pevtcmd = kzalloc(cmdsz, GFP_ATOMIC); - if (!pevtcmd) { - kfree(pcmd_obj); - return; - } - - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); - pcmd_obj->cmdsz = cmdsz; - pcmd_obj->parmbuf = pevtcmd; - - pcmd_obj->rsp = NULL; - pcmd_obj->rspsz = 0; - - pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); - pc2h_evt_hdr->len = sizeof(struct stadel_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA); - pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); - - pdel_sta_evt = (struct stadel_event*)(pevtcmd + sizeof(struct C2HEvent_Header)); - ether_addr_copy((unsigned char *)&pdel_sta_evt->macaddr, MacAddr); - memcpy((unsigned char *)pdel_sta_evt->rsvd, (unsigned char *)&reason, - 2); - - psta = rtw_get_stainfo23a(&padapter->stapriv, MacAddr); - if (psta) - mac_id = (int)psta->mac_id; - else - mac_id = -1; - - pdel_sta_evt->mac_id = mac_id; - - DBG_8723A("report_del_sta_event23a: delete STA, mac_id =%d\n", mac_id); - - rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj); -} - -void report_add_sta_event23a(struct rtw_adapter *padapter, - unsigned char *MacAddr, int cam_idx) -{ - struct cmd_obj *pcmd_obj; - u8 *pevtcmd; - u32 cmdsz; - struct stassoc_event *padd_sta_evt; - struct C2HEvent_Header *pc2h_evt_hdr; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!pcmd_obj) - return; - - cmdsz = sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header); - pevtcmd = kzalloc(cmdsz, GFP_ATOMIC); - if (!pevtcmd) { - kfree(pcmd_obj); - return; - } - - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); - pcmd_obj->cmdsz = cmdsz; - pcmd_obj->parmbuf = pevtcmd; - - pcmd_obj->rsp = NULL; - pcmd_obj->rspsz = 0; - - pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); - pc2h_evt_hdr->len = sizeof(struct stassoc_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA); - pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); - - padd_sta_evt = (struct stassoc_event*)(pevtcmd + sizeof(struct C2HEvent_Header)); - ether_addr_copy((unsigned char *)&padd_sta_evt->macaddr, MacAddr); - padd_sta_evt->cam_id = cam_idx; - - DBG_8723A("report_add_sta_event23a: add STA\n"); - - rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj); -} - -/**************************************************************************** - -Following are the event callback functions - -*****************************************************************************/ - -/* for sta/adhoc mode */ -void update_sta_info23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - /* ERP */ - VCS_update23a(padapter, psta); - - /* HT */ - if (pmlmepriv->htpriv.ht_option) { - psta->htpriv.ht_option = true; - - psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable; - - if (support_short_GI23a(padapter, &pmlmeinfo->ht_cap)) - psta->htpriv.sgi = true; - - psta->qos_option = true; - - } else { - psta->htpriv.ht_option = false; - - psta->htpriv.ampdu_enable = false; - - psta->htpriv.sgi = false; - psta->qos_option = false; - - } - psta->htpriv.bwmode = pmlmeext->cur_bwmode; - psta->htpriv.ch_offset = pmlmeext->cur_ch_offset; - - psta->htpriv.agg_enable_bitmap = 0x0;/* reset */ - psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */ - - /* QoS */ - if (pmlmepriv->qos_option) - psta->qos_option = true; - - psta->state = _FW_LINKED; -} - -void mlmeext_joinbss_event_callback23a(struct rtw_adapter *padapter, - int join_res) -{ - struct sta_info *psta, *psta_bmc; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - struct sta_priv *pstapriv = &padapter->stapriv; - - if (join_res < 0) { - hw_var_set_mlme_join(padapter, 1); - hw_var_set_bssid(padapter, null_addr); - - /* restore to initial setting. */ - update_tx_basic_rate23a(padapter, - padapter->registrypriv.wireless_mode); - - goto exit_mlmeext_joinbss_event_callback23a; - } - - if ((pmlmeinfo->state&0x03) == MSR_ADHOC) { - /* for bc/mc */ - psta_bmc = rtw_get_bcmc_stainfo23a(padapter); - if (psta_bmc) { - pmlmeinfo->FW_sta_info[psta_bmc->mac_id].psta = psta_bmc; - update_bmc_sta_support_rate23a(padapter, psta_bmc->mac_id); - Update_RA_Entry23a(padapter, psta_bmc); - } - } - - /* turn on dynamic functions */ - rtl8723a_odm_support_ability_set(padapter, DYNAMIC_ALL_FUNC_ENABLE); - - /* update IOT-releated issue */ - update_IOT_info23a(padapter); - - HalSetBrateCfg23a(padapter, cur_network->SupportedRates); - - /* BCN interval */ - rtl8723a_set_beacon_interval(padapter, pmlmeinfo->bcn_interval); - - /* update capability */ - update_capinfo23a(padapter, pmlmeinfo->capability); - - /* WMM, Update EDCA param */ - WMMOnAssocRsp23a(padapter); - - /* HT */ - HTOnAssocRsp23a(padapter); - - /* Set cur_channel&cur_bwmode&cur_ch_offset */ - set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - - psta = rtw_get_stainfo23a(pstapriv, cur_network->MacAddress); - if (psta) { /* only for infra. mode */ - pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta; - - /* DBG_8723A("set_sta_rate23a\n"); */ - - psta->wireless_mode = pmlmeext->cur_wireless_mode; - - /* set per sta rate after updating HT cap. */ - set_sta_rate23a(padapter, psta); - } - - hw_var_set_mlme_join(padapter, 2); - - if ((pmlmeinfo->state&0x03) == MSR_INFRA) { - /* correcting TSF */ - rtw_correct_TSF(padapter); - - /* set_link_timer(pmlmeext, DISCONNECT_TO); */ - } - - rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_CONNECT, 0); - -exit_mlmeext_joinbss_event_callback23a: - DBG_8723A("=>%s\n", __func__); -} - -void mlmeext_sta_add_event_callback23a(struct rtw_adapter *padapter, - struct sta_info *psta) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - DBG_8723A("%s\n", __func__); - - if ((pmlmeinfo->state & 0x03) == MSR_ADHOC) { - /* adhoc master or sta_count>1 */ - if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { - /* nothing to do */ - } else { /* adhoc client */ - /* correcting TSF */ - rtw_correct_TSF(padapter); - - /* start beacon */ - if (send_beacon23a(padapter) != _SUCCESS) { - pmlmeinfo->FW_sta_info[psta->mac_id].status = 0; - - pmlmeinfo->state ^= MSR_ADHOC; - - return; - } - - pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; - } - hw_var_set_mlme_join(padapter, 2); - } - - pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta; - - /* rate radaptive */ - Update_RA_Entry23a(padapter, psta); - - /* update adhoc sta_info */ - update_sta_info23a(padapter, psta); -} - -void mlmeext_sta_del_event_callback23a(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (is_client_associated_to_ap23a(padapter) || - is_IBSS_empty23a(padapter)) { - /* set_opmode_cmd(padapter, infra_client_with_mlme); */ - - hw_var_set_mlme_disconnect(padapter); - hw_var_set_bssid(padapter, null_addr); - - /* restore to initial setting. */ - update_tx_basic_rate23a(padapter, - padapter->registrypriv.wireless_mode); - - /* switch to the 20M Hz mode after disconnect */ - pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20; - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - - set_channel_bwmode23a(padapter, pmlmeext->cur_channel, - pmlmeext->cur_ch_offset, - pmlmeext->cur_bwmode); - - flush_all_cam_entry23a(padapter); - - pmlmeinfo->state = MSR_NOLINK; - - /* set MSR to no link state -> infra. mode */ - rtl8723a_set_media_status(padapter, MSR_INFRA); - - del_timer_sync(&pmlmeext->link_timer); - } -} - -static u8 chk_ap_is_alive(struct rtw_adapter *padapter, struct sta_info *psta) -{ - u8 ret = false; - - if (sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta) && - sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta) && - sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta)) - ret = false; - else - ret = true; - - sta_update_last_rx_pkts(psta); - return ret; -} - -void linked_status_chk23a(struct rtw_adapter *padapter) -{ - u32 i; - struct sta_info *psta; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sta_priv *pstapriv = &padapter->stapriv; - - if (is_client_associated_to_ap23a(padapter)) { - /* linked infrastructure client mode */ - - int tx_chk = _SUCCESS, rx_chk = _SUCCESS; - int rx_chk_limit; - - rx_chk_limit = 4; - - psta = rtw_get_stainfo23a(pstapriv, - pmlmeinfo->network.MacAddress); - if (psta) { - bool is_p2p_enable = false; - - if (chk_ap_is_alive(padapter, psta) == false) - rx_chk = _FAIL; - - if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts) - tx_chk = _FAIL; - - if (pmlmeext->active_keep_alive_check && - (rx_chk == _FAIL || tx_chk == _FAIL)) { - u8 backup_oper_channel = 0; - - /* switch to correct channel of current - network before issue keep-alive frames */ - if (rtw_get_oper_ch23a(padapter) != - pmlmeext->cur_channel) { - backup_oper_channel = - rtw_get_oper_ch23a(padapter); - SelectChannel23a(padapter, - pmlmeext->cur_channel); - } - - if (rx_chk != _SUCCESS) - issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, psta->hwaddr, 3, 1); - - if ((tx_chk != _SUCCESS && - pmlmeinfo->link_count++ == 0xf) || - rx_chk != _SUCCESS) { - tx_chk = issue_nulldata23a(padapter, - psta->hwaddr, - 0, 3, 1); - /* if tx acked and p2p disabled, - set rx_chk _SUCCESS to reset retry - count */ - if (tx_chk == _SUCCESS && - !is_p2p_enable) - rx_chk = _SUCCESS; - } - - /* back to the original operation channel */ - if (backup_oper_channel>0) - SelectChannel23a(padapter, - backup_oper_channel); - } else { - if (rx_chk != _SUCCESS) { - if (pmlmeext->retry == 0) { - issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress); - issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress); - issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress); - } - } - - if (tx_chk != _SUCCESS && - pmlmeinfo->link_count++ == 0xf) - tx_chk = issue_nulldata23a(padapter, - NULL, 0, 1, - 0); - } - - if (rx_chk == _FAIL) { - pmlmeext->retry++; - if (pmlmeext->retry > rx_chk_limit) { - DBG_8723A_LEVEL(_drv_always_, - "%s(%s): disconnect or " - "roaming\n", __func__, - padapter->pnetdev->name); - receive_disconnect23a(padapter, pmlmeinfo->network.MacAddress, - WLAN_REASON_EXPIRATION_CHK); - return; - } - } else - pmlmeext->retry = 0; - - if (tx_chk == _FAIL) - pmlmeinfo->link_count &= 0xf; - else { - pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts; - pmlmeinfo->link_count = 0; - } - - } - } else if (is_client_associated_to_ibss23a(padapter)) { - /* linked IBSS mode */ - /* for each assoc list entry to check the rx pkt counter */ - for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) { - if (pmlmeinfo->FW_sta_info[i].status == 1) { - psta = pmlmeinfo->FW_sta_info[i].psta; - - if (!psta) - continue; - - if (pmlmeinfo->FW_sta_info[i].rx_pkt == - sta_rx_pkts(psta)) { - - if (pmlmeinfo->FW_sta_info[i].retry<3) { - pmlmeinfo->FW_sta_info[i].retry++; - } else { - pmlmeinfo->FW_sta_info[i].retry = 0; - pmlmeinfo->FW_sta_info[i].status = 0; - report_del_sta_event23a(padapter, psta->hwaddr, - 65535/* indicate disconnect caused by no rx */ - ); - } - } else { - pmlmeinfo->FW_sta_info[i].retry = 0; - pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta); - } - } - } - /* set_link_timer(pmlmeext, DISCONNECT_TO); */ - } -} - -static void survey_timer_hdl(unsigned long data) -{ - struct rtw_adapter *padapter = (struct rtw_adapter *)data; - struct cmd_obj *ph2c; - struct sitesurvey_parm *psurveyPara; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - /* issue rtw_sitesurvey_cmd23a */ - if (pmlmeext->sitesurvey_res.state > SCAN_START) { - if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) - pmlmeext->sitesurvey_res.channel_idx++; - - if (pmlmeext->scan_abort == true) { - pmlmeext->sitesurvey_res.channel_idx = - pmlmeext->sitesurvey_res.ch_num; - DBG_8723A("%s idx:%d\n", __func__, - pmlmeext->sitesurvey_res.channel_idx); - - pmlmeext->scan_abort = false;/* reset */ - } - - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!ph2c) - goto exit_survey_timer_hdl; - - psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), - GFP_ATOMIC); - if (!psurveyPara) { - kfree(ph2c); - goto exit_survey_timer_hdl; - } - - init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, - GEN_CMD_CODE(_SiteSurvey)); - rtw_enqueue_cmd23a(pcmdpriv, ph2c); - } - -exit_survey_timer_hdl: - return; -} - -static void link_timer_hdl(unsigned long data) -{ - struct rtw_adapter *padapter = (struct rtw_adapter *)data; - /* static unsigned int rx_pkt = 0; */ - /* static u64 tx_cnt = 0; */ - /* struct xmit_priv *pxmitpriv = &padapter->xmitpriv; */ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - /* struct sta_priv *pstapriv = &padapter->stapriv; */ - - if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) { - DBG_8723A("link_timer_hdl:no beacon while connecting\n"); - pmlmeinfo->state = MSR_NOLINK; - report_join_res23a(padapter, -3); - } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) { - /* re-auth timer */ - if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) { - /* if (pmlmeinfo->auth_algo != dot11AuthAlgrthm_Auto) */ - /* */ - pmlmeinfo->state = 0; - report_join_res23a(padapter, -1); - return; - /* */ - /* else */ - /* */ - /* pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; */ - /* pmlmeinfo->reauth_count = 0; */ - /* */ - } - - DBG_8723A("link_timer_hdl: auth timeout and try again\n"); - pmlmeinfo->auth_seq = 1; - issue_auth(padapter, NULL, 0); - set_link_timer(pmlmeext, REAUTH_TO); - } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) { - /* re-assoc timer */ - if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) { - pmlmeinfo->state = MSR_NOLINK; - report_join_res23a(padapter, -2); - return; - } - - DBG_8723A("link_timer_hdl: assoc timeout and try again\n"); - issue_assocreq(padapter); - set_link_timer(pmlmeext, REASSOC_TO); - } -} - -static void addba_timer_hdl(unsigned long data) -{ - struct sta_info *psta = (struct sta_info *)data; - struct ht_priv *phtpriv; - - if (!psta) - return; - - phtpriv = &psta->htpriv; - - if (phtpriv->ht_option && phtpriv->ampdu_enable) { - if (phtpriv->candidate_tid_bitmap) - phtpriv->candidate_tid_bitmap = 0x0; - } -} - -void init_addba_retry_timer23a(struct sta_info *psta) -{ - setup_timer(&psta->addba_retry_timer, addba_timer_hdl, - (unsigned long)psta); -} - -void init_mlme_ext_timer23a(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - setup_timer(&pmlmeext->survey_timer, survey_timer_hdl, - (unsigned long)padapter); - - setup_timer(&pmlmeext->link_timer, link_timer_hdl, - (unsigned long)padapter); -} - -int NULL_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - return H2C_SUCCESS; -} - -int setopmode_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - enum nl80211_iftype type; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - const struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf; - - switch (psetop->mode) { - case NL80211_IFTYPE_P2P_GO: - case NL80211_IFTYPE_AP: - pmlmeinfo->state = MSR_AP; - type = MSR_AP; - break; - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_STATION: - /* clear state */ - pmlmeinfo->state &= ~(BIT(0)|BIT(1)); - /* set to STATION_STATE */ - pmlmeinfo->state |= MSR_INFRA; - type = MSR_INFRA; - break; - case NL80211_IFTYPE_ADHOC: - type = MSR_ADHOC; - break; - default: - type = MSR_NOLINK; - break; - } - - hw_var_set_opmode(padapter, type); - /* Set_NETYPE0_MSR(padapter, type); */ - - return H2C_SUCCESS; -} - -int createbss_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; - const struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf; - /* u32 initialgain; */ - - if (pparm->ifmode == NL80211_IFTYPE_AP || - pparm->ifmode == NL80211_IFTYPE_P2P_GO) { -#ifdef CONFIG_8723AU_AP_MODE - if (pmlmeinfo->state == MSR_AP) { - /* todo: */ - return H2C_SUCCESS; - } -#endif - } - - /* below is for ad-hoc master */ - if (pparm->ifmode == NL80211_IFTYPE_ADHOC) { - rtw_joinbss_reset23a(padapter); - - pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20; - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - pmlmeinfo->ERP_enable = 0; - pmlmeinfo->WMM_enable = 0; - pmlmeinfo->HT_enable = 0; - pmlmeinfo->HT_caps_enable = 0; - pmlmeinfo->HT_info_enable = 0; - - /* disable dynamic functions, such as high power, DIG */ - rtl8723a_odm_support_ability_backup(padapter); - - rtl8723a_odm_support_ability_clr(padapter, - DYNAMIC_FUNC_DISABLE); - - /* cancel link timer */ - del_timer_sync(&pmlmeext->link_timer); - - /* clear CAM */ - flush_all_cam_entry23a(padapter); - - if (pparm->IELength > MAX_IE_SZ)/* Check pbuf->IELength */ - return H2C_PARAMETERS_ERROR; - - memcpy(pnetwork, pparm, sizeof(struct wlan_bssid_ex)); - - start_create_ibss(padapter); - } - - return H2C_SUCCESS; -} - -int join_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - struct registry_priv *pregpriv = &padapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; - const struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf; - struct ieee80211_ht_operation *pht_info; - u32 i; - u8 *p; - /* u32 initialgain; */ - /* u32 acparm; */ - - /* check already connecting to AP or not */ - if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { - if (pmlmeinfo->state & MSR_INFRA) - issue_deauth_ex(padapter, pnetwork->MacAddress, - WLAN_REASON_DEAUTH_LEAVING, 5, 100); - - pmlmeinfo->state = MSR_NOLINK; - - /* clear CAM */ - flush_all_cam_entry23a(padapter); - - del_timer_sync(&pmlmeext->link_timer); - - /* set MSR to nolink -> infra. mode */ - rtl8723a_set_media_status(padapter, MSR_INFRA); - - hw_var_set_mlme_disconnect(padapter); - } - - rtw_joinbss_reset23a(padapter); - - pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20; - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - pmlmeinfo->ERP_enable = 0; - pmlmeinfo->WMM_enable = 0; - pmlmeinfo->HT_enable = 0; - pmlmeinfo->HT_caps_enable = 0; - pmlmeinfo->HT_info_enable = 0; - pmlmeinfo->bwmode_updated = false; - /* pmlmeinfo->assoc_AP_vendor = HT_IOT_PEER_MAX; */ - - if (pparm->IELength > MAX_IE_SZ)/* Check pbuf->IELength */ - return H2C_PARAMETERS_ERROR; - - memcpy(pnetwork, pbuf, sizeof(struct wlan_bssid_ex)); - - /* Check AP vendor to move rtw_joinbss_cmd23a() */ - /* pmlmeinfo->assoc_AP_vendor = check_assoc_AP23a(pnetwork->IEs, - pnetwork->IELength); */ - - for (i = 0; i < pnetwork->IELength;) { - p = pnetwork->IEs + i; - - switch (p[0]) { - case WLAN_EID_VENDOR_SPECIFIC:/* Get WMM IE. */ - if (!memcmp(p + 2, WMM_OUI23A, 4)) - pmlmeinfo->WMM_enable = 1; - break; - - case WLAN_EID_HT_CAPABILITY: /* Get HT Cap IE. */ - pmlmeinfo->HT_caps_enable = 1; - break; - - case WLAN_EID_HT_OPERATION: /* Get HT Info IE. */ - pmlmeinfo->HT_info_enable = 1; - - /* spec case only for cisco's ap because cisco's ap - * issue assoc rsp using mcs rate @40MHz or @20MHz */ - pht_info = (struct ieee80211_ht_operation *)(p + 2); - - if (pregpriv->cbw40_enable && - (pht_info->ht_param & - IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) { - /* switch to the 40M Hz mode according to AP */ - pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40; - switch (pht_info->ht_param & - IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { - case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: - pmlmeext->cur_ch_offset = - HAL_PRIME_CHNL_OFFSET_LOWER; - break; - - case IEEE80211_HT_PARAM_CHA_SEC_BELOW: - pmlmeext->cur_ch_offset = - HAL_PRIME_CHNL_OFFSET_UPPER; - break; - - default: - pmlmeext->cur_ch_offset = - HAL_PRIME_CHNL_OFFSET_DONT_CARE; - break; - } - - DBG_8723A("set ch/bw before connected\n"); - } - break; - - default: - break; - } - - i += (p[1] + 2); - } - - hw_var_set_bssid(padapter, pmlmeinfo->network.MacAddress); - hw_var_set_mlme_join(padapter, 0); - - /* cancel link timer */ - del_timer_sync(&pmlmeext->link_timer); - - start_clnt_join(padapter); - - return H2C_SUCCESS; -} - -int disconnect_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - const struct disconnect_parm *param = (struct disconnect_parm *)pbuf; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; - - if (is_client_associated_to_ap23a(padapter)) { - issue_deauth_ex(padapter, pnetwork->MacAddress, - WLAN_REASON_DEAUTH_LEAVING, - param->deauth_timeout_ms/100, 100); - } - - /* set_opmode_cmd(padapter, infra_client_with_mlme); */ - - /* pmlmeinfo->state = MSR_NOLINK; */ - - hw_var_set_mlme_disconnect(padapter); - hw_var_set_bssid(padapter, null_addr); - - /* restore to initial setting. */ - update_tx_basic_rate23a(padapter, padapter->registrypriv.wireless_mode); - - if ((pmlmeinfo->state & 0x03) == MSR_ADHOC || - (pmlmeinfo->state & 0x03) == MSR_AP) - rtl8723a_set_bcn_func(padapter, 0); /* Stop BCN */ - - /* set MSR to no link state -> infra. mode */ - rtl8723a_set_media_status(padapter, MSR_INFRA); - - pmlmeinfo->state = MSR_NOLINK; - - /* switch to the 20M Hz mode after disconnect */ - pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20; - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - - set_channel_bwmode23a(padapter, pmlmeext->cur_channel, - pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - - flush_all_cam_entry23a(padapter); - - del_timer_sync(&pmlmeext->link_timer); - - rtw_free_uc_swdec_pending_queue23a(padapter); - - return H2C_SUCCESS; -} - -static int -rtw_scan_ch_decision(struct rtw_adapter *padapter, - struct rtw_ieee80211_channel *out, u32 out_num, - const struct rtw_ieee80211_channel *in, u32 in_num) -{ - int i, j; - int scan_ch_num = 0; - int set_idx; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - /* clear out first */ - memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num); - - /* acquire channels from in */ - j = 0; - for (i = 0;i<in_num;i++) { - if (in[i].hw_value && - !(in[i].flags & IEEE80211_CHAN_DISABLED) && - (set_idx = rtw_ch_set_search_ch23a(pmlmeext->channel_set, - in[i].hw_value)) >= 0) { - memcpy(&out[j], &in[i], - sizeof(struct rtw_ieee80211_channel)); - - if (pmlmeext->channel_set[set_idx].ScanType == - SCAN_PASSIVE) - out[j].flags &= IEEE80211_CHAN_NO_IR; - - j++; - } - if (j>= out_num) - break; - } - - /* if out is empty, use channel_set as default */ - if (j == 0) { - for (i = 0;i<pmlmeext->max_chan_nums;i++) { - out[i].hw_value = pmlmeext->channel_set[i].ChannelNum; - - if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE) - out[i].flags &= IEEE80211_CHAN_NO_IR; - - j++; - } - } - - if (padapter->setband == GHZ_24) { /* 2.4G */ - for (i = 0; i < j ; i++) { - if (out[i].hw_value > 35) - memset(&out[i], 0, - sizeof(struct rtw_ieee80211_channel)); - else - scan_ch_num++; - } - j = scan_ch_num; - } else if (padapter->setband == GHZ_50) { /* 5G */ - for (i = 0; i < j ; i++) { - if (out[i].hw_value > 35) { - memcpy(&out[scan_ch_num++], &out[i], - sizeof(struct rtw_ieee80211_channel)); - } - } - j = scan_ch_num; - } else - {} - - return j; -} - -int sitesurvey_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - const struct sitesurvey_parm *pparm = (struct sitesurvey_parm *)pbuf; - u8 bdelayscan = false; - u32 initialgain; - u32 i; - - if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) { - pmlmeext->sitesurvey_res.state = SCAN_START; - pmlmeext->sitesurvey_res.bss_cnt = 0; - pmlmeext->sitesurvey_res.channel_idx = 0; - - for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) { - if (pparm->ssid[i].ssid_len) { - memcpy(pmlmeext->sitesurvey_res.ssid[i].ssid, - pparm->ssid[i].ssid, - IEEE80211_MAX_SSID_LEN); - pmlmeext->sitesurvey_res.ssid[i].ssid_len = - pparm->ssid[i].ssid_len; - } else { - pmlmeext->sitesurvey_res.ssid[i].ssid_len = 0; - } - } - - pmlmeext->sitesurvey_res.ch_num = - rtw_scan_ch_decision(padapter, - pmlmeext->sitesurvey_res.ch, - RTW_CHANNEL_SCAN_AMOUNT, - pparm->ch, pparm->ch_num); - - pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode; - - /* issue null data if associating to the AP */ - if (is_client_associated_to_ap23a(padapter)) { - pmlmeext->sitesurvey_res.state = SCAN_TXNULL; - - /* switch to correct channel of current network - before issue keep-alive frames */ - if (rtw_get_oper_ch23a(padapter) != - pmlmeext->cur_channel) - SelectChannel23a(padapter, - pmlmeext->cur_channel); - - issue_nulldata23a(padapter, NULL, 1, 3, 500); - - bdelayscan = true; - } - - if (bdelayscan) { - /* delay 50ms to protect nulldata(1). */ - set_survey_timer(pmlmeext, 50); - return H2C_SUCCESS; - } - } - - if (pmlmeext->sitesurvey_res.state == SCAN_START || - pmlmeext->sitesurvey_res.state == SCAN_TXNULL) { - /* disable dynamic functions, such as high power, DIG */ - rtl8723a_odm_support_ability_backup(padapter); - rtl8723a_odm_support_ability_clr(padapter, - DYNAMIC_FUNC_DISABLE); - - /* config the initial gain under scanning, need to - write the BB registers */ - if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled == true) - initialgain = 0x30; - else - initialgain = 0x1E; - - rtl8723a_set_initial_gain(padapter, initialgain); - - /* set MSR to no link state */ - rtl8723a_set_media_status(padapter, MSR_NOLINK); - - rtl8723a_mlme_sitesurvey(padapter, 1); - - pmlmeext->sitesurvey_res.state = SCAN_PROCESS; - } - - rtw_site_survey(padapter); - - return H2C_SUCCESS; -} - -int setauth_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - const struct setauth_parm *pparm = (struct setauth_parm *)pbuf; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (pparm->mode < 4) - pmlmeinfo->auth_algo = pparm->mode; - - return H2C_SUCCESS; -} - -int setkey_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - unsigned short ctrl; - const struct setkey_parm *pparm = (struct setkey_parm *)pbuf; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - unsigned char null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - - /* main tx key for wep. */ - if (pparm->set_tx) - pmlmeinfo->key_index = pparm->keyid; - - /* write cam */ - ctrl = BIT(15) | (pparm->algorithm) << 2 | pparm->keyid; - - DBG_8723A_LEVEL(_drv_always_, "set group key to hw: alg:%d(WEP40-1 " - "WEP104-5 TKIP-2 AES-4) keyid:%d\n", - pparm->algorithm, pparm->keyid); - rtl8723a_cam_write(padapter, pparm->keyid, ctrl, null_sta, pparm->key); - - /* allow multicast packets to driver */ - rtl8723a_on_rcr_am(padapter); - - return H2C_SUCCESS; -} - -int set_stakey_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - u16 ctrl = 0; - u8 cam_id;/* cam_entry */ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - const struct set_stakey_parm *pparm = (struct set_stakey_parm *)pbuf; - - /* cam_entry: */ - /* 0~3 for default key */ - - /* for concurrent mode (ap+sta): */ - /* default key is disable, using sw encrypt/decrypt */ - /* cam_entry = 4 for sta mode (macid = 0) */ - /* cam_entry(macid+3) = 5 ~ N for ap mode (aid = 1~N, macid = 2 ~N) */ - - /* for concurrent mode (sta+sta): */ - /* default key is disable, using sw encrypt/decrypt */ - /* cam_entry = 4 mapping to macid = 0 */ - /* cam_entry = 5 mapping to macid = 2 */ - - cam_id = 4; - - DBG_8723A_LEVEL(_drv_always_, "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) == MSR_AP) { - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - - if (pparm->algorithm == 0) { /* clear cam entry */ - clear_cam_entry23a(padapter, pparm->id); - return H2C_SUCCESS_RSP; - } - - psta = rtw_get_stainfo23a(pstapriv, pparm->addr); - if (psta) { - ctrl = BIT(15) | (pparm->algorithm << 2); - - DBG_8723A("r871x_set_stakey_hdl23a(): enc_algorithm " - "=%d\n", pparm->algorithm); - - if (psta->mac_id < 1 || psta->mac_id > (NUM_STA - 4)) { - DBG_8723A("r871x_set_stakey_hdl23a():set_stakey" - " failed, mac_id(aid) =%d\n", - psta->mac_id); - return H2C_REJECTED; - } - - /* 0~3 for default key, cmd_id = macid + 3, - macid = aid+1; */ - cam_id = psta->mac_id + 3; - - DBG_8723A("Write CAM, mac_addr =%pM, " - "cam_entry =%d\n", pparm->addr, cam_id); - - rtl8723a_cam_write(padapter, cam_id, ctrl, - pparm->addr, pparm->key); - - return H2C_SUCCESS_RSP; - } else { - DBG_8723A("r871x_set_stakey_hdl23a(): sta has been " - "free\n"); - return H2C_REJECTED; - } - } - - /* below for sta mode */ - - if (pparm->algorithm == 0) { /* clear cam entry */ - clear_cam_entry23a(padapter, pparm->id); - return H2C_SUCCESS; - } - - ctrl = BIT(15) | (pparm->algorithm << 2); - - rtl8723a_cam_write(padapter, cam_id, ctrl, pparm->addr, pparm->key); - - pmlmeinfo->enc_algo = pparm->algorithm; - - return H2C_SUCCESS; -} - -int add_ba_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - const struct addBaReq_parm *pparm = (struct addBaReq_parm *)pbuf; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sta_info *psta; - - psta = rtw_get_stainfo23a(&padapter->stapriv, pparm->addr); - - if (!psta) - return H2C_SUCCESS; - - if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && - pmlmeinfo->HT_enable) || - (pmlmeinfo->state & 0x03) == MSR_AP) { - issue_action_BA23a(padapter, pparm->addr, - WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid); - mod_timer(&psta->addba_retry_timer, - jiffies + msecs_to_jiffies(ADDBA_TO)); - } else - psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid); - - return H2C_SUCCESS; -} - -int set_tx_beacon_cmd23a(struct rtw_adapter *padapter) -{ - struct cmd_obj *ph2c; - struct Tx_Beacon_param *ptxBeacon_parm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - u8 res = _SUCCESS; - int len_diff = 0; - - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - ptxBeacon_parm = kzalloc(sizeof(struct Tx_Beacon_param), GFP_ATOMIC); - if (!ptxBeacon_parm) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - memcpy(&ptxBeacon_parm->network, &pmlmeinfo->network, - sizeof(struct wlan_bssid_ex)); - - len_diff = update_hidden_ssid(ptxBeacon_parm->network.IEs, - ptxBeacon_parm->network.IELength, - pmlmeinfo->hidden_ssid_mode); - ptxBeacon_parm->network.IELength += len_diff; - - init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, - GEN_CMD_CODE(_TX_Beacon)); - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); - -exit: - return res; -} - -int mlme_evt_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - u8 evt_code, evt_seq; - u16 evt_sz; - const struct C2HEvent_Header *c2h; - void (*event_callback)(struct rtw_adapter *dev, const u8 *pbuf); - - c2h = (struct C2HEvent_Header *)pbuf; - evt_sz = c2h->len; - evt_seq = c2h->seq; - evt_code = c2h->ID; - - /* checking if event code is valid */ - if (evt_code >= MAX_C2HEVT) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "Event Code(%d) mismatch!\n", evt_code); - 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_, - "Event(%d) Parm Size mismatch (%d vs %d)!\n", - evt_code, wlanevents[evt_code].parmsize, evt_sz); - goto _abort_event_; - } - - event_callback = wlanevents[evt_code].event_callback; - event_callback(padapter, pbuf + sizeof(struct C2HEvent_Header)); - -_abort_event_: - - return H2C_SUCCESS; -} - -int h2c_msg_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - if (!pbuf) - return H2C_PARAMETERS_ERROR; - - return H2C_SUCCESS; -} - -int tx_beacon_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - if (send_beacon23a(padapter) == _FAIL) { - DBG_8723A("issue_beacon23a, fail!\n"); - return H2C_PARAMETERS_ERROR; - } -#ifdef CONFIG_8723AU_AP_MODE - else { /* tx bc/mc frames after update TIM */ - struct sta_info *psta_bmc; - struct list_head *phead; - struct xmit_frame *pxmitframe, *ptmp; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct sta_priv *pstapriv = &padapter->stapriv; - - /* for BC/MC Frames */ - psta_bmc = rtw_get_bcmc_stainfo23a(padapter); - if (!psta_bmc) - return H2C_SUCCESS; - - if (pstapriv->tim_bitmap & BIT(0) && psta_bmc->sleepq_len > 0) { - msleep(10);/* 10ms, ATIM(HIQ) Windows */ - /* spin_lock_bh(&psta_bmc->sleep_q.lock); */ - spin_lock_bh(&pxmitpriv->lock); - - phead = get_list_head(&psta_bmc->sleep_q); - - list_for_each_entry_safe(pxmitframe, ptmp, - phead, list) { - - list_del_init(&pxmitframe->list); - - psta_bmc->sleepq_len--; - if (psta_bmc->sleepq_len>0) - pxmitframe->attrib.mdata = 1; - else - pxmitframe->attrib.mdata = 0; - - pxmitframe->attrib.triggered = 1; - - pxmitframe->attrib.qsel = 0x11;/* HIQ */ - - rtl8723au_hal_xmitframe_enqueue(padapter, - pxmitframe); - } - /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */ - spin_unlock_bh(&pxmitpriv->lock); - } - } -#endif - - return H2C_SUCCESS; -} - -int set_ch_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - const struct set_ch_parm *set_ch_parm; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (!pbuf) - return H2C_PARAMETERS_ERROR; - - set_ch_parm = (struct set_ch_parm *)pbuf; - - DBG_8723A("%s(%s): ch:%u, bw:%u, ch_offset:%u\n", __func__, - padapter->pnetdev->name, 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; - - set_channel_bwmode23a(padapter, set_ch_parm->ch, - set_ch_parm->ch_offset, set_ch_parm->bw); - - return H2C_SUCCESS; -} - -int set_chplan_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - const struct SetChannelPlan_param *setChannelPlan_param; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (!pbuf) - return H2C_PARAMETERS_ERROR; - - setChannelPlan_param = (struct SetChannelPlan_param *)pbuf; - - pmlmeext->max_chan_nums = - init_channel_set(padapter, setChannelPlan_param->channel_plan, - pmlmeext->channel_set); - init_channel_list(padapter, pmlmeext->channel_set, - pmlmeext->max_chan_nums, &pmlmeext->channel_list); - - return H2C_SUCCESS; -} - -int led_blink_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - struct LedBlink_param *ledBlink_param; - - if (!pbuf) - return H2C_PARAMETERS_ERROR; - - ledBlink_param = (struct LedBlink_param *)pbuf; - - return H2C_SUCCESS; -} - -int set_csa_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - return H2C_REJECTED; -} - -/* TDLS_WRCR : write RCR DATA BIT */ -/* TDLS_SD_PTI : issue peer traffic indication */ -/* TDLS_CS_OFF : go back to the channel linked with AP, - terminating channel switch procedure */ -/* TDLS_INIT_CH_SEN : init channel sensing, receive all data and - mgnt frame */ -/* TDLS_DONE_CH_SEN : channel sensing and report candidate channel */ -/* TDLS_OFF_CH : first time set channel to off channel */ -/* TDLS_BASE_CH : go back tp the channel linked with AP when set - base channel as target channel */ -/* TDLS_P_OFF_CH : periodically go to off channel */ -/* TDLS_P_BASE_CH : periodically go back to base channel */ -/* TDLS_RS_RCR : restore RCR */ -/* TDLS_CKALV_PH1 : check alive timer phase1 */ -/* TDLS_CKALV_PH2 : check alive timer phase2 */ -/* TDLS_FREE_STA : free tdls sta */ -int tdls_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - return H2C_REJECTED; -} diff --git a/drivers/staging/rtl8723au/core/rtw_pwrctrl.c b/drivers/staging/rtl8723au/core/rtw_pwrctrl.c deleted file mode 100644 index 2d43958..0000000 --- a/drivers/staging/rtl8723au/core/rtw_pwrctrl.c +++ /dev/null @@ -1,607 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RTW_PWRCTRL_C_ - -#include <linux/mutex.h> -#include <osdep_service.h> -#include <drv_types.h> -#include <osdep_intf.h> -#include <rtl8723a_cmd.h> -#include <rtw_sreset.h> - -#include <rtl8723a_bt_intf.h> -#include <usb_ops_linux.h> - -void ips_enter23a(struct rtw_adapter *padapter) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - - mutex_lock(&pwrpriv->mutex_lock); - - pwrpriv->bips_processing = true; - - /* syn ips_mode with request */ - pwrpriv->ips_mode = pwrpriv->ips_mode_req; - - pwrpriv->ips_enter23a_cnts++; - DBG_8723A("==>ips_enter23a cnts:%d\n", pwrpriv->ips_enter23a_cnts); - rtl8723a_BT_disable_coexist(padapter); - - if (pwrpriv->change_rfpwrstate == rf_off) { - pwrpriv->bpower_saving = true; - DBG_8723A_LEVEL(_drv_always_, "nolinked power save enter\n"); - - if (pwrpriv->ips_mode == IPS_LEVEL_2) - pwrpriv->bkeepfwalive = true; - - rtw_ips_pwr_down23a(padapter); - pwrpriv->rf_pwrstate = rf_off; - } - pwrpriv->bips_processing = false; - - mutex_unlock(&pwrpriv->mutex_lock); -} - -int ips_leave23a(struct rtw_adapter *padapter) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - int result = _SUCCESS; - int keyid; - - mutex_lock(&pwrpriv->mutex_lock); - - if (pwrpriv->rf_pwrstate == rf_off && !pwrpriv->bips_processing) { - pwrpriv->bips_processing = true; - pwrpriv->change_rfpwrstate = rf_on; - pwrpriv->ips_leave23a_cnts++; - DBG_8723A("==>ips_leave23a cnts:%d\n", - pwrpriv->ips_leave23a_cnts); - - result = rtw_ips_pwr_up23a(padapter); - if (result == _SUCCESS) - pwrpriv->rf_pwrstate = rf_on; - - DBG_8723A_LEVEL(_drv_always_, "nolinked power save leave\n"); - - if (psecuritypriv->dot11PrivacyAlgrthm == - WLAN_CIPHER_SUITE_WEP40 || - psecuritypriv->dot11PrivacyAlgrthm == - WLAN_CIPHER_SUITE_WEP104) { - DBG_8723A("==>%s, channel(%d), processing(%x)\n", - __func__, padapter->mlmeextpriv.cur_channel, - pwrpriv->bips_processing); - set_channel_bwmode23a(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)) { - if (keyid == - psecuritypriv->dot11PrivacyKeyIndex) - result = rtw_set_key23a(padapter, psecuritypriv, keyid, 1); - else - result = rtw_set_key23a(padapter, psecuritypriv, keyid, 0); - } - } - } - - DBG_8723A("==> ips_leave23a.....LED(0x%08x)...\n", - rtl8723au_read32(padapter, 0x4c)); - pwrpriv->bips_processing = false; - - pwrpriv->bkeepfwalive = false; - pwrpriv->bpower_saving = false; - } - - mutex_unlock(&pwrpriv->mutex_lock); - - return result; -} - - -static bool rtw_pwr_unassociated_idle(struct rtw_adapter *adapter) -{ - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct xmit_priv *pxmit_priv = &adapter->xmitpriv; - - bool ret = false; - - if (time_after_eq(adapter->pwrctrlpriv.ips_deny_time, jiffies)) - goto exit; - - if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR) || - check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS) || - check_fwstate(pmlmepriv, WIFI_AP_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)){ - goto exit; - } - - if (pxmit_priv->free_xmitbuf_cnt != NR_XMITBUFF || - pxmit_priv->free_xmit_extbuf_cnt != NR_XMIT_EXTBUFF) { - DBG_8723A_LEVEL(_drv_always_, - "There are some pkts to transmit\n"); - DBG_8723A_LEVEL(_drv_info_, "free_xmitbuf_cnt: %d, " - "free_xmit_extbuf_cnt: %d\n", - pxmit_priv->free_xmitbuf_cnt, - pxmit_priv->free_xmit_extbuf_cnt); - goto exit; - } - - ret = true; - -exit: - return ret; -} - -void rtw_ps_processor23a(struct rtw_adapter *padapter) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - pwrpriv->ps_processing = true; - - if (pwrpriv->bips_processing == true) - goto exit; - - if (pwrpriv->ips_mode_req == IPS_NONE) - goto exit; - - if (!rtw_pwr_unassociated_idle(padapter)) - goto exit; - - if (pwrpriv->rf_pwrstate == rf_on && - (pwrpriv->pwr_state_check_cnts % 4) == 0) { - DBG_8723A("==>%s .fw_state(%x)\n", __func__, - get_fwstate(pmlmepriv)); - pwrpriv->change_rfpwrstate = rf_off; - ips_enter23a(padapter); - } -exit: - rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv); - pwrpriv->ps_processing = false; -} - -static void pwr_state_check_handler(unsigned long data) -{ - struct rtw_adapter *padapter = (struct rtw_adapter *)data; - - rtw_ps_cmd23a(padapter); -} - -/* - * - * Parameters - * padapter - * pslv power state level, only could be PS_STATE_S0 ~ PS_STATE_S4 - * - */ -void rtw_set_rpwm23a(struct rtw_adapter *padapter, u8 pslv) -{ - u8 rpwm; - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - - pslv = PS_STATE(pslv); - - if (pwrpriv->btcoex_rfon) { - if (pslv < PS_STATE_S4) - 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); - return; - } - - if (padapter->bSurpriseRemoved == true || - padapter->hw_init_completed == false) { - 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 == true) { - 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); - return; - } - } - - rpwm = pslv | pwrpriv->tog; - RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_, - "rtw_set_rpwm23a: rpwm = 0x%02x cpwm = 0x%02x\n", - rpwm, pwrpriv->cpwm); - - pwrpriv->rpwm = pslv; - - rtl8723a_set_rpwm(padapter, rpwm); - - pwrpriv->tog += 0x80; - pwrpriv->cpwm = pslv; -} - -static bool PS_RDY_CHECK(struct rtw_adapter *padapter) -{ - unsigned long delta_time; - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - delta_time = jiffies - pwrpriv->DelayLPSLastTimeStamp; - - if (delta_time < LPS_DELAY_TIME) - return false; - - if (!check_fwstate(pmlmepriv, _FW_LINKED) || - check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) || - check_fwstate(pmlmepriv, WIFI_AP_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) - return false; - if (pwrpriv->bInSuspend) - return false; - if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && - !padapter->securitypriv.binstallGrpkey) { - DBG_8723A("Group handshake still in progress !!!\n"); - return false; - } - if (!rtw_cfg80211_pwr_mgmt(padapter)) - return false; - - return true; -} - -void rtw_set_ps_mode23a(struct rtw_adapter *padapter, u8 ps_mode, - u8 smart_ps, u8 bcn_ant_mode) -{ - 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); - return; - } - - if (pwrpriv->pwr_mode == ps_mode) { - if (PS_MODE_ACTIVE == ps_mode) - return; - - if (pwrpriv->smart_ps == smart_ps && - pwrpriv->bcn_ant_mode == bcn_ant_mode) - return; - } - - if (ps_mode == PS_MODE_ACTIVE) { - DBG_8723A("rtw_set_ps_mode23a: Leave 802.11 power save\n"); - - pwrpriv->pwr_mode = ps_mode; - rtw_set_rpwm23a(padapter, PS_STATE_S4); - rtl8723a_set_FwPwrMode_cmd(padapter, ps_mode); - pwrpriv->bFwCurrentInPSMode = false; - } else { - if (PS_RDY_CHECK(padapter) || - rtl8723a_BT_using_antenna_1(padapter)) { - DBG_8723A("%s: Enter 802.11 power save\n", __func__); - - pwrpriv->bFwCurrentInPSMode = true; - pwrpriv->pwr_mode = ps_mode; - pwrpriv->smart_ps = smart_ps; - pwrpriv->bcn_ant_mode = bcn_ant_mode; - rtl8723a_set_FwPwrMode_cmd(padapter, ps_mode); - - rtw_set_rpwm23a(padapter, PS_STATE_S2); - } - } -} - -/* - * Return: - * 0: Leave OK - * -1: Timeout - * -2: Other error - */ -s32 LPS_RF_ON_check23a(struct rtw_adapter *padapter, u32 delay_ms) -{ - unsigned long start_time, end_time; - u8 bAwake = false; - s32 err = 0; - - start_time = jiffies; - end_time = start_time + msecs_to_jiffies(delay_ms); - - while (1) { - bAwake = rtl8723a_get_fwlps_rf_on(padapter); - if (bAwake == true) - break; - - if (padapter->bSurpriseRemoved == true) { - err = -2; - DBG_8723A("%s: device surprise removed!!\n", __func__); - break; - } - - if (time_after(jiffies, end_time)) { - err = -1; - DBG_8723A("%s: Wait for FW LPS leave more than %u " - "ms!\n", __func__, delay_ms); - break; - } - udelay(100); - } - - return err; -} - -/* Description: */ -/* Enter the leisure power save mode. */ -void LPS_Enter23a(struct rtw_adapter *padapter) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - - if (!PS_RDY_CHECK(padapter)) - return; - - if (pwrpriv->bLeisurePs) { - /* Idle for a while if we connect to AP a while ago. */ - if (pwrpriv->LpsIdleCount >= 2) { /* 4 Sec */ - if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) { - pwrpriv->bpower_saving = true; - DBG_8723A("%s smart_ps:%d\n", __func__, - pwrpriv->smart_ps); - /* For Tenda W311R IOT issue */ - rtw_set_ps_mode23a(padapter, - pwrpriv->power_mgnt, - pwrpriv->smart_ps, 0); - } - } else - pwrpriv->LpsIdleCount++; - } -} - -/* Description: */ -/* Leave the leisure power save mode. */ -void LPS_Leave23a(struct rtw_adapter *padapter) -{ -#define LPS_LEAVE_TIMEOUT_MS 100 - - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - - if (pwrpriv->bLeisurePs) { - if (pwrpriv->pwr_mode != PS_MODE_ACTIVE) { - rtw_set_ps_mode23a(padapter, PS_MODE_ACTIVE, 0, 0); - - if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) - LPS_RF_ON_check23a(padapter, - LPS_LEAVE_TIMEOUT_MS); - } - } - - pwrpriv->bpower_saving = false; -} - -/* Description: Leave all power save mode: LPS, FwLPS, IPS if needed. */ -/* Move code to function by tynli. 2010.03.26. */ -void LeaveAllPowerSaveMode23a(struct rtw_adapter *Adapter) -{ - struct mlme_priv *pmlmepriv = &Adapter->mlmepriv; - u8 enqueue = 0; - - /* DBG_8723A("%s.....\n", __func__); */ - if (check_fwstate(pmlmepriv, _FW_LINKED)) - rtw_lps_ctrl_wk_cmd23a(Adapter, LPS_CTRL_LEAVE, enqueue); -} - -void rtw_init_pwrctrl_priv23a(struct rtw_adapter *padapter) -{ - struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; - - mutex_init(&pwrctrlpriv->mutex_lock); - pwrctrlpriv->rf_pwrstate = rf_on; - pwrctrlpriv->ips_enter23a_cnts = 0; - pwrctrlpriv->ips_leave23a_cnts = 0; - pwrctrlpriv->bips_processing = false; - - pwrctrlpriv->ips_mode = padapter->registrypriv.ips_mode; - pwrctrlpriv->ips_mode_req = padapter->registrypriv.ips_mode; - - pwrctrlpriv->pwr_state_check_interval = RTW_PWR_STATE_CHK_INTERVAL; - pwrctrlpriv->pwr_state_check_cnts = 0; - pwrctrlpriv->bInSuspend = false; - pwrctrlpriv->bkeepfwalive = false; - - pwrctrlpriv->LpsIdleCount = 0; - - /* PS_MODE_MIN; */ - pwrctrlpriv->power_mgnt = padapter->registrypriv.power_mgnt; - pwrctrlpriv->bLeisurePs = - (PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt)?true:false; - - pwrctrlpriv->bFwCurrentInPSMode = false; - - pwrctrlpriv->rpwm = 0; - pwrctrlpriv->cpwm = PS_STATE_S4; - - pwrctrlpriv->pwr_mode = PS_MODE_ACTIVE; - pwrctrlpriv->smart_ps = padapter->registrypriv.smart_ps; - pwrctrlpriv->bcn_ant_mode = 0; - - pwrctrlpriv->tog = 0x80; - - pwrctrlpriv->btcoex_rfon = false; - - setup_timer(&pwrctrlpriv->pwr_state_check_timer, - pwr_state_check_handler, (unsigned long)padapter); -} - -void rtw_free_pwrctrl_priv(struct rtw_adapter *adapter) -{ -} - -inline void rtw_set_ips_deny23a(struct rtw_adapter *padapter, u32 ms) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - - pwrpriv->ips_deny_time = jiffies + msecs_to_jiffies(ms); -} - -/* -* rtw_pwr_wakeup - Wake the NIC up from: 1)IPS. 2)USB autosuspend -* @adapter: pointer to _adapter structure -* @ips_deffer_ms: the ms will prevent from falling into IPS after wakeup -* Return _SUCCESS or _FAIL -*/ - -int _rtw_pwr_wakeup23a(struct rtw_adapter *padapter, u32 ips_deffer_ms, const char *caller) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - int ret = _SUCCESS; - unsigned long start = jiffies; - unsigned long new_deny_time; - - new_deny_time = jiffies + msecs_to_jiffies(ips_deffer_ms); - - if (time_before(pwrpriv->ips_deny_time, new_deny_time)) - pwrpriv->ips_deny_time = new_deny_time; - - if (pwrpriv->ps_processing) { - DBG_8723A("%s wait ps_processing...\n", __func__); - while (pwrpriv->ps_processing && - jiffies_to_msecs(jiffies - start) <= 3000) - msleep(10); - if (pwrpriv->ps_processing) - DBG_8723A("%s wait ps_processing timeout\n", __func__); - else - DBG_8723A("%s wait ps_processing done\n", __func__); - } - - if (rtw_sreset_inprogress(padapter)) { - DBG_8723A("%s wait sreset_inprogress...\n", __func__); - while (rtw_sreset_inprogress(padapter) && - jiffies_to_msecs(jiffies - start) <= 4000) - msleep(10); - if (rtw_sreset_inprogress(padapter)) - DBG_8723A("%s wait sreset_inprogress timeout\n", - __func__); - else - DBG_8723A("%s wait sreset_inprogress done\n", __func__); - } - - if (pwrpriv->bInSuspend) { - DBG_8723A("%s wait bInSuspend...\n", __func__); - while (pwrpriv->bInSuspend && - (jiffies_to_msecs(jiffies - start) <= 3000)) { - msleep(10); - } - if (pwrpriv->bInSuspend) - DBG_8723A("%s wait bInSuspend timeout\n", __func__); - else - DBG_8723A("%s wait bInSuspend done\n", __func__); - } - - /* System suspend is not allowed to wakeup */ - if (pwrpriv->bInSuspend) { - ret = _FAIL; - goto exit; - } - - /* I think this should be check in IPS, LPS, autosuspend functions... */ - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - ret = _SUCCESS; - goto exit; - } - - if (rf_off == pwrpriv->rf_pwrstate) { - DBG_8723A("%s call ips_leave23a....\n", __func__); - if (ips_leave23a(padapter)== _FAIL) { - DBG_8723A("======> ips_leave23a fail.............\n"); - ret = _FAIL; - goto exit; - } - } - - /* TODO: the following checking need to be merged... */ - if (padapter->bDriverStopped || !padapter->bup || - !padapter->hw_init_completed) { - DBG_8723A("%s: bDriverStopped =%d, bup =%d, hw_init_completed " - "=%u\n", caller, padapter->bDriverStopped, - padapter->bup, padapter->hw_init_completed); - ret = _FAIL; - goto exit; - } - -exit: - new_deny_time = jiffies + msecs_to_jiffies(ips_deffer_ms); - if (time_before(pwrpriv->ips_deny_time, new_deny_time)) - pwrpriv->ips_deny_time = new_deny_time; - return ret; -} - -int rtw_pm_set_lps23a(struct rtw_adapter *padapter, u8 mode) -{ - int ret = 0; - struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; - - if (mode < PS_MODE_NUM) { - if (pwrctrlpriv->power_mgnt != mode) { - if (PS_MODE_ACTIVE == mode) - LeaveAllPowerSaveMode23a(padapter); - else - pwrctrlpriv->LpsIdleCount = 2; - pwrctrlpriv->power_mgnt = mode; - pwrctrlpriv->bLeisurePs = - (PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt) ? - true:false; - } - } else - ret = -EINVAL; - - return ret; -} - -int rtw_pm_set_ips23a(struct rtw_adapter *padapter, u8 mode) -{ - struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; - - if (mode != IPS_NORMAL && mode != IPS_LEVEL_2 && mode != IPS_NONE) - return -EINVAL; - - pwrctrlpriv->ips_mode_req = mode; - if (mode == IPS_NONE) { - DBG_8723A("%s %s\n", __func__, "IPS_NONE"); - if (padapter->bSurpriseRemoved == 0 && - rtw_pwr_wakeup(padapter) == _FAIL) - return -EFAULT; - } - - return 0; -} diff --git a/drivers/staging/rtl8723au/core/rtw_recv.c b/drivers/staging/rtl8723au/core/rtw_recv.c deleted file mode 100644 index 150dabc..0000000 --- a/drivers/staging/rtl8723au/core/rtw_recv.c +++ /dev/null @@ -1,2204 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RTW_RECV_C_ -#include <osdep_service.h> -#include <drv_types.h> -#include <recv_osdep.h> -#include <mlme_osdep.h> -#include <linux/ip.h> -#include <linux/if_ether.h> -#include <usb_ops.h> -#include <linux/ieee80211.h> -#include <wifi.h> -#include <rtl8723a_recv.h> -#include <rtl8723a_xmit.h> - -void rtw_signal_stat_timer_hdl23a(unsigned long data); - -void _rtw_init_sta_recv_priv23a(struct sta_recv_priv *psta_recvpriv) -{ - - - - spin_lock_init(&psta_recvpriv->lock); - - /* for (i = 0; i<MAX_RX_NUMBLKS; i++) */ - /* _rtw_init_queue23a(&psta_recvpriv->blk_strms[i]); */ - - _rtw_init_queue23a(&psta_recvpriv->defrag_q); - - -} - -int _rtw_init_recv_priv23a(struct recv_priv *precvpriv, - struct rtw_adapter *padapter) -{ - struct recv_frame *precvframe; - int i; - int res = _SUCCESS; - - spin_lock_init(&precvpriv->lock); - - _rtw_init_queue23a(&precvpriv->free_recv_queue); - _rtw_init_queue23a(&precvpriv->recv_pending_queue); - _rtw_init_queue23a(&precvpriv->uc_swdec_pending_queue); - - precvpriv->adapter = padapter; - - for (i = 0; i < NR_RECVFRAME ; i++) { - precvframe = kzalloc(sizeof(struct recv_frame), GFP_KERNEL); - if (!precvframe) - break; - INIT_LIST_HEAD(&precvframe->list); - - list_add_tail(&precvframe->list, - &precvpriv->free_recv_queue.queue); - - precvframe->adapter = padapter; - precvframe++; - } - - precvpriv->free_recvframe_cnt = i; - precvpriv->rx_pending_cnt = 1; - - res = rtl8723au_init_recv_priv(padapter); - - setup_timer(&precvpriv->signal_stat_timer, rtw_signal_stat_timer_hdl23a, - (unsigned long)padapter); - - precvpriv->signal_stat_sampling_interval = 1000; /* ms */ - - rtw_set_signal_stat_timer(precvpriv); - - return res; -} - -void _rtw_free_recv_priv23a(struct recv_priv *precvpriv) -{ - struct rtw_adapter *padapter = precvpriv->adapter; - struct recv_frame *precvframe, *ptmp; - - rtw_free_uc_swdec_pending_queue23a(padapter); - - list_for_each_entry_safe(precvframe, ptmp, - &precvpriv->free_recv_queue.queue, list) { - list_del_init(&precvframe->list); - kfree(precvframe); - } - - rtl8723au_free_recv_priv(padapter); -} - -struct recv_frame *rtw_alloc_recvframe23a(struct rtw_queue *pfree_recv_queue) -{ - struct recv_frame *pframe; - struct rtw_adapter *padapter; - struct recv_priv *precvpriv; - - spin_lock_bh(&pfree_recv_queue->lock); - - pframe = list_first_entry_or_null(&pfree_recv_queue->queue, - struct recv_frame, list); - if (pframe) { - list_del_init(&pframe->list); - padapter = pframe->adapter; - if (padapter) { - precvpriv = &padapter->recvpriv; - if (pfree_recv_queue == &precvpriv->free_recv_queue) - precvpriv->free_recvframe_cnt--; - } - } - - spin_unlock_bh(&pfree_recv_queue->lock); - - return pframe; -} - -int rtw_free_recvframe23a(struct recv_frame *precvframe) -{ - struct rtw_adapter *padapter = precvframe->adapter; - struct recv_priv *precvpriv = &padapter->recvpriv; - struct rtw_queue *pfree_recv_queue; - - if (precvframe->pkt) { - dev_kfree_skb_any(precvframe->pkt);/* free skb by driver */ - precvframe->pkt = NULL; - } - - pfree_recv_queue = &precvpriv->free_recv_queue; - spin_lock_bh(&pfree_recv_queue->lock); - - list_del_init(&precvframe->list); - - list_add_tail(&precvframe->list, get_list_head(pfree_recv_queue)); - - if (padapter) { - if (pfree_recv_queue == &precvpriv->free_recv_queue) - precvpriv->free_recvframe_cnt++; - } - - spin_unlock_bh(&pfree_recv_queue->lock); - - - - return _SUCCESS; -} - -int rtw_enqueue_recvframe23a(struct recv_frame *precvframe, struct rtw_queue *queue) -{ - struct rtw_adapter *padapter = precvframe->adapter; - struct recv_priv *precvpriv = &padapter->recvpriv; - - spin_lock_bh(&queue->lock); - - list_del_init(&precvframe->list); - - list_add_tail(&precvframe->list, get_list_head(queue)); - - if (padapter) { - if (queue == &precvpriv->free_recv_queue) - precvpriv->free_recvframe_cnt++; - } - - spin_unlock_bh(&queue->lock); - - return _SUCCESS; -} - -/* -caller : defrag ; recvframe_chk_defrag23a in recv_thread (passive) -pframequeue: defrag_queue : will be accessed in recv_thread (passive) - -using spinlock to protect - -*/ - -static void rtw_free_recvframe23a_queue(struct rtw_queue *pframequeue) -{ - struct recv_frame *hdr, *ptmp; - struct list_head *phead; - - spin_lock(&pframequeue->lock); - phead = get_list_head(pframequeue); - list_for_each_entry_safe(hdr, ptmp, phead, list) - rtw_free_recvframe23a(hdr); - spin_unlock(&pframequeue->lock); -} - -u32 rtw_free_uc_swdec_pending_queue23a(struct rtw_adapter *adapter) -{ - u32 cnt = 0; - struct recv_frame *pending_frame; - - while ((pending_frame = rtw_alloc_recvframe23a(&adapter->recvpriv.uc_swdec_pending_queue))) { - rtw_free_recvframe23a(pending_frame); - DBG_8723A("%s: dequeue uc_swdec_pending_queue\n", __func__); - cnt++; - } - - return cnt; -} - -struct recv_buf *rtw_dequeue_recvbuf23a (struct rtw_queue *queue) -{ - unsigned long irqL; - struct recv_buf *precvbuf; - - spin_lock_irqsave(&queue->lock, irqL); - - precvbuf = list_first_entry_or_null(&queue->queue, - struct recv_buf, list); - if (precvbuf) - list_del_init(&precvbuf->list); - - spin_unlock_irqrestore(&queue->lock, irqL); - - return precvbuf; -} - -int recvframe_chkmic(struct rtw_adapter *adapter, - struct recv_frame *precvframe); -int recvframe_chkmic(struct rtw_adapter *adapter, - struct recv_frame *precvframe) { - - int i, res = _SUCCESS; - u32 datalen; - u8 miccode[8]; - u8 bmic_err = false, brpt_micerror = true; - u8 *pframe, *payload, *pframemic; - u8 *mickey; - struct sta_info *stainfo; - struct rx_pkt_attrib *prxattrib = &precvframe->attrib; - struct security_priv *psecuritypriv = &adapter->securitypriv; - - struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - - stainfo = rtw_get_stainfo23a(&adapter->stapriv, &prxattrib->ta[0]); - - if (prxattrib->encrypt == WLAN_CIPHER_SUITE_TKIP) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "recvframe_chkmic:prxattrib->encrypt == WLAN_CIPHER_SUITE_TKIP\n"); - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "recvframe_chkmic:da = %pM\n", prxattrib->ra); - - /* calculate mic code */ - if (stainfo != NULL) { - if (is_multicast_ether_addr(prxattrib->ra)) { - mickey = &psecuritypriv->dot118021XGrprxmickey[prxattrib->key_index].skey[0]; - - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "recvframe_chkmic: bcmc key\n"); - - if (!psecuritypriv->binstallGrpkey) { - res = _FAIL; - RT_TRACE(_module_rtl871x_recv_c_, - _drv_err_, - "recvframe_chkmic:didn't install group key!\n"); - DBG_8723A("\n recvframe_chkmic:didn't " - "install group key!!!!!!\n"); - goto exit; - } - } else { - mickey = &stainfo->dot11tkiprxmickey.skey[0]; - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "recvframe_chkmic: unicast key\n"); - } - - /* icv_len included the mic code */ - datalen = precvframe->pkt->len-prxattrib-> - hdrlen-prxattrib->iv_len-prxattrib->icv_len - 8; - pframe = precvframe->pkt->data; - payload = pframe + prxattrib->hdrlen + - prxattrib->iv_len; - - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "prxattrib->iv_len =%d prxattrib->icv_len =%d\n", - prxattrib->iv_len, prxattrib->icv_len); - - /* care the length of the data */ - rtw_seccalctkipmic23a(mickey, pframe, payload, - datalen, &miccode[0], - (unsigned char)prxattrib->priority); - - pframemic = payload + datalen; - - bmic_err = false; - - for (i = 0; i < 8; i++) { - if (miccode[i] != *(pframemic + i)) { - RT_TRACE(_module_rtl871x_recv_c_, - _drv_err_, - "recvframe_chkmic:miccode[%d](%02x) != *(pframemic+%d)(%02x)\n", - i, miccode[i], - i, *(pframemic + i)); - bmic_err = true; - } - } - - if (bmic_err == true) { - int i; - - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "*(pframemic-8)-*(pframemic-1) =%*phC\n", - 8, pframemic - 8); - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "*(pframemic-16)-*(pframemic-9) =%*phC\n", - 8, pframemic - 16); - - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "====== demp packet (len =%d) ======\n", - precvframe->pkt->len); - for (i = 0; i < precvframe->pkt->len; i = i + 8) { - RT_TRACE(_module_rtl871x_recv_c_, - _drv_err_, "%*phC\n", - 8, precvframe->pkt->data + i); - } - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "====== demp packet end [len =%d]======\n", - precvframe->pkt->len); - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "hrdlen =%d\n", prxattrib->hdrlen); - - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "ra = %pM psecuritypriv->binstallGrpkey =%d\n", - prxattrib->ra, - 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 == true) && - (brpt_micerror == true)) { - rtw_handle_tkip_mic_err23a(adapter, (u8)is_multicast_ether_addr(prxattrib->ra)); - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "mic error :prxattrib->bdecrypted =%d\n", - prxattrib->bdecrypted); - DBG_8723A(" mic error :prxattrib->" - "bdecrypted =%d\n", - prxattrib->bdecrypted); - } else { - RT_TRACE(_module_rtl871x_recv_c_, - _drv_err_, - "mic error :prxattrib->bdecrypted =%d\n", - prxattrib->bdecrypted); - DBG_8723A(" mic error :prxattrib->" - "bdecrypted =%d\n", - prxattrib->bdecrypted); - } - - res = _FAIL; - } else { - /* mic checked ok */ - if (!psecuritypriv->bcheck_grpkey && - is_multicast_ether_addr(prxattrib->ra)) { - psecuritypriv->bcheck_grpkey = 1; - RT_TRACE(_module_rtl871x_recv_c_, - _drv_err_, - "psecuritypriv->bcheck_grpkey = true\n"); - } - } - } else { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "recvframe_chkmic: rtw_get_stainfo23a ==NULL!!!\n"); - } - - skb_trim(precvframe->pkt, precvframe->pkt->len - 8); - } - -exit: - - - - return res; -} - -/* decrypt and set the ivlen, icvlen of the recv_frame */ -struct recv_frame *decryptor(struct rtw_adapter *padapter, - struct recv_frame *precv_frame); -struct recv_frame *decryptor(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ - struct rx_pkt_attrib *prxattrib = &precv_frame->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct recv_frame *return_packet = precv_frame; - int 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_8723A("prxattrib->key_index(%d) > WEP_KEYS\n", - prxattrib->key_index); - - switch (prxattrib->encrypt) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - prxattrib->key_index = - psecuritypriv->dot11PrivacyKeyIndex; - break; - case WLAN_CIPHER_SUITE_TKIP: - case WLAN_CIPHER_SUITE_CCMP: - default: - prxattrib->key_index = - psecuritypriv->dot118021XGrpKeyid; - break; - } - } - } - - if ((prxattrib->encrypt > 0) && ((prxattrib->bdecrypted == 0))) { - psecuritypriv->hw_decrypted = 0; - switch (prxattrib->encrypt) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - rtw_wep_decrypt23a(padapter, precv_frame); - break; - case WLAN_CIPHER_SUITE_TKIP: - res = rtw_tkip_decrypt23a(padapter, precv_frame); - break; - case WLAN_CIPHER_SUITE_CCMP: - res = rtw_aes_decrypt23a(padapter, precv_frame); - break; - default: - break; - } - } else if (prxattrib->bdecrypted == 1 && prxattrib->encrypt > 0 && - (psecuritypriv->busetkipkey == 1 || - prxattrib->encrypt != WLAN_CIPHER_SUITE_TKIP)) { - psecuritypriv->hw_decrypted = 1; - } - - if (res == _FAIL) { - rtw_free_recvframe23a(return_packet); - return_packet = NULL; - } - - - - return return_packet; -} - -/* set the security information in the recv_frame */ -static struct recv_frame *portctrl(struct rtw_adapter *adapter, - struct recv_frame *precv_frame) -{ - u8 *psta_addr, *ptr; - uint auth_alg; - struct recv_frame *pfhdr; - struct sta_info *psta; - struct sta_priv *pstapriv ; - struct recv_frame *prtnframe; - u16 ether_type; - u16 eapol_type = ETH_P_PAE;/* for Funia BD's WPA issue */ - struct rx_pkt_attrib *pattrib; - - pstapriv = &adapter->stapriv; - - auth_alg = adapter->securitypriv.dot11AuthAlgrthm; - - pfhdr = precv_frame; - pattrib = &pfhdr->attrib; - psta_addr = pattrib->ta; - psta = rtw_get_stainfo23a(pstapriv, psta_addr); - - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "########portctrl:adapter->securitypriv.dot11AuthAlgrthm =%d\n", - adapter->securitypriv.dot11AuthAlgrthm); - - prtnframe = precv_frame; - - if (auth_alg == dot11AuthAlgrthm_8021X) { - /* get ether_type */ - ptr = pfhdr->pkt->data + pfhdr->attrib.hdrlen; - - ether_type = (ptr[6] << 8) | ptr[7]; - - if (psta && psta->ieee8021x_blocked) { - /* blocked */ - /* only accept EAPOL frame */ - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "########portctrl:psta->ieee8021x_blocked ==1\n"); - - if (ether_type != eapol_type) { - /* free this frame */ - rtw_free_recvframe23a(precv_frame); - prtnframe = NULL; - } - } - } - - return prtnframe; -} - -int recv_decache(struct recv_frame *precv_frame, u8 bretry, - struct stainfo_rxcache *prxcache); -int recv_decache(struct recv_frame *precv_frame, u8 bretry, - struct stainfo_rxcache *prxcache) -{ - int tid = precv_frame->attrib.priority; - - 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_, - "recv_decache, (tid>15)! seq_ctrl = 0x%x, tid = 0x%x\n", - seq_ctrl, tid); - - return _FAIL; - } - - if (1) { /* if (bretry) */ - if (seq_ctrl == prxcache->tid_rxseq[tid]) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, - "recv_decache, seq_ctrl = 0x%x, tid = 0x%x, tid_rxseq = 0x%x\n", - seq_ctrl, tid, prxcache->tid_rxseq[tid]); - - return _FAIL; - } - } - - prxcache->tid_rxseq[tid] = seq_ctrl; - - - - return _SUCCESS; -} - -void process23a_pwrbit_data(struct rtw_adapter *padapter, - struct recv_frame *precv_frame); -void process23a_pwrbit_data(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ -#ifdef CONFIG_8723AU_AP_MODE - unsigned char pwrbit; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct rx_pkt_attrib *pattrib = &precv_frame->attrib; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *psta; - - psta = rtw_get_stainfo23a(pstapriv, pattrib->src); - - if (psta) { - pwrbit = ieee80211_has_pm(hdr->frame_control); - - if (pwrbit) { - if (!(psta->state & WIFI_SLEEP_STATE)) - stop_sta_xmit23a(padapter, psta); - } else { - if (psta->state & WIFI_SLEEP_STATE) - wakeup_sta_to_xmit23a(padapter, psta); - } - } - -#endif -} - -void process_wmmps_data(struct rtw_adapter *padapter, - struct recv_frame *precv_frame); -void process_wmmps_data(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ -#ifdef CONFIG_8723AU_AP_MODE - struct rx_pkt_attrib *pattrib = &precv_frame->attrib; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *psta; - - psta = rtw_get_stainfo23a(pstapriv, pattrib->src); - - if (!psta) - return; - - - if (!psta->qos_option) - return; - - if (!(psta->qos_info & 0xf)) - return; - - if (psta->state & WIFI_SLEEP_STATE) { - u8 wmmps_ac = 0; - - switch (pattrib->priority) { - case 1: - case 2: - wmmps_ac = psta->uapsd_bk & BIT(1); - break; - case 4: - case 5: - wmmps_ac = psta->uapsd_vi & BIT(1); - break; - case 6: - case 7: - wmmps_ac = psta->uapsd_vo & BIT(1); - break; - case 0: - case 3: - default: - wmmps_ac = psta->uapsd_be & BIT(1); - break; - } - - if (wmmps_ac) { - if (psta->sleepq_ac_len > 0) { - /* process received triggered frame */ - xmit_delivery_enabled_frames23a(padapter, psta); - } else { - /* issue one qos null frame with More data bit = 0 and the EOSP bit set (= 1) */ - issue_qos_nulldata23a(padapter, psta->hwaddr, - (u16)pattrib->priority, - 0, 0); - } - } - } - -#endif -} - -static void count_rx_stats(struct rtw_adapter *padapter, - struct recv_frame *prframe, struct sta_info *sta) -{ - int sz; - struct sta_info *psta = NULL; - struct stainfo_stats *pstats = NULL; - struct rx_pkt_attrib *pattrib = & prframe->attrib; - struct recv_priv *precvpriv = &padapter->recvpriv; - - sz = prframe->pkt->len; - precvpriv->rx_bytes += sz; - - padapter->mlmepriv.LinkDetectInfo.NumRxOkInPeriod++; - - if ((!is_broadcast_ether_addr(pattrib->dst)) && - (!is_multicast_ether_addr(pattrib->dst))) - padapter->mlmepriv.LinkDetectInfo.NumRxUnicastOkInPeriod++; - - if (sta) - psta = sta; - else - psta = prframe->psta; - - if (psta) { - pstats = &psta->sta_stats; - - pstats->rx_data_pkts++; - pstats->rx_bytes += sz; - } -} - -static int sta2sta_data_frame(struct rtw_adapter *adapter, - struct recv_frame *precv_frame, - struct sta_info**psta) -{ - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - int ret = _SUCCESS; - struct rx_pkt_attrib *pattrib = & precv_frame->attrib; - struct sta_priv *pstapriv = &adapter->stapriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - u8 *mybssid = get_bssid(pmlmepriv); - u8 *myhwaddr = myid(&adapter->eeprompriv); - u8 *sta_addr = NULL; - int bmcast = is_multicast_ether_addr(pattrib->dst); - - - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { - - /* filter packets that SA is myself or multicast or broadcast */ - if (ether_addr_equal(myhwaddr, pattrib->src)) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "SA == myself\n"); - ret = _FAIL; - goto exit; - } - - if (!ether_addr_equal(myhwaddr, pattrib->dst) && !bmcast) { - ret = _FAIL; - goto exit; - } - - if (ether_addr_equal(pattrib->bssid, "\x0\x0\x0\x0\x0\x0") || - ether_addr_equal(mybssid, "\x0\x0\x0\x0\x0\x0") || - !ether_addr_equal(pattrib->bssid, mybssid)) { - ret = _FAIL; - goto exit; - } - - sta_addr = pattrib->src; - } 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 (!ether_addr_equal(pattrib->bssid, pattrib->src)) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "bssid != TA under STATION_MODE; drop pkt\n"); - ret = _FAIL; - goto exit; - } - - sta_addr = pattrib->bssid; - - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - if (bmcast) { - /* For AP mode, if DA == MCAST, then BSSID should be also MCAST */ - if (!is_multicast_ether_addr(pattrib->bssid)) { - ret = _FAIL; - goto exit; - } - } else { /* not mc-frame */ - /* For AP mode, if DA is non-MCAST, then it must - be BSSID, and bssid == BSSID */ - if (!ether_addr_equal(pattrib->bssid, pattrib->dst)) { - ret = _FAIL; - goto exit; - } - - sta_addr = pattrib->src; - } - } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) { - ether_addr_copy(pattrib->dst, hdr->addr1); - ether_addr_copy(pattrib->src, hdr->addr2); - ether_addr_copy(pattrib->bssid, hdr->addr3); - ether_addr_copy(pattrib->ra, pattrib->dst); - ether_addr_copy(pattrib->ta, pattrib->src); - - sta_addr = mybssid; - } else { - ret = _FAIL; - } - - if (bmcast) - *psta = rtw_get_bcmc_stainfo23a(adapter); - else - *psta = rtw_get_stainfo23a(pstapriv, sta_addr); /* get ap_info */ - - if (*psta == NULL) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "can't get psta under sta2sta_data_frame ; drop pkt\n"); - ret = _FAIL; - goto exit; - } - -exit: - - return ret; -} - -int ap2sta_data_frame(struct rtw_adapter *adapter, - struct recv_frame *precv_frame, - struct sta_info **psta); -int ap2sta_data_frame(struct rtw_adapter *adapter, - struct recv_frame *precv_frame, - struct sta_info **psta) -{ - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct rx_pkt_attrib *pattrib = & precv_frame->attrib; - int ret = _SUCCESS; - struct sta_priv *pstapriv = &adapter->stapriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - u8 *mybssid = get_bssid(pmlmepriv); - u8 *myhwaddr = myid(&adapter->eeprompriv); - int bmcast = is_multicast_ether_addr(pattrib->dst); - - - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) && - (check_fwstate(pmlmepriv, _FW_LINKED) || - check_fwstate(pmlmepriv, _FW_UNDER_LINKING))) { - - /* filter packets that SA is myself or multicast or broadcast */ - if (ether_addr_equal(myhwaddr, pattrib->src)) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "SA == myself\n"); - ret = _FAIL; - goto exit; - } - - /* da should be for me */ - if (!ether_addr_equal(myhwaddr, pattrib->dst) && !bmcast) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "ap2sta_data_frame: compare DA failed; DA=%pM\n", - pattrib->dst); - ret = _FAIL; - goto exit; - } - - /* check BSSID */ - if (ether_addr_equal(pattrib->bssid, "\x0\x0\x0\x0\x0\x0") || - ether_addr_equal(mybssid, "\x0\x0\x0\x0\x0\x0") || - !ether_addr_equal(pattrib->bssid, mybssid)) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "ap2sta_data_frame: compare BSSID failed; BSSID=%pM\n", - pattrib->bssid); - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "mybssid=%pM\n", mybssid); - - if (!bmcast) { - DBG_8723A("issue_deauth23a to the nonassociated ap=%pM for the reason(7)\n", - pattrib->bssid); - issue_deauth23a(adapter, pattrib->bssid, - WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); - } - - ret = _FAIL; - goto exit; - } - - if (bmcast) - *psta = rtw_get_bcmc_stainfo23a(adapter); - else - /* get ap_info */ - *psta = rtw_get_stainfo23a(pstapriv, pattrib->bssid); - - if (*psta == NULL) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "ap2sta: can't get psta under STATION_MODE; drop pkt\n"); - ret = _FAIL; - goto exit; - } - - if (ieee80211_is_nullfunc(hdr->frame_control)) { - /* No data, will not indicate to upper layer, - temporily count it here */ - count_rx_stats(adapter, precv_frame, *psta); - ret = RTW_RX_HANDLED; - goto exit; - } - - } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE) && - check_fwstate(pmlmepriv, _FW_LINKED)) { - ether_addr_copy(pattrib->dst, hdr->addr1); - ether_addr_copy(pattrib->src, hdr->addr2); - ether_addr_copy(pattrib->bssid, hdr->addr3); - ether_addr_copy(pattrib->ra, pattrib->dst); - ether_addr_copy(pattrib->ta, pattrib->src); - - /* */ - ether_addr_copy(pattrib->bssid, mybssid); - - /* get sta_info */ - *psta = rtw_get_stainfo23a(pstapriv, pattrib->bssid); - if (*psta == NULL) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "can't get psta under MP_MODE ; drop pkt\n"); - ret = _FAIL; - goto exit; - } - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - /* Special case */ - ret = RTW_RX_HANDLED; - goto exit; - } else { - if (ether_addr_equal(myhwaddr, pattrib->dst) && !bmcast) { - *psta = rtw_get_stainfo23a(pstapriv, pattrib->bssid); - if (*psta == NULL) { - DBG_8723A("issue_deauth23a to the ap=%pM for the reason(7)\n", - pattrib->bssid); - - issue_deauth23a(adapter, pattrib->bssid, - WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); - } - } - - ret = _FAIL; - } - -exit: - - - - return ret; -} - -int sta2ap_data_frame(struct rtw_adapter *adapter, - struct recv_frame *precv_frame, - struct sta_info **psta); -int sta2ap_data_frame(struct rtw_adapter *adapter, - struct recv_frame *precv_frame, - struct sta_info **psta) -{ - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct rx_pkt_attrib *pattrib = & precv_frame->attrib; - struct sta_priv *pstapriv = &adapter->stapriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - unsigned char *mybssid = get_bssid(pmlmepriv); - int ret = _SUCCESS; - - - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - /* For AP mode, RA = BSSID, TX = STA(SRC_ADDR), A3 = DST_ADDR */ - if (!ether_addr_equal(pattrib->bssid, mybssid)) { - ret = _FAIL; - goto exit; - } - - *psta = rtw_get_stainfo23a(pstapriv, pattrib->src); - if (*psta == NULL) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "can't get psta under AP_MODE; drop pkt\n"); - DBG_8723A("issue_deauth23a to sta=%pM for the reason(7)\n", - pattrib->src); - - issue_deauth23a(adapter, pattrib->src, - WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); - - ret = RTW_RX_HANDLED; - goto exit; - } - - process23a_pwrbit_data(adapter, precv_frame); - - /* We only get here if it's a data frame, so no need to - * confirm data frame type first */ - if (ieee80211_is_data_qos(hdr->frame_control)) - process_wmmps_data(adapter, precv_frame); - - if (ieee80211_is_nullfunc(hdr->frame_control)) { - /* No data, will not indicate to upper layer, - temporily count it here */ - count_rx_stats(adapter, precv_frame, *psta); - ret = RTW_RX_HANDLED; - goto exit; - } - } else { - u8 *myhwaddr = myid(&adapter->eeprompriv); - - if (!ether_addr_equal(pattrib->ra, myhwaddr)) { - ret = RTW_RX_HANDLED; - goto exit; - } - DBG_8723A("issue_deauth23a to sta=%pM for the reason(7)\n", - pattrib->src); - issue_deauth23a(adapter, pattrib->src, - WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); - ret = RTW_RX_HANDLED; - goto exit; - } - -exit: - - - - return ret; -} - -static int validate_recv_ctrl_frame(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ -#ifdef CONFIG_8723AU_AP_MODE - struct rx_pkt_attrib *pattrib = &precv_frame->attrib; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - - if (!ieee80211_is_ctl(hdr->frame_control)) - return _FAIL; - - /* receive the frames that ra(a1) is my address */ - if (!ether_addr_equal(hdr->addr1, myid(&padapter->eeprompriv))) - return _FAIL; - - /* only handle ps-poll */ - if (ieee80211_is_pspoll(hdr->frame_control)) { - struct ieee80211_pspoll *psp = (struct ieee80211_pspoll *)hdr; - u16 aid; - u8 wmmps_ac = 0; - struct sta_info *psta = NULL; - - aid = le16_to_cpu(psp->aid) & 0x3fff; - psta = rtw_get_stainfo23a(pstapriv, hdr->addr2); - - if (!psta || psta->aid != aid) - return _FAIL; - - /* for rx pkt statistics */ - psta->sta_stats.rx_ctrl_pkts++; - - switch (pattrib->priority) { - case 1: - case 2: - wmmps_ac = psta->uapsd_bk & BIT(0); - break; - case 4: - case 5: - wmmps_ac = psta->uapsd_vi & BIT(0); - break; - case 6: - case 7: - wmmps_ac = psta->uapsd_vo & BIT(0); - break; - case 0: - case 3: - default: - wmmps_ac = psta->uapsd_be & BIT(0); - break; - } - - if (wmmps_ac) - return _FAIL; - - if (psta->state & WIFI_STA_ALIVE_CHK_STATE) { - DBG_8723A("%s alive check-rx ps-poll\n", __func__); - psta->expire_to = pstapriv->expire_to; - psta->state ^= WIFI_STA_ALIVE_CHK_STATE; - } - - if ((psta->state & WIFI_SLEEP_STATE) && - (pstapriv->sta_dz_bitmap & CHKBIT(psta->aid))) { - struct list_head *xmitframe_phead; - struct xmit_frame *pxmitframe; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - spin_lock_bh(&pxmitpriv->lock); - - xmitframe_phead = get_list_head(&psta->sleep_q); - pxmitframe = list_first_entry_or_null(xmitframe_phead, - struct xmit_frame, - list); - if (pxmitframe) { - list_del_init(&pxmitframe->list); - - psta->sleepq_len--; - - if (psta->sleepq_len>0) - pxmitframe->attrib.mdata = 1; - else - pxmitframe->attrib.mdata = 0; - - pxmitframe->attrib.triggered = 1; - - rtl8723au_hal_xmitframe_enqueue(padapter, - pxmitframe); - - if (psta->sleepq_len == 0) { - pstapriv->tim_bitmap &= ~CHKBIT(psta->aid); - update_beacon23a(padapter, WLAN_EID_TIM, - NULL, false); - } - - spin_unlock_bh(&pxmitpriv->lock); - - } else { - spin_unlock_bh(&pxmitpriv->lock); - - if (pstapriv->tim_bitmap & CHKBIT(psta->aid)) { - if (psta->sleepq_len == 0) { - DBG_8723A("no buffered packets " - "to xmit\n"); - - /* issue nulldata with More data bit = 0 to indicate we have no buffered packets */ - issue_nulldata23a(padapter, - psta->hwaddr, - 0, 0, 0); - } else { - DBG_8723A("error!psta->sleepq" - "_len =%d\n", - psta->sleepq_len); - psta->sleepq_len = 0; - } - - pstapriv->tim_bitmap &= ~CHKBIT(psta->aid); - - update_beacon23a(padapter, WLAN_EID_TIM, - NULL, false); - } - } - } - } - -#endif - return _FAIL; -} - -struct recv_frame *recvframe_chk_defrag23a(struct rtw_adapter *padapter, - struct recv_frame *precv_frame); -static int validate_recv_mgnt_frame(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ - struct sta_info *psta; - struct sk_buff *skb; - struct ieee80211_hdr *hdr; - - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "+validate_recv_mgnt_frame\n"); - - precv_frame = recvframe_chk_defrag23a(padapter, precv_frame); - if (precv_frame == NULL) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, - "%s: fragment packet\n", __func__); - return _SUCCESS; - } - - skb = precv_frame->pkt; - hdr = (struct ieee80211_hdr *) skb->data; - - /* for rx pkt statistics */ - psta = rtw_get_stainfo23a(&padapter->stapriv, hdr->addr2); - if (psta) { - psta->sta_stats.rx_mgnt_pkts++; - - if (ieee80211_is_beacon(hdr->frame_control)) - psta->sta_stats.rx_beacon_pkts++; - else if (ieee80211_is_probe_req(hdr->frame_control)) - psta->sta_stats.rx_probereq_pkts++; - else if (ieee80211_is_probe_resp(hdr->frame_control)) { - if (ether_addr_equal(padapter->eeprompriv.mac_addr, - hdr->addr1)) - psta->sta_stats.rx_probersp_pkts++; - else if (is_broadcast_ether_addr(hdr->addr1) || - is_multicast_ether_addr(hdr->addr1)) - psta->sta_stats.rx_probersp_bm_pkts++; - else - psta->sta_stats.rx_probersp_uo_pkts++; - } - } - - mgt_dispatcher23a(padapter, precv_frame); - - return _SUCCESS; -} - -static int validate_recv_data_frame(struct rtw_adapter *adapter, - struct recv_frame *precv_frame) -{ - u8 bretry; - u8 *psa, *pda; - struct sta_info *psta = NULL; - struct rx_pkt_attrib *pattrib = & precv_frame->attrib; - struct security_priv *psecuritypriv = &adapter->securitypriv; - int ret = _SUCCESS; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - - - - bretry = ieee80211_has_retry(hdr->frame_control); - pda = ieee80211_get_DA(hdr); - psa = ieee80211_get_SA(hdr); - - ether_addr_copy(pattrib->dst, pda); - ether_addr_copy(pattrib->src, psa); - - switch (hdr->frame_control & - cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) { - case cpu_to_le16(0): - ether_addr_copy(pattrib->bssid, hdr->addr3); - ether_addr_copy(pattrib->ra, pda); - ether_addr_copy(pattrib->ta, psa); - ret = sta2sta_data_frame(adapter, precv_frame, &psta); - break; - - case cpu_to_le16(IEEE80211_FCTL_FROMDS): - ether_addr_copy(pattrib->bssid, hdr->addr2); - ether_addr_copy(pattrib->ra, pda); - ether_addr_copy(pattrib->ta, hdr->addr2); - ret = ap2sta_data_frame(adapter, precv_frame, &psta); - break; - - case cpu_to_le16(IEEE80211_FCTL_TODS): - ether_addr_copy(pattrib->bssid, hdr->addr1); - ether_addr_copy(pattrib->ra, hdr->addr1); - ether_addr_copy(pattrib->ta, psa); - ret = sta2ap_data_frame(adapter, precv_frame, &psta); - break; - - case cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): - /* - * There is no BSSID in this case, but the driver has been - * using addr1 so far, so keep it for now. - */ - ether_addr_copy(pattrib->bssid, hdr->addr1); - ether_addr_copy(pattrib->ra, hdr->addr1); - ether_addr_copy(pattrib->ta, hdr->addr2); - ret = _FAIL; - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, "case 3\n"); - break; - } - - if ((ret == _FAIL) || (ret == RTW_RX_HANDLED)) - goto exit; - - if (!psta) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "after to_fr_ds_chk; psta == NULL\n"); - ret = _FAIL; - goto exit; - } - - precv_frame->psta = psta; - - pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); - if (ieee80211_has_a4(hdr->frame_control)) - pattrib->hdrlen += ETH_ALEN; - - /* parsing QC field */ - if (pattrib->qos == 1) { - __le16 *qptr = (__le16 *)ieee80211_get_qos_ctl(hdr); - u16 qos_ctrl = le16_to_cpu(*qptr); - - pattrib->priority = qos_ctrl & IEEE80211_QOS_CTL_TID_MASK; - pattrib->ack_policy = (qos_ctrl >> 5) & 3; - pattrib->amsdu = - (qos_ctrl & IEEE80211_QOS_CTL_A_MSDU_PRESENT) >> 7; - pattrib->hdrlen += IEEE80211_QOS_CTL_LEN; - - if (pattrib->priority != 0 && pattrib->priority != 3) { - adapter->recvpriv.bIsAnyNonBEPkts = true; - } - } else { - pattrib->priority = 0; - pattrib->ack_policy = 0; - pattrib->amsdu = 0; - } - - if (pattrib->order) { /* HT-CTRL 11n */ - pattrib->hdrlen += 4; - } - - precv_frame->preorder_ctrl = &psta->recvreorder_ctrl[pattrib->priority]; - - /* 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_, - "validate_recv_data_frame:pattrib->privacy =%x\n", - pattrib->privacy); - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "^^^^^^^^^^^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_, - "pattrib->encrypt =%d\n", pattrib->encrypt); - - switch (pattrib->encrypt) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - pattrib->iv_len = IEEE80211_WEP_IV_LEN; - pattrib->icv_len = IEEE80211_WEP_ICV_LEN; - break; - case WLAN_CIPHER_SUITE_TKIP: - pattrib->iv_len = IEEE80211_TKIP_IV_LEN; - pattrib->icv_len = IEEE80211_TKIP_ICV_LEN; - break; - case WLAN_CIPHER_SUITE_CCMP: - pattrib->iv_len = IEEE80211_CCMP_HDR_LEN; - pattrib->icv_len = IEEE80211_CCMP_MIC_LEN; - break; - default: - pattrib->iv_len = 0; - pattrib->icv_len = 0; - break; - } - } else { - pattrib->encrypt = 0; - pattrib->iv_len = 0; - pattrib->icv_len = 0; - } - -exit: - - - - return ret; -} - -static void dump_rx_pkt(struct sk_buff *skb, u16 type, int level) -{ - int i; - u8 *ptr; - - if ((level == 1) || - ((level == 2) && (type == IEEE80211_FTYPE_MGMT)) || - ((level == 3) && (type == IEEE80211_FTYPE_DATA))) { - - ptr = skb->data; - - DBG_8723A("#############################\n"); - - for (i = 0; i < 64; i = i + 8) - DBG_8723A("%*phC:\n", 8, ptr + i); - DBG_8723A("#############################\n"); - } -} - -static int validate_recv_frame(struct rtw_adapter *adapter, - struct recv_frame *precv_frame) -{ - /* shall check frame subtype, to / from ds, da, bssid */ - - /* then call check if rx seq/frag. duplicated. */ - u8 type; - u8 subtype; - int retval = _SUCCESS; - struct rx_pkt_attrib *pattrib = & precv_frame->attrib; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - u8 ver; - u8 bDumpRxPkt; - u16 seq_ctrl, fctl; - - fctl = le16_to_cpu(hdr->frame_control); - ver = fctl & IEEE80211_FCTL_VERS; - type = fctl & IEEE80211_FCTL_FTYPE; - subtype = fctl & IEEE80211_FCTL_STYPE; - - /* 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; - } - - seq_ctrl = le16_to_cpu(hdr->seq_ctrl); - pattrib->frag_num = seq_ctrl & IEEE80211_SCTL_FRAG; - pattrib->seq_num = seq_ctrl >> 4; - - pattrib->pw_save = ieee80211_has_pm(hdr->frame_control); - pattrib->mfrag = ieee80211_has_morefrags(hdr->frame_control); - pattrib->mdata = ieee80211_has_moredata(hdr->frame_control); - pattrib->privacy = ieee80211_has_protected(hdr->frame_control); - pattrib->order = ieee80211_has_order(hdr->frame_control); - - GetHalDefVar8192CUsb(adapter, HAL_DEF_DBG_DUMP_RXPKT, &bDumpRxPkt); - - if (unlikely(bDumpRxPkt == 1)) - dump_rx_pkt(skb, type, bDumpRxPkt); - - switch (type) { - case IEEE80211_FTYPE_MGMT: - 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 IEEE80211_FTYPE_CTL: - 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 IEEE80211_FTYPE_DATA: - pattrib->qos = (subtype & IEEE80211_STYPE_QOS_DATA) ? 1 : 0; - retval = validate_recv_data_frame(adapter, precv_frame); - if (retval == _FAIL) { - struct recv_priv *precvpriv = &adapter->recvpriv; - - precvpriv->rx_drop++; - } - break; - default: - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "validate_recv_data_frame fail! type = 0x%x\n", type); - retval = _FAIL; - break; - } - -exit: - return retval; -} - -/* remove the wlanhdr and add the eth_hdr */ - -static int wlanhdr_to_ethhdr (struct recv_frame *precvframe) -{ - u16 eth_type, len, hdrlen; - u8 bsnaphdr; - u8 *psnap; - struct rtw_adapter *adapter = precvframe->adapter; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - - struct sk_buff *skb = precvframe->pkt; - u8 *ptr; - struct rx_pkt_attrib *pattrib = &precvframe->attrib; - - - - ptr = skb->data; - hdrlen = pattrib->hdrlen; - psnap = ptr + hdrlen; - eth_type = (psnap[6] << 8) | psnap[7]; - /* convert hdr + possible LLC headers into Ethernet header */ - if ((ether_addr_equal(psnap, rfc1042_header) && - eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) || - ether_addr_equal(psnap, bridge_tunnel_header)) { - /* remove RFC1042 or Bridge-Tunnel encapsulation - and replace EtherType */ - bsnaphdr = true; - hdrlen += SNAP_SIZE; - } else { - /* Leave Ethernet header part of hdr and full payload */ - bsnaphdr = false; - eth_type = (psnap[0] << 8) | psnap[1]; - } - - len = skb->len - hdrlen; - - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "=== pattrib->hdrlen: %x, pattrib->iv_len:%x ===\n", - pattrib->hdrlen, pattrib->iv_len); - - pattrib->eth_type = eth_type; - if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) { - ptr += hdrlen; - *ptr = 0x87; - *(ptr + 1) = 0x12; - - eth_type = 0x8712; - /* append rx status for mp test packets */ - - ptr = skb_pull(skb, (hdrlen - sizeof(struct ethhdr) + 2) - 24); - memcpy(ptr, skb->head, 24); - ptr += 24; - } else { - ptr = skb_pull(skb, (hdrlen - sizeof(struct ethhdr) + - (bsnaphdr ? 2:0))); - } - - ether_addr_copy(ptr, pattrib->dst); - ether_addr_copy(ptr + ETH_ALEN, pattrib->src); - - if (!bsnaphdr) { - put_unaligned_be16(len, ptr + 12); - } - - - return _SUCCESS; -} - -/* perform defrag */ -struct recv_frame *recvframe_defrag(struct rtw_adapter *adapter, - struct rtw_queue *defrag_q); -struct recv_frame *recvframe_defrag(struct rtw_adapter *adapter, - struct rtw_queue *defrag_q) -{ - struct list_head *phead; - u8 wlanhdr_offset; - u8 curfragnum; - struct recv_frame *pnfhdr, *ptmp; - struct recv_frame *prframe, *pnextrframe; - struct rtw_queue *pfree_recv_queue; - struct sk_buff *skb; - - curfragnum = 0; - pfree_recv_queue = &adapter->recvpriv.free_recv_queue; - - phead = get_list_head(defrag_q); - prframe = list_first_entry(phead, struct recv_frame, list); - list_del_init(&prframe->list); - skb = prframe->pkt; - - if (curfragnum != prframe->attrib.frag_num) { - /* the first fragment number must be 0 */ - /* free the whole queue */ - rtw_free_recvframe23a(prframe); - rtw_free_recvframe23a_queue(defrag_q); - - return NULL; - } - - curfragnum++; - - list_for_each_entry_safe(pnfhdr, ptmp, phead, list) { - pnextrframe = (struct recv_frame *)pnfhdr; - /* check the fragment sequence (2nd ~n fragment frame) */ - - if (curfragnum != pnfhdr->attrib.frag_num) { - /* the fragment number must be increasing - (after decache) */ - /* release the defrag_q & prframe */ - rtw_free_recvframe23a(prframe); - rtw_free_recvframe23a_queue(defrag_q); - return NULL; - } - - curfragnum++; - - /* copy the 2nd~n fragment frame's payload to the - first fragment */ - /* get the 2nd~last fragment frame's payload */ - - wlanhdr_offset = pnfhdr->attrib.hdrlen + pnfhdr->attrib.iv_len; - - skb_pull(pnfhdr->pkt, wlanhdr_offset); - - /* append to first fragment frame's tail - (if privacy frame, pull the ICV) */ - - skb_trim(skb, skb->len - prframe->attrib.icv_len); - - memcpy(skb_tail_pointer(skb), pnfhdr->pkt->data, - pnfhdr->pkt->len); - - skb_put(skb, pnfhdr->pkt->len); - - prframe->attrib.icv_len = pnfhdr->attrib.icv_len; - } - - /* free the defrag_q queue and return the prframe */ - rtw_free_recvframe23a_queue(defrag_q); - - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "Performance defrag!!!!!\n"); - - return prframe; -} - -/* check if need to defrag, if needed queue the frame to defrag_q */ -struct recv_frame *recvframe_chk_defrag23a(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ - u8 ismfrag; - u8 fragnum; - u8 *psta_addr; - struct recv_frame *pfhdr; - struct sta_info *psta; - struct sta_priv *pstapriv; - struct list_head *phead; - struct recv_frame *prtnframe = NULL; - struct rtw_queue *pfree_recv_queue, *pdefrag_q; - - - - pstapriv = &padapter->stapriv; - - pfhdr = precv_frame; - - pfree_recv_queue = &padapter->recvpriv.free_recv_queue; - - /* need to define struct of wlan header frame ctrl */ - ismfrag = pfhdr->attrib.mfrag; - fragnum = pfhdr->attrib.frag_num; - - psta_addr = pfhdr->attrib.ta; - psta = rtw_get_stainfo23a(pstapriv, psta_addr); - if (!psta) { - struct ieee80211_hdr *hdr = - (struct ieee80211_hdr *) pfhdr->pkt->data; - if (!ieee80211_is_data(hdr->frame_control)) { - psta = rtw_get_bcmc_stainfo23a(padapter); - pdefrag_q = &psta->sta_recvpriv.defrag_q; - } else - pdefrag_q = NULL; - } else - pdefrag_q = &psta->sta_recvpriv.defrag_q; - - if ((ismfrag == 0) && (fragnum == 0)) { - prtnframe = precv_frame;/* isn't a fragment frame */ - } - - if (ismfrag == 1) { - /* 0~(n-1) fragment frame */ - /* enqueue to defraf_g */ - if (pdefrag_q != NULL) { - if (fragnum == 0) { - /* the first fragment */ - if (!list_empty(&pdefrag_q->queue)) { - /* free current defrag_q */ - rtw_free_recvframe23a_queue(pdefrag_q); - } - } - - /* Then enqueue the 0~(n-1) fragment into the - defrag_q */ - - /* spin_lock(&pdefrag_q->lock); */ - phead = get_list_head(pdefrag_q); - list_add_tail(&pfhdr->list, phead); - /* spin_unlock(&pdefrag_q->lock); */ - - 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_recvframe23a(precv_frame); - prtnframe = NULL; - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "Free because pdefrag_q == NULL: ismfrag = %d, fragnum = %d\n", - ismfrag, fragnum); - } - } - - if ((ismfrag == 0) && (fragnum != 0)) { - /* the last fragment frame */ - /* enqueue the last fragment */ - if (pdefrag_q != NULL) { - /* spin_lock(&pdefrag_q->lock); */ - phead = get_list_head(pdefrag_q); - list_add_tail(&pfhdr->list, phead); - /* spin_unlock(&pdefrag_q->lock); */ - - /* 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_recvframe23a(precv_frame); - prtnframe = NULL; - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "Free because pdefrag_q == NULL: ismfrag = %d, fragnum = %d\n", - ismfrag, fragnum); - } - - } - - if ((prtnframe != NULL) && (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_recvframe23a(prtnframe); - prtnframe = NULL; - } - } - - - - return prtnframe; -} - -int amsdu_to_msdu(struct rtw_adapter *padapter, struct recv_frame *prframe); -int amsdu_to_msdu(struct rtw_adapter *padapter, struct recv_frame *prframe) -{ - struct rx_pkt_attrib *pattrib; - struct sk_buff *skb, *sub_skb; - struct sk_buff_head skb_list; - - pattrib = &prframe->attrib; - - skb = prframe->pkt; - skb_pull(skb, prframe->attrib.hdrlen); - __skb_queue_head_init(&skb_list); - - ieee80211_amsdu_to_8023s(skb, &skb_list, NULL, 0, 0, false); - - while (!skb_queue_empty(&skb_list)) { - sub_skb = __skb_dequeue(&skb_list); - - sub_skb->protocol = eth_type_trans(sub_skb, padapter->pnetdev); - sub_skb->dev = padapter->pnetdev; - - sub_skb->ip_summed = CHECKSUM_NONE; - - netif_rx(sub_skb); - } - - prframe->pkt = NULL; - rtw_free_recvframe23a(prframe); - return _SUCCESS; -} - -int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_num); -int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_num) -{ - u8 wsize = preorder_ctrl->wsize_b; - u16 wend = (preorder_ctrl->indicate_seq + wsize -1) & 0xFFF; - - /* Rx Reorder initialize condition. */ - if (preorder_ctrl->indicate_seq == 0xFFFF) - preorder_ctrl->indicate_seq = seq_num; - - /* Drop out the packet which SeqNum is smaller than WinStart */ - if (SN_LESS(seq_num, preorder_ctrl->indicate_seq)) - return false; - - /* */ - /* Sliding window manipulation. Conditions includes: */ - /* 1. Incoming SeqNum is equal to WinStart =>Window shift 1 */ - /* 2. Incoming SeqNum is larger than the WinEnd => Window shift N */ - /* */ - if (SN_EQUAL(seq_num, preorder_ctrl->indicate_seq)) { - preorder_ctrl->indicate_seq = - (preorder_ctrl->indicate_seq + 1) & 0xFFF; - } else if (SN_LESS(wend, seq_num)) { - /* boundary situation, when seq_num cross 0xFFF */ - if (seq_num >= (wsize - 1)) - preorder_ctrl->indicate_seq = seq_num + 1 -wsize; - else - preorder_ctrl->indicate_seq = 0xFFF - (wsize - (seq_num + 1)) + 1; - } - return true; -} - -static int enqueue_reorder_recvframe23a(struct recv_reorder_ctrl *preorder_ctrl, - struct recv_frame *prframe) -{ - struct rx_pkt_attrib *pattrib = &prframe->attrib; - struct rtw_queue *ppending_recvframe_queue; - struct list_head *phead, *plist, *ptmp; - struct recv_frame *hdr; - struct rx_pkt_attrib *pnextattrib; - - ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; - phead = get_list_head(ppending_recvframe_queue); - - list_for_each_safe(plist, ptmp, phead) { - hdr = container_of(plist, struct recv_frame, list); - pnextattrib = &hdr->attrib; - - if (SN_LESS(pnextattrib->seq_num, pattrib->seq_num)) { - continue; - } else if (SN_EQUAL(pnextattrib->seq_num, pattrib->seq_num)) { - /* Duplicate entry is found!! Do not insert current entry. */ - return false; - } else { - break; - } - - } - - list_del_init(&prframe->list); - - list_add_tail(&prframe->list, plist); - - return true; -} - -int recv_indicatepkts_in_order(struct rtw_adapter *padapter, - struct recv_reorder_ctrl *preorder_ctrl, - int bforced); -int recv_indicatepkts_in_order(struct rtw_adapter *padapter, - struct recv_reorder_ctrl *preorder_ctrl, - int bforced) -{ - struct list_head *phead, *plist; - struct recv_frame *prframe; - struct rx_pkt_attrib *pattrib; - int bPktInBuf = false; - struct recv_priv *precvpriv; - struct rtw_queue *ppending_recvframe_queue; - - precvpriv = &padapter->recvpriv; - ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; - phead = get_list_head(ppending_recvframe_queue); - plist = phead->next; - - /* Handling some condition for forced indicate case. */ - if (bforced) { - if (list_empty(phead)) { - return true; - } - - prframe = container_of(plist, struct recv_frame, list); - pattrib = &prframe->attrib; - preorder_ctrl->indicate_seq = pattrib->seq_num; - } - - /* Prepare indication list and indication. */ - /* Check if there is any packet need indicate. */ - while (!list_empty(phead)) { - - prframe = container_of(plist, struct recv_frame, list); - pattrib = &prframe->attrib; - - if (!SN_LESS(preorder_ctrl->indicate_seq, pattrib->seq_num)) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, - "recv_indicatepkts_in_order: indicate =%d seq =%d amsdu =%d\n", - preorder_ctrl->indicate_seq, - pattrib->seq_num, pattrib->amsdu); - - plist = plist->next; - list_del_init(&prframe->list); - - if (SN_EQUAL(preorder_ctrl->indicate_seq, - pattrib->seq_num)) { - preorder_ctrl->indicate_seq = - (preorder_ctrl->indicate_seq + 1)&0xFFF; - } - - if (!pattrib->amsdu) { - if ((padapter->bDriverStopped == false) && - (padapter->bSurpriseRemoved == false)) { - rtw_recv_indicatepkt23a(padapter, prframe); - } - } else { - if (amsdu_to_msdu(padapter, prframe) != - _SUCCESS) - rtw_free_recvframe23a(prframe); - } - - /* Update local variables. */ - bPktInBuf = false; - - } else { - bPktInBuf = true; - break; - } - - } - - return bPktInBuf; -} - -int recv_indicatepkt_reorder(struct rtw_adapter *padapter, - struct recv_frame *prframe); -int recv_indicatepkt_reorder(struct rtw_adapter *padapter, - struct recv_frame *prframe) -{ - int retval = _SUCCESS; - struct rx_pkt_attrib *pattrib; - struct recv_reorder_ctrl *preorder_ctrl; - struct rtw_queue *ppending_recvframe_queue; - - pattrib = &prframe->attrib; - preorder_ctrl = prframe->preorder_ctrl; - ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; - - if (!pattrib->amsdu) { - /* s1. */ - wlanhdr_to_ethhdr(prframe); - - if ((pattrib->qos!= 1) || (pattrib->eth_type == ETH_P_ARP) || - (pattrib->ack_policy != 0)) { - if ((padapter->bDriverStopped == false) && - (padapter->bSurpriseRemoved == false)) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, - "@@@@ recv_indicatepkt_reorder -recv_func recv_indicatepkt\n"); - - rtw_recv_indicatepkt23a(padapter, prframe); - return _SUCCESS; - } - - return _FAIL; - } - - if (preorder_ctrl->enable == false) { - /* indicate this recv_frame */ - preorder_ctrl->indicate_seq = pattrib->seq_num; - rtw_recv_indicatepkt23a(padapter, prframe); - - preorder_ctrl->indicate_seq = - (preorder_ctrl->indicate_seq + 1) % 4096; - return _SUCCESS; - } - } else { - /* temp filter -> means didn't support A-MSDUs in a A-MPDU */ - if (preorder_ctrl->enable == false) { - preorder_ctrl->indicate_seq = pattrib->seq_num; - retval = amsdu_to_msdu(padapter, prframe); - - preorder_ctrl->indicate_seq = - (preorder_ctrl->indicate_seq + 1) % 4096; - return retval; - } - } - - spin_lock_bh(&ppending_recvframe_queue->lock); - - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, - "recv_indicatepkt_reorder: indicate =%d seq =%d\n", - 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)) { - goto _err_exit; - } - - /* s3. Insert all packet into Reorder Queue to maintain its ordering. */ - if (!enqueue_reorder_recvframe23a(preorder_ctrl, prframe)) { - goto _err_exit; - } - - /* s4. */ - /* Indication process. */ - /* After Packet dropping and Sliding Window shifting as above, - we can now just indicate the packets */ - /* with the SeqNum smaller than latest WinStart and buffer - other packets. */ - /* */ - /* For Rx Reorder condition: */ - /* 1. All packets with SeqNum smaller than WinStart => Indicate */ - /* 2. All packets with SeqNum larger than or equal to WinStart => - Buffer it. */ - /* */ - - if (recv_indicatepkts_in_order(padapter, preorder_ctrl, false) == true) { - mod_timer(&preorder_ctrl->reordering_ctrl_timer, - jiffies + msecs_to_jiffies(REORDER_WAIT_TIME)); - spin_unlock_bh(&ppending_recvframe_queue->lock); - } else { - spin_unlock_bh(&ppending_recvframe_queue->lock); - del_timer_sync(&preorder_ctrl->reordering_ctrl_timer); - } - return _SUCCESS; - -_err_exit: - - spin_unlock_bh(&ppending_recvframe_queue->lock); - return _FAIL; -} - -void rtw_reordering_ctrl_timeout_handler23a(unsigned long pcontext) -{ - struct recv_reorder_ctrl *preorder_ctrl; - struct rtw_adapter *padapter; - struct rtw_queue *ppending_recvframe_queue; - - preorder_ctrl = (struct recv_reorder_ctrl *)pcontext; - padapter = preorder_ctrl->padapter; - ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; - - if (padapter->bDriverStopped || padapter->bSurpriseRemoved) { - return; - } - - spin_lock_bh(&ppending_recvframe_queue->lock); - - if (recv_indicatepkts_in_order(padapter, preorder_ctrl, true) == true) { - mod_timer(&preorder_ctrl->reordering_ctrl_timer, - jiffies + msecs_to_jiffies(REORDER_WAIT_TIME)); - } - - spin_unlock_bh(&ppending_recvframe_queue->lock); -} - -int process_recv_indicatepkts(struct rtw_adapter *padapter, - struct recv_frame *prframe); -int process_recv_indicatepkts(struct rtw_adapter *padapter, - struct recv_frame *prframe) -{ - int retval = _SUCCESS; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - - if (phtpriv->ht_option == true) { /* B/G/N Mode */ - /* including perform A-MPDU Rx Ordering Buffer Control */ - if (recv_indicatepkt_reorder(padapter, prframe) != _SUCCESS) { - if ((padapter->bDriverStopped == false) && - (padapter->bSurpriseRemoved == false)) { - retval = _FAIL; - return retval; - } - } - } 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"); - return retval; - } - - if ((padapter->bDriverStopped == false) && - (padapter->bSurpriseRemoved == false)) { - /* indicate this recv_frame */ - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, - "@@@@ process_recv_indicatepkts- recv_func recv_indicatepkt\n"); - rtw_recv_indicatepkt23a(padapter, prframe); - } else { - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, - "@@@@ process_recv_indicatepkts- recv_func free_indicatepkt\n"); - - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, - "recv_func:bDriverStopped(%d) OR bSurpriseRemoved(%d)\n", - padapter->bDriverStopped, - padapter->bSurpriseRemoved); - retval = _FAIL; - return retval; - } - - } - - return retval; -} - -static int recv_func_prehandle(struct rtw_adapter *padapter, - struct recv_frame *rframe) -{ - int ret; - - /* 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_recvframe23a(rframe); - goto exit; - } - -exit: - return ret; -} - -static int recv_func_posthandle(struct rtw_adapter *padapter, - struct recv_frame *prframe) -{ - int ret = _SUCCESS; - struct recv_frame *orig_prframe = prframe; - struct recv_priv *precvpriv = &padapter->recvpriv; - - /* DATA FRAME */ - prframe = decryptor(padapter, prframe); - if (prframe == NULL) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "decryptor: drop pkt\n"); - ret = _FAIL; - goto _recv_data_drop; - } - - prframe = recvframe_chk_defrag23a(padapter, prframe); - if (!prframe) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "recvframe_chk_defrag23a: drop pkt\n"); - goto _recv_data_drop; - } - - /* - * Pull off crypto headers - */ - if (prframe->attrib.iv_len > 0) { - skb_pull(prframe->pkt, prframe->attrib.iv_len); - } - - if (prframe->attrib.icv_len > 0) { - skb_trim(prframe->pkt, - prframe->pkt->len - prframe->attrib.icv_len); - } - - prframe = portctrl(padapter, prframe); - if (!prframe) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "portctrl: drop pkt\n"); - ret = _FAIL; - goto _recv_data_drop; - } - - count_rx_stats(padapter, prframe, NULL); - - 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_recvframe23a(orig_prframe);/* free this recv_frame */ - goto _recv_data_drop; - } - return ret; - -_recv_data_drop: - precvpriv->rx_drop++; - return ret; -} - -int rtw_recv_entry23a(struct recv_frame *rframe) -{ - int ret, r; - struct rtw_adapter *padapter = rframe->adapter; - struct rx_pkt_attrib *prxattrib = &rframe->attrib; - struct recv_priv *recvpriv = &padapter->recvpriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_priv *mlmepriv = &padapter->mlmepriv; - - /* check if need to handle uc_swdec_pending_queue*/ - if (check_fwstate(mlmepriv, WIFI_STATION_STATE) && - psecuritypriv->busetkipkey) { - struct recv_frame *pending_frame; - - while ((pending_frame = rtw_alloc_recvframe23a(&padapter->recvpriv.uc_swdec_pending_queue))) { - r = recv_func_posthandle(padapter, pending_frame); - if (r == _SUCCESS) - DBG_8723A("%s: dequeue uc_swdec_pending_queue\n", __func__); - } - } - - ret = recv_func_prehandle(padapter, rframe); - - if (ret == _SUCCESS) { - /* check if need to enqueue into uc_swdec_pending_queue*/ - if (check_fwstate(mlmepriv, WIFI_STATION_STATE) && - !is_multicast_ether_addr(prxattrib->ra) && - prxattrib->encrypt > 0 && - (prxattrib->bdecrypted == 0) && - !is_wep_enc(psecuritypriv->dot11PrivacyAlgrthm) && - !psecuritypriv->busetkipkey) { - rtw_enqueue_recvframe23a(rframe, &padapter->recvpriv.uc_swdec_pending_queue); - DBG_8723A("%s: no key, enqueue uc_swdec_pending_queue\n", __func__); - goto exit; - } - - ret = recv_func_posthandle(padapter, rframe); - - recvpriv->rx_pkts++; - } - -exit: - return ret; -} - -void rtw_signal_stat_timer_hdl23a(unsigned long data) -{ - struct rtw_adapter *adapter = (struct rtw_adapter *)data; - struct recv_priv *recvpriv = &adapter->recvpriv; - - u32 tmp_s, tmp_q; - u8 avg_signal_strength = 0; - u8 avg_signal_qual = 0; - u32 num_signal_strength = 0; - u32 num_signal_qual = 0; - u8 _alpha = 3; /* this value is based on converging_constant = 5000 */ - /* and sampling_interval = 1000 */ - - if (recvpriv->signal_strength_data.update_req == 0) { - /* update_req is clear, means we got rx */ - avg_signal_strength = recvpriv->signal_strength_data.avg_val; - num_signal_strength = recvpriv->signal_strength_data.total_num; - /* after avg_vals are acquired, we can re-stat */ - /* the signal values */ - recvpriv->signal_strength_data.update_req = 1; - } - - if (recvpriv->signal_qual_data.update_req == 0) { - /* update_req is clear, means we got rx */ - avg_signal_qual = recvpriv->signal_qual_data.avg_val; - num_signal_qual = recvpriv->signal_qual_data.total_num; - /* after avg_vals are acquired, we can re-stat */ - /*the signal values */ - recvpriv->signal_qual_data.update_req = 1; - } - - /* update value of signal_strength, rssi, signal_qual */ - if (!check_fwstate(&adapter->mlmepriv, _FW_UNDER_SURVEY)) { - tmp_s = avg_signal_strength + (_alpha - 1) * - recvpriv->signal_strength; - if (tmp_s %_alpha) - tmp_s = tmp_s / _alpha + 1; - else - tmp_s = tmp_s / _alpha; - if (tmp_s > 100) - tmp_s = 100; - - tmp_q = avg_signal_qual + (_alpha - 1) * recvpriv->signal_qual; - if (tmp_q %_alpha) - tmp_q = tmp_q / _alpha + 1; - else - tmp_q = tmp_q / _alpha; - if (tmp_q > 100) - tmp_q = 100; - - recvpriv->signal_strength = tmp_s; - recvpriv->signal_qual = tmp_q; - - DBG_8723A("%s signal_strength:%3u, signal_qual:%3u, " - "num_signal_strength:%u, num_signal_qual:%u\n", - __func__, recvpriv->signal_strength, - recvpriv->signal_qual, num_signal_strength, - num_signal_qual); - } - - rtw_set_signal_stat_timer(recvpriv); -} diff --git a/drivers/staging/rtl8723au/core/rtw_security.c b/drivers/staging/rtl8723au/core/rtw_security.c deleted file mode 100644 index 5a4cfdf..0000000 --- a/drivers/staging/rtl8723au/core/rtw_security.c +++ /dev/null @@ -1,1630 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RTW_SECURITY_C_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <wifi.h> -#include <osdep_intf.h> - -/* WEP related ===== */ - -#define CRC32_POLY 0x04c11db7 - -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 int bcrc32initialized; -static u32 crc32_table[256]; - -static u8 crc32_reverseBit(u8 data) -{ - u8 retval = ((data << 7) & 0x80) | ((data << 5) & 0x40) | - ((data << 3) & 0x20) | ((data << 1) & 0x10) | - ((data >> 1) & 0x08) | ((data >> 3) & 0x04) | - ((data >> 5) & 0x02) | ((data >> 7) & 0x01); - return retval; -} - -static void crc32_init(void) -{ - int i, j; - u32 c; - u8 *p, *p1; - u8 k; - - if (bcrc32initialized == 1) - return; - - p = (u8 *) &c; - 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 : (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 u32 getcrc32(u8 *buf, 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 ~crc; /* transmit complement, per CRC-32 spec */ -} - -/* Need to consider the fragment situation */ -void rtw_wep_encrypt23a(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - /* exclude ICV */ - __le32 crc; - struct arc4context mycontext; - int curfragnum, length, index; - u32 keylength; - u8 *pframe, *payload, *iv; /* wepkey */ - u8 wepkey[16]; - u8 hw_hdr_offset = 0; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - if (!pxmitframe->buf_addr) - return; - - hw_hdr_offset = TXDESC_OFFSET; - - pframe = pxmitframe->buf_addr + hw_hdr_offset; - - /* start to encrypt each fragment */ - if (pattrib->encrypt != WLAN_CIPHER_SUITE_WEP40 && - pattrib->encrypt != WLAN_CIPHER_SUITE_WEP104) - return; - - index = psecuritypriv->dot11PrivacyKeyIndex; - keylength = psecuritypriv->wep_key[index].keylen; - - for (curfragnum = 0; curfragnum < pattrib->nr_frags ; curfragnum++) { - iv = pframe + pattrib->hdrlen; - memcpy(&wepkey[0], iv, 3); - memcpy(&wepkey[3], &psecuritypriv->wep_key[index].key, - keylength); - payload = pframe + pattrib->iv_len + pattrib->hdrlen; - - if ((curfragnum + 1) == pattrib->nr_frags) { - /* the last fragment */ - length = pattrib->last_txcmdsz - pattrib->hdrlen - - pattrib->iv_len - pattrib->icv_len; - - crc = cpu_to_le32(getcrc32(payload, length)); - - arcfour_init(&mycontext, wepkey, 3 + keylength); - arcfour_encrypt(&mycontext, payload, payload, length); - arcfour_encrypt(&mycontext, payload + length, - (char *)&crc, 4); - } else { - length = pxmitpriv->frag_len - pattrib->hdrlen - - pattrib->iv_len - pattrib->icv_len; - crc = cpu_to_le32(getcrc32(payload, length)); - arcfour_init(&mycontext, wepkey, 3 + keylength); - arcfour_encrypt(&mycontext, payload, payload, length); - arcfour_encrypt(&mycontext, payload + length, - (char *)&crc, 4); - - pframe += pxmitpriv->frag_len; - pframe = PTR_ALIGN(pframe, 4); - } - } - -} - -void rtw_wep_decrypt23a(struct rtw_adapter *padapter, - struct recv_frame *precvframe) -{ - /* exclude ICV */ - u32 actual_crc, expected_crc; - struct arc4context mycontext; - int length; - u32 keylength; - u8 *pframe, *payload, *iv, wepkey[16]; - u8 keyindex; - struct rx_pkt_attrib *prxattrib = &precvframe->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct sk_buff *skb = precvframe->pkt; - - pframe = skb->data; - - /* start to decrypt recvframe */ - if (prxattrib->encrypt != WLAN_CIPHER_SUITE_WEP40 && - prxattrib->encrypt != WLAN_CIPHER_SUITE_WEP104) - return; - - iv = pframe + prxattrib->hdrlen; - /* keyindex = (iv[3]&0x3); */ - keyindex = prxattrib->key_index; - keylength = psecuritypriv->wep_key[keyindex].keylen; - memcpy(&wepkey[0], iv, 3); - /* memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[psecuritypriv->dot11PrivacyKeyIndex].skey[0], keylength); */ - memcpy(&wepkey[3], &psecuritypriv->wep_key[keyindex].key, keylength); - length = skb->len - prxattrib->hdrlen - prxattrib->iv_len; - - payload = pframe + prxattrib->iv_len + prxattrib->hdrlen; - - /* decrypt payload include icv */ - arcfour_init(&mycontext, wepkey, 3 + keylength); - arcfour_encrypt(&mycontext, payload, payload, length); - - /* calculate icv and compare the icv */ - actual_crc = getcrc32(payload, length - 4); - expected_crc = get_unaligned_le32(&payload[length - 4]); - - if (actual_crc != expected_crc) { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s:icv CRC mismatch: " - "actual: %08x, expected: %08x\n", - __func__, actual_crc, expected_crc); - } -} - -/* 3 ===== TKIP related ===== */ - -static u32 secmicgetuint32(u8 *p) -/* Convert from Byte[] to u32 in a portable way */ -{ - s32 i; - u32 res = 0; - - for (i = 0; i < 4; i++) - res |= ((u32)(*p++)) << (8 * i); - - return res; -} - -static void secmicputuint32(u8 *p, u32 val) -/* Convert from long to Byte[] in a portable way */ -{ - long i; - - for (i = 0; i < 4; i++) { - *p++ = (u8) (val & 0xff); - val >>= 8; - } - -} - -static void secmicclear(struct mic_data *pmicdata) -{ -/* Reset the state to the empty message. */ - - pmicdata->L = pmicdata->K0; - pmicdata->R = pmicdata->K1; - pmicdata->nBytesInM = 0; - pmicdata->M = 0; - -} - -void rtw_secmicsetkey23a(struct mic_data *pmicdata, u8 *key) -{ - /* Set the key */ - - pmicdata->K0 = secmicgetuint32(key); - pmicdata->K1 = secmicgetuint32(key + 4); - /* and reset the message */ - secmicclear(pmicdata); - -} - -void rtw_secmicappend23abyte23a(struct mic_data *pmicdata, u8 b) -{ - - /* Append the byte to our word-sized buffer */ - pmicdata->M |= ((unsigned long)b) << (8 * pmicdata->nBytesInM); - pmicdata->nBytesInM++; - /* Process the word if it is full. */ - if (pmicdata->nBytesInM >= 4) { - pmicdata->L ^= pmicdata->M; - pmicdata->R ^= ROL32(pmicdata->L, 17); - pmicdata->L += pmicdata->R; - pmicdata->R ^= ((pmicdata->L & 0xff00ff00) >> 8) | ((pmicdata->L & 0x00ff00ff) << 8); - pmicdata->L += pmicdata->R; - pmicdata->R ^= ROL32(pmicdata->L, 3); - pmicdata->L += pmicdata->R; - pmicdata->R ^= ROR32(pmicdata->L, 2); - pmicdata->L += pmicdata->R; - /* Clear the buffer */ - pmicdata->M = 0; - pmicdata->nBytesInM = 0; - } - -} - -void rtw_secmicappend23a(struct mic_data *pmicdata, u8 *src, u32 nbytes) -{ - - /* This is simple */ - while (nbytes > 0) { - rtw_secmicappend23abyte23a(pmicdata, *src++); - nbytes--; - } - -} - -void rtw_secgetmic23a(struct mic_data *pmicdata, u8 *dst) -{ - - /* Append the minimum padding */ - rtw_secmicappend23abyte23a(pmicdata, 0x5a); - rtw_secmicappend23abyte23a(pmicdata, 0); - rtw_secmicappend23abyte23a(pmicdata, 0); - rtw_secmicappend23abyte23a(pmicdata, 0); - rtw_secmicappend23abyte23a(pmicdata, 0); - /* and then zeroes until the length is a multiple of 4 */ - while (pmicdata->nBytesInM != 0) - rtw_secmicappend23abyte23a(pmicdata, 0); - /* The appendByte function has already computed the result. */ - secmicputuint32(dst, pmicdata->L); - secmicputuint32(dst + 4, pmicdata->R); - /* Reset to the empty message. */ - secmicclear(pmicdata); - -} - -void rtw_seccalctkipmic23a(u8 *key, u8 *header, u8 *data, u32 data_len, - u8 *mic_code, u8 pri) -{ - - struct mic_data micdata; - u8 priority[4] = {0x0, 0x0, 0x0, 0x0}; - - rtw_secmicsetkey23a(&micdata, key); - priority[0] = pri; - - /* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */ - if (header[1]&1) { /* ToDS == 1 */ - rtw_secmicappend23a(&micdata, &header[16], 6); /* DA */ - if (header[1]&2) /* From Ds == 1 */ - rtw_secmicappend23a(&micdata, &header[24], 6); - else - rtw_secmicappend23a(&micdata, &header[10], 6); - } else { /* ToDS == 0 */ - rtw_secmicappend23a(&micdata, &header[4], 6); /* DA */ - if (header[1]&2) /* From Ds == 1 */ - rtw_secmicappend23a(&micdata, &header[16], 6); - else - rtw_secmicappend23a(&micdata, &header[10], 6); - - } - rtw_secmicappend23a(&micdata, &priority[0], 4); - - rtw_secmicappend23a(&micdata, data, data_len); - - rtw_secgetmic23a(&micdata, mic_code); - -} - -/* macros for extraction/creation of unsigned char/unsigned short values */ -#define RotR1(v16) ((((v16) >> 1) & 0x7FFF) ^ (((v16) & 1) << 15)) -#define Lo8(v16) ((u8)((v16) & 0x00FF)) -#define Hi8(v16) ((u8)(((v16) >> 8) & 0x00FF)) -#define Lo16(v32) ((u16)((v32) & 0xFFFF)) -#define Hi16(v32) ((u16)(((v32) >> 16) & 0xFFFF)) -#define Mk16(hi, lo) ((lo) ^ (((u16)(hi)) << 8)) - -/* select the Nth 16-bit word of the temporal key unsigned char array TK[] */ -#define TK16(N) Mk16(tk[2 * (N) + 1], tk[2 * (N)]) - -/* S-box lookup: 16 bits --> 16 bits */ -#define _S_(v16) (Sbox1[0][Lo8(v16)] ^ Sbox1[1][Hi8(v16)]) - -/* fixed algorithm "parameters" */ -#define PHASE1_LOOP_CNT 8 /* this needs to be "big enough" */ -#define TA_SIZE 6 /* 48-bit transmitter address */ -#define TK_SIZE 16 /* 128-bit temporal key */ -#define P1K_SIZE 10 /* 80-bit Phase1 key */ -#define RC4_KEY_SIZE 16 /* 128-bit RC4KEY (104 bits unknown) */ - -/* 2-unsigned char by 2-unsigned char subset of the full AES S-box table */ -static const unsigned short Sbox1[2][256] = { - /* Sbox for hash (can be in ROM) */ - { - 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154, - 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A, - 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B, - 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B, - 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F, - 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F, - 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5, - 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F, - 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB, - 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397, - 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED, - 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A, - 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194, - 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3, - 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104, - 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D, - 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39, - 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695, - 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83, - 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76, - 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4, - 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B, - 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0, - 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018, - 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751, - 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85, - 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12, - 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9, - 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7, - 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A, - 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8, - 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A, - }, - { /* second half of table is unsigned char-reversed version of first! */ - 0xA5C6, 0x84F8, 0x99EE, 0x8DF6, 0x0DFF, 0xBDD6, 0xB1DE, 0x5491, - 0x5060, 0x0302, 0xA9CE, 0x7D56, 0x19E7, 0x62B5, 0xE64D, 0x9AEC, - 0x458F, 0x9D1F, 0x4089, 0x87FA, 0x15EF, 0xEBB2, 0xC98E, 0x0BFB, - 0xEC41, 0x67B3, 0xFD5F, 0xEA45, 0xBF23, 0xF753, 0x96E4, 0x5B9B, - 0xC275, 0x1CE1, 0xAE3D, 0x6A4C, 0x5A6C, 0x417E, 0x02F5, 0x4F83, - 0x5C68, 0xF451, 0x34D1, 0x08F9, 0x93E2, 0x73AB, 0x5362, 0x3F2A, - 0x0C08, 0x5295, 0x6546, 0x5E9D, 0x2830, 0xA137, 0x0F0A, 0xB52F, - 0x090E, 0x3624, 0x9B1B, 0x3DDF, 0x26CD, 0x694E, 0xCD7F, 0x9FEA, - 0x1B12, 0x9E1D, 0x7458, 0x2E34, 0x2D36, 0xB2DC, 0xEEB4, 0xFB5B, - 0xF6A4, 0x4D76, 0x61B7, 0xCE7D, 0x7B52, 0x3EDD, 0x715E, 0x9713, - 0xF5A6, 0x68B9, 0x0000, 0x2CC1, 0x6040, 0x1FE3, 0xC879, 0xEDB6, - 0xBED4, 0x468D, 0xD967, 0x4B72, 0xDE94, 0xD498, 0xE8B0, 0x4A85, - 0x6BBB, 0x2AC5, 0xE54F, 0x16ED, 0xC586, 0xD79A, 0x5566, 0x9411, - 0xCF8A, 0x10E9, 0x0604, 0x81FE, 0xF0A0, 0x4478, 0xBA25, 0xE34B, - 0xF3A2, 0xFE5D, 0xC080, 0x8A05, 0xAD3F, 0xBC21, 0x4870, 0x04F1, - 0xDF63, 0xC177, 0x75AF, 0x6342, 0x3020, 0x1AE5, 0x0EFD, 0x6DBF, - 0x4C81, 0x1418, 0x3526, 0x2FC3, 0xE1BE, 0xA235, 0xCC88, 0x392E, - 0x5793, 0xF255, 0x82FC, 0x477A, 0xACC8, 0xE7BA, 0x2B32, 0x95E6, - 0xA0C0, 0x9819, 0xD19E, 0x7FA3, 0x6644, 0x7E54, 0xAB3B, 0x830B, - 0xCA8C, 0x29C7, 0xD36B, 0x3C28, 0x79A7, 0xE2BC, 0x1D16, 0x76AD, - 0x3BDB, 0x5664, 0x4E74, 0x1E14, 0xDB92, 0x0A0C, 0x6C48, 0xE4B8, - 0x5D9F, 0x6EBD, 0xEF43, 0xA6C4, 0xA839, 0xA431, 0x37D3, 0x8BF2, - 0x32D5, 0x438B, 0x596E, 0xB7DA, 0x8C01, 0x64B1, 0xD29C, 0xE049, - 0xB4D8, 0xFAAC, 0x07F3, 0x25CF, 0xAFCA, 0x8EF4, 0xE947, 0x1810, - 0xD56F, 0x88F0, 0x6F4A, 0x725C, 0x2438, 0xF157, 0xC773, 0x5197, - 0x23CB, 0x7CA1, 0x9CE8, 0x213E, 0xDD96, 0xDC61, 0x860D, 0x850F, - 0x90E0, 0x427C, 0xC471, 0xAACC, 0xD890, 0x0506, 0x01F7, 0x121C, - 0xA3C2, 0x5F6A, 0xF9AE, 0xD069, 0x9117, 0x5899, 0x273A, 0xB927, - 0x38D9, 0x13EB, 0xB32B, 0x3322, 0xBBD2, 0x70A9, 0x8907, 0xA733, - 0xB62D, 0x223C, 0x9215, 0x20C9, 0x4987, 0xFFAA, 0x7850, 0x7AA5, - 0x8F03, 0xF859, 0x8009, 0x171A, 0xDA65, 0x31D7, 0xC684, 0xB8D0, - 0xC382, 0xB029, 0x775A, 0x111E, 0xCB7B, 0xFCA8, 0xD66D, 0x3A2C, - } -}; - - /* -********************************************************************** -* Routine: Phase 1 -- generate P1K, given TA, TK, IV32 -* -* Inputs: -* tk[] = temporal key [128 bits] -* ta[] = transmitter's MAC address [ 48 bits] -* iv32 = upper 32 bits of IV [ 32 bits] -* Output: -* p1k[] = Phase 1 key [ 80 bits] -* -* Note: -* This function only needs to be called every 2**16 packets, -* although in theory it could be called every packet. -* -********************************************************************** -*/ -static void phase1(u16 *p1k, const u8 *tk, const u8 *ta, u32 iv32) -{ - int i; - - /* Initialize the 80 bits of P1K[] from IV32 and TA[0..5] */ - p1k[0] = Lo16(iv32); - p1k[1] = Hi16(iv32); - p1k[2] = Mk16(ta[1], ta[0]); /* use TA[] as little-endian */ - p1k[3] = Mk16(ta[3], ta[2]); - p1k[4] = Mk16(ta[5], ta[4]); - - /* Now compute an unbalanced Feistel cipher with 80-bit block */ - /* size on the 80-bit block P1K[], using the 128-bit key TK[] */ - for (i = 0; i < PHASE1_LOOP_CNT; i++) { - /* Each add operation here is mod 2**16 */ - p1k[0] += _S_(p1k[4] ^ TK16((i & 1) + 0)); - p1k[1] += _S_(p1k[0] ^ TK16((i & 1) + 2)); - p1k[2] += _S_(p1k[1] ^ TK16((i & 1) + 4)); - p1k[3] += _S_(p1k[2] ^ TK16((i & 1) + 6)); - p1k[4] += _S_(p1k[3] ^ TK16((i & 1) + 0)); - p1k[4] += (unsigned short) i; /* avoid "slide attacks" */ - } - -} - -/* -********************************************************************** -* Routine: Phase 2 -- generate RC4KEY, given TK, P1K, IV16 -* -* Inputs: -* tk[] = Temporal key [128 bits] -* p1k[] = Phase 1 output key [ 80 bits] -* iv16 = low 16 bits of IV counter [ 16 bits] -* Output: -* rc4key[] = the key used to encrypt the packet [128 bits] -* -* Note: -* The value {TA, IV32, IV16} for Phase1/Phase2 must be unique -* across all packets using the same key TK value. Then, for a -* given value of TK[], this TKIP48 construction guarantees that -* the final RC4KEY value is unique across all packets. -* -* Suggested implementation optimization: if PPK[] is "overlaid" -* appropriately on RC4KEY[], there is no need for the final -* for loop below that copies the PPK[] result into RC4KEY[]. -* -********************************************************************** -*/ -static void phase2(u8 *rc4key, const u8 *tk, const u16 *p1k, u16 iv16) -{ - int i; - u16 PPK[6]; /* temporary key for mixing */ - - /* Note: all adds in the PPK[] equations below are mod 2**16 */ - for (i = 0; i < 5; i++) - PPK[i] = p1k[i]; /* first, copy P1K to PPK */ - - PPK[5] = p1k[4] + iv16; /* next, add in IV16 */ - - /* Bijective non-linear mixing of the 96 bits of PPK[0..5] */ - PPK[0] += _S_(PPK[5] ^ TK16(0)); /* Mix key in each "round" */ - PPK[1] += _S_(PPK[0] ^ TK16(1)); - PPK[2] += _S_(PPK[1] ^ TK16(2)); - PPK[3] += _S_(PPK[2] ^ TK16(3)); - PPK[4] += _S_(PPK[3] ^ TK16(4)); - PPK[5] += _S_(PPK[4] ^ TK16(5)); /* Total # S-box lookups == 6 */ - - /* Final sweep: bijective, "linear". Rotates kill LSB correlations */ - PPK[0] += RotR1(PPK[5] ^ TK16(6)); - PPK[1] += RotR1(PPK[0] ^ TK16(7)); /* Use all of TK[] in Phase2 */ - PPK[2] += RotR1(PPK[1]); - PPK[3] += RotR1(PPK[2]); - PPK[4] += RotR1(PPK[3]); - PPK[5] += RotR1(PPK[4]); - /* Note: At this point, for a given key TK[0..15], the 96-bit output */ - /* value PPK[0..5] is guaranteed to be unique, as a function */ - /* of the 96-bit "input" value {TA, IV32, IV16}. That is, */ - /* P1K is now a keyed permutation of {TA, IV32, IV16}. */ - - /* Set RC4KEY[0..3], which includes "cleartext" portion of RC4 key */ - rc4key[0] = Hi8(iv16); /* RC4KEY[0..2] is the WEP IV */ - rc4key[1] = (Hi8(iv16) | 0x20) & 0x7F; /* Help avoid weak (FMS) keys */ - rc4key[2] = Lo8(iv16); - rc4key[3] = Lo8((PPK[5] ^ TK16(0)) >> 1); - - /* Copy 96 bits of PPK[0..5] to RC4KEY[4..15] (little-endian) */ - for (i = 0; i < 6; i++) { - rc4key[4 + 2 * i] = Lo8(PPK[i]); - rc4key[5 + 2 * i] = Hi8(PPK[i]); - } - -} - -/* The hlen isn't include the IV */ -int rtw_tkip_encrypt23a(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - u16 pnl; - u32 pnh; - u8 rc4key[16]; - u8 ttkey[16]; - __le32 crc; - u8 hw_hdr_offset = 0; - struct arc4context mycontext; - int curfragnum, length; - u8 *pframe, *payload, *iv, *prwskey; - union pn48 dot11txpn; - struct sta_info *stainfo; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - int res = _SUCCESS; - - if (pattrib->encrypt != WLAN_CIPHER_SUITE_TKIP) - return _FAIL; - - if (!pxmitframe->buf_addr) - return _FAIL; - - hw_hdr_offset = TXDESC_OFFSET; - - pframe = pxmitframe->buf_addr + hw_hdr_offset; - - if (pattrib->psta) - stainfo = pattrib->psta; - else { - DBG_8723A("%s, call rtw_get_stainfo()\n", __func__); - stainfo = rtw_get_stainfo23a(&padapter->stapriv, - &pattrib->ra[0]); - } - - if (!stainfo) { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s: stainfo == NULL!!!\n", __func__); - DBG_8723A("%s, psta == NUL\n", __func__); - return _FAIL; - } - - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s: stainfo!= NULL!!!\n", __func__); - - if (!(stainfo->state & _FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, stainfo->state); - return _FAIL; - } - - if (is_multicast_ether_addr(pattrib->ra)) - prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey; - else - prwskey = &stainfo->dot118021x_UncstKey.skey[0]; - - /* 4 start to encrypt each fragment */ - for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) { - iv = pframe + pattrib->hdrlen; - payload = pframe + pattrib->iv_len + pattrib->hdrlen; - - GET_TKIP_PN(iv, dot11txpn); - - pnl = (u16)(dot11txpn.val); - pnh = (u32)(dot11txpn.val>>16); - - phase1((u16 *)&ttkey[0], prwskey, &pattrib->ta[0], pnh); - - phase2(&rc4key[0], prwskey, (u16 *)&ttkey[0], pnl); - - 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); - crc = cpu_to_le32(getcrc32(payload, length)); - - arcfour_init(&mycontext, rc4key, 16); - arcfour_encrypt(&mycontext, payload, payload, length); - arcfour_encrypt(&mycontext, payload + length, - (char *)&crc, 4); - - } else { - length = (pxmitpriv->frag_len - - pattrib->hdrlen - - pattrib->iv_len - - pattrib->icv_len); - - crc = cpu_to_le32(getcrc32(payload, length)); - arcfour_init(&mycontext, rc4key, 16); - arcfour_encrypt(&mycontext, payload, payload, length); - arcfour_encrypt(&mycontext, payload + length, - (char *)&crc, 4); - - pframe += pxmitpriv->frag_len; - pframe = PTR_ALIGN(pframe, 4); - } - } - - return res; -} - -/* The hlen isn't include the IV */ -int rtw_tkip_decrypt23a(struct rtw_adapter *padapter, - struct recv_frame *precvframe) -{ - u16 pnl; - u32 pnh; - u8 rc4key[16]; - u8 ttkey[16]; - u32 actual_crc, expected_crc; - struct arc4context mycontext; - int length; - u8 *pframe, *payload, *iv, *prwskey; - union pn48 dot11txpn; - struct sta_info *stainfo; - struct rx_pkt_attrib *prxattrib = &precvframe->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct sk_buff *skb = precvframe->pkt; - int res = _SUCCESS; - - if (prxattrib->encrypt != WLAN_CIPHER_SUITE_TKIP) - return _FAIL; - - pframe = skb->data; - - stainfo = rtw_get_stainfo23a(&padapter->stapriv, - &prxattrib->ta[0]); - if (!stainfo) { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s: stainfo == NULL!!!\n", __func__); - return _FAIL; - } - - /* 4 start to decrypt recvframe */ - if (is_multicast_ether_addr(prxattrib->ra)) { - if (psecuritypriv->binstallGrpkey == 0) { - res = _FAIL; - DBG_8723A("%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]; - } - - iv = pframe + prxattrib->hdrlen; - payload = pframe + prxattrib->iv_len + prxattrib->hdrlen; - length = skb->len - prxattrib->hdrlen - prxattrib->iv_len; - - GET_TKIP_PN(iv, dot11txpn); - - pnl = (u16)(dot11txpn.val); - pnh = (u32)(dot11txpn.val>>16); - - phase1((u16 *)&ttkey[0], prwskey, &prxattrib->ta[0], pnh); - phase2(&rc4key[0], prwskey, (unsigned short *)&ttkey[0], pnl); - - /* 4 decrypt payload include icv */ - arcfour_init(&mycontext, rc4key, 16); - arcfour_encrypt(&mycontext, payload, payload, length); - - actual_crc = getcrc32(payload, length - 4); - expected_crc = get_unaligned_le32(&payload[length - 4]); - - if (actual_crc != expected_crc) { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s:icv CRC mismatch: " - "actual: %08x, expected: %08x\n", - __func__, actual_crc, expected_crc); - res = _FAIL; - } - -exit: - return res; -} - -/* 3 ===== AES related ===== */ - -#define MAX_MSG_SIZE 2048 -/*****************************/ -/******** SBOX Table *********/ -/*****************************/ - -static 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 ****/ -/*****************************/ - -static void construct_mic_header2(u8 *mic_header2, u8 *mpdu, int a4_exists, - int qc_exists); - -static void xor_128(u8 *a, u8 *b, u8 *out) -{ - int i; - - for (i = 0; i < 16; i++) - out[i] = a[i] ^ b[i]; -} - -static void xor_32(u8 *a, u8 *b, u8 *out) -{ - int i; - - for (i = 0; i < 4; i++) - out[i] = a[i] ^ b[i]; -} - -static u8 sbox(u8 a) -{ - return sbox_table[(int)a]; -} - -static void next_key(u8 *key, int round) -{ - u8 rcon; - u8 sbox_key[4]; - 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) -{ - 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) -{ - 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) -{ - int round; - int i; - u8 intermediatea[16]; - u8 intermediateb[16]; - u8 round_key[16]; - - 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); - } - } - -} - -/************************************************/ -/* construct_mic_iv() */ -/* Builds the MIC IV from header fields and PN */ -/************************************************/ -static void construct_mic_iv(u8 *mic_iv, int qc_exists, int a4_exists, u8 *mpdu, - uint payload_length, u8 *pn_vector) -{ - int i; - - mic_iv[0] = 0x59; - if (qc_exists && a4_exists) - mic_iv[1] = mpdu[30] & 0x0f; /* QoS_TC */ - if (qc_exists && !a4_exists) - mic_iv[1] = mpdu[24] & 0x0f; /* mute bits 7-4 */ - if (!qc_exists) - mic_iv[1] = 0x00; - for (i = 2; i < 8; i++) - mic_iv[i] = mpdu[i + 8]; /* mic_iv[2:7] = A2[0:5] = mpdu[10:15] */ - for (i = 8; i < 14; i++) - mic_iv[i] = pn_vector[13 - i]; /* mic_iv[8:13] = PN[5:0] */ - mic_iv[14] = (unsigned char)(payload_length / 256); - mic_iv[15] = (unsigned char)(payload_length % 256); -} - -/************************************************/ -/* construct_mic_header1() */ -/* Builds the first MIC header block from */ -/* header fields. */ -/************************************************/ -static void construct_mic_header1(u8 *mic_header1, int header_length, u8 *mpdu) -{ - mic_header1[0] = (u8)((header_length - 2) / 256); - mic_header1[1] = (u8)((header_length - 2) % 256); - mic_header1[2] = mpdu[0] & 0xcf; /* Mute CF poll & CF ack bits */ - mic_header1[3] = mpdu[1] & 0xc7; /* Mute retry, more data and pwr mgt bits */ - mic_header1[4] = mpdu[4]; /* A1 */ - mic_header1[5] = mpdu[5]; - mic_header1[6] = mpdu[6]; - mic_header1[7] = mpdu[7]; - mic_header1[8] = mpdu[8]; - mic_header1[9] = mpdu[9]; - mic_header1[10] = mpdu[10]; /* A2 */ - mic_header1[11] = mpdu[11]; - mic_header1[12] = mpdu[12]; - mic_header1[13] = mpdu[13]; - mic_header1[14] = mpdu[14]; - mic_header1[15] = mpdu[15]; - -} - -/************************************************/ -/* construct_mic_header2() */ -/* Builds the last MIC header block from */ -/* header fields. */ -/************************************************/ -static void construct_mic_header2(u8 *mic_header2, u8 *mpdu, int a4_exists, - int qc_exists) -{ - int i; - - for (i = 0; i < 16; i++) - mic_header2[i] = 0x00; - - mic_header2[0] = mpdu[16]; /* A3 */ - mic_header2[1] = mpdu[17]; - mic_header2[2] = mpdu[18]; - mic_header2[3] = mpdu[19]; - mic_header2[4] = mpdu[20]; - mic_header2[5] = mpdu[21]; - - mic_header2[6] = 0x00; - mic_header2[7] = 0x00; /* mpdu[23]; */ - - if (!qc_exists && a4_exists) { - for (i = 0; i < 6; i++) - mic_header2[8+i] = mpdu[24+i]; /* A4 */ - } - - if (qc_exists && !a4_exists) { - mic_header2[8] = mpdu[24] & 0x0f; /* mute bits 15 - 4 */ - mic_header2[9] = mpdu[25] & 0x00; - } - - if (qc_exists && a4_exists) { - for (i = 0; i < 6; i++) - mic_header2[8+i] = mpdu[24+i]; /* A4 */ - - mic_header2[14] = mpdu[30] & 0x0f; - mic_header2[15] = mpdu[31] & 0x00; - } - -} - -/************************************************/ -/* construct_mic_header2() */ -/* Builds the last MIC header block from */ -/* header fields. */ -/************************************************/ -static void construct_ctr_preload(u8 *ctr_preload, int a4_exists, int qc_exists, - u8 *mpdu, u8 *pn_vector, int c) -{ - int i = 0; - - for (i = 0; i < 16; i++) - ctr_preload[i] = 0x00; - - i = 0; - - ctr_preload[0] = 0x01; /* flag */ - if (qc_exists && a4_exists) - ctr_preload[1] = mpdu[30] & 0x0f; /* QoC_Control */ - if (qc_exists && !a4_exists) - ctr_preload[1] = mpdu[24] & 0x0f; - - for (i = 2; i < 8; i++) - ctr_preload[i] = mpdu[i + 8]; /* ctr_preload[2:7] = A2[0:5] = mpdu[10:15] */ - for (i = 8; i < 14; i++) - ctr_preload[i] = pn_vector[13 - i]; /* ctr_preload[8:13] = PN[5:0] */ - ctr_preload[14] = (unsigned char) (c / 256); /* Ctr */ - ctr_preload[15] = (unsigned char) (c % 256); - -} - -/************************************/ -/* bitwise_xor() */ -/* A 128 bit, bitwise exclusive or */ -/************************************/ -static void bitwise_xor(u8 *ina, u8 *inb, u8 *out) -{ - int i; - - for (i = 0; i < 16; i++) - out[i] = ina[i] ^ inb[i]; -} - -static int aes_cipher(u8 *key, uint hdrlen, u8 *pframe, uint plen) -{ - uint qc_exists, a4_exists, i, j, payload_remainder, - num_blocks, payload_index; - u8 pn_vector[6]; - u8 mic_iv[16]; - u8 mic_header1[16]; - u8 mic_header2[16]; - u8 ctr_preload[16]; - /* Intermediate Buffers */ - u8 chain_buffer[16]; - u8 aes_out[16]; - u8 padded_buffer[16]; - u8 mic[8]; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)pframe; - u16 frsubtype = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_STYPE; - - memset((void *)mic_iv, 0, 16); - memset((void *)mic_header1, 0, 16); - memset((void *)mic_header2, 0, 16); - memset((void *)ctr_preload, 0, 16); - memset((void *)chain_buffer, 0, 16); - memset((void *)aes_out, 0, 16); - memset((void *)padded_buffer, 0, 16); - - if ((hdrlen == sizeof(struct ieee80211_hdr_3addr) || - (hdrlen == sizeof(struct ieee80211_qos_hdr)))) - a4_exists = 0; - else - a4_exists = 1; - - if (ieee80211_is_data(hdr->frame_control)) { - if ((frsubtype == IEEE80211_STYPE_DATA_CFACK) || - (frsubtype == IEEE80211_STYPE_DATA_CFPOLL) || - (frsubtype == IEEE80211_STYPE_DATA_CFACKPOLL)) { - qc_exists = 1; - if (hdrlen != sizeof(struct ieee80211_qos_hdr)) - hdrlen += 2; - } else if ((frsubtype == IEEE80211_STYPE_QOS_DATA) || - (frsubtype == IEEE80211_STYPE_QOS_DATA_CFACK) || - (frsubtype == IEEE80211_STYPE_QOS_DATA_CFPOLL) || - (frsubtype == IEEE80211_STYPE_QOS_DATA_CFACKPOLL)) { - if (hdrlen != sizeof(struct ieee80211_qos_hdr)) - hdrlen += 2; - qc_exists = 1; - } else { - qc_exists = 0; - } - } else { - qc_exists = 0; - } - pn_vector[0] = pframe[hdrlen]; - pn_vector[1] = pframe[hdrlen + 1]; - pn_vector[2] = pframe[hdrlen + 4]; - pn_vector[3] = pframe[hdrlen + 5]; - pn_vector[4] = pframe[hdrlen + 6]; - pn_vector[5] = pframe[hdrlen + 7]; - - construct_mic_iv(mic_iv, qc_exists, a4_exists, pframe, plen, pn_vector); - - construct_mic_header1(mic_header1, hdrlen, pframe); - construct_mic_header2(mic_header2, pframe, a4_exists, qc_exists); - - payload_remainder = plen % 16; - num_blocks = plen / 16; - - /* Find start of payload */ - payload_index = hdrlen + 8; - - /* Calculate MIC */ - aes128k128d(key, mic_iv, aes_out); - bitwise_xor(aes_out, mic_header1, chain_buffer); - aes128k128d(key, chain_buffer, aes_out); - bitwise_xor(aes_out, mic_header2, chain_buffer); - aes128k128d(key, chain_buffer, aes_out); - - for (i = 0; i < num_blocks; i++) { - bitwise_xor(aes_out, &pframe[payload_index], chain_buffer); - - payload_index += 16; - aes128k128d(key, chain_buffer, aes_out); - } - - /* Add on the final payload block if it needs padding */ - if (payload_remainder > 0) { - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < payload_remainder; j++) - padded_buffer[j] = pframe[payload_index++]; - bitwise_xor(aes_out, padded_buffer, chain_buffer); - aes128k128d(key, chain_buffer, aes_out); - } - - for (j = 0; j < 8; j++) - mic[j] = aes_out[j]; - - /* Insert MIC into payload */ - for (j = 0; j < 8; j++) - pframe[payload_index + j] = mic[j]; - - payload_index = hdrlen + 8; - for (i = 0; i < num_blocks; i++) { - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, - pframe, pn_vector, i + 1); - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, &pframe[payload_index], chain_buffer); - for (j = 0; j < 16; j++) - pframe[payload_index++] = chain_buffer[j]; - } - - if (payload_remainder > 0) { - /* If there is a short final block, then pad it, - * encrypt it and copy the unpadded part back - */ - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, - pn_vector, num_blocks + 1); - - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < payload_remainder; j++) - padded_buffer[j] = pframe[payload_index + j]; - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, padded_buffer, chain_buffer); - for (j = 0; j < payload_remainder; j++) - pframe[payload_index++] = chain_buffer[j]; - } - - /* Encrypt the MIC */ - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, - pn_vector, 0); - - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < 8; j++) - padded_buffer[j] = pframe[j + hdrlen + 8 + plen]; - - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, padded_buffer, chain_buffer); - for (j = 0; j < 8; j++) - pframe[payload_index++] = chain_buffer[j]; - - return _SUCCESS; -} - -int rtw_aes_encrypt23a(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ /* exclude ICV */ - /* Intermediate Buffers */ - int curfragnum, length; - u8 *pframe, *prwskey; - u8 hw_hdr_offset = 0; - struct sta_info *stainfo; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - int res = _SUCCESS; - - if (!pxmitframe->buf_addr) - return _FAIL; - - hw_hdr_offset = TXDESC_OFFSET; - - pframe = pxmitframe->buf_addr + hw_hdr_offset; - - /* 4 start to encrypt each fragment */ - if (pattrib->encrypt != WLAN_CIPHER_SUITE_CCMP) - return _FAIL; - - if (pattrib->psta) { - stainfo = pattrib->psta; - } else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - stainfo = rtw_get_stainfo23a(&padapter->stapriv, &pattrib->ra[0]); - } - - if (!stainfo) { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s: stainfo == NULL!!!\n", __func__); - DBG_8723A("%s, psta == NUL\n", __func__); - res = _FAIL; - goto out; - } - if (!(stainfo->state & _FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", - __func__, stainfo->state); - return _FAIL; - } - 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 - prwskey = &stainfo->dot118021x_UncstKey.skey[0]; - - for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) { - /* 4 the last fragment */ - if ((curfragnum + 1) == pattrib->nr_frags) { - length = pattrib->last_txcmdsz - - pattrib->hdrlen-pattrib->iv_len - - pattrib->icv_len; - - aes_cipher(prwskey, pattrib->hdrlen, pframe, length); - } else { - length = pxmitpriv->frag_len-pattrib->hdrlen - - pattrib->iv_len - pattrib->icv_len; - - aes_cipher(prwskey, pattrib->hdrlen, pframe, length); - pframe += pxmitpriv->frag_len; - pframe = PTR_ALIGN(pframe, 4); - } - } -out: - return res; -} - -static int aes_decipher(u8 *key, uint hdrlen, u8 *pframe, uint plen) -{ - static u8 message[MAX_MSG_SIZE]; - uint qc_exists, a4_exists, i, j, payload_remainder, - num_blocks, payload_index; - int res = _SUCCESS; - u8 pn_vector[6]; - u8 mic_iv[16]; - u8 mic_header1[16]; - u8 mic_header2[16]; - u8 ctr_preload[16]; - /* Intermediate Buffers */ - u8 chain_buffer[16]; - u8 aes_out[16]; - u8 padded_buffer[16]; - u8 mic[8]; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)pframe; - u16 frsubtype = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_STYPE; - - memset((void *)mic_iv, 0, 16); - memset((void *)mic_header1, 0, 16); - memset((void *)mic_header2, 0, 16); - memset((void *)ctr_preload, 0, 16); - memset((void *)chain_buffer, 0, 16); - memset((void *)aes_out, 0, 16); - memset((void *)padded_buffer, 0, 16); - - /* start to decrypt the payload */ - - num_blocks = (plen - 8) / 16; /* plen including llc, payload_length and mic) */ - - payload_remainder = (plen - 8) % 16; - - pn_vector[0] = pframe[hdrlen]; - pn_vector[1] = pframe[hdrlen + 1]; - pn_vector[2] = pframe[hdrlen + 4]; - pn_vector[3] = pframe[hdrlen + 5]; - pn_vector[4] = pframe[hdrlen + 6]; - pn_vector[5] = pframe[hdrlen + 7]; - - if ((hdrlen == sizeof(struct ieee80211_hdr_3addr) || - (hdrlen == sizeof(struct ieee80211_qos_hdr)))) - a4_exists = 0; - else - a4_exists = 1; - - if (ieee80211_is_data(hdr->frame_control)) { - if ((frsubtype == IEEE80211_STYPE_DATA_CFACK) || - (frsubtype == IEEE80211_STYPE_DATA_CFPOLL) || - (frsubtype == IEEE80211_STYPE_DATA_CFACKPOLL)) { - qc_exists = 1; - if (hdrlen != sizeof(struct ieee80211_hdr_3addr)) - hdrlen += 2; - } else if ((frsubtype == IEEE80211_STYPE_QOS_DATA) || - (frsubtype == IEEE80211_STYPE_QOS_DATA_CFACK) || - (frsubtype == IEEE80211_STYPE_QOS_DATA_CFPOLL) || - (frsubtype == IEEE80211_STYPE_QOS_DATA_CFACKPOLL)) { - if (hdrlen != sizeof(struct ieee80211_hdr_3addr)) - hdrlen += 2; - qc_exists = 1; - } else { - qc_exists = 0; - } - } else { - qc_exists = 0; - } - - /* now, decrypt pframe with hdrlen offset and plen long */ - - payload_index = hdrlen + 8; /* 8 is for extiv */ - - for (i = 0; i < num_blocks; i++) { - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, - pframe, pn_vector, i + 1); - - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, &pframe[payload_index], chain_buffer); - - for (j = 0; j < 16; j++) - pframe[payload_index++] = chain_buffer[j]; - } - - if (payload_remainder > 0) { - /* If there is a short final block, then pad it, - * encrypt it and copy the unpadded part back - */ - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, - pn_vector, num_blocks + 1); - - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < payload_remainder; j++) - padded_buffer[j] = pframe[payload_index + j]; - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, padded_buffer, chain_buffer); - for (j = 0; j < payload_remainder; j++) - pframe[payload_index++] = chain_buffer[j]; - } - - /* start to calculate the mic */ - if ((hdrlen + plen + 8) <= MAX_MSG_SIZE) - memcpy(message, pframe, (hdrlen + plen + 8)); /* 8 is for ext iv len */ - - pn_vector[0] = pframe[hdrlen]; - pn_vector[1] = pframe[hdrlen + 1]; - pn_vector[2] = pframe[hdrlen + 4]; - pn_vector[3] = pframe[hdrlen + 5]; - pn_vector[4] = pframe[hdrlen + 6]; - pn_vector[5] = pframe[hdrlen + 7]; - - construct_mic_iv(mic_iv, qc_exists, a4_exists, message, - plen - 8, pn_vector); - - construct_mic_header1(mic_header1, hdrlen, message); - construct_mic_header2(mic_header2, message, a4_exists, qc_exists); - - payload_remainder = (plen - 8) % 16; - num_blocks = (plen - 8) / 16; - - /* Find start of payload */ - payload_index = hdrlen + 8; - - /* Calculate MIC */ - aes128k128d(key, mic_iv, aes_out); - bitwise_xor(aes_out, mic_header1, chain_buffer); - aes128k128d(key, chain_buffer, aes_out); - bitwise_xor(aes_out, mic_header2, chain_buffer); - aes128k128d(key, chain_buffer, aes_out); - - for (i = 0; i < num_blocks; i++) { - bitwise_xor(aes_out, &message[payload_index], chain_buffer); - - payload_index += 16; - aes128k128d(key, chain_buffer, aes_out); - } - - /* Add on the final payload block if it needs padding */ - if (payload_remainder > 0) { - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < payload_remainder; j++) - padded_buffer[j] = message[payload_index++]; - bitwise_xor(aes_out, padded_buffer, chain_buffer); - aes128k128d(key, chain_buffer, aes_out); - } - - for (j = 0 ; j < 8; j++) - mic[j] = aes_out[j]; - - /* Insert MIC into payload */ - for (j = 0; j < 8; j++) - message[payload_index + j] = mic[j]; - - payload_index = hdrlen + 8; - for (i = 0; i < num_blocks; i++) { - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, - message, pn_vector, i + 1); - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, &message[payload_index], chain_buffer); - for (j = 0; j < 16; j++) - message[payload_index++] = chain_buffer[j]; - } - - if (payload_remainder > 0) { - /* If there is a short final block, then pad it, - * encrypt it and copy the unpadded part back - */ - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, - message, pn_vector, num_blocks + 1); - - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < payload_remainder; j++) - padded_buffer[j] = message[payload_index + j]; - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, padded_buffer, chain_buffer); - for (j = 0; j < payload_remainder; j++) - message[payload_index++] = chain_buffer[j]; - } - - /* Encrypt the MIC */ - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, message, - pn_vector, 0); - - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < 8; j++) - padded_buffer[j] = message[j + hdrlen + 8 + plen - 8]; - - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, padded_buffer, chain_buffer); - for (j = 0; j < 8; j++) - message[payload_index++] = chain_buffer[j]; - - /* compare the mic */ - for (i = 0; i < 8; i++) { - if (pframe[hdrlen + 8 + plen - 8 + i] != message[hdrlen + 8 + plen - 8 + i]) { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s:mic check error mic[%d]: pframe(%x) != message(%x)\n", - __func__, i, - pframe[hdrlen + 8 + plen - 8 + i], - message[hdrlen + 8 + plen - 8 + i]); - DBG_8723A("%s:mic check error mic[%d]: pframe(%x) != message(%x)\n", - __func__, i, - pframe[hdrlen + 8 + plen - 8 + i], - message[hdrlen + 8 + plen - 8 + i]); - res = _FAIL; - } - } - return res; -} - -int rtw_aes_decrypt23a(struct rtw_adapter *padapter, - struct recv_frame *precvframe) -{ /* exclude ICV */ - struct sta_info *stainfo; - struct rx_pkt_attrib *prxattrib = &precvframe->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct sk_buff *skb = precvframe->pkt; - int length; - u8 *pframe, *prwskey; - int res = _SUCCESS; - - pframe = skb->data; - /* 4 start to encrypt each fragment */ - if (prxattrib->encrypt != WLAN_CIPHER_SUITE_CCMP) - return _FAIL; - - stainfo = rtw_get_stainfo23a(&padapter->stapriv, &prxattrib->ta[0]); - if (!stainfo) { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s: stainfo == NULL!!!\n", __func__); - res = _FAIL; - goto exit; - } - - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s: stainfo!= NULL!!!\n", __func__); - - if (is_multicast_ether_addr(prxattrib->ra)) { - /* in concurrent we should use sw decrypt in - * group key, so we remove this message - */ - if (!psecuritypriv->binstallGrpkey) { - res = _FAIL; - DBG_8723A("%s:rx bc/mc packets, but didn't install " - "group key!!!!!!!!!!\n", __func__); - goto exit; - } - prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey; - if (psecuritypriv->dot118021XGrpKeyid != prxattrib->key_index) { - DBG_8723A("not match packet_index =%d, install_index =" - "%d\n", prxattrib->key_index, - psecuritypriv->dot118021XGrpKeyid); - res = _FAIL; - goto exit; - } - } else { - prwskey = &stainfo->dot118021x_UncstKey.skey[0]; - } - - length = skb->len - prxattrib->hdrlen - prxattrib->iv_len; - - res = aes_decipher(prwskey, prxattrib->hdrlen, pframe, length); -exit: - return res; -} - -void rtw_use_tkipkey_handler23a(void *function_context) -{ - struct rtw_adapter *padapter = function_context; - - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "^^^%s ^^^\n", __func__); - padapter->securitypriv.busetkipkey = 1; - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "^^^%s padapter->securitypriv.busetkipkey =%d^^^\n", - __func__, padapter->securitypriv.busetkipkey); -} diff --git a/drivers/staging/rtl8723au/core/rtw_sreset.c b/drivers/staging/rtl8723au/core/rtw_sreset.c deleted file mode 100644 index 29a29d9..0000000 --- a/drivers/staging/rtl8723au/core/rtw_sreset.c +++ /dev/null @@ -1,214 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ - -#include <rtw_sreset.h> -#include <usb_ops_linux.h> - -void rtw_sreset_init(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct sreset_priv *psrtpriv = &pHalData->srestpriv; - - mutex_init(&psrtpriv->silentreset_mutex); - psrtpriv->silent_reset_inprogress = false; - psrtpriv->last_tx_time = 0; - psrtpriv->last_tx_complete_time = 0; -} - -void rtw_sreset_reset_value(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct sreset_priv *psrtpriv = &pHalData->srestpriv; - - psrtpriv->silent_reset_inprogress = false; - psrtpriv->last_tx_time = 0; - psrtpriv->last_tx_complete_time = 0; -} - -bool rtw_sreset_inprogress(struct rtw_adapter *padapter) -{ - struct rtw_adapter *primary_adapter = GET_PRIMARY_ADAPTER(padapter); - struct hal_data_8723a *pHalData = GET_HAL_DATA(primary_adapter); - - return pHalData->srestpriv.silent_reset_inprogress; -} - -static void sreset_restore_security_station(struct rtw_adapter *padapter) -{ - struct mlme_priv *mlmepriv = &padapter->mlmepriv; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *psta; - struct mlme_ext_info *pmlmeinfo = &padapter->mlmeextpriv.mlmext_info; - u8 val8; - - if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) - val8 = 0xcc; - else - val8 = 0xcf; - - rtl8723a_set_sec_cfg(padapter, val8); - - if (padapter->securitypriv.dot11PrivacyAlgrthm == - WLAN_CIPHER_SUITE_TKIP || - padapter->securitypriv.dot11PrivacyAlgrthm == - WLAN_CIPHER_SUITE_CCMP) { - psta = rtw_get_stainfo23a(pstapriv, get_bssid(mlmepriv)); - if (psta == NULL) { - /* DEBUG_ERR(("Set wpa_set_encryption: Obtain Sta_info fail\n")); */ - } else { - /* pairwise key */ - rtw_setstakey_cmd23a(padapter, (unsigned char *)psta, true); - /* group key */ - rtw_set_key23a(padapter,&padapter->securitypriv, padapter->securitypriv.dot118021XGrpKeyid, 0); - } - } -} - -static void sreset_restore_network_station(struct rtw_adapter *padapter) -{ - struct mlme_priv *mlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - u8 threshold; - - rtw_setopmode_cmd23a(padapter, NL80211_IFTYPE_STATION); - - /* TH = 1 => means that invalidate usb rx aggregation */ - /* TH = 0 => means that validate usb rx aggregation, use init value. */ - if (mlmepriv->htpriv.ht_option) { - if (padapter->registrypriv.wifi_spec == 1) - threshold = 1; - else - threshold = 0; - } else - threshold = 1; - - rtl8723a_set_rxdma_agg_pg_th(padapter, threshold); - - set_channel_bwmode23a(padapter, pmlmeext->cur_channel, - pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - - hw_var_set_bssid(padapter, pmlmeinfo->network.MacAddress); - hw_var_set_mlme_join(padapter, 0); - - rtl8723a_set_media_status(padapter, pmlmeinfo->state & 0x3); - - mlmeext_joinbss_event_callback23a(padapter, 1); - /* restore Sequence No. */ - rtl8723au_write8(padapter, REG_NQOS_SEQ, padapter->xmitpriv.nqos_ssn); - - sreset_restore_security_station(padapter); -} - -static void sreset_restore_network_status(struct rtw_adapter *padapter) -{ - struct mlme_priv *mlmepriv = &padapter->mlmepriv; - - if (check_fwstate(mlmepriv, WIFI_STATION_STATE)) { - DBG_8723A("%s(%s): fwstate:0x%08x - WIFI_STATION_STATE\n", - __func__, padapter->pnetdev->name, - get_fwstate(mlmepriv)); - sreset_restore_network_station(padapter); -#ifdef CONFIG_8723AU_AP_MODE - } else if (check_fwstate(mlmepriv, WIFI_AP_STATE)) { - DBG_8723A("%s(%s): fwstate:0x%08x - WIFI_AP_STATE\n", - __func__, padapter->pnetdev->name, - get_fwstate(mlmepriv)); - rtw_ap_restore_network(padapter); -#endif - } else if (check_fwstate(mlmepriv, WIFI_ADHOC_STATE)) { - DBG_8723A("%s(%s): fwstate:0x%08x - WIFI_ADHOC_STATE\n", - __func__, padapter->pnetdev->name, - get_fwstate(mlmepriv)); - } else { - DBG_8723A("%s(%s): fwstate:0x%08x - ???\n", __func__, - padapter->pnetdev->name, get_fwstate(mlmepriv)); - } -} - -static void sreset_stop_adapter(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - if (padapter == NULL) - return; - - DBG_8723A("%s(%s)\n", __func__, padapter->pnetdev->name); - - if (!rtw_netif_queue_stopped(padapter->pnetdev)) - netif_tx_stop_all_queues(padapter->pnetdev); - - rtw_cancel_all_timer23a(padapter); - - /* TODO: OS and HCI independent */ - tasklet_kill(&pxmitpriv->xmit_tasklet); - - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) - rtw_scan_abort23a(padapter); - - if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) - rtw23a_join_to_handler((unsigned long)padapter); -} - -static void sreset_start_adapter(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - if (padapter == NULL) - return; - - DBG_8723A("%s(%s)\n", __func__, padapter->pnetdev->name); - - if (check_fwstate(pmlmepriv, _FW_LINKED)) - sreset_restore_network_status(padapter); - - /* TODO: OS and HCI independent */ - tasklet_hi_schedule(&pxmitpriv->xmit_tasklet); - - mod_timer(&padapter->mlmepriv.dynamic_chk_timer, - jiffies + msecs_to_jiffies(2000)); - - if (rtw_netif_queue_stopped(padapter->pnetdev)) - netif_tx_wake_all_queues(padapter->pnetdev); -} - -void rtw_sreset_reset(struct rtw_adapter *active_adapter) -{ - struct rtw_adapter *padapter = GET_PRIMARY_ADAPTER(active_adapter); - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct sreset_priv *psrtpriv = &pHalData->srestpriv; - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - unsigned long start = jiffies; - - DBG_8723A("%s\n", __func__); - - mutex_lock(&psrtpriv->silentreset_mutex); - psrtpriv->silent_reset_inprogress = true; - pwrpriv->change_rfpwrstate = rf_off; - - sreset_stop_adapter(padapter); - - ips_enter23a(padapter); - ips_leave23a(padapter); - - sreset_start_adapter(padapter); - psrtpriv->silent_reset_inprogress = false; - mutex_unlock(&psrtpriv->silentreset_mutex); - - DBG_8723A("%s done in %d ms\n", __func__, - jiffies_to_msecs(jiffies - start)); -} diff --git a/drivers/staging/rtl8723au/core/rtw_sta_mgt.c b/drivers/staging/rtl8723au/core/rtw_sta_mgt.c deleted file mode 100644 index a9b778c..0000000 --- a/drivers/staging/rtl8723au/core/rtw_sta_mgt.c +++ /dev/null @@ -1,439 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RTW_STA_MGT_C_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <recv_osdep.h> -#include <xmit_osdep.h> -#include <mlme_osdep.h> -#include <sta_info.h> -#include <rtl8723a_hal.h> - -static const u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - -static void _rtw_init_stainfo(struct sta_info *psta) -{ - memset((u8 *)psta, 0, sizeof(struct sta_info)); - spin_lock_init(&psta->lock); - INIT_LIST_HEAD(&psta->list); - INIT_LIST_HEAD(&psta->hash_list); - _rtw_init_queue23a(&psta->sleep_q); - psta->sleepq_len = 0; - _rtw_init_sta_xmit_priv23a(&psta->sta_xmitpriv); - _rtw_init_sta_recv_priv23a(&psta->sta_recvpriv); -#ifdef CONFIG_8723AU_AP_MODE - INIT_LIST_HEAD(&psta->asoc_list); - INIT_LIST_HEAD(&psta->auth_list); - psta->expire_to = 0; - psta->flags = 0; - psta->capability = 0; - psta->bpairwise_key_installed = false; - psta->nonerp_set = 0; - psta->no_short_slot_time_set = 0; - psta->no_short_preamble_set = 0; - psta->no_ht_gf_set = 0; - psta->no_ht_set = 0; - psta->ht_20mhz_set = 0; - psta->keep_alive_trycnt = 0; -#endif /* CONFIG_8723AU_AP_MODE */ -} - -int _rtw_init_sta_priv23a(struct sta_priv *pstapriv) -{ - int i; - - spin_lock_init(&pstapriv->sta_hash_lock); - pstapriv->asoc_sta_count = 0; - for (i = 0; i < NUM_STA; i++) - INIT_LIST_HEAD(&pstapriv->sta_hash[i]); - -#ifdef CONFIG_8723AU_AP_MODE - pstapriv->sta_dz_bitmap = 0; - pstapriv->tim_bitmap = 0; - INIT_LIST_HEAD(&pstapriv->asoc_list); - INIT_LIST_HEAD(&pstapriv->auth_list); - spin_lock_init(&pstapriv->asoc_list_lock); - spin_lock_init(&pstapriv->auth_list_lock); - pstapriv->asoc_list_cnt = 0; - pstapriv->auth_list_cnt = 0; - pstapriv->auth_to = 3; /* 3*2 = 6 sec */ - pstapriv->assoc_to = 3; - /* pstapriv->expire_to = 900; 900*2 = 1800 sec = 30 min, - expire after no any traffic. */ - /* pstapriv->expire_to = 30; 30*2 = 60 sec = 1 min, - expire after no any traffic. */ - pstapriv->expire_to = 3; /* 3*2 = 6 sec */ - pstapriv->max_num_sta = NUM_STA; -#endif - return _SUCCESS; -} - -int _rtw_free_sta_priv23a(struct sta_priv *pstapriv) -{ - struct list_head *phead; - struct sta_info *psta, *ptmp; - struct recv_reorder_ctrl *preorder_ctrl; - int index; - - if (pstapriv) { - /* delete all reordering_ctrl_timer */ - spin_lock_bh(&pstapriv->sta_hash_lock); - for (index = 0; index < NUM_STA; index++) { - phead = &pstapriv->sta_hash[index]; - list_for_each_entry_safe(psta, ptmp, phead, hash_list) { - int i; - - for (i = 0; i < 16 ; i++) { - preorder_ctrl = &psta->recvreorder_ctrl[i]; - del_timer_sync(&preorder_ctrl->reordering_ctrl_timer); - } - } - } - spin_unlock_bh(&pstapriv->sta_hash_lock); - /*===============================*/ - } - return _SUCCESS; -} - -struct sta_info * -rtw_alloc_stainfo23a(struct sta_priv *pstapriv, const u8 *hwaddr, gfp_t gfp) -{ - struct list_head *phash_list; - struct sta_info *psta; - struct recv_reorder_ctrl *preorder_ctrl; - s32 index; - int i = 0; - u16 wRxSeqInitialValue = 0xffff; - - psta = kmalloc(sizeof(struct sta_info), gfp); - if (!psta) - return NULL; - - spin_lock_bh(&pstapriv->sta_hash_lock); - - _rtw_init_stainfo(psta); - - psta->padapter = pstapriv->padapter; - - ether_addr_copy(psta->hwaddr, hwaddr); - - index = wifi_mac_hash(hwaddr); - - RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_, - "rtw_alloc_stainfo23a: index = %x\n", index); - if (index >= NUM_STA) { - RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, - "ERROR => rtw_alloc_stainfo23a: index >= NUM_STA\n"); - psta = NULL; - goto exit; - } - phash_list = &pstapriv->sta_hash[index]; - - list_add_tail(&psta->hash_list, phash_list); - - pstapriv->asoc_sta_count++; - -/* For the SMC router, the sequence number of first packet of WPS - handshake will be 0. */ -/* In this case, this packet will be dropped by recv_decache function - if we use the 0x00 as the default value for tid_rxseq variable. */ -/* So, we initialize the tid_rxseq variable as the 0xffff. */ - - for (i = 0; i < 16; i++) - 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_timer23a(psta); - - /* for A-MPDU Rx reordering buffer control */ - for (i = 0; i < 16; i++) { - preorder_ctrl = &psta->recvreorder_ctrl[i]; - - preorder_ctrl->padapter = pstapriv->padapter; - - preorder_ctrl->enable = false; - - preorder_ctrl->indicate_seq = 0xffff; - preorder_ctrl->wend_b = 0xffff; - /* preorder_ctrl->wsize_b = (NR_RECVBUFF-2); */ - preorder_ctrl->wsize_b = 64;/* 64; */ - - _rtw_init_queue23a(&preorder_ctrl->pending_recvframe_queue); - - rtw_init_recv_timer23a(preorder_ctrl); - } - /* init for DM */ - psta->rssi_stat.UndecoratedSmoothedPWDB = (-1); - psta->rssi_stat.UndecoratedSmoothedCCK = (-1); - - /* init for the sequence number of received management frame */ - psta->RxMgmtFrameSeqNum = 0xffff; -exit: - spin_unlock_bh(&pstapriv->sta_hash_lock); - return psta; -} - -/* using pstapriv->sta_hash_lock to protect */ -int rtw_free_stainfo23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - struct recv_reorder_ctrl *preorder_ctrl; - struct sta_xmit_priv *pstaxmitpriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct sta_priv *pstapriv = &padapter->stapriv; - struct hw_xmit *phwxmit; - int i; - - if (!psta) - goto exit; - - spin_lock_bh(&psta->lock); - psta->state &= ~_FW_LINKED; - spin_unlock_bh(&psta->lock); - - pstaxmitpriv = &psta->sta_xmitpriv; - - spin_lock_bh(&pxmitpriv->lock); - - rtw_free_xmitframe_queue23a(pxmitpriv, &psta->sleep_q); - psta->sleepq_len = 0; - - /* vo */ - rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending); - list_del_init(&pstaxmitpriv->vo_q.tx_pending); - phwxmit = pxmitpriv->hwxmits; - phwxmit->accnt -= pstaxmitpriv->vo_q.qcnt; - pstaxmitpriv->vo_q.qcnt = 0; - - /* vi */ - rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending); - list_del_init(&pstaxmitpriv->vi_q.tx_pending); - phwxmit = pxmitpriv->hwxmits+1; - phwxmit->accnt -= pstaxmitpriv->vi_q.qcnt; - pstaxmitpriv->vi_q.qcnt = 0; - - /* be */ - rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->be_q.sta_pending); - list_del_init(&pstaxmitpriv->be_q.tx_pending); - phwxmit = pxmitpriv->hwxmits+2; - phwxmit->accnt -= pstaxmitpriv->be_q.qcnt; - pstaxmitpriv->be_q.qcnt = 0; - - /* bk */ - rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending); - list_del_init(&pstaxmitpriv->bk_q.tx_pending); - phwxmit = pxmitpriv->hwxmits+3; - phwxmit->accnt -= pstaxmitpriv->bk_q.qcnt; - pstaxmitpriv->bk_q.qcnt = 0; - - spin_unlock_bh(&pxmitpriv->lock); - - list_del_init(&psta->hash_list); - RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, - "free number_%d stainfo with hwaddr = %pM\n", - pstapriv->asoc_sta_count, psta->hwaddr); - pstapriv->asoc_sta_count--; - - /* re-init sta_info; 20061114 will be init in alloc_stainfo */ - /* _rtw_init_sta_xmit_priv23a(&psta->sta_xmitpriv); */ - /* _rtw_init_sta_recv_priv23a(&psta->sta_recvpriv); */ - - del_timer_sync(&psta->addba_retry_timer); - - /* for A-MPDU Rx reordering buffer control, - cancel reordering_ctrl_timer */ - for (i = 0; i < 16; i++) { - struct list_head *phead, *plist; - struct recv_frame *prframe; - struct rtw_queue *ppending_recvframe_queue; - - preorder_ctrl = &psta->recvreorder_ctrl[i]; - - del_timer_sync(&preorder_ctrl->reordering_ctrl_timer); - - ppending_recvframe_queue = - &preorder_ctrl->pending_recvframe_queue; - - spin_lock_bh(&ppending_recvframe_queue->lock); - phead = get_list_head(ppending_recvframe_queue); - plist = phead->next; - - while (!list_empty(phead)) { - prframe = container_of(plist, struct recv_frame, list); - plist = plist->next; - list_del_init(&prframe->list); - rtw_free_recvframe23a(prframe); - } - spin_unlock_bh(&ppending_recvframe_queue->lock); - } - if (!(psta->state & WIFI_AP_STATE)) - rtl8723a_SetHalODMVar(padapter, HAL_ODM_STA_INFO, psta, false); -#ifdef CONFIG_8723AU_AP_MODE - spin_lock_bh(&pstapriv->auth_list_lock); - if (!list_empty(&psta->auth_list)) { - list_del_init(&psta->auth_list); - pstapriv->auth_list_cnt--; - } - spin_unlock_bh(&pstapriv->auth_list_lock); - - psta->expire_to = 0; - - psta->sleepq_ac_len = 0; - psta->qos_info = 0; - - psta->max_sp_len = 0; - psta->uapsd_bk = 0; - psta->uapsd_be = 0; - psta->uapsd_vi = 0; - psta->uapsd_vo = 0; - - psta->has_legacy_ac = 0; - - pstapriv->sta_dz_bitmap &= ~CHKBIT(psta->aid); - pstapriv->tim_bitmap &= ~CHKBIT(psta->aid); - - if ((psta->aid > 0) && (pstapriv->sta_aid[psta->aid - 1] == psta)) { - pstapriv->sta_aid[psta->aid - 1] = NULL; - psta->aid = 0; - } -#endif /* CONFIG_8723AU_AP_MODE */ - - kfree(psta); -exit: - return _SUCCESS; -} - -/* free all stainfo which in sta_hash[all] */ -void rtw_free_all_stainfo23a(struct rtw_adapter *padapter) -{ - struct list_head *phead; - struct sta_info *psta, *ptmp; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *pbcmc_stainfo = rtw_get_bcmc_stainfo23a(padapter); - s32 index; - - if (pstapriv->asoc_sta_count == 1) - return; - - spin_lock_bh(&pstapriv->sta_hash_lock); - for (index = 0; index < NUM_STA; index++) { - phead = &pstapriv->sta_hash[index]; - list_for_each_entry_safe(psta, ptmp, phead, hash_list) { - if (pbcmc_stainfo != psta) - rtw_free_stainfo23a(padapter, psta); - } - } - spin_unlock_bh(&pstapriv->sta_hash_lock); -} - -/* any station allocated can be searched by hash list */ -struct sta_info *rtw_get_stainfo23a(struct sta_priv *pstapriv, const u8 *hwaddr) -{ - struct list_head *phead; - struct sta_info *pos, *psta = NULL; - u32 index; - const u8 *addr; - - if (!hwaddr) - return NULL; - - if (is_multicast_ether_addr(hwaddr)) - addr = bc_addr; - else - addr = hwaddr; - - index = wifi_mac_hash(addr); - - spin_lock_bh(&pstapriv->sta_hash_lock); - phead = &pstapriv->sta_hash[index]; - list_for_each_entry(pos, phead, hash_list) { - psta = pos; - - /* if found the matched address */ - if (ether_addr_equal(psta->hwaddr, addr)) - break; - - psta = NULL; - } - spin_unlock_bh(&pstapriv->sta_hash_lock); - return psta; -} - -int rtw_init_bcmc_stainfo23a(struct rtw_adapter *padapter) -{ - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *psta; - struct tx_servq *ptxservq; - int res = _SUCCESS; - - psta = rtw_alloc_stainfo23a(pstapriv, bc_addr, GFP_KERNEL); - if (!psta) { - res = _FAIL; - RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, - "rtw_alloc_stainfo23a fail\n"); - return res; - } - /* default broadcast & multicast use macid 1 */ - psta->mac_id = 1; - - ptxservq = &psta->sta_xmitpriv.be_q; - return _SUCCESS; -} - -struct sta_info *rtw_get_bcmc_stainfo23a(struct rtw_adapter *padapter) -{ - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - - psta = rtw_get_stainfo23a(pstapriv, bc_addr); - return psta; -} - -bool rtw_access_ctrl23a(struct rtw_adapter *padapter, u8 *mac_addr) -{ - bool res = true; -#ifdef CONFIG_8723AU_AP_MODE - struct list_head *phead; - struct rtw_wlan_acl_node *paclnode; - bool match = false; - struct sta_priv *pstapriv = &padapter->stapriv; - struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; - struct rtw_queue *pacl_node_q = &pacl_list->acl_node_q; - - spin_lock_bh(&pacl_node_q->lock); - phead = get_list_head(pacl_node_q); - list_for_each_entry(paclnode, phead, list) { - if (ether_addr_equal(paclnode->addr, mac_addr)) { - if (paclnode->valid) { - match = true; - break; - } - } - } - spin_unlock_bh(&pacl_node_q->lock); - - if (pacl_list->mode == 1)/* accept unless in deny list */ - res = (match) ? false : true; - else if (pacl_list->mode == 2)/* deny unless in accept list */ - res = (match) ? true : false; - else - res = true; -#endif - return res; -} diff --git a/drivers/staging/rtl8723au/core/rtw_wlan_util.c b/drivers/staging/rtl8723au/core/rtw_wlan_util.c deleted file mode 100644 index 694cf17..0000000 --- a/drivers/staging/rtl8723au/core/rtw_wlan_util.c +++ /dev/null @@ -1,1537 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RTW_WLAN_UTIL_C_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <linux/ieee80211.h> -#include <wifi.h> -#include <rtl8723a_spec.h> - -static unsigned char ARTHEROS_OUI1[] = {0x00, 0x03, 0x7f}; -static unsigned char ARTHEROS_OUI2[] = {0x00, 0x13, 0x74}; - -static unsigned char BROADCOM_OUI1[] = {0x00, 0x10, 0x18}; -static unsigned char BROADCOM_OUI2[] = {0x00, 0x0a, 0xf7}; - -static unsigned char CISCO_OUI[] = {0x00, 0x40, 0x96}; -static unsigned char MARVELL_OUI[] = {0x00, 0x50, 0x43}; -static unsigned char RALINK_OUI[] = {0x00, 0x0c, 0x43}; -static unsigned char REALTEK_OUI[] = {0x00, 0xe0, 0x4c}; -static unsigned char AIRGOCAP_OUI[] = {0x00, 0x0a, 0xf5}; -static unsigned char EPIGRAM_OUI[] = {0x00, 0x90, 0x4c}; - -static unsigned char WPA_TKIP_CIPHER[4] = {0x00, 0x50, 0xf2, 0x02}; -static unsigned char RSN_TKIP_CIPHER[4] = {0x00, 0x0f, 0xac, 0x02}; - -#define R2T_PHY_DELAY 0 - -/* define WAIT_FOR_BCN_TO_MIN 3000 */ -#define WAIT_FOR_BCN_TO_MIN 6000 -#define WAIT_FOR_BCN_TO_MAX 20000 - -static u8 rtw_basic_rate_cck[4] = { - IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK -}; - -static u8 rtw_basic_rate_ofdm[3] = { - IEEE80211_OFDM_RATE_6MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_OFDM_RATE_12MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_OFDM_RATE_24MB | IEEE80211_BASIC_RATE_MASK -}; - -static u8 rtw_basic_rate_mix[7] = { - IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_OFDM_RATE_6MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_OFDM_RATE_12MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_OFDM_RATE_24MB | IEEE80211_BASIC_RATE_MASK -}; - -int cckrates_included23a(unsigned char *rate, int ratelen) -{ - int i; - - for (i = 0; i < ratelen; i++) { - if (((rate[i]) & 0x7f) == 2 || ((rate[i]) & 0x7f) == 4 || - ((rate[i]) & 0x7f) == 11 || ((rate[i]) & 0x7f) == 22) - return true; - } - - return false; -} - -int cckratesonly_included23a(unsigned char *rate, int ratelen) -{ - int i; - - for (i = 0; i < ratelen; i++) { - if (((rate[i]) & 0x7f) != 2 && ((rate[i]) & 0x7f) != 4 && - ((rate[i]) & 0x7f) != 11 && ((rate[i]) & 0x7f) != 22) - return false; - } - - return true; -} - -unsigned char networktype_to_raid23a(unsigned char network_type) -{ - unsigned char raid; - - switch (network_type) { - case WIRELESS_11B: - raid = RATR_INX_WIRELESS_B; - break; - case WIRELESS_11A: - case WIRELESS_11G: - raid = RATR_INX_WIRELESS_G; - break; - case WIRELESS_11BG: - raid = RATR_INX_WIRELESS_GB; - break; - case WIRELESS_11_24N: - case WIRELESS_11_5N: - raid = RATR_INX_WIRELESS_N; - break; - case WIRELESS_11A_5N: - case WIRELESS_11G_24N: - raid = RATR_INX_WIRELESS_NG; - break; - case WIRELESS_11BG_24N: - raid = RATR_INX_WIRELESS_NGB; - break; - default: - raid = RATR_INX_WIRELESS_GB; - break; - } - return raid; -} - -u8 judge_network_type23a(struct rtw_adapter *padapter, - unsigned char *rate, int ratelen) -{ - u8 network_type = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (pmlmeext->cur_channel > 14) { - if (pmlmeinfo->HT_enable) - network_type = WIRELESS_11_5N; - network_type |= WIRELESS_11A; - } else { - if (pmlmeinfo->HT_enable) - network_type = WIRELESS_11_24N; - - if ((cckratesonly_included23a(rate, ratelen)) == true) - network_type |= WIRELESS_11B; - else if ((cckrates_included23a(rate, ratelen)) == true) - network_type |= WIRELESS_11BG; - else - network_type |= WIRELESS_11G; - } - return network_type; -} - -static unsigned char ratetbl_val_2wifirate(unsigned char rate) -{ - unsigned char val = 0; - - switch (rate & 0x7f) { - case 0: - val = IEEE80211_CCK_RATE_1MB; - break; - case 1: - val = IEEE80211_CCK_RATE_2MB; - break; - case 2: - val = IEEE80211_CCK_RATE_5MB; - break; - case 3: - val = IEEE80211_CCK_RATE_11MB; - break; - case 4: - val = IEEE80211_OFDM_RATE_6MB; - break; - case 5: - val = IEEE80211_OFDM_RATE_9MB; - break; - case 6: - val = IEEE80211_OFDM_RATE_12MB; - break; - case 7: - val = IEEE80211_OFDM_RATE_18MB; - break; - case 8: - val = IEEE80211_OFDM_RATE_24MB; - break; - case 9: - val = IEEE80211_OFDM_RATE_36MB; - break; - case 10: - val = IEEE80211_OFDM_RATE_48MB; - break; - case 11: - val = IEEE80211_OFDM_RATE_54MB; - break; - } - return val; -} - -static int is_basicrate(struct rtw_adapter *padapter, unsigned char rate) -{ - int i; - unsigned char val; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - for (i = 0; i < NumRates; i++) { - val = pmlmeext->basicrate[i]; - - if (val != 0xff && val != 0xfe) { - if (rate == ratetbl_val_2wifirate(val)) - return true; - } - } - - return false; -} - -static unsigned int ratetbl2rateset(struct rtw_adapter *padapter, - unsigned char *rateset) -{ - int i; - unsigned char rate; - unsigned int len = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - for (i = 0; i < NumRates; i++) { - rate = pmlmeext->datarate[i]; - - switch (rate) { - case 0xff: - return len; - case 0xfe: - continue; - default: - rate = ratetbl_val_2wifirate(rate); - - if (is_basicrate(padapter, rate) == true) - rate |= IEEE80211_BASIC_RATE_MASK; - - rateset[len] = rate; - len++; - break; - } - } - return len; -} - -void get_rate_set23a(struct rtw_adapter *padapter, - unsigned char *pbssrate, int *bssrate_len) -{ - unsigned char supportedrates[NumRates]; - - memset(supportedrates, 0, NumRates); - *bssrate_len = ratetbl2rateset(padapter, supportedrates); - memcpy(pbssrate, supportedrates, *bssrate_len); -} - -void UpdateBrateTbl23a(struct rtw_adapter *Adapter, u8 *mBratesOS) -{ - u8 i; - u8 rate; - - /* 1M, 2M, 5.5M, 11M, 6M, 12M, 24M are mandatory. */ - for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) { - rate = mBratesOS[i] & 0x7f; - switch (rate) { - case IEEE80211_CCK_RATE_1MB: - case IEEE80211_CCK_RATE_2MB: - case IEEE80211_CCK_RATE_5MB: - case IEEE80211_CCK_RATE_11MB: - case IEEE80211_OFDM_RATE_6MB: - case IEEE80211_OFDM_RATE_12MB: - case IEEE80211_OFDM_RATE_24MB: - mBratesOS[i] |= IEEE80211_BASIC_RATE_MASK; - break; - default: - break; - } - } -} - -void Update23aTblForSoftAP(u8 *bssrateset, u32 bssratelen) -{ - u8 i; - u8 rate; - - for (i = 0; i < bssratelen; i++) { - rate = bssrateset[i] & 0x7f; - switch (rate) { - case IEEE80211_CCK_RATE_1MB: - case IEEE80211_CCK_RATE_2MB: - case IEEE80211_CCK_RATE_5MB: - case IEEE80211_CCK_RATE_11MB: - bssrateset[i] |= IEEE80211_BASIC_RATE_MASK; - break; - } - } -} - -inline u8 rtw_get_oper_ch23a(struct rtw_adapter *adapter) -{ - return adapter_to_dvobj(adapter)->oper_channel; -} - -inline void rtw_set_oper_ch23a(struct rtw_adapter *adapter, u8 ch) -{ - adapter_to_dvobj(adapter)->oper_channel = ch; -} - -inline void rtw_set_oper_bw23a(struct rtw_adapter *adapter, u8 bw) -{ - adapter_to_dvobj(adapter)->oper_bwmode = bw; -} - -inline void rtw_set_oper_ch23aoffset23a(struct rtw_adapter *adapter, u8 offset) -{ - adapter_to_dvobj(adapter)->oper_ch_offset = offset; -} - -void SelectChannel23a(struct rtw_adapter *padapter, unsigned char channel) -{ - mutex_lock(&adapter_to_dvobj(padapter)->setch_mutex); - - /* saved channel info */ - rtw_set_oper_ch23a(padapter, channel); - - PHY_SwChnl8723A(padapter, channel); - - mutex_unlock(&adapter_to_dvobj(padapter)->setch_mutex); -} - -static void set_bwmode(struct rtw_adapter *padapter, unsigned short bwmode, - unsigned char channel_offset) -{ - mutex_lock(&adapter_to_dvobj(padapter)->setbw_mutex); - - /* saved bw info */ - rtw_set_oper_bw23a(padapter, bwmode); - rtw_set_oper_ch23aoffset23a(padapter, channel_offset); - - PHY_SetBWMode23a8723A(padapter, (enum ht_channel_width)bwmode, - channel_offset); - - mutex_unlock(&adapter_to_dvobj(padapter)->setbw_mutex); -} - -void set_channel_bwmode23a(struct rtw_adapter *padapter, unsigned char channel, - unsigned char channel_offset, unsigned short bwmode) -{ - u8 center_ch; - - if (bwmode == HT_CHANNEL_WIDTH_20 || - channel_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) { - /* SelectChannel23a(padapter, channel); */ - center_ch = channel; - } else { - /* switch to the proper channel */ - if (channel_offset == HAL_PRIME_CHNL_OFFSET_LOWER) { - /* SelectChannel23a(padapter, channel + 2); */ - center_ch = channel + 2; - } else { - /* SelectChannel23a(padapter, channel - 2); */ - center_ch = channel - 2; - } - } - - /* set Channel */ - mutex_lock(&adapter_to_dvobj(padapter)->setch_mutex); - - /* saved channel/bw info */ - rtw_set_oper_ch23a(padapter, channel); - rtw_set_oper_bw23a(padapter, bwmode); - rtw_set_oper_ch23aoffset23a(padapter, channel_offset); - - PHY_SwChnl8723A(padapter, center_ch); /* set center channel */ - - mutex_unlock(&adapter_to_dvobj(padapter)->setch_mutex); - - set_bwmode(padapter, bwmode, channel_offset); -} - -inline u8 *get_my_bssid23a(struct wlan_bssid_ex *pnetwork) -{ - return pnetwork->MacAddress; -} - -bool is_client_associated_to_ap23a(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext; - struct mlme_ext_info *pmlmeinfo; - - if (!padapter) - return false; - - pmlmeext = &padapter->mlmeextpriv; - pmlmeinfo = &pmlmeext->mlmext_info; - - if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS && - (pmlmeinfo->state & 0x03) == MSR_INFRA) - return true; - else - return false; -} - -bool is_client_associated_to_ibss23a(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS && - (pmlmeinfo->state & 0x03) == MSR_ADHOC) - return true; - else - return false; -} - -bool is_IBSS_empty23a(struct rtw_adapter *padapter) -{ - unsigned int i; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) { - if (pmlmeinfo->FW_sta_info[i].status == 1) - return false; - } - - return true; -} - -unsigned int decide_wait_for_beacon_timeout23a(unsigned int bcn_interval) -{ - if ((bcn_interval << 2) < WAIT_FOR_BCN_TO_MIN) - return WAIT_FOR_BCN_TO_MIN; - else if ((bcn_interval << 2) > WAIT_FOR_BCN_TO_MAX) - return WAIT_FOR_BCN_TO_MAX; - else - return bcn_interval << 2; -} - -void clear_cam_entry23a(struct rtw_adapter *padapter, u8 entry) -{ - unsigned char null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - - unsigned char null_key[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00}; - - rtl8723a_cam_write(padapter, entry, 0, null_sta, null_key); -} - -int allocate_fw_sta_entry23a(struct rtw_adapter *padapter) -{ - unsigned int mac_id; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - for (mac_id = IBSS_START_MAC_ID; mac_id < NUM_STA; mac_id++) { - if (pmlmeinfo->FW_sta_info[mac_id].status == 0) { - pmlmeinfo->FW_sta_info[mac_id].status = 1; - pmlmeinfo->FW_sta_info[mac_id].retry = 0; - break; - } - } - - return mac_id; -} - -void flush_all_cam_entry23a(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - rtl8723a_cam_invalidate_all(padapter); - - memset(pmlmeinfo->FW_sta_info, 0, sizeof(pmlmeinfo->FW_sta_info)); -} - -int WMM_param_handler23a(struct rtw_adapter *padapter, const u8 *p) -{ - /* struct registry_priv *pregpriv = &padapter->registrypriv; */ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (pmlmepriv->qos_option == 0) { - pmlmeinfo->WMM_enable = 0; - return _FAIL; - } - - pmlmeinfo->WMM_enable = 1; - memcpy(&pmlmeinfo->WMM_param, p + 2 + 6, - sizeof(struct WMM_para_element)); - return true; -} - -void WMMOnAssocRsp23a(struct rtw_adapter *padapter) -{ - u8 ACI, ACM, AIFS, ECWMin, ECWMax, aSifsTime; - u8 acm_mask; - u16 TXOP; - u32 acParm, i; - u32 edca[4], inx[4]; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct registry_priv *pregpriv = &padapter->registrypriv; - - if (pmlmeinfo->WMM_enable == 0) { - padapter->mlmepriv.acm_mask = 0; - return; - } - - acm_mask = 0; - - if (pmlmeext->cur_wireless_mode == WIRELESS_11B) - aSifsTime = 10; - else - aSifsTime = 16; - - for (i = 0; i < 4; i++) { - ACI = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN >> 5) & 0x03; - ACM = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN >> 4) & 0x01; - - /* AIFS = AIFSN * slot time + SIFS - r2t phy delay */ - AIFS = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN & 0x0f) * - pmlmeinfo->slotTime + aSifsTime; - - ECWMin = pmlmeinfo->WMM_param.ac_param[i].CW & 0x0f; - ECWMax = (pmlmeinfo->WMM_param.ac_param[i].CW & 0xf0) >> 4; - TXOP = le16_to_cpu(pmlmeinfo->WMM_param.ac_param[i].TXOP_limit); - - acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16); - - switch (ACI) { - case 0x0: - rtl8723a_set_ac_param_be(padapter, acParm); - acm_mask |= (ACM? BIT(1):0); - edca[XMIT_BE_QUEUE] = acParm; - break; - case 0x1: - rtl8723a_set_ac_param_bk(padapter, acParm); - /* acm_mask |= (ACM? BIT(0):0); */ - edca[XMIT_BK_QUEUE] = acParm; - break; - case 0x2: - rtl8723a_set_ac_param_vi(padapter, acParm); - acm_mask |= (ACM? BIT(2):0); - edca[XMIT_VI_QUEUE] = acParm; - break; - case 0x3: - rtl8723a_set_ac_param_vo(padapter, acParm); - acm_mask |= (ACM? BIT(3):0); - edca[XMIT_VO_QUEUE] = acParm; - break; - } - - DBG_8723A("WMM(%x): %x, %x\n", ACI, ACM, acParm); - } - - if (padapter->registrypriv.acm_method == 1) - rtl8723a_set_acm_ctrl(padapter, acm_mask); - else - padapter->mlmepriv.acm_mask = acm_mask; - - inx[0] = 0; inx[1] = 1; inx[2] = 2; inx[3] = 3; - - if (pregpriv->wifi_spec == 1) { - u32 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; - } - } - } - } - - for (i = 0; i<4; i++) { - pxmitpriv->wmm_para_seq[i] = inx[i]; - DBG_8723A("wmm_para_seq(%d): %d\n", i, - pxmitpriv->wmm_para_seq[i]); - } -} - -static void bwmode_update_check(struct rtw_adapter *padapter, const u8 *p) -{ - struct ieee80211_ht_operation *pHT_info; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - unsigned char new_bwmode; - unsigned char new_ch_offset; - - if (!p) - return; - if (!phtpriv->ht_option) - return; - if (p[1] != sizeof(struct ieee80211_ht_operation)) - return; - - pHT_info = (struct ieee80211_ht_operation *)(p + 2); - - if ((pHT_info->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) && - pregistrypriv->cbw40_enable) { - new_bwmode = HT_CHANNEL_WIDTH_40; - - switch (pHT_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET){ - case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: - new_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER; - break; - case IEEE80211_HT_PARAM_CHA_SEC_BELOW: - new_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER; - break; - default: - new_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - break; - } - } else { - new_bwmode = HT_CHANNEL_WIDTH_20; - new_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - } - - if (new_bwmode != pmlmeext->cur_bwmode || - new_ch_offset != pmlmeext->cur_ch_offset) { - pmlmeinfo->bwmode_updated = true; - - pmlmeext->cur_bwmode = new_bwmode; - pmlmeext->cur_ch_offset = new_ch_offset; - - /* update HT info also */ - HT_info_handler23a(padapter, p); - } else - pmlmeinfo->bwmode_updated = false; - - if (pmlmeinfo->bwmode_updated) { - struct sta_info *psta; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - struct sta_priv *pstapriv = &padapter->stapriv; - - /* set_channel_bwmode23a(padapter, pmlmeext->cur_channel, - pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */ - - /* update ap's stainfo */ - psta = rtw_get_stainfo23a(pstapriv, cur_network->MacAddress); - if (psta) { - struct ht_priv *phtpriv_sta = &psta->htpriv; - - if (phtpriv_sta->ht_option) { - /* bwmode */ - phtpriv_sta->bwmode = pmlmeext->cur_bwmode; - phtpriv_sta->ch_offset = - pmlmeext->cur_ch_offset; - } else { - phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_20; - phtpriv_sta->ch_offset = - HAL_PRIME_CHNL_OFFSET_DONT_CARE; - } - } - } -} - -void HT_caps_handler23a(struct rtw_adapter *padapter, const u8 *p) -{ - unsigned int i; - u8 rf_type; - u8 max_AMPDU_len, min_MPDU_spacing; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - struct ieee80211_ht_cap *cap; - u8 *dstcap; - - if (!p) - return; - - if (!phtpriv->ht_option) - return; - - pmlmeinfo->HT_caps_enable = 1; - - cap = &pmlmeinfo->ht_cap; - dstcap = (u8 *)cap; - for (i = 0; i < p[1]; i++) { - if (i != 2) { - dstcap[i] &= p[i + 2]; - } else { - /* modify from fw by Thomas 2010/11/17 */ - if ((cap->ampdu_params_info & - IEEE80211_HT_AMPDU_PARM_FACTOR) > - (p[i + 2] & IEEE80211_HT_AMPDU_PARM_FACTOR)) - max_AMPDU_len = p[i + 2] & - IEEE80211_HT_AMPDU_PARM_FACTOR; - else - max_AMPDU_len = cap->ampdu_params_info & - IEEE80211_HT_AMPDU_PARM_FACTOR; - - if ((cap->ampdu_params_info & - IEEE80211_HT_AMPDU_PARM_DENSITY) > - (p[i + 2] & IEEE80211_HT_AMPDU_PARM_DENSITY)) - min_MPDU_spacing = cap->ampdu_params_info & - IEEE80211_HT_AMPDU_PARM_DENSITY; - else - min_MPDU_spacing = p[i + 2] & - IEEE80211_HT_AMPDU_PARM_DENSITY; - - cap->ampdu_params_info = - max_AMPDU_len | min_MPDU_spacing; - } - } - - rf_type = rtl8723a_get_rf_type(padapter); - - /* update the MCS rates */ - for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) { - if (rf_type == RF_1T1R || rf_type == RF_1T2R) - cap->mcs.rx_mask[i] &= MCS_rate_1R23A[i]; - else - cap->mcs.rx_mask[i] &= MCS_rate_2R23A[i]; - } -} - -void HT_info_handler23a(struct rtw_adapter *padapter, const u8 *p) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - - if (!p) - return; - - if (!phtpriv->ht_option) - return; - - if (p[1] != sizeof(struct ieee80211_ht_operation)) - return; - - pmlmeinfo->HT_info_enable = 1; - memcpy(&pmlmeinfo->HT_info, p + 2, p[1]); -} - -void HTOnAssocRsp23a(struct rtw_adapter *padapter) -{ - unsigned char max_AMPDU_len; - unsigned char min_MPDU_spacing; - /* struct registry_priv *pregpriv = &padapter->registrypriv; */ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - DBG_8723A("%s\n", __func__); - - if (pmlmeinfo->HT_info_enable && pmlmeinfo->HT_caps_enable) - pmlmeinfo->HT_enable = 1; - else { - pmlmeinfo->HT_enable = 0; - /* set_channel_bwmode23a(padapter, pmlmeext->cur_channel, - pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */ - return; - } - - /* handle A-MPDU parameter field */ - /* - AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k - AMPDU_para [4:2]:Min MPDU Start Spacing - */ - max_AMPDU_len = pmlmeinfo->ht_cap.ampdu_params_info & - IEEE80211_HT_AMPDU_PARM_FACTOR; - - min_MPDU_spacing = - (pmlmeinfo->ht_cap.ampdu_params_info & - IEEE80211_HT_AMPDU_PARM_DENSITY) >> 2; - - rtl8723a_set_ampdu_min_space(padapter, min_MPDU_spacing); - rtl8723a_set_ampdu_factor(padapter, max_AMPDU_len); -} - -void ERP_IE_handler23a(struct rtw_adapter *padapter, const u8 *p) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (p[1] > 1) - return; - - pmlmeinfo->ERP_enable = 1; - memcpy(&pmlmeinfo->ERP_IE, p + 2, p[1]); -} - -void VCS_update23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - struct registry_priv *pregpriv = &padapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - switch (pregpriv->vrtl_carrier_sense) { /* 0:off 1:on 2:auto */ - case 0: /* off */ - psta->rtsen = 0; - psta->cts2self = 0; - break; - case 1: /* on */ - if (pregpriv->vcs_type == RTS_CTS) { - psta->rtsen = 1; - psta->cts2self = 0; - } else { - psta->rtsen = 0; - psta->cts2self = 1; - } - break; - case 2: /* auto */ - default: - if (pmlmeinfo->ERP_enable && pmlmeinfo->ERP_IE & BIT(1)) { - if (pregpriv->vcs_type == RTS_CTS) { - psta->rtsen = 1; - psta->cts2self = 0; - } else { - psta->rtsen = 0; - psta->cts2self = 1; - } - } else { - psta->rtsen = 0; - psta->cts2self = 0; - } - break; - } -} - -int rtw_check_bcn_info23a(struct rtw_adapter *Adapter, - struct ieee80211_mgmt *mgmt, u32 pkt_len) -{ - struct wlan_network *cur_network = &Adapter->mlmepriv.cur_network; - struct ieee80211_ht_operation *pht_info; - unsigned short val16; - u8 crypto, bcn_channel; - int group_cipher = 0, pairwise_cipher = 0, is_8021x = 0, r; - int pie_len, ssid_len, privacy; - const u8 *p, *ssid; - - if (!is_client_associated_to_ap23a(Adapter)) - return _SUCCESS; - - if (unlikely(!ieee80211_is_beacon(mgmt->frame_control))) { - printk(KERN_WARNING "%s: received a non beacon frame!\n", - __func__); - return _FAIL; - } - - if (!ether_addr_equal(cur_network->network.MacAddress, mgmt->bssid)) { - DBG_8723A("%s: linked but recv other bssid bcn %pM %pM\n", - __func__, mgmt->bssid, - cur_network->network.MacAddress); - return _FAIL; - } - - /* check bw and channel offset */ - /* parsing HT_CAP_IE */ - pie_len = pkt_len - offsetof(struct ieee80211_mgmt, u.beacon.variable); - - /* Checking for channel */ - p = cfg80211_find_ie(WLAN_EID_DS_PARAMS, mgmt->u.beacon.variable, - pie_len); - if (p) - bcn_channel = p[2]; - else { - /* In 5G, some ap do not have DSSET IE checking HT - info for channel */ - p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, - mgmt->u.beacon.variable, pie_len); - - if (p && p[1] > 0) { - pht_info = (struct ieee80211_ht_operation *)(p + 2); - bcn_channel = pht_info->primary_chan; - } else { /* we don't find channel IE, so don't check it */ - DBG_8723A("Oops: %s we don't find channel IE, so don't " - "check it\n", __func__); - bcn_channel = Adapter->mlmeextpriv.cur_channel; - } - } - if (bcn_channel != Adapter->mlmeextpriv.cur_channel) { - DBG_8723A("%s beacon channel:%d cur channel:%d disconnect\n", - __func__, bcn_channel, - Adapter->mlmeextpriv.cur_channel); - goto _mismatch; - } - - /* checking SSID */ - p = cfg80211_find_ie(WLAN_EID_SSID, mgmt->u.beacon.variable, pie_len); - if (p && p[1]) { - ssid = p + 2; - ssid_len = p[1]; - } else { - DBG_8723A("%s marc: cannot find SSID for survey event\n", - __func__); - ssid = NULL; - ssid_len = 0; - } - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "%s bssid.Ssid.Ssid:%s bssid.Ssid.SsidLength:%d cur_network->network.Ssid.Ssid:%s len:%d\n", - __func__, ssid, ssid_len, cur_network->network.Ssid.ssid, - cur_network->network.Ssid.ssid_len); - - if (ssid_len != cur_network->network.Ssid.ssid_len || ssid_len > 32 || - (ssid_len && - memcmp(ssid, cur_network->network.Ssid.ssid, ssid_len))) { - DBG_8723A("%s(), SSID is not match return FAIL\n", __func__); - goto _mismatch; - } - - /* check encryption info */ - val16 = le16_to_cpu(mgmt->u.beacon.capab_info); - - if (val16 & WLAN_CAPABILITY_PRIVACY) - privacy = 1; - else - 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, privacy); - if (cur_network->network.Privacy != privacy) { - DBG_8723A("%s(), privacy is not match return FAIL\n", __func__); - goto _mismatch; - } - - p = cfg80211_find_ie(WLAN_EID_RSN, mgmt->u.beacon.variable, pie_len); - if (p && p[1]) { - crypto = ENCRYP_PROTOCOL_WPA2; - if (p && p[1]) { - r = rtw_parse_wpa2_ie23a(p, p[1] + 2, &group_cipher, - &pairwise_cipher, &is_8021x); - if (r == _SUCCESS) - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "%s pnetwork->pairwise_cipher: %d, pnetwork->group_cipher: %d, is_802x : %d\n", - __func__, pairwise_cipher, - group_cipher, is_8021x); - } - } else { - p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPA, - mgmt->u.beacon.variable, pie_len); - if (p && p[1]) { - crypto = ENCRYP_PROTOCOL_WPA; - r = rtw_parse_wpa_ie23a(p, p[1] + 2, &group_cipher, - &pairwise_cipher, &is_8021x); - if (r == _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); - } else { - if (privacy) - crypto = ENCRYP_PROTOCOL_WEP; - else - crypto = ENCRYP_PROTOCOL_OPENSYS; - } - } - - if (cur_network->BcnInfo.encryp_protocol != crypto) { - DBG_8723A("%s(): encryption mismatch, return FAIL\n", __func__); - goto _mismatch; - } - - if (crypto == ENCRYP_PROTOCOL_WPA || crypto == ENCRYP_PROTOCOL_WPA2) { - 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_8723A("%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); - goto _mismatch; - } - - if (is_8021x != cur_network->BcnInfo.is_8021x) { - DBG_8723A("%s authentication is not match, return " - "FAIL\n", __func__); - goto _mismatch; - } - } - - return _SUCCESS; - -_mismatch: - - return _FAIL; -} - -void update_beacon23a_info(struct rtw_adapter *padapter, - struct ieee80211_mgmt *mgmt, - uint pkt_len, struct sta_info *psta) -{ - unsigned int len; - const u8 *p; - - len = pkt_len - offsetof(struct ieee80211_mgmt, u.beacon.variable); - - p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, mgmt->u.beacon.variable, - len); - if (p) - bwmode_update_check(padapter, p); - - p = cfg80211_find_ie(WLAN_EID_ERP_INFO, mgmt->u.beacon.variable, len); - if (p) { - ERP_IE_handler23a(padapter, p); - VCS_update23a(padapter, psta); - } -} - -bool is_ap_in_tkip23a(struct rtw_adapter *padapter) -{ - u32 i; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - const u8 *p; - - if (cur_network->capability & WLAN_CAPABILITY_PRIVACY) { - for (i = 0; i < pmlmeinfo->network.IELength;) { - p = pmlmeinfo->network.IEs + i; - - switch (p[0]) { - case WLAN_EID_VENDOR_SPECIFIC: - if (!memcmp(p + 2, RTW_WPA_OUI23A_TYPE, 4) && - !memcmp(p + 2 + 12, WPA_TKIP_CIPHER, 4)) - return true; - break; - case WLAN_EID_RSN: - if (!memcmp(p + 2 + 8, RSN_TKIP_CIPHER, 4)) - return true; - break; - default: - break; - } - i += (p[1] + 2); - } - return false; - } else - return false; -} - -bool should_forbid_n_rate23a(struct rtw_adapter *padapter) -{ - u32 i; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *cur_network = &pmlmepriv->cur_network.network; - const u8 *p; - - if (cur_network->capability & WLAN_CAPABILITY_PRIVACY) { - for (i = 0; i < cur_network->IELength;) { - p = cur_network->IEs + i; - - switch (p[0]) { - case WLAN_EID_VENDOR_SPECIFIC: - if (!memcmp(p + 2, RTW_WPA_OUI23A_TYPE, 4) && - (!memcmp(p + 2 + 12, - WPA_CIPHER_SUITE_CCMP23A, 4) || - !memcmp(p + 2 + 16, - WPA_CIPHER_SUITE_CCMP23A, 4))) - return false; - break; - case WLAN_EID_RSN: - if (!memcmp(p + 2 + 8, - RSN_CIPHER_SUITE_CCMP23A, 4) || - !memcmp(p + 2 + 12, - RSN_CIPHER_SUITE_CCMP23A, 4)) - return false; - default: - break; - } - - i += (p[1] + 2); - } - return true; - } else { - return false; - } -} - -bool is_ap_in_wep23a(struct rtw_adapter *padapter) -{ - u32 i; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - const u8 *p; - - if (cur_network->capability & WLAN_CAPABILITY_PRIVACY) { - for (i = 0; i < pmlmeinfo->network.IELength;) { - p = pmlmeinfo->network.IEs + i; - - switch (p[0]) { - case WLAN_EID_VENDOR_SPECIFIC: - if (!memcmp(p + 2, RTW_WPA_OUI23A_TYPE, 4)) - return false; - break; - case WLAN_EID_RSN: - return false; - - default: - break; - } - - i += (p[1] + 2); - } - - return true; - } else - return false; -} - -static int wifirate2_ratetbl_inx23a(unsigned char rate) -{ - int inx = 0; - - rate = rate & 0x7f; - - switch (rate) { - case 54*2: - inx = 11; - break; - case 48*2: - inx = 10; - break; - case 36*2: - inx = 9; - break; - case 24*2: - inx = 8; - break; - case 18*2: - inx = 7; - break; - case 12*2: - inx = 6; - break; - case 9*2: - inx = 5; - break; - case 6*2: - inx = 4; - break; - case 11*2: - inx = 3; - break; - case 11: - inx = 2; - break; - case 2*2: - inx = 1; - break; - case 1*2: - inx = 0; - break; - } - return inx; -} - -unsigned int update_basic_rate23a(unsigned char *ptn, unsigned int ptn_sz) -{ - unsigned int i, num_of_rate; - unsigned int mask = 0; - - num_of_rate = (ptn_sz > NumRates)? NumRates: ptn_sz; - - for (i = 0; i < num_of_rate; i++) { - if ((*(ptn + i)) & 0x80) - mask |= 0x1 << wifirate2_ratetbl_inx23a(*(ptn + i)); - } - return mask; -} - -unsigned int update_supported_rate23a(unsigned char *ptn, unsigned int ptn_sz) -{ - unsigned int i, num_of_rate; - unsigned int mask = 0; - - num_of_rate = (ptn_sz > NumRates) ? NumRates : ptn_sz; - - for (i = 0; i < num_of_rate; i++) - mask |= 0x1 << wifirate2_ratetbl_inx23a(*(ptn + i)); - return mask; -} - -unsigned int update_MSC_rate23a(struct ieee80211_ht_cap *pHT_caps) -{ - unsigned int mask; - - mask = pHT_caps->mcs.rx_mask[0] << 12 | - pHT_caps->mcs.rx_mask[1] << 20; - - return mask; -} - -int support_short_GI23a(struct rtw_adapter *padapter, - struct ieee80211_ht_cap *pHT_caps) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - unsigned char bit_offset; - - if (!pmlmeinfo->HT_enable) - return _FAIL; - if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_RALINK) - return _FAIL; - bit_offset = (pmlmeext->cur_bwmode & HT_CHANNEL_WIDTH_40)? 6: 5; - - if (pHT_caps->cap_info & cpu_to_le16(0x1 << bit_offset)) - return _SUCCESS; - else - return _FAIL; -} - -unsigned char get_highest_rate_idx23a(u32 mask) -{ - int i; - unsigned char rate_idx = 0; - - for (i = 27; i >= 0; i--) { - if (mask & BIT(i)) { - rate_idx = i; - break; - } - } - return rate_idx; -} - -void Update_RA_Entry23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - rtw_hal_update_ra_mask23a(psta, 0); -} - -static void enable_rate_adaptive(struct rtw_adapter *padapter, - struct sta_info *psta) -{ - Update_RA_Entry23a(padapter, psta); -} - -void set_sta_rate23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - /* rate adaptive */ - enable_rate_adaptive(padapter, psta); -} - -/* Update RRSR and Rate for USERATE */ -void update_tx_basic_rate23a(struct rtw_adapter *padapter, u8 wirelessmode) -{ - unsigned char supported_rates[NDIS_802_11_LENGTH_RATES_EX]; - - memset(supported_rates, 0, NDIS_802_11_LENGTH_RATES_EX); - - if (wirelessmode == WIRELESS_11B) { - memcpy(supported_rates, rtw_basic_rate_cck, 4); - } else if (wirelessmode & WIRELESS_11B) { - memcpy(supported_rates, rtw_basic_rate_mix, 7); - } else { - memcpy(supported_rates, rtw_basic_rate_ofdm, 3); - } - - if (wirelessmode & WIRELESS_11B) - update_mgnt_tx_rate23a(padapter, IEEE80211_CCK_RATE_1MB); - else - update_mgnt_tx_rate23a(padapter, IEEE80211_OFDM_RATE_6MB); - - HalSetBrateCfg23a(padapter, supported_rates); -} - -unsigned char check_assoc_AP23a(u8 *pframe, uint len) -{ - int i; - u8 epigram_vendor_flag; - u8 ralink_vendor_flag; - const u8 *p; - - epigram_vendor_flag = 0; - ralink_vendor_flag = 0; - - for (i = 0; i < len;) { - p = pframe + i; - - switch (p[0]) { - case WLAN_EID_VENDOR_SPECIFIC: - if (!memcmp(p + 2, ARTHEROS_OUI1, 3) || - !memcmp(p + 2, ARTHEROS_OUI2, 3)) { - DBG_8723A("link to Artheros AP\n"); - return HT_IOT_PEER_ATHEROS; - } else if (!memcmp(p + 2, BROADCOM_OUI1, 3) || - !memcmp(p + 2, BROADCOM_OUI2, 3)) { - DBG_8723A("link to Broadcom AP\n"); - return HT_IOT_PEER_BROADCOM; - } else if (!memcmp(p + 2, MARVELL_OUI, 3)) { - DBG_8723A("link to Marvell AP\n"); - return HT_IOT_PEER_MARVELL; - } else if (!memcmp(p + 2, RALINK_OUI, 3)) { - if (!ralink_vendor_flag) - ralink_vendor_flag = 1; - else { - DBG_8723A("link to Ralink AP\n"); - return HT_IOT_PEER_RALINK; - } - } else if (!memcmp(p + 2, CISCO_OUI, 3)) { - DBG_8723A("link to Cisco AP\n"); - return HT_IOT_PEER_CISCO; - } else if (!memcmp(p + 2, REALTEK_OUI, 3)) { - DBG_8723A("link to Realtek 96B\n"); - return HT_IOT_PEER_REALTEK; - } else if (!memcmp(p + 2, AIRGOCAP_OUI, 3)) { - DBG_8723A("link to Airgo Cap\n"); - return HT_IOT_PEER_AIRGO; - } else if (!memcmp(p + 2, EPIGRAM_OUI, 3)) { - epigram_vendor_flag = 1; - if (ralink_vendor_flag) { - DBG_8723A("link to Tenda W311R AP\n"); - return HT_IOT_PEER_TENDA; - } else - DBG_8723A("Capture EPIGRAM_OUI\n"); - } else - break; - default: - break; - } - - i += (p[1] + 2); - } - - if (ralink_vendor_flag && !epigram_vendor_flag) { - DBG_8723A("link to Ralink AP\n"); - return HT_IOT_PEER_RALINK; - } else if (ralink_vendor_flag && epigram_vendor_flag) { - DBG_8723A("link to Tenda W311R AP\n"); - return HT_IOT_PEER_TENDA; - } else { - DBG_8723A("link to new AP\n"); - return HT_IOT_PEER_UNKNOWN; - } -} - -void update_IOT_info23a(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - switch (pmlmeinfo->assoc_AP_vendor) { - case HT_IOT_PEER_MARVELL: - pmlmeinfo->turboMode_cts2self = 1; - pmlmeinfo->turboMode_rtsen = 0; - break; - case HT_IOT_PEER_RALINK: - pmlmeinfo->turboMode_cts2self = 0; - pmlmeinfo->turboMode_rtsen = 1; - /* disable high power */ - rtl8723a_odm_support_ability_clr(padapter, (u32) - ~DYNAMIC_BB_DYNAMIC_TXPWR); - break; - case HT_IOT_PEER_REALTEK: - /* rtw_write16(padapter, 0x4cc, 0xffff); */ - /* rtw_write16(padapter, 0x546, 0x01c0); */ - /* disable high power */ - rtl8723a_odm_support_ability_clr(padapter, (u32) - ~DYNAMIC_BB_DYNAMIC_TXPWR); - break; - default: - pmlmeinfo->turboMode_cts2self = 0; - pmlmeinfo->turboMode_rtsen = 1; - break; - } -} - -void update_capinfo23a(struct rtw_adapter *Adapter, u16 updateCap) -{ - struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (updateCap & cShortPreamble) { - /* Short Preamble */ - if (pmlmeinfo->preamble_mode != PREAMBLE_SHORT) { - /* PREAMBLE_LONG or PREAMBLE_AUTO */ - pmlmeinfo->preamble_mode = PREAMBLE_SHORT; - rtl8723a_ack_preamble(Adapter, true); - } - } else { /* Long Preamble */ - if (pmlmeinfo->preamble_mode != PREAMBLE_LONG) { - /* PREAMBLE_SHORT or PREAMBLE_AUTO */ - pmlmeinfo->preamble_mode = PREAMBLE_LONG; - rtl8723a_ack_preamble(Adapter, false); - } - } - if (updateCap & cIBSS) { - /* Filen: See 802.11-2007 p.91 */ - pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME; - } else { - /* Filen: See 802.11-2007 p.90 */ - if (pmlmeext->cur_wireless_mode & - (WIRELESS_11G | WIRELESS_11_24N)) { - if (updateCap & cShortSlotTime) { /* Short Slot Time */ - if (pmlmeinfo->slotTime != SHORT_SLOT_TIME) - pmlmeinfo->slotTime = SHORT_SLOT_TIME; - } else { /* Long Slot Time */ - if (pmlmeinfo->slotTime != NON_SHORT_SLOT_TIME) - pmlmeinfo->slotTime = - NON_SHORT_SLOT_TIME; - } - } else if (pmlmeext->cur_wireless_mode & - (WIRELESS_11A | WIRELESS_11_5N)) { - pmlmeinfo->slotTime = SHORT_SLOT_TIME; - } else { - /* B Mode */ - pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME; - } - } - rtl8723a_set_slot_time(Adapter, pmlmeinfo->slotTime); -} - -void update_wireless_mode23a(struct rtw_adapter *padapter) -{ - int ratelen, network_type = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - unsigned char *rate = cur_network->SupportedRates; - - ratelen = rtw_get_rateset_len23a(cur_network->SupportedRates); - - if ((pmlmeinfo->HT_info_enable) && (pmlmeinfo->HT_caps_enable)) - pmlmeinfo->HT_enable = 1; - - if (pmlmeext->cur_channel > 14) { - if (pmlmeinfo->HT_enable) - network_type = WIRELESS_11_5N; - network_type |= WIRELESS_11A; - } else { - if (pmlmeinfo->HT_enable) - network_type = WIRELESS_11_24N; - - if (cckratesonly_included23a(rate, ratelen) == true) - network_type |= WIRELESS_11B; - else if (cckrates_included23a(rate, ratelen) == true) - network_type |= WIRELESS_11BG; - else - network_type |= WIRELESS_11G; - } - - pmlmeext->cur_wireless_mode = - network_type & padapter->registrypriv.wireless_mode; - - /* 0x0808 -> for CCK, 0x0a0a -> for OFDM */ - /* change this value if having IOT issues. */ - rtl8723a_set_resp_sifs(padapter, 0x08, 0x08, 0x0a, 0x0a); - - if (pmlmeext->cur_wireless_mode & WIRELESS_11B) - update_mgnt_tx_rate23a(padapter, IEEE80211_CCK_RATE_1MB); - else - update_mgnt_tx_rate23a(padapter, IEEE80211_OFDM_RATE_6MB); -} - -void update_bmc_sta_support_rate23a(struct rtw_adapter *padapter, u32 mac_id) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (pmlmeext->cur_wireless_mode & WIRELESS_11B) { - /* Only B, B/G, and B/G/N AP could use CCK rate */ - memcpy((pmlmeinfo->FW_sta_info[mac_id].SupportedRates), - rtw_basic_rate_cck, 4); - } else { - memcpy(pmlmeinfo->FW_sta_info[mac_id].SupportedRates, - rtw_basic_rate_ofdm, 3); - } -} - -int update_sta_support_rate23a(struct rtw_adapter *padapter, u8 *pvar_ie, - uint var_ie_len, int cam_idx) -{ - int supportRateNum = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - const u8 *p; - - p = cfg80211_find_ie(WLAN_EID_SUPP_RATES, pvar_ie, var_ie_len); - if (!p) - return _FAIL; - - memcpy(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates, p + 2, p[1]); - supportRateNum = p[1]; - - p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, pvar_ie, var_ie_len); - if (p) - memcpy(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates + - supportRateNum, p + 2, p[1]); - return _SUCCESS; -} - -void process_addba_req23a(struct rtw_adapter *padapter, - u8 *paddba_req, u8 *addr) -{ - struct sta_info *psta; - u16 tid, start_seq, param; - struct recv_reorder_ctrl *preorder_ctrl; - struct sta_priv *pstapriv = &padapter->stapriv; - struct ADDBA_request *preq = (struct ADDBA_request *)paddba_req; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - psta = rtw_get_stainfo23a(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; - - preorder_ctrl = &psta->recvreorder_ctrl[tid]; - - preorder_ctrl->indicate_seq = 0xffff; - - preorder_ctrl->enable = (pmlmeinfo->bAcceptAddbaReq == true) ? - true : false; - } -} diff --git a/drivers/staging/rtl8723au/core/rtw_xmit.c b/drivers/staging/rtl8723au/core/rtw_xmit.c deleted file mode 100644 index 003576d..0000000 --- a/drivers/staging/rtl8723au/core/rtw_xmit.c +++ /dev/null @@ -1,2337 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RTW_XMIT_C_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <wifi.h> -#include <osdep_intf.h> -#include <linux/ip.h> -#include <usb_ops.h> -#include <rtl8723a_xmit.h> - -static void _init_txservq(struct tx_servq *ptxservq) -{ - - INIT_LIST_HEAD(&ptxservq->tx_pending); - _rtw_init_queue23a(&ptxservq->sta_pending); - ptxservq->qcnt = 0; - -} - -void _rtw_init_sta_xmit_priv23a(struct sta_xmit_priv *psta_xmitpriv) -{ - - spin_lock_init(&psta_xmitpriv->lock); - - /* for (i = 0 ; i < MAX_NUMBLKS; i++) */ - /* _init_txservq(&psta_xmitpriv->blk_q[i]); */ - - _init_txservq(&psta_xmitpriv->be_q); - _init_txservq(&psta_xmitpriv->bk_q); - _init_txservq(&psta_xmitpriv->vi_q); - _init_txservq(&psta_xmitpriv->vo_q); - INIT_LIST_HEAD(&psta_xmitpriv->legacy_dz); - INIT_LIST_HEAD(&psta_xmitpriv->apsd); - -} - -int _rtw_init_xmit_priv23a(struct xmit_priv *pxmitpriv, - struct rtw_adapter *padapter) -{ - int i; - struct xmit_buf *pxmitbuf; - struct xmit_frame *pxframe; - int res = _SUCCESS; - u32 max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ; - u32 num_xmit_extbuf = NR_XMIT_EXTBUFF; - - spin_lock_init(&pxmitpriv->lock); - spin_lock_init(&pxmitpriv->lock_sctx); - - pxmitpriv->adapter = padapter; - - _rtw_init_queue23a(&pxmitpriv->be_pending); - _rtw_init_queue23a(&pxmitpriv->bk_pending); - _rtw_init_queue23a(&pxmitpriv->vi_pending); - _rtw_init_queue23a(&pxmitpriv->vo_pending); - _rtw_init_queue23a(&pxmitpriv->bm_pending); - - _rtw_init_queue23a(&pxmitpriv->free_xmit_queue); - - for (i = 0; i < NR_XMITFRAME; i++) { - pxframe = kzalloc(sizeof(struct xmit_frame), GFP_KERNEL); - if (!pxframe) - break; - INIT_LIST_HEAD(&pxframe->list); - - pxframe->padapter = padapter; - pxframe->frame_tag = NULL_FRAMETAG; - - list_add_tail(&pxframe->list, - &pxmitpriv->free_xmit_queue.queue); - } - - pxmitpriv->free_xmitframe_cnt = i; - - pxmitpriv->frag_len = MAX_FRAG_THRESHOLD; - - /* init xmit_buf */ - _rtw_init_queue23a(&pxmitpriv->free_xmitbuf_queue); - INIT_LIST_HEAD(&pxmitpriv->xmitbuf_list); - _rtw_init_queue23a(&pxmitpriv->pending_xmitbuf_queue); - - for (i = 0; i < NR_XMITBUFF; i++) { - pxmitbuf = kzalloc(sizeof(struct xmit_buf), GFP_KERNEL); - if (!pxmitbuf) - goto fail; - INIT_LIST_HEAD(&pxmitbuf->list); - INIT_LIST_HEAD(&pxmitbuf->list2); - - pxmitbuf->padapter = padapter; - - /* Tx buf allocation may fail sometimes, so sleep and retry. */ - res = rtw_os_xmit_resource_alloc23a(padapter, pxmitbuf, - (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ)); - if (res == _FAIL) { - goto fail; - } - - list_add_tail(&pxmitbuf->list, - &pxmitpriv->free_xmitbuf_queue.queue); - list_add_tail(&pxmitbuf->list2, - &pxmitpriv->xmitbuf_list); - } - - pxmitpriv->free_xmitbuf_cnt = NR_XMITBUFF; - - /* init xframe_ext queue, the same count as extbuf */ - _rtw_init_queue23a(&pxmitpriv->free_xframe_ext_queue); - - for (i = 0; i < num_xmit_extbuf; i++) { - pxframe = kzalloc(sizeof(struct xmit_frame), GFP_KERNEL); - if (!pxframe) - break; - INIT_LIST_HEAD(&pxframe->list); - - pxframe->padapter = padapter; - pxframe->frame_tag = NULL_FRAMETAG; - - pxframe->pkt = NULL; - - pxframe->buf_addr = NULL; - pxframe->pxmitbuf = NULL; - - pxframe->ext_tag = 1; - - list_add_tail(&pxframe->list, - &pxmitpriv->free_xframe_ext_queue.queue); - } - pxmitpriv->free_xframe_ext_cnt = i; - - /* Init xmit extension buff */ - _rtw_init_queue23a(&pxmitpriv->free_xmit_extbuf_queue); - INIT_LIST_HEAD(&pxmitpriv->xmitextbuf_list); - - for (i = 0; i < num_xmit_extbuf; i++) { - pxmitbuf = kzalloc(sizeof(struct xmit_buf), GFP_KERNEL); - if (!pxmitbuf) - goto fail; - INIT_LIST_HEAD(&pxmitbuf->list); - INIT_LIST_HEAD(&pxmitbuf->list2); - - pxmitbuf->padapter = padapter; - - /* Tx buf allocation may fail sometimes, so sleep and retry. */ - res = rtw_os_xmit_resource_alloc23a(padapter, pxmitbuf, - max_xmit_extbuf_size + XMITBUF_ALIGN_SZ); - if (res == _FAIL) { - goto exit; - } - - list_add_tail(&pxmitbuf->list, - &pxmitpriv->free_xmit_extbuf_queue.queue); - list_add_tail(&pxmitbuf->list2, - &pxmitpriv->xmitextbuf_list); - } - - pxmitpriv->free_xmit_extbuf_cnt = num_xmit_extbuf; - - rtw_alloc_hwxmits23a(padapter); - rtw_init_hwxmits23a(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry); - - for (i = 0; i < 4; i ++) - pxmitpriv->wmm_para_seq[i] = i; - - pxmitpriv->ack_tx = false; - mutex_init(&pxmitpriv->ack_tx_mutex); - rtw_sctx_init23a(&pxmitpriv->ack_tx_ops, 0); - tasklet_init(&padapter->xmitpriv.xmit_tasklet, - (void(*)(unsigned long))rtl8723au_xmit_tasklet, - (unsigned long)padapter); - -exit: - - return res; -fail: - goto exit; -} - -void _rtw_free_xmit_priv23a(struct xmit_priv *pxmitpriv) -{ - struct rtw_adapter *padapter = pxmitpriv->adapter; - struct xmit_frame *pxframe, *ptmp; - struct xmit_buf *pxmitbuf, *ptmp2; - - list_for_each_entry_safe(pxframe, ptmp, - &pxmitpriv->free_xmit_queue.queue, list) { - list_del_init(&pxframe->list); - rtw_os_xmit_complete23a(padapter, pxframe); - kfree(pxframe); - } - - list_for_each_entry_safe(pxmitbuf, ptmp2, - &pxmitpriv->xmitbuf_list, list2) { - list_del_init(&pxmitbuf->list2); - rtw_os_xmit_resource_free23a(padapter, pxmitbuf); - kfree(pxmitbuf); - } - - /* free xframe_ext queue, the same count as extbuf */ - list_for_each_entry_safe(pxframe, ptmp, - &pxmitpriv->free_xframe_ext_queue.queue, - list) { - list_del_init(&pxframe->list); - rtw_os_xmit_complete23a(padapter, pxframe); - kfree(pxframe); - } - - /* free xmit extension buff */ - list_for_each_entry_safe(pxmitbuf, ptmp2, - &pxmitpriv->xmitextbuf_list, list2) { - list_del_init(&pxmitbuf->list2); - rtw_os_xmit_resource_free23a(padapter, pxmitbuf); - kfree(pxmitbuf); - } - - rtw_free_hwxmits23a(padapter); - mutex_destroy(&pxmitpriv->ack_tx_mutex); -} - -static void update_attrib_vcs_info(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe) -{ - u32 sz; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct sta_info *psta = pattrib->psta; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (pattrib->psta) { - psta = pattrib->psta; - } else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - psta = rtw_get_stainfo23a(&padapter->stapriv, &pattrib->ra[0]); - } - - if (psta == NULL) { - DBG_8723A("%s, psta == NUL\n", __func__); - return; - } - - if (!(psta->state &_FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state); - return; - } - - if (pattrib->nr_frags != 1) - sz = padapter->xmitpriv.frag_len; - else /* no frag */ - sz = pattrib->last_txcmdsz; - - /* (1) RTS_Threshold is compared to the MPDU, not MSDU. */ - /* (2) If there are more than one frag in this MSDU, only the first frag uses protection frame. */ - /* Other fragments are protected by previous fragment. */ - /* So we only need to check the length of first fragment. */ - if (pmlmeext->cur_wireless_mode < WIRELESS_11_24N || padapter->registrypriv.wifi_spec) { - if (sz > padapter->registrypriv.rts_thresh) { - pattrib->vcs_mode = RTS_CTS; - } else { - if (psta->rtsen) - pattrib->vcs_mode = RTS_CTS; - else if (psta->cts2self) - pattrib->vcs_mode = CTS_TO_SELF; - else - pattrib->vcs_mode = NONE_VCS; - } - } else { - while (true) { - /* IOT action */ - if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_ATHEROS && - pattrib->ampdu_en && - padapter->securitypriv.dot11PrivacyAlgrthm == - WLAN_CIPHER_SUITE_CCMP) { - pattrib->vcs_mode = CTS_TO_SELF; - break; - } - - /* check ERP protection */ - if (psta->rtsen || psta->cts2self) { - if (psta->rtsen) - pattrib->vcs_mode = RTS_CTS; - else if (psta->cts2self) - pattrib->vcs_mode = CTS_TO_SELF; - - break; - } - - /* check HT op mode */ - if (pattrib->ht_en) { - u8 HTOpMode = pmlmeinfo->HT_protection; - - if ((pmlmeext->cur_bwmode && (HTOpMode == 2 || HTOpMode == 3)) || - (!pmlmeext->cur_bwmode && HTOpMode == 3)) { - pattrib->vcs_mode = RTS_CTS; - break; - } - } - - /* check rts */ - if (sz > padapter->registrypriv.rts_thresh) { - pattrib->vcs_mode = RTS_CTS; - break; - } - - /* to do list: check MIMO power save condition. */ - - /* check AMPDU aggregation for TXOP */ - if (pattrib->ampdu_en) { - pattrib->vcs_mode = RTS_CTS; - break; - } - - pattrib->vcs_mode = NONE_VCS; - break; - } - } -} - -static void update_attrib_phy_info(struct pkt_attrib *pattrib, struct sta_info *psta) -{ - /*if (psta->rtsen) - pattrib->vcs_mode = RTS_CTS; - else if (psta->cts2self) - pattrib->vcs_mode = CTS_TO_SELF; - else - pattrib->vcs_mode = NONE_VCS;*/ - - pattrib->mdata = 0; - pattrib->eosp = 0; - pattrib->triggered = 0; - - /* qos_en, ht_en, init rate, , bw, ch_offset, sgi */ - pattrib->qos_en = psta->qos_option; - - pattrib->raid = psta->raid; - pattrib->ht_en = psta->htpriv.ht_option; - pattrib->bwmode = psta->htpriv.bwmode; - pattrib->ch_offset = psta->htpriv.ch_offset; - pattrib->sgi = psta->htpriv.sgi; - pattrib->ampdu_en = false; - - pattrib->retry_ctrl = false; -} - -u8 qos_acm23a(u8 acm_mask, u8 priority) -{ - u8 change_priority = priority; - - switch (priority) { - case 0: - case 3: - if (acm_mask & BIT(1)) - change_priority = 1; - break; - case 1: - case 2: - break; - case 4: - case 5: - if (acm_mask & BIT(2)) - change_priority = 0; - break; - case 6: - case 7: - if (acm_mask & BIT(3)) - change_priority = 5; - break; - default: - DBG_8723A("qos_acm23a(): invalid pattrib->priority: %d!!!\n", - priority); - change_priority = 0; - break; - } - - return change_priority; -} - -static void set_qos(struct sk_buff *skb, struct pkt_attrib *pattrib) -{ - u8 *pframe = skb->data; - struct iphdr *ip_hdr; - u8 UserPriority = 0; - - /* get UserPriority from IP hdr */ - if (pattrib->ether_type == ETH_P_IP) { - ip_hdr = (struct iphdr *)(pframe + ETH_HLEN); - UserPriority = ip_hdr->tos >> 5; - } else if (pattrib->ether_type == ETH_P_PAE) { - /* "When priority processing of data frames is supported, */ - /* a STA's SME should send EAPOL-Key frames at the highest - priority." */ - UserPriority = 7; - } - - pattrib->priority = UserPriority; - pattrib->hdrlen = sizeof(struct ieee80211_qos_hdr); - pattrib->type = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA; -} - -static int update_attrib(struct rtw_adapter *padapter, - struct sk_buff *skb, struct pkt_attrib *pattrib) -{ - struct sta_info *psta = NULL; - int bmcast; - struct sta_priv *pstapriv = &padapter->stapriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - int res = _SUCCESS; - struct ethhdr *ehdr = (struct ethhdr *) skb->data; - - pattrib->ether_type = ntohs(ehdr->h_proto); - - ether_addr_copy(pattrib->dst, ehdr->h_dest); - ether_addr_copy(pattrib->src, ehdr->h_source); - - pattrib->pctrl = 0; - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { - ether_addr_copy(pattrib->ra, pattrib->dst); - ether_addr_copy(pattrib->ta, pattrib->src); - } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - ether_addr_copy(pattrib->ra, get_bssid(pmlmepriv)); - ether_addr_copy(pattrib->ta, pattrib->src); - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - ether_addr_copy(pattrib->ra, pattrib->dst); - ether_addr_copy(pattrib->ta, get_bssid(pmlmepriv)); - } - - pattrib->pktlen = skb->len - ETH_HLEN; - - 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 */ - pattrib->dhcp_pkt = 0; - /* MINIMUM_DHCP_PACKET_SIZE) { */ - if (pattrib->pktlen > 282 + 24) { - if (pattrib->ether_type == ETH_P_IP) {/* IP header */ - u8 *pframe = skb->data; - - pframe += ETH_HLEN; - - if ((pframe[21] == 68 && pframe[23] == 67) || - (pframe[21] == 67 && pframe[23] == 68)) { - /* 68 : UDP BOOTP client */ - /* 67 : UDP BOOTP server */ - RT_TRACE(_module_rtl871x_xmit_c_, - _drv_err_, - "======================update_attrib: get DHCP Packet\n"); - pattrib->dhcp_pkt = 1; - } - } - } - } else if (pattrib->ether_type == ETH_P_PAE) { - DBG_8723A_LEVEL(_drv_always_, "send eapol packet\n"); - } - - if ((pattrib->ether_type == ETH_P_PAE) || (pattrib->dhcp_pkt == 1)) { - rtw_set_scan_deny(padapter, 3000); - } - - /* If EAPOL , ARP , OR DHCP packet, driver must be in active mode. */ - if ((pattrib->ether_type == ETH_P_ARP) || - (pattrib->ether_type == ETH_P_PAE) || (pattrib->dhcp_pkt == 1)) { - rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_SPECIAL_PACKET, 1); - } - - bmcast = is_multicast_ether_addr(pattrib->ra); - - /* get sta_info */ - if (bmcast) { - psta = rtw_get_bcmc_stainfo23a(padapter); - } else { - psta = rtw_get_stainfo23a(pstapriv, pattrib->ra); - if (psta == NULL) { /* if we cannot get psta => drrp the pkt */ - RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_, - "update_attrib => get sta_info fail, ra:%pM\n", - pattrib->ra); - res = _FAIL; - goto exit; - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) && - (!(psta->state & _FW_LINKED))) { - res = _FAIL; - goto exit; - } - } - - if (psta) { - pattrib->mac_id = psta->mac_id; - /* DBG_8723A("%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_, - "update_attrib => get sta_info fail, ra:%pM\n", - pattrib->ra); - res = _FAIL; - goto exit; - } - - pattrib->ack_policy = 0; - /* get ether_hdr_len */ - - /* pattrib->ether_type == 0x8100) ? (14 + 4): 14; vlan tag */ - pattrib->pkt_hdrlen = ETH_HLEN; - - pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); - pattrib->type = IEEE80211_FTYPE_DATA; - pattrib->priority = 0; - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE | WIFI_ADHOC_STATE | - WIFI_ADHOC_MASTER_STATE)) { - if (psta->qos_option) - set_qos(skb, pattrib); - } else { - if (pmlmepriv->qos_option) { - set_qos(skb, pattrib); - - if (pmlmepriv->acm_mask != 0) { - pattrib->priority = qos_acm23a(pmlmepriv->acm_mask, - pattrib->priority); - } - } - } - - if (psta->ieee8021x_blocked == true) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "psta->ieee8021x_blocked == true\n"); - - pattrib->encrypt = 0; - - if ((pattrib->ether_type != ETH_P_PAE) && - !check_fwstate(pmlmepriv, WIFI_MP_STATE)) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "psta->ieee8021x_blocked == true, pattrib->ether_type(%.4x) != 0x888e\n", - pattrib->ether_type); - res = _FAIL; - goto exit; - } - } else { - GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, bmcast); - - switch (psecuritypriv->dot11AuthAlgrthm) { - case dot11AuthAlgrthm_Open: - case dot11AuthAlgrthm_Shared: - case dot11AuthAlgrthm_Auto: - pattrib->key_idx = - (u8)psecuritypriv->dot11PrivacyKeyIndex; - break; - case dot11AuthAlgrthm_8021X: - if (bmcast) - pattrib->key_idx = - (u8)psecuritypriv->dot118021XGrpKeyid; - else - pattrib->key_idx = 0; - break; - default: - pattrib->key_idx = 0; - break; - } - - } - - switch (pattrib->encrypt) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - pattrib->iv_len = IEEE80211_WEP_IV_LEN; - pattrib->icv_len = IEEE80211_WEP_ICV_LEN; - break; - - case WLAN_CIPHER_SUITE_TKIP: - pattrib->iv_len = IEEE80211_TKIP_IV_LEN; - pattrib->icv_len = IEEE80211_TKIP_ICV_LEN; - - if (!padapter->securitypriv.busetkipkey) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "padapter->securitypriv.busetkipkey(%d) == false drop packet\n", - padapter->securitypriv.busetkipkey); - res = _FAIL; - goto exit; - } - - break; - case WLAN_CIPHER_SUITE_CCMP: - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "pattrib->encrypt =%d (WLAN_CIPHER_SUITE_CCMP)\n", - pattrib->encrypt); - pattrib->iv_len = IEEE80211_CCMP_HDR_LEN; - pattrib->icv_len = IEEE80211_CCMP_MIC_LEN; - break; - - default: - pattrib->iv_len = 0; - pattrib->icv_len = 0; - break; - } - - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "update_attrib: encrypt =%d\n", pattrib->encrypt); - - if (pattrib->encrypt && !psecuritypriv->hw_decrypted) { - pattrib->bswenc = true; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "update_attrib: encrypt =%d bswenc = true\n", - pattrib->encrypt); - } else { - pattrib->bswenc = false; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "update_attrib: bswenc = false\n"); - } - update_attrib_phy_info(pattrib, psta); - -exit: - - return res; -} - -static int xmitframe_addmic(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) { - struct mic_data micdata; - struct sta_info *stainfo; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - int curfragnum, length; - u8 *pframe, *payload, mic[8]; - u8 priority[4]= {0x0, 0x0, 0x0, 0x0}; - u8 hw_hdr_offset = 0; - int bmcst = is_multicast_ether_addr(pattrib->ra); - - if (pattrib->psta) { - stainfo = pattrib->psta; - } else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - stainfo = rtw_get_stainfo23a(&padapter->stapriv, &pattrib->ra[0]); - } - - if (!stainfo) { - DBG_8723A("%s, psta == NUL\n", __func__); - return _FAIL; - } - - if (!(stainfo->state &_FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", - __func__, stainfo->state); - return _FAIL; - } - - hw_hdr_offset = TXDESC_OFFSET; - - if (pattrib->encrypt == WLAN_CIPHER_SUITE_TKIP) { - /* encode mic code */ - if (stainfo) { - u8 null_key[16]={0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0}; - - pframe = pxmitframe->buf_addr + hw_hdr_offset; - - if (bmcst) { - if (!memcmp(psecuritypriv->dot118021XGrptxmickey[psecuritypriv->dot118021XGrpKeyid].skey, null_key, 16)) { - return _FAIL; - } - /* start to calculate the mic code */ - rtw_secmicsetkey23a(&micdata, psecuritypriv->dot118021XGrptxmickey[psecuritypriv->dot118021XGrpKeyid].skey); - } else { - if (!memcmp(&stainfo->dot11tkiptxmickey.skey[0], - null_key, 16)) { - return _FAIL; - } - /* start to calculate the mic code */ - rtw_secmicsetkey23a(&micdata, &stainfo->dot11tkiptxmickey.skey[0]); - } - - if (pframe[1] & 1) { /* ToDS == 1 */ - /* DA */ - rtw_secmicappend23a(&micdata, &pframe[16], 6); - if (pframe[1] & 2) /* From Ds == 1 */ - rtw_secmicappend23a(&micdata, - &pframe[24], 6); - else - rtw_secmicappend23a(&micdata, - &pframe[10], 6); - } else { /* ToDS == 0 */ - /* DA */ - rtw_secmicappend23a(&micdata, &pframe[4], 6); - if (pframe[1] & 2) /* From Ds == 1 */ - rtw_secmicappend23a(&micdata, - &pframe[16], 6); - else - rtw_secmicappend23a(&micdata, - &pframe[10], 6); - } - - /* if (pmlmepriv->qos_option == 1) */ - if (pattrib->qos_en) - priority[0] = (u8)pxmitframe->attrib.priority; - - rtw_secmicappend23a(&micdata, &priority[0], 4); - - payload = pframe; - - for (curfragnum = 0; curfragnum < pattrib->nr_frags; - curfragnum++) { - payload = PTR_ALIGN(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 = payload + pattrib->hdrlen + - pattrib->iv_len; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "curfragnum =%d pattrib->hdrlen =%d pattrib->iv_len =%d\n", - curfragnum, - pattrib->hdrlen, pattrib->iv_len); - if ((curfragnum + 1) == pattrib->nr_frags) { - length = pattrib->last_txcmdsz - - pattrib->hdrlen - - pattrib->iv_len - - ((pattrib->bswenc) ? - pattrib->icv_len : 0); - rtw_secmicappend23a(&micdata, payload, - length); - payload = payload + length; - } else { - length = pxmitpriv->frag_len - - pattrib->hdrlen - - pattrib->iv_len - - ((pattrib->bswenc) ? - pattrib->icv_len : 0); - rtw_secmicappend23a(&micdata, payload, - length); - payload = payload + length + - pattrib->icv_len; - RT_TRACE(_module_rtl871x_xmit_c_, - _drv_err_, - "curfragnum =%d length =%d pattrib->icv_len =%d\n", - curfragnum, length, - pattrib->icv_len); - } - } - rtw_secgetmic23a(&micdata, &mic[0]); - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "xmitframe_addmic: before add mic code!!\n"); - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "xmitframe_addmic: pattrib->last_txcmdsz =%d!!!\n", - pattrib->last_txcmdsz); - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "xmitframe_addmic: mic[0]= 0x%.2x , mic[1]=0x%.2x , mic[2]= 0x%.2x , mic[3]= 0x%.2x\nmic[4]= 0x%.2x , mic[5]= 0x%.2x , mic[6]= 0x%.2x , mic[7]= 0x%.2x !!!!\n", - 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_, - "======== last pkt ========\n"); - payload = payload - pattrib->last_txcmdsz + 8; - for (curfragnum = 0; curfragnum < pattrib->last_txcmdsz; - curfragnum = curfragnum + 8) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "%.2x, %.2x, %.2x, %.2x, %.2x, %.2x, %.2x, %.2x\n", - *(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_, - "xmitframe_addmic: rtw_get_stainfo23a ==NULL!!!\n"); - } - } - - return _SUCCESS; -} - -static int xmitframe_swencrypt(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - struct pkt_attrib *pattrib = &pxmitframe->attrib; - - /* if ((psecuritypriv->sw_encrypt)||(pattrib->bswenc)) */ - if (pattrib->bswenc) { - /* DBG_8723A("start xmitframe_swencrypt\n"); */ - RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_, - "### xmitframe_swencrypt\n"); - switch (pattrib->encrypt) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - rtw_wep_encrypt23a(padapter, pxmitframe); - break; - case WLAN_CIPHER_SUITE_TKIP: - rtw_tkip_encrypt23a(padapter, pxmitframe); - break; - case WLAN_CIPHER_SUITE_CCMP: - rtw_aes_encrypt23a(padapter, pxmitframe); - break; - default: - break; - } - - } else { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_notice_, - "### xmitframe_hwencrypt\n"); - } - - return _SUCCESS; -} - -static int rtw_make_wlanhdr(struct rtw_adapter *padapter, u8 *hdr, - struct pkt_attrib *pattrib) -{ - struct ieee80211_hdr *pwlanhdr = (struct ieee80211_hdr *)hdr; - struct ieee80211_qos_hdr *qoshdr; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - u8 qos_option = false; - int res = _SUCCESS; - - struct sta_info *psta; - - int bmcst = is_multicast_ether_addr(pattrib->ra); - - if (pattrib->psta) { - psta = pattrib->psta; - } else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - if (bmcst) { - psta = rtw_get_bcmc_stainfo23a(padapter); - } else { - psta = rtw_get_stainfo23a(&padapter->stapriv, pattrib->ra); - } - } - - if (psta == NULL) { - DBG_8723A("%s, psta == NUL\n", __func__); - return _FAIL; - } - - if (!(psta->state &_FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state); - return _FAIL; - } - - memset(hdr, 0, WLANHDR_OFFSET); - - pwlanhdr->frame_control = cpu_to_le16(pattrib->type); - - if (pattrib->type & IEEE80211_FTYPE_DATA) { - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - /* to_ds = 1, fr_ds = 0; */ - /* Data transfer to AP */ - pwlanhdr->frame_control |= - cpu_to_le16(IEEE80211_FCTL_TODS); - ether_addr_copy(pwlanhdr->addr1, get_bssid(pmlmepriv)); - ether_addr_copy(pwlanhdr->addr2, pattrib->src); - ether_addr_copy(pwlanhdr->addr3, pattrib->dst); - - if (pmlmepriv->qos_option) - qos_option = true; - - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - /* to_ds = 0, fr_ds = 1; */ - pwlanhdr->frame_control |= - cpu_to_le16(IEEE80211_FCTL_FROMDS); - ether_addr_copy(pwlanhdr->addr1, pattrib->dst); - ether_addr_copy(pwlanhdr->addr2, get_bssid(pmlmepriv)); - ether_addr_copy(pwlanhdr->addr3, pattrib->src); - - if (psta->qos_option) - qos_option = true; - } else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { - ether_addr_copy(pwlanhdr->addr1, pattrib->dst); - ether_addr_copy(pwlanhdr->addr2, pattrib->src); - ether_addr_copy(pwlanhdr->addr3, get_bssid(pmlmepriv)); - - if (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; - } - if (pattrib->mdata) - pwlanhdr->frame_control |= - cpu_to_le16(IEEE80211_FCTL_MOREDATA); - if (pattrib->encrypt) - pwlanhdr->frame_control |= - cpu_to_le16(IEEE80211_FCTL_PROTECTED); - if (qos_option) { - qoshdr = (struct ieee80211_qos_hdr *)hdr; - - qoshdr->qos_ctrl = cpu_to_le16( - pattrib->priority & IEEE80211_QOS_CTL_TID_MASK); - - qoshdr->qos_ctrl |= cpu_to_le16( - (pattrib->ack_policy << 5) & - IEEE80211_QOS_CTL_ACK_POLICY_MASK); - - if (pattrib->eosp) - qoshdr->qos_ctrl |= - cpu_to_le16(IEEE80211_QOS_CTL_EOSP); - } - /* TODO: fill HT Control Field */ - - /* Update Seq Num will be handled by f/w */ - if (psta) { - psta->sta_xmitpriv.txseq_tid[pattrib->priority]++; - psta->sta_xmitpriv.txseq_tid[pattrib->priority] &= 0xFFF; - pattrib->seqnum = psta->sta_xmitpriv.txseq_tid[pattrib->priority]; - /* We dont need to worry about frag bits here */ - pwlanhdr->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ( - pattrib->seqnum)); - /* check if enable ampdu */ - if (pattrib->ht_en && psta->htpriv.ampdu_enable) { - if (pattrib->priority >= 16) - printk(KERN_WARNING "%s: Invalid " - "pattrib->priority %i\n", - __func__, pattrib->priority); - if (psta->htpriv.agg_enable_bitmap & - BIT(pattrib->priority)) - pattrib->ampdu_en = true; - } - /* re-check if enable ampdu by BA_starting_seqctrl */ - if (pattrib->ampdu_en) { - u16 tx_seq; - - tx_seq = psta->BA_starting_seqctrl[pattrib->priority & 0x0f]; - - /* check BA_starting_seqctrl */ - if (SN_LESS(pattrib->seqnum, tx_seq)) { - /* DBG_8723A("tx ampdu seqnum(%d) < tx_seq(%d)\n", pattrib->seqnum, tx_seq); */ - pattrib->ampdu_en = false;/* AGG BK */ - } else if (SN_EQUAL(pattrib->seqnum, tx_seq)) { - psta->BA_starting_seqctrl[pattrib->priority & 0x0f] = (tx_seq+1)&0xfff; - pattrib->ampdu_en = true;/* AGG EN */ - } else { - /* DBG_8723A("tx ampdu over run\n"); */ - psta->BA_starting_seqctrl[pattrib->priority & 0x0f] = (pattrib->seqnum+1)&0xfff; - pattrib->ampdu_en = true;/* AGG EN */ - } - } - } - } -exit: - return res; -} - -s32 rtw_txframes_pending23a(struct rtw_adapter *padapter) -{ - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - return (!list_empty(&pxmitpriv->be_pending.queue)) || - (!list_empty(&pxmitpriv->bk_pending.queue)) || - (!list_empty(&pxmitpriv->vi_pending.queue)) || - (!list_empty(&pxmitpriv->vo_pending.queue)); -} - -s32 rtw_txframes_sta_ac_pending23a(struct rtw_adapter *padapter, - struct pkt_attrib *pattrib) -{ - struct sta_info *psta; - struct tx_servq *ptxservq; - int priority = pattrib->priority; - - if (pattrib->psta) { - psta = pattrib->psta; - } else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - psta = rtw_get_stainfo23a(&padapter->stapriv, &pattrib->ra[0]); - } - if (psta == NULL) { - DBG_8723A("%s, psta == NUL\n", __func__); - return 0; - } - if (!(psta->state &_FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, - psta->state); - return 0; - } - switch (priority) { - case 1: - case 2: - ptxservq = &psta->sta_xmitpriv.bk_q; - break; - case 4: - case 5: - ptxservq = &psta->sta_xmitpriv.vi_q; - break; - case 6: - case 7: - ptxservq = &psta->sta_xmitpriv.vo_q; - break; - case 0: - case 3: - default: - ptxservq = &psta->sta_xmitpriv.be_q; - break; - } - return ptxservq->qcnt; -} - -/* Logical Link Control(LLC) SubNetwork Attachment Point(SNAP) header - * IEEE LLC/SNAP header contains 8 octets - * First 3 octets comprise the LLC portion - * SNAP portion, 5 octets, is divided into two fields: - * Organizationally Unique Identifier(OUI), 3 octets, - * type, defined by that organization, 2 octets. - */ -static int rtw_put_snap(u8 *data, u16 h_proto) -{ - if (h_proto == ETH_P_IPX || h_proto == ETH_P_AARP) - ether_addr_copy(data, bridge_tunnel_header); - else - ether_addr_copy(data, rfc1042_header); - - data += ETH_ALEN; - put_unaligned_be16(h_proto, data); - return ETH_ALEN + sizeof(u16); -} - -/* - -This sub-routine will perform all the following: - -1. remove 802.3 header. -2. create wlan_header, based on the info in pxmitframe -3. append sta's iv/ext-iv -4. append LLC -5. move frag chunk from pframe to pxmitframe->mem -6. apply sw-encrypt, if necessary. - -*/ -int rtw_xmitframe_coalesce23a(struct rtw_adapter *padapter, struct sk_buff *skb, - struct xmit_frame *pxmitframe) -{ - struct sta_info *psta; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct ieee80211_hdr *hdr; - s32 frg_inx, frg_len, mpdu_len, llc_sz, mem_sz; - u8 *pframe, *mem_start; - u8 hw_hdr_offset; - u8 *pbuf_start; - u8 *pdata = skb->data; - int data_len = skb->len; - s32 bmcst = is_multicast_ether_addr(pattrib->ra); - int res = _SUCCESS; - - if (pattrib->psta) - psta = pattrib->psta; - else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - psta = rtw_get_stainfo23a(&padapter->stapriv, pattrib->ra); - } - - if (!psta) { - DBG_8723A("%s, psta == NUL\n", __func__); - return _FAIL; - } - - if (!(psta->state &_FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", - __func__, psta->state); - return _FAIL; - } - - if (!pxmitframe->buf_addr) { - DBG_8723A("==> %s buf_addr == NULL\n", __func__); - return _FAIL; - } - - pbuf_start = pxmitframe->buf_addr; - - hw_hdr_offset = TXDESC_OFFSET; - - 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__); - res = _FAIL; - goto exit; - } - - pdata += pattrib->pkt_hdrlen; - data_len -= pattrib->pkt_hdrlen; - - frg_inx = 0; - frg_len = pxmitpriv->frag_len - 4;/* 2346-4 = 2342 */ - - while (1) { - llc_sz = 0; - - mpdu_len = frg_len; - - pframe = mem_start; - hdr = (struct ieee80211_hdr *)mem_start; - - pframe += pattrib->hdrlen; - mpdu_len -= pattrib->hdrlen; - - /* adding icv, if necessary... */ - if (pattrib->iv_len) { - if (psta) { - switch (pattrib->encrypt) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - WEP_IV(pattrib->iv, psta->dot11txpn, - pattrib->key_idx); - break; - case WLAN_CIPHER_SUITE_TKIP: - if (bmcst) - TKIP_IV(pattrib->iv, - psta->dot11txpn, - pattrib->key_idx); - else - TKIP_IV(pattrib->iv, - psta->dot11txpn, 0); - break; - case WLAN_CIPHER_SUITE_CCMP: - if (bmcst) - AES_IV(pattrib->iv, - psta->dot11txpn, - pattrib->key_idx); - else - AES_IV(pattrib->iv, - psta->dot11txpn, 0); - break; - } - } - - memcpy(pframe, pattrib->iv, pattrib->iv_len); - - RT_TRACE(_module_rtl871x_xmit_c_, _drv_notice_, - "rtw_xmiaframe_coalesce23a: keyid =%d pattrib->iv[3]=%.2x pframe =%.2x %.2x %.2x %.2x\n", - padapter->securitypriv.dot11PrivacyKeyIndex, - pattrib->iv[3], *pframe, *(pframe+1), - *(pframe+2), *(pframe+3)); - pframe += pattrib->iv_len; - mpdu_len -= pattrib->iv_len; - } - if (frg_inx == 0) { - llc_sz = rtw_put_snap(pframe, pattrib->ether_type); - pframe += llc_sz; - mpdu_len -= llc_sz; - } - - if (pattrib->icv_len > 0 && pattrib->bswenc) - mpdu_len -= pattrib->icv_len; - - if (bmcst) - /* don't do fragment to broadcast/multicast packets */ - mem_sz = min_t(s32, data_len, pattrib->pktlen); - else - mem_sz = min_t(s32, data_len, mpdu_len); - - memcpy(pframe, pdata, mem_sz); - - pframe += mem_sz; - pdata += mem_sz; - data_len -= mem_sz; - - if ((pattrib->icv_len >0) && (pattrib->bswenc)) { - memcpy(pframe, pattrib->icv, pattrib->icv_len); - pframe += pattrib->icv_len; - } - - frg_inx++; - - if (bmcst || data_len <= 0) { - pattrib->nr_frags = frg_inx; - - pattrib->last_txcmdsz = pattrib->hdrlen + - pattrib->iv_len + - ((pattrib->nr_frags == 1) ? - llc_sz : 0) + - ((pattrib->bswenc) ? - pattrib->icv_len : 0) + mem_sz; - hdr->frame_control &= - ~cpu_to_le16(IEEE80211_FCTL_MOREFRAGS); - - break; - } else { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "%s: There're still something in packet!\n", - __func__); - } - hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREFRAGS); - - mem_start = PTR_ALIGN(pframe, 4) + hw_hdr_offset; - memcpy(mem_start, pbuf_start + hw_hdr_offset, pattrib->hdrlen); - } - - if (xmitframe_addmic(padapter, pxmitframe) == _FAIL) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "xmitframe_addmic(padapter, pxmitframe) == _FAIL\n"); - DBG_8723A("xmitframe_addmic(padapter, pxmitframe) == _FAIL\n"); - res = _FAIL; - goto exit; - } - - xmitframe_swencrypt(padapter, pxmitframe); - - if (bmcst == false) - update_attrib_vcs_info(padapter, pxmitframe); - else - pattrib->vcs_mode = NONE_VCS; - -exit: - return res; -} - -void rtw_update_protection23a(struct rtw_adapter *padapter, u8 *ie, uint ie_len) -{ - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - uint protection; - const u8 *p; - - switch (pregistrypriv->vrtl_carrier_sense) { - case DISABLE_VCS: - pxmitpriv->vcs = NONE_VCS; - break; - case ENABLE_VCS: - break; - case AUTO_VCS: - default: - p = cfg80211_find_ie(WLAN_EID_ERP_INFO, ie, ie_len); - if (!p) - pxmitpriv->vcs = NONE_VCS; - else { - protection = (*(p + 2)) & BIT(1); - if (protection) { - if (pregistrypriv->vcs_type == RTS_CTS) - pxmitpriv->vcs = RTS_CTS; - else - pxmitpriv->vcs = CTS_TO_SELF; - } else { - pxmitpriv->vcs = NONE_VCS; - } - } - break; - } -} - -void rtw_count_tx_stats23a(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe, int sz) -{ - struct sta_info *psta = NULL; - struct stainfo_stats *pstats = NULL; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (pxmitframe->frame_tag == DATA_FRAMETAG) { - pxmitpriv->tx_bytes += sz; - pmlmepriv->LinkDetectInfo.NumTxOkInPeriod++; - - psta = pxmitframe->attrib.psta; - if (psta) { - pstats = &psta->sta_stats; - pstats->tx_pkts++; - pstats->tx_bytes += sz; - } - } -} - -struct xmit_buf *rtw_alloc_xmitbuf23a_ext(struct xmit_priv *pxmitpriv) -{ - unsigned long irqL; - struct xmit_buf *pxmitbuf = NULL; - struct list_head *phead; - struct rtw_queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue; - - spin_lock_irqsave(&pfree_queue->lock, irqL); - - phead = get_list_head(pfree_queue); - - if (!list_empty(phead)) { - pxmitbuf = list_first_entry(phead, struct xmit_buf, list); - - list_del_init(&pxmitbuf->list); - - pxmitpriv->free_xmit_extbuf_cnt--; - pxmitbuf->priv_data = NULL; - pxmitbuf->ext_tag = true; - - if (pxmitbuf->sctx) { - DBG_8723A("%s pxmitbuf->sctx is not NULL\n", __func__); - rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC); - } - } - - spin_unlock_irqrestore(&pfree_queue->lock, irqL); - - return pxmitbuf; -} - -int rtw_free_xmitbuf_ext23a(struct xmit_priv *pxmitpriv, - struct xmit_buf *pxmitbuf) -{ - unsigned long irqL; - struct rtw_queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue; - - if (pxmitbuf == NULL) - return _FAIL; - - spin_lock_irqsave(&pfree_queue->lock, irqL); - - list_del_init(&pxmitbuf->list); - - list_add_tail(&pxmitbuf->list, get_list_head(pfree_queue)); - pxmitpriv->free_xmit_extbuf_cnt++; - - spin_unlock_irqrestore(&pfree_queue->lock, irqL); - - return _SUCCESS; -} - -struct xmit_buf *rtw_alloc_xmitbuf23a(struct xmit_priv *pxmitpriv) -{ - unsigned long irqL; - struct xmit_buf *pxmitbuf = NULL; - struct list_head *phead; - struct rtw_queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue; - - /* DBG_8723A("+rtw_alloc_xmitbuf23a\n"); */ - - spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL); - - phead = get_list_head(pfree_xmitbuf_queue); - - if (!list_empty(phead)) { - pxmitbuf = list_first_entry(phead, struct xmit_buf, list); - - list_del_init(&pxmitbuf->list); - - pxmitpriv->free_xmitbuf_cnt--; - pxmitbuf->priv_data = NULL; - pxmitbuf->ext_tag = false; - pxmitbuf->flags = XMIT_VO_QUEUE; - - if (pxmitbuf->sctx) { - DBG_8723A("%s pxmitbuf->sctx is not NULL\n", __func__); - rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC); - } - } - - spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL); - - return pxmitbuf; -} - -int rtw_free_xmitbuf23a(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) -{ - unsigned long irqL; - struct rtw_queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue; - - /* DBG_8723A("+rtw_free_xmitbuf23a\n"); */ - - if (pxmitbuf == NULL) - return _FAIL; - - if (pxmitbuf->sctx) { - DBG_8723A("%s pxmitbuf->sctx is not NULL\n", __func__); - rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_FREE); - } - - if (pxmitbuf->ext_tag) { - rtw_free_xmitbuf_ext23a(pxmitpriv, pxmitbuf); - } else { - spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL); - - list_del_init(&pxmitbuf->list); - - list_add_tail(&pxmitbuf->list, - get_list_head(pfree_xmitbuf_queue)); - - pxmitpriv->free_xmitbuf_cnt++; - spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL); - } - - return _SUCCESS; -} - -static void rtw_init_xmitframe(struct xmit_frame *pxframe) -{ - if (pxframe != NULL) { - /* default value setting */ - pxframe->buf_addr = NULL; - pxframe->pxmitbuf = NULL; - - memset(&pxframe->attrib, 0, sizeof(struct pkt_attrib)); - /* pxframe->attrib.psta = NULL; */ - - pxframe->frame_tag = DATA_FRAMETAG; - - pxframe->pkt = NULL; - pxframe->pkt_offset = 1;/* default use pkt_offset to fill tx desc */ - - pxframe->ack_report = 0; - } -} - -/* -Calling context: -1. OS_TXENTRY -2. RXENTRY (rx_thread or RX_ISR/RX_CallBack) - -If we turn on USE_RXTHREAD, then, no need for critical section. -Otherwise, we must use _enter/_exit critical to protect free_xmit_queue... - -Must be very very cautious... - -*/ -static struct xmit_frame *rtw_alloc_xmitframe(struct xmit_priv *pxmitpriv) -{ - struct xmit_frame *pxframe; - struct rtw_queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue; - - 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 { - list_del_init(&pxframe->list); - pxmitpriv->free_xmitframe_cnt--; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_alloc_xmitframe():free_xmitframe_cnt =%d\n", - pxmitpriv->free_xmitframe_cnt); - } - - spin_unlock_bh(&pfree_xmit_queue->lock); - - rtw_init_xmitframe(pxframe); - - return pxframe; -} - -struct xmit_frame *rtw_alloc_xmitframe23a_ext(struct xmit_priv *pxmitpriv) -{ - struct xmit_frame *pxframe; - struct rtw_queue *queue = &pxmitpriv->free_xframe_ext_queue; - - spin_lock_bh(&queue->lock); - - pxframe = list_first_entry_or_null(&queue->queue, - struct xmit_frame, list); - if (!pxframe) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_alloc_xmitframe23a_ext:%d\n", - pxmitpriv->free_xframe_ext_cnt); - } else { - list_del_init(&pxframe->list); - pxmitpriv->free_xframe_ext_cnt--; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_alloc_xmitframe23a_ext():free_xmitframe_cnt =%d\n", - pxmitpriv->free_xframe_ext_cnt); - } - - spin_unlock_bh(&queue->lock); - - rtw_init_xmitframe(pxframe); - - return pxframe; -} - -s32 rtw_free_xmitframe23a(struct xmit_priv *pxmitpriv, struct xmit_frame *pxmitframe) -{ - struct rtw_queue *queue = NULL; - struct rtw_adapter *padapter = pxmitpriv->adapter; - struct sk_buff *pndis_pkt = NULL; - - if (pxmitframe == NULL) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "====== rtw_free_xmitframe23a():pxmitframe == NULL!!!!!!!!!!\n"); - goto exit; - } - - if (pxmitframe->pkt) { - pndis_pkt = pxmitframe->pkt; - pxmitframe->pkt = NULL; - } - - if (pxmitframe->ext_tag == 0) - queue = &pxmitpriv->free_xmit_queue; - else if (pxmitframe->ext_tag == 1) - queue = &pxmitpriv->free_xframe_ext_queue; - - if (!queue) - goto check_pkt_complete; - spin_lock_bh(&queue->lock); - - list_del_init(&pxmitframe->list); - list_add_tail(&pxmitframe->list, get_list_head(queue)); - if (pxmitframe->ext_tag == 0) { - pxmitpriv->free_xmitframe_cnt++; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_debug_, - "rtw_free_xmitframe23a():free_xmitframe_cnt =%d\n", - pxmitpriv->free_xmitframe_cnt); - } else if (pxmitframe->ext_tag == 1) { - pxmitpriv->free_xframe_ext_cnt++; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_debug_, - "rtw_free_xmitframe23a():free_xframe_ext_cnt =%d\n", - pxmitpriv->free_xframe_ext_cnt); - } - - spin_unlock_bh(&queue->lock); - -check_pkt_complete: - - if (pndis_pkt) - rtw_os_pkt_complete23a(padapter, pndis_pkt); - -exit: - - return _SUCCESS; -} - -void rtw_free_xmitframe_queue23a(struct xmit_priv *pxmitpriv, - struct rtw_queue *pframequeue) -{ - struct list_head *phead; - struct xmit_frame *pxmitframe, *ptmp; - - spin_lock_bh(&pframequeue->lock); - phead = get_list_head(pframequeue); - list_for_each_entry_safe(pxmitframe, ptmp, phead, list) - rtw_free_xmitframe23a(pxmitpriv, pxmitframe); - spin_unlock_bh(&pframequeue->lock); - -} - -int rtw_xmitframe_enqueue23a(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - if (rtw_xmit23a_classifier(padapter, pxmitframe) == _FAIL) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "rtw_xmitframe_enqueue23a: drop xmit pkt for classifier fail\n"); - return _FAIL; - } - - return _SUCCESS; -} - -static struct xmit_frame * -dequeue_one_xmitframe(struct xmit_priv *pxmitpriv, struct hw_xmit *phwxmit, - struct tx_servq *ptxservq, struct rtw_queue *pframe_queue) -{ - struct list_head *phead; - struct xmit_frame *pxmitframe = NULL; - - phead = get_list_head(pframe_queue); - - if (!list_empty(phead)) { - pxmitframe = list_first_entry(phead, struct xmit_frame, list); - list_del_init(&pxmitframe->list); - ptxservq->qcnt--; - } - return pxmitframe; -} - -struct xmit_frame * -rtw_dequeue_xframe23a(struct xmit_priv *pxmitpriv, struct hw_xmit *phwxmit_i, - int entry) -{ - struct list_head *sta_phead; - struct hw_xmit *phwxmit; - struct tx_servq *ptxservq = NULL, *ptmp; - struct rtw_queue *pframe_queue = NULL; - struct xmit_frame *pxmitframe = NULL; - struct rtw_adapter *padapter = pxmitpriv->adapter; - struct registry_priv *pregpriv = &padapter->registrypriv; - int i, inx[4]; - - inx[0] = 0; - inx[1] = 1; - inx[2] = 2; - inx[3] = 3; - if (pregpriv->wifi_spec == 1) { - int j; - - for (j = 0; j < 4; j++) - inx[j] = pxmitpriv->wmm_para_seq[j]; - } - - spin_lock_bh(&pxmitpriv->lock); - - for (i = 0; i < entry; i++) { - phwxmit = phwxmit_i + inx[i]; - - sta_phead = get_list_head(phwxmit->sta_queue); - list_for_each_entry_safe(ptxservq, ptmp, sta_phead, - tx_pending) { - pframe_queue = &ptxservq->sta_pending; - - pxmitframe = dequeue_one_xmitframe(pxmitpriv, phwxmit, ptxservq, pframe_queue); - - if (pxmitframe) { - phwxmit->accnt--; - - /* Remove sta node when there is no pending packets. */ - /* must be done after get_next and - before break */ - if (list_empty(&pframe_queue->queue)) - list_del_init(&ptxservq->tx_pending); - goto exit; - } - } - } -exit: - spin_unlock_bh(&pxmitpriv->lock); - return pxmitframe; -} - -struct tx_servq *rtw_get_sta_pending23a(struct rtw_adapter *padapter, struct sta_info *psta, int up, u8 *ac) -{ - struct tx_servq *ptxservq = NULL; - - switch (up) { - case 1: - case 2: - ptxservq = &psta->sta_xmitpriv.bk_q; - *(ac) = 3; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_get_sta_pending23a : BK\n"); - break; - case 4: - case 5: - ptxservq = &psta->sta_xmitpriv.vi_q; - *(ac) = 1; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_get_sta_pending23a : VI\n"); - break; - case 6: - case 7: - ptxservq = &psta->sta_xmitpriv.vo_q; - *(ac) = 0; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_get_sta_pending23a : VO\n"); - break; - case 0: - case 3: - default: - ptxservq = &psta->sta_xmitpriv.be_q; - *(ac) = 2; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_get_sta_pending23a : BE\n"); - break; - } - return ptxservq; -} - -/* - * Will enqueue pxmitframe to the proper queue, - * and indicate it to xx_pending list..... - */ -int rtw_xmit23a_classifier(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - struct sta_info *psta; - struct tx_servq *ptxservq; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct sta_priv *pstapriv = &padapter->stapriv; - struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits; - u8 ac_index; - int res = _SUCCESS; - - if (pattrib->psta) { - psta = pattrib->psta; - } else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - psta = rtw_get_stainfo23a(pstapriv, pattrib->ra); - } - if (psta == NULL) { - res = _FAIL; - DBG_8723A("rtw_xmit23a_classifier: psta == NULL\n"); - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "rtw_xmit23a_classifier: psta == NULL\n"); - goto exit; - } - if (!(psta->state & _FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, - psta->state); - return _FAIL; - } - ptxservq = rtw_get_sta_pending23a(padapter, psta, pattrib->priority, - (u8 *)(&ac_index)); - - if (list_empty(&ptxservq->tx_pending)) { - list_add_tail(&ptxservq->tx_pending, - get_list_head(phwxmits[ac_index].sta_queue)); - } - - list_add_tail(&pxmitframe->list, get_list_head(&ptxservq->sta_pending)); - ptxservq->qcnt++; - phwxmits[ac_index].accnt++; -exit: - return res; -} - -void rtw_alloc_hwxmits23a(struct rtw_adapter *padapter) -{ - struct hw_xmit *hwxmits; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - int size; - - pxmitpriv->hwxmit_entry = HWXMIT_ENTRY; - - size = sizeof(struct hw_xmit) * (pxmitpriv->hwxmit_entry + 1); - pxmitpriv->hwxmits = kzalloc(size, GFP_KERNEL); - - hwxmits = pxmitpriv->hwxmits; - - if (pxmitpriv->hwxmit_entry == 5) { - /* pxmitpriv->bmc_txqueue.head = 0; */ - /* hwxmits[0] .phwtxqueue = &pxmitpriv->bmc_txqueue; */ - hwxmits[0] .sta_queue = &pxmitpriv->bm_pending; - - /* pxmitpriv->vo_txqueue.head = 0; */ - /* hwxmits[1] .phwtxqueue = &pxmitpriv->vo_txqueue; */ - hwxmits[1] .sta_queue = &pxmitpriv->vo_pending; - - /* pxmitpriv->vi_txqueue.head = 0; */ - /* hwxmits[2] .phwtxqueue = &pxmitpriv->vi_txqueue; */ - hwxmits[2] .sta_queue = &pxmitpriv->vi_pending; - - /* pxmitpriv->bk_txqueue.head = 0; */ - /* hwxmits[3] .phwtxqueue = &pxmitpriv->bk_txqueue; */ - hwxmits[3] .sta_queue = &pxmitpriv->bk_pending; - - /* pxmitpriv->be_txqueue.head = 0; */ - /* hwxmits[4] .phwtxqueue = &pxmitpriv->be_txqueue; */ - hwxmits[4] .sta_queue = &pxmitpriv->be_pending; - - } else if (pxmitpriv->hwxmit_entry == 4) { - - /* pxmitpriv->vo_txqueue.head = 0; */ - /* hwxmits[0] .phwtxqueue = &pxmitpriv->vo_txqueue; */ - hwxmits[0] .sta_queue = &pxmitpriv->vo_pending; - - /* pxmitpriv->vi_txqueue.head = 0; */ - /* hwxmits[1] .phwtxqueue = &pxmitpriv->vi_txqueue; */ - hwxmits[1] .sta_queue = &pxmitpriv->vi_pending; - - /* pxmitpriv->be_txqueue.head = 0; */ - /* hwxmits[2] .phwtxqueue = &pxmitpriv->be_txqueue; */ - hwxmits[2] .sta_queue = &pxmitpriv->be_pending; - - /* pxmitpriv->bk_txqueue.head = 0; */ - /* hwxmits[3] .phwtxqueue = &pxmitpriv->bk_txqueue; */ - hwxmits[3] .sta_queue = &pxmitpriv->bk_pending; - } else { - - } -} - -void rtw_free_hwxmits23a(struct rtw_adapter *padapter) -{ - struct hw_xmit *hwxmits; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - hwxmits = pxmitpriv->hwxmits; - kfree(hwxmits); -} - -void rtw_init_hwxmits23a(struct hw_xmit *phwxmit, int entry) -{ - int i; - - for (i = 0; i < entry; i++, phwxmit++) - phwxmit->accnt = 0; -} - -u32 rtw_get_ff_hwaddr23a(struct xmit_frame *pxmitframe) -{ - u32 addr; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - - switch (pattrib->qsel) { - case 0: - case 3: - addr = BE_QUEUE_INX; - break; - case 1: - case 2: - addr = BK_QUEUE_INX; - break; - case 4: - case 5: - addr = VI_QUEUE_INX; - break; - case 6: - case 7: - addr = VO_QUEUE_INX; - break; - case 0x10: - addr = BCN_QUEUE_INX; - break; - case 0x11:/* BC/MC in PS (HIQ) */ - addr = HIGH_QUEUE_INX; - break; - case 0x12: - default: - addr = MGT_QUEUE_INX; - break; - } - - return addr; -} - -/* - * The main transmit(tx) entry - * - * Return - * 1 enqueue - * 0 success, hardware will handle this xmit frame(packet) - * <0 fail - */ -int rtw_xmit23a(struct rtw_adapter *padapter, struct sk_buff *skb) -{ - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct xmit_frame *pxmitframe = NULL; - int res; - - pxmitframe = rtw_alloc_xmitframe(pxmitpriv); - - if (pxmitframe == NULL) { - RT_TRACE(_module_xmit_osdep_c_, _drv_err_, - "rtw_xmit23a: no more pxmitframe\n"); - return -1; - } - - res = update_attrib(padapter, skb, &pxmitframe->attrib); - - if (res == _FAIL) { - RT_TRACE(_module_xmit_osdep_c_, _drv_err_, - "rtw_xmit23a: update attrib fail\n"); - rtw_free_xmitframe23a(pxmitpriv, pxmitframe); - return -1; - } - pxmitframe->pkt = skb; - - pxmitframe->attrib.qsel = pxmitframe->attrib.priority; - -#ifdef CONFIG_8723AU_AP_MODE - spin_lock_bh(&pxmitpriv->lock); - if (xmitframe_enqueue_for_sleeping_sta23a(padapter, pxmitframe)) { - spin_unlock_bh(&pxmitpriv->lock); - return 1; - } - spin_unlock_bh(&pxmitpriv->lock); -#endif - - if (rtl8723au_hal_xmit(padapter, pxmitframe) == false) - return 1; - - return 0; -} - -#if defined(CONFIG_8723AU_AP_MODE) - -int xmitframe_enqueue_for_sleeping_sta23a(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe) -{ - int ret = false; - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - int bmcst = is_multicast_ether_addr(pattrib->ra); - - if (!check_fwstate(pmlmepriv, WIFI_AP_STATE)) - return ret; - - if (pattrib->psta) { - psta = pattrib->psta; - } else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - psta = rtw_get_stainfo23a(pstapriv, pattrib->ra); - } - - if (psta == NULL) { - DBG_8723A("%s, psta == NUL\n", __func__); - return false; - } - - if (!(psta->state & _FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, - psta->state); - return false; - } - - if (pattrib->triggered == 1) { - if (bmcst) - pattrib->qsel = 0x11;/* HIQ */ - return ret; - } - - if (bmcst) { - spin_lock_bh(&psta->sleep_q.lock); - - if (pstapriv->sta_dz_bitmap) { - /* if anyone sta is in ps mode */ - list_del_init(&pxmitframe->list); - - /* spin_lock_bh(&psta->sleep_q.lock); */ - - list_add_tail(&pxmitframe->list, get_list_head(&psta->sleep_q)); - - psta->sleepq_len++; - - pstapriv->tim_bitmap |= BIT(0);/* */ - pstapriv->sta_dz_bitmap |= BIT(0); - - /* DBG_8723A("enqueue, sq_len =%d, tim =%x\n", psta->sleepq_len, pstapriv->tim_bitmap); */ - - /* tx bc/mc packets after update bcn */ - update_beacon23a(padapter, WLAN_EID_TIM, NULL, false); - - /* spin_unlock_bh(&psta->sleep_q.lock); */ - - ret = true; - - } - - spin_unlock_bh(&psta->sleep_q.lock); - - return ret; - - } - - spin_lock_bh(&psta->sleep_q.lock); - - if (psta->state&WIFI_SLEEP_STATE) { - u8 wmmps_ac = 0; - - if (pstapriv->sta_dz_bitmap & CHKBIT(psta->aid)) { - list_del_init(&pxmitframe->list); - - /* spin_lock_bh(&psta->sleep_q.lock); */ - - list_add_tail(&pxmitframe->list, get_list_head(&psta->sleep_q)); - - psta->sleepq_len++; - - switch (pattrib->priority) { - case 1: - case 2: - wmmps_ac = psta->uapsd_bk & BIT(0); - break; - case 4: - case 5: - wmmps_ac = psta->uapsd_vi & BIT(0); - break; - case 6: - case 7: - wmmps_ac = psta->uapsd_vo & BIT(0); - break; - case 0: - case 3: - default: - wmmps_ac = psta->uapsd_be & BIT(0); - break; - } - - if (wmmps_ac) - psta->sleepq_ac_len++; - - if (((psta->has_legacy_ac) && (!wmmps_ac)) || - ((!psta->has_legacy_ac) && (wmmps_ac))) { - pstapriv->tim_bitmap |= CHKBIT(psta->aid); - - if (psta->sleepq_len == 1) { - /* update BCN for TIM IE */ - update_beacon23a(padapter, WLAN_EID_TIM, - NULL, false); - } - } - - /* spin_unlock_bh(&psta->sleep_q.lock); */ - - /* if (psta->sleepq_len > (NR_XMITFRAME>>3)) */ - /* */ - /* wakeup_sta_to_xmit23a(padapter, psta); */ - /* */ - - ret = true; - - } - - } - - spin_unlock_bh(&psta->sleep_q.lock); - - return ret; -} - -static void -dequeue_xmitframes_to_sleeping_queue(struct rtw_adapter *padapter, - struct sta_info *psta, - struct rtw_queue *pframequeue) -{ - int ret; - struct list_head *phead; - u8 ac_index; - struct tx_servq *ptxservq; - struct pkt_attrib *pattrib; - struct xmit_frame *pxmitframe, *ptmp; - struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits; - - phead = get_list_head(pframequeue); - list_for_each_entry_safe(pxmitframe, ptmp, phead, list) { - ret = xmitframe_enqueue_for_sleeping_sta23a(padapter, pxmitframe); - - if (ret == true) { - pattrib = &pxmitframe->attrib; - - ptxservq = rtw_get_sta_pending23a(padapter, psta, pattrib->priority, (u8 *)(&ac_index)); - - ptxservq->qcnt--; - phwxmits[ac_index].accnt--; - } else { - /* DBG_8723A("xmitframe_enqueue_for_sleeping_sta23a return false\n"); */ - } - } -} - -void stop_sta_xmit23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - struct sta_info *psta_bmc; - struct sta_xmit_priv *pstaxmitpriv; - struct sta_priv *pstapriv = &padapter->stapriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - pstaxmitpriv = &psta->sta_xmitpriv; - - /* for BC/MC Frames */ - psta_bmc = rtw_get_bcmc_stainfo23a(padapter); - - spin_lock_bh(&pxmitpriv->lock); - - psta->state |= WIFI_SLEEP_STATE; - - pstapriv->sta_dz_bitmap |= CHKBIT(psta->aid); - - dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->vo_q.sta_pending); - list_del_init(&pstaxmitpriv->vo_q.tx_pending); - - dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->vi_q.sta_pending); - list_del_init(&pstaxmitpriv->vi_q.tx_pending); - - dequeue_xmitframes_to_sleeping_queue(padapter, psta, - &pstaxmitpriv->be_q.sta_pending); - list_del_init(&pstaxmitpriv->be_q.tx_pending); - - dequeue_xmitframes_to_sleeping_queue(padapter, psta, - &pstaxmitpriv->bk_q.sta_pending); - list_del_init(&pstaxmitpriv->bk_q.tx_pending); - - /* for BC/MC Frames */ - pstaxmitpriv = &psta_bmc->sta_xmitpriv; - dequeue_xmitframes_to_sleeping_queue(padapter, psta_bmc, - &pstaxmitpriv->be_q.sta_pending); - list_del_init(&pstaxmitpriv->be_q.tx_pending); - - spin_unlock_bh(&pxmitpriv->lock); -} - -void wakeup_sta_to_xmit23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - u8 update_mask = 0, wmmps_ac = 0; - struct sta_info *psta_bmc; - struct list_head *phead; - struct xmit_frame *pxmitframe = NULL, *ptmp; - struct sta_priv *pstapriv = &padapter->stapriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - spin_lock_bh(&pxmitpriv->lock); - phead = get_list_head(&psta->sleep_q); - list_for_each_entry_safe(pxmitframe, ptmp, phead, list) { - list_del_init(&pxmitframe->list); - - switch (pxmitframe->attrib.priority) { - case 1: - case 2: - wmmps_ac = psta->uapsd_bk & BIT(1); - break; - case 4: - case 5: - wmmps_ac = psta->uapsd_vi & BIT(1); - break; - case 6: - case 7: - wmmps_ac = psta->uapsd_vo & BIT(1); - break; - case 0: - case 3: - default: - wmmps_ac = psta->uapsd_be & BIT(1); - break; - } - - psta->sleepq_len--; - if (psta->sleepq_len > 0) - pxmitframe->attrib.mdata = 1; - else - pxmitframe->attrib.mdata = 0; - - if (wmmps_ac) { - psta->sleepq_ac_len--; - if (psta->sleepq_ac_len > 0) { - pxmitframe->attrib.mdata = 1; - pxmitframe->attrib.eosp = 0; - } else { - pxmitframe->attrib.mdata = 0; - pxmitframe->attrib.eosp = 1; - } - } - - pxmitframe->attrib.triggered = 1; - rtl8723au_hal_xmitframe_enqueue(padapter, pxmitframe); - } - - if (psta->sleepq_len == 0) { - pstapriv->tim_bitmap &= ~CHKBIT(psta->aid); - - /* update BCN for TIM IE */ - update_mask = BIT(0); - - if (psta->state&WIFI_SLEEP_STATE) - psta->state ^= WIFI_SLEEP_STATE; - - if (psta->state & WIFI_STA_ALIVE_CHK_STATE) { - psta->expire_to = pstapriv->expire_to; - psta->state ^= WIFI_STA_ALIVE_CHK_STATE; - } - - pstapriv->sta_dz_bitmap &= ~CHKBIT(psta->aid); - } - /* spin_unlock_bh(&psta->sleep_q.lock); */ - spin_unlock_bh(&pxmitpriv->lock); - - /* for BC/MC Frames */ - psta_bmc = rtw_get_bcmc_stainfo23a(padapter); - if (!psta_bmc) - return; - - if ((pstapriv->sta_dz_bitmap&0xfffe) == 0x0) { - /* no any sta in ps mode */ - spin_lock_bh(&pxmitpriv->lock); - phead = get_list_head(&psta_bmc->sleep_q); - list_for_each_entry_safe(pxmitframe, ptmp, phead, list) { - list_del_init(&pxmitframe->list); - - psta_bmc->sleepq_len--; - if (psta_bmc->sleepq_len > 0) - pxmitframe->attrib.mdata = 1; - else - pxmitframe->attrib.mdata = 0; - - pxmitframe->attrib.triggered = 1; - rtl8723au_hal_xmitframe_enqueue(padapter, pxmitframe); - } - if (psta_bmc->sleepq_len == 0) { - pstapriv->tim_bitmap &= ~BIT(0); - pstapriv->sta_dz_bitmap &= ~BIT(0); - - /* update BCN for TIM IE */ - /* update_BCNTIM(padapter); */ - update_mask |= BIT(1); - } - /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */ - spin_unlock_bh(&pxmitpriv->lock); - } - - if (update_mask) - update_beacon23a(padapter, WLAN_EID_TIM, NULL, false); -} - -void xmit_delivery_enabled_frames23a(struct rtw_adapter *padapter, - struct sta_info *psta) -{ - u8 wmmps_ac = 0; - struct list_head *phead; - struct xmit_frame *pxmitframe, *ptmp; - struct sta_priv *pstapriv = &padapter->stapriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - /* spin_lock_bh(&psta->sleep_q.lock); */ - spin_lock_bh(&pxmitpriv->lock); - phead = get_list_head(&psta->sleep_q); - list_for_each_entry_safe(pxmitframe, ptmp, phead, list) { - switch (pxmitframe->attrib.priority) { - case 1: - case 2: - wmmps_ac = psta->uapsd_bk & BIT(1); - break; - case 4: - case 5: - wmmps_ac = psta->uapsd_vi & BIT(1); - break; - case 6: - case 7: - wmmps_ac = psta->uapsd_vo & BIT(1); - break; - case 0: - case 3: - default: - wmmps_ac = psta->uapsd_be & BIT(1); - break; - } - - if (!wmmps_ac) - continue; - - list_del_init(&pxmitframe->list); - - psta->sleepq_len--; - psta->sleepq_ac_len--; - - if (psta->sleepq_ac_len > 0) { - pxmitframe->attrib.mdata = 1; - pxmitframe->attrib.eosp = 0; - } else { - pxmitframe->attrib.mdata = 0; - pxmitframe->attrib.eosp = 1; - } - - pxmitframe->attrib.triggered = 1; - - rtl8723au_hal_xmitframe_enqueue(padapter, pxmitframe); - - if ((psta->sleepq_ac_len == 0) && (!psta->has_legacy_ac) && - (wmmps_ac)) { - pstapriv->tim_bitmap &= ~CHKBIT(psta->aid); - - /* update BCN for TIM IE */ - update_beacon23a(padapter, WLAN_EID_TIM, NULL, false); - } - } - spin_unlock_bh(&pxmitpriv->lock); -} - -#endif - -void rtw_sctx_init23a(struct submit_ctx *sctx, int timeout_ms) -{ - sctx->timeout_ms = timeout_ms; - init_completion(&sctx->done); - sctx->status = RTW_SCTX_SUBMITTED; -} - -int rtw_sctx_wait23a(struct submit_ctx *sctx) -{ - int ret = _FAIL; - unsigned long expire; - int status = 0; - - expire = sctx->timeout_ms ? msecs_to_jiffies(sctx->timeout_ms) : - MAX_SCHEDULE_TIMEOUT; - if (!wait_for_completion_timeout(&sctx->done, expire)) { - /* timeout, do something?? */ - status = RTW_SCTX_DONE_TIMEOUT; - DBG_8723A("%s timeout\n", __func__); - } else { - status = sctx->status; - } - - if (status == RTW_SCTX_DONE_SUCCESS) - ret = _SUCCESS; - - return ret; -} - -static bool rtw_sctx_chk_waring_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 rtw23a_sctx_done_err(struct submit_ctx **sctx, int status) -{ - if (*sctx) { - if (rtw_sctx_chk_waring_status(status)) - DBG_8723A("%s status:%d\n", __func__, status); - (*sctx)->status = status; - complete(&(*sctx)->done); - *sctx = NULL; - } -} - -int rtw_ack_tx_wait23a(struct xmit_priv *pxmitpriv, u32 timeout_ms) -{ - struct submit_ctx *pack_tx_ops = &pxmitpriv->ack_tx_ops; - - pack_tx_ops->timeout_ms = timeout_ms; - pack_tx_ops->status = RTW_SCTX_SUBMITTED; - - return rtw_sctx_wait23a(pack_tx_ops); -} - diff --git a/drivers/staging/rtl8723au/hal/Hal8723PwrSeq.c b/drivers/staging/rtl8723au/hal/Hal8723PwrSeq.c deleted file mode 100644 index 747f86c..0000000 --- a/drivers/staging/rtl8723au/hal/Hal8723PwrSeq.c +++ /dev/null @@ -1,80 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ - -#include "Hal8723PwrSeq.h" - -/* - drivers should parse below arrays and do the corresponding actions -*/ -/* 3 Power on Array */ -struct wlan_pwr_cfg rtl8723AU_power_on_flow[RTL8723A_TRANS_CARDEMU_TO_ACT_STEPS+RTL8723A_TRANS_END_STEPS] = { - RTL8723A_TRANS_CARDEMU_TO_ACT - RTL8723A_TRANS_END -}; - -/* 3 Radio off GPIO Array */ -struct wlan_pwr_cfg rtl8723AU_radio_off_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_END_STEPS] = { - RTL8723A_TRANS_ACT_TO_CARDEMU - RTL8723A_TRANS_END -}; - -/* 3 Card Disable Array */ -struct wlan_pwr_cfg rtl8723AU_card_disable_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS+RTL8723A_TRANS_END_STEPS] = { - RTL8723A_TRANS_ACT_TO_CARDEMU - RTL8723A_TRANS_CARDEMU_TO_CARDDIS - RTL8723A_TRANS_END -}; - -/* 3 Card Enable Array */ -struct wlan_pwr_cfg rtl8723AU_card_enable_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS+RTL8723A_TRANS_END_STEPS] = { - RTL8723A_TRANS_CARDDIS_TO_CARDEMU - RTL8723A_TRANS_CARDEMU_TO_ACT - RTL8723A_TRANS_END -}; - -/* 3 Suspend Array */ -struct wlan_pwr_cfg rtl8723AU_suspend_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_SUS_STEPS+RTL8723A_TRANS_END_STEPS] = { - RTL8723A_TRANS_ACT_TO_CARDEMU - RTL8723A_TRANS_CARDEMU_TO_SUS - RTL8723A_TRANS_END -}; - -/* 3 Resume Array */ -struct wlan_pwr_cfg rtl8723AU_resume_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_SUS_STEPS+RTL8723A_TRANS_END_STEPS] = { - RTL8723A_TRANS_SUS_TO_CARDEMU - RTL8723A_TRANS_CARDEMU_TO_ACT - RTL8723A_TRANS_END -}; - -/* 3 HWPDN Array */ -struct wlan_pwr_cfg rtl8723AU_hwpdn_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS+RTL8723A_TRANS_END_STEPS] = { - RTL8723A_TRANS_ACT_TO_CARDEMU - RTL8723A_TRANS_CARDEMU_TO_PDN - RTL8723A_TRANS_END -}; - -/* 3 Enter LPS */ -struct wlan_pwr_cfg rtl8723AU_enter_lps_flow[RTL8723A_TRANS_ACT_TO_LPS_STEPS+RTL8723A_TRANS_END_STEPS] = { - /* FW behavior */ - RTL8723A_TRANS_ACT_TO_LPS - RTL8723A_TRANS_END -}; - -/* 3 Leave LPS */ -struct wlan_pwr_cfg rtl8723AU_leave_lps_flow[RTL8723A_TRANS_LPS_TO_ACT_STEPS+RTL8723A_TRANS_END_STEPS] = { - /* FW behavior */ - RTL8723A_TRANS_LPS_TO_ACT - RTL8723A_TRANS_END -}; diff --git a/drivers/staging/rtl8723au/hal/Hal8723UHWImg_CE.c b/drivers/staging/rtl8723au/hal/Hal8723UHWImg_CE.c deleted file mode 100644 index 56833da..0000000 --- a/drivers/staging/rtl8723au/hal/Hal8723UHWImg_CE.c +++ /dev/null @@ -1,136 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ - -/*Created on 2013/01/14, 15:51*/ -#include "odm_precomp.h" - -u32 Rtl8723UPHY_REG_Array_PG[Rtl8723UPHY_REG_Array_PGLength] = { - 0xe00, 0xffffffff, 0x0a0c0c0c, - 0xe04, 0xffffffff, 0x02040608, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x0a0c0d0e, - 0xe14, 0xffffffff, 0x02040608, - 0xe18, 0xffffffff, 0x0a0c0d0e, - 0xe1c, 0xffffffff, 0x02040608, - 0x830, 0xffffffff, 0x0a0c0c0c, - 0x834, 0xffffffff, 0x02040608, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x0a0c0d0e, - 0x848, 0xffffffff, 0x02040608, - 0x84c, 0xffffffff, 0x0a0c0d0e, - 0x868, 0xffffffff, 0x02040608, - 0xe00, 0xffffffff, 0x00000000, - 0xe04, 0xffffffff, 0x00000000, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x00000000, - 0x834, 0xffffffff, 0x00000000, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x04040404, - 0xe04, 0xffffffff, 0x00020204, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x06060606, - 0xe14, 0xffffffff, 0x00020406, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x04040404, - 0x834, 0xffffffff, 0x00020204, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x06060606, - 0x848, 0xffffffff, 0x00020406, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x00000000, - 0xe04, 0xffffffff, 0x00000000, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x00000000, - 0x834, 0xffffffff, 0x00000000, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x00000000, - 0xe04, 0xffffffff, 0x00000000, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x00000000, - 0x834, 0xffffffff, 0x00000000, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x04040404, - 0xe04, 0xffffffff, 0x00020204, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x04040404, - 0x834, 0xffffffff, 0x00020204, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x00000000, - 0xe04, 0xffffffff, 0x00000000, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x00000000, - 0x834, 0xffffffff, 0x00000000, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - }; - -u32 Rtl8723UMACPHY_Array_PG[Rtl8723UMACPHY_Array_PGLength] = { - 0x0, -}; diff --git a/drivers/staging/rtl8723au/hal/HalDMOutSrc8723A_CE.c b/drivers/staging/rtl8723au/hal/HalDMOutSrc8723A_CE.c deleted file mode 100644 index 3f9ec9e0..0000000 --- a/drivers/staging/rtl8723au/hal/HalDMOutSrc8723A_CE.c +++ /dev/null @@ -1,1097 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -/* Description: */ -/* This file is for 92CE/92CU dynamic mechanism only */ - -/* include files */ - -#include "odm_precomp.h" -#include <usb_ops_linux.h> - -#define DPK_DELTA_MAPPING_NUM 13 -#define index_mapping_HP_NUM 15 -/* 091212 chiyokolin */ -static void -odm_TXPowerTrackingCallback_ThermalMeter_92C(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - u8 ThermalValue = 0, delta, delta_LCK, delta_IQK, delta_HP; - int ele_A, ele_D, TempCCk, X, value32; - int Y, ele_C; - s8 OFDM_index[2], CCK_index = 0, OFDM_index_old[2] = {0}; - s8 CCK_index_old = 0; - int i = 0; - u8 OFDM_min_index = 6, rf; /* OFDM BB Swing should be less than +3.0dB*/ - u8 ThermalValue_HP_count = 0; - u32 ThermalValue_HP = 0; - s32 index_mapping_HP[index_mapping_HP_NUM] = { - 0, 1, 3, 4, 6, - 7, 9, 10, 12, 13, - 15, 16, 18, 19, 21 - }; - s8 index_HP; - - pdmpriv->TXPowerTrackingCallbackCnt++; /* cosa add for debug */ - pdmpriv->bTXPowerTrackingInit = true; - - if (pHalData->CurrentChannel == 14 && !pdmpriv->bCCKinCH14) - pdmpriv->bCCKinCH14 = true; - else if (pHalData->CurrentChannel != 14 && pdmpriv->bCCKinCH14) - pdmpriv->bCCKinCH14 = false; - - ThermalValue = (u8)PHY_QueryRFReg(Adapter, RF_PATH_A, RF_T_METER, - 0x1f);/* 0x24: RF Reg[4:0] */ - - rtl8723a_phy_ap_calibrate(Adapter, (ThermalValue - - pHalData->EEPROMThermalMeter)); - - if (pHalData->rf_type == RF_2T2R) - rf = 2; - else - rf = 1; - - if (ThermalValue) { - /* Query OFDM path A default setting */ - ele_D = rtl8723au_read32(Adapter, rOFDM0_XATxIQImbalance) & - bMaskOFDM_D; - for (i = 0; i < OFDM_TABLE_SIZE_92C; i++) { - /* find the index */ - if (ele_D == (OFDMSwingTable23A[i]&bMaskOFDM_D)) { - OFDM_index_old[0] = (u8)i; - break; - } - } - - /* Query OFDM path B default setting */ - if (pHalData->rf_type == RF_2T2R) { - ele_D = rtl8723au_read32(Adapter, - rOFDM0_XBTxIQImbalance); - ele_D &= bMaskOFDM_D; - for (i = 0; i < OFDM_TABLE_SIZE_92C; i++) { /* find the index */ - if (ele_D == (OFDMSwingTable23A[i]&bMaskOFDM_D)) { - OFDM_index_old[1] = (u8)i; - break; - } - } - } - - /* Query CCK default setting From 0xa24 */ - TempCCk = rtl8723au_read32(Adapter, rCCK0_TxFilter2) & bMaskCCK; - for (i = 0 ; i < CCK_TABLE_SIZE ; i++) { - if (pdmpriv->bCCKinCH14) { - if (!memcmp(&TempCCk, - &CCKSwingTable_Ch1423A[i][2], 4)) { - CCK_index_old = (u8)i; - break; - } - } else { - if (!memcmp(&TempCCk, - &CCKSwingTable_Ch1_Ch1323A[i][2], 4)) { - CCK_index_old = (u8)i; - break; - } - } - } - - if (!pdmpriv->ThermalValue) { - pdmpriv->ThermalValue = pHalData->EEPROMThermalMeter; - pdmpriv->ThermalValue_LCK = ThermalValue; - pdmpriv->ThermalValue_IQK = ThermalValue; - pdmpriv->ThermalValue_DPK = pHalData->EEPROMThermalMeter; - - for (i = 0; i < rf; i++) { - pdmpriv->OFDM_index_HP[i] = OFDM_index_old[i]; - pdmpriv->OFDM_index[i] = OFDM_index_old[i]; - } - pdmpriv->CCK_index_HP = CCK_index_old; - pdmpriv->CCK_index = CCK_index_old; - } - - if (pHalData->BoardType == BOARD_USB_High_PA) { - pdmpriv->ThermalValue_HP[pdmpriv->ThermalValue_HP_index] = ThermalValue; - pdmpriv->ThermalValue_HP_index++; - if (pdmpriv->ThermalValue_HP_index == HP_THERMAL_NUM) - pdmpriv->ThermalValue_HP_index = 0; - - for (i = 0; i < HP_THERMAL_NUM; i++) { - if (pdmpriv->ThermalValue_HP[i]) { - ThermalValue_HP += pdmpriv->ThermalValue_HP[i]; - ThermalValue_HP_count++; - } - } - - if (ThermalValue_HP_count) - ThermalValue = (u8)(ThermalValue_HP / ThermalValue_HP_count); - } - - delta = (ThermalValue > pdmpriv->ThermalValue) ? - (ThermalValue - pdmpriv->ThermalValue) : - (pdmpriv->ThermalValue - ThermalValue); - if (pHalData->BoardType == BOARD_USB_High_PA) { - if (pdmpriv->bDoneTxpower) - delta_HP = (ThermalValue > pdmpriv->ThermalValue) ? - (ThermalValue - pdmpriv->ThermalValue) : - (pdmpriv->ThermalValue - ThermalValue); - else - delta_HP = ThermalValue > pHalData->EEPROMThermalMeter ? - (ThermalValue - pHalData->EEPROMThermalMeter) : - (pHalData->EEPROMThermalMeter - ThermalValue); - } else { - delta_HP = 0; - } - delta_LCK = (ThermalValue > pdmpriv->ThermalValue_LCK) ? - (ThermalValue - pdmpriv->ThermalValue_LCK) : - (pdmpriv->ThermalValue_LCK - ThermalValue); - delta_IQK = (ThermalValue > pdmpriv->ThermalValue_IQK) ? - (ThermalValue - pdmpriv->ThermalValue_IQK) : - (pdmpriv->ThermalValue_IQK - ThermalValue); - - if (delta_LCK > 1) { - pdmpriv->ThermalValue_LCK = ThermalValue; - rtl8723a_phy_lc_calibrate(Adapter); - } - - if ((delta > 0 || delta_HP > 0) && pdmpriv->TxPowerTrackControl) { - if (pHalData->BoardType == BOARD_USB_High_PA) { - pdmpriv->bDoneTxpower = true; - delta_HP = ThermalValue > pHalData->EEPROMThermalMeter ? - (ThermalValue - pHalData->EEPROMThermalMeter) : - (pHalData->EEPROMThermalMeter - ThermalValue); - - if (delta_HP > index_mapping_HP_NUM-1) - index_HP = index_mapping_HP[index_mapping_HP_NUM-1]; - else - index_HP = index_mapping_HP[delta_HP]; - - if (ThermalValue > pHalData->EEPROMThermalMeter) { - /* set larger Tx power */ - for (i = 0; i < rf; i++) - OFDM_index[i] = pdmpriv->OFDM_index_HP[i] - index_HP; - CCK_index = pdmpriv->CCK_index_HP - index_HP; - } else { - for (i = 0; i < rf; i++) - OFDM_index[i] = pdmpriv->OFDM_index_HP[i] + index_HP; - CCK_index = pdmpriv->CCK_index_HP + index_HP; - } - - delta_HP = (ThermalValue > pdmpriv->ThermalValue) ? - (ThermalValue - pdmpriv->ThermalValue) : - (pdmpriv->ThermalValue - ThermalValue); - } else { - if (ThermalValue > pdmpriv->ThermalValue) { - for (i = 0; i < rf; i++) - pdmpriv->OFDM_index[i] -= delta; - pdmpriv->CCK_index -= delta; - } else { - for (i = 0; i < rf; i++) - pdmpriv->OFDM_index[i] += delta; - pdmpriv->CCK_index += delta; - } - } - - /* no adjust */ - if (pHalData->BoardType != BOARD_USB_High_PA) { - if (ThermalValue > pHalData->EEPROMThermalMeter) { - for (i = 0; i < rf; i++) - OFDM_index[i] = pdmpriv->OFDM_index[i]+1; - CCK_index = pdmpriv->CCK_index+1; - } else { - for (i = 0; i < rf; i++) - OFDM_index[i] = pdmpriv->OFDM_index[i]; - CCK_index = pdmpriv->CCK_index; - } - } - for (i = 0; i < rf; i++) { - if (OFDM_index[i] > (OFDM_TABLE_SIZE_92C-1)) - OFDM_index[i] = (OFDM_TABLE_SIZE_92C-1); - else if (OFDM_index[i] < OFDM_min_index) - OFDM_index[i] = OFDM_min_index; - } - - if (CCK_index > (CCK_TABLE_SIZE-1)) - CCK_index = CCK_TABLE_SIZE-1; - else if (CCK_index < 0) - CCK_index = 0; - } - - if (pdmpriv->TxPowerTrackControl && - (delta != 0 || delta_HP != 0)) { - /* Adujst OFDM Ant_A according to IQK result */ - ele_D = (OFDMSwingTable23A[OFDM_index[0]] & 0xFFC00000)>>22; - X = pdmpriv->RegE94; - Y = pdmpriv->RegE9C; - - if (X != 0) { - if ((X & 0x00000200) != 0) - X = X | 0xFFFFFC00; - ele_A = ((X * ele_D)>>8)&0x000003FF; - - /* new element C = element D x Y */ - if ((Y & 0x00000200) != 0) - Y = Y | 0xFFFFFC00; - ele_C = ((Y * ele_D)>>8)&0x000003FF; - - /* write new elements A, C, D to regC80 and regC94, element B is always 0 */ - value32 = (ele_D<<22)|((ele_C&0x3F)<<16)|ele_A; - rtl8723au_write32(Adapter, - rOFDM0_XATxIQImbalance, - value32); - - value32 = (ele_C&0x000003C0)>>6; - PHY_SetBBReg(Adapter, rOFDM0_XCTxAFE, bMaskH4Bits, value32); - - value32 = ((X * ele_D)>>7)&0x01; - PHY_SetBBReg(Adapter, rOFDM0_ECCAThreshold, - BIT(31), value32); - - value32 = ((Y * ele_D)>>7)&0x01; - PHY_SetBBReg(Adapter, rOFDM0_ECCAThreshold, - BIT(29), value32); - } else { - rtl8723au_write32(Adapter, - rOFDM0_XATxIQImbalance, - OFDMSwingTable23A[OFDM_index[0]]); - PHY_SetBBReg(Adapter, rOFDM0_XCTxAFE, - bMaskH4Bits, 0x00); - PHY_SetBBReg(Adapter, rOFDM0_ECCAThreshold, - BIT(31) | BIT(29), 0x00); - } - - /* Adjust CCK according to IQK result */ - if (!pdmpriv->bCCKinCH14) { - rtl8723au_write8(Adapter, 0xa22, CCKSwingTable_Ch1_Ch1323A[CCK_index][0]); - rtl8723au_write8(Adapter, 0xa23, CCKSwingTable_Ch1_Ch1323A[CCK_index][1]); - rtl8723au_write8(Adapter, 0xa24, CCKSwingTable_Ch1_Ch1323A[CCK_index][2]); - rtl8723au_write8(Adapter, 0xa25, CCKSwingTable_Ch1_Ch1323A[CCK_index][3]); - rtl8723au_write8(Adapter, 0xa26, CCKSwingTable_Ch1_Ch1323A[CCK_index][4]); - rtl8723au_write8(Adapter, 0xa27, CCKSwingTable_Ch1_Ch1323A[CCK_index][5]); - rtl8723au_write8(Adapter, 0xa28, CCKSwingTable_Ch1_Ch1323A[CCK_index][6]); - rtl8723au_write8(Adapter, 0xa29, CCKSwingTable_Ch1_Ch1323A[CCK_index][7]); - } else { - rtl8723au_write8(Adapter, 0xa22, CCKSwingTable_Ch1423A[CCK_index][0]); - rtl8723au_write8(Adapter, 0xa23, CCKSwingTable_Ch1423A[CCK_index][1]); - rtl8723au_write8(Adapter, 0xa24, CCKSwingTable_Ch1423A[CCK_index][2]); - rtl8723au_write8(Adapter, 0xa25, CCKSwingTable_Ch1423A[CCK_index][3]); - rtl8723au_write8(Adapter, 0xa26, CCKSwingTable_Ch1423A[CCK_index][4]); - rtl8723au_write8(Adapter, 0xa27, CCKSwingTable_Ch1423A[CCK_index][5]); - rtl8723au_write8(Adapter, 0xa28, CCKSwingTable_Ch1423A[CCK_index][6]); - rtl8723au_write8(Adapter, 0xa29, CCKSwingTable_Ch1423A[CCK_index][7]); - } - - if (pHalData->rf_type == RF_2T2R) { - ele_D = (OFDMSwingTable23A[(u8)OFDM_index[1]] & 0xFFC00000)>>22; - - /* new element A = element D x X */ - X = pdmpriv->RegEB4; - Y = pdmpriv->RegEBC; - - if (X != 0) { - if ((X & 0x00000200) != 0) /* consider minus */ - X = X | 0xFFFFFC00; - ele_A = ((X * ele_D)>>8)&0x000003FF; - - /* new element C = element D x Y */ - if ((Y & 0x00000200) != 0) - Y = Y | 0xFFFFFC00; - ele_C = ((Y * ele_D)>>8)&0x00003FF; - - /* write new elements A, C, D to regC88 and regC9C, element B is always 0 */ - value32 = (ele_D<<22)|((ele_C&0x3F)<<16) | ele_A; - rtl8723au_write32(Adapter, rOFDM0_XBTxIQImbalance, value32); - - value32 = (ele_C&0x000003C0)>>6; - PHY_SetBBReg(Adapter, rOFDM0_XDTxAFE, bMaskH4Bits, value32); - - value32 = ((X * ele_D)>>7)&0x01; - PHY_SetBBReg(Adapter, - rOFDM0_ECCAThreshold, - BIT(27), value32); - - value32 = ((Y * ele_D)>>7)&0x01; - PHY_SetBBReg(Adapter, - rOFDM0_ECCAThreshold, - BIT(25), value32); - } else { - rtl8723au_write32(Adapter, - rOFDM0_XBTxIQImbalance, - OFDMSwingTable23A[OFDM_index[1]]); - PHY_SetBBReg(Adapter, - rOFDM0_XDTxAFE, - bMaskH4Bits, 0x00); - PHY_SetBBReg(Adapter, - rOFDM0_ECCAThreshold, - BIT(27) | BIT(25), 0x00); - } - } - - } - if (delta_IQK > 3) { - pdmpriv->ThermalValue_IQK = ThermalValue; - rtl8723a_phy_iq_calibrate(Adapter, false); - } - - /* update thermal meter value */ - if (pdmpriv->TxPowerTrackControl) - pdmpriv->ThermalValue = ThermalValue; - } - pdmpriv->TXPowercount = 0; -} - -/* Description: */ -/* - Dispatch TxPower Tracking direct call ONLY for 92s. */ -/* - We shall NOT schedule Workitem within PASSIVE LEVEL, which will cause system resource */ -/* leakage under some platform. */ -/* Assumption: */ -/* PASSIVE_LEVEL when this routine is called. */ -static void ODM_TXPowerTracking92CDirectCall(struct rtw_adapter *Adapter) -{ - odm_TXPowerTrackingCallback_ThermalMeter_92C(Adapter); -} - -void rtl8723a_odm_check_tx_power_tracking(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - - if (!pdmpriv->TM_Trigger) { /* at least delay 1 sec */ - PHY_SetRFReg(Adapter, RF_PATH_A, RF_T_METER, bRFRegOffsetMask, 0x60); - - pdmpriv->TM_Trigger = 1; - return; - } else { - ODM_TXPowerTracking92CDirectCall(Adapter); - pdmpriv->TM_Trigger = 0; - } -} - -/* IQK */ -#define MAX_TOLERANCE 5 -#define IQK_DELAY_TIME 1 /* ms */ - -static u8 _PHY_PathA_IQK(struct rtw_adapter *pAdapter, bool configPathB) -{ - u32 regEAC, regE94, regE9C, regEA4; - u8 result = 0x00; - struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter); - - /* path-A IQK setting */ - rtl8723au_write32(pAdapter, rTx_IQK_Tone_A, 0x10008c1f); - rtl8723au_write32(pAdapter, rRx_IQK_Tone_A, 0x10008c1f); - rtl8723au_write32(pAdapter, rTx_IQK_PI_A, 0x82140102); - - rtl8723au_write32(pAdapter, rRx_IQK_PI_A, configPathB ? 0x28160202 : - IS_81xxC_VENDOR_UMC_B_CUT(pHalData->VersionID)?0x28160202:0x28160502); - - /* path-B IQK setting */ - if (configPathB) { - rtl8723au_write32(pAdapter, rTx_IQK_Tone_B, 0x10008c22); - rtl8723au_write32(pAdapter, rRx_IQK_Tone_B, 0x10008c22); - rtl8723au_write32(pAdapter, rTx_IQK_PI_B, 0x82140102); - rtl8723au_write32(pAdapter, rRx_IQK_PI_B, 0x28160202); - } - - /* LO calibration setting */ - rtl8723au_write32(pAdapter, rIQK_AGC_Rsp, 0x001028d1); - - /* One shot, path A LOK & IQK */ - rtl8723au_write32(pAdapter, rIQK_AGC_Pts, 0xf9000000); - rtl8723au_write32(pAdapter, rIQK_AGC_Pts, 0xf8000000); - - /* delay x ms */ - /* PlatformStallExecution(IQK_DELAY_TIME*1000); */ - udelay(IQK_DELAY_TIME*1000); - - /* Check failed */ - regEAC = rtl8723au_read32(pAdapter, rRx_Power_After_IQK_A_2); - regE94 = rtl8723au_read32(pAdapter, rTx_Power_Before_IQK_A); - regE9C = rtl8723au_read32(pAdapter, rTx_Power_After_IQK_A); - regEA4 = rtl8723au_read32(pAdapter, rRx_Power_Before_IQK_A_2); - - if (!(regEAC & BIT(28)) && - (((regE94 & 0x03FF0000)>>16) != 0x142) && - (((regE9C & 0x03FF0000)>>16) != 0x42)) - result |= 0x01; - else /* if Tx not OK, ignore Rx */ - return result; - - if (!(regEAC & BIT(27)) && /* if Tx is OK, check whether Rx is OK */ - (((regEA4 & 0x03FF0000)>>16) != 0x132) && - (((regEAC & 0x03FF0000)>>16) != 0x36)) - result |= 0x02; - else - DBG_8723A("Path A Rx IQK fail!!\n"); - return result; -} - -static u8 _PHY_PathB_IQK(struct rtw_adapter *pAdapter) -{ - u32 regEAC, regEB4, regEBC, regEC4, regECC; - u8 result = 0x00; - - /* One shot, path B LOK & IQK */ - rtl8723au_write32(pAdapter, rIQK_AGC_Cont, 0x00000002); - rtl8723au_write32(pAdapter, rIQK_AGC_Cont, 0x00000000); - - /* delay x ms */ - udelay(IQK_DELAY_TIME*1000); - - /* Check failed */ - regEAC = rtl8723au_read32(pAdapter, rRx_Power_After_IQK_A_2); - regEB4 = rtl8723au_read32(pAdapter, rTx_Power_Before_IQK_B); - regEBC = rtl8723au_read32(pAdapter, rTx_Power_After_IQK_B); - regEC4 = rtl8723au_read32(pAdapter, rRx_Power_Before_IQK_B_2); - regECC = rtl8723au_read32(pAdapter, rRx_Power_After_IQK_B_2); - - if (!(regEAC & BIT(31)) && - (((regEB4 & 0x03FF0000)>>16) != 0x142) && - (((regEBC & 0x03FF0000)>>16) != 0x42)) - result |= 0x01; - else - return result; - - if (!(regEAC & BIT(30)) && - (((regEC4 & 0x03FF0000)>>16) != 0x132) && - (((regECC & 0x03FF0000)>>16) != 0x36)) - result |= 0x02; - else - DBG_8723A("Path B Rx IQK fail!!\n"); - return result; -} - -static void _PHY_PathAFillIQKMatrix(struct rtw_adapter *pAdapter, - bool bIQKOK, - int result[][8], - u8 final_candidate, - bool bTxOnly - ) -{ - u32 Oldval_0, X, TX0_A, reg; - s32 Y, TX0_C; - - DBG_8723A("Path A IQ Calibration %s !\n", (bIQKOK)?"Success":"Failed"); - - if (final_candidate == 0xFF) { - return; - } else if (bIQKOK) { - Oldval_0 = rtl8723au_read32(pAdapter, rOFDM0_XATxIQImbalance); - Oldval_0 = (Oldval_0 >> 22) & 0x3FF; - - X = result[final_candidate][0]; - if ((X & 0x00000200) != 0) - X = X | 0xFFFFFC00; - TX0_A = (X * Oldval_0) >> 8; - PHY_SetBBReg(pAdapter, rOFDM0_XATxIQImbalance, 0x3FF, TX0_A); - PHY_SetBBReg(pAdapter, rOFDM0_ECCAThreshold, BIT(31), - ((X * Oldval_0>>7) & 0x1)); - - Y = result[final_candidate][1]; - if ((Y & 0x00000200) != 0) - Y = Y | 0xFFFFFC00; - TX0_C = (Y * Oldval_0) >> 8; - PHY_SetBBReg(pAdapter, rOFDM0_XCTxAFE, 0xF0000000, - ((TX0_C&0x3C0)>>6)); - PHY_SetBBReg(pAdapter, rOFDM0_XATxIQImbalance, 0x003F0000, - (TX0_C&0x3F)); - PHY_SetBBReg(pAdapter, rOFDM0_ECCAThreshold, BIT(29), - ((Y * Oldval_0>>7) & 0x1)); - - if (bTxOnly) { - DBG_8723A("_PHY_PathAFillIQKMatrix only Tx OK\n"); - return; - } - - reg = result[final_candidate][2]; - PHY_SetBBReg(pAdapter, rOFDM0_XARxIQImbalance, 0x3FF, reg); - - reg = result[final_candidate][3] & 0x3F; - PHY_SetBBReg(pAdapter, rOFDM0_XARxIQImbalance, 0xFC00, reg); - - reg = (result[final_candidate][3] >> 6) & 0xF; - PHY_SetBBReg(pAdapter, rOFDM0_RxIQExtAnta, 0xF0000000, reg); - } -} - -static void _PHY_PathBFillIQKMatrix(struct rtw_adapter *pAdapter, bool bIQKOK, int result[][8], u8 final_candidate, bool bTxOnly) -{ - u32 Oldval_1, X, TX1_A, reg; - s32 Y, TX1_C; - - DBG_8723A("Path B IQ Calibration %s !\n", (bIQKOK)?"Success":"Failed"); - - if (final_candidate == 0xFF) { - return; - } else if (bIQKOK) { - Oldval_1 = rtl8723au_read32(pAdapter, rOFDM0_XBTxIQImbalance); - Oldval_1 = (Oldval_1 >> 22) & 0x3FF; - - X = result[final_candidate][4]; - if ((X & 0x00000200) != 0) - X = X | 0xFFFFFC00; - TX1_A = (X * Oldval_1) >> 8; - PHY_SetBBReg(pAdapter, rOFDM0_XBTxIQImbalance, 0x3FF, TX1_A); - PHY_SetBBReg(pAdapter, rOFDM0_ECCAThreshold, BIT(27), - ((X * Oldval_1 >> 7) & 0x1)); - - Y = result[final_candidate][5]; - if ((Y & 0x00000200) != 0) - Y = Y | 0xFFFFFC00; - TX1_C = (Y * Oldval_1) >> 8; - PHY_SetBBReg(pAdapter, rOFDM0_XDTxAFE, 0xF0000000, - ((TX1_C & 0x3C0) >> 6)); - PHY_SetBBReg(pAdapter, rOFDM0_XBTxIQImbalance, 0x003F0000, - (TX1_C & 0x3F)); - PHY_SetBBReg(pAdapter, rOFDM0_ECCAThreshold, BIT(25), - ((Y * Oldval_1 >> 7) & 0x1)); - - if (bTxOnly) - return; - - reg = result[final_candidate][6]; - PHY_SetBBReg(pAdapter, rOFDM0_XBRxIQImbalance, 0x3FF, reg); - - reg = result[final_candidate][7] & 0x3F; - PHY_SetBBReg(pAdapter, rOFDM0_XBRxIQImbalance, 0xFC00, reg); - - reg = (result[final_candidate][7] >> 6) & 0xF; - PHY_SetBBReg(pAdapter, rOFDM0_AGCRSSITable, 0x0000F000, reg); - } -} - -static void _PHY_SaveADDARegisters(struct rtw_adapter *pAdapter, u32 *ADDAReg, u32 *ADDABackup, u32 RegisterNum) -{ - u32 i; - - for (i = 0 ; i < RegisterNum ; i++) { - ADDABackup[i] = rtl8723au_read32(pAdapter, ADDAReg[i]); - } -} - -static void _PHY_SaveMACRegisters(struct rtw_adapter *pAdapter, u32 *MACReg, - u32 *MACBackup) -{ - u32 i; - - for (i = 0 ; i < (IQK_MAC_REG_NUM - 1); i++) { - MACBackup[i] = rtl8723au_read8(pAdapter, MACReg[i]); - } - MACBackup[i] = rtl8723au_read32(pAdapter, MACReg[i]); -} - -static void _PHY_ReloadADDARegisters(struct rtw_adapter *pAdapter, - u32 *ADDAReg, u32 *ADDABackup, - u32 RegiesterNum) -{ - u32 i; - - for (i = 0 ; i < RegiesterNum ; i++) { - rtl8723au_write32(pAdapter, ADDAReg[i], ADDABackup[i]); - } -} - -static void _PHY_ReloadMACRegisters(struct rtw_adapter *pAdapter, - u32 *MACReg, u32 *MACBackup) -{ - u32 i; - - for (i = 0 ; i < (IQK_MAC_REG_NUM - 1); i++) - rtl8723au_write8(pAdapter, MACReg[i], (u8)MACBackup[i]); - - rtl8723au_write32(pAdapter, MACReg[i], MACBackup[i]); -} - -static void _PHY_PathADDAOn(struct rtw_adapter *pAdapter, u32 *ADDAReg, - bool isPathAOn, bool is2T) -{ - u32 pathOn; - u32 i; - - pathOn = isPathAOn ? 0x04db25a4 : 0x0b1b25a4; - if (!is2T) { - pathOn = 0x0bdb25a0; - rtl8723au_write32(pAdapter, ADDAReg[0], 0x0b1b25a0); - } else { - rtl8723au_write32(pAdapter, ADDAReg[0], pathOn); - } - - for (i = 1 ; i < IQK_ADDA_REG_NUM ; i++) - rtl8723au_write32(pAdapter, ADDAReg[i], pathOn); -} - -static void _PHY_MACSettingCalibration(struct rtw_adapter *pAdapter, - u32 *MACReg, u32 *MACBackup) -{ - u32 i = 0; - - rtl8723au_write8(pAdapter, MACReg[i], 0x3F); - - for (i = 1 ; i < (IQK_MAC_REG_NUM - 1); i++) { - rtl8723au_write8(pAdapter, MACReg[i], - (u8)(MACBackup[i] & ~BIT(3))); - } - rtl8723au_write8(pAdapter, MACReg[i], (u8)(MACBackup[i] & ~BIT(5))); -} - -static void _PHY_PathAStandBy(struct rtw_adapter *pAdapter) -{ - rtl8723au_write32(pAdapter, rFPGA0_IQK, 0x0); - rtl8723au_write32(pAdapter, 0x840, 0x00010000); - rtl8723au_write32(pAdapter, rFPGA0_IQK, 0x80800000); -} - -static void _PHY_PIModeSwitch(struct rtw_adapter *pAdapter, bool PIMode) -{ - u32 mode; - - mode = PIMode ? 0x01000100 : 0x01000000; - rtl8723au_write32(pAdapter, 0x820, mode); - rtl8723au_write32(pAdapter, 0x828, mode); -} - -/* -return false => do IQK again -*/ -static bool _PHY_SimularityCompare(struct rtw_adapter *pAdapter, int result[][8], u8 c1, u8 c2) -{ - u32 i, j, diff, SimularityBitMap, bound = 0; - struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter); - u8 final_candidate[2] = {0xFF, 0xFF}; /* for path A and path B */ - bool bResult = true; - - if (pHalData->rf_type == RF_2T2R) - bound = 8; - else - bound = 4; - - SimularityBitMap = 0; - - for (i = 0; i < bound; i++) { - diff = (result[c1][i] > result[c2][i]) ? (result[c1][i] - result[c2][i]) : (result[c2][i] - result[c1][i]); - if (diff > MAX_TOLERANCE) { - if ((i == 2 || i == 6) && !SimularityBitMap) { - if (result[c1][i]+result[c1][i+1] == 0) - final_candidate[(i/4)] = c2; - else if (result[c2][i]+result[c2][i+1] == 0) - final_candidate[(i/4)] = c1; - else - SimularityBitMap = SimularityBitMap|(1<<i); - } else { - SimularityBitMap = SimularityBitMap|(1<<i); - } - } - } - - if (SimularityBitMap == 0) { - for (i = 0; i < (bound/4); i++) { - if (final_candidate[i] != 0xFF) { - for (j = i*4; j < (i+1)*4-2; j++) - result[3][j] = result[final_candidate[i]][j]; - bResult = false; - } - } - return bResult; - } else if (!(SimularityBitMap & 0x0F)) { - /* path A OK */ - for (i = 0; i < 4; i++) - result[3][i] = result[c1][i]; - return false; - } else if (!(SimularityBitMap & 0xF0) && pHalData->rf_type == RF_2T2R) { - /* path B OK */ - for (i = 4; i < 8; i++) - result[3][i] = result[c1][i]; - return false; - } else { - return false; - } -} - -static void _PHY_IQCalibrate(struct rtw_adapter *pAdapter, int result[][8], u8 t, bool is2T) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - u32 i; - u8 PathAOK, PathBOK; - u32 ADDA_REG[IQK_ADDA_REG_NUM] = { - rFPGA0_XCD_SwitchControl, rBlue_Tooth, - rRx_Wait_CCA, rTx_CCK_RFON, - rTx_CCK_BBON, rTx_OFDM_RFON, - rTx_OFDM_BBON, rTx_To_Rx, - rTx_To_Tx, rRx_CCK, - rRx_OFDM, rRx_Wait_RIFS, - rRx_TO_Rx, rStandby, - rSleep, rPMPD_ANAEN - }; - - u32 IQK_MAC_REG[IQK_MAC_REG_NUM] = { - REG_TXPAUSE, REG_BCN_CTRL, - REG_BCN_CTRL_1, REG_GPIO_MUXCFG - }; - - u32 IQK_BB_REG_92C[IQK_BB_REG_NUM] = { - rOFDM0_TRxPathEnable, rOFDM0_TRMuxPar, - rFPGA0_XCD_RFInterfaceSW, rConfig_AntA, rConfig_AntB, - rFPGA0_XAB_RFInterfaceSW, rFPGA0_XA_RFInterfaceOE, - rFPGA0_XB_RFInterfaceOE, rFPGA0_RFMOD - }; - - const u32 retryCount = 2; - - /* Note: IQ calibration must be performed after loading */ - /* PHY_REG.txt , and radio_a, radio_b.txt */ - - u32 bbvalue; - - if (t == 0) { - bbvalue = rtl8723au_read32(pAdapter, rFPGA0_RFMOD); - - /* Save ADDA parameters, turn Path A ADDA on */ - _PHY_SaveADDARegisters(pAdapter, ADDA_REG, pdmpriv->ADDA_backup, IQK_ADDA_REG_NUM); - _PHY_SaveMACRegisters(pAdapter, IQK_MAC_REG, pdmpriv->IQK_MAC_backup); - _PHY_SaveADDARegisters(pAdapter, IQK_BB_REG_92C, pdmpriv->IQK_BB_backup, IQK_BB_REG_NUM); - } - _PHY_PathADDAOn(pAdapter, ADDA_REG, true, is2T); - - if (t == 0) - pdmpriv->bRfPiEnable = (u8) - PHY_QueryBBReg(pAdapter, rFPGA0_XA_HSSIParameter1, - BIT(8)); - - if (!pdmpriv->bRfPiEnable) { - /* Switch BB to PI mode to do IQ Calibration. */ - _PHY_PIModeSwitch(pAdapter, true); - } - - PHY_SetBBReg(pAdapter, rFPGA0_RFMOD, BIT(24), 0x00); - rtl8723au_write32(pAdapter, rOFDM0_TRxPathEnable, 0x03a05600); - rtl8723au_write32(pAdapter, rOFDM0_TRMuxPar, 0x000800e4); - rtl8723au_write32(pAdapter, rFPGA0_XCD_RFInterfaceSW, 0x22204000); - PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT(10), 0x01); - PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT(26), 0x01); - PHY_SetBBReg(pAdapter, rFPGA0_XA_RFInterfaceOE, BIT(10), 0x00); - PHY_SetBBReg(pAdapter, rFPGA0_XB_RFInterfaceOE, BIT(10), 0x00); - - if (is2T) { - rtl8723au_write32(pAdapter, - rFPGA0_XA_LSSIParameter, 0x00010000); - rtl8723au_write32(pAdapter, - rFPGA0_XB_LSSIParameter, 0x00010000); - } - - /* MAC settings */ - _PHY_MACSettingCalibration(pAdapter, IQK_MAC_REG, pdmpriv->IQK_MAC_backup); - - /* Page B init */ - rtl8723au_write32(pAdapter, rConfig_AntA, 0x00080000); - - if (is2T) - rtl8723au_write32(pAdapter, rConfig_AntB, 0x00080000); - - /* IQ calibration setting */ - rtl8723au_write32(pAdapter, rFPGA0_IQK, 0x80800000); - rtl8723au_write32(pAdapter, rTx_IQK, 0x01007c00); - rtl8723au_write32(pAdapter, rRx_IQK, 0x01004800); - - for (i = 0 ; i < retryCount ; i++) { - PathAOK = _PHY_PathA_IQK(pAdapter, is2T); - if (PathAOK == 0x03) { - DBG_8723A("Path A IQK Success!!\n"); - result[t][0] = (rtl8723au_read32(pAdapter, rTx_Power_Before_IQK_A)&0x3FF0000)>>16; - result[t][1] = (rtl8723au_read32(pAdapter, rTx_Power_After_IQK_A)&0x3FF0000)>>16; - result[t][2] = (rtl8723au_read32(pAdapter, rRx_Power_Before_IQK_A_2)&0x3FF0000)>>16; - result[t][3] = (rtl8723au_read32(pAdapter, rRx_Power_After_IQK_A_2)&0x3FF0000)>>16; - break; - } else if (i == (retryCount-1) && PathAOK == 0x01) { - /* Tx IQK OK */ - DBG_8723A("Path A IQK Only Tx Success!!\n"); - - result[t][0] = (rtl8723au_read32(pAdapter, rTx_Power_Before_IQK_A)&0x3FF0000)>>16; - result[t][1] = (rtl8723au_read32(pAdapter, rTx_Power_After_IQK_A)&0x3FF0000)>>16; - } - } - - if (0x00 == PathAOK) { - DBG_8723A("Path A IQK failed!!\n"); - } - - if (is2T) { - _PHY_PathAStandBy(pAdapter); - - /* Turn Path B ADDA on */ - _PHY_PathADDAOn(pAdapter, ADDA_REG, false, is2T); - - for (i = 0 ; i < retryCount ; i++) { - PathBOK = _PHY_PathB_IQK(pAdapter); - if (PathBOK == 0x03) { - DBG_8723A("Path B IQK Success!!\n"); - result[t][4] = (rtl8723au_read32(pAdapter, rTx_Power_Before_IQK_B)&0x3FF0000)>>16; - result[t][5] = (rtl8723au_read32(pAdapter, rTx_Power_After_IQK_B)&0x3FF0000)>>16; - result[t][6] = (rtl8723au_read32(pAdapter, rRx_Power_Before_IQK_B_2)&0x3FF0000)>>16; - result[t][7] = (rtl8723au_read32(pAdapter, rRx_Power_After_IQK_B_2)&0x3FF0000)>>16; - break; - } else if (i == (retryCount - 1) && PathBOK == 0x01) { - /* Tx IQK OK */ - DBG_8723A("Path B Only Tx IQK Success!!\n"); - result[t][4] = (rtl8723au_read32(pAdapter, rTx_Power_Before_IQK_B)&0x3FF0000)>>16; - result[t][5] = (rtl8723au_read32(pAdapter, rTx_Power_After_IQK_B)&0x3FF0000)>>16; - } - } - - if (0x00 == PathBOK) { - DBG_8723A("Path B IQK failed!!\n"); - } - } - - /* Back to BB mode, load original value */ - rtl8723au_write32(pAdapter, rFPGA0_IQK, 0); - - if (t != 0) { - if (!pdmpriv->bRfPiEnable) { - /* Switch back BB to SI mode after finish IQ Calibration. */ - _PHY_PIModeSwitch(pAdapter, false); - } - - /* Reload ADDA power saving parameters */ - _PHY_ReloadADDARegisters(pAdapter, ADDA_REG, pdmpriv->ADDA_backup, IQK_ADDA_REG_NUM); - - /* Reload MAC parameters */ - _PHY_ReloadMACRegisters(pAdapter, IQK_MAC_REG, pdmpriv->IQK_MAC_backup); - - /* Reload BB parameters */ - _PHY_ReloadADDARegisters(pAdapter, IQK_BB_REG_92C, pdmpriv->IQK_BB_backup, IQK_BB_REG_NUM); - - /* Restore RX initial gain */ - rtl8723au_write32(pAdapter, - rFPGA0_XA_LSSIParameter, 0x00032ed3); - if (is2T) { - rtl8723au_write32(pAdapter, - rFPGA0_XB_LSSIParameter, 0x00032ed3); - } - - /* load 0xe30 IQC default value */ - rtl8723au_write32(pAdapter, rTx_IQK_Tone_A, 0x01008c00); - rtl8723au_write32(pAdapter, rRx_IQK_Tone_A, 0x01008c00); - - } -} - -static void _PHY_LCCalibrate(struct rtw_adapter *pAdapter, bool is2T) -{ - u8 tmpReg; - u32 RF_Amode = 0, RF_Bmode = 0, LC_Cal; - - /* Check continuous TX and Packet TX */ - tmpReg = rtl8723au_read8(pAdapter, 0xd03); - - if ((tmpReg&0x70) != 0) { - /* Deal with contisuous TX case */ - /* disable all continuous TX */ - rtl8723au_write8(pAdapter, 0xd03, tmpReg&0x8F); - } else { - /* Deal with Packet TX case */ - /* block all queues */ - rtl8723au_write8(pAdapter, REG_TXPAUSE, 0xFF); - } - - if ((tmpReg&0x70) != 0) { - /* 1. Read original RF mode */ - /* Path-A */ - RF_Amode = PHY_QueryRFReg(pAdapter, RF_PATH_A, RF_AC, bMask12Bits); - - /* Path-B */ - if (is2T) - RF_Bmode = PHY_QueryRFReg(pAdapter, RF_PATH_B, RF_AC, bMask12Bits); - - /* 2. Set RF mode = standby mode */ - /* Path-A */ - PHY_SetRFReg(pAdapter, RF_PATH_A, RF_AC, bMask12Bits, (RF_Amode&0x8FFFF)|0x10000); - - /* Path-B */ - if (is2T) - PHY_SetRFReg(pAdapter, RF_PATH_B, RF_AC, bMask12Bits, (RF_Bmode&0x8FFFF)|0x10000); - } - - /* 3. Read RF reg18 */ - LC_Cal = PHY_QueryRFReg(pAdapter, RF_PATH_A, RF_CHNLBW, bMask12Bits); - - /* 4. Set LC calibration begin */ - PHY_SetRFReg(pAdapter, RF_PATH_A, RF_CHNLBW, bMask12Bits, LC_Cal|0x08000); - - msleep(100); - - /* Restore original situation */ - if ((tmpReg&0x70) != 0) { /* Deal with contuous TX case */ - /* Path-A */ - rtl8723au_write8(pAdapter, 0xd03, tmpReg); - PHY_SetRFReg(pAdapter, RF_PATH_A, RF_AC, bMask12Bits, RF_Amode); - - /* Path-B */ - if (is2T) - PHY_SetRFReg(pAdapter, RF_PATH_B, RF_AC, bMask12Bits, RF_Bmode); - } else /* Deal with Packet TX case */ - rtl8723au_write8(pAdapter, REG_TXPAUSE, 0x00); -} - -/* Analog Pre-distortion calibration */ -#define APK_BB_REG_NUM 8 -#define APK_CURVE_REG_NUM 4 -#define PATH_NUM 2 - -void rtl8723a_phy_iq_calibrate(struct rtw_adapter *pAdapter, bool bReCovery) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - s32 result[4][8]; /* last is final result */ - u8 i, final_candidate; - bool bPathAOK, bPathBOK; - s32 RegE94, RegE9C, RegEA4, RegEAC, RegEB4, RegEBC, RegEC4; - s32 RegECC, RegTmp = 0; - bool is12simular, is13simular, is23simular; - bool bStartContTx = false, bSingleTone = false; - bool bCarrierSuppression = false; - u32 IQK_BB_REG_92C[IQK_BB_REG_NUM] = { - rOFDM0_XARxIQImbalance, rOFDM0_XBRxIQImbalance, - rOFDM0_ECCAThreshold, rOFDM0_AGCRSSITable, - rOFDM0_XATxIQImbalance, rOFDM0_XBTxIQImbalance, - rOFDM0_XCTxAFE, rOFDM0_XDTxAFE, - rOFDM0_RxIQExtAnta - }; - - /* ignore IQK when continuous Tx */ - if (bStartContTx || bSingleTone || bCarrierSuppression) - return; - - if (bReCovery) { - _PHY_ReloadADDARegisters(pAdapter, IQK_BB_REG_92C, pdmpriv->IQK_BB_backup_recover, 9); - return; - } - DBG_8723A("IQK:Start!!!\n"); - - for (i = 0; i < 8; i++) { - result[0][i] = 0; - result[1][i] = 0; - result[2][i] = 0; - result[3][i] = 0; - } - final_candidate = 0xff; - bPathAOK = false; - bPathBOK = false; - is12simular = false; - is23simular = false; - is13simular = false; - - for (i = 0; i < 3; i++) { - if (pHalData->rf_type == RF_2T2R) - _PHY_IQCalibrate(pAdapter, result, i, true); - else /* For 88C 1T1R */ - _PHY_IQCalibrate(pAdapter, result, i, false); - - if (i == 1) { - is12simular = _PHY_SimularityCompare(pAdapter, result, 0, 1); - if (is12simular) { - final_candidate = 0; - break; - } - } - - if (i == 2) { - is13simular = _PHY_SimularityCompare(pAdapter, result, 0, 2); - if (is13simular) { - final_candidate = 0; - break; - } - - is23simular = _PHY_SimularityCompare(pAdapter, result, 1, 2); - if (is23simular) { - final_candidate = 1; - } else { - for (i = 0; i < 8; i++) - RegTmp += result[3][i]; - - if (RegTmp != 0) - final_candidate = 3; - else - final_candidate = 0xFF; - } - } - } - - for (i = 0; i < 4; i++) { - 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]; - } - - if (final_candidate != 0xff) { - RegE94 = result[final_candidate][0]; - pdmpriv->RegE94 = RegE94; - RegE9C = result[final_candidate][1]; - pdmpriv->RegE9C = RegE9C; - RegEA4 = result[final_candidate][2]; - RegEAC = result[final_candidate][3]; - RegEB4 = result[final_candidate][4]; - pdmpriv->RegEB4 = RegEB4; - RegEBC = result[final_candidate][5]; - pdmpriv->RegEBC = RegEBC; - RegEC4 = result[final_candidate][6]; - RegECC = result[final_candidate][7]; - DBG_8723A("IQK: final_candidate is %x\n", final_candidate); - DBG_8723A("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 { - RegE94 = RegEB4 = pdmpriv->RegE94 = pdmpriv->RegEB4 = 0x100; /* X default value */ - RegE9C = RegEBC = pdmpriv->RegE9C = pdmpriv->RegEBC = 0x0; /* Y default value */ - } - - if ((RegE94 != 0)/*&&(RegEA4 != 0)*/) - _PHY_PathAFillIQKMatrix(pAdapter, bPathAOK, result, final_candidate, (RegEA4 == 0)); - - if (pHalData->rf_type == RF_2T2R) { - if ((RegEB4 != 0)/*&&(RegEC4 != 0)*/) - _PHY_PathBFillIQKMatrix(pAdapter, bPathBOK, result, - final_candidate, (RegEC4 == 0)); - } - - _PHY_SaveADDARegisters(pAdapter, IQK_BB_REG_92C, pdmpriv->IQK_BB_backup_recover, 9); -} - -void rtl8723a_phy_lc_calibrate(struct rtw_adapter *pAdapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter); - struct mlme_ext_priv *pmlmeext = &pAdapter->mlmeextpriv; - bool bStartContTx = false, bSingleTone = false, bCarrierSuppression = false; - - /* ignore IQK when continuous Tx */ - if (bStartContTx || bSingleTone || bCarrierSuppression) - return; - - if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) - return; - - if (pHalData->rf_type == RF_2T2R) - _PHY_LCCalibrate(pAdapter, true); - else /* For 88C 1T1R */ - _PHY_LCCalibrate(pAdapter, false); -} - -void -rtl8723a_phy_ap_calibrate(struct rtw_adapter *pAdapter, char delta) -{ -} diff --git a/drivers/staging/rtl8723au/hal/HalHWImg8723A_BB.c b/drivers/staging/rtl8723au/hal/HalHWImg8723A_BB.c deleted file mode 100644 index 8d3ea6c..0000000 --- a/drivers/staging/rtl8723au/hal/HalHWImg8723A_BB.c +++ /dev/null @@ -1,565 +0,0 @@ -/****************************************************************************** -* -* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms of version 2 of the GNU General Public License as -* published by the Free Software Foundation. -* -* This program is distributed in the hope that it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -******************************************************************************/ - -#include "odm_precomp.h" - -static bool CheckCondition(const u32 Condition, const u32 Hex) -{ - u32 _board = (Hex & 0x000000FF); - u32 _interface = (Hex & 0x0000FF00) >> 8; - u32 _platform = (Hex & 0x00FF0000) >> 16; - u32 cond = Condition; - - if (Condition == 0xCDCDCDCD) - return true; - - cond = Condition & 0x000000FF; - if ((_board == cond) && cond != 0x00) - return false; - - cond = Condition & 0x0000FF00; - cond >>= 8; - if ((_interface & cond) == 0 && cond != 0x07) - return false; - - cond = Condition & 0x00FF0000; - cond >>= 16; - if ((_platform & cond) == 0 && cond != 0x0F) - return false; - return true; -} - -/****************************************************************************** -* AGC_TAB_1T.TXT -******************************************************************************/ - -static u32 Array_AGC_TAB_1T_8723A[] = { - 0xC78, 0x7B000001, - 0xC78, 0x7B010001, - 0xC78, 0x7B020001, - 0xC78, 0x7B030001, - 0xC78, 0x7B040001, - 0xC78, 0x7B050001, - 0xC78, 0x7A060001, - 0xC78, 0x79070001, - 0xC78, 0x78080001, - 0xC78, 0x77090001, - 0xC78, 0x760A0001, - 0xC78, 0x750B0001, - 0xC78, 0x740C0001, - 0xC78, 0x730D0001, - 0xC78, 0x720E0001, - 0xC78, 0x710F0001, - 0xC78, 0x70100001, - 0xC78, 0x6F110001, - 0xC78, 0x6E120001, - 0xC78, 0x6D130001, - 0xC78, 0x6C140001, - 0xC78, 0x6B150001, - 0xC78, 0x6A160001, - 0xC78, 0x69170001, - 0xC78, 0x68180001, - 0xC78, 0x67190001, - 0xC78, 0x661A0001, - 0xC78, 0x651B0001, - 0xC78, 0x641C0001, - 0xC78, 0x631D0001, - 0xC78, 0x621E0001, - 0xC78, 0x611F0001, - 0xC78, 0x60200001, - 0xC78, 0x49210001, - 0xC78, 0x48220001, - 0xC78, 0x47230001, - 0xC78, 0x46240001, - 0xC78, 0x45250001, - 0xC78, 0x44260001, - 0xC78, 0x43270001, - 0xC78, 0x42280001, - 0xC78, 0x41290001, - 0xC78, 0x402A0001, - 0xC78, 0x262B0001, - 0xC78, 0x252C0001, - 0xC78, 0x242D0001, - 0xC78, 0x232E0001, - 0xC78, 0x222F0001, - 0xC78, 0x21300001, - 0xC78, 0x20310001, - 0xC78, 0x06320001, - 0xC78, 0x05330001, - 0xC78, 0x04340001, - 0xC78, 0x03350001, - 0xC78, 0x02360001, - 0xC78, 0x01370001, - 0xC78, 0x00380001, - 0xC78, 0x00390001, - 0xC78, 0x003A0001, - 0xC78, 0x003B0001, - 0xC78, 0x003C0001, - 0xC78, 0x003D0001, - 0xC78, 0x003E0001, - 0xC78, 0x003F0001, - 0xC78, 0x7B400001, - 0xC78, 0x7B410001, - 0xC78, 0x7B420001, - 0xC78, 0x7B430001, - 0xC78, 0x7B440001, - 0xC78, 0x7B450001, - 0xC78, 0x7A460001, - 0xC78, 0x79470001, - 0xC78, 0x78480001, - 0xC78, 0x77490001, - 0xC78, 0x764A0001, - 0xC78, 0x754B0001, - 0xC78, 0x744C0001, - 0xC78, 0x734D0001, - 0xC78, 0x724E0001, - 0xC78, 0x714F0001, - 0xC78, 0x70500001, - 0xC78, 0x6F510001, - 0xC78, 0x6E520001, - 0xC78, 0x6D530001, - 0xC78, 0x6C540001, - 0xC78, 0x6B550001, - 0xC78, 0x6A560001, - 0xC78, 0x69570001, - 0xC78, 0x68580001, - 0xC78, 0x67590001, - 0xC78, 0x665A0001, - 0xC78, 0x655B0001, - 0xC78, 0x645C0001, - 0xC78, 0x635D0001, - 0xC78, 0x625E0001, - 0xC78, 0x615F0001, - 0xC78, 0x60600001, - 0xC78, 0x49610001, - 0xC78, 0x48620001, - 0xC78, 0x47630001, - 0xC78, 0x46640001, - 0xC78, 0x45650001, - 0xC78, 0x44660001, - 0xC78, 0x43670001, - 0xC78, 0x42680001, - 0xC78, 0x41690001, - 0xC78, 0x406A0001, - 0xC78, 0x266B0001, - 0xC78, 0x256C0001, - 0xC78, 0x246D0001, - 0xC78, 0x236E0001, - 0xC78, 0x226F0001, - 0xC78, 0x21700001, - 0xC78, 0x20710001, - 0xC78, 0x06720001, - 0xC78, 0x05730001, - 0xC78, 0x04740001, - 0xC78, 0x03750001, - 0xC78, 0x02760001, - 0xC78, 0x01770001, - 0xC78, 0x00780001, - 0xC78, 0x00790001, - 0xC78, 0x007A0001, - 0xC78, 0x007B0001, - 0xC78, 0x007C0001, - 0xC78, 0x007D0001, - 0xC78, 0x007E0001, - 0xC78, 0x007F0001, - 0xC78, 0x3800001E, - 0xC78, 0x3801001E, - 0xC78, 0x3802001E, - 0xC78, 0x3803001E, - 0xC78, 0x3804001E, - 0xC78, 0x3805001E, - 0xC78, 0x3806001E, - 0xC78, 0x3807001E, - 0xC78, 0x3808001E, - 0xC78, 0x3C09001E, - 0xC78, 0x3E0A001E, - 0xC78, 0x400B001E, - 0xC78, 0x440C001E, - 0xC78, 0x480D001E, - 0xC78, 0x4C0E001E, - 0xC78, 0x500F001E, - 0xC78, 0x5210001E, - 0xC78, 0x5611001E, - 0xC78, 0x5A12001E, - 0xC78, 0x5E13001E, - 0xC78, 0x6014001E, - 0xC78, 0x6015001E, - 0xC78, 0x6016001E, - 0xC78, 0x6217001E, - 0xC78, 0x6218001E, - 0xC78, 0x6219001E, - 0xC78, 0x621A001E, - 0xC78, 0x621B001E, - 0xC78, 0x621C001E, - 0xC78, 0x621D001E, - 0xC78, 0x621E001E, - 0xC78, 0x621F001E, -}; - -#define READ_NEXT_PAIR(v1, v2, i) \ - do { \ - i += 2; v1 = Array[i]; v2 = Array[i+1]; \ - } while (0) - -void ODM_ReadAndConfig_AGC_TAB_1T_8723A(struct dm_odm_t *pDM_Odm) -{ - u32 hex; - u32 i; - u8 platform = 0x04; - u8 board = pDM_Odm->BoardType; - u32 ArrayLen = ARRAY_SIZE(Array_AGC_TAB_1T_8723A); - u32 *Array = Array_AGC_TAB_1T_8723A; - - hex = board; - hex += ODM_ITRF_USB << 8; - hex += platform << 16; - hex += 0xFF000000; - for (i = 0; i < ArrayLen; i += 2) { - u32 v1 = Array[i]; - u32 v2 = Array[i+1]; - - /* This (offset, data) pair meets the condition. */ - if (v1 < 0xCDCDCDCD) { - odm_ConfigBB_AGC_8723A(pDM_Odm, v1, v2); - continue; - } else { - if (!CheckCondition(Array[i], hex)) { - /* Discard the following (offset, data) pairs */ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < ArrayLen - 2) - READ_NEXT_PAIR(v1, v2, i); - i -= 2; /* prevent from for-loop += 2 */ - } else { - /* Configure matched pairs and skip to - end of if-else. */ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < ArrayLen - 2) { - odm_ConfigBB_AGC_8723A(pDM_Odm, v1, v2); - READ_NEXT_PAIR(v1, v2, i); - } - while (v2 != 0xDEAD && i < ArrayLen - 2) - READ_NEXT_PAIR(v1, v2, i); - } - } - } -} - -/****************************************************************************** -* PHY_REG_1T.TXT -******************************************************************************/ - -static u32 Array_PHY_REG_1T_8723A[] = { - 0x800, 0x80040000, - 0x804, 0x00000003, - 0x808, 0x0000FC00, - 0x80C, 0x0000000A, - 0x810, 0x10001331, - 0x814, 0x020C3D10, - 0x818, 0x02200385, - 0x81C, 0x00000000, - 0x820, 0x01000100, - 0x824, 0x00390004, - 0x828, 0x00000000, - 0x82C, 0x00000000, - 0x830, 0x00000000, - 0x834, 0x00000000, - 0x838, 0x00000000, - 0x83C, 0x00000000, - 0x840, 0x00010000, - 0x844, 0x00000000, - 0x848, 0x00000000, - 0x84C, 0x00000000, - 0x850, 0x00000000, - 0x854, 0x00000000, - 0x858, 0x569A569A, - 0x85C, 0x001B25A4, - 0x860, 0x66F60110, - 0x864, 0x061F0130, - 0x868, 0x00000000, - 0x86C, 0x32323200, - 0x870, 0x07000760, - 0x874, 0x22004000, - 0x878, 0x00000808, - 0x87C, 0x00000000, - 0x880, 0xC0083070, - 0x884, 0x000004D5, - 0x888, 0x00000000, - 0x88C, 0xCCC000C0, - 0x890, 0x00000800, - 0x894, 0xFFFFFFFE, - 0x898, 0x40302010, - 0x89C, 0x00706050, - 0x900, 0x00000000, - 0x904, 0x00000023, - 0x908, 0x00000000, - 0x90C, 0x81121111, - 0xA00, 0x00D047C8, - 0xA04, 0x80FF000C, - 0xA08, 0x8C838300, - 0xA0C, 0x2E68120F, - 0xA10, 0x9500BB78, - 0xA14, 0x11144028, - 0xA18, 0x00881117, - 0xA1C, 0x89140F00, - 0xA20, 0x1A1B0000, - 0xA24, 0x090E1317, - 0xA28, 0x00000204, - 0xA2C, 0x00D30000, - 0xA70, 0x101FBF00, - 0xA74, 0x00000007, - 0xA78, 0x00000900, - 0xC00, 0x48071D40, - 0xC04, 0x03A05611, - 0xC08, 0x000000E4, - 0xC0C, 0x6C6C6C6C, - 0xC10, 0x08800000, - 0xC14, 0x40000100, - 0xC18, 0x08800000, - 0xC1C, 0x40000100, - 0xC20, 0x00000000, - 0xC24, 0x00000000, - 0xC28, 0x00000000, - 0xC2C, 0x00000000, - 0xC30, 0x69E9AC44, - 0xFF0F011F, 0xABCD, - 0xC34, 0x469652CF, - 0xCDCDCDCD, 0xCDCD, - 0xC34, 0x469652AF, - 0xFF0F011F, 0xDEAD, - 0xC38, 0x49795994, - 0xC3C, 0x0A97971C, - 0xC40, 0x1F7C403F, - 0xC44, 0x000100B7, - 0xC48, 0xEC020107, - 0xC4C, 0x007F037F, - 0xC50, 0x69543420, - 0xC54, 0x43BC0094, - 0xC58, 0x69543420, - 0xC5C, 0x433C0094, - 0xC60, 0x00000000, - 0xFF0F011F, 0xABCD, - 0xC64, 0x7116848B, - 0xCDCDCDCD, 0xCDCD, - 0xC64, 0x7112848B, - 0xFF0F011F, 0xDEAD, - 0xC68, 0x47C00BFF, - 0xC6C, 0x00000036, - 0xC70, 0x2C7F000D, - 0xC74, 0x018610DB, - 0xC78, 0x0000001F, - 0xC7C, 0x00B91612, - 0xC80, 0x40000100, - 0xC84, 0x20F60000, - 0xC88, 0x40000100, - 0xC8C, 0x20200000, - 0xC90, 0x00121820, - 0xC94, 0x00000000, - 0xC98, 0x00121820, - 0xC9C, 0x00007F7F, - 0xCA0, 0x00000000, - 0xCA4, 0x00000080, - 0xCA8, 0x00000000, - 0xCAC, 0x00000000, - 0xCB0, 0x00000000, - 0xCB4, 0x00000000, - 0xCB8, 0x00000000, - 0xCBC, 0x28000000, - 0xCC0, 0x00000000, - 0xCC4, 0x00000000, - 0xCC8, 0x00000000, - 0xCCC, 0x00000000, - 0xCD0, 0x00000000, - 0xCD4, 0x00000000, - 0xCD8, 0x64B22427, - 0xCDC, 0x00766932, - 0xCE0, 0x00222222, - 0xCE4, 0x00000000, - 0xCE8, 0x37644302, - 0xCEC, 0x2F97D40C, - 0xD00, 0x00080740, - 0xD04, 0x00020401, - 0xD08, 0x0000907F, - 0xD0C, 0x20010201, - 0xD10, 0xA0633333, - 0xD14, 0x3333BC43, - 0xD18, 0x7A8F5B6B, - 0xD2C, 0xCC979975, - 0xD30, 0x00000000, - 0xD34, 0x80608000, - 0xD38, 0x00000000, - 0xD3C, 0x00027293, - 0xD40, 0x00000000, - 0xD44, 0x00000000, - 0xD48, 0x00000000, - 0xD4C, 0x00000000, - 0xD50, 0x6437140A, - 0xD54, 0x00000000, - 0xD58, 0x00000000, - 0xD5C, 0x30032064, - 0xD60, 0x4653DE68, - 0xD64, 0x04518A3C, - 0xD68, 0x00002101, - 0xD6C, 0x2A201C16, - 0xD70, 0x1812362E, - 0xD74, 0x322C2220, - 0xD78, 0x000E3C24, - 0xE00, 0x2A2A2A2A, - 0xE04, 0x2A2A2A2A, - 0xE08, 0x03902A2A, - 0xE10, 0x2A2A2A2A, - 0xE14, 0x2A2A2A2A, - 0xE18, 0x2A2A2A2A, - 0xE1C, 0x2A2A2A2A, - 0xE28, 0x00000000, - 0xE30, 0x1000DC1F, - 0xE34, 0x10008C1F, - 0xE38, 0x02140102, - 0xE3C, 0x681604C2, - 0xE40, 0x01007C00, - 0xE44, 0x01004800, - 0xE48, 0xFB000000, - 0xE4C, 0x000028D1, - 0xE50, 0x1000DC1F, - 0xE54, 0x10008C1F, - 0xE58, 0x02140102, - 0xE5C, 0x28160D05, - 0xE60, 0x00000008, - 0xE68, 0x001B25A4, - 0xE6C, 0x631B25A0, - 0xE70, 0x631B25A0, - 0xE74, 0x081B25A0, - 0xE78, 0x081B25A0, - 0xE7C, 0x081B25A0, - 0xE80, 0x081B25A0, - 0xE84, 0x631B25A0, - 0xE88, 0x081B25A0, - 0xE8C, 0x631B25A0, - 0xED0, 0x631B25A0, - 0xED4, 0x631B25A0, - 0xED8, 0x631B25A0, - 0xEDC, 0x001B25A0, - 0xEE0, 0x001B25A0, - 0xEEC, 0x6B1B25A0, - 0xF14, 0x00000003, - 0xF4C, 0x00000000, - 0xF00, 0x00000300, -}; - -void ODM_ReadAndConfig_PHY_REG_1T_8723A(struct dm_odm_t *pDM_Odm) -{ - u32 hex = 0; - u32 i = 0; - u8 platform = 0x04; - u8 board = pDM_Odm->BoardType; - u32 ArrayLen = ARRAY_SIZE(Array_PHY_REG_1T_8723A); - u32 *Array = Array_PHY_REG_1T_8723A; - - hex += board; - hex += ODM_ITRF_USB << 8; - hex += platform << 16; - hex += 0xFF000000; - for (i = 0; i < ArrayLen; i += 2) { - u32 v1 = Array[i]; - u32 v2 = Array[i+1]; - - /* This (offset, data) pair meets the condition. */ - if (v1 < 0xCDCDCDCD) { - odm_ConfigBB_PHY_8723A(pDM_Odm, v1, v2); - continue; - } else { - if (!CheckCondition(Array[i], hex)) { - /* Discard the following (offset, data) pairs */ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < ArrayLen - 2) - READ_NEXT_PAIR(v1, v2, i); - i -= 2; /* prevent from for-loop += 2 */ - } else { - /* Configure matched pairs and skip to - end of if-else. */ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < ArrayLen - 2) { - odm_ConfigBB_PHY_8723A(pDM_Odm, v1, v2); - READ_NEXT_PAIR(v1, v2, i); - } - while (v2 != 0xDEAD && i < ArrayLen - 2) - READ_NEXT_PAIR(v1, v2, i); - } - } - } -} - -/****************************************************************************** -* PHY_REG_MP.TXT -******************************************************************************/ - -static u32 Array_PHY_REG_MP_8723A[] = { - 0xC30, 0x69E9AC4A, - 0xC3C, 0x0A979718, -}; - -void ODM_ReadAndConfig_PHY_REG_MP_8723A(struct dm_odm_t *pDM_Odm) -{ - u32 hex = 0; - u32 i; - u8 platform = 0x04; - u8 board = pDM_Odm->BoardType; - u32 ArrayLen = ARRAY_SIZE(Array_PHY_REG_MP_8723A); - u32 *Array = Array_PHY_REG_MP_8723A; - - hex += board; - hex += ODM_ITRF_USB << 8; - hex += platform << 16; - hex += 0xFF000000; - for (i = 0; i < ArrayLen; i += 2) { - u32 v1 = Array[i]; - u32 v2 = Array[i+1]; - - /* This (offset, data) pair meets the condition. */ - if (v1 < 0xCDCDCDCD) { - odm_ConfigBB_PHY_8723A(pDM_Odm, v1, v2); - continue; - } else { - if (!CheckCondition(Array[i], hex)) { - /* Discard the following (offset, data) pairs */ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < ArrayLen - 2) - READ_NEXT_PAIR(v1, v2, i); - i -= 2; /* prevent from for-loop += 2 */ - } else { - /* Configure matched pairs and skip to - end of if-else. */ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < ArrayLen - 2) { - odm_ConfigBB_PHY_8723A(pDM_Odm, v1, v2); - READ_NEXT_PAIR(v1, v2, i); - } - while (v2 != 0xDEAD && i < ArrayLen - 2) - READ_NEXT_PAIR(v1, v2, i); - } - } - } -} diff --git a/drivers/staging/rtl8723au/hal/HalHWImg8723A_MAC.c b/drivers/staging/rtl8723au/hal/HalHWImg8723A_MAC.c deleted file mode 100644 index 9bf6859..0000000 --- a/drivers/staging/rtl8723au/hal/HalHWImg8723A_MAC.c +++ /dev/null @@ -1,187 +0,0 @@ -/****************************************************************************** -* -* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms of version 2 of the GNU General Public License as -* published by the Free Software Foundation. -* -* This program is distributed in the hope that it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -******************************************************************************/ - -#include "odm_precomp.h" - -static bool CheckCondition(const u32 Condition, const u32 Hex) -{ - u32 _board = (Hex & 0x000000FF); - u32 _interface = (Hex & 0x0000FF00) >> 8; - u32 _platform = (Hex & 0x00FF0000) >> 16; - u32 cond = Condition; - - if (Condition == 0xCDCDCDCD) - return true; - - cond = Condition & 0x000000FF; - if ((_board == cond) && cond != 0x00) - return false; - - cond = Condition & 0x0000FF00; - cond >>= 8; - if ((_interface & cond) == 0 && cond != 0x07) - return false; - - cond = Condition & 0x00FF0000; - cond >>= 16; - if ((_platform & cond) == 0 && cond != 0x0F) - return false; - return true; -} - -/****************************************************************************** -* MAC_REG.TXT -******************************************************************************/ - -static u32 Array_MAC_REG_8723A[] = { - 0x420, 0x00000080, - 0x423, 0x00000000, - 0x430, 0x00000000, - 0x431, 0x00000000, - 0x432, 0x00000000, - 0x433, 0x00000001, - 0x434, 0x00000004, - 0x435, 0x00000005, - 0x436, 0x00000006, - 0x437, 0x00000007, - 0x438, 0x00000000, - 0x439, 0x00000000, - 0x43A, 0x00000000, - 0x43B, 0x00000001, - 0x43C, 0x00000004, - 0x43D, 0x00000005, - 0x43E, 0x00000006, - 0x43F, 0x00000007, - 0x440, 0x0000005D, - 0x441, 0x00000001, - 0x442, 0x00000000, - 0x444, 0x00000015, - 0x445, 0x000000F0, - 0x446, 0x0000000F, - 0x447, 0x00000000, - 0x458, 0x00000041, - 0x459, 0x000000A8, - 0x45A, 0x00000072, - 0x45B, 0x000000B9, - 0x460, 0x00000066, - 0x461, 0x00000066, - 0x462, 0x00000008, - 0x463, 0x00000003, - 0x4C8, 0x000000FF, - 0x4C9, 0x00000008, - 0x4CC, 0x000000FF, - 0x4CD, 0x000000FF, - 0x4CE, 0x00000001, - 0x500, 0x00000026, - 0x501, 0x000000A2, - 0x502, 0x0000002F, - 0x503, 0x00000000, - 0x504, 0x00000028, - 0x505, 0x000000A3, - 0x506, 0x0000005E, - 0x507, 0x00000000, - 0x508, 0x0000002B, - 0x509, 0x000000A4, - 0x50A, 0x0000005E, - 0x50B, 0x00000000, - 0x50C, 0x0000004F, - 0x50D, 0x000000A4, - 0x50E, 0x00000000, - 0x50F, 0x00000000, - 0x512, 0x0000001C, - 0x514, 0x0000000A, - 0x515, 0x00000010, - 0x516, 0x0000000A, - 0x517, 0x00000010, - 0x51A, 0x00000016, - 0x524, 0x0000000F, - 0x525, 0x0000004F, - 0x546, 0x00000040, - 0x547, 0x00000000, - 0x550, 0x00000010, - 0x551, 0x00000010, - 0x559, 0x00000002, - 0x55A, 0x00000002, - 0x55D, 0x000000FF, - 0x605, 0x00000030, - 0x608, 0x0000000E, - 0x609, 0x0000002A, - 0x652, 0x00000020, - 0x63C, 0x0000000A, - 0x63D, 0x0000000A, - 0x63E, 0x0000000E, - 0x63F, 0x0000000E, - 0x66E, 0x00000005, - 0x700, 0x00000021, - 0x701, 0x00000043, - 0x702, 0x00000065, - 0x703, 0x00000087, - 0x708, 0x00000021, - 0x709, 0x00000043, - 0x70A, 0x00000065, - 0x70B, 0x00000087, -}; - -void ODM_ReadAndConfig_MAC_REG_8723A(struct dm_odm_t *pDM_Odm) -{ - #define READ_NEXT_PAIR(v1, v2, i) \ - do { \ - i += 2; v1 = Array[i]; v2 = Array[i+1]; \ - } while (0) - - u32 hex = 0; - u32 i = 0; - u8 platform = 0x04; - u8 board = pDM_Odm->BoardType; - u32 ArrayLen = ARRAY_SIZE(Array_MAC_REG_8723A); - u32 *Array = Array_MAC_REG_8723A; - - hex += board; - hex += ODM_ITRF_USB << 8; - hex += platform << 16; - hex += 0xFF000000; - for (i = 0; i < ArrayLen; i += 2) { - u32 v1 = Array[i]; - u32 v2 = Array[i+1]; - - /* This (offset, data) pair meets the condition. */ - if (v1 < 0xCDCDCDCD) { - odm_ConfigMAC_8723A(pDM_Odm, v1, (u8)v2); - continue; - } else { - if (!CheckCondition(Array[i], hex)) { - /* Discard the following (offset, data) pairs. */ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < ArrayLen - 2) - READ_NEXT_PAIR(v1, v2, i); - i -= 2; /* prevent from for-loop += 2 */ - } else { - /* Configure matched pairs and skip to end of if-else. */ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < ArrayLen - 2) { - odm_ConfigMAC_8723A(pDM_Odm, v1, (u8)v2); - READ_NEXT_PAIR(v1, v2, i); - } - - while (v2 != 0xDEAD && i < ArrayLen - 2) - READ_NEXT_PAIR(v1, v2, i); - } - } - } -} diff --git a/drivers/staging/rtl8723au/hal/HalHWImg8723A_RF.c b/drivers/staging/rtl8723au/hal/HalHWImg8723A_RF.c deleted file mode 100644 index 286f3ea..0000000 --- a/drivers/staging/rtl8723au/hal/HalHWImg8723A_RF.c +++ /dev/null @@ -1,259 +0,0 @@ -/****************************************************************************** -* -* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms of version 2 of the GNU General Public License as -* published by the Free Software Foundation. -* -* This program is distributed in the hope that it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -******************************************************************************/ - -#include "odm_precomp.h" - -static bool CheckCondition(const u32 Condition, const u32 Hex) -{ - u32 _board = (Hex & 0x000000FF); - u32 _interface = (Hex & 0x0000FF00) >> 8; - u32 _platform = (Hex & 0x00FF0000) >> 16; - u32 cond = Condition; - - if (Condition == 0xCDCDCDCD) - return true; - - cond = Condition & 0x000000FF; - if ((_board == cond) && cond != 0x00) - return false; - - cond = Condition & 0x0000FF00; - cond >>= 8; - if ((_interface & cond) == 0 && cond != 0x07) - return false; - - cond = Condition & 0x00FF0000; - cond >>= 16; - if ((_platform & cond) == 0 && cond != 0x0F) - return false; - return true; -} - -/****************************************************************************** -* RadioA_1T.TXT -******************************************************************************/ - -static u32 Array_RadioA_1T_8723A[] = { - 0x000, 0x00030159, - 0x001, 0x00031284, - 0x002, 0x00098000, - 0xFF0F011F, 0xABCD, - 0x003, 0x00018C63, - 0xCDCDCDCD, 0xCDCD, - 0x003, 0x00039C63, - 0xFF0F011F, 0xDEAD, - 0x004, 0x000210E7, - 0x009, 0x0002044F, - 0x00A, 0x0001A3F1, - 0x00B, 0x00014787, - 0x00C, 0x000896FE, - 0x00D, 0x0000E02C, - 0x00E, 0x00039CE7, - 0x00F, 0x00000451, - 0x019, 0x00000000, - 0x01A, 0x00030355, - 0x01B, 0x00060A00, - 0x01C, 0x000FC378, - 0x01D, 0x000A1250, - 0x01E, 0x0000024F, - 0x01F, 0x00000000, - 0x020, 0x0000B614, - 0x021, 0x0006C000, - 0x022, 0x00000000, - 0x023, 0x00001558, - 0x024, 0x00000060, - 0x025, 0x00000483, - 0x026, 0x0004F000, - 0x027, 0x000EC7D9, - 0x028, 0x00057730, - 0x029, 0x00004783, - 0x02A, 0x00000001, - 0x02B, 0x00021334, - 0x02A, 0x00000000, - 0x02B, 0x00000054, - 0x02A, 0x00000001, - 0x02B, 0x00000808, - 0x02B, 0x00053333, - 0x02C, 0x0000000C, - 0x02A, 0x00000002, - 0x02B, 0x00000808, - 0x02B, 0x0005B333, - 0x02C, 0x0000000D, - 0x02A, 0x00000003, - 0x02B, 0x00000808, - 0x02B, 0x00063333, - 0x02C, 0x0000000D, - 0x02A, 0x00000004, - 0x02B, 0x00000808, - 0x02B, 0x0006B333, - 0x02C, 0x0000000D, - 0x02A, 0x00000005, - 0x02B, 0x00000808, - 0x02B, 0x00073333, - 0x02C, 0x0000000D, - 0x02A, 0x00000006, - 0x02B, 0x00000709, - 0x02B, 0x0005B333, - 0x02C, 0x0000000D, - 0x02A, 0x00000007, - 0x02B, 0x00000709, - 0x02B, 0x00063333, - 0x02C, 0x0000000D, - 0x02A, 0x00000008, - 0x02B, 0x0000060A, - 0x02B, 0x0004B333, - 0x02C, 0x0000000D, - 0x02A, 0x00000009, - 0x02B, 0x0000060A, - 0x02B, 0x00053333, - 0x02C, 0x0000000D, - 0x02A, 0x0000000A, - 0x02B, 0x0000060A, - 0x02B, 0x0005B333, - 0x02C, 0x0000000D, - 0x02A, 0x0000000B, - 0x02B, 0x0000060A, - 0x02B, 0x00063333, - 0x02C, 0x0000000D, - 0x02A, 0x0000000C, - 0x02B, 0x0000060A, - 0x02B, 0x0006B333, - 0x02C, 0x0000000D, - 0x02A, 0x0000000D, - 0x02B, 0x0000060A, - 0x02B, 0x00073333, - 0x02C, 0x0000000D, - 0x02A, 0x0000000E, - 0x02B, 0x0000050B, - 0x02B, 0x00066666, - 0x02C, 0x0000001A, - 0x02A, 0x000E0000, - 0x010, 0x0004000F, - 0x011, 0x000E31FC, - 0x010, 0x0006000F, - 0x011, 0x000FF9F8, - 0x010, 0x0002000F, - 0x011, 0x000203F9, - 0x010, 0x0003000F, - 0x011, 0x000FF500, - 0x010, 0x00000000, - 0x011, 0x00000000, - 0x010, 0x0008000F, - 0x011, 0x0003F100, - 0x010, 0x0009000F, - 0x011, 0x00023100, - 0x012, 0x00032000, - 0x012, 0x00071000, - 0x012, 0x000B0000, - 0x012, 0x000FC000, - 0x013, 0x000287B3, - 0x013, 0x000244B7, - 0x013, 0x000204AB, - 0x013, 0x0001C49F, - 0x013, 0x00018493, - 0x013, 0x0001429B, - 0x013, 0x00010299, - 0x013, 0x0000C29C, - 0x013, 0x000081A0, - 0x013, 0x000040AC, - 0x013, 0x00000020, - 0x014, 0x0001944C, - 0x014, 0x00059444, - 0x014, 0x0009944C, - 0x014, 0x000D9444, - 0xFF0F011F, 0xABCD, - 0x015, 0x0000F424, - 0x015, 0x0004F424, - 0x015, 0x0008F424, - 0x015, 0x000CF424, - 0xCDCDCDCD, 0xCDCD, - 0x015, 0x0000F474, - 0x015, 0x0004F477, - 0x015, 0x0008F455, - 0x015, 0x000CF455, - 0xFF0F011F, 0xDEAD, - 0x016, 0x00000339, - 0x016, 0x00040339, - 0x016, 0x00080339, - 0xFF0F011F, 0xABCD, - 0x016, 0x000C0356, - 0xCDCDCDCD, 0xCDCD, - 0x016, 0x000C0366, - 0xFF0F011F, 0xDEAD, - 0x000, 0x00010159, - 0x018, 0x0000F401, - 0x0FE, 0x00000000, - 0x0FE, 0x00000000, - 0x01F, 0x00000003, - 0x0FE, 0x00000000, - 0x0FE, 0x00000000, - 0x01E, 0x00000247, - 0x01F, 0x00000000, - 0x000, 0x00030159, -}; - -void ODM_ReadAndConfig_RadioA_1T_8723A(struct dm_odm_t *pDM_Odm) -{ - #define READ_NEXT_PAIR(v1, v2, i) \ - do { \ - i += 2; v1 = Array[i]; v2 = Array[i+1];\ - } while (0) - - u32 hex = 0; - u32 i = 0; - u8 platform = 0x04; - u8 board = pDM_Odm->BoardType; - u32 ArrayLen = ARRAY_SIZE(Array_RadioA_1T_8723A); - u32 *Array = Array_RadioA_1T_8723A; - - hex += board; - hex += ODM_ITRF_USB << 8; - hex += platform << 16; - hex += 0xFF000000; - - for (i = 0; i < ArrayLen; i += 2) { - u32 v1 = Array[i]; - u32 v2 = Array[i+1]; - - /* This (offset, data) pair meets the condition. */ - if (v1 < 0xCDCDCDCD) { - odm_ConfigRFReg_8723A(pDM_Odm, v1, v2, RF_PATH_A, v1); - continue; - } else { - if (!CheckCondition(Array[i], hex)) { - /* Discard the following (offset, data) pairs. */ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < ArrayLen - 2) - READ_NEXT_PAIR(v1, v2, i); - i -= 2; /* prevent from for-loop += 2 */ - } else { - /* Configure matched pairs and skip to end of if-else. */ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < ArrayLen - 2) { - odm_ConfigRFReg_8723A(pDM_Odm, v1, v2, - RF_PATH_A, v1); - READ_NEXT_PAIR(v1, v2, i); - } - - while (v2 != 0xDEAD && i < ArrayLen - 2) - READ_NEXT_PAIR(v1, v2, i); - } - } - } -} diff --git a/drivers/staging/rtl8723au/hal/HalPwrSeqCmd.c b/drivers/staging/rtl8723au/hal/HalPwrSeqCmd.c deleted file mode 100644 index 0a3d96e..0000000 --- a/drivers/staging/rtl8723au/hal/HalPwrSeqCmd.c +++ /dev/null @@ -1,156 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -/*++ -Copyright (c) Realtek Semiconductor Corp. All rights reserved. - -Module Name: - HalPwrSeqCmd.c - -Abstract: - Implement HW Power sequence configuration CMD handling routine for - Realtek devices. - -Major Change History: - When Who What - ---------- --------------- ------------------------------- - 2011-10-26 Lucas Modify to be compatible with SD4-CE driver. - 2011-07-07 Roger Create. - ---*/ -#include <HalPwrSeqCmd.h> -#include <usb_ops_linux.h> - -/* */ -/* Description: */ -/* This routine deal with the Power Configuration CMDs parsing - for RTL8723/RTL8188E Series IC. */ -/* */ -/* Assumption: */ -/* We should follow specific format which was released from - HW SD. */ -/* */ -/* 2011.07.07, added by Roger. */ -/* */ -u8 HalPwrSeqCmdParsing23a(struct rtw_adapter *padapter, u8 CutVersion, - u8 FabVersion, u8 InterfaceType, - struct wlan_pwr_cfg PwrSeqCmd[]) -{ - struct wlan_pwr_cfg PwrCfgCmd; - u8 bPollingBit; - u32 AryIdx = 0; - u8 value; - u32 offset; - u32 pollingCount = 0; /* polling autoload done. */ - u32 maxPollingCnt = 5000; - - do { - PwrCfgCmd = PwrSeqCmd[AryIdx]; - - RT_TRACE(_module_hal_init_c_, _drv_info_, - "HalPwrSeqCmdParsing23a: offset(%#x) cut_msk(%#x) fab_msk(%#x) interface_msk(%#x) base(%#x) cmd(%#x) msk(%#x) value(%#x)\n", - GET_PWR_CFG_OFFSET(PwrCfgCmd), - GET_PWR_CFG_CUT_MASK(PwrCfgCmd), - GET_PWR_CFG_FAB_MASK(PwrCfgCmd), - GET_PWR_CFG_INTF_MASK(PwrCfgCmd), - GET_PWR_CFG_BASE(PwrCfgCmd), - GET_PWR_CFG_CMD(PwrCfgCmd), - GET_PWR_CFG_MASK(PwrCfgCmd), - GET_PWR_CFG_VALUE(PwrCfgCmd)); - - /* 2 Only Handle the command whose FAB, CUT, and Interface are - matched */ - if ((GET_PWR_CFG_FAB_MASK(PwrCfgCmd) & FabVersion) && - (GET_PWR_CFG_CUT_MASK(PwrCfgCmd) & CutVersion) && - (GET_PWR_CFG_INTF_MASK(PwrCfgCmd) & InterfaceType)) { - switch (GET_PWR_CFG_CMD(PwrCfgCmd)) { - case PWR_CMD_READ: - RT_TRACE(_module_hal_init_c_, _drv_info_, - "HalPwrSeqCmdParsing23a: PWR_CMD_READ\n"); - break; - - case PWR_CMD_WRITE: - RT_TRACE(_module_hal_init_c_, _drv_info_, - "HalPwrSeqCmdParsing23a: PWR_CMD_WRITE\n"); - offset = GET_PWR_CFG_OFFSET(PwrCfgCmd); - - /* Read the value from system register */ - value = rtl8723au_read8(padapter, offset); - - value &= ~(GET_PWR_CFG_MASK(PwrCfgCmd)); - value |= (GET_PWR_CFG_VALUE(PwrCfgCmd) & - GET_PWR_CFG_MASK(PwrCfgCmd)); - - /* Write the value back to system register */ - rtl8723au_write8(padapter, offset, value); - break; - - case PWR_CMD_POLLING: - RT_TRACE(_module_hal_init_c_, _drv_info_, - "HalPwrSeqCmdParsing23a: PWR_CMD_POLLING\n"); - - bPollingBit = false; - offset = GET_PWR_CFG_OFFSET(PwrCfgCmd); - do { - value = rtl8723au_read8(padapter, - offset); - - value &= GET_PWR_CFG_MASK(PwrCfgCmd); - if (value == - (GET_PWR_CFG_VALUE(PwrCfgCmd) & - GET_PWR_CFG_MASK(PwrCfgCmd))) - bPollingBit = true; - else - udelay(10); - - if (pollingCount++ > maxPollingCnt) { - DBG_8723A("Fail to polling " - "Offset[%#x]\n", - offset); - return false; - } - } while (!bPollingBit); - - break; - - case PWR_CMD_DELAY: - RT_TRACE(_module_hal_init_c_, _drv_info_, - "HalPwrSeqCmdParsing23a: PWR_CMD_DELAY\n"); - if (GET_PWR_CFG_VALUE(PwrCfgCmd) == - PWRSEQ_DELAY_US) - udelay(GET_PWR_CFG_OFFSET(PwrCfgCmd)); - else - udelay(GET_PWR_CFG_OFFSET(PwrCfgCmd) * - 1000); - break; - - case PWR_CMD_END: - /* When this command is parsed, end - the process */ - RT_TRACE(_module_hal_init_c_, _drv_info_, - "HalPwrSeqCmdParsing23a: PWR_CMD_END\n"); - return true; - - default: - RT_TRACE(_module_hal_init_c_, _drv_err_, - "HalPwrSeqCmdParsing23a: Unknown CMD!!\n"); - break; - } - } - - AryIdx++; /* Add Array Index */ - } while (1); - - return true; -} diff --git a/drivers/staging/rtl8723au/hal/hal_com.c b/drivers/staging/rtl8723au/hal/hal_com.c deleted file mode 100644 index 9d7b11b..0000000 --- a/drivers/staging/rtl8723au/hal/hal_com.c +++ /dev/null @@ -1,853 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#include <osdep_service.h> -#include <drv_types.h> - -#include <hal_intf.h> -#include <hal_com.h> -#include <rtl8723a_hal.h> -#include <usb_ops_linux.h> - -#define _HAL_INIT_C_ - -#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 - -/* return the final channel plan decision */ -/* hw_channel_plan: channel plan from HW (efuse/eeprom) */ -/* sw_channel_plan: channel plan from SW (registry/module param) */ -/* def_channel_plan: channel plan used when the former two is invalid */ -u8 hal_com_get_channel_plan23a(struct rtw_adapter *padapter, u8 hw_channel_plan, - u8 sw_channel_plan, u8 def_channel_plan, - bool AutoLoadFail) -{ - u8 swConfig; - u8 chnlPlan; - - swConfig = true; - if (!AutoLoadFail) { - if (!rtw_is_channel_plan_valid(sw_channel_plan)) - swConfig = false; - if (hw_channel_plan & EEPROM_CHANNEL_PLAN_BY_HW_MASK) - swConfig = false; - } - - if (swConfig == true) - chnlPlan = sw_channel_plan; - else - chnlPlan = hw_channel_plan & (~EEPROM_CHANNEL_PLAN_BY_HW_MASK); - - if (!rtw_is_channel_plan_valid(chnlPlan)) - chnlPlan = def_channel_plan; - - return chnlPlan; -} - -u8 MRateToHwRate23a(u8 rate) -{ - u8 ret = DESC_RATE1M; - - switch (rate) { - /* CCK and OFDM non-HT rates */ - case IEEE80211_CCK_RATE_1MB: - ret = DESC_RATE1M; - break; - case IEEE80211_CCK_RATE_2MB: - ret = DESC_RATE2M; - break; - case IEEE80211_CCK_RATE_5MB: - ret = DESC_RATE5_5M; - break; - case IEEE80211_CCK_RATE_11MB: - ret = DESC_RATE11M; - break; - case IEEE80211_OFDM_RATE_6MB: - ret = DESC_RATE6M; - break; - case IEEE80211_OFDM_RATE_9MB: - ret = DESC_RATE9M; - break; - case IEEE80211_OFDM_RATE_12MB: - ret = DESC_RATE12M; - break; - case IEEE80211_OFDM_RATE_18MB: - ret = DESC_RATE18M; - break; - case IEEE80211_OFDM_RATE_24MB: - ret = DESC_RATE24M; - break; - case IEEE80211_OFDM_RATE_36MB: - ret = DESC_RATE36M; - break; - case IEEE80211_OFDM_RATE_48MB: - ret = DESC_RATE48M; - break; - case IEEE80211_OFDM_RATE_54MB: - ret = DESC_RATE54M; - break; - - /* HT rates since here */ - /* case MGN_MCS0: ret = DESC_RATEMCS0; break; */ - /* case MGN_MCS1: ret = DESC_RATEMCS1; break; */ - /* case MGN_MCS2: ret = DESC_RATEMCS2; break; */ - /* case MGN_MCS3: ret = DESC_RATEMCS3; break; */ - /* case MGN_MCS4: ret = DESC_RATEMCS4; break; */ - /* case MGN_MCS5: ret = DESC_RATEMCS5; break; */ - /* case MGN_MCS6: ret = DESC_RATEMCS6; break; */ - /* case MGN_MCS7: ret = DESC_RATEMCS7; break; */ - - default: - break; - } - return ret; -} - -void HalSetBrateCfg23a(struct rtw_adapter *padapter, u8 *mBratesOS) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 i, is_brate, brate; - u16 brate_cfg = 0; - u8 rate_index; - - for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) { - is_brate = mBratesOS[i] & IEEE80211_BASIC_RATE_MASK; - brate = mBratesOS[i] & 0x7f; - - if (is_brate) { - switch (brate) { - case IEEE80211_CCK_RATE_1MB: - brate_cfg |= RATE_1M; - break; - case IEEE80211_CCK_RATE_2MB: - brate_cfg |= RATE_2M; - break; - case IEEE80211_CCK_RATE_5MB: - brate_cfg |= RATE_5_5M; - break; - case IEEE80211_CCK_RATE_11MB: - brate_cfg |= RATE_11M; - break; - case IEEE80211_OFDM_RATE_6MB: - brate_cfg |= RATE_6M; - break; - case IEEE80211_OFDM_RATE_9MB: - brate_cfg |= RATE_9M; - break; - case IEEE80211_OFDM_RATE_12MB: - brate_cfg |= RATE_12M; - break; - case IEEE80211_OFDM_RATE_18MB: - brate_cfg |= RATE_18M; - break; - case IEEE80211_OFDM_RATE_24MB: - brate_cfg |= RATE_24M; - break; - case IEEE80211_OFDM_RATE_36MB: - brate_cfg |= RATE_36M; - break; - case IEEE80211_OFDM_RATE_48MB: - brate_cfg |= RATE_48M; - break; - case IEEE80211_OFDM_RATE_54MB: - brate_cfg |= RATE_54M; - break; - } - } - } - - /* 2007.01.16, by Emily */ - /* Select RRSR (in Legacy-OFDM and CCK) */ - /* For 8190, we select only 24M, 12M, 6M, 11M, 5.5M, 2M, - and 1M from the Basic rate. */ - /* We do not use other rates. */ - /* 2011.03.30 add by Luke Lee */ - /* CCK 2M ACK should be disabled for some BCM and Atheros AP IOT */ - /* because CCK 2M has poor TXEVM */ - /* CCK 5.5M & 11M ACK should be enabled for better - performance */ - - brate_cfg = (brate_cfg | 0xd) & 0x15d; - pHalData->BasicRateSet = brate_cfg; - brate_cfg |= 0x01; /* default enable 1M ACK rate */ - DBG_8723A("HW_VAR_BASIC_RATE: BrateCfg(%#x)\n", brate_cfg); - - /* Set RRSR rate table. */ - rtl8723au_write8(padapter, REG_RRSR, brate_cfg & 0xff); - rtl8723au_write8(padapter, REG_RRSR + 1, (brate_cfg >> 8) & 0xff); - rtl8723au_write8(padapter, REG_RRSR + 2, - rtl8723au_read8(padapter, REG_RRSR + 2) & 0xf0); - - rate_index = 0; - /* Set RTS initial rate */ - while (brate_cfg > 0x1) { - brate_cfg >>= 1; - rate_index++; - } - /* Ziv - Check */ - rtl8723au_write8(padapter, REG_INIRTS_RATE_SEL, rate_index); -} - -static void _OneOutPipeMapping(struct rtw_adapter *pAdapter) -{ - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter); - - pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0]; /* VO */ - pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0]; /* VI */ - pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[0]; /* BE */ - pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[0]; /* BK */ - - pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */ - pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */ - pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */ - pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD */ -} - -static void _TwoOutPipeMapping(struct rtw_adapter *pAdapter, bool bWIFICfg) -{ - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter); - - if (bWIFICfg) { /* WMM */ - /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */ - /* 0, 1, 0, 1, 0, 0, 0, 0, 0 }; */ - /* 0:H, 1:L */ - pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[1]; /* VO */ - pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0]; /* VI */ - pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1]; /* BE */ - pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[0]; /* BK */ - - pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */ - pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */ - pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */ - pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/ - } else { /* typical setting */ - /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */ - /* 1, 1, 0, 0, 0, 0, 0, 0, 0 }; */ - /* 0:H, 1:L */ - pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0]; /* VO */ - pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0]; /* VI */ - pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1]; /* BE */ - pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1]; /* BK */ - - pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */ - pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */ - pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */ - pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/ - } -} - -static void _ThreeOutPipeMapping(struct rtw_adapter *pAdapter, bool bWIFICfg) -{ - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter); - - if (bWIFICfg) { /* for WMM */ - /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */ - /* 1, 2, 1, 0, 0, 0, 0, 0, 0 }; */ - /* 0:H, 1:N, 2:L */ - pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0]; /* VO */ - pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1]; /* VI */ - pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2]; /* BE */ - pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1]; /* BK */ - - pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */ - pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */ - pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */ - pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/ - } else { /* typical setting */ - /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */ - /* 2, 2, 1, 0, 0, 0, 0, 0, 0 }; */ - /* 0:H, 1:N, 2:L */ - pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0]; /* VO */ - pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1]; /* VI */ - pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2]; /* BE */ - pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[2]; /* BK */ - - pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */ - pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */ - pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */ - pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/ - } -} - -bool Hal_MappingOutPipe23a(struct rtw_adapter *pAdapter, u8 NumOutPipe) -{ - struct registry_priv *pregistrypriv = &pAdapter->registrypriv; - bool bWIFICfg = (pregistrypriv->wifi_spec) ? true : false; - bool result = true; - - switch (NumOutPipe) { - case 2: - _TwoOutPipeMapping(pAdapter, bWIFICfg); - break; - case 3: - _ThreeOutPipeMapping(pAdapter, bWIFICfg); - break; - case 1: - _OneOutPipeMapping(pAdapter); - break; - default: - result = false; - break; - } - - return result; -} - -/* -* C2H event format: -* Field TRIGGER CONTENT CMD_SEQ CMD_LEN CMD_ID -* BITS [127:120] [119:16] [15:8] [7:4] [3:0] -*/ - -void c2h_evt_clear23a(struct rtw_adapter *adapter) -{ - rtl8723au_write8(adapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE); -} - -int c2h_evt_read23a(struct rtw_adapter *adapter, u8 *buf) -{ - int ret = _FAIL; - struct c2h_evt_hdr *c2h_evt; - int i; - u8 trigger; - - if (buf == NULL) - goto exit; - - trigger = rtl8723au_read8(adapter, REG_C2HEVT_CLEAR); - - if (trigger == C2H_EVT_HOST_CLOSE) - goto exit; /* Not ready */ - if (trigger != C2H_EVT_FW_CLOSE) - goto clear_evt; /* Not a valid value */ - - c2h_evt = (struct c2h_evt_hdr *)buf; - - memset(c2h_evt, 0, 16); - - *buf = rtl8723au_read8(adapter, REG_C2HEVT_MSG_NORMAL); - *(buf + 1) = rtl8723au_read8(adapter, REG_C2HEVT_MSG_NORMAL + 1); - - RT_PRINT_DATA(_module_hal_init_c_, _drv_info_, "c2h_evt_read23a(): ", - &c2h_evt, sizeof(c2h_evt)); - - if (0) { - DBG_8723A("%s id:%u, len:%u, seq:%u, trigger:0x%02x\n", - __func__, c2h_evt->id, c2h_evt->plen, c2h_evt->seq, - trigger); - } - - /* Read the content */ - for (i = 0; i < c2h_evt->plen; i++) - c2h_evt->payload[i] = rtl8723au_read8(adapter, - REG_C2HEVT_MSG_NORMAL + - sizeof(*c2h_evt) + i); - - RT_PRINT_DATA(_module_hal_init_c_, _drv_info_, - "c2h_evt_read23a(): Command Content:\n", c2h_evt->payload, - c2h_evt->plen); - - ret = _SUCCESS; - -clear_evt: - /* - * Clear event to notify FW we have read the command. - * If this field isn't clear, the FW won't update the - * next command message. - */ - c2h_evt_clear23a(adapter); -exit: - return ret; -} - -void -rtl8723a_set_ampdu_min_space(struct rtw_adapter *padapter, u8 MinSpacingToSet) -{ - u8 SecMinSpace; - - if (MinSpacingToSet <= 7) { - switch (padapter->securitypriv.dot11PrivacyAlgrthm) { - case 0: - case WLAN_CIPHER_SUITE_CCMP: - SecMinSpace = 0; - break; - - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - case WLAN_CIPHER_SUITE_TKIP: - SecMinSpace = 6; - break; - default: - SecMinSpace = 7; - break; - } - - if (MinSpacingToSet < SecMinSpace) - MinSpacingToSet = SecMinSpace; - - MinSpacingToSet |= - rtl8723au_read8(padapter, REG_AMPDU_MIN_SPACE) & 0xf8; - rtl8723au_write8(padapter, REG_AMPDU_MIN_SPACE, - MinSpacingToSet); - } -} - -void rtl8723a_set_ampdu_factor(struct rtw_adapter *padapter, u8 FactorToSet) -{ - u8 RegToSet_Normal[4] = { 0x41, 0xa8, 0x72, 0xb9 }; - u8 MaxAggNum; - u8 *pRegToSet; - u8 index = 0; - - pRegToSet = RegToSet_Normal; /* 0xb972a841; */ - - if (rtl8723a_BT_enabled(padapter) && - rtl8723a_BT_using_antenna_1(padapter)) - MaxAggNum = 0x8; - else - MaxAggNum = 0xF; - - if (FactorToSet <= 3) { - FactorToSet = 1 << (FactorToSet + 2); - if (FactorToSet > MaxAggNum) - FactorToSet = MaxAggNum; - - for (index = 0; index < 4; index++) { - if ((pRegToSet[index] & 0xf0) > (FactorToSet << 4)) - pRegToSet[index] = (pRegToSet[index] & 0x0f) | - (FactorToSet << 4); - - if ((pRegToSet[index] & 0x0f) > FactorToSet) - pRegToSet[index] = (pRegToSet[index] & 0xf0) | - FactorToSet; - - rtl8723au_write8(padapter, REG_AGGLEN_LMT + index, - pRegToSet[index]); - } - } -} - -void rtl8723a_set_acm_ctrl(struct rtw_adapter *padapter, u8 ctrl) -{ - u8 hwctrl = 0; - - if (ctrl != 0) { - hwctrl |= AcmHw_HwEn; - - if (ctrl & BIT(1)) /* BE */ - hwctrl |= AcmHw_BeqEn; - - if (ctrl & BIT(2)) /* VI */ - hwctrl |= AcmHw_ViqEn; - - if (ctrl & BIT(3)) /* VO */ - hwctrl |= AcmHw_VoqEn; - } - - DBG_8723A("[HW_VAR_ACM_CTRL] Write 0x%02X\n", hwctrl); - rtl8723au_write8(padapter, REG_ACMHWCTRL, hwctrl); -} - -void rtl8723a_set_media_status(struct rtw_adapter *padapter, u8 status) -{ - u8 val8; - - val8 = rtl8723au_read8(padapter, MSR) & 0x0c; - val8 |= status; - rtl8723au_write8(padapter, MSR, val8); -} - -void rtl8723a_set_media_status1(struct rtw_adapter *padapter, u8 status) -{ - u8 val8; - - val8 = rtl8723au_read8(padapter, MSR) & 0x03; - val8 |= status << 2; - rtl8723au_write8(padapter, MSR, val8); -} - -void rtl8723a_set_bcn_func(struct rtw_adapter *padapter, u8 val) -{ - if (val) - SetBcnCtrlReg23a(padapter, EN_BCN_FUNCTION | EN_TXBCN_RPT, 0); - else - SetBcnCtrlReg23a(padapter, 0, EN_BCN_FUNCTION | EN_TXBCN_RPT); -} - -void rtl8723a_check_bssid(struct rtw_adapter *padapter, u8 val) -{ - u32 val32; - - val32 = rtl8723au_read32(padapter, REG_RCR); - if (val) - val32 |= RCR_CBSSID_DATA | RCR_CBSSID_BCN; - else - val32 &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN); - rtl8723au_write32(padapter, REG_RCR, val32); -} - -void rtl8723a_mlme_sitesurvey(struct rtw_adapter *padapter, u8 flag) -{ - if (flag) { /* under sitesurvey */ - u32 v32; - - /* config RCR to receive different BSSID & not - to receive data frame */ - v32 = rtl8723au_read32(padapter, REG_RCR); - v32 &= ~(RCR_CBSSID_BCN); - rtl8723au_write32(padapter, REG_RCR, v32); - /* reject all data frame */ - rtl8723au_write16(padapter, REG_RXFLTMAP2, 0); - - /* disable update TSF */ - SetBcnCtrlReg23a(padapter, DIS_TSF_UDT, 0); - } else { /* sitesurvey done */ - - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo; - u32 v32; - - pmlmeinfo = &pmlmeext->mlmext_info; - - if ((is_client_associated_to_ap23a(padapter) == true) || - ((pmlmeinfo->state & 0x03) == MSR_ADHOC) || - ((pmlmeinfo->state & 0x03) == MSR_AP)) { - /* enable to rx data frame */ - rtl8723au_write16(padapter, REG_RXFLTMAP2, 0xFFFF); - - /* enable update TSF */ - SetBcnCtrlReg23a(padapter, 0, DIS_TSF_UDT); - } - - v32 = rtl8723au_read32(padapter, REG_RCR); - v32 |= RCR_CBSSID_BCN; - rtl8723au_write32(padapter, REG_RCR, v32); - } - - rtl8723a_BT_wifiscan_notify(padapter, flag ? true : false); -} - -void rtl8723a_on_rcr_am(struct rtw_adapter *padapter) -{ - rtl8723au_write32(padapter, REG_RCR, - rtl8723au_read32(padapter, REG_RCR) | RCR_AM); - DBG_8723A("%s, %d, RCR = %x\n", __func__, __LINE__, - rtl8723au_read32(padapter, REG_RCR)); -} - -void rtl8723a_off_rcr_am(struct rtw_adapter *padapter) -{ - rtl8723au_write32(padapter, REG_RCR, - rtl8723au_read32(padapter, REG_RCR) & (~RCR_AM)); - DBG_8723A("%s, %d, RCR = %x\n", __func__, __LINE__, - rtl8723au_read32(padapter, REG_RCR)); -} - -void rtl8723a_set_slot_time(struct rtw_adapter *padapter, u8 slottime) -{ - u8 u1bAIFS, aSifsTime; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - rtl8723au_write8(padapter, REG_SLOT, slottime); - - if (pmlmeinfo->WMM_enable == 0) { - if (pmlmeext->cur_wireless_mode == WIRELESS_11B) - aSifsTime = 10; - else - aSifsTime = 16; - - u1bAIFS = aSifsTime + (2 * pmlmeinfo->slotTime); - - /* <Roger_EXP> Temporary removed, 2008.06.20. */ - rtl8723au_write8(padapter, REG_EDCA_VO_PARAM, u1bAIFS); - rtl8723au_write8(padapter, REG_EDCA_VI_PARAM, u1bAIFS); - rtl8723au_write8(padapter, REG_EDCA_BE_PARAM, u1bAIFS); - rtl8723au_write8(padapter, REG_EDCA_BK_PARAM, u1bAIFS); - } -} - -void rtl8723a_ack_preamble(struct rtw_adapter *padapter, u8 bShortPreamble) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 regTmp; - - /* Joseph marked out for Netgear 3500 TKIP - channel 7 issue.(Temporarily) */ - regTmp = (pHalData->nCur40MhzPrimeSC) << 5; - /* regTmp = 0; */ - if (bShortPreamble) - regTmp |= 0x80; - rtl8723au_write8(padapter, REG_RRSR + 2, regTmp); -} - -void rtl8723a_set_sec_cfg(struct rtw_adapter *padapter, u8 sec) -{ - rtl8723au_write8(padapter, REG_SECCFG, sec); -} - -void rtl8723a_cam_empty_entry(struct rtw_adapter *padapter, u8 ucIndex) -{ - u8 i; - u32 ulCommand = 0; - u32 ulContent = 0; - u32 ulEncAlgo = CAM_AES; - - for (i = 0; i < CAM_CONTENT_COUNT; i++) { - /* filled id in CAM config 2 byte */ - if (i == 0) { - ulContent |= (ucIndex & 0x03) | - ((u16) (ulEncAlgo) << 2); - /* ulContent |= CAM_VALID; */ - } else { - ulContent = 0; - } - /* polling bit, and No Write enable, and address */ - ulCommand = CAM_CONTENT_COUNT * ucIndex + i; - ulCommand = ulCommand | CAM_POLLINIG | CAM_WRITE; - /* write content 0 is equall to mark invalid */ - /* delay_ms(40); */ - rtl8723au_write32(padapter, WCAMI, ulContent); - /* delay_ms(40); */ - rtl8723au_write32(padapter, REG_CAMCMD, ulCommand); - } -} - -void rtl8723a_cam_invalidate_all(struct rtw_adapter *padapter) -{ - rtl8723au_write32(padapter, REG_CAMCMD, CAM_POLLINIG | BIT(30)); -} - -void rtl8723a_cam_write(struct rtw_adapter *padapter, - u8 entry, u16 ctrl, const u8 *mac, const u8 *key) -{ - u32 cmd; - unsigned int i, val, addr; - int j; - - addr = entry << 3; - - for (j = 5; j >= 0; j--) { - switch (j) { - case 0: - val = ctrl | (mac[0] << 16) | (mac[1] << 24); - break; - case 1: - val = mac[2] | (mac[3] << 8) | - (mac[4] << 16) | (mac[5] << 24); - break; - default: - i = (j - 2) << 2; - val = key[i] | (key[i+1] << 8) | - (key[i+2] << 16) | (key[i+3] << 24); - break; - } - - rtl8723au_write32(padapter, WCAMI, val); - cmd = CAM_POLLINIG | CAM_WRITE | (addr + j); - rtl8723au_write32(padapter, REG_CAMCMD, cmd); - - /* DBG_8723A("%s => cam write: %x, %x\n", __func__, cmd, val);*/ - } -} - -void rtl8723a_fifo_cleanup(struct rtw_adapter *padapter) -{ -#define RW_RELEASE_EN BIT(18) -#define RXDMA_IDLE BIT(17) - - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - u8 trycnt = 100; - - /* pause tx */ - rtl8723au_write8(padapter, REG_TXPAUSE, 0xff); - - /* keep sn */ - padapter->xmitpriv.nqos_ssn = rtl8723au_read8(padapter, REG_NQOS_SEQ); - - if (pwrpriv->bkeepfwalive != true) { - u32 v32; - - /* RX DMA stop */ - v32 = rtl8723au_read32(padapter, REG_RXPKT_NUM); - v32 |= RW_RELEASE_EN; - rtl8723au_write32(padapter, REG_RXPKT_NUM, v32); - do { - v32 = rtl8723au_read32(padapter, - REG_RXPKT_NUM) & RXDMA_IDLE; - if (!v32) - break; - } while (trycnt--); - if (trycnt == 0) - DBG_8723A("Stop RX DMA failed......\n"); - - /* RQPN Load 0 */ - rtl8723au_write16(padapter, REG_RQPN_NPQ, 0); - rtl8723au_write32(padapter, REG_RQPN, 0x80000000); - mdelay(10); - } -} - -void rtl8723a_bcn_valid(struct rtw_adapter *padapter) -{ - /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2, - write 1 to clear, Clear by sw */ - rtl8723au_write8(padapter, REG_TDECTRL + 2, - rtl8723au_read8(padapter, REG_TDECTRL + 2) | BIT(0)); -} - -bool rtl8723a_get_bcn_valid(struct rtw_adapter *padapter) -{ - bool retval; - - retval = (rtl8723au_read8(padapter, REG_TDECTRL + 2) & BIT(0)) ? true : false; - - return retval; -} - -void rtl8723a_set_beacon_interval(struct rtw_adapter *padapter, u16 interval) -{ - rtl8723au_write16(padapter, REG_BCN_INTERVAL, interval); -} - -void rtl8723a_set_resp_sifs(struct rtw_adapter *padapter, - u8 r2t1, u8 r2t2, u8 t2t1, u8 t2t2) -{ - /* SIFS_Timer = 0x0a0a0808; */ - /* RESP_SIFS for CCK */ - /* SIFS_T2T_CCK (0x08) */ - rtl8723au_write8(padapter, REG_R2T_SIFS, r2t1); - /* SIFS_R2T_CCK(0x08) */ - rtl8723au_write8(padapter, REG_R2T_SIFS + 1, r2t2); - /* RESP_SIFS for OFDM */ - /* SIFS_T2T_OFDM (0x0a) */ - rtl8723au_write8(padapter, REG_T2T_SIFS, t2t1); - /* SIFS_R2T_OFDM(0x0a) */ - rtl8723au_write8(padapter, REG_T2T_SIFS + 1, t2t2); -} - -void rtl8723a_set_ac_param_vo(struct rtw_adapter *padapter, u32 vo) -{ - rtl8723au_write32(padapter, REG_EDCA_VO_PARAM, vo); -} - -void rtl8723a_set_ac_param_vi(struct rtw_adapter *padapter, u32 vi) -{ - rtl8723au_write32(padapter, REG_EDCA_VI_PARAM, vi); -} - -void rtl8723a_set_ac_param_be(struct rtw_adapter *padapter, u32 be) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - pHalData->AcParam_BE = be; - rtl8723au_write32(padapter, REG_EDCA_BE_PARAM, be); -} - -void rtl8723a_set_ac_param_bk(struct rtw_adapter *padapter, u32 bk) -{ - rtl8723au_write32(padapter, REG_EDCA_BK_PARAM, bk); -} - -void rtl8723a_set_rxdma_agg_pg_th(struct rtw_adapter *padapter, u8 val) -{ - rtl8723au_write8(padapter, REG_RXDMA_AGG_PG_TH, val); -} - -void rtl8723a_set_initial_gain(struct rtw_adapter *padapter, u32 rx_gain) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct dig_t *pDigTable = &pHalData->odmpriv.DM_DigTable; - - if (rx_gain == 0xff) /* restore rx gain */ - ODM_Write_DIG23a(&pHalData->odmpriv, pDigTable->BackupIGValue); - else { - pDigTable->BackupIGValue = pDigTable->CurIGValue; - ODM_Write_DIG23a(&pHalData->odmpriv, rx_gain); - } -} - -void rtl8723a_odm_support_ability_restore(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - pHalData->odmpriv.SupportAbility = pHalData->odmpriv.BK_SupportAbility; -} - -void rtl8723a_odm_support_ability_backup(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - pHalData->odmpriv.BK_SupportAbility = pHalData->odmpriv.SupportAbility; -} - -void rtl8723a_odm_support_ability_set(struct rtw_adapter *padapter, u32 val) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (val == DYNAMIC_ALL_FUNC_ENABLE) - pHalData->odmpriv.SupportAbility = pHalData->dmpriv.InitODMFlag; - else - pHalData->odmpriv.SupportAbility |= val; -} - -void rtl8723a_odm_support_ability_clr(struct rtw_adapter *padapter, u32 val) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - pHalData->odmpriv.SupportAbility &= val; -} - -void rtl8723a_set_rpwm(struct rtw_adapter *padapter, u8 val) -{ - rtl8723au_write8(padapter, REG_USB_HRPWM, val); -} - -u8 rtl8723a_get_rf_type(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - return pHalData->rf_type; -} - -bool rtl8723a_get_fwlps_rf_on(struct rtw_adapter *padapter) -{ - bool retval; - u32 valRCR; - - /* When we halt NIC, we should check if FW LPS is leave. */ - - if ((padapter->bSurpriseRemoved == true) || - (padapter->pwrctrlpriv.rf_pwrstate == rf_off)) { - /* If it is in HW/SW Radio OFF or IPS state, we do - not check Fw LPS Leave, because Fw is unload. */ - retval = true; - } else { - valRCR = rtl8723au_read32(padapter, REG_RCR); - if (valRCR & 0x00070000) - retval = false; - else - retval = true; - } - - return retval; -} - -bool rtl8723a_chk_hi_queue_empty(struct rtw_adapter *padapter) -{ - u32 hgq; - - hgq = rtl8723au_read32(padapter, REG_HGQ_INFORMATION); - - return ((hgq & 0x0000ff00) == 0) ? true : false; -} diff --git a/drivers/staging/rtl8723au/hal/hal_intf.c b/drivers/staging/rtl8723au/hal/hal_intf.c deleted file mode 100644 index 5383e69..0000000 --- a/drivers/staging/rtl8723au/hal/hal_intf.c +++ /dev/null @@ -1,42 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ - -#define _HAL_INTF_C_ -#include <osdep_service.h> -#include <drv_types.h> - -#include <hal_intf.h> - -#include <rtl8723a_hal.h> - -void rtw_hal_update_ra_mask23a(struct sta_info *psta, u8 rssi_level) -{ - struct rtw_adapter *padapter; - struct mlme_priv *pmlmepriv; - - if (!psta) - return; - - padapter = psta->padapter; - - pmlmepriv = &padapter->mlmepriv; - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { -#ifdef CONFIG_8723AU_AP_MODE - add_RATid23a(padapter, psta, rssi_level); -#endif - } else - rtl8723a_update_ramask(padapter, psta->mac_id, rssi_level); -} diff --git a/drivers/staging/rtl8723au/hal/odm.c b/drivers/staging/rtl8723au/hal/odm.c deleted file mode 100644 index e279c34..0000000 --- a/drivers/staging/rtl8723au/hal/odm.c +++ /dev/null @@ -1,1732 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ - -#include "odm_precomp.h" -#include "usb_ops_linux.h" - -static const u16 dB_Invert_Table[8][12] = { - {1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4}, - {4, 5, 6, 6, 7, 8, 9, 10, 11, 13, 14, 16}, - {18, 20, 22, 25, 28, 32, 35, 40, 45, 50, 56, 63}, - {71, 79, 89, 100, 112, 126, 141, 158, 178, 200, 224, 251}, - {282, 316, 355, 398, 447, 501, 562, 631, 708, 794, 891, 1000}, - {1122, 1259, 1413, 1585, 1778, 1995, 2239, 2512, 2818, 3162, 3548, 3981}, - {4467, 5012, 5623, 6310, 7079, 7943, 8913, 10000, 11220, 12589, 14125, 15849}, - {17783, 19953, 22387, 25119, 28184, 31623, 35481, 39811, 44668, 50119, 56234, 65535} -}; - -static u32 EDCAParam[HT_IOT_PEER_MAX][3] = { /* UL DL */ - {0x5ea42b, 0x5ea42b, 0x5ea42b}, /* 0:unknown AP */ - {0xa44f, 0x5ea44f, 0x5e431c}, /* 1:realtek AP */ - {0x5ea42b, 0x5ea42b, 0x5ea42b}, /* 2:unknown AP => realtek_92SE */ - {0x5ea32b, 0x5ea42b, 0x5e4322}, /* 3:broadcom AP */ - {0x5ea422, 0x00a44f, 0x00a44f}, /* 4:ralink AP */ - {0x5ea322, 0x00a630, 0x00a44f}, /* 5:atheros AP */ - {0x5e4322, 0x5e4322, 0x5e4322},/* 6:cisco AP */ - {0x5ea44f, 0x00a44f, 0x5ea42b}, /* 8:marvell AP */ - {0x5ea42b, 0x5ea42b, 0x5ea42b}, /* 10:unknown AP => 92U AP */ - {0x5ea42b, 0xa630, 0x5e431c}, /* 11:airgocap AP */ -}; - -/* EDCA Parameter for AP/ADSL by Mingzhi 2011-11-22 */ - -/* Global var */ -u32 OFDMSwingTable23A[OFDM_TABLE_SIZE_92D] = { - 0x7f8001fe, /* 0, +6.0dB */ - 0x788001e2, /* 1, +5.5dB */ - 0x71c001c7, /* 2, +5.0dB */ - 0x6b8001ae, /* 3, +4.5dB */ - 0x65400195, /* 4, +4.0dB */ - 0x5fc0017f, /* 5, +3.5dB */ - 0x5a400169, /* 6, +3.0dB */ - 0x55400155, /* 7, +2.5dB */ - 0x50800142, /* 8, +2.0dB */ - 0x4c000130, /* 9, +1.5dB */ - 0x47c0011f, /* 10, +1.0dB */ - 0x43c0010f, /* 11, +0.5dB */ - 0x40000100, /* 12, +0dB */ - 0x3c8000f2, /* 13, -0.5dB */ - 0x390000e4, /* 14, -1.0dB */ - 0x35c000d7, /* 15, -1.5dB */ - 0x32c000cb, /* 16, -2.0dB */ - 0x300000c0, /* 17, -2.5dB */ - 0x2d4000b5, /* 18, -3.0dB */ - 0x2ac000ab, /* 19, -3.5dB */ - 0x288000a2, /* 20, -4.0dB */ - 0x26000098, /* 21, -4.5dB */ - 0x24000090, /* 22, -5.0dB */ - 0x22000088, /* 23, -5.5dB */ - 0x20000080, /* 24, -6.0dB */ - 0x1e400079, /* 25, -6.5dB */ - 0x1c800072, /* 26, -7.0dB */ - 0x1b00006c, /* 27. -7.5dB */ - 0x19800066, /* 28, -8.0dB */ - 0x18000060, /* 29, -8.5dB */ - 0x16c0005b, /* 30, -9.0dB */ - 0x15800056, /* 31, -9.5dB */ - 0x14400051, /* 32, -10.0dB */ - 0x1300004c, /* 33, -10.5dB */ - 0x12000048, /* 34, -11.0dB */ - 0x11000044, /* 35, -11.5dB */ - 0x10000040, /* 36, -12.0dB */ - 0x0f00003c,/* 37, -12.5dB */ - 0x0e400039,/* 38, -13.0dB */ - 0x0d800036,/* 39, -13.5dB */ - 0x0cc00033,/* 40, -14.0dB */ - 0x0c000030,/* 41, -14.5dB */ - 0x0b40002d,/* 42, -15.0dB */ -}; - -u8 CCKSwingTable_Ch1_Ch1323A[CCK_TABLE_SIZE][8] = { - {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, /* 0, +0dB */ - {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 1, -0.5dB */ - {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 2, -1.0dB */ - {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 3, -1.5dB */ - {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 4, -2.0dB */ - {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 5, -2.5dB */ - {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 6, -3.0dB */ - {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 7, -3.5dB */ - {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 8, -4.0dB */ - {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 9, -4.5dB */ - {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 10, -5.0dB */ - {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 11, -5.5dB */ - {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 12, -6.0dB */ - {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 13, -6.5dB */ - {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 14, -7.0dB */ - {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 15, -7.5dB */ - {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */ - {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 17, -8.5dB */ - {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 18, -9.0dB */ - {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 19, -9.5dB */ - {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 20, -10.0dB */ - {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 21, -10.5dB */ - {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 22, -11.0dB */ - {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 23, -11.5dB */ - {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 24, -12.0dB */ - {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 25, -12.5dB */ - {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 26, -13.0dB */ - {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 27, -13.5dB */ - {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 28, -14.0dB */ - {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 29, -14.5dB */ - {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 30, -15.0dB */ - {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 31, -15.5dB */ - {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} /* 32, -16.0dB */ -}; - -u8 CCKSwingTable_Ch1423A[CCK_TABLE_SIZE][8] = { - {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, /* 0, +0dB */ - {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 1, -0.5dB */ - {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 2, -1.0dB */ - {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 3, -1.5dB */ - {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 4, -2.0dB */ - {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 5, -2.5dB */ - {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 6, -3.0dB */ - {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 7, -3.5dB */ - {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 8, -4.0dB */ - {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 9, -4.5dB */ - {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 10, -5.0dB */ - {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 11, -5.5dB */ - {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 12, -6.0dB */ - {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 13, -6.5dB */ - {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 14, -7.0dB */ - {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 15, -7.5dB */ - {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */ - {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 17, -8.5dB */ - {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 18, -9.0dB */ - {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 19, -9.5dB */ - {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 20, -10.0dB */ - {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 21, -10.5dB */ - {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 22, -11.0dB */ - {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 23, -11.5dB */ - {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 24, -12.0dB */ - {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 25, -12.5dB */ - {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 26, -13.0dB */ - {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 27, -13.5dB */ - {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 28, -14.0dB */ - {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 29, -14.5dB */ - {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 30, -15.0dB */ - {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 31, -15.5dB */ - {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} /* 32, -16.0dB */ -}; - -/* Local Function predefine. */ - -/* START------------COMMON INFO RELATED--------------- */ -void odm_CommonInfoSelfInit23a(struct dm_odm_t *pDM_Odm); - -static void odm_CommonInfoSelfUpdate(struct hal_data_8723a *pHalData); - -void odm_CmnInfoInit_Debug23a(struct dm_odm_t *pDM_Odm); - -void odm_CmnInfoUpdate_Debug23a(struct dm_odm_t *pDM_Odm); - -/* START---------------DIG--------------------------- */ -void odm_FalseAlarmCounterStatistics23a(struct dm_odm_t *pDM_Odm); - -void odm_DIG23aInit(struct dm_odm_t *pDM_Odm); - -void odm_DIG23a(struct rtw_adapter *adapter); - -void odm_CCKPacketDetectionThresh23a(struct dm_odm_t *pDM_Odm); -/* END---------------DIG--------------------------- */ - -/* START-------BB POWER SAVE----------------------- */ -void odm23a_DynBBPSInit(struct dm_odm_t *pDM_Odm); - - -/* END---------BB POWER SAVE----------------------- */ - -void odm_DynamicTxPower23aInit(struct dm_odm_t *pDM_Odm); - -static void odm_RSSIMonitorCheck(struct dm_odm_t *pDM_Odm); -void odm_DynamicTxPower23a(struct dm_odm_t *pDM_Odm); - -static void odm_RefreshRateAdaptiveMask(struct dm_odm_t *pDM_Odm); - -void odm_RateAdaptiveMaskInit23a(struct dm_odm_t *pDM_Odm); - -static void odm_TXPowerTrackingInit(struct dm_odm_t *pDM_Odm); - -static void odm_EdcaTurboCheck23a(struct dm_odm_t *pDM_Odm); -static void ODM_EdcaTurboInit23a(struct dm_odm_t *pDM_Odm); - -#define RxDefaultAnt1 0x65a9 -#define RxDefaultAnt2 0x569a - -bool odm_StaDefAntSel(struct dm_odm_t *pDM_Odm, - u32 OFDM_Ant1_Cnt, - u32 OFDM_Ant2_Cnt, - u32 CCK_Ant1_Cnt, - u32 CCK_Ant2_Cnt, - u8 *pDefAnt - ); - -void odm_SetRxIdleAnt(struct dm_odm_t *pDM_Odm, - u8 Ant, - bool bDualPath -); - -/* 3 Export Interface */ - -/* 2011/09/21 MH Add to describe different team necessary resource allocate?? */ -void ODM23a_DMInit(struct dm_odm_t *pDM_Odm) -{ - /* For all IC series */ - odm_CommonInfoSelfInit23a(pDM_Odm); - odm_CmnInfoInit_Debug23a(pDM_Odm); - odm_DIG23aInit(pDM_Odm); - odm_RateAdaptiveMaskInit23a(pDM_Odm); - - odm23a_DynBBPSInit(pDM_Odm); - odm_DynamicTxPower23aInit(pDM_Odm); - odm_TXPowerTrackingInit(pDM_Odm); - ODM_EdcaTurboInit23a(pDM_Odm); -} - -/* 2011/09/20 MH This is the entry pointer for all team to execute HW out source DM. */ -/* You can not add any dummy function here, be care, you can only use DM structure */ -/* to perform any new ODM_DM. */ -void ODM_DMWatchdog23a(struct rtw_adapter *adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(adapter); - struct dm_odm_t *pDM_Odm = &pHalData->odmpriv; - struct pwrctrl_priv *pwrctrlpriv = &adapter->pwrctrlpriv; - - /* 2012.05.03 Luke: For all IC series */ - odm_CmnInfoUpdate_Debug23a(pDM_Odm); - odm_CommonInfoSelfUpdate(pHalData); - odm_FalseAlarmCounterStatistics23a(pDM_Odm); - odm_RSSIMonitorCheck(pDM_Odm); - - /* 8723A or 8189ES platform */ - /* NeilChen--2012--08--24-- */ - /* Fix Leave LPS issue */ - if ((pDM_Odm->Adapter->pwrctrlpriv.pwr_mode != PS_MODE_ACTIVE) &&/* in LPS mode */ - (pDM_Odm->SupportICType & ODM_RTL8723A)) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("----Step1: odm_DIG23a is in LPS mode\n")); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("---Step2: 8723AS is in LPS mode\n")); - odm_DIG23abyRSSI_LPS(pDM_Odm); - } else { - odm_DIG23a(adapter); - } - - odm_CCKPacketDetectionThresh23a(pDM_Odm); - - if (pwrctrlpriv->bpower_saving) - return; - - odm_RefreshRateAdaptiveMask(pDM_Odm); - - - odm_EdcaTurboCheck23a(pDM_Odm); -} - -/* */ -/* Init /.. Fixed HW value. Only init time. */ -/* */ -void ODM_CmnInfoInit23a(struct dm_odm_t *pDM_Odm, - enum odm_cmninfo CmnInfo, - u32 Value - ) -{ - /* ODM_RT_TRACE(pDM_Odm,); */ - - /* */ - /* This section is used for init value */ - /* */ - switch (CmnInfo) { - /* Fixed ODM value. */ - case ODM_CMNINFO_MP_TEST_CHIP: - pDM_Odm->bIsMPChip = (u8)Value; - break; - case ODM_CMNINFO_IC_TYPE: - pDM_Odm->SupportICType = Value; - break; - case ODM_CMNINFO_CUT_VER: - pDM_Odm->CutVersion = (u8)Value; - break; - case ODM_CMNINFO_FAB_VER: - pDM_Odm->FabVersion = (u8)Value; - break; - case ODM_CMNINFO_BOARD_TYPE: - pDM_Odm->BoardType = (u8)Value; - break; - case ODM_CMNINFO_EXT_LNA: - pDM_Odm->ExtLNA = (u8)Value; - break; - case ODM_CMNINFO_EXT_PA: - pDM_Odm->ExtPA = (u8)Value; - break; - case ODM_CMNINFO_EXT_TRSW: - pDM_Odm->ExtTRSW = (u8)Value; - break; - case ODM_CMNINFO_BINHCT_TEST: - pDM_Odm->bInHctTest = (bool)Value; - break; - case ODM_CMNINFO_BWIFI_TEST: - pDM_Odm->bWIFITest = (bool)Value; - break; - case ODM_CMNINFO_SMART_CONCURRENT: - pDM_Odm->bDualMacSmartConcurrent = (bool)Value; - break; - /* To remove the compiler warning, must add an empty default statement to handle the other values. */ - default: - /* do nothing */ - break; - } -} - -void ODM_CmnInfoPtrArrayHook23a(struct dm_odm_t *pDM_Odm, enum odm_cmninfo CmnInfo, - u16 Index, void *pValue) -{ - /* Hook call by reference pointer. */ - switch (CmnInfo) { - /* Dynamic call by reference pointer. */ - case ODM_CMNINFO_STA_STATUS: - pDM_Odm->pODM_StaInfo[Index] = (struct sta_info *)pValue; - break; - /* To remove the compiler warning, must add an empty default statement to handle the other values. */ - default: - /* do nothing */ - break; - } -} - -/* Update Band/CHannel/.. The values are dynamic but non-per-packet. */ -void ODM_CmnInfoUpdate23a(struct dm_odm_t *pDM_Odm, u32 CmnInfo, u64 Value) -{ - /* This init variable may be changed in run time. */ - switch (CmnInfo) { - case ODM_CMNINFO_WIFI_DIRECT: - pDM_Odm->bWIFI_Direct = (bool)Value; - break; - case ODM_CMNINFO_WIFI_DISPLAY: - pDM_Odm->bWIFI_Display = (bool)Value; - break; - case ODM_CMNINFO_LINK: - pDM_Odm->bLinked = (bool)Value; - break; - case ODM_CMNINFO_RSSI_MIN: - 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; - case ODM_CMNINFO_RA_THRESHOLD_LOW: - pDM_Odm->RateAdaptive.LowRSSIThresh = (u8)Value; - break; - } - -} - -void odm_CommonInfoSelfInit23a(struct dm_odm_t *pDM_Odm) -{ - u32 val32; - - val32 = rtl8723au_read32(pDM_Odm->Adapter, rFPGA0_XA_HSSIParameter2); - if (val32 & BIT(9)) - pDM_Odm->bCckHighPower = true; - else - pDM_Odm->bCckHighPower = false; - - pDM_Odm->RFPathRxEnable = - rtl8723au_read32(pDM_Odm->Adapter, rOFDM0_TRxPathEnable) & 0x0F; - - ODM_InitDebugSetting23a(pDM_Odm); -} - -static void odm_CommonInfoSelfUpdate(struct hal_data_8723a *pHalData) -{ - struct dm_odm_t *pDM_Odm = &pHalData->odmpriv; - struct sta_info *pEntry; - u8 EntryCnt = 0; - u8 i; - - for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) { - pEntry = pDM_Odm->pODM_StaInfo[i]; - if (pEntry) - EntryCnt++; - } - if (EntryCnt == 1) - pDM_Odm->bOneEntryOnly = true; - else - pDM_Odm->bOneEntryOnly = false; -} - -void odm_CmnInfoInit_Debug23a(struct dm_odm_t *pDM_Odm) -{ - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("odm_CmnInfoInit_Debug23a ==>\n")); - 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, ("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, ("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, ("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_CmnInfoUpdate_Debug23a(struct dm_odm_t *pDM_Odm) -{ - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("odm_CmnInfoUpdate_Debug23a ==>\n")); - 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_DIG23a(struct dm_odm_t *pDM_Odm, u8 CurrentIGI) -{ - struct rtw_adapter *adapter = pDM_Odm->Adapter; - struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable; - u32 val32; - - if (pDM_DigTable->CurIGValue != CurrentIGI) { - val32 = rtl8723au_read32(adapter, ODM_REG_IGI_A_11N); - val32 &= ~ODM_BIT_IGI_11N; - val32 |= CurrentIGI; - rtl8723au_write32(adapter, ODM_REG_IGI_A_11N, val32); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, - ("CurrentIGI(0x%02x). \n", CurrentIGI)); - pDM_DigTable->CurIGValue = CurrentIGI; - } - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, - ("ODM_Write_DIG23a():CurrentIGI = 0x%x \n", CurrentIGI)); -} - -/* Need LPS mode for CE platform --2012--08--24--- */ -/* 8723AS/8189ES */ -void odm_DIG23abyRSSI_LPS(struct dm_odm_t *pDM_Odm) -{ - struct rtw_adapter *pAdapter = pDM_Odm->Adapter; - struct false_alarm_stats *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt; - u8 RSSI_Lower = DM_DIG_MIN_NIC; /* 0x1E or 0x1C */ - u8 bFwCurrentInPSMode = false; - u8 CurrentIGI = pDM_Odm->RSSI_Min; - - if (!(pDM_Odm->SupportICType & ODM_RTL8723A)) - return; - - CurrentIGI = CurrentIGI+RSSI_OFFSET_DIG; - bFwCurrentInPSMode = pAdapter->pwrctrlpriv.bFwCurrentInPSMode; - - /* Using FW PS mode to make IGI */ - if (bFwCurrentInPSMode) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, - ("---Neil---odm_DIG23a is in LPS mode\n")); - /* Adjust by FA in LPS MODE */ - if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH2_LPS) - CurrentIGI = CurrentIGI+2; - else if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH1_LPS) - CurrentIGI = CurrentIGI+1; - else if (pFalseAlmCnt->Cnt_all < DM_DIG_FA_TH0_LPS) - CurrentIGI = CurrentIGI-1; - } else { - CurrentIGI = RSSI_Lower; - } - - /* Lower bound checking */ - - /* RSSI Lower bound check */ - if ((pDM_Odm->RSSI_Min-10) > DM_DIG_MIN_NIC) - RSSI_Lower = (pDM_Odm->RSSI_Min-10); - else - RSSI_Lower = DM_DIG_MIN_NIC; - - /* Upper and Lower Bound checking */ - if (CurrentIGI > DM_DIG_MAX_NIC) - CurrentIGI = DM_DIG_MAX_NIC; - else if (CurrentIGI < RSSI_Lower) - CurrentIGI = RSSI_Lower; - - ODM_Write_DIG23a(pDM_Odm, CurrentIGI); -} - -void odm_DIG23aInit(struct dm_odm_t *pDM_Odm) -{ - struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable; - u32 val32; - - val32 = rtl8723au_read32(pDM_Odm->Adapter, ODM_REG_IGI_A_11N); - pDM_DigTable->CurIGValue = val32 & ODM_BIT_IGI_11N; - - pDM_DigTable->RssiLowThresh = DM_DIG_THRESH_LOW; - pDM_DigTable->RssiHighThresh = DM_DIG_THRESH_HIGH; - pDM_DigTable->FALowThresh = DM_FALSEALARM_THRESH_LOW; - pDM_DigTable->FAHighThresh = DM_FALSEALARM_THRESH_HIGH; - if (pDM_Odm->BoardType == ODM_BOARD_HIGHPWR) { - pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC; - pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC; - } else { - pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC; - pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC; - } - pDM_DigTable->BackoffVal = DM_DIG_BACKOFF_DEFAULT; - pDM_DigTable->BackoffVal_range_max = DM_DIG_BACKOFF_MAX; - pDM_DigTable->BackoffVal_range_min = DM_DIG_BACKOFF_MIN; - pDM_DigTable->PreCCK_CCAThres = 0xFF; - pDM_DigTable->CurCCK_CCAThres = 0x83; - pDM_DigTable->ForbiddenIGI = DM_DIG_MIN_NIC; - pDM_DigTable->LargeFAHit = 0; - pDM_DigTable->Recover_cnt = 0; - pDM_DigTable->DIG_Dynamic_MIN_0 = DM_DIG_MIN_NIC; - pDM_DigTable->DIG_Dynamic_MIN_1 = DM_DIG_MIN_NIC; - pDM_DigTable->bMediaConnect_0 = false; - pDM_DigTable->bMediaConnect_1 = false; -} - -void odm_DIG23a(struct rtw_adapter *adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(adapter); - struct dm_odm_t *pDM_Odm = &pHalData->odmpriv; - struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable; - struct false_alarm_stats *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt; - u8 DIG_Dynamic_MIN; - u8 DIG_MaxOfMin; - bool FirstConnect, FirstDisConnect; - u8 dm_dig_max, dm_dig_min; - u8 CurrentIGI = pDM_DigTable->CurIGValue; - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, - ("odm_DIG23a() ==>\n")); - if (adapter->mlmepriv.bScanInProcess) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, - ("odm_DIG23a() Return: In Scan Progress \n")); - return; - } - - DIG_Dynamic_MIN = pDM_DigTable->DIG_Dynamic_MIN_0; - FirstConnect = (pDM_Odm->bLinked) && (!pDM_DigTable->bMediaConnect_0); - FirstDisConnect = (!pDM_Odm->bLinked) && - (pDM_DigTable->bMediaConnect_0); - - /* 1 Boundary Decision */ - if ((pDM_Odm->SupportICType & ODM_RTL8723A) && - (pDM_Odm->BoardType == ODM_BOARD_HIGHPWR || pDM_Odm->ExtLNA)) { - dm_dig_max = DM_DIG_MAX_NIC_HP; - dm_dig_min = DM_DIG_MIN_NIC_HP; - DIG_MaxOfMin = DM_DIG_MAX_AP_HP; - } else { - dm_dig_max = DM_DIG_MAX_NIC; - dm_dig_min = DM_DIG_MIN_NIC; - DIG_MaxOfMin = DM_DIG_MAX_AP; - } - - if (pDM_Odm->bLinked) { - /* 2 8723A Series, offset need to be 10 */ - if (pDM_Odm->SupportICType == ODM_RTL8723A) { - /* 2 Upper Bound */ - if ((pDM_Odm->RSSI_Min + 10) > DM_DIG_MAX_NIC) - pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC; - else if ((pDM_Odm->RSSI_Min + 10) < DM_DIG_MIN_NIC) - pDM_DigTable->rx_gain_range_max = DM_DIG_MIN_NIC; - else - pDM_DigTable->rx_gain_range_max = pDM_Odm->RSSI_Min + 10; - - /* 2 If BT is Concurrent, need to set Lower Bound */ - DIG_Dynamic_MIN = DM_DIG_MIN_NIC; - } else { - /* 2 Modify DIG upper bound */ - if ((pDM_Odm->RSSI_Min + 20) > dm_dig_max) - pDM_DigTable->rx_gain_range_max = dm_dig_max; - else if ((pDM_Odm->RSSI_Min + 20) < dm_dig_min) - pDM_DigTable->rx_gain_range_max = dm_dig_min; - else - pDM_DigTable->rx_gain_range_max = pDM_Odm->RSSI_Min + 20; - - /* 2 Modify DIG lower bound */ - if (pDM_Odm->bOneEntryOnly) { - if (pDM_Odm->RSSI_Min < dm_dig_min) - DIG_Dynamic_MIN = dm_dig_min; - else if (pDM_Odm->RSSI_Min > DIG_MaxOfMin) - DIG_Dynamic_MIN = DIG_MaxOfMin; - else - DIG_Dynamic_MIN = pDM_Odm->RSSI_Min; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, - ("odm_DIG23a() : bOneEntryOnly = true, DIG_Dynamic_MIN = 0x%x\n", - DIG_Dynamic_MIN)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, - ("odm_DIG23a() : pDM_Odm->RSSI_Min =%d\n", - pDM_Odm->RSSI_Min)); - } 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, ("odm_DIG23a() : No Link\n")); - } - - /* 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(): Abnornally false alarm case. \n")); - - if (pDM_DigTable->LargeFAHit != 3) - pDM_DigTable->LargeFAHit++; - if (pDM_DigTable->ForbiddenIGI < CurrentIGI) { - pDM_DigTable->ForbiddenIGI = CurrentIGI; - pDM_DigTable->LargeFAHit = 1; - } - - if (pDM_DigTable->LargeFAHit >= 3) { - if ((pDM_DigTable->ForbiddenIGI+1) > pDM_DigTable->rx_gain_range_max) - pDM_DigTable->rx_gain_range_min = pDM_DigTable->rx_gain_range_max; - else - pDM_DigTable->rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 1); - pDM_DigTable->Recover_cnt = 3600; /* 3600 = 2hr */ - } - } else { - /* Recovery mechanism for IGI lower bound */ - if (pDM_DigTable->Recover_cnt != 0) { - pDM_DigTable->Recover_cnt--; - } else { - if (pDM_DigTable->LargeFAHit < 3) { - if ((pDM_DigTable->ForbiddenIGI - 1) < DIG_Dynamic_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, - ("odm_DIG23a(): Normal Case: At Lower Bound\n")); - } 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, - ("odm_DIG23a(): Normal Case: Approach Lower Bound\n")); - } - } else { - pDM_DigTable->LargeFAHit = 0; - } - } - } - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): pDM_DigTable->LargeFAHit =%d\n", 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, ("odm_DIG23a(): DIG AfterLink\n")); - 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; */ - else if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH1) - CurrentIGI = CurrentIGI + 2;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+1; */ - else if (pFalseAlmCnt->Cnt_all < DM_DIG_FA_TH0) - CurrentIGI = CurrentIGI - 2;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue-1; */ - } - } else { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): DIG BeforeLink\n")); - if (FirstDisConnect) { - CurrentIGI = pDM_DigTable->rx_gain_range_min; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): First DisConnect \n")); - } else { - /* 2012.03.30 LukeLee: enable DIG before link but with very high thresholds */ - if (pFalseAlmCnt->Cnt_all > 10000) - CurrentIGI = CurrentIGI + 2;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+2; */ - else if (pFalseAlmCnt->Cnt_all > 8000) - 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, ("odm_DIG23a(): England DIG \n")); - } - } - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): DIG End Adjust IGI\n")); - /* 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, ("odm_DIG23a(): rx_gain_range_max = 0x%x, rx_gain_range_min = 0x%x\n", - pDM_DigTable->rx_gain_range_max, pDM_DigTable->rx_gain_range_min)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): TotalFA =%d\n", pFalseAlmCnt->Cnt_all)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): CurIGValue = 0x%x\n", CurrentIGI)); - - /* 2 High power RSSI threshold */ - - ODM_Write_DIG23a(pDM_Odm, CurrentIGI);/* ODM_Write_DIG23a(pDM_Odm, pDM_DigTable->CurIGValue); */ - pDM_DigTable->bMediaConnect_0 = pDM_Odm->bLinked; - pDM_DigTable->DIG_Dynamic_MIN_0 = DIG_Dynamic_MIN; -} - -/* 3 ============================================================ */ -/* 3 FASLE ALARM CHECK */ -/* 3 ============================================================ */ - -void odm_FalseAlarmCounterStatistics23a(struct dm_odm_t *pDM_Odm) -{ - struct rtw_adapter *adapter = pDM_Odm->Adapter; - struct false_alarm_stats *FalseAlmCnt = &pDM_Odm->FalseAlmCnt; - u32 ret_value, val32; - - /* hold ofdm counter */ - /* hold page C counter */ - val32 = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_HOLDC_11N); - val32 |= BIT(31); - rtl8723au_write32(adapter, ODM_REG_OFDM_FA_HOLDC_11N, val32); - /* hold page D counter */ - val32 = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_RSTD_11N); - val32 |= BIT(31); - rtl8723au_write32(adapter, ODM_REG_OFDM_FA_RSTD_11N, val32); - ret_value = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_TYPE1_11N); - FalseAlmCnt->Cnt_Fast_Fsync = (ret_value&0xffff); - FalseAlmCnt->Cnt_SB_Search_fail = (ret_value & 0xffff0000)>>16; - ret_value = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_TYPE2_11N); - FalseAlmCnt->Cnt_OFDM_CCA = (ret_value&0xffff); - FalseAlmCnt->Cnt_Parity_Fail = (ret_value & 0xffff0000)>>16; - ret_value = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_TYPE3_11N); - FalseAlmCnt->Cnt_Rate_Illegal = (ret_value&0xffff); - FalseAlmCnt->Cnt_Crc8_fail = (ret_value & 0xffff0000)>>16; - ret_value = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_TYPE4_11N); - FalseAlmCnt->Cnt_Mcs_fail = (ret_value&0xffff); - - FalseAlmCnt->Cnt_Ofdm_fail = FalseAlmCnt->Cnt_Parity_Fail + - FalseAlmCnt->Cnt_Rate_Illegal + - FalseAlmCnt->Cnt_Crc8_fail + - FalseAlmCnt->Cnt_Mcs_fail + - FalseAlmCnt->Cnt_Fast_Fsync + - FalseAlmCnt->Cnt_SB_Search_fail; - /* hold cck counter */ - val32 = rtl8723au_read32(adapter, ODM_REG_CCK_FA_RST_11N); - val32 |= (BIT(12) | BIT(14)); - rtl8723au_write32(adapter, ODM_REG_CCK_FA_RST_11N, val32); - - ret_value = rtl8723au_read32(adapter, ODM_REG_CCK_FA_LSB_11N) & 0xff; - FalseAlmCnt->Cnt_Cck_fail = ret_value; - ret_value = rtl8723au_read32(adapter, ODM_REG_CCK_FA_MSB_11N) >> 16; - FalseAlmCnt->Cnt_Cck_fail += (ret_value & 0xff00); - - ret_value = rtl8723au_read32(adapter, ODM_REG_CCK_CCA_CNT_11N); - FalseAlmCnt->Cnt_CCK_CCA = - ((ret_value&0xFF)<<8) | ((ret_value&0xFF00)>>8); - - FalseAlmCnt->Cnt_all = (FalseAlmCnt->Cnt_Fast_Fsync + - FalseAlmCnt->Cnt_SB_Search_fail + - FalseAlmCnt->Cnt_Parity_Fail + - FalseAlmCnt->Cnt_Rate_Illegal + - FalseAlmCnt->Cnt_Crc8_fail + - FalseAlmCnt->Cnt_Mcs_fail + - FalseAlmCnt->Cnt_Cck_fail); - - FalseAlmCnt->Cnt_CCA_all = - FalseAlmCnt->Cnt_OFDM_CCA + FalseAlmCnt->Cnt_CCK_CCA; - - if (pDM_Odm->SupportICType >= ODM_RTL8723A) { - /* reset false alarm counter registers */ - val32 = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_RSTC_11N); - val32 |= BIT(31); - rtl8723au_write32(adapter, ODM_REG_OFDM_FA_RSTC_11N, val32); - val32 = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_RSTC_11N); - val32 &= ~BIT(31); - rtl8723au_write32(adapter, ODM_REG_OFDM_FA_RSTC_11N, val32); - - val32 = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_RSTD_11N); - val32 |= BIT(27); - rtl8723au_write32(adapter, ODM_REG_OFDM_FA_RSTD_11N, val32); - val32 = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_RSTD_11N); - val32 &= ~BIT(27); - rtl8723au_write32(adapter, ODM_REG_OFDM_FA_RSTD_11N, val32); - - /* update ofdm counter */ - /* update page C counter */ - val32 = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_HOLDC_11N); - val32 &= ~BIT(31); - rtl8723au_write32(adapter, ODM_REG_OFDM_FA_HOLDC_11N, val32); - - /* update page D counter */ - val32 = rtl8723au_read32(adapter, ODM_REG_OFDM_FA_RSTD_11N); - val32 &= ~BIT(31); - rtl8723au_write32(adapter, ODM_REG_OFDM_FA_RSTD_11N, val32); - - /* reset CCK CCA counter */ - val32 = rtl8723au_read32(adapter, ODM_REG_CCK_FA_RST_11N); - val32 &= ~(BIT(12) | BIT(13) | BIT(14) | BIT(15)); - rtl8723au_write32(adapter, ODM_REG_CCK_FA_RST_11N, val32); - - val32 = rtl8723au_read32(adapter, ODM_REG_CCK_FA_RST_11N); - val32 |= (BIT(13) | BIT(15)); - rtl8723au_write32(adapter, ODM_REG_CCK_FA_RST_11N, val32); - } - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, - ("Enter odm_FalseAlarmCounterStatistics23a\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_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 ============================================================ */ -/* 3 CCK Packet Detect Threshold */ -/* 3 ============================================================ */ - -void odm_CCKPacketDetectionThresh23a(struct dm_odm_t *pDM_Odm) -{ - struct false_alarm_stats *FalseAlmCnt = &pDM_Odm->FalseAlmCnt; - u8 CurCCK_CCAThres; - - if (pDM_Odm->ExtLNA) - return; - - if (pDM_Odm->bLinked) { - if (pDM_Odm->RSSI_Min > 25) { - CurCCK_CCAThres = 0xcd; - } else if (pDM_Odm->RSSI_Min <= 25 && pDM_Odm->RSSI_Min > 10) { - CurCCK_CCAThres = 0x83; - } else { - if (FalseAlmCnt->Cnt_Cck_fail > 1000) - CurCCK_CCAThres = 0x83; - else - CurCCK_CCAThres = 0x40; - } - } else { - if (FalseAlmCnt->Cnt_Cck_fail > 1000) - CurCCK_CCAThres = 0x83; - else - CurCCK_CCAThres = 0x40; - } - - ODM_Write_CCK_CCA_Thres23a(pDM_Odm, CurCCK_CCAThres); -} - -void ODM_Write_CCK_CCA_Thres23a(struct dm_odm_t *pDM_Odm, u8 CurCCK_CCAThres) -{ - struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable; - - if (pDM_DigTable->CurCCK_CCAThres != CurCCK_CCAThres) - rtl8723au_write8(pDM_Odm->Adapter, ODM_REG(CCK_CCA, pDM_Odm), - CurCCK_CCAThres); - pDM_DigTable->PreCCK_CCAThres = pDM_DigTable->CurCCK_CCAThres; - pDM_DigTable->CurCCK_CCAThres = CurCCK_CCAThres; -} - -/* 3 ============================================================ */ -/* 3 BB Power Save */ -/* 3 ============================================================ */ -void odm23a_DynBBPSInit(struct dm_odm_t *pDM_Odm) -{ - struct dynamic_pwr_sav *pDM_PSTable = &pDM_Odm->DM_PSTable; - - pDM_PSTable->PreCCAState = CCA_MAX; - pDM_PSTable->CurCCAState = CCA_MAX; - pDM_PSTable->PreRFState = RF_MAX; - pDM_PSTable->CurRFState = RF_MAX; - pDM_PSTable->Rssi_val_min = 0; - pDM_PSTable->initialize = 0; -} - - -void ODM_RF_Saving23a(struct dm_odm_t *pDM_Odm, u8 bForceInNormal) -{ - struct dynamic_pwr_sav *pDM_PSTable = &pDM_Odm->DM_PSTable; - struct rtw_adapter *adapter = pDM_Odm->Adapter; - u32 val32; - u8 Rssi_Up_bound = 30; - u8 Rssi_Low_bound = 25; - if (pDM_PSTable->initialize == 0) { - - pDM_PSTable->Reg874 = - rtl8723au_read32(adapter, 0x874) & 0x1CC000; - pDM_PSTable->RegC70 = - rtl8723au_read32(adapter, 0xc70) & BIT(3); - pDM_PSTable->Reg85C = - rtl8723au_read32(adapter, 0x85c) & 0xFF000000; - pDM_PSTable->RegA74 = rtl8723au_read32(adapter, 0xa74) & 0xF000; - pDM_PSTable->initialize = 1; - } - - if (!bForceInNormal) { - if (pDM_Odm->RSSI_Min != 0xFF) { - if (pDM_PSTable->PreRFState == RF_Normal) { - if (pDM_Odm->RSSI_Min >= Rssi_Up_bound) - pDM_PSTable->CurRFState = RF_Save; - else - pDM_PSTable->CurRFState = RF_Normal; - } else { - if (pDM_Odm->RSSI_Min <= Rssi_Low_bound) - pDM_PSTable->CurRFState = RF_Normal; - else - pDM_PSTable->CurRFState = RF_Save; - } - } else { - pDM_PSTable->CurRFState = RF_MAX; - } - } else { - pDM_PSTable->CurRFState = RF_Normal; - } - - if (pDM_PSTable->PreRFState != pDM_PSTable->CurRFState) { - if (pDM_PSTable->CurRFState == RF_Save) { - /* <tynli_note> 8723 RSSI report will be wrong. - * Set 0x874[5]= 1 when enter BB power saving mode. */ - /* Suggested by SD3 Yu-Nan. 2011.01.20. */ - /* Reg874[5]= 1b'1 */ - if (pDM_Odm->SupportICType == ODM_RTL8723A) { - val32 = rtl8723au_read32(adapter, 0x874); - val32 |= BIT(5); - rtl8723au_write32(adapter, 0x874, val32); - } - /* Reg874[20:18]= 3'b010 */ - val32 = rtl8723au_read32(adapter, 0x874); - val32 &= ~(BIT(18) | BIT(20)); - val32 |= BIT(19); - rtl8723au_write32(adapter, 0x874, val32); - /* RegC70[3]= 1'b0 */ - val32 = rtl8723au_read32(adapter, 0xc70); - val32 &= ~BIT(3); - rtl8723au_write32(adapter, 0xc70, val32); - /* Reg85C[31:24]= 0x63 */ - val32 = rtl8723au_read32(adapter, 0x85c); - val32 &= 0x00ffffff; - val32 |= 0x63000000; - rtl8723au_write32(adapter, 0x85c, val32); - /* Reg874[15:14]= 2'b10 */ - val32 = rtl8723au_read32(adapter, 0x874); - val32 &= ~BIT(14); - val32 |= BIT(15); - rtl8723au_write32(adapter, 0x874, val32); - /* RegA75[7:4]= 0x3 */ - val32 = rtl8723au_read32(adapter, 0xa74); - val32 &= ~(BIT(14) | BIT(15)); - val32 |= (BIT(12) | BIT(13)); - rtl8723au_write32(adapter, 0xa74, val32); - /* Reg818[28]= 1'b0 */ - val32 = rtl8723au_read32(adapter, 0x818); - val32 &= ~BIT(28); - rtl8723au_write32(adapter, 0x818, val32); - /* Reg818[28]= 1'b1 */ - val32 = rtl8723au_read32(adapter, 0x818); - val32 |= BIT(28); - rtl8723au_write32(adapter, 0x818, val32); - } else { - val32 = rtl8723au_read32(adapter, 0x874); - val32 |= pDM_PSTable->Reg874; - rtl8723au_write32(adapter, 0x874, val32); - - val32 = rtl8723au_read32(adapter, 0xc70); - val32 |= pDM_PSTable->RegC70; - rtl8723au_write32(adapter, 0xc70, val32); - - val32 = rtl8723au_read32(adapter, 0x85c); - val32 |= pDM_PSTable->Reg85C; - rtl8723au_write32(adapter, 0x85c, val32); - - val32 = rtl8723au_read32(adapter, 0xa74); - val32 |= pDM_PSTable->RegA74; - rtl8723au_write32(adapter, 0xa74, val32); - - val32 = rtl8723au_read32(adapter, 0x818); - val32 &= ~BIT(28); - rtl8723au_write32(adapter, 0x818, val32); - - /* Reg874[5]= 1b'0 */ - if (pDM_Odm->SupportICType == ODM_RTL8723A) { - val32 = rtl8723au_read32(adapter, 0x874); - val32 &= ~BIT(5); - rtl8723au_write32(adapter, 0x874, val32); - } - } - pDM_PSTable->PreRFState = pDM_PSTable->CurRFState; - } -} - -/* 3 ============================================================ */ -/* 3 RATR MASK */ -/* 3 ============================================================ */ -/* 3 ============================================================ */ -/* 3 Rate Adaptive */ -/* 3 ============================================================ */ - -void odm_RateAdaptiveMaskInit23a(struct dm_odm_t *pDM_Odm) -{ - struct odm_rate_adapt *pOdmRA = &pDM_Odm->RateAdaptive; - - pOdmRA->Type = DM_Type_ByDriver; - - pOdmRA->RATRState = DM_RATR_STA_INIT; - pOdmRA->HighRSSIThresh = 50; - pOdmRA->LowRSSIThresh = 20; -} - -u32 ODM_Get_Rate_Bitmap23a(struct hal_data_8723a *pHalData, u32 macid, - u32 ra_mask, u8 rssi_level) -{ - struct dm_odm_t *pDM_Odm = &pHalData->odmpriv; - struct sta_info *pEntry; - u32 rate_bitmap = 0x0fffffff; - u8 WirelessMode; - - pEntry = pDM_Odm->pODM_StaInfo[macid]; - if (!pEntry) - return ra_mask; - - WirelessMode = pEntry->wireless_mode; - - switch (WirelessMode) { - case ODM_WM_B: - if (ra_mask & 0x0000000c) /* 11M or 5.5M enable */ - rate_bitmap = 0x0000000d; - else - rate_bitmap = 0x0000000f; - break; - case (ODM_WM_A|ODM_WM_G): - if (rssi_level == DM_RATR_STA_HIGH) - rate_bitmap = 0x00000f00; - else - rate_bitmap = 0x00000ff0; - break; - case (ODM_WM_B|ODM_WM_G): - if (rssi_level == DM_RATR_STA_HIGH) - rate_bitmap = 0x00000f00; - else if (rssi_level == DM_RATR_STA_MIDDLE) - rate_bitmap = 0x00000ff0; - else - rate_bitmap = 0x00000ff5; - break; - case (ODM_WM_B|ODM_WM_G|ODM_WM_N24G): - case (ODM_WM_A|ODM_WM_B|ODM_WM_G|ODM_WM_N24G): - if (pHalData->rf_type == RF_1T2R || - pHalData->rf_type == RF_1T1R) { - if (rssi_level == DM_RATR_STA_HIGH) { - rate_bitmap = 0x000f0000; - } else if (rssi_level == DM_RATR_STA_MIDDLE) { - rate_bitmap = 0x000ff000; - } else { - if (pHalData->CurrentChannelBW == - HT_CHANNEL_WIDTH_40) - rate_bitmap = 0x000ff015; - else - rate_bitmap = 0x000ff005; - } - } else { - if (rssi_level == DM_RATR_STA_HIGH) { - rate_bitmap = 0x0f8f0000; - } else if (rssi_level == DM_RATR_STA_MIDDLE) { - rate_bitmap = 0x0f8ff000; - } else { - if (pHalData->CurrentChannelBW == - HT_CHANNEL_WIDTH_40) - rate_bitmap = 0x0f8ff015; - else - rate_bitmap = 0x0f8ff005; - } - } - break; - default: - /* case WIRELESS_11_24N: */ - /* case WIRELESS_11_5N: */ - if (pHalData->rf_type == RF_1T2R) - rate_bitmap = 0x000fffff; - else - rate_bitmap = 0x0fffffff; - 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; -} - -/*----------------------------------------------------------------------------- - * Function: odm_RefreshRateAdaptiveMask() - * - * Overview: Update rate table mask according to rssi - * - * Input: NONE - * - * Output: NONE - * - * Return: NONE - * - * Revised History: - *When Who Remark - *05/27/2009 hpfan Create Version 0. - * - *---------------------------------------------------------------------------*/ -static void odm_RefreshRateAdaptiveMask(struct dm_odm_t *pDM_Odm) -{ - struct rtw_adapter *pAdapter = pDM_Odm->Adapter; - u32 smoothed; - u8 i; - - if (pAdapter->bDriverStopped) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_TRACE, - ("<---- %s: driver is going to unload\n", - __func__)); - return; - } - - for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) { - struct sta_info *pstat = pDM_Odm->pODM_StaInfo[i]; - if (pstat) { - smoothed = pstat->rssi_stat.UndecoratedSmoothedPWDB; - if (ODM_RAStateCheck23a(pDM_Odm, smoothed, false, - &pstat->rssi_level)) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, - ODM_DBG_LOUD, - ("RSSI:%d, RSSI_LEVEL:%d\n", - smoothed, - pstat->rssi_level)); - rtw_hal_update_ra_mask23a(pstat, - pstat->rssi_level); - } - } - } -} - -/* Return Value: bool */ -/* - true: RATRState is changed. */ -bool ODM_RAStateCheck23a(struct dm_odm_t *pDM_Odm, s32 RSSI, bool bForceUpdate, - u8 *pRATRState) -{ - struct odm_rate_adapt *pRA = &pDM_Odm->RateAdaptive; - const u8 GoUpGap = 5; - u8 HighRSSIThreshForRA = pRA->HighRSSIThresh; - u8 LowRSSIThreshForRA = pRA->LowRSSIThresh; - u8 RATRState; - - /* Threshold Adjustment: */ - /* when RSSI state trends to go up one or two levels, make sure RSSI is high enough. */ - /* Here GoUpGap is added to solve the boundary's level alternation issue. */ - switch (*pRATRState) { - case DM_RATR_STA_INIT: - case DM_RATR_STA_HIGH: - break; - case DM_RATR_STA_MIDDLE: - HighRSSIThreshForRA += GoUpGap; - break; - case DM_RATR_STA_LOW: - HighRSSIThreshForRA += GoUpGap; - LowRSSIThreshForRA += GoUpGap; - break; - default: - ODM_RT_ASSERT(pDM_Odm, false, ("wrong rssi level setting %d !", - *pRATRState)); - break; - } - - /* Decide RATRState by RSSI. */ - if (RSSI > HighRSSIThreshForRA) - RATRState = DM_RATR_STA_HIGH; - else if (RSSI > LowRSSIThreshForRA) - RATRState = DM_RATR_STA_MIDDLE; - else - 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; - } - return false; -} - -/* 3 ============================================================ */ -/* 3 Dynamic Tx Power */ -/* 3 ============================================================ */ - -void odm_DynamicTxPower23aInit(struct dm_odm_t *pDM_Odm) -{ - struct rtw_adapter *Adapter = pDM_Odm->Adapter; - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - - /* - * This is never changed, so we should be able to clean up the - * code checking for different values in rtl8723a_rf6052.c - */ - pdmpriv->DynamicTxHighPowerLvl = TxHighPwrLevel_Normal; -} - -static void -FindMinimumRSSI(struct rtw_adapter *pAdapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - struct dm_odm_t *pDM_Odm = &pHalData->odmpriv; - - /* 1 1.Determine the minimum RSSI */ - - if (!pDM_Odm->bLinked && !pdmpriv->EntryMinUndecoratedSmoothedPWDB) - pdmpriv->MinUndecoratedPWDBForDM = 0; - else - pdmpriv->MinUndecoratedPWDBForDM = - pdmpriv->EntryMinUndecoratedSmoothedPWDB; -} - -static void odm_RSSIMonitorCheck(struct dm_odm_t *pDM_Odm) -{ - struct rtw_adapter *Adapter = pDM_Odm->Adapter; - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - int i; - int MaxDB = 0, MinDB = 0xff; - u8 sta_cnt = 0; - u32 tmpdb; - u32 PWDB_rssi[NUM_STA] = {0};/* 0~15]:MACID, [16~31]:PWDB_rssi */ - struct sta_info *psta; - - if (!pDM_Odm->bLinked) - return; - - for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) { - psta = pDM_Odm->pODM_StaInfo[i]; - if (psta) { - if (psta->rssi_stat.UndecoratedSmoothedPWDB < MinDB) - MinDB = psta->rssi_stat.UndecoratedSmoothedPWDB; - - if (psta->rssi_stat.UndecoratedSmoothedPWDB > MaxDB) - MaxDB = psta->rssi_stat.UndecoratedSmoothedPWDB; - - if (psta->rssi_stat.UndecoratedSmoothedPWDB != -1) { - tmpdb = psta->rssi_stat.UndecoratedSmoothedPWDB; - PWDB_rssi[sta_cnt++] = psta->mac_id | - (tmpdb << 16); - } - } - } - - for (i = 0; i < sta_cnt; i++) { - if (PWDB_rssi[i] != (0)) - rtl8723a_set_rssi_cmd(Adapter, PWDB_rssi[i]); - } - - pdmpriv->EntryMaxUndecoratedSmoothedPWDB = MaxDB; - - if (MinDB != 0xff) /* If associated entry is found */ - pdmpriv->EntryMinUndecoratedSmoothedPWDB = MinDB; - else - pdmpriv->EntryMinUndecoratedSmoothedPWDB = 0; - - FindMinimumRSSI(Adapter);/* get pdmpriv->MinUndecoratedPWDBForDM */ - - ODM_CmnInfoUpdate23a(&pHalData->odmpriv, ODM_CMNINFO_RSSI_MIN, - pdmpriv->MinUndecoratedPWDBForDM); -} - -/* endif */ -/* 3 ============================================================ */ -/* 3 Tx Power Tracking */ -/* 3 ============================================================ */ - -static void odm_TXPowerTrackingInit(struct dm_odm_t *pDM_Odm) -{ - struct rtw_adapter *Adapter = pDM_Odm->Adapter; - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - - pdmpriv->bTXPowerTracking = true; - pdmpriv->TXPowercount = 0; - pdmpriv->bTXPowerTrackingInit = false; - pdmpriv->TxPowerTrackControl = true; - MSG_8723A("pdmpriv->TxPowerTrackControl = %d\n", - pdmpriv->TxPowerTrackControl); - - pDM_Odm->RFCalibrateInfo.TxPowerTrackControl = true; -} - -/* EDCA Turbo */ -static void ODM_EdcaTurboInit23a(struct dm_odm_t *pDM_Odm) -{ - struct rtw_adapter *Adapter = pDM_Odm->Adapter; - - pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = false; - Adapter->recvpriv.bIsAnyNonBEPkts = false; - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, - ("Orginial VO PARAM: 0x%x\n", - rtl8723au_read32(Adapter, ODM_EDCA_VO_PARAM))); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, - ("Orginial VI PARAM: 0x%x\n", - rtl8723au_read32(Adapter, ODM_EDCA_VI_PARAM))); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, - ("Orginial BE PARAM: 0x%x\n", - rtl8723au_read32(Adapter, ODM_EDCA_BE_PARAM))); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, - ("Orginial BK PARAM: 0x%x\n", - rtl8723au_read32(Adapter, ODM_EDCA_BK_PARAM))); -} - -static void odm_EdcaTurboCheck23a(struct dm_odm_t *pDM_Odm) -{ - struct rtw_adapter *Adapter = pDM_Odm->Adapter; - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct xmit_priv *pxmitpriv = &Adapter->xmitpriv; - struct recv_priv *precvpriv = &Adapter->recvpriv; - struct registry_priv *pregpriv = &Adapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - u32 trafficIndex; - u32 edca_param; - u64 cur_tx_bytes; - u64 cur_rx_bytes; - - /* For AP/ADSL use struct rtl8723a_priv * */ - /* For CE/NIC use struct rtw_adapter * */ - - /* - * 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. - */ - - if ((pregpriv->wifi_spec == 1))/* (pmlmeinfo->HT_enable == 0)) */ - goto dm_CheckEdcaTurbo_EXIT; - - if (pmlmeinfo->assoc_AP_vendor >= HT_IOT_PEER_MAX) - goto dm_CheckEdcaTurbo_EXIT; - - if (rtl8723a_BT_disable_EDCA_turbo(Adapter)) - goto dm_CheckEdcaTurbo_EXIT; - - /* Check if the status needs to be changed. */ - if (!precvpriv->bIsAnyNonBEPkts) { - cur_tx_bytes = pxmitpriv->tx_bytes - pxmitpriv->last_tx_bytes; - cur_rx_bytes = precvpriv->rx_bytes - precvpriv->last_rx_bytes; - - /* traffic, TX or RX */ - if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_RALINK) || - (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_ATHEROS)) { - if (cur_tx_bytes > (cur_rx_bytes << 2)) { - /* Uplink TP is present. */ - trafficIndex = UP_LINK; - } else { /* Balance TP is present. */ - trafficIndex = DOWN_LINK; - } - } else { - if (cur_rx_bytes > (cur_tx_bytes << 2)) { - /* Downlink TP is present. */ - trafficIndex = DOWN_LINK; - } else { /* Balance TP is present. */ - trafficIndex = UP_LINK; - } - } - - if ((pDM_Odm->DM_EDCA_Table.prv_traffic_idx != trafficIndex) || - (!pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA)) { - if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_CISCO) && - (pmlmeext->cur_wireless_mode & WIRELESS_11_24N)) - edca_param = EDCAParam[pmlmeinfo->assoc_AP_vendor][trafficIndex]; - else - edca_param = EDCAParam[HT_IOT_PEER_UNKNOWN][trafficIndex]; - rtl8723au_write32(Adapter, REG_EDCA_BE_PARAM, - edca_param); - - pDM_Odm->DM_EDCA_Table.prv_traffic_idx = trafficIndex; - } - - pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = true; - } else { - /* Turn Off EDCA turbo here. */ - /* Restore original EDCA according to the declaration of AP. */ - if (pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA) { - rtl8723au_write32(Adapter, REG_EDCA_BE_PARAM, - pHalData->AcParam_BE); - pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = false; - } - } - -dm_CheckEdcaTurbo_EXIT: - /* Set variables for next time. */ - precvpriv->bIsAnyNonBEPkts = false; - pxmitpriv->last_tx_bytes = pxmitpriv->tx_bytes; - precvpriv->last_rx_bytes = precvpriv->rx_bytes; -} - -u32 GetPSDData(struct dm_odm_t *pDM_Odm, unsigned int point, - u8 initial_gain_psd) -{ - struct rtw_adapter *adapter = pDM_Odm->Adapter; - u32 psd_report, val32; - - /* Set DCO frequency index, offset = (40MHz/SamplePts)*point */ - val32 = rtl8723au_read32(adapter, 0x808); - val32 &= ~0x3ff; - val32 |= (point & 0x3ff); - rtl8723au_write32(adapter, 0x808, val32); - - /* Start PSD calculation, Reg808[22]= 0->1 */ - val32 = rtl8723au_read32(adapter, 0x808); - val32 |= BIT(22); - rtl8723au_write32(adapter, 0x808, val32); - /* Need to wait for HW PSD report */ - udelay(30); - val32 = rtl8723au_read32(adapter, 0x808); - val32 &= ~BIT(22); - rtl8723au_write32(adapter, 0x808, val32); - /* Read PSD report, Reg8B4[15:0] */ - psd_report = rtl8723au_read32(adapter, 0x8B4) & 0x0000FFFF; - - psd_report = (u32)(ConvertTo_dB23a(psd_report)) + - (u32)(initial_gain_psd-0x1c); - - return psd_report; -} - -u32 ConvertTo_dB23a(u32 Value) -{ - u8 i; - u8 j; - u32 dB; - - Value = Value & 0xFFFF; - - for (i = 0; i < 8; i++) { - if (Value <= dB_Invert_Table[i][11]) - break; - } - - if (i >= 8) - return 96; /* maximum 96 dB */ - - for (j = 0; j < 12; j++) { - if (Value <= dB_Invert_Table[i][j]) - break; - } - - dB = i*12 + j + 1; - - return dB; -} - -/* */ -/* Description: */ -/* Set Single/Dual Antenna default setting for products that do not - * do detection in advance. */ -/* */ -/* Added by Joseph, 2012.03.22 */ -/* */ -void ODM_SingleDualAntennaDefaultSetting(struct dm_odm_t *pDM_Odm) -{ - struct sw_ant_sw *pDM_SWAT_Table = &pDM_Odm->DM_SWAT_Table; - - pDM_SWAT_Table->ANTA_ON = true; - pDM_SWAT_Table->ANTB_ON = true; -} - -/* 2 8723A ANT DETECT */ - -static void odm_PHY_SaveAFERegisters(struct dm_odm_t *pDM_Odm, u32 *AFEReg, - u32 *AFEBackup, u32 RegisterNum) -{ - u32 i; - - for (i = 0 ; i < RegisterNum ; i++) - AFEBackup[i] = rtl8723au_read32(pDM_Odm->Adapter, AFEReg[i]); -} - -static void odm_PHY_ReloadAFERegisters(struct dm_odm_t *pDM_Odm, u32 *AFEReg, - u32 *AFEBackup, u32 RegiesterNum) -{ - u32 i; - - for (i = 0 ; i < RegiesterNum; i++) - rtl8723au_write32(pDM_Odm->Adapter, AFEReg[i], AFEBackup[i]); -} - -/* 2 8723A ANT DETECT */ -/* Description: */ -/* Implement IQK single tone for RF DPK loopback and BB PSD scanning. */ -/* This function is cooperated with BB team Neil. */ -bool ODM_SingleDualAntennaDetection(struct dm_odm_t *pDM_Odm, u8 mode) -{ - struct sw_ant_sw *pDM_SWAT_Table = &pDM_Odm->DM_SWAT_Table; - struct rtw_adapter *adapter = pDM_Odm->Adapter; - u32 CurrentChannel, RfLoopReg; - u8 n; - u32 Reg88c, Regc08, Reg874, Regc50, val32; - u8 initial_gain = 0x5a; - u32 PSD_report_tmp; - u32 AntA_report = 0x0, AntB_report = 0x0, AntO_report = 0x0; - bool bResult = true; - u32 AFE_Backup[16]; - u32 AFE_REG_8723A[16] = { - rRx_Wait_CCA, rTx_CCK_RFON, - rTx_CCK_BBON, rTx_OFDM_RFON, - rTx_OFDM_BBON, rTx_To_Rx, - rTx_To_Tx, rRx_CCK, - rRx_OFDM, rRx_Wait_RIFS, - rRx_TO_Rx, rStandby, - rSleep, rPMPD_ANAEN, - rFPGA0_XCD_SwitchControl, rBlue_Tooth}; - - if (!(pDM_Odm->SupportICType & ODM_RTL8723A)) - return bResult; - - if (!(pDM_Odm->SupportAbility&ODM_BB_ANT_DIV)) - return bResult; - /* 1 Backup Current RF/BB Settings */ - - CurrentChannel = ODM_GetRFReg(pDM_Odm, RF_PATH_A, ODM_CHANNEL, - bRFRegOffsetMask); - RfLoopReg = ODM_GetRFReg(pDM_Odm, RF_PATH_A, 0x00, bRFRegOffsetMask); - /* change to Antenna A */ - val32 = rtl8723au_read32(adapter, rFPGA0_XA_RFInterfaceOE); - val32 &= ~0x300; - val32 |= 0x100; /* Enable antenna A */ - rtl8723au_write32(adapter, rFPGA0_XA_RFInterfaceOE, val32); - - /* Step 1: USE IQK to transmitter single tone */ - - udelay(10); - - /* Store A Path Register 88c, c08, 874, c50 */ - Reg88c = rtl8723au_read32(adapter, rFPGA0_AnalogParameter4); - Regc08 = rtl8723au_read32(adapter, rOFDM0_TRMuxPar); - Reg874 = rtl8723au_read32(adapter, rFPGA0_XCD_RFInterfaceSW); - Regc50 = rtl8723au_read32(adapter, rOFDM0_XAAGCCore1); - - /* Store AFE Registers */ - odm_PHY_SaveAFERegisters(pDM_Odm, AFE_REG_8723A, AFE_Backup, 16); - - /* Set PSD 128 pts */ - val32 = rtl8723au_read32(adapter, rFPGA0_PSDFunction); - val32 &= ~(BIT(14) | BIT(15)); - rtl8723au_write32(adapter, rFPGA0_PSDFunction, val32); - - /* To SET CH1 to do */ - ODM_SetRFReg(pDM_Odm, RF_PATH_A, ODM_CHANNEL, bRFRegOffsetMask, 0x01); - - /* AFE all on step */ - rtl8723au_write32(adapter, rRx_Wait_CCA, 0x6FDB25A4); - rtl8723au_write32(adapter, rTx_CCK_RFON, 0x6FDB25A4); - rtl8723au_write32(adapter, rTx_CCK_BBON, 0x6FDB25A4); - rtl8723au_write32(adapter, rTx_OFDM_RFON, 0x6FDB25A4); - rtl8723au_write32(adapter, rTx_OFDM_BBON, 0x6FDB25A4); - rtl8723au_write32(adapter, rTx_To_Rx, 0x6FDB25A4); - rtl8723au_write32(adapter, rTx_To_Tx, 0x6FDB25A4); - rtl8723au_write32(adapter, rRx_CCK, 0x6FDB25A4); - rtl8723au_write32(adapter, rRx_OFDM, 0x6FDB25A4); - rtl8723au_write32(adapter, rRx_Wait_RIFS, 0x6FDB25A4); - rtl8723au_write32(adapter, rRx_TO_Rx, 0x6FDB25A4); - rtl8723au_write32(adapter, rStandby, 0x6FDB25A4); - rtl8723au_write32(adapter, rSleep, 0x6FDB25A4); - rtl8723au_write32(adapter, rPMPD_ANAEN, 0x6FDB25A4); - rtl8723au_write32(adapter, rFPGA0_XCD_SwitchControl, 0x6FDB25A4); - rtl8723au_write32(adapter, rBlue_Tooth, 0x6FDB25A4); - - /* 3 wire Disable */ - rtl8723au_write32(adapter, rFPGA0_AnalogParameter4, 0xCCF000C0); - - /* BB IQK Setting */ - rtl8723au_write32(adapter, rOFDM0_TRMuxPar, 0x000800E4); - rtl8723au_write32(adapter, rFPGA0_XCD_RFInterfaceSW, 0x22208000); - - /* IQK setting tone@ 4.34Mhz */ - rtl8723au_write32(adapter, rTx_IQK_Tone_A, 0x10008C1C); - rtl8723au_write32(adapter, rTx_IQK, 0x01007c00); - - /* Page B init */ - rtl8723au_write32(adapter, rConfig_AntA, 0x00080000); - rtl8723au_write32(adapter, rConfig_AntA, 0x0f600000); - rtl8723au_write32(adapter, rRx_IQK, 0x01004800); - rtl8723au_write32(adapter, rRx_IQK_Tone_A, 0x10008c1f); - rtl8723au_write32(adapter, rTx_IQK_PI_A, 0x82150008); - rtl8723au_write32(adapter, rRx_IQK_PI_A, 0x28150008); - rtl8723au_write32(adapter, rIQK_AGC_Rsp, 0x001028d0); - - /* RF loop Setting */ - ODM_SetRFReg(pDM_Odm, RF_PATH_A, 0x0, 0xFFFFF, 0x50008); - - /* IQK Single tone start */ - rtl8723au_write32(adapter, rFPGA0_IQK, 0x80800000); - rtl8723au_write32(adapter, rIQK_AGC_Pts, 0xf8000000); - udelay(1000); - PSD_report_tmp = 0x0; - - for (n = 0; n < 2; n++) { - PSD_report_tmp = GetPSDData(pDM_Odm, 14, initial_gain); - if (PSD_report_tmp > AntA_report) - AntA_report = PSD_report_tmp; - } - - PSD_report_tmp = 0x0; - - val32 = rtl8723au_read32(adapter, rFPGA0_XA_RFInterfaceOE); - val32 &= ~0x300; - val32 |= 0x200; /* Enable antenna B */ - rtl8723au_write32(adapter, rFPGA0_XA_RFInterfaceOE, val32); - udelay(10); - - for (n = 0; n < 2; n++) { - PSD_report_tmp = GetPSDData(pDM_Odm, 14, initial_gain); - if (PSD_report_tmp > AntB_report) - AntB_report = PSD_report_tmp; - } - - /* change to open case */ - /* change to Ant A and B all open case */ - val32 = rtl8723au_read32(adapter, rFPGA0_XA_RFInterfaceOE); - val32 &= ~0x300; - rtl8723au_write32(adapter, rFPGA0_XA_RFInterfaceOE, val32); - udelay(10); - - for (n = 0; n < 2; n++) { - PSD_report_tmp = GetPSDData(pDM_Odm, 14, initial_gain); - if (PSD_report_tmp > AntO_report) - AntO_report = PSD_report_tmp; - } - - /* Close IQK Single Tone function */ - rtl8723au_write32(adapter, rFPGA0_IQK, 0x00000000); - PSD_report_tmp = 0x0; - - /* 1 Return to antanna A */ - val32 = rtl8723au_read32(adapter, rFPGA0_XA_RFInterfaceOE); - val32 &= ~0x300; - val32 |= 0x100; /* Enable antenna A */ - rtl8723au_write32(adapter, rFPGA0_XA_RFInterfaceOE, val32); - rtl8723au_write32(adapter, rFPGA0_AnalogParameter4, Reg88c); - rtl8723au_write32(adapter, rOFDM0_TRMuxPar, Regc08); - rtl8723au_write32(adapter, rFPGA0_XCD_RFInterfaceSW, Reg874); - val32 = rtl8723au_read32(adapter, rOFDM0_XAAGCCore1); - val32 &= ~0x7f; - val32 |= 0x40; - rtl8723au_write32(adapter, rOFDM0_XAAGCCore1, val32); - - rtl8723au_write32(adapter, rOFDM0_XAAGCCore1, Regc50); - ODM_SetRFReg(pDM_Odm, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask, - CurrentChannel); - ODM_SetRFReg(pDM_Odm, RF_PATH_A, 0x00, bRFRegOffsetMask, RfLoopReg); - - /* Reload AFE Registers */ - odm_PHY_ReloadAFERegisters(pDM_Odm, AFE_REG_8723A, AFE_Backup, 16); - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, - ("psd_report_A[%d]= %d \n", 2416, AntA_report)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, - ("psd_report_B[%d]= %d \n", 2416, AntB_report)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, - ("psd_report_O[%d]= %d \n", 2416, AntO_report)); - - /* 2 Test Ant B based on Ant A is ON */ - if (mode == ANTTESTB) { - if (AntA_report >= 100) { - if (AntB_report > (AntA_report+1)) { - pDM_SWAT_Table->ANTB_ON = false; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("ODM_SingleDualAntennaDetection(): Single Antenna A\n")); - } else { - pDM_SWAT_Table->ANTB_ON = true; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("ODM_SingleDualAntennaDetection(): Dual Antenna is A and B\n")); - } - } else { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("ODM_SingleDualAntennaDetection(): Need to check again\n")); - pDM_SWAT_Table->ANTB_ON = false; /* Set Antenna B off as default */ - bResult = false; - } - } else if (mode == ANTTESTALL) { - /* 2 Test Ant A and B based on DPDT Open */ - if ((AntO_report >= 100) & (AntO_report < 118)) { - if (AntA_report > (AntO_report+1)) { - pDM_SWAT_Table->ANTA_ON = false; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, - ODM_DBG_LOUD, ("Ant A is OFF")); - } else { - pDM_SWAT_Table->ANTA_ON = true; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, - ODM_DBG_LOUD, ("Ant A is ON")); - } - - if (AntB_report > (AntO_report+2)) { - pDM_SWAT_Table->ANTB_ON = false; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, - ODM_DBG_LOUD, ("Ant B is OFF")); - } else { - pDM_SWAT_Table->ANTB_ON = true; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, - ODM_DBG_LOUD, ("Ant B is ON")); - } - } - } else { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, - ("ODM_SingleDualAntennaDetection(): Need to check again\n")); - /* Set Antenna A on as default */ - pDM_SWAT_Table->ANTA_ON = true; - /* Set Antenna B off as default */ - pDM_SWAT_Table->ANTB_ON = false; - bResult = false; - } - - return bResult; -} diff --git a/drivers/staging/rtl8723au/hal/odm_HWConfig.c b/drivers/staging/rtl8723au/hal/odm_HWConfig.c deleted file mode 100644 index 0562f61..0000000 --- a/drivers/staging/rtl8723au/hal/odm_HWConfig.c +++ /dev/null @@ -1,396 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ - -/* */ -/* include files */ -/* */ - -#include "odm_precomp.h" - -static u8 odm_QueryRxPwrPercentage(s8 AntPower) -{ - if ((AntPower <= -100) || (AntPower >= 20)) - return 0; - else if (AntPower >= 0) - return 100; - else - return 100 + AntPower; -} - -static s32 odm_SignalScaleMapping_92CSeries(struct dm_odm_t *pDM_Odm, s32 CurrSig) -{ - s32 RetSig = 0; - - if (CurrSig >= 51 && CurrSig <= 100) - RetSig = 100; - else if (CurrSig >= 41 && CurrSig <= 50) - RetSig = 80 + ((CurrSig - 40)*2); - else if (CurrSig >= 31 && CurrSig <= 40) - RetSig = 66 + (CurrSig - 30); - else if (CurrSig >= 21 && CurrSig <= 30) - RetSig = 54 + (CurrSig - 20); - else if (CurrSig >= 10 && CurrSig <= 20) - RetSig = 42 + (((CurrSig - 10) * 2) / 3); - else if (CurrSig >= 5 && CurrSig <= 9) - RetSig = 22 + (((CurrSig - 5) * 3) / 2); - else if (CurrSig >= 1 && CurrSig <= 4) - RetSig = 6 + (((CurrSig - 1) * 3) / 2); - else - RetSig = CurrSig; - - return RetSig; -} - -static s32 odm_SignalScaleMapping(struct dm_odm_t *pDM_Odm, s32 CurrSig) -{ - return odm_SignalScaleMapping_92CSeries(pDM_Odm, CurrSig); -} - -static u8 -odm_EVMdbToPercentage( - s8 Value - ) -{ - /* */ - /* -33dB~0dB to 0%~99% */ - /* */ - s8 ret_val; - - ret_val = Value; - - if (ret_val >= 0) - ret_val = 0; - if (ret_val <= -33) - ret_val = -33; - - ret_val = 0 - ret_val; - ret_val *= 3; - - if (ret_val == 99) - ret_val = 100; - - return ret_val; -} - -static void odm_RxPhyStatus92CSeries_Parsing(struct dm_odm_t *pDM_Odm, - struct phy_info *pPhyInfo, - u8 *pPhyStatus, - struct odm_packet_info *pPktinfo) -{ - struct phy_status_rpt *pPhyStaRpt = (struct phy_status_rpt *)pPhyStatus; - u8 i, Max_spatial_stream; - s8 rx_pwr[4], rx_pwr_all = 0; - u8 EVM, PWDB_ALL = 0, PWDB_ALL_BT; - u8 RSSI, total_rssi = 0; - u8 isCCKrate = 0; - u8 rf_rx_num = 0; - u8 cck_highpwr = 0; - - isCCKrate = (pPktinfo->Rate <= DESC92C_RATE11M) ? true : false; - pPhyInfo->RxMIMOSignalQuality[RF_PATH_A] = -1; - pPhyInfo->RxMIMOSignalQuality[RF_PATH_B] = -1; - - if (isCCKrate) { - u8 report; - u8 cck_agc_rpt; - - pDM_Odm->PhyDbgInfo.NumQryPhyStatusCCK++; - /* (1)Hardware does not provide RSSI for CCK */ - /* (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive) */ - - cck_highpwr = pDM_Odm->bCckHighPower; - - cck_agc_rpt = pPhyStaRpt->cck_agc_rpt_ofdm_cfosho_a; - - /* The RSSI formula should be modified according to the gain table */ - if (!cck_highpwr) { - report = (cck_agc_rpt & 0xc0)>>6; - switch (report) { - /* Modify the RF RNA gain value to -40, -20, -2, 14 by Jenyu's suggestion */ - /* Note: different RF with the different RNA gain. */ - case 0x3: - rx_pwr_all = -46 - (cck_agc_rpt & 0x3e); - break; - case 0x2: - rx_pwr_all = -26 - (cck_agc_rpt & 0x3e); - break; - case 0x1: - rx_pwr_all = -12 - (cck_agc_rpt & 0x3e); - break; - case 0x0: - rx_pwr_all = 16 - (cck_agc_rpt & 0x3e); - break; - } - } else { - report = (cck_agc_rpt & 0x60)>>5; - switch (report) { - case 0x3: - rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f)<<1); - break; - case 0x2: - rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f)<<1); - break; - case 0x1: - rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f)<<1); - break; - case 0x0: - rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f)<<1); - break; - } - } - - PWDB_ALL = odm_QueryRxPwrPercentage(rx_pwr_all); - - /* Modification for ext-LNA board */ - if (pDM_Odm->BoardType == ODM_BOARD_HIGHPWR) { - if ((cck_agc_rpt>>7) == 0) { - PWDB_ALL = (PWDB_ALL > 94) ? 100 : (PWDB_ALL+6); - } else { - if (PWDB_ALL > 38) - PWDB_ALL -= 16; - else - PWDB_ALL = (PWDB_ALL <= 16) ? (PWDB_ALL>>2) : (PWDB_ALL-12); - } - - /* CCK modification */ - if (PWDB_ALL > 25 && PWDB_ALL <= 60) - PWDB_ALL += 6; - } else { /* Modification for int-LNA board */ - if (PWDB_ALL > 99) - PWDB_ALL -= 8; - else if (PWDB_ALL > 50 && PWDB_ALL <= 68) - PWDB_ALL += 4; - } - pPhyInfo->RxPWDBAll = PWDB_ALL; - pPhyInfo->BTRxRSSIPercentage = PWDB_ALL; - pPhyInfo->RecvSignalPower = rx_pwr_all; - /* (3) Get Signal Quality (EVM) */ - if (pPktinfo->bPacketMatchBSSID) { - u8 SQ, SQ_rpt; - - SQ_rpt = pPhyStaRpt->cck_sig_qual_ofdm_pwdb_all; - - if (SQ_rpt > 64) - SQ = 0; - else if (SQ_rpt < 20) - SQ = 100; - else - SQ = ((64-SQ_rpt) * 100) / 44; - - pPhyInfo->SignalQuality = SQ; - pPhyInfo->RxMIMOSignalQuality[RF_PATH_A] = SQ; - pPhyInfo->RxMIMOSignalQuality[RF_PATH_B] = -1; - } - } else { /* is OFDM rate */ - pDM_Odm->PhyDbgInfo.NumQryPhyStatusOFDM++; - - /* (1)Get RSSI for HT rate */ - - for (i = RF_PATH_A; i < RF_PATH_MAX; i++) { - /* 2008/01/30 MH we will judge RF RX path now. */ - if (pDM_Odm->RFPathRxEnable & BIT(i)) - rf_rx_num++; - - rx_pwr[i] = ((pPhyStaRpt->path_agc[i].gain & 0x3F)*2) - 110; - - pPhyInfo->RxPwr[i] = rx_pwr[i]; - - /* Translate DBM to percentage. */ - RSSI = odm_QueryRxPwrPercentage(rx_pwr[i]); - total_rssi += RSSI; - - /* Modification for ext-LNA board */ - if (pDM_Odm->BoardType == ODM_BOARD_HIGHPWR) { - if ((pPhyStaRpt->path_agc[i].trsw) == 1) - RSSI = (RSSI > 94) ? 100 : (RSSI+6); - else - RSSI = (RSSI <= 16) ? (RSSI>>3) : (RSSI-16); - - if ((RSSI <= 34) && (RSSI >= 4)) - RSSI -= 4; - } - - pPhyInfo->RxMIMOSignalStrength[i] = (u8) RSSI; - - /* Get Rx snr value in DB */ - pPhyInfo->RxSNR[i] = pDM_Odm->PhyDbgInfo.RxSNRdB[i] = (s32)(pPhyStaRpt->path_rxsnr[i]/2); - } - - /* (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive) */ - rx_pwr_all = (((pPhyStaRpt->cck_sig_qual_ofdm_pwdb_all) >> 1) & 0x7f)-110; - - PWDB_ALL = odm_QueryRxPwrPercentage(rx_pwr_all); - PWDB_ALL_BT = PWDB_ALL; - - pPhyInfo->RxPWDBAll = PWDB_ALL; - pPhyInfo->BTRxRSSIPercentage = PWDB_ALL_BT; - pPhyInfo->RxPower = rx_pwr_all; - pPhyInfo->RecvSignalPower = rx_pwr_all; - - /* (3)EVM of HT rate */ - if (pPktinfo->Rate >= DESC92C_RATEMCS8 && pPktinfo->Rate <= DESC92C_RATEMCS15) - Max_spatial_stream = 2; /* both spatial stream make sense */ - else - Max_spatial_stream = 1; /* only spatial stream 1 makes sense */ - - for (i = 0; i < Max_spatial_stream; i++) { - /* Do not use shift operation like "rx_evmX >>= 1" because the compilor of free build environment */ - /* fill most significant bit to "zero" when doing shifting operation which may change a negative */ - /* 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 */ - - if (pPktinfo->bPacketMatchBSSID) { - if (i == RF_PATH_A) { - /* Fill value in RFD, Get the first spatial stream only */ - pPhyInfo->SignalQuality = (u8)(EVM & 0xff); - } - pPhyInfo->RxMIMOSignalQuality[i] = (u8)(EVM & 0xff); - } - } - } - /* UI BSS List signal strength(in percentage), make it good looking, from 0~100. */ - /* It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp(). */ - if (isCCKrate) { - pPhyInfo->SignalStrength = (u8)(odm_SignalScaleMapping(pDM_Odm, PWDB_ALL));/* PWDB_ALL; */ - } else { - if (rf_rx_num != 0) - pPhyInfo->SignalStrength = (u8)(odm_SignalScaleMapping(pDM_Odm, total_rssi /= rf_rx_num)); - } -} - -static void odm_Process_RSSIForDM(struct dm_odm_t *pDM_Odm, - struct phy_info *pPhyInfo, - struct odm_packet_info *pPktinfo) -{ - s32 UndecoratedSmoothedPWDB, UndecoratedSmoothedCCK; - s32 UndecoratedSmoothedOFDM, RSSI_Ave; - u8 isCCKrate = 0; - u8 RSSI_max, RSSI_min, i; - u32 OFDM_pkt = 0; - u32 Weighting = 0; - struct sta_info *pEntry; - - if (pPktinfo->StationID == 0xFF) - return; - - pEntry = pDM_Odm->pODM_StaInfo[pPktinfo->StationID]; - if (!pEntry) - return; - if ((!pPktinfo->bPacketMatchBSSID)) - return; - - isCCKrate = (pPktinfo->Rate <= DESC92C_RATE11M) ? true : false; - - /* Smart Antenna Debug Message------------------*/ - - UndecoratedSmoothedCCK = pEntry->rssi_stat.UndecoratedSmoothedCCK; - UndecoratedSmoothedOFDM = pEntry->rssi_stat.UndecoratedSmoothedOFDM; - UndecoratedSmoothedPWDB = pEntry->rssi_stat.UndecoratedSmoothedPWDB; - - if (pPktinfo->bPacketToSelf || pPktinfo->bPacketBeacon) { - if (!isCCKrate) { /* ofdm rate */ - if (pPhyInfo->RxMIMOSignalStrength[RF_PATH_B] == 0) { - RSSI_Ave = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A]; - } else { - if (pPhyInfo->RxMIMOSignalStrength[RF_PATH_A] > pPhyInfo->RxMIMOSignalStrength[RF_PATH_B]) { - RSSI_max = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A]; - RSSI_min = pPhyInfo->RxMIMOSignalStrength[RF_PATH_B]; - } else { - RSSI_max = pPhyInfo->RxMIMOSignalStrength[RF_PATH_B]; - RSSI_min = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A]; - } - if ((RSSI_max - RSSI_min) < 3) - RSSI_Ave = RSSI_max; - else if ((RSSI_max - RSSI_min) < 6) - RSSI_Ave = RSSI_max - 1; - else if ((RSSI_max - RSSI_min) < 10) - RSSI_Ave = RSSI_max - 2; - else - RSSI_Ave = RSSI_max - 3; - } - - /* 1 Process OFDM RSSI */ - if (UndecoratedSmoothedOFDM <= 0) { - /* initialize */ - UndecoratedSmoothedOFDM = pPhyInfo->RxPWDBAll; - } else { - if (pPhyInfo->RxPWDBAll > (u32)UndecoratedSmoothedOFDM) { - UndecoratedSmoothedOFDM = - (((UndecoratedSmoothedOFDM)*(Rx_Smooth_Factor-1)) + - (RSSI_Ave)) / (Rx_Smooth_Factor); - UndecoratedSmoothedOFDM = UndecoratedSmoothedOFDM + 1; - } else { - UndecoratedSmoothedOFDM = - (((UndecoratedSmoothedOFDM)*(Rx_Smooth_Factor-1)) + - (RSSI_Ave)) / (Rx_Smooth_Factor); - } - } - pEntry->rssi_stat.PacketMap = - (pEntry->rssi_stat.PacketMap<<1) | BIT(0); - } else { - RSSI_Ave = pPhyInfo->RxPWDBAll; - - /* 1 Process CCK RSSI */ - if (UndecoratedSmoothedCCK <= 0) { - /* initialize */ - UndecoratedSmoothedCCK = pPhyInfo->RxPWDBAll; - } else { - if (pPhyInfo->RxPWDBAll > (u32)UndecoratedSmoothedCCK) { - UndecoratedSmoothedCCK = - (((UndecoratedSmoothedCCK)*(Rx_Smooth_Factor-1)) + - (pPhyInfo->RxPWDBAll)) / (Rx_Smooth_Factor); - UndecoratedSmoothedCCK = UndecoratedSmoothedCCK + 1; - } else { - UndecoratedSmoothedCCK = - (((UndecoratedSmoothedCCK)*(Rx_Smooth_Factor-1)) + - (pPhyInfo->RxPWDBAll)) / (Rx_Smooth_Factor); - } - } - pEntry->rssi_stat.PacketMap = pEntry->rssi_stat.PacketMap<<1; - } - - /* 2011.07.28 LukeLee: modified to prevent unstable CCK RSSI */ - if (pEntry->rssi_stat.ValidBit >= 64) - pEntry->rssi_stat.ValidBit = 64; - else - pEntry->rssi_stat.ValidBit++; - - for (i = 0; i < pEntry->rssi_stat.ValidBit; i++) - OFDM_pkt += - (u8)(pEntry->rssi_stat.PacketMap>>i) & BIT(0); - - if (pEntry->rssi_stat.ValidBit == 64) { - Weighting = ((OFDM_pkt<<4) > 64)?64:(OFDM_pkt<<4); - UndecoratedSmoothedPWDB = (Weighting*UndecoratedSmoothedOFDM+(64-Weighting)*UndecoratedSmoothedCCK)>>6; - } else { - if (pEntry->rssi_stat.ValidBit != 0) - UndecoratedSmoothedPWDB = (OFDM_pkt*UndecoratedSmoothedOFDM+(pEntry->rssi_stat.ValidBit-OFDM_pkt)*UndecoratedSmoothedCCK)/pEntry->rssi_stat.ValidBit; - else - UndecoratedSmoothedPWDB = 0; - } - pEntry->rssi_stat.UndecoratedSmoothedCCK = UndecoratedSmoothedCCK; - pEntry->rssi_stat.UndecoratedSmoothedOFDM = UndecoratedSmoothedOFDM; - pEntry->rssi_stat.UndecoratedSmoothedPWDB = UndecoratedSmoothedPWDB; - } -} - -void ODM_PhyStatusQuery23a(struct dm_odm_t *pDM_Odm, struct phy_info *pPhyInfo, - u8 *pPhyStatus, struct odm_packet_info *pPktinfo) -{ - odm_RxPhyStatus92CSeries_Parsing(pDM_Odm, pPhyInfo, - pPhyStatus, pPktinfo); - - odm_Process_RSSIForDM(pDM_Odm, pPhyInfo, pPktinfo); -} diff --git a/drivers/staging/rtl8723au/hal/odm_RegConfig8723A.c b/drivers/staging/rtl8723au/hal/odm_RegConfig8723A.c deleted file mode 100644 index a63c6cb..0000000 --- a/drivers/staging/rtl8723au/hal/odm_RegConfig8723A.c +++ /dev/null @@ -1,88 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ - -#include "odm_precomp.h" -#include "usb_ops_linux.h" - -void -odm_ConfigRFReg_8723A( - struct dm_odm_t *pDM_Odm, - u32 Addr, - u32 Data, - enum RF_RADIO_PATH RF_PATH, - u32 RegAddr - ) -{ - if (Addr == 0xfe) { - msleep(50); - } else if (Addr == 0xfd) { - mdelay(5); - } else if (Addr == 0xfc) { - mdelay(1); - } else if (Addr == 0xfb) { - udelay(50); - } else if (Addr == 0xfa) { - udelay(5); - } else if (Addr == 0xf9) { - udelay(1); - } else { - ODM_SetRFReg(pDM_Odm, RF_PATH, RegAddr, bRFRegOffsetMask, Data); - /* Add 1us delay between BB/RF register setting. */ - udelay(1); - } -} - -void odm_ConfigMAC_8723A(struct dm_odm_t *pDM_Odm, u32 addr, u8 data) -{ - rtl8723au_write8(pDM_Odm->Adapter, addr, data); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD, - ("===> %s: [MAC_REG] %08X %08X\n", __func__, addr, data)); -} - -void odm_ConfigBB_AGC_8723A(struct dm_odm_t *pDM_Odm, u32 addr, u32 data) -{ - rtl8723au_write32(pDM_Odm->Adapter, addr, data); - /* Add 1us delay between BB/RF register setting. */ - udelay(1); - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD, - ("===> %s: [AGC_TAB] %08X %08X\n", __func__, addr, data)); -} - -void -odm_ConfigBB_PHY_8723A(struct dm_odm_t *pDM_Odm, u32 addr, u32 data) -{ - if (addr == 0xfe) - msleep(50); - else if (addr == 0xfd) - mdelay(5); - else if (addr == 0xfc) - mdelay(1); - else if (addr == 0xfb) - udelay(50); - else if (addr == 0xfa) - udelay(5); - else if (addr == 0xf9) - udelay(1); - else if (addr == 0xa24) - pDM_Odm->RFCalibrateInfo.RegA24 = data; - rtl8723au_write32(pDM_Odm->Adapter, addr, data); - - /* Add 1us delay between BB/RF register setting. */ - udelay(1); - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD, - ("===> %s: [PHY_REG] %08X %08X\n", __func__, addr, data)); -} diff --git a/drivers/staging/rtl8723au/hal/odm_debug.c b/drivers/staging/rtl8723au/hal/odm_debug.c deleted file mode 100644 index cb2bdda..0000000 --- a/drivers/staging/rtl8723au/hal/odm_debug.c +++ /dev/null @@ -1,39 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ - -#include "odm_precomp.h" - -void ODM_InitDebugSetting23a(struct dm_odm_t *pDM_Odm) -{ - pDM_Odm->DebugLevel = ODM_DBG_TRACE; - pDM_Odm->DebugComponents = 0; -} - -u32 GlobalDebugLevel23A; - -void rt_trace(int comp, int level, const char *fmt, ...) -{ - struct va_format vaf; - va_list args; - - va_start(args, fmt); - - vaf.fmt = fmt; - vaf.va = &args; - - pr_info(DRIVER_PREFIX " [0x%08x,%d] %pV", comp, level, &vaf); - - va_end(args); -} diff --git a/drivers/staging/rtl8723au/hal/odm_interface.c b/drivers/staging/rtl8723au/hal/odm_interface.c deleted file mode 100644 index d8f6790..0000000 --- a/drivers/staging/rtl8723au/hal/odm_interface.c +++ /dev/null @@ -1,49 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ - -/* */ -/* include files */ -/* */ - -#include "odm_precomp.h" -/* */ -/* ODM IO Relative API. */ -/* */ -#include <usb_ops_linux.h> - -void ODM_SetRFReg( - struct dm_odm_t *pDM_Odm, - enum RF_RADIO_PATH eRFPath, - u32 RegAddr, - u32 BitMask, - u32 Data - ) -{ - struct rtw_adapter *Adapter = pDM_Odm->Adapter; - - PHY_SetRFReg(Adapter, eRFPath, RegAddr, BitMask, Data); -} - -u32 ODM_GetRFReg( - struct dm_odm_t *pDM_Odm, - enum RF_RADIO_PATH eRFPath, - u32 RegAddr, - u32 BitMask - ) -{ - struct rtw_adapter *Adapter = pDM_Odm->Adapter; - - return PHY_QueryRFReg(Adapter, eRFPath, RegAddr, BitMask); -} diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c b/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c deleted file mode 100644 index 47e8d69..0000000 --- a/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c +++ /dev/null @@ -1,11265 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - *published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#include <drv_types.h> -#include <rtl8723a_hal.h> -#include <usb_ops_linux.h> - -#define DIS_PS_RX_BCN - -u32 BTCoexDbgLevel = _bt_dbg_off_; - -#define RTPRINT(_Comp, _Level, Fmt)\ -do {\ - if ((BTCoexDbgLevel == _bt_dbg_on_)) {\ - printk Fmt;\ - } \ -} while (0) - -#define RTPRINT_ADDR(dbgtype, dbgflag, printstr, _Ptr)\ -if ((BTCoexDbgLevel == _bt_dbg_on_)) {\ - u32 __i; \ - u8 *ptr = (u8 *)_Ptr; \ - printk printstr; \ - printk(" "); \ - for (__i = 0; __i < 6; __i++) \ - printk("%02X%s", ptr[__i], (__i == 5)?"":"-"); \ - printk("\n"); \ -} -#define RTPRINT_DATA(dbgtype, dbgflag, _TitleString, _HexData, _HexDataLen)\ -if ((BTCoexDbgLevel == _bt_dbg_on_)) {\ - u32 __i; \ - u8 *ptr = (u8 *)_HexData; \ - printk(_TitleString); \ - for (__i = 0; __i < (u32)_HexDataLen; __i++) { \ - printk("%02X%s", ptr[__i], (((__i + 1) % 4) == 0)?" ":" ");\ - if (((__i + 1) % 16) == 0) \ - printk("\n"); \ - } \ - printk("\n"); \ -} -/* Added by Annie, 2005-11-22. */ -#define MAX_STR_LEN 64 -/* I want to see ASCII 33 to 126 only. Otherwise, I print '?'. */ -#define PRINTABLE(_ch) (_ch >= ' ' && _ch <= '~') -#define RT_PRINT_STR(_Comp, _Level, _TitleString, _Ptr, _Len) \ - { \ - u32 __i; \ - u8 buffer[MAX_STR_LEN]; \ - u32 length = (_Len < MAX_STR_LEN) ? _Len : (MAX_STR_LEN-1);\ - memset(buffer, 0, MAX_STR_LEN); \ - memcpy(buffer, (u8 *)_Ptr, length); \ - for (__i = 0; __i < length; __i++) { \ - if (!PRINTABLE(buffer[__i])) \ - buffer[__i] = '?'; \ - } \ - buffer[length] = '\0'; \ - printk(_TitleString); \ - printk(": %d, <%s>\n", _Len, buffer); \ - } - -#define DCMD_Printf(...) -#define RT_ASSERT(...) - - -#define GetDefaultAdapter(padapter) padapter - -#define PlatformZeroMemory(ptr, sz) memset(ptr, 0, sz) - -#define GET_UNDECORATED_AVERAGE_RSSI(padapter) \ - (GET_HAL_DATA(padapter)->dmpriv.EntryMinUndecoratedSmoothedPWDB) -#define RT_RF_CHANGE_SOURCE u32 - -enum { - RT_JOIN_INFRA = 1, - RT_JOIN_IBSS = 2, - RT_START_IBSS = 3, - RT_NO_ACTION = 4, -}; - -/* power saving */ - -/* ===== Below this line is sync from SD7 driver COMMOM/BT.c ===== */ - -static u8 BT_Operation(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - if (pBtMgnt->BtOperationOn) - return true; - else - return false; -} - -static u8 BT_IsLegalChannel(struct rtw_adapter *padapter, u8 channel) -{ - struct rt_channel_info *pChanneList = NULL; - u8 channelLen, i; - - pChanneList = padapter->mlmeextpriv.channel_set; - channelLen = padapter->mlmeextpriv.max_chan_nums; - - for (i = 0; i < channelLen; i++) { - RTPRINT(FIOCTL, IOCTL_STATE, - ("Check if chnl(%d) in channel plan contains bt target chnl(%d) for BT connection\n", - pChanneList[i].ChannelNum, channel)); - if ((channel == pChanneList[i].ChannelNum) || - (channel == pChanneList[i].ChannelNum + 2)) - return channel; - } - return 0; -} - -void BT_SignalCompensation(struct rtw_adapter *padapter, u8 *rssi_wifi, u8 *rssi_bt) -{ - BTDM_SignalCompensation(padapter, rssi_wifi, rssi_bt); -} - -void rtl8723a_BT_wifiscan_notify(struct rtw_adapter *padapter, u8 scanType) -{ - BTHCI_WifiScanNotify(padapter, scanType); - BTDM_CheckAntSelMode(padapter); - BTDM_WifiScanNotify(padapter, scanType); -} - -void rtl8723a_BT_wifiassociate_notify(struct rtw_adapter *padapter, u8 action) -{ - /* action : */ - /* true = associate start */ - /* false = associate finished */ - if (action) - BTDM_CheckAntSelMode(padapter); - - BTDM_WifiAssociateNotify(padapter, action); -} - -void BT_HaltProcess(struct rtw_adapter *padapter) -{ - BTDM_ForHalt(padapter); -} - -/* ===== End of sync from SD7 driver COMMOM/BT.c ===== */ - -#define i64fmt "ll" -#define UINT64_C(v) (v) - -#define FillOctetString(_os, _octet, _len) \ - (_os).Octet = (u8 *)(_octet); \ - (_os).Length = (_len); - -static enum rt_status PlatformIndicateBTEvent( - struct rtw_adapter *padapter, - void *pEvntData, - u32 dataLen - ) -{ - enum rt_status rt_status = RT_STATUS_FAILURE; - - RTPRINT(FIOCTL, IOCTL_BT_EVENT_DETAIL, ("BT event start, %d bytes data to Transferred!!\n", dataLen)); - RTPRINT_DATA(FIOCTL, IOCTL_BT_EVENT_DETAIL, "To transfer Hex Data :\n", - pEvntData, dataLen); - - BT_EventParse(padapter, pEvntData, dataLen); - - printk(KERN_WARNING "%s: Linux has no way to report BT event!!\n", __func__); - - RTPRINT(FIOCTL, IOCTL_BT_EVENT_DETAIL, ("BT event end, %s\n", - (rt_status == RT_STATUS_SUCCESS) ? "SUCCESS" : "FAIL")); - - return rt_status; -} - -/* ===== Below this line is sync from SD7 driver COMMOM/bt_hci.c ===== */ - -static u8 bthci_GetLocalChannel(struct rtw_adapter *padapter) -{ - return padapter->mlmeextpriv.cur_channel; -} - -static u8 bthci_GetCurrentEntryNum(struct rtw_adapter *padapter, u8 PhyHandle) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - u8 i; - - for (i = 0; i < MAX_BT_ASOC_ENTRY_NUM; i++) { - if ((pBTInfo->BtAsocEntry[i].bUsed) && - (pBTInfo->BtAsocEntry[i].PhyLinkCmdData.BtPhyLinkhandle == PhyHandle)) - return i; - } - - return 0xFF; -} - -static void bthci_DecideBTChannel(struct rtw_adapter *padapter, u8 EntryNum) -{ -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct mlme_priv *pmlmepriv; - struct bt_30info *pBTInfo; - struct bt_mgnt *pBtMgnt; - struct bt_hci_info *pBtHciInfo; - struct chnl_txpower_triple *pTriple_subband = NULL; - struct common_triple *pTriple; - u8 i, j, localchnl, firstRemoteLegalChnlInTriplet = 0; - u8 regulatory_skipLen = 0; - u8 subbandTripletCnt = 0; - - pmlmepriv = &padapter->mlmepriv; - pBTInfo = GET_BT_INFO(padapter); - pBtMgnt = &pBTInfo->BtMgnt; - pBtHciInfo = &pBTInfo->BtHciInfo; - - pBtMgnt->CheckChnlIsSuit = true; - localchnl = bthci_GetLocalChannel(padapter); - - pTriple = (struct common_triple *) - &pBtHciInfo->BTPreChnllist[COUNTRY_STR_LEN]; - - /* contains country string, len is 3 */ - for (i = 0; i < (pBtHciInfo->BtPreChnlListLen-COUNTRY_STR_LEN); i += 3, pTriple++) { - /* */ - /* check every triplet, an triplet may be */ - /* regulatory extension identifier or sub-band triplet */ - /* */ - if (pTriple->byte_1st == 0xc9) { - /* Regulatory Extension Identifier, skip it */ - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), - ("Find Regulatory ID, regulatory class = %d\n", pTriple->byte_2nd)); - regulatory_skipLen += 3; - pTriple_subband = NULL; - continue; - } else { /* Sub-band triplet */ - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Find Sub-band triplet \n")); - subbandTripletCnt++; - pTriple_subband = (struct chnl_txpower_triple *)pTriple; - /* if remote first legal channel not found, then find first remote channel */ - /* and it's legal for our channel plan. */ - - /* search the sub-band triplet and find if remote channel is legal to our channel plan. */ - for (j = pTriple_subband->FirstChnl; j < (pTriple_subband->FirstChnl+pTriple_subband->NumChnls); j++) { - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), (" Check if chnl(%d) is legal\n", j)); - if (BT_IsLegalChannel(padapter, j)) { - /* remote channel is legal for our channel plan. */ - firstRemoteLegalChnlInTriplet = j; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), - ("Find first remote legal channel : %d\n", - firstRemoteLegalChnlInTriplet)); - - /* If we find a remote legal channel in the sub-band triplet */ - /* and only BT connection is established(local not connect to any AP or IBSS), */ - /* then we just switch channel to remote channel. */ - if (!(check_fwstate(pmlmepriv, WIFI_ASOC_STATE|WIFI_ADHOC_STATE|WIFI_AP_STATE) || - BTHCI_HsConnectionEstablished(padapter))) { - pBtMgnt->BTChannel = firstRemoteLegalChnlInTriplet; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Remote legal channel (%d) is selected, Local not connect to any!!\n", pBtMgnt->BTChannel)); - return; - } else { - if ((localchnl >= firstRemoteLegalChnlInTriplet) && - (localchnl < (pTriple_subband->FirstChnl+pTriple_subband->NumChnls))) { - pBtMgnt->BTChannel = localchnl; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Local channel (%d) is selected, wifi or BT connection exists\n", pBtMgnt->BTChannel)); - return; - } - } - break; - } - } - } - } - - if (subbandTripletCnt) { - /* if any preferred channel triplet exists */ - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("There are %d sub band triplet exists, ", subbandTripletCnt)); - if (firstRemoteLegalChnlInTriplet == 0) { - /* no legal channel is found, reject the connection. */ - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("no legal channel is found!!\n")); - } else { - /* Remote Legal channel is found but not match to local */ - /* wifi connection exists), so reject the connection. */ - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), - ("Remote Legal channel is found but not match to local(wifi connection exists)!!\n")); - } - pBtMgnt->CheckChnlIsSuit = false; - } else { - /* There are not any preferred channel triplet exists */ - /* Use current legal channel as the bt channel. */ - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("No sub band triplet exists!!\n")); - } - pBtMgnt->BTChannel = localchnl; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Local channel (%d) is selected!!\n", pBtMgnt->BTChannel)); -} - -/* Success:return true */ -/* Fail:return false */ -static u8 bthci_GetAssocInfo(struct rtw_adapter *padapter, u8 EntryNum) -{ - struct bt_30info *pBTInfo; - struct bt_hci_info *pBtHciInfo; - u8 tempBuf[256]; - u8 i = 0; - u8 BaseMemoryShift = 0; - u16 TotalLen = 0; - struct amp_assoc_structure *pAmpAsoc; - - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("GetAssocInfo start\n")); - pBTInfo = GET_BT_INFO(padapter); - pBtHciInfo = &pBTInfo->BtHciInfo; - - if (pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar == 0) { - if (pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocRemLen < (MAX_AMP_ASSOC_FRAG_LEN)) - TotalLen = pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocRemLen; - else if (pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocRemLen == (MAX_AMP_ASSOC_FRAG_LEN)) - TotalLen = MAX_AMP_ASSOC_FRAG_LEN; - } else if (pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar > 0) - TotalLen = pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar; - - while ((pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar >= BaseMemoryShift) || TotalLen > BaseMemoryShift) { - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_DETAIL, ("GetAssocInfo, TotalLen =%d, BaseMemoryShift =%d\n", TotalLen, BaseMemoryShift)); - memcpy(tempBuf, - (u8 *)pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocfragment+BaseMemoryShift, - TotalLen-BaseMemoryShift); - RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_DETAIL, "GetAssocInfo :\n", - tempBuf, TotalLen-BaseMemoryShift); - - pAmpAsoc = (struct amp_assoc_structure *)tempBuf; - le16_to_cpus(&pAmpAsoc->Length); - BaseMemoryShift += 3 + pAmpAsoc->Length; - - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("TypeID = 0x%x, ", pAmpAsoc->TypeID)); - RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD, "Hex Data: \n", pAmpAsoc->Data, pAmpAsoc->Length); - switch (pAmpAsoc->TypeID) { - case AMP_MAC_ADDR: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("==> AMP_MAC_ADDR\n")); - if (pAmpAsoc->Length > 6) - return false; - memcpy(pBTInfo->BtAsocEntry[EntryNum].BTRemoteMACAddr, pAmpAsoc->Data, 6); - RTPRINT_ADDR(FIOCTL, IOCTL_BT_HCICMD, ("Remote Mac address \n"), pBTInfo->BtAsocEntry[EntryNum].BTRemoteMACAddr); - break; - case AMP_PREFERRED_CHANNEL_LIST: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("==> AMP_PREFERRED_CHANNEL_LIST\n")); - pBtHciInfo->BtPreChnlListLen = pAmpAsoc->Length; - memcpy(pBtHciInfo->BTPreChnllist, - pAmpAsoc->Data, - pBtHciInfo->BtPreChnlListLen); - RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD, "Preferred channel list : \n", pBtHciInfo->BTPreChnllist, pBtHciInfo->BtPreChnlListLen); - bthci_DecideBTChannel(padapter, EntryNum); - break; - case AMP_CONNECTED_CHANNEL: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("==> AMP_CONNECTED_CHANNEL\n")); - pBtHciInfo->BTConnectChnlListLen = pAmpAsoc->Length; - memcpy(pBtHciInfo->BTConnectChnllist, - pAmpAsoc->Data, - pBtHciInfo->BTConnectChnlListLen); - break; - case AMP_80211_PAL_CAP_LIST: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("==> AMP_80211_PAL_CAP_LIST\n")); - pBTInfo->BtAsocEntry[EntryNum].BTCapability = *(u32 *)(pAmpAsoc->Data); - if (pBTInfo->BtAsocEntry[EntryNum].BTCapability & 0x00000001) { - /* TODO: */ - - /* Signifies PAL capable of utilizing received activity reports. */ - } - if (pBTInfo->BtAsocEntry[EntryNum].BTCapability & 0x00000002) { - /* TODO: */ - /* Signifies PAL is capable of utilizing scheduling information received in an activity reports. */ - } - break; - case AMP_80211_PAL_VISION: - pBtHciInfo->BTPalVersion = *(u8 *)(pAmpAsoc->Data); - pBtHciInfo->BTPalCompanyID = *(u16 *)(((u8 *)(pAmpAsoc->Data))+1); - pBtHciInfo->BTPalsubversion = *(u16 *)(((u8 *)(pAmpAsoc->Data))+3); - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("==> AMP_80211_PAL_VISION PalVersion 0x%x, PalCompanyID 0x%x, Palsubversion 0x%x\n", - pBtHciInfo->BTPalVersion, - pBtHciInfo->BTPalCompanyID, - pBtHciInfo->BTPalsubversion)); - break; - default: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("==> Unsupport TypeID !!\n")); - break; - } - i++; - } - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("GetAssocInfo end\n")); - - return true; -} - -static u8 bthci_AddEntry(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo; - struct bt_mgnt *pBtMgnt; - u8 i; - - pBTInfo = GET_BT_INFO(padapter); - pBtMgnt = &pBTInfo->BtMgnt; - - for (i = 0; i < MAX_BT_ASOC_ENTRY_NUM; i++) { - if (pBTInfo->BtAsocEntry[i].bUsed == false) { - pBTInfo->BtAsocEntry[i].bUsed = true; - pBtMgnt->CurrentConnectEntryNum = i; - break; - } - } - - if (i == MAX_BT_ASOC_ENTRY_NUM) { - RTPRINT(FIOCTL, IOCTL_STATE, ("bthci_AddEntry(), Add entry fail!!\n")); - return false; - } - return true; -} - -static u8 bthci_DiscardTxPackets(struct rtw_adapter *padapter, u16 LLH) -{ - return false; -} - -static u8 -bthci_CheckLogLinkBehavior( - struct rtw_adapter *padapter, - struct hci_flow_spec TxFlowSpec - ) -{ - u8 ID = TxFlowSpec.Identifier; - u8 ServiceType = TxFlowSpec.ServiceType; - u16 MaxSDUSize = TxFlowSpec.MaximumSDUSize; - u32 SDUInterArrivatime = TxFlowSpec.SDUInterArrivalTime; - u8 match = false; - - switch (ID) { - case 1: - if (ServiceType == BT_LL_BE) { - match = true; - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type = TX best effort flowspec\n")); - } else if ((ServiceType == BT_LL_GU) && (MaxSDUSize == 0xffff)) { - match = true; - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type = RX guaranteed latency flowspec\n")); - } else if ((ServiceType == BT_LL_GU) && (MaxSDUSize == 2500)) { - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type = RX guaranteed Large latency flowspec\n")); - } - break; - case 2: - if (ServiceType == BT_LL_BE) { - match = true; - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type = RX best effort flowspec\n")); - - } - break; - case 3: - if ((ServiceType == BT_LL_GU) && (MaxSDUSize == 1492)) { - match = true; - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type = TX guaranteed latency flowspec\n")); - } else if ((ServiceType == BT_LL_GU) && (MaxSDUSize == 2500)) { - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type = TX guaranteed Large latency flowspec\n")); - } - break; - case 4: - if (ServiceType == BT_LL_BE) { - if ((SDUInterArrivatime == 0xffffffff) && (ServiceType == BT_LL_BE) && (MaxSDUSize == 1492)) { - match = true; - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type = TX/RX aggregated best effort flowspec\n")); - } - } else if (ServiceType == BT_LL_GU) { - if (SDUInterArrivatime == 100) { - match = true; - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type = TX/RX guaranteed bandwidth flowspec\n")); - } - } - break; - default: - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type = Unknow Type !!!!!!!!\n")); - break; - } - - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), - ("ID = 0x%x, ServiceType = 0x%x, MaximumSDUSize = 0x%x, SDUInterArrivalTime = 0x%x, AccessLatency = 0x%x, FlushTimeout = 0x%x\n", - TxFlowSpec.Identifier, TxFlowSpec.ServiceType, MaxSDUSize, - SDUInterArrivatime, TxFlowSpec.AccessLatency, TxFlowSpec.FlushTimeout)); - return match; -} - -static u16 bthci_AssocMACAddr(struct rtw_adapter *padapter, void *pbuf) -{ - struct amp_assoc_structure *pAssoStrc = (struct amp_assoc_structure *)pbuf; - pAssoStrc->TypeID = AMP_MAC_ADDR; - pAssoStrc->Length = 0x06; - memcpy(&pAssoStrc->Data[0], padapter->eeprompriv.mac_addr, 6); - RTPRINT_DATA(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), - ("AssocMACAddr : \n"), pAssoStrc, pAssoStrc->Length+3); - - return pAssoStrc->Length + 3; -} - -static u16 -bthci_PALCapabilities( - struct rtw_adapter *padapter, - void *pbuf - ) -{ - struct amp_assoc_structure *pAssoStrc = (struct amp_assoc_structure *)pbuf; - - pAssoStrc->TypeID = AMP_80211_PAL_CAP_LIST; - pAssoStrc->Length = 0x04; - - pAssoStrc->Data[0] = 0x00; - pAssoStrc->Data[1] = 0x00; - - RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_DETAIL, ("PALCapabilities:\n"), pAssoStrc, pAssoStrc->Length+3); - RTPRINT(FIOCTL, IOCTL_BT_LOGO, ("PALCapabilities \n")); - - RTPRINT(FIOCTL, IOCTL_BT_LOGO, (" TypeID = 0x%x,\n Length = 0x%x,\n Content = 0x0000\n", - pAssoStrc->TypeID, - pAssoStrc->Length)); - - return pAssoStrc->Length + 3; -} - -static u16 bthci_AssocPreferredChannelList(struct rtw_adapter *padapter, - void *pbuf, u8 EntryNum) -{ - struct bt_30info *pBTInfo; - struct amp_assoc_structure *pAssoStrc; - struct amp_pref_chnl_regulatory *pReg; - struct chnl_txpower_triple *pTriple; - char ctrString[3] = {'X', 'X', 'X'}; - u32 len = 0; - u8 preferredChnl; - - pBTInfo = GET_BT_INFO(padapter); - pAssoStrc = (struct amp_assoc_structure *)pbuf; - pReg = (struct amp_pref_chnl_regulatory *)&pAssoStrc->Data[3]; - - preferredChnl = bthci_GetLocalChannel(padapter); - pAssoStrc->TypeID = AMP_PREFERRED_CHANNEL_LIST; - - /* locale unknown */ - memcpy(&pAssoStrc->Data[0], &ctrString[0], 3); - pReg->reXId = 201; - pReg->regulatoryClass = 254; - pReg->coverageClass = 0; - len += 6; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD | IOCTL_BT_LOGO), ("PREFERRED_CHNL_LIST\n")); - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD | IOCTL_BT_LOGO), ("XXX, 201, 254, 0\n")); - /* at the following, chnl 1~11 should be contained */ - pTriple = (struct chnl_txpower_triple *)&pAssoStrc->Data[len]; - - /* (1) if any wifi or bt HS connection exists */ - if ((pBTInfo->BtAsocEntry[EntryNum].AMPRole == AMP_BTAP_CREATOR) || - (check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE | - WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE | - WIFI_AP_STATE)) || - BTHCI_HsConnectionEstablished(padapter)) { - pTriple->FirstChnl = preferredChnl; - pTriple->NumChnls = 1; - pTriple->MaxTxPowerInDbm = 20; - len += 3; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD | IOCTL_BT_LOGO), ("First Channel = %d, Channel Num = %d, MaxDbm = %d\n", - pTriple->FirstChnl, - pTriple->NumChnls, - pTriple->MaxTxPowerInDbm)); - } - - pAssoStrc->Length = (u16)len; - RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD, ("AssocPreferredChannelList : \n"), pAssoStrc, pAssoStrc->Length+3); - - return pAssoStrc->Length + 3; -} - -static u16 bthci_AssocPALVer(struct rtw_adapter *padapter, void *pbuf) -{ - struct amp_assoc_structure *pAssoStrc = (struct amp_assoc_structure *)pbuf; - u8 *pu1Tmp; - u16 *pu2Tmp; - - pAssoStrc->TypeID = AMP_80211_PAL_VISION; - pAssoStrc->Length = 0x5; - pu1Tmp = &pAssoStrc->Data[0]; - *pu1Tmp = 0x1; /* PAL Version */ - pu2Tmp = (u16 *)&pAssoStrc->Data[1]; - *pu2Tmp = 0x5D; /* SIG Company identifier of 802.11 PAL vendor */ - pu2Tmp = (u16 *)&pAssoStrc->Data[3]; - *pu2Tmp = 0x1; /* PAL Sub-version specifier */ - - RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_DETAIL, ("AssocPALVer : \n"), pAssoStrc, pAssoStrc->Length+3); - RTPRINT(FIOCTL, IOCTL_BT_LOGO, ("AssocPALVer \n")); - - RTPRINT(FIOCTL, IOCTL_BT_LOGO, (" TypeID = 0x%x,\n Length = 0x%x,\n PAL Version = 0x01,\n PAL vendor = 0x01,\n PAL Sub-version specifier = 0x01\n", - pAssoStrc->TypeID, - pAssoStrc->Length)); - return pAssoStrc->Length + 3; -} - -static u8 bthci_CheckRfStateBeforeConnect(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo; - enum rt_rf_power_state RfState; - - pBTInfo = GET_BT_INFO(padapter); - - RfState = padapter->pwrctrlpriv.rf_pwrstate; - - if (RfState != rf_on) { - mod_timer(&pBTInfo->BTPsDisableTimer, - jiffies + msecs_to_jiffies(50)); - return false; - } - return true; -} - -static void bthci_ResponderStartToScan(struct rtw_adapter *padapter) -{ -} - -static u8 bthci_PhyLinkConnectionInProgress(struct rtw_adapter *padapter, u8 PhyLinkHandle) -{ - struct bt_30info *pBTInfo; - struct bt_mgnt *pBtMgnt; - - pBTInfo = GET_BT_INFO(padapter); - pBtMgnt = &pBTInfo->BtMgnt; - - if (pBtMgnt->bPhyLinkInProgress && - (pBtMgnt->BtCurrentPhyLinkhandle == PhyLinkHandle)) - return true; - return false; -} - -static void bthci_ResetFlowSpec(struct rtw_adapter *padapter, u8 EntryNum, u8 index) -{ - struct bt_30info *pBTinfo; - - pBTinfo = GET_BT_INFO(padapter); - - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].BtLogLinkhandle = 0; - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].BtPhyLinkhandle = 0; - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].bLLCompleteEventIsSet = false; - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].bLLCancelCMDIsSetandComplete = false; - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].BtTxFlowSpecID = 0; - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].TxPacketCount = 0; - - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Tx_Flow_Spec.Identifier = 0x01; - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Tx_Flow_Spec.ServiceType = SERVICE_BEST_EFFORT; - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Tx_Flow_Spec.MaximumSDUSize = 0xffff; - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Tx_Flow_Spec.SDUInterArrivalTime = 0xffffffff; - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Tx_Flow_Spec.AccessLatency = 0xffffffff; - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Tx_Flow_Spec.FlushTimeout = 0xffffffff; - - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Rx_Flow_Spec.Identifier = 0x01; - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Rx_Flow_Spec.ServiceType = SERVICE_BEST_EFFORT; - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Rx_Flow_Spec.MaximumSDUSize = 0xffff; - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Rx_Flow_Spec.SDUInterArrivalTime = 0xffffffff; - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Rx_Flow_Spec.AccessLatency = 0xffffffff; - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Rx_Flow_Spec.FlushTimeout = 0xffffffff; -} - -static void bthci_ResetEntry(struct rtw_adapter *padapter, u8 EntryNum) -{ - struct bt_30info *pBTinfo; - struct bt_mgnt *pBtMgnt; - u8 j; - - pBTinfo = GET_BT_INFO(padapter); - pBtMgnt = &pBTinfo->BtMgnt; - - pBTinfo->BtAsocEntry[EntryNum].bUsed = false; - pBTinfo->BtAsocEntry[EntryNum].BtCurrentState = HCI_STATE_DISCONNECTED; - pBTinfo->BtAsocEntry[EntryNum].BtNextState = HCI_STATE_DISCONNECTED; - - pBTinfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocRemLen = 0; - pBTinfo->BtAsocEntry[EntryNum].AmpAsocCmdData.BtPhyLinkhandle = 0; - if (pBTinfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocfragment != NULL) - memset(pBTinfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocfragment, 0, TOTAL_ALLOCIATE_ASSOC_LEN); - pBTinfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar = 0; - - pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyType = 0; - pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle = 0; - memset(pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKey, 0, - pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyLen); - pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyLen = 0; - - /* 0x640; 0.625ms*1600 = 1000ms, 0.625ms*16000 = 10000ms */ - pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.LinkSuperversionTimeout = 0x3e80; - - pBTinfo->BtAsocEntry[EntryNum].AMPRole = AMP_BTAP_NONE; - - pBTinfo->BtAsocEntry[EntryNum].mAssoc = false; - pBTinfo->BtAsocEntry[EntryNum].b4waySuccess = false; - - /* Reset BT WPA */ - pBTinfo->BtAsocEntry[EntryNum].KeyReplayCounter = 0; - pBTinfo->BtAsocEntry[EntryNum].BTWPAAuthState = STATE_WPA_AUTH_UNINITIALIZED; - - pBTinfo->BtAsocEntry[EntryNum].bSendSupervisionPacket = false; - pBTinfo->BtAsocEntry[EntryNum].NoRxPktCnt = 0; - pBTinfo->BtAsocEntry[EntryNum].ShortRangeMode = 0; - pBTinfo->BtAsocEntry[EntryNum].rxSuvpPktCnt = 0; - - for (j = 0; j < MAX_LOGICAL_LINK_NUM; j++) - bthci_ResetFlowSpec(padapter, EntryNum, j); - - pBtMgnt->BTAuthCount = 0; - pBtMgnt->BTAsocCount = 0; - pBtMgnt->BTCurrentConnectType = BT_DISCONNECT; - pBtMgnt->BTReceiveConnectPkt = BT_DISCONNECT; - - HALBT_RemoveKey(padapter, EntryNum); -} - -static void bthci_RemoveEntryByEntryNum(struct rtw_adapter *padapter, u8 EntryNum) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - bthci_ResetEntry(padapter, EntryNum); - - if (pBtMgnt->CurrentBTConnectionCnt > 0) - pBtMgnt->CurrentBTConnectionCnt--; - - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], CurrentBTConnectionCnt = %d!!\n", - pBtMgnt->CurrentBTConnectionCnt)); - - if (pBtMgnt->CurrentBTConnectionCnt > 0) { - pBtMgnt->BtOperationOn = true; - } else { - pBtMgnt->BtOperationOn = false; - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], Bt Operation OFF!!\n")); - } - - if (!pBtMgnt->BtOperationOn) { - del_timer_sync(&pBTInfo->BTHCIDiscardAclDataTimer); - del_timer_sync(&pBTInfo->BTBeaconTimer); - pBtMgnt->bStartSendSupervisionPkt = false; - } -} - -static u8 -bthci_CommandCompleteHeader( - u8 *pbuf, - u16 OGF, - u16 OCF, - enum hci_status status - ) -{ - struct packet_irp_hcievent_data *PPacketIrpEvent = (struct packet_irp_hcievent_data *)pbuf; - u8 NumHCI_Comm = 0x1; - - PPacketIrpEvent->EventCode = HCI_EVENT_COMMAND_COMPLETE; - PPacketIrpEvent->Data[0] = NumHCI_Comm; /* packet # */ - PPacketIrpEvent->Data[1] = HCIOPCODELOW(OCF, OGF); - PPacketIrpEvent->Data[2] = HCIOPCODEHIGHT(OCF, OGF); - - if (OGF == OGF_EXTENSION) { - if (OCF == HCI_SET_RSSI_VALUE) { - RTPRINT(FIOCTL, (IOCTL_BT_EVENT_PERIODICAL), - ("[BT event], CommandComplete, Num_HCI_Comm = 0x%x, Opcode = 0x%02x%02x, status = 0x%x, OGF = 0x%x, OCF = 0x%x\n", - NumHCI_Comm, (HCIOPCODEHIGHT(OCF, OGF)), (HCIOPCODELOW(OCF, OGF)), status, OGF, OCF)); - } else { - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_EXT), - ("[BT event], CommandComplete, Num_HCI_Comm = 0x%x, Opcode = 0x%02x%02x, status = 0x%x, OGF = 0x%x, OCF = 0x%x\n", - NumHCI_Comm, (HCIOPCODEHIGHT(OCF, OGF)), (HCIOPCODELOW(OCF, OGF)), status, OGF, OCF)); - } - } else { - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), - ("[BT event], CommandComplete, Num_HCI_Comm = 0x%x, Opcode = 0x%02x%02x, status = 0x%x, OGF = 0x%x, OCF = 0x%x\n", - NumHCI_Comm, (HCIOPCODEHIGHT(OCF, OGF)), (HCIOPCODELOW(OCF, OGF)), status, OGF, OCF)); - } - return 3; -} - -static u8 bthci_ExtensionEventHeaderRtk(u8 *pbuf, u8 extensionEvent) -{ - struct packet_irp_hcievent_data *PPacketIrpEvent = (struct packet_irp_hcievent_data *)pbuf; - PPacketIrpEvent->EventCode = HCI_EVENT_EXTENSION_RTK; - PPacketIrpEvent->Data[0] = extensionEvent; /* extension event code */ - - return 1; -} - -static enum rt_status -bthci_IndicateEvent( - struct rtw_adapter *padapter, - void *pEvntData, - u32 dataLen - ) -{ - return PlatformIndicateBTEvent(padapter, pEvntData, dataLen); -} - -static void -bthci_EventWriteRemoteAmpAssoc( - struct rtw_adapter *padapter, - enum hci_status status, - u8 PLHandle - ) -{ - u8 localBuf[TmpLocalBufSize] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PlatformZeroMemory(&localBuf[0], TmpLocalBufSize); - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_STATUS_PARAMETERS, - HCI_WRITE_REMOTE_AMP_ASSOC, - status); - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("PhyLinkHandle = 0x%x, status = %d\n", PLHandle, status)); - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - pRetPar[1] = PLHandle; - len += 2; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); -} - -static void -bthci_EventEnhancedFlushComplete( - struct rtw_adapter *padapter, - u16 LLH - ) -{ - u8 localBuf[4] = ""; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("EventEnhancedFlushComplete, LLH = 0x%x\n", LLH)); - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - PPacketIrpEvent->EventCode = HCI_EVENT_ENHANCED_FLUSH_COMPLETE; - PPacketIrpEvent->Length = 2; - /* Logical link handle */ - PPacketIrpEvent->Data[0] = TWOBYTE_LOWBYTE(LLH); - PPacketIrpEvent->Data[1] = TWOBYTE_HIGHTBYTE(LLH); - - bthci_IndicateEvent(padapter, PPacketIrpEvent, 4); -} - -static void -bthci_EventShortRangeModeChangeComplete( - struct rtw_adapter *padapter, - enum hci_status HciStatus, - u8 ShortRangeState, - u8 EntryNum - ) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u8 localBuf[5] = ""; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_SHORT_RANGE_MODE_CHANGE_COMPLETE)) { - RTPRINT(FIOCTL, IOCTL_BT_EVENT, - ("[BT event], Short Range Mode Change Complete, Ignore to send this event due to event mask page 2\n")); - return; - } - RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Short Range Mode Change Complete, Status = %d\n , PLH = 0x%x\n, Short_Range_Mode_State = 0x%x\n", - HciStatus, pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle, ShortRangeState)); - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - PPacketIrpEvent->EventCode = HCI_EVENT_SHORT_RANGE_MODE_CHANGE_COMPLETE; - PPacketIrpEvent->Length = 3; - PPacketIrpEvent->Data[0] = HciStatus; - PPacketIrpEvent->Data[1] = pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle; - PPacketIrpEvent->Data[2] = ShortRangeState; - bthci_IndicateEvent(padapter, PPacketIrpEvent, 5); -} - -static void bthci_EventSendFlowSpecModifyComplete(struct rtw_adapter *padapter, - enum hci_status HciStatus, - u16 logicHandle) -{ - u8 localBuf[5] = ""; - struct packet_irp_hcievent_data *PPacketIrpEvent; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - - if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_FLOW_SPEC_MODIFY_COMPLETE)) { - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), - ("[BT event], Flow Spec Modify Complete, Ignore to send this event due to event mask page 2\n")); - return; - } - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), - ("[BT event], Flow Spec Modify Complete, status = 0x%x, LLH = 0x%x\n", HciStatus, logicHandle)); - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - PPacketIrpEvent->EventCode = HCI_EVENT_FLOW_SPEC_MODIFY_COMPLETE; - PPacketIrpEvent->Length = 3; - - PPacketIrpEvent->Data[0] = HciStatus; - /* Logical link handle */ - PPacketIrpEvent->Data[1] = TWOBYTE_LOWBYTE(logicHandle); - PPacketIrpEvent->Data[2] = TWOBYTE_HIGHTBYTE(logicHandle); - - bthci_IndicateEvent(padapter, PPacketIrpEvent, 5); -} - -static void -bthci_EventExtWifiScanNotify( - struct rtw_adapter *padapter, - u8 scanType - ) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - u8 len = 0; - u8 localBuf[7] = ""; - u8 *pRetPar; - u8 *pu1Temp; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - if (!pBtMgnt->BtOperationOn) - return; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_ExtensionEventHeaderRtk(&localBuf[0], HCI_EVENT_EXT_WIFI_SCAN_NOTIFY); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pu1Temp = (u8 *)&pRetPar[0]; - *pu1Temp = scanType; - len += 1; - - PPacketIrpEvent->Length = len; - - if (bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2) == RT_STATUS_SUCCESS) { - RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Wifi scan notify, scan type = %d\n", - scanType)); - } -} - -static void -bthci_EventAMPReceiverReport( - struct rtw_adapter *padapter, - u8 Reason - ) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - - if (pBtHciInfo->bTestNeedReport) { - u8 localBuf[20] = ""; - u32 *pu4Temp; - u16 *pu2Temp; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), (" HCI_EVENT_AMP_RECEIVER_REPORT\n")); - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - PPacketIrpEvent->EventCode = HCI_EVENT_AMP_RECEIVER_REPORT; - PPacketIrpEvent->Length = 2; - - PPacketIrpEvent->Data[0] = pBtHciInfo->TestCtrType; - - PPacketIrpEvent->Data[1] = Reason; - - pu4Temp = (u32 *)&PPacketIrpEvent->Data[2]; - *pu4Temp = pBtHciInfo->TestEventType; - - pu2Temp = (u16 *)&PPacketIrpEvent->Data[6]; - *pu2Temp = pBtHciInfo->TestNumOfFrame; - - pu2Temp = (u16 *)&PPacketIrpEvent->Data[8]; - *pu2Temp = pBtHciInfo->TestNumOfErrFrame; - - pu4Temp = (u32 *)&PPacketIrpEvent->Data[10]; - *pu4Temp = pBtHciInfo->TestNumOfBits; - - pu4Temp = (u32 *)&PPacketIrpEvent->Data[14]; - *pu4Temp = pBtHciInfo->TestNumOfErrBits; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, 20); - - /* Return to Idel state with RX and TX off. */ - - } - - pBtHciInfo->TestNumOfFrame = 0x00; -} - -static void -bthci_EventChannelSelected( - struct rtw_adapter *padapter, - u8 EntryNum - ) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u8 localBuf[3] = ""; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_CHANNEL_SELECT)) { - RTPRINT(FIOCTL, IOCTL_BT_EVENT, - ("[BT event], Channel Selected, Ignore to send this event due to event mask page 2\n")); - return; - } - - RTPRINT(FIOCTL, IOCTL_BT_EVENT|IOCTL_STATE, - ("[BT event], Channel Selected, PhyLinkHandle %d\n", - pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle)); - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - PPacketIrpEvent->EventCode = HCI_EVENT_CHANNEL_SELECT; - PPacketIrpEvent->Length = 1; - PPacketIrpEvent->Data[0] = pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle; - bthci_IndicateEvent(padapter, PPacketIrpEvent, 3); -} - -static void -bthci_EventDisconnectPhyLinkComplete( - struct rtw_adapter *padapter, - enum hci_status HciStatus, - enum hci_status Reason, - u8 EntryNum - ) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u8 localBuf[5] = ""; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_DISCONNECT_PHY_LINK_COMPLETE)) { - RTPRINT(FIOCTL, IOCTL_BT_EVENT, - ("[BT event], Disconnect Physical Link Complete, Ignore to send this event due to event mask page 2\n")); - return; - } - RTPRINT(FIOCTL, IOCTL_BT_EVENT, - ("[BT event], Disconnect Physical Link Complete, Status = 0x%x, PLH = 0x%x Reason = 0x%x\n", - HciStatus, pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle, Reason)); - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - PPacketIrpEvent->EventCode = HCI_EVENT_DISCONNECT_PHY_LINK_COMPLETE; - PPacketIrpEvent->Length = 3; - PPacketIrpEvent->Data[0] = HciStatus; - PPacketIrpEvent->Data[1] = pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle; - PPacketIrpEvent->Data[2] = Reason; - bthci_IndicateEvent(padapter, PPacketIrpEvent, 5); -} - -static void -bthci_EventPhysicalLinkComplete( - struct rtw_adapter *padapter, - enum hci_status HciStatus, - u8 EntryNum, - u8 PLHandle - ) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - struct bt_dgb *pBtDbg = &pBTInfo->BtDbg; - u8 localBuf[4] = ""; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u8 PL_handle; - - pBtMgnt->bPhyLinkInProgress = false; - pBtDbg->dbgHciInfo.hciCmdPhyLinkStatus = HciStatus; - if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_PHY_LINK_COMPLETE)) { - RTPRINT(FIOCTL, IOCTL_BT_EVENT, - ("[BT event], Physical Link Complete, Ignore to send this event due to event mask page 2\n")); - return; - } - - if (EntryNum == 0xff) { - /* connection not started yet, just use the input physical link handle to response. */ - PL_handle = PLHandle; - } else { - /* connection is under progress, use the phy link handle we recorded. */ - PL_handle = pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle; - pBTInfo->BtAsocEntry[EntryNum].bNeedPhysLinkCompleteEvent = false; - } - - RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Physical Link Complete, Status = 0x%x PhyLinkHandle = 0x%x\n", HciStatus, - PL_handle)); - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - PPacketIrpEvent->EventCode = HCI_EVENT_PHY_LINK_COMPLETE; - PPacketIrpEvent->Length = 2; - - PPacketIrpEvent->Data[0] = HciStatus; - PPacketIrpEvent->Data[1] = PL_handle; - bthci_IndicateEvent(padapter, PPacketIrpEvent, 4); - -} - -static void -bthci_EventCommandStatus( - struct rtw_adapter *padapter, - u8 OGF, - u16 OCF, - enum hci_status HciStatus - ) -{ - - u8 localBuf[6] = ""; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u8 Num_Hci_Comm = 0x1; - RTPRINT(FIOCTL, IOCTL_BT_EVENT, - ("[BT event], CommandStatus, Opcode = 0x%02x%02x, OGF = 0x%x, OCF = 0x%x, Status = 0x%x, Num_HCI_COMM = 0x%x\n", - (HCIOPCODEHIGHT(OCF, OGF)), (HCIOPCODELOW(OCF, OGF)), OGF, OCF, HciStatus, Num_Hci_Comm)); - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - PPacketIrpEvent->EventCode = HCI_EVENT_COMMAND_STATUS; - PPacketIrpEvent->Length = 4; - PPacketIrpEvent->Data[0] = HciStatus; /* current pending */ - PPacketIrpEvent->Data[1] = Num_Hci_Comm; /* packet # */ - PPacketIrpEvent->Data[2] = HCIOPCODELOW(OCF, OGF); - PPacketIrpEvent->Data[3] = HCIOPCODEHIGHT(OCF, OGF); - - bthci_IndicateEvent(padapter, PPacketIrpEvent, 6); - -} - -static void -bthci_EventLogicalLinkComplete( - struct rtw_adapter *padapter, - enum hci_status HciStatus, - u8 PhyLinkHandle, - u16 LogLinkHandle, - u8 LogLinkIndex, - u8 EntryNum - ) -{ -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u8 localBuf[7] = ""; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_LOGICAL_LINK_COMPLETE)) { - RTPRINT(FIOCTL, IOCTL_BT_EVENT, - ("[BT event], Logical Link Complete, Ignore to send this event due to event mask page 2\n")); - return; - } - RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Logical Link Complete, PhyLinkHandle = 0x%x, LogLinkHandle = 0x%x, Status = 0x%x\n", - PhyLinkHandle, LogLinkHandle, HciStatus)); - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - PPacketIrpEvent->EventCode = HCI_EVENT_LOGICAL_LINK_COMPLETE; - PPacketIrpEvent->Length = 5; - - PPacketIrpEvent->Data[0] = HciStatus;/* status code */ - /* Logical link handle */ - PPacketIrpEvent->Data[1] = TWOBYTE_LOWBYTE(LogLinkHandle); - PPacketIrpEvent->Data[2] = TWOBYTE_HIGHTBYTE(LogLinkHandle); - /* Physical link handle */ - PPacketIrpEvent->Data[3] = TWOBYTE_LOWBYTE(PhyLinkHandle); - /* corresponding Tx flow spec ID */ - if (HciStatus == HCI_STATUS_SUCCESS) { - PPacketIrpEvent->Data[4] = - pBTInfo->BtAsocEntry[EntryNum].LogLinkCmdData[LogLinkIndex].Tx_Flow_Spec.Identifier; - } else { - PPacketIrpEvent->Data[4] = 0x0; - } - - bthci_IndicateEvent(padapter, PPacketIrpEvent, 7); -} - -static void -bthci_EventDisconnectLogicalLinkComplete( - struct rtw_adapter *padapter, - enum hci_status HciStatus, - u16 LogLinkHandle, - enum hci_status Reason - ) -{ - u8 localBuf[6] = ""; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_DISCONNECT_LOGICAL_LINK_COMPLETE)) { - RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Disconnect Logical Link Complete, Ignore to send this event due to event mask page 2\n")); - return; - } - RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Disconnect Logical Link Complete, Status = 0x%x, LLH = 0x%x Reason = 0x%x\n", HciStatus, LogLinkHandle, Reason)); - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - PPacketIrpEvent->EventCode = HCI_EVENT_DISCONNECT_LOGICAL_LINK_COMPLETE; - PPacketIrpEvent->Length = 4; - - PPacketIrpEvent->Data[0] = HciStatus; - /* Logical link handle */ - PPacketIrpEvent->Data[1] = TWOBYTE_LOWBYTE(LogLinkHandle); - PPacketIrpEvent->Data[2] = TWOBYTE_HIGHTBYTE(LogLinkHandle); - /* Disconnect reason */ - PPacketIrpEvent->Data[3] = Reason; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, 6); -} - -static void -bthci_EventFlushOccurred( - struct rtw_adapter *padapter, - u16 LogLinkHandle - ) -{ - u8 localBuf[4] = ""; - struct packet_irp_hcievent_data *PPacketIrpEvent; - RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("bthci_EventFlushOccurred(), LLH = 0x%x\n", LogLinkHandle)); - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - PPacketIrpEvent->EventCode = HCI_EVENT_FLUSH_OCCRUED; - PPacketIrpEvent->Length = 2; - /* Logical link handle */ - PPacketIrpEvent->Data[0] = TWOBYTE_LOWBYTE(LogLinkHandle); - PPacketIrpEvent->Data[1] = TWOBYTE_HIGHTBYTE(LogLinkHandle); - - bthci_IndicateEvent(padapter, PPacketIrpEvent, 4); -} - -static enum hci_status -bthci_BuildPhysicalLink( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd, - u16 OCF -) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - u8 EntryNum, PLH; - - /* Send HCI Command status event to AMP. */ - bthci_EventCommandStatus(padapter, - LINK_CONTROL_COMMANDS, - OCF, - HCI_STATUS_SUCCESS); - - PLH = *((u8 *)pHciCmd->Data); - - /* Check if resource or bt connection is under progress, if yes, reject the link creation. */ - if (!bthci_AddEntry(padapter)) { - status = HCI_STATUS_CONNECT_RJT_LIMIT_RESOURCE; - bthci_EventPhysicalLinkComplete(padapter, status, INVALID_ENTRY_NUM, PLH); - return status; - } - - EntryNum = pBtMgnt->CurrentConnectEntryNum; - pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle = PLH; - pBtMgnt->BtCurrentPhyLinkhandle = PLH; - - if (pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocfragment == NULL) { - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Create/Accept PhysicalLink, AMP controller is busy\n")); - status = HCI_STATUS_CONTROLLER_BUSY; - bthci_EventPhysicalLinkComplete(padapter, status, INVALID_ENTRY_NUM, PLH); - return status; - } - - /* Record Key and the info */ - pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyLen = (*((u8 *)pHciCmd->Data+1)); - pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyType = (*((u8 *)pHciCmd->Data+2)); - memcpy(pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKey, - (((u8 *)pHciCmd->Data+3)), pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyLen); - memcpy(pBTInfo->BtAsocEntry[EntryNum].PMK, pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKey, PMK_LEN); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("BuildPhysicalLink, EntryNum = %d, PLH = 0x%x KeyLen = 0x%x, KeyType = 0x%x\n", - EntryNum, pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle, - pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyLen, - pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyType)); - RTPRINT_DATA(FIOCTL, (IOCTL_BT_LOGO|IOCTL_BT_HCICMD), ("BtAMPKey\n"), pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKey, - pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyLen); - RTPRINT_DATA(FIOCTL, (IOCTL_BT_LOGO|IOCTL_BT_HCICMD), ("PMK\n"), pBTInfo->BtAsocEntry[EntryNum].PMK, - PMK_LEN); - - if (OCF == HCI_CREATE_PHYSICAL_LINK) { - /* These macros require braces */ - BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTED, STATE_CMD_CREATE_PHY_LINK, EntryNum); - } else if (OCF == HCI_ACCEPT_PHYSICAL_LINK) { - BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTED, STATE_CMD_ACCEPT_PHY_LINK, EntryNum); - } - - return status; -} - -static void -bthci_BuildLogicalLink( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd, - u16 OCF - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTinfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTinfo->BtMgnt; - u8 PhyLinkHandle, EntryNum; - static u16 AssignLogHandle = 1; - - struct hci_flow_spec TxFlowSpec; - struct hci_flow_spec RxFlowSpec; - u32 MaxSDUSize, ArriveTime, Bandwidth; - - PhyLinkHandle = *((u8 *)pHciCmd->Data); - - EntryNum = bthci_GetCurrentEntryNum(padapter, PhyLinkHandle); - - memcpy(&TxFlowSpec, - &pHciCmd->Data[1], sizeof(struct hci_flow_spec)); - memcpy(&RxFlowSpec, - &pHciCmd->Data[17], sizeof(struct hci_flow_spec)); - - MaxSDUSize = TxFlowSpec.MaximumSDUSize; - ArriveTime = TxFlowSpec.SDUInterArrivalTime; - - if (bthci_CheckLogLinkBehavior(padapter, TxFlowSpec) && bthci_CheckLogLinkBehavior(padapter, RxFlowSpec)) - Bandwidth = BTTOTALBANDWIDTH; - else if (MaxSDUSize == 0xffff && ArriveTime == 0xffffffff) - Bandwidth = BTTOTALBANDWIDTH; - else - Bandwidth = MaxSDUSize*8*1000/(ArriveTime+244); - - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, - ("BuildLogicalLink, PhyLinkHandle = 0x%x, MaximumSDUSize = 0x%x, SDUInterArrivalTime = 0x%x, Bandwidth = 0x%x\n", - PhyLinkHandle, MaxSDUSize, ArriveTime, Bandwidth)); - - if (EntryNum == 0xff) { - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Invalid Physical Link handle = 0x%x, status = HCI_STATUS_UNKNOW_CONNECT_ID, return\n", PhyLinkHandle)); - status = HCI_STATUS_UNKNOW_CONNECT_ID; - - /* When we receive Create/Accept logical link command, we should send command status event first. */ - bthci_EventCommandStatus(padapter, - LINK_CONTROL_COMMANDS, - OCF, - status); - return; - } - - if (!pBtMgnt->bLogLinkInProgress) { - if (bthci_PhyLinkConnectionInProgress(padapter, PhyLinkHandle)) { - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Physical link connection in progress, status = HCI_STATUS_CMD_DISALLOW, return\n")); - status = HCI_STATUS_CMD_DISALLOW; - - pBtMgnt->bPhyLinkInProgressStartLL = true; - /* When we receive Create/Accept logical link command, we should send command status event first. */ - bthci_EventCommandStatus(padapter, - LINK_CONTROL_COMMANDS, - OCF, - status); - - return; - } - - if (Bandwidth > BTTOTALBANDWIDTH) { - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("status = HCI_STATUS_QOS_REJECT, Bandwidth = 0x%x, return\n", Bandwidth)); - status = HCI_STATUS_QOS_REJECT; - - /* When we receive Create/Accept logical link command, we should send command status event first. */ - bthci_EventCommandStatus(padapter, - LINK_CONTROL_COMMANDS, - OCF, - status); - } else { - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("status = HCI_STATUS_SUCCESS\n")); - status = HCI_STATUS_SUCCESS; - - /* When we receive Create/Accept logical link command, we should send command status event first. */ - bthci_EventCommandStatus(padapter, - LINK_CONTROL_COMMANDS, - OCF, - status); - - } - - if (pBTinfo->BtAsocEntry[EntryNum].BtCurrentState != HCI_STATE_CONNECTED) { - bthci_EventLogicalLinkComplete(padapter, - HCI_STATUS_CMD_DISALLOW, 0, 0, 0, EntryNum); - } else { - u8 i, find = 0; - - pBtMgnt->bLogLinkInProgress = true; - - /* find an unused logical link index and copy the data */ - for (i = 0; i < MAX_LOGICAL_LINK_NUM; i++) { - if (pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].BtLogLinkhandle == 0) { - enum hci_status LogCompEventstatus = HCI_STATUS_SUCCESS; - - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].BtPhyLinkhandle = *((u8 *)pHciCmd->Data); - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].BtLogLinkhandle = AssignLogHandle; - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("BuildLogicalLink, EntryNum = %d, physical link handle = 0x%x, logical link handle = 0x%x\n", - EntryNum, pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle, - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].BtLogLinkhandle)); - memcpy(&pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].Tx_Flow_Spec, - &TxFlowSpec, sizeof(struct hci_flow_spec)); - memcpy(&pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].Rx_Flow_Spec, - &RxFlowSpec, sizeof(struct hci_flow_spec)); - - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].bLLCompleteEventIsSet = false; - - if (pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].bLLCancelCMDIsSetandComplete) - LogCompEventstatus = HCI_STATUS_UNKNOW_CONNECT_ID; - bthci_EventLogicalLinkComplete(padapter, - LogCompEventstatus, - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].BtPhyLinkhandle, - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].BtLogLinkhandle, i, EntryNum); - - pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].bLLCompleteEventIsSet = true; - - find = 1; - pBtMgnt->BtCurrentLogLinkhandle = AssignLogHandle; - AssignLogHandle++; - break; - } - } - - if (!find) { - bthci_EventLogicalLinkComplete(padapter, - HCI_STATUS_CONNECT_RJT_LIMIT_RESOURCE, 0, 0, 0, EntryNum); - } - pBtMgnt->bLogLinkInProgress = false; - } - } else { - bthci_EventLogicalLinkComplete(padapter, - HCI_STATUS_CONTROLLER_BUSY, 0, 0, 0, EntryNum); - } - -} - -static void -bthci_StartBeaconAndConnect( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd, - u8 CurrentAssocNum - ) -{ -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("StartBeaconAndConnect, CurrentAssocNum =%d, AMPRole =%d\n", - CurrentAssocNum, - pBTInfo->BtAsocEntry[CurrentAssocNum].AMPRole)); - - if (!pBtMgnt->CheckChnlIsSuit) { - bthci_EventPhysicalLinkComplete(padapter, HCI_STATUS_CONNECT_REJ_NOT_SUIT_CHNL_FOUND, CurrentAssocNum, INVALID_PL_HANDLE); - bthci_RemoveEntryByEntryNum(padapter, CurrentAssocNum); - return; - } - - if (pBTInfo->BtAsocEntry[CurrentAssocNum].AMPRole == AMP_BTAP_CREATOR) { - snprintf((char *)pBTInfo->BtAsocEntry[CurrentAssocNum].BTSsidBuf, 32, - "AMP-%pMF", padapter->eeprompriv.mac_addr); - } else if (pBTInfo->BtAsocEntry[CurrentAssocNum].AMPRole == AMP_BTAP_JOINER) { - snprintf((char *)pBTInfo->BtAsocEntry[CurrentAssocNum].BTSsidBuf, 32, - "AMP-%pMF", pBTInfo->BtAsocEntry[CurrentAssocNum].BTRemoteMACAddr); - } - - FillOctetString(pBTInfo->BtAsocEntry[CurrentAssocNum].BTSsid, pBTInfo->BtAsocEntry[CurrentAssocNum].BTSsidBuf, 21); - pBTInfo->BtAsocEntry[CurrentAssocNum].BTSsid.Length = 21; - - /* To avoid set the start ap or connect twice, or the original connection will be disconnected. */ - if (!pBtMgnt->bBTConnectInProgress) { - pBtMgnt->bBTConnectInProgress = true; - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], BT Connect in progress ON!!\n")); - BTHCI_SM_WITH_INFO(padapter, HCI_STATE_STARTING, STATE_CMD_MAC_START_COMPLETE, CurrentAssocNum); - - /* 20100325 Joseph: Check RF ON/OFF. */ - /* If RF OFF, it reschedule connecting operation after 50ms. */ - if (!bthci_CheckRfStateBeforeConnect(padapter)) - return; - - if (pBTInfo->BtAsocEntry[CurrentAssocNum].AMPRole == AMP_BTAP_CREATOR) { - /* These macros need braces */ - BTHCI_SM_WITH_INFO(padapter, HCI_STATE_CONNECTING, STATE_CMD_MAC_CONNECT_COMPLETE, CurrentAssocNum); - } else if (pBTInfo->BtAsocEntry[CurrentAssocNum].AMPRole == AMP_BTAP_JOINER) { - bthci_ResponderStartToScan(padapter); - } - } - RT_PRINT_STR(_module_rtl871x_mlme_c_, _drv_notice_, - "StartBeaconAndConnect, SSID:\n", - pBTInfo->BtAsocEntry[pBtMgnt->CurrentConnectEntryNum].BTSsid.Octet, - pBTInfo->BtAsocEntry[pBtMgnt->CurrentConnectEntryNum].BTSsid.Length); -} - -static void bthci_ResetBtMgnt(struct bt_mgnt *pBtMgnt) -{ - pBtMgnt->BtOperationOn = false; - pBtMgnt->bBTConnectInProgress = false; - pBtMgnt->bLogLinkInProgress = false; - pBtMgnt->bPhyLinkInProgress = false; - pBtMgnt->bPhyLinkInProgressStartLL = false; - pBtMgnt->DisconnectEntryNum = 0xff; - pBtMgnt->bStartSendSupervisionPkt = false; - pBtMgnt->JoinerNeedSendAuth = false; - pBtMgnt->CurrentBTConnectionCnt = 0; - pBtMgnt->BTCurrentConnectType = BT_DISCONNECT; - pBtMgnt->BTReceiveConnectPkt = BT_DISCONNECT; - pBtMgnt->BTAuthCount = 0; - pBtMgnt->btLogoTest = 0; -} - -static void bthci_ResetBtHciInfo(struct bt_hci_info *pBtHciInfo) -{ - pBtHciInfo->BTEventMask = 0; - pBtHciInfo->BTEventMaskPage2 = 0; - pBtHciInfo->ConnAcceptTimeout = 10000; - pBtHciInfo->PageTimeout = 0x30; - pBtHciInfo->LocationDomainAware = 0x0; - pBtHciInfo->LocationDomain = 0x5858; - pBtHciInfo->LocationDomainOptions = 0x58; - pBtHciInfo->LocationOptions = 0x0; - pBtHciInfo->FlowControlMode = 0x1; /* 0:Packet based data flow control mode(BR/EDR), 1: Data block based data flow control mode(AMP). */ - - pBtHciInfo->enFlush_LLH = 0; - pBtHciInfo->FLTO_LLH = 0; - - /* Test command only */ - pBtHciInfo->bTestIsEnd = true; - pBtHciInfo->bInTestMode = false; - pBtHciInfo->bTestNeedReport = false; - pBtHciInfo->TestScenario = 0xff; - pBtHciInfo->TestReportInterval = 0x01; - pBtHciInfo->TestCtrType = 0x5d; - pBtHciInfo->TestEventType = 0x00; - pBtHciInfo->TestNumOfFrame = 0; - pBtHciInfo->TestNumOfErrFrame = 0; - pBtHciInfo->TestNumOfBits = 0; - pBtHciInfo->TestNumOfErrBits = 0; -} - -static void bthci_ResetBtSec(struct rtw_adapter *padapter, struct bt_security *pBtSec) -{ -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - - /* Set BT used HW or SW encrypt !! */ - if (GET_HAL_DATA(padapter)->bBTMode) - pBtSec->bUsedHwEncrypt = true; - else - pBtSec->bUsedHwEncrypt = false; - RT_TRACE(_module_rtl871x_security_c_, _drv_info_, - "%s: bUsedHwEncrypt =%d\n", __func__, pBtSec->bUsedHwEncrypt); - - pBtSec->RSNIE.Octet = pBtSec->RSNIEBuf; -} - -static void bthci_ResetBtExtInfo(struct bt_mgnt *pBtMgnt) -{ - u8 i; - - for (i = 0; i < MAX_BT_ASOC_ENTRY_NUM; i++) { - pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle = 0; - pBtMgnt->ExtConfig.linkInfo[i].IncomingTrafficMode = 0; - pBtMgnt->ExtConfig.linkInfo[i].OutgoingTrafficMode = 0; - pBtMgnt->ExtConfig.linkInfo[i].BTProfile = BT_PROFILE_NONE; - pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec = BT_SPEC_2_1_EDR; - pBtMgnt->ExtConfig.linkInfo[i].BT_RSSI = 0; - pBtMgnt->ExtConfig.linkInfo[i].TrafficProfile = BT_PROFILE_NONE; - pBtMgnt->ExtConfig.linkInfo[i].linkRole = BT_LINK_MASTER; - } - - pBtMgnt->ExtConfig.CurrentConnectHandle = 0; - pBtMgnt->ExtConfig.CurrentIncomingTrafficMode = 0; - pBtMgnt->ExtConfig.CurrentOutgoingTrafficMode = 0; - pBtMgnt->ExtConfig.MIN_BT_RSSI = 0; - pBtMgnt->ExtConfig.NumberOfHandle = 0; - pBtMgnt->ExtConfig.NumberOfSCO = 0; - pBtMgnt->ExtConfig.CurrentBTStatus = 0; - pBtMgnt->ExtConfig.HCIExtensionVer = 0; - - pBtMgnt->ExtConfig.bManualControl = false; - pBtMgnt->ExtConfig.bBTBusy = false; - pBtMgnt->ExtConfig.bBTA2DPBusy = false; -} - -static enum hci_status bthci_CmdReset(struct rtw_adapter *_padapter, u8 bNeedSendEvent) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct rtw_adapter *padapter; -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct bt_30info *pBTInfo; - struct bt_mgnt *pBtMgnt; - struct bt_hci_info *pBtHciInfo; - struct bt_security *pBtSec; - struct bt_dgb *pBtDbg; - u8 i; - - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("bthci_CmdReset()\n")); - - padapter = GetDefaultAdapter(_padapter); - pBTInfo = GET_BT_INFO(padapter); - pBtMgnt = &pBTInfo->BtMgnt; - pBtHciInfo = &pBTInfo->BtHciInfo; - pBtSec = &pBTInfo->BtSec; - pBtDbg = &pBTInfo->BtDbg; - - pBTInfo->padapter = padapter; - - for (i = 0; i < MAX_BT_ASOC_ENTRY_NUM; i++) - bthci_ResetEntry(padapter, i); - - bthci_ResetBtMgnt(pBtMgnt); - bthci_ResetBtHciInfo(pBtHciInfo); - bthci_ResetBtSec(padapter, pBtSec); - - pBtMgnt->BTChannel = BT_Default_Chnl; - pBtMgnt->CheckChnlIsSuit = true; - - pBTInfo->BTBeaconTmrOn = false; - - pBtMgnt->bCreateSpportQos = true; - - del_timer_sync(&pBTInfo->BTHCIDiscardAclDataTimer); - del_timer_sync(&pBTInfo->BTBeaconTimer); - - HALBT_SetRtsCtsNoLenLimit(padapter); - /* */ - /* Maybe we need to take care Group != AES case !! */ - /* now we Pairwise and Group all used AES !! */ - - bthci_ResetBtExtInfo(pBtMgnt); - - /* send command complete event here when all data are received. */ - if (bNeedSendEvent) { - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_RESET, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdWriteRemoteAMPAssoc( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_dgb *pBtDbg = &pBTInfo->BtDbg; - u8 CurrentAssocNum; - u8 PhyLinkHandle; - - pBtDbg->dbgHciInfo.hciCmdCntWriteRemoteAmpAssoc++; - PhyLinkHandle = *((u8 *)pHciCmd->Data); - CurrentAssocNum = bthci_GetCurrentEntryNum(padapter, PhyLinkHandle); - - if (CurrentAssocNum == 0xff) { - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("WriteRemoteAMPAssoc, No such Handle in the Entry\n")); - status = HCI_STATUS_UNKNOW_CONNECT_ID; - bthci_EventWriteRemoteAmpAssoc(padapter, status, PhyLinkHandle); - return status; - } - - if (pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocfragment == NULL) { - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("WriteRemoteAMPAssoc, AMP controller is busy\n")); - status = HCI_STATUS_CONTROLLER_BUSY; - bthci_EventWriteRemoteAmpAssoc(padapter, status, PhyLinkHandle); - return status; - } - - pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.BtPhyLinkhandle = PhyLinkHandle;/* u8 *)pHciCmd->Data); */ - pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.LenSoFar = *((u16 *)((u8 *)pHciCmd->Data+1)); - pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocRemLen = *((u16 *)((u8 *)pHciCmd->Data+3)); - - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("WriteRemoteAMPAssoc, LenSoFar = 0x%x, AssocRemLen = 0x%x\n", - pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.LenSoFar, - pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocRemLen)); - - RTPRINT_DATA(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), - ("WriteRemoteAMPAssoc fragment \n"), - pHciCmd->Data, - pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocRemLen+5); - if ((pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocRemLen) > MAX_AMP_ASSOC_FRAG_LEN) { - memcpy(((u8 *)pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocfragment+(pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.LenSoFar*(sizeof(u8)))), - (u8 *)pHciCmd->Data+5, - MAX_AMP_ASSOC_FRAG_LEN); - } else { - memcpy((u8 *)(pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocfragment)+(pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.LenSoFar*(sizeof(u8))), - ((u8 *)pHciCmd->Data+5), - (pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocRemLen)); - - RTPRINT_DATA(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), "WriteRemoteAMPAssoc :\n", - pHciCmd->Data+5, pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocRemLen); - - if (!bthci_GetAssocInfo(padapter, CurrentAssocNum)) - status = HCI_STATUS_INVALID_HCI_CMD_PARA_VALUE; - - bthci_EventWriteRemoteAmpAssoc(padapter, status, PhyLinkHandle); - - bthci_StartBeaconAndConnect(padapter, pHciCmd, CurrentAssocNum); - } - - return status; -} - -/* 7.3.13 */ -static enum hci_status bthci_CmdReadConnectionAcceptTimeout(struct rtw_adapter *padapter) -{ - enum hci_status status = HCI_STATUS_SUCCESS; -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u8 localBuf[8] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u16 *pu2Temp; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_READ_CONNECTION_ACCEPT_TIMEOUT, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - pu2Temp = (u16 *)&pRetPar[1]; /* Conn_Accept_Timeout */ - *pu2Temp = pBtHciInfo->ConnAcceptTimeout; - len += 3; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - - return status; -} - -/* 7.3.14 */ -static enum hci_status -bthci_CmdWriteConnectionAcceptTimeout( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u16 *pu2Temp; - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - pu2Temp = (u16 *)&pHciCmd->Data[0]; - pBtHciInfo->ConnAcceptTimeout = *pu2Temp; - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_DETAIL, ("ConnAcceptTimeout = 0x%x", - pBtHciInfo->ConnAcceptTimeout)); - - /* send command complete event here when all data are received. */ - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_WRITE_CONNECTION_ACCEPT_TIMEOUT, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - - return status; -} - -static enum hci_status -bthci_CmdReadPageTimeout( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u8 localBuf[8] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u16 *pu2Temp; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_READ_PAGE_TIMEOUT, - status); - - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Read PageTimeout = 0x%x\n", pBtHciInfo->PageTimeout)); - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - pu2Temp = (u16 *)&pRetPar[1]; /* Page_Timeout */ - *pu2Temp = pBtHciInfo->PageTimeout; - len += 3; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - - return status; -} - -static enum hci_status -bthci_CmdWritePageTimeout( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u16 *pu2Temp; - - pu2Temp = (u16 *)&pHciCmd->Data[0]; - pBtHciInfo->PageTimeout = *pu2Temp; - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Write PageTimeout = 0x%x\n", - pBtHciInfo->PageTimeout)); - - /* send command complete event here when all data are received. */ - { - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_WRITE_PAGE_TIMEOUT, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdReadLinkSupervisionTimeout( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTinfo = GET_BT_INFO(padapter); - u8 physicalLinkHandle, EntryNum; - - physicalLinkHandle = *((u8 *)pHciCmd->Data); - - EntryNum = bthci_GetCurrentEntryNum(padapter, physicalLinkHandle); - - if (EntryNum == 0xff) { - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("ReadLinkSupervisionTimeout, No such Handle in the Entry\n")); - status = HCI_STATUS_UNKNOW_CONNECT_ID; - return status; - } - - if (pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle != physicalLinkHandle) - status = HCI_STATUS_UNKNOW_CONNECT_ID; - - { - u8 localBuf[10] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u16 *pu2Temp; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_READ_LINK_SUPERVISION_TIMEOUT, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; - pRetPar[1] = pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle; - pRetPar[2] = 0; - pu2Temp = (u16 *)&pRetPar[3]; /* Conn_Accept_Timeout */ - *pu2Temp = pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.LinkSuperversionTimeout; - len += 5; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdWriteLinkSupervisionTimeout( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTinfo = GET_BT_INFO(padapter); - u8 physicalLinkHandle, EntryNum; - - physicalLinkHandle = *((u8 *)pHciCmd->Data); - - EntryNum = bthci_GetCurrentEntryNum(padapter, physicalLinkHandle); - - if (EntryNum == 0xff) { - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("WriteLinkSupervisionTimeout, No such Handle in the Entry\n")); - status = HCI_STATUS_UNKNOW_CONNECT_ID; - } else { - if (pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle != physicalLinkHandle) { - status = HCI_STATUS_UNKNOW_CONNECT_ID; - } else { - pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.LinkSuperversionTimeout = *((u16 *)(((u8 *)pHciCmd->Data)+2)); - RTPRINT(FIOCTL, IOCTL_STATE, ("BT Write LinkSuperversionTimeout[%d] = 0x%x\n", - EntryNum, pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.LinkSuperversionTimeout)); - } - } - - { - u8 localBuf[8] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_WRITE_LINK_SUPERVISION_TIMEOUT, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; - pRetPar[1] = pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle; - pRetPar[2] = 0; - len += 3; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdEnhancedFlush( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTinfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTinfo->BtHciInfo; - u16 logicHandle; - u8 Packet_Type; - - logicHandle = *((u16 *)&pHciCmd->Data[0]); - Packet_Type = pHciCmd->Data[2]; - - if (Packet_Type != 0) - status = HCI_STATUS_INVALID_HCI_CMD_PARA_VALUE; - else - pBtHciInfo->enFlush_LLH = logicHandle; - - if (bthci_DiscardTxPackets(padapter, pBtHciInfo->enFlush_LLH)) - bthci_EventFlushOccurred(padapter, pBtHciInfo->enFlush_LLH); - - /* should send command status event */ - bthci_EventCommandStatus(padapter, - OGF_SET_EVENT_MASK_COMMAND, - HCI_ENHANCED_FLUSH, - status); - - if (pBtHciInfo->enFlush_LLH) { - bthci_EventEnhancedFlushComplete(padapter, pBtHciInfo->enFlush_LLH); - pBtHciInfo->enFlush_LLH = 0; - } - - return status; -} - -static enum hci_status -bthci_CmdReadLogicalLinkAcceptTimeout( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u8 localBuf[8] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u16 *pu2Temp; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_READ_LOGICAL_LINK_ACCEPT_TIMEOUT, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; - - pu2Temp = (u16 *)&pRetPar[1]; /* Conn_Accept_Timeout */ - *pu2Temp = pBtHciInfo->LogicalAcceptTimeout; - len += 3; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - - return status; -} - -static enum hci_status -bthci_CmdWriteLogicalLinkAcceptTimeout( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - pBtHciInfo->LogicalAcceptTimeout = *((u16 *)pHciCmd->Data); - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_WRITE_LOGICAL_LINK_ACCEPT_TIMEOUT, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; - - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - return status; -} - -static enum hci_status -bthci_CmdSetEventMask( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u8 *pu8Temp; - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - pu8Temp = (u8 *)&pHciCmd->Data[0]; - pBtHciInfo->BTEventMask = *pu8Temp; - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_DETAIL, ("BTEventMask = 0x%"i64fmt"x\n", - pBtHciInfo->BTEventMask)); - - /* send command complete event here when all data are received. */ - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_SET_EVENT_MASK, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - - return status; -} - -/* 7.3.69 */ -static enum hci_status -bthci_CmdSetEventMaskPage2( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u8 *pu8Temp; - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - pu8Temp = (u8 *)&pHciCmd->Data[0]; - pBtHciInfo->BTEventMaskPage2 = *pu8Temp; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("BTEventMaskPage2 = 0x%"i64fmt"x\n", - pBtHciInfo->BTEventMaskPage2)); - - /* send command complete event here when all data are received. */ - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_SET_EVENT_MASK_PAGE_2, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - - return status; -} - -static enum hci_status -bthci_CmdReadLocationData( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u8 localBuf[12] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u16 *pu2Temp; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_READ_LOCATION_DATA, - status); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("DomainAware = 0x%x\n", pBtHciInfo->LocationDomainAware)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Domain = 0x%x\n", pBtHciInfo->LocationDomain)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("DomainOptions = 0x%x\n", pBtHciInfo->LocationDomainOptions)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Options = 0x%x\n", pBtHciInfo->LocationOptions)); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; - - pRetPar[1] = pBtHciInfo->LocationDomainAware; /* 0x0; Location_Domain_Aware */ - pu2Temp = (u16 *)&pRetPar[2]; /* Location_Domain */ - *pu2Temp = pBtHciInfo->LocationDomain; /* 0x5858; */ - pRetPar[4] = pBtHciInfo->LocationDomainOptions; /* 0x58; Location_Domain_Options */ - pRetPar[5] = pBtHciInfo->LocationOptions; /* 0x0; Location_Options */ - len += 6; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - return status; -} - -static enum hci_status -bthci_CmdWriteLocationData( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u16 *pu2Temp; - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - pBtHciInfo->LocationDomainAware = pHciCmd->Data[0]; - pu2Temp = (u16 *)&pHciCmd->Data[1]; - pBtHciInfo->LocationDomain = *pu2Temp; - pBtHciInfo->LocationDomainOptions = pHciCmd->Data[3]; - pBtHciInfo->LocationOptions = pHciCmd->Data[4]; - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("DomainAware = 0x%x\n", pBtHciInfo->LocationDomainAware)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Domain = 0x%x\n", pBtHciInfo->LocationDomain)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("DomainOptions = 0x%x\n", pBtHciInfo->LocationDomainOptions)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Options = 0x%x\n", pBtHciInfo->LocationOptions)); - - /* send command complete event here when all data are received. */ - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_WRITE_LOCATION_DATA, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - - return status; -} - -static enum hci_status -bthci_CmdReadFlowControlMode( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u8 localBuf[7] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_READ_FLOW_CONTROL_MODE, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; - pRetPar[1] = pBtHciInfo->FlowControlMode; /* Flow Control Mode */ - len += 2; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - return status; -} - -static enum hci_status -bthci_CmdWriteFlowControlMode( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - pBtHciInfo->FlowControlMode = pHciCmd->Data[0]; - - /* send command complete event here when all data are received. */ - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_WRITE_FLOW_CONTROL_MODE, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - - return status; -} - -static enum hci_status -bthci_CmdReadBestEffortFlushTimeout( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTinfo = GET_BT_INFO(padapter); - u16 i, j, logicHandle; - u32 BestEffortFlushTimeout = 0xffffffff; - u8 find = 0; - - logicHandle = *((u16 *)pHciCmd->Data); - /* find an matched logical link index and copy the data */ - for (j = 0; j < MAX_BT_ASOC_ENTRY_NUM; j++) { - for (i = 0; i < MAX_LOGICAL_LINK_NUM; i++) { - if (pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].BtLogLinkhandle == logicHandle) { - BestEffortFlushTimeout = pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].BestEffortFlushTimeout; - find = 1; - break; - } - } - } - - if (!find) - status = HCI_STATUS_UNKNOW_CONNECT_ID; - - { - u8 localBuf[10] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u32 *pu4Temp; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_READ_BEST_EFFORT_FLUSH_TIMEOUT, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; - pu4Temp = (u32 *)&pRetPar[1]; /* Best_Effort_Flush_Timeout */ - *pu4Temp = BestEffortFlushTimeout; - len += 5; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - return status; -} - -static enum hci_status -bthci_CmdWriteBestEffortFlushTimeout( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTinfo = GET_BT_INFO(padapter); - u16 i, j, logicHandle; - u32 BestEffortFlushTimeout = 0xffffffff; - u8 find = 0; - - logicHandle = *((u16 *)pHciCmd->Data); - BestEffortFlushTimeout = *((u32 *)(pHciCmd->Data+1)); - - /* find an matched logical link index and copy the data */ - for (j = 0; j < MAX_BT_ASOC_ENTRY_NUM; j++) { - for (i = 0; i < MAX_LOGICAL_LINK_NUM; i++) { - if (pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].BtLogLinkhandle == logicHandle) { - pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].BestEffortFlushTimeout = BestEffortFlushTimeout; - find = 1; - break; - } - } - } - - if (!find) - status = HCI_STATUS_UNKNOW_CONNECT_ID; - - { - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_WRITE_BEST_EFFORT_FLUSH_TIMEOUT, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - return status; -} - -static enum hci_status -bthci_CmdShortRangeMode( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - u8 PhyLinkHandle, EntryNum, ShortRangeMode; - - PhyLinkHandle = pHciCmd->Data[0]; - ShortRangeMode = pHciCmd->Data[1]; - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("PLH = 0x%x, Short_Range_Mode = 0x%x\n", PhyLinkHandle, ShortRangeMode)); - - EntryNum = bthci_GetCurrentEntryNum(padapter, PhyLinkHandle); - if (EntryNum != 0xff) { - pBTInfo->BtAsocEntry[EntryNum].ShortRangeMode = ShortRangeMode; - } else { - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("No such PLH(0x%x)\n", PhyLinkHandle)); - status = HCI_STATUS_UNKNOW_CONNECT_ID; - } - - bthci_EventCommandStatus(padapter, - OGF_SET_EVENT_MASK_COMMAND, - HCI_SHORT_RANGE_MODE, - status); - - bthci_EventShortRangeModeChangeComplete(padapter, status, ShortRangeMode, EntryNum); - - return status; -} - -static enum hci_status bthci_CmdReadLocalSupportedCommands(struct rtw_adapter *padapter) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - u8 localBuf[TmpLocalBufSize] = ""; - u8 *pRetPar, *pSupportedCmds; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - /* send command complete event here when all data are received. */ - PlatformZeroMemory(&localBuf[0], TmpLocalBufSize); - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_INFORMATIONAL_PARAMETERS, - HCI_READ_LOCAL_SUPPORTED_COMMANDS, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - len += 1; - pSupportedCmds = &pRetPar[1]; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[5]= 0xc0\nBit [6]= Set Event Mask, [7]= Reset\n")); - pSupportedCmds[5] = 0xc0; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[6]= 0x01\nBit [0]= Set Event Filter\n")); - pSupportedCmds[6] = 0x01; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[7]= 0x0c\nBit [2]= Read Connection Accept Timeout, [3]= Write Connection Accept Timeout\n")); - pSupportedCmds[7] = 0x0c; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[10]= 0x80\nBit [7]= Host Number Of Completed Packets\n")); - pSupportedCmds[10] = 0x80; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[11]= 0x03\nBit [0]= Read Link Supervision Timeout, [1]= Write Link Supervision Timeout\n")); - pSupportedCmds[11] = 0x03; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[14]= 0xa8\nBit [3]= Read Local Version Information, [5]= Read Local Supported Features, [7]= Read Buffer Size\n")); - pSupportedCmds[14] = 0xa8; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[15]= 0x1c\nBit [2]= Read Failed Contact Count, [3]= Reset Failed Contact Count, [4]= Get Link Quality\n")); - pSupportedCmds[15] = 0x1c; - /* pSupportedCmds[16] = 0x04; */ - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[19]= 0x40\nBit [6]= Enhanced Flush\n")); - pSupportedCmds[19] = 0x40; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[21]= 0xff\nBit [0]= Create Physical Link, [1]= Accept Physical Link, [2]= Disconnect Physical Link, [3]= Create Logical Link\n")); - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), (" [4]= Accept Logical Link, [5]= Disconnect Logical Link, [6]= Logical Link Cancel, [7]= Flow Spec Modify\n")); - pSupportedCmds[21] = 0xff; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[22]= 0xff\nBit [0]= Read Logical Link Accept Timeout, [1]= Write Logical Link Accept Timeout, [2]= Set Event Mask Page 2, [3]= Read Location Data\n")); - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), (" [4]= Write Location Data, [5]= Read Local AMP Info, [6]= Read Local AMP_ASSOC, [7]= Write Remote AMP_ASSOC\n")); - pSupportedCmds[22] = 0xff; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[23]= 0x07\nBit [0]= Read Flow Control Mode, [1]= Write Flow Control Mode, [2]= Read Data Block Size\n")); - pSupportedCmds[23] = 0x07; - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[24]= 0x1c\nBit [2]= Read Best Effort Flush Timeout, [3]= Write Best Effort Flush Timeout, [4]= Short Range Mode\n")); - pSupportedCmds[24] = 0x1c; - len += 64; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - - return status; -} - -static enum hci_status bthci_CmdReadLocalSupportedFeatures(struct rtw_adapter *padapter) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - u8 localBuf[TmpLocalBufSize] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - /* send command complete event here when all data are received. */ - PlatformZeroMemory(&localBuf[0], TmpLocalBufSize); - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_INFORMATIONAL_PARAMETERS, - HCI_READ_LOCAL_SUPPORTED_FEATURES, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - len += 9; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - return status; -} - -static enum hci_status bthci_CmdReadLocalAMPAssoc(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - struct bt_dgb *pBtDbg = &pBTInfo->BtDbg; - u8 PhyLinkHandle, EntryNum; - - pBtDbg->dbgHciInfo.hciCmdCntReadLocalAmpAssoc++; - PhyLinkHandle = *((u8 *)pHciCmd->Data); - EntryNum = bthci_GetCurrentEntryNum(padapter, PhyLinkHandle); - - if ((EntryNum == 0xff) && PhyLinkHandle != 0) { - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("ReadLocalAMPAssoc, EntryNum = %d !!!!!, physical link handle = 0x%x\n", - EntryNum, PhyLinkHandle)); - status = HCI_STATUS_UNKNOW_CONNECT_ID; - } else if (pBtMgnt->bPhyLinkInProgressStartLL) { - status = HCI_STATUS_UNKNOW_CONNECT_ID; - pBtMgnt->bPhyLinkInProgressStartLL = false; - } else { - pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.BtPhyLinkhandle = *((u8 *)pHciCmd->Data); - pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar = *((u16 *)((u8 *)pHciCmd->Data+1)); - pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.MaxRemoteASSOCLen = *((u16 *)((u8 *)pHciCmd->Data+3)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_DETAIL, ("ReadLocalAMPAssoc, LenSoFar =%d, MaxRemoteASSOCLen =%d\n", - pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar, - pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.MaxRemoteASSOCLen)); - } - - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("ReadLocalAMPAssoc, EntryNum = %d !!!!!, physical link handle = 0x%x, LengthSoFar = %x \n", - EntryNum, PhyLinkHandle, pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar)); - - /* send command complete event here when all data are received. */ - { - struct packet_irp_hcievent_data *PPacketIrpEvent; - - /* PVOID buffer = padapter->IrpHCILocalbuf.Ptr; */ - u8 localBuf[TmpLocalBufSize] = ""; - u16 *pRemainLen; - u32 totalLen = 0; - u16 typeLen = 0, remainLen = 0, ret_index = 0; - u8 *pRetPar; - - PlatformZeroMemory(&localBuf[0], TmpLocalBufSize); - /* PPacketIrpEvent = (struct packet_irp_hcievent_data *)(buffer); */ - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - totalLen += bthci_CommandCompleteHeader(&localBuf[0], - OGF_STATUS_PARAMETERS, - HCI_READ_LOCAL_AMP_ASSOC, - status); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("ReadLocalAMPAssoc, Remaining_Len =%d \n", remainLen)); - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[totalLen]; - pRetPar[0] = status; /* status */ - pRetPar[1] = *((u8 *)pHciCmd->Data); - pRemainLen = (u16 *)&pRetPar[2]; /* AMP_ASSOC_Remaining_Length */ - totalLen += 4; /* 0]~[3] */ - ret_index = 4; - - typeLen = bthci_AssocMACAddr(padapter, &pRetPar[ret_index]); - totalLen += typeLen; - remainLen += typeLen; - ret_index += typeLen; - typeLen = bthci_AssocPreferredChannelList(padapter, &pRetPar[ret_index], EntryNum); - totalLen += typeLen; - remainLen += typeLen; - ret_index += typeLen; - typeLen = bthci_PALCapabilities(padapter, &pRetPar[ret_index]); - totalLen += typeLen; - remainLen += typeLen; - ret_index += typeLen; - typeLen = bthci_AssocPALVer(padapter, &pRetPar[ret_index]); - totalLen += typeLen; - remainLen += typeLen; - PPacketIrpEvent->Length = (u8)totalLen; - *pRemainLen = remainLen; /* AMP_ASSOC_Remaining_Length */ - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("ReadLocalAMPAssoc, Remaining_Len =%d \n", remainLen)); - RTPRINT_DATA(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("AMP_ASSOC_fragment : \n"), PPacketIrpEvent->Data, totalLen); - - bthci_IndicateEvent(padapter, PPacketIrpEvent, totalLen+2); - } - - return status; -} - -static enum hci_status bthci_CmdReadFailedContactCounter(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u8 localBuf[TmpLocalBufSize] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u16 handle; - - handle = *((u16 *)pHciCmd->Data); - /* send command complete event here when all data are received. */ - PlatformZeroMemory(&localBuf[0], TmpLocalBufSize); - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_STATUS_PARAMETERS, - HCI_READ_FAILED_CONTACT_COUNTER, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - pRetPar[1] = TWOBYTE_LOWBYTE(handle); - pRetPar[2] = TWOBYTE_HIGHTBYTE(handle); - pRetPar[3] = TWOBYTE_LOWBYTE(pBtHciInfo->FailContactCount); - pRetPar[4] = TWOBYTE_HIGHTBYTE(pBtHciInfo->FailContactCount); - len += 5; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - - return status; -} - -static enum hci_status -bthci_CmdResetFailedContactCounter( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u16 handle; - u8 localBuf[TmpLocalBufSize] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - handle = *((u16 *)pHciCmd->Data); - pBtHciInfo->FailContactCount = 0; - - /* send command complete event here when all data are received. */ - PlatformZeroMemory(&localBuf[0], TmpLocalBufSize); - /* PPacketIrpEvent = (struct packet_irp_hcievent_data *)(buffer); */ - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_STATUS_PARAMETERS, - HCI_RESET_FAILED_CONTACT_COUNTER, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - pRetPar[1] = TWOBYTE_LOWBYTE(handle); - pRetPar[2] = TWOBYTE_HIGHTBYTE(handle); - len += 3; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - return status; -} - -/* */ -/* BT 3.0+HS [Vol 2] 7.4.1 */ -/* */ -static enum hci_status -bthci_CmdReadLocalVersionInformation( - struct rtw_adapter *padapter - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - /* send command complete event here when all data are received. */ - u8 localBuf[TmpLocalBufSize] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u16 *pu2Temp; - - PlatformZeroMemory(&localBuf[0], TmpLocalBufSize); - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_INFORMATIONAL_PARAMETERS, - HCI_READ_LOCAL_VERSION_INFORMATION, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - pRetPar[1] = 0x05; /* HCI_Version */ - pu2Temp = (u16 *)&pRetPar[2]; /* HCI_Revision */ - *pu2Temp = 0x0001; - pRetPar[4] = 0x05; /* LMP/PAL_Version */ - pu2Temp = (u16 *)&pRetPar[5]; /* Manufacturer_Name */ - *pu2Temp = 0x005d; - pu2Temp = (u16 *)&pRetPar[7]; /* LMP/PAL_Subversion */ - *pu2Temp = 0x0001; - len += 9; - PPacketIrpEvent->Length = len; - - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("LOCAL_VERSION_INFORMATION\n")); - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("Status %x\n", status)); - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("HCI_Version = 0x05\n")); - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("HCI_Revision = 0x0001\n")); - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("LMP/PAL_Version = 0x05\n")); - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("Manufacturer_Name = 0x0001\n")); - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("LMP/PAL_Subversion = 0x0001\n")); - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - - return status; -} - -/* 7.4.7 */ -static enum hci_status bthci_CmdReadDataBlockSize(struct rtw_adapter *padapter) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - u8 localBuf[TmpLocalBufSize] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u16 *pu2Temp; - - PlatformZeroMemory(&localBuf[0], TmpLocalBufSize); - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_INFORMATIONAL_PARAMETERS, - HCI_READ_DATA_BLOCK_SIZE, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = HCI_STATUS_SUCCESS; /* status */ - pu2Temp = (u16 *)&pRetPar[1]; /* Max_ACL_Data_Packet_Length */ - *pu2Temp = Max80211PALPDUSize; - - pu2Temp = (u16 *)&pRetPar[3]; /* Data_Block_Length */ - *pu2Temp = Max80211PALPDUSize; - pu2Temp = (u16 *)&pRetPar[5]; /* Total_Num_Data_Blocks */ - *pu2Temp = BTTotalDataBlockNum; - len += 7; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - - return status; -} - -/* 7.4.5 */ -static enum hci_status bthci_CmdReadBufferSize(struct rtw_adapter *padapter) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - u8 localBuf[TmpLocalBufSize] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u16 *pu2Temp; - - PlatformZeroMemory(&localBuf[0], TmpLocalBufSize); - /* PPacketIrpEvent = (struct packet_irp_hcievent_data *)(buffer); */ - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_INFORMATIONAL_PARAMETERS, - HCI_READ_BUFFER_SIZE, - status); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Synchronous_Data_Packet_Length = 0x%x\n", BTSynDataPacketLength)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Total_Num_ACL_Data_Packets = 0x%x\n", BTTotalDataBlockNum)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Total_Num_Synchronous_Data_Packets = 0x%x\n", BTTotalDataBlockNum)); - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - pu2Temp = (u16 *)&pRetPar[1]; /* HC_ACL_Data_Packet_Length */ - *pu2Temp = Max80211PALPDUSize; - - pRetPar[3] = BTSynDataPacketLength; /* HC_Synchronous_Data_Packet_Length */ - pu2Temp = (u16 *)&pRetPar[4]; /* HC_Total_Num_ACL_Data_Packets */ - *pu2Temp = BTTotalDataBlockNum; - pu2Temp = (u16 *)&pRetPar[6]; /* HC_Total_Num_Synchronous_Data_Packets */ - *pu2Temp = BTTotalDataBlockNum; - len += 8; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - - return status; -} - -static enum hci_status bthci_CmdReadLocalAMPInfo(struct rtw_adapter *padapter) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct pwrctrl_priv *ppwrctrl = &padapter->pwrctrlpriv; - u8 localBuf[TmpLocalBufSize] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u16 *pu2Temp; - u32 *pu4Temp; - u32 TotalBandwidth = BTTOTALBANDWIDTH, MaxBandGUBandwidth = BTMAXBANDGUBANDWIDTH; - u8 ControlType = 0x01, AmpStatus = 0x01; - u32 MaxFlushTimeout = 10000, BestEffortFlushTimeout = 5000; - u16 MaxPDUSize = Max80211PALPDUSize, PalCap = 0x1, AmpAssocLen = Max80211AMPASSOCLen, MinLatency = 20; - - if ((ppwrctrl->rfoff_reason & RF_CHANGE_BY_HW) || - (ppwrctrl->rfoff_reason & RF_CHANGE_BY_SW)) { - AmpStatus = AMP_STATUS_NO_CAPACITY_FOR_BT; - } - - PlatformZeroMemory(&localBuf[0], TmpLocalBufSize); - /* PPacketIrpEvent = (struct packet_irp_hcievent_data *)(buffer); */ - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_STATUS_PARAMETERS, - HCI_READ_LOCAL_AMP_INFO, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - pRetPar[1] = AmpStatus; /* AMP_Status */ - pu4Temp = (u32 *)&pRetPar[2]; /* Total_Bandwidth */ - *pu4Temp = TotalBandwidth; /* 0x19bfcc00;0x7530; */ - pu4Temp = (u32 *)&pRetPar[6]; /* Max_Guaranteed_Bandwidth */ - *pu4Temp = MaxBandGUBandwidth; /* 0x19bfcc00;0x4e20; */ - pu4Temp = (u32 *)&pRetPar[10]; /* Min_Latency */ - *pu4Temp = MinLatency; /* 150; */ - pu4Temp = (u32 *)&pRetPar[14]; /* Max_PDU_Size */ - *pu4Temp = MaxPDUSize; - pRetPar[18] = ControlType; /* Controller_Type */ - pu2Temp = (u16 *)&pRetPar[19]; /* PAL_Capabilities */ - *pu2Temp = PalCap; - pu2Temp = (u16 *)&pRetPar[21]; /* AMP_ASSOC_Length */ - *pu2Temp = AmpAssocLen; - pu4Temp = (u32 *)&pRetPar[23]; /* Max_Flush_Timeout */ - *pu4Temp = MaxFlushTimeout; - pu4Temp = (u32 *)&pRetPar[27]; /* Best_Effort_Flush_Timeout */ - *pu4Temp = BestEffortFlushTimeout; - len += 31; - PPacketIrpEvent->Length = len; - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("AmpStatus = 0x%x\n", - AmpStatus)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("TotalBandwidth = 0x%x, MaxBandGUBandwidth = 0x%x, MinLatency = 0x%x, \n MaxPDUSize = 0x%x, ControlType = 0x%x\n", - TotalBandwidth, MaxBandGUBandwidth, MinLatency, MaxPDUSize, ControlType)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("PalCap = 0x%x, AmpAssocLen = 0x%x, MaxFlushTimeout = 0x%x, BestEffortFlushTimeout = 0x%x\n", - PalCap, AmpAssocLen, MaxFlushTimeout, BestEffortFlushTimeout)); - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - return status; -} - -static enum hci_status -bthci_CmdCreatePhysicalLink( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_dgb *pBtDbg = &pBTInfo->BtDbg; - - pBtDbg->dbgHciInfo.hciCmdCntCreatePhyLink++; - - return bthci_BuildPhysicalLink(padapter, - pHciCmd, HCI_CREATE_PHYSICAL_LINK); -} - -static enum hci_status -bthci_CmdReadLinkQuality( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - u16 PLH; - u8 EntryNum, LinkQuality = 0x55; - - PLH = *((u16 *)&pHciCmd->Data[0]); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("PLH = 0x%x\n", PLH)); - - EntryNum = bthci_GetCurrentEntryNum(padapter, (u8)PLH); - if (EntryNum == 0xff) { - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("No such PLH(0x%x)\n", PLH)); - status = HCI_STATUS_UNKNOW_CONNECT_ID; - } - - { - u8 localBuf[11] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_STATUS_PARAMETERS, - HCI_READ_LINK_QUALITY, - status); - - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, (" PLH = 0x%x\n Link Quality = 0x%x\n", PLH, LinkQuality)); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - *((u16 *)&pRetPar[1]) = pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle; /* Handle */ - pRetPar[3] = 0x55; /* Link Quailty */ - len += 4; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdCreateLogicalLink( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_dgb *pBtDbg = &pBTInfo->BtDbg; - - pBtDbg->dbgHciInfo.hciCmdCntCreateLogLink++; - - bthci_BuildLogicalLink(padapter, pHciCmd, - HCI_CREATE_LOGICAL_LINK); - - return HCI_STATUS_SUCCESS; -} - -static enum hci_status -bthci_CmdAcceptLogicalLink( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_dgb *pBtDbg = &pBTInfo->BtDbg; - - pBtDbg->dbgHciInfo.hciCmdCntAcceptLogLink++; - - bthci_BuildLogicalLink(padapter, pHciCmd, - HCI_ACCEPT_LOGICAL_LINK); - - return HCI_STATUS_SUCCESS; -} - -static enum hci_status -bthci_CmdDisconnectLogicalLink( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct bt_30info *pBTinfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTinfo->BtMgnt; - struct bt_dgb *pBtDbg = &pBTinfo->BtDbg; - u16 logicHandle; - u8 i, j, find = 0, LogLinkCount = 0; - - pBtDbg->dbgHciInfo.hciCmdCntDisconnectLogLink++; - - logicHandle = *((u16 *)pHciCmd->Data); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("DisconnectLogicalLink, logicHandle = 0x%x\n", logicHandle)); - - /* find an created logical link index and clear the data */ - for (j = 0; j < MAX_BT_ASOC_ENTRY_NUM; j++) { - for (i = 0; i < MAX_LOGICAL_LINK_NUM; i++) { - if (pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].BtLogLinkhandle == logicHandle) { - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("DisconnectLogicalLink, logicHandle is matched 0x%x\n", logicHandle)); - bthci_ResetFlowSpec(padapter, j, i); - find = 1; - pBtMgnt->DisconnectEntryNum = j; - break; - } - } - } - - if (!find) - status = HCI_STATUS_UNKNOW_CONNECT_ID; - - /* To check each */ - for (i = 0; i < MAX_LOGICAL_LINK_NUM; i++) { - if (pBTinfo->BtAsocEntry[pBtMgnt->DisconnectEntryNum].LogLinkCmdData[i].BtLogLinkhandle != 0) - LogLinkCount++; - } - - /* When we receive Create logical link command, we should send command status event first. */ - bthci_EventCommandStatus(padapter, - LINK_CONTROL_COMMANDS, - HCI_DISCONNECT_LOGICAL_LINK, - status); - /* */ - /* When we determines the logical link is established, we should send command complete event. */ - /* */ - if (status == HCI_STATUS_SUCCESS) { - bthci_EventDisconnectLogicalLinkComplete(padapter, status, - logicHandle, HCI_STATUS_CONNECT_TERMINATE_LOCAL_HOST); - } - - if (LogLinkCount == 0) - mod_timer(&pBTinfo->BTDisconnectPhyLinkTimer, - jiffies + msecs_to_jiffies(100)); - - return status; -} - -static enum hci_status -bthci_CmdLogicalLinkCancel(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTinfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTinfo->BtMgnt; - u8 CurrentEntryNum, CurrentLogEntryNum; - - u8 physicalLinkHandle, TxFlowSpecID, i; - u16 CurrentLogicalHandle; - - physicalLinkHandle = *((u8 *)pHciCmd->Data); - TxFlowSpecID = *(((u8 *)pHciCmd->Data)+1); - - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("LogicalLinkCancel, physicalLinkHandle = 0x%x, TxFlowSpecID = 0x%x\n", - physicalLinkHandle, TxFlowSpecID)); - - CurrentEntryNum = pBtMgnt->CurrentConnectEntryNum; - CurrentLogicalHandle = pBtMgnt->BtCurrentLogLinkhandle; - - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("CurrentEntryNum = 0x%x, CurrentLogicalHandle = 0x%x\n", - CurrentEntryNum, CurrentLogicalHandle)); - - CurrentLogEntryNum = 0xff; - for (i = 0; i < MAX_LOGICAL_LINK_NUM; i++) { - if ((CurrentLogicalHandle == pBTinfo->BtAsocEntry[CurrentEntryNum].LogLinkCmdData[i].BtLogLinkhandle) && - (physicalLinkHandle == pBTinfo->BtAsocEntry[CurrentEntryNum].LogLinkCmdData[i].BtPhyLinkhandle)) { - CurrentLogEntryNum = i; - break; - } - } - - if (CurrentLogEntryNum == 0xff) { - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("LogicalLinkCancel, CurrentLogEntryNum == 0xff !!!!\n")); - status = HCI_STATUS_UNKNOW_CONNECT_ID; - return status; - } else { - if (pBTinfo->BtAsocEntry[CurrentEntryNum].LogLinkCmdData[CurrentLogEntryNum].bLLCompleteEventIsSet) { - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("LogicalLinkCancel, LLCompleteEventIsSet!!!!\n")); - status = HCI_STATUS_ACL_CONNECT_EXISTS; - } - } - - { - u8 localBuf[8] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - LINK_CONTROL_COMMANDS, - HCI_LOGICAL_LINK_CANCEL, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - pRetPar[1] = pBTinfo->BtAsocEntry[CurrentEntryNum].LogLinkCmdData[CurrentLogEntryNum].BtPhyLinkhandle; - pRetPar[2] = pBTinfo->BtAsocEntry[CurrentEntryNum].LogLinkCmdData[CurrentLogEntryNum].BtTxFlowSpecID; - len += 3; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - pBTinfo->BtAsocEntry[CurrentEntryNum].LogLinkCmdData[CurrentLogEntryNum].bLLCancelCMDIsSetandComplete = true; - - return status; -} - -static enum hci_status -bthci_CmdFlowSpecModify(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct bt_30info *pBTinfo = GET_BT_INFO(padapter); - u8 i, j, find = 0; - u16 logicHandle; - - logicHandle = *((u16 *)pHciCmd->Data); - /* find an matched logical link index and copy the data */ - for (j = 0; j < MAX_BT_ASOC_ENTRY_NUM; j++) { - for (i = 0; i < MAX_LOGICAL_LINK_NUM; i++) { - if (pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].BtLogLinkhandle == logicHandle) { - memcpy(&pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].Tx_Flow_Spec, - &pHciCmd->Data[2], sizeof(struct hci_flow_spec)); - memcpy(&pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].Rx_Flow_Spec, - &pHciCmd->Data[18], sizeof(struct hci_flow_spec)); - - bthci_CheckLogLinkBehavior(padapter, pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].Tx_Flow_Spec); - find = 1; - break; - } - } - } - RTPRINT(FIOCTL, IOCTL_BT_LOGO, ("FlowSpecModify, LLH = 0x%x, \n", logicHandle)); - - /* When we receive Flow Spec Modify command, we should send command status event first. */ - bthci_EventCommandStatus(padapter, - LINK_CONTROL_COMMANDS, - HCI_FLOW_SPEC_MODIFY, - HCI_STATUS_SUCCESS); - - if (!find) - status = HCI_STATUS_UNKNOW_CONNECT_ID; - - bthci_EventSendFlowSpecModifyComplete(padapter, status, logicHandle); - - return status; -} - -static enum hci_status -bthci_CmdAcceptPhysicalLink(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_dgb *pBtDbg = &pBTInfo->BtDbg; - - pBtDbg->dbgHciInfo.hciCmdCntAcceptPhyLink++; - - return bthci_BuildPhysicalLink(padapter, - pHciCmd, HCI_ACCEPT_PHYSICAL_LINK); -} - -static enum hci_status -bthci_CmdDisconnectPhysicalLink(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_dgb *pBtDbg = &pBTInfo->BtDbg; - u8 PLH, CurrentEntryNum, PhysLinkDisconnectReason; - - pBtDbg->dbgHciInfo.hciCmdCntDisconnectPhyLink++; - - PLH = *((u8 *)pHciCmd->Data); - PhysLinkDisconnectReason = *((u8 *)pHciCmd->Data+1); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_DISCONNECT_PHYSICAL_LINK PhyHandle = 0x%x, Reason = 0x%x\n", - PLH, PhysLinkDisconnectReason)); - - CurrentEntryNum = bthci_GetCurrentEntryNum(padapter, PLH); - - if (CurrentEntryNum == 0xff) { - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, - ("DisconnectPhysicalLink, No such Handle in the Entry\n")); - status = HCI_STATUS_UNKNOW_CONNECT_ID; - } else { - pBTInfo->BtAsocEntry[CurrentEntryNum].PhyLinkDisconnectReason = - (enum hci_status)PhysLinkDisconnectReason; - } - /* Send HCI Command status event to AMP. */ - bthci_EventCommandStatus(padapter, LINK_CONTROL_COMMANDS, - HCI_DISCONNECT_PHYSICAL_LINK, status); - - if (status != HCI_STATUS_SUCCESS) - return status; - - /* The macros below require { and } in the if statement */ - if (pBTInfo->BtAsocEntry[CurrentEntryNum].BtCurrentState == HCI_STATE_DISCONNECTED) { - BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTED, STATE_CMD_DISCONNECT_PHY_LINK, CurrentEntryNum); - } else { - BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTING, STATE_CMD_DISCONNECT_PHY_LINK, CurrentEntryNum); - } - return status; -} - -static enum hci_status -bthci_CmdSetACLLinkDataFlowMode(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - u8 localBuf[8] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u16 *pu2Temp; - - pBtMgnt->ExtConfig.CurrentConnectHandle = *((u16 *)pHciCmd->Data); - pBtMgnt->ExtConfig.CurrentIncomingTrafficMode = *((u8 *)pHciCmd->Data)+2; - pBtMgnt->ExtConfig.CurrentOutgoingTrafficMode = *((u8 *)pHciCmd->Data)+3; - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("Connection Handle = 0x%x, Incoming Traffic mode = 0x%x, Outgoing Traffic mode = 0x%x", - pBtMgnt->ExtConfig.CurrentConnectHandle, - pBtMgnt->ExtConfig.CurrentIncomingTrafficMode, - pBtMgnt->ExtConfig.CurrentOutgoingTrafficMode)); - - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_EXTENSION, - HCI_SET_ACL_LINK_DATA_FLOW_MODE, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - - pu2Temp = (u16 *)&pRetPar[1]; - *pu2Temp = pBtMgnt->ExtConfig.CurrentConnectHandle; - len += 3; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - return status; -} - -static enum hci_status -bthci_CmdSetACLLinkStatus(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - struct bt_dgb *pBtDbg = &pBTInfo->BtDbg; - u8 i; - u8 *pTriple; - - pBtDbg->dbgHciInfo.hciCmdCntSetAclLinkStatus++; - RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_EXT, "SetACLLinkStatus, Hex Data :\n", - &pHciCmd->Data[0], pHciCmd->Length); - - /* Only Core Stack v251 and later version support this command. */ - pBtMgnt->bSupportProfile = true; - - pBtMgnt->ExtConfig.NumberOfHandle = *((u8 *)pHciCmd->Data); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("NumberOfHandle = 0x%x\n", pBtMgnt->ExtConfig.NumberOfHandle)); - - pTriple = &pHciCmd->Data[1]; - for (i = 0; i < pBtMgnt->ExtConfig.NumberOfHandle; i++) { - pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle = *((u16 *)&pTriple[0]); - pBtMgnt->ExtConfig.linkInfo[i].IncomingTrafficMode = pTriple[2]; - pBtMgnt->ExtConfig.linkInfo[i].OutgoingTrafficMode = pTriple[3]; - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, - ("Connection_Handle = 0x%x, Incoming Traffic mode = 0x%x, Outgoing Traffic Mode = 0x%x\n", - pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle, - pBtMgnt->ExtConfig.linkInfo[i].IncomingTrafficMode, - pBtMgnt->ExtConfig.linkInfo[i].OutgoingTrafficMode)); - pTriple += 4; - } - - { - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_EXTENSION, - HCI_SET_ACL_LINK_STATUS, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdSetSCOLinkStatus( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - struct bt_dgb *pBtDbg = &pBTInfo->BtDbg; - - pBtDbg->dbgHciInfo.hciCmdCntSetScoLinkStatus++; - pBtMgnt->ExtConfig.NumberOfSCO = *((u8 *)pHciCmd->Data); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("NumberOfSCO = 0x%x\n", - pBtMgnt->ExtConfig.NumberOfSCO)); - - { - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_EXTENSION, - HCI_SET_SCO_LINK_STATUS, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdSetRSSIValue( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - s8 min_bt_rssi = 0; - u8 i; - for (i = 0; i < pBtMgnt->ExtConfig.NumberOfHandle; i++) { - if (pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle == *((u16 *)&pHciCmd->Data[0])) { - pBtMgnt->ExtConfig.linkInfo[i].BT_RSSI = (s8)(pHciCmd->Data[2]); - RTPRINT(FIOCTL, IOCTL_BT_EVENT_PERIODICAL, - ("Connection_Handle = 0x%x, RSSI = %d \n", - pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle, - pBtMgnt->ExtConfig.linkInfo[i].BT_RSSI)); - } - /* get the minimum bt rssi value */ - if (pBtMgnt->ExtConfig.linkInfo[i].BT_RSSI <= min_bt_rssi) - min_bt_rssi = pBtMgnt->ExtConfig.linkInfo[i].BT_RSSI; - } - - pBtMgnt->ExtConfig.MIN_BT_RSSI = min_bt_rssi; - RTPRINT(FBT, BT_TRACE, ("[bt rssi], the min rssi is %d\n", min_bt_rssi)); - - { - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_EXTENSION, - HCI_SET_RSSI_VALUE, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdSetCurrentBluetoothStatus( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - pBtMgnt->ExtConfig.CurrentBTStatus = *((u8 *)&pHciCmd->Data[0]); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("SetCurrentBluetoothStatus, CurrentBTStatus = 0x%x\n", - pBtMgnt->ExtConfig.CurrentBTStatus)); - - { - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_EXTENSION, - HCI_SET_CURRENT_BLUETOOTH_STATUS, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - len += 1; - - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdExtensionVersionNotify( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - struct bt_dgb *pBtDbg = &pBTInfo->BtDbg; - - pBtDbg->dbgHciInfo.hciCmdCntExtensionVersionNotify++; - RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_EXT, "ExtensionVersionNotify, Hex Data :\n", - &pHciCmd->Data[0], pHciCmd->Length); - - pBtMgnt->ExtConfig.HCIExtensionVer = *((u16 *)&pHciCmd->Data[0]); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCIExtensionVer = 0x%x\n", pBtMgnt->ExtConfig.HCIExtensionVer)); - - { - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_EXTENSION, - HCI_EXTENSION_VERSION_NOTIFY, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdLinkStatusNotify( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - struct bt_dgb *pBtDbg = &pBTInfo->BtDbg; - u8 i; - u8 *pTriple; - - pBtDbg->dbgHciInfo.hciCmdCntLinkStatusNotify++; - RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_EXT, "LinkStatusNotify, Hex Data :\n", - &pHciCmd->Data[0], pHciCmd->Length); - - /* Current only RTL8723 support this command. */ - pBtMgnt->bSupportProfile = true; - - pBtMgnt->ExtConfig.NumberOfHandle = *((u8 *)pHciCmd->Data); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("NumberOfHandle = 0x%x\n", pBtMgnt->ExtConfig.NumberOfHandle)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCIExtensionVer = %d\n", pBtMgnt->ExtConfig.HCIExtensionVer)); - - pTriple = &pHciCmd->Data[1]; - for (i = 0; i < pBtMgnt->ExtConfig.NumberOfHandle; i++) { - if (pBtMgnt->ExtConfig.HCIExtensionVer < 1) { - pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle = *((u16 *)&pTriple[0]); - pBtMgnt->ExtConfig.linkInfo[i].BTProfile = pTriple[2]; - pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec = pTriple[3]; - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, - ("Connection_Handle = 0x%x, BTProfile =%d, BTSpec =%d\n", - pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle, - pBtMgnt->ExtConfig.linkInfo[i].BTProfile, - pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec)); - pTriple += 4; - } else { - pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle = *((u16 *)&pTriple[0]); - pBtMgnt->ExtConfig.linkInfo[i].BTProfile = pTriple[2]; - pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec = pTriple[3]; - pBtMgnt->ExtConfig.linkInfo[i].linkRole = pTriple[4]; - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, - ("Connection_Handle = 0x%x, BTProfile =%d, BTSpec =%d, LinkRole =%d\n", - pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle, - pBtMgnt->ExtConfig.linkInfo[i].BTProfile, - pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec, - pBtMgnt->ExtConfig.linkInfo[i].linkRole)); - pTriple += 5; - } - - } - BTHCI_UpdateBTProfileRTKToMoto(padapter); - { - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_EXTENSION, - HCI_LINK_STATUS_NOTIFY, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdBtOperationNotify( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_EXT, "Bt Operation notify, Hex Data :\n", - &pHciCmd->Data[0], pHciCmd->Length); - - pBtMgnt->ExtConfig.btOperationCode = *((u8 *)pHciCmd->Data); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("btOperationCode = 0x%x\n", pBtMgnt->ExtConfig.btOperationCode)); - switch (pBtMgnt->ExtConfig.btOperationCode) { - case HCI_BT_OP_NONE: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Operation None!!\n")); - break; - case HCI_BT_OP_INQUIRY_START: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Inquire start!!\n")); - break; - case HCI_BT_OP_INQUIRY_FINISH: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Inquire finished!!\n")); - break; - case HCI_BT_OP_PAGING_START: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Paging is started!!\n")); - break; - case HCI_BT_OP_PAGING_SUCCESS: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Paging complete successfully!!\n")); - break; - case HCI_BT_OP_PAGING_UNSUCCESS: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Paging complete unsuccessfully!!\n")); - break; - case HCI_BT_OP_PAIRING_START: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Pairing start!!\n")); - break; - case HCI_BT_OP_PAIRING_FINISH: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Pairing finished!!\n")); - break; - case HCI_BT_OP_BT_DEV_ENABLE: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : BT Device is enabled!!\n")); - break; - case HCI_BT_OP_BT_DEV_DISABLE: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : BT Device is disabled!!\n")); - break; - default: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Unknown, error!!\n")); - break; - } - BTDM_AdjustForBtOperation(padapter); - { - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_EXTENSION, - HCI_BT_OPERATION_NOTIFY, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdEnableWifiScanNotify(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_EXT, "Enable Wifi scan notify, Hex Data :\n", - &pHciCmd->Data[0], pHciCmd->Length); - - pBtMgnt->ExtConfig.bEnableWifiScanNotify = *((u8 *)pHciCmd->Data); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("bEnableWifiScanNotify = %d\n", pBtMgnt->ExtConfig.bEnableWifiScanNotify)); - - { - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_EXTENSION, - HCI_ENABLE_WIFI_SCAN_NOTIFY, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdWIFICurrentChannel(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - u8 chnl = pmlmeext->cur_channel; - - if (pmlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40) { - if (pmlmeext->cur_ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER) - chnl += 2; - else if (pmlmeext->cur_ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER) - chnl -= 2; - } - - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("Current Channel = 0x%x\n", chnl)); - - { - u8 localBuf[8] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_EXTENSION, - HCI_WIFI_CURRENT_CHANNEL, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - pRetPar[1] = chnl; /* current channel */ - len += 2; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdWIFICurrentBandwidth(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - enum ht_channel_width bw; - u8 CurrentBW = 0; - - bw = padapter->mlmeextpriv.cur_bwmode; - - if (bw == HT_CHANNEL_WIDTH_20) - CurrentBW = 0; - else if (bw == HT_CHANNEL_WIDTH_40) - CurrentBW = 1; - - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("Current BW = 0x%x\n", - CurrentBW)); - - { - u8 localBuf[8] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_EXTENSION, - HCI_WIFI_CURRENT_BANDWIDTH, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - pRetPar[1] = CurrentBW; /* current BW */ - len += 2; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdWIFIConnectionStatus( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - u8 connectStatus = HCI_WIFI_NOT_CONNECTED; - - if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE)) { - if (padapter->stapriv.asoc_sta_count >= 3) - connectStatus = HCI_WIFI_CONNECTED; - else - connectStatus = HCI_WIFI_NOT_CONNECTED; - } else if (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE|WIFI_ASOC_STATE)) { - connectStatus = HCI_WIFI_CONNECTED; - } else if (check_fwstate(&padapter->mlmepriv, WIFI_UNDER_LINKING)) { - connectStatus = HCI_WIFI_CONNECT_IN_PROGRESS; - } else { - connectStatus = HCI_WIFI_NOT_CONNECTED; - } - - { - u8 localBuf[8] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_EXTENSION, - HCI_WIFI_CONNECTION_STATUS, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - pRetPar[1] = connectStatus; /* connect status */ - len += 2; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdEnableDeviceUnderTestMode( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - - pBtHciInfo->bInTestMode = true; - pBtHciInfo->bTestIsEnd = false; - - /* send command complete event here when all data are received. */ - { - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_TESTING_COMMANDS, - HCI_ENABLE_DEVICE_UNDER_TEST_MODE, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdAMPTestEnd(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - - if (!pBtHciInfo->bInTestMode) { - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Not in Test mode, return status = HCI_STATUS_CMD_DISALLOW\n")); - status = HCI_STATUS_CMD_DISALLOW; - return status; - } - - pBtHciInfo->bTestIsEnd = true; - - del_timer_sync(&pBTInfo->BTTestSendPacketTimer); - - rtl8723a_check_bssid(padapter, true); - - /* send command complete event here when all data are received. */ - { - u8 localBuf[4] = ""; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("AMP Test End Event \n")); - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - PPacketIrpEvent->EventCode = HCI_EVENT_AMP_TEST_END; - PPacketIrpEvent->Length = 2; - - PPacketIrpEvent->Data[0] = status; - PPacketIrpEvent->Data[1] = pBtHciInfo->TestScenario; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, 4); - } - - bthci_EventAMPReceiverReport(padapter, 0x01); - - return status; -} - -static enum hci_status -bthci_CmdAMPTestCommand(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - - if (!pBtHciInfo->bInTestMode) { - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Not in Test mode, return status = HCI_STATUS_CMD_DISALLOW\n")); - status = HCI_STATUS_CMD_DISALLOW; - return status; - } - - pBtHciInfo->TestScenario = *((u8 *)pHciCmd->Data); - - if (pBtHciInfo->TestScenario == 0x01) - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("TX Single Test \n")); - else if (pBtHciInfo->TestScenario == 0x02) - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Receive Frame Test \n")); - else - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("No Such Test !!!!!!!!!!!!!!!!!! \n")); - - if (pBtHciInfo->bTestIsEnd) { - u8 localBuf[5] = ""; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("AMP Test End Event \n")); - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - PPacketIrpEvent->EventCode = HCI_EVENT_AMP_TEST_END; - PPacketIrpEvent->Length = 2; - - PPacketIrpEvent->Data[0] = status; - PPacketIrpEvent->Data[1] = pBtHciInfo->TestScenario ; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, 4); - - /* Return to Idel state with RX and TX off. */ - - return status; - } - - /* should send command status event */ - bthci_EventCommandStatus(padapter, - OGF_TESTING_COMMANDS, - HCI_AMP_TEST_COMMAND, - status); - - /* The HCI_AMP_Start Test Event shall be generated when the */ - /* HCI_AMP_Test_Command has completed and the first data is ready to be sent */ - /* or received. */ - - { - u8 localBuf[5] = ""; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), (" HCI_AMP_Start Test Event \n")); - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - PPacketIrpEvent->EventCode = HCI_EVENT_AMP_START_TEST; - PPacketIrpEvent->Length = 2; - - PPacketIrpEvent->Data[0] = status; - PPacketIrpEvent->Data[1] = pBtHciInfo->TestScenario ; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, 4); - - /* Return to Idel state with RX and TX off. */ - } - - if (pBtHciInfo->TestScenario == 0x01) { - /* - When in a transmitter test scenario and the frames/bursts count have been - transmitted the HCI_AMP_Test_End event shall be sent. - */ - mod_timer(&pBTInfo->BTTestSendPacketTimer, - jiffies + msecs_to_jiffies(50)); - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("TX Single Test \n")); - } else if (pBtHciInfo->TestScenario == 0x02) { - rtl8723a_check_bssid(padapter, false); - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Receive Frame Test \n")); - } - - return status; -} - -static enum hci_status -bthci_CmdEnableAMPReceiverReports(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - - if (!pBtHciInfo->bInTestMode) { - status = HCI_STATUS_CMD_DISALLOW; - /* send command complete event here when all data are received. */ - { - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_TESTING_COMMANDS, - HCI_ENABLE_AMP_RECEIVER_REPORTS, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - return status; - } - - pBtHciInfo->bTestNeedReport = *((u8 *)pHciCmd->Data); - pBtHciInfo->TestReportInterval = (*((u8 *)pHciCmd->Data+2)); - - bthci_EventAMPReceiverReport(padapter, 0x00); - - /* send command complete event here when all data are received. */ - { - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_TESTING_COMMANDS, - HCI_ENABLE_AMP_RECEIVER_REPORTS, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - } - - return status; -} - -static enum hci_status -bthci_CmdHostBufferSize(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - struct packet_irp_hcievent_data *PPacketIrpEvent; - enum hci_status status = HCI_STATUS_SUCCESS; - u8 localBuf[6] = ""; - u8 *pRetPar; - u8 len = 0; - - pBTInfo->BtAsocEntry[pBtMgnt->CurrentConnectEntryNum].ACLPacketsData.ACLDataPacketLen = *((u16 *)pHciCmd->Data); - pBTInfo->BtAsocEntry[pBtMgnt->CurrentConnectEntryNum].SyncDataPacketLen = *((u8 *)(pHciCmd->Data+2)); - pBTInfo->BtAsocEntry[pBtMgnt->CurrentConnectEntryNum].TotalNumACLDataPackets = *((u16 *)(pHciCmd->Data+3)); - pBTInfo->BtAsocEntry[pBtMgnt->CurrentConnectEntryNum].TotalSyncNumDataPackets = *((u16 *)(pHciCmd->Data+5)); - - /* send command complete event here when all data are received. */ - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - len += bthci_CommandCompleteHeader(&localBuf[0], - OGF_SET_EVENT_MASK_COMMAND, - HCI_HOST_BUFFER_SIZE, - status); - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[len]; - pRetPar[0] = status; /* status */ - len += 1; - PPacketIrpEvent->Length = len; - - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); - - return status; -} - -static enum hci_status -bthci_UnknownCMD(struct rtw_adapter *padapter, struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_UNKNOW_HCI_CMD; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_dgb *pBtDbg = &pBTInfo->BtDbg; - - pBtDbg->dbgHciInfo.hciCmdCntUnknown++; - bthci_EventCommandStatus(padapter, - (u8)pHciCmd->OGF, - pHciCmd->OCF, - status); - - return status; -} - -static enum hci_status -bthci_HandleOGFInformationalParameters(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - - switch (pHciCmd->OCF) { - case HCI_READ_LOCAL_VERSION_INFORMATION: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LOCAL_VERSION_INFORMATION\n")); - status = bthci_CmdReadLocalVersionInformation(padapter); - break; - case HCI_READ_LOCAL_SUPPORTED_COMMANDS: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LOCAL_SUPPORTED_COMMANDS\n")); - status = bthci_CmdReadLocalSupportedCommands(padapter); - break; - case HCI_READ_LOCAL_SUPPORTED_FEATURES: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LOCAL_SUPPORTED_FEATURES\n")); - status = bthci_CmdReadLocalSupportedFeatures(padapter); - break; - case HCI_READ_BUFFER_SIZE: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_BUFFER_SIZE\n")); - status = bthci_CmdReadBufferSize(padapter); - break; - case HCI_READ_DATA_BLOCK_SIZE: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_DATA_BLOCK_SIZE\n")); - status = bthci_CmdReadDataBlockSize(padapter); - break; - default: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("bthci_HandleOGFInformationalParameters(), Unknown case = 0x%x\n", pHciCmd->OCF)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_UNKNOWN_COMMAND\n")); - status = bthci_UnknownCMD(padapter, pHciCmd); - break; - } - return status; -} - -static enum hci_status -bthci_HandleOGFSetEventMaskCMD(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - - switch (pHciCmd->OCF) { - case HCI_SET_EVENT_MASK: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_SET_EVENT_MASK\n")); - status = bthci_CmdSetEventMask(padapter, pHciCmd); - break; - case HCI_RESET: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_RESET\n")); - status = bthci_CmdReset(padapter, true); - break; - case HCI_READ_CONNECTION_ACCEPT_TIMEOUT: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_CONNECTION_ACCEPT_TIMEOUT\n")); - status = bthci_CmdReadConnectionAcceptTimeout(padapter); - break; - case HCI_SET_EVENT_FILTER: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_SET_EVENT_FILTER\n")); - break; - case HCI_WRITE_CONNECTION_ACCEPT_TIMEOUT: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_CONNECTION_ACCEPT_TIMEOUT\n")); - status = bthci_CmdWriteConnectionAcceptTimeout(padapter, pHciCmd); - break; - case HCI_READ_PAGE_TIMEOUT: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_PAGE_TIMEOUT\n")); - status = bthci_CmdReadPageTimeout(padapter, pHciCmd); - break; - case HCI_WRITE_PAGE_TIMEOUT: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_PAGE_TIMEOUT\n")); - status = bthci_CmdWritePageTimeout(padapter, pHciCmd); - break; - case HCI_HOST_NUMBER_OF_COMPLETED_PACKETS: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_HOST_NUMBER_OF_COMPLETED_PACKETS\n")); - break; - case HCI_READ_LINK_SUPERVISION_TIMEOUT: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LINK_SUPERVISION_TIMEOUT\n")); - status = bthci_CmdReadLinkSupervisionTimeout(padapter, pHciCmd); - break; - case HCI_WRITE_LINK_SUPERVISION_TIMEOUT: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_LINK_SUPERVISION_TIMEOUT\n")); - status = bthci_CmdWriteLinkSupervisionTimeout(padapter, pHciCmd); - break; - case HCI_ENHANCED_FLUSH: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_ENHANCED_FLUSH\n")); - status = bthci_CmdEnhancedFlush(padapter, pHciCmd); - break; - case HCI_READ_LOGICAL_LINK_ACCEPT_TIMEOUT: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LOGICAL_LINK_ACCEPT_TIMEOUT\n")); - status = bthci_CmdReadLogicalLinkAcceptTimeout(padapter, pHciCmd); - break; - case HCI_WRITE_LOGICAL_LINK_ACCEPT_TIMEOUT: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_LOGICAL_LINK_ACCEPT_TIMEOUT\n")); - status = bthci_CmdWriteLogicalLinkAcceptTimeout(padapter, pHciCmd); - break; - case HCI_SET_EVENT_MASK_PAGE_2: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_SET_EVENT_MASK_PAGE_2\n")); - status = bthci_CmdSetEventMaskPage2(padapter, pHciCmd); - break; - case HCI_READ_LOCATION_DATA: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LOCATION_DATA\n")); - status = bthci_CmdReadLocationData(padapter, pHciCmd); - break; - case HCI_WRITE_LOCATION_DATA: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_LOCATION_DATA\n")); - status = bthci_CmdWriteLocationData(padapter, pHciCmd); - break; - case HCI_READ_FLOW_CONTROL_MODE: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_FLOW_CONTROL_MODE\n")); - status = bthci_CmdReadFlowControlMode(padapter, pHciCmd); - break; - case HCI_WRITE_FLOW_CONTROL_MODE: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_FLOW_CONTROL_MODE\n")); - status = bthci_CmdWriteFlowControlMode(padapter, pHciCmd); - break; - case HCI_READ_BEST_EFFORT_FLUSH_TIMEOUT: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_BEST_EFFORT_FLUSH_TIMEOUT\n")); - status = bthci_CmdReadBestEffortFlushTimeout(padapter, pHciCmd); - break; - case HCI_WRITE_BEST_EFFORT_FLUSH_TIMEOUT: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_BEST_EFFORT_FLUSH_TIMEOUT\n")); - status = bthci_CmdWriteBestEffortFlushTimeout(padapter, pHciCmd); - break; - case HCI_SHORT_RANGE_MODE: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_SHORT_RANGE_MODE\n")); - status = bthci_CmdShortRangeMode(padapter, pHciCmd); - break; - case HCI_HOST_BUFFER_SIZE: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_HOST_BUFFER_SIZE\n")); - status = bthci_CmdHostBufferSize(padapter, pHciCmd); - break; - default: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("bthci_HandleOGFSetEventMaskCMD(), Unknown case = 0x%x\n", pHciCmd->OCF)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_UNKNOWN_COMMAND\n")); - status = bthci_UnknownCMD(padapter, pHciCmd); - break; - } - return status; -} - -static enum hci_status -bthci_HandleOGFStatusParameters(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - - switch (pHciCmd->OCF) { - case HCI_READ_FAILED_CONTACT_COUNTER: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_FAILED_CONTACT_COUNTER\n")); - status = bthci_CmdReadFailedContactCounter(padapter, pHciCmd); - break; - case HCI_RESET_FAILED_CONTACT_COUNTER: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_RESET_FAILED_CONTACT_COUNTER\n")); - status = bthci_CmdResetFailedContactCounter(padapter, pHciCmd); - break; - case HCI_READ_LINK_QUALITY: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LINK_QUALITY\n")); - status = bthci_CmdReadLinkQuality(padapter, pHciCmd); - break; - case HCI_READ_RSSI: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_RSSI\n")); - break; - case HCI_READ_LOCAL_AMP_INFO: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LOCAL_AMP_INFO\n")); - status = bthci_CmdReadLocalAMPInfo(padapter); - break; - case HCI_READ_LOCAL_AMP_ASSOC: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LOCAL_AMP_ASSOC\n")); - status = bthci_CmdReadLocalAMPAssoc(padapter, pHciCmd); - break; - case HCI_WRITE_REMOTE_AMP_ASSOC: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_REMOTE_AMP_ASSOC\n")); - status = bthci_CmdWriteRemoteAMPAssoc(padapter, pHciCmd); - break; - default: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("bthci_HandleOGFStatusParameters(), Unknown case = 0x%x\n", pHciCmd->OCF)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_UNKNOWN_COMMAND\n")); - status = bthci_UnknownCMD(padapter, pHciCmd); - break; - } - return status; -} - -static enum hci_status -bthci_HandleOGFLinkControlCMD(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - - switch (pHciCmd->OCF) { - case HCI_CREATE_PHYSICAL_LINK: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_CREATE_PHYSICAL_LINK\n")); - status = bthci_CmdCreatePhysicalLink(padapter, pHciCmd); - break; - case HCI_ACCEPT_PHYSICAL_LINK: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_ACCEPT_PHYSICAL_LINK\n")); - status = bthci_CmdAcceptPhysicalLink(padapter, pHciCmd); - break; - case HCI_DISCONNECT_PHYSICAL_LINK: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_DISCONNECT_PHYSICAL_LINK\n")); - status = bthci_CmdDisconnectPhysicalLink(padapter, pHciCmd); - break; - case HCI_CREATE_LOGICAL_LINK: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_CREATE_LOGICAL_LINK\n")); - status = bthci_CmdCreateLogicalLink(padapter, pHciCmd); - break; - case HCI_ACCEPT_LOGICAL_LINK: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_ACCEPT_LOGICAL_LINK\n")); - status = bthci_CmdAcceptLogicalLink(padapter, pHciCmd); - break; - case HCI_DISCONNECT_LOGICAL_LINK: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_DISCONNECT_LOGICAL_LINK\n")); - status = bthci_CmdDisconnectLogicalLink(padapter, pHciCmd); - break; - case HCI_LOGICAL_LINK_CANCEL: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_LOGICAL_LINK_CANCEL\n")); - status = bthci_CmdLogicalLinkCancel(padapter, pHciCmd); - break; - case HCI_FLOW_SPEC_MODIFY: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_FLOW_SPEC_MODIFY\n")); - status = bthci_CmdFlowSpecModify(padapter, pHciCmd); - break; - default: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("bthci_HandleOGFLinkControlCMD(), Unknown case = 0x%x\n", pHciCmd->OCF)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_UNKNOWN_COMMAND\n")); - status = bthci_UnknownCMD(padapter, pHciCmd); - break; - } - return status; -} - -static enum hci_status -bthci_HandleOGFTestingCMD(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - switch (pHciCmd->OCF) { - case HCI_ENABLE_DEVICE_UNDER_TEST_MODE: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_ENABLE_DEVICE_UNDER_TEST_MODE\n")); - bthci_CmdEnableDeviceUnderTestMode(padapter, pHciCmd); - break; - case HCI_AMP_TEST_END: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_AMP_TEST_END\n")); - bthci_CmdAMPTestEnd(padapter, pHciCmd); - break; - case HCI_AMP_TEST_COMMAND: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_AMP_TEST_COMMAND\n")); - bthci_CmdAMPTestCommand(padapter, pHciCmd); - break; - case HCI_ENABLE_AMP_RECEIVER_REPORTS: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_ENABLE_AMP_RECEIVER_REPORTS\n")); - bthci_CmdEnableAMPReceiverReports(padapter, pHciCmd); - break; - default: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_UNKNOWN_COMMAND\n")); - status = bthci_UnknownCMD(padapter, pHciCmd); - break; - } - return status; -} - -static enum hci_status -bthci_HandleOGFExtension(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - switch (pHciCmd->OCF) { - case HCI_SET_ACL_LINK_DATA_FLOW_MODE: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_SET_ACL_LINK_DATA_FLOW_MODE\n")); - status = bthci_CmdSetACLLinkDataFlowMode(padapter, pHciCmd); - break; - case HCI_SET_ACL_LINK_STATUS: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_SET_ACL_LINK_STATUS\n")); - status = bthci_CmdSetACLLinkStatus(padapter, pHciCmd); - break; - case HCI_SET_SCO_LINK_STATUS: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_SET_SCO_LINK_STATUS\n")); - status = bthci_CmdSetSCOLinkStatus(padapter, pHciCmd); - break; - case HCI_SET_RSSI_VALUE: - RTPRINT(FIOCTL, IOCTL_BT_EVENT_PERIODICAL, ("HCI_SET_RSSI_VALUE\n")); - status = bthci_CmdSetRSSIValue(padapter, pHciCmd); - break; - case HCI_SET_CURRENT_BLUETOOTH_STATUS: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_SET_CURRENT_BLUETOOTH_STATUS\n")); - status = bthci_CmdSetCurrentBluetoothStatus(padapter, pHciCmd); - break; - /* The following is for RTK8723 */ - - case HCI_EXTENSION_VERSION_NOTIFY: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_EXTENSION_VERSION_NOTIFY\n")); - status = bthci_CmdExtensionVersionNotify(padapter, pHciCmd); - break; - case HCI_LINK_STATUS_NOTIFY: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_LINK_STATUS_NOTIFY\n")); - status = bthci_CmdLinkStatusNotify(padapter, pHciCmd); - break; - case HCI_BT_OPERATION_NOTIFY: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_BT_OPERATION_NOTIFY\n")); - status = bthci_CmdBtOperationNotify(padapter, pHciCmd); - break; - case HCI_ENABLE_WIFI_SCAN_NOTIFY: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_ENABLE_WIFI_SCAN_NOTIFY\n")); - status = bthci_CmdEnableWifiScanNotify(padapter, pHciCmd); - break; - - /* The following is for IVT */ - case HCI_WIFI_CURRENT_CHANNEL: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_WIFI_CURRENT_CHANNEL\n")); - status = bthci_CmdWIFICurrentChannel(padapter, pHciCmd); - break; - case HCI_WIFI_CURRENT_BANDWIDTH: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_WIFI_CURRENT_BANDWIDTH\n")); - status = bthci_CmdWIFICurrentBandwidth(padapter, pHciCmd); - break; - case HCI_WIFI_CONNECTION_STATUS: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_WIFI_CONNECTION_STATUS\n")); - status = bthci_CmdWIFIConnectionStatus(padapter, pHciCmd); - break; - - default: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_UNKNOWN_COMMAND\n")); - status = bthci_UnknownCMD(padapter, pHciCmd); - break; - } - return status; -} - -static void -bthci_StateStarting(struct rtw_adapter *padapter, - enum hci_state_with_cmd StateCmd, u8 EntryNum) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT state], [Starting], ")); - switch (StateCmd) { - case STATE_CMD_CONNECT_ACCEPT_TIMEOUT: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_CONNECT_ACCEPT_TIMEOUT\n")); - pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus = HCI_STATUS_CONNECT_ACCEPT_TIMEOUT; - pBtMgnt->bNeedNotifyAMPNoCap = true; - BTHCI_DisconnectPeer(padapter, EntryNum); - break; - case STATE_CMD_DISCONNECT_PHY_LINK: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_DISCONNECT_PHY_LINK\n")); - - bthci_EventDisconnectPhyLinkComplete(padapter, - HCI_STATUS_SUCCESS, - pBTInfo->BtAsocEntry[EntryNum].PhyLinkDisconnectReason, - EntryNum); - - del_timer_sync(&pBTInfo->BTHCIJoinTimeoutTimer); - - pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus = HCI_STATUS_UNKNOW_CONNECT_ID; - - BTHCI_DisconnectPeer(padapter, EntryNum); - break; - case STATE_CMD_MAC_START_COMPLETE: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_MAC_START_COMPLETE\n")); - if (pBTInfo->BtAsocEntry[EntryNum].AMPRole == AMP_BTAP_CREATOR) - bthci_EventChannelSelected(padapter, EntryNum); - break; - default: - RTPRINT(FIOCTL, IOCTL_STATE, ("State command(%d) is Wrong !!!\n", StateCmd)); - break; - } -} - -static void -bthci_StateConnecting(struct rtw_adapter *padapter, - enum hci_state_with_cmd StateCmd, u8 EntryNum) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT state], [Connecting], ")); - switch (StateCmd) { - case STATE_CMD_CONNECT_ACCEPT_TIMEOUT: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_CONNECT_ACCEPT_TIMEOUT\n")); - pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus = HCI_STATUS_CONNECT_ACCEPT_TIMEOUT; - pBtMgnt->bNeedNotifyAMPNoCap = true; - BTHCI_DisconnectPeer(padapter, EntryNum); - break; - case STATE_CMD_MAC_CONNECT_COMPLETE: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_MAC_CONNECT_COMPLETE\n")); - - if (pBTInfo->BtAsocEntry[EntryNum].AMPRole == AMP_BTAP_JOINER) { - RT_TRACE(_module_rtl871x_security_c_, _drv_info_, - "StateConnecting\n"); - } - break; - case STATE_CMD_DISCONNECT_PHY_LINK: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_DISCONNECT_PHY_LINK\n")); - - bthci_EventDisconnectPhyLinkComplete(padapter, - HCI_STATUS_SUCCESS, - pBTInfo->BtAsocEntry[EntryNum].PhyLinkDisconnectReason, - EntryNum); - - pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus = HCI_STATUS_UNKNOW_CONNECT_ID; - - del_timer_sync(&pBTInfo->BTHCIJoinTimeoutTimer); - - BTHCI_DisconnectPeer(padapter, EntryNum); - - break; - case STATE_CMD_MAC_CONNECT_CANCEL_INDICATE: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_MAC_CONNECT_CANCEL_INDICATE\n")); - pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus = HCI_STATUS_CONTROLLER_BUSY; - /* Because this state cmd is caused by the BTHCI_EventAMPStatusChange(), */ - /* we don't need to send event in the following BTHCI_DisconnectPeer() again. */ - pBtMgnt->bNeedNotifyAMPNoCap = false; - BTHCI_DisconnectPeer(padapter, EntryNum); - break; - default: - RTPRINT(FIOCTL, IOCTL_STATE, ("State command(%d) is Wrong !!!\n", StateCmd)); - break; - } -} - -static void -bthci_StateConnected(struct rtw_adapter *padapter, - enum hci_state_with_cmd StateCmd, u8 EntryNum) -{ -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - u8 i; - u16 logicHandle = 0; - - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT state], [Connected], ")); - switch (StateCmd) { - case STATE_CMD_DISCONNECT_PHY_LINK: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_DISCONNECT_PHY_LINK\n")); - - /* When we are trying to disconnect the phy link, we should disconnect log link first, */ - for (i = 0; i < MAX_LOGICAL_LINK_NUM; i++) { - if (pBTInfo->BtAsocEntry[EntryNum].LogLinkCmdData->BtLogLinkhandle != 0) { - logicHandle = pBTInfo->BtAsocEntry[EntryNum].LogLinkCmdData->BtLogLinkhandle; - - bthci_EventDisconnectLogicalLinkComplete(padapter, HCI_STATUS_SUCCESS, - logicHandle, pBTInfo->BtAsocEntry[EntryNum].PhyLinkDisconnectReason); - - pBTInfo->BtAsocEntry[EntryNum].LogLinkCmdData->BtLogLinkhandle = 0; - } - } - - bthci_EventDisconnectPhyLinkComplete(padapter, - HCI_STATUS_SUCCESS, - pBTInfo->BtAsocEntry[EntryNum].PhyLinkDisconnectReason, - EntryNum); - - del_timer_sync(&pBTInfo->BTHCIJoinTimeoutTimer); - - BTHCI_DisconnectPeer(padapter, EntryNum); - break; - - case STATE_CMD_MAC_DISCONNECT_INDICATE: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_MAC_DISCONNECT_INDICATE\n")); - - bthci_EventDisconnectPhyLinkComplete(padapter, - HCI_STATUS_SUCCESS, - /* TODO: Remote Host not local host */ - HCI_STATUS_CONNECT_TERMINATE_LOCAL_HOST, - EntryNum); - BTHCI_DisconnectPeer(padapter, EntryNum); - - break; - case STATE_CMD_ENTER_STATE: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_ENTER_STATE\n")); - - if (pBtMgnt->bBTConnectInProgress) { - pBtMgnt->bBTConnectInProgress = false; - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], BT Connect in progress OFF!!\n")); - } - pBTInfo->BtAsocEntry[EntryNum].BtCurrentState = HCI_STATE_CONNECTED; - pBTInfo->BtAsocEntry[EntryNum].b4waySuccess = true; - pBtMgnt->bStartSendSupervisionPkt = true; - - /* for rate adaptive */ - - rtl8723a_update_ramask(padapter, - MAX_FW_SUPPORT_MACID_NUM-1-EntryNum, 0); - - HalSetBrateCfg23a(padapter, padapter->mlmepriv.cur_network.network.SupportedRates); - BTDM_SetFwChnlInfo(padapter, RT_MEDIA_CONNECT); - break; - default: - RTPRINT(FIOCTL, IOCTL_STATE, ("State command(%d) is Wrong !!!\n", StateCmd)); - break; - } -} - -static void -bthci_StateAuth(struct rtw_adapter *padapter, enum hci_state_with_cmd StateCmd, - u8 EntryNum) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT state], [Authenticating], ")); - switch (StateCmd) { - case STATE_CMD_CONNECT_ACCEPT_TIMEOUT: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_CONNECT_ACCEPT_TIMEOUT\n")); - pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus = HCI_STATUS_CONNECT_ACCEPT_TIMEOUT; - pBtMgnt->bNeedNotifyAMPNoCap = true; - BTHCI_DisconnectPeer(padapter, EntryNum); - break; - case STATE_CMD_DISCONNECT_PHY_LINK: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_DISCONNECT_PHY_LINK\n")); - bthci_EventDisconnectPhyLinkComplete(padapter, - HCI_STATUS_SUCCESS, - pBTInfo->BtAsocEntry[EntryNum].PhyLinkDisconnectReason, - EntryNum); - - pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus = HCI_STATUS_UNKNOW_CONNECT_ID; - - del_timer_sync(&pBTInfo->BTHCIJoinTimeoutTimer); - - BTHCI_DisconnectPeer(padapter, EntryNum); - break; - case STATE_CMD_4WAY_FAILED: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_4WAY_FAILED\n")); - - pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus = HCI_STATUS_AUTH_FAIL; - pBtMgnt->bNeedNotifyAMPNoCap = true; - - BTHCI_DisconnectPeer(padapter, EntryNum); - - del_timer_sync(&pBTInfo->BTHCIJoinTimeoutTimer); - break; - case STATE_CMD_4WAY_SUCCESSED: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_4WAY_SUCCESSED\n")); - - bthci_EventPhysicalLinkComplete(padapter, HCI_STATUS_SUCCESS, EntryNum, INVALID_PL_HANDLE); - - del_timer_sync(&pBTInfo->BTHCIJoinTimeoutTimer); - - BTHCI_SM_WITH_INFO(padapter, HCI_STATE_CONNECTED, STATE_CMD_ENTER_STATE, EntryNum); - break; - default: - RTPRINT(FIOCTL, IOCTL_STATE, ("State command(%d) is Wrong !!!\n", StateCmd)); - break; - } -} - -static void -bthci_StateDisconnecting(struct rtw_adapter *padapter, - enum hci_state_with_cmd StateCmd, u8 EntryNum) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT state], [Disconnecting], ")); - switch (StateCmd) { - case STATE_CMD_MAC_CONNECT_CANCEL_INDICATE: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_MAC_CONNECT_CANCEL_INDICATE\n")); - if (pBTInfo->BtAsocEntry[EntryNum].bNeedPhysLinkCompleteEvent) { - bthci_EventPhysicalLinkComplete(padapter, - pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus, - EntryNum, INVALID_PL_HANDLE); - } - - if (pBtMgnt->bBTConnectInProgress) { - pBtMgnt->bBTConnectInProgress = false; - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], BT Connect in progress OFF!!\n")); - } - - BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTED, STATE_CMD_ENTER_STATE, EntryNum); - break; - case STATE_CMD_DISCONNECT_PHY_LINK: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_DISCONNECT_PHY_LINK\n")); - - bthci_EventDisconnectPhyLinkComplete(padapter, - HCI_STATUS_SUCCESS, - pBTInfo->BtAsocEntry[EntryNum].PhyLinkDisconnectReason, - EntryNum); - - del_timer_sync(&pBTInfo->BTHCIJoinTimeoutTimer); - - BTHCI_DisconnectPeer(padapter, EntryNum); - break; - default: - RTPRINT(FIOCTL, IOCTL_STATE, ("State command(%d) is Wrong !!!\n", StateCmd)); - break; - } -} - -static void -bthci_StateDisconnected(struct rtw_adapter *padapter, - enum hci_state_with_cmd StateCmd, u8 EntryNum) -{ -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT state], [Disconnected], ")); - switch (StateCmd) { - case STATE_CMD_CREATE_PHY_LINK: - case STATE_CMD_ACCEPT_PHY_LINK: - if (StateCmd == STATE_CMD_CREATE_PHY_LINK) - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_CREATE_PHY_LINK\n")); - else - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_ACCEPT_PHY_LINK\n")); - - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT PS], Disable IPS and LPS\n")); - ips_leave23a(padapter); - LPS_Leave23a(padapter); - - pBtMgnt->bPhyLinkInProgress = true; - pBtMgnt->BTCurrentConnectType = BT_DISCONNECT; - pBtMgnt->CurrentBTConnectionCnt++; - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], CurrentBTConnectionCnt = %d\n", - pBtMgnt->CurrentBTConnectionCnt)); - pBtMgnt->BtOperationOn = true; - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], Bt Operation ON!! CurrentConnectEntryNum = %d\n", - pBtMgnt->CurrentConnectEntryNum)); - - if (pBtMgnt->bBTConnectInProgress) { - bthci_EventPhysicalLinkComplete(padapter, HCI_STATUS_CONTROLLER_BUSY, INVALID_ENTRY_NUM, pBtMgnt->BtCurrentPhyLinkhandle); - bthci_RemoveEntryByEntryNum(padapter, EntryNum); - return; - } - - if (StateCmd == STATE_CMD_CREATE_PHY_LINK) - pBTInfo->BtAsocEntry[EntryNum].AMPRole = AMP_BTAP_CREATOR; - else - pBTInfo->BtAsocEntry[EntryNum].AMPRole = AMP_BTAP_JOINER; - - /* 1. MAC not yet in selected channel */ - while (check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR)) { - RTPRINT(FIOCTL, IOCTL_STATE, ("Scan/Roaming/Wifi Link is in Progress, wait 200 ms\n")); - mdelay(200); - } - /* 2. MAC already in selected channel */ - RTPRINT(FIOCTL, IOCTL_STATE, ("Channel is Ready\n")); - mod_timer(&pBTInfo->BTHCIJoinTimeoutTimer, - jiffies + msecs_to_jiffies(pBtHciInfo->ConnAcceptTimeout)); - - pBTInfo->BtAsocEntry[EntryNum].bNeedPhysLinkCompleteEvent = true; - break; - case STATE_CMD_DISCONNECT_PHY_LINK: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_DISCONNECT_PHY_LINK\n")); - - del_timer_sync(&pBTInfo->BTHCIJoinTimeoutTimer); - - bthci_EventDisconnectPhyLinkComplete(padapter, - HCI_STATUS_SUCCESS, - pBTInfo->BtAsocEntry[EntryNum].PhyLinkDisconnectReason, - EntryNum); - - if (pBTInfo->BtAsocEntry[EntryNum].bNeedPhysLinkCompleteEvent) { - bthci_EventPhysicalLinkComplete(padapter, - HCI_STATUS_UNKNOW_CONNECT_ID, - EntryNum, INVALID_PL_HANDLE); - } - - if (pBtMgnt->bBTConnectInProgress) { - pBtMgnt->bBTConnectInProgress = false; - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], BT Connect in progress OFF!!\n")); - } - BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTED, STATE_CMD_ENTER_STATE, EntryNum); - bthci_RemoveEntryByEntryNum(padapter, EntryNum); - break; - case STATE_CMD_ENTER_STATE: - RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_ENTER_STATE\n")); - break; - default: - RTPRINT(FIOCTL, IOCTL_STATE, ("State command(%d) is Wrong !!!\n", StateCmd)); - break; - } -} - -void BTHCI_EventParse(struct rtw_adapter *padapter, void *pEvntData, u32 dataLen) -{ -} - -u8 BTHCI_HsConnectionEstablished(struct rtw_adapter *padapter) -{ - u8 bBtConnectionExist = false; - struct bt_30info *pBtinfo = GET_BT_INFO(padapter); - u8 i; - - for (i = 0; i < MAX_BT_ASOC_ENTRY_NUM; i++) { - if (pBtinfo->BtAsocEntry[i].b4waySuccess) { - bBtConnectionExist = true; - break; - } - } - -/*RTPRINT(FIOCTL, IOCTL_STATE, (" BTHCI_HsConnectionEstablished(), connection exist = %d\n", bBtConnectionExist)); */ - - return bBtConnectionExist; -} - -static u8 -BTHCI_CheckProfileExist(struct rtw_adapter *padapter, - enum bt_traffic_mode_profile Profile) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - u8 IsPRofile = false; - u8 i = 0; - - for (i = 0; i < pBtMgnt->ExtConfig.NumberOfHandle; i++) { - if (pBtMgnt->ExtConfig.linkInfo[i].TrafficProfile == Profile) { - IsPRofile = true; - break; - } - } - - return IsPRofile; -} - -void BTHCI_UpdateBTProfileRTKToMoto(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - u8 i = 0; - - pBtMgnt->ExtConfig.NumberOfSCO = 0; - - for (i = 0; i < pBtMgnt->ExtConfig.NumberOfHandle; i++) { - pBtMgnt->ExtConfig.linkInfo[i].TrafficProfile = BT_PROFILE_NONE; - - if (pBtMgnt->ExtConfig.linkInfo[i].BTProfile == BT_PROFILE_SCO) - pBtMgnt->ExtConfig.NumberOfSCO++; - - pBtMgnt->ExtConfig.linkInfo[i].TrafficProfile = pBtMgnt->ExtConfig.linkInfo[i].BTProfile; - switch (pBtMgnt->ExtConfig.linkInfo[i].TrafficProfile) { - case BT_PROFILE_SCO: - break; - case BT_PROFILE_PAN: - pBtMgnt->ExtConfig.linkInfo[i].IncomingTrafficMode = BT_MOTOR_EXT_BE; - pBtMgnt->ExtConfig.linkInfo[i].OutgoingTrafficMode = BT_MOTOR_EXT_BE; - break; - case BT_PROFILE_A2DP: - pBtMgnt->ExtConfig.linkInfo[i].IncomingTrafficMode = BT_MOTOR_EXT_GULB; - pBtMgnt->ExtConfig.linkInfo[i].OutgoingTrafficMode = BT_MOTOR_EXT_GULB; - break; - case BT_PROFILE_HID: - pBtMgnt->ExtConfig.linkInfo[i].IncomingTrafficMode = BT_MOTOR_EXT_GUL; - pBtMgnt->ExtConfig.linkInfo[i].OutgoingTrafficMode = BT_MOTOR_EXT_BE; - break; - default: - break; - } - } - - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RTK, NumberOfHandle = %d, NumberOfSCO = %d\n", - pBtMgnt->ExtConfig.NumberOfHandle, pBtMgnt->ExtConfig.NumberOfSCO)); -} - -void BTHCI_WifiScanNotify(struct rtw_adapter *padapter, u8 scanType) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - if (pBtMgnt->ExtConfig.bEnableWifiScanNotify) - bthci_EventExtWifiScanNotify(padapter, scanType); -} - -void -BTHCI_StateMachine( - struct rtw_adapter *padapter, - u8 StateToEnter, - enum hci_state_with_cmd StateCmd, - u8 EntryNum - ) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - if (EntryNum == 0xff) { - RTPRINT(FIOCTL, IOCTL_STATE, (" StateMachine, error EntryNum = 0x%x \n", EntryNum)); - return; - } - RTPRINT(FIOCTL, IOCTL_STATE, (" StateMachine, EntryNum = 0x%x, CurrentState = 0x%x, BtNextState = 0x%x, StateCmd = 0x%x , StateToEnter = 0x%x\n", - EntryNum, pBTInfo->BtAsocEntry[EntryNum].BtCurrentState, pBTInfo->BtAsocEntry[EntryNum].BtNextState, StateCmd, StateToEnter)); - - if (pBTInfo->BtAsocEntry[EntryNum].BtNextState & StateToEnter) { - pBTInfo->BtAsocEntry[EntryNum].BtCurrentState = StateToEnter; - - switch (StateToEnter) { - case HCI_STATE_STARTING: - pBTInfo->BtAsocEntry[EntryNum].BtNextState = HCI_STATE_DISCONNECTING | HCI_STATE_CONNECTING; - bthci_StateStarting(padapter, StateCmd, EntryNum); - break; - case HCI_STATE_CONNECTING: - pBTInfo->BtAsocEntry[EntryNum].BtNextState = HCI_STATE_CONNECTING | HCI_STATE_DISCONNECTING | HCI_STATE_AUTHENTICATING; - bthci_StateConnecting(padapter, StateCmd, EntryNum); - break; - case HCI_STATE_AUTHENTICATING: - pBTInfo->BtAsocEntry[EntryNum].BtNextState = HCI_STATE_DISCONNECTING | HCI_STATE_CONNECTED; - bthci_StateAuth(padapter, StateCmd, EntryNum); - break; - case HCI_STATE_CONNECTED: - pBTInfo->BtAsocEntry[EntryNum].BtNextState = HCI_STATE_CONNECTED | HCI_STATE_DISCONNECTING; - bthci_StateConnected(padapter, StateCmd, EntryNum); - break; - case HCI_STATE_DISCONNECTING: - pBTInfo->BtAsocEntry[EntryNum].BtNextState = HCI_STATE_DISCONNECTED | HCI_STATE_DISCONNECTING; - bthci_StateDisconnecting(padapter, StateCmd, EntryNum); - break; - case HCI_STATE_DISCONNECTED: - pBTInfo->BtAsocEntry[EntryNum].BtNextState = HCI_STATE_DISCONNECTED | HCI_STATE_STARTING | HCI_STATE_CONNECTING; - bthci_StateDisconnected(padapter, StateCmd, EntryNum); - break; - default: - RTPRINT(FIOCTL, IOCTL_STATE, (" StateMachine, Unknown state to enter!!!\n")); - break; - } - } else { - RTPRINT(FIOCTL, IOCTL_STATE, (" StateMachine, Wrong state to enter\n")); - } - - /* 20100325 Joseph: Disable/Enable IPS/LPS according to BT status. */ - if (!pBtMgnt->bBTConnectInProgress && !pBtMgnt->BtOperationOn) { - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT PS], ips_enter23a()\n")); - ips_enter23a(padapter); - } -} - -void BTHCI_DisconnectPeer(struct rtw_adapter *padapter, u8 EntryNum) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, (" BTHCI_DisconnectPeer()\n")); - - BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTING, STATE_CMD_MAC_CONNECT_CANCEL_INDICATE, EntryNum); - - if (pBTInfo->BtAsocEntry[EntryNum].bUsed) { -/*BTPKT_SendDeauthentication(padapter, pBTInfo->BtAsocEntry[EntryNum].BTRemoteMACAddr, unspec_reason); not porting yet */ - } - - if (pBtMgnt->bBTConnectInProgress) { - pBtMgnt->bBTConnectInProgress = false; - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], BT Connect in progress OFF!!\n")); - } - - bthci_RemoveEntryByEntryNum(padapter, EntryNum); - - if (pBtMgnt->bNeedNotifyAMPNoCap) { - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT AMPStatus], set to invalid in BTHCI_DisconnectPeer()\n")); - BTHCI_EventAMPStatusChange(padapter, AMP_STATUS_NO_CAPACITY_FOR_BT); - } -} - -void BTHCI_EventNumOfCompletedDataBlocks(struct rtw_adapter *padapter) -{ -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo; - u8 localBuf[TmpLocalBufSize] = ""; - u8 *pRetPar, *pTriple; - u8 len = 0, i, j, handleNum = 0; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u16 *pu2Temp, *pPackets, *pHandle, *pDblocks; - u8 sent = 0; - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - - if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_NUM_OF_COMPLETE_DATA_BLOCKS)) { - RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Num Of Completed DataBlocks, Ignore to send NumOfCompletedDataBlocksEvent due to event mask page 2\n")); - return; - } - - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[0]; - pTriple = &pRetPar[3]; - for (j = 0; j < MAX_BT_ASOC_ENTRY_NUM; j++) { - - for (i = 0; i < MAX_LOGICAL_LINK_NUM; i++) { - if (pBTInfo->BtAsocEntry[j].LogLinkCmdData[i].BtLogLinkhandle) { - handleNum++; - pHandle = (u16 *)&pTriple[0]; /* Handle[i] */ - pPackets = (u16 *)&pTriple[2]; /* Num_Of_Completed_Packets[i] */ - pDblocks = (u16 *)&pTriple[4]; /* Num_Of_Completed_Blocks[i] */ - *pHandle = pBTInfo->BtAsocEntry[j].LogLinkCmdData[i].BtLogLinkhandle; - *pPackets = (u16)pBTInfo->BtAsocEntry[j].LogLinkCmdData[i].TxPacketCount; - *pDblocks = (u16)pBTInfo->BtAsocEntry[j].LogLinkCmdData[i].TxPacketCount; - if (pBTInfo->BtAsocEntry[j].LogLinkCmdData[i].TxPacketCount) { - sent = 1; - RTPRINT(FIOCTL, IOCTL_BT_EVENT_DETAIL, - ("[BT event], Num Of Completed DataBlocks, Handle = 0x%x, Num_Of_Completed_Packets = 0x%x, Num_Of_Completed_Blocks = 0x%x\n", - *pHandle, *pPackets, *pDblocks)); - } - pBTInfo->BtAsocEntry[j].LogLinkCmdData[i].TxPacketCount = 0; - len += 6; - pTriple += len; - } - } - } - - pRetPar[2] = handleNum; /* Number_of_Handles */ - len += 1; - pu2Temp = (u16 *)&pRetPar[0]; - *pu2Temp = BTTotalDataBlockNum; - len += 2; - - PPacketIrpEvent->EventCode = HCI_EVENT_NUM_OF_COMPLETE_DATA_BLOCKS; - PPacketIrpEvent->Length = len; - if (handleNum && sent) - bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2); -} - -void BTHCI_EventAMPStatusChange(struct rtw_adapter *padapter, u8 AMP_Status) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - struct packet_irp_hcievent_data *PPacketIrpEvent; - u8 len = 0; - u8 localBuf[7] = ""; - u8 *pRetPar; - - if (AMP_Status == AMP_STATUS_NO_CAPACITY_FOR_BT) { - pBtMgnt->BTNeedAMPStatusChg = true; - pBtMgnt->bNeedNotifyAMPNoCap = false; - - BTHCI_DisconnectAll(padapter); - } else if (AMP_Status == AMP_STATUS_FULL_CAPACITY_FOR_BT) { - pBtMgnt->BTNeedAMPStatusChg = false; - } - - PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]); - /* Return parameters starts from here */ - pRetPar = &PPacketIrpEvent->Data[0]; - - pRetPar[0] = 0; /* Status */ - len += 1; - pRetPar[1] = AMP_Status; /* AMP_Status */ - len += 1; - - PPacketIrpEvent->EventCode = HCI_EVENT_AMP_STATUS_CHANGE; - PPacketIrpEvent->Length = len; - if (bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2) == RT_STATUS_SUCCESS) - RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_STATE), ("[BT event], AMP Status Change, AMP_Status = %d\n", AMP_Status)); -} - -void BTHCI_DisconnectAll(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - u8 i; - - RTPRINT(FIOCTL, IOCTL_STATE, (" DisconnectALL()\n")); - - for (i = 0; i < MAX_BT_ASOC_ENTRY_NUM; i++) { - if (pBTInfo->BtAsocEntry[i].b4waySuccess) { - BTHCI_SM_WITH_INFO(padapter, HCI_STATE_CONNECTED, STATE_CMD_DISCONNECT_PHY_LINK, i); - } else if (pBTInfo->BtAsocEntry[i].bUsed) { - if (pBTInfo->BtAsocEntry[i].BtCurrentState == HCI_STATE_CONNECTING) { - BTHCI_SM_WITH_INFO(padapter, HCI_STATE_CONNECTING, STATE_CMD_MAC_CONNECT_CANCEL_INDICATE, i); - } else if (pBTInfo->BtAsocEntry[i].BtCurrentState == HCI_STATE_DISCONNECTING) { - BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTING, STATE_CMD_MAC_CONNECT_CANCEL_INDICATE, i); - } - } - } -} - -enum hci_status -BTHCI_HandleHCICMD( - struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd - ) -{ - enum hci_status status = HCI_STATUS_SUCCESS; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_dgb *pBtDbg = &pBTInfo->BtDbg; - - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("\n")); - RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("HCI Command start, OGF = 0x%x, OCF = 0x%x, Length = 0x%x\n", - pHciCmd->OGF, pHciCmd->OCF, pHciCmd->Length)); - if (pHciCmd->Length) { - RTPRINT_DATA(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), "HCI Command, Hex Data :\n", - &pHciCmd->Data[0], pHciCmd->Length); - } - if (pHciCmd->OGF == OGF_EXTENSION) { - if (pHciCmd->OCF == HCI_SET_RSSI_VALUE) - RTPRINT(FIOCTL, IOCTL_BT_EVENT_PERIODICAL, ("[BT cmd], ")); - else - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[BT cmd], ")); - } else { - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("[BT cmd], ")); - } - - pBtDbg->dbgHciInfo.hciCmdCnt++; - - switch (pHciCmd->OGF) { - case LINK_CONTROL_COMMANDS: - status = bthci_HandleOGFLinkControlCMD(padapter, pHciCmd); - break; - case HOLD_MODE_COMMAND: - break; - case OGF_SET_EVENT_MASK_COMMAND: - status = bthci_HandleOGFSetEventMaskCMD(padapter, pHciCmd); - break; - case OGF_INFORMATIONAL_PARAMETERS: - status = bthci_HandleOGFInformationalParameters(padapter, pHciCmd); - break; - case OGF_STATUS_PARAMETERS: - status = bthci_HandleOGFStatusParameters(padapter, pHciCmd); - break; - case OGF_TESTING_COMMANDS: - status = bthci_HandleOGFTestingCMD(padapter, pHciCmd); - break; - case OGF_EXTENSION: - status = bthci_HandleOGFExtension(padapter, pHciCmd); - break; - default: - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI Command(), Unknown OGF = 0x%x\n", pHciCmd->OGF)); - RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_UNKNOWN_COMMAND\n")); - status = bthci_UnknownCMD(padapter, pHciCmd); - break; - } - RTPRINT(FIOCTL, IOCTL_BT_HCICMD_DETAIL, ("HCI Command execution end!!\n")); - - return status; -} - -/* ===== End of sync from SD7 driver COMMOM/bt_hci.c ===== */ - -static const char *const BtStateString[] = { - "BT_DISABLED", - "BT_NO_CONNECTION", - "BT_CONNECT_IDLE", - "BT_INQ_OR_PAG", - "BT_ACL_ONLY_BUSY", - "BT_SCO_ONLY_BUSY", - "BT_ACL_SCO_BUSY", - "BT_ACL_INQ_OR_PAG", - "BT_STATE_NOT_DEFINED" -}; - -/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtc87231Ant.c ===== */ - -static void btdm_SetFwIgnoreWlanAct(struct rtw_adapter *padapter, u8 bEnable) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 H2C_Parameter[1] = {0}; - - if (bEnable) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT Ignore Wlan_Act !!\n")); - H2C_Parameter[0] |= BIT(0); /* function enable */ - pHalData->bt_coexist.bFWCoexistAllOff = false; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT don't ignore Wlan_Act !!\n")); - } - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], set FW for BT Ignore Wlan_Act, write 0x25 = 0x%02x\n", - H2C_Parameter[0])); - - FillH2CCmd(padapter, BT_IGNORE_WLAN_ACT_EID, 1, H2C_Parameter); -} - -static void btdm_NotifyFwScan(struct rtw_adapter *padapter, u8 scanType) -{ - u8 H2C_Parameter[1] = {0}; - - if (scanType == true) - H2C_Parameter[0] = 0x1; - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Notify FW for wifi scan, write 0x3b = 0x%02x\n", - H2C_Parameter[0])); - - FillH2CCmd(padapter, 0x3b, 1, H2C_Parameter); -} - -static void btdm_1AntSetPSMode(struct rtw_adapter *padapter, - u8 enable, u8 smartps, u8 mode) -{ - struct pwrctrl_priv *pwrctrl; - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Current LPS(%s, %d), smartps =%d\n", enable == true?"ON":"OFF", mode, smartps)); - - pwrctrl = &padapter->pwrctrlpriv; - - if (enable == true) { - rtw_set_ps_mode23a(padapter, PS_MODE_MIN, smartps, mode); - } else { - rtw_set_ps_mode23a(padapter, PS_MODE_ACTIVE, 0, 0); - LPS_RF_ON_check23a(padapter, 100); - } -} - -static void btdm_1AntTSFSwitch(struct rtw_adapter *padapter, u8 enable) -{ - u8 oldVal, newVal; - - oldVal = rtl8723au_read8(padapter, 0x550); - - if (enable) - newVal = oldVal | EN_BCN_FUNCTION; - else - newVal = oldVal & ~EN_BCN_FUNCTION; - - if (oldVal != newVal) - rtl8723au_write8(padapter, 0x550, newVal); -} - -static u8 btdm_Is1AntPsTdmaStateChange(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_1ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm1Ant; - - if ((pBtdm8723->bPrePsTdmaOn != pBtdm8723->bCurPsTdmaOn) || - (pBtdm8723->prePsTdma != pBtdm8723->curPsTdma)) - return true; - else - return false; -} - -/* Before enter TDMA, make sure Power Saving is enable! */ -static void -btdm_1AntPsTdma( - struct rtw_adapter *padapter, - u8 bTurnOn, - u8 type - ) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_1ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm1Ant; - - pBtdm8723->bCurPsTdmaOn = bTurnOn; - pBtdm8723->curPsTdma = type; - if (bTurnOn) { - switch (type) { - case 1: /* A2DP Level-1 or FTP/OPP */ - default: - if (btdm_Is1AntPsTdmaStateChange(padapter)) { - /* wide duration for WiFi */ - BTDM_SetFw3a(padapter, 0xd3, 0x1a, 0x1a, 0x0, 0x58); - } - break; - case 2: /* A2DP Level-2 */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) { - /* normal duration for WiFi */ - BTDM_SetFw3a(padapter, 0xd3, 0x12, 0x12, 0x0, 0x58); - } - break; - case 3: /* BT FTP/OPP */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) { - /* normal duration for WiFi */ - BTDM_SetFw3a(padapter, 0xd3, 0x30, 0x03, 0x10, 0x58); - - } - break; - case 4: /* for wifi scan & BT is connected */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) { - /* protect 3 beacons in 3-beacon period & no Tx pause at BT slot */ - BTDM_SetFw3a(padapter, 0x93, 0x15, 0x03, 0x14, 0x0); - } - break; - case 5: /* for WiFi connected-busy & BT is Non-Connected-Idle */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) { - /* SCO mode, Ant fixed at WiFi, WLAN_Act toggle */ - BTDM_SetFw3a(padapter, 0x61, 0x15, 0x03, 0x31, 0x00); - } - break; - case 9: /* ACL high-retry type - 2 */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) { - /* narrow duration for WiFi */ - BTDM_SetFw3a(padapter, 0xd3, 0xa, 0xa, 0x0, 0x58); /* narrow duration for WiFi */ - } - break; - case 10: /* for WiFi connect idle & BT ACL busy or WiFi Connected-Busy & BT is Inquiry */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) - BTDM_SetFw3a(padapter, 0x13, 0xa, 0xa, 0x0, 0x40); - break; - case 11: /* ACL high-retry type - 3 */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) { - /* narrow duration for WiFi */ - BTDM_SetFw3a(padapter, 0xd3, 0x05, 0x05, 0x00, 0x58); - } - break; - case 12: /* for WiFi Connected-Busy & BT is Connected-Idle */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) { - /* Allow High-Pri BT */ - BTDM_SetFw3a(padapter, 0xeb, 0x0a, 0x03, 0x31, 0x18); - } - break; - case 20: /* WiFi only busy , TDMA mode for power saving */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) - BTDM_SetFw3a(padapter, 0x13, 0x25, 0x25, 0x00, 0x00); - break; - case 27: /* WiFi DHCP/Site Survey & BT SCO busy */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) - BTDM_SetFw3a(padapter, 0xa3, 0x25, 0x03, 0x31, 0x98); - break; - case 28: /* WiFi DHCP/Site Survey & BT idle */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) - BTDM_SetFw3a(padapter, 0x69, 0x25, 0x03, 0x31, 0x00); - break; - case 29: /* WiFi DHCP/Site Survey & BT ACL busy */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) { - BTDM_SetFw3a(padapter, 0xeb, 0x1a, 0x1a, 0x01, 0x18); - rtl8723au_write32(padapter, 0x6c0, 0x5afa5afa); - rtl8723au_write32(padapter, 0x6c4, 0x5afa5afa); - } - break; - case 30: /* WiFi idle & BT Inquiry */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) - BTDM_SetFw3a(padapter, 0x93, 0x15, 0x03, 0x14, 0x00); - break; - case 31: /* BT HID */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) - BTDM_SetFw3a(padapter, 0xd3, 0x1a, 0x1a, 0x00, 0x58); - break; - case 32: /* BT SCO & Inquiry */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) - BTDM_SetFw3a(padapter, 0xab, 0x0a, 0x03, 0x11, 0x98); - break; - case 33: /* BT SCO & WiFi site survey */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) - BTDM_SetFw3a(padapter, 0xa3, 0x25, 0x03, 0x30, 0x98); - break; - case 34: /* BT HID & WiFi site survey */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) - BTDM_SetFw3a(padapter, 0xd3, 0x1a, 0x1a, 0x00, 0x18); - break; - case 35: /* BT HID & WiFi Connecting */ - if (btdm_Is1AntPsTdmaStateChange(padapter)) - BTDM_SetFw3a(padapter, 0xe3, 0x1a, 0x1a, 0x00, 0x18); - break; - } - } else { - /* disable PS-TDMA */ - switch (type) { - case 8: - if (btdm_Is1AntPsTdmaStateChange(padapter)) { - /* Antenna control by PTA, 0x870 = 0x310 */ - BTDM_SetFw3a(padapter, 0x8, 0x0, 0x0, 0x0, 0x0); - } - break; - case 0: - default: - if (btdm_Is1AntPsTdmaStateChange(padapter)) { - /* Antenna control by PTA, 0x870 = 0x310 */ - BTDM_SetFw3a(padapter, 0x0, 0x0, 0x0, 0x8, 0x0); - } - /* Switch Antenna to BT */ - rtl8723au_write16(padapter, 0x860, 0x210); - RTPRINT(FBT, BT_TRACE, ("[BTCoex], 0x860 = 0x210, Switch Antenna to BT\n")); - break; - case 9: - if (btdm_Is1AntPsTdmaStateChange(padapter)) { - /* Antenna control by PTA, 0x870 = 0x310 */ - BTDM_SetFw3a(padapter, 0x0, 0x0, 0x0, 0x8, 0x0); - } - /* Switch Antenna to WiFi */ - rtl8723au_write16(padapter, 0x860, 0x110); - RTPRINT(FBT, BT_TRACE, ("[BTCoex], 0x860 = 0x110, Switch Antenna to WiFi\n")); - break; - } - } - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Current TDMA(%s, %d)\n", - pBtdm8723->bCurPsTdmaOn?"ON":"OFF", pBtdm8723->curPsTdma)); - - /* update pre state */ - pBtdm8723->bPrePsTdmaOn = pBtdm8723->bCurPsTdmaOn; - pBtdm8723->prePsTdma = pBtdm8723->curPsTdma; -} - -static void -_btdm_1AntSetPSTDMA(struct rtw_adapter *padapter, u8 bPSEn, u8 smartps, - u8 psOption, u8 bTDMAOn, u8 tdmaType) -{ - struct pwrctrl_priv *pwrctrl; - struct hal_data_8723a *pHalData; - struct btdm_8723a_1ant *pBtdm8723; - u8 psMode; - u8 bSwitchPS; - - if (!check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) && - (get_fwstate(&padapter->mlmepriv) != WIFI_NULL_STATE)) { - btdm_1AntPsTdma(padapter, bTDMAOn, tdmaType); - return; - } - psOption &= ~BIT(0); - - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], Set LPS(%s, %d) TDMA(%s, %d)\n", - bPSEn == true?"ON":"OFF", psOption, - bTDMAOn == true?"ON":"OFF", tdmaType)); - - pwrctrl = &padapter->pwrctrlpriv; - pHalData = GET_HAL_DATA(padapter); - pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm1Ant; - - if (bPSEn) { - if (pBtdm8723->bWiFiHalt) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Enable PS Fail, WiFi in Halt!!\n")); - return; - } - - if (pwrctrl->bInSuspend) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Enable PS Fail, WiFi in Suspend!!\n")); - return; - } - - if (padapter->bDriverStopped) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Enable PS Fail, WiFi driver stopped!!\n")); - return; - } - - if (padapter->bSurpriseRemoved) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Enable PS Fail, WiFi Surprise Removed!!\n")); - return; - } - - psMode = PS_MODE_MIN; - } else { - psMode = PS_MODE_ACTIVE; - psOption = 0; - } - - if (psMode != pwrctrl->pwr_mode) { - bSwitchPS = true; - } else if (psMode != PS_MODE_ACTIVE) { - if (psOption != pwrctrl->bcn_ant_mode) - bSwitchPS = true; - else if (smartps != pwrctrl->smart_ps) - bSwitchPS = true; - else - bSwitchPS = false; - } else { - bSwitchPS = false; - } - - if (bSwitchPS) { - /* disable TDMA */ - if (pBtdm8723->bCurPsTdmaOn) { - if (!bTDMAOn) { - btdm_1AntPsTdma(padapter, false, tdmaType); - } else { - if (!rtl8723a_BT_enabled(padapter) || - (pHalData->bt_coexist.halCoex8723.c2hBtInfo == BT_INFO_STATE_NO_CONNECTION) || - (pHalData->bt_coexist.halCoex8723.c2hBtInfo == BT_INFO_STATE_CONNECT_IDLE) || - (tdmaType == 29)) - btdm_1AntPsTdma(padapter, false, 9); - else - btdm_1AntPsTdma(padapter, false, 0); - } - } - - /* change Power Save State */ - btdm_1AntSetPSMode(padapter, bPSEn, smartps, psOption); - } - - btdm_1AntPsTdma(padapter, bTDMAOn, tdmaType); -} - -static void -btdm_1AntSetPSTDMA(struct rtw_adapter *padapter, u8 bPSEn, - u8 psOption, u8 bTDMAOn, u8 tdmaType) -{ - _btdm_1AntSetPSTDMA(padapter, bPSEn, 0, psOption, bTDMAOn, tdmaType); -} - -static void btdm_1AntWifiParaAdjust(struct rtw_adapter *padapter, u8 bEnable) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_1ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm1Ant; - - if (bEnable) { - pBtdm8723->curWifiPara = 1; - if (pBtdm8723->preWifiPara != pBtdm8723->curWifiPara) - BTDM_SetSwPenaltyTxRateAdaptive(padapter, BT_TX_RATE_ADAPTIVE_LOW_PENALTY); - } else { - pBtdm8723->curWifiPara = 2; - if (pBtdm8723->preWifiPara != pBtdm8723->curWifiPara) - BTDM_SetSwPenaltyTxRateAdaptive(padapter, BT_TX_RATE_ADAPTIVE_NORMAL); - } - -} - -static void btdm_1AntPtaParaReload(struct rtw_adapter *padapter) -{ - /* PTA parameter */ - rtl8723au_write8(padapter, 0x6cc, 0x0); /* 1-Ant coex */ - rtl8723au_write32(padapter, 0x6c8, 0xffff); /* wifi break table */ - rtl8723au_write32(padapter, 0x6c4, 0x55555555); /* coex table */ - - /* Antenna switch control parameter */ - rtl8723au_write32(padapter, 0x858, 0xaaaaaaaa); - if (IS_8723A_A_CUT(GET_HAL_DATA(padapter)->VersionID)) { - /* SPDT(connected with TRSW) control by hardware PTA */ - rtl8723au_write32(padapter, 0x870, 0x0); - rtl8723au_write8(padapter, 0x40, 0x24); - } else { - rtl8723au_write8(padapter, 0x40, 0x20); - /* set antenna at bt side if ANTSW is software control */ - rtl8723au_write16(padapter, 0x860, 0x210); - /* SPDT(connected with TRSW) control by hardware PTA */ - rtl8723au_write32(padapter, 0x870, 0x300); - /* ANTSW keep by GNT_BT */ - rtl8723au_write32(padapter, 0x874, 0x22804000); - } - - /* coexistence parameters */ - rtl8723au_write8(padapter, 0x778, 0x1); /* enable RTK mode PTA */ - - /* BT don't ignore WLAN_Act */ - btdm_SetFwIgnoreWlanAct(padapter, false); -} - -/* - * Return - *1: upgrade (add WiFi duration time) - *0: keep - *-1: downgrade (add BT duration time) - */ -static s8 btdm_1AntTdmaJudgement(struct rtw_adapter *padapter, u8 retry) -{ - struct hal_data_8723a *pHalData; - struct btdm_8723a_1ant *pBtdm8723; - static s8 up, dn, m = 1, WaitCount; - s8 ret; - - pHalData = GET_HAL_DATA(padapter); - pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm1Ant; - ret = 0; - - if (pBtdm8723->psTdmaMonitorCnt == 0) { - up = 0; - dn = 0; - m = 1; - WaitCount = 0; - } else { - WaitCount++; - } - - if (retry == 0) { - /* no retry in the last 2-second duration */ - up++; - dn--; - if (dn < 0) - dn = 0; - if (up >= 3*m) { - /* retry = 0 in consecutive 3m*(2s), add WiFi duration */ - ret = 1; - up = 0; - dn = 0; - WaitCount = 0; - } - } else if (retry <= 3) { - /* retry<= 3 in the last 2-second duration */ - up--; - dn++; - if (up < 0) - up = 0; - - if (dn == 2) { - /* retry<= 3 in consecutive 2*(2s), minus WiFi duration (add BT duration) */ - ret = -1; - - /* record how many time downgrad WiFi duration */ - if (WaitCount <= 2) - m++; - else - m = 1; - /* the max number of m is 20 */ - /* the longest time of upgrade WiFi duration is 20*3*2s = 120s */ - if (m >= 20) - m = 20; - up = 0; - dn = 0; - WaitCount = 0; - } - } else { - /* retry count > 3 */ - /* retry>3, minus WiFi duration (add BT duration) */ - ret = -1; - - /* record how many time downgrad WiFi duration */ - if (WaitCount == 1) - m++; - else - m = 1; - if (m >= 20) - m = 20; - - up = 0; - dn = 0; - WaitCount = 0; - } - return ret; -} - -static void btdm_1AntTdmaDurationAdjustForACL(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_1ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm1Ant; - - if (pBtdm8723->psTdmaGlobalCnt != pBtdm8723->psTdmaMonitorCnt) { - pBtdm8723->psTdmaMonitorCnt = 0; - pBtdm8723->psTdmaGlobalCnt = 0; - } - if (pBtdm8723->psTdmaMonitorCnt == 0) { - btdm_1AntSetPSTDMA(padapter, true, 0, true, 2); - pBtdm8723->psTdmaDuAdjType = 2; - } else { - /* Now we only have 4 level Ps Tdma, */ - /* if that's not the following 4 level(will changed by wifi scan, dhcp...), */ - /* then we have to adjust it back to the previous record one. */ - if ((pBtdm8723->curPsTdma != 1) && - (pBtdm8723->curPsTdma != 2) && - (pBtdm8723->curPsTdma != 9) && - (pBtdm8723->curPsTdma != 11)) { - btdm_1AntSetPSTDMA(padapter, true, 0, true, pBtdm8723->psTdmaDuAdjType); - } else { - s32 judge; - - judge = btdm_1AntTdmaJudgement(padapter, pHalData->bt_coexist.halCoex8723.btRetryCnt); - if (judge == -1) { - if (pBtdm8723->curPsTdma == 1) { - /* Decrease WiFi duration for high BT retry */ - if (pHalData->bt_coexist.halCoex8723.btInfoExt) - pBtdm8723->psTdmaDuAdjType = 9; - else - pBtdm8723->psTdmaDuAdjType = 2; - btdm_1AntSetPSTDMA(padapter, true, 0, true, pBtdm8723->psTdmaDuAdjType); - } else if (pBtdm8723->curPsTdma == 2) { - btdm_1AntSetPSTDMA(padapter, true, 0, true, 9); - pBtdm8723->psTdmaDuAdjType = 9; - } else if (pBtdm8723->curPsTdma == 9) { - btdm_1AntSetPSTDMA(padapter, true, 0, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } - } else if (judge == 1) { - if (pBtdm8723->curPsTdma == 11) { - btdm_1AntSetPSTDMA(padapter, true, 0, true, 9); - pBtdm8723->psTdmaDuAdjType = 9; - } else if (pBtdm8723->curPsTdma == 9) { - if (pHalData->bt_coexist.halCoex8723.btInfoExt) - pBtdm8723->psTdmaDuAdjType = 9; - else - pBtdm8723->psTdmaDuAdjType = 2; - btdm_1AntSetPSTDMA(padapter, true, 0, true, pBtdm8723->psTdmaDuAdjType); - } else if (pBtdm8723->curPsTdma == 2) { - if (pHalData->bt_coexist.halCoex8723.btInfoExt) - pBtdm8723->psTdmaDuAdjType = 9; - else - pBtdm8723->psTdmaDuAdjType = 1; - btdm_1AntSetPSTDMA(padapter, true, 0, true, pBtdm8723->psTdmaDuAdjType); - } - } - } - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], ACL current TDMA(%s, %d)\n", - (pBtdm8723->bCurPsTdmaOn ? "ON" : "OFF"), pBtdm8723->curPsTdma)); - } - pBtdm8723->psTdmaMonitorCnt++; -} - -static void btdm_1AntCoexProcessForWifiConnect(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv; - struct hal_data_8723a *pHalData; - struct bt_coexist_8723a *pBtCoex; - struct btdm_8723a_1ant *pBtdm8723; - u8 BtState; - - pmlmepriv = &padapter->mlmepriv; - pHalData = GET_HAL_DATA(padapter); - pBtCoex = &pHalData->bt_coexist.halCoex8723; - pBtdm8723 = &pBtCoex->btdm1Ant; - BtState = pBtCoex->c2hBtInfo; - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], WiFi is %s\n", - BTDM_IsWifiBusy(padapter)?"Busy":"IDLE")); - RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT is %s\n", - BtStateString[BtState])); - - padapter->pwrctrlpriv.btcoex_rfon = false; - - if (!BTDM_IsWifiBusy(padapter) && - !check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) && - (BtState == BT_INFO_STATE_NO_CONNECTION || - BtState == BT_INFO_STATE_CONNECT_IDLE)) { - switch (BtState) { - case BT_INFO_STATE_NO_CONNECTION: - _btdm_1AntSetPSTDMA(padapter, true, 2, 0x26, false, 9); - break; - case BT_INFO_STATE_CONNECT_IDLE: - _btdm_1AntSetPSTDMA(padapter, true, 2, 0x26, false, 0); - break; - } - } else { - switch (BtState) { - case BT_INFO_STATE_NO_CONNECTION: - case BT_INFO_STATE_CONNECT_IDLE: - /* WiFi is Busy */ - btdm_1AntSetPSTDMA(padapter, false, 0, true, 5); - rtl8723au_write32(padapter, 0x6c0, 0x5a5a5a5a); - rtl8723au_write32(padapter, 0x6c4, 0x5a5a5a5a); - break; - case BT_INFO_STATE_ACL_INQ_OR_PAG: - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], BT PROFILE is " - "BT_INFO_STATE_ACL_INQ_OR_PAG\n")); - case BT_INFO_STATE_INQ_OR_PAG: - padapter->pwrctrlpriv.btcoex_rfon = true; - btdm_1AntSetPSTDMA(padapter, true, 0, true, 30); - break; - case BT_INFO_STATE_SCO_ONLY_BUSY: - case BT_INFO_STATE_ACL_SCO_BUSY: - if (true == pBtCoex->bC2hBtInquiryPage) - btdm_1AntSetPSTDMA(padapter, false, 0, - true, 32); - else { -#ifdef BTCOEX_CMCC_TEST - btdm_1AntSetPSTDMA(padapter, false, 0, - true, 23); -#else /* !BTCOEX_CMCC_TEST */ - btdm_1AntSetPSTDMA(padapter, false, 0, - false, 8); - rtl8723au_write32(padapter, 0x6c0, 0x5a5a5a5a); - rtl8723au_write32(padapter, 0x6c4, 0x5a5a5a5a); -#endif /* !BTCOEX_CMCC_TEST */ - } - break; - case BT_INFO_STATE_ACL_ONLY_BUSY: - padapter->pwrctrlpriv.btcoex_rfon = true; - if (pBtCoex->c2hBtProfile == BT_INFO_HID) { - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], BT PROFILE is HID\n")); - btdm_1AntSetPSTDMA(padapter, true, 0, true, 31); - } else if (pBtCoex->c2hBtProfile == BT_INFO_FTP) { - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], BT PROFILE is FTP/OPP\n")); - btdm_1AntSetPSTDMA(padapter, true, 0, true, 3); - } else if (pBtCoex->c2hBtProfile == (BT_INFO_A2DP|BT_INFO_FTP)) { - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], BT PROFILE is A2DP_FTP\n")); - btdm_1AntSetPSTDMA(padapter, true, 0, true, 11); - } else { - if (pBtCoex->c2hBtProfile == BT_INFO_A2DP) - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], BT PROFILE is " - "A2DP\n")); - else - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], BT PROFILE is " - "UNKNOWN(0x%02X)! Use A2DP " - "Profile\n", - pBtCoex->c2hBtProfile)); - btdm_1AntTdmaDurationAdjustForACL(padapter); - } - break; - } - } - - pBtdm8723->psTdmaGlobalCnt++; -} - -static void -btdm_1AntUpdateHalRAMask(struct rtw_adapter *padapter, u32 mac_id, u32 filter) -{ - u8 init_rate = 0; - u8 raid, arg; - u32 mask; - u8 shortGIrate = false; - int supportRateNum = 0; - struct sta_info *psta; - struct hal_data_8723a *pHalData; - struct dm_priv *pdmpriv; - struct mlme_ext_priv *pmlmeext; - struct mlme_ext_info *pmlmeinfo; - struct wlan_bssid_ex *cur_network; - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], %s, MACID =%d, filter = 0x%08x!!\n", - __func__, mac_id, filter)); - - pHalData = GET_HAL_DATA(padapter); - pdmpriv = &pHalData->dmpriv; - pmlmeext = &padapter->mlmeextpriv; - pmlmeinfo = &pmlmeext->mlmext_info; - cur_network = &pmlmeinfo->network; - - if (mac_id >= NUM_STA) { /* CAM_SIZE */ - RTPRINT(FBT, BT_TRACE, ("[BTCoex], %s, MACID =%d illegal!!\n", - __func__, mac_id)); - return; - } - - psta = pmlmeinfo->FW_sta_info[mac_id].psta; - if (!psta) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], %s, Can't find station!!\n", - __func__)); - return; - } - - raid = psta->raid; - - switch (mac_id) { - case 0:/* for infra mode */ - supportRateNum = - rtw_get_rateset_len23a(cur_network->SupportedRates); - mask = update_supported_rate23a(cur_network->SupportedRates, - supportRateNum); - mask |= (pmlmeinfo->HT_enable) ? - update_MSC_rate23a(&pmlmeinfo->ht_cap):0; - if (support_short_GI23a(padapter, &pmlmeinfo->ht_cap)) - shortGIrate = true; - break; - case 1:/* for broadcast/multicast */ - supportRateNum = rtw_get_rateset_len23a( - pmlmeinfo->FW_sta_info[mac_id].SupportedRates); - mask = update_basic_rate23a(cur_network->SupportedRates, - supportRateNum); - break; - default: /* for each sta in IBSS */ - supportRateNum = rtw_get_rateset_len23a( - pmlmeinfo->FW_sta_info[mac_id].SupportedRates); - mask = update_supported_rate23a(cur_network->SupportedRates, - supportRateNum); - break; - } - mask |= ((raid<<28)&0xf0000000); - mask &= 0xffffffff; - mask &= ~filter; - init_rate = get_highest_rate_idx23a(mask)&0x3f; - - arg = mac_id&0x1f;/* MACID */ - arg |= BIT(7); - if (true == shortGIrate) - arg |= BIT(5); - - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], Update FW RAID entry, MASK = 0x%08x, " - "arg = 0x%02x\n", mask, arg)); - - rtl8723a_set_raid_cmd(padapter, mask, arg); - - psta->init_rate = init_rate; - pdmpriv->INIDATA_RATE[mac_id] = init_rate; -} - -static void -btdm_1AntUpdateHalRAMaskForSCO(struct rtw_adapter *padapter, u8 forceUpdate) -{ - struct btdm_8723a_1ant *pBtdm8723; - struct sta_priv *pstapriv; - struct wlan_bssid_ex *cur_network; - struct sta_info *psta; - u32 macid; - u32 filter = 0; - - pBtdm8723 = &GET_HAL_DATA(padapter)->bt_coexist.halCoex8723.btdm1Ant; - - if (pBtdm8723->bRAChanged == true && forceUpdate == false) - return; - - pstapriv = &padapter->stapriv; - cur_network = &padapter->mlmeextpriv.mlmext_info.network; - psta = rtw_get_stainfo23a(pstapriv, cur_network->MacAddress); - macid = psta->mac_id; - - filter |= BIT(_1M_RATE_); - filter |= BIT(_2M_RATE_); - filter |= BIT(_5M_RATE_); - filter |= BIT(_11M_RATE_); - filter |= BIT(_6M_RATE_); - filter |= BIT(_9M_RATE_); - - btdm_1AntUpdateHalRAMask(padapter, macid, filter); - - pBtdm8723->bRAChanged = true; -} - -static void btdm_1AntRecoverHalRAMask(struct rtw_adapter *padapter) -{ - struct btdm_8723a_1ant *pBtdm8723; - struct sta_priv *pstapriv; - struct wlan_bssid_ex *cur_network; - struct sta_info *psta; - - pBtdm8723 = &GET_HAL_DATA(padapter)->bt_coexist.halCoex8723.btdm1Ant; - - if (pBtdm8723->bRAChanged == false) - return; - - pstapriv = &padapter->stapriv; - cur_network = &padapter->mlmeextpriv.mlmext_info.network; - psta = rtw_get_stainfo23a(pstapriv, cur_network->MacAddress); - - Update_RA_Entry23a(padapter, psta); - - pBtdm8723->bRAChanged = false; -} - -static void -btdm_1AntBTStateChangeHandler(struct rtw_adapter *padapter, - enum bt_state_1ant oldState, - enum bt_state_1ant newState) -{ - struct hal_data_8723a *phaldata; - RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT state change, %s => %s\n", - BtStateString[oldState], - BtStateString[newState])); - - /* BT default ignore wlan active, */ - /* WiFi MUST disable this when BT is enable */ - if (newState > BT_INFO_STATE_DISABLED) - btdm_SetFwIgnoreWlanAct(padapter, false); - - if ((check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE)) && - (BTDM_IsWifiConnectionExist(padapter))) { - if ((newState == BT_INFO_STATE_SCO_ONLY_BUSY) || - (newState == BT_INFO_STATE_ACL_SCO_BUSY)) { - btdm_1AntUpdateHalRAMaskForSCO(padapter, false); - } else { - /* Recover original RA setting */ - btdm_1AntRecoverHalRAMask(padapter); - } - } else { - phaldata = GET_HAL_DATA(padapter); - phaldata->bt_coexist.halCoex8723.btdm1Ant.bRAChanged = false; - } - - if (oldState == newState) - return; - - if (oldState == BT_INFO_STATE_ACL_ONLY_BUSY) { - struct hal_data_8723a *Hal = GET_HAL_DATA(padapter); - Hal->bt_coexist.halCoex8723.btdm1Ant.psTdmaMonitorCnt = 0; - Hal->bt_coexist.halCoex8723.btdm1Ant.psTdmaMonitorCntForSCO = 0; - } - - if ((oldState == BT_INFO_STATE_SCO_ONLY_BUSY) || - (oldState == BT_INFO_STATE_ACL_SCO_BUSY)) { - struct hal_data_8723a *Hal = GET_HAL_DATA(padapter); - Hal->bt_coexist.halCoex8723.btdm1Ant.psTdmaMonitorCntForSCO = 0; - } - - /* Active 2Ant mechanism when BT Connected */ - if ((oldState == BT_INFO_STATE_DISABLED) || - (oldState == BT_INFO_STATE_NO_CONNECTION)) { - if ((newState != BT_INFO_STATE_DISABLED) && - (newState != BT_INFO_STATE_NO_CONNECTION)) { - BTDM_SetSwRfRxLpfCorner(padapter, - BT_RF_RX_LPF_CORNER_SHRINK); - BTDM_AGCTable(padapter, BT_AGCTABLE_ON); - BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON); - } - } else { - if ((newState == BT_INFO_STATE_DISABLED) || - (newState == BT_INFO_STATE_NO_CONNECTION)) { - BTDM_SetSwRfRxLpfCorner(padapter, - BT_RF_RX_LPF_CORNER_RESUME); - BTDM_AGCTable(padapter, BT_AGCTABLE_OFF); - BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_OFF); - } - } -} - -static void btdm_1AntBtCoexistHandler(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - struct bt_coexist_8723a *pBtCoex8723; - struct btdm_8723a_1ant *pBtdm8723; - - pHalData = GET_HAL_DATA(padapter); - pBtCoex8723 = &pHalData->bt_coexist.halCoex8723; - pBtdm8723 = &pBtCoex8723->btdm1Ant; - padapter->pwrctrlpriv.btcoex_rfon = false; - if (!rtl8723a_BT_enabled(padapter)) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT is disabled\n")); - - if (BTDM_IsWifiConnectionExist(padapter)) { - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], wifi is connected\n")); - - if (BTDM_IsWifiBusy(padapter)) { - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], Wifi is busy\n")); - btdm_1AntSetPSTDMA(padapter, false, 0, - false, 9); - } else { - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], Wifi is idle\n")); - _btdm_1AntSetPSTDMA(padapter, true, 2, 1, - false, 9); - } - } else { - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], wifi is disconnected\n")); - - btdm_1AntSetPSTDMA(padapter, false, 0, false, 9); - } - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT is enabled\n")); - - if (BTDM_IsWifiConnectionExist(padapter)) { - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], wifi is connected\n")); - - btdm_1AntWifiParaAdjust(padapter, true); - btdm_1AntCoexProcessForWifiConnect(padapter); - } else { - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], wifi is disconnected\n")); - - /* Antenna switch at BT side(0x870 = 0x300, - 0x860 = 0x210) after PSTDMA off */ - btdm_1AntWifiParaAdjust(padapter, false); - btdm_1AntSetPSTDMA(padapter, false, 0, false, 0); - } - } - - btdm_1AntBTStateChangeHandler(padapter, pBtCoex8723->prec2hBtInfo, - pBtCoex8723->c2hBtInfo); - pBtCoex8723->prec2hBtInfo = pBtCoex8723->c2hBtInfo; -} - -void BTDM_1AntSignalCompensation(struct rtw_adapter *padapter, - u8 *rssi_wifi, u8 *rssi_bt) -{ - struct hal_data_8723a *pHalData; - struct btdm_8723a_1ant *pBtdm8723; - u8 RSSI_WiFi_Cmpnstn, RSSI_BT_Cmpnstn; - - pHalData = GET_HAL_DATA(padapter); - pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm1Ant; - RSSI_WiFi_Cmpnstn = 0; - RSSI_BT_Cmpnstn = 0; - - switch (pBtdm8723->curPsTdma) { - case 1: /* WiFi 52ms */ - RSSI_WiFi_Cmpnstn = 11; /* 22*0.48 */ - break; - case 2: /* WiFi 36ms */ - RSSI_WiFi_Cmpnstn = 14; /* 22*0.64 */ - break; - case 9: /* WiFi 20ms */ - RSSI_WiFi_Cmpnstn = 18; /* 22*0.80 */ - break; - case 11: /* WiFi 10ms */ - RSSI_WiFi_Cmpnstn = 20; /* 22*0.90 */ - break; - case 4: /* WiFi 21ms */ - RSSI_WiFi_Cmpnstn = 17; /* 22*0.79 */ - break; - case 16: /* WiFi 24ms */ - RSSI_WiFi_Cmpnstn = 18; /* 22*0.76 */ - break; - case 18: /* WiFi 37ms */ - RSSI_WiFi_Cmpnstn = 14; /* 22*0.64 */ - break; - case 23: /* Level-1, Antenna switch to BT at all time */ - case 24: /* Level-2, Antenna switch to BT at all time */ - case 25: /* Level-3a, Antenna switch to BT at all time */ - case 26: /* Level-3b, Antenna switch to BT at all time */ - case 27: /* Level-3b, Antenna switch to BT at all time */ - case 33: /* BT SCO & WiFi site survey */ - RSSI_WiFi_Cmpnstn = 22; - break; - default: - break; - } - - if (rssi_wifi && RSSI_WiFi_Cmpnstn) { - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], 1AntSgnlCmpnstn, case %d, WiFiCmpnstn " - "=%d(%d => %d)\n", pBtdm8723->curPsTdma, - RSSI_WiFi_Cmpnstn, *rssi_wifi, - *rssi_wifi+RSSI_WiFi_Cmpnstn)); - *rssi_wifi += RSSI_WiFi_Cmpnstn; - } - - if (rssi_bt && RSSI_BT_Cmpnstn) { - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], 1AntSgnlCmpnstn, case %d, BTCmpnstn " - "=%d(%d => %d)\n", pBtdm8723->curPsTdma, - RSSI_BT_Cmpnstn, *rssi_bt, *rssi_bt+RSSI_BT_Cmpnstn)); - *rssi_bt += RSSI_BT_Cmpnstn; - } -} - -static void BTDM_1AntParaInit(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - struct bt_coexist_8723a *pBtCoex; - struct btdm_8723a_1ant *pBtdm8723; - - pHalData = GET_HAL_DATA(padapter); - pBtCoex = &pHalData->bt_coexist.halCoex8723; - pBtdm8723 = &pBtCoex->btdm1Ant; - - /* Enable counter statistics */ - rtl8723au_write8(padapter, 0x76e, 0x4); - btdm_1AntPtaParaReload(padapter); - - pBtdm8723->wifiRssiThresh = 48; - - pBtdm8723->bWiFiHalt = false; - pBtdm8723->bRAChanged = false; - - if ((pBtCoex->c2hBtInfo != BT_INFO_STATE_DISABLED) && - (pBtCoex->c2hBtInfo != BT_INFO_STATE_NO_CONNECTION)) { - BTDM_SetSwRfRxLpfCorner(padapter, BT_RF_RX_LPF_CORNER_SHRINK); - BTDM_AGCTable(padapter, BT_AGCTABLE_ON); - BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON); - } -} - -static void BTDM_1AntForHalt(struct rtw_adapter *padapter) -{ - RTPRINT(FBT, BT_TRACE, ("\n[BTCoex], 1Ant for halt\n")); - - GET_HAL_DATA(padapter)->bt_coexist.halCoex8723.btdm1Ant.bWiFiHalt = - true; - - btdm_1AntWifiParaAdjust(padapter, false); - - /* don't use btdm_1AntSetPSTDMA() here */ - /* it will call rtw_set_ps_mode23a() and request pwrpriv->lock. */ - /* This will lead to deadlock, if this function is called in IPS */ - /* Lucas@20130205 */ - btdm_1AntPsTdma(padapter, false, 0); - - btdm_SetFwIgnoreWlanAct(padapter, true); -} - -static void BTDM_1AntLpsLeave(struct rtw_adapter *padapter) -{ - RTPRINT(FBT, BT_TRACE, ("\n[BTCoex], 1Ant for LPS Leave\n")); - - /* Prevent from entering LPS again */ - GET_HAL_DATA(padapter)->bt_coexist.halCoex8723.btdm1Ant.bWiFiHalt = - true; - - btdm_1AntSetPSTDMA(padapter, false, 0, false, 8); -/*btdm_1AntPsTdma(padapter, false, 8); */ -} - -static void BTDM_1AntWifiAssociateNotify(struct rtw_adapter *padapter, u8 type) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - RTPRINT(FBT, BT_TRACE, - ("\n[BTCoex], 1Ant for associate, type =%d\n", type)); - - if (type) { - rtl8723a_CheckAntenna_Selection(padapter); - if (!rtl8723a_BT_enabled(padapter)) - btdm_1AntSetPSTDMA(padapter, false, 0, false, 9); - else { - struct bt_coexist_8723a *pBtCoex; - u8 BtState; - - pBtCoex = &pHalData->bt_coexist.halCoex8723; - BtState = pBtCoex->c2hBtInfo; - - btdm_1AntTSFSwitch(padapter, true); - - if (BtState == BT_INFO_STATE_NO_CONNECTION || - BtState == BT_INFO_STATE_CONNECT_IDLE) { - btdm_1AntSetPSTDMA(padapter, false, 0, - true, 28); - } else if (BtState == BT_INFO_STATE_SCO_ONLY_BUSY || - BtState == BT_INFO_STATE_ACL_SCO_BUSY) { - btdm_1AntSetPSTDMA(padapter, false, 0, - false, 8); - rtl8723au_write32(padapter, 0x6c0, 0x5a5a5a5a); - rtl8723au_write32(padapter, 0x6c4, 0x5a5a5a5a); - } else if (BtState == BT_INFO_STATE_ACL_ONLY_BUSY || - BtState == BT_INFO_STATE_ACL_INQ_OR_PAG) { - if (pBtCoex->c2hBtProfile == BT_INFO_HID) - btdm_1AntSetPSTDMA(padapter, false, 0, - true, 35); - else - btdm_1AntSetPSTDMA(padapter, false, 0, - true, 29); - } - } - } else { - if (!rtl8723a_BT_enabled(padapter)) { - if (!BTDM_IsWifiConnectionExist(padapter)) { - btdm_1AntPsTdma(padapter, false, 0); - btdm_1AntTSFSwitch(padapter, false); - } - } - - btdm_1AntBtCoexistHandler(padapter); - } -} - -static void -BTDM_1AntMediaStatusNotify(struct rtw_adapter *padapter, - enum rt_media_status mstatus) -{ - struct bt_coexist_8723a *pBtCoex; - - pBtCoex = &GET_HAL_DATA(padapter)->bt_coexist.halCoex8723; - - RTPRINT(FBT, BT_TRACE, - ("\n\n[BTCoex]******************************\n")); - RTPRINT(FBT, BT_TRACE, ("[BTCoex], MediaStatus, WiFi %s !!\n", - mstatus == RT_MEDIA_CONNECT?"CONNECT":"DISCONNECT")); - RTPRINT(FBT, BT_TRACE, ("[BTCoex]******************************\n")); - - if (RT_MEDIA_CONNECT == mstatus) { - if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE)) { - if (pBtCoex->c2hBtInfo == BT_INFO_STATE_SCO_ONLY_BUSY || - pBtCoex->c2hBtInfo == BT_INFO_STATE_ACL_SCO_BUSY) - btdm_1AntUpdateHalRAMaskForSCO(padapter, true); - } - - padapter->pwrctrlpriv.DelayLPSLastTimeStamp = jiffies; - BTDM_1AntForDhcp(padapter); - } else { - /* DBG_8723A("%s rtl8723a_DeinitAntenna_Selection\n", - __func__); */ - rtl8723a_DeinitAntenna_Selection(padapter); - btdm_1AntBtCoexistHandler(padapter); - pBtCoex->btdm1Ant.bRAChanged = false; - } -} - -void BTDM_1AntForDhcp(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - u8 BtState; - struct bt_coexist_8723a *pBtCoex; - struct btdm_8723a_1ant *pBtdm8723; - - pHalData = GET_HAL_DATA(padapter); - pBtCoex = &pHalData->bt_coexist.halCoex8723; - BtState = pBtCoex->c2hBtInfo; - pBtdm8723 = &pBtCoex->btdm1Ant; - - RTPRINT(FBT, BT_TRACE, ("\n[BTCoex], 1Ant for DHCP\n")); - RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1Ant for DHCP, WiFi is %s\n", - BTDM_IsWifiBusy(padapter)?"Busy":"IDLE")); - RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1Ant for DHCP, %s\n", - BtStateString[BtState])); - - BTDM_1AntWifiAssociateNotify(padapter, true); -} - -static void BTDM_1AntWifiScanNotify(struct rtw_adapter *padapter, u8 scanType) -{ - struct hal_data_8723a *pHalData; - u8 BtState; - struct bt_coexist_8723a *pBtCoex; - struct btdm_8723a_1ant *pBtdm8723; - - pHalData = GET_HAL_DATA(padapter); - BtState = pHalData->bt_coexist.halCoex8723.c2hBtInfo; - pBtCoex = &pHalData->bt_coexist.halCoex8723; - pBtdm8723 = &pBtCoex->btdm1Ant; - - RTPRINT(FBT, BT_TRACE, ("\n[BTCoex], 1Ant for wifi scan =%d!!\n", - scanType)); - RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1Ant for wifi scan, WiFi is %s\n", - BTDM_IsWifiBusy(padapter)?"Busy":"IDLE")); - RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1Ant for wifi scan, %s\n", - BtStateString[BtState])); - - if (scanType) { - rtl8723a_CheckAntenna_Selection(padapter); - if (!rtl8723a_BT_enabled(padapter)) { - btdm_1AntSetPSTDMA(padapter, false, 0, false, 9); - } else if (BTDM_IsWifiConnectionExist(padapter) == false) { - BTDM_1AntWifiAssociateNotify(padapter, true); - } else { - if ((BtState == BT_INFO_STATE_SCO_ONLY_BUSY) || - (BtState == BT_INFO_STATE_ACL_SCO_BUSY)) { - if (pBtCoex->bC2hBtInquiryPage) { - btdm_1AntSetPSTDMA(padapter, false, 0, - true, 32); - } else { - padapter->pwrctrlpriv.btcoex_rfon = - true; - btdm_1AntSetPSTDMA(padapter, true, 0, - true, 33); - } - } else if (true == pBtCoex->bC2hBtInquiryPage) { - padapter->pwrctrlpriv.btcoex_rfon = true; - btdm_1AntSetPSTDMA(padapter, true, 0, true, 30); - } else if (BtState == BT_INFO_STATE_ACL_ONLY_BUSY) { - padapter->pwrctrlpriv.btcoex_rfon = true; - if (pBtCoex->c2hBtProfile == BT_INFO_HID) - btdm_1AntSetPSTDMA(padapter, true, 0, - true, 34); - else - btdm_1AntSetPSTDMA(padapter, true, 0, - true, 4); - } else { - padapter->pwrctrlpriv.btcoex_rfon = true; - btdm_1AntSetPSTDMA(padapter, true, 0, true, 5); - } - } - - btdm_NotifyFwScan(padapter, 1); - } else { - /* WiFi_Finish_Scan */ - btdm_NotifyFwScan(padapter, 0); - btdm_1AntBtCoexistHandler(padapter); - } -} - -static void BTDM_1AntFwC2hBtInfo8723A(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - struct bt_30info *pBTInfo; - struct bt_mgnt *pBtMgnt; - struct bt_coexist_8723a *pBtCoex; - u8 u1tmp, btState; - - pHalData = GET_HAL_DATA(padapter); - pBTInfo = GET_BT_INFO(padapter); - pBtMgnt = &pBTInfo->BtMgnt; - pBtCoex = &pHalData->bt_coexist.halCoex8723; - - u1tmp = pBtCoex->c2hBtInfoOriginal; - /* sco BUSY bit is not used on voice over PCM platform */ - btState = u1tmp & 0xF; - pBtCoex->c2hBtProfile = u1tmp & 0xE0; - - /* default set bt to idle state. */ - pBtMgnt->ExtConfig.bBTBusy = false; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_IDLE; - - /* check BIT2 first ==> check if bt is under inquiry or page scan */ - if (btState & BIT(2)) - pBtCoex->bC2hBtInquiryPage = true; - else - pBtCoex->bC2hBtInquiryPage = false; - btState &= ~BIT(2); - - if (!(btState & BIT(0))) - pBtCoex->c2hBtInfo = BT_INFO_STATE_NO_CONNECTION; - else { - if (btState == 0x1) - pBtCoex->c2hBtInfo = BT_INFO_STATE_CONNECT_IDLE; - else if (btState == 0x9) { - if (pBtCoex->bC2hBtInquiryPage == true) - pBtCoex->c2hBtInfo = - BT_INFO_STATE_ACL_INQ_OR_PAG; - else - pBtCoex->c2hBtInfo = - BT_INFO_STATE_ACL_ONLY_BUSY; - pBtMgnt->ExtConfig.bBTBusy = true; - } else if (btState == 0x3) { - pBtCoex->c2hBtInfo = BT_INFO_STATE_SCO_ONLY_BUSY; - pBtMgnt->ExtConfig.bBTBusy = true; - } else if (btState == 0xb) { - pBtCoex->c2hBtInfo = BT_INFO_STATE_ACL_SCO_BUSY; - pBtMgnt->ExtConfig.bBTBusy = true; - } else - pBtCoex->c2hBtInfo = BT_INFO_STATE_MAX; - if (pBtMgnt->ExtConfig.bBTBusy) - pHalData->bt_coexist.CurrentState &= - ~BT_COEX_STATE_BT_IDLE; - } - - if (BT_INFO_STATE_NO_CONNECTION == pBtCoex->c2hBtInfo || - BT_INFO_STATE_CONNECT_IDLE == pBtCoex->c2hBtInfo) { - if (pBtCoex->bC2hBtInquiryPage) - pBtCoex->c2hBtInfo = BT_INFO_STATE_INQ_OR_PAG; - } - - RTPRINT(FBT, BT_TRACE, ("[BTC2H], %s(%d)\n", - BtStateString[pBtCoex->c2hBtInfo], pBtCoex->c2hBtInfo)); - - if (pBtCoex->c2hBtProfile != BT_INFO_HID) - pBtCoex->c2hBtProfile &= ~BT_INFO_HID; -} - -void BTDM_1AntBtCoexist8723A(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv; - struct hal_data_8723a *pHalData; - unsigned long delta_time; - - pmlmepriv = &padapter->mlmepriv; - pHalData = GET_HAL_DATA(padapter); - - if (check_fwstate(pmlmepriv, WIFI_SITE_MONITOR)) { - /* already done in BTDM_1AntForScan() */ - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], wifi is under scan progress!!\n")); - return; - } - - if (check_fwstate(pmlmepriv, WIFI_UNDER_LINKING)) { - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], wifi is under link progress!!\n")); - return; - } - - /* under DHCP(Special packet) */ - delta_time = jiffies - padapter->pwrctrlpriv.DelayLPSLastTimeStamp; - delta_time = jiffies_to_msecs(delta_time); - if (delta_time < 500) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], wifi is under DHCP " - "progress(%li ms)!!\n", delta_time)); - return; - } - - BTDM_CheckWiFiState(padapter); - - btdm_1AntBtCoexistHandler(padapter); -} - -/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtc87231Ant.c ===== */ - -/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtc87232Ant.c ===== */ - -/* local function start with btdm_ */ -static u8 btdm_ActionAlgorithm(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - u8 bScoExist = false, bBtLinkExist = false, bBtHsModeExist = false; - u8 algorithm = BT_2ANT_COEX_ALGO_UNDEFINED; - - if (pBtMgnt->ExtConfig.NumberOfHandle) - bBtLinkExist = true; - if (pBtMgnt->ExtConfig.NumberOfSCO) - bScoExist = true; - if (BT_HsConnectionEstablished(padapter)) - bBtHsModeExist = true; - - /* here we get BT status first */ - /* 1) initialize */ - pBtdm8723->btStatus = BT_2ANT_BT_STATUS_IDLE; - - if ((bScoExist) || (bBtHsModeExist) || - (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID))) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO or HID or HS exists, set BT non-idle !!!\n")); - pBtdm8723->btStatus = BT_2ANT_BT_STATUS_NON_IDLE; - } else { - /* A2dp profile */ - if ((pBtMgnt->ExtConfig.NumberOfHandle == 1) && - (BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP))) { - if (BTDM_BtTxRxCounterL(padapter) < 100) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP, low priority tx+rx < 100, set BT connected-idle!!!\n")); - pBtdm8723->btStatus = BT_2ANT_BT_STATUS_CONNECTED_IDLE; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP, low priority tx+rx >= 100, set BT non-idle!!!\n")); - pBtdm8723->btStatus = BT_2ANT_BT_STATUS_NON_IDLE; - } - } - /* Pan profile */ - if ((pBtMgnt->ExtConfig.NumberOfHandle == 1) && - (BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN))) { - if (BTDM_BtTxRxCounterL(padapter) < 600) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN, low priority tx+rx < 600, set BT connected-idle!!!\n")); - pBtdm8723->btStatus = BT_2ANT_BT_STATUS_CONNECTED_IDLE; - } else { - if (pHalData->bt_coexist.halCoex8723.lowPriorityTx) { - if ((pHalData->bt_coexist.halCoex8723.lowPriorityRx / - pHalData->bt_coexist.halCoex8723.lowPriorityTx) > 9) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN, low priority rx/tx > 9, set BT connected-idle!!!\n")); - pBtdm8723->btStatus = BT_2ANT_BT_STATUS_CONNECTED_IDLE; - } - } - } - if (BT_2ANT_BT_STATUS_CONNECTED_IDLE != pBtdm8723->btStatus) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN, set BT non-idle!!!\n")); - pBtdm8723->btStatus = BT_2ANT_BT_STATUS_NON_IDLE; - } - } - /* Pan+A2dp profile */ - if ((pBtMgnt->ExtConfig.NumberOfHandle == 2) && - (BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) && - (BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN))) { - if (BTDM_BtTxRxCounterL(padapter) < 600) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN+A2DP, low priority tx+rx < 600, set BT connected-idle!!!\n")); - pBtdm8723->btStatus = BT_2ANT_BT_STATUS_CONNECTED_IDLE; - } else { - if (pHalData->bt_coexist.halCoex8723.lowPriorityTx) { - if ((pHalData->bt_coexist.halCoex8723.lowPriorityRx / - pHalData->bt_coexist.halCoex8723.lowPriorityTx) > 9) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN+A2DP, low priority rx/tx > 9, set BT connected-idle!!!\n")); - pBtdm8723->btStatus = BT_2ANT_BT_STATUS_CONNECTED_IDLE; - } - } - } - if (BT_2ANT_BT_STATUS_CONNECTED_IDLE != pBtdm8723->btStatus) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN+A2DP, set BT non-idle!!!\n")); - pBtdm8723->btStatus = BT_2ANT_BT_STATUS_NON_IDLE; - } - } - } - if (BT_2ANT_BT_STATUS_IDLE != pBtdm8723->btStatus) - pBtMgnt->ExtConfig.bBTBusy = true; - else - pBtMgnt->ExtConfig.bBTBusy = false; - - if (!bBtLinkExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], No profile exists!!!\n")); - return algorithm; - } - - if (pBtMgnt->ExtConfig.NumberOfHandle == 1) { - if (bScoExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO only\n")); - algorithm = BT_2ANT_COEX_ALGO_SCO; - } else { - if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID)) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID only\n")); - algorithm = BT_2ANT_COEX_ALGO_HID; - } else if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP only\n")); - algorithm = BT_2ANT_COEX_ALGO_A2DP; - } else if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN)) { - if (bBtHsModeExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN(HS) only\n")); - algorithm = BT_2ANT_COEX_ALGO_PANHS; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN(EDR) only\n")); - algorithm = BT_2ANT_COEX_ALGO_PANEDR; - } - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! NO matched profile for NumberOfHandle =%d \n", - pBtMgnt->ExtConfig.NumberOfHandle)); - } - } - } else if (pBtMgnt->ExtConfig.NumberOfHandle == 2) { - if (bScoExist) { - if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID)) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + HID\n")); - algorithm = BT_2ANT_COEX_ALGO_HID; - } else if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO + A2DP\n")); - } else if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN)) { - if (bBtHsModeExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + PAN(HS)\n")); - algorithm = BT_2ANT_COEX_ALGO_SCO; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + PAN(EDR)\n")); - algorithm = BT_2ANT_COEX_ALGO_PANEDR_HID; - } - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO exists but why NO matched ACL profile for NumberOfHandle =%d\n", - pBtMgnt->ExtConfig.NumberOfHandle)); - } - } else { - if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID) && - BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP\n")); - algorithm = BT_2ANT_COEX_ALGO_HID_A2DP; - } else if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID) && - BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN)) { - if (bBtHsModeExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + PAN(HS)\n")); - algorithm = BT_2ANT_COEX_ALGO_HID_A2DP; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + PAN(EDR)\n")); - algorithm = BT_2ANT_COEX_ALGO_PANEDR_HID; - } - } else if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN) && - BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) { - if (bBtHsModeExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP + PAN(HS)\n")); - algorithm = BT_2ANT_COEX_ALGO_A2DP; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP + PAN(EDR)\n")); - algorithm = BT_2ANT_COEX_ALGO_PANEDR_A2DP; - } - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! NO matched profile for NumberOfHandle =%d\n", - pBtMgnt->ExtConfig.NumberOfHandle)); - } - } - } else if (pBtMgnt->ExtConfig.NumberOfHandle == 3) { - if (bScoExist) { - if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID) && - BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO + HID + A2DP\n")); - } else if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID) && - BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN)) { - if (bBtHsModeExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + HID + PAN(HS)\n")); - algorithm = BT_2ANT_COEX_ALGO_HID_A2DP; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + HID + PAN(EDR)\n")); - algorithm = BT_2ANT_COEX_ALGO_PANEDR_HID; - } - } else if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN) && - BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) { - if (bBtHsModeExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO + A2DP + PAN(HS)\n")); - algorithm = BT_2ANT_COEX_ALGO_SCO; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO + A2DP + PAN(EDR)\n")); - } - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO exists but why NO matched profile for NumberOfHandle =%d\n", - pBtMgnt->ExtConfig.NumberOfHandle)); - } - } else { - if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID) && - BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN) && - BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) { - if (bBtHsModeExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP + PAN(HS)\n")); - algorithm = BT_2ANT_COEX_ALGO_HID_A2DP_PANHS; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP + PAN(EDR)\n")); - algorithm = BT_2ANT_COEX_ALGO_HID_A2DP_PANEDR; - } - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! NO matched profile for NumberOfHandle =%d\n", - pBtMgnt->ExtConfig.NumberOfHandle)); - } - } - } else if (pBtMgnt->ExtConfig.NumberOfHandle >= 3) { - if (bScoExist) { - if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID) && - BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN) && - BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) { - if (bBtHsModeExist) - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO + HID + A2DP + PAN(HS)\n")); - else - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO + HID + A2DP + PAN(EDR)\n")); - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO exists but why NO matched profile for NumberOfHandle =%d\n", - pBtMgnt->ExtConfig.NumberOfHandle)); - } - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! NO matched profile for NumberOfHandle =%d\n", - pBtMgnt->ExtConfig.NumberOfHandle)); - } - } - return algorithm; -} - -static u8 btdm_NeedToDecBtPwr(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 bRet = false; - - if (BT_Operation(padapter)) { - if (pHalData->dmpriv.EntryMinUndecoratedSmoothedPWDB > 47) { - RTPRINT(FBT, BT_TRACE, ("Need to decrease bt power for HS mode!!\n")); - bRet = true; - } else { - RTPRINT(FBT, BT_TRACE, ("NO Need to decrease bt power for HS mode!!\n")); - } - } else { - if (BTDM_IsWifiConnectionExist(padapter)) { - RTPRINT(FBT, BT_TRACE, ("Need to decrease bt power for Wifi is connected!!\n")); - bRet = true; - } - } - return bRet; -} - -static void -btdm_SetCoexTable(struct rtw_adapter *padapter, u32 val0x6c0, - u32 val0x6c8, u8 val0x6cc) -{ - RTPRINT(FBT, BT_TRACE, ("set coex table, set 0x6c0 = 0x%x\n", val0x6c0)); - rtl8723au_write32(padapter, 0x6c0, val0x6c0); - - RTPRINT(FBT, BT_TRACE, ("set coex table, set 0x6c8 = 0x%x\n", val0x6c8)); - rtl8723au_write32(padapter, 0x6c8, val0x6c8); - - RTPRINT(FBT, BT_TRACE, ("set coex table, set 0x6cc = 0x%x\n", val0x6cc)); - rtl8723au_write8(padapter, 0x6cc, val0x6cc); -} - -static void -btdm_SetSwFullTimeDacSwing(struct rtw_adapter *padapter, u8 bSwDacSwingOn, - u32 swDacSwingLvl) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (bSwDacSwingOn) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], SwDacSwing = 0x%x\n", swDacSwingLvl)); - PHY_SetBBReg(padapter, 0x880, 0xff000000, swDacSwingLvl); - pHalData->bt_coexist.bSWCoexistAllOff = false; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], SwDacSwing Off!\n")); - PHY_SetBBReg(padapter, 0x880, 0xff000000, 0xc0); - } -} - -static void -btdm_SetFwDacSwingLevel(struct rtw_adapter *padapter, u8 dacSwingLvl) -{ - u8 H2C_Parameter[1] = {0}; - - H2C_Parameter[0] = dacSwingLvl; - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Set Dac Swing Level = 0x%x\n", dacSwingLvl)); - RTPRINT(FBT, BT_TRACE, ("[BTCoex], write 0x29 = 0x%x\n", H2C_Parameter[0])); - - FillH2CCmd(padapter, 0x29, 1, H2C_Parameter); -} - -static void btdm_2AntDecBtPwr(struct rtw_adapter *padapter, u8 bDecBtPwr) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], Dec BT power = %s\n", - ((bDecBtPwr) ? "ON" : "OFF"))); - pBtdm8723->bCurDecBtPwr = bDecBtPwr; - - if (pBtdm8723->bPreDecBtPwr == pBtdm8723->bCurDecBtPwr) - return; - - BTDM_SetFwDecBtPwr(padapter, pBtdm8723->bCurDecBtPwr); - - pBtdm8723->bPreDecBtPwr = pBtdm8723->bCurDecBtPwr; -} - -static void -btdm_2AntFwDacSwingLvl(struct rtw_adapter *padapter, u8 fwDacSwingLvl) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], set FW Dac Swing level = %d\n", fwDacSwingLvl)); - pBtdm8723->curFwDacSwingLvl = fwDacSwingLvl; - - /* RTPRINT(FBT, BT_TRACE, ("[BTCoex], preFwDacSwingLvl =%d, curFwDacSwingLvl =%d\n", */ - /*pBtdm8723->preFwDacSwingLvl, pBtdm8723->curFwDacSwingLvl)); */ - - if (pBtdm8723->preFwDacSwingLvl == pBtdm8723->curFwDacSwingLvl) - return; - - btdm_SetFwDacSwingLevel(padapter, pBtdm8723->curFwDacSwingLvl); - - pBtdm8723->preFwDacSwingLvl = pBtdm8723->curFwDacSwingLvl; -} - -static void -btdm_2AntRfShrink(struct rtw_adapter *padapter, u8 bRxRfShrinkOn) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], turn Rx RF Shrink = %s\n", - ((bRxRfShrinkOn) ? "ON" : "OFF"))); - pBtdm8723->bCurRfRxLpfShrink = bRxRfShrinkOn; - - /* RTPRINT(FBT, BT_TRACE, ("[BTCoex], bPreRfRxLpfShrink =%d, bCurRfRxLpfShrink =%d\n", */ - /*pBtdm8723->bPreRfRxLpfShrink, pBtdm8723->bCurRfRxLpfShrink)); */ - - if (pBtdm8723->bPreRfRxLpfShrink == pBtdm8723->bCurRfRxLpfShrink) - return; - - BTDM_SetSwRfRxLpfCorner(padapter, (u8)pBtdm8723->bCurRfRxLpfShrink); - - pBtdm8723->bPreRfRxLpfShrink = pBtdm8723->bCurRfRxLpfShrink; -} - -static void -btdm_2AntLowPenaltyRa(struct rtw_adapter *padapter, u8 bLowPenaltyRa) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], turn LowPenaltyRA = %s\n", - ((bLowPenaltyRa) ? "ON" : "OFF"))); - pBtdm8723->bCurLowPenaltyRa = bLowPenaltyRa; - - /* RTPRINT(FBT, BT_TRACE, ("[BTCoex], bPreLowPenaltyRa =%d, bCurLowPenaltyRa =%d\n", */ - /*pBtdm8723->bPreLowPenaltyRa, pBtdm8723->bCurLowPenaltyRa)); */ - - if (pBtdm8723->bPreLowPenaltyRa == pBtdm8723->bCurLowPenaltyRa) - return; - - BTDM_SetSwPenaltyTxRateAdaptive(padapter, (u8)pBtdm8723->bCurLowPenaltyRa); - - pBtdm8723->bPreLowPenaltyRa = pBtdm8723->bCurLowPenaltyRa; -} - -static void -btdm_2AntDacSwing(struct rtw_adapter *padapter, - u8 bDacSwingOn, u32 dacSwingLvl) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], turn DacSwing =%s, dacSwingLvl = 0x%x\n", - (bDacSwingOn ? "ON" : "OFF"), dacSwingLvl)); - pBtdm8723->bCurDacSwingOn = bDacSwingOn; - pBtdm8723->curDacSwingLvl = dacSwingLvl; - - if ((pBtdm8723->bPreDacSwingOn == pBtdm8723->bCurDacSwingOn) && - (pBtdm8723->preDacSwingLvl == pBtdm8723->curDacSwingLvl)) - return; - - mdelay(30); - btdm_SetSwFullTimeDacSwing(padapter, bDacSwingOn, dacSwingLvl); - - pBtdm8723->bPreDacSwingOn = pBtdm8723->bCurDacSwingOn; - pBtdm8723->preDacSwingLvl = pBtdm8723->curDacSwingLvl; -} - -static void btdm_2AntAdcBackOff(struct rtw_adapter *padapter, u8 bAdcBackOff) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], turn AdcBackOff = %s\n", - ((bAdcBackOff) ? "ON" : "OFF"))); - pBtdm8723->bCurAdcBackOff = bAdcBackOff; - - if (pBtdm8723->bPreAdcBackOff == pBtdm8723->bCurAdcBackOff) - return; - - BTDM_BBBackOffLevel(padapter, (u8)pBtdm8723->bCurAdcBackOff); - - pBtdm8723->bPreAdcBackOff = pBtdm8723->bCurAdcBackOff; -} - -static void btdm_2AntAgcTable(struct rtw_adapter *padapter, u8 bAgcTableEn) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], %s Agc Table\n", ((bAgcTableEn) ? "Enable" : "Disable"))); - pBtdm8723->bCurAgcTableEn = bAgcTableEn; - - /* RTPRINT(FBT, BT_TRACE, ("[BTCoex], bPreAgcTableEn =%d, bCurAgcTableEn =%d\n", */ - /*pBtdm8723->bPreAgcTableEn, pBtdm8723->bCurAgcTableEn)); */ - - if (pBtdm8723->bPreAgcTableEn == pBtdm8723->bCurAgcTableEn) - return; - - BTDM_AGCTable(padapter, (u8)bAgcTableEn); - - pBtdm8723->bPreAgcTableEn = pBtdm8723->bCurAgcTableEn; -} - -static void -btdm_2AntCoexTable(struct rtw_adapter *padapter, - u32 val0x6c0, u32 val0x6c8, u8 val0x6cc) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], write Coex Table 0x6c0 = 0x%x, 0x6c8 = 0x%x, 0x6cc = 0x%x\n", - val0x6c0, val0x6c8, val0x6cc)); - pBtdm8723->curVal0x6c0 = val0x6c0; - pBtdm8723->curVal0x6c8 = val0x6c8; - pBtdm8723->curVal0x6cc = val0x6cc; - - /* RTPRINT(FBT, BT_TRACE, ("[BTCoex], preVal0x6c0 = 0x%x, preVal0x6c8 = 0x%x, preVal0x6cc = 0x%x !!\n", */ - /*pBtdm8723->preVal0x6c0, pBtdm8723->preVal0x6c8, pBtdm8723->preVal0x6cc)); */ - /* RTPRINT(FBT, BT_TRACE, ("[BTCoex], curVal0x6c0 = 0x%x, curVal0x6c8 = 0x%x, curVal0x6cc = 0x%x !!\n", */ - /*pBtdm8723->curVal0x6c0, pBtdm8723->curVal0x6c8, pBtdm8723->curVal0x6cc)); */ - - if ((pBtdm8723->preVal0x6c0 == pBtdm8723->curVal0x6c0) && - (pBtdm8723->preVal0x6c8 == pBtdm8723->curVal0x6c8) && - (pBtdm8723->preVal0x6cc == pBtdm8723->curVal0x6cc)) - return; - - btdm_SetCoexTable(padapter, val0x6c0, val0x6c8, val0x6cc); - - pBtdm8723->preVal0x6c0 = pBtdm8723->curVal0x6c0; - pBtdm8723->preVal0x6c8 = pBtdm8723->curVal0x6c8; - pBtdm8723->preVal0x6cc = pBtdm8723->curVal0x6cc; -} - -static void btdm_2AntIgnoreWlanAct(struct rtw_adapter *padapter, u8 bEnable) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], turn Ignore WlanAct %s\n", (bEnable ? "ON" : "OFF"))); - pBtdm8723->bCurIgnoreWlanAct = bEnable; - - - if (pBtdm8723->bPreIgnoreWlanAct == pBtdm8723->bCurIgnoreWlanAct) - return; - - btdm_SetFwIgnoreWlanAct(padapter, bEnable); - pBtdm8723->bPreIgnoreWlanAct = pBtdm8723->bCurIgnoreWlanAct; -} - -static void -btdm_2AntSetFw3a(struct rtw_adapter *padapter, u8 byte1, u8 byte2, - u8 byte3, u8 byte4, u8 byte5) -{ - u8 H2C_Parameter[5] = {0}; - - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - /* byte1[1:0] != 0 means enable pstdma */ - /* for 2Ant bt coexist, if byte1 != 0 means enable pstdma */ - if (byte1) - pHalData->bt_coexist.bFWCoexistAllOff = false; - H2C_Parameter[0] = byte1; - H2C_Parameter[1] = byte2; - H2C_Parameter[2] = byte3; - H2C_Parameter[3] = byte4; - H2C_Parameter[4] = byte5; - - pHalData->bt_coexist.fw3aVal[0] = byte1; - pHalData->bt_coexist.fw3aVal[1] = byte2; - pHalData->bt_coexist.fw3aVal[2] = byte3; - pHalData->bt_coexist.fw3aVal[3] = byte4; - pHalData->bt_coexist.fw3aVal[4] = byte5; - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], FW write 0x3a(5bytes) = 0x%x%08x\n", - H2C_Parameter[0], - H2C_Parameter[1]<<24|H2C_Parameter[2]<<16|H2C_Parameter[3]<<8|H2C_Parameter[4])); - - FillH2CCmd(padapter, 0x3a, 5, H2C_Parameter); - } - -static void btdm_2AntPsTdma(struct rtw_adapter *padapter, u8 bTurnOn, u8 type) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - u32 btTxRxCnt = 0; - u8 bTurnOnByCnt = false; - u8 psTdmaTypeByCnt = 0; - - btTxRxCnt = BTDM_BtTxRxCounterH(padapter)+BTDM_BtTxRxCounterL(padapter); - RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT TxRx Counters = %d\n", btTxRxCnt)); - if (btTxRxCnt > 3000) { - bTurnOnByCnt = true; - psTdmaTypeByCnt = 8; - - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], For BTTxRxCounters, turn %s PS TDMA, type =%d\n", - (bTurnOnByCnt ? "ON" : "OFF"), psTdmaTypeByCnt)); - pBtdm8723->bCurPsTdmaOn = bTurnOnByCnt; - pBtdm8723->curPsTdma = psTdmaTypeByCnt; - } else { - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], turn %s PS TDMA, type =%d\n", - (bTurnOn ? "ON" : "OFF"), type)); - pBtdm8723->bCurPsTdmaOn = bTurnOn; - pBtdm8723->curPsTdma = type; - } - - if ((pBtdm8723->bPrePsTdmaOn == pBtdm8723->bCurPsTdmaOn) && - (pBtdm8723->prePsTdma == pBtdm8723->curPsTdma)) - return; - - if (bTurnOn) { - switch (type) { - case 1: - default: - btdm_2AntSetFw3a(padapter, 0xe3, 0x1a, 0x1a, 0xa1, 0x98); - break; - case 2: - btdm_2AntSetFw3a(padapter, 0xe3, 0x12, 0x12, 0xa1, 0x98); - break; - case 3: - btdm_2AntSetFw3a(padapter, 0xe3, 0xa, 0xa, 0xa1, 0x98); - break; - case 4: - btdm_2AntSetFw3a(padapter, 0xa3, 0x5, 0x5, 0xa1, 0x80); - break; - case 5: - btdm_2AntSetFw3a(padapter, 0xe3, 0x1a, 0x1a, 0x20, 0x98); - break; - case 6: - btdm_2AntSetFw3a(padapter, 0xe3, 0x12, 0x12, 0x20, 0x98); - break; - case 7: - btdm_2AntSetFw3a(padapter, 0xe3, 0xa, 0xa, 0x20, 0x98); - break; - case 8: - btdm_2AntSetFw3a(padapter, 0xa3, 0x5, 0x5, 0x20, 0x80); - break; - case 9: - btdm_2AntSetFw3a(padapter, 0xe3, 0x1a, 0x1a, 0xa1, 0x98); - break; - case 10: - btdm_2AntSetFw3a(padapter, 0xe3, 0x12, 0x12, 0xa1, 0x98); - break; - case 11: - btdm_2AntSetFw3a(padapter, 0xe3, 0xa, 0xa, 0xa1, 0x98); - break; - case 12: - btdm_2AntSetFw3a(padapter, 0xe3, 0x5, 0x5, 0xa1, 0x98); - break; - case 13: - btdm_2AntSetFw3a(padapter, 0xe3, 0x1a, 0x1a, 0x20, 0x98); - break; - case 14: - btdm_2AntSetFw3a(padapter, 0xe3, 0x12, 0x12, 0x20, 0x98); - break; - case 15: - btdm_2AntSetFw3a(padapter, 0xe3, 0xa, 0xa, 0x20, 0x98); - break; - case 16: - btdm_2AntSetFw3a(padapter, 0xe3, 0x5, 0x5, 0x20, 0x98); - break; - case 17: - btdm_2AntSetFw3a(padapter, 0xa3, 0x2f, 0x2f, 0x20, 0x80); - break; - case 18: - btdm_2AntSetFw3a(padapter, 0xe3, 0x5, 0x5, 0xa1, 0x98); - break; - case 19: - btdm_2AntSetFw3a(padapter, 0xe3, 0x25, 0x25, 0xa1, 0x98); - break; - case 20: - btdm_2AntSetFw3a(padapter, 0xe3, 0x25, 0x25, 0x20, 0x98); - break; - } - } else { - /* disable PS tdma */ - switch (type) { - case 0: - btdm_2AntSetFw3a(padapter, 0x0, 0x0, 0x0, 0x8, 0x0); - break; - case 1: - btdm_2AntSetFw3a(padapter, 0x0, 0x0, 0x0, 0x0, 0x0); - break; - default: - btdm_2AntSetFw3a(padapter, 0x0, 0x0, 0x0, 0x8, 0x0); - break; - } - } - - /* update pre state */ - pBtdm8723->bPrePsTdmaOn = pBtdm8723->bCurPsTdmaOn; - pBtdm8723->prePsTdma = pBtdm8723->curPsTdma; -} - -static void btdm_2AntBtInquiryPage(struct rtw_adapter *padapter) -{ - btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3); - btdm_2AntIgnoreWlanAct(padapter, false); - btdm_2AntPsTdma(padapter, true, 8); -} - -static u8 btdm_HoldForBtInqPage(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u32 curTime = jiffies; - - if (pHalData->bt_coexist.halCoex8723.bC2hBtInquiryPage) { - /* bt inquiry or page is started. */ - if (pHalData->bt_coexist.halCoex8723.btInqPageStartTime == 0) { - pHalData->bt_coexist.halCoex8723.btInqPageStartTime = curTime; - RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT Inquiry/page is started at time : 0x%lx \n", - pHalData->bt_coexist.halCoex8723.btInqPageStartTime)); - } - } - RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT Inquiry/page started time : 0x%lx, curTime : 0x%x \n", - pHalData->bt_coexist.halCoex8723.btInqPageStartTime, curTime)); - - if (pHalData->bt_coexist.halCoex8723.btInqPageStartTime) { - if (((curTime - pHalData->bt_coexist.halCoex8723.btInqPageStartTime)/1000000) >= 10) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT Inquiry/page >= 10sec!!!")); - pHalData->bt_coexist.halCoex8723.btInqPageStartTime = 0; - } - } - - if (pHalData->bt_coexist.halCoex8723.btInqPageStartTime) { - btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3); - btdm_2AntIgnoreWlanAct(padapter, false); - btdm_2AntPsTdma(padapter, true, 8); - return true; - } else { - return false; - } -} - -static u8 btdm_Is2Ant8723ACommonAction(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - u8 bCommon = false; - - RTPRINT(FBT, BT_TRACE, ("%s :BTDM_IsWifiConnectionExist =%x check_fwstate =%x pmlmepriv->fw_state = 0x%x\n", __func__, BTDM_IsWifiConnectionExist(padapter), check_fwstate(&padapter->mlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING)), padapter->mlmepriv.fw_state)); - - if ((!BTDM_IsWifiConnectionExist(padapter)) && - (!check_fwstate(&padapter->mlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING))) && - (BT_2ANT_BT_STATUS_IDLE == pBtdm8723->btStatus)) { - RTPRINT(FBT, BT_TRACE, ("Wifi idle + Bt idle!!\n")); - - btdm_2AntLowPenaltyRa(padapter, false); - btdm_2AntRfShrink(padapter, false); - btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3); - - btdm_2AntIgnoreWlanAct(padapter, false); - btdm_2AntPsTdma(padapter, false, 0); - btdm_2AntFwDacSwingLvl(padapter, 0x20); - btdm_2AntDecBtPwr(padapter, false); - - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - - bCommon = true; - } else if (((BTDM_IsWifiConnectionExist(padapter)) || - (check_fwstate(&padapter->mlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING)))) && - (BT_2ANT_BT_STATUS_IDLE == pBtdm8723->btStatus)) { - RTPRINT(FBT, BT_TRACE, ("Wifi non-idle + BT idle!!\n")); - - btdm_2AntLowPenaltyRa(padapter, true); - btdm_2AntRfShrink(padapter, false); - btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3); - - btdm_2AntIgnoreWlanAct(padapter, false); - btdm_2AntPsTdma(padapter, false, 0); - btdm_2AntFwDacSwingLvl(padapter, 0x20); - btdm_2AntDecBtPwr(padapter, true); - - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - - bCommon = true; - } else if ((!BTDM_IsWifiConnectionExist(padapter)) && - (!check_fwstate(&padapter->mlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING))) && - (BT_2ANT_BT_STATUS_CONNECTED_IDLE == pBtdm8723->btStatus)) { - RTPRINT(FBT, BT_TRACE, ("Wifi idle + Bt connected idle!!\n")); - - btdm_2AntLowPenaltyRa(padapter, true); - btdm_2AntRfShrink(padapter, true); - btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3); - - btdm_2AntIgnoreWlanAct(padapter, false); - btdm_2AntPsTdma(padapter, false, 0); - btdm_2AntFwDacSwingLvl(padapter, 0x20); - btdm_2AntDecBtPwr(padapter, false); - - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - - bCommon = true; - } else if (((BTDM_IsWifiConnectionExist(padapter)) || - (check_fwstate(&padapter->mlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING)))) && - (BT_2ANT_BT_STATUS_CONNECTED_IDLE == pBtdm8723->btStatus)) { - RTPRINT(FBT, BT_TRACE, ("Wifi non-idle + Bt connected idle!!\n")); - - btdm_2AntLowPenaltyRa(padapter, true); - btdm_2AntRfShrink(padapter, true); - btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3); - - btdm_2AntIgnoreWlanAct(padapter, false); - btdm_2AntPsTdma(padapter, false, 0); - btdm_2AntFwDacSwingLvl(padapter, 0x20); - btdm_2AntDecBtPwr(padapter, true); - - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - - bCommon = true; - } else if ((!BTDM_IsWifiConnectionExist(padapter)) && - (!check_fwstate(&padapter->mlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING))) && - (BT_2ANT_BT_STATUS_NON_IDLE == pBtdm8723->btStatus)) { - RTPRINT(FBT, BT_TRACE, ("Wifi idle + BT non-idle!!\n")); - - btdm_2AntLowPenaltyRa(padapter, true); - btdm_2AntRfShrink(padapter, true); - btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3); - - btdm_2AntIgnoreWlanAct(padapter, false); - btdm_2AntPsTdma(padapter, false, 0); - btdm_2AntFwDacSwingLvl(padapter, 0x20); - btdm_2AntDecBtPwr(padapter, false); - - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - - bCommon = true; - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi non-idle + BT non-idle!!\n")); - btdm_2AntLowPenaltyRa(padapter, true); - btdm_2AntRfShrink(padapter, true); - btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3); - btdm_2AntIgnoreWlanAct(padapter, false); - btdm_2AntFwDacSwingLvl(padapter, 0x20); - - bCommon = false; - } - return bCommon; -} - -static void -btdm_2AntTdmaDurationAdjust(struct rtw_adapter *padapter, u8 bScoHid, - u8 bTxPause, u8 maxInterval) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - static s32 up, dn, m, n, WaitCount; - s32 result; /* 0: no change, +1: increase WiFi duration, -1: decrease WiFi duration */ - u8 retryCount = 0; - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], TdmaDurationAdjust()\n")); - - if (pBtdm8723->bResetTdmaAdjust) { - pBtdm8723->bResetTdmaAdjust = false; - RTPRINT(FBT, BT_TRACE, ("[BTCoex], first run TdmaDurationAdjust()!!\n")); - if (bScoHid) { - if (bTxPause) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } - } else { - if (bTxPause) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } - } - up = 0; - dn = 0; - m = 1; - n = 3; - result = 0; - WaitCount = 0; - } else { - /* accquire the BT TRx retry count from BT_Info byte2 */ - retryCount = pHalData->bt_coexist.halCoex8723.btRetryCnt; - RTPRINT(FBT, BT_TRACE, ("[BTCoex], retryCount = %d\n", retryCount)); - result = 0; - WaitCount++; - - if (retryCount == 0) { /* no retry in the last 2-second duration */ - up++; - dn--; - - if (dn <= 0) - dn = 0; - - if (up >= n) { /* if ³sÄò n ­Ó2¬í retry count¬°0, «h½Õ¼eWiFi duration */ - WaitCount = 0; - n = 3; - up = 0; - dn = 0; - result = 1; - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Increase wifi duration!!\n")); - } - } else if (retryCount <= 3) { /* <= 3 retry in the last 2-second duration */ - up--; - dn++; - - if (up <= 0) - up = 0; - - if (dn == 2) { /* if ³sÄò 2 ­Ó2¬í retry count< 3, «h½Õ¯¶WiFi duration */ - if (WaitCount <= 2) - m++; /* ÁקK¤@ª½¦b¨â­Ólevel¤¤¨Ó¦^ */ - else - m = 1; - - if (m >= 20) /* m ³Ì¤j­È = 20 ' ³Ì¤j120¬í recheck¬O§_½Õ¾ã WiFi duration. */ - m = 20; - - n = 3*m; - up = 0; - dn = 0; - WaitCount = 0; - result = -1; - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Decrease wifi duration for retryCounter<3!!\n")); - } - } else { /* retry count > 3, ¥u­n1¦¸ retry count > 3, «h½Õ¯¶WiFi duration */ - if (WaitCount == 1) - m++; /* ÁקK¤@ª½¦b¨â­Ólevel¤¤¨Ó¦^ */ - else - m = 1; - - if (m >= 20) /* m ³Ì¤j­È = 20 ' ³Ì¤j120¬í recheck¬O§_½Õ¾ã WiFi duration. */ - m = 20; - n = 3*m; - up = 0; - dn = 0; - WaitCount = 0; - result = -1; - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Decrease wifi duration for retryCounter>3!!\n")); - } - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], max Interval = %d\n", maxInterval)); - if (maxInterval == 1) { - if (bTxPause) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], TxPause = 1\n")); - if (pBtdm8723->curPsTdma == 1) { - btdm_2AntPsTdma(padapter, true, 5); - pBtdm8723->psTdmaDuAdjType = 5; - } else if (pBtdm8723->curPsTdma == 2) { - btdm_2AntPsTdma(padapter, true, 6); - pBtdm8723->psTdmaDuAdjType = 6; - } else if (pBtdm8723->curPsTdma == 3) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (pBtdm8723->curPsTdma == 4) { - btdm_2AntPsTdma(padapter, true, 8); - pBtdm8723->psTdmaDuAdjType = 8; - } - if (pBtdm8723->curPsTdma == 9) { - btdm_2AntPsTdma(padapter, true, 13); - pBtdm8723->psTdmaDuAdjType = 13; - } else if (pBtdm8723->curPsTdma == 10) { - btdm_2AntPsTdma(padapter, true, 14); - pBtdm8723->psTdmaDuAdjType = 14; - } else if (pBtdm8723->curPsTdma == 11) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (pBtdm8723->curPsTdma == 12) { - btdm_2AntPsTdma(padapter, true, 16); - pBtdm8723->psTdmaDuAdjType = 16; - } - - if (result == -1) { - if (pBtdm8723->curPsTdma == 5) { - btdm_2AntPsTdma(padapter, true, 6); - pBtdm8723->psTdmaDuAdjType = 6; - } else if (pBtdm8723->curPsTdma == 6) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (pBtdm8723->curPsTdma == 7) { - btdm_2AntPsTdma(padapter, true, 8); - pBtdm8723->psTdmaDuAdjType = 8; - } else if (pBtdm8723->curPsTdma == 13) { - btdm_2AntPsTdma(padapter, true, 14); - pBtdm8723->psTdmaDuAdjType = 14; - } else if (pBtdm8723->curPsTdma == 14) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (pBtdm8723->curPsTdma == 15) { - btdm_2AntPsTdma(padapter, true, 16); - pBtdm8723->psTdmaDuAdjType = 16; - } - } else if (result == 1) { - if (pBtdm8723->curPsTdma == 8) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (pBtdm8723->curPsTdma == 7) { - btdm_2AntPsTdma(padapter, true, 6); - pBtdm8723->psTdmaDuAdjType = 6; - } else if (pBtdm8723->curPsTdma == 6) { - btdm_2AntPsTdma(padapter, true, 5); - pBtdm8723->psTdmaDuAdjType = 5; - } else if (pBtdm8723->curPsTdma == 16) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (pBtdm8723->curPsTdma == 15) { - btdm_2AntPsTdma(padapter, true, 14); - pBtdm8723->psTdmaDuAdjType = 14; - } else if (pBtdm8723->curPsTdma == 14) { - btdm_2AntPsTdma(padapter, true, 13); - pBtdm8723->psTdmaDuAdjType = 13; - } - } - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], TxPause = 0\n")); - if (pBtdm8723->curPsTdma == 5) { - btdm_2AntPsTdma(padapter, true, 1); - pBtdm8723->psTdmaDuAdjType = 1; - } else if (pBtdm8723->curPsTdma == 6) { - btdm_2AntPsTdma(padapter, true, 2); - pBtdm8723->psTdmaDuAdjType = 2; - } else if (pBtdm8723->curPsTdma == 7) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (pBtdm8723->curPsTdma == 8) { - btdm_2AntPsTdma(padapter, true, 4); - pBtdm8723->psTdmaDuAdjType = 4; - } - if (pBtdm8723->curPsTdma == 13) { - btdm_2AntPsTdma(padapter, true, 9); - pBtdm8723->psTdmaDuAdjType = 9; - } else if (pBtdm8723->curPsTdma == 14) { - btdm_2AntPsTdma(padapter, true, 10); - pBtdm8723->psTdmaDuAdjType = 10; - } else if (pBtdm8723->curPsTdma == 15) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (pBtdm8723->curPsTdma == 16) { - btdm_2AntPsTdma(padapter, true, 12); - pBtdm8723->psTdmaDuAdjType = 12; - } - - if (result == -1) { - if (pBtdm8723->curPsTdma == 1) { - btdm_2AntPsTdma(padapter, true, 2); - pBtdm8723->psTdmaDuAdjType = 2; - } else if (pBtdm8723->curPsTdma == 2) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (pBtdm8723->curPsTdma == 3) { - btdm_2AntPsTdma(padapter, true, 4); - pBtdm8723->psTdmaDuAdjType = 4; - } else if (pBtdm8723->curPsTdma == 9) { - btdm_2AntPsTdma(padapter, true, 10); - pBtdm8723->psTdmaDuAdjType = 10; - } else if (pBtdm8723->curPsTdma == 10) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (pBtdm8723->curPsTdma == 11) { - btdm_2AntPsTdma(padapter, true, 12); - pBtdm8723->psTdmaDuAdjType = 12; - } - } else if (result == 1) { - if (pBtdm8723->curPsTdma == 4) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (pBtdm8723->curPsTdma == 3) { - btdm_2AntPsTdma(padapter, true, 2); - pBtdm8723->psTdmaDuAdjType = 2; - } else if (pBtdm8723->curPsTdma == 2) { - btdm_2AntPsTdma(padapter, true, 1); - pBtdm8723->psTdmaDuAdjType = 1; - } else if (pBtdm8723->curPsTdma == 12) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (pBtdm8723->curPsTdma == 11) { - btdm_2AntPsTdma(padapter, true, 10); - pBtdm8723->psTdmaDuAdjType = 10; - } else if (pBtdm8723->curPsTdma == 10) { - btdm_2AntPsTdma(padapter, true, 9); - pBtdm8723->psTdmaDuAdjType = 9; - } - } - } - } else if (maxInterval == 2) { - if (bTxPause) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], TxPause = 1\n")); - if (pBtdm8723->curPsTdma == 1) { - btdm_2AntPsTdma(padapter, true, 6); - pBtdm8723->psTdmaDuAdjType = 6; - } else if (pBtdm8723->curPsTdma == 2) { - btdm_2AntPsTdma(padapter, true, 6); - pBtdm8723->psTdmaDuAdjType = 6; - } else if (pBtdm8723->curPsTdma == 3) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (pBtdm8723->curPsTdma == 4) { - btdm_2AntPsTdma(padapter, true, 8); - pBtdm8723->psTdmaDuAdjType = 8; - } - if (pBtdm8723->curPsTdma == 9) { - btdm_2AntPsTdma(padapter, true, 14); - pBtdm8723->psTdmaDuAdjType = 14; - } else if (pBtdm8723->curPsTdma == 10) { - btdm_2AntPsTdma(padapter, true, 14); - pBtdm8723->psTdmaDuAdjType = 14; - } else if (pBtdm8723->curPsTdma == 11) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (pBtdm8723->curPsTdma == 12) { - btdm_2AntPsTdma(padapter, true, 16); - pBtdm8723->psTdmaDuAdjType = 16; - } - if (result == -1) { - if (pBtdm8723->curPsTdma == 5) { - btdm_2AntPsTdma(padapter, true, 6); - pBtdm8723->psTdmaDuAdjType = 6; - } else if (pBtdm8723->curPsTdma == 6) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (pBtdm8723->curPsTdma == 7) { - btdm_2AntPsTdma(padapter, true, 8); - pBtdm8723->psTdmaDuAdjType = 8; - } else if (pBtdm8723->curPsTdma == 13) { - btdm_2AntPsTdma(padapter, true, 14); - pBtdm8723->psTdmaDuAdjType = 14; - } else if (pBtdm8723->curPsTdma == 14) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (pBtdm8723->curPsTdma == 15) { - btdm_2AntPsTdma(padapter, true, 16); - pBtdm8723->psTdmaDuAdjType = 16; - } - } else if (result == 1) { - if (pBtdm8723->curPsTdma == 8) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (pBtdm8723->curPsTdma == 7) { - btdm_2AntPsTdma(padapter, true, 6); - pBtdm8723->psTdmaDuAdjType = 6; - } else if (pBtdm8723->curPsTdma == 6) { - btdm_2AntPsTdma(padapter, true, 6); - pBtdm8723->psTdmaDuAdjType = 6; - } else if (pBtdm8723->curPsTdma == 16) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (pBtdm8723->curPsTdma == 15) { - btdm_2AntPsTdma(padapter, true, 14); - pBtdm8723->psTdmaDuAdjType = 14; - } else if (pBtdm8723->curPsTdma == 14) { - btdm_2AntPsTdma(padapter, true, 14); - pBtdm8723->psTdmaDuAdjType = 14; - } - } - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], TxPause = 0\n")); - if (pBtdm8723->curPsTdma == 5) { - btdm_2AntPsTdma(padapter, true, 2); - pBtdm8723->psTdmaDuAdjType = 2; - } else if (pBtdm8723->curPsTdma == 6) { - btdm_2AntPsTdma(padapter, true, 2); - pBtdm8723->psTdmaDuAdjType = 2; - } else if (pBtdm8723->curPsTdma == 7) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (pBtdm8723->curPsTdma == 8) { - btdm_2AntPsTdma(padapter, true, 4); - pBtdm8723->psTdmaDuAdjType = 4; - } - if (pBtdm8723->curPsTdma == 13) { - btdm_2AntPsTdma(padapter, true, 10); - pBtdm8723->psTdmaDuAdjType = 10; - } else if (pBtdm8723->curPsTdma == 14) { - btdm_2AntPsTdma(padapter, true, 10); - pBtdm8723->psTdmaDuAdjType = 10; - } else if (pBtdm8723->curPsTdma == 15) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (pBtdm8723->curPsTdma == 16) { - btdm_2AntPsTdma(padapter, true, 12); - pBtdm8723->psTdmaDuAdjType = 12; - } - if (result == -1) { - if (pBtdm8723->curPsTdma == 1) { - btdm_2AntPsTdma(padapter, true, 2); - pBtdm8723->psTdmaDuAdjType = 2; - } else if (pBtdm8723->curPsTdma == 2) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (pBtdm8723->curPsTdma == 3) { - btdm_2AntPsTdma(padapter, true, 4); - pBtdm8723->psTdmaDuAdjType = 4; - } else if (pBtdm8723->curPsTdma == 9) { - btdm_2AntPsTdma(padapter, true, 10); - pBtdm8723->psTdmaDuAdjType = 10; - } else if (pBtdm8723->curPsTdma == 10) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (pBtdm8723->curPsTdma == 11) { - btdm_2AntPsTdma(padapter, true, 12); - pBtdm8723->psTdmaDuAdjType = 12; - } - } else if (result == 1) { - if (pBtdm8723->curPsTdma == 4) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (pBtdm8723->curPsTdma == 3) { - btdm_2AntPsTdma(padapter, true, 2); - pBtdm8723->psTdmaDuAdjType = 2; - } else if (pBtdm8723->curPsTdma == 2) { - btdm_2AntPsTdma(padapter, true, 2); - pBtdm8723->psTdmaDuAdjType = 2; - } else if (pBtdm8723->curPsTdma == 12) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (pBtdm8723->curPsTdma == 11) { - btdm_2AntPsTdma(padapter, true, 10); - pBtdm8723->psTdmaDuAdjType = 10; - } else if (pBtdm8723->curPsTdma == 10) { - btdm_2AntPsTdma(padapter, true, 10); - pBtdm8723->psTdmaDuAdjType = 10; - } - } - } - } else if (maxInterval == 3) { - if (bTxPause) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], TxPause = 1\n")); - if (pBtdm8723->curPsTdma == 1) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (pBtdm8723->curPsTdma == 2) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (pBtdm8723->curPsTdma == 3) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (pBtdm8723->curPsTdma == 4) { - btdm_2AntPsTdma(padapter, true, 8); - pBtdm8723->psTdmaDuAdjType = 8; - } - if (pBtdm8723->curPsTdma == 9) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (pBtdm8723->curPsTdma == 10) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (pBtdm8723->curPsTdma == 11) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (pBtdm8723->curPsTdma == 12) { - btdm_2AntPsTdma(padapter, true, 16); - pBtdm8723->psTdmaDuAdjType = 16; - } - if (result == -1) { - if (pBtdm8723->curPsTdma == 5) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (pBtdm8723->curPsTdma == 6) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (pBtdm8723->curPsTdma == 7) { - btdm_2AntPsTdma(padapter, true, 8); - pBtdm8723->psTdmaDuAdjType = 8; - } else if (pBtdm8723->curPsTdma == 13) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (pBtdm8723->curPsTdma == 14) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (pBtdm8723->curPsTdma == 15) { - btdm_2AntPsTdma(padapter, true, 16); - pBtdm8723->psTdmaDuAdjType = 16; - } - } else if (result == 1) { - if (pBtdm8723->curPsTdma == 8) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (pBtdm8723->curPsTdma == 7) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (pBtdm8723->curPsTdma == 6) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (pBtdm8723->curPsTdma == 16) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (pBtdm8723->curPsTdma == 15) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (pBtdm8723->curPsTdma == 14) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } - } - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], TxPause = 0\n")); - if (pBtdm8723->curPsTdma == 5) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (pBtdm8723->curPsTdma == 6) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (pBtdm8723->curPsTdma == 7) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (pBtdm8723->curPsTdma == 8) { - btdm_2AntPsTdma(padapter, true, 4); - pBtdm8723->psTdmaDuAdjType = 4; - } - if (pBtdm8723->curPsTdma == 13) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (pBtdm8723->curPsTdma == 14) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (pBtdm8723->curPsTdma == 15) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (pBtdm8723->curPsTdma == 16) { - btdm_2AntPsTdma(padapter, true, 12); - pBtdm8723->psTdmaDuAdjType = 12; - } - if (result == -1) { - if (pBtdm8723->curPsTdma == 1) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (pBtdm8723->curPsTdma == 2) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (pBtdm8723->curPsTdma == 3) { - btdm_2AntPsTdma(padapter, true, 4); - pBtdm8723->psTdmaDuAdjType = 4; - } else if (pBtdm8723->curPsTdma == 9) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (pBtdm8723->curPsTdma == 10) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (pBtdm8723->curPsTdma == 11) { - btdm_2AntPsTdma(padapter, true, 12); - pBtdm8723->psTdmaDuAdjType = 12; - } - } else if (result == 1) { - if (pBtdm8723->curPsTdma == 4) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (pBtdm8723->curPsTdma == 3) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (pBtdm8723->curPsTdma == 2) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (pBtdm8723->curPsTdma == 12) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (pBtdm8723->curPsTdma == 11) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (pBtdm8723->curPsTdma == 10) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } - } - } - } - } - RTPRINT(FBT, BT_TRACE, ("[BTCoex], PsTdma type : recordPsTdma =%d\n", pBtdm8723->psTdmaDuAdjType)); - /* if current PsTdma not match with the recorded one (when scan, dhcp...), */ - /* then we have to adjust it back to the previous record one. */ - if (pBtdm8723->curPsTdma != pBtdm8723->psTdmaDuAdjType) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], PsTdma type dismatch!!!, curPsTdma =%d, recordPsTdma =%d\n", - pBtdm8723->curPsTdma, pBtdm8723->psTdmaDuAdjType)); - - if (!check_fwstate(&padapter->mlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) - btdm_2AntPsTdma(padapter, true, pBtdm8723->psTdmaDuAdjType); - else - RTPRINT(FBT, BT_TRACE, ("[BTCoex], roaming/link/scan is under progress, will adjust next time!!!\n")); - } -} - -/* default Action */ -/* SCO only or SCO+PAN(HS) */ -static void btdm_2Ant8723ASCOAction(struct rtw_adapter *padapter) -{ - u8 btRssiState, btRssiState1; - - if (btdm_NeedToDecBtPwr(padapter)) - btdm_2AntDecBtPwr(padapter, true); - else - btdm_2AntDecBtPwr(padapter, false); - - if (BTDM_IsHT40(padapter)) { - RTPRINT(FBT, BT_TRACE, ("HT40\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - /* fw mechanism */ - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - btdm_2AntPsTdma(padapter, true, 11); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n")); - btdm_2AntPsTdma(padapter, true, 15); - } - - /* sw mechanism */ - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0); - - /* fw mechanism */ - if ((btRssiState1 == BT_RSSI_STATE_HIGH) || - (btRssiState1 == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - btdm_2AntPsTdma(padapter, true, 11); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n")); - btdm_2AntPsTdma(padapter, true, 15); - } - - /* sw mechanism */ - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - btdm_2AntAgcTable(padapter, true); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - } - } -} - -static void btdm_2Ant8723AHIDAction(struct rtw_adapter *padapter) -{ - u8 btRssiState, btRssiState1; - - if (btdm_NeedToDecBtPwr(padapter)) - btdm_2AntDecBtPwr(padapter, true); - else - btdm_2AntDecBtPwr(padapter, false); - - if (BTDM_IsHT40(padapter)) { - RTPRINT(FBT, BT_TRACE, ("HT40\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - /* fw mechanism */ - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - btdm_2AntPsTdma(padapter, true, 9); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n")); - btdm_2AntPsTdma(padapter, true, 13); - } - - /* sw mechanism */ - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0); - - /* fw mechanism */ - if ((btRssiState1 == BT_RSSI_STATE_HIGH) || - (btRssiState1 == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - btdm_2AntPsTdma(padapter, true, 9); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n")); - btdm_2AntPsTdma(padapter, true, 13); - } - - /* sw mechanism */ - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - btdm_2AntAgcTable(padapter, true); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - } - } -} - -/* A2DP only / PAN(EDR) only/ A2DP+PAN(HS) */ -static void btdm_2Ant8723AA2DPAction(struct rtw_adapter *padapter) -{ - u8 btRssiState, btRssiState1; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 btInfoExt = pHalData->bt_coexist.halCoex8723.btInfoExt; - - if (btdm_NeedToDecBtPwr(padapter)) - btdm_2AntDecBtPwr(padapter, true); - else - btdm_2AntDecBtPwr(padapter, false); - - if (BTDM_IsHT40(padapter)) { - RTPRINT(FBT, BT_TRACE, ("HT40\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - - /* fw mechanism */ - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, false, false, 3); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, false, false, 1); - } - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, false, true, 3); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, false, true, 1); - } - } - - /* sw mechanism */ - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0); - - /* fw mechanism */ - if ((btRssiState1 == BT_RSSI_STATE_HIGH) || - (btRssiState1 == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, false, false, 3); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, false, false, 1); - } - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n")); - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, false, true, 3); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, false, true, 1); - } - } - - /* sw mechanism */ - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - btdm_2AntAgcTable(padapter, true); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - } - } -} - -static void btdm_2Ant8723APANEDRAction(struct rtw_adapter *padapter) -{ - u8 btRssiState, btRssiState1; - - if (btdm_NeedToDecBtPwr(padapter)) - btdm_2AntDecBtPwr(padapter, true); - else - btdm_2AntDecBtPwr(padapter, false); - - if (BTDM_IsHT40(padapter)) { - RTPRINT(FBT, BT_TRACE, ("HT40\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - - /* fw mechanism */ - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - btdm_2AntPsTdma(padapter, true, 2); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - btdm_2AntPsTdma(padapter, true, 6); - } - - /* sw mechanism */ - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0); - - /* fw mechanism */ - if ((btRssiState1 == BT_RSSI_STATE_HIGH) || - (btRssiState1 == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - btdm_2AntPsTdma(padapter, true, 2); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n")); - btdm_2AntPsTdma(padapter, true, 6); - } - - /* sw mechanism */ - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - btdm_2AntAgcTable(padapter, true); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - } - } -} - -/* PAN(HS) only */ -static void btdm_2Ant8723APANHSAction(struct rtw_adapter *padapter) -{ - u8 btRssiState; - - if (BTDM_IsHT40(padapter)) { - RTPRINT(FBT, BT_TRACE, ("HT40\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 47, 0); - /* fw mechanism */ - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - btdm_2AntDecBtPwr(padapter, true); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - btdm_2AntDecBtPwr(padapter, false); - } - btdm_2AntPsTdma(padapter, false, 0); - - /* sw mechanism */ - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 47, 0); - - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high\n")); - /* fw mechanism */ - btdm_2AntDecBtPwr(padapter, true); - btdm_2AntPsTdma(padapter, false, 0); - - /* sw mechanism */ - btdm_2AntAgcTable(padapter, true); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low\n")); - /* fw mechanism */ - btdm_2AntDecBtPwr(padapter, false); - btdm_2AntPsTdma(padapter, false, 0); - - /* sw mechanism */ - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - } - } -} - -/* PAN(EDR)+A2DP */ -static void btdm_2Ant8723APANEDRA2DPAction(struct rtw_adapter *padapter) -{ - u8 btRssiState, btRssiState1, btInfoExt; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - btInfoExt = pHalData->bt_coexist.halCoex8723.btInfoExt; - - if (btdm_NeedToDecBtPwr(padapter)) - btdm_2AntDecBtPwr(padapter, true); - else - btdm_2AntDecBtPwr(padapter, false); - - if (BTDM_IsHT40(padapter)) { - RTPRINT(FBT, BT_TRACE, ("HT40\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - /* fw mechanism */ - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntPsTdma(padapter, true, 4); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntPsTdma(padapter, true, 2); - } - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - /* fw mechanism */ - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntPsTdma(padapter, true, 8); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntPsTdma(padapter, true, 6); - } - } - - /* sw mechanism */ - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0); - - if ((btRssiState1 == BT_RSSI_STATE_HIGH) || - (btRssiState1 == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - /* fw mechanism */ - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntPsTdma(padapter, true, 4); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntPsTdma(padapter, true, 2); - } - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n")); - /* fw mechanism */ - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntPsTdma(padapter, true, 8); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntPsTdma(padapter, true, 6); - } - } - - /* sw mechanism */ - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - btdm_2AntAgcTable(padapter, true); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - } - } -} - -static void btdm_2Ant8723APANEDRHIDAction(struct rtw_adapter *padapter) -{ - u8 btRssiState, btRssiState1; - - if (btdm_NeedToDecBtPwr(padapter)) - btdm_2AntDecBtPwr(padapter, true); - else - btdm_2AntDecBtPwr(padapter, false); - - if (BTDM_IsHT40(padapter)) { - RTPRINT(FBT, BT_TRACE, ("HT40\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - /* fw mechanism */ - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - btdm_2AntPsTdma(padapter, true, 10); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - btdm_2AntPsTdma(padapter, true, 14); - } - - /* sw mechanism */ - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0); - - /* fw mechanism */ - if ((btRssiState1 == BT_RSSI_STATE_HIGH) || - (btRssiState1 == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - btdm_2AntPsTdma(padapter, true, 10); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n")); - btdm_2AntPsTdma(padapter, true, 14); - } - - /* sw mechanism */ - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - btdm_2AntAgcTable(padapter, true); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - } - } -} - -/* HID+A2DP+PAN(EDR) */ -static void btdm_2Ant8723AHIDA2DPPANEDRAction(struct rtw_adapter *padapter) -{ - u8 btRssiState, btRssiState1, btInfoExt; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - btInfoExt = pHalData->bt_coexist.halCoex8723.btInfoExt; - - if (btdm_NeedToDecBtPwr(padapter)) - btdm_2AntDecBtPwr(padapter, true); - else - btdm_2AntDecBtPwr(padapter, false); - - if (BTDM_IsHT40(padapter)) { - RTPRINT(FBT, BT_TRACE, ("HT40\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntPsTdma(padapter, true, 12); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntPsTdma(padapter, true, 10); - } - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntPsTdma(padapter, true, 16); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntPsTdma(padapter, true, 14); - } - } - - /* sw mechanism */ - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n")); - btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 37, 0); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 27, 0); - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntPsTdma(padapter, true, 12); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntPsTdma(padapter, true, 10); - } - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntPsTdma(padapter, true, 16); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntPsTdma(padapter, true, 14); - } - } - - /* sw mechanism */ - if ((btRssiState1 == BT_RSSI_STATE_HIGH) || - (btRssiState1 == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n")); - btdm_2AntAgcTable(padapter, true); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n")); - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - } - } -} - -static void btdm_2Ant8723AHIDA2DPAction(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 btRssiState, btRssiState1, btInfoExt; - - btInfoExt = pHalData->bt_coexist.halCoex8723.btInfoExt; - - if (btdm_NeedToDecBtPwr(padapter)) - btdm_2AntDecBtPwr(padapter, true); - else - btdm_2AntDecBtPwr(padapter, false); - - if (BTDM_IsHT40(padapter)) { - RTPRINT(FBT, BT_TRACE, ("HT40\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, true, false, 3); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, true, false, 1); - } - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, true, true, 3); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, true, true, 1); - } - } - /* sw mechanism */ - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - btRssiState1 = BTDM_CheckCoexRSSIState(padapter, 2, 27, 0); - - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, true, false, 3); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, true, false, 1); - } - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */ - RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, true, true, 3); - } else { - RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n")); - btdm_2AntTdmaDurationAdjust(padapter, true, true, 1); - } - } - if ((btRssiState1 == BT_RSSI_STATE_HIGH) || - (btRssiState1 == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n")); - /* sw mechanism */ - btdm_2AntAgcTable(padapter, true); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n")); - /* sw mechanism */ - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - } - } -} - -static void btdm_2Ant8723AA2dp(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 btRssiState, btRssiState1, btInfoExt; - - btInfoExt = pHalData->bt_coexist.halCoex8723.btInfoExt; - - if (btdm_NeedToDecBtPwr(padapter)) - btdm_2AntDecBtPwr(padapter, true); - else - btdm_2AntDecBtPwr(padapter, false); - /* coex table */ - btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3); - btdm_2AntIgnoreWlanAct(padapter, false); - - if (BTDM_IsHT40(padapter)) { - RTPRINT(FBT, BT_TRACE, ("HT40\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0); - /* fw mechanism */ - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - btdm_2AntTdmaDurationAdjust(padapter, false, false, 1); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n")); - btdm_2AntTdmaDurationAdjust(padapter, false, true, 1); - } - - /* sw mechanism */ - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n")); - btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 47, 0); - btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0); - - /* fw mechanism */ - if ((btRssiState1 == BT_RSSI_STATE_HIGH) || - (btRssiState1 == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n")); - PlatformEFIOWrite1Byte(padapter, 0x883, 0x40); - btdm_2AntTdmaDurationAdjust(padapter, false, false, 1); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n")); - btdm_2AntTdmaDurationAdjust(padapter, false, true, 1); - } - - /* sw mechanism */ - if ((btRssiState == BT_RSSI_STATE_HIGH) || - (btRssiState == BT_RSSI_STATE_STAY_HIGH)) { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n")); - btdm_2AntAgcTable(padapter, true); - btdm_2AntAdcBackOff(padapter, true); - btdm_2AntDacSwing(padapter, false, 0xc0); - } else { - RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n")); - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); - } - } -} - -/* extern function start with BTDM_ */ -static void BTDM_2AntParaInit(struct rtw_adapter *padapter) -{ - - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], 2Ant Parameter Init!!\n")); - - /* Enable counter statistics */ - rtl8723au_write8(padapter, 0x76e, 0x4); - rtl8723au_write8(padapter, 0x778, 0x3); - rtl8723au_write8(padapter, 0x40, 0x20); - - /* force to reset coex mechanism */ - pBtdm8723->preVal0x6c0 = 0x0; - btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3); - - pBtdm8723->bPrePsTdmaOn = true; - btdm_2AntPsTdma(padapter, false, 0); - - pBtdm8723->preFwDacSwingLvl = 0x10; - btdm_2AntFwDacSwingLvl(padapter, 0x20); - - pBtdm8723->bPreDecBtPwr = true; - btdm_2AntDecBtPwr(padapter, false); - - pBtdm8723->bPreAgcTableEn = true; - btdm_2AntAgcTable(padapter, false); - - pBtdm8723->bPreAdcBackOff = true; - btdm_2AntAdcBackOff(padapter, false); - - pBtdm8723->bPreLowPenaltyRa = true; - btdm_2AntLowPenaltyRa(padapter, false); - - pBtdm8723->bPreRfRxLpfShrink = true; - btdm_2AntRfShrink(padapter, false); - - pBtdm8723->bPreDacSwingOn = true; - btdm_2AntDacSwing(padapter, false, 0xc0); - - pBtdm8723->bPreIgnoreWlanAct = true; - btdm_2AntIgnoreWlanAct(padapter, false); -} - -static void BTDM_2AntHwCoexAllOff8723A(struct rtw_adapter *padapter) -{ - btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3); -} - -static void BTDM_2AntFwCoexAllOff8723A(struct rtw_adapter *padapter) -{ - btdm_2AntIgnoreWlanAct(padapter, false); - btdm_2AntPsTdma(padapter, false, 0); - btdm_2AntFwDacSwingLvl(padapter, 0x20); - btdm_2AntDecBtPwr(padapter, false); -} - -static void BTDM_2AntSwCoexAllOff8723A(struct rtw_adapter *padapter) -{ - btdm_2AntAgcTable(padapter, false); - btdm_2AntAdcBackOff(padapter, false); - btdm_2AntLowPenaltyRa(padapter, false); - btdm_2AntRfShrink(padapter, false); - btdm_2AntDacSwing(padapter, false, 0xc0); -} - -static void BTDM_2AntFwC2hBtInfo8723A(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - u8 btInfo = 0; - u8 algorithm = BT_2ANT_COEX_ALGO_UNDEFINED; - u8 bBtLinkExist = false, bBtHsModeExist = false; - - btInfo = pHalData->bt_coexist.halCoex8723.c2hBtInfoOriginal; - pBtdm8723->btStatus = BT_2ANT_BT_STATUS_IDLE; - - /* check BIT2 first ==> check if bt is under inquiry or page scan */ - if (btInfo & BIT(2)) { - if (!pHalData->bt_coexist.halCoex8723.bC2hBtInquiryPage) { - pBtMgnt->ExtConfig.bHoldForBtOperation = true; - pBtMgnt->ExtConfig.bHoldPeriodCnt = 1; - btdm_2AntBtInquiryPage(padapter); - } else { - pBtMgnt->ExtConfig.bHoldPeriodCnt++; - btdm_HoldForBtInqPage(padapter); - } - pHalData->bt_coexist.halCoex8723.bC2hBtInquiryPage = true; - - } else { - pHalData->bt_coexist.halCoex8723.bC2hBtInquiryPage = false; - pBtMgnt->ExtConfig.bHoldForBtOperation = false; - pBtMgnt->ExtConfig.bHoldPeriodCnt = 0; - - } - RTPRINT(FBT, BT_TRACE, - ("[BTC2H], pHalData->bt_coexist.halCoex8723.bC2hBtInquiryPage =%x pBtMgnt->ExtConfig.bHoldPeriodCnt =%x pBtMgnt->ExtConfig.bHoldForBtOperation =%x\n", - pHalData->bt_coexist.halCoex8723.bC2hBtInquiryPage, - pBtMgnt->ExtConfig.bHoldPeriodCnt, - pBtMgnt->ExtConfig.bHoldForBtOperation)); - - RTPRINT(FBT, BT_TRACE, - ("[BTC2H], btInfo =%x pHalData->bt_coexist.halCoex8723.c2hBtInfoOriginal =%x\n", - btInfo, pHalData->bt_coexist.halCoex8723.c2hBtInfoOriginal)); - if (btInfo&BT_INFO_ACL) { - RTPRINT(FBT, BT_TRACE, ("[BTC2H], BTInfo: bConnect = true btInfo =%x\n", btInfo)); - bBtLinkExist = true; - if (((btInfo&(BT_INFO_FTP|BT_INFO_A2DP|BT_INFO_HID|BT_INFO_SCO_BUSY)) != 0) || - pHalData->bt_coexist.halCoex8723.btRetryCnt > 0) { - pBtdm8723->btStatus = BT_2ANT_BT_STATUS_NON_IDLE; - } else { - pBtdm8723->btStatus = BT_2ANT_BT_STATUS_CONNECTED_IDLE; - } - - if (btInfo&BT_INFO_SCO || btInfo&BT_INFO_SCO_BUSY) { - if (btInfo&BT_INFO_FTP || btInfo&BT_INFO_A2DP || btInfo&BT_INFO_HID) { - switch (btInfo&0xe0) { - case BT_INFO_HID: - RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + HID\n")); - algorithm = BT_2ANT_COEX_ALGO_HID; - break; - case BT_INFO_A2DP: - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO + A2DP\n")); - break; - case BT_INFO_FTP: - if (bBtHsModeExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + PAN(HS)\n")); - algorithm = BT_2ANT_COEX_ALGO_SCO; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + PAN(EDR)\n")); - algorithm = BT_2ANT_COEX_ALGO_PANEDR_HID; - } - break; - case (BT_INFO_HID | BT_INFO_A2DP): - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP\n")); - algorithm = BT_2ANT_COEX_ALGO_HID_A2DP; - break; - case (BT_INFO_HID | BT_INFO_FTP): - if (bBtHsModeExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + PAN(HS)\n")); - algorithm = BT_2ANT_COEX_ALGO_HID_A2DP; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + PAN(EDR)\n")); - algorithm = BT_2ANT_COEX_ALGO_PANEDR_HID; - } - break; - case (BT_INFO_A2DP | BT_INFO_FTP): - if (bBtHsModeExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP + PAN(HS)\n")); - algorithm = BT_2ANT_COEX_ALGO_A2DP; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP + PAN(EDR)\n")); - algorithm = BT_2ANT_COEX_ALGO_PANEDR_A2DP; - } - break; - case (BT_INFO_HID | BT_INFO_A2DP | BT_INFO_FTP): - if (bBtHsModeExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP + PAN(HS)\n")); - algorithm = BT_2ANT_COEX_ALGO_HID_A2DP; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP + PAN(EDR)\n")); - algorithm = BT_2ANT_COEX_ALGO_HID_A2DP_PANEDR; - } - break; - } - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO only\n")); - algorithm = BT_2ANT_COEX_ALGO_SCO; - } - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], non SCO\n")); - switch (btInfo&0xe0) { - case BT_INFO_HID: - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID\n")); - algorithm = BT_2ANT_COEX_ALGO_HID; - break; - case BT_INFO_A2DP: - RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP\n")); - algorithm = BT_2ANT_COEX_ALGO_A2DP; - break; - case BT_INFO_FTP: - RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN(EDR)\n")); - algorithm = BT_2ANT_COEX_ALGO_PANEDR_HID; - break; - case (BT_INFO_HID | BT_INFO_A2DP): - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP\n")); - algorithm = BT_2ANT_COEX_ALGO_HID_A2DP; - break; - case (BT_INFO_HID|BT_INFO_FTP): - if (bBtHsModeExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + PAN(HS)\n")); - algorithm = BT_2ANT_COEX_ALGO_HID_A2DP; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + PAN(EDR)\n")); - algorithm = BT_2ANT_COEX_ALGO_PANEDR_HID; - } - break; - case (BT_INFO_A2DP|BT_INFO_FTP): - if (bBtHsModeExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP + PAN(HS)\n")); - algorithm = BT_2ANT_COEX_ALGO_A2DP; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP + PAN(EDR)\n")); - algorithm = BT_2ANT_COEX_ALGO_PANEDR_A2DP; - } - break; - case (BT_INFO_HID|BT_INFO_A2DP|BT_INFO_FTP): - if (bBtHsModeExist) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP + PAN(HS)\n")); - algorithm = BT_2ANT_COEX_ALGO_HID_A2DP; - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP + PAN(EDR)\n")); - algorithm = BT_2ANT_COEX_ALGO_HID_A2DP_PANEDR; - } - break; - } - - } - } else { - RTPRINT(FBT, BT_TRACE, ("[BTC2H], BTInfo: bConnect = false\n")); - pBtdm8723->btStatus = BT_2ANT_BT_STATUS_IDLE; - } - - pBtdm8723->curAlgorithm = algorithm; - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Algorithm = %d \n", pBtdm8723->curAlgorithm)); - -/* From */ - BTDM_CheckWiFiState(padapter); - if (pBtMgnt->ExtConfig.bManualControl) { - RTPRINT(FBT, BT_TRACE, ("Action Manual control, won't execute bt coexist mechanism!!\n")); - return; - } -} - -void BTDM_2AntBtCoexist8723A(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - struct bt_dgb *pBtDbg = &pBTInfo->BtDbg; - u8 btInfoOriginal = 0; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant; - - if (BTDM_BtProfileSupport(padapter)) { - if (pBtMgnt->ExtConfig.bHoldForBtOperation) { - RTPRINT(FBT, BT_TRACE, ("Action for BT Operation adjust!!\n")); - return; - } - if (pBtMgnt->ExtConfig.bHoldPeriodCnt) { - RTPRINT(FBT, BT_TRACE, ("Hold BT inquiry/page scan setting (cnt = %d)!!\n", - pBtMgnt->ExtConfig.bHoldPeriodCnt)); - if (pBtMgnt->ExtConfig.bHoldPeriodCnt >= 11) { - pBtMgnt->ExtConfig.bHoldPeriodCnt = 0; - /* next time the coexist parameters should be reset again. */ - } else { - pBtMgnt->ExtConfig.bHoldPeriodCnt++; - } - return; - } - - if (pBtDbg->dbgCtrl) - RTPRINT(FBT, BT_TRACE, ("[Dbg control], ")); - - pBtdm8723->curAlgorithm = btdm_ActionAlgorithm(padapter); - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Algorithm = %d \n", pBtdm8723->curAlgorithm)); - - if (btdm_Is2Ant8723ACommonAction(padapter)) { - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant common.\n")); - pBtdm8723->bResetTdmaAdjust = true; - } else { - if (pBtdm8723->curAlgorithm != pBtdm8723->preAlgorithm) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], preAlgorithm =%d, curAlgorithm =%d\n", - pBtdm8723->preAlgorithm, pBtdm8723->curAlgorithm)); - pBtdm8723->bResetTdmaAdjust = true; - } - switch (pBtdm8723->curAlgorithm) { - case BT_2ANT_COEX_ALGO_SCO: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = SCO.\n")); - btdm_2Ant8723ASCOAction(padapter); - break; - case BT_2ANT_COEX_ALGO_HID: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HID.\n")); - btdm_2Ant8723AHIDAction(padapter); - break; - case BT_2ANT_COEX_ALGO_A2DP: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = A2DP.\n")); - btdm_2Ant8723AA2DPAction(padapter); - break; - case BT_2ANT_COEX_ALGO_PANEDR: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = PAN(EDR).\n")); - btdm_2Ant8723APANEDRAction(padapter); - break; - case BT_2ANT_COEX_ALGO_PANHS: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HS mode.\n")); - btdm_2Ant8723APANHSAction(padapter); - break; - case BT_2ANT_COEX_ALGO_PANEDR_A2DP: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = PAN+A2DP.\n")); - btdm_2Ant8723APANEDRA2DPAction(padapter); - break; - case BT_2ANT_COEX_ALGO_PANEDR_HID: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = PAN(EDR)+HID.\n")); - btdm_2Ant8723APANEDRHIDAction(padapter); - break; - case BT_2ANT_COEX_ALGO_HID_A2DP_PANEDR: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HID+A2DP+PAN.\n")); - btdm_2Ant8723AHIDA2DPPANEDRAction(padapter); - break; - case BT_2ANT_COEX_ALGO_HID_A2DP: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HID+A2DP.\n")); - btdm_2Ant8723AHIDA2DPAction(padapter); - break; - default: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = 0.\n")); - btdm_2Ant8723AA2DPAction(padapter); - break; - } - pBtdm8723->preAlgorithm = pBtdm8723->curAlgorithm; - } - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex] Get bt info by fw!!\n")); - /* msg shows c2h rsp for bt_info is received or not. */ - if (pHalData->bt_coexist.halCoex8723.bC2hBtInfoReqSent) - RTPRINT(FBT, BT_TRACE, ("[BTCoex] c2h for btInfo not rcvd yet!!\n")); - - btInfoOriginal = pHalData->bt_coexist.halCoex8723.c2hBtInfoOriginal; - - if (pBtMgnt->ExtConfig.bHoldForBtOperation) { - RTPRINT(FBT, BT_TRACE, ("Action for BT Operation adjust!!\n")); - return; - } - if (pBtMgnt->ExtConfig.bHoldPeriodCnt) { - RTPRINT(FBT, BT_TRACE, - ("Hold BT inquiry/page scan setting (cnt = %d)!!\n", - pBtMgnt->ExtConfig.bHoldPeriodCnt)); - if (pBtMgnt->ExtConfig.bHoldPeriodCnt >= 11) { - pBtMgnt->ExtConfig.bHoldPeriodCnt = 0; - /* next time the coexist parameters should be reset again. */ - } else { - pBtMgnt->ExtConfig.bHoldPeriodCnt++; - } - return; - } - - if (pBtDbg->dbgCtrl) - RTPRINT(FBT, BT_TRACE, ("[Dbg control], ")); - if (btdm_Is2Ant8723ACommonAction(padapter)) { - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant common.\n")); - pBtdm8723->bResetTdmaAdjust = true; - } else { - if (pBtdm8723->curAlgorithm != pBtdm8723->preAlgorithm) { - RTPRINT(FBT, BT_TRACE, - ("[BTCoex], preAlgorithm =%d, curAlgorithm =%d\n", - pBtdm8723->preAlgorithm, - pBtdm8723->curAlgorithm)); - pBtdm8723->bResetTdmaAdjust = true; - } - switch (pBtdm8723->curAlgorithm) { - case BT_2ANT_COEX_ALGO_SCO: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = SCO.\n")); - btdm_2Ant8723ASCOAction(padapter); - break; - case BT_2ANT_COEX_ALGO_HID: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HID.\n")); - btdm_2Ant8723AHIDAction(padapter); - break; - case BT_2ANT_COEX_ALGO_A2DP: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = A2DP.\n")); - btdm_2Ant8723AA2dp(padapter); - break; - case BT_2ANT_COEX_ALGO_PANEDR: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = PAN(EDR).\n")); - btdm_2Ant8723APANEDRAction(padapter); - break; - case BT_2ANT_COEX_ALGO_PANHS: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HS mode.\n")); - btdm_2Ant8723APANHSAction(padapter); - break; - case BT_2ANT_COEX_ALGO_PANEDR_A2DP: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = PAN+A2DP.\n")); - btdm_2Ant8723APANEDRA2DPAction(padapter); - break; - case BT_2ANT_COEX_ALGO_PANEDR_HID: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = PAN(EDR)+HID.\n")); - btdm_2Ant8723APANEDRHIDAction(padapter); - break; - case BT_2ANT_COEX_ALGO_HID_A2DP_PANEDR: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HID+A2DP+PAN.\n")); - btdm_2Ant8723AHIDA2DPPANEDRAction(padapter); - break; - case BT_2ANT_COEX_ALGO_HID_A2DP: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HID+A2DP.\n")); - btdm_2Ant8723AHIDA2DPAction(padapter); - break; - default: - RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = 0.\n")); - btdm_2Ant8723AA2DPAction(padapter); - break; - } - pBtdm8723->preAlgorithm = pBtdm8723->curAlgorithm; - } - } -} - -/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtc87232Ant.c ===== */ - -/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtc8723.c ===== */ - -static u8 btCoexDbgBuf[BT_TMP_BUF_SIZE]; - -static const char *const BtProfileString[] = { - "NONE", - "A2DP", - "PAN", - "HID", - "SCO", -}; - -static const char *const BtSpecString[] = { - "1.0b", - "1.1", - "1.2", - "2.0+EDR", - "2.1+EDR", - "3.0+HS", - "4.0", -}; - -static const char *const BtLinkRoleString[] = { - "Master", - "Slave", -}; - -static u8 btdm_BtWifiAntNum(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct bt_coexist_8723a *pBtCoex = &pHalData->bt_coexist.halCoex8723; - - if (Ant_x2 == pHalData->bt_coexist.BT_Ant_Num) { - if (Ant_x2 == pBtCoex->TotalAntNum) - return Ant_x2; - else - return Ant_x1; - } else { - return Ant_x1; - } - return Ant_x2; -} - -static void btdm_BtHwCountersMonitor(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u32 regHPTxRx, regLPTxRx, u4Tmp; - u32 regHPTx = 0, regHPRx = 0, regLPTx = 0, regLPRx = 0; - - regHPTxRx = REG_HIGH_PRIORITY_TXRX; - regLPTxRx = REG_LOW_PRIORITY_TXRX; - - u4Tmp = rtl8723au_read32(padapter, regHPTxRx); - regHPTx = u4Tmp & bMaskLWord; - regHPRx = (u4Tmp & bMaskHWord)>>16; - - u4Tmp = rtl8723au_read32(padapter, regLPTxRx); - regLPTx = u4Tmp & bMaskLWord; - regLPRx = (u4Tmp & bMaskHWord)>>16; - - pHalData->bt_coexist.halCoex8723.highPriorityTx = regHPTx; - pHalData->bt_coexist.halCoex8723.highPriorityRx = regHPRx; - pHalData->bt_coexist.halCoex8723.lowPriorityTx = regLPTx; - pHalData->bt_coexist.halCoex8723.lowPriorityRx = regLPRx; - - RTPRINT(FBT, BT_TRACE, ("High Priority Tx/Rx = %d / %d\n", regHPTx, regHPRx)); - RTPRINT(FBT, BT_TRACE, ("Low Priority Tx/Rx = %d / %d\n", regLPTx, regLPRx)); - - /* reset counter */ - rtl8723au_write8(padapter, 0x76e, 0xc); -} - -/* This function check if 8723 bt is disabled */ -static void btdm_BtEnableDisableCheck8723A(struct rtw_adapter *padapter) -{ - u8 btAlife = true; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - -#ifdef CHECK_BT_EXIST_FROM_REG - u8 val8; - - /* ox68[28]= 1 => BT enable; otherwise disable */ - val8 = rtl8723au_read8(padapter, 0x6B); - if (!(val8 & BIT(4))) - btAlife = false; - - if (btAlife) - pHalData->bt_coexist.bCurBtDisabled = false; - else - pHalData->bt_coexist.bCurBtDisabled = true; -#else - if (pHalData->bt_coexist.halCoex8723.highPriorityTx == 0 && - pHalData->bt_coexist.halCoex8723.highPriorityRx == 0 && - pHalData->bt_coexist.halCoex8723.lowPriorityTx == 0 && - pHalData->bt_coexist.halCoex8723.lowPriorityRx == 0) - btAlife = false; - if (pHalData->bt_coexist.halCoex8723.highPriorityTx == 0xeaea && - pHalData->bt_coexist.halCoex8723.highPriorityRx == 0xeaea && - pHalData->bt_coexist.halCoex8723.lowPriorityTx == 0xeaea && - pHalData->bt_coexist.halCoex8723.lowPriorityRx == 0xeaea) - btAlife = false; - if (pHalData->bt_coexist.halCoex8723.highPriorityTx == 0xffff && - pHalData->bt_coexist.halCoex8723.highPriorityRx == 0xffff && - pHalData->bt_coexist.halCoex8723.lowPriorityTx == 0xffff && - pHalData->bt_coexist.halCoex8723.lowPriorityRx == 0xffff) - btAlife = false; - if (btAlife) { - pHalData->bt_coexist.btActiveZeroCnt = 0; - pHalData->bt_coexist.bCurBtDisabled = false; - RTPRINT(FBT, BT_TRACE, ("8723A BT is enabled !!\n")); - } else { - pHalData->bt_coexist.btActiveZeroCnt++; - RTPRINT(FBT, BT_TRACE, ("8723A bt all counters = 0, %d times!!\n", - pHalData->bt_coexist.btActiveZeroCnt)); - if (pHalData->bt_coexist.btActiveZeroCnt >= 2) { - pHalData->bt_coexist.bCurBtDisabled = true; - RTPRINT(FBT, BT_TRACE, ("8723A BT is disabled !!\n")); - } - } -#endif - - if (!pHalData->bt_coexist.bCurBtDisabled) { - if (BTDM_IsWifiConnectionExist(padapter)) - BTDM_SetFwChnlInfo(padapter, RT_MEDIA_CONNECT); - else - BTDM_SetFwChnlInfo(padapter, RT_MEDIA_DISCONNECT); - } - - if (pHalData->bt_coexist.bPreBtDisabled != - pHalData->bt_coexist.bCurBtDisabled) { - RTPRINT(FBT, BT_TRACE, ("8723A BT is from %s to %s!!\n", - (pHalData->bt_coexist.bPreBtDisabled ? "disabled":"enabled"), - (pHalData->bt_coexist.bCurBtDisabled ? "disabled":"enabled"))); - pHalData->bt_coexist.bPreBtDisabled = pHalData->bt_coexist.bCurBtDisabled; - } -} - -static void btdm_BTCoexist8723AHandler(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - - pHalData = GET_HAL_DATA(padapter); - - if (btdm_BtWifiAntNum(padapter) == Ant_x2) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], 2 Ant mechanism\n")); - BTDM_2AntBtCoexist8723A(padapter); - } else { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1 Ant mechanism\n")); - BTDM_1AntBtCoexist8723A(padapter); - } - - if (!BTDM_IsSameCoexistState(padapter)) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Coexist State[bitMap] change from 0x%"i64fmt"x to 0x%"i64fmt"x\n", - pHalData->bt_coexist.PreviousState, - pHalData->bt_coexist.CurrentState)); - pHalData->bt_coexist.PreviousState = pHalData->bt_coexist.CurrentState; - - RTPRINT(FBT, BT_TRACE, ("[")); - if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_BT30) - RTPRINT(FBT, BT_TRACE, ("BT 3.0, ")); - if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_HT20) - RTPRINT(FBT, BT_TRACE, ("HT20, ")); - if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_HT40) - RTPRINT(FBT, BT_TRACE, ("HT40, ")); - if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_LEGACY) - RTPRINT(FBT, BT_TRACE, ("Legacy, ")); - if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_RSSI_LOW) - RTPRINT(FBT, BT_TRACE, ("Rssi_Low, ")); - if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_RSSI_MEDIUM) - RTPRINT(FBT, BT_TRACE, ("Rssi_Mid, ")); - if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_RSSI_HIGH) - RTPRINT(FBT, BT_TRACE, ("Rssi_High, ")); - if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_IDLE) - RTPRINT(FBT, BT_TRACE, ("Wifi_Idle, ")); - if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_UPLINK) - RTPRINT(FBT, BT_TRACE, ("Wifi_Uplink, ")); - if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_DOWNLINK) - RTPRINT(FBT, BT_TRACE, ("Wifi_Downlink, ")); - if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_BT_IDLE) - RTPRINT(FBT, BT_TRACE, ("BT_idle, ")); - if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_PROFILE_HID) - RTPRINT(FBT, BT_TRACE, ("PRO_HID, ")); - if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_PROFILE_A2DP) - RTPRINT(FBT, BT_TRACE, ("PRO_A2DP, ")); - if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_PROFILE_PAN) - RTPRINT(FBT, BT_TRACE, ("PRO_PAN, ")); - if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_PROFILE_SCO) - RTPRINT(FBT, BT_TRACE, ("PRO_SCO, ")); - RTPRINT(FBT, BT_TRACE, ("]\n")); - } -} - -/* extern function start with BTDM_ */ -u32 BTDM_BtTxRxCounterH(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u32 counters; - - counters = pHalData->bt_coexist.halCoex8723.highPriorityTx+ - pHalData->bt_coexist.halCoex8723.highPriorityRx; - return counters; -} - -u32 BTDM_BtTxRxCounterL(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u32 counters; - - counters = pHalData->bt_coexist.halCoex8723.lowPriorityTx+ - pHalData->bt_coexist.halCoex8723.lowPriorityRx; - return counters; -} - -void BTDM_SetFwChnlInfo(struct rtw_adapter *padapter, enum rt_media_status mstatus) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - u8 H2C_Parameter[3] = {0}; - u8 chnl; - - /* opMode */ - if (RT_MEDIA_CONNECT == mstatus) - H2C_Parameter[0] = 0x1; /* 0: disconnected, 1:connected */ - - if (check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE)) { - /* channel */ - chnl = pmlmeext->cur_channel; - if (BTDM_IsHT40(padapter)) { - if (pmlmeext->cur_ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER) - chnl -= 2; - else if (pmlmeext->cur_ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER) - chnl += 2; - } - H2C_Parameter[1] = chnl; - } else { /* check if HS link is exists */ - /* channel */ - if (BT_Operation(padapter)) - H2C_Parameter[1] = pBtMgnt->BTChannel; - else - H2C_Parameter[1] = pmlmeext->cur_channel; - } - - if (BTDM_IsHT40(padapter)) - H2C_Parameter[2] = 0x30; - else - H2C_Parameter[2] = 0x20; - - FillH2CCmd(padapter, 0x19, 3, H2C_Parameter); -} - -u8 BTDM_IsWifiConnectionExist(struct rtw_adapter *padapter) -{ - u8 bRet = false; - - if (BTHCI_HsConnectionEstablished(padapter)) - bRet = true; - - if (check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE) == true) - bRet = true; - - return bRet; -} - -void BTDM_SetFw3a( - struct rtw_adapter *padapter, - u8 byte1, - u8 byte2, - u8 byte3, - u8 byte4, - u8 byte5 - ) -{ - u8 H2C_Parameter[5] = {0}; - - if (rtl8723a_BT_using_antenna_1(padapter)) { - if ((!check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE)) && - (get_fwstate(&padapter->mlmepriv) != WIFI_NULL_STATE)) { - /* for softap mode */ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct bt_coexist_8723a *pBtCoex = &pHalData->bt_coexist.halCoex8723; - u8 BtState = pBtCoex->c2hBtInfo; - - if ((BtState != BT_INFO_STATE_NO_CONNECTION) && - (BtState != BT_INFO_STATE_CONNECT_IDLE)) { - if (byte1 & BIT(4)) { - byte1 &= ~BIT(4); - byte1 |= BIT(5); - } - - byte5 |= BIT(5); - if (byte5 & BIT(6)) - byte5 &= ~BIT(6); - } - } - } - - H2C_Parameter[0] = byte1; - H2C_Parameter[1] = byte2; - H2C_Parameter[2] = byte3; - H2C_Parameter[3] = byte4; - H2C_Parameter[4] = byte5; - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], FW write 0x3a(5bytes) = 0x%02x%08x\n", - H2C_Parameter[0], - H2C_Parameter[1]<<24|H2C_Parameter[2]<<16|H2C_Parameter[3]<<8|H2C_Parameter[4])); - - FillH2CCmd(padapter, 0x3a, 5, H2C_Parameter); -} - -void BTDM_QueryBtInformation(struct rtw_adapter *padapter) -{ - u8 H2C_Parameter[1] = {0}; - struct hal_data_8723a *pHalData; - struct bt_coexist_8723a *pBtCoex; - - pHalData = GET_HAL_DATA(padapter); - pBtCoex = &pHalData->bt_coexist.halCoex8723; - - if (!rtl8723a_BT_enabled(padapter)) { - pBtCoex->c2hBtInfo = BT_INFO_STATE_DISABLED; - pBtCoex->bC2hBtInfoReqSent = false; - return; - } - - if (pBtCoex->c2hBtInfo == BT_INFO_STATE_DISABLED) - pBtCoex->c2hBtInfo = BT_INFO_STATE_NO_CONNECTION; - - if (pBtCoex->bC2hBtInfoReqSent == true) - RTPRINT(FBT, BT_TRACE, ("[BTCoex], didn't recv previous BtInfo report!\n")); - else - pBtCoex->bC2hBtInfoReqSent = true; - - H2C_Parameter[0] |= BIT(0); /* trigger */ - -/*RTPRINT(FBT, BT_TRACE, ("[BTCoex], Query Bt information, write 0x38 = 0x%x\n", */ -/*H2C_Parameter[0])); */ - - FillH2CCmd(padapter, 0x38, 1, H2C_Parameter); -} - -void BTDM_SetSwRfRxLpfCorner(struct rtw_adapter *padapter, u8 type) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (BT_RF_RX_LPF_CORNER_SHRINK == type) { - /* Shrink RF Rx LPF corner */ - RTPRINT(FBT, BT_TRACE, ("Shrink RF Rx LPF corner!!\n")); - PHY_SetRFReg(padapter, PathA, 0x1e, bRFRegOffsetMask, 0xf0ff7); - pHalData->bt_coexist.bSWCoexistAllOff = false; - } else if (BT_RF_RX_LPF_CORNER_RESUME == type) { - /* Resume RF Rx LPF corner */ - RTPRINT(FBT, BT_TRACE, ("Resume RF Rx LPF corner!!\n")); - PHY_SetRFReg(padapter, PathA, 0x1e, bRFRegOffsetMask, pHalData->bt_coexist.BtRfRegOrigin1E); - } -} - -void -BTDM_SetSwPenaltyTxRateAdaptive( - struct rtw_adapter *padapter, - u8 raType - ) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 tmpU1; - - tmpU1 = rtl8723au_read8(padapter, 0x4fd); - tmpU1 |= BIT(0); - if (BT_TX_RATE_ADAPTIVE_LOW_PENALTY == raType) { - tmpU1 &= ~BIT(2); - pHalData->bt_coexist.bSWCoexistAllOff = false; - } else if (BT_TX_RATE_ADAPTIVE_NORMAL == raType) { - tmpU1 |= BIT(2); - } - - rtl8723au_write8(padapter, 0x4fd, tmpU1); -} - -void BTDM_SetFwDecBtPwr(struct rtw_adapter *padapter, u8 bDecBtPwr) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 H2C_Parameter[1] = {0}; - - H2C_Parameter[0] = 0; - - if (bDecBtPwr) { - H2C_Parameter[0] |= BIT(1); - pHalData->bt_coexist.bFWCoexistAllOff = false; - } - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], decrease Bt Power : %s, write 0x21 = 0x%x\n", - (bDecBtPwr ? "Yes!!" : "No!!"), H2C_Parameter[0])); - - FillH2CCmd(padapter, 0x21, 1, H2C_Parameter); -} - -u8 BTDM_BtProfileSupport(struct rtw_adapter *padapter) -{ - u8 bRet = false; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (pBtMgnt->bSupportProfile && - !pHalData->bt_coexist.halCoex8723.bForceFwBtInfo) - bRet = true; - - return bRet; -} - -static void BTDM_AdjustForBtOperation8723A(struct rtw_adapter *padapter) -{ - /* BTDM_2AntAdjustForBtOperation8723(padapter); */ -} - -static void BTDM_FwC2hBtRssi8723A(struct rtw_adapter *padapter, u8 *tmpBuf) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 percent, u1tmp; - - u1tmp = tmpBuf[0]; - percent = u1tmp*2+10; - - pHalData->bt_coexist.halCoex8723.btRssi = percent; -/*RTPRINT(FBT, BT_TRACE, ("[BTC2H], BT RSSI =%d\n", percent)); */ -} - -void -rtl8723a_fw_c2h_BT_info(struct rtw_adapter *padapter, u8 *tmpBuf, u8 length) -{ - struct hal_data_8723a *pHalData; - struct bt_30info *pBTInfo; - struct bt_mgnt *pBtMgnt; - struct bt_coexist_8723a *pBtCoex; - u8 i; - - pHalData = GET_HAL_DATA(padapter); - pBTInfo = GET_BT_INFO(padapter); - pBtMgnt = &pBTInfo->BtMgnt; - pBtCoex = &pHalData->bt_coexist.halCoex8723; - - pBtCoex->bC2hBtInfoReqSent = false; - - RTPRINT(FBT, BT_TRACE, ("[BTC2H], BT info[%d]=[", length)); - - pBtCoex->btRetryCnt = 0; - for (i = 0; i < length; i++) { - switch (i) { - case 0: - pBtCoex->c2hBtInfoOriginal = tmpBuf[i]; - break; - case 1: - pBtCoex->btRetryCnt = tmpBuf[i]; - break; - case 2: - BTDM_FwC2hBtRssi8723A(padapter, &tmpBuf[i]); - break; - case 3: - pBtCoex->btInfoExt = tmpBuf[i]&BIT(0); - break; - } - - if (i == length-1) - RTPRINT(FBT, BT_TRACE, ("0x%02x]\n", tmpBuf[i])); - else - RTPRINT(FBT, BT_TRACE, ("0x%02x, ", tmpBuf[i])); - } - RTPRINT(FBT, BT_TRACE, ("[BTC2H], BT RSSI =%d\n", pBtCoex->btRssi)); - if (pBtCoex->btInfoExt) - RTPRINT(FBT, BT_TRACE, ("[BTC2H], pBtCoex->btInfoExt =%x\n", pBtCoex->btInfoExt)); - - if (btdm_BtWifiAntNum(padapter) == Ant_x1) - BTDM_1AntFwC2hBtInfo8723A(padapter); - else - BTDM_2AntFwC2hBtInfo8723A(padapter); - - if (pBtMgnt->ExtConfig.bManualControl) { - RTPRINT(FBT, BT_TRACE, ("%s: Action Manual control!!\n", __func__)); - return; - } - - btdm_BTCoexist8723AHandler(padapter); -} - -static void BTDM_Display8723ABtCoexInfo(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct bt_coexist_8723a *pBtCoex = &pHalData->bt_coexist.halCoex8723; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - u8 u1Tmp, u1Tmp1, u1Tmp2, i, btInfoExt, psTdmaCase = 0; - u32 u4Tmp[4]; - u8 antNum = Ant_x2; - - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n ============[BT Coexist info]============"); - DCMD_Printf(btCoexDbgBuf); - - if (!rtl8723a_BT_coexist(padapter)) { - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n BT not exists !!!"); - DCMD_Printf(btCoexDbgBuf); - return; - } - - antNum = btdm_BtWifiAntNum(padapter); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d/%d ", "Ant mechanism PG/Now run :", \ - ((pHalData->bt_coexist.BT_Ant_Num == Ant_x2) ? 2 : 1), ((antNum == Ant_x2) ? 2 : 1)); - DCMD_Printf(btCoexDbgBuf); - - if (pBtMgnt->ExtConfig.bManualControl) { - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s", "[Action Manual control]!!"); - DCMD_Printf(btCoexDbgBuf); - } else { - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %s / %d", "BT stack/ hci ext ver", \ - ((pBtMgnt->bSupportProfile) ? "Yes" : "No"), pBtMgnt->ExtConfig.HCIExtensionVer); - DCMD_Printf(btCoexDbgBuf); - } - - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\n %-35s = / %d", "Dot11 channel / BT channel", \ - pBtMgnt->BTChannel); - DCMD_Printf(btCoexDbgBuf); - - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\n %-35s = %d / %d / %d", "Wifi/BT/HS rssi", \ - BTDM_GetRxSS(padapter), - pHalData->bt_coexist.halCoex8723.btRssi, - pHalData->dmpriv.EntryMinUndecoratedSmoothedPWDB); - DCMD_Printf(btCoexDbgBuf); - - if (!pBtMgnt->ExtConfig.bManualControl) { - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\n %-35s = %s / %s ", "WIfi status", - ((BTDM_Legacy(padapter)) ? "Legacy" : (((BTDM_IsHT40(padapter)) ? "HT40" : "HT20"))), - ((!BTDM_IsWifiBusy(padapter)) ? "idle" : ((BTDM_IsWifiUplink(padapter)) ? "uplink" : "downlink"))); - DCMD_Printf(btCoexDbgBuf); - - if (pBtMgnt->bSupportProfile) { - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d / %d / %d / %d", "SCO/HID/PAN/A2DP", - ((BTHCI_CheckProfileExist(padapter, BT_PROFILE_SCO)) ? 1 : 0), - ((BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID)) ? 1 : 0), - ((BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN)) ? 1 : 0), - ((BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) ? 1 : 0)); - DCMD_Printf(btCoexDbgBuf); - - for (i = 0; i < pBtMgnt->ExtConfig.NumberOfHandle; i++) { - if (pBtMgnt->ExtConfig.HCIExtensionVer >= 1) { - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %s/ %s/ %s", "Bt link type/spec/role", - BtProfileString[pBtMgnt->ExtConfig.linkInfo[i].BTProfile], - BtSpecString[pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec], - BtLinkRoleString[pBtMgnt->ExtConfig.linkInfo[i].linkRole]); - DCMD_Printf(btCoexDbgBuf); - - btInfoExt = pHalData->bt_coexist.halCoex8723.btInfoExt; - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %s", "A2DP rate", \ - (btInfoExt & BIT(0)) ? - "Basic rate" : "EDR rate"); - DCMD_Printf(btCoexDbgBuf); - } else { - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %s/ %s", "Bt link type/spec", \ - BtProfileString[pBtMgnt->ExtConfig.linkInfo[i].BTProfile], - BtSpecString[pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec]); - DCMD_Printf(btCoexDbgBuf); - } - } - } - } - - /* Sw mechanism */ - if (!pBtMgnt->ExtConfig.bManualControl) { - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s", "============[Sw BT Coex mechanism]============"); - DCMD_Printf(btCoexDbgBuf); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d ", "AGC Table", \ - pBtCoex->btdm2Ant.bCurAgcTableEn); - DCMD_Printf(btCoexDbgBuf); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d ", "ADC Backoff", \ - pBtCoex->btdm2Ant.bCurAdcBackOff); - DCMD_Printf(btCoexDbgBuf); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d ", "Low penalty RA", \ - pBtCoex->btdm2Ant.bCurLowPenaltyRa); - DCMD_Printf(btCoexDbgBuf); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d ", "RF Rx LPF Shrink", \ - pBtCoex->btdm2Ant.bCurRfRxLpfShrink); - DCMD_Printf(btCoexDbgBuf); - } - u4Tmp[0] = PHY_QueryRFReg(padapter, PathA, 0x1e, 0xff0); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x/ 0x%x", "RF-A, 0x1e[11:4]/original val", \ - u4Tmp[0], pHalData->bt_coexist.BtRfRegOrigin1E); - DCMD_Printf(btCoexDbgBuf); - - /* Fw mechanism */ - if (!pBtMgnt->ExtConfig.bManualControl) { - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s", "============[Fw BT Coex mechanism]============"); - DCMD_Printf(btCoexDbgBuf); - } - if (!pBtMgnt->ExtConfig.bManualControl) { - if (btdm_BtWifiAntNum(padapter) == Ant_x1) - psTdmaCase = pHalData->bt_coexist.halCoex8723.btdm1Ant.curPsTdma; - else - psTdmaCase = pHalData->bt_coexist.halCoex8723.btdm2Ant.curPsTdma; - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %*ph case-%d", - "PS TDMA(0x3a)", 5, pHalData->bt_coexist.fw3aVal, psTdmaCase); - DCMD_Printf(btCoexDbgBuf); - - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d ", "Decrease Bt Power", \ - pBtCoex->btdm2Ant.bCurDecBtPwr); - DCMD_Printf(btCoexDbgBuf); - } - u1Tmp = rtl8723au_read8(padapter, 0x778); - u1Tmp1 = rtl8723au_read8(padapter, 0x783); - u1Tmp2 = rtl8723au_read8(padapter, 0x796); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", "0x778/ 0x783/ 0x796", \ - u1Tmp, u1Tmp1, u1Tmp2); - DCMD_Printf(btCoexDbgBuf); - - if (!pBtMgnt->ExtConfig.bManualControl) { - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x / 0x%x", "Sw DacSwing Ctrl/Val", \ - pBtCoex->btdm2Ant.bCurDacSwingOn, pBtCoex->btdm2Ant.curDacSwingLvl); - DCMD_Printf(btCoexDbgBuf); - } - u4Tmp[0] = rtl8723au_read32(padapter, 0x880); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x", "0x880", \ - u4Tmp[0]); - DCMD_Printf(btCoexDbgBuf); - - /* Hw mechanism */ - if (!pBtMgnt->ExtConfig.bManualControl) { - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s", "============[Hw BT Coex mechanism]============"); - DCMD_Printf(btCoexDbgBuf); - } - - u1Tmp = rtl8723au_read8(padapter, 0x40); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x", "0x40", \ - u1Tmp); - DCMD_Printf(btCoexDbgBuf); - - u4Tmp[0] = rtl8723au_read32(padapter, 0x550); - u1Tmp = rtl8723au_read8(padapter, 0x522); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x/0x%x", "0x550(bcn contrl)/0x522", \ - u4Tmp[0], u1Tmp); - DCMD_Printf(btCoexDbgBuf); - - u4Tmp[0] = rtl8723au_read32(padapter, 0x484); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x", "0x484(rate adaptive)", \ - u4Tmp[0]); - DCMD_Printf(btCoexDbgBuf); - - u4Tmp[0] = rtl8723au_read32(padapter, 0x50); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x", "0xc50(dig)", \ - u4Tmp[0]); - DCMD_Printf(btCoexDbgBuf); - - u4Tmp[0] = rtl8723au_read32(padapter, 0xda0); - u4Tmp[1] = rtl8723au_read32(padapter, 0xda4); - u4Tmp[2] = rtl8723au_read32(padapter, 0xda8); - u4Tmp[3] = rtl8723au_read32(padapter, 0xdac); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x", "0xda0/0xda4/0xda8/0xdac(FA cnt)", \ - u4Tmp[0], u4Tmp[1], u4Tmp[2], u4Tmp[3]); - DCMD_Printf(btCoexDbgBuf); - - u4Tmp[0] = rtl8723au_read32(padapter, 0x6c0); - u4Tmp[1] = rtl8723au_read32(padapter, 0x6c4); - u4Tmp[2] = rtl8723au_read32(padapter, 0x6c8); - u1Tmp = rtl8723au_read8(padapter, 0x6cc); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x", "0x6c0/0x6c4/0x6c8/0x6cc(coexTable)", \ - u4Tmp[0], u4Tmp[1], u4Tmp[2], u1Tmp); - DCMD_Printf(btCoexDbgBuf); - - /* u4Tmp = rtl8723au_read32(padapter, 0x770); */ - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d / %d", "0x770(Hi pri Rx[31:16]/Tx[15:0])", \ - pHalData->bt_coexist.halCoex8723.highPriorityRx, - pHalData->bt_coexist.halCoex8723.highPriorityTx); - DCMD_Printf(btCoexDbgBuf); - /* u4Tmp = rtl8723au_read32(padapter, 0x774); */ - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d / %d", "0x774(Lo pri Rx[31:16]/Tx[15:0])", \ - pHalData->bt_coexist.halCoex8723.lowPriorityRx, - pHalData->bt_coexist.halCoex8723.lowPriorityTx); - DCMD_Printf(btCoexDbgBuf); - - /* Tx mgnt queue hang or not, 0x41b should = 0xf, ex: 0xd ==>hang */ - u1Tmp = rtl8723au_read8(padapter, 0x41b); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x", "0x41b (hang chk == 0xf)", \ - u1Tmp); - DCMD_Printf(btCoexDbgBuf); - snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x", "lastHMEBoxNum", \ - pHalData->LastHMEBoxNum); - DCMD_Printf(btCoexDbgBuf); -} - -static void -BTDM_8723ASignalCompensation(struct rtw_adapter *padapter, - u8 *rssi_wifi, u8 *rssi_bt) -{ - if (btdm_BtWifiAntNum(padapter) == Ant_x1) - BTDM_1AntSignalCompensation(padapter, rssi_wifi, rssi_bt); -} - -static void BTDM_8723AInit(struct rtw_adapter *padapter) -{ - if (btdm_BtWifiAntNum(padapter) == Ant_x2) - BTDM_2AntParaInit(padapter); - else - BTDM_1AntParaInit(padapter); -} - -static void BTDM_HWCoexAllOff8723A(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - if (pBtMgnt->ExtConfig.bManualControl) - return; - - if (btdm_BtWifiAntNum(padapter) == Ant_x2) - BTDM_2AntHwCoexAllOff8723A(padapter); -} - -static void BTDM_FWCoexAllOff8723A(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - if (pBtMgnt->ExtConfig.bManualControl) - return; - - if (btdm_BtWifiAntNum(padapter) == Ant_x2) - BTDM_2AntFwCoexAllOff8723A(padapter); -} - -static void BTDM_SWCoexAllOff8723A(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - if (pBtMgnt->ExtConfig.bManualControl) - return; - - if (btdm_BtWifiAntNum(padapter) == Ant_x2) - BTDM_2AntSwCoexAllOff8723A(padapter); -} - -static void -BTDM_Set8723ABtCoexCurrAntNum(struct rtw_adapter *padapter, u8 antNum) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct bt_coexist_8723a *pBtCoex = &pHalData->bt_coexist.halCoex8723; - - if (antNum == 1) - pBtCoex->TotalAntNum = Ant_x1; - else if (antNum == 2) - pBtCoex->TotalAntNum = Ant_x2; -} - -void rtl8723a_BT_lps_leave(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - if (pBtMgnt->ExtConfig.bManualControl) - return; - - if (btdm_BtWifiAntNum(padapter) == Ant_x1) - BTDM_1AntLpsLeave(padapter); -} - -static void BTDM_ForHalt8723A(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - if (pBtMgnt->ExtConfig.bManualControl) - return; - - if (btdm_BtWifiAntNum(padapter) == Ant_x1) - BTDM_1AntForHalt(padapter); -} - -static void BTDM_WifiScanNotify8723A(struct rtw_adapter *padapter, u8 scanType) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - if (pBtMgnt->ExtConfig.bManualControl) - return; - - if (btdm_BtWifiAntNum(padapter) == Ant_x1) - BTDM_1AntWifiScanNotify(padapter, scanType); -} - -static void -BTDM_WifiAssociateNotify8723A(struct rtw_adapter *padapter, u8 action) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - if (pBtMgnt->ExtConfig.bManualControl) - return; - - if (btdm_BtWifiAntNum(padapter) == Ant_x1) - BTDM_1AntWifiAssociateNotify(padapter, action); -} - -static void -BTDM_MediaStatusNotify8723A(struct rtw_adapter *padapter, - enum rt_media_status mstatus) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], MediaStatusNotify, %s\n", - mstatus?"connect":"disconnect")); - - BTDM_SetFwChnlInfo(padapter, mstatus); - - if (pBtMgnt->ExtConfig.bManualControl) - return; - - if (btdm_BtWifiAntNum(padapter) == Ant_x1) - BTDM_1AntMediaStatusNotify(padapter, mstatus); -} - -static void BTDM_ForDhcp8723A(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - if (pBtMgnt->ExtConfig.bManualControl) - return; - - if (btdm_BtWifiAntNum(padapter) == Ant_x1) - BTDM_1AntForDhcp(padapter); -} - -bool rtl8723a_BT_using_antenna_1(struct rtw_adapter *padapter) -{ - if (btdm_BtWifiAntNum(padapter) == Ant_x1) - return true; - else - return false; -} - -static void BTDM_BTCoexist8723A(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - struct bt_30info *pBTInfo; - struct bt_mgnt *pBtMgnt; - struct bt_coexist_8723a *pBtCoex; - - pHalData = GET_HAL_DATA(padapter); - pBTInfo = GET_BT_INFO(padapter); - pBtMgnt = &pBTInfo->BtMgnt; - pBtCoex = &pHalData->bt_coexist.halCoex8723; - - RTPRINT(FBT, BT_TRACE, ("[BTCoex], beacon RSSI = 0x%x(%d)\n", - pHalData->dmpriv.EntryMinUndecoratedSmoothedPWDB, - pHalData->dmpriv.EntryMinUndecoratedSmoothedPWDB)); - - btdm_BtHwCountersMonitor(padapter); - btdm_BtEnableDisableCheck8723A(padapter); - - if (pBtMgnt->ExtConfig.bManualControl) { - RTPRINT(FBT, BT_TRACE, ("%s: Action Manual control!!\n", __func__)); - return; - } - - if (pBtCoex->bC2hBtInfoReqSent) { - if (!rtl8723a_BT_enabled(padapter)) { - pBtCoex->c2hBtInfo = BT_INFO_STATE_DISABLED; - } else { - if (pBtCoex->c2hBtInfo == BT_INFO_STATE_DISABLED) - pBtCoex->c2hBtInfo = BT_INFO_STATE_NO_CONNECTION; - } - - btdm_BTCoexist8723AHandler(padapter); - } else if (!rtl8723a_BT_enabled(padapter)) { - pBtCoex->c2hBtInfo = BT_INFO_STATE_DISABLED; - btdm_BTCoexist8723AHandler(padapter); - } - - BTDM_QueryBtInformation(padapter); -} - -/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtc8723.c ===== */ - -/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtcCsr1Ant.c ===== */ - -/* local function start with btdm_ */ -/* extern function start with BTDM_ */ - -static void BTDM_SetAntenna(struct rtw_adapter *padapter, u8 who) -{ -} - -void -BTDM_SingleAnt( - struct rtw_adapter *padapter, - u8 bSingleAntOn, - u8 bInterruptOn, - u8 bMultiNAVOn - ) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 H2C_Parameter[3] = {0}; - - if (pHalData->bt_coexist.BT_Ant_Num != Ant_x1) - return; - - H2C_Parameter[2] = 0; - H2C_Parameter[1] = 0; - H2C_Parameter[0] = 0; - - if (bInterruptOn) { - H2C_Parameter[2] |= 0x02; /* BIT1 */ - pHalData->bt_coexist.bFWCoexistAllOff = false; - } - pHalData->bt_coexist.bInterruptOn = bInterruptOn; - - if (bSingleAntOn) { - H2C_Parameter[2] |= 0x10; /* BIT4 */ - pHalData->bt_coexist.bFWCoexistAllOff = false; - } - pHalData->bt_coexist.bSingleAntOn = bSingleAntOn; - - if (bMultiNAVOn) { - H2C_Parameter[2] |= 0x20; /* BIT5 */ - pHalData->bt_coexist.bFWCoexistAllOff = false; - } - pHalData->bt_coexist.bMultiNAVOn = bMultiNAVOn; - - RTPRINT(FBT, BT_TRACE, ("[DM][BT], SingleAntenna =[%s:%s:%s], write 0xe = 0x%x\n", - bSingleAntOn?"ON":"OFF", bInterruptOn?"ON":"OFF", bMultiNAVOn?"ON":"OFF", - H2C_Parameter[0]<<16|H2C_Parameter[1]<<8|H2C_Parameter[2])); -} - -void BTDM_CheckBTIdleChange1Ant(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - u8 stateChange = false; - u32 BT_Polling, Ratio_Act, Ratio_STA; - u32 BT_Active, BT_State; - u32 regBTActive = 0, regBTState = 0, regBTPolling = 0; - - if (!rtl8723a_BT_coexist(padapter)) - return; - if (pBtMgnt->ExtConfig.bManualControl) - return; - if (pHalData->bt_coexist.BT_CoexistType != BT_CSR_BC8) - return; - if (pHalData->bt_coexist.BT_Ant_Num != Ant_x1) - return; - - /* The following we only consider CSR BC8 and fw version should be >= 62 */ - RTPRINT(FBT, BT_TRACE, ("[DM][BT], FirmwareVersion = 0x%x(%d)\n", - pHalData->FirmwareVersion, pHalData->FirmwareVersion)); - regBTActive = REG_BT_ACTIVE; - regBTState = REG_BT_STATE; - if (pHalData->FirmwareVersion >= FW_VER_BT_REG1) - regBTPolling = REG_BT_POLLING1; - else - regBTPolling = REG_BT_POLLING; - - BT_Active = rtl8723au_read32(padapter, regBTActive); - RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT_Active(0x%x) =%x\n", regBTActive, BT_Active)); - BT_Active = BT_Active & 0x00ffffff; - - BT_State = rtl8723au_read32(padapter, regBTState); - RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT_State(0x%x) =%x\n", regBTState, BT_State)); - BT_State = BT_State & 0x00ffffff; - - BT_Polling = rtl8723au_read32(padapter, regBTPolling); - RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT_Polling(0x%x) =%x\n", regBTPolling, BT_Polling)); - - if (BT_Active == 0x00ffffff && BT_State == 0x00ffffff && BT_Polling == 0xffffffff) - return; - if (BT_Polling == 0) - return; - - Ratio_Act = BT_Active*1000/BT_Polling; - Ratio_STA = BT_State*1000/BT_Polling; - - pHalData->bt_coexist.Ratio_Tx = Ratio_Act; - pHalData->bt_coexist.Ratio_PRI = Ratio_STA; - - RTPRINT(FBT, BT_TRACE, ("[DM][BT], Ratio_Act =%d\n", Ratio_Act)); - RTPRINT(FBT, BT_TRACE, ("[DM][BT], Ratio_STA =%d\n", Ratio_STA)); - - if (Ratio_STA < 60 && Ratio_Act < 500) { /* BT PAN idle */ - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_PAN_IDLE; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_DOWNLINK; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_UPLINK; - } else { - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_IDLE; - - if (Ratio_STA) { - /* Check if BT PAN (under BT 2.1) is uplink or downlink */ - if ((Ratio_Act/Ratio_STA) < 2) { - /* BT PAN Uplink */ - pHalData->bt_coexist.BT21TrafficStatistics.bTxBusyTraffic = true; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_PAN_UPLINK; - pHalData->bt_coexist.BT21TrafficStatistics.bRxBusyTraffic = false; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_DOWNLINK; - } else { - /* BT PAN downlink */ - pHalData->bt_coexist.BT21TrafficStatistics.bTxBusyTraffic = false; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_UPLINK; - pHalData->bt_coexist.BT21TrafficStatistics.bRxBusyTraffic = true; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_PAN_DOWNLINK; - } - } else { - /* BT PAN downlink */ - pHalData->bt_coexist.BT21TrafficStatistics.bTxBusyTraffic = false; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_UPLINK; - pHalData->bt_coexist.BT21TrafficStatistics.bRxBusyTraffic = true; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_PAN_DOWNLINK; - } - } - - /* Check BT is idle or not */ - if (pBtMgnt->ExtConfig.NumberOfHandle == 0 && - pBtMgnt->ExtConfig.NumberOfSCO == 0) { - pBtMgnt->ExtConfig.bBTBusy = false; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_IDLE; - } else { - if (Ratio_STA < 60) { - pBtMgnt->ExtConfig.bBTBusy = false; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_IDLE; - } else { - pBtMgnt->ExtConfig.bBTBusy = true; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_IDLE; - } - } - - if (pBtMgnt->ExtConfig.NumberOfHandle == 0 && - pBtMgnt->ExtConfig.NumberOfSCO == 0) { - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_RSSI_LOW; - pBtMgnt->ExtConfig.MIN_BT_RSSI = 0; - BTDM_SetAntenna(padapter, BTDM_ANT_BT_IDLE); - } else { - if (pBtMgnt->ExtConfig.MIN_BT_RSSI <= -5) { - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_RSSI_LOW; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], core stack notify bt rssi Low\n")); - } else { - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_RSSI_LOW; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], core stack notify bt rssi Normal\n")); - } - } - - if (pHalData->bt_coexist.bBTBusyTraffic != pBtMgnt->ExtConfig.bBTBusy) { - /* BT idle or BT non-idle */ - pHalData->bt_coexist.bBTBusyTraffic = pBtMgnt->ExtConfig.bBTBusy; - stateChange = true; - } - - if (stateChange) { - if (!pBtMgnt->ExtConfig.bBTBusy) - RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT is idle or disable\n")); - else - RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT is non-idle\n")); - } - if (!pBtMgnt->ExtConfig.bBTBusy) { - RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT is idle or disable\n")); - if (check_fwstate(&padapter->mlmepriv, WIFI_UNDER_LINKING|WIFI_SITE_MONITOR) == true) - BTDM_SetAntenna(padapter, BTDM_ANT_WIFI); - } -} - -/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtcCsr1Ant.c ===== */ - -/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtcCsr2Ant.c ===== */ - -/* local function start with btdm_ */ - -/* Note: */ -/* In the following, FW should be done before SW mechanism. */ -/* BTDM_Balance(), BTDM_DiminishWiFi(), BT_NAV() should be done */ -/* before BTDM_AGCTable(), BTDM_BBBackOffLevel(), btdm_DacSwing(). */ - -/* extern function start with BTDM_ */ - -void -BTDM_DiminishWiFi( - struct rtw_adapter *padapter, - u8 bDACOn, - u8 bInterruptOn, - u8 DACSwingLevel, - u8 bNAVOn - ) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 H2C_Parameter[3] = {0}; - - if (pHalData->bt_coexist.BT_Ant_Num != Ant_x2) - return; - - if ((pHalData->bt_coexist.CurrentState & BT_COEX_STATE_BT_RSSI_LOW) && - (DACSwingLevel == 0x20)) { - RTPRINT(FBT, BT_TRACE, ("[BT]DiminishWiFi 0x20 original, but set 0x18 for Low RSSI!\n")); - DACSwingLevel = 0x18; - } - - H2C_Parameter[2] = 0; - H2C_Parameter[1] = DACSwingLevel; - H2C_Parameter[0] = 0; - if (bDACOn) { - H2C_Parameter[2] |= 0x01; /* BIT0 */ - if (bInterruptOn) - H2C_Parameter[2] |= 0x02; /* BIT1 */ - pHalData->bt_coexist.bFWCoexistAllOff = false; - } - if (bNAVOn) { - H2C_Parameter[2] |= 0x08; /* BIT3 */ - pHalData->bt_coexist.bFWCoexistAllOff = false; - } - - RTPRINT(FBT, BT_TRACE, ("[DM][BT], bDACOn = %s, bInterruptOn = %s, write 0xe = 0x%x\n", - bDACOn?"ON":"OFF", bInterruptOn?"ON":"OFF", - H2C_Parameter[0]<<16|H2C_Parameter[1]<<8|H2C_Parameter[2])); - RTPRINT(FBT, BT_TRACE, ("[DM][BT], bNAVOn = %s\n", - bNAVOn?"ON":"OFF")); -} - -/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtcCsr2Ant.c ===== */ - -/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtCoexist.c ===== */ - -/* local function */ -static void btdm_ResetFWCoexState(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - pHalData->bt_coexist.CurrentState = 0; - pHalData->bt_coexist.PreviousState = 0; -} - -static void btdm_InitBtCoexistDM(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - /* 20100415 Joseph: Restore RF register 0x1E and 0x1F value for further usage. */ - pHalData->bt_coexist.BtRfRegOrigin1E = PHY_QueryRFReg(padapter, PathA, RF_RCK1, bRFRegOffsetMask); - pHalData->bt_coexist.BtRfRegOrigin1F = PHY_QueryRFReg(padapter, PathA, RF_RCK2, 0xf0); - - pHalData->bt_coexist.CurrentState = 0; - pHalData->bt_coexist.PreviousState = 0; - - BTDM_8723AInit(padapter); - pHalData->bt_coexist.bInitlized = true; -} - -/* */ -/* extern function */ -/* */ -void BTDM_CheckAntSelMode(struct rtw_adapter *padapter) -{ -} - -void BTDM_FwC2hBtRssi(struct rtw_adapter *padapter, u8 *tmpBuf) -{ - BTDM_FwC2hBtRssi8723A(padapter, tmpBuf); -} - -void BTDM_DisplayBtCoexInfo(struct rtw_adapter *padapter) -{ - BTDM_Display8723ABtCoexInfo(padapter); -} - -void BTDM_RejectAPAggregatedPacket(struct rtw_adapter *padapter, u8 bReject) -{ -} - -u8 BTDM_IsHT40(struct rtw_adapter *padapter) -{ - u8 isht40 = true; - enum ht_channel_width bw; - - bw = padapter->mlmeextpriv.cur_bwmode; - - if (bw == HT_CHANNEL_WIDTH_20) - isht40 = false; - else if (bw == HT_CHANNEL_WIDTH_40) - isht40 = true; - - return isht40; -} - -u8 BTDM_Legacy(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext; - u8 isLegacy = false; - - pmlmeext = &padapter->mlmeextpriv; - if ((pmlmeext->cur_wireless_mode == WIRELESS_11B) || - (pmlmeext->cur_wireless_mode == WIRELESS_11G) || - (pmlmeext->cur_wireless_mode == WIRELESS_11BG)) - isLegacy = true; - - return isLegacy; -} - -void BTDM_CheckWiFiState(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - struct mlme_priv *pmlmepriv; - struct bt_30info *pBTInfo; - struct bt_mgnt *pBtMgnt; - - pHalData = GET_HAL_DATA(padapter); - pmlmepriv = &padapter->mlmepriv; - pBTInfo = GET_BT_INFO(padapter); - pBtMgnt = &pBTInfo->BtMgnt; - - if (pmlmepriv->LinkDetectInfo.bBusyTraffic) { - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_IDLE; - - if (pmlmepriv->LinkDetectInfo.bTxBusyTraffic) - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_UPLINK; - else - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_UPLINK; - - if (pmlmepriv->LinkDetectInfo.bRxBusyTraffic) - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_DOWNLINK; - else - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_DOWNLINK; - } else { - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_IDLE; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_UPLINK; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_DOWNLINK; - } - - if (BTDM_Legacy(padapter)) { - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_LEGACY; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_HT20; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_HT40; - } else { - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_LEGACY; - if (BTDM_IsHT40(padapter)) { - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_HT40; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_HT20; - } else { - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_HT20; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_HT40; - } - } - - if (pBtMgnt->BtOperationOn) - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT30; - else - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT30; -} - -s32 BTDM_GetRxSS(struct rtw_adapter *padapter) -{ -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct mlme_priv *pmlmepriv; - struct hal_data_8723a *pHalData; - s32 UndecoratedSmoothedPWDB = 0; - - pmlmepriv = &padapter->mlmepriv; - pHalData = GET_HAL_DATA(padapter); - - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - UndecoratedSmoothedPWDB = GET_UNDECORATED_AVERAGE_RSSI(padapter); - } else { /* associated entry pwdb */ - UndecoratedSmoothedPWDB = pHalData->dmpriv.EntryMinUndecoratedSmoothedPWDB; - /* pHalData->BT_EntryMinUndecoratedSmoothedPWDB */ - } - RTPRINT(FBT, BT_TRACE, ("BTDM_GetRxSS() = %d\n", UndecoratedSmoothedPWDB)); - return UndecoratedSmoothedPWDB; -} - -static s32 BTDM_GetRxBeaconSS(struct rtw_adapter *padapter) -{ -/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */ - struct mlme_priv *pmlmepriv; - struct hal_data_8723a *pHalData; - s32 pwdbBeacon = 0; - - pmlmepriv = &padapter->mlmepriv; - pHalData = GET_HAL_DATA(padapter); - - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - /* pwdbBeacon = pHalData->dmpriv.UndecoratedSmoothedBeacon; */ - pwdbBeacon = pHalData->dmpriv.EntryMinUndecoratedSmoothedPWDB; - } - RTPRINT(FBT, BT_TRACE, ("BTDM_GetRxBeaconSS() = %d\n", pwdbBeacon)); - return pwdbBeacon; -} - -/* Get beacon rssi state */ -u8 BTDM_CheckCoexBcnRssiState(struct rtw_adapter *padapter, u8 levelNum, - u8 RssiThresh, u8 RssiThresh1) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - s32 pwdbBeacon = 0; - u8 bcnRssiState = 0; - - pwdbBeacon = BTDM_GetRxBeaconSS(padapter); - - if (levelNum == 2) { - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_MEDIUM; - - if ((pHalData->bt_coexist.preRssiStateBeacon == BT_RSSI_STATE_LOW) || - (pHalData->bt_coexist.preRssiStateBeacon == BT_RSSI_STATE_STAY_LOW)) { - if (pwdbBeacon >= (RssiThresh+BT_FW_COEX_THRESH_TOL)) { - bcnRssiState = BT_RSSI_STATE_HIGH; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_BEACON_HIGH; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_LOW; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state switch to High\n")); - } else { - bcnRssiState = BT_RSSI_STATE_STAY_LOW; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state stay at Low\n")); - } - } else { - if (pwdbBeacon < RssiThresh) { - bcnRssiState = BT_RSSI_STATE_LOW; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_BEACON_LOW; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_HIGH; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state switch to Low\n")); - } else { - bcnRssiState = BT_RSSI_STATE_STAY_HIGH; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state stay at High\n")); - } - } - } else if (levelNum == 3) { - if (RssiThresh > RssiThresh1) { - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON thresh error!!\n")); - return pHalData->bt_coexist.preRssiStateBeacon; - } - - if ((pHalData->bt_coexist.preRssiStateBeacon == BT_RSSI_STATE_LOW) || - (pHalData->bt_coexist.preRssiStateBeacon == BT_RSSI_STATE_STAY_LOW)) { - if (pwdbBeacon >= (RssiThresh+BT_FW_COEX_THRESH_TOL)) { - bcnRssiState = BT_RSSI_STATE_MEDIUM; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_BEACON_MEDIUM; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_LOW; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_HIGH; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state switch to Medium\n")); - } else { - bcnRssiState = BT_RSSI_STATE_STAY_LOW; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state stay at Low\n")); - } - } else if ((pHalData->bt_coexist.preRssiStateBeacon == BT_RSSI_STATE_MEDIUM) || - (pHalData->bt_coexist.preRssiStateBeacon == BT_RSSI_STATE_STAY_MEDIUM)) { - if (pwdbBeacon >= (RssiThresh1+BT_FW_COEX_THRESH_TOL)) { - bcnRssiState = BT_RSSI_STATE_HIGH; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_BEACON_HIGH; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_LOW; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_MEDIUM; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state switch to High\n")); - } else if (pwdbBeacon < RssiThresh) { - bcnRssiState = BT_RSSI_STATE_LOW; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_BEACON_LOW; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_HIGH; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_MEDIUM; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state switch to Low\n")); - } else { - bcnRssiState = BT_RSSI_STATE_STAY_MEDIUM; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state stay at Medium\n")); - } - } else { - if (pwdbBeacon < RssiThresh1) { - bcnRssiState = BT_RSSI_STATE_MEDIUM; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_BEACON_MEDIUM; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_HIGH; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_LOW; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state switch to Medium\n")); - } else { - bcnRssiState = BT_RSSI_STATE_STAY_HIGH; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state stay at High\n")); - } - } - } - - pHalData->bt_coexist.preRssiStateBeacon = bcnRssiState; - - return bcnRssiState; -} - -u8 BTDM_CheckCoexRSSIState1(struct rtw_adapter *padapter, u8 levelNum, - u8 RssiThresh, u8 RssiThresh1) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - s32 UndecoratedSmoothedPWDB = 0; - u8 btRssiState = 0; - - UndecoratedSmoothedPWDB = BTDM_GetRxSS(padapter); - - if (levelNum == 2) { - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_MEDIUM; - - if ((pHalData->bt_coexist.preRssiState1 == BT_RSSI_STATE_LOW) || - (pHalData->bt_coexist.preRssiState1 == BT_RSSI_STATE_STAY_LOW)) { - if (UndecoratedSmoothedPWDB >= (RssiThresh+BT_FW_COEX_THRESH_TOL)) { - btRssiState = BT_RSSI_STATE_HIGH; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_1_HIGH; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_LOW; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state switch to High\n")); - } else { - btRssiState = BT_RSSI_STATE_STAY_LOW; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state stay at Low\n")); - } - } else { - if (UndecoratedSmoothedPWDB < RssiThresh) { - btRssiState = BT_RSSI_STATE_LOW; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_1_LOW; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_HIGH; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state switch to Low\n")); - } else { - btRssiState = BT_RSSI_STATE_STAY_HIGH; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state stay at High\n")); - } - } - } else if (levelNum == 3) { - if (RssiThresh > RssiThresh1) { - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 thresh error!!\n")); - return pHalData->bt_coexist.preRssiState1; - } - - if ((pHalData->bt_coexist.preRssiState1 == BT_RSSI_STATE_LOW) || - (pHalData->bt_coexist.preRssiState1 == BT_RSSI_STATE_STAY_LOW)) { - if (UndecoratedSmoothedPWDB >= (RssiThresh+BT_FW_COEX_THRESH_TOL)) { - btRssiState = BT_RSSI_STATE_MEDIUM; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_1_MEDIUM; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_LOW; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_HIGH; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state switch to Medium\n")); - } else { - btRssiState = BT_RSSI_STATE_STAY_LOW; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state stay at Low\n")); - } - } else if ((pHalData->bt_coexist.preRssiState1 == BT_RSSI_STATE_MEDIUM) || - (pHalData->bt_coexist.preRssiState1 == BT_RSSI_STATE_STAY_MEDIUM)) { - if (UndecoratedSmoothedPWDB >= (RssiThresh1+BT_FW_COEX_THRESH_TOL)) { - btRssiState = BT_RSSI_STATE_HIGH; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_1_HIGH; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_LOW; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_MEDIUM; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state switch to High\n")); - } else if (UndecoratedSmoothedPWDB < RssiThresh) { - btRssiState = BT_RSSI_STATE_LOW; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_1_LOW; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_HIGH; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_MEDIUM; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state switch to Low\n")); - } else { - btRssiState = BT_RSSI_STATE_STAY_MEDIUM; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state stay at Medium\n")); - } - } else { - if (UndecoratedSmoothedPWDB < RssiThresh1) { - btRssiState = BT_RSSI_STATE_MEDIUM; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_1_MEDIUM; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_HIGH; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_LOW; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state switch to Medium\n")); - } else { - btRssiState = BT_RSSI_STATE_STAY_HIGH; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state stay at High\n")); - } - } - } - - pHalData->bt_coexist.preRssiState1 = btRssiState; - - return btRssiState; -} - -u8 BTDM_CheckCoexRSSIState(struct rtw_adapter *padapter, u8 levelNum, - u8 RssiThresh, u8 RssiThresh1) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - s32 UndecoratedSmoothedPWDB = 0; - u8 btRssiState = 0; - - UndecoratedSmoothedPWDB = BTDM_GetRxSS(padapter); - - if (levelNum == 2) { - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_MEDIUM; - - if ((pHalData->bt_coexist.preRssiState == BT_RSSI_STATE_LOW) || - (pHalData->bt_coexist.preRssiState == BT_RSSI_STATE_STAY_LOW)) { - if (UndecoratedSmoothedPWDB >= (RssiThresh+BT_FW_COEX_THRESH_TOL)) { - btRssiState = BT_RSSI_STATE_HIGH; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_HIGH; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_LOW; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state switch to High\n")); - } else { - btRssiState = BT_RSSI_STATE_STAY_LOW; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state stay at Low\n")); - } - } else { - if (UndecoratedSmoothedPWDB < RssiThresh) { - btRssiState = BT_RSSI_STATE_LOW; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_LOW; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_HIGH; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state switch to Low\n")); - } else { - btRssiState = BT_RSSI_STATE_STAY_HIGH; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state stay at High\n")); - } - } - } else if (levelNum == 3) { - if (RssiThresh > RssiThresh1) { - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI thresh error!!\n")); - return pHalData->bt_coexist.preRssiState; - } - - if ((pHalData->bt_coexist.preRssiState == BT_RSSI_STATE_LOW) || - (pHalData->bt_coexist.preRssiState == BT_RSSI_STATE_STAY_LOW)) { - if (UndecoratedSmoothedPWDB >= (RssiThresh+BT_FW_COEX_THRESH_TOL)) { - btRssiState = BT_RSSI_STATE_MEDIUM; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_MEDIUM; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_LOW; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_HIGH; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state switch to Medium\n")); - } else { - btRssiState = BT_RSSI_STATE_STAY_LOW; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state stay at Low\n")); - } - } else if ((pHalData->bt_coexist.preRssiState == BT_RSSI_STATE_MEDIUM) || - (pHalData->bt_coexist.preRssiState == BT_RSSI_STATE_STAY_MEDIUM)) { - if (UndecoratedSmoothedPWDB >= (RssiThresh1+BT_FW_COEX_THRESH_TOL)) { - btRssiState = BT_RSSI_STATE_HIGH; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_HIGH; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_LOW; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_MEDIUM; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state switch to High\n")); - } else if (UndecoratedSmoothedPWDB < RssiThresh) { - btRssiState = BT_RSSI_STATE_LOW; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_LOW; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_HIGH; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_MEDIUM; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state switch to Low\n")); - } else { - btRssiState = BT_RSSI_STATE_STAY_MEDIUM; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state stay at Medium\n")); - } - } else { - if (UndecoratedSmoothedPWDB < RssiThresh1) { - btRssiState = BT_RSSI_STATE_MEDIUM; - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_MEDIUM; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_HIGH; - pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_LOW; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state switch to Medium\n")); - } else { - btRssiState = BT_RSSI_STATE_STAY_HIGH; - RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state stay at High\n")); - } - } - } - - pHalData->bt_coexist.preRssiState = btRssiState; - - return btRssiState; -} - -bool rtl8723a_BT_disable_EDCA_turbo(struct rtw_adapter *padapter) -{ - struct bt_mgnt *pBtMgnt; - struct hal_data_8723a *pHalData; - u8 bBtChangeEDCA = false; - u32 EDCA_BT_BE = 0x5ea42b, cur_EDCA_reg; - bool bRet = false; - - pHalData = GET_HAL_DATA(padapter); - pBtMgnt = &pHalData->BtInfo.BtMgnt; - - if (!rtl8723a_BT_coexist(padapter)) { - bRet = false; - pHalData->bt_coexist.lastBtEdca = 0; - return bRet; - } - if (!((pBtMgnt->bSupportProfile) || - (pHalData->bt_coexist.BT_CoexistType == BT_CSR_BC8))) { - bRet = false; - pHalData->bt_coexist.lastBtEdca = 0; - return bRet; - } - - if (rtl8723a_BT_using_antenna_1(padapter)) { - bRet = false; - pHalData->bt_coexist.lastBtEdca = 0; - return bRet; - } - - if (pHalData->bt_coexist.exec_cnt < 3) - pHalData->bt_coexist.exec_cnt++; - else - pHalData->bt_coexist.bEDCAInitialized = true; - - /* When BT is non idle */ - if (!(pHalData->bt_coexist.CurrentState & BT_COEX_STATE_BT_IDLE)) { - RTPRINT(FBT, BT_TRACE, ("BT state non idle, set bt EDCA\n")); - - /* aggr_num = 0x0909; */ - if (pHalData->odmpriv.DM_EDCA_Table.bCurrentTurboEDCA) { - bBtChangeEDCA = true; - pHalData->odmpriv.DM_EDCA_Table.bCurrentTurboEDCA = false; - pHalData->dmpriv.prv_traffic_idx = 3; - } - cur_EDCA_reg = rtl8723au_read32(padapter, REG_EDCA_BE_PARAM); - - if (cur_EDCA_reg != EDCA_BT_BE) - bBtChangeEDCA = true; - if (bBtChangeEDCA || !pHalData->bt_coexist.bEDCAInitialized) { - rtl8723au_write32(padapter, REG_EDCA_BE_PARAM, - EDCA_BT_BE); - pHalData->bt_coexist.lastBtEdca = EDCA_BT_BE; - } - bRet = true; - } else { - RTPRINT(FBT, BT_TRACE, ("BT state idle, set original EDCA\n")); - pHalData->bt_coexist.lastBtEdca = 0; - bRet = false; - } - return bRet; -} - -void -BTDM_Balance( - struct rtw_adapter *padapter, - u8 bBalanceOn, - u8 ms0, - u8 ms1 - ) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 H2C_Parameter[3] = {0}; - - if (bBalanceOn) { - H2C_Parameter[2] = 1; - H2C_Parameter[1] = ms1; - H2C_Parameter[0] = ms0; - pHalData->bt_coexist.bFWCoexistAllOff = false; - } else { - H2C_Parameter[2] = 0; - H2C_Parameter[1] = 0; - H2C_Parameter[0] = 0; - } - pHalData->bt_coexist.bBalanceOn = bBalanceOn; - - RTPRINT(FBT, BT_TRACE, ("[DM][BT], Balance =[%s:%dms:%dms], write 0xc = 0x%x\n", - bBalanceOn?"ON":"OFF", ms0, ms1, - H2C_Parameter[0]<<16|H2C_Parameter[1]<<8|H2C_Parameter[2])); - - FillH2CCmd(padapter, 0xc, 3, H2C_Parameter); -} - -void BTDM_AGCTable(struct rtw_adapter *padapter, u8 type) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - if (type == BT_AGCTABLE_OFF) { - RTPRINT(FBT, BT_TRACE, ("[BT]AGCTable Off!\n")); - rtl8723au_write32(padapter, 0xc78, 0x641c0001); - rtl8723au_write32(padapter, 0xc78, 0x631d0001); - rtl8723au_write32(padapter, 0xc78, 0x621e0001); - rtl8723au_write32(padapter, 0xc78, 0x611f0001); - rtl8723au_write32(padapter, 0xc78, 0x60200001); - - PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0x32000); - PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0x71000); - PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0xb0000); - PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0xfc000); - PHY_SetRFReg(padapter, PathA, RF_RX_G1, bRFRegOffsetMask, 0x30355); - - pHalData->bt_coexist.b8723aAgcTableOn = false; - } else if (type == BT_AGCTABLE_ON) { - RTPRINT(FBT, BT_TRACE, ("[BT]AGCTable On!\n")); - rtl8723au_write32(padapter, 0xc78, 0x4e1c0001); - rtl8723au_write32(padapter, 0xc78, 0x4d1d0001); - rtl8723au_write32(padapter, 0xc78, 0x4c1e0001); - rtl8723au_write32(padapter, 0xc78, 0x4b1f0001); - rtl8723au_write32(padapter, 0xc78, 0x4a200001); - - PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0xdc000); - PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0x90000); - PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0x51000); - PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0x12000); - PHY_SetRFReg(padapter, PathA, RF_RX_G1, bRFRegOffsetMask, 0x00355); - - pHalData->bt_coexist.b8723aAgcTableOn = true; - - pHalData->bt_coexist.bSWCoexistAllOff = false; - } -} - -void BTDM_BBBackOffLevel(struct rtw_adapter *padapter, u8 type) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (type == BT_BB_BACKOFF_OFF) { - RTPRINT(FBT, BT_TRACE, ("[BT]BBBackOffLevel Off!\n")); - rtl8723au_write32(padapter, 0xc04, 0x3a05611); - } else if (type == BT_BB_BACKOFF_ON) { - RTPRINT(FBT, BT_TRACE, ("[BT]BBBackOffLevel On!\n")); - rtl8723au_write32(padapter, 0xc04, 0x3a07611); - pHalData->bt_coexist.bSWCoexistAllOff = false; - } -} - -void BTDM_FWCoexAllOff(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - RTPRINT(FBT, BT_TRACE, ("BTDM_FWCoexAllOff()\n")); - if (pHalData->bt_coexist.bFWCoexistAllOff) - return; - RTPRINT(FBT, BT_TRACE, ("BTDM_FWCoexAllOff(), real Do\n")); - - BTDM_FWCoexAllOff8723A(padapter); - - pHalData->bt_coexist.bFWCoexistAllOff = true; -} - -void BTDM_SWCoexAllOff(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - RTPRINT(FBT, BT_TRACE, ("BTDM_SWCoexAllOff()\n")); - if (pHalData->bt_coexist.bSWCoexistAllOff) - return; - RTPRINT(FBT, BT_TRACE, ("BTDM_SWCoexAllOff(), real Do\n")); - BTDM_SWCoexAllOff8723A(padapter); - - pHalData->bt_coexist.bSWCoexistAllOff = true; -} - -void BTDM_HWCoexAllOff(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - RTPRINT(FBT, BT_TRACE, ("BTDM_HWCoexAllOff()\n")); - if (pHalData->bt_coexist.bHWCoexistAllOff) - return; - RTPRINT(FBT, BT_TRACE, ("BTDM_HWCoexAllOff(), real Do\n")); - - BTDM_HWCoexAllOff8723A(padapter); - - pHalData->bt_coexist.bHWCoexistAllOff = true; -} - -void BTDM_CoexAllOff(struct rtw_adapter *padapter) -{ - BTDM_FWCoexAllOff(padapter); - BTDM_SWCoexAllOff(padapter); - BTDM_HWCoexAllOff(padapter); -} - -void rtl8723a_BT_disable_coexist(struct rtw_adapter *padapter) -{ - struct pwrctrl_priv *ppwrctrl = &padapter->pwrctrlpriv; - - if (!rtl8723a_BT_coexist(padapter)) - return; - - /* 8723 1Ant doesn't need to turn off bt coexist mechanism. */ - if (rtl8723a_BT_using_antenna_1(padapter)) - return; - - /* Before enter IPS, turn off FW BT Co-exist mechanism */ - if (ppwrctrl->reg_rfoff == rf_on) { - RTPRINT(FBT, BT_TRACE, ("[BT][DM], Before enter IPS, turn off all Coexist DM\n")); - btdm_ResetFWCoexState(padapter); - BTDM_CoexAllOff(padapter); - BTDM_SetAntenna(padapter, BTDM_ANT_BT); - } -} - -void BTDM_SignalCompensation(struct rtw_adapter *padapter, u8 *rssi_wifi, u8 *rssi_bt) -{ - BTDM_8723ASignalCompensation(padapter, rssi_wifi, rssi_bt); -} - -void rtl8723a_BT_do_coexist(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (!rtl8723a_BT_coexist(padapter)) { - RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT not exists!!\n")); - return; - } - - if (!pHalData->bt_coexist.bInitlized) { - RTPRINT(FBT, BT_TRACE, ("[DM][BT], btdm_InitBtCoexistDM()\n")); - btdm_InitBtCoexistDM(padapter); - } - - RTPRINT(FBT, BT_TRACE, ("\n\n[DM][BT], BTDM start!!\n")); - - BTDM_PWDBMonitor(padapter); - - RTPRINT(FBT, BT_TRACE, ("[DM][BT], HW type is 8723\n")); - BTDM_BTCoexist8723A(padapter); - RTPRINT(FBT, BT_TRACE, ("[DM][BT], BTDM end!!\n\n")); -} - -void BTDM_UpdateCoexState(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (!BTDM_IsSameCoexistState(padapter)) { - RTPRINT(FBT, BT_TRACE, ("[BTCoex], Coexist State[bitMap] change from 0x%"i64fmt"x to 0x%"i64fmt"x, changeBits = 0x%"i64fmt"x\n", - pHalData->bt_coexist.PreviousState, - pHalData->bt_coexist.CurrentState, - (pHalData->bt_coexist.PreviousState^pHalData->bt_coexist.CurrentState))); - pHalData->bt_coexist.PreviousState = pHalData->bt_coexist.CurrentState; - } -} - -u8 BTDM_IsSameCoexistState(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState) { - return true; - } else { - RTPRINT(FBT, BT_TRACE, ("[DM][BT], Coexist state changed!!\n")); - return false; - } -} - -void BTDM_PWDBMonitor(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(GetDefaultAdapter(padapter)); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 H2C_Parameter[3] = {0}; - s32 tmpBTEntryMaxPWDB = 0, tmpBTEntryMinPWDB = 0xff; - u8 i; - - if (pBtMgnt->BtOperationOn) { - for (i = 0; i < MAX_BT_ASOC_ENTRY_NUM; i++) { - if (pBTInfo->BtAsocEntry[i].bUsed) { - if (pBTInfo->BtAsocEntry[i].UndecoratedSmoothedPWDB < tmpBTEntryMinPWDB) - tmpBTEntryMinPWDB = pBTInfo->BtAsocEntry[i].UndecoratedSmoothedPWDB; - if (pBTInfo->BtAsocEntry[i].UndecoratedSmoothedPWDB > tmpBTEntryMaxPWDB) - tmpBTEntryMaxPWDB = pBTInfo->BtAsocEntry[i].UndecoratedSmoothedPWDB; - /* Report every BT connection (HS mode) RSSI to FW */ - H2C_Parameter[2] = (u8)(pBTInfo->BtAsocEntry[i].UndecoratedSmoothedPWDB & 0xFF); - H2C_Parameter[0] = (MAX_FW_SUPPORT_MACID_NUM-1-i); - RTPRINT(FDM, DM_BT30, ("RSSI report for BT[%d], H2C_Par = 0x%x\n", i, H2C_Parameter[0])); - FillH2CCmd(padapter, RSSI_SETTING_EID, 3, H2C_Parameter); - RTPRINT_ADDR(FDM, (DM_PWDB|DM_BT30), ("BT_Entry Mac :"), - pBTInfo->BtAsocEntry[i].BTRemoteMACAddr) - RTPRINT(FDM, (DM_PWDB|DM_BT30), - ("BT rx pwdb[%d] = 0x%x(%d)\n", i, - pBTInfo->BtAsocEntry[i].UndecoratedSmoothedPWDB, - pBTInfo->BtAsocEntry[i].UndecoratedSmoothedPWDB)); - } - } - if (tmpBTEntryMaxPWDB != 0) { /* If associated entry is found */ - pHalData->dmpriv.BT_EntryMaxUndecoratedSmoothedPWDB = tmpBTEntryMaxPWDB; - RTPRINT(FDM, (DM_PWDB|DM_BT30), ("BT_EntryMaxPWDB = 0x%x(%d)\n", - tmpBTEntryMaxPWDB, tmpBTEntryMaxPWDB)); - } else { - pHalData->dmpriv.BT_EntryMaxUndecoratedSmoothedPWDB = 0; - } - if (tmpBTEntryMinPWDB != 0xff) { /* If associated entry is found */ - pHalData->dmpriv.BT_EntryMinUndecoratedSmoothedPWDB = tmpBTEntryMinPWDB; - RTPRINT(FDM, (DM_PWDB|DM_BT30), ("BT_EntryMinPWDB = 0x%x(%d)\n", - tmpBTEntryMinPWDB, tmpBTEntryMinPWDB)); - } else { - pHalData->dmpriv.BT_EntryMinUndecoratedSmoothedPWDB = 0; - } - } -} - -u8 BTDM_IsBTBusy(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt; - - if (pBtMgnt->ExtConfig.bBTBusy) - return true; - else - return false; -} - -u8 BTDM_IsWifiBusy(struct rtw_adapter *padapter) -{ -/*PMGNT_INFO pMgntInfo = &GetDefaultAdapter(padapter)->MgntInfo; */ - struct mlme_priv *pmlmepriv = &GetDefaultAdapter(padapter)->mlmepriv; - struct bt_30info *pBTInfo = GET_BT_INFO(padapter); - struct bt_traffic *pBtTraffic = &pBTInfo->BtTraffic; - - if (pmlmepriv->LinkDetectInfo.bBusyTraffic || - pBtTraffic->Bt30TrafficStatistics.bTxBusyTraffic || - pBtTraffic->Bt30TrafficStatistics.bRxBusyTraffic) - return true; - else - return false; -} - -u8 BTDM_IsCoexistStateChanged(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState) - return false; - else - return true; -} - -u8 BTDM_IsWifiUplink(struct rtw_adapter *padapter) -{ -/*PMGNT_INFO pMgntInfo = &GetDefaultAdapter(padapter)->MgntInfo; */ - struct mlme_priv *pmlmepriv; - struct bt_30info *pBTInfo; - struct bt_traffic *pBtTraffic; - - pmlmepriv = &padapter->mlmepriv; - pBTInfo = GET_BT_INFO(padapter); - pBtTraffic = &pBTInfo->BtTraffic; - - if ((pmlmepriv->LinkDetectInfo.bTxBusyTraffic) || - (pBtTraffic->Bt30TrafficStatistics.bTxBusyTraffic)) - return true; - else - return false; -} - -u8 BTDM_IsWifiDownlink(struct rtw_adapter *padapter) -{ -/*PMGNT_INFO pMgntInfo = &GetDefaultAdapter(padapter)->MgntInfo; */ - struct mlme_priv *pmlmepriv; - struct bt_30info *pBTInfo; - struct bt_traffic *pBtTraffic; - - pmlmepriv = &padapter->mlmepriv; - pBTInfo = GET_BT_INFO(padapter); - pBtTraffic = &pBTInfo->BtTraffic; - - if ((pmlmepriv->LinkDetectInfo.bRxBusyTraffic) || - (pBtTraffic->Bt30TrafficStatistics.bRxBusyTraffic)) - return true; - else - return false; -} - -u8 BTDM_IsBTHSMode(struct rtw_adapter *padapter) -{ -/*PMGNT_INFO pMgntInfo = &GetDefaultAdapter(padapter)->MgntInfo; */ - struct hal_data_8723a *pHalData; - struct bt_mgnt *pBtMgnt; - - pHalData = GET_HAL_DATA(padapter); - pBtMgnt = &pHalData->BtInfo.BtMgnt; - - if (pBtMgnt->BtOperationOn) - return true; - else - return false; -} - -u8 BTDM_IsBTUplink(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (pHalData->bt_coexist.BT21TrafficStatistics.bTxBusyTraffic) - return true; - else - return false; -} - -u8 BTDM_IsBTDownlink(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (pHalData->bt_coexist.BT21TrafficStatistics.bRxBusyTraffic) - return true; - else - return false; -} - -void BTDM_AdjustForBtOperation(struct rtw_adapter *padapter) -{ - RTPRINT(FBT, BT_TRACE, ("[BT][DM], BTDM_AdjustForBtOperation()\n")); - BTDM_AdjustForBtOperation8723A(padapter); -} - -void BTDM_SetBtCoexCurrAntNum(struct rtw_adapter *padapter, u8 antNum) -{ - BTDM_Set8723ABtCoexCurrAntNum(padapter, antNum); -} - -void BTDM_ForHalt(struct rtw_adapter *padapter) -{ - if (!rtl8723a_BT_coexist(padapter)) - return; - - BTDM_ForHalt8723A(padapter); - GET_HAL_DATA(padapter)->bt_coexist.bInitlized = false; -} - -void BTDM_WifiScanNotify(struct rtw_adapter *padapter, u8 scanType) -{ - if (!rtl8723a_BT_coexist(padapter)) - return; - - BTDM_WifiScanNotify8723A(padapter, scanType); -} - -void BTDM_WifiAssociateNotify(struct rtw_adapter *padapter, u8 action) -{ - if (!rtl8723a_BT_coexist(padapter)) - return; - - BTDM_WifiAssociateNotify8723A(padapter, action); -} - -void rtl8723a_BT_mediastatus_notify(struct rtw_adapter *padapter, - enum rt_media_status mstatus) -{ - if (!rtl8723a_BT_coexist(padapter)) - return; - - BTDM_MediaStatusNotify8723A(padapter, mstatus); -} - -void rtl8723a_BT_specialpacket_notify(struct rtw_adapter *padapter) -{ - if (!rtl8723a_BT_coexist(padapter)) - return; - - BTDM_ForDhcp8723A(padapter); -} - -void BTDM_ResetActionProfileState(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - pHalData->bt_coexist.CurrentState &= ~\ - (BT_COEX_STATE_PROFILE_HID|BT_COEX_STATE_PROFILE_A2DP| - BT_COEX_STATE_PROFILE_PAN|BT_COEX_STATE_PROFILE_SCO); -} - -u8 BTDM_IsActionSCO(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - struct bt_30info *pBTInfo; - struct bt_mgnt *pBtMgnt; - struct bt_dgb *pBtDbg; - u8 bRet; - - pHalData = GET_HAL_DATA(padapter); - pBTInfo = GET_BT_INFO(padapter); - pBtMgnt = &pBTInfo->BtMgnt; - pBtDbg = &pBTInfo->BtDbg; - bRet = false; - - if (pBtDbg->dbgCtrl) { - if (pBtDbg->dbgProfile == BT_DBG_PROFILE_SCO) { - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_SCO; - bRet = true; - } - } else { - if (pBtMgnt->ExtConfig.NumberOfSCO > 0) { - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_SCO; - bRet = true; - } - } - return bRet; -} - -u8 BTDM_IsActionHID(struct rtw_adapter *padapter) -{ - struct bt_30info *pBTInfo; - struct hal_data_8723a *pHalData; - struct bt_mgnt *pBtMgnt; - struct bt_dgb *pBtDbg; - u8 bRet; - - pHalData = GET_HAL_DATA(padapter); - pBTInfo = GET_BT_INFO(padapter); - pBtMgnt = &pBTInfo->BtMgnt; - pBtDbg = &pBTInfo->BtDbg; - bRet = false; - - if (pBtDbg->dbgCtrl) { - if (pBtDbg->dbgProfile == BT_DBG_PROFILE_HID) { - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_HID; - bRet = true; - } - } else { - if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID) && - pBtMgnt->ExtConfig.NumberOfHandle == 1) { - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_HID; - bRet = true; - } - } - return bRet; -} - -u8 BTDM_IsActionA2DP(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - struct bt_30info *pBTInfo; - struct bt_mgnt *pBtMgnt; - struct bt_dgb *pBtDbg; - u8 bRet; - - pHalData = GET_HAL_DATA(padapter); - pBTInfo = GET_BT_INFO(padapter); - pBtMgnt = &pBTInfo->BtMgnt; - pBtDbg = &pBTInfo->BtDbg; - bRet = false; - - if (pBtDbg->dbgCtrl) { - if (pBtDbg->dbgProfile == BT_DBG_PROFILE_A2DP) { - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_A2DP; - bRet = true; - } - } else { - if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP) && - pBtMgnt->ExtConfig.NumberOfHandle == 1) { - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_A2DP; - bRet = true; - } - } - return bRet; -} - -u8 BTDM_IsActionPAN(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - struct bt_30info *pBTInfo; - struct bt_mgnt *pBtMgnt; - struct bt_dgb *pBtDbg; - u8 bRet; - - pHalData = GET_HAL_DATA(padapter); - pBTInfo = GET_BT_INFO(padapter); - pBtMgnt = &pBTInfo->BtMgnt; - pBtDbg = &pBTInfo->BtDbg; - bRet = false; - - if (pBtDbg->dbgCtrl) { - if (pBtDbg->dbgProfile == BT_DBG_PROFILE_PAN) { - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_PAN; - bRet = true; - } - } else { - if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN) && - pBtMgnt->ExtConfig.NumberOfHandle == 1) { - pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_PAN; - bRet = true; - } - } - return bRet; -} - -u8 BTDM_IsActionHIDA2DP(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - struct bt_30info *pBTInfo; - struct bt_mgnt *pBtMgnt; - struct bt_dgb *pBtDbg; - u8 bRet; - - pHalData = GET_HAL_DATA(padapter); - pBTInfo = GET_BT_INFO(padapter); - pBtMgnt = &pBTInfo->BtMgnt; - pBtDbg = &pBTInfo->BtDbg; - bRet = false; - - if (pBtDbg->dbgCtrl) { - if (pBtDbg->dbgProfile == BT_DBG_PROFILE_HID_A2DP) { - pHalData->bt_coexist.CurrentState |= (BT_COEX_STATE_PROFILE_HID|BT_COEX_STATE_PROFILE_A2DP); - bRet = true; - } - } else { - if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID) && - BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) { - pHalData->bt_coexist.CurrentState |= (BT_COEX_STATE_PROFILE_HID|BT_COEX_STATE_PROFILE_A2DP); - bRet = true; - } - } - return bRet; -} - -u8 BTDM_IsActionHIDPAN(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - struct bt_30info *pBTInfo; - struct bt_dgb *pBtDbg; - u8 bRet; - - pHalData = GET_HAL_DATA(padapter); - pBTInfo = GET_BT_INFO(padapter); - pBtDbg = &pBTInfo->BtDbg; - bRet = false; - - if (pBtDbg->dbgCtrl) { - if (pBtDbg->dbgProfile == BT_DBG_PROFILE_HID_PAN) { - pHalData->bt_coexist.CurrentState |= (BT_COEX_STATE_PROFILE_HID|BT_COEX_STATE_PROFILE_PAN); - bRet = true; - } - } else { - if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID) && - BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN)) { - pHalData->bt_coexist.CurrentState |= (BT_COEX_STATE_PROFILE_HID|BT_COEX_STATE_PROFILE_PAN); - bRet = true; - } - } - return bRet; -} - -u8 BTDM_IsActionPANA2DP(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - struct bt_30info *pBTInfo; - struct bt_dgb *pBtDbg; - u8 bRet; - - pHalData = GET_HAL_DATA(padapter); - pBTInfo = GET_BT_INFO(padapter); - pBtDbg = &pBTInfo->BtDbg; - bRet = false; - - if (pBtDbg->dbgCtrl) { - if (pBtDbg->dbgProfile == BT_DBG_PROFILE_PAN_A2DP) { - pHalData->bt_coexist.CurrentState |= (BT_COEX_STATE_PROFILE_PAN|BT_COEX_STATE_PROFILE_A2DP); - bRet = true; - } - } else { - if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN) && BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) { - pHalData->bt_coexist.CurrentState |= (BT_COEX_STATE_PROFILE_PAN|BT_COEX_STATE_PROFILE_A2DP); - bRet = true; - } - } - return bRet; -} - -bool rtl8723a_BT_enabled(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (pHalData->bt_coexist.bCurBtDisabled) - return false; - else - return true; -} - -/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtCoexist.c ===== */ - -/* ===== Below this line is sync from SD7 driver HAL/HalBT.c ===== */ - -/* */ -/*local function */ -/* */ - -static void halbt_InitHwConfig8723A(struct rtw_adapter *padapter) -{ -} - -/* */ -/*extern function */ -/* */ -u8 HALBT_GetPGAntNum(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - return pHalData->bt_coexist.BT_Ant_Num; -} - -void HALBT_SetKey(struct rtw_adapter *padapter, u8 EntryNum) -{ - struct bt_30info *pBTinfo; - struct bt_asoc_entry *pBtAssocEntry; - u16 usConfig = 0; - - pBTinfo = GET_BT_INFO(padapter); - pBtAssocEntry = &pBTinfo->BtAsocEntry[EntryNum]; - - pBtAssocEntry->HwCAMIndex = BT_HWCAM_STAR + EntryNum; - - usConfig = CAM_VALID | (CAM_AES << 2); - rtl8723a_cam_write(padapter, pBtAssocEntry->HwCAMIndex, usConfig, - pBtAssocEntry->BTRemoteMACAddr, - pBtAssocEntry->PTK + TKIP_ENC_KEY_POS); -} - -void HALBT_RemoveKey(struct rtw_adapter *padapter, u8 EntryNum) -{ - struct bt_30info *pBTinfo; - struct bt_asoc_entry *pBtAssocEntry; - - pBTinfo = GET_BT_INFO(padapter); - pBtAssocEntry = &pBTinfo->BtAsocEntry[EntryNum]; - - if (pBTinfo->BtAsocEntry[EntryNum].HwCAMIndex != 0) { - /* ToDo : add New HALBT_RemoveKey function !! */ - if (pBtAssocEntry->HwCAMIndex >= BT_HWCAM_STAR && - pBtAssocEntry->HwCAMIndex < HALF_CAM_ENTRY) - rtl8723a_cam_empty_entry(padapter, - pBtAssocEntry->HwCAMIndex); - pBTinfo->BtAsocEntry[EntryNum].HwCAMIndex = 0; - } -} - -void rtl8723a_BT_init_hal_vars(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - - pHalData = GET_HAL_DATA(padapter); - - pHalData->bt_coexist.BluetoothCoexist = pHalData->EEPROMBluetoothCoexist; - pHalData->bt_coexist.BT_Ant_Num = pHalData->EEPROMBluetoothAntNum; - pHalData->bt_coexist.BT_CoexistType = pHalData->EEPROMBluetoothType; - pHalData->bt_coexist.BT_Ant_isolation = pHalData->EEPROMBluetoothAntIsolation; - pHalData->bt_coexist.bt_radiosharedtype = pHalData->EEPROMBluetoothRadioShared; - - RT_TRACE(_module_hal_init_c_, _drv_info_, - "BT Coexistance = 0x%x\n", rtl8723a_BT_coexist(padapter)); - - if (rtl8723a_BT_coexist(padapter)) { - if (pHalData->bt_coexist.BT_Ant_Num == Ant_x2) { - BTDM_SetBtCoexCurrAntNum(padapter, 2); - RT_TRACE(_module_hal_init_c_, _drv_info_, - "BlueTooth BT_Ant_Num = Antx2\n"); - } else if (pHalData->bt_coexist.BT_Ant_Num == Ant_x1) { - BTDM_SetBtCoexCurrAntNum(padapter, 1); - RT_TRACE(_module_hal_init_c_, _drv_info_, - "BlueTooth BT_Ant_Num = Antx1\n"); - } - pHalData->bt_coexist.bBTBusyTraffic = false; - pHalData->bt_coexist.bBTTrafficModeSet = false; - pHalData->bt_coexist.bBTNonTrafficModeSet = false; - pHalData->bt_coexist.CurrentState = 0; - pHalData->bt_coexist.PreviousState = 0; - - RT_TRACE(_module_hal_init_c_, _drv_info_, - "bt_radiosharedType = 0x%x\n", - pHalData->bt_coexist.bt_radiosharedtype); - } -} - -bool rtl8723a_BT_coexist(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (pHalData->bt_coexist.BluetoothCoexist) - return true; - else - return false; -} - -u8 HALBT_BTChipType(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - return pHalData->bt_coexist.BT_CoexistType; -} - -void rtl8723a_BT_init_hwconfig(struct rtw_adapter *padapter) -{ - halbt_InitHwConfig8723A(padapter); - rtl8723a_BT_do_coexist(padapter); -} - -void HALBT_SetRtsCtsNoLenLimit(struct rtw_adapter *padapter) -{ -} - -/* ===== End of sync from SD7 driver HAL/HalBT.c ===== */ - -void rtl8723a_dual_antenna_detection(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - struct dm_odm_t *pDM_Odm; - struct sw_ant_sw *pDM_SWAT_Table; - u8 i; - - pHalData = GET_HAL_DATA(padapter); - pDM_Odm = &pHalData->odmpriv; - pDM_SWAT_Table = &pDM_Odm->DM_SWAT_Table; - - /* */ - /* <Roger_Notes> RTL8723A Single and Dual antenna dynamic detection - mechanism when RF power state is on. */ - /* We should take power tracking, IQK, LCK, RCK RF read/write - operation into consideration. */ - /* 2011.12.15. */ - /* */ - if (!pHalData->bAntennaDetected) { - u8 btAntNum = BT_GetPGAntNum(padapter); - - /* Set default antenna B status */ - if (btAntNum == Ant_x2) - pDM_SWAT_Table->ANTB_ON = true; - else if (btAntNum == Ant_x1) - pDM_SWAT_Table->ANTB_ON = false; - else - pDM_SWAT_Table->ANTB_ON = true; - - if (pHalData->CustomerID != RT_CID_TOSHIBA) { - for (i = 0; i < MAX_ANTENNA_DETECTION_CNT; i++) { - if (ODM_SingleDualAntennaDetection - (&pHalData->odmpriv, ANTTESTALL) == true) - break; - } - - /* Set default antenna number for BT coexistence */ - if (btAntNum == Ant_x2) - BT_SetBtCoexCurrAntNum(padapter, - pDM_SWAT_Table-> - ANTB_ON ? 2 : 1); - } - pHalData->bAntennaDetected = true; - } -} diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_cmd.c b/drivers/staging/rtl8723au/hal/rtl8723a_cmd.c deleted file mode 100644 index 2230f4c..0000000 --- a/drivers/staging/rtl8723au/hal/rtl8723a_cmd.c +++ /dev/null @@ -1,755 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RTL8723A_CMD_C_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <recv_osdep.h> -#include <mlme_osdep.h> -#include <rtl8723a_hal.h> -#include <usb_ops_linux.h> - -#define RTL92C_MAX_H2C_BOX_NUMS 4 -#define RTL92C_MAX_CMD_LEN 5 -#define MESSAGE_BOX_SIZE 4 -#define EX_MESSAGE_BOX_SIZE 2 - -static u8 _is_fw_read_cmd_down(struct rtw_adapter *padapter, u8 msgbox_num) -{ - u8 read_down = false; - int retry_cnts = 100; - u8 valid; - - do { - valid = rtl8723au_read8(padapter, REG_HMETFR) & BIT(msgbox_num); - if (0 == valid) - read_down = true; - } while ((!read_down) && (retry_cnts--)); - - return read_down; -} - -/***************************************** -* H2C Msg format : -*| 31 - 8 |7 | 6 - 0 | -*| h2c_msg |Ext_bit |CMD_ID | -* -******************************************/ -int FillH2CCmd(struct rtw_adapter *padapter, u8 ElementID, u32 CmdLen, - u8 *pCmdBuffer) -{ - u8 bcmd_down = false; - s32 retry_cnts = 100; - u8 h2c_box_num; - u32 msgbox_addr; - u32 msgbox_ex_addr; - struct hal_data_8723a *pHalData; - u32 h2c_cmd = 0; - u16 h2c_cmd_ex = 0; - int ret = _FAIL; - - padapter = GET_PRIMARY_ADAPTER(padapter); - pHalData = GET_HAL_DATA(padapter); - - mutex_lock(&adapter_to_dvobj(padapter)->h2c_fwcmd_mutex); - - if (!pCmdBuffer) - goto exit; - if (CmdLen > RTL92C_MAX_CMD_LEN) - goto exit; - if (padapter->bSurpriseRemoved == true) - goto exit; - - /* pay attention to if race condition happened in H2C cmd setting. */ - do { - h2c_box_num = pHalData->LastHMEBoxNum; - - if (!_is_fw_read_cmd_down(padapter, h2c_box_num)) { - DBG_8723A(" fw read cmd failed...\n"); - goto exit; - } - - if (CmdLen <= 3) { - memcpy((u8 *)(&h2c_cmd)+1, pCmdBuffer, CmdLen); - } else { - memcpy((u8 *)(&h2c_cmd_ex), pCmdBuffer, EX_MESSAGE_BOX_SIZE); - memcpy((u8 *)(&h2c_cmd)+1, pCmdBuffer+2, (CmdLen-EX_MESSAGE_BOX_SIZE)); - *(u8 *)(&h2c_cmd) |= BIT(7); - } - - *(u8 *)(&h2c_cmd) |= ElementID; - - if (h2c_cmd & BIT(7)) { - msgbox_ex_addr = REG_HMEBOX_EXT_0 + (h2c_box_num * EX_MESSAGE_BOX_SIZE); - h2c_cmd_ex = le16_to_cpu(h2c_cmd_ex); - rtl8723au_write16(padapter, msgbox_ex_addr, h2c_cmd_ex); - } - msgbox_addr = REG_HMEBOX_0 + (h2c_box_num * MESSAGE_BOX_SIZE); - h2c_cmd = le32_to_cpu(h2c_cmd); - rtl8723au_write32(padapter, msgbox_addr, h2c_cmd); - - bcmd_down = true; - - pHalData->LastHMEBoxNum = (h2c_box_num+1) % RTL92C_MAX_H2C_BOX_NUMS; - - } while ((!bcmd_down) && (retry_cnts--)); - - ret = _SUCCESS; - -exit: - mutex_unlock(&adapter_to_dvobj(padapter)->h2c_fwcmd_mutex); - return ret; -} - -int rtl8723a_set_rssi_cmd(struct rtw_adapter *padapter, u32 param) -{ - __le32 cmd = cpu_to_le32(param); - - FillH2CCmd(padapter, RSSI_SETTING_EID, 3, (void *)&cmd); - - return _SUCCESS; -} - -int rtl8723a_set_raid_cmd(struct rtw_adapter *padapter, u32 mask, u8 arg) -{ - u8 buf[5]; - - memset(buf, 0, 5); - put_unaligned_le32(mask, buf); - buf[4] = arg; - - FillH2CCmd(padapter, MACID_CONFIG_EID, 5, buf); - - return _SUCCESS; -} - -/* bitmap[0:27] = tx_rate_bitmap */ -/* bitmap[28:31]= Rate Adaptive id */ -/* arg[0:4] = macid */ -/* arg[5] = Short GI */ -void rtl8723a_add_rateatid(struct rtw_adapter *pAdapter, u32 bitmap, u8 arg, u8 rssi_level) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter); - u8 macid = arg & 0x1f; - u32 raid = bitmap & 0xf0000000; - - bitmap &= 0x0fffffff; - if (rssi_level != DM_RATR_STA_INIT) - bitmap = ODM_Get_Rate_Bitmap23a(pHalData, macid, bitmap, - rssi_level); - - bitmap |= raid; - - rtl8723a_set_raid_cmd(pAdapter, bitmap, arg); -} - -void rtl8723a_set_FwPwrMode_cmd(struct rtw_adapter *padapter, u8 Mode) -{ - struct setpwrmode_parm H2CSetPwrMode; - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - DBG_8723A("%s: Mode =%d SmartPS =%d UAPSD =%d BcnMode = 0x%02x\n", __func__, - Mode, pwrpriv->smart_ps, padapter->registrypriv.uapsd_enable, pwrpriv->bcn_ant_mode); - - /* Forece leave RF low power mode for 1T1R to - prevent conficting setting in Fw power */ - /* saving sequence. 2010.06.07. Added by tynli. - Suggested by SD3 yschang. */ - if (Mode != PS_MODE_ACTIVE && pHalData->rf_type != RF_2T2R) - ODM_RF_Saving23a(&pHalData->odmpriv, true); - - H2CSetPwrMode.Mode = Mode; - H2CSetPwrMode.SmartPS = pwrpriv->smart_ps; - H2CSetPwrMode.AwakeInterval = 1; - H2CSetPwrMode.bAllQueueUAPSD = padapter->registrypriv.uapsd_enable; - H2CSetPwrMode.BcnAntMode = pwrpriv->bcn_ant_mode; - - FillH2CCmd(padapter, SET_PWRMODE_EID, sizeof(H2CSetPwrMode), (u8 *)&H2CSetPwrMode); - -} - -static void -ConstructBeacon(struct rtw_adapter *padapter, u8 *pframe, u32 *pLength) -{ - struct ieee80211_mgmt *mgmt; - u32 rate_len, pktlen; - 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}; - - /* DBG_8723A("%s\n", __func__); */ - - mgmt = (struct ieee80211_mgmt *)pframe; - - mgmt->frame_control = - cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); - - ether_addr_copy(mgmt->da, bc_addr); - ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); - ether_addr_copy(mgmt->bssid, get_my_bssid23a(cur_network)); - - /* A Beacon frame shouldn't have fragment bits set */ - mgmt->seq_ctrl = 0; - - /* timestamp will be inserted by hardware */ - - put_unaligned_le16(cur_network->beacon_interval, - &mgmt->u.beacon.beacon_int); - - put_unaligned_le16(cur_network->capability, - &mgmt->u.beacon.capab_info); - - pframe = mgmt->u.beacon.variable; - pktlen = offsetof(struct ieee80211_mgmt, u.beacon.variable); - - if ((pmlmeinfo->state&0x03) == MSR_AP) { - /* DBG_8723A("ie len =%d\n", cur_network->IELength); */ - pktlen += cur_network->IELength; - memcpy(pframe, cur_network->IEs, pktlen); - - goto _ConstructBeacon; - } - - /* below for ad-hoc mode */ - - /* SSID */ - pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, - cur_network->Ssid.ssid_len, - cur_network->Ssid.ssid, &pktlen); - - /* supported rates... */ - rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates); - pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, ((rate_len > 8) ? - 8 : rate_len), cur_network->SupportedRates, &pktlen); - - /* DS parameter set */ - pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *) - &cur_network->DSConfig, &pktlen); - - if ((pmlmeinfo->state&0x03) == MSR_ADHOC) { - u32 ATIMWindow; - /* IBSS Parameter Set... */ - /* ATIMWindow = cur->ATIMWindow; */ - ATIMWindow = 0; - pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2, - (unsigned char *)&ATIMWindow, &pktlen); - } - - /* todo: ERP IE */ - - /* EXTERNDED SUPPORTED RATE */ - if (rate_len > 8) - pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES, - (rate_len - 8), - (cur_network->SupportedRates + 8), - &pktlen); - - /* todo:HT for adhoc */ - -_ConstructBeacon: - - if ((pktlen + TXDESC_SIZE) > 512) { - DBG_8723A("beacon frame too large\n"); - return; - } - - *pLength = pktlen; - - /* DBG_8723A("%s bcn_sz =%d\n", __func__, pktlen); */ - -} - -static void ConstructPSPoll(struct rtw_adapter *padapter, - u8 *pframe, u32 *pLength) -{ - struct ieee80211_hdr *pwlanhdr; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - pwlanhdr = (struct ieee80211_hdr *)pframe; - - /* Frame control. */ - pwlanhdr->frame_control = - cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL); - pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); - - /* AID. */ - pwlanhdr->duration_id = cpu_to_le16(pmlmeinfo->aid | 0xc000); - - /* BSSID. */ - memcpy(pwlanhdr->addr1, get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN); - - /* TA. */ - memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN); - - *pLength = 16; -} - -static void -ConstructNullFunctionData(struct rtw_adapter *padapter, u8 *pframe, - u32 *pLength, u8 *StaAddr, u8 bQoS, u8 AC, - u8 bEosp, u8 bForcePowerSave) -{ - struct ieee80211_hdr *pwlanhdr; - u32 pktlen; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_network *cur_network = &pmlmepriv->cur_network; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - pwlanhdr = (struct ieee80211_hdr *)pframe; - - pwlanhdr->frame_control = 0; - pwlanhdr->seq_ctrl = 0; - - if (bForcePowerSave) - pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); - - switch (cur_network->network.ifmode) { - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_STATION: - pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_TODS); - memcpy(pwlanhdr->addr1, - get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), - ETH_ALEN); - memcpy(pwlanhdr->addr3, StaAddr, ETH_ALEN); - break; - case NL80211_IFTYPE_P2P_GO: - case NL80211_IFTYPE_AP: - pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_FROMDS); - memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN); - memcpy(pwlanhdr->addr2, - get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN); - memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv), - ETH_ALEN); - break; - case NL80211_IFTYPE_ADHOC: - default: - memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN); - memcpy(pwlanhdr->addr3, - get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN); - break; - } - - if (bQoS == true) { - struct ieee80211_qos_hdr *qoshdr; - qoshdr = (struct ieee80211_qos_hdr *)pframe; - - qoshdr->frame_control |= - cpu_to_le16(IEEE80211_FTYPE_DATA | - IEEE80211_STYPE_QOS_NULLFUNC); - - qoshdr->qos_ctrl = cpu_to_le16(AC & IEEE80211_QOS_CTL_TID_MASK); - if (bEosp) - qoshdr->qos_ctrl |= cpu_to_le16(IEEE80211_QOS_CTL_EOSP); - - pktlen = sizeof(struct ieee80211_qos_hdr); - } else { - pwlanhdr->frame_control |= - cpu_to_le16(IEEE80211_FTYPE_DATA | - IEEE80211_STYPE_NULLFUNC); - - pktlen = sizeof(struct ieee80211_hdr_3addr); - } - - *pLength = pktlen; -} - -static void ConstructProbeRsp(struct rtw_adapter *padapter, u8 *pframe, - u32 *pLength, u8 *StaAddr, bool bHideSSID) -{ - struct ieee80211_mgmt *mgmt; - u8 *mac, *bssid; - u32 pktlen; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - - /* DBG_8723A("%s\n", __func__); */ - - mgmt = (struct ieee80211_mgmt *)pframe; - - mac = myid(&padapter->eeprompriv); - bssid = cur_network->MacAddress; - - mgmt->frame_control = - cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP); - - mgmt->seq_ctrl = 0; - - memcpy(mgmt->da, StaAddr, ETH_ALEN); - memcpy(mgmt->sa, mac, ETH_ALEN); - memcpy(mgmt->bssid, bssid, ETH_ALEN); - - put_unaligned_le64(cur_network->tsf, - &mgmt->u.probe_resp.timestamp); - put_unaligned_le16(cur_network->beacon_interval, - &mgmt->u.probe_resp.beacon_int); - put_unaligned_le16(cur_network->capability, - &mgmt->u.probe_resp.capab_info); - - pktlen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); - - if (cur_network->IELength > MAX_IE_SZ) - return; - - memcpy(mgmt->u.probe_resp.variable, cur_network->IEs, - cur_network->IELength); - pktlen += (cur_network->IELength); - - *pLength = pktlen; -} - -/* */ -/* Description: Fill the reserved packets that FW will use to RSVD page. */ -/* Now we just send 4 types packet to rsvd page. */ -/* (1)Beacon, (2)Ps-poll, (3)Null data, (4)ProbeRsp. */ -/* Input: */ -/* bDLFinished - false: At the first time we will send all the packets as a large packet to Hw, */ -/* so we need to set the packet length to total lengh. */ -/* true: At the second time, we should send the first packet (default:beacon) */ -/* to Hw again and set the lengh in descriptor to the real beacon lengh. */ -/* 2009.10.15 by tynli. */ -static void SetFwRsvdPagePkt(struct rtw_adapter *padapter, bool bDLFinished) -{ - struct hal_data_8723a *pHalData; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - struct xmit_priv *pxmitpriv; - struct mlme_ext_priv *pmlmeext; - struct mlme_ext_info *pmlmeinfo; - u32 BeaconLength = 0, ProbeRspLength = 0, PSPollLength; - u32 NullDataLength, QosNullLength, BTQosNullLength; - u8 *ReservedPagePacket; - u8 PageNum, PageNeed, TxDescLen; - u16 BufIndex; - u32 TotalPacketLen; - struct rsvdpage_loc RsvdPageLoc; - - DBG_8723A("%s\n", __func__); - - ReservedPagePacket = kzalloc(1000, GFP_KERNEL); - if (ReservedPagePacket == NULL) { - DBG_8723A("%s: alloc ReservedPagePacket fail!\n", __func__); - return; - } - - pHalData = GET_HAL_DATA(padapter); - pxmitpriv = &padapter->xmitpriv; - pmlmeext = &padapter->mlmeextpriv; - pmlmeinfo = &pmlmeext->mlmext_info; - - TxDescLen = TXDESC_SIZE; - PageNum = 0; - - /* 3 (1) beacon */ - BufIndex = TXDESC_OFFSET; - ConstructBeacon(padapter, &ReservedPagePacket[BufIndex], &BeaconLength); - - /* When we count the first page size, we need to reserve description size for the RSVD */ - /* packet, it will be filled in front of the packet in TXPKTBUF. */ - PageNeed = (u8)PageNum_128(TxDescLen + BeaconLength); - /* To reserved 2 pages for beacon buffer. 2010.06.24. */ - if (PageNeed == 1) - PageNeed += 1; - PageNum += PageNeed; - pHalData->FwRsvdPageStartOffset = PageNum; - - BufIndex += PageNeed*128; - - /* 3 (2) ps-poll */ - RsvdPageLoc.LocPsPoll = PageNum; - ConstructPSPoll(padapter, &ReservedPagePacket[BufIndex], &PSPollLength); - rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], PSPollLength, true, false); - - PageNeed = (u8)PageNum_128(TxDescLen + PSPollLength); - PageNum += PageNeed; - - BufIndex += PageNeed*128; - - /* 3 (3) null data */ - RsvdPageLoc.LocNullData = PageNum; - ConstructNullFunctionData(padapter, &ReservedPagePacket[BufIndex], - &NullDataLength, - get_my_bssid23a(&pmlmeinfo->network), - false, 0, 0, false); - rtl8723a_fill_fake_txdesc(padapter, - &ReservedPagePacket[BufIndex-TxDescLen], - NullDataLength, false, false); - - PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength); - PageNum += PageNeed; - - BufIndex += PageNeed*128; - - /* 3 (4) probe response */ - RsvdPageLoc.LocProbeRsp = PageNum; - ConstructProbeRsp( - padapter, - &ReservedPagePacket[BufIndex], - &ProbeRspLength, - get_my_bssid23a(&pmlmeinfo->network), - false); - rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], ProbeRspLength, false, false); - - PageNeed = (u8)PageNum_128(TxDescLen + ProbeRspLength); - PageNum += PageNeed; - - BufIndex += PageNeed*128; - - /* 3 (5) Qos null data */ - RsvdPageLoc.LocQosNull = PageNum; - ConstructNullFunctionData( - padapter, - &ReservedPagePacket[BufIndex], - &QosNullLength, - get_my_bssid23a(&pmlmeinfo->network), - true, 0, 0, false); - rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], QosNullLength, false, false); - - PageNeed = (u8)PageNum_128(TxDescLen + QosNullLength); - PageNum += PageNeed; - - BufIndex += PageNeed*128; - - /* 3 (6) BT Qos null data */ - RsvdPageLoc.LocBTQosNull = PageNum; - ConstructNullFunctionData( - padapter, - &ReservedPagePacket[BufIndex], - &BTQosNullLength, - get_my_bssid23a(&pmlmeinfo->network), - true, 0, 0, false); - rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, false, true); - - TotalPacketLen = BufIndex + BTQosNullLength; - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (pmgntframe == NULL) - goto exit; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - pattrib->qsel = 0x10; - pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TXDESC_OFFSET; - memcpy(pmgntframe->buf_addr, ReservedPagePacket, TotalPacketLen); - - rtl8723au_mgnt_xmit(padapter, pmgntframe); - - DBG_8723A("%s: Set RSVD page location to Fw\n", __func__); - FillH2CCmd(padapter, RSVD_PAGE_EID, sizeof(RsvdPageLoc), (u8 *)&RsvdPageLoc); - -exit: - kfree(ReservedPagePacket); -} - -void rtl8723a_set_FwJoinBssReport_cmd(struct rtw_adapter *padapter, u8 mstatus) -{ - struct joinbssrpt_parm JoinBssRptParm; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - DBG_8723A("%s mstatus(%x)\n", __func__, mstatus); - - if (mstatus == 1) { - bool bRecover = false; - u8 v8; - - /* We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C. */ - /* Suggested by filen. Added by tynli. */ - rtl8723au_write16(padapter, REG_BCN_PSR_RPT, - 0xC000|pmlmeinfo->aid); - /* Do not set TSF again here or vWiFi beacon DMA INT will not work. */ - /* correct_TSF23a(padapter, pmlmeext); */ - /* Hw sequende enable by dedault. 2010.06.23. by tynli. */ - /* rtl8723au_write16(padapter, REG_NQOS_SEQ, ((pmlmeext->mgnt_seq+100)&0xFFF)); */ - /* rtl8723au_write8(padapter, REG_HWSEQ_CTRL, 0xFF); */ - - /* set REG_CR bit 8 */ - v8 = rtl8723au_read8(padapter, REG_CR+1); - v8 |= BIT(0); /* ENSWBCN */ - rtl8723au_write8(padapter, REG_CR+1, v8); - - /* Disable Hw protection for a time which revserd for Hw sending beacon. */ - /* Fix download reserved page packet fail that access collision with the protection time. */ - /* 2010.05.11. Added by tynli. */ -/* SetBcnCtrlReg23a(padapter, 0, BIT(3)); */ -/* SetBcnCtrlReg23a(padapter, BIT(4), 0); */ - SetBcnCtrlReg23a(padapter, BIT(4), BIT(3)); - - /* Set FWHW_TXQ_CTRL 0x422[6]= 0 to tell Hw the packet is not a real beacon frame. */ - if (pHalData->RegFwHwTxQCtrl & BIT(6)) - bRecover = true; - - /* To tell Hw the packet is not a real beacon frame. */ - /* U1bTmp = rtl8723au_read8(padapter, REG_FWHW_TXQ_CTRL+2); */ - rtl8723au_write8(padapter, REG_FWHW_TXQ_CTRL + 2, - pHalData->RegFwHwTxQCtrl & ~BIT(6)); - pHalData->RegFwHwTxQCtrl &= ~BIT(6); - SetFwRsvdPagePkt(padapter, 0); - - /* 2010.05.11. Added by tynli. */ - SetBcnCtrlReg23a(padapter, BIT(3), BIT(4)); - - /* To make sure that if there exists an adapter which would like to send beacon. */ - /* If exists, the origianl value of 0x422[6] will be 1, we should check this to */ - /* prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */ - /* the beacon cannot be sent by HW. */ - /* 2010.06.23. Added by tynli. */ - if (bRecover) { - rtl8723au_write8(padapter, REG_FWHW_TXQ_CTRL + 2, - pHalData->RegFwHwTxQCtrl | BIT(6)); - pHalData->RegFwHwTxQCtrl |= BIT(6); - } - - /* Clear CR[8] or beacon packet will not be send to TxBuf anymore. */ - v8 = rtl8723au_read8(padapter, REG_CR+1); - v8 &= ~BIT(0); /* ~ENSWBCN */ - rtl8723au_write8(padapter, REG_CR+1, v8); - } - - JoinBssRptParm.OpMode = mstatus; - - FillH2CCmd(padapter, JOINBSS_RPT_EID, sizeof(JoinBssRptParm), (u8 *)&JoinBssRptParm); - -} - -#ifdef CONFIG_8723AU_BT_COEXIST -static void SetFwRsvdPagePkt_BTCoex(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - struct xmit_priv *pxmitpriv; - struct mlme_ext_priv *pmlmeext; - struct mlme_ext_info *pmlmeinfo; - u8 fakemac[6] = {0x00, 0xe0, 0x4c, 0x00, 0x00, 0x00}; - u32 NullDataLength, BTQosNullLength; - u8 *ReservedPagePacket; - u8 PageNum, PageNeed, TxDescLen; - u16 BufIndex; - u32 TotalPacketLen; - struct rsvdpage_loc RsvdPageLoc; - - DBG_8723A("+%s\n", __func__); - - ReservedPagePacket = kzalloc(1024, GFP_KERNEL); - if (ReservedPagePacket == NULL) { - DBG_8723A("%s: alloc ReservedPagePacket fail!\n", __func__); - return; - } - - pHalData = GET_HAL_DATA(padapter); - pxmitpriv = &padapter->xmitpriv; - pmlmeext = &padapter->mlmeextpriv; - pmlmeinfo = &pmlmeext->mlmext_info; - - TxDescLen = TXDESC_SIZE; - PageNum = 0; - - /* 3 (1) beacon */ - BufIndex = TXDESC_OFFSET; - /* skip Beacon Packet */ - PageNeed = 3; - - PageNum += PageNeed; - pHalData->FwRsvdPageStartOffset = PageNum; - - BufIndex += PageNeed*128; - - /* 3 (3) null data */ - RsvdPageLoc.LocNullData = PageNum; - ConstructNullFunctionData( - padapter, - &ReservedPagePacket[BufIndex], - &NullDataLength, - fakemac, - false, 0, 0, false); - rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], NullDataLength, false, false); - - PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength); - PageNum += PageNeed; - - BufIndex += PageNeed*128; - - /* 3 (6) BT Qos null data */ - RsvdPageLoc.LocBTQosNull = PageNum; - ConstructNullFunctionData( - padapter, - &ReservedPagePacket[BufIndex], - &BTQosNullLength, - fakemac, - true, 0, 0, false); - rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, false, true); - - TotalPacketLen = BufIndex + BTQosNullLength; - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (pmgntframe == NULL) - goto exit; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - pattrib->qsel = 0x10; - pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TXDESC_OFFSET; - memcpy(pmgntframe->buf_addr, ReservedPagePacket, TotalPacketLen); - - rtl8723au_mgnt_xmit(padapter, pmgntframe); - - DBG_8723A("%s: Set RSVD page location to Fw\n", __func__); - FillH2CCmd(padapter, RSVD_PAGE_EID, sizeof(RsvdPageLoc), (u8 *)&RsvdPageLoc); - -exit: - kfree(ReservedPagePacket); -} - -void rtl8723a_set_BTCoex_AP_mode_FwRsvdPkt_cmd(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - u8 bRecover = false; - - DBG_8723A("+%s\n", __func__); - - pHalData = GET_HAL_DATA(padapter); - - /* Set FWHW_TXQ_CTRL 0x422[6]= 0 to tell Hw the packet is not a real beacon frame. */ - if (pHalData->RegFwHwTxQCtrl & BIT(6)) - bRecover = true; - - /* To tell Hw the packet is not a real beacon frame. */ - pHalData->RegFwHwTxQCtrl &= ~BIT(6); - rtl8723au_write8(padapter, REG_FWHW_TXQ_CTRL + 2, - pHalData->RegFwHwTxQCtrl); - SetFwRsvdPagePkt_BTCoex(padapter); - - /* To make sure that if there exists an adapter which would like to send beacon. */ - /* If exists, the origianl value of 0x422[6] will be 1, we should check this to */ - /* prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */ - /* the beacon cannot be sent by HW. */ - /* 2010.06.23. Added by tynli. */ - if (bRecover) { - pHalData->RegFwHwTxQCtrl |= BIT(6); - rtl8723au_write8(padapter, REG_FWHW_TXQ_CTRL + 2, - pHalData->RegFwHwTxQCtrl); - } -} -#endif diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_dm.c b/drivers/staging/rtl8723au/hal/rtl8723a_dm.c deleted file mode 100644 index 1e831f2..0000000 --- a/drivers/staging/rtl8723au/hal/rtl8723a_dm.c +++ /dev/null @@ -1,194 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -/* */ -/* Description: */ -/* */ -/* This file is for 92CE/92CU dynamic mechanism only */ -/* */ -/* */ -/* */ -#define _RTL8723A_DM_C_ - -/* */ -/* include files */ -/* */ -#include <osdep_service.h> -#include <drv_types.h> - -#include <rtl8723a_hal.h> -#include <usb_ops_linux.h> - -/* */ -/* Global var */ -/* */ - -static void dm_CheckPbcGPIO(struct rtw_adapter *padapter) -{ - u8 tmp1byte; - u8 bPbcPressed = false; - - if (!padapter->registrypriv.hw_wps_pbc) - return; - - tmp1byte = rtl8723au_read8(padapter, GPIO_IO_SEL); - tmp1byte |= (HAL_8192C_HW_GPIO_WPS_BIT); - /* enable GPIO[2] as output mode */ - rtl8723au_write8(padapter, GPIO_IO_SEL, tmp1byte); - - tmp1byte &= ~(HAL_8192C_HW_GPIO_WPS_BIT); - /* reset the floating voltage level */ - rtl8723au_write8(padapter, GPIO_IN, tmp1byte); - - tmp1byte = rtl8723au_read8(padapter, GPIO_IO_SEL); - tmp1byte &= ~(HAL_8192C_HW_GPIO_WPS_BIT); - /* enable GPIO[2] as input mode */ - rtl8723au_write8(padapter, GPIO_IO_SEL, tmp1byte); - - tmp1byte = rtl8723au_read8(padapter, GPIO_IN); - - if (tmp1byte == 0xff) - return; - - if (tmp1byte&HAL_8192C_HW_GPIO_WPS_BIT) - bPbcPressed = true; - - if (bPbcPressed) { - /* Here we only set bPbcPressed to true */ - /* After trigger PBC, the variable will be set to false */ - DBG_8723A("CheckPbcGPIO - PBC is pressed\n"); - - if (padapter->pid[0] == 0) { - /* 0 is the default value and it means the application - * monitors the HW PBC doesn't privde its pid to driver. - */ - return; - } - - kill_pid(find_vpid(padapter->pid[0]), SIGUSR1, 1); - } -} - -/* Initialize GPIO setting registers */ -/* functions */ - -void rtl8723a_init_dm_priv(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - struct dm_odm_t *pDM_Odm = &pHalData->odmpriv; - u8 cut_ver, fab_ver; - - memset(pdmpriv, 0, sizeof(struct dm_priv)); - memset(pDM_Odm, 0, sizeof(*pDM_Odm)); - - pDM_Odm->Adapter = Adapter; - - ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_IC_TYPE, ODM_RTL8723A); - - if (IS_8723A_A_CUT(pHalData->VersionID)) { - fab_ver = ODM_UMC; - cut_ver = ODM_CUT_A; - } else if (IS_8723A_B_CUT(pHalData->VersionID)) { - fab_ver = ODM_UMC; - cut_ver = ODM_CUT_B; - } else { - fab_ver = ODM_TSMC; - cut_ver = ODM_CUT_A; - } - ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_FAB_VER, fab_ver); - ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_CUT_VER, cut_ver); - ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_MP_TEST_CHIP, IS_NORMAL_CHIP(pHalData->VersionID)); - - ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_BOARD_TYPE, pHalData->BoardType); - - if (pHalData->BoardType == BOARD_USB_High_PA) { - ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_EXT_LNA, true); - ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_EXT_PA, true); - } - ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_BWIFI_TEST, Adapter->registrypriv.wifi_spec); -} - -static void Update_ODM_ComInfo_8723a(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct dm_odm_t *pDM_Odm = &pHalData->odmpriv; - struct dm_priv *pdmpriv = &pHalData->dmpriv; - int i; - pdmpriv->InitODMFlag = 0; - /* Pointer reference */ - rtl8723a_odm_support_ability_set(Adapter, DYNAMIC_ALL_FUNC_ENABLE); - - for (i = 0; i < NUM_STA; i++) - ODM_CmnInfoPtrArrayHook23a(pDM_Odm, ODM_CMNINFO_STA_STATUS, i, NULL); -} - -void rtl8723a_InitHalDm(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - struct dm_odm_t *pDM_Odm = &pHalData->odmpriv; - u8 i; - - Update_ODM_ComInfo_8723a(Adapter); - ODM23a_DMInit(pDM_Odm); - /* Save REG_INIDATA_RATE_SEL value for TXDESC. */ - for (i = 0; i < 32; i++) - pdmpriv->INIDATA_RATE[i] = rtl8723au_read8(Adapter, REG_INIDATA_RATE_SEL+i) & 0x3f; -} - -void -rtl8723a_HalDmWatchDog( - struct rtw_adapter *Adapter - ) -{ - bool bFwCurrentInPSMode = false; - bool bFwPSAwake = true; - u8 bLinked = false; - u8 hw_init_completed = false; - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - - hw_init_completed = Adapter->hw_init_completed; - - if (hw_init_completed == false) - goto skip_dm; - - bFwCurrentInPSMode = Adapter->pwrctrlpriv.bFwCurrentInPSMode; - bFwPSAwake = rtl8723a_get_fwlps_rf_on(Adapter); - - if (!bFwCurrentInPSMode && bFwPSAwake) { - /* Read REG_INIDATA_RATE_SEL value for TXDESC. */ - if (check_fwstate(&Adapter->mlmepriv, WIFI_STATION_STATE)) { - pdmpriv->INIDATA_RATE[0] = rtl8723au_read8(Adapter, REG_INIDATA_RATE_SEL) & 0x3f; - } else { - u8 i; - for (i = 1 ; i < (Adapter->stapriv.asoc_sta_count + 1); i++) - pdmpriv->INIDATA_RATE[i] = rtl8723au_read8(Adapter, (REG_INIDATA_RATE_SEL+i)) & 0x3f; - } - } - - /* ODM */ - if (rtw_linked_check(Adapter)) - bLinked = true; - - ODM_CmnInfoUpdate23a(&pHalData->odmpriv, ODM_CMNINFO_LINK, bLinked); - ODM_DMWatchdog23a(Adapter); - -skip_dm: - - /* Check GPIO to determine current RF on/off and Pbc status. */ - /* Check Hardware Radio ON/OFF or not */ - dm_CheckPbcGPIO(Adapter); -} diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c b/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c deleted file mode 100644 index 1ea0af4..0000000 --- a/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c +++ /dev/null @@ -1,2076 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _HAL_INIT_C_ - -#include <linux/firmware.h> -#include <drv_types.h> -#include <rtw_efuse.h> - -#include <rtl8723a_hal.h> -#include <usb_ops_linux.h> - -static void _FWDownloadEnable(struct rtw_adapter *padapter, bool enable) -{ - u8 tmp; - - if (enable) { - /* 8051 enable */ - tmp = rtl8723au_read8(padapter, REG_SYS_FUNC_EN + 1); - rtl8723au_write8(padapter, REG_SYS_FUNC_EN + 1, tmp | 0x04); - - /* MCU firmware download enable. */ - tmp = rtl8723au_read8(padapter, REG_MCUFWDL); - rtl8723au_write8(padapter, REG_MCUFWDL, tmp | 0x01); - - /* 8051 reset */ - tmp = rtl8723au_read8(padapter, REG_MCUFWDL + 2); - rtl8723au_write8(padapter, REG_MCUFWDL + 2, tmp & 0xf7); - } else { - /* MCU firmware download disable. */ - tmp = rtl8723au_read8(padapter, REG_MCUFWDL); - rtl8723au_write8(padapter, REG_MCUFWDL, tmp & 0xfe); - - /* Reserved for fw extension. */ - rtl8723au_write8(padapter, REG_MCUFWDL + 1, 0x00); - } -} - -static int -_PageWrite(struct rtw_adapter *padapter, u32 page, void *buffer, u32 size) -{ - u8 value8; - u8 u8Page = (u8) (page & 0x07); - - if (size > MAX_PAGE_SIZE) - return _FAIL; - - value8 = (rtl8723au_read8(padapter, REG_MCUFWDL + 2) & 0xF8) | u8Page; - rtl8723au_write8(padapter, REG_MCUFWDL + 2, value8); - - return rtl8723au_writeN(padapter, FW_8723A_START_ADDRESS, size, buffer); -} - -static int _WriteFW(struct rtw_adapter *padapter, void *buffer, u32 size) -{ - /* Since we need dynamic decide method of dwonload fw, so we - call this function to get chip version. */ - /* We can remove _ReadChipVersion from ReadpadapterInfo8192C later. */ - int ret = _SUCCESS; - u32 pageNums, remainSize; - u32 page, offset; - u8 *bufferPtr = (u8 *) buffer; - - pageNums = size / MAX_PAGE_SIZE; - /* RT_ASSERT((pageNums <= 4), - ("Page numbers should not greater then 4 \n")); */ - remainSize = size % MAX_PAGE_SIZE; - - for (page = 0; page < pageNums; page++) { - offset = page * MAX_PAGE_SIZE; - ret = _PageWrite(padapter, page, bufferPtr + offset, - MAX_PAGE_SIZE); - - if (ret == _FAIL) - goto exit; - } - if (remainSize) { - offset = pageNums * MAX_PAGE_SIZE; - page = pageNums; - ret = _PageWrite(padapter, page, bufferPtr + offset, - remainSize); - - if (ret == _FAIL) - goto exit; - } - RT_TRACE(_module_hal_init_c_, _drv_info_, - "_WriteFW Done- for Normal chip.\n"); - -exit: - return ret; -} - -static int _FWFreeToGo(struct rtw_adapter *padapter) -{ - u32 counter = 0; - u32 value32; - - /* polling CheckSum report */ - do { - value32 = rtl8723au_read32(padapter, REG_MCUFWDL); - if (value32 & FWDL_ChkSum_rpt) - break; - } while (counter++ < POLLING_READY_TIMEOUT_COUNT); - - if (counter >= POLLING_READY_TIMEOUT_COUNT) { - RT_TRACE(_module_hal_init_c_, _drv_err_, - "%s: chksum report fail! REG_MCUFWDL:0x%08x\n", - __func__, value32); - return _FAIL; - } - RT_TRACE(_module_hal_init_c_, _drv_info_, - "%s: Checksum report OK! REG_MCUFWDL:0x%08x\n", __func__, - value32); - - value32 = rtl8723au_read32(padapter, REG_MCUFWDL); - value32 |= MCUFWDL_RDY; - value32 &= ~WINTINI_RDY; - rtl8723au_write32(padapter, REG_MCUFWDL, value32); - - /* polling for FW ready */ - counter = 0; - do { - value32 = rtl8723au_read32(padapter, REG_MCUFWDL); - if (value32 & WINTINI_RDY) { - RT_TRACE(_module_hal_init_c_, _drv_info_, - "%s: Polling FW ready success!! REG_MCUFWDL:0x%08x\n", - __func__, value32); - return _SUCCESS; - } - udelay(5); - } while (counter++ < POLLING_READY_TIMEOUT_COUNT); - - RT_TRACE(_module_hal_init_c_, _drv_err_, - "%s: Polling FW ready fail!! REG_MCUFWDL:0x%08x\n", - __func__, value32); - return _FAIL; -} - -#define IS_FW_81xxC(padapter) (((GET_HAL_DATA(padapter))->FirmwareSignature & 0xFFF0) == 0x88C0) - -void rtl8723a_FirmwareSelfReset(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 u1bTmp; - u8 Delay = 100; - - if (!(IS_FW_81xxC(padapter) && - ((pHalData->FirmwareVersion < 0x21) || - (pHalData->FirmwareVersion == 0x21 && - pHalData->FirmwareSubVersion < 0x01)))) { - /* after 88C Fw v33.1 */ - /* 0x1cf = 0x20. Inform 8051 to reset. 2009.12.25. tynli_test */ - rtl8723au_write8(padapter, REG_HMETFR + 3, 0x20); - - u1bTmp = rtl8723au_read8(padapter, REG_SYS_FUNC_EN + 1); - while (u1bTmp & BIT(2)) { - Delay--; - if (Delay == 0) - break; - udelay(50); - u1bTmp = rtl8723au_read8(padapter, REG_SYS_FUNC_EN + 1); - } - RT_TRACE(_module_hal_init_c_, _drv_info_, - "-%s: 8051 reset success (%d)\n", __func__, - Delay); - - if ((Delay == 0)) { - /* force firmware reset */ - u1bTmp = rtl8723au_read8(padapter, REG_SYS_FUNC_EN + 1); - rtl8723au_write8(padapter, REG_SYS_FUNC_EN + 1, - u1bTmp & ~BIT(2)); - } - } -} - -/* */ -/* Description: */ -/* Download 8192C firmware code. */ -/* */ -/* */ -int rtl8723a_FirmwareDownload(struct rtw_adapter *padapter) -{ - int rtStatus = _SUCCESS; - u8 writeFW_retry = 0; - unsigned long fwdl_start_time; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); - struct device *device = dvobj_to_dev(dvobj); - struct rt_8723a_firmware_hdr *pFwHdr = NULL; - const struct firmware *fw; - char *fw_name; - u8 *firmware_buf = NULL; - u8 *buf; - int fw_size; - static int log_version; - - RT_TRACE(_module_hal_init_c_, _drv_info_, "+%s\n", __func__); - - if (IS_8723A_A_CUT(pHalData->VersionID)) { - fw_name = "rtlwifi/rtl8723aufw_A.bin"; - RT_TRACE(_module_hal_init_c_, _drv_info_, - "rtl8723a_FirmwareDownload: R8723FwImageArray_UMC for RTL8723A A CUT\n"); - } else if (IS_8723A_B_CUT(pHalData->VersionID)) { - /* WLAN Fw. */ - if (padapter->registrypriv.wifi_spec == 1) { - fw_name = "rtlwifi/rtl8723aufw_B_NoBT.bin"; - DBG_8723A(" Rtl8723_FwUMCBCutImageArrayWithoutBT for " - "RTL8723A B CUT\n"); - } else { - if (rtl8723a_BT_coexist(padapter)) { - fw_name = "rtlwifi/rtl8723aufw_B.bin"; - DBG_8723A(" Rtl8723_FwUMCBCutImageArrayWithBT " - "for RTL8723A B CUT\n"); - } else { - fw_name = "rtlwifi/rtl8723aufw_B_NoBT.bin"; - DBG_8723A(" Rtl8723_FwUMCBCutImageArrayWithout " - "BT for RTL8723A B CUT\n"); - } - } - } else { - /* <Roger_TODO> We should download proper RAM Code here - to match the ROM code. */ - RT_TRACE(_module_hal_init_c_, _drv_err_, - "%s: unknown version!\n", __func__); - rtStatus = _FAIL; - goto Exit; - } - - pr_info("rtl8723au: Loading firmware %s\n", fw_name); - if (request_firmware(&fw, fw_name, device)) { - pr_err("rtl8723au: request_firmware load failed\n"); - rtStatus = _FAIL; - goto Exit; - } - if (!fw) { - pr_err("rtl8723au: Firmware %s not available\n", fw_name); - rtStatus = _FAIL; - goto Exit; - } - firmware_buf = kmemdup(fw->data, fw->size, GFP_KERNEL); - fw_size = fw->size; - release_firmware(fw); - if (!firmware_buf) { - rtStatus = _FAIL; - goto Exit; - } - buf = firmware_buf; - - /* To Check Fw header. Added by tynli. 2009.12.04. */ - pFwHdr = (struct rt_8723a_firmware_hdr *)firmware_buf; - - pHalData->FirmwareVersion = le16_to_cpu(pFwHdr->Version); - pHalData->FirmwareSubVersion = pFwHdr->Subversion; - pHalData->FirmwareSignature = le16_to_cpu(pFwHdr->Signature); - - DBG_8723A("%s: fw_ver =%d fw_subver =%d sig = 0x%x\n", - __func__, pHalData->FirmwareVersion, - pHalData->FirmwareSubVersion, pHalData->FirmwareSignature); - - if (!log_version++) - pr_info("%sFirmware Version %d, SubVersion %d, Signature " - "0x%x\n", DRIVER_PREFIX, pHalData->FirmwareVersion, - pHalData->FirmwareSubVersion, - pHalData->FirmwareSignature); - - if (IS_FW_HEADER_EXIST(pFwHdr)) { - /* Shift 32 bytes for FW header */ - buf = buf + 32; - fw_size = fw_size - 32; - } - - /* Suggested by Filen. If 8051 is running in RAM code, driver should - inform Fw to reset by itself, */ - /* or it will cause download Fw fail. 2010.02.01. by tynli. */ - if (rtl8723au_read8(padapter, REG_MCUFWDL) & RAM_DL_SEL) { - /* 8051 RAM code */ - rtl8723a_FirmwareSelfReset(padapter); - rtl8723au_write8(padapter, REG_MCUFWDL, 0x00); - } - - _FWDownloadEnable(padapter, true); - fwdl_start_time = jiffies; - while (1) { - /* reset the FWDL chksum */ - rtl8723au_write8(padapter, REG_MCUFWDL, - rtl8723au_read8(padapter, REG_MCUFWDL) | - FWDL_ChkSum_rpt); - - rtStatus = _WriteFW(padapter, buf, fw_size); - - if (rtStatus == _SUCCESS || - (jiffies_to_msecs(jiffies - fwdl_start_time) > 500 && - writeFW_retry++ >= 3)) - break; - - DBG_8723A("%s writeFW_retry:%u, time after fwdl_start_time:" - "%ums\n", __func__, writeFW_retry, - jiffies_to_msecs(jiffies - fwdl_start_time)); - } - _FWDownloadEnable(padapter, false); - if (_SUCCESS != rtStatus) { - DBG_8723A("DL Firmware failed!\n"); - goto Exit; - } - - rtStatus = _FWFreeToGo(padapter); - if (_SUCCESS != rtStatus) { - RT_TRACE(_module_hal_init_c_, _drv_err_, - "DL Firmware failed!\n"); - goto Exit; - } - RT_TRACE(_module_hal_init_c_, _drv_info_, - "Firmware is ready to run!\n"); - -Exit: - kfree(firmware_buf); - return rtStatus; -} - -void rtl8723a_InitializeFirmwareVars(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - /* Init Fw LPS related. */ - padapter->pwrctrlpriv.bFwCurrentInPSMode = false; - - /* Init H2C counter. by tynli. 2009.12.09. */ - pHalData->LastHMEBoxNum = 0; -} - -/* */ -/* Efuse related code */ -/* */ -static u8 -hal_EfuseSwitchToBank(struct rtw_adapter *padapter, u8 bank) -{ - u8 bRet = false; - u32 value32 = 0; - - DBG_8723A("%s: Efuse switch bank to %d\n", __func__, bank); - value32 = rtl8723au_read32(padapter, EFUSE_TEST); - bRet = true; - switch (bank) { - case 0: - value32 = (value32 & ~EFUSE_SEL_MASK) | - EFUSE_SEL(EFUSE_WIFI_SEL_0); - break; - case 1: - value32 = (value32 & ~EFUSE_SEL_MASK) | - EFUSE_SEL(EFUSE_BT_SEL_0); - break; - case 2: - value32 = (value32 & ~EFUSE_SEL_MASK) | - EFUSE_SEL(EFUSE_BT_SEL_1); - break; - case 3: - value32 = (value32 & ~EFUSE_SEL_MASK) | - EFUSE_SEL(EFUSE_BT_SEL_2); - break; - default: - value32 = (value32 & ~EFUSE_SEL_MASK) | - EFUSE_SEL(EFUSE_WIFI_SEL_0); - bRet = false; - break; - } - rtl8723au_write32(padapter, EFUSE_TEST, value32); - - return bRet; -} - -static void -hal_ReadEFuse_WiFi(struct rtw_adapter *padapter, - u16 _offset, u16 _size_byte, u8 *pbuf) -{ - u8 *efuseTbl = NULL; - u16 eFuse_Addr = 0; - u8 offset, wden; - u8 efuseHeader, efuseExtHdr, efuseData; - u16 i, total, used; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - /* Do NOT excess total size of EFuse table. - Added by Roger, 2008.11.10. */ - if ((_offset + _size_byte) > EFUSE_MAP_LEN_8723A) { - DBG_8723A("%s: Invalid offset(%#x) with read bytes(%#x)!!\n", - __func__, _offset, _size_byte); - return; - } - - efuseTbl = kmalloc(EFUSE_MAP_LEN_8723A, GFP_KERNEL); - if (!efuseTbl) - return; - /* 0xff will be efuse default value instead of 0x00. */ - memset(efuseTbl, 0xFF, EFUSE_MAP_LEN_8723A); - - /* switch bank back to bank 0 for later BT and wifi use. */ - hal_EfuseSwitchToBank(padapter, 0); - - while (AVAILABLE_EFUSE_ADDR(eFuse_Addr)) { - ReadEFuseByte23a(padapter, eFuse_Addr++, &efuseHeader); - if (efuseHeader == 0xFF) { - DBG_8723A("%s: data end at address =%#x\n", __func__, - eFuse_Addr); - break; - } - - /* Check PG header for section num. */ - if (EXT_HEADER(efuseHeader)) { /* extended header */ - offset = GET_HDR_OFFSET_2_0(efuseHeader); - - ReadEFuseByte23a(padapter, eFuse_Addr++, &efuseExtHdr); - if (ALL_WORDS_DISABLED(efuseExtHdr)) - continue; - - offset |= ((efuseExtHdr & 0xF0) >> 1); - wden = efuseExtHdr & 0x0F; - } else { - offset = (efuseHeader >> 4) & 0x0f; - wden = efuseHeader & 0x0f; - } - - if (offset < EFUSE_MAX_SECTION_8723A) { - u16 addr; - /* Get word enable value from PG header */ - - addr = offset * PGPKT_DATA_SIZE; - for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { - /* Check word enable condition in the section */ - if (!(wden & (0x01 << i))) { - ReadEFuseByte23a(padapter, eFuse_Addr++, - &efuseData); - efuseTbl[addr] = efuseData; - - ReadEFuseByte23a(padapter, eFuse_Addr++, - &efuseData); - efuseTbl[addr + 1] = efuseData; - } - addr += 2; - } - } else { - DBG_8723A(KERN_ERR "%s: offset(%d) is illegal!!\n", - __func__, offset); - eFuse_Addr += Efuse_CalculateWordCnts23a(wden) * 2; - } - } - - /* Copy from Efuse map to output pointer memory!!! */ - for (i = 0; i < _size_byte; i++) - pbuf[i] = efuseTbl[_offset + i]; - - /* Calculate Efuse utilization */ - EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI, - TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &total); - used = eFuse_Addr - 1; - pHalData->EfuseUsedBytes = used; - - kfree(efuseTbl); -} - -static void -hal_ReadEFuse_BT(struct rtw_adapter *padapter, - u16 _offset, u16 _size_byte, u8 *pbuf) -{ - u8 *efuseTbl; - u8 bank; - u16 eFuse_Addr; - u8 efuseHeader, efuseExtHdr, efuseData; - u8 offset, wden; - u16 i, total, used; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - /* Do NOT excess total size of EFuse table. - Added by Roger, 2008.11.10. */ - if ((_offset + _size_byte) > EFUSE_BT_MAP_LEN) { - DBG_8723A("%s: Invalid offset(%#x) with read bytes(%#x)!!\n", - __func__, _offset, _size_byte); - return; - } - - efuseTbl = kmalloc(EFUSE_BT_MAP_LEN, GFP_KERNEL); - if (!efuseTbl) - return; - /* 0xff will be efuse default value instead of 0x00. */ - memset(efuseTbl, 0xFF, EFUSE_BT_MAP_LEN); - - EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT, - TYPE_AVAILABLE_EFUSE_BYTES_BANK, &total); - - for (bank = 1; bank < EFUSE_MAX_BANK; bank++) { - if (hal_EfuseSwitchToBank(padapter, bank) == false) { - DBG_8723A("%s: hal_EfuseSwitchToBank Fail!!\n", - __func__); - goto exit; - } - - eFuse_Addr = 0; - - while (AVAILABLE_EFUSE_ADDR(eFuse_Addr)) { - ReadEFuseByte23a(padapter, eFuse_Addr++, &efuseHeader); - if (efuseHeader == 0xFF) - break; - - /* Check PG header for section num. */ - if (EXT_HEADER(efuseHeader)) { /* extended header */ - offset = GET_HDR_OFFSET_2_0(efuseHeader); - - ReadEFuseByte23a(padapter, eFuse_Addr++, - &efuseExtHdr); - if (ALL_WORDS_DISABLED(efuseExtHdr)) - continue; - - offset |= ((efuseExtHdr & 0xF0) >> 1); - wden = efuseExtHdr & 0x0F; - } else { - offset = (efuseHeader >> 4) & 0x0f; - wden = efuseHeader & 0x0f; - } - - if (offset < EFUSE_BT_MAX_SECTION) { - u16 addr; - - /* Get word enable value from PG header */ - - addr = offset * PGPKT_DATA_SIZE; - for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { - /* Check word enable condition in - the section */ - if (!(wden & (0x01 << i))) { - ReadEFuseByte23a(padapter, - eFuse_Addr++, - &efuseData); - efuseTbl[addr] = efuseData; - - ReadEFuseByte23a(padapter, - eFuse_Addr++, - &efuseData); - efuseTbl[addr + 1] = efuseData; - } - addr += 2; - } - } else { - DBG_8723A(KERN_ERR - "%s: offset(%d) is illegal!!\n", - __func__, offset); - eFuse_Addr += Efuse_CalculateWordCnts23a(wden) * 2; - } - } - - if ((eFuse_Addr - 1) < total) { - DBG_8723A("%s: bank(%d) data end at %#x\n", - __func__, bank, eFuse_Addr - 1); - break; - } - } - - /* switch bank back to bank 0 for later BT and wifi use. */ - hal_EfuseSwitchToBank(padapter, 0); - - /* Copy from Efuse map to output pointer memory!!! */ - for (i = 0; i < _size_byte; i++) - pbuf[i] = efuseTbl[_offset + i]; - - /* */ - /* Calculate Efuse utilization. */ - /* */ - EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT, - TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &total); - used = (EFUSE_BT_REAL_BANK_CONTENT_LEN * (bank - 1)) + eFuse_Addr - 1; - pHalData->BTEfuseUsedBytes = used; - -exit: - kfree(efuseTbl); -} - -void -rtl8723a_readefuse(struct rtw_adapter *padapter, - u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf) -{ - if (efuseType == EFUSE_WIFI) - hal_ReadEFuse_WiFi(padapter, _offset, _size_byte, pbuf); - else - hal_ReadEFuse_BT(padapter, _offset, _size_byte, pbuf); -} - -u16 rtl8723a_EfuseGetCurrentSize_WiFi(struct rtw_adapter *padapter) -{ - u16 efuse_addr = 0; - u8 hoffset = 0, hworden = 0; - u8 efuse_data, word_cnts = 0; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - efuse_addr = pHalData->EfuseUsedBytes; - - DBG_8723A("%s: start_efuse_addr = 0x%X\n", __func__, efuse_addr); - - /* switch bank back to bank 0 for later BT and wifi use. */ - hal_EfuseSwitchToBank(padapter, 0); - - while (AVAILABLE_EFUSE_ADDR(efuse_addr)) { - if (efuse_OneByteRead23a(padapter, efuse_addr, &efuse_data) == - _FAIL) { - DBG_8723A(KERN_ERR "%s: efuse_OneByteRead23a Fail! " - "addr = 0x%X !!\n", __func__, efuse_addr); - break; - } - - if (efuse_data == 0xFF) - break; - - if (EXT_HEADER(efuse_data)) { - hoffset = GET_HDR_OFFSET_2_0(efuse_data); - efuse_addr++; - efuse_OneByteRead23a(padapter, efuse_addr, &efuse_data); - if (ALL_WORDS_DISABLED(efuse_data)) - continue; - - hoffset |= ((efuse_data & 0xF0) >> 1); - hworden = efuse_data & 0x0F; - } else { - hoffset = (efuse_data >> 4) & 0x0F; - hworden = efuse_data & 0x0F; - } - - word_cnts = Efuse_CalculateWordCnts23a(hworden); - efuse_addr += (word_cnts * 2) + 1; - } - - pHalData->EfuseUsedBytes = efuse_addr; - - DBG_8723A("%s: CurrentSize =%d\n", __func__, efuse_addr); - - return efuse_addr; -} - -u16 rtl8723a_EfuseGetCurrentSize_BT(struct rtw_adapter *padapter) -{ - u16 btusedbytes; - u16 efuse_addr; - u8 bank, startBank; - u8 hoffset = 0, hworden = 0; - u8 efuse_data, word_cnts = 0; - u16 retU2 = 0; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - btusedbytes = pHalData->BTEfuseUsedBytes; - - efuse_addr = (u16) ((btusedbytes % EFUSE_BT_REAL_BANK_CONTENT_LEN)); - startBank = (u8) (1 + (btusedbytes / EFUSE_BT_REAL_BANK_CONTENT_LEN)); - - DBG_8723A("%s: start from bank =%d addr = 0x%X\n", __func__, startBank, - efuse_addr); - - EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT, - TYPE_AVAILABLE_EFUSE_BYTES_BANK, &retU2); - - for (bank = startBank; bank < EFUSE_MAX_BANK; bank++) { - if (hal_EfuseSwitchToBank(padapter, bank) == false) { - DBG_8723A(KERN_ERR "%s: switch bank(%d) Fail!!\n", - __func__, bank); - bank = EFUSE_MAX_BANK; - break; - } - - /* only when bank is switched we have to reset - the efuse_addr. */ - if (bank != startBank) - efuse_addr = 0; - - while (AVAILABLE_EFUSE_ADDR(efuse_addr)) { - if (efuse_OneByteRead23a(padapter, efuse_addr, - &efuse_data) == _FAIL) { - DBG_8723A(KERN_ERR "%s: efuse_OneByteRead23a Fail!" - " addr = 0x%X !!\n", - __func__, efuse_addr); - bank = EFUSE_MAX_BANK; - break; - } - - if (efuse_data == 0xFF) - break; - - if (EXT_HEADER(efuse_data)) { - hoffset = GET_HDR_OFFSET_2_0(efuse_data); - efuse_addr++; - efuse_OneByteRead23a(padapter, efuse_addr, - &efuse_data); - if (ALL_WORDS_DISABLED(efuse_data)) { - efuse_addr++; - continue; - } - - hoffset |= ((efuse_data & 0xF0) >> 1); - hworden = efuse_data & 0x0F; - } else { - hoffset = (efuse_data >> 4) & 0x0F; - hworden = efuse_data & 0x0F; - } - word_cnts = Efuse_CalculateWordCnts23a(hworden); - /* read next header */ - efuse_addr += (word_cnts * 2) + 1; - } - - /* Check if we need to check next bank efuse */ - if (efuse_addr < retU2) - break; /* don't need to check next bank. */ - } - - retU2 = ((bank - 1) * EFUSE_BT_REAL_BANK_CONTENT_LEN) + efuse_addr; - pHalData->BTEfuseUsedBytes = retU2; - - DBG_8723A("%s: CurrentSize =%d\n", __func__, retU2); - return retU2; -} - -void rtl8723a_read_chip_version(struct rtw_adapter *padapter) -{ - u32 value32; - struct hal_version ChipVersion; - struct hal_data_8723a *pHalData; - - pHalData = GET_HAL_DATA(padapter); - - value32 = rtl8723au_read32(padapter, REG_SYS_CFG); - ChipVersion.ICType = CHIP_8723A; - ChipVersion.ChipType = ((value32 & RTL_ID) ? TEST_CHIP : NORMAL_CHIP); - pHalData->rf_type = RF_1T1R; - ChipVersion.VendorType = - ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : CHIP_VENDOR_TSMC); - ChipVersion.CUTVersion = (value32 & CHIP_VER_RTL_MASK) >> CHIP_VER_RTL_SHIFT; /* IC version (CUT) */ - - /* For regulator mode. by tynli. 2011.01.14 */ - pHalData->RegulatorMode = ((value32 & SPS_SEL) ? - RT_LDO_REGULATOR : RT_SWITCHING_REGULATOR); - - value32 = rtl8723au_read32(padapter, REG_GPIO_OUTSTS); - /* ROM code version. */ - ChipVersion.ROMVer = (value32 & RF_RL_ID) >> 20; - - /* For multi-function consideration. Added by Roger, 2010.10.06. */ - pHalData->MultiFunc = RT_MULTI_FUNC_NONE; - value32 = rtl8723au_read32(padapter, REG_MULTI_FUNC_CTRL); - pHalData->MultiFunc |= - ((value32 & WL_FUNC_EN) ? RT_MULTI_FUNC_WIFI : 0); - pHalData->MultiFunc |= ((value32 & BT_FUNC_EN) ? RT_MULTI_FUNC_BT : 0); - pHalData->MultiFunc |= - ((value32 & GPS_FUNC_EN) ? RT_MULTI_FUNC_GPS : 0); - pHalData->PolarityCtl = - ((value32 & WL_HWPDN_SL) ? RT_POLARITY_HIGH_ACT : - RT_POLARITY_LOW_ACT); - pHalData->VersionID = ChipVersion; - - MSG_8723A("RF_Type is %x!!\n", pHalData->rf_type); -} - -/* */ -/* */ -/* 20100209 Joseph: */ -/* This function is used only for 92C to set REG_BCN_CTRL(0x550) register. */ -/* We just reserve the value of the register in variable - pHalData->RegBcnCtrlVal and then operate */ -/* the value of the register via atomic operation. */ -/* This prevents from race condition when setting this register. */ -/* The value of pHalData->RegBcnCtrlVal is initialized in - HwConfigureRTL8192CE() function. */ -/* */ -void SetBcnCtrlReg23a(struct rtw_adapter *padapter, u8 SetBits, u8 ClearBits) -{ - u8 val8; - - val8 = rtl8723au_read8(padapter, REG_BCN_CTRL); - val8 |= SetBits; - val8 &= ~ClearBits; - - rtl8723au_write8(padapter, REG_BCN_CTRL, val8); -} - -void rtl8723a_InitBeaconParameters(struct rtw_adapter *padapter) -{ - rtl8723au_write16(padapter, REG_BCN_CTRL, 0x1010); - - /* TODO: Remove these magic number */ - rtl8723au_write16(padapter, REG_TBTT_PROHIBIT, 0x6404); /* ms */ - /* Firmware will control REG_DRVERLYINT when power saving is enable, */ - /* so don't set this register on STA mode. */ - if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == false) - rtl8723au_write8(padapter, REG_DRVERLYINT, - DRIVER_EARLY_INT_TIME); - /* 2ms */ - rtl8723au_write8(padapter, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME); - - /* Suggested by designer timchen. Change beacon AIFS to the - largest number beacause test chip does not contension before - sending beacon. by tynli. 2009.11.03 */ - rtl8723au_write16(padapter, REG_BCNTCFG, 0x660F); -} - -static void ResumeTxBeacon(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - /* 2010.03.01. Marked by tynli. No need to call workitem beacause - we record the value */ - /* which should be read from register to a global variable. */ - - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, "+ResumeTxBeacon\n"); - - pHalData->RegFwHwTxQCtrl |= BIT(6); - rtl8723au_write8(padapter, REG_FWHW_TXQ_CTRL + 2, - pHalData->RegFwHwTxQCtrl); - rtl8723au_write8(padapter, REG_TBTT_PROHIBIT + 1, 0xff); - pHalData->RegReg542 |= BIT(0); - rtl8723au_write8(padapter, REG_TBTT_PROHIBIT + 2, pHalData->RegReg542); -} - -static void StopTxBeacon(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - /* 2010.03.01. Marked by tynli. No need to call workitem beacause - we record the value */ - /* which should be read from register to a global variable. */ - - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, "+StopTxBeacon\n"); - - pHalData->RegFwHwTxQCtrl &= ~BIT(6); - rtl8723au_write8(padapter, REG_FWHW_TXQ_CTRL + 2, - pHalData->RegFwHwTxQCtrl); - rtl8723au_write8(padapter, REG_TBTT_PROHIBIT + 1, 0x64); - pHalData->RegReg542 &= ~BIT(0); - rtl8723au_write8(padapter, REG_TBTT_PROHIBIT + 2, pHalData->RegReg542); -} - -static void _BeaconFunctionEnable(struct rtw_adapter *padapter, u8 Enable, - u8 Linked) -{ - SetBcnCtrlReg23a(padapter, DIS_TSF_UDT | EN_BCN_FUNCTION | DIS_BCNQ_SUB, - 0); - rtl8723au_write8(padapter, REG_RD_CTRL + 1, 0x6F); -} - -void rtl8723a_SetBeaconRelatedRegisters(struct rtw_adapter *padapter) -{ - u32 value32; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - /* reset TSF, enable update TSF, correcting TSF On Beacon */ - - /* REG_BCN_INTERVAL */ - /* REG_BCNDMATIM */ - /* REG_ATIMWND */ - /* REG_TBTT_PROHIBIT */ - /* REG_DRVERLYINT */ - /* REG_BCN_MAX_ERR */ - /* REG_BCNTCFG (0x510) */ - /* REG_DUAL_TSF_RST */ - /* REG_BCN_CTRL (0x550) */ - - /* */ - /* ATIM window */ - /* */ - rtl8723au_write16(padapter, REG_ATIMWND, 2); - - /* */ - /* Beacon interval (in unit of TU). */ - /* */ - rtl8723au_write16(padapter, REG_BCN_INTERVAL, pmlmeinfo->bcn_interval); - - rtl8723a_InitBeaconParameters(padapter); - - rtl8723au_write8(padapter, REG_SLOT, 0x09); - - /* */ - /* Reset TSF Timer to zero, added by Roger. 2008.06.24 */ - /* */ - value32 = rtl8723au_read32(padapter, REG_TCR); - value32 &= ~TSFRST; - rtl8723au_write32(padapter, REG_TCR, value32); - - value32 |= TSFRST; - rtl8723au_write32(padapter, REG_TCR, value32); - - /* NOTE: Fix test chip's bug (about contention windows's randomness) */ - if (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE | - WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE) == true) { - rtl8723au_write8(padapter, REG_RXTSF_OFFSET_CCK, 0x50); - rtl8723au_write8(padapter, REG_RXTSF_OFFSET_OFDM, 0x50); - } - - _BeaconFunctionEnable(padapter, true, true); - - ResumeTxBeacon(padapter); - SetBcnCtrlReg23a(padapter, DIS_BCNQ_SUB, 0); -} - -void rtl8723a_SetHalODMVar(struct rtw_adapter *Adapter, - enum hal_odm_variable eVariable, - void *pValue1, bool bSet) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct dm_odm_t *podmpriv = &pHalData->odmpriv; - switch (eVariable) { - case HAL_ODM_STA_INFO: - { - struct sta_info *psta = (struct sta_info *)pValue1; - - if (bSet) { - DBG_8723A("Set STA_(%d) info\n", psta->mac_id); - ODM_CmnInfoPtrArrayHook23a(podmpriv, - ODM_CMNINFO_STA_STATUS, - psta->mac_id, psta); - } else { - DBG_8723A("Clean STA_(%d) info\n", psta->mac_id); - ODM_CmnInfoPtrArrayHook23a(podmpriv, - ODM_CMNINFO_STA_STATUS, - psta->mac_id, NULL); - } - } - break; - case HAL_ODM_P2P_STATE: - ODM_CmnInfoUpdate23a(podmpriv, ODM_CMNINFO_WIFI_DIRECT, bSet); - break; - case HAL_ODM_WIFI_DISPLAY_STATE: - ODM_CmnInfoUpdate23a(podmpriv, ODM_CMNINFO_WIFI_DISPLAY, bSet); - break; - default: - break; - } -} - -void rtl8723a_notch_filter(struct rtw_adapter *adapter, bool enable) -{ - if (enable) { - DBG_8723A("Enable notch filter\n"); - rtl8723au_write8(adapter, rOFDM0_RxDSP + 1, - rtl8723au_read8(adapter, rOFDM0_RxDSP + 1) | - BIT(1)); - } else { - DBG_8723A("Disable notch filter\n"); - rtl8723au_write8(adapter, rOFDM0_RxDSP + 1, - rtl8723au_read8(adapter, rOFDM0_RxDSP + 1) & - ~BIT(1)); - } -} - -bool c2h_id_filter_ccx_8723a(u8 id) -{ - bool ret = false; - if (id == C2H_CCX_TX_RPT) - ret = true; - - return ret; -} - -int c2h_handler_8723a(struct rtw_adapter *padapter, struct c2h_evt_hdr *c2h_evt) -{ - int ret = _SUCCESS; - u8 i = 0; - - if (c2h_evt == NULL) { - DBG_8723A("%s c2h_evt is NULL\n", __func__); - ret = _FAIL; - goto exit; - } - - switch (c2h_evt->id) { - case C2H_DBG: - RT_TRACE(_module_hal_init_c_, _drv_info_, - "C2HCommandHandler: %s\n", c2h_evt->payload); - break; - - case C2H_CCX_TX_RPT: - handle_txrpt_ccx_8723a(padapter, c2h_evt->payload); - break; - case C2H_EXT_RA_RPT: - break; - case C2H_HW_INFO_EXCH: - RT_TRACE(_module_hal_init_c_, _drv_info_, - "[BT], C2H_HW_INFO_EXCH\n"); - for (i = 0; i < c2h_evt->plen; i++) { - RT_TRACE(_module_hal_init_c_, _drv_info_, - "[BT], tmpBuf[%d]= 0x%x\n", i, - c2h_evt->payload[i]); - } - break; - - case C2H_C2H_H2C_TEST: - RT_TRACE(_module_hal_init_c_, _drv_info_, - "[BT], C2H_H2C_TEST\n"); - RT_TRACE(_module_hal_init_c_, _drv_info_, - "[BT], tmpBuf[0]/[1]/[2]/[3]/[4]= 0x%x/ 0x%x/ 0x%x/ 0x%x/ 0x%x\n", - c2h_evt->payload[0], - c2h_evt->payload[1], c2h_evt->payload[2], - c2h_evt->payload[3], c2h_evt->payload[4]); - break; - - case C2H_BT_INFO: - DBG_8723A("%s , Got C2H_BT_INFO \n", __func__); - rtl8723a_fw_c2h_BT_info(padapter, - c2h_evt->payload, c2h_evt->plen); - break; - - default: - ret = _FAIL; - break; - } - -exit: - return ret; -} - -void handle_txrpt_ccx_8723a(struct rtw_adapter *adapter, void *buf) -{ - struct txrpt_ccx_8723a *txrpt_ccx = buf; - struct submit_ctx *pack_tx_ops = &adapter->xmitpriv.ack_tx_ops; - - if (txrpt_ccx->int_ccx && adapter->xmitpriv.ack_tx) { - if (txrpt_ccx->pkt_ok) - rtw23a_sctx_done_err(&pack_tx_ops, - RTW_SCTX_DONE_SUCCESS); - else - rtw23a_sctx_done_err(&pack_tx_ops, - RTW_SCTX_DONE_CCX_PKT_FAIL); - } -} - -void rtl8723a_InitAntenna_Selection(struct rtw_adapter *padapter) -{ - u8 val; - - val = rtl8723au_read8(padapter, REG_LEDCFG2); - /* Let 8051 take control antenna setting */ - val |= BIT(7); /* DPDT_SEL_EN, 0x4C[23] */ - rtl8723au_write8(padapter, REG_LEDCFG2, val); -} - -void rtl8723a_CheckAntenna_Selection(struct rtw_adapter *padapter) -{ - u8 val; - - val = rtl8723au_read8(padapter, REG_LEDCFG2); - /* Let 8051 take control antenna setting */ - if (!(val & BIT(7))) { - val |= BIT(7); /* DPDT_SEL_EN, 0x4C[23] */ - rtl8723au_write8(padapter, REG_LEDCFG2, val); - } -} - -void rtl8723a_DeinitAntenna_Selection(struct rtw_adapter *padapter) -{ - u8 val; - - val = rtl8723au_read8(padapter, REG_LEDCFG2); - /* Let 8051 take control antenna setting */ - val &= ~BIT(7); /* DPDT_SEL_EN, clear 0x4C[23] */ - rtl8723au_write8(padapter, REG_LEDCFG2, val); -} - -void rtl8723a_init_default_value(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData; - struct dm_priv *pdmpriv; - u8 i; - - pHalData = GET_HAL_DATA(padapter); - pdmpriv = &pHalData->dmpriv; - - /* init default value */ - pHalData->bIQKInitialized = false; - if (!padapter->pwrctrlpriv.bkeepfwalive) - pHalData->LastHMEBoxNum = 0; - - pHalData->bIQKInitialized = false; - - /* init dm default value */ - pdmpriv->TM_Trigger = 0; /* for IQK */ -/* pdmpriv->binitialized = false; */ -/* pdmpriv->prv_traffic_idx = 3; */ -/* pdmpriv->initialize = 0; */ - - pdmpriv->ThermalValue_HP_index = 0; - for (i = 0; i < HP_THERMAL_NUM; i++) - pdmpriv->ThermalValue_HP[i] = 0; - - /* init Efuse variables */ - pHalData->EfuseUsedBytes = 0; - pHalData->BTEfuseUsedBytes = 0; -} - -u8 GetEEPROMSize8723A(struct rtw_adapter *padapter) -{ - u8 size = 0; - u32 cr; - - cr = rtl8723au_read16(padapter, REG_9346CR); - /* 6: EEPROM used is 93C46, 4: boot from E-Fuse. */ - size = (cr & BOOT_FROM_EEPROM) ? 6 : 4; - - MSG_8723A("EEPROM type is %s\n", size == 4 ? "E-FUSE" : "93C46"); - - return size; -} - -/* */ -/* */ -/* LLT R/W/Init function */ -/* */ -/* */ -static int _LLTWrite(struct rtw_adapter *padapter, u32 address, u32 data) -{ - int status = _SUCCESS; - s32 count = 0; - u32 value = _LLT_INIT_ADDR(address) | _LLT_INIT_DATA(data) | - _LLT_OP(_LLT_WRITE_ACCESS); - u16 LLTReg = REG_LLT_INIT; - - rtl8723au_write32(padapter, LLTReg, value); - - /* polling */ - do { - value = rtl8723au_read32(padapter, LLTReg); - if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) - 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; - } - } while (count++); - - return status; -} - -int InitLLTTable23a(struct rtw_adapter *padapter, u32 boundary) -{ - int status = _SUCCESS; - u32 i; - u32 txpktbuf_bndy = boundary; - u32 Last_Entry_Of_TxPktBuf = LAST_ENTRY_OF_TX_PKT_BUFFER; - - for (i = 0; i < (txpktbuf_bndy - 1); i++) { - status = _LLTWrite(padapter, i, i + 1); - if (status != _SUCCESS) - return status; - } - - /* end of list */ - status = _LLTWrite(padapter, (txpktbuf_bndy - 1), 0xFF); - if (status != _SUCCESS) - return status; - - /* Make the other pages as ring buffer */ - /* This ring buffer is used as beacon buffer if we config this - MAC as two MAC transfer. */ - /* Otherwise used as local loopback buffer. */ - for (i = txpktbuf_bndy; i < Last_Entry_Of_TxPktBuf; i++) { - status = _LLTWrite(padapter, i, (i + 1)); - if (_SUCCESS != status) - return status; - } - - /* Let last entry point to the start entry of ring buffer */ - status = _LLTWrite(padapter, Last_Entry_Of_TxPktBuf, txpktbuf_bndy); - - return status; -} - -static void _DisableGPIO(struct rtw_adapter *padapter) -{ -/*************************************** -j. GPIO_PIN_CTRL 0x44[31:0]= 0x000 -k.Value = GPIO_PIN_CTRL[7:0] -l. GPIO_PIN_CTRL 0x44[31:0] = 0x00FF0000 | (value <<8); write external PIN level -m. GPIO_MUXCFG 0x42 [15:0] = 0x0780 -n. LEDCFG 0x4C[15:0] = 0x8080 -***************************************/ - u32 value32; - u32 u4bTmp; - - /* 1. Disable GPIO[7:0] */ - rtl8723au_write16(padapter, REG_GPIO_PIN_CTRL + 2, 0x0000); - value32 = rtl8723au_read32(padapter, REG_GPIO_PIN_CTRL) & 0xFFFF00FF; - u4bTmp = value32 & 0x000000FF; - value32 |= ((u4bTmp << 8) | 0x00FF0000); - rtl8723au_write32(padapter, REG_GPIO_PIN_CTRL, value32); - - /* */ - /* <Roger_Notes> For RTL8723u multi-function configuration which - was autoload from Efuse offset 0x0a and 0x0b, */ - /* WLAN HW GPIO[9], GPS HW GPIO[10] and BT HW GPIO[11]. */ - /* Added by Roger, 2010.10.07. */ - /* */ - /* 2. Disable GPIO[8] and GPIO[12] */ - - /* Configure all pins as input mode. */ - rtl8723au_write16(padapter, REG_GPIO_IO_SEL_2, 0x0000); - value32 = rtl8723au_read32(padapter, REG_GPIO_PIN_CTRL_2) & 0xFFFF001F; - u4bTmp = value32 & 0x0000001F; - /* Set pin 8, 10, 11 and pin 12 to output mode. */ - value32 |= ((u4bTmp << 8) | 0x001D0000); - rtl8723au_write32(padapter, REG_GPIO_PIN_CTRL_2, value32); - - /* 3. Disable LED0 & 1 */ - rtl8723au_write16(padapter, REG_LEDCFG0, 0x8080); -} /* end of _DisableGPIO() */ - -static void _DisableRFAFEAndResetBB8192C(struct rtw_adapter *padapter) -{ -/************************************** -a. TXPAUSE 0x522[7:0] = 0xFF Pause MAC TX queue -b. RF path 0 offset 0x00 = 0x00 disable RF -c. APSD_CTRL 0x600[7:0] = 0x40 -d. SYS_FUNC_EN 0x02[7:0] = 0x16 reset BB state machine -e. SYS_FUNC_EN 0x02[7:0] = 0x14 reset BB state machine -***************************************/ - u8 value8; - - rtl8723au_write8(padapter, REG_TXPAUSE, 0xFF); - - PHY_SetRFReg(padapter, RF_PATH_A, 0x0, bMaskByte0, 0x0); - - value8 = APSDOFF; - rtl8723au_write8(padapter, REG_APSD_CTRL, value8); /* 0x40 */ - - /* Set BB reset at first */ - value8 = FEN_USBD | FEN_USBA | FEN_BB_GLB_RSTn; - rtl8723au_write8(padapter, REG_SYS_FUNC_EN, value8); /* 0x16 */ - - /* Set global reset. */ - value8 &= ~FEN_BB_GLB_RSTn; - rtl8723au_write8(padapter, REG_SYS_FUNC_EN, value8); /* 0x14 */ - - /* 2010/08/12 MH We need to set BB/GLBAL reset to save power - for SS mode. */ -} - -static void _ResetDigitalProcedure1_92C(struct rtw_adapter *padapter, - bool bWithoutHWSM) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (IS_FW_81xxC(padapter) && (pHalData->FirmwareVersion <= 0x20)) { - /***************************** - f. MCUFWDL 0x80[7:0]= 0 reset MCU ready status - g. SYS_FUNC_EN 0x02[10]= 0 reset MCU register, (8051 reset) - h. SYS_FUNC_EN 0x02[15-12]= 5 reset MAC register, DCORE - i. SYS_FUNC_EN 0x02[10]= 1 enable MCU register, - (8051 enable) - ******************************/ - u16 valu16; - rtl8723au_write8(padapter, REG_MCUFWDL, 0); - - valu16 = rtl8723au_read16(padapter, REG_SYS_FUNC_EN); - /* reset MCU , 8051 */ - rtl8723au_write16(padapter, REG_SYS_FUNC_EN, - valu16 & ~FEN_CPUEN); - - valu16 = rtl8723au_read16(padapter, REG_SYS_FUNC_EN) & 0x0FFF; - /* reset MAC */ - rtl8723au_write16(padapter, REG_SYS_FUNC_EN, - valu16 | FEN_HWPDN | FEN_ELDR); - - valu16 = rtl8723au_read16(padapter, REG_SYS_FUNC_EN); - /* enable MCU , 8051 */ - rtl8723au_write16(padapter, REG_SYS_FUNC_EN, - valu16 | FEN_CPUEN); - } else { - u8 retry_cnts = 0; - u8 val8; - - val8 = rtl8723au_read8(padapter, REG_MCUFWDL); - - /* 2010/08/12 MH For USB SS, we can not stop 8051 when we - are trying to enter IPS/HW&SW radio off. For - S3/S4/S5/Disable, we can stop 8051 because */ - /* we will init FW when power on again. */ - /* If we want to SS mode, we can not reset 8051. */ - if ((val8 & BIT(1)) && padapter->bFWReady) { - /* IF fw in RAM code, do reset */ - /* 2010/08/25 MH According to RD alfred's - suggestion, we need to disable other */ - /* HRCV INT to influence 8051 reset. */ - rtl8723au_write8(padapter, REG_FWIMR, 0x20); - /* 2011/02/15 MH According to Alex's - suggestion, close mask to prevent - incorrect FW write operation. */ - rtl8723au_write8(padapter, REG_FTIMR, 0x00); - rtl8723au_write8(padapter, REG_FSIMR, 0x00); - - /* 8051 reset by self */ - rtl8723au_write8(padapter, REG_HMETFR + 3, 0x20); - - while ((retry_cnts++ < 100) && - (rtl8723au_read16(padapter, REG_SYS_FUNC_EN) & - FEN_CPUEN)) { - udelay(50); /* us */ - } - - if (retry_cnts >= 100) { - /* Reset MAC and Enable 8051 */ - rtl8723au_write8(padapter, - REG_SYS_FUNC_EN + 1, 0x50); - mdelay(10); - } - } - /* Reset MAC and Enable 8051 */ - rtl8723au_write8(padapter, REG_SYS_FUNC_EN + 1, 0x54); - rtl8723au_write8(padapter, REG_MCUFWDL, 0); - } - - if (bWithoutHWSM) { - /***************************** - Without HW auto state machine - g. SYS_CLKR 0x08[15:0] = 0x30A3 disable MAC clock - h. AFE_PLL_CTRL 0x28[7:0] = 0x80 disable AFE PLL - i. AFE_XTAL_CTRL 0x24[15:0] = 0x880F gated AFE DIG_CLOCK - j. SYS_ISO_CTRL 0x00[7:0] = 0xF9 isolated digital to PON - ******************************/ - /* modify to 0x70A3 by Scott. */ - rtl8723au_write16(padapter, REG_SYS_CLKR, 0x70A3); - rtl8723au_write8(padapter, REG_AFE_PLL_CTRL, 0x80); - rtl8723au_write16(padapter, REG_AFE_XTAL_CTRL, 0x880F); - rtl8723au_write8(padapter, REG_SYS_ISO_CTRL, 0xF9); - } else { - /* Disable all RF/BB power */ - rtl8723au_write8(padapter, REG_RF_CTRL, 0x00); - } -} - -static void _ResetDigitalProcedure2(struct rtw_adapter *padapter) -{ -/***************************** -k. SYS_FUNC_EN 0x03[7:0] = 0x44 disable ELDR runction -l. SYS_CLKR 0x08[15:0] = 0x3083 disable ELDR clock -m. SYS_ISO_CTRL 0x01[7:0] = 0x83 isolated ELDR to PON -******************************/ - /* modify to 0x70a3 by Scott. */ - rtl8723au_write16(padapter, REG_SYS_CLKR, 0x70a3); - /* modify to 0x82 by Scott. */ - rtl8723au_write8(padapter, REG_SYS_ISO_CTRL + 1, 0x82); -} - -static void _DisableAnalog(struct rtw_adapter *padapter, bool bWithoutHWSM) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u16 value16; - u8 value8; - - if (bWithoutHWSM) { - /***************************** - n. LDOA15_CTRL 0x20[7:0] = 0x04 disable A15 power - o. LDOV12D_CTRL 0x21[7:0] = 0x54 disable digital core power - r. When driver call disable, the ASIC will turn off remaining - clock automatically - ******************************/ - - rtl8723au_write8(padapter, REG_LDOA15_CTRL, 0x04); - /* rtl8723au_write8(padapter, REG_LDOV12D_CTRL, 0x54); */ - - value8 = rtl8723au_read8(padapter, REG_LDOV12D_CTRL); - value8 &= ~LDV12_EN; - rtl8723au_write8(padapter, REG_LDOV12D_CTRL, value8); - } - - /***************************** - h. SPS0_CTRL 0x11[7:0] = 0x23 enter PFM mode - i. APS_FSMCO 0x04[15:0] = 0x4802 set USB suspend - ******************************/ - value8 = 0x23; - if (IS_81xxC_VENDOR_UMC_B_CUT(pHalData->VersionID)) - value8 |= BIT(3); - - rtl8723au_write8(padapter, REG_SPS0_CTRL, value8); - - if (bWithoutHWSM) { - /* value16 |= (APDM_HOST | FSM_HSUS |/PFM_ALDN); */ - /* 2010/08/31 According to Filen description, we need to - use HW to shut down 8051 automatically. */ - /* Because suspend operation need the asistance of 8051 - to wait for 3ms. */ - value16 = APDM_HOST | AFSM_HSUS | PFM_ALDN; - } else { - value16 = APDM_HOST | AFSM_HSUS | PFM_ALDN; - } - - rtl8723au_write16(padapter, REG_APS_FSMCO, value16); /* 0x4802 */ - - rtl8723au_write8(padapter, REG_RSV_CTRL, 0x0e); -} - -/* HW Auto state machine */ -int CardDisableHWSM(struct rtw_adapter *padapter, u8 resetMCU) -{ - if (padapter->bSurpriseRemoved) - return _SUCCESS; - - /* RF Off Sequence ==== */ - _DisableRFAFEAndResetBB8192C(padapter); - - /* ==== Reset digital sequence ====== */ - _ResetDigitalProcedure1_92C(padapter, false); - - /* ==== Pull GPIO PIN to balance level and LED control ====== */ - _DisableGPIO(padapter); - - /* ==== Disable analog sequence === */ - _DisableAnalog(padapter, false); - - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "======> Card disable finished.\n"); - - return _SUCCESS; -} - -/* without HW Auto state machine */ -int CardDisableWithoutHWSM(struct rtw_adapter *padapter) -{ - if (padapter->bSurpriseRemoved) - return _SUCCESS; - - /* RF Off Sequence ==== */ - _DisableRFAFEAndResetBB8192C(padapter); - - /* ==== Reset digital sequence ====== */ - _ResetDigitalProcedure1_92C(padapter, true); - - /* ==== Pull GPIO PIN to balance level and LED control ====== */ - _DisableGPIO(padapter); - - /* ==== Reset digital sequence ====== */ - _ResetDigitalProcedure2(padapter); - - /* ==== Disable analog sequence === */ - _DisableAnalog(padapter, true); - - return _SUCCESS; -} - -void Hal_InitPGData(struct rtw_adapter *padapter, u8 *PROMContent) -{ - struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter); - - if (!pEEPROM->bautoload_fail_flag) { /* autoload OK. */ - if (!pEEPROM->EepromOrEfuse) { - /* Read EFUSE real map to shadow. */ - EFUSE_ShadowMapUpdate23a(padapter, EFUSE_WIFI); - memcpy(PROMContent, pEEPROM->efuse_eeprom_data, - HWSET_MAX_SIZE); - } - } else { - RT_TRACE(_module_hci_hal_init_c_, _drv_notice_, - "AutoLoad Fail reported from CR9346!!\n"); - /* update to default value 0xFF */ - if (!pEEPROM->EepromOrEfuse) - EFUSE_ShadowMapUpdate23a(padapter, EFUSE_WIFI); - memcpy(PROMContent, pEEPROM->efuse_eeprom_data, - HWSET_MAX_SIZE); - } -} - -void Hal_EfuseParseIDCode(struct rtw_adapter *padapter, u8 *hwinfo) -{ - struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter); -/* struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); */ - u16 EEPROMId; - - /* Checl 0x8129 again for making sure autoload status!! */ - EEPROMId = le16_to_cpu(*((__le16 *) hwinfo)); - if (EEPROMId != RTL_EEPROM_ID) { - DBG_8723A("EEPROM ID(%#x) is invalid!!\n", EEPROMId); - pEEPROM->bautoload_fail_flag = true; - } else { - pEEPROM->bautoload_fail_flag = false; - } - - RT_TRACE(_module_hal_init_c_, _drv_info_, - "EEPROM ID = 0x%04x\n", EEPROMId); -} - -static void -Hal_ReadPowerValueFromPROM_8723A(struct txpowerinfo *pwrInfo, - u8 *PROMContent, bool AutoLoadFail) -{ - u32 rfPath, eeAddr, group, rfPathMax = 1; - - memset(pwrInfo, 0, sizeof(*pwrInfo)); - - if (AutoLoadFail) { - for (group = 0; group < MAX_CHNL_GROUP; group++) { - for (rfPath = 0; rfPath < rfPathMax; rfPath++) { - pwrInfo->CCKIndex[rfPath][group] = - EEPROM_Default_TxPowerLevel; - pwrInfo->HT40_1SIndex[rfPath][group] = - EEPROM_Default_TxPowerLevel; - pwrInfo->HT40_2SIndexDiff[rfPath][group] = - EEPROM_Default_HT40_2SDiff; - pwrInfo->HT20IndexDiff[rfPath][group] = - EEPROM_Default_HT20_Diff; - pwrInfo->OFDMIndexDiff[rfPath][group] = - EEPROM_Default_LegacyHTTxPowerDiff; - pwrInfo->HT40MaxOffset[rfPath][group] = - EEPROM_Default_HT40_PwrMaxOffset; - pwrInfo->HT20MaxOffset[rfPath][group] = - EEPROM_Default_HT20_PwrMaxOffset; - } - } - pwrInfo->TSSI_A[0] = EEPROM_Default_TSSI; - return; - } - - for (rfPath = 0; rfPath < rfPathMax; rfPath++) { - for (group = 0; group < MAX_CHNL_GROUP; group++) { - eeAddr = - EEPROM_CCK_TX_PWR_INX_8723A + (rfPath * 3) + group; - - pwrInfo->CCKIndex[rfPath][group] = PROMContent[eeAddr]; - if (pwrInfo->CCKIndex[rfPath][group] > 63) - pwrInfo->CCKIndex[rfPath][group] = - EEPROM_Default_TxPowerLevel; - - eeAddr = EEPROM_HT40_1S_TX_PWR_INX_8723A + - (rfPath * 3) + group; - pwrInfo->HT40_1SIndex[rfPath][group] = - PROMContent[eeAddr]; - if (pwrInfo->HT40_1SIndex[rfPath][group] > 63) - pwrInfo->HT40_1SIndex[rfPath][group] = - EEPROM_Default_TxPowerLevel; - } - } - - for (group = 0; group < MAX_CHNL_GROUP; group++) { - for (rfPath = 0; rfPath < rfPathMax; rfPath++) { - pwrInfo->HT40_2SIndexDiff[rfPath][group] = 0; - pwrInfo->HT20IndexDiff[rfPath][group] = - (PROMContent - [EEPROM_HT20_TX_PWR_INX_DIFF_8723A + - group] >> (rfPath * 4)) & 0xF; - /* 4bit sign number to 8 bit sign number */ - if (pwrInfo->HT20IndexDiff[rfPath][group] & BIT(3)) - pwrInfo->HT20IndexDiff[rfPath][group] |= 0xF0; - - pwrInfo->OFDMIndexDiff[rfPath][group] = - (PROMContent[EEPROM_OFDM_TX_PWR_INX_DIFF_8723A + - group] >> (rfPath * 4)) & 0xF; - - pwrInfo->HT40MaxOffset[rfPath][group] = - (PROMContent[EEPROM_HT40_MAX_PWR_OFFSET_8723A + - group] >> (rfPath * 4)) & 0xF; - - pwrInfo->HT20MaxOffset[rfPath][group] = - (PROMContent[EEPROM_HT20_MAX_PWR_OFFSET_8723A + - group] >> (rfPath * 4)) & 0xF; - } - } - - pwrInfo->TSSI_A[0] = PROMContent[EEPROM_TSSI_A_8723A]; -} - -static u8 Hal_GetChnlGroup(u8 chnl) -{ - u8 group = 0; - - if (chnl < 3) /* Cjanel 1-3 */ - group = 0; - else if (chnl < 9) /* Channel 4-9 */ - group = 1; - else /* Channel 10-14 */ - group = 2; - - return group; -} - -void -Hal_EfuseParsetxpowerinfo_8723A(struct rtw_adapter *padapter, - u8 *PROMContent, bool AutoLoadFail) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct txpowerinfo pwrInfo; - u8 rfPath, ch, group, rfPathMax = 1; - u8 pwr, diff; - - Hal_ReadPowerValueFromPROM_8723A(&pwrInfo, PROMContent, AutoLoadFail); - for (rfPath = 0; rfPath < rfPathMax; rfPath++) { - for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) { - group = Hal_GetChnlGroup(ch); - - pHalData->TxPwrLevelCck[rfPath][ch] = - pwrInfo.CCKIndex[rfPath][group]; - pHalData->TxPwrLevelHT40_1S[rfPath][ch] = - pwrInfo.HT40_1SIndex[rfPath][group]; - - pHalData->TxPwrHt20Diff[rfPath][ch] = - pwrInfo.HT20IndexDiff[rfPath][group]; - pHalData->TxPwrLegacyHtDiff[rfPath][ch] = - pwrInfo.OFDMIndexDiff[rfPath][group]; - pHalData->PwrGroupHT20[rfPath][ch] = - pwrInfo.HT20MaxOffset[rfPath][group]; - pHalData->PwrGroupHT40[rfPath][ch] = - pwrInfo.HT40MaxOffset[rfPath][group]; - - pwr = pwrInfo.HT40_1SIndex[rfPath][group]; - diff = pwrInfo.HT40_2SIndexDiff[rfPath][group]; - - pHalData->TxPwrLevelHT40_2S[rfPath][ch] = - (pwr > diff) ? (pwr - diff) : 0; - } - } - for (rfPath = 0; rfPath < RF_PATH_MAX; rfPath++) { - for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) { - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "RF(%u)-Ch(%u) [CCK / HT40_1S / HT40_2S] = [0x%x / 0x%x / 0x%x]\n", - rfPath, ch, - pHalData->TxPwrLevelCck[rfPath][ch], - pHalData->TxPwrLevelHT40_1S[rfPath][ch], - pHalData->TxPwrLevelHT40_2S[rfPath][ch]); - - } - } - for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) { - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "RF-A Ht20 to HT40 Diff[%u] = 0x%x(%d)\n", ch, - pHalData->TxPwrHt20Diff[RF_PATH_A][ch], - pHalData->TxPwrHt20Diff[RF_PATH_A][ch]); - } - for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "RF-A Legacy to Ht40 Diff[%u] = 0x%x\n", ch, - pHalData->TxPwrLegacyHtDiff[RF_PATH_A][ch]); - for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) { - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "RF-B Ht20 to HT40 Diff[%u] = 0x%x(%d)\n", ch, - pHalData->TxPwrHt20Diff[RF_PATH_B][ch], - pHalData->TxPwrHt20Diff[RF_PATH_B][ch]); - } - for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "RF-B Legacy to HT40 Diff[%u] = 0x%x\n", ch, - pHalData->TxPwrLegacyHtDiff[RF_PATH_B][ch]); - if (!AutoLoadFail) { - struct registry_priv *registry_par = &padapter->registrypriv; - if (registry_par->regulatory_tid == 0xff) { - if (PROMContent[RF_OPTION1_8723A] == 0xff) - pHalData->EEPROMRegulatory = 0; - else - pHalData->EEPROMRegulatory = - PROMContent[RF_OPTION1_8723A] & 0x7; - } else { - pHalData->EEPROMRegulatory = - registry_par->regulatory_tid; - } - } else { - pHalData->EEPROMRegulatory = 0; - } - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "EEPROMRegulatory = 0x%x\n", pHalData->EEPROMRegulatory); - - if (!AutoLoadFail) - pHalData->bTXPowerDataReadFromEEPORM = true; -} - -void -Hal_EfuseParseBTCoexistInfo_8723A(struct rtw_adapter *padapter, - u8 *hwinfo, bool AutoLoadFail) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - u8 tempval; - u32 tmpu4; - - if (!AutoLoadFail) { - tmpu4 = rtl8723au_read32(padapter, REG_MULTI_FUNC_CTRL); - if (tmpu4 & BT_FUNC_EN) - pHalData->EEPROMBluetoothCoexist = 1; - else - pHalData->EEPROMBluetoothCoexist = 0; - pHalData->EEPROMBluetoothType = BT_RTL8723A; - - /* The following need to be checked with newer version of */ - /* eeprom spec */ - tempval = hwinfo[RF_OPTION4_8723A]; - pHalData->EEPROMBluetoothAntNum = (tempval & 0x1); - pHalData->EEPROMBluetoothAntIsolation = (tempval & 0x10) >> 4; - pHalData->EEPROMBluetoothRadioShared = (tempval & 0x20) >> 5; - } else { - pHalData->EEPROMBluetoothCoexist = 0; - pHalData->EEPROMBluetoothType = BT_RTL8723A; - pHalData->EEPROMBluetoothAntNum = Ant_x2; - pHalData->EEPROMBluetoothAntIsolation = 0; - pHalData->EEPROMBluetoothRadioShared = BT_Radio_Shared; - } - - rtl8723a_BT_init_hal_vars(padapter); -} - -void -Hal_EfuseParseEEPROMVer(struct rtw_adapter *padapter, - u8 *hwinfo, bool AutoLoadFail) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (!AutoLoadFail) - pHalData->EEPROMVersion = hwinfo[EEPROM_VERSION_8723A]; - else - pHalData->EEPROMVersion = 1; - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "Hal_EfuseParseEEPROMVer(), EEVer = %d\n", - pHalData->EEPROMVersion); -} - -void -rtl8723a_EfuseParseChnlPlan(struct rtw_adapter *padapter, - u8 *hwinfo, bool AutoLoadFail) -{ - padapter->mlmepriv.ChannelPlan = - hal_com_get_channel_plan23a(padapter, hwinfo ? - hwinfo[EEPROM_ChannelPlan_8723A]:0xFF, - padapter->registrypriv.channel_plan, - RT_CHANNEL_DOMAIN_WORLD_WIDE_13, - AutoLoadFail); - - DBG_8723A("mlmepriv.ChannelPlan = 0x%02x\n", - padapter->mlmepriv.ChannelPlan); -} - -void -Hal_EfuseParseCustomerID(struct rtw_adapter *padapter, - u8 *hwinfo, bool AutoLoadFail) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - if (!AutoLoadFail) { - pHalData->EEPROMCustomerID = hwinfo[EEPROM_CustomID_8723A]; - pHalData->EEPROMSubCustomerID = - hwinfo[EEPROM_SubCustomID_8723A]; - } else { - pHalData->EEPROMCustomerID = 0; - pHalData->EEPROMSubCustomerID = 0; - } - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "EEPROM Customer ID: 0x%2x\n", pHalData->EEPROMCustomerID); - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "EEPROM SubCustomer ID: 0x%02x\n", - pHalData->EEPROMSubCustomerID); -} - -void -Hal_EfuseParseAntennaDiversity(struct rtw_adapter *padapter, - u8 *hwinfo, bool AutoLoadFail) -{ -} - -void -Hal_EfuseParseRateIndicationOption(struct rtw_adapter *padapter, - u8 *hwinfo, bool AutoLoadFail) -{ -} - -void -Hal_EfuseParseXtal_8723A(struct rtw_adapter *pAdapter, - u8 *hwinfo, u8 AutoLoadFail) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter); - - if (!AutoLoadFail) { - pHalData->CrystalCap = hwinfo[EEPROM_XTAL_K_8723A]; - if (pHalData->CrystalCap == 0xFF) - pHalData->CrystalCap = EEPROM_Default_CrystalCap_8723A; - } else { - pHalData->CrystalCap = EEPROM_Default_CrystalCap_8723A; - } - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "%s: CrystalCap = 0x%2x\n", __func__, - pHalData->CrystalCap); -} - -void -Hal_EfuseParseThermalMeter_8723A(struct rtw_adapter *padapter, - u8 *PROMContent, bool AutoloadFail) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - - /* */ - /* ThermalMeter from EEPROM */ - /* */ - if (!AutoloadFail) - pHalData->EEPROMThermalMeter = - PROMContent[EEPROM_THERMAL_METER_8723A]; - else - pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter; - - if ((pHalData->EEPROMThermalMeter == 0xff) || AutoloadFail) { - pHalData->bAPKThermalMeterIgnore = true; - pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter; - } - - DBG_8723A("%s: ThermalMeter = 0x%x\n", __func__, - pHalData->EEPROMThermalMeter); -} - -static void rtl8723a_cal_txdesc_chksum(struct tx_desc *ptxdesc) -{ - __le16 *usPtr = (__le16 *)ptxdesc; - u32 count = 16; /* (32 bytes / 2 bytes per XOR) => 16 times */ - u32 index; - u16 checksum = 0; - - /* Clear first */ - ptxdesc->txdw7 &= cpu_to_le32(0xffff0000); - - for (index = 0; index < count; index++) - checksum ^= le16_to_cpu(usPtr[index]); - - ptxdesc->txdw7 |= cpu_to_le32(checksum & 0x0000ffff); -} - -/* - * Description: In normal chip, we should send some packet to Hw which - * will be used by Fw in FW LPS mode. The function is to fill the Tx - * descriptor of this packets, then - */ -/* Fw can tell Hw to send these packet derectly. */ -/* Added by tynli. 2009.10.15. */ -/* */ -void rtl8723a_fill_fake_txdesc(struct rtw_adapter *padapter, u8 *pDesc, - u32 BufferLen, u8 IsPsPoll, u8 IsBTQosNull) -{ - struct tx_desc *ptxdesc; - - /* Clear all status */ - ptxdesc = (struct tx_desc *)pDesc; - memset(pDesc, 0, TXDESC_SIZE); - - /* offset 0 */ - /* own, bFirstSeg, bLastSeg; */ - ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG); - - /* 32 bytes for TX Desc */ - ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ) << - OFFSET_SHT) & 0x00ff0000); - - /* Buffer size + command header */ - ptxdesc->txdw0 |= cpu_to_le32(BufferLen & 0x0000ffff); - - /* offset 4 */ - /* Fixed queue of Mgnt queue */ - ptxdesc->txdw1 |= cpu_to_le32((QSLT_MGNT << QSEL_SHT) & 0x00001f00); - - /* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed - to error vlaue by Hw. */ - if (IsPsPoll) { - ptxdesc->txdw1 |= cpu_to_le32(NAVUSEHDR); - } else { - /* Hw set sequence number */ - ptxdesc->txdw4 |= cpu_to_le32(BIT(7)); - /* set bit3 to 1. Suugested by TimChen. 2009.12.29. */ - ptxdesc->txdw3 |= cpu_to_le32((8 << 28)); - } - - if (true == IsBTQosNull) - ptxdesc->txdw2 |= cpu_to_le32(BIT(23)); /* BT NULL */ - - /* offset 16 */ - ptxdesc->txdw4 |= cpu_to_le32(BIT(8)); /* driver uses rate */ - - /* USB interface drop packet if the checksum of descriptor isn't - correct. */ - /* Using this checksum can let hardware recovery from packet bulk - out error (e.g. Cancel URC, Bulk out error.). */ - rtl8723a_cal_txdesc_chksum(ptxdesc); -} - -void hw_var_set_opmode(struct rtw_adapter *padapter, u8 mode) -{ - u8 val8; - - if (mode == MSR_INFRA || mode == MSR_NOLINK) { - StopTxBeacon(padapter); - - /* disable atim wnd */ - val8 = DIS_TSF_UDT | EN_BCN_FUNCTION | DIS_ATIM; - SetBcnCtrlReg23a(padapter, val8, ~val8); - } else if (mode == MSR_ADHOC) { - ResumeTxBeacon(padapter); - - val8 = DIS_TSF_UDT | EN_BCN_FUNCTION | DIS_BCNQ_SUB; - SetBcnCtrlReg23a(padapter, val8, ~val8); - } else if (mode == MSR_AP) { - /* add NULL Data and BT NULL Data Packets to FW RSVD Page */ - rtl8723a_set_BTCoex_AP_mode_FwRsvdPkt_cmd(padapter); - - ResumeTxBeacon(padapter); - - val8 = DIS_TSF_UDT | DIS_BCNQ_SUB; - SetBcnCtrlReg23a(padapter, val8, ~val8); - - /* Set RCR */ - /* rtl8723au_write32(padapter, REG_RCR, 0x70002a8e); - CBSSID_DATA must set to 0 */ - /* CBSSID_DATA must set to 0 */ - rtl8723au_write32(padapter, REG_RCR, 0x7000228e); - /* enable to rx data frame */ - rtl8723au_write16(padapter, REG_RXFLTMAP2, 0xFFFF); - /* enable to rx ps-poll */ - rtl8723au_write16(padapter, REG_RXFLTMAP1, 0x0400); - - /* Beacon Control related register for first time */ - /* 2ms */ - rtl8723au_write8(padapter, REG_BCNDMATIM, 0x02); - /* 5ms */ - rtl8723au_write8(padapter, REG_DRVERLYINT, 0x05); - /* 10ms for port0 */ - rtl8723au_write8(padapter, REG_ATIMWND, 0x0a); - rtl8723au_write16(padapter, REG_BCNTCFG, 0x00); - rtl8723au_write16(padapter, REG_TBTT_PROHIBIT, 0xff04); - /* +32767 (~32ms) */ - rtl8723au_write16(padapter, REG_TSFTR_SYN_OFFSET, 0x7fff); - - /* reset TSF */ - rtl8723au_write8(padapter, REG_DUAL_TSF_RST, BIT(0)); - - /* enable BCN Function */ - /* don't enable update TSF (due to TSF update when - beacon/probe rsp are received) */ - val8 = DIS_TSF_UDT | EN_BCN_FUNCTION | - EN_TXBCN_RPT | DIS_BCNQ_SUB; - SetBcnCtrlReg23a(padapter, val8, ~val8); - } - - val8 = rtl8723au_read8(padapter, MSR); - val8 = (val8 & 0xC) | mode; - rtl8723au_write8(padapter, MSR, val8); -} - -void hw_var_set_macaddr(struct rtw_adapter *padapter, u8 *val) -{ - u8 idx = 0; - u32 reg_macid; - - reg_macid = REG_MACID; - - for (idx = 0; idx < 6; idx++) - rtl8723au_write8(padapter, (reg_macid + idx), val[idx]); -} - -void hw_var_set_bssid(struct rtw_adapter *padapter, u8 *val) -{ - u8 idx = 0; - u32 reg_bssid; - - reg_bssid = REG_BSSID; - - for (idx = 0; idx < 6; idx++) - rtl8723au_write8(padapter, (reg_bssid + idx), val[idx]); -} - -void hw_var_set_correct_tsf(struct rtw_adapter *padapter) -{ - u64 tsf; - u32 reg_tsftr; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - /* tsf = pmlmeext->TSFValue - ((u32)pmlmeext->TSFValue % - (pmlmeinfo->bcn_interval*1024)) - 1024; us */ - tsf = pmlmeext->TSFValue - - do_div(pmlmeext->TSFValue, - (pmlmeinfo->bcn_interval * 1024)) - 1024; /* us */ - - if (((pmlmeinfo->state & 0x03) == MSR_ADHOC) || - ((pmlmeinfo->state & 0x03) == MSR_AP)) { - /* pHalData->RegTxPause |= STOP_BCNQ;BIT(6) */ - /* rtl8723au_write8(padapter, REG_TXPAUSE, - (rtl8723au_read8(Adapter, REG_TXPAUSE)|BIT(6))); */ - StopTxBeacon(padapter); - } - - reg_tsftr = REG_TSFTR; - - /* disable related TSF function */ - SetBcnCtrlReg23a(padapter, 0, EN_BCN_FUNCTION); - - rtl8723au_write32(padapter, reg_tsftr, tsf); - rtl8723au_write32(padapter, reg_tsftr + 4, tsf >> 32); - - /* enable related TSF function */ - SetBcnCtrlReg23a(padapter, EN_BCN_FUNCTION, 0); - - if (((pmlmeinfo->state & 0x03) == MSR_ADHOC) || - ((pmlmeinfo->state & 0x03) == MSR_AP)) - ResumeTxBeacon(padapter); -} - -void hw_var_set_mlme_disconnect(struct rtw_adapter *padapter) -{ - /* reject all data frames */ - rtl8723au_write16(padapter, REG_RXFLTMAP2, 0); - - /* reset TSF */ - rtl8723au_write8(padapter, REG_DUAL_TSF_RST, BIT(0)); - - /* disable update TSF */ - SetBcnCtrlReg23a(padapter, DIS_TSF_UDT, 0); -} - -void hw_var_set_mlme_join(struct rtw_adapter *padapter, u8 type) -{ - u8 RetryLimit = 0x30; - - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (type == 0) { /* prepare to join */ - u32 v32; - - /* enable to rx data frame.Accept all data frame */ - /* rtl8723au_write32(padapter, REG_RCR, - rtl8723au_read32(padapter, REG_RCR)|RCR_ADF); */ - rtl8723au_write16(padapter, REG_RXFLTMAP2, 0xFFFF); - - v32 = rtl8723au_read32(padapter, REG_RCR); - v32 |= RCR_CBSSID_DATA | RCR_CBSSID_BCN; - rtl8723au_write32(padapter, REG_RCR, v32); - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) - RetryLimit = - (pHalData->CustomerID == RT_CID_CCX) ? 7 : 48; - else /* Ad-hoc Mode */ - RetryLimit = 0x7; - } else if (type == 1) { /* joinbss_event callback when join res < 0 */ - /* config RCR to receive different BSSID & not to - receive data frame during linking */ - rtl8723au_write16(padapter, REG_RXFLTMAP2, 0); - } else if (type == 2) { /* sta add event callback */ - /* enable update TSF */ - SetBcnCtrlReg23a(padapter, 0, DIS_TSF_UDT); - - if (check_fwstate(pmlmepriv, - WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)) { - /* fixed beacon issue for 8191su........... */ - rtl8723au_write8(padapter, 0x542, 0x02); - RetryLimit = 0x7; - } - } - - rtl8723au_write16(padapter, REG_RL, - RetryLimit << RETRY_LIMIT_SHORT_SHIFT | RetryLimit << - RETRY_LIMIT_LONG_SHIFT); - - switch (type) { - case 0: - /* prepare to join */ - rtl8723a_BT_wifiassociate_notify(padapter, true); - break; - case 1: - /* joinbss_event callback when join res < 0 */ - rtl8723a_BT_wifiassociate_notify(padapter, false); - break; - case 2: - /* sta add event callback */ -/* BT_WifiMediaStatusNotify(padapter, RT_MEDIA_CONNECT); */ - break; - } -} diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c b/drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c deleted file mode 100644 index 06a6c3e..0000000 --- a/drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c +++ /dev/null @@ -1,961 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RTL8723A_PHYCFG_C_ - -#include <osdep_service.h> -#include <drv_types.h> - -#include <rtl8723a_hal.h> -#include <usb_ops_linux.h> - -/*---------------------------Define Local Constant---------------------------*/ -/* Channel switch:The size of command tables for switch channel*/ -#define MAX_PRECMD_CNT 16 -#define MAX_RFDEPENDCMD_CNT 16 -#define MAX_POSTCMD_CNT 16 - -#define MAX_DOZE_WAITING_TIMES_9x 64 - -/*---------------------------Define Local Constant---------------------------*/ - -/*------------------------Define global variable-----------------------------*/ - -/*------------------------Define local variable------------------------------*/ - -/*--------------------Define export function prototype-----------------------*/ -/* Please refer to header file */ -/*--------------------Define export function prototype-----------------------*/ - -/*----------------------------Function Body----------------------------------*/ -/* */ -/* 1. BB register R/W API */ -/* */ - -/** -* Function: phy_CalculateBitShift -* -* OverView: Get shifted position of the BitMask -* -* Input: -* u32 BitMask, -* -* Output: none -* Return: u32 Return the shift bit bit position of the mask -*/ -static u32 phy_CalculateBitShift(u32 BitMask) -{ - u32 i; - - for (i = 0; i <= 31; i++) { - if (((BitMask>>i) & 0x1) == 1) - break; - } - - return i; -} - -/** -* Function: PHY_QueryBBReg -* -* OverView: Read "sepcific bits" from BB register -* -* Input: -* struct rtw_adapter * Adapter, -* u32 RegAddr, Target address to be readback -* u32 BitMask Target bit position in the -* target address to be readback -* Output: -* None -* Return: -* u32 Data The readback register value -* Note: -* This function is equal to "GetRegSetting" in PHY programming guide -*/ -u32 -PHY_QueryBBReg(struct rtw_adapter *Adapter, u32 RegAddr, u32 BitMask) -{ - u32 ReturnValue = 0, OriginalValue, BitShift; - - OriginalValue = rtl8723au_read32(Adapter, RegAddr); - BitShift = phy_CalculateBitShift(BitMask); - ReturnValue = (OriginalValue & BitMask) >> BitShift; - return ReturnValue; -} - -/** -* Function: PHY_SetBBReg -* -* OverView: Write "Specific bits" to BB register (page 8~) -* -* Input: -* struct rtw_adapter * Adapter, -* u32 RegAddr, Target address to be modified -* u32 BitMask Target bit position in the -* target address to be modified -* u32 Data The new register value in the -* target bit position of the -* target address -* -* Output: -* None -* Return: -* None -* Note: -* This function is equal to "PutRegSetting" in PHY programming guide -*/ - -void -PHY_SetBBReg(struct rtw_adapter *Adapter, u32 RegAddr, u32 BitMask, u32 Data) -{ - u32 OriginalValue, BitShift; - - if (BitMask != bMaskDWord) {/* if not "double word" write */ - OriginalValue = rtl8723au_read32(Adapter, RegAddr); - BitShift = phy_CalculateBitShift(BitMask); - Data = (OriginalValue & (~BitMask)) | (Data << BitShift); - } - - rtl8723au_write32(Adapter, RegAddr, Data); - - /* RTPRINT(FPHY, PHY_BBW, ("BBW MASK = 0x%lx Addr[0x%lx]= 0x%lx\n", BitMask, RegAddr, Data)); */ -} - -/* */ -/* 2. RF register R/W API */ -/* */ - -/** -* Function: phy_RFSerialRead -* -* OverView: Read regster from RF chips -* -* Input: -* struct rtw_adapter * Adapter, -* enum RF_RADIO_PATH eRFPath, Radio path of A/B/C/D -* u32 Offset, The target address to be read -* -* Output: None -* Return: u32 reback value -* Note: Threre are three types of serial operations: -* 1. Software serial write -* 2. Hardware LSSI-Low Speed Serial Interface -* 3. Hardware HSSI-High speed -* serial write. Driver need to implement (1) and (2). -* This function is equal to the combination of RF_ReadReg() and -* RFLSSIRead() -*/ -static u32 -phy_RFSerialRead(struct rtw_adapter *Adapter, enum RF_RADIO_PATH eRFPath, - u32 Offset) -{ - u32 retValue = 0; - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct bb_reg_define *pPhyReg = &pHalData->PHYRegDef[eRFPath]; - u32 NewOffset; - u32 tmplong, tmplong2; - u8 RfPiEnable = 0; - /* */ - /* Make sure RF register offset is correct */ - /* */ - Offset &= 0x3f; - - /* */ - /* Switch page for 8256 RF IC */ - /* */ - NewOffset = Offset; - - /* 2009/06/17 MH We can not execute IO for power save or - other accident mode. */ - /* if (RT_CANNOT_IO(Adapter)) */ - /* */ - /* RTPRINT(FPHY, PHY_RFR, ("phy_RFSerialRead return all one\n")); */ - /* return 0xFFFFFFFF; */ - /* */ - - /* For 92S LSSI Read RFLSSIRead */ - /* For RF A/B write 0x824/82c(does not work in the future) */ - /* We must use 0x824 for RF A and B to execute read trigger */ - tmplong = rtl8723au_read32(Adapter, rFPGA0_XA_HSSIParameter2); - if (eRFPath == RF_PATH_A) - tmplong2 = tmplong; - else - tmplong2 = rtl8723au_read32(Adapter, pPhyReg->rfHSSIPara2); - - tmplong2 = (tmplong2 & ~bLSSIReadAddress) | - (NewOffset << 23) | bLSSIReadEdge; /* T65 RF */ - - rtl8723au_write32(Adapter, rFPGA0_XA_HSSIParameter2, - tmplong & (~bLSSIReadEdge)); - udelay(10);/* PlatformStallExecution(10); */ - - rtl8723au_write32(Adapter, pPhyReg->rfHSSIPara2, tmplong2); - udelay(100);/* PlatformStallExecution(100); */ - - rtl8723au_write32(Adapter, rFPGA0_XA_HSSIParameter2, - tmplong | bLSSIReadEdge); - udelay(10);/* PlatformStallExecution(10); */ - - if (eRFPath == RF_PATH_A) - RfPiEnable = (u8)PHY_QueryBBReg(Adapter, - rFPGA0_XA_HSSIParameter1, - BIT(8)); - else if (eRFPath == RF_PATH_B) - RfPiEnable = (u8)PHY_QueryBBReg(Adapter, - rFPGA0_XB_HSSIParameter1, - BIT(8)); - - if (RfPiEnable) { - /* Read from BBreg8b8, 12 bits for 8190, 20bits for T65 RF */ - retValue = PHY_QueryBBReg(Adapter, pPhyReg->rfLSSIReadBackPi, - bLSSIReadBackData); - /* DBG_8723A("Readback from RF-PI : 0x%x\n", retValue); */ - } else { - /* Read from BBreg8a0, 12 bits for 8190, 20 bits for T65 RF */ - retValue = PHY_QueryBBReg(Adapter, pPhyReg->rfLSSIReadBack, - bLSSIReadBackData); - /* DBG_8723A("Readback from RF-SI : 0x%x\n", retValue); */ - } - /* DBG_8723A("RFR-%d Addr[0x%x]= 0x%x\n", eRFPath, pPhyReg->rfLSSIReadBack, retValue); */ - - return retValue; -} - -/** -* Function: phy_RFSerialWrite -* -* OverView: Write data to RF register (page 8~) -* -* Input: -* struct rtw_adapter * Adapter, -* enum RF_RADIO_PATH eRFPath, Radio path of A/B/C/D -* u32 Offset, The target address to be read -* u32 Data The new register Data in the target -* bit position of the target to be read -* -* Output: -* None -* Return: -* None -* Note: -* Threre are three types of serial operations: -* 1. Software serial write -* 2. Hardware LSSI-Low Speed Serial Interface -* 3. Hardware HSSI-High speed -* serial write. Driver need to implement (1) and (2). -* This function is equal to the combination of RF_ReadReg() and -* RFLSSIRead() -* -* Note: For RF8256 only -* The total count of RTL8256(Zebra4) register is around 36 bit it only employs -* 4-bit RF address. RTL8256 uses "register mode control bit" -* (Reg00[12], Reg00[10]) to access register address bigger than 0xf. -* See "Appendix-4 in PHY Configuration programming guide" for more details. -* Thus, we define a sub-finction for RTL8526 register address conversion -* =========================================================== -* Register Mode: RegCTL[1] RegCTL[0] Note -* (Reg00[12]) (Reg00[10]) -* =========================================================== -* Reg_Mode0 0 x Reg 0 ~15(0x0 ~ 0xf) -* ------------------------------------------------------------------ -* Reg_Mode1 1 0 Reg 16 ~30(0x1 ~ 0xf) -* ------------------------------------------------------------------ -* Reg_Mode2 1 1 Reg 31 ~ 45(0x1 ~ 0xf) -* ------------------------------------------------------------------ -* -* 2008/09/02 MH Add 92S RF definition -*/ -static void -phy_RFSerialWrite(struct rtw_adapter *Adapter, enum RF_RADIO_PATH eRFPath, - u32 Offset, u32 Data) -{ - u32 DataAndAddr = 0; - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct bb_reg_define *pPhyReg = &pHalData->PHYRegDef[eRFPath]; - u32 NewOffset; - - /* 2009/06/17 MH We can not execute IO for power save or - other accident mode. */ - /* if (RT_CANNOT_IO(Adapter)) */ - /* */ - /* RTPRINT(FPHY, PHY_RFW, ("phy_RFSerialWrite stop\n")); */ - /* return; */ - /* */ - - Offset &= 0x3f; - - /* */ - /* Shadow Update */ - /* */ - /* PHY_RFShadowWrite(Adapter, eRFPath, Offset, Data); */ - - /* */ - /* Switch page for 8256 RF IC */ - /* */ - NewOffset = Offset; - - /* */ - /* Put write addr in [5:0] and write data in [31:16] */ - /* */ - /* DataAndAddr = (Data<<16) | (NewOffset&0x3f); */ - /* T65 RF */ - DataAndAddr = ((NewOffset<<20) | (Data&0x000fffff)) & 0x0fffffff; - - /* */ - /* Write Operation */ - /* */ - rtl8723au_write32(Adapter, pPhyReg->rf3wireOffset, DataAndAddr); -} - -/** -* Function: PHY_QueryRFReg -* -* OverView: Query "Specific bits" to RF register (page 8~) -* -* Input: -* struct rtw_adapter * Adapter, -* enum RF_RADIO_PATH eRFPath, Radio path of A/B/C/D -* u32 RegAddr, The target address to be read -* u32BitMask The target bit position in the target -* address to be read -* -* Output: -* None -* Return: -* u32 Readback value -* Note: -* This function is equal to "GetRFRegSetting" in PHY programming guide -*/ -u32 -PHY_QueryRFReg(struct rtw_adapter *Adapter, enum RF_RADIO_PATH eRFPath, - u32 RegAddr, u32 BitMask) -{ - u32 Original_Value, Readback_Value, BitShift; - /* struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); */ - /* u8 RFWaitCounter = 0; */ - /* _irqL irqL; */ - - Original_Value = phy_RFSerialRead(Adapter, eRFPath, RegAddr); - - BitShift = phy_CalculateBitShift(BitMask); - Readback_Value = (Original_Value & BitMask) >> BitShift; - - return Readback_Value; -} - -/** -* Function: PHY_SetRFReg -* -* OverView: Write "Specific bits" to RF register (page 8~) -* -* Input: -* struct rtw_adapter * Adapter, -* enum RF_RADIO_PATH eRFPath, Radio path of A/B/C/D -* u32 RegAddr, The target address to be modified -* u32 BitMask The target bit position in the target -* address to be modified -* u32 Data The new register Data in the target -* bit position of the target address -* -* Output: -* None -* Return: -* None -* Note: This function is equal to "PutRFRegSetting" in PHY programming guide -*/ -void -PHY_SetRFReg(struct rtw_adapter *Adapter, enum RF_RADIO_PATH eRFPath, - u32 RegAddr, u32 BitMask, u32 Data) -{ - /* struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); */ - /* u8 RFWaitCounter = 0; */ - u32 Original_Value, BitShift; - - /* RF data is 12 bits only */ - if (BitMask != bRFRegOffsetMask) { - Original_Value = phy_RFSerialRead(Adapter, eRFPath, RegAddr); - BitShift = phy_CalculateBitShift(BitMask); - Data = (Original_Value & (~BitMask)) | (Data << BitShift); - } - - phy_RFSerialWrite(Adapter, eRFPath, RegAddr, Data); -} - -/* 3. Initial MAC/BB/RF config by reading MAC/BB/RF txt. */ - -/*----------------------------------------------------------------------------- - * Function: PHY_MACConfig8723A - * - * Overview: Condig MAC by header file or parameter file. - * - * Input: NONE - * - * Output: NONE - * - * Return: NONE - * - * Revised History: - * When Who Remark - * 08/12/2008 MHC Create Version 0. - * - *---------------------------------------------------------------------------*/ -int PHY_MACConfig8723A(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - - /* */ - /* Config MAC */ - /* */ - ODM_ReadAndConfig_MAC_REG_8723A(&pHalData->odmpriv); - - /* 2010.07.13 AMPDU aggregation number 9 */ - rtl8723au_write8(Adapter, REG_MAX_AGGR_NUM, 0x0A); - if (pHalData->rf_type == RF_2T2R && - BOARD_USB_DONGLE == pHalData->BoardType) - rtl8723au_write8(Adapter, 0x40, 0x04); - - return _SUCCESS; -} - -/** -* Function: phy_InitBBRFRegisterDefinition -* -* OverView: Initialize Register definition offset for Radio Path A/B/C/D -* -* Input: -* struct rtw_adapter * Adapter, -* -* Output: None -* Return: None -* Note: -* The initialization value is constant and it should never be changes -*/ -static void -phy_InitBBRFRegisterDefinition(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - - /* RF Interface Sowrtware Control */ - /* 16 LSBs if read 32-bit from 0x870 */ - pHalData->PHYRegDef[RF_PATH_A].rfintfs = rFPGA0_XAB_RFInterfaceSW; - /* 16 MSBs if read 32-bit from 0x870 (16-bit for 0x872) */ - pHalData->PHYRegDef[RF_PATH_B].rfintfs = rFPGA0_XAB_RFInterfaceSW; - - /* RF Interface Readback Value */ - /* 16 LSBs if read 32-bit from 0x8E0 */ - pHalData->PHYRegDef[RF_PATH_A].rfintfi = rFPGA0_XAB_RFInterfaceRB; - /* 16 MSBs if read 32-bit from 0x8E0 (16-bit for 0x8E2) */ - pHalData->PHYRegDef[RF_PATH_B].rfintfi = rFPGA0_XAB_RFInterfaceRB; - - /* RF Interface Output (and Enable) */ - /* 16 LSBs if read 32-bit from 0x860 */ - pHalData->PHYRegDef[RF_PATH_A].rfintfo = rFPGA0_XA_RFInterfaceOE; - /* 16 LSBs if read 32-bit from 0x864 */ - pHalData->PHYRegDef[RF_PATH_B].rfintfo = rFPGA0_XB_RFInterfaceOE; - - /* RF Interface (Output and) Enable */ - /* 16 MSBs if read 32-bit from 0x860 (16-bit for 0x862) */ - pHalData->PHYRegDef[RF_PATH_A].rfintfe = rFPGA0_XA_RFInterfaceOE; - /* 16 MSBs if read 32-bit from 0x864 (16-bit for 0x866) */ - pHalData->PHYRegDef[RF_PATH_B].rfintfe = rFPGA0_XB_RFInterfaceOE; - - /* Addr of LSSI. Wirte RF register by driver */ - pHalData->PHYRegDef[RF_PATH_A].rf3wireOffset = rFPGA0_XA_LSSIParameter; - pHalData->PHYRegDef[RF_PATH_B].rf3wireOffset = rFPGA0_XB_LSSIParameter; - - /* RF parameter */ - /* BB Band Select */ - pHalData->PHYRegDef[RF_PATH_A].rfLSSI_Select = rFPGA0_XAB_RFParameter; - pHalData->PHYRegDef[RF_PATH_B].rfLSSI_Select = rFPGA0_XAB_RFParameter; - - /* Tx AGC Gain Stage (same for all path. Should we remove this?) */ - pHalData->PHYRegDef[RF_PATH_A].rfTxGainStage = rFPGA0_TxGainStage; - pHalData->PHYRegDef[RF_PATH_B].rfTxGainStage = rFPGA0_TxGainStage; - - /* Tranceiver A~D HSSI Parameter-1 */ - /* wire control parameter1 */ - pHalData->PHYRegDef[RF_PATH_A].rfHSSIPara1 = rFPGA0_XA_HSSIParameter1; - /* wire control parameter1 */ - pHalData->PHYRegDef[RF_PATH_B].rfHSSIPara1 = rFPGA0_XB_HSSIParameter1; - - /* Tranceiver A~D HSSI Parameter-2 */ - /* wire control parameter2 */ - pHalData->PHYRegDef[RF_PATH_A].rfHSSIPara2 = rFPGA0_XA_HSSIParameter2; - /* wire control parameter2 */ - pHalData->PHYRegDef[RF_PATH_B].rfHSSIPara2 = rFPGA0_XB_HSSIParameter2; - - /* RF switch Control */ - pHalData->PHYRegDef[RF_PATH_A].rfSwitchControl = - rFPGA0_XAB_SwitchControl; /* TR/Ant switch control */ - pHalData->PHYRegDef[RF_PATH_B].rfSwitchControl = - rFPGA0_XAB_SwitchControl; - - /* AGC control 1 */ - pHalData->PHYRegDef[RF_PATH_A].rfAGCControl1 = rOFDM0_XAAGCCore1; - pHalData->PHYRegDef[RF_PATH_B].rfAGCControl1 = rOFDM0_XBAGCCore1; - - /* AGC control 2 */ - pHalData->PHYRegDef[RF_PATH_A].rfAGCControl2 = rOFDM0_XAAGCCore2; - pHalData->PHYRegDef[RF_PATH_B].rfAGCControl2 = rOFDM0_XBAGCCore2; - - /* RX AFE control 1 */ - pHalData->PHYRegDef[RF_PATH_A].rfRxIQImbalance = rOFDM0_XARxIQImbalance; - pHalData->PHYRegDef[RF_PATH_B].rfRxIQImbalance = rOFDM0_XBRxIQImbalance; - - /* RX AFE control 1 */ - pHalData->PHYRegDef[RF_PATH_A].rfRxAFE = rOFDM0_XARxAFE; - pHalData->PHYRegDef[RF_PATH_B].rfRxAFE = rOFDM0_XBRxAFE; - - /* Tx AFE control 1 */ - pHalData->PHYRegDef[RF_PATH_A].rfTxIQImbalance = rOFDM0_XATxIQImbalance; - pHalData->PHYRegDef[RF_PATH_B].rfTxIQImbalance = rOFDM0_XBTxIQImbalance; - - /* Tx AFE control 2 */ - pHalData->PHYRegDef[RF_PATH_A].rfTxAFE = rOFDM0_XATxAFE; - pHalData->PHYRegDef[RF_PATH_B].rfTxAFE = rOFDM0_XBTxAFE; - - /* Tranceiver LSSI Readback SI mode */ - pHalData->PHYRegDef[RF_PATH_A].rfLSSIReadBack = rFPGA0_XA_LSSIReadBack; - pHalData->PHYRegDef[RF_PATH_B].rfLSSIReadBack = rFPGA0_XB_LSSIReadBack; - - /* Tranceiver LSSI Readback PI mode */ - pHalData->PHYRegDef[RF_PATH_A].rfLSSIReadBackPi = - TransceiverA_HSPI_Readback; - pHalData->PHYRegDef[RF_PATH_B].rfLSSIReadBackPi = - TransceiverB_HSPI_Readback; -} - -/* The following is for High Power PA */ -static void -storePwrIndexDiffRateOffset(struct rtw_adapter *Adapter, u32 RegAddr, - u32 BitMask, u32 Data) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - - if (RegAddr == rTxAGC_A_Rate18_06) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][0] = Data; - } - if (RegAddr == rTxAGC_A_Rate54_24) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][1] = Data; - } - if (RegAddr == rTxAGC_A_CCK1_Mcs32) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][6] = Data; - } - if (RegAddr == rTxAGC_B_CCK11_A_CCK2_11 && BitMask == 0xffffff00) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][7] = Data; - } - if (RegAddr == rTxAGC_A_Mcs03_Mcs00) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][2] = Data; - } - if (RegAddr == rTxAGC_A_Mcs07_Mcs04) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][3] = Data; - } - if (RegAddr == rTxAGC_A_Mcs11_Mcs08) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][4] = Data; - } - if (RegAddr == rTxAGC_A_Mcs15_Mcs12) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][5] = Data; - } - if (RegAddr == rTxAGC_B_Rate18_06) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][8] = Data; - } - if (RegAddr == rTxAGC_B_Rate54_24) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][9] = Data; - } - if (RegAddr == rTxAGC_B_CCK1_55_Mcs32) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][14] = Data; - } - if (RegAddr == rTxAGC_B_CCK11_A_CCK2_11 && BitMask == 0x000000ff) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][15] = Data; - } - if (RegAddr == rTxAGC_B_Mcs03_Mcs00) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][10] = Data; - } - if (RegAddr == rTxAGC_B_Mcs07_Mcs04) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][11] = Data; - } - if (RegAddr == rTxAGC_B_Mcs11_Mcs08) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][12] = Data; - } - if (RegAddr == rTxAGC_B_Mcs15_Mcs12) { - pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][13] = Data; - pHalData->pwrGroupCnt++; - } -} - -/*----------------------------------------------------------------------------- - * Function: phy_ConfigBBWithPgHeaderFile - * - * Overview: Config PHY_REG_PG array - * - * Input: NONE - * - * Output: NONE - * - * Return: NONE - * - * Revised History: - * When Who Remark - * 11/06/2008 MHC Add later!!!!!!.. Please modify for new files!!!! - * 11/10/2008 tynli Modify to mew files. - *---------------------------------------------------------------------------*/ -static int -phy_ConfigBBWithPgHeaderFile(struct rtw_adapter *Adapter) -{ - int i; - u32 *Rtl819XPHY_REGArray_Table_PG; - u16 PHY_REGArrayPGLen; - - PHY_REGArrayPGLen = Rtl8723_PHY_REG_Array_PGLength; - Rtl819XPHY_REGArray_Table_PG = (u32 *)Rtl8723_PHY_REG_Array_PG; - - for (i = 0; i < PHY_REGArrayPGLen; i = i + 3) { - storePwrIndexDiffRateOffset(Adapter, - Rtl819XPHY_REGArray_Table_PG[i], - Rtl819XPHY_REGArray_Table_PG[i+1], - Rtl819XPHY_REGArray_Table_PG[i+2]); - } - - return _SUCCESS; -} - -static void -phy_BB8192C_Config_1T(struct rtw_adapter *Adapter) -{ - /* for path - B */ - PHY_SetBBReg(Adapter, rFPGA0_TxInfo, 0x3, 0x2); - PHY_SetBBReg(Adapter, rFPGA1_TxInfo, 0x300033, 0x200022); - - /* 20100519 Joseph: Add for 1T2R config. Suggested by Kevin, - Jenyu and Yunan. */ - PHY_SetBBReg(Adapter, rCCK0_AFESetting, bMaskByte3, 0x45); - PHY_SetBBReg(Adapter, rOFDM0_TRxPathEnable, bMaskByte0, 0x23); - /* B path first AGC */ - PHY_SetBBReg(Adapter, rOFDM0_AGCParameter1, 0x30, 0x1); - - PHY_SetBBReg(Adapter, 0xe74, 0x0c000000, 0x2); - PHY_SetBBReg(Adapter, 0xe78, 0x0c000000, 0x2); - PHY_SetBBReg(Adapter, 0xe7c, 0x0c000000, 0x2); - PHY_SetBBReg(Adapter, 0xe80, 0x0c000000, 0x2); - PHY_SetBBReg(Adapter, 0xe88, 0x0c000000, 0x2); -} - -static int -phy_BB8723a_Config_ParaFile(struct rtw_adapter *Adapter) -{ - struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(Adapter); - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - int rtStatus = _SUCCESS; - - /* */ - /* 1. Read PHY_REG.TXT BB INIT!! */ - /* We will separate as 88C / 92C according to chip version */ - /* */ - ODM_ReadAndConfig_PHY_REG_1T_8723A(&pHalData->odmpriv); - - /* */ - /* 20100318 Joseph: Config 2T2R to 1T2R if necessary. */ - /* */ - if (pHalData->rf_type == RF_1T2R) { - phy_BB8192C_Config_1T(Adapter); - DBG_8723A("phy_BB8723a_Config_ParaFile():Config to 1T!!\n"); - } - - /* */ - /* 2. If EEPROM or EFUSE autoload OK, We must config by - PHY_REG_PG.txt */ - /* */ - if (pEEPROM->bautoload_fail_flag == false) { - pHalData->pwrGroupCnt = 0; - - rtStatus = phy_ConfigBBWithPgHeaderFile(Adapter); - } - - if (rtStatus != _SUCCESS) - goto phy_BB8190_Config_ParaFile_Fail; - - /* */ - /* 3. BB AGC table Initialization */ - /* */ - ODM_ReadAndConfig_AGC_TAB_1T_8723A(&pHalData->odmpriv); - -phy_BB8190_Config_ParaFile_Fail: - - return rtStatus; -} - -int -PHY_BBConfig8723A(struct rtw_adapter *Adapter) -{ - int rtStatus = _SUCCESS; - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - u8 TmpU1B = 0; - u8 CrystalCap; - - phy_InitBBRFRegisterDefinition(Adapter); - - /* Suggested by Scott. tynli_test. 2010.12.30. */ - /* 1. 0x28[1] = 1 */ - TmpU1B = rtl8723au_read8(Adapter, REG_AFE_PLL_CTRL); - udelay(2); - rtl8723au_write8(Adapter, REG_AFE_PLL_CTRL, TmpU1B | BIT(1)); - udelay(2); - - /* 2. 0x29[7:0] = 0xFF */ - rtl8723au_write8(Adapter, REG_AFE_PLL_CTRL+1, 0xff); - udelay(2); - - /* 3. 0x02[1:0] = 2b'11 */ - TmpU1B = rtl8723au_read8(Adapter, REG_SYS_FUNC_EN); - rtl8723au_write8(Adapter, REG_SYS_FUNC_EN, - (TmpU1B | FEN_BB_GLB_RSTn | FEN_BBRSTB)); - - /* 4. 0x25[6] = 0 */ - TmpU1B = rtl8723au_read8(Adapter, REG_AFE_XTAL_CTRL + 1); - rtl8723au_write8(Adapter, REG_AFE_XTAL_CTRL+1, TmpU1B & ~BIT(6)); - - /* 5. 0x24[20] = 0 Advised by SD3 Alex Wang. 2011.02.09. */ - TmpU1B = rtl8723au_read8(Adapter, REG_AFE_XTAL_CTRL+2); - rtl8723au_write8(Adapter, REG_AFE_XTAL_CTRL+2, TmpU1B & ~BIT(4)); - - /* 6. 0x1f[7:0] = 0x07 */ - rtl8723au_write8(Adapter, REG_RF_CTRL, 0x07); - - /* */ - /* Config BB and AGC */ - /* */ - rtStatus = phy_BB8723a_Config_ParaFile(Adapter); - -/* only for B-cut */ - if (pHalData->EEPROMVersion >= 0x01) { - CrystalCap = pHalData->CrystalCap & 0x3F; - PHY_SetBBReg(Adapter, REG_MAC_PHY_CTRL, 0xFFF000, - (CrystalCap | (CrystalCap << 6))); - } - - rtl8723au_write32(Adapter, REG_LDOA15_CTRL, 0x01572505); - return rtStatus; -} - -/*----------------------------------------------------------------------------- - * Function: SetTxPowerLevel8723A() - * - * Overview: This function is export to "HalCommon" moudule - * We must consider RF path later!!!!!!! - * - * Input: struct rtw_adapter * Adapter - * u8 channel - * - * Output: NONE - * - * Return: NONE - * - *---------------------------------------------------------------------------*/ -void PHY_SetTxPowerLevel8723A(struct rtw_adapter *Adapter, u8 channel) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - u8 cckpwr[2], ofdmpwr[2]; /* [0]:RF-A, [1]:RF-B */ - int i = channel - 1; - - if (pHalData->bTXPowerDataReadFromEEPORM == false) - return; - - /* 1. CCK */ - cckpwr[RF_PATH_A] = pHalData->TxPwrLevelCck[RF_PATH_A][i]; - cckpwr[RF_PATH_B] = pHalData->TxPwrLevelCck[RF_PATH_B][i]; - - /* 2. OFDM for 1S or 2S */ - if (GET_RF_TYPE(Adapter) == RF_1T2R || - GET_RF_TYPE(Adapter) == RF_1T1R) { - /* Read HT 40 OFDM TX power */ - ofdmpwr[RF_PATH_A] = pHalData->TxPwrLevelHT40_1S[RF_PATH_A][i]; - ofdmpwr[RF_PATH_B] = pHalData->TxPwrLevelHT40_1S[RF_PATH_B][i]; - } else if (GET_RF_TYPE(Adapter) == RF_2T2R) { - /* Read HT 40 OFDM TX power */ - ofdmpwr[RF_PATH_A] = pHalData->TxPwrLevelHT40_2S[RF_PATH_A][i]; - ofdmpwr[RF_PATH_B] = pHalData->TxPwrLevelHT40_2S[RF_PATH_B][i]; - } - - rtl823a_phy_rf6052setccktxpower(Adapter, &cckpwr[0]); - rtl8723a_PHY_RF6052SetOFDMTxPower(Adapter, &ofdmpwr[0], channel); -} - -/*----------------------------------------------------------------------------- - * Function: PHY_SetBWMode23aCallback8192C() - * - * Overview: Timer callback function for SetSetBWMode23a - * - * Input: PRT_TIMER pTimer - * - * Output: NONE - * - * Return: NONE - * - * Note: - * (1) We do not take j mode into consideration now - * (2) Will two workitem of "switch channel" and - * "switch channel bandwidth" run concurrently? - *---------------------------------------------------------------------------*/ -static void -_PHY_SetBWMode23a92C(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - u8 regBwOpMode; - u8 regRRSR_RSC; - - if (Adapter->bDriverStopped) - return; - - /* 3 */ - /* 3<1>Set MAC register */ - /* 3 */ - - regBwOpMode = rtl8723au_read8(Adapter, REG_BWOPMODE); - regRRSR_RSC = rtl8723au_read8(Adapter, REG_RRSR+2); - - switch (pHalData->CurrentChannelBW) { - case HT_CHANNEL_WIDTH_20: - regBwOpMode |= BW_OPMODE_20MHZ; - rtl8723au_write8(Adapter, REG_BWOPMODE, regBwOpMode); - break; - case HT_CHANNEL_WIDTH_40: - regBwOpMode &= ~BW_OPMODE_20MHZ; - rtl8723au_write8(Adapter, REG_BWOPMODE, regBwOpMode); - regRRSR_RSC = (regRRSR_RSC & 0x90) | - (pHalData->nCur40MhzPrimeSC << 5); - rtl8723au_write8(Adapter, REG_RRSR+2, regRRSR_RSC); - break; - - default: - break; - } - - /* 3 */ - /* 3<2>Set PHY related register */ - /* 3 */ - switch (pHalData->CurrentChannelBW) { - /* 20 MHz channel*/ - case HT_CHANNEL_WIDTH_20: - PHY_SetBBReg(Adapter, rFPGA0_RFMOD, bRFMOD, 0x0); - PHY_SetBBReg(Adapter, rFPGA1_RFMOD, bRFMOD, 0x0); - PHY_SetBBReg(Adapter, rFPGA0_AnalogParameter2, BIT(10), 1); - - break; - - /* 40 MHz channel*/ - case HT_CHANNEL_WIDTH_40: - PHY_SetBBReg(Adapter, rFPGA0_RFMOD, bRFMOD, 0x1); - PHY_SetBBReg(Adapter, rFPGA1_RFMOD, bRFMOD, 0x1); - - /* Set Control channel to upper or lower. These settings - are required only for 40MHz */ - PHY_SetBBReg(Adapter, rCCK0_System, bCCKSideBand, - (pHalData->nCur40MhzPrimeSC >> 1)); - PHY_SetBBReg(Adapter, rOFDM1_LSTF, 0xC00, - pHalData->nCur40MhzPrimeSC); - PHY_SetBBReg(Adapter, rFPGA0_AnalogParameter2, BIT(10), 0); - - PHY_SetBBReg(Adapter, 0x818, BIT(26) | BIT(27), - (pHalData->nCur40MhzPrimeSC == - HAL_PRIME_CHNL_OFFSET_LOWER) ? 2:1); - break; - - default: - break; - } - /* Skip over setting of J-mode in BB register here. Default value - is "None J mode". Emily 20070315 */ - - /* Added it for 20/40 mhz switch time evaluation by guangan 070531 */ - /* NowL = PlatformEFIORead4Byte(Adapter, TSFR); */ - /* NowH = PlatformEFIORead4Byte(Adapter, TSFR+4); */ - /* EndTime = ((u64)NowH << 32) + NowL; */ - - rtl8723a_phy_rf6052set_bw(Adapter, pHalData->CurrentChannelBW); -} - - /*----------------------------------------------------------------------------- - * Function: SetBWMode23a8190Pci() - * - * Overview: This function is export to "HalCommon" moudule - * - * Input: struct rtw_adapter * Adapter - * enum ht_channel_width Bandwidth 20M or 40M - * - * Output: NONE - * - * Return: NONE - * - * Note: We do not take j mode into consideration now - *---------------------------------------------------------------------------*/ -void -PHY_SetBWMode23a8723A(struct rtw_adapter *Adapter, - enum ht_channel_width Bandwidth, unsigned char Offset) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - enum ht_channel_width tmpBW = pHalData->CurrentChannelBW; - - pHalData->CurrentChannelBW = Bandwidth; - - pHalData->nCur40MhzPrimeSC = Offset; - - if ((!Adapter->bDriverStopped) && (!Adapter->bSurpriseRemoved)) - _PHY_SetBWMode23a92C(Adapter); - else - pHalData->CurrentChannelBW = tmpBW; -} - -static void _PHY_SwChnl8723A(struct rtw_adapter *Adapter, u8 channel) -{ - enum RF_RADIO_PATH eRFPath; - u32 param1, param2; - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - - /* s1. pre common command - CmdID_SetTxPowerLevel */ - PHY_SetTxPowerLevel8723A(Adapter, channel); - - /* s2. RF dependent command - CmdID_RF_WriteReg, - param1 = RF_CHNLBW, param2 = channel */ - param1 = RF_CHNLBW; - param2 = channel; - for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++) { - pHalData->RfRegChnlVal[eRFPath] = - (pHalData->RfRegChnlVal[eRFPath] & 0xfffffc00) | param2; - PHY_SetRFReg(Adapter, eRFPath, param1, - bRFRegOffsetMask, pHalData->RfRegChnlVal[eRFPath]); - } - - /* s3. post common command - CmdID_End, None */ -} - -void PHY_SwChnl8723A(struct rtw_adapter *Adapter, u8 channel) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - u8 tmpchannel = pHalData->CurrentChannel; - bool result = true; - - if (channel == 0) - channel = 1; - - pHalData->CurrentChannel = channel; - - if ((!Adapter->bDriverStopped) && (!Adapter->bSurpriseRemoved)) { - _PHY_SwChnl8723A(Adapter, channel); - - if (!result) - pHalData->CurrentChannel = tmpchannel; - } else { - pHalData->CurrentChannel = tmpchannel; - } -} diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_rf6052.c b/drivers/staging/rtl8723au/hal/rtl8723a_rf6052.c deleted file mode 100644 index 24c0ff3..0000000 --- a/drivers/staging/rtl8723au/hal/rtl8723a_rf6052.c +++ /dev/null @@ -1,503 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -/****************************************************************************** - * - * - * Module: rtl8192c_rf6052.c (Source C File) - * - * Note: Provide RF 6052 series relative API. - * - * Function: - * - * Export: - * - * Abbrev: - * - * History: - * Data Who Remark - * - * 09/25/2008 MHC Create initial version. - * 11/05/2008 MHC Add API for tw power setting. - * - * -******************************************************************************/ - -#define _RTL8723A_RF6052_C_ - -#include <osdep_service.h> -#include <drv_types.h> - -#include <rtl8723a_hal.h> -#include <usb_ops_linux.h> - -/*----------------------------------------------------------------------------- - * Function: PHY_RF6052SetBandwidth() - * - * Overview: This function is called by SetBWMode23aCallback8190Pci() only - * - * Input: struct rtw_adapter * Adapter - * WIRELESS_BANDWIDTH_E Bandwidth 20M or 40M - * - * Output: NONE - * - * Return: NONE - * - * Note: For RF type 0222D - *---------------------------------------------------------------------------*/ -void rtl8723a_phy_rf6052set_bw(struct rtw_adapter *Adapter, - enum ht_channel_width Bandwidth) /* 20M or 40M */ -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - - switch (Bandwidth) { - case HT_CHANNEL_WIDTH_20: - pHalData->RfRegChnlVal[0] = - (pHalData->RfRegChnlVal[0] & 0xfffff3ff) | 0x0400; - PHY_SetRFReg(Adapter, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask, - pHalData->RfRegChnlVal[0]); - break; - case HT_CHANNEL_WIDTH_40: - pHalData->RfRegChnlVal[0] = - (pHalData->RfRegChnlVal[0] & 0xfffff3ff); - PHY_SetRFReg(Adapter, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask, - pHalData->RfRegChnlVal[0]); - break; - default: - break; - } -} - -/*----------------------------------------------------------------------------- - * Function: PHY_RF6052SetCckTxPower - * - * Overview: - * - * Input: NONE - * - * Output: NONE - * - * Return: NONE - * - * Revised History: - * When Who Remark - * 11/05/2008 MHC Simulate 8192series.. - * - *---------------------------------------------------------------------------*/ - -void rtl823a_phy_rf6052setccktxpower(struct rtw_adapter *Adapter, - u8 *pPowerlevel) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv; - u32 TxAGC[2] = {0, 0}, tmpval = 0; - u8 idx1, idx2; - u8 *ptr; - - if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { - TxAGC[RF_PATH_A] = 0x3f3f3f3f; - TxAGC[RF_PATH_B] = 0x3f3f3f3f; - - for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) { - TxAGC[idx1] = pPowerlevel[idx1] | - (pPowerlevel[idx1] << 8) | - (pPowerlevel[idx1] << 16) | - (pPowerlevel[idx1] << 24); - /* - * 2010/10/18 MH For external PA module. We need - * to limit power index to be less than 0x20. - */ - if (TxAGC[idx1] > 0x20 && pHalData->ExternalPA) - TxAGC[idx1] = 0x20; - } - } else { -/* 20100427 Joseph: Driver dynamic Tx power shall not affect Tx - * power. It shall be determined by power training mechanism. */ -/* Currently, we cannot fully disable driver dynamic tx power - * mechanism because it is referenced by BT coexist mechanism. */ -/* In the future, two mechanism shall be separated from each other - * and maintained independently. Thanks for Lanhsin's reminder. */ - if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1) { - TxAGC[RF_PATH_A] = 0x10101010; - TxAGC[RF_PATH_B] = 0x10101010; - } else if (pdmpriv->DynamicTxHighPowerLvl == - TxHighPwrLevel_Level2) { - TxAGC[RF_PATH_A] = 0x00000000; - TxAGC[RF_PATH_B] = 0x00000000; - } else { - for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) { - TxAGC[idx1] = pPowerlevel[idx1] | - (pPowerlevel[idx1] << 8) | - (pPowerlevel[idx1] << 16) | - (pPowerlevel[idx1] << 24); - } - - if (pHalData->EEPROMRegulatory == 0) { - tmpval = (pHalData->MCSTxPowerLevelOriginalOffset[0][6]) + - (pHalData->MCSTxPowerLevelOriginalOffset[0][7]<<8); - TxAGC[RF_PATH_A] += tmpval; - - tmpval = (pHalData->MCSTxPowerLevelOriginalOffset[0][14]) + - (pHalData->MCSTxPowerLevelOriginalOffset[0][15]<<24); - TxAGC[RF_PATH_B] += tmpval; - } - } - } - - for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) { - ptr = (u8 *)(&TxAGC[idx1]); - for (idx2 = 0; idx2 < 4; idx2++) { - if (*ptr > RF6052_MAX_TX_PWR) - *ptr = RF6052_MAX_TX_PWR; - ptr++; - } - } - - /* rf-A cck tx power */ - tmpval = TxAGC[RF_PATH_A] & 0xff; - PHY_SetBBReg(Adapter, rTxAGC_A_CCK1_Mcs32, bMaskByte1, tmpval); - tmpval = TxAGC[RF_PATH_A] >> 8; - PHY_SetBBReg(Adapter, rTxAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval); - - /* rf-B cck tx power */ - tmpval = TxAGC[RF_PATH_B] >> 24; - PHY_SetBBReg(Adapter, rTxAGC_B_CCK11_A_CCK2_11, bMaskByte0, tmpval); - tmpval = TxAGC[RF_PATH_B] & 0x00ffffff; - PHY_SetBBReg(Adapter, rTxAGC_B_CCK1_55_Mcs32, 0xffffff00, tmpval); -} /* PHY_RF6052SetCckTxPower */ - -/* powerbase0 for OFDM rates */ -/* powerbase1 for HT MCS rates */ -static void getPowerBase(struct rtw_adapter *Adapter, u8 *pPowerLevel, - u8 Channel, u32 *OfdmBase, u32 *MCSBase) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - u32 ofdm, mcs; - u8 Legacy_pwrdiff = 0; - s8 HT20_pwrdiff = 0; - u8 i, powerlevel[2]; - - for (i = 0; i < 2; i++) { - powerlevel[i] = pPowerLevel[i]; - Legacy_pwrdiff = pHalData->TxPwrLegacyHtDiff[i][Channel-1]; - ofdm = powerlevel[i] + Legacy_pwrdiff; - - ofdm = ofdm << 24 | ofdm << 16 | ofdm << 8 | ofdm; - *(OfdmBase + i) = ofdm; - } - - for (i = 0; i < 2; i++) { - /* Check HT20 to HT40 diff */ - if (pHalData->CurrentChannelBW == HT_CHANNEL_WIDTH_20) { - HT20_pwrdiff = pHalData->TxPwrHt20Diff[i][Channel-1]; - powerlevel[i] += HT20_pwrdiff; - } - mcs = powerlevel[i]; - mcs = mcs << 24 | mcs << 16 | mcs << 8 | mcs; - *(MCSBase + i) = mcs; - } -} - -static void -getTxPowerWriteValByRegulatory(struct rtw_adapter *Adapter, u8 Channel, - u8 index, u32 *powerBase0, u32 *powerBase1, - u32 *pOutWriteVal) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - u8 i, chnlGroup = 0, pwr_diff_limit[4]; - u32 writeVal, customer_limit, rf; - - /* Index 0 & 1 = legacy OFDM, 2-5 = HT_MCS rate */ - for (rf = 0; rf < 2; rf++) { - switch (pHalData->EEPROMRegulatory) { - case 0: /* Realtek better performance */ - /* increase power diff defined by Realtek for - * large power */ - chnlGroup = 0; - writeVal = pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index+(rf?8:0)] + - ((index < 2) ? powerBase0[rf] : powerBase1[rf]); - break; - case 1: /* Realtek regulatory */ - /* increase power diff defined by Realtek for - * regulatory */ - if (pHalData->pwrGroupCnt == 1) - chnlGroup = 0; - if (pHalData->pwrGroupCnt >= 3) { - if (Channel <= 3) - chnlGroup = 0; - else if (Channel >= 4 && Channel <= 9) - chnlGroup = 1; - else if (Channel > 9) - chnlGroup = 2; - - if (pHalData->CurrentChannelBW == - HT_CHANNEL_WIDTH_20) - chnlGroup++; - else - chnlGroup += 4; - } - writeVal = pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index+(rf?8:0)] + - ((index < 2) ? powerBase0[rf] : - powerBase1[rf]); - break; - case 2: /* Better regulatory */ - /* don't increase any power diff */ - writeVal = (index < 2) ? powerBase0[rf] : - powerBase1[rf]; - break; - case 3: /* Customer defined power diff. */ - chnlGroup = 0; - - for (i = 0; i < 4; i++) { - pwr_diff_limit[i] = (u8)((pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index + - (rf ? 8 : 0)]&(0x7f << (i*8))) >> (i*8)); - if (pHalData->CurrentChannelBW == HT_CHANNEL_WIDTH_40) { - if (pwr_diff_limit[i] > pHalData->PwrGroupHT40[rf][Channel-1]) - pwr_diff_limit[i] = pHalData->PwrGroupHT40[rf][Channel-1]; - } else { - if (pwr_diff_limit[i] > pHalData->PwrGroupHT20[rf][Channel-1]) - pwr_diff_limit[i] = pHalData->PwrGroupHT20[rf][Channel-1]; - } - } - customer_limit = (pwr_diff_limit[3]<<24) | (pwr_diff_limit[2]<<16) | - (pwr_diff_limit[1]<<8) | (pwr_diff_limit[0]); - writeVal = customer_limit + ((index<2)?powerBase0[rf]:powerBase1[rf]); - break; - default: - chnlGroup = 0; - writeVal = pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index+(rf?8:0)] + - ((index < 2) ? powerBase0[rf] : powerBase1[rf]); - break; - } - -/* 20100427 Joseph: Driver dynamic Tx power shall not affect Tx power. - It shall be determined by power training mechanism. */ -/* Currently, we cannot fully disable driver dynamic tx power mechanism - because it is referenced by BT coexist mechanism. */ -/* In the future, two mechanism shall be separated from each other and - maintained independently. Thanks for Lanhsin's reminder. */ - - if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1) - writeVal = 0x14141414; - else if (pdmpriv->DynamicTxHighPowerLvl == - TxHighPwrLevel_Level2) - writeVal = 0x00000000; - - /* 20100628 Joseph: High power mode for BT-Coexist mechanism. */ - /* This mechanism is only applied when - Driver-Highpower-Mechanism is OFF. */ - if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_BT1) - writeVal = writeVal - 0x06060606; - else if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_BT2) - writeVal = writeVal; - *(pOutWriteVal + rf) = writeVal; - } -} - -static void writeOFDMPowerReg(struct rtw_adapter *Adapter, u8 index, - u32 *pValue) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - u16 RegOffset_A[6] = { - rTxAGC_A_Rate18_06, rTxAGC_A_Rate54_24, - rTxAGC_A_Mcs03_Mcs00, rTxAGC_A_Mcs07_Mcs04, - rTxAGC_A_Mcs11_Mcs08, rTxAGC_A_Mcs15_Mcs12 - }; - u16 RegOffset_B[6] = { - rTxAGC_B_Rate18_06, rTxAGC_B_Rate54_24, - rTxAGC_B_Mcs03_Mcs00, rTxAGC_B_Mcs07_Mcs04, - rTxAGC_B_Mcs11_Mcs08, rTxAGC_B_Mcs15_Mcs12 - }; - u8 i, rf, pwr_val[4]; - u32 writeVal; - u16 RegOffset; - - for (rf = 0; rf < 2; rf++) { - writeVal = pValue[rf]; - for (i = 0; i < 4; i++) { - pwr_val[i] = (u8)((writeVal & - (0x7f << (i * 8))) >> (i * 8)); - if (pwr_val[i] > RF6052_MAX_TX_PWR) - pwr_val[i] = RF6052_MAX_TX_PWR; - } - writeVal = pwr_val[3] << 24 | pwr_val[2] << 16 | - pwr_val[1] << 8 | pwr_val[0]; - - if (rf == 0) - RegOffset = RegOffset_A[index]; - else - RegOffset = RegOffset_B[index]; - - rtl8723au_write32(Adapter, RegOffset, writeVal); - - /* 201005115 Joseph: Set Tx Power diff for Tx power - training mechanism. */ - if (((pHalData->rf_type == RF_2T2R) && - (RegOffset == rTxAGC_A_Mcs15_Mcs12 || - RegOffset == rTxAGC_B_Mcs15_Mcs12)) || - ((pHalData->rf_type != RF_2T2R) && - (RegOffset == rTxAGC_A_Mcs07_Mcs04 || - RegOffset == rTxAGC_B_Mcs07_Mcs04))) { - writeVal = pwr_val[3]; - if (RegOffset == rTxAGC_A_Mcs15_Mcs12 || - RegOffset == rTxAGC_A_Mcs07_Mcs04) - RegOffset = 0xc90; - if (RegOffset == rTxAGC_B_Mcs15_Mcs12 || - RegOffset == rTxAGC_B_Mcs07_Mcs04) - RegOffset = 0xc98; - for (i = 0; i < 3; i++) { - if (i != 2) - writeVal = (writeVal > 8) ? - (writeVal - 8) : 0; - else - writeVal = (writeVal > 6) ? - (writeVal - 6) : 0; - rtl8723au_write8(Adapter, RegOffset + i, - (u8)writeVal); - } - } - } -} -/*----------------------------------------------------------------------------- - * Function: PHY_RF6052SetOFDMTxPower - * - * Overview: For legacy and HY OFDM, we must read EEPROM TX power index for - * different channel and read original value in TX power - * register area from 0xe00. We increase offset and - * original value to be correct tx pwr. - * - * Input: NONE - * - * Output: NONE - * - * Return: NONE - * - * Revised History: - * When Remark - * 11/05/2008 MHC Simulate 8192 series method. - * 01/06/2009 MHC 1. Prevent Path B tx power overflow or - * underflow dure to A/B pwr difference or - * legacy/HT pwr diff. - * 2. We concern with path B legacy/HT OFDM difference. - * 01/22/2009 MHC Support new EPRO format from SD3. - * - *---------------------------------------------------------------------------*/ -void rtl8723a_PHY_RF6052SetOFDMTxPower(struct rtw_adapter *Adapter, - u8 *pPowerLevel, u8 Channel) -{ - u32 writeVal[2], powerBase0[2], powerBase1[2]; - u8 index = 0; - - getPowerBase(Adapter, pPowerLevel, Channel, - &powerBase0[0], &powerBase1[0]); - - for (index = 0; index < 6; index++) { - getTxPowerWriteValByRegulatory(Adapter, Channel, index, - &powerBase0[0], &powerBase1[0], &writeVal[0]); - - writeOFDMPowerReg(Adapter, index, &writeVal[0]); - } -} - -static int phy_RF6052_Config_ParaFile(struct rtw_adapter *Adapter) -{ - u32 u4RegValue = 0; - u8 eRFPath; - struct bb_reg_define *pPhyReg; - int rtStatus = _SUCCESS; - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - - /* 3----------------------------------------------------------------- */ - /* 3 <2> Initialize RF */ - /* 3----------------------------------------------------------------- */ - for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++) { - - pPhyReg = &pHalData->PHYRegDef[eRFPath]; - - /*----Store original RFENV control type----*/ - switch (eRFPath) { - case RF_PATH_A: - u4RegValue = PHY_QueryBBReg(Adapter, pPhyReg->rfintfs, - bRFSI_RFENV); - break; - case RF_PATH_B: - u4RegValue = PHY_QueryBBReg(Adapter, pPhyReg->rfintfs, - bRFSI_RFENV << 16); - break; - } - - /*----Set RF_ENV enable----*/ - PHY_SetBBReg(Adapter, pPhyReg->rfintfe, bRFSI_RFENV << 16, 0x1); - udelay(1);/* PlatformStallExecution(1); */ - - /*----Set RF_ENV output high----*/ - PHY_SetBBReg(Adapter, pPhyReg->rfintfo, bRFSI_RFENV, 0x1); - udelay(1);/* PlatformStallExecution(1); */ - - /* Set bit number of Address and Data for RF register */ - PHY_SetBBReg(Adapter, pPhyReg->rfHSSIPara2, b3WireAddressLength, - 0x0); /* Set 1 to 4 bits for 8255 */ - udelay(1);/* PlatformStallExecution(1); */ - - PHY_SetBBReg(Adapter, pPhyReg->rfHSSIPara2, b3WireDataLength, - 0x0); /* Set 0 to 12 bits for 8255 */ - udelay(1);/* PlatformStallExecution(1); */ - - /*----Initialize RF fom connfiguration file----*/ - switch (eRFPath) { - case RF_PATH_A: - ODM_ReadAndConfig_RadioA_1T_8723A(&pHalData->odmpriv); - break; - case RF_PATH_B: - break; - } - - /*----Restore RFENV control type----*/ - switch (eRFPath) { - case RF_PATH_A: - PHY_SetBBReg(Adapter, pPhyReg->rfintfs, - bRFSI_RFENV, u4RegValue); - break; - case RF_PATH_B: - PHY_SetBBReg(Adapter, pPhyReg->rfintfs, - bRFSI_RFENV << 16, u4RegValue); - break; - } - - if (rtStatus != _SUCCESS) { - goto phy_RF6052_Config_ParaFile_Fail; - } - } -phy_RF6052_Config_ParaFile_Fail: - return rtStatus; -} - -int PHY_RF6052_Config8723A(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - - /* Initialize general global value */ - /* TODO: Extend RF_PATH_C and RF_PATH_D in the future */ - if (pHalData->rf_type == RF_1T1R) - pHalData->NumTotalRFPath = 1; - else - pHalData->NumTotalRFPath = 2; - - /* Config BB and RF */ - return phy_RF6052_Config_ParaFile(Adapter); -} - -/* End of HalRf6052.c */ diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_rxdesc.c b/drivers/staging/rtl8723au/hal/rtl8723a_rxdesc.c deleted file mode 100644 index 81b5efe..0000000 --- a/drivers/staging/rtl8723au/hal/rtl8723a_rxdesc.c +++ /dev/null @@ -1,69 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RTL8723A_REDESC_C_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <rtl8723a_hal.h> - -static void process_rssi(struct rtw_adapter *padapter, - struct recv_frame *prframe) -{ - struct rx_pkt_attrib *pattrib = &prframe->attrib; - struct signal_stat *signal_stat = &padapter->recvpriv.signal_strength_data; - - if (signal_stat->update_req) { - signal_stat->total_num = 0; - signal_stat->total_val = 0; - signal_stat->update_req = 0; - } - - signal_stat->total_num++; - signal_stat->total_val += pattrib->phy_info.SignalStrength; - signal_stat->avg_val = signal_stat->total_val / signal_stat->total_num; -} - -static void process_link_qual(struct rtw_adapter *padapter, - struct recv_frame *prframe) -{ - struct rx_pkt_attrib *pattrib; - struct signal_stat *signal_stat; - - if (prframe == NULL || padapter == NULL) - return; - - pattrib = &prframe->attrib; - signal_stat = &padapter->recvpriv.signal_qual_data; - - if (signal_stat->update_req) { - signal_stat->total_num = 0; - signal_stat->total_val = 0; - signal_stat->update_req = 0; - } - - signal_stat->total_num++; - signal_stat->total_val += pattrib->phy_info.SignalQuality; - signal_stat->avg_val = signal_stat->total_val / signal_stat->total_num; -} - -/* void rtl8723a_process_phy_info(struct rtw_adapter *padapter, union recv_frame *prframe) */ -void rtl8723a_process_phy_info(struct rtw_adapter *padapter, void *prframe) -{ - struct recv_frame *precvframe = prframe; - /* Check RSSI */ - process_rssi(padapter, precvframe); - /* Check EVM */ - process_link_qual(padapter, precvframe); -} diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_sreset.c b/drivers/staging/rtl8723au/hal/rtl8723a_sreset.c deleted file mode 100644 index 3c46294..0000000 --- a/drivers/staging/rtl8723au/hal/rtl8723a_sreset.c +++ /dev/null @@ -1,55 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RTL8723A_SRESET_C_ - -#include <rtl8723a_sreset.h> -#include <rtl8723a_hal.h> -#include <usb_ops_linux.h> - -void rtl8723a_sreset_xmit_status_check(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct sreset_priv *psrtpriv = &pHalData->srestpriv; - - unsigned long current_time; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - unsigned int diff_time; - u32 txdma_status; - - txdma_status = rtl8723au_read32(padapter, REG_TXDMA_STATUS); - if (txdma_status != 0) { - DBG_8723A("%s REG_TXDMA_STATUS:0x%08x\n", __func__, txdma_status); - rtw_sreset_reset(padapter); - } - - current_time = jiffies; - - if (0 == pxmitpriv->free_xmitbuf_cnt || 0 == pxmitpriv->free_xmit_extbuf_cnt) { - - diff_time = jiffies_to_msecs(jiffies - psrtpriv->last_tx_time); - - if (diff_time > 2000) { - if (psrtpriv->last_tx_complete_time == 0) { - psrtpriv->last_tx_complete_time = current_time; - } else { - diff_time = jiffies_to_msecs(jiffies - psrtpriv->last_tx_complete_time); - if (diff_time > 4000) { - DBG_8723A("%s tx hang\n", __func__); - rtw_sreset_reset(padapter); - } - } - } - } -} diff --git a/drivers/staging/rtl8723au/hal/rtl8723au_recv.c b/drivers/staging/rtl8723au/hal/rtl8723au_recv.c deleted file mode 100644 index 0fec84b..0000000 --- a/drivers/staging/rtl8723au/hal/rtl8723au_recv.c +++ /dev/null @@ -1,267 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RTL8192CU_RECV_C_ -#include <osdep_service.h> -#include <drv_types.h> -#include <recv_osdep.h> -#include <mlme_osdep.h> -#include <linux/ip.h> -#include <linux/if_ether.h> -#include <usb_ops.h> -#include <wifi.h> -#include <rtl8723a_hal.h> - -int rtl8723au_init_recv_priv(struct rtw_adapter *padapter) -{ - struct recv_priv *precvpriv = &padapter->recvpriv; - int i, size, res = _SUCCESS; - struct recv_buf *precvbuf; - unsigned long tmpaddr; - unsigned long alignment; - struct sk_buff *pskb; - - tasklet_init(&precvpriv->recv_tasklet, - (void(*)(unsigned long))rtl8723au_recv_tasklet, - (unsigned long)padapter); - - precvpriv->int_in_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!precvpriv->int_in_urb) - DBG_8723A("alloc_urb for interrupt in endpoint fail !!!!\n"); - precvpriv->int_in_buf = kzalloc(USB_INTR_CONTENT_LENGTH, GFP_KERNEL); - if (!precvpriv->int_in_buf) - DBG_8723A("alloc_mem for interrupt in endpoint fail !!!!\n"); - - size = NR_RECVBUFF * sizeof(struct recv_buf); - precvpriv->precv_buf = kzalloc(size, GFP_KERNEL); - if (!precvpriv->precv_buf) { - res = _FAIL; - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "alloc recv_buf fail!\n"); - goto exit; - } - - precvbuf = (struct recv_buf *)precvpriv->precv_buf; - - for (i = 0; i < NR_RECVBUFF; i++) { - INIT_LIST_HEAD(&precvbuf->list); - - precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL); - if (!precvbuf->purb) - break; - - precvbuf->adapter = padapter; - - precvbuf++; - } - - skb_queue_head_init(&precvpriv->rx_skb_queue); - skb_queue_head_init(&precvpriv->free_recv_skb_queue); - - for (i = 0; i < NR_PREALLOC_RECV_SKB; i++) { - size = MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ; - pskb = __netdev_alloc_skb(padapter->pnetdev, size, GFP_KERNEL); - - if (pskb) { - pskb->dev = padapter->pnetdev; - - tmpaddr = (unsigned long)pskb->data; - alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1); - skb_reserve(pskb, (RECVBUFF_ALIGN_SZ - alignment)); - - skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb); - } - - pskb = NULL; - } - -exit: - return res; -} - -void rtl8723au_free_recv_priv(struct rtw_adapter *padapter) -{ - int i; - struct recv_buf *precvbuf; - struct recv_priv *precvpriv = &padapter->recvpriv; - - precvbuf = (struct recv_buf *)precvpriv->precv_buf; - - for (i = 0; i < NR_RECVBUFF; i++) { - usb_free_urb(precvbuf->purb); - - if (precvbuf->pskb) - dev_kfree_skb_any(precvbuf->pskb); - - precvbuf++; - } - - kfree(precvpriv->precv_buf); - - usb_free_urb(precvpriv->int_in_urb); - kfree(precvpriv->int_in_buf); - - if (skb_queue_len(&precvpriv->rx_skb_queue)) - DBG_8723A(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_8723A(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); -} - -struct recv_stat_cpu { - u32 rxdw0; - u32 rxdw1; - u32 rxdw2; - u32 rxdw3; - u32 rxdw4; - u32 rxdw5; -}; - -void update_recvframe_attrib(struct recv_frame *precvframe, - struct recv_stat *prxstat) -{ - struct rx_pkt_attrib *pattrib; - struct recv_stat_cpu report; - struct rxreport_8723a *prxreport; - - report.rxdw0 = le32_to_cpu(prxstat->rxdw0); - report.rxdw1 = le32_to_cpu(prxstat->rxdw1); - report.rxdw2 = le32_to_cpu(prxstat->rxdw2); - report.rxdw3 = le32_to_cpu(prxstat->rxdw3); - report.rxdw4 = le32_to_cpu(prxstat->rxdw4); - report.rxdw5 = le32_to_cpu(prxstat->rxdw5); - - prxreport = (struct rxreport_8723a *)&report; - - pattrib = &precvframe->attrib; - memset(pattrib, 0, sizeof(struct rx_pkt_attrib)); - - /* update rx report to recv_frame attribute */ - pattrib->pkt_len = (u16)prxreport->pktlen; - pattrib->drvinfo_sz = (u8)(prxreport->drvinfosize << 3); - pattrib->physt = (u8)prxreport->physt; - - pattrib->crc_err = (u8)prxreport->crc32; - pattrib->icv_err = (u8)prxreport->icverr; - - pattrib->bdecrypted = (u8)(prxreport->swdec ? 0 : 1); - pattrib->encrypt = (u8)prxreport->security; - - pattrib->qos = (u8)prxreport->qos; - pattrib->priority = (u8)prxreport->tid; - - pattrib->amsdu = (u8)prxreport->amsdu; - - pattrib->seq_num = (u16)prxreport->seq; - pattrib->frag_num = (u8)prxreport->frag; - pattrib->mfrag = (u8)prxreport->mf; - pattrib->mdata = (u8)prxreport->md; - - pattrib->mcs_rate = (u8)prxreport->rxmcs; - pattrib->rxht = (u8)prxreport->rxht; -} - -void update_recvframe_phyinfo(struct recv_frame *precvframe, - struct phy_stat *pphy_status) -{ - struct rtw_adapter *padapter = precvframe->adapter; - struct rx_pkt_attrib *pattrib = &precvframe->attrib; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct phy_info *pPHYInfo = &pattrib->phy_info; - struct odm_packet_info pkt_info; - u8 *sa = NULL, *da; - struct sta_priv *pstapriv; - struct sta_info *psta; - struct sk_buff *skb = precvframe->pkt; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - bool matchbssid = false; - u8 *bssid; - - matchbssid = !ieee80211_is_ctl(hdr->frame_control) && - !pattrib->icv_err && !pattrib->crc_err; - - if (matchbssid) { - switch (hdr->frame_control & - cpu_to_le16(IEEE80211_FCTL_TODS | - IEEE80211_FCTL_FROMDS)) { - case cpu_to_le16(IEEE80211_FCTL_TODS): - bssid = hdr->addr1; - break; - case cpu_to_le16(IEEE80211_FCTL_FROMDS): - bssid = hdr->addr2; - break; - case cpu_to_le16(0): - bssid = hdr->addr3; - break; - default: - bssid = NULL; - matchbssid = false; - } - - if (bssid) - matchbssid = ether_addr_equal( - get_bssid(&padapter->mlmepriv), bssid); - } - - pkt_info.bPacketMatchBSSID = matchbssid; - - da = ieee80211_get_DA(hdr); - pkt_info.bPacketToSelf = pkt_info.bPacketMatchBSSID && - (!memcmp(da, myid(&padapter->eeprompriv), ETH_ALEN)); - - pkt_info.bPacketBeacon = pkt_info.bPacketMatchBSSID && - ieee80211_is_beacon(hdr->frame_control); - - pkt_info.StationID = 0xFF; - if (pkt_info.bPacketBeacon) { - if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == true) - sa = padapter->mlmepriv.cur_network.network.MacAddress; - /* to do Ad-hoc */ - } else { - sa = ieee80211_get_SA(hdr); - } - - pstapriv = &padapter->stapriv; - psta = rtw_get_stainfo23a(pstapriv, sa); - if (psta) { - pkt_info.StationID = psta->mac_id; - /* printk("%s ==> StationID(%d)\n", __func__, pkt_info.StationID); */ - } - pkt_info.Rate = pattrib->mcs_rate; - - ODM_PhyStatusQuery23a(&pHalData->odmpriv, pPHYInfo, - (u8 *)pphy_status, &pkt_info); - precvframe->psta = NULL; - if (pkt_info.bPacketMatchBSSID && - (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true)) { - if (psta) { - precvframe->psta = psta; - rtl8723a_process_phy_info(padapter, precvframe); - } - } else if (pkt_info.bPacketToSelf || pkt_info.bPacketBeacon) { - if (check_fwstate(&padapter->mlmepriv, - WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE) == - true) { - if (psta) - precvframe->psta = psta; - } - rtl8723a_process_phy_info(padapter, precvframe); - } -} diff --git a/drivers/staging/rtl8723au/hal/rtl8723au_xmit.c b/drivers/staging/rtl8723au/hal/rtl8723au_xmit.c deleted file mode 100644 index 14746dd..0000000 --- a/drivers/staging/rtl8723au/hal/rtl8723au_xmit.c +++ /dev/null @@ -1,520 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RTL8192C_XMIT_C_ -#include <osdep_service.h> -#include <drv_types.h> -#include <wifi.h> -#include <osdep_intf.h> -#include <usb_ops.h> -/* include <rtl8192c_hal.h> */ -#include <rtl8723a_hal.h> - -static int urb_zero_packet_chk(struct rtw_adapter *padapter, int sz) -{ - int blnSetTxDescOffset; - struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter); - - if (pdvobj->ishighspeed) { - if (((sz + TXDESC_SIZE) % 512) == 0) - blnSetTxDescOffset = 1; - else - blnSetTxDescOffset = 0; - } else { - if (((sz + TXDESC_SIZE) % 64) == 0) - blnSetTxDescOffset = 1; - else - blnSetTxDescOffset = 0; - } - return blnSetTxDescOffset; -} - -static void rtl8192cu_cal_txdesc_chksum(struct tx_desc *ptxdesc) -{ - __le16 *usPtr = (__le16 *)ptxdesc; - u32 count = 16; /* (32 bytes / 2 bytes per XOR) => 16 times */ - u32 index; - u16 checksum = 0; - - /* Clear first */ - ptxdesc->txdw7 &= cpu_to_le32(0xffff0000); - - for (index = 0 ; index < count ; index++) - checksum = checksum ^ le16_to_cpu(*(usPtr + index)); - - ptxdesc->txdw7 |= cpu_to_le32(0x0000ffff&checksum); -} - -static void fill_txdesc_sectype(struct pkt_attrib *pattrib, struct tx_desc *ptxdesc) -{ - if ((pattrib->encrypt > 0) && !pattrib->bswenc) { - switch (pattrib->encrypt) { - /* SEC_TYPE */ - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - ptxdesc->txdw1 |= cpu_to_le32((0x01<<22)&0x00c00000); - break; - case WLAN_CIPHER_SUITE_TKIP: - /* ptxdesc->txdw1 |= cpu_to_le32((0x02<<22)&0x00c00000); */ - ptxdesc->txdw1 |= cpu_to_le32((0x01<<22)&0x00c00000); - break; - case WLAN_CIPHER_SUITE_CCMP: - ptxdesc->txdw1 |= cpu_to_le32((0x03<<22)&0x00c00000); - break; - case 0: - default: - break; - } - } -} - -static void fill_txdesc_vcs(struct pkt_attrib *pattrib, __le32 *pdw) -{ - /* DBG_8723A("cvs_mode =%d\n", pattrib->vcs_mode); */ - - switch (pattrib->vcs_mode) { - case RTS_CTS: - *pdw |= cpu_to_le32(BIT(12)); - break; - case CTS_TO_SELF: - *pdw |= cpu_to_le32(BIT(11)); - break; - case NONE_VCS: - default: - break; - } - - if (pattrib->vcs_mode) { - *pdw |= cpu_to_le32(BIT(13)); - - /* Set RTS BW */ - if (pattrib->ht_en) { - *pdw |= (pattrib->bwmode&HT_CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(27)) : 0; - - if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER) - *pdw |= cpu_to_le32((0x01<<28)&0x30000000); - else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER) - *pdw |= cpu_to_le32((0x02<<28)&0x30000000); - else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) - *pdw |= 0; - else - *pdw |= cpu_to_le32((0x03<<28)&0x30000000); - } - } -} - -static void fill_txdesc_phy(struct pkt_attrib *pattrib, __le32 *pdw) -{ - if (pattrib->ht_en) { - *pdw |= (pattrib->bwmode&HT_CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(25)) : 0; - - if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER) - *pdw |= cpu_to_le32((0x01<<20)&0x003f0000); - else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER) - *pdw |= cpu_to_le32((0x02<<20)&0x003f0000); - else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) - *pdw |= 0; - else - *pdw |= cpu_to_le32((0x03<<20)&0x003f0000); - } -} - -static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz) -{ - int pull = 0; - uint qsel; - struct rtw_adapter *padapter = pxmitframe->padapter; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - struct tx_desc *ptxdesc = (struct tx_desc *)pmem; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - int bmcst = is_multicast_ether_addr(pattrib->ra); - - if (urb_zero_packet_chk(padapter, sz) == 0) { - ptxdesc = (struct tx_desc *)(pmem+PACKET_OFFSET_SZ); - pull = 1; - pxmitframe->pkt_offset--; - } - - memset(ptxdesc, 0, sizeof(struct tx_desc)); - - if (pxmitframe->frame_tag == DATA_FRAMETAG) { - /* offset 4 */ - ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id&0x1f); - - qsel = (uint)(pattrib->qsel & 0x0000001f); - ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00); - - ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid<<16) & 0x000f0000); - - fill_txdesc_sectype(pattrib, ptxdesc); - - if (pattrib->ampdu_en) - ptxdesc->txdw1 |= cpu_to_le32(BIT(5));/* AGG EN */ - else - ptxdesc->txdw1 |= cpu_to_le32(BIT(6));/* AGG BK */ - - /* offset 8 */ - - /* offset 12 */ - ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000); - - /* offset 16 , offset 20 */ - if (pattrib->qos_en) - ptxdesc->txdw4 |= cpu_to_le32(BIT(6));/* QoS */ - - if ((pattrib->ether_type != 0x888e) && - (pattrib->ether_type != 0x0806) && - (pattrib->dhcp_pkt != 1)) { - /* Non EAP & ARP & DHCP type data packet */ - - fill_txdesc_vcs(pattrib, &ptxdesc->txdw4); - fill_txdesc_phy(pattrib, &ptxdesc->txdw4); - - ptxdesc->txdw4 |= cpu_to_le32(0x00000008);/* RTS Rate = 24M */ - ptxdesc->txdw5 |= cpu_to_le32(0x0001ff00);/* */ - - /* use REG_INIDATA_RATE_SEL value */ - ptxdesc->txdw5 |= cpu_to_le32(pdmpriv->INIDATA_RATE[pattrib->mac_id]); - } else { - /* EAP data packet and ARP packet. */ - /* Use the 1M data rate to send the EAP/ARP packet. */ - /* This will maybe make the handshake smooth. */ - - ptxdesc->txdw1 |= cpu_to_le32(BIT(6));/* AGG BK */ - - ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */ - - if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT) - ptxdesc->txdw4 |= cpu_to_le32(BIT(24));/* DATA_SHORT */ - - ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate23a(pmlmeext->tx_rate)); - } - } else if (pxmitframe->frame_tag == MGNT_FRAMETAG) { - /* offset 4 */ - ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id&0x1f); - - qsel = (uint)(pattrib->qsel&0x0000001f); - ptxdesc->txdw1 |= cpu_to_le32((qsel<<QSEL_SHT)&0x00001f00); - - ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid<<16) & 0x000f0000); - - /* offset 8 */ - /* CCX-TXRPT ack for xmit mgmt frames. */ - if (pxmitframe->ack_report) - ptxdesc->txdw2 |= cpu_to_le32(BIT(19)); - - /* offset 12 */ - ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000); - - /* offset 16 */ - ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */ - - /* offset 20 */ - ptxdesc->txdw5 |= cpu_to_le32(BIT(17));/* retry limit enable */ - ptxdesc->txdw5 |= cpu_to_le32(0x00180000);/* retry limit = 6 */ - - ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate23a(pmlmeext->tx_rate)); - } else if (pxmitframe->frame_tag == TXAGG_FRAMETAG) { - DBG_8723A("pxmitframe->frame_tag == TXAGG_FRAMETAG\n"); - } else { - DBG_8723A("pxmitframe->frame_tag = %d\n", - pxmitframe->frame_tag); - - /* offset 4 */ - ptxdesc->txdw1 |= cpu_to_le32((4)&0x1f);/* CAM_ID(MAC_ID) */ - - ptxdesc->txdw1 |= cpu_to_le32((6<<16) & 0x000f0000);/* raid */ - - /* offset 8 */ - - /* offset 12 */ - ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000); - - /* offset 16 */ - ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */ - - /* offset 20 */ - ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate23a(pmlmeext->tx_rate)); - } - - /* (1) The sequence number of each non-Qos frame / broadcast / multicast / */ - /* mgnt frame should be controlled by Hw because Fw will also send null data */ - /* which we cannot control when Fw LPS enable. */ - /* --> default enable non-Qos data sequense number. 2010.06.23. by tynli. */ - /* (2) Enable HW SEQ control for beacon packet, because we use Hw beacon. */ - /* (3) Use HW Qos SEQ to control the seq num of Ext port non-Qos packets. */ - if (!pattrib->qos_en) { - /* Hw set sequence number */ - ptxdesc->txdw4 |= cpu_to_le32(BIT(7)); - /* set bit3 to 1. */ - ptxdesc->txdw3 |= cpu_to_le32((8 << 28)); - } - - /* offset 0 */ - ptxdesc->txdw0 |= cpu_to_le32(sz&0x0000ffff); - ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG); - ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE+OFFSET_SZ)<<OFFSET_SHT)&0x00ff0000);/* 32 bytes for TX Desc */ - - if (bmcst) - ptxdesc->txdw0 |= cpu_to_le32(BIT(24)); - - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "offset0-txdesc = 0x%x\n", ptxdesc->txdw0); - - /* offset 4 */ - /* pkt_offset, unit:8 bytes padding */ - if (pxmitframe->pkt_offset > 0) - ptxdesc->txdw1 |= cpu_to_le32((pxmitframe->pkt_offset << 26) & 0x7c000000); - - rtl8192cu_cal_txdesc_chksum(ptxdesc); - return pull; -} - -static int rtw_dump_xframe(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - int ret = _SUCCESS; - int inner_ret = _SUCCESS; - int t, sz, w_sz, pull = 0; - u8 *mem_addr; - u32 ff_hwaddr; - struct xmit_buf *pxmitbuf = pxmitframe->pxmitbuf; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - if (pxmitframe->frame_tag == DATA_FRAMETAG && - pxmitframe->attrib.ether_type != ETH_P_ARP && - pxmitframe->attrib.ether_type != ETH_P_PAE && - pxmitframe->attrib.dhcp_pkt != 1) - rtw_issue_addbareq_cmd23a(padapter, pxmitframe); - - mem_addr = pxmitframe->buf_addr; - - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, "rtw_dump_xframe()\n"); - - 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 { - /* no frag */ - sz = pattrib->last_txcmdsz; - } - - pull = update_txdesc(pxmitframe, mem_addr, sz); - - if (pull) { - mem_addr += PACKET_OFFSET_SZ; /* pull txdesc head */ - - pxmitframe->buf_addr = mem_addr; - - w_sz = sz + TXDESC_SIZE; - } else { - w_sz = sz + TXDESC_SIZE + PACKET_OFFSET_SZ; - } - - ff_hwaddr = rtw_get_ff_hwaddr23a(pxmitframe); - inner_ret = rtl8723au_write_port(padapter, ff_hwaddr, - w_sz, pxmitbuf); - rtw_count_tx_stats23a(padapter, 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 = PTR_ALIGN(mem_addr, 4); - } - - rtw_free_xmitframe23a(pxmitpriv, pxmitframe); - - if (ret != _SUCCESS) - rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_UNKNOWN); - - return ret; -} - -bool rtl8723au_xmitframe_complete(struct rtw_adapter *padapter, - struct xmit_priv *pxmitpriv, - struct xmit_buf *pxmitbuf) -{ - struct hw_xmit *phwxmits; - struct xmit_frame *pxmitframe; - int hwentry; - int res = _SUCCESS, xcnt = 0; - - phwxmits = pxmitpriv->hwxmits; - hwentry = pxmitpriv->hwxmit_entry; - - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, "xmitframe_complete()\n"); - - if (pxmitbuf == NULL) { - pxmitbuf = rtw_alloc_xmitbuf23a(pxmitpriv); - if (!pxmitbuf) - return false; - } - pxmitframe = rtw_dequeue_xframe23a(pxmitpriv, phwxmits, hwentry); - - if (pxmitframe) { - pxmitframe->pxmitbuf = pxmitbuf; - - pxmitframe->buf_addr = pxmitbuf->pbuf; - - pxmitbuf->priv_data = pxmitframe; - - if (pxmitframe->frame_tag == DATA_FRAMETAG) { - if (pxmitframe->attrib.priority <= 15)/* TID0~15 */ - res = rtw_xmitframe_coalesce23a(padapter, pxmitframe->pkt, pxmitframe); - - rtw_os_xmit_complete23a(padapter, pxmitframe);/* always return ndis_packet after rtw_xmitframe_coalesce23a */ - } - - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "xmitframe_complete(): rtw_dump_xframe\n"); - - if (res == _SUCCESS) { - rtw_dump_xframe(padapter, pxmitframe); - } else { - rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf); - rtw_free_xmitframe23a(pxmitpriv, pxmitframe); - } - xcnt++; - } else { - rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf); - return false; - } - return true; -} - -static int xmitframe_direct(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - int res; - - res = rtw_xmitframe_coalesce23a(padapter, pxmitframe->pkt, pxmitframe); - if (res == _SUCCESS) - rtw_dump_xframe(padapter, pxmitframe); - return res; -} - -/* - * Return - * true dump packet directly - * false enqueue packet - */ -bool rtl8723au_hal_xmit(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - int res; - struct xmit_buf *pxmitbuf = NULL; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - pattrib->qsel = pattrib->priority; - spin_lock_bh(&pxmitpriv->lock); - -#ifdef CONFIG_8723AU_AP_MODE - if (xmitframe_enqueue_for_sleeping_sta23a(padapter, pxmitframe)) { - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - - spin_unlock_bh(&pxmitpriv->lock); - - if (pattrib->psta) - psta = pattrib->psta; - else - psta = rtw_get_stainfo23a(pstapriv, pattrib->ra); - - if (psta) { - if (psta->sleepq_len > (NR_XMITFRAME>>3)) - wakeup_sta_to_xmit23a(padapter, psta); - } - - return false; - } -#endif - - if (rtw_txframes_sta_ac_pending23a(padapter, pattrib) > 0) - goto enqueue; - - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == true) - goto enqueue; - - pxmitbuf = rtw_alloc_xmitbuf23a(pxmitpriv); - if (pxmitbuf == NULL) - goto enqueue; - - spin_unlock_bh(&pxmitpriv->lock); - - pxmitframe->pxmitbuf = pxmitbuf; - pxmitframe->buf_addr = pxmitbuf->pbuf; - pxmitbuf->priv_data = pxmitframe; - - if (xmitframe_direct(padapter, pxmitframe) != _SUCCESS) { - rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf); - rtw_free_xmitframe23a(pxmitpriv, pxmitframe); - } - return true; - -enqueue: - res = rtw_xmitframe_enqueue23a(padapter, pxmitframe); - spin_unlock_bh(&pxmitpriv->lock); - - if (res != _SUCCESS) { - RT_TRACE(_module_xmit_osdep_c_, _drv_err_, - "pre_xmitframe: enqueue xmitframe fail\n"); - rtw_free_xmitframe23a(pxmitpriv, pxmitframe); - - /* Trick, make the statistics correct */ - pxmitpriv->tx_pkts--; - pxmitpriv->tx_drop++; - return true; - } - return false; -} - -int rtl8723au_mgnt_xmit(struct rtw_adapter *padapter, - struct xmit_frame *pmgntframe) -{ - return rtw_dump_xframe(padapter, pmgntframe); -} - -int rtl8723au_hal_xmitframe_enqueue(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - int err; - - err = rtw_xmitframe_enqueue23a(padapter, pxmitframe); - if (err != _SUCCESS) { - rtw_free_xmitframe23a(pxmitpriv, pxmitframe); - - /* Trick, make the statistics correct */ - pxmitpriv->tx_pkts--; - pxmitpriv->tx_drop++; - } else { - tasklet_hi_schedule(&pxmitpriv->xmit_tasklet); - } - return err; -} diff --git a/drivers/staging/rtl8723au/hal/usb_halinit.c b/drivers/staging/rtl8723au/hal/usb_halinit.c deleted file mode 100644 index fa47aeb..0000000 --- a/drivers/staging/rtl8723au/hal/usb_halinit.c +++ /dev/null @@ -1,1269 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _HCI_HAL_INIT_C_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <rtw_efuse.h> - -#include <HalPwrSeqCmd.h> -#include <Hal8723PwrSeq.h> -#include <rtl8723a_hal.h> -#include <linux/ieee80211.h> - -#include <usb_ops.h> - -static void phy_SsPwrSwitch92CU(struct rtw_adapter *Adapter, - enum rt_rf_power_state eRFPowerState); - -static void -_ConfigChipOutEP(struct rtw_adapter *pAdapter, u8 NumOutPipe) -{ - u8 value8; - struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter); - - pHalData->OutEpQueueSel = 0; - pHalData->OutEpNumber = 0; - - /* Normal and High queue */ - value8 = rtl8723au_read8(pAdapter, (REG_NORMAL_SIE_EP + 1)); - - if (value8 & USB_NORMAL_SIE_EP_MASK) { - pHalData->OutEpQueueSel |= TX_SELE_HQ; - pHalData->OutEpNumber++; - } - - if ((value8 >> USB_NORMAL_SIE_EP_SHIFT) & USB_NORMAL_SIE_EP_MASK) { - pHalData->OutEpQueueSel |= TX_SELE_NQ; - pHalData->OutEpNumber++; - } - - /* Low queue */ - value8 = rtl8723au_read8(pAdapter, (REG_NORMAL_SIE_EP + 2)); - if (value8 & USB_NORMAL_SIE_EP_MASK) { - pHalData->OutEpQueueSel |= TX_SELE_LQ; - pHalData->OutEpNumber++; - } - - /* TODO: Error recovery for this case */ - /* RT_ASSERT((NumOutPipe == pHalData->OutEpNumber), - ("Out EP number isn't match! %d(Descriptor) != %d (SIE reg)\n", - (u32)NumOutPipe, (u32)pHalData->OutEpNumber)); */ -} - -bool rtl8723au_chip_configure(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); - u8 NumInPipe = pdvobjpriv->RtNumInPipes; - u8 NumOutPipe = pdvobjpriv->RtNumOutPipes; - - _ConfigChipOutEP(padapter, NumOutPipe); - - /* Normal chip with one IN and one OUT doesn't have interrupt IN EP. */ - if (pHalData->OutEpNumber == 1) { - if (NumInPipe != 1) - return false; - } - - return Hal_MappingOutPipe23a(padapter, NumOutPipe); -} - -static int _InitPowerOn(struct rtw_adapter *padapter) -{ - u16 value16; - u8 value8; - - /* RSV_CTRL 0x1C[7:0] = 0x00 - unlock ISO/CLK/Power control register */ - rtl8723au_write8(padapter, REG_RSV_CTRL, 0x0); - - /* HW Power on sequence */ - if (!HalPwrSeqCmdParsing23a(padapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, - PWR_INTF_USB_MSK, rtl8723AU_card_enable_flow)) - return _FAIL; - - /* 0x04[19] = 1, suggest by Jackie 2011.05.09, reset 8051 */ - value8 = rtl8723au_read8(padapter, REG_APS_FSMCO+2); - rtl8723au_write8(padapter, REG_APS_FSMCO + 2, value8 | BIT(3)); - - /* Enable MAC DMA/WMAC/SCHEDULE/SEC block */ - /* Set CR bit10 to enable 32k calibration. Suggested by SD1 Gimmy. - Added by tynli. 2011.08.31. */ - value16 = rtl8723au_read16(padapter, REG_CR); - value16 |= (HCI_TXDMA_EN | HCI_RXDMA_EN | TXDMA_EN | RXDMA_EN | - PROTOCOL_EN | SCHEDULE_EN | MACTXEN | MACRXEN | - ENSEC | CALTMR_EN); - rtl8723au_write16(padapter, REG_CR, value16); - - /* for Efuse PG, suggest by Jackie 2011.11.23 */ - PHY_SetBBReg(padapter, REG_EFUSE_CTRL, BIT(28)|BIT(29)|BIT(30), 0x06); - - return _SUCCESS; -} - -/* Shall USB interface init this? */ -static void _InitInterrupt(struct rtw_adapter *Adapter) -{ - u32 value32; - - /* HISR - turn all on */ - value32 = 0xFFFFFFFF; - rtl8723au_write32(Adapter, REG_HISR, value32); - - /* HIMR - turn all on */ - rtl8723au_write32(Adapter, REG_HIMR, value32); -} - -static void _InitQueueReservedPage(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct registry_priv *pregistrypriv = &Adapter->registrypriv; - u32 numHQ = 0; - u32 numLQ = 0; - u32 numNQ = 0; - u32 numPubQ; - u32 value32; - u8 value8; - bool bWiFiConfig = pregistrypriv->wifi_spec; - - /* RT_ASSERT((outEPNum>= 2), ("for WMM , number of out-ep " - "must more than or equal to 2!\n")); */ - - numPubQ = bWiFiConfig ? WMM_NORMAL_PAGE_NUM_PUBQ : NORMAL_PAGE_NUM_PUBQ; - - if (pHalData->OutEpQueueSel & TX_SELE_HQ) { - numHQ = bWiFiConfig ? - WMM_NORMAL_PAGE_NUM_HPQ : NORMAL_PAGE_NUM_HPQ; - } - - if (pHalData->OutEpQueueSel & TX_SELE_LQ) { - numLQ = bWiFiConfig ? - WMM_NORMAL_PAGE_NUM_LPQ : NORMAL_PAGE_NUM_LPQ; - } - /* NOTE: This step shall be proceed before - writting REG_RQPN. */ - if (pHalData->OutEpQueueSel & TX_SELE_NQ) { - numNQ = bWiFiConfig ? - WMM_NORMAL_PAGE_NUM_NPQ : NORMAL_PAGE_NUM_NPQ; - } - value8 = (u8)_NPQ(numNQ); - rtl8723au_write8(Adapter, REG_RQPN_NPQ, value8); - - /* TX DMA */ - value32 = _HPQ(numHQ) | _LPQ(numLQ) | _PUBQ(numPubQ) | LD_RQPN; - rtl8723au_write32(Adapter, REG_RQPN, value32); -} - -static void _InitTxBufferBoundary(struct rtw_adapter *Adapter) -{ - struct registry_priv *pregistrypriv = &Adapter->registrypriv; - - u8 txpktbuf_bndy; - - if (!pregistrypriv->wifi_spec) - txpktbuf_bndy = TX_PAGE_BOUNDARY; - else /* for WMM */ - txpktbuf_bndy = WMM_NORMAL_TX_PAGE_BOUNDARY; - - rtl8723au_write8(Adapter, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy); - rtl8723au_write8(Adapter, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy); - rtl8723au_write8(Adapter, REG_TXPKTBUF_WMAC_LBK_BF_HD, txpktbuf_bndy); - rtl8723au_write8(Adapter, REG_TRXFF_BNDY, txpktbuf_bndy); - rtl8723au_write8(Adapter, REG_TDECTRL+1, txpktbuf_bndy); -} - -static void _InitPageBoundary(struct rtw_adapter *Adapter) -{ - /* RX Page Boundary */ - /* srand(static_cast<unsigned int>(time(NULL))); */ - u16 rxff_bndy = 0x27FF;/* rand() % 1) ? 0x27FF : 0x23FF; */ - - rtl8723au_write16(Adapter, (REG_TRXFF_BNDY + 2), rxff_bndy); - - /* TODO: ?? shall we set tx boundary? */ -} - -static void -_InitNormalChipRegPriority(struct rtw_adapter *Adapter, u16 beQ, u16 bkQ, - u16 viQ, u16 voQ, u16 mgtQ, u16 hiQ) -{ - u16 value16 = rtl8723au_read16(Adapter, REG_TRXDMA_CTRL) & 0x7; - - value16 |= _TXDMA_BEQ_MAP(beQ) | _TXDMA_BKQ_MAP(bkQ) | - _TXDMA_VIQ_MAP(viQ) | _TXDMA_VOQ_MAP(voQ) | - _TXDMA_MGQ_MAP(mgtQ) | _TXDMA_HIQ_MAP(hiQ); - - rtl8723au_write16(Adapter, REG_TRXDMA_CTRL, value16); -} - -static void _InitNormalChipOneOutEpPriority(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - u16 value = 0; - - switch (pHalData->OutEpQueueSel) { - case TX_SELE_HQ: - value = QUEUE_HIGH; - break; - case TX_SELE_LQ: - value = QUEUE_LOW; - break; - case TX_SELE_NQ: - value = QUEUE_NORMAL; - break; - default: - /* RT_ASSERT(false, ("Shall not reach here!\n")); */ - break; - } - - _InitNormalChipRegPriority(Adapter, value, value, value, - value, value, value); -} - -static void _InitNormalChipTwoOutEpPriority(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct registry_priv *pregistrypriv = &Adapter->registrypriv; - u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ; - u16 valueHi = 0; - u16 valueLow = 0; - - switch (pHalData->OutEpQueueSel) { - case (TX_SELE_HQ | TX_SELE_LQ): - valueHi = QUEUE_HIGH; - valueLow = QUEUE_LOW; - break; - case (TX_SELE_NQ | TX_SELE_LQ): - valueHi = QUEUE_NORMAL; - valueLow = QUEUE_LOW; - break; - case (TX_SELE_HQ | TX_SELE_NQ): - valueHi = QUEUE_HIGH; - valueLow = QUEUE_NORMAL; - break; - default: - /* RT_ASSERT(false, ("Shall not reach here!\n")); */ - break; - } - - if (!pregistrypriv->wifi_spec) { - beQ = valueLow; - bkQ = valueLow; - viQ = valueHi; - voQ = valueHi; - mgtQ = valueHi; - hiQ = valueHi; - } else {/* for WMM , CONFIG_OUT_EP_WIFI_MODE */ - beQ = valueLow; - bkQ = valueHi; - viQ = valueHi; - voQ = valueLow; - mgtQ = valueHi; - hiQ = valueHi; - } - - _InitNormalChipRegPriority(Adapter, beQ, bkQ, viQ, voQ, mgtQ, hiQ); -} - -static void _InitNormalChipThreeOutEpPriority(struct rtw_adapter *Adapter) -{ - struct registry_priv *pregistrypriv = &Adapter->registrypriv; - u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ; - - if (!pregistrypriv->wifi_spec) {/* typical setting */ - beQ = QUEUE_LOW; - bkQ = QUEUE_LOW; - viQ = QUEUE_NORMAL; - voQ = QUEUE_HIGH; - mgtQ = QUEUE_HIGH; - hiQ = QUEUE_HIGH; - } else {/* for WMM */ - beQ = QUEUE_LOW; - bkQ = QUEUE_NORMAL; - viQ = QUEUE_NORMAL; - voQ = QUEUE_HIGH; - mgtQ = QUEUE_HIGH; - hiQ = QUEUE_HIGH; - } - _InitNormalChipRegPriority(Adapter, beQ, bkQ, viQ, voQ, mgtQ, hiQ); -} - -static void _InitQueuePriority(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - - switch (pHalData->OutEpNumber) { - case 1: - _InitNormalChipOneOutEpPriority(Adapter); - break; - case 2: - _InitNormalChipTwoOutEpPriority(Adapter); - break; - case 3: - _InitNormalChipThreeOutEpPriority(Adapter); - break; - default: - /* RT_ASSERT(false, ("Shall not reach here!\n")); */ - break; - } -} - -static void _InitTransferPageSize(struct rtw_adapter *Adapter) -{ - /* Tx page size is always 128. */ - - u8 value8; - value8 = _PSRX(PBP_128) | _PSTX(PBP_128); - rtl8723au_write8(Adapter, REG_PBP, value8); -} - -static void _InitDriverInfoSize(struct rtw_adapter *Adapter, u8 drvInfoSize) -{ - rtl8723au_write8(Adapter, REG_RX_DRVINFO_SZ, drvInfoSize); -} - -static void _InitWMACSetting(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - - /* don't turn on AAP, it will allow all packets to driver */ - pHalData->ReceiveConfig = RCR_APM | RCR_AM | RCR_AB | RCR_CBSSID_DATA | - RCR_CBSSID_BCN | RCR_APP_ICV | RCR_AMF | - RCR_HTC_LOC_CTRL | RCR_APP_MIC | - RCR_APP_PHYSTS; - - /* some REG_RCR will be modified later by - phy_ConfigMACWithHeaderFile() */ - rtl8723au_write32(Adapter, REG_RCR, pHalData->ReceiveConfig); - - /* Accept all multicast address */ - rtl8723au_write32(Adapter, REG_MAR, 0xFFFFFFFF); - rtl8723au_write32(Adapter, REG_MAR + 4, 0xFFFFFFFF); - - /* Accept all data frames */ - /* value16 = 0xFFFF; */ - /* rtl8723au_write16(Adapter, REG_RXFLTMAP2, value16); */ - - /* 2010.09.08 hpfan */ - /* Since ADF is removed from RCR, ps-poll will not be indicate - to driver, */ - /* RxFilterMap should mask ps-poll to guarantee AP mode can - rx ps-poll. */ - /* value16 = 0x400; */ - /* rtl8723au_write16(Adapter, REG_RXFLTMAP1, value16); */ - - /* Accept all management frames */ - /* value16 = 0xFFFF; */ - /* rtl8723au_write16(Adapter, REG_RXFLTMAP0, value16); */ - - /* enable RX_SHIFT bits */ - /* rtl8723au_write8(Adapter, REG_TRXDMA_CTRL, rtl8723au_read8(Adapter, - REG_TRXDMA_CTRL)|BIT(1)); */ -} - -static void _InitAdaptiveCtrl(struct rtw_adapter *Adapter) -{ - u16 value16; - u32 value32; - - /* Response Rate Set */ - value32 = rtl8723au_read32(Adapter, REG_RRSR); - value32 &= ~RATE_BITMAP_ALL; - value32 |= RATE_RRSR_CCK_ONLY_1M; - rtl8723au_write32(Adapter, REG_RRSR, value32); - - /* CF-END Threshold */ - /* m_spIoBase->rtl8723au_write8(REG_CFEND_TH, 0x1); */ - - /* SIFS (used in NAV) */ - value16 = _SPEC_SIFS_CCK(0x10) | _SPEC_SIFS_OFDM(0x10); - rtl8723au_write16(Adapter, REG_SPEC_SIFS, value16); - - /* Retry Limit */ - value16 = _LRL(0x30) | _SRL(0x30); - rtl8723au_write16(Adapter, REG_RL, value16); -} - -static void _InitRateFallback(struct rtw_adapter *Adapter) -{ - /* Set Data Auto Rate Fallback Retry Count register. */ - rtl8723au_write32(Adapter, REG_DARFRC, 0x00000000); - rtl8723au_write32(Adapter, REG_DARFRC+4, 0x10080404); - rtl8723au_write32(Adapter, REG_RARFRC, 0x04030201); - rtl8723au_write32(Adapter, REG_RARFRC+4, 0x08070605); -} - -static void _InitEDCA(struct rtw_adapter *Adapter) -{ - /* Set Spec SIFS (used in NAV) */ - rtl8723au_write16(Adapter, REG_SPEC_SIFS, 0x100a); - rtl8723au_write16(Adapter, REG_MAC_SPEC_SIFS, 0x100a); - - /* Set SIFS for CCK */ - rtl8723au_write16(Adapter, REG_SIFS_CTX, 0x100a); - - /* Set SIFS for OFDM */ - rtl8723au_write16(Adapter, REG_SIFS_TRX, 0x100a); - - /* TXOP */ - rtl8723au_write32(Adapter, REG_EDCA_BE_PARAM, 0x005EA42B); - rtl8723au_write32(Adapter, REG_EDCA_BK_PARAM, 0x0000A44F); - rtl8723au_write32(Adapter, REG_EDCA_VI_PARAM, 0x005EA324); - rtl8723au_write32(Adapter, REG_EDCA_VO_PARAM, 0x002FA226); -} - -static void _InitRDGSetting(struct rtw_adapter *Adapter) -{ - rtl8723au_write8(Adapter, REG_RD_CTRL, 0xFF); - rtl8723au_write16(Adapter, REG_RD_NAV_NXT, 0x200); - rtl8723au_write8(Adapter, REG_RD_RESP_PKT_TH, 0x05); -} - -static void _InitRetryFunction(struct rtw_adapter *Adapter) -{ - u8 value8; - - value8 = rtl8723au_read8(Adapter, REG_FWHW_TXQ_CTRL); - value8 |= EN_AMPDU_RTY_NEW; - rtl8723au_write8(Adapter, REG_FWHW_TXQ_CTRL, value8); - - /* Set ACK timeout */ - rtl8723au_write8(Adapter, REG_ACKTO, 0x40); -} - -static void _InitRFType(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - - pHalData->rf_type = RF_1T1R; -} - -/* Set CCK and OFDM Block "ON" */ -static void _BBTurnOnBlock(struct rtw_adapter *Adapter) -{ - PHY_SetBBReg(Adapter, rFPGA0_RFMOD, bCCKEn, 0x1); - PHY_SetBBReg(Adapter, rFPGA0_RFMOD, bOFDMEn, 0x1); -} - -#define MgntActSet_RF_State(...) -static void _RfPowerSave(struct rtw_adapter *padapter) -{ -} - -enum { - Antenna_Lfet = 1, - Antenna_Right = 2, -}; - -enum rt_rf_power_state RfOnOffDetect23a(struct rtw_adapter *pAdapter) -{ - /* struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter); */ - u8 val8; - enum rt_rf_power_state rfpowerstate = rf_off; - - rtl8723au_write8(pAdapter, REG_MAC_PINMUX_CFG, - rtl8723au_read8(pAdapter, - REG_MAC_PINMUX_CFG) & ~BIT(3)); - val8 = rtl8723au_read8(pAdapter, REG_GPIO_IO_SEL); - DBG_8723A("GPIO_IN =%02x\n", val8); - rfpowerstate = (val8 & BIT(3)) ? rf_on : rf_off; - - return rfpowerstate; -} - -int rtl8723au_hal_init(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - struct pwrctrl_priv *pwrctrlpriv = &Adapter->pwrctrlpriv; - struct registry_priv *pregistrypriv = &Adapter->registrypriv; - u8 val8 = 0; - u32 boundary; - int status = _SUCCESS; - bool mac_on; - - unsigned long init_start_time = jiffies; - - Adapter->hw_init_completed = false; - - if (Adapter->pwrctrlpriv.bkeepfwalive) { - phy_SsPwrSwitch92CU(Adapter, rf_on); - - if (pHalData->bIQKInitialized) { - rtl8723a_phy_iq_calibrate(Adapter, true); - } else { - rtl8723a_phy_iq_calibrate(Adapter, false); - pHalData->bIQKInitialized = true; - } - rtl8723a_odm_check_tx_power_tracking(Adapter); - rtl8723a_phy_lc_calibrate(Adapter); - - goto exit; - } - - /* Check if MAC has already power on. by tynli. 2011.05.27. */ - val8 = rtl8723au_read8(Adapter, REG_CR); - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "%s: REG_CR 0x100 = 0x%02x\n", __func__, val8); - /* Fix 92DU-VC S3 hang with the reason is that secondary mac is not - initialized. */ - /* 0x100 value of first mac is 0xEA while 0x100 value of secondary - is 0x00 */ - if (val8 == 0xEA) { - mac_on = false; - } else { - mac_on = true; - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "%s: MAC has already power on\n", __func__); - } - - status = _InitPowerOn(Adapter); - if (status == _FAIL) { - RT_TRACE(_module_hci_hal_init_c_, _drv_err_, - "Failed to init power on!\n"); - goto exit; - } - - if (!pregistrypriv->wifi_spec) { - boundary = TX_PAGE_BOUNDARY; - } else { - /* for WMM */ - boundary = WMM_NORMAL_TX_PAGE_BOUNDARY; - } - - if (!mac_on) { - status = InitLLTTable23a(Adapter, boundary); - if (status == _FAIL) { - RT_TRACE(_module_hci_hal_init_c_, _drv_err_, - "Failed to init LLT table\n"); - goto exit; - } - } - - if (pHalData->bRDGEnable) - _InitRDGSetting(Adapter); - - status = rtl8723a_FirmwareDownload(Adapter); - if (status != _SUCCESS) { - Adapter->bFWReady = false; - DBG_8723A("fw download fail!\n"); - goto exit; - } else { - Adapter->bFWReady = true; - DBG_8723A("fw download ok!\n"); - } - - rtl8723a_InitializeFirmwareVars(Adapter); - - if (pwrctrlpriv->reg_rfoff == true) { - pwrctrlpriv->rf_pwrstate = rf_off; - } - - /* 2010/08/09 MH We need to check if we need to turnon or off RF after detecting */ - /* HW GPIO pin. Before PHY_RFConfig8192C. */ - /* HalDetectPwrDownMode(Adapter); */ - /* 2010/08/26 MH If Efuse does not support sective suspend then disable the function. */ - /* HalDetectSelectiveSuspendMode(Adapter); */ - - /* Set RF type for BB/RF configuration */ - _InitRFType(Adapter);/* _ReadRFType() */ - - /* Save target channel */ - /* <Roger_Notes> Current Channel will be updated again later. */ - pHalData->CurrentChannel = 6;/* default set to 6 */ - - status = PHY_MACConfig8723A(Adapter); - if (status == _FAIL) { - DBG_8723A("PHY_MACConfig8723A fault !!\n"); - goto exit; - } - - /* */ - /* d. Initialize BB related configurations. */ - /* */ - status = PHY_BBConfig8723A(Adapter); - if (status == _FAIL) { - DBG_8723A("PHY_BBConfig8723A fault !!\n"); - goto exit; - } - - /* Add for tx power by rate fine tune. We need to call the function after BB config. */ - /* Because the tx power by rate table is inited in BB config. */ - - status = PHY_RF6052_Config8723A(Adapter); - if (status == _FAIL) { - DBG_8723A("PHY_RF6052_Config8723A failed!!\n"); - goto exit; - } - - /* reducing 80M spur */ - rtl8723au_write32(Adapter, REG_AFE_XTAL_CTRL, 0x0381808d); - rtl8723au_write32(Adapter, REG_AFE_PLL_CTRL, 0xf0ffff83); - rtl8723au_write32(Adapter, REG_AFE_PLL_CTRL, 0xf0ffff82); - rtl8723au_write32(Adapter, REG_AFE_PLL_CTRL, 0xf0ffff83); - - /* RFSW Control */ - /* 0x804[14]= 0 */ - rtl8723au_write32(Adapter, rFPGA0_TxInfo, 0x00000003); - /* 0x870[6:5]= b'11 */ - rtl8723au_write32(Adapter, rFPGA0_XAB_RFInterfaceSW, 0x07000760); - /* 0x860[6:5]= b'00 */ - rtl8723au_write32(Adapter, rFPGA0_XA_RFInterfaceOE, 0x66F60210); - - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "%s: 0x870 = value 0x%x\n", __func__, - rtl8723au_read32(Adapter, 0x870)); - - /* */ - /* Joseph Note: Keep RfRegChnlVal for later use. */ - /* */ - pHalData->RfRegChnlVal[0] = PHY_QueryRFReg(Adapter, RF_PATH_A, - RF_CHNLBW, bRFRegOffsetMask); - pHalData->RfRegChnlVal[1] = PHY_QueryRFReg(Adapter, RF_PATH_B, - RF_CHNLBW, bRFRegOffsetMask); - - if (!mac_on) { - _InitQueueReservedPage(Adapter); - _InitTxBufferBoundary(Adapter); - } - _InitQueuePriority(Adapter); - _InitPageBoundary(Adapter); - _InitTransferPageSize(Adapter); - - /* Get Rx PHY status in order to report RSSI and others. */ - _InitDriverInfoSize(Adapter, DRVINFO_SZ); - - _InitInterrupt(Adapter); - hw_var_set_macaddr(Adapter, Adapter->eeprompriv.mac_addr); - rtl8723a_set_media_status(Adapter, MSR_INFRA); - _InitWMACSetting(Adapter); - _InitAdaptiveCtrl(Adapter); - _InitEDCA(Adapter); - _InitRateFallback(Adapter); - _InitRetryFunction(Adapter); - rtl8723a_InitBeaconParameters(Adapter); - - _BBTurnOnBlock(Adapter); - /* NicIFSetMacAddress(padapter, padapter->PermanentAddress); */ - - rtl8723a_cam_invalidate_all(Adapter); - - /* 2010/12/17 MH We need to set TX power according to EFUSE content at first. */ - PHY_SetTxPowerLevel8723A(Adapter, pHalData->CurrentChannel); - - rtl8723a_InitAntenna_Selection(Adapter); - - /* HW SEQ CTRL */ - /* set 0x0 to 0xFF by tynli. Default enable HW SEQ NUM. */ - rtl8723au_write8(Adapter, REG_HWSEQ_CTRL, 0xFF); - - /* */ - /* Disable BAR, suggested by Scott */ - /* 2010.04.09 add by hpfan */ - /* */ - rtl8723au_write32(Adapter, REG_BAR_MODE_CTRL, 0x0201ffff); - - if (pregistrypriv->wifi_spec) - rtl8723au_write16(Adapter, REG_FAST_EDCA_CTRL, 0); - - /* Move by Neo for USB SS from above setp */ - _RfPowerSave(Adapter); - - /* 2010/08/26 MH Merge from 8192CE. */ - /* sherry masked that it has been done in _RfPowerSave */ - /* 20110927 */ - /* recovery for 8192cu and 9723Au 20111017 */ - if (pwrctrlpriv->rf_pwrstate == rf_on) { - if (pHalData->bIQKInitialized) { - rtl8723a_phy_iq_calibrate(Adapter, true); - } else { - rtl8723a_phy_iq_calibrate(Adapter, false); - pHalData->bIQKInitialized = true; - } - - rtl8723a_odm_check_tx_power_tracking(Adapter); - - rtl8723a_phy_lc_calibrate(Adapter); - - rtl8723a_dual_antenna_detection(Adapter); - } - - /* fixed USB interface interference issue */ - rtl8723au_write8(Adapter, 0xfe40, 0xe0); - rtl8723au_write8(Adapter, 0xfe41, 0x8d); - rtl8723au_write8(Adapter, 0xfe42, 0x80); - rtl8723au_write32(Adapter, 0x20c, 0xfd0320); - /* Solve too many protocol error on USB bus */ - if (!IS_81xxC_VENDOR_UMC_A_CUT(pHalData->VersionID)) { - /* 0xE6 = 0x94 */ - rtl8723au_write8(Adapter, 0xFE40, 0xE6); - rtl8723au_write8(Adapter, 0xFE41, 0x94); - rtl8723au_write8(Adapter, 0xFE42, 0x80); - - /* 0xE0 = 0x19 */ - rtl8723au_write8(Adapter, 0xFE40, 0xE0); - rtl8723au_write8(Adapter, 0xFE41, 0x19); - rtl8723au_write8(Adapter, 0xFE42, 0x80); - - /* 0xE5 = 0x91 */ - rtl8723au_write8(Adapter, 0xFE40, 0xE5); - rtl8723au_write8(Adapter, 0xFE41, 0x91); - rtl8723au_write8(Adapter, 0xFE42, 0x80); - - /* 0xE2 = 0x81 */ - rtl8723au_write8(Adapter, 0xFE40, 0xE2); - rtl8723au_write8(Adapter, 0xFE41, 0x81); - rtl8723au_write8(Adapter, 0xFE42, 0x80); - - } - -/* _InitPABias(Adapter); */ - - /* Init BT hw config. */ - rtl8723a_BT_init_hwconfig(Adapter); - - rtl8723a_InitHalDm(Adapter); - - val8 = DIV_ROUND_UP(WiFiNavUpperUs, HAL_8723A_NAV_UPPER_UNIT); - rtl8723au_write8(Adapter, REG_NAV_UPPER, val8); - - /* 2011/03/09 MH debug only, UMC-B cut pass 2500 S5 test, but we need to fin root cause. */ - if (((rtl8723au_read32(Adapter, rFPGA0_RFMOD) & 0xFF000000) != - 0x83000000)) { - PHY_SetBBReg(Adapter, rFPGA0_RFMOD, BIT(24), 1); - RT_TRACE(_module_hci_hal_init_c_, _drv_err_, - "%s: IQK fail recover\n", __func__); - } - - /* ack for xmit mgmt frames. */ - rtl8723au_write32(Adapter, REG_FWHW_TXQ_CTRL, - rtl8723au_read32(Adapter, REG_FWHW_TXQ_CTRL)|BIT(12)); - -exit: - if (status == _SUCCESS) { - Adapter->hw_init_completed = true; - - if (Adapter->registrypriv.notch_filter == 1) - rtl8723a_notch_filter(Adapter, 1); - } - - DBG_8723A("%s in %dms\n", __func__, - jiffies_to_msecs(jiffies - init_start_time)); - return status; -} - -static void phy_SsPwrSwitch92CU(struct rtw_adapter *Adapter, - enum rt_rf_power_state eRFPowerState) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - u8 sps0; - - sps0 = rtl8723au_read8(Adapter, REG_SPS0_CTRL); - - switch (eRFPowerState) { - case rf_on: - /* 1. Enable MAC Clock. Can not be enabled now. */ - /* WriteXBYTE(REG_SYS_CLKR+1, - ReadXBYTE(REG_SYS_CLKR+1) | BIT(3)); */ - - /* 2. Force PWM, Enable SPS18_LDO_Marco_Block */ - rtl8723au_write8(Adapter, REG_SPS0_CTRL, - sps0 | BIT(0) | BIT(3)); - - /* 3. restore BB, AFE control register. */ - /* RF */ - if (pHalData->rf_type == RF_2T2R) - PHY_SetBBReg(Adapter, rFPGA0_XAB_RFParameter, - 0x380038, 1); - else - PHY_SetBBReg(Adapter, rFPGA0_XAB_RFParameter, - 0x38, 1); - PHY_SetBBReg(Adapter, rOFDM0_TRxPathEnable, 0xf0, 1); - PHY_SetBBReg(Adapter, rFPGA0_RFMOD, BIT(1), 0); - - /* AFE */ - if (pHalData->rf_type == RF_2T2R) - rtl8723au_write32(Adapter, rRx_Wait_CCA, 0x63DB25A0); - else if (pHalData->rf_type == RF_1T1R) - rtl8723au_write32(Adapter, rRx_Wait_CCA, 0x631B25A0); - - /* 4. issue 3-wire command that RF set to Rx idle - mode. This is used to re-write the RX idle mode. */ - /* We can only prvide a usual value instead and then - HW will modify the value by itself. */ - PHY_SetRFReg(Adapter, RF_PATH_A, RF_AC, - bRFRegOffsetMask, 0x32D95); - if (pHalData->rf_type == RF_2T2R) { - PHY_SetRFReg(Adapter, RF_PATH_B, RF_AC, - bRFRegOffsetMask, 0x32D95); - } - break; - case rf_sleep: - case rf_off: - if (IS_81xxC_VENDOR_UMC_B_CUT(pHalData->VersionID)) - sps0 &= ~BIT(0); - else - sps0 &= ~(BIT(0) | BIT(3)); - - RT_TRACE(_module_hal_init_c_, _drv_err_, "SS LVL1\n"); - /* Disable RF and BB only for SelectSuspend. */ - - /* 1. Set BB/RF to shutdown. */ - /* (1) Reg878[5:3]= 0 RF rx_code for - preamble power saving */ - /* (2)Reg878[21:19]= 0 Turn off RF-B */ - /* (3) RegC04[7:4]= 0 Turn off all paths - for packet detection */ - /* (4) Reg800[1] = 1 enable preamble power saving */ - Adapter->pwrctrlpriv.PS_BBRegBackup[PSBBREG_RF0] = - rtl8723au_read32(Adapter, rFPGA0_XAB_RFParameter); - Adapter->pwrctrlpriv.PS_BBRegBackup[PSBBREG_RF1] = - rtl8723au_read32(Adapter, rOFDM0_TRxPathEnable); - Adapter->pwrctrlpriv.PS_BBRegBackup[PSBBREG_RF2] = - rtl8723au_read32(Adapter, rFPGA0_RFMOD); - if (pHalData->rf_type == RF_2T2R) - PHY_SetBBReg(Adapter, rFPGA0_XAB_RFParameter, - 0x380038, 0); - else if (pHalData->rf_type == RF_1T1R) - PHY_SetBBReg(Adapter, rFPGA0_XAB_RFParameter, 0x38, 0); - PHY_SetBBReg(Adapter, rOFDM0_TRxPathEnable, 0xf0, 0); - PHY_SetBBReg(Adapter, rFPGA0_RFMOD, BIT(1), 1); - - /* 2 .AFE control register to power down. bit[30:22] */ - Adapter->pwrctrlpriv.PS_BBRegBackup[PSBBREG_AFE0] = - rtl8723au_read32(Adapter, rRx_Wait_CCA); - if (pHalData->rf_type == RF_2T2R) - rtl8723au_write32(Adapter, rRx_Wait_CCA, 0x00DB25A0); - else if (pHalData->rf_type == RF_1T1R) - rtl8723au_write32(Adapter, rRx_Wait_CCA, 0x001B25A0); - - /* 3. issue 3-wire command that RF set to power down.*/ - PHY_SetRFReg(Adapter, RF_PATH_A, RF_AC, bRFRegOffsetMask, 0); - if (pHalData->rf_type == RF_2T2R) - PHY_SetRFReg(Adapter, RF_PATH_B, RF_AC, - bRFRegOffsetMask, 0); - - /* 4. Force PFM , disable SPS18_LDO_Marco_Block */ - rtl8723au_write8(Adapter, REG_SPS0_CTRL, sps0); - break; - default: - break; - } -} - -static void CardDisableRTL8723U(struct rtw_adapter *Adapter) -{ - u8 u1bTmp; - - DBG_8723A("CardDisableRTL8723U\n"); - /* USB-MF Card Disable Flow */ - /* 1. Run LPS WL RFOFF flow */ - HalPwrSeqCmdParsing23a(Adapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, - PWR_INTF_USB_MSK, rtl8723AU_enter_lps_flow); - - /* 2. 0x1F[7:0] = 0 turn off RF */ - rtl8723au_write8(Adapter, REG_RF_CTRL, 0x00); - - /* ==== Reset digital sequence ====== */ - if ((rtl8723au_read8(Adapter, REG_MCUFWDL) & BIT(7)) && - Adapter->bFWReady) /* 8051 RAM code */ - rtl8723a_FirmwareSelfReset(Adapter); - - /* Reset MCU. Suggested by Filen. 2011.01.26. by tynli. */ - u1bTmp = rtl8723au_read8(Adapter, REG_SYS_FUNC_EN+1); - rtl8723au_write8(Adapter, REG_SYS_FUNC_EN+1, u1bTmp & ~BIT(2)); - - /* g. MCUFWDL 0x80[1:0]= 0 reset MCU ready status */ - rtl8723au_write8(Adapter, REG_MCUFWDL, 0x00); - - /* ==== Reset digital sequence end ====== */ - /* Card disable power action flow */ - HalPwrSeqCmdParsing23a(Adapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, - PWR_INTF_USB_MSK, - rtl8723AU_card_disable_flow); - - /* Reset MCU IO Wrapper, added by Roger, 2011.08.30. */ - u1bTmp = rtl8723au_read8(Adapter, REG_RSV_CTRL + 1); - rtl8723au_write8(Adapter, REG_RSV_CTRL+1, u1bTmp & ~BIT(0)); - u1bTmp = rtl8723au_read8(Adapter, REG_RSV_CTRL + 1); - rtl8723au_write8(Adapter, REG_RSV_CTRL+1, u1bTmp | BIT(0)); - - /* 7. RSV_CTRL 0x1C[7:0] = 0x0E lock ISO/CLK/Power control register */ - rtl8723au_write8(Adapter, REG_RSV_CTRL, 0x0e); -} - -int rtl8723au_hal_deinit(struct rtw_adapter *padapter) -{ - DBG_8723A("==> %s\n", __func__); - -#ifdef CONFIG_8723AU_BT_COEXIST - BT_HaltProcess(padapter); -#endif - /* 2011/02/18 To Fix RU LNA power leakage problem. We need to - execute below below in Adapter init and halt sequence. - According to EEchou's opinion, we can enable the ability for all */ - /* IC. Accord to johnny's opinion, only RU need the support. */ - CardDisableRTL8723U(padapter); - - padapter->hw_init_completed = false; - - return _SUCCESS; -} - -int rtl8723au_inirp_init(struct rtw_adapter *Adapter) -{ - u8 i; - struct recv_buf *precvbuf; - int status; - struct recv_priv *precvpriv = &Adapter->recvpriv; - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - - status = _SUCCESS; - - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, "===> usb_inirp_init\n"); - - /* issue Rx irp to receive data */ - precvbuf = (struct recv_buf *)precvpriv->precv_buf; - for (i = 0; i < NR_RECVBUFF; i++) { - if (rtl8723au_read_port(Adapter, 0, precvbuf) == _FAIL) { - RT_TRACE(_module_hci_hal_init_c_, _drv_err_, - "usb_rx_init: usb_read_port error\n"); - status = _FAIL; - goto exit; - } - precvbuf++; - } - if (rtl8723au_read_interrupt(Adapter) == _FAIL) { - RT_TRACE(_module_hci_hal_init_c_, _drv_err_, - "%s: usb_read_interrupt error\n", __func__); - status = _FAIL; - } - pHalData->IntrMask[0] = rtl8723au_read32(Adapter, REG_USB_HIMR); - MSG_8723A("pHalData->IntrMask = 0x%04x\n", pHalData->IntrMask[0]); - pHalData->IntrMask[0] |= UHIMR_C2HCMD|UHIMR_CPWM; - rtl8723au_write32(Adapter, REG_USB_HIMR, pHalData->IntrMask[0]); -exit: - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "<=== usb_inirp_init\n"); - return status; -} - -int rtl8723au_inirp_deinit(struct rtw_adapter *Adapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "===> usb_rx_deinit\n"); - rtl8723au_read_port_cancel(Adapter); - pHalData->IntrMask[0] = rtl8723au_read32(Adapter, REG_USB_HIMR); - MSG_8723A("%s pHalData->IntrMask = 0x%04x\n", __func__, - pHalData->IntrMask[0]); - pHalData->IntrMask[0] = 0x0; - rtl8723au_write32(Adapter, REG_USB_HIMR, pHalData->IntrMask[0]); - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - "<=== usb_rx_deinit\n"); - return _SUCCESS; -} - -static void _ReadBoardType(struct rtw_adapter *Adapter, u8 *PROMContent, - bool AutoloadFail) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - u8 boardType = BOARD_USB_DONGLE; - - if (AutoloadFail) { - if (IS_8723_SERIES(pHalData->VersionID)) - pHalData->rf_type = RF_1T1R; - else - pHalData->rf_type = RF_2T2R; - pHalData->BoardType = boardType; - return; - } - - boardType = PROMContent[EEPROM_NORMAL_BoardType]; - boardType &= BOARD_TYPE_NORMAL_MASK;/* bit[7:5] */ - boardType >>= 5; - - pHalData->BoardType = boardType; - MSG_8723A("_ReadBoardType(%x)\n", pHalData->BoardType); - - if (boardType == BOARD_USB_High_PA) - pHalData->ExternalPA = 1; -} - -static void Hal_EfuseParseMACAddr_8723AU(struct rtw_adapter *padapter, - u8 *hwinfo, bool AutoLoadFail) -{ - u16 i; - u8 sMacAddr[ETH_ALEN] = {0x00, 0xE0, 0x4C, 0x87, 0x23, 0x00}; - struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter); - - if (AutoLoadFail) { - for (i = 0; i < 6; i++) - pEEPROM->mac_addr[i] = sMacAddr[i]; - } else { - /* Read Permanent MAC address */ - memcpy(pEEPROM->mac_addr, &hwinfo[EEPROM_MAC_ADDR_8723AU], - ETH_ALEN); - } - - RT_TRACE(_module_hci_hal_init_c_, _drv_notice_, - "Hal_EfuseParseMACAddr_8723AU: Permanent Address =%pM\n", - pEEPROM->mac_addr); -} - -static void readAdapterInfo(struct rtw_adapter *padapter) -{ - struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter); - /* struct hal_data_8723a * pHalData = GET_HAL_DATA(padapter); */ - u8 hwinfo[HWSET_MAX_SIZE]; - - Hal_InitPGData(padapter, hwinfo); - Hal_EfuseParseIDCode(padapter, hwinfo); - Hal_EfuseParseEEPROMVer(padapter, hwinfo, - pEEPROM->bautoload_fail_flag); - Hal_EfuseParseMACAddr_8723AU(padapter, hwinfo, - pEEPROM->bautoload_fail_flag); - Hal_EfuseParsetxpowerinfo_8723A(padapter, hwinfo, - pEEPROM->bautoload_fail_flag); - _ReadBoardType(padapter, hwinfo, pEEPROM->bautoload_fail_flag); - Hal_EfuseParseBTCoexistInfo_8723A(padapter, hwinfo, - pEEPROM->bautoload_fail_flag); - - rtl8723a_EfuseParseChnlPlan(padapter, hwinfo, - pEEPROM->bautoload_fail_flag); - Hal_EfuseParseThermalMeter_8723A(padapter, hwinfo, - pEEPROM->bautoload_fail_flag); -/* _ReadRFSetting(Adapter, PROMContent, pEEPROM->bautoload_fail_flag); */ -/* _ReadPSSetting(Adapter, PROMContent, pEEPROM->bautoload_fail_flag); */ - Hal_EfuseParseAntennaDiversity(padapter, hwinfo, - pEEPROM->bautoload_fail_flag); - - Hal_EfuseParseEEPROMVer(padapter, hwinfo, pEEPROM->bautoload_fail_flag); - Hal_EfuseParseCustomerID(padapter, hwinfo, - pEEPROM->bautoload_fail_flag); - Hal_EfuseParseRateIndicationOption(padapter, hwinfo, - pEEPROM->bautoload_fail_flag); - Hal_EfuseParseXtal_8723A(padapter, hwinfo, - pEEPROM->bautoload_fail_flag); - - /* hal_CustomizedBehavior_8723U(Adapter); */ - -/* Adapter->bDongle = (PROMContent[EEPROM_EASY_REPLACEMENT] == 1)? 0: 1; */ - DBG_8723A("%s(): REPLACEMENT = %x\n", __func__, padapter->bDongle); -} - -static void _ReadPROMContent(struct rtw_adapter *Adapter) -{ - struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(Adapter); - u8 eeValue; - - eeValue = rtl8723au_read8(Adapter, REG_9346CR); - /* To check system boot selection. */ - pEEPROM->EepromOrEfuse = (eeValue & BOOT_FROM_EEPROM) ? true : false; - pEEPROM->bautoload_fail_flag = (eeValue & EEPROM_EN) ? false : true; - - DBG_8723A("Boot from %s, Autoload %s !\n", - (pEEPROM->EepromOrEfuse ? "EEPROM" : "EFUSE"), - (pEEPROM->bautoload_fail_flag ? "Fail" : "OK")); - - readAdapterInfo(Adapter); -} - -/* */ -/* Description: */ -/* We should set Efuse cell selection to WiFi cell in default. */ -/* */ -/* Assumption: */ -/* PASSIVE_LEVEL */ -/* */ -/* Added by Roger, 2010.11.23. */ -/* */ -static void hal_EfuseCellSel(struct rtw_adapter *Adapter) -{ - u32 value32; - - value32 = rtl8723au_read32(Adapter, EFUSE_TEST); - value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_WIFI_SEL_0); - rtl8723au_write32(Adapter, EFUSE_TEST, value32); -} - -void rtl8723a_read_adapter_info(struct rtw_adapter *Adapter) -{ - unsigned long start = jiffies; - - /* Read EEPROM size before call any EEPROM function */ - Adapter->EepromAddressSize = GetEEPROMSize8723A(Adapter); - - MSG_8723A("====> _ReadAdapterInfo8723AU\n"); - - hal_EfuseCellSel(Adapter); - - _ReadPROMContent(Adapter); - - MSG_8723A("<==== _ReadAdapterInfo8723AU in %d ms\n", - jiffies_to_msecs(jiffies - start)); -} - -/* */ -/* Description: */ -/* Query setting of specified variable. */ -/* */ -int GetHalDefVar8192CUsb(struct rtw_adapter *Adapter, - enum hal_def_variable eVariable, void *pValue) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - int bResult = _SUCCESS; - - switch (eVariable) { - case HAL_DEF_UNDERCORATEDSMOOTHEDPWDB: - *((int *)pValue) = pHalData->dmpriv.UndecoratedSmoothedPWDB; - break; - case HAL_DEF_IS_SUPPORT_ANT_DIV: - break; - case HAL_DEF_CURRENT_ANTENNA: - break; - case HAL_DEF_DRVINFO_SZ: - *((u32 *)pValue) = DRVINFO_SZ; - break; - case HAL_DEF_MAX_RECVBUF_SZ: - *((u32 *)pValue) = MAX_RECVBUF_SZ; - break; - case HAL_DEF_RX_PACKET_OFFSET: - *((u32 *)pValue) = RXDESC_SIZE + DRVINFO_SZ; - break; - case HAL_DEF_DBG_DUMP_RXPKT: - *((u8 *)pValue) = pHalData->bDumpRxPkt; - break; - case HAL_DEF_DBG_DM_FUNC: - *((u32 *)pValue) = pHalData->odmpriv.SupportAbility; - break; - case HW_VAR_MAX_RX_AMPDU_FACTOR: - *((u32 *)pValue) = IEEE80211_HT_MAX_AMPDU_64K; - break; - case HW_DEF_ODM_DBG_FLAG: - { - struct dm_odm_t *pDM_Odm = &pHalData->odmpriv; - printk("pDM_Odm->DebugComponents = 0x%llx\n", - pDM_Odm->DebugComponents); - } - break; - default: - bResult = _FAIL; - break; - } - - return bResult; -} - -void rtl8723a_update_ramask(struct rtw_adapter *padapter, - u32 mac_id, u8 rssi_level) -{ - struct sta_info *psta; - struct FW_Sta_Info *fw_sta; - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - u8 init_rate, networkType, raid, arg; - u32 mask, rate_bitmap; - u8 shortGIrate = false; - int supportRateNum; - - if (mac_id >= NUM_STA) /* CAM_SIZE */ - return; - - psta = pmlmeinfo->FW_sta_info[mac_id].psta; - if (psta == NULL) - return; - - switch (mac_id) { - case 0:/* for infra mode */ - supportRateNum = - rtw_get_rateset_len23a(cur_network->SupportedRates); - networkType = judge_network_type23a(padapter, - cur_network->SupportedRates, - supportRateNum) & 0xf; - /* pmlmeext->cur_wireless_mode = networkType; */ - raid = networktype_to_raid23a(networkType); - - mask = update_supported_rate23a(cur_network->SupportedRates, - supportRateNum); - mask |= (pmlmeinfo->HT_enable) ? - update_MSC_rate23a(&pmlmeinfo->ht_cap) : 0; - - if (support_short_GI23a(padapter, &pmlmeinfo->ht_cap)) - shortGIrate = true; - break; - - case 1:/* for broadcast/multicast */ - fw_sta = &pmlmeinfo->FW_sta_info[mac_id]; - supportRateNum = rtw_get_rateset_len23a(fw_sta->SupportedRates); - if (pmlmeext->cur_wireless_mode & WIRELESS_11B) - networkType = WIRELESS_11B; - else - networkType = WIRELESS_11G; - raid = networktype_to_raid23a(networkType); - - mask = update_basic_rate23a(cur_network->SupportedRates, - supportRateNum); - break; - - default: /* for each sta in IBSS */ - fw_sta = &pmlmeinfo->FW_sta_info[mac_id]; - supportRateNum = rtw_get_rateset_len23a(fw_sta->SupportedRates); - networkType = judge_network_type23a(padapter, - fw_sta->SupportedRates, - supportRateNum) & 0xf; - /* pmlmeext->cur_wireless_mode = networkType; */ - raid = networktype_to_raid23a(networkType); - - mask = update_supported_rate23a(cur_network->SupportedRates, - supportRateNum); - - /* todo: support HT in IBSS */ - break; - } - - /* mask &= 0x0fffffff; */ - rate_bitmap = ODM_Get_Rate_Bitmap23a(pHalData, mac_id, mask, - rssi_level); - DBG_8723A("%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; - mask |= ((raid << 28) & 0xf0000000); - - init_rate = get_highest_rate_idx23a(mask) & 0x3f; - - arg = mac_id & 0x1f;/* MACID */ - arg |= BIT(7); - - if (shortGIrate == true) - arg |= BIT(5); - - DBG_8723A("update raid entry, mask = 0x%x, arg = 0x%x\n", mask, arg); - - rtl8723a_set_raid_cmd(padapter, mask, arg); - - /* set ra_id */ - psta->raid = raid; - psta->init_rate = init_rate; - - /* set correct initial date rate for each mac_id */ - pdmpriv->INIDATA_RATE[mac_id] = init_rate; -} diff --git a/drivers/staging/rtl8723au/hal/usb_ops_linux.c b/drivers/staging/rtl8723au/hal/usb_ops_linux.c deleted file mode 100644 index 5c81ff4..0000000 --- a/drivers/staging/rtl8723au/hal/usb_ops_linux.c +++ /dev/null @@ -1,690 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _HCI_OPS_OS_C_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <osdep_intf.h> -#include <usb_ops.h> -#include <recv_osdep.h> -#include <rtl8723a_hal.h> -#include <rtl8723a_recv.h> - -u8 rtl8723au_read8(struct rtw_adapter *padapter, u16 addr) -{ - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); - struct usb_device *udev = pdvobjpriv->pusbdev; - int len; - u8 data; - - mutex_lock(&pdvobjpriv->usb_vendor_req_mutex); - len = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - REALTEK_USB_VENQT_CMD_REQ, REALTEK_USB_VENQT_READ, - addr, 0, &pdvobjpriv->usb_buf.val8, sizeof(data), - RTW_USB_CONTROL_MSG_TIMEOUT); - - data = pdvobjpriv->usb_buf.val8; - mutex_unlock(&pdvobjpriv->usb_vendor_req_mutex); - - return data; -} - -u16 rtl8723au_read16(struct rtw_adapter *padapter, u16 addr) -{ - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); - struct usb_device *udev = pdvobjpriv->pusbdev; - int len; - u16 data; - - mutex_lock(&pdvobjpriv->usb_vendor_req_mutex); - len = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - REALTEK_USB_VENQT_CMD_REQ, REALTEK_USB_VENQT_READ, - addr, 0, &pdvobjpriv->usb_buf.val16, sizeof(data), - RTW_USB_CONTROL_MSG_TIMEOUT); - - data = le16_to_cpu(pdvobjpriv->usb_buf.val16); - mutex_unlock(&pdvobjpriv->usb_vendor_req_mutex); - - return data; -} - -u32 rtl8723au_read32(struct rtw_adapter *padapter, u16 addr) -{ - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); - struct usb_device *udev = pdvobjpriv->pusbdev; - int len; - u32 data; - - mutex_lock(&pdvobjpriv->usb_vendor_req_mutex); - len = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - REALTEK_USB_VENQT_CMD_REQ, REALTEK_USB_VENQT_READ, - addr, 0, &pdvobjpriv->usb_buf.val32, sizeof(data), - RTW_USB_CONTROL_MSG_TIMEOUT); - - data = le32_to_cpu(pdvobjpriv->usb_buf.val32); - mutex_unlock(&pdvobjpriv->usb_vendor_req_mutex); - - return data; -} - -int rtl8723au_write8(struct rtw_adapter *padapter, u16 addr, u8 val) -{ - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); - struct usb_device *udev = pdvobjpriv->pusbdev; - int ret; - - mutex_lock(&pdvobjpriv->usb_vendor_req_mutex); - pdvobjpriv->usb_buf.val8 = val; - - ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - REALTEK_USB_VENQT_CMD_REQ, - REALTEK_USB_VENQT_WRITE, - addr, 0, &pdvobjpriv->usb_buf.val8, sizeof(val), - RTW_USB_CONTROL_MSG_TIMEOUT); - - if (ret != sizeof(val)) - ret = _FAIL; - else - ret = _SUCCESS; - - mutex_unlock(&pdvobjpriv->usb_vendor_req_mutex); - return ret; -} - -int rtl8723au_write16(struct rtw_adapter *padapter, u16 addr, u16 val) -{ - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); - struct usb_device *udev = pdvobjpriv->pusbdev; - int ret; - - mutex_lock(&pdvobjpriv->usb_vendor_req_mutex); - pdvobjpriv->usb_buf.val16 = cpu_to_le16(val); - - ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - REALTEK_USB_VENQT_CMD_REQ, - REALTEK_USB_VENQT_WRITE, - addr, 0, &pdvobjpriv->usb_buf.val16, sizeof(val), - RTW_USB_CONTROL_MSG_TIMEOUT); - - if (ret != sizeof(val)) - ret = _FAIL; - else - ret = _SUCCESS; - - mutex_unlock(&pdvobjpriv->usb_vendor_req_mutex); - return ret; -} - -int rtl8723au_write32(struct rtw_adapter *padapter, u16 addr, u32 val) -{ - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); - struct usb_device *udev = pdvobjpriv->pusbdev; - int ret; - - mutex_lock(&pdvobjpriv->usb_vendor_req_mutex); - pdvobjpriv->usb_buf.val32 = cpu_to_le32(val); - - ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - REALTEK_USB_VENQT_CMD_REQ, - REALTEK_USB_VENQT_WRITE, - addr, 0, &pdvobjpriv->usb_buf.val32, sizeof(val), - RTW_USB_CONTROL_MSG_TIMEOUT); - - if (ret != sizeof(val)) - ret = _FAIL; - else - ret = _SUCCESS; - - mutex_unlock(&pdvobjpriv->usb_vendor_req_mutex); - return ret; -} - -int rtl8723au_writeN(struct rtw_adapter *padapter, u16 addr, u16 len, u8 *buf) -{ - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); - struct usb_device *udev = pdvobjpriv->pusbdev; - int ret; - - ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - REALTEK_USB_VENQT_CMD_REQ, - REALTEK_USB_VENQT_WRITE, - addr, 0, buf, len, RTW_USB_CONTROL_MSG_TIMEOUT); - - if (ret != len) - return _FAIL; - return _SUCCESS; -} - -/* - * Description: - * Recognize the interrupt content by reading the interrupt - * register or content and masking interrupt mask (IMR) - * if it is our NIC's interrupt. After recognizing, we may clear - * the all interrupts (ISR). - * Arguments: - * [in] Adapter - - * The adapter context. - * [in] pContent - - * Under PCI interface, this field is ignord. - * Under USB interface, the content is the interrupt - * content pointer. - * Under SDIO interface, this is the interrupt type which - * is Local interrupt or system interrupt. - * [in] ContentLen - - * The length in byte of pContent. - * Return: - * If any interrupt matches the mask (IMR), return true, and - * return false otherwise. - */ -static bool -InterruptRecognized8723AU(struct rtw_adapter *Adapter, void *pContent, - u32 ContentLen) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); - u8 *buffer = (u8 *)pContent; - struct reportpwrstate_parm report; - - memcpy(&pHalData->IntArray[0], &buffer[USB_INTR_CONTENT_HISR_OFFSET], - 4); - pHalData->IntArray[0] &= pHalData->IntrMask[0]; - - /* For HISR extension. Added by tynli. 2009.10.07. */ - memcpy(&pHalData->IntArray[1], - &buffer[USB_INTR_CONTENT_HISRE_OFFSET], 4); - pHalData->IntArray[1] &= pHalData->IntrMask[1]; - - /* We sholud remove this function later because DDK suggest - * not to executing too many operations in MPISR */ - - memcpy(&report.state, &buffer[USB_INTR_CPWM_OFFSET], 1); - - return (pHalData->IntArray[0] & pHalData->IntrMask[0]) != 0 || - (pHalData->IntArray[1] & pHalData->IntrMask[1]) != 0; -} - -static void usb_read_interrupt_complete(struct urb *purb) -{ - int err; - struct rtw_adapter *padapter = (struct rtw_adapter *)purb->context; - - if (padapter->bSurpriseRemoved || padapter->bDriverStopped || - padapter->bReadPortCancel) { - DBG_8723A("%s() RX Warning! bDriverStopped(%d) OR " - "bSurpriseRemoved(%d) bReadPortCancel(%d)\n", - __func__, padapter->bDriverStopped, - padapter->bSurpriseRemoved, - padapter->bReadPortCancel); - return; - } - - if (purb->status == 0) { - struct c2h_evt_hdr *c2h_evt; - - c2h_evt = (struct c2h_evt_hdr *)purb->transfer_buffer; - - if (purb->actual_length > USB_INTR_CONTENT_LENGTH) { - DBG_8723A("usb_read_interrupt_complete: purb->actual_" - "length > USB_INTR_CONTENT_LENGTH\n"); - goto urb_submit; - } - - InterruptRecognized8723AU(padapter, purb->transfer_buffer, - purb->actual_length); - - if (c2h_evt_exist(c2h_evt)) { - if (c2h_id_filter_ccx_8723a(c2h_evt->id)) { - /* Handle CCX report here */ - handle_txrpt_ccx_8723a(padapter, (void *) - c2h_evt->payload); - schedule_work(&padapter->evtpriv.irq_wk); - } else { - struct evt_work *c2w; - int res; - - c2w = kmalloc(sizeof(struct evt_work), - GFP_ATOMIC); - - if (!c2w) - goto urb_submit; - - c2w->adapter = padapter; - INIT_WORK(&c2w->work, rtw_evt_work); - memcpy(c2w->u.buf, purb->transfer_buffer, 16); - - res = queue_work(padapter->evtpriv.wq, - &c2w->work); - - if (!res) { - printk(KERN_ERR "%s: Call to " - "queue_work() failed\n", - __func__); - kfree(c2w); - goto urb_submit; - } - } - } - -urb_submit: - err = usb_submit_urb(purb, GFP_ATOMIC); - if (err && (err != -EPERM)) { - DBG_8723A("cannot submit interrupt in-token(err = " - "0x%08x), urb_status = %d\n", - err, purb->status); - } - } else { - DBG_8723A("###=> usb_read_interrupt_complete => urb " - "status(%d)\n", purb->status); - - switch (purb->status) { - case -EINVAL: - case -EPIPE: - case -ENODEV: - case -ESHUTDOWN: - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_read_port_complete:bSurpriseRemoved =true\n"); - /* Fall Through here */ - case -ENOENT: - padapter->bDriverStopped = true; - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_read_port_complete:bDriverStopped =true\n"); - break; - case -EPROTO: - break; - case -EINPROGRESS: - DBG_8723A("ERROR: URB IS IN PROGRESS!\n"); - break; - default: - break; - } - } -} - -int rtl8723au_read_interrupt(struct rtw_adapter *adapter) -{ - int err; - unsigned int pipe; - int ret = _SUCCESS; - struct dvobj_priv *pdvobj = adapter_to_dvobj(adapter); - struct recv_priv *precvpriv = &adapter->recvpriv; - struct usb_device *pusbd = pdvobj->pusbdev; - - /* translate DMA FIFO addr to pipehandle */ - pipe = usb_rcvintpipe(pusbd, pdvobj->RtInPipe[1]); - - usb_fill_int_urb(precvpriv->int_in_urb, pusbd, pipe, - precvpriv->int_in_buf, USB_INTR_CONTENT_LENGTH, - usb_read_interrupt_complete, adapter, 1); - - err = usb_submit_urb(precvpriv->int_in_urb, GFP_ATOMIC); - if (err && (err != -EPERM)) { - DBG_8723A("cannot submit interrupt in-token(err = 0x%08x)," - "urb_status = %d\n", err, - precvpriv->int_in_urb->status); - ret = _FAIL; - } - - return ret; -} - -static int recvbuf2recvframe(struct rtw_adapter *padapter, struct sk_buff *pskb) -{ - u8 *pbuf; - u8 shift_sz = 0; - u16 pkt_cnt; - u32 pkt_offset, skb_len, alloc_sz; - int transfer_len; - struct recv_stat *prxstat; - struct phy_stat *pphy_info; - struct sk_buff *pkt_copy; - struct recv_frame *precvframe; - struct rx_pkt_attrib *pattrib; - struct recv_priv *precvpriv = &padapter->recvpriv; - struct rtw_queue *pfree_recv_queue = &precvpriv->free_recv_queue; - - transfer_len = (int)pskb->len; - pbuf = pskb->data; - - prxstat = (struct recv_stat *)pbuf; - pkt_cnt = (le32_to_cpu(prxstat->rxdw2) >> 16) & 0xff; - - do { - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "recvbuf2recvframe: rxdesc = offsset 0:0x%08x, 4:0x%08x, 8:0x%08x, C:0x%08x\n", - prxstat->rxdw0, prxstat->rxdw1, - prxstat->rxdw2, prxstat->rxdw4); - - prxstat = (struct recv_stat *)pbuf; - - precvframe = rtw_alloc_recvframe23a(pfree_recv_queue); - if (!precvframe) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "recvbuf2recvframe: precvframe == NULL\n"); - DBG_8723A("%s()-%d: rtw_alloc_recvframe23a() failed! RX " - "Drop!\n", __func__, __LINE__); - goto _exit_recvbuf2recvframe; - } - - INIT_LIST_HEAD(&precvframe->list); - - update_recvframe_attrib(precvframe, prxstat); - - pattrib = &precvframe->attrib; - - if (pattrib->crc_err) { - DBG_8723A("%s()-%d: RX Warning! rx CRC ERROR !!\n", - __func__, __LINE__); - rtw_free_recvframe23a(precvframe); - goto _exit_recvbuf2recvframe; - } - - 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_, - "recvbuf2recvframe: pkt_len<= 0\n"); - DBG_8723A("%s()-%d: RX Warning!\n", - __func__, __LINE__); - rtw_free_recvframe23a(precvframe); - goto _exit_recvbuf2recvframe; - } - - /* Modified by Albert 20101213 */ - /* For 8 bytes IP header alignment. */ - /* Qos data, wireless lan header length is 26 */ - if (pattrib->qos) - shift_sz = 6; - else - shift_sz = 0; - - skb_len = pattrib->pkt_len; - - /* for first fragment packet, driver need allocate - * 1536+drvinfo_sz+RXDESC_SIZE to defrag packet. - * modify alloc_sz for recvive crc error packet - * by thomas 2011-06-02 */ - if (pattrib->mfrag == 1 && pattrib->frag_num == 0) { - /* alloc_sz = 1664; 1664 is 128 alignment. */ - if (skb_len <= 1650) - alloc_sz = 1664; - else - alloc_sz = skb_len + 14; - } else { - alloc_sz = skb_len; - /* 6 is for IP header 8 bytes alignment in QoS packet case. */ - /* 8 is for skb->data 4 bytes alignment. */ - alloc_sz += 14; - } - - pkt_copy = netdev_alloc_skb(padapter->pnetdev, alloc_sz); - if (pkt_copy) { - pkt_copy->dev = padapter->pnetdev; - precvframe->pkt = pkt_copy; - /* force pkt_copy->data at 8-byte alignment address */ - skb_reserve(pkt_copy, 8 - - ((unsigned long)(pkt_copy->data) & 7)); - /*force ip_hdr at 8-byte alignment address - according to shift_sz. */ - skb_reserve(pkt_copy, shift_sz); - memcpy(pkt_copy->data, pbuf + pattrib->shift_sz + - pattrib->drvinfo_sz + RXDESC_SIZE, skb_len); - skb_put(pkt_copy, skb_len); - } else { - if (pattrib->mfrag == 1 && pattrib->frag_num == 0) { - DBG_8723A("recvbuf2recvframe: alloc_skb fail, " - "drop frag frame \n"); - rtw_free_recvframe23a(precvframe); - goto _exit_recvbuf2recvframe; - } - - precvframe->pkt = skb_clone(pskb, GFP_ATOMIC); - if (!precvframe->pkt) { - DBG_8723A("recvbuf2recvframe: skb_clone " - "fail\n"); - rtw_free_recvframe23a(precvframe); - goto _exit_recvbuf2recvframe; - } - } - - if (pattrib->physt) { - pphy_info = (struct phy_stat *)(pbuf + RXDESC_OFFSET); - update_recvframe_phyinfo(precvframe, pphy_info); - } - - if (rtw_recv_entry23a(precvframe) != _SUCCESS) - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "recvbuf2recvframe: rtw_recv_entry23a(precvframe) != _SUCCESS\n"); - - pkt_cnt--; - transfer_len -= pkt_offset; - pbuf += pkt_offset; - precvframe = NULL; - pkt_copy = NULL; - - if (transfer_len > 0 && pkt_cnt == 0) - pkt_cnt = (le32_to_cpu(prxstat->rxdw2)>>16) & 0xff; - - } while (transfer_len > 0 && pkt_cnt > 0); - -_exit_recvbuf2recvframe: - - return _SUCCESS; -} - -void rtl8723au_recv_tasklet(void *priv) -{ - struct sk_buff *pskb; - struct rtw_adapter *padapter = (struct rtw_adapter *)priv; - struct recv_priv *precvpriv = &padapter->recvpriv; - - while (NULL != (pskb = skb_dequeue(&precvpriv->rx_skb_queue))) { - if (padapter->bDriverStopped || padapter->bSurpriseRemoved) { - DBG_8723A("recv_tasklet => bDriverStopped or " - "bSurpriseRemoved \n"); - dev_kfree_skb_any(pskb); - break; - } - - recvbuf2recvframe(padapter, pskb); - skb_reset_tail_pointer(pskb); - - pskb->len = 0; - - skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb); - } -} - -static void usb_read_port_complete(struct urb *purb) -{ - struct recv_buf *precvbuf = (struct recv_buf *)purb->context; - struct rtw_adapter *padapter = (struct rtw_adapter *)precvbuf->adapter; - struct recv_priv *precvpriv = &padapter->recvpriv; - - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_read_port_complete!!!\n"); - - precvpriv->rx_pending_cnt--; - - if (padapter->bSurpriseRemoved || padapter->bDriverStopped || - padapter->bReadPortCancel) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_read_port_complete:bDriverStopped(%d) OR bSurpriseRemoved(%d)\n", - padapter->bDriverStopped, padapter->bSurpriseRemoved); - - DBG_8723A("%s()-%d: RX Warning! bDriverStopped(%d) OR " - "bSurpriseRemoved(%d) bReadPortCancel(%d)\n", - __func__, __LINE__, padapter->bDriverStopped, - padapter->bSurpriseRemoved, padapter->bReadPortCancel); - return; - } - - if (purb->status == 0) { - if (purb->actual_length > MAX_RECVBUF_SZ || - purb->actual_length < RXDESC_SIZE) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_read_port_complete: (purb->actual_length > MAX_RECVBUF_SZ) || (purb->actual_length < RXDESC_SIZE)\n"); - rtl8723au_read_port(padapter, 0, precvbuf); - DBG_8723A("%s()-%d: RX Warning!\n", - __func__, __LINE__); - } else { - rtw_reset_continual_urb_error( - adapter_to_dvobj(padapter)); - - skb_put(precvbuf->pskb, purb->actual_length); - skb_queue_tail(&precvpriv->rx_skb_queue, - precvbuf->pskb); - - if (skb_queue_len(&precvpriv->rx_skb_queue) <= 1) - tasklet_schedule(&precvpriv->recv_tasklet); - - precvbuf->pskb = NULL; - rtl8723au_read_port(padapter, 0, precvbuf); - } - } else { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_read_port_complete : purb->status(%d) != 0\n", - purb->status); - skb_put(precvbuf->pskb, purb->actual_length); - precvbuf->pskb = NULL; - - DBG_8723A("###=> usb_read_port_complete => urb status(%d)\n", - purb->status); - - if (rtw_inc_and_chk_continual_urb_error( - adapter_to_dvobj(padapter))) { - padapter->bSurpriseRemoved = true; - } - - switch (purb->status) { - case -EINVAL: - case -EPIPE: - case -ENODEV: - case -ESHUTDOWN: - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_read_port_complete:bSurpriseRemoved = true\n"); - /* Intentional fall through here */ - case -ENOENT: - padapter->bDriverStopped = true; - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_read_port_complete:bDriverStopped = true\n"); - break; - case -EPROTO: - case -EOVERFLOW: - rtl8723au_read_port(padapter, 0, precvbuf); - break; - case -EINPROGRESS: - DBG_8723A("ERROR: URB IS IN PROGRESS!\n"); - break; - default: - break; - } - } -} - -int rtl8723au_read_port(struct rtw_adapter *adapter, u32 cnt, - struct recv_buf *precvbuf) -{ - struct urb *purb; - struct dvobj_priv *pdvobj = adapter_to_dvobj(adapter); - struct recv_priv *precvpriv = &adapter->recvpriv; - struct usb_device *pusbd = pdvobj->pusbdev; - int err; - unsigned int pipe; - unsigned long tmpaddr; - unsigned long alignment; - int ret = _SUCCESS; - - if (adapter->bDriverStopped || adapter->bSurpriseRemoved) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_read_port:(padapter->bDriverStopped ||padapter->bSurpriseRemoved)!!!\n"); - return _FAIL; - } - - if (!precvbuf) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_read_port:precvbuf == NULL\n"); - return _FAIL; - } - - if (!precvbuf->pskb) - precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue); - - /* re-assign for linux based on skb */ - if (!precvbuf->pskb) { - precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev, MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ); - if (precvbuf->pskb == NULL) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "init_recvbuf(): alloc_skb fail!\n"); - return _FAIL; - } - - tmpaddr = (unsigned long)precvbuf->pskb->data; - alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1); - skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment)); - } - - precvpriv->rx_pending_cnt++; - - purb = precvbuf->purb; - - /* translate DMA FIFO addr to pipehandle */ - pipe = usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe[0]); - - usb_fill_bulk_urb(purb, pusbd, pipe, precvbuf->pskb->data, - MAX_RECVBUF_SZ, usb_read_port_complete, - 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\n", - err, purb->status); - DBG_8723A("cannot submit rx in-token(err = 0x%08x), urb_status " - "= %d\n", err, purb->status); - ret = _FAIL; - } - return ret; -} - -void rtl8723au_xmit_tasklet(void *priv) -{ - int ret; - struct rtw_adapter *padapter = (struct rtw_adapter *)priv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - if (check_fwstate(&padapter->mlmepriv, _FW_UNDER_SURVEY)) - return; - - while (1) { - if (padapter->bDriverStopped || padapter->bSurpriseRemoved || - padapter->bWritePortCancel) { - DBG_8723A("xmit_tasklet => bDriverStopped or " - "bSurpriseRemoved or bWritePortCancel\n"); - break; - } - - ret = rtl8723au_xmitframe_complete(padapter, pxmitpriv, NULL); - - if (!ret) - break; - } -} - -void rtl8723au_set_hw_type(struct rtw_adapter *padapter) -{ - padapter->chip_type = RTL8723A; - padapter->HardwareType = HARDWARE_TYPE_RTL8723AU; - DBG_8723A("CHIP TYPE: RTL8723A\n"); -} diff --git a/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h b/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h deleted file mode 100644 index bcf3657..0000000 --- a/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h +++ /dev/null @@ -1,162 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * - ******************************************************************************/ -#ifndef __INC_HAL8723PHYCFG_H__ -#define __INC_HAL8723PHYCFG_H__ - -/*------------------------------Define structure----------------------------*/ -enum RF_RADIO_PATH { - RF_PATH_A = 0, /* Radio Path A */ - RF_PATH_B = 1, /* Radio Path B */ - RF_PATH_MAX /* Max RF number 90 support */ -}; - -#define CHANNEL_MAX_NUMBER 14 /* 14 is the max channel number */ - -enum WIRELESS_MODE { - WIRELESS_MODE_UNKNOWN = 0x00, - WIRELESS_MODE_A = BIT(2), - WIRELESS_MODE_B = BIT(0), - WIRELESS_MODE_G = BIT(1), - WIRELESS_MODE_AUTO = BIT(5), - WIRELESS_MODE_N_24G = BIT(3), - WIRELESS_MODE_N_5G = BIT(4), - WIRELESS_MODE_AC = BIT(6) -}; - -struct bb_reg_define { - u32 rfintfs; /* set software control: */ - /* 0x870~0x877[8 bytes] */ - u32 rfintfi; /* readback data: */ - /* 0x8e0~0x8e7[8 bytes] */ - u32 rfintfo; /* output data: */ - /* 0x860~0x86f [16 bytes] */ - u32 rfintfe; /* output enable: */ - /* 0x860~0x86f [16 bytes] */ - u32 rf3wireOffset; /* LSSI data: */ - /* 0x840~0x84f [16 bytes] */ - u32 rfLSSI_Select; /* BB Band Select: */ - /* 0x878~0x87f [8 bytes] */ - u32 rfTxGainStage; /* Tx gain stage: */ - /* 0x80c~0x80f [4 bytes] */ - u32 rfHSSIPara1; /* wire parameter control1 : */ - /* 0x820~0x823, 0x828~0x82b, 0x830~0x833, 0x838~0x83b [16 bytes] */ - u32 rfHSSIPara2; /* wire parameter control2 : */ - /* 0x824~0x827, 0x82c~0x82f, 0x834~0x837, 0x83c~0x83f [16 bytes] */ - u32 rfSwitchControl; /* Tx Rx antenna control : */ - /* 0x858~0x85f [16 bytes] */ - u32 rfAGCControl1; /* AGC parameter control1 : */ - /* 0xc50~0xc53, 0xc58~0xc5b, 0xc60~0xc63, 0xc68~0xc6b [16 bytes] */ - u32 rfAGCControl2; /* AGC parameter control2 : */ - /* 0xc54~0xc57, 0xc5c~0xc5f, 0xc64~0xc67, 0xc6c~0xc6f [16 bytes] */ - u32 rfRxIQImbalance; /* OFDM Rx IQ imbalance matrix : */ - /* 0xc14~0xc17, 0xc1c~0xc1f, 0xc24~0xc27, 0xc2c~0xc2f [16 bytes] */ - u32 rfRxAFE; /* Rx IQ DC ofset and Rx digital filter, Rx DC notch filter : */ - /* 0xc10~0xc13, 0xc18~0xc1b, 0xc20~0xc23, 0xc28~0xc2b [16 bytes] */ - u32 rfTxIQImbalance; /* OFDM Tx IQ imbalance matrix */ - /* 0xc80~0xc83, 0xc88~0xc8b, 0xc90~0xc93, 0xc98~0xc9b [16 bytes] */ - u32 rfTxAFE; /* Tx IQ DC Offset and Tx DFIR type */ - /* 0xc84~0xc87, 0xc8c~0xc8f, 0xc94~0xc97, 0xc9c~0xc9f [16 bytes] */ - u32 rfLSSIReadBack; /* LSSI RF readback data SI mode */ - /* 0x8a0~0x8af [16 bytes] */ - u32 rfLSSIReadBackPi; /* LSSI RF readback data PI mode 0x8b8-8bc for Path A and B */ -}; - -struct r_antenna_sel_ofdm { - u32 r_tx_antenna:4; - u32 r_ant_l:4; - u32 r_ant_non_ht:4; - u32 r_ant_ht1:4; - u32 r_ant_ht2:4; - u32 r_ant_ht_s1:4; - u32 r_ant_non_ht_s1:4; - u32 OFDM_TXSC:2; - u32 Reserved:2; -}; - -struct r_antenna_sel_cck { - u8 r_cckrx_enable_2:2; - u8 r_cckrx_enable:2; - u8 r_ccktx_enable:4; -}; - -/*------------------------------Define structure----------------------------*/ - - -/*------------------------Export global variable----------------------------*/ -/*------------------------Export global variable----------------------------*/ - - -/*------------------------Export Macro Definition---------------------------*/ -/*------------------------Export Macro Definition---------------------------*/ - - -/*--------------------------Exported Function prototype---------------------*/ -/* */ -/* BB and RF register read/write */ -/* */ -u32 PHY_QueryBBReg(struct rtw_adapter *Adapter, u32 RegAddr, - u32 BitMask); -void PHY_SetBBReg(struct rtw_adapter *Adapter, u32 RegAddr, - u32 BitMask, u32 Data); -u32 PHY_QueryRFReg(struct rtw_adapter *Adapter, - enum RF_RADIO_PATH eRFPath, u32 RegAddr, - u32 BitMask); -void PHY_SetRFReg(struct rtw_adapter *Adapter, - enum RF_RADIO_PATH eRFPath, u32 RegAddr, - u32 BitMask, u32 Data); - -/* */ -/* BB TX Power R/W */ -/* */ -void PHY_SetTxPowerLevel8723A(struct rtw_adapter *Adapter, u8 channel); - -/* */ -/* Switch bandwidth for 8723A */ -/* */ -void PHY_SetBWMode23a8723A(struct rtw_adapter *pAdapter, - enum ht_channel_width ChnlWidth, - unsigned char Offset); - -/* */ -/* channel switch related funciton */ -/* */ -void PHY_SwChnl8723A(struct rtw_adapter *pAdapter, u8 channel); - /* Call after initialization */ -void ChkFwCmdIoDone(struct rtw_adapter *Adapter); - -/* */ -/* Modify the value of the hw register when beacon interval be changed. */ -/* */ -void -rtl8192c_PHY_SetBeaconHwReg(struct rtw_adapter *Adapter, u16 BeaconInterval); - - -void PHY_SwitchEphyParameter(struct rtw_adapter *Adapter); - -void PHY_EnableHostClkReq(struct rtw_adapter *Adapter); - -bool -SetAntennaConfig92C(struct rtw_adapter *Adapter, u8 DefaultAnt); - -/*--------------------------Exported Function prototype---------------------*/ - -#define PHY_SetMacReg PHY_SetBBReg - -/* MAC/BB/RF HAL config */ -int PHY_BBConfig8723A(struct rtw_adapter *Adapter); -s32 PHY_MACConfig8723A(struct rtw_adapter *padapter); - -#endif diff --git a/drivers/staging/rtl8723au/include/Hal8723APhyReg.h b/drivers/staging/rtl8723au/include/Hal8723APhyReg.h deleted file mode 100644 index 759928f..0000000 --- a/drivers/staging/rtl8723au/include/Hal8723APhyReg.h +++ /dev/null @@ -1,1078 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * - ******************************************************************************/ -#ifndef __INC_HAL8723APHYREG_H__ -#define __INC_HAL8723APHYREG_H__ - -/* 1. PMAC duplicate register due to connection: RF_Mode, TRxRN, NumOf L-STF */ -/* 1. Page1(0x100) */ -#define rPMAC_Reset 0x100 -#define rPMAC_TxStart 0x104 -#define rPMAC_TxLegacySIG 0x108 -#define rPMAC_TxHTSIG1 0x10c -#define rPMAC_TxHTSIG2 0x110 -#define rPMAC_PHYDebug 0x114 -#define rPMAC_TxPacketNum 0x118 -#define rPMAC_TxIdle 0x11c -#define rPMAC_TxMACHeader0 0x120 -#define rPMAC_TxMACHeader1 0x124 -#define rPMAC_TxMACHeader2 0x128 -#define rPMAC_TxMACHeader3 0x12c -#define rPMAC_TxMACHeader4 0x130 -#define rPMAC_TxMACHeader5 0x134 -#define rPMAC_TxDataType 0x138 -#define rPMAC_TxRandomSeed 0x13c -#define rPMAC_CCKPLCPPreamble 0x140 -#define rPMAC_CCKPLCPHeader 0x144 -#define rPMAC_CCKCRC16 0x148 -#define rPMAC_OFDMRxCRC32OK 0x170 -#define rPMAC_OFDMRxCRC32Er 0x174 -#define rPMAC_OFDMRxParityEr 0x178 -#define rPMAC_OFDMRxCRC8Er 0x17c -#define rPMAC_CCKCRxRC16Er 0x180 -#define rPMAC_CCKCRxRC32Er 0x184 -#define rPMAC_CCKCRxRC32OK 0x188 -#define rPMAC_TxStatus 0x18c - -/* 2. Page2(0x200) */ -/* The following two definition are only used for USB interface. */ -#define RF_BB_CMD_ADDR 0x02c0 /* RF/BB read/write command address. */ -#define RF_BB_CMD_DATA 0x02c4 /* RF/BB read/write command data. */ - -/* 3. Page8(0x800) */ -#define rFPGA0_RFMOD 0x800 /* RF mode & CCK TxSC RF BW Setting?? */ - -#define rFPGA0_TxInfo 0x804 /* Status report?? */ -#define rFPGA0_PSDFunction 0x808 - -#define rFPGA0_TxGainStage 0x80c /* Set TX PWR init gain? */ - -#define rFPGA0_RFTiming1 0x810 /* Useless now */ -#define rFPGA0_RFTiming2 0x814 - -#define rFPGA0_XA_HSSIParameter1 0x820 /* RF 3 wire register */ -#define rFPGA0_XA_HSSIParameter2 0x824 -#define rFPGA0_XB_HSSIParameter1 0x828 -#define rFPGA0_XB_HSSIParameter2 0x82c -#define rTxAGC_B_Rate18_06 0x830 -#define rTxAGC_B_Rate54_24 0x834 -#define rTxAGC_B_CCK1_55_Mcs32 0x838 -#define rTxAGC_B_Mcs03_Mcs00 0x83c - -#define rTxAGC_B_Mcs07_Mcs04 0x848 -#define rTxAGC_B_Mcs11_Mcs08 0x84c - -#define rFPGA0_XA_LSSIParameter 0x840 -#define rFPGA0_XB_LSSIParameter 0x844 - -#define rFPGA0_RFWakeUpParameter 0x850 /* Useless now */ -#define rFPGA0_RFSleepUpParameter 0x854 - -#define rFPGA0_XAB_SwitchControl 0x858 /* RF Channel switch */ -#define rFPGA0_XCD_SwitchControl 0x85c - -#define rFPGA0_XA_RFInterfaceOE 0x860 /* RF Channel switch */ -#define rFPGA0_XB_RFInterfaceOE 0x864 - -#define rTxAGC_B_Mcs15_Mcs12 0x868 -#define rTxAGC_B_CCK11_A_CCK2_11 0x86c - -#define rFPGA0_XAB_RFInterfaceSW 0x870 /* RF Interface Software Control */ -#define rFPGA0_XCD_RFInterfaceSW 0x874 - -#define rFPGA0_XAB_RFParameter 0x878 /* RF Parameter */ -#define rFPGA0_XCD_RFParameter 0x87c - -#define rFPGA0_AnalogParameter1 0x880 /* Crystal cap setting RF-R/W protection for parameter4?? */ -#define rFPGA0_AnalogParameter2 0x884 -#define rFPGA0_AnalogParameter3 0x888 /* Useless now */ -#define rFPGA0_AnalogParameter4 0x88c - -#define rFPGA0_XA_LSSIReadBack 0x8a0 /* Tranceiver LSSI Readback */ -#define rFPGA0_XB_LSSIReadBack 0x8a4 -#define rFPGA0_XC_LSSIReadBack 0x8a8 -#define rFPGA0_XD_LSSIReadBack 0x8ac - -#define rFPGA0_PSDReport 0x8b4 /* Useless now */ -#define TransceiverA_HSPI_Readback 0x8b8 /* Transceiver A HSPI Readback */ -#define TransceiverB_HSPI_Readback 0x8bc /* Transceiver B HSPI Readback */ -#define rFPGA0_XAB_RFInterfaceRB 0x8e0 /* Useless now RF Interface Readback Value */ -#define rFPGA0_XCD_RFInterfaceRB 0x8e4 /* Useless now */ - -/* 4. Page9(0x900) */ -#define rFPGA1_RFMOD 0x900 /* RF mode & OFDM TxSC RF BW Setting?? */ - -#define rFPGA1_TxBlock 0x904 /* Useless now */ -#define rFPGA1_DebugSelect 0x908 /* Useless now */ -#define rFPGA1_TxInfo 0x90c /* Useless now Status report?? */ - -/* 5. PageA(0xA00) */ -/* Set Control channel to upper or lower. These settings are required only for 40MHz */ -#define rCCK0_System 0xa00 - -#define rCCK0_AFESetting 0xa04 /* Disable init gain now Select RX path by RSSI */ -#define rCCK0_CCA 0xa08 /* Disable init gain now Init gain */ - -#define rCCK0_RxAGC1 0xa0c /* AGC default value, saturation level Antenna Diversity, RX AGC, LNA Threshold, RX LNA Threshold useless now. Not the same as 90 series */ -#define rCCK0_RxAGC2 0xa10 /* AGC & DAGC */ - -#define rCCK0_RxHP 0xa14 - -#define rCCK0_DSPParameter1 0xa18 /* Timing recovery & Channel estimation threshold */ -#define rCCK0_DSPParameter2 0xa1c /* SQ threshold */ - -#define rCCK0_TxFilter1 0xa20 -#define rCCK0_TxFilter2 0xa24 -#define rCCK0_DebugPort 0xa28 /* debug port and Tx filter3 */ -#define rCCK0_FalseAlarmReport 0xa2c /* 0xa2d useless now 0xa30-a4f channel report */ -#define rCCK0_TRSSIReport 0xa50 -#define rCCK0_RxReport 0xa54 /* 0xa57 */ -#define rCCK0_FACounterLower 0xa5c /* 0xa5b */ -#define rCCK0_FACounterUpper 0xa58 /* 0xa5c */ -/* PageB(0xB00) */ -#define rPdp_AntA 0xb00 -#define rPdp_AntA_4 0xb04 -#define rConfig_Pmpd_AntA 0xb28 -#define rConfig_AntA 0xb68 -#define rConfig_AntB 0xb6c -#define rPdp_AntB 0xb70 -#define rPdp_AntB_4 0xb74 -#define rConfig_Pmpd_AntB 0xb98 -#define rAPK 0xbd8 - -/* 6. PageC(0xC00) */ -#define rOFDM0_LSTF 0xc00 - -#define rOFDM0_TRxPathEnable 0xc04 -#define rOFDM0_TRMuxPar 0xc08 -#define rOFDM0_TRSWIsolation 0xc0c - -#define rOFDM0_XARxAFE 0xc10 /* RxIQ DC offset, Rx digital filter, DC notch filter */ -#define rOFDM0_XARxIQImbalance 0xc14 /* RxIQ imblance matrix */ -#define rOFDM0_XBRxAFE 0xc18 -#define rOFDM0_XBRxIQImbalance 0xc1c -#define rOFDM0_XCRxAFE 0xc20 -#define rOFDM0_XCRxIQImbalance 0xc24 -#define rOFDM0_XDRxAFE 0xc28 -#define rOFDM0_XDRxIQImbalance 0xc2c - -#define rOFDM0_RxDetector1 0xc30 /* PD,BW & SBD DM tune init gain */ -#define rOFDM0_RxDetector2 0xc34 /* SBD & Fame Sync. */ -#define rOFDM0_RxDetector3 0xc38 /* Frame Sync. */ -#define rOFDM0_RxDetector4 0xc3c /* PD, SBD, Frame Sync & Short-GI */ - -#define rOFDM0_RxDSP 0xc40 /* Rx Sync Path */ -#define rOFDM0_CFOandDAGC 0xc44 /* CFO & DAGC */ -#define rOFDM0_CCADropThreshold 0xc48 /* CCA Drop threshold */ -#define rOFDM0_ECCAThreshold 0xc4c /* energy CCA */ - -#define rOFDM0_XAAGCCore1 0xc50 /* DIG */ -#define rOFDM0_XAAGCCore2 0xc54 -#define rOFDM0_XBAGCCore1 0xc58 -#define rOFDM0_XBAGCCore2 0xc5c -#define rOFDM0_XCAGCCore1 0xc60 -#define rOFDM0_XCAGCCore2 0xc64 -#define rOFDM0_XDAGCCore1 0xc68 -#define rOFDM0_XDAGCCore2 0xc6c - -#define rOFDM0_AGCParameter1 0xc70 -#define rOFDM0_AGCParameter2 0xc74 -#define rOFDM0_AGCRSSITable 0xc78 -#define rOFDM0_HTSTFAGC 0xc7c - -#define rOFDM0_XATxIQImbalance 0xc80 /* TX PWR TRACK and DIG */ -#define rOFDM0_XATxAFE 0xc84 -#define rOFDM0_XBTxIQImbalance 0xc88 -#define rOFDM0_XBTxAFE 0xc8c -#define rOFDM0_XCTxIQImbalance 0xc90 -#define rOFDM0_XCTxAFE 0xc94 -#define rOFDM0_XDTxIQImbalance 0xc98 -#define rOFDM0_XDTxAFE 0xc9c - -#define rOFDM0_RxIQExtAnta 0xca0 -#define rOFDM0_TxCoeff1 0xca4 -#define rOFDM0_TxCoeff2 0xca8 -#define rOFDM0_TxCoeff3 0xcac -#define rOFDM0_TxCoeff4 0xcb0 -#define rOFDM0_TxCoeff5 0xcb4 -#define rOFDM0_TxCoeff6 0xcb8 -#define rOFDM0_RxHPParameter 0xce0 -#define rOFDM0_TxPseudoNoiseWgt 0xce4 -#define rOFDM0_FrameSync 0xcf0 -#define rOFDM0_DFSReport 0xcf4 - -/* 7. PageD(0xD00) */ -#define rOFDM1_LSTF 0xd00 -#define rOFDM1_TRxPathEnable 0xd04 - -#define rOFDM1_CFO 0xd08 /* No setting now */ -#define rOFDM1_CSI1 0xd10 -#define rOFDM1_SBD 0xd14 -#define rOFDM1_CSI2 0xd18 -#define rOFDM1_CFOTracking 0xd2c -#define rOFDM1_TRxMesaure1 0xd34 -#define rOFDM1_IntfDet 0xd3c -#define rOFDM1_PseudoNoiseStateAB 0xd50 -#define rOFDM1_PseudoNoiseStateCD 0xd54 -#define rOFDM1_RxPseudoNoiseWgt 0xd58 - -#define rOFDM_PHYCounter1 0xda0 /* cca, parity fail */ -#define rOFDM_PHYCounter2 0xda4 /* rate illegal, crc8 fail */ -#define rOFDM_PHYCounter3 0xda8 /* MCS not support */ - -#define rOFDM_ShortCFOAB 0xdac /* No setting now */ -#define rOFDM_ShortCFOCD 0xdb0 -#define rOFDM_LongCFOAB 0xdb4 -#define rOFDM_LongCFOCD 0xdb8 -#define rOFDM_TailCFOAB 0xdbc -#define rOFDM_TailCFOCD 0xdc0 -#define rOFDM_PWMeasure1 0xdc4 -#define rOFDM_PWMeasure2 0xdc8 -#define rOFDM_BWReport 0xdcc -#define rOFDM_AGCReport 0xdd0 -#define rOFDM_RxSNR 0xdd4 -#define rOFDM_RxEVMCSI 0xdd8 -#define rOFDM_SIGReport 0xddc - - -/* 8. PageE(0xE00) */ -#define rTxAGC_A_Rate18_06 0xe00 -#define rTxAGC_A_Rate54_24 0xe04 -#define rTxAGC_A_CCK1_Mcs32 0xe08 -#define rTxAGC_A_Mcs03_Mcs00 0xe10 -#define rTxAGC_A_Mcs07_Mcs04 0xe14 -#define rTxAGC_A_Mcs11_Mcs08 0xe18 -#define rTxAGC_A_Mcs15_Mcs12 0xe1c - -#define rFPGA0_IQK 0xe28 -#define rTx_IQK_Tone_A 0xe30 -#define rRx_IQK_Tone_A 0xe34 -#define rTx_IQK_PI_A 0xe38 -#define rRx_IQK_PI_A 0xe3c - -#define rTx_IQK 0xe40 -#define rRx_IQK 0xe44 -#define rIQK_AGC_Pts 0xe48 -#define rIQK_AGC_Rsp 0xe4c -#define rTx_IQK_Tone_B 0xe50 -#define rRx_IQK_Tone_B 0xe54 -#define rTx_IQK_PI_B 0xe58 -#define rRx_IQK_PI_B 0xe5c -#define rIQK_AGC_Cont 0xe60 - -#define rBlue_Tooth 0xe6c -#define rRx_Wait_CCA 0xe70 -#define rTx_CCK_RFON 0xe74 -#define rTx_CCK_BBON 0xe78 -#define rTx_OFDM_RFON 0xe7c -#define rTx_OFDM_BBON 0xe80 -#define rTx_To_Rx 0xe84 -#define rTx_To_Tx 0xe88 -#define rRx_CCK 0xe8c - -#define rTx_Power_Before_IQK_A 0xe94 -#define rTx_Power_After_IQK_A 0xe9c - -#define rRx_Power_Before_IQK_A 0xea0 -#define rRx_Power_Before_IQK_A_2 0xea4 -#define rRx_Power_After_IQK_A 0xea8 -#define rRx_Power_After_IQK_A_2 0xeac - -#define rTx_Power_Before_IQK_B 0xeb4 -#define rTx_Power_After_IQK_B 0xebc - -#define rRx_Power_Before_IQK_B 0xec0 -#define rRx_Power_Before_IQK_B_2 0xec4 -#define rRx_Power_After_IQK_B 0xec8 -#define rRx_Power_After_IQK_B_2 0xecc - -#define rRx_OFDM 0xed0 -#define rRx_Wait_RIFS 0xed4 -#define rRx_TO_Rx 0xed8 -#define rStandby 0xedc -#define rSleep 0xee0 -#define rPMPD_ANAEN 0xeec - -/* 7. RF Register 0x00-0x2E (RF 8256) */ -/* RF-0222D 0x00-3F */ -/* Zebra1 */ -#define rZebra1_HSSIEnable 0x0 /* Useless now */ -#define rZebra1_TRxEnable1 0x1 -#define rZebra1_TRxEnable2 0x2 -#define rZebra1_AGC 0x4 -#define rZebra1_ChargePump 0x5 -#define rZebra1_Channel 0x7 /* RF channel switch */ - -#define rZebra1_TxGain 0x8 /* Useless now */ -#define rZebra1_TxLPF 0x9 -#define rZebra1_RxLPF 0xb -#define rZebra1_RxHPFCorner 0xc - -/* Zebra4 */ -#define rGlobalCtrl 0 /* Useless now */ -#define rRTL8256_TxLPF 19 -#define rRTL8256_RxLPF 11 - -/* RTL8258 */ -#define rRTL8258_TxLPF 0x11 /* Useless now */ -#define rRTL8258_RxLPF 0x13 -#define rRTL8258_RSSILPF 0xa - -/* RL6052 Register definition */ -#define RF_AC 0x00 -#define RF_IQADJ_G1 0x01 -#define RF_IQADJ_G2 0x02 -#define RF_BS_PA_APSET_G1_G4 0x03 -#define RF_BS_PA_APSET_G5_G8 0x04 -#define RF_POW_TRSW 0x05 -#define RF_GAIN_RX 0x06 -#define RF_GAIN_TX 0x07 -#define RF_TXM_IDAC 0x08 -#define RF_IPA_G 0x09 -#define RF_TXBIAS_G 0x0A -#define RF_TXPA_AG 0x0B -#define RF_IPA_A 0x0C -#define RF_TXBIAS_A 0x0D -#define RF_BS_PA_APSET_G9_G11 0x0E -#define RF_BS_IQGEN 0x0F -#define RF_MODE1 0x10 -#define RF_MODE2 0x11 -#define RF_RX_AGC_HP 0x12 -#define RF_TX_AGC 0x13 -#define RF_BIAS 0x14 -#define RF_IPA 0x15 -#define RF_TXBIAS 0x16 -#define RF_POW_ABILITY 0x17 -#define RF_MODE_AG 0x18 -#define rRfChannel 0x18 /* RF channel and BW switch */ -#define RF_CHNLBW 0x18 /* RF channel and BW switch */ -#define RF_TOP 0x19 -#define RF_RX_G1 0x1A -#define RF_RX_G2 0x1B -#define RF_RX_BB2 0x1C -#define RF_RX_BB1 0x1D -#define RF_RCK1 0x1E -#define RF_RCK2 0x1F -#define RF_TX_G1 0x20 -#define RF_TX_G2 0x21 -#define RF_TX_G3 0x22 -#define RF_TX_BB1 0x23 -#define RF_T_METER 0x24 -#define RF_SYN_G1 0x25 /* RF TX Power control */ -#define RF_SYN_G2 0x26 /* RF TX Power control */ -#define RF_SYN_G3 0x27 /* RF TX Power control */ -#define RF_SYN_G4 0x28 /* RF TX Power control */ -#define RF_SYN_G5 0x29 /* RF TX Power control */ -#define RF_SYN_G6 0x2A /* RF TX Power control */ -#define RF_SYN_G7 0x2B /* RF TX Power control */ -#define RF_SYN_G8 0x2C /* RF TX Power control */ - -#define RF_RCK_OS 0x30 /* RF TX PA control */ - -#define RF_TXPA_G1 0x31 /* RF TX PA control */ -#define RF_TXPA_G2 0x32 /* RF TX PA control */ -#define RF_TXPA_G3 0x33 /* RF TX PA control */ - -/* Bit Mask */ -/* 1. Page1(0x100) */ -#define bBBResetB 0x100 /* Useless now? */ -#define bGlobalResetB 0x200 -#define bOFDMTxStart 0x4 -#define bCCKTxStart 0x8 -#define bCRC32Debug 0x100 -#define bPMACLoopback 0x10 -#define bTxLSIG 0xffffff -#define bOFDMTxRate 0xf -#define bOFDMTxReserved 0x10 -#define bOFDMTxLength 0x1ffe0 -#define bOFDMTxParity 0x20000 -#define bTxHTSIG1 0xffffff -#define bTxHTMCSRate 0x7f -#define bTxHTBW 0x80 -#define bTxHTLength 0xffff00 -#define bTxHTSIG2 0xffffff -#define bTxHTSmoothing 0x1 -#define bTxHTSounding 0x2 -#define bTxHTReserved 0x4 -#define bTxHTAggreation 0x8 -#define bTxHTSTBC 0x30 -#define bTxHTAdvanceCoding 0x40 -#define bTxHTShortGI 0x80 -#define bTxHTNumberHT_LTF 0x300 -#define bTxHTCRC8 0x3fc00 -#define bCounterReset 0x10000 -#define bNumOfOFDMTx 0xffff -#define bNumOfCCKTx 0xffff0000 -#define bTxIdleInterval 0xffff -#define bOFDMService 0xffff0000 -#define bTxMACHeader 0xffffffff -#define bTxDataInit 0xff -#define bTxHTMode 0x100 -#define bTxDataType 0x30000 -#define bTxRandomSeed 0xffffffff -#define bCCKTxPreamble 0x1 -#define bCCKTxSFD 0xffff0000 -#define bCCKTxSIG 0xff -#define bCCKTxService 0xff00 -#define bCCKLengthExt 0x8000 -#define bCCKTxLength 0xffff0000 -#define bCCKTxCRC16 0xffff -#define bCCKTxStatus 0x1 -#define bOFDMTxStatus 0x2 - -#define IS_BB_REG_OFFSET_92S(_Offset) \ - ((_Offset >= 0x800) && (_Offset <= 0xfff)) - -/* 2. Page8(0x800) */ -#define bRFMOD 0x1 /* Reg 0x800 rFPGA0_RFMOD */ -#define bJapanMode 0x2 -#define bCCKTxSC 0x30 -#define bCCKEn 0x1000000 -#define bOFDMEn 0x2000000 - -#define bOFDMRxADCPhase 0x10000 /* Useless now */ -#define bOFDMTxDACPhase 0x40000 -#define bXATxAGC 0x3f - -#define bAntennaSelect 0x0300 - -#define bXBTxAGC 0xf00 /* Reg 80c rFPGA0_TxGainStage */ -#define bXCTxAGC 0xf000 -#define bXDTxAGC 0xf0000 - -#define bPAStart 0xf0000000 /* Useless now */ -#define bTRStart 0x00f00000 -#define bRFStart 0x0000f000 -#define bBBStart 0x000000f0 -#define bBBCCKStart 0x0000000f -#define bPAEnd 0xf /* Reg0x814 */ -#define bTREnd 0x0f000000 -#define bRFEnd 0x000f0000 -#define bCCAMask 0x000000f0 /* T2R */ -#define bR2RCCAMask 0x00000f00 -#define bHSSI_R2TDelay 0xf8000000 -#define bHSSI_T2RDelay 0xf80000 -#define bContTxHSSI 0x400 /* chane gain at continue Tx */ -#define bIGFromCCK 0x200 -#define bAGCAddress 0x3f -#define bRxHPTx 0x7000 -#define bRxHPT2R 0x38000 -#define bRxHPCCKIni 0xc0000 -#define bAGCTxCode 0xc00000 -#define bAGCRxCode 0x300000 - -#define b3WireDataLength 0x800 /* Reg 0x820~84f rFPGA0_XA_HSSIParameter1 */ -#define b3WireAddressLength 0x400 - -#define b3WireRFPowerDown 0x1 /* Useless now */ -/* define bHWSISelect 0x8 */ -#define b5GPAPEPolarity 0x40000000 -#define b2GPAPEPolarity 0x80000000 -#define bRFSW_TxDefaultAnt 0x3 -#define bRFSW_TxOptionAnt 0x30 -#define bRFSW_RxDefaultAnt 0x300 -#define bRFSW_RxOptionAnt 0x3000 -#define bRFSI_3WireData 0x1 -#define bRFSI_3WireClock 0x2 -#define bRFSI_3WireLoad 0x4 -#define bRFSI_3WireRW 0x8 -#define bRFSI_3Wire 0xf - -#define bRFSI_RFENV 0x10 /* Reg 0x870 rFPGA0_XAB_RFInterfaceSW */ - -#define bRFSI_TRSW 0x20 /* Useless now */ -#define bRFSI_TRSWB 0x40 -#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 -#define bHTSIG2_Sounding 0x02 -#define bHTSIG2_Aggreaton 0x08 -#define bHTSIG2_STBC 0x30 -#define bHTSIG2_AdvCoding 0x40 -#define bHTSIG2_NumOfHTLTF 0x300 -#define bHTSIG2_CRC8 0x3fc -#define bHTSIG1_MCS 0x7f -#define bHTSIG1_BandWidth 0x80 -#define bHTSIG1_HTLength 0xffff -#define bLSIG_Rate 0xf -#define bLSIG_Reserved 0x10 -#define bLSIG_Length 0x1fffe -#define bLSIG_Parity 0x20 -#define bCCKRxPhase 0x4 - -#define bLSSIReadAddress 0x7f800000 /* T65 RF */ - -#define bLSSIReadEdge 0x80000000 /* LSSI "Read" edge signal */ - -#define bLSSIReadBackData 0xfffff /* T65 RF */ - -#define bLSSIReadOKFlag 0x1000 /* Useless now */ -#define bCCKSampleRate 0x8 /* 0: 44MHz, 1:88MHz */ -#define bRegulator0Standby 0x1 -#define bRegulatorPLLStandby 0x2 -#define bRegulator1Standby 0x4 -#define bPLLPowerUp 0x8 -#define bDPLLPowerUp 0x10 -#define bDA10PowerUp 0x20 -#define bAD7PowerUp 0x200 -#define bDA6PowerUp 0x2000 -#define bXtalPowerUp 0x4000 -#define b40MDClkPowerUP 0x8000 -#define bDA6DebugMode 0x20000 -#define bDA6Swing 0x380000 - -#define bADClkPhase 0x4000000 /* Reg 0x880 rFPGA0_AnalogParameter1 20/40 CCK support switch 40/80 BB MHZ */ - -#define b80MClkDelay 0x18000000 /* Useless */ -#define bAFEWatchDogEnable 0x20000000 - -#define bXtalCap01 0xc0000000 /* Reg 0x884 rFPGA0_AnalogParameter2 Crystal cap */ -#define bXtalCap23 0x3 -#define bXtalCap92x 0x0f000000 -#define bXtalCap 0x0f000000 - -#define bIntDifClkEnable 0x400 /* Useless */ -#define bExtSigClkEnable 0x800 -#define bBandgapMbiasPowerUp 0x10000 -#define bAD11SHGain 0xc0000 -#define bAD11InputRange 0x700000 -#define bAD11OPCurrent 0x3800000 -#define bIPathLoopback 0x4000000 -#define bQPathLoopback 0x8000000 -#define bAFELoopback 0x10000000 -#define bDA10Swing 0x7e0 -#define bDA10Reverse 0x800 -#define bDAClkSource 0x1000 -#define bAD7InputRange 0x6000 -#define bAD7Gain 0x38000 -#define bAD7OutputCMMode 0x40000 -#define bAD7InputCMMode 0x380000 -#define bAD7Current 0xc00000 -#define bRegulatorAdjust 0x7000000 -#define bAD11PowerUpAtTx 0x1 -#define bDA10PSAtTx 0x10 -#define bAD11PowerUpAtRx 0x100 -#define bDA10PSAtRx 0x1000 -#define bCCKRxAGCFormat 0x200 -#define bPSDFFTSamplepPoint 0xc000 -#define bPSDAverageNum 0x3000 -#define bIQPathControl 0xc00 -#define bPSDFreq 0x3ff -#define bPSDAntennaPath 0x30 -#define bPSDIQSwitch 0x40 -#define bPSDRxTrigger 0x400000 -#define bPSDTxTrigger 0x80000000 -#define bPSDSineToneScale 0x7f000000 -#define bPSDReport 0xffff - -/* 3. Page9(0x900) */ -#define bOFDMTxSC 0x30000000 /* Useless */ -#define bCCKTxOn 0x1 -#define bOFDMTxOn 0x2 -#define bDebugPage 0xfff /* reset debug page and also HWord, LWord */ -#define bDebugItem 0xff /* reset debug page and LWord */ -#define bAntL 0x10 -#define bAntNonHT 0x100 -#define bAntHT1 0x1000 -#define bAntHT2 0x10000 -#define bAntHT1S1 0x100000 -#define bAntNonHTS1 0x1000000 - -/* 4. PageA(0xA00) */ -#define bCCKBBMode 0x3 /* Useless */ -#define bCCKTxPowerSaving 0x80 -#define bCCKRxPowerSaving 0x40 - -#define bCCKSideBand 0x10 /* Reg 0xa00 rCCK0_System 20/40 switch */ - -#define bCCKScramble 0x8 /* Useless */ -#define bCCKAntDiversity 0x8000 -#define bCCKCarrierRecovery 0x4000 -#define bCCKTxRate 0x3000 -#define bCCKDCCancel 0x0800 -#define bCCKISICancel 0x0400 -#define bCCKMatchFilter 0x0200 -#define bCCKEqualizer 0x0100 -#define bCCKPreambleDetect 0x800000 -#define bCCKFastFalseCCA 0x400000 -#define bCCKChEstStart 0x300000 -#define bCCKCCACount 0x080000 -#define bCCKcs_lim 0x070000 -#define bCCKBistMode 0x80000000 -#define bCCKCCAMask 0x40000000 -#define bCCKTxDACPhase 0x4 -#define bCCKRxADCPhase 0x20000000 /* r_rx_clk */ -#define bCCKr_cp_mode0 0x0100 -#define bCCKTxDCOffset 0xf0 -#define bCCKRxDCOffset 0xf -#define bCCKCCAMode 0xc000 -#define bCCKFalseCS_lim 0x3f00 -#define bCCKCS_ratio 0xc00000 -#define bCCKCorgBit_sel 0x300000 -#define bCCKPD_lim 0x0f0000 -#define bCCKNewCCA 0x80000000 -#define bCCKRxHPofIG 0x8000 -#define bCCKRxIG 0x7f00 -#define bCCKLNAPolarity 0x800000 -#define bCCKRx1stGain 0x7f0000 -#define bCCKRFExtend 0x20000000 /* CCK Rx Iinital gain polarity */ -#define bCCKRxAGCSatLevel 0x1f000000 -#define bCCKRxAGCSatCount 0xe0 -#define bCCKRxRFSettle 0x1f /* AGCsamp_dly */ -#define bCCKFixedRxAGC 0x8000 -/* define bCCKRxAGCFormat 0x4000 remove to HSSI register 0x824 */ -#define bCCKAntennaPolarity 0x2000 -#define bCCKTxFilterType 0x0c00 -#define bCCKRxAGCReportType 0x0300 -#define bCCKRxDAGCEn 0x80000000 -#define bCCKRxDAGCPeriod 0x20000000 -#define bCCKRxDAGCSatLevel 0x1f000000 -#define bCCKTimingRecovery 0x800000 -#define bCCKTxC0 0x3f0000 -#define bCCKTxC1 0x3f000000 -#define bCCKTxC2 0x3f -#define bCCKTxC3 0x3f00 -#define bCCKTxC4 0x3f0000 -#define bCCKTxC5 0x3f000000 -#define bCCKTxC6 0x3f -#define bCCKTxC7 0x3f00 -#define bCCKDebugPort 0xff0000 -#define bCCKDACDebug 0x0f000000 -#define bCCKFalseAlarmEnable 0x8000 -#define bCCKFalseAlarmRead 0x4000 -#define bCCKTRSSI 0x7f -#define bCCKRxAGCReport 0xfe -#define bCCKRxReport_AntSel 0x80000000 -#define bCCKRxReport_MFOff 0x40000000 -#define bCCKRxRxReport_SQLoss 0x20000000 -#define bCCKRxReport_Pktloss 0x10000000 -#define bCCKRxReport_Lockedbit 0x08000000 -#define bCCKRxReport_RateError 0x04000000 -#define bCCKRxReport_RxRate 0x03000000 -#define bCCKRxFACounterLower 0xff -#define bCCKRxFACounterUpper 0xff000000 -#define bCCKRxHPAGCStart 0xe000 -#define bCCKRxHPAGCFinal 0x1c00 -#define bCCKRxFalseAlarmEnable 0x8000 -#define bCCKFACounterFreeze 0x4000 -#define bCCKTxPathSel 0x10000000 -#define bCCKDefaultRxPath 0xc000000 -#define bCCKOptionRxPath 0x3000000 - -/* 5. PageC(0xC00) */ -#define bNumOfSTF 0x3 /* Useless */ -#define bShift_L 0xc0 -#define bGI_TH 0xc -#define bRxPathA 0x1 -#define bRxPathB 0x2 -#define bRxPathC 0x4 -#define bRxPathD 0x8 -#define bTxPathA 0x1 -#define bTxPathB 0x2 -#define bTxPathC 0x4 -#define bTxPathD 0x8 -#define bTRSSIFreq 0x200 -#define bADCBackoff 0x3000 -#define bDFIRBackoff 0xc000 -#define bTRSSILatchPhase 0x10000 -#define bRxIDCOffset 0xff -#define bRxQDCOffset 0xff00 -#define bRxDFIRMode 0x1800000 -#define bRxDCNFType 0xe000000 -#define bRXIQImb_A 0x3ff -#define bRXIQImb_B 0xfc00 -#define bRXIQImb_C 0x3f0000 -#define bRXIQImb_D 0xffc00000 -#define bDC_dc_Notch 0x60000 -#define bRxNBINotch 0x1f000000 -#define bPD_TH 0xf -#define bPD_TH_Opt2 0xc000 -#define bPWED_TH 0x700 -#define bIfMF_Win_L 0x800 -#define bPD_Option 0x1000 -#define bMF_Win_L 0xe000 -#define bBW_Search_L 0x30000 -#define bwin_enh_L 0xc0000 -#define bBW_TH 0x700000 -#define bED_TH2 0x3800000 -#define bBW_option 0x4000000 -#define bRatio_TH 0x18000000 -#define bWindow_L 0xe0000000 -#define bSBD_Option 0x1 -#define bFrame_TH 0x1c -#define bFS_Option 0x60 -#define bDC_Slope_check 0x80 -#define bFGuard_Counter_DC_L 0xe00 -#define bFrame_Weight_Short 0x7000 -#define bSub_Tune 0xe00000 -#define bFrame_DC_Length 0xe000000 -#define bSBD_start_offset 0x30000000 -#define bFrame_TH_2 0x7 -#define bFrame_GI2_TH 0x38 -#define bGI2_Sync_en 0x40 -#define bSarch_Short_Early 0x300 -#define bSarch_Short_Late 0xc00 -#define bSarch_GI2_Late 0x70000 -#define bCFOAntSum 0x1 -#define bCFOAcc 0x2 -#define bCFOStartOffset 0xc -#define bCFOLookBack 0x70 -#define bCFOSumWeight 0x80 -#define bDAGCEnable 0x10000 -#define bTXIQImb_A 0x3ff -#define bTXIQImb_B 0xfc00 -#define bTXIQImb_C 0x3f0000 -#define bTXIQImb_D 0xffc00000 -#define bTxIDCOffset 0xff -#define bTxQDCOffset 0xff00 -#define bTxDFIRMode 0x10000 -#define bTxPesudoNoiseOn 0x4000000 -#define bTxPesudoNoise_A 0xff -#define bTxPesudoNoise_B 0xff00 -#define bTxPesudoNoise_C 0xff0000 -#define bTxPesudoNoise_D 0xff000000 -#define bCCADropOption 0x20000 -#define bCCADropThres 0xfff00000 -#define bEDCCA_H 0xf -#define bEDCCA_L 0xf0 -#define bLambda_ED 0x300 -#define bRxInitialGain 0x7f -#define bRxAntDivEn 0x80 -#define bRxAGCAddressForLNA 0x7f00 -#define bRxHighPowerFlow 0x8000 -#define bRxAGCFreezeThres 0xc0000 -#define bRxFreezeStep_AGC1 0x300000 -#define bRxFreezeStep_AGC2 0xc00000 -#define bRxFreezeStep_AGC3 0x3000000 -#define bRxFreezeStep_AGC0 0xc000000 -#define bRxRssi_Cmp_En 0x10000000 -#define bRxQuickAGCEn 0x20000000 -#define bRxAGCFreezeThresMode 0x40000000 -#define bRxOverFlowCheckType 0x80000000 -#define bRxAGCShift 0x7f -#define bTRSW_Tri_Only 0x80 -#define bPowerThres 0x300 -#define bRxAGCEn 0x1 -#define bRxAGCTogetherEn 0x2 -#define bRxAGCMin 0x4 -#define bRxHP_Ini 0x7 -#define bRxHP_TRLNA 0x70 -#define bRxHP_RSSI 0x700 -#define bRxHP_BBP1 0x7000 -#define bRxHP_BBP2 0x70000 -#define bRxHP_BBP3 0x700000 -#define bRSSI_H 0x7f0000 /* the threshold for high power */ -#define bRSSI_Gen 0x7f000000 /* the threshold for ant diversity */ -#define bRxSettle_TRSW 0x7 -#define bRxSettle_LNA 0x38 -#define bRxSettle_RSSI 0x1c0 -#define bRxSettle_BBP 0xe00 -#define bRxSettle_RxHP 0x7000 -#define bRxSettle_AntSW_RSSI 0x38000 -#define bRxSettle_AntSW 0xc0000 -#define bRxProcessTime_DAGC 0x300000 -#define bRxSettle_HSSI 0x400000 -#define bRxProcessTime_BBPPW 0x800000 -#define bRxAntennaPowerShift 0x3000000 -#define bRSSITableSelect 0xc000000 -#define bRxHP_Final 0x7000000 -#define bRxHTSettle_BBP 0x7 -#define bRxHTSettle_HSSI 0x8 -#define bRxHTSettle_RxHP 0x70 -#define bRxHTSettle_BBPPW 0x80 -#define bRxHTSettle_Idle 0x300 -#define bRxHTSettle_Reserved 0x1c00 -#define bRxHTRxHPEn 0x8000 -#define bRxHTAGCFreezeThres 0x30000 -#define bRxHTAGCTogetherEn 0x40000 -#define bRxHTAGCMin 0x80000 -#define bRxHTAGCEn 0x100000 -#define bRxHTDAGCEn 0x200000 -#define bRxHTRxHP_BBP 0x1c00000 -#define bRxHTRxHP_Final 0xe0000000 -#define bRxPWRatioTH 0x3 -#define bRxPWRatioEn 0x4 -#define bRxMFHold 0x3800 -#define bRxPD_Delay_TH1 0x38 -#define bRxPD_Delay_TH2 0x1c0 -#define bRxPD_DC_COUNT_MAX 0x600 -/* define bRxMF_Hold 0x3800 */ -#define bRxPD_Delay_TH 0x8000 -#define bRxProcess_Delay 0xf0000 -#define bRxSearchrange_GI2_Early 0x700000 -#define bRxFrame_Guard_Counter_L 0x3800000 -#define bRxSGI_Guard_L 0xc000000 -#define bRxSGI_Search_L 0x30000000 -#define bRxSGI_TH 0xc0000000 -#define bDFSCnt0 0xff -#define bDFSCnt1 0xff00 -#define bDFSFlag 0xf0000 -#define bMFWeightSum 0x300000 -#define bMinIdxTH 0x7f000000 -#define bDAFormat 0x40000 -#define bTxChEmuEnable 0x01000000 -#define bTRSWIsolation_A 0x7f -#define bTRSWIsolation_B 0x7f00 -#define bTRSWIsolation_C 0x7f0000 -#define bTRSWIsolation_D 0x7f000000 -#define bExtLNAGain 0x7c00 - -/* 6. PageE(0xE00) */ -#define bSTBCEn 0x4 /* Useless */ -#define bAntennaMapping 0x10 -#define bNss 0x20 -#define bCFOAntSumD 0x200 -#define bPHYCounterReset 0x8000000 -#define bCFOReportGet 0x4000000 -#define bOFDMContinueTx 0x10000000 -#define bOFDMSingleCarrier 0x20000000 -#define bOFDMSingleTone 0x40000000 -/* define bRxPath1 0x01 */ -/* define bRxPath2 0x02 */ -/* define bRxPath3 0x04 */ -/* define bRxPath4 0x08 */ -/* define bTxPath1 0x10 */ -/* define bTxPath2 0x20 */ -#define bHTDetect 0x100 -#define bCFOEn 0x10000 -#define bCFOValue 0xfff00000 -#define bSigTone_Re 0x3f -#define bSigTone_Im 0x7f00 -#define bCounter_CCA 0xffff -#define bCounter_ParityFail 0xffff0000 -#define bCounter_RateIllegal 0xffff -#define bCounter_CRC8Fail 0xffff0000 -#define bCounter_MCSNoSupport 0xffff -#define bCounter_FastSync 0xffff -#define bShortCFO 0xfff -#define bShortCFOTLength 12 /* total */ -#define bShortCFOFLength 11 /* fraction */ -#define bLongCFO 0x7ff -#define bLongCFOTLength 11 -#define bLongCFOFLength 11 -#define bTailCFO 0x1fff -#define bTailCFOTLength 13 -#define bTailCFOFLength 12 -#define bmax_en_pwdB 0xffff -#define bCC_power_dB 0xffff0000 -#define bnoise_pwdB 0xffff -#define bPowerMeasTLength 10 -#define bPowerMeasFLength 3 -#define bRx_HT_BW 0x1 -#define bRxSC 0x6 -#define bRx_HT 0x8 -#define bNB_intf_det_on 0x1 -#define bIntf_win_len_cfg 0x30 -#define bNB_Intf_TH_cfg 0x1c0 -#define bRFGain 0x3f -#define bTableSel 0x40 -#define bTRSW 0x80 -#define bRxSNR_A 0xff -#define bRxSNR_B 0xff00 -#define bRxSNR_C 0xff0000 -#define bRxSNR_D 0xff000000 -#define bSNREVMTLength 8 -#define bSNREVMFLength 1 -#define bCSI1st 0xff -#define bCSI2nd 0xff00 -#define bRxEVM1st 0xff0000 -#define bRxEVM2nd 0xff000000 -#define bSIGEVM 0xff -#define bPWDB 0xff00 -#define bSGIEN 0x10000 - -#define bSFactorQAM1 0xf /* Useless */ -#define bSFactorQAM2 0xf0 -#define bSFactorQAM3 0xf00 -#define bSFactorQAM4 0xf000 -#define bSFactorQAM5 0xf0000 -#define bSFactorQAM6 0xf0000 -#define bSFactorQAM7 0xf00000 -#define bSFactorQAM8 0xf000000 -#define bSFactorQAM9 0xf0000000 -#define bCSIScheme 0x100000 - -#define bNoiseLvlTopSet 0x3 /* Useless */ -#define bChSmooth 0x4 -#define bChSmoothCfg1 0x38 -#define bChSmoothCfg2 0x1c0 -#define bChSmoothCfg3 0xe00 -#define bChSmoothCfg4 0x7000 -#define bMRCMode 0x800000 -#define bTHEVMCfg 0x7000000 - -#define bLoopFitType 0x1 /* Useless */ -#define bUpdCFO 0x40 -#define bUpdCFOOffData 0x80 -#define bAdvUpdCFO 0x100 -#define bAdvTimeCtrl 0x800 -#define bUpdClko 0x1000 -#define bFC 0x6000 -#define bTrackingMode 0x8000 -#define bPhCmpEnable 0x10000 -#define bUpdClkoLTF 0x20000 -#define bComChCFO 0x40000 -#define bCSIEstiMode 0x80000 -#define bAdvUpdEqz 0x100000 -#define bUChCfg 0x7000000 -#define bUpdEqz 0x8000000 - -/* Rx Pseduo noise */ -#define bRxPesudoNoiseOn 0x20000000 /* Useless */ -#define bRxPesudoNoise_A 0xff -#define bRxPesudoNoise_B 0xff00 -#define bRxPesudoNoise_C 0xff0000 -#define bRxPesudoNoise_D 0xff000000 -#define bPesudoNoiseState_A 0xffff -#define bPesudoNoiseState_B 0xffff0000 -#define bPesudoNoiseState_C 0xffff -#define bPesudoNoiseState_D 0xffff0000 - -/* 7. RF Register */ -/* Zebra1 */ -#define bZebra1_HSSIEnable 0x8 /* Useless */ -#define bZebra1_TRxControl 0xc00 -#define bZebra1_TRxGainSetting 0x07f -#define bZebra1_RxCorner 0xc00 -#define bZebra1_TxChargePump 0x38 -#define bZebra1_RxChargePump 0x7 -#define bZebra1_ChannelNum 0xf80 -#define bZebra1_TxLPFBW 0x400 -#define bZebra1_RxLPFBW 0x600 - -/* Zebra4 */ -#define bRTL8256RegModeCtrl1 0x100 /* Useless */ -#define bRTL8256RegModeCtrl0 0x40 -#define bRTL8256_TxLPFBW 0x18 -#define bRTL8256_RxLPFBW 0x600 - -/* RTL8258 */ -#define bRTL8258_TxLPFBW 0xc /* Useless */ -#define bRTL8258_RxLPFBW 0xc00 -#define bRTL8258_RSSILPFBW 0xc0 - - -/* Other Definition */ - -/* byte endable for sb_write */ -#define bByte0 0x1 /* Useless */ -#define bByte1 0x2 -#define bByte2 0x4 -#define bByte3 0x8 -#define bWord0 0x3 -#define bWord1 0xc -#define bDWord 0xf - -/* for PutRegsetting & GetRegSetting BitMask */ -#define bMaskByte0 0xff /* Reg 0xc50 rOFDM0_XAAGCCore~0xC6f */ -#define bMaskByte1 0xff00 -#define bMaskByte2 0xff0000 -#define bMaskByte3 0xff000000 -#define bMaskHWord 0xffff0000 -#define bMaskLWord 0x0000ffff -#define bMaskDWord 0xffffffff -#define bMask12Bits 0xfff -#define bMaskH4Bits 0xf0000000 -#define bMaskOFDM_D 0xffc00000 -#define bMaskCCK 0x3f3f3f3f - -/* for PutRFRegsetting & GetRFRegSetting BitMask */ -#define bRFRegOffsetMask 0xfffff - -#define bDisable 0x0 - -#define LeftAntenna 0x0 /* Useless */ -#define RightAntenna 0x1 - -#define tCheckTxStatus 500 /* 500ms Useless */ -#define tUpdateRxCounter 100 /* 100ms */ - -#define rateCCK 0 /* Useless */ -#define rateOFDM 1 -#define rateHT 2 - -/* define Register-End */ -#define bPMAC_End 0x1ff /* Useless */ -#define bFPGAPHY0_End 0x8ff -#define bFPGAPHY1_End 0x9ff -#define bCCKPHY0_End 0xaff -#define bOFDMPHY0_End 0xcff -#define bOFDMPHY1_End 0xdff - -/* define max debug item in each debug page */ -/* define bMaxItem_FPGA_PHY0 0x9 */ -/* define bMaxItem_FPGA_PHY1 0x3 */ -/* define bMaxItem_PHY_11B 0x16 */ -/* define bMaxItem_OFDM_PHY0 0x29 */ -/* define bMaxItem_OFDM_PHY1 0x0 */ - -#define bPMACControl 0x0 /* Useless */ -#define bWMACControl 0x1 -#define bWNICControl 0x2 - -#define PathA 0x0 /* Useless */ -#define PathB 0x1 -#define PathC 0x2 -#define PathD 0x3 - -/* PageB(0xB00) */ -#define rPdp_AntA 0xb00 -#define rPdp_AntA_4 0xb04 -#define rPdp_AntA_8 0xb08 -#define rPdp_AntA_C 0xb0c -#define rPdp_AntA_18 0xb18 -#define rPdp_AntA_1C 0xb1c -#define rPdp_AntA_20 0xb20 -#define rPdp_AntA_24 0xb24 - -#define rConfig_Pmpd_AntA 0xb28 -#define rConfig_ram64x16 0xb2c - -#define rBndA 0xb30 -#define rHssiPar 0xb34 - -#define rConfig_AntA 0xb68 -#define rConfig_AntB 0xb6c - -#define rPdp_AntB 0xb70 -#define rPdp_AntB_4 0xb74 -#define rPdp_AntB_8 0xb78 -#define rPdp_AntB_C 0xb7c -#define rPdp_AntB_10 0xb80 -#define rPdp_AntB_14 0xb84 -#define rPdp_AntB_18 0xb88 -#define rPdp_AntB_1C 0xb8c -#define rPdp_AntB_20 0xb90 -#define rPdp_AntB_24 0xb94 - -#define rConfig_Pmpd_AntB 0xb98 - -#define rBndB 0xba0 - -#define rAPK 0xbd8 -#define rPm_Rx0_AntA 0xbdc -#define rPm_Rx1_AntA 0xbe0 -#define rPm_Rx2_AntA 0xbe4 -#define rPm_Rx3_AntA 0xbe8 -#define rPm_Rx0_AntB 0xbec -#define rPm_Rx1_AntB 0xbf0 -#define rPm_Rx2_AntB 0xbf4 -#define rPm_Rx3_AntB 0xbf8 - -#endif diff --git a/drivers/staging/rtl8723au/include/Hal8723PwrSeq.h b/drivers/staging/rtl8723au/include/Hal8723PwrSeq.h deleted file mode 100644 index 3771d6b..0000000 --- a/drivers/staging/rtl8723au/include/Hal8723PwrSeq.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef __HAL8723PWRSEQ_H__ -#define __HAL8723PWRSEQ_H__ -/* - Check document WM-20110607-Paul-RTL8723A_Power_Architecture-R02.vsd - There are 6 HW Power States: - 0: POFF--Power Off - 1: PDN--Power Down - 2: CARDEMU--Card Emulation - 3: ACT--Active Mode - 4: LPS--Low Power State - 5: SUS--Suspend - - The transision from different states are defined below - TRANS_CARDEMU_TO_ACT - TRANS_ACT_TO_CARDEMU - TRANS_CARDEMU_TO_SUS - TRANS_SUS_TO_CARDEMU - TRANS_CARDEMU_TO_PDN - TRANS_ACT_TO_LPS - TRANS_LPS_TO_ACT - - TRANS_END -*/ -#include "HalPwrSeqCmd.h" -#include "rtl8723a_spec.h" - -#define RTL8723A_TRANS_CARDEMU_TO_ACT_STEPS 15 -#define RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS 15 -#define RTL8723A_TRANS_CARDEMU_TO_SUS_STEPS 15 -#define RTL8723A_TRANS_SUS_TO_CARDEMU_STEPS 15 -#define RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS 15 -#define RTL8723A_TRANS_PDN_TO_CARDEMU_STEPS 15 -#define RTL8723A_TRANS_ACT_TO_LPS_STEPS 15 -#define RTL8723A_TRANS_LPS_TO_ACT_STEPS 15 -#define RTL8723A_TRANS_END_STEPS 1 - - -/* format - * { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, comments here - */ -#define RTL8723A_TRANS_CARDEMU_TO_ACT \ - {0x0020, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)}, /*0x20[0] = 1b'1 enable LDOA12 MACRO block for all interface*/ \ - {0x0067, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, /*0x67[0] = 0 to disable BT_GPS_SEL pins*/ \ - {0x0001, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_DELAY, 1, PWRSEQ_DELAY_MS},/*Delay 1ms*/ \ - {0x0000, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), 0}, /*0x00[5] = 1b'0 release analog Ips to digital , 1:isolation*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(2), 0},/* disable SW LPS 0x04[10]= 0*/ \ - {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), BIT(1)},/* wait till 0x04[17] = 1 power ready*/ \ - {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)},/* release WLON reset 0x04[16]= 1*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0},/* disable HWPDN 0x04[15]= 0*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, (BIT(4)|BIT(3)), 0},/* disable WL suspend*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)},/* polling until return 0*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(0), 0},/**/ \ - {0x004E, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 1},/*0x4C[23] = 0x4E[7] = 1, switch DPDT_SEL_P output from WL BB */\ - -#define RTL8723A_TRANS_ACT_TO_CARDEMU \ - {0x001F, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0},/*0x1F[7:0] = 0 turn off RF*/ \ - {0x004E, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0},/*0x4C[23] = 0x4E[7] = 0, switch DPDT_SEL_P output from register 0x65[2] */\ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)}, /*0x04[9] = 1 turn off MAC by HW state machine*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), 0}, /*wait till 0x04[9] = 0 polling until return 0 to disable*/ \ - {0x0000, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), BIT(5)}, /*0x00[5] = 1b'1 analog Ips to digital , 1:isolation*/ \ - {0x0020, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0}, /*0x20[0] = 1b'0 disable LDOA12 MACRO block*/ \ - - -#define RTL8723A_TRANS_CARDEMU_TO_SUS \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, /*0x04[12:11] = 2b'01 enable WL suspend*/ - -#define RTL8723A_TRANS_SUS_TO_CARDEMU \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3) | BIT(7), 0}, /*clear suspend enable and power down enable*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0}, /*0x04[12:11] = 2b'01enable WL suspend*/ - -#define RTL8723A_TRANS_CARDEMU_TO_CARDDIS \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, /*0x04[12:11] = 2b'01 enable WL suspend*/ \ - {0x004A, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)}, /*0x48[16] = 1 to enable GPIO9 as EXT WAKEUP*/ - -#define RTL8723A_TRANS_CARDDIS_TO_CARDEMU \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3) | BIT(7), 0}, /*clear suspend enable and power down enable*/ \ - {0x004A, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0}, /*0x48[16] = 0 to disable GPIO9 as EXT WAKEUP*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0}, /*0x04[12:11] = 2b'01enable WL suspend*/ - -#define RTL8723A_TRANS_CARDEMU_TO_PDN \ - {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x20}, /*0x07[7:0] = 0x20 SOP option to disable BG/MB/ACK/SWR*/ \ - {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0},/* 0x04[16] = 0*/\ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7)},/* 0x04[15] = 1*/ - -#define RTL8723A_TRANS_PDN_TO_CARDEMU \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0},/* 0x04[15] = 0*/ - -#define RTL8723A_TRANS_ACT_TO_LPS \ - {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF},/*Tx Pause*/ \ - {0x05F8, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0},/*Should be zero if no packet is transmitting*/ \ - {0x05F9, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0},/*Should be zero if no packet is transmitting*/ \ - {0x05FA, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0},/*Should be zero if no packet is transmitting*/ \ - {0x05FB, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0},/*Should be zero if no packet is transmitting*/ \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0},/*CCK and OFDM are disabled, and clock are gated*/ \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_US},/*Delay 1us*/ \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), 0},/*Whole BB is reset*/ \ - {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x03},/*Reset MAC TRX*/ \ - {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), 0},/*check if removed later*/ \ - {0x0553, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), BIT(5)},/*Respond TxOK to scheduler*/ - -#define RTL8723A_TRANS_LPS_TO_ACT \ - {0xFE58, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84}, /*USB RPWM*/\ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_MS}, /*Delay*/\ - {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, /*. 0x08[4] = 0 switch TSF to 40M*/\ - {0x0109, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(7), 0}, /*Polling 0x109[7]= 0 TSF in 40M*/\ - {0x0029, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(6)|BIT(7), 0}, /*. 0x29[7:6] = 2b'00 enable BB clock*/\ - {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)}, /*. 0x101[1] = 1*/\ - {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF}, /*. 0x100[7:0] = 0xFF enable WMAC TRX*/\ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1)|BIT(0), BIT(1)|BIT(0)}, /*. 0x02[1:0] = 2b'11 enable BB macro*/\ - {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0}, /*. 0x522 = 0*/ - -#define RTL8723A_TRANS_END \ - {0xFFFF, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, 0, PWR_CMD_END, 0, 0}, - - -extern struct wlan_pwr_cfg rtl8723AU_power_on_flow[RTL8723A_TRANS_CARDEMU_TO_ACT_STEPS+RTL8723A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723AU_radio_off_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723AU_card_disable_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS+RTL8723A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723AU_card_enable_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS+RTL8723A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723AU_suspend_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_SUS_STEPS+RTL8723A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723AU_resume_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_SUS_STEPS+RTL8723A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723AU_hwpdn_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS+RTL8723A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723AU_enter_lps_flow[RTL8723A_TRANS_ACT_TO_LPS_STEPS+RTL8723A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723AU_leave_lps_flow[RTL8723A_TRANS_LPS_TO_ACT_STEPS+RTL8723A_TRANS_END_STEPS]; - -#endif diff --git a/drivers/staging/rtl8723au/include/Hal8723UHWImg_CE.h b/drivers/staging/rtl8723au/include/Hal8723UHWImg_CE.h deleted file mode 100644 index c834b3a..0000000 --- a/drivers/staging/rtl8723au/include/Hal8723UHWImg_CE.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef __INC_HAL8723U_FW_IMG_H -#define __INC_HAL8723U_FW_IMG_H - -/*Created on 2013/01/14, 15:51*/ - -/* FW v16 enable usb interrupt */ -#define Rtl8723UImgArrayLength 22172 -extern u8 Rtl8723UFwImgArray[Rtl8723UImgArrayLength]; -#define Rtl8723UBTImgArrayLength 1 -extern u8 Rtl8723UFwBTImgArray[Rtl8723UBTImgArrayLength]; - -#define Rtl8723UUMCBCutImgArrayWithBTLength 24118 -#define Rtl8723UUMCBCutImgArrayWithoutBTLength 19200 - -extern u8 Rtl8723UFwUMCBCutImgArrayWithBT[Rtl8723UUMCBCutImgArrayWithBTLength]; -extern u8 Rtl8723UFwUMCBCutImgArrayWithoutBT[Rtl8723UUMCBCutImgArrayWithoutBTLength]; - -#define Rtl8723SUMCBCutMPImgArrayLength 24174 -extern const u8 Rtl8723SFwUMCBCutMPImgArray[Rtl8723SUMCBCutMPImgArrayLength]; - -#define Rtl8723EBTImgArrayLength 15276 -extern u8 Rtl8723EFwBTImgArray[Rtl8723EBTImgArrayLength]; - -#define Rtl8723UPHY_REG_Array_PGLength 336 -extern u32 Rtl8723UPHY_REG_Array_PG[Rtl8723UPHY_REG_Array_PGLength]; -#define Rtl8723UMACPHY_Array_PGLength 1 -extern u32 Rtl8723UMACPHY_Array_PG[Rtl8723UMACPHY_Array_PGLength]; - -#endif /* ifndef __INC_HAL8723U_FW_IMG_H */ diff --git a/drivers/staging/rtl8723au/include/HalDMOutSrc8723A.h b/drivers/staging/rtl8723au/include/HalDMOutSrc8723A.h deleted file mode 100644 index d7651f7..0000000 --- a/drivers/staging/rtl8723au/include/HalDMOutSrc8723A.h +++ /dev/null @@ -1,64 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * - ******************************************************************************/ -#ifndef __RTL8723A_ODM_H__ -#define __RTL8723A_ODM_H__ -/* */ - -#define RSSI_CCK 0 -#define RSSI_OFDM 1 -#define RSSI_DEFAULT 2 - -#define IQK_MAC_REG_NUM 4 -#define IQK_ADDA_REG_NUM 16 -#define IQK_BB_REG_NUM 9 -#define HP_THERMAL_NUM 8 - - -/* */ -/* structure and define */ -/* */ - - - - -/*------------------------Export global variable----------------------------*/ -/*------------------------Export global variable----------------------------*/ -/*------------------------Export Marco Definition---------------------------*/ -/* define DM_MultiSTA_InitGainChangeNotify(Event) {DM_DigTable.CurMultiSTAConnectState = Event;} */ - - -/* */ -/* function prototype */ -/* */ - -/* */ -/* IQ calibrate */ -/* */ -void rtl8723a_phy_iq_calibrate(struct rtw_adapter *pAdapter, bool bReCovery); - -/* */ -/* LC calibrate */ -/* */ -void rtl8723a_phy_lc_calibrate(struct rtw_adapter *pAdapter); - -/* */ -/* AP calibrate */ -/* */ -void rtl8723a_phy_ap_calibrate(struct rtw_adapter *pAdapter, char delta); - -void rtl8723a_odm_check_tx_power_tracking(struct rtw_adapter *Adapter); - -#endif diff --git a/drivers/staging/rtl8723au/include/HalHWImg8723A_BB.h b/drivers/staging/rtl8723au/include/HalHWImg8723A_BB.h deleted file mode 100644 index 1276094..0000000 --- a/drivers/staging/rtl8723au/include/HalHWImg8723A_BB.h +++ /dev/null @@ -1,38 +0,0 @@ -/****************************************************************************** -* -* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms of version 2 of the GNU General Public License as -* published by the Free Software Foundation. -* -* This program is distributed in the hope that it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* -******************************************************************************/ - -#ifndef __INC_BB_8723A_HW_IMG_H -#define __INC_BB_8723A_HW_IMG_H - -/****************************************************************************** -* AGC_TAB_1T.TXT -******************************************************************************/ - -void ODM_ReadAndConfig_AGC_TAB_1T_8723A(struct dm_odm_t *pDM_Odm); - -/****************************************************************************** -* PHY_REG_1T.TXT -******************************************************************************/ - -void ODM_ReadAndConfig_PHY_REG_1T_8723A(struct dm_odm_t *pDM_Odm); - -/****************************************************************************** -* PHY_REG_MP.TXT -******************************************************************************/ - -void ODM_ReadAndConfig_PHY_REG_MP_8723A(struct dm_odm_t *pDM_Odm); - -#endif /* end of HWIMG_SUPPORT */ diff --git a/drivers/staging/rtl8723au/include/HalHWImg8723A_FW.h b/drivers/staging/rtl8723au/include/HalHWImg8723A_FW.h deleted file mode 100644 index 7ee363b..0000000 --- a/drivers/staging/rtl8723au/include/HalHWImg8723A_FW.h +++ /dev/null @@ -1,28 +0,0 @@ -/****************************************************************************** -* -* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms of version 2 of the GNU General Public License as -* published by the Free Software Foundation. -* -* This program is distributed in the hope that it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* -******************************************************************************/ - -#ifndef __INC_FW_8723A_HW_IMG_H -#define __INC_FW_8723A_HW_IMG_H - - -/****************************************************************************** -* rtl8723fw_B.TXT -******************************************************************************/ - -void ODM_ReadFirmware_8723A_rtl8723fw_B(struct dm_odm_t *pDM_Odm, - u8 *pFirmware, u32 *pFirmwareSize); - -#endif /* end of HWIMG_SUPPORT */ diff --git a/drivers/staging/rtl8723au/include/HalHWImg8723A_MAC.h b/drivers/staging/rtl8723au/include/HalHWImg8723A_MAC.h deleted file mode 100644 index 201be1f..0000000 --- a/drivers/staging/rtl8723au/include/HalHWImg8723A_MAC.h +++ /dev/null @@ -1,26 +0,0 @@ -/****************************************************************************** -* -* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms of version 2 of the GNU General Public License as -* published by the Free Software Foundation. -* -* This program is distributed in the hope that it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* -******************************************************************************/ - -#ifndef __INC_MAC_8723A_HW_IMG_H -#define __INC_MAC_8723A_HW_IMG_H - -/****************************************************************************** -* MAC_REG.TXT -******************************************************************************/ - -void ODM_ReadAndConfig_MAC_REG_8723A(struct dm_odm_t *pDM_Odm); - -#endif /* end of HWIMG_SUPPORT */ diff --git a/drivers/staging/rtl8723au/include/HalHWImg8723A_RF.h b/drivers/staging/rtl8723au/include/HalHWImg8723A_RF.h deleted file mode 100644 index c9af1c3..0000000 --- a/drivers/staging/rtl8723au/include/HalHWImg8723A_RF.h +++ /dev/null @@ -1,25 +0,0 @@ -/****************************************************************************** -* -* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms of version 2 of the GNU General Public License as -* published by the Free Software Foundation. -* -* This program is distributed in the hope that it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -******************************************************************************/ - -#ifndef __INC_RF_8723A_HW_IMG_H -#define __INC_RF_8723A_HW_IMG_H - -/****************************************************************************** -* RadioA_1T.TXT -******************************************************************************/ - -void ODM_ReadAndConfig_RadioA_1T_8723A(struct dm_odm_t *pDM_Odm); - -#endif /* end of HWIMG_SUPPORT */ diff --git a/drivers/staging/rtl8723au/include/HalPwrSeqCmd.h b/drivers/staging/rtl8723au/include/HalPwrSeqCmd.h deleted file mode 100644 index 12e03a3..0000000 --- a/drivers/staging/rtl8723au/include/HalPwrSeqCmd.h +++ /dev/null @@ -1,130 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * - ******************************************************************************/ -#ifndef __HALPWRSEQCMD_H__ -#define __HALPWRSEQCMD_H__ - -#include <drv_types.h> - -/*---------------------------------------------*/ -/*---------------------------------------------*/ -#define PWR_CMD_READ 0x00 - /* offset: the read register offset */ - /* msk: the mask of the read value */ - /* value: N/A, left by 0 */ - /* note: dirver shall implement this function by read & msk */ - -#define PWR_CMD_WRITE 0x01 - /* offset: the read register offset */ - /* msk: the mask of the write bits */ - /* value: write value */ - /* note: driver shall implement this cmd by read & msk after write */ - -#define PWR_CMD_POLLING 0x02 - /* offset: the read register offset */ - /* msk: the mask of the polled value */ - /* value: the value to be polled, masked by the msd field. */ - /* note: driver shall implement this cmd by */ - /* do{ */ - /* if( (Read(offset) & msk) == (value & msk) ) */ - /* break; */ - /* } while(not timeout); */ - -#define PWR_CMD_DELAY 0x03 - /* offset: the value to delay */ - /* msk: N/A */ - /* value: the unit of delay, 0: us, 1: ms */ - -#define PWR_CMD_END 0x04 - /* offset: N/A */ - /* msk: N/A */ - /* value: N/A */ - -/*---------------------------------------------*/ -/* 3 The value of base: 4 bits */ -/*---------------------------------------------*/ - /* define the base address of each block */ -#define PWR_BASEADDR_MAC 0x00 -#define PWR_BASEADDR_USB 0x01 -#define PWR_BASEADDR_PCIE 0x02 -#define PWR_BASEADDR_SDIO 0x03 - -/*---------------------------------------------*/ -/* 3 The value of interface_msk: 4 bits */ -/*---------------------------------------------*/ -#define PWR_INTF_SDIO_MSK BIT(0) -#define PWR_INTF_USB_MSK BIT(1) -#define PWR_INTF_PCI_MSK BIT(2) -#define PWR_INTF_ALL_MSK (BIT(0)|BIT(1)|BIT(2)|BIT(3)) - -/*---------------------------------------------*/ -/* 3 The value of fab_msk: 4 bits */ -/*---------------------------------------------*/ -#define PWR_FAB_TSMC_MSK BIT(0) -#define PWR_FAB_UMC_MSK BIT(1) -#define PWR_FAB_ALL_MSK (BIT(0)|BIT(1)|BIT(2)|BIT(3)) - -/*---------------------------------------------*/ -/* 3 The value of cut_msk: 8 bits */ -/*---------------------------------------------*/ -#define PWR_CUT_TESTCHIP_MSK BIT(0) -#define PWR_CUT_A_MSK BIT(1) -#define PWR_CUT_B_MSK BIT(2) -#define PWR_CUT_C_MSK BIT(3) -#define PWR_CUT_D_MSK BIT(4) -#define PWR_CUT_E_MSK BIT(5) -#define PWR_CUT_F_MSK BIT(6) -#define PWR_CUT_G_MSK BIT(7) -#define PWR_CUT_ALL_MSK 0xFF - - -enum pwrseq_delay_unit { - PWRSEQ_DELAY_US, - PWRSEQ_DELAY_MS, -}; - -struct wlan_pwr_cfg { - u16 offset; - u8 cut_msk; - u8 fab_msk:4; - u8 interface_msk:4; - u8 base:4; - u8 cmd:4; - u8 msk; - u8 value; -}; - - -#define GET_PWR_CFG_OFFSET(__PWR_CMD) __PWR_CMD.offset -#define GET_PWR_CFG_CUT_MASK(__PWR_CMD) __PWR_CMD.cut_msk -#define GET_PWR_CFG_FAB_MASK(__PWR_CMD) __PWR_CMD.fab_msk -#define GET_PWR_CFG_INTF_MASK(__PWR_CMD) __PWR_CMD.interface_msk -#define GET_PWR_CFG_BASE(__PWR_CMD) __PWR_CMD.base -#define GET_PWR_CFG_CMD(__PWR_CMD) __PWR_CMD.cmd -#define GET_PWR_CFG_MASK(__PWR_CMD) __PWR_CMD.msk -#define GET_PWR_CFG_VALUE(__PWR_CMD) __PWR_CMD.value - - -/* */ -/* Prototype of protected function. */ -/* */ -u8 HalPwrSeqCmdParsing23a( - struct rtw_adapter *padapter, - u8 CutVersion, - u8 FabVersion, - u8 InterfaceType, - struct wlan_pwr_cfg PwrCfgCmd[]); - -#endif diff --git a/drivers/staging/rtl8723au/include/HalVerDef.h b/drivers/staging/rtl8723au/include/HalVerDef.h deleted file mode 100644 index 2a0e4ea..0000000 --- a/drivers/staging/rtl8723au/include/HalVerDef.h +++ /dev/null @@ -1,114 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __HAL_VERSION_DEF_H__ -#define __HAL_VERSION_DEF_H__ - -enum hal_ic_type { - CHIP_8192S = 0, - CHIP_8188C = 1, - CHIP_8192C = 2, - CHIP_8192D = 3, - CHIP_8723A = 4, - CHIP_8188E = 5, - CHIP_8881A = 6, - CHIP_8812A = 7, - CHIP_8821A = 8, - CHIP_8723B = 9, - CHIP_8192E = 10, -}; - -enum hal_chip_type { - TEST_CHIP = 0, - NORMAL_CHIP = 1, - FPGA = 2, -}; - -enum hal_cut_version { - A_CUT_VERSION = 0, - B_CUT_VERSION = 1, - C_CUT_VERSION = 2, - D_CUT_VERSION = 3, - E_CUT_VERSION = 4, - F_CUT_VERSION = 5, - G_CUT_VERSION = 6, -}; - -/* HAL_Manufacturer */ -enum hal_vendor { - CHIP_VENDOR_TSMC = 0, - CHIP_VENDOR_UMC = 1, -}; - -struct hal_version { - enum hal_ic_type ICType; - enum hal_chip_type ChipType; - enum hal_cut_version CUTVersion; - enum hal_vendor VendorType; - u8 ROMVer; -}; - -/* Get element */ -#define GET_CVID_IC_TYPE(version) ((version).ICType) -#define GET_CVID_CHIP_TYPE(version) ((version).ChipType) -#define GET_CVID_MANUFACTUER(version) ((version).VendorType) -#define GET_CVID_CUT_VERSION(version) ((version).CUTVersion) -#define GET_CVID_ROM_VERSION(version) (((version).ROMVer) & ROM_VERSION_MASK) - -/* Common Macro. -- */ - -#define IS_81XXC(version) \ - (((GET_CVID_IC_TYPE(version) == CHIP_8192C) || \ - (GET_CVID_IC_TYPE(version) == CHIP_8188C)) ? true : false) -#define IS_8723_SERIES(version) \ - ((GET_CVID_IC_TYPE(version) == CHIP_8723A) ? true : false) - -#define IS_TEST_CHIP(version) \ - ((GET_CVID_CHIP_TYPE(version) == TEST_CHIP) ? true : false) -#define IS_NORMAL_CHIP(version) \ - ((GET_CVID_CHIP_TYPE(version) == NORMAL_CHIP) ? true : false) - -#define IS_A_CUT(version) \ - ((GET_CVID_CUT_VERSION(version) == A_CUT_VERSION) ? true : false) -#define IS_B_CUT(version) \ - ((GET_CVID_CUT_VERSION(version) == B_CUT_VERSION) ? true : false) -#define IS_C_CUT(version) \ - ((GET_CVID_CUT_VERSION(version) == C_CUT_VERSION) ? true : false) -#define IS_D_CUT(version) \ - ((GET_CVID_CUT_VERSION(version) == D_CUT_VERSION) ? true : false) -#define IS_E_CUT(version) \ - ((GET_CVID_CUT_VERSION(version) == E_CUT_VERSION) ? true : false) - -#define IS_CHIP_VENDOR_TSMC(version) \ - ((GET_CVID_MANUFACTUER(version) == CHIP_VENDOR_TSMC) ? true : false) -#define IS_CHIP_VENDOR_UMC(version) \ - ((GET_CVID_MANUFACTUER(version) == CHIP_VENDOR_UMC) ? true : false) - -/* Chip version Macro. -- */ - -#define IS_81xxC_VENDOR_UMC_A_CUT(version) \ - (IS_81XXC(version)?(IS_CHIP_VENDOR_UMC(version) ? \ - (IS_A_CUT(version) ? true : false) : false) : false) -#define IS_81xxC_VENDOR_UMC_B_CUT(version) \ - (IS_81XXC(version) ? (IS_CHIP_VENDOR_UMC(version) ? \ - (IS_B_CUT(version) ? true : false) : false): false) -#define IS_81xxC_VENDOR_UMC_C_CUT(version) \ - (IS_81XXC(version)?(IS_CHIP_VENDOR_UMC(version) ? \ - (IS_C_CUT(version) ? true : false) : false) : false) -#define IS_8723A_A_CUT(version) \ - ((IS_8723_SERIES(version)) ? (IS_A_CUT(version) ? true : false) : false) -#define IS_8723A_B_CUT(version) \ - ((IS_8723_SERIES(version)) ? (IS_B_CUT(version) ? true : false) : false) - -#endif diff --git a/drivers/staging/rtl8723au/include/drv_types.h b/drivers/staging/rtl8723au/include/drv_types.h deleted file mode 100644 index e83463a..0000000 --- a/drivers/staging/rtl8723au/include/drv_types.h +++ /dev/null @@ -1,274 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -/*----------------------------------------------------------------------------- - - For type defines and data structure defines - -------------------------------------------------------------------------------*/ - - -#ifndef __DRV_TYPES_H__ -#define __DRV_TYPES_H__ - -#include <osdep_service.h> -#include <wlan_bssdef.h> - - -enum _NIC_VERSION { - RTL8711_NIC, - RTL8712_NIC, - RTL8713_NIC, - RTL8716_NIC - -}; - - -#include <rtw_ht.h> - -#include <rtw_cmd.h> -#include <rtw_xmit.h> -#include <rtw_recv.h> -#include <hal_intf.h> -#include <hal_com.h> -#include <rtw_security.h> -#include <rtw_pwrctrl.h> -#include <rtw_io.h> -#include <rtw_eeprom.h> -#include <sta_info.h> -#include <rtw_mlme.h> -#include <rtw_debug.h> -#include <rtw_rf.h> -#include <rtw_event.h> -#include <rtw_mlme_ext.h> -#include <rtw_ap.h> - -#include "ioctl_cfg80211.h" - -struct registry_priv { - u8 chip_version; - u8 rfintfs; - struct cfg80211_ssid ssid; - u8 channel;/* ad-hoc support requirement */ - u8 wireless_mode;/* A, B, G, auto */ - u8 scan_mode;/* active, passive */ - u8 preamble;/* long, short, auto */ - u8 vrtl_carrier_sense;/* Enable, Disable, Auto */ - u8 vcs_type;/* RTS/CTS, CTS-to-self */ - u16 rts_thresh; - u16 frag_thresh; - u8 adhoc_tx_pwr; - u8 soft_ap; - u8 power_mgnt; - u8 ips_mode; - u8 smart_ps; - u8 long_retry_lmt; - u8 short_retry_lmt; - u16 busy_thresh; - u8 ack_policy; - u8 software_encrypt; - u8 software_decrypt; - u8 acm_method; - /* UAPSD */ - u8 wmm_enable; - u8 uapsd_enable; - - struct wlan_bssid_ex dev_network; - - u8 ht_enable; - u8 cbw40_enable; - u8 ampdu_enable;/* for tx */ - u8 rx_stbc; - u8 ampdu_amsdu;/* A-MPDU Supports A-MSDU is permitted */ - u8 lowrate_two_xmit; - - u8 rf_config; - u8 low_power; - - u8 wifi_spec;/* !turbo_mode */ - - u8 channel_plan; -#ifdef CONFIG_8723AU_BT_COEXIST - u8 btcoex; - u8 bt_iso; - u8 bt_sco; - u8 bt_ampdu; -#endif - bool bAcceptAddbaReq; - - u8 antdiv_cfg; - u8 antdiv_type; - - u8 hwpdn_mode;/* 0:disable,1:enable,2:decide by EFUSE config */ - u8 hwpwrp_detect;/* 0:disable,1:enable */ - - u8 hw_wps_pbc;/* 0:disable,1:enable */ - - u8 max_roaming_times; /* max number driver will try to roaming */ - - u8 enable80211d; - - u8 ifname[16]; - u8 if2name[16]; - - u8 notch_filter; - - u8 regulatory_tid; -}; - - -#define MAX_CONTINUAL_URB_ERR 4 - -#define GET_PRIMARY_ADAPTER(padapter) \ - (((struct rtw_adapter *)padapter)->dvobj->if1) - -enum _IFACE_ID { - IFACE_ID0, /* maping to PRIMARY_ADAPTER */ - IFACE_ID1, /* maping to SECONDARY_ADAPTER */ - IFACE_ID2, - IFACE_ID3, - IFACE_ID_MAX, -}; - -struct dvobj_priv { - struct rtw_adapter *if1; /* PRIMARY_ADAPTER */ - struct rtw_adapter *if2; /* SECONDARY_ADAPTER */ - - /* for local/global synchronization */ - struct mutex hw_init_mutex; - struct mutex h2c_fwcmd_mutex; - struct mutex setch_mutex; - struct mutex setbw_mutex; - - unsigned char oper_channel; /* saved chan info when set chan bw */ - unsigned char oper_bwmode; - unsigned char oper_ch_offset;/* PRIME_CHNL_OFFSET */ - - struct rtw_adapter *padapters[IFACE_ID_MAX]; - u8 iface_nums; /* total number of ifaces used runtime */ - - /* For 92D, DMDP have 2 interface. */ - u8 InterfaceNumber; - u8 NumInterfaces; - - /* In /Out Pipe information */ - int RtInPipe[2]; - int RtOutPipe[3]; - u8 Queue2Pipe[HW_QUEUE_ENTRY];/* for out pipe mapping */ - -/*-------- below is for USB INTERFACE --------*/ - - u8 nr_endpoint; - u8 ishighspeed; - u8 RtNumInPipes; - u8 RtNumOutPipes; - int ep_num[5]; /* endpoint number */ - - struct mutex usb_vendor_req_mutex; - - union { - __le32 val32; - __le16 val16; - u8 val8; - } usb_buf; - - struct usb_interface *pusbintf; - struct usb_device *pusbdev; - atomic_t continual_urb_error; - -/*-------- below is for PCIE INTERFACE --------*/ - -}; - -static inline struct device *dvobj_to_dev(struct dvobj_priv *dvobj) -{ - /* todo: get interface type from dvobj and the return the dev accordingly */ - return &dvobj->pusbintf->dev; -} - -enum _IFACE_TYPE { - IFACE_PORT0, /* mapping to port0 for C/D series chips */ - IFACE_PORT1, /* mapping to port1 for C/D series chip */ - MAX_IFACE_PORT, -}; - -enum _ADAPTER_TYPE { - PRIMARY_ADAPTER, - SECONDARY_ADAPTER, - MAX_ADAPTER, -}; - -struct rtw_adapter { - int pid[3];/* process id from UI, 0:wps, 1:hostapd, 2:dhcpcd */ - int bDongle;/* build-in module or external dongle */ - u16 chip_type; - u16 HardwareType; - - struct dvobj_priv *dvobj; - struct mlme_priv mlmepriv; - struct mlme_ext_priv mlmeextpriv; - struct cmd_priv cmdpriv; - struct evt_priv evtpriv; - struct xmit_priv xmitpriv; - struct recv_priv recvpriv; - struct sta_priv stapriv; - struct security_priv securitypriv; - struct registry_priv registrypriv; - struct pwrctrl_priv pwrctrlpriv; - struct eeprom_priv eeprompriv; - - u32 setband; - - void *HalData; - - s32 bDriverStopped; - s32 bSurpriseRemoved; - s32 bCardDisableWOHSM; - - u32 IsrContent; - u32 ImrContent; - - u8 EepromAddressSize; - u8 hw_init_completed; - u8 bDriverIsGoingToUnload; - u8 init_adpt_in_progress; - u8 bHaltInProgress; - - struct net_device *pnetdev; - - /* used by rtw_rereg_nd_name related function */ - int bup; - struct net_device_stats stats; - - struct wireless_dev *rtw_wdev; - int net_closed; - - u8 bFWReady; - u8 bReadPortCancel; - u8 bWritePortCancel; - - /* extend to support multi interface */ - /* IFACE_ID0 is equals to PRIMARY_ADAPTER */ - /* IFACE_ID1 is equals to SECONDARY_ADAPTER */ - u8 iface_id; -}; - -#define adapter_to_dvobj(adapter) (adapter->dvobj) - -static inline u8 *myid(struct eeprom_priv *peepriv) -{ - return peepriv->mac_addr; -} - -#endif /* __DRV_TYPES_H__ */ diff --git a/drivers/staging/rtl8723au/include/hal_com.h b/drivers/staging/rtl8723au/include/hal_com.h deleted file mode 100644 index 9c50320..0000000 --- a/drivers/staging/rtl8723au/include/hal_com.h +++ /dev/null @@ -1,182 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __HAL_COMMON_H__ -#define __HAL_COMMON_H__ - -/* */ -/* Rate Definition */ -/* */ -/* CCK */ -#define RATR_1M 0x00000001 -#define RATR_2M 0x00000002 -#define RATR_55M 0x00000004 -#define RATR_11M 0x00000008 -/* OFDM */ -#define RATR_6M 0x00000010 -#define RATR_9M 0x00000020 -#define RATR_12M 0x00000040 -#define RATR_18M 0x00000080 -#define RATR_24M 0x00000100 -#define RATR_36M 0x00000200 -#define RATR_48M 0x00000400 -#define RATR_54M 0x00000800 -/* MCS 1 Spatial Stream */ -#define RATR_MCS0 0x00001000 -#define RATR_MCS1 0x00002000 -#define RATR_MCS2 0x00004000 -#define RATR_MCS3 0x00008000 -#define RATR_MCS4 0x00010000 -#define RATR_MCS5 0x00020000 -#define RATR_MCS6 0x00040000 -#define RATR_MCS7 0x00080000 -/* MCS 2 Spatial Stream */ -#define RATR_MCS8 0x00100000 -#define RATR_MCS9 0x00200000 -#define RATR_MCS10 0x00400000 -#define RATR_MCS11 0x00800000 -#define RATR_MCS12 0x01000000 -#define RATR_MCS13 0x02000000 -#define RATR_MCS14 0x04000000 -#define RATR_MCS15 0x08000000 - -/* CCK */ -#define RATE_1M BIT(0) -#define RATE_2M BIT(1) -#define RATE_5_5M BIT(2) -#define RATE_11M BIT(3) -/* OFDM */ -#define RATE_6M BIT(4) -#define RATE_9M BIT(5) -#define RATE_12M BIT(6) -#define RATE_18M BIT(7) -#define RATE_24M BIT(8) -#define RATE_36M BIT(9) -#define RATE_48M BIT(10) -#define RATE_54M BIT(11) - -/*------------------------------ Tx Desc definition Macro ------------------------*/ -/* pragma mark -- Tx Desc related definition. -- */ -/* */ -/* */ -/* Rate */ -/* */ -/* CCK Rates, TxHT = 0 */ -#define DESC_RATE1M 0x00 -#define DESC_RATE2M 0x01 -#define DESC_RATE5_5M 0x02 -#define DESC_RATE11M 0x03 - -/* OFDM Rates, TxHT = 0 */ -#define DESC_RATE6M 0x04 -#define DESC_RATE9M 0x05 -#define DESC_RATE12M 0x06 -#define DESC_RATE18M 0x07 -#define DESC_RATE24M 0x08 -#define DESC_RATE36M 0x09 -#define DESC_RATE48M 0x0a -#define DESC_RATE54M 0x0b - -/* MCS Rates, TxHT = 1 */ -#define DESC_RATEMCS0 0x0c -#define DESC_RATEMCS1 0x0d -#define DESC_RATEMCS2 0x0e -#define DESC_RATEMCS3 0x0f -#define DESC_RATEMCS4 0x10 -#define DESC_RATEMCS5 0x11 -#define DESC_RATEMCS6 0x12 -#define DESC_RATEMCS7 0x13 -#define DESC_RATEMCS8 0x14 -#define DESC_RATEMCS9 0x15 -#define DESC_RATEMCS10 0x16 -#define DESC_RATEMCS11 0x17 -#define DESC_RATEMCS12 0x18 -#define DESC_RATEMCS13 0x19 -#define DESC_RATEMCS14 0x1a -#define DESC_RATEMCS15 0x1b -#define DESC_RATEMCS15_SG 0x1c -#define DESC_RATEMCS32 0x20 - -#define REG_P2P_CTWIN 0x0572 /* 1 Byte long (in unit of TU) */ -#define REG_NOA_DESC_SEL 0x05CF -#define REG_NOA_DESC_DURATION 0x05E0 -#define REG_NOA_DESC_INTERVAL 0x05E4 -#define REG_NOA_DESC_START 0x05E8 -#define REG_NOA_DESC_COUNT 0x05EC - -#include "HalVerDef.h" - - -u8 /* return the final channel plan decision */ -hal_com_get_channel_plan23a( - struct rtw_adapter *padapter, - u8 hw_channel_plan, /* channel plan from HW (efuse/eeprom) */ - u8 sw_channel_plan, /* channel plan from SW (registry/module param) */ - u8 def_channel_plan, /* channel plan used when the former two is invalid */ - bool AutoLoadFail - ); - -u8 MRateToHwRate23a(u8 rate); - -void HalSetBrateCfg23a(struct rtw_adapter *padapter, u8 *mBratesOS); - -bool -Hal_MappingOutPipe23a(struct rtw_adapter *pAdapter, u8 NumOutPipe); - -void c2h_evt_clear23a(struct rtw_adapter *adapter); -s32 c2h_evt_read23a(struct rtw_adapter *adapter, u8 *buf); - -void rtl8723a_set_ampdu_min_space(struct rtw_adapter *padapter, u8 MinSpacingToSet); -void rtl8723a_set_ampdu_factor(struct rtw_adapter *padapter, u8 FactorToSet); -void rtl8723a_set_acm_ctrl(struct rtw_adapter *padapter, u8 ctrl); -void rtl8723a_set_media_status(struct rtw_adapter *padapter, u8 status); -void rtl8723a_set_media_status1(struct rtw_adapter *padapter, u8 status); -void rtl8723a_set_bcn_func(struct rtw_adapter *padapter, u8 val); -void rtl8723a_check_bssid(struct rtw_adapter *padapter, u8 val); -void rtl8723a_mlme_sitesurvey(struct rtw_adapter *padapter, u8 flag); -void rtl8723a_on_rcr_am(struct rtw_adapter *padapter); -void rtl8723a_off_rcr_am(struct rtw_adapter *padapter); -void rtl8723a_set_slot_time(struct rtw_adapter *padapter, u8 slottime); -void rtl8723a_ack_preamble(struct rtw_adapter *padapter, u8 bShortPreamble); -void rtl8723a_set_sec_cfg(struct rtw_adapter *padapter, u8 sec); -void rtl8723a_cam_empty_entry(struct rtw_adapter *padapter, u8 ucIndex); -void rtl8723a_cam_invalidate_all(struct rtw_adapter *padapter); -void rtl8723a_cam_write(struct rtw_adapter *padapter, - u8 entry, u16 ctrl, const u8 *mac, const u8 *key); -void rtl8723a_fifo_cleanup(struct rtw_adapter *padapter); -void rtl8723a_set_apfm_on_mac(struct rtw_adapter *padapter, u8 val); -void rtl8723a_bcn_valid(struct rtw_adapter *padapter); -bool rtl8723a_get_bcn_valid(struct rtw_adapter *padapter); -void rtl8723a_set_beacon_interval(struct rtw_adapter *padapter, u16 interval); -void rtl8723a_set_resp_sifs(struct rtw_adapter *padapter, - u8 r2t1, u8 r2t2, u8 t2t1, u8 t2t2); -void rtl8723a_set_ac_param_vo(struct rtw_adapter *padapter, u32 vo); -void rtl8723a_set_ac_param_vi(struct rtw_adapter *padapter, u32 vi); -void rtl8723a_set_ac_param_be(struct rtw_adapter *padapter, u32 be); -void rtl8723a_set_ac_param_bk(struct rtw_adapter *padapter, u32 bk); -void rtl8723a_set_rxdma_agg_pg_th(struct rtw_adapter *padapter, u8 val); -void rtl8723a_set_initial_gain(struct rtw_adapter *padapter, u32 rx_gain); - -void rtl8723a_odm_support_ability_write(struct rtw_adapter *padapter, u32 val); -void rtl8723a_odm_support_ability_backup(struct rtw_adapter *padapter); -void rtl8723a_odm_support_ability_restore(struct rtw_adapter *padapter); -void rtl8723a_odm_support_ability_set(struct rtw_adapter *padapter, u32 val); -void rtl8723a_odm_support_ability_clr(struct rtw_adapter *padapter, u32 val); - -void rtl8723a_set_rpwm(struct rtw_adapter *padapter, u8 val); -u8 rtl8723a_get_rf_type(struct rtw_adapter *padapter); -bool rtl8723a_get_fwlps_rf_on(struct rtw_adapter *padapter); -bool rtl8723a_chk_hi_queue_empty(struct rtw_adapter *padapter); - -#endif /* __HAL_COMMON_H__ */ diff --git a/drivers/staging/rtl8723au/include/hal_intf.h b/drivers/staging/rtl8723au/include/hal_intf.h deleted file mode 100644 index b924d47..0000000 --- a/drivers/staging/rtl8723au/include/hal_intf.h +++ /dev/null @@ -1,115 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __HAL_INTF_H__ -#define __HAL_INTF_H__ - -#include <osdep_service.h> -#include <drv_types.h> - -enum _CHIP_TYPE { - NULL_CHIP_TYPE, - RTL8712_8188S_8191S_8192S, - RTL8188C_8192C, - RTL8192D, - RTL8723A, - RTL8188E, - MAX_CHIP_TYPE -}; - -enum hal_def_variable { - HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, - HAL_DEF_IS_SUPPORT_ANT_DIV, - HAL_DEF_CURRENT_ANTENNA, - HAL_DEF_DRVINFO_SZ, - HAL_DEF_MAX_RECVBUF_SZ, - HAL_DEF_RX_PACKET_OFFSET, - HAL_DEF_DBG_DUMP_RXPKT,/* for dbg */ - HAL_DEF_DBG_DM_FUNC,/* for dbg */ - HAL_DEF_RA_DECISION_RATE, - HAL_DEF_RA_SGI, - HAL_DEF_PT_PWR_STATUS, - HW_VAR_MAX_RX_AMPDU_FACTOR, - HW_DEF_RA_INFO_DUMP, - HAL_DEF_DBG_DUMP_TXPKT, - HW_DEF_FA_CNT_DUMP, - HW_DEF_ODM_DBG_FLAG, -}; - -enum hal_odm_variable { - HAL_ODM_STA_INFO, - HAL_ODM_P2P_STATE, - HAL_ODM_WIFI_DISPLAY_STATE, -}; - -enum rt_eeprom_type { - EEPROM_93C46, - EEPROM_93C56, - EEPROM_BOOT_EFUSE, -}; - - - -#define RF_CHANGE_BY_INIT 0 -#define RF_CHANGE_BY_IPS BIT(28) -#define RF_CHANGE_BY_PS BIT(29) -#define RF_CHANGE_BY_HW BIT(30) -#define RF_CHANGE_BY_SW BIT(31) - -enum hardware_type { - HARDWARE_TYPE_RTL8180, - HARDWARE_TYPE_RTL8185, - HARDWARE_TYPE_RTL8187, - HARDWARE_TYPE_RTL8188, - HARDWARE_TYPE_RTL8190P, - HARDWARE_TYPE_RTL8192E, - HARDWARE_TYPE_RTL819xU, - HARDWARE_TYPE_RTL8192SE, - HARDWARE_TYPE_RTL8192SU, - HARDWARE_TYPE_RTL8192CE, - HARDWARE_TYPE_RTL8192CU, - HARDWARE_TYPE_RTL8192DE, - HARDWARE_TYPE_RTL8192DU, - HARDWARE_TYPE_RTL8723AE, - HARDWARE_TYPE_RTL8723AU, - HARDWARE_TYPE_RTL8723AS, - HARDWARE_TYPE_RTL8188EE, - HARDWARE_TYPE_RTL8188EU, - HARDWARE_TYPE_RTL8188ES, - HARDWARE_TYPE_MAX, -}; - -#define GET_EEPROM_EFUSE_PRIV(adapter) (&adapter->eeprompriv) - -void rtw_hal_def_value_init23a(struct rtw_adapter *padapter); -int pm_netdev_open23a(struct net_device *pnetdev, u8 bnormal); - -int rtl8723au_hal_init(struct rtw_adapter *padapter); -int rtl8723au_hal_deinit(struct rtw_adapter *padapter); -void rtw_hal_stop(struct rtw_adapter *padapter); - -void rtw_hal_update_ra_mask23a(struct sta_info *psta, u8 rssi_level); -void rtw_hal_clone_data(struct rtw_adapter *dst_padapter, struct rtw_adapter *src_padapter); - -void hw_var_set_correct_tsf(struct rtw_adapter *padapter); -void hw_var_set_mlme_disconnect(struct rtw_adapter *padapter); -void hw_var_set_opmode(struct rtw_adapter *padapter, u8 mode); -void hw_var_set_macaddr(struct rtw_adapter *padapter, u8 *val); -void hw_var_set_bssid(struct rtw_adapter *padapter, u8 *val); -void hw_var_set_mlme_join(struct rtw_adapter *padapter, u8 type); - -int GetHalDefVar8192CUsb(struct rtw_adapter *Adapter, - enum hal_def_variable eVariable, void *pValue); - -#endif /* __HAL_INTF_H__ */ diff --git a/drivers/staging/rtl8723au/include/ieee80211.h b/drivers/staging/rtl8723au/include/ieee80211.h deleted file mode 100644 index 634102e..0000000 --- a/drivers/staging/rtl8723au/include/ieee80211.h +++ /dev/null @@ -1,341 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __IEEE80211_H -#define __IEEE80211_H - -#include <osdep_service.h> -#include <drv_types.h> -#include "linux/ieee80211.h" -#include "wifi.h" - -#include <linux/wireless.h> - -#if (WIRELESS_EXT < 22) -#error "Obsolete pre 2007 wireless extensions are not supported" -#endif - - -#ifdef CONFIG_8723AU_AP_MODE - -/* STA flags */ -#define WLAN_STA_AUTH BIT(0) -#define WLAN_STA_ASSOC BIT(1) -#define WLAN_STA_PS BIT(2) -#define WLAN_STA_TIM BIT(3) -#define WLAN_STA_PERM BIT(4) -#define WLAN_STA_AUTHORIZED BIT(5) -#define WLAN_STA_PENDING_POLL BIT(6) /* pending activity poll not ACKed */ -#define WLAN_STA_SHORT_PREAMBLE BIT(7) -#define WLAN_STA_PREAUTH BIT(8) -#define WLAN_STA_WME BIT(9) -#define WLAN_STA_MFP BIT(10) -#define WLAN_STA_HT BIT(11) -#define WLAN_STA_WPS BIT(12) -#define WLAN_STA_MAYBE_WPS BIT(13) -#define WLAN_STA_NONERP BIT(31) - -#endif - -#define WPA_CIPHER_NONE BIT(0) -#define WPA_CIPHER_WEP40 BIT(1) -#define WPA_CIPHER_WEP104 BIT(2) -#define WPA_CIPHER_TKIP BIT(3) -#define WPA_CIPHER_CCMP BIT(4) - - - -#define WPA_SELECTOR_LEN 4 -extern u8 RTW_WPA_OUI23A_TYPE[] ; -extern u16 RTW_WPA_VERSION23A ; -extern u8 WPA_AUTH_KEY_MGMT_NONE23A[]; -extern u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X23A[]; -extern u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X23A[]; -extern u8 WPA_CIPHER_SUITE_NONE23A[]; -extern u8 WPA_CIPHER_SUITE_WEP4023A[]; -extern u8 WPA_CIPHER_SUITE_TKIP23A[]; -extern u8 WPA_CIPHER_SUITE_WRAP23A[]; -extern u8 WPA_CIPHER_SUITE_CCMP23A[]; -extern u8 WPA_CIPHER_SUITE_WEP10423A[]; - - -#define RSN_HEADER_LEN 4 -#define RSN_SELECTOR_LEN 4 - -extern u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X23A[]; -extern u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X23A[]; -extern u8 RSN_CIPHER_SUITE_NONE23A[]; -extern u8 RSN_CIPHER_SUITE_WEP4023A[]; -extern u8 RSN_CIPHER_SUITE_TKIP23A[]; -extern u8 RSN_CIPHER_SUITE_WRAP23A[]; -extern u8 RSN_CIPHER_SUITE_CCMP23A[]; -extern u8 RSN_CIPHER_SUITE_WEP10423A[]; - -enum ratr_table_mode { - RATR_INX_WIRELESS_NGB = 0, /* BGN 40 Mhz 2SS 1SS */ - RATR_INX_WIRELESS_NG = 1, /* GN or N */ - RATR_INX_WIRELESS_NB = 2, /* BGN 20 Mhz 2SS 1SS or BN */ - RATR_INX_WIRELESS_N = 3, - RATR_INX_WIRELESS_GB = 4, - RATR_INX_WIRELESS_G = 5, - RATR_INX_WIRELESS_B = 6, - RATR_INX_WIRELESS_MC = 7, - RATR_INX_WIRELESS_AC_N = 8, -}; - -enum NETWORK_TYPE -{ - WIRELESS_INVALID = 0, - /* Sub-Element */ - /* tx: cck only , rx: cck only, hw: cck */ - WIRELESS_11B = BIT(0), - /* tx: ofdm only, rx: ofdm & cck, hw: cck & ofdm */ - WIRELESS_11G = BIT(1), - /* tx: ofdm only, rx: ofdm only, hw: ofdm only */ - WIRELESS_11A = BIT(2), - /* tx: MCS only, rx: MCS & cck, hw: MCS & cck */ - WIRELESS_11_24N = BIT(3), - /* tx: MCS only, rx: MCS & ofdm, hw: ofdm only */ - WIRELESS_11_5N = BIT(4), - /* WIRELESS_AUTO = BIT(5), */ - WIRELESS_AC = BIT(6), - - /* Combination */ - /* tx: cck & ofdm, rx: cck & ofdm & MCS, hw: cck & ofdm */ - WIRELESS_11BG = WIRELESS_11B|WIRELESS_11G, - /* tx: ofdm & MCS, rx: ofdm & cck & MCS, hw: cck & ofdm */ - WIRELESS_11G_24N = WIRELESS_11G | WIRELESS_11_24N, - /* tx: ofdm & MCS, rx: ofdm & MCS, hw: ofdm only */ - WIRELESS_11A_5N = WIRELESS_11A | WIRELESS_11_5N, - /* tx: ofdm & cck & MCS, rx: ofdm & cck & MCS, hw: ofdm & cck */ - WIRELESS_11BG_24N = WIRELESS_11B | WIRELESS_11G | WIRELESS_11_24N, - /* tx: ofdm & MCS, rx: ofdm & MCS, hw: ofdm only */ - WIRELESS_11AGN = WIRELESS_11A | WIRELESS_11G | WIRELESS_11_24N | - WIRELESS_11_5N, - WIRELESS_11ABGN = WIRELESS_11A | WIRELESS_11B | WIRELESS_11G | - WIRELESS_11_24N | WIRELESS_11_5N, -}; - -#define SUPPORTED_24G_NETTYPE_MSK (WIRELESS_11B | WIRELESS_11G | WIRELESS_11_24N) -#define SUPPORTED_5G_NETTYPE_MSK (WIRELESS_11A | WIRELESS_11_5N) - -#define IsSupported24G(NetType) (NetType & SUPPORTED_24G_NETTYPE_MSK ? true : false) -#define IsSupported5G(NetType) (NetType & SUPPORTED_5G_NETTYPE_MSK ? true : false) - -#define IsEnableHWCCK(NetType) IsSupported24G(NetType) -#define IsEnableHWOFDM(NetType) (NetType & (WIRELESS_11G|WIRELESS_11_24N|SUPPORTED_5G_NETTYPE_MSK) ? true : false) - -#define IsSupportedRxCCK(NetType) IsEnableHWCCK(NetType) -#define IsSupportedRxOFDM(NetType) IsEnableHWOFDM(NetType) -#define IsSupportedRxMCS(NetType) IsEnableHWOFDM(NetType) - -#define IsSupportedTxCCK(NetType) (NetType & (WIRELESS_11B) ? true : false) -#define IsSupportedTxOFDM(NetType) (NetType & (WIRELESS_11G|WIRELESS_11A) ? true : false) -#define IsSupportedTxMCS(NetType) (NetType & (WIRELESS_11_24N|WIRELESS_11_5N) ? true : false) - - -#define MIN_FRAG_THRESHOLD 256U -#define MAX_FRAG_THRESHOLD 2346U - -/* QoS,QOS */ -#define NORMAL_ACK 0 -#define NO_ACK 1 -#define NON_EXPLICIT_ACK 2 -#define BLOCK_ACK 3 - -/* IEEE 802.11 defines */ - -#define P80211_OUI_LEN 3 - -struct ieee80211_snap_hdr { - u8 dsap; /* always 0xAA */ - u8 ssap; /* always 0xAA */ - u8 ctrl; /* always 0x03 */ - u8 oui[P80211_OUI_LEN]; /* organizational universal id */ -} __attribute__ ((packed)); - - -#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr) - -#define WLAN_REASON_JOIN_WRONG_CHANNEL 65534 -#define WLAN_REASON_EXPIRATION_CHK 65535 - -#define IEEE80211_CCK_RATE_LEN 4 -#define IEEE80211_NUM_OFDM_RATESLEN 8 - - -#define IEEE80211_CCK_RATE_1MB 0x02 -#define IEEE80211_CCK_RATE_2MB 0x04 -#define IEEE80211_CCK_RATE_5MB 0x0B -#define IEEE80211_CCK_RATE_11MB 0x16 -#define IEEE80211_OFDM_RATE_LEN 8 -#define IEEE80211_OFDM_RATE_6MB 0x0C -#define IEEE80211_OFDM_RATE_9MB 0x12 -#define IEEE80211_OFDM_RATE_12MB 0x18 -#define IEEE80211_OFDM_RATE_18MB 0x24 -#define IEEE80211_OFDM_RATE_24MB 0x30 -#define IEEE80211_OFDM_RATE_36MB 0x48 -#define IEEE80211_OFDM_RATE_48MB 0x60 -#define IEEE80211_OFDM_RATE_54MB 0x6C -#define IEEE80211_BASIC_RATE_MASK 0x80 - -#define IEEE80211_CCK_RATE_1MB_MASK (1<<0) -#define IEEE80211_CCK_RATE_2MB_MASK (1<<1) -#define IEEE80211_CCK_RATE_5MB_MASK (1<<2) -#define IEEE80211_CCK_RATE_11MB_MASK (1<<3) -#define IEEE80211_OFDM_RATE_6MB_MASK (1<<4) -#define IEEE80211_OFDM_RATE_9MB_MASK (1<<5) -#define IEEE80211_OFDM_RATE_12MB_MASK (1<<6) -#define IEEE80211_OFDM_RATE_18MB_MASK (1<<7) -#define IEEE80211_OFDM_RATE_24MB_MASK (1<<8) -#define IEEE80211_OFDM_RATE_36MB_MASK (1<<9) -#define IEEE80211_OFDM_RATE_48MB_MASK (1<<10) -#define IEEE80211_OFDM_RATE_54MB_MASK (1<<11) - -#define IEEE80211_CCK_RATES_MASK 0x0000000F -#define IEEE80211_CCK_BASIC_RATES_MASK (IEEE80211_CCK_RATE_1MB_MASK | \ - IEEE80211_CCK_RATE_2MB_MASK) -#define IEEE80211_CCK_DEFAULT_RATES_MASK (IEEE80211_CCK_BASIC_RATES_MASK | \ - IEEE80211_CCK_RATE_5MB_MASK | \ - IEEE80211_CCK_RATE_11MB_MASK) - -#define IEEE80211_OFDM_RATES_MASK 0x00000FF0 -#define IEEE80211_OFDM_BASIC_RATES_MASK (IEEE80211_OFDM_RATE_6MB_MASK | \ - IEEE80211_OFDM_RATE_12MB_MASK | \ - IEEE80211_OFDM_RATE_24MB_MASK) -#define IEEE80211_OFDM_DEFAULT_RATES_MASK (IEEE80211_OFDM_BASIC_RATES_MASK | \ - IEEE80211_OFDM_RATE_9MB_MASK | \ - IEEE80211_OFDM_RATE_18MB_MASK | \ - IEEE80211_OFDM_RATE_36MB_MASK | \ - IEEE80211_OFDM_RATE_48MB_MASK | \ - IEEE80211_OFDM_RATE_54MB_MASK) -#define IEEE80211_DEFAULT_RATES_MASK (IEEE80211_OFDM_DEFAULT_RATES_MASK | \ - IEEE80211_CCK_DEFAULT_RATES_MASK) - -#define IEEE80211_NUM_OFDM_RATES 8 -#define IEEE80211_NUM_CCK_RATES 4 -#define IEEE80211_OFDM_SHIFT_MASK_A 4 - -#define WEP_KEYS 4 - - -/* MAX_RATES_LENGTH needs to be 12. The spec says 8, and many APs - * only use 8, and then use extended rates for the remaining supported - * rates. Other APs, however, stick all of their supported rates on the - * main rates information element... */ -#define MAX_RATES_LENGTH 12 -#define MAX_RATES_EX_LENGTH 16 -#define MAX_CHANNEL_NUMBER 161 -#define RTW_CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */ - -#define MAX_WPA_IE_LEN 256 -#define MAX_WPS_IE_LEN 256 -#define MAX_P2P_IE_LEN 256 -#define MAX_WFD_IE_LEN 128 - -/* -join_res: --1: authentication fail --2: association fail -> 0: TID -*/ - -#define MAXTID 16 - -#define WME_OUI_TYPE 2 -#define WME_OUI_SUBTYPE_INFORMATION_ELEMENT 0 -#define WME_OUI_SUBTYPE_PARAMETER_ELEMENT 1 -#define WME_OUI_SUBTYPE_TSPEC_ELEMENT 2 -#define WME_VERSION 1 - - -#define OUI_BROADCOM 0x00904c /* Broadcom (Epigram) */ - -#define VENDOR_HT_CAPAB_OUI_TYPE 0x33 /* 00-90-4c:0x33 */ - -/* Represent channel details, subset of ieee80211_channel */ -struct rtw_ieee80211_channel { - /* enum nl80211_band band; */ - /* u16 center_freq; */ - u16 hw_value; - u32 flags; - /* int max_antenna_gain; */ - /* int max_power; */ - /* int max_reg_power; */ - /* bool beacon_found; */ - /* u32 orig_flags; */ - /* int orig_mag; */ - /* int orig_mpwr; */ -}; - -#define CHAN_FMT \ - /*"band:%d, "*/ \ - /*"center_freq:%u, "*/ \ - "hw_value:%u, " \ - "flags:0x%08x" \ - /*"max_antenna_gain:%d\n"*/ \ - /*"max_power:%d\n"*/ \ - /*"max_reg_power:%d\n"*/ \ - /*"beacon_found:%u\n"*/ \ - /*"orig_flags:0x%08x\n"*/ \ - /*"orig_mag:%d\n"*/ \ - /*"orig_mpwr:%d\n"*/ - -#define CHAN_ARG(channel) \ - /*(channel)->band*/ \ - /*, (channel)->center_freq*/ \ - (channel)->hw_value \ - , (channel)->flags \ - /*, (channel)->max_antenna_gain*/ \ - /*, (channel)->max_power*/ \ - /*, (channel)->max_reg_power*/ \ - /*, (channel)->beacon_found*/ \ - /*, (channel)->orig_flags*/ \ - /*, (channel)->orig_mag*/ \ - /*, (channel)->orig_mpwr*/ \ - -u8 *rtw_set_ie23a(u8 *pbuf, int index, uint len, const u8 *source, uint *frlen); - -u8 hal_ch_offset_to_secondary_ch_offset23a(u8 ch_offset); -u8 *rtw_set_ie23a_ch_switch(u8 *buf, u32 *buf_len, u8 ch_switch_mode, u8 new_ch, u8 ch_switch_cnt); -u8 *rtw_set_ie23a_secondary_ch_offset(u8 *buf, u32 *buf_len, u8 secondary_ch_offset); - -u8 *rtw_get_ie23a(u8*pbuf, int index, int *len, int limit); -u8 *rtw_get_ie23a_ex(u8 *in_ie, uint in_len, u8 eid, u8 *oui, u8 oui_len, u8 *ie, uint *ielen); -int rtw_ies_remove_ie23a(u8 *ies, uint *ies_len, uint offset, u8 eid, u8 *oui, u8 oui_len); - -void rtw_set_supported_rate23a(u8 *SupportedRates, uint mode); - -int rtw_parse_wpa_ie23a(const u8* wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x); -int rtw_parse_wpa2_ie23a(const u8* wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x); - -const u8 *rtw_get_wps_attr23a(const u8 *wps_ie, uint wps_ielen, u16 target_attr_id ,u8 *buf_attr, u32 *len_attr); -const u8 *rtw_get_wps_attr_content23a(const u8 *wps_ie, uint wps_ielen, u16 target_attr_id ,u8 *buf_content); - -uint rtw_get_rateset_len23a(u8 *rateset); - -struct registry_priv; -int rtw_generate_ie23a(struct registry_priv *pregistrypriv); - - -int rtw_get_bit_value_from_ieee_value23a(u8 val); - -int rtw_check_network_type23a(unsigned char *rate, int ratelen, int channel); - -void rtw_get_bcn_info23a(struct wlan_network *pnetwork); - -u16 rtw_mcs_rate23a(u8 rf_type, u8 bw_40MHz, u8 short_GI_20, u8 short_GI_40, - struct ieee80211_mcs_info *mcs); - -#endif /* IEEE80211_H */ diff --git a/drivers/staging/rtl8723au/include/ioctl_cfg80211.h b/drivers/staging/rtl8723au/include/ioctl_cfg80211.h deleted file mode 100644 index 3a4ead5..0000000 --- a/drivers/staging/rtl8723au/include/ioctl_cfg80211.h +++ /dev/null @@ -1,66 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __IOCTL_CFG80211_H__ -#define __IOCTL_CFG80211_H__ - -struct rtw_wdev_priv { - struct wireless_dev *rtw_wdev; - - struct rtw_adapter *padapter; - - struct cfg80211_scan_request *scan_request; - spinlock_t scan_req_lock; - - struct net_device *pmon_ndev;/* for monitor interface */ - char ifname_mon[IFNAMSIZ + 1]; /* name for monitor interface */ - - u8 p2p_enabled; - - bool power_mgmt; -}; - -#define wdev_to_priv(w) ((struct rtw_wdev_priv *)(wdev_priv(w))) - -#define wiphy_to_adapter(x) \ - (struct rtw_adapter *)(((struct rtw_wdev_priv *) \ - wiphy_priv(x))->padapter) - -#define wiphy_to_wdev(x) \ - (struct wireless_dev *)(((struct rtw_wdev_priv *) \ - wiphy_priv(x))->rtw_wdev) - -int rtw_wdev_alloc(struct rtw_adapter *padapter, struct device *dev); -void rtw_wdev_free(struct wireless_dev *wdev); -void rtw_wdev_unregister(struct wireless_dev *wdev); - -void rtw_cfg80211_init_wiphy(struct rtw_adapter *padapter); - -void rtw_cfg80211_surveydone_event_callback(struct rtw_adapter *padapter); - -void rtw_cfg80211_indicate_connect(struct rtw_adapter *padapter); -void rtw_cfg80211_indicate_disconnect(struct rtw_adapter *padapter); -void rtw_cfg80211_indicate_scan_done(struct rtw_wdev_priv *pwdev_priv, - bool aborted); - -#ifdef CONFIG_8723AU_AP_MODE -void rtw_cfg80211_indicate_sta_assoc(struct rtw_adapter *padapter, - u8 *pmgmt_frame, uint frame_len); -void rtw_cfg80211_indicate_sta_disassoc(struct rtw_adapter *padapter, - unsigned char *da, unsigned short reason); -#endif /* CONFIG_8723AU_AP_MODE */ - -bool rtw_cfg80211_pwr_mgmt(struct rtw_adapter *adapter); - -#endif /* __IOCTL_CFG80211_H__ */ diff --git a/drivers/staging/rtl8723au/include/mlme_osdep.h b/drivers/staging/rtl8723au/include/mlme_osdep.h deleted file mode 100644 index 4bb5525..0000000 --- a/drivers/staging/rtl8723au/include/mlme_osdep.h +++ /dev/null @@ -1,24 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __MLME_OSDEP_H_ -#define __MLME_OSDEP_H_ - -#include <osdep_service.h> -#include <drv_types.h> - -void rtw_os_indicate_disconnect23a(struct rtw_adapter *adapter); -void rtw_reset_securitypriv23a(struct rtw_adapter *adapter); - -#endif /* _MLME_OSDEP_H_ */ diff --git a/drivers/staging/rtl8723au/include/odm.h b/drivers/staging/rtl8723au/include/odm.h deleted file mode 100644 index 24f2f28..0000000 --- a/drivers/staging/rtl8723au/include/odm.h +++ /dev/null @@ -1,860 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ - - -#ifndef __HALDMOUTSRC_H__ -#define __HALDMOUTSRC_H__ - -/* */ -/* Definition */ -/* */ -/* */ -/* 2011/09/22 MH Define all team supprt ability. */ -/* */ - -/* */ -/* 2011/09/22 MH Define for all teams. Please Define the constan in your precomp header. */ -/* */ -/* define DM_ODM_SUPPORT_AP 0 */ -/* define DM_ODM_SUPPORT_ADSL 0 */ -/* define DM_ODM_SUPPORT_CE 0 */ -/* define DM_ODM_SUPPORT_MP 1 */ - -#define TP_MODE 0 -#define RSSI_MODE 1 -#define TRAFFIC_LOW 0 -#define TRAFFIC_HIGH 1 - - -/* */ -/* 3 Tx Power Tracking */ -/* 3============================================================ */ -#define DPK_DELTA_MAPPING_NUM 13 -#define index_mapping_HP_NUM 15 - - -/* */ -/* 3 PSD Handler */ -/* 3============================================================ */ - -#define AFH_PSD 1 /* 0:normal PSD scan, 1: only do 20 pts PSD */ -#define MODE_40M 0 /* 0:20M, 1:40M */ -#define PSD_TH2 3 -#define PSD_CHMIN 20 /* Minimum channel number for BT AFH */ -#define SIR_STEP_SIZE 3 -#define Smooth_Size_1 5 -#define Smooth_TH_1 3 -#define Smooth_Size_2 10 -#define Smooth_TH_2 4 -#define Smooth_Size_3 20 -#define Smooth_TH_3 4 -#define Smooth_Step_Size 5 -#define Adaptive_SIR 1 -#define PSD_RESCAN 4 -#define PSD_SCAN_INTERVAL 700 /* ms */ - -/* 8723A High Power IGI Setting */ -#define DM_DIG_HIGH_PWR_IGI_LOWER_BOUND 0x22 -#define DM_DIG_Gmode_HIGH_PWR_IGI_LOWER_BOUND 0x28 -#define DM_DIG_HIGH_PWR_THRESHOLD 0x3a - -/* LPS define */ -#define DM_DIG_FA_TH0_LPS 4 /* 4 in lps */ -#define DM_DIG_FA_TH1_LPS 15 /* 15 lps */ -#define DM_DIG_FA_TH2_LPS 30 /* 30 lps */ -#define RSSI_OFFSET_DIG 0x05; - -/* ANT Test */ -#define ANTTESTALL 0x00 /* Ant A or B will be Testing */ -#define ANTTESTA 0x01 /* Ant A will be Testing */ -#define ANTTESTB 0x02 /* Ant B will be testing */ - - -/* */ -/* structure and define */ -/* */ - -struct dig_t { - u8 Dig_Enable_Flag; - u8 Dig_Ext_Port_Stage; - - int RssiLowThresh; - int RssiHighThresh; - - u32 FALowThresh; - u32 FAHighThresh; - - u8 CurSTAConnectState; - u8 PreSTAConnectState; - u8 CurMultiSTAConnectState; - - u8 PreIGValue; - u8 CurIGValue; - u8 BackupIGValue; - - s8 BackoffVal; - s8 BackoffVal_range_max; - s8 BackoffVal_range_min; - u8 rx_gain_range_max; - u8 rx_gain_range_min; - u8 Rssi_val_min; - - u8 PreCCK_CCAThres; - u8 CurCCK_CCAThres; - u8 PreCCKPDState; - u8 CurCCKPDState; - - u8 LargeFAHit; - u8 ForbiddenIGI; - u32 Recover_cnt; - - u8 DIG_Dynamic_MIN_0; - u8 DIG_Dynamic_MIN_1; - bool bMediaConnect_0; - bool bMediaConnect_1; - - u32 RSSI_max; -}; - -struct dynamic_pwr_sav { - u8 PreCCAState; - u8 CurCCAState; - - u8 PreRFState; - u8 CurRFState; - - int Rssi_val_min; - - u8 initialize; - u32 Reg874, RegC70, Reg85C, RegA74; -}; - -struct false_alarm_stats { - u32 Cnt_Parity_Fail; - u32 Cnt_Rate_Illegal; - u32 Cnt_Crc8_fail; - u32 Cnt_Mcs_fail; - u32 Cnt_Ofdm_fail; - u32 Cnt_Cck_fail; - u32 Cnt_all; - u32 Cnt_Fast_Fsync; - u32 Cnt_SB_Search_fail; - u32 Cnt_OFDM_CCA; - u32 Cnt_CCK_CCA; - u32 Cnt_CCA_all; - u32 Cnt_BW_USC; /* Gary */ - u32 Cnt_BW_LSC; /* Gary */ -}; - -#define ASSOCIATE_ENTRY_NUM 32 /* Max size of AsocEntry[]. */ -#define ODM_ASSOCIATE_ENTRY_NUM ASSOCIATE_ENTRY_NUM - -/* This indicates two different the steps. */ -/* In SWAW_STEP_PEAK, driver needs to switch antenna and listen to the signal on the air. */ -/* In SWAW_STEP_DETERMINE, driver just compares the signal captured in SWAW_STEP_PEAK */ -/* with original RSSI to determine if it is necessary to switch antenna. */ -#define SWAW_STEP_PEAK 0 -#define SWAW_STEP_DETERMINE 1 - -#define TP_MODE 0 -#define RSSI_MODE 1 -#define TRAFFIC_LOW 0 -#define TRAFFIC_HIGH 1 - -struct sw_ant_sw { - u8 try_flag; - s32 PreRSSI; - u8 CurAntenna; - u8 PreAntenna; - u8 RSSI_Trying; - u8 TestMode; - u8 bTriggerAntennaSwitch; - u8 SelectAntennaMap; - u8 RSSI_target; - - /* Before link Antenna Switch check */ - u8 SWAS_NoLink_State; - u32 SWAS_NoLink_BK_Reg860; - bool ANTA_ON; /* To indicate Ant A is or not */ - bool ANTB_ON; /* To indicate Ant B is on or not */ - - s32 RSSI_sum_A; - s32 RSSI_sum_B; - s32 RSSI_cnt_A; - s32 RSSI_cnt_B; - - u64 lastTxOkCnt; - u64 lastRxOkCnt; - u64 TXByteCnt_A; - u64 TXByteCnt_B; - u64 RXByteCnt_A; - u64 RXByteCnt_B; - u8 TrafficLoad; -}; - -struct edca_turbo { - bool bCurrentTurboEDCA; - u32 prv_traffic_idx; /* edca turbo */ -}; - -struct odm_rate_adapt { - u8 Type; /* DM_Type_ByFW/DM_Type_ByDriver */ - u8 HighRSSIThresh; /* if RSSI > HighRSSIThresh => RATRState is DM_RATR_STA_HIGH */ - u8 LowRSSIThresh; /* if RSSI <= LowRSSIThresh => RATRState is DM_RATR_STA_LOW */ - u8 RATRState; /* Current RSSI level, DM_RATR_STA_HIGH/DM_RATR_STA_MIDDLE/DM_RATR_STA_LOW */ - u32 LastRATR; /* RATR Register Content */ -}; - -#define IQK_MAC_REG_NUM 4 -#define IQK_ADDA_REG_NUM 16 -#define IQK_BB_REG_NUM_MAX 10 -#define IQK_BB_REG_NUM 9 -#define HP_THERMAL_NUM 8 - -#define AVG_THERMAL_NUM 8 -#define IQK_Matrix_REG_NUM 8 -#define IQK_Matrix_Settings_NUM 1+24+21 - -#define DM_Type_ByFW 0 -#define DM_Type_ByDriver 1 - -/* Declare for common info */ - -struct odm_phy_dbg_info { - /* ODM Write,debug info */ - s8 RxSNRdB[RF_PATH_MAX]; - u64 NumQryPhyStatus; - u64 NumQryPhyStatusCCK; - u64 NumQryPhyStatusOFDM; - /* Others */ - s32 RxEVM[RF_PATH_MAX]; - -}; - -struct odm_packet_info { - u8 Rate; - u8 StationID; - bool bPacketMatchBSSID; - bool bPacketToSelf; - bool bPacketBeacon; -}; - - -enum { - /* BB Team */ - ODM_DIG = 0x00000001, - ODM_HIGH_POWER = 0x00000002, - ODM_CCK_CCA_TH = 0x00000004, - ODM_FA_STATISTICS = 0x00000008, - ODM_RAMASK = 0x00000010, - ODM_RSSI_MONITOR = 0x00000020, - ODM_SW_ANTDIV = 0x00000040, - ODM_HW_ANTDIV = 0x00000080, - ODM_BB_PWRSV = 0x00000100, - ODM_2TPATHDIV = 0x00000200, - ODM_1TPATHDIV = 0x00000400, - ODM_PSD2AFH = 0x00000800 -}; - -/* */ -/* 2011/10/20 MH Define Common info enum for all team. */ -/* */ - -enum odm_cmninfo { - /* Fixed value: */ - /* */ - - ODM_CMNINFO_MP_TEST_CHIP = 2, - ODM_CMNINFO_IC_TYPE, /* enum odm_ic_type_def */ - ODM_CMNINFO_CUT_VER, /* enum odm_cut_version */ - ODM_CMNINFO_FAB_VER, /* enum odm_fab_version */ - ODM_CMNINFO_BOARD_TYPE, /* enum odm_board_type */ - ODM_CMNINFO_EXT_LNA, /* true */ - ODM_CMNINFO_EXT_PA, - ODM_CMNINFO_EXT_TRSW, - ODM_CMNINFO_BINHCT_TEST, - ODM_CMNINFO_BWIFI_TEST, - ODM_CMNINFO_SMART_CONCURRENT, - - - /* */ - /* Dynamic value: */ - /* */ - ODM_CMNINFO_MP_MODE, - - ODM_CMNINFO_WIFI_DIRECT, - ODM_CMNINFO_WIFI_DISPLAY, - ODM_CMNINFO_LINK, - ODM_CMNINFO_RSSI_MIN, - ODM_CMNINFO_DBG_COMP, /* u64 */ - ODM_CMNINFO_DBG_LEVEL, /* u32 */ - ODM_CMNINFO_RA_THRESHOLD_HIGH, /* u8 */ - ODM_CMNINFO_RA_THRESHOLD_LOW, /* u8 */ - ODM_CMNINFO_RF_ANTENNA_TYPE, /* u8 */ - ODM_CMNINFO_BT_DISABLED, - ODM_CMNINFO_BT_OPERATION, - ODM_CMNINFO_BT_DIG, - ODM_CMNINFO_BT_BUSY, /* Check Bt is using or not */ - ODM_CMNINFO_BT_DISABLE_EDCA, - - /* */ - /* Dynamic ptr array hook itms. */ - /* */ - ODM_CMNINFO_STA_STATUS, - ODM_CMNINFO_PHY_STATUS, - ODM_CMNINFO_MAC_STATUS, - - ODM_CMNINFO_MAX, -}; - -/* Define ODM support ability. ODM_CMNINFO_ABILITY */ -enum { - /* BB ODM section BIT 0-15 */ - ODM_BB_ANT_DIV = BIT(6), -}; - -/* ODM_CMNINFO_INTERFACE */ -enum odm_interface_def { - ODM_ITRF_PCIE = 0x1, - ODM_ITRF_USB = 0x2, - ODM_ITRF_SDIO = 0x4, - ODM_ITRF_ALL = 0x7, -}; - -/* ODM_CMNINFO_IC_TYPE */ -enum odm_ic_type_def { - ODM_RTL8192S = BIT(0), - ODM_RTL8192C = BIT(1), - ODM_RTL8192D = BIT(2), - ODM_RTL8723A = BIT(3), - ODM_RTL8188E = BIT(4), - ODM_RTL8812 = BIT(5), - ODM_RTL8821 = BIT(6), -}; - -/* ODM_CMNINFO_CUT_VER */ -enum odm_cut_version { - ODM_CUT_A = 1, - ODM_CUT_B = 2, - ODM_CUT_C = 3, - ODM_CUT_D = 4, - ODM_CUT_E = 5, - ODM_CUT_F = 6, - ODM_CUT_TEST = 7, -}; - -/* ODM_CMNINFO_FAB_VER */ -enum odm_fab_version { - ODM_TSMC = 0, - ODM_UMC = 1, -}; - -/* For example 1T2R (A+AB = BIT0|BIT4|BIT5) */ -enum rf_path_def { - ODM_RF_TX_A = BIT(0), - ODM_RF_TX_B = BIT(1), - ODM_RF_TX_C = BIT(2), - ODM_RF_TX_D = BIT(3), - ODM_RF_RX_A = BIT(4), - ODM_RF_RX_B = BIT(5), - ODM_RF_RX_C = BIT(6), - ODM_RF_RX_D = BIT(7), -}; - -/* ODM Dynamic common info value definition */ - -enum odm_mac_phy_mode { - ODM_SMSP = 0, - ODM_DMSP = 1, - ODM_DMDP = 2, -}; - - -enum odm_bt_coexist { - ODM_BT_BUSY = 1, - ODM_BT_ON = 2, - ODM_BT_OFF = 3, - ODM_BT_NONE = 4, -}; - -/* ODM_CMNINFO_OP_MODE */ -enum odm_operation_mode { - ODM_NO_LINK = BIT(0), - ODM_LINK = BIT(1), - ODM_SCAN = BIT(2), - ODM_POWERSAVE = BIT(3), - ODM_AP_MODE = BIT(4), - ODM_CLIENT_MODE = BIT(5), - ODM_AD_HOC = BIT(6), - ODM_WIFI_DIRECT = BIT(7), - ODM_WIFI_DISPLAY = BIT(8), -}; - -/* ODM_CMNINFO_WM_MODE */ -enum odm_wireless_mode { - ODM_WM_UNKNOW = 0x0, - ODM_WM_B = BIT(0), - ODM_WM_G = BIT(1), - ODM_WM_A = BIT(2), - ODM_WM_N24G = BIT(3), - ODM_WM_N5G = BIT(4), - ODM_WM_AUTO = BIT(5), - ODM_WM_AC = BIT(6), -}; - -/* ODM_CMNINFO_BAND */ -enum odm_band_type { - ODM_BAND_2_4G = BIT(0), - ODM_BAND_5G = BIT(1), - -}; - -/* ODM_CMNINFO_SEC_CHNL_OFFSET */ -enum odm_sec_chnl_offset { - ODM_DONT_CARE = 0, - ODM_BELOW = 1, - ODM_ABOVE = 2 -}; - -/* ODM_CMNINFO_CHNL */ - -/* ODM_CMNINFO_BOARD_TYPE */ -enum odm_board_type { - ODM_BOARD_NORMAL = 0, - ODM_BOARD_HIGHPWR = 1, - ODM_BOARD_MINICARD = 2, - ODM_BOARD_SLIM = 3, - ODM_BOARD_COMBO = 4, - -}; - -/* ODM_CMNINFO_ONE_PATH_CCA */ -enum odm_cca_path { - ODM_CCA_2R = 0, - ODM_CCA_1R_A = 1, - ODM_CCA_1R_B = 2, -}; - -struct iqk_matrix_regs_set { - bool bIQKDone; - s32 Value[1][IQK_Matrix_REG_NUM]; -}; - -struct odm_rf_cal_t { - /* for tx power tracking */ - - u32 RegA24; /* for TempCCK */ - s32 RegE94; - s32 RegE9C; - s32 RegEB4; - s32 RegEBC; - - /* u8 bTXPowerTracking; */ - u8 TXPowercount; - bool bTXPowerTrackingInit; - 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; - u8 ThermalValue_LCK; - u8 ThermalValue_IQK; - u8 ThermalValue_DPK; - u8 ThermalValue_AVG[AVG_THERMAL_NUM]; - u8 ThermalValue_AVG_index; - u8 ThermalValue_RxGain; - u8 ThermalValue_Crystal; - u8 ThermalValue_DPKstore; - u8 ThermalValue_DPKtrack; - bool TxPowerTrackingInProgress; - bool bDPKenable; - - bool bReloadtxpowerindex; - u8 bRfPiEnable; - u32 TXPowerTrackingCallbackCnt; /* cosa add for debug */ - - u8 bCCKinCH14; - u8 CCK_index; - u8 OFDM_index[2]; - bool bDoneTxpower; - - u8 ThermalValue_HP[HP_THERMAL_NUM]; - u8 ThermalValue_HP_index; - struct iqk_matrix_regs_set IQKMatrixRegSetting[IQK_Matrix_Settings_NUM]; - - u8 Delta_IQK; - u8 Delta_LCK; - - /* for IQK */ - u32 RegC04; - u32 Reg874; - u32 RegC08; - u32 RegB68; - u32 RegB6C; - u32 Reg870; - u32 Reg860; - u32 Reg864; - - bool bIQKInitialized; - bool bLCKInProgress; - bool bAntennaDetected; - u32 ADDA_backup[IQK_ADDA_REG_NUM]; - u32 IQK_MAC_backup[IQK_MAC_REG_NUM]; - u32 IQK_BB_backup_recover[9]; - u32 IQK_BB_backup[IQK_BB_REG_NUM]; - - /* for APK */ - u32 APKoutput[2][2]; /* path A/B; output1_1a/output1_2a */ - u8 bAPKdone; - u8 bAPKThermalMeterIgnore; - u8 bDPdone; - u8 bDPPathAOK; - u8 bDPPathBOK; -}; - -enum ant_dif_type { - NO_ANTDIV = 0xFF, - CG_TRX_HW_ANTDIV = 0x01, - CGCS_RX_HW_ANTDIV = 0x02, - FIXED_HW_ANTDIV = 0x03, - CG_TRX_SMART_ANTDIV = 0x04, - CGCS_RX_SW_ANTDIV = 0x05, -}; - -/* 2011/09/22 MH Copy from SD4 defined structure. We use to support PHY DM integration. */ -struct dm_odm_t { - /* */ - /* Add for different team use temporarily */ - /* */ - struct rtw_adapter *Adapter; /* For CE/NIC team */ - - u64 DebugComponents; - u32 DebugLevel; - -/* ODM HANDLE, DRIVER NEEDS NOT TO HOOK------ */ - bool bCckHighPower; - u8 RFPathRxEnable; /* ODM_CMNINFO_RFPATH_ENABLE */ -/* ODM HANDLE, DRIVER NEEDS NOT TO HOOK------ */ - -/* 1 COMMON INFORMATION */ - - /* Init Value */ -/* HOOK BEFORE REG INIT----------- */ - /* ODM Support Ability DIG/RATR/TX_PWR_TRACK/ ¡K¡K = 1/2/3/¡K */ - u32 SupportAbility; - /* ODM composite or independent. Bit oriented/ 92C+92D+ .... or any other type = 1/2/3/... */ - u32 SupportICType; - /* Cut Version TestChip/A-cut/B-cut... = 0/1/2/3/... */ - u8 CutVersion; - /* Fab Version TSMC/UMC = 0/1 */ - u8 FabVersion; - /* Board Type Normal/HighPower/MiniCard/SLIM/Combo/... = 0/1/2/3/4/... */ - u8 BoardType; - /* with external LNA NO/Yes = 0/1 */ - u8 ExtLNA; - /* with external PA NO/Yes = 0/1 */ - u8 ExtPA; - /* with external TRSW NO/Yes = 0/1 */ - u8 ExtTRSW; - bool bInHctTest; - bool bWIFITest; - - bool bDualMacSmartConcurrent; - u32 BK_SupportAbility; -/* HOOK BEFORE REG INIT----------- */ - - /* */ - /* Dynamic Value */ - /* */ -/* POINTER REFERENCE----------- */ - - u8 u8_temp; - bool bool_temp; - struct rtw_adapter *PADAPTER_temp; - -/* POINTER REFERENCE----------- */ - /* */ -/* CALL BY VALUE------------- */ - bool bWIFI_Direct; - bool bWIFI_Display; - bool bLinked; - u8 RSSI_Min; - u8 InterfaceIndex; /* Add for 92D dual MAC: 0--Mac0 1--Mac1 */ - bool bIsMPChip; - bool bOneEntryOnly; - /* Common info for BTDM */ - bool bBtDisabled; /* BT is disabled */ - bool bBtHsOperation; /* BT HS mode is under progress */ - u8 btHsDigVal; /* use BT rssi to decide the DIG value */ - bool bBtDisableEdcaTurbo; /* Under some condition, don't enable the EDCA Turbo */ - bool bBtBusy; /* BT is busy. */ -/* CALL BY VALUE------------- */ - - /* 2 Define STA info. */ - /* _ODM_STA_INFO */ - /* 2012/01/12 MH For MP, we need to reduce one array pointer for default port.?? */ - struct sta_info * pODM_StaInfo[ODM_ASSOCIATE_ENTRY_NUM]; - - /* Latest packet phy info (ODM write) */ - struct odm_phy_dbg_info PhyDbgInfo; - /* PHY_INFO_88E PhyInfo; */ - - /* Latest packet phy info (ODM write) */ - /* MAC_INFO_88E MacInfo; */ - - /* Different Team independt structure?? */ - - /* */ - /* TX_RTP_CMN TX_retrpo; */ - /* TX_RTP_88E TX_retrpo; */ - /* TX_RTP_8195 TX_retrpo; */ - - /* */ - /* ODM Structure */ - /* */ - struct dig_t DM_DigTable; - struct dynamic_pwr_sav DM_PSTable; - struct false_alarm_stats FalseAlmCnt; - struct false_alarm_stats FlaseAlmCntBuddyAdapter; - struct sw_ant_sw DM_SWAT_Table; - - struct edca_turbo DM_EDCA_Table; - u32 WMMEDCA_BE; - /* Copy from SD4 structure */ - /* */ - /* ================================================== */ - /* */ - - /* PSD */ - u8 RSSI_BT; /* come from BT */ - struct odm_rate_adapt RateAdaptive; - - - struct odm_rf_cal_t RFCalibrateInfo; -}; /* DM_Dynamic_Mechanism_Structure */ - -enum odm_rf_content { - odm_radioa_txt = 0x1000, - odm_radiob_txt = 0x1001, - odm_radioc_txt = 0x1002, - odm_radiod_txt = 0x1003 -}; - -/* Status code */ -enum rt_status { - RT_STATUS_SUCCESS, - RT_STATUS_FAILURE, - RT_STATUS_PENDING, - RT_STATUS_RESOURCE, - RT_STATUS_INVALID_CONTEXT, - RT_STATUS_INVALID_PARAMETER, - RT_STATUS_NOT_SUPPORT, - RT_STATUS_OS_API_FAILED, -}; - -/* include "odm_function.h" */ - -/* 3=========================================================== */ -/* 3 DIG */ -/* 3=========================================================== */ - -enum dm_dig_op { - DIG_TYPE_THRESH_HIGH = 0, - DIG_TYPE_THRESH_LOW = 1, - DIG_TYPE_BACKOFF = 2, - DIG_TYPE_RX_GAIN_MIN = 3, - DIG_TYPE_RX_GAIN_MAX = 4, - DIG_TYPE_ENABLE = 5, - DIG_TYPE_DISABLE = 6, - DIG_OP_TYPE_MAX -}; - -#define DM_DIG_THRESH_HIGH 40 -#define DM_DIG_THRESH_LOW 35 - -#define DM_SCAN_RSSI_TH 0x14 /* scan return issue for LC */ - - -#define DM_FALSEALARM_THRESH_LOW 400 -#define DM_FALSEALARM_THRESH_HIGH 1000 - -#define DM_DIG_MAX_NIC 0x4e -#define DM_DIG_MIN_NIC 0x1e - -#define DM_DIG_MAX_AP 0x32 -#define DM_DIG_MIN_AP 0x20 - -#define DM_DIG_MAX_NIC_HP 0x46 -#define DM_DIG_MIN_NIC_HP 0x2e - -#define DM_DIG_MAX_AP_HP 0x42 -#define DM_DIG_MIN_AP_HP 0x30 - -/* vivi 92c&92d has different definition, 20110504 */ -/* this is for 92c */ -#define DM_DIG_FA_TH0 0x200 -#define DM_DIG_FA_TH1 0x300 -#define DM_DIG_FA_TH2 0x400 -/* this is for 92d */ -#define DM_DIG_FA_TH0_92D 0x100 -#define DM_DIG_FA_TH1_92D 0x400 -#define DM_DIG_FA_TH2_92D 0x600 - -#define DM_DIG_BACKOFF_MAX 12 -#define DM_DIG_BACKOFF_MIN -4 -#define DM_DIG_BACKOFF_DEFAULT 10 - -/* 3=========================================================== */ -/* 3 AGC RX High Power Mode */ -/* 3=========================================================== */ -#define LNA_Low_Gain_1 0x64 -#define LNA_Low_Gain_2 0x5A -#define LNA_Low_Gain_3 0x58 - -#define FA_RXHP_TH1 5000 -#define FA_RXHP_TH2 1500 -#define FA_RXHP_TH3 800 -#define FA_RXHP_TH4 600 -#define FA_RXHP_TH5 500 - -/* 3=========================================================== */ -/* 3 EDCA */ -/* 3=========================================================== */ - -/* 3=========================================================== */ -/* 3 Dynamic Tx Power */ -/* 3=========================================================== */ -/* Dynamic Tx Power Control Threshold */ -#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 -#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 -#define TX_POWER_NEAR_FIELD_THRESH_AP 0x3F - -#define TxHighPwrLevel_Normal 0 -#define TxHighPwrLevel_Level1 1 -#define TxHighPwrLevel_Level2 2 -#define TxHighPwrLevel_BT1 3 -#define TxHighPwrLevel_BT2 4 -#define TxHighPwrLevel_15 5 -#define TxHighPwrLevel_35 6 -#define TxHighPwrLevel_50 7 -#define TxHighPwrLevel_70 8 -#define TxHighPwrLevel_100 9 - -/* 3=========================================================== */ -/* 3 Rate Adaptive */ -/* 3=========================================================== */ -#define DM_RATR_STA_INIT 0 -#define DM_RATR_STA_HIGH 1 -#define DM_RATR_STA_MIDDLE 2 -#define DM_RATR_STA_LOW 3 - -/* 3=========================================================== */ -/* 3 BB Power Save */ -/* 3=========================================================== */ - - -enum dm_1r_cca { - CCA_1R =0, - CCA_2R = 1, - CCA_MAX = 2, -}; - -enum dm_rf_def { - RF_Save =0, - RF_Normal = 1, - RF_MAX = 2, -}; - -/* 3=========================================================== */ -/* 3 Antenna Diversity */ -/* 3=========================================================== */ -enum dm_swas { - Antenna_A = 1, - Antenna_B = 2, - Antenna_MAX = 3, -}; - -/* Maximal number of antenna detection mechanism needs to perform, added by Roger, 2011.12.28. */ -#define MAX_ANTENNA_DETECTION_CNT 10 - -/* */ -/* Extern Global Variables. */ -/* */ -#define OFDM_TABLE_SIZE_92C 37 -#define OFDM_TABLE_SIZE_92D 43 -#define CCK_TABLE_SIZE 33 - -extern u32 OFDMSwingTable23A[OFDM_TABLE_SIZE_92D]; -extern u8 CCKSwingTable_Ch1_Ch1323A[CCK_TABLE_SIZE][8]; -extern u8 CCKSwingTable_Ch1423A [CCK_TABLE_SIZE][8]; - - - -/* 20100514 Joseph: Add definition for antenna switching test after link. */ -/* This indicates two different the steps. */ -/* In SWAW_STEP_PEAK, driver needs to switch antenna and listen to the signal on the air. */ -/* In SWAW_STEP_DETERMINE, driver just compares the signal captured in SWAW_STEP_PEAK */ -/* with original RSSI to determine if it is necessary to switch antenna. */ -#define SWAW_STEP_PEAK 0 -#define SWAW_STEP_DETERMINE 1 - -struct hal_data_8723a; - -void ODM_Write_DIG23a(struct dm_odm_t *pDM_Odm, u8 CurrentIGI); -void ODM_Write_CCK_CCA_Thres23a(struct dm_odm_t *pDM_Odm, u8 CurCCK_CCAThres); - -void ODM_SetAntenna(struct dm_odm_t *pDM_Odm, u8 Antenna); - - -#define dm_RF_Saving ODM_RF_Saving23a -void ODM_RF_Saving23a(struct dm_odm_t *pDM_Odm, u8 bForceInNormal); - -#define dm_CheckTXPowerTracking ODM_TXPowerTrackingCheck23a -void ODM_TXPowerTrackingCheck23a(struct dm_odm_t *pDM_Odm); - -bool ODM_RAStateCheck23a(struct dm_odm_t *pDM_Odm, s32 RSSI, bool bForceUpdate, - u8 *pRATRState); - - -u32 ConvertTo_dB23a(u32 Value); - -u32 GetPSDData(struct dm_odm_t *pDM_Odm, unsigned int point, u8 initial_gain_psd); - -void odm_DIG23abyRSSI_LPS(struct dm_odm_t *pDM_Odm); - -u32 ODM_Get_Rate_Bitmap23a(struct hal_data_8723a *pHalData, u32 macid, u32 ra_mask, u8 rssi_level); - - -void ODM23a_DMInit(struct dm_odm_t *pDM_Odm); - -void ODM_DMWatchdog23a(struct rtw_adapter *adapter); - -void ODM_CmnInfoInit23a(struct dm_odm_t *pDM_Odm, enum odm_cmninfo CmnInfo, u32 Value); - -void ODM_CmnInfoPtrArrayHook23a(struct dm_odm_t *pDM_Odm, enum odm_cmninfo CmnInfo, u16 Index, void *pValue); - -void ODM_CmnInfoUpdate23a(struct dm_odm_t *pDM_Odm, u32 CmnInfo, u64 Value); - -void ODM_ResetIQKResult(struct dm_odm_t *pDM_Odm); - -void ODM_AntselStatistics_88C(struct dm_odm_t *pDM_Odm, u8 MacId, u32 PWDBAll, bool isCCKrate); - -void ODM_SingleDualAntennaDefaultSetting(struct dm_odm_t *pDM_Odm); - -bool ODM_SingleDualAntennaDetection(struct dm_odm_t *pDM_Odm, u8 mode); - -#endif diff --git a/drivers/staging/rtl8723au/include/odm_HWConfig.h b/drivers/staging/rtl8723au/include/odm_HWConfig.h deleted file mode 100644 index c748d5f..0000000 --- a/drivers/staging/rtl8723au/include/odm_HWConfig.h +++ /dev/null @@ -1,153 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ - - -#ifndef __HALHWOUTSRC_H__ -#define __HALHWOUTSRC_H__ - -#include <Hal8723APhyCfg.h> - -/* */ -/* Definition */ -/* */ -/* */ -/* */ -/* CCK Rates, TxHT = 0 */ -#define DESC92C_RATE1M 0x00 -#define DESC92C_RATE2M 0x01 -#define DESC92C_RATE5_5M 0x02 -#define DESC92C_RATE11M 0x03 - -/* OFDM Rates, TxHT = 0 */ -#define DESC92C_RATE6M 0x04 -#define DESC92C_RATE9M 0x05 -#define DESC92C_RATE12M 0x06 -#define DESC92C_RATE18M 0x07 -#define DESC92C_RATE24M 0x08 -#define DESC92C_RATE36M 0x09 -#define DESC92C_RATE48M 0x0a -#define DESC92C_RATE54M 0x0b - -/* MCS Rates, TxHT = 1 */ -#define DESC92C_RATEMCS0 0x0c -#define DESC92C_RATEMCS1 0x0d -#define DESC92C_RATEMCS2 0x0e -#define DESC92C_RATEMCS3 0x0f -#define DESC92C_RATEMCS4 0x10 -#define DESC92C_RATEMCS5 0x11 -#define DESC92C_RATEMCS6 0x12 -#define DESC92C_RATEMCS7 0x13 -#define DESC92C_RATEMCS8 0x14 -#define DESC92C_RATEMCS9 0x15 -#define DESC92C_RATEMCS10 0x16 -#define DESC92C_RATEMCS11 0x17 -#define DESC92C_RATEMCS12 0x18 -#define DESC92C_RATEMCS13 0x19 -#define DESC92C_RATEMCS14 0x1a -#define DESC92C_RATEMCS15 0x1b -#define DESC92C_RATEMCS15_SG 0x1c -#define DESC92C_RATEMCS32 0x20 - - -/* */ -/* structure and define */ -/* */ - -struct phy_rx_agc_info { - #ifdef __LITTLE_ENDIAN - u8 gain:7, trsw:1; - #else - u8 trsw:1, gain:7; - #endif -}; - -struct phy_status_rpt { - struct phy_rx_agc_info path_agc[RF_PATH_MAX]; - u8 ch_corr[RF_PATH_MAX]; - u8 cck_sig_qual_ofdm_pwdb_all; - u8 cck_agc_rpt_ofdm_cfosho_a; - u8 cck_rpt_b_ofdm_cfosho_b; - u8 rsvd_1;/* ch_corr_msb; */ - u8 noise_power_db_msb; - u8 path_cfotail[RF_PATH_MAX]; - u8 pcts_mask[RF_PATH_MAX]; - s8 stream_rxevm[RF_PATH_MAX]; - u8 path_rxsnr[RF_PATH_MAX]; - u8 noise_power_db_lsb; - u8 rsvd_2[3]; - u8 stream_csi[RF_PATH_MAX]; - u8 stream_target_csi[RF_PATH_MAX]; - s8 sig_evm; - u8 rsvd_3; - -#ifdef __LITTLE_ENDIAN - u8 antsel_rx_keep_2:1; /* ex_intf_flg:1; */ - u8 sgi_en:1; - u8 rxsc:2; - u8 idle_long:1; - u8 r_ant_train_en:1; - u8 ant_sel_b:1; - u8 ant_sel:1; -#else /* _BIG_ENDIAN_ */ - u8 ant_sel:1; - u8 ant_sel_b:1; - u8 r_ant_train_en:1; - u8 idle_long:1; - u8 rxsc:2; - u8 sgi_en:1; - u8 antsel_rx_keep_2:1; /* ex_intf_flg:1; */ -#endif -}; - - -struct phy_status_rpt_8195 { - struct phy_rx_agc_info path_agc[2]; - u8 ch_num[2]; - u8 cck_sig_qual_ofdm_pwdb_all; - u8 cck_agc_rpt_ofdm_cfosho_a; - u8 cck_bb_pwr_ofdm_cfosho_b; - u8 cck_rx_path; /* CCK_RX_PATH [3:0] (with regA07[3:0] definition) */ - u8 rsvd_1; - u8 path_cfotail[2]; - u8 pcts_mask[2]; - s8 stream_rxevm[2]; - u8 path_rxsnr[2]; - u8 rsvd_2[2]; - u8 stream_snr[2]; - u8 stream_csi[2]; - u8 rsvd_3[2]; - s8 sig_evm; - u8 rsvd_4; -#ifdef __LITTLE_ENDIAN - u8 antidx_anta:3; - u8 antidx_antb:3; - u8 rsvd_5:2; -#else /* _BIG_ENDIAN_ */ - u8 rsvd_5:2; - u8 antidx_antb:3; - u8 antidx_anta:3; -#endif -}; - - -void -ODM_PhyStatusQuery23a( - struct dm_odm_t *pDM_Odm, - struct phy_info *pPhyInfo, - u8 * pPhyStatus, - struct odm_packet_info *pPktinfo - ); - -#endif diff --git a/drivers/staging/rtl8723au/include/odm_RegConfig8723A.h b/drivers/staging/rtl8723au/include/odm_RegConfig8723A.h deleted file mode 100644 index f2a54d8..0000000 --- a/drivers/staging/rtl8723au/include/odm_RegConfig8723A.h +++ /dev/null @@ -1,27 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __INC_ODM_REGCONFIG_H_8723A -#define __INC_ODM_REGCONFIG_H_8723A - -void odm_ConfigRFReg_8723A(struct dm_odm_t *pDM_Odm, u32 Addr, u32 Data, - enum RF_RADIO_PATH RF_PATH, u32 RegAddr); - -void odm_ConfigMAC_8723A(struct dm_odm_t *pDM_Odm, u32 Addr, u8 Data); - -void odm_ConfigBB_AGC_8723A(struct dm_odm_t *pDM_Odm, u32 addr, u32 data); - -void odm_ConfigBB_PHY_8723A(struct dm_odm_t *pDM_Odm, u32 addr, u32 data); - -#endif /* end of SUPPORT */ diff --git a/drivers/staging/rtl8723au/include/odm_RegDefine11N.h b/drivers/staging/rtl8723au/include/odm_RegDefine11N.h deleted file mode 100644 index 2778215..0000000 --- a/drivers/staging/rtl8723au/include/odm_RegDefine11N.h +++ /dev/null @@ -1,165 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ - -#ifndef __ODM_REGDEFINE11N_H__ -#define __ODM_REGDEFINE11N_H__ - - -/* 2 RF REG LIST */ -#define ODM_REG_RF_MODE_11N 0x00 -#define ODM_REG_RF_0B_11N 0x0B -#define ODM_REG_CHNBW_11N 0x18 -#define ODM_REG_T_METER_11N 0x24 -#define ODM_REG_RF_25_11N 0x25 -#define ODM_REG_RF_26_11N 0x26 -#define ODM_REG_RF_27_11N 0x27 -#define ODM_REG_RF_2B_11N 0x2B -#define ODM_REG_RF_2C_11N 0x2C -#define ODM_REG_RXRF_A3_11N 0x3C -#define ODM_REG_T_METER_92D_11N 0x42 -#define ODM_REG_T_METER_88E_11N 0x42 - - - -/* 2 BB REG LIST */ -/* PAGE 8 */ -#define ODM_REG_BB_CTRL_11N 0x800 -#define ODM_REG_RF_PIN_11N 0x804 -#define ODM_REG_PSD_CTRL_11N 0x808 -#define ODM_REG_TX_ANT_CTRL_11N 0x80C -#define ODM_REG_BB_PWR_SAV5_11N 0x818 -#define ODM_REG_CCK_RPT_FORMAT_11N 0x824 -#define ODM_REG_RX_DEFUALT_A_11N 0x858 -#define ODM_REG_RX_DEFUALT_B_11N 0x85A -#define ODM_REG_BB_PWR_SAV3_11N 0x85C -#define ODM_REG_ANTSEL_CTRL_11N 0x860 -#define ODM_REG_RX_ANT_CTRL_11N 0x864 -#define ODM_REG_PIN_CTRL_11N 0x870 -#define ODM_REG_BB_PWR_SAV1_11N 0x874 -#define ODM_REG_ANTSEL_PATH_11N 0x878 -#define ODM_REG_BB_3WIRE_11N 0x88C -#define ODM_REG_SC_CNT_11N 0x8C4 -#define ODM_REG_PSD_DATA_11N 0x8B4 -/* PAGE 9 */ -#define ODM_REG_ANT_MAPPING1_11N 0x914 -#define ODM_REG_ANT_MAPPING2_11N 0x918 -/* PAGE A */ -#define ODM_REG_CCK_ANTDIV_PARA1_11N 0xA00 -#define ODM_REG_CCK_CCA_11N 0xA0A -#define ODM_REG_CCK_ANTDIV_PARA2_11N 0xA0C -#define ODM_REG_CCK_ANTDIV_PARA3_11N 0xA10 -#define ODM_REG_CCK_ANTDIV_PARA4_11N 0xA14 -#define ODM_REG_CCK_FILTER_PARA1_11N 0xA22 -#define ODM_REG_CCK_FILTER_PARA2_11N 0xA23 -#define ODM_REG_CCK_FILTER_PARA3_11N 0xA24 -#define ODM_REG_CCK_FILTER_PARA4_11N 0xA25 -#define ODM_REG_CCK_FILTER_PARA5_11N 0xA26 -#define ODM_REG_CCK_FILTER_PARA6_11N 0xA27 -#define ODM_REG_CCK_FILTER_PARA7_11N 0xA28 -#define ODM_REG_CCK_FILTER_PARA8_11N 0xA29 -#define ODM_REG_CCK_FA_RST_11N 0xA2C -#define ODM_REG_CCK_FA_MSB_11N 0xA58 -#define ODM_REG_CCK_FA_LSB_11N 0xA5C -#define ODM_REG_CCK_CCA_CNT_11N 0xA60 -#define ODM_REG_BB_PWR_SAV4_11N 0xA74 -/* PAGE B */ -#define ODM_REG_LNA_SWITCH_11N 0xB2C -#define ODM_REG_PATH_SWITCH_11N 0xB30 -#define ODM_REG_RSSI_CTRL_11N 0xB38 -#define ODM_REG_CONFIG_ANTA_11N 0xB68 -#define ODM_REG_RSSI_BT_11N 0xB9C -/* PAGE C */ -#define ODM_REG_OFDM_FA_HOLDC_11N 0xC00 -#define ODM_REG_RX_PATH_11N 0xC04 -#define ODM_REG_TRMUX_11N 0xC08 -#define ODM_REG_OFDM_FA_RSTC_11N 0xC0C -#define ODM_REG_RXIQI_MATRIX_11N 0xC14 -#define ODM_REG_TXIQK_MATRIX_LSB1_11N 0xC4C -#define ODM_REG_IGI_A_11N 0xC50 -#define ODM_REG_ANTDIV_PARA2_11N 0xC54 -#define ODM_REG_IGI_B_11N 0xC58 -#define ODM_REG_ANTDIV_PARA3_11N 0xC5C -#define ODM_REG_BB_PWR_SAV2_11N 0xC70 -#define ODM_REG_RX_OFF_11N 0xC7C -#define ODM_REG_TXIQK_MATRIXA_11N 0xC80 -#define ODM_REG_TXIQK_MATRIXB_11N 0xC88 -#define ODM_REG_TXIQK_MATRIXA_LSB2_11N 0xC94 -#define ODM_REG_TXIQK_MATRIXB_LSB2_11N 0xC9C -#define ODM_REG_RXIQK_MATRIX_LSB_11N 0xCA0 -#define ODM_REG_ANTDIV_PARA1_11N 0xCA4 -#define ODM_REG_OFDM_FA_TYPE1_11N 0xCF0 -/* PAGE D */ -#define ODM_REG_OFDM_FA_RSTD_11N 0xD00 -#define ODM_REG_OFDM_FA_TYPE2_11N 0xDA0 -#define ODM_REG_OFDM_FA_TYPE3_11N 0xDA4 -#define ODM_REG_OFDM_FA_TYPE4_11N 0xDA8 -/* PAGE E */ -#define ODM_REG_TXAGC_A_6_18_11N 0xE00 -#define ODM_REG_TXAGC_A_24_54_11N 0xE04 -#define ODM_REG_TXAGC_A_1_MCS32_11N 0xE08 -#define ODM_REG_TXAGC_A_MCS0_3_11N 0xE10 -#define ODM_REG_TXAGC_A_MCS4_7_11N 0xE14 -#define ODM_REG_TXAGC_A_MCS8_11_11N 0xE18 -#define ODM_REG_TXAGC_A_MCS12_15_11N 0xE1C -#define ODM_REG_FPGA0_IQK_11N 0xE28 -#define ODM_REG_TXIQK_TONE_A_11N 0xE30 -#define ODM_REG_RXIQK_TONE_A_11N 0xE34 -#define ODM_REG_TXIQK_PI_A_11N 0xE38 -#define ODM_REG_RXIQK_PI_A_11N 0xE3C -#define ODM_REG_TXIQK_11N 0xE40 -#define ODM_REG_RXIQK_11N 0xE44 -#define ODM_REG_IQK_AGC_PTS_11N 0xE48 -#define ODM_REG_IQK_AGC_RSP_11N 0xE4C -#define ODM_REG_BLUETOOTH_11N 0xE6C -#define ODM_REG_RX_WAIT_CCA_11N 0xE70 -#define ODM_REG_TX_CCK_RFON_11N 0xE74 -#define ODM_REG_TX_CCK_BBON_11N 0xE78 -#define ODM_REG_OFDM_RFON_11N 0xE7C -#define ODM_REG_OFDM_BBON_11N 0xE80 -#define ODM_REG_TX2RX_11N 0xE84 -#define ODM_REG_TX2TX_11N 0xE88 -#define ODM_REG_RX_CCK_11N 0xE8C -#define ODM_REG_RX_OFDM_11N 0xED0 -#define ODM_REG_RX_WAIT_RIFS_11N 0xED4 -#define ODM_REG_RX2RX_11N 0xED8 -#define ODM_REG_STANDBY_11N 0xEDC -#define ODM_REG_SLEEP_11N 0xEE0 -#define ODM_REG_PMPD_ANAEN_11N 0xEEC - - - - - - - -/* 2 MAC REG LIST */ -#define ODM_REG_BB_RST_11N 0x02 -#define ODM_REG_ANTSEL_PIN_11N 0x4C -#define ODM_REG_EARLY_MODE_11N 0x4D0 -#define ODM_REG_RSSI_MONITOR_11N 0x4FE -#define ODM_REG_EDCA_VO_11N 0x500 -#define ODM_REG_EDCA_VI_11N 0x504 -#define ODM_REG_EDCA_BE_11N 0x508 -#define ODM_REG_EDCA_BK_11N 0x50C -#define ODM_REG_TXPAUSE_11N 0x522 -#define ODM_REG_RESP_TX_11N 0x6D8 -#define ODM_REG_ANT_TRAIN_PARA1_11N 0x7b0 -#define ODM_REG_ANT_TRAIN_PARA2_11N 0x7b4 - - -/* DIG Related */ -#define ODM_BIT_IGI_11N 0x0000007F - -#endif diff --git a/drivers/staging/rtl8723au/include/odm_debug.h b/drivers/staging/rtl8723au/include/odm_debug.h deleted file mode 100644 index c4b375a..0000000 --- a/drivers/staging/rtl8723au/include/odm_debug.h +++ /dev/null @@ -1,117 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ - - -#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 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 unexpeted 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 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_TRAIN 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 Macro Definition---------------------------*/ - #define RT_PRINTK(fmt, args...) printk("%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)) \ - { \ - printk("[ODM-8723A] "); \ - RT_PRINTK fmt; \ - } - -#define ODM_RT_ASSERT(pDM_Odm, expr, fmt) \ - if(!(expr)) { \ - printk("Assertion failed! %s at ......\n", #expr); \ - printk(" ......%s,%s,line=%d\n", __FILE__, __func__, __LINE__);\ - RT_PRINTK fmt; \ - ASSERT(false); \ - } - -void ODM_InitDebugSetting23a(struct dm_odm_t *pDM_Odm); - -#endif /* __ODM_DBG_H__ */ diff --git a/drivers/staging/rtl8723au/include/odm_interface.h b/drivers/staging/rtl8723au/include/odm_interface.h deleted file mode 100644 index 1d3bf03..0000000 --- a/drivers/staging/rtl8723au/include/odm_interface.h +++ /dev/null @@ -1,62 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ - - -#ifndef __ODM_INTERFACE_H__ -#define __ODM_INTERFACE_H__ - - -/* _cat: implemented by Token-Pasting Operator. */ - -/*=================================== - -#define ODM_REG_DIG_11N 0xC50 -#define ODM_REG_DIG_11AC 0xDDD - -ODM_REG(DIG,_pDM_Odm) -=====================================*/ - -#define _reg_11N(_name) ODM_REG_##_name##_11N -#define _reg_11AC(_name) ODM_REG_##_name##_11AC -#define _bit_11N(_name) ODM_BIT_##_name##_11N -#define _bit_11AC(_name) ODM_BIT_##_name##_11AC - -#define _cat(_name, _func) \ - ( \ - _func##_11N(_name) \ - ) - -/* _name: name of register or bit. */ -/* Example: "ODM_REG(R_A_AGC_CORE1, pDM_Odm)" */ -/* gets "ODM_R_A_AGC_CORE1" or "ODM_R_A_AGC_CORE1_8192C", depends on SupportICType. */ -#define ODM_REG(_name, _pDM_Odm) _cat(_name, _reg) -#define ODM_BIT(_name, _pDM_Odm) _cat(_name, _bit) - -/* */ -/* 2012/02/17 MH For non-MP compile pass only. Linux does not support workitem. */ -/* Suggest HW team to use thread instead of workitem. Windows also support the feature. */ -/* */ -typedef void (*RT_WORKITEM_CALL_BACK)(struct work_struct *pContext); - -/* */ -/* =========== EXtern Function Prototype */ -/* */ - -void ODM_SetRFReg(struct dm_odm_t *pDM_Odm, enum RF_RADIO_PATH eRFPath, - u32 RegAddr, u32 BitMask, u32 Data); -u32 ODM_GetRFReg(struct dm_odm_t *pDM_Odm, enum RF_RADIO_PATH eRFPath, - u32 RegAddr, u32 BitMask); - -#endif /* __ODM_INTERFACE_H__ */ diff --git a/drivers/staging/rtl8723au/include/odm_precomp.h b/drivers/staging/rtl8723au/include/odm_precomp.h deleted file mode 100644 index fb793c8..0000000 --- a/drivers/staging/rtl8723au/include/odm_precomp.h +++ /dev/null @@ -1,49 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ - -#ifndef __ODM_PRECOMP_H__ -#define __ODM_PRECOMP_H__ - -/* 2 Config Flags and Structs - defined by each ODM Type */ - -#include <osdep_service.h> -#include <drv_types.h> -#include <hal_intf.h> - - -/* 2 Hardware Parameter Files */ -#include "Hal8723UHWImg_CE.h" - - -/* 2 OutSrc Header Files */ - -#include "odm.h" -#include "odm_HWConfig.h" -#include "odm_debug.h" -#include "odm_RegDefine11N.h" - -#include "HalDMOutSrc8723A.h" /* for IQK,LCK,Power-tracking */ -#include "rtl8723a_hal.h" - -#include "odm_interface.h" -#include "odm_reg.h" - -#include "HalHWImg8723A_MAC.h" -#include "HalHWImg8723A_RF.h" -#include "HalHWImg8723A_BB.h" -#include "HalHWImg8723A_FW.h" -#include "odm_RegConfig8723A.h" - -#endif /* __ODM_PRECOMP_H__ */ diff --git a/drivers/staging/rtl8723au/include/odm_reg.h b/drivers/staging/rtl8723au/include/odm_reg.h deleted file mode 100644 index c1843312..0000000 --- a/drivers/staging/rtl8723au/include/odm_reg.h +++ /dev/null @@ -1,111 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -/* */ -/* File Name: odm_reg.h */ -/* */ -/* Description: */ -/* */ -/* This file is for general register definition. */ -/* */ -/* */ -/* */ -#ifndef __HAL_ODM_REG_H__ -#define __HAL_ODM_REG_H__ - -/* */ -/* Register Definition */ -/* */ - -/* MAC REG */ -#define ODM_BB_RESET 0x002 -#define ODM_DUMMY 0x4fe -#define ODM_EDCA_VO_PARAM 0x500 -#define ODM_EDCA_VI_PARAM 0x504 -#define ODM_EDCA_BE_PARAM 0x508 -#define ODM_EDCA_BK_PARAM 0x50C -#define ODM_TXPAUSE 0x522 - -/* BB REG */ -#define ODM_FPGA_PHY0_PAGE8 0x800 -#define ODM_PSD_SETTING 0x808 -#define ODM_AFE_SETTING 0x818 -#define ODM_TXAGC_B_6_18 0x830 -#define ODM_TXAGC_B_24_54 0x834 -#define ODM_TXAGC_B_MCS32_5 0x838 -#define ODM_TXAGC_B_MCS0_MCS3 0x83c -#define ODM_TXAGC_B_MCS4_MCS7 0x848 -#define ODM_TXAGC_B_MCS8_MCS11 0x84c -#define ODM_ANALOG_REGISTER 0x85c -#define ODM_RF_INTERFACE_OUTPUT 0x860 -#define ODM_TXAGC_B_MCS12_MCS15 0x868 -#define ODM_TXAGC_B_11_A_2_11 0x86c -#define ODM_AD_DA_LSB_MASK 0x874 -#define ODM_ENABLE_3_WIRE 0x88c -#define ODM_PSD_REPORT 0x8b4 -#define ODM_R_ANT_SELECT 0x90c -#define ODM_CCK_ANT_SELECT 0xa07 -#define ODM_CCK_PD_THRESH 0xa0a -#define ODM_CCK_RF_REG1 0xa11 -#define ODM_CCK_MATCH_FILTER 0xa20 -#define ODM_CCK_RAKE_MAC 0xa2e -#define ODM_CCK_CNT_RESET 0xa2d -#define ODM_CCK_TX_DIVERSITY 0xa2f -#define ODM_CCK_FA_CNT_MSB 0xa5b -#define ODM_CCK_FA_CNT_LSB 0xa5c -#define ODM_CCK_NEW_FUNCTION 0xa75 -#define ODM_OFDM_PHY0_PAGE_C 0xc00 -#define ODM_OFDM_RX_ANT 0xc04 -#define ODM_R_A_RXIQI 0xc14 -#define ODM_R_A_AGC_CORE1 0xc50 -#define ODM_R_A_AGC_CORE2 0xc54 -#define ODM_R_B_AGC_CORE1 0xc58 -#define ODM_R_AGC_PAR 0xc70 -#define ODM_R_HTSTF_AGC_PAR 0xc7c -#define ODM_TX_PWR_TRAINING_A 0xc90 -#define ODM_TX_PWR_TRAINING_B 0xc98 -#define ODM_OFDM_FA_CNT1 0xcf0 -#define ODM_OFDM_PHY0_PAGE_D 0xd00 -#define ODM_OFDM_FA_CNT2 0xda0 -#define ODM_OFDM_FA_CNT3 0xda4 -#define ODM_OFDM_FA_CNT4 0xda8 -#define ODM_TXAGC_A_6_18 0xe00 -#define ODM_TXAGC_A_24_54 0xe04 -#define ODM_TXAGC_A_1_MCS32 0xe08 -#define ODM_TXAGC_A_MCS0_MCS3 0xe10 -#define ODM_TXAGC_A_MCS4_MCS7 0xe14 -#define ODM_TXAGC_A_MCS8_MCS11 0xe18 -#define ODM_TXAGC_A_MCS12_MCS15 0xe1c - -/* RF REG */ -#define ODM_GAIN_SETTING 0x00 -#define ODM_CHANNEL 0x18 - -/* Ant Detect Reg */ -#define ODM_DPDT 0x300 - -/* PSD Init */ -#define ODM_PSDREG 0x808 - -/* 92D Path Div */ -#define PATHDIV_REG 0xB30 -#define PATHDIV_TRI 0xBA0 - -/* */ -/* Bitmap Definition */ -/* */ - -#define BIT_FA_RESET BIT(0) - -#endif diff --git a/drivers/staging/rtl8723au/include/osdep_intf.h b/drivers/staging/rtl8723au/include/osdep_intf.h deleted file mode 100644 index a157eb2..0000000 --- a/drivers/staging/rtl8723au/include/osdep_intf.h +++ /dev/null @@ -1,45 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ - -#ifndef __OSDEP_INTF_H_ -#define __OSDEP_INTF_H_ - -#include <osdep_service.h> -#include <drv_types.h> - -int rtw_init_drv_sw23a(struct rtw_adapter *padapter); -int rtw_free_drv_sw23a(struct rtw_adapter *padapter); -int rtw_reset_drv_sw23a(struct rtw_adapter *padapter); - -void rtw_cancel_all_timer23a(struct rtw_adapter *padapter); - -int rtw_init_netdev23a_name23a(struct net_device *pnetdev, const char *ifname); -struct net_device *rtw_init_netdev23a(struct rtw_adapter *padapter); - -u16 rtw_recv_select_queue23a(struct sk_buff *skb); - -void rtw_ips_dev_unload23a(struct rtw_adapter *padapter); - -int rtw_ips_pwr_up23a(struct rtw_adapter *padapter); -void rtw_ips_pwr_down23a(struct rtw_adapter *padapter); - -int rtw_drv_register_netdev(struct rtw_adapter *padapter); -void rtw_ndev_destructor(struct net_device *ndev); - -int rtl8723au_inirp_init(struct rtw_adapter *Adapter); -int rtl8723au_inirp_deinit(struct rtw_adapter *Adapter); -void rtl8723a_usb_intf_stop(struct rtw_adapter *padapter); - -#endif /* _OSDEP_INTF_H_ */ diff --git a/drivers/staging/rtl8723au/include/osdep_service.h b/drivers/staging/rtl8723au/include/osdep_service.h deleted file mode 100644 index 33ecb9c..0000000 --- a/drivers/staging/rtl8723au/include/osdep_service.h +++ /dev/null @@ -1,87 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __OSDEP_SERVICE_H_ -#define __OSDEP_SERVICE_H_ - -#define _FAIL 0 -#define _SUCCESS 1 -#define RTW_RX_HANDLED 2 - -#include <linux/spinlock.h> -#include <linux/compiler.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/kref.h> -#include <linux/netdevice.h> -#include <linux/skbuff.h> -#include <linux/uaccess.h> -#include <asm/byteorder.h> -#include <linux/atomic.h> -#include <linux/io.h> -#include <linux/sem.h> -#include <linux/sched.h> -#include <linux/etherdevice.h> -#include <linux/wireless.h> -#include <linux/if_arp.h> -#include <linux/rtnetlink.h> -#include <linux/delay.h> -#include <linux/interrupt.h> /* for struct tasklet_struct */ -#include <linux/ip.h> - -#include <net/ieee80211_radiotap.h> -#include <net/cfg80211.h> - -struct rtw_queue { - struct list_head queue; - spinlock_t lock; -}; - -static inline struct list_head *get_list_head(struct rtw_queue *queue) -{ - return &queue->queue; -} - -static inline int rtw_netif_queue_stopped(struct net_device *pnetdev) -{ - return (netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 0)) && - netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 1)) && - netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 2)) && - netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 3))); -} - -static inline u32 CHKBIT(u32 x) -{ - WARN_ON(x >= 32); - if (x >= 32) - return 0; - return BIT(x); -} - -extern unsigned char MCS_rate_2R23A[16]; - -extern unsigned char MCS_rate_2R23A[16]; -extern unsigned char MCS_rate_1R23A[16]; - -void _rtw_init_queue23a(struct rtw_queue *pqueue); - -/* Macros for handling unaligned memory accesses */ - -#define RTW_GET_BE24(a) ((((u32) (a)[0]) << 16) | (((u32) (a)[1]) << 8) | \ - ((u32) (a)[2])) - -#endif diff --git a/drivers/staging/rtl8723au/include/recv_osdep.h b/drivers/staging/rtl8723au/include/recv_osdep.h deleted file mode 100644 index c2d3f1b..0000000 --- a/drivers/staging/rtl8723au/include/recv_osdep.h +++ /dev/null @@ -1,36 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __RECV_OSDEP_H_ -#define __RECV_OSDEP_H_ - -#include <osdep_service.h> -#include <drv_types.h> - -int _rtw_init_recv_priv23a(struct recv_priv *precvpriv, struct rtw_adapter *padapter); -void _rtw_free_recv_priv23a (struct recv_priv *precvpriv); - -int rtw_recv_entry23a(struct recv_frame *precv_frame); -int rtw_recv_indicatepkt23a(struct rtw_adapter *adapter, struct recv_frame *precv_frame); - -void rtw_handle_tkip_mic_err23a(struct rtw_adapter *padapter, u8 bgroup); - -int rtw_init_recv_priv(struct recv_priv *precvpriv, struct rtw_adapter *padapter); -void rtw_free_recv_priv (struct recv_priv *precvpriv); - -int rtw_os_recv_resource_init(struct recv_priv *precvpriv, struct rtw_adapter *padapter); - -void rtw_init_recv_timer23a(struct recv_reorder_ctrl *preorder_ctrl); - -#endif diff --git a/drivers/staging/rtl8723au/include/rtl8723a_bt-coexist.h b/drivers/staging/rtl8723au/include/rtl8723a_bt-coexist.h deleted file mode 100644 index 7add5df..0000000 --- a/drivers/staging/rtl8723au/include/rtl8723a_bt-coexist.h +++ /dev/null @@ -1,1627 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __RTL8723A_BT_COEXIST_H__ -#define __RTL8723A_BT_COEXIST_H__ - -#include <drv_types.h> -#include "odm_precomp.h" - - -/* HEADER/PlatformDef.h */ -enum rt_media_status { - RT_MEDIA_DISCONNECT = 0, - RT_MEDIA_CONNECT = 1 -}; - -/* ===== Below this line is sync from SD7 driver COMMON/BT.h ===== */ - -#define BT_TMP_BUF_SIZE 100 - -void BT_SignalCompensation(struct rtw_adapter *padapter, - u8 *rssi_wifi, u8 *rssi_bt); -void BT_HaltProcess(struct rtw_adapter *padapter); -void BT_LpsLeave(struct rtw_adapter *padapter); - - -#define BT_HsConnectionEstablished(Adapter) false -/* ===== End of sync from SD7 driver COMMON/BT.h ===== */ - -/* HEADER/SecurityType.h */ -#define TKIP_ENC_KEY_POS 32 /* KEK_LEN+KEK_LEN) */ -#define MAXRSNIELEN 256 - -/* COMMON/Protocol802_11.h */ -/* */ -/* 802.11 Management frame Status Code field */ -/* */ -struct octet_string { - u8 *Octet; - u16 Length; -}; - - -/* AES_CCMP specific */ -enum { - AESCCMP_BLK_SIZE = 16, /* # octets in an AES block */ - AESCCMP_MAX_PACKET = 4*512, /* largest packet size */ - AESCCMP_N_RESERVED = 0, /* reserved nonce octet value */ - AESCCMP_A_DATA = 0x40, /* the Adata bit in the flags */ - AESCCMP_M_SHIFT = 3, /* how much to shift the 3-bit M field */ - AESCCMP_L_SHIFT = 0, /* how much to shift the 3-bit L field */ - AESCCMP_L_SIZE = 2, /* size of the l(m) length field (in octets) */ - AESCCMP_OFFSET_SC = 22, - AESCCMP_OFFSET_DURATION = 4, - AESCCMP_OFFSET_A2 = 10, - AESCCMP_OFFSET_A4 = 24, - AESCCMP_QC_TID_MASK = 0x0f, - AESCCMP_BLK_SIZE_TOTAL = 16*16, /* Added by Annie for CKIP AES MIC BSOD, 2006-08-17. */ - /* 16*8 < 4*60 Resove to 16*16 */ -}; - -/* Key Length */ -#define PMK_LEN 32 -#define PTK_LEN_TKIP 64 -#define GTK_LEN 32 -#define KEY_NONCE_LEN 32 - - -/* COMMON/Dot11d.h */ -struct chnl_txpower_triple { - u8 FirstChnl; - u8 NumChnls; - s8 MaxTxPowerInDbm; -}; - - -/* ===== Below this line is sync from SD7 driver COMMON/bt_hci.h ===== */ -/* The following is for BT 3.0 + HS HCI COMMAND ERRORS CODES */ - -#define Max80211PALPDUSize 1492 -#define Max80211AMPASSOCLen 672 -#define MinGUserPrio 4 -#define MaxGUserPrio 7 -#define BEUserPrio0 0 -#define BEUserPrio1 3 -#define Max80211BeaconPeriod 2000 -#define ShortRangeModePowerMax 4 - -#define BT_Default_Chnl 10 -#define ACLDataHeaderLen 4 - -#define BTTotalDataBlockNum 0x100 -#define BTLocalBufNum 0x200 -#define BTMaxDataBlockLen 0x800 -#define BTTOTALBANDWIDTH 0x7530 -#define BTMAXBANDGUBANDWIDTH 0x4e20 -#define TmpLocalBufSize 0x100 -#define BTSynDataPacketLength 0xff -/* */ - -#define BTMaxAuthCount 5 -#define BTMaxAsocCount 5 - -#define MAX_LOGICAL_LINK_NUM 2 /* temporarily define */ -#define MAX_BT_ASOC_ENTRY_NUM 2 /* temporarily define */ - -#define INVALID_PL_HANDLE 0xff -#define INVALID_ENTRY_NUM 0xff -/* */ - -#define CAM_BT_START_INDEX (HALF_CAM_ENTRY - 4) /* MAX_BT_ASOC_ENTRY_NUM : 4 !!! */ -#define BT_HWCAM_STAR CAM_BT_START_INDEX /* We used HALF_CAM_ENTRY ~ HALF_CAM_ENTRY -MAX_BT_ASOC_ENTRY_NUM */ - -enum hci_status { - HCI_STATUS_SUCCESS = 0x00, /* Success */ - HCI_STATUS_UNKNOW_HCI_CMD = 0x01, /* Unknown HCI Command */ - HCI_STATUS_UNKNOW_CONNECT_ID = 0X02, /* Unknown Connection Identifier */ - HCI_STATUS_HW_FAIL = 0X03, /* Hardware Failure */ - HCI_STATUS_PAGE_TIMEOUT = 0X04, /* Page Timeout */ - HCI_STATUS_AUTH_FAIL = 0X05, /* Authentication Failure */ - HCI_STATUS_PIN_OR_KEY_MISSING = 0X06, /* PIN or Key Missing */ - HCI_STATUS_MEM_CAP_EXCEED = 0X07, /* Memory Capacity Exceeded */ - HCI_STATUS_CONNECT_TIMEOUT = 0X08, /* Connection Timeout */ - HCI_STATUS_CONNECT_LIMIT = 0X09, /* Connection Limit Exceeded */ - HCI_STATUS_SYN_CONNECT_LIMIT = 0X0a, /* Synchronous Connection Limit To A Device Exceeded */ - HCI_STATUS_ACL_CONNECT_EXISTS = 0X0b, /* ACL Connection Already Exists */ - HCI_STATUS_CMD_DISALLOW = 0X0c, /* Command Disallowed */ - HCI_STATUS_CONNECT_RJT_LIMIT_RESOURCE = 0X0d, /* Connection Rejected due to Limited Resources */ - HCI_STATUS_CONNECT_RJT_SEC_REASON = 0X0e, /* Connection Rejected Due To Security Reasons */ - HCI_STATUS_CONNECT_RJT_UNACCEPT_BD_ADDR = 0X0f, /* Connection Rejected due to Unacceptable BD_ADDR */ - HCI_STATUS_CONNECT_ACCEPT_TIMEOUT = 0X10, /* Connection Accept Timeout Exceeded */ - HCI_STATUS_UNSUPPORT_FEATURE_PARA_VALUE = 0X11, /* Unsupported Feature or Parameter Value */ - HCI_STATUS_INVALID_HCI_CMD_PARA_VALUE = 0X12, /* Invalid HCI Command Parameters */ - HCI_STATUS_REMOTE_USER_TERMINATE_CONNECT = 0X13, /* Remote User Terminated Connection */ - HCI_STATUS_REMOTE_DEV_TERMINATE_LOW_RESOURCE = 0X14, /* Remote Device Terminated Connection due to Low Resources */ - HCI_STATUS_REMOTE_DEV_TERMINATE_CONNECT_POWER_OFF = 0X15, /* Remote Device Terminated Connection due to Power Off */ - HCI_STATUS_CONNECT_TERMINATE_LOCAL_HOST = 0X16, /* Connection Terminated By Local Host */ - HCI_STATUS_REPEATE_ATTEMPT = 0X17, /* Repeated Attempts */ - HCI_STATUS_PAIR_NOT_ALLOW = 0X18, /* Pairing Not Allowed */ - HCI_STATUS_UNKNOW_LMP_PDU = 0X19, /* Unknown LMP PDU */ - HCI_STATUS_UNSUPPORT_REMOTE_LMP_FEATURE = 0X1a, /* Unsupported Remote Feature / Unsupported LMP Feature */ - HCI_STATUS_SOC_OFFSET_REJECT = 0X1b, /* SCO Offset Rejected */ - HCI_STATUS_SOC_INTERVAL_REJECT = 0X1c, /* SCO Interval Rejected */ - HCI_STATUS_SOC_AIR_MODE_REJECT = 0X1d,/* SCO Air Mode Rejected */ - HCI_STATUS_INVALID_LMP_PARA = 0X1e, /* Invalid LMP Parameters */ - HCI_STATUS_UNSPECIFIC_ERROR = 0X1f, /* Unspecified Error */ - HCI_STATUS_UNSUPPORT_LMP_PARA_VALUE = 0X20, /* Unsupported LMP Parameter Value */ - HCI_STATUS_ROLE_CHANGE_NOT_ALLOW = 0X21, /* Role Change Not Allowed */ - HCI_STATUS_LMP_RESPONSE_TIMEOUT = 0X22, /* LMP Response Timeout */ - HCI_STATUS_LMP_ERROR_TRANSACTION_COLLISION = 0X23, /* LMP Error Transaction Collision */ - HCI_STATUS_LMP_PDU_NOT_ALLOW = 0X24, /* LMP PDU Not Allowed */ - HCI_STATUS_ENCRYPTION_MODE_NOT_ALLOW = 0X25, /* Encryption Mode Not Acceptable */ - HCI_STATUS_LINK_KEY_CAN_NOT_CHANGE = 0X26, /* Link Key Can Not be Changed */ - HCI_STATUS_REQUEST_QOS_NOT_SUPPORT = 0X27, /* Requested QoS Not Supported */ - HCI_STATUS_INSTANT_PASSED = 0X28, /* Instant Passed */ - HCI_STATUS_PAIRING_UNIT_KEY_NOT_SUPPORT = 0X29, /* Pairing With Unit Key Not Supported */ - HCI_STATUS_DIFFERENT_TRANSACTION_COLLISION = 0X2a, /* Different Transaction Collision */ - HCI_STATUS_RESERVE_1 = 0X2b, /* Reserved */ - HCI_STATUS_QOS_UNACCEPT_PARA = 0X2c, /* QoS Unacceptable Parameter */ - HCI_STATUS_QOS_REJECT = 0X2d, /* QoS Rejected */ - HCI_STATUS_CHNL_CLASSIFICATION_NOT_SUPPORT = 0X2e, /* Channel Classification Not Supported */ - HCI_STATUS_INSUFFICIENT_SECURITY = 0X2f, /* Insufficient Security */ - HCI_STATUS_PARA_OUT_OF_RANGE = 0x30, /* Parameter Out Of Mandatory Range */ - HCI_STATUS_RESERVE_2 = 0X31, /* Reserved */ - HCI_STATUS_ROLE_SWITCH_PENDING = 0X32, /* Role Switch Pending */ - HCI_STATUS_RESERVE_3 = 0X33, /* Reserved */ - HCI_STATUS_RESERVE_SOLT_VIOLATION = 0X34, /* Reserved Slot Violation */ - HCI_STATUS_ROLE_SWITCH_FAIL = 0X35, /* Role Switch Failed */ - HCI_STATUS_EXTEND_INQUIRY_RSP_TOO_LARGE = 0X36, /* Extended Inquiry Response Too Large */ - HCI_STATUS_SEC_SIMPLE_PAIRING_NOT_SUPPORT = 0X37, /* Secure Simple Pairing Not Supported By Host. */ - HCI_STATUS_HOST_BUSY_PAIRING = 0X38, /* Host Busy - Pairing */ - HCI_STATUS_CONNECT_REJ_NOT_SUIT_CHNL_FOUND = 0X39, /* Connection Rejected due to No Suitable Channel Found */ - HCI_STATUS_CONTROLLER_BUSY = 0X3a /* CONTROLLER BUSY */ -}; - -/* */ -/* The following is for BT 3.0 + HS HCI COMMAND */ -/* */ - -/* bit 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */ -/* | OCF | OGF | */ -/* */ - -/* OGF 0x01 */ -#define LINK_CONTROL_COMMANDS 0x01 -enum link_control_commands { - HCI_INQUIRY = 0x0001, - HCI_INQUIRY_CANCEL = 0x0002, - HCI_PERIODIC_INQUIRY_MODE = 0x0003, - HCI_EXIT_PERIODIC_INQUIRY_MODE = 0x0004, - HCI_CREATE_CONNECTION = 0x0005, - HCI_DISCONNECT = 0x0006, - HCI_CREATE_CONNECTION_CANCEL = 0x0008, - HCI_ACCEPT_CONNECTIONREQUEST = 0x0009, - HCI_REJECT_CONNECTION_REQUEST = 0x000a, - HCI_LINK_KEY_REQUEST_REPLY = 0x000b, - HCI_LINK_KEY_REQUEST_NEGATIVE_REPLY = 0x000c, - HCI_PIN_CODE_REQUEST_REPLY = 0x000d, - HCI_PIN_CODE_REQUEST_NEGATIVE_REPLY = 0x000e, - HCI_CHANGE_CONNECTION_PACKET_TYPE = 0x000f, - HCI_AUTHENTICATION_REQUESTED = 0x0011, - HCI_SET_CONNECTION_ENCRYPTION = 0x0013, - HCI_CHANGE_CONNECTION_LINK_KEY = 0x0015, - HCI_MASTER_LINK_KEY = 0x0017, - HCI_REMOTE_NAME_REQUEST = 0x0019, - HCI_REMOTE_NAME_REQUEST_CANCEL = 0x001a, - HCI_READ_REMOTE_SUPPORTED_FEATURES = 0x001b, - HCI_READ_REMOTE_EXTENDED_FEATURES = 0x001c, - HCI_READ_REMOTE_VERSION_INFORMATION = 0x001d, - HCI_READ_CLOCK_OFFSET = 0x001f, - HCI_READ_LMP_HANDLE = 0x0020, - HCI_SETUP_SYNCHRONOUS_CONNECTION = 0x0028, - HCI_ACCEPT_SYNCHRONOUS_CONNECTION_REQUEST = 0x0029, - HCI_REJECT_SYNCHRONOUS_CONNECTION_REQUEST = 0x002a, - HCI_IO_CAPABILITY_REQUEST_REPLY = 0x002b, - HCI_USER_CONFIRMATION_REQUEST_REPLY = 0x002c, - HCI_USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY = 0x002d, - HCI_USER_PASSKEY_REQUEST_REPLY = 0x002e, - HCI_USER_PASSKEY_REQUESTNEGATIVE_REPLY = 0x002f, - HCI_REMOTE_OOB_DATA_REQUEST_REPLY = 0x0030, - HCI_REMOTE_OOB_DATA_REQUEST_NEGATIVE_REPLY = 0x0033, - HCI_IO_CAPABILITY_REQUEST_NEGATIVE_REPLY = 0x0034, - HCI_CREATE_PHYSICAL_LINK = 0x0035, - HCI_ACCEPT_PHYSICAL_LINK = 0x0036, - HCI_DISCONNECT_PHYSICAL_LINK = 0x0037, - HCI_CREATE_LOGICAL_LINK = 0x0038, - HCI_ACCEPT_LOGICAL_LINK = 0x0039, - HCI_DISCONNECT_LOGICAL_LINK = 0x003a, - HCI_LOGICAL_LINK_CANCEL = 0x003b, - HCI_FLOW_SPEC_MODIFY = 0x003c -}; - -/* OGF 0x02 */ -#define HOLD_MODE_COMMAND 0x02 -enum hold_mode_command { - HCI_HOLD_MODE = 0x0001, - HCI_SNIFF_MODE = 0x0002, - HCI_EXIT_SNIFF_MODE = 0x0003, - HCI_PARK_STATE = 0x0005, - HCI_EXIT_PARK_STATE = 0x0006, - HCI_QOS_SETUP = 0x0007, - HCI_ROLE_DISCOVERY = 0x0009, - HCI_SWITCH_ROLE = 0x000b, - HCI_READ_LINK_POLICY_SETTINGS = 0x000c, - HCI_WRITE_LINK_POLICY_SETTINGS = 0x000d, - HCI_READ_DEFAULT_LINK_POLICY_SETTINGS = 0x000e, - HCI_WRITE_DEFAULT_LINK_POLICY_SETTINGS = 0x000f, - HCI_FLOW_SPECIFICATION = 0x0010, - HCI_SNIFF_SUBRATING = 0x0011 -}; - -/* OGF 0x03 */ -#define OGF_SET_EVENT_MASK_COMMAND 0x03 -enum set_event_mask_command { - HCI_SET_EVENT_MASK = 0x0001, - HCI_RESET = 0x0003, - HCI_SET_EVENT_FILTER = 0x0005, - HCI_FLUSH = 0x0008, - HCI_READ_PIN_TYPE = 0x0009, - HCI_WRITE_PIN_TYPE = 0x000a, - HCI_CREATE_NEW_UNIT_KEY = 0x000b, - HCI_READ_STORED_LINK_KEY = 0x000d, - HCI_WRITE_STORED_LINK_KEY = 0x0011, - HCI_DELETE_STORED_LINK_KEY = 0x0012, - HCI_WRITE_LOCAL_NAME = 0x0013, - HCI_READ_LOCAL_NAME = 0x0014, - HCI_READ_CONNECTION_ACCEPT_TIMEOUT = 0x0015, - HCI_WRITE_CONNECTION_ACCEPT_TIMEOUT = 0x0016, - HCI_READ_PAGE_TIMEOUT = 0x0017, - HCI_WRITE_PAGE_TIMEOUT = 0x0018, - HCI_READ_SCAN_ENABLE = 0x0019, - HCI_WRITE_SCAN_ENABLE = 0x001a, - HCI_READ_PAGE_SCAN_ACTIVITY = 0x001b, - HCI_WRITE_PAGE_SCAN_ACTIVITY = 0x001c, - HCI_READ_INQUIRY_SCAN_ACTIVITY = 0x001d, - HCI_WRITE_INQUIRY_SCAN_ACTIVITY = 0x001e, - HCI_READ_AUTHENTICATION_ENABLE = 0x001f, - HCI_WRITE_AUTHENTICATION_ENABLE = 0x0020, - HCI_READ_CLASS_OF_DEVICE = 0x0023, - HCI_WRITE_CLASS_OF_DEVICE = 0x0024, - HCI_READ_VOICE_SETTING = 0x0025, - HCI_WRITE_VOICE_SETTING = 0x0026, - HCI_READ_AUTOMATIC_FLUSH_TIMEOUT = 0x0027, - HCI_WRITE_AUTOMATIC_FLUSH_TIMEOUT = 0x0028, - HCI_READ_NUM_BROADCAST_RETRANSMISSIONS = 0x0029, - HCI_WRITE_NUM_BROADCAST_RETRANSMISSIONS = 0x002a, - HCI_READ_HOLD_MODE_ACTIVITY = 0x002b, - HCI_WRITE_HOLD_MODE_ACTIVITY = 0x002c, - HCI_READ_SYNCHRONOUS_FLOW_CONTROL_ENABLE = 0x002e, - HCI_WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE = 0x002f, - HCI_SET_CONTROLLER_TO_HOST_FLOW_CONTROL = 0x0031, - HCI_HOST_BUFFER_SIZE = 0x0033, - HCI_HOST_NUMBER_OF_COMPLETED_PACKETS = 0x0035, - HCI_READ_LINK_SUPERVISION_TIMEOUT = 0x0036, - HCI_WRITE_LINK_SUPERVISION_TIMEOUT = 0x0037, - HCI_READ_NUMBER_OF_SUPPORTED_IAC = 0x0038, - HCI_READ_CURRENT_IAC_LAP = 0x0039, - HCI_WRITE_CURRENT_IAC_LAP = 0x003a, - HCI_READ_PAGE_SCAN_MODE = 0x003d, - HCI_WRITE_PAGE_SCAN_MODE = 0x003e, - HCI_SET_AFH_HOST_CHANNEL_CLASSIFICATION = 0x003f, - HCI_READ_INQUIRY_SCAN_TYPE = 0x0042, - HCI_WRITE_INQUIRY_SCAN_TYPE = 0x0043, - HCI_READ_INQUIRY_MODE = 0x0044, - HCI_WRITE_INQUIRY_MODE = 0x0045, - HCI_READ_PAGE_SCAN_TYPE = 0x0046, - HCI_WRITE_PAGE_SCAN_TYPE = 0x0047, - HCI_READ_AFH_CHANNEL_ASSESSMENT_MODE = 0x0048, - HCI_WRITE_AFH_CHANNEL_ASSESSMENT_MODE = 0x0049, - HCI_READ_EXTENDED_INQUIRY_RESPONSE = 0x0051, - HCI_WRITE_EXTENDED_INQUIRY_RESPONSE = 0x0052, - HCI_REFRESH_ENCRYPTION_KEY = 0x0053, - HCI_READ_SIMPLE_PAIRING_MODE = 0x0055, - HCI_WRITE_SIMPLE_PAIRING_MODE = 0x0056, - HCI_READ_LOCAL_OOB_DATA = 0x0057, - HCI_READ_INQUIRY_RESPONSE_TRANSMIT_POWER_LEVEL = 0x0058, - HCI_WRITE_INQUIRY_TRANSMIT_POWER_LEVEL = 0x0059, - HCI_READ_DEFAULT_ERRONEOUS_DATA_REPORTING = 0x005a, - HCI_WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING = 0x005b, - HCI_ENHANCED_FLUSH = 0x005f, - HCI_SEND_KEYPRESS_NOTIFICATION = 0x0060, - HCI_READ_LOGICAL_LINK_ACCEPT_TIMEOUT = 0x0061, - HCI_WRITE_LOGICAL_LINK_ACCEPT_TIMEOUT = 0x0062, - HCI_SET_EVENT_MASK_PAGE_2 = 0x0063, - HCI_READ_LOCATION_DATA = 0x0064, - HCI_WRITE_LOCATION_DATA = 0x0065, - HCI_READ_FLOW_CONTROL_MODE = 0x0066, - HCI_WRITE_FLOW_CONTROL_MODE = 0x0067, - HCI_READ_ENHANCE_TRANSMIT_POWER_LEVEL = 0x0068, - HCI_READ_BEST_EFFORT_FLUSH_TIMEOUT = 0x0069, - HCI_WRITE_BEST_EFFORT_FLUSH_TIMEOUT = 0x006a, - HCI_SHORT_RANGE_MODE = 0x006b -}; - -/* OGF 0x04 */ -#define OGF_INFORMATIONAL_PARAMETERS 0x04 -enum informational_params { - HCI_READ_LOCAL_VERSION_INFORMATION = 0x0001, - HCI_READ_LOCAL_SUPPORTED_COMMANDS = 0x0002, - HCI_READ_LOCAL_SUPPORTED_FEATURES = 0x0003, - HCI_READ_LOCAL_EXTENDED_FEATURES = 0x0004, - HCI_READ_BUFFER_SIZE = 0x0005, - HCI_READ_BD_ADDR = 0x0009, - HCI_READ_DATA_BLOCK_SIZE = 0x000a -}; - -/* OGF 0x05 */ -#define OGF_STATUS_PARAMETERS 0x05 -enum status_params { - HCI_READ_FAILED_CONTACT_COUNTER = 0x0001, - HCI_RESET_FAILED_CONTACT_COUNTER = 0x0002, - HCI_READ_LINK_QUALITY = 0x0003, - HCI_READ_RSSI = 0x0005, - HCI_READ_AFH_CHANNEL_MAP = 0x0006, - HCI_READ_CLOCK = 0x0007, - HCI_READ_ENCRYPTION_KEY_SIZE = 0x0008, - HCI_READ_LOCAL_AMP_INFO = 0x0009, - HCI_READ_LOCAL_AMP_ASSOC = 0x000a, - HCI_WRITE_REMOTE_AMP_ASSOC = 0x000b -}; - -/* OGF 0x06 */ -#define OGF_TESTING_COMMANDS 0x06 -enum testing_commands { - HCI_READ_LOOPBACK_MODE = 0x0001, - HCI_WRITE_LOOPBACK_MODE = 0x0002, - HCI_ENABLE_DEVICE_UNDER_TEST_MODE = 0x0003, - HCI_WRITE_SIMPLE_PAIRING_DEBUG_MODE = 0x0004, - HCI_ENABLE_AMP_RECEIVER_REPORTS = 0x0007, - HCI_AMP_TEST_END = 0x0008, - HCI_AMP_TEST_COMMAND = 0x0009 -}; - -/* OGF 0x3f */ -#define OGF_EXTENSION 0X3f -enum hci_extension_commands { - HCI_SET_ACL_LINK_DATA_FLOW_MODE = 0x0010, - HCI_SET_ACL_LINK_STATUS = 0x0020, - HCI_SET_SCO_LINK_STATUS = 0x0030, - HCI_SET_RSSI_VALUE = 0x0040, - HCI_SET_CURRENT_BLUETOOTH_STATUS = 0x0041, - - /* The following is for RTK8723 */ - HCI_EXTENSION_VERSION_NOTIFY = 0x0100, - HCI_LINK_STATUS_NOTIFY = 0x0101, - HCI_BT_OPERATION_NOTIFY = 0x0102, - HCI_ENABLE_WIFI_SCAN_NOTIFY = 0x0103, - - - /* The following is for IVT */ - HCI_WIFI_CURRENT_CHANNEL = 0x0300, - HCI_WIFI_CURRENT_BANDWIDTH = 0x0301, - HCI_WIFI_CONNECTION_STATUS = 0x0302, -}; - -enum bt_spec { - BT_SPEC_1_0_b = 0x00, - BT_SPEC_1_1 = 0x01, - BT_SPEC_1_2 = 0x02, - BT_SPEC_2_0_EDR = 0x03, - BT_SPEC_2_1_EDR = 0x04, - BT_SPEC_3_0_HS = 0x05, - BT_SPEC_4_0 = 0x06 -}; - -/* The following is for BT 3.0 + HS EVENTS */ -enum hci_event { - HCI_EVENT_INQUIRY_COMPLETE = 0x01, - HCI_EVENT_INQUIRY_RESULT = 0x02, - HCI_EVENT_CONNECTION_COMPLETE = 0x03, - HCI_EVENT_CONNECTION_REQUEST = 0x04, - HCI_EVENT_DISCONNECTION_COMPLETE = 0x05, - HCI_EVENT_AUTHENTICATION_COMPLETE = 0x06, - HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE = 0x07, - HCI_EVENT_ENCRYPTION_CHANGE = 0x08, - HCI_EVENT_CHANGE_LINK_KEY_COMPLETE = 0x09, - HCI_EVENT_MASTER_LINK_KEY_COMPLETE = 0x0a, - HCI_EVENT_READ_REMOTE_SUPPORT_FEATURES_COMPLETE = 0x0b, - HCI_EVENT_READ_REMOTE_VER_INFO_COMPLETE = 0x0c, - HCI_EVENT_QOS_SETUP_COMPLETE = 0x0d, - HCI_EVENT_COMMAND_COMPLETE = 0x0e, - HCI_EVENT_COMMAND_STATUS = 0x0f, - HCI_EVENT_HARDWARE_ERROR = 0x10, - HCI_EVENT_FLUSH_OCCRUED = 0x11, - HCI_EVENT_ROLE_CHANGE = 0x12, - HCI_EVENT_NUMBER_OF_COMPLETE_PACKETS = 0x13, - HCI_EVENT_MODE_CHANGE = 0x14, - HCI_EVENT_RETURN_LINK_KEYS = 0x15, - HCI_EVENT_PIN_CODE_REQUEST = 0x16, - HCI_EVENT_LINK_KEY_REQUEST = 0x17, - HCI_EVENT_LINK_KEY_NOTIFICATION = 0x18, - HCI_EVENT_LOOPBACK_COMMAND = 0x19, - HCI_EVENT_DATA_BUFFER_OVERFLOW = 0x1a, - HCI_EVENT_MAX_SLOTS_CHANGE = 0x1b, - HCI_EVENT_READ_CLOCK_OFFSET_COMPLETE = 0x1c, - HCI_EVENT_CONNECT_PACKET_TYPE_CHANGE = 0x1d, - HCI_EVENT_QOS_VIOLATION = 0x1e, - HCI_EVENT_PAGE_SCAN_REPETITION_MODE_CHANGE = 0x20, - HCI_EVENT_FLOW_SEPC_COMPLETE = 0x21, - HCI_EVENT_INQUIRY_RESULT_WITH_RSSI = 0x22, - HCI_EVENT_READ_REMOTE_EXT_FEATURES_COMPLETE = 0x23, - HCI_EVENT_SYNC_CONNECT_COMPLETE = 0x2c, - HCI_EVENT_SYNC_CONNECT_CHANGE = 0x2d, - HCI_EVENT_SNIFFER_SUBRATING = 0x2e, - HCI_EVENT_EXTENTED_INQUIRY_RESULT = 0x2f, - HCI_EVENT_ENCRYPTION_KEY_REFLASH_COMPLETE = 0x30, - HCI_EVENT_IO_CAPIBILITY_COMPLETE = 0x31, - HCI_EVENT_IO_CAPIBILITY_RESPONSE = 0x32, - HCI_EVENT_USER_CONFIRMTION_REQUEST = 0x33, - HCI_EVENT_USER_PASSKEY_REQUEST = 0x34, - HCI_EVENT_REMOTE_OOB_DATA_REQUEST = 0x35, - HCI_EVENT_SIMPLE_PAIRING_COMPLETE = 0x36, - HCI_EVENT_LINK_SUPERVISION_TIMEOUT_CHANGE = 0x38, - HCI_EVENT_ENHANCED_FLUSH_COMPLETE = 0x39, - HCI_EVENT_USER_PASSKEY_NOTIFICATION = 0x3b, - HCI_EVENT_KEYPRESS_NOTIFICATION = 0x3c, - HCI_EVENT_REMOTE_HOST_SUPPORT_FEATURES_NOTIFICATION = 0x3d, - HCI_EVENT_PHY_LINK_COMPLETE = 0x40, - HCI_EVENT_CHANNEL_SELECT = 0x41, - HCI_EVENT_DISCONNECT_PHY_LINK_COMPLETE = 0x42, - HCI_EVENT_PHY_LINK_LOSS_EARLY_WARNING = 0x43, - HCI_EVENT_PHY_LINK_RECOVER = 0x44, - HCI_EVENT_LOGICAL_LINK_COMPLETE = 0x45, - HCI_EVENT_DISCONNECT_LOGICAL_LINK_COMPLETE = 0x46, - HCI_EVENT_FLOW_SPEC_MODIFY_COMPLETE = 0x47, - HCI_EVENT_NUM_OF_COMPLETE_DATA_BLOCKS = 0x48, - HCI_EVENT_AMP_START_TEST = 0x49, - HCI_EVENT_AMP_TEST_END = 0x4a, - HCI_EVENT_AMP_RECEIVER_REPORT = 0x4b, - HCI_EVENT_SHORT_RANGE_MODE_CHANGE_COMPLETE = 0x4c, - HCI_EVENT_AMP_STATUS_CHANGE = 0x4d, - HCI_EVENT_EXTENSION_RTK = 0xfe, - HCI_EVENT_EXTENSION_MOTO = 0xff, -}; - -enum hci_extension_event_moto { - HCI_EVENT_GET_BT_RSSI = 0x01, -}; - -enum hci_extension_event { - HCI_EVENT_EXT_WIFI_SCAN_NOTIFY = 0x01, -}; - -enum hci_event_mask_page_2 { - EMP2_HCI_EVENT_PHY_LINK_COMPLETE = 0x0000000000000001, - EMP2_HCI_EVENT_CHANNEL_SELECT = 0x0000000000000002, - EMP2_HCI_EVENT_DISCONNECT_PHY_LINK_COMPLETE = 0x0000000000000004, - EMP2_HCI_EVENT_PHY_LINK_LOSS_EARLY_WARNING = 0x0000000000000008, - EMP2_HCI_EVENT_PHY_LINK_RECOVER = 0x0000000000000010, - EMP2_HCI_EVENT_LOGICAL_LINK_COMPLETE = 0x0000000000000020, - EMP2_HCI_EVENT_DISCONNECT_LOGICAL_LINK_COMPLETE = 0x0000000000000040, - EMP2_HCI_EVENT_FLOW_SPEC_MODIFY_COMPLETE = 0x0000000000000080, - EMP2_HCI_EVENT_NUM_OF_COMPLETE_DATA_BLOCKS = 0x0000000000000100, - EMP2_HCI_EVENT_AMP_START_TEST = 0x0000000000000200, - EMP2_HCI_EVENT_AMP_TEST_END = 0x0000000000000400, - EMP2_HCI_EVENT_AMP_RECEIVER_REPORT = 0x0000000000000800, - EMP2_HCI_EVENT_SHORT_RANGE_MODE_CHANGE_COMPLETE = 0x0000000000001000, - EMP2_HCI_EVENT_AMP_STATUS_CHANGE = 0x0000000000002000, -}; - -enum hci_state_machine { - HCI_STATE_STARTING = 0x01, - HCI_STATE_CONNECTING = 0x02, - HCI_STATE_AUTHENTICATING = 0x04, - HCI_STATE_CONNECTED = 0x08, - HCI_STATE_DISCONNECTING = 0x10, - HCI_STATE_DISCONNECTED = 0x20 -}; - -enum amp_assoc_structure_type { - AMP_MAC_ADDR = 0x01, - AMP_PREFERRED_CHANNEL_LIST = 0x02, - AMP_CONNECTED_CHANNEL = 0x03, - AMP_80211_PAL_CAP_LIST = 0x04, - AMP_80211_PAL_VISION = 0x05, - AMP_RESERVED_FOR_TESTING = 0x33 -}; - -enum amp_btap_type { - AMP_BTAP_NONE, - AMP_BTAP_CREATOR, - AMP_BTAP_JOINER -}; - -enum hci_state_with_cmd { - STATE_CMD_CREATE_PHY_LINK, - STATE_CMD_ACCEPT_PHY_LINK, - STATE_CMD_DISCONNECT_PHY_LINK, - STATE_CMD_CONNECT_ACCEPT_TIMEOUT, - STATE_CMD_MAC_START_COMPLETE, - STATE_CMD_MAC_START_FAILED, - STATE_CMD_MAC_CONNECT_COMPLETE, - STATE_CMD_MAC_CONNECT_FAILED, - STATE_CMD_MAC_DISCONNECT_INDICATE, - STATE_CMD_MAC_CONNECT_CANCEL_INDICATE, - STATE_CMD_4WAY_FAILED, - STATE_CMD_4WAY_SUCCESSED, - STATE_CMD_ENTER_STATE, - STATE_CMD_NO_SUCH_CMD, -}; - -enum hci_service_type { - SERVICE_NO_TRAFFIC, - SERVICE_BEST_EFFORT, - SERVICE_GUARANTEE -}; - -enum hci_traffic_mode { - TRAFFIC_MODE_BEST_EFFORT = 0x00, - TRAFFIC_MODE_GUARANTEED_LATENCY = 0x01, - TRAFFIC_MODE_GUARANTEED_BANDWIDTH = 0x02, - TRAFFIC_MODE_GUARANTEED_LATENCY_AND_BANDWIDTH = 0x03 -}; - -#define HCIOPCODE(_OCF, _OGF) (_OGF<<10|_OCF) -#define HCIOPCODELOW(_OCF, _OGF) (u8)(HCIOPCODE(_OCF, _OGF)&0x00ff) -#define HCIOPCODEHIGHT(_OCF, _OGF) (u8)(HCIOPCODE(_OCF, _OGF)>>8) - -#define TWOBYTE_HIGHTBYTE(_DATA) (u8)(_DATA>>8) -#define TWOBYTE_LOWBYTE(_DATA) (u8)(_DATA) - -enum amp_status { - AMP_STATUS_AVA_PHY_PWR_DWN = 0x0, - AMP_STATUS_BT_USE_ONLY = 0x1, - AMP_STATUS_NO_CAPACITY_FOR_BT = 0x2, - AMP_STATUS_LOW_CAPACITY_FOR_BT = 0x3, - AMP_STATUS_MEDIUM_CAPACITY_FOR_BT = 0x4, - AMP_STATUS_HIGH_CAPACITY_FOR_BT = 0x5, - AMP_STATUS_FULL_CAPACITY_FOR_BT = 0x6 -}; - -enum bt_wpa_msg_type { - Type_BT_4way1st = 0, - Type_BT_4way2nd = 1, - Type_BT_4way3rd = 2, - Type_BT_4way4th = 3, - Type_BT_unknow = 4 -}; - -enum bt_connect_type { - BT_CONNECT_AUTH_REQ = 0x00, - BT_CONNECT_AUTH_RSP = 0x01, - BT_CONNECT_ASOC_REQ = 0x02, - BT_CONNECT_ASOC_RSP = 0x03, - BT_DISCONNECT = 0x04 -}; - -enum bt_ll_service_type { - BT_LL_BE = 0x01, - BT_LL_GU = 0x02 -}; - -enum bt_ll_flowspec { - BT_TX_BE_FS, /* TX best effort flowspec */ - BT_RX_BE_FS, /* RX best effort flowspec */ - BT_TX_GU_FS, /* TX guaranteed latency flowspec */ - BT_RX_GU_FS, /* RX guaranteed latency flowspec */ - BT_TX_BE_AGG_FS, /* TX aggregated best effort flowspec */ - BT_RX_BE_AGG_FS, /* RX aggregated best effort flowspec */ - BT_TX_GU_BW_FS, /* TX guaranteed bandwidth flowspec */ - BT_RX_GU_BW_FS, /* RX guaranteed bandwidth flowspec */ - BT_TX_GU_LARGE_FS, /* TX guaranteed latency flowspec, for testing only */ - BT_RX_GU_LARGE_FS, /* RX guaranteed latency flowspec, for testing only */ -}; - -enum bt_traffic_mode { - BT_MOTOR_EXT_BE = 0x00, /* Best Effort. Default. for HCRP, PAN, SDP, RFCOMM-based profiles like FTP, OPP, SPP, DUN, etc. */ - BT_MOTOR_EXT_GUL = 0x01, /* Guaranteed Latency. This type of traffic is used e.g. for HID and AVRCP. */ - BT_MOTOR_EXT_GUB = 0X02, /* Guaranteed Bandwidth. */ - BT_MOTOR_EXT_GULB = 0X03 /* Guaranteed Latency and Bandwidth. for A2DP and VDP. */ -}; - -enum bt_traffic_mode_profile { - BT_PROFILE_NONE, - BT_PROFILE_A2DP, - BT_PROFILE_PAN, - BT_PROFILE_HID, - BT_PROFILE_SCO -}; - -enum bt_link_role { - BT_LINK_MASTER = 0, - BT_LINK_SLAVE = 1 -}; - -enum bt_state_wpa_auth { - STATE_WPA_AUTH_UNINITIALIZED, - STATE_WPA_AUTH_WAIT_PACKET_1, /* Join */ - STATE_WPA_AUTH_WAIT_PACKET_2, /* Creat */ - STATE_WPA_AUTH_WAIT_PACKET_3, - STATE_WPA_AUTH_WAIT_PACKET_4, - STATE_WPA_AUTH_SUCCESSED -}; - -#define BT_WPA_AUTH_TIMEOUT_PERIOD 1000 -#define BTMaxWPAAuthReTransmitCoun 5 - -#define MAX_AMP_ASSOC_FRAG_LEN 248 -#define TOTAL_ALLOCIATE_ASSOC_LEN 1000 - -struct hci_flow_spec { - u8 Identifier; - u8 ServiceType; - u16 MaximumSDUSize; - u32 SDUInterArrivalTime; - u32 AccessLatency; - u32 FlushTimeout; -}; - -struct hci_log_link_cmd_data { - u8 BtPhyLinkhandle; - u16 BtLogLinkhandle; - u8 BtTxFlowSpecID; - struct hci_flow_spec Tx_Flow_Spec; - struct hci_flow_spec Rx_Flow_Spec; - u32 TxPacketCount; - u32 BestEffortFlushTimeout; - - u8 bLLCompleteEventIsSet; - - u8 bLLCancelCMDIsSetandComplete; -}; - -struct hci_phy_link_cmd_data { - /* Physical_Link_Handle */ - u8 BtPhyLinkhandle; - - u16 LinkSuperversionTimeout; - - /* u16 SuperTimeOutCnt; */ - - /* Dedicated_AMP_Key_Length */ - u8 BtAMPKeyLen; - /* Dedicated_AMP_Key_Type */ - u8 BtAMPKeyType; - /* Dedicated_AMP_Key */ - u8 BtAMPKey[PMK_LEN]; -}; - -struct amp_assoc_structure { - /* TYPE ID */ - u8 TypeID; - /* Length */ - u16 Length; - /* Value */ - u8 Data[1]; -}; - -struct amp_pref_chnl_regulatory { - u8 reXId; - u8 regulatoryClass; - u8 coverageClass; -}; - -struct amp_assoc_cmd_data { - /* Physical_Link_Handle */ - u8 BtPhyLinkhandle; - /* Length_So_Far */ - u16 LenSoFar; - - u16 MaxRemoteASSOCLen; - /* AMP_ASSOC_Remaining_Length */ - u16 AMPAssocRemLen; - /* AMP_ASSOC_fragment */ - void *AMPAssocfragment; -}; - -struct hci_link_info { - u16 ConnectHandle; - u8 IncomingTrafficMode; - u8 OutgoingTrafficMode; - u8 BTProfile; - u8 BTCoreSpec; - s8 BT_RSSI; - u8 TrafficProfile; - u8 linkRole; -}; - -struct hci_ext_config { - struct hci_link_info linkInfo[MAX_BT_ASOC_ENTRY_NUM]; - u8 btOperationCode; - u16 CurrentConnectHandle; - u8 CurrentIncomingTrafficMode; - u8 CurrentOutgoingTrafficMode; - s8 MIN_BT_RSSI; - u8 NumberOfHandle; - u8 NumberOfSCO; - u8 CurrentBTStatus; - u16 HCIExtensionVer; - - /* Bt coexist related */ - u8 btProfileCase; - u8 btProfileAction; - u8 bManualControl; - u8 bBTBusy; - u8 bBTA2DPBusy; - u8 bEnableWifiScanNotify; - - u8 bHoldForBtOperation; - u32 bHoldPeriodCnt; -}; - -struct hci_acl_packet_data { - u16 ACLDataPacketLen; - u8 SyncDataPacketLen; - u16 TotalNumACLDataPackets; - u16 TotalSyncNumDataPackets; -}; - -struct hci_phy_link_bss_info { - u16 bdCap; /* capability information */ -}; - -struct packet_irp_hcicmd_data { - u16 OCF:10; - u16 OGF:6; - u8 Length; - u8 Data[20]; -}; - -struct bt_asoc_entry { - u8 bUsed; - u8 mAssoc; - u8 b4waySuccess; - u8 Bssid[6]; - struct hci_phy_link_cmd_data PhyLinkCmdData; - - struct hci_log_link_cmd_data LogLinkCmdData[MAX_LOGICAL_LINK_NUM]; - - struct hci_acl_packet_data ACLPacketsData; - - struct amp_assoc_cmd_data AmpAsocCmdData; - struct octet_string BTSsid; - u8 BTSsidBuf[33]; - - enum hci_status PhyLinkDisconnectReason; - - u8 bSendSupervisionPacket; - /* u8 CurrentSuervisionPacketSendNum; */ - /* u8 LastSuervisionPacketSendNum; */ - u32 NoRxPktCnt; - /* Is Creator or Joiner */ - enum amp_btap_type AMPRole; - - /* BT current state */ - u8 BtCurrentState; - /* BT next state */ - u8 BtNextState; - - u8 bNeedPhysLinkCompleteEvent; - - enum hci_status PhysLinkCompleteStatus; - - u8 BTRemoteMACAddr[6]; - - u32 BTCapability; - - u8 SyncDataPacketLen; - - u16 TotalSyncNumDataPackets; - u16 TotalNumACLDataPackets; - - u8 ShortRangeMode; - - u8 PTK[PTK_LEN_TKIP]; - u8 GTK[GTK_LEN]; - u8 ANonce[KEY_NONCE_LEN]; - u8 SNonce[KEY_NONCE_LEN]; - u64 KeyReplayCounter; - u8 WPAAuthReplayCount; - u8 AESKeyBuf[AESCCMP_BLK_SIZE_TOTAL]; - u8 PMK[PMK_LEN]; - enum bt_state_wpa_auth BTWPAAuthState; - s32 UndecoratedSmoothedPWDB; - - /* Add for HW security !! */ - u8 HwCAMIndex; /* Cam index */ - u8 bPeerQosSta; - - u32 rxSuvpPktCnt; -}; - -struct bt_traffic_statistics { - u8 bTxBusyTraffic; - u8 bRxBusyTraffic; - u8 bIdle; - u32 TxPktCntInPeriod; - u32 RxPktCntInPeriod; - u64 TxPktLenInPeriod; - u64 RxPktLenInPeriod; -}; - -struct bt_mgnt { - u8 bBTConnectInProgress; - u8 bLogLinkInProgress; - u8 bPhyLinkInProgress; - u8 bPhyLinkInProgressStartLL; - u8 BtCurrentPhyLinkhandle; - u16 BtCurrentLogLinkhandle; - u8 CurrentConnectEntryNum; - u8 DisconnectEntryNum; - u8 CurrentBTConnectionCnt; - enum bt_connect_type BTCurrentConnectType; - enum bt_connect_type BTReceiveConnectPkt; - u8 BTAuthCount; - u8 BTAsocCount; - u8 bStartSendSupervisionPkt; - u8 BtOperationOn; - u8 BTNeedAMPStatusChg; - u8 JoinerNeedSendAuth; - struct hci_phy_link_bss_info bssDesc; - struct hci_ext_config ExtConfig; - u8 bNeedNotifyAMPNoCap; - u8 bCreateSpportQos; - u8 bSupportProfile; - u8 BTChannel; - u8 CheckChnlIsSuit; - u8 bBtScan; - u8 btLogoTest; -}; - -struct bt_hci_dgb_info { - u32 hciCmdCnt; - u32 hciCmdCntUnknown; - u32 hciCmdCntCreatePhyLink; - u32 hciCmdCntAcceptPhyLink; - u32 hciCmdCntDisconnectPhyLink; - u32 hciCmdPhyLinkStatus; - u32 hciCmdCntCreateLogLink; - u32 hciCmdCntAcceptLogLink; - u32 hciCmdCntDisconnectLogLink; - u32 hciCmdCntReadLocalAmpAssoc; - u32 hciCmdCntWriteRemoteAmpAssoc; - u32 hciCmdCntSetAclLinkStatus; - u32 hciCmdCntSetScoLinkStatus; - u32 hciCmdCntExtensionVersionNotify; - u32 hciCmdCntLinkStatusNotify; -}; - -struct bt_irp_dgb_info { - u32 irpMJCreate; - /* Io Control */ - u32 irpIoControl; - u32 irpIoCtrlHciCmd; - u32 irpIoCtrlHciEvent; - u32 irpIoCtrlHciTxData; - u32 irpIoCtrlHciRxData; - u32 irpIoCtrlUnknown; - - u32 irpIoCtrlHciTxData1s; -}; - -struct bt_packet_dgb_info { - u32 btPktTxProbReq; - u32 btPktRxProbReq; - u32 btPktRxProbReqFail; - u32 btPktTxProbRsp; - u32 btPktRxProbRsp; - u32 btPktTxAuth; - u32 btPktRxAuth; - u32 btPktRxAuthButDrop; - u32 btPktTxAssocReq; - u32 btPktRxAssocReq; - u32 btPktRxAssocReqButDrop; - u32 btPktTxAssocRsp; - u32 btPktRxAssocRsp; - u32 btPktTxDisassoc; - u32 btPktRxDisassoc; - u32 btPktRxDeauth; - u32 btPktTx4way1st; - u32 btPktRx4way1st; - u32 btPktTx4way2nd; - u32 btPktRx4way2nd; - u32 btPktTx4way3rd; - u32 btPktRx4way3rd; - u32 btPktTx4way4th; - u32 btPktRx4way4th; - u32 btPktTxLinkSuperReq; - u32 btPktRxLinkSuperReq; - u32 btPktTxLinkSuperRsp; - u32 btPktRxLinkSuperRsp; - u32 btPktTxData; - u32 btPktRxData; -}; - -struct bt_dgb { - u8 dbgCtrl; - u32 dbgProfile; - struct bt_hci_dgb_info dbgHciInfo; - struct bt_irp_dgb_info dbgIrpInfo; - struct bt_packet_dgb_info dbgBtPkt; -}; - -struct bt_hci_info { - /* 802.11 Pal version specifier */ - u8 BTPalVersion; - u16 BTPalCompanyID; - u16 BTPalsubversion; - - /* Connected channel list */ - u16 BTConnectChnlListLen; - u8 BTConnectChnllist[64]; - - /* Fail contact counter */ - u16 FailContactCount; - - /* Event mask */ - u64 BTEventMask; - u64 BTEventMaskPage2; - - /* timeout var */ - u16 ConnAcceptTimeout; - u16 LogicalAcceptTimeout; - u16 PageTimeout; - - u8 LocationDomainAware; - u16 LocationDomain; - u8 LocationDomainOptions; - u8 LocationOptions; - - u8 FlowControlMode; - - /* Preferred channel list */ - u16 BtPreChnlListLen; - u8 BTPreChnllist[64]; - - u16 enFlush_LLH; /* enhanced flush handle */ - u16 FLTO_LLH; /* enhanced flush handle */ - - /* */ - /* Test command only. */ - u8 bInTestMode; - u8 bTestIsEnd; - u8 bTestNeedReport; - u8 TestScenario; - u8 TestReportInterval; - u8 TestCtrType; - u32 TestEventType; - u16 TestNumOfFrame; - u16 TestNumOfErrFrame; - u16 TestNumOfBits; - u16 TestNumOfErrBits; - /* */ -}; - -struct bt_traffic { - /* Add for check replay data */ - u8 LastRxUniFragNum; - u16 LastRxUniSeqNum; - - /* s32 EntryMaxUndecoratedSmoothedPWDB; */ - /* s32 EntryMinUndecoratedSmoothedPWDB; */ - - struct bt_traffic_statistics Bt30TrafficStatistics; -}; - -#define RT_WORK_ITEM struct work_struct - -struct bt_security { - /* WPA auth state - * May need to remove to BTSecInfo ... - * enum bt_state_wpa_auth BTWPAAuthState; - */ - struct octet_string RSNIE; - u8 RSNIEBuf[MAXRSNIELEN]; - u8 bRegNoEncrypt; - u8 bUsedHwEncrypt; -}; - -struct bt_30info { - struct rtw_adapter *padapter; - struct bt_asoc_entry BtAsocEntry[MAX_BT_ASOC_ENTRY_NUM]; - struct bt_mgnt BtMgnt; - struct bt_dgb BtDbg; - struct bt_hci_info BtHciInfo; - struct bt_traffic BtTraffic; - struct bt_security BtSec; - RT_WORK_ITEM HCICmdWorkItem; - struct timer_list BTHCICmdTimer; - RT_WORK_ITEM BTPsDisableWorkItem; - RT_WORK_ITEM BTConnectWorkItem; - struct timer_list BTHCIDiscardAclDataTimer; - struct timer_list BTHCIJoinTimeoutTimer; - struct timer_list BTTestSendPacketTimer; - struct timer_list BTDisconnectPhyLinkTimer; - struct timer_list BTBeaconTimer; - u8 BTBeaconTmrOn; - - struct timer_list BTPsDisableTimer; - - void * pBtChnlList; -}; - -struct packet_irp_acl_data { - u16 Handle:12; - u16 PB_Flag:2; - u16 BC_Flag:2; - u16 Length; - u8 Data[1]; -}; - -struct packet_irp_hcievent_data { - u8 EventCode; - u8 Length; - u8 Data[20]; -}; - -struct common_triple { - u8 byte_1st; - u8 byte_2nd; - u8 byte_3rd; -}; - -#define COUNTRY_STR_LEN 3 /* country string len = 3 */ - -#define LOCAL_PMK 0 - -enum hci_wifi_connect_status { - HCI_WIFI_NOT_CONNECTED = 0x0, - HCI_WIFI_CONNECTED = 0x1, - HCI_WIFI_CONNECT_IN_PROGRESS = 0x2, -}; - -enum hci_ext_bp_operation { - HCI_BT_OP_NONE = 0x0, - HCI_BT_OP_INQUIRY_START = 0x1, - HCI_BT_OP_INQUIRY_FINISH = 0x2, - HCI_BT_OP_PAGING_START = 0x3, - HCI_BT_OP_PAGING_SUCCESS = 0x4, - HCI_BT_OP_PAGING_UNSUCCESS = 0x5, - HCI_BT_OP_PAIRING_START = 0x6, - HCI_BT_OP_PAIRING_FINISH = 0x7, - HCI_BT_OP_BT_DEV_ENABLE = 0x8, - HCI_BT_OP_BT_DEV_DISABLE = 0x9, - HCI_BT_OP_MAX -}; - -#define BTHCI_SM_WITH_INFO(_Adapter, _StateToEnter, _StateCmd, _EntryNum) \ -{ \ - RTPRINT(FIOCTL, IOCTL_STATE, ("[BT state change] caused by ""%s"", line =%d\n", __func__, __LINE__)); \ - BTHCI_StateMachine(_Adapter, _StateToEnter, _StateCmd, _EntryNum);\ -} - -void BTHCI_EventParse(struct rtw_adapter *padapter, void *pEvntData, - u32 dataLen); -#define BT_EventParse BTHCI_EventParse -u8 BTHCI_HsConnectionEstablished(struct rtw_adapter *padapter); -void BTHCI_UpdateBTProfileRTKToMoto(struct rtw_adapter *padapter); -void BTHCI_WifiScanNotify(struct rtw_adapter *padapter, u8 scanType); -void BTHCI_StateMachine(struct rtw_adapter *padapter, u8 StateToEnter, - enum hci_state_with_cmd StateCmd, u8 EntryNum); -void BTHCI_DisconnectPeer(struct rtw_adapter *padapter, u8 EntryNum); -void BTHCI_EventNumOfCompletedDataBlocks(struct rtw_adapter *padapter); -void BTHCI_EventAMPStatusChange(struct rtw_adapter *padapter, u8 AMP_Status); -void BTHCI_DisconnectAll(struct rtw_adapter *padapter); -enum hci_status BTHCI_HandleHCICMD(struct rtw_adapter *padapter, - struct packet_irp_hcicmd_data *pHciCmd); - -/* ===== End of sync from SD7 driver COMMON/bt_hci.h ===== */ - -/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtc87231Ant.h ===== */ -#define GET_BT_INFO(padapter) (&GET_HAL_DATA(padapter)->BtInfo) - -#define BTC_FOR_SCAN_START 1 -#define BTC_FOR_SCAN_FINISH 0 - -#define BT_TXRX_CNT_THRES_1 1200 -#define BT_TXRX_CNT_THRES_2 1400 -#define BT_TXRX_CNT_THRES_3 3000 -#define BT_TXRX_CNT_LEVEL_0 0 /* < 1200 */ -#define BT_TXRX_CNT_LEVEL_1 1 /* >= 1200 && < 1400 */ -#define BT_TXRX_CNT_LEVEL_2 2 /* >= 1400 */ -#define BT_TXRX_CNT_LEVEL_3 3 /* >= 3000 */ - -enum bt_state_1ant { - BT_INFO_STATE_DISABLED = 0, - BT_INFO_STATE_NO_CONNECTION = 1, - BT_INFO_STATE_CONNECT_IDLE = 2, - BT_INFO_STATE_INQ_OR_PAG = 3, - BT_INFO_STATE_ACL_ONLY_BUSY = 4, - BT_INFO_STATE_SCO_ONLY_BUSY = 5, - BT_INFO_STATE_ACL_SCO_BUSY = 6, - BT_INFO_STATE_ACL_INQ_OR_PAG = 7, - BT_INFO_STATE_MAX = 8 -}; - -struct btdm_8723a_1ant { - u8 prePsTdma; - u8 curPsTdma; - u8 psTdmaDuAdjType; - u8 bPrePsTdmaOn; - u8 bCurPsTdmaOn; - u8 preWifiPara; - u8 curWifiPara; - u8 preCoexWifiCon; - u8 curCoexWifiCon; - u8 wifiRssiThresh; - - u32 psTdmaMonitorCnt; - u32 psTdmaGlobalCnt; - - /* DurationAdjust For SCO */ - u32 psTdmaMonitorCntForSCO; - u8 psTdmaDuAdjTypeForSCO; - u8 RSSI_WiFi_Last; - u8 RSSI_BT_Last; - - u8 bWiFiHalt; - u8 bRAChanged; -}; - -void BTDM_1AntSignalCompensation(struct rtw_adapter *padapter, - u8 *rssi_wifi, u8 *rssi_bt); -void BTDM_1AntForDhcp(struct rtw_adapter *padapter); -void BTDM_1AntBtCoexist8723A(struct rtw_adapter *padapter); - -/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtc87231Ant.h ===== */ - -/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtc87232Ant.h ===== */ -enum bt_2ant_bt_status { - BT_2ANT_BT_STATUS_IDLE = 0x0, - BT_2ANT_BT_STATUS_CONNECTED_IDLE = 0x1, - BT_2ANT_BT_STATUS_NON_IDLE = 0x2, - BT_2ANT_BT_STATUS_MAX -}; - -enum bt_2ant_coex_algo { - BT_2ANT_COEX_ALGO_UNDEFINED = 0x0, - BT_2ANT_COEX_ALGO_SCO = 0x1, - BT_2ANT_COEX_ALGO_HID = 0x2, - BT_2ANT_COEX_ALGO_A2DP = 0x3, - BT_2ANT_COEX_ALGO_PANEDR = 0x4, - BT_2ANT_COEX_ALGO_PANHS = 0x5, - BT_2ANT_COEX_ALGO_PANEDR_A2DP = 0x6, - BT_2ANT_COEX_ALGO_PANEDR_HID = 0x7, - BT_2ANT_COEX_ALGO_HID_A2DP_PANEDR = 0x8, - BT_2ANT_COEX_ALGO_HID_A2DP = 0x9, - BT_2ANT_COEX_ALGO_HID_A2DP_PANHS = 0xA, - BT_2ANT_COEX_ALGO_MAX = 0xB, -}; - -struct btdm_8723a_2ant { - u8 bPreDecBtPwr; - u8 bCurDecBtPwr; - - u8 preWlanActHi; - u8 curWlanActHi; - u8 preWlanActLo; - u8 curWlanActLo; - - u8 preFwDacSwingLvl; - u8 curFwDacSwingLvl; - - u8 bPreRfRxLpfShrink; - u8 bCurRfRxLpfShrink; - - u8 bPreLowPenaltyRa; - u8 bCurLowPenaltyRa; - - u8 preBtRetryIndex; - u8 curBtRetryIndex; - - u8 bPreDacSwingOn; - u32 preDacSwingLvl; - u8 bCurDacSwingOn; - u32 curDacSwingLvl; - - u8 bPreAdcBackOff; - u8 bCurAdcBackOff; - - u8 bPreAgcTableEn; - u8 bCurAgcTableEn; - - u32 preVal0x6c0; - u32 curVal0x6c0; - u32 preVal0x6c8; - u32 curVal0x6c8; - u8 preVal0x6cc; - u8 curVal0x6cc; - - u8 bCurIgnoreWlanAct; - u8 bPreIgnoreWlanAct; - - u8 prePsTdma; - u8 curPsTdma; - u8 psTdmaDuAdjType; - u8 bPrePsTdmaOn; - u8 bCurPsTdmaOn; - - u8 preAlgorithm; - u8 curAlgorithm; - u8 bResetTdmaAdjust; - - u8 btStatus; -}; - -void BTDM_2AntBtCoexist8723A(struct rtw_adapter *padapter); -/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtc87232Ant.h ===== */ - -/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtc8723.h ===== */ - -#define BT_Q_PKT_OFF 0 -#define BT_Q_PKT_ON 1 - -#define BT_TX_PWR_OFF 0 -#define BT_TX_PWR_ON 1 - -/* TDMA mode definition */ -#define TDMA_2ANT 0 -#define TDMA_1ANT 1 -#define TDMA_NAV_OFF 0 -#define TDMA_NAV_ON 1 -#define TDMA_DAC_SWING_OFF 0 -#define TDMA_DAC_SWING_ON 1 - -#define BT_RSSI_LEVEL_H 0 -#define BT_RSSI_LEVEL_M 1 -#define BT_RSSI_LEVEL_L 2 - -/* PTA mode related definition */ -#define BT_PTA_MODE_OFF 0 -#define BT_PTA_MODE_ON 1 - -/* Penalty Tx Rate Adaptive */ -#define BT_TX_RATE_ADAPTIVE_NORMAL 0 -#define BT_TX_RATE_ADAPTIVE_LOW_PENALTY 1 - -/* RF Corner */ -#define BT_RF_RX_LPF_CORNER_RESUME 0 -#define BT_RF_RX_LPF_CORNER_SHRINK 1 - -#define BT_INFO_ACL BIT(0) -#define BT_INFO_SCO BIT(1) -#define BT_INFO_INQ_PAG BIT(2) -#define BT_INFO_ACL_BUSY BIT(3) -#define BT_INFO_SCO_BUSY BIT(4) -#define BT_INFO_HID BIT(5) -#define BT_INFO_A2DP BIT(6) -#define BT_INFO_FTP BIT(7) - - - -struct bt_coexist_8723a { - u32 highPriorityTx; - u32 highPriorityRx; - u32 lowPriorityTx; - u32 lowPriorityRx; - u8 btRssi; - u8 TotalAntNum; - u8 bC2hBtInfoSupport; - u8 c2hBtInfo; - u8 c2hBtInfoOriginal; - u8 prec2hBtInfo; /* for 1Ant */ - u8 bC2hBtInquiryPage; - unsigned long btInqPageStartTime; /* for 2Ant */ - u8 c2hBtProfile; /* for 1Ant */ - u8 btRetryCnt; - u8 btInfoExt; - u8 bC2hBtInfoReqSent; - u8 bForceFwBtInfo; - u8 bForceA2dpSink; - struct btdm_8723a_2ant btdm2Ant; - struct btdm_8723a_1ant btdm1Ant; -}; - -void BTDM_SetFwChnlInfo(struct rtw_adapter *padapter, - enum rt_media_status mstatus); -u8 BTDM_IsWifiConnectionExist(struct rtw_adapter *padapter); -void BTDM_SetFw3a(struct rtw_adapter *padapter, u8 byte1, u8 byte2, u8 byte3, - u8 byte4, u8 byte5); -void BTDM_QueryBtInformation(struct rtw_adapter *padapter); -void BTDM_SetSwRfRxLpfCorner(struct rtw_adapter *padapter, u8 type); -void BTDM_SetSwPenaltyTxRateAdaptive(struct rtw_adapter *padapter, u8 raType); -void BTDM_SetFwDecBtPwr(struct rtw_adapter *padapter, u8 bDecBtPwr); -u8 BTDM_BtProfileSupport(struct rtw_adapter *padapter); -void BTDM_LpsLeave(struct rtw_adapter *padapter); - -/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtc8723.h ===== */ - -/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtcCsr1Ant.h ===== */ - -enum BT_A2DP_INDEX{ - BT_A2DP_INDEX0 = 0, /* 32, 12; the most critical for BT */ - BT_A2DP_INDEX1, /* 12, 24 */ - BT_A2DP_INDEX2, /* 0, 0 */ - BT_A2DP_INDEX_MAX -}; - -#define BT_A2DP_STATE_NOT_ENTERED 0 -#define BT_A2DP_STATE_DETECTING 1 -#define BT_A2DP_STATE_DETECTED 2 - -#define BTDM_ANT_BT_IDLE 0 -#define BTDM_ANT_WIFI 1 -#define BTDM_ANT_BT 2 - - -void BTDM_SingleAnt(struct rtw_adapter *padapter, u8 bSingleAntOn, - u8 bInterruptOn, u8 bMultiNAVOn); -void BTDM_CheckBTIdleChange1Ant(struct rtw_adapter *padapter); - -/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtcCsr1Ant.h ===== */ - -/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtcCsr2Ant.h ===== */ - -/* */ -/* For old core stack before v251 */ -/* */ -#define BT_RSSI_STATE_NORMAL_POWER BIT(0) -#define BT_RSSI_STATE_AMDPU_OFF BIT(1) -#define BT_RSSI_STATE_SPECIAL_LOW BIT(2) -#define BT_RSSI_STATE_BG_EDCA_LOW BIT(3) -#define BT_RSSI_STATE_TXPOWER_LOW BIT(4) - -#define BT_DACSWING_OFF 0 -#define BT_DACSWING_M4 1 -#define BT_DACSWING_M7 2 -#define BT_DACSWING_M10 3 - -void BTDM_DiminishWiFi(struct rtw_adapter *Adapter, u8 bDACOn, u8 bInterruptOn, - u8 DACSwingLevel, u8 bNAVOn); - -/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtcCsr2Ant.h ===== */ - -/* HEADER/TypeDef.h */ -#define MAX_FW_SUPPORT_MACID_NUM 64 - -/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtCoexist.h ===== */ - -#define FW_VER_BT_REG 62 -#define FW_VER_BT_REG1 74 -#define REG_BT_ACTIVE 0x444 -#define REG_BT_STATE 0x448 -#define REG_BT_POLLING1 0x44c -#define REG_BT_POLLING 0x700 - -#define REG_BT_ACTIVE_OLD 0x488 -#define REG_BT_STATE_OLD 0x48c -#define REG_BT_POLLING_OLD 0x490 - -/* The reg define is for 8723 */ -#define REG_HIGH_PRIORITY_TXRX 0x770 -#define REG_LOW_PRIORITY_TXRX 0x774 - -#define BT_FW_COEX_THRESH_TOL 6 -#define BT_FW_COEX_THRESH_20 20 -#define BT_FW_COEX_THRESH_23 23 -#define BT_FW_COEX_THRESH_25 25 -#define BT_FW_COEX_THRESH_30 30 -#define BT_FW_COEX_THRESH_35 35 -#define BT_FW_COEX_THRESH_40 40 -#define BT_FW_COEX_THRESH_45 45 -#define BT_FW_COEX_THRESH_47 47 -#define BT_FW_COEX_THRESH_50 50 -#define BT_FW_COEX_THRESH_55 55 -#define BT_FW_COEX_THRESH_65 65 - -#define BT_COEX_STATE_BT30 BIT(0) -#define BT_COEX_STATE_WIFI_HT20 BIT(1) -#define BT_COEX_STATE_WIFI_HT40 BIT(2) -#define BT_COEX_STATE_WIFI_LEGACY BIT(3) - -#define BT_COEX_STATE_WIFI_RSSI_LOW BIT(4) -#define BT_COEX_STATE_WIFI_RSSI_MEDIUM BIT(5) -#define BT_COEX_STATE_WIFI_RSSI_HIGH BIT(6) -#define BT_COEX_STATE_DEC_BT_POWER BIT(7) - -#define BT_COEX_STATE_WIFI_IDLE BIT(8) -#define BT_COEX_STATE_WIFI_UPLINK BIT(9) -#define BT_COEX_STATE_WIFI_DOWNLINK BIT(10) - -#define BT_COEX_STATE_BT_INQ_PAGE BIT(11) -#define BT_COEX_STATE_BT_IDLE BIT(12) -#define BT_COEX_STATE_BT_UPLINK BIT(13) -#define BT_COEX_STATE_BT_DOWNLINK BIT(14) -/* */ -/* Todo: Remove these definitions */ -#define BT_COEX_STATE_BT_PAN_IDLE BIT(15) -#define BT_COEX_STATE_BT_PAN_UPLINK BIT(16) -#define BT_COEX_STATE_BT_PAN_DOWNLINK BIT(17) -#define BT_COEX_STATE_BT_A2DP_IDLE BIT(18) -/* */ -#define BT_COEX_STATE_BT_RSSI_LOW BIT(19) - -#define BT_COEX_STATE_PROFILE_HID BIT(20) -#define BT_COEX_STATE_PROFILE_A2DP BIT(21) -#define BT_COEX_STATE_PROFILE_PAN BIT(22) -#define BT_COEX_STATE_PROFILE_SCO BIT(23) - -#define BT_COEX_STATE_WIFI_RSSI_1_LOW BIT(24) -#define BT_COEX_STATE_WIFI_RSSI_1_MEDIUM BIT(25) -#define BT_COEX_STATE_WIFI_RSSI_1_HIGH BIT(26) - -#define BT_COEX_STATE_WIFI_RSSI_BEACON_LOW BIT(27) -#define BT_COEX_STATE_WIFI_RSSI_BEACON_MEDIUM BIT(28) -#define BT_COEX_STATE_WIFI_RSSI_BEACON_HIGH BIT(29) - - -#define BT_COEX_STATE_BTINFO_COMMON BIT(30) -#define BT_COEX_STATE_BTINFO_B_HID_SCOESCO BIT(31) -#define BT_COEX_STATE_BTINFO_B_FTP_A2DP BIT(32) - -#define BT_COEX_STATE_BT_CNT_LEVEL_0 BIT(33) -#define BT_COEX_STATE_BT_CNT_LEVEL_1 BIT(34) -#define BT_COEX_STATE_BT_CNT_LEVEL_2 BIT(35) -#define BT_COEX_STATE_BT_CNT_LEVEL_3 BIT(36) - -#define BT_RSSI_STATE_HIGH 0 -#define BT_RSSI_STATE_MEDIUM 1 -#define BT_RSSI_STATE_LOW 2 -#define BT_RSSI_STATE_STAY_HIGH 3 -#define BT_RSSI_STATE_STAY_MEDIUM 4 -#define BT_RSSI_STATE_STAY_LOW 5 - -#define BT_AGCTABLE_OFF 0 -#define BT_AGCTABLE_ON 1 - -#define BT_BB_BACKOFF_OFF 0 -#define BT_BB_BACKOFF_ON 1 - -#define BT_FW_NAV_OFF 0 -#define BT_FW_NAV_ON 1 - -#define BT_COEX_MECH_NONE 0 -#define BT_COEX_MECH_SCO 1 -#define BT_COEX_MECH_HID 2 -#define BT_COEX_MECH_A2DP 3 -#define BT_COEX_MECH_PAN 4 -#define BT_COEX_MECH_HID_A2DP 5 -#define BT_COEX_MECH_HID_PAN 6 -#define BT_COEX_MECH_PAN_A2DP 7 -#define BT_COEX_MECH_HID_SCO_ESCO 8 -#define BT_COEX_MECH_FTP_A2DP 9 -#define BT_COEX_MECH_COMMON 10 -#define BT_COEX_MECH_MAX 11 -/* BT Dbg Ctrl */ -#define BT_DBG_PROFILE_NONE 0 -#define BT_DBG_PROFILE_SCO 1 -#define BT_DBG_PROFILE_HID 2 -#define BT_DBG_PROFILE_A2DP 3 -#define BT_DBG_PROFILE_PAN 4 -#define BT_DBG_PROFILE_HID_A2DP 5 -#define BT_DBG_PROFILE_HID_PAN 6 -#define BT_DBG_PROFILE_PAN_A2DP 7 -#define BT_DBG_PROFILE_MAX 9 - -struct bt_coexist_str { - u8 BluetoothCoexist; - u8 BT_Ant_Num; - u8 BT_CoexistType; - u8 BT_Ant_isolation; /* 0:good, 1:bad */ - u8 bt_radiosharedtype; - u32 Ratio_Tx; - u32 Ratio_PRI; - u8 bInitlized; - u32 BtRfRegOrigin1E; - u32 BtRfRegOrigin1F; - u8 bBTBusyTraffic; - u8 bBTTrafficModeSet; - u8 bBTNonTrafficModeSet; - struct bt_traffic_statistics BT21TrafficStatistics; - u64 CurrentState; - u64 PreviousState; - u8 preRssiState; - u8 preRssiState1; - u8 preRssiStateBeacon; - u8 bFWCoexistAllOff; - u8 bSWCoexistAllOff; - u8 bHWCoexistAllOff; - u8 bBalanceOn; - u8 bSingleAntOn; - u8 bInterruptOn; - u8 bMultiNAVOn; - u8 PreWLANActH; - u8 PreWLANActL; - u8 WLANActH; - u8 WLANActL; - u8 A2DPState; - u8 AntennaState; - u32 lastBtEdca; - u16 last_aggr_num; - u8 bEDCAInitialized; - u8 exec_cnt; - u8 b8723aAgcTableOn; - u8 b92DAgcTableOn; - struct bt_coexist_8723a halCoex8723; - u8 btActiveZeroCnt; - u8 bCurBtDisabled; - u8 bPreBtDisabled; - u8 bNeedToRoamForBtDisableEnable; - u8 fw3aVal[5]; -}; - -void BTDM_CheckAntSelMode(struct rtw_adapter *padapter); -void BTDM_FwC2hBtRssi(struct rtw_adapter *padapter, u8 *tmpBuf); -#define BT_FwC2hBtRssi BTDM_FwC2hBtRssi -void BTDM_DisplayBtCoexInfo(struct rtw_adapter *padapter); -#define BT_DisplayBtCoexInfo BTDM_DisplayBtCoexInfo -void BTDM_RejectAPAggregatedPacket(struct rtw_adapter *padapter, u8 bReject); -u8 BTDM_IsHT40(struct rtw_adapter *padapter); -u8 BTDM_Legacy(struct rtw_adapter *padapter); -void BTDM_CheckWiFiState(struct rtw_adapter *padapter); -s32 BTDM_GetRxSS(struct rtw_adapter *padapter); -u8 BTDM_CheckCoexBcnRssiState(struct rtw_adapter *padapter, u8 levelNum, - u8 RssiThresh, u8 RssiThresh1); -u8 BTDM_CheckCoexRSSIState1(struct rtw_adapter *padapter, u8 levelNum, - u8 RssiThresh, u8 RssiThresh1); -u8 BTDM_CheckCoexRSSIState(struct rtw_adapter *padapter, u8 levelNum, - u8 RssiThresh, u8 RssiThresh1); -void BTDM_Balance(struct rtw_adapter *padapter, u8 bBalanceOn, u8 ms0, u8 ms1); -void BTDM_AGCTable(struct rtw_adapter *padapter, u8 type); -void BTDM_BBBackOffLevel(struct rtw_adapter *padapter, u8 type); -void BTDM_FWCoexAllOff(struct rtw_adapter *padapter); -void BTDM_SWCoexAllOff(struct rtw_adapter *padapter); -void BTDM_HWCoexAllOff(struct rtw_adapter *padapter); -void BTDM_CoexAllOff(struct rtw_adapter *padapter); -void BTDM_TurnOffBtCoexistBeforeEnterIPS(struct rtw_adapter *padapter); -void BTDM_SignalCompensation(struct rtw_adapter *padapter, u8 *rssi_wifi, - u8 *rssi_bt); -void BTDM_UpdateCoexState(struct rtw_adapter *padapter); -u8 BTDM_IsSameCoexistState(struct rtw_adapter *padapter); -void BTDM_PWDBMonitor(struct rtw_adapter *padapter); -u8 BTDM_IsBTBusy(struct rtw_adapter *padapter); -#define BT_IsBtBusy BTDM_IsBTBusy -u8 BTDM_IsWifiBusy(struct rtw_adapter *padapter); -u8 BTDM_IsCoexistStateChanged(struct rtw_adapter *padapter); -u8 BTDM_IsWifiUplink(struct rtw_adapter *padapter); -u8 BTDM_IsWifiDownlink(struct rtw_adapter *padapter); -u8 BTDM_IsBTHSMode(struct rtw_adapter *padapter); -u8 BTDM_IsBTUplink(struct rtw_adapter *padapter); -u8 BTDM_IsBTDownlink(struct rtw_adapter *padapter); -void BTDM_AdjustForBtOperation(struct rtw_adapter *padapter); -void BTDM_ForHalt(struct rtw_adapter *padapter); -void BTDM_WifiScanNotify(struct rtw_adapter *padapter, u8 scanType); -void BTDM_WifiAssociateNotify(struct rtw_adapter *padapter, u8 action); -void BTDM_MediaStatusNotify(struct rtw_adapter *padapter, - enum rt_media_status mstatus); -void BTDM_ForDhcp(struct rtw_adapter *padapter); -void BTDM_ResetActionProfileState(struct rtw_adapter *padapter); -void BTDM_SetBtCoexCurrAntNum(struct rtw_adapter *padapter, u8 antNum); -#define BT_SetBtCoexCurrAntNum BTDM_SetBtCoexCurrAntNum -u8 BTDM_IsActionSCO(struct rtw_adapter *padapter); -u8 BTDM_IsActionHID(struct rtw_adapter *padapter); -u8 BTDM_IsActionA2DP(struct rtw_adapter *padapter); -u8 BTDM_IsActionPAN(struct rtw_adapter *padapter); -u8 BTDM_IsActionHIDA2DP(struct rtw_adapter *padapter); -u8 BTDM_IsActionHIDPAN(struct rtw_adapter *padapter); -u8 BTDM_IsActionPANA2DP(struct rtw_adapter *padapter); -u32 BTDM_BtTxRxCounterH(struct rtw_adapter *padapter); -u32 BTDM_BtTxRxCounterL(struct rtw_adapter *padapter); - -/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtCoexist.h ===== */ - -/* ===== Below this line is sync from SD7 driver HAL/HalBT.h ===== */ - -#define RTS_CTS_NO_LEN_LIMIT 0 - -u8 HALBT_GetPGAntNum(struct rtw_adapter *padapter); -#define BT_GetPGAntNum HALBT_GetPGAntNum -void HALBT_SetKey(struct rtw_adapter *padapter, u8 EntryNum); -void HALBT_RemoveKey(struct rtw_adapter *padapter, u8 EntryNum); -u8 HALBT_IsBTExist(struct rtw_adapter *padapter); -#define BT_IsBtExist HALBT_IsBTExist -u8 HALBT_BTChipType(struct rtw_adapter *padapter); -void HALBT_SetRtsCtsNoLenLimit(struct rtw_adapter *padapter); - -/* ===== End of sync from SD7 driver HAL/HalBT.c ===== */ - -#define _bt_dbg_off_ 0 -#define _bt_dbg_on_ 1 - -extern u32 BTCoexDbgLevel; - - - -#endif /* __RTL8723A_BT_COEXIST_H__ */ diff --git a/drivers/staging/rtl8723au/include/rtl8723a_bt_intf.h b/drivers/staging/rtl8723au/include/rtl8723a_bt_intf.h deleted file mode 100644 index 4733559..0000000 --- a/drivers/staging/rtl8723au/include/rtl8723a_bt_intf.h +++ /dev/null @@ -1,69 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * Copyright(c) 2014, Jes Sorensen <Jes.Sorensen@redhat.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __RTL8723A_BT_INTF_H__ -#define __RTL8723A_BT_INTF_H__ - -#include <drv_types.h> - -#ifdef CONFIG_8723AU_BT_COEXIST -enum rt_media_status; -bool rtl8723a_BT_using_antenna_1(struct rtw_adapter *padapter); -bool rtl8723a_BT_enabled(struct rtw_adapter *padapter); -bool rtl8723a_BT_coexist(struct rtw_adapter *padapter); -void rtl8723a_BT_do_coexist(struct rtw_adapter *padapter); -void rtl8723a_BT_wifiscan_notify(struct rtw_adapter *padapter, u8 scanType); -void rtl8723a_BT_mediastatus_notify(struct rtw_adapter *padapter, - enum rt_media_status mstatus); -void rtl8723a_BT_specialpacket_notify(struct rtw_adapter *padapter); -void rtl8723a_BT_lps_leave(struct rtw_adapter *padapter); -void rtl8723a_BT_disable_coexist(struct rtw_adapter *padapter); -bool rtl8723a_BT_disable_EDCA_turbo(struct rtw_adapter *padapter); -void rtl8723a_dual_antenna_detection(struct rtw_adapter *padapter); -void rtl8723a_BT_init_hwconfig(struct rtw_adapter *padapter); -void rtl8723a_BT_wifiassociate_notify(struct rtw_adapter *padapter, u8 action); -void rtl8723a_BT_init_hal_vars(struct rtw_adapter *padapter); -void rtl8723a_fw_c2h_BT_info(struct rtw_adapter *padapter, u8 *tmpBuf, u8 length); -#else -static inline bool rtl8723a_BT_using_antenna_1(struct rtw_adapter *padapter) -{ - return false; -} -static inline bool rtl8723a_BT_enabled(struct rtw_adapter *padapter) -{ - return false; -} -static inline bool rtl8723a_BT_coexist(struct rtw_adapter *padapter) -{ - return false; -} -#define rtl8723a_BT_do_coexist(padapter) do {} while(0) -#define rtl8723a_BT_wifiscan_notify(padapter, scanType) do {} while(0) -#define rtl8723a_BT_mediastatus_notify(padapter, mstatus) do {} while(0) -#define rtl8723a_BT_specialpacket_notify(padapter) do {} while(0) -#define rtl8723a_BT_lps_leave(padapter) do {} while(0) -#define rtl8723a_BT_disable_coexist(padapter) do {} while(0) -static inline bool rtl8723a_BT_disable_EDCA_turbo(struct rtw_adapter *padapter) -{ - return false; -} -#define rtl8723a_dual_antenna_detection(padapter) do {} while(0) -#define rtl8723a_BT_init_hwconfig(padapter) do {} while(0) -#define rtl8723a_BT_wifiassociate_notify(padapter, action) do {} while(0) -#define rtl8723a_BT_init_hal_vars(padapter) do {} while(0) -#define rtl8723a_fw_c2h_BT_info(padapter, tmpBuf, length) do {} while(0) -#endif - -#endif diff --git a/drivers/staging/rtl8723au/include/rtl8723a_cmd.h b/drivers/staging/rtl8723au/include/rtl8723a_cmd.h deleted file mode 100644 index f95535a..0000000 --- a/drivers/staging/rtl8723au/include/rtl8723a_cmd.h +++ /dev/null @@ -1,158 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __RTL8723A_CMD_H__ -#define __RTL8723A_CMD_H__ - - -#define H2C_BT_FW_PATCH_LEN 3 -#define H2C_BT_PWR_FORCE_LEN 3 - -enum cmd_msg_element_id -{ - NONE_CMDMSG_EID, - AP_OFFLOAD_EID = 0, - SET_PWRMODE_EID = 1, - JOINBSS_RPT_EID = 2, - RSVD_PAGE_EID = 3, - RSSI_4_EID = 4, - RSSI_SETTING_EID = 5, - MACID_CONFIG_EID = 6, - MACID_PS_MODE_EID = 7, - P2P_PS_OFFLOAD_EID = 8, - SELECTIVE_SUSPEND_ROF_CMD = 9, - BT_QUEUE_PKT_EID = 17, - BT_ANT_TDMA_EID = 20, - BT_2ANT_HID_EID = 21, - P2P_PS_CTW_CMD_EID = 32, - FORCE_BT_TX_PWR_EID = 33, - SET_TDMA_WLAN_ACT_TIME_EID = 34, - SET_BT_TX_RETRY_INDEX_EID = 35, - HID_PROFILE_ENABLE_EID = 36, - BT_IGNORE_WLAN_ACT_EID = 37, - BT_PTA_MANAGER_UPDATE_ENABLE_EID = 38, - DAC_SWING_VALUE_EID = 41, - TRADITIONAL_TDMA_EN_EID = 51, - H2C_BT_FW_PATCH = 54, - B_TYPE_TDMA_EID = 58, - SCAN_EN_EID = 59, - LOWPWR_LPS_EID = 71, - H2C_RESET_TSF = 75, - MAX_CMDMSG_EID -}; - -struct cmd_msg_parm { - u8 eid; /* element id */ - u8 sz; /* sz */ - u8 buf[6]; -}; - -struct setpwrmode_parm { - u8 Mode; - u8 SmartPS; - u8 AwakeInterval; /* unit: beacon interval */ - u8 bAllQueueUAPSD; - -#define SETPM_LOWRXBCN BIT(0) -#define SETPM_AUTOANTSWITCH BIT(1) -#define SETPM_PSALLOWBTHIGHPRI BIT(2) - u8 BcnAntMode; -} __packed; - -struct H2C_SS_RFOFF_PARAM{ - u8 ROFOn; /* 1: on, 0:off */ - u16 gpio_period; /* unit: 1024 us */ -}__attribute__ ((packed)); - - -struct joinbssrpt_parm { - u8 OpMode; /* enum rt_media_status */ -}; - -struct rsvdpage_loc { - u8 LocProbeRsp; - u8 LocPsPoll; - u8 LocNullData; - u8 LocQosNull; - u8 LocBTQosNull; -}; - -struct P2P_PS_Offload_t { - u8 Offload_En:1; - u8 role:1; /* 1: Owner, 0: Client */ - u8 CTWindow_En:1; - u8 NoA0_En:1; - u8 NoA1_En:1; - u8 AllStaSleep:1; /* Only valid in Owner */ - u8 discovery:1; - u8 rsvd:1; -}; - -struct P2P_PS_CTWPeriod_t { - u8 CTWPeriod; /* TU */ -}; - -#define B_TDMA_EN BIT(0) -#define B_TDMA_FIXANTINBT BIT(1) -#define B_TDMA_TXPSPOLL BIT(2) -#define B_TDMA_VAL870 BIT(3) -#define B_TDMA_AUTOWAKEUP BIT(4) -#define B_TDMA_NOPS BIT(5) -#define B_TDMA_WLANHIGHPRI BIT(6) - -struct b_type_tdma_parm { - u8 option; - - u8 TBTTOnPeriod; - u8 MedPeriod; - u8 rsvd30; -} __packed; - -struct scan_en_parm { - u8 En; -} __packed; - -/* BT_PWR */ -#define SET_H2CCMD_BT_PWR_IDX(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE_8BIT(__pH2CCmd, 0, 8, __Value) - -/* BT_FW_PATCH */ -#define SET_H2CCMD_BT_FW_PATCH_ENABLE(__pH2CCmd, __Value) SET_BITS_TO_LE_4BYTE(__pH2CCmd, 0, 8, __Value) /* SET_BITS_TO_LE_1BYTE(__pH2CCmd, 0, 8, __Value) */ -#define SET_H2CCMD_BT_FW_PATCH_SIZE(__pH2CCmd, __Value) SET_BITS_TO_LE_4BYTE(__pH2CCmd, 8, 16, __Value) /* SET_BITS_TO_LE_2BYTE((__pH2CCmd)+1, 0, 16, __Value) */ - -struct lowpwr_lps_parm{ - u8 bcn_count:4; - u8 tb_bcn_threshold:3; - u8 enable:1; - u8 bcn_interval; - u8 drop_threshold; - u8 max_early_period; - u8 max_bcn_timeout_period; -} __packed; - - -/* host message to firmware cmd */ -void rtl8723a_set_FwPwrMode_cmd(struct rtw_adapter *padapter, u8 Mode); -void rtl8723a_set_FwJoinBssReport_cmd(struct rtw_adapter *padapter, u8 mstatus); -#ifdef CONFIG_8723AU_BT_COEXIST -void rtl8723a_set_BTCoex_AP_mode_FwRsvdPkt_cmd(struct rtw_adapter *padapter); -#else -#define rtl8723a_set_BTCoex_AP_mode_FwRsvdPkt_cmd(padapter) do {} while(0) -#endif -int rtl8723a_set_rssi_cmd(struct rtw_adapter *padapter, u32 param); -int rtl8723a_set_raid_cmd(struct rtw_adapter *padapter, u32 mask, u8 arg); -void rtl8723a_add_rateatid(struct rtw_adapter *padapter, u32 bitmap, u8 arg, u8 rssi_level); - -int FillH2CCmd(struct rtw_adapter *padapter, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer); - -#endif diff --git a/drivers/staging/rtl8723au/include/rtl8723a_dm.h b/drivers/staging/rtl8723au/include/rtl8723a_dm.h deleted file mode 100644 index bf236e8..0000000 --- a/drivers/staging/rtl8723au/include/rtl8723a_dm.h +++ /dev/null @@ -1,137 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __RTL8723A_DM_H__ -#define __RTL8723A_DM_H__ -/* */ -/* Description: */ -/* */ -/* This file is for 8723A dynamic mechanism only */ -/* */ -/* */ -/* */ -#define DYNAMIC_FUNC_BT BIT(0) - -enum{ - UP_LINK, - DOWN_LINK, -}; -/* */ -/* structure and define */ -/* */ - -/* duplicate code,will move to ODM ######### */ -#define IQK_MAC_REG_NUM 4 -#define IQK_ADDA_REG_NUM 16 -#define IQK_BB_REG_NUM 9 -#define HP_THERMAL_NUM 8 -/* duplicate code,will move to ODM ######### */ -struct dm_priv { - u32 InitODMFlag; - - /* Upper and Lower Signal threshold for Rate Adaptive*/ - int UndecoratedSmoothedPWDB; - int UndecoratedSmoothedCCK; - int EntryMinUndecoratedSmoothedPWDB; - int EntryMaxUndecoratedSmoothedPWDB; - int MinUndecoratedPWDBForDM; - int LastMinUndecoratedPWDBForDM; - - s32 UndecoratedSmoothedBeacon; - #ifdef CONFIG_8723AU_BT_COEXIST - s32 BT_EntryMinUndecoratedSmoothedPWDB; - s32 BT_EntryMaxUndecoratedSmoothedPWDB; - #endif - - /* for High Power */ - u8 DynamicTxHighPowerLvl;/* Add by Jacken Tx Power Control for Near/Far Range 2008/03/06 */ - - /* for tx power tracking */ - u8 bTXPowerTracking; - u8 TXPowercount; - u8 bTXPowerTrackingInit; - u8 TxPowerTrackControl; /* for mp mode, turn off txpwrtracking as default */ - u8 TM_Trigger; - - u8 ThermalMeter[2]; /* ThermalMeter, index 0 for RFIC0, and 1 for RFIC1 */ - u8 ThermalValue; - u8 ThermalValue_LCK; - u8 ThermalValue_IQK; - u8 ThermalValue_DPK; - - u8 bRfPiEnable; - - /* for APK */ - u32 APKoutput[2][2]; /* path A/B; output1_1a/output1_2a */ - u8 bAPKdone; - u8 bAPKThermalMeterIgnore; - u8 bDPdone; - u8 bDPPathAOK; - u8 bDPPathBOK; - - /* for IQK */ - u32 RegC04; - u32 Reg874; - u32 RegC08; - u32 RegB68; - u32 RegB6C; - u32 Reg870; - u32 Reg860; - u32 Reg864; - u32 ADDA_backup[IQK_ADDA_REG_NUM]; - u32 IQK_MAC_backup[IQK_MAC_REG_NUM]; - u32 IQK_BB_backup_recover[9]; - u32 IQK_BB_backup[IQK_BB_REG_NUM]; - u8 PowerIndex_backup[6]; - - u8 bCCKinCH14; - - u8 CCK_index; - u8 OFDM_index[2]; - - u8 bDoneTxpower; - u8 CCK_index_HP; - u8 OFDM_index_HP[2]; - u8 ThermalValue_HP[HP_THERMAL_NUM]; - u8 ThermalValue_HP_index; - - /* for TxPwrTracking */ - s32 RegE94; - s32 RegE9C; - s32 RegEB4; - s32 RegEBC; - - u32 TXPowerTrackingCallbackCnt; /* cosa add for debug */ - - u32 prv_traffic_idx; /* edca turbo */ - - s32 OFDM_Pkt_Cnt; - u8 RSSI_Select; -/* u8 DIG_Dynamic_MIN ; */ -/* duplicate code,will move to ODM ######### */ - /* Add for Reading Initial Data Rate SEL Register 0x484 during watchdog. Using for fill tx desc. 2011.3.21 by Thomas */ - u8 INIDATA_RATE[32]; -}; - - -/* */ -/* function prototype */ -/* */ - -void rtl8723a_init_dm_priv(struct rtw_adapter *padapter); - -void rtl8723a_InitHalDm(struct rtw_adapter *padapter); -void rtl8723a_HalDmWatchDog(struct rtw_adapter *padapter); - -#endif diff --git a/drivers/staging/rtl8723au/include/rtl8723a_hal.h b/drivers/staging/rtl8723au/include/rtl8723a_hal.h deleted file mode 100644 index 77a0fd4..0000000 --- a/drivers/staging/rtl8723au/include/rtl8723a_hal.h +++ /dev/null @@ -1,538 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __RTL8723A_HAL_H__ -#define __RTL8723A_HAL_H__ - -#include "rtl8723a_spec.h" -#include "rtl8723a_pg.h" -#include "Hal8723APhyReg.h" -#include "Hal8723APhyCfg.h" -#include "rtl8723a_rf.h" -#include "rtl8723a_bt_intf.h" -#ifdef CONFIG_8723AU_BT_COEXIST -#include "rtl8723a_bt-coexist.h" -#endif -#include "rtl8723a_dm.h" -#include "rtl8723a_recv.h" -#include "rtl8723a_xmit.h" -#include "rtl8723a_cmd.h" -#include "rtl8723a_sreset.h" -#include "rtw_efuse.h" -#include "rtw_eeprom.h" - -#include "odm_precomp.h" -#include "odm.h" - - -/* 2TODO: We should define 8192S firmware related macro settings here!! */ -#define RTL819X_DEFAULT_RF_TYPE RF_1T2R -#define RTL819X_TOTAL_RF_PATH 2 - -/* */ -/* RTL8723S From header */ -/* */ - -/* Fw Array */ -#define Rtl8723_FwImageArray Rtl8723UFwImgArray -#define Rtl8723_FwUMCBCutImageArrayWithBT Rtl8723UFwUMCBCutImgArrayWithBT -#define Rtl8723_FwUMCBCutImageArrayWithoutBT Rtl8723UFwUMCBCutImgArrayWithoutBT - -#define Rtl8723_ImgArrayLength Rtl8723UImgArrayLength -#define Rtl8723_UMCBCutImgArrayWithBTLength Rtl8723UUMCBCutImgArrayWithBTLength -#define Rtl8723_UMCBCutImgArrayWithoutBTLength Rtl8723UUMCBCutImgArrayWithoutBTLength - -#define Rtl8723_PHY_REG_Array_PG Rtl8723UPHY_REG_Array_PG -#define Rtl8723_PHY_REG_Array_PGLength Rtl8723UPHY_REG_Array_PGLength - -#define Rtl8723_FwUMCBCutMPImageArray Rtl8723SFwUMCBCutMPImgAr -#define Rtl8723_UMCBCutMPImgArrayLength Rtl8723SUMCBCutMPImgArrayLength - -#define DRVINFO_SZ 4 /* unit is 8bytes */ -#define PageNum_128(_Len) (u32)(((_Len)>>7) + ((_Len)&0x7F ? 1:0)) - -#define FW_8723A_SIZE 0x8000 -#define FW_8723A_START_ADDRESS 0x1000 -#define FW_8723A_END_ADDRESS 0x1FFF /* 0x5FFF */ - -#define MAX_PAGE_SIZE 4096 /* @ page : 4k bytes */ - -#define IS_FW_HEADER_EXIST(_pFwHdr) ((le16_to_cpu(_pFwHdr->Signature)&0xFFF0) == 0x92C0 ||\ - (le16_to_cpu(_pFwHdr->Signature)&0xFFF0) == 0x88C0 ||\ - (le16_to_cpu(_pFwHdr->Signature)&0xFFF0) == 0x2300) - -/* */ -/* This structure must be cared byte-ordering */ -/* */ -/* Added by tynli. 2009.12.04. */ -struct rt_8723a_firmware_hdr { - /* 8-byte alinment required */ - - /* LONG WORD 0 ---- */ - __le16 Signature; /* - * 92C0: test chip; 92C, 88C0: test chip; - * 88C1: MP A-cut; 92C1: MP A-cut - */ - u8 Category; /* AP/NIC and USB/PCI */ - u8 Function; /* Reserved for different FW function indcation, for further use when driver needs to download different FW in different conditions */ - __le16 Version; /* FW Version */ - u8 Subversion; /* FW Subversion, default 0x00 */ - u8 Rsvd1; - - - /* LONG WORD 1 ---- */ - u8 Month; /* Release time Month field */ - u8 Date; /* Release time Date field */ - u8 Hour; /* Release time Hour field */ - u8 Minute; /* Release time Minute field */ - __le16 RamCodeSize; /* The size of RAM code */ - __le16 Rsvd2; - - /* LONG WORD 2 ---- */ - __le32 SvnIdx; /* The SVN entry index */ - __le32 Rsvd3; - - /* LONG WORD 3 ---- */ - __le32 Rsvd4; - __le32 Rsvd5; -}; - -#define DRIVER_EARLY_INT_TIME 0x05 -#define BCN_DMA_ATIME_INT_TIME 0x02 - - -/* BK, BE, VI, VO, HCCA, MANAGEMENT, COMMAND, HIGH, BEACON. */ -#define MAX_TX_QUEUE 9 - -#define TX_SELE_HQ BIT(0) /* High Queue */ -#define TX_SELE_LQ BIT(1) /* Low Queue */ -#define TX_SELE_NQ BIT(2) /* Normal Queue */ - -/* Note: We will divide number of page equally for each queue other than public queue! */ -#define TX_TOTAL_PAGE_NUMBER 0xF8 -#define TX_PAGE_BOUNDARY (TX_TOTAL_PAGE_NUMBER + 1) - -/* For Normal Chip Setting */ -/* (HPQ + LPQ + NPQ + PUBQ) shall be TX_TOTAL_PAGE_NUMBER */ -#define NORMAL_PAGE_NUM_PUBQ 0xE7 -#define NORMAL_PAGE_NUM_HPQ 0x0C -#define NORMAL_PAGE_NUM_LPQ 0x02 -#define NORMAL_PAGE_NUM_NPQ 0x02 - -/* For Test Chip Setting */ -/* (HPQ + LPQ + PUBQ) shall be TX_TOTAL_PAGE_NUMBER */ -#define TEST_PAGE_NUM_PUBQ 0x7E - -/* For Test Chip Setting */ -#define WMM_TEST_TX_TOTAL_PAGE_NUMBER 0xF5 -#define WMM_TEST_TX_PAGE_BOUNDARY (WMM_TEST_TX_TOTAL_PAGE_NUMBER + 1) /* F6 */ - -#define WMM_TEST_PAGE_NUM_PUBQ 0xA3 -#define WMM_TEST_PAGE_NUM_HPQ 0x29 -#define WMM_TEST_PAGE_NUM_LPQ 0x29 - -/* Note: For Normal Chip Setting, modify later */ -#define WMM_NORMAL_TX_TOTAL_PAGE_NUMBER 0xF5 -#define WMM_NORMAL_TX_PAGE_BOUNDARY (WMM_TEST_TX_TOTAL_PAGE_NUMBER + 1) /* F6 */ - -#define WMM_NORMAL_PAGE_NUM_PUBQ 0xB0 -#define WMM_NORMAL_PAGE_NUM_HPQ 0x29 -#define WMM_NORMAL_PAGE_NUM_LPQ 0x1C -#define WMM_NORMAL_PAGE_NUM_NPQ 0x1C - - -/* */ -/* Chip specific */ -/* */ -#define CHIP_BONDING_IDENTIFIER(_value) (((_value)>>22)&0x3) -#define CHIP_BONDING_92C_1T2R 0x1 -#define CHIP_BONDING_88C_USB_MCARD 0x2 -#define CHIP_BONDING_88C_USB_HP 0x1 - -#include "HalVerDef.h" -#include "hal_com.h" - -/* */ -/* Channel Plan */ -/* */ -enum ChannelPlan -{ - CHPL_FCC = 0, - CHPL_IC = 1, - CHPL_ETSI = 2, - CHPL_SPAIN = 3, - CHPL_FRANCE = 4, - CHPL_MKK = 5, - CHPL_MKK1 = 6, - CHPL_ISRAEL = 7, - CHPL_TELEC = 8, - CHPL_GLOBAL = 9, - CHPL_WORLD = 10, -}; - -#define EFUSE_REAL_CONTENT_LEN 512 -#define EFUSE_MAP_LEN 128 -#define EFUSE_MAX_SECTION 16 -#define EFUSE_IC_ID_OFFSET 506 /* For some inferiority IC purpose. added by Roger, 2009.09.02. */ -#define AVAILABLE_EFUSE_ADDR(addr) (addr < EFUSE_REAL_CONTENT_LEN) -/* */ -/* <Roger_Notes> */ -/* To prevent out of boundary programming case, */ -/* leave 1byte and program full section */ -/* 9bytes + 1byt + 5bytes and pre 1byte. */ -/* For worst case: */ -/* | 1byte|----8bytes----|1byte|--5bytes--| */ -/* | | Reserved(14bytes) | */ -/* */ - -/* PG data exclude header, dummy 6 bytes from CP test and reserved 1byte. */ -#define EFUSE_OOB_PROTECT_BYTES 15 - -#define EFUSE_REAL_CONTENT_LEN_8723A 512 -#define EFUSE_MAP_LEN_8723A 256 -#define EFUSE_MAX_SECTION_8723A 32 - -/* */ -/* EFUSE for BT definition */ -/* */ -#define EFUSE_BT_REAL_BANK_CONTENT_LEN 512 -#define EFUSE_BT_REAL_CONTENT_LEN 1536 /* 512*3 */ -#define EFUSE_BT_MAP_LEN 1024 /* 1k bytes */ -#define EFUSE_BT_MAX_SECTION 128 /* 1024/8 */ - -#define EFUSE_PROTECT_BYTES_BANK 16 - -/* */ -/* <Roger_Notes> For RTL8723 WiFi/BT/GPS multi-function configuration. 2010.10.06. */ -/* */ -enum RT_MULTI_FUNC { - RT_MULTI_FUNC_NONE = 0x00, - RT_MULTI_FUNC_WIFI = 0x01, - RT_MULTI_FUNC_BT = 0x02, - RT_MULTI_FUNC_GPS = 0x04, -}; - -/* */ -/* <Roger_Notes> For RTL8723 WiFi PDn/GPIO polarity control configuration. 2010.10.08. */ -/* */ -enum RT_POLARITY_CTL { - RT_POLARITY_LOW_ACT = 0, - RT_POLARITY_HIGH_ACT = 1, -}; - -/* For RTL8723 regulator mode. by tynli. 2011.01.14. */ -enum RT_REGULATOR_MODE { - RT_SWITCHING_REGULATOR = 0, - RT_LDO_REGULATOR = 1, -}; - -/* Description: Determine the types of C2H events that are the same in driver and Fw. */ -/* Fisrt constructed by tynli. 2009.10.09. */ -enum { - C2H_DBG = 0, - C2H_TSF = 1, - C2H_AP_RPT_RSP = 2, - C2H_CCX_TX_RPT = 3, /* The FW notify the report of the specific tx packet. */ - C2H_BT_RSSI = 4, - C2H_BT_OP_MODE = 5, - C2H_EXT_RA_RPT = 6, - C2H_HW_INFO_EXCH = 10, - C2H_C2H_H2C_TEST = 11, - C2H_BT_INFO = 12, - C2H_BT_MP_INFO = 15, - MAX_C2HEVENT -}; - -struct hal_data_8723a { - struct hal_version VersionID; - enum rt_customer_id CustomerID; - - u16 FirmwareVersion; - u16 FirmwareVersionRev; - u16 FirmwareSubVersion; - u16 FirmwareSignature; - - /* current WIFI_PHY values */ - u32 ReceiveConfig; - enum WIRELESS_MODE CurrentWirelessMode; - enum ht_channel_width CurrentChannelBW; - u8 CurrentChannel; - u8 nCur40MhzPrimeSC;/* Control channel sub-carrier */ - - u16 BasicRateSet; - - /* rf_ctrl */ - u8 rf_type; - u8 NumTotalRFPath; - - u8 BoardType; - u8 CrystalCap; - /* */ - /* EEPROM setting. */ - /* */ - u8 EEPROMVersion; - u8 EEPROMCustomerID; - u8 EEPROMSubCustomerID; - u8 EEPROMRegulatory; - u8 EEPROMThermalMeter; - u8 EEPROMBluetoothCoexist; - u8 EEPROMBluetoothType; - u8 EEPROMBluetoothAntNum; - u8 EEPROMBluetoothAntIsolation; - u8 EEPROMBluetoothRadioShared; - - u8 bTXPowerDataReadFromEEPORM; - u8 bAPKThermalMeterIgnore; - - u8 bIQKInitialized; - u8 bAntennaDetected; - - u8 TxPwrLevelCck[RF_PATH_MAX][CHANNEL_MAX_NUMBER]; - u8 TxPwrLevelHT40_1S[RF_PATH_MAX][CHANNEL_MAX_NUMBER]; /* For HT 40MHZ pwr */ - u8 TxPwrLevelHT40_2S[RF_PATH_MAX][CHANNEL_MAX_NUMBER]; /* For HT 40MHZ pwr */ - u8 TxPwrHt20Diff[RF_PATH_MAX][CHANNEL_MAX_NUMBER];/* HT 20<->40 Pwr diff */ - u8 TxPwrLegacyHtDiff[RF_PATH_MAX][CHANNEL_MAX_NUMBER];/* For HT<->legacy pwr diff */ - /* For power group */ - u8 PwrGroupHT20[RF_PATH_MAX][CHANNEL_MAX_NUMBER]; - u8 PwrGroupHT40[RF_PATH_MAX][CHANNEL_MAX_NUMBER]; - - u8 LegacyHTTxPowerDiff;/* Legacy to HT rate power diff */ - - /* Read/write are allow for following hardware information variables */ - u8 framesync; - u32 framesyncC34; - u8 framesyncMonitor; - u8 pwrGroupCnt; - u32 MCSTxPowerLevelOriginalOffset[7][16]; - u32 CCKTxPowerLevelOriginalOffset; - - u32 AntennaTxPath; /* Antenna path Tx */ - u32 AntennaRxPath; /* Antenna path Rx */ - u8 ExternalPA; - - u8 bLedOpenDrain; /* Support Open-drain arrangement for controlling the LED. Added by Roger, 2009.10.16. */ - - u8 b1x1RecvCombine; /* for 1T1R receive combining */ - - /* For EDCA Turbo mode */ - - u32 AcParam_BE; /* Original parameter for BE, use for EDCA turbo. */ - - /* vivi, for tx power tracking, 20080407 */ - /* u16 TSSI_13dBm; */ - /* u32 Pwr_Track; */ - /* The current Tx Power Level */ - u8 CurrentCckTxPwrIdx; - u8 CurrentOfdm24GTxPwrIdx; - - struct bb_reg_define PHYRegDef[4]; /* Radio A/B/C/D */ - - bool bRFPathRxEnable[4]; /* We support 4 RF path now. */ - - u32 RfRegChnlVal[2]; - - u8 bCckHighPower; - - /* RDG enable */ - bool bRDGEnable; - - /* for host message to fw */ - u8 LastHMEBoxNum; - - u8 RegTxPause; - /* Beacon function related global variable. */ - u8 RegFwHwTxQCtrl; - u8 RegReg542; - - struct dm_priv dmpriv; - struct dm_odm_t odmpriv; - struct sreset_priv srestpriv; - -#ifdef CONFIG_8723AU_BT_COEXIST - u8 bBTMode; - /* BT only. */ - struct bt_30info BtInfo; - /* For bluetooth co-existance */ - struct bt_coexist_str bt_coexist; -#endif - - u8 bDumpRxPkt;/* for debug */ - u8 FwRsvdPageStartOffset; /* 2010.06.23. Added by tynli. Reserve page start offset except beacon in TxQ. */ - - /* 2010/08/09 MH Add CU power down mode. */ - u8 pwrdown; - - u8 OutEpQueueSel; - u8 OutEpNumber; - - /* */ - /* Add For EEPROM Efuse switch and Efuse Shadow map Setting */ - /* */ - u8 EepromOrEfuse; - u16 EfuseUsedBytes; - u16 BTEfuseUsedBytes; - - /* Interrupt relatd register information. */ - u32 SysIntrStatus; - u32 SysIntrMask; - - /* */ - /* 2011/02/23 MH Add for 8723 mylti function definition. The define should be moved to an */ - /* independent file in the future. */ - /* */ - /* 8723-----------------------------------------*/ - enum RT_MULTI_FUNC MultiFunc; /* For multi-function consideration. */ - enum RT_POLARITY_CTL PolarityCtl; /* For Wifi PDn Polarity control. */ - enum RT_REGULATOR_MODE RegulatorMode; /* switching regulator or LDO */ - /* 8723----------------------------------------- - * 2011/02/23 MH Add for 8723 mylti function definition. The define should be moved to an */ - /* independent file in the future. */ - - /* Interrupt related register information. */ - u32 IntArray[2]; - u32 IntrMask[2]; -}; - -#define GET_HAL_DATA(__pAdapter) ((struct hal_data_8723a *)((__pAdapter)->HalData)) -#define GET_RF_TYPE(priv) (GET_HAL_DATA(priv)->rf_type) - -#define INCLUDE_MULTI_FUNC_BT(_Adapter) (GET_HAL_DATA(_Adapter)->MultiFunc & RT_MULTI_FUNC_BT) -#define INCLUDE_MULTI_FUNC_GPS(_Adapter) (GET_HAL_DATA(_Adapter)->MultiFunc & RT_MULTI_FUNC_GPS) - -struct rxreport_8723a { - u32 pktlen:14; - u32 crc32:1; - u32 icverr:1; - u32 drvinfosize:4; - u32 security:3; - u32 qos:1; - u32 shift:2; - u32 physt:1; - u32 swdec:1; - u32 ls:1; - u32 fs:1; - u32 eor:1; - u32 own:1; - - u32 macid:5; - u32 tid:4; - u32 hwrsvd:4; - u32 amsdu:1; - u32 paggr:1; - u32 faggr:1; - u32 a1fit:4; - u32 a2fit:4; - u32 pam:1; - u32 pwr:1; - u32 md:1; - u32 mf:1; - u32 type:2; - u32 mc:1; - u32 bc:1; - - u32 seq:12; - u32 frag:4; - u32 nextpktlen:14; - u32 nextind:1; - u32 rsvd0831:1; - - u32 rxmcs:6; - u32 rxht:1; - u32 gf:1; - u32 splcp:1; - u32 bw:1; - u32 htc:1; - u32 eosp:1; - u32 bssidfit:2; - u32 rsvd1214:16; - u32 unicastwake:1; - u32 magicwake:1; - - u32 pattern0match:1; - u32 pattern1match:1; - u32 pattern2match:1; - u32 pattern3match:1; - u32 pattern4match:1; - u32 pattern5match:1; - u32 pattern6match:1; - u32 pattern7match:1; - u32 pattern8match:1; - u32 pattern9match:1; - u32 patternamatch:1; - u32 patternbmatch:1; - u32 patterncmatch:1; - u32 rsvd1613:19; - - u32 tsfl; - - u32 bassn:12; - u32 bavld:1; - u32 rsvd2413:19; -}; - -/* rtl8723a_hal_init.c */ -s32 rtl8723a_FirmwareDownload(struct rtw_adapter *padapter); -void rtl8723a_FirmwareSelfReset(struct rtw_adapter *padapter); -void rtl8723a_InitializeFirmwareVars(struct rtw_adapter *padapter); - -void rtl8723a_InitAntenna_Selection(struct rtw_adapter *padapter); -void rtl8723a_DeinitAntenna_Selection(struct rtw_adapter *padapter); -void rtl8723a_CheckAntenna_Selection(struct rtw_adapter *padapter); -void rtl8723a_init_default_value(struct rtw_adapter *padapter); - -s32 InitLLTTable23a(struct rtw_adapter *padapter, u32 boundary); - -s32 CardDisableHWSM(struct rtw_adapter *padapter, u8 resetMCU); -s32 CardDisableWithoutHWSM(struct rtw_adapter *padapter); - -/* EFuse */ -u8 GetEEPROMSize8723A(struct rtw_adapter *padapter); -void Hal_InitPGData(struct rtw_adapter *padapter, u8 *PROMContent); -void Hal_EfuseParseIDCode(struct rtw_adapter *padapter, u8 *hwinfo); -void Hal_EfuseParsetxpowerinfo_8723A(struct rtw_adapter *padapter, u8 *PROMContent, bool AutoLoadFail); -void Hal_EfuseParseBTCoexistInfo_8723A(struct rtw_adapter *padapter, u8 *hwinfo, bool AutoLoadFail); -void Hal_EfuseParseEEPROMVer(struct rtw_adapter *padapter, u8 *hwinfo, bool AutoLoadFail); -void rtl8723a_EfuseParseChnlPlan(struct rtw_adapter *padapter, u8 *hwinfo, bool AutoLoadFail); -void Hal_EfuseParseCustomerID(struct rtw_adapter *padapter, u8 *hwinfo, bool AutoLoadFail); -void Hal_EfuseParseAntennaDiversity(struct rtw_adapter *padapter, u8 *hwinfo, bool AutoLoadFail); -void Hal_EfuseParseRateIndicationOption(struct rtw_adapter *padapter, u8 *hwinfo, bool AutoLoadFail); -void Hal_EfuseParseXtal_8723A(struct rtw_adapter *pAdapter, u8 *hwinfo, u8 AutoLoadFail); -void Hal_EfuseParseThermalMeter_8723A(struct rtw_adapter *padapter, u8 *hwinfo, bool AutoLoadFail); - -/* register */ -void SetBcnCtrlReg23a(struct rtw_adapter *padapter, u8 SetBits, u8 ClearBits); -void rtl8723a_InitBeaconParameters(struct rtw_adapter *padapter); - -void rtl8723a_start_thread(struct rtw_adapter *padapter); -void rtl8723a_stop_thread(struct rtw_adapter *padapter); - -bool c2h_id_filter_ccx_8723a(u8 id); -int c2h_handler_8723a(struct rtw_adapter *padapter, struct c2h_evt_hdr *c2h_evt); - -void rtl8723a_read_adapter_info(struct rtw_adapter *Adapter); -void rtl8723a_read_chip_version(struct rtw_adapter *padapter); -void rtl8723a_notch_filter(struct rtw_adapter *adapter, bool enable); -void rtl8723a_SetBeaconRelatedRegisters(struct rtw_adapter *padapter); -void rtl8723a_SetHalODMVar(struct rtw_adapter *Adapter, - enum hal_odm_variable eVariable, - void *pValue1, bool bSet); -void -rtl8723a_readefuse(struct rtw_adapter *padapter, - u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf); -u16 rtl8723a_EfuseGetCurrentSize_WiFi(struct rtw_adapter *padapter); -u16 rtl8723a_EfuseGetCurrentSize_BT(struct rtw_adapter *padapter); -void rtl8723a_update_ramask(struct rtw_adapter *padapter, - u32 mac_id, u8 rssi_level); - -#endif diff --git a/drivers/staging/rtl8723au/include/rtl8723a_pg.h b/drivers/staging/rtl8723au/include/rtl8723a_pg.h deleted file mode 100644 index 5c2ec44..0000000 --- a/drivers/staging/rtl8723au/include/rtl8723a_pg.h +++ /dev/null @@ -1,98 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __RTL8723A_PG_H__ -#define __RTL8723A_PG_H__ - -/* EEPROM/Efuse PG Offset for 8723E/8723U/8723S */ -#define EEPROM_CCK_TX_PWR_INX_8723A 0x10 -#define EEPROM_HT40_1S_TX_PWR_INX_8723A 0x16 -#define EEPROM_HT20_TX_PWR_INX_DIFF_8723A 0x1C -#define EEPROM_OFDM_TX_PWR_INX_DIFF_8723A 0x1F -#define EEPROM_HT40_MAX_PWR_OFFSET_8723A 0x22 -#define EEPROM_HT20_MAX_PWR_OFFSET_8723A 0x25 - -#define EEPROM_ChannelPlan_8723A 0x28 -#define EEPROM_TSSI_A_8723A 0x29 -#define EEPROM_THERMAL_METER_8723A 0x2A -#define RF_OPTION1_8723A 0x2B -#define RF_OPTION2_8723A 0x2C -#define RF_OPTION3_8723A 0x2D -#define RF_OPTION4_8723A 0x2E -#define EEPROM_VERSION_8723A 0x30 -#define EEPROM_CustomID_8723A 0x31 -#define EEPROM_SubCustomID_8723A 0x32 -#define EEPROM_XTAL_K_8723A 0x33 -#define EEPROM_Chipset_8723A 0x34 - -/* RTL8723AE */ -#define EEPROM_VID_8723AE 0x49 -#define EEPROM_DID_8723AE 0x4B -#define EEPROM_SVID_8723AE 0x4D -#define EEPROM_SMID_8723AE 0x4F -#define EEPROM_MAC_ADDR_8723AE 0x67 - -/* RTL8723AU */ -#define EEPROM_MAC_ADDR_8723AU 0xC6 -#define EEPROM_VID_8723AU 0xB7 -#define EEPROM_PID_8723AU 0xB9 - -/* RTL8723AS */ -#define EEPROM_MAC_ADDR_8723AS 0xAA - -/* EEPROM/Efuse Value Type */ -#define EETYPE_TX_PWR 0x0 - -/* EEPROM/Efuse Default Value */ -#define EEPROM_Default_CrystalCap_8723A 0x20 - - -/* EEPROM/EFUSE data structure definition. */ -#define MAX_CHNL_GROUP 3+9 - -struct txpowerinfo { - u8 CCKIndex[RF_PATH_MAX][MAX_CHNL_GROUP]; - u8 HT40_1SIndex[RF_PATH_MAX][MAX_CHNL_GROUP]; - u8 HT40_2SIndexDiff[RF_PATH_MAX][MAX_CHNL_GROUP]; - u8 HT20IndexDiff[RF_PATH_MAX][MAX_CHNL_GROUP]; - u8 OFDMIndexDiff[RF_PATH_MAX][MAX_CHNL_GROUP]; - u8 HT40MaxOffset[RF_PATH_MAX][MAX_CHNL_GROUP]; - u8 HT20MaxOffset[RF_PATH_MAX][MAX_CHNL_GROUP]; - u8 TSSI_A[3]; - u8 TSSI_B[3]; - u8 TSSI_A_5G[3]; /* 5GL/5GM/5GH */ - u8 TSSI_B_5G[3]; -}; - -enum bt_ant_num { - Ant_x2 = 0, - Ant_x1 = 1 -}; - -enum bt_cotype { - BT_2Wire = 0, - BT_ISSC_3Wire = 1, - BT_Accel = 2, - BT_CSR_BC4 = 3, - BT_CSR_BC8 = 4, - BT_RTL8756 = 5, - BT_RTL8723A = 6 -}; - -enum bt_radioshared { - BT_Radio_Shared = 0, - BT_Radio_Individual = 1, -}; - -#endif diff --git a/drivers/staging/rtl8723au/include/rtl8723a_recv.h b/drivers/staging/rtl8723au/include/rtl8723a_recv.h deleted file mode 100644 index 875d37b..0000000 --- a/drivers/staging/rtl8723au/include/rtl8723a_recv.h +++ /dev/null @@ -1,65 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __RTL8723A_RECV_H__ -#define __RTL8723A_RECV_H__ - -#include <osdep_service.h> -#include <drv_types.h> - -#define NR_RECVBUFF 4 - -#define NR_PREALLOC_RECV_SKB 8 - -#define RECV_BLK_SZ 512 -#define RECV_BLK_CNT 16 -#define RECV_BLK_TH RECV_BLK_CNT - -#define MAX_RECVBUF_SZ 15360 /* 15k < 16k */ - -#define PHY_RSSI_SLID_WIN_MAX 100 -#define PHY_LINKQUALITY_SLID_WIN_MAX 20 - - -struct phy_stat { - unsigned int phydw0; - unsigned int phydw1; - unsigned int phydw2; - unsigned int phydw3; - unsigned int phydw4; - unsigned int phydw5; - unsigned int phydw6; - unsigned int phydw7; -}; - -/* Rx smooth factor */ -#define Rx_Smooth_Factor 20 - -struct interrupt_msg_format { - unsigned int C2H_MSG0; - unsigned int C2H_MSG1; - unsigned int C2H_MSG2; - unsigned int C2H_MSG3; - unsigned int HISR; /* from HISR Reg0x124, read to clear */ - unsigned int HISRE;/* from HISRE Reg0x12c, read to clear */ - unsigned int MSG_EX; -}; - -int rtl8723au_init_recv_priv(struct rtw_adapter *padapter); -void rtl8723au_free_recv_priv(struct rtw_adapter *padapter); -void rtl8723a_process_phy_info(struct rtw_adapter *padapter, void *prframe); -void update_recvframe_attrib(struct recv_frame *precvframe, struct recv_stat *prxstat); -void update_recvframe_phyinfo(struct recv_frame *precvframe, struct phy_stat *pphy_info); - -#endif diff --git a/drivers/staging/rtl8723au/include/rtl8723a_rf.h b/drivers/staging/rtl8723au/include/rtl8723a_rf.h deleted file mode 100644 index 0432799..0000000 --- a/drivers/staging/rtl8723au/include/rtl8723a_rf.h +++ /dev/null @@ -1,58 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __RTL8723A_RF_H__ -#define __RTL8723A_RF_H__ - -/*--------------------------Define Parameters-------------------------------*/ - -/* */ -/* For RF 6052 Series */ -/* */ -#define RF6052_MAX_TX_PWR 0x3F -#define RF6052_MAX_REG 0x3F -#define RF6052_MAX_PATH 2 -/*--------------------------Define Parameters-------------------------------*/ - - -/*------------------------------Define structure----------------------------*/ - -/*------------------------------Define structure----------------------------*/ - - -/*------------------------Export global variable----------------------------*/ -/*------------------------Export global variable----------------------------*/ - -/*------------------------Export Marco Definition---------------------------*/ - -/*------------------------Export Marco Definition---------------------------*/ - - -/*--------------------------Exported Function prototype---------------------*/ - -/* */ -/* RF RL6052 Series API */ -/* */ -void rtl8723a_phy_rf6052set_bw(struct rtw_adapter *Adapter, - enum ht_channel_width Bandwidth); -void rtl823a_phy_rf6052setccktxpower(struct rtw_adapter *Adapter, - u8 *pPowerlevel); -void rtl8723a_PHY_RF6052SetOFDMTxPower(struct rtw_adapter *Adapter, - u8 *pPowerLevel, u8 Channel); - -/*--------------------------Exported Function prototype---------------------*/ - -int PHY_RF6052_Config8723A(struct rtw_adapter *Adapter); - -#endif diff --git a/drivers/staging/rtl8723au/include/rtl8723a_spec.h b/drivers/staging/rtl8723au/include/rtl8723a_spec.h deleted file mode 100644 index 2f18689..0000000 --- a/drivers/staging/rtl8723au/include/rtl8723a_spec.h +++ /dev/null @@ -1,2148 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - *******************************************************************************/ -#ifndef __RTL8723A_SPEC_H__ -#define __RTL8723A_SPEC_H__ - -/* */ -/* */ -/* 0x0000h ~ 0x00FFh System Configuration */ -/* */ -/* */ -#define REG_SYS_ISO_CTRL 0x0000 -#define REG_SYS_FUNC_EN 0x0002 -#define REG_APS_FSMCO 0x0004 -#define REG_SYS_CLKR 0x0008 -#define REG_9346CR 0x000A -#define REG_EE_VPD 0x000C -#define REG_AFE_MISC 0x0010 -#define REG_SPS0_CTRL 0x0011 -#define REG_SPS_OCP_CFG 0x0018 -#define REG_RSV_CTRL 0x001C -#define REG_RF_CTRL 0x001F -#define REG_LDOA15_CTRL 0x0020 -#define REG_LDOV12D_CTRL 0x0021 -#define REG_LDOHCI12_CTRL 0x0022 -#define REG_LPLDO_CTRL 0x0023 -#define REG_AFE_XTAL_CTRL 0x0024 -#define REG_AFE_PLL_CTRL 0x0028 -#define REG_MAC_PHY_CTRL 0x002c -#define REG_EFUSE_CTRL 0x0030 -#define REG_EFUSE_TEST 0x0034 -#define REG_PWR_DATA 0x0038 -#define REG_CAL_TIMER 0x003C -#define REG_ACLK_MON 0x003E -#define REG_GPIO_MUXCFG 0x0040 -#define REG_GPIO_IO_SEL 0x0042 -#define REG_MAC_PINMUX_CFG 0x0043 -#define REG_GPIO_PIN_CTRL 0x0044 -#define REG_GPIO_INTM 0x0048 -#define REG_LEDCFG0 0x004C -#define REG_LEDCFG1 0x004D -#define REG_LEDCFG2 0x004E -#define REG_LEDCFG3 0x004F -#define REG_LEDCFG REG_LEDCFG2 -#define REG_FSIMR 0x0050 -#define REG_FSISR 0x0054 -#define REG_HSIMR 0x0058 -#define REG_HSISR 0x005c - /* RTL8723 WIFI/BT/GPS Multi-Function GPIO Pin Control. */ -#define REG_GPIO_PIN_CTRL_2 0x0060 - /* RTL8723 WIFI/BT/GPS Multi-Function GPIO Select. */ -#define REG_GPIO_IO_SEL_2 0x0062 - /* RTL8723 WIFI/BT/GPS Multi-Function control source. */ -#define REG_MULTI_FUNC_CTRL 0x0068 -#define REG_MCUFWDL 0x0080 -#define REG_HMEBOX_EXT_0 0x0088 -#define REG_HMEBOX_EXT_1 0x008A -#define REG_HMEBOX_EXT_2 0x008C -#define REG_HMEBOX_EXT_3 0x008E - /* Host suspend counter on FPGA platform */ -#define REG_HOST_SUSP_CNT 0x00BC - /* Efuse access protection for RTL8723 */ -#define REG_EFUSE_ACCESS 0x00CF -#define REG_BIST_SCAN 0x00D0 -#define REG_BIST_RPT 0x00D4 -#define REG_BIST_ROM_RPT 0x00D8 -#define REG_USB_SIE_INTF 0x00E0 -#define REG_PCIE_MIO_INTF 0x00E4 -#define REG_PCIE_MIO_INTD 0x00E8 -#define REG_HPON_FSM 0x00EC -#define REG_SYS_CFG 0x00F0 -#define REG_GPIO_OUTSTS 0x00F4 /* For RTL8723 only. */ - -/* */ -/* */ -/* 0x0100h ~ 0x01FFh MACTOP General Configuration */ -/* */ -/* */ -#define REG_CR 0x0100 -#define REG_PBP 0x0104 -#define REG_TRXDMA_CTRL 0x010C -#define REG_TRXFF_BNDY 0x0114 -#define REG_TRXFF_STATUS 0x0118 -#define REG_RXFF_PTR 0x011C -#define REG_HIMR 0x0120 -#define REG_HISR 0x0124 -#define REG_HIMRE 0x0128 -#define REG_HISRE 0x012C -#define REG_CPWM 0x012F -#define REG_FWIMR 0x0130 -#define REG_FWISR 0x0134 -#define REG_PKTBUF_DBG_CTRL 0x0140 -#define REG_PKTBUF_DBG_DATA_L 0x0144 -#define REG_PKTBUF_DBG_DATA_H 0x0148 - -#define REG_TC0_CTRL 0x0150 -#define REG_TC1_CTRL 0x0154 -#define REG_TC2_CTRL 0x0158 -#define REG_TC3_CTRL 0x015C -#define REG_TC4_CTRL 0x0160 -#define REG_TCUNIT_BASE 0x0164 -#define REG_MBIST_START 0x0174 -#define REG_MBIST_DONE 0x0178 -#define REG_MBIST_FAIL 0x017C -#define REG_C2HEVT_MSG_NORMAL 0x01A0 -#define REG_C2HEVT_CLEAR 0x01AF -#define REG_C2HEVT_MSG_TEST 0x01B8 -#define REG_MCUTST_1 0x01c0 -#define REG_FMETHR 0x01C8 -#define REG_HMETFR 0x01CC -#define REG_HMEBOX_0 0x01D0 -#define REG_HMEBOX_1 0x01D4 -#define REG_HMEBOX_2 0x01D8 -#define REG_HMEBOX_3 0x01DC - -#define REG_LLT_INIT 0x01E0 -#define REG_BB_ACCEESS_CTRL 0x01E8 -#define REG_BB_ACCESS_DATA 0x01EC - - -/* */ -/* */ -/* 0x0200h ~ 0x027Fh TXDMA Configuration */ -/* */ -/* */ -#define REG_RQPN 0x0200 -#define REG_FIFOPAGE 0x0204 -#define REG_TDECTRL 0x0208 -#define REG_TXDMA_OFFSET_CHK 0x020C -#define REG_TXDMA_STATUS 0x0210 -#define REG_RQPN_NPQ 0x0214 - -/* */ -/* */ -/* 0x0280h ~ 0x02FFh RXDMA Configuration */ -/* */ -/* */ -#define REG_RXDMA_AGG_PG_TH 0x0280 -#define REG_RXPKT_NUM 0x0284 -#define REG_RXDMA_STATUS 0x0288 - - -/* */ -/* */ -/* 0x0300h ~ 0x03FFh PCIe */ -/* */ -/* */ -#define REG_PCIE_CTRL_REG 0x0300 -#define REG_INT_MIG 0x0304 /* Interrupt Migration */ - /* TX Beacon Descriptor Address */ -#define REG_BCNQ_DESA 0x0308 - /* TX High Queue Descriptor Address */ -#define REG_HQ_DESA 0x0310 - /* TX Manage Queue Descriptor Address */ -#define REG_MGQ_DESA 0x0318 - /* TX VO Queue Descriptor Address */ -#define REG_VOQ_DESA 0x0320 - /* TX VI Queue Descriptor Address */ -#define REG_VIQ_DESA 0x0328 - /* TX BE Queue Descriptor Address */ -#define REG_BEQ_DESA 0x0330 - /* TX BK Queue Descriptor Address */ -#define REG_BKQ_DESA 0x0338 - /* RX Queue Descriptor Address */ -#define REG_RX_DESA 0x0340 - /* Backdoor REG for Access Configuration */ -#define REG_DBI 0x0348 - /* MDIO for Access PCIE PHY */ -#define REG_MDIO 0x0354 - /* Debug Selection Register */ -#define REG_DBG_SEL 0x0360 - /* PCIe RPWM */ -#define REG_PCIE_HRPWM 0x0361 - /* PCIe CPWM */ -#define REG_PCIE_HCPWM 0x0363 - /* UART Control */ -#define REG_UART_CTRL 0x0364 - /* UART TX Descriptor Address */ -#define REG_UART_TX_DESA 0x0370 - /* UART Rx Descriptor Address */ -#define REG_UART_RX_DESA 0x0378 - - -/* spec version 11 */ -/* */ -/* */ -/* 0x0400h ~ 0x047Fh Protocol Configuration */ -/* */ -/* */ -#define REG_VOQ_INFORMATION 0x0400 -#define REG_VIQ_INFORMATION 0x0404 -#define REG_BEQ_INFORMATION 0x0408 -#define REG_BKQ_INFORMATION 0x040C -#define REG_MGQ_INFORMATION 0x0410 -#define REG_HGQ_INFORMATION 0x0414 -#define REG_BCNQ_INFORMATION 0x0418 - - -#define REG_CPU_MGQ_INFORMATION 0x041C -#define REG_FWHW_TXQ_CTRL 0x0420 -#define REG_HWSEQ_CTRL 0x0423 -#define REG_TXPKTBUF_BCNQ_BDNY 0x0424 -#define REG_TXPKTBUF_MGQ_BDNY 0x0425 -#define REG_LIFETIME_EN 0x0426 -#define REG_MULTI_BCNQ_OFFSET 0x0427 -#define REG_SPEC_SIFS 0x0428 -#define REG_RL 0x042A -#define REG_DARFRC 0x0430 -#define REG_RARFRC 0x0438 -#define REG_RRSR 0x0440 -#define REG_ARFR0 0x0444 -#define REG_ARFR1 0x0448 -#define REG_ARFR2 0x044C -#define REG_ARFR3 0x0450 -#define REG_AGGLEN_LMT 0x0458 -#define REG_AMPDU_MIN_SPACE 0x045C -#define REG_TXPKTBUF_WMAC_LBK_BF_HD 0x045D -#define REG_FAST_EDCA_CTRL 0x0460 -#define REG_RD_RESP_PKT_TH 0x0463 -#define REG_INIRTS_RATE_SEL 0x0480 -#define REG_INIDATA_RATE_SEL 0x0484 - - -#define REG_POWER_STATUS 0x04A4 -#define REG_POWER_STAGE1 0x04B4 -#define REG_POWER_STAGE2 0x04B8 -#define REG_PKT_VO_VI_LIFE_TIME 0x04C0 -#define REG_PKT_BE_BK_LIFE_TIME 0x04C2 -#define REG_STBC_SETTING 0x04C4 -#define REG_PROT_MODE_CTRL 0x04C8 -#define REG_MAX_AGGR_NUM 0x04CA -#define REG_RTS_MAX_AGGR_NUM 0x04CB -#define REG_BAR_MODE_CTRL 0x04CC -#define REG_RA_TRY_RATE_AGG_LMT 0x04CF -#define REG_NQOS_SEQ 0x04DC -#define REG_QOS_SEQ 0x04DE -#define REG_NEED_CPU_HANDLE 0x04E0 -#define REG_PKT_LOSE_RPT 0x04E1 -#define REG_PTCL_ERR_STATUS 0x04E2 -#define REG_DUMMY 0x04FC - - - -/* */ -/* */ -/* 0x0500h ~ 0x05FFh EDCA Configuration */ -/* */ -/* */ -#define REG_EDCA_VO_PARAM 0x0500 -#define REG_EDCA_VI_PARAM 0x0504 -#define REG_EDCA_BE_PARAM 0x0508 -#define REG_EDCA_BK_PARAM 0x050C -#define REG_BCNTCFG 0x0510 -#define REG_PIFS 0x0512 -#define REG_RDG_PIFS 0x0513 -#define REG_SIFS_CCK 0x0514 -#define REG_SIFS_OFDM 0x0516 -#define REG_SIFS_CTX 0x0514 -#define REG_SIFS_TRX 0x0516 -#define REG_TSFTR_SYN_OFFSET 0x0518 -#define REG_AGGR_BREAK_TIME 0x051A -#define REG_SLOT 0x051B -#define REG_TX_PTCL_CTRL 0x0520 -#define REG_TXPAUSE 0x0522 -#define REG_DIS_TXREQ_CLR 0x0523 -#define REG_RD_CTRL 0x0524 -#define REG_TBTT_PROHIBIT 0x0540 -#define REG_RD_NAV_NXT 0x0544 -#define REG_NAV_PROT_LEN 0x0546 -#define REG_BCN_CTRL 0x0550 -#define REG_BCN_CTRL_1 0x0551 -#define REG_MBID_NUM 0x0552 -#define REG_DUAL_TSF_RST 0x0553 - /* The same as REG_MBSSID_BCN_SPACE */ -#define REG_BCN_INTERVAL 0x0554 -#define REG_MBSSID_BCN_SPACE 0x0554 -#define REG_DRVERLYINT 0x0558 -#define REG_BCNDMATIM 0x0559 -#define REG_ATIMWND 0x055A -#define REG_BCN_MAX_ERR 0x055D -#define REG_RXTSF_OFFSET_CCK 0x055E -#define REG_RXTSF_OFFSET_OFDM 0x055F -#define REG_TSFTR 0x0560 -#define REG_TSFTR1 0x0568 -#define REG_INIT_TSFTR 0x0564 -#define REG_ATIMWND_1 0x0570 -#define REG_PSTIMER 0x0580 -#define REG_TIMER0 0x0584 -#define REG_TIMER1 0x0588 -#define REG_ACMHWCTRL 0x05C0 -#define REG_ACMRSTCTRL 0x05C1 -#define REG_ACMAVG 0x05C2 -#define REG_VO_ADMTIME 0x05C4 -#define REG_VI_ADMTIME 0x05C6 -#define REG_BE_ADMTIME 0x05C8 -#define REG_EDCA_RANDOM_GEN 0x05CC -#define REG_SCH_TXCMD 0x05D0 - -/* define REG_FW_TSF_SYNC_CNT 0x04A0 */ -#define REG_FW_RESET_TSF_CNT_1 0x05FC -#define REG_FW_RESET_TSF_CNT_0 0x05FD -#define REG_FW_BCN_DIS_CNT 0x05FE - -/* */ -/* */ -/* 0x0600h ~ 0x07FFh WMAC Configuration */ -/* */ -/* */ -#define REG_APSD_CTRL 0x0600 -#define REG_BWOPMODE 0x0603 -#define REG_TCR 0x0604 -#define REG_RCR 0x0608 -#define REG_RX_PKT_LIMIT 0x060C -#define REG_RX_DLK_TIME 0x060D -#define REG_RX_DRVINFO_SZ 0x060F - -#define REG_MACID 0x0610 -#define REG_BSSID 0x0618 -#define REG_MAR 0x0620 -#define REG_MBIDCAMCFG 0x0628 - -#define REG_USTIME_EDCA 0x0638 -#define REG_MAC_SPEC_SIFS 0x063A - -/* 20100719 Joseph: Hardware register definition change. (HW datasheet v54) */ - /* [15:8]SIFS_R2T_OFDM, [7:0]SIFS_R2T_CCK */ -#define REG_R2T_SIFS 0x063C - /* [15:8]SIFS_T2T_OFDM, [7:0]SIFS_T2T_CCK */ -#define REG_T2T_SIFS 0x063E -#define REG_ACKTO 0x0640 -#define REG_CTS2TO 0x0641 -#define REG_EIFS 0x0642 - -/* WMA, BA, CCX */ -#define REG_NAV_CTRL 0x0650 -#define REG_BACAMCMD 0x0654 -#define REG_BACAMCONTENT 0x0658 -#define REG_LBDLY 0x0660 -#define REG_FWDLY 0x0661 -#define REG_RXERR_RPT 0x0664 -#define REG_WMAC_TRXPTCL_CTL 0x0668 - - -/* Security */ -#define REG_CAMCMD 0x0670 -#define REG_CAMWRITE 0x0674 -#define REG_CAMREAD 0x0678 -#define REG_CAMDBG 0x067C -#define REG_SECCFG 0x0680 - -/* Power */ -#define REG_WOW_CTRL 0x0690 -#define REG_PSSTATUS 0x0691 -#define REG_PS_RX_INFO 0x0692 -#define REG_LPNAV_CTRL 0x0694 -#define REG_WKFMCAM_CMD 0x0698 -#define REG_WKFMCAM_RWD 0x069C -#define REG_RXFLTMAP0 0x06A0 -#define REG_RXFLTMAP1 0x06A2 -#define REG_RXFLTMAP2 0x06A4 -#define REG_BCN_PSR_RPT 0x06A8 -#define REG_CALB32K_CTRL 0x06AC -#define REG_PKT_MON_CTRL 0x06B4 -#define REG_BT_COEX_TABLE 0x06C0 -#define REG_WMAC_RESP_TXINFO 0x06D8 - -#define REG_MACID1 0x0700 -#define REG_BSSID1 0x0708 - - -/* */ -/* */ -/* 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 - -/* For test chip */ -#define REG_TEST_USB_TXQS 0xFE48 -#define REG_TEST_SIE_VID 0xFE60 /* 0xFE60~0xFE61 */ -#define REG_TEST_SIE_PID 0xFE62 /* 0xFE62~0xFE63 */ -#define REG_TEST_SIE_OPTIONAL 0xFE64 -#define REG_TEST_SIE_CHIRP_K 0xFE65 -#define REG_TEST_SIE_PHY 0xFE66 /* 0xFE66~0xFE6B */ -#define REG_TEST_SIE_MAC_ADDR 0xFE70 /* 0xFE70~0xFE75 */ -#define REG_TEST_SIE_STRING 0xFE80 /* 0xFE80~0xFEB9 */ - - -/* For normal chip */ -#define REG_NORMAL_SIE_VID 0xFE60 /* 0xFE60~0xFE61 */ -#define REG_NORMAL_SIE_PID 0xFE62 /* 0xFE62~0xFE63 */ -#define REG_NORMAL_SIE_OPTIONAL 0xFE64 -#define REG_NORMAL_SIE_EP 0xFE65 /* 0xFE65~0xFE67 */ -#define REG_NORMAL_SIE_PHY 0xFE68 /* 0xFE68~0xFE6B */ -#define REG_NORMAL_SIE_OPTIONAL2 0xFE6C -#define REG_NORMAL_SIE_GPS_EP 0xFE6D /* RTL8723 only */ -#define REG_NORMAL_SIE_MAC_ADDR 0xFE70 /* 0xFE70~0xFE75 */ -#define REG_NORMAL_SIE_STRING 0xFE80 /* 0xFE80~0xFEDF */ - - -/* */ -/* */ -/* Redifine 8192C register definition for compatibility */ -/* */ -/* */ - -/* TODO: use these definition when using REG_xxx naming rule. */ -/* NOTE: DO NOT Remove these definition. Use later. */ - - /* System Isolation Interface Control. */ -#define SYS_ISO_CTRL REG_SYS_ISO_CTRL - /* System Function Enable. */ -#define SYS_FUNC_EN REG_SYS_FUNC_EN -#define SYS_CLK REG_SYS_CLKR - /* 93C46/93C56 Command Register. */ -#define CR9346 REG_9346CR - /* E-Fuse Control. */ -#define EFUSE_CTRL REG_EFUSE_CTRL - /* E-Fuse Test. */ -#define EFUSE_TEST REG_EFUSE_TEST - /* Media Status register */ -#define MSR (REG_CR + 2) -#define ISR REG_HISR - /* Timing Sync Function Timer Register. */ -#define TSFR REG_TSFTR - - /* MAC ID Register, Offset 0x0050-0x0053 */ -#define MACIDR0 REG_MACID - /* MAC ID Register, Offset 0x0054-0x0055 */ -#define MACIDR4 (REG_MACID + 4) - -#define PBP REG_PBP - - /* Redifine MACID register, to compatible prior ICs. */ -#define IDR0 MACIDR0 -#define IDR4 MACIDR4 - - -/* */ -/* 9. Security Control Registers (Offset: ) */ -/* */ - /* Software write CAM input content */ -#define WCAMI REG_CAMWRITE - /* Software read/write CAM config */ -#define RCAMO REG_CAMREAD -#define CAMDBG REG_CAMDBG - /* Security Configuration Register */ -#define SECR REG_SECCFG - -/* Unused register */ -#define UnusedRegister 0x1BF -#define DCAM UnusedRegister -#define PSR UnusedRegister -#define BBAddr UnusedRegister -#define PhyDataR UnusedRegister - -#define InvalidBBRFValue 0x12345678 - -/* Min Spacing related settings. */ -#define MAX_MSS_DENSITY_2T 0x13 -#define MAX_MSS_DENSITY_1T 0x0A - -/* */ -/* 8192C Cmd9346CR bits (Offset 0xA, 16bit) */ -/* */ - /* EEPROM enable when set 1 */ -#define CmdEEPROM_En BIT(5) - /* System EEPROM select, 0: boot from E-FUSE, - 1: The EEPROM used is 9346 */ -#define CmdEERPOMSEL BIT(4) -#define Cmd9346CR_9356SEL BIT(4) -#define AutoLoadEEPROM (CmdEEPROM_En|CmdEERPOMSEL) -#define AutoLoadEFUSE CmdEEPROM_En - -/* */ -/* 8192C GPIO MUX Configuration Register (offset 0x40, 4 byte) */ -/* */ -#define GPIOSEL_GPIO 0 -#define GPIOSEL_ENBT BIT(5) - -/* */ -/* 8192C GPIO PIN Control Register (offset 0x44, 4 byte) */ -/* */ - /* GPIO pins input value */ -#define GPIO_IN REG_GPIO_PIN_CTRL - /* GPIO pins output value */ -#define GPIO_OUT (REG_GPIO_PIN_CTRL+1) - /* GPIO pins output enable when a bit is set to "1"; - otherwise, input is configured. */ -#define GPIO_IO_SEL (REG_GPIO_PIN_CTRL+2) -#define GPIO_MOD (REG_GPIO_PIN_CTRL+3) - -/* */ -/* 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 - -/* */ -/* 6. Adaptive Control Registers (Offset: 0x0160 - 0x01CF) */ -/* */ -/* */ -/* 8192C Response Rate Set Register (offset 0x181, 24bits) */ -/* */ -#define RRSR_RSC_OFFSET 21 -#define RRSR_SHORT_OFFSET 23 -#define RRSR_RSC_BW_40M 0x600000 -#define RRSR_RSC_UPSUBCHNL 0x400000 -#define RRSR_RSC_LOWSUBCHNL 0x200000 -#define RRSR_SHORT 0x800000 -#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) -#define BRSR_AckShortPmb BIT(23) -/* CCK ACK: use Short Preamble or not */ - -/* */ -/* 8192C BW_OPMODE bits (Offset 0x203, 8bit) */ -/* */ -#define BW_OPMODE_20MHZ BIT(2) -#define BW_OPMODE_5G BIT(1) -#define BW_OPMODE_11J BIT(0) - - -/* */ -/* 8192C CAM Config Setting (offset 0x250, 1 byte) */ -/* */ -#define CAM_VALID BIT(15) -#define CAM_NOTVALID 0x0000 -#define CAM_USEDK BIT(5) - -#define CAM_CONTENT_COUNT 8 - -#define CAM_NONE 0x0 -#define CAM_WEP40 0x01 -#define CAM_TKIP 0x02 -#define CAM_AES 0x04 -#define CAM_WEP104 0x05 - -#define TOTAL_CAM_ENTRY 32 -#define HALF_CAM_ENTRY 16 - -#define CAM_CONFIG_USEDK true -#define CAM_CONFIG_NO_USEDK false - -#define CAM_WRITE BIT(16) -#define CAM_READ 0x00000000 -#define CAM_POLLINIG BIT(31) - -#define SCR_UseDK 0x01 -#define SCR_TxSecEnable 0x02 -#define SCR_RxSecEnable 0x04 - - -/* */ -/* 12. Host Interrupt Status Registers (Offset: 0x0300 - 0x030F) */ -/* */ -/* */ -/* 8190 IMR/ISR bits (offset 0xfd, 8bits) */ -/* */ -#define IMR8190_DISABLED 0x0 -/* IMR DW0 Bit 0-31 */ - -#define IMR_BCNDMAINT6 BIT(31) /* Beacon DMA Interrupt 6 */ -#define IMR_BCNDMAINT5 BIT(30) /* Beacon DMA Interrupt 5 */ -#define IMR_BCNDMAINT4 BIT(29) /* Beacon DMA Interrupt 4 */ -#define IMR_BCNDMAINT3 BIT(28) /* Beacon DMA Interrupt 3 */ -#define IMR_BCNDMAINT2 BIT(27) /* Beacon DMA Interrupt 2 */ -#define IMR_BCNDMAINT1 BIT(26) /* Beacon DMA Interrupt 1 */ -#define IMR_BCNDOK8 BIT(25) /* Beacon Queue DMA OK - Interrupt 8 */ -#define IMR_BCNDOK7 BIT(24) /* Beacon Queue DMA OK - Interrupt 7 */ -#define IMR_BCNDOK6 BIT(23) /* Beacon Queue DMA OK - Interrupt 6 */ -#define IMR_BCNDOK5 BIT(22) /* Beacon Queue DMA OK - Interrupt 5 */ -#define IMR_BCNDOK4 BIT(21) /* Beacon Queue DMA OK - Interrupt 4 */ -#define IMR_BCNDOK3 BIT(20) /* Beacon Queue DMA OK - Interrupt 3 */ -#define IMR_BCNDOK2 BIT(19) /* Beacon Queue DMA OK - Interrupt 2 */ -#define IMR_BCNDOK1 BIT(18) /* Beacon Queue DMA OK - Interrupt 1 */ -#define IMR_TIMEOUT2 BIT(17) /* Timeout interrupt 2 */ -#define IMR_TIMEOUT1 BIT(16) /* Timeout interrupt 1 */ -#define IMR_TXFOVW BIT(15) /* Transmit FIFO Overflow */ -#define IMR_PSTIMEOUT BIT(14) /* Power save time out - interrupt */ -#define IMR_BcnInt BIT(13) /* Beacon DMA Interrupt 0 */ -#define IMR_RXFOVW BIT(12) /* Receive FIFO Overflow */ -#define IMR_RDU BIT(11) /* Receive Descriptor - Unavailable */ -#define IMR_ATIMEND BIT(10) /* For 92C,ATIM Window - End Interrupt */ -#define IMR_BDOK BIT(9) /* Beacon Queue DMA OK - Interrup */ -#define IMR_HIGHDOK BIT(8) /* High Queue DMA OK - Interrupt */ -#define IMR_TBDOK BIT(7) /* Transmit Beacon OK - interrup */ -#define IMR_MGNTDOK BIT(6) /* Management Queue DMA OK - Interrupt */ -#define IMR_TBDER BIT(5) /* For 92C,Transmit Beacon - Error Interrupt */ -#define IMR_BKDOK BIT(4) /* AC_BK DMA OK Interrupt */ -#define IMR_BEDOK BIT(3) /* AC_BE DMA OK Interrupt */ -#define IMR_VIDOK BIT(2) /* AC_VI DMA OK Interrupt */ -#define IMR_VODOK BIT(1) /* AC_VO DMA Interrupt */ -#define IMR_ROK BIT(0) /* Receive DMA OK Interrupt */ - -#define IMR_RX_MASK (IMR_ROK|IMR_RDU|IMR_RXFOVW) -#define IMR_TX_MASK (IMR_VODOK|IMR_VIDOK|IMR_BEDOK| \ - IMR_BKDOK|IMR_MGNTDOK|IMR_HIGHDOK| \ - IMR_BDOK) - -/* 13. Host Interrupt Status Extension Register (Offset: 0x012C-012Eh) */ -#define IMR_BcnInt_E BIT(12) -#define IMR_TXERR BIT(11) -#define IMR_RXERR BIT(10) -#define IMR_C2HCMD BIT(9) -#define IMR_CPWM BIT(8) -/* RSVD [2-7] */ -#define IMR_OCPINT BIT(1) -#define IMR_WLANOFF BIT(0) - - -/* 8192C EEPROM/EFUSE share register definition. */ - -/* 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 0x22 -#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 - -/* For debug */ -#define EEPROM_Default_PID 0x1234 -#define EEPROM_Default_VID 0x5678 -#define EEPROM_Default_CustomerID 0xAB -#define EEPROM_Default_SubCustomerID 0xCD -#define EEPROM_Default_Version 0 - -#define EEPROM_CHANNEL_PLAN_FCC 0x0 -#define EEPROM_CHANNEL_PLAN_IC 0x1 -#define EEPROM_CHANNEL_PLAN_ETSI 0x2 -#define EEPROM_CHANNEL_PLAN_SPAIN 0x3 -#define EEPROM_CHANNEL_PLAN_FRANCE 0x4 -#define EEPROM_CHANNEL_PLAN_MKK 0x5 -#define EEPROM_CHANNEL_PLAN_MKK1 0x6 -#define EEPROM_CHANNEL_PLAN_ISRAEL 0x7 -#define EEPROM_CHANNEL_PLAN_TELEC 0x8 -#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9 -#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA -#define EEPROM_CHANNEL_PLAN_NCC 0xB -#define EEPROM_USB_OPTIONAL1 0xE -#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 - - -#define EEPROM_CID_DEFAULT 0x0 -#define EEPROM_CID_TOSHIBA 0x4 - /* CCX test. By Bruce, 2009-02-25. */ -#define EEPROM_CID_CCX 0x10 -#define EEPROM_CID_QMI 0x0D - /* added by chiyoko for dtm, 20090108 */ -#define EEPROM_CID_WHQL 0xFE - - -#define RTL_EEPROM_ID 0x8129 - -#define SUPPORT_HW_RADIO_DETECT(pHalData) \ - (pHalData->BoardType == BOARD_MINICARD || \ - pHalData->BoardType == BOARD_USB_SOLO || \ - pHalData->BoardType == BOARD_USB_COMBO) - -/* */ -/* EEPROM address for Test chip */ -/* */ -#define EEPROM_TEST_USB_OPT 0x0E -#define EEPROM_TEST_CHIRP_K 0x0F -#define EEPROM_TEST_EP_SETTING 0x0E -#define EEPROM_TEST_USB_PHY 0x10 - - -/* */ -/* EEPROM address for Normal chip */ -/* */ -#define EEPROM_NORMAL_USB_OPT 0x0E -#define EEPROM_NORMAL_CHIRP_K 0x0E /* Changed */ -#define EEPROM_NORMAL_EP_SETTING 0x0F /* Changed */ -#define EEPROM_NORMAL_USB_PHY 0x12 /* Changed */ - -enum { - BOARD_USB_DONGLE = 0, /* USB dongle */ - BOARD_USB_High_PA = 1, /* USB dongle with high power PA */ - BOARD_MINICARD = 2, /* Minicard */ - BOARD_USB_SOLO = 3, /* USB solo-Slim module */ - BOARD_USB_COMBO = 4, /* USB Combo-Slim module */ -}; - -/* Test chip and normal chip common define */ -/* */ -/* EEPROM address for both */ -/* */ -#define EEPROM_ID0 0x00 -#define EEPROM_ID1 0x01 -#define EEPROM_RTK_RSV1 0x02 -#define EEPROM_RTK_RSV2 0x03 -#define EEPROM_RTK_RSV3 0x04 -#define EEPROM_RTK_RSV4 0x05 -#define EEPROM_RTK_RSV5 0x06 -#define EEPROM_DBG_SEL 0x07 -#define EEPROM_RTK_RSV6 0x08 -#define EEPROM_VID 0x0A -#define EEPROM_PID 0x0C - -#define EEPROM_MAC_ADDR 0x16 -#define EEPROM_STRING 0x1C -#define EEPROM_SUBCUSTOMER_ID 0x59 -#define EEPROM_CCK_TX_PWR_INX 0x5A -#define EEPROM_HT40_1S_TX_PWR_INX 0x60 -#define EEPROM_HT40_2S_TX_PWR_INX_DIFF 0x66 -#define EEPROM_HT20_TX_PWR_INX_DIFF 0x69 -#define EEPROM_OFDM_TX_PWR_INX_DIFF 0x6C -#define EEPROM_HT40_MAX_PWR_OFFSET 0x6F -#define EEPROM_HT20_MAX_PWR_OFFSET 0x72 - -#define EEPROM_CHANNEL_PLAN 0x75 -#define EEPROM_TSSI_A 0x76 -#define EEPROM_TSSI_B 0x77 -#define EEPROM_THERMAL_METER 0x78 -#define EEPROM_RF_OPT1 0x79 -#define EEPROM_RF_OPT2 0x7A -#define EEPROM_RF_OPT3 0x7B -#define EEPROM_RF_OPT4 0x7C -#define EEPROM_VERSION 0x7E -#define EEPROM_CUSTOMER_ID 0x7F - - /* 0x0: RTL8188SU, 0x1: RTL8191SU, 0x2: RTL8192SU, 0x3: RTL8191GU */ -#define EEPROM_BoardType 0x54 - /* 0x5C-0x76, Tx Power index. */ -#define EEPROM_TxPwIndex 0x5C - /* Difference of gain index between legacy and high throughput OFDM. */ -#define EEPROM_PwDiff 0x67 - /* CCK Tx Power */ -#define EEPROM_TxPowerCCK 0x5A - -/* 2009/02/09 Cosa Add for SD3 requirement */ - /* HT20 Tx Power Index Difference */ -#define EEPROM_TX_PWR_HT20_DIFF 0x6e - /* HT20<->40 default Tx Power Index Difference */ -#define DEFAULT_HT20_TXPWR_DIFF 2 - /* OFDM Tx Power Index Difference */ -#define EEPROM_TX_PWR_OFDM_DIFF 0x71 - - /* Power diff for channel group */ -#define EEPROM_TxPWRGroup 0x73 - /* Check if power safety is need */ -#define EEPROM_Regulatory 0x79 - - /* 92cu, 0x7E[4] */ -#define EEPROM_BLUETOOTH_COEXIST 0x7E -#define EEPROM_NORMAL_BoardType EEPROM_RF_OPT1 /* 7:5] */ -#define BOARD_TYPE_NORMAL_MASK 0xE0 -#define BOARD_TYPE_TEST_MASK 0x0F - /* BIT0 1 for build-in module, 0 for external dongle */ -#define EEPROM_EASY_REPLACEMENT 0x50 -/* */ -/* EPROM content definitions */ -/* */ -#define OS_LINK_SPEED BIT(5) - -#define BOARD_TYPE_MASK 0xF - -#define BT_COEXISTENCE BIT(4) -#define BT_CO_SHIFT 4 - -#define EP_NUMBER_MASK 0x30 /* bit 4:5 0Eh */ -#define EP_NUMBER_SHIFT 4 - - -#define USB_PHY_PARA_SIZE 5 - - -/* */ -/* EEPROM default value definitions */ -/* */ -/* Use 0xABCD instead of 0x8192 for debug */ -#define EEPROM_DEF_ID_0 0xCD /* Byte 0x00 */ -#define EEPROM_DEF_ID_1 0xAB /* Byte 0x01 */ - -#define EEPROM_DEF_RTK_RSV_A3 0x74 /* Byte 0x03 */ -#define EEPROM_DEF_RTK_RSV_A4 0x6D /* Byte 0x04 */ -#define EEPROM_DEF_RTK_RSV_A8 0xFF /* Byte 0x08 */ - -#define EEPROM_DEF_VID_0 0x0A /* Byte 0x0A */ -#define EEPROM_DEF_VID_1 0x0B - -#define EEPROM_DEF_PID_0 0x92 /* Byte 0x0C */ -#define EEPROM_DEF_PID_1 0x81 - - -#define EEPROM_TEST_DEF_USB_OPT 0x80 /* Byte 0x0E */ -#define EEPROM_NORMAL_DEF_USB_OPT 0x00 /* Byte 0x0E */ - -#define EEPROM_DEF_CHIRPK 0x15 /* Byte 0x0F */ - -#define EEPROM_DEF_USB_PHY_0 0x85 /* Byte 0x10 */ -#define EEPROM_DEF_USB_PHY_1 0x62 /* Byte 0x11 */ -#define EEPROM_DEF_USB_PHY_2 0x9E /* Byte 0x12 */ -#define EEPROM_DEF_USB_PHY_3 0x06 /* Byte 0x13 */ - -#define EEPROM_DEF_TSSI_A 0x09 /* Byte 0x78 */ -#define EEPROM_DEF_TSSI_B 0x09 /* Byte 0x79 */ - - -#define EEPROM_DEF_THERMAL_METER 0x12 /* Byte 0x7A */ - - /* Check if power safety spec is need */ -#define RF_OPTION1 0x79 -#define RF_OPTION2 0x7A -#define RF_OPTION3 0x7B -#define RF_OPTION4 0x7C - - -#define EEPROM_USB_SN BIT(0) -#define EEPROM_USB_REMOTE_WAKEUP BIT(1) -#define EEPROM_USB_DEVICE_PWR BIT(2) -#define EEPROM_EP_NUMBER (BIT(3)|BIT(4)) - -/*=================================================================== -===================================================================== -Here the register defines are for 92C. When the define is as same with 92C, -we will use the 92C's define for the consistency -So the following defines for 92C is not entire!!!!!! -===================================================================== -=====================================================================*/ -/* -Based on Datasheet V33---090401 -Register Summary -Current IOREG MAP -0x0000h ~ 0x00FFh System Configuration (256 Bytes) -0x0100h ~ 0x01FFh MACTOP General Configuration (256 Bytes) -0x0200h ~ 0x027Fh TXDMA Configuration (128 Bytes) -0x0280h ~ 0x02FFh RXDMA Configuration (128 Bytes) -0x0300h ~ 0x03FFh PCIE EMAC Reserved Region (256 Bytes) -0x0400h ~ 0x04FFh Protocol Configuration (256 Bytes) -0x0500h ~ 0x05FFh EDCA Configuration (256 Bytes) -0x0600h ~ 0x07FFh WMAC Configuration (512 Bytes) -0x2000h ~ 0x3FFFh 8051 FW Download Region (8196 Bytes) -*/ - -/* */ -/* 8192C (RCR) Receive Configuration Register (Offset 0x608, 32 bits) */ -/* */ -#define RCR_APPFCS BIT(31) /* WMAC append FCS after payload*/ -#define RCR_APP_MIC BIT(30) -#define RCR_APP_PHYSTS BIT(28) -#define RCR_APP_ICV BIT(29) -#define RCR_APP_PHYST_RXFF BIT(28) -#define RCR_APP_BA_SSN BIT(27) /* Accept BA SSN */ -#define RCR_ENMBID BIT(24) /* Enable Multiple BssId. */ -#define RCR_LSIGEN BIT(23) -#define RCR_MFBEN BIT(22) -#define RCR_HTC_LOC_CTRL BIT(14) /* MFC<--HTC=1 MFC-->HTC=0 */ -#define RCR_AMF BIT(13) /* Accept management type frame */ -#define RCR_ACF BIT(12) /* Accept control type frame */ -#define RCR_ADF BIT(11) /* Accept data type frame */ -#define RCR_AICV BIT(9) /* Accept ICV error packet */ -#define RCR_ACRC32 BIT(8) /* Accept CRC32 error packet */ -#define RCR_CBSSID_BCN BIT(7) /* Accept BSSID match packet - (Rx beacon, probe rsp) */ -#define RCR_CBSSID_DATA BIT(6) /* Accept BSSID match packet - (Data) */ -#define RCR_CBSSID RCR_CBSSID_DATA /* Accept BSSID match - packet */ -#define RCR_APWRMGT BIT(5) /* Accept power management - packet */ -#define RCR_ADD3 BIT(4) /* Accept address 3 match - packet */ -#define RCR_AB BIT(3) /* Accept broadcast packet */ -#define RCR_AM BIT(2) /* Accept multicast packet */ -#define RCR_APM BIT(1) /* Accept physical match packet */ -#define RCR_AAP BIT(0) /* Accept all unicast packet */ -#define RCR_MXDMA_OFFSET 8 -#define RCR_FIFO_OFFSET 13 - - - -/* */ -/* 8192c USB specific Regsiter Offset and Content definition, */ -/* 2009.08.18, added by vivi. for merge 92c and 92C into one driver */ -/* */ -/* define APS_FSMCO 0x0004 same with 92Ce */ -#define RSV_CTRL 0x001C -#define RD_CTRL 0x0524 - -/* */ -/* */ -/* 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_VID 0xFE60 -#define REG_USB_PID 0xFE62 -#define REG_USB_OPTIONAL 0xFE64 -#define REG_USB_CHIRP_K 0xFE65 -#define REG_USB_PHY 0xFE66 -#define REG_USB_MAC_ADDR 0xFE70 - -#define REG_USB_HRPWM 0xFE58 -#define REG_USB_HCPWM 0xFE57 - -#define InvalidBBRFValue 0x12345678 - -/* */ -/* 8192C Regsiter Bit and Content definition */ -/* */ -/* */ -/* */ -/* 0x0000h ~ 0x00FFh System Configuration */ -/* */ -/* */ - -/* 2 SPS0_CTRL */ -#define SW18_FPWM BIT(3) - - -/* 2 SYS_ISO_CTRL */ -#define ISO_MD2PP BIT(0) -#define ISO_UA2USB BIT(1) -#define ISO_UD2CORE BIT(2) -#define ISO_PA2PCIE BIT(3) -#define ISO_PD2CORE BIT(4) -#define ISO_IP2MAC BIT(5) -#define ISO_DIOP BIT(6) -#define ISO_DIOE BIT(7) -#define ISO_EB2CORE BIT(8) -#define ISO_DIOR BIT(9) - -#define PWC_EV25V BIT(14) -#define PWC_EV12V BIT(15) - - -/* 2 SYS_FUNC_EN */ -#define FEN_BBRSTB BIT(0) -#define FEN_BB_GLB_RSTn BIT(1) -#define FEN_USBA BIT(2) -#define FEN_UPLL BIT(3) -#define FEN_USBD BIT(4) -#define FEN_DIO_PCIE BIT(5) -#define FEN_PCIEA BIT(6) -#define FEN_PPLL BIT(7) -#define FEN_PCIED BIT(8) -#define FEN_DIOE BIT(9) -#define FEN_CPUEN BIT(10) -#define FEN_DCORE BIT(11) -#define FEN_ELDR BIT(12) -#define FEN_DIO_RF BIT(13) -#define FEN_HWPDN BIT(14) -#define FEN_MREGEN BIT(15) - -/* 2 APS_FSMCO */ -#define PFM_LDALL BIT(0) -#define PFM_ALDN BIT(1) -#define PFM_LDKP BIT(2) -#define PFM_WOWL BIT(3) -#define EnPDN BIT(4) -#define PDN_PL BIT(5) -#define APFM_ONMAC BIT(8) -#define APFM_OFF BIT(9) -#define APFM_RSM BIT(10) -#define AFSM_HSUS BIT(11) -#define AFSM_PCIE BIT(12) -#define APDM_MAC BIT(13) -#define APDM_HOST BIT(14) -#define APDM_HPDN BIT(15) -#define RDY_MACON BIT(16) -#define SUS_HOST BIT(17) -#define ROP_ALD BIT(20) -#define ROP_PWR BIT(21) -#define ROP_SPS BIT(22) -#define SOP_MRST BIT(25) -#define SOP_FUSE BIT(26) -#define SOP_ABG BIT(27) -#define SOP_AMB BIT(28) -#define SOP_RCK BIT(29) -#define SOP_A8M BIT(30) -#define XOP_BTCK BIT(31) - -/* 2 SYS_CLKR */ -#define ANAD16V_EN BIT(0) -#define ANA8M BIT(1) -#define MACSLP BIT(4) -#define LOADER_CLK_EN BIT(5) -#define _80M_SSC_DIS BIT(7) -#define _80M_SSC_EN_HO BIT(8) -#define PHY_SSC_RSTB BIT(9) -#define SEC_CLK_EN BIT(10) -#define MAC_CLK_EN BIT(11) -#define SYS_CLK_EN BIT(12) -#define RING_CLK_EN BIT(13) - - -/* 2 9346CR */ - - -#define EEDO BIT(0) -#define EEDI BIT(1) -#define EESK BIT(2) -#define EECS BIT(3) -/* define EERPROMSEL BIT(4) */ -/* define EEPROM_EN BIT(5) */ -#define BOOT_FROM_EEPROM BIT(4) -#define EEPROM_EN BIT(5) -#define EEM0 BIT(6) -#define EEM1 BIT(7) - - -/* 2 AFE_MISC */ -#define AFE_BGEN BIT(0) -#define AFE_MBEN BIT(1) -#define MAC_ID_EN BIT(7) - - -/* 2 SPS0_CTRL */ - - -/* 2 SPS_OCP_CFG */ - - -/* 2 RSV_CTRL */ -#define WLOCK_ALL BIT(0) -#define WLOCK_00 BIT(1) -#define WLOCK_04 BIT(2) -#define WLOCK_08 BIT(3) -#define WLOCK_40 BIT(4) -#define R_DIS_PRST_0 BIT(5) -#define R_DIS_PRST_1 BIT(6) -#define LOCK_ALL_EN BIT(7) - -/* 2 RF_CTRL */ -#define RF_EN BIT(0) -#define RF_RSTB BIT(1) -#define RF_SDMRSTB BIT(2) - - - -/* 2 LDOA15_CTRL */ -#define LDA15_EN BIT(0) -#define LDA15_STBY BIT(1) -#define LDA15_OBUF BIT(2) -#define LDA15_REG_VOS BIT(3) -#define _LDA15_VOADJ(x) (((x) & 0x7) << 4) - - - -/* 2 LDOV12D_CTRL */ -#define LDV12_EN BIT(0) -#define LDV12_SDBY BIT(1) -#define LPLDO_HSM BIT(2) -#define LPLDO_LSM_DIS BIT(3) -#define _LDV12_VADJ(x) (((x) & 0xF) << 4) - - -/* 2 AFE_XTAL_CTRL */ -#define XTAL_EN BIT(0) -#define XTAL_BSEL BIT(1) -#define _XTAL_BOSC(x) (((x) & 0x3) << 2) -#define _XTAL_CADJ(x) (((x) & 0xF) << 4) -#define XTAL_GATE_USB BIT(8) -#define _XTAL_USB_DRV(x) (((x) & 0x3) << 9) -#define XTAL_GATE_AFE BIT(11) -#define _XTAL_AFE_DRV(x) (((x) & 0x3) << 12) -#define XTAL_RF_GATE BIT(14) -#define _XTAL_RF_DRV(x) (((x) & 0x3) << 15) -#define XTAL_GATE_DIG BIT(17) -#define _XTAL_DIG_DRV(x) (((x) & 0x3) << 18) -#define XTAL_BT_GATE BIT(20) -#define _XTAL_BT_DRV(x) (((x) & 0x3) << 21) -#define _XTAL_GPIO(x) (((x) & 0x7) << 23) - - -#define CKDLY_AFE BIT(26) -#define CKDLY_USB BIT(27) -#define CKDLY_DIG BIT(28) -#define CKDLY_BT BIT(29) - - -/* 2 AFE_PLL_CTRL */ -#define APLL_EN BIT(0) -#define APLL_320_EN BIT(1) -#define APLL_FREF_SEL BIT(2) -#define APLL_EDGE_SEL BIT(3) -#define APLL_WDOGB BIT(4) -#define APLL_LPFEN BIT(5) - -#define APLL_REF_CLK_13MHZ 0x1 -#define APLL_REF_CLK_19_2MHZ 0x2 -#define APLL_REF_CLK_20MHZ 0x3 -#define APLL_REF_CLK_25MHZ 0x4 -#define APLL_REF_CLK_26MHZ 0x5 -#define APLL_REF_CLK_38_4MHZ 0x6 -#define APLL_REF_CLK_40MHZ 0x7 - -#define APLL_320EN BIT(14) -#define APLL_80EN BIT(15) -#define APLL_1MEN BIT(24) - - -/* 2 EFUSE_CTRL */ -#define ALD_EN BIT(18) -#define EF_PD BIT(19) -#define EF_FLAG BIT(31) - -/* 2 EFUSE_TEST (For RTL8723 partially) */ -#define EF_TRPT BIT(7) - /* 00: Wifi Efuse, 01: BT Efuse0, 10: BT Efuse1, 11: BT Efuse2 */ -#define EF_CELL_SEL (BIT(8)|BIT(9)) -#define LDOE25_EN BIT(31) -#define EFUSE_SEL(x) (((x) & 0x3) << 8) -#define EFUSE_SEL_MASK 0x300 -#define EFUSE_WIFI_SEL_0 0x0 -#define EFUSE_BT_SEL_0 0x1 -#define EFUSE_BT_SEL_1 0x2 -#define EFUSE_BT_SEL_2 0x3 - -#define EFUSE_ACCESS_ON 0x69 /* For RTL8723 only. */ -#define EFUSE_ACCESS_OFF 0x00 /* For RTL8723 only. */ - -/* 2 PWR_DATA */ - -/* 2 CAL_TIMER */ - -/* 2 ACLK_MON */ -#define RSM_EN BIT(0) -#define Timer_EN BIT(4) - - -/* 2 GPIO_MUXCFG */ -#define TRSW0EN BIT(2) -#define TRSW1EN BIT(3) -#define EROM_EN BIT(4) -#define EnBT BIT(5) -#define EnUart BIT(8) -#define Uart_910 BIT(9) -#define EnPMAC BIT(10) -#define SIC_SWRST BIT(11) -#define EnSIC BIT(12) -#define SIC_23 BIT(13) -#define EnHDP BIT(14) -#define SIC_LBK BIT(15) - -/* 2 GPIO_PIN_CTRL */ - -/* GPIO BIT */ -#define HAL_8192C_HW_GPIO_WPS_BIT BIT(2) - -/* 2 GPIO_INTM */ - -/* 2 LEDCFG */ -#define LED0PL BIT(4) -#define LED0DIS BIT(7) -#define LED1DIS BIT(15) -#define LED1PL BIT(12) - -#define SECCAM_CLR BIT(30) - - -/* 2 FSIMR */ - -/* 2 FSISR */ - - -/* 2 8051FWDL */ -/* 2 MCUFWDL */ -#define MCUFWDL_EN BIT(0) -#define MCUFWDL_RDY BIT(1) -#define FWDL_ChkSum_rpt BIT(2) -#define MACINI_RDY BIT(3) -#define BBINI_RDY BIT(4) -#define RFINI_RDY BIT(5) -#define WINTINI_RDY BIT(6) -#define CPRST BIT(23) - -/* 2REG_HPON_FSM */ -#define BOND92CE_1T2R_CFG BIT(22) - - -/* 2 REG_SYS_CFG */ -#define XCLK_VLD BIT(0) -#define ACLK_VLD BIT(1) -#define UCLK_VLD BIT(2) -#define PCLK_VLD BIT(3) -#define PCIRSTB BIT(4) -#define V15_VLD BIT(5) -#define TRP_B15V_EN BIT(7) -#define SIC_IDLE BIT(8) -#define BD_MAC2 BIT(9) -#define BD_MAC1 BIT(10) -#define IC_MACPHY_MODE BIT(11) -#define CHIP_VER (BIT(12)|BIT(13)|BIT(14)|BIT(15)) -#define BT_FUNC BIT(16) -#define VENDOR_ID BIT(19) -#define PAD_HWPD_IDN BIT(22) -#define TRP_VAUX_EN BIT(23) -#define TRP_BT_EN BIT(24) -#define BD_PKG_SEL BIT(25) -#define BD_HCI_SEL BIT(26) -#define TYPE_ID BIT(27) - -#define CHIP_VER_RTL_MASK 0xF000 /* Bit 12 ~ 15 */ -#define CHIP_VER_RTL_SHIFT 12 - -/* 2REG_GPIO_OUTSTS (For RTL8723 only) */ -#define EFS_HCI_SEL (BIT(0)|BIT(1)) -#define PAD_HCI_SEL (BIT(2)|BIT(3)) -#define HCI_SEL (BIT(4)|BIT(5)) -#define PKG_SEL_HCI BIT(6) -#define FEN_GPS BIT(7) -#define FEN_BT BIT(8) -#define FEN_WL BIT(9) -#define FEN_PCI BIT(10) -#define FEN_USB BIT(11) -#define BTRF_HWPDN_N BIT(12) -#define WLRF_HWPDN_N BIT(13) -#define PDN_BT_N BIT(14) -#define PDN_GPS_N BIT(15) -#define BT_CTL_HWPDN BIT(16) -#define GPS_CTL_HWPDN BIT(17) -#define PPHY_SUSB BIT(20) -#define UPHY_SUSB BIT(21) -#define PCI_SUSEN BIT(22) -#define USB_SUSEN BIT(23) -#define RF_RL_ID (BIT(31)|BIT(30)|BIT(29)|BIT(28)) - -/* */ -/* */ -/* 0x0100h ~ 0x01FFh MACTOP General Configuration */ -/* */ -/* */ - - -/* 2 Function Enable Registers */ -/* 2 CR */ - -#define REG_LBMODE (REG_CR + 3) - - -#define HCI_TXDMA_EN BIT(0) -#define HCI_RXDMA_EN BIT(1) -#define TXDMA_EN BIT(2) -#define RXDMA_EN BIT(3) -#define PROTOCOL_EN BIT(4) -#define SCHEDULE_EN BIT(5) -#define MACTXEN BIT(6) -#define MACRXEN BIT(7) -#define ENSWBCN BIT(8) -#define ENSEC BIT(9) - -#define _LBMODE(x) (((x) & 0xF) << 24) -#define MASK_LBMODE 0xF000000 -#define LOOPBACK_NORMAL 0x0 -#define LOOPBACK_IMMEDIATELY 0xB -#define LOOPBACK_MAC_DELAY 0x3 -#define LOOPBACK_PHY 0x1 -#define LOOPBACK_DMA 0x7 - - -/* 2 PBP - Page Size Register */ -#define GET_RX_PAGE_SIZE(value) ((value) & 0xF) -#define GET_TX_PAGE_SIZE(value) (((value) & 0xF0) >> 4) -#define _PSRX_MASK 0xF -#define _PSTX_MASK 0xF0 -#define _PSRX(x) (x) -#define _PSTX(x) ((x) << 4) - -#define PBP_64 0x0 -#define PBP_128 0x1 -#define PBP_256 0x2 -#define PBP_512 0x3 -#define PBP_1024 0x4 - - -/* 2 TX/RXDMA */ -#define RXDMA_ARBBW_EN BIT(0) -#define RXSHFT_EN BIT(1) -#define RXDMA_AGG_EN BIT(2) -#define QS_VO_QUEUE BIT(8) -#define QS_VI_QUEUE BIT(9) -#define QS_BE_QUEUE BIT(10) -#define QS_BK_QUEUE BIT(11) -#define QS_MANAGER_QUEUE BIT(12) -#define QS_HIGH_QUEUE BIT(13) - -#define HQSEL_VOQ BIT(0) -#define HQSEL_VIQ BIT(1) -#define HQSEL_BEQ BIT(2) -#define HQSEL_BKQ BIT(3) -#define HQSEL_MGTQ BIT(4) -#define HQSEL_HIQ BIT(5) - -/* For normal driver, 0x10C */ -#define _TXDMA_HIQ_MAP(x) (((x)&0x3) << 14) -#define _TXDMA_MGQ_MAP(x) (((x)&0x3) << 12) -#define _TXDMA_BKQ_MAP(x) (((x)&0x3) << 10) -#define _TXDMA_BEQ_MAP(x) (((x)&0x3) << 8) -#define _TXDMA_VIQ_MAP(x) (((x)&0x3) << 6) -#define _TXDMA_VOQ_MAP(x) (((x)&0x3) << 4) - -#define QUEUE_LOW 1 -#define QUEUE_NORMAL 2 -#define QUEUE_HIGH 3 - - - -/* 2 TRXFF_BNDY */ - - -/* 2 LLT_INIT */ -#define _LLT_NO_ACTIVE 0x0 -#define _LLT_WRITE_ACCESS 0x1 -#define _LLT_READ_ACCESS 0x2 - -#define _LLT_INIT_DATA(x) ((x) & 0xFF) -#define _LLT_INIT_ADDR(x) (((x) & 0xFF) << 8) -#define _LLT_OP(x) (((x) & 0x3) << 30) -#define _LLT_OP_VALUE(x) (((x) >> 30) & 0x3) - - -/* 2 BB_ACCESS_CTRL */ -#define BB_WRITE_READ_MASK (BIT(31) | BIT(30)) -#define BB_WRITE_EN BIT(30) -#define BB_READ_EN BIT(31) -/* define BB_ADDR_MASK 0xFFF */ -/* define _BB_ADDR(x) ((x) & BB_ADDR_MASK) */ - -/* */ -/* */ -/* 0x0200h ~ 0x027Fh TXDMA Configuration */ -/* */ -/* */ -/* 2 RQPN */ -#define _HPQ(x) ((x) & 0xFF) -#define _LPQ(x) (((x) & 0xFF) << 8) -#define _PUBQ(x) (((x) & 0xFF) << 16) - /* NOTE: in RQPN_NPQ register */ -#define _NPQ(x) ((x) & 0xFF) - - -#define HPQ_PUBLIC_DIS BIT(24) -#define LPQ_PUBLIC_DIS BIT(25) -#define LD_RQPN BIT(31) - - -/* 2 TDECTRL */ -#define BCN_VALID BIT(16) -#define BCN_HEAD(x) (((x) & 0xFF) << 8) -#define BCN_HEAD_MASK 0xFF00 - -/* 2 TDECTL */ -#define BLK_DESC_NUM_SHIFT 4 -#define BLK_DESC_NUM_MASK 0xF - - -/* 2 TXDMA_OFFSET_CHK */ -#define DROP_DATA_EN BIT(9) - -/* */ -/* */ -/* 0x0400h ~ 0x047Fh Protocol Configuration */ -/* */ -/* */ -/* 2 FWHW_TXQ_CTRL */ -#define EN_AMPDU_RTY_NEW BIT(7) - -/* 2 INIRTSMCS_SEL */ -#define _INIRTSMCS_SEL(x) ((x) & 0x3F) - - -/* 2 SPEC SIFS */ -#define _SPEC_SIFS_CCK(x) ((x) & 0xFF) -#define _SPEC_SIFS_OFDM(x) (((x) & 0xFF) << 8) - - -/* 2 RRSR */ - -#define RATE_REG_BITMAP_ALL 0xFFFFF - -#define _RRSC_BITMAP(x) ((x) & 0xFFFFF) - -#define _RRSR_RSC(x) (((x) & 0x3) << 21) -#define RRSR_RSC_RESERVED 0x0 -#define RRSR_RSC_UPPER_SUBCHANNEL 0x1 -#define RRSR_RSC_LOWER_SUBCHANNEL 0x2 -#define RRSR_RSC_DUPLICATE_MODE 0x3 - - -/* 2 ARFR */ -#define USE_SHORT_G1 BIT(20) - -/* 2 AGGLEN_LMT_L */ -#define _AGGLMT_MCS0(x) ((x) & 0xF) -#define _AGGLMT_MCS1(x) (((x) & 0xF) << 4) -#define _AGGLMT_MCS2(x) (((x) & 0xF) << 8) -#define _AGGLMT_MCS3(x) (((x) & 0xF) << 12) -#define _AGGLMT_MCS4(x) (((x) & 0xF) << 16) -#define _AGGLMT_MCS5(x) (((x) & 0xF) << 20) -#define _AGGLMT_MCS6(x) (((x) & 0xF) << 24) -#define _AGGLMT_MCS7(x) (((x) & 0xF) << 28) - - -/* 2 RL */ -#define RETRY_LIMIT_SHORT_SHIFT 8 -#define RETRY_LIMIT_LONG_SHIFT 0 - - -/* 2 DARFRC */ -#define _DARF_RC1(x) ((x) & 0x1F) -#define _DARF_RC2(x) (((x) & 0x1F) << 8) -#define _DARF_RC3(x) (((x) & 0x1F) << 16) -#define _DARF_RC4(x) (((x) & 0x1F) << 24) -/* NOTE: shift starting from address (DARFRC + 4) */ -#define _DARF_RC5(x) ((x) & 0x1F) -#define _DARF_RC6(x) (((x) & 0x1F) << 8) -#define _DARF_RC7(x) (((x) & 0x1F) << 16) -#define _DARF_RC8(x) (((x) & 0x1F) << 24) - - -/* 2 RARFRC */ -#define _RARF_RC1(x) ((x) & 0x1F) -#define _RARF_RC2(x) (((x) & 0x1F) << 8) -#define _RARF_RC3(x) (((x) & 0x1F) << 16) -#define _RARF_RC4(x) (((x) & 0x1F) << 24) -/* NOTE: shift starting from address (RARFRC + 4) */ -#define _RARF_RC5(x) ((x) & 0x1F) -#define _RARF_RC6(x) (((x) & 0x1F) << 8) -#define _RARF_RC7(x) (((x) & 0x1F) << 16) -#define _RARF_RC8(x) (((x) & 0x1F) << 24) - - -/* */ -/* */ -/* 0x0500h ~ 0x05FFh EDCA Configuration */ -/* */ -/* */ - - - -/* 2 EDCA setting */ -#define AC_PARAM_TXOP_LIMIT_OFFSET 16 -#define AC_PARAM_ECW_MAX_OFFSET 12 -#define AC_PARAM_ECW_MIN_OFFSET 8 -#define AC_PARAM_AIFS_OFFSET 0 - - -/* 2 EDCA_VO_PARAM */ -#define _AIFS(x) (x) -#define _ECW_MAX_MIN(x) ((x) << 8) -#define _TXOP_LIMIT(x) ((x) << 16) - - -#define _BCNIFS(x) ((x) & 0xFF) -#define _BCNECW(x) (((x) & 0xF))<< 8) - - -#define _LRL(x) ((x) & 0x3F) -#define _SRL(x) (((x) & 0x3F) << 8) - - -/* 2 SIFS_CCK */ -#define _SIFS_CCK_CTX(x) ((x) & 0xFF) -#define _SIFS_CCK_TRX(x) (((x) & 0xFF) << 8); - - -/* 2 SIFS_OFDM */ -#define _SIFS_OFDM_CTX(x) ((x) & 0xFF) -#define _SIFS_OFDM_TRX(x) (((x) & 0xFF) << 8); - - -/* 2 TBTT PROHIBIT */ -#define _TBTT_PROHIBIT_HOLD(x) (((x) & 0xFF) << 8) - - -/* 2 REG_RD_CTRL */ -#define DIS_EDCA_CNT_DWN BIT(11) - - -/* 2 BCN_CTRL */ -#define EN_MBSSID BIT(1) -#define EN_TXBCN_RPT BIT(2) -#define EN_BCN_FUNCTION BIT(3) -#define DIS_TSF_UPDATE BIT(3) - -/* The same function but different bit field. */ -#define DIS_TSF_UDT0_NORMAL_CHIP BIT(4) -#define DIS_TSF_UDT0_TEST_CHIP BIT(5) - -/* 2 ACMHWCTRL */ -#define AcmHw_HwEn BIT(0) -#define AcmHw_BeqEn BIT(1) -#define AcmHw_ViqEn BIT(2) -#define AcmHw_VoqEn BIT(3) -#define AcmHw_BeqStatus BIT(4) -#define AcmHw_ViqStatus BIT(5) -#define AcmHw_VoqStatus BIT(6) - - - -/* */ -/* */ -/* 0x0600h ~ 0x07FFh WMAC Configuration */ -/* */ -/* */ - -/* 2 APSD_CTRL */ -#define APSDOFF BIT(6) -#define APSDOFF_STATUS BIT(7) - - -/* 2 BWOPMODE */ -#define BW_20MHZ BIT(2) - - -#define RATE_BITMAP_ALL 0xFFFFF - -/* Only use CCK 1M rate for ACK */ -#define RATE_RRSR_CCK_ONLY_1M 0xFFFF1 - -/* 2 TCR */ -#define TSFRST BIT(0) -#define DIS_GCLK BIT(1) -#define PAD_SEL BIT(2) -#define PWR_ST BIT(6) -#define PWRBIT_OW_EN BIT(7) -#define ACRC BIT(8) -#define CFENDFORM BIT(9) -#define ICV BIT(10) - - - -/* 2 RCR */ -#define AAP BIT(0) -#define APM BIT(1) -#define AM BIT(2) -#define AB BIT(3) -#define ADD3 BIT(4) -#define APWRMGT BIT(5) -#define CBSSID BIT(6) -#define CBSSID_BCN BIT(7) -#define ACRC32 BIT(8) -#define AICV BIT(9) -#define ADF BIT(11) -#define ACF BIT(12) -#define AMF BIT(13) -#define HTC_LOC_CTRL BIT(14) -#define UC_DATA_EN BIT(16) -#define BM_DATA_EN BIT(17) -#define MFBEN BIT(22) -#define LSIGEN BIT(23) -#define EnMBID BIT(24) -#define APP_BASSN BIT(27) -#define APP_PHYSTS BIT(28) -#define APP_ICV BIT(29) -#define APP_MIC BIT(30) -#define APP_FCS BIT(31) - -/* 2 RX_PKT_LIMIT */ - -/* 2 RX_DLK_TIME */ - -/* 2 MBIDCAMCFG */ - - - -/* 2 AMPDU_MIN_SPACE */ -#define _MIN_SPACE(x) ((x) & 0x7) -#define _SHORT_GI_PADDING(x) (((x) & 0x1F) << 3) - - -/* 2 RXERR_RPT */ -#define RXERR_TYPE_OFDM_PPDU 0 -#define RXERR_TYPE_OFDMfalse_ALARM 1 -#define RXERR_TYPE_OFDM_MPDU_OK 2 -#define RXERR_TYPE_OFDM_MPDU_FAIL 3 -#define RXERR_TYPE_CCK_PPDU 4 -#define RXERR_TYPE_CCKfalse_ALARM 5 -#define RXERR_TYPE_CCK_MPDU_OK 6 -#define RXERR_TYPE_CCK_MPDU_FAIL 7 -#define RXERR_TYPE_HT_PPDU 8 -#define RXERR_TYPE_HTfalse_ALARM 9 -#define RXERR_TYPE_HT_MPDU_TOTAL 10 -#define RXERR_TYPE_HT_MPDU_OK 11 -#define RXERR_TYPE_HT_MPDU_FAIL 12 -#define RXERR_TYPE_RX_FULL_DROP 15 - -#define RXERR_COUNTER_MASK 0xFFFFF -#define RXERR_RPT_RST BIT(27) -#define _RXERR_RPT_SEL(type) ((type) << 28) - - -/* 2 SECCFG */ -#define SCR_TxUseDK BIT(0) /* Force Tx Use Default Key */ -#define SCR_RxUseDK BIT(1) /* Force Rx Use Default Key */ -#define SCR_TxEncEnable BIT(2) /* Enable Tx Encryption */ -#define SCR_RxDecEnable BIT(3) /* Enable Rx Decryption */ -#define SCR_SKByA2 BIT(4) /* Search kEY BY A2 */ -#define SCR_NoSKMC BIT(5) /* No Key Search Multicast */ - - - -/* */ -/* */ -/* 0xFE00h ~ 0xFE55h USB Configuration */ -/* */ -/* */ - -/* 2 USB Information (0xFE17) */ -#define USB_IS_HIGH_SPEED 0 -#define USB_IS_FULL_SPEED 1 -#define USB_SPEED_MASK BIT(5) - -#define USB_NORMAL_SIE_EP_MASK 0xF -#define USB_NORMAL_SIE_EP_SHIFT 4 - -#define USB_TEST_EP_MASK 0x30 -#define USB_TEST_EP_SHIFT 4 - -/* 2 Special Option */ -#define USB_AGG_EN BIT(3) - - -/* 2REG_C2HEVT_CLEAR */ - /* Set by driver and notify FW that the driver has read the - C2H command message */ -#define C2H_EVT_HOST_CLOSE 0x00 - /* Set by FW indicating that FW had set the C2H command message - and it's not yet read by driver. */ -#define C2H_EVT_FW_CLOSE 0xFF - - -/* 2REG_MULTI_FUNC_CTRL(For RTL8723 Only) */ - /* Enable GPIO[9] as WiFi HW PDn source */ -#define WL_HWPDN_EN BIT(0) - /* WiFi HW PDn polarity control */ -#define WL_HWPDN_SL BIT(1) - /* WiFi function enable */ -#define WL_FUNC_EN BIT(2) - /* Enable GPIO[9] as WiFi RF HW PDn source */ -#define WL_HWROF_EN BIT(3) - /* Enable GPIO[11] as BT HW PDn source */ -#define BT_HWPDN_EN BIT(16) - /* BT HW PDn polarity control */ -#define BT_HWPDN_SL BIT(17) - /* BT function enable */ -#define BT_FUNC_EN BIT(18) - /* Enable GPIO[11] as BT/GPS RF HW PDn source */ -#define BT_HWROF_EN BIT(19) - /* Enable GPIO[10] as GPS HW PDn source */ -#define GPS_HWPDN_EN BIT(20) - /* GPS HW PDn polarity control */ -#define GPS_HWPDN_SL BIT(21) - /* 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, said by Tim. */ - -/* */ -/* General definitions */ -/* */ - -#define LAST_ENTRY_OF_TX_PKT_BUFFER 255 - -#define POLLING_LLT_THRESHOLD 20 -#define POLLING_READY_TIMEOUT_COUNT 1000 - -/* Min Spacing related settings. */ -#define MAX_MSS_DENSITY_2T 0x13 -#define MAX_MSS_DENSITY_1T 0x0A - -/* */ -/* 8723A Regsiter offset definition */ -/* */ -#define HAL_8723A_NAV_UPPER_UNIT 128 /* micro-second */ - -/* */ -/* */ -/* 0x0000h ~ 0x00FFh System Configuration */ -/* */ -/* */ -#define REG_SYSON_REG_LOCK 0x001C - - -/* */ -/* */ -/* 0x0100h ~ 0x01FFh MACTOP General Configuration */ -/* */ -/* */ -#define REG_FTIMR 0x0138 - - -/* */ -/* */ -/* 0x0200h ~ 0x027Fh TXDMA Configuration */ -/* */ -/* */ - - -/* */ -/* */ -/* 0x0280h ~ 0x02FFh RXDMA Configuration */ -/* */ -/* */ - - -/* */ -/* */ -/* 0x0300h ~ 0x03FFh PCIe */ -/* */ -/* */ - - -/* */ -/* */ -/* 0x0400h ~ 0x047Fh Protocol Configuration */ -/* */ -/* */ -#define REG_EARLY_MODE_CONTROL 0x4D0 - - -/* */ -/* */ -/* 0x0500h ~ 0x05FFh EDCA Configuration */ -/* */ -/* */ - -/* 2 BCN_CTRL */ -#define DIS_ATIM BIT(0) -#define DIS_BCNQ_SUB BIT(1) -#define DIS_TSF_UDT BIT(4) - - -/* */ -/* */ -/* 0x0600h ~ 0x07FFh WMAC Configuration */ -/* */ -/* */ -/* */ -/* Note: */ -/* The NAV upper value is very important to WiFi 11n 5.2.3 NAV test. - * The default value is always too small, but the WiFi TestPlan test - * by 25,000 microseconds of NAV through sending CTS in the air. We - * must update this value greater than 25,000 microseconds to pass the - * item. -* The offset of NAV_UPPER in 8192C Spec is incorrect, and the offset -* should be 0x0652. Commented by SD1 Scott. */ -/* By Bruce, 2011-07-18. */ -/* */ -#define REG_NAV_UPPER 0x0652 /* unit of 128 */ - - -/* */ -/* 8723 Regsiter Bit and Content definition */ -/* */ - -/* */ -/* */ -/* 0x0000h ~ 0x00FFh System Configuration */ -/* */ -/* */ - -/* 2 SPS0_CTRL */ - -/* 2 SYS_ISO_CTRL */ - -/* 2 SYS_FUNC_EN */ - -/* 2 APS_FSMCO */ -#define EN_WLON BIT(16) - -/* 2 SYS_CLKR */ - -/* 2 9346CR */ - -/* 2 AFE_MISC */ - -/* 2 SPS0_CTRL */ - -/* 2 SPS_OCP_CFG */ - -/* 2 SYSON_REG_LOCK */ -#define WLOCK_ALL BIT(0) -#define WLOCK_00 BIT(1) -#define WLOCK_04 BIT(2) -#define WLOCK_08 BIT(3) -#define WLOCK_40 BIT(4) -#define WLOCK_1C_B6 BIT(5) -#define R_DIS_PRST_1 BIT(6) -#define LOCK_ALL_EN BIT(7) - -/* 2 RF_CTRL */ - -/* 2 LDOA15_CTRL */ - -/* 2 LDOV12D_CTRL */ - -/* 2 AFE_XTAL_CTRL */ - -/* 2 AFE_PLL_CTRL */ - -/* 2 EFUSE_CTRL */ - -/* 2 EFUSE_TEST (For RTL8723 partially) */ - -/* 2 PWR_DATA */ - -/* 2 CAL_TIMER */ - -/* 2 ACLK_MON */ - -/* 2 GPIO_MUXCFG */ - -/* 2 GPIO_PIN_CTRL */ - -/* 2 GPIO_INTM */ - -/* 2 LEDCFG */ - -/* 2 FSIMR */ - -/* 2 FSISR */ - -/* 2 HSIMR */ -/* 8723 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_PDNINT_EN BIT(7) -#define HSIMR_GPIO9_INT_EN BIT(25) - -/* 2 HSISR */ -/* 8723 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 BIT(6) -#define HSISR_PDNINT BIT(7) -#define HSISR_GPIO9_INT BIT(25) - -/* interrupt mask which needs to clear */ -#define MASK_HSISR_CLEAR (HSISR_GPIO12_0_INT | \ - HSISR_SPS_OCP_INT | \ - HSISR_RON_INT | \ - HSISR_PDNINT | \ - HSISR_GPIO9_INT) - -/* 2 MCUFWDL */ -#define RAM_DL_SEL BIT(7) /* 1:RAM, 0:ROM */ - -/* 2 HPON_FSM */ - -/* 2 SYS_CFG */ -#define RTL_ID BIT(23) /* TestChip ID, - 1:Test(RLE); 0:MP(RL) */ -#define SPS_SEL BIT(24) /* 1:LDO regulator mode; - 0:Switching regulator mode*/ - - -/* */ -/* */ -/* 0x0100h ~ 0x01FFh MACTOP General Configuration */ -/* */ -/* */ - -/* 2 Function Enable Registers */ - -/* 2 CR */ -#define CALTMR_EN BIT(10) - -/* 2 PBP - Page Size Register */ - -/* 2 TX/RXDMA */ - -/* 2 TRXFF_BNDY */ - -/* 2 LLT_INIT */ - -/* 2 BB_ACCESS_CTRL */ - - -/* */ -/* */ -/* 0x0200h ~ 0x027Fh TXDMA Configuration */ -/* */ -/* */ - -/* 2 RQPN */ - -/* 2 TDECTRL */ - -/* 2 TDECTL */ - -/* 2 TXDMA_OFFSET_CHK */ - - -/* */ -/* */ -/* 0x0400h ~ 0x047Fh Protocol Configuration */ -/* */ -/* */ - -/* 2 FWHW_TXQ_CTRL */ - -/* 2 INIRTSMCS_SEL */ - -/* 2 SPEC SIFS */ - -/* 2 RRSR */ - -/* 2 ARFR */ - -/* 2 AGGLEN_LMT_L */ - -/* 2 RL */ - -/* 2 DARFRC */ - -/* 2 RARFRC */ - - -/* */ -/* */ -/* 0x0500h ~ 0x05FFh EDCA Configuration */ -/* */ -/* */ - -/* 2 EDCA setting */ - -/* 2 EDCA_VO_PARAM */ - -/* 2 SIFS_CCK */ - -/* 2 SIFS_OFDM */ - -/* 2 TBTT PROHIBIT */ - -/* 2 REG_RD_CTRL */ - -/* 2 BCN_CTRL */ - -/* 2 ACMHWCTRL */ - - -/* */ -/* */ -/* 0x0600h ~ 0x07FFh WMAC Configuration */ -/* */ -/* */ - -/* 2 APSD_CTRL */ - -/* 2 BWOPMODE */ - -/* 2 TCR */ - -/* 2 RCR */ - -/* 2 RX_PKT_LIMIT */ - -/* 2 RX_DLK_TIME */ - -/* 2 MBIDCAMCFG */ - -/* 2 AMPDU_MIN_SPACE */ - -/* 2 RXERR_RPT */ - -/* 2 SECCFG */ - - -/* */ -/* */ -/* 0xFE00h ~ 0xFE55h RTL8723 SDIO Configuration */ -/* */ -/* */ - -/* I/O bus domain address mapping */ -#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 WLAN_IOREG_MSK 0x7FFF -#define WLAN_FIFO_MSK 0x1FFF /* Aggregation Length[12:0] */ -#define WLAN_RX0FF_MSK 0x0003 - -#define WLAN_RX0FF_DEVICE_ID 7 /* 0b[16], 111b[15:13] */ -#define WLAN_IOREG_DEVICE_ID 8 /* 1b[16] */ - -/* 8723 EFUSE */ -#define HWSET_MAX_SIZE 256 - - -/* USB interrupt */ -#define UHIMR_TIMEOUT2 BIT(31) -#define UHIMR_TIMEOUT1 BIT(30) -#define UHIMR_PSTIMEOUT BIT(29) -#define UHIMR_GTINT4 BIT(28) -#define UHIMR_GTINT3 BIT(27) -#define UHIMR_TXBCNERR BIT(26) -#define UHIMR_TXBCNOK BIT(25) -#define UHIMR_TSF_BIT32_TOGGLE BIT(24) -#define UHIMR_BCNDMAINT3 BIT(23) -#define UHIMR_BCNDMAINT2 BIT(22) -#define UHIMR_BCNDMAINT1 BIT(21) -#define UHIMR_BCNDMAINT0 BIT(20) -#define UHIMR_BCNDOK3 BIT(19) -#define UHIMR_BCNDOK2 BIT(18) -#define UHIMR_BCNDOK1 BIT(17) -#define UHIMR_BCNDOK0 BIT(16) -#define UHIMR_HSISR_IND BIT(15) -#define UHIMR_BCNDMAINT_E BIT(14) -/* RSVD BIT(13) */ -#define UHIMR_CTW_END BIT(12) -/* RSVD BIT(11) */ -#define UHIMR_C2HCMD BIT(10) -#define UHIMR_CPWM2 BIT(9) -#define UHIMR_CPWM BIT(8) -#define UHIMR_HIGHDOK BIT(7) /* High Queue DMA OK - Interrupt */ -#define UHIMR_MGNTDOK BIT(6) /* Management Queue DMA OK - Interrupt */ -#define UHIMR_BKDOK BIT(5) /* AC_BK DMA OK Interrupt */ -#define UHIMR_BEDOK BIT(4) /* AC_BE DMA OK Interrupt */ -#define UHIMR_VIDOK BIT(3) /* AC_VI DMA OK Interrupt */ -#define UHIMR_VODOK BIT(2) /* AC_VO DMA Interrupt */ -#define UHIMR_RDU BIT(1) /* Receive Descriptor - Unavailable */ -#define UHIMR_ROK BIT(0) /* Receive DMA OK Interrupt */ - -/* USB Host Interrupt Status Extension bit */ -#define UHIMR_BCNDMAINT7 BIT(23) -#define UHIMR_BCNDMAINT6 BIT(22) -#define UHIMR_BCNDMAINT5 BIT(21) -#define UHIMR_BCNDMAINT4 BIT(20) -#define UHIMR_BCNDOK7 BIT(19) -#define UHIMR_BCNDOK6 BIT(18) -#define UHIMR_BCNDOK5 BIT(17) -#define UHIMR_BCNDOK4 BIT(16) -/* bit14-15: RSVD */ -#define UHIMR_ATIMEND_E BIT(13) -#define UHIMR_ATIMEND BIT(12) -#define UHIMR_TXERR BIT(11) -#define UHIMR_RXERR BIT(10) -#define UHIMR_TXFOVW BIT(9) -#define UHIMR_RXFOVW BIT(8) -/* bit2-7: RSVD */ -#define UHIMR_OCPINT BIT(1) -/* bit0: RSVD */ - -#define REG_USB_HIMR 0xFE38 -#define REG_USB_HIMRE 0xFE3C -#define REG_USB_HISR 0xFE78 -#define REG_USB_HISRE 0xFE7C - -#define USB_INTR_CPWM_OFFSET 16 -#define USB_INTR_CONTENT_HISR_OFFSET 48 -#define USB_INTR_CONTENT_HISRE_OFFSET 52 -#define USB_INTR_CONTENT_LENGTH 56 -#define USB_C2H_CMDID_OFFSET 0 -#define USB_C2H_SEQ_OFFSET 1 -#define USB_C2H_EVENT_OFFSET 2 -/* */ -/* General definitions */ -/* */ - -#endif diff --git a/drivers/staging/rtl8723au/include/rtl8723a_sreset.h b/drivers/staging/rtl8723au/include/rtl8723a_sreset.h deleted file mode 100644 index 6197910..0000000 --- a/drivers/staging/rtl8723au/include/rtl8723a_sreset.h +++ /dev/null @@ -1,24 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef _RTL8723A_SRESET_H_ -#define _RTL8723A_SRESET_H_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <rtw_sreset.h> - -void rtl8723a_sreset_xmit_status_check(struct rtw_adapter *padapter); - -#endif diff --git a/drivers/staging/rtl8723au/include/rtl8723a_xmit.h b/drivers/staging/rtl8723au/include/rtl8723a_xmit.h deleted file mode 100644 index 7db29f4..0000000 --- a/drivers/staging/rtl8723au/include/rtl8723a_xmit.h +++ /dev/null @@ -1,225 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __RTL8723A_XMIT_H__ -#define __RTL8723A_XMIT_H__ - -/* */ -/* Queue Select Value in TxDesc */ -/* */ -#define QSLT_BK 0x2/* 0x01 */ -#define QSLT_BE 0x0 -#define QSLT_VI 0x5/* 0x4 */ -#define QSLT_VO 0x7/* 0x6 */ -#define QSLT_BEACON 0x10 -#define QSLT_HIGH 0x11 -#define QSLT_MGNT 0x12 -#define QSLT_CMD 0x13 - -/* */ -/* defined for TX DESC Operation */ -/* */ - -#define MAX_TID (15) - -/* OFFSET 0 */ -#define OFFSET_SZ 0 -#define OFFSET_SHT 16 -#define BMC BIT(24) -#define LSG BIT(26) -#define FSG BIT(27) -#define OWN BIT(31) - - -/* OFFSET 4 */ -#define PKT_OFFSET_SZ 0 -#define BK BIT(6) -#define QSEL_SHT 8 -#define Rate_ID_SHT 16 -#define NAVUSEHDR BIT(20) -#define PKT_OFFSET_SHT 26 -#define HWPC BIT(31) - -/* OFFSET 8 */ -#define AGG_EN BIT(29) - -/* OFFSET 12 */ -#define SEQ_SHT 16 - -/* OFFSET 16 */ -#define QoS BIT(6) -#define HW_SEQ_EN BIT(7) -#define USERATE BIT(8) -#define DISDATAFB BIT(10) -#define DATA_SHORT BIT(24) -#define DATA_BW BIT(25) - -/* OFFSET 20 */ -#define SGI BIT(6) - -struct txdesc_8723a { - u32 pktlen:16; - u32 offset:8; - u32 bmc:1; - u32 htc:1; - u32 ls:1; - u32 fs:1; - u32 linip:1; - u32 noacm:1; - u32 gf:1; - u32 own:1; - - u32 macid:5; - u32 agg_en:1; - u32 bk:1; - u32 rd_en:1; - u32 qsel:5; - u32 rd_nav_ext:1; - u32 lsig_txop_en:1; - u32 pifs:1; - u32 rate_id:4; - u32 navusehdr:1; - u32 en_desc_id:1; - u32 sectype:2; - u32 rsvd0424:2; - u32 pkt_offset:5; /* unit: 8 bytes */ - u32 rsvd0431:1; - - u32 rts_rc:6; - u32 data_rc:6; - u32 rsvd0812:2; - u32 bar_rty_th:2; - u32 rsvd0816:1; - u32 morefrag:1; - u32 raw:1; - u32 ccx:1; - u32 ampdu_density:3; - u32 bt_null:1; - u32 ant_sel_a:1; - u32 ant_sel_b:1; - u32 tx_ant_cck:2; - u32 tx_antl:2; - u32 tx_ant_ht:2; - - u32 nextheadpage:8; - u32 tailpage:8; - u32 seq:12; - u32 cpu_handle:1; - u32 tag1:1; - u32 trigger_int:1; - u32 hwseq_en:1; - - u32 rtsrate:5; - u32 ap_dcfe:1; - u32 hwseq_sel:2; - u32 userate:1; - u32 disrtsfb:1; - u32 disdatafb:1; - u32 cts2self:1; - u32 rtsen:1; - u32 hw_rts_en:1; - u32 port_id:1; - u32 rsvd1615:3; - u32 wait_dcts:1; - u32 cts2ap_en:1; - u32 data_sc:2; - u32 data_stbc:2; - u32 data_short:1; - u32 data_bw:1; - u32 rts_short:1; - u32 rts_bw:1; - u32 rts_sc:2; - u32 vcs_stbc:2; - - u32 datarate:6; - u32 sgi:1; - u32 try_rate:1; - u32 data_ratefb_lmt:5; - u32 rts_ratefb_lmt:4; - u32 rty_lmt_en:1; - u32 data_rt_lmt:6; - u32 usb_txagg_num:8; - - u32 txagg_a:5; - u32 txagg_b:5; - u32 use_max_len:1; - u32 max_agg_num:5; - u32 mcsg1_max_len:4; - u32 mcsg2_max_len:4; - u32 mcsg3_max_len:4; - u32 mcs7_sgi_max_len:4; - - u32 checksum:16; /* TxBuffSize(PCIe)/CheckSum(USB) */ - u32 mcsg4_max_len:4; - u32 mcsg5_max_len:4; - u32 mcsg6_max_len:4; - u32 mcs15_sgi_max_len:4; -}; - -#define txdesc_set_ccx_sw_8723a(txdesc, value) \ - do { \ - ((struct txdesc_8723a *)(txdesc))->mcsg4_max_len = (((value)>>8) & 0x0f); \ - ((struct txdesc_8723a *)(txdesc))->mcs15_sgi_max_len= (((value)>>4) & 0x0f); \ - ((struct txdesc_8723a *)(txdesc))->mcsg6_max_len = ((value) & 0x0f); \ - } while (0) - -struct txrpt_ccx_8723a { - /* offset 0 */ - u8 tag1:1; - u8 rsvd:4; - u8 int_bt:1; - u8 int_tri:1; - u8 int_ccx:1; - - /* offset 1 */ - u8 mac_id:5; - u8 pkt_drop:1; - u8 pkt_ok:1; - u8 bmc:1; - - /* offset 2 */ - u8 retry_cnt:6; - u8 lifetime_over:1; - u8 retry_over:1; - - /* offset 3 */ - u8 ccx_qtime0; - u8 ccx_qtime1; - - /* offset 5 */ - u8 final_data_rate; - - /* offset 6 */ - u8 sw1:4; - u8 qsel:4; - - /* offset 7 */ - u8 sw0; -}; - -#define txrpt_ccx_sw_8723a(txrpt_ccx) ((txrpt_ccx)->sw0 + ((txrpt_ccx)->sw1<<8)) -#define txrpt_ccx_qtime_8723a(txrpt_ccx) ((txrpt_ccx)->ccx_qtime0+((txrpt_ccx)->ccx_qtime1<<8)) - -void handle_txrpt_ccx_8723a(struct rtw_adapter *adapter, void *buf); -void rtl8723a_fill_fake_txdesc(struct rtw_adapter *padapter, u8 *pDesc, u32 BufferLen, u8 IsPsPoll, u8 IsBTQosNull); - -int rtl8723au_hal_xmitframe_enqueue(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe); -s32 rtl8723au_xmit_buf_handler(struct rtw_adapter *padapter); -#define hal_xmit_handler rtl8723au_xmit_buf_handler -bool rtl8723au_hal_xmit(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe); -int rtl8723au_mgnt_xmit(struct rtw_adapter *padapter, struct xmit_frame *pmgntframe); -bool rtl8723au_xmitframe_complete(struct rtw_adapter *padapter, struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf); - - -#endif diff --git a/drivers/staging/rtl8723au/include/rtw_ap.h b/drivers/staging/rtl8723au/include/rtw_ap.h deleted file mode 100644 index 55a708f..0000000 --- a/drivers/staging/rtl8723au/include/rtw_ap.h +++ /dev/null @@ -1,51 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __RTW_AP_H_ -#define __RTW_AP_H_ - -#include <osdep_service.h> -#include <drv_types.h> - - -#ifdef CONFIG_8723AU_AP_MODE - -/* external function */ - -void init_mlme_ap_info23a(struct rtw_adapter *padapter); -void free_mlme_ap_info23a(struct rtw_adapter *padapter); -/* void update_BCNTIM(struct rtw_adapter *padapter); */ -void rtw_add_bcn_ie(struct rtw_adapter *padapter, struct wlan_bssid_ex *pnetwork, u8 index, u8 *data, u8 len); -void rtw_remove_bcn_ie(struct rtw_adapter *padapter, struct wlan_bssid_ex *pnetwork, u8 index); -void update_beacon23a(struct rtw_adapter *padapter, u8 ie_id, u8 *oui, u8 tx); -void add_RATid23a(struct rtw_adapter *padapter, struct sta_info *psta, u8 rssi_level); -void expire_timeout_chk23a(struct rtw_adapter *padapter); -void update_sta_info23a_apmode23a(struct rtw_adapter *padapter, struct sta_info *psta); -int rtw_check_beacon_data23a(struct rtw_adapter *padapter, - struct ieee80211_mgmt *mgmt, unsigned int len); -void rtw_ap_restore_network(struct rtw_adapter *padapter); -void rtw_set_macaddr_acl23a(struct rtw_adapter *padapter, int mode); - -void associated_clients_update23a(struct rtw_adapter *padapter, u8 updated); -void bss_cap_update_on_sta_join23a(struct rtw_adapter *padapter, struct sta_info *psta); -u8 bss_cap_update_on_sta_leave23a(struct rtw_adapter *padapter, struct sta_info *psta); -void sta_info_update23a(struct rtw_adapter *padapter, struct sta_info *psta); -void ap_sta_info_defer_update23a(struct rtw_adapter *padapter, struct sta_info *psta); -u8 ap_free_sta23a(struct rtw_adapter *padapter, struct sta_info *psta, bool active, u16 reason); -int rtw_sta_flush23a(struct rtw_adapter *padapter); -void start_ap_mode23a(struct rtw_adapter *padapter); -void stop_ap_mode23a(struct rtw_adapter *padapter); -#endif /* end of CONFIG_8723AU_AP_MODE */ - -#endif diff --git a/drivers/staging/rtl8723au/include/rtw_cmd.h b/drivers/staging/rtl8723au/include/rtw_cmd.h deleted file mode 100644 index d1fa95d..0000000 --- a/drivers/staging/rtl8723au/include/rtw_cmd.h +++ /dev/null @@ -1,815 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __RTW_CMD_H_ -#define __RTW_CMD_H_ - -#include <wlan_bssdef.h> -#include <rtw_rf.h> - -#define C2H_MEM_SZ (16*1024) - -#include <osdep_service.h> -#include <ieee80211.h> /* <ieee80211/ieee80211.h> */ - - -#define MAX_CMDSZ 1024 -#define MAX_RSPSZ 512 -#define MAX_EVTSZ 1024 - -#define CMDBUFF_ALIGN_SZ 512 - -struct cmd_obj { - struct work_struct work; - struct rtw_adapter *padapter; - u16 cmdcode; - int res; - u32 cmdsz; - u8 *parmbuf; - u8 *rsp; - u32 rspsz; -}; - -struct cmd_priv { - struct workqueue_struct *wq; - u32 cmd_issued_cnt; - u32 cmd_done_cnt; - u32 rsp_cnt; - struct rtw_adapter *padapter; -}; - -#define C2H_QUEUE_MAX_LEN 10 - -struct evt_priv { - struct workqueue_struct *wq; - struct work_struct irq_wk; -}; - -#define init_h2fwcmd_w_parm_no_rsp(pcmd, pparm, code) \ -do {\ - pcmd->cmdcode = code;\ - pcmd->parmbuf = (u8 *)(pparm);\ - pcmd->cmdsz = sizeof (*pparm);\ - pcmd->rsp = NULL;\ - pcmd->rspsz = 0;\ -} while(0) - -struct c2h_evt_hdr { - u8 id:4; - u8 plen:4; - u8 seq; - u8 payload[0]; -}; - -/* - * Do not reorder - this allows for struct evt_work to be passed on to - * rtw_c2h_wk_cmd23a() as a 'struct c2h_evt_hdr *' without making an - * additional copy. - */ -struct evt_work { - union { - struct c2h_evt_hdr c2h_evt; - u8 buf[16]; - } u; - struct work_struct work; - struct rtw_adapter *adapter; -}; - -#define c2h_evt_exist(c2h_evt) ((c2h_evt)->id || (c2h_evt)->plen) - -void rtw_evt_work(struct work_struct *work); - -int rtw_enqueue_cmd23a(struct cmd_priv *pcmdpriv, struct cmd_obj *obj); -void rtw_free_cmd_obj23a(struct cmd_obj *pcmd); - -int rtw_cmd_thread23a(void *context); - -int rtw_init_cmd_priv23a(struct cmd_priv *pcmdpriv); - -u32 rtw_init_evt_priv23a (struct evt_priv *pevtpriv); -void rtw_free_evt_priv23a (struct evt_priv *pevtpriv); -void rtw_evt_notify_isr(struct evt_priv *pevtpriv); - -enum rtw_drvextra_cmd_id -{ - NONE_WK_CID, - DYNAMIC_CHK_WK_CID, - DM_CTRL_WK_CID, - PBC_POLLING_WK_CID, - POWER_SAVING_CTRL_WK_CID,/* IPS,AUTOSuspend */ - LPS_CTRL_WK_CID, - ANT_SELECT_WK_CID, - P2P_PS_WK_CID, - P2P_PROTO_WK_CID, - CHECK_HIQ_WK_CID,/* for softap mode, check hi queue if empty */ - C2H_WK_CID, - RTP_TIMER_CFG_WK_CID, - MAX_WK_CID -}; - -enum LPS_CTRL_TYPE -{ - LPS_CTRL_SCAN=0, - LPS_CTRL_JOINBSS=1, - LPS_CTRL_CONNECT=2, - LPS_CTRL_DISCONNECT=3, - LPS_CTRL_SPECIAL_PACKET=4, - LPS_CTRL_LEAVE=5, -}; - -enum RFINTFS { - SWSI, - HWSI, - HWPI, -}; - -/* -Caller Mode: Infra, Ad-HoC(C) - -Notes: To enter USB suspend mode - -Command Mode - -*/ -struct usb_suspend_parm { - u32 action;/* 1: sleep, 0:resume */ -}; - -/* -Caller Mode: Infra, Ad-HoC - -Notes: To join a known BSS. - -Command-Event Mode - -*/ - -/* -Caller Mode: Infra, Ad-HoC(C) - -Notes: To disconnect the current associated BSS - -Command Mode - -*/ -struct disconnect_parm { - u32 deauth_timeout_ms; -}; - -struct setopmode_parm { - enum nl80211_iftype mode; -}; - -/* -Caller Mode: AP, Ad-HoC, Infra - -Notes: To ask RTL8711 performing site-survey - -Command-Event Mode - -*/ - -#define RTW_SSID_SCAN_AMOUNT 9 /* for WEXT_CSCAN_AMOUNT 9 */ -#define RTW_CHANNEL_SCAN_AMOUNT (14+37) -struct sitesurvey_parm { - int scan_mode; /* active: 1, passive: 0 */ - u8 ssid_num; - u8 ch_num; - struct cfg80211_ssid ssid[RTW_SSID_SCAN_AMOUNT]; - struct rtw_ieee80211_channel ch[RTW_CHANNEL_SCAN_AMOUNT]; -}; - -/* -Caller Mode: Any - -Notes: To set the auth type of RTL8711. open/shared/802.1x - -Command Mode - -*/ -struct setauth_parm { - u8 mode; /* 0: legacy open, 1: legacy shared 2: 802.1x */ - u8 _1x; /* 0: PSK, 1: TLS */ - u8 rsvd[2]; -}; - -/* -Caller Mode: Infra - -a. algorithm: wep40, wep104, tkip & aes -b. keytype: grp key/unicast key -c. key contents - -when shared key ==> keyid is the camid -when 802.1x ==> keyid [0:1] ==> grp key -when 802.1x ==> keyid > 2 ==> unicast key - -*/ -struct setkey_parm { - u32 algorithm; /* encryption algorithm, could be none, wep40, TKIP, CCMP, wep104 */ - u8 keyid; - u8 grpkey; /* 1: this is the grpkey for 802.1x. 0: this is the unicast key for 802.1x */ - u8 set_tx; /* 1: main tx key for wep. 0: other key. */ - u8 key[16]; /* this could be 40 or 104 */ -}; - -/* -When in AP or Ad-Hoc mode, this is used to -allocate an sw/hw entry for a newly associated sta. - -Command - -when shared key ==> algorithm/keyid - -*/ -struct set_stakey_parm { - u8 addr[ETH_ALEN]; - u8 id;/* currently for erasing cam entry if algorithm == _NO_PRIVACY_ */ - u32 algorithm; - u8 key[16]; -}; - -struct set_stakey_rsp { - u8 addr[ETH_ALEN]; - u8 keyid; - u8 rsvd; -}; - -/* -Caller Ad-Hoc/AP - -Command -Rsp(AID == CAMID) mode - -This is to force fw to add an sta_data entry per driver's request. - -FW will write an cam entry associated with it. - -*/ -struct set_assocsta_parm { - u8 addr[ETH_ALEN]; -}; - -struct set_assocsta_rsp { - u8 cam_id; - u8 rsvd[3]; -}; - -/* - Caller Ad-Hoc/AP - - Command mode - - This is to force fw to del an sta_data entry per driver's request - - FW will invalidate the cam entry associated with it. - -*/ -struct del_assocsta_parm { - u8 addr[ETH_ALEN]; -}; - -/* -Caller Mode: AP/Ad-HoC(M) - -Notes: To notify fw that given staid has changed its power state - -Command Mode - -*/ -struct setstapwrstate_parm { - u8 staid; - u8 status; - u8 hwaddr[6]; -}; - -/* -Caller Mode: Any - -Notes: To setup the basic rate of RTL8711 - -Command Mode - -*/ -struct setbasicrate_parm { - u8 basicrates[NumRates]; -}; - -/* -Caller Mode: Any - -Notes: To read the current basic rate - -Command-Rsp Mode - -*/ -struct getbasicrate_parm { - u32 rsvd; -}; - -struct getbasicrate_rsp { - u8 basicrates[NumRates]; -}; - -/* -Caller Mode: Any - -Notes: To setup the data rate of RTL8711 - -Command Mode - -*/ -struct setdatarate_parm { - u8 mac_id; - u8 datarates[NumRates]; -}; - -/* -Caller Mode: Any - -Notes: To read the current data rate - -Command-Rsp Mode - -*/ -struct getdatarate_parm { - u32 rsvd; -}; - -struct getdatarate_rsp { - u8 datarates[NumRates]; -}; - - -/* -Caller Mode: Any -AP: AP can use the info for the contents of beacon frame -Infra: STA can use the info when sitesurveying -Ad-HoC(M): Like AP -Ad-HoC(C): Like STA - - -Notes: To set the phy capability of the NIC - -Command Mode - -*/ - -struct setphyinfo_parm { - struct regulatory_class class_sets[NUM_REGULATORYS]; - u8 status; -}; - -struct getphyinfo_parm { - u32 rsvd; -}; - -struct getphyinfo_rsp { - struct regulatory_class class_sets[NUM_REGULATORYS]; - u8 status; -}; - -/* -Caller Mode: Any - -Notes: To set the channel/modem/band -This command will be used when channel/modem/band is changed. - -Command Mode - -*/ -struct setphy_parm { - u8 rfchannel; - u8 modem; -}; - -/* -Caller Mode: Any - -Notes: To get the current setting of channel/modem/band - -Command-Rsp Mode - -*/ -struct getphy_parm { - u32 rsvd; -}; - -struct getphy_rsp { - u8 rfchannel; - u8 modem; -}; - -struct readBB_parm { - u8 offset; -}; - -struct readBB_rsp { - u8 value; -}; - -struct readTSSI_parm { - u8 offset; -}; - -struct readTSSI_rsp { - u8 value; -}; - -struct writeBB_parm { - u8 offset; - u8 value; -}; - -struct readRF_parm { - u8 offset; -}; - -struct readRF_rsp { - u32 value; -}; - -struct writeRF_parm { - u32 offset; - u32 value; -}; - -struct getrfintfs_parm { - u8 rfintfs; -}; - -struct Tx_Beacon_param { - struct wlan_bssid_ex network; -}; - -/* CMD param Formart for driver extra cmd handler */ -struct drvextra_cmd_parm { - int ec_id; /* extra cmd id */ - int type_size; /* Can use this field as the type id or command size */ - unsigned char *pbuf; -}; - -/*------------------- Below are used for RF/BB tunning ---------------------*/ - -struct setantenna_parm { - u8 tx_antset; - u8 rx_antset; - u8 tx_antenna; - u8 rx_antenna; -}; - -struct enrateadaptive_parm { - u32 en; -}; - -struct settxagctbl_parm { - u32 txagc[MAX_RATES_LENGTH]; -}; - -struct gettxagctbl_parm { - u32 rsvd; -}; - -struct gettxagctbl_rsp { - u32 txagc[MAX_RATES_LENGTH]; -}; - -struct setagcctrl_parm { - u32 agcctrl; /* 0: pure hw, 1: fw */ -}; - -struct setssup_parm { - u32 ss_ForceUp[MAX_RATES_LENGTH]; -}; - -struct getssup_parm { - u32 rsvd; -}; - -struct getssup_rsp { - u8 ss_ForceUp[MAX_RATES_LENGTH]; -}; - -struct setssdlevel_parm { - u8 ss_DLevel[MAX_RATES_LENGTH]; -}; - -struct getssdlevel_parm { - u32 rsvd; -}; - -struct getssdlevel_rsp { - u8 ss_DLevel[MAX_RATES_LENGTH]; -}; - -struct setssulevel_parm { - u8 ss_ULevel[MAX_RATES_LENGTH]; -}; - -struct getssulevel_parm { - u32 rsvd; -}; - -struct getssulevel_rsp { - u8 ss_ULevel[MAX_RATES_LENGTH]; -}; - -struct setcountjudge_parm { - u8 count_judge[MAX_RATES_LENGTH]; -}; - -struct getcountjudge_parm { - u32 rsvd; -}; - -struct getcountjudge_rsp { - u8 count_judge[MAX_RATES_LENGTH]; -}; - -struct setratable_parm { - u8 ss_ForceUp[NumRates]; - u8 ss_ULevel[NumRates]; - u8 ss_DLevel[NumRates]; - u8 count_judge[NumRates]; -}; - -struct getratable_parm { - uint rsvd; -}; - -struct getratable_rsp { - u8 ss_ForceUp[NumRates]; - u8 ss_ULevel[NumRates]; - u8 ss_DLevel[NumRates]; - u8 count_judge[NumRates]; -}; - -/* to get TX,RX retry count */ -struct gettxretrycnt_parm{ - unsigned int rsvd; -}; -struct gettxretrycnt_rsp{ - unsigned long tx_retrycnt; -}; - -struct getrxretrycnt_parm{ - unsigned int rsvd; -}; -struct getrxretrycnt_rsp{ - unsigned long rx_retrycnt; -}; - -/* to get BCNOK,BCNERR count */ -struct getbcnokcnt_parm{ - unsigned int rsvd; -}; -struct getbcnokcnt_rsp{ - unsigned long bcnokcnt; -}; - -struct getbcnerrcnt_parm{ - unsigned int rsvd; -}; -struct getbcnerrcnt_rsp{ - unsigned long bcnerrcnt; -}; - -/* to get current TX power level */ -struct getcurtxpwrlevel_parm{ - unsigned int rsvd; -}; - -struct getcurtxpwrlevel_rsp{ - unsigned short tx_power; -}; - -struct setprobereqextraie_parm { - unsigned char e_id; - unsigned char ie_len; - unsigned char ie[0]; -}; - -struct setassocreqextraie_parm { - unsigned char e_id; - unsigned char ie_len; - unsigned char ie[0]; -}; - -struct setproberspextraie_parm { - unsigned char e_id; - unsigned char ie_len; - unsigned char ie[0]; -}; - -struct setassocrspextraie_parm { - unsigned char e_id; - unsigned char ie_len; - unsigned char ie[0]; -}; - -struct addBaReq_parm { - unsigned int tid; - u8 addr[ETH_ALEN]; -}; - -/*H2C Handler index: 46 */ -struct set_ch_parm { - u8 ch; - u8 bw; - u8 ch_offset; -}; - -/*H2C Handler index: 59 */ -struct SetChannelPlan_param { - u8 channel_plan; -}; - -/*H2C Handler index: 60 */ -struct LedBlink_param { - struct led_8723a *pLed; -}; - -/*H2C Handler index: 61 */ -struct SetChannelSwitch_param { - u8 new_ch_no; -}; - -/*H2C Handler index: 62 */ -struct TDLSoption_param { - u8 addr[ETH_ALEN]; - u8 option; -}; - -#define GEN_CMD_CODE(cmd) cmd ## _CMD_ - - -/* - -Result: -0x00: success -0x01: success, and check Response. -0x02: cmd ignored due to duplicated sequcne number -0x03: cmd dropped due to invalid cmd code -0x04: reserved. - -*/ - -#define H2C_RSP_OFFSET 512 - -#define H2C_SUCCESS 0x00 -#define H2C_SUCCESS_RSP 0x01 -#define H2C_DUPLICATED 0x02 -#define H2C_DROPPED 0x03 -#define H2C_PARAMETERS_ERROR 0x04 -#define H2C_REJECTED 0x05 -#define H2C_CMD_OVERFLOW 0x06 -#define H2C_RESERVED 0x07 - -int rtw_setassocsta_cmd(struct rtw_adapter *padapter, u8 *mac_addr); -int rtw_setstandby_cmd(struct rtw_adapter *padapter, uint action); -int rtw_sitesurvey_cmd23a(struct rtw_adapter *padapter, struct cfg80211_ssid *ssid, int ssid_num, struct rtw_ieee80211_channel *ch, int ch_num); -int rtw_createbss_cmd23a(struct rtw_adapter *padapter); -int rtw_createbss_cmd23a_ex(struct rtw_adapter *padapter, unsigned char *pbss, unsigned int sz); -int rtw_setphy_cmd(struct rtw_adapter *padapter, u8 modem, u8 ch); -int rtw_setstakey_cmd23a(struct rtw_adapter *padapter, u8 *psta, u8 unicast_key); -int rtw_clearstakey_cmd23a(struct rtw_adapter *padapter, u8 *psta, u8 entry, u8 enqueue); -int rtw_joinbss_cmd23a(struct rtw_adapter *padapter, struct wlan_network* pnetwork); -int rtw_disassoc_cmd23a(struct rtw_adapter *padapter, u32 deauth_timeout_ms, bool enqueue); -int rtw_setopmode_cmd23a(struct rtw_adapter *padapter, enum nl80211_iftype ifmode); -int rtw_setdatarate_cmd(struct rtw_adapter *padapter, u8 *rateset); -int rtw_setbasicrate_cmd(struct rtw_adapter *padapter, u8 *rateset); -int rtw_setbbreg_cmd(struct rtw_adapter *padapter, u8 offset, u8 val); -int rtw_setrfreg_cmd(struct rtw_adapter *padapter, u8 offset, u32 val); -int rtw_getbbreg_cmd(struct rtw_adapter *padapter, u8 offset, u8 *pval); -int rtw_getrfreg_cmd(struct rtw_adapter *padapter, u8 offset, u8 *pval); -int rtw_setrfintfs_cmd(struct rtw_adapter *padapter, u8 mode); -int rtw_setrttbl_cmd(struct rtw_adapter *padapter, struct setratable_parm *prate_table); -int rtw_getrttbl_cmd(struct rtw_adapter *padapter, struct getratable_rsp *pval); - -int rtw_gettssi_cmd(struct rtw_adapter *padapter, u8 offset, u8 *pval); -int rtw_setfwdig_cmd(struct rtw_adapter*padapter, u8 type); -int rtw_setfwra_cmd(struct rtw_adapter*padapter, u8 type); - -int rtw_addbareq_cmd23a(struct rtw_adapter*padapter, u8 tid, u8 *addr); - -int rtw_dynamic_chk_wk_cmd23a(struct rtw_adapter *adapter); - -int rtw_lps_ctrl_wk_cmd23a(struct rtw_adapter*padapter, u8 lps_ctrl_type, u8 enqueue); - -int rtw_ps_cmd23a(struct rtw_adapter*padapter); - -#ifdef CONFIG_8723AU_AP_MODE -int rtw_chk_hi_queue_cmd23a(struct rtw_adapter*padapter); -#endif - -int rtw_set_chplan_cmd(struct rtw_adapter*padapter, u8 chplan, u8 enqueue); -int rtw_led_blink_cmd(struct rtw_adapter*padapter, struct led_8723a *pLed); -int rtw_set_csa_cmd(struct rtw_adapter*padapter, u8 new_ch_no); - -int rtw_c2h_wk_cmd23a(struct rtw_adapter *padapter, u8 *c2h_evt); - -int rtw_drvextra_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); - -void rtw_survey_cmd_callback23a(struct rtw_adapter *padapter, struct cmd_obj *pcmd); -void rtw_disassoc_cmd23a_callback(struct rtw_adapter *padapter, struct cmd_obj *pcmd); -void rtw_joinbss_cmd23a_callback(struct rtw_adapter *padapter, struct cmd_obj *pcmd); -void rtw_createbss_cmd23a_callback(struct rtw_adapter *padapter, struct cmd_obj *pcmd); -void rtw_getbbrfreg_cmdrsp_callback23a(struct rtw_adapter *padapter, struct cmd_obj *pcmd); - -void rtw_setstaKey_cmdrsp_callback23a(struct rtw_adapter *padapter, struct cmd_obj *pcmd); -void rtw_setassocsta_cmdrsp_callback23a(struct rtw_adapter *padapter, struct cmd_obj *pcmd); - -struct _cmd_callback { - u32 cmd_code; - void (*callback)(struct rtw_adapter *padapter, struct cmd_obj *cmd); -}; - -enum rtw_h2c_cmd { - GEN_CMD_CODE(_Read_MACREG) , /*0*/ - GEN_CMD_CODE(_Write_MACREG) , - GEN_CMD_CODE(_Read_BBREG) , - GEN_CMD_CODE(_Write_BBREG) , - GEN_CMD_CODE(_Read_RFREG) , - GEN_CMD_CODE(_Write_RFREG) , /*5*/ - GEN_CMD_CODE(_Read_EEPROM) , - GEN_CMD_CODE(_Write_EEPROM) , - GEN_CMD_CODE(_Read_EFUSE) , - GEN_CMD_CODE(_Write_EFUSE) , - - GEN_CMD_CODE(_Read_CAM) , /*10*/ - GEN_CMD_CODE(_Write_CAM) , - GEN_CMD_CODE(_setBCNITV), - GEN_CMD_CODE(_setMBIDCFG), - GEN_CMD_CODE(_JoinBss), /*14*/ - GEN_CMD_CODE(_DisConnect) , /*15*/ - GEN_CMD_CODE(_CreateBss) , - GEN_CMD_CODE(_SetOpMode) , - GEN_CMD_CODE(_SiteSurvey), /*18*/ - GEN_CMD_CODE(_SetAuth) , - - GEN_CMD_CODE(_SetKey) , /*20*/ - GEN_CMD_CODE(_SetStaKey) , - GEN_CMD_CODE(_SetAssocSta) , - GEN_CMD_CODE(_DelAssocSta) , - GEN_CMD_CODE(_SetStaPwrState) , - GEN_CMD_CODE(_SetBasicRate) , /*25*/ - GEN_CMD_CODE(_GetBasicRate) , - GEN_CMD_CODE(_SetDataRate) , - GEN_CMD_CODE(_GetDataRate) , - GEN_CMD_CODE(_SetPhyInfo) , - - GEN_CMD_CODE(_GetPhyInfo) , /*30*/ - GEN_CMD_CODE(_SetPhy) , - GEN_CMD_CODE(_GetPhy) , - GEN_CMD_CODE(_readRssi) , - GEN_CMD_CODE(_readGain) , - GEN_CMD_CODE(_SetAtim) , /*35*/ - GEN_CMD_CODE(_SetPwrMode) , - GEN_CMD_CODE(_JoinbssRpt), - GEN_CMD_CODE(_SetRaTable) , - GEN_CMD_CODE(_GetRaTable) , - - GEN_CMD_CODE(_GetCCXReport), /*40*/ - GEN_CMD_CODE(_GetDTMReport), - GEN_CMD_CODE(_GetTXRateStatistics), - GEN_CMD_CODE(_SetUsbSuspend), - GEN_CMD_CODE(_SetH2cLbk), - GEN_CMD_CODE(_AddBAReq) , /*45*/ - GEN_CMD_CODE(_SetChannel), /*46*/ - GEN_CMD_CODE(_SetTxPower), - GEN_CMD_CODE(_SwitchAntenna), - GEN_CMD_CODE(_SetCrystalCap), - GEN_CMD_CODE(_SetSingleCarrierTx), /*50*/ - - GEN_CMD_CODE(_SetSingleToneTx),/*51*/ - GEN_CMD_CODE(_SetCarrierSuppressionTx), - GEN_CMD_CODE(_SetContinuousTx), - GEN_CMD_CODE(_SwitchBandwidth), /*54*/ - GEN_CMD_CODE(_TX_Beacon), /*55*/ - - GEN_CMD_CODE(_Set_MLME_EVT), /*56*/ - GEN_CMD_CODE(_Set_Drv_Extra), /*57*/ - GEN_CMD_CODE(_Set_H2C_MSG), /*58*/ - - GEN_CMD_CODE(_SetChannelPlan), /*59*/ - GEN_CMD_CODE(_LedBlink), /*60*/ - - GEN_CMD_CODE(_SetChannelSwitch), /*61*/ - GEN_CMD_CODE(_TDLS), /*62*/ - - MAX_H2CCMD -}; - -extern struct _cmd_callback rtw_cmd_callback[]; - -#endif /* _CMD_H_ */ diff --git a/drivers/staging/rtl8723au/include/rtw_debug.h b/drivers/staging/rtl8723au/include/rtw_debug.h deleted file mode 100644 index 159183e..0000000 --- a/drivers/staging/rtl8723au/include/rtw_debug.h +++ /dev/null @@ -1,191 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * - ******************************************************************************/ -#ifndef __RTW_DEBUG_H__ -#define __RTW_DEBUG_H__ - -#include <osdep_service.h> -#include <drv_types.h> - -#define _drv_always_ 1 -#define _drv_emerg_ 2 -#define _drv_alert_ 3 -#define _drv_err_ 4 -#define _drv_warning_ 5 -#define _drv_notice_ 6 -#define _drv_info_ 7 -#define _drv_debug_ 8 - -#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(28) -#define _module_hal_xmit_c_ BIT(28) /* duplication intentional */ -#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_MP_C_ - #define _MODULE_DEFINE_ _module_mp_ -#elif defined _RTW_MP_IOCTL_C_ - #define _MODULE_DEFINE_ _module_mp_ -#elif defined _RTW_EFUSE_C_ - #define _MODULE_DEFINE_ _module_efuse_ -#endif - -#define DRIVER_PREFIX "RTL8723AU: " -#define DEBUG_LEVEL (_drv_err_) -#define DBG_8723A_LEVEL(_level, fmt, arg...) \ - do { \ - if (_level <= GlobalDebugLevel23A) \ - pr_info(DRIVER_PREFIX fmt, ##arg);\ - } while (0) - -#define DBG_8723A(...) \ - do { \ - if (_drv_err_ <= GlobalDebugLevel23A) \ - pr_info(DRIVER_PREFIX __VA_ARGS__); \ - } while (0) - -#define MSG_8723A(...) \ - do { \ - if (_drv_err_ <= GlobalDebugLevel23A) \ - pr_info(DRIVER_PREFIX __VA_ARGS__); \ - } while (0) - -extern u32 GlobalDebugLevel23A; - -__printf(3, 4) -void rt_trace(int comp, int level, const char *fmt, ...); - -#define RT_TRACE(_Comp, _Level, Fmt, ...) \ -do { \ - if (_Level <= GlobalDebugLevel23A) \ - rt_trace(_Comp, _Level, Fmt, ##__VA_ARGS__); \ -} while (0) - -#define RT_PRINT_DATA(_Comp, _Level, _TitleString, _HexData, \ - _HexDataLen) \ - if (_Level <= GlobalDebugLevel23A) { \ - int __i; \ - u8 *ptr = (u8 *)_HexData; \ - pr_info("%s", DRIVER_PREFIX); \ - pr_info(_TitleString); \ - for (__i = 0; __i < (int)_HexDataLen; __i++) { \ - printk("%02X%s", ptr[__i], \ - (((__i + 1) % 4) == 0) ? " " : " "); \ - if (((__i + 1) % 16) == 0) \ - printk("\n"); \ - } \ - printk("\n"); \ - } - -#endif /* __RTW_DEBUG_H__ */ diff --git a/drivers/staging/rtl8723au/include/rtw_eeprom.h b/drivers/staging/rtl8723au/include/rtw_eeprom.h deleted file mode 100644 index a86f36e..0000000 --- a/drivers/staging/rtl8723au/include/rtw_eeprom.h +++ /dev/null @@ -1,135 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __RTW_EEPROM_H__ -#define __RTW_EEPROM_H__ - -#include <osdep_service.h> -#include <drv_types.h> - -#define RTL8712_EEPROM_ID 0x8712 -/* define EEPROM_MAX_SIZE 256 */ - -#define HWSET_MAX_SIZE_512 512 -#define EEPROM_MAX_SIZE HWSET_MAX_SIZE_512 - -#define CLOCK_RATE 50 /* 100us */ - -/* EEPROM opcodes */ -#define EEPROM_READ_OPCODE 06 -#define EEPROM_WRITE_OPCODE 05 -#define EEPROM_ERASE_OPCODE 07 -#define EEPROM_EWEN_OPCODE 19 /* Erase/write enable */ -#define EEPROM_EWDS_OPCODE 16 /* Erase/write disable */ - -/* Country codes */ -#define USA 0x555320 -#define EUROPE 0x1 /* temp, should be provided later */ -#define JAPAN 0x2 /* temp, should be provided later */ - -#define EEPROM_CID_DEFAULT 0x0 -#define EEPROM_CID_ALPHA 0x1 -#define EEPROM_CID_Senao 0x3 -#define EEPROM_CID_NetCore 0x5 -#define EEPROM_CID_CAMEO 0X8 -#define EEPROM_CID_SITECOM 0x9 -#define EEPROM_CID_COREGA 0xB -#define EEPROM_CID_EDIMAX_BELKIN 0xC -#define EEPROM_CID_SERCOMM_BELKIN 0xE -#define EEPROM_CID_CAMEO1 0xF -#define EEPROM_CID_WNC_COREGA 0x12 -#define EEPROM_CID_CLEVO 0x13 -#define EEPROM_CID_WHQL 0xFE /* added by chiyoko for dtm, 20090108 */ - -/* */ -/* Customer ID, note that: */ -/* This variable is initiailzed through EEPROM or registry, */ -/* however, its definition may be different with that in EEPROM for */ -/* EEPROM size consideration. So, we have to perform proper translation between them. */ -/* Besides, CustomerID of registry has precedence of that of EEPROM. */ -/* defined below. 060703, by rcnjko. */ -/* */ -enum rt_customer_id -{ - RT_CID_DEFAULT = 0, - RT_CID_8187_ALPHA0 = 1, - RT_CID_8187_SERCOMM_PS = 2, - RT_CID_8187_HW_LED = 3, - RT_CID_8187_NETGEAR = 4, - RT_CID_WHQL = 5, - RT_CID_819x_CAMEO = 6, - RT_CID_819x_RUNTOP = 7, - RT_CID_819x_Senao = 8, - RT_CID_TOSHIBA = 9, /* Merge by Jacken, 2008/01/31. */ - RT_CID_819x_Netcore = 10, - RT_CID_Nettronix = 11, - RT_CID_DLINK = 12, - RT_CID_PRONET = 13, - RT_CID_COREGA = 14, - RT_CID_CHINA_MOBILE = 15, - RT_CID_819x_ALPHA = 16, - RT_CID_819x_Sitecom = 17, - RT_CID_CCX = 18, /* It's set under CCX logo test and isn't demanded for CCX functions, but for test behavior like retry limit and tx report. By Bruce, 2009-02-17. */ - RT_CID_819x_Lenovo = 19, - RT_CID_819x_QMI = 20, - RT_CID_819x_Edimax_Belkin = 21, - RT_CID_819x_Sercomm_Belkin = 22, - RT_CID_819x_CAMEO1 = 23, - RT_CID_819x_MSI = 24, - RT_CID_819x_Acer = 25, - RT_CID_819x_AzWave_ASUS = 26, - RT_CID_819x_AzWave = 27, /* For AzWave in PCIe, The ID is AzWave use and not only Asus */ - RT_CID_819x_HP = 28, - RT_CID_819x_WNC_COREGA = 29, - RT_CID_819x_Arcadyan_Belkin = 30, - RT_CID_819x_SAMSUNG = 31, - RT_CID_819x_CLEVO = 32, - RT_CID_819x_DELL = 33, - RT_CID_819x_PRONETS = 34, - RT_CID_819x_Edimax_ASUS = 35, - RT_CID_819x_CAMEO_NETGEAR = 36, - RT_CID_PLANEX = 37, - RT_CID_CC_C = 38, - RT_CID_819x_Xavi = 39, - RT_CID_819x_FUNAI_TV = 40, - RT_CID_819x_ALPHA_WD=41, -}; - -struct eeprom_priv { - u8 mac_addr[6]; /* PermanentAddress */ - u8 bautoload_fail_flag; - u8 bloadfile_fail_flag; - u8 bloadmac_fail_flag; - /* u8 bempty; */ - /* u8 sys_config; */ - /* u8 config0; */ - u16 channel_plan; - /* u8 country_string[3]; */ - /* u8 tx_power_b[15]; */ - /* u8 tx_power_g[15]; */ - /* u8 tx_power_a[201]; */ - - u8 EepromOrEfuse; - - u8 efuse_eeprom_data[HWSET_MAX_SIZE_512]; /* 92C:256bytes, 88E:512bytes, we use union set (512bytes) */ -}; - -void eeprom_write16(struct rtw_adapter *padapter, u16 reg, u16 data); -u16 eeprom_read16(struct rtw_adapter *padapter, u16 reg); -void read_eeprom_content(struct rtw_adapter *padapter); -void eeprom_read_sz(struct rtw_adapter *padapter, u16 reg, u8 *data, u32 sz); - -void read_eeprom_content_by_attrib(struct rtw_adapter *padapter); - -#endif /* __RTL871X_EEPROM_H__ */ diff --git a/drivers/staging/rtl8723au/include/rtw_efuse.h b/drivers/staging/rtl8723au/include/rtw_efuse.h deleted file mode 100644 index c577e26..0000000 --- a/drivers/staging/rtl8723au/include/rtw_efuse.h +++ /dev/null @@ -1,109 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * - ******************************************************************************/ -#ifndef __RTW_EFUSE_H__ -#define __RTW_EFUSE_H__ - -#include <osdep_service.h> - -#define EFUSE_ERROE_HANDLE 1 - -#define PG_STATE_HEADER 0x01 -#define PG_STATE_WORD_0 0x02 -#define PG_STATE_WORD_1 0x04 -#define PG_STATE_WORD_2 0x08 -#define PG_STATE_WORD_3 0x10 -#define PG_STATE_DATA 0x20 - -#define PG_SWBYTE_H 0x01 -#define PG_SWBYTE_L 0x02 - -#define PGPKT_DATA_SIZE 8 - -#define EFUSE_WIFI 0 -#define EFUSE_BT 1 - -enum _EFUSE_DEF_TYPE { - TYPE_EFUSE_MAX_SECTION = 0, - TYPE_EFUSE_REAL_CONTENT_LEN = 1, - TYPE_AVAILABLE_EFUSE_BYTES_BANK = 2, - TYPE_AVAILABLE_EFUSE_BYTES_TOTAL = 3, - TYPE_EFUSE_MAP_LEN = 4, - TYPE_EFUSE_PROTECT_BYTES_BANK = 5, - TYPE_EFUSE_CONTENT_LEN_BANK = 6, -}; - -/* E-Fuse */ -#define EFUSE_MAP_SIZE 256 - -#define EFUSE_MAX_SIZE 512 -/* end of E-Fuse */ - -#define EFUSE_MAX_MAP_LEN 256 -#define EFUSE_MAX_HW_SIZE 512 -#define EFUSE_MAX_SECTION_BASE 16 - -#define EXT_HEADER(header) ((header & 0x1F) == 0x0F) -#define ALL_WORDS_DISABLED(wde) ((wde & 0x0F) == 0x0F) -#define GET_HDR_OFFSET_2_0(header) ( (header & 0xE0) >> 5) - -#define EFUSE_REPEAT_THRESHOLD_ 3 - -/* */ -/* The following is for BT Efuse definition */ -/* */ -#define EFUSE_BT_MAX_MAP_LEN 1024 -#define EFUSE_MAX_BANK 4 -#define EFUSE_MAX_BT_BANK (EFUSE_MAX_BANK-1) -/* */ -/*--------------------------Define Parameters-------------------------------*/ -#define EFUSE_MAX_WORD_UNIT 4 - -/*------------------------------Define structure----------------------------*/ -struct pg_pkt_struct { - u8 offset; - u8 word_en; - u8 data[8]; - u8 word_cnts; -}; - -/*------------------------Export global variable----------------------------*/ - -u16 efuse_GetMaxSize23a(struct rtw_adapter *padapter); -int rtw_efuse_access23a(struct rtw_adapter *padapter, u8 bRead, u16 start_addr, u16 cnts, u8 *data); -int rtw_efuse_map_read23a(struct rtw_adapter *padapter, u16 addr, u16 cnts, u8 *data); -u8 rtw_efuse_map_write(struct rtw_adapter *padapter, u16 addr, u16 cnts, u8 *data); -int rtw_BT_efuse_map_read23a(struct rtw_adapter *padapter, u16 addr, u16 cnts, u8 *data); -u8 rtw_BT_efuse_map_write(struct rtw_adapter *padapter, u16 addr, u16 cnts, u8 *data); - -u16 Efuse_GetCurrentSize23a(struct rtw_adapter *pAdapter, u8 efuseType); -u8 Efuse_CalculateWordCnts23a(u8 word_en); -void ReadEFuseByte23a(struct rtw_adapter *Adapter, u16 _offset, u8 *pbuf); -void EFUSE_GetEfuseDefinition23a(struct rtw_adapter *pAdapter, u8 efuseType, u8 type, void *pOut); -int efuse_OneByteRead23a(struct rtw_adapter *pAdapter, u16 addr, u8 *data); -int efuse_OneByteWrite23a(struct rtw_adapter *pAdapter, u16 addr, u8 data); - -void Efuse_PowerSwitch23a(struct rtw_adapter *pAdapter, u8 bWrite, - u8 PwrState); -int Efuse_PgPacketRead23a(struct rtw_adapter *pAdapter, u8 offset, u8 *data); -int Efuse_PgPacketWrite23a(struct rtw_adapter *pAdapter, u8 offset, u8 word_en, u8 *data); -void efuse_WordEnableDataRead23a(u8 word_en, u8 *sourdata, u8 *targetdata); -u8 Efuse_WordEnableDataWrite23a(struct rtw_adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data); - -u8 EFUSE_Read1Byte23a(struct rtw_adapter *pAdapter, u16 Address); -void EFUSE_ShadowMapUpdate23a(struct rtw_adapter *pAdapter, u8 efuseType); -void EFUSE_ShadowRead23a(struct rtw_adapter *pAdapter, u8 Type, u16 Offset, u32 *Value); - -#endif diff --git a/drivers/staging/rtl8723au/include/rtw_event.h b/drivers/staging/rtl8723au/include/rtw_event.h deleted file mode 100644 index 4557aec..0000000 --- a/drivers/staging/rtl8723au/include/rtw_event.h +++ /dev/null @@ -1,74 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef _RTW_EVENT_H_ -#define _RTW_EVENT_H_ - -#include <osdep_service.h> -#include <wlan_bssdef.h> - -/* -Used to report a bss has been scanned -*/ -struct survey_event { - struct wlan_bssid_ex *bss; -}; - -/* -Used to report that the requested site survey has been done. -bss_cnt indicates the number of bss that has been reported. -*/ -struct surveydone_event { - unsigned int bss_cnt; -}; - -/* -Used to report the link result of joinning the given bss -join_res: --1: authentication fail --2: association fail -> 0: TID -*/ -struct joinbss_event { - struct wlan_network network; -}; - -/* -Used to report a given STA has joinned the created BSS. -It is used in AP/Ad-HoC(M) mode. -*/ -struct stassoc_event { - unsigned char macaddr[6]; - unsigned char rsvd[2]; - int cam_id; -}; - -struct stadel_event { - unsigned char macaddr[6]; - unsigned char rsvd[2]; /* for reason */ - int mac_id; -}; - -struct addba_event { - unsigned int tid; -}; - -#define GEN_EVT_CODE(event) event ## _EVT_ - -struct fwevent { - u32 parmsize; - void (*event_callback)(struct rtw_adapter *dev, const u8 *pbuf); -}; - -#endif /* _WLANEVENT_H_ */ diff --git a/drivers/staging/rtl8723au/include/rtw_ht.h b/drivers/staging/rtl8723au/include/rtw_ht.h deleted file mode 100644 index 780eb89..0000000 --- a/drivers/staging/rtl8723au/include/rtw_ht.h +++ /dev/null @@ -1,42 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef _RTW_HT_H_ -#define _RTW_HT_H_ - -#include <osdep_service.h> -#include "linux/ieee80211.h" -#include "wifi.h" - -struct ht_priv { - bool ht_option; - bool ampdu_enable;/* for enable Tx A-MPDU */ - /* u8 baddbareq_issued[16]; */ - u32 tx_amsdu_enable;/* for enable Tx A-MSDU */ - u32 tx_amdsu_maxlen; /* 1: 8k, 0:4k ; default:8k, for tx */ - u32 rx_ampdu_maxlen; /* for rx reordering ctrl win_sz, updated when join_callback. */ - - u8 bwmode;/* */ - u8 ch_offset;/* PRIME_CHNL_OFFSET */ - u8 sgi;/* short GI */ - - /* for processing Tx A-MPDU */ - u16 agg_enable_bitmap; - /* u8 ADDBA_retry_count; */ - u16 candidate_tid_bitmap; - - struct ieee80211_ht_cap ht_cap; -}; - -#endif /* _RTL871X_HT_H_ */ diff --git a/drivers/staging/rtl8723au/include/rtw_io.h b/drivers/staging/rtl8723au/include/rtw_io.h deleted file mode 100644 index d875e9e..0000000 --- a/drivers/staging/rtl8723au/include/rtw_io.h +++ /dev/null @@ -1,235 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ - -#ifndef _RTW_IO_H_ -#define _RTW_IO_H_ - -#include <osdep_service.h> -#include <osdep_intf.h> - -#include <asm/byteorder.h> -#include <linux/list.h> -/* include <linux/smp_lock.h> */ -#include <linux/spinlock.h> -#include <asm/atomic.h> - -#include <linux/usb.h> -#include <linux/usb/ch9.h> - -#define rtw_usb_buffer_alloc(dev, size, dma) usb_alloc_coherent((dev), (size), (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL), (dma)) -#define rtw_usb_buffer_free(dev, size, addr, dma) usb_free_coherent((dev), (size), (addr), (dma)) - -#define NUM_IOREQ 8 - -#define MAX_PROT_SZ (64-16) - -#define _IOREADY 0 -#define _IO_WAIT_COMPLETE 1 -#define _IO_WAIT_RSP 2 - -/* IO COMMAND TYPE */ -#define _IOSZ_MASK_ (0x7F) -#define _IO_WRITE_ BIT(7) -#define _IO_FIXED_ BIT(8) -#define _IO_BURST_ BIT(9) -#define _IO_BYTE_ BIT(10) -#define _IO_HW_ BIT(11) -#define _IO_WORD_ BIT(12) -#define _IO_SYNC_ BIT(13) -#define _IO_CMDMASK_ (0x1F80) - - -/* - For prompt mode accessing, caller shall free io_req - Otherwise, io_handler will free io_req -*/ - - - -/* IO STATUS TYPE */ -#define _IO_ERR_ BIT(2) -#define _IO_SUCCESS_ BIT(1) -#define _IO_DONE_ BIT(0) - - -#define IO_RD32 (_IO_SYNC_ | _IO_WORD_) -#define IO_RD16 (_IO_SYNC_ | _IO_HW_) -#define IO_RD8 (_IO_SYNC_ | _IO_BYTE_) - -#define IO_RD32_ASYNC (_IO_WORD_) -#define IO_RD16_ASYNC (_IO_HW_) -#define IO_RD8_ASYNC (_IO_BYTE_) - -#define IO_WR32 (_IO_WRITE_ | _IO_SYNC_ | _IO_WORD_) -#define IO_WR16 (_IO_WRITE_ | _IO_SYNC_ | _IO_HW_) -#define IO_WR8 (_IO_WRITE_ | _IO_SYNC_ | _IO_BYTE_) - -#define IO_WR32_ASYNC (_IO_WRITE_ | _IO_WORD_) -#define IO_WR16_ASYNC (_IO_WRITE_ | _IO_HW_) -#define IO_WR8_ASYNC (_IO_WRITE_ | _IO_BYTE_) - -/* - - Only Sync. burst accessing is provided. - -*/ - -#define IO_WR_BURST(x) (_IO_WRITE_ | _IO_SYNC_ | _IO_BURST_ | ( (x) & _IOSZ_MASK_)) -#define IO_RD_BURST(x) (_IO_SYNC_ | _IO_BURST_ | ( (x) & _IOSZ_MASK_)) - - - -/* below is for the intf_option bit defition... */ - -#define _INTF_ASYNC_ BIT(0) /* support async io */ - -struct intf_priv; - -struct io_req { - struct list_head list; - u32 addr; - volatile u32 val; - u32 command; - u32 status; - u8 *pbuf; - - void (*_async_io_callback)(struct rtw_adapter *padater, struct io_req *pio_req, u8 *cnxt); - u8 *cnxt; -}; - -struct reg_protocol_rd { - -#ifdef __LITTLE_ENDIAN - - /* DW1 */ - u32 NumOfTrans:4; - u32 Reserved1:4; - u32 Reserved2:24; - /* DW2 */ - u32 ByteCount:7; - u32 WriteEnable:1; /* 0:read, 1:write */ - u32 FixOrContinuous:1; /* 0:continuous, 1: Fix */ - u32 BurstMode:1; - u32 Byte1Access:1; - u32 Byte2Access:1; - u32 Byte4Access:1; - u32 Reserved3:3; - u32 Reserved4:16; - /* DW3 */ - u32 BusAddress; - /* DW4 */ - /* u32 Value; */ -#else - - -/* DW1 */ - u32 Reserved1 :4; - u32 NumOfTrans :4; - - u32 Reserved2 :24; - - /* DW2 */ - u32 WriteEnable : 1; - u32 ByteCount :7; - - - u32 Reserved3 : 3; - u32 Byte4Access : 1; - - u32 Byte2Access : 1; - u32 Byte1Access : 1; - u32 BurstMode :1 ; - u32 FixOrContinuous : 1; - - u32 Reserved4 : 16; - - /* DW3 */ - u32 BusAddress; - - /* DW4 */ - /* u32 Value; */ - -#endif - -}; - - -struct reg_protocol_wt { - - -#ifdef __LITTLE_ENDIAN - - /* DW1 */ - u32 NumOfTrans:4; - u32 Reserved1:4; - u32 Reserved2:24; - /* DW2 */ - u32 ByteCount:7; - u32 WriteEnable:1; /* 0:read, 1:write */ - u32 FixOrContinuous:1; /* 0:continuous, 1: Fix */ - u32 BurstMode:1; - u32 Byte1Access:1; - u32 Byte2Access:1; - u32 Byte4Access:1; - u32 Reserved3:3; - u32 Reserved4:16; - /* DW3 */ - u32 BusAddress; - /* DW4 */ - u32 Value; - -#else - /* DW1 */ - u32 Reserved1 :4; - u32 NumOfTrans :4; - - u32 Reserved2 :24; - - /* DW2 */ - u32 WriteEnable : 1; - u32 ByteCount :7; - - u32 Reserved3 : 3; - u32 Byte4Access : 1; - - u32 Byte2Access : 1; - u32 Byte1Access : 1; - u32 BurstMode :1 ; - u32 FixOrContinuous : 1; - - u32 Reserved4 : 16; - - /* DW3 */ - u32 BusAddress; - - /* DW4 */ - u32 Value; - -#endif - -}; - -#define PlatformEFIOWrite1Byte(_a, _b, _c) \ - rtl8723au_write8(_a, _b, _c) -#define PlatformEFIOWrite2Byte(_a, _b, _c) \ - rtl8723au_write16(_a, _b, _c) -#define PlatformEFIOWrite4Byte(_a, _b, _c) \ - rtl8723au_write32(_a, _b, _c) - -#define PlatformEFIORead1Byte(_a, _b) rtl8723au_read8(_a, _b) -#define PlatformEFIORead2Byte(_a, _b) rtl8723au_read16(_a, _b) -#define PlatformEFIORead4Byte(_a, _b) rtl8723au_read32(_a, _b) - -#endif /* _RTL8711_IO_H_ */ diff --git a/drivers/staging/rtl8723au/include/rtw_mlme.h b/drivers/staging/rtl8723au/include/rtw_mlme.h deleted file mode 100644 index dbd3a5f..0000000 --- a/drivers/staging/rtl8723au/include/rtw_mlme.h +++ /dev/null @@ -1,340 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * - ******************************************************************************/ -#ifndef __RTW_MLME_H_ -#define __RTW_MLME_H_ - -#include <osdep_service.h> -#include <mlme_osdep.h> -#include <drv_types.h> -#include <wlan_bssdef.h> - -#define MAX_BSS_CNT 128 -#define MAX_JOIN_TIMEOUT 6500 - -/* Increase the scanning timeout because of increasing the SURVEY_TO value. */ - -#define SCANNING_TIMEOUT 8000 - -#define SCAN_INTERVAL (30) /* unit:2sec, 30*2 = 60sec */ - -#define SCANQUEUE_LIFETIME 20 /* unit:sec */ - -#define WIFI_NULL_STATE 0x00000000 - -#define WIFI_ASOC_STATE 0x00000001 /* Under Linked state.*/ -#define WIFI_REASOC_STATE 0x00000002 -#define WIFI_SLEEP_STATE 0x00000004 -#define WIFI_STATION_STATE 0x00000008 - -#define WIFI_AP_STATE 0x00000010 -#define WIFI_ADHOC_STATE 0x00000020 -#define WIFI_ADHOC_MASTER_STATE 0x00000040 -#define WIFI_UNDER_LINKING 0x00000080 - -#define WIFI_UNDER_WPS 0x00000100 -#define WIFI_STA_ALIVE_CHK_STATE 0x00000400 -/* to indicate the station is under site surveying */ -#define WIFI_SITE_MONITOR 0x00000800 - -#define WIFI_MP_STATE 0x00010000 -#define WIFI_MP_CTX_BACKGROUND 0x00020000 /* in continuous tx background */ -#define WIFI_MP_CTX_ST 0x00040000 /* in continuous tx with single-tone */ -#define WIFI_MP_CTX_BACKGROUND_PENDING 0x00080000 /* pending in continuous tx background due to out of skb */ -#define WIFI_MP_CTX_CCK_HW 0x00100000 /* in continuous tx */ -#define WIFI_MP_CTX_CCK_CS 0x00200000 /* in continuous tx with carrier suppression */ -#define WIFI_MP_LPBK_STATE 0x00400000 - -#define _FW_UNDER_LINKING WIFI_UNDER_LINKING -#define _FW_LINKED WIFI_ASOC_STATE -#define _FW_UNDER_SURVEY WIFI_SITE_MONITOR - - -enum dot11AuthAlgrthmNum { - dot11AuthAlgrthm_Open = 0, - dot11AuthAlgrthm_Shared, - dot11AuthAlgrthm_8021X, - dot11AuthAlgrthm_Auto, - dot11AuthAlgrthm_MaxNum -}; - -/* Scan type including active and passive scan. */ -enum rt_scan_type { - SCAN_PASSIVE, - SCAN_ACTIVE, - SCAN_MIX, -}; - -enum { - GHZ24_50 = 0, - GHZ_50, - GHZ_24, -}; - -/* - -there are several "locks" in mlme_priv, -since mlme_priv is a shared resource between many threads, -like ISR/Call-Back functions, the OID handlers, and even timer functions. - - -Each _queue has its own locks, already. -Other items are protected by mlme_priv.lock. - -To avoid possible dead lock, any thread trying to modifiying mlme_priv -SHALL not lock up more than one locks at a time! -*/ - -struct rt_link_detect { - u32 NumTxOkInPeriod; - u32 NumRxOkInPeriod; - u32 NumRxUnicastOkInPeriod; - bool bBusyTraffic; - bool bTxBusyTraffic; - bool bRxBusyTraffic; - bool bHigherBusyTraffic; /* For interrupt migration purpose. */ - bool bHigherBusyRxTraffic; /* We may disable Tx interrupt according as Rx traffic. */ - bool bHigherBusyTxTraffic; /* We may disable Tx interrupt according as Tx traffic. */ -}; - -struct mlme_priv { - spinlock_t lock; - int fw_state; - u8 bScanInProcess; - u8 to_join; /* flag */ - u8 to_roaming; /* roaming trying times */ - - struct rtw_adapter *nic_hdl; - - u8 not_indic_disco; - struct rtw_queue scanned_queue; - - struct cfg80211_ssid assoc_ssid; - u8 assoc_bssid[6]; - - struct wlan_network cur_network; - - /* uint wireless_mode; no used, remove it */ - - u32 scan_interval; - - struct timer_list assoc_timer; - - uint assoc_by_bssid; - uint assoc_by_rssi; - - struct timer_list scan_to_timer; - - struct timer_list set_scan_deny_timer; - atomic_t set_scan_deny; /* 0: allowed, 1: deny */ - - unsigned int qos_option; - - /* Number of non-HT AP/stations */ - int num_sta_no_ht; - - int num_FortyMHzIntolerant; - - struct ht_priv htpriv; - - struct rt_link_detect LinkDetectInfo; - struct timer_list dynamic_chk_timer; /* dynamic/periodic check timer */ - - u8 key_mask; /* use for ips to set wep key after ips_leave23a */ - u8 acm_mask; /* for wmm acm mask */ - u8 ChannelPlan; - enum rt_scan_type scan_mode; /* active: 1, passive: 0 */ - - u8 *wps_probe_req_ie; - u32 wps_probe_req_ie_len; - u8 *assoc_req; - u32 assoc_req_len; - u32 assoc_rsp_len; - u8 *assoc_rsp; - -#ifdef CONFIG_8723AU_AP_MODE - /* Number of associated Non-ERP stations (i.e., stations using 802.11b - * in 802.11g BSS) */ - int num_sta_non_erp; - - /* Number of associated stations that do not support Short Slot Time */ - int num_sta_no_short_slot_time; - - /* Number of associated stations that do not support Short Preamble */ - int num_sta_no_short_preamble; - - int olbc; /* Overlapping Legacy BSS Condition */ - - /* Number of HT associated stations that do not support greenfield */ - int num_sta_ht_no_gf; - - /* Number of associated non-HT stations */ - /* int num_sta_no_ht; */ - - /* Number of HT associated stations 20 MHz */ - int num_sta_ht_20mhz; - - /* Overlapping BSS information */ - int olbc_ht; - - u16 ht_op_mode; - - spinlock_t bcn_update_lock; - u8 update_bcn; - -#endif /* ifdef CONFIG_8723AU_AP_MODE */ -}; - -void rtw_joinbss_event_prehandle23a(struct rtw_adapter *adapter, u8 *pbuf); -void rtw_survey_event_cb23a(struct rtw_adapter *adapter, const u8 *pbuf); -void rtw_surveydone_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf); -void rtw23a_joinbss_event_cb(struct rtw_adapter *adapter, const u8 *pbuf); -void rtw_stassoc_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf); -void rtw_stadel_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf); - -int event_thread(void *context); -void rtw23a_join_to_handler(unsigned long); - -void rtw_free_network_queue23a(struct rtw_adapter *adapter); -int rtw_init_mlme_priv23a(struct rtw_adapter *adapter); - -void rtw_free_mlme_priv23a(struct mlme_priv *pmlmepriv); - -int rtw_do_join_adhoc(struct rtw_adapter *adapter); -int rtw_do_join_network(struct rtw_adapter *adapter, - struct wlan_network *candidate); -int rtw_select_and_join_from_scanned_queue23a(struct mlme_priv *pmlmepriv); -int rtw_set_key23a(struct rtw_adapter *adapter, - struct security_priv *psecuritypriv, int keyid, u8 set_tx); -int rtw_set_auth23a(struct rtw_adapter *adapter, - struct security_priv *psecuritypriv); - -static inline u8 *get_bssid(struct mlme_priv *pmlmepriv) -{ /* if sta_mode:pmlmepriv->cur_network.network.MacAddress => bssid */ - /* if adhoc_mode:pmlmepriv->cur_network.network.MacAddress => ibss mac address */ - return pmlmepriv->cur_network.network.MacAddress; -} - -static inline bool check_fwstate(struct mlme_priv *pmlmepriv, int state) -{ - if (pmlmepriv->fw_state & state) - return true; - - return false; -} - -static inline int get_fwstate(struct mlme_priv *pmlmepriv) -{ - return pmlmepriv->fw_state; -} - -/* - * No Limit on the calling context, - * therefore set it to be the critical section... - * - * ### NOTE:#### (!!!!) - * MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock - */ -static inline void set_fwstate(struct mlme_priv *pmlmepriv, int state) -{ - pmlmepriv->fw_state |= state; - /* FOR HW integration */ - if (_FW_UNDER_SURVEY == state) - pmlmepriv->bScanInProcess = true; -} - -static inline void _clr_fwstate_(struct mlme_priv *pmlmepriv, int state) -{ - pmlmepriv->fw_state &= ~state; - /* FOR HW integration */ - if (_FW_UNDER_SURVEY == state) - pmlmepriv->bScanInProcess = false; -} - -/* - * No Limit on the calling context, - * therefore set it to be the critical section... - */ -static inline void clr_fwstate(struct mlme_priv *pmlmepriv, int state) -{ - spin_lock_bh(&pmlmepriv->lock); - if (check_fwstate(pmlmepriv, state)) - pmlmepriv->fw_state ^= state; - spin_unlock_bh(&pmlmepriv->lock); -} - -static inline void clr_fwstate_ex(struct mlme_priv *pmlmepriv, int state) -{ - spin_lock_bh(&pmlmepriv->lock); - _clr_fwstate_(pmlmepriv, state); - spin_unlock_bh(&pmlmepriv->lock); -} - -void rtw_disconnect_hdl23a_under_linked(struct rtw_adapter *adapter, - struct sta_info *psta, u8 free_assoc); -void rtw_generate_random_ibss23a(u8 *pibss); -struct wlan_network *rtw_find_network23a(struct rtw_queue *scanned_queue, u8 *addr); -struct wlan_network *rtw_get_oldest_wlan_network23a(struct rtw_queue *scanned_queue); - -void rtw_free_assoc_resources23a(struct rtw_adapter *adapter, - int lock_scanned_queue); -void rtw_indicate_disconnect23a(struct rtw_adapter *adapter); -void rtw_indicate_connect23a(struct rtw_adapter *adapter); -void rtw_scan_abort23a(struct rtw_adapter *adapter); - -int rtw_restruct_sec_ie23a(struct rtw_adapter *adapter, u8 *in_ie, u8 *out_ie, - uint in_len); -int rtw_restruct_wmm_ie23a(struct rtw_adapter *adapter, u8 *in_ie, u8 *out_ie, - uint in_len, uint initial_out_len); -void rtw_init_registrypriv_dev_network23a(struct rtw_adapter *adapter); - -void rtw_update_registrypriv_dev_network23a(struct rtw_adapter *adapter); - -void rtw_scan_timeout_handler23a(unsigned long data); - -void rtw_dynamic_check_timer_handler(unsigned long data); -bool rtw_is_scan_deny(struct rtw_adapter *adapter); -void rtw_clear_scan_deny(struct rtw_adapter *adapter); -void rtw_set_scan_deny_timer_hdl(unsigned long data); -void rtw_set_scan_deny(struct rtw_adapter *adapter, u32 ms); - -void rtw23a_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv); - -void _rtw_free_mlme_priv23a(struct mlme_priv *pmlmepriv); - -struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv, gfp_t gfp); - -int rtw_if_up23a(struct rtw_adapter *padapter); - -int rtw_linked_check(struct rtw_adapter *padapter); - -void rtw_joinbss_reset23a(struct rtw_adapter *padapter); - -bool rtw_restructure_ht_ie23a(struct rtw_adapter *padapter, u8 *in_ie, - u8 *out_ie, uint in_len, uint *pout_len); -void rtw_update_ht_cap23a(struct rtw_adapter *padapter, - u8 *pie, uint ie_len); -void rtw_issue_addbareq_cmd23a(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe); - -bool rtw_is_same_ibss23a(struct rtw_adapter *adapter, - struct wlan_network *pnetwork); -int is_same_network23a(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst); - -void rtw23a_roaming(struct rtw_adapter *adapter, - struct wlan_network *tgt_network); -void rtw_set_roaming(struct rtw_adapter *adapter, u8 to_roaming); - -#endif /* __RTL871X_MLME_H_ */ diff --git a/drivers/staging/rtl8723au/include/rtw_mlme_ext.h b/drivers/staging/rtl8723au/include/rtw_mlme_ext.h deleted file mode 100644 index 0e7d3da..0000000 --- a/drivers/staging/rtl8723au/include/rtw_mlme_ext.h +++ /dev/null @@ -1,683 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __RTW_MLME_EXT_H_ -#define __RTW_MLME_EXT_H_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <wlan_bssdef.h> - - -/* Commented by Albert 20101105 */ -/* Increase the SURVEY_TO value from 100 to 150 ( 100ms to 150ms ) */ -/* The Realtek 8188CE SoftAP will spend around 100ms to send the probe response after receiving the probe request. */ -/* So, this driver tried to extend the dwell time for each scanning channel. */ -/* This will increase the chance to receive the probe response from SoftAP. */ - -#define SURVEY_TO (100) -#define REAUTH_TO (300) /* 50) */ -#define REASSOC_TO (300) /* 50) */ -/* define DISCONNECT_TO (3000) */ -#define ADDBA_TO (2000) - -#define LINKED_TO (1) /* unit:2 sec, 1x2=2 sec */ - -#define REAUTH_LIMIT (4) -#define REASSOC_LIMIT (4) -#define READDBA_LIMIT (2) - -#define ROAMING_LIMIT 8 - -#define DYNAMIC_FUNC_DISABLE (0x0) - -/* ====== enum odm_ability ======== */ -/* BB ODM section BIT 0-15 */ -#define DYNAMIC_BB_DIG BIT(0) -#define DYNAMIC_BB_RA_MASK BIT(1) -#define DYNAMIC_BB_DYNAMIC_TXPWR BIT(2) -#define DYNAMIC_BB_BB_FA_CNT BIT(3) - -#define DYNAMIC_BB_RSSI_MONITOR BIT(4) -#define DYNAMIC_BB_CCK_PD BIT(5) -#define DYNAMIC_BB_ANT_DIV BIT(6) -#define DYNAMIC_BB_PWR_SAVE BIT(7) -#define DYNAMIC_BB_PWR_TRAIN BIT(8) -#define DYNAMIC_BB_RATE_ADAPTIVE BIT(9) -#define DYNAMIC_BB_PATH_DIV BIT(10) -#define DYNAMIC_BB_PSD BIT(11) - -/* MAC DM section BIT 16-23 */ -#define DYNAMIC_MAC_struct edca_turboURBO BIT(16) -#define DYNAMIC_MAC_EARLY_MODE BIT(17) - -/* RF ODM section BIT 24-31 */ -#define DYNAMIC_RF_TX_PWR_TRACK BIT(24) -#define DYNAMIC_RF_RX_GAIN_TRACK BIT(25) -#define DYNAMIC_RF_CALIBRATION BIT(26) - -#define DYNAMIC_ALL_FUNC_ENABLE 0xFFFFFFF - -#define _HW_STATE_NOLINK_ 0x00 -#define _HW_STATE_ADHOC_ 0x01 -#define _HW_STATE_STATION_ 0x02 -#define _HW_STATE_AP_ 0x03 - - -#define _1M_RATE_ 0 -#define _2M_RATE_ 1 -#define _5M_RATE_ 2 -#define _11M_RATE_ 3 -#define _6M_RATE_ 4 -#define _9M_RATE_ 5 -#define _12M_RATE_ 6 -#define _18M_RATE_ 7 -#define _24M_RATE_ 8 -#define _36M_RATE_ 9 -#define _48M_RATE_ 10 -#define _54M_RATE_ 11 - - -extern unsigned char WMM_OUI23A[]; -extern unsigned char WPS_OUI23A[]; -extern unsigned char WFD_OUI23A[]; -extern unsigned char P2P_OUI23A[]; - -extern unsigned char WMM_INFO_OUI23A[]; -extern unsigned char WMM_PARA_OUI23A[]; - - -/* */ -/* Channel Plan Type. */ -/* Note: */ -/* We just add new channel plan when the new channel plan is different from any of the following */ -/* channel plan. */ -/* If you just want to customize the actions(scan period or join actions) about one of the channel plan, */ -/* customize them in struct rt_channel_info in the RT_CHANNEL_LIST. */ -/* */ -enum { /* _RT_CHANNEL_DOMAIN */ - /* old channel plan mapping ===== */ - RT_CHANNEL_DOMAIN_FCC = 0x00, - RT_CHANNEL_DOMAIN_IC = 0x01, - RT_CHANNEL_DOMAIN_ETSI = 0x02, - RT_CHANNEL_DOMAIN_SPAIN = 0x03, - RT_CHANNEL_DOMAIN_FRANCE = 0x04, - RT_CHANNEL_DOMAIN_MKK = 0x05, - RT_CHANNEL_DOMAIN_MKK1 = 0x06, - RT_CHANNEL_DOMAIN_ISRAEL = 0x07, - RT_CHANNEL_DOMAIN_TELEC = 0x08, - RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN = 0x09, - RT_CHANNEL_DOMAIN_WORLD_WIDE_13 = 0x0A, - RT_CHANNEL_DOMAIN_TAIWAN = 0x0B, - RT_CHANNEL_DOMAIN_CHINA = 0x0C, - RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO = 0x0D, - RT_CHANNEL_DOMAIN_KOREA = 0x0E, - RT_CHANNEL_DOMAIN_TURKEY = 0x0F, - RT_CHANNEL_DOMAIN_JAPAN = 0x10, - RT_CHANNEL_DOMAIN_FCC_NO_DFS = 0x11, - RT_CHANNEL_DOMAIN_JAPAN_NO_DFS = 0x12, - RT_CHANNEL_DOMAIN_WORLD_WIDE_5G = 0x13, - RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS = 0x14, - - /* new channel plan mapping, (2GDOMAIN_5GDOMAIN) ===== */ - RT_CHANNEL_DOMAIN_WORLD_NULL = 0x20, - RT_CHANNEL_DOMAIN_ETSI1_NULL = 0x21, - RT_CHANNEL_DOMAIN_FCC1_NULL = 0x22, - RT_CHANNEL_DOMAIN_MKK1_NULL = 0x23, - RT_CHANNEL_DOMAIN_ETSI2_NULL = 0x24, - RT_CHANNEL_DOMAIN_FCC1_FCC1 = 0x25, - RT_CHANNEL_DOMAIN_WORLD_ETSI1 = 0x26, - RT_CHANNEL_DOMAIN_MKK1_MKK1 = 0x27, - RT_CHANNEL_DOMAIN_WORLD_KCC1 = 0x28, - RT_CHANNEL_DOMAIN_WORLD_FCC2 = 0x29, - RT_CHANNEL_DOMAIN_WORLD_FCC3 = 0x30, - RT_CHANNEL_DOMAIN_WORLD_FCC4 = 0x31, - RT_CHANNEL_DOMAIN_WORLD_FCC5 = 0x32, - RT_CHANNEL_DOMAIN_WORLD_FCC6 = 0x33, - RT_CHANNEL_DOMAIN_FCC1_FCC7 = 0x34, - RT_CHANNEL_DOMAIN_WORLD_ETSI2 = 0x35, - RT_CHANNEL_DOMAIN_WORLD_ETSI3 = 0x36, - RT_CHANNEL_DOMAIN_MKK1_MKK2 = 0x37, - RT_CHANNEL_DOMAIN_MKK1_MKK3 = 0x38, - RT_CHANNEL_DOMAIN_FCC1_NCC1 = 0x39, - RT_CHANNEL_DOMAIN_FCC1_NCC2 = 0x40, - RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G = 0x41, - /* Add new channel plan above this line=============== */ - RT_CHANNEL_DOMAIN_MAX, - RT_CHANNEL_DOMAIN_REALTEK_DEFINE = 0x7F, -}; - -enum { /* _RT_CHANNEL_DOMAIN_2G */ - RT_CHANNEL_DOMAIN_2G_WORLD = 0x00, /* Worldwird 13 */ - RT_CHANNEL_DOMAIN_2G_ETSI1 = 0x01, /* Europe */ - RT_CHANNEL_DOMAIN_2G_FCC1 = 0x02, /* US */ - RT_CHANNEL_DOMAIN_2G_MKK1 = 0x03, /* Japan */ - RT_CHANNEL_DOMAIN_2G_ETSI2 = 0x04, /* France */ - RT_CHANNEL_DOMAIN_2G_NULL = 0x05, - /* Add new channel plan above this line=============== */ - RT_CHANNEL_DOMAIN_2G_MAX, -}; - -enum { /* _RT_CHANNEL_DOMAIN_5G */ - 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 */ - /* Add new channel plan above this line=============== */ - /* Driver Self Defined ===== */ - RT_CHANNEL_DOMAIN_5G_FCC = 0x11, - RT_CHANNEL_DOMAIN_5G_JAPAN_NO_DFS = 0x12, - RT_CHANNEL_DOMAIN_5G_FCC4_NO_DFS = 0x13, - 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 { - unsigned char Channel[MAX_CHANNEL_NUM]; - unsigned char Len; -}; - -struct rt_channel_plan_2g { - unsigned char Channel[MAX_CHANNEL_NUM_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 Associated_AP { - atherosAP = 0, - broadcomAP = 1, - ciscoAP = 2, - marvellAP = 3, - ralinkAP = 4, - realtekAP = 5, - airgocapAP = 6, - unknownAP = 7, - maxAP, -}; - -enum { /* HT_IOT_PEER_E */ - HT_IOT_PEER_UNKNOWN = 0, - HT_IOT_PEER_REALTEK = 1, - HT_IOT_PEER_REALTEK_92SE = 2, - HT_IOT_PEER_BROADCOM = 3, - HT_IOT_PEER_RALINK = 4, - HT_IOT_PEER_ATHEROS = 5, - HT_IOT_PEER_CISCO = 6, - HT_IOT_PEER_MERU = 7, - HT_IOT_PEER_MARVELL = 8, - HT_IOT_PEER_REALTEK_SOFTAP = 9,/* peer is RealTek SOFT_AP, by Bohn, 2009.12.17 */ - HT_IOT_PEER_SELF_SOFTAP = 10, /* Self is SoftAP */ - HT_IOT_PEER_AIRGO = 11, - HT_IOT_PEER_INTEL = 12, - HT_IOT_PEER_RTK_APCLIENT = 13, - HT_IOT_PEER_REALTEK_81XX = 14, - HT_IOT_PEER_REALTEK_WOW = 15, - HT_IOT_PEER_TENDA = 16, - HT_IOT_PEER_MAX = 17 -}; - -enum SCAN_STATE { - SCAN_DISABLE = 0, - SCAN_START = 1, - SCAN_TXNULL = 2, - SCAN_PROCESS = 3, - SCAN_COMPLETE = 4, - SCAN_STATE_MAX, -}; - -struct mlme_handler { - char *str; - int (*func)(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -}; - -struct action_handler { - unsigned int num; - char *str; - int (*func)(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -}; - -struct ss_res { - int state; - int bss_cnt; - int channel_idx; - int scan_mode; - u8 ssid_num; - u8 ch_num; - struct cfg80211_ssid ssid[RTW_SSID_SCAN_AMOUNT]; - struct rtw_ieee80211_channel ch[RTW_CHANNEL_SCAN_AMOUNT]; -}; - -#define WIFI_FW_AUTH_NULL 0x00000100 -#define WIFI_FW_AUTH_STATE 0x00000200 -#define WIFI_FW_AUTH_SUCCESS 0x00000400 - -#define WIFI_FW_ASSOC_STATE 0x00002000 -#define WIFI_FW_ASSOC_SUCCESS 0x00004000 - -#define WIFI_FW_LINKING_STATE (WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE | WIFI_FW_AUTH_SUCCESS |WIFI_FW_ASSOC_STATE) - -struct FW_Sta_Info { - struct sta_info *psta; - u32 status; - u32 rx_pkt; - u32 retry; - unsigned char SupportedRates[NDIS_802_11_LENGTH_RATES_EX]; -}; - -/* - * Usage: - * When one iface acted as AP mode and the other iface is STA mode and scanning, - * it should switch back to AP's operating channel periodically. - * Parameters 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, - * 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 - * 4. Back to channel 1 for 300 milliseconds - * 5. ... and so on, till survey done. - */ - -struct mlme_ext_info { - u32 state; - u32 reauth_count; - u32 reassoc_count; - u32 link_count; - u32 auth_seq; - u32 auth_algo; /* 802.11 auth, could be open, shared, auto */ - u32 authModeToggle; - u32 enc_algo;/* encrypt algorithm; */ - u32 key_index; /* this is only valid for legendary wep, 0~3 for key id. */ - u32 iv; - u8 chg_txt[128]; - u16 aid; - u16 bcn_interval; - u16 capability; - u8 assoc_AP_vendor; - u8 slotTime; - u8 preamble_mode; - u8 WMM_enable; - u8 ERP_enable; - u8 ERP_IE; - u8 HT_enable; - u8 HT_caps_enable; - u8 HT_info_enable; - u8 HT_protection; - u8 turboMode_cts2self; - u8 turboMode_rtsen; - u8 SM_PS; - u8 ADDBA_retry_count; - u8 dialogToken; - /* Accept ADDBA Request */ - bool bAcceptAddbaReq; - u8 bwmode_updated; - u8 hidden_ssid_mode; - - struct ADDBA_request ADDBA_req; - struct WMM_para_element WMM_param; - struct ieee80211_ht_cap ht_cap; - struct ieee80211_ht_operation HT_info; - struct wlan_bssid_ex network;/* join network or bss_network, if in ap mode, it is the same to cur_network.network */ - struct FW_Sta_Info FW_sta_info[NUM_STA]; -}; - -/* The channel information about this channel including joining, scanning, and power constraints. */ -struct rt_channel_info { - u8 ChannelNum; /* The channel number. */ - enum rt_scan_type ScanType; /* Scan type such as passive or active scan. */ -}; - -int rtw_ch_set_search_ch23a(struct rt_channel_info *ch_set, const u32 ch); - -/* P2P_MAX_REG_CLASSES - Maximum number of regulatory classes */ -#define P2P_MAX_REG_CLASSES 10 - -/* P2P_MAX_REG_CLASS_CHANNELS - Maximum number of channels per regulatory class */ -#define P2P_MAX_REG_CLASS_CHANNELS 20 - -/* struct p2p_channels - List of supported channels */ -struct p2p_channels { - /* struct p2p_reg_class - Supported regulatory class */ - struct p2p_reg_class { - /* reg_class - Regulatory class (IEEE 802.11-2007, Annex J) */ - u8 reg_class; - - /* channel - Supported channels */ - u8 channel[P2P_MAX_REG_CLASS_CHANNELS]; - - /* channels - Number of channel entries in use */ - size_t channels; - } reg_class[P2P_MAX_REG_CLASSES]; - - /* reg_classes - Number of reg_class entries in use */ - size_t reg_classes; -}; - -struct p2p_oper_class_map { - enum hw_mode {IEEE80211G, IEEE80211A} mode; - u8 op_class; - u8 min_chan; - u8 max_chan; - u8 inc; - enum { - BW20, BW40PLUS, BW40MINUS - } bw; -}; - -struct mlme_ext_priv { - struct rtw_adapter *padapter; - u8 mlmeext_init; - atomic_t event_seq; - u16 mgnt_seq; - - /* struct fw_priv fwpriv; */ - - unsigned char cur_channel; - unsigned char cur_bwmode; - unsigned char cur_ch_offset;/* PRIME_CHNL_OFFSET */ - unsigned char cur_wireless_mode; /* NETWORK_TYPE */ - - unsigned char max_chan_nums; - struct rt_channel_info channel_set[MAX_CHANNEL_NUM]; - struct p2p_channels channel_list; - unsigned char basicrate[NumRates]; - unsigned char datarate[NumRates]; - - struct ss_res sitesurvey_res; - struct mlme_ext_info mlmext_info;/* for sta/adhoc mode, including current scanning/connecting/connected related info. */ - /* for ap mode, network includes ap's cap_info */ - struct timer_list survey_timer; - struct timer_list link_timer; - u16 chan_scan_time; - - u8 scan_abort; - u8 tx_rate; /* TXRATE when USERATE is set. */ - - u32 retry; /* retry for issue probereq */ - - u64 TSFValue; - - unsigned char bstart_bss; - u8 update_channel_plan_by_ap_done; - /* recv_decache check for Action_public frame */ - u8 action_public_dialog_token; - u16 action_public_rxseq; - u8 active_keep_alive_check; -}; - -int init_mlme_ext_priv23a(struct rtw_adapter *padapter); -int init_hw_mlme_ext23a(struct rtw_adapter *padapter); -void free_mlme_ext_priv23a (struct mlme_ext_priv *pmlmeext); -void init_mlme_ext_timer23a(struct rtw_adapter *padapter); -void init_addba_retry_timer23a(struct sta_info *psta); -struct xmit_frame *alloc_mgtxmitframe23a(struct xmit_priv *pxmitpriv); - -unsigned char networktype_to_raid23a(unsigned char network_type); -u8 judge_network_type23a(struct rtw_adapter *padapter, unsigned char *rate, - int ratelen); -void get_rate_set23a(struct rtw_adapter *padapter, unsigned char *pbssrate, - int *bssrate_len); -void UpdateBrateTbl23a(struct rtw_adapter *padapter, u8 *mBratesOS); -void Update23aTblForSoftAP(u8 *bssrateset, u32 bssratelen); - -u8 rtw_get_oper_ch23a(struct rtw_adapter *adapter); -void rtw_set_oper_ch23a(struct rtw_adapter *adapter, u8 ch); -void rtw_set_oper_bw23a(struct rtw_adapter *adapter, u8 bw); -void rtw_set_oper_ch23aoffset23a(struct rtw_adapter *adapter, u8 offset); - -void set_channel_bwmode23a(struct rtw_adapter *padapter, unsigned char channel, - unsigned char channel_offset, unsigned short bwmode); -void SelectChannel23a(struct rtw_adapter *padapter, unsigned char channel); - -unsigned int decide_wait_for_beacon_timeout23a(unsigned int bcn_interval); - -void clear_cam_entry23a(struct rtw_adapter *padapter, u8 entry); - -void invalidate_cam_all23a(struct rtw_adapter *padapter); - -int allocate_fw_sta_entry23a(struct rtw_adapter *padapter); -void flush_all_cam_entry23a(struct rtw_adapter *padapter); - -bool IsLegal5GChannel(struct rtw_adapter *Adapter, u8 channel); - -void update_network23a(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src, - struct rtw_adapter *padapter, bool update_ie); - -u8 *get_my_bssid23a(struct wlan_bssid_ex *pnetwork); - -bool is_client_associated_to_ap23a(struct rtw_adapter *padapter); -bool is_client_associated_to_ibss23a(struct rtw_adapter *padapter); -bool is_IBSS_empty23a(struct rtw_adapter *padapter); - -unsigned char check_assoc_AP23a(u8 *pframe, uint len); - -int WMM_param_handler23a(struct rtw_adapter *padapter, const u8 *p); -void WMMOnAssocRsp23a(struct rtw_adapter *padapter); - -void HT_caps_handler23a(struct rtw_adapter *padapter, const u8 *p); -void HT_info_handler23a(struct rtw_adapter *padapter, const u8 *p); -void HTOnAssocRsp23a(struct rtw_adapter *padapter); - -void ERP_IE_handler23a(struct rtw_adapter *padapter, const u8 *p); -void VCS_update23a(struct rtw_adapter *padapter, struct sta_info *psta); - -void update_beacon23a_info(struct rtw_adapter *padapter, - struct ieee80211_mgmt *mgmt, uint len, - struct sta_info *psta); -int rtw_check_bcn_info23a(struct rtw_adapter *Adapter, - struct ieee80211_mgmt *mgmt, u32 packet_len); -void update_IOT_info23a(struct rtw_adapter *padapter); -void update_capinfo23a(struct rtw_adapter *Adapter, u16 updateCap); -void update_wireless_mode23a(struct rtw_adapter *padapter); -void update_tx_basic_rate23a(struct rtw_adapter *padapter, u8 modulation); -void update_bmc_sta_support_rate23a(struct rtw_adapter *padapter, u32 mac_id); -int update_sta_support_rate23a(struct rtw_adapter *padapter, u8 *pvar_ie, - uint var_ie_len, int cam_idx); - -/* for sta/adhoc mode */ -void update_sta_info23a(struct rtw_adapter *padapter, struct sta_info *psta); -unsigned int update_basic_rate23a(unsigned char *ptn, unsigned int ptn_sz); -unsigned int update_supported_rate23a(unsigned char *ptn, unsigned int ptn_sz); -unsigned int update_MSC_rate23a(struct ieee80211_ht_cap *ht_cap); -void Update_RA_Entry23a(struct rtw_adapter *padapter, struct sta_info *psta); -void set_sta_rate23a(struct rtw_adapter *padapter, struct sta_info *psta); - -int receive_disconnect23a(struct rtw_adapter *padapter, - unsigned char *MacAddr, unsigned short reason); - -unsigned char get_highest_rate_idx23a(u32 mask); -int support_short_GI23a(struct rtw_adapter *padapter, - struct ieee80211_ht_cap *ht_cap); -bool is_ap_in_tkip23a(struct rtw_adapter *padapter); -bool is_ap_in_wep23a(struct rtw_adapter *padapter); -bool should_forbid_n_rate23a(struct rtw_adapter *padapter); - -void report_join_res23a(struct rtw_adapter *padapter, int res); -void report_survey_event23a(struct rtw_adapter *padapter, - struct recv_frame *precv_frame); -void report_surveydone_event23a(struct rtw_adapter *padapter); -void report_del_sta_event23a(struct rtw_adapter *padapter, - unsigned char *MacAddr, unsigned short reason); -void report_add_sta_event23a(struct rtw_adapter *padapter, - unsigned char *MacAddr, int cam_idx); - -int set_tx_beacon_cmd23a(struct rtw_adapter*padapter); -unsigned int setup_beacon_frame(struct rtw_adapter *padapter, - unsigned char *beacon_frame); -void update_mgnt_tx_rate23a(struct rtw_adapter *padapter, u8 rate); -void update_mgntframe_attrib23a(struct rtw_adapter *padapter, - struct pkt_attrib *pattrib); -void dump_mgntframe23a(struct rtw_adapter *padapter, - struct xmit_frame *pmgntframe); -s32 dump_mgntframe23a_and_wait(struct rtw_adapter *padapter, - struct xmit_frame *pmgntframe, int timeout_ms); -s32 dump_mgntframe23a_and_wait_ack23a(struct rtw_adapter *padapter, - struct xmit_frame *pmgntframe); - -void issue_beacon23a(struct rtw_adapter *padapter, int timeout_ms); -int issue_nulldata23a(struct rtw_adapter *padapter, unsigned char *da, - unsigned int power_mode, int try_cnt, int wait_ms); -int issue_qos_nulldata23a(struct rtw_adapter *padapter, unsigned char *da, u16 tid, - int try_cnt, int wait_ms); -int issue_deauth23a(struct rtw_adapter *padapter, unsigned char *da, - unsigned short reason); -void issue_action_spct_ch_switch23a(struct rtw_adapter *padapter, u8 *ra, - u8 new_ch, u8 ch_offset); -void issue_action_BA23a(struct rtw_adapter *padapter, - const unsigned char *raddr, - unsigned char action, unsigned short status); -int send_delba23a(struct rtw_adapter *padapter, u8 initiator, u8 *addr); -int send_beacon23a(struct rtw_adapter *padapter); - -void mlmeext_joinbss_event_callback23a(struct rtw_adapter *padapter, int join_res); -void mlmeext_sta_del_event_callback23a(struct rtw_adapter *padapter); -void mlmeext_sta_add_event_callback23a(struct rtw_adapter *padapter, struct sta_info *psta); - -void linked_status_chk23a(struct rtw_adapter *padapter); - -#define set_survey_timer(mlmeext, ms) \ - /*DBG_8723A("%s set_survey_timer(%p, %d)\n", __func__, (mlmeext), (ms));*/ \ - mod_timer(&mlmeext->survey_timer, jiffies + msecs_to_jiffies(ms)); - -#define set_link_timer(mlmeext, ms) \ - /*DBG_8723A("%s set_link_timer(%p, %d)\n", __func__, (mlmeext), (ms));*/ \ - mod_timer(&mlmeext->link_timer, jiffies + msecs_to_jiffies(ms)); - -int cckrates_included23a(unsigned char *rate, int ratelen); -int cckratesonly_included23a(unsigned char *rate, int ratelen); - -void process_addba_req23a(struct rtw_adapter *padapter, u8 *paddba_req, u8 *addr); - -void correct_TSF23a(struct rtw_adapter *padapter, struct mlme_ext_priv *pmlmeext); - -struct cmd_hdl { - uint parmsize; - int (*h2cfuns)(struct rtw_adapter *padapter, const u8 *pbuf); -}; - - -int read_macreg_hdl(struct rtw_adapter *padapter, u8 *pbuf); -int write_macreg_hdl(struct rtw_adapter *padapter, u8 *pbuf); -int read_bbreg_hdl(struct rtw_adapter *padapter, u8 *pbuf); -int write_bbreg_hdl(struct rtw_adapter *padapter, u8 *pbuf); -int read_rfreg_hdl(struct rtw_adapter *padapter, u8 *pbuf); -int write_rfreg_hdl(struct rtw_adapter *padapter, u8 *pbuf); - - -int NULL_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); -int join_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); -int disconnect_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); -int createbss_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); -int setopmode_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); -int sitesurvey_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); -int setauth_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); -int setkey_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); -int set_stakey_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); -int set_assocsta_hdl(struct rtw_adapter *padapter, const u8 *pbuf); -int del_assocsta_hdl(struct rtw_adapter *padapter, const u8 *pbuf); -int add_ba_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); - -int mlme_evt_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); -int h2c_msg_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); -int tx_beacon_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); -int set_ch_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); -int set_chplan_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); -int led_blink_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); -int set_csa_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); /* Kurt: Handling DFS channel switch announcement ie. */ -int tdls_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf); - -#define GEN_DRV_CMD_HANDLER(size, cmd) {size, &cmd ## _hdl23a}, -#define GEN_MLME_EXT_HANDLER(size, cmd) {size, cmd}, - -struct C2HEvent_Header { -#ifdef __LITTLE_ENDIAN - - unsigned int len:16; - unsigned int ID:8; - unsigned int seq:8; - -#elif defined(__BIG_ENDIAN) - - unsigned int seq:8; - unsigned int ID:8; - unsigned int len:16; - -#else - -# error "Must be LITTLE or BIG Endian" - -#endif - - unsigned int rsvd; -}; - -enum rtw_c2h_event { - GEN_EVT_CODE(_Read_MACREG) = 0, /*0*/ - GEN_EVT_CODE(_Read_BBREG), - GEN_EVT_CODE(_Read_RFREG), - GEN_EVT_CODE(_Read_EEPROM), - GEN_EVT_CODE(_Read_EFUSE), - GEN_EVT_CODE(_Read_CAM), /*5*/ - GEN_EVT_CODE(_Get_BasicRate), - GEN_EVT_CODE(_Get_DataRate), - GEN_EVT_CODE(_Survey), /*8*/ - GEN_EVT_CODE(_SurveyDone), /*9*/ - - GEN_EVT_CODE(_JoinBss) , /*10*/ - GEN_EVT_CODE(_AddSTA), - GEN_EVT_CODE(_DelSTA), - GEN_EVT_CODE(_AtimDone) , - GEN_EVT_CODE(_TX_Report), - GEN_EVT_CODE(_CCX_Report), /*15*/ - GEN_EVT_CODE(_DTM_Report), - GEN_EVT_CODE(_TX_Rate_Statistics), - GEN_EVT_CODE(_C2HLBK), - GEN_EVT_CODE(_FWDBG), - GEN_EVT_CODE(_C2HFEEDBACK), /*20*/ - GEN_EVT_CODE(_ADDBA), - GEN_EVT_CODE(_C2HBCN), - GEN_EVT_CODE(_ReportPwrState), /* filen: only for PCIE, USB */ - GEN_EVT_CODE(_CloseRF), /* filen: only for PCIE, work around ASPM */ - MAX_C2HEVT -}; - -#endif diff --git a/drivers/staging/rtl8723au/include/rtw_pwrctrl.h b/drivers/staging/rtl8723au/include/rtw_pwrctrl.h deleted file mode 100644 index 699b9f3..0000000 --- a/drivers/staging/rtl8723au/include/rtw_pwrctrl.h +++ /dev/null @@ -1,242 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __RTW_PWRCTRL_H_ -#define __RTW_PWRCTRL_H_ - -#include <linux/mutex.h> -#include <osdep_service.h> -#include <drv_types.h> - -#define FW_PWR0 0 -#define FW_PWR1 1 -#define FW_PWR2 2 -#define FW_PWR3 3 - - -#define HW_PWR0 7 -#define HW_PWR1 6 -#define HW_PWR2 2 -#define HW_PWR3 0 -#define HW_PWR4 8 - -#define FW_PWRMSK 0x7 - - -#define XMIT_ALIVE BIT(0) -#define RECV_ALIVE BIT(1) -#define CMD_ALIVE BIT(2) -#define EVT_ALIVE BIT(3) - -enum Power_Mgnt { - PS_MODE_ACTIVE = 0, - PS_MODE_MIN, - PS_MODE_MAX, - PS_MODE_DTIM, - PS_MODE_VOIP, - PS_MODE_UAPSD_WMM, - PS_MODE_UAPSD, - PS_MODE_IBSS, - PS_MODE_WWLAN, - PM_Radio_Off, - PM_Card_Disable, - PS_MODE_NUM -}; - - -/* BIT[2:0] = HW state - * BIT[3] = Protocol PS state, 0: active, 1: sleep state - * BIT[4] = sub-state - */ - -#define PS_DPS BIT(0) -#define PS_LCLK (PS_DPS) -#define PS_RF_OFF BIT(1) -#define PS_ALL_ON BIT(2) -#define PS_ST_ACTIVE BIT(3) - -#define PS_ISR_ENABLE BIT(4) -#define PS_IMR_ENABLE BIT(5) -#define PS_ACK BIT(6) -#define PS_TOGGLE BIT(7) - -#define PS_STATE_MASK (0x0F) -#define PS_STATE_HW_MASK (0x07) -#define PS_SEQ_MASK (0xc0) - -#define PS_STATE(x) (PS_STATE_MASK & (x)) -#define PS_STATE_HW(x) (PS_STATE_HW_MASK & (x)) -#define PS_SEQ(x) (PS_SEQ_MASK & (x)) - -#define PS_STATE_S0 (PS_DPS) -#define PS_STATE_S1 (PS_LCLK) -#define PS_STATE_S2 (PS_RF_OFF) -#define PS_STATE_S3 (PS_ALL_ON) -#define PS_STATE_S4 ((PS_ST_ACTIVE) | (PS_ALL_ON)) - - -#define PS_IS_RF_ON(x) ((x) & (PS_ALL_ON)) -#define PS_IS_ACTIVE(x) ((x) & (PS_ST_ACTIVE)) -#define CLR_PS_STATE(x) ((x) = ((x) & (0xF0))) - - -struct reportpwrstate_parm { - unsigned char mode; - unsigned char state; /* the CPWM value */ - unsigned short rsvd; -}; - -#define LPS_DELAY_TIME (1*HZ) /* 1 sec */ - -#define EXE_PWR_NONE 0x01 -#define EXE_PWR_IPS 0x02 -#define EXE_PWR_LPS 0x04 - -/* RF state. */ -enum rt_rf_power_state { - rf_on, /* RF is on after RFSleep or RFOff */ - rf_sleep, /* 802.11 Power Save mode */ - rf_off, /* HW/SW Radio OFF or Inactive Power Save */ - /* Add the new RF state above this line===== */ - rf_max -}; - -/* RF Off Level for IPS or HW/SW radio off */ -#define RT_RF_OFF_LEVL_ASPM BIT(0) /* PCI ASPM */ -#define RT_RF_OFF_LEVL_CLK_REQ BIT(1) /* PCI clock request */ -#define RT_RF_OFF_LEVL_PCI_D3 BIT(2) /* PCI D3 mode */ -/* NIC halt, re-init hw params */ -#define RT_RF_OFF_LEVL_HALT_NIC BIT(3) -/* FW free, re-download the FW */ -#define RT_RF_OFF_LEVL_FREE_FW BIT(4) -#define RT_RF_OFF_LEVL_FW_32K BIT(5) /* FW in 32k */ -/* Always enable ASPM and Clock Req in initialization. */ -#define RT_RF_PS_LEVEL_ALWAYS_ASPM BIT(6) -/* When LPS is on, disable 2R if no packet is received or transmittd. */ -#define RT_RF_LPS_DISALBE_2R BIT(30) -#define RT_RF_LPS_LEVEL_ASPM BIT(31) /* LPS with ASPM */ - -#define RT_IN_PS_LEVEL(ppsc, _PS_FLAG) \ - ((ppsc->cur_ps_level & _PS_FLAG) ? true : false) -#define RT_CLEAR_PS_LEVEL(ppsc, _PS_FLAG) \ - (ppsc->cur_ps_level &= (~(_PS_FLAG))) -#define RT_SET_PS_LEVEL(ppsc, _PS_FLAG) \ - (ppsc->cur_ps_level |= _PS_FLAG) - - -enum { - PSBBREG_RF0 = 0, - PSBBREG_RF1, - PSBBREG_RF2, - PSBBREG_AFE0, - PSBBREG_TOTALCNT -}; - -enum { /* for ips_mode */ - IPS_NONE = 0, - IPS_NORMAL, - IPS_LEVEL_2, -}; - -struct pwrctrl_priv { - struct mutex mutex_lock; - volatile u8 rpwm; /* requested power state for fw */ - volatile u8 cpwm; /* fw current power state. updated when 1. - * read from HCPWM 2. driver lowers power level - */ - volatile u8 tog; /* toggling */ - - u8 pwr_mode; - u8 smart_ps; - u8 bcn_ant_mode; - - u8 bpower_saving; - - u8 reg_rfoff; - u32 rfoff_reason; - - /* RF OFF Level */ - u32 cur_ps_level; - u32 reg_rfps_level; - - uint ips_enter23a_cnts; - uint ips_leave23a_cnts; - - u8 ips_mode; - u8 ips_mode_req; /* used to accept the mode setting request */ - uint bips_processing; - unsigned long ips_deny_time; /* deny IPS when system time is smaller */ - u8 ps_processing; /* used to mark whether in rtw_ps_processor23a */ - - u8 bLeisurePs; - u8 LpsIdleCount; - u8 power_mgnt; - u8 bFwCurrentInPSMode; - unsigned long DelayLPSLastTimeStamp; - u8 btcoex_rfon; - - u8 bInSuspend; -#ifdef CONFIG_8723AU_BT_COEXIST - u8 bAutoResume; - u8 autopm_cnt; -#endif - u8 bSupportRemoteWakeup; - struct timer_list pwr_state_check_timer; - int pwr_state_check_interval; - u8 pwr_state_check_cnts; - - enum rt_rf_power_state rf_pwrstate;/* cur power state */ - enum rt_rf_power_state change_rfpwrstate; - - u8 bkeepfwalive; - unsigned long PS_BBRegBackup[PSBBREG_TOTALCNT]; -}; - -#define RTW_PWR_STATE_CHK_INTERVAL 2000 - -#define _rtw_set_pwr_state_check_timer(pwrctrlpriv, ms) \ - (mod_timer(&pwrctrlpriv->pwr_state_check_timer, jiffies + \ - msecs_to_jiffies(ms))) - -#define rtw_set_pwr_state_check_timer(pwrctrlpriv) \ - (_rtw_set_pwr_state_check_timer((pwrctrlpriv), \ - (pwrctrlpriv)->pwr_state_check_interval)) - -void rtw_init_pwrctrl_priv23a(struct rtw_adapter *adapter); -void rtw_free_pwrctrl_priv(struct rtw_adapter *adapter); - -void rtw_set_ps_mode23a(struct rtw_adapter *padapter, u8 ps_mode, - u8 smart_ps, u8 bcn_ant_mode); -void rtw_set_rpwm23a(struct rtw_adapter *padapter, u8 val8); -void LeaveAllPowerSaveMode23a(struct rtw_adapter *adapter); -void ips_enter23a(struct rtw_adapter *padapter); -int ips_leave23a(struct rtw_adapter *padapter); - -void rtw_ps_processor23a(struct rtw_adapter *padapter); - -enum rt_rf_power_state RfOnOffDetect23a(struct rtw_adapter *adapter); - -s32 LPS_RF_ON_check23a(struct rtw_adapter *padapter, u32 delay_ms); -void LPS_Enter23a(struct rtw_adapter *padapter); -void LPS_Leave23a(struct rtw_adapter *padapter); - -void rtw_set_ips_deny23a(struct rtw_adapter *padapter, u32 ms); -int _rtw_pwr_wakeup23a(struct rtw_adapter *padapter, u32 ips_deffer_ms, - const char *caller); -#define rtw_pwr_wakeup(adapter) _rtw_pwr_wakeup23a(adapter, \ - RTW_PWR_STATE_CHK_INTERVAL, __func__) -int rtw_pm_set_ips23a(struct rtw_adapter *padapter, u8 mode); -int rtw_pm_set_lps23a(struct rtw_adapter *padapter, u8 mode); - -#endif /* __RTL871X_PWRCTRL_H_ */ diff --git a/drivers/staging/rtl8723au/include/rtw_recv.h b/drivers/staging/rtl8723au/include/rtw_recv.h deleted file mode 100644 index 85a5edb..0000000 --- a/drivers/staging/rtl8723au/include/rtw_recv.h +++ /dev/null @@ -1,305 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef _RTW_RECV_H_ -#define _RTW_RECV_H_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <Hal8723APhyCfg.h> - -#define NR_RECVFRAME 256 - -#define MAX_RXFRAME_CNT 512 -#define MAX_RX_NUMBLKS (32) -#define RECVFRAME_HDR_ALIGN 128 - -#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr) - -#define MAX_SUBFRAME_COUNT 64 - -/* for Rx reordering buffer control */ -struct recv_reorder_ctrl { - struct rtw_adapter *padapter; - u8 enable; - u16 indicate_seq;/* wstart_b, init_value=0xffff */ - u16 wend_b; - u8 wsize_b; - struct rtw_queue pending_recvframe_queue; - struct timer_list reordering_ctrl_timer; -}; - -struct stainfo_rxcache { - u16 tid_rxseq[16]; -/* - unsigned short tid0_rxseq; - unsigned short tid1_rxseq; - unsigned short tid2_rxseq; - unsigned short tid3_rxseq; - unsigned short tid4_rxseq; - unsigned short tid5_rxseq; - unsigned short tid6_rxseq; - unsigned short tid7_rxseq; - unsigned short tid8_rxseq; - unsigned short tid9_rxseq; - unsigned short tid10_rxseq; - unsigned short tid11_rxseq; - unsigned short tid12_rxseq; - unsigned short tid13_rxseq; - unsigned short tid14_rxseq; - unsigned short tid15_rxseq; -*/ -}; - -struct smooth_rssi_data { - u32 elements[100]; /* array to store values */ - u32 index; /* index to current array to store */ - u32 total_num; /* num of valid elements */ - u32 total_val; /* sum of valid elements */ -}; - -struct signal_stat { - u8 update_req; /* used to indicate */ - u8 avg_val; /* avg of valid elements */ - u32 total_num; /* num of valid elements */ - u32 total_val; /* sum of valid elements */ -}; - -struct phy_info { - u8 RxPWDBAll; - u8 SignalQuality; /* in 0-100 index. */ - u8 RxMIMOSignalQuality[RF_PATH_MAX]; /* EVM */ - u8 RxMIMOSignalStrength[RF_PATH_MAX];/* 0~100 */ - s8 RxPower; /* in dBm Translate from PWdB */ - /* Real power in dBm for this packet, no beautification and aggregation. - * Keep this raw info to be used for the other procedures. - */ - s8 RecvSignalPower; - u8 BTRxRSSIPercentage; - u8 SignalStrength; /* in 0-100 index. */ - u8 RxPwr[RF_PATH_MAX];/* per-path's pwdb */ - u8 RxSNR[RF_PATH_MAX];/* per-path's SNR */ -}; - - -struct rx_pkt_attrib { - u16 pkt_len; - u8 physt; - u8 drvinfo_sz; - u8 shift_sz; - u8 hdrlen; /* the WLAN Header Len */ - u8 amsdu; - u8 qos; - u8 priority; - u8 pw_save; - u8 mdata; - u16 seq_num; - u8 frag_num; - u8 mfrag; - u8 order; - u8 privacy; /* in frame_ctrl field */ - u8 bdecrypted; - /* when 0 indicate no encrypt. when non-zero, indicate the algorith */ - u32 encrypt; - u8 iv_len; - u8 icv_len; - u8 crc_err; - u8 icv_err; - - u16 eth_type; - - u8 dst[ETH_ALEN]; - u8 src[ETH_ALEN]; - u8 ta[ETH_ALEN]; - u8 ra[ETH_ALEN]; - u8 bssid[ETH_ALEN]; - - u8 ack_policy; - - u8 tcpchk_valid; /* 0: invalid, 1: valid */ - u8 ip_chkrpt; /* 0: incorrect, 1: correct */ - u8 tcp_chkrpt; /* 0: incorrect, 1: correct */ - u8 key_index; - - u8 mcs_rate; - u8 rxht; - u8 sgi; - u8 pkt_rpt_type; - u32 MacIDValidEntry[2]; /* 64 bits present 64 entry. */ - struct phy_info phy_info; -}; - -/* These definition is used for Rx packet reordering. */ -#define SN_LESS(a, b) (((a-b) & 0x800) != 0) -#define SN_EQUAL(a, b) (a == b) -#define REORDER_WAIT_TIME (50) /* (ms) */ - -#define RECVBUFF_ALIGN_SZ 8 - -#define RXDESC_SIZE 24 -#define RXDESC_OFFSET RXDESC_SIZE - -struct recv_stat { - __le32 rxdw0; - __le32 rxdw1; - __le32 rxdw2; - __le32 rxdw3; - __le32 rxdw4; - __le32 rxdw5; -}; - -/* accesser of recv_priv: rtw_recv_entry23a(dispatch / passive level); \ - * recv_thread(passive) ; returnpkt(dispatch) ; halt(passive) ; - * - * using enter_critical section to protect - */ -struct recv_priv { - spinlock_t lock; - - struct rtw_queue free_recv_queue; - struct rtw_queue recv_pending_queue; - struct rtw_queue uc_swdec_pending_queue; - - int free_recvframe_cnt; - - struct rtw_adapter *adapter; - - u32 bIsAnyNonBEPkts; - u64 rx_bytes; - u64 rx_pkts; - u64 rx_drop; - u64 last_rx_bytes; - - uint rx_icv_err; - uint rx_largepacket_crcerr; - uint rx_smallpacket_crcerr; - uint rx_middlepacket_crcerr; - - /* u8 *pallocated_urb_buf; */ - u8 rx_pending_cnt; - - struct urb *int_in_urb; - - u8 *int_in_buf; - - struct tasklet_struct irq_prepare_beacon_tasklet; - struct tasklet_struct recv_tasklet; - struct sk_buff_head free_recv_skb_queue; - struct sk_buff_head rx_skb_queue; - u8 *precv_buf; - - /* For display the phy informatiom */ - s8 rxpwdb; - u8 signal_strength; - u8 signal_qual; - u8 noise; - int RxSNRdB[2]; - s8 RxRssi[2]; - int FalseAlmCnt_all; - - struct timer_list signal_stat_timer; - u32 signal_stat_sampling_interval; - /* u32 signal_stat_converging_constant; */ - struct signal_stat signal_qual_data; - struct signal_stat signal_strength_data; -}; - -#define rtw_set_signal_stat_timer(recvpriv) \ - mod_timer(&(recvpriv)->signal_stat_timer, jiffies + \ - msecs_to_jiffies((recvpriv)->signal_stat_sampling_interval)) - -struct sta_recv_priv { - spinlock_t lock; - int option; - - /* struct rtw_queue blk_strms[MAX_RX_NUMBLKS]; */ - struct rtw_queue defrag_q; /* keeping the fragment frame until defrag */ - - struct stainfo_rxcache rxcache; - - /* uint sta_rx_bytes; */ - /* uint sta_rx_pkts; */ - /* uint sta_rx_fail; */ - -}; - - -struct recv_buf { - struct list_head list; - - struct rtw_adapter *adapter; - - struct urb *purb; - struct sk_buff *pskb; -}; - -/* head -----> - * - * data -----> - * - * payload - * - * tail -----> - * - * end -----> - * - * len = (unsigned int )(tail - data); - * - */ -struct recv_frame { - struct list_head list; - struct sk_buff *pkt; - - struct rtw_adapter *adapter; - - struct rx_pkt_attrib attrib; - - struct sta_info *psta; - - /* for A-MPDU Rx reordering buffer control */ - struct recv_reorder_ctrl *preorder_ctrl; -}; - -/* get a free recv_frame from pfree_recv_queue */ -struct recv_frame *rtw_alloc_recvframe23a(struct rtw_queue *pfree_recv_queue); -int rtw_free_recvframe23a(struct recv_frame *precvframe); - -int rtw_enqueue_recvframe23a(struct recv_frame *precvframe, struct rtw_queue *queue); - -u32 rtw_free_uc_swdec_pending_queue23a(struct rtw_adapter *adapter); - -struct recv_buf *rtw_dequeue_recvbuf23a(struct rtw_queue *queue); - -void rtw_reordering_ctrl_timeout_handler23a(unsigned long pcontext); - -static inline s32 translate_percentage_to_dbm(u32 SignalStrengthIndex) -{ - s32 SignalPower; /* in dBm. */ - - /* Translate to dBm (x=0.5y-95). */ - SignalPower = (s32)((SignalStrengthIndex + 1) >> 1); - SignalPower -= 95; - - return SignalPower; -} - - -struct sta_info; - -void _rtw_init_sta_recv_priv23a(struct sta_recv_priv *psta_recvpriv); - -void mgt_dispatcher23a(struct rtw_adapter *padapter, - struct recv_frame *precv_frame); - -#endif diff --git a/drivers/staging/rtl8723au/include/rtw_rf.h b/drivers/staging/rtl8723au/include/rtw_rf.h deleted file mode 100644 index a7de714..0000000 --- a/drivers/staging/rtl8723au/include/rtw_rf.h +++ /dev/null @@ -1,102 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __RTW_RF_H_ -#define __RTW_RF_H_ - -#include <rtw_cmd.h> - -#define OFDM_PHY 1 -#define MIXED_PHY 2 -#define CCK_PHY 3 - -#define NumRates (13) - -/* slot time for 11g */ -#define SHORT_SLOT_TIME 9 -#define NON_SHORT_SLOT_TIME 20 - -/* We now define the max channels in each channel plan. */ -#define MAX_CHANNEL_NUM_2G 14 -#define MAX_CHANNEL_NUM_5G 24 -#define MAX_CHANNEL_NUM 38/* 14+24 */ - -/* define NUM_REGULATORYS 21 */ -#define NUM_REGULATORYS 1 - -/* Country codes */ -#define USA 0x555320 -#define EUROPE 0x1 /* temp, should be provided later */ -#define JAPAN 0x2 /* temp, should be provided later */ - -struct regulatory_class { - u32 starting_freq; /* MHz, */ - u8 channel_set[MAX_CHANNEL_NUM]; - u8 channel_cck_power[MAX_CHANNEL_NUM];/* dbm */ - u8 channel_ofdm_power[MAX_CHANNEL_NUM];/* dbm */ - u8 txpower_limit; /* dbm */ - u8 channel_spacing; /* MHz */ - u8 modem; -}; - -enum { - cESS = 0x0001, - cIBSS = 0x0002, - cPollable = 0x0004, - cPollReq = 0x0008, - cPrivacy = 0x0010, - cShortPreamble = 0x0020, - cPBCC = 0x0040, - cChannelAgility = 0x0080, - cSpectrumMgnt = 0x0100, - cQos = 0x0200, /* For HCCA, use with CF-Pollable and CF-PollReq */ - cShortSlotTime = 0x0400, - cAPSD = 0x0800, - cRM = 0x1000, /* RRM (Radio Request Measurement) */ - cDSSS_OFDM = 0x2000, - cDelayedBA = 0x4000, - cImmediateBA = 0x8000, -}; - -enum { - PREAMBLE_LONG = 1, - PREAMBLE_AUTO = 2, - PREAMBLE_SHORT = 3, -}; - -/* Bandwidth Offset */ -#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0 -#define HAL_PRIME_CHNL_OFFSET_LOWER 1 -#define HAL_PRIME_CHNL_OFFSET_UPPER 2 - -/* Represent Channel Width in HT Capabilities */ -enum ht_channel_width { - HT_CHANNEL_WIDTH_20 = 0, - HT_CHANNEL_WIDTH_40 = 1, - HT_CHANNEL_WIDTH_80 = 2, - HT_CHANNEL_WIDTH_160 = 3, - HT_CHANNEL_WIDTH_10 = 4, -}; - -/* 2007/11/15 MH Define different RF type. */ -enum { - RF_1T2R = 0, - RF_2T4R = 1, - RF_2T2R = 2, - RF_1T1R = 3, - RF_2T2R_GREEN = 4, - RF_819X_MAX_TYPE = 5, -}; - -#endif /* _RTL8711_RF_H_ */ diff --git a/drivers/staging/rtl8723au/include/rtw_security.h b/drivers/staging/rtl8723au/include/rtw_security.h deleted file mode 100644 index 624a9d7..0000000 --- a/drivers/staging/rtl8723au/include/rtw_security.h +++ /dev/null @@ -1,331 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __RTW_SECURITY_H_ -#define __RTW_SECURITY_H_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <net/lib80211.h> - - -#define is_wep_enc(alg) (alg == WLAN_CIPHER_SUITE_WEP40 || \ - alg == WLAN_CIPHER_SUITE_WEP104) - -#define SHA256_MAC_LEN 32 -#define AES_BLOCK_SIZE 16 -#define AES_PRIV_SIZE (4 * 44) - -enum ENCRYP_PROTOCOL { - ENCRYP_PROTOCOL_OPENSYS, /* open system */ - ENCRYP_PROTOCOL_WEP, /* WEP */ - ENCRYP_PROTOCOL_WPA, /* WPA */ - ENCRYP_PROTOCOL_WPA2, /* WPA2 */ - ENCRYP_PROTOCOL_MAX -}; - -#ifndef Ndis802_11AuthModeWPA2 -#define Ndis802_11AuthModeWPA2 (Ndis802_11AuthModeWPANone + 1) -#endif - -#ifndef Ndis802_11AuthModeWPA2PSK -#define Ndis802_11AuthModeWPA2PSK (Ndis802_11AuthModeWPANone + 2) -#endif - -union pn48 { - u64 val; - -#ifdef __LITTLE_ENDIAN - -struct { - u8 TSC0; - u8 TSC1; - u8 TSC2; - u8 TSC3; - u8 TSC4; - u8 TSC5; - u8 TSC6; - u8 TSC7; -} _byte_; - -#elif defined(__BIG_ENDIAN) - -struct { - u8 TSC7; - u8 TSC6; - u8 TSC5; - u8 TSC4; - u8 TSC3; - u8 TSC2; - u8 TSC1; - u8 TSC0; -} _byte_; -#else -#error Need BIG or LITTLE endian - -#endif - -}; - -union Keytype { - u8 skey[16]; - u32 lkey[4]; -}; - -struct rtw_wep_key { - u8 key[WLAN_KEY_LEN_WEP104 + 1]; /* 14 */ - u16 keylen; -}; - -struct rt_pmkid_list { - u8 bUsed; - u8 Bssid[6]; - u8 PMKID[16]; - u8 SsidBuf[33]; - u8 *ssid_octet; - u16 ssid_length; -}; - -struct security_priv { - u32 dot11AuthAlgrthm; /* 802.11 auth, could be open, shared, - * 8021x and authswitch */ - u32 dot11PrivacyAlgrthm; /* This specifies the privacy for - * shared auth. algorithm. - */ - /* WEP */ - u32 dot11PrivacyKeyIndex; /* this is only valid for legendary - * wep, 0~3 for key id. (tx key index) - */ - struct rtw_wep_key wep_key[NUM_WEP_KEYS]; - - u32 dot118021XGrpPrivacy; /* specify the privacy algthm. - * used for Grp key - */ - u32 dot118021XGrpKeyid; /* key id used for Grp Key - * (tx key index) - */ - union Keytype dot118021XGrpKey[4];/* 802.1x Grp Key, inx0 and inx1 */ - union Keytype dot118021XGrptxmickey[4]; - union Keytype dot118021XGrprxmickey[4]; - union pn48 dot11Grptxpn; /* PN48 used for Grp Key xmit.*/ - union pn48 dot11Grprxpn; /* PN48 used for Grp Key recv.*/ - -#ifdef CONFIG_8723AU_AP_MODE - /* extend security capabilities for AP_MODE */ - unsigned int dot8021xalg;/* 0:disable, 1:psk, 2:802.1x */ - unsigned int wpa_psk;/* 0:disable, bit(0): WPA, bit(1):WPA2 */ - unsigned int wpa_group_cipher; - unsigned int wpa2_group_cipher; - unsigned int wpa_pairwise_cipher; - unsigned int wpa2_pairwise_cipher; -#endif - - u8 wps_ie[MAX_WPS_IE_LEN];/* added in assoc req */ - int wps_ie_len; - unsigned int binstallGrpkey:1; - unsigned int busetkipkey:1; - unsigned int bcheck_grpkey:1; - unsigned int hw_decrypted:1; - u32 ndisauthtype; /* enum ndis_802_11_auth_mode */ - u32 ndisencryptstatus; /* NDIS_802_11_ENCRYPTION_STATUS */ - struct wlan_bssid_ex sec_bss; /* for joinbss (h2c buffer) usage */ - u8 assoc_info[600]; - u8 szofcapability[256]; /* for wpa2 usage */ - u8 oidassociation[512]; /* for wpa/wpa2 usage */ - u8 supplicant_ie[256]; /* store sta security information element */ - - /* for tkip countermeasure */ - unsigned long last_mic_err_time; - u8 btkip_countermeasure; - u8 btkip_wait_report; - unsigned long btkip_countermeasure_time; - - /* For WPA2 Pre-Authentication. */ - struct rt_pmkid_list PMKIDList[NUM_PMKID_CACHE]; - u8 PMKIDIndex; - u8 bWepDefaultKeyIdxSet; -}; - -struct sha256_state { - u64 length; - u32 state[8], curlen; - u8 buf[64]; -}; - -#define GET_ENCRY_ALGO(psecuritypriv, psta, encry_algo, bmcst)\ -do {\ - switch (psecuritypriv->dot11AuthAlgrthm) {\ - case dot11AuthAlgrthm_Open:\ - case dot11AuthAlgrthm_Shared:\ - case dot11AuthAlgrthm_Auto:\ - encry_algo = psecuritypriv->dot11PrivacyAlgrthm;\ - break;\ - case dot11AuthAlgrthm_8021X:\ - if (bmcst)\ - encry_algo = psecuritypriv->dot118021XGrpPrivacy;\ - else\ - encry_algo = psta->dot118021XPrivacy;\ - break;\ - } \ -} while (0) - -#define GET_TKIP_PN(iv, dot11txpn)\ -do {\ - dot11txpn._byte_.TSC0 = iv[2];\ - dot11txpn._byte_.TSC1 = iv[0];\ - dot11txpn._byte_.TSC2 = iv[4];\ - dot11txpn._byte_.TSC3 = iv[5];\ - dot11txpn._byte_.TSC4 = iv[6];\ - dot11txpn._byte_.TSC5 = iv[7];\ -} while (0) - -#define ROL32(A, n) (((A) << (n)) | (((A)>>(32-(n))) & ((1UL << (n)) - 1))) -#define ROR32(A, n) ROL32((A), 32-(n)) - -struct mic_data { - u32 K0, K1; /* Key */ - u32 L, R; /* Current state */ - u32 M; /* Message accumulator (single word) */ - 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. */ - -/* the K array */ -static const unsigned long K[64] = { - 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, - 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, - 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, - 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, - 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, - 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, - 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, - 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, - 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, - 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, - 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, - 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, - 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL -}; - -void rtw_secmicsetkey23a(struct mic_data *pmicdata, u8 *key); -void rtw_secmicappend23abyte23a(struct mic_data *pmicdata, u8 b); -void rtw_secmicappend23a(struct mic_data *pmicdata, u8 *src, u32 nbBytes); -void rtw_secgetmic23a(struct mic_data *pmicdata, u8 *dst); - -void rtw_seccalctkipmic23a(u8 *key, u8 *header, u8 *data, u32 data_len, - u8 *Miccode, u8 priorityi); - -int rtw_aes_encrypt23a(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe); -int rtw_tkip_encrypt23a(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe); -void rtw_wep_encrypt23a(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe); -int rtw_aes_decrypt23a(struct rtw_adapter *padapter, - struct recv_frame *precvframe); -int rtw_tkip_decrypt23a(struct rtw_adapter *padapter, - struct recv_frame *precvframe); -void rtw_wep_decrypt23a(struct rtw_adapter *padapter, struct recv_frame *precvframe); - -void rtw_use_tkipkey_handler23a(void *FunctionContext); - -#endif /* __RTL871X_SECURITY_H_ */ diff --git a/drivers/staging/rtl8723au/include/rtw_sreset.h b/drivers/staging/rtl8723au/include/rtw_sreset.h deleted file mode 100644 index 60fa829..0000000 --- a/drivers/staging/rtl8723au/include/rtw_sreset.h +++ /dev/null @@ -1,36 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef _RTW_SRESET_C_ -#define _RTW_SRESET_C_ - -#include <osdep_service.h> -#include <drv_types.h> - -struct sreset_priv { - struct mutex silentreset_mutex; - u8 silent_reset_inprogress; - unsigned long last_tx_time; - unsigned long last_tx_complete_time; -}; - -#include <rtl8723a_hal.h> - -void rtw_sreset_init(struct rtw_adapter *padapter); -void rtw_sreset_reset_value(struct rtw_adapter *padapter); -bool rtw_sreset_inprogress(struct rtw_adapter *padapter); -void sreset_set_trigger_point(struct rtw_adapter *padapter, s32 tgp); -void rtw_sreset_reset(struct rtw_adapter *active_adapter); - -#endif diff --git a/drivers/staging/rtl8723au/include/rtw_version.h b/drivers/staging/rtl8723au/include/rtw_version.h deleted file mode 100644 index c947733..0000000 --- a/drivers/staging/rtl8723au/include/rtw_version.h +++ /dev/null @@ -1 +0,0 @@ -#define DRIVERVERSION "v4.1.6_7336.20130426" diff --git a/drivers/staging/rtl8723au/include/rtw_xmit.h b/drivers/staging/rtl8723au/include/rtw_xmit.h deleted file mode 100644 index 24f326b..0000000 --- a/drivers/staging/rtl8723au/include/rtw_xmit.h +++ /dev/null @@ -1,380 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef _RTW_XMIT_H_ -#define _RTW_XMIT_H_ - -#include <osdep_service.h> -#include <drv_types.h> - -#define MAX_XMITBUF_SZ 2048 -#define NR_XMITBUFF 4 - -#define XMITBUF_ALIGN_SZ 512 - -/* xmit extension buff defination */ -#define MAX_XMIT_EXTBUF_SZ 1536 -#define NR_XMIT_EXTBUFF 32 - -#define MAX_NUMBLKS 1 - -#define XMIT_VO_QUEUE 0 -#define XMIT_VI_QUEUE 1 -#define XMIT_BE_QUEUE 2 -#define XMIT_BK_QUEUE 3 - -#define VO_QUEUE_INX 0 -#define VI_QUEUE_INX 1 -#define BE_QUEUE_INX 2 -#define BK_QUEUE_INX 3 -#define BCN_QUEUE_INX 4 -#define MGT_QUEUE_INX 5 -#define HIGH_QUEUE_INX 6 -#define TXCMD_QUEUE_INX 7 - -#define HW_QUEUE_ENTRY 8 - -#define WEP_IV(pattrib_iv, dot11txpn, keyidx) \ -do { \ - pattrib_iv[0] = dot11txpn._byte_.TSC0; \ - pattrib_iv[1] = dot11txpn._byte_.TSC1; \ - pattrib_iv[2] = dot11txpn._byte_.TSC2; \ - pattrib_iv[3] = ((keyidx & 0x3) << 6); \ - dot11txpn.val = (dot11txpn.val == 0xffffff) ? 0 : \ - (dot11txpn.val+1); \ -} while (0) - -#define TKIP_IV(pattrib_iv, dot11txpn, keyidx) \ -do { \ - pattrib_iv[0] = dot11txpn._byte_.TSC1; \ - pattrib_iv[1] = (dot11txpn._byte_.TSC1 | 0x20) & 0x7f; \ - pattrib_iv[2] = dot11txpn._byte_.TSC0; \ - pattrib_iv[3] = BIT(5) | ((keyidx & 0x3)<<6); \ - pattrib_iv[4] = dot11txpn._byte_.TSC2; \ - pattrib_iv[5] = dot11txpn._byte_.TSC3; \ - pattrib_iv[6] = dot11txpn._byte_.TSC4; \ - pattrib_iv[7] = dot11txpn._byte_.TSC5; \ - dot11txpn.val = dot11txpn.val == 0xffffffffffffULL ? 0 : \ - (dot11txpn.val+1); \ -} while (0) - -#define AES_IV(pattrib_iv, dot11txpn, keyidx)\ -do { \ - pattrib_iv[0] = dot11txpn._byte_.TSC0; \ - pattrib_iv[1] = dot11txpn._byte_.TSC1; \ - pattrib_iv[2] = 0; \ - pattrib_iv[3] = BIT(5) | ((keyidx & 0x3) << 6); \ - pattrib_iv[4] = dot11txpn._byte_.TSC2; \ - pattrib_iv[5] = dot11txpn._byte_.TSC3; \ - pattrib_iv[6] = dot11txpn._byte_.TSC4; \ - pattrib_iv[7] = dot11txpn._byte_.TSC5; \ - dot11txpn.val = dot11txpn.val == 0xffffffffffffULL ? 0 : \ - (dot11txpn.val+1); \ -} while (0) - -#define HWXMIT_ENTRY 4 - -#define TXDESC_SIZE 32 - -#define PACKET_OFFSET_SZ 8 -#define TXDESC_OFFSET (TXDESC_SIZE + PACKET_OFFSET_SZ) - -struct tx_desc { - /* DWORD 0 */ - __le32 txdw0; - __le32 txdw1; - __le32 txdw2; - __le32 txdw3; - __le32 txdw4; - __le32 txdw5; - __le32 txdw6; - __le32 txdw7; -}; - -union txdesc { - struct tx_desc txdesc; - unsigned int value[TXDESC_SIZE>>2]; -}; - -struct hw_xmit { - struct rtw_queue *sta_queue; - int accnt; -}; - -/* reduce size */ -struct pkt_attrib { - u16 type; - u8 bswenc; - u8 dhcp_pkt; - u16 ether_type; - u16 seqnum; - u16 pkt_hdrlen; /* the original 802.3 pkt header len */ - u16 hdrlen; /* the WLAN Header Len */ - u32 pktlen; /* the original 802.3 pkt raw_data len */ - u32 last_txcmdsz; - u32 encrypt; /* when 0 indicate no encrypt. */ - u8 nr_frags; - u8 iv_len; - u8 icv_len; - u8 iv[18]; - u8 icv[16]; - u8 priority; - u8 ack_policy; - u8 mac_id; - u8 vcs_mode; /* virtual carrier sense method */ - u8 dst[ETH_ALEN]; - u8 src[ETH_ALEN]; - u8 ta[ETH_ALEN]; - u8 ra[ETH_ALEN]; - u8 key_idx; - u8 qos_en; - u8 ht_en; - u8 raid;/* rate adpative id */ - u8 bwmode; - u8 ch_offset;/* PRIME_CHNL_OFFSET */ - u8 sgi;/* short GI */ - u8 ampdu_en;/* tx ampdu enable */ - u8 mdata;/* more data bit */ - u8 pctrl;/* per packet txdesc control enable */ - u8 triggered;/* for ap mode handling Power Saving sta */ - u8 qsel; - u8 eosp; - u8 rate; - u8 retry_ctrl; - struct sta_info *psta; -}; - -#define WLANHDR_OFFSET 64 - -#define NULL_FRAMETAG 0x0 -#define DATA_FRAMETAG 0x01 -#define L2_FRAMETAG 0x02 -#define MGNT_FRAMETAG 0x03 -#define AMSDU_FRAMETAG 0x04 - -#define EII_FRAMETAG 0x05 -#define IEEE8023_FRAMETAG 0x06 - -#define MP_FRAMETAG 0x07 - -#define TXAGG_FRAMETAG 0x08 - -struct submit_ctx { - u32 timeout_ms; /* <0: not synchronous, 0: wait forever, - * >0: up to ms waiting - */ - int status; /* status for operation */ - struct completion done; -}; - -enum { - RTW_SCTX_SUBMITTED = -1, - RTW_SCTX_DONE_SUCCESS = 0, - RTW_SCTX_DONE_UNKNOWN, - RTW_SCTX_DONE_TIMEOUT, - RTW_SCTX_DONE_BUF_ALLOC, - RTW_SCTX_DONE_BUF_FREE, - RTW_SCTX_DONE_WRITE_PORT_ERR, - RTW_SCTX_DONE_TX_DESC_NA, - RTW_SCTX_DONE_TX_DENY, - RTW_SCTX_DONE_CCX_PKT_FAIL, - RTW_SCTX_DONE_DRV_STOP, - RTW_SCTX_DONE_DEV_REMOVE, -}; - -void rtw_sctx_init23a(struct submit_ctx *sctx, int timeout_ms); -int rtw_sctx_wait23a(struct submit_ctx *sctx); -void rtw23a_sctx_done_err(struct submit_ctx **sctx, int status); - -struct xmit_buf { - struct list_head list, list2; - struct rtw_adapter *padapter; - - u8 *pallocated_buf; - u8 *pbuf; - void *priv_data; - - u16 ext_tag; /* 0: Normal xmitbuf, 1: extension xmitbuf. */ - u16 flags; - u32 alloc_sz; - u32 len; - struct submit_ctx *sctx; - u32 ff_hwaddr; - struct urb *pxmit_urb[8]; - u8 bpending[8]; - int last[8]; -#if defined(DBG_XMIT_BUF) || defined(DBG_XMIT_BUF_EXT) - u8 no; -#endif -}; - -struct xmit_frame { - struct list_head list; - struct pkt_attrib attrib; - struct sk_buff *pkt; - int frame_tag; - struct rtw_adapter *padapter; - u8 *buf_addr; - struct xmit_buf *pxmitbuf; - - s8 pkt_offset; - - u8 ack_report; - - u8 ext_tag; /* 0:data, 1:mgmt */ -}; - -struct tx_servq { - struct list_head tx_pending; - struct rtw_queue sta_pending; - int qcnt; -}; - -struct sta_xmit_priv { - spinlock_t lock; - int option; - int apsd_setting; /* When bit mask is on, the associated edca - * queue supports APSD. - */ - struct tx_servq be_q; /* priority == 0,3 */ - struct tx_servq bk_q; /* priority == 1,2 */ - struct tx_servq vi_q; /* priority == 4,5 */ - struct tx_servq vo_q; /* priority == 6,7 */ - struct list_head legacy_dz; - struct list_head apsd; - u16 txseq_tid[16]; -}; - -struct hw_txqueue { - volatile int head; - volatile int tail; - volatile int free_sz; /* in units of 64 bytes */ - volatile int free_cmdsz; - volatile int txsz[8]; - uint ff_hwaddr; - uint cmd_hwaddr; - int ac_tag; -}; - -struct agg_pkt_info { - u16 offset; - u16 pkt_len; -}; - -struct xmit_priv { - spinlock_t lock; - - struct rtw_queue be_pending; - struct rtw_queue bk_pending; - struct rtw_queue vi_pending; - struct rtw_queue vo_pending; - struct rtw_queue bm_pending; - - int free_xmitframe_cnt; - struct rtw_queue free_xmit_queue; - - int free_xframe_ext_cnt; - struct rtw_queue free_xframe_ext_queue; - - uint frag_len; - - struct rtw_adapter *adapter; - - u64 tx_bytes; - u64 tx_pkts; - u64 tx_drop; - u64 last_tx_bytes; - u64 last_tx_pkts; - - struct hw_xmit *hwxmits; - u8 hwxmit_entry; - u8 vcs; - u8 nqos_ssn; - - u8 wmm_para_seq[4];/* sequence for wmm ac parameter strength from - * large to small. it's value is 0->vo, 1->vi, - * 2->be, 3->bk. - */ - - struct tasklet_struct xmit_tasklet; - - struct rtw_queue free_xmitbuf_queue; - struct list_head xmitbuf_list; /* track buffers for cleanup */ - struct rtw_queue pending_xmitbuf_queue; - uint free_xmitbuf_cnt; - - struct rtw_queue free_xmit_extbuf_queue; - struct list_head xmitextbuf_list; /* track buffers for cleanup */ - uint free_xmit_extbuf_cnt; - - int ack_tx; - struct mutex ack_tx_mutex; - struct submit_ctx ack_tx_ops; - spinlock_t lock_sctx; -}; - -struct xmit_buf *rtw_alloc_xmitbuf23a_ext(struct xmit_priv *pxmitpriv); -s32 rtw_free_xmitbuf_ext23a(struct xmit_priv *pxmitpriv, - struct xmit_buf *pxmitbuf); - -struct xmit_buf *rtw_alloc_xmitbuf23a(struct xmit_priv *pxmitpriv); -s32 rtw_free_xmitbuf23a(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf); - -void rtw_count_tx_stats23a(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe, int sz); -void rtw_update_protection23a(struct rtw_adapter *padapter, u8 *ie, uint ie_len); -struct xmit_frame *rtw_alloc_xmitframe23a_ext(struct xmit_priv *pxmitpriv); -struct xmit_frame *rtw_alloc_xmitframe23a_once(struct xmit_priv *pxmitpriv); -s32 rtw_free_xmitframe23a(struct xmit_priv *pxmitpriv, - struct xmit_frame *pxmitframe); -void rtw_free_xmitframe_queue23a(struct xmit_priv *pxmitpriv, struct rtw_queue *pframequeue); -struct tx_servq *rtw_get_sta_pending23a(struct rtw_adapter *padapter, - struct sta_info *psta, int up, u8 *ac); -s32 rtw_xmitframe_enqueue23a(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe); -struct xmit_frame *rtw_dequeue_xframe23a(struct xmit_priv *pxmitpriv, - struct hw_xmit *phwxmit_i, int entry); -s32 rtw_xmit23a_classifier(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe); -s32 rtw_xmitframe_coalesce23a(struct rtw_adapter *padapter, struct sk_buff *pkt, - struct xmit_frame *pxmitframe); -s32 _rtw_init_hw_txqueue(struct hw_txqueue *phw_txqueue, u8 ac_tag); -void _rtw_init_sta_xmit_priv23a(struct sta_xmit_priv *psta_xmitpriv); - -s32 rtw_txframes_pending23a(struct rtw_adapter *padapter); -s32 rtw_txframes_sta_ac_pending23a(struct rtw_adapter *padapter, - struct pkt_attrib *pattrib); -void rtw_init_hwxmits23a(struct hw_xmit *phwxmit, int entry); -int _rtw_init_xmit_priv23a(struct xmit_priv *pxmitpriv, - struct rtw_adapter *padapter); -void _rtw_free_xmit_priv23a(struct xmit_priv *pxmitpriv); -void rtw_alloc_hwxmits23a(struct rtw_adapter *padapter); -void rtw_free_hwxmits23a(struct rtw_adapter *padapter); -int rtw_xmit23a(struct rtw_adapter *padapter, struct sk_buff *pkt); -#if defined(CONFIG_8723AU_AP_MODE) -int xmitframe_enqueue_for_sleeping_sta23a(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe); -void stop_sta_xmit23a(struct rtw_adapter *padapter, struct sta_info *psta); -void wakeup_sta_to_xmit23a(struct rtw_adapter *padapter, struct sta_info *psta); -void xmit_delivery_enabled_frames23a(struct rtw_adapter *padapter, - struct sta_info *psta); -#endif -u8 qos_acm23a(u8 acm_mask, u8 priority); -u32 rtw_get_ff_hwaddr23a(struct xmit_frame *pxmitframe); -int rtw_ack_tx_wait23a(struct xmit_priv *pxmitpriv, u32 timeout_ms); - -/* include after declaring struct xmit_buf, in order to avoid warning */ -#include <xmit_osdep.h> - -#endif /* _RTL871X_XMIT_H_ */ diff --git a/drivers/staging/rtl8723au/include/sta_info.h b/drivers/staging/rtl8723au/include/sta_info.h deleted file mode 100644 index e726005..0000000 --- a/drivers/staging/rtl8723au/include/sta_info.h +++ /dev/null @@ -1,373 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __STA_INFO_H_ -#define __STA_INFO_H_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <wifi.h> - -#define IBSS_START_MAC_ID 2 -#define NUM_STA 32 -#define NUM_ACL 16 - - -/* if mode ==0, then the sta is allowed once the addr is hit. */ -/* if mode ==1, then the sta is rejected once the addr is non-hit. */ -struct rtw_wlan_acl_node { - struct list_head list; - u8 addr[ETH_ALEN]; - u8 valid; -}; - -/* mode=0, disable */ -/* mode=1, accept unless in deny list */ -/* mode=2, deny unless in accept list */ -struct wlan_acl_pool { - int mode; - int num; - struct rtw_wlan_acl_node aclnode[NUM_ACL]; - struct rtw_queue acl_node_q; -}; - -struct rssi_sta { - s32 UndecoratedSmoothedPWDB; - s32 UndecoratedSmoothedCCK; - s32 UndecoratedSmoothedOFDM; - u64 PacketMap; - u8 ValidBit; -}; - -struct stainfo_stats { - u64 rx_mgnt_pkts; - u64 rx_beacon_pkts; - u64 rx_probereq_pkts; - u64 rx_probersp_pkts; - u64 rx_probersp_bm_pkts; - u64 rx_probersp_uo_pkts; - u64 rx_ctrl_pkts; - u64 rx_data_pkts; - - u64 last_rx_mgnt_pkts; - u64 last_rx_beacon_pkts; - u64 last_rx_probereq_pkts; - u64 last_rx_probersp_pkts; - u64 last_rx_probersp_bm_pkts; - u64 last_rx_probersp_uo_pkts; - u64 last_rx_ctrl_pkts; - u64 last_rx_data_pkts; - - u64 rx_bytes; - u64 rx_drops; - - u64 tx_pkts; - u64 tx_bytes; - u64 tx_drops; - -}; - -struct sta_info { - spinlock_t lock; - struct list_head list; /* free_sta_queue */ - struct list_head hash_list; /* sta_hash */ - struct rtw_adapter *padapter; - - struct sta_xmit_priv sta_xmitpriv; - struct sta_recv_priv sta_recvpriv; - - struct rtw_queue sleep_q; - unsigned int sleepq_len; - - uint state; - uint aid; - uint mac_id; - uint qos_option; - u8 hwaddr[ETH_ALEN]; - - uint ieee8021x_blocked; /* 0: allowed, 1:blocked */ - u32 dot118021XPrivacy; /* aes, tkip... */ - union Keytype dot11tkiptxmickey; - union Keytype dot11tkiprxmickey; - union Keytype dot118021x_UncstKey; - union pn48 dot11txpn; /* PN48 used for Unicast xmit. */ - union pn48 dot11rxpn; /* PN48 used for Unicast recv. */ - - - u8 bssrateset[16]; - u32 bssratelen; - s32 rssi; - s32 signal_quality; - - u8 cts2self; - u8 rtsen; - - u8 raid; - u8 init_rate; - u32 ra_mask; - u8 wireless_mode; /* NETWORK_TYPE */ - struct stainfo_stats sta_stats; - - /* for A-MPDU TX, ADDBA timeout check */ - struct timer_list addba_retry_timer; - - /* for A-MPDU Rx reordering buffer control */ - struct recv_reorder_ctrl recvreorder_ctrl[16]; - - /* for A-MPDU Tx */ - /* unsigned char ampdu_txen_bitmap; */ - u16 BA_starting_seqctrl[16]; - - struct ht_priv htpriv; - - /* Notes: */ - /* STA_Mode: */ - /* curr_network(mlme_priv/security_priv/qos/ht) + sta_info: (STA & AP) CAP/INFO */ - /* scan_q: AP CAP/INFO */ - - /* AP_Mode: */ - /* curr_network(mlme_priv/security_priv/qos/ht) : AP CAP/INFO */ - /* sta_info: (AP & STA) CAP/INFO */ - - struct list_head asoc_list; - struct list_head auth_list; - - unsigned int expire_to; - unsigned int auth_seq; - unsigned int authalg; - unsigned char chg_txt[128]; - - u16 capability; - int flags; - - int dot8021xalg;/* 0:disable, 1:psk, 2:802.1x */ - int wpa_psk;/* 0:disable, bit(0): WPA, bit(1):WPA2 */ - int wpa_group_cipher; - int wpa2_group_cipher; - int wpa_pairwise_cipher; - int wpa2_pairwise_cipher; - - u8 bpairwise_key_installed; - - u8 wpa_ie[32]; - - u8 nonerp_set; - u8 no_short_slot_time_set; - u8 no_short_preamble_set; - u8 no_ht_gf_set; - u8 no_ht_set; - u8 ht_20mhz_set; - - unsigned int tx_ra_bitmap; - u8 qos_info; - - u8 max_sp_len; - u8 uapsd_bk;/* BIT(0): Delivery enabled, BIT(1): Trigger enabled */ - u8 uapsd_be; - u8 uapsd_vi; - u8 uapsd_vo; - - u8 has_legacy_ac; - unsigned int sleepq_ac_len; - - /* p2p priv data */ - u8 is_p2p_device; - u8 p2p_status_code; - - u8 keep_alive_trycnt; - - /* p2p client info */ - u8 dev_addr[ETH_ALEN]; - u8 dev_cap; - u16 config_methods; - u8 primary_dev_type[8]; - u8 num_of_secdev_type; - u8 secdev_types_list[32];/* 32/8 == 4; */ - u16 dev_name_len; - u8 dev_name[32]; - u8 *passoc_req; - u32 assoc_req_len; - - /* for DM */ - struct rssi_sta rssi_stat; - - /* */ - /* ================ODM Relative Info======================= */ - /* Please be care, dont declare too much structure here. It will cost memory * STA support num. */ - /* */ - /* */ - /* 2011/10/20 MH Add for ODM STA info. */ - /* */ - /* Driver Write */ - u8 bValid; /* record the sta status link or not? */ - u8 rssi_level; /* for Refresh RA mask */ - /* ODM Write */ - /* 1 PHY_STATUS_INFO */ - u8 RSSI_Path[4]; /* */ - u8 RSSI_Ave; - u8 RXEVM[4]; - u8 RXSNR[4]; - - /* ODM Write */ - /* 1 TX_INFO (may changed by IC) */ - /* ================ODM Relative Info======================= */ - /* */ - - /* To store the sequence number of received management frame */ - u16 RxMgmtFrameSeqNum; -}; - -#define sta_rx_pkts(sta) \ - (sta->sta_stats.rx_mgnt_pkts \ - + sta->sta_stats.rx_ctrl_pkts \ - + sta->sta_stats.rx_data_pkts) - -#define sta_last_rx_pkts(sta) \ - (sta->sta_stats.last_rx_mgnt_pkts \ - + sta->sta_stats.last_rx_ctrl_pkts \ - + sta->sta_stats.last_rx_data_pkts) - -#define sta_rx_data_pkts(sta) \ - (sta->sta_stats.rx_data_pkts) - -#define sta_last_rx_data_pkts(sta) \ - (sta->sta_stats.last_rx_data_pkts) - -#define sta_rx_mgnt_pkts(sta) \ - (sta->sta_stats.rx_mgnt_pkts) - -#define sta_last_rx_mgnt_pkts(sta) \ - (sta->sta_stats.last_rx_mgnt_pkts) - -#define sta_rx_beacon_pkts(sta) \ - (sta->sta_stats.rx_beacon_pkts) - -#define sta_last_rx_beacon_pkts(sta) \ - (sta->sta_stats.last_rx_beacon_pkts) - -#define sta_rx_probereq_pkts(sta) \ - (sta->sta_stats.rx_probereq_pkts) - -#define sta_last_rx_probereq_pkts(sta) \ - (sta->sta_stats.last_rx_probereq_pkts) - -#define sta_rx_probersp_pkts(sta) \ - (sta->sta_stats.rx_probersp_pkts) - -#define sta_last_rx_probersp_pkts(sta) \ - (sta->sta_stats.last_rx_probersp_pkts) - -#define sta_rx_probersp_bm_pkts(sta) \ - (sta->sta_stats.rx_probersp_bm_pkts) - -#define sta_last_rx_probersp_bm_pkts(sta) \ - (sta->sta_stats.last_rx_probersp_bm_pkts) - -#define sta_rx_probersp_uo_pkts(sta) \ - (sta->sta_stats.rx_probersp_uo_pkts) - -#define sta_last_rx_probersp_uo_pkts(sta) \ - (sta->sta_stats.last_rx_probersp_uo_pkts) - -#define sta_update_last_rx_pkts(sta) \ - do { \ - sta->sta_stats.last_rx_mgnt_pkts = sta->sta_stats.rx_mgnt_pkts; \ - sta->sta_stats.last_rx_beacon_pkts = sta->sta_stats.rx_beacon_pkts; \ - sta->sta_stats.last_rx_probereq_pkts = sta->sta_stats.rx_probereq_pkts; \ - sta->sta_stats.last_rx_probersp_pkts = sta->sta_stats.rx_probersp_pkts; \ - sta->sta_stats.last_rx_probersp_bm_pkts = sta->sta_stats.rx_probersp_bm_pkts; \ - sta->sta_stats.last_rx_probersp_uo_pkts = sta->sta_stats.rx_probersp_uo_pkts; \ - sta->sta_stats.last_rx_ctrl_pkts = sta->sta_stats.rx_ctrl_pkts; \ - sta->sta_stats.last_rx_data_pkts = sta->sta_stats.rx_data_pkts; \ - } while (0) - -#define STA_RX_PKTS_ARG(sta) \ - sta->sta_stats.rx_mgnt_pkts \ - , sta->sta_stats.rx_ctrl_pkts \ - , sta->sta_stats.rx_data_pkts - -#define STA_LAST_RX_PKTS_ARG(sta) \ - sta->sta_stats.last_rx_mgnt_pkts, \ - sta->sta_stats.last_rx_ctrl_pkts, \ - sta->sta_stats.last_rx_data_pkts - -#define STA_RX_PKTS_DIFF_ARG(sta) \ - sta->sta_stats.rx_mgnt_pkts - sta->sta_stats.last_rx_mgnt_pkts, \ - sta->sta_stats.rx_ctrl_pkts - sta->sta_stats.last_rx_ctrl_pkts, \ - sta->sta_stats.rx_data_pkts - sta->sta_stats.last_rx_data_pkts - -#define STA_PKTS_FMT "(m:%llu, c:%llu, d:%llu)" - -struct sta_priv { - spinlock_t sta_hash_lock; - struct list_head sta_hash[NUM_STA]; - int asoc_sta_count; - - struct rtw_adapter *padapter; - struct list_head asoc_list; - struct list_head auth_list; - spinlock_t asoc_list_lock; - spinlock_t auth_list_lock; - u8 asoc_list_cnt; - u8 auth_list_cnt; - - unsigned int auth_to; /* sec, time to expire in authenticating. */ - unsigned int assoc_to; /* sec, time to expire before associating. */ - unsigned int expire_to; /* sec , time to expire after associated. */ - - /* pointers to STA info; based on allocated AID or NULL if AID free - * AID is in the range 1-2007, so sta_aid[0] corresponders to AID 1 - * and so on - */ - struct sta_info *sta_aid[NUM_STA]; - - u16 sta_dz_bitmap;/* only support 15 stations, station aid bitmap - * for sleeping sta. */ - u16 tim_bitmap;/* only support 15 stations, - * aid=0~15 mapping bit0~bit15 */ - - u16 max_num_sta; - - struct wlan_acl_pool acl_list; -}; - -static inline u32 wifi_mac_hash(const u8 *mac) -{ - u32 x; - - x = mac[0]; - x = (x << 2) ^ mac[1]; - x = (x << 2) ^ mac[2]; - x = (x << 2) ^ mac[3]; - x = (x << 2) ^ mac[4]; - x = (x << 2) ^ mac[5]; - - x ^= x >> 8; - x = x & (NUM_STA - 1); - - return x; -} - -int _rtw_init_sta_priv23a(struct sta_priv *pstapriv); -int _rtw_free_sta_priv23a(struct sta_priv *pstapriv); - -struct sta_info *rtw_alloc_stainfo23a(struct sta_priv *pstapriv, const u8 *hwaddr, gfp_t gfp); -int rtw_free_stainfo23a(struct rtw_adapter *padapter, struct sta_info *psta); -void rtw_free_all_stainfo23a(struct rtw_adapter *padapter); -struct sta_info *rtw_get_stainfo23a(struct sta_priv *pstapriv, const u8 *hwaddr); -int rtw_init_bcmc_stainfo23a(struct rtw_adapter *padapter); -struct sta_info *rtw_get_bcmc_stainfo23a(struct rtw_adapter *padapter); -bool rtw_access_ctrl23a(struct rtw_adapter *padapter, u8 *mac_addr); - -#endif /* _STA_INFO_H_ */ diff --git a/drivers/staging/rtl8723au/include/usb_ops.h b/drivers/staging/rtl8723au/include/usb_ops.h deleted file mode 100644 index ff11e13..0000000 --- a/drivers/staging/rtl8723au/include/usb_ops.h +++ /dev/null @@ -1,68 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __USB_OPS_H_ -#define __USB_OPS_H_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <osdep_intf.h> -#include <usb_ops_linux.h> - -#define REALTEK_USB_VENQT_READ 0xC0 -#define REALTEK_USB_VENQT_WRITE 0x40 -#define REALTEK_USB_VENQT_CMD_REQ 0x05 -#define REALTEK_USB_VENQT_CMD_IDX 0x00 - -enum { - VENDOR_WRITE = 0x00, - VENDOR_READ = 0x01, -}; - -#define ALIGNMENT_UNIT 16 -#define MAX_VENDOR_REQ_CMD_SIZE 254 /* 8188cu SIE Support */ -#define MAX_USB_IO_CTL_SIZE (MAX_VENDOR_REQ_CMD_SIZE +ALIGNMENT_UNIT) - -void rtl8723au_set_hw_type(struct rtw_adapter *padapter); - -void rtl8723au_recv_tasklet(void *priv); - -void rtl8723au_xmit_tasklet(void *priv); - -/* Increase and check if the continual_urb_error of this @param dvobjprive is - * larger than MAX_CONTINUAL_URB_ERR. Return result - */ -static inline int rtw_inc_and_chk_continual_urb_error(struct dvobj_priv *dvobj) -{ - int ret = false; - int value; - - value = atomic_inc_return(&dvobj->continual_urb_error); - if (value > MAX_CONTINUAL_URB_ERR) { - DBG_8723A("[dvobj:%p][ERROR] continual_urb_error:%d > %d\n", - dvobj, value, MAX_CONTINUAL_URB_ERR); - ret = true; - } - return ret; -} - -/* Set the continual_urb_error of this @param dvobjprive to 0 */ -static inline void rtw_reset_continual_urb_error(struct dvobj_priv *dvobj) -{ - atomic_set(&dvobj->continual_urb_error, 0); -} - -bool rtl8723au_chip_configure(struct rtw_adapter *padapter); - -#endif /* __USB_OPS_H_ */ diff --git a/drivers/staging/rtl8723au/include/usb_ops_linux.h b/drivers/staging/rtl8723au/include/usb_ops_linux.h deleted file mode 100644 index af2f14b..0000000 --- a/drivers/staging/rtl8723au/include/usb_ops_linux.h +++ /dev/null @@ -1,41 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __USB_OPS_LINUX_H__ -#define __USB_OPS_LINUX_H__ - -#define VENDOR_CMD_MAX_DATA_LEN 254 - -#define RTW_USB_CONTROL_MSG_TIMEOUT 500/* ms */ - -#define MAX_USBCTRL_VENDORREQ_TIMES 10 - -int rtl8723au_read_port(struct rtw_adapter *adapter, u32 cnt, - struct recv_buf *precvbuf); -void rtl8723au_read_port_cancel(struct rtw_adapter *padapter); -int rtl8723au_write_port(struct rtw_adapter *padapter, u32 addr, u32 cnt, - struct xmit_buf *pxmitbuf); -void rtl8723au_write_port_cancel(struct rtw_adapter *padapter); -int rtl8723au_read_interrupt(struct rtw_adapter *adapter); - -u8 rtl8723au_read8(struct rtw_adapter *padapter, u16 addr); -u16 rtl8723au_read16(struct rtw_adapter *padapter, u16 addr); -u32 rtl8723au_read32(struct rtw_adapter *padapter, u16 addr); -int rtl8723au_write8(struct rtw_adapter *padapter, u16 addr, u8 val); -int rtl8723au_write16(struct rtw_adapter *padapter, u16 addr, u16 val); -int rtl8723au_write32(struct rtw_adapter *padapter, u16 addr, u32 val); -int rtl8723au_writeN(struct rtw_adapter *padapter, - u16 addr, u16 length, u8 *pdata); - -#endif diff --git a/drivers/staging/rtl8723au/include/wifi.h b/drivers/staging/rtl8723au/include/wifi.h deleted file mode 100644 index 25d573c..0000000 --- a/drivers/staging/rtl8723au/include/wifi.h +++ /dev/null @@ -1,84 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef _WIFI_H_ -#define _WIFI_H_ - -/* This value is tested by WiFi 11n Test Plan 5.2.3. - * This test verifies the WLAN NIC can update the NAV through sending - * the CTS with large duration. - */ -#define WiFiNavUpperUs 30000 /* 30 ms */ - -/*----------------------------------------------------------------------------- - Below is the definition for 802.11n -------------------------------------------------------------------------------*/ - -struct AC_param { - u8 ACI_AIFSN; - u8 CW; - __le16 TXOP_limit; -} __packed; - -struct WMM_para_element { - unsigned char QoS_info; - unsigned char reserved; - struct AC_param ac_param[4]; -} __packed; - -struct ADDBA_request { - u8 dialog_token; - __le16 BA_para_set; - __le16 BA_timeout_value; - __le16 BA_starting_seqctrl; -} __packed; - - -/* ===============WPS Section=============== */ -/* WPS attribute ID */ -#define WPS_ATTR_VER1 0x104A -#define WPS_ATTR_SIMPLE_CONF_STATE 0x1044 -#define WPS_ATTR_RESP_TYPE 0x103B -#define WPS_ATTR_UUID_E 0x1047 -#define WPS_ATTR_MANUFACTURER 0x1021 -#define WPS_ATTR_MODEL_NAME 0x1023 -#define WPS_ATTR_MODEL_NUMBER 0x1024 -#define WPS_ATTR_SERIAL_NUMBER 0x1042 -#define WPS_ATTR_PRIMARY_DEV_TYPE 0x1054 -#define WPS_ATTR_SEC_DEV_TYPE_LIST 0x1055 -#define WPS_ATTR_DEVICE_NAME 0x1011 -#define WPS_ATTR_CONF_METHOD 0x1008 -#define WPS_ATTR_RF_BANDS 0x103C -#define WPS_ATTR_DEVICE_PWID 0x1012 -#define WPS_ATTR_REQUEST_TYPE 0x103A -#define WPS_ATTR_ASSOCIATION_STATE 0x1002 -#define WPS_ATTR_CONFIG_ERROR 0x1009 -#define WPS_ATTR_VENDOR_EXT 0x1049 -#define WPS_ATTR_SELECTED_REGISTRAR 0x1041 - -/* WPS Configuration Method */ -#define WPS_CM_NONE 0x0000 -#define WPS_CM_LABEL 0x0004 -#define WPS_CM_DISPLYA 0x0008 -#define WPS_CM_EXTERNAL_NFC_TOKEN 0x0010 -#define WPS_CM_INTEGRATED_NFC_TOKEN 0x0020 -#define WPS_CM_NFC_INTERFACE 0x0040 -#define WPS_CM_PUSH_BUTTON 0x0080 -#define WPS_CM_KEYPAD 0x0100 -#define WPS_CM_SW_PUHS_BUTTON 0x0280 -#define WPS_CM_HW_PUHS_BUTTON 0x0480 -#define WPS_CM_SW_DISPLAY_PIN 0x2008 -#define WPS_CM_LCD_DISPLAY_PIN 0x4008 - -#endif /* _WIFI_H_ */ diff --git a/drivers/staging/rtl8723au/include/wlan_bssdef.h b/drivers/staging/rtl8723au/include/wlan_bssdef.h deleted file mode 100644 index 95b32e1..0000000 --- a/drivers/staging/rtl8723au/include/wlan_bssdef.h +++ /dev/null @@ -1,123 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __WLAN_BSSDEF_H__ -#define __WLAN_BSSDEF_H__ - - -#define MAX_IE_SZ 768 - - -#define NDIS_802_11_LENGTH_RATES 8 -#define NDIS_802_11_LENGTH_RATES_EX 16 - -/* Length is the 4 bytes multiples of the sum of - * sizeof(6 * sizeof(unsigned char)) + 2 + sizeof(struct ndis_802_11_ssid) + - * sizeof(u32) + sizeof(long) + sizeof(enum ndis_802_11_net_type) + - * sizeof(struct ndis_802_11_config) + sizeof(sizeof(unsigned char) * - * NDIS_802_11_LENGTH_RATES_EX) + IELength - * - * Except the IELength, all other fields are fixed length. Therefore, - * we can define a macro to present the partial sum. - */ - -enum ndis_802_11_auth_mode { - Ndis802_11AuthModeOpen, - Ndis802_11AuthModeShared, - Ndis802_11AuthModeAutoSwitch, - Ndis802_11AuthModeWPA, - Ndis802_11AuthModeWPAPSK, - Ndis802_11AuthModeWPANone, - dis802_11AuthModeMax /* upper bound */ -}; - -enum { - Ndis802_11WEPEnabled, - Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled, - Ndis802_11WEPDisabled, - Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled, - Ndis802_11WEPKeyAbsent, - Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent, - Ndis802_11WEPNotSupported, - Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported, - Ndis802_11Encryption2Enabled, - Ndis802_11Encryption2KeyAbsent, - Ndis802_11Encryption3Enabled, - Ndis802_11Encryption3KeyAbsent, -}; - -struct wlan_bcn_info { - /* these infor get from rtw_get_encrypt_info when - * * translate scan to UI */ - u8 encryp_protocol;/* ENCRYP_PROTOCOL_E: OPEN/WEP/WPA/WPA2 */ - int group_cipher; /* WPA/WPA2 group cipher */ - int pairwise_cipher;/* WPA/WPA2/WEP pairwise cipher */ - int is_8021x; - - /* bwmode 20/40 and ch_offset UP/LOW */ -}; - -struct wlan_bssid_ex { - u32 Length; - u8 MacAddress[ETH_ALEN]; - u16 reserved; - struct cfg80211_ssid Ssid; - u32 Privacy; - long Rssi;/* in dBM, raw data , get from PHY) */ - u16 beacon_interval; - u16 capability; - u64 tsf; - u32 ATIMWindow; /* units are Kusec */ - u32 DSConfig; /* Frequency, units are kHz */ - enum nl80211_iftype ifmode; - unsigned char SupportedRates[NDIS_802_11_LENGTH_RATES_EX]; - u8 SignalStrength;/* in percentage */ - u8 SignalQuality;/* in percentage */ - u32 IELength; - u8 IEs[MAX_IE_SZ]; /* timestamp, beacon interval, and capability info*/ -} __packed; - -static inline uint get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss) -{ - return sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + bss->IELength; -} - -struct wlan_network { - struct list_head list; - int network_type; /* refer to ieee80211.h for 11A/B/G */ - /* set to fixed when not to be removed as site-surveying */ - int fixed; - unsigned long last_scanned; /* timestamp for the network */ - int join_res; - struct wlan_bssid_ex network; /* must be the last item */ - struct wlan_bcn_info BcnInfo; -}; - -enum VRTL_CARRIER_SENSE { - DISABLE_VCS, - ENABLE_VCS, - AUTO_VCS -}; - -enum VCS_TYPE { - NONE_VCS, - RTS_CTS, - CTS_TO_SELF -}; - -/* john */ -#define NUM_PRE_AUTH_KEY 16 -#define NUM_PMKID_CACHE NUM_PRE_AUTH_KEY - -#endif /* ifndef WLAN_BSSDEF_H_ */ diff --git a/drivers/staging/rtl8723au/include/xmit_osdep.h b/drivers/staging/rtl8723au/include/xmit_osdep.h deleted file mode 100644 index 2be04c48..0000000 --- a/drivers/staging/rtl8723au/include/xmit_osdep.h +++ /dev/null @@ -1,38 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __XMIT_OSDEP_H_ -#define __XMIT_OSDEP_H_ - -#include <osdep_service.h> -#include <drv_types.h> - - -#define NR_XMITFRAME 256 - -int rtw_xmit23a_entry23a(struct sk_buff *pkt, struct net_device *pnetdev); - -void rtw_os_xmit_schedule23a(struct rtw_adapter *padapter); - -int rtw_os_xmit_resource_alloc23a(struct rtw_adapter *padapter, - struct xmit_buf *pxmitbuf, u32 alloc_sz); -void rtw_os_xmit_resource_free23a(struct rtw_adapter *padapter, - struct xmit_buf *pxmitbuf); - -void rtw_os_pkt_complete23a(struct rtw_adapter *padapter, struct sk_buff *pkt); -void rtw_os_xmit_complete23a(struct rtw_adapter *padapter, - struct xmit_frame *pxframe); -int netdev_open23a(struct net_device *pnetdev); - -#endif /* __XMIT_OSDEP_H_ */ diff --git a/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c deleted file mode 100644 index d0ba377..0000000 --- a/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c +++ /dev/null @@ -1,3348 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _IOCTL_CFG80211_C_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <xmit_osdep.h> - -#include "ioctl_cfg80211.h" - -#define RTW_MAX_MGMT_TX_CNT 8 - -#define RTW_MAX_REMAIN_ON_CHANNEL_DURATION 65535 /* ms */ -#define RTW_MAX_NUM_PMKIDS 4 - -static const u32 rtw_cipher_suites[] = { - WLAN_CIPHER_SUITE_WEP40, - WLAN_CIPHER_SUITE_WEP104, - WLAN_CIPHER_SUITE_TKIP, - WLAN_CIPHER_SUITE_CCMP, -}; - -#define RATETAB_ENT(_rate, _rateid, _flags) { \ - .bitrate = (_rate), \ - .hw_value = (_rateid), \ - .flags = (_flags), \ -} - -#define CHAN2G(_channel, _freq, _flags) { \ - .band = NL80211_BAND_2GHZ, \ - .center_freq = (_freq), \ - .hw_value = (_channel), \ - .flags = (_flags), \ - .max_antenna_gain = 0, \ - .max_power = 30, \ -} - -#define CHAN5G(_channel, _flags) { \ - .band = NL80211_BAND_5GHZ, \ - .center_freq = 5000 + (5 * (_channel)), \ - .hw_value = (_channel), \ - .flags = (_flags), \ - .max_antenna_gain = 0, \ - .max_power = 30, \ -} - -static struct ieee80211_rate rtw_rates[] = { - RATETAB_ENT(10, 0x1, 0), - RATETAB_ENT(20, 0x2, 0), - RATETAB_ENT(55, 0x4, 0), - RATETAB_ENT(110, 0x8, 0), - RATETAB_ENT(60, 0x10, 0), - RATETAB_ENT(90, 0x20, 0), - RATETAB_ENT(120, 0x40, 0), - RATETAB_ENT(180, 0x80, 0), - RATETAB_ENT(240, 0x100, 0), - RATETAB_ENT(360, 0x200, 0), - RATETAB_ENT(480, 0x400, 0), - RATETAB_ENT(540, 0x800, 0), -}; - -#define rtw_a_rates (rtw_rates + 4) -#define RTW_A_RATES_NUM 8 -#define rtw_g_rates (rtw_rates + 0) -#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), - CHAN2G(2, 2417, 0), - CHAN2G(3, 2422, 0), - CHAN2G(4, 2427, 0), - CHAN2G(5, 2432, 0), - CHAN2G(6, 2437, 0), - CHAN2G(7, 2442, 0), - CHAN2G(8, 2447, 0), - CHAN2G(9, 2452, 0), - CHAN2G(10, 2457, 0), - CHAN2G(11, 2462, 0), - CHAN2G(12, 2467, 0), - CHAN2G(13, 2472, 0), - CHAN2G(14, 2484, 0), -}; - -static struct ieee80211_channel rtw_5ghz_a_channels[] = { - CHAN5G(34, 0), CHAN5G(36, 0), - CHAN5G(38, 0), CHAN5G(40, 0), - CHAN5G(42, 0), CHAN5G(44, 0), - CHAN5G(46, 0), CHAN5G(48, 0), - CHAN5G(52, 0), CHAN5G(56, 0), - CHAN5G(60, 0), CHAN5G(64, 0), - CHAN5G(100, 0), CHAN5G(104, 0), - CHAN5G(108, 0), CHAN5G(112, 0), - CHAN5G(116, 0), CHAN5G(120, 0), - CHAN5G(124, 0), CHAN5G(128, 0), - CHAN5G(132, 0), CHAN5G(136, 0), - CHAN5G(140, 0), CHAN5G(149, 0), - CHAN5G(153, 0), CHAN5G(157, 0), - CHAN5G(161, 0), CHAN5G(165, 0), - CHAN5G(184, 0), CHAN5G(188, 0), - CHAN5G(192, 0), CHAN5G(196, 0), - CHAN5G(200, 0), CHAN5G(204, 0), - CHAN5G(208, 0), CHAN5G(212, 0), - CHAN5G(216, 0), -}; - -static void rtw_2g_channels_init(struct ieee80211_channel *channels) -{ - memcpy((void *)channels, (void *)rtw_2ghz_channels, - sizeof(struct ieee80211_channel) * RTW_2G_CHANNELS_NUM); -} - -static void rtw_5g_channels_init(struct ieee80211_channel *channels) -{ - memcpy((void *)channels, (void *)rtw_5ghz_a_channels, - sizeof(struct ieee80211_channel) * RTW_5G_CHANNELS_NUM); -} - -static void rtw_2g_rates_init(struct ieee80211_rate *rates) -{ - memcpy(rates, rtw_g_rates, - sizeof(struct ieee80211_rate) * RTW_G_RATES_NUM); -} - -static void rtw_5g_rates_init(struct ieee80211_rate *rates) -{ - memcpy(rates, rtw_a_rates, - sizeof(struct ieee80211_rate) * RTW_A_RATES_NUM); -} - -static struct ieee80211_supported_band * -rtw_spt_band_alloc(enum nl80211_band band) -{ - struct ieee80211_supported_band *spt_band = NULL; - int n_channels, n_bitrates; - - if (band == NL80211_BAND_2GHZ) { - n_channels = RTW_2G_CHANNELS_NUM; - n_bitrates = RTW_G_RATES_NUM; - } else if (band == NL80211_BAND_5GHZ) { - n_channels = RTW_5G_CHANNELS_NUM; - n_bitrates = RTW_A_RATES_NUM; - } else { - goto exit; - } - spt_band = kzalloc(sizeof(struct ieee80211_supported_band) + - sizeof(struct ieee80211_channel) * n_channels + - sizeof(struct ieee80211_rate) * n_bitrates, - GFP_KERNEL); - if (!spt_band) - goto exit; - - spt_band->channels = - (struct ieee80211_channel *)(((u8 *) spt_band) + - sizeof(struct - ieee80211_supported_band)); - spt_band->bitrates = - (struct ieee80211_rate *)(((u8 *) spt_band->channels) + - sizeof(struct ieee80211_channel) * - n_channels); - spt_band->band = band; - spt_band->n_channels = n_channels; - spt_band->n_bitrates = n_bitrates; - - if (band == NL80211_BAND_2GHZ) { - rtw_2g_channels_init(spt_band->channels); - rtw_2g_rates_init(spt_band->bitrates); - } else if (band == NL80211_BAND_5GHZ) { - rtw_5g_channels_init(spt_band->channels); - rtw_5g_rates_init(spt_band->bitrates); - } - - /* spt_band.ht_cap */ - -exit: - return spt_band; -} - -static const struct ieee80211_txrx_stypes -rtw_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { - [NL80211_IFTYPE_ADHOC] = { - .tx = 0xffff, - .rx = BIT(IEEE80211_STYPE_ACTION >> 4) - }, - [NL80211_IFTYPE_STATION] = { - .tx = 0xffff, - .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4) - }, - [NL80211_IFTYPE_AP] = { - .tx = 0xffff, - .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | - BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | - BIT(IEEE80211_STYPE_DISASSOC >> 4) | - BIT(IEEE80211_STYPE_AUTH >> 4) | - BIT(IEEE80211_STYPE_DEAUTH >> 4) | - BIT(IEEE80211_STYPE_ACTION >> 4) - }, - [NL80211_IFTYPE_AP_VLAN] = { - /* copy AP */ - .tx = 0xffff, - .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | - BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | - BIT(IEEE80211_STYPE_DISASSOC >> 4) | - BIT(IEEE80211_STYPE_AUTH >> 4) | - BIT(IEEE80211_STYPE_DEAUTH >> 4) | - BIT(IEEE80211_STYPE_ACTION >> 4) - }, - [NL80211_IFTYPE_P2P_CLIENT] = { - .tx = 0xffff, - .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4) - }, - [NL80211_IFTYPE_P2P_GO] = { - .tx = 0xffff, - .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | - BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | - BIT(IEEE80211_STYPE_DISASSOC >> 4) | - BIT(IEEE80211_STYPE_AUTH >> 4) | - BIT(IEEE80211_STYPE_DEAUTH >> 4) | - BIT(IEEE80211_STYPE_ACTION >> 4) - }, -}; - -static int rtw_cfg80211_inform_bss(struct rtw_adapter *padapter, - struct wlan_network *pnetwork) -{ - int ret = 0; - struct ieee80211_channel *notify_channel; - struct cfg80211_bss *bss; - u16 channel; - u32 freq; - u8 *notify_ie; - size_t notify_ielen; - s32 notify_signal; - struct wireless_dev *wdev = padapter->rtw_wdev; - struct wiphy *wiphy = wdev->wiphy; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - channel = pnetwork->network.DSConfig; - if (channel <= RTW_CH_MAX_2G_CHANNEL) - freq = ieee80211_channel_to_frequency(channel, - NL80211_BAND_2GHZ); - else - freq = ieee80211_channel_to_frequency(channel, - NL80211_BAND_5GHZ); - - notify_channel = ieee80211_get_channel(wiphy, freq); - - notify_ie = pnetwork->network.IEs; - notify_ielen = pnetwork->network.IELength; - - /* We've set wiphy's signal_type as CFG80211_SIGNAL_TYPE_MBM: - * signal strength in mBm (100*dBm) - */ - if (check_fwstate(pmlmepriv, _FW_LINKED) && - is_same_network23a(&pmlmepriv->cur_network.network, - &pnetwork->network)) { - notify_signal = 100 * translate_percentage_to_dbm(padapter->recvpriv.signal_strength); /* dbm */ - } else { - notify_signal = 100 * translate_percentage_to_dbm( - pnetwork->network.SignalStrength); /* dbm */ - } - - bss = cfg80211_inform_bss(wiphy, notify_channel, - CFG80211_BSS_FTYPE_UNKNOWN, - pnetwork->network.MacAddress, - pnetwork->network.tsf, - pnetwork->network.capability, - pnetwork->network.beacon_interval, - notify_ie, notify_ielen, - notify_signal, GFP_ATOMIC); - - if (unlikely(!bss)) { - DBG_8723A("rtw_cfg80211_inform_bss error\n"); - return -EINVAL; - } - - cfg80211_put_bss(wiphy, bss); - - return ret; -} - -void rtw_cfg80211_indicate_connect(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_network *cur_network = &pmlmepriv->cur_network; - struct wireless_dev *pwdev = padapter->rtw_wdev; - - DBG_8723A("%s(padapter =%p)\n", __func__, padapter); - - if (pwdev->iftype != NL80211_IFTYPE_STATION && - pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT) - return; - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) - return; - - if (padapter->mlmepriv.to_roaming > 0) { - struct wiphy *wiphy = pwdev->wiphy; - struct ieee80211_channel *notify_channel; - u32 freq; - u16 channel = cur_network->network.DSConfig; - - if (channel <= RTW_CH_MAX_2G_CHANNEL) - freq = - ieee80211_channel_to_frequency(channel, - NL80211_BAND_2GHZ); - else - freq = - ieee80211_channel_to_frequency(channel, - NL80211_BAND_5GHZ); - - notify_channel = ieee80211_get_channel(wiphy, freq); - - DBG_8723A("%s call cfg80211_roamed\n", __func__); - cfg80211_roamed(padapter->pnetdev, notify_channel, - cur_network->network.MacAddress, - pmlmepriv->assoc_req + - sizeof(struct ieee80211_hdr_3addr) + 2, - pmlmepriv->assoc_req_len - - sizeof(struct ieee80211_hdr_3addr) - 2, - pmlmepriv->assoc_rsp + - sizeof(struct ieee80211_hdr_3addr) + 6, - pmlmepriv->assoc_rsp_len - - sizeof(struct ieee80211_hdr_3addr) - 6, - GFP_ATOMIC); - } else { - cfg80211_connect_result(padapter->pnetdev, - cur_network->network.MacAddress, - pmlmepriv->assoc_req + - sizeof(struct ieee80211_hdr_3addr) + 2, - pmlmepriv->assoc_req_len - - sizeof(struct ieee80211_hdr_3addr) - 2, - pmlmepriv->assoc_rsp + - sizeof(struct ieee80211_hdr_3addr) + 6, - pmlmepriv->assoc_rsp_len - - sizeof(struct ieee80211_hdr_3addr) - 6, - WLAN_STATUS_SUCCESS, GFP_ATOMIC); - } -} - -void rtw_cfg80211_indicate_disconnect(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wireless_dev *pwdev = padapter->rtw_wdev; - - DBG_8723A("%s(padapter =%p)\n", __func__, padapter); - - if (pwdev->iftype != NL80211_IFTYPE_STATION && - pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT) - return; - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) - return; - - if (!padapter->mlmepriv.not_indic_disco) { - if (check_fwstate(&padapter->mlmepriv, WIFI_UNDER_LINKING)) { - cfg80211_connect_result(padapter->pnetdev, NULL, NULL, - 0, NULL, 0, - WLAN_STATUS_UNSPECIFIED_FAILURE, - GFP_ATOMIC); - } else { - cfg80211_disconnected(padapter->pnetdev, 0, NULL, - 0, false, GFP_ATOMIC); - } - } -} - -#ifdef CONFIG_8723AU_AP_MODE -static int set_pairwise_key(struct rtw_adapter *padapter, struct sta_info *psta) -{ - struct cmd_obj *ph2c; - struct set_stakey_parm *psetstakey_para; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - int res = _SUCCESS; - - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (ph2c == NULL) { - res = _FAIL; - goto exit; - } - - psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL); - if (psetstakey_para == NULL) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_); - - psetstakey_para->algorithm = psta->dot118021XPrivacy; - - ether_addr_copy(psetstakey_para->addr, psta->hwaddr); - - memcpy(psetstakey_para->key, &psta->dot118021x_UncstKey, 16); - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); - -exit: - return res; -} - -static int set_group_key(struct rtw_adapter *padapter, struct key_params *parms, - u32 alg, u8 keyid) -{ - struct cmd_obj *pcmd; - struct setkey_parm *psetkeyparm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - int res = _SUCCESS; - - DBG_8723A("%s\n", __func__); - - if (keyid >= 4) { - res = _FAIL; - goto exit; - } - - pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (!pcmd) { - res = _FAIL; - goto exit; - } - psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL); - if (!psetkeyparm) { - kfree(pcmd); - res = _FAIL; - goto exit; - } - - psetkeyparm->keyid = keyid; - if (is_wep_enc(alg)) - padapter->mlmepriv.key_mask |= BIT(psetkeyparm->keyid); - - psetkeyparm->algorithm = alg; - - psetkeyparm->set_tx = 1; - - memcpy(&psetkeyparm->key, parms->key, parms->key_len); - - pcmd->cmdcode = _SetKey_CMD_; - pcmd->parmbuf = (u8 *) psetkeyparm; - pcmd->cmdsz = sizeof(struct setkey_parm); - pcmd->rsp = NULL; - pcmd->rspsz = 0; - - res = rtw_enqueue_cmd23a(pcmdpriv, pcmd); - -exit: - return res; -} - -static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, u8 key_index, - int set_tx, const u8 *sta_addr, - struct key_params *keyparms) -{ - int key_len; - struct sta_info *psta = NULL, *pbcmc_sta = NULL; - struct rtw_adapter *padapter = netdev_priv(dev); - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct sta_priv *pstapriv = &padapter->stapriv; - - DBG_8723A("%s\n", __func__); - - if (!is_broadcast_ether_addr(sta_addr)) { - psta = rtw_get_stainfo23a(pstapriv, sta_addr); - if (!psta) { - /* ret = -EINVAL; */ - DBG_8723A("rtw_set_encryption(), sta has already " - "been removed or never been added\n"); - goto exit; - } - } - - key_len = keyparms->key_len; - - if (!psta && (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 || - keyparms->cipher == WLAN_CIPHER_SUITE_WEP104)) { - DBG_8723A("r871x_set_encryption, crypt.alg = WEP\n"); - - DBG_8723A("r871x_set_encryption, wep_key_idx =%d, len =%d\n", - key_index, key_len); - - if (psecuritypriv->bWepDefaultKeyIdxSet == 0) { - /* wep default key has not been set, so use - this key index as default key. */ - - psecuritypriv->ndisencryptstatus = - Ndis802_11Encryption1Enabled; - psecuritypriv->dot11PrivacyAlgrthm = keyparms->cipher; - psecuritypriv->dot118021XGrpPrivacy = keyparms->cipher; - - psecuritypriv->dot11PrivacyKeyIndex = key_index; - } - - memcpy(&psecuritypriv->wep_key[key_index].key, - keyparms->key, key_len); - - psecuritypriv->wep_key[key_index].keylen = key_len; - - set_group_key(padapter, keyparms, keyparms->cipher, key_index); - - goto exit; - } - - if (!psta) { /* group key */ - if (set_tx == 0) { /* group key */ - if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 || - keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) { - DBG_8723A("%s, set group_key, WEP\n", __func__); - - memcpy(psecuritypriv-> - dot118021XGrpKey[key_index].skey, - keyparms->key, key_len); - - psecuritypriv->dot118021XGrpPrivacy = - keyparms->cipher; - } else if (keyparms->cipher == WLAN_CIPHER_SUITE_TKIP) { - DBG_8723A("%s, set group_key, TKIP\n", - __func__); - - psecuritypriv->dot118021XGrpPrivacy = - WLAN_CIPHER_SUITE_TKIP; - - memcpy(psecuritypriv-> - dot118021XGrpKey[key_index].skey, - keyparms->key, - (min(16, key_len))); - - /* set mic key */ - memcpy(psecuritypriv-> - dot118021XGrptxmickey[key_index].skey, - &keyparms->key[16], 8); - memcpy(psecuritypriv-> - dot118021XGrprxmickey[key_index].skey, - &keyparms->key[24], 8); - - psecuritypriv->busetkipkey = 1; - - } else if (keyparms->cipher == WLAN_CIPHER_SUITE_CCMP) { - DBG_8723A("%s, set group_key, CCMP\n", - __func__); - - psecuritypriv->dot118021XGrpPrivacy = - WLAN_CIPHER_SUITE_CCMP; - - memcpy(psecuritypriv-> - dot118021XGrpKey[key_index].skey, - keyparms->key, - (min(16, key_len))); - } else { - DBG_8723A("%s, set group_key, none\n", - __func__); - - psecuritypriv->dot118021XGrpPrivacy = 0; - } - - psecuritypriv->dot118021XGrpKeyid = key_index; - - psecuritypriv->binstallGrpkey = 1; - - psecuritypriv->dot11PrivacyAlgrthm = - psecuritypriv->dot118021XGrpPrivacy; - - set_group_key(padapter, keyparms, - psecuritypriv->dot118021XGrpPrivacy, - key_index); - - pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter); - if (pbcmc_sta) { - pbcmc_sta->ieee8021x_blocked = false; - /* rx will use bmc_sta's dot118021XPrivacy */ - pbcmc_sta->dot118021XPrivacy = - psecuritypriv->dot118021XGrpPrivacy; - - } - - } - - goto exit; - } - - if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { - /* psk/802_1x */ - if (set_tx == 1) { - /* pairwise key */ - memcpy(psta->dot118021x_UncstKey.skey, - keyparms->key, (min(16, key_len))); - - if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 || - keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) { - DBG_8723A("%s, set pairwise key, WEP\n", - __func__); - - psecuritypriv->dot118021XGrpPrivacy = - keyparms->cipher; - } else if (keyparms->cipher == WLAN_CIPHER_SUITE_TKIP) { - DBG_8723A("%s, set pairwise key, TKIP\n", - __func__); - - psta->dot118021XPrivacy = - WLAN_CIPHER_SUITE_TKIP; - - /* set mic key */ - memcpy(psta->dot11tkiptxmickey.skey, - &keyparms->key[16], 8); - memcpy(psta->dot11tkiprxmickey.skey, - &keyparms->key[24], 8); - - psecuritypriv->busetkipkey = 1; - - } else if (keyparms->cipher == WLAN_CIPHER_SUITE_CCMP) { - DBG_8723A("%s, set pairwise key, CCMP\n", - __func__); - - psta->dot118021XPrivacy = - WLAN_CIPHER_SUITE_CCMP; - } else { - DBG_8723A("%s, set pairwise key, none\n", - __func__); - - psta->dot118021XPrivacy = 0; - } - - set_pairwise_key(padapter, psta); - - psta->ieee8021x_blocked = false; - - psta->bpairwise_key_installed = true; - } else { /* group key??? */ - if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 || - keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) { - memcpy(psecuritypriv-> - dot118021XGrpKey[key_index].skey, - keyparms->key, key_len); - - psecuritypriv->dot118021XGrpPrivacy = - keyparms->cipher; - } else if (keyparms->cipher == WLAN_CIPHER_SUITE_TKIP) { - psecuritypriv->dot118021XGrpPrivacy = - WLAN_CIPHER_SUITE_TKIP; - - memcpy(psecuritypriv-> - dot118021XGrpKey[key_index].skey, - keyparms->key, - (min(16, key_len))); - - /* set mic key */ - memcpy(psecuritypriv-> - dot118021XGrptxmickey[key_index].skey, - &keyparms->key[16], 8); - memcpy(psecuritypriv-> - dot118021XGrprxmickey[key_index].skey, - &keyparms->key[24], 8); - - psecuritypriv->busetkipkey = 1; - } else if (keyparms->cipher == WLAN_CIPHER_SUITE_CCMP) { - psecuritypriv->dot118021XGrpPrivacy = - WLAN_CIPHER_SUITE_CCMP; - - memcpy(psecuritypriv-> - dot118021XGrpKey[key_index].skey, - keyparms->key, - (min(16, key_len))); - } else { - psecuritypriv->dot118021XGrpPrivacy = 0; - } - - psecuritypriv->dot118021XGrpKeyid = key_index; - - psecuritypriv->binstallGrpkey = 1; - - psecuritypriv->dot11PrivacyAlgrthm = - psecuritypriv->dot118021XGrpPrivacy; - - set_group_key(padapter, keyparms, - psecuritypriv->dot118021XGrpPrivacy, - key_index); - - pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter); - if (pbcmc_sta) { - /* rx will use bmc_sta's - dot118021XPrivacy */ - pbcmc_sta->ieee8021x_blocked = false; - pbcmc_sta->dot118021XPrivacy = - psecuritypriv->dot118021XGrpPrivacy; - } - } - } - -exit: - - return 0; -} -#endif - -static int rtw_cfg80211_set_encryption(struct net_device *dev, u8 key_index, - int set_tx, const u8 *sta_addr, - struct key_params *keyparms) -{ - int ret = 0; - int key_len; - struct rtw_adapter *padapter = netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - - DBG_8723A("%s\n", __func__); - - key_len = keyparms->key_len; - - if (keyparms->cipher == WLAN_CIPHER_SUITE_WEP40 || - keyparms->cipher == WLAN_CIPHER_SUITE_WEP104) { - RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, - "wpa_set_encryption, crypt.alg = WEP\n"); - DBG_8723A("wpa_set_encryption, crypt.alg = WEP\n"); - - if (psecuritypriv->bWepDefaultKeyIdxSet == 0) { - /* wep default key has not been set, so use this - key index as default key. */ - - psecuritypriv->ndisencryptstatus = - Ndis802_11Encryption1Enabled; - psecuritypriv->dot11PrivacyAlgrthm = keyparms->cipher; - psecuritypriv->dot118021XGrpPrivacy = keyparms->cipher; - - psecuritypriv->dot11PrivacyKeyIndex = key_index; - } - - memcpy(&psecuritypriv->wep_key[key_index].key, - keyparms->key, key_len); - - psecuritypriv->wep_key[key_index].keylen = key_len; - - rtw_set_key23a(padapter, psecuritypriv, key_index, 0); - - goto exit; - } - - if (padapter->securitypriv.dot11AuthAlgrthm == - dot11AuthAlgrthm_8021X) { /* 802_1x */ - struct sta_info *psta, *pbcmc_sta; - struct sta_priv *pstapriv = &padapter->stapriv; - - if (check_fwstate(pmlmepriv, - WIFI_STATION_STATE | WIFI_MP_STATE)) { - /* sta mode */ - psta = rtw_get_stainfo23a(pstapriv, get_bssid(pmlmepriv)); - if (psta == NULL) { - DBG_8723A("%s, : Obtain Sta_info fail\n", - __func__); - } else { - /* Jeff: don't disable ieee8021x_blocked - while clearing key */ - if (keyparms->cipher != IW_AUTH_CIPHER_NONE && - keyparms->cipher != 0) - psta->ieee8021x_blocked = false; - - if ((padapter->securitypriv.ndisencryptstatus == - Ndis802_11Encryption2Enabled) || - (padapter->securitypriv.ndisencryptstatus == - Ndis802_11Encryption3Enabled)) { - psta->dot118021XPrivacy = - padapter->securitypriv. - dot11PrivacyAlgrthm; - } - - if (set_tx == 1) { - /* pairwise key */ - DBG_8723A("%s, : set_tx == 1\n", - __func__); - - memcpy(psta->dot118021x_UncstKey.skey, - keyparms->key, - (min(16, key_len))); - - if (keyparms->cipher == - WLAN_CIPHER_SUITE_TKIP) { - memcpy(psta->dot11tkiptxmickey. - skey, - &keyparms->key[16], 8); - memcpy(psta->dot11tkiprxmickey. - skey, - &keyparms->key[24], 8); - - padapter->securitypriv. - busetkipkey = 0; - } - DBG_8723A(" ~~~~set sta key:unicastkey\n"); - - rtw_setstakey_cmd23a(padapter, - (unsigned char *)psta, - true); - } else { /* group key */ - memcpy(padapter->securitypriv. - dot118021XGrpKey[key_index].skey, - keyparms->key, - (min(16, key_len))); - memcpy(padapter->securitypriv. - dot118021XGrptxmickey[key_index]. - skey, &keyparms->key[16], 8); - memcpy(padapter->securitypriv. - dot118021XGrprxmickey[key_index]. - skey, &keyparms->key[24], 8); - padapter->securitypriv.binstallGrpkey = - 1; - DBG_8723A - (" ~~~~set sta key:groupkey\n"); - - padapter->securitypriv. - dot118021XGrpKeyid = key_index; - - rtw_set_key23a(padapter, - &padapter->securitypriv, - key_index, 1); - } - } - - pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter); - if (pbcmc_sta) { - /* Jeff: don't disable ieee8021x_blocked - while clearing key */ - if (keyparms->cipher != IW_AUTH_CIPHER_NONE && - keyparms->cipher != 0) - pbcmc_sta->ieee8021x_blocked = false; - - if ((padapter->securitypriv.ndisencryptstatus == - Ndis802_11Encryption2Enabled) || - (padapter->securitypriv.ndisencryptstatus == - Ndis802_11Encryption3Enabled)) { - pbcmc_sta->dot118021XPrivacy = - padapter->securitypriv. - dot11PrivacyAlgrthm; - } - } - } - } - -exit: - - DBG_8723A("%s, ret =%d\n", __func__, ret); - - - - return ret; -} - -static int cfg80211_rtw_add_key(struct wiphy *wiphy, struct net_device *ndev, - u8 key_index, bool pairwise, - const u8 *mac_addr, struct key_params *params) -{ - int set_tx, ret = 0; - struct wireless_dev *rtw_wdev = wiphy_to_wdev(wiphy); - struct rtw_adapter *padapter = wiphy_to_adapter(wiphy); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - u8 sta_addr[ETH_ALEN]; - - DBG_8723A("%s(%s): adding key for %pM\n", __func__, ndev->name, - mac_addr); - DBG_8723A("cipher = 0x%x\n", params->cipher); - DBG_8723A("key_len = 0x%x\n", params->key_len); - DBG_8723A("seq_len = 0x%x\n", params->seq_len); - DBG_8723A("key_index =%d\n", key_index); - DBG_8723A("pairwise =%d\n", pairwise); - - switch (params->cipher) { - case IW_AUTH_CIPHER_NONE: - case WLAN_CIPHER_SUITE_WEP40: - if (params->key_len != WLAN_KEY_LEN_WEP40) { - ret = -EINVAL; - goto exit; - } - case WLAN_CIPHER_SUITE_WEP104: - if (params->key_len != WLAN_KEY_LEN_WEP104) { - ret = -EINVAL; - goto exit; - } - case WLAN_CIPHER_SUITE_TKIP: - case WLAN_CIPHER_SUITE_CCMP: - break; - default: - ret = -ENOTSUPP; - goto exit; - } - - if (key_index >= WEP_KEYS || params->key_len < 0) { - ret = -EINVAL; - goto exit; - } - - eth_broadcast_addr(sta_addr); - - if (!mac_addr || is_broadcast_ether_addr(mac_addr)) - set_tx = 0; /* for wpa/wpa2 group key */ - else - set_tx = 1; /* for wpa/wpa2 pairwise key */ - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - ret = rtw_cfg80211_set_encryption(ndev, key_index, set_tx, - sta_addr, params); - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { -#ifdef CONFIG_8723AU_AP_MODE - if (mac_addr) - ether_addr_copy(sta_addr, mac_addr); - - ret = rtw_cfg80211_ap_set_encryption(ndev, key_index, set_tx, - sta_addr, params); -#endif - } else { - DBG_8723A("error! fw_state = 0x%x, iftype =%d\n", - pmlmepriv->fw_state, rtw_wdev->iftype); - - } - -exit: - return ret; -} - -static int -cfg80211_rtw_get_key(struct wiphy *wiphy, struct net_device *ndev, - u8 key_index, bool pairwise, const u8 *mac_addr, - void *cookie, - void (*callback) (void *cookie, struct key_params *)) -{ - DBG_8723A("%s(%s)\n", __func__, ndev->name); - return 0; -} - -static int cfg80211_rtw_del_key(struct wiphy *wiphy, struct net_device *ndev, - u8 key_index, bool pairwise, - const u8 *mac_addr) -{ - struct rtw_adapter *padapter = netdev_priv(ndev); - struct security_priv *psecuritypriv = &padapter->securitypriv; - - DBG_8723A("%s(%s): key_index =%d\n", __func__, ndev->name, key_index); - - if (key_index == psecuritypriv->dot11PrivacyKeyIndex) { - /* clear the flag of wep default key set. */ - psecuritypriv->bWepDefaultKeyIdxSet = 0; - } - - return 0; -} - -static int cfg80211_rtw_set_default_key(struct wiphy *wiphy, - struct net_device *ndev, u8 key_index, - bool unicast, bool multicast) -{ - struct rtw_adapter *padapter = netdev_priv(ndev); - struct security_priv *psecuritypriv = &padapter->securitypriv; - - DBG_8723A("%s(%s): key_index =%d, unicast =%d, multicast =%d.\n", - __func__, ndev->name, key_index, unicast, multicast); - - if (key_index < NUM_WEP_KEYS && - (psecuritypriv->dot11PrivacyAlgrthm == WLAN_CIPHER_SUITE_WEP40 || - psecuritypriv->dot11PrivacyAlgrthm == WLAN_CIPHER_SUITE_WEP104)) { - /* set wep default key */ - psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled; - - psecuritypriv->dot11PrivacyKeyIndex = key_index; - - psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40; - psecuritypriv->dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP40; - if (psecuritypriv->wep_key[key_index].keylen == 13) { - psecuritypriv->dot11PrivacyAlgrthm = - WLAN_CIPHER_SUITE_WEP104; - psecuritypriv->dot118021XGrpPrivacy = - WLAN_CIPHER_SUITE_WEP104; - } - - /* set the flag to represent that wep default key - has been set */ - psecuritypriv->bWepDefaultKeyIdxSet = 1; - } - - return 0; -} - -static u16 rtw_get_cur_max_rate(struct rtw_adapter *adapter) -{ - int i = 0; - const u8 *p; - u16 rate = 0, max_rate = 0; - struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct registry_priv *pregistrypriv = &adapter->registrypriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; - struct ieee80211_ht_cap *pht_capie; - u8 rf_type = 0; - u8 bw_40MHz = 0, short_GI_20 = 0, short_GI_40 = 0; - u16 mcs_rate = 0; - - p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, - pcur_bss->IEs, pcur_bss->IELength); - if (p && p[1] > 0) { - pht_capie = (struct ieee80211_ht_cap *)(p + 2); - - memcpy(&mcs_rate, &pht_capie->mcs, 2); - - /* bw_40MHz = (pht_capie->cap_info& - IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1:0; */ - /* cur_bwmod is updated by beacon, pmlmeinfo is - updated by association response */ - bw_40MHz = (pmlmeext->cur_bwmode && - (pmlmeinfo->HT_info.ht_param & - IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) ? 1:0; - - /* short_GI = (pht_capie->cap_info & (IEEE80211_HT_CAP - _SGI_20|IEEE80211_HT_CAP_SGI_40)) ? 1 : 0; */ - short_GI_20 = (pmlmeinfo->ht_cap.cap_info & - cpu_to_le16(IEEE80211_HT_CAP_SGI_20)) ? 1:0; - short_GI_40 = (pmlmeinfo->ht_cap.cap_info & - cpu_to_le16(IEEE80211_HT_CAP_SGI_40)) ? 1:0; - - rf_type = rtl8723a_get_rf_type(adapter); - max_rate = rtw_mcs_rate23a(rf_type, bw_40MHz & - pregistrypriv->cbw40_enable, - short_GI_20, short_GI_40, - &pmlmeinfo->ht_cap.mcs); - } else { - while (pcur_bss->SupportedRates[i] != 0 && - pcur_bss->SupportedRates[i] != 0xFF) { - rate = pcur_bss->SupportedRates[i] & 0x7F; - if (rate > max_rate) - max_rate = rate; - i++; - } - - max_rate = max_rate * 10 / 2; - } - - return max_rate; -} - -static int cfg80211_rtw_get_station(struct wiphy *wiphy, - struct net_device *ndev, - const u8 *mac, struct station_info *sinfo) -{ - int ret = 0; - struct rtw_adapter *padapter = wiphy_to_adapter(wiphy); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - - sinfo->filled = 0; - - if (!mac) { - DBG_8723A("%s(%s): mac ==%p\n", __func__, ndev->name, mac); - ret = -ENOENT; - goto exit; - } - - psta = rtw_get_stainfo23a(pstapriv, mac); - if (psta == NULL) { - DBG_8723A("%s, sta_info is null\n", __func__); - ret = -ENOENT; - goto exit; - } - DBG_8723A("%s(%s): mac=%pM\n", __func__, ndev->name, mac); - - /* for infra./P2PClient mode */ - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) && - check_fwstate(pmlmepriv, _FW_LINKED)) { - struct wlan_network *cur_network = &pmlmepriv->cur_network; - - if (!ether_addr_equal(mac, cur_network->network.MacAddress)) { - DBG_8723A("%s, mismatch bssid=%pM\n", - __func__, cur_network->network.MacAddress); - ret = -ENOENT; - goto exit; - } - - sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); - sinfo->signal = translate_percentage_to_dbm(padapter->recvpriv. - signal_strength); - - sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); - sinfo->txrate.legacy = rtw_get_cur_max_rate(padapter); - - sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS); - sinfo->rx_packets = sta_rx_data_pkts(psta); - - sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS); - sinfo->tx_packets = psta->sta_stats.tx_pkts; - } - - /* for Ad-Hoc/AP mode */ - if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) || - check_fwstate(pmlmepriv, WIFI_AP_STATE)) && - check_fwstate(pmlmepriv, _FW_LINKED) - ) { - /* TODO: should acquire station info... */ - } - -exit: - return ret; -} - -static int cfg80211_infrastructure_mode(struct rtw_adapter *padapter, - enum nl80211_iftype ifmode) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_network *cur_network = &pmlmepriv->cur_network; - enum nl80211_iftype old_mode; - - old_mode = cur_network->network.ifmode; - - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_notice_, - "+%s: old =%d new =%d fw_state = 0x%08x\n", __func__, - old_mode, ifmode, get_fwstate(pmlmepriv)); - - if (old_mode != ifmode) { - spin_lock_bh(&pmlmepriv->lock); - - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, - "change mode!\n"); - - if (old_mode == NL80211_IFTYPE_AP || - old_mode == NL80211_IFTYPE_P2P_GO) { - /* change to other mode from Ndis802_11APMode */ - cur_network->join_res = -1; - -#ifdef CONFIG_8723AU_AP_MODE - stop_ap_mode23a(padapter); -#endif - } - - if (check_fwstate(pmlmepriv, _FW_LINKED) || - old_mode == NL80211_IFTYPE_ADHOC) - rtw_disassoc_cmd23a(padapter, 0, true); - - if (check_fwstate(pmlmepriv, _FW_LINKED) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) - rtw_free_assoc_resources23a(padapter, 1); - - if (old_mode == NL80211_IFTYPE_STATION || - old_mode == NL80211_IFTYPE_P2P_CLIENT || - old_mode == NL80211_IFTYPE_ADHOC) { - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - /* will clr Linked_state; before this function, - we must have chked whether issue - dis-assoc_cmd or not */ - rtw_indicate_disconnect23a(padapter); - } - } - - cur_network->network.ifmode = ifmode; - - _clr_fwstate_(pmlmepriv, ~WIFI_NULL_STATE); - - switch (ifmode) { - case NL80211_IFTYPE_ADHOC: - set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); - break; - - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_STATION: - set_fwstate(pmlmepriv, WIFI_STATION_STATE); - break; - - case NL80211_IFTYPE_P2P_GO: - case NL80211_IFTYPE_AP: - set_fwstate(pmlmepriv, WIFI_AP_STATE); -#ifdef CONFIG_8723AU_AP_MODE - start_ap_mode23a(padapter); - /* rtw_indicate_connect23a(padapter); */ -#endif - break; - - default: - break; - } - - /* SecClearAllKeys(adapter); */ - - spin_unlock_bh(&pmlmepriv->lock); - } - - return _SUCCESS; -} - -static int cfg80211_rtw_change_iface(struct wiphy *wiphy, - struct net_device *ndev, - enum nl80211_iftype type, u32 *flags, - struct vif_params *params) -{ - enum nl80211_iftype old_type; - struct rtw_adapter *padapter = wiphy_to_adapter(wiphy); - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct wireless_dev *rtw_wdev = wiphy_to_wdev(wiphy); - int ret = 0; - - DBG_8723A("%s(%s): call netdev_open23a\n", __func__, ndev->name); - - old_type = rtw_wdev->iftype; - DBG_8723A("%s(%s): old_iftype =%d, new_iftype =%d\n", - __func__, ndev->name, old_type, type); - - if (old_type != type) { - pmlmeext->action_public_rxseq = 0xffff; - pmlmeext->action_public_dialog_token = 0xff; - } - - switch (type) { - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_P2P_GO: - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_UNSPECIFIED: - break; - default: - return -EOPNOTSUPP; - } - - rtw_wdev->iftype = type; - - if (cfg80211_infrastructure_mode(padapter, type) != _SUCCESS) { - rtw_wdev->iftype = old_type; - ret = -EPERM; - goto exit; - } - - rtw_setopmode_cmd23a(padapter, type); - -exit: - return ret; -} - -void rtw_cfg80211_indicate_scan_done(struct rtw_wdev_priv *pwdev_priv, - bool aborted) -{ - spin_lock_bh(&pwdev_priv->scan_req_lock); - if (pwdev_priv->scan_request != NULL) { - DBG_8723A("%s with scan req\n", __func__); - - if (pwdev_priv->scan_request->wiphy != - pwdev_priv->rtw_wdev->wiphy) { - DBG_8723A("error wiphy compare\n"); - } else { - struct cfg80211_scan_info info = { - .aborted = aborted, - }; - - cfg80211_scan_done(pwdev_priv->scan_request, &info); - } - - pwdev_priv->scan_request = NULL; - } else { - DBG_8723A("%s without scan req\n", __func__); - } - spin_unlock_bh(&pwdev_priv->scan_req_lock); -} - -void rtw_cfg80211_surveydone_event_callback(struct rtw_adapter *padapter) -{ - struct list_head *phead; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct rtw_queue *queue = &pmlmepriv->scanned_queue; - struct wlan_network *pnetwork, *ptmp; - - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - phead = get_list_head(queue); - list_for_each_entry_safe(pnetwork, ptmp, phead, list) { - /* report network only if the current channel set - contains the channel to which this network belongs */ - if (rtw_ch_set_search_ch23a - (padapter->mlmeextpriv.channel_set, - pnetwork->network.DSConfig) >= 0) - rtw_cfg80211_inform_bss(padapter, pnetwork); - } - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - - /* call this after other things have been done */ - rtw_cfg80211_indicate_scan_done(wdev_to_priv(padapter->rtw_wdev), - false); -} - -static int rtw_cfg80211_set_probe_req_wpsp2pie(struct rtw_adapter *padapter, - char *buf, int len) -{ - int ret = 0; - const u8 *wps_ie; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - DBG_8723A("%s, ielen =%d\n", __func__, len); - - if (len > 0) { - wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPS, - buf, len); - if (wps_ie) { - DBG_8723A("probe_req_wps_ielen =%d\n", wps_ie[1]); - - if (pmlmepriv->wps_probe_req_ie) { - pmlmepriv->wps_probe_req_ie_len = 0; - kfree(pmlmepriv->wps_probe_req_ie); - pmlmepriv->wps_probe_req_ie = NULL; - } - - pmlmepriv->wps_probe_req_ie = kmemdup(wps_ie, wps_ie[1], - GFP_KERNEL); - if (pmlmepriv->wps_probe_req_ie == NULL) { - DBG_8723A("%s()-%d: kmalloc() ERROR!\n", - __func__, __LINE__); - return -EINVAL; - } - pmlmepriv->wps_probe_req_ie_len = wps_ie[1]; - } - } - - return ret; -} - -static int cfg80211_rtw_scan(struct wiphy *wiphy, - struct cfg80211_scan_request *request) -{ - int i; - u8 _status = false; - int ret = 0; - struct rtw_adapter *padapter = wiphy_to_adapter(wiphy); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct cfg80211_ssid ssid[RTW_SSID_SCAN_AMOUNT]; - struct rtw_ieee80211_channel ch[RTW_CHANNEL_SCAN_AMOUNT]; - struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev); - struct cfg80211_ssid *ssids = request->ssids; - bool need_indicate_scan_done = false; - - DBG_8723A("%s(%s)\n", __func__, padapter->pnetdev->name); - - spin_lock_bh(&pwdev_priv->scan_req_lock); - pwdev_priv->scan_request = request; - spin_unlock_bh(&pwdev_priv->scan_req_lock); - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - DBG_8723A("%s under WIFI_AP_STATE\n", __func__); - /* need_indicate_scan_done = true; */ - /* goto check_need_indicate_scan_done; */ - } - - if (rtw_pwr_wakeup(padapter) == _FAIL) { - need_indicate_scan_done = true; - goto check_need_indicate_scan_done; - } - - if (request->ie && request->ie_len > 0) { - rtw_cfg80211_set_probe_req_wpsp2pie(padapter, - (u8 *) request->ie, - request->ie_len); - } - - if (pmlmepriv->LinkDetectInfo.bBusyTraffic == true) { - DBG_8723A("%s, bBusyTraffic == true\n", __func__); - need_indicate_scan_done = true; - goto check_need_indicate_scan_done; - } - if (rtw_is_scan_deny(padapter)) { - DBG_8723A("%s(%s): scan deny\n", __func__, - padapter->pnetdev->name); - need_indicate_scan_done = true; - goto check_need_indicate_scan_done; - } - - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING) == - true) { - DBG_8723A("%s, fwstate = 0x%x\n", __func__, pmlmepriv->fw_state); - need_indicate_scan_done = true; - goto check_need_indicate_scan_done; - } - - memset(ssid, 0, sizeof(struct cfg80211_ssid) * RTW_SSID_SCAN_AMOUNT); - /* parsing request ssids, n_ssids */ - for (i = 0; i < request->n_ssids && i < RTW_SSID_SCAN_AMOUNT; i++) { - DBG_8723A("ssid =%s, len =%d\n", ssids[i].ssid, - ssids[i].ssid_len); - memcpy(ssid[i].ssid, ssids[i].ssid, ssids[i].ssid_len); - ssid[i].ssid_len = ssids[i].ssid_len; - } - - /* parsing channels, n_channels */ - memset(ch, 0, - sizeof(struct rtw_ieee80211_channel) * RTW_CHANNEL_SCAN_AMOUNT); - - if (request->n_channels == 1) { - for (i = 0; i < request->n_channels && - i < RTW_CHANNEL_SCAN_AMOUNT; i++) { - DBG_8723A("%s:(%s):" CHAN_FMT "\n", - __func__, padapter->pnetdev->name, - CHAN_ARG(request->channels[i])); - ch[i].hw_value = request->channels[i]->hw_value; - ch[i].flags = request->channels[i]->flags; - } - } - - spin_lock_bh(&pmlmepriv->lock); - if (request->n_channels == 1) { - memcpy(&ch[1], &ch[0], sizeof(struct rtw_ieee80211_channel)); - memcpy(&ch[2], &ch[0], sizeof(struct rtw_ieee80211_channel)); - _status = rtw_sitesurvey_cmd23a(padapter, ssid, - RTW_SSID_SCAN_AMOUNT, ch, 3); - } else { - _status = rtw_sitesurvey_cmd23a(padapter, ssid, - RTW_SSID_SCAN_AMOUNT, NULL, 0); - } - spin_unlock_bh(&pmlmepriv->lock); - - if (_status == false) - ret = -1; - -check_need_indicate_scan_done: - if (need_indicate_scan_done) - rtw_cfg80211_surveydone_event_callback(padapter); - return ret; -} - -static int cfg80211_rtw_set_wiphy_params(struct wiphy *wiphy, u32 changed) -{ - DBG_8723A("%s\n", __func__); - return 0; -} - -static int cfg80211_rtw_join_ibss(struct wiphy *wiphy, struct net_device *ndev, - struct cfg80211_ibss_params *params) -{ - DBG_8723A("%s(%s)\n", __func__, ndev->name); - return 0; -} - -static int cfg80211_rtw_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) -{ - DBG_8723A("%s(%s)\n", __func__, ndev->name); - return 0; -} - -static int rtw_cfg80211_set_wpa_version(struct security_priv *psecuritypriv, - u32 wpa_version) -{ - DBG_8723A("%s, wpa_version =%d\n", __func__, wpa_version); - - if (!wpa_version) { - psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen; - return 0; - } - - if (wpa_version & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) - psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPAPSK; - -/* - if (wpa_version & NL80211_WPA_VERSION_2) - { - psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPA2PSK; - } -*/ - - return 0; -} - -static int rtw_cfg80211_set_auth_type(struct security_priv *psecuritypriv, - enum nl80211_auth_type sme_auth_type) -{ - DBG_8723A("%s, nl80211_auth_type =%d\n", __func__, sme_auth_type); - - switch (sme_auth_type) { - case NL80211_AUTHTYPE_AUTOMATIC: - psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto; - - break; - case NL80211_AUTHTYPE_OPEN_SYSTEM: - psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; - - if (psecuritypriv->ndisauthtype > Ndis802_11AuthModeWPA) - psecuritypriv->dot11AuthAlgrthm = - dot11AuthAlgrthm_8021X; - break; - case NL80211_AUTHTYPE_SHARED_KEY: - psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Shared; - - psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled; - break; - default: - psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; - /* return -ENOTSUPP; */ - } - - return 0; -} - -static int rtw_cfg80211_set_cipher(struct security_priv *psecuritypriv, - u32 cipher, bool ucast) -{ - u32 ndisencryptstatus = Ndis802_11EncryptionDisabled; - - u32 *profile_cipher = ucast ? &psecuritypriv->dot11PrivacyAlgrthm : - &psecuritypriv->dot118021XGrpPrivacy; - - DBG_8723A("%s, ucast =%d, cipher = 0x%x\n", __func__, ucast, cipher); - - if (!cipher) { - *profile_cipher = 0; - psecuritypriv->ndisencryptstatus = ndisencryptstatus; - return 0; - } - - switch (cipher) { - case IW_AUTH_CIPHER_NONE: - *profile_cipher = 0; - ndisencryptstatus = Ndis802_11EncryptionDisabled; - break; - case WLAN_CIPHER_SUITE_WEP40: - *profile_cipher = WLAN_CIPHER_SUITE_WEP40; - ndisencryptstatus = Ndis802_11Encryption1Enabled; - break; - case WLAN_CIPHER_SUITE_WEP104: - *profile_cipher = WLAN_CIPHER_SUITE_WEP104; - ndisencryptstatus = Ndis802_11Encryption1Enabled; - break; - case WLAN_CIPHER_SUITE_TKIP: - *profile_cipher = WLAN_CIPHER_SUITE_TKIP; - ndisencryptstatus = Ndis802_11Encryption2Enabled; - break; - case WLAN_CIPHER_SUITE_CCMP: - *profile_cipher = WLAN_CIPHER_SUITE_CCMP; - ndisencryptstatus = Ndis802_11Encryption3Enabled; - break; - default: - DBG_8723A("Unsupported cipher: 0x%x\n", cipher); - return -ENOTSUPP; - } - - if (ucast) - psecuritypriv->ndisencryptstatus = ndisencryptstatus; - - return 0; -} - -static int rtw_cfg80211_set_key_mgt(struct security_priv *psecuritypriv, - u32 key_mgt) -{ - DBG_8723A("%s, key_mgt = 0x%x\n", __func__, key_mgt); - - if (key_mgt == WLAN_AKM_SUITE_8021X) - psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; - else if (key_mgt == WLAN_AKM_SUITE_PSK) - psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; - else - DBG_8723A("Invalid key mgt: 0x%x\n", key_mgt); - - return 0; -} - -static int rtw_cfg80211_set_wpa_ie(struct rtw_adapter *padapter, const u8 *pie, - size_t ielen) -{ - const u8 *wps_ie; - int group_cipher = 0, pairwise_cipher = 0; - int ret = 0; - const u8 *pwpa, *pwpa2; - int i; - - if (!pie || !ielen) { - /* Treat this as normal case, but need to clear - WIFI_UNDER_WPS */ - _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS); - goto exit; - } - if (ielen > MAX_WPA_IE_LEN + MAX_WPS_IE_LEN + MAX_P2P_IE_LEN) { - ret = -EINVAL; - goto exit; - } - - /* dump */ - DBG_8723A("set wpa_ie(length:%zu):\n", ielen); - for (i = 0; i < ielen; i = i + 8) - DBG_8723A("0x%.2x 0x%.2x 0x%.2x 0x%.2x " - "0x%.2x 0x%.2x 0x%.2x 0x%.2x\n", - pie[i], pie[i + 1], pie[i + 2], pie[i + 3], - pie[i + 4], pie[i + 5], pie[i + 6], pie[i + 7]); - if (ielen < RSN_HEADER_LEN) { - RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, - "Ie len too short %d\n", (int)ielen); - ret = -1; - goto exit; - } - - pwpa = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPA, - pie, ielen); - if (pwpa && pwpa[1] > 0) { - if (rtw_parse_wpa_ie23a(pwpa, pwpa[1] + 2, &group_cipher, - &pairwise_cipher, NULL) == _SUCCESS) { - padapter->securitypriv.dot11AuthAlgrthm = - dot11AuthAlgrthm_8021X; - padapter->securitypriv.ndisauthtype = - Ndis802_11AuthModeWPAPSK; - memcpy(padapter->securitypriv.supplicant_ie, pwpa, - pwpa[1] + 2); - - DBG_8723A("got wpa_ie, wpa_ielen:%u\n", pwpa[1]); - } - } - - pwpa2 = cfg80211_find_ie(WLAN_EID_RSN, pie, ielen); - if (pwpa2 && pwpa2[1] > 0) { - if (rtw_parse_wpa2_ie23a (pwpa2, pwpa2[1] + 2, &group_cipher, - &pairwise_cipher, NULL) == _SUCCESS) { - padapter->securitypriv.dot11AuthAlgrthm = - dot11AuthAlgrthm_8021X; - padapter->securitypriv.ndisauthtype = - Ndis802_11AuthModeWPA2PSK; - memcpy(padapter->securitypriv.supplicant_ie, pwpa2, - pwpa2[1] + 2); - - DBG_8723A("got wpa2_ie, wpa2_ielen:%u\n", pwpa2[1]); - } - } - - if (group_cipher == 0) { - group_cipher = WPA_CIPHER_NONE; - } - if (pairwise_cipher == 0) { - pairwise_cipher = WPA_CIPHER_NONE; - } - - switch (group_cipher) { - case WPA_CIPHER_NONE: - padapter->securitypriv.dot118021XGrpPrivacy = 0; - padapter->securitypriv.ndisencryptstatus = - Ndis802_11EncryptionDisabled; - break; - case WPA_CIPHER_WEP40: - padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP40; - padapter->securitypriv.ndisencryptstatus = - Ndis802_11Encryption1Enabled; - break; - case WPA_CIPHER_TKIP: - padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_TKIP; - padapter->securitypriv.ndisencryptstatus = - Ndis802_11Encryption2Enabled; - break; - case WPA_CIPHER_CCMP: - padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_CCMP; - padapter->securitypriv.ndisencryptstatus = - Ndis802_11Encryption3Enabled; - break; - case WPA_CIPHER_WEP104: - padapter->securitypriv.dot118021XGrpPrivacy = WLAN_CIPHER_SUITE_WEP104; - padapter->securitypriv.ndisencryptstatus = - Ndis802_11Encryption1Enabled; - break; - } - - switch (pairwise_cipher) { - case WPA_CIPHER_NONE: - padapter->securitypriv.dot11PrivacyAlgrthm = 0; - padapter->securitypriv.ndisencryptstatus = - Ndis802_11EncryptionDisabled; - break; - case WPA_CIPHER_WEP40: - padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40; - padapter->securitypriv.ndisencryptstatus = - Ndis802_11Encryption1Enabled; - break; - case WPA_CIPHER_TKIP: - padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_TKIP; - padapter->securitypriv.ndisencryptstatus = - Ndis802_11Encryption2Enabled; - break; - case WPA_CIPHER_CCMP: - padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_CCMP; - padapter->securitypriv.ndisencryptstatus = - Ndis802_11Encryption3Enabled; - break; - case WPA_CIPHER_WEP104: - padapter->securitypriv.dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP104; - padapter->securitypriv.ndisencryptstatus = - Ndis802_11Encryption1Enabled; - break; - } - - wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPS, - pie, ielen); - if (wps_ie && wps_ie[1] > 0) { - DBG_8723A("got wps_ie, wps_ielen:%u\n", wps_ie[1]); - padapter->securitypriv.wps_ie_len = wps_ie[1]; - memcpy(padapter->securitypriv.wps_ie, wps_ie, - padapter->securitypriv.wps_ie_len); - set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS); - } else { - _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS); - } - - /* TKIP and AES disallow multicast packets until installing group key */ - if (padapter->securitypriv.dot11PrivacyAlgrthm == - WLAN_CIPHER_SUITE_TKIP || - padapter->securitypriv.dot11PrivacyAlgrthm == - WLAN_CIPHER_SUITE_CCMP) - /* WPS open need to enable multicast */ - /* check_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS) == true)*/ - rtl8723a_off_rcr_am(padapter); - - RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, - "rtw_set_wpa_ie: pairwise_cipher = 0x%08x padapter->securitypriv.ndisencryptstatus =%d padapter->securitypriv.ndisauthtype =%d\n", - pairwise_cipher, - padapter->securitypriv.ndisencryptstatus, - padapter->securitypriv.ndisauthtype); - -exit: - if (ret) - _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS); - return ret; -} - -static int rtw_cfg80211_add_wep(struct rtw_adapter *padapter, - struct rtw_wep_key *wep, u8 keyid) -{ - int res; - struct security_priv *psecuritypriv = &padapter->securitypriv; - - if (keyid >= NUM_WEP_KEYS) { - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, - "%s:keyid>4 =>fail\n", __func__); - res = _FAIL; - goto exit; - } - - switch (wep->keylen) { - case WLAN_KEY_LEN_WEP40: - psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP40; - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, - "%s:wep->KeyLength = 5\n", __func__); - break; - case WLAN_KEY_LEN_WEP104: - psecuritypriv->dot11PrivacyAlgrthm = WLAN_CIPHER_SUITE_WEP104; - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, - "%s:wep->KeyLength = 13\n", __func__); - break; - default: - psecuritypriv->dot11PrivacyAlgrthm = 0; - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, - "%s:wep->KeyLength!= 5 or 13\n", __func__); - res = _FAIL; - goto exit; - } - - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, - "%s:before memcpy, wep->KeyLength = 0x%x keyid =%x\n", - __func__, wep->keylen, keyid); - - memcpy(&psecuritypriv->wep_key[keyid], wep, sizeof(struct rtw_wep_key)); - - 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->wep_key[keyid].key[0], - psecuritypriv->wep_key[keyid].key[1], - psecuritypriv->wep_key[keyid].key[2], - psecuritypriv->wep_key[keyid].key[3], - psecuritypriv->wep_key[keyid].key[4], - psecuritypriv->wep_key[keyid].key[5], - psecuritypriv->wep_key[keyid].key[6], - psecuritypriv->wep_key[keyid].key[7], - psecuritypriv->wep_key[keyid].key[8], - psecuritypriv->wep_key[keyid].key[9], - psecuritypriv->wep_key[keyid].key[10], - psecuritypriv->wep_key[keyid].key[11], - psecuritypriv->wep_key[keyid].key[12]); - - res = rtw_set_key23a(padapter, psecuritypriv, keyid, 1); - -exit: - - return res; -} - -static int rtw_set_ssid(struct rtw_adapter *padapter, - struct wlan_network *newnetwork) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_network *pnetwork = &pmlmepriv->cur_network; - int status = _SUCCESS; - u32 cur_time = 0; - - DBG_8723A_LEVEL(_drv_always_, "set ssid [%s] fw_state = 0x%08x\n", - newnetwork->network.Ssid.ssid, get_fwstate(pmlmepriv)); - - if (padapter->hw_init_completed == false) { - 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_8723A("Set SSID under fw_state = 0x%08x\n", get_fwstate(pmlmepriv)); - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) - goto handle_tkip_countermeasure; - - 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_len == - newnetwork->network.Ssid.ssid_len && - !memcmp(&pmlmepriv->assoc_ssid.ssid, - newnetwork->network.Ssid.ssid, - newnetwork->network.Ssid.ssid_len)) { - if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - RT_TRACE(_module_rtl871x_ioctl_set_c_, - _drv_err_, - "New SSID is same SSID, fw_state = 0x%08x\n", - get_fwstate(pmlmepriv)); - - if (rtw_is_same_ibss23a(padapter, pnetwork)) { - /* - * it means driver is in - * WIFI_ADHOC_MASTER_STATE, we needn't - * create bss again. - */ - goto release_mlme_lock; - } - - /* - * if in WIFI_ADHOC_MASTER_STATE | - * WIFI_ADHOC_STATE, create bss or - * rejoin again - */ - rtw_disassoc_cmd23a(padapter, 0, true); - - if (check_fwstate(pmlmepriv, _FW_LINKED)) - rtw_indicate_disconnect23a(padapter); - - rtw_free_assoc_resources23a(padapter, 1); - - if (check_fwstate(pmlmepriv, - WIFI_ADHOC_MASTER_STATE)) { - _clr_fwstate_(pmlmepriv, - WIFI_ADHOC_MASTER_STATE); - set_fwstate(pmlmepriv, - WIFI_ADHOC_STATE); - } - } else { - rtw_lps_ctrl_wk_cmd23a(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", - newnetwork->network.Ssid.ssid, - newnetwork->network.Ssid.ssid_len); - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, - "assoc_ssid =[%s] len = 0x%x\n", - pmlmepriv->assoc_ssid.ssid, - pmlmepriv->assoc_ssid.ssid_len); - - rtw_disassoc_cmd23a(padapter, 0, true); - - if (check_fwstate(pmlmepriv, _FW_LINKED)) - rtw_indicate_disconnect23a(padapter); - - rtw_free_assoc_resources23a(padapter, 1); - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { - _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE); - set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); - } - } - } - -handle_tkip_countermeasure: - - if (padapter->securitypriv.btkip_countermeasure == true) { - cur_time = jiffies; - - if ((cur_time - - padapter->securitypriv.btkip_countermeasure_time) > - 60 * HZ) { - padapter->securitypriv.btkip_countermeasure = false; - padapter->securitypriv.btkip_countermeasure_time = 0; - } else { - status = _FAIL; - goto release_mlme_lock; - } - } - - memcpy(&pmlmepriv->assoc_ssid, &newnetwork->network.Ssid, - sizeof(struct cfg80211_ssid)); - - pmlmepriv->assoc_by_bssid = false; - - pmlmepriv->to_join = true; - - if (!check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) { - pmlmepriv->cur_network.join_res = -2; - - status = rtw_do_join_network(padapter, newnetwork); - if (status == _SUCCESS) { - pmlmepriv->to_join = false; - } else { - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { - /* switch to ADHOC_MASTER */ - status = rtw_do_join_adhoc(padapter); - if (status != _SUCCESS) - goto release_mlme_lock; - } else { - /* can't associate ; reset under-linking */ - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); - status = _FAIL; - pmlmepriv->to_join = false; - } - } - } -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; -} - -static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev, - struct cfg80211_connect_params *sme) -{ - int ret = 0; - struct list_head *phead, *plist, *ptmp; - struct wlan_network *pnetwork = NULL; - /* u8 matched_by_bssid = false; */ - /* u8 matched_by_ssid = false; */ - u8 matched = false; - struct rtw_adapter *padapter = wiphy_to_adapter(wiphy); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct rtw_queue *queue = &pmlmepriv->scanned_queue; - - DBG_8723A("=>" "%s(%s)\n", __func__, ndev->name); - DBG_8723A("privacy =%d, key =%p, key_len =%d, key_idx =%d\n", - sme->privacy, sme->key, sme->key_len, sme->key_idx); - - if (_FAIL == rtw_pwr_wakeup(padapter)) { - ret = -EPERM; - goto exit; - } - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - ret = -EPERM; - goto exit; - } - - if (!sme->ssid || !sme->ssid_len || - sme->ssid_len > IEEE80211_MAX_SSID_LEN) { - ret = -EINVAL; - goto exit; - } - - DBG_8723A("ssid =%s, len =%zu\n", sme->ssid, sme->ssid_len); - - if (sme->bssid) - DBG_8723A("bssid=%pM\n", sme->bssid); - - if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) { - ret = -EBUSY; - DBG_8723A("%s, fw_state = 0x%x, goto exit\n", __func__, - pmlmepriv->fw_state); - goto exit; - } - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) { - rtw_scan_abort23a(padapter); - } - - spin_lock_bh(&queue->lock); - - phead = get_list_head(queue); - - list_for_each_safe(plist, ptmp, phead) { - pnetwork = container_of(plist, struct wlan_network, list); - - if (sme->bssid) { - if (!ether_addr_equal(pnetwork->network.MacAddress, - sme->bssid)) - continue; - } - - if (sme->ssid && sme->ssid_len) { - if (pnetwork->network.Ssid.ssid_len != sme->ssid_len || - memcmp(pnetwork->network.Ssid.ssid, sme->ssid, - sme->ssid_len)) - continue; - } - - if (sme->bssid) { - if (ether_addr_equal(pnetwork->network.MacAddress, - sme->bssid)) { - DBG_8723A("matched by bssid\n"); - - matched = true; - break; - } - } else if (sme->ssid && sme->ssid_len) { - if (!memcmp(pnetwork->network.Ssid.ssid, - sme->ssid, sme->ssid_len) && - pnetwork->network.Ssid.ssid_len == sme->ssid_len) { - DBG_8723A("matched by ssid\n"); - - matched = true; - break; - } - } - } - - spin_unlock_bh(&queue->lock); - - if (!matched || !pnetwork) { - ret = -ENOENT; - DBG_8723A("connect, matched == false, goto exit\n"); - goto exit; - } - - if (cfg80211_infrastructure_mode( - padapter, pnetwork->network.ifmode) != _SUCCESS) { - ret = -EPERM; - goto exit; - } - - psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled; - psecuritypriv->dot11PrivacyAlgrthm = 0; - psecuritypriv->dot118021XGrpPrivacy = 0; - psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; - psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen; - - ret = rtw_cfg80211_set_wpa_version(psecuritypriv, - sme->crypto.wpa_versions); - if (ret < 0) - goto exit; - - ret = rtw_cfg80211_set_auth_type(psecuritypriv, sme->auth_type); - - if (ret < 0) - goto exit; - - DBG_8723A("%s, ie_len =%zu\n", __func__, sme->ie_len); - - ret = rtw_cfg80211_set_wpa_ie(padapter, sme->ie, sme->ie_len); - if (ret < 0) - goto exit; - - if (sme->crypto.n_ciphers_pairwise) { - ret = rtw_cfg80211_set_cipher(psecuritypriv, - sme->crypto.ciphers_pairwise[0], - true); - if (ret < 0) - goto exit; - } - - /* For WEP Shared auth */ - if ((psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_Shared || - psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_Auto) && - sme->key) { - struct rtw_wep_key wep_key; - u8 wep_key_idx, wep_key_len; - DBG_8723A("%s(): Shared/Auto WEP\n", __func__); - - wep_key_idx = sme->key_idx; - wep_key_len = sme->key_len; - - if (wep_key_idx > WEP_KEYS || !wep_key_len || - wep_key_len > WLAN_KEY_LEN_WEP104) { - ret = -EINVAL; - goto exit; - } - - wep_key_len = wep_key_len <= 5 ? 5 : 13; - - memset(&wep_key, 0, sizeof(struct rtw_wep_key)); - - wep_key.keylen = wep_key_len; - - if (wep_key_len == 13) { - padapter->securitypriv.dot11PrivacyAlgrthm = - WLAN_CIPHER_SUITE_WEP104; - padapter->securitypriv.dot118021XGrpPrivacy = - WLAN_CIPHER_SUITE_WEP104; - } else { - padapter->securitypriv.dot11PrivacyAlgrthm = - WLAN_CIPHER_SUITE_WEP40; - padapter->securitypriv.dot118021XGrpPrivacy = - WLAN_CIPHER_SUITE_WEP40; - } - - memcpy(wep_key.key, (void *)sme->key, wep_key.keylen); - - if (rtw_cfg80211_add_wep(padapter, &wep_key, wep_key_idx) != - _SUCCESS) - ret = -EOPNOTSUPP; - - if (ret < 0) - goto exit; - } - - ret = rtw_cfg80211_set_cipher(psecuritypriv, - sme->crypto.cipher_group, false); - if (ret < 0) - goto exit; - - if (sme->crypto.n_akm_suites) { - ret = rtw_cfg80211_set_key_mgt(psecuritypriv, - sme->crypto.akm_suites[0]); - if (ret < 0) - goto exit; - } - - if (psecuritypriv->ndisauthtype > 3) - psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; - - if (rtw_set_auth23a(padapter, psecuritypriv) != _SUCCESS) { - ret = -EBUSY; - goto exit; - } - - /* rtw_set_802_11_encryption_mode(padapter, - padapter->securitypriv.ndisencryptstatus); */ - - if (rtw_set_ssid(padapter, pnetwork) != _SUCCESS) { - ret = -EBUSY; - goto exit; - } - - DBG_8723A("set ssid:dot11AuthAlgrthm =%d, dot11PrivacyAlgrthm =%d, " - "dot118021XGrpPrivacy =%d\n", psecuritypriv->dot11AuthAlgrthm, - psecuritypriv->dot11PrivacyAlgrthm, - psecuritypriv->dot118021XGrpPrivacy); - -exit: - - DBG_8723A("<=%s, ret %d\n", __func__, ret); - - return ret; -} - -static int cfg80211_rtw_disconnect(struct wiphy *wiphy, struct net_device *ndev, - u16 reason_code) -{ - struct rtw_adapter *padapter = wiphy_to_adapter(wiphy); - - DBG_8723A("%s(%s)\n", __func__, ndev->name); - - rtw_set_roaming(padapter, 0); - - if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) { - rtw_scan_abort23a(padapter); - LeaveAllPowerSaveMode23a(padapter); - rtw_disassoc_cmd23a(padapter, 500, false); - - DBG_8723A("%s...call rtw_indicate_disconnect23a\n", __func__); - - padapter->mlmepriv.not_indic_disco = true; - rtw_indicate_disconnect23a(padapter); - padapter->mlmepriv.not_indic_disco = false; - - rtw_free_assoc_resources23a(padapter, 1); - } - - return 0; -} - -static int cfg80211_rtw_set_txpower(struct wiphy *wiphy, - struct wireless_dev *wdev, - enum nl80211_tx_power_setting type, int mbm) -{ - DBG_8723A("%s\n", __func__); - return 0; -} - -static int cfg80211_rtw_get_txpower(struct wiphy *wiphy, - struct wireless_dev *wdev, int *dbm) -{ - DBG_8723A("%s\n", __func__); - *dbm = 12; - return 0; -} - -inline bool rtw_cfg80211_pwr_mgmt(struct rtw_adapter *adapter) -{ - struct rtw_wdev_priv *rtw_wdev_priv = wdev_to_priv(adapter->rtw_wdev); - return rtw_wdev_priv->power_mgmt; -} - -static int cfg80211_rtw_set_power_mgmt(struct wiphy *wiphy, - struct net_device *ndev, - bool enabled, int timeout) -{ - struct rtw_adapter *padapter = wiphy_to_adapter(wiphy); - struct rtw_wdev_priv *rtw_wdev_priv = wdev_to_priv(padapter->rtw_wdev); - - DBG_8723A("%s(%s): enabled:%u, timeout:%d\n", - __func__, ndev->name, enabled, timeout); - - rtw_wdev_priv->power_mgmt = enabled; - - if (!enabled) - LPS_Leave23a(padapter); - - return 0; -} - -static int cfg80211_rtw_set_pmksa(struct wiphy *wiphy, - struct net_device *netdev, - struct cfg80211_pmksa *pmksa) -{ - u8 index, blInserted = false; - struct rtw_adapter *padapter = wiphy_to_adapter(wiphy); - struct security_priv *psecuritypriv = &padapter->securitypriv; - - DBG_8723A("%s(%s)\n", __func__, netdev->name); - - if (is_zero_ether_addr(pmksa->bssid)) - return -EINVAL; - - blInserted = false; - - /* overwrite PMKID */ - for (index = 0; index < NUM_PMKID_CACHE; index++) { - if (ether_addr_equal(psecuritypriv->PMKIDList[index].Bssid, - pmksa->bssid)) { - /* BSSID is matched, the same AP => rewrite with - new PMKID. */ - DBG_8723A("%s(%s): BSSID exists in the PMKList.\n", - __func__, netdev->name); - - memcpy(psecuritypriv->PMKIDList[index].PMKID, - pmksa->pmkid, WLAN_PMKID_LEN); - psecuritypriv->PMKIDList[index].bUsed = true; - psecuritypriv->PMKIDIndex = index + 1; - blInserted = true; - break; - } - } - - if (!blInserted) { - /* Find a new entry */ - DBG_8723A("%s(%s): Use new entry index = %d for this PMKID\n", - __func__, netdev->name, psecuritypriv->PMKIDIndex); - - ether_addr_copy( - psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex]. - Bssid, pmksa->bssid); - memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex]. - PMKID, pmksa->pmkid, WLAN_PMKID_LEN); - - psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bUsed = - true; - psecuritypriv->PMKIDIndex++; - if (psecuritypriv->PMKIDIndex == 16) { - psecuritypriv->PMKIDIndex = 0; - } - } - - return 0; -} - -static int cfg80211_rtw_del_pmksa(struct wiphy *wiphy, - struct net_device *netdev, - struct cfg80211_pmksa *pmksa) -{ - u8 index, bMatched = false; - struct rtw_adapter *padapter = wiphy_to_adapter(wiphy); - struct security_priv *psecuritypriv = &padapter->securitypriv; - - DBG_8723A("%s(%s)\n", __func__, netdev->name); - - for (index = 0; index < NUM_PMKID_CACHE; index++) { - if (ether_addr_equal(psecuritypriv->PMKIDList[index].Bssid, - pmksa->bssid)) { - /* BSSID is matched, the same AP => Remove this PMKID - information and reset it. */ - eth_zero_addr(psecuritypriv->PMKIDList[index].Bssid); - memset(psecuritypriv->PMKIDList[index].PMKID, 0x00, - WLAN_PMKID_LEN); - psecuritypriv->PMKIDList[index].bUsed = false; - bMatched = true; - break; - } - } - - if (false == bMatched) { - DBG_8723A("%s(%s): do not have matched BSSID\n", __func__, - netdev->name); - return -EINVAL; - } - - return 0; -} - -static int cfg80211_rtw_flush_pmksa(struct wiphy *wiphy, - struct net_device *netdev) -{ - struct rtw_adapter *padapter = wiphy_to_adapter(wiphy); - struct security_priv *psecuritypriv = &padapter->securitypriv; - - DBG_8723A("%s(%s)\n", __func__, netdev->name); - - memset(&psecuritypriv->PMKIDList[0], 0x00, - sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE); - psecuritypriv->PMKIDIndex = 0; - - return 0; -} - -#ifdef CONFIG_8723AU_AP_MODE -void rtw_cfg80211_indicate_sta_assoc(struct rtw_adapter *padapter, - u8 *pmgmt_frame, uint frame_len) -{ - s32 freq; - int channel; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct net_device *ndev = padapter->pnetdev; - - DBG_8723A("%s(padapter =%p,%s)\n", __func__, padapter, ndev->name); - -#if defined(RTW_USE_CFG80211_STA_EVENT) - { - struct station_info sinfo; - u8 ie_offset; - - if (ieee80211_is_assoc_req(hdr->frame_control)) - ie_offset = offsetof(struct ieee80211_mgmt, - u.assoc_req.variable); - else /* WIFI_REASSOCREQ */ - ie_offset = offsetof(struct ieee80211_mgmt, - u.reassoc_req.variable); - - sinfo.filled = 0; - sinfo.assoc_req_ies = pmgmt_frame + ie_offset; - sinfo.assoc_req_ies_len = frame_len - ie_offset; - cfg80211_new_sta(ndev, hdr->addr2, &sinfo, GFP_ATOMIC); - } -#else /* defined(RTW_USE_CFG80211_STA_EVENT) */ - channel = pmlmeext->cur_channel; - if (channel <= RTW_CH_MAX_2G_CHANNEL) - freq = ieee80211_channel_to_frequency(channel, - NL80211_BAND_2GHZ); - else - freq = ieee80211_channel_to_frequency(channel, - NL80211_BAND_5GHZ); - - cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, pmgmt_frame, frame_len, - 0); -#endif /* defined(RTW_USE_CFG80211_STA_EVENT) */ -} - -void rtw_cfg80211_indicate_sta_disassoc(struct rtw_adapter *padapter, - unsigned char *da, - unsigned short reason) -{ - s32 freq; - int channel; - uint frame_len; - struct ieee80211_mgmt mgmt; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct net_device *ndev = padapter->pnetdev; - - DBG_8723A("%s(padapter =%p,%s)\n", __func__, padapter, ndev->name); - - memset(&mgmt, 0, sizeof(struct ieee80211_mgmt)); - -#if defined(RTW_USE_CFG80211_STA_EVENT) - cfg80211_del_sta(ndev, da, GFP_ATOMIC); -#else /* defined(RTW_USE_CFG80211_STA_EVENT) */ - channel = pmlmeext->cur_channel; - if (channel <= RTW_CH_MAX_2G_CHANNEL) - freq = ieee80211_channel_to_frequency(channel, - NL80211_BAND_2GHZ); - else - freq = ieee80211_channel_to_frequency(channel, - NL80211_BAND_5GHZ); - - mgmt.frame_control = - cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH); - - ether_addr_copy(mgmt.da, myid(&padapter->eeprompriv)); - ether_addr_copy(mgmt.sa, da); - ether_addr_copy(mgmt.bssid, get_my_bssid23a(&pmlmeinfo->network)); - - mgmt.seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - pmlmeext->mgnt_seq++; - - mgmt.u.disassoc.reason_code = cpu_to_le16(reason); - - frame_len = sizeof(struct ieee80211_hdr_3addr) + 2; - - cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, (u8 *)&mgmt, frame_len, - 0); -#endif /* defined(RTW_USE_CFG80211_STA_EVENT) */ -} - -static int rtw_cfg80211_monitor_if_open(struct net_device *ndev) -{ - DBG_8723A("%s\n", __func__); - - return 0; -} - -static int rtw_cfg80211_monitor_if_close(struct net_device *ndev) -{ - DBG_8723A("%s\n", __func__); - - return 0; -} - -static int rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb, - struct net_device *ndev) -{ - int ret = 0; - int rtap_len; - int qos_len = 0; - int dot11_hdr_len = 24; - int snap_len = 6; - unsigned char *pdata; - unsigned char src_mac_addr[6]; - unsigned char dst_mac_addr[6]; - struct ieee80211_hdr *dot11_hdr; - struct ieee80211_radiotap_header *rtap_hdr; - struct rtw_adapter *padapter = netdev_priv(ndev); - - DBG_8723A("%s(%s)\n", __func__, ndev->name); - - if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header))) - goto fail; - - rtap_hdr = (struct ieee80211_radiotap_header *)skb->data; - if (unlikely(rtap_hdr->it_version)) - goto fail; - - rtap_len = ieee80211_get_radiotap_len(skb->data); - if (unlikely(skb->len < rtap_len)) - goto fail; - - if (rtap_len != 14) { - DBG_8723A("radiotap len (should be 14): %d\n", rtap_len); - goto fail; - } - - /* Skip the ratio tap header */ - skb_pull(skb, rtap_len); - - dot11_hdr = (struct ieee80211_hdr *)skb->data; - /* Check if the QoS bit is set */ - if (ieee80211_is_data(dot11_hdr->frame_control)) { - /* Check if this ia a Wireless Distribution System (WDS) frame - * which has 4 MAC addresses - */ - if (ieee80211_is_data_qos(dot11_hdr->frame_control)) - qos_len = IEEE80211_QOS_CTL_LEN; - if (ieee80211_has_a4(dot11_hdr->frame_control)) - dot11_hdr_len += 6; - - memcpy(dst_mac_addr, dot11_hdr->addr1, sizeof(dst_mac_addr)); - memcpy(src_mac_addr, dot11_hdr->addr2, sizeof(src_mac_addr)); - - /* - * Skip the 802.11 header, QoS (if any) and SNAP, - * but leave spaces for two MAC addresses - */ - skb_pull(skb, dot11_hdr_len + qos_len + snap_len - - ETH_ALEN * 2); - pdata = (unsigned char *)skb->data; - ether_addr_copy(pdata, dst_mac_addr); - ether_addr_copy(pdata + ETH_ALEN, src_mac_addr); - - DBG_8723A("should be eapol packet\n"); - - /* Use the real net device to transmit the packet */ - ret = rtw_xmit23a_entry23a(skb, padapter->pnetdev); - - return ret; - - } else if (ieee80211_is_action(dot11_hdr->frame_control)) { - struct ieee80211_mgmt *mgmt; - /* only for action frames */ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - /* u8 category, action, OUI_Subtype, dialogToken = 0; */ - /* unsigned char *frame_body; */ - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - u32 len = skb->len; - u8 category, action; - - mgmt = (struct ieee80211_mgmt *)dot11_hdr; - - DBG_8723A("RTW_Tx:da=%pM via %s(%s)\n", - mgmt->da, __func__, ndev->name); - category = mgmt->u.action.category; - action = mgmt->u.action.u.wme_action.action_code; - DBG_8723A("RTW_Tx:category(%u), action(%u)\n", - category, action); - - /* starting alloc mgmt frame to dump it */ - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (pmgntframe == NULL) - goto fail; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - pattrib->retry_ctrl = false; - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - - memcpy(pframe, skb->data, len); - pattrib->pktlen = len; - - /* update seq number */ - pmlmeext->mgnt_seq = le16_to_cpu(dot11_hdr->seq_ctrl) >> 4; - pattrib->seqnum = pmlmeext->mgnt_seq; - pmlmeext->mgnt_seq++; - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe23a(padapter, pmgntframe); - } - -fail: - - dev_kfree_skb(skb); - - return 0; -} - -static int -rtw_cfg80211_monitor_if_set_mac_address(struct net_device *ndev, void *addr) -{ - DBG_8723A("%s\n", __func__); - - return 0; -} - -static const struct net_device_ops rtw_cfg80211_monitor_if_ops = { - .ndo_open = rtw_cfg80211_monitor_if_open, - .ndo_stop = rtw_cfg80211_monitor_if_close, - .ndo_start_xmit = rtw_cfg80211_monitor_if_xmit_entry, - .ndo_set_mac_address = rtw_cfg80211_monitor_if_set_mac_address, -}; - -static int rtw_cfg80211_add_monitor_if(struct rtw_adapter *padapter, char *name, - unsigned char name_assign_type, - struct net_device **ndev) -{ - int ret = 0; - struct net_device *mon_ndev = NULL; - struct wireless_dev *mon_wdev = NULL; - struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev); - - if (!name) { - DBG_8723A("%s(%s): without specific name\n", - __func__, padapter->pnetdev->name); - ret = -EINVAL; - goto out; - } - - if (pwdev_priv->pmon_ndev) { - DBG_8723A("%s(%s): monitor interface exist: %s\n", __func__, - padapter->pnetdev->name, pwdev_priv->pmon_ndev->name); - ret = -EBUSY; - goto out; - } - - mon_ndev = alloc_etherdev(sizeof(struct rtw_adapter)); - if (!mon_ndev) { - DBG_8723A("%s(%s): allocate ndev fail\n", __func__, - padapter->pnetdev->name); - ret = -ENOMEM; - goto out; - } - - mon_ndev->type = ARPHRD_IEEE80211_RADIOTAP; - strncpy(mon_ndev->name, name, IFNAMSIZ); - mon_ndev->name[IFNAMSIZ - 1] = 0; - mon_ndev->name_assign_type = name_assign_type; - mon_ndev->destructor = rtw_ndev_destructor; - - mon_ndev->netdev_ops = &rtw_cfg80211_monitor_if_ops; - - /* wdev */ - mon_wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); - if (!mon_wdev) { - ret = -ENOMEM; - goto out; - } - - mon_wdev->wiphy = padapter->rtw_wdev->wiphy; - mon_wdev->netdev = mon_ndev; - mon_wdev->iftype = NL80211_IFTYPE_MONITOR; - mon_ndev->ieee80211_ptr = mon_wdev; - - ret = register_netdevice(mon_ndev); - if (ret) { - goto out; - } - - *ndev = pwdev_priv->pmon_ndev = mon_ndev; - memcpy(pwdev_priv->ifname_mon, name, IFNAMSIZ + 1); - -out: - if (ret) { - kfree(mon_wdev); - mon_wdev = NULL; - } - - if (ret && mon_ndev) { - free_netdev(mon_ndev); - *ndev = mon_ndev = NULL; - } - - return ret; -} - -static struct wireless_dev * -cfg80211_rtw_add_virtual_intf(struct wiphy *wiphy, const char *name, - unsigned char name_assign_type, - enum nl80211_iftype type, u32 *flags, - struct vif_params *params) -{ - int ret = 0; - struct net_device *ndev = NULL; - struct rtw_adapter *padapter = wiphy_to_adapter(wiphy); - - DBG_8723A("%s(%s): wiphy:%s, name:%s, type:%d\n", __func__, - padapter->pnetdev->name, wiphy_name(wiphy), name, type); - - switch (type) { - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_AP_VLAN: - case NL80211_IFTYPE_WDS: - case NL80211_IFTYPE_MESH_POINT: - ret = -ENODEV; - break; - case NL80211_IFTYPE_MONITOR: - ret = - rtw_cfg80211_add_monitor_if(padapter, (char *)name, - name_assign_type, &ndev); - break; - - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_STATION: - ret = -ENODEV; - break; - - case NL80211_IFTYPE_P2P_GO: - case NL80211_IFTYPE_AP: - ret = -ENODEV; - break; - default: - ret = -ENODEV; - DBG_8723A("Unsupported interface type\n"); - break; - } - - DBG_8723A("%s(%s): ndev:%p, ret:%d\n", __func__, - padapter->pnetdev->name, - ndev, ret); - - return ndev ? ndev->ieee80211_ptr : ERR_PTR(ret); -} - -static int cfg80211_rtw_del_virtual_intf(struct wiphy *wiphy, - struct wireless_dev *wdev) -{ - struct rtw_wdev_priv *pwdev_priv = - (struct rtw_wdev_priv *)wiphy_priv(wiphy); - struct net_device *ndev; - ndev = wdev ? wdev->netdev : NULL; - - if (!ndev) - goto exit; - - unregister_netdevice(ndev); - - if (ndev == pwdev_priv->pmon_ndev) { - pwdev_priv->pmon_ndev = NULL; - pwdev_priv->ifname_mon[0] = '\0'; - DBG_8723A("%s(%s): remove monitor interface\n", - __func__, ndev->name); - } - -exit: - return 0; -} - -static int rtw_add_beacon(struct rtw_adapter *adapter, const u8 *head, - size_t head_len, const u8 *tail, size_t tail_len) -{ - int ret = 0; - u8 *pbuf; - uint len, ielen, wps_ielen = 0; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct wlan_bssid_ex *bss = &pmlmepriv->cur_network.network; - const struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)head; - struct ieee80211_mgmt *tmpmgmt; - /* struct sta_priv *pstapriv = &padapter->stapriv; */ - - DBG_8723A("%s beacon_head_len =%zu, beacon_tail_len =%zu\n", - __func__, head_len, tail_len); - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) - return -EINVAL; - - if (head_len < offsetof(struct ieee80211_mgmt, u.beacon.variable)) - return -EINVAL; - - pbuf = kzalloc(head_len + tail_len, GFP_KERNEL); - if (!pbuf) - return -ENOMEM; - tmpmgmt = (struct ieee80211_mgmt *)pbuf; - - bss->beacon_interval = get_unaligned_le16(&mgmt->u.beacon.beacon_int); - bss->capability = get_unaligned_le16(&mgmt->u.beacon.capab_info); - bss->tsf = get_unaligned_le64(&mgmt->u.beacon.timestamp); - - /* 24 = beacon header len. */ - memcpy(pbuf, (void *)head, head_len); - memcpy(pbuf + head_len, (void *)tail, tail_len); - - len = head_len + tail_len; - ielen = len - offsetof(struct ieee80211_mgmt, u.beacon.variable); - /* check wps ie if inclued */ - if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPS, - tmpmgmt->u.beacon.variable, ielen)) - DBG_8723A("add bcn, wps_ielen =%d\n", wps_ielen); - - /* pbss_network->IEs will not include p2p_ie, wfd ie */ - rtw_ies_remove_ie23a(tmpmgmt->u.beacon.variable, &ielen, 0, - WLAN_EID_VENDOR_SPECIFIC, P2P_OUI23A, 4); - rtw_ies_remove_ie23a(tmpmgmt->u.beacon.variable, &ielen, 0, - WLAN_EID_VENDOR_SPECIFIC, WFD_OUI23A, 4); - - len = ielen + offsetof(struct ieee80211_mgmt, u.beacon.variable); - if (rtw_check_beacon_data23a(adapter, tmpmgmt, len) == _SUCCESS) { - ret = 0; - } else { - ret = -EINVAL; - } - - kfree(pbuf); - - return ret; -} - -static int cfg80211_rtw_start_ap(struct wiphy *wiphy, struct net_device *ndev, - struct cfg80211_ap_settings *settings) -{ - int ret = 0; - struct rtw_adapter *adapter = wiphy_to_adapter(wiphy); - - DBG_8723A("%s(%s): hidden_ssid:%d, auth_type:%d\n", - __func__, ndev->name, settings->hidden_ssid, - settings->auth_type); - - ret = rtw_add_beacon(adapter, settings->beacon.head, - settings->beacon.head_len, settings->beacon.tail, - settings->beacon.tail_len); - - adapter->mlmeextpriv.mlmext_info.hidden_ssid_mode = - settings->hidden_ssid; - - if (settings->ssid && settings->ssid_len) { - struct wlan_bssid_ex *pbss_network = - &adapter->mlmepriv.cur_network.network; - struct wlan_bssid_ex *pbss_network_ext = - &adapter->mlmeextpriv.mlmext_info.network; - - memcpy(pbss_network->Ssid.ssid, (void *)settings->ssid, - settings->ssid_len); - pbss_network->Ssid.ssid_len = settings->ssid_len; - memcpy(pbss_network_ext->Ssid.ssid, (void *)settings->ssid, - settings->ssid_len); - pbss_network_ext->Ssid.ssid_len = settings->ssid_len; - } - - return ret; -} - -static int cfg80211_rtw_change_beacon(struct wiphy *wiphy, - struct net_device *ndev, - struct cfg80211_beacon_data *info) -{ - int ret = 0; - struct rtw_adapter *adapter = wiphy_to_adapter(wiphy); - - DBG_8723A("%s(%s)\n", __func__, ndev->name); - - ret = rtw_add_beacon(adapter, info->head, info->head_len, info->tail, - info->tail_len); - - return ret; -} - -static int cfg80211_rtw_stop_ap(struct wiphy *wiphy, struct net_device *ndev) -{ - DBG_8723A("%s(%s)\n", __func__, ndev->name); - return 0; -} - -static int cfg80211_rtw_add_station(struct wiphy *wiphy, - struct net_device *ndev, const u8 *mac, - struct station_parameters *params) -{ - DBG_8723A("%s(%s)\n", __func__, ndev->name); - - return 0; -} - -static int cfg80211_rtw_del_station(struct wiphy *wiphy, - struct net_device *ndev, - struct station_del_parameters *params) -{ - const u8 *mac = params->mac; - int ret = 0; - struct list_head *phead; - u8 updated = 0; - struct sta_info *psta, *ptmp; - struct rtw_adapter *padapter = netdev_priv(ndev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct sta_priv *pstapriv = &padapter->stapriv; - - DBG_8723A("+%s(%s)\n", __func__, ndev->name); - - if (check_fwstate(pmlmepriv, (_FW_LINKED | WIFI_AP_STATE)) != true) { - DBG_8723A("%s, fw_state != FW_LINKED|WIFI_AP_STATE\n", - __func__); - return -EINVAL; - } - - if (!mac) { - DBG_8723A("flush all sta, and cam_entry\n"); - - flush_all_cam_entry23a(padapter); /* clear CAM */ - - ret = rtw_sta_flush23a(padapter); - - return ret; - } - - DBG_8723A("free sta macaddr=%pM\n", mac); - - if (is_broadcast_ether_addr(mac)) - return -EINVAL; - - spin_lock_bh(&pstapriv->asoc_list_lock); - phead = &pstapriv->asoc_list; - /* check asoc_queue */ - list_for_each_entry_safe(psta, ptmp, phead, asoc_list) { - if (ether_addr_equal(mac, psta->hwaddr)) { - if (psta->dot8021xalg == 1 && - psta->bpairwise_key_installed == false) { - DBG_8723A("%s, sta's dot8021xalg = 1 and " - "key_installed = false\n", __func__); - } else { - DBG_8723A("free psta =%p, aid =%d\n", psta, - psta->aid); - - list_del_init(&psta->asoc_list); - pstapriv->asoc_list_cnt--; - - /* spin_unlock_bh(&pstapriv->asoc_list_lock); */ - updated = - ap_free_sta23a(padapter, psta, true, - WLAN_REASON_DEAUTH_LEAVING); - /* spin_lock_bh(&pstapriv->asoc_list_lock); */ - - psta = NULL; - - break; - } - } - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - associated_clients_update23a(padapter, updated); - - DBG_8723A("-%s(%s)\n", __func__, ndev->name); - - return ret; -} - -static int cfg80211_rtw_change_station(struct wiphy *wiphy, - struct net_device *ndev, const u8 *mac, - struct station_parameters *params) -{ - DBG_8723A("%s(%s)\n", __func__, ndev->name); - return 0; -} - -static int cfg80211_rtw_dump_station(struct wiphy *wiphy, - struct net_device *ndev, int idx, u8 *mac, - struct station_info *sinfo) -{ - DBG_8723A("%s(%s)\n", __func__, ndev->name); - - /* TODO: dump scanned queue */ - - return -ENOENT; -} - -static int cfg80211_rtw_change_bss(struct wiphy *wiphy, struct net_device *ndev, - struct bss_parameters *params) -{ - DBG_8723A("%s(%s)\n", __func__, ndev->name); - return 0; -} -#endif /* CONFIG_8723AU_AP_MODE */ - -static int _cfg80211_rtw_mgmt_tx(struct rtw_adapter *padapter, u8 tx_ch, - const u8 *buf, size_t len) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - int ret = _FAIL; - struct ieee80211_hdr *pwlanhdr; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (_FAIL == rtw_pwr_wakeup(padapter)) { - ret = -EFAULT; - goto exit; - } - - rtw_set_scan_deny(padapter, 1000); - - rtw_scan_abort23a(padapter); - - if (tx_ch != rtw_get_oper_ch23a(padapter)) { - if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) - pmlmeext->cur_channel = tx_ch; - set_channel_bwmode23a(padapter, tx_ch, - HAL_PRIME_CHNL_OFFSET_DONT_CARE, - HT_CHANNEL_WIDTH_20); - } - - /* starting alloc mgmt frame to dump it */ - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) { - /* ret = -ENOMEM; */ - ret = _FAIL; - goto exit; - } - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - pattrib->retry_ctrl = false; - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *) (pmgntframe->buf_addr) + TXDESC_OFFSET; - - memcpy(pframe, (void *)buf, len); - pattrib->pktlen = len; - - pwlanhdr = (struct ieee80211_hdr *)pframe; - /* update seq number */ - pmlmeext->mgnt_seq = le16_to_cpu(pwlanhdr->seq_ctrl) >> 4; - pattrib->seqnum = pmlmeext->mgnt_seq; - pmlmeext->mgnt_seq++; - - pattrib->last_txcmdsz = pattrib->pktlen; - - ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe); - - if (ret != _SUCCESS) - DBG_8723A("%s, ack == false\n", __func__); - else - DBG_8723A("%s, ack == true\n", __func__); - -exit: - - DBG_8723A("%s, ret =%d\n", __func__, ret); - - return ret; -} - -static int cfg80211_rtw_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, - struct cfg80211_mgmt_tx_params *params, - u64 *cookie) -{ - struct rtw_adapter *padapter = - (struct rtw_adapter *)wiphy_to_adapter(wiphy); - int ret = 0; - int tx_ret; - u32 dump_limit = RTW_MAX_MGMT_TX_CNT; - u32 dump_cnt = 0; - bool ack = true; - u8 category, action; - unsigned long start = jiffies; - size_t len = params->len; - struct ieee80211_channel *chan = params->chan; - const u8 *buf = params->buf; - struct ieee80211_mgmt *hdr = (struct ieee80211_mgmt *)buf; - u8 tx_ch = (u8) ieee80211_frequency_to_channel(chan->center_freq); - - if (!ieee80211_is_action(hdr->frame_control)) - return -EINVAL; - - /* cookie generation */ - *cookie = (unsigned long)buf; - - DBG_8723A("%s(%s): len =%zu, ch =%d\n", __func__, - padapter->pnetdev->name, len, tx_ch); - - /* indicate ack before issue frame to avoid racing with rsp frame */ - cfg80211_mgmt_tx_status(padapter->rtw_wdev, *cookie, buf, len, ack, - GFP_KERNEL); - - DBG_8723A("RTW_Tx:tx_ch =%d, da =%pM\n", tx_ch, hdr->da); - category = hdr->u.action.category; - action = hdr->u.action.u.wme_action.action_code; - DBG_8723A("RTW_Tx:category(%u), action(%u)\n", category, action); - - do { - dump_cnt++; - tx_ret = _cfg80211_rtw_mgmt_tx(padapter, tx_ch, buf, len); - } while (dump_cnt < dump_limit && tx_ret != _SUCCESS); - - if (tx_ret != _SUCCESS || dump_cnt > 1) { - DBG_8723A("%s(%s): %s (%d/%d) in %d ms\n", - __func__, padapter->pnetdev->name, - tx_ret == _SUCCESS ? "OK" : "FAIL", dump_cnt, - dump_limit, jiffies_to_msecs(jiffies - start)); - } - - return ret; -} - -static void cfg80211_rtw_mgmt_frame_register(struct wiphy *wiphy, - struct wireless_dev *wdev, - u16 frame_type, bool reg) -{ - if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ)) - return; - - return; -} - -static struct cfg80211_ops rtw_cfg80211_ops = { - .change_virtual_intf = cfg80211_rtw_change_iface, - .add_key = cfg80211_rtw_add_key, - .get_key = cfg80211_rtw_get_key, - .del_key = cfg80211_rtw_del_key, - .set_default_key = cfg80211_rtw_set_default_key, - .get_station = cfg80211_rtw_get_station, - .scan = cfg80211_rtw_scan, - .set_wiphy_params = cfg80211_rtw_set_wiphy_params, - .connect = cfg80211_rtw_connect, - .disconnect = cfg80211_rtw_disconnect, - .join_ibss = cfg80211_rtw_join_ibss, - .leave_ibss = cfg80211_rtw_leave_ibss, - .set_tx_power = cfg80211_rtw_set_txpower, - .get_tx_power = cfg80211_rtw_get_txpower, - .set_power_mgmt = cfg80211_rtw_set_power_mgmt, - .set_pmksa = cfg80211_rtw_set_pmksa, - .del_pmksa = cfg80211_rtw_del_pmksa, - .flush_pmksa = cfg80211_rtw_flush_pmksa, - -#ifdef CONFIG_8723AU_AP_MODE - .add_virtual_intf = cfg80211_rtw_add_virtual_intf, - .del_virtual_intf = cfg80211_rtw_del_virtual_intf, - - .start_ap = cfg80211_rtw_start_ap, - .change_beacon = cfg80211_rtw_change_beacon, - .stop_ap = cfg80211_rtw_stop_ap, - - .add_station = cfg80211_rtw_add_station, - .del_station = cfg80211_rtw_del_station, - .change_station = cfg80211_rtw_change_station, - .dump_station = cfg80211_rtw_dump_station, - .change_bss = cfg80211_rtw_change_bss, -#endif /* CONFIG_8723AU_AP_MODE */ - - .mgmt_tx = cfg80211_rtw_mgmt_tx, - .mgmt_frame_register = cfg80211_rtw_mgmt_frame_register, -}; - -static void rtw_cfg80211_init_ht_capab(struct ieee80211_sta_ht_cap *ht_cap, - enum nl80211_band band, u8 rf_type) -{ - -#define MAX_BIT_RATE_40MHZ_MCS15 300 /* Mbps */ -#define MAX_BIT_RATE_40MHZ_MCS7 150 /* Mbps */ - - ht_cap->ht_supported = true; - - ht_cap->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | - IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20 | - IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU; - - /* - *Maximum length of AMPDU that the STA can receive. - *Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets) - */ - ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; - - /*Minimum MPDU start spacing , */ - ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; - - ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; - - /* - *hw->wiphy->bands[NL80211_BAND_2GHZ] - *base on ant_num - *rx_mask: RX mask - *if rx_ant = 1 rx_mask[0]= 0xff;==>MCS0-MCS7 - *if rx_ant = 2 rx_mask[1]= 0xff;==>MCS8-MCS15 - *if rx_ant >= 3 rx_mask[2]= 0xff; - *if BW_40 rx_mask[4]= 0x01; - *highest supported RX rate - */ - if (rf_type == RF_1T1R) { - ht_cap->mcs.rx_mask[0] = 0xFF; - ht_cap->mcs.rx_mask[1] = 0x00; - ht_cap->mcs.rx_mask[4] = 0x01; - - ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS7); - } else if ((rf_type == RF_1T2R) || (rf_type == RF_2T2R)) { - ht_cap->mcs.rx_mask[0] = 0xFF; - ht_cap->mcs.rx_mask[1] = 0xFF; - ht_cap->mcs.rx_mask[4] = 0x01; - - ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15); - } else { - DBG_8723A("%s, error rf_type =%d\n", __func__, rf_type); - } - -} - -void rtw_cfg80211_init_wiphy(struct rtw_adapter *padapter) -{ - u8 rf_type; - struct ieee80211_supported_band *bands; - struct wireless_dev *pwdev = padapter->rtw_wdev; - struct wiphy *wiphy = pwdev->wiphy; - - rf_type = rtl8723a_get_rf_type(padapter); - - DBG_8723A("%s:rf_type =%d\n", __func__, rf_type); - - /* if (padapter->registrypriv.wireless_mode & WIRELESS_11G) */ - { - bands = wiphy->bands[NL80211_BAND_2GHZ]; - if (bands) - rtw_cfg80211_init_ht_capab(&bands->ht_cap, - NL80211_BAND_2GHZ, - rf_type); - } - - /* if (padapter->registrypriv.wireless_mode & WIRELESS_11A) */ - { - bands = wiphy->bands[NL80211_BAND_5GHZ]; - if (bands) - rtw_cfg80211_init_ht_capab(&bands->ht_cap, - NL80211_BAND_5GHZ, - rf_type); - } -} - -static void rtw_cfg80211_preinit_wiphy(struct rtw_adapter *padapter, - struct wiphy *wiphy) -{ - wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; - - wiphy->max_scan_ssids = RTW_SSID_SCAN_AMOUNT; - wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; - wiphy->max_num_pmkids = RTW_MAX_NUM_PMKIDS; - - wiphy->max_remain_on_channel_duration = - RTW_MAX_REMAIN_ON_CHANNEL_DURATION; - - wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC) | -#ifdef CONFIG_8723AU_AP_MODE - BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR) | -#endif - 0; - -#ifdef CONFIG_8723AU_AP_MODE - wiphy->mgmt_stypes = rtw_cfg80211_default_mgmt_stypes; -#endif /* CONFIG_8723AU_AP_MODE */ - - wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR); - - /* - wiphy->iface_combinations = &rtw_combinations; - wiphy->n_iface_combinations = 1; - */ - - wiphy->cipher_suites = rtw_cipher_suites; - wiphy->n_cipher_suites = ARRAY_SIZE(rtw_cipher_suites); - - /* if (padapter->registrypriv.wireless_mode & WIRELESS_11G) */ - wiphy->bands[NL80211_BAND_2GHZ] = - rtw_spt_band_alloc(NL80211_BAND_2GHZ); - /* if (padapter->registrypriv.wireless_mode & WIRELESS_11A) */ - wiphy->bands[NL80211_BAND_5GHZ] = - rtw_spt_band_alloc(NL80211_BAND_5GHZ); - - wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; - wiphy->flags |= WIPHY_FLAG_OFFCHAN_TX | WIPHY_FLAG_HAVE_AP_SME; - - if (padapter->registrypriv.power_mgnt != PS_MODE_ACTIVE) - wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; - else - wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; -} - -int rtw_wdev_alloc(struct rtw_adapter *padapter, struct device *dev) -{ - int ret = 0; - struct wiphy *wiphy; - struct wireless_dev *wdev; - struct rtw_wdev_priv *pwdev_priv; - struct net_device *pnetdev = padapter->pnetdev; - - DBG_8723A("%s(padapter =%p)\n", __func__, padapter); - - /* wiphy */ - wiphy = wiphy_new(&rtw_cfg80211_ops, sizeof(struct rtw_wdev_priv)); - if (!wiphy) { - DBG_8723A("Couldn't allocate wiphy device\n"); - ret = -ENOMEM; - goto exit; - } - - /* wdev */ - wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); - if (!wdev) { - ret = -ENOMEM; - goto free_wiphy; - } - - set_wiphy_dev(wiphy, dev); - rtw_cfg80211_preinit_wiphy(padapter, wiphy); - - ret = wiphy_register(wiphy); - if (ret < 0) { - DBG_8723A("Couldn't register wiphy device\n"); - goto free_wdev; - } - - wdev->wiphy = wiphy; - wdev->netdev = pnetdev; - /* wdev->iftype = NL80211_IFTYPE_STATION; */ - /* for rtw_setopmode_cmd23a() in cfg80211_rtw_change_iface() */ - wdev->iftype = NL80211_IFTYPE_MONITOR; - padapter->rtw_wdev = wdev; - pnetdev->ieee80211_ptr = wdev; - - /* init pwdev_priv */ - pwdev_priv = wdev_to_priv(wdev); - pwdev_priv->rtw_wdev = wdev; - pwdev_priv->pmon_ndev = NULL; - pwdev_priv->ifname_mon[0] = '\0'; - pwdev_priv->padapter = padapter; - pwdev_priv->scan_request = NULL; - spin_lock_init(&pwdev_priv->scan_req_lock); - - pwdev_priv->p2p_enabled = false; - - if (padapter->registrypriv.power_mgnt != PS_MODE_ACTIVE) - pwdev_priv->power_mgmt = true; - else - pwdev_priv->power_mgmt = false; - - return ret; -free_wdev: - kfree(wdev); -free_wiphy: - wiphy_free(wiphy); -exit: - return ret; -} - -void rtw_wdev_free(struct wireless_dev *wdev) -{ - DBG_8723A("%s(wdev =%p)\n", __func__, wdev); - - if (!wdev) - return; - - kfree(wdev->wiphy->bands[NL80211_BAND_2GHZ]); - kfree(wdev->wiphy->bands[NL80211_BAND_5GHZ]); - - wiphy_free(wdev->wiphy); - - kfree(wdev); -} - -void rtw_wdev_unregister(struct wireless_dev *wdev) -{ - struct rtw_wdev_priv *pwdev_priv; - - DBG_8723A("%s(wdev =%p)\n", __func__, wdev); - - if (!wdev) - return; - - pwdev_priv = wdev_to_priv(wdev); - - rtw_cfg80211_indicate_scan_done(pwdev_priv, true); - - if (pwdev_priv->pmon_ndev) { - DBG_8723A("%s, unregister monitor interface\n", __func__); - unregister_netdev(pwdev_priv->pmon_ndev); - } - - wiphy_unregister(wdev->wiphy); -} diff --git a/drivers/staging/rtl8723au/os_dep/mlme_linux.c b/drivers/staging/rtl8723au/os_dep/mlme_linux.c deleted file mode 100644 index ca24369..0000000 --- a/drivers/staging/rtl8723au/os_dep/mlme_linux.c +++ /dev/null @@ -1,81 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ - -#define _MLME_OSDEP_C_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <mlme_osdep.h> - -static struct rt_pmkid_list backupPMKIDList[NUM_PMKID_CACHE]; - -void rtw_reset_securitypriv23a(struct rtw_adapter *adapter) -{ - u8 backupPMKIDIndex = 0; - u8 backupTKIPCountermeasure = 0x00; - unsigned long backupTKIPcountermeasure_time = 0; - - if (adapter->securitypriv.dot11AuthAlgrthm == - dot11AuthAlgrthm_8021X) { /* 802.1x */ - /* We have to backup the PMK information for WiFi PMK - * Caching test item. - * Backup the btkip_countermeasure information. - * When the countermeasure is trigger, the driver have to - * disconnect with AP for 60 seconds. - */ - memcpy(&backupPMKIDList[0], &adapter->securitypriv.PMKIDList[0], - sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE); - backupPMKIDIndex = adapter->securitypriv.PMKIDIndex; - backupTKIPCountermeasure = adapter->securitypriv.btkip_countermeasure; - backupTKIPcountermeasure_time = adapter->securitypriv.btkip_countermeasure_time; - - memset((unsigned char *)&adapter->securitypriv, 0, - sizeof (struct security_priv)); - /* Restore the PMK information to securitypriv structure - * for the following connection. - */ - memcpy(&adapter->securitypriv.PMKIDList[0], &backupPMKIDList[0], - sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE); - adapter->securitypriv.PMKIDIndex = backupPMKIDIndex; - adapter->securitypriv.btkip_countermeasure = backupTKIPCountermeasure; - adapter->securitypriv.btkip_countermeasure_time = backupTKIPcountermeasure_time; - - adapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen; - adapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled; - } else { /* reset values in securitypriv */ - struct security_priv *psec_priv = &adapter->securitypriv; - - /* open system */ - psec_priv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; - psec_priv->dot11PrivacyAlgrthm = 0; - psec_priv->dot11PrivacyKeyIndex = 0; - - psec_priv->dot118021XGrpPrivacy = 0; - psec_priv->dot118021XGrpKeyid = 1; - - psec_priv->ndisauthtype = Ndis802_11AuthModeOpen; - psec_priv->ndisencryptstatus = Ndis802_11WEPDisabled; - } -} - -void rtw_os_indicate_disconnect23a(struct rtw_adapter *adapter) -{ - /* Do it first for tx broadcast pkt after disconnection issue! */ - netif_carrier_off(adapter->pnetdev); - - rtw_cfg80211_indicate_disconnect(adapter); - - rtw_reset_securitypriv23a(adapter); -} diff --git a/drivers/staging/rtl8723au/os_dep/os_intfs.c b/drivers/staging/rtl8723au/os_dep/os_intfs.c deleted file mode 100644 index b8848c2..0000000 --- a/drivers/staging/rtl8723au/os_dep/os_intfs.c +++ /dev/null @@ -1,852 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _OS_INTFS_C_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <xmit_osdep.h> -#include <recv_osdep.h> -#include <hal_intf.h> -#include <rtw_version.h> - -#include <rtl8723a_hal.h> - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Realtek Wireless Lan Driver"); -MODULE_AUTHOR("Realtek Semiconductor Corp."); -MODULE_AUTHOR("Larry Finger <Larry.Finger@lwfinger.net>"); -MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@redhat.com>"); -MODULE_VERSION(DRIVERVERSION); -MODULE_FIRMWARE("rtlwifi/rtl8723aufw_A.bin"); -MODULE_FIRMWARE("rtlwifi/rtl8723aufw_B.bin"); -MODULE_FIRMWARE("rtlwifi/rtl8723aufw_B_NoBT.bin"); - -/* module param defaults */ -static int rtw_chip_version; -static int rtw_rfintfs = HWPI; -static int rtw_debug = 1; - -static int rtw_channel = 1;/* ad-hoc support requirement */ -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;/* */ -static int rtw_frag_thresh = 2346;/* */ -static int rtw_preamble = PREAMBLE_LONG;/* long, short, auto */ -static int rtw_scan_mode = 1;/* active, passive */ -static int rtw_adhoc_tx_pwr = 1; -static int rtw_soft_ap; -static int rtw_power_mgnt = 1; -static int rtw_ips_mode = IPS_NORMAL; - -static int rtw_smart_ps = 2; - -module_param(rtw_ips_mode, int, 0644); -MODULE_PARM_DESC(rtw_ips_mode, "The default IPS mode"); - -static int rtw_long_retry_lmt = 7; -static int rtw_short_retry_lmt = 7; -static int rtw_busy_thresh = 40; -static int rtw_ack_policy = NORMAL_ACK; - -static int rtw_acm_method;/* 0:By SW 1:By HW. */ - -static int rtw_wmm_enable = 1;/* default is set to enable the wmm. */ -static int rtw_uapsd_enable; - -static int rtw_ht_enable = 1; -/* 0 :diable, bit(0): enable 2.4g, bit(1): enable 5g */ -static int rtw_cbw40_enable = 3; -static int rtw_ampdu_enable = 1;/* for enable tx_ampdu */ -/* 0: disable, bit(0):enable 2.4g, bit(1):enable 5g, default is set to enable - * 2.4GHZ for IOT issue with bufflao's AP at 5GHZ - */ -static int rtw_rx_stbc = 1; -static int rtw_ampdu_amsdu;/* 0: disabled, 1:enabled, 2:auto */ - -/* Use 2 path Tx to transmit MCS0~7 and legacy mode */ -static int rtw_lowrate_two_xmit = 1; - -/* int rf_config = RF_1T2R; 1T2R */ -static int rtw_rf_config = RF_819X_MAX_TYPE; /* auto */ -static int rtw_low_power; -static int rtw_wifi_spec; -static int rtw_channel_plan = RT_CHANNEL_DOMAIN_MAX; - -#ifdef CONFIG_8723AU_BT_COEXIST -static int rtw_btcoex_enable = 1; -static int rtw_bt_iso = 2;/* 0:Low, 1:High, 2:From Efuse */ -/* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter, 4.Busy, 5.OtherBusy */ -static int rtw_bt_sco = 3; -/* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */ -static int rtw_bt_ampdu = 1; -#endif - -/* 0:Reject AP's Add BA req, 1:Accept AP's Add BA req. */ -static int rtw_AcceptAddbaReq = true; - -static int rtw_antdiv_cfg = 2; /* 0:OFF , 1:ON, 2:decide by Efuse config */ -static int rtw_antdiv_type; /* 0:decide by efuse */ - -static int rtw_enusbss;/* 0:disable, 1:enable */ - -static int rtw_hwpdn_mode = 2;/* 0:disable, 1:enable, 2: by EFUSE config */ - -static int rtw_hwpwrp_detect; /* HW power ping detect 0:disable , 1:enable */ - -static int rtw_hw_wps_pbc = 1; - -static int rtw_80211d; - -static int rtw_regulatory_id = 0xff;/* Regulatory tab id, 0xff = follow efuse's setting */ - -module_param(rtw_regulatory_id, int, 0644); - -static char *ifname = "wlan%d"; -module_param(ifname, charp, 0644); -MODULE_PARM_DESC(ifname, "The default name to allocate for first interface"); - -static char *if2name = "wlan%d"; -module_param(if2name, charp, 0644); -MODULE_PARM_DESC(if2name, "The default name to allocate for second interface"); - -module_param(rtw_channel_plan, int, 0644); -module_param(rtw_chip_version, int, 0644); -module_param(rtw_rfintfs, int, 0644); -module_param(rtw_channel, int, 0644); -module_param(rtw_wmm_enable, int, 0644); -module_param(rtw_vrtl_carrier_sense, int, 0644); -module_param(rtw_vcs_type, int, 0644); -module_param(rtw_busy_thresh, int, 0644); -module_param(rtw_ht_enable, int, 0644); -module_param(rtw_cbw40_enable, int, 0644); -module_param(rtw_ampdu_enable, int, 0644); -module_param(rtw_rx_stbc, int, 0644); -module_param(rtw_ampdu_amsdu, int, 0644); - -module_param(rtw_lowrate_two_xmit, int, 0644); - -module_param(rtw_rf_config, int, 0644); -module_param(rtw_power_mgnt, int, 0644); -module_param(rtw_smart_ps, int, 0644); -module_param(rtw_low_power, int, 0644); -module_param(rtw_wifi_spec, int, 0644); - -module_param(rtw_antdiv_cfg, int, 0644); - -module_param(rtw_enusbss, int, 0644); -module_param(rtw_hwpdn_mode, int, 0644); -module_param(rtw_hwpwrp_detect, int, 0644); - -module_param(rtw_hw_wps_pbc, int, 0644); - -static uint rtw_max_roaming_times = 2; -module_param(rtw_max_roaming_times, uint, 0644); -MODULE_PARM_DESC(rtw_max_roaming_times, "The max roaming times to try"); - -module_param(rtw_80211d, int, 0644); -MODULE_PARM_DESC(rtw_80211d, "Enable 802.11d mechanism"); - -#ifdef CONFIG_8723AU_BT_COEXIST -module_param(rtw_btcoex_enable, int, 0644); -MODULE_PARM_DESC(rtw_btcoex_enable, "Enable BT co-existence mechanism"); -#endif - -static uint rtw_notch_filter; -module_param(rtw_notch_filter, uint, 0644); -MODULE_PARM_DESC(rtw_notch_filter, "0:Disable, 1:Enable, 2:Enable only for P2P"); -module_param_named(debug, rtw_debug, int, 0444); -MODULE_PARM_DESC(debug, "Set debug level (1-9) (default 1)"); - -static int netdev_close(struct net_device *pnetdev); - -static void loadparam(struct rtw_adapter *padapter, struct net_device *pnetdev) -{ - struct registry_priv *registry_par = &padapter->registrypriv; - - GlobalDebugLevel23A = rtw_debug; - registry_par->chip_version = (u8)rtw_chip_version; - registry_par->rfintfs = (u8)rtw_rfintfs; - memcpy(registry_par->ssid.ssid, "ANY", 3); - registry_par->ssid.ssid_len = 3; - registry_par->channel = (u8)rtw_channel; - registry_par->wireless_mode = (u8)rtw_wireless_mode; - registry_par->vrtl_carrier_sense = (u8)rtw_vrtl_carrier_sense; - registry_par->vcs_type = (u8)rtw_vcs_type; - registry_par->rts_thresh = (u16)rtw_rts_thresh; - registry_par->frag_thresh = (u16)rtw_frag_thresh; - registry_par->preamble = (u8)rtw_preamble; - registry_par->scan_mode = (u8)rtw_scan_mode; - registry_par->adhoc_tx_pwr = (u8)rtw_adhoc_tx_pwr; - registry_par->soft_ap = (u8)rtw_soft_ap; - registry_par->smart_ps = (u8)rtw_smart_ps; - registry_par->power_mgnt = (u8)rtw_power_mgnt; - registry_par->ips_mode = (u8)rtw_ips_mode; - registry_par->long_retry_lmt = (u8)rtw_long_retry_lmt; - registry_par->short_retry_lmt = (u8)rtw_short_retry_lmt; - registry_par->busy_thresh = (u16)rtw_busy_thresh; - registry_par->ack_policy = (u8)rtw_ack_policy; - registry_par->acm_method = (u8)rtw_acm_method; - /* UAPSD */ - registry_par->wmm_enable = (u8)rtw_wmm_enable; - registry_par->uapsd_enable = (u8)rtw_uapsd_enable; - registry_par->ht_enable = (u8)rtw_ht_enable; - registry_par->cbw40_enable = (u8)rtw_cbw40_enable; - registry_par->ampdu_enable = (u8)rtw_ampdu_enable; - registry_par->rx_stbc = (u8)rtw_rx_stbc; - registry_par->ampdu_amsdu = (u8)rtw_ampdu_amsdu; - registry_par->lowrate_two_xmit = (u8)rtw_lowrate_two_xmit; - registry_par->rf_config = (u8)rtw_rf_config; - registry_par->low_power = (u8)rtw_low_power; - registry_par->wifi_spec = (u8)rtw_wifi_spec; - registry_par->channel_plan = (u8)rtw_channel_plan; -#ifdef CONFIG_8723AU_BT_COEXIST - registry_par->btcoex = (u8)rtw_btcoex_enable; - registry_par->bt_iso = (u8)rtw_bt_iso; - registry_par->bt_sco = (u8)rtw_bt_sco; - registry_par->bt_ampdu = (u8)rtw_bt_ampdu; -#endif - registry_par->bAcceptAddbaReq = (u8)rtw_AcceptAddbaReq; - registry_par->antdiv_cfg = (u8)rtw_antdiv_cfg; - registry_par->antdiv_type = (u8)rtw_antdiv_type; - - /* 0:disable, 1:enable, 2:by EFUSE config */ - registry_par->hwpdn_mode = (u8)rtw_hwpdn_mode; - /* 0:disable, 1:enable */ - registry_par->hwpwrp_detect = (u8)rtw_hwpwrp_detect; - registry_par->hw_wps_pbc = (u8)rtw_hw_wps_pbc; - registry_par->max_roaming_times = (u8)rtw_max_roaming_times; - registry_par->enable80211d = (u8)rtw_80211d; - snprintf(registry_par->ifname, 16, "%s", ifname); - snprintf(registry_par->if2name, 16, "%s", if2name); - registry_par->notch_filter = (u8)rtw_notch_filter; - registry_par->regulatory_tid = (u8)rtw_regulatory_id; -} - -static int rtw_net_set_mac_address(struct net_device *pnetdev, void *p) -{ - struct rtw_adapter *padapter = netdev_priv(pnetdev); - struct sockaddr *addr = p; - - if (!padapter->bup) - ether_addr_copy(padapter->eeprompriv.mac_addr, addr->sa_data); - return 0; -} - -static struct net_device_stats *rtw_net_get_stats(struct net_device *pnetdev) -{ - struct rtw_adapter *padapter = netdev_priv(pnetdev); - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct recv_priv *precvpriv = &padapter->recvpriv; - - padapter->stats.tx_packets = pxmitpriv->tx_pkts; - padapter->stats.rx_packets = precvpriv->rx_pkts; - padapter->stats.tx_dropped = pxmitpriv->tx_drop; - padapter->stats.rx_dropped = precvpriv->rx_drop; - padapter->stats.tx_bytes = pxmitpriv->tx_bytes; - padapter->stats.rx_bytes = precvpriv->rx_bytes; - - return &padapter->stats; -} - -/* - * AC to queue mapping - * - * AC_VO -> queue 0 - * AC_VI -> queue 1 - * AC_BE -> queue 2 - * AC_BK -> queue 3 - */ -static const u16 rtw_1d_to_queue[8] = { 2, 3, 3, 2, 1, 1, 0, 0 }; - -/* Given a data frame determine the 802.1p/1d tag to use. */ -static u32 rtw_classify8021d(struct sk_buff *skb) -{ - u32 dscp; - - /* skb->priority values from 256->263 are magic values to - * directly indicate a specific 802.1d priority. This is used - * to allow 802.1d priority to be passed directly in from VLAN - * tags, etc. - */ - if (skb->priority >= 256 && skb->priority <= 263) - return skb->priority - 256; - switch (skb->protocol) { - case htons(ETH_P_IP): - dscp = ip_hdr(skb)->tos & 0xfc; - break; - default: - return 0; - } - return dscp >> 5; -} - -static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv, - select_queue_fallback_t fallback) -{ - struct rtw_adapter *padapter = netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - skb->priority = rtw_classify8021d(skb); - - if (pmlmepriv->acm_mask != 0) - skb->priority = qos_acm23a(pmlmepriv->acm_mask, skb->priority); - return rtw_1d_to_queue[skb->priority]; -} - -u16 rtw_recv_select_queue23a(struct sk_buff *skb) -{ - struct iphdr *piphdr; - struct ethhdr *eth = (struct ethhdr *)skb->data; - unsigned int dscp; - u16 eth_type = get_unaligned_be16(ð->h_proto); - u32 priority; - u8 *pdata = skb->data; - - switch (eth_type) { - case ETH_P_IP: - piphdr = (struct iphdr *)(pdata + ETH_HLEN); - dscp = piphdr->tos & 0xfc; - priority = dscp >> 5; - break; - default: - priority = 0; - } - return rtw_1d_to_queue[priority]; -} - -static const struct net_device_ops rtw_netdev_ops = { - .ndo_open = netdev_open23a, - .ndo_stop = netdev_close, - .ndo_start_xmit = rtw_xmit23a_entry23a, - .ndo_select_queue = rtw_select_queue, - .ndo_set_mac_address = rtw_net_set_mac_address, - .ndo_get_stats = rtw_net_get_stats, -}; - -int rtw_init_netdev23a_name23a(struct net_device *pnetdev, const char *ifname) -{ - if (dev_alloc_name(pnetdev, ifname) < 0) { - RT_TRACE(_module_os_intfs_c_, _drv_err_, - "dev_alloc_name, fail!\n"); - } - netif_carrier_off(pnetdev); - return 0; -} - -static const struct device_type wlan_type = { - .name = "wlan", -}; - -struct net_device *rtw_init_netdev23a(struct rtw_adapter *old_padapter) -{ - struct rtw_adapter *padapter; - struct net_device *pnetdev; - - RT_TRACE(_module_os_intfs_c_, _drv_info_, "+init_net_dev\n"); - - pnetdev = alloc_etherdev_mq(sizeof(struct rtw_adapter), 4); - if (!pnetdev) - return NULL; - - pnetdev->dev.type = &wlan_type; - padapter = netdev_priv(pnetdev); - padapter->pnetdev = pnetdev; - - DBG_8723A("register rtw_netdev_ops to netdev_ops\n"); - pnetdev->netdev_ops = &rtw_netdev_ops; - - pnetdev->watchdog_timeo = HZ*3; /* 3 second timeout */ - - loadparam(padapter, pnetdev); - return pnetdev; -} - -static int rtw_init_default_value(struct rtw_adapter *padapter) -{ - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - - /* xmit_priv */ - pxmitpriv->vcs = pregistrypriv->vcs_type; - /* pxmitpriv->rts_thresh = pregistrypriv->rts_thresh; */ - pxmitpriv->frag_len = pregistrypriv->frag_thresh; - - /* mlme_priv */ - pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */ - pmlmepriv->scan_mode = SCAN_ACTIVE; - - /* ht_priv */ - pmlmepriv->htpriv.ampdu_enable = false;/* set to disabled */ - - /* security_priv */ - psecuritypriv->binstallGrpkey = 0; - - /* open system */ - psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; - psecuritypriv->dot11PrivacyAlgrthm = 0; - - psecuritypriv->dot11PrivacyKeyIndex = 0; - - psecuritypriv->dot118021XGrpPrivacy = 0; - psecuritypriv->dot118021XGrpKeyid = 1; - - psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen; - psecuritypriv->ndisencryptstatus = Ndis802_11WEPDisabled; - - /* registry_priv */ - rtw_init_registrypriv_dev_network23a(padapter); - rtw_update_registrypriv_dev_network23a(padapter); - - /* hal_priv */ - rtl8723a_init_default_value(padapter); - - /* misc. */ - padapter->bReadPortCancel = false; - padapter->bWritePortCancel = false; - return _SUCCESS; -} - -int rtw_reset_drv_sw23a(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; - - /* hal_priv */ - rtl8723a_init_default_value(padapter); - padapter->bReadPortCancel = false; - padapter->bWritePortCancel = false; - pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */ - - padapter->xmitpriv.tx_pkts = 0; - padapter->recvpriv.rx_pkts = 0; - - pmlmepriv->LinkDetectInfo.bBusyTraffic = false; - - _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING); - - rtw_sreset_reset_value(padapter); - pwrctrlpriv->pwr_state_check_cnts = 0; - - /* mlmeextpriv */ - padapter->mlmeextpriv.sitesurvey_res.state = SCAN_DISABLE; - - rtw_set_signal_stat_timer(&padapter->recvpriv); - return _SUCCESS; -} - -int rtw_init_drv_sw23a(struct rtw_adapter *padapter) -{ - int ret8 = _SUCCESS; - - RT_TRACE(_module_os_intfs_c_, _drv_info_, "+rtw_init_drv_sw23a\n"); - - if (rtw_init_cmd_priv23a(&padapter->cmdpriv) == _FAIL) { - RT_TRACE(_module_os_intfs_c_, _drv_err_, - "Can't init cmd_priv\n"); - ret8 = _FAIL; - goto exit; - } - - padapter->cmdpriv.padapter = padapter; - - if (rtw_init_evt_priv23a(&padapter->evtpriv) == _FAIL) { - RT_TRACE(_module_os_intfs_c_, _drv_err_, - "Can't init evt_priv\n"); - ret8 = _FAIL; - goto exit; - } - - if (rtw_init_mlme_priv23a(padapter) == _FAIL) { - RT_TRACE(_module_os_intfs_c_, _drv_err_, - "Can't init mlme_priv\n"); - ret8 = _FAIL; - goto exit; - } - - - if (init_mlme_ext_priv23a(padapter) == _FAIL) { - RT_TRACE(_module_os_intfs_c_, _drv_err_, - "Can't init mlme_ext_priv\n"); - ret8 = _FAIL; - goto exit; - } - - if (_rtw_init_xmit_priv23a(&padapter->xmitpriv, padapter) == _FAIL) { - DBG_8723A("Can't _rtw_init_xmit_priv23a\n"); - ret8 = _FAIL; - goto exit; - } - - if (_rtw_init_recv_priv23a(&padapter->recvpriv, padapter) == _FAIL) { - DBG_8723A("Can't _rtw_init_recv_priv23a\n"); - ret8 = _FAIL; - goto exit; - } - - if (_rtw_init_sta_priv23a(&padapter->stapriv) == _FAIL) { - DBG_8723A("Can't _rtw_init_sta_priv23a\n"); - ret8 = _FAIL; - goto exit; - } - - padapter->stapriv.padapter = padapter; - padapter->setband = GHZ24_50; - rtw_init_bcmc_stainfo23a(padapter); - - rtw_init_pwrctrl_priv23a(padapter); - - ret8 = rtw_init_default_value(padapter); - - rtl8723a_init_dm_priv(padapter); - - rtw_sreset_init(padapter); - -exit: - - RT_TRACE(_module_os_intfs_c_, _drv_info_, "-rtw_init_drv_sw23a\n"); - return ret8; -} - -void rtw_cancel_all_timer23a(struct rtw_adapter *padapter) -{ - RT_TRACE(_module_os_intfs_c_, _drv_info_, - "+rtw_cancel_all_timer23a\n"); - - 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__); - - del_timer_sync(&padapter->pwrctrlpriv.pwr_state_check_timer); - - del_timer_sync(&padapter->mlmepriv.set_scan_deny_timer); - rtw_clear_scan_deny(padapter); - RT_TRACE(_module_os_intfs_c_, _drv_info_, - "%s:cancel set_scan_deny_timer!\n", __func__); - - del_timer_sync(&padapter->recvpriv.signal_stat_timer); -} - -int rtw_free_drv_sw23a(struct rtw_adapter *padapter) -{ - RT_TRACE(_module_os_intfs_c_, _drv_info_, "==>rtw_free_drv_sw23a\n"); - - free_mlme_ext_priv23a(&padapter->mlmeextpriv); - - rtw_free_evt_priv23a(&padapter->evtpriv); - - rtw_free_mlme_priv23a(&padapter->mlmepriv); - - _rtw_free_xmit_priv23a(&padapter->xmitpriv); - - /* will free bcmc_stainfo here */ - _rtw_free_sta_priv23a(&padapter->stapriv); - - _rtw_free_recv_priv23a(&padapter->recvpriv); - - rtw_free_pwrctrl_priv(padapter); - - kfree(padapter->HalData); - padapter->HalData = NULL; - - RT_TRACE(_module_os_intfs_c_, _drv_info_, "-rtw_free_drv_sw23a\n"); - return _SUCCESS; -} - -static int _rtw_drv_register_netdev(struct rtw_adapter *padapter, char *name) -{ - struct net_device *pnetdev = padapter->pnetdev; - int ret = _SUCCESS; - - /* alloc netdev name */ - rtw_init_netdev23a_name23a(pnetdev, name); - - ether_addr_copy(pnetdev->dev_addr, padapter->eeprompriv.mac_addr); - - /* Tell the network stack we exist */ - if (register_netdev(pnetdev)) { - DBG_8723A("%s(%s): Failed!\n", __func__, pnetdev->name); - ret = _FAIL; - goto error_register_netdev; - } - DBG_8723A("%s, MAC Address (if%d) = %pM\n", - __func__, padapter->iface_id + 1, pnetdev->dev_addr); - return ret; - -error_register_netdev: - - if (padapter->iface_id > IFACE_ID0) { - rtw_free_drv_sw23a(padapter); - - free_netdev(pnetdev); - } - return ret; -} - -int rtw_drv_register_netdev(struct rtw_adapter *if1) -{ - struct dvobj_priv *dvobj = if1->dvobj; - int i, status = _SUCCESS; - - if (dvobj->iface_nums >= IFACE_ID_MAX) { - status = _FAIL; /* -EINVAL */ - goto exit; - } - - for (i = 0; i < dvobj->iface_nums; i++) { - struct rtw_adapter *padapter = dvobj->padapters[i]; - - if (padapter) { - char *name; - - if (padapter->iface_id == IFACE_ID0) - name = if1->registrypriv.ifname; - else if (padapter->iface_id == IFACE_ID1) - name = if1->registrypriv.if2name; - else - name = "wlan%d"; - status = _rtw_drv_register_netdev(padapter, name); - if (status != _SUCCESS) - break; - } - } - -exit: - return status; -} - -int netdev_open23a(struct net_device *pnetdev) -{ - struct rtw_adapter *padapter = netdev_priv(pnetdev); - struct pwrctrl_priv *pwrctrlpriv; - int ret = 0; - int status; - - RT_TRACE(_module_os_intfs_c_, _drv_info_, "+871x_drv - dev_open\n"); - DBG_8723A("+871x_drv - drv_open, bup =%d\n", padapter->bup); - - mutex_lock(&adapter_to_dvobj(padapter)->hw_init_mutex); - - pwrctrlpriv = &padapter->pwrctrlpriv; - - if (!padapter->bup) { - padapter->bDriverStopped = false; - padapter->bSurpriseRemoved = false; - padapter->bCardDisableWOHSM = false; - - status = rtl8723au_hal_init(padapter); - if (status == _FAIL) { - RT_TRACE(_module_os_intfs_c_, _drv_err_, - "rtl871x_hal_init(): Can't init h/w!\n"); - goto netdev_open23a_error; - } - - DBG_8723A("MAC Address = %pM\n", pnetdev->dev_addr); - - if (init_hw_mlme_ext23a(padapter) == _FAIL) { - DBG_8723A("can't init mlme_ext_priv\n"); - goto netdev_open23a_error; - } - - rtl8723au_inirp_init(padapter); - - rtw_cfg80211_init_wiphy(padapter); - - padapter->bup = true; - } - padapter->net_closed = false; - - mod_timer(&padapter->mlmepriv.dynamic_chk_timer, - jiffies + msecs_to_jiffies(2000)); - - padapter->pwrctrlpriv.bips_processing = false; - rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv); - - /* netif_carrier_on(pnetdev);call this func when - rtw23a_joinbss_event_cb return success */ - if (!rtw_netif_queue_stopped(pnetdev)) - netif_tx_start_all_queues(pnetdev); - else - netif_tx_wake_all_queues(pnetdev); - - RT_TRACE(_module_os_intfs_c_, _drv_info_, "-871x_drv - dev_open\n"); - DBG_8723A("-871x_drv - drv_open, bup =%d\n", padapter->bup); -exit: - mutex_unlock(&adapter_to_dvobj(padapter)->hw_init_mutex); - return ret; - -netdev_open23a_error: - padapter->bup = false; - - netif_carrier_off(pnetdev); - netif_tx_stop_all_queues(pnetdev); - - RT_TRACE(_module_os_intfs_c_, _drv_err_, - "-871x_drv - dev_open, fail!\n"); - DBG_8723A("-871x_drv - drv_open fail, bup =%d\n", padapter->bup); - - ret = -1; - goto exit; -} - -static int ips_netdrv_open(struct rtw_adapter *padapter) -{ - int status = _SUCCESS; - - padapter->net_closed = false; - DBG_8723A("===> %s.........\n", __func__); - - padapter->bDriverStopped = false; - padapter->bSurpriseRemoved = false; - padapter->bCardDisableWOHSM = false; - - status = rtl8723au_hal_init(padapter); - if (status == _FAIL) { - RT_TRACE(_module_os_intfs_c_, _drv_err_, - "ips_netdrv_open(): Can't init h/w!\n"); - goto netdev_open23a_error; - } - - rtl8723au_inirp_init(padapter); - - rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv); - mod_timer(&padapter->mlmepriv.dynamic_chk_timer, - jiffies + msecs_to_jiffies(5000)); - - return _SUCCESS; - -netdev_open23a_error: - /* padapter->bup = false; */ - DBG_8723A("-ips_netdrv_open - drv_open failure, bup =%d\n", - padapter->bup); - - return _FAIL; -} - -int rtw_ips_pwr_up23a(struct rtw_adapter *padapter) -{ - int result; - unsigned long start_time = jiffies; - - DBG_8723A("===> rtw_ips_pwr_up23a..............\n"); - rtw_reset_drv_sw23a(padapter); - - result = ips_netdrv_open(padapter); - - DBG_8723A("<=== rtw_ips_pwr_up23a.............. in %dms\n", - jiffies_to_msecs(jiffies - start_time)); - return result; -} - -void rtw_ips_pwr_down23a(struct rtw_adapter *padapter) -{ - unsigned long start_time = jiffies; - - DBG_8723A("===> rtw_ips_pwr_down23a...................\n"); - - padapter->bCardDisableWOHSM = true; - padapter->net_closed = true; - - rtw_ips_dev_unload23a(padapter); - padapter->bCardDisableWOHSM = false; - DBG_8723A("<=== rtw_ips_pwr_down23a..................... in %dms\n", - jiffies_to_msecs(jiffies - start_time)); -} - -void rtw_ips_dev_unload23a(struct rtw_adapter *padapter) -{ - rtl8723a_fifo_cleanup(padapter); - - rtl8723a_usb_intf_stop(padapter); - - /* s5. */ - if (!padapter->bSurpriseRemoved) - rtl8723au_hal_deinit(padapter); -} - -int pm_netdev_open23a(struct net_device *pnetdev, u8 bnormal) -{ - int status; - - if (bnormal) - status = netdev_open23a(pnetdev); - else - status = (_SUCCESS == ips_netdrv_open(netdev_priv(pnetdev))) ? - (0) : (-1); - - return status; -} - -static int netdev_close(struct net_device *pnetdev) -{ - struct rtw_adapter *padapter = netdev_priv(pnetdev); - - RT_TRACE(_module_os_intfs_c_, _drv_info_, "+871x_drv - drv_close\n"); - - padapter->net_closed = true; - - if (padapter->pwrctrlpriv.rf_pwrstate == rf_on) { - DBG_8723A("(2)871x_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)) - netif_tx_stop_all_queues(pnetdev); - } - - /* s2. */ - LeaveAllPowerSaveMode23a(padapter); - rtw_disassoc_cmd23a(padapter, 500, false); - /* s2-2. indicate disconnect to os */ - rtw_indicate_disconnect23a(padapter); - /* s2-3. */ - rtw_free_assoc_resources23a(padapter, 1); - /* s2-4. */ - rtw_free_network_queue23a(padapter); - } - - rtw_scan_abort23a(padapter); - - RT_TRACE(_module_os_intfs_c_, _drv_info_, "-871x_drv - drv_close\n"); - DBG_8723A("-871x_drv - drv_close, bup =%d\n", padapter->bup); - - return 0; -} - -void rtw_ndev_destructor(struct net_device *ndev) -{ - DBG_8723A("%s(%s)\n", __func__, ndev->name); - kfree(ndev->ieee80211_ptr); - free_netdev(ndev); -} - -void _rtw_init_queue23a(struct rtw_queue *pqueue) -{ - INIT_LIST_HEAD(&pqueue->queue); - spin_lock_init(&pqueue->lock); -} diff --git a/drivers/staging/rtl8723au/os_dep/recv_linux.c b/drivers/staging/rtl8723au/os_dep/recv_linux.c deleted file mode 100644 index 084b506..0000000 --- a/drivers/staging/rtl8723au/os_dep/recv_linux.c +++ /dev/null @@ -1,165 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RECV_OSDEP_C_ - -#include <osdep_service.h> -#include <drv_types.h> - -#include <wifi.h> -#include <recv_osdep.h> - -#include <osdep_intf.h> - -#include <usb_ops.h> - -void rtw_handle_tkip_mic_err23a(struct rtw_adapter *padapter, u8 bgroup) -{ - enum nl80211_key_type key_type = 0; - union iwreq_data wrqu; - struct iw_michaelmicfailure ev; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - unsigned long cur_time; - - if (psecuritypriv->last_mic_err_time == 0) { - psecuritypriv->last_mic_err_time = jiffies; - } else { - cur_time = jiffies; - - if (cur_time - psecuritypriv->last_mic_err_time < 60*HZ) { - psecuritypriv->btkip_countermeasure = true; - psecuritypriv->last_mic_err_time = 0; - psecuritypriv->btkip_countermeasure_time = cur_time; - } else { - psecuritypriv->last_mic_err_time = jiffies; - } - } - - if (bgroup) - key_type |= NL80211_KEYTYPE_GROUP; - else - key_type |= NL80211_KEYTYPE_PAIRWISE; - - cfg80211_michael_mic_failure(padapter->pnetdev, - (u8 *)&pmlmepriv->assoc_bssid[0], - key_type, -1, NULL, GFP_ATOMIC); - - memset(&ev, 0x00, sizeof(ev)); - if (bgroup) - ev.flags |= IW_MICFAILURE_GROUP; - else - ev.flags |= IW_MICFAILURE_PAIRWISE; - - ev.src_addr.sa_family = ARPHRD_ETHER; - ether_addr_copy(ev.src_addr.sa_data, &pmlmepriv->assoc_bssid[0]); - - memset(&wrqu, 0x00, sizeof(wrqu)); - wrqu.data.length = sizeof(ev); -} - -int rtw_recv_indicatepkt23a(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ - struct recv_priv *precvpriv; - struct sk_buff *skb; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - precvpriv = &padapter->recvpriv; - - skb = precv_frame->pkt; - if (!skb) { - RT_TRACE(_module_recv_osdep_c_, _drv_err_, - "rtw_recv_indicatepkt23a():skb == NULL!!!!\n"); - goto _recv_indicatepkt_drop; - } - - RT_TRACE(_module_recv_osdep_c_, _drv_info_, - "rtw_recv_indicatepkt23a():skb != NULL !!!\n"); - RT_TRACE(_module_recv_osdep_c_, _drv_info_, - "rtw_recv_indicatepkt23a():precv_frame->hdr.rx_data =%p\n", - precv_frame->pkt->data); - RT_TRACE(_module_recv_osdep_c_, _drv_info_, - "skb->head =%p skb->data =%p skb->tail =%p skb->end =%p skb->len =%d\n", - skb->head, skb->data, - skb_tail_pointer(skb), skb_end_pointer(skb), skb->len); - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) { - struct sk_buff *pskb2 = NULL; - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct rx_pkt_attrib *pattrib = &precv_frame->attrib; - int bmcast = is_multicast_ether_addr(pattrib->dst); - - /* DBG_8723A("bmcast =%d\n", bmcast); */ - - if (!ether_addr_equal(pattrib->dst, - myid(&padapter->eeprompriv))) { - /* DBG_8723A("not ap psta =%p, addr =%pM\n", psta, pattrib->dst); */ - if (bmcast) { - psta = rtw_get_bcmc_stainfo23a(padapter); - pskb2 = skb_clone(skb, GFP_ATOMIC); - } else { - psta = rtw_get_stainfo23a(pstapriv, pattrib->dst); - } - - if (psta) { - struct net_device *pnetdev = padapter->pnetdev; - - /* DBG_8723A("directly forwarding to the rtw_xmit23a_entry23a\n"); */ - - /* skb->ip_summed = CHECKSUM_NONE; */ - skb->dev = pnetdev; - skb_set_queue_mapping(skb, rtw_recv_select_queue23a(skb)); - - rtw_xmit23a_entry23a(skb, pnetdev); - - if (bmcast) - skb = pskb2; - else - goto _recv_indicatepkt_end; - } - } else { /* to APself */ - /* DBG_8723A("to APSelf\n"); */ - } - } - - skb->ip_summed = CHECKSUM_NONE; - skb->dev = padapter->pnetdev; - skb->protocol = eth_type_trans(skb, padapter->pnetdev); - - netif_rx(skb); - -_recv_indicatepkt_end: - - precv_frame->pkt = NULL; /* pointers to NULL before rtw_free_recvframe23a() */ - - rtw_free_recvframe23a(precv_frame); - - RT_TRACE(_module_recv_osdep_c_, _drv_info_, - "rtw_recv_indicatepkt23a :after netif_rx!!!!\n"); - return _SUCCESS; - -_recv_indicatepkt_drop: - - rtw_free_recvframe23a(precv_frame); - return _FAIL; -} - -void rtw_init_recv_timer23a(struct recv_reorder_ctrl *preorder_ctrl) -{ - setup_timer(&preorder_ctrl->reordering_ctrl_timer, - rtw_reordering_ctrl_timeout_handler23a, - (unsigned long)preorder_ctrl); -} diff --git a/drivers/staging/rtl8723au/os_dep/usb_intf.c b/drivers/staging/rtl8723au/os_dep/usb_intf.c deleted file mode 100644 index fa7dda5..0000000 --- a/drivers/staging/rtl8723au/os_dep/usb_intf.c +++ /dev/null @@ -1,628 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _HCI_INTF_C_ - -#include <linux/mutex.h> -#include <osdep_service.h> -#include <drv_types.h> -#include <recv_osdep.h> -#include <xmit_osdep.h> -#include <hal_intf.h> -#include <rtw_version.h> -#include <osdep_intf.h> -#include <usb_ops.h> -#include <rtl8723a_hal.h> - -static int rtw_suspend(struct usb_interface *intf, pm_message_t message); -static int rtw_resume(struct usb_interface *intf); -static int rtw_drv_init(struct usb_interface *pusb_intf, - const struct usb_device_id *pdid); -static void rtw_disconnect(struct usb_interface *pusb_intf); - -#define USB_VENDER_ID_REALTEK 0x0BDA - -#define RTL8723A_USB_IDS \ - {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDER_ID_REALTEK, 0x8724, \ - 0xff, 0xff, 0xff)}, /* 8723AU 1*1 */ \ - {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDER_ID_REALTEK, 0x1724, \ - 0xff, 0xff, 0xff)}, /* 8723AU 1*1 */ \ - {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDER_ID_REALTEK, 0x0724, \ - 0xff, 0xff, 0xff)}, /* 8723AU 1*1 */ - -static struct usb_device_id rtl8723a_usb_id_tbl[] = { - RTL8723A_USB_IDS - {} /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, rtl8723a_usb_id_tbl); - -static struct usb_driver rtl8723a_usb_drv = { - .name = (char *)"rtl8723au", - .probe = rtw_drv_init, - .disconnect = rtw_disconnect, - .id_table = rtl8723a_usb_id_tbl, - .suspend = rtw_suspend, - .resume = rtw_resume, - .reset_resume = rtw_resume, -}; - -static struct usb_driver *usb_drv = &rtl8723a_usb_drv; - -static int rtw_init_intf_priv(struct dvobj_priv *dvobj) -{ - mutex_init(&dvobj->usb_vendor_req_mutex); - - return _SUCCESS; -} - -static int rtw_deinit_intf_priv(struct dvobj_priv *dvobj) -{ - mutex_destroy(&dvobj->usb_vendor_req_mutex); - - return _SUCCESS; -} - -static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf) -{ - struct dvobj_priv *pdvobjpriv; - struct usb_host_config *phost_conf; - struct usb_config_descriptor *pconf_desc; - struct usb_host_interface *phost_iface; - struct usb_interface_descriptor *piface_desc; - struct usb_endpoint_descriptor *pendp_desc; - struct usb_device *pusbd; - int i, status = _FAIL; - - pdvobjpriv = kzalloc(sizeof(*pdvobjpriv), GFP_KERNEL); - if (!pdvobjpriv) - goto exit; - - mutex_init(&pdvobjpriv->hw_init_mutex); - mutex_init(&pdvobjpriv->h2c_fwcmd_mutex); - mutex_init(&pdvobjpriv->setch_mutex); - mutex_init(&pdvobjpriv->setbw_mutex); - - pdvobjpriv->pusbintf = usb_intf; - pusbd = interface_to_usbdev(usb_intf); - pdvobjpriv->pusbdev = pusbd; - usb_set_intfdata(usb_intf, pdvobjpriv); - - pdvobjpriv->RtNumInPipes = 0; - pdvobjpriv->RtNumOutPipes = 0; - - phost_conf = pusbd->actconfig; - pconf_desc = &phost_conf->desc; - - phost_iface = &usb_intf->altsetting[0]; - piface_desc = &phost_iface->desc; - - pdvobjpriv->NumInterfaces = pconf_desc->bNumInterfaces; - pdvobjpriv->InterfaceNumber = piface_desc->bInterfaceNumber; - pdvobjpriv->nr_endpoint = piface_desc->bNumEndpoints; - - for (i = 0; i < pdvobjpriv->nr_endpoint; i++) { - pendp_desc = &phost_iface->endpoint[i].desc; - - DBG_8723A("\nusb_endpoint_descriptor(%d):\n", i); - DBG_8723A("bLength =%x\n", pendp_desc->bLength); - DBG_8723A("bDescriptorType =%x\n", pendp_desc->bDescriptorType); - DBG_8723A("bEndpointAddress =%x\n", - pendp_desc->bEndpointAddress); - DBG_8723A("wMaxPacketSize =%d\n", - le16_to_cpu(pendp_desc->wMaxPacketSize)); - DBG_8723A("bInterval =%x\n", pendp_desc->bInterval); - - if (usb_endpoint_is_bulk_in(pendp_desc)) { - DBG_8723A("usb_endpoint_is_bulk_in = %x\n", - usb_endpoint_num(pendp_desc)); - pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] = - usb_endpoint_num(pendp_desc); - pdvobjpriv->RtNumInPipes++; - } else if (usb_endpoint_is_int_in(pendp_desc)) { - DBG_8723A("usb_endpoint_is_int_in = %x, Interval = " - "%x\n", usb_endpoint_num(pendp_desc), - pendp_desc->bInterval); - pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] = - usb_endpoint_num(pendp_desc); - pdvobjpriv->RtNumInPipes++; - } else if (usb_endpoint_is_bulk_out(pendp_desc)) { - DBG_8723A("usb_endpoint_is_bulk_out = %x\n", - usb_endpoint_num(pendp_desc)); - pdvobjpriv->RtOutPipe[pdvobjpriv->RtNumOutPipes] = - usb_endpoint_num(pendp_desc); - pdvobjpriv->RtNumOutPipes++; - } - pdvobjpriv->ep_num[i] = usb_endpoint_num(pendp_desc); - } - DBG_8723A("nr_endpoint =%d, in_num =%d, out_num =%d\n\n", - pdvobjpriv->nr_endpoint, pdvobjpriv->RtNumInPipes, - pdvobjpriv->RtNumOutPipes); - - if (pusbd->speed == USB_SPEED_HIGH) { - pdvobjpriv->ishighspeed = true; - DBG_8723A("USB_SPEED_HIGH\n"); - } else { - pdvobjpriv->ishighspeed = false; - DBG_8723A("NON USB_SPEED_HIGH\n"); - } - - if (rtw_init_intf_priv(pdvobjpriv) == _FAIL) { - RT_TRACE(_module_os_intfs_c_, _drv_err_, - "Can't INIT rtw_init_intf_priv\n"); - goto free_dvobj; - } - /* 3 misc */ - rtw_reset_continual_urb_error(pdvobjpriv); - usb_get_dev(pusbd); - status = _SUCCESS; -free_dvobj: - if (status != _SUCCESS && pdvobjpriv) { - usb_set_intfdata(usb_intf, NULL); - mutex_destroy(&pdvobjpriv->hw_init_mutex); - mutex_destroy(&pdvobjpriv->h2c_fwcmd_mutex); - mutex_destroy(&pdvobjpriv->setch_mutex); - mutex_destroy(&pdvobjpriv->setbw_mutex); - kfree(pdvobjpriv); - pdvobjpriv = NULL; - } -exit: - return pdvobjpriv; -} - -static void usb_dvobj_deinit(struct usb_interface *usb_intf) -{ - struct dvobj_priv *dvobj = usb_get_intfdata(usb_intf); - - usb_set_intfdata(usb_intf, NULL); - if (dvobj) { - /* Modify condition for 92DU DMDP 2010.11.18, by Thomas */ - if ((dvobj->NumInterfaces != 2 && dvobj->NumInterfaces != 3) || - (dvobj->InterfaceNumber == 1)) { - if (interface_to_usbdev(usb_intf)->state != - USB_STATE_NOTATTACHED) { - /* If we didn't unplug usb dongle and - * remove/insert module, driver fails on - * sitesurvey for the first time when - * device is up . - * Reset usb port for sitesurvey fail issue. - */ - DBG_8723A("usb attached..., try to reset usb device\n"); - usb_reset_device(interface_to_usbdev(usb_intf)); - } - } - rtw_deinit_intf_priv(dvobj); - mutex_destroy(&dvobj->hw_init_mutex); - mutex_destroy(&dvobj->h2c_fwcmd_mutex); - mutex_destroy(&dvobj->setch_mutex); - mutex_destroy(&dvobj->setbw_mutex); - kfree(dvobj); - } - usb_put_dev(interface_to_usbdev(usb_intf)); -} - -void rtl8723a_usb_intf_stop(struct rtw_adapter *padapter) -{ - RT_TRACE(_module_hci_intfs_c_, _drv_err_, "+usb_intf_stop\n"); - - /* 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 */ - rtl8723au_inirp_deinit(padapter); - - /* cancel out irp */ - rtl8723au_write_port_cancel(padapter); - - /* todo:cancel other irps */ - RT_TRACE(_module_hci_intfs_c_, _drv_err_, "-usb_intf_stop\n"); -} - -static void rtw_dev_unload(struct rtw_adapter *padapter) -{ - struct submit_ctx *pack_tx_ops = &padapter->xmitpriv.ack_tx_ops; - - RT_TRACE(_module_hci_intfs_c_, _drv_err_, "+rtw_dev_unload\n"); - - if (padapter->bup) { - DBG_8723A("===> rtw_dev_unload\n"); - - padapter->bDriverStopped = true; - if (padapter->xmitpriv.ack_tx) - rtw23a_sctx_done_err(&pack_tx_ops, - RTW_SCTX_DONE_DRV_STOP); - - /* s3. */ - rtl8723a_usb_intf_stop(padapter); - - /* s4. */ - flush_workqueue(padapter->cmdpriv.wq); - - /* s5. */ - if (!padapter->bSurpriseRemoved) { - rtl8723au_hal_deinit(padapter); - padapter->bSurpriseRemoved = true; - } - padapter->bup = false; - } else { - RT_TRACE(_module_hci_intfs_c_, _drv_err_, - "r871x_dev_unload():padapter->bup == false\n"); - } - DBG_8723A("<=== rtw_dev_unload\n"); - RT_TRACE(_module_hci_intfs_c_, _drv_err_, "-rtw_dev_unload\n"); -} - -static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message) -{ - struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf); - struct rtw_adapter *padapter = dvobj->if1; - struct net_device *pnetdev = padapter->pnetdev; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - int ret = 0; - unsigned long start_time = jiffies; - - DBG_8723A("==> %s (%s:%d)\n", __func__, current->comm, current->pid); - - if ((!padapter->bup) || (padapter->bDriverStopped) || - (padapter->bSurpriseRemoved)) { - DBG_8723A("padapter->bup =%d bDriverStopped =%d bSurpriseRemoved = %d\n", - padapter->bup, padapter->bDriverStopped, - padapter->bSurpriseRemoved); - goto exit; - } - pwrpriv->bInSuspend = true; - rtw_cancel_all_timer23a(padapter); - LeaveAllPowerSaveMode23a(padapter); - - mutex_lock(&pwrpriv->mutex_lock); - /* padapter->net_closed = true; */ - /* s1. */ - if (pnetdev) { - netif_carrier_off(pnetdev); - netif_tx_stop_all_queues(pnetdev); - } - - /* s2. */ - rtw_disassoc_cmd23a(padapter, 0, false); - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) && - check_fwstate(pmlmepriv, _FW_LINKED)) { - DBG_8723A("%s:%d %s(%pM), length:%d assoc_ssid.length:%d\n", - __func__, __LINE__, - pmlmepriv->cur_network.network.Ssid.ssid, - pmlmepriv->cur_network.network.MacAddress, - pmlmepriv->cur_network.network.Ssid.ssid_len, - pmlmepriv->assoc_ssid.ssid_len); - - rtw_set_roaming(padapter, 1); - } - /* s2-2. indicate disconnect to os */ - rtw_indicate_disconnect23a(padapter); - /* s2-3. */ - rtw_free_assoc_resources23a(padapter, 1); - /* s2-4. */ - rtw_free_network_queue23a(padapter); - - rtw_dev_unload(padapter); - mutex_unlock(&pwrpriv->mutex_lock); - - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) - rtw_cfg80211_indicate_scan_done( - wdev_to_priv(padapter->rtw_wdev), true); - - if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) - rtw_indicate_disconnect23a(padapter); - -exit: - DBG_8723A("<=== %s return %d.............. in %dms\n", __func__, - ret, jiffies_to_msecs(jiffies - start_time)); - - return ret; -} - -static int rtw_resume(struct usb_interface *pusb_intf) -{ - struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf); - struct rtw_adapter *padapter = dvobj->if1; - struct net_device *pnetdev; - struct pwrctrl_priv *pwrpriv = NULL; - int ret = -1; - unsigned long start_time = jiffies; - - DBG_8723A("==> %s (%s:%d)\n", __func__, current->comm, current->pid); - - if (!padapter) - goto exit; - pnetdev = padapter->pnetdev; - pwrpriv = &padapter->pwrctrlpriv; - - mutex_lock(&pwrpriv->mutex_lock); - rtw_reset_drv_sw23a(padapter); - pwrpriv->bkeepfwalive = false; - - DBG_8723A("bkeepfwalive(%x)\n", pwrpriv->bkeepfwalive); - if (pm_netdev_open23a(pnetdev, true) != 0) { - mutex_unlock(&pwrpriv->mutex_lock); - goto exit; - } - - netif_device_attach(pnetdev); - netif_carrier_on(pnetdev); - - mutex_unlock(&pwrpriv->mutex_lock); - - if (padapter->pid[1] != 0) { - DBG_8723A("pid[1]:%d\n", padapter->pid[1]); - kill_pid(find_vpid(padapter->pid[1]), SIGUSR2, 1); - } - - rtw23a_roaming(padapter, NULL); - - ret = 0; -exit: - if (pwrpriv) - pwrpriv->bInSuspend = false; - DBG_8723A("<=== %s return %d.............. in %dms\n", __func__, - ret, jiffies_to_msecs(jiffies - start_time)); - - return ret; -} - -/* - * drv_init() - a device potentially for us - * - * notes: drv_init() is called when the bus driver has located a card - * for us to support. - * We accept the new device by returning 0. - */ -static struct rtw_adapter *rtw_usb_if1_init(struct dvobj_priv *dvobj, - struct usb_interface *pusb_intf, - const struct usb_device_id *pdid) -{ - struct rtw_adapter *padapter = NULL; - struct net_device *pnetdev = NULL; - int status = _FAIL; - - pnetdev = rtw_init_netdev23a(padapter); - if (!pnetdev) - goto free_adapter; - padapter = netdev_priv(pnetdev); - - padapter->dvobj = dvobj; - padapter->bDriverStopped = true; - dvobj->if1 = padapter; - dvobj->padapters[dvobj->iface_nums++] = padapter; - padapter->iface_id = IFACE_ID0; - - rtl8723au_set_hw_type(padapter); - - SET_NETDEV_DEV(pnetdev, dvobj_to_dev(dvobj)); - - if (rtw_wdev_alloc(padapter, dvobj_to_dev(dvobj))) - goto free_adapter; - - /* step 2. allocate HalData */ - padapter->HalData = kzalloc(sizeof(struct hal_data_8723a), GFP_KERNEL); - if (!padapter->HalData) - goto free_wdev; - - /* step read_chip_version */ - rtl8723a_read_chip_version(padapter); - - /* step usb endpoint mapping */ - if (!rtl8723au_chip_configure(padapter)) - goto free_hal_data; - - /* step read efuse/eeprom data and get mac_addr */ - rtl8723a_read_adapter_info(padapter); - - /* step 5. */ - if (rtw_init_drv_sw23a(padapter) == _FAIL) { - RT_TRACE(_module_hci_intfs_c_, _drv_err_, - "Initialize driver software resource Failed!\n"); - goto free_hal_data; - } - -#ifdef CONFIG_PM - if (padapter->pwrctrlpriv.bSupportRemoteWakeup) { - dvobj->pusbdev->do_remote_wakeup = 1; - pusb_intf->needs_remote_wakeup = 1; - device_init_wakeup(&pusb_intf->dev, 1); - DBG_8723A("\n padapter->pwrctrlpriv.bSupportRemoteWakeup~~~~~~\n"); - DBG_8723A("\n padapter->pwrctrlpriv.bSupportRemoteWakeup~~~[%d]~~~\n", - device_may_wakeup(&pusb_intf->dev)); - } -#endif - /* 2012-07-11 Move here to prevent the 8723AS-VAU BT - * auto suspend influence - */ - if (usb_autopm_get_interface(pusb_intf) < 0) - DBG_8723A("can't get autopm:\n"); -#ifdef CONFIG_8723AU_BT_COEXIST - padapter->pwrctrlpriv.autopm_cnt = 1; -#endif - - /* If the eeprom mac address is corrupted, assign a random address */ - if (is_broadcast_ether_addr(padapter->eeprompriv.mac_addr) || - is_zero_ether_addr(padapter->eeprompriv.mac_addr)) - eth_random_addr(padapter->eeprompriv.mac_addr); - - DBG_8723A("bDriverStopped:%d, bSurpriseRemoved:%d, bup:%d, hw_init_completed:%d\n", - padapter->bDriverStopped, padapter->bSurpriseRemoved, - padapter->bup, padapter->hw_init_completed - ); - status = _SUCCESS; - -free_hal_data: - if (status != _SUCCESS) - kfree(padapter->HalData); -free_wdev: - if (status != _SUCCESS) { - rtw_wdev_unregister(padapter->rtw_wdev); - rtw_wdev_free(padapter->rtw_wdev); - } -free_adapter: - if (status != _SUCCESS) { - if (pnetdev) - free_netdev(pnetdev); - padapter = NULL; - } - return padapter; -} - -static void rtw_usb_if1_deinit(struct rtw_adapter *if1) -{ - struct net_device *pnetdev = if1->pnetdev; - struct mlme_priv *pmlmepriv = &if1->mlmepriv; - - if (check_fwstate(pmlmepriv, _FW_LINKED)) - rtw_disassoc_cmd23a(if1, 0, false); - -#ifdef CONFIG_8723AU_AP_MODE - free_mlme_ap_info23a(if1); -#endif - - if (pnetdev) - unregister_netdev(pnetdev); /* will call netdev_close() */ - - rtw_cancel_all_timer23a(if1); - - rtw_dev_unload(if1); - - DBG_8723A("+r871xu_dev_remove, hw_init_completed =%d\n", - if1->hw_init_completed); - - if (if1->rtw_wdev) { - rtw_wdev_unregister(if1->rtw_wdev); - rtw_wdev_free(if1->rtw_wdev); - } - -#ifdef CONFIG_8723AU_BT_COEXIST - if (1 == if1->pwrctrlpriv.autopm_cnt) { - usb_autopm_put_interface(adapter_to_dvobj(if1)->pusbintf); - if1->pwrctrlpriv.autopm_cnt--; - } -#endif - - rtw_free_drv_sw23a(if1); - - if (pnetdev) - free_netdev(pnetdev); -} - -static int rtw_drv_init(struct usb_interface *pusb_intf, - const struct usb_device_id *pdid) -{ - struct rtw_adapter *if1 = NULL; - struct dvobj_priv *dvobj; - struct usb_device *udev; - int status = _FAIL; - - RT_TRACE(_module_hci_intfs_c_, _drv_err_, "+rtw_drv_init\n"); - - /* Initialize dvobj_priv */ - dvobj = usb_dvobj_init(pusb_intf); - if (!dvobj) { - RT_TRACE(_module_hci_intfs_c_, _drv_err_, - "initialize device object priv Failed!\n"); - goto exit; - } - - udev = dvobj->pusbdev; - dev_warn(&udev->dev, "WARNING: The rtl8723au driver is deprecated!"); - dev_warn(&udev->dev, "Please use the rtl8xxxu driver for this device!"); - - if1 = rtw_usb_if1_init(dvobj, pusb_intf, pdid); - if (!if1) { - DBG_8723A("rtw_init_primary_adapter Failed!\n"); - goto free_dvobj; - } - - /* dev_alloc_name && register_netdev */ - status = rtw_drv_register_netdev(if1); - if (status != _SUCCESS) - goto free_if1; - RT_TRACE(_module_hci_intfs_c_, _drv_err_, - "-871x_drv - drv_init, success!\n"); - - status = _SUCCESS; - -free_if1: - if (status != _SUCCESS && if1) - rtw_usb_if1_deinit(if1); -free_dvobj: - if (status != _SUCCESS) - usb_dvobj_deinit(pusb_intf); -exit: - return status == _SUCCESS ? 0 : -ENODEV; -} - -/* dev_remove() - our device is being removed */ -static void rtw_disconnect(struct usb_interface *pusb_intf) -{ - struct dvobj_priv *dvobj; - struct rtw_adapter *padapter; - struct net_device *pnetdev; - struct mlme_priv *pmlmepriv; - - dvobj = usb_get_intfdata(pusb_intf); - if (!dvobj) - return; - - padapter = dvobj->if1; - pnetdev = padapter->pnetdev; - pmlmepriv = &padapter->mlmepriv; - - usb_set_intfdata(pusb_intf, NULL); - - RT_TRACE(_module_hci_intfs_c_, _drv_err_, "+dev_remove()\n"); - - rtw_pm_set_ips23a(padapter, IPS_NONE); - rtw_pm_set_lps23a(padapter, PS_MODE_ACTIVE); - - LeaveAllPowerSaveMode23a(padapter); - - rtw_usb_if1_deinit(padapter); - - usb_dvobj_deinit(pusb_intf); - - RT_TRACE(_module_hci_intfs_c_, _drv_err_, "-dev_remove()\n"); - DBG_8723A("-r871xu_dev_remove, done\n"); -} - -static int __init rtw_drv_entry(void) -{ - RT_TRACE(_module_hci_intfs_c_, _drv_err_, "+rtw_drv_entry\n"); - return usb_register(usb_drv); -} - -static void __exit rtw_drv_halt(void) -{ - RT_TRACE(_module_hci_intfs_c_, _drv_err_, "+rtw_drv_halt\n"); - DBG_8723A("+rtw_drv_halt\n"); - - usb_deregister(usb_drv); - - DBG_8723A("-rtw_drv_halt\n"); -} - -module_init(rtw_drv_entry); -module_exit(rtw_drv_halt); diff --git a/drivers/staging/rtl8723au/os_dep/usb_ops_linux.c b/drivers/staging/rtl8723au/os_dep/usb_ops_linux.c deleted file mode 100644 index cf4a506..0000000 --- a/drivers/staging/rtl8723au/os_dep/usb_ops_linux.c +++ /dev/null @@ -1,233 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _USB_OPS_LINUX_C_ - -#include <drv_types.h> -#include <usb_ops_linux.h> -#include <rtw_sreset.h> - -void rtl8723au_read_port_cancel(struct rtw_adapter *padapter) -{ - struct recv_buf *precvbuf; - int i; - - precvbuf = (struct recv_buf *)padapter->recvpriv.precv_buf; - - DBG_8723A("%s\n", __func__); - - padapter->bReadPortCancel = true; - - for (i = 0; i < NR_RECVBUFF ; i++) { - if (precvbuf->purb) - usb_kill_urb(precvbuf->purb); - precvbuf++; - } - usb_kill_urb(padapter->recvpriv.int_in_urb); -} - -static void usb_write_port23a_complete(struct urb *purb) -{ - struct xmit_buf *pxmitbuf = (struct xmit_buf *)purb->context; - struct rtw_adapter *padapter = pxmitbuf->padapter; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct hal_data_8723a *phaldata; - unsigned long irqL; - - switch (pxmitbuf->flags) { - case HIGH_QUEUE_INX: -#ifdef CONFIG_8723AU_AP_MODE - rtw_chk_hi_queue_cmd23a(padapter); -#endif - break; - default: - break; - } - - if (padapter->bSurpriseRemoved || padapter->bDriverStopped || - padapter->bWritePortCancel) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_write_port23a_complete:bDriverStopped(%d) OR bSurpriseRemoved(%d)\n", - padapter->bDriverStopped, padapter->bSurpriseRemoved); - DBG_8723A("%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); - - goto check_completion; - } - - if (purb->status) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_write_port23a_complete : purb->status(%d) != 0\n", - purb->status); - DBG_8723A("###=> urb_write_port_complete status(%d)\n", - purb->status); - if (purb->status == -EPIPE || purb->status == -EPROTO) { - } else if (purb->status == -EINPROGRESS) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_write_port23a_complete: EINPROGESS\n"); - goto check_completion; - } else if (purb->status == -ENOENT) { - DBG_8723A("%s: -ENOENT\n", __func__); - goto check_completion; - } else if (purb->status == -ECONNRESET) { - DBG_8723A("%s: -ECONNRESET\n", __func__); - goto check_completion; - } else if (purb->status == -ESHUTDOWN) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_write_port23a_complete: ESHUTDOWN\n"); - padapter->bDriverStopped = true; - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_write_port23a_complete:bDriverStopped = true\n"); - goto check_completion; - } else { - padapter->bSurpriseRemoved = true; - DBG_8723A("bSurpriseRemoved = true\n"); - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_write_port23a_complete:bSurpriseRemoved = true\n"); - goto check_completion; - } - } - phaldata = GET_HAL_DATA(padapter); - phaldata->srestpriv.last_tx_complete_time = jiffies; - -check_completion: - spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL); - rtw23a_sctx_done_err(&pxmitbuf->sctx, - purb->status ? RTW_SCTX_DONE_WRITE_PORT_ERR : - RTW_SCTX_DONE_SUCCESS); - spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL); - - rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf); - - tasklet_hi_schedule(&pxmitpriv->xmit_tasklet); -} - -int rtl8723au_write_port(struct rtw_adapter *padapter, u32 addr, u32 cnt, - struct xmit_buf *pxmitbuf) -{ - struct urb *purb = NULL; - struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter); - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct xmit_frame *pxmitframe; - struct usb_device *pusbd = pdvobj->pusbdev; - unsigned long irqL; - unsigned int pipe, ep_num; - int status; - int ret = _FAIL; - - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, "+usb_write_port23a\n"); - - if (padapter->bDriverStopped || padapter->bSurpriseRemoved) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "%s:(padapter->bDriverStopped || padapter->bSurpriseRemoved)!!!\n", - __func__); - rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_TX_DENY); - goto exit; - } - - pxmitframe = (struct xmit_frame *)pxmitbuf->priv_data; - spin_lock_irqsave(&pxmitpriv->lock, irqL); - - switch (addr) { - case VO_QUEUE_INX: - pxmitbuf->flags = VO_QUEUE_INX; - break; - case VI_QUEUE_INX: - pxmitbuf->flags = VI_QUEUE_INX; - break; - case BE_QUEUE_INX: - pxmitbuf->flags = BE_QUEUE_INX; - break; - case BK_QUEUE_INX: - pxmitbuf->flags = BK_QUEUE_INX; - break; - case HIGH_QUEUE_INX: - pxmitbuf->flags = HIGH_QUEUE_INX; - break; - default: - pxmitbuf->flags = MGT_QUEUE_INX; - break; - } - - spin_unlock_irqrestore(&pxmitpriv->lock, irqL); - - purb = pxmitbuf->pxmit_urb[0]; - - /* translate DMA FIFO addr to pipehandle */ - ep_num = pdvobj->Queue2Pipe[addr]; - pipe = usb_sndbulkpipe(pusbd, ep_num); - - usb_fill_bulk_urb(purb, pusbd, pipe, - pxmitframe->buf_addr, /* pxmitbuf->pbuf */ - cnt, usb_write_port23a_complete, - pxmitbuf);/* context is pxmitbuf */ - - status = usb_submit_urb(purb, GFP_ATOMIC); - if (!status) { - struct hal_data_8723a *phaldata = GET_HAL_DATA(padapter); - phaldata->srestpriv.last_tx_time = jiffies; - } else { - rtw23a_sctx_done_err(&pxmitbuf->sctx, - RTW_SCTX_DONE_WRITE_PORT_ERR); - DBG_8723A("usb_write_port23a, status =%d\n", status); - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - "usb_write_port23a(): usb_submit_urb, status =%x\n", - status); - - switch (status) { - case -ENODEV: - padapter->bDriverStopped = true; - break; - default: - break; - } - goto exit; - } - ret = _SUCCESS; - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, "-usb_write_port23a\n"); - -exit: - if (ret != _SUCCESS) - rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf); - - return ret; -} - -void rtl8723au_write_port_cancel(struct rtw_adapter *padapter) -{ - struct xmit_buf *pxmitbuf; - int j; - - DBG_8723A("%s\n", __func__); - - padapter->bWritePortCancel = true; - - list_for_each_entry(pxmitbuf, &padapter->xmitpriv.xmitbuf_list, - list2) { - for (j = 0; j < 8; j++) { - if (pxmitbuf->pxmit_urb[j]) - usb_kill_urb(pxmitbuf->pxmit_urb[j]); - } - } - list_for_each_entry(pxmitbuf, &padapter->xmitpriv.xmitextbuf_list, - list2) { - for (j = 0; j < 8; j++) { - if (pxmitbuf->pxmit_urb[j]) - usb_kill_urb(pxmitbuf->pxmit_urb[j]); - } - } -} diff --git a/drivers/staging/rtl8723au/os_dep/xmit_linux.c b/drivers/staging/rtl8723au/os_dep/xmit_linux.c deleted file mode 100644 index 64be72a..0000000 --- a/drivers/staging/rtl8723au/os_dep/xmit_linux.c +++ /dev/null @@ -1,154 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _XMIT_OSDEP_C_ - -#include <osdep_service.h> -#include <drv_types.h> - -#include <linux/if_ether.h> -#include <linux/ip.h> -#include <wifi.h> -#include <mlme_osdep.h> -#include <xmit_osdep.h> -#include <osdep_intf.h> - -int rtw_os_xmit_resource_alloc23a(struct rtw_adapter *padapter, - struct xmit_buf *pxmitbuf, u32 alloc_sz) -{ - int i; - - pxmitbuf->pallocated_buf = kzalloc(alloc_sz, GFP_KERNEL); - if (pxmitbuf->pallocated_buf == NULL) - return _FAIL; - - pxmitbuf->pbuf = PTR_ALIGN(pxmitbuf->pallocated_buf, XMITBUF_ALIGN_SZ); - - for (i = 0; i < 8; i++) { - pxmitbuf->pxmit_urb[i] = usb_alloc_urb(0, GFP_KERNEL); - if (!pxmitbuf->pxmit_urb[i]) { - DBG_8723A("pxmitbuf->pxmit_urb[i]==NULL"); - return _FAIL; - } - } - return _SUCCESS; -} - -void rtw_os_xmit_resource_free23a(struct rtw_adapter *padapter, - struct xmit_buf *pxmitbuf) -{ - int i; - - for (i = 0; i < 8; i++) - usb_free_urb(pxmitbuf->pxmit_urb[i]); - kfree(pxmitbuf->pallocated_buf); -} - -#define WMM_XMIT_THRESHOLD (NR_XMITFRAME*2/5) - -void rtw_os_pkt_complete23a(struct rtw_adapter *padapter, struct sk_buff *pkt) -{ - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - u16 queue; - - queue = skb_get_queue_mapping(pkt); - if (padapter->registrypriv.wifi_spec) { - if (__netif_subqueue_stopped(padapter->pnetdev, queue) && - (pxmitpriv->hwxmits[queue].accnt < WMM_XMIT_THRESHOLD)) - netif_wake_subqueue(padapter->pnetdev, queue); - } else { - if (__netif_subqueue_stopped(padapter->pnetdev, queue)) - netif_wake_subqueue(padapter->pnetdev, queue); - } - dev_kfree_skb_any(pkt); -} - -void rtw_os_xmit_complete23a(struct rtw_adapter *padapter, - struct xmit_frame *pxframe) -{ - if (pxframe->pkt) - rtw_os_pkt_complete23a(padapter, pxframe->pkt); - - pxframe->pkt = NULL; -} - -void rtw_os_xmit_schedule23a(struct rtw_adapter *padapter) -{ - struct xmit_priv *pxmitpriv; - - if (!padapter) - return; - pxmitpriv = &padapter->xmitpriv; - - spin_lock_bh(&pxmitpriv->lock); - - if (rtw_txframes_pending23a(padapter)) - tasklet_hi_schedule(&pxmitpriv->xmit_tasklet); - spin_unlock_bh(&pxmitpriv->lock); -} - -static void rtw_check_xmit_resource(struct rtw_adapter *padapter, - struct sk_buff *pkt) -{ - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - u16 queue; - - queue = skb_get_queue_mapping(pkt); - if (padapter->registrypriv.wifi_spec) { - /* No free space for Tx, tx_worker is too slow */ - if (pxmitpriv->hwxmits[queue].accnt > WMM_XMIT_THRESHOLD) - netif_stop_subqueue(padapter->pnetdev, queue); - } else { - if (pxmitpriv->free_xmitframe_cnt <= 4) { - if (!netif_tx_queue_stopped(netdev_get_tx_queue(padapter->pnetdev, queue))) - netif_stop_subqueue(padapter->pnetdev, queue); - } - } -} - -int rtw_xmit23a_entry23a(struct sk_buff *skb, struct net_device *pnetdev) -{ - struct rtw_adapter *padapter = netdev_priv(pnetdev); - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - int res = 0; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, "+xmit_enry\n"); - - if (!rtw_if_up23a(padapter)) { - RT_TRACE(_module_xmit_osdep_c_, _drv_err_, - "rtw_xmit23a_entry23a: rtw_if_up23a fail\n"); - goto drop_packet; - } - - rtw_check_xmit_resource(padapter, skb); - - res = rtw_xmit23a(padapter, skb); - if (res < 0) - goto drop_packet; - - pxmitpriv->tx_pkts++; - RT_TRACE(_module_xmit_osdep_c_, _drv_info_, - "rtw_xmit23a_entry23a: tx_pkts=%d\n", - (u32)pxmitpriv->tx_pkts); - goto exit; - -drop_packet: - pxmitpriv->tx_drop++; - dev_kfree_skb_any(skb); - RT_TRACE(_module_xmit_osdep_c_, _drv_notice_, - "rtw_xmit23a_entry23a: drop, tx_drop=%d\n", - (u32)pxmitpriv->tx_drop); -exit: - return 0; -} -- cgit v0.10.2 From 4b1a9380a62ae669d1ae10dc118570c276a645ea Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen <lars@metafoo.de> Date: Thu, 8 Sep 2016 18:49:10 +0200 Subject: iio: iio_push_event(): Don't crash if the event interface is not registered iio_push_event() operates on a struct iio_dev. This struct can be allocated using iio_device_alloc() which returns a valid struct iio_dev pointer. But iio_push_event() is not safe to use on such a iio_dev until iio_device_register() for the same device has successfully completed. This restriction is not documented anywhere and most drivers are written with the assumption that this restriction does not exist. The basic pattern that is followed by all drivers looks like the following: irqreturn_t event_callback(int irq, void *devid) { struct iio_dev *indio_dev = devid; ... iio_push_event(indio_dev, ...); return IRQ_HANDLED; } int driver_probe(struct device *dev) { struct iio_dev *indio_dev; indio_dev = iio_device_alloc(...); request_irq(event_irq, event_callback, ..., indio_dev); return iio_device_register(indio_dev); } And while it is unlikely that the IRQ fires before iio_device_register() completes (e.g. because the IRQ is disabled in the device) it is not impossible and might be triggered by glitches on the signal line or incorrect hardware configuration. To avoid undefined behaviour in such a case extend iio_push_event() to check if the event has been registered and discard generated events if it has not. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c index 0ebfc92..90fac8e 100644 --- a/drivers/iio/industrialio-event.c +++ b/drivers/iio/industrialio-event.c @@ -57,6 +57,11 @@ bool iio_event_enabled(const struct iio_event_interface *ev_int) * * Note: The caller must make sure that this function is not running * concurrently for the same indio_dev more than once. + * + * This function may be safely used as soon as a valid reference to iio_dev has + * been obtained via iio_device_alloc(), but any events that are submitted + * before iio_device_register() has successfully completed will be silently + * discarded. **/ int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp) { @@ -64,6 +69,9 @@ int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp) struct iio_event_data ev; int copied; + if (!ev_int) + return 0; + /* Does anyone care? */ if (iio_event_enabled(ev_int)) { -- cgit v0.10.2 From 702a7b8e064a93df0b63e9d718b666a9851088fc Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Thu, 1 Sep 2016 10:27:17 +0200 Subject: iio: trigger: helpers to determine own trigger This adds a helper function to the IIO trigger framework: iio_trigger_using_own(): for an IIO device, this tells whether the device is using itself as a trigger. This is true if the indio device: (A) supplies a trigger and (B) has assigned its own buffer poll function to use this trigger. This helper function is good when constructing triggered, buffered drivers that can either use its own hardware *OR* an external trigger such as a HRTimer or even the trigger from a totally different sensor. Under such circumstances it is important to know for example if the timestamp from the same trigger hardware should be used when populating the buffer: if iio_trigger_using_own() is true, we can use this timestamp, else we need to pick a unique timestamp directly in the trigger handler. For this to work of course IIO devices registering hardware triggers must follow the convention to set the parent device properly, as as well as setting the parent of the IIO device itself. When a new poll function is attached, we check if the parent device of the IIO of the poll function is the same as the parent device of the trigger and in that case we conclude that the hardware is using itself as trigger. Cc: Giuseppe Barba <giuseppe.barba@st.com> Cc: Denis Ciocca <denis.ciocca@st.com> Cc: Crestez Dan Leonard <leonard.crestez@intel.com> Cc: Gregor Boirie <gregor.boirie@parrot.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c index ba584b5..e1e1048 100644 --- a/drivers/iio/industrialio-trigger.c +++ b/drivers/iio/industrialio-trigger.c @@ -271,6 +271,14 @@ static int iio_trigger_attach_poll_func(struct iio_trigger *trig, goto out_free_irq; } + /* + * Check if we just registered to our own trigger: we determine that + * this is the case if the IIO device and the trigger device share the + * same parent device. + */ + if (pf->indio_dev->dev.parent == trig->dev.parent) + trig->attached_own_device = true; + return ret; out_free_irq: @@ -295,6 +303,8 @@ static int iio_trigger_detach_poll_func(struct iio_trigger *trig, if (ret) return ret; } + if (pf->indio_dev->dev.parent == trig->dev.parent) + trig->attached_own_device = false; iio_trigger_put_irq(trig, pf->irq); free_irq(pf->irq, pf); module_put(pf->indio_dev->info->driver_module); @@ -701,6 +711,12 @@ void devm_iio_trigger_unregister(struct device *dev, } EXPORT_SYMBOL_GPL(devm_iio_trigger_unregister); +bool iio_trigger_using_own(struct iio_dev *indio_dev) +{ + return indio_dev->trig->attached_own_device; +} +EXPORT_SYMBOL(iio_trigger_using_own); + void iio_device_register_trigger_consumer(struct iio_dev *indio_dev) { indio_dev->groups[indio_dev->groupcounter++] = diff --git a/include/linux/iio/trigger.h b/include/linux/iio/trigger.h index f0890a5..4f1154f 100644 --- a/include/linux/iio/trigger.h +++ b/include/linux/iio/trigger.h @@ -56,6 +56,9 @@ struct iio_trigger_ops { * @subirqs: [INTERN] information about the 'child' irqs. * @pool: [INTERN] bitmap of irqs currently in use. * @pool_lock: [INTERN] protection of the irq pool. + * @attached_own_device:[INTERN] if we are using our own device as trigger, + * i.e. if we registered a poll function to the same + * device as the one providing the trigger. **/ struct iio_trigger { const struct iio_trigger_ops *ops; @@ -73,6 +76,7 @@ struct iio_trigger { struct iio_subirq subirqs[CONFIG_IIO_CONSUMERS_PER_TRIGGER]; unsigned long pool[BITS_TO_LONGS(CONFIG_IIO_CONSUMERS_PER_TRIGGER)]; struct mutex pool_lock; + bool attached_own_device; }; @@ -160,6 +164,13 @@ irqreturn_t iio_trigger_generic_data_rdy_poll(int irq, void *private); __printf(1, 2) struct iio_trigger *iio_trigger_alloc(const char *fmt, ...); void iio_trigger_free(struct iio_trigger *trig); +/** + * iio_trigger_using_own() - tells us if we use our own HW trigger ourselves + * @indio_dev: device to check + */ +bool iio_trigger_using_own(struct iio_dev *indio_dev); + + #else struct iio_trigger; struct iio_trigger_ops; -- cgit v0.10.2 From 7ba4b884b7a890e240a13f5f65d607721e80396a Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Thu, 1 Sep 2016 10:27:18 +0200 Subject: iio: st_sensors: use the helper function The ST sensors can be used as a trigger for its own triggered buffer but it is also possible to use an external trigger: a HRTimer or even a different sensor (!) as trigger. In that case we should not pick the timestamp from our own interrupt top half even if it is active. This could practically happen if some other sensor is using the ST sensor as trigger but the ST sensor itself is using e.g. an HRTimer as trigger. So the trigger is on, but not used by us. We used to assume that whenever the hardware interrupt is turned on, we are using it for our own trigger, but this is an oversimplification. Handle this logically by using the iio_trigger_using_own() helper. Cc: Giuseppe Barba <giuseppe.barba@st.com> Cc: Denis Ciocca <denis.ciocca@st.com> Cc: Crestez Dan Leonard <leonard.crestez@intel.com> Cc: Gregor Boirie <gregor.boirie@parrot.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/common/st_sensors/st_sensors_buffer.c b/drivers/iio/common/st_sensors/st_sensors_buffer.c index d06e728..fe7775b 100644 --- a/drivers/iio/common/st_sensors/st_sensors_buffer.c +++ b/drivers/iio/common/st_sensors/st_sensors_buffer.c @@ -63,7 +63,7 @@ irqreturn_t st_sensors_trigger_handler(int irq, void *p) * the hardware trigger) and the hw_timestamp may get updated. * By storing it in a local variable first, we are safe. */ - if (sdata->hw_irq_trigger) + if (iio_trigger_using_own(indio_dev)) timestamp = sdata->hw_timestamp; else timestamp = iio_get_time_ns(indio_dev); -- cgit v0.10.2 From c0554645a8c5a2fe6dd3dceb17a906f407e5bbf9 Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Fri, 9 Sep 2016 15:25:35 +0200 Subject: staging: most: hdm-usb: extend DCI access This patch extends the direct communication interface ABI of the USB network interface controller. It is needed to provide applications arbitrary access to DCI registers and the ability to synchronize the internal endpoint logic of the controller. Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index 08c4a3b..da47253 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -79,10 +79,12 @@ struct buf_anchor { * struct most_dci_obj - Direct Communication Interface * @kobj:position in sysfs * @usb_device: pointer to the usb device + * @reg_addr: register address for arbitrary DCI access */ struct most_dci_obj { struct kobject kobj; struct usb_device *usb_device; + u16 reg_addr; }; #define to_dci_obj(p) container_of(p, struct most_dci_obj, kobj) @@ -948,6 +950,10 @@ static struct usb_device_id usbid[] = { struct most_dci_attribute most_dci_attr_##_name = \ __ATTR(_name, S_IRUGO | S_IWUSR, show_value, store_value) +#define MOST_DCI_WO_ATTR(_name) \ + struct most_dci_attribute most_dci_attr_##_name = \ + __ATTR(_name, S_IWUSR, show_value, store_value) + /** * struct most_dci_attribute - to access the attributes of a dci object * @attr: attributes of a dci object @@ -1031,6 +1037,9 @@ static ssize_t show_value(struct most_dci_obj *dci_obj, u16 reg_addr; int err; + if (!strcmp(attr->attr.name, "arb_address")) + return snprintf(buf, PAGE_SIZE, "%04x\n", dci_obj->reg_addr); + if (!strcmp(attr->attr.name, "ni_state")) reg_addr = DRCI_REG_NI_STATE; else if (!strcmp(attr->attr.name, "packet_bandwidth")) @@ -1055,6 +1064,8 @@ static ssize_t show_value(struct most_dci_obj *dci_obj, reg_addr = DRCI_REG_HW_ADDR_MI; else if (!strcmp(attr->attr.name, "mep_eui48_lo")) reg_addr = DRCI_REG_HW_ADDR_LO; + else if (!strcmp(attr->attr.name, "arb_value")) + reg_addr = dci_obj->reg_addr; else return -EIO; @@ -1073,6 +1084,14 @@ static ssize_t store_value(struct most_dci_obj *dci_obj, u16 reg_addr; int err; + err = kstrtou16(buf, 16, &val); + if (err) + return err; + + if (!strcmp(attr->attr.name, "arb_address")) { + dci_obj->reg_addr = val; + return count; + } if (!strcmp(attr->attr.name, "mep_filter")) reg_addr = DRCI_REG_MEP_FILTER; else if (!strcmp(attr->attr.name, "mep_hash0")) @@ -1089,13 +1108,16 @@ static ssize_t store_value(struct most_dci_obj *dci_obj, reg_addr = DRCI_REG_HW_ADDR_MI; else if (!strcmp(attr->attr.name, "mep_eui48_lo")) reg_addr = DRCI_REG_HW_ADDR_LO; - else + else if (!strcmp(attr->attr.name, "arb_value")) + reg_addr = dci_obj->reg_addr; + else if (!strcmp(attr->attr.name, "sync_ep")) { + u16 ep = val; + + reg_addr = DRCI_REG_BASE + DRCI_COMMAND + ep * 16; + val = 1; + } else return -EIO; - err = kstrtou16(buf, 16, &val); - if (err) - return err; - err = drci_wr_reg(dci_obj->usb_device, reg_addr, val); if (err < 0) return err; @@ -1107,6 +1129,7 @@ static MOST_DCI_RO_ATTR(ni_state); static MOST_DCI_RO_ATTR(packet_bandwidth); static MOST_DCI_RO_ATTR(node_address); static MOST_DCI_RO_ATTR(node_position); +static MOST_DCI_WO_ATTR(sync_ep); static MOST_DCI_ATTR(mep_filter); static MOST_DCI_ATTR(mep_hash0); static MOST_DCI_ATTR(mep_hash1); @@ -1115,6 +1138,8 @@ static MOST_DCI_ATTR(mep_hash3); static MOST_DCI_ATTR(mep_eui48_hi); static MOST_DCI_ATTR(mep_eui48_mi); static MOST_DCI_ATTR(mep_eui48_lo); +static MOST_DCI_ATTR(arb_address); +static MOST_DCI_ATTR(arb_value); /** * most_dci_def_attrs - array of default attribute files of the dci object @@ -1124,6 +1149,7 @@ static struct attribute *most_dci_def_attrs[] = { &most_dci_attr_packet_bandwidth.attr, &most_dci_attr_node_address.attr, &most_dci_attr_node_position.attr, + &most_dci_attr_sync_ep.attr, &most_dci_attr_mep_filter.attr, &most_dci_attr_mep_hash0.attr, &most_dci_attr_mep_hash1.attr, @@ -1132,6 +1158,8 @@ static struct attribute *most_dci_def_attrs[] = { &most_dci_attr_mep_eui48_hi.attr, &most_dci_attr_mep_eui48_mi.attr, &most_dci_attr_mep_eui48_lo.attr, + &most_dci_attr_arb_address.attr, + &most_dci_attr_arb_value.attr, NULL, }; -- cgit v0.10.2 From d5cfb0ff2e628ae07f7226e7cfe8684b7c186e0e Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Fri, 9 Sep 2016 15:25:36 +0200 Subject: staging: most: hdm-usb: use defined error codes This patch replaces return values with defined error codes to indicate an exception. Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index da47253..5d62d1b 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -801,17 +801,17 @@ static int hdm_update_netinfo(struct most_dev *mdev) if (!is_valid_ether_addr(mdev->hw_addr)) { if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_HI, &hi) < 0) { dev_err(dev, "Vendor request \"hw_addr_hi\" failed\n"); - return -1; + return -EFAULT; } if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_MI, &mi) < 0) { dev_err(dev, "Vendor request \"hw_addr_mid\" failed\n"); - return -1; + return -EFAULT; } if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_LO, &lo) < 0) { dev_err(dev, "Vendor request \"hw_addr_low\" failed\n"); - return -1; + return -EFAULT; } mutex_lock(&mdev->io_mutex); @@ -826,7 +826,7 @@ static int hdm_update_netinfo(struct most_dev *mdev) if (drci_rd_reg(usb_device, DRCI_REG_NI_STATE, &link) < 0) { dev_err(dev, "Vendor request \"link status\" failed\n"); - return -1; + return -EFAULT; } mutex_lock(&mdev->io_mutex); @@ -1116,7 +1116,7 @@ static ssize_t store_value(struct most_dci_obj *dci_obj, reg_addr = DRCI_REG_BASE + DRCI_COMMAND + ep * 16; val = 1; } else - return -EIO; + return -EFAULT; err = drci_wr_reg(dci_obj->usb_device, reg_addr, val); if (err < 0) -- cgit v0.10.2 From 1296bd62b0dcbdc8fd66908eb2d72dc4c3dba219 Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Fri, 9 Sep 2016 15:25:37 +0200 Subject: staging: most: Documentation: update ABI description This patch updates the ABI description file to reflect the latest changes of the interface. Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/Documentation/ABI/sysfs-class-most.txt b/drivers/staging/most/Documentation/ABI/sysfs-class-most.txt index 42ff0d8..48aa45a 100644 --- a/drivers/staging/most/Documentation/ABI/sysfs-class-most.txt +++ b/drivers/staging/most/Documentation/ABI/sysfs-class-most.txt @@ -51,6 +51,140 @@ Description: uses. Users: +What: /sys/class/most/mostcore/devices/<mdev>/dci +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + If the network interface controller is attached via USB, a dci + directory is created that allows applications to use the + controller's direct communication interface (DCI) to exchange + information. +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/dci/arb_address +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is used to set an arbitrary DCI register address an + application wants to read from or write to. +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/dci/arb_value +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is used to read from or write to the arbitrary DCI register + whose address is stored in arb_address. +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/dci/mep_eui48_hi +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is used to check and configure the MAC address. +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/dci/mep_eui48_lo +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is used to check and configure the MAC address. +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/dci/mep_eui48_mi +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is used to check and configure the MAC address. +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/dci/mep_filter +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is used to check and configure the MEP filter address. +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/dci/mep_hash0 +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is used to check and configure the MEP hash table. +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/dci/mep_hash1 +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is used to check and configure the MEP hash table. +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/dci/mep_hash2 +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is used to check and configure the MEP hash table. +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/dci/mep_hash3 +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is used to check and configure the MEP hash table. +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/dci/ni_state +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + Indicates the current network interface state. +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/dci/node_address +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + Indicates the current node address. +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/dci/node_position +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + Indicates the current node position. +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/dci/packet_bandwidth +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + Indicates the configured packet bandwidth. +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/dci/sync_ep +Date: June 2016 +KernelVersion: 4.9 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + Triggers the controller's synchronization process for a certain + endpoint. +Users: + What: /sys/class/most/mostcore/devices/<mdev>/<channel>/ Date: June 2015 KernelVersion: 4.3 -- cgit v0.10.2 From a747b42c8cd70bffe96862479aa1358553a0ab8f Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Fri, 9 Sep 2016 15:25:38 +0200 Subject: staging: most: hdm-usb: replace if-else branches with lookup table This patch removes a series of if-else-if conditions with a lookup table. Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index 5d62d1b..c82b8c1 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -1030,6 +1030,46 @@ static void most_dci_release(struct kobject *kobj) kfree(dci_obj); } +struct regs { + const char *name; + u16 reg; +}; + +static const struct regs ro_regs[] = { + { "ni_state", DRCI_REG_NI_STATE }, + { "packet_bandwidth", DRCI_REG_PACKET_BW }, + { "node_address", DRCI_REG_NODE_ADDR }, + { "node_position", DRCI_REG_NODE_POS }, +}; + +static const struct regs rw_regs[] = { + { "mep_filter", DRCI_REG_MEP_FILTER }, + { "mep_hash0", DRCI_REG_HASH_TBL0 }, + { "mep_hash1", DRCI_REG_HASH_TBL1 }, + { "mep_hash2", DRCI_REG_HASH_TBL2 }, + { "mep_hash3", DRCI_REG_HASH_TBL3 }, + { "mep_eui48_hi", DRCI_REG_HW_ADDR_HI }, + { "mep_eui48_mi", DRCI_REG_HW_ADDR_MI }, + { "mep_eui48_lo", DRCI_REG_HW_ADDR_LO }, +}; + +static int get_stat_reg_addr(const struct regs *regs, int size, + const char *name, u16 *reg_addr) +{ + int i; + + for (i = 0; i < size; i++) { + if (!strcmp(name, regs[i].name)) { + *reg_addr = regs[i].reg; + return 0; + } + } + return -EFAULT; +} + +#define get_static_reg_addr(regs, name, reg_addr) \ + get_stat_reg_addr(regs, ARRAY_SIZE(regs), name, reg_addr) + static ssize_t show_value(struct most_dci_obj *dci_obj, struct most_dci_attribute *attr, char *buf) { @@ -1039,34 +1079,10 @@ static ssize_t show_value(struct most_dci_obj *dci_obj, if (!strcmp(attr->attr.name, "arb_address")) return snprintf(buf, PAGE_SIZE, "%04x\n", dci_obj->reg_addr); - - if (!strcmp(attr->attr.name, "ni_state")) - reg_addr = DRCI_REG_NI_STATE; - else if (!strcmp(attr->attr.name, "packet_bandwidth")) - reg_addr = DRCI_REG_PACKET_BW; - else if (!strcmp(attr->attr.name, "node_address")) - reg_addr = DRCI_REG_NODE_ADDR; - else if (!strcmp(attr->attr.name, "node_position")) - reg_addr = DRCI_REG_NODE_POS; - else if (!strcmp(attr->attr.name, "mep_filter")) - reg_addr = DRCI_REG_MEP_FILTER; - else if (!strcmp(attr->attr.name, "mep_hash0")) - reg_addr = DRCI_REG_HASH_TBL0; - else if (!strcmp(attr->attr.name, "mep_hash1")) - reg_addr = DRCI_REG_HASH_TBL1; - else if (!strcmp(attr->attr.name, "mep_hash2")) - reg_addr = DRCI_REG_HASH_TBL2; - else if (!strcmp(attr->attr.name, "mep_hash3")) - reg_addr = DRCI_REG_HASH_TBL3; - else if (!strcmp(attr->attr.name, "mep_eui48_hi")) - reg_addr = DRCI_REG_HW_ADDR_HI; - else if (!strcmp(attr->attr.name, "mep_eui48_mi")) - reg_addr = DRCI_REG_HW_ADDR_MI; - else if (!strcmp(attr->attr.name, "mep_eui48_lo")) - reg_addr = DRCI_REG_HW_ADDR_LO; - else if (!strcmp(attr->attr.name, "arb_value")) + if (!strcmp(attr->attr.name, "arb_value")) reg_addr = dci_obj->reg_addr; - else + else if (get_static_reg_addr(ro_regs, attr->attr.name, ®_addr) && + get_static_reg_addr(rw_regs, attr->attr.name, ®_addr)) return -EIO; err = drci_rd_reg(dci_obj->usb_device, reg_addr, &tmp_val); @@ -1092,31 +1108,16 @@ static ssize_t store_value(struct most_dci_obj *dci_obj, dci_obj->reg_addr = val; return count; } - if (!strcmp(attr->attr.name, "mep_filter")) - reg_addr = DRCI_REG_MEP_FILTER; - else if (!strcmp(attr->attr.name, "mep_hash0")) - reg_addr = DRCI_REG_HASH_TBL0; - else if (!strcmp(attr->attr.name, "mep_hash1")) - reg_addr = DRCI_REG_HASH_TBL1; - else if (!strcmp(attr->attr.name, "mep_hash2")) - reg_addr = DRCI_REG_HASH_TBL2; - else if (!strcmp(attr->attr.name, "mep_hash3")) - reg_addr = DRCI_REG_HASH_TBL3; - else if (!strcmp(attr->attr.name, "mep_eui48_hi")) - reg_addr = DRCI_REG_HW_ADDR_HI; - else if (!strcmp(attr->attr.name, "mep_eui48_mi")) - reg_addr = DRCI_REG_HW_ADDR_MI; - else if (!strcmp(attr->attr.name, "mep_eui48_lo")) - reg_addr = DRCI_REG_HW_ADDR_LO; - else if (!strcmp(attr->attr.name, "arb_value")) + if (!strcmp(attr->attr.name, "arb_value")) { reg_addr = dci_obj->reg_addr; - else if (!strcmp(attr->attr.name, "sync_ep")) { + } else if (!strcmp(attr->attr.name, "sync_ep")) { u16 ep = val; reg_addr = DRCI_REG_BASE + DRCI_COMMAND + ep * 16; val = 1; - } else + } else if (get_static_reg_addr(ro_regs, attr->attr.name, ®_addr)) { return -EFAULT; + } err = drci_wr_reg(dci_obj->usb_device, reg_addr, val); if (err < 0) -- cgit v0.10.2 From a27cb25b64d9737df3e12f970ef9b5b638f7907f Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov <andrey.shvetsov@k2l.de> Date: Fri, 9 Sep 2016 15:25:39 +0200 Subject: staging: most: hdm-usb: unify returned errors This patch is needed to return the same error codes for the same error cases in the functions show_value() and store_value(). Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index c82b8c1..9c9a438 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -1083,7 +1083,7 @@ static ssize_t show_value(struct most_dci_obj *dci_obj, reg_addr = dci_obj->reg_addr; else if (get_static_reg_addr(ro_regs, attr->attr.name, ®_addr) && get_static_reg_addr(rw_regs, attr->attr.name, ®_addr)) - return -EIO; + return -EFAULT; err = drci_rd_reg(dci_obj->usb_device, reg_addr, &tmp_val); if (err < 0) -- cgit v0.10.2 From 0e9b9d08319ce195e12f8cc7860949ca88c7541a Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Fri, 9 Sep 2016 15:25:40 +0200 Subject: staging: most: hdm-usb: unify variable names This patch is needed to have the same variable name for the same quantity in the functions show_value() and store_value(). Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index 9c9a438..073a2aa 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -1073,7 +1073,7 @@ static int get_stat_reg_addr(const struct regs *regs, int size, static ssize_t show_value(struct most_dci_obj *dci_obj, struct most_dci_attribute *attr, char *buf) { - u16 tmp_val; + u16 val; u16 reg_addr; int err; @@ -1085,11 +1085,11 @@ static ssize_t show_value(struct most_dci_obj *dci_obj, get_static_reg_addr(rw_regs, attr->attr.name, ®_addr)) return -EFAULT; - err = drci_rd_reg(dci_obj->usb_device, reg_addr, &tmp_val); + err = drci_rd_reg(dci_obj->usb_device, reg_addr, &val); if (err < 0) return err; - return snprintf(buf, PAGE_SIZE, "%04x\n", tmp_val); + return snprintf(buf, PAGE_SIZE, "%04x\n", val); } static ssize_t store_value(struct most_dci_obj *dci_obj, -- cgit v0.10.2 From ac33fbb86578c5587eb5904e66b9ea3ec99c78aa Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov <andrey.shvetsov@k2l.de> Date: Fri, 9 Sep 2016 15:25:41 +0200 Subject: staging: most: hdm-usb: initialize variables by declaration This patch moves initialization of the variables to the declaration where possible. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index 073a2aa..f3264f1 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -326,10 +326,10 @@ static int hdm_poison_channel(struct most_interface *iface, int channel) static int hdm_add_padding(struct most_dev *mdev, int channel, struct mbo *mbo) { struct most_channel_config *conf = &mdev->conf[channel]; - unsigned int j, num_frames, frame_size; + unsigned int frame_size = get_stream_frame_size(conf); + unsigned int j, num_frames; u16 rd_addr, wr_addr; - frame_size = get_stream_frame_size(conf); if (!frame_size) return -EIO; num_frames = mbo->buffer_length / frame_size; @@ -363,10 +363,10 @@ static int hdm_add_padding(struct most_dev *mdev, int channel, struct mbo *mbo) static int hdm_remove_padding(struct most_dev *mdev, int channel, struct mbo *mbo) { - unsigned int j, num_frames, frame_size; struct most_channel_config *const conf = &mdev->conf[channel]; + unsigned int frame_size = get_stream_frame_size(conf); + unsigned int j, num_frames; - frame_size = get_stream_frame_size(conf); if (!frame_size) return -EIO; num_frames = mbo->processed_length / USB_MTU; @@ -1098,9 +1098,8 @@ static ssize_t store_value(struct most_dci_obj *dci_obj, { u16 val; u16 reg_addr; - int err; + int err = kstrtou16(buf, 16, &val); - err = kstrtou16(buf, 16, &val); if (err) return err; -- cgit v0.10.2 From 3e2880bee53b22b35df3cbbd58ffc84c2ba5c0e6 Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov <andrey.shvetsov@k2l.de> Date: Fri, 9 Sep 2016 15:25:42 +0200 Subject: staging: most: hdm-usb: remove reference to read function in write only macro This patch replaces the reference to the function show_value() with NULL in the macro MOST_DCI_WO_ATTR used for the write only attributes. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index f3264f1..b27544e 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -952,7 +952,7 @@ static struct usb_device_id usbid[] = { #define MOST_DCI_WO_ATTR(_name) \ struct most_dci_attribute most_dci_attr_##_name = \ - __ATTR(_name, S_IWUSR, show_value, store_value) + __ATTR(_name, S_IWUSR, NULL, store_value) /** * struct most_dci_attribute - to access the attributes of a dci object -- cgit v0.10.2 From 98a3c4d7ae9ad0ca8a8edbed5f37e559673aa3ac Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Fri, 9 Sep 2016 15:25:43 +0200 Subject: staging: most: hdm-usb: remove repeated access to structure This patch removes the repeated access to a struct member by assigning its value to a local variable once. Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index b27544e..5b27e96 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -1073,16 +1073,18 @@ static int get_stat_reg_addr(const struct regs *regs, int size, static ssize_t show_value(struct most_dci_obj *dci_obj, struct most_dci_attribute *attr, char *buf) { + const char *name = attr->attr.name; u16 val; u16 reg_addr; int err; - if (!strcmp(attr->attr.name, "arb_address")) + if (!strcmp(name, "arb_address")) return snprintf(buf, PAGE_SIZE, "%04x\n", dci_obj->reg_addr); - if (!strcmp(attr->attr.name, "arb_value")) + + if (!strcmp(name, "arb_value")) reg_addr = dci_obj->reg_addr; - else if (get_static_reg_addr(ro_regs, attr->attr.name, ®_addr) && - get_static_reg_addr(rw_regs, attr->attr.name, ®_addr)) + else if (get_static_reg_addr(ro_regs, name, ®_addr) && + get_static_reg_addr(rw_regs, name, ®_addr)) return -EFAULT; err = drci_rd_reg(dci_obj->usb_device, reg_addr, &val); @@ -1098,23 +1100,25 @@ static ssize_t store_value(struct most_dci_obj *dci_obj, { u16 val; u16 reg_addr; + const char *name = attr->attr.name; int err = kstrtou16(buf, 16, &val); if (err) return err; - if (!strcmp(attr->attr.name, "arb_address")) { + if (!strcmp(name, "arb_address")) { dci_obj->reg_addr = val; return count; } - if (!strcmp(attr->attr.name, "arb_value")) { + + if (!strcmp(name, "arb_value")) { reg_addr = dci_obj->reg_addr; - } else if (!strcmp(attr->attr.name, "sync_ep")) { + } else if (!strcmp(name, "sync_ep")) { u16 ep = val; reg_addr = DRCI_REG_BASE + DRCI_COMMAND + ep * 16; val = 1; - } else if (get_static_reg_addr(ro_regs, attr->attr.name, ®_addr)) { + } else if (get_static_reg_addr(ro_regs, name, ®_addr)) { return -EFAULT; } -- cgit v0.10.2 From 369e1b69c1a2ed9fb66cfd2a6fe2f7340c64cd49 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Date: Sun, 4 Sep 2016 20:30:18 +0530 Subject: staging: ks7010: return on failure On failure we were jumping to error_out0 where we were trying sdio_release_host() but at this point of execution we still have not done sdio_claim_host() and as a result host->claimed can still be 0. And if host->claimed is 0 then WARN_ON(!host->claimed) will give a warning. Moreover, if it is still not claimed then mmc_host->claim_cnt will be 0 and mmc_release_host() will do "if (--host->claim_cnt)" and thus the condition will become true. Lets just return the value on allocation failure instead of trying to release the host before claiming it. Signed-off-by: Sudip Mukherjee <sudip.mukherjee@codethink.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c index 47b69cb..7bcf1ea 100644 --- a/drivers/staging/ks7010/ks7010_sdio.c +++ b/drivers/staging/ks7010/ks7010_sdio.c @@ -776,10 +776,8 @@ static int ks7010_upload_firmware(struct ks_wlan_private *priv, /* buffer allocate */ rom_buf = kmalloc(ROM_BUFF_SIZE, GFP_KERNEL); - if (!rom_buf) { - rc = 3; - goto error_out0; - } + if (!rom_buf) + return 3; sdio_claim_host(card->func); -- cgit v0.10.2 From b80cfea24b02bcdc94cdbf67091d7b1c27ba6cd4 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Date: Sun, 4 Sep 2016 20:30:19 +0530 Subject: staging: ks7010: fix memory leak If the firmware request failed we were just returning but we missed freeing the memory and releasing the MMC Host. Signed-off-by: Sudip Mukherjee <sudip.mukherjee@codethink.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c index 7bcf1ea..86cdebe 100644 --- a/drivers/staging/ks7010/ks7010_sdio.c +++ b/drivers/staging/ks7010/ks7010_sdio.c @@ -791,7 +791,7 @@ static int ks7010_upload_firmware(struct ks_wlan_private *priv, retval = request_firmware(&fw_entry, ROM_FILE, &priv->ks_wlan_hw.sdio_card->func->dev); if (retval) - return retval; + goto error_out0; length = fw_entry->size; -- cgit v0.10.2 From f5dc9399c07ee141924bcdccfeeacd7597a44cfe Mon Sep 17 00:00:00 2001 From: Hariharan R <hariharanrangasamy@gmail.com> Date: Mon, 5 Sep 2016 18:22:46 -0400 Subject: staging: ks7010: fix warning on return for void functions This patch fixes the checkpatch warning in ks7010_sdio.c 'void function return statements are not generally useful' Signed-off-by: Hariharan R <hariharanrangasamy@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c index 86cdebe..632253c 100644 --- a/drivers/staging/ks7010/ks7010_sdio.c +++ b/drivers/staging/ks7010/ks7010_sdio.c @@ -115,7 +115,6 @@ void ks_wlan_hw_sleep_doze_request(struct ks_wlan_private *priv) out: priv->sleep_mode = atomic_read(&priv->sleepstatus.status); - return; } void ks_wlan_hw_sleep_wakeup_request(struct ks_wlan_private *priv) @@ -146,7 +145,6 @@ void ks_wlan_hw_sleep_wakeup_request(struct ks_wlan_private *priv) out: priv->sleep_mode = atomic_read(&priv->sleepstatus.status); - return; } void ks_wlan_hw_wakeup_request(struct ks_wlan_private *priv) @@ -357,7 +355,6 @@ static void tx_device_task(void *dev) &priv->ks_wlan_hw.rw_wq, 0); } } - return; } int ks_wlan_hw_tx(struct ks_wlan_private *priv, void *p, unsigned long size, @@ -405,8 +402,6 @@ static void rx_event_task(unsigned long dev) tasklet_schedule(&priv->ks_wlan_hw.rx_bh_task); } } - - return; } static void ks_wlan_hw_rx(void *dev, uint16_t size) @@ -557,8 +552,6 @@ static void ks7010_rw_function(struct work_struct *work) err_out: sdio_release_host(priv->ks_wlan_hw.sdio_card->func); - - return; } static void ks_sdio_interrupt(struct sdio_func *func) @@ -666,7 +659,6 @@ static void ks_sdio_interrupt(struct sdio_func *func) intr_out: queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq, &priv->ks_wlan_hw.rw_wq, 0); - return; } static int trx_device_init(struct ks_wlan_private *priv) @@ -701,8 +693,6 @@ static void trx_device_exit(struct ks_wlan_private *priv) } tasklet_kill(&priv->ks_wlan_hw.rx_bh_task); - - return; } static int ks7010_sdio_update_index(struct ks_wlan_private *priv, u32 index) @@ -1208,7 +1198,6 @@ static void ks7010_sdio_remove(struct sdio_func *func) DPRINTK(1, "kfree()\n"); DPRINTK(5, " Bye !!\n"); - return; } static struct sdio_driver ks7010_sdio_driver = { -- cgit v0.10.2 From 8defffb20854500825162d336bdd183d2d218cf9 Mon Sep 17 00:00:00 2001 From: Colin Ian King <colin.king@canonical.com> Date: Wed, 7 Sep 2016 17:23:09 +0100 Subject: staging: ks7010: avoid dereferencing packet if it is null Updating tx_bytes from packet->len if packet is null will cause a null pointer dereference, so only update tx_bytes if it packet is not null. Signed-off-by: Colin Ian King <colin.king@canonical.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks_wlan_net.c b/drivers/staging/ks7010/ks_wlan_net.c index 1e21eb1..d69b4c9 100644 --- a/drivers/staging/ks7010/ks_wlan_net.c +++ b/drivers/staging/ks7010/ks_wlan_net.c @@ -3396,13 +3396,13 @@ void send_packet_complete(void *arg1, void *arg2) DPRINTK(3, "\n"); - priv->nstats.tx_bytes += packet->len; priv->nstats.tx_packets++; if (netif_queue_stopped(priv->net_dev)) netif_wake_queue(priv->net_dev); if (packet) { + priv->nstats.tx_bytes += packet->len; dev_kfree_skb(packet); packet = NULL; } -- cgit v0.10.2 From aeaf5d86faa5d8c64674465da544c26c97e9404a Mon Sep 17 00:00:00 2001 From: Colin Ian King <colin.king@canonical.com> Date: Fri, 9 Sep 2016 16:56:38 +0100 Subject: staging: ks7010: fix two memory leaks on error return path On the error case where there is an invalid MAC address there is memory leak on packet and pp on the error return. Free these first before returning to fix the leak. Signed-off-by: Colin Ian King <colin.king@canonical.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c index c5fc31c..e09df360 100644 --- a/drivers/staging/ks7010/ks_hostif.c +++ b/drivers/staging/ks7010/ks_hostif.c @@ -1196,6 +1196,8 @@ int hostif_data_request(struct ks_wlan_private *priv, struct sk_buff *packet) DPRINTK(1, "ethernet->h_source=%02X:%02X:%02X:%02X:%02X:%02X\n", eth->h_source[0], eth->h_source[1], eth->h_source[2], eth->h_source[3], eth->h_source[4], eth->h_source[5]); + dev_kfree_skb(packet); + kfree(pp); return -3; } -- cgit v0.10.2 From d87f574d6923c546e7d0f75ce0581436376b98a6 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:27:57 +0700 Subject: staging: r8188eu: replace rtw_ieee80211_hdr with ieee80211_hdr rtw_ieee80211_hdr is duplicate of ieee80211_hdr. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index ed026f7..de29177 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -320,7 +320,7 @@ static void issue_beacon(struct adapter *padapter, int timeout_ms) struct xmit_frame *pmgntframe; struct pkt_attrib *pattrib; unsigned char *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; + struct ieee80211_hdr *pwlanhdr; __le16 *fctrl; unsigned int rate_len; struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); @@ -347,10 +347,10 @@ static void issue_beacon(struct adapter *padapter, int timeout_ms) memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + pwlanhdr = (struct ieee80211_hdr *)pframe; - fctrl = &(pwlanhdr->frame_ctl); + fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); @@ -461,7 +461,7 @@ static void issue_probersp(struct adapter *padapter, unsigned char *da) struct xmit_frame *pmgntframe; struct pkt_attrib *pattrib; unsigned char *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; + struct ieee80211_hdr *pwlanhdr; __le16 *fctrl; unsigned char *mac, *bssid; struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); @@ -488,12 +488,12 @@ static void issue_probersp(struct adapter *padapter, unsigned char *da) memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + pwlanhdr = (struct ieee80211_hdr *)pframe; mac = myid(&(padapter->eeprompriv)); bssid = cur_network->MacAddress; - fctrl = &(pwlanhdr->frame_ctl); + fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; memcpy(pwlanhdr->addr1, da, ETH_ALEN); memcpy(pwlanhdr->addr2, mac, ETH_ALEN); @@ -609,7 +609,7 @@ static int issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pss struct xmit_frame *pmgntframe; struct pkt_attrib *pattrib; unsigned char *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; + struct ieee80211_hdr *pwlanhdr; __le16 *fctrl; unsigned char *mac; unsigned char bssrate[NumRates]; @@ -633,11 +633,11 @@ static int issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pss memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + pwlanhdr = (struct ieee80211_hdr *)pframe; mac = myid(&(padapter->eeprompriv)); - fctrl = &(pwlanhdr->frame_ctl); + fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; if (da) { @@ -745,7 +745,7 @@ static void issue_auth(struct adapter *padapter, struct sta_info *psta, struct xmit_frame *pmgntframe; struct pkt_attrib *pattrib; unsigned char *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; + struct ieee80211_hdr *pwlanhdr; __le16 *fctrl; unsigned int val32; u16 val16; @@ -769,9 +769,9 @@ static void issue_auth(struct adapter *padapter, struct sta_info *psta, memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + pwlanhdr = (struct ieee80211_hdr *)pframe; - fctrl = &(pwlanhdr->frame_ctl); + fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); @@ -889,7 +889,7 @@ static void issue_asocrsp(struct adapter *padapter, unsigned short status, struct sta_info *pstat, int pkt_type) { struct xmit_frame *pmgntframe; - struct rtw_ieee80211_hdr *pwlanhdr; + struct ieee80211_hdr *pwlanhdr; struct pkt_attrib *pattrib; unsigned char *pbuf, *pframe; unsigned short val; @@ -916,9 +916,9 @@ static void issue_asocrsp(struct adapter *padapter, unsigned short status, memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + pwlanhdr = (struct ieee80211_hdr *)pframe; - fctrl = &(pwlanhdr->frame_ctl); + fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr, ETH_ALEN); @@ -1017,7 +1017,7 @@ static void issue_assocreq(struct adapter *padapter) struct xmit_frame *pmgntframe; struct pkt_attrib *pattrib; unsigned char *pframe, *p; - struct rtw_ieee80211_hdr *pwlanhdr; + struct ieee80211_hdr *pwlanhdr; __le16 *fctrl; unsigned int i, j, ie_len, index = 0; unsigned char rf_type, bssrate[NumRates], sta_bssrate[NumRates]; @@ -1040,9 +1040,9 @@ static void issue_assocreq(struct adapter *padapter) memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + pwlanhdr = (struct ieee80211_hdr *)pframe; - fctrl = &(pwlanhdr->frame_ctl); + fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; memcpy(pwlanhdr->addr1, pnetwork->MacAddress, ETH_ALEN); memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); @@ -1212,7 +1212,7 @@ static int _issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned struct xmit_frame *pmgntframe; struct pkt_attrib *pattrib; unsigned char *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; + struct ieee80211_hdr *pwlanhdr; __le16 *fctrl; struct xmit_priv *pxmitpriv; struct mlme_ext_priv *pmlmeext; @@ -1239,9 +1239,9 @@ static int _issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + pwlanhdr = (struct ieee80211_hdr *)pframe; - fctrl = &(pwlanhdr->frame_ctl); + fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) @@ -1332,7 +1332,7 @@ static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 struct xmit_frame *pmgntframe; struct pkt_attrib *pattrib; unsigned char *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; + struct ieee80211_hdr *pwlanhdr; __le16 *fctrl; unsigned short *qc; struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); @@ -1359,9 +1359,9 @@ static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + pwlanhdr = (struct ieee80211_hdr *)pframe; - fctrl = &(pwlanhdr->frame_ctl); + fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) @@ -1457,7 +1457,7 @@ static int _issue_deauth(struct adapter *padapter, unsigned char *da, unsigned s struct xmit_frame *pmgntframe; struct pkt_attrib *pattrib; unsigned char *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; + struct ieee80211_hdr *pwlanhdr; __le16 *fctrl; struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); @@ -1478,9 +1478,9 @@ static int _issue_deauth(struct adapter *padapter, unsigned char *da, unsigned s memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + pwlanhdr = (struct ieee80211_hdr *)pframe; - fctrl = &(pwlanhdr->frame_ctl); + fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; memcpy(pwlanhdr->addr1, da, ETH_ALEN); @@ -1573,7 +1573,7 @@ static void issue_action_BA(struct adapter *padapter, unsigned char *raddr, struct xmit_frame *pmgntframe; struct pkt_attrib *pattrib; u8 *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; + struct ieee80211_hdr *pwlanhdr; __le16 *fctrl; struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); @@ -1596,9 +1596,9 @@ static void issue_action_BA(struct adapter *padapter, unsigned char *raddr, memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + pwlanhdr = (struct ieee80211_hdr *)pframe; - fctrl = &(pwlanhdr->frame_ctl); + fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); @@ -1719,7 +1719,7 @@ static void issue_action_BSSCoexistPacket(struct adapter *padapter) struct xmit_frame *pmgntframe; struct pkt_attrib *pattrib; unsigned char *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; + struct ieee80211_hdr *pwlanhdr; __le16 *fctrl; struct wlan_network *pnetwork = NULL; struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); @@ -1755,9 +1755,9 @@ static void issue_action_BSSCoexistPacket(struct adapter *padapter) memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + pwlanhdr = (struct ieee80211_hdr *)pframe; - fctrl = &(pwlanhdr->frame_ctl); + fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; memcpy(pwlanhdr->addr1, cur_network->MacAddress, ETH_ALEN); diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c index 1e1b6d8..66c6629 100644 --- a/drivers/staging/rtl8188eu/core/rtw_xmit.c +++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c @@ -765,13 +765,13 @@ s32 rtw_make_wlanhdr(struct adapter *padapter, u8 *hdr, struct pkt_attrib *pattr { u16 *qc; - struct rtw_ieee80211_hdr *pwlanhdr = (struct rtw_ieee80211_hdr *)hdr; + struct ieee80211_hdr *pwlanhdr = (struct ieee80211_hdr *)hdr; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct qos_priv *pqospriv = &pmlmepriv->qospriv; u8 qos_option = false; int res = _SUCCESS; - __le16 *fctrl = &pwlanhdr->frame_ctl; + __le16 *fctrl = &pwlanhdr->frame_control; struct sta_info *psta; diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c index 2422c02..9d57a75 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c @@ -219,7 +219,7 @@ void rtl8188e_set_FwMediaStatus_cmd(struct adapter *adapt, __le16 mstatus_rpt) static void ConstructBeacon(struct adapter *adapt, u8 *pframe, u32 *pLength) { - struct rtw_ieee80211_hdr *pwlanhdr; + struct ieee80211_hdr *pwlanhdr; __le16 *fctrl; u32 rate_len, pktlen; struct mlme_ext_priv *pmlmeext = &(adapt->mlmeextpriv); @@ -227,9 +227,9 @@ static void ConstructBeacon(struct adapter *adapt, u8 *pframe, u32 *pLength) struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + pwlanhdr = (struct ieee80211_hdr *)pframe; - fctrl = &(pwlanhdr->frame_ctl); + fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); @@ -304,16 +304,16 @@ _ConstructBeacon: static void ConstructPSPoll(struct adapter *adapt, u8 *pframe, u32 *pLength) { - struct rtw_ieee80211_hdr *pwlanhdr; + struct ieee80211_hdr *pwlanhdr; struct mlme_ext_priv *pmlmeext = &(adapt->mlmeextpriv); struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); __le16 *fctrl; struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + pwlanhdr = (struct ieee80211_hdr *)pframe; /* Frame control. */ - fctrl = &(pwlanhdr->frame_ctl); + fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; SetPwrMgt(fctrl); SetFrameSubType(pframe, WIFI_PSPOLL); @@ -338,7 +338,7 @@ static void ConstructNullFunctionData(struct adapter *adapt, u8 *pframe, u8 bEosp, u8 bForcePowerSave) { - struct rtw_ieee80211_hdr *pwlanhdr; + struct ieee80211_hdr *pwlanhdr; __le16 *fctrl; u32 pktlen; struct mlme_priv *pmlmepriv = &adapt->mlmepriv; @@ -347,9 +347,9 @@ static void ConstructNullFunctionData(struct adapter *adapt, u8 *pframe, struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + pwlanhdr = (struct ieee80211_hdr *)pframe; - fctrl = &pwlanhdr->frame_ctl; + fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; if (bForcePowerSave) SetPwrMgt(fctrl); @@ -398,7 +398,7 @@ static void ConstructNullFunctionData(struct adapter *adapt, u8 *pframe, static void ConstructProbeRsp(struct adapter *adapt, u8 *pframe, u32 *pLength, u8 *StaAddr, bool bHideSSID) { - struct rtw_ieee80211_hdr *pwlanhdr; + struct ieee80211_hdr *pwlanhdr; __le16 *fctrl; u8 *mac, *bssid; u32 pktlen; @@ -406,12 +406,12 @@ static void ConstructProbeRsp(struct adapter *adapt, u8 *pframe, u32 *pLength, u struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + pwlanhdr = (struct ieee80211_hdr *)pframe; mac = myid(&(adapt->eeprompriv)); bssid = cur_network->MacAddress; - fctrl = &(pwlanhdr->frame_ctl); + fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN); memcpy(pwlanhdr->addr2, mac, ETH_ALEN); diff --git a/drivers/staging/rtl8188eu/include/ieee80211.h b/drivers/staging/rtl8188eu/include/ieee80211.h index 37a6f9d..cd9225d 100644 --- a/drivers/staging/rtl8188eu/include/ieee80211.h +++ b/drivers/staging/rtl8188eu/include/ieee80211.h @@ -291,16 +291,6 @@ struct sta_data { /* this is stolen from ipw2200 driver */ #define IEEE_IBSS_MAC_HASH_SIZE 31 -struct rtw_ieee80211_hdr { - __le16 frame_ctl; - __le16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - u16 seq_ctl; - u8 addr4[ETH_ALEN]; -} __packed; - struct rtw_ieee80211_hdr_3addr { __le16 frame_ctl; __le16 duration_id; -- cgit v0.10.2 From bbfe286b07d8282f4957dee692e85b3bd60de770 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:28:28 +0700 Subject: staging: r8188eu: replace rtw_ieee80211_hdr_3addr with ieee80211_hdr_3addr rtw_ieee80211_hdr_3addr is duplicate of ieee80211_hdr_3addr. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index de29177..b1f254c 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -361,8 +361,8 @@ static void issue_beacon(struct adapter *padapter, int timeout_ms) /* pmlmeext->mgnt_seq++; */ SetFrameSubType(pframe, WIFI_BEACON); - pframe += sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pframe += sizeof(struct ieee80211_hdr_3addr); + pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) { int len_diff; @@ -377,8 +377,8 @@ static void issue_beacon(struct adapter *padapter, int timeout_ms) ); pframe += (cur_network->IELength+len_diff); pattrib->pktlen += (cur_network->IELength+len_diff); - wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct rtw_ieee80211_hdr_3addr)+_BEACON_IE_OFFSET_, - pattrib->pktlen-sizeof(struct rtw_ieee80211_hdr_3addr)-_BEACON_IE_OFFSET_, NULL, &wps_ielen); + wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct ieee80211_hdr_3addr)+_BEACON_IE_OFFSET_, + pattrib->pktlen-sizeof(struct ieee80211_hdr_3addr)-_BEACON_IE_OFFSET_, NULL, &wps_ielen); if (wps_ie && wps_ielen > 0) rtw_get_wps_attr_content(wps_ie, wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL); if (sr != 0) @@ -503,7 +503,7 @@ static void issue_probersp(struct adapter *padapter, unsigned char *da) pmlmeext->mgnt_seq++; SetFrameSubType(fctrl, WIFI_PROBERSP); - pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); pattrib->pktlen = pattrib->hdrlen; pframe += pattrib->hdrlen; @@ -656,8 +656,8 @@ static int issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pss pmlmeext->mgnt_seq++; SetFrameSubType(pframe, WIFI_PROBEREQ); - pframe += sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pframe += sizeof(struct ieee80211_hdr_3addr); + pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); if (pssid) pframe = rtw_set_ie(pframe, _SSID_IE_, pssid->SsidLength, pssid->Ssid, &(pattrib->pktlen)); @@ -778,8 +778,8 @@ static void issue_auth(struct adapter *padapter, struct sta_info *psta, pmlmeext->mgnt_seq++; SetFrameSubType(pframe, WIFI_AUTH); - pframe += sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pframe += sizeof(struct ieee80211_hdr_3addr); + pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); if (psta) {/* for AP mode */ @@ -866,7 +866,7 @@ static void issue_auth(struct adapter *padapter, struct sta_info *psta, SetPrivacy(fctrl); - pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); pattrib->encrypt = _WEP40_; @@ -933,7 +933,7 @@ static void issue_asocrsp(struct adapter *padapter, unsigned short status, else return; - pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); pattrib->pktlen += pattrib->hdrlen; pframe += pattrib->hdrlen; @@ -1052,8 +1052,8 @@ static void issue_assocreq(struct adapter *padapter) pmlmeext->mgnt_seq++; SetFrameSubType(pframe, WIFI_ASSOCREQ); - pframe += sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pframe += sizeof(struct ieee80211_hdr_3addr); + pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); /* caps */ @@ -1260,8 +1260,8 @@ static int _issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned pmlmeext->mgnt_seq++; SetFrameSubType(pframe, WIFI_DATA_NULL); - pframe += sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pframe += sizeof(struct ieee80211_hdr_3addr); + pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); pattrib->last_txcmdsz = pattrib->pktlen; @@ -1491,8 +1491,8 @@ static int _issue_deauth(struct adapter *padapter, unsigned char *da, unsigned s pmlmeext->mgnt_seq++; SetFrameSubType(pframe, WIFI_DEAUTH); - pframe += sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pframe += sizeof(struct ieee80211_hdr_3addr); + pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); le_tmp = cpu_to_le16(reason); pframe = rtw_set_fixed_ie(pframe, _RSON_CODE_, &le_tmp, @@ -1609,8 +1609,8 @@ static void issue_action_BA(struct adapter *padapter, unsigned char *raddr, pmlmeext->mgnt_seq++; SetFrameSubType(pframe, WIFI_ACTION); - pframe += sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pframe += sizeof(struct ieee80211_hdr_3addr); + pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen)); @@ -1768,8 +1768,8 @@ static void issue_action_BSSCoexistPacket(struct adapter *padapter) pmlmeext->mgnt_seq++; SetFrameSubType(pframe, WIFI_ACTION); - pframe += sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pframe += sizeof(struct ieee80211_hdr_3addr); + pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen)); @@ -2052,7 +2052,7 @@ static u8 collect_bss_info(struct adapter *padapter, struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - len = packet_len - sizeof(struct rtw_ieee80211_hdr_3addr); + len = packet_len - sizeof(struct ieee80211_hdr_3addr); if (len > MAX_IE_SZ) return _FAIL; @@ -2082,7 +2082,7 @@ static u8 collect_bss_info(struct adapter *padapter, /* below is to copy the information element */ bssid->IELength = len; - memcpy(bssid->IEs, (pframe + sizeof(struct rtw_ieee80211_hdr_3addr)), bssid->IELength); + memcpy(bssid->IEs, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->IELength); /* get the signal strength in dBM.raw data */ bssid->Rssi = precv_frame->attrib.phy_info.recvpower; @@ -2624,7 +2624,7 @@ static unsigned int OnBeacon(struct adapter *padapter, } /* check the vendor of the assoc AP */ - pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe+sizeof(struct rtw_ieee80211_hdr_3addr), len-sizeof(struct rtw_ieee80211_hdr_3addr)); + pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe+sizeof(struct ieee80211_hdr_3addr), len-sizeof(struct ieee80211_hdr_3addr)); /* update TSF Value */ update_TSF(pmlmeext, pframe, len); @@ -3581,7 +3581,7 @@ static unsigned int on_action_spct(struct adapter *padapter, struct sta_info *psta = NULL; struct sta_priv *pstapriv = &padapter->stapriv; u8 *pframe = precv_frame->rx_data; - u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr); + u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr); u8 category; u8 action; @@ -3655,7 +3655,7 @@ static unsigned int OnAction_back(struct adapter *padapter, if (psta == NULL) return _SUCCESS; - frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr)); + frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr)); category = frame_body[0]; if (category == RTW_WLAN_CATEGORY_BACK) { /* representing Block Ack */ @@ -3742,7 +3742,7 @@ static unsigned int on_action_public_p2p(struct recv_frame *precv_frame) u8 *pframe = precv_frame->rx_data; u8 *frame_body; u8 dialogToken = 0; - frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr)); + frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr)); dialogToken = frame_body[7]; @@ -3756,7 +3756,7 @@ static unsigned int on_action_public_vendor(struct recv_frame *precv_frame) { unsigned int ret = _FAIL; u8 *pframe = precv_frame->rx_data; - u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr); + u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr); if (!memcmp(frame_body + 2, P2P_OUI, 4)) ret = on_action_public_p2p(precv_frame); @@ -3768,7 +3768,7 @@ static unsigned int on_action_public_default(struct recv_frame *precv_frame, u8 { unsigned int ret = _FAIL; u8 *pframe = precv_frame->rx_data; - u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr); + u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr); u8 token; token = frame_body[2]; @@ -3787,7 +3787,7 @@ static unsigned int on_action_public(struct adapter *padapter, { unsigned int ret = _FAIL; u8 *pframe = precv_frame->rx_data; - u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr); + u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr); u8 category, action; /* check RA matches or not */ @@ -3859,7 +3859,7 @@ static unsigned int OnAction(struct adapter *padapter, unsigned char *frame_body; u8 *pframe = precv_frame->rx_data; - frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr)); + frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr)); category = frame_body[0]; diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c index 2d115d7..a3b50cc 100644 --- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c @@ -881,7 +881,7 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len) if (is_client_associated_to_ap(Adapter) == false) return true; - len = packet_len - sizeof(struct rtw_ieee80211_hdr_3addr); + len = packet_len - sizeof(struct ieee80211_hdr_3addr); if (len > MAX_IE_SZ) { DBG_88E("%s IE too long for survey event\n", __func__); @@ -907,7 +907,7 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len) /* below is to copy the information element */ bssid->IELength = len; - memcpy(bssid->IEs, (pframe + sizeof(struct rtw_ieee80211_hdr_3addr)), bssid->IELength); + memcpy(bssid->IEs, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->IELength); /* check bw and channel offset */ /* parsing HT_CAP_IE */ @@ -1587,7 +1587,7 @@ void update_TSF(struct mlme_ext_priv *pmlmeext, u8 *pframe, uint len) u8 *pIE; __le32 *pbuf; - pIE = pframe + sizeof(struct rtw_ieee80211_hdr_3addr); + pIE = pframe + sizeof(struct ieee80211_hdr_3addr); pbuf = (__le32 *)pIE; pmlmeext->TSFValue = le32_to_cpu(*(pbuf+1)); diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c index 9d57a75..b2da4bf 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c @@ -239,8 +239,8 @@ static void ConstructBeacon(struct adapter *adapt, u8 *pframe, u32 *pLength) SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/); SetFrameSubType(pframe, WIFI_BEACON); - pframe += sizeof(struct rtw_ieee80211_hdr_3addr); - pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pframe += sizeof(struct ieee80211_hdr_3addr); + pktlen = sizeof(struct ieee80211_hdr_3addr); /* timestamp will be inserted by hardware */ pframe += 8; @@ -390,7 +390,7 @@ static void ConstructNullFunctionData(struct adapter *adapt, u8 *pframe, } else { SetFrameSubType(pframe, WIFI_DATA_NULL); - pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pktlen = sizeof(struct ieee80211_hdr_3addr); } *pLength = pktlen; @@ -420,7 +420,7 @@ static void ConstructProbeRsp(struct adapter *adapt, u8 *pframe, u32 *pLength, u SetSeqNum(pwlanhdr, 0); SetFrameSubType(fctrl, WIFI_PROBERSP); - pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pktlen = sizeof(struct ieee80211_hdr_3addr); pframe += pktlen; if (cur_network->IELength > MAX_IE_SZ) diff --git a/drivers/staging/rtl8188eu/include/ieee80211.h b/drivers/staging/rtl8188eu/include/ieee80211.h index cd9225d..b66fc5e 100644 --- a/drivers/staging/rtl8188eu/include/ieee80211.h +++ b/drivers/staging/rtl8188eu/include/ieee80211.h @@ -291,15 +291,6 @@ struct sta_data { /* this is stolen from ipw2200 driver */ #define IEEE_IBSS_MAC_HASH_SIZE 31 -struct rtw_ieee80211_hdr_3addr { - __le16 frame_ctl; - __le16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - u16 seq_ctl; -} __packed; - struct rtw_ieee80211_hdr_3addr_qos { __le16 frame_ctl; __le16 duration_id; -- cgit v0.10.2 From 5cd8396540b5f7ef7c3ac499e967dd4deb8e9930 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:28:56 +0700 Subject: staging: r8188eu: replace rtw_ieee80211_hdr_3addr_qos with ieee80211_qos_hdr rtw_ieee80211_hdr_3addr_qos is duplicate of ieee80211_qos_hdr. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index b1f254c..9544e55 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -1388,8 +1388,8 @@ static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 pmlmeext->mgnt_seq++; SetFrameSubType(pframe, WIFI_QOS_DATA_NULL); - pframe += sizeof(struct rtw_ieee80211_hdr_3addr_qos); - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr_qos); + pframe += sizeof(struct ieee80211_qos_hdr); + pattrib->pktlen = sizeof(struct ieee80211_qos_hdr); pattrib->last_txcmdsz = pattrib->pktlen; diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c index b2da4bf..40a0114 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c @@ -378,15 +378,15 @@ static void ConstructNullFunctionData(struct adapter *adapt, u8 *pframe, SetSeqNum(pwlanhdr, 0); if (bQoS) { - struct rtw_ieee80211_hdr_3addr_qos *pwlanqoshdr; + struct ieee80211_qos_hdr *pwlanqoshdr; SetFrameSubType(pframe, WIFI_QOS_DATA_NULL); - pwlanqoshdr = (struct rtw_ieee80211_hdr_3addr_qos *)pframe; - SetPriority(&pwlanqoshdr->qc, AC); - SetEOSP(&pwlanqoshdr->qc, bEosp); + pwlanqoshdr = (struct ieee80211_qos_hdr *)pframe; + SetPriority(&pwlanqoshdr->qos_ctrl, AC); + SetEOSP(&pwlanqoshdr->qos_ctrl, bEosp); - pktlen = sizeof(struct rtw_ieee80211_hdr_3addr_qos); + pktlen = sizeof(struct ieee80211_qos_hdr); } else { SetFrameSubType(pframe, WIFI_DATA_NULL); diff --git a/drivers/staging/rtl8188eu/include/ieee80211.h b/drivers/staging/rtl8188eu/include/ieee80211.h index b66fc5e..f84bc32 100644 --- a/drivers/staging/rtl8188eu/include/ieee80211.h +++ b/drivers/staging/rtl8188eu/include/ieee80211.h @@ -291,16 +291,6 @@ struct sta_data { /* this is stolen from ipw2200 driver */ #define IEEE_IBSS_MAC_HASH_SIZE 31 -struct rtw_ieee80211_hdr_3addr_qos { - __le16 frame_ctl; - __le16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - u16 seq_ctl; - u16 qc; -} __packed; - enum eap_type { EAP_PACKET = 0, EAPOL_START, -- cgit v0.10.2 From d94971aa97670d400371baef5d9d5cf6dc8ea2b5 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:29:14 +0700 Subject: staging: r8188eu: remove ieee80211_txb and tx_pending structures ieee80211_txb and tx_pending structures are not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/ieee80211.h b/drivers/staging/rtl8188eu/include/ieee80211.h index f84bc32..fc58621 100644 --- a/drivers/staging/rtl8188eu/include/ieee80211.h +++ b/drivers/staging/rtl8188eu/include/ieee80211.h @@ -540,16 +540,6 @@ struct ieee80211_snap_hdr { #define IEEE80211_DEFAULT_TX_ESSID "Penguin" #define IEEE80211_DEFAULT_BASIC_RATE 10 -struct ieee80211_txb { - u8 nr_frags; - u8 encrypted; - u16 reserved; - u16 frag_size; - u16 payload_size; - struct sk_buff *fragments[0]; -}; - - /* SWEEP TABLE ENTRIES NUMBER*/ #define MAX_SWEEP_TAB_ENTRIES 42 #define MAX_SWEEP_TAB_ENTRIES_PER_PACKET 7 @@ -647,11 +637,6 @@ static inline int is_broadcast_mac_addr(const u8 *addr) #define CFG_IEEE80211_RESERVE_FCS (1<<0) #define CFG_IEEE80211_COMPUTE_FCS (1<<1) -struct tx_pending { - int frag; - struct ieee80211_txb *txb; -}; - #define MAXTID 16 #define IEEE_A (1<<0) -- cgit v0.10.2 From 5cd3809eb92ec1164ffe5abf1391b6b4705f4eed Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:29:19 +0700 Subject: staging: r8188eu: remove bNotifyChannelChange member of struct adapter Default value of this variable used only to produce debug output. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c index a3b50cc..8e7605e 100644 --- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c @@ -341,9 +341,6 @@ void set_channel_bwmode(struct adapter *padapter, unsigned char channel, unsigne { u8 center_ch; - if (padapter->bNotifyChannelChange) - DBG_88E("[%s] ch = %d, offset = %d, bwmode = %d\n", __func__, channel, channel_offset, bwmode); - if ((bwmode == HT_CHANNEL_WIDTH_20) || (channel_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)) { /* SelectChannel(padapter, channel); */ diff --git a/drivers/staging/rtl8188eu/hal/phy.c b/drivers/staging/rtl8188eu/hal/phy.c index a83bbea9..0c2b54f 100644 --- a/drivers/staging/rtl8188eu/hal/phy.c +++ b/drivers/staging/rtl8188eu/hal/phy.c @@ -295,9 +295,6 @@ static void phy_sw_chnl_callback(struct adapter *adapt, u8 channel) u32 param1, param2; struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); - if (adapt->bNotifyChannelChange) - DBG_88E("[%s] ch = %d\n", __func__, channel); - phy_set_tx_power_level(adapt, channel); param1 = RF_CHNLBW; diff --git a/drivers/staging/rtl8188eu/include/drv_types.h b/drivers/staging/rtl8188eu/include/drv_types.h index 55506a7..384a09b 100644 --- a/drivers/staging/rtl8188eu/include/drv_types.h +++ b/drivers/staging/rtl8188eu/include/drv_types.h @@ -223,9 +223,6 @@ struct adapter { u8 bReadPortCancel; u8 bWritePortCancel; u8 bRxRSSIDisplay; - /* The driver will show up the desired channel number - * when this flag is 1. */ - u8 bNotifyChannelChange; struct mutex hw_init_mutex; diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c index c494845..23dbb6c 100644 --- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c +++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c @@ -821,7 +821,6 @@ static u8 rtw_init_default_value(struct adapter *padapter) padapter->bReadPortCancel = false; padapter->bWritePortCancel = false; padapter->bRxRSSIDisplay = 0; - padapter->bNotifyChannelChange = 0; return _SUCCESS; } -- cgit v0.10.2 From 2104905ac0c646a4d694e089f5d3aa9de1faadf4 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:29:40 +0700 Subject: staging: r8188eu: remove in_cta_test member of struct adapter bNotifyChannelChange does not changed after initialization. "if" branches with in_cta_test != 0 removed too. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 363f3a3..03c143f 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -1426,17 +1426,8 @@ static void SetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val) /* enable update TSF */ usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)&(~BIT(4))); } - if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) { - usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR)|RCR_CBSSID_BCN); - } else { - if (Adapter->in_cta_test) { - u32 v = usb_read32(Adapter, REG_RCR); - v &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);/* RCR_ADF */ - usb_write32(Adapter, REG_RCR, v); - } else { - usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR)|RCR_CBSSID_BCN); - } - } + + usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR)|RCR_CBSSID_BCN); } break; case HW_VAR_MLME_JOIN: @@ -1449,13 +1440,7 @@ static void SetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val) /* enable to rx data frame.Accept all data frame */ usb_write16(Adapter, REG_RXFLTMAP2, 0xFFFF); - if (Adapter->in_cta_test) { - u32 v = usb_read32(Adapter, REG_RCR); - v &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);/* RCR_ADF */ - usb_write32(Adapter, REG_RCR, v); - } else { - usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR)|RCR_CBSSID_DATA|RCR_CBSSID_BCN); - } + usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR)|RCR_CBSSID_DATA|RCR_CBSSID_BCN); if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) RetryLimit = (haldata->CustomerID == RT_CID_CCX) ? 7 : 48; diff --git a/drivers/staging/rtl8188eu/include/drv_types.h b/drivers/staging/rtl8188eu/include/drv_types.h index 384a09b..e5def33 100644 --- a/drivers/staging/rtl8188eu/include/drv_types.h +++ b/drivers/staging/rtl8188eu/include/drv_types.h @@ -229,8 +229,6 @@ struct adapter { spinlock_t br_ext_lock; u8 fix_rate; - - unsigned char in_cta_test; }; #define adapter_to_dvobj(adapter) (adapter->dvobj) -- cgit v0.10.2 From ca9e5b3e658915fcc6c554ff19c6a059e91e7d3c Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:29:50 +0700 Subject: staging: r8188eu: remove br_ext_lock and fix_rate members of struct adapter br_ext_lock and fix_rate are not used after initialization. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c index 81f2931..a37dc29 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c @@ -139,7 +139,6 @@ void rtl8188e_InitHalDm(struct adapter *Adapter) pdmpriv->DMFlag = DYNAMIC_FUNC_DISABLE; Update_ODM_ComInfo_88E(Adapter); ODM_DMInit(dm_odm); - Adapter->fix_rate = 0xFF; } void rtl8188e_HalDmWatchDog(struct adapter *Adapter) diff --git a/drivers/staging/rtl8188eu/include/drv_types.h b/drivers/staging/rtl8188eu/include/drv_types.h index e5def33..0279eaf 100644 --- a/drivers/staging/rtl8188eu/include/drv_types.h +++ b/drivers/staging/rtl8188eu/include/drv_types.h @@ -225,10 +225,6 @@ struct adapter { u8 bRxRSSIDisplay; struct mutex hw_init_mutex; - - spinlock_t br_ext_lock; - - u8 fix_rate; }; #define adapter_to_dvobj(adapter) (adapter->dvobj) diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c index 23dbb6c..20eca02 100644 --- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c +++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c @@ -911,8 +911,6 @@ u8 rtw_init_drv_sw(struct adapter *padapter) rtw_hal_sreset_init(padapter); - spin_lock_init(&padapter->br_ext_lock); - exit: RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-rtw_init_drv_sw\n")); -- cgit v0.10.2 From 33dda29bd301ef0190d15b753aa93e1a0a50a1f4 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:29:56 +0700 Subject: staging: r8188eu: remove rereg_nd_name_priv member of struct adapter Only default value of rereg_nd_name_priv was used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/drv_types.h b/drivers/staging/rtl8188eu/include/drv_types.h index 0279eaf..246d0fc 100644 --- a/drivers/staging/rtl8188eu/include/drv_types.h +++ b/drivers/staging/rtl8188eu/include/drv_types.h @@ -205,14 +205,6 @@ struct adapter { struct net_device *pnetdev; struct net_device *pmondev; - /* used by rtw_rereg_nd_name related function */ - struct rereg_nd_name_data { - struct net_device *old_pnetdev; - char old_ifname[IFNAMSIZ]; - u8 old_ips_mode; - u8 old_bRegUseLed; - } rereg_nd_name_priv; - int bup; struct net_device_stats stats; struct iw_statistics iwstats; diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c index 20eca02..73cbfd3 100644 --- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c +++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c @@ -958,12 +958,6 @@ u8 rtw_free_drv_sw(struct adapter *padapter) RT_TRACE(_module_os_intfs_c_, _drv_info_, ("<== rtw_free_drv_sw\n")); - /* free the old_pnetdev */ - if (padapter->rereg_nd_name_priv.old_pnetdev) { - free_netdev(padapter->rereg_nd_name_priv.old_pnetdev); - padapter->rereg_nd_name_priv.old_pnetdev = NULL; - } - mutex_destroy(&padapter->hw_init_mutex); RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-rtw_free_drv_sw\n")); -- cgit v0.10.2 From 89f3b361586ddf0ecd8795ec1f84e4cea1b40d57 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:30:01 +0700 Subject: staging: r8188eu: remove evtThread member of struct adapter evtThread does not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/drv_types.h b/drivers/staging/rtl8188eu/include/drv_types.h index 246d0fc..e0bdd80 100644 --- a/drivers/staging/rtl8188eu/include/drv_types.h +++ b/drivers/staging/rtl8188eu/include/drv_types.h @@ -199,7 +199,6 @@ struct adapter { u8 hw_init_completed; void *cmdThread; - void *evtThread; void (*intf_start)(struct adapter *adapter); void (*intf_stop)(struct adapter *adapter); struct net_device *pnetdev; -- cgit v0.10.2 From 430fc0fa40ab5c0331608f6ca32eb267ff590c07 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:30:06 +0700 Subject: staging: r8188eu: remove rwdinfo member of struct adapter Only default value of wdinfo was used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c index a37dc29..f9ad01a 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c @@ -156,11 +156,6 @@ void rtl8188e_HalDmWatchDog(struct adapter *Adapter) rtw_hal_get_hwreg(Adapter, HW_VAR_FWLPS_RF_ON, (u8 *)(&fw_ps_awake)); - /* Fw is under p2p powersaving mode, driver should stop dynamic mechanism. */ - /* modifed by thomas. 2011.06.11. */ - if (Adapter->wdinfo.p2p_ps_mode) - fw_ps_awake = false; - /* ODM */ pmlmepriv = &Adapter->mlmepriv; diff --git a/drivers/staging/rtl8188eu/include/drv_types.h b/drivers/staging/rtl8188eu/include/drv_types.h index e0bdd80..1190e98 100644 --- a/drivers/staging/rtl8188eu/include/drv_types.h +++ b/drivers/staging/rtl8188eu/include/drv_types.h @@ -188,8 +188,6 @@ struct adapter { struct hostapd_priv *phostapdpriv; #endif - struct wifidirect_info wdinfo; - void *HalData; struct hal_ops HalFunc; -- cgit v0.10.2 From 329473af1b4015d5e2a2a64e7e030a01a985a146 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:30:10 +0700 Subject: staging: r8188eu: remove fw_ps_awake variable of rtl8188e_HalDmWatchDog function Value of the fw_ps_awake does not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c index f9ad01a..e717999 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c @@ -143,7 +143,6 @@ void rtl8188e_InitHalDm(struct adapter *Adapter) void rtl8188e_HalDmWatchDog(struct adapter *Adapter) { - bool fw_ps_awake = true; u8 hw_init_completed = false; struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter); struct mlme_priv *pmlmepriv = NULL; @@ -154,8 +153,6 @@ void rtl8188e_HalDmWatchDog(struct adapter *Adapter) if (!hw_init_completed) goto skip_dm; - rtw_hal_get_hwreg(Adapter, HW_VAR_FWLPS_RF_ON, (u8 *)(&fw_ps_awake)); - /* ODM */ pmlmepriv = &Adapter->mlmepriv; -- cgit v0.10.2 From bbd8a4584235c5492209d79ebcaa7c817585c1ba Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:30:15 +0700 Subject: staging: r8188eu: remove phostapdpriv member of struct adapter phostapdpriv does not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/drv_types.h b/drivers/staging/rtl8188eu/include/drv_types.h index 1190e98..32b4612 100644 --- a/drivers/staging/rtl8188eu/include/drv_types.h +++ b/drivers/staging/rtl8188eu/include/drv_types.h @@ -184,10 +184,6 @@ struct adapter { struct eeprom_priv eeprompriv; struct led_priv ledpriv; -#ifdef CONFIG_88EU_AP_MODE - struct hostapd_priv *phostapdpriv; -#endif - void *HalData; struct hal_ops HalFunc; -- cgit v0.10.2 From cf65514a6adcb3f6a30d4176687f14a8014b712b Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:30:19 +0700 Subject: staging: r8188eu: remove usb_vendor_req_buf member of dvobj_priv Memory allocation moved into usbctrl_vendorreq function. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/drv_types.h b/drivers/staging/rtl8188eu/include/drv_types.h index 32b4612..92807a4 100644 --- a/drivers/staging/rtl8188eu/include/drv_types.h +++ b/drivers/staging/rtl8188eu/include/drv_types.h @@ -157,8 +157,6 @@ struct dvobj_priv { int ep_num[5]; /* endpoint number */ struct mutex usb_vendor_req_mutex; - u8 *usb_vendor_req_buf; - struct usb_interface *pusbintf; struct usb_device *pusbdev; }; diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c index 7da3534..16effd7 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c @@ -107,13 +107,6 @@ static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf) pdvobjpriv->ishighspeed = false; mutex_init(&pdvobjpriv->usb_vendor_req_mutex); - pdvobjpriv->usb_vendor_req_buf = kzalloc(MAX_USB_IO_CTL_SIZE, GFP_KERNEL); - - if (!pdvobjpriv->usb_vendor_req_buf) { - usb_set_intfdata(usb_intf, NULL); - kfree(pdvobjpriv); - return NULL; - } usb_get_dev(pusbd); return pdvobjpriv; @@ -141,7 +134,6 @@ static void usb_dvobj_deinit(struct usb_interface *usb_intf) } } - kfree(dvobj->usb_vendor_req_buf); mutex_destroy(&dvobj->usb_vendor_req_mutex); kfree(dvobj); } diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c index ce1e1a1..abb476b 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c @@ -251,7 +251,7 @@ static int usbctrl_vendorreq(struct adapter *adapt, u8 request, u16 value, u16 i } /* Acquire IO memory for vendorreq */ - pIo_buf = dvobjpriv->usb_vendor_req_buf; + pIo_buf = kmalloc(MAX_USB_IO_CTL_SIZE, GFP_ATOMIC); if (pIo_buf == NULL) { DBG_88E("[%s] pIo_buf == NULL\n", __func__); @@ -303,6 +303,8 @@ static int usbctrl_vendorreq(struct adapter *adapt, u8 request, u16 value, u16 i if ((value >= FW_8188E_START_ADDRESS && value <= FW_8188E_END_ADDRESS) || status == len) break; } + kfree(pIo_buf); + release_mutex: mutex_unlock(&dvobjpriv->usb_vendor_req_mutex); exit: -- cgit v0.10.2 From 999266d87bb4025f18c169e5f9ce4f785797cecb Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:30:28 +0700 Subject: staging: r8188eu: remove ep_num member of dvobj_priv structure Value of the ep_num does not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/drv_types.h b/drivers/staging/rtl8188eu/include/drv_types.h index 92807a4..289f2aa 100644 --- a/drivers/staging/rtl8188eu/include/drv_types.h +++ b/drivers/staging/rtl8188eu/include/drv_types.h @@ -154,7 +154,6 @@ struct dvobj_priv { u8 ishighspeed; u8 RtNumInPipes; u8 RtNumOutPipes; - int ep_num[5]; /* endpoint number */ struct mutex usb_vendor_req_mutex; struct usb_interface *pusbintf; diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c index 16effd7..4a7a557 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c @@ -98,7 +98,6 @@ static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf) ep_num; pdvobjpriv->RtNumOutPipes++; } - pdvobjpriv->ep_num[i] = ep_num; } if (pusbd->speed == USB_SPEED_HIGH) -- cgit v0.10.2 From c672491969fae421f9de16877aa3a2257893558f Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:30:32 +0700 Subject: staging: r8188eu: remove nr_endpoint member of dvobj_priv structure nr_endpoint used as local variable. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/drv_types.h b/drivers/staging/rtl8188eu/include/drv_types.h index 289f2aa..997b92f 100644 --- a/drivers/staging/rtl8188eu/include/drv_types.h +++ b/drivers/staging/rtl8188eu/include/drv_types.h @@ -149,8 +149,6 @@ struct dvobj_priv { u8 Queue2Pipe[HW_QUEUE_ENTRY];/* for out pipe mapping */ /*-------- below is for USB INTERFACE --------*/ - - u8 nr_endpoint; u8 ishighspeed; u8 RtNumInPipes; u8 RtNumOutPipes; diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c index 4a7a557..900dd53 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c @@ -79,9 +79,8 @@ static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf) pdvobjpriv->NumInterfaces = pconf_desc->bNumInterfaces; pdvobjpriv->InterfaceNumber = piface_desc->bInterfaceNumber; - pdvobjpriv->nr_endpoint = piface_desc->bNumEndpoints; - for (i = 0; i < pdvobjpriv->nr_endpoint; i++) { + for (i = 0; i < piface_desc->bNumEndpoints; i++) { int ep_num; pendp_desc = &phost_iface->endpoint[i].desc; -- cgit v0.10.2 From 3bb0ef95fce03470124090442fc7d3fc5d6474ee Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:30:44 +0700 Subject: staging: r8188eu: remove some members of registry_priv structure some registry_priv members does not used after initialization. Module parameters corresponding to this members deleted too. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/drv_types.h b/drivers/staging/rtl8188eu/include/drv_types.h index 997b92f..7b56540 100644 --- a/drivers/staging/rtl8188eu/include/drv_types.h +++ b/drivers/staging/rtl8188eu/include/drv_types.h @@ -53,30 +53,17 @@ #define SPEC_DEV_ID_ASSIGN_IFNAME BIT(5) struct registry_priv { - u8 chip_version; - u8 rfintfs; - u8 lbkmode; - u8 hci; struct ndis_802_11_ssid ssid; - u8 network_mode; /* infra, ad-hoc, auto */ u8 channel;/* ad-hoc support requirement */ u8 wireless_mode;/* A, B, G, auto */ - u8 scan_mode;/* active, passive */ - u8 radio_enable; u8 preamble;/* long, short, auto */ u8 vrtl_carrier_sense;/* Enable, Disable, Auto */ u8 vcs_type;/* RTS/CTS, CTS-to-self */ u16 rts_thresh; u16 frag_thresh; - u8 adhoc_tx_pwr; - u8 soft_ap; u8 power_mgnt; u8 ips_mode; u8 smart_ps; - u8 long_retry_lmt; - u8 short_retry_lmt; - u16 busy_thresh; - u8 ack_policy; u8 mp_mode; u8 software_encrypt; u8 software_decrypt; @@ -84,11 +71,6 @@ struct registry_priv { /* UAPSD */ u8 wmm_enable; u8 uapsd_enable; - u8 uapsd_max_sp; - u8 uapsd_acbk_en; - u8 uapsd_acbe_en; - u8 uapsd_acvi_en; - u8 uapsd_acvo_en; struct wlan_bssid_ex dev_network; @@ -97,10 +79,6 @@ struct registry_priv { u8 ampdu_enable;/* for tx */ u8 rx_stbc; u8 ampdu_amsdu;/* A-MPDU Supports A-MSDU is permitted */ - u8 lowrate_two_xmit; - - u8 rf_config; - u8 low_power; u8 wifi_spec;/* !turbo_mode */ @@ -112,9 +90,6 @@ struct registry_priv { u8 usbss_enable;/* 0:disable,1:enable */ u8 hwpdn_mode;/* 0:disable,1:enable,2:decide by EFUSE config */ - u8 hwpwrp_detect;/* 0:disable,1:enable */ - - u8 hw_wps_pbc;/* 0:disable,1:enable */ u8 max_roaming_times; /* the max number driver will try */ diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c index 73cbfd3..6f9bf7c 100644 --- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c +++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c @@ -33,11 +33,7 @@ MODULE_VERSION(DRIVERVERSION); #define RTW_NOTCH_FILTER 0 /* 0:Disable, 1:Enable, */ /* module param defaults */ -static int rtw_chip_version; -static int rtw_rfintfs = HWPI; -static int rtw_lbkmode;/* RTL8712_AIR_TRX; */ /* Ndis802_11Infrastructure; infra, ad-hoc, auto */ -static int rtw_network_mode = Ndis802_11IBSS; static int rtw_channel = 1;/* ad-hoc support requirement */ static int rtw_wireless_mode = WIRELESS_11BG_24N; static int rtw_vrtl_carrier_sense = AUTO_VCS; @@ -45,9 +41,6 @@ static int rtw_vcs_type = RTS_CTS;/* */ static int rtw_rts_thresh = 2347;/* */ static int rtw_frag_thresh = 2346;/* */ static int rtw_preamble = PREAMBLE_LONG;/* long, short, auto */ -static int rtw_scan_mode = 1;/* active, passive */ -static int rtw_adhoc_tx_pwr = 1; -static int rtw_soft_ap; static int rtw_power_mgnt = 1; static int rtw_ips_mode = IPS_NORMAL; @@ -57,11 +50,6 @@ module_param(rtw_ips_mode, int, 0644); MODULE_PARM_DESC(rtw_ips_mode, "The default IPS mode"); static int rtw_debug = 1; -static int rtw_radio_enable = 1; -static int rtw_long_retry_lmt = 7; -static int rtw_short_retry_lmt = 7; -static int rtw_busy_thresh = 40; -static int rtw_ack_policy = NORMAL_ACK; static int rtw_software_encrypt; static int rtw_software_decrypt; @@ -70,11 +58,6 @@ static int rtw_acm_method;/* 0:By SW 1:By HW. */ static int rtw_wmm_enable = 1;/* default is set to enable the wmm. */ static int rtw_uapsd_enable; -static int rtw_uapsd_max_sp = NO_LIMIT; -static int rtw_uapsd_acbk_en; -static int rtw_uapsd_acbe_en; -static int rtw_uapsd_acvi_en; -static int rtw_uapsd_acvo_en; static int rtw_ht_enable = 1; /* 0 :disable, bit(0): enable 2.4g, bit(1): enable 5g */ @@ -89,11 +72,6 @@ static int rtw_ampdu_enable = 1;/* for enable tx_ampdu */ static int rtw_rx_stbc = 1; static int rtw_ampdu_amsdu;/* 0: disabled, 1:enabled, 2:auto */ -/* Use 2 path Tx to transmit MCS0~7 and legacy mode */ -static int rtw_lowrate_two_xmit = 1; - -static int rtw_rf_config = RF_819X_MAX_TYPE; /* auto */ -static int rtw_low_power; static int rtw_wifi_spec; static int rtw_channel_plan = RT_CHANNEL_DOMAIN_MAX; @@ -111,10 +89,6 @@ static int rtw_enusbss;/* 0:disable, 1:enable */ static int rtw_hwpdn_mode = 2;/* 0:disable, 1:enable, 2: by EFUSE config */ -static int rtw_hwpwrp_detect; /* HW power ping detect 0:disable , 1:enable */ - -static int rtw_hw_wps_pbc = 1; - int rtw_mc2u_disable; static int rtw_80211d; @@ -132,32 +106,22 @@ char *rtw_initmac; module_param(rtw_initmac, charp, 0644); module_param(rtw_channel_plan, int, 0644); -module_param(rtw_chip_version, int, 0644); -module_param(rtw_rfintfs, int, 0644); -module_param(rtw_lbkmode, int, 0644); -module_param(rtw_network_mode, int, 0644); module_param(rtw_channel, int, 0644); module_param(rtw_wmm_enable, int, 0644); module_param(rtw_vrtl_carrier_sense, int, 0644); module_param(rtw_vcs_type, int, 0644); -module_param(rtw_busy_thresh, int, 0644); module_param(rtw_ht_enable, int, 0644); module_param(rtw_cbw40_enable, int, 0644); module_param(rtw_ampdu_enable, int, 0644); module_param(rtw_rx_stbc, int, 0644); module_param(rtw_ampdu_amsdu, int, 0644); -module_param(rtw_lowrate_two_xmit, int, 0644); -module_param(rtw_rf_config, int, 0644); module_param(rtw_power_mgnt, int, 0644); module_param(rtw_smart_ps, int, 0644); -module_param(rtw_low_power, int, 0644); module_param(rtw_wifi_spec, int, 0644); module_param(rtw_antdiv_cfg, int, 0644); module_param(rtw_antdiv_type, int, 0644); module_param(rtw_enusbss, int, 0644); module_param(rtw_hwpdn_mode, int, 0644); -module_param(rtw_hwpwrp_detect, int, 0644); -module_param(rtw_hw_wps_pbc, int, 0644); static uint rtw_max_roaming_times = 2; module_param(rtw_max_roaming_times, uint, 0644); @@ -536,10 +500,6 @@ static void loadparam(struct adapter *padapter, struct net_device *pnetdev) struct registry_priv *registry_par = &padapter->registrypriv; GlobalDebugLevel = rtw_debug; - registry_par->chip_version = (u8)rtw_chip_version; - registry_par->rfintfs = (u8)rtw_rfintfs; - registry_par->lbkmode = (u8)rtw_lbkmode; - registry_par->network_mode = (u8)rtw_network_mode; memcpy(registry_par->ssid.Ssid, "ANY", 3); registry_par->ssid.SsidLength = 3; @@ -551,17 +511,9 @@ static void loadparam(struct adapter *padapter, struct net_device *pnetdev) registry_par->rts_thresh = (u16)rtw_rts_thresh; registry_par->frag_thresh = (u16)rtw_frag_thresh; registry_par->preamble = (u8)rtw_preamble; - registry_par->scan_mode = (u8)rtw_scan_mode; - registry_par->adhoc_tx_pwr = (u8)rtw_adhoc_tx_pwr; - registry_par->soft_ap = (u8)rtw_soft_ap; registry_par->smart_ps = (u8)rtw_smart_ps; registry_par->power_mgnt = (u8)rtw_power_mgnt; registry_par->ips_mode = (u8)rtw_ips_mode; - registry_par->radio_enable = (u8)rtw_radio_enable; - registry_par->long_retry_lmt = (u8)rtw_long_retry_lmt; - registry_par->short_retry_lmt = (u8)rtw_short_retry_lmt; - registry_par->busy_thresh = (u16)rtw_busy_thresh; - registry_par->ack_policy = (u8)rtw_ack_policy; registry_par->mp_mode = 0; registry_par->software_encrypt = (u8)rtw_software_encrypt; registry_par->software_decrypt = (u8)rtw_software_decrypt; @@ -570,28 +522,18 @@ static void loadparam(struct adapter *padapter, struct net_device *pnetdev) /* UAPSD */ registry_par->wmm_enable = (u8)rtw_wmm_enable; registry_par->uapsd_enable = (u8)rtw_uapsd_enable; - registry_par->uapsd_max_sp = (u8)rtw_uapsd_max_sp; - registry_par->uapsd_acbk_en = (u8)rtw_uapsd_acbk_en; - registry_par->uapsd_acbe_en = (u8)rtw_uapsd_acbe_en; - registry_par->uapsd_acvi_en = (u8)rtw_uapsd_acvi_en; - registry_par->uapsd_acvo_en = (u8)rtw_uapsd_acvo_en; registry_par->ht_enable = (u8)rtw_ht_enable; registry_par->cbw40_enable = (u8)rtw_cbw40_enable; registry_par->ampdu_enable = (u8)rtw_ampdu_enable; registry_par->rx_stbc = (u8)rtw_rx_stbc; registry_par->ampdu_amsdu = (u8)rtw_ampdu_amsdu; - registry_par->lowrate_two_xmit = (u8)rtw_lowrate_two_xmit; - registry_par->rf_config = (u8)rtw_rf_config; - registry_par->low_power = (u8)rtw_low_power; registry_par->wifi_spec = (u8)rtw_wifi_spec; registry_par->channel_plan = (u8)rtw_channel_plan; registry_par->accept_addba_req = true; registry_par->antdiv_cfg = (u8)rtw_antdiv_cfg; registry_par->antdiv_type = (u8)rtw_antdiv_type; registry_par->hwpdn_mode = (u8)rtw_hwpdn_mode; - registry_par->hwpwrp_detect = (u8)rtw_hwpwrp_detect; - registry_par->hw_wps_pbc = (u8)rtw_hw_wps_pbc; registry_par->max_roaming_times = (u8)rtw_max_roaming_times; -- cgit v0.10.2 From 1c23e99da5ce4c048836736cfda1cd2bdff90f7a Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:30:48 +0700 Subject: staging: r8188eu: remove p2p_* members from mlme_priv structure This members does not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c index 3562f11..bf722e7 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ap.c +++ b/drivers/staging/rtl8188eu/core/rtw_ap.c @@ -1827,9 +1827,6 @@ void start_ap_mode(struct adapter *padapter) pmlmepriv->wps_probe_resp_ie = NULL; pmlmepriv->wps_assoc_resp_ie = NULL; - pmlmepriv->p2p_beacon_ie = NULL; - pmlmepriv->p2p_probe_resp_ie = NULL; - /* for ACL */ INIT_LIST_HEAD(&(pacl_list->acl_node_q.queue)); pacl_list->num = 0; diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c index 4b63979..55ff6ee 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c @@ -100,12 +100,6 @@ void rtw_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv) rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_req_ie, &pmlmepriv->wps_probe_req_ie_len); rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_resp_ie, &pmlmepriv->wps_probe_resp_ie_len); rtw_free_mlme_ie_data(&pmlmepriv->wps_assoc_resp_ie, &pmlmepriv->wps_assoc_resp_ie_len); - - rtw_free_mlme_ie_data(&pmlmepriv->p2p_beacon_ie, &pmlmepriv->p2p_beacon_ie_len); - rtw_free_mlme_ie_data(&pmlmepriv->p2p_probe_req_ie, &pmlmepriv->p2p_probe_req_ie_len); - rtw_free_mlme_ie_data(&pmlmepriv->p2p_probe_resp_ie, &pmlmepriv->p2p_probe_resp_ie_len); - rtw_free_mlme_ie_data(&pmlmepriv->p2p_go_probe_resp_ie, &pmlmepriv->p2p_go_probe_resp_ie_len); - rtw_free_mlme_ie_data(&pmlmepriv->p2p_assoc_req_ie, &pmlmepriv->p2p_assoc_req_ie_len); } #else void rtw_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv) diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme.h b/drivers/staging/rtl8188eu/include/rtw_mlme.h index 5d8bce0..627dccc 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme.h @@ -387,17 +387,6 @@ struct mlme_priv { u32 wps_probe_resp_ie_len; u32 wps_assoc_resp_ie_len; - u8 *p2p_beacon_ie; - u8 *p2p_probe_req_ie; - u8 *p2p_probe_resp_ie; - u8 *p2p_go_probe_resp_ie; /* for GO */ - u8 *p2p_assoc_req_ie; - - u32 p2p_beacon_ie_len; - u32 p2p_probe_req_ie_len; - u32 p2p_probe_resp_ie_len; - u32 p2p_go_probe_resp_ie_len; /* for GO */ - u32 p2p_assoc_req_ie_len; spinlock_t bcn_update_lock; u8 update_bcn; #endif /* if defined (CONFIG_88EU_AP_MODE) */ -- cgit v0.10.2 From e015bae3d3b91aa5e1d70ab587a464fb81df4f94 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:30:52 +0700 Subject: staging: r8188eu: remove scan_start_time and assoc_by_rssi members from mlme_priv structure Value of this members does not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_cmd.c b/drivers/staging/rtl8188eu/core/rtw_cmd.c index c0af5ab..e87ab11 100644 --- a/drivers/staging/rtl8188eu/core/rtw_cmd.c +++ b/drivers/staging/rtl8188eu/core/rtw_cmd.c @@ -305,8 +305,6 @@ u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid, res = rtw_enqueue_cmd(pcmdpriv, ph2c); if (res == _SUCCESS) { - pmlmepriv->scan_start_time = jiffies; - mod_timer(&pmlmepriv->scan_to_timer, jiffies + msecs_to_jiffies(SCANNING_TIMEOUT)); diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme.h b/drivers/staging/rtl8188eu/include/rtw_mlme.h index 627dccc..552fd6d 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme.h @@ -318,10 +318,8 @@ struct mlme_priv { struct timer_list assoc_timer; uint assoc_by_bssid; - uint assoc_by_rssi; struct timer_list scan_to_timer; /* driver itself handles scan_timeout status. */ - u32 scan_start_time; /* used to evaluate the time spent in scanning */ struct qos_priv qospriv; -- cgit v0.10.2 From ec355ca54919469656728e91b3f45c88f0095a68 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:30:57 +0700 Subject: staging: r8188eu: remove num_of_scanned member of mlme_priv structure and corresponding to it code Value of this variabl does not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c index 55ff6ee..012fba8 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c @@ -52,8 +52,6 @@ int rtw_init_mlme_priv(struct adapter *padapter) _rtw_init_queue(&(pmlmepriv->free_bss_pool)); _rtw_init_queue(&(pmlmepriv->scanned_queue)); - set_scanned_network_val(pmlmepriv, 0); - memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid)); pbuf = vzalloc(MAX_BSS_CNT * (sizeof(struct wlan_network))); @@ -137,8 +135,6 @@ struct wlan_network *_rtw_alloc_network(struct mlme_priv *pmlmepriv) pnetwork->aid = 0; pnetwork->join_res = 0; - pmlmepriv->num_of_scanned++; - exit: spin_unlock_bh(&free_queue->lock); @@ -169,7 +165,6 @@ static void _rtw_free_network(struct mlme_priv *pmlmepriv, struct wlan_network * spin_lock_bh(&free_queue->lock); list_del_init(&(pnetwork->list)); list_add_tail(&(pnetwork->list), &(free_queue->queue)); - pmlmepriv->num_of_scanned--; spin_unlock_bh(&free_queue->lock); } @@ -183,7 +178,6 @@ void _rtw_free_network_nolock(struct mlme_priv *pmlmepriv, struct wlan_network * return; list_del_init(&(pnetwork->list)); list_add_tail(&(pnetwork->list), get_list_head(free_queue)); - pmlmepriv->num_of_scanned--; } /* @@ -726,7 +720,6 @@ static void free_scanqueue(struct mlme_priv *pmlmepriv) list_del_init(plist); list_add_tail(plist, &free_queue->queue); plist = ptemp; - pmlmepriv->num_of_scanned--; } spin_unlock_bh(&free_queue->lock); diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme.h b/drivers/staging/rtl8188eu/include/rtw_mlme.h index 552fd6d..4da445c 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme.h @@ -306,7 +306,6 @@ struct mlme_priv { struct __queue free_bss_pool; struct __queue scanned_queue; u8 *free_bss_buf; - u32 num_of_scanned; struct ndis_802_11_ssid assoc_ssid; u8 assoc_bssid[6]; @@ -487,27 +486,6 @@ static inline void clr_fwstate_ex(struct mlme_priv *pmlmepriv, int state) spin_unlock_bh(&pmlmepriv->lock); } -static inline void up_scanned_network(struct mlme_priv *pmlmepriv) -{ - spin_lock_bh(&pmlmepriv->lock); - pmlmepriv->num_of_scanned++; - spin_unlock_bh(&pmlmepriv->lock); -} - -static inline void down_scanned_network(struct mlme_priv *pmlmepriv) -{ - spin_lock_bh(&pmlmepriv->lock); - pmlmepriv->num_of_scanned--; - spin_unlock_bh(&pmlmepriv->lock); -} - -static inline void set_scanned_network_val(struct mlme_priv *pmlmepriv, int val) -{ - spin_lock_bh(&pmlmepriv->lock); - pmlmepriv->num_of_scanned = val; - spin_unlock_bh(&pmlmepriv->lock); -} - u16 rtw_get_capability(struct wlan_bssid_ex *bss); void rtw_update_scanned_network(struct adapter *adapter, struct wlan_bssid_ex *target); -- cgit v0.10.2 From 78d41b168d40513c29bce8384f44545a88259fa0 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:31:00 +0700 Subject: staging: r8188eu: remove not_indic_disco member of mlme_priv structure This member does not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme.h b/drivers/staging/rtl8188eu/include/rtw_mlme.h index 4da445c..9434b86 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme.h @@ -301,7 +301,6 @@ struct mlme_priv { u8 *nic_hdl; - u8 not_indic_disco; struct list_head *pscanned; struct __queue free_bss_pool; struct __queue scanned_queue; -- cgit v0.10.2 From cfb800828e5dbdd20f703d85a91f6bf026d08aec Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:31:06 +0700 Subject: staging: r8188eu: remove sizeof_priv member of rtw_netdev_priv_indicator sizeof_priv does not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/osdep_service.h b/drivers/staging/rtl8188eu/include/osdep_service.h index 6f6a8f8..00c4355 100644 --- a/drivers/staging/rtl8188eu/include/osdep_service.h +++ b/drivers/staging/rtl8188eu/include/osdep_service.h @@ -82,7 +82,6 @@ void _rtw_init_queue(struct __queue *pqueue); struct rtw_netdev_priv_indicator { void *priv; - u32 sizeof_priv; }; struct net_device *rtw_alloc_etherdev_with_old_priv(int sizeof_priv, void *old_priv); diff --git a/drivers/staging/rtl8188eu/os_dep/osdep_service.c b/drivers/staging/rtl8188eu/os_dep/osdep_service.c index 24d1774..4869cc7 100644 --- a/drivers/staging/rtl8188eu/os_dep/osdep_service.c +++ b/drivers/staging/rtl8188eu/os_dep/osdep_service.c @@ -73,7 +73,6 @@ struct net_device *rtw_alloc_etherdev_with_old_priv(int sizeof_priv, pnpi = netdev_priv(pnetdev); pnpi->priv = old_priv; - pnpi->sizeof_priv = sizeof_priv; RETURN: return pnetdev; -- cgit v0.10.2 From f8a1a236b7866c4cd5ce02530f3a2c3e666e4639 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:31:10 +0700 Subject: staging: r8188eu: remove sizeof_priv parameter of rtw_alloc_etherdev_with_old_priv function sizeof_priv does not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/osdep_service.h b/drivers/staging/rtl8188eu/include/osdep_service.h index 00c4355..2df2b65 100644 --- a/drivers/staging/rtl8188eu/include/osdep_service.h +++ b/drivers/staging/rtl8188eu/include/osdep_service.h @@ -83,8 +83,7 @@ void _rtw_init_queue(struct __queue *pqueue); struct rtw_netdev_priv_indicator { void *priv; }; -struct net_device *rtw_alloc_etherdev_with_old_priv(int sizeof_priv, - void *old_priv); +struct net_device *rtw_alloc_etherdev_with_old_priv(void *old_priv); #define rtw_netdev_priv(netdev) \ (((struct rtw_netdev_priv_indicator *)netdev_priv(netdev))->priv) diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c index 6f9bf7c..3b606ee 100644 --- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c +++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c @@ -674,7 +674,7 @@ struct net_device *rtw_init_netdev(struct adapter *old_padapter) RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+init_net_dev\n")); if (old_padapter != NULL) - pnetdev = rtw_alloc_etherdev_with_old_priv(sizeof(struct adapter), (void *)old_padapter); + pnetdev = rtw_alloc_etherdev_with_old_priv((void *)old_padapter); if (!pnetdev) return NULL; diff --git a/drivers/staging/rtl8188eu/os_dep/osdep_service.c b/drivers/staging/rtl8188eu/os_dep/osdep_service.c index 4869cc7..7cd2655 100644 --- a/drivers/staging/rtl8188eu/os_dep/osdep_service.c +++ b/drivers/staging/rtl8188eu/os_dep/osdep_service.c @@ -61,8 +61,7 @@ void _rtw_init_queue(struct __queue *pqueue) spin_lock_init(&(pqueue->lock)); } -struct net_device *rtw_alloc_etherdev_with_old_priv(int sizeof_priv, - void *old_priv) +struct net_device *rtw_alloc_etherdev_with_old_priv(void *old_priv) { struct net_device *pnetdev; struct rtw_netdev_priv_indicator *pnpi; -- cgit v0.10.2 From 3929667e897911f83ffdd2a1983673b886d6bbba Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:31:20 +0700 Subject: staging: r8188eu: remove do_queue_select function do_queue_select is simplest one-line function. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c index 66c6629..be7fe74 100644 --- a/drivers/staging/rtl8188eu/core/rtw_xmit.c +++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c @@ -1654,16 +1654,6 @@ u32 rtw_get_ff_hwaddr(struct xmit_frame *pxmitframe) return addr; } -static void do_queue_select(struct adapter *padapter, struct pkt_attrib *pattrib) -{ - u8 qsel; - - qsel = pattrib->priority; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("### do_queue_select priority=%d , qsel = %d\n", pattrib->priority, qsel)); - - pattrib->qsel = qsel; -} - /* * The main transmit(tx) entry * @@ -1696,7 +1686,7 @@ s32 rtw_xmit(struct adapter *padapter, struct sk_buff **ppkt) rtw_led_control(padapter, LED_CTL_TX); - do_queue_select(padapter, &pxmitframe->attrib); + pxmitframe->attrib.qsel = pxmitframe->attrib.priority; #ifdef CONFIG_88EU_AP_MODE spin_lock_bh(&pxmitpriv->lock); -- cgit v0.10.2 From 11c717427d60c618f33c8a24c893217c30a31472 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:31:25 +0700 Subject: staging: r8188eu: remove pxmitbuf parameter of rtl8188eu_xmitframe_complete function pxmitbuf always is NULL. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c index ec21d8c..88d1dade 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c @@ -424,11 +424,12 @@ static u32 xmitframe_need_length(struct xmit_frame *pxmitframe) return len; } -s32 rtl8188eu_xmitframe_complete(struct adapter *adapt, struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) +s32 rtl8188eu_xmitframe_complete(struct adapter *adapt, struct xmit_priv *pxmitpriv) { struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); struct xmit_frame *pxmitframe = NULL; struct xmit_frame *pfirstframe = NULL; + struct xmit_buf *pxmitbuf; /* aggregate variable */ struct hw_xmit *phwxmit; @@ -450,12 +451,9 @@ s32 rtl8188eu_xmitframe_complete(struct adapter *adapt, struct xmit_priv *pxmitp RT_TRACE(_module_rtl8192c_xmit_c_, _drv_info_, ("+xmitframe_complete\n")); - /* check xmitbuffer is ok */ - if (pxmitbuf == NULL) { - pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv); - if (pxmitbuf == NULL) - return false; - } + pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv); + if (pxmitbuf == NULL) + return false; /* 3 1. pick up first frame */ rtw_free_xmitframe(pxmitpriv, pxmitframe); diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h b/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h index 65a63df..97942c5 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h @@ -160,8 +160,7 @@ s32 rtl8188eu_xmit_buf_handler(struct adapter *padapter); #define hal_xmit_handler rtl8188eu_xmit_buf_handler void rtl8188eu_xmit_tasklet(void *priv); s32 rtl8188eu_xmitframe_complete(struct adapter *padapter, - struct xmit_priv *pxmitpriv, - struct xmit_buf *pxmitbuf); + struct xmit_priv *pxmitpriv); void dump_txrpt_ccx_88e(void *buf); void handle_txrpt_ccx_88e(struct adapter *adapter, u8 *buf); diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c index abb476b..7f9fbe9 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c @@ -848,7 +848,7 @@ void rtl8188eu_xmit_tasklet(void *priv) break; } - ret = rtl8188eu_xmitframe_complete(adapt, pxmitpriv, NULL); + ret = rtl8188eu_xmitframe_complete(adapt, pxmitpriv); if (!ret) break; -- cgit v0.10.2 From 61a30f36e381e6cbac0e9d416c12c466c69f1769 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:31:31 +0700 Subject: staging: r8188eu: rename rtl8188eu_mgnt_xmit to rtw_hal_mgnt_xmit And remove many one-line wrappers. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index 085f0fb..5745230 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -170,15 +170,6 @@ s32 rtw_hal_xmit(struct adapter *adapt, struct xmit_frame *pxmitframe) return false; } -s32 rtw_hal_mgnt_xmit(struct adapter *adapt, struct xmit_frame *pmgntframe) -{ - s32 ret = _FAIL; - - if (adapt->HalFunc.mgnt_xmit) - ret = adapt->HalFunc.mgnt_xmit(adapt, pmgntframe); - return ret; -} - s32 rtw_hal_init_xmit_priv(struct adapter *adapt) { if (adapt->HalFunc.init_xmit_priv) diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c index 88d1dade..48386d0 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c @@ -672,7 +672,7 @@ enqueue: return false; } -s32 rtl8188eu_mgnt_xmit(struct adapter *adapt, struct xmit_frame *pmgntframe) +s32 rtw_hal_mgnt_xmit(struct adapter *adapt, struct xmit_frame *pmgntframe) { struct xmit_priv *xmitpriv = &adapt->xmitpriv; diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 03c143f..a99d316 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -2088,7 +2088,6 @@ void rtl8188eu_set_hal_ops(struct adapter *adapt) halfunc->SetBeaconRelatedRegistersHandler = &SetBeaconRelatedRegisters8188EUsb; halfunc->hal_xmit = &rtl8188eu_hal_xmit; - halfunc->mgnt_xmit = &rtl8188eu_mgnt_xmit; rtl8188e_set_hal_ops(halfunc); } diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index eaf939b..bb61a0f 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -201,8 +201,6 @@ struct hal_ops { struct wlan_bssid_ex *src); s32 (*hal_xmit)(struct adapter *padapter, struct xmit_frame *pxmitframe); - s32 (*mgnt_xmit)(struct adapter *padapter, - struct xmit_frame *pmgntframe); u32 (*read_rfreg)(struct adapter *padapter, enum rf_radio_path eRFPath, u32 RegAddr, u32 BitMask); diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h b/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h index 97942c5..b9ebb66 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h @@ -155,7 +155,6 @@ void rtl8188e_fill_fake_txdesc(struct adapter *padapter, u8 *pDesc, u32 BufferLen, u8 IsPsPoll, u8 IsBTQosNull); s32 rtl8188eu_init_xmit_priv(struct adapter *padapter); s32 rtl8188eu_hal_xmit(struct adapter *padapter, struct xmit_frame *frame); -s32 rtl8188eu_mgnt_xmit(struct adapter *padapter, struct xmit_frame *frame); s32 rtl8188eu_xmit_buf_handler(struct adapter *padapter); #define hal_xmit_handler rtl8188eu_xmit_buf_handler void rtl8188eu_xmit_tasklet(void *priv); -- cgit v0.10.2 From b3a4942fbcaecf1f8e83aa88668a283c49c0c6d7 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:31:36 +0700 Subject: staging: r8188eu: rename pre_xmitframe to rtw_hal_xmit And remove many one-line wrappers. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index 5745230..18b43aa 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -162,14 +162,6 @@ u32 rtw_hal_inirp_deinit(struct adapter *adapt) return _FAIL; } -s32 rtw_hal_xmit(struct adapter *adapt, struct xmit_frame *pxmitframe) -{ - if (adapt->HalFunc.hal_xmit) - return adapt->HalFunc.hal_xmit(adapt, pxmitframe); - - return false; -} - s32 rtw_hal_init_xmit_priv(struct adapter *adapt) { if (adapt->HalFunc.init_xmit_priv) diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c index 48386d0..f2c8f7a 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c @@ -622,7 +622,7 @@ static s32 xmitframe_direct(struct adapter *adapt, struct xmit_frame *pxmitframe * true dump packet directly * false enqueue packet */ -static s32 pre_xmitframe(struct adapter *adapt, struct xmit_frame *pxmitframe) +s32 rtw_hal_xmit(struct adapter *adapt, struct xmit_frame *pxmitframe) { s32 res; struct xmit_buf *pxmitbuf = NULL; @@ -679,13 +679,3 @@ s32 rtw_hal_mgnt_xmit(struct adapter *adapt, struct xmit_frame *pmgntframe) rtl88eu_mon_xmit_hook(adapt->pmondev, pmgntframe, xmitpriv->frag_len); return rtw_dump_xframe(adapt, pmgntframe); } - -/* - * Return - * true dump packet directly ok - * false temporary can't transmit packets to hardware - */ -s32 rtl8188eu_hal_xmit(struct adapter *adapt, struct xmit_frame *pxmitframe) -{ - return pre_xmitframe(adapt, pxmitframe); -} diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index a99d316..f7ac68b 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -2087,7 +2087,5 @@ void rtl8188eu_set_hal_ops(struct adapter *adapt) halfunc->UpdateRAMaskHandler = &UpdateHalRAMask8188EUsb; halfunc->SetBeaconRelatedRegistersHandler = &SetBeaconRelatedRegisters8188EUsb; - halfunc->hal_xmit = &rtl8188eu_hal_xmit; - rtl8188e_set_hal_ops(halfunc); } diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index bb61a0f..5b882f6 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -199,8 +199,6 @@ struct hal_ops { void (*AntDivCompareHandler)(struct adapter *adapter, struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src); - s32 (*hal_xmit)(struct adapter *padapter, - struct xmit_frame *pxmitframe); u32 (*read_rfreg)(struct adapter *padapter, enum rf_radio_path eRFPath, u32 RegAddr, u32 BitMask); diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h b/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h index b9ebb66..66205b7 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h @@ -154,7 +154,6 @@ struct txrpt_ccx_88e { void rtl8188e_fill_fake_txdesc(struct adapter *padapter, u8 *pDesc, u32 BufferLen, u8 IsPsPoll, u8 IsBTQosNull); s32 rtl8188eu_init_xmit_priv(struct adapter *padapter); -s32 rtl8188eu_hal_xmit(struct adapter *padapter, struct xmit_frame *frame); s32 rtl8188eu_xmit_buf_handler(struct adapter *padapter); #define hal_xmit_handler rtl8188eu_xmit_buf_handler void rtl8188eu_xmit_tasklet(void *priv); -- cgit v0.10.2 From 0e1e385a18d1394a96fd2056ff603921d972961b Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:31:41 +0700 Subject: staging: r8188eu: rename SetBeaconRelatedRegisters8188EUsb to rtw_hal_bcn_related_reg_setting And remove many one-line wrappers. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index 18b43aa..514cbd1 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -243,12 +243,6 @@ void rtw_hal_dm_watchdog(struct adapter *adapt) adapt->HalFunc.hal_dm_watchdog(adapt); } -void rtw_hal_bcn_related_reg_setting(struct adapter *adapt) -{ - if (adapt->HalFunc.SetBeaconRelatedRegistersHandler) - adapt->HalFunc.SetBeaconRelatedRegistersHandler(adapt); -} - u8 rtw_hal_antdiv_before_linked(struct adapter *adapt) { if (adapt->HalFunc.AntDivBeforeLinkHandler) diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index f7ac68b..d64940a 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -1996,7 +1996,7 @@ static void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_l psta->init_rate = init_rate; } -static void SetBeaconRelatedRegisters8188EUsb(struct adapter *adapt) +void rtw_hal_bcn_related_reg_setting(struct adapter *adapt) { u32 value32; struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv; @@ -2085,7 +2085,6 @@ void rtl8188eu_set_hal_ops(struct adapter *adapt) halfunc->GetHalDefVarHandler = &GetHalDefVar8188EUsb; halfunc->UpdateRAMaskHandler = &UpdateHalRAMask8188EUsb; - halfunc->SetBeaconRelatedRegistersHandler = &SetBeaconRelatedRegisters8188EUsb; rtl8188e_set_hal_ops(halfunc); } diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index 5b882f6..188f584 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -190,7 +190,6 @@ struct hal_ops { void (*UpdateRAMaskHandler)(struct adapter *padapter, u32 mac_id, u8 rssi_level); - void (*SetBeaconRelatedRegistersHandler)(struct adapter *padapter); void (*Add_RateATid)(struct adapter *adapter, u32 bitmap, u8 arg, u8 rssi_level); -- cgit v0.10.2 From 90c69b7a1d964b591f663b44830da57a8bc30467 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:31:45 +0700 Subject: staging: r8188eu: remove UpdateRAMaskHandler member of hal_ops structure It is unnecessary wrapper for UpdateHalRAMask8188EUsb function. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index 514cbd1..cff9b1b 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -198,9 +198,7 @@ void rtw_hal_update_ra_mask(struct adapter *adapt, u32 mac_id, u8 rssi_level) add_RATid(adapt, psta, 0);/* todo: based on rssi_level*/ #endif } else { - if (adapt->HalFunc.UpdateRAMaskHandler) - adapt->HalFunc.UpdateRAMaskHandler(adapt, mac_id, - rssi_level); + UpdateHalRAMask8188EUsb(adapt, mac_id, rssi_level); } } diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index d64940a..841f691 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -1933,7 +1933,7 @@ GetHalDefVar8188EUsb( return bResult; } -static void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level) +void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level) { u8 init_rate = 0; u8 networkType, raid; @@ -2084,7 +2084,5 @@ void rtl8188eu_set_hal_ops(struct adapter *adapt) halfunc->GetHwRegHandler = &GetHwReg8188EU; halfunc->GetHalDefVarHandler = &GetHalDefVar8188EUsb; - halfunc->UpdateRAMaskHandler = &UpdateHalRAMask8188EUsb; - rtl8188e_set_hal_ops(halfunc); } diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index 188f584..c56f701 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -188,9 +188,6 @@ struct hal_ops { enum hal_odm_variable eVariable, void *pValue1, bool bSet); - void (*UpdateRAMaskHandler)(struct adapter *padapter, - u32 mac_id, u8 rssi_level); - void (*Add_RateATid)(struct adapter *adapter, u32 bitmap, u8 arg, u8 rssi_level); @@ -230,6 +227,7 @@ enum hardware_type { #define is_boot_from_eeprom(adapter) (adapter->eeprompriv.EepromOrEfuse) +void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level); void rtw_hal_def_value_init(struct adapter *padapter); void rtw_hal_free_data(struct adapter *padapter); -- cgit v0.10.2 From 359d96127fef2b2d3a2193244bc354e8cbe634c5 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:31:49 +0700 Subject: staging: r8188eu: rename GetHalDefVar8188EUsb to rtw_hal_get_def_var And remove many one-line wrappers. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index cff9b1b..1cc8674 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -126,14 +126,6 @@ void rtw_hal_get_hwreg(struct adapter *adapt, u8 variable, u8 *val) adapt->HalFunc.GetHwRegHandler(adapt, variable, val); } -u8 rtw_hal_get_def_var(struct adapter *adapt, - enum hal_def_variable var, void *val) -{ - if (adapt->HalFunc.GetHalDefVarHandler) - return adapt->HalFunc.GetHalDefVarHandler(adapt, var, val); - return _FAIL; -} - void rtw_hal_set_odm_var(struct adapter *adapt, enum hal_odm_variable var, void *val1, bool set) diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 841f691..6fa7158 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -1838,8 +1838,7 @@ static void GetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val) /* Description: */ /* Query setting of specified variable. */ /* */ -static u8 -GetHalDefVar8188EUsb( +u8 rtw_hal_get_def_var( struct adapter *Adapter, enum hal_def_variable eVariable, void *pValue @@ -2082,7 +2081,6 @@ void rtl8188eu_set_hal_ops(struct adapter *adapt) halfunc->SetHwRegHandler = &SetHwReg8188EU; halfunc->GetHwRegHandler = &GetHwReg8188EU; - halfunc->GetHalDefVarHandler = &GetHalDefVar8188EUsb; rtl8188e_set_hal_ops(halfunc); } diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index c56f701..5f89bdc 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -180,10 +180,6 @@ struct hal_ops { void (*GetHwRegHandler)(struct adapter *padapter, u8 variable, u8 *val); - u8 (*GetHalDefVarHandler)(struct adapter *padapter, - enum hal_def_variable eVariable, - void *pValue); - void (*SetHalODMVarHandler)(struct adapter *padapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet); -- cgit v0.10.2 From 385b452ca11d38cf3feac22847bde413debdaa4d Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:31:53 +0700 Subject: staging: r8188eu: rename GetHwReg8188EU to rtw_hal_get_hwreg And remove two one-line wrappers. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c index 012fba8..249568c 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c @@ -2019,7 +2019,7 @@ void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len) int i; u8 rf_type; - padapter->HalFunc.GetHwRegHandler(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type)); + rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type)); /* update the MCS rates */ for (i = 0; i < 16; i++) { diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index 1cc8674..041208c 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -120,12 +120,6 @@ void rtw_hal_set_hwreg(struct adapter *adapt, u8 variable, u8 *val) adapt->HalFunc.SetHwRegHandler(adapt, variable, val); } -void rtw_hal_get_hwreg(struct adapter *adapt, u8 variable, u8 *val) -{ - if (adapt->HalFunc.GetHwRegHandler) - adapt->HalFunc.GetHwRegHandler(adapt, variable, val); -} - void rtw_hal_set_odm_var(struct adapter *adapt, enum hal_odm_variable var, void *val1, bool set) diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 6fa7158..be5d068 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -1778,7 +1778,7 @@ static void SetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val) } } -static void GetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val) +void rtw_hal_get_hwreg(struct adapter *Adapter, u8 variable, u8 *val) { struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); struct odm_dm_struct *podmpriv = &haldata->odmpriv; @@ -2080,7 +2080,6 @@ void rtl8188eu_set_hal_ops(struct adapter *adapt) halfunc->read_adapter_info = &_ReadAdapterInfo8188EU; halfunc->SetHwRegHandler = &SetHwReg8188EU; - halfunc->GetHwRegHandler = &GetHwReg8188EU; rtl8188e_set_hal_ops(halfunc); } diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index 5f89bdc..89f3fb8 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -177,8 +177,6 @@ struct hal_ops { void (*SetHwRegHandler)(struct adapter *padapter, u8 variable, u8 *val); - void (*GetHwRegHandler)(struct adapter *padapter, u8 variable, - u8 *val); void (*SetHalODMVarHandler)(struct adapter *padapter, enum hal_odm_variable eVariable, -- cgit v0.10.2 From 655266d53882815371802972c3329cf9dc1bd95f Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:31:58 +0700 Subject: staging: r8188eu: rename SetHwReg8188EU to rtw_hal_set_hwreg And remove two one-line wrappers. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c index 8e7605e..2a65ac7 100644 --- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c @@ -1508,7 +1508,7 @@ void update_wireless_mode(struct adapter *padapter) SIFS_Timer = 0x0a0a0808;/* 0x0808 -> for CCK, 0x0a0a -> for OFDM */ /* change this value if having IOT issues. */ - padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_RESP_SIFS, (u8 *)&SIFS_Timer); + rtw_hal_set_hwreg(padapter, HW_VAR_RESP_SIFS, (u8 *)&SIFS_Timer); if (pmlmeext->cur_wireless_mode & WIRELESS_11B) update_mgnt_tx_rate(padapter, IEEE80211_CCK_RATE_1MB); diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index 041208c..373d788 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -114,12 +114,6 @@ uint rtw_hal_deinit(struct adapter *adapt) return status; } -void rtw_hal_set_hwreg(struct adapter *adapt, u8 variable, u8 *val) -{ - if (adapt->HalFunc.SetHwRegHandler) - adapt->HalFunc.SetHwRegHandler(adapt, variable, val); -} - void rtw_hal_set_odm_var(struct adapter *adapt, enum hal_odm_variable var, void *val1, bool set) diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index be5d068..4065416 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -1276,7 +1276,7 @@ static void hw_var_set_bcn_func(struct adapter *Adapter, u8 variable, u8 *val) usb_write8(Adapter, bcn_ctrl_reg, usb_read8(Adapter, bcn_ctrl_reg)&(~(EN_BCN_FUNCTION | EN_TXBCN_RPT))); } -static void SetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val) +void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) { struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); struct dm_priv *pdmpriv = &haldata->dmpriv; @@ -2079,7 +2079,5 @@ void rtl8188eu_set_hal_ops(struct adapter *adapt) halfunc->intf_chip_configure = &rtl8188eu_interface_configure; halfunc->read_adapter_info = &_ReadAdapterInfo8188EU; - halfunc->SetHwRegHandler = &SetHwReg8188EU; - rtl8188e_set_hal_ops(halfunc); } diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index 89f3fb8..5ab50ab 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -175,9 +175,6 @@ struct hal_ops { void (*hal_dm_watchdog)(struct adapter *padapter); - void (*SetHwRegHandler)(struct adapter *padapter, u8 variable, - u8 *val); - void (*SetHalODMVarHandler)(struct adapter *padapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet); -- cgit v0.10.2 From 61e0c324dce32d77b0c1bc5fc0d8d83d7b8b1bfd Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:32:01 +0700 Subject: staging: r8188eu: rename _ReadAdapterInfo8188EU to rtw_hal_read_chip_info And remove two one-line wrappers. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index 373d788..fc34f6e 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -25,12 +25,6 @@ void rtw_hal_chip_configure(struct adapter *adapt) adapt->HalFunc.intf_chip_configure(adapt); } -void rtw_hal_read_chip_info(struct adapter *adapt) -{ - if (adapt->HalFunc.read_adapter_info) - adapt->HalFunc.read_adapter_info(adapt); -} - void rtw_hal_read_chip_version(struct adapter *adapt) { if (adapt->HalFunc.read_chip_version) diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 4065416..8968df7 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -1137,7 +1137,7 @@ static void _ReadRFType(struct adapter *Adapter) haldata->rf_chip = RF_6052; } -static void _ReadAdapterInfo8188EU(struct adapter *Adapter) +void rtw_hal_read_chip_info(struct adapter *Adapter) { unsigned long start = jiffies; @@ -2077,7 +2077,6 @@ void rtl8188eu_set_hal_ops(struct adapter *adapt) halfunc->init_default_value = &rtl8188eu_init_default_value; halfunc->intf_chip_configure = &rtl8188eu_interface_configure; - halfunc->read_adapter_info = &_ReadAdapterInfo8188EU; rtl8188e_set_hal_ops(halfunc); } diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index 5ab50ab..a95f3e7 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -164,8 +164,6 @@ struct hal_ops { void (*intf_chip_configure)(struct adapter *padapter); - void (*read_adapter_info)(struct adapter *padapter); - s32 (*interrupt_handler)(struct adapter *padapter); void (*set_bwmode_handler)(struct adapter *padapter, -- cgit v0.10.2 From 7d962ca011c5f52bbd76a41d7fa026574aa7cb8c Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:32:06 +0700 Subject: staging: r8188eu: rename rtl8188eu_interface_configure to rtw_hal_chip_configure And remove two one-line wrappers. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index fc34f6e..214b978 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -19,12 +19,6 @@ #include <hal_intf.h> #include <usb_hal.h> -void rtw_hal_chip_configure(struct adapter *adapt) -{ - if (adapt->HalFunc.intf_chip_configure) - adapt->HalFunc.intf_chip_configure(adapt); -} - void rtw_hal_read_chip_version(struct adapter *adapt) { if (adapt->HalFunc.read_chip_version) diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 8968df7..ff4e95d 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -69,7 +69,7 @@ static bool HalUsbSetQueuePipeMapping8188EUsb(struct adapter *adapt, u8 NumInPip return result; } -static void rtl8188eu_interface_configure(struct adapter *adapt) +void rtw_hal_chip_configure(struct adapter *adapt) { struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(adapt); @@ -2076,7 +2076,6 @@ void rtl8188eu_set_hal_ops(struct adapter *adapt) halfunc->DeInitSwLeds = &rtl8188eu_DeInitSwLeds; halfunc->init_default_value = &rtl8188eu_init_default_value; - halfunc->intf_chip_configure = &rtl8188eu_interface_configure; rtl8188e_set_hal_ops(halfunc); } diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index a95f3e7..dd3fc79 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -162,8 +162,6 @@ struct hal_ops { void (*init_default_value)(struct adapter *padapter); - void (*intf_chip_configure)(struct adapter *padapter); - s32 (*interrupt_handler)(struct adapter *padapter); void (*set_bwmode_handler)(struct adapter *padapter, -- cgit v0.10.2 From 2d91255a69eebe5ef8bc246fd89c261321aab974 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:32:11 +0700 Subject: staging: r8188eu: rename rtl8188eu_init_default_value to rtw_hal_def_value_init And remove two one-line wrappers. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index 214b978..805f3ad 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -25,12 +25,6 @@ void rtw_hal_read_chip_version(struct adapter *adapt) adapt->HalFunc.read_chip_version(adapt); } -void rtw_hal_def_value_init(struct adapter *adapt) -{ - if (adapt->HalFunc.init_default_value) - adapt->HalFunc.init_default_value(adapt); -} - void rtw_hal_free_data(struct adapter *adapt) { if (adapt->HalFunc.free_hal_data) diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index ff4e95d..bbc385e 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -2029,7 +2029,7 @@ void rtw_hal_bcn_related_reg_setting(struct adapter *adapt) usb_write8(adapt, bcn_ctrl_reg, usb_read8(adapt, bcn_ctrl_reg) | BIT(1)); } -static void rtl8188eu_init_default_value(struct adapter *adapt) +void rtw_hal_def_value_init(struct adapter *adapt) { struct hal_data_8188e *haldata; struct pwrctrl_priv *pwrctrlpriv; @@ -2075,7 +2075,5 @@ void rtl8188eu_set_hal_ops(struct adapter *adapt) halfunc->InitSwLeds = &rtl8188eu_InitSwLeds; halfunc->DeInitSwLeds = &rtl8188eu_DeInitSwLeds; - halfunc->init_default_value = &rtl8188eu_init_default_value; - rtl8188e_set_hal_ops(halfunc); } diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index dd3fc79..58b4ee3 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -160,8 +160,6 @@ struct hal_ops { void (*dm_init)(struct adapter *padapter); void (*read_chip_version)(struct adapter *padapter); - void (*init_default_value)(struct adapter *padapter); - s32 (*interrupt_handler)(struct adapter *padapter); void (*set_bwmode_handler)(struct adapter *padapter, -- cgit v0.10.2 From d435335fdf8015aec6c71fb2b6fc070e2cfc4aa4 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:32:16 +0700 Subject: staging: r8188eu: rename rtl8188eu_DeInitSwLeds to rtw_hal_sw_led_deinit And remove two one-line wrappers. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index 805f3ad..f03da1c 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -43,12 +43,6 @@ void rtw_hal_sw_led_init(struct adapter *adapt) adapt->HalFunc.InitSwLeds(adapt); } -void rtw_hal_sw_led_deinit(struct adapter *adapt) -{ - if (adapt->HalFunc.DeInitSwLeds) - adapt->HalFunc.DeInitSwLeds(adapt); -} - u32 rtw_hal_power_on(struct adapter *adapt) { if (adapt->HalFunc.hal_power_on) diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c index d9e677e..694ce59 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c @@ -80,7 +80,7 @@ void rtl8188eu_InitSwLeds(struct adapter *padapter) /* Description: */ /* DeInitialize all LED_819xUsb objects. */ -void rtl8188eu_DeInitSwLeds(struct adapter *padapter) +void rtw_hal_sw_led_deinit(struct adapter *padapter) { struct led_priv *ledpriv = &(padapter->ledpriv); diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index bbc385e..a4c6f06 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -2073,7 +2073,6 @@ void rtl8188eu_set_hal_ops(struct adapter *adapt) halfunc->init_recv_priv = &rtl8188eu_init_recv_priv; halfunc->free_recv_priv = &rtl8188eu_free_recv_priv; halfunc->InitSwLeds = &rtl8188eu_InitSwLeds; - halfunc->DeInitSwLeds = &rtl8188eu_DeInitSwLeds; rtl8188e_set_hal_ops(halfunc); } diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index 58b4ee3..cc8fadd 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -155,7 +155,6 @@ struct hal_ops { void (*free_recv_priv)(struct adapter *padapter); void (*InitSwLeds)(struct adapter *padapter); - void (*DeInitSwLeds)(struct adapter *padapter); void (*dm_init)(struct adapter *padapter); void (*read_chip_version)(struct adapter *padapter); diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_led.h b/drivers/staging/rtl8188eu/include/rtl8188e_led.h index fca6d8c..ca71a0f 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_led.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_led.h @@ -23,7 +23,6 @@ /* Interface to manipulate LED objects. */ /* */ void rtl8188eu_InitSwLeds(struct adapter *padapter); -void rtl8188eu_DeInitSwLeds(struct adapter *padapter); void SwLedOn(struct adapter *padapter, struct LED_871x *pLed); void SwLedOff(struct adapter *padapter, struct LED_871x *pLed); -- cgit v0.10.2 From 02d0de1f8c9efd0b84ba4ba6265053513ab9bb37 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:32:20 +0700 Subject: staging: r8188eu: rename rtl8188eu_InitSwLeds to rtw_hal_sw_led_init And remove two one-line wrappers. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index f03da1c..afab835 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -37,12 +37,6 @@ void rtw_hal_dm_init(struct adapter *adapt) adapt->HalFunc.dm_init(adapt); } -void rtw_hal_sw_led_init(struct adapter *adapt) -{ - if (adapt->HalFunc.InitSwLeds) - adapt->HalFunc.InitSwLeds(adapt); -} - u32 rtw_hal_power_on(struct adapter *adapt) { if (adapt->HalFunc.hal_power_on) diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c index 694ce59..becf5b5 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c @@ -66,7 +66,7 @@ exit: /* Description: */ /* Initialize all LED_871x objects. */ -void rtl8188eu_InitSwLeds(struct adapter *padapter) +void rtw_hal_sw_led_init(struct adapter *padapter) { struct led_priv *pledpriv = &(padapter->ledpriv); struct hal_data_8188e *haldata = GET_HAL_DATA(padapter); diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index a4c6f06..662281d 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -2072,7 +2072,6 @@ void rtl8188eu_set_hal_ops(struct adapter *adapt) halfunc->init_recv_priv = &rtl8188eu_init_recv_priv; halfunc->free_recv_priv = &rtl8188eu_free_recv_priv; - halfunc->InitSwLeds = &rtl8188eu_InitSwLeds; rtl8188e_set_hal_ops(halfunc); } diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index cc8fadd..6cddfd4 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -154,8 +154,6 @@ struct hal_ops { s32 (*init_recv_priv)(struct adapter *padapter); void (*free_recv_priv)(struct adapter *padapter); - void (*InitSwLeds)(struct adapter *padapter); - void (*dm_init)(struct adapter *padapter); void (*read_chip_version)(struct adapter *padapter); diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_led.h b/drivers/staging/rtl8188eu/include/rtl8188e_led.h index ca71a0f..d1ad6aa 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_led.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_led.h @@ -22,7 +22,6 @@ /* */ /* Interface to manipulate LED objects. */ /* */ -void rtl8188eu_InitSwLeds(struct adapter *padapter); void SwLedOn(struct adapter *padapter, struct LED_871x *pLed); void SwLedOff(struct adapter *padapter, struct LED_871x *pLed); -- cgit v0.10.2 From 67f7ada8dc1430820c9520127cda0a12bf9a960e Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:32:23 +0700 Subject: staging: r8188eu: rename rtl8188eu_free_recv_priv to rtw_hal_free_recv_priv And remove two one-line wrappers. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index afab835..2afc116 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -127,12 +127,6 @@ s32 rtw_hal_init_recv_priv(struct adapter *adapt) return _FAIL; } -void rtw_hal_free_recv_priv(struct adapter *adapt) -{ - if (adapt->HalFunc.free_recv_priv) - adapt->HalFunc.free_recv_priv(adapt); -} - void rtw_hal_update_ra_mask(struct adapter *adapt, u32 mac_id, u8 rssi_level) { struct mlme_priv *pmlmepriv = &(adapt->mlmepriv); diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c index 093a998..7e9b2dd 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c @@ -89,7 +89,7 @@ exit: return res; } -void rtl8188eu_free_recv_priv(struct adapter *padapter) +void rtw_hal_free_recv_priv(struct adapter *padapter) { int i; struct recv_buf *precvbuf; diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 662281d..66072e2 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -2071,7 +2071,6 @@ void rtl8188eu_set_hal_ops(struct adapter *adapt) halfunc->init_xmit_priv = &rtl8188eu_init_xmit_priv; halfunc->init_recv_priv = &rtl8188eu_init_recv_priv; - halfunc->free_recv_priv = &rtl8188eu_free_recv_priv; rtl8188e_set_hal_ops(halfunc); } diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index 6cddfd4..23a4738 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -152,7 +152,6 @@ struct hal_ops { s32 (*init_xmit_priv)(struct adapter *padapter); s32 (*init_recv_priv)(struct adapter *padapter); - void (*free_recv_priv)(struct adapter *padapter); void (*dm_init)(struct adapter *padapter); void (*read_chip_version)(struct adapter *padapter); diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_recv.h b/drivers/staging/rtl8188eu/include/rtl8188e_recv.h index 54048bc..623fe64 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_recv.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_recv.h @@ -52,7 +52,6 @@ enum rx_packet_type { #define INTERRUPT_MSG_FORMAT_LEN 60 s32 rtl8188eu_init_recv_priv(struct adapter *padapter); -void rtl8188eu_free_recv_priv(struct adapter *padapter); void rtl8188eu_recv_hdl(struct adapter *padapter, struct recv_buf *precvbuf); void rtl8188eu_recv_tasklet(void *priv); void rtl8188e_query_rx_phy_status(struct recv_frame *fr, struct phy_stat *phy); -- cgit v0.10.2 From 286fe9b30de1cbae28e275a7db6cda7a10e84303 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:32:26 +0700 Subject: staging: r8188eu: rename rtl8188eu_init_recv_priv to rtw_hal_init_recv_priv And remove two one-line wrappers. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index 2afc116..793b42f 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -119,14 +119,6 @@ s32 rtw_hal_init_xmit_priv(struct adapter *adapt) return _FAIL; } -s32 rtw_hal_init_recv_priv(struct adapter *adapt) -{ - if (adapt->HalFunc.init_recv_priv) - return adapt->HalFunc.init_recv_priv(adapt); - - return _FAIL; -} - void rtw_hal_update_ra_mask(struct adapter *adapt, u32 mac_id, u8 rssi_level) { struct mlme_priv *pmlmepriv = &(adapt->mlmepriv); diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c index 7e9b2dd..d0495a1 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c @@ -24,7 +24,7 @@ #include <rtl8188e_hal.h> -int rtl8188eu_init_recv_priv(struct adapter *padapter) +int rtw_hal_init_recv_priv(struct adapter *padapter) { struct recv_priv *precvpriv = &padapter->recvpriv; int i, res = _SUCCESS; diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 66072e2..bfdc372 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -2070,7 +2070,5 @@ void rtl8188eu_set_hal_ops(struct adapter *adapt) halfunc->init_xmit_priv = &rtl8188eu_init_xmit_priv; - halfunc->init_recv_priv = &rtl8188eu_init_recv_priv; - rtl8188e_set_hal_ops(halfunc); } diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index 23a4738..aed7b61 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -151,8 +151,6 @@ struct hal_ops { s32 (*init_xmit_priv)(struct adapter *padapter); - s32 (*init_recv_priv)(struct adapter *padapter); - void (*dm_init)(struct adapter *padapter); void (*read_chip_version)(struct adapter *padapter); @@ -244,7 +242,7 @@ s32 rtw_hal_mgnt_xmit(struct adapter *padapter, s32 rtw_hal_init_xmit_priv(struct adapter *padapter); -s32 rtw_hal_init_recv_priv(struct adapter *padapter); +int rtw_hal_init_recv_priv(struct adapter *padapter); void rtw_hal_free_recv_priv(struct adapter *padapter); void rtw_hal_update_ra_mask(struct adapter *padapter, u32 mac_id, u8 level); diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_recv.h b/drivers/staging/rtl8188eu/include/rtl8188e_recv.h index 623fe64..516c6d7 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_recv.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_recv.h @@ -51,7 +51,6 @@ enum rx_packet_type { }; #define INTERRUPT_MSG_FORMAT_LEN 60 -s32 rtl8188eu_init_recv_priv(struct adapter *padapter); void rtl8188eu_recv_hdl(struct adapter *padapter, struct recv_buf *precvbuf); void rtl8188eu_recv_tasklet(void *priv); void rtl8188e_query_rx_phy_status(struct recv_frame *fr, struct phy_stat *phy); -- cgit v0.10.2 From e582af5d4233326b63161f73f197105b41b28483 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:32:30 +0700 Subject: staging: r8188eu: rename rtl8188eu_init_xmit_priv to rtw_hal_init_xmit_priv And remove two one-line wrappers. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index 793b42f..b1ab8e8 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -112,13 +112,6 @@ u32 rtw_hal_inirp_deinit(struct adapter *adapt) return _FAIL; } -s32 rtw_hal_init_xmit_priv(struct adapter *adapt) -{ - if (adapt->HalFunc.init_xmit_priv) - return adapt->HalFunc.init_xmit_priv(adapt); - return _FAIL; -} - void rtw_hal_update_ra_mask(struct adapter *adapt, u32 mac_id, u8 rssi_level) { struct mlme_priv *pmlmepriv = &(adapt->mlmepriv); diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c index f2c8f7a..3e6f5ca 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c @@ -21,7 +21,7 @@ #include <usb_ops_linux.h> #include <rtl8188e_hal.h> -s32 rtl8188eu_init_xmit_priv(struct adapter *adapt) +s32 rtw_hal_init_xmit_priv(struct adapter *adapt) { struct xmit_priv *pxmitpriv = &adapt->xmitpriv; diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index bfdc372..d73f560 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -2068,7 +2068,5 @@ void rtl8188eu_set_hal_ops(struct adapter *adapt) halfunc->inirp_init = &rtl8188eu_inirp_init; halfunc->inirp_deinit = &rtl8188eu_inirp_deinit; - halfunc->init_xmit_priv = &rtl8188eu_init_xmit_priv; - rtl8188e_set_hal_ops(halfunc); } diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index aed7b61..f3c7e4c 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -149,8 +149,6 @@ struct hal_ops { u32 (*inirp_init)(struct adapter *padapter); u32 (*inirp_deinit)(struct adapter *padapter); - s32 (*init_xmit_priv)(struct adapter *padapter); - void (*dm_init)(struct adapter *padapter); void (*read_chip_version)(struct adapter *padapter); -- cgit v0.10.2 From 08d58ec80b22b1950773baea3ebb372a011e2d46 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:32:33 +0700 Subject: staging: r8188eu: rename usb_read_port_cancel to rtw_hal_inirp_deinit And remove three one-line wrappers. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index b1ab8e8..cd2869d 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -104,14 +104,6 @@ u32 rtw_hal_inirp_init(struct adapter *adapt) return rst; } -u32 rtw_hal_inirp_deinit(struct adapter *adapt) -{ - if (adapt->HalFunc.inirp_deinit) - return adapt->HalFunc.inirp_deinit(adapt); - - return _FAIL; -} - void rtw_hal_update_ra_mask(struct adapter *adapt, u32 mac_id, u8 rssi_level) { struct mlme_priv *pmlmepriv = &(adapt->mlmepriv); diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index d73f560..acb0628 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -1029,17 +1029,6 @@ exit: return status; } -static unsigned int rtl8188eu_inirp_deinit(struct adapter *Adapter) -{ - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("\n ===> usb_rx_deinit\n")); - - usb_read_port_cancel(Adapter); - - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("\n <=== usb_rx_deinit\n")); - - return _SUCCESS; -} - /* */ /* */ /* EEPROM/EFUSE Content Parsing */ @@ -2066,7 +2055,6 @@ void rtl8188eu_set_hal_ops(struct adapter *adapt) halfunc->hal_deinit = &rtl8188eu_hal_deinit; halfunc->inirp_init = &rtl8188eu_inirp_init; - halfunc->inirp_deinit = &rtl8188eu_inirp_deinit; rtl8188e_set_hal_ops(halfunc); } diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index f3c7e4c..c07f7f1 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -147,7 +147,6 @@ struct hal_ops { void (*free_hal_data)(struct adapter *padapter); u32 (*inirp_init)(struct adapter *padapter); - u32 (*inirp_deinit)(struct adapter *padapter); void (*dm_init)(struct adapter *padapter); void (*read_chip_version)(struct adapter *padapter); @@ -232,7 +231,7 @@ void rtw_hal_set_odm_var(struct adapter *padapter, bool bSet); u32 rtw_hal_inirp_init(struct adapter *padapter); -u32 rtw_hal_inirp_deinit(struct adapter *padapter); +void rtw_hal_inirp_deinit(struct adapter *padapter); s32 rtw_hal_xmit(struct adapter *padapter, struct xmit_frame *pxmitframe); s32 rtw_hal_mgnt_xmit(struct adapter *padapter, diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c index 7f9fbe9..9359cc7 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c @@ -527,7 +527,7 @@ u32 usb_read_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *rmem) return ret; } -void usb_read_port_cancel(struct adapter *padapter) +void rtw_hal_inirp_deinit(struct adapter *padapter) { int i; struct recv_buf *precvbuf; -- cgit v0.10.2 From 09ebc91ee200e03516feb1fd3e254a70192e72e1 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:32:36 +0700 Subject: staging: r8188eu: rename rtl8188eu_inirp_init to rtw_hal_inirp_init And remove two one-line wrappers. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index cd2869d..88c380a 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -93,17 +93,6 @@ void rtw_hal_set_odm_var(struct adapter *adapt, val1, set); } -u32 rtw_hal_inirp_init(struct adapter *adapt) -{ - u32 rst = _FAIL; - - if (adapt->HalFunc.inirp_init) - rst = adapt->HalFunc.inirp_init(adapt); - else - DBG_88E(" %s HalFunc.inirp_init is NULL!!!\n", __func__); - return rst; -} - void rtw_hal_update_ra_mask(struct adapter *adapt, u32 mac_id, u8 rssi_level) { struct mlme_priv *pmlmepriv = &(adapt->mlmepriv); diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index acb0628..3cfa5c2 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -994,7 +994,7 @@ static u32 rtl8188eu_hal_deinit(struct adapter *Adapter) return _SUCCESS; } -static unsigned int rtl8188eu_inirp_init(struct adapter *Adapter) +u32 rtw_hal_inirp_init(struct adapter *Adapter) { u8 i; struct recv_buf *precvbuf; @@ -2054,7 +2054,5 @@ void rtl8188eu_set_hal_ops(struct adapter *adapt) halfunc->hal_init = &rtl8188eu_hal_init; halfunc->hal_deinit = &rtl8188eu_hal_deinit; - halfunc->inirp_init = &rtl8188eu_inirp_init; - rtl8188e_set_hal_ops(halfunc); } diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index c07f7f1..c94a377 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -146,8 +146,6 @@ struct hal_ops { void (*free_hal_data)(struct adapter *padapter); - u32 (*inirp_init)(struct adapter *padapter); - void (*dm_init)(struct adapter *padapter); void (*read_chip_version)(struct adapter *padapter); -- cgit v0.10.2 From b1e120a598eb648c1e9589691e77ae9517dba5cf Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:32:40 +0700 Subject: staging: r8188eu: remove hal_deinit member of hal_ops structure It is unnecessary wrapper for rtl8188eu_hal_deinit function. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index 88c380a..cc71d85 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -74,7 +74,7 @@ uint rtw_hal_deinit(struct adapter *adapt) { uint status = _SUCCESS; - status = adapt->HalFunc.hal_deinit(adapt); + status = rtl8188eu_hal_deinit(adapt); if (status == _SUCCESS) adapt->hw_init_completed = false; diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 3cfa5c2..d4bbccf 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -972,7 +972,7 @@ static void rtl8192cu_hw_power_down(struct adapter *adapt) usb_write16(adapt, REG_APS_FSMCO, 0x8812); } -static u32 rtl8188eu_hal_deinit(struct adapter *Adapter) +u32 rtl8188eu_hal_deinit(struct adapter *Adapter) { DBG_88E("==> %s\n", __func__); @@ -2052,7 +2052,6 @@ void rtl8188eu_set_hal_ops(struct adapter *adapt) halfunc->hal_power_on = rtl8188eu_InitPowerOn; halfunc->hal_init = &rtl8188eu_hal_init; - halfunc->hal_deinit = &rtl8188eu_hal_deinit; rtl8188e_set_hal_ops(halfunc); } diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index c94a377..f9de294 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -142,7 +142,6 @@ enum hal_intf_ps_func { struct hal_ops { u32 (*hal_power_on)(struct adapter *padapter); u32 (*hal_init)(struct adapter *padapter); - u32 (*hal_deinit)(struct adapter *padapter); void (*free_hal_data)(struct adapter *padapter); @@ -202,6 +201,7 @@ enum hardware_type { #define is_boot_from_eeprom(adapter) (adapter->eeprompriv.EepromOrEfuse) void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level); +u32 rtl8188eu_hal_deinit(struct adapter *Adapter); void rtw_hal_def_value_init(struct adapter *padapter); void rtw_hal_free_data(struct adapter *padapter); -- cgit v0.10.2 From dbc1917aa2182225c35794ad41042bbef7ae2395 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:32:43 +0700 Subject: staging: r8188eu: remove hal_init member of hal_ops structure It is unnecessary wrapper for rtl8188eu_hal_init function. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index cc71d85..b239ffc 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -50,7 +50,7 @@ uint rtw_hal_init(struct adapter *adapt) adapt->hw_init_completed = false; - status = adapt->HalFunc.hal_init(adapt); + status = rtl8188eu_hal_init(adapt); if (status == _SUCCESS) { adapt->hw_init_completed = true; diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index d4bbccf..c5ea852 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -672,7 +672,7 @@ enum rt_rf_power_state RfOnOffDetect(struct adapter *adapt) return rfpowerstate; } /* HalDetectPwrDownMode */ -static u32 rtl8188eu_hal_init(struct adapter *Adapter) +u32 rtl8188eu_hal_init(struct adapter *Adapter) { u8 value8 = 0; u16 value16; @@ -2051,7 +2051,6 @@ void rtl8188eu_set_hal_ops(struct adapter *adapt) DBG_88E("cant not alloc memory for HAL DATA\n"); halfunc->hal_power_on = rtl8188eu_InitPowerOn; - halfunc->hal_init = &rtl8188eu_hal_init; rtl8188e_set_hal_ops(halfunc); } diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index f9de294..c4b2895 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -141,7 +141,6 @@ enum hal_intf_ps_func { struct hal_ops { u32 (*hal_power_on)(struct adapter *padapter); - u32 (*hal_init)(struct adapter *padapter); void (*free_hal_data)(struct adapter *padapter); @@ -202,6 +201,7 @@ enum hardware_type { void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level); u32 rtl8188eu_hal_deinit(struct adapter *Adapter); +u32 rtl8188eu_hal_init(struct adapter *Adapter); void rtw_hal_def_value_init(struct adapter *padapter); void rtw_hal_free_data(struct adapter *padapter); -- cgit v0.10.2 From ecee4947a206f97a18a90a0a2c9e90bb89c8a23c Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:32:47 +0700 Subject: staging: r8188eu: rename rtl8188eu_InitPowerOn to rtw_hal_power_on And remove many one-line wrappers. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index b239ffc..c8cfb5b 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -37,13 +37,6 @@ void rtw_hal_dm_init(struct adapter *adapt) adapt->HalFunc.dm_init(adapt); } -u32 rtw_hal_power_on(struct adapter *adapt) -{ - if (adapt->HalFunc.hal_power_on) - return adapt->HalFunc.hal_power_on(adapt); - return _FAIL; -} - uint rtw_hal_init(struct adapter *adapt) { uint status = _SUCCESS; diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index c5ea852..36abe9f 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -94,7 +94,7 @@ void rtw_hal_chip_configure(struct adapter *adapt) pdvobjpriv->RtNumInPipes, pdvobjpriv->RtNumOutPipes); } -static u32 rtl8188eu_InitPowerOn(struct adapter *adapt) +u32 rtw_hal_power_on(struct adapter *adapt) { u16 value16; /* HW Power on sequence */ @@ -702,7 +702,7 @@ u32 rtl8188eu_hal_init(struct adapter *Adapter) } HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_PW_ON); - status = rtl8188eu_InitPowerOn(Adapter); + 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; @@ -2050,7 +2050,5 @@ void rtl8188eu_set_hal_ops(struct adapter *adapt) if (!adapt->HalData) DBG_88E("cant not alloc memory for HAL DATA\n"); - halfunc->hal_power_on = rtl8188eu_InitPowerOn; - rtl8188e_set_hal_ops(halfunc); } diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index c4b2895..4d77984 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -140,8 +140,6 @@ enum hal_intf_ps_func { }; struct hal_ops { - u32 (*hal_power_on)(struct adapter *padapter); - void (*free_hal_data)(struct adapter *padapter); void (*dm_init)(struct adapter *padapter); -- cgit v0.10.2 From 91d0696299e5d083cc96cbd7d1315483211aff14 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:32:50 +0700 Subject: staging: r8188eu: rename hal_notch_filter_8188e to rtw_hal_notch_filter And remove many one-line wrappers. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index c8cfb5b..eb93008 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -165,12 +165,6 @@ void rtw_hal_sreset_init(struct adapter *adapt) adapt->HalFunc.sreset_init_value(adapt); } -void rtw_hal_notch_filter(struct adapter *adapter, bool enable) -{ - if (adapter->HalFunc.hal_notch_filter) - adapter->HalFunc.hal_notch_filter(adapter, enable); -} - void rtw_hal_reset_security_engine(struct adapter *adapter) { if (adapter->HalFunc.hal_reset_security_engine) diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c index 0b444fd..7ef47c1 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c @@ -175,7 +175,7 @@ static void rtl8188e_SetHalODMVar(struct adapter *Adapter, enum hal_odm_variable } } -static void hal_notch_filter_8188e(struct adapter *adapter, bool enable) +void rtw_hal_notch_filter(struct adapter *adapter, bool enable) { if (enable) { DBG_88E("Enable notch filter\n"); @@ -208,8 +208,6 @@ void rtl8188e_set_hal_ops(struct hal_ops *pHalFunc) pHalFunc->sreset_get_wifi_status = &sreset_get_wifi_status; pHalFunc->SetHalODMVarHandler = &rtl8188e_SetHalODMVar; - - pHalFunc->hal_notch_filter = &hal_notch_filter_8188e; } /* */ diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index 4d77984..429b0ac 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -172,7 +172,6 @@ struct hal_ops { void (*sreset_init_value)(struct adapter *padapter); u8 (*sreset_get_wifi_status)(struct adapter *padapter); - void (*hal_notch_filter)(struct adapter *adapter, bool enable); void (*hal_reset_security_engine)(struct adapter *adapter); }; -- cgit v0.10.2 From 685adf8aa3c008111b2808b335b64e26c13c9173 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:32:53 +0700 Subject: staging: r8188eu: rename rtl8188e_SetHalODMVar to rtw_hal_set_odm_var And remove many one-line wrappers. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index eb93008..a4696b08 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -77,15 +77,6 @@ uint rtw_hal_deinit(struct adapter *adapt) return status; } -void rtw_hal_set_odm_var(struct adapter *adapt, - enum hal_odm_variable var, void *val1, - bool set) -{ - if (adapt->HalFunc.SetHalODMVarHandler) - adapt->HalFunc.SetHalODMVarHandler(adapt, var, - val1, set); -} - void rtw_hal_update_ra_mask(struct adapter *adapt, u32 mac_id, u8 rssi_level) { struct mlme_priv *pmlmepriv = &(adapt->mlmepriv); diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c index 7ef47c1..10b679c 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c @@ -145,7 +145,7 @@ static void ReadChipVersion8188E(struct adapter *padapter) MSG_88E("RF_Type is %x!!\n", pHalData->rf_type); } -static void rtl8188e_SetHalODMVar(struct adapter *Adapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet) +void rtw_hal_set_odm_var(struct adapter *Adapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet) { struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter); struct odm_dm_struct *podmpriv = &pHalData->odmpriv; @@ -206,8 +206,6 @@ void rtl8188e_set_hal_ops(struct hal_ops *pHalFunc) pHalFunc->sreset_init_value = &sreset_init_value; pHalFunc->sreset_get_wifi_status = &sreset_get_wifi_status; - - pHalFunc->SetHalODMVarHandler = &rtl8188e_SetHalODMVar; } /* */ diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index 429b0ac..6cbe58f 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -154,10 +154,6 @@ struct hal_ops { void (*hal_dm_watchdog)(struct adapter *padapter); - void (*SetHalODMVarHandler)(struct adapter *padapter, - enum hal_odm_variable eVariable, - void *pValue1, bool bSet); - void (*Add_RateATid)(struct adapter *adapter, u32 bitmap, u8 arg, u8 rssi_level); -- cgit v0.10.2 From 35e224f3fd35627022b102fec4f133413b14bcde Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:32:57 +0700 Subject: staging: r8188eu: remove sreset_get_wifi_status of hal_ops structure Driver does not use it. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c index 10b679c..c123f4e 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c @@ -205,7 +205,6 @@ void rtl8188e_set_hal_ops(struct hal_ops *pHalFunc) pHalFunc->read_rfreg = &phy_query_rf_reg; pHalFunc->sreset_init_value = &sreset_init_value; - pHalFunc->sreset_get_wifi_status = &sreset_get_wifi_status; } /* */ diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index 6cbe58f..c1d4879 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -166,7 +166,6 @@ struct hal_ops { u32 BitMask); void (*sreset_init_value)(struct adapter *padapter); - u8 (*sreset_get_wifi_status)(struct adapter *padapter); void (*hal_reset_security_engine)(struct adapter *adapter); }; -- cgit v0.10.2 From 348526f75d175acbcd172fc9800894b4bd03d2dc Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:33:00 +0700 Subject: staging: r8188eu: rename sreset_init_value to rtw_hal_sreset_init And remove two one-line wrappers. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_sreset.c b/drivers/staging/rtl8188eu/core/rtw_sreset.c index 13a5bf4..5d631c5 100644 --- a/drivers/staging/rtl8188eu/core/rtw_sreset.c +++ b/drivers/staging/rtl8188eu/core/rtw_sreset.c @@ -16,7 +16,7 @@ #include <rtw_sreset.h> #include <usb_ops_linux.h> -void sreset_init_value(struct adapter *padapter) +void rtw_hal_sreset_init(struct adapter *padapter) { struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter); struct sreset_priv *psrtpriv = &pHalData->srestpriv; diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index a4696b08..adceade 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -150,12 +150,6 @@ void rtw_hal_antdiv_rssi_compared(struct adapter *adapt, adapt->HalFunc.AntDivCompareHandler(adapt, dst, src); } -void rtw_hal_sreset_init(struct adapter *adapt) -{ - if (adapt->HalFunc.sreset_init_value) - adapt->HalFunc.sreset_init_value(adapt); -} - void rtw_hal_reset_security_engine(struct adapter *adapter) { if (adapter->HalFunc.hal_reset_security_engine) diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c index c123f4e..ea46ea7 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c @@ -203,8 +203,6 @@ void rtl8188e_set_hal_ops(struct hal_ops *pHalFunc) pHalFunc->AntDivBeforeLinkHandler = &AntDivBeforeLink8188E; pHalFunc->AntDivCompareHandler = &AntDivCompare8188E; pHalFunc->read_rfreg = &phy_query_rf_reg; - - pHalFunc->sreset_init_value = &sreset_init_value; } /* */ diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index c1d4879..971fc62 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -165,8 +165,6 @@ struct hal_ops { enum rf_radio_path eRFPath, u32 RegAddr, u32 BitMask); - void (*sreset_init_value)(struct adapter *padapter); - void (*hal_reset_security_engine)(struct adapter *adapter); }; diff --git a/drivers/staging/rtl8188eu/include/rtw_sreset.h b/drivers/staging/rtl8188eu/include/rtw_sreset.h index ce027df..4c4ccd5 100644 --- a/drivers/staging/rtl8188eu/include/rtw_sreset.h +++ b/drivers/staging/rtl8188eu/include/rtw_sreset.h @@ -33,7 +33,6 @@ struct sreset_priv { #define WIFI_RX_HANG BIT(5) #define WIFI_IF_NOT_EXIST BIT(6) -void sreset_init_value(struct adapter *padapter); u8 sreset_get_wifi_status(struct adapter *padapter); void sreset_set_wifi_error_status(struct adapter *padapter, u32 status); -- cgit v0.10.2 From 76098bcb305557fc1a5a7e29510a4452f92f2f5b Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:33:05 +0700 Subject: staging: r8188eu: rename phy_query_rf_reg to rtw_hal_read_rfreg And remove two one-line wrappers. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index adceade..df1192e 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -104,17 +104,6 @@ void rtw_hal_add_ra_tid(struct adapter *adapt, u32 bitmap, u8 arg, rssi_level); } -u32 rtw_hal_read_rfreg(struct adapter *adapt, enum rf_radio_path rfpath, - u32 regaddr, u32 bitmask) -{ - u32 data = 0; - - if (adapt->HalFunc.read_rfreg) - data = adapt->HalFunc.read_rfreg(adapt, rfpath, regaddr, - bitmask); - return data; -} - void rtw_hal_set_bwmode(struct adapter *adapt, enum ht_channel_width bandwidth, u8 offset) { diff --git a/drivers/staging/rtl8188eu/hal/phy.c b/drivers/staging/rtl8188eu/hal/phy.c index 0c2b54f..2b66c6d 100644 --- a/drivers/staging/rtl8188eu/hal/phy.c +++ b/drivers/staging/rtl8188eu/hal/phy.c @@ -118,7 +118,7 @@ static void rf_serial_write(struct adapter *adapt, phy_set_bb_reg(adapt, phyreg->rf3wireOffset, bMaskDWord, data_and_addr); } -u32 phy_query_rf_reg(struct adapter *adapt, enum rf_radio_path rf_path, +u32 rtw_hal_read_rfreg(struct adapter *adapt, enum rf_radio_path rf_path, u32 reg_addr, u32 bit_mask) { u32 original_value, readback_value, bit_shift; @@ -436,7 +436,7 @@ void rtl88eu_dm_txpower_tracking_callback_thermalmeter(struct adapter *adapt) dm_odm->RFCalibrateInfo.RegA24 = 0x090e1317; - thermal_val = (u8)phy_query_rf_reg(adapt, RF_PATH_A, + thermal_val = (u8)rtw_hal_read_rfreg(adapt, RF_PATH_A, RF_T_METER_88E, 0xfc00); if (is2t) @@ -1229,12 +1229,12 @@ static void phy_lc_calibrate(struct adapter *adapt, bool is2t) if ((tmpreg&0x70) != 0) { /* 1. Read original RF mode */ /* Path-A */ - rf_a_mode = phy_query_rf_reg(adapt, RF_PATH_A, RF_AC, + rf_a_mode = rtw_hal_read_rfreg(adapt, RF_PATH_A, RF_AC, bMask12Bits); /* Path-B */ if (is2t) - rf_b_mode = phy_query_rf_reg(adapt, RF_PATH_B, RF_AC, + rf_b_mode = rtw_hal_read_rfreg(adapt, RF_PATH_B, RF_AC, bMask12Bits); /* 2. Set RF mode = standby mode */ @@ -1249,7 +1249,7 @@ static void phy_lc_calibrate(struct adapter *adapt, bool is2t) } /* 3. Read RF reg18 */ - lc_cal = phy_query_rf_reg(adapt, RF_PATH_A, RF_CHNLBW, bMask12Bits); + lc_cal = rtw_hal_read_rfreg(adapt, RF_PATH_A, RF_CHNLBW, bMask12Bits); /* 4. Set LC calibration begin bit15 */ phy_set_rf_reg(adapt, RF_PATH_A, RF_CHNLBW, bMask12Bits, diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c index ea46ea7..c7b030f 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c @@ -202,7 +202,6 @@ void rtl8188e_set_hal_ops(struct hal_ops *pHalFunc) pHalFunc->AntDivBeforeLinkHandler = &AntDivBeforeLink8188E; pHalFunc->AntDivCompareHandler = &AntDivCompare8188E; - pHalFunc->read_rfreg = &phy_query_rf_reg; } /* */ diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 36abe9f..e2f54cf 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -810,8 +810,8 @@ u32 rtl8188eu_hal_init(struct adapter *Adapter) usb_write16(Adapter, REG_PKT_BE_BK_LIFE_TIME, 0x0400); /* unit: 256us. 256ms */ /* Keep RfRegChnlVal for later use. */ - haldata->RfRegChnlVal[0] = phy_query_rf_reg(Adapter, (enum rf_radio_path)0, RF_CHNLBW, bRFRegOffsetMask); - haldata->RfRegChnlVal[1] = phy_query_rf_reg(Adapter, (enum rf_radio_path)1, RF_CHNLBW, bRFRegOffsetMask); + 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); diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index 971fc62..075cf03 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -161,9 +161,6 @@ struct hal_ops { void (*AntDivCompareHandler)(struct adapter *adapter, struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src); - u32 (*read_rfreg)(struct adapter *padapter, - enum rf_radio_path eRFPath, u32 RegAddr, - u32 BitMask); void (*hal_reset_security_engine)(struct adapter *adapter); }; diff --git a/drivers/staging/rtl8188eu/include/phy.h b/drivers/staging/rtl8188eu/include/phy.h index 9a9ab82..0b42fc1 100644 --- a/drivers/staging/rtl8188eu/include/phy.h +++ b/drivers/staging/rtl8188eu/include/phy.h @@ -11,7 +11,7 @@ bool rtl88eu_phy_bb_config(struct adapter *adapt); u32 phy_query_bb_reg(struct adapter *adapt, u32 regaddr, u32 bitmask); void phy_set_bb_reg(struct adapter *adapt, u32 regaddr, u32 bitmask, u32 data); -u32 phy_query_rf_reg(struct adapter *adapt, enum rf_radio_path rf_path, +u32 rtw_hal_read_rfreg(struct adapter *adapt, enum rf_radio_path rf_path, u32 reg_addr, u32 bit_mask); void phy_set_rf_reg(struct adapter *adapt, enum rf_radio_path rf_path, u32 reg_addr, u32 bit_mask, u32 data); -- cgit v0.10.2 From 2865af357c899dc5be7b948a47d518fb46e2ba3b Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:33:11 +0700 Subject: staging: r8188eu: rename AntDivCompare8188E to rtw_hal_antdiv_rssi_compared And remove two one-line wrappers. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index df1192e..c64e53f 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -131,14 +131,6 @@ u8 rtw_hal_antdiv_before_linked(struct adapter *adapt) return false; } -void rtw_hal_antdiv_rssi_compared(struct adapter *adapt, - struct wlan_bssid_ex *dst, - struct wlan_bssid_ex *src) -{ - if (adapt->HalFunc.AntDivCompareHandler) - adapt->HalFunc.AntDivCompareHandler(adapt, dst, src); -} - void rtw_hal_reset_security_engine(struct adapter *adapter) { if (adapter->HalFunc.hal_reset_security_engine) diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c index e717999..1fa81e8 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c @@ -187,7 +187,7 @@ void rtl8188e_init_dm_priv(struct adapter *Adapter) /* Add new function to reset the state of antenna diversity before link. */ /* Compare RSSI for deciding antenna */ -void AntDivCompare8188E(struct adapter *Adapter, struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src) +void rtw_hal_antdiv_rssi_compared(struct adapter *Adapter, struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src) { struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter); diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c index c7b030f..7629c68 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c @@ -201,7 +201,6 @@ void rtl8188e_set_hal_ops(struct hal_ops *pHalFunc) pHalFunc->Add_RateATid = &rtl8188e_Add_RateATid; pHalFunc->AntDivBeforeLinkHandler = &AntDivBeforeLink8188E; - pHalFunc->AntDivCompareHandler = &AntDivCompare8188E; } /* */ diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index 075cf03..c7b00bb 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -158,9 +158,6 @@ struct hal_ops { u8 rssi_level); u8 (*AntDivBeforeLinkHandler)(struct adapter *adapter); - void (*AntDivCompareHandler)(struct adapter *adapter, - struct wlan_bssid_ex *dst, - struct wlan_bssid_ex *src); void (*hal_reset_security_engine)(struct adapter *adapter); }; -- cgit v0.10.2 From 1e24579b0a011b05266e5a69c64dc354eb67f7b9 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:33:15 +0700 Subject: staging: r8188eu: rename AntDivBeforeLink8188E to rtw_hal_antdiv_before_linked And remove two one-line wrappers. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index c64e53f..bd5159c 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -124,13 +124,6 @@ void rtw_hal_dm_watchdog(struct adapter *adapt) adapt->HalFunc.hal_dm_watchdog(adapt); } -u8 rtw_hal_antdiv_before_linked(struct adapter *adapt) -{ - if (adapt->HalFunc.AntDivBeforeLinkHandler) - return adapt->HalFunc.AntDivBeforeLinkHandler(adapt); - return false; -} - void rtw_hal_reset_security_engine(struct adapter *adapter) { if (adapter->HalFunc.hal_reset_security_engine) diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c index 1fa81e8..c4c8798 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c @@ -201,7 +201,7 @@ void rtw_hal_antdiv_rssi_compared(struct adapter *Adapter, struct wlan_bssid_ex } /* Add new function to reset the state of antenna diversity before link. */ -u8 AntDivBeforeLink8188E(struct adapter *Adapter) +u8 rtw_hal_antdiv_before_linked(struct adapter *Adapter) { struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter); struct odm_dm_struct *dm_odm = &hal_data->odmpriv; diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c index 7629c68..6facf4b 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c @@ -199,8 +199,6 @@ void rtl8188e_set_hal_ops(struct hal_ops *pHalFunc) pHalFunc->hal_dm_watchdog = &rtl8188e_HalDmWatchDog; pHalFunc->Add_RateATid = &rtl8188e_Add_RateATid; - - pHalFunc->AntDivBeforeLinkHandler = &AntDivBeforeLink8188E; } /* */ diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index c7b00bb..c79fa9c 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -157,8 +157,6 @@ struct hal_ops { void (*Add_RateATid)(struct adapter *adapter, u32 bitmap, u8 arg, u8 rssi_level); - u8 (*AntDivBeforeLinkHandler)(struct adapter *adapter); - void (*hal_reset_security_engine)(struct adapter *adapter); }; diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_dm.h b/drivers/staging/rtl8188eu/include/rtl8188e_dm.h index 4190112..4ef657b 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_dm.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_dm.h @@ -51,6 +51,5 @@ void rtl8188e_HalDmWatchDog(struct adapter *adapt); void AntDivCompare8188E(struct adapter *adapt, struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src); -u8 AntDivBeforeLink8188E(struct adapter *adapt); #endif -- cgit v0.10.2 From c8059764180921e332b6043d714509b66c8e8bbc Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:33:18 +0700 Subject: staging: r8188eu: rename rtl8188e_Add_RateATid to rtw_hal_add_ra_tid And remove two one-line wrappers. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index bd5159c..7237b94 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -96,14 +96,6 @@ void rtw_hal_update_ra_mask(struct adapter *adapt, u32 mac_id, u8 rssi_level) } } -void rtw_hal_add_ra_tid(struct adapter *adapt, u32 bitmap, u8 arg, - u8 rssi_level) -{ - if (adapt->HalFunc.Add_RateATid) - adapt->HalFunc.Add_RateATid(adapt, bitmap, arg, - rssi_level); -} - void rtw_hal_set_bwmode(struct adapter *adapt, enum ht_channel_width bandwidth, u8 offset) { diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c index 40a0114..18f69b8 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c @@ -126,7 +126,7 @@ exit: /* bitmap[28:31]= Rate Adaptive id */ /* arg[0:4] = macid */ /* arg[5] = Short GI */ -void rtl8188e_Add_RateATid(struct adapter *pAdapter, u32 bitmap, u8 arg, u8 rssi_level) +void rtw_hal_add_ra_tid(struct adapter *pAdapter, u32 bitmap, u8 arg, u8 rssi_level) { struct hal_data_8188e *haldata = GET_HAL_DATA(pAdapter); diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c index 6facf4b..b2928a5 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c @@ -197,8 +197,6 @@ void rtl8188e_set_hal_ops(struct hal_ops *pHalFunc) pHalFunc->set_channel_handler = &phy_sw_chnl; pHalFunc->hal_dm_watchdog = &rtl8188e_HalDmWatchDog; - - pHalFunc->Add_RateATid = &rtl8188e_Add_RateATid; } /* */ diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index c79fa9c..893e10e 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -154,9 +154,6 @@ struct hal_ops { void (*hal_dm_watchdog)(struct adapter *padapter); - void (*Add_RateATid)(struct adapter *adapter, u32 bitmap, u8 arg, - u8 rssi_level); - void (*hal_reset_security_engine)(struct adapter *adapter); }; diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h b/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h index 820c045..042b4ec 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h @@ -72,8 +72,6 @@ struct rsvdpage_loc { /* host message to firmware cmd */ void rtl8188e_set_FwPwrMode_cmd(struct adapter *padapter, u8 Mode); void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *padapter, u8 mstatus); -void rtl8188e_Add_RateATid(struct adapter *padapter, u32 bitmap, u8 arg, - u8 rssi_level); void rtl8188e_set_FwMediaStatus_cmd(struct adapter *adapt, __le16 mstatus_rpt); -- cgit v0.10.2 From 66fa5a46884394da05e197416d47c0be57d023f4 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:33:22 +0700 Subject: staging: r8188eu: rename rtl8188e_HalDmWatchDog to rtw_hal_dm_watchdog And remove two one-line wrappers. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index 7237b94..5b38fb4 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -110,12 +110,6 @@ void rtw_hal_set_chan(struct adapter *adapt, u8 channel) adapt->HalFunc.set_channel_handler(adapt, channel); } -void rtw_hal_dm_watchdog(struct adapter *adapt) -{ - if (adapt->HalFunc.hal_dm_watchdog) - adapt->HalFunc.hal_dm_watchdog(adapt); -} - void rtw_hal_reset_security_engine(struct adapter *adapter) { if (adapter->HalFunc.hal_reset_security_engine) diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c index c4c8798..73d6827 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c @@ -141,7 +141,7 @@ void rtl8188e_InitHalDm(struct adapter *Adapter) ODM_DMInit(dm_odm); } -void rtl8188e_HalDmWatchDog(struct adapter *Adapter) +void rtw_hal_dm_watchdog(struct adapter *Adapter) { u8 hw_init_completed = false; struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter); diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c index b2928a5..90d1aa3 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c @@ -195,8 +195,6 @@ void rtl8188e_set_hal_ops(struct hal_ops *pHalFunc) pHalFunc->set_bwmode_handler = &phy_set_bw_mode; pHalFunc->set_channel_handler = &phy_sw_chnl; - - pHalFunc->hal_dm_watchdog = &rtl8188e_HalDmWatchDog; } /* */ diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index 893e10e..0f04a8b 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -152,8 +152,6 @@ struct hal_ops { u8 Offset); void (*set_channel_handler)(struct adapter *padapter, u8 channel); - void (*hal_dm_watchdog)(struct adapter *padapter); - void (*hal_reset_security_engine)(struct adapter *adapter); }; diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_dm.h b/drivers/staging/rtl8188eu/include/rtl8188e_dm.h index 4ef657b..39e453c 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_dm.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_dm.h @@ -47,7 +47,6 @@ struct dm_priv { void rtl8188e_init_dm_priv(struct adapter *adapt); void rtl8188e_InitHalDm(struct adapter *adapt); -void rtl8188e_HalDmWatchDog(struct adapter *adapt); void AntDivCompare8188E(struct adapter *adapt, struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src); -- cgit v0.10.2 From bada35ba84c8522bd0e58be5bdfeb612d9641e3f Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:33:26 +0700 Subject: staging: r8188eu: rename phy_sw_chnl to rtw_hal_set_chan And remove two one-line wrappers. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index 5b38fb4..5f4bf5f 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -104,12 +104,6 @@ void rtw_hal_set_bwmode(struct adapter *adapt, offset); } -void rtw_hal_set_chan(struct adapter *adapt, u8 channel) -{ - if (adapt->HalFunc.set_channel_handler) - adapt->HalFunc.set_channel_handler(adapt, channel); -} - void rtw_hal_reset_security_engine(struct adapter *adapter) { if (adapter->HalFunc.hal_reset_security_engine) diff --git a/drivers/staging/rtl8188eu/hal/phy.c b/drivers/staging/rtl8188eu/hal/phy.c index 2b66c6d..4856c24 100644 --- a/drivers/staging/rtl8188eu/hal/phy.c +++ b/drivers/staging/rtl8188eu/hal/phy.c @@ -307,7 +307,7 @@ static void phy_sw_chnl_callback(struct adapter *adapt, u8 channel) } } -void phy_sw_chnl(struct adapter *adapt, u8 channel) +void rtw_hal_set_chan(struct adapter *adapt, u8 channel) { struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); u8 tmpchannel = hal_data->CurrentChannel; diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c index 90d1aa3..2b15b11 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c @@ -194,7 +194,6 @@ void rtl8188e_set_hal_ops(struct hal_ops *pHalFunc) pHalFunc->read_chip_version = &ReadChipVersion8188E; pHalFunc->set_bwmode_handler = &phy_set_bw_mode; - pHalFunc->set_channel_handler = &phy_sw_chnl; } /* */ diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index 0f04a8b..8c15c58 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -150,7 +150,6 @@ struct hal_ops { void (*set_bwmode_handler)(struct adapter *padapter, enum ht_channel_width Bandwidth, u8 Offset); - void (*set_channel_handler)(struct adapter *padapter, u8 channel); void (*hal_reset_security_engine)(struct adapter *adapter); }; diff --git a/drivers/staging/rtl8188eu/include/phy.h b/drivers/staging/rtl8188eu/include/phy.h index 0b42fc1..4637520 100644 --- a/drivers/staging/rtl8188eu/include/phy.h +++ b/drivers/staging/rtl8188eu/include/phy.h @@ -20,7 +20,6 @@ void phy_set_tx_power_level(struct adapter *adapt, u8 channel); void phy_set_bw_mode(struct adapter *adapt, enum ht_channel_width bandwidth, unsigned char offset); -void phy_sw_chnl(struct adapter *adapt, u8 channel); void rtl88eu_dm_txpower_track_adjust(struct odm_dm_struct *dm_odm, u8 type, u8 *dir, u32 *out_write); -- cgit v0.10.2 From 1ac7c98699396cbe53fab75b353f223743b52e7d Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:33:30 +0700 Subject: staging: r8188eu: rename phy_set_bw_mode to rtw_hal_set_bwmode And remove two one-line wrappers. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index 5f4bf5f..daed450 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -96,14 +96,6 @@ void rtw_hal_update_ra_mask(struct adapter *adapt, u32 mac_id, u8 rssi_level) } } -void rtw_hal_set_bwmode(struct adapter *adapt, - enum ht_channel_width bandwidth, u8 offset) -{ - if (adapt->HalFunc.set_bwmode_handler) - adapt->HalFunc.set_bwmode_handler(adapt, bandwidth, - offset); -} - void rtw_hal_reset_security_engine(struct adapter *adapter) { if (adapter->HalFunc.hal_reset_security_engine) diff --git a/drivers/staging/rtl8188eu/hal/phy.c b/drivers/staging/rtl8188eu/hal/phy.c index 4856c24..776e5b8 100644 --- a/drivers/staging/rtl8188eu/hal/phy.c +++ b/drivers/staging/rtl8188eu/hal/phy.c @@ -274,7 +274,7 @@ static void phy_set_bw_mode_callback(struct adapter *adapt) rtl88eu_phy_rf6052_set_bandwidth(adapt, hal_data->CurrentChannelBW); } -void phy_set_bw_mode(struct adapter *adapt, enum ht_channel_width bandwidth, +void rtw_hal_set_bwmode(struct adapter *adapt, enum ht_channel_width bandwidth, unsigned char offset) { struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c index 2b15b11..75eda92 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c @@ -192,8 +192,6 @@ void rtl8188e_set_hal_ops(struct hal_ops *pHalFunc) pHalFunc->dm_init = &rtl8188e_init_dm_priv; pHalFunc->read_chip_version = &ReadChipVersion8188E; - - pHalFunc->set_bwmode_handler = &phy_set_bw_mode; } /* */ diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index 8c15c58..d3243ef 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -147,10 +147,6 @@ struct hal_ops { s32 (*interrupt_handler)(struct adapter *padapter); - void (*set_bwmode_handler)(struct adapter *padapter, - enum ht_channel_width Bandwidth, - u8 Offset); - void (*hal_reset_security_engine)(struct adapter *adapter); }; diff --git a/drivers/staging/rtl8188eu/include/phy.h b/drivers/staging/rtl8188eu/include/phy.h index 4637520..cd387e9 100644 --- a/drivers/staging/rtl8188eu/include/phy.h +++ b/drivers/staging/rtl8188eu/include/phy.h @@ -18,9 +18,6 @@ void phy_set_rf_reg(struct adapter *adapt, enum rf_radio_path rf_path, void phy_set_tx_power_level(struct adapter *adapt, u8 channel); -void phy_set_bw_mode(struct adapter *adapt, enum ht_channel_width bandwidth, - unsigned char offset); - void rtl88eu_dm_txpower_track_adjust(struct odm_dm_struct *dm_odm, u8 type, u8 *dir, u32 *out_write); -- cgit v0.10.2 From f86fc9b0b67ea6af2e04fc2a4a43e0152a944902 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:33:34 +0700 Subject: staging: r8188eu: rename ReadChipVersion8188E to rtw_hal_read_chip_version And remove two one-line wrappers. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index daed450..bc253f4 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -19,12 +19,6 @@ #include <hal_intf.h> #include <usb_hal.h> -void rtw_hal_read_chip_version(struct adapter *adapt) -{ - if (adapt->HalFunc.read_chip_version) - adapt->HalFunc.read_chip_version(adapt); -} - void rtw_hal_free_data(struct adapter *adapt) { if (adapt->HalFunc.free_hal_data) diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c index 75eda92..8c9fdfb 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c @@ -123,7 +123,7 @@ static void rtl8188e_free_hal_data(struct adapter *padapter) padapter->HalData = NULL; } -static void ReadChipVersion8188E(struct adapter *padapter) +void rtw_hal_read_chip_version(struct adapter *padapter) { u32 value32; struct HAL_VERSION ChipVersion; @@ -190,8 +190,6 @@ void rtl8188e_set_hal_ops(struct hal_ops *pHalFunc) pHalFunc->free_hal_data = &rtl8188e_free_hal_data; pHalFunc->dm_init = &rtl8188e_init_dm_priv; - - pHalFunc->read_chip_version = &ReadChipVersion8188E; } /* */ diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index d3243ef..b0ade59 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -143,7 +143,6 @@ struct hal_ops { void (*free_hal_data)(struct adapter *padapter); void (*dm_init)(struct adapter *padapter); - void (*read_chip_version)(struct adapter *padapter); s32 (*interrupt_handler)(struct adapter *padapter); -- cgit v0.10.2 From a5c2587435c613f3676c321dd378552c0628a144 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:33:37 +0700 Subject: staging: r8188eu: rename rtl8188e_init_dm_priv to rtw_hal_dm_init And remove two one-line wrappers. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index bc253f4..094c454 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -25,12 +25,6 @@ void rtw_hal_free_data(struct adapter *adapt) adapt->HalFunc.free_hal_data(adapt); } -void rtw_hal_dm_init(struct adapter *adapt) -{ - if (adapt->HalFunc.dm_init) - adapt->HalFunc.dm_init(adapt); -} - uint rtw_hal_init(struct adapter *adapt) { uint status = _SUCCESS; diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c index 73d6827..11e7246 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c @@ -174,7 +174,7 @@ skip_dm: return; } -void rtl8188e_init_dm_priv(struct adapter *Adapter) +void rtw_hal_dm_init(struct adapter *Adapter) { struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter); struct dm_priv *pdmpriv = &hal_data->dmpriv; diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c index 8c9fdfb..d1f89f8 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c @@ -188,8 +188,6 @@ void rtw_hal_notch_filter(struct adapter *adapter, bool enable) void rtl8188e_set_hal_ops(struct hal_ops *pHalFunc) { pHalFunc->free_hal_data = &rtl8188e_free_hal_data; - - pHalFunc->dm_init = &rtl8188e_init_dm_priv; } /* */ diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index b0ade59..0228c374 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -142,8 +142,6 @@ enum hal_intf_ps_func { struct hal_ops { void (*free_hal_data)(struct adapter *padapter); - void (*dm_init)(struct adapter *padapter); - s32 (*interrupt_handler)(struct adapter *padapter); void (*hal_reset_security_engine)(struct adapter *adapter); diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_dm.h b/drivers/staging/rtl8188eu/include/rtl8188e_dm.h index 39e453c..c0ffd98 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_dm.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_dm.h @@ -45,7 +45,6 @@ struct dm_priv { u8 PowerIndex_backup[6]; }; -void rtl8188e_init_dm_priv(struct adapter *adapt); void rtl8188e_InitHalDm(struct adapter *adapt); void AntDivCompare8188E(struct adapter *adapt, struct wlan_bssid_ex *dst, -- cgit v0.10.2 From 2490fbf7b600237c508cef698945b2e3f4dbaf22 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:33:40 +0700 Subject: staging: r8188eu: rename rtl8188e_free_hal_data to rtw_hal_free_data And remove two one-line wrappers. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index 094c454..d76ccd0 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -19,12 +19,6 @@ #include <hal_intf.h> #include <usb_hal.h> -void rtw_hal_free_data(struct adapter *adapt) -{ - if (adapt->HalFunc.free_hal_data) - adapt->HalFunc.free_hal_data(adapt); -} - uint rtw_hal_init(struct adapter *adapt) { uint status = _SUCCESS; diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c index d1f89f8..85794cb 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c @@ -117,7 +117,7 @@ void rtl8188e_InitializeFirmwareVars(struct adapter *padapter) pHalData->LastHMEBoxNum = 0; } -static void rtl8188e_free_hal_data(struct adapter *padapter) +void rtw_hal_free_data(struct adapter *padapter) { kfree(padapter->HalData); padapter->HalData = NULL; @@ -187,7 +187,6 @@ void rtw_hal_notch_filter(struct adapter *adapter, bool enable) } void rtl8188e_set_hal_ops(struct hal_ops *pHalFunc) { - pHalFunc->free_hal_data = &rtl8188e_free_hal_data; } /* */ diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index 0228c374..9b3528a 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -140,8 +140,6 @@ enum hal_intf_ps_func { }; struct hal_ops { - void (*free_hal_data)(struct adapter *padapter); - s32 (*interrupt_handler)(struct adapter *padapter); void (*hal_reset_security_engine)(struct adapter *adapter); -- cgit v0.10.2 From 274c4f2912188cc7d5c4c1355e06d287a3c22a1a Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:33:44 +0700 Subject: staging: r8188eu: remove rtl8188e_set_hal_ops function rtl8188e_set_hal_ops do nothing. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c index 85794cb..938d6f5 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c @@ -185,9 +185,6 @@ void rtw_hal_notch_filter(struct adapter *adapter, bool enable) usb_write8(adapter, rOFDM0_RxDSP+1, usb_read8(adapter, rOFDM0_RxDSP+1) & ~BIT(1)); } } -void rtl8188e_set_hal_ops(struct hal_ops *pHalFunc) -{ -} /* */ /* */ diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index e2f54cf..cc27d64 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -2043,12 +2043,7 @@ void rtw_hal_def_value_init(struct adapter *adapt) void rtl8188eu_set_hal_ops(struct adapter *adapt) { - struct hal_ops *halfunc = &adapt->HalFunc; - - adapt->HalData = kzalloc(sizeof(struct hal_data_8188e), GFP_KERNEL); if (!adapt->HalData) DBG_88E("cant not alloc memory for HAL DATA\n"); - - rtl8188e_set_hal_ops(halfunc); } diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h index 9dd5c29..418bdb9 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h @@ -385,8 +385,6 @@ void Hal_EfuseParseBoardType88E(struct adapter *pAdapter, u8 *hwinfo, void Hal_ReadPowerSavingMode88E(struct adapter *pAdapter, u8 *hwinfo, bool AutoLoadFail); -void rtl8188e_set_hal_ops(struct hal_ops *pHalFunc); - /* register */ void rtl8188e_start_thread(struct adapter *padapter); -- cgit v0.10.2 From 6559b8b5cb0c232da487e2e221bc999c27c19b14 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:33:49 +0700 Subject: staging: r8188eu: remove hal_set_hal_ops macro hal_set_hal_ops is a trivial wrapper for rtl8188eu_set_hal_ops. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/usb_hal.h b/drivers/staging/rtl8188eu/include/usb_hal.h index b1bf07a..fd9921f 100644 --- a/drivers/staging/rtl8188eu/include/usb_hal.h +++ b/drivers/staging/rtl8188eu/include/usb_hal.h @@ -16,6 +16,5 @@ #define __USB_HAL_H__ void rtl8188eu_set_hal_ops(struct adapter *padapter); -#define hal_set_hal_ops rtl8188eu_set_hal_ops #endif /* __USB_HAL_H__ */ diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c index 900dd53..ea77082 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c @@ -362,7 +362,7 @@ static struct adapter *rtw_usb_if1_init(struct dvobj_priv *dvobj, } /* step 2. hook HalFunc, allocate HalData */ - hal_set_hal_ops(padapter); + rtl8188eu_set_hal_ops(padapter); padapter->intf_start = &usb_intf_start; padapter->intf_stop = &usb_intf_stop; -- cgit v0.10.2 From 20b63baa1e62f044724af6cadfafa198dd2f99db Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:33:52 +0700 Subject: staging: r8188eu: remove interrupt_handler member of hal_ops structure interrupt_handler does not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index 9b3528a..2528a6e 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -140,8 +140,6 @@ enum hal_intf_ps_func { }; struct hal_ops { - s32 (*interrupt_handler)(struct adapter *padapter); - void (*hal_reset_security_engine)(struct adapter *adapter); }; -- cgit v0.10.2 From e72a384b8fa3599bf8f4f9d6cd139f83ce8d168e Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:33:56 +0700 Subject: staging: r8188eu: remove hal_reset_security_engine member of hal_ops structure hal_reset_security_engine always is NULL. Also rtw_hal_reset_security_engine function removed. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index d76ccd0..12fde45 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -32,8 +32,6 @@ uint rtw_hal_init(struct adapter *adapt) if (adapt->registrypriv.notch_filter == 1) rtw_hal_notch_filter(adapt, 1); - - rtw_hal_reset_security_engine(adapt); } else { adapt->hw_init_completed = false; DBG_88E("rtw_hal_init: hal__init fail\n"); @@ -77,9 +75,3 @@ void rtw_hal_update_ra_mask(struct adapter *adapt, u32 mac_id, u8 rssi_level) UpdateHalRAMask8188EUsb(adapt, mac_id, rssi_level); } } - -void rtw_hal_reset_security_engine(struct adapter *adapter) -{ - if (adapter->HalFunc.hal_reset_security_engine) - adapter->HalFunc.hal_reset_security_engine(adapter); -} diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index 2528a6e..262a704 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -140,7 +140,6 @@ enum hal_intf_ps_func { }; struct hal_ops { - void (*hal_reset_security_engine)(struct adapter *adapter); }; enum rt_eeprom_type { @@ -228,7 +227,6 @@ void rtw_hal_antdiv_rssi_compared(struct adapter *padapter, void rtw_hal_sreset_init(struct adapter *padapter); void rtw_hal_notch_filter(struct adapter *adapter, bool enable); -void rtw_hal_reset_security_engine(struct adapter *adapter); void indicate_wx_scan_complete_event(struct adapter *padapter); u8 rtw_do_join(struct adapter *padapter); -- cgit v0.10.2 From 71d387c9ddc585f35cfaccabebe5890e8e90bb73 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Sat, 3 Sep 2016 22:34:00 +0700 Subject: staging: r8188eu: remove HalFunc member of adapter structure hal_ops structure is empty. Also remove hal_ops definition. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/drv_types.h b/drivers/staging/rtl8188eu/include/drv_types.h index 7b56540..7af690e 100644 --- a/drivers/staging/rtl8188eu/include/drv_types.h +++ b/drivers/staging/rtl8188eu/include/drv_types.h @@ -155,7 +155,6 @@ struct adapter { struct led_priv ledpriv; void *HalData; - struct hal_ops HalFunc; s32 bDriverStopped; s32 bSurpriseRemoved; diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index 262a704..0c0fa35 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -139,9 +139,6 @@ enum hal_intf_ps_func { HAL_MAX_ID, }; -struct hal_ops { -}; - enum rt_eeprom_type { EEPROM_93C46, EEPROM_93C56, -- cgit v0.10.2 From ce4b80fb057563ec0cd8751658530597641fcfc9 Mon Sep 17 00:00:00 2001 From: Imre Deak <imre.deak@gmail.com> Date: Sun, 11 Sep 2016 19:48:08 +0300 Subject: staging: gdm724x: gdm_lte: Constify gdm_netdev_ops Fix the following checkpatch.pl warning: WARNING: struct net_device_ops should normally be const +static struct net_device_ops gdm_netdev_ops = { Signed-off-by: Imre Deak <imre.deak@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/gdm724x/gdm_lte.c b/drivers/staging/gdm724x/gdm_lte.c index bb55219..e72dfa9 100644 --- a/drivers/staging/gdm724x/gdm_lte.c +++ b/drivers/staging/gdm724x/gdm_lte.c @@ -828,7 +828,7 @@ void start_rx_proc(struct phy_dev *phy_dev) rx_complete, phy_dev, USB_COMPLETE); } -static struct net_device_ops gdm_netdev_ops = { +static const struct net_device_ops gdm_netdev_ops = { .ndo_open = gdm_lte_open, .ndo_stop = gdm_lte_close, .ndo_set_config = gdm_lte_set_config, -- cgit v0.10.2 From 1c099ed63f8363228a0b075a25511c9feb90e03f Mon Sep 17 00:00:00 2001 From: Julia Lawall <Julia.Lawall@lip6.fr> Date: Sun, 11 Sep 2016 15:05:45 +0200 Subject: staging: rtl8192e: constify local structures For structure types defined in the same file or local header files, find top-level static structure declarations that have the following properties: 1. Never reassigned. 2. Address never taken 3. Not passed to a top-level macro call 4. No pointer or array-typed field passed to a function or stored in a variable. Declare structures having all of these properties as const. Done using Coccinelle. Based on a suggestion by Joe Perches <joe@perches.com>. Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c index e01fff0..4c30eea 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c @@ -38,7 +38,7 @@ static int channels = 0x3fff; static char *ifname = "wlan%d"; -static struct rtl819x_ops rtl819xp_ops = { +static const struct rtl819x_ops rtl819xp_ops = { .nic_type = NIC_8192E, .get_eeprom_size = rtl92e_get_eeprom_size, .init_adapter_variable = rtl92e_init_variables, -- cgit v0.10.2 From bef611a92ee2d107365cf77e3665ce91d4f08da2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Beamonte?= <raphael.beamonte@gmail.com> Date: Fri, 9 Sep 2016 11:31:45 -0400 Subject: staging: rtl8712: checkpatch cleanup: block comments using a trailing */ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix checkpatch.pl warning "Block comments use a trailing */ on a separate line" on multiple files of the driver by editing the affected comments. Signed-off-by: Raphaël Beamonte <raphael.beamonte@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8712/rtl8712_led.c b/drivers/staging/rtl8712/rtl8712_led.c index 9055827..76d0535 100644 --- a/drivers/staging/rtl8712/rtl8712_led.c +++ b/drivers/staging/rtl8712/rtl8712_led.c @@ -58,10 +58,12 @@ enum _LED_STATE_871x { LED_POWER_ON_BLINK = 5, LED_SCAN_BLINK = 6, /* LED is blinking during scanning period, * the # of times to blink is depend on time - * for scanning. */ + * for scanning. + */ LED_NO_LINK_BLINK = 7, /* LED is blinking during no link state. */ LED_BLINK_StartToBlink = 8,/* Customized for Sercomm Printer - * Server case */ + * Server case + */ LED_BLINK_WPS = 9, /* LED is blinkg during WPS communication */ LED_TXRX_BLINK = 10, LED_BLINK_WPS_STOP = 11, /*for ALPHA */ @@ -110,7 +112,8 @@ static void DeInitLed871x(struct LED_871x *pLed) { del_timer_sync(&pLed->BlinkTimer); /* We should reset bLedBlinkInProgress if we cancel - * the LedControlTimer, */ + * the LedControlTimer, + */ pLed->bLedBlinkInProgress = false; } @@ -827,7 +830,8 @@ static void BlinkTimerCallback(unsigned long data) struct LED_871x *pLed = (struct LED_871x *)data; /* This fixed the crash problem on Fedora 12 when trying to do the - * insmod;ifconfig up;rmmod commands. */ + * insmod;ifconfig up;rmmod commands. + */ if (pLed->padapter->bSurpriseRemoved || pLed->padapter->bDriverStopped) return; schedule_work(&pLed->BlinkWorkItem); diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index f25b34c..4027d1a 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -163,7 +163,8 @@ static void update_recvframe_attrib_from_recvstat(struct rx_pkt_attrib *pattrib, drvinfo_sz = (le32_to_cpu(prxstat->rxdw0) & 0x000f0000) >> 16; drvinfo_sz <<= 3; /*TODO: - * Offset 0 */ + * Offset 0 + */ pattrib->bdecrypted = ((le32_to_cpu(prxstat->rxdw0) & BIT(27)) >> 27) ? 0 : 1; pattrib->crc_err = (le32_to_cpu(prxstat->rxdw0) & BIT(14)) >> 14; @@ -210,7 +211,8 @@ static union recv_frame *recvframe_defrag(struct _adapter *adapter, curfragnum = 0; if (curfragnum != pfhdr->attrib.frag_num) { /*the first fragment number must be 0 - *free the whole queue*/ + *free the whole queue + */ r8712_free_recvframe(prframe, pfree_recv_queue); r8712_free_recvframe_queue(defrag_q, pfree_recv_queue); return NULL; @@ -224,18 +226,21 @@ static union recv_frame *recvframe_defrag(struct _adapter *adapter, /*check the fragment sequence (2nd ~n fragment frame) */ if (curfragnum != pnfhdr->attrib.frag_num) { /* the fragment number must increase (after decache) - * release the defrag_q & prframe */ + * release the defrag_q & prframe + */ r8712_free_recvframe(prframe, pfree_recv_queue); r8712_free_recvframe_queue(defrag_q, pfree_recv_queue); return NULL; } curfragnum++; /* copy the 2nd~n fragment frame's payload to the first fragment - * get the 2nd~last fragment frame's payload */ + * get the 2nd~last fragment frame's payload + */ wlanhdr_offset = pnfhdr->attrib.hdrlen + pnfhdr->attrib.iv_len; recvframe_pull(pnextrframe, wlanhdr_offset); /* append to first fragment frame's tail (if privacy frame, - * pull the ICV) */ + * pull the ICV) + */ recvframe_pull_tail(prframe, pfhdr->attrib.icv_len); memcpy(pfhdr->rx_tail, pnfhdr->rx_data, pnfhdr->len); recvframe_put(prframe, pnfhdr->len); @@ -278,7 +283,8 @@ union recv_frame *r8712_recvframe_chk_defrag(struct _adapter *padapter, prtnframe = precv_frame;/*isn't a fragment frame*/ if (ismfrag == 1) { /* 0~(n-1) fragment frame - * enqueue to defraf_g */ + * enqueue to defraf_g + */ if (pdefrag_q != NULL) { if (fragnum == 0) { /*the first fragment*/ @@ -294,7 +300,8 @@ union recv_frame *r8712_recvframe_chk_defrag(struct _adapter *padapter, prtnframe = NULL; } else { /* can't find this ta's defrag_queue, so free this - * recv_frame */ + * recv_frame + */ r8712_free_recvframe(precv_frame, pfree_recv_queue); prtnframe = NULL; } @@ -302,7 +309,8 @@ union recv_frame *r8712_recvframe_chk_defrag(struct _adapter *padapter, } if ((ismfrag == 0) && (fragnum != 0)) { /* the last fragment frame - * enqueue the last fragment */ + * enqueue the last fragment + */ if (pdefrag_q != NULL) { phead = &pdefrag_q->queue; list_add_tail(&pfhdr->list, phead); @@ -311,7 +319,8 @@ union recv_frame *r8712_recvframe_chk_defrag(struct _adapter *padapter, prtnframe = precv_frame; } else { /* can't find this ta's defrag_queue, so free this - * recv_frame */ + * recv_frame + */ r8712_free_recvframe(precv_frame, pfree_recv_queue); prtnframe = NULL; } @@ -391,7 +400,8 @@ static int amsdu_to_msdu(struct _adapter *padapter, union recv_frame *prframe) eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) || !memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE))) { /* remove RFC1042 or Bridge-Tunnel encapsulation and - * replace EtherType */ + * replace EtherType + */ skb_pull(sub_skb, SNAP_SIZE); memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src, ETH_ALEN); @@ -530,7 +540,8 @@ int r8712_recv_indicatepkts_in_order(struct _adapter *padapter, preorder_ctrl->indicate_seq = pattrib->seq_num; } /* Prepare indication list and indication. - * Check if there is any packet need indicate. */ + * Check if there is any packet need indicate. + */ while (!list_empty(phead)) { prframe = container_of(plist, union recv_frame, u.list); pattrib = &prframe->u.hdr.attrib; @@ -757,7 +768,8 @@ static void query_rx_phy_status(struct _adapter *padapter, /* Modify the RF RNA gain value to -40, -20, * -2, 14 by Jenyu's suggestion * Note: different RF with the different - * RNA gain. */ + * RNA gain. + */ case 0x3: rx_pwr_all = -40 - (pcck_buf->cck_agc_rpt & 0x3e); @@ -842,7 +854,8 @@ static void query_rx_phy_status(struct _adapter *padapter, total_rssi += rssi; } /* (2)PWDB, Average PWDB cacluated by hardware (for - * rate adaptive) */ + * rate adaptive) + */ rx_pwr_all = (((pphy_head[PHY_STAT_PWDB_ALL_SHT]) >> 1) & 0x7f) - 106; pwdb_all = query_rx_pwr_percentage(rx_pwr_all); @@ -870,7 +883,8 @@ static void query_rx_phy_status(struct _adapter *padapter, } /* UI BSS List signal strength(in percentage), make it good looking, * from 0~100. It is assigned to the BSS List in - * GetValueFromBeaconOrProbeRsp(). */ + * GetValueFromBeaconOrProbeRsp(). + */ if (bcck_rate) prframe->u.hdr.attrib.signal_strength = (u8)r8712_signal_scale_mapping(pwdb_all); @@ -1027,10 +1041,12 @@ static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb) transfer_len = pskb->len; /* Test throughput with Netgear 3700 (No security) with Chariot 3T3R * pairs. The packet count will be a big number so that the containing - * packet will effect the Rx reordering. */ + * packet will effect the Rx reordering. + */ if (transfer_len < pkt_len) { /* In this case, it means the MAX_RECVBUF_SZ is too small to - * get the data from 8712u. */ + * get the data from 8712u. + */ return _FAIL; } do { @@ -1057,14 +1073,16 @@ static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb) tmp_len = pkt_len + drvinfo_sz + RXDESC_SIZE; pkt_offset = (u16)round_up(tmp_len, 128); /* for first fragment packet, driver need allocate 1536 + - * drvinfo_sz + RXDESC_SIZE to defrag packet. */ + * drvinfo_sz + RXDESC_SIZE to defrag packet. + */ if ((mf == 1) && (frag == 0)) /*1658+6=1664, 1664 is 128 alignment.*/ alloc_sz = max_t(u16, tmp_len, 1658); else alloc_sz = tmp_len; /* 2 is for IP header 4 bytes alignment in QoS packet case. - * 4 is for skb->data 4 bytes alignment. */ + * 4 is for skb->data 4 bytes alignment. + */ alloc_sz += 6; pkt_copy = netdev_alloc_skb(padapter->pnetdev, alloc_sz); if (pkt_copy) { diff --git a/drivers/staging/rtl8712/rtl8712_recv.h b/drivers/staging/rtl8712/rtl8712_recv.h index 925ec74..96ca3e2 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.h +++ b/drivers/staging/rtl8712/rtl8712_recv.h @@ -61,7 +61,8 @@ struct recv_stat { struct phy_cck_rx_status { /* For CCK rate descriptor. This is a unsigned 8:1 variable. * LSB bit present 0.5. And MSB 7 bts present a signed value. - * Range from -64~+63.5. */ + * Range from -64~+63.5. + */ u8 adc_pwdb_X[4]; u8 sq_rpt; u8 cck_agc_rpt; diff --git a/drivers/staging/rtl8712/rtl8712_spec.h b/drivers/staging/rtl8712/rtl8712_spec.h index af11b44..51e0428 100644 --- a/drivers/staging/rtl8712/rtl8712_spec.h +++ b/drivers/staging/rtl8712/rtl8712_spec.h @@ -83,7 +83,8 @@ #define CMD_ADDR_MAPPING_SHIFT 2 /*SDIO CMD ADDR MAPPING, *shift 2 bit for match - * offset[14:2]*/ + * offset[14:2] + */ /*Offset for SDIO LOCAL*/ #define OFFSET_SDIO_LOCAL 0x0FFF diff --git a/drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h b/drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h index eed09c8..2e66d28 100644 --- a/drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h +++ b/drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h @@ -68,11 +68,13 @@ #define SYS_CLKSEL BIT(SYS_CLKSEL_SHT) /* System Clock 80MHz*/ #define PS_CLKSEL_SHT 1 #define PS_CLKSEL BIT(PS_CLKSEL_SHT) /*System power save - * clock select.*/ + * clock select. + */ #define CPU_CLKSEL_SHT 2 #define CPU_CLKSEL BIT(CPU_CLKSEL_SHT) /* System Clock select, * 1: AFE source, - * 0: System clock(L-Bus)*/ + * 0: System clock(L-Bus) + */ #define INT32K_EN_SHT 3 #define INT32K_EN BIT(INT32K_EN_SHT) #define MACSLP_SHT 4 @@ -85,10 +87,12 @@ #define RING_CLK_EN BIT(RING_CLK_EN_SHT) #define SWHW_SEL_SHT 14 #define SWHW_SEL BIT(SWHW_SEL_SHT) /* Load done, - * control path switch.*/ + * control path switch. + */ #define FWHW_SEL_SHT 15 #define FWHW_SEL BIT(FWHW_SEL_SHT) /* Sleep exit, - * control path switch.*/ + * control path switch. + */ /*9346CR*/ #define _VPDIDX_MSK 0xFF00 @@ -118,10 +122,12 @@ #define AFE_MISC_E32_EN BIT(AFE_MISC_E32_EN_SHT) #define AFE_MISC_MBEN_SHT 1 #define AFE_MISC_MBEN BIT(AFE_MISC_MBEN_SHT)/* Enable AFE Macro - * Block's Mbias.*/ + * Block's Mbias. + */ #define AFE_MISC_BGEN_SHT 0 #define AFE_MISC_BGEN BIT(AFE_MISC_BGEN_SHT)/* Enable AFE Macro - * Block's Bandgap.*/ + * Block's Bandgap. + */ /*--------------------------------------------------------------------------*/ @@ -149,10 +155,12 @@ /* EFUSE_CTRL*/ #define EF_FLAG BIT(31) /* Access Flag, Write:1; - * Read:0*/ + * Read:0 + */ #define EF_PGPD 0x70000000 /* E-fuse Program time*/ #define EF_RDT 0x0F000000 /* E-fuse read time: in the - * unit of cycle time*/ + * unit of cycle time + */ #define EF_PDN_EN BIT(19) /* EFuse Power down enable*/ #define ALD_EN BIT(18) /* Autoload Enable*/ #define EF_ADDR 0x0003FF00 /* Access Address*/ @@ -164,7 +172,8 @@ /* EFUSE_CLK_CTRL*/ #define EFUSE_CLK_EN BIT(1) /* E-Fuse Clock Enable*/ #define EFUSE_CLK_SEL BIT(0) /* E-Fuse Clock Select, - * 0:500K, 1:40M*/ + * 0:500K, 1:40M + */ #endif /*__RTL8712_SYSCFG_BITDEF_H__*/ diff --git a/drivers/staging/rtl8712/rtl8712_xmit.c b/drivers/staging/rtl8712/rtl8712_xmit.c index 7e0b945..4bbf76f 100644 --- a/drivers/staging/rtl8712/rtl8712_xmit.c +++ b/drivers/staging/rtl8712/rtl8712_xmit.c @@ -535,7 +535,8 @@ static void update_txdesc(struct xmit_frame *pxmitframe, uint *pmem, int sz) * seqnum per tid. about usb using 4-endpoint, qsel points out * the correct mapping between AC&Endpoint, * the purpose is that correct mapping lets the MAC release - * the AC Queue list correctly. */ + * the AC Queue list correctly. + */ ptxdesc->txdw3 = cpu_to_le32((pattrib->priority << SEQ_SHT) & 0x0fff0000); if ((pattrib->ether_type != 0x888e) && @@ -586,7 +587,8 @@ static void update_txdesc(struct xmit_frame *pxmitframe, uint *pmem, int sz) * per tid. about usb using 4-endpoint, qsel points out the * correct mapping between AC&Endpoint, * the purpose is that correct mapping let the MAC releases - * the AC Queue list correctly. */ + * the AC Queue list correctly. + */ ptxdesc->txdw3 = cpu_to_le32((pattrib->priority << SEQ_SHT) & 0x0fff0000); /* offset 16 */ @@ -686,7 +688,8 @@ int r8712_xmitframe_complete(struct _adapter *padapter, res = r8712_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe); /* always return ndis_packet after - * r8712_xmitframe_coalesce */ + * r8712_xmitframe_coalesce + */ r8712_xmit_complete(padapter, pxmitframe); } if (res == _SUCCESS) diff --git a/drivers/staging/rtl8712/rtl871x_cmd.h b/drivers/staging/rtl8712/rtl871x_cmd.h index ebd2e1d..a2cee36 100644 --- a/drivers/staging/rtl8712/rtl871x_cmd.h +++ b/drivers/staging/rtl8712/rtl871x_cmd.h @@ -185,10 +185,12 @@ struct setauth_parm { */ struct setkey_parm { u8 algorithm; /* encryption algorithm, could be none, wep40, - * TKIP, CCMP, wep104 */ + * TKIP, CCMP, wep104 + */ u8 keyid; u8 grpkey; /* 1: this is the grpkey for 802.1x. - * 0: this is the unicast key for 802.1x */ + * 0: this is the unicast key for 802.1x + */ u8 key[16]; /* this could be 40 or 104 */ }; @@ -570,7 +572,8 @@ struct setpwrmode_parm { u8 bcn_rx_en; u8 bcn_pass_cnt; /* fw report one beacon information to * driver when it receives bcn_pass_cnt - * beacons. */ + * beacons. + */ u8 bcn_to; /* beacon TO (ms). ¡§=0¡¨ no limit.*/ u16 bcn_itv; u8 app_itv; /* only for VOIP mode. */ diff --git a/drivers/staging/rtl8712/rtl871x_ht.h b/drivers/staging/rtl8712/rtl871x_ht.h index 41872d9..513f458 100644 --- a/drivers/staging/rtl8712/rtl871x_ht.h +++ b/drivers/staging/rtl8712/rtl871x_ht.h @@ -36,7 +36,8 @@ struct ht_priv { unsigned int tx_amsdu_enable;/*for enable Tx A-MSDU */ unsigned int tx_amdsu_maxlen; /* 1: 8k, 0:4k ; default:8k, for tx */ unsigned int rx_ampdu_maxlen; /* for rx reordering ctrl win_sz, - * updated when join_callback. */ + * updated when join_callback. + */ struct ieee80211_ht_cap ht_cap; }; diff --git a/drivers/staging/rtl8712/rtl871x_ioctl.h b/drivers/staging/rtl8712/rtl871x_ioctl.h index c9218be..08bcb3b 100644 --- a/drivers/staging/rtl8712/rtl871x_ioctl.h +++ b/drivers/staging/rtl8712/rtl871x_ioctl.h @@ -68,7 +68,8 @@ struct oid_par_priv { struct oid_obj_priv { unsigned char dbg; /* 0: without OID debug message - * 1: with OID debug message */ + * 1: with OID debug message + */ uint (*oidfuns)(struct oid_par_priv *poid_par_priv); }; diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_set.c b/drivers/staging/rtl8712/rtl871x_ioctl_set.c index 56760cd..0aaf2aa 100644 --- a/drivers/staging/rtl8712/rtl871x_ioctl_set.c +++ b/drivers/staging/rtl8712/rtl871x_ioctl_set.c @@ -140,7 +140,8 @@ u8 r8712_set_802_11_bssid(struct _adapter *padapter, u8 *bssid) ETH_ALEN)) { if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE)) goto _Abort_Set_BSSID; /* driver is in - * WIFI_ADHOC_MASTER_STATE */ + * WIFI_ADHOC_MASTER_STATE + */ } else { r8712_disassoc_cmd(padapter); if (check_fwstate(pmlmepriv, _FW_LINKED)) @@ -203,7 +204,8 @@ void r8712_set_802_11_ssid(struct _adapter *padapter, } } else { goto _Abort_Set_SSID; /* driver is in - * WIFI_ADHOC_MASTER_STATE */ + * WIFI_ADHOC_MASTER_STATE + */ } } } else { @@ -254,12 +256,14 @@ void r8712_set_802_11_infrastructure_mode(struct _adapter *padapter, (*pold_state == Ndis802_11IBSS)) { /* will clr Linked_state before this function, * we must have checked whether issue dis-assoc_cmd or - * not */ + * not + */ r8712_ind_disconnect(padapter); } *pold_state = networktype; /* clear WIFI_STATION_STATE; WIFI_AP_STATE; WIFI_ADHOC_STATE; - * WIFI_ADHOC_MASTER_STATE */ + * WIFI_ADHOC_MASTER_STATE + */ _clr_fwstate_(pmlmepriv, WIFI_STATION_STATE | WIFI_AP_STATE | WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE); switch (networktype) { diff --git a/drivers/staging/rtl8712/rtl871x_led.h b/drivers/staging/rtl8712/rtl871x_led.h index eb61205..adfbc40 100644 --- a/drivers/staging/rtl8712/rtl871x_led.h +++ b/drivers/staging/rtl8712/rtl871x_led.h @@ -72,14 +72,17 @@ enum LED_STRATEGY_871x { SW_LED_MODE0, /* SW control 1 LED via GPIO0. It is default option. */ SW_LED_MODE1, /* 2 LEDs, through LED0 and LED1. For ALPHA. */ SW_LED_MODE2, /* SW control 1 LED via GPIO0, - * custom for AzWave 8187 minicard. */ + * custom for AzWave 8187 minicard. + */ SW_LED_MODE3, /* SW control 1 LED via GPIO0, - * customized for Sercomm Printer Server case.*/ + * customized for Sercomm Printer Server case. + */ SW_LED_MODE4, /*for Edimax / Belkin*/ SW_LED_MODE5, /*for Sercomm / Belkin*/ SW_LED_MODE6, /*for WNC / Corega*/ HW_LED, /* HW control 2 LEDs, LED0 and LED1 (there are 4 different - * control modes, see MAC.CONFIG1 for details.)*/ + * control modes, see MAC.CONFIG1 for details.) + */ }; struct LED_871x { @@ -96,7 +99,8 @@ struct LED_871x { u8 bLedWPSBlinkInProgress; u32 BlinkTimes; /* No. times to toggle for blink.*/ u32 BlinkingLedState; /* Next state for blinking, - * either LED_ON or OFF.*/ + * either LED_ON or OFF. + */ struct timer_list BlinkTimer; /* Timer object for led blinking.*/ struct work_struct BlinkWorkItem; /* Workitem used by BlinkTimer */ @@ -115,7 +119,8 @@ struct led_priv { /*=========================================================================== * Interface to manipulate LED objects. - *===========================================================================*/ + *=========================================================================== + */ void r8712_InitSwLeds(struct _adapter *padapter); void r8712_DeInitSwLeds(struct _adapter *padapter); void LedControl871x(struct _adapter *padapter, enum LED_CTL_MODE LedAction); diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c index 772bf9f..c1feef3 100644 --- a/drivers/staging/rtl8712/rtl871x_mlme.c +++ b/drivers/staging/rtl8712/rtl871x_mlme.c @@ -403,7 +403,8 @@ static void update_scanned_network(struct _adapter *adapter, /* If we didn't find a match, then get a new network slot to initialize - * with this beacon's information */ + * with this beacon's information + */ if (end_of_queue_search(phead, plist)) { if (list_empty(&pmlmepriv->free_bss_pool.queue)) { /* If there are no more slots, expire the oldest */ @@ -926,7 +927,8 @@ void r8712_stassoc_event_callback(struct _adapter *adapter, u8 *pbuf) if (psta != NULL) { /*the sta have been in sta_info_queue => do nothing *(between drv has received this event before and - * fw have not yet to set key to CAM_ENTRY) */ + * fw have not yet to set key to CAM_ENTRY) + */ return; } @@ -1171,7 +1173,8 @@ int r8712_select_and_join_from_scan(struct mlme_priv *pmlmepriv) pmlmepriv->assoc_ssid.SsidLength))) { if (pmlmepriv->assoc_by_rssi) { /* if the ssid is the same, select the bss - * which has the max rssi*/ + * which has the max rssi + */ if (pnetwork_max_rssi) { if (pnetwork->network.Rssi > pnetwork_max_rssi->network.Rssi) @@ -1352,7 +1355,8 @@ static int SecIsInPMKIDList(struct _adapter *Adapter, u8 *bssid) i = -1; /* Could not find. */ } else { ; /* There is one Pre-Authentication Key for the - * specific BSSID. */ + * specific BSSID. + */ } return i; } @@ -1430,7 +1434,8 @@ sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie, if (match) { if (sec_ie[0] == _WPA_IE_ID_) { /* parsing SSN IE to select required encryption - * algorithm, and set the bc/mc encryption algorithm */ + * algorithm, and set the bc/mc encryption algorithm + */ while (true) { /*check wpa_oui tag*/ if (memcmp(&sec_ie[2], &wpa_oui[0], 4)) { @@ -1444,7 +1449,8 @@ sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie, } if (!memcmp(&sec_ie[8], &wpa_oui[0], 3)) { /* get bc/mc encryption type (group - * key type)*/ + * key type) + */ switch (sec_ie[11]) { case 0x0: /*none*/ psecuritypriv->XGrpPrivacy = @@ -1482,7 +1488,8 @@ sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie, } /*else the uncst_oui is match*/ } else { /*mixed mode, unicast_enc_type > 1*/ /*select the uncst_oui and remove - * the other uncst_oui*/ + * the other uncst_oui + */ cnt = sec_ie[12]; remove_cnt = (cnt - 1) * 4; sec_ie[12] = 0x01; @@ -1499,7 +1506,8 @@ sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie, } if (authmode == _WPA2_IE_ID_) { /* parsing RSN IE to select required encryption - * algorithm, and set the bc/mc encryption algorithm */ + * algorithm, and set the bc/mc encryption algorithm + */ while (true) { if ((sec_ie[2] != 0x01) || (sec_ie[3] != 0x0)) { /*IE Ver error*/ @@ -1543,7 +1551,8 @@ sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie, } /*else the uncst_oui is match*/ } else { /*mixed mode, unicast_enc_type > 1*/ /*select the uncst_oui and remove the - * other uncst_oui*/ + * other uncst_oui + */ cnt = sec_ie[8]; remove_cnt = (cnt - 1) * 4; sec_ie[8] = 0x01; @@ -1667,7 +1676,8 @@ void r8712_joinbss_reset(struct _adapter *padapter) struct ht_priv *phtpriv = &pmlmepriv->htpriv; /* todo: if you want to do something io/reg/hw setting before join_bss, - * please add code here */ + * please add code here + */ phtpriv->ampdu_enable = false;/*reset to disabled*/ for (i = 0; i < 16; i++) phtpriv->baddbareq_issued[i] = false;/*reset it*/ diff --git a/drivers/staging/rtl8712/rtl871x_mlme.h b/drivers/staging/rtl8712/rtl871x_mlme.h index 61e0eb7..ddaaab0 100644 --- a/drivers/staging/rtl8712/rtl871x_mlme.h +++ b/drivers/staging/rtl8712/rtl871x_mlme.h @@ -47,16 +47,20 @@ #define WIFI_ADHOC_MASTER_STATE 0x00000040 #define WIFI_UNDER_LINKING 0x00000080 #define WIFI_SITE_MONITOR 0x00000800 /* to indicate the station - * is under site surveying*/ + * is under site surveying + */ #define WIFI_MP_STATE 0x00010000 #define WIFI_MP_CTX_BACKGROUND 0x00020000 /* in cont. tx background*/ #define WIFI_MP_CTX_ST 0x00040000 /* in cont. tx with - * single-tone*/ + * single-tone + */ #define WIFI_MP_CTX_BACKGROUND_PENDING 0x00080000 /* pending in cont, tx - * background due to out of skb*/ + * background due to out of skb + */ #define WIFI_MP_CTX_CCK_HW 0x00100000 /* in continuous tx*/ #define WIFI_MP_CTX_CCK_CS 0x00200000 /* in cont, tx with carrier - * suppression*/ + * suppression + */ #define WIFI_MP_LPBK_STATE 0x00400000 #define _FW_UNDER_LINKING WIFI_UNDER_LINKING diff --git a/drivers/staging/rtl8712/rtl871x_mp.c b/drivers/staging/rtl8712/rtl871x_mp.c index 5e4fda1..3c10a2c 100644 --- a/drivers/staging/rtl8712/rtl871x_mp.c +++ b/drivers/staging/rtl8712/rtl871x_mp.c @@ -376,7 +376,8 @@ void r8712_SwitchBandwidth(struct _adapter *pAdapter) /* Use PHY_REG.txt default value. Do not need to change. * Correct the tx power for CCK rate in 40M. * Set Control channel to upper or lower. These settings are - * required only for 40MHz */ + * required only for 40MHz + */ set_bb_reg(pAdapter, rCCK0_System, bCCKSideBand, (HAL_PRIME_CHNL_OFFSET_DONT_CARE >> 1)); set_bb_reg(pAdapter, rOFDM1_LSTF, 0xC00, diff --git a/drivers/staging/rtl8712/rtl871x_mp.h b/drivers/staging/rtl8712/rtl871x_mp.h index 3f3b2e7..8df452e 100644 --- a/drivers/staging/rtl8712/rtl871x_mp.h +++ b/drivers/staging/rtl8712/rtl871x_mp.h @@ -108,7 +108,8 @@ struct mp_priv { unsigned char network_macaddr[6]; /*Testing Flag*/ u32 mode;/*0 for normal type packet, - * 1 for loopback packet (16bytes TXCMD)*/ + * 1 for loopback packet (16bytes TXCMD) + */ sint prev_fw_state; u8 *pallocated_mp_xmitframe_buf; u8 *pmp_xmtframe_buf; diff --git a/drivers/staging/rtl8712/rtl871x_mp_ioctl.h b/drivers/staging/rtl8712/rtl871x_mp_ioctl.h index 8dc8980..1102451 100644 --- a/drivers/staging/rtl8712/rtl871x_mp_ioctl.h +++ b/drivers/staging/rtl8712/rtl871x_mp_ioctl.h @@ -158,28 +158,37 @@ static const struct oid_obj_priv oid_rtl_seg_81_80_00[] = { {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*/ + * OID_RT_PRO_SET_MANUAL_DIVERS_BB + */ {1, oid_rt_pro_set_channel_direct_call_hdl}, /*0x08*/ {1, oid_null_function}, /*0x09 - * OID_RT_PRO_SET_SLEEP_MODE_DIRECT_CALL*/ + * OID_RT_PRO_SET_SLEEP_MODE_DIRECT_CALL + */ {1, oid_null_function}, /*0x0A - * OID_RT_PRO_SET_WAKE_MODE_DIRECT_CALL*/ + * OID_RT_PRO_SET_WAKE_MODE_DIRECT_CALL + */ {1, oid_rt_pro_set_continuous_tx_hdl}, /*0x0B - * OID_RT_PRO_SET_TX_CONTINUOUS_DIRECT_CALL*/ + * OID_RT_PRO_SET_TX_CONTINUOUS_DIRECT_CALL + */ {1, oid_rt_pro_set_single_carrier_tx_hdl}, /*0x0C - * OID_RT_PRO_SET_SINGLE_CARRIER_TX_CONTINUOUS*/ + * OID_RT_PRO_SET_SINGLE_CARRIER_TX_CONTINUOUS + */ {1, oid_null_function}, /*0x0D - * OID_RT_PRO_SET_TX_ANTENNA_BB*/ + * OID_RT_PRO_SET_TX_ANTENNA_BB + */ {1, oid_rt_pro_set_antenna_bb_hdl}, /*0x0E*/ {1, oid_null_function}, /*0x0F OID_RT_PRO_SET_CR_SCRAMBLER*/ {1, oid_null_function}, /*0x10 OID_RT_PRO_SET_CR_NEW_FILTER*/ {1, oid_rt_pro_set_tx_power_control_hdl}, /*0x11 - * OID_RT_PRO_SET_TX_POWER_CONTROL*/ + * OID_RT_PRO_SET_TX_POWER_CONTROL + */ {1, oid_null_function}, /*0x12 OID_RT_PRO_SET_CR_TX_CONFIG*/ {1, oid_null_function}, /*0x13 - * OID_RT_PRO_GET_TX_POWER_CONTROL*/ + * OID_RT_PRO_GET_TX_POWER_CONTROL + */ {1, oid_null_function}, /*0x14 - * OID_RT_PRO_GET_CR_SIGNAL_QUALITY*/ + * 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*/ @@ -203,13 +212,17 @@ static const struct oid_obj_priv oid_rtl_seg_81_80_20[] = { {1, oid_rt_pro_query_rx_packet_received_hdl}, /*0x26*/ {1, oid_rt_pro_query_rx_packet_crc32_error_hdl},/*0x27*/ {1, oid_null_function}, /*0x28 - *OID_RT_PRO_QUERY_CURRENT_ADDRESS*/ + *OID_RT_PRO_QUERY_CURRENT_ADDRESS + */ {1, oid_null_function}, /*0x29 - *OID_RT_PRO_QUERY_PERMANENT_ADDRESS*/ + *OID_RT_PRO_QUERY_PERMANENT_ADDRESS + */ {1, oid_null_function}, /*0x2A - *OID_RT_PRO_SET_PHILIPS_RF_PARAMETERS*/ + *OID_RT_PRO_SET_PHILIPS_RF_PARAMETERS + */ {1, oid_rt_pro_set_carrier_suppression_tx_hdl},/*0x2B - *OID_RT_PRO_SET_CARRIER_SUPPRESSION_TX*/ + *OID_RT_PRO_SET_CARRIER_SUPPRESSION_TX + */ {1, oid_null_function}, /*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*/ diff --git a/drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h b/drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h index 2e9120a..11bcfb7 100644 --- a/drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h +++ b/drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h @@ -82,7 +82,8 @@ * 3. Page8(0x800) */ #define rFPGA0_RFMOD 0x800 /*RF mode & CCK TxSC RF - * BW Setting?? */ + * BW Setting?? + */ #define rFPGA0_TxInfo 0x804 /* Status report?? */ #define rFPGA0_PSDFunction 0x808 #define rFPGA0_TxGainStage 0x80c /* Set TX PWR init gain? */ @@ -119,7 +120,8 @@ #define rFPGA0_AnalogParameter1 0x880 /* Crystal cap setting * RF-R/W protection - * for parameter4?? */ + * for parameter4?? + */ #define rFPGA0_AnalogParameter2 0x884 #define rFPGA0_AnalogParameter3 0x888 /* Useless now */ #define rFPGA0_AnalogParameter4 0x88c @@ -146,7 +148,8 @@ * 5. PageA(0xA00) * * Set Control channel to upper or lower. - * These settings are required only for 40MHz */ + * These settings are required only for 40MHz + */ #define rCCK0_System 0xa00 #define rCCK0_AFESetting 0xa04 /* Disable init gain now */ @@ -155,20 +158,23 @@ #define rCCK0_RxAGC1 0xa0c /* AGC default value, saturation level * Antenna Diversity, RX AGC, LNA Threshold, RX LNA Threshold useless now. - * Not the same as 90 series */ + * Not the same as 90 series + */ #define rCCK0_RxAGC2 0xa10 /* AGC & DAGC */ #define rCCK0_RxHP 0xa14 #define rCCK0_DSPParameter1 0xa18 /* Timing recovery & Channel - * estimation threshold */ + * estimation threshold + */ #define rCCK0_DSPParameter2 0xa1c /* SQ threshold */ #define rCCK0_TxFilter1 0xa20 #define rCCK0_TxFilter2 0xa24 #define rCCK0_DebugPort 0xa28 /* debug port and Tx filter3 */ #define rCCK0_FalseAlarmReport 0xa2c /* 0xa2d useless now 0xa30-a4f - * channel report */ + * channel report + */ #define rCCK0_TRSSIReport 0xa50 #define rCCK0_RxReport 0xa54 /* 0xa57 */ #define rCCK0_FACounterLower 0xa5c /* 0xa5b */ @@ -193,11 +199,13 @@ #define rOFDM0_XDRxIQImbalance 0xc2c #define rOFDM0_RxDetector1 0xc30 /* PD,BW & SBD DM tune - * init gain */ + * init gain + */ #define rOFDM0_RxDetector2 0xc34 /* SBD & Fame Sync. */ #define rOFDM0_RxDetector3 0xc38 /* Frame Sync. */ #define rOFDM0_RxDetector4 0xc3c /* PD, SBD, Frame Sync & - * Short-GI */ + * Short-GI + */ #define rOFDM0_RxDSP 0xc40 /* Rx Sync Path */ #define rOFDM0_CFOandDAGC 0xc44 /* CFO & DAGC */ @@ -283,7 +291,8 @@ #define rTxAGC_Mcs15_Mcs12 0xe1c /* Analog- control in RX_WAIT_CCA : REG: EE0 - * [Analog- Power & Control Register] */ + * [Analog- Power & Control Register] + */ #define rRx_Wait_CCCA 0xe70 #define rAnapar_Ctrl_BB 0xee0 @@ -371,7 +380,8 @@ /* * Bit Mask * - * 1. Page1(0x100) */ + * 1. Page1(0x100) + */ #define bBBResetB 0x100 /* Useless now? */ #define bGlobalResetB 0x200 #define bOFDMTxStart 0x4 @@ -918,7 +928,8 @@ #define bPesudoNoiseState_D 0xffff0000 /* 7. RF Register - * Zebra1 */ + * Zebra1 + */ #define bZebra1_HSSIEnable 0x8 /* Useless */ #define bZebra1_TRxControl 0xc00 #define bZebra1_TRxGainSetting 0x07f diff --git a/drivers/staging/rtl8712/rtl871x_pwrctrl.c b/drivers/staging/rtl8712/rtl871x_pwrctrl.c index 8d7ead6..8f82d85 100644 --- a/drivers/staging/rtl8712/rtl871x_pwrctrl.c +++ b/drivers/staging/rtl8712/rtl871x_pwrctrl.c @@ -52,7 +52,8 @@ void r8712_set_rpwm(struct _adapter *padapter, u8 val8) pwrpriv->cpwm = val8; break; case PS_STATE_S2:/* only for USB normal powersave mode use, - * temp mark some code. */ + * temp mark some code. + */ case PS_STATE_S3: case PS_STATE_S4: pwrpriv->cpwm = val8; diff --git a/drivers/staging/rtl8712/rtl871x_pwrctrl.h b/drivers/staging/rtl8712/rtl871x_pwrctrl.h index 231445e..c82fdf8 100644 --- a/drivers/staging/rtl8712/rtl871x_pwrctrl.h +++ b/drivers/staging/rtl8712/rtl871x_pwrctrl.h @@ -91,7 +91,8 @@ struct pwrctrl_priv { struct mutex mutex_lock; /*volatile*/ u8 rpwm; /* requested power state for fw */ /* fw current power state. updated when 1. read from HCPWM or - * 2. driver lowers power level */ + * 2. driver lowers power level + */ /*volatile*/ u8 cpwm; /*volatile*/ u8 tog; /* toggling */ /*volatile*/ u8 cpwm_tog; /* toggling */ diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl8712/rtl871x_recv.c index 23c1438..cbd2e51 100644 --- a/drivers/staging/rtl8712/rtl871x_recv.c +++ b/drivers/staging/rtl8712/rtl871x_recv.c @@ -265,7 +265,8 @@ union recv_frame *r8712_portctrl(struct _adapter *adapter, if ((psta != NULL) && (psta->ieee8021x_blocked)) { /* blocked - * only accept EAPOL frame */ + * only accept EAPOL frame + */ if (ether_type == 0x888e) { prtnframe = precv_frame; } else { @@ -277,7 +278,8 @@ union recv_frame *r8712_portctrl(struct _adapter *adapter, } else { /* allowed * check decryption status, and decrypt the - * frame if needed */ + * frame if needed + */ prtnframe = precv_frame; /* check is the EAPOL frame or not (Rekey) */ if (ether_type == 0x888e) { @@ -334,19 +336,22 @@ static sint sta2sta_data_frame(struct _adapter *adapter, sta_addr = pattrib->src; } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { /* For Station mode, sa and bssid should always be BSSID, - * and DA is my mac-address */ + * and DA is my mac-address + */ if (memcmp(pattrib->bssid, pattrib->src, ETH_ALEN)) return _FAIL; sta_addr = pattrib->bssid; } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { if (bmcast) { /* For AP mode, if DA == MCAST, then BSSID should - * be also MCAST */ + * be also MCAST + */ if (!IS_MCAST(pattrib->bssid)) return _FAIL; } else { /* not mc-frame */ /* For AP mode, if DA is non-MCAST, then it must be - * BSSID, and bssid == BSSID */ + * BSSID, and bssid == BSSID + */ if (memcmp(pattrib->bssid, pattrib->dst, ETH_ALEN)) return _FAIL; sta_addr = pattrib->src; @@ -391,7 +396,8 @@ static sint ap2sta_data_frame(struct _adapter *adapter, if ((GetFrameSubType(ptr)) == WIFI_DATA_NULL) return _FAIL; /* drop QoS-SubType Data, including QoS NULL, - * excluding QoS-Data */ + * excluding QoS-Data + */ if ((GetFrameSubType(ptr) & WIFI_QOS_DATA_TYPE) == WIFI_QOS_DATA_TYPE) { if (GetFrameSubType(ptr) & (BIT(4) | BIT(5) | BIT(6))) @@ -445,7 +451,8 @@ static sint sta2ap_data_frame(struct _adapter *adapter, if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { /* For AP mode, if DA is non-MCAST, then it must be BSSID, * and bssid == BSSID - * For AP mode, RA=BSSID, TX=STA(SRC_ADDR), A3=DST_ADDR */ + * For AP mode, RA=BSSID, TX=STA(SRC_ADDR), A3=DST_ADDR + */ if (memcmp(pattrib->bssid, mybssid, ETH_ALEN)) return _FAIL; *psta = r8712_get_stainfo(pstapriv, pattrib->src); @@ -619,7 +626,8 @@ sint r8712_wlanhdr_to_ethhdr(union recv_frame *precvframe) (memcmp(psnap_type, (void *)SNAP_ETH_TYPE_APPLETALK_AARP, 2))) || !memcmp(psnap, (void *)bridge_tunnel_header, SNAP_SIZE)) { /* remove RFC1042 or Bridge-Tunnel encapsulation and - * replace EtherType */ + * replace EtherType + */ bsnaphdr = true; } else { /* Leave Ethernet header part of hdr and full payload */ diff --git a/drivers/staging/rtl8712/rtl871x_recv.h b/drivers/staging/rtl8712/rtl871x_recv.h index 77487bb..f419943 100644 --- a/drivers/staging/rtl8712/rtl871x_recv.h +++ b/drivers/staging/rtl8712/rtl871x_recv.h @@ -153,7 +153,8 @@ static inline u8 *get_recvframe_data(union recv_frame *precvframe) static inline u8 *recvframe_pull(union recv_frame *precvframe, sint sz) { /* used for extract sz bytes from rx_data, update rx_data and return - * the updated rx_data to the caller */ + * the updated rx_data to the caller + */ if (precvframe == NULL) return NULL; precvframe->u.hdr.rx_data += sz; @@ -169,7 +170,8 @@ static inline u8 *recvframe_put(union recv_frame *precvframe, sint sz) { /* used for append sz bytes from ptr to rx_tail, update rx_tail and * return the updated rx_tail to the caller - * after putting, rx_tail must be still larger than rx_end. */ + * after putting, rx_tail must be still larger than rx_end. + */ if (precvframe == NULL) return NULL; precvframe->u.hdr.rx_tail += sz; @@ -186,7 +188,8 @@ static inline u8 *recvframe_pull_tail(union recv_frame *precvframe, sint sz) /* rmv data from rx_tail (by yitsen) * used for extract sz bytes from rx_end, update rx_end and return the * updated rx_end to the caller - * after pulling, rx_end must be still larger than rx_data. */ + * after pulling, rx_end must be still larger than rx_data. + */ if (precvframe == NULL) return NULL; precvframe->u.hdr.rx_tail -= sz; diff --git a/drivers/staging/rtl8712/rtl871x_security.h b/drivers/staging/rtl8712/rtl871x_security.h index 2295f0e..fa952e1 100644 --- a/drivers/staging/rtl8712/rtl871x_security.h +++ b/drivers/staging/rtl8712/rtl871x_security.h @@ -90,18 +90,23 @@ struct RT_PMKID_LIST { struct security_priv { u32 AuthAlgrthm; /* 802.11 auth, could be open, shared, - * 8021x and authswitch */ + * 8021x and authswitch + */ u32 PrivacyAlgrthm; /* This specify the privacy for shared - * auth. algorithm. */ + * auth. algorithm. + */ u32 PrivacyKeyIndex; /* this is only valid for legendary - * wep, 0~3 for key id. */ + * wep, 0~3 for key id. + */ union Keytype DefKey[4]; /* this is only valid for def. key */ u32 DefKeylen[4]; u32 XGrpPrivacy; /* This specify the privacy algthm. - * used for Grp key */ + * used for Grp key + */ u32 XGrpKeyid; /* key id used for Grp Key */ union Keytype XGrpKey[2]; /* 802.1x Group Key, for - * inx0 and inx1 */ + * inx0 and inx1 + */ union Keytype XGrptxmickey[2]; union Keytype XGrprxmickey[2]; union pn48 Grptxpn; /* PN48 used for Grp Key xmit. */ @@ -118,9 +123,11 @@ struct security_priv { s32 sw_encrypt; /* from registry_priv */ s32 sw_decrypt; /* from registry_priv */ s32 hw_decrypted; /* if the rx packets is hw_decrypted==false, - * it means the hw has not been ready. */ + * it means the hw has not been ready. + */ u32 ndisauthtype; /* keeps the auth_type & enc_status from upper - * layer ioctl(wpa_supplicant or wzc) */ + * layer ioctl(wpa_supplicant or wzc) + */ u32 ndisencryptstatus; struct wlan_bssid_ex sec_bss; /* for joinbss (h2c buffer) usage */ struct NDIS_802_11_WEP ndiswep; @@ -136,7 +143,8 @@ struct security_priv { u32 btkip_countermeasure_time; /*------------------------------------------------------------------- * For WPA2 Pre-Authentication. - *------------------------------------------------------------------ */ + *------------------------------------------------------------------ + **/ struct RT_PMKID_LIST PMKIDList[NUM_PMKID_CACHE]; u8 PMKIDIndex; }; diff --git a/drivers/staging/rtl8712/rtl871x_sta_mgt.c b/drivers/staging/rtl8712/rtl871x_sta_mgt.c index e11ce28..e2d75e4 100644 --- a/drivers/staging/rtl8712/rtl871x_sta_mgt.c +++ b/drivers/staging/rtl8712/rtl871x_sta_mgt.c @@ -188,7 +188,8 @@ void r8712_free_stainfo(struct _adapter *padapter, struct sta_info *psta) _r8712_init_sta_xmit_priv(&psta->sta_xmitpriv); _r8712_init_sta_recv_priv(&psta->sta_recvpriv); /* for A-MPDU Rx reordering buffer control, - * cancel reordering_ctrl_timer */ + * cancel reordering_ctrl_timer + */ for (i = 0; i < 16; i++) { preorder_ctrl = &psta->recvreorder_ctrl[i]; del_timer(&preorder_ctrl->reordering_ctrl_timer); diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c index 99256ba..be38364 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.c +++ b/drivers/staging/rtl8712/rtl871x_xmit.c @@ -204,7 +204,8 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, { /*If driver xmit ARP packet, driver can set ps mode to initial - * setting. It stands for getting DHCP or fix IP.*/ + * setting. It stands for getting DHCP or fix IP. + */ if (pattrib->ether_type == 0x0806) { if (padapter->pwrctrlpriv.pwr_mode != padapter->registrypriv.power_mgnt) { @@ -232,7 +233,8 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, if (pattrib->ether_type != 0x8712) return _FAIL; /* for mp storing the txcmd per packet, - * according to the info of txcmd to update pattrib */ + * according to the info of txcmd to update pattrib + */ /*get MP_TXDESC_SIZE bytes txcmd per packet*/ _r8712_pktfile_read(&pktfile, (u8 *)&txdesc, TXDESC_SIZE); memcpy(pattrib->ra, pattrib->dst, ETH_ALEN); @@ -244,7 +246,8 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, 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 */ + * to prevent DHCP protocol fail + */ u8 tmp[24]; _r8712_pktfile_read(&pktfile, &tmp[0], 24); @@ -255,7 +258,8 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, ((tmp[21] == 67) && (tmp[23] == 68))) { /* 68 : UDP BOOTP client * 67 : UDP BOOTP server - * Use low rate to send DHCP packet.*/ + * Use low rate to send DHCP packet. + */ pattrib->dhcp_pkt = 1; } } @@ -337,7 +341,8 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, else pattrib->bswenc = false; /* if in MP_STATE, update pkt_attrib from mp_txcmd, and overwrite - * some settings above.*/ + * some settings above. + */ if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) pattrib->priority = (txdesc.txdw1 >> QSEL_SHT) & 0x1f; return _SUCCESS; @@ -438,7 +443,8 @@ static sint xmitframe_addmic(struct _adapter *padapter, } r8712_secgetmic(&micdata, &(mic[0])); /* add mic code and add the mic code length in - * last_txcmdsz */ + * last_txcmdsz + */ memcpy(payload, &(mic[0]), 8); pattrib->last_txcmdsz += 8; payload = payload - pattrib->last_txcmdsz + 8; diff --git a/drivers/staging/rtl8712/rtl871x_xmit.h b/drivers/staging/rtl8712/rtl871x_xmit.h index a9633c3..d899d0c 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.h +++ b/drivers/staging/rtl8712/rtl871x_xmit.h @@ -58,7 +58,8 @@ do { \ } while (0) /* Fixed the Big Endian bug when doing the Tx. - * The Linksys WRH54G will check this.*/ + * The Linksys WRH54G will check this. + */ #define TKIP_IV(pattrib_iv, txpn, keyidx)\ do { \ pattrib_iv[0] = txpn._byte_.TSC1;\ @@ -105,7 +106,8 @@ struct pkt_attrib { u16 seqnum; u16 ether_type; u16 pktlen; /* the original 802.3 pkt raw_data len - * (not include ether_hdr data) */ + * (not include ether_hdr data) + */ u16 last_txcmdsz; u8 pkt_hdrlen; /*the original 802.3 pkt header len*/ @@ -119,7 +121,8 @@ struct pkt_attrib { u8 priority; u8 encrypt; /* when 0 indicate no encrypt. when non-zero, - * indicate the encrypt algorithm*/ + * indicate the encrypt algorithm + */ u8 iv_len; u8 icv_len; unsigned char iv[8]; @@ -176,7 +179,8 @@ struct sta_xmit_priv { spinlock_t lock; sint option; sint apsd_setting; /* When bit mask is on, the associated edca - * queue supports APSD.*/ + * queue supports APSD. + */ struct tx_servq be_q; /* priority == 0,3 */ struct tx_servq bk_q; /* priority == 1,2*/ struct tx_servq vi_q; /*priority == 4,5*/ diff --git a/drivers/staging/rtl8712/usb_halinit.c b/drivers/staging/rtl8712/usb_halinit.c index ad21df1..0b15985 100644 --- a/drivers/staging/rtl8712/usb_halinit.c +++ b/drivers/staging/rtl8712/usb_halinit.c @@ -196,7 +196,8 @@ u8 r8712_usb_hal_bus_init(struct _adapter *padapter) msleep(20); /* Revised POS, */ /* Enable AFE Macro Block's Bandgap and Enable AFE Macro - * Block's Mbias */ + * Block's Mbias + */ r8712_write8(padapter, SPS0_CTRL + 1, 0x53); r8712_write8(padapter, SPS0_CTRL, 0x57); val8 = r8712_read8(padapter, AFE_MISC); diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c index c1a0ca49..3fc65b2 100644 --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c @@ -301,7 +301,8 @@ void rtl871x_intf_stop(struct _adapter *padapter) /*disable_hw_interrupt*/ if (!padapter->bSurpriseRemoved) { /*device still exists, so driver can do i/o operation - * TODO: */ + * TODO: + */ } /* cancel in irp */ @@ -611,7 +612,8 @@ error: } /* rmmod module & unplug(SurpriseRemoved) will call r871xu_dev_remove() - * => how to recognize both */ + * => how to recognize both + */ static void r871xu_dev_remove(struct usb_interface *pusb_intf) { struct net_device *pnetdev = usb_get_intfdata(pusb_intf); @@ -635,12 +637,14 @@ static void r871xu_dev_remove(struct usb_interface *pusb_intf) r8712_free_drv_sw(padapter); /* decrease the reference count of the usb device structure - * when disconnect */ + * when disconnect + */ usb_put_dev(udev); } /* If we didn't unplug usb dongle and remove/insert module, driver * fails on sitesurvey for the first time when device is up. - * Reset usb port for sitesurvey fail issue. */ + * Reset usb port for sitesurvey fail issue. + */ if (udev->state != USB_STATE_NOTATTACHED) usb_reset_device(udev); } diff --git a/drivers/staging/rtl8712/wifi.h b/drivers/staging/rtl8712/wifi.h index 7a352c4..b8af965 100644 --- a/drivers/staging/rtl8712/wifi.h +++ b/drivers/staging/rtl8712/wifi.h @@ -376,7 +376,8 @@ static inline unsigned char *get_hdr_bssid(unsigned char *pframe) /*----------------------------------------------------------------------------- Below is for the security related definition -------------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------- + */ #define _RESERVED_FRAME_TYPE_ 0 #define _SKB_FRAME_TYPE_ 2 #define _PRE_ALLOCMEM_ 1 @@ -420,7 +421,8 @@ static inline unsigned char *get_hdr_bssid(unsigned char *pframe) /* --------------------------------------------------------------------------- Below is the fixed elements... ------------------------------------------------------------------------------*/ + * --------------------------------------------------------------------------- + */ #define _AUTH_ALGM_NUM_ 2 #define _AUTH_SEQ_NUM_ 2 #define _BEACON_ITERVAL_ 2 @@ -448,20 +450,23 @@ static inline unsigned char *get_hdr_bssid(unsigned char *pframe) /*----------------------------------------------------------------------------- Below is the definition for 802.11i / 802.1x -------------------------------------------------------------------------------*/ + *------------------------------------------------------------------------------ + */ #define _IEEE8021X_MGT_ 1 /*WPA */ #define _IEEE8021X_PSK_ 2 /* WPA with pre-shared key */ /*----------------------------------------------------------------------------- Below is the definition for WMM -------------------------------------------------------------------------------*/ + *------------------------------------------------------------------------------ + */ #define _WMM_IE_Length_ 7 /* for WMM STA */ #define _WMM_Para_Element_Length_ 24 /*----------------------------------------------------------------------------- Below is the definition for 802.11n -------------------------------------------------------------------------------*/ + *------------------------------------------------------------------------------ + */ /* block-ack parameters */ #define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002 diff --git a/drivers/staging/rtl8712/wlan_bssdef.h b/drivers/staging/rtl8712/wlan_bssdef.h index fda5707..86a88b4 100644 --- a/drivers/staging/rtl8712/wlan_bssdef.h +++ b/drivers/staging/rtl8712/wlan_bssdef.h @@ -171,7 +171,8 @@ struct NDIS_802_11_REMOVE_KEY { struct NDIS_802_11_WEP { u32 Length; /* Length of this structure */ u32 KeyIndex; /* 0 is the per-client key, - * 1-N are the global keys */ + * 1-N are the global keys + */ u32 KeyLength; /* length of key in bytes */ u8 KeyMaterial[16]; /* variable length depending on above field */ }; @@ -194,7 +195,8 @@ struct wlan_network { struct list_head list; int network_type; /*refer to ieee80211.h for WIRELESS_11A/B/G */ int fixed; /* set to fixed when not to be removed asi - * site-surveying */ + * site-surveying + */ unsigned int last_scanned; /*timestamp for the network */ int aid; /*will only be valid when a BSS is joined. */ int join_res; -- cgit v0.10.2 From 02b23803c6af399473703e26703f74cfff3f22f8 Mon Sep 17 00:00:00 2001 From: Laura Abbott <labbott@redhat.com> Date: Wed, 7 Sep 2016 11:49:59 -0700 Subject: staging: android: ion: Add ioctl to query available heaps Ion clients currently lack a good method to determine what heaps are available and what ids they map to. This leads to tight coupling between user and kernel space and headaches. Add a query ioctl to let userspace know the availability of heaps. Signed-off-by: Laura Abbott <labbott@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/ion-ioctl.c b/drivers/staging/android/ion/ion-ioctl.c index 341ba7d..7e7431d 100644 --- a/drivers/staging/android/ion/ion-ioctl.c +++ b/drivers/staging/android/ion/ion-ioctl.c @@ -22,6 +22,31 @@ #include "ion_priv.h" #include "compat_ion.h" +union ion_ioctl_arg { + struct ion_fd_data fd; + struct ion_allocation_data allocation; + struct ion_handle_data handle; + struct ion_custom_data custom; + struct ion_heap_query query; +}; + +static int validate_ioctl_arg(unsigned int cmd, union ion_ioctl_arg *arg) +{ + int ret = 0; + + switch (cmd) { + case ION_IOC_HEAP_QUERY: + ret = arg->query.reserved0 != 0; + ret |= arg->query.reserved1 != 0; + ret |= arg->query.reserved2 != 0; + break; + default: + break; + } + + return ret ? -EINVAL : 0; +} + /* fix up the cases where the ioctl direction bits are incorrect */ static unsigned int ion_ioctl_dir(unsigned int cmd) { @@ -42,22 +67,27 @@ long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) struct ion_handle *cleanup_handle = NULL; int ret = 0; unsigned int dir; - - union { - struct ion_fd_data fd; - struct ion_allocation_data allocation; - struct ion_handle_data handle; - struct ion_custom_data custom; - } data; + union ion_ioctl_arg data; dir = ion_ioctl_dir(cmd); if (_IOC_SIZE(cmd) > sizeof(data)) return -EINVAL; - if (dir & _IOC_WRITE) - if (copy_from_user(&data, (void __user *)arg, _IOC_SIZE(cmd))) - return -EFAULT; + /* + * The copy_from_user is unconditional here for both read and write + * to do the validate. If there is no write for the ioctl, the + * buffer is cleared + */ + if (copy_from_user(&data, (void __user *)arg, _IOC_SIZE(cmd))) + return -EFAULT; + + ret = validate_ioctl_arg(cmd, &data); + if (WARN_ON_ONCE(ret)) + return ret; + + if (!(dir & _IOC_WRITE)) + memset(&data, 0, sizeof(data)); switch (cmd) { case ION_IOC_ALLOC: @@ -129,6 +159,9 @@ long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) data.custom.arg); break; } + case ION_IOC_HEAP_QUERY: + ret = ion_query_heaps(client, &data.query); + break; default: return -ENOTTY; } diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index a92804f..396ded5 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -1159,6 +1159,48 @@ int ion_sync_for_device(struct ion_client *client, int fd) return 0; } +int ion_query_heaps(struct ion_client *client, struct ion_heap_query *query) +{ + struct ion_device *dev = client->dev; + struct ion_heap_data __user *buffer = u64_to_user_ptr(query->heaps); + int ret = -EINVAL, cnt = 0, max_cnt; + struct ion_heap *heap; + struct ion_heap_data hdata; + + memset(&hdata, 0, sizeof(hdata)); + + down_read(&dev->lock); + if (!buffer) { + query->cnt = dev->heap_cnt; + ret = 0; + goto out; + } + + if (query->cnt <= 0) + goto out; + + max_cnt = query->cnt; + + plist_for_each_entry(heap, &dev->heaps, node) { + strncpy(hdata.name, heap->name, MAX_HEAP_NAME); + hdata.name[sizeof(hdata.name) - 1] = '\0'; + hdata.type = heap->type; + hdata.heap_id = heap->id; + + ret = copy_to_user(&buffer[cnt], + &hdata, sizeof(hdata)); + + cnt++; + if (cnt >= max_cnt) + break; + } + + query->cnt = cnt; +out: + up_read(&dev->lock); + return ret; +} + static int ion_release(struct inode *inode, struct file *file) { struct ion_client *client = file->private_data; @@ -1376,6 +1418,7 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) } } + dev->heap_cnt++; up_write(&dev->lock); } EXPORT_SYMBOL(ion_device_add_heap); diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index 4a78fab..3c3b324 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -102,6 +102,7 @@ struct ion_device { struct dentry *debug_root; struct dentry *heaps_debug_root; struct dentry *clients_debug_root; + int heap_cnt; }; /** @@ -467,4 +468,6 @@ struct ion_handle *ion_handle_get_by_id(struct ion_client *client, int ion_handle_put(struct ion_handle *handle); +int ion_query_heaps(struct ion_client *client, struct ion_heap_query *query); + #endif /* _ION_PRIV_H */ diff --git a/drivers/staging/android/uapi/ion.h b/drivers/staging/android/uapi/ion.h index a9c4e8b..647f130 100644 --- a/drivers/staging/android/uapi/ion.h +++ b/drivers/staging/android/uapi/ion.h @@ -128,6 +128,36 @@ struct ion_custom_data { unsigned long arg; }; +#define MAX_HEAP_NAME 32 + +/** + * struct ion_heap_data - data about a heap + * @name - first 32 characters of the heap name + * @type - heap type + * @heap_id - heap id for the heap + */ +struct ion_heap_data { + char name[MAX_HEAP_NAME]; + __u32 type; + __u32 heap_id; + __u32 reserved0; + __u32 reserved1; + __u32 reserved2; +}; + +/** + * struct ion_heap_query - collection of data about all heaps + * @cnt - total number of heaps to be copied + * @heaps - buffer to copy heap data + */ +struct ion_heap_query { + __u32 cnt; /* Total number of heaps to be copied */ + __u32 reserved0; /* align to 64bits */ + __u64 heaps; /* buffer to be populated */ + __u32 reserved1; + __u32 reserved2; +}; + #define ION_IOC_MAGIC 'I' /** @@ -194,4 +224,13 @@ struct ion_custom_data { */ #define ION_IOC_CUSTOM _IOWR(ION_IOC_MAGIC, 6, struct ion_custom_data) +/** + * DOC: ION_IOC_HEAP_QUERY - information about available heaps + * + * Takes an ion_heap_query structure and populates information about + * available Ion heaps. + */ +#define ION_IOC_HEAP_QUERY _IOWR(ION_IOC_MAGIC, 8, \ + struct ion_heap_query) + #endif /* _UAPI_LINUX_ION_H */ -- cgit v0.10.2 From 76a96d86c8348c61b4abcb492a4892575833c3f9 Mon Sep 17 00:00:00 2001 From: Laura Abbott <labbott@redhat.com> Date: Tue, 30 Aug 2016 17:04:27 -0700 Subject: devicetree: bindings for Ion This adds a base set of devicetree bindings for the Ion memory manager. This supports setting up the generic set of heaps and their properties. Signed-off-by: Laura Abbott <labbott@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/devicetree.txt b/drivers/staging/android/ion/devicetree.txt new file mode 100644 index 0000000..16871527 --- /dev/null +++ b/drivers/staging/android/ion/devicetree.txt @@ -0,0 +1,51 @@ +Ion Memory Manager + +Ion is a memory manager that allows for sharing of buffers via dma-buf. +Ion allows for different types of allocation via an abstraction called +a 'heap'. A heap represents a specific type of memory. Each heap has +a different type. There can be multiple instances of the same heap +type. + +Specific heap instances are tied to heap IDs. Heap IDs are not to be specified +in the devicetree. + +Required properties for Ion + +- compatible: "linux,ion" PLUS a compatible property for the device + +All child nodes of a linux,ion node are interpreted as heaps + +required properties for heaps + +- compatible: compatible string for a heap type PLUS a compatible property +for the specific instance of the heap. Current heap types +-- linux,ion-heap-system +-- linux,ion-heap-system-contig +-- linux,ion-heap-carveout +-- linux,ion-heap-chunk +-- linux,ion-heap-dma +-- linux,ion-heap-custom + +Optional properties +- memory-region: A phandle to a memory region. Required for DMA heap type +(see reserved-memory.txt for details on the reservation) + +Example: + + ion { + compatbile = "hisilicon,ion", "linux,ion"; + + ion-system-heap { + compatbile = "hisilicon,system-heap", "linux,ion-heap-system" + }; + + ion-camera-region { + compatible = "hisilicon,camera-heap", "linux,ion-heap-dma" + memory-region = <&camera_region>; + }; + + ion-fb-region { + compatbile = "hisilicon,fb-heap", "linux,ion-heap-dma" + memory-region = <&fb_region>; + }; + } -- cgit v0.10.2 From 13439479c7de873f2ad5399b9224249c928decd8 Mon Sep 17 00:00:00 2001 From: Laura Abbott <labbott@redhat.com> Date: Tue, 30 Aug 2016 17:04:28 -0700 Subject: staging: ion: Add files for parsing the devicetree Devicetree is the preferred mechanism for platform definition these days. Add a set of files for supporting Ion with devicetree. This includes a set of bindings for heaps common across all devices and parsing methods. Clients may use the standard bindings or they can call the parsing functions along with their own parsing for platform specific heaps. Signed-off-by: Laura Abbott <labbott@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig index 19c1572..8a54ddc 100644 --- a/drivers/staging/android/ion/Kconfig +++ b/drivers/staging/android/ion/Kconfig @@ -40,3 +40,14 @@ config ION_HISI Choose this option if you wish to use ion on Hisilicon Platform. source "drivers/staging/android/ion/hisilicon/Kconfig" + +config ION_OF + bool "Devicetree support for Ion" + depends on ION && OF + help + Provides base support for defining Ion heaps in devicetree + and setting them up. Also includes functions for platforms + to parse the devicetree and expand for their own custom + extensions + + If using Ion and devicetree, you should say Y here diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile index 376c2b2..5d630a0 100644 --- a/drivers/staging/android/ion/Makefile +++ b/drivers/staging/android/ion/Makefile @@ -9,4 +9,5 @@ endif obj-$(CONFIG_ION_DUMMY) += ion_dummy_driver.o obj-$(CONFIG_ION_TEGRA) += tegra/ obj-$(CONFIG_ION_HISI) += hisilicon/ +obj-$(CONFIG_ION_OF) += ion_of.o diff --git a/drivers/staging/android/ion/ion_of.c b/drivers/staging/android/ion/ion_of.c new file mode 100644 index 0000000..de0899a --- /dev/null +++ b/drivers/staging/android/ion/ion_of.c @@ -0,0 +1,185 @@ +/* + * Based on work from: + * Andrew Andrianov <andrew@ncrmnt.org> + * Google + * The Linux Foundation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <linux/of_address.h> +#include <linux/clk.h> +#include <linux/dma-mapping.h> +#include <linux/cma.h> +#include <linux/dma-contiguous.h> +#include <linux/io.h> +#include <linux/of_reserved_mem.h> +#include "ion.h" +#include "ion_priv.h" +#include "ion_of.h" + +int ion_parse_dt_heap_common(struct device_node *heap_node, + struct ion_platform_heap *heap, + struct ion_of_heap *compatible) +{ + int i; + + for (i = 0; compatible[i].name != NULL; i++) { + if (of_device_is_compatible(heap_node, compatible[i].compat)) + break; + } + + if (compatible[i].name == NULL) + return -ENODEV; + + heap->id = compatible[i].heap_id; + heap->type = compatible[i].type; + heap->name = compatible[i].name; + heap->align = compatible[i].align; + + /* Some kind of callback function pointer? */ + + pr_info("%s: id %d type %d name %s align %lx\n", __func__, + heap->id, heap->type, heap->name, heap->align); + return 0; +} + +int ion_setup_heap_common(struct platform_device *parent, + struct device_node *heap_node, + struct ion_platform_heap *heap) +{ + int ret = 0; + + switch (heap->type) { + case ION_HEAP_TYPE_CARVEOUT: + case ION_HEAP_TYPE_CHUNK: + if (heap->base && heap->size) + return 0; + + ret = of_reserved_mem_device_init(heap->priv); + break; + default: + break; + } + + return ret; +} + +struct ion_platform_data *ion_parse_dt(struct platform_device *pdev, + struct ion_of_heap *compatible) +{ + int num_heaps, ret; + const struct device_node *dt_node = pdev->dev.of_node; + struct device_node *node; + struct ion_platform_heap *heaps; + struct ion_platform_data *data; + int i = 0; + + num_heaps = of_get_available_child_count(dt_node); + + if (!num_heaps) + return ERR_PTR(-EINVAL); + + heaps = devm_kzalloc(&pdev->dev, + sizeof(struct ion_platform_heap)*num_heaps, + GFP_KERNEL); + if (!heaps) + return ERR_PTR(-ENOMEM); + + data = devm_kzalloc(&pdev->dev, sizeof(struct ion_platform_data), + GFP_KERNEL); + if (!data) + return ERR_PTR(-ENOMEM); + + for_each_available_child_of_node(dt_node, node) { + struct platform_device *heap_pdev; + + ret = ion_parse_dt_heap_common(node, &heaps[i], compatible); + if (ret) + return ERR_PTR(ret); + + heap_pdev = of_platform_device_create(node, heaps[i].name, + &pdev->dev); + if (!pdev) + return ERR_PTR(-ENOMEM); + heap_pdev->dev.platform_data = &heaps[i]; + + heaps[i].priv = &heap_pdev->dev; + + ret = ion_setup_heap_common(pdev, node, &heaps[i]); + if (ret) + goto out_err; + i++; + } + + + data->heaps = heaps; + data->nr = num_heaps; + return data; + +out_err: + for ( ; i >= 0; i--) + if (heaps[i].priv) + of_device_unregister(to_platform_device(heaps[i].priv)); + + return ERR_PTR(ret); +} + +void ion_destroy_platform_data(struct ion_platform_data *data) +{ + int i; + + for (i = 0; i < data->nr; i++) + if (data->heaps[i].priv) + of_device_unregister(to_platform_device( + data->heaps[i].priv)); +} + +#ifdef CONFIG_OF_RESERVED_MEM +#include <linux/of.h> +#include <linux/of_fdt.h> +#include <linux/of_reserved_mem.h> + +static int rmem_ion_device_init(struct reserved_mem *rmem, struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct ion_platform_heap *heap = pdev->dev.platform_data; + + heap->base = rmem->base; + heap->base = rmem->size; + pr_debug("%s: heap %s base %pa size %pa dev %p\n", __func__, + heap->name, &rmem->base, &rmem->size, dev); + return 0; +} + +static void rmem_ion_device_release(struct reserved_mem *rmem, + struct device *dev) +{ + return; +} + +static const struct reserved_mem_ops rmem_dma_ops = { + .device_init = rmem_ion_device_init, + .device_release = rmem_ion_device_release, +}; + +static int __init rmem_ion_setup(struct reserved_mem *rmem) +{ + phys_addr_t size = rmem->size; + + size = size / 1024; + + pr_info("Ion memory setup at %pa size %pa MiB\n", + &rmem->base, &size); + rmem->ops = &rmem_dma_ops; + return 0; +} +RESERVEDMEM_OF_DECLARE(ion, "ion-region", rmem_ion_setup); +#endif diff --git a/drivers/staging/android/ion/ion_of.h b/drivers/staging/android/ion/ion_of.h new file mode 100644 index 0000000..8241a17 --- /dev/null +++ b/drivers/staging/android/ion/ion_of.h @@ -0,0 +1,37 @@ +/* + * Based on work from: + * Andrew Andrianov <andrew@ncrmnt.org> + * Google + * The Linux Foundation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _ION_OF_H +#define _ION_OF_H + +struct ion_of_heap { + const char *compat; + int heap_id; + int type; + const char *name; + int align; +}; + +#define PLATFORM_HEAP(_compat, _id, _type, _name) \ +{ \ + .compat = _compat, \ + .heap_id = _id, \ + .type = _type, \ + .name = _name, \ + .align = PAGE_SIZE, \ +} + +struct ion_platform_data *ion_parse_dt(struct platform_device *pdev, + struct ion_of_heap *compatible); + +void ion_destroy_platform_data(struct ion_platform_data *data); + +#endif -- cgit v0.10.2 From b6e336dbeda85585c3ba6d935753d8240e18baf1 Mon Sep 17 00:00:00 2001 From: Laura Abbott <labbott@redhat.com> Date: Tue, 30 Aug 2016 17:04:29 -0700 Subject: staging: android: ion: Convert hi6220 to common platform Now that we have common devicetree bindings, convert hisilicon platform to use the binding and parsing methods. Signed-off-by: Laura Abbott <labbott@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/hisilicon/hi6220_ion.c b/drivers/staging/android/ion/hisilicon/hi6220_ion.c index fe9f0fd..f392db2 100644 --- a/drivers/staging/android/ion/hisilicon/hi6220_ion.c +++ b/drivers/staging/android/ion/hisilicon/hi6220_ion.c @@ -19,181 +19,74 @@ #include <linux/mm.h> #include "../ion_priv.h" #include "../ion.h" +#include "../ion_of.h" -struct hi6220_ion_type_table { - const char *name; - enum ion_heap_type type; +struct hisi_ion_dev { + struct ion_heap **heaps; + struct ion_device *idev; + struct ion_platform_data *data; }; -static struct hi6220_ion_type_table ion_type_table[] = { - {"ion_system", ION_HEAP_TYPE_SYSTEM}, - {"ion_system_contig", ION_HEAP_TYPE_SYSTEM_CONTIG}, - {"ion_carveout", ION_HEAP_TYPE_CARVEOUT}, - {"ion_chunk", ION_HEAP_TYPE_CHUNK}, - {"ion_dma", ION_HEAP_TYPE_DMA}, - {"ion_custom", ION_HEAP_TYPE_CUSTOM}, +static struct ion_of_heap hisi_heaps[] = { + PLATFORM_HEAP("hisilicon,sys_user", 0, + ION_HEAP_TYPE_SYSTEM, "sys_user"), + PLATFORM_HEAP("hisilicon,sys_contig", 1, + ION_HEAP_TYPE_SYSTEM_CONTIG, "sys_contig"), + PLATFORM_HEAP("hisilicon,cma", ION_HEAP_TYPE_DMA, ION_HEAP_TYPE_DMA, + "cma"), + {} }; -static struct ion_device *idev; -static int num_heaps; -static struct ion_heap **heaps; -static struct ion_platform_heap **heaps_data; - -static int get_type_by_name(const char *name, enum ion_heap_type *type) +static int hi6220_ion_probe(struct platform_device *pdev) { + struct hisi_ion_dev *ipdev; int i; - for (i = 0; i < ARRAY_SIZE(ion_type_table); i++) { - if (strncmp(name, ion_type_table[i].name, strlen(name))) - continue; - - *type = ion_type_table[i].type; - return 0; - } - - return -EINVAL; -} - -static int hi6220_set_platform_data(struct platform_device *pdev) -{ - unsigned int base; - unsigned int size; - unsigned int id; - const char *heap_name; - const char *type_name; - enum ion_heap_type type; - int ret; - struct device_node *np; - struct ion_platform_heap *p_data; - const struct device_node *dt_node = pdev->dev.of_node; - int index = 0; - - for_each_child_of_node(dt_node, np) - num_heaps++; - - heaps_data = devm_kzalloc(&pdev->dev, - sizeof(struct ion_platform_heap *) * - num_heaps, - GFP_KERNEL); - if (!heaps_data) + ipdev = devm_kzalloc(&pdev->dev, sizeof(*ipdev), GFP_KERNEL); + if (!ipdev) return -ENOMEM; - for_each_child_of_node(dt_node, np) { - ret = of_property_read_string(np, "heap-name", &heap_name); - if (ret < 0) { - pr_err("check the name of node %s\n", np->name); - continue; - } - - ret = of_property_read_u32(np, "heap-id", &id); - if (ret < 0) { - pr_err("check the id %s\n", np->name); - continue; - } - - ret = of_property_read_u32(np, "heap-base", &base); - if (ret < 0) { - pr_err("check the base of node %s\n", np->name); - continue; - } - - ret = of_property_read_u32(np, "heap-size", &size); - if (ret < 0) { - pr_err("check the size of node %s\n", np->name); - continue; - } - - ret = of_property_read_string(np, "heap-type", &type_name); - if (ret < 0) { - pr_err("check the type of node %s\n", np->name); - continue; - } - - ret = get_type_by_name(type_name, &type); - if (ret < 0) { - pr_err("type name error %s!\n", type_name); - continue; - } - pr_info("heap index %d : name %s base 0x%x size 0x%x id %d type %d\n", - index, heap_name, base, size, id, type); - - p_data = devm_kzalloc(&pdev->dev, - sizeof(struct ion_platform_heap), - GFP_KERNEL); - if (!p_data) - return -ENOMEM; + platform_set_drvdata(pdev, ipdev); - p_data->name = heap_name; - p_data->base = base; - p_data->size = size; - p_data->id = id; - p_data->type = type; + ipdev->idev = ion_device_create(NULL); + if (!ipdev->idev) + return -ENOMEM; - heaps_data[index] = p_data; - index++; - } - return 0; -} + ipdev->data = ion_parse_dt(pdev, hisi_heaps); + if (IS_ERR(ipdev->data)) + return PTR_ERR(ipdev->data); -static int hi6220_ion_probe(struct platform_device *pdev) -{ - int i; - int err; - static struct ion_platform_heap *p_heap; - - idev = ion_device_create(NULL); - err = hi6220_set_platform_data(pdev); - if (err) { - pr_err("ion set platform data error!\n"); - goto err_free_idev; - } - heaps = devm_kzalloc(&pdev->dev, - sizeof(struct ion_heap *) * num_heaps, - GFP_KERNEL); - if (!heaps) { - err = -ENOMEM; - goto err_free_idev; + ipdev->heaps = devm_kzalloc(&pdev->dev, + sizeof(struct ion_heap)*ipdev->data->nr, + GFP_KERNEL); + if (!ipdev->heaps) { + ion_destroy_platform_data(ipdev->data); + return -ENOMEM; } - /* - * create the heaps as specified in the dts file - */ - for (i = 0; i < num_heaps; i++) { - p_heap = heaps_data[i]; - heaps[i] = ion_heap_create(p_heap); - if (IS_ERR_OR_NULL(heaps[i])) { - err = PTR_ERR(heaps[i]); - goto err_free_heaps; + for (i = 0; i < ipdev->data->nr; i++) { + ipdev->heaps[i] = ion_heap_create(&ipdev->data->heaps[i]); + if (!ipdev->heaps) { + ion_destroy_platform_data(ipdev->data); + return -ENOMEM; } - - ion_device_add_heap(idev, heaps[i]); - - pr_info("%s: adding heap %s of type %d with %lx@%lx\n", - __func__, p_heap->name, p_heap->type, - p_heap->base, (unsigned long)p_heap->size); + ion_device_add_heap(ipdev->idev, ipdev->heaps[i]); } - return err; - -err_free_heaps: - for (i = 0; i < num_heaps; ++i) { - ion_heap_destroy(heaps[i]); - heaps[i] = NULL; - } -err_free_idev: - ion_device_destroy(idev); - - return err; + return 0; } static int hi6220_ion_remove(struct platform_device *pdev) { + struct hisi_ion_dev *ipdev; int i; - for (i = 0; i < num_heaps; i++) { - ion_heap_destroy(heaps[i]); - heaps[i] = NULL; + ipdev = platform_get_drvdata(pdev); + + for (i = 0; i < ipdev->data->nr; i++) { + ion_heap_destroy(ipdev->heaps[i]); } - ion_device_destroy(idev); + ion_destroy_platform_data(ipdev->data); + ion_device_destroy(ipdev->idev); return 0; } -- cgit v0.10.2 From bb84f356ac48f8704ac23edefbcf59661361df0c Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Mon, 12 Sep 2016 15:37:37 +0530 Subject: staging: emxx_udc: Remove unnecessary blank line This patch fixes the checkpatch.pl warning: Blank lines aren't necessary before a close brace '}' Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/emxx_udc/emxx_udc.c b/drivers/staging/emxx_udc/emxx_udc.c index f4d9000..f6233ec 100644 --- a/drivers/staging/emxx_udc/emxx_udc.c +++ b/drivers/staging/emxx_udc/emxx_udc.c @@ -131,7 +131,6 @@ static void _nbu2ss_dump_register(struct nbu2ss_udc *udc) reg_data = _nbu2ss_readl( (u32 *)IO_ADDRESS(USB_BASE_ADDRESS + i + 12)); dev_dbg(&udc->dev, " %08x\n", (int)reg_data); - } spin_lock(&udc->lock); -- cgit v0.10.2 From e62641475b20a3a7a65491dcf4cb9b10e5ee9567 Mon Sep 17 00:00:00 2001 From: Baoyou Xie <baoyou.xie@linaro.org> Date: Thu, 8 Sep 2016 16:46:07 +0800 Subject: staging/lustre/obdclass: add missing header dependencies We get 1 warning when building kernel with W=1: drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c:157:5: warning: no previous prototype for 'obd_sysctl_init' [-Wmissing-prototypes] In fact, this function is declared in ../../include/obd_class.h, so this patch add missing header dependencies. Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org> Acked-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c index bcf005d..aea1abd 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c @@ -45,6 +45,7 @@ #include "../../include/obd_support.h" #include "../../include/lprocfs_status.h" +#include "../../include/obd_class.h" struct static_lustre_uintvalue_attr { struct { -- cgit v0.10.2 From ac4455e09b21572fd0c63d54ef76328f36d39cec Mon Sep 17 00:00:00 2001 From: Anchal Jain <anchalj109@gmail.com> Date: Fri, 9 Sep 2016 20:32:16 +0530 Subject: staging: lustre: lustre: obdclass: Modify return statement Modify the return statement. The Coccinelle semantic patch used to make this change is as follows: @@ expression e, ret; @@ -ret = +return e; -return ret; Delete the declaration of the return variable rc, as it is no longer used. Signed-off-by: Anchal Jain <anchalj109@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/obdclass/llog_cat.c b/drivers/staging/lustre/lustre/obdclass/llog_cat.c index a82a295..d28751a 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_cat.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_cat.c @@ -123,7 +123,6 @@ out: int llog_cat_close(const struct lu_env *env, struct llog_handle *cathandle) { struct llog_handle *loghandle, *n; - int rc; list_for_each_entry_safe(loghandle, n, &cathandle->u.chd.chd_head, u.phd.phd_entry) { @@ -134,8 +133,7 @@ int llog_cat_close(const struct lu_env *env, struct llog_handle *cathandle) /* if handle was stored in ctxt, remove it too */ if (cathandle->lgh_ctxt->loc_handle == cathandle) cathandle->lgh_ctxt->loc_handle = NULL; - rc = llog_close(env, cathandle); - return rc; + return llog_close(env, cathandle); } EXPORT_SYMBOL(llog_cat_close); -- cgit v0.10.2 From 5cb6b910680c7002a2ce587c006d7390fd98c32c Mon Sep 17 00:00:00 2001 From: Nicolas Iooss <nicolas.iooss_linux@m4x.org> Date: Sat, 3 Sep 2016 15:55:23 +0200 Subject: staging: rtl8192u: do not use undefined $(TOPDIR) in Makefile drivers/staging/rtl8192u/ieee80211/Makefile uses $(TOPDIR) to configure an include directory, without defining this variable first. The path which is configured is therefore "/drivers/net/wireless", which does not seem to be the intended path. Remove the offending line. Signed-off-by: Nicolas Iooss <nicolas.iooss_linux@m4x.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8192u/ieee80211/Makefile b/drivers/staging/rtl8192u/ieee80211/Makefile index b5d0c2e..9e3f432 100644 --- a/drivers/staging/rtl8192u/ieee80211/Makefile +++ b/drivers/staging/rtl8192u/ieee80211/Makefile @@ -1,7 +1,6 @@ NIC_SELECT = RTL8192U -ccflags-y := -I$(TOPDIR)/drivers/net/wireless -ccflags-y += -O2 +ccflags-y := -O2 ccflags-y += -DJACKSON_NEW_8187 -DJACKSON_NEW_RX ieee80211-rsl-objs := ieee80211_rx.o \ -- cgit v0.10.2 From ec65ef8e8aa15126970a85348359a43a4c5c301a Mon Sep 17 00:00:00 2001 From: Baoyou Xie <baoyou.xie@linaro.org> Date: Sun, 4 Sep 2016 14:33:35 +0800 Subject: Staging: rtl8192e: mark symbols static where possible We get a few warnings when building kernel with W=1: drivers/staging/rtl8192e/rtllib_softmac.c:279:13: warning: no previous declaration for 'softmac_ps_mgmt_xmit' [-Wmissing-declarations] drivers/staging/rtl8192e/rtllib_softmac.c:773:24: warning: no previous declaration for 'rtllib_authentication_req' [-Wmissing-declarations] .... In fact, these functions are only used in the file in which they are declared and don't need a declaration, but can be made static. In addition, some of these functions are declared in different files, it looks like that we need to clean the codes of this driver up, but we can repress these warnings first, then clean it up. so this patch marks these functions with 'static' now. Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c index e84ffc8..da74dc4 100644 --- a/drivers/staging/rtl8192e/rtllib_softmac.c +++ b/drivers/staging/rtl8192e/rtllib_softmac.c @@ -276,8 +276,9 @@ inline void softmac_mgmt_xmit(struct sk_buff *skb, struct rtllib_device *ieee) } } -inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, - struct rtllib_device *ieee) +static inline void +softmac_ps_mgmt_xmit(struct sk_buff *skb, + struct rtllib_device *ieee) { short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE; struct rtllib_hdr_3addr *header = @@ -770,8 +771,10 @@ void rtllib_start_scan_syncro(struct rtllib_device *ieee, u8 is_mesh) } EXPORT_SYMBOL(rtllib_start_scan_syncro); -inline struct sk_buff *rtllib_authentication_req(struct rtllib_network *beacon, - struct rtllib_device *ieee, int challengelen, u8 *daddr) +static inline struct sk_buff * +rtllib_authentication_req(struct rtllib_network *beacon, + struct rtllib_device *ieee, + int challengelen, u8 *daddr) { struct sk_buff *skb; struct rtllib_authentication *auth; @@ -1130,7 +1133,7 @@ static void rtllib_resp_to_probe(struct rtllib_device *ieee, u8 *dest) } -inline int SecIsInPMKIDList(struct rtllib_device *ieee, u8 *bssid) +static inline int SecIsInPMKIDList(struct rtllib_device *ieee, u8 *bssid) { int i = 0; @@ -1146,8 +1149,9 @@ inline int SecIsInPMKIDList(struct rtllib_device *ieee, u8 *bssid) return i; } -inline struct sk_buff *rtllib_association_req(struct rtllib_network *beacon, - struct rtllib_device *ieee) +static inline struct sk_buff * +rtllib_association_req(struct rtllib_network *beacon, + struct rtllib_device *ieee) { struct sk_buff *skb; struct rtllib_assoc_request_frame *hdr; @@ -2209,8 +2213,9 @@ static void rtllib_process_action(struct rtllib_device *ieee, } } -inline int rtllib_rx_assoc_resp(struct rtllib_device *ieee, struct sk_buff *skb, - struct rtllib_rx_stats *rx_stats) +static inline int +rtllib_rx_assoc_resp(struct rtllib_device *ieee, struct sk_buff *skb, + struct rtllib_rx_stats *rx_stats) { u16 errcode; int aid; @@ -2344,8 +2349,9 @@ static void rtllib_rx_auth_resp(struct rtllib_device *ieee, struct sk_buff *skb) } } -inline int rtllib_rx_auth(struct rtllib_device *ieee, struct sk_buff *skb, - struct rtllib_rx_stats *rx_stats) +static inline int +rtllib_rx_auth(struct rtllib_device *ieee, struct sk_buff *skb, + struct rtllib_rx_stats *rx_stats) { if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) { @@ -2361,7 +2367,8 @@ inline int rtllib_rx_auth(struct rtllib_device *ieee, struct sk_buff *skb, return 0; } -inline int rtllib_rx_deauth(struct rtllib_device *ieee, struct sk_buff *skb) +static inline int +rtllib_rx_deauth(struct rtllib_device *ieee, struct sk_buff *skb) { struct rtllib_hdr_3addr *header = (struct rtllib_hdr_3addr *) skb->data; u16 frame_ctl; @@ -3397,8 +3404,9 @@ static int rtllib_wpa_set_encryption(struct rtllib_device *ieee, return ret; } -inline struct sk_buff *rtllib_disauth_skb(struct rtllib_network *beacon, - struct rtllib_device *ieee, u16 asRsn) +static inline struct sk_buff * +rtllib_disauth_skb(struct rtllib_network *beacon, + struct rtllib_device *ieee, u16 asRsn) { struct sk_buff *skb; struct rtllib_disauth *disauth; @@ -3423,8 +3431,9 @@ inline struct sk_buff *rtllib_disauth_skb(struct rtllib_network *beacon, return skb; } -inline struct sk_buff *rtllib_disassociate_skb(struct rtllib_network *beacon, - struct rtllib_device *ieee, u16 asRsn) +static inline struct sk_buff * +rtllib_disassociate_skb(struct rtllib_network *beacon, + struct rtllib_device *ieee, u16 asRsn) { struct sk_buff *skb; struct rtllib_disassoc *disass; -- cgit v0.10.2 From 4fe514dc2049b06e3cd2851513202b518ee6ee6d Mon Sep 17 00:00:00 2001 From: Amit Ghadge <amitg.b14@gmail.com> Date: Sun, 4 Sep 2016 22:53:35 +0530 Subject: Staging: rtl8188eu: ioctl_linux: Clean up if function returned NULL on failure. Clean some all functions to return NULL on failure. Used !x instead of x==NULL. Signed-off-by: Amit Ghadge <amitg.b14@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c index 44d3ed6..4de9dbc 100644 --- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c @@ -403,7 +403,7 @@ 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 + offsetof(struct ndis_802_11_wep, KeyMaterial); pwep = (struct ndis_802_11_wep *)rtw_malloc(wep_total_len); - if (pwep == NULL) { + if (!pwep) { RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, (" wpa_set_encryption: pwep allocate fail !!!\n")); goto exit; } @@ -444,7 +444,7 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE)) { /* sta mode */ psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv)); - if (psta == NULL) { + if (!psta) { ; } else { if (strcmp(param->u.crypt.alg, "none") != 0) @@ -479,7 +479,7 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, } } pbcmc_sta = rtw_get_bcmc_stainfo(padapter); - if (pbcmc_sta == NULL) { + if (!pbcmc_sta) { ; } else { /* Jeff: don't disable ieee8021x_blocked while clearing key */ @@ -505,9 +505,9 @@ static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ie int group_cipher = 0, pairwise_cipher = 0; int ret = 0; - if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL)) { + if ((ielen > MAX_WPA_IE_LEN) || (!pie)) { _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS); - if (pie == NULL) + if (!pie) return ret; else return -EINVAL; @@ -515,7 +515,7 @@ static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ie if (ielen) { buf = kmemdup(pie, ielen, GFP_KERNEL); - if (buf == NULL) { + if (!buf) { ret = -ENOMEM; goto exit; } @@ -1052,7 +1052,7 @@ static int rtw_wx_set_mlme(struct net_device *dev, struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); struct iw_mlme *mlme = (struct iw_mlme *)extra; - if (mlme == NULL) + if (!mlme) return -1; DBG_88E("%s\n", __func__); @@ -1899,7 +1899,7 @@ static int rtw_wx_set_enc_ext(struct net_device *dev, param_len = sizeof(struct ieee_param) + pext->key_len; param = (struct ieee_param *)rtw_malloc(param_len); - if (param == NULL) + if (!param) return -1; memset(param, 0, param_len); @@ -2064,7 +2064,7 @@ static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p) } param = (struct ieee_param *)rtw_malloc(p->length); - if (param == NULL) { + if (!param) { ret = -ENOMEM; goto out; } @@ -2257,13 +2257,13 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, } } - if (strcmp(param->u.crypt.alg, "none") == 0 && (psta == NULL)) { + 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 == NULL)) { + 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; @@ -2277,7 +2277,7 @@ 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 == NULL) { + if (!pwep) { DBG_88E(" r871x_set_encryption: pwep allocate fail !!!\n"); goto exit; } @@ -2704,7 +2704,7 @@ 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 == NULL) { + if (!pmlmepriv->wps_beacon_ie) { DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__); return -EINVAL; } @@ -2739,7 +2739,7 @@ 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 == NULL) { + if (!pmlmepriv->wps_probe_resp_ie) { DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__); return -EINVAL; } @@ -2769,7 +2769,7 @@ 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 == NULL) { + if (!pmlmepriv->wps_assoc_resp_ie) { DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__); return -EINVAL; } @@ -2871,7 +2871,7 @@ static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p) } param = (struct ieee_param *)rtw_malloc(p->length); - if (param == NULL) { + if (!param) { ret = -ENOMEM; goto out; } @@ -2981,7 +2981,7 @@ static int rtw_wx_set_priv(struct net_device *dev, pmlmepriv->wps_probe_req_ie = NULL; pmlmepriv->wps_probe_req_ie = rtw_malloc(cp_sz); - if (pmlmepriv->wps_probe_req_ie == NULL) { + if (!pmlmepriv->wps_probe_req_ie) { pr_info("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__); ret = -EINVAL; goto FREE_EXT; -- cgit v0.10.2 From 2e3656dcf9b5b35514535d628929777cd9366565 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli <luca@lucaceresoli.net> Date: Tue, 6 Sep 2016 18:36:53 +0200 Subject: staging: rtl8188eu: remove unimplemented functions declaration These functions have been declared without any implementation since the first commit (58c434013a22fccfdb14abc2bb8408ca29073b76) and there has been no mention of them in following commits. Signed-off-by: Luca Ceresoli <luca@lucaceresoli.net> Cc: Kyle Kuffermann <kyle.kuffermann@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/recv_osdep.h b/drivers/staging/rtl8188eu/include/recv_osdep.h index cad3158..7550d58 100644 --- a/drivers/staging/rtl8188eu/include/recv_osdep.h +++ b/drivers/staging/rtl8188eu/include/recv_osdep.h @@ -26,13 +26,9 @@ void _rtw_free_recv_priv(struct recv_priv *precvpriv); s32 rtw_recv_entry(struct recv_frame *precv_frame); int rtw_recv_indicatepkt(struct adapter *adapter, struct recv_frame *recv_frame); -void rtw_recv_returnpacket(struct net_device *cnxt, struct sk_buff *retpkt); void rtw_handle_tkip_mic_err(struct adapter *padapter, u8 bgroup); -int rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter); -void rtw_free_recv_priv(struct recv_priv *precvpriv); - void rtw_os_recv_resource_alloc(struct recv_frame *recvfr); int rtw_os_recvbuf_resource_alloc(struct adapter *adapt, struct recv_buf *buf); -- cgit v0.10.2 From 181c6c679de13d1f6df182279e6b242a4352972b Mon Sep 17 00:00:00 2001 From: Luca Ceresoli <luca@lucaceresoli.net> Date: Tue, 6 Sep 2016 18:36:54 +0200 Subject: staging: rtl8188eu: declare internal function as static This function is only used inside rtw_recv.c. Which is quite logical, since it's a timer callback: it is passed as the _fn argument to setup_timer(). So it is internal to rtw_recv.c and should be static. Signed-off-by: Luca Ceresoli <luca@lucaceresoli.net> Cc: Bhaktipriya Shridhar <bhaktipriya96@gmail.com> Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Cc: Geliang Tang <geliangtang@163.com> Cc: Jakub Sitnicki <jsitnicki@gmail.com> Cc: Ivan Safonov <insafonov@gmail.com> Cc: Kyle Kuffermann <kyle.kuffermann@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c index 977bb25..1063617 100644 --- a/drivers/staging/rtl8188eu/core/rtw_recv.c +++ b/drivers/staging/rtl8188eu/core/rtw_recv.c @@ -39,7 +39,7 @@ static u8 rtw_rfc1042_header[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; -void rtw_signal_stat_timer_hdl(unsigned long data); +static void rtw_signal_stat_timer_hdl(unsigned long data); void _rtw_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv) { @@ -2088,7 +2088,7 @@ _recv_entry_drop: return ret; } -void rtw_signal_stat_timer_hdl(unsigned long data) +static void rtw_signal_stat_timer_hdl(unsigned long data) { struct adapter *adapter = (struct adapter *)data; struct recv_priv *recvpriv = &adapter->recvpriv; -- cgit v0.10.2 From ac66b628a9f3e9b153aec31aba9e4f3ff2a1fc09 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli <luca@lucaceresoli.net> Date: Tue, 6 Sep 2016 18:36:55 +0200 Subject: staging: rtl8188eu: remove rtw_proc_{init,remove}_one MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rtw_proc_init_one() and rtw_proc_remove_one() are two very long functions that are supposed to create a bunch of proc entries to access debugging features of the driver. But both of them are under #if 0 since their first commit three years ago (5adef66acf73705ae95ea0b1e6b5fc7f17d82d30), replaced by two empty functions. Should they be moved out of #if 0 thay would not even compile, as they used functions that have been removed years ago (create_proc_read_entry()) and they use variables that are not defined (e.g. rtw_proc_cnt). rtw_proc_init_one() mentions several other functions that are not mentioned anywhere else in the kernel tree. Thus, after the present patch, all of those other functions can be cleanly removed as well, as they will be not mentioned anymore, not even in disabled code. Subsequent commits remove those other functions. Should anybody want to implement (in a proper way) the mentioned debugging features, they can still fetch this code from the git history. Signed-off-by: Luca Ceresoli <luca@lucaceresoli.net> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Kyle Kuffermann <kyle.kuffermann@gmail.com> Cc: Binoy Jayan <binoy.jayan@linaro.org> Cc: Arnd Bergmann <arnd@arndb.de> Cc: "Rémy Oudompheng" <remyoudompheng@gmail.com> Cc: Ivan Safonov <insafonov@gmail.com> Cc: Jakub Sitnicki <jsitnicki@gmail.com> Cc: Alexey Khoroshilov <khoroshilov@ispras.ru> Cc: Bhaktipriya Shridhar <bhaktipriya96@gmail.com> Cc: Bhumika Goyal <bhumirks@gmail.com> Cc: devel@driverdev.osuosl.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/osdep_intf.h b/drivers/staging/rtl8188eu/include/osdep_intf.h index 54fca79..dbd7dc4 100644 --- a/drivers/staging/rtl8188eu/include/osdep_intf.h +++ b/drivers/staging/rtl8188eu/include/osdep_intf.h @@ -34,7 +34,6 @@ int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); int rtw_init_netdev_name(struct net_device *pnetdev, const char *ifname); struct net_device *rtw_init_netdev(struct adapter *padapter); u16 rtw_recv_select_queue(struct sk_buff *skb); -void rtw_proc_remove_one(struct net_device *dev); int pm_netdev_open(struct net_device *pnetdev, u8 bnormal); void rtw_ips_dev_unload(struct adapter *padapter); diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c index 3b606ee..79b1755 100644 --- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c +++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c @@ -149,352 +149,6 @@ MODULE_PARM_DESC(monitor_enable, "Enable monitor inferface (default: false)"); static int netdev_open(struct net_device *pnetdev); static int netdev_close(struct net_device *pnetdev); -/* dummy routines */ -void rtw_proc_remove_one(struct net_device *dev) -{ -} - -static void rtw_proc_init_one(struct net_device *dev) -{ -} - -#if 0 /* TODO: Convert these to /sys */ -static void rtw_proc_init_one(struct net_device *dev) -{ - struct proc_dir_entry *dir_dev = NULL; - struct proc_dir_entry *entry = NULL; - struct adapter *padapter = rtw_netdev_priv(dev); - u8 rf_type; - - if (rtw_proc == NULL) { - memcpy(rtw_proc_name, DRV_NAME, sizeof(DRV_NAME)); - - rtw_proc = create_proc_entry(rtw_proc_name, S_IFDIR, - init_net.proc_net); - if (rtw_proc == NULL) { - DBG_88E(KERN_ERR "Unable to create rtw_proc directory\n"); - return; - } - - entry = create_proc_read_entry("ver_info", S_IFREG | S_IRUGO, - rtw_proc, proc_get_drv_version, - dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - } - - if (padapter->dir_dev == NULL) { - padapter->dir_dev = create_proc_entry(dev->name, - S_IFDIR | S_IRUGO | S_IXUGO, - rtw_proc); - dir_dev = padapter->dir_dev; - if (dir_dev == NULL) { - if (rtw_proc_cnt == 0 && rtw_proc) { - remove_proc_entry(rtw_proc_name, init_net.proc_net); - rtw_proc = NULL; - } - - pr_info("Unable to create dir_dev directory\n"); - return; - } - } else { - return; - } - - rtw_proc_cnt++; - - entry = create_proc_read_entry("write_reg", S_IFREG | S_IRUGO, - dir_dev, proc_get_write_reg, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - entry->write_proc = proc_set_write_reg; - - entry = create_proc_read_entry("read_reg", S_IFREG | S_IRUGO, - dir_dev, proc_get_read_reg, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - entry->write_proc = proc_set_read_reg; - - - entry = create_proc_read_entry("fwstate", S_IFREG | S_IRUGO, - dir_dev, proc_get_fwstate, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("sec_info", S_IFREG | S_IRUGO, - dir_dev, proc_get_sec_info, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("mlmext_state", S_IFREG | S_IRUGO, - dir_dev, proc_get_mlmext_state, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("qos_option", S_IFREG | S_IRUGO, - dir_dev, proc_get_qos_option, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("ht_option", S_IFREG | S_IRUGO, - dir_dev, proc_get_ht_option, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("rf_info", S_IFREG | S_IRUGO, - dir_dev, proc_get_rf_info, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("ap_info", S_IFREG | S_IRUGO, - dir_dev, proc_get_ap_info, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("adapter_state", S_IFREG | S_IRUGO, - dir_dev, proc_getstruct adapter_state, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("trx_info", S_IFREG | S_IRUGO, - dir_dev, proc_get_trx_info, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("mac_reg_dump1", S_IFREG | S_IRUGO, - dir_dev, proc_get_mac_reg_dump1, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("mac_reg_dump2", S_IFREG | S_IRUGO, - dir_dev, proc_get_mac_reg_dump2, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("mac_reg_dump3", S_IFREG | S_IRUGO, - dir_dev, proc_get_mac_reg_dump3, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("bb_reg_dump1", S_IFREG | S_IRUGO, - dir_dev, proc_get_bb_reg_dump1, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("bb_reg_dump2", S_IFREG | S_IRUGO, - dir_dev, proc_get_bb_reg_dump2, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("bb_reg_dump3", S_IFREG | S_IRUGO, - dir_dev, proc_get_bb_reg_dump3, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("rf_reg_dump1", S_IFREG | S_IRUGO, - dir_dev, proc_get_rf_reg_dump1, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("rf_reg_dump2", S_IFREG | S_IRUGO, - dir_dev, proc_get_rf_reg_dump2, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type)); - if ((RF_1T2R == rf_type) || (RF_1T1R == rf_type)) { - entry = create_proc_read_entry("rf_reg_dump3", - S_IFREG | S_IRUGO, dir_dev, - proc_get_rf_reg_dump3, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("rf_reg_dump4", - S_IFREG | S_IRUGO, dir_dev, - proc_get_rf_reg_dump4, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - } - -#ifdef CONFIG_88EU_AP_MODE - - entry = create_proc_read_entry("all_sta_info", S_IFREG | S_IRUGO, - dir_dev, proc_get_all_sta_info, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } -#endif - - entry = create_proc_read_entry("best_channel", S_IFREG | S_IRUGO, - dir_dev, proc_get_best_channel, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - - entry = create_proc_read_entry("rx_signal", S_IFREG | S_IRUGO, - dir_dev, proc_get_rx_signal, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - entry->write_proc = proc_set_rx_signal; - entry = create_proc_read_entry("ht_enable", S_IFREG | S_IRUGO, - dir_dev, proc_get_ht_enable, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - entry->write_proc = proc_set_ht_enable; - - entry = create_proc_read_entry("cbw40_enable", S_IFREG | S_IRUGO, - dir_dev, proc_get_cbw40_enable, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - entry->write_proc = proc_set_cbw40_enable; - - entry = create_proc_read_entry("ampdu_enable", S_IFREG | S_IRUGO, - dir_dev, proc_get_ampdu_enable, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - entry->write_proc = proc_set_ampdu_enable; - - entry = create_proc_read_entry("rx_stbc", S_IFREG | S_IRUGO, - dir_dev, proc_get_rx_stbc, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - entry->write_proc = proc_set_rx_stbc; - - entry = create_proc_read_entry("path_rssi", S_IFREG | S_IRUGO, - dir_dev, proc_get_two_path_rssi, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - entry = create_proc_read_entry("rssi_disp", S_IFREG | S_IRUGO, - dir_dev, proc_get_rssi_disp, dev); - if (!entry) { - pr_info("Unable to create_proc_read_entry!\n"); - return; - } - entry->write_proc = proc_set_rssi_disp; -} - -void rtw_proc_remove_one(struct net_device *dev) -{ - struct proc_dir_entry *dir_dev = NULL; - struct adapter *padapter = rtw_netdev_priv(dev); - u8 rf_type; - - dir_dev = padapter->dir_dev; - padapter->dir_dev = NULL; - - if (dir_dev) { - remove_proc_entry("write_reg", dir_dev); - remove_proc_entry("read_reg", dir_dev); - remove_proc_entry("fwstate", dir_dev); - remove_proc_entry("sec_info", dir_dev); - remove_proc_entry("mlmext_state", dir_dev); - remove_proc_entry("qos_option", dir_dev); - remove_proc_entry("ht_option", dir_dev); - remove_proc_entry("rf_info", dir_dev); - remove_proc_entry("ap_info", dir_dev); - remove_proc_entry("adapter_state", dir_dev); - remove_proc_entry("trx_info", dir_dev); - remove_proc_entry("mac_reg_dump1", dir_dev); - remove_proc_entry("mac_reg_dump2", dir_dev); - remove_proc_entry("mac_reg_dump3", dir_dev); - remove_proc_entry("bb_reg_dump1", dir_dev); - remove_proc_entry("bb_reg_dump2", dir_dev); - remove_proc_entry("bb_reg_dump3", dir_dev); - remove_proc_entry("rf_reg_dump1", dir_dev); - remove_proc_entry("rf_reg_dump2", dir_dev); - rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type)); - if ((RF_1T2R == rf_type) || (RF_1T1R == rf_type)) { - remove_proc_entry("rf_reg_dump3", dir_dev); - remove_proc_entry("rf_reg_dump4", dir_dev); - } -#ifdef CONFIG_88EU_AP_MODE - remove_proc_entry("all_sta_info", dir_dev); -#endif - - remove_proc_entry("best_channel", dir_dev); - remove_proc_entry("rx_signal", dir_dev); - remove_proc_entry("cbw40_enable", dir_dev); - remove_proc_entry("ht_enable", dir_dev); - remove_proc_entry("ampdu_enable", dir_dev); - remove_proc_entry("rx_stbc", dir_dev); - remove_proc_entry("path_rssi", dir_dev); - remove_proc_entry("rssi_disp", dir_dev); - remove_proc_entry(dev->name, rtw_proc); - dir_dev = NULL; - } else { - return; - } - rtw_proc_cnt--; - - if (rtw_proc_cnt == 0) { - if (rtw_proc) { - remove_proc_entry("ver_info", rtw_proc); - - remove_proc_entry(rtw_proc_name, init_net.proc_net); - rtw_proc = NULL; - } - } -} -#endif - static void loadparam(struct adapter *padapter, struct net_device *pnetdev) { struct registry_priv *registry_par = &padapter->registrypriv; @@ -946,7 +600,6 @@ static int _netdev_open(struct net_device *pnetdev) } if (padapter->intf_start) padapter->intf_start(padapter); - rtw_proc_init_one(pnetdev); rtw_led_control(padapter, LED_CTL_NO_LINK); diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c index ea77082..cf33f65 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c @@ -448,11 +448,9 @@ static void rtw_usb_if1_deinit(struct adapter *if1) free_mlme_ap_info(if1); #endif - if (pnetdev) { - /* will call netdev_close() */ - unregister_netdev(pnetdev); - rtw_proc_remove_one(pnetdev); - } + if (pnetdev) + unregister_netdev(pnetdev); /* will call netdev_close() */ + rtl88eu_mon_deinit(if1->pmondev); rtw_cancel_all_timer(if1); -- cgit v0.10.2 From f1a2b7ab269884a17bbbd9cee643975e857b6fbe Mon Sep 17 00:00:00 2001 From: Luca Ceresoli <luca@lucaceresoli.net> Date: Tue, 6 Sep 2016 18:36:56 +0200 Subject: staging: rtl8188eu: remove useless include MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the removal of rtw_proc_init_one() the proc filesystem is not mentioned in this driver. So this include becomes useless. Signed-off-by: Luca Ceresoli <luca@lucaceresoli.net> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Binoy Jayan <binoy.jayan@linaro.org> Cc: Anish Bhatt <anish@gatech.edu> Cc: "Rémy Oudompheng" <remyoudompheng@gmail.com> Cc: Alexey Khoroshilov <khoroshilov@ispras.ru> Cc: Kyle Kuffermann <kyle.kuffermann@gmail.com> Cc: devel@driverdev.osuosl.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/osdep_service.h b/drivers/staging/rtl8188eu/include/osdep_service.h index 2df2b65..9047b6d 100644 --- a/drivers/staging/rtl8188eu/include/osdep_service.h +++ b/drivers/staging/rtl8188eu/include/osdep_service.h @@ -44,7 +44,6 @@ #include <linux/if_arp.h> #include <linux/rtnetlink.h> #include <linux/delay.h> -#include <linux/proc_fs.h> /* Necessary because we use the proc fs */ #include <linux/interrupt.h> /* for struct tasklet_struct */ #include <linux/ip.h> #include <linux/kthread.h> -- cgit v0.10.2 From da25a8ec6b2d66d9510358173b8da4c80d686c2b Mon Sep 17 00:00:00 2001 From: Luca Ceresoli <luca@lucaceresoli.net> Date: Tue, 6 Sep 2016 18:36:57 +0200 Subject: staging: rtl8188eu: remove unused debugging functions These functions were only mentioned in the rtw_proc_init_one() function in drivers/staging/rtl8188eu/os_dep/os_intfs.c, which was under #if 0 and has now been removed completely. As they are not used anywhere, and also violate the coding style rules, remove them. Signed-off-by: Luca Ceresoli <luca@lucaceresoli.net> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Kyle Kuffermann <kyle.kuffermann@gmail.com> Cc: Chris Elliott <chris@uksysadmin.com> Cc: Ivan Safonov <insafonov@gmail.com> Cc: devel@driverdev.osuosl.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_debug.c b/drivers/staging/rtl8188eu/core/rtw_debug.c index db5c952..60d8c7b 100644 --- a/drivers/staging/rtl8188eu/core/rtw_debug.c +++ b/drivers/staging/rtl8188eu/core/rtw_debug.c @@ -138,144 +138,6 @@ int proc_set_read_reg(struct file *file, const char __user *buffer, return count; } -int proc_get_fwstate(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - int len = 0; - - len += snprintf(page + len, count - len, "fwstate=0x%x\n", get_fwstate(pmlmepriv)); - - *eof = 1; - return len; -} - -int proc_get_sec_info(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct security_priv *psecuritypriv = &padapter->securitypriv; - - int len = 0; - - len += snprintf(page + len, count - len, "auth_alg=0x%x, enc_alg=0x%x, auth_type=0x%x, enc_type=0x%x\n", - psecuritypriv->dot11AuthAlgrthm, psecuritypriv->dot11PrivacyAlgrthm, - psecuritypriv->ndisauthtype, psecuritypriv->ndisencryptstatus); - - *eof = 1; - return len; -} - -int proc_get_mlmext_state(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - int len = 0; - - len += snprintf(page + len, count - len, "pmlmeinfo->state=0x%x\n", pmlmeinfo->state); - - *eof = 1; - return len; -} - -int proc_get_qos_option(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - int len = 0; - - len += snprintf(page + len, count - len, "qos_option=%d\n", pmlmepriv->qospriv.qos_option); - - *eof = 1; - return len; -} - -int proc_get_ht_option(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - int len = 0; - - len += snprintf(page + len, count - len, "ht_option=%d\n", pmlmepriv->htpriv.ht_option); - *eof = 1; - return len; -} - -int proc_get_rf_info(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - int len = 0; - - len += snprintf(page + len, count - len, "cur_ch=%d, cur_bw=%d, cur_ch_offset=%d\n", - pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset); - *eof = 1; - return len; -} - -int proc_get_ap_info(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct sta_info *psta; - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct wlan_network *cur_network = &pmlmepriv->cur_network; - struct sta_priv *pstapriv = &padapter->stapriv; - int len = 0; - - psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress); - if (psta) { - int i; - struct recv_reorder_ctrl *preorder_ctrl; - - len += snprintf(page + len, count - len, "SSID=%s\n", cur_network->network.Ssid.Ssid); - len += snprintf(page + len, count - len, "sta's macaddr:%pM\n", psta->hwaddr); - len += snprintf(page + len, count - len, "cur_channel=%d, cur_bwmode=%d, cur_ch_offset=%d\n", pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset); - len += snprintf(page + len, count - len, "rtsen=%d, cts2slef=%d\n", psta->rtsen, psta->cts2self); - len += snprintf(page + len, count - len, "state=0x%x, aid=%d, macid=%d, raid=%d\n", psta->state, psta->aid, psta->mac_id, psta->raid); - len += snprintf(page + len, count - len, "qos_en=%d, ht_en=%d, init_rate=%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate); - len += snprintf(page + len, count - len, "bwmode=%d, ch_offset=%d, sgi=%d\n", psta->htpriv.bwmode, psta->htpriv.ch_offset, psta->htpriv.sgi); - len += snprintf(page + len, count - len, "ampdu_enable = %d\n", psta->htpriv.ampdu_enable); - len += snprintf(page + len, count - len, "agg_enable_bitmap=%x, candidate_tid_bitmap=%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap); - - for (i = 0; i < 16; i++) { - preorder_ctrl = &psta->recvreorder_ctrl[i]; - if (preorder_ctrl->enable) - len += snprintf(page + len, count - len, "tid=%d, indicate_seq=%d\n", i, preorder_ctrl->indicate_seq); - } - } else { - len += snprintf(page + len, count - len, "can't get sta's macaddr, cur_network's macaddr: %pM\n", cur_network->network.MacAddress); - } - - *eof = 1; - return len; -} - int proc_get_adapter_state(char *page, char **start, off_t offset, int count, int *eof, void *data) @@ -291,599 +153,6 @@ int proc_get_adapter_state(char *page, char **start, return len; } -int proc_get_trx_info(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct recv_priv *precvpriv = &padapter->recvpriv; - int len = 0; - - len += snprintf(page + len, count - len, "free_xmitbuf_cnt=%d, free_xmitframe_cnt=%d, free_ext_xmitbuf_cnt=%d, free_recvframe_cnt=%d\n", - pxmitpriv->free_xmitbuf_cnt, pxmitpriv->free_xmitframe_cnt, pxmitpriv->free_xmit_extbuf_cnt, precvpriv->free_recvframe_cnt); - len += snprintf(page + len, count - len, "rx_urb_pending_cn=%d\n", precvpriv->rx_pending_cnt); - - *eof = 1; - return len; -} - -int proc_get_mac_reg_dump1(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - int len = 0; - int i, j = 1; - - len += snprintf(page + len, count - len, "\n======= MAC REG =======\n"); - - for (i = 0x0; i < 0x300; i += 4) { - if (j%4 == 1) - len += snprintf(page + len, count - len, "0x%02x", i); - len += snprintf(page + len, count - len, " 0x%08x ", usb_read32(padapter, i)); - if ((j++)%4 == 0) - len += snprintf(page + len, count - len, "\n"); - } - - *eof = 1; - return len; -} - -int proc_get_mac_reg_dump2(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - int len = 0; - int i, j = 1; - - len += snprintf(page + len, count - len, "\n======= MAC REG =======\n"); - memset(page, 0, count); - for (i = 0x300; i < 0x600; i += 4) { - if (j%4 == 1) - len += snprintf(page + len, count - len, "0x%02x", i); - len += snprintf(page + len, count - len, " 0x%08x ", usb_read32(padapter, i)); - if ((j++)%4 == 0) - len += snprintf(page + len, count - len, "\n"); - } - - *eof = 1; - return len; -} - -int proc_get_mac_reg_dump3(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - int len = 0; - int i, j = 1; - - len += snprintf(page + len, count - len, "\n======= MAC REG =======\n"); - - for (i = 0x600; i < 0x800; i += 4) { - if (j%4 == 1) - len += snprintf(page + len, count - len, "0x%02x", i); - len += snprintf(page + len, count - len, " 0x%08x ", usb_read32(padapter, i)); - if ((j++)%4 == 0) - len += snprintf(page + len, count - len, "\n"); - } - - *eof = 1; - return len; -} - -int proc_get_bb_reg_dump1(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - int len = 0; - int i, j = 1; - - len += snprintf(page + len, count - len, "\n======= BB REG =======\n"); - for (i = 0x800; i < 0xB00; i += 4) { - if (j%4 == 1) - len += snprintf(page + len, count - len, "0x%02x", i); - len += snprintf(page + len, count - len, " 0x%08x ", usb_read32(padapter, i)); - if ((j++)%4 == 0) - len += snprintf(page + len, count - len, "\n"); - } - *eof = 1; - return len; -} - -int proc_get_bb_reg_dump2(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - int len = 0; - int i, j = 1; - - len += snprintf(page + len, count - len, "\n======= BB REG =======\n"); - for (i = 0xB00; i < 0xE00; i += 4) { - if (j%4 == 1) - len += snprintf(page + len, count - len, "0x%02x", i); - len += snprintf(page + len, count - len, " 0x%08x ", usb_read32(padapter, i)); - if ((j++)%4 == 0) - len += snprintf(page + len, count - len, "\n"); - } - *eof = 1; - return len; -} - -int proc_get_bb_reg_dump3(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - int len = 0; - int i, j = 1; - - len += snprintf(page + len, count - len, "\n======= BB REG =======\n"); - for (i = 0xE00; i < 0x1000; i += 4) { - if (j%4 == 1) - len += snprintf(page + len, count - len, "0x%02x", i); - len += snprintf(page + len, count - len, " 0x%08x ", usb_read32(padapter, i)); - if ((j++)%4 == 0) - len += snprintf(page + len, count - len, "\n"); - } - *eof = 1; - return len; -} - -int proc_get_rf_reg_dump1(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - int len = 0; - int i, j = 1, path; - u32 value; - - len += snprintf(page + len, count - len, "\n======= RF REG =======\n"); - path = 1; - len += snprintf(page + len, count - len, "\nRF_Path(%x)\n", path); - for (i = 0; i < 0xC0; i++) { - value = rtw_hal_read_rfreg(padapter, path, i, 0xffffffff); - if (j%4 == 1) - len += snprintf(page + len, count - len, "0x%02x ", i); - len += snprintf(page + len, count - len, " 0x%08x ", value); - if ((j++)%4 == 0) - len += snprintf(page + len, count - len, "\n"); - } - *eof = 1; - return len; -} - -int proc_get_rf_reg_dump2(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - int len = 0; - int i, j = 1, path; - u32 value; - - len += snprintf(page + len, count - len, "\n======= RF REG =======\n"); - path = 1; - len += snprintf(page + len, count - len, "\nRF_Path(%x)\n", path); - for (i = 0xC0; i < 0x100; i++) { - value = rtw_hal_read_rfreg(padapter, path, i, 0xffffffff); - if (j%4 == 1) - len += snprintf(page + len, count - len, "0x%02x ", i); - len += snprintf(page + len, count - len, " 0x%08x ", value); - if ((j++)%4 == 0) - len += snprintf(page + len, count - len, "\n"); - } - *eof = 1; - return len; -} - -int proc_get_rf_reg_dump3(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - int len = 0; - int i, j = 1, path; - u32 value; - - len += snprintf(page + len, count - len, "\n======= RF REG =======\n"); - path = 2; - len += snprintf(page + len, count - len, "\nRF_Path(%x)\n", path); - for (i = 0; i < 0xC0; i++) { - value = rtw_hal_read_rfreg(padapter, path, i, 0xffffffff); - if (j%4 == 1) - len += snprintf(page + len, count - len, "0x%02x ", i); - len += snprintf(page + len, count - len, " 0x%08x ", value); - if ((j++)%4 == 0) - len += snprintf(page + len, count - len, "\n"); - } - - *eof = 1; - return len; -} - - -int proc_get_rf_reg_dump4(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - int len = 0; - int i, j = 1, path; - u32 value; - - len += snprintf(page + len, count - len, "\n======= RF REG =======\n"); - path = 2; - len += snprintf(page + len, count - len, "\nRF_Path(%x)\n", path); - for (i = 0xC0; i < 0x100; i++) { - value = rtw_hal_read_rfreg(padapter, path, i, 0xffffffff); - if (j%4 == 1) - len += snprintf(page + len, count - len, "0x%02x ", i); - len += snprintf(page + len, count - len, " 0x%08x ", value); - if ((j++)%4 == 0) - len += snprintf(page + len, count - len, "\n"); - } - *eof = 1; - return len; -} - - - -int proc_get_rx_signal(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - int len = 0; - - len = snprintf(page + len, count, - "rssi:%d\n" - "rxpwdb:%d\n" - "signal_strength:%u\n" - "signal_qual:%u\n" - "noise:%u\n", - padapter->recvpriv.rssi, - padapter->recvpriv.rxpwdb, - padapter->recvpriv.signal_strength, - padapter->recvpriv.signal_qual, - padapter->recvpriv.noise - ); - - *eof = 1; - return len; -} - -int proc_set_rx_signal(struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - char tmp[32]; - u32 is_signal_dbg; - s32 signal_strength; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - int num = sscanf(tmp, "%u %u", &is_signal_dbg, &signal_strength); - - is_signal_dbg = is_signal_dbg == 0 ? 0 : 1; - if (is_signal_dbg && num != 2) - return count; - - signal_strength = clamp(signal_strength, 0, 100); - - padapter->recvpriv.is_signal_dbg = is_signal_dbg; - padapter->recvpriv.signal_strength_dbg = signal_strength; - - if (is_signal_dbg) - DBG_88E("set %s %u\n", "DBG_SIGNAL_STRENGTH", signal_strength); - else - DBG_88E("set %s\n", "HW_SIGNAL_STRENGTH"); - } - return count; -} - -int proc_get_ht_enable(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - int len = 0; - - if (pregpriv) - len += snprintf(page + len, count - len, - "%d\n", - pregpriv->ht_enable - ); - *eof = 1; - return len; -} - -int proc_set_ht_enable(struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - char tmp[32]; - s32 mode = 0; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - if (pregpriv) { - pregpriv->ht_enable = mode; - pr_info("ht_enable=%d\n", pregpriv->ht_enable); - } - } - - return count; -} - -int proc_get_cbw40_enable(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - - int len = 0; - - if (pregpriv) - len += snprintf(page + len, count - len, - "%d\n", - pregpriv->cbw40_enable - ); - - *eof = 1; - return len; -} - -int proc_set_cbw40_enable(struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - char tmp[32]; - s32 mode = 0; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - if (pregpriv) { - pregpriv->cbw40_enable = mode; - pr_info("cbw40_enable=%d\n", mode); - } - } - return count; -} - -int proc_get_ampdu_enable(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - - int len = 0; - - if (pregpriv) - len += snprintf(page + len, count - len, - "%d\n", - pregpriv->ampdu_enable - ); - - *eof = 1; - return len; -} - -int proc_set_ampdu_enable(struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - char tmp[32]; - s32 mode = 0; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - if (pregpriv) { - pregpriv->ampdu_enable = mode; - pr_info("ampdu_enable=%d\n", mode); - } - } - return count; -} - -int proc_get_two_path_rssi(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - - int len = 0; - - if (padapter) - len += snprintf(page + len, count - len, - "%d %d\n", - padapter->recvpriv.RxRssi[0], - padapter->recvpriv.RxRssi[1] - ); - - *eof = 1; - return len; -} - -int proc_get_rx_stbc(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - - int len = 0; - - if (pregpriv) - len += snprintf(page + len, count - len, - "%d\n", - pregpriv->rx_stbc - ); - - *eof = 1; - return len; -} - -int proc_set_rx_stbc(struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - char tmp[32]; - u32 mode = 0; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - if (pregpriv) { - pregpriv->rx_stbc = mode; - netdev_info(dev, "rx_stbc=%d\n", mode); - } - } - return count; -} - -int proc_get_rssi_disp(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - *eof = 1; - return 0; -} - -int proc_set_rssi_disp(struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - char tmp[32]; - u32 enable = 0; - - if (count < 1) { - DBG_88E("argument size is less than 1\n"); - return -EFAULT; - } - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - int num = sscanf(tmp, "%x", &enable); - - if (num != 1) { - DBG_88E("invalid set_rssi_disp parameter!\n"); - return count; - } - - if (enable) { - DBG_88E("Turn On Rx RSSI Display Function\n"); - padapter->bRxRSSIDisplay = enable; - } else { - DBG_88E("Turn Off Rx RSSI Display Function\n"); - padapter->bRxRSSIDisplay = 0; - } - } - return count; -} - -#ifdef CONFIG_88EU_AP_MODE - -int proc_get_all_sta_info(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct sta_info *psta; - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct sta_priv *pstapriv = &padapter->stapriv; - int i, j; - struct list_head *plist, *phead; - struct recv_reorder_ctrl *preorder_ctrl; - int len = 0; - - - len += snprintf(page + len, count - len, "sta_dz_bitmap=0x%x, tim_bitmap=0x%x\n", pstapriv->sta_dz_bitmap, pstapriv->tim_bitmap); - - spin_lock_bh(&pstapriv->sta_hash_lock); - - for (i = 0; i < NUM_STA; i++) { - phead = &pstapriv->sta_hash[i]; - plist = phead->next; - - while (phead != plist) { - psta = container_of(plist, struct sta_info, hash_list); - - plist = plist->next; - - len += snprintf(page + len, count - len, "sta's macaddr: %pM\n", psta->hwaddr); - len += snprintf(page + len, count - len, "rtsen=%d, cts2slef=%d\n", psta->rtsen, psta->cts2self); - len += snprintf(page + len, count - len, "state=0x%x, aid=%d, macid=%d, raid=%d\n", psta->state, psta->aid, psta->mac_id, psta->raid); - len += snprintf(page + len, count - len, "qos_en=%d, ht_en=%d, init_rate=%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate); - len += snprintf(page + len, count - len, "bwmode=%d, ch_offset=%d, sgi=%d\n", psta->htpriv.bwmode, psta->htpriv.ch_offset, psta->htpriv.sgi); - len += snprintf(page + len, count - len, "ampdu_enable = %d\n", psta->htpriv.ampdu_enable); - len += snprintf(page + len, count - len, "agg_enable_bitmap=%x, candidate_tid_bitmap=%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap); - len += snprintf(page + len, count - len, "sleepq_len=%d\n", psta->sleepq_len); - len += snprintf(page + len, count - len, "capability=0x%x\n", psta->capability); - len += snprintf(page + len, count - len, "flags=0x%x\n", psta->flags); - len += snprintf(page + len, count - len, "wpa_psk=0x%x\n", psta->wpa_psk); - len += snprintf(page + len, count - len, "wpa2_group_cipher=0x%x\n", psta->wpa2_group_cipher); - len += snprintf(page + len, count - len, "wpa2_pairwise_cipher=0x%x\n", psta->wpa2_pairwise_cipher); - len += snprintf(page + len, count - len, "qos_info=0x%x\n", psta->qos_info); - len += snprintf(page + len, count - len, "dot118021XPrivacy=0x%x\n", psta->dot118021XPrivacy); - - for (j = 0; j < 16; j++) { - preorder_ctrl = &psta->recvreorder_ctrl[j]; - if (preorder_ctrl->enable) - len += snprintf(page + len, count - len, "tid=%d, indicate_seq=%d\n", j, preorder_ctrl->indicate_seq); - } - } - } - spin_unlock_bh(&pstapriv->sta_hash_lock); - - *eof = 1; - return len; -} -#endif - int proc_get_best_channel(char *page, char **start, off_t offset, int count, int *eof, void *data) diff --git a/drivers/staging/rtl8188eu/include/rtw_debug.h b/drivers/staging/rtl8188eu/include/rtw_debug.h index 7ed4cad..95590a1 100644 --- a/drivers/staging/rtl8188eu/include/rtw_debug.h +++ b/drivers/staging/rtl8188eu/include/rtw_debug.h @@ -129,133 +129,12 @@ int proc_get_read_reg(char *page, char **start, int proc_set_read_reg(struct file *file, const char __user *buffer, unsigned long count, void *data); -int proc_get_fwstate(char *page, char **start, - off_t offset, int count, - int *eof, void *data); -int proc_get_sec_info(char *page, char **start, - off_t offset, int count, - int *eof, void *data); -int proc_get_mlmext_state(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_get_qos_option(char *page, char **start, - off_t offset, int count, - int *eof, void *data); -int proc_get_ht_option(char *page, char **start, - off_t offset, int count, - int *eof, void *data); -int proc_get_rf_info(char *page, char **start, - off_t offset, int count, - int *eof, void *data); -int proc_get_ap_info(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - int proc_get_adapter_state(char *page, char **start, off_t offset, int count, int *eof, void *data); -int proc_get_trx_info(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_get_mac_reg_dump1(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_get_mac_reg_dump2(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_get_mac_reg_dump3(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_get_bb_reg_dump1(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_get_bb_reg_dump2(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_get_bb_reg_dump3(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_get_rf_reg_dump1(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_get_rf_reg_dump2(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_get_rf_reg_dump3(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_get_rf_reg_dump4(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -#ifdef CONFIG_88EU_AP_MODE - -int proc_get_all_sta_info(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -#endif - int proc_get_best_channel(char *page, char **start, off_t offset, int count, int *eof, void *data); -int proc_get_rx_signal(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_set_rx_signal(struct file *file, const char __user *buffer, - unsigned long count, void *data); - -int proc_get_ht_enable(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_set_ht_enable(struct file *file, const char __user *buffer, - unsigned long count, void *data); - -int proc_get_cbw40_enable(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_set_cbw40_enable(struct file *file, const char __user *buffer, - unsigned long count, void *data); - -int proc_get_ampdu_enable(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_set_ampdu_enable(struct file *file, const char __user *buffer, - unsigned long count, void *data); - -int proc_get_rx_stbc(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_set_rx_stbc(struct file *file, const char __user *buffer, - unsigned long count, void *data); - -int proc_get_two_path_rssi(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_get_rssi_disp(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_set_rssi_disp(struct file *file, const char __user *buffer, - unsigned long count, void *data); - #endif /* __RTW_DEBUG_H__ */ -- cgit v0.10.2 From 777953182ea9a750e744bd0a50fb8893cd061397 Mon Sep 17 00:00:00 2001 From: Pavel Andrianov <andrianov@ispras.ru> Date: Mon, 5 Sep 2016 16:17:47 +0300 Subject: speakup: Add spinlock in synth_direct_store All operations with synth buffer should be protected, as there are global pointers, which should be modified atomically. Found by Linux Driver Verification project (linuxtesting.org) Signed-off-by: Pavel Andrianov <andrianov@ispras.ru> Acked-by: Vaishali Thakkar <vaishali.thakkar@oracle.com> Reviewed-by: Samuel Thibault <samuel.thibault@ens-lyon.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/speakup/kobjects.c b/drivers/staging/speakup/kobjects.c index 528cbdc..7fedee3 100644 --- a/drivers/staging/speakup/kobjects.c +++ b/drivers/staging/speakup/kobjects.c @@ -411,11 +411,13 @@ static ssize_t synth_direct_store(struct kobject *kobj, int len; int bytes; const char *ptr = buf; + unsigned long flags; if (!synth) return -EPERM; len = strlen(buf); + spin_lock_irqsave(&speakup_info.spinlock, flags); while (len > 0) { bytes = min_t(size_t, len, 250); strncpy(tmp, ptr, bytes); @@ -425,6 +427,7 @@ static ssize_t synth_direct_store(struct kobject *kobj, ptr += bytes; len -= bytes; } + spin_unlock_irqrestore(&speakup_info.spinlock, flags); return count; } -- cgit v0.10.2 From 992f961480d23e9ef9e686e512a419efef723523 Mon Sep 17 00:00:00 2001 From: Phil Turnbull <phil.turnbull@oracle.com> Date: Fri, 2 Sep 2016 15:35:31 -0400 Subject: staging: sm750fb: Correctly set CLOCK_PHASE bit of display controller. Commit 6fba39cf32a3 ("staging: sm750fb: use BIT macro for PANEL_DISPLAY_CTRL single-bit fields") accidentally changed the CLOCK_PHASE logic from '|=' to '=' which clears all the previously set bits. Fixes: 6fba39cf32a3 ("staging: sm750fb: use BIT macro for PANEL_DISPLAY_CTRL single-bit fields") Signed-off-by: Phil Turnbull <phil.turnbull@oracle.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/sm750fb/ddk750_mode.c b/drivers/staging/sm750fb/ddk750_mode.c index ccb4e06..e29d4bd 100644 --- a/drivers/staging/sm750fb/ddk750_mode.c +++ b/drivers/staging/sm750fb/ddk750_mode.c @@ -63,7 +63,7 @@ static unsigned long displayControlAdjust_SM750LE(mode_parameter_t *pModeParam, dispControl |= (CRT_DISPLAY_CTRL_CRTSELECT | CRT_DISPLAY_CTRL_RGBBIT); /* Set bit 14 of display controller */ - dispControl = DISPLAY_CTRL_CLOCK_PHASE; + dispControl |= DISPLAY_CTRL_CLOCK_PHASE; POKE32(CRT_DISPLAY_CTRL, dispControl); -- cgit v0.10.2 From 152f04483dcce4b8d7a7c82689e8917196d84921 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea <claudiu.beznea@gmail.com> Date: Sun, 4 Sep 2016 20:52:17 +0300 Subject: Staging: wlan-ng: uses DIDmib_dot11smt_dot11WEPDefaultKeysTable_key() macro instead of DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0 This patch removes DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0 macro and uses DIDmib_dot11smt_dot11WEPDefaultKeysTable_key() instead. Signed-off-by: Claudiu Beznea <claudiu.beznea@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/p80211metadef.h b/drivers/staging/wlan-ng/p80211metadef.h index 98fda3d..9a7fa8e 100644 --- a/drivers/staging/wlan-ng/p80211metadef.h +++ b/drivers/staging/wlan-ng/p80211metadef.h @@ -155,10 +155,6 @@ #define DIDmib_dot11smt_dot11WEPDefaultKeysTable \ (P80211DID_MKSECTION(1) | \ P80211DID_MKGROUP(4)) -#define DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(4) | \ - P80211DID_MKITEM(1) | 0x0c000000) #define DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1 \ (P80211DID_MKSECTION(1) | \ P80211DID_MKGROUP(4) | \ diff --git a/drivers/staging/wlan-ng/p80211req.c b/drivers/staging/wlan-ng/p80211req.c index 5c2b801..c7325fa 100644 --- a/drivers/staging/wlan-ng/p80211req.c +++ b/drivers/staging/wlan-ng/p80211req.c @@ -200,7 +200,7 @@ static void p80211req_mibset_mibget(wlandevice_t *wlandev, u8 *key = mibitem->data + sizeof(p80211pstrd_t); switch (mibitem->did) { - case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0: + case DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(1): case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1: case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2: case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3: diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c index 4dd4cdf..5fcfc81 100644 --- a/drivers/staging/wlan-ng/prism2mib.c +++ b/drivers/staging/wlan-ng/prism2mib.c @@ -148,7 +148,7 @@ static int prism2mib_priv(struct mibrec *mib, static struct mibrec mibtab[] = { /* dot11smt MIB's */ - {DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0, + {DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(1), F_STA | F_WRITE, HFA384x_RID_CNFWEPDEFAULTKEY0, 0, 0, prism2mib_wepdefaultkey}, -- cgit v0.10.2 From 41e9b844cc8ec2c7a747aec52706f3312878395f Mon Sep 17 00:00:00 2001 From: Claudiu Beznea <claudiu.beznea@gmail.com> Date: Sun, 4 Sep 2016 20:52:18 +0300 Subject: Staging: wlan-ng: uses DIDmib_dot11smt_dot11WEPDefaultKeysTable_key() macro instead of DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1 This patch removes DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1 macro and uses DIDmib_dot11smt_dot11WEPDefaultKeysTable_key() instead. Signed-off-by: Claudiu Beznea <claudiu.beznea@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/p80211metadef.h b/drivers/staging/wlan-ng/p80211metadef.h index 9a7fa8e..c15ed08 100644 --- a/drivers/staging/wlan-ng/p80211metadef.h +++ b/drivers/staging/wlan-ng/p80211metadef.h @@ -155,10 +155,6 @@ #define DIDmib_dot11smt_dot11WEPDefaultKeysTable \ (P80211DID_MKSECTION(1) | \ P80211DID_MKGROUP(4)) -#define DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(4) | \ - P80211DID_MKITEM(2) | 0x0c000000) #define DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2 \ (P80211DID_MKSECTION(1) | \ P80211DID_MKGROUP(4) | \ diff --git a/drivers/staging/wlan-ng/p80211req.c b/drivers/staging/wlan-ng/p80211req.c index c7325fa..c1ad57f 100644 --- a/drivers/staging/wlan-ng/p80211req.c +++ b/drivers/staging/wlan-ng/p80211req.c @@ -201,7 +201,7 @@ static void p80211req_mibset_mibget(wlandevice_t *wlandev, switch (mibitem->did) { case DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(1): - case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1: + case DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(2): case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2: case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3: if (!isget) diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c index 5fcfc81..7887f2aa 100644 --- a/drivers/staging/wlan-ng/prism2mib.c +++ b/drivers/staging/wlan-ng/prism2mib.c @@ -152,7 +152,7 @@ static struct mibrec mibtab[] = { F_STA | F_WRITE, HFA384x_RID_CNFWEPDEFAULTKEY0, 0, 0, prism2mib_wepdefaultkey}, - {DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1, + {DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(2), F_STA | F_WRITE, HFA384x_RID_CNFWEPDEFAULTKEY1, 0, 0, prism2mib_wepdefaultkey}, -- cgit v0.10.2 From 8d3a225251bd1250be2f4c2cfc8efb571602a926 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea <claudiu.beznea@gmail.com> Date: Sun, 4 Sep 2016 20:52:19 +0300 Subject: Staging: wlan-ng: uses DIDmib_dot11smt_dot11WEPDefaultKeysTable_key() macro instead of DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2 This patch removes DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2 macro and uses DIDmib_dot11smt_dot11WEPDefaultKeysTable_key() instead. Signed-off-by: Claudiu Beznea <claudiu.beznea@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/p80211metadef.h b/drivers/staging/wlan-ng/p80211metadef.h index c15ed08..33b743c 100644 --- a/drivers/staging/wlan-ng/p80211metadef.h +++ b/drivers/staging/wlan-ng/p80211metadef.h @@ -155,10 +155,6 @@ #define DIDmib_dot11smt_dot11WEPDefaultKeysTable \ (P80211DID_MKSECTION(1) | \ P80211DID_MKGROUP(4)) -#define DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(4) | \ - P80211DID_MKITEM(3) | 0x0c000000) #define DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3 \ (P80211DID_MKSECTION(1) | \ P80211DID_MKGROUP(4) | \ diff --git a/drivers/staging/wlan-ng/p80211req.c b/drivers/staging/wlan-ng/p80211req.c index c1ad57f..27292ea 100644 --- a/drivers/staging/wlan-ng/p80211req.c +++ b/drivers/staging/wlan-ng/p80211req.c @@ -202,7 +202,7 @@ static void p80211req_mibset_mibget(wlandevice_t *wlandev, switch (mibitem->did) { case DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(1): case DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(2): - case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2: + case DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(3): case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3: if (!isget) wep_change_key(wlandev, diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c index 7887f2aa..6bc7bec 100644 --- a/drivers/staging/wlan-ng/prism2mib.c +++ b/drivers/staging/wlan-ng/prism2mib.c @@ -156,7 +156,7 @@ static struct mibrec mibtab[] = { F_STA | F_WRITE, HFA384x_RID_CNFWEPDEFAULTKEY1, 0, 0, prism2mib_wepdefaultkey}, - {DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2, + {DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(3), F_STA | F_WRITE, HFA384x_RID_CNFWEPDEFAULTKEY2, 0, 0, prism2mib_wepdefaultkey}, -- cgit v0.10.2 From 17d9ff12c0b14a2a265c41720761499e22acc549 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea <claudiu.beznea@gmail.com> Date: Sun, 4 Sep 2016 20:52:20 +0300 Subject: Staging: wlan-ng: uses DIDmib_dot11smt_dot11WEPDefaultKeysTable_key() macro instead of DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3 This patch removes DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3 macro and uses DIDmib_dot11smt_dot11WEPDefaultKeysTable_key() instead. Signed-off-by: Claudiu Beznea <claudiu.beznea@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/p80211metadef.h b/drivers/staging/wlan-ng/p80211metadef.h index 33b743c..33de041 100644 --- a/drivers/staging/wlan-ng/p80211metadef.h +++ b/drivers/staging/wlan-ng/p80211metadef.h @@ -155,10 +155,6 @@ #define DIDmib_dot11smt_dot11WEPDefaultKeysTable \ (P80211DID_MKSECTION(1) | \ P80211DID_MKGROUP(4)) -#define DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(4) | \ - P80211DID_MKITEM(4) | 0x0c000000) #define DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(_i) \ (P80211DID_MKSECTION(1) | \ P80211DID_MKGROUP(4) | \ diff --git a/drivers/staging/wlan-ng/p80211req.c b/drivers/staging/wlan-ng/p80211req.c index 27292ea..f755318 100644 --- a/drivers/staging/wlan-ng/p80211req.c +++ b/drivers/staging/wlan-ng/p80211req.c @@ -203,7 +203,7 @@ static void p80211req_mibset_mibget(wlandevice_t *wlandev, case DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(1): case DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(2): case DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(3): - case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3: + case DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(4): if (!isget) wep_change_key(wlandev, P80211DID_ITEM(mibitem->did) - 1, diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c index 6bc7bec..524271f 100644 --- a/drivers/staging/wlan-ng/prism2mib.c +++ b/drivers/staging/wlan-ng/prism2mib.c @@ -160,7 +160,7 @@ static struct mibrec mibtab[] = { F_STA | F_WRITE, HFA384x_RID_CNFWEPDEFAULTKEY2, 0, 0, prism2mib_wepdefaultkey}, - {DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3, + {DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(4), F_STA | F_WRITE, HFA384x_RID_CNFWEPDEFAULTKEY3, 0, 0, prism2mib_wepdefaultkey}, -- cgit v0.10.2 From 943407ce3012385855f860493bd7326cfa401316 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea <claudiu.beznea@gmail.com> Date: Sun, 4 Sep 2016 20:52:21 +0300 Subject: Staging: wlan-ng: changed definition of DIDmib_dot11smt_dot11WEPDefaultKeysTable_key() macro This patch changes definition of DIDmib_dot11smt_dot11WEPDefaultKeysTable_key() macro and uses DIDmib_dot11smt_dot11WEPDefaultKeysTable instead of using directly (P80211DID_MKSECTION(1) | P80211DID_MKGROUP(4)). Signed-off-by: Claudiu Beznea <claudiu.beznea@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/p80211metadef.h b/drivers/staging/wlan-ng/p80211metadef.h index 33de041..b0d3567 100644 --- a/drivers/staging/wlan-ng/p80211metadef.h +++ b/drivers/staging/wlan-ng/p80211metadef.h @@ -156,8 +156,7 @@ (P80211DID_MKSECTION(1) | \ P80211DID_MKGROUP(4)) #define DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(_i) \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(4) | \ + (DIDmib_dot11smt_dot11WEPDefaultKeysTable | \ P80211DID_MKITEM(_i) | 0x0c000000) #define DIDmib_dot11smt_dot11PrivacyTable \ (P80211DID_MKSECTION(1) | \ -- cgit v0.10.2 From 60dcf58a628475281748742cda3b09d5a66babeb Mon Sep 17 00:00:00 2001 From: Aaro Koskinen <aaro.koskinen@iki.fi> Date: Sat, 3 Sep 2016 00:33:38 +0300 Subject: staging: octeon: stop using cvmx_helper_link_autoconf() Stop using cvmx_helper_link_autoconf(). We want to remove it in the future, as it duplicates link state information into platform code for no reason. Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c index 48846df..4e73042 100644 --- a/drivers/staging/octeon/ethernet-rgmii.c +++ b/drivers/staging/octeon/ethernet-rgmii.c @@ -117,7 +117,10 @@ static void cvm_oct_rgmii_poll(struct net_device *dev) cvmx_helper_link_info_t link_info; bool status_change; - link_info = cvmx_helper_link_autoconf(priv->port); + link_info = cvmx_helper_link_get(priv->port); + if (priv->link_info != link_info.u64 && + cvmx_helper_link_set(priv->port, link_info)) + link_info.u64 = priv->link_info; status_change = priv->link_info != link_info.u64; priv->link_info = link_info.u64; diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index 0bd5c18..5f746b8 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -521,8 +521,10 @@ void cvm_oct_link_poll(struct net_device *dev) if (link_info.u64 == priv->link_info) return; - link_info = cvmx_helper_link_autoconf(priv->port); - priv->link_info = link_info.u64; + if (cvmx_helper_link_set(priv->port, link_info)) + link_info.u64 = priv->link_info; + else + priv->link_info = link_info.u64; if (link_info.s.link_up) { if (!netif_carrier_ok(dev)) -- cgit v0.10.2 From 970e82dfade8e2640d3ad73785732435148e5917 Mon Sep 17 00:00:00 2001 From: Fernando Apesteguia <fernando.apesteguia@gmail.com> Date: Mon, 5 Sep 2016 20:28:32 +0200 Subject: staging: dgnc: Fix multi line comment alignment Fix alignment in multi line comment block. Remove extra '*' to use the preferred comment style as in Documentation/CodingStyle Signed-off-by: Fernando Apesteguia <fernando.apesteguia@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c index cc6105a..01e948c 100644 --- a/drivers/staging/dgnc/dgnc_driver.c +++ b/drivers/staging/dgnc/dgnc_driver.c @@ -602,31 +602,31 @@ static void dgnc_do_remap(struct dgnc_board *brd) brd->re_map_membase = ioremap(brd->membase, 0x1000); } -/***************************************************************************** -* -* Function: -* -* dgnc_poll_handler -* -* Author: -* -* Scott H Kilau -* -* Parameters: -* -* dummy -- ignored -* -* Return Values: -* -* none -* -* Description: -* -* As each timer expires, it determines (a) whether the "transmit" -* waiter needs to be woken up, and (b) whether the poller needs to -* be rescheduled. -* -******************************************************************************/ +/* + * + * Function: + * + * dgnc_poll_handler + * + * Author: + * + * Scott H Kilau + * + * Parameters: + * + * dummy -- ignored + * + * Return Values: + * + * none + * + * Description: + * + * As each timer expires, it determines (a) whether the "transmit" + * waiter needs to be woken up, and (b) whether the poller needs to + * be rescheduled. + * + */ static void dgnc_poll_handler(ulong dummy) { -- cgit v0.10.2 From 0c8de4cf6dd5a9f7f44df33eac76f0aa70c97521 Mon Sep 17 00:00:00 2001 From: Matias Mucciolo <mmucciolo@suteba.org.ar> Date: Fri, 9 Sep 2016 12:42:33 -0300 Subject: staging: dgnc: dgnc_sysfs *_ATTR() macros convert Convert DRIVER_ATTR() macro with DRIVER_ATTR_RO/RW and DEVICE_ATTR() macro with DEVICE_ATTR_RO() Signed-off-by: Matias Mucciolo <mmucciolo@suteba.org.ar> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_sysfs.c b/drivers/staging/dgnc/dgnc_sysfs.c index b8d41c5..a83e0e4 100644 --- a/drivers/staging/dgnc/dgnc_sysfs.c +++ b/drivers/staging/dgnc/dgnc_sysfs.c @@ -25,31 +25,31 @@ #include "dgnc_driver.h" #include "dgnc_mgmt.h" -static ssize_t dgnc_driver_version_show(struct device_driver *ddp, char *buf) +static ssize_t version_show(struct device_driver *ddp, char *buf) { return snprintf(buf, PAGE_SIZE, "%s\n", DG_PART); } -static DRIVER_ATTR(version, S_IRUSR, dgnc_driver_version_show, NULL); +static DRIVER_ATTR_RO(version); -static ssize_t dgnc_driver_boards_show(struct device_driver *ddp, char *buf) +static ssize_t boards_show(struct device_driver *ddp, char *buf) { return snprintf(buf, PAGE_SIZE, "%d\n", dgnc_num_boards); } -static DRIVER_ATTR(boards, S_IRUSR, dgnc_driver_boards_show, NULL); +static DRIVER_ATTR_RO(boards); -static ssize_t dgnc_driver_maxboards_show(struct device_driver *ddp, char *buf) +static ssize_t maxboards_show(struct device_driver *ddp, char *buf) { return snprintf(buf, PAGE_SIZE, "%d\n", MAXBOARDS); } -static DRIVER_ATTR(maxboards, S_IRUSR, dgnc_driver_maxboards_show, NULL); +static DRIVER_ATTR_RO(maxboards); -static ssize_t dgnc_driver_pollrate_show(struct device_driver *ddp, char *buf) +static ssize_t pollrate_show(struct device_driver *ddp, char *buf) { return snprintf(buf, PAGE_SIZE, "%dms\n", dgnc_poll_tick); } -static ssize_t dgnc_driver_pollrate_store(struct device_driver *ddp, - const char *buf, size_t count) +static ssize_t pollrate_store(struct device_driver *ddp, + const char *buf, size_t count) { unsigned long flags; int tick; @@ -65,8 +65,7 @@ static ssize_t dgnc_driver_pollrate_store(struct device_driver *ddp, return count; } -static DRIVER_ATTR(pollrate, (S_IRUSR | S_IWUSR), dgnc_driver_pollrate_show, - dgnc_driver_pollrate_store); +static DRIVER_ATTR_RW(pollrate); void dgnc_create_driver_sysfiles(struct pci_driver *dgnc_driver) { @@ -103,8 +102,8 @@ void dgnc_remove_driver_sysfiles(struct pci_driver *dgnc_driver) return 0; \ } while (0) -static ssize_t dgnc_vpd_show(struct device *p, struct device_attribute *attr, - char *buf) +static ssize_t vpd_show(struct device *p, struct device_attribute *attr, + char *buf) { struct dgnc_board *bd; int count = 0; @@ -123,10 +122,10 @@ static ssize_t dgnc_vpd_show(struct device *p, struct device_attribute *attr, return count; } -static DEVICE_ATTR(vpd, S_IRUSR, dgnc_vpd_show, NULL); +static DEVICE_ATTR_RO(vpd); -static ssize_t dgnc_serial_number_show(struct device *p, - struct device_attribute *attr, char *buf) +static ssize_t serial_number_show(struct device *p, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; int count = 0; @@ -140,10 +139,10 @@ static ssize_t dgnc_serial_number_show(struct device *p, return count; } -static DEVICE_ATTR(serial_number, S_IRUSR, dgnc_serial_number_show, NULL); +static DEVICE_ATTR_RO(serial_number); -static ssize_t dgnc_ports_state_show(struct device *p, - struct device_attribute *attr, char *buf) +static ssize_t ports_state_show(struct device *p, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; int count = 0; @@ -158,10 +157,10 @@ static ssize_t dgnc_ports_state_show(struct device *p, } return count; } -static DEVICE_ATTR(ports_state, S_IRUSR, dgnc_ports_state_show, NULL); +static DEVICE_ATTR_RO(ports_state); -static ssize_t dgnc_ports_baud_show(struct device *p, - struct device_attribute *attr, char *buf) +static ssize_t ports_baud_show(struct device *p, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; int count = 0; @@ -176,11 +175,10 @@ static ssize_t dgnc_ports_baud_show(struct device *p, } return count; } -static DEVICE_ATTR(ports_baud, S_IRUSR, dgnc_ports_baud_show, NULL); +static DEVICE_ATTR_RO(ports_baud); -static ssize_t dgnc_ports_msignals_show(struct device *p, - struct device_attribute *attr, - char *buf) +static ssize_t ports_msignals_show(struct device *p, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; int count = 0; @@ -208,10 +206,10 @@ static ssize_t dgnc_ports_msignals_show(struct device *p, } return count; } -static DEVICE_ATTR(ports_msignals, S_IRUSR, dgnc_ports_msignals_show, NULL); +static DEVICE_ATTR_RO(ports_msignals); -static ssize_t dgnc_ports_iflag_show(struct device *p, - struct device_attribute *attr, char *buf) +static ssize_t ports_iflag_show(struct device *p, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; int count = 0; @@ -226,10 +224,10 @@ static ssize_t dgnc_ports_iflag_show(struct device *p, } return count; } -static DEVICE_ATTR(ports_iflag, S_IRUSR, dgnc_ports_iflag_show, NULL); +static DEVICE_ATTR_RO(ports_iflag); -static ssize_t dgnc_ports_cflag_show(struct device *p, - struct device_attribute *attr, char *buf) +static ssize_t ports_cflag_show(struct device *p, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; int count = 0; @@ -244,10 +242,10 @@ static ssize_t dgnc_ports_cflag_show(struct device *p, } return count; } -static DEVICE_ATTR(ports_cflag, S_IRUSR, dgnc_ports_cflag_show, NULL); +static DEVICE_ATTR_RO(ports_cflag); -static ssize_t dgnc_ports_oflag_show(struct device *p, - struct device_attribute *attr, char *buf) +static ssize_t ports_oflag_show(struct device *p, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; int count = 0; @@ -262,10 +260,10 @@ static ssize_t dgnc_ports_oflag_show(struct device *p, } return count; } -static DEVICE_ATTR(ports_oflag, S_IRUSR, dgnc_ports_oflag_show, NULL); +static DEVICE_ATTR_RO(ports_oflag); -static ssize_t dgnc_ports_lflag_show(struct device *p, - struct device_attribute *attr, char *buf) +static ssize_t ports_lflag_show(struct device *p, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; int count = 0; @@ -280,11 +278,10 @@ static ssize_t dgnc_ports_lflag_show(struct device *p, } return count; } -static DEVICE_ATTR(ports_lflag, S_IRUSR, dgnc_ports_lflag_show, NULL); +static DEVICE_ATTR_RO(ports_lflag); -static ssize_t dgnc_ports_digi_flag_show(struct device *p, - struct device_attribute *attr, - char *buf) +static ssize_t ports_digi_flag_show(struct device *p, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; int count = 0; @@ -299,10 +296,10 @@ static ssize_t dgnc_ports_digi_flag_show(struct device *p, } return count; } -static DEVICE_ATTR(ports_digi_flag, S_IRUSR, dgnc_ports_digi_flag_show, NULL); +static DEVICE_ATTR_RO(ports_digi_flag); -static ssize_t dgnc_ports_rxcount_show(struct device *p, - struct device_attribute *attr, char *buf) +static ssize_t ports_rxcount_show(struct device *p, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; int count = 0; @@ -317,10 +314,10 @@ static ssize_t dgnc_ports_rxcount_show(struct device *p, } return count; } -static DEVICE_ATTR(ports_rxcount, S_IRUSR, dgnc_ports_rxcount_show, NULL); +static DEVICE_ATTR_RO(ports_rxcount); -static ssize_t dgnc_ports_txcount_show(struct device *p, - struct device_attribute *attr, char *buf) +static ssize_t ports_txcount_show(struct device *p, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; int count = 0; @@ -335,7 +332,7 @@ static ssize_t dgnc_ports_txcount_show(struct device *p, } return count; } -static DEVICE_ATTR(ports_txcount, S_IRUSR, dgnc_ports_txcount_show, NULL); +static DEVICE_ATTR_RO(ports_txcount); /* this function creates the sys files that will export each signal status * to sysfs each value will be put in a separate filename @@ -378,8 +375,8 @@ void dgnc_remove_ports_sysfiles(struct dgnc_board *bd) device_remove_file(&bd->pdev->dev, &dev_attr_serial_number); } -static ssize_t dgnc_tty_state_show(struct device *d, - struct device_attribute *attr, char *buf) +static ssize_t tty_state_show(struct device *d, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; struct channel_t *ch; @@ -402,10 +399,10 @@ static ssize_t dgnc_tty_state_show(struct device *d, return snprintf(buf, PAGE_SIZE, "%s", un->un_open_count ? "Open" : "Closed"); } -static DEVICE_ATTR(state, S_IRUSR, dgnc_tty_state_show, NULL); +static DEVICE_ATTR_RO(tty_state); -static ssize_t dgnc_tty_baud_show(struct device *d, - struct device_attribute *attr, char *buf) +static ssize_t tty_baud_show(struct device *d, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; struct channel_t *ch; @@ -427,10 +424,10 @@ static ssize_t dgnc_tty_baud_show(struct device *d, return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_old_baud); } -static DEVICE_ATTR(baud, S_IRUSR, dgnc_tty_baud_show, NULL); +static DEVICE_ATTR_RO(tty_baud); -static ssize_t dgnc_tty_msignals_show(struct device *d, - struct device_attribute *attr, char *buf) +static ssize_t tty_msignals_show(struct device *d, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; struct channel_t *ch; @@ -461,10 +458,10 @@ static ssize_t dgnc_tty_msignals_show(struct device *d, } return 0; } -static DEVICE_ATTR(msignals, S_IRUSR, dgnc_tty_msignals_show, NULL); +static DEVICE_ATTR_RO(tty_msignals); -static ssize_t dgnc_tty_iflag_show(struct device *d, - struct device_attribute *attr, char *buf) +static ssize_t tty_iflag_show(struct device *d, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; struct channel_t *ch; @@ -486,10 +483,10 @@ static ssize_t dgnc_tty_iflag_show(struct device *d, return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_iflag); } -static DEVICE_ATTR(iflag, S_IRUSR, dgnc_tty_iflag_show, NULL); +static DEVICE_ATTR_RO(tty_iflag); -static ssize_t dgnc_tty_cflag_show(struct device *d, - struct device_attribute *attr, char *buf) +static ssize_t tty_cflag_show(struct device *d, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; struct channel_t *ch; @@ -511,10 +508,10 @@ static ssize_t dgnc_tty_cflag_show(struct device *d, return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_cflag); } -static DEVICE_ATTR(cflag, S_IRUSR, dgnc_tty_cflag_show, NULL); +static DEVICE_ATTR_RO(tty_cflag); -static ssize_t dgnc_tty_oflag_show(struct device *d, - struct device_attribute *attr, char *buf) +static ssize_t tty_oflag_show(struct device *d, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; struct channel_t *ch; @@ -536,10 +533,10 @@ static ssize_t dgnc_tty_oflag_show(struct device *d, return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_oflag); } -static DEVICE_ATTR(oflag, S_IRUSR, dgnc_tty_oflag_show, NULL); +static DEVICE_ATTR_RO(tty_oflag); -static ssize_t dgnc_tty_lflag_show(struct device *d, - struct device_attribute *attr, char *buf) +static ssize_t tty_lflag_show(struct device *d, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; struct channel_t *ch; @@ -561,10 +558,10 @@ static ssize_t dgnc_tty_lflag_show(struct device *d, return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_lflag); } -static DEVICE_ATTR(lflag, S_IRUSR, dgnc_tty_lflag_show, NULL); +static DEVICE_ATTR_RO(tty_lflag); -static ssize_t dgnc_tty_digi_flag_show(struct device *d, - struct device_attribute *attr, char *buf) +static ssize_t tty_digi_flag_show(struct device *d, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; struct channel_t *ch; @@ -586,10 +583,10 @@ static ssize_t dgnc_tty_digi_flag_show(struct device *d, return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_digi.digi_flags); } -static DEVICE_ATTR(digi_flag, S_IRUSR, dgnc_tty_digi_flag_show, NULL); +static DEVICE_ATTR_RO(tty_digi_flag); -static ssize_t dgnc_tty_rxcount_show(struct device *d, - struct device_attribute *attr, char *buf) +static ssize_t tty_rxcount_show(struct device *d, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; struct channel_t *ch; @@ -611,10 +608,10 @@ static ssize_t dgnc_tty_rxcount_show(struct device *d, return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_rxcount); } -static DEVICE_ATTR(rxcount, S_IRUSR, dgnc_tty_rxcount_show, NULL); +static DEVICE_ATTR_RO(tty_rxcount); -static ssize_t dgnc_tty_txcount_show(struct device *d, - struct device_attribute *attr, char *buf) +static ssize_t tty_txcount_show(struct device *d, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; struct channel_t *ch; @@ -636,10 +633,10 @@ static ssize_t dgnc_tty_txcount_show(struct device *d, return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_txcount); } -static DEVICE_ATTR(txcount, S_IRUSR, dgnc_tty_txcount_show, NULL); +static DEVICE_ATTR_RO(tty_txcount); -static ssize_t dgnc_tty_name_show(struct device *d, - struct device_attribute *attr, char *buf) +static ssize_t tty_custom_name_show(struct device *d, + struct device_attribute *attr, char *buf) { struct dgnc_board *bd; struct channel_t *ch; @@ -663,20 +660,20 @@ static ssize_t dgnc_tty_name_show(struct device *d, (un->un_type == DGNC_PRINT) ? "pr" : "tty", bd->boardnum + 1, 'a' + ch->ch_portnum); } -static DEVICE_ATTR(custom_name, S_IRUSR, dgnc_tty_name_show, NULL); +static DEVICE_ATTR_RO(tty_custom_name); static struct attribute *dgnc_sysfs_tty_entries[] = { - &dev_attr_state.attr, - &dev_attr_baud.attr, - &dev_attr_msignals.attr, - &dev_attr_iflag.attr, - &dev_attr_cflag.attr, - &dev_attr_oflag.attr, - &dev_attr_lflag.attr, - &dev_attr_digi_flag.attr, - &dev_attr_rxcount.attr, - &dev_attr_txcount.attr, - &dev_attr_custom_name.attr, + &dev_attr_tty_state.attr, + &dev_attr_tty_baud.attr, + &dev_attr_tty_msignals.attr, + &dev_attr_tty_iflag.attr, + &dev_attr_tty_cflag.attr, + &dev_attr_tty_oflag.attr, + &dev_attr_tty_lflag.attr, + &dev_attr_tty_digi_flag.attr, + &dev_attr_tty_rxcount.attr, + &dev_attr_tty_txcount.attr, + &dev_attr_tty_custom_name.attr, NULL }; -- cgit v0.10.2 From f6376a59017847bb107b01f17bf6594c65901c03 Mon Sep 17 00:00:00 2001 From: Erik Arfvidson <erik.arfvidson@unisys.com> Date: Fri, 2 Sep 2016 16:41:25 -0400 Subject: staging: unisys: visorchipset.c remove unused pound defines This removes three unused pound defines in the visorchipset.c file. Signed-off-by: Erik Arfvidson <erik.arfvidson@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 0b4a138..f70f609 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -36,9 +36,6 @@ #define CURRENT_FILE_PC VISOR_CHIPSET_PC_visorchipset_main_c -#define MAX_NAME_SIZE 128 -#define MAX_IP_SIZE 50 -#define MAXOUTSTANDINGCHANNELCOMMAND 256 #define POLLJIFFIES_CONTROLVMCHANNEL_FAST 1 #define POLLJIFFIES_CONTROLVMCHANNEL_SLOW 100 -- cgit v0.10.2 From 992d03d91b4cdc141957d2876ab75d83a30d18bc Mon Sep 17 00:00:00 2001 From: Erik Arfvidson <erik.arfvidson@unisys.com> Date: Fri, 2 Sep 2016 16:41:26 -0400 Subject: staging: unisys: visorbus_main.c remove unused pound defines This removes two unused pound defines in the visorbus_main.c file. Signed-off-by: Erik Arfvidson <erik.arfvidson@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 293532f..a100c79 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -29,13 +29,10 @@ static int visorbus_forcematch; static int visorbus_forcenomatch; -#define SERIALLOOPBACKCHANADDR (100 * 1024 * 1024) - /* Display string that is guaranteed to be no longer the 99 characters*/ #define LINESIZE 99 #define CURRENT_FILE_PC VISOR_BUS_PC_visorbus_main_c -#define POLLJIFFIES_TESTWORK 100 #define POLLJIFFIES_NORMALCHANNEL 10 static int busreg_rc = -ENODEV; /* stores the result from bus registration */ -- cgit v0.10.2 From fbb5d8cf680b4bc7e8d73b86229055c60b1c6820 Mon Sep 17 00:00:00 2001 From: Erik Arfvidson <erik.arfvidson@unisys.com> Date: Fri, 2 Sep 2016 16:41:27 -0400 Subject: staging: unisys: visornic_main.c remove unused pound defines This removes two unused pound defines in the visornic_main.c file. Signed-off-by: Erik Arfvidson <erik.arfvidson@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index 4fbe703..49ee747 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -29,8 +29,6 @@ #include "iochannel.h" #define VISORNIC_INFINITE_RSP_WAIT 0 -#define VISORNICSOPENMAX 32 -#define MAXDEVICES 16384 /* MAX_BUF = 64 lines x 32 MAXVNIC x 80 characters * = 163840 bytes -- cgit v0.10.2 From 1bda5a2b0acc4f99b602f612c24da777a989c095 Mon Sep 17 00:00:00 2001 From: Jon Frisch <jon.frisch@unisys.com> Date: Fri, 2 Sep 2016 16:41:28 -0400 Subject: staging: unisys: visorbus: remove g_devicechangestate_packet This patch removes the unused struct controlvm_message_packet g_devicechangestate_packet. The struct is set but never called. Signed-off-by: Jon Frisch <jon.frisch@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index f70f609..52f79c7 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -98,7 +98,6 @@ static struct delayed_work periodic_controlvm_work; static struct cdev file_cdev; static struct visorchannel **file_controlvm_channel; -static struct controlvm_message_packet g_devicechangestate_packet; static LIST_HEAD(bus_info_list); static LIST_HEAD(dev_info_list); @@ -1717,7 +1716,6 @@ handle_command(struct controlvm_message inmsg, u64 channel_addr) * when sending back the response to Command */ my_device_changestate(&inmsg); - g_devicechangestate_packet = inmsg.cmd; break; } break; -- cgit v0.10.2 From d5bc757c1f6606c03e14d093c3a96e9e7f2f413f Mon Sep 17 00:00:00 2001 From: Jon Frisch <jon.frisch@unisys.com> Date: Fri, 2 Sep 2016 16:41:29 -0400 Subject: staging: unisys: visorbus: remove unused lists This patch removes the following lists that were never used: LIST_HEAD(bus_info_list) LIST_HEAD(dev_info_list) LIST_HEAD(putfile_request_list) Signed-off-by: Jon Frisch <jon.frisch@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 52f79c7..54f90d9 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -99,9 +99,6 @@ static struct delayed_work periodic_controlvm_work; static struct cdev file_cdev; static struct visorchannel **file_controlvm_channel; -static LIST_HEAD(bus_info_list); -static LIST_HEAD(dev_info_list); - static struct visorchannel *controlvm_channel; /* Manages the request payload in the controlvm channel */ @@ -135,13 +132,6 @@ struct putfile_buffer_entry { }; /* - * List of struct putfile_request *, via next_putfile_request member. - * Each entry in this list identifies an outstanding TRANSMIT_FILE - * conversation. - */ -static LIST_HEAD(putfile_request_list); - -/* * This describes a buffer and its current state of transfer (e.g., how many * bytes have already been supplied as putfile data, and how many bytes are * remaining) for a putfile_request. -- cgit v0.10.2 From 1e5bcbe67aee51e72e3a0411351d783185c8229b Mon Sep 17 00:00:00 2001 From: Jon Frisch <jon.frisch@unisys.com> Date: Fri, 2 Sep 2016 16:41:30 -0400 Subject: staging: unisys: visorbus: remove putfile_buffer_entry This patch removes the unused struct putfile_buffer_entry. Signed-off-by: Jon Frisch <jon.frisch@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 54f90d9..b653a5b 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -123,15 +123,6 @@ static struct controlvm_message controlvm_pending_msg; static bool controlvm_pending_msg_valid; /* - * This identifies a data buffer that has been received via a controlvm messages - * in a remote --> local CONTROLVM_TRANSMIT_FILE conversation. - */ -struct putfile_buffer_entry { - struct list_head next; /* putfile_buffer_entry list */ - struct parser_context *parser_ctx; /* points to input data buffer */ -}; - -/* * This describes a buffer and its current state of transfer (e.g., how many * bytes have already been supplied as putfile data, and how many bytes are * remaining) for a putfile_request. -- cgit v0.10.2 From 43c0ab0e1c7f9d5dec502af988b8922599b485f5 Mon Sep 17 00:00:00 2001 From: Bryan Thompson <bryan.thompson@unisys.com> Date: Fri, 2 Sep 2016 16:41:31 -0400 Subject: staging: unisys: Move vbushelper.h contents to visorbus_private.h The contents of vbushelper.h are now only used by visorbus, so it no longer needs to be a general include file and it can be incorporated in the visorbus private header. Signed-off-by: Bryan Thompson <bryan.thompson@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/vbushelper.h b/drivers/staging/unisys/visorbus/vbushelper.h deleted file mode 100644 index f1b6aac..0000000 --- a/drivers/staging/unisys/visorbus/vbushelper.h +++ /dev/null @@ -1,46 +0,0 @@ -/* vbushelper.h - * - * Copyright (C) 2011 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#ifndef __VBUSHELPER_H__ -#define __VBUSHELPER_H__ - -/* TARGET_HOSTNAME specified as -DTARGET_HOSTNAME=\"thename\" on the - * command line - */ - -#define TARGET_HOSTNAME "linuxguest" - -static inline void bus_device_info_init( - struct ultra_vbus_deviceinfo *bus_device_info_ptr, - const char *dev_type, const char *drv_name, - const char *ver, const char *ver_tag) -{ - memset(bus_device_info_ptr, 0, sizeof(struct ultra_vbus_deviceinfo)); - snprintf(bus_device_info_ptr->devtype, - sizeof(bus_device_info_ptr->devtype), - "%s", (dev_type) ? dev_type : "unknownType"); - snprintf(bus_device_info_ptr->drvname, - sizeof(bus_device_info_ptr->drvname), - "%s", (drv_name) ? drv_name : "unknownDriver"); - snprintf(bus_device_info_ptr->infostrs, - sizeof(bus_device_info_ptr->infostrs), "%s\t%s\t%s", - (ver) ? ver : "unknownVer", - (ver_tag) ? ver_tag : "unknownVerTag", - TARGET_HOSTNAME); -} - -#endif diff --git a/drivers/staging/unisys/visorbus/visorbus_private.h b/drivers/staging/unisys/visorbus/visorbus_private.h index 3f6ad52..0624e23 100644 --- a/drivers/staging/unisys/visorbus/visorbus_private.h +++ b/drivers/staging/unisys/visorbus/visorbus_private.h @@ -21,7 +21,31 @@ #include "controlvmchannel.h" #include "vbusdeviceinfo.h" -#include "vbushelper.h" + +/* TARGET_HOSTNAME specified as -DTARGET_HOSTNAME=\"thename\" on the + * command line + */ + +#define TARGET_HOSTNAME "linuxguest" + +static inline void bus_device_info_init( + struct ultra_vbus_deviceinfo *bus_device_info_ptr, + const char *dev_type, const char *drv_name, + const char *ver, const char *ver_tag) +{ + memset(bus_device_info_ptr, 0, sizeof(struct ultra_vbus_deviceinfo)); + snprintf(bus_device_info_ptr->devtype, + sizeof(bus_device_info_ptr->devtype), + "%s", (dev_type) ? dev_type : "unknownType"); + snprintf(bus_device_info_ptr->drvname, + sizeof(bus_device_info_ptr->drvname), + "%s", (drv_name) ? drv_name : "unknownDriver"); + snprintf(bus_device_info_ptr->infostrs, + sizeof(bus_device_info_ptr->infostrs), "%s\t%s\t%s", + (ver) ? ver : "unknownVer", + (ver_tag) ? ver_tag : "unknownVerTag", + TARGET_HOSTNAME); +} void chipset_bus_create(struct visor_device *bus_info); void chipset_bus_destroy(struct visor_device *bus_info); -- cgit v0.10.2 From 7339cb09a91ea316b6b84944910a2869abfc7fea Mon Sep 17 00:00:00 2001 From: David Binder <david.binder@unisys.com> Date: Fri, 2 Sep 2016 16:41:32 -0400 Subject: staging: unisys: visorbus: Convert visorchipset.h refs visorbus_private.h was previously named visorchipset.h. This patch removes references to the old filename, and updates them with the new filename. Signed-off-by: David Binder <david.binder@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorbus_private.h b/drivers/staging/unisys/visorbus/visorbus_private.h index 0624e23..b10fc1a 100644 --- a/drivers/staging/unisys/visorbus/visorbus_private.h +++ b/drivers/staging/unisys/visorbus/visorbus_private.h @@ -1,4 +1,4 @@ -/* visorchipset.h +/* visorbus_private.h * * Copyright (C) 2010 - 2015 UNISYS CORPORATION * All rights reserved. @@ -14,8 +14,8 @@ * details. */ -#ifndef __VISORCHIPSET_H__ -#define __VISORCHIPSET_H__ +#ifndef __VISORBUS_PRIVATE_H__ +#define __VISORBUS_PRIVATE_H__ #include <linux/uuid.h> -- cgit v0.10.2 From d6d0c6f444a82a792cef1be5860255bd1cae93bb Mon Sep 17 00:00:00 2001 From: David Binder <david.binder@unisys.com> Date: Fri, 2 Sep 2016 16:41:33 -0400 Subject: staging: unisys: visorbus: Merge channel_guid.h with channel.h Merges the contents of channel_guid.h with channel.h, as the former was not a proper header file. Therefore, the channel_guid.h is no longer needed. Signed-off-by: David Binder <david.binder@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/include/channel.h b/drivers/staging/unisys/include/channel.h index db4e6b2..ff86f7a 100644 --- a/drivers/staging/unisys/include/channel.h +++ b/drivers/staging/unisys/include/channel.h @@ -569,4 +569,45 @@ unsigned int spar_signal_remove_all(struct channel_header *ch, u32 queue, unsigned char spar_signalqueue_empty(struct channel_header __iomem *ch, u32 queue); +/* + * CHANNEL Guids + */ + +/* {414815ed-c58c-11da-95a9-00e08161165f} */ +#define SPAR_VHBA_CHANNEL_PROTOCOL_UUID \ + UUID_LE(0x414815ed, 0xc58c, 0x11da, \ + 0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f) +static const uuid_le spar_vhba_channel_protocol_uuid = + SPAR_VHBA_CHANNEL_PROTOCOL_UUID; +#define SPAR_VHBA_CHANNEL_PROTOCOL_UUID_STR \ + "414815ed-c58c-11da-95a9-00e08161165f" + +/* {8cd5994d-c58e-11da-95a9-00e08161165f} */ +#define SPAR_VNIC_CHANNEL_PROTOCOL_UUID \ + UUID_LE(0x8cd5994d, 0xc58e, 0x11da, \ + 0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f) +static const uuid_le spar_vnic_channel_protocol_uuid = + SPAR_VNIC_CHANNEL_PROTOCOL_UUID; +#define SPAR_VNIC_CHANNEL_PROTOCOL_UUID_STR \ + "8cd5994d-c58e-11da-95a9-00e08161165f" + +/* {72120008-4AAB-11DC-8530-444553544200} */ +#define SPAR_SIOVM_UUID \ + UUID_LE(0x72120008, 0x4AAB, 0x11DC, \ + 0x85, 0x30, 0x44, 0x45, 0x53, 0x54, 0x42, 0x00) +static const uuid_le spar_siovm_uuid = SPAR_SIOVM_UUID; + +/* {5b52c5ac-e5f5-4d42-8dff-429eaecd221f} */ +#define SPAR_CONTROLDIRECTOR_CHANNEL_PROTOCOL_UUID \ + UUID_LE(0x5b52c5ac, 0xe5f5, 0x4d42, \ + 0x8d, 0xff, 0x42, 0x9e, 0xae, 0xcd, 0x22, 0x1f) + +static const uuid_le spar_controldirector_channel_protocol_uuid = + SPAR_CONTROLDIRECTOR_CHANNEL_PROTOCOL_UUID; + +/* {b4e79625-aede-4eAA-9e11-D3eddcd4504c} */ +#define SPAR_DIAG_POOL_CHANNEL_PROTOCOL_UUID \ + UUID_LE(0xb4e79625, 0xaede, 0x4eaa, \ + 0x9e, 0x11, 0xd3, 0xed, 0xdc, 0xd4, 0x50, 0x4c) + #endif diff --git a/drivers/staging/unisys/include/channel_guid.h b/drivers/staging/unisys/include/channel_guid.h deleted file mode 100644 index 17cb499..0000000 --- a/drivers/staging/unisys/include/channel_guid.h +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -/* - * CHANNEL Guids - */ - -/* {414815ed-c58c-11da-95a9-00e08161165f} */ -#define SPAR_VHBA_CHANNEL_PROTOCOL_UUID \ - UUID_LE(0x414815ed, 0xc58c, 0x11da, \ - 0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f) -static const uuid_le spar_vhba_channel_protocol_uuid = - SPAR_VHBA_CHANNEL_PROTOCOL_UUID; -#define SPAR_VHBA_CHANNEL_PROTOCOL_UUID_STR \ - "414815ed-c58c-11da-95a9-00e08161165f" - -/* {8cd5994d-c58e-11da-95a9-00e08161165f} */ -#define SPAR_VNIC_CHANNEL_PROTOCOL_UUID \ - UUID_LE(0x8cd5994d, 0xc58e, 0x11da, \ - 0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f) -static const uuid_le spar_vnic_channel_protocol_uuid = - SPAR_VNIC_CHANNEL_PROTOCOL_UUID; -#define SPAR_VNIC_CHANNEL_PROTOCOL_UUID_STR \ - "8cd5994d-c58e-11da-95a9-00e08161165f" - -/* {72120008-4AAB-11DC-8530-444553544200} */ -#define SPAR_SIOVM_UUID \ - UUID_LE(0x72120008, 0x4AAB, 0x11DC, \ - 0x85, 0x30, 0x44, 0x45, 0x53, 0x54, 0x42, 0x00) -static const uuid_le spar_siovm_uuid = SPAR_SIOVM_UUID; - -/* {5b52c5ac-e5f5-4d42-8dff-429eaecd221f} */ -#define SPAR_CONTROLDIRECTOR_CHANNEL_PROTOCOL_UUID \ - UUID_LE(0x5b52c5ac, 0xe5f5, 0x4d42, \ - 0x8d, 0xff, 0x42, 0x9e, 0xae, 0xcd, 0x22, 0x1f) - -static const uuid_le spar_controldirector_channel_protocol_uuid = - SPAR_CONTROLDIRECTOR_CHANNEL_PROTOCOL_UUID; - -/* {b4e79625-aede-4eAA-9e11-D3eddcd4504c} */ -#define SPAR_DIAG_POOL_CHANNEL_PROTOCOL_UUID \ - UUID_LE(0xb4e79625, 0xaede, 0x4eaa, \ - 0x9e, 0x11, 0xd3, 0xed, 0xdc, 0xd4, 0x50, 0x4c) diff --git a/drivers/staging/unisys/include/iochannel.h b/drivers/staging/unisys/include/iochannel.h index 5ccf814..cba4433 100644 --- a/drivers/staging/unisys/include/iochannel.h +++ b/drivers/staging/unisys/include/iochannel.h @@ -33,7 +33,6 @@ #include <linux/dma-direction.h> #include "channel.h" -#include "channel_guid.h" #define ULTRA_VHBA_CHANNEL_PROTOCOL_SIGNATURE ULTRA_CHANNEL_PROTOCOL_SIGNATURE #define ULTRA_VNIC_CHANNEL_PROTOCOL_SIGNATURE ULTRA_CHANNEL_PROTOCOL_SIGNATURE diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index b653a5b..890c0f6 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -25,7 +25,7 @@ #include <linux/uuid.h> #include <linux/crash_dump.h> -#include "channel_guid.h" +#include "channel.h" #include "controlvmchannel.h" #include "controlvmcompletionstatus.h" #include "guestlinuxdebug.h" -- cgit v0.10.2 From d7cbd9f6c4cdb379ebd04cda9cfce1bbf6442e26 Mon Sep 17 00:00:00 2001 From: Bryan Thompson <bryan.thompson@unisys.com> Date: Fri, 2 Sep 2016 16:41:34 -0400 Subject: staging: unisys: visorinput: Update visorinput.c includes Remove unnecessary channel.h include from visorinput.c. Signed-off-by: Bryan Thompson <bryan.thompson@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorinput/visorinput.c b/drivers/staging/unisys/visorinput/visorinput.c index 2aff945..641cdab 100644 --- a/drivers/staging/unisys/visorinput/visorinput.c +++ b/drivers/staging/unisys/visorinput/visorinput.c @@ -31,7 +31,6 @@ #include "version.h" #include "visorbus.h" -#include "channel.h" #include "ultrainputreport.h" /* Keyboard channel {c73416d0-b0b8-44af-b304-9d2ae99f1b3d} */ -- cgit v0.10.2 From 89cb05105117dfa0b86635c7e8c124e529047f15 Mon Sep 17 00:00:00 2001 From: Bryan Thompson <bryan.thompson@unisys.com> Date: Fri, 2 Sep 2016 16:41:35 -0400 Subject: staging: unisys: visorinput: Remove ultrainputreport.h include Stop ultrainputreport.h from including itself. Signed-off-by: Bryan Thompson <bryan.thompson@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorinput/ultrainputreport.h b/drivers/staging/unisys/visorinput/ultrainputreport.h index 1bc3d20..53dde7c 100644 --- a/drivers/staging/unisys/visorinput/ultrainputreport.h +++ b/drivers/staging/unisys/visorinput/ultrainputreport.h @@ -17,8 +17,6 @@ #include <linux/types.h> -#include "ultrainputreport.h" - /* Identifies mouse and keyboard activity which is specified by the firmware to * the host using the cmsimpleinput protocol. @ingroup coretypes */ -- cgit v0.10.2 From e308d698bca71476c8410a7f2e68a376c34a8a3b Mon Sep 17 00:00:00 2001 From: Erik Arfvidson <erik.arfvidson@unisys.com> Date: Fri, 2 Sep 2016 16:41:36 -0400 Subject: staging: unisys: merge diagchannel.h to visorbus.h It is pointless to have a dedicated include for another include. So I merged them together. Signed-off-by: Erik Arfvidson <erik.arfvidson@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/include/diagchannel.h b/drivers/staging/unisys/include/diagchannel.h deleted file mode 100644 index 6e813c7..0000000 --- a/drivers/staging/unisys/include/diagchannel.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#ifndef _DIAG_CHANNEL_H_ -#define _DIAG_CHANNEL_H_ - -/* Levels of severity for diagnostic events, in order from lowest severity to - * highest (i.e. fatal errors are the most severe, and should always be logged, - * but info events rarely need to be logged except during debugging). The - * values DIAG_SEVERITY_ENUM_BEGIN and DIAG_SEVERITY_ENUM_END are not valid - * severity values. They exist merely to dilineate the list, so that future - * additions won't require changes to the driver (i.e. when checking for - * out-of-range severities in SetSeverity). The values DIAG_SEVERITY_OVERRIDE - * and DIAG_SEVERITY_SHUTOFF are not valid severity values for logging events - * but they are valid for controlling the amount of event data. Changes made - * to the enum, need to be reflected in s-Par. - */ -enum diag_severity { - DIAG_SEVERITY_VERBOSE = 0, - DIAG_SEVERITY_INFO = 1, - DIAG_SEVERITY_WARNING = 2, - DIAG_SEVERITY_ERR = 3, - DIAG_SEVERITY_PRINT = 4, -}; - -#endif diff --git a/drivers/staging/unisys/include/visorbus.h b/drivers/staging/unisys/include/visorbus.h index c836c8d..993cf19 100644 --- a/drivers/staging/unisys/include/visorbus.h +++ b/drivers/staging/unisys/include/visorbus.h @@ -187,6 +187,25 @@ int visorbus_write_channel(struct visor_device *dev, void visorbus_enable_channel_interrupts(struct visor_device *dev); void visorbus_disable_channel_interrupts(struct visor_device *dev); +/* Levels of severity for diagnostic events, in order from lowest severity to + * highest (i.e. fatal errors are the most severe, and should always be logged, + * but info events rarely need to be logged except during debugging). The + * values DIAG_SEVERITY_ENUM_BEGIN and DIAG_SEVERITY_ENUM_END are not valid + * severity values. They exist merely to dilineate the list, so that future + * additions won't require changes to the driver (i.e. when checking for + * out-of-range severities in SetSeverity). The values DIAG_SEVERITY_OVERRIDE + * and DIAG_SEVERITY_SHUTOFF are not valid severity values for logging events + * but they are valid for controlling the amount of event data. Changes made + * to the enum, need to be reflected in s-Par. + */ +enum diag_severity { + DIAG_SEVERITY_VERBOSE = 0, + DIAG_SEVERITY_INFO = 1, + DIAG_SEVERITY_WARNING = 2, + DIAG_SEVERITY_ERR = 3, + DIAG_SEVERITY_PRINT = 4, +}; + bool visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg); bool visorchannel_signalinsert(struct visorchannel *channel, u32 queue, diff --git a/drivers/staging/unisys/visorbus/vmcallinterface.h b/drivers/staging/unisys/visorbus/vmcallinterface.h index c043fa4..d1e6158 100644 --- a/drivers/staging/unisys/visorbus/vmcallinterface.h +++ b/drivers/staging/unisys/visorbus/vmcallinterface.h @@ -24,7 +24,6 @@ #ifdef __GNUC__ #include "iovmcall_gnuc.h" #endif /* */ -#include "diagchannel.h" #ifdef VMCALL_IO_CONTROLVM_ADDR #undef VMCALL_IO_CONTROLVM_ADDR -- cgit v0.10.2 From 8a7a2fde4d8a7a24e0ca6acc5e032ddedc0b6640 Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Fri, 2 Sep 2016 16:41:37 -0400 Subject: staging: unisys: visorbus: Merge controlvm completion status to controlvmchannel The completion status are valid only for the controlvm channel so they should be moved into its header file. Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/controlvmchannel.h b/drivers/staging/unisys/visorbus/controlvmchannel.h index 03e36fb..f0bfc4d 100644 --- a/drivers/staging/unisys/visorbus/controlvmchannel.h +++ b/drivers/staging/unisys/visorbus/controlvmchannel.h @@ -482,4 +482,80 @@ struct spar_controlvm_parameters_header { u32 reserved; /* Natural alignment */ }; +/* General Errors------------------------------------------------------[0-99] */ +#define CONTROLVM_RESP_SUCCESS 0 +#define CONTROLVM_RESP_ERROR_ALREADY_DONE 1 +#define CONTROLVM_RESP_ERROR_IOREMAP_FAILED 2 +#define CONTROLVM_RESP_ERROR_KMALLOC_FAILED 3 +#define CONTROLVM_RESP_ERROR_MESSAGE_ID_UNKNOWN 4 +#define CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT 5 + +/* CONTROLVM_INIT_CHIPSET-------------------------------------------[100-199] */ +#define CONTROLVM_RESP_ERROR_CLIENT_SWITCHCOUNT_NONZERO 100 +#define CONTROLVM_RESP_ERROR_EXPECTED_CHIPSET_INIT 101 + +/* Maximum Limit----------------------------------------------------[200-299] */ +#define CONTROLVM_RESP_ERROR_MAX_BUSES 201 /* BUS_CREATE */ +#define CONTROLVM_RESP_ERROR_MAX_DEVICES 202 /* DEVICE_CREATE */ +/* Payload and Parameter Related------------------------------------[400-499] */ +#define CONTROLVM_RESP_ERROR_PAYLOAD_INVALID 400 /* SWITCH_ATTACHEXTPORT, + * DEVICE_CONFIGURE + */ +#define CONTROLVM_RESP_ERROR_INITIATOR_PARAMETER_INVALID 401 /* Multiple */ +#define CONTROLVM_RESP_ERROR_TARGET_PARAMETER_INVALID 402 /* DEVICE_CONFIGURE */ +#define CONTROLVM_RESP_ERROR_CLIENT_PARAMETER_INVALID 403 /* DEVICE_CONFIGURE */ +/* Specified[Packet Structure] Value-------------------------------[500-599] */ +#define CONTROLVM_RESP_ERROR_BUS_INVALID 500 /* SWITCH_ATTACHINTPORT, + * BUS_CONFIGURE, + * DEVICE_CREATE, + * DEVICE_CONFIG + * DEVICE_DESTROY + */ +#define CONTROLVM_RESP_ERROR_DEVICE_INVALID 501 /* SWITCH_ATTACHINTPORT */ + /* DEVICE_CREATE, + * DEVICE_CONFIGURE, + * DEVICE_DESTROY + */ +#define CONTROLVM_RESP_ERROR_CHANNEL_INVALID 502 /* DEVICE_CREATE, + * DEVICE_CONFIGURE + */ +/* Partition Driver Callback Interface----------------------[600-699] */ +#define CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE 604 /* BUS_CREATE, + * BUS_DESTROY, + * DEVICE_CREATE, + * DEVICE_DESTROY + */ +/* Unable to invoke VIRTPCI callback */ +#define CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR 605 + /* BUS_CREATE, + * BUS_DESTROY, + * DEVICE_CREATE, + * DEVICE_DESTROY + */ +/* VIRTPCI Callback returned error */ +#define CONTROLVM_RESP_ERROR_GENERIC_DRIVER_CALLBACK_ERROR 606 + /* SWITCH_ATTACHEXTPORT, + * SWITCH_DETACHEXTPORT + * DEVICE_CONFIGURE + */ + +/* generic device callback returned error */ +/* Bus Related------------------------------------------------------[700-799] */ +#define CONTROLVM_RESP_ERROR_BUS_DEVICE_ATTACHED 700 /* BUS_DESTROY */ +/* Channel Related--------------------------------------------------[800-899] */ +#define CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN 800 /* GET_CHANNELINFO, + * DEVICE_DESTROY + */ +#define CONTROLVM_RESP_ERROR_CHANNEL_SIZE_TOO_SMALL 801 /* DEVICE_CREATE */ +/* Chipset Shutdown Related---------------------------------------[1000-1099] */ +#define CONTROLVM_RESP_ERROR_CHIPSET_SHUTDOWN_FAILED 1000 +#define CONTROLVM_RESP_ERROR_CHIPSET_SHUTDOWN_ALREADY_ACTIVE 1001 + +/* Chipset Stop Related-------------------------------------------[1100-1199] */ +#define CONTROLVM_RESP_ERROR_CHIPSET_STOP_FAILED_BUS 1100 +#define CONTROLVM_RESP_ERROR_CHIPSET_STOP_FAILED_SWITCH 1101 + +/* Device Related-------------------------------------------------[1400-1499] */ +#define CONTROLVM_RESP_ERROR_DEVICE_UDEV_TIMEOUT 1400 + #endif /* __CONTROLVMCHANNEL_H__ */ diff --git a/drivers/staging/unisys/visorbus/controlvmcompletionstatus.h b/drivers/staging/unisys/visorbus/controlvmcompletionstatus.h deleted file mode 100644 index 23ad0ea..0000000 --- a/drivers/staging/unisys/visorbus/controlvmcompletionstatus.h +++ /dev/null @@ -1,101 +0,0 @@ -/* controlvmcompletionstatus.c - * - * Copyright (C) 2010 - 2015 UNISYS CORPORATION - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -/* Defines for all valid values returned in the response message header - * completionStatus field. See controlvmchannel.h for description of - * the header: _CONTROLVM_MESSAGE_HEADER. - */ - -#ifndef __CONTROLVMCOMPLETIONSTATUS_H__ -#define __CONTROLVMCOMPLETIONSTATUS_H__ - -/* General Errors------------------------------------------------------[0-99] */ -#define CONTROLVM_RESP_SUCCESS 0 -#define CONTROLVM_RESP_ERROR_ALREADY_DONE 1 -#define CONTROLVM_RESP_ERROR_IOREMAP_FAILED 2 -#define CONTROLVM_RESP_ERROR_KMALLOC_FAILED 3 -#define CONTROLVM_RESP_ERROR_MESSAGE_ID_UNKNOWN 4 -#define CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT 5 - -/* CONTROLVM_INIT_CHIPSET-------------------------------------------[100-199] */ -#define CONTROLVM_RESP_ERROR_CLIENT_SWITCHCOUNT_NONZERO 100 -#define CONTROLVM_RESP_ERROR_EXPECTED_CHIPSET_INIT 101 - -/* Maximum Limit----------------------------------------------------[200-299] */ -#define CONTROLVM_RESP_ERROR_MAX_BUSES 201 /* BUS_CREATE */ -#define CONTROLVM_RESP_ERROR_MAX_DEVICES 202 /* DEVICE_CREATE */ -/* Payload and Parameter Related------------------------------------[400-499] */ -#define CONTROLVM_RESP_ERROR_PAYLOAD_INVALID 400 /* SWITCH_ATTACHEXTPORT, - * DEVICE_CONFIGURE - */ -#define CONTROLVM_RESP_ERROR_INITIATOR_PARAMETER_INVALID 401 /* Multiple */ -#define CONTROLVM_RESP_ERROR_TARGET_PARAMETER_INVALID 402 /* DEVICE_CONFIGURE */ -#define CONTROLVM_RESP_ERROR_CLIENT_PARAMETER_INVALID 403 /* DEVICE_CONFIGURE */ -/* Specified[Packet Structure] Value-------------------------------[500-599] */ -#define CONTROLVM_RESP_ERROR_BUS_INVALID 500 /* SWITCH_ATTACHINTPORT, - * BUS_CONFIGURE, - * DEVICE_CREATE, - * DEVICE_CONFIG - * DEVICE_DESTROY - */ -#define CONTROLVM_RESP_ERROR_DEVICE_INVALID 501 /* SWITCH_ATTACHINTPORT */ - /* DEVICE_CREATE, - * DEVICE_CONFIGURE, - * DEVICE_DESTROY - */ -#define CONTROLVM_RESP_ERROR_CHANNEL_INVALID 502 /* DEVICE_CREATE, - * DEVICE_CONFIGURE - */ -/* Partition Driver Callback Interface----------------------[600-699] */ -#define CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE 604 /* BUS_CREATE, - * BUS_DESTROY, - * DEVICE_CREATE, - * DEVICE_DESTROY - */ -/* Unable to invoke VIRTPCI callback */ -#define CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR 605 - /* BUS_CREATE, - * BUS_DESTROY, - * DEVICE_CREATE, - * DEVICE_DESTROY - */ -/* VIRTPCI Callback returned error */ -#define CONTROLVM_RESP_ERROR_GENERIC_DRIVER_CALLBACK_ERROR 606 - /* SWITCH_ATTACHEXTPORT, - * SWITCH_DETACHEXTPORT - * DEVICE_CONFIGURE - */ - -/* generic device callback returned error */ -/* Bus Related------------------------------------------------------[700-799] */ -#define CONTROLVM_RESP_ERROR_BUS_DEVICE_ATTACHED 700 /* BUS_DESTROY */ -/* Channel Related--------------------------------------------------[800-899] */ -#define CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN 800 /* GET_CHANNELINFO, - * DEVICE_DESTROY - */ -#define CONTROLVM_RESP_ERROR_CHANNEL_SIZE_TOO_SMALL 801 /* DEVICE_CREATE */ -/* Chipset Shutdown Related---------------------------------------[1000-1099] */ -#define CONTROLVM_RESP_ERROR_CHIPSET_SHUTDOWN_FAILED 1000 -#define CONTROLVM_RESP_ERROR_CHIPSET_SHUTDOWN_ALREADY_ACTIVE 1001 - -/* Chipset Stop Related-------------------------------------------[1100-1199] */ -#define CONTROLVM_RESP_ERROR_CHIPSET_STOP_FAILED_BUS 1100 -#define CONTROLVM_RESP_ERROR_CHIPSET_STOP_FAILED_SWITCH 1101 - -/* Device Related-------------------------------------------------[1400-1499] */ -#define CONTROLVM_RESP_ERROR_DEVICE_UDEV_TIMEOUT 1400 - -#endif /* __CONTROLVMCOMPLETIONSTATUS_H__ not defined */ diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 890c0f6..a8e7708 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -27,7 +27,6 @@ #include "channel.h" #include "controlvmchannel.h" -#include "controlvmcompletionstatus.h" #include "guestlinuxdebug.h" #include "version.h" #include "visorbus.h" -- cgit v0.10.2 From 3995c5da25e988b5699989912a2024a10c0d1b95 Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Fri, 2 Sep 2016 16:41:38 -0400 Subject: staging: unisys: visorbus: Reorder functions to avoid including header Visorchannel does not need to include visorbus_private.h; all it was using it for was function prototypes. A simple reorder causes it to no longer need to include it. Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c index fbae66e..b84c8d8 100644 --- a/drivers/staging/unisys/visorbus/visorchannel.c +++ b/drivers/staging/unisys/visorbus/visorchannel.c @@ -25,7 +25,6 @@ #include "version.h" #include "visorbus.h" #include "controlvmchannel.h" -#include "visorbus_private.h" #define MYDRVNAME "visorchannel" @@ -56,128 +55,6 @@ struct visorchannel { uuid_le inst; }; -/** - * visorchannel_create_guts() - creates the struct visorchannel abstraction - * for a data area in memory, but does NOT modify - * this data area - * @physaddr: physical address of start of channel - * @channel_bytes: size of the channel in bytes; this may 0 if the channel has - * already been initialized in memory (which is true for all - * channels provided to guest environments by the s-Par - * back-end), in which case the actual channel size will be - * read from the channel header in memory - * @gfp: gfp_t to use when allocating memory for the data struct - * @guid: uuid that identifies channel type; this may 0 if the channel - * has already been initialized in memory (which is true for all - * channels provided to guest environments by the s-Par - * back-end), in which case the actual channel guid will be - * read from the channel header in memory - * @needs_lock: must specify true if you have multiple threads of execution - * that will be calling visorchannel methods of this - * visorchannel at the same time - * - * Return: pointer to visorchannel that was created if successful, - * otherwise NULL - */ -static struct visorchannel * -visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes, - gfp_t gfp, uuid_le guid, bool needs_lock) -{ - struct visorchannel *channel; - int err; - size_t size = sizeof(struct channel_header); - - if (physaddr == 0) - return NULL; - - channel = kzalloc(sizeof(*channel), gfp); - if (!channel) - return NULL; - - channel->needs_lock = needs_lock; - spin_lock_init(&channel->insert_lock); - spin_lock_init(&channel->remove_lock); - - /* - * Video driver constains the efi framebuffer so it will get a - * conflict resource when requesting its full mem region. Since - * we are only using the efi framebuffer for video we can ignore - * this. Remember that we haven't requested it so we don't try to - * release later on. - */ - channel->requested = request_mem_region(physaddr, size, MYDRVNAME); - if (!channel->requested) { - if (uuid_le_cmp(guid, spar_video_guid)) { - /* Not the video channel we care about this */ - goto err_destroy_channel; - } - } - - channel->mapped = memremap(physaddr, size, MEMREMAP_WB); - if (!channel->mapped) { - release_mem_region(physaddr, size); - goto err_destroy_channel; - } - - channel->physaddr = physaddr; - channel->nbytes = size; - - err = visorchannel_read(channel, 0, &channel->chan_hdr, - sizeof(struct channel_header)); - if (err) - goto err_destroy_channel; - - /* we had better be a CLIENT of this channel */ - if (channel_bytes == 0) - channel_bytes = (ulong)channel->chan_hdr.size; - if (uuid_le_cmp(guid, NULL_UUID_LE) == 0) - guid = channel->chan_hdr.chtype; - - memunmap(channel->mapped); - if (channel->requested) - release_mem_region(channel->physaddr, channel->nbytes); - channel->mapped = NULL; - channel->requested = request_mem_region(channel->physaddr, - channel_bytes, MYDRVNAME); - if (!channel->requested) { - if (uuid_le_cmp(guid, spar_video_guid)) { - /* Different we care about this */ - goto err_destroy_channel; - } - } - - channel->mapped = memremap(channel->physaddr, channel_bytes, - MEMREMAP_WB); - if (!channel->mapped) { - release_mem_region(channel->physaddr, channel_bytes); - goto err_destroy_channel; - } - - channel->nbytes = channel_bytes; - channel->guid = guid; - return channel; - -err_destroy_channel: - visorchannel_destroy(channel); - return NULL; -} - -struct visorchannel * -visorchannel_create(u64 physaddr, unsigned long channel_bytes, - gfp_t gfp, uuid_le guid) -{ - return visorchannel_create_guts(physaddr, channel_bytes, gfp, guid, - false); -} - -struct visorchannel * -visorchannel_create_with_lock(u64 physaddr, unsigned long channel_bytes, - gfp_t gfp, uuid_le guid) -{ - return visorchannel_create_guts(physaddr, channel_bytes, gfp, guid, - true); -} - void visorchannel_destroy(struct visorchannel *channel) { @@ -489,6 +366,128 @@ signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg) } /** + * visorchannel_create_guts() - creates the struct visorchannel abstraction + * for a data area in memory, but does NOT modify + * this data area + * @physaddr: physical address of start of channel + * @channel_bytes: size of the channel in bytes; this may 0 if the channel has + * already been initialized in memory (which is true for all + * channels provided to guest environments by the s-Par + * back-end), in which case the actual channel size will be + * read from the channel header in memory + * @gfp: gfp_t to use when allocating memory for the data struct + * @guid: uuid that identifies channel type; this may 0 if the channel + * has already been initialized in memory (which is true for all + * channels provided to guest environments by the s-Par + * back-end), in which case the actual channel guid will be + * read from the channel header in memory + * @needs_lock: must specify true if you have multiple threads of execution + * that will be calling visorchannel methods of this + * visorchannel at the same time + * + * Return: pointer to visorchannel that was created if successful, + * otherwise NULL + */ +static struct visorchannel * +visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes, + gfp_t gfp, uuid_le guid, bool needs_lock) +{ + struct visorchannel *channel; + int err; + size_t size = sizeof(struct channel_header); + + if (physaddr == 0) + return NULL; + + channel = kzalloc(sizeof(*channel), gfp); + if (!channel) + return NULL; + + channel->needs_lock = needs_lock; + spin_lock_init(&channel->insert_lock); + spin_lock_init(&channel->remove_lock); + + /* + * Video driver constains the efi framebuffer so it will get a + * conflict resource when requesting its full mem region. Since + * we are only using the efi framebuffer for video we can ignore + * this. Remember that we haven't requested it so we don't try to + * release later on. + */ + channel->requested = request_mem_region(physaddr, size, MYDRVNAME); + if (!channel->requested) { + if (uuid_le_cmp(guid, spar_video_guid)) { + /* Not the video channel we care about this */ + goto err_destroy_channel; + } + } + + channel->mapped = memremap(physaddr, size, MEMREMAP_WB); + if (!channel->mapped) { + release_mem_region(physaddr, size); + goto err_destroy_channel; + } + + channel->physaddr = physaddr; + channel->nbytes = size; + + err = visorchannel_read(channel, 0, &channel->chan_hdr, + sizeof(struct channel_header)); + if (err) + goto err_destroy_channel; + + /* we had better be a CLIENT of this channel */ + if (channel_bytes == 0) + channel_bytes = (ulong)channel->chan_hdr.size; + if (uuid_le_cmp(guid, NULL_UUID_LE) == 0) + guid = channel->chan_hdr.chtype; + + memunmap(channel->mapped); + if (channel->requested) + release_mem_region(channel->physaddr, channel->nbytes); + channel->mapped = NULL; + channel->requested = request_mem_region(channel->physaddr, + channel_bytes, MYDRVNAME); + if (!channel->requested) { + if (uuid_le_cmp(guid, spar_video_guid)) { + /* Different we care about this */ + goto err_destroy_channel; + } + } + + channel->mapped = memremap(channel->physaddr, channel_bytes, + MEMREMAP_WB); + if (!channel->mapped) { + release_mem_region(channel->physaddr, channel_bytes); + goto err_destroy_channel; + } + + channel->nbytes = channel_bytes; + channel->guid = guid; + return channel; + +err_destroy_channel: + visorchannel_destroy(channel); + return NULL; +} + +struct visorchannel * +visorchannel_create(u64 physaddr, unsigned long channel_bytes, + gfp_t gfp, uuid_le guid) +{ + return visorchannel_create_guts(physaddr, channel_bytes, gfp, guid, + false); +} + +struct visorchannel * +visorchannel_create_with_lock(u64 physaddr, unsigned long channel_bytes, + gfp_t gfp, uuid_le guid) +{ + return visorchannel_create_guts(physaddr, channel_bytes, gfp, guid, + true); +} + +/** * visorchannel_signalinsert() - inserts a message into the designated * channel/queue * @channel: the channel the message will be added to -- cgit v0.10.2 From b6d0fa15e851cc8779a5e7676f2b52a33baba8ba Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Fri, 2 Sep 2016 16:41:39 -0400 Subject: staging: unisys: visorbus: merge vbusdeviceinfo.h into vbuschannel vbusdeviceinfo.h was only used by vbuschannel.h so merge them together. Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/vbuschannel.h b/drivers/staging/unisys/visorbus/vbuschannel.h index 90fa12e..3f7830b 100644 --- a/drivers/staging/unisys/visorbus/vbuschannel.h +++ b/drivers/staging/unisys/visorbus/vbuschannel.h @@ -23,7 +23,6 @@ * the client devices and client drivers for the server end to see. */ #include <linux/uuid.h> -#include "vbusdeviceinfo.h" #include "channel.h" /* {193b331b-c58f-11da-95a9-00e08161165f} */ @@ -58,6 +57,217 @@ static const uuid_le spar_vbus_channel_protocol_uuid = actual_bytes)) #pragma pack(push, 1) /* both GCC and VC now allow this pragma */ + +/* + * An array of this struct is present in the channel area for each vbus. + * (See vbuschannel.h.) + * It is filled in by the client side to provide info about the device + * and driver from the client's perspective. + */ +struct ultra_vbus_deviceinfo { + u8 devtype[16]; /* short string identifying the device type */ + u8 drvname[16]; /* driver .sys file name */ + u8 infostrs[96]; /* sequence of tab-delimited id strings: */ + /* <DRIVER_REV> <DRIVER_VERTAG> <DRIVER_COMPILETIME> */ + u8 reserved[128]; /* pad size to 256 bytes */ +}; + +/** + * vbuschannel_sanitize_buffer() - remove non-printable chars from buffer + * @p: destination buffer where chars are written to + * @remain: number of bytes that can be written starting at #p + * @src: pointer to source buffer + * @srcmax: number of valid characters at #src + * + * Reads chars from the buffer at @src for @srcmax bytes, and writes to + * the buffer at @p, which is @remain bytes long, ensuring never to + * overflow the buffer at @p, using the following rules: + * - printable characters are simply copied from the buffer at @src to the + * buffer at @p + * - intervening streaks of non-printable characters in the buffer at @src + * are replaced with a single space in the buffer at @p + * Note that we pay no attention to '\0'-termination. + * + * Pass @p == NULL and @remain == 0 for this special behavior -- In this + * case, we simply return the number of bytes that WOULD HAVE been written + * to a buffer at @p, had it been infinitely big. + * + * Return: the number of bytes written to @p (or WOULD HAVE been written to + * @p, as described in the previous paragraph) + */ +static inline int +vbuschannel_sanitize_buffer(char *p, int remain, char *src, int srcmax) +{ + int chars = 0; + int nonprintable_streak = 0; + + while (srcmax > 0) { + if ((*src >= ' ') && (*src < 0x7f)) { + if (nonprintable_streak) { + if (remain > 0) { + *p = ' '; + p++; + remain--; + chars++; + } else if (!p) { + chars++; + } + nonprintable_streak = 0; + } + if (remain > 0) { + *p = *src; + p++; + remain--; + chars++; + } else if (!p) { + chars++; + } + } else { + nonprintable_streak = 1; + } + src++; + srcmax--; + } + return chars; +} + +#define VBUSCHANNEL_ADDACHAR(ch, p, remain, chars) \ + do { \ + if (remain <= 0) \ + break; \ + *p = ch; \ + p++; chars++; remain--; \ + } while (0) + +/** + * vbuschannel_itoa() - convert non-negative int to string + * @p: destination string + * @remain: max number of bytes that can be written to @p + * @num: input int to convert + * + * Converts the non-negative value at @num to an ascii decimal string + * at @p, writing at most @remain bytes. Note there is NO '\0' termination + * written to @p. + * + * Return: number of bytes written to @p + * + */ +static inline int +vbuschannel_itoa(char *p, int remain, int num) +{ + int digits = 0; + char s[32]; + int i; + + if (num == 0) { + /* '0' is a special case */ + if (remain <= 0) + return 0; + *p = '0'; + return 1; + } + /* form a backwards decimal ascii string in <s> */ + while (num > 0) { + if (digits >= (int)sizeof(s)) + return 0; + s[digits++] = (num % 10) + '0'; + num = num / 10; + } + if (remain < digits) { + /* not enough room left at <p> to hold number, so fill with + * '?' + */ + for (i = 0; i < remain; i++, p++) + *p = '?'; + return remain; + } + /* plug in the decimal ascii string representing the number, by */ + /* reversing the string we just built in <s> */ + i = digits; + while (i > 0) { + i--; + *p = s[i]; + p++; + } + return digits; +} + +/** + * vbuschannel_devinfo_to_string() - format a struct ultra_vbus_deviceinfo + * to a printable string + * @devinfo: the struct ultra_vbus_deviceinfo to format + * @p: destination string area + * @remain: size of destination string area in bytes + * @devix: the device index to be included in the output data, or -1 if no + * device index is to be included + * + * Reads @devInfo, and converts its contents to a printable string at @p, + * writing at most @remain bytes. Note there is NO '\0' termination + * written to @p. + * + * Return: number of bytes written to @p + */ +static inline int +vbuschannel_devinfo_to_string(struct ultra_vbus_deviceinfo *devinfo, + char *p, int remain, int devix) +{ + char *psrc; + int nsrc, x, i, pad; + int chars = 0; + + psrc = &devinfo->devtype[0]; + nsrc = sizeof(devinfo->devtype); + if (vbuschannel_sanitize_buffer(NULL, 0, psrc, nsrc) <= 0) + return 0; + + /* emit device index */ + if (devix >= 0) { + VBUSCHANNEL_ADDACHAR('[', p, remain, chars); + x = vbuschannel_itoa(p, remain, devix); + p += x; + remain -= x; + chars += x; + VBUSCHANNEL_ADDACHAR(']', p, remain, chars); + } else { + VBUSCHANNEL_ADDACHAR(' ', p, remain, chars); + VBUSCHANNEL_ADDACHAR(' ', p, remain, chars); + VBUSCHANNEL_ADDACHAR(' ', p, remain, chars); + } + + /* emit device type */ + x = vbuschannel_sanitize_buffer(p, remain, psrc, nsrc); + p += x; + remain -= x; + chars += x; + pad = 15 - x; /* pad device type to be exactly 15 chars */ + for (i = 0; i < pad; i++) + VBUSCHANNEL_ADDACHAR(' ', p, remain, chars); + VBUSCHANNEL_ADDACHAR(' ', p, remain, chars); + + /* emit driver name */ + psrc = &devinfo->drvname[0]; + nsrc = sizeof(devinfo->drvname); + x = vbuschannel_sanitize_buffer(p, remain, psrc, nsrc); + p += x; + remain -= x; + chars += x; + pad = 15 - x; /* pad driver name to be exactly 15 chars */ + for (i = 0; i < pad; i++) + VBUSCHANNEL_ADDACHAR(' ', p, remain, chars); + VBUSCHANNEL_ADDACHAR(' ', p, remain, chars); + + /* emit strings */ + psrc = &devinfo->infostrs[0]; + nsrc = sizeof(devinfo->infostrs); + x = vbuschannel_sanitize_buffer(p, remain, psrc, nsrc); + p += x; + remain -= x; + chars += x; + VBUSCHANNEL_ADDACHAR('\n', p, remain, chars); + + return chars; +} + struct spar_vbus_headerinfo { u32 struct_bytes; /* size of this struct in bytes */ u32 device_info_struct_bytes; /* sizeof(ULTRA_VBUS_DEVICEINFO) */ diff --git a/drivers/staging/unisys/visorbus/vbusdeviceinfo.h b/drivers/staging/unisys/visorbus/vbusdeviceinfo.h deleted file mode 100644 index e6bfed1..0000000 --- a/drivers/staging/unisys/visorbus/vbusdeviceinfo.h +++ /dev/null @@ -1,234 +0,0 @@ -/* Copyright (C) 2010 - 2015 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#ifndef __VBUSDEVICEINFO_H__ -#define __VBUSDEVICEINFO_H__ - -#include <linux/types.h> - -#pragma pack(push, 1) /* both GCC and VC now allow this pragma */ - -/* - * An array of this struct is present in the channel area for each vbus. - * (See vbuschannel.h.) - * It is filled in by the client side to provide info about the device - * and driver from the client's perspective. - */ -struct ultra_vbus_deviceinfo { - u8 devtype[16]; /* short string identifying the device type */ - u8 drvname[16]; /* driver .sys file name */ - u8 infostrs[96]; /* sequence of tab-delimited id strings: */ - /* <DRIVER_REV> <DRIVER_VERTAG> <DRIVER_COMPILETIME> */ - u8 reserved[128]; /* pad size to 256 bytes */ -}; - -#pragma pack(pop) - -/** - * vbuschannel_sanitize_buffer() - remove non-printable chars from buffer - * @p: destination buffer where chars are written to - * @remain: number of bytes that can be written starting at #p - * @src: pointer to source buffer - * @srcmax: number of valid characters at #src - * - * Reads chars from the buffer at @src for @srcmax bytes, and writes to - * the buffer at @p, which is @remain bytes long, ensuring never to - * overflow the buffer at @p, using the following rules: - * - printable characters are simply copied from the buffer at @src to the - * buffer at @p - * - intervening streaks of non-printable characters in the buffer at @src - * are replaced with a single space in the buffer at @p - * Note that we pay no attention to '\0'-termination. - * - * Pass @p == NULL and @remain == 0 for this special behavior -- In this - * case, we simply return the number of bytes that WOULD HAVE been written - * to a buffer at @p, had it been infinitely big. - * - * Return: the number of bytes written to @p (or WOULD HAVE been written to - * @p, as described in the previous paragraph) - */ -static inline int -vbuschannel_sanitize_buffer(char *p, int remain, char *src, int srcmax) -{ - int chars = 0; - int nonprintable_streak = 0; - - while (srcmax > 0) { - if ((*src >= ' ') && (*src < 0x7f)) { - if (nonprintable_streak) { - if (remain > 0) { - *p = ' '; - p++; - remain--; - chars++; - } else if (!p) { - chars++; - } - nonprintable_streak = 0; - } - if (remain > 0) { - *p = *src; - p++; - remain--; - chars++; - } else if (!p) { - chars++; - } - } else { - nonprintable_streak = 1; - } - src++; - srcmax--; - } - return chars; -} - -#define VBUSCHANNEL_ADDACHAR(ch, p, remain, chars) \ - do { \ - if (remain <= 0) \ - break; \ - *p = ch; \ - p++; chars++; remain--; \ - } while (0) - -/** - * vbuschannel_itoa() - convert non-negative int to string - * @p: destination string - * @remain: max number of bytes that can be written to @p - * @num: input int to convert - * - * Converts the non-negative value at @num to an ascii decimal string - * at @p, writing at most @remain bytes. Note there is NO '\0' termination - * written to @p. - * - * Return: number of bytes written to @p - * - */ -static inline int -vbuschannel_itoa(char *p, int remain, int num) -{ - int digits = 0; - char s[32]; - int i; - - if (num == 0) { - /* '0' is a special case */ - if (remain <= 0) - return 0; - *p = '0'; - return 1; - } - /* form a backwards decimal ascii string in <s> */ - while (num > 0) { - if (digits >= (int)sizeof(s)) - return 0; - s[digits++] = (num % 10) + '0'; - num = num / 10; - } - if (remain < digits) { - /* not enough room left at <p> to hold number, so fill with - * '?' - */ - for (i = 0; i < remain; i++, p++) - *p = '?'; - return remain; - } - /* plug in the decimal ascii string representing the number, by */ - /* reversing the string we just built in <s> */ - i = digits; - while (i > 0) { - i--; - *p = s[i]; - p++; - } - return digits; -} - -/** - * vbuschannel_devinfo_to_string() - format a struct ultra_vbus_deviceinfo - * to a printable string - * @devinfo: the struct ultra_vbus_deviceinfo to format - * @p: destination string area - * @remain: size of destination string area in bytes - * @devix: the device index to be included in the output data, or -1 if no - * device index is to be included - * - * Reads @devInfo, and converts its contents to a printable string at @p, - * writing at most @remain bytes. Note there is NO '\0' termination - * written to @p. - * - * Return: number of bytes written to @p - */ -static inline int -vbuschannel_devinfo_to_string(struct ultra_vbus_deviceinfo *devinfo, - char *p, int remain, int devix) -{ - char *psrc; - int nsrc, x, i, pad; - int chars = 0; - - psrc = &devinfo->devtype[0]; - nsrc = sizeof(devinfo->devtype); - if (vbuschannel_sanitize_buffer(NULL, 0, psrc, nsrc) <= 0) - return 0; - - /* emit device index */ - if (devix >= 0) { - VBUSCHANNEL_ADDACHAR('[', p, remain, chars); - x = vbuschannel_itoa(p, remain, devix); - p += x; - remain -= x; - chars += x; - VBUSCHANNEL_ADDACHAR(']', p, remain, chars); - } else { - VBUSCHANNEL_ADDACHAR(' ', p, remain, chars); - VBUSCHANNEL_ADDACHAR(' ', p, remain, chars); - VBUSCHANNEL_ADDACHAR(' ', p, remain, chars); - } - - /* emit device type */ - x = vbuschannel_sanitize_buffer(p, remain, psrc, nsrc); - p += x; - remain -= x; - chars += x; - pad = 15 - x; /* pad device type to be exactly 15 chars */ - for (i = 0; i < pad; i++) - VBUSCHANNEL_ADDACHAR(' ', p, remain, chars); - VBUSCHANNEL_ADDACHAR(' ', p, remain, chars); - - /* emit driver name */ - psrc = &devinfo->drvname[0]; - nsrc = sizeof(devinfo->drvname); - x = vbuschannel_sanitize_buffer(p, remain, psrc, nsrc); - p += x; - remain -= x; - chars += x; - pad = 15 - x; /* pad driver name to be exactly 15 chars */ - for (i = 0; i < pad; i++) - VBUSCHANNEL_ADDACHAR(' ', p, remain, chars); - VBUSCHANNEL_ADDACHAR(' ', p, remain, chars); - - /* emit strings */ - psrc = &devinfo->infostrs[0]; - nsrc = sizeof(devinfo->infostrs); - x = vbuschannel_sanitize_buffer(p, remain, psrc, nsrc); - p += x; - remain -= x; - chars += x; - VBUSCHANNEL_ADDACHAR('\n', p, remain, chars); - - return chars; -} - -#endif diff --git a/drivers/staging/unisys/visorbus/visorbus_private.h b/drivers/staging/unisys/visorbus/visorbus_private.h index b10fc1a..2f4e1e6 100644 --- a/drivers/staging/unisys/visorbus/visorbus_private.h +++ b/drivers/staging/unisys/visorbus/visorbus_private.h @@ -20,7 +20,7 @@ #include <linux/uuid.h> #include "controlvmchannel.h" -#include "vbusdeviceinfo.h" +#include "vbuschannel.h" /* TARGET_HOSTNAME specified as -DTARGET_HOSTNAME=\"thename\" on the * command line -- cgit v0.10.2 From 77190cfc458af4b04b135f09ae9b0f892449ee40 Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Fri, 2 Sep 2016 16:41:40 -0400 Subject: staging: unisys: visorbus: Merge iovmcall_gnuc into vmcallinterface iovmcall_gnuc was only being referenced by vmcallinterface, so merge them together. Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/iovmcall_gnuc.h b/drivers/staging/unisys/visorbus/iovmcall_gnuc.h deleted file mode 100644 index 98ea7f3..0000000 --- a/drivers/staging/unisys/visorbus/iovmcall_gnuc.h +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright (C) 2010 - 2015 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -/* Linux GCC Version (32-bit and 64-bit) */ -static inline unsigned long -__unisys_vmcall_gnuc(unsigned long tuple, unsigned long reg_ebx, - unsigned long reg_ecx) -{ - unsigned long result = 0; - unsigned int cpuid_eax, cpuid_ebx, cpuid_ecx, cpuid_edx; - - cpuid(0x00000001, &cpuid_eax, &cpuid_ebx, &cpuid_ecx, &cpuid_edx); - if (!(cpuid_ecx & 0x80000000)) - return -EPERM; - - __asm__ __volatile__(".byte 0x00f, 0x001, 0x0c1" : "=a"(result) : - "a"(tuple), "b"(reg_ebx), "c"(reg_ecx)); - return result; -} - -static inline unsigned long -__unisys_extended_vmcall_gnuc(unsigned long long tuple, - unsigned long long reg_ebx, - unsigned long long reg_ecx, - unsigned long long reg_edx) -{ - unsigned long result = 0; - unsigned int cpuid_eax, cpuid_ebx, cpuid_ecx, cpuid_edx; - - cpuid(0x00000001, &cpuid_eax, &cpuid_ebx, &cpuid_ecx, &cpuid_edx); - if (!(cpuid_ecx & 0x80000000)) - return -EPERM; - - __asm__ __volatile__(".byte 0x00f, 0x001, 0x0c1" : "=a"(result) : - "a"(tuple), "b"(reg_ebx), "c"(reg_ecx), "d"(reg_edx)); - return result; -} diff --git a/drivers/staging/unisys/visorbus/vmcallinterface.h b/drivers/staging/unisys/visorbus/vmcallinterface.h index d1e6158..0e8f146 100644 --- a/drivers/staging/unisys/visorbus/vmcallinterface.h +++ b/drivers/staging/unisys/visorbus/vmcallinterface.h @@ -20,10 +20,39 @@ * Virtualization. The VMCALLs are provided by Monitor and used by IO code * running on IO Partitions. */ +static inline unsigned long +__unisys_vmcall_gnuc(unsigned long tuple, unsigned long reg_ebx, + unsigned long reg_ecx) +{ + unsigned long result = 0; + unsigned int cpuid_eax, cpuid_ebx, cpuid_ecx, cpuid_edx; -#ifdef __GNUC__ -#include "iovmcall_gnuc.h" -#endif /* */ + cpuid(0x00000001, &cpuid_eax, &cpuid_ebx, &cpuid_ecx, &cpuid_edx); + if (!(cpuid_ecx & 0x80000000)) + return -EPERM; + + __asm__ __volatile__(".byte 0x00f, 0x001, 0x0c1" : "=a"(result) : + "a"(tuple), "b"(reg_ebx), "c"(reg_ecx)); + return result; +} + +static inline unsigned long +__unisys_extended_vmcall_gnuc(unsigned long long tuple, + unsigned long long reg_ebx, + unsigned long long reg_ecx, + unsigned long long reg_edx) +{ + unsigned long result = 0; + unsigned int cpuid_eax, cpuid_ebx, cpuid_ecx, cpuid_edx; + + cpuid(0x00000001, &cpuid_eax, &cpuid_ebx, &cpuid_ecx, &cpuid_edx); + if (!(cpuid_ecx & 0x80000000)) + return -EPERM; + + __asm__ __volatile__(".byte 0x00f, 0x001, 0x0c1" : "=a"(result) : + "a"(tuple), "b"(reg_ebx), "c"(reg_ecx), "d"(reg_edx)); + return result; +} #ifdef VMCALL_IO_CONTROLVM_ADDR #undef VMCALL_IO_CONTROLVM_ADDR -- cgit v0.10.2 From 443c0c7ae95de44da1b92f371f23a181a9786076 Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Fri, 2 Sep 2016 16:41:41 -0400 Subject: staging: unisys: visorbus: remove include for vbuschannel.h visorbus_main.c does not need to include vbuschannel.h. Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index a100c79..b17c94c 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -19,7 +19,6 @@ #include "visorbus.h" #include "visorbus_private.h" #include "version.h" -#include "vbuschannel.h" #include "guestlinuxdebug.h" #include "vmcallinterface.h" -- cgit v0.10.2 From dca0a14df16cea02ac690443487995fe4424fae9 Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Fri, 2 Sep 2016 16:41:42 -0400 Subject: staging: unisys: visorbus: Move non global guestlinuxdebug to visorbus Guestlinuxdebug.h is only used by visorbus, move the include file into its directory instead of the global one. Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/include/guestlinuxdebug.h b/drivers/staging/unisys/include/guestlinuxdebug.h deleted file mode 100644 index 5af3f77..0000000 --- a/drivers/staging/unisys/include/guestlinuxdebug.h +++ /dev/null @@ -1,180 +0,0 @@ -/* Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#ifndef __GUESTLINUXDEBUG_H__ -#define __GUESTLINUXDEBUG_H__ - -/* - * This file contains supporting interface for "vmcallinterface.h", particularly - * regarding adding additional structure and functionality to linux - * ISSUE_IO_VMCALL_POSTCODE_SEVERITY - */ - -/******* INFO ON ISSUE_POSTCODE_LINUX() BELOW *******/ -enum driver_pc { /* POSTCODE driver identifier tuples */ - /* visorchipset driver files */ - VISOR_CHIPSET_PC = 0xA0, - VISOR_CHIPSET_PC_controlvm_c = 0xA1, - VISOR_CHIPSET_PC_controlvm_cm2 = 0xA2, - VISOR_CHIPSET_PC_controlvm_direct_c = 0xA3, - VISOR_CHIPSET_PC_file_c = 0xA4, - VISOR_CHIPSET_PC_parser_c = 0xA5, - VISOR_CHIPSET_PC_testing_c = 0xA6, - VISOR_CHIPSET_PC_visorchipset_main_c = 0xA7, - VISOR_CHIPSET_PC_visorswitchbus_c = 0xA8, - /* visorbus driver files */ - VISOR_BUS_PC = 0xB0, - VISOR_BUS_PC_businst_attr_c = 0xB1, - VISOR_BUS_PC_channel_attr_c = 0xB2, - VISOR_BUS_PC_devmajorminor_attr_c = 0xB3, - VISOR_BUS_PC_visorbus_main_c = 0xB4, - /* visorclientbus driver files */ - VISOR_CLIENT_BUS_PC = 0xC0, - VISOR_CLIENT_BUS_PC_visorclientbus_main_c = 0xC1, - /* virt hba driver files */ - VIRT_HBA_PC = 0xC2, - VIRT_HBA_PC_virthba_c = 0xC3, - /* virtpci driver files */ - VIRT_PCI_PC = 0xC4, - VIRT_PCI_PC_virtpci_c = 0xC5, - /* virtnic driver files */ - VIRT_NIC_PC = 0xC6, - VIRT_NIC_P_virtnic_c = 0xC7, - /* uislib driver files */ - UISLIB_PC = 0xD0, - UISLIB_PC_uislib_c = 0xD1, - UISLIB_PC_uisqueue_c = 0xD2, - /* 0xD3 RESERVED */ - UISLIB_PC_uisutils_c = 0xD4, -}; - -enum event_pc { /* POSTCODE event identifier tuples */ - ATTACH_PORT_ENTRY_PC = 0x001, - ATTACH_PORT_FAILURE_PC = 0x002, - ATTACH_PORT_SUCCESS_PC = 0x003, - BUS_FAILURE_PC = 0x004, - BUS_CREATE_ENTRY_PC = 0x005, - BUS_CREATE_FAILURE_PC = 0x006, - BUS_CREATE_EXIT_PC = 0x007, - BUS_CONFIGURE_ENTRY_PC = 0x008, - BUS_CONFIGURE_FAILURE_PC = 0x009, - BUS_CONFIGURE_EXIT_PC = 0x00A, - CHIPSET_INIT_ENTRY_PC = 0x00B, - CHIPSET_INIT_SUCCESS_PC = 0x00C, - CHIPSET_INIT_FAILURE_PC = 0x00D, - CHIPSET_INIT_EXIT_PC = 0x00E, - CREATE_WORKQUEUE_PC = 0x00F, - CREATE_WORKQUEUE_FAILED_PC = 0x0A0, - CONTROLVM_INIT_FAILURE_PC = 0x0A1, - DEVICE_CREATE_ENTRY_PC = 0x0A2, - DEVICE_CREATE_FAILURE_PC = 0x0A3, - DEVICE_CREATE_SUCCESS_PC = 0x0A4, - DEVICE_CREATE_EXIT_PC = 0x0A5, - DEVICE_ADD_PC = 0x0A6, - DEVICE_REGISTER_FAILURE_PC = 0x0A7, - DEVICE_CHANGESTATE_ENTRY_PC = 0x0A8, - DEVICE_CHANGESTATE_FAILURE_PC = 0x0A9, - DEVICE_CHANGESTATE_EXIT_PC = 0x0AA, - DRIVER_ENTRY_PC = 0x0AB, - DRIVER_EXIT_PC = 0x0AC, - MALLOC_FAILURE_PC = 0x0AD, - QUEUE_DELAYED_WORK_PC = 0x0AE, - /* 0x0B7 RESERVED */ - VBUS_CHANNEL_ENTRY_PC = 0x0B8, - VBUS_CHANNEL_FAILURE_PC = 0x0B9, - VBUS_CHANNEL_EXIT_PC = 0x0BA, - VHBA_CREATE_ENTRY_PC = 0x0BB, - VHBA_CREATE_FAILURE_PC = 0x0BC, - VHBA_CREATE_EXIT_PC = 0x0BD, - VHBA_CREATE_SUCCESS_PC = 0x0BE, - VHBA_COMMAND_HANDLER_PC = 0x0BF, - VHBA_PROBE_ENTRY_PC = 0x0C0, - VHBA_PROBE_FAILURE_PC = 0x0C1, - VHBA_PROBE_EXIT_PC = 0x0C2, - VNIC_CREATE_ENTRY_PC = 0x0C3, - VNIC_CREATE_FAILURE_PC = 0x0C4, - VNIC_CREATE_SUCCESS_PC = 0x0C5, - VNIC_PROBE_ENTRY_PC = 0x0C6, - VNIC_PROBE_FAILURE_PC = 0x0C7, - VNIC_PROBE_EXIT_PC = 0x0C8, - VPCI_CREATE_ENTRY_PC = 0x0C9, - VPCI_CREATE_FAILURE_PC = 0x0CA, - VPCI_CREATE_EXIT_PC = 0x0CB, - VPCI_PROBE_ENTRY_PC = 0x0CC, - VPCI_PROBE_FAILURE_PC = 0x0CD, - VPCI_PROBE_EXIT_PC = 0x0CE, - CRASH_DEV_ENTRY_PC = 0x0CF, - CRASH_DEV_EXIT_PC = 0x0D0, - CRASH_DEV_HADDR_NULL = 0x0D1, - CRASH_DEV_CONTROLVM_NULL = 0x0D2, - CRASH_DEV_RD_BUS_FAIULRE_PC = 0x0D3, - CRASH_DEV_RD_DEV_FAIULRE_PC = 0x0D4, - CRASH_DEV_BUS_NULL_FAILURE_PC = 0x0D5, - CRASH_DEV_DEV_NULL_FAILURE_PC = 0x0D6, - CRASH_DEV_CTRL_RD_FAILURE_PC = 0x0D7, - CRASH_DEV_COUNT_FAILURE_PC = 0x0D8, - SAVE_MSG_BUS_FAILURE_PC = 0x0D9, - SAVE_MSG_DEV_FAILURE_PC = 0x0DA, - CALLHOME_INIT_FAILURE_PC = 0x0DB -}; - -#ifdef __GNUC__ - -#define POSTCODE_SEVERITY_ERR DIAG_SEVERITY_ERR -#define POSTCODE_SEVERITY_WARNING DIAG_SEVERITY_WARNING -/* TODO-> Info currently doesn't show, so we set info=warning */ -#define POSTCODE_SEVERITY_INFO DIAG_SEVERITY_PRINT - -/* example call of POSTCODE_LINUX_2(VISOR_CHIPSET_PC, POSTCODE_SEVERITY_ERR); - * Please also note that the resulting postcode is in hex, so if you are - * searching for the __LINE__ number, convert it first to decimal. The line - * number combined with driver and type of call, will allow you to track down - * exactly what line an error occurred on, or where the last driver - * entered/exited from. - */ - -/* BASE FUNCTIONS */ -#define POSTCODE_LINUX_A(DRIVER_PC, EVENT_PC, pc32bit, severity) \ -do { \ - unsigned long long post_code_temp; \ - post_code_temp = (((u64)DRIVER_PC) << 56) | (((u64)EVENT_PC) << 44) | \ - ((((u64)__LINE__) & 0xFFF) << 32) | \ - (((u64)pc32bit) & 0xFFFFFFFF); \ - ISSUE_IO_VMCALL_POSTCODE_SEVERITY(post_code_temp, severity); \ -} while (0) - -#define POSTCODE_LINUX_B(DRIVER_PC, EVENT_PC, pc16bit1, pc16bit2, severity) \ -do { \ - unsigned long long post_code_temp; \ - post_code_temp = (((u64)DRIVER_PC) << 56) | (((u64)EVENT_PC) << 44) | \ - ((((u64)__LINE__) & 0xFFF) << 32) | \ - ((((u64)pc16bit1) & 0xFFFF) << 16) | \ - (((u64)pc16bit2) & 0xFFFF); \ - ISSUE_IO_VMCALL_POSTCODE_SEVERITY(post_code_temp, severity); \ -} while (0) - -/* MOST COMMON */ -#define POSTCODE_LINUX_2(EVENT_PC, severity) \ - POSTCODE_LINUX_A(CURRENT_FILE_PC, EVENT_PC, 0x0000, severity) - -#define POSTCODE_LINUX_3(EVENT_PC, pc32bit, severity) \ - POSTCODE_LINUX_A(CURRENT_FILE_PC, EVENT_PC, pc32bit, severity) - -#define POSTCODE_LINUX_4(EVENT_PC, pc16bit1, pc16bit2, severity) \ - POSTCODE_LINUX_B(CURRENT_FILE_PC, EVENT_PC, pc16bit1, \ - pc16bit2, severity) - -#endif -#endif diff --git a/drivers/staging/unisys/visorbus/guestlinuxdebug.h b/drivers/staging/unisys/visorbus/guestlinuxdebug.h new file mode 100644 index 0000000..5af3f77 --- /dev/null +++ b/drivers/staging/unisys/visorbus/guestlinuxdebug.h @@ -0,0 +1,180 @@ +/* Copyright (C) 2010 - 2013 UNISYS CORPORATION + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + */ + +#ifndef __GUESTLINUXDEBUG_H__ +#define __GUESTLINUXDEBUG_H__ + +/* + * This file contains supporting interface for "vmcallinterface.h", particularly + * regarding adding additional structure and functionality to linux + * ISSUE_IO_VMCALL_POSTCODE_SEVERITY + */ + +/******* INFO ON ISSUE_POSTCODE_LINUX() BELOW *******/ +enum driver_pc { /* POSTCODE driver identifier tuples */ + /* visorchipset driver files */ + VISOR_CHIPSET_PC = 0xA0, + VISOR_CHIPSET_PC_controlvm_c = 0xA1, + VISOR_CHIPSET_PC_controlvm_cm2 = 0xA2, + VISOR_CHIPSET_PC_controlvm_direct_c = 0xA3, + VISOR_CHIPSET_PC_file_c = 0xA4, + VISOR_CHIPSET_PC_parser_c = 0xA5, + VISOR_CHIPSET_PC_testing_c = 0xA6, + VISOR_CHIPSET_PC_visorchipset_main_c = 0xA7, + VISOR_CHIPSET_PC_visorswitchbus_c = 0xA8, + /* visorbus driver files */ + VISOR_BUS_PC = 0xB0, + VISOR_BUS_PC_businst_attr_c = 0xB1, + VISOR_BUS_PC_channel_attr_c = 0xB2, + VISOR_BUS_PC_devmajorminor_attr_c = 0xB3, + VISOR_BUS_PC_visorbus_main_c = 0xB4, + /* visorclientbus driver files */ + VISOR_CLIENT_BUS_PC = 0xC0, + VISOR_CLIENT_BUS_PC_visorclientbus_main_c = 0xC1, + /* virt hba driver files */ + VIRT_HBA_PC = 0xC2, + VIRT_HBA_PC_virthba_c = 0xC3, + /* virtpci driver files */ + VIRT_PCI_PC = 0xC4, + VIRT_PCI_PC_virtpci_c = 0xC5, + /* virtnic driver files */ + VIRT_NIC_PC = 0xC6, + VIRT_NIC_P_virtnic_c = 0xC7, + /* uislib driver files */ + UISLIB_PC = 0xD0, + UISLIB_PC_uislib_c = 0xD1, + UISLIB_PC_uisqueue_c = 0xD2, + /* 0xD3 RESERVED */ + UISLIB_PC_uisutils_c = 0xD4, +}; + +enum event_pc { /* POSTCODE event identifier tuples */ + ATTACH_PORT_ENTRY_PC = 0x001, + ATTACH_PORT_FAILURE_PC = 0x002, + ATTACH_PORT_SUCCESS_PC = 0x003, + BUS_FAILURE_PC = 0x004, + BUS_CREATE_ENTRY_PC = 0x005, + BUS_CREATE_FAILURE_PC = 0x006, + BUS_CREATE_EXIT_PC = 0x007, + BUS_CONFIGURE_ENTRY_PC = 0x008, + BUS_CONFIGURE_FAILURE_PC = 0x009, + BUS_CONFIGURE_EXIT_PC = 0x00A, + CHIPSET_INIT_ENTRY_PC = 0x00B, + CHIPSET_INIT_SUCCESS_PC = 0x00C, + CHIPSET_INIT_FAILURE_PC = 0x00D, + CHIPSET_INIT_EXIT_PC = 0x00E, + CREATE_WORKQUEUE_PC = 0x00F, + CREATE_WORKQUEUE_FAILED_PC = 0x0A0, + CONTROLVM_INIT_FAILURE_PC = 0x0A1, + DEVICE_CREATE_ENTRY_PC = 0x0A2, + DEVICE_CREATE_FAILURE_PC = 0x0A3, + DEVICE_CREATE_SUCCESS_PC = 0x0A4, + DEVICE_CREATE_EXIT_PC = 0x0A5, + DEVICE_ADD_PC = 0x0A6, + DEVICE_REGISTER_FAILURE_PC = 0x0A7, + DEVICE_CHANGESTATE_ENTRY_PC = 0x0A8, + DEVICE_CHANGESTATE_FAILURE_PC = 0x0A9, + DEVICE_CHANGESTATE_EXIT_PC = 0x0AA, + DRIVER_ENTRY_PC = 0x0AB, + DRIVER_EXIT_PC = 0x0AC, + MALLOC_FAILURE_PC = 0x0AD, + QUEUE_DELAYED_WORK_PC = 0x0AE, + /* 0x0B7 RESERVED */ + VBUS_CHANNEL_ENTRY_PC = 0x0B8, + VBUS_CHANNEL_FAILURE_PC = 0x0B9, + VBUS_CHANNEL_EXIT_PC = 0x0BA, + VHBA_CREATE_ENTRY_PC = 0x0BB, + VHBA_CREATE_FAILURE_PC = 0x0BC, + VHBA_CREATE_EXIT_PC = 0x0BD, + VHBA_CREATE_SUCCESS_PC = 0x0BE, + VHBA_COMMAND_HANDLER_PC = 0x0BF, + VHBA_PROBE_ENTRY_PC = 0x0C0, + VHBA_PROBE_FAILURE_PC = 0x0C1, + VHBA_PROBE_EXIT_PC = 0x0C2, + VNIC_CREATE_ENTRY_PC = 0x0C3, + VNIC_CREATE_FAILURE_PC = 0x0C4, + VNIC_CREATE_SUCCESS_PC = 0x0C5, + VNIC_PROBE_ENTRY_PC = 0x0C6, + VNIC_PROBE_FAILURE_PC = 0x0C7, + VNIC_PROBE_EXIT_PC = 0x0C8, + VPCI_CREATE_ENTRY_PC = 0x0C9, + VPCI_CREATE_FAILURE_PC = 0x0CA, + VPCI_CREATE_EXIT_PC = 0x0CB, + VPCI_PROBE_ENTRY_PC = 0x0CC, + VPCI_PROBE_FAILURE_PC = 0x0CD, + VPCI_PROBE_EXIT_PC = 0x0CE, + CRASH_DEV_ENTRY_PC = 0x0CF, + CRASH_DEV_EXIT_PC = 0x0D0, + CRASH_DEV_HADDR_NULL = 0x0D1, + CRASH_DEV_CONTROLVM_NULL = 0x0D2, + CRASH_DEV_RD_BUS_FAIULRE_PC = 0x0D3, + CRASH_DEV_RD_DEV_FAIULRE_PC = 0x0D4, + CRASH_DEV_BUS_NULL_FAILURE_PC = 0x0D5, + CRASH_DEV_DEV_NULL_FAILURE_PC = 0x0D6, + CRASH_DEV_CTRL_RD_FAILURE_PC = 0x0D7, + CRASH_DEV_COUNT_FAILURE_PC = 0x0D8, + SAVE_MSG_BUS_FAILURE_PC = 0x0D9, + SAVE_MSG_DEV_FAILURE_PC = 0x0DA, + CALLHOME_INIT_FAILURE_PC = 0x0DB +}; + +#ifdef __GNUC__ + +#define POSTCODE_SEVERITY_ERR DIAG_SEVERITY_ERR +#define POSTCODE_SEVERITY_WARNING DIAG_SEVERITY_WARNING +/* TODO-> Info currently doesn't show, so we set info=warning */ +#define POSTCODE_SEVERITY_INFO DIAG_SEVERITY_PRINT + +/* example call of POSTCODE_LINUX_2(VISOR_CHIPSET_PC, POSTCODE_SEVERITY_ERR); + * Please also note that the resulting postcode is in hex, so if you are + * searching for the __LINE__ number, convert it first to decimal. The line + * number combined with driver and type of call, will allow you to track down + * exactly what line an error occurred on, or where the last driver + * entered/exited from. + */ + +/* BASE FUNCTIONS */ +#define POSTCODE_LINUX_A(DRIVER_PC, EVENT_PC, pc32bit, severity) \ +do { \ + unsigned long long post_code_temp; \ + post_code_temp = (((u64)DRIVER_PC) << 56) | (((u64)EVENT_PC) << 44) | \ + ((((u64)__LINE__) & 0xFFF) << 32) | \ + (((u64)pc32bit) & 0xFFFFFFFF); \ + ISSUE_IO_VMCALL_POSTCODE_SEVERITY(post_code_temp, severity); \ +} while (0) + +#define POSTCODE_LINUX_B(DRIVER_PC, EVENT_PC, pc16bit1, pc16bit2, severity) \ +do { \ + unsigned long long post_code_temp; \ + post_code_temp = (((u64)DRIVER_PC) << 56) | (((u64)EVENT_PC) << 44) | \ + ((((u64)__LINE__) & 0xFFF) << 32) | \ + ((((u64)pc16bit1) & 0xFFFF) << 16) | \ + (((u64)pc16bit2) & 0xFFFF); \ + ISSUE_IO_VMCALL_POSTCODE_SEVERITY(post_code_temp, severity); \ +} while (0) + +/* MOST COMMON */ +#define POSTCODE_LINUX_2(EVENT_PC, severity) \ + POSTCODE_LINUX_A(CURRENT_FILE_PC, EVENT_PC, 0x0000, severity) + +#define POSTCODE_LINUX_3(EVENT_PC, pc32bit, severity) \ + POSTCODE_LINUX_A(CURRENT_FILE_PC, EVENT_PC, pc32bit, severity) + +#define POSTCODE_LINUX_4(EVENT_PC, pc16bit1, pc16bit2, severity) \ + POSTCODE_LINUX_B(CURRENT_FILE_PC, EVENT_PC, pc16bit1, \ + pc16bit2, severity) + +#endif +#endif -- cgit v0.10.2 From 7f5780a266cd0fd005242c68f8afc755ebbf9769 Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Fri, 2 Sep 2016 16:41:43 -0400 Subject: staging: unisys: remove check for GNUC The check for GNUC is redundant and is not needed for vmcallinterface.h. Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/vmcallinterface.h b/drivers/staging/unisys/visorbus/vmcallinterface.h index 0e8f146..ae18996 100644 --- a/drivers/staging/unisys/visorbus/vmcallinterface.h +++ b/drivers/staging/unisys/visorbus/vmcallinterface.h @@ -85,7 +85,6 @@ enum vmcall_monitor_interface_method_tuple { /* VMCALL identification tuples */ #define VMCALL_SUCCESS 0 #define VMCALL_SUCCESSFUL(result) (result == 0) -#ifdef __GNUC__ #define unisys_vmcall(tuple, reg_ebx, reg_ecx) \ __unisys_vmcall_gnuc(tuple, reg_ebx, reg_ecx) #define unisys_extended_vmcall(tuple, reg_ebx, reg_ecx, reg_edx) \ @@ -102,7 +101,6 @@ enum vmcall_monitor_interface_method_tuple { /* VMCALL identification tuples */ #define ISSUE_IO_VMCALL_POSTCODE_SEVERITY(postcode, severity) \ ISSUE_IO_EXTENDED_VMCALL(VMCALL_POST_CODE_LOGEVENT, severity, \ MDS_APPOS, postcode) -#endif /* Structures for IO VMCALLs */ -- cgit v0.10.2 From 4f3f0c3d7c3d0e6532e355068e0f0dc195380356 Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Fri, 2 Sep 2016 16:41:44 -0400 Subject: staging: unisys: visorbus: merge guestlinuxdebug with vmcallinterface.h Merge guestlinuxdebug into vmcallinterface.h since it is dependent on it Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/guestlinuxdebug.h b/drivers/staging/unisys/visorbus/guestlinuxdebug.h deleted file mode 100644 index 5af3f77..0000000 --- a/drivers/staging/unisys/visorbus/guestlinuxdebug.h +++ /dev/null @@ -1,180 +0,0 @@ -/* Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#ifndef __GUESTLINUXDEBUG_H__ -#define __GUESTLINUXDEBUG_H__ - -/* - * This file contains supporting interface for "vmcallinterface.h", particularly - * regarding adding additional structure and functionality to linux - * ISSUE_IO_VMCALL_POSTCODE_SEVERITY - */ - -/******* INFO ON ISSUE_POSTCODE_LINUX() BELOW *******/ -enum driver_pc { /* POSTCODE driver identifier tuples */ - /* visorchipset driver files */ - VISOR_CHIPSET_PC = 0xA0, - VISOR_CHIPSET_PC_controlvm_c = 0xA1, - VISOR_CHIPSET_PC_controlvm_cm2 = 0xA2, - VISOR_CHIPSET_PC_controlvm_direct_c = 0xA3, - VISOR_CHIPSET_PC_file_c = 0xA4, - VISOR_CHIPSET_PC_parser_c = 0xA5, - VISOR_CHIPSET_PC_testing_c = 0xA6, - VISOR_CHIPSET_PC_visorchipset_main_c = 0xA7, - VISOR_CHIPSET_PC_visorswitchbus_c = 0xA8, - /* visorbus driver files */ - VISOR_BUS_PC = 0xB0, - VISOR_BUS_PC_businst_attr_c = 0xB1, - VISOR_BUS_PC_channel_attr_c = 0xB2, - VISOR_BUS_PC_devmajorminor_attr_c = 0xB3, - VISOR_BUS_PC_visorbus_main_c = 0xB4, - /* visorclientbus driver files */ - VISOR_CLIENT_BUS_PC = 0xC0, - VISOR_CLIENT_BUS_PC_visorclientbus_main_c = 0xC1, - /* virt hba driver files */ - VIRT_HBA_PC = 0xC2, - VIRT_HBA_PC_virthba_c = 0xC3, - /* virtpci driver files */ - VIRT_PCI_PC = 0xC4, - VIRT_PCI_PC_virtpci_c = 0xC5, - /* virtnic driver files */ - VIRT_NIC_PC = 0xC6, - VIRT_NIC_P_virtnic_c = 0xC7, - /* uislib driver files */ - UISLIB_PC = 0xD0, - UISLIB_PC_uislib_c = 0xD1, - UISLIB_PC_uisqueue_c = 0xD2, - /* 0xD3 RESERVED */ - UISLIB_PC_uisutils_c = 0xD4, -}; - -enum event_pc { /* POSTCODE event identifier tuples */ - ATTACH_PORT_ENTRY_PC = 0x001, - ATTACH_PORT_FAILURE_PC = 0x002, - ATTACH_PORT_SUCCESS_PC = 0x003, - BUS_FAILURE_PC = 0x004, - BUS_CREATE_ENTRY_PC = 0x005, - BUS_CREATE_FAILURE_PC = 0x006, - BUS_CREATE_EXIT_PC = 0x007, - BUS_CONFIGURE_ENTRY_PC = 0x008, - BUS_CONFIGURE_FAILURE_PC = 0x009, - BUS_CONFIGURE_EXIT_PC = 0x00A, - CHIPSET_INIT_ENTRY_PC = 0x00B, - CHIPSET_INIT_SUCCESS_PC = 0x00C, - CHIPSET_INIT_FAILURE_PC = 0x00D, - CHIPSET_INIT_EXIT_PC = 0x00E, - CREATE_WORKQUEUE_PC = 0x00F, - CREATE_WORKQUEUE_FAILED_PC = 0x0A0, - CONTROLVM_INIT_FAILURE_PC = 0x0A1, - DEVICE_CREATE_ENTRY_PC = 0x0A2, - DEVICE_CREATE_FAILURE_PC = 0x0A3, - DEVICE_CREATE_SUCCESS_PC = 0x0A4, - DEVICE_CREATE_EXIT_PC = 0x0A5, - DEVICE_ADD_PC = 0x0A6, - DEVICE_REGISTER_FAILURE_PC = 0x0A7, - DEVICE_CHANGESTATE_ENTRY_PC = 0x0A8, - DEVICE_CHANGESTATE_FAILURE_PC = 0x0A9, - DEVICE_CHANGESTATE_EXIT_PC = 0x0AA, - DRIVER_ENTRY_PC = 0x0AB, - DRIVER_EXIT_PC = 0x0AC, - MALLOC_FAILURE_PC = 0x0AD, - QUEUE_DELAYED_WORK_PC = 0x0AE, - /* 0x0B7 RESERVED */ - VBUS_CHANNEL_ENTRY_PC = 0x0B8, - VBUS_CHANNEL_FAILURE_PC = 0x0B9, - VBUS_CHANNEL_EXIT_PC = 0x0BA, - VHBA_CREATE_ENTRY_PC = 0x0BB, - VHBA_CREATE_FAILURE_PC = 0x0BC, - VHBA_CREATE_EXIT_PC = 0x0BD, - VHBA_CREATE_SUCCESS_PC = 0x0BE, - VHBA_COMMAND_HANDLER_PC = 0x0BF, - VHBA_PROBE_ENTRY_PC = 0x0C0, - VHBA_PROBE_FAILURE_PC = 0x0C1, - VHBA_PROBE_EXIT_PC = 0x0C2, - VNIC_CREATE_ENTRY_PC = 0x0C3, - VNIC_CREATE_FAILURE_PC = 0x0C4, - VNIC_CREATE_SUCCESS_PC = 0x0C5, - VNIC_PROBE_ENTRY_PC = 0x0C6, - VNIC_PROBE_FAILURE_PC = 0x0C7, - VNIC_PROBE_EXIT_PC = 0x0C8, - VPCI_CREATE_ENTRY_PC = 0x0C9, - VPCI_CREATE_FAILURE_PC = 0x0CA, - VPCI_CREATE_EXIT_PC = 0x0CB, - VPCI_PROBE_ENTRY_PC = 0x0CC, - VPCI_PROBE_FAILURE_PC = 0x0CD, - VPCI_PROBE_EXIT_PC = 0x0CE, - CRASH_DEV_ENTRY_PC = 0x0CF, - CRASH_DEV_EXIT_PC = 0x0D0, - CRASH_DEV_HADDR_NULL = 0x0D1, - CRASH_DEV_CONTROLVM_NULL = 0x0D2, - CRASH_DEV_RD_BUS_FAIULRE_PC = 0x0D3, - CRASH_DEV_RD_DEV_FAIULRE_PC = 0x0D4, - CRASH_DEV_BUS_NULL_FAILURE_PC = 0x0D5, - CRASH_DEV_DEV_NULL_FAILURE_PC = 0x0D6, - CRASH_DEV_CTRL_RD_FAILURE_PC = 0x0D7, - CRASH_DEV_COUNT_FAILURE_PC = 0x0D8, - SAVE_MSG_BUS_FAILURE_PC = 0x0D9, - SAVE_MSG_DEV_FAILURE_PC = 0x0DA, - CALLHOME_INIT_FAILURE_PC = 0x0DB -}; - -#ifdef __GNUC__ - -#define POSTCODE_SEVERITY_ERR DIAG_SEVERITY_ERR -#define POSTCODE_SEVERITY_WARNING DIAG_SEVERITY_WARNING -/* TODO-> Info currently doesn't show, so we set info=warning */ -#define POSTCODE_SEVERITY_INFO DIAG_SEVERITY_PRINT - -/* example call of POSTCODE_LINUX_2(VISOR_CHIPSET_PC, POSTCODE_SEVERITY_ERR); - * Please also note that the resulting postcode is in hex, so if you are - * searching for the __LINE__ number, convert it first to decimal. The line - * number combined with driver and type of call, will allow you to track down - * exactly what line an error occurred on, or where the last driver - * entered/exited from. - */ - -/* BASE FUNCTIONS */ -#define POSTCODE_LINUX_A(DRIVER_PC, EVENT_PC, pc32bit, severity) \ -do { \ - unsigned long long post_code_temp; \ - post_code_temp = (((u64)DRIVER_PC) << 56) | (((u64)EVENT_PC) << 44) | \ - ((((u64)__LINE__) & 0xFFF) << 32) | \ - (((u64)pc32bit) & 0xFFFFFFFF); \ - ISSUE_IO_VMCALL_POSTCODE_SEVERITY(post_code_temp, severity); \ -} while (0) - -#define POSTCODE_LINUX_B(DRIVER_PC, EVENT_PC, pc16bit1, pc16bit2, severity) \ -do { \ - unsigned long long post_code_temp; \ - post_code_temp = (((u64)DRIVER_PC) << 56) | (((u64)EVENT_PC) << 44) | \ - ((((u64)__LINE__) & 0xFFF) << 32) | \ - ((((u64)pc16bit1) & 0xFFFF) << 16) | \ - (((u64)pc16bit2) & 0xFFFF); \ - ISSUE_IO_VMCALL_POSTCODE_SEVERITY(post_code_temp, severity); \ -} while (0) - -/* MOST COMMON */ -#define POSTCODE_LINUX_2(EVENT_PC, severity) \ - POSTCODE_LINUX_A(CURRENT_FILE_PC, EVENT_PC, 0x0000, severity) - -#define POSTCODE_LINUX_3(EVENT_PC, pc32bit, severity) \ - POSTCODE_LINUX_A(CURRENT_FILE_PC, EVENT_PC, pc32bit, severity) - -#define POSTCODE_LINUX_4(EVENT_PC, pc16bit1, pc16bit2, severity) \ - POSTCODE_LINUX_B(CURRENT_FILE_PC, EVENT_PC, pc16bit1, \ - pc16bit2, severity) - -#endif -#endif diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index b17c94c..fe5fc21 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -19,7 +19,6 @@ #include "visorbus.h" #include "visorbus_private.h" #include "version.h" -#include "guestlinuxdebug.h" #include "vmcallinterface.h" #define MYDRVNAME "visorbus" diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index a8e7708..fc40a17 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -27,7 +27,6 @@ #include "channel.h" #include "controlvmchannel.h" -#include "guestlinuxdebug.h" #include "version.h" #include "visorbus.h" #include "visorbus_private.h" diff --git a/drivers/staging/unisys/visorbus/vmcallinterface.h b/drivers/staging/unisys/visorbus/vmcallinterface.h index ae18996..86e695d 100644 --- a/drivers/staging/unisys/visorbus/vmcallinterface.h +++ b/drivers/staging/unisys/visorbus/vmcallinterface.h @@ -115,4 +115,156 @@ struct vmcall_io_controlvm_addr_params { u8 unused[4]; /* Unused Bytes in the 64-Bit Aligned Struct */ } __packed; +/******* INFO ON ISSUE_POSTCODE_LINUX() BELOW *******/ +enum driver_pc { /* POSTCODE driver identifier tuples */ + /* visorchipset driver files */ + VISOR_CHIPSET_PC = 0xA0, + VISOR_CHIPSET_PC_controlvm_c = 0xA1, + VISOR_CHIPSET_PC_controlvm_cm2 = 0xA2, + VISOR_CHIPSET_PC_controlvm_direct_c = 0xA3, + VISOR_CHIPSET_PC_file_c = 0xA4, + VISOR_CHIPSET_PC_parser_c = 0xA5, + VISOR_CHIPSET_PC_testing_c = 0xA6, + VISOR_CHIPSET_PC_visorchipset_main_c = 0xA7, + VISOR_CHIPSET_PC_visorswitchbus_c = 0xA8, + /* visorbus driver files */ + VISOR_BUS_PC = 0xB0, + VISOR_BUS_PC_businst_attr_c = 0xB1, + VISOR_BUS_PC_channel_attr_c = 0xB2, + VISOR_BUS_PC_devmajorminor_attr_c = 0xB3, + VISOR_BUS_PC_visorbus_main_c = 0xB4, + /* visorclientbus driver files */ + VISOR_CLIENT_BUS_PC = 0xC0, + VISOR_CLIENT_BUS_PC_visorclientbus_main_c = 0xC1, + /* virt hba driver files */ + VIRT_HBA_PC = 0xC2, + VIRT_HBA_PC_virthba_c = 0xC3, + /* virtpci driver files */ + VIRT_PCI_PC = 0xC4, + VIRT_PCI_PC_virtpci_c = 0xC5, + /* virtnic driver files */ + VIRT_NIC_PC = 0xC6, + VIRT_NIC_P_virtnic_c = 0xC7, + /* uislib driver files */ + UISLIB_PC = 0xD0, + UISLIB_PC_uislib_c = 0xD1, + UISLIB_PC_uisqueue_c = 0xD2, + /* 0xD3 RESERVED */ + UISLIB_PC_uisutils_c = 0xD4, +}; + +enum event_pc { /* POSTCODE event identifier tuples */ + ATTACH_PORT_ENTRY_PC = 0x001, + ATTACH_PORT_FAILURE_PC = 0x002, + ATTACH_PORT_SUCCESS_PC = 0x003, + BUS_FAILURE_PC = 0x004, + BUS_CREATE_ENTRY_PC = 0x005, + BUS_CREATE_FAILURE_PC = 0x006, + BUS_CREATE_EXIT_PC = 0x007, + BUS_CONFIGURE_ENTRY_PC = 0x008, + BUS_CONFIGURE_FAILURE_PC = 0x009, + BUS_CONFIGURE_EXIT_PC = 0x00A, + CHIPSET_INIT_ENTRY_PC = 0x00B, + CHIPSET_INIT_SUCCESS_PC = 0x00C, + CHIPSET_INIT_FAILURE_PC = 0x00D, + CHIPSET_INIT_EXIT_PC = 0x00E, + CREATE_WORKQUEUE_PC = 0x00F, + CREATE_WORKQUEUE_FAILED_PC = 0x0A0, + CONTROLVM_INIT_FAILURE_PC = 0x0A1, + DEVICE_CREATE_ENTRY_PC = 0x0A2, + DEVICE_CREATE_FAILURE_PC = 0x0A3, + DEVICE_CREATE_SUCCESS_PC = 0x0A4, + DEVICE_CREATE_EXIT_PC = 0x0A5, + DEVICE_ADD_PC = 0x0A6, + DEVICE_REGISTER_FAILURE_PC = 0x0A7, + DEVICE_CHANGESTATE_ENTRY_PC = 0x0A8, + DEVICE_CHANGESTATE_FAILURE_PC = 0x0A9, + DEVICE_CHANGESTATE_EXIT_PC = 0x0AA, + DRIVER_ENTRY_PC = 0x0AB, + DRIVER_EXIT_PC = 0x0AC, + MALLOC_FAILURE_PC = 0x0AD, + QUEUE_DELAYED_WORK_PC = 0x0AE, + /* 0x0B7 RESERVED */ + VBUS_CHANNEL_ENTRY_PC = 0x0B8, + VBUS_CHANNEL_FAILURE_PC = 0x0B9, + VBUS_CHANNEL_EXIT_PC = 0x0BA, + VHBA_CREATE_ENTRY_PC = 0x0BB, + VHBA_CREATE_FAILURE_PC = 0x0BC, + VHBA_CREATE_EXIT_PC = 0x0BD, + VHBA_CREATE_SUCCESS_PC = 0x0BE, + VHBA_COMMAND_HANDLER_PC = 0x0BF, + VHBA_PROBE_ENTRY_PC = 0x0C0, + VHBA_PROBE_FAILURE_PC = 0x0C1, + VHBA_PROBE_EXIT_PC = 0x0C2, + VNIC_CREATE_ENTRY_PC = 0x0C3, + VNIC_CREATE_FAILURE_PC = 0x0C4, + VNIC_CREATE_SUCCESS_PC = 0x0C5, + VNIC_PROBE_ENTRY_PC = 0x0C6, + VNIC_PROBE_FAILURE_PC = 0x0C7, + VNIC_PROBE_EXIT_PC = 0x0C8, + VPCI_CREATE_ENTRY_PC = 0x0C9, + VPCI_CREATE_FAILURE_PC = 0x0CA, + VPCI_CREATE_EXIT_PC = 0x0CB, + VPCI_PROBE_ENTRY_PC = 0x0CC, + VPCI_PROBE_FAILURE_PC = 0x0CD, + VPCI_PROBE_EXIT_PC = 0x0CE, + CRASH_DEV_ENTRY_PC = 0x0CF, + CRASH_DEV_EXIT_PC = 0x0D0, + CRASH_DEV_HADDR_NULL = 0x0D1, + CRASH_DEV_CONTROLVM_NULL = 0x0D2, + CRASH_DEV_RD_BUS_FAIULRE_PC = 0x0D3, + CRASH_DEV_RD_DEV_FAIULRE_PC = 0x0D4, + CRASH_DEV_BUS_NULL_FAILURE_PC = 0x0D5, + CRASH_DEV_DEV_NULL_FAILURE_PC = 0x0D6, + CRASH_DEV_CTRL_RD_FAILURE_PC = 0x0D7, + CRASH_DEV_COUNT_FAILURE_PC = 0x0D8, + SAVE_MSG_BUS_FAILURE_PC = 0x0D9, + SAVE_MSG_DEV_FAILURE_PC = 0x0DA, + CALLHOME_INIT_FAILURE_PC = 0x0DB +}; + +#define POSTCODE_SEVERITY_ERR DIAG_SEVERITY_ERR +#define POSTCODE_SEVERITY_WARNING DIAG_SEVERITY_WARNING +/* TODO-> Info currently doesn't show, so we set info=warning */ +#define POSTCODE_SEVERITY_INFO DIAG_SEVERITY_PRINT + +/* example call of POSTCODE_LINUX_2(VISOR_CHIPSET_PC, POSTCODE_SEVERITY_ERR); + * Please also note that the resulting postcode is in hex, so if you are + * searching for the __LINE__ number, convert it first to decimal. The line + * number combined with driver and type of call, will allow you to track down + * exactly what line an error occurred on, or where the last driver + * entered/exited from. + */ + +/* BASE FUNCTIONS */ +#define POSTCODE_LINUX_A(DRIVER_PC, EVENT_PC, pc32bit, severity) \ +do { \ + unsigned long long post_code_temp; \ + post_code_temp = (((u64)DRIVER_PC) << 56) | (((u64)EVENT_PC) << 44) | \ + ((((u64)__LINE__) & 0xFFF) << 32) | \ + (((u64)pc32bit) & 0xFFFFFFFF); \ + ISSUE_IO_VMCALL_POSTCODE_SEVERITY(post_code_temp, severity); \ +} while (0) + +#define POSTCODE_LINUX_B(DRIVER_PC, EVENT_PC, pc16bit1, pc16bit2, severity) \ +do { \ + unsigned long long post_code_temp; \ + post_code_temp = (((u64)DRIVER_PC) << 56) | (((u64)EVENT_PC) << 44) | \ + ((((u64)__LINE__) & 0xFFF) << 32) | \ + ((((u64)pc16bit1) & 0xFFFF) << 16) | \ + (((u64)pc16bit2) & 0xFFFF); \ + ISSUE_IO_VMCALL_POSTCODE_SEVERITY(post_code_temp, severity); \ +} while (0) + +/* MOST COMMON */ +#define POSTCODE_LINUX_2(EVENT_PC, severity) \ + POSTCODE_LINUX_A(CURRENT_FILE_PC, EVENT_PC, 0x0000, severity) + +#define POSTCODE_LINUX_3(EVENT_PC, pc32bit, severity) \ + POSTCODE_LINUX_A(CURRENT_FILE_PC, EVENT_PC, pc32bit, severity) + +#define POSTCODE_LINUX_4(EVENT_PC, pc16bit1, pc16bit2, severity) \ + POSTCODE_LINUX_B(CURRENT_FILE_PC, EVENT_PC, pc16bit1, \ + pc16bit2, severity) + #endif /* __IOMONINTF_H__ */ -- cgit v0.10.2 From f6573adedb7d8ee4be3a88fdb2b2e944695946d7 Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Fri, 2 Sep 2016 16:41:45 -0400 Subject: staging: unisys: visorbus: cleanup include listings Cleaned up include section of files so that they only include the files needed by them. If an include file includes the file already don't repeat it. Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index fc40a17..ad8a407 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -25,8 +25,6 @@ #include <linux/uuid.h> #include <linux/crash_dump.h> -#include "channel.h" -#include "controlvmchannel.h" #include "version.h" #include "visorbus.h" #include "visorbus_private.h" -- cgit v0.10.2 From 1696566f995cfd4ddf3f167b4097cdc83f1458f2 Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Sun, 11 Sep 2016 18:29:16 +0200 Subject: iio: accel: mxc6255: Fix chip-id check The initial commit adding support for the mxc6225 assumed the mxc6225 has a chip-id of 0xe5 based on testing on a single Allwinner A23 tablet with a mxc6225. Testing on a bunch of other Allwinner tablets have shown that the chip-id for the mxc6225 is not constant. A datasheet for the MXC6255 which I've found online says that bits 7 and 6 of the chip-id register are undefined (for the mxc6255), testing on 5 different tablets with a mxc6225 has found the following ids: 0x25, 0x45, 0x65, 0x85, 0xe5. So it seems that for the mxc6225 bits 7, 6 and 5 of the chip-id register are undefined. This commit adjusts the chip-id check so that the mxc6255 driver properly recognizes the mxc6225 in all these tablets. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/accel/mxc6255.c b/drivers/iio/accel/mxc6255.c index 50343a7..0abad69 100644 --- a/drivers/iio/accel/mxc6255.c +++ b/drivers/iio/accel/mxc6255.c @@ -26,7 +26,6 @@ #define MXC6255_REG_YOUT 0x01 #define MXC6255_REG_CHIP_ID 0x08 -#define MXC6225_CHIP_ID 0xe5 #define MXC6255_CHIP_ID 0x05 /* @@ -155,11 +154,7 @@ static int mxc6255_probe(struct i2c_client *client, return ret; } - switch (chip_id) { - case MXC6225_CHIP_ID: - case MXC6255_CHIP_ID: - break; - default: + if ((chip_id & 0x1f) != MXC6255_CHIP_ID) { dev_err(&client->dev, "Invalid chip id %x\n", chip_id); return -ENODEV; } -- cgit v0.10.2 From 12bc1d1e9cb18176dcd80564067114b32d189d24 Mon Sep 17 00:00:00 2001 From: Omri Arad <omriarad3@gmail.com> Date: Mon, 12 Sep 2016 21:02:25 +0300 Subject: staging: rtl8712: fix coding style error reported from checkpatch removed the following: ERROR: code indent should use tabs where possible WARNING: please, no spaces at the start of a line WARNING: Statements should start on a tabstop Signed-off-by: Omri Arad <omriarad3@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c index e205adf..475e790 100644 --- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c +++ b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c @@ -1976,9 +1976,9 @@ static int r871x_get_ap_info(struct net_device *dev, if (pdata->length >= 32) { if (copy_from_user(data, pdata->pointer, 32)) return -EINVAL; - data[32] = 0; + data[32] = 0; } else { - return -EINVAL; + return -EINVAL; } spin_lock_irqsave(&(pmlmepriv->scanned_queue.lock), irqL); phead = &queue->queue; -- cgit v0.10.2 From 4a2a867f5bada15b3f81168089258a28eb02dc04 Mon Sep 17 00:00:00 2001 From: Shaily Sangwan <shaily15297@yahoo.com> Date: Tue, 13 Sep 2016 02:54:14 +0530 Subject: staging: rtl8712: fix block comments This patch fixes the following checkpatch.pl warning: Block comments use * on subsequent lines Signed-off-by: Shaily Sangwan <shaily15297@yahoo.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8712/rtl8712_recv.h b/drivers/staging/rtl8712/rtl8712_recv.h index 96ca3e2..0b0c273 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.h +++ b/drivers/staging/rtl8712/rtl8712_recv.h @@ -116,13 +116,13 @@ struct recv_buf { }; /* - head -----> - data -----> - payload - tail -----> - end -----> - len = (unsigned int )(tail - data); -*/ + * head -----> + * data -----> + * payload + * tail -----> + * end -----> + * len = (unsigned int )(tail - data); + */ struct recv_frame_hdr { struct list_head list; _pkt *pkt; diff --git a/drivers/staging/rtl8712/rtl871x_cmd.h b/drivers/staging/rtl8712/rtl871x_cmd.h index a2cee36..3284dcf 100644 --- a/drivers/staging/rtl8712/rtl871x_cmd.h +++ b/drivers/staging/rtl8712/rtl871x_cmd.h @@ -217,15 +217,15 @@ struct SetMacAddr_param { }; /* -Caller Ad-Hoc/AP - -Command -Rsp(AID == CAMID) mode - -This is to force fw to add an sta_data entry per driver's request. - -FW will write an cam entry associated with it. - -*/ + * Caller Ad-Hoc/AP + * + * Command -Rsp(AID == CAMID) mode + * + * This is to force fw to add an sta_data entry per driver's request. + * + * FW will write an cam entry associated with it. + * + */ struct set_assocsta_parm { u8 addr[ETH_ALEN]; }; @@ -236,27 +236,27 @@ struct set_assocsta_rsp { }; /* - Caller Ad-Hoc/AP - - Command mode - - This is to force fw to del an sta_data entry per driver's request - - FW will invalidate the cam entry associated with it. - -*/ + * Caller Ad-Hoc/AP + * + * Command mode + * + * This is to force fw to del an sta_data entry per driver's request + * + * FW will invalidate the cam entry associated with it. + * + */ struct del_assocsta_parm { u8 addr[ETH_ALEN]; }; /* -Caller Mode: AP/Ad-HoC(M) - -Notes: To notify fw that given staid has changed its power state - -Command Mode - -*/ + * Caller Mode: AP/Ad-HoC(M) + * + * Notes: To notify fw that given staid has changed its power state + * + * Command Mode + * + */ struct setstapwrstate_parm { u8 staid; u8 status; @@ -264,25 +264,25 @@ struct setstapwrstate_parm { }; /* -Caller Mode: Any - -Notes: To setup the basic rate of RTL8711 - -Command Mode - -*/ + * Caller Mode: Any + * + * Notes: To setup the basic rate of RTL8711 + * + * Command Mode + * + */ struct setbasicrate_parm { u8 basicrates[NumRates]; }; /* -Caller Mode: Any - -Notes: To read the current basic rate - -Command-Rsp Mode - -*/ + * Caller Mode: Any + * + * Notes: To read the current basic rate + * + * Command-Rsp Mode + * + */ struct getbasicrate_parm { u32 rsvd; }; @@ -292,13 +292,13 @@ struct getbasicrate_rsp { }; /* -Caller Mode: Any - -Notes: To setup the data rate of RTL8711 - -Command Mode - -*/ + * Caller Mode: Any + * + * Notes: To setup the data rate of RTL8711 + * + * Command Mode + * + */ struct setdatarate_parm { u8 mac_id; u8 datarates[NumRates]; @@ -334,13 +334,13 @@ struct SetChannelPlan_param { }; /* -Caller Mode: Any - -Notes: To read the current data rate - -Command-Rsp Mode - -*/ + * Caller Mode: Any + * + * Notes: To read the current data rate + * + * Command-Rsp Mode + * + */ struct getdatarate_parm { u32 rsvd; @@ -351,36 +351,36 @@ struct getdatarate_rsp { /* -Caller Mode: Any -AP: AP can use the info for the contents of beacon frame -Infra: STA can use the info when sitesurveying -Ad-HoC(M): Like AP -Ad-HoC(C): Like STA - - -Notes: To set the phy capability of the NIC - -Command Mode - -*/ + * Caller Mode: Any + * AP: AP can use the info for the contents of beacon frame + * Infra: STA can use the info when sitesurveying + * Ad-HoC(M): Like AP + * Ad-HoC(C): Like STA + * + * + * Notes: To set the phy capability of the NIC + * + * Command Mode + * + */ /* -Caller Mode: Any - -Notes: To set the channel/modem/band -This command will be used when channel/modem/band is changed. - -Command Mode - -*/ + * Caller Mode: Any + * + * Notes: To set the channel/modem/band + * This command will be used when channel/modem/band is changed. + * + * Command Mode + * + */ /* -Caller Mode: Any - -Notes: To get the current setting of channel/modem/band - -Command-Rsp Mode - -*/ + * Caller Mode: Any + * + * Notes: To get the current setting of channel/modem/band + * + * Command-Rsp Mode + * + */ struct getphy_rsp { u8 rfchannel; u8 modem; @@ -430,58 +430,58 @@ struct getrfintfs_parm { }; /* - Notes: This command is used for H2C/C2H loopback testing - - mac[0] == 0 - ==> CMD mode, return H2C_SUCCESS. - The following condition must be ture under CMD mode - mac[1] == mac[4], mac[2] == mac[3], mac[0]=mac[5]= 0; - s0 == 0x1234, s1 == 0xabcd, w0 == 0x78563412, w1 == 0x5aa5def7; - s2 == (b1 << 8 | b0); - - mac[0] == 1 - ==> CMD_RSP mode, return H2C_SUCCESS_RSP - - The rsp layout shall be: - rsp: parm: - mac[0] = mac[5]; - mac[1] = mac[4]; - mac[2] = mac[3]; - mac[3] = mac[2]; - mac[4] = mac[1]; - mac[5] = mac[0]; - s0 = s1; - s1 = swap16(s0); - w0 = swap32(w1); - b0 = b1 - s2 = s0 + s1 - b1 = b0 - w1 = w0 - - mac[0] == 2 - ==> CMD_EVENT mode, return H2C_SUCCESS - The event layout shall be: - event: parm: - mac[0] = mac[5]; - mac[1] = mac[4]; - mac[2] = event's sequence number, starting from 1 to parm's marc[3] - mac[3] = mac[2]; - mac[4] = mac[1]; - mac[5] = mac[0]; - s0 = swap16(s0) - event.mac[2]; - s1 = s1 + event.mac[2]; - w0 = swap32(w0); - b0 = b1 - s2 = s0 + event.mac[2] - b1 = b0 - w1 = swap32(w1) - event.mac[2]; - - parm->mac[3] is the total event counts that host requested. - - - event will be the same with the cmd's param. - -*/ + * Notes: This command is used for H2C/C2H loopback testing + * + * mac[0] == 0 + * ==> CMD mode, return H2C_SUCCESS. + * The following condition must be ture under CMD mode + * mac[1] == mac[4], mac[2] == mac[3], mac[0]=mac[5]= 0; + * s0 == 0x1234, s1 == 0xabcd, w0 == 0x78563412, w1 == 0x5aa5def7; + * s2 == (b1 << 8 | b0); + * + * mac[0] == 1 + * ==> CMD_RSP mode, return H2C_SUCCESS_RSP + * + * The rsp layout shall be: + * rsp: parm: + * mac[0] = mac[5]; + * mac[1] = mac[4]; + * mac[2] = mac[3]; + * mac[3] = mac[2]; + * mac[4] = mac[1]; + * mac[5] = mac[0]; + * s0 = s1; + * s1 = swap16(s0); + * w0 = swap32(w1); + * b0 = b1 + * s2 = s0 + s1 + * b1 = b0 + * w1 = w0 + * + * mac[0] == 2 + * ==> CMD_EVENT mode, return H2C_SUCCESS + * The event layout shall be: + * event: parm: + * mac[0] = mac[5]; + * mac[1] = mac[4]; + * mac[2] = event's sequence number, starting from 1 to parm's marc[3] + * mac[3] = mac[2]; + * mac[4] = mac[1]; + * mac[5] = mac[0]; + * s0 = swap16(s0) - event.mac[2]; + * s1 = s1 + event.mac[2]; + * w0 = swap32(w0); + * b0 = b1 + * s2 = s0 + event.mac[2] + * b1 = b0 + * w1 = swap32(w1) - event.mac[2]; + * + * parm->mac[3] is the total event counts that host requested. + * + * + * event will be the same with the cmd's param. + * + */ /* CMD param Formart for DRV INTERNAL CMD HDL*/ struct drvint_cmd_parm { -- cgit v0.10.2 From 601e59fa5149f428737c569b7f8a01c6ccb3e223 Mon Sep 17 00:00:00 2001 From: sayli karnik <karniksayli1995@gmail.com> Date: Mon, 12 Sep 2016 17:13:09 +0530 Subject: staging: gdm724x: Add spaces around the '*' operator This patch fixes the checkpatch.pl warning: Spaces required around the '*' operator. Signed-off-by: sayli karnik <karniksayli1995@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/gdm724x/gdm_mux.h b/drivers/staging/gdm724x/gdm_mux.h index 3d50383..0871b8f 100644 --- a/drivers/staging/gdm724x/gdm_mux.h +++ b/drivers/staging/gdm724x/gdm_mux.h @@ -27,8 +27,8 @@ #define START_FLAG 0xA512485A #define MUX_HEADER_SIZE 14 -#define MUX_TX_MAX_SIZE (1024*10) -#define MUX_RX_MAX_SIZE (1024*30) +#define MUX_TX_MAX_SIZE (1024 * 10) +#define MUX_RX_MAX_SIZE (1024 * 30) #define AT_PKT_TYPE 0xF011 #define DM_PKT_TYPE 0xF010 diff --git a/drivers/staging/gdm724x/gdm_usb.h b/drivers/staging/gdm724x/gdm_usb.h index e6486e7..ffb3d99 100644 --- a/drivers/staging/gdm724x/gdm_usb.h +++ b/drivers/staging/gdm724x/gdm_usb.h @@ -26,10 +26,10 @@ #define PM_SUSPEND 1 #define AUTO_SUSPEND_TIMER 5000 /* ms */ -#define RX_BUF_SIZE (1024*32) -#define TX_BUF_SIZE (1024*32) +#define RX_BUF_SIZE (1024 * 32) +#define TX_BUF_SIZE (1024 * 32) #define SDU_BUF_SIZE 2048 -#define MAX_SDU_SIZE (1024*30) +#define MAX_SDU_SIZE (1024 * 30) #define MAX_PACKET_IN_MULTI_SDU 256 #define VID_GCT 0x1076 -- cgit v0.10.2 From 6e30293976983daf09eea8e882d48a09c80d5987 Mon Sep 17 00:00:00 2001 From: Matias Mucciolo <mmucciolo@suteba.org.ar> Date: Mon, 12 Sep 2016 10:18:59 -0300 Subject: staging: comedi: comedi_fops: coding style fixes - Fixed coding style in comedi_fops.c Symbolic to octal permission. Signed-off-by: Matias Mucciolo <mmucciolo@suteba.org.ar> Reviewed-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 1999eed..bf922ea 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -81,20 +81,20 @@ struct comedi_file { (COMEDI_NUM_MINORS - COMEDI_NUM_BOARD_MINORS) static int comedi_num_legacy_minors; -module_param(comedi_num_legacy_minors, int, S_IRUGO); +module_param(comedi_num_legacy_minors, int, 0444); MODULE_PARM_DESC(comedi_num_legacy_minors, "number of comedi minor devices to reserve for non-auto-configured devices (default 0)" ); unsigned int comedi_default_buf_size_kb = CONFIG_COMEDI_DEFAULT_BUF_SIZE_KB; -module_param(comedi_default_buf_size_kb, uint, S_IRUGO | S_IWUSR); +module_param(comedi_default_buf_size_kb, uint, 0644); MODULE_PARM_DESC(comedi_default_buf_size_kb, "default asynchronous buffer size in KiB (default " __MODULE_STRING(CONFIG_COMEDI_DEFAULT_BUF_SIZE_KB) ")"); unsigned int comedi_default_buf_maxsize_kb = CONFIG_COMEDI_DEFAULT_BUF_MAXSIZE_KB; -module_param(comedi_default_buf_maxsize_kb, uint, S_IRUGO | S_IWUSR); +module_param(comedi_default_buf_maxsize_kb, uint, 0644); MODULE_PARM_DESC(comedi_default_buf_maxsize_kb, "default maximum size of asynchronous buffer in KiB (default " __MODULE_STRING(CONFIG_COMEDI_DEFAULT_BUF_MAXSIZE_KB) ")"); -- cgit v0.10.2 From 25b80dbe3fa6d76d8f19af0623d1fd8ed0dd671e Mon Sep 17 00:00:00 2001 From: Bhumika Goyal <bhumirks@gmail.com> Date: Mon, 12 Sep 2016 23:02:47 +0530 Subject: Staging: comedi: drivers: Delete NULL check before pci_dev_put The function pci_dev_put checks whether its argument is NULL and returns immediately. Therefore, NULL test before the call if not needed. Found using coccinelle: @@ expression x; @@ - if(x) - pci_dev_put(x); + pci_dev_put(x); Signed-off-by: Bhumika Goyal <bhumirks@gmail.com> Reviewed-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c index be70bd3..86450c0 100644 --- a/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/drivers/staging/comedi/drivers/adl_pci9118.c @@ -1693,8 +1693,7 @@ static void pci9118_detach(struct comedi_device *dev) pci9118_reset(dev); comedi_pci_detach(dev); pci9118_free_dma(dev); - if (pcidev) - pci_dev_put(pcidev); + pci_dev_put(pcidev); } static struct comedi_driver adl_pci9118_driver = { -- cgit v0.10.2 From bc5f96a15658f390aba8688408526542c9329d7e Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Mon, 12 Sep 2016 16:26:13 +0200 Subject: staging: most: core: show all linked channels This patch is needed to have all linked channels being reported by the show() function of the attribute file add_link. Currently user space can only read back the latest link that has been established to a certain channel. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index db0606ca..bd555ec 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -848,7 +848,23 @@ static ssize_t show_add_link(struct most_aim_obj *aim_obj, struct most_aim_attribute *attr, char *buf) { - return snprintf(buf, PAGE_SIZE, "%s\n", aim_obj->add_link); + struct most_c_obj *c; + struct most_inst_obj *i; + int offs = 0; + + list_for_each_entry(i, &instance_list, list) { + list_for_each_entry(c, &i->channel_list, list) { + if (c->aim0.ptr == aim_obj->driver || + c->aim1.ptr == aim_obj->driver) { + offs += snprintf(buf + offs, PAGE_SIZE - offs, + "%s:%s\n", + kobject_name(&i->kobj), + kobject_name(&c->kobj)); + } + } + } + + return offs; } /** -- cgit v0.10.2 From 602facfd96397298461cd71f6a6f9e17b82f9788 Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov <andrey.shvetsov@k2l.de> Date: Mon, 12 Sep 2016 16:26:14 +0200 Subject: staging: most: core: constify structure member This patch adds the const qualifier to the declaration of the member name_suffix of structure most_channel_capability. It is needed since it points to string literals. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/mostcore/mostcore.h b/drivers/staging/most/mostcore/mostcore.h index 60e018e..e768cb8 100644 --- a/drivers/staging/most/mostcore/mostcore.h +++ b/drivers/staging/most/mostcore/mostcore.h @@ -112,7 +112,7 @@ struct most_channel_capability { u16 buffer_size_packet; u16 num_buffers_streaming; u16 buffer_size_streaming; - char *name_suffix; + const char *name_suffix; }; /** -- cgit v0.10.2 From c371ffa79c4ca29b8cd7da4d30157179162130c8 Mon Sep 17 00:00:00 2001 From: Gargi Sharma <gs051095@gmail.com> Date: Tue, 13 Sep 2016 00:42:07 +0530 Subject: staging: slicoss: add new line after struct declaration checkpatch generates a warning for no blank line after struct declaration. Inserted a new line. Signed-off-by: Gargi Sharma <gs051095@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/slicoss/slic.h b/drivers/staging/slicoss/slic.h index fe1d2ce..6d28539 100644 --- a/drivers/staging/slicoss/slic.h +++ b/drivers/staging/slicoss/slic.h @@ -92,6 +92,7 @@ struct slic_rcvbuf_info { u32 lasttime; u32 lastid; }; + /* * SLIC Handle structure. Used to restrict handle values to * 32 bits by using an index rather than an address. -- cgit v0.10.2 From b8a7b474672321c7f0550620b32cd676501c3506 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal <bhumirks@gmail.com> Date: Tue, 13 Sep 2016 00:38:19 +0530 Subject: Staging: vt6655: Remove unused function vnt_key_init_table The function vnt_key_init_table is not used anywhere in the kernel. Therefore, remove the function definition and prototype. Grepped to find occurences. Signed-off-by: Bhumika Goyal <bhumirks@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/vt6655/key.c b/drivers/staging/vt6655/key.c index ffcaf25..e161d5d 100644 --- a/drivers/staging/vt6655/key.c +++ b/drivers/staging/vt6655/key.c @@ -31,16 +31,6 @@ #include "key.h" #include "mac.h" -int vnt_key_init_table(struct vnt_private *priv) -{ - u32 i; - - for (i = 0; i < MAX_KEY_TABLE; i++) - MACvDisableKeyEntry(priv, i); - - return 0; -} - static int vnt_set_keymode(struct ieee80211_hw *hw, u8 *mac_addr, struct ieee80211_key_conf *key, u32 key_type, u32 mode, bool onfly_latch) diff --git a/drivers/staging/vt6655/key.h b/drivers/staging/vt6655/key.h index 261f818..d7271974 100644 --- a/drivers/staging/vt6655/key.h +++ b/drivers/staging/vt6655/key.h @@ -61,8 +61,6 @@ struct vnt_private; -int vnt_key_init_table(struct vnt_private *); - int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta, struct ieee80211_vif *vif, struct ieee80211_key_conf *key); -- cgit v0.10.2 From 8b70d6961f03483a7c9db9aecba2c3b3b467cce2 Mon Sep 17 00:00:00 2001 From: Mike Kofron <mpkofron@gmail.com> Date: Mon, 12 Sep 2016 14:23:31 -0400 Subject: staging: netlogic: Make net_device_ops const This patch fixes the checkpatch.pl warning: WARNING: struct net_device_ops should normally be const Signed-off-by: Mike Kofron <mpkofron@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/netlogic/xlr_net.c b/drivers/staging/netlogic/xlr_net.c index 595ac1b..7db88aa 100644 --- a/drivers/staging/netlogic/xlr_net.c +++ b/drivers/staging/netlogic/xlr_net.c @@ -413,7 +413,7 @@ static struct rtnl_link_stats64 *xlr_get_stats64(struct net_device *ndev, return stats; } -static struct net_device_ops xlr_netdev_ops = { +static const struct net_device_ops xlr_netdev_ops = { .ndo_open = xlr_net_open, .ndo_stop = xlr_net_stop, .ndo_start_xmit = xlr_net_start_xmit, -- cgit v0.10.2 From c7e65f4d2f7968de8605ef1b83ac1019e8e51d22 Mon Sep 17 00:00:00 2001 From: sayli karnik <karniksayli1995@gmail.com> Date: Tue, 13 Sep 2016 02:47:28 +0530 Subject: staging: ks7010: Remove the explicit NULL comparison The patch removes the explicit null comparisons entirely for the ks7010 driver. This was detected by checkpatch.pl Signed-off-by: sayli karnik <karniksayli1995@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c index 632253c..d5299f0 100644 --- a/drivers/staging/ks7010/ks7010_sdio.c +++ b/drivers/staging/ks7010/ks7010_sdio.c @@ -266,7 +266,7 @@ static int enqueue_txdev(struct ks_wlan_private *priv, unsigned char *p, if (priv->dev_state < DEVICE_STATE_BOOT) { kfree(p); - if (complete_handler != NULL) + if (complete_handler) (*complete_handler) (arg1, arg2); return 1; } @@ -275,7 +275,7 @@ static int enqueue_txdev(struct ks_wlan_private *priv, unsigned char *p, /* in case of buffer overflow */ DPRINTK(1, "tx buffer overflow\n"); kfree(p); - if (complete_handler != NULL) + if (complete_handler) (*complete_handler) (arg1, arg2); return 1; } @@ -346,7 +346,7 @@ static void tx_device_task(void *dev) } kfree(sp->sendp); /* allocated memory free */ - if (sp->complete_handler != NULL) /* TX Complete */ + if (sp->complete_handler) /* TX Complete */ (*sp->complete_handler) (sp->arg1, sp->arg2); inc_txqhead(priv); @@ -687,7 +687,7 @@ static void trx_device_exit(struct ks_wlan_private *priv) while (cnt_txqbody(priv) > 0) { sp = &priv->tx_dev.tx_dev_buff[priv->tx_dev.qhead]; kfree(sp->sendp); /* allocated memory free */ - if (sp->complete_handler != NULL) /* TX Complete */ + if (sp->complete_handler) /* TX Complete */ (*sp->complete_handler) (sp->arg1, sp->arg2); inc_txqhead(priv); } @@ -1010,7 +1010,7 @@ static int ks7010_sdio_probe(struct sdio_func *func, /* private memory allocate */ netdev = alloc_etherdev(sizeof(*priv)); - if (netdev == NULL) { + if (!netdev) { printk(KERN_ERR "ks7010 : Unable to alloc new net device\n"); goto error_release_irq; } @@ -1126,7 +1126,7 @@ static void ks7010_sdio_remove(struct sdio_func *func) card = sdio_get_drvdata(func); - if (card == NULL) + if (!card) return; DPRINTK(1, "priv = card->priv\n"); @@ -1149,7 +1149,7 @@ static void ks7010_sdio_remove(struct sdio_func *func) struct hostif_stop_request_t *pp; pp = (struct hostif_stop_request_t *) kzalloc(hif_align_size(sizeof(*pp)), GFP_KERNEL); - if (pp == NULL) { + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; /* to do goto ni suru */ } diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c index e09df360..8e33a43 100644 --- a/drivers/staging/ks7010/ks_hostif.c +++ b/drivers/staging/ks7010/ks_hostif.c @@ -1178,7 +1178,7 @@ int hostif_data_request(struct ks_wlan_private *priv, struct sk_buff *packet) kmalloc(hif_align_size(sizeof(*pp) + 6 + packet_len + 8), KS_WLAN_MEM_FLAG); - if (pp == NULL) { + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); dev_kfree_skb(packet); return -2; @@ -1319,7 +1319,7 @@ void hostif_mib_get_request(struct ks_wlan_private *priv, /* make primitive */ pp = (struct hostif_mib_get_request_t *) kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); - if (pp == NULL) { + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; } @@ -1350,7 +1350,7 @@ void hostif_mib_set_request(struct ks_wlan_private *priv, /* make primitive */ pp = (struct hostif_mib_set_request_t *) kmalloc(hif_align_size(sizeof(*pp) + size), KS_WLAN_MEM_FLAG); - if (pp == NULL) { + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; } @@ -1380,7 +1380,7 @@ void hostif_start_request(struct ks_wlan_private *priv, unsigned char mode) /* make primitive */ pp = (struct hostif_start_request_t *) kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); - if (pp == NULL) { + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; } @@ -1408,7 +1408,7 @@ void hostif_ps_adhoc_set_request(struct ks_wlan_private *priv) /* make primitive */ pp = (struct hostif_ps_adhoc_set_request_t *) kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); - if (pp == NULL) { + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; } @@ -1452,7 +1452,7 @@ void hostif_infrastructure_set_request(struct ks_wlan_private *priv) /* make primitive */ pp = (struct hostif_infrastructure_set_request_t *) kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); - if (pp == NULL) { + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; } @@ -1519,7 +1519,7 @@ static void hostif_infrastructure_set2_request(struct ks_wlan_private *priv) /* make primitive */ pp = (struct hostif_infrastructure_set2_request_t *) kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); - if (pp == NULL) { + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; } @@ -1589,7 +1589,7 @@ void hostif_adhoc_set_request(struct ks_wlan_private *priv) /* make primitive */ pp = (struct hostif_adhoc_set_request_t *) kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); - if (pp == NULL) { + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; } @@ -1635,7 +1635,7 @@ void hostif_adhoc_set2_request(struct ks_wlan_private *priv) /* make primitive */ pp = (struct hostif_adhoc_set2_request_t *) kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); - if (pp == NULL) { + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; } @@ -1683,7 +1683,7 @@ void hostif_stop_request(struct ks_wlan_private *priv) /* make primitive */ pp = (struct hostif_stop_request_t *) kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); - if (pp == NULL) { + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; } @@ -1706,7 +1706,7 @@ void hostif_phy_information_request(struct ks_wlan_private *priv) /* make primitive */ pp = (struct hostif_phy_information_request_t *) kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); - if (pp == NULL) { + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; } @@ -1738,7 +1738,7 @@ void hostif_power_mngmt_request(struct ks_wlan_private *priv, /* make primitive */ pp = (struct hostif_power_mngmt_request_t *) kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); - if (pp == NULL) { + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; } @@ -1765,7 +1765,7 @@ void hostif_sleep_request(struct ks_wlan_private *priv, unsigned long mode) /* make primitive */ pp = (struct hostif_sleep_request_t *) kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); - if (pp == NULL) { + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; } @@ -1799,7 +1799,7 @@ void hostif_bss_scan_request(struct ks_wlan_private *priv, /* make primitive */ pp = (struct hostif_bss_scan_request_t *) kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); - if (pp == NULL) { + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; } @@ -1856,7 +1856,7 @@ void hostif_mic_failure_request(struct ks_wlan_private *priv, /* make primitive */ pp = (struct hostif_mic_failure_request_t *) kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); - if (pp == NULL) { + if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; } diff --git a/drivers/staging/ks7010/ks_wlan_net.c b/drivers/staging/ks7010/ks_wlan_net.c index d69b4c9..a35325e 100644 --- a/drivers/staging/ks7010/ks_wlan_net.c +++ b/drivers/staging/ks7010/ks_wlan_net.c @@ -3366,7 +3366,7 @@ int ks_wlan_start_xmit(struct sk_buff *skb, struct net_device *dev) DPRINTK(3, "in_interrupt()=%ld\n", in_interrupt()); - if (skb == NULL) { + if (!skb) { printk(KERN_ERR "ks_wlan: skb == NULL!!!\n"); return 0; } -- cgit v0.10.2 From b9ac4b65b5c0b16a34c12e3f0a3edf1452d4c34a Mon Sep 17 00:00:00 2001 From: sayli karnik <karniksayli1995@gmail.com> Date: Mon, 12 Sep 2016 20:54:07 +0530 Subject: staging: gs_fpga_boot: Remove multiple blank lines This patch fixes the following checkpatch warning for the gs_fpgaboot driver: CHECK: Please don't use multiple blank lines. Signed-off-by: sayli karnik <karniksayli1995@gmail.com> Acked-by: Julia Lawall <julia.lawall@lip6.fr> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/gs_fpgaboot/io.h b/drivers/staging/gs_fpgaboot/io.h index 7b46ac2..5e839b1 100644 --- a/drivers/staging/gs_fpgaboot/io.h +++ b/drivers/staging/gs_fpgaboot/io.h @@ -66,10 +66,8 @@ enum wbus { bus_2byte = 2, }; - #define MAX_WAIT_DONE 10000 - struct gpiobus { int ngpio; void __iomem *r[4]; -- cgit v0.10.2 From 65f5c3ea622dfca230e96e5098603f1df9e0a902 Mon Sep 17 00:00:00 2001 From: Ryan Swan <ryan@ryanswan.com> Date: Mon, 12 Sep 2016 09:58:20 -0400 Subject: staging: vme/devices: vme_user.c: fix: converted decimal permissions to octal Ran checkpatch.pl -f vme_user.c Fixed: ERROR: Use 4 digit octal (0777) not decimal permissions Signed-off-by: Ryan Swan <ryan@ryanswan.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/vme/devices/vme_user.c b/drivers/staging/vme/devices/vme_user.c index b95883b..5dd430f 100644 --- a/drivers/staging/vme/devices/vme_user.c +++ b/drivers/staging/vme/devices/vme_user.c @@ -773,7 +773,7 @@ static void __exit vme_user_exit(void) } MODULE_PARM_DESC(bus, "Enumeration of VMEbus to which the driver is connected"); -module_param_array(bus, int, &bus_num, 0); +module_param_array(bus, int, &bus_num, 0000); MODULE_DESCRIPTION("VME User Space Access Driver"); MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com"); -- cgit v0.10.2 From 1d191e1057aec4f9f635556d49f4f0ef90b704d4 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal <bhumirks@gmail.com> Date: Tue, 13 Sep 2016 17:41:26 +0530 Subject: Staging: wilc1000: Remove struct typedef Remove typedef from structure tstrRSSI as using typedef for structures is not preferred. Found using coccinelle: @r1@ type T; @@ typedef struct { ... } T; @script:python c1@ T2; T << r1.T; @@ if T[-2:] =="_t": coccinelle.T2 = T[:-2]; print T else: coccinelle.T2=T; @r2@ type r1.T; identifier c1.T2; @@ -typedef struct + T2 { ... } -T ; @r3@ type r1.T; identifier c1.T2; @@ - T + struct T2 Signed-off-by: Bhumika Goyal <bhumirks@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 076e06a..cff1698 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -70,11 +70,11 @@ enum connect_status { CONNECT_STS_FORCE_16_BIT = 0xFFFF }; -typedef struct { +struct tstrRSSI { u8 u8Full; u8 u8Index; s8 as8RSSI[NUM_RSSI]; -} tstrRSSI; +}; struct network_info { s8 rssi; @@ -93,7 +93,7 @@ struct network_info { u8 *ies; u16 ies_len; void *join_params; - tstrRSSI str_rssi; + struct tstrRSSI str_rssi; u64 tsf_hi; }; -- cgit v0.10.2 From d2f3e1058c7ff9dc18d14548f6263dcf13af67f7 Mon Sep 17 00:00:00 2001 From: Simon Chopin <chopin.simon@gmail.com> Date: Sat, 10 Sep 2016 07:11:52 +0200 Subject: staging: fwserial: fix checkpatch permission warnings Fix the following warnings: Symbolic permissions are not preferred. Consider using octal permissions. Signed-off-by: Simon Chopin <chopin.simon@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c index c241c0a..49c718b 100644 --- a/drivers/staging/fwserial/fwserial.c +++ b/drivers/staging/fwserial/fwserial.c @@ -39,9 +39,9 @@ static int num_ttys = 4; /* # of std ttys to create per fw_card */ static bool auto_connect = true; /* try to VIRT_CABLE to every peer */ static bool create_loop_dev = true; /* create a loopback device for each card */ -module_param_named(ttys, num_ttys, int, S_IRUGO | S_IWUSR); -module_param_named(auto, auto_connect, bool, S_IRUGO | S_IWUSR); -module_param_named(loop, create_loop_dev, bool, S_IRUGO | S_IWUSR); +module_param_named(ttys, num_ttys, int, 0644); +module_param_named(auto, auto_connect, bool, 0644); +module_param_named(loop, create_loop_dev, bool, 0644); /* * Threshold below which the tty is woken for writing -- cgit v0.10.2 From 8c243d21d6ac980bdb38e11db9ffa3a44b1dc84c Mon Sep 17 00:00:00 2001 From: Laura Abbott <labbott@redhat.com> Date: Wed, 14 Sep 2016 08:33:58 -0700 Subject: staging: android: ion: Make ION_OF depend on OF_ADDRESS The Ion platform code uses of_platform_device_create which has dependencies on OF_ADDRESS. Depending on OF is not sufficient Building sparc64:allmodconfig ... failed -------------- Error log: ... drivers/built-in.o: In function `ion_parse_dt': (.text+0x11aa2c): undefined reference to `of_platform_device_create' Add a dependency on OF_ADDRESS Reported-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Laura Abbott <labbott@redhat.com> Reviewed-by: Sumit Semwal <sumit.semwal@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig index 8a54ddc..9410554 100644 --- a/drivers/staging/android/ion/Kconfig +++ b/drivers/staging/android/ion/Kconfig @@ -43,7 +43,7 @@ source "drivers/staging/android/ion/hisilicon/Kconfig" config ION_OF bool "Devicetree support for Ion" - depends on ION && OF + depends on ION && OF_ADDRESS help Provides base support for defining Ion heaps in devicetree and setting them up. Also includes functions for platforms -- cgit v0.10.2 From 55f142ca5f2d0fbb1e3c438f4a5aa86b339437d0 Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov <andrey.shvetsov@k2l.de> Date: Thu, 15 Sep 2016 16:19:03 +0200 Subject: staging: most: hdm-dim2: fix channel configuration The DIM2 HDM checks the parameters passed to the function configure_channel() and adapts the buffer sizes of the configuration according to the hardware limitation. This patch is needed to init the HAL layer with the correct values. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c index 87039d9..dc71dab 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hdm.c +++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c @@ -1,7 +1,7 @@ /* * dim2_hdm.c - MediaLB DIM2 Hardware Dependent Module * - * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG + * Copyright (C) 2015-2016, Microchip Technology Germany II GmbH & Co. KG * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -557,7 +557,7 @@ static int configure_channel(struct most_interface *most_iface, int ch_idx, hdm_ch->name, buf_size, new_size); spin_lock_irqsave(&dim_lock, flags); hal_ret = dim_init_control(&hdm_ch->ch, is_tx, ch_addr, - buf_size); + new_size); break; case MOST_CH_ASYNC: new_size = dim_norm_ctrl_async_buffer_size(buf_size); @@ -570,7 +570,7 @@ static int configure_channel(struct most_interface *most_iface, int ch_idx, pr_warn("%s: fixed buffer size (%d -> %d)\n", hdm_ch->name, buf_size, new_size); spin_lock_irqsave(&dim_lock, flags); - hal_ret = dim_init_async(&hdm_ch->ch, is_tx, ch_addr, buf_size); + hal_ret = dim_init_async(&hdm_ch->ch, is_tx, ch_addr, new_size); break; case MOST_CH_ISOC_AVP: new_size = dim_norm_isoc_buffer_size(buf_size, sub_size); -- cgit v0.10.2 From 424a679997e1df1b56cf4075c41559c4508a0565 Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov <andrey.shvetsov@k2l.de> Date: Thu, 15 Sep 2016 16:19:04 +0200 Subject: staging: most: hdm-dim2: remove macro ENABLE_HDM_TEST This patch removes the macro ENABLE_HDM_TEST, which was needed while doing DIM2-HAL simulations. But these are not conducted anymore. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c index dc71dab..8bef73c 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hdm.c +++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c @@ -55,17 +55,6 @@ static u8 fcnt = 4; /* (1 << fcnt) frames per subbuffer */ module_param(fcnt, byte, 0); MODULE_PARM_DESC(fcnt, "Num of frames per sub-buffer for sync channels as a power of 2"); -/* - * ############################################################################# - * - * The define below activates an utility function used by HAL-simu - * for calling DIM interrupt handler. - * It is used only for TEST PURPOSE and shall be commented before release. - * - * ############################################################################# - */ -/* #define ENABLE_HDM_TEST */ - static DEFINE_SPINLOCK(dim_lock); static void dim2_tasklet_fn(unsigned long data); @@ -129,10 +118,6 @@ struct dim2_hdm { (((p)[1] == 0x18) && ((p)[2] == 0x05) && ((p)[3] == 0x0C) && \ ((p)[13] == 0x3C) && ((p)[14] == 0x00) && ((p)[15] == 0x0A)) -#if defined(ENABLE_HDM_TEST) -static struct dim2_hdm *test_dev; -#endif - bool dim2_sysfs_get_state_cb(void) { bool state; @@ -467,27 +452,11 @@ static irqreturn_t dim2_ahb_isr(int irq, void *_dev) dim_service_irq(get_active_channels(dev, buffer)); spin_unlock_irqrestore(&dim_lock, flags); -#if !defined(ENABLE_HDM_TEST) dim2_tasklet.data = (unsigned long)dev; tasklet_schedule(&dim2_tasklet); -#else - dim2_tasklet_fn((unsigned long)dev); -#endif return IRQ_HANDLED; } -#if defined(ENABLE_HDM_TEST) - -/* - * Utility function used by HAL-simu for calling DIM interrupt handler. - * It is used only for TEST PURPOSE. - */ -void raise_dim_interrupt(void) -{ - (void)dim2_ahb_isr(0, test_dev); -} -#endif - /** * complete_all_mbos - complete MBO's in a list * @head: list head @@ -757,9 +726,6 @@ static int dim2_probe(struct platform_device *pdev) dev->atx_idx = -1; platform_set_drvdata(pdev, dev); -#if defined(ENABLE_HDM_TEST) - test_dev = dev; -#else res = platform_get_resource(pdev, IORESOURCE_MEM, 0); dev->io_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(dev->io_base)) @@ -779,7 +745,6 @@ static int dim2_probe(struct platform_device *pdev) dev->irq_ahb0, ret); return ret; } -#endif init_waitqueue_head(&dev->netinfo_waitq); dev->deliver_netinfo = 0; dev->netinfo_task = kthread_run(&deliver_netinfo_thread, (void *)dev, -- cgit v0.10.2 From 9b762fdfe26e798897f2a84a426df0fdee548dae Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov <andrey.shvetsov@k2l.de> Date: Thu, 15 Sep 2016 16:19:05 +0200 Subject: staging: most: hdm-dim2: relocate variable declarations This patch eliminates nested variable declarations by putting them at the beginning of the function in order to flatten the code. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.c b/drivers/staging/most/hdm-dim2/dim2_hal.c index 20b6970..0c58ab8 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hal.c +++ b/drivers/staging/most/hdm-dim2/dim2_hal.c @@ -2,7 +2,7 @@ * dim2_hal.c - DIM2 HAL implementation * (MediaLB, Device Interface Macro IP, OS62420) * - * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG + * Copyright (C) 2015-2016, Microchip Technology Germany II GmbH & Co. KG * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -518,20 +518,17 @@ static inline bool service_channel(u8 ch_addr, u8 idx) { u8 const shift = idx * 16; u32 const adt1 = dim2_read_ctr(ADT + ch_addr, 1); + u32 mask[4] = { 0, 0, 0, 0 }; + u32 adt_w[4] = { 0, 0, 0, 0 }; if (((adt1 >> (ADT1_DNE_BIT + shift)) & 1) == 0) return false; - { - u32 mask[4] = { 0, 0, 0, 0 }; - u32 adt_w[4] = { 0, 0, 0, 0 }; - - mask[1] = - bit_mask(ADT1_DNE_BIT + shift) | - bit_mask(ADT1_ERR_BIT + shift) | - bit_mask(ADT1_RDY_BIT + shift); - dim2_write_ctr_mask(ADT + ch_addr, mask, adt_w); - } + mask[1] = + bit_mask(ADT1_DNE_BIT + shift) | + bit_mask(ADT1_ERR_BIT + shift) | + bit_mask(ADT1_RDY_BIT + shift); + dim2_write_ctr_mask(ADT + ch_addr, mask, adt_w); /* clear channel status bit */ dimcb_io_write(&g.dim2->ACSR0, bit_mask(ch_addr)); -- cgit v0.10.2 From 6631c5c9b0c3698f3977caf5694e8ece6a36f48b Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov <andrey.shvetsov@k2l.de> Date: Thu, 15 Sep 2016 16:19:06 +0200 Subject: staging: most: hdm-dim2: double size of DBR buffer This patch increases the size of the asynchronous and control DBR buffers in the Tx path to twice the max. message size. This patch is needed to increase the throughput for big messages. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c index 8bef73c..78ce747 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hdm.c +++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c @@ -526,7 +526,7 @@ static int configure_channel(struct most_interface *most_iface, int ch_idx, hdm_ch->name, buf_size, new_size); spin_lock_irqsave(&dim_lock, flags); hal_ret = dim_init_control(&hdm_ch->ch, is_tx, ch_addr, - new_size); + is_tx ? new_size * 2 : new_size); break; case MOST_CH_ASYNC: new_size = dim_norm_ctrl_async_buffer_size(buf_size); @@ -539,7 +539,8 @@ static int configure_channel(struct most_interface *most_iface, int ch_idx, pr_warn("%s: fixed buffer size (%d -> %d)\n", hdm_ch->name, buf_size, new_size); spin_lock_irqsave(&dim_lock, flags); - hal_ret = dim_init_async(&hdm_ch->ch, is_tx, ch_addr, new_size); + hal_ret = dim_init_async(&hdm_ch->ch, is_tx, ch_addr, + is_tx ? new_size * 2 : new_size); break; case MOST_CH_ISOC_AVP: new_size = dim_norm_isoc_buffer_size(buf_size, sub_size); -- cgit v0.10.2 From a85ee2aa99684321274b85052a9d5b692d814296 Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov <andrey.shvetsov@k2l.de> Date: Thu, 15 Sep 2016 16:19:07 +0200 Subject: staging: most: hdm-dim2: round up DBR memory for async/ctrl As the DBR memory is allocated in units of DBR_BLOCK_SIZE, it is more efficient to configure the DIM2 IP to use whole blocks of the DBR memory. This patch ceils the DBR memory size used by the DIM2 IP for async/ctrl channels. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.c b/drivers/staging/most/hdm-dim2/dim2_hal.c index 0c58ab8..11abce7 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hal.c +++ b/drivers/staging/most/hdm-dim2/dim2_hal.c @@ -49,6 +49,8 @@ #define DBR_SIZE (16 * 1024) /* specified by IP */ #define DBR_BLOCK_SIZE (DBR_SIZE / 32 / DBR_MAP_SIZE) +#define ROUND_UP_TO(x, d) (((x) + (d) - 1) / (d) * (d)) + /* -------------------------------------------------------------------------- */ /* generic helper functions and macros */ @@ -698,7 +700,7 @@ static u8 init_ctrl_async(struct dim_channel *ch, u8 type, u8 is_tx, if (!check_channel_address(ch_address)) return DIM_INIT_ERR_CHANNEL_ADDRESS; - ch->dbr_size = hw_buffer_size; + ch->dbr_size = ROUND_UP_TO(hw_buffer_size, DBR_BLOCK_SIZE); ch->dbr_addr = alloc_dbr(ch->dbr_size); if (ch->dbr_addr >= DBR_SIZE) return DIM_INIT_ERR_OUT_OF_MEMORY; -- cgit v0.10.2 From 52076fe26c2873e4d36acc10172216b2223bbb57 Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov <andrey.shvetsov@k2l.de> Date: Thu, 15 Sep 2016 16:19:08 +0200 Subject: staging: most: hdm-dim2: remove structure member This patch removes the member irq_ahb0 of the structure dim2_hdm, since its job is suitably done by a simple auto variable. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c index 78ce747..1e5ac20 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hdm.c +++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c @@ -85,7 +85,6 @@ struct hdm_channel { * @most_iface: most interface structure * @capabilities: an array of channel capability data * @io_base: I/O register base address - * @irq_ahb0: dim2 AHB0 irq number * @clk_speed: user selectable (through command line parameter) clock speed * @netinfo_task: thread to deliver network status * @netinfo_waitq: waitq for the thread to sleep @@ -100,7 +99,6 @@ struct dim2_hdm { struct most_interface most_iface; char name[16 + sizeof "dim2-"]; void __iomem *io_base; - unsigned int irq_ahb0; int clk_speed; struct task_struct *netinfo_task; wait_queue_head_t netinfo_waitq; @@ -719,6 +717,7 @@ static int dim2_probe(struct platform_device *pdev) struct resource *res; int ret, i; struct kobject *kobj; + int irq; dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); if (!dev) @@ -732,18 +731,17 @@ static int dim2_probe(struct platform_device *pdev) if (IS_ERR(dev->io_base)) return PTR_ERR(dev->io_base); - ret = platform_get_irq(pdev, 0); - if (ret < 0) { + irq = platform_get_irq(pdev, 0); + if (irq < 0) { dev_err(&pdev->dev, "failed to get irq\n"); return -ENODEV; } - dev->irq_ahb0 = ret; - ret = devm_request_irq(&pdev->dev, dev->irq_ahb0, dim2_ahb_isr, 0, + ret = devm_request_irq(&pdev->dev, irq, dim2_ahb_isr, 0, "mlb_ahb0", dev); if (ret) { dev_err(&pdev->dev, "failed to request IRQ: %d, err: %d\n", - dev->irq_ahb0, ret); + irq, ret); return ret; } init_waitqueue_head(&dev->netinfo_waitq); -- cgit v0.10.2 From 055f1d12da0b56c878da9ab48c922df3e8905973 Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov <andrey.shvetsov@k2l.de> Date: Thu, 15 Sep 2016 16:19:09 +0200 Subject: staging: most: hdm-dim2: rename function This patch renames the function dim_service_irq. It subsitutes the name with the more suitable identifier dim_service_ahb_int_irq. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.c b/drivers/staging/most/hdm-dim2/dim2_hal.c index 11abce7..1382b78 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hal.c +++ b/drivers/staging/most/hdm-dim2/dim2_hal.c @@ -826,7 +826,7 @@ u8 dim_destroy_channel(struct dim_channel *ch) return DIM_NO_ERROR; } -void dim_service_irq(struct dim_channel *const *channels) +void dim_service_ahb_int_irq(struct dim_channel *const *channels) { bool state_changed; diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.h b/drivers/staging/most/hdm-dim2/dim2_hal.h index 62eb5e7..777a56e 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hal.h +++ b/drivers/staging/most/hdm-dim2/dim2_hal.h @@ -87,7 +87,7 @@ u8 dim_init_sync(struct dim_channel *ch, u8 is_tx, u16 ch_address, u8 dim_destroy_channel(struct dim_channel *ch); -void dim_service_irq(struct dim_channel *const *channels); +void dim_service_ahb_int_irq(struct dim_channel *const *channels); u8 dim_service_channel(struct dim_channel *ch); diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c index 1e5ac20..a20c9fd 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hdm.c +++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c @@ -447,7 +447,7 @@ static irqreturn_t dim2_ahb_isr(int irq, void *_dev) unsigned long flags; spin_lock_irqsave(&dim_lock, flags); - dim_service_irq(get_active_channels(dev, buffer)); + dim_service_ahb_int_irq(get_active_channels(dev, buffer)); spin_unlock_irqrestore(&dim_lock, flags); dim2_tasklet.data = (unsigned long)dev; -- cgit v0.10.2 From cad29b4b201f97725fd41139bdd70330a5d53948 Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov <andrey.shvetsov@k2l.de> Date: Thu, 15 Sep 2016 16:19:10 +0200 Subject: staging: most: hdm-dim2: delete error code from logging message This patch removes the logging of the returned error code of function dim2_probe as it is done by the calling function. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c index a20c9fd..c7e9ca4 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hdm.c +++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c @@ -740,8 +740,7 @@ static int dim2_probe(struct platform_device *pdev) ret = devm_request_irq(&pdev->dev, irq, dim2_ahb_isr, 0, "mlb_ahb0", dev); if (ret) { - dev_err(&pdev->dev, "failed to request IRQ: %d, err: %d\n", - irq, ret); + dev_err(&pdev->dev, "failed to request IRQ: %d\n", irq); return ret; } init_waitqueue_head(&dev->netinfo_waitq); -- cgit v0.10.2 From 3512ede28e6e65684504e1e83c5de1731da6ac36 Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov <andrey.shvetsov@k2l.de> Date: Thu, 15 Sep 2016 16:19:11 +0200 Subject: staging: most: hdm-dim2: remove clearance of pending MLB interrupt This patch removes unnecessary clearing of a pending mlb_int from the service routine for ahb interrupt. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.c b/drivers/staging/most/hdm-dim2/dim2_hal.c index 1382b78..695f316 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hal.c +++ b/drivers/staging/most/hdm-dim2/dim2_hal.c @@ -858,10 +858,6 @@ void dim_service_ahb_int_irq(struct dim_channel *const *channels) ++ch; } } while (state_changed); - - /* clear pending Interrupts */ - dimcb_io_write(&g.dim2->MS0, 0); - dimcb_io_write(&g.dim2->MS1, 0); } u8 dim_service_channel(struct dim_channel *ch) -- cgit v0.10.2 From a0adbc7a81ec5430989bb2323a58c7981215077d Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov <andrey.shvetsov@k2l.de> Date: Thu, 15 Sep 2016 16:19:12 +0200 Subject: staging: most: hdm-dim2: fix dim2-ip interrupt names This patch fixes the DIM2 IP interrupt names. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c index c7e9ca4..0350798 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hdm.c +++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c @@ -733,14 +733,14 @@ static int dim2_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "failed to get irq\n"); + dev_err(&pdev->dev, "failed to get ahb0_int irq\n"); return -ENODEV; } ret = devm_request_irq(&pdev->dev, irq, dim2_ahb_isr, 0, - "mlb_ahb0", dev); + "dim2_ahb0_int", dev); if (ret) { - dev_err(&pdev->dev, "failed to request IRQ: %d\n", irq); + dev_err(&pdev->dev, "failed to request ahb0_int irq %d\n", irq); return ret; } init_waitqueue_head(&dev->netinfo_waitq); -- cgit v0.10.2 From 8f5334651a14661f945c2d440479bb9bfa6c2b49 Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov <andrey.shvetsov@k2l.de> Date: Thu, 15 Sep 2016 16:19:13 +0200 Subject: staging: most: hdm-dim2: monitor atx DBR space This patch implements a workaround for a DIM2 issue where the device macro, in case the asynchronous channel sends data (to MOST), sporadically duplicates the synchronous blocks with a size of half the synchronous DBR buffer. The patch monitors the size of the unused asynchronous Tx DBR memory (that includes the ping and pong sizes) to prevent the potential DBR overflow for the asynchronous Tx DBR buffer. The patched DIM2 HDM expects that the platform driver delivers the 2nd platform irq (index 1) as the mlb_int of the DIM2 macro. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.c b/drivers/staging/most/hdm-dim2/dim2_hal.c index 695f316..0b9816c 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hal.c +++ b/drivers/staging/most/hdm-dim2/dim2_hal.c @@ -68,10 +68,19 @@ static inline bool dim_on_error(u8 error_id, const char *error_message) /* -------------------------------------------------------------------------- */ /* types and local variables */ +struct async_tx_dbr { + u8 ch_addr; + u16 rpc; + u16 wpc; + u16 rest_size; + u16 sz_queue[CDT0_RPC_MASK + 1]; +}; + struct lld_global_vars_t { bool dim_is_initialized; bool mcm_is_initialized; struct dim2_regs __iomem *dim2; /* DIM2 core base address */ + struct async_tx_dbr atx_dbr; u32 fcnt; u32 dbr_map[DBR_MAP_SIZE]; }; @@ -253,6 +262,13 @@ static void dim2_configure_cdt(u8 ch_addr, u16 dbr_address, u16 hw_buffer_size, dim2_write_ctr(CDT + ch_addr, cdt); } +static u16 dim2_rpc(u8 ch_addr) +{ + u32 cdt0 = dim2_read_ctr(CDT + ch_addr, 0); + + return (cdt0 >> CDT0_RPC_SHIFT) & CDT0_RPC_MASK; +} + static void dim2_clear_cdt(u8 ch_addr) { u32 cdt[4] = { 0, 0, 0, 0 }; @@ -363,6 +379,49 @@ static void dim2_clear_channel(u8 ch_addr) } /* -------------------------------------------------------------------------- */ +/* trace async tx dbr fill state */ + +static inline u16 norm_pc(u16 pc) +{ + return pc & CDT0_RPC_MASK; +} + +static void dbrcnt_init(u8 ch_addr, u16 dbr_size) +{ + g.atx_dbr.rest_size = dbr_size; + g.atx_dbr.rpc = dim2_rpc(ch_addr); + g.atx_dbr.wpc = g.atx_dbr.rpc; +} + +static void dbrcnt_enq(int buf_sz) +{ + g.atx_dbr.rest_size -= buf_sz; + g.atx_dbr.sz_queue[norm_pc(g.atx_dbr.wpc)] = buf_sz; + g.atx_dbr.wpc++; +} + +u16 dim_dbr_space(struct dim_channel *ch) +{ + u16 cur_rpc; + struct async_tx_dbr *dbr = &g.atx_dbr; + + if (ch->addr != dbr->ch_addr) + return 0xFFFF; + + cur_rpc = dim2_rpc(ch->addr); + + while (norm_pc(dbr->rpc) != cur_rpc) { + dbr->rest_size += dbr->sz_queue[norm_pc(dbr->rpc)]; + dbr->rpc++; + } + + if ((u16)(dbr->wpc - dbr->rpc) >= CDT0_RPC_MASK) + return 0; + + return dbr->rest_size; +} + +/* -------------------------------------------------------------------------- */ /* channel state helpers */ static void state_init(struct int_ch_state *state) @@ -614,6 +673,9 @@ static bool channel_start(struct dim_channel *ch, u32 buf_addr, u16 buf_size) ++state->level; + if (ch->addr == g.atx_dbr.ch_addr) + dbrcnt_enq(buf_size); + if (ch->packet_length || ch->bytes_per_frame) dim2_start_isoc_sync(ch->addr, state->idx1, buf_addr, buf_size); else @@ -713,6 +775,12 @@ static u8 init_ctrl_async(struct dim_channel *ch, u8 type, u8 is_tx, return DIM_NO_ERROR; } +void dim_service_mlb_int_irq(void) +{ + dimcb_io_write(&g.dim2->MS0, 0); + dimcb_io_write(&g.dim2->MS1, 0); +} + u16 dim_norm_ctrl_async_buffer_size(u16 buf_size) { return norm_ctrl_async_buffer_size(buf_size); @@ -756,8 +824,16 @@ u8 dim_init_control(struct dim_channel *ch, u8 is_tx, u16 ch_address, u8 dim_init_async(struct dim_channel *ch, u8 is_tx, u16 ch_address, u16 max_buffer_size) { - return init_ctrl_async(ch, CAT_CT_VAL_ASYNC, is_tx, ch_address, - max_buffer_size); + u8 ret = init_ctrl_async(ch, CAT_CT_VAL_ASYNC, is_tx, ch_address, + max_buffer_size); + + if (is_tx && !g.atx_dbr.ch_addr) { + g.atx_dbr.ch_addr = ch->addr; + dbrcnt_init(ch->addr, ch->dbr_size); + dimcb_io_write(&g.dim2->MIEN, bit_mask(20)); + } + + return ret; } u8 dim_init_isoc(struct dim_channel *ch, u8 is_tx, u16 ch_address, @@ -818,6 +894,11 @@ u8 dim_destroy_channel(struct dim_channel *ch) if (!g.dim_is_initialized || !ch) return DIM_ERR_DRIVER_NOT_INITIALIZED; + if (ch->addr == g.atx_dbr.ch_addr) { + dimcb_io_write(&g.dim2->MIEN, 0); + g.atx_dbr.ch_addr = 0; + } + dim2_clear_channel(ch->addr); if (ch->dbr_addr < DBR_SIZE) free_dbr(ch->dbr_addr, ch->dbr_size); diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.h b/drivers/staging/most/hdm-dim2/dim2_hal.h index 777a56e..6df6ea5 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hal.h +++ b/drivers/staging/most/hdm-dim2/dim2_hal.h @@ -87,6 +87,8 @@ u8 dim_init_sync(struct dim_channel *ch, u8 is_tx, u16 ch_address, u8 dim_destroy_channel(struct dim_channel *ch); +void dim_service_mlb_int_irq(void); + void dim_service_ahb_int_irq(struct dim_channel *const *channels); u8 dim_service_channel(struct dim_channel *ch); @@ -94,6 +96,8 @@ u8 dim_service_channel(struct dim_channel *ch); struct dim_ch_state_t *dim_get_channel_state(struct dim_channel *ch, struct dim_ch_state_t *state_ptr); +u16 dim_dbr_space(struct dim_channel *ch); + bool dim_enqueue_buffer(struct dim_channel *ch, u32 buffer_addr, u16 buffer_size); diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c index 0350798..71f4ae7 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hdm.c +++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c @@ -249,6 +249,11 @@ static int try_start_dim_transfer(struct hdm_channel *hdm_ch) mbo = list_first_entry(head, struct mbo, list); buf_size = mbo->buffer_length; + if (dim_dbr_space(&hdm_ch->ch) < buf_size) { + spin_unlock_irqrestore(&dim_lock, flags); + return -EAGAIN; + } + BUG_ON(mbo->bus_address == 0); if (!dim_enqueue_buffer(&hdm_ch->ch, mbo->bus_address, buf_size)) { list_del(head->next); @@ -406,6 +411,22 @@ static struct dim_channel **get_active_channels(struct dim2_hdm *dev, return buffer; } +static irqreturn_t dim2_mlb_isr(int irq, void *_dev) +{ + struct dim2_hdm *dev = _dev; + unsigned long flags; + + spin_lock_irqsave(&dim_lock, flags); + dim_service_mlb_int_irq(); + spin_unlock_irqrestore(&dim_lock, flags); + + if (dev->atx_idx >= 0 && dev->hch[dev->atx_idx].is_initialized) + while (!try_start_dim_transfer(dev->hch + dev->atx_idx)) + continue; + + return IRQ_HANDLED; +} + /** * dim2_tasklet_fn - tasklet function * @data: private data @@ -743,6 +764,20 @@ static int dim2_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failed to request ahb0_int irq %d\n", irq); return ret; } + + irq = platform_get_irq(pdev, 1); + if (irq < 0) { + dev_err(&pdev->dev, "failed to get mlb_int irq\n"); + return -ENODEV; + } + + ret = devm_request_irq(&pdev->dev, irq, dim2_mlb_isr, 0, + "dim2_mlb_int", dev); + if (ret) { + dev_err(&pdev->dev, "failed to request mlb_int irq %d\n", irq); + return ret; + } + init_waitqueue_head(&dev->netinfo_waitq); dev->deliver_netinfo = 0; dev->netinfo_task = kthread_run(&deliver_netinfo_thread, (void *)dev, diff --git a/drivers/staging/most/hdm-dim2/dim2_reg.h b/drivers/staging/most/hdm-dim2/dim2_reg.h index 3b1c200..01fe499 100644 --- a/drivers/staging/most/hdm-dim2/dim2_reg.h +++ b/drivers/staging/most/hdm-dim2/dim2_reg.h @@ -117,6 +117,9 @@ enum { }; enum { + CDT0_RPC_SHIFT = 16 + 11, + CDT0_RPC_MASK = DIM2_MASK(5), + CDT1_BS_ISOC_SHIFT = 0, CDT1_BS_ISOC_MASK = DIM2_MASK(9), -- cgit v0.10.2 From b9aabfcc988c81ce442e61df7b84c50098b13083 Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Thu, 15 Sep 2016 18:20:31 +0530 Subject: staging: lustre: Add space b/w concatenated strings Fixes checkpatch.pl warning: CHECK: Concatenated strings should use spaces between elements Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/fid/fid_request.c b/drivers/staging/lustre/lustre/fid/fid_request.c index 454744d..edd72b9 100644 --- a/drivers/staging/lustre/lustre/fid/fid_request.c +++ b/drivers/staging/lustre/lustre/fid/fid_request.c @@ -125,19 +125,19 @@ static int seq_client_rpc(struct lu_client_seq *seq, if (!range_is_sane(output)) { CERROR("%s: Invalid range received from server: " - DRANGE"\n", seq->lcs_name, PRANGE(output)); + DRANGE "\n", seq->lcs_name, PRANGE(output)); rc = -EINVAL; goto out_req; } if (range_is_exhausted(output)) { CERROR("%s: Range received from server is exhausted: " - DRANGE"]\n", seq->lcs_name, PRANGE(output)); + DRANGE "]\n", seq->lcs_name, PRANGE(output)); rc = -EINVAL; goto out_req; } - CDEBUG_LIMIT(debug_mask, "%s: Allocated %s-sequence "DRANGE"]\n", + CDEBUG_LIMIT(debug_mask, "%s: Allocated %s-sequence " DRANGE "]\n", seq->lcs_name, opcname, PRANGE(output)); out_req: @@ -179,7 +179,7 @@ static int seq_client_alloc_seq(const struct lu_env *env, seq->lcs_name, rc); return rc; } - CDEBUG(D_INFO, "%s: New range - "DRANGE"\n", + CDEBUG(D_INFO, "%s: New range - " DRANGE "\n", seq->lcs_name, PRANGE(&seq->lcs_space)); } else { rc = 0; diff --git a/drivers/staging/lustre/lustre/fid/lproc_fid.c b/drivers/staging/lustre/lustre/fid/lproc_fid.c index 81b7ca9..3ed32d7 100644 --- a/drivers/staging/lustre/lustre/fid/lproc_fid.c +++ b/drivers/staging/lustre/lustre/fid/lproc_fid.c @@ -105,7 +105,7 @@ ldebugfs_fid_space_seq_write(struct file *file, rc = ldebugfs_fid_write_common(buffer, count, &seq->lcs_space); if (rc == 0) { - CDEBUG(D_INFO, "%s: Space: "DRANGE"\n", + CDEBUG(D_INFO, "%s: Space: " DRANGE "\n", seq->lcs_name, PRANGE(&seq->lcs_space)); } -- cgit v0.10.2 From e9d6122c198df78a8b6b730bd5901c80a9ae3e65 Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Thu, 15 Sep 2016 18:21:04 +0530 Subject: staging: lustre: Fix block comment style Fixes checkpatch.pl warning: WARNING: Block comments use a trailing */ on a separate line. Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index 1dc8d21..f4364f9 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -1410,7 +1410,8 @@ static int ldlm_prepare_lru_list(struct ldlm_namespace *ns, * That is, for shrinker policy we drop only * old locks, but additionally choose them by * their weight. Big extent locks will stay in - * the cache. */ + * the cache. + */ result = pf(ns, lock, unused, added, count); if (result == LDLM_POLICY_KEEP_LOCK) { lu_ref_del(&lock->l_reference, @@ -1700,7 +1701,8 @@ static int ldlm_cli_hash_cancel_unused(struct cfs_hash *hs, * that have 0 readers/writers. * * If flags & LCF_LOCAL, throw the locks away without trying - * to notify the server. */ + * to notify the server. + */ int ldlm_cli_cancel_unused(struct ldlm_namespace *ns, const struct ldlm_res_id *res_id, enum ldlm_cancel_flags flags, void *opaque) -- cgit v0.10.2 From 483ace0605a8e718e35db6d2219b9a7d08c8c28b Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Thu, 15 Sep 2016 18:21:42 +0530 Subject: staging: lustre: Change 'unsigned' to 'unsigned int' Fixes checkpatch.pl warning: WARNING: Prefer 'unsigned int' to bare use of 'unsigned' Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c index e2c2587..62d9f6f 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c @@ -449,8 +449,8 @@ static unsigned ldlm_res_hop_hash(struct cfs_hash *hs, const void *key, unsigned mask) { const struct ldlm_res_id *id = key; - unsigned val = 0; - unsigned i; + unsigned int val = 0; + unsigned int i; for (i = 0; i < RES_NAME_SIZE; i++) val += id->name[i]; @@ -561,9 +561,9 @@ static struct cfs_hash_ops ldlm_ns_fid_hash_ops = { struct ldlm_ns_hash_def { enum ldlm_ns_type nsd_type; /** hash bucket bits */ - unsigned nsd_bkt_bits; + unsigned int nsd_bkt_bits; /** hash bits */ - unsigned nsd_all_bits; + unsigned int nsd_all_bits; /** hash operations */ struct cfs_hash_ops *nsd_hops; }; -- cgit v0.10.2 From 02c041c157a397e40f44345d689fbd13c3585262 Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Thu, 15 Sep 2016 18:22:10 +0530 Subject: staging: lustre: Change 'seq_printf' to 'seq_puts' Fixes checkpatch.pl warning: Prefer seq_puts to seq_printf. This can be done as both have same type of first two arguments in their function definition. Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/lproc_llite.c b/drivers/staging/lustre/lustre/llite/lproc_llite.c index 4e82db8..af233ea 100644 --- a/drivers/staging/lustre/lustre/llite/lproc_llite.c +++ b/drivers/staging/lustre/lustre/llite/lproc_llite.c @@ -774,7 +774,7 @@ static int ll_sbi_flags_seq_show(struct seq_file *m, void *v) flags >>= 1; ++i; } - seq_printf(m, "\b\n"); + seq_puts(m, "\b\n"); return 0; } -- cgit v0.10.2 From 994b48775ab8cda03fcc92bf653b06a63b439658 Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Thu, 15 Sep 2016 18:22:40 +0530 Subject: staging: lustre: Remove unnecessary 'return' Remove unnecessary void return at the end of a function. Issue detected by checkpatch. Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index bb85d16..23747fa 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -667,7 +667,6 @@ static void ras_update_stride_detector(struct ll_readahead_state *ras, ras->ras_stride_length = stride_gap + ras->ras_consecutive_pages; RAS_CDEBUG(ras); - return; } /* Stride Read-ahead window will be increased inc_len according to @@ -883,7 +882,6 @@ out_unlock: RAS_CDEBUG(ras); ras->ras_request_index++; spin_unlock(&ras->ras_lock); - return; } int ll_writepage(struct page *vmpage, struct writeback_control *wbc) -- cgit v0.10.2 From c03eb7541065868691443e1d853a780969bad608 Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Thu, 15 Sep 2016 18:23:18 +0530 Subject: staging: lustre: Fix indentation Fixes checkpatch.pl warning: Statements should start on a tabstop. Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index e2e81bf..bfac6dd 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -602,7 +602,7 @@ restart: } else if (it->it_flags & FMODE_EXEC) { och_p = &lli->lli_mds_exec_och; och_usecount = &lli->lli_open_fd_exec_count; - } else { + } else { och_p = &lli->lli_mds_read_och; och_usecount = &lli->lli_open_fd_read_count; } diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index 23747fa..25de3bf 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -1022,7 +1022,7 @@ int ll_writepages(struct address_space *mapping, struct writeback_control *wbc) if (result > 0) { wbc->nr_to_write -= result; result = 0; - } + } if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) { if (end == OBD_OBJECT_EOF) -- cgit v0.10.2 From 08441a938b173ff7001e2ea588bd0c26778776fd Mon Sep 17 00:00:00 2001 From: Baoyou Xie <baoyou.xie@linaro.org> Date: Thu, 15 Sep 2016 23:45:17 +0800 Subject: staging: lustre: clean function declarations in class_obd.c up We get 2 warnings when building kernel with W=1: drivers/staging/lustre/lustre/obdclass/linux/linux-module.c:413:5: warning: no previous prototype for 'class_procfs_init' [-Wmissing-prototypes] drivers/staging/lustre/lustre/obdclass/linux/linux-module.c:449:5: warning: no previous prototype for 'class_procfs_clean' [-Wmissing-prototypes] In fact, both functions are declared in drivers/staging/lustre/lustre/obdclass/class_obd.c,but should be declared in a header file, thus can be recognized in other file. So this patch moves the declarations into drivers/staging/lustre/lustre/include/obd_class.h. Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index 9702ad4..324c70d 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -1716,6 +1716,8 @@ void class_exit_uuidlist(void); extern char obd_jobid_node[]; extern struct miscdevice obd_psdev; extern spinlock_t obd_types_lock; +int class_procfs_init(void); +int class_procfs_clean(void); /* prng.c */ #define ll_generate_random_uuid(uuid_out) cfs_get_random_bytes(uuid_out, sizeof(class_uuid_t)) diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c index 6700167..710039a 100644 --- a/drivers/staging/lustre/lustre/obdclass/class_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c @@ -446,9 +446,6 @@ static int obd_init_checks(void) return ret; } -extern int class_procfs_init(void); -extern int class_procfs_clean(void); - static int __init obdclass_init(void) { int i, err; -- cgit v0.10.2 From f8b30859856a964ed76934a8a6d480d0b52b252c Mon Sep 17 00:00:00 2001 From: Asbjoern Sloth Toennesen <asbjorn@asbjorn.st> Date: Tue, 13 Sep 2016 19:12:36 +0000 Subject: staging: octeon: use defines instead of magic numbers The ugly magic number 65392 is waiting for CVMX_IPD_MAX_MTU to appear in the mips tree. Signed-off-by: Asbjoern Sloth Toennesen <asbjorn@asbjorn.st> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index 5f746b8..790477c 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -17,6 +17,8 @@ #include <linux/slab.h> #include <linux/interrupt.h> #include <linux/of_net.h> +#include <linux/if_ether.h> +#include <linux/if_vlan.h> #include <net/dst.h> @@ -39,6 +41,8 @@ #include <asm/octeon/cvmx-gmxx-defs.h> #include <asm/octeon/cvmx-smix-defs.h> +#define OCTEON_MAX_MTU 65392 + static int num_packet_buffers = 1024; module_param(num_packet_buffers, int, 0444); MODULE_PARM_DESC(num_packet_buffers, "\n" @@ -249,19 +253,21 @@ static int cvm_oct_common_change_mtu(struct net_device *dev, int new_mtu) struct octeon_ethernet *priv = netdev_priv(dev); int interface = INTERFACE(priv->port); #if IS_ENABLED(CONFIG_VLAN_8021Q) - int vlan_bytes = 4; + int vlan_bytes = VLAN_HLEN; #else int vlan_bytes = 0; #endif + int mtu_overhead = ETH_HLEN + ETH_FCS_LEN + vlan_bytes; /* * Limit the MTU to make sure the ethernet packets are between * 64 bytes and 65535 bytes. */ - if ((new_mtu + 14 + 4 + vlan_bytes < 64) || - (new_mtu + 14 + 4 + vlan_bytes > 65392)) { + if ((new_mtu + mtu_overhead < VLAN_ETH_ZLEN) || + (new_mtu + mtu_overhead > OCTEON_MAX_MTU)) { pr_err("MTU must be between %d and %d.\n", - 64 - 14 - 4 - vlan_bytes, 65392 - 14 - 4 - vlan_bytes); + VLAN_ETH_ZLEN - mtu_overhead, + OCTEON_MAX_MTU - mtu_overhead); return -EINVAL; } dev->mtu = new_mtu; @@ -271,7 +277,7 @@ static int cvm_oct_common_change_mtu(struct net_device *dev, int new_mtu) CVMX_HELPER_INTERFACE_MODE_SPI)) { int index = INDEX(priv->port); /* Add ethernet header and FCS, and VLAN if configured. */ - int max_packet = new_mtu + 14 + 4 + vlan_bytes; + int max_packet = new_mtu + mtu_overhead; if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN58XX)) { @@ -286,7 +292,7 @@ static int cvm_oct_common_change_mtu(struct net_device *dev, int new_mtu) union cvmx_pip_frm_len_chkx frm_len_chk; frm_len_chk.u64 = 0; - frm_len_chk.s.minlen = 64; + frm_len_chk.s.minlen = VLAN_ETH_ZLEN; frm_len_chk.s.maxlen = max_packet; cvmx_write_csr(CVMX_PIP_FRM_LEN_CHKX(interface), frm_len_chk.u64); -- cgit v0.10.2 From e52f21494f48b437839ae59f8ce8d9b60eca01cf Mon Sep 17 00:00:00 2001 From: Sandhya Bankar <bankarsandhya512@gmail.com> Date: Thu, 15 Sep 2016 13:52:51 +0530 Subject: Staging: wlan-ng: Use !x instead of x == NULL. Use !x instead of x == NULL. This issue was found by checkpatch. Signed-off-by: Sandhya Bankar <bankarsandhya512@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index a36e40d..884d0d5 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -265,7 +265,7 @@ static int prism2_get_station(struct wiphy *wiphy, struct net_device *dev, memset(sinfo, 0, sizeof(*sinfo)); - if ((wlandev == NULL) || (wlandev->msdstate != WLAN_MSD_RUNNING)) + if (!wlandev || (wlandev->msdstate != WLAN_MSD_RUNNING)) return -EOPNOTSUPP; /* build request message */ @@ -274,7 +274,7 @@ static int prism2_get_station(struct wiphy *wiphy, struct net_device *dev, quality.dbm.status = P80211ENUM_msgitem_status_data_ok; /* send message to nsd */ - if (wlandev->mlmerequest == NULL) + if (!wlandev->mlmerequest) return -EOPNOTSUPP; result = wlandev->mlmerequest(wlandev, (struct p80211msg *)&quality); -- cgit v0.10.2 From d769079b08da16c614849362199cc075f5a1fda2 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar <bankarsandhya512@gmail.com> Date: Wed, 14 Sep 2016 17:37:51 +0530 Subject: Staging: sm750fb: Remove unnecessary blank line Remove unnecessary blank line. This patch is detected by checkpatch.pl script . CHECK: Blank lines aren't necessary before a close brace '}' Signed-off-by: Sandhya Bankar <bankarsandhya512@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/sm750fb/ddk750_display.c b/drivers/staging/sm750fb/ddk750_display.c index a040042..4023c476 100644 --- a/drivers/staging/sm750fb/ddk750_display.c +++ b/drivers/staging/sm750fb/ddk750_display.c @@ -137,7 +137,6 @@ static void swPanelPowerSequence(int disp, int delay) reg |= (disp ? PANEL_DISPLAY_CTRL_FPEN : 0); POKE32(PANEL_DISPLAY_CTRL, reg); primaryWaitVerticalSync(delay); - } void ddk750_setLogicalDispOut(disp_output_t output) @@ -162,7 +161,6 @@ void ddk750_setLogicalDispOut(disp_output_t output) /*se blank off */ reg &= ~CRT_DISPLAY_CTRL_BLANK; POKE32(CRT_DISPLAY_CTRL, reg); - } if (output & PRI_TP_USAGE) { -- cgit v0.10.2 From 46b7dd7ce3e0de9b92402032877cc414b5ba9216 Mon Sep 17 00:00:00 2001 From: Moshe Green <mgmoshes@gmail.com> Date: Thu, 15 Sep 2016 23:15:50 +0300 Subject: staging: sm750fb: fix line length coding style issues in ddk750_chip.c Fix multiple line length warnings found by the checkpatch.pl tool in ddk750_chip.c. Signed-off-by: Moshe Green <mgmoshes@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index c1356bb..7cba1ab 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -71,9 +71,10 @@ static void setChipClock(unsigned int frequency) pll.clockType = MXCLK_PLL; /* - * Call calcPllValue() to fill up the other fields for PLL structure. - * Sometime, the chip cannot set up the exact clock required by User. - * Return value from calcPllValue() gives the actual possible clock. + * Call calcPllValue() to fill the other fields of PLL structure. + * Sometime, the chip cannot set up the exact clock + * required by the User. + * Return value of calcPllValue gives the actual possible clock. */ ulActualMxClk = calcPllValue(frequency, &pll); @@ -94,8 +95,8 @@ static void setMemoryClock(unsigned int frequency) if (frequency) { /* - * Set the frequency to the maximum frequency that the DDR Memory can take - * which is 336MHz. + * Set the frequency to the maximum frequency + * that the DDR Memory can take which is 336MHz. */ if (frequency > MHz(336)) frequency = MHz(336); @@ -305,7 +306,9 @@ int ddk750_initHw(initchip_param_t *pInitParam) */ unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll) { - /* as sm750 register definition, N located in 2,15 and M located in 1,255 */ + /* as sm750 register definition, + * N located in 2,15 and M located in 1,255 + */ int N, M, X, d; int mini_diff; unsigned int RN, quo, rem, fl_quo; @@ -325,12 +328,16 @@ unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll) request = request_orig / 1000; input = pll->inputFreq / 1000; - /* for MXCLK register , no POD provided, so need be treated differently */ + /* for MXCLK register, + * no POD provided, so need be treated differently + */ if (pll->clockType == MXCLK_PLL) max_d = 3; for (N = 15; N > 1; N--) { - /* RN will not exceed maximum long if @request <= 285 MHZ (for 32bit cpu) */ + /* RN will not exceed maximum long + * if @request <= 285 MHZ (for 32bit cpu) + */ RN = N * request; quo = RN / input; rem = RN % input;/* rem always small than 14318181 */ -- cgit v0.10.2 From b29376c31aaade2e28a79722c680f7c60500af48 Mon Sep 17 00:00:00 2001 From: Moshe Green <mgmoshes@gmail.com> Date: Thu, 15 Sep 2016 23:16:11 +0300 Subject: staging: sm750fb: fix block comment style and spelling issues in ddk750_chip.c Fix the following warning types: - line length - block comment line * prefix - trailing */ on a separate line found by the checkpatch.pl tool in multiple block comments. Fix a single spelling error in a comment. Signed-off-by: Moshe Green <mgmoshes@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index 7cba1ab..f557b6d 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -145,8 +145,9 @@ static void setMasterClock(unsigned int frequency) return; if (frequency) { - /* Set the frequency to the maximum frequency that the SM750 engine can - run, which is about 190 MHz. */ + /* Set the frequency to the maximum frequency + * that the SM750 engine can run, which is about 190 MHz. + */ if (frequency > MHz(190)) frequency = MHz(190); @@ -243,9 +244,10 @@ int ddk750_initHw(initchip_param_t *pInitParam) setMasterClock(MHz(pInitParam->masterClock)); - /* Reset the memory controller. If the memory controller is not reset in SM750, - the system might hang when sw accesses the memory. - The memory should be resetted after changing the MXCLK. + /* Reset the memory controller. + * If the memory controller is not reset in SM750, + * the system might hang when sw accesses the memory. + * The memory should be resetted after changing the MXCLK. */ if (pInitParam->resetMemory == 1) { reg = PEEK32(MISC_CTRL); @@ -289,21 +291,22 @@ int ddk750_initHw(initchip_param_t *pInitParam) } /* - monk liu @ 4/6/2011: - re-write the calculatePLL function of ddk750. - the original version function does not use some mathematics tricks and shortcut - when it doing the calculation of the best N,M,D combination - I think this version gives a little upgrade in speed - - 750 pll clock formular: - Request Clock = (Input Clock * M )/(N * X) - - Input Clock = 14318181 hz - X = 2 power D - D ={0,1,2,3,4,5,6} - M = {1,...,255} - N = {2,...,15} -*/ + * monk liu @ 4/6/2011: + * re-write the calculatePLL function of ddk750. + * the original version function does not use + * some mathematics tricks and shortcut + * when it doing the calculation of the best N,M,D combination + * I think this version gives a little upgrade in speed + * + * 750 pll clock formular: + * Request Clock = (Input Clock * M )/(N * X) + * + * Input Clock = 14318181 hz + * X = 2 power D + * D ={0,1,2,3,4,5,6} + * M = {1,...,255} + * N = {2,...,15} + */ unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll) { /* as sm750 register definition, @@ -318,8 +321,10 @@ unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll) int max_d = 6; if (getChipType() == SM750LE) { - /* SM750LE don't have prgrammable PLL and M/N values to work on. - Just return the requested clock. */ + /* SM750LE don't have + * programmable PLL and M/N values to work on. + * Just return the requested clock. + */ return request_orig; } -- cgit v0.10.2 From 71b4de84a0ef8b495da3d3ca884e3e601b05af1b Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Fri, 16 Sep 2016 03:02:42 +0530 Subject: staging: sm750fb: Change 'x != NULL' to 'x' Changes the explicit comparison to NULL from 'x != NULL' to 'x'. Issue detected by checkpatch. Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c index 6ed004e..7d90e25 100644 --- a/drivers/staging/sm750fb/sm750.c +++ b/drivers/staging/sm750fb/sm750.c @@ -1176,7 +1176,7 @@ static int __init lynxfb_setup(char *options) else { strcat(tmp, opt); tmp += strlen(opt); - if (options != NULL) + if (options) *tmp++ = ':'; else *tmp++ = 0; -- cgit v0.10.2 From 1fed320aaeb0f8c75860f2e772619bf18d2144eb Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Fri, 16 Sep 2016 03:03:21 +0530 Subject: staging: sm750fb: Change 'uint32_t' to 'u32' It is preferred to use 'u32' instead of 'uint32_t' for unsigned int. Issue detected by checkpatch. Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index 1de9f81..a376d17 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -534,7 +534,7 @@ int hw_sm750_pan_display(struct lynxfb_crtc *crtc, const struct fb_var_screeninfo *var, const struct fb_info *info) { - uint32_t total; + u32 total; /* check params */ if ((var->xoffset + var->xres > var->xres_virtual) || (var->yoffset + var->yres > var->yres_virtual)) { -- cgit v0.10.2 From 2c768b8bfb61e45f736bb042ce3218096f6a1bfd Mon Sep 17 00:00:00 2001 From: Anchal Jain <anchalj109@gmail.com> Date: Tue, 13 Sep 2016 16:30:41 +0530 Subject: staging: media: lirc: lirc_bt829: Remove explicit NULL comparison Remove explicit NULL comparison and write it in its simpler form. Signed-off-by: Anchal Jain <anchalj109@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/media/lirc/lirc_bt829.c b/drivers/staging/media/lirc/lirc_bt829.c index 44f5655..f740115 100644 --- a/drivers/staging/media/lirc/lirc_bt829.c +++ b/drivers/staging/media/lirc/lirc_bt829.c @@ -120,7 +120,7 @@ int init_module(void) int rc; pdev = do_pci_probe(); - if (pdev == NULL) + if (!pdev) return -ENODEV; rc = pci_enable_device(pdev); -- cgit v0.10.2 From 0152b5b2a519406e10f91cdb3f1ab7d507f49783 Mon Sep 17 00:00:00 2001 From: Anchal Jain <anchalj109@gmail.com> Date: Tue, 13 Sep 2016 16:34:53 +0530 Subject: staging: media: lirc: lirc_imon: Remove multiple blank lines checkpatch complains about multiple blank lines. Signed-off-by: Anchal Jain <anchalj109@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/media/lirc/lirc_imon.c b/drivers/staging/media/lirc/lirc_imon.c index a183e68..1da5cc0 100644 --- a/drivers/staging/media/lirc/lirc_imon.c +++ b/drivers/staging/media/lirc/lirc_imon.c @@ -32,7 +32,6 @@ #include <media/lirc.h> #include <media/lirc_dev.h> - #define MOD_AUTHOR "Venky Raju <dev@venky.ws>" #define MOD_DESC "Driver for SoundGraph iMON MultiMedia IR/Display" #define MOD_NAME "lirc_imon" -- cgit v0.10.2 From 09ed2c0b9b2f87f5459f13330762abf902b7ed0d Mon Sep 17 00:00:00 2001 From: Anchal Jain <anchalj109@gmail.com> Date: Tue, 13 Sep 2016 16:42:51 +0530 Subject: staging: media: lirc: lirc_imon: Remove unnecessary blank line CHECK: Remove a blank lines before a closed parenthesis '}' Signed-off-by: Anchal Jain <anchalj109@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/media/lirc/lirc_imon.c b/drivers/staging/media/lirc/lirc_imon.c index 1da5cc0..c12053d 100644 --- a/drivers/staging/media/lirc/lirc_imon.c +++ b/drivers/staging/media/lirc/lirc_imon.c @@ -211,7 +211,6 @@ static void deregister_from_lirc(struct imon_context *context) else dev_info(&context->usbdev->dev, "Deregistered iMON driver (minor:%d)\n", minor); - } /** -- cgit v0.10.2 From c16f06f55c88ed831fe8569668d75b18f8ead795 Mon Sep 17 00:00:00 2001 From: Anchal Jain <anchalj109@gmail.com> Date: Tue, 13 Sep 2016 16:45:24 +0530 Subject: staging: media: lirc: lirc_imon: Remove a blank line before a close parenthesis '}' CHECK: Remove unnecessary space after cast Signed-off-by: Anchal Jain <anchalj109@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/media/lirc/lirc_imon.c b/drivers/staging/media/lirc/lirc_imon.c index c12053d..e44f841 100644 --- a/drivers/staging/media/lirc/lirc_imon.c +++ b/drivers/staging/media/lirc/lirc_imon.c @@ -427,7 +427,7 @@ static ssize_t vfd_write(struct file *file, const char __user *buf, do { memcpy(context->usb_tx_buf, context->tx.data_buf + offset, 7); - context->usb_tx_buf[7] = (unsigned char) seq; + context->usb_tx_buf[7] = (unsigned char)seq; retval = send_packet(context); if (retval) { @@ -445,7 +445,7 @@ static ssize_t vfd_write(struct file *file, const char __user *buf, if (context->vfd_proto_6p) { /* Send packet #6 */ memcpy(context->usb_tx_buf, &vfd_packet6, sizeof(vfd_packet6)); - context->usb_tx_buf[7] = (unsigned char) seq; + context->usb_tx_buf[7] = (unsigned char)seq; retval = send_packet(context); if (retval) dev_err(&context->usbdev->dev, -- cgit v0.10.2 From f32519bf8ec6659324b95af98d0c450488f3b451 Mon Sep 17 00:00:00 2001 From: Anchal Jain <anchalj109@gmail.com> Date: Tue, 13 Sep 2016 16:48:01 +0530 Subject: staging: media: lirc: lirc_imon: Add space around the operators CHECK: Add space around the operators { "<<", "*"}. Signed-off-by: Anchal Jain <anchalj109@gmail.com> Acked-by: Julia Lawall <julia.lawall@lip6.fr> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/media/lirc/lirc_imon.c b/drivers/staging/media/lirc/lirc_imon.c index e44f841..ee12da2 100644 --- a/drivers/staging/media/lirc/lirc_imon.c +++ b/drivers/staging/media/lirc/lirc_imon.c @@ -561,7 +561,7 @@ static void submit_data(struct imon_context *context) value |= PULSE_BIT; for (i = 0; i < 4; ++i) - buf[i] = value>>(i*8); + buf[i] = value >> (i * 8); lirc_buffer_write(context->driver->rbuf, buf); wake_up(&context->driver->rbuf->wait_poll); -- cgit v0.10.2 From a54570a8c0ba5a08b017c6afbe5ffed242ea6c59 Mon Sep 17 00:00:00 2001 From: Anchal Jain <anchalj109@gmail.com> Date: Tue, 13 Sep 2016 16:51:51 +0530 Subject: staging: media: lirc: lirc_imon: Fix alignment with the open parenthesis Fix alignment to match open parenthesis. Signed-off-by: Anchal Jain <anchalj109@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/media/lirc/lirc_imon.c b/drivers/staging/media/lirc/lirc_imon.c index ee12da2..b1c28e5 100644 --- a/drivers/staging/media/lirc/lirc_imon.c +++ b/drivers/staging/media/lirc/lirc_imon.c @@ -587,7 +587,7 @@ static void imon_incoming_packet(struct imon_context *context, if (len != 8) { dev_warn(dev, "imon %s: invalid incoming packet size (len = %d, intf%d)\n", - __func__, len, intf); + __func__, len, intf); return; } @@ -828,7 +828,7 @@ static int imon_probe(struct usb_interface *interface, } dev_info(dev, "Registered iMON driver (lirc minor: %d)\n", - lirc_minor); + lirc_minor); /* Needed while unregistering! */ driver->minor = lirc_minor; @@ -849,8 +849,8 @@ static int imon_probe(struct usb_interface *interface, context->display = 1; usb_fill_int_urb(context->rx_urb, context->usbdev, - usb_rcvintpipe(context->usbdev, - context->rx_endpoint->bEndpointAddress), + usb_rcvintpipe(context->usbdev, + context->rx_endpoint->bEndpointAddress), context->usb_rx_buf, sizeof(context->usb_rx_buf), usb_rx_callback, context, context->rx_endpoint->bInterval); @@ -875,7 +875,7 @@ static int imon_probe(struct usb_interface *interface, } dev_info(dev, "iMON device (%04x:%04x, intf%d) on usb<%d:%d> initialized\n", - vendor, product, ifnum, usbdev->bus->busnum, usbdev->devnum); + vendor, product, ifnum, usbdev->bus->busnum, usbdev->devnum); /* Everything went fine. Just unlock and return retval (with is 0) */ mutex_unlock(&context->ctx_lock); @@ -966,8 +966,8 @@ static int imon_resume(struct usb_interface *intf) struct imon_context *context = usb_get_intfdata(intf); usb_fill_int_urb(context->rx_urb, context->usbdev, - usb_rcvintpipe(context->usbdev, - context->rx_endpoint->bEndpointAddress), + usb_rcvintpipe(context->usbdev, + context->rx_endpoint->bEndpointAddress), context->usb_rx_buf, sizeof(context->usb_rx_buf), usb_rx_callback, context, context->rx_endpoint->bInterval); -- cgit v0.10.2 From 1ef87b8d5c91c405745c35544d9c8e6bf1c94502 Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Fri, 16 Sep 2016 00:45:57 +0530 Subject: staging: slicoss: Remove unnecessary blank line Removes unnecessary blank line detected by checkpatch. Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index 21280a3..a5dd75a 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -1661,7 +1661,6 @@ static int slic_link_event_handler(struct adapter *adapter) struct slic_shmemory *sm = &adapter->shmem; dma_addr_t phaddr = sm->lnkstatus_phaddr; - if (adapter->state != ADAPT_UP) { /* Adapter is not operational. Ignore. */ return -ENODEV; -- cgit v0.10.2 From 1462b30786e336d73251e6c102e2ad92abc23b4a Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Fri, 16 Sep 2016 00:44:38 +0530 Subject: staging: slicoss: Remove blank lines before & after braces Removes unnecessary blank lines after an opening brace '{' and before a closing brace '}'. Issue detected by checkpatch.pl. Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index a5dd75a..81297ca 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -514,7 +514,6 @@ static int slic_card_download(struct adapter *adapter) slic_write32(adapter, SLIC_REG_WCS, instruction); instruction = *(u32 *)(fw->data + index); index += 4; - } } release_firmware(fw); @@ -2717,7 +2716,6 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter) /* see if the EEPROM is valid by checking it's checksum */ if ((eecodesize <= MAX_EECODE_SIZE) && (eecodesize >= MIN_EECODE_SIZE)) { - ee_chksum = *(u16 *)((char *)peeprom + (eecodesize - 2)); /* @@ -2855,7 +2853,6 @@ static int slic_init_adapter(struct net_device *netdev, */ for (index = 1, pslic_handle = &adapter->slic_handles[1]; index < SLIC_CMDQ_MAXCMDS; index++, pslic_handle++) { - pslic_handle->token.handle_index = index; pslic_handle->type = SLIC_HANDLE_FREE; pslic_handle->next = adapter->pfree_slic_handles; -- cgit v0.10.2 From baa30626a9473efe4004512a0507645a6832cb1b Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Fri, 16 Sep 2016 00:45:32 +0530 Subject: staging: slicoss: Remove unnecessary braces {} Removes unnecessary braces {} on both arms of an if-else block as they have a single statement each. Issue detected by checkpatch. Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index 81297ca..714e6e1 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -1630,11 +1630,10 @@ static u32 slic_rcvqueue_reinsert(struct adapter *adapter, struct sk_buff *skb) dev_err(dev, " rcvq->tail[%p]\n", rcvq->tail); dev_err(dev, " rcvq->count[%x]\n", rcvq->count); } - if (paddrh == 0) { + if (paddrh == 0) slic_write32(adapter, SLIC_REG_HBAR, (u32)paddrl); - } else { + else slic_write64(adapter, SLIC_REG_HBAR64, paddrl, paddrh); - } if (rcvq->head) rcvq->tail->next = skb; else -- cgit v0.10.2 From c8abeaf8021b1d78ba3b86235815047c8d648f4a Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Thu, 15 Sep 2016 00:52:58 +0530 Subject: staging: ks7010: Remove whitespace before newline This patch fixes the checkpatch.pl warning: WARNING: unnecessary whitespace before a quoted newline. Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c index d5299f0..f9aec4f 100644 --- a/drivers/staging/ks7010/ks7010_sdio.c +++ b/drivers/staging/ks7010/ks7010_sdio.c @@ -492,7 +492,7 @@ static void ks7010_rw_function(struct work_struct *work) /* wiat after DOZE */ if (time_after(priv->last_doze + ((30 * HZ) / 1000), jiffies)) { - DPRINTK(4, "wait after DOZE \n"); + DPRINTK(4, "wait after DOZE\n"); queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq, &priv->ks_wlan_hw.rw_wq, 1); return; @@ -500,7 +500,7 @@ static void ks7010_rw_function(struct work_struct *work) /* wiat after WAKEUP */ while (time_after(priv->last_wakeup + ((30 * HZ) / 1000), jiffies)) { - DPRINTK(4, "wait after WAKEUP \n"); + DPRINTK(4, "wait after WAKEUP\n"); /* queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,&priv->ks_wlan_hw.rw_wq, (priv->last_wakeup + ((30*HZ)/1000) - jiffies));*/ printk("wake: %lu %lu\n", priv->last_wakeup + (30 * HZ) / 1000, @@ -745,7 +745,7 @@ static int ks7010_sdio_data_compare(struct ks_wlan_private *priv, u32 address, retval = memcmp(data, read_buf, size); if (retval) { - DPRINTK(0, "data compare error (%d) \n", retval); + DPRINTK(0, "data compare error (%d)\n", retval); rc = 3; goto error_out; } diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c index 8e33a43..76ba236 100644 --- a/drivers/staging/ks7010/ks_hostif.c +++ b/drivers/staging/ks7010/ks_hostif.c @@ -244,13 +244,13 @@ int get_ap_information(struct ks_wlan_private *priv, struct ap_info_t *ap_info, offset = 0; while (bsize > offset) { - /* DPRINTK(4, "Element ID=%d \n",*bp); */ + /* DPRINTK(4, "Element ID=%d\n",*bp); */ switch (*bp) { case 0: /* ssid */ if (*(bp + 1) <= SSID_MAX_SIZE) { ap->ssid.size = *(bp + 1); } else { - DPRINTK(1, "size over :: ssid size=%d \n", + DPRINTK(1, "size over :: ssid size=%d\n", *(bp + 1)); ap->ssid.size = SSID_MAX_SIZE; } @@ -264,7 +264,7 @@ int get_ap_information(struct ks_wlan_private *priv, struct ap_info_t *ap_info, bp + 2, *(bp + 1)); ap->rate_set.size += *(bp + 1); } else { - DPRINTK(1, "size over :: rate size=%d \n", + DPRINTK(1, "size over :: rate size=%d\n", (*(bp + 1) + ap->rate_set.size)); memcpy(&(ap->rate_set.body[ap->rate_set.size]), bp + 2, @@ -280,7 +280,7 @@ int get_ap_information(struct ks_wlan_private *priv, struct ap_info_t *ap_info, if (*(bp + 1) <= RSN_IE_BODY_MAX) { ap->rsn_ie.size = *(bp + 1); } else { - DPRINTK(1, "size over :: rsn size=%d \n", + DPRINTK(1, "size over :: rsn size=%d\n", *(bp + 1)); ap->rsn_ie.size = RSN_IE_BODY_MAX; } @@ -293,7 +293,7 @@ int get_ap_information(struct ks_wlan_private *priv, struct ap_info_t *ap_info, ap->wpa_ie.size = *(bp + 1); } else { DPRINTK(1, - "size over :: wpa size=%d \n", + "size over :: wpa size=%d\n", *(bp + 1)); ap->wpa_ie.size = RSN_IE_BODY_MAX; } @@ -311,7 +311,7 @@ int get_ap_information(struct ks_wlan_private *priv, struct ap_info_t *ap_info, case 47: /* Reserve ID 47 Broadcom AP */ break; default: - DPRINTK(4, "unknown Element ID=%d \n", *bp); + DPRINTK(4, "unknown Element ID=%d\n", *bp); break; } offset += 2; /* id & size field */ @@ -408,7 +408,7 @@ void hostif_data_indication(struct ks_wlan_private *priv) HZ >= 60) { mic_failure->failure = 0; } - DPRINTK(4, "MIC FAILURE \n"); + DPRINTK(4, "MIC FAILURE\n"); if (mic_failure->failure == 0) { mic_failure->failure = 1; mic_failure->counter = 0; @@ -1150,7 +1150,7 @@ int hostif_data_request(struct ks_wlan_private *priv, struct sk_buff *packet) packet_len = packet->len; if (packet_len > ETH_FRAME_LEN) { - DPRINTK(1, "bad length packet_len=%d \n", packet_len); + DPRINTK(1, "bad length packet_len=%d\n", packet_len); dev_kfree_skb(packet); return -1; } @@ -1447,7 +1447,7 @@ void hostif_infrastructure_set_request(struct ks_wlan_private *priv) struct hostif_infrastructure_set_request_t *pp; uint16_t capability; - DPRINTK(3, "ssid.size=%d \n", priv->reg.ssid.size); + DPRINTK(3, "ssid.size=%d\n", priv->reg.ssid.size); /* make primitive */ pp = (struct hostif_infrastructure_set_request_t *) @@ -1514,7 +1514,7 @@ static void hostif_infrastructure_set2_request(struct ks_wlan_private *priv) struct hostif_infrastructure_set2_request_t *pp; uint16_t capability; - DPRINTK(2, "ssid.size=%d \n", priv->reg.ssid.size); + DPRINTK(2, "ssid.size=%d\n", priv->reg.ssid.size); /* make primitive */ pp = (struct hostif_infrastructure_set2_request_t *) @@ -1759,7 +1759,7 @@ void hostif_sleep_request(struct ks_wlan_private *priv, unsigned long mode) { struct hostif_sleep_request_t *pp; - DPRINTK(3, "mode=%lu \n", mode); + DPRINTK(3, "mode=%lu\n", mode); if (mode == SLP_SLEEP) { /* make primitive */ @@ -1783,7 +1783,7 @@ void hostif_sleep_request(struct ks_wlan_private *priv, unsigned long mode) queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq, &priv->ks_wlan_hw.rw_wq, 1); } else { - DPRINTK(3, "invalid mode %ld \n", mode); + DPRINTK(3, "invalid mode %ld\n", mode); return; } } -- cgit v0.10.2 From a1a736df3a811241100737b90f21582742529cff Mon Sep 17 00:00:00 2001 From: sayli karnik <karniksayli1995@gmail.com> Date: Thu, 15 Sep 2016 14:08:22 +0530 Subject: staging: ks7010: Remove the explicit cast on kmalloc The assignment operator implicitly converts a void pointer to the type of the pointer it is assigned to. Hence an explicit cast on the result of the kmalloc function is not required. Signed-off-by: sayli karnik <karniksayli1995@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c index 76ba236..e3cc8ce 100644 --- a/drivers/staging/ks7010/ks_hostif.c +++ b/drivers/staging/ks7010/ks_hostif.c @@ -1174,9 +1174,8 @@ int hostif_data_request(struct ks_wlan_private *priv, struct sk_buff *packet) } DPRINTK(4, "skb_buff length=%d\n", packet_len); - pp = (struct hostif_data_request_t *) - kmalloc(hif_align_size(sizeof(*pp) + 6 + packet_len + 8), - KS_WLAN_MEM_FLAG); + pp = kmalloc(hif_align_size(sizeof(*pp) + 6 + packet_len + 8), + KS_WLAN_MEM_FLAG); if (!pp) { DPRINTK(3, "allocate memory failed..\n"); @@ -1317,8 +1316,7 @@ void hostif_mib_get_request(struct ks_wlan_private *priv, DPRINTK(3, "\n"); /* make primitive */ - pp = (struct hostif_mib_get_request_t *) - kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); + pp = kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; @@ -1348,8 +1346,7 @@ void hostif_mib_set_request(struct ks_wlan_private *priv, } /* make primitive */ - pp = (struct hostif_mib_set_request_t *) - kmalloc(hif_align_size(sizeof(*pp) + size), KS_WLAN_MEM_FLAG); + pp = kmalloc(hif_align_size(sizeof(*pp) + size), KS_WLAN_MEM_FLAG); if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; @@ -1378,8 +1375,7 @@ void hostif_start_request(struct ks_wlan_private *priv, unsigned char mode) DPRINTK(3, "\n"); /* make primitive */ - pp = (struct hostif_start_request_t *) - kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); + pp = kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; @@ -1406,8 +1402,7 @@ void hostif_ps_adhoc_set_request(struct ks_wlan_private *priv) DPRINTK(3, "\n"); /* make primitive */ - pp = (struct hostif_ps_adhoc_set_request_t *) - kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); + pp = kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; @@ -1450,8 +1445,7 @@ void hostif_infrastructure_set_request(struct ks_wlan_private *priv) DPRINTK(3, "ssid.size=%d\n", priv->reg.ssid.size); /* make primitive */ - pp = (struct hostif_infrastructure_set_request_t *) - kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); + pp = kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; @@ -1517,8 +1511,7 @@ static void hostif_infrastructure_set2_request(struct ks_wlan_private *priv) DPRINTK(2, "ssid.size=%d\n", priv->reg.ssid.size); /* make primitive */ - pp = (struct hostif_infrastructure_set2_request_t *) - kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); + pp = kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; @@ -1587,8 +1580,7 @@ void hostif_adhoc_set_request(struct ks_wlan_private *priv) DPRINTK(3, "\n"); /* make primitive */ - pp = (struct hostif_adhoc_set_request_t *) - kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); + pp = kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; @@ -1633,8 +1625,7 @@ void hostif_adhoc_set2_request(struct ks_wlan_private *priv) DPRINTK(3, "\n"); /* make primitive */ - pp = (struct hostif_adhoc_set2_request_t *) - kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); + pp = kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; @@ -1681,8 +1672,7 @@ void hostif_stop_request(struct ks_wlan_private *priv) DPRINTK(3, "\n"); /* make primitive */ - pp = (struct hostif_stop_request_t *) - kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); + pp = kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; @@ -1704,8 +1694,7 @@ void hostif_phy_information_request(struct ks_wlan_private *priv) DPRINTK(3, "\n"); /* make primitive */ - pp = (struct hostif_phy_information_request_t *) - kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); + pp = kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; @@ -1736,8 +1725,7 @@ void hostif_power_mngmt_request(struct ks_wlan_private *priv, DPRINTK(3, "mode=%lu wake_up=%lu receiveDTIMs=%lu\n", mode, wake_up, receiveDTIMs); /* make primitive */ - pp = (struct hostif_power_mngmt_request_t *) - kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); + pp = kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; @@ -1763,8 +1751,7 @@ void hostif_sleep_request(struct ks_wlan_private *priv, unsigned long mode) if (mode == SLP_SLEEP) { /* make primitive */ - pp = (struct hostif_sleep_request_t *) - kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); + pp = kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; @@ -1797,8 +1784,7 @@ void hostif_bss_scan_request(struct ks_wlan_private *priv, DPRINTK(2, "\n"); /* make primitive */ - pp = (struct hostif_bss_scan_request_t *) - kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); + pp = kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; @@ -1854,8 +1840,7 @@ void hostif_mic_failure_request(struct ks_wlan_private *priv, DPRINTK(3, "count=%d :: timer=%d\n", failure_count, timer); /* make primitive */ - pp = (struct hostif_mic_failure_request_t *) - kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); + pp = kmalloc(hif_align_size(sizeof(*pp)), KS_WLAN_MEM_FLAG); if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; -- cgit v0.10.2 From e30ed33d197ccabfb7b46a6b1354a2fdfb546c8f Mon Sep 17 00:00:00 2001 From: Wei Yongjun <weiyongjun1@huawei.com> Date: Thu, 15 Sep 2016 10:13:04 +0000 Subject: staging: ks7010: remove unused including <linux/version.h> Remove including <linux/version.h> that don't need it. Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks_wlan_net.c b/drivers/staging/ks7010/ks_wlan_net.c index a35325e..c17c45d 100644 --- a/drivers/staging/ks7010/ks_wlan_net.c +++ b/drivers/staging/ks7010/ks_wlan_net.c @@ -9,7 +9,6 @@ * published by the Free Software Foundation. */ -#include <linux/version.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/compiler.h> -- cgit v0.10.2 From 4db7c0bebdff87e1c81ed4fbafc65cddec109e3d Mon Sep 17 00:00:00 2001 From: Wei Yongjun <weiyongjun1@huawei.com> Date: Thu, 15 Sep 2016 10:12:05 +0000 Subject: staging: rtl8712: fix double lock bug in SetPSModeWorkItemCallback() Fix a double lock bug in SetPSModeWorkItemCallback(). Fixes: 5c2ba8b85e35 ("rtl8712: pwrctrl_priv: Replace semaphore lock with mutex") Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8712/rtl871x_pwrctrl.c b/drivers/staging/rtl8712/rtl871x_pwrctrl.c index 8f82d85..d464c13 100644 --- a/drivers/staging/rtl8712/rtl871x_pwrctrl.c +++ b/drivers/staging/rtl8712/rtl871x_pwrctrl.c @@ -145,7 +145,7 @@ static void SetPSModeWorkItemCallback(struct work_struct *work) mutex_lock(&pwrpriv->mutex_lock); if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) r8712_set_rpwm(padapter, PS_STATE_S4); - mutex_lock(&pwrpriv->mutex_lock); + mutex_unlock(&pwrpriv->mutex_lock); } } -- cgit v0.10.2 From e88e4463b9e1bae7c6701b82673d29ba281712e1 Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Wed, 14 Sep 2016 20:38:24 +0530 Subject: staging: dgnc: Fix lines over 80 characters This patch fixes the checkpatch.pl warning: Line over 80 characters. Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_neo.c b/drivers/staging/dgnc/dgnc_neo.c index 5ef5b3e..8cd408c 100644 --- a/drivers/staging/dgnc/dgnc_neo.c +++ b/drivers/staging/dgnc/dgnc_neo.c @@ -401,7 +401,9 @@ static inline void neo_parse_isr(struct dgnc_board *brd, uint port) /* Read data from uart -> queue */ neo_copy_data_from_uart_to_queue(ch); - /* Call our tty layer to enforce queue flow control if needed. */ + /* Call our tty layer to enforce queue + * flow control if needed. + */ spin_lock_irqsave(&ch->ch_lock, flags); dgnc_check_queue_flow_control(ch); spin_unlock_irqrestore(&ch->ch_lock, flags); @@ -424,7 +426,9 @@ static inline void neo_parse_isr(struct dgnc_board *brd, uint port) * one it was, so we can suspend or resume data flow. */ if (cause == UART_17158_XON_DETECT) { - /* Is output stopped right now, if so, resume it */ + /* Is output stopped right now, if so, + * resume it + */ if (brd->channels[port]->ch_flags & CH_STOP) { spin_lock_irqsave(&ch->ch_lock, flags); @@ -445,8 +449,9 @@ static inline void neo_parse_isr(struct dgnc_board *brd, uint port) if (isr & UART_17158_IIR_HWFLOW_STATE_CHANGE) { /* - * If we get here, this means the hardware is doing auto flow control. - * Check to see whether RTS/DTR or CTS/DSR caused this interrupt. + * If we get here, this means the hardware is + * doing auto flow control. Check to see whether + * RTS/DTR or CTS/DSR caused this interrupt. */ cause = readb(&ch->ch_neo_uart->mcr); /* Which pin is doing auto flow? RTS or DTR? */ @@ -653,7 +658,9 @@ static void neo_param(struct tty_struct *tty) 4800, 9600, 19200, 38400 } }; - /* Only use the TXPrint baud rate if the terminal unit is NOT open */ + /* Only use the TXPrint baud rate if the terminal unit + * is NOT open + */ if (!(ch->ch_tun.un_flags & UN_ISOPEN) && (un->un_type == DGNC_PRINT)) baud = C_BAUD(ch->ch_pun.un_tty) & 0xff; @@ -776,7 +783,9 @@ static void neo_param(struct tty_struct *tty) if (ch->ch_digi.digi_flags & CTSPACE || ch->ch_c_cflag & CRTSCTS) { neo_set_cts_flow_control(ch); } else if (ch->ch_c_iflag & IXON) { - /* If start/stop is set to disable, then we should disable flow control */ + /* If start/stop is set to disable, then we should + * disable flow control + */ if ((ch->ch_startc == _POSIX_VDISABLE) || (ch->ch_stopc == _POSIX_VDISABLE)) neo_set_no_output_flow_control(ch); @@ -789,7 +798,9 @@ static void neo_param(struct tty_struct *tty) if (ch->ch_digi.digi_flags & RTSPACE || ch->ch_c_cflag & CRTSCTS) { neo_set_rts_flow_control(ch); } else if (ch->ch_c_iflag & IXOFF) { - /* If start/stop is set to disable, then we should disable flow control */ + /* If start/stop is set to disable, then we should + * disable flow control + */ if ((ch->ch_startc == _POSIX_VDISABLE) || (ch->ch_stopc == _POSIX_VDISABLE)) neo_set_no_input_flow_control(ch); -- cgit v0.10.2 From bbac843d144cdabe0c63321a7e3325c62a0bb7a9 Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Thu, 15 Sep 2016 09:38:21 +0530 Subject: staging: dgnc: Fix long line and spelling mistake This patch fixes the checkpatch.pl warning: Line over 80 characters. Also, the word 'because' was spelled as 'Becuz' and has been corrected. Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_neo.c b/drivers/staging/dgnc/dgnc_neo.c index 8cd408c..e794056 100644 --- a/drivers/staging/dgnc/dgnc_neo.c +++ b/drivers/staging/dgnc/dgnc_neo.c @@ -107,7 +107,9 @@ static inline void neo_set_cts_flow_control(struct channel_t *ch) /* Turn off auto Xon flow control */ efr &= ~UART_17158_EFR_IXON; - /* Why? Becuz Exar's spec says we have to zero it out before setting it */ + /* Why? Because Exar's spec says we have to zero it + * out before setting it + */ writeb(0, &ch->ch_neo_uart->efr); /* Turn on UART enhanced bits */ @@ -143,7 +145,9 @@ static inline void neo_set_rts_flow_control(struct channel_t *ch) ier &= ~UART_17158_IER_XOFF; efr &= ~UART_17158_EFR_IXOFF; - /* Why? Becuz Exar's spec says we have to zero it out before setting it */ + /* Why? Because Exar's spec says we have to zero it + * out before setting it + */ writeb(0, &ch->ch_neo_uart->efr); /* Turn on UART enhanced bits */ @@ -181,7 +185,9 @@ static inline void neo_set_ixon_flow_control(struct channel_t *ch) /* Turn on auto Xon flow control */ efr |= (UART_17158_EFR_ECB | UART_17158_EFR_IXON); - /* Why? Becuz Exar's spec says we have to zero it out before setting it */ + /* Why? Because Exar's spec says we have to zero it + * out before setting it + */ writeb(0, &ch->ch_neo_uart->efr); /* Turn on UART enhanced bits */ @@ -219,7 +225,9 @@ static inline void neo_set_ixoff_flow_control(struct channel_t *ch) ier |= UART_17158_IER_XOFF; efr |= (UART_17158_EFR_ECB | UART_17158_EFR_IXOFF); - /* Why? Becuz Exar's spec says we have to zero it out before setting it */ + /* Why? Because Exar's spec says we have to zero it + * out before setting it + */ writeb(0, &ch->ch_neo_uart->efr); /* Turn on UART enhanced bits */ @@ -260,7 +268,9 @@ static inline void neo_set_no_input_flow_control(struct channel_t *ch) else efr &= ~(UART_17158_EFR_ECB | UART_17158_EFR_IXOFF); - /* Why? Becuz Exar's spec says we have to zero it out before setting it */ + /* Why? Because Exar's spec says we have to zero + * it out before setting it + */ writeb(0, &ch->ch_neo_uart->efr); /* Turn on UART enhanced bits */ @@ -298,7 +308,9 @@ static inline void neo_set_no_output_flow_control(struct channel_t *ch) else efr &= ~(UART_17158_EFR_ECB | UART_17158_EFR_IXON); - /* Why? Becuz Exar's spec says we have to zero it out before setting it */ + /* Why? Because Exar's spec says we have to zero it + * out before setting it + */ writeb(0, &ch->ch_neo_uart->efr); /* Turn on UART enhanced bits */ -- cgit v0.10.2 From 30fde3a91ce7c0ea61f1b672e256d574b53f132f Mon Sep 17 00:00:00 2001 From: Bhumika Goyal <bhumirks@gmail.com> Date: Thu, 15 Sep 2016 19:47:18 +0530 Subject: Staging: netlogic: Remove unused function The function xlr_wakeup_queue is not used anywhere in the kernel. Therefore, remove it. The static unused functions were detected using Coccinelle but the change was done by hand. Script used: @initialize:python@ @@ def display(name,p): print(name,p[0].file) @r1@ identifier func; type T; position p; @@ static T func@p(...) { ... } @r@ identifier r1.func; @@ func @script:python depends on !r@ func << r1.func; p << r1.p; @@ display(func,p) Signed-off-by: Bhumika Goyal <bhumirks@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/netlogic/xlr_net.c b/drivers/staging/netlogic/xlr_net.c index 7db88aa..552a7dc 100644 --- a/drivers/staging/netlogic/xlr_net.c +++ b/drivers/staging/netlogic/xlr_net.c @@ -269,16 +269,6 @@ static void xlr_make_tx_desc(struct nlm_fmn_msg *msg, unsigned long addr, msg->msg3 = 0; } -static void __maybe_unused xlr_wakeup_queue(unsigned long dev) -{ - struct net_device *ndev = (struct net_device *)dev; - struct xlr_net_priv *priv = netdev_priv(ndev); - struct phy_device *phydev = xlr_get_phydev(priv); - - if (phydev->link) - netif_tx_wake_queue(netdev_get_tx_queue(ndev, priv->wakeup_q)); -} - static netdev_tx_t xlr_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) { -- cgit v0.10.2 From 49288a345b3df3d8b4212856cb1e056227cc3653 Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Wed, 14 Sep 2016 21:43:04 +0530 Subject: staging: gdm724x: Remove unnecessary blank line This patch fixes the checkpatch.pl warning: CHECK: Please don't use multiple blank lines Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/gdm724x/hci_packet.h b/drivers/staging/gdm724x/hci_packet.h index dbc4446..4644f84 100644 --- a/drivers/staging/gdm724x/hci_packet.h +++ b/drivers/staging/gdm724x/hci_packet.h @@ -89,5 +89,4 @@ struct hci_connect_ind { u32 connect; } __packed; - #endif /* _HCI_PACKET_H_ */ -- cgit v0.10.2 From d5102ad4d61881671a804c379c59052b89da4fd0 Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Wed, 14 Sep 2016 22:14:56 +0530 Subject: staging: gs_fpgaboot: Remove FSF address from GPL notice This patch fixes the checkpatch.pl warning: CHECK: Do not include the paragraph about writing to the Free Software Foundation's mailing address from the sample GPL notice. The FSF has changed addresses in the past, and may do so again. Linux already includes a copy of the GPL. Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/gs_fpgaboot/gs_fpgaboot.c b/drivers/staging/gs_fpgaboot/gs_fpgaboot.c index a221f26..8ed4d39 100644 --- a/drivers/staging/gs_fpgaboot/gs_fpgaboot.c +++ b/drivers/staging/gs_fpgaboot/gs_fpgaboot.c @@ -8,10 +8,6 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <linux/kernel.h> diff --git a/drivers/staging/gs_fpgaboot/gs_fpgaboot.h b/drivers/staging/gs_fpgaboot/gs_fpgaboot.h index 8cc3255..7b8cc3a 100644 --- a/drivers/staging/gs_fpgaboot/gs_fpgaboot.h +++ b/drivers/staging/gs_fpgaboot/gs_fpgaboot.h @@ -7,12 +7,7 @@ * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <linux/firmware.h> -- cgit v0.10.2 From 190b95170daa713fbd1a8ad53e266aa1139678be Mon Sep 17 00:00:00 2001 From: Anchal Jain <anchalj109@gmail.com> Date: Wed, 14 Sep 2016 23:38:04 +0530 Subject: staging: emxx_udc: Fix unsigned int to bare use of unsigned This is a patch to fixes up a WARNING: Prefer 'unsigned int' to bare use of 'unsigned' found by the checkpatch.pl tool Signed-off-by: Anchal Jain <anchalj109@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/emxx_udc/emxx_udc.h b/drivers/staging/emxx_udc/emxx_udc.h index 39769e3..789bfb9 100644 --- a/drivers/staging/emxx_udc/emxx_udc.h +++ b/drivers/staging/emxx_udc/emxx_udc.h @@ -586,7 +586,7 @@ struct nbu2ss_udc { unsigned remote_wakeup:1; unsigned udc_enabled:1; - unsigned mA; + unsigned int mA; u32 curr_config; /* Current Configuration Number */ -- cgit v0.10.2 From 3428e918e25611a08842b37b352ccb1960fbe012 Mon Sep 17 00:00:00 2001 From: Gargi Sharma <gs051095@gmail.com> Date: Fri, 16 Sep 2016 01:44:14 +0530 Subject: staging: emxx_udc: add braces to if-else block add braces to if/else clause to fix the checkpatch issue braces {} should be used on all arms of if/else block. Does not affect flow because only single statement inside if/else block. Signed-off-by: Gargi Sharma <gs051095@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/emxx_udc/emxx_udc.c b/drivers/staging/emxx_udc/emxx_udc.c index f6233ec..c3e2988 100644 --- a/drivers/staging/emxx_udc/emxx_udc.c +++ b/drivers/staging/emxx_udc/emxx_udc.c @@ -477,9 +477,9 @@ static void _nbu2ss_dma_map_single( ) { if (req->req.dma == DMA_ADDR_INVALID) { - if (req->unaligned) + if (req->unaligned) { req->req.dma = ep->phys_buf; - else { + } else { req->req.dma = dma_map_single( udc->gadget.dev.parent, req->req.buf, @@ -1235,9 +1235,9 @@ static int _nbu2ss_start_transfer( req->dma_flag = FALSE; req->div_len = 0; - if (req->req.length == 0) + if (req->req.length == 0) { req->zero = false; - else { + } else { if ((req->req.length % ep->ep.maxpacket) == 0) req->zero = req->req.zero; else @@ -1940,9 +1940,9 @@ static void _nbu2ss_ep_done( if (likely(req->req.status == -EINPROGRESS)) req->req.status = status; - if (ep->stalled) + if (ep->stalled) { _nbu2ss_epn_set_stall(udc, ep); - else { + } else { if (!list_empty(&ep->queue)) _nbu2ss_restert_transfer(ep); } @@ -2473,8 +2473,9 @@ static irqreturn_t _nbu2ss_udc_irq(int irq, void *_udc) _nbu2ss_writel(&preg->USB_INT_STA, ~USB_INT_STA_RW); _nbu2ss_writel(&preg->USB_INT_ENA, 0); status = 0; - } else + } else { status = _nbu2ss_readl(&preg->USB_INT_STA); + } if (status == 0) break; -- cgit v0.10.2 From 29b7d5817bd2795454739226f517fc2b47eb2b51 Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Fri, 16 Sep 2016 01:11:08 +0530 Subject: staging: lustre: Remove unnecessary return capture Instead of storing the return value of a function call into a variable and then returning it, we can club the two into a single return statement. This change was made using the following semantic patch by Coccinelle: @@ local idexpression ret; expression e; @@ -ret = +return e; -return ret; Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 5bf95f9..cf94926 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -2488,9 +2488,8 @@ static int mdc_set_info_async(const struct lu_env *env, } spin_unlock(&imp->imp_lock); - rc = do_set_info_async(imp, MDS_SET_INFO, LUSTRE_MDS_VERSION, - keylen, key, vallen, val, set); - return rc; + return do_set_info_async(imp, MDS_SET_INFO, LUSTRE_MDS_VERSION, + keylen, key, vallen, val, set); } if (KEY_IS(KEY_SPTLRPC_CONF)) { sptlrpc_conf_client_adapt(exp->exp_obd); -- cgit v0.10.2 From 299ac44422fbe7ff23ff1f01667cfe87bc61c74a Mon Sep 17 00:00:00 2001 From: Wei Yongjun <weiyongjun1@huawei.com> Date: Thu, 15 Sep 2016 02:20:43 +0000 Subject: staging: android: ion: Fix return value check in hi6220_ion_probe() In case of error, the function ion_device_create() returns ERR_PTR() and never returns NULL. The NULL test in the return value check should be replaced with IS_ERR(). Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com> Reviewed-by: Sumit Semwal <sumit.semwal@linaro.org> Acked-by: Laura Abbott <labbott@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/hisilicon/hi6220_ion.c b/drivers/staging/android/ion/hisilicon/hi6220_ion.c index f392db2..659aa71 100644 --- a/drivers/staging/android/ion/hisilicon/hi6220_ion.c +++ b/drivers/staging/android/ion/hisilicon/hi6220_ion.c @@ -49,8 +49,8 @@ static int hi6220_ion_probe(struct platform_device *pdev) platform_set_drvdata(pdev, ipdev); ipdev->idev = ion_device_create(NULL); - if (!ipdev->idev) - return -ENOMEM; + if (IS_ERR(ipdev->idev)) + return PTR_ERR(ipdev->idev); ipdev->data = ion_parse_dt(pdev, hisi_heaps); if (IS_ERR(ipdev->data)) -- cgit v0.10.2 From 4a236d01b5e0d7e6f4ee9e6c4056fce10b38e8ad Mon Sep 17 00:00:00 2001 From: Arnd Bergmann <arnd@arndb.de> Date: Thu, 15 Sep 2016 17:57:40 +0200 Subject: staging: android ion/hisi: fix dependencies The newly added Hi6220 Ion code fails to build when the ION_OF helpers are not present: drivers/staging/android/ion/hisilicon/hi6220_ion.o: In function `hi6220_ion_remove': hi6220_ion.c:(.text.hi6220_ion_remove+0x4c): undefined reference to `ion_destroy_platform_data' drivers/staging/android/ion/hisilicon/hi6220_ion.o: In function `hi6220_ion_probe': hi6220_ion.c:(.text.hi6220_ion_probe+0x5c): undefined reference to `ion_parse_dt' hi6220_ion.c:(.text.hi6220_ion_probe+0xf8): undefined reference to `ion_destroy_platform_data' This selects the symbol when needed. Fixes: 2b40182a19bc ("staging: android: ion: Add ion driver for Hi6220 SoC platform") Signed-off-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Laura Abbott <labbott@redhat.com> Reviewed-by: Sumit Semwal <sumit.semwal@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig index 9410554..c8fb413 100644 --- a/drivers/staging/android/ion/Kconfig +++ b/drivers/staging/android/ion/Kconfig @@ -36,6 +36,7 @@ config ION_TEGRA config ION_HISI tristate "Ion for Hisilicon" depends on ARCH_HISI && ION + select ION_OF help Choose this option if you wish to use ion on Hisilicon Platform. -- cgit v0.10.2 From 9f4feef54d97529c095f27f131f2ae6a254645fd Mon Sep 17 00:00:00 2001 From: Wei Yongjun <weiyongjun1@huawei.com> Date: Thu, 15 Sep 2016 02:27:04 +0000 Subject: staging: fsl-mc: use list_del_init instead of list_del/INIT_LIST_HEAD Using list_del_init() instead of list_del() + INIT_LIST_HEAD(). Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com> Acked-by: Stuart Yoder <stuart.yoder@nxp.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c index 2004fa7..1e06d28 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c @@ -142,8 +142,7 @@ static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device goto out_unlock; } - list_del(&resource->node); - INIT_LIST_HEAD(&resource->node); + list_del_init(&resource->node); res_pool->free_count--; res_pool->max_count--; @@ -220,8 +219,7 @@ int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, res_pool->free_count > res_pool->max_count)) goto out_unlock; - list_del(&resource->node); - INIT_LIST_HEAD(&resource->node); + list_del_init(&resource->node); res_pool->free_count--; error = 0; -- cgit v0.10.2 From 053ead220203d3e742d8345d411ebb166f2aa6b4 Mon Sep 17 00:00:00 2001 From: Wei Yongjun <weiyongjun1@huawei.com> Date: Thu, 15 Sep 2016 02:27:27 +0000 Subject: staging: fsl-mc: remove .owner field for driver Remove .owner field if calls are used which set it automatically. Generated by: scripts/coccinelle/api/platform_no_drv_owner.cocci Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com> Acked-by: Stuart Yoder <stuart.yoder@nxp.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c index 1e06d28..e93ab53 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c @@ -650,7 +650,6 @@ static const struct fsl_mc_device_id match_id_table[] = { static struct fsl_mc_driver fsl_mc_allocator_driver = { .driver = { .name = "fsl_mc_allocator", - .owner = THIS_MODULE, .pm = NULL, }, .match_id_table = match_id_table, -- cgit v0.10.2 From 132aba090d2dd98adb45c8f8cc38e21ccbfb98b3 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Thu, 15 Sep 2016 20:51:24 +0200 Subject: staging: rts5208: make some vars to lower case to keep the style consistent This patch fixes the checkpatch.pl warning: WARNING: Comparisons should place the constant on the right side of the test Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rts5208/rtsx_card.c b/drivers/staging/rts5208/rtsx_card.c index 9a5cd63..91e62c1 100644 --- a/drivers/staging/rts5208/rtsx_card.c +++ b/drivers/staging/rts5208/rtsx_card.c @@ -631,21 +631,21 @@ void rtsx_init_cards(struct rtsx_chip *chip) int switch_ssc_clock(struct rtsx_chip *chip, int clk) { int retval; - u8 N = (u8)(clk - 2), min_N, max_N; + u8 n = (u8)(clk - 2), min_n, max_n; u8 mcu_cnt, div, max_div, ssc_depth, ssc_depth_mask; int sd_vpclk_phase_reset = 0; if (chip->cur_clk == clk) return STATUS_SUCCESS; - min_N = 60; - max_N = 120; + min_n = 60; + max_n = 120; max_div = CLK_DIV_4; dev_dbg(rtsx_dev(chip), "Switch SSC clock to %dMHz (cur_clk = %d)\n", clk, chip->cur_clk); - if ((clk <= 2) || (N > max_N)) { + if ((clk <= 2) || (n > max_n)) { rtsx_trace(chip); return STATUS_FAIL; } @@ -655,15 +655,15 @@ int switch_ssc_clock(struct rtsx_chip *chip, int clk) mcu_cnt = 7; div = CLK_DIV_1; - while ((N < min_N) && (div < max_div)) { - N = (N + 2) * 2 - 2; + while ((n < min_n) && (div < max_div)) { + n = (n + 2) * 2 - 2; div++; } - dev_dbg(rtsx_dev(chip), "N = %d, div = %d\n", N, div); + dev_dbg(rtsx_dev(chip), "n = %d, div = %d\n", n, div); if (chip->ssc_en) { ssc_depth = 0x01; - N -= 2; + n -= 2; } else { ssc_depth = 0; } @@ -677,7 +677,7 @@ int switch_ssc_clock(struct rtsx_chip *chip, int clk) rtsx_add_cmd(chip, WRITE_REG_CMD, CLK_DIV, 0xFF, (div << 4) | mcu_cnt); rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, 0); rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL2, ssc_depth_mask, ssc_depth); - rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_DIV_N_0, 0xFF, N); + rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_DIV_N_0, 0xFF, n); rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, SSC_RSTB); if (sd_vpclk_phase_reset) { rtsx_add_cmd(chip, WRITE_REG_CMD, SD_VPCLK0_CTL, -- cgit v0.10.2 From 52edd01ffdc094465906f34ba78aec0bc0f2eedc Mon Sep 17 00:00:00 2001 From: Gargi Sharma <gs051095@gmail.com> Date: Fri, 16 Sep 2016 00:07:51 +0530 Subject: staging: octeon: remove multiple blank lines Fixes the checkpatch issue Please don't use multiple blank lines. Signed-off-by: Gargi Sharma <gs051095@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index 790477c..d02e3e3 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -694,7 +694,6 @@ static int cvm_oct_probe(struct platform_device *pdev) return -EINVAL; } - cvm_oct_configure_common_hw(); cvmx_helper_initialize_packet_io_global(); @@ -937,7 +936,6 @@ static int cvm_oct_remove(struct platform_device *pdev) } } - cvmx_pko_shutdown(); cvmx_ipd_free_ptr(); -- cgit v0.10.2 From 521865a8c9a8d4a189355339457d96b62699eb35 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal <bhumirks@gmail.com> Date: Fri, 16 Sep 2016 02:09:08 +0530 Subject: Staging: comedi: s626: Remove all unused functions Remove all #ifdef'ed static functions as they are not used anywhere in the kernel. Some functions were detected using Coccinelle but removed by hand and some were removed as the functions in which they were getting used were also unused functions. Script: @initialize:python@ @@ def display(name,p): print(name,p[0].file) @r1@ identifier func; type T; position p; @@ static T func@p(...) { ... } @r@ identifier r1.func; @@ func @script:python depends on !r@ func << r1.func; p << r1.p; @@ display(func,p) Signed-off-by: Bhumika Goyal <bhumirks@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index 6d89ca0..c14a025 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -697,134 +697,6 @@ static void s626_reset_cap_flags(struct comedi_device *dev, s626_debi_replace(dev, S626_LP_CRB(chan), ~S626_CRBMSK_INTCTRL, set); } -#ifdef unused -/* - * Return counter setup in a format (COUNTER_SETUP) that is consistent - * for both A and B counters. - */ -static uint16_t s626_get_mode_a(struct comedi_device *dev, - unsigned int chan) -{ - uint16_t cra; - uint16_t crb; - uint16_t setup; - unsigned int cntsrc, clkmult, clkpol, encmode; - - /* Fetch CRA and CRB register images. */ - cra = s626_debi_read(dev, S626_LP_CRA(chan)); - crb = s626_debi_read(dev, S626_LP_CRB(chan)); - - /* - * Populate the standardized counter setup bit fields. - */ - setup = - /* LoadSrc = LoadSrcA. */ - S626_SET_STD_LOADSRC(S626_GET_CRA_LOADSRC_A(cra)) | - /* LatchSrc = LatchSrcA. */ - S626_SET_STD_LATCHSRC(S626_GET_CRB_LATCHSRC(crb)) | - /* IntSrc = IntSrcA. */ - S626_SET_STD_INTSRC(S626_GET_CRA_INTSRC_A(cra)) | - /* IndxSrc = IndxSrcA. */ - S626_SET_STD_INDXSRC(S626_GET_CRA_INDXSRC_A(cra)) | - /* IndxPol = IndxPolA. */ - S626_SET_STD_INDXPOL(S626_GET_CRA_INDXPOL_A(cra)) | - /* ClkEnab = ClkEnabA. */ - S626_SET_STD_CLKENAB(S626_GET_CRB_CLKENAB_A(crb)); - - /* Adjust mode-dependent parameters. */ - cntsrc = S626_GET_CRA_CNTSRC_A(cra); - if (cntsrc & S626_CNTSRC_SYSCLK) { - /* Timer mode (CntSrcA<1> == 1): */ - encmode = S626_ENCMODE_TIMER; - /* Set ClkPol to indicate count direction (CntSrcA<0>). */ - clkpol = cntsrc & 1; - /* ClkMult must be 1x in Timer mode. */ - clkmult = S626_CLKMULT_1X; - } else { - /* Counter mode (CntSrcA<1> == 0): */ - encmode = S626_ENCMODE_COUNTER; - /* Pass through ClkPol. */ - clkpol = S626_GET_CRA_CLKPOL_A(cra); - /* Force ClkMult to 1x if not legal, else pass through. */ - clkmult = S626_GET_CRA_CLKMULT_A(cra); - if (clkmult == S626_CLKMULT_SPECIAL) - clkmult = S626_CLKMULT_1X; - } - setup |= S626_SET_STD_ENCMODE(encmode) | S626_SET_STD_CLKMULT(clkmult) | - S626_SET_STD_CLKPOL(clkpol); - - /* Return adjusted counter setup. */ - return setup; -} - -static uint16_t s626_get_mode_b(struct comedi_device *dev, - unsigned int chan) -{ - uint16_t cra; - uint16_t crb; - uint16_t setup; - unsigned int cntsrc, clkmult, clkpol, encmode; - - /* Fetch CRA and CRB register images. */ - cra = s626_debi_read(dev, S626_LP_CRA(chan)); - crb = s626_debi_read(dev, S626_LP_CRB(chan)); - - /* - * Populate the standardized counter setup bit fields. - */ - setup = - /* IntSrc = IntSrcB. */ - S626_SET_STD_INTSRC(S626_GET_CRB_INTSRC_B(crb)) | - /* LatchSrc = LatchSrcB. */ - S626_SET_STD_LATCHSRC(S626_GET_CRB_LATCHSRC(crb)) | - /* LoadSrc = LoadSrcB. */ - S626_SET_STD_LOADSRC(S626_GET_CRB_LOADSRC_B(crb)) | - /* IndxPol = IndxPolB. */ - S626_SET_STD_INDXPOL(S626_GET_CRB_INDXPOL_B(crb)) | - /* ClkEnab = ClkEnabB. */ - S626_SET_STD_CLKENAB(S626_GET_CRB_CLKENAB_B(crb)) | - /* IndxSrc = IndxSrcB. */ - S626_SET_STD_INDXSRC(S626_GET_CRA_INDXSRC_B(cra)); - - /* Adjust mode-dependent parameters. */ - cntsrc = S626_GET_CRA_CNTSRC_B(cra); - clkmult = S626_GET_CRB_CLKMULT_B(crb); - if (clkmult == S626_CLKMULT_SPECIAL) { - /* Extender mode (ClkMultB == S626_CLKMULT_SPECIAL): */ - encmode = S626_ENCMODE_EXTENDER; - /* Indicate multiplier is 1x. */ - clkmult = S626_CLKMULT_1X; - /* Set ClkPol equal to Timer count direction (CntSrcB<0>). */ - clkpol = cntsrc & 1; - } else if (cntsrc & S626_CNTSRC_SYSCLK) { - /* Timer mode (CntSrcB<1> == 1): */ - encmode = S626_ENCMODE_TIMER; - /* Indicate multiplier is 1x. */ - clkmult = S626_CLKMULT_1X; - /* Set ClkPol equal to Timer count direction (CntSrcB<0>). */ - clkpol = cntsrc & 1; - } else { - /* If Counter mode (CntSrcB<1> == 0): */ - encmode = S626_ENCMODE_COUNTER; - /* Clock multiplier is passed through. */ - /* Clock polarity is passed through. */ - clkpol = S626_GET_CRB_CLKPOL_B(crb); - } - setup |= S626_SET_STD_ENCMODE(encmode) | S626_SET_STD_CLKMULT(clkmult) | - S626_SET_STD_CLKPOL(clkpol); - - /* Return adjusted counter setup. */ - return setup; -} - -static uint16_t s626_get_mode(struct comedi_device *dev, - unsigned int chan) -{ - return (chan < 3) ? s626_get_mode_a(dev, chan) - : s626_get_mode_b(dev, chan); -} -#endif - /* * Set the operating mode for the specified counter. The setup * parameter is treated as a COUNTER_SETUP data type. The following @@ -1023,25 +895,6 @@ static void s626_set_enable(struct comedi_device *dev, s626_debi_replace(dev, S626_LP_CRB(chan), ~mask, set); } -#ifdef unused -static uint16_t s626_get_enable(struct comedi_device *dev, - unsigned int chan) -{ - uint16_t crb = s626_debi_read(dev, S626_LP_CRB(chan)); - - return (chan < 3) ? S626_GET_CRB_CLKENAB_A(crb) - : S626_GET_CRB_CLKENAB_B(crb); -} -#endif - -#ifdef unused -static uint16_t s626_get_latch_source(struct comedi_device *dev, - unsigned int chan) -{ - return S626_GET_CRB_LATCHSRC(s626_debi_read(dev, S626_LP_CRB(chan))); -} -#endif - /* * Return/set the event that will trigger transfer of the preload * register into the counter. 0=ThisCntr_Index, 1=ThisCntr_Overflow, @@ -1066,19 +919,6 @@ static void s626_set_load_trig(struct comedi_device *dev, s626_debi_replace(dev, reg, ~mask, set); } -#ifdef unused -static uint16_t s626_get_load_trig(struct comedi_device *dev, - unsigned int chan) -{ - if (chan < 3) - return S626_GET_CRA_LOADSRC_A(s626_debi_read(dev, - S626_LP_CRA(chan))); - else - return S626_GET_CRB_LOADSRC_B(s626_debi_read(dev, - S626_LP_CRB(chan))); -} -#endif - /* * Return/set counter interrupt source and clear any captured * index/overflow events. int_source: 0=Disabled, 1=OverflowOnly, @@ -1138,93 +978,6 @@ static void s626_set_int_src(struct comedi_device *dev, } } -#ifdef unused -static uint16_t s626_get_int_src(struct comedi_device *dev, - unsigned int chan) -{ - if (chan < 3) - return S626_GET_CRA_INTSRC_A(s626_debi_read(dev, - S626_LP_CRA(chan))); - else - return S626_GET_CRB_INTSRC_B(s626_debi_read(dev, - S626_LP_CRB(chan))); -} -#endif - -#ifdef unused -/* - * Return/set the clock multiplier. - */ -static void s626_set_clk_mult(struct comedi_device *dev, - unsigned int chan, uint16_t value) -{ - uint16_t mode; - - mode = s626_get_mode(dev, chan); - mode &= ~S626_STDMSK_CLKMULT; - mode |= S626_SET_STD_CLKMULT(value); - - s626_set_mode(dev, chan, mode, false); -} - -/* - * Return/set the clock polarity. - */ -static void s626_set_clk_pol(struct comedi_device *dev, - unsigned int chan, uint16_t value) -{ - uint16_t mode; - - mode = s626_get_mode(dev, chan); - mode &= ~S626_STDMSK_CLKPOL; - mode |= S626_SET_STD_CLKPOL(value); - - s626_set_mode(dev, chan, mode, false); -} - -/* - * Return/set the encoder mode. - */ -static void s626_set_enc_mode(struct comedi_device *dev, - unsigned int chan, uint16_t value) -{ - uint16_t mode; - - mode = s626_get_mode(dev, chan); - mode &= ~S626_STDMSK_ENCMODE; - mode |= S626_SET_STD_ENCMODE(value); - - s626_set_mode(dev, chan, mode, false); -} - -static uint16_t s626_get_index_pol(struct comedi_device *dev, - unsigned int chan) -{ - return S626_GET_STD_INDXPOL(s626_get_mode(dev, chan)); -} - -/* - * Return/set the index source. - */ -static void s626_set_index_src(struct comedi_device *dev, - unsigned int chan, uint16_t value) -{ - uint16_t mode; - - mode = s626_get_mode(dev, chan); - mode &= ~S626_STDMSK_INDXSRC; - mode |= S626_SET_STD_INDXSRC(value != 0); - - s626_set_mode(dev, chan, mode, false); -} - -static uint16_t s626_get_index_src(struct comedi_device *dev, - unsigned int chan) -{ - return S626_GET_STD_INDXSRC(s626_get_mode(dev, chan)); -} -#endif - /* * Generate an index pulse. */ @@ -1717,43 +1470,6 @@ static void s626_reset_adc(struct comedi_device *dev, uint8_t *ppl) /* End of RPS program build */ } -#ifdef unused_code -static int s626_ai_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct s626_private *devpriv = dev->private; - uint8_t i; - int32_t *readaddr; - - /* Trigger ADC scan loop start */ - s626_mc_enable(dev, S626_MC2_ADC_RPS, S626_P_MC2); - - /* Wait until ADC scan loop is finished (RPS Signal 0 reset) */ - while (s626_mc_test(dev, S626_MC2_ADC_RPS, S626_P_MC2)) - ; - - /* - * Init ptr to DMA buffer that holds new ADC data. We skip the - * first uint16_t in the buffer because it contains junk data from - * the final ADC of the previous poll list scan. - */ - readaddr = (uint32_t *)devpriv->ana_buf.logical_base + 1; - - /* - * Convert ADC data to 16-bit integer values and - * copy to application buffer. - */ - for (i = 0; i < devpriv->adc_items; i++) { - *data = s626_ai_reg_to_uint(*readaddr++); - data++; - } - - return i; -} -#endif - static int s626_ai_eoc(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, -- cgit v0.10.2 From 13bfbf0edce13bb61adff5fd2b8052c262ba75f4 Mon Sep 17 00:00:00 2001 From: Gargi Sharma <gs051095@gmail.com> Date: Fri, 16 Sep 2016 00:37:09 +0530 Subject: staging: xgifb: move AND operator for logical continuation Move && up to the previous line, to fix the checkpatch issue Logical continuations should be on the previous line. Signed-off-by: Gargi Sharma <gs051095@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 50c8ea4..316209f 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -1741,8 +1741,8 @@ static void XGI_SetCRT2ECLK(unsigned short ModeIdIndex, for (i = 0; i < 4; i++) { xgifb_reg_and_or(pVBInfo->P3d4, 0x31, ~0x30, (unsigned short) (0x10 * i)); - if ((!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) - && (!(pVBInfo->VBInfo & SetInSlaveMode))) { + if ((!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) && + (!(pVBInfo->VBInfo & SetInSlaveMode))) { xgifb_reg_set(pVBInfo->P3c4, 0x2e, di_0); xgifb_reg_set(pVBInfo->P3c4, 0x2f, di_1); } else { @@ -4141,8 +4141,8 @@ static void XGI_SetGroup4(unsigned short ModeIdIndex, | TVSetYPbPr525p | TVSetYPbPr750p | TVSetHiVision))) { temp |= 0x0001; - if ((pVBInfo->VBInfo & SetInSlaveMode) - && (!(pVBInfo->TVInfo + if ((pVBInfo->VBInfo & SetInSlaveMode) && + (!(pVBInfo->TVInfo & TVSimuMode))) temp &= (~0x0001); } -- cgit v0.10.2 From aa18660f62a7013683204fbfd66254f056474054 Mon Sep 17 00:00:00 2001 From: Gargi Sharma <gs051095@gmail.com> Date: Fri, 16 Sep 2016 00:37:10 +0530 Subject: staging: xgifb: remove unnecessary parentheses ! has higher priority than && or ||, so remove parentheses around ! expressions to make the code more readable. Signed-off-by: Gargi Sharma <gs051095@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 316209f..af3f4d0 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -214,7 +214,7 @@ static unsigned char XGI_AjustCRT2Rate(unsigned short ModeIdIndex, if (!(pVBInfo->VBInfo & TVSetPAL) && (modeflag & NoSupportSimuTV) && (pVBInfo->VBInfo & SetInSlaveMode) && - (!(pVBInfo->VBInfo & SetNotSimuMode))) + !(pVBInfo->VBInfo & SetNotSimuMode)) return 0; } @@ -1655,7 +1655,7 @@ static unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex, modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag; if ((pVBInfo->SetFlag & ProgrammingCRT2) && - (!(pVBInfo->LCDInfo & EnableScalingLCD))) { /* {LCDA/LCDB} */ + !(pVBInfo->LCDInfo & EnableScalingLCD)) { /* {LCDA/LCDB} */ index = XGI_GetLCDCapPtr(pVBInfo); tempal = pVBInfo->LCDCapList[index].LCD_VCLK; @@ -1716,7 +1716,7 @@ static void XGI_GetVCLKLen(unsigned char tempal, unsigned char *di_0, { if (pVBInfo->VBType & (VB_SIS301 | VB_SIS301B | VB_SIS302B | VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) { - if ((!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) && + if (!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) && (pVBInfo->SetFlag & ProgrammingCRT2)) { *di_0 = XGI_VBVCLKData[tempal].Part4_A; *di_1 = XGI_VBVCLKData[tempal].Part4_B; @@ -1741,8 +1741,8 @@ static void XGI_SetCRT2ECLK(unsigned short ModeIdIndex, for (i = 0; i < 4; i++) { xgifb_reg_and_or(pVBInfo->P3d4, 0x31, ~0x30, (unsigned short) (0x10 * i)); - if ((!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) && - (!(pVBInfo->VBInfo & SetInSlaveMode))) { + if (!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) && + !(pVBInfo->VBInfo & SetInSlaveMode)) { xgifb_reg_set(pVBInfo->P3c4, 0x2e, di_0); xgifb_reg_set(pVBInfo->P3c4, 0x2f, di_1); } else { @@ -1986,7 +1986,7 @@ static void XGI_GetVBInfo(unsigned short ModeIdIndex, } if (!(tempbx & DisableCRT2Display)) { - if ((!(tempbx & DriverMode)) || (!(modeflag & CRT2Mode))) { + if (!(tempbx & DriverMode) || !(modeflag & CRT2Mode)) { if (!(tempbx & XGI_SetCRT2ToLCDA)) tempbx |= (SetInSlaveMode | SetSimuScanMode); } @@ -2132,7 +2132,7 @@ static unsigned char XGI_GetLCDInfo(unsigned short ModeIdIndex, if ((pVBInfo->LCDResInfo == Panel_1400x1050) && (pVBInfo->VBInfo & SetCRT2ToLCD) && (resinfo == 9) && - (!(tempbx & EnableScalingLCD))) + !(tempbx & EnableScalingLCD)) /* * set to center in 1280x1024 LCDB * for Panel_1400x1050 @@ -3922,7 +3922,7 @@ static void XGI_SetTap4Regs(struct vb_device_info *pVBInfo) xgifb_reg_set(pVBInfo->Part2Port, i, Tap4TimingPtr->Reg[j]); if ((pVBInfo->VBInfo & SetCRT2ToTV) && - (!(pVBInfo->VBInfo & SetCRT2ToHiVision))) { + !(pVBInfo->VBInfo & SetCRT2ToHiVision)) { /* Set Vertical Scaling */ Tap4TimingPtr = XGI_GetTap4Ptr(1, pVBInfo); for (i = 0xC0, j = 0; i < 0xFF; i++, j++) @@ -3932,7 +3932,7 @@ static void XGI_SetTap4Regs(struct vb_device_info *pVBInfo) } if ((pVBInfo->VBInfo & SetCRT2ToTV) && - (!(pVBInfo->VBInfo & SetCRT2ToHiVision))) + !(pVBInfo->VBInfo & SetCRT2ToHiVision)) /* Enable V.Scaling */ xgifb_reg_and_or(pVBInfo->Part2Port, 0x4E, ~0x14, 0x04); else @@ -4142,8 +4142,8 @@ static void XGI_SetGroup4(unsigned short ModeIdIndex, | TVSetHiVision))) { temp |= 0x0001; if ((pVBInfo->VBInfo & SetInSlaveMode) && - (!(pVBInfo->TVInfo - & TVSimuMode))) + !(pVBInfo->TVInfo + & TVSimuMode)) temp &= (~0x0001); } } @@ -4476,7 +4476,7 @@ static void XGI_DisableBridge(struct xgifb_video_info *xgifb_info, if ((pVBInfo->VBInfo & (DisableCRT2Display | SetSimuScanMode)) || - ((!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) && + (!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) && (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD | SetCRT2ToTV)))) xgifb_reg_or(pVBInfo->Part1Port, 0x00, 0x80); @@ -4587,7 +4587,7 @@ static void XGI_GetTVPtrIndex2(unsigned short *tempbx, unsigned char *tempcl, if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) { - if ((!(pVBInfo->VBInfo & SetInSlaveMode)) || (pVBInfo->TVInfo + if (!(pVBInfo->VBInfo & SetInSlaveMode) || (pVBInfo->TVInfo & TVSimuMode)) { *tempbx += 8; *tempcl += 1; @@ -4988,8 +4988,8 @@ reg_and_or: if (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { tempah &= (~0x08); - if ((pVBInfo->ModeType == ModeVGA) && (!(pVBInfo->VBInfo - & SetInSlaveMode))) { + if ((pVBInfo->ModeType == ModeVGA) && !(pVBInfo->VBInfo + & SetInSlaveMode)) { tempah |= 0x010; } tempah |= 0x080; @@ -5486,7 +5486,7 @@ unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info, XGI_DisableBridge(xgifb_info, HwDeviceExtension, pVBInfo); if (pVBInfo->VBInfo & (SetSimuScanMode | XGI_SetCRT2ToLCDA) || - (!(pVBInfo->VBInfo & SwitchCRT2))) { + !(pVBInfo->VBInfo & SwitchCRT2)) { XGI_SetCRT1Group(xgifb_info, HwDeviceExtension, ModeNo, ModeIdIndex, pVBInfo); -- cgit v0.10.2 From 909bb2b41f765a4882cc9a5ead13297b8a1f86c7 Mon Sep 17 00:00:00 2001 From: Gargi Sharma <gs051095@gmail.com> Date: Fri, 16 Sep 2016 00:37:11 +0530 Subject: staging: xgifb: remove blank line after open brace delete a blank line after an open brace to fix the check patch issue, Blank lines aren't necessary after an open brace '{'. Signed-off-by: Gargi Sharma <gs051095@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index af3f4d0..41dcc6d3 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -1647,7 +1647,6 @@ static void XGI_GetLCDVCLKPtr(unsigned char *di_0, unsigned char *di_1, static unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo) { - unsigned short index, modeflag; unsigned char tempal; @@ -2291,7 +2290,6 @@ static void XGI_DisplayOn(struct xgifb_video_info *xgifb_info, struct xgi_hw_device_info *pXGIHWDE, struct vb_device_info *pVBInfo) { - xgifb_reg_and_or(pVBInfo->P3c4, 0x01, 0xDF, 0x00); if (pXGIHWDE->jChipType == XG21) { if (pVBInfo->IF_DEF_LVDS == 1) { @@ -2338,7 +2336,6 @@ void XGI_DisplayOff(struct xgifb_video_info *xgifb_info, struct xgi_hw_device_info *pXGIHWDE, struct vb_device_info *pVBInfo) { - if (pXGIHWDE->jChipType == XG21) { if (pVBInfo->IF_DEF_LVDS == 1) { /* LVDS backlight off */ @@ -2455,7 +2452,6 @@ exit: static unsigned char XGI_IsLCDDualLink(struct vb_device_info *pVBInfo) { - if ((pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) && (pVBInfo->LCDInfo & SetLCDDualLink)) /* shampoo0129 */ return 1; @@ -4389,7 +4385,6 @@ static void xgifb_set_lvds(struct xgifb_video_info *xgifb_info, (value << 2) & 0x7C); for (temp = 0, value = 0; temp < 3; temp++) { - xgifb_reg_and_or(pVBInfo->P3c4, 0x31, ~0x30, value); xgifb_reg_set(pVBInfo->P3c4, 0x2B, xgifb_info->lvds_data.VCLKData1); @@ -5416,7 +5411,6 @@ static void XGI_SetCRT1Group(struct xgifb_video_info *xgifb_info, if (HwDeviceExtension->jChipType >= XG21) { temp = xgifb_reg_get(pVBInfo->P3d4, 0x38); if (temp & 0xA0) { - if (HwDeviceExtension->jChipType == XG27) XGI_SetXG27CRTC(RefreshRateTableIndex, pVBInfo); else -- cgit v0.10.2 From 4d09a43839853b9df7549fddd802a6e59b7201c1 Mon Sep 17 00:00:00 2001 From: Gargi Sharma <gs051095@gmail.com> Date: Fri, 16 Sep 2016 00:37:12 +0530 Subject: staging: xgifb: add spaces around | insert spaces around '|' to fix the checkpatch issue spaces preferred around that '|'. Signed-off-by: Gargi Sharma <gs051095@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 41dcc6d3..b0ec981 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -1914,7 +1914,7 @@ static void XGI_GetVBInfo(unsigned short ModeIdIndex, } } - if (pVBInfo->VBType & (VB_SIS301LV|VB_SIS302LV|VB_XGI301C)) { + if (pVBInfo->VBType & (VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) { if (temp & SetYPbPr) { /* shampoo add for new scratch */ temp = xgifb_reg_get(pVBInfo->P3d4, 0x35); -- cgit v0.10.2 From e35bf9b44ddc83f2ca3ca1b3491a4b2906485632 Mon Sep 17 00:00:00 2001 From: Gargi Sharma <gs051095@gmail.com> Date: Fri, 16 Sep 2016 00:37:13 +0530 Subject: staging: xgifb: remove blank line before closing brace delete blank line before '}' to fix the checkpatch issue Blank lines aren't necessary before a closing brace '}'. Signed-off-by: Gargi Sharma <gs051095@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index b0ec981..8488612 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -1677,7 +1677,6 @@ static unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex, if (!(modeflag & Charx8Dot)) tempal = TVCLKBASE_315 + HiTVTextVCLK; - } return tempal; } @@ -2244,7 +2243,6 @@ static void XGI_XG21BLSignalVDD(unsigned short tempbh, unsigned short tempbl, /* CR B4[1] */ xgifb_reg_and_or(pVBInfo->P3d4, 0xB4, ~0x02, temp); - } temp = xgifb_reg_get(pVBInfo->P3d4, 0x48); @@ -2273,7 +2271,6 @@ static void XGI_XG27BLSignalVDD(unsigned short tempbh, unsigned short tempbl, /* CR B4[1] */ xgifb_reg_and_or(pVBInfo->P3d4, 0xB4, ~0x02, temp); - } xgifb_reg_and_or(pVBInfo->P3d4, 0xB4, ~tempbh0, tempbl0); @@ -2308,7 +2305,6 @@ static void XGI_DisplayOn(struct xgifb_video_info *xgifb_info, /* DVO/DVI signal on */ XGI_XG21BLSignalVDD(0x20, 0x20, pVBInfo); } - } if (pXGIHWDE->jChipType == XG27) { @@ -2328,7 +2324,6 @@ static void XGI_DisplayOn(struct xgifb_video_info *xgifb_info, /* DVO/DVI signal on */ XGI_XG27BLSignalVDD(0x20, 0x20, pVBInfo); } - } } @@ -4128,7 +4123,6 @@ static void XGI_SetGroup4(unsigned short ModeIdIndex, if (pVBInfo->VBInfo & (SetCRT2ToTV | SetCRT2ToHiVision)) { if (pVBInfo->VGAHDE > 800) xgifb_reg_or(pVBInfo->Part4Port, 0x1E, 0x08); - } temp = 0x0036; @@ -4404,7 +4398,6 @@ static void xgifb_set_lvds(struct xgifb_video_info *xgifb_info, inb(pVBInfo->P3da); /* reset 3da */ } - } /* --------------------------------------------------------------------- */ -- cgit v0.10.2 From a33d506b72b670e2bfb72671b603f8a2054120d4 Mon Sep 17 00:00:00 2001 From: Gargi Sharma <gs051095@gmail.com> Date: Fri, 16 Sep 2016 00:37:14 +0530 Subject: staging: xgifb: fix alignment for if arguments Reduce indentation of multi-line if-test arguments for better readability. Signed-off-by: Gargi Sharma <gs051095@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 8488612..d8010c5 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -1740,7 +1740,7 @@ static void XGI_SetCRT2ECLK(unsigned short ModeIdIndex, xgifb_reg_and_or(pVBInfo->P3d4, 0x31, ~0x30, (unsigned short) (0x10 * i)); if (!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) && - !(pVBInfo->VBInfo & SetInSlaveMode)) { + !(pVBInfo->VBInfo & SetInSlaveMode)) { xgifb_reg_set(pVBInfo->P3c4, 0x2e, di_0); xgifb_reg_set(pVBInfo->P3c4, 0x2f, di_1); } else { -- cgit v0.10.2 From e28c631770f7d9f23da832e9fcc930a2bb59ad48 Mon Sep 17 00:00:00 2001 From: sayli karnik <karniksayli1995@gmail.com> Date: Fri, 16 Sep 2016 02:27:05 +0530 Subject: staging: comedi: Use the BIT() macro instead of left shifting 1 This patch replaces left shifts on 1 with the BIT(x) macro, as suggested by checkpatch.pl. Signed-off-by: sayli karnik <karniksayli1995@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index deaa7f2..daeb4ad 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -60,36 +60,36 @@ #define Window_Address 4 /* W */ #define Interrupt_And_Window_Status 4 /* R */ -#define IntStatus1 (1<<0) -#define IntStatus2 (1<<1) +#define IntStatus1 BIT(0) +#define IntStatus2 BIT(1) #define WindowAddressStatus_mask 0x7c #define Master_DMA_And_Interrupt_Control 5 /* W */ #define InterruptLine(x) ((x)&3) -#define OpenInt (1<<2) +#define OpenInt BIT(2) #define Group_Status 5 /* R */ -#define DataLeft (1<<0) -#define Req (1<<2) -#define StopTrig (1<<3) +#define DataLeft BIT(0) +#define Req BIT(2) +#define StopTrig BIT(3) #define Group_1_Flags 6 /* R */ #define Group_2_Flags 7 /* R */ -#define TransferReady (1<<0) -#define CountExpired (1<<1) -#define Waited (1<<5) -#define PrimaryTC (1<<6) -#define SecondaryTC (1<<7) +#define TransferReady BIT(0) +#define CountExpired BIT(1) +#define Waited BIT(5) +#define PrimaryTC BIT(6) +#define SecondaryTC BIT(7) /* #define SerialRose */ /* #define ReqRose */ /* #define Paused */ #define Group_1_First_Clear 6 /* W */ #define Group_2_First_Clear 7 /* W */ -#define ClearWaited (1<<3) -#define ClearPrimaryTC (1<<4) -#define ClearSecondaryTC (1<<5) -#define DMAReset (1<<6) -#define FIFOReset (1<<7) +#define ClearWaited BIT(3) +#define ClearPrimaryTC BIT(4) +#define ClearSecondaryTC BIT(5) +#define DMAReset BIT(6) +#define FIFOReset BIT(7) #define ClearAll 0xf8 #define Group_1_FIFO 8 /* W */ @@ -110,27 +110,27 @@ #define Group_1_Second_Clear 46 /* W */ #define Group_2_Second_Clear 47 /* W */ -#define ClearExpired (1<<0) +#define ClearExpired BIT(0) #define Port_Pattern(x) (48+(x)) #define Data_Path 64 -#define FIFOEnableA (1<<0) -#define FIFOEnableB (1<<1) -#define FIFOEnableC (1<<2) -#define FIFOEnableD (1<<3) +#define FIFOEnableA BIT(0) +#define FIFOEnableB BIT(1) +#define FIFOEnableC BIT(2) +#define FIFOEnableD BIT(3) #define Funneling(x) (((x)&3)<<4) -#define GroupDirection (1<<7) +#define GroupDirection BIT(7) #define Protocol_Register_1 65 #define OpMode Protocol_Register_1 #define RunMode(x) ((x)&7) -#define Numbered (1<<3) +#define Numbered BIT(3) #define Protocol_Register_2 66 #define ClockReg Protocol_Register_2 #define ClockLine(x) (((x)&3)<<5) -#define InvertStopTrig (1<<7) +#define InvertStopTrig BIT(7) #define DataLatching(x) (((x)&3)<<5) #define Protocol_Register_3 67 @@ -151,17 +151,17 @@ #define Protocol_Register_6 73 #define LinePolarities Protocol_Register_6 -#define InvertAck (1<<0) -#define InvertReq (1<<1) -#define InvertClock (1<<2) -#define InvertSerial (1<<3) -#define OpenAck (1<<4) -#define OpenClock (1<<5) +#define InvertAck BIT(0) +#define InvertReq BIT(1) +#define InvertClock BIT(2) +#define InvertSerial BIT(3) +#define OpenAck BIT(4) +#define OpenClock BIT(5) #define Protocol_Register_7 74 #define AckSer Protocol_Register_7 #define AckLine(x) (((x)&3)<<2) -#define ExchangePins (1<<7) +#define ExchangePins BIT(7) #define Interrupt_Control 75 /* bits same as flags */ @@ -182,20 +182,20 @@ static inline unsigned int secondary_DMAChannel_bits(unsigned int channel) #define Transfer_Size_Control 77 #define TransferWidth(x) ((x)&3) #define TransferLength(x) (((x)&3)<<3) -#define RequireRLevel (1<<5) +#define RequireRLevel BIT(5) #define Protocol_Register_15 79 #define DAQOptions Protocol_Register_15 #define StartSource(x) ((x)&0x3) -#define InvertStart (1<<2) +#define InvertStart BIT(2) #define StopSource(x) (((x)&0x3)<<3) -#define ReqStart (1<<6) -#define PreStart (1<<7) +#define ReqStart BIT(6) +#define PreStart BIT(7) #define Pattern_Detection 81 -#define DetectionMethod (1<<0) -#define InvertMatch (1<<1) -#define IE_Pattern_Detection (1<<2) +#define DetectionMethod BIT(0) +#define InvertMatch BIT(1) +#define IE_Pattern_Detection BIT(2) #define Protocol_Register_9 82 #define ReqDelay Protocol_Register_9 -- cgit v0.10.2 From 3b13abf5a7095f1ff468e50345d8b2e34399f817 Mon Sep 17 00:00:00 2001 From: Gargi Sharma <gs051095@gmail.com> Date: Fri, 16 Sep 2016 06:08:35 +0530 Subject: staging: i4l: correct misspelled "ressources" to "resources" change ressources to resources to fix the checkpatch issue 'ressources' may be misspelled. Signed-off-by: Gargi Sharma <gs051095@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/i4l/act2000/act2000_isa.c b/drivers/staging/i4l/act2000/act2000_isa.c index 1d93151..c800da8 100644 --- a/drivers/staging/i4l/act2000/act2000_isa.c +++ b/drivers/staging/i4l/act2000/act2000_isa.c @@ -176,7 +176,7 @@ act2000_isa_config_port(act2000_card *card, unsigned short portbase) } /* - * Release ressources, used by an adaptor. + * Release resources, used by an adaptor. */ void act2000_isa_release(act2000_card *card) -- cgit v0.10.2 From 007afa8bd3e9adaa277b6f9451659e0974bde923 Mon Sep 17 00:00:00 2001 From: Gargi Sharma <gs051095@gmail.com> Date: Fri, 16 Sep 2016 04:08:11 +0530 Subject: staging: fbtft: move && operator for logical continuation Move && up to the previous line, to fix the checkpatch issue Logical continuations should be on the previous line. Signed-off-by: Gargi Sharma <gs051095@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fbtft/fb_ssd1351.c b/drivers/staging/fbtft/fb_ssd1351.c index 8267bbbc..ab1a31d 100644 --- a/drivers/staging/fbtft/fb_ssd1351.c +++ b/drivers/staging/fbtft/fb_ssd1351.c @@ -25,8 +25,8 @@ static void register_onboard_backlight(struct fbtft_par *par); static int init_display(struct fbtft_par *par) { - if (par->pdata - && par->pdata->display.backlight == FBTFT_ONBOARD_BACKLIGHT) { + if (par->pdata && + par->pdata->display.backlight == FBTFT_ONBOARD_BACKLIGHT) { /* module uses onboard GPIO for panel power */ par->fbtftops.register_backlight = register_onboard_backlight; } @@ -189,8 +189,8 @@ static int update_onboard_backlight(struct backlight_device *bd) "%s: power=%d, fb_blank=%d\n", __func__, bd->props.power, bd->props.fb_blank); - on = (bd->props.power == FB_BLANK_UNBLANK) - && (bd->props.fb_blank == FB_BLANK_UNBLANK); + on = (bd->props.power == FB_BLANK_UNBLANK) && + (bd->props.fb_blank == FB_BLANK_UNBLANK); /* Onboard backlight connected to GPIO0 on SSD1351, GPIO1 unused */ write_reg(par, 0xB5, on ? 0x03 : 0x02); -- cgit v0.10.2 From e3f680ddaed9d94ee629aee7747e419f2c700f4e Mon Sep 17 00:00:00 2001 From: Gargi Sharma <gs051095@gmail.com> Date: Fri, 16 Sep 2016 04:08:12 +0530 Subject: staging: fbtft: add spaces around << add spaces around << to fix the checkpatch issue, spaces preferred around that '<<'. Signed-off-by: Gargi Sharma <gs051095@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fbtft/fb_ssd1351.c b/drivers/staging/fbtft/fb_ssd1351.c index ab1a31d..200aa9b 100644 --- a/drivers/staging/fbtft/fb_ssd1351.c +++ b/drivers/staging/fbtft/fb_ssd1351.c @@ -80,10 +80,10 @@ static int set_var(struct fbtft_par *par) switch (par->info->var.rotate) { case 0: - write_reg(par, 0xA0, remap | 0x00 | 1<<4); + write_reg(par, 0xA0, remap | 0x00 | 1 << 4); break; case 270: - write_reg(par, 0xA0, remap | 0x03 | 1<<4); + write_reg(par, 0xA0, remap | 0x03 | 1 << 4); break; case 180: write_reg(par, 0xA0, remap | 0x02); -- cgit v0.10.2 From 0548cad1c40d91bd7e6791ae5a0daf89da468169 Mon Sep 17 00:00:00 2001 From: Gargi Sharma <gs051095@gmail.com> Date: Fri, 16 Sep 2016 08:16:03 +0530 Subject: staging: wlan-ng: add spaces around + add spaces around + to fix the checkpatch issue, spaces preferred around that '&'. Signed-off-by: Gargi Sharma <gs051095@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index cec6d0b..5bb8c58 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -63,7 +63,7 @@ /*--- Mins & Maxs -----------------------------------*/ #define HFA384x_PORTID_MAX ((u16)7) -#define HFA384x_NUMPORTS_MAX ((u16)(HFA384x_PORTID_MAX+1)) +#define HFA384x_NUMPORTS_MAX ((u16)(HFA384x_PORTID_MAX + 1)) #define HFA384x_PDR_LEN_MAX ((u16)512) /* in bytes, from EK */ #define HFA384x_PDA_RECS_MAX ((u16)200) /* a guess */ #define HFA384x_PDA_LEN_MAX ((u16)1024) /* in bytes, from EK*/ -- cgit v0.10.2 From 65dbeefd023329c1f45769719b0438e19e3cb011 Mon Sep 17 00:00:00 2001 From: Gargi Sharma <gs051095@gmail.com> Date: Fri, 16 Sep 2016 08:16:04 +0530 Subject: staging: wlan-ng: add spaces around & add space around & to fix the checkpatch issue spaces preferred around that '&'. Signed-off-by: Gargi Sharma <gs051095@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 5bb8c58..e466883 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -116,14 +116,14 @@ /* Make a 32-bit flat address from AUX format 16-bit page and offset */ #define HFA384x_ADDR_AUX_MKFLAT(p, o) \ - ((((u32)(((u16)(p))&HFA384x_ADDR_AUX_PAGE_MASK)) << 7) | \ - ((u32)(((u16)(o))&HFA384x_ADDR_AUX_OFF_MASK))) + ((((u32)(((u16)(p)) & HFA384x_ADDR_AUX_PAGE_MASK)) << 7) | \ + ((u32)(((u16)(o)) & HFA384x_ADDR_AUX_OFF_MASK))) /* Make CMD format offset and page from a 32-bit flat address */ #define HFA384x_ADDR_CMD_MKPAGE(f) \ - ((u16)((((u32)(f))&HFA384x_ADDR_FLAT_CMD_PAGE_MASK)>>16)) + ((u16)((((u32)(f)) & HFA384x_ADDR_FLAT_CMD_PAGE_MASK)>>16)) #define HFA384x_ADDR_CMD_MKOFF(f) \ - ((u16)(((u32)(f))&HFA384x_ADDR_FLAT_CMD_OFF_MASK)) + ((u16)(((u32)(f)) & HFA384x_ADDR_FLAT_CMD_OFF_MASK)) /*--- Controller Memory addresses -------------------*/ #define HFA3842_PDA_BASE (0x007f0000UL) @@ -503,12 +503,12 @@ Communication Frames: Test/Get/Set Field Values for Transmit Frames --------------------------------------------------------------------*/ /*-- Status Field --*/ #define HFA384x_TXSTATUS_ISERROR(v) \ - (((u16)(v))&\ + (((u16)(v)) & \ (HFA384x_TXSTATUS_ACKERR|HFA384x_TXSTATUS_FORMERR|\ HFA384x_TXSTATUS_DISCON|HFA384x_TXSTATUS_AGEDERR|\ HFA384x_TXSTATUS_RETRYERR)) -#define HFA384x_TX_SET(v, m, s) ((((u16)(v))<<((u16)(s)))&((u16)(m))) +#define HFA384x_TX_SET(v, m, s) ((((u16)(v))<<((u16)(s))) & ((u16)(m))) #define HFA384x_TX_MACPORT_SET(v) HFA384x_TX_SET(v, HFA384x_TX_MACPORT, 8) #define HFA384x_TX_STRUCTYPE_SET(v) HFA384x_TX_SET(v, \ -- cgit v0.10.2 From 061eab5c6396894de5a01bcaf5ab7bae51232ba7 Mon Sep 17 00:00:00 2001 From: Gargi Sharma <gs051095@gmail.com> Date: Fri, 16 Sep 2016 08:16:05 +0530 Subject: staging: wlan-ng: add spaces around >> add spaces around >> to fix the checkpatch issue, spaces preferred around that '>>'. Signed-off-by: Gargi Sharma <gs051095@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index e466883..d4b1dbf 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -121,7 +121,7 @@ /* Make CMD format offset and page from a 32-bit flat address */ #define HFA384x_ADDR_CMD_MKPAGE(f) \ - ((u16)((((u32)(f)) & HFA384x_ADDR_FLAT_CMD_PAGE_MASK)>>16)) + ((u16)((((u32)(f)) & HFA384x_ADDR_FLAT_CMD_PAGE_MASK) >> 16)) #define HFA384x_ADDR_CMD_MKOFF(f) \ ((u16)(((u32)(f)) & HFA384x_ADDR_FLAT_CMD_OFF_MASK)) -- cgit v0.10.2 From 05235ce2ec77f4507d242963dba13085b14b4172 Mon Sep 17 00:00:00 2001 From: Gargi Sharma <gs051095@gmail.com> Date: Fri, 16 Sep 2016 08:16:06 +0530 Subject: staging: wlan-ng: add spaces around | add spaces around | to fix the checkpatch issue, spaces preferred around that '|'. Signed-off-by: Gargi Sharma <gs051095@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index d4b1dbf..4bbbce5 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -504,8 +504,8 @@ Communication Frames: Test/Get/Set Field Values for Transmit Frames /*-- Status Field --*/ #define HFA384x_TXSTATUS_ISERROR(v) \ (((u16)(v)) & \ - (HFA384x_TXSTATUS_ACKERR|HFA384x_TXSTATUS_FORMERR|\ - HFA384x_TXSTATUS_DISCON|HFA384x_TXSTATUS_AGEDERR|\ + (HFA384x_TXSTATUS_ACKERR | HFA384x_TXSTATUS_FORMERR | \ + HFA384x_TXSTATUS_DISCON | HFA384x_TXSTATUS_AGEDERR | \ HFA384x_TXSTATUS_RETRYERR)) #define HFA384x_TX_SET(v, m, s) ((((u16)(v))<<((u16)(s))) & ((u16)(m))) -- cgit v0.10.2 From 6e81f6f1213d6b88f0f4f8d0577b418ab0166fc7 Mon Sep 17 00:00:00 2001 From: Gargi Sharma <gs051095@gmail.com> Date: Fri, 16 Sep 2016 08:16:07 +0530 Subject: staging: wlan-ng: add spaces around << add spaces around << to fix the checkpatch issue, spaces preferred around that '<<'. Signed-off-by: Gargi Sharma <gs051095@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 4bbbce5..616da07 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -508,7 +508,7 @@ Communication Frames: Test/Get/Set Field Values for Transmit Frames HFA384x_TXSTATUS_DISCON | HFA384x_TXSTATUS_AGEDERR | \ HFA384x_TXSTATUS_RETRYERR)) -#define HFA384x_TX_SET(v, m, s) ((((u16)(v))<<((u16)(s))) & ((u16)(m))) +#define HFA384x_TX_SET(v, m, s) ((((u16)(v)) << ((u16)(s))) & ((u16)(m))) #define HFA384x_TX_MACPORT_SET(v) HFA384x_TX_SET(v, HFA384x_TX_MACPORT, 8) #define HFA384x_TX_STRUCTYPE_SET(v) HFA384x_TX_SET(v, \ -- cgit v0.10.2 From 7399c2c3959c71e7cef3ba9aca393f82163c633f Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Fri, 16 Sep 2016 21:33:12 +0700 Subject: staging: r8188eu: remove ODM_CmnInfoUpdate function This function does not improve code readability. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/odm.c b/drivers/staging/rtl8188eu/hal/odm.c index 57a1275..33f4839 100644 --- a/drivers/staging/rtl8188eu/hal/odm.c +++ b/drivers/staging/rtl8188eu/hal/odm.c @@ -385,46 +385,6 @@ void ODM_CmnInfoPtrArrayHook(struct odm_dm_struct *pDM_Odm, enum odm_common_info } } -/* Update Band/CHannel/.. The values are dynamic but non-per-packet. */ -void ODM_CmnInfoUpdate(struct odm_dm_struct *pDM_Odm, u32 CmnInfo, u64 Value) -{ - /* */ - /* This init variable may be changed in run time. */ - /* */ - switch (CmnInfo) { - case ODM_CMNINFO_ABILITY: - pDM_Odm->SupportAbility = (u32)Value; - break; - case ODM_CMNINFO_RF_TYPE: - pDM_Odm->RFType = (u8)Value; - break; - case ODM_CMNINFO_WIFI_DIRECT: - pDM_Odm->bWIFI_Direct = (bool)Value; - break; - case ODM_CMNINFO_WIFI_DISPLAY: - pDM_Odm->bWIFI_Display = (bool)Value; - break; - case ODM_CMNINFO_LINK: - pDM_Odm->bLinked = (bool)Value; - break; - case ODM_CMNINFO_RSSI_MIN: - 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; - case ODM_CMNINFO_RA_THRESHOLD_LOW: - pDM_Odm->RateAdaptive.LowRSSIThresh = (u8)Value; - break; - } -} - void odm_CommonInfoSelfInit(struct odm_dm_struct *pDM_Odm) { struct adapter *adapter = pDM_Odm->Adapter; @@ -1179,8 +1139,7 @@ void odm_RSSIMonitorCheckCE(struct odm_dm_struct *pDM_Odm) pdmpriv->EntryMinUndecoratedSmoothedPWDB = 0; FindMinimumRSSI(Adapter); - ODM_CmnInfoUpdate(&pHalData->odmpriv, ODM_CMNINFO_RSSI_MIN, - pdmpriv->MinUndecoratedPWDBForDM); + pHalData->odmpriv.RSSI_Min = pdmpriv->MinUndecoratedPWDBForDM; } /* 3============================================================ */ diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c index 11e7246..b99008b 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c @@ -67,18 +67,18 @@ static void Init_ODM_ComInfo_88E(struct adapter *Adapter) if (hal_data->rf_type == RF_1T1R) - ODM_CmnInfoUpdate(dm_odm, ODM_CMNINFO_RF_TYPE, ODM_1T1R); + dm_odm->RFType = ODM_1T1R; else if (hal_data->rf_type == RF_2T2R) - ODM_CmnInfoUpdate(dm_odm, ODM_CMNINFO_RF_TYPE, ODM_2T2R); + dm_odm->RFType = ODM_2T2R; else if (hal_data->rf_type == RF_1T2R) - ODM_CmnInfoUpdate(dm_odm, ODM_CMNINFO_RF_TYPE, ODM_1T2R); + dm_odm->RFType = ODM_1T2R; ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_RF_ANTENNA_TYPE, hal_data->TRxAntDivType); pdmpriv->InitODMFlag = ODM_RF_CALIBRATION | ODM_RF_TX_PWR_TRACK; - ODM_CmnInfoUpdate(dm_odm, ODM_CMNINFO_ABILITY, pdmpriv->InitODMFlag); + dm_odm->SupportAbility = pdmpriv->InitODMFlag; } static void Update_ODM_ComInfo_88E(struct adapter *Adapter) @@ -109,7 +109,7 @@ static void Update_ODM_ComInfo_88E(struct adapter *Adapter) ODM_RF_TX_PWR_TRACK; } - ODM_CmnInfoUpdate(dm_odm, ODM_CMNINFO_ABILITY, pdmpriv->InitODMFlag); + dm_odm->SupportAbility = pdmpriv->InitODMFlag; ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_TX_UNI, &(Adapter->xmitpriv.tx_bytes)); ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_RX_UNI, &(Adapter->recvpriv.rx_bytes)); @@ -166,7 +166,7 @@ void rtw_hal_dm_watchdog(struct adapter *Adapter) bLinked = true; } - ODM_CmnInfoUpdate(&hal_data->odmpriv, ODM_CMNINFO_LINK, bLinked); + hal_data->odmpriv.bLinked = bLinked; ODM_DMWatchdog(&hal_data->odmpriv); skip_dm: /* Check GPIO to determine current RF on/off and Pbc status. */ diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c index 938d6f5..a1812dd 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c @@ -165,10 +165,10 @@ void rtw_hal_set_odm_var(struct adapter *Adapter, enum hal_odm_variable eVariabl } break; case HAL_ODM_P2P_STATE: - ODM_CmnInfoUpdate(podmpriv, ODM_CMNINFO_WIFI_DIRECT, bSet); + podmpriv->bWIFI_Direct = bSet; break; case HAL_ODM_WIFI_DISPLAY_STATE: - ODM_CmnInfoUpdate(podmpriv, ODM_CMNINFO_WIFI_DISPLAY, bSet); + podmpriv->bWIFI_Display = bSet; break; default: break; -- cgit v0.10.2 From 02f14ca4232207e75e57bfd679b60b48e60993f4 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Fri, 16 Sep 2016 21:33:42 +0700 Subject: staging: r8188eu: remove ODM_CmnInfoHook function This function used once, and does not improve code readability. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/odm.c b/drivers/staging/rtl8188eu/hal/odm.c index 33f4839..534e919 100644 --- a/drivers/staging/rtl8188eu/hal/odm.c +++ b/drivers/staging/rtl8188eu/hal/odm.c @@ -293,83 +293,6 @@ void ODM_CmnInfoInit(struct odm_dm_struct *pDM_Odm, enum odm_common_info_def Cmn pDM_Odm->BbSwingFlagOfdm = false; } -void ODM_CmnInfoHook(struct odm_dm_struct *pDM_Odm, enum odm_common_info_def CmnInfo, void *pValue) -{ - /* */ - /* Hook call by reference pointer. */ - /* */ - switch (CmnInfo) { - /* Dynamic call by reference pointer. */ - case ODM_CMNINFO_MAC_PHY_MODE: - pDM_Odm->pMacPhyMode = (u8 *)pValue; - break; - case ODM_CMNINFO_TX_UNI: - pDM_Odm->pNumTxBytesUnicast = (u64 *)pValue; - break; - case ODM_CMNINFO_RX_UNI: - pDM_Odm->pNumRxBytesUnicast = (u64 *)pValue; - break; - case ODM_CMNINFO_WM_MODE: - pDM_Odm->pWirelessMode = (u8 *)pValue; - break; - case ODM_CMNINFO_BAND: - pDM_Odm->pBandType = (u8 *)pValue; - break; - case ODM_CMNINFO_SEC_CHNL_OFFSET: - pDM_Odm->pSecChOffset = (u8 *)pValue; - break; - case ODM_CMNINFO_SEC_MODE: - pDM_Odm->pSecurity = (u8 *)pValue; - break; - case ODM_CMNINFO_BW: - pDM_Odm->pBandWidth = (u8 *)pValue; - break; - case ODM_CMNINFO_CHNL: - pDM_Odm->pChannel = (u8 *)pValue; - break; - case ODM_CMNINFO_DMSP_GET_VALUE: - pDM_Odm->pbGetValueFromOtherMac = (bool *)pValue; - break; - case ODM_CMNINFO_BUDDY_ADAPTOR: - pDM_Odm->pBuddyAdapter = (struct adapter **)pValue; - break; - case ODM_CMNINFO_DMSP_IS_MASTER: - pDM_Odm->pbMasterOfDMSP = (bool *)pValue; - break; - case ODM_CMNINFO_SCAN: - pDM_Odm->pbScanInProcess = (bool *)pValue; - break; - case ODM_CMNINFO_POWER_SAVING: - pDM_Odm->pbPowerSaving = (bool *)pValue; - break; - case ODM_CMNINFO_ONE_PATH_CCA: - pDM_Odm->pOnePathCCA = (u8 *)pValue; - break; - case ODM_CMNINFO_DRV_STOP: - pDM_Odm->pbDriverStopped = (bool *)pValue; - break; - case ODM_CMNINFO_PNP_IN: - pDM_Odm->pbDriverIsGoingToPnpSetPowerSleep = (bool *)pValue; - break; - case ODM_CMNINFO_INIT_ON: - pDM_Odm->pinit_adpt_in_progress = (bool *)pValue; - break; - case ODM_CMNINFO_ANT_TEST: - pDM_Odm->pAntennaTest = (u8 *)pValue; - break; - case ODM_CMNINFO_NET_CLOSED: - pDM_Odm->pbNet_closed = (bool *)pValue; - break; - case ODM_CMNINFO_MP_MODE: - pDM_Odm->mp_mode = (u8 *)pValue; - break; - /* To remove the compiler warning, must add an empty default statement to handle the other values. */ - default: - /* do nothing */ - break; - } -} - void ODM_CmnInfoPtrArrayHook(struct odm_dm_struct *pDM_Odm, enum odm_common_info_def CmnInfo, u16 Index, void *pValue) { /* Hook call by reference pointer. */ diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c index b99008b..8070a24 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c @@ -111,17 +111,17 @@ static void Update_ODM_ComInfo_88E(struct adapter *Adapter) dm_odm->SupportAbility = pdmpriv->InitODMFlag; - ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_TX_UNI, &(Adapter->xmitpriv.tx_bytes)); - ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_RX_UNI, &(Adapter->recvpriv.rx_bytes)); - ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_WM_MODE, &(pmlmeext->cur_wireless_mode)); - ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_SEC_CHNL_OFFSET, &(hal_data->nCur40MhzPrimeSC)); - ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_SEC_MODE, &(Adapter->securitypriv.dot11PrivacyAlgrthm)); - ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_BW, &(hal_data->CurrentChannelBW)); - ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_CHNL, &(hal_data->CurrentChannel)); - ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_NET_CLOSED, &(Adapter->net_closed)); - ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_MP_MODE, &(Adapter->registrypriv.mp_mode)); - ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_SCAN, &(pmlmepriv->bScanInProcess)); - ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_POWER_SAVING, &(pwrctrlpriv->bpower_saving)); + dm_odm->pNumTxBytesUnicast = &Adapter->xmitpriv.tx_bytes; + dm_odm->pNumRxBytesUnicast = &Adapter->recvpriv.rx_bytes; + dm_odm->pWirelessMode = &pmlmeext->cur_wireless_mode; + dm_odm->pSecChOffset = &hal_data->nCur40MhzPrimeSC; + dm_odm->pSecurity = (u8 *)&Adapter->securitypriv.dot11PrivacyAlgrthm; + dm_odm->pBandWidth = (u8 *)&hal_data->CurrentChannelBW; + dm_odm->pChannel = &hal_data->CurrentChannel; + dm_odm->pbNet_closed = (bool *)&Adapter->net_closed; + dm_odm->mp_mode = &Adapter->registrypriv.mp_mode; + dm_odm->pbScanInProcess = (bool *)&pmlmepriv->bScanInProcess; + dm_odm->pbPowerSaving = (bool *)&pwrctrlpriv->bpower_saving; ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_RF_ANTENNA_TYPE, hal_data->TRxAntDivType); for (i = 0; i < NUM_STA; i++) -- cgit v0.10.2 From d7c952a3664c5f52a1a117327a9e32e64cc74ed4 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Fri, 16 Sep 2016 21:34:12 +0700 Subject: staging: r8188eu: remove ODM_CmnInfoPtrArrayHook function This function used once, and does not improve code readability. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/odm.c b/drivers/staging/rtl8188eu/hal/odm.c index 534e919..d1c9ef3 100644 --- a/drivers/staging/rtl8188eu/hal/odm.c +++ b/drivers/staging/rtl8188eu/hal/odm.c @@ -226,73 +226,6 @@ void ODM_DMWatchdog(struct odm_dm_struct *pDM_Odm) odm_EdcaTurboCheck(pDM_Odm); } -/* Init /.. Fixed HW value. Only init time. */ -void ODM_CmnInfoInit(struct odm_dm_struct *pDM_Odm, enum odm_common_info_def CmnInfo, u32 Value) -{ - /* This section is used for init value */ - switch (CmnInfo) { - /* Fixed ODM value. */ - case ODM_CMNINFO_ABILITY: - pDM_Odm->SupportAbility = (u32)Value; - break; - case ODM_CMNINFO_PLATFORM: - pDM_Odm->SupportPlatform = (u8)Value; - break; - case ODM_CMNINFO_INTERFACE: - pDM_Odm->SupportInterface = (u8)Value; - break; - case ODM_CMNINFO_MP_TEST_CHIP: - pDM_Odm->bIsMPChip = (u8)Value; - break; - case ODM_CMNINFO_IC_TYPE: - pDM_Odm->SupportICType = Value; - break; - case ODM_CMNINFO_CUT_VER: - pDM_Odm->CutVersion = (u8)Value; - break; - case ODM_CMNINFO_RF_TYPE: - pDM_Odm->RFType = (u8)Value; - break; - case ODM_CMNINFO_RF_ANTENNA_TYPE: - pDM_Odm->AntDivType = (u8)Value; - break; - case ODM_CMNINFO_BOARD_TYPE: - pDM_Odm->BoardType = (u8)Value; - break; - case ODM_CMNINFO_EXT_LNA: - pDM_Odm->ExtLNA = (u8)Value; - break; - case ODM_CMNINFO_EXT_PA: - pDM_Odm->ExtPA = (u8)Value; - break; - case ODM_CMNINFO_EXT_TRSW: - pDM_Odm->ExtTRSW = (u8)Value; - break; - case ODM_CMNINFO_PATCH_ID: - pDM_Odm->PatchID = (u8)Value; - break; - case ODM_CMNINFO_BINHCT_TEST: - pDM_Odm->bInHctTest = (bool)Value; - break; - case ODM_CMNINFO_BWIFI_TEST: - pDM_Odm->bWIFITest = (bool)Value; - break; - case ODM_CMNINFO_SMART_CONCURRENT: - pDM_Odm->bDualMacSmartConcurrent = (bool)Value; - break; - /* To remove the compiler warning, must add an empty default statement to handle the other values. */ - default: - /* do nothing */ - break; - } - - /* Tx power tracking BB swing table. */ - /* The base index = 12. +((12-n)/2)dB 13~?? = decrease tx pwr by -((n-12)/2)dB */ - pDM_Odm->BbSwingIdxOfdm = 12; /* Set defalut value as index 12. */ - pDM_Odm->BbSwingIdxOfdmCurrent = 12; - pDM_Odm->BbSwingFlagOfdm = false; -} - void ODM_CmnInfoPtrArrayHook(struct odm_dm_struct *pDM_Odm, enum odm_common_info_def CmnInfo, u16 Index, void *pValue) { /* Hook call by reference pointer. */ diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c index 8070a24..0c853fc 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c @@ -45,26 +45,17 @@ static void Init_ODM_ComInfo_88E(struct adapter *Adapter) struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter); struct dm_priv *pdmpriv = &hal_data->dmpriv; struct odm_dm_struct *dm_odm = &(hal_data->odmpriv); - u8 cut_ver; /* Init Value */ memset(dm_odm, 0, sizeof(*dm_odm)); dm_odm->Adapter = Adapter; - - ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_PLATFORM, ODM_CE); - - ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_IC_TYPE, ODM_RTL8188E); - - cut_ver = ODM_CUT_A; - - ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_CUT_VER, cut_ver); - - ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_MP_TEST_CHIP, hal_data->VersionID.ChipType == NORMAL_CHIP ? true : false); - - ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_PATCH_ID, hal_data->CustomerID); - ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_BWIFI_TEST, Adapter->registrypriv.wifi_spec); - + dm_odm->SupportPlatform = ODM_CE; + dm_odm->SupportICType = ODM_RTL8188E; + dm_odm->CutVersion = ODM_CUT_A; + dm_odm->bIsMPChip = hal_data->VersionID.ChipType == NORMAL_CHIP; + dm_odm->PatchID = hal_data->CustomerID; + dm_odm->bWIFITest = Adapter->registrypriv.wifi_spec; if (hal_data->rf_type == RF_1T1R) dm_odm->RFType = ODM_1T1R; @@ -73,7 +64,13 @@ static void Init_ODM_ComInfo_88E(struct adapter *Adapter) else if (hal_data->rf_type == RF_1T2R) dm_odm->RFType = ODM_1T2R; - ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_RF_ANTENNA_TYPE, hal_data->TRxAntDivType); + dm_odm->AntDivType = hal_data->TRxAntDivType; + + /* Tx power tracking BB swing table. */ + /* The base index = 12. +((12-n)/2)dB 13~?? = decrease tx pwr by -((n-12)/2)dB */ + dm_odm->BbSwingIdxOfdm = 12; /* Set defalut value as index 12. */ + dm_odm->BbSwingIdxOfdmCurrent = 12; + dm_odm->BbSwingFlagOfdm = false; pdmpriv->InitODMFlag = ODM_RF_CALIBRATION | ODM_RF_TX_PWR_TRACK; @@ -122,7 +119,13 @@ static void Update_ODM_ComInfo_88E(struct adapter *Adapter) dm_odm->mp_mode = &Adapter->registrypriv.mp_mode; dm_odm->pbScanInProcess = (bool *)&pmlmepriv->bScanInProcess; dm_odm->pbPowerSaving = (bool *)&pwrctrlpriv->bpower_saving; - ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_RF_ANTENNA_TYPE, hal_data->TRxAntDivType); + dm_odm->AntDivType = hal_data->TRxAntDivType; + + /* Tx power tracking BB swing table. */ + /* The base index = 12. +((12-n)/2)dB 13~?? = decrease tx pwr by -((n-12)/2)dB */ + dm_odm->BbSwingIdxOfdm = 12; /* Set defalut value as index 12. */ + dm_odm->BbSwingIdxOfdmCurrent = 12; + dm_odm->BbSwingFlagOfdm = false; for (i = 0; i < NUM_STA; i++) ODM_CmnInfoPtrArrayHook(dm_odm, ODM_CMNINFO_STA_STATUS, i, NULL); -- cgit v0.10.2 From faa48ea82bcd4b186dd548529d2514a9a2892095 Mon Sep 17 00:00:00 2001 From: sayli karnik <karniksayli1995@gmail.com> Date: Fri, 16 Sep 2016 16:23:02 +0530 Subject: staging: wilc1000: Use sizeof type *pointer instead of sizeof type The patch uses the size of the dereference to a variable instead of it's type, to make the code more resistant to type changes in the future. The type of the pointer variable here is the same as the type in the argument that is being replaced in sizeof(). Signed-off-by: sayli karnik <karniksayli1995@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 78f524f..d0cb568 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3329,7 +3329,7 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) init_completion(&hif_wait_response); - hif_drv = kzalloc(sizeof(struct host_if_drv), GFP_KERNEL); + hif_drv = kzalloc(sizeof(*hif_drv), GFP_KERNEL); if (!hif_drv) { result = -ENOMEM; goto _fail_; @@ -3878,7 +3878,7 @@ static void *host_int_ParseJoinBssParam(struct network_info *ptstrNetworkInfo) pu8IEs = ptstrNetworkInfo->ies; u16IEsLen = ptstrNetworkInfo->ies_len; - pNewJoinBssParam = kzalloc(sizeof(struct join_bss_param), GFP_KERNEL); + pNewJoinBssParam = kzalloc(sizeof(*pNewJoinBssParam), GFP_KERNEL); if (pNewJoinBssParam) { pNewJoinBssParam->dtim_period = ptstrNetworkInfo->dtim_period; pNewJoinBssParam->beacon_period = ptstrNetworkInfo->beacon_period; -- cgit v0.10.2 From 30b48e2dbe7f4d78fb8f7abbef9851ec36a93dff Mon Sep 17 00:00:00 2001 From: Bhumika Goyal <bhumirks@gmail.com> Date: Fri, 16 Sep 2016 19:54:37 +0530 Subject: Staging: ks7010: Replace memset with eth_zero_addr Use eth_zero_addr to assign zero address to the given address array instead of memset when the second argument in memset is address of zero. Coccinelle was used to do the replacement and add the header file linux/etherdevice.h if not already present. Script: @header@ @@ #include <linux/etherdevice.h> @r1@ expression e; @@ -memset(e,0,ETH_ALEN); +eth_zero_addr(e); @includeheader depends on r1 && !header@ @@ + #include <linux/etherdevice.h> #include <...> Signed-off-by: Bhumika Goyal <bhumirks@gmail.com> Acked-by: Julia Lawall <julia.lawall@lip6.fr> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c index e3cc8ce..deb82ab 100644 --- a/drivers/staging/ks7010/ks_hostif.c +++ b/drivers/staging/ks7010/ks_hostif.c @@ -14,6 +14,7 @@ #include "eap_packet.h" #include "michael_mic.h" +#include <linux/etherdevice.h> #include <linux/if_ether.h> #include <linux/if_arp.h> @@ -780,7 +781,7 @@ void hostif_start_confirm(struct ks_wlan_private *priv) wrqu.data.flags = 0; wrqu.ap_addr.sa_family = ARPHRD_ETHER; if ((priv->connect_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) { - memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN); + eth_zero_addr(wrqu.ap_addr.sa_data); DPRINTK(3, "IWEVENT: disconnect\n"); wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL); } @@ -838,7 +839,7 @@ void hostif_connect_indication(struct ks_wlan_private *priv) wrqu0.ap_addr.sa_family = ARPHRD_ETHER; if ((priv->connect_status & CONNECT_STATUS_MASK) == DISCONNECT_STATUS && (old_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) { - memset(wrqu0.ap_addr.sa_data, '\0', ETH_ALEN); + eth_zero_addr(wrqu0.ap_addr.sa_data); DPRINTK(3, "IWEVENT: disconnect\n"); DPRINTK(3, "disconnect :: scan_ind_count=%d\n", priv->scan_ind_count); @@ -910,7 +911,7 @@ void hostif_stop_confirm(struct ks_wlan_private *priv) if ((priv->connect_status & CONNECT_STATUS_MASK) == DISCONNECT_STATUS && (old_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) { - memset(wrqu0.ap_addr.sa_data, '\0', ETH_ALEN); + eth_zero_addr(wrqu0.ap_addr.sa_data); DPRINTK(3, "IWEVENT: disconnect\n"); printk("IWEVENT: disconnect\n"); DPRINTK(3, "disconnect :: scan_ind_count=%d\n", diff --git a/drivers/staging/ks7010/ks_wlan_net.c b/drivers/staging/ks7010/ks_wlan_net.c index c17c45d..70cc9be 100644 --- a/drivers/staging/ks7010/ks_wlan_net.c +++ b/drivers/staging/ks7010/ks_wlan_net.c @@ -401,7 +401,7 @@ static int ks_wlan_set_wap(struct net_device *dev, struct iw_request_info *info, priv->need_commit |= SME_MODE_SET; } } else { - memset(priv->reg.bssid, 0x0, ETH_ALEN); + eth_zero_addr(priv->reg.bssid); return -EOPNOTSUPP; } @@ -432,7 +432,7 @@ static int ks_wlan_get_wap(struct net_device *dev, struct iw_request_info *info, if ((priv->connect_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) { memcpy(awrq->sa_data, &(priv->current_ap.bssid[0]), ETH_ALEN); } else { - memset(awrq->sa_data, 0, ETH_ALEN); + eth_zero_addr(awrq->sa_data); } awrq->sa_family = ARPHRD_ETHER; @@ -2091,7 +2091,7 @@ static int ks_wlan_set_pmksa(struct net_device *dev, list_for_each(ptr, &priv->pmklist.head) { pmk = list_entry(ptr, struct pmk_t, list); if (!memcmp(pmksa->bssid.sa_data, pmk->bssid, ETH_ALEN)) { /* match address! list del. */ - memset(pmk->bssid, 0, ETH_ALEN); + eth_zero_addr(pmk->bssid); memset(pmk->pmkid, 0, IW_PMKID_LEN); list_del_init(&pmk->list); break; -- cgit v0.10.2 From 63ed97ecf79059c917eacf23ed6cd260bcaabd3b Mon Sep 17 00:00:00 2001 From: Richard Groux <rgroux@sauron-mordor.net> Date: Fri, 16 Sep 2016 17:51:02 +0200 Subject: staging: lustre: include/lustre_net.h: Remove unnecessary space before function pointer arguments. Minor warnings spotted by checkpatch.pl in lustre Remove unnecessary space before function pointer arguments. Signed-off-by: Richard Groux <rgroux@sauron-mordor.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre_net.h b/drivers/staging/lustre/lustre/include/lustre_net.h index d5debd6..24ddccab 100644 --- a/drivers/staging/lustre/lustre/include/lustre_net.h +++ b/drivers/staging/lustre/lustre/include/lustre_net.h @@ -570,13 +570,13 @@ struct ptlrpc_nrs_pol_ops { * * \param[in,out] policy The policy being initialized */ - int (*op_policy_init) (struct ptlrpc_nrs_policy *policy); + int (*op_policy_init)(struct ptlrpc_nrs_policy *policy); /** * Called during policy unregistration; this operation is optional. * * \param[in,out] policy The policy being unregistered/finalized */ - void (*op_policy_fini) (struct ptlrpc_nrs_policy *policy); + void (*op_policy_fini)(struct ptlrpc_nrs_policy *policy); /** * Called when activating a policy via lprocfs; policies allocate and * initialize their resources here; this operation is optional. @@ -585,7 +585,7 @@ struct ptlrpc_nrs_pol_ops { * * \see nrs_policy_start_locked() */ - int (*op_policy_start) (struct ptlrpc_nrs_policy *policy); + int (*op_policy_start)(struct ptlrpc_nrs_policy *policy); /** * Called when deactivating a policy via lprocfs; policies deallocate * their resources here; this operation is optional @@ -594,7 +594,7 @@ struct ptlrpc_nrs_pol_ops { * * \see nrs_policy_stop0() */ - void (*op_policy_stop) (struct ptlrpc_nrs_policy *policy); + void (*op_policy_stop)(struct ptlrpc_nrs_policy *policy); /** * Used for policy-specific operations; i.e. not generic ones like * \e PTLRPC_NRS_CTL_START and \e PTLRPC_NRS_CTL_GET_INFO; analogous @@ -610,8 +610,8 @@ struct ptlrpc_nrs_pol_ops { * * \see ptlrpc_nrs_policy_control() */ - int (*op_policy_ctl) (struct ptlrpc_nrs_policy *policy, - enum ptlrpc_nrs_ctl opc, void *arg); + int (*op_policy_ctl)(struct ptlrpc_nrs_policy *policy, + enum ptlrpc_nrs_ctl opc, void *arg); /** * Called when obtaining references to the resources of the resource @@ -648,11 +648,11 @@ struct ptlrpc_nrs_pol_ops { * \see ptlrpc_nrs_req_initialize() * \see ptlrpc_nrs_hpreq_add_nolock() */ - int (*op_res_get) (struct ptlrpc_nrs_policy *policy, - struct ptlrpc_nrs_request *nrq, - const struct ptlrpc_nrs_resource *parent, - struct ptlrpc_nrs_resource **resp, - bool moving_req); + int (*op_res_get)(struct ptlrpc_nrs_policy *policy, + struct ptlrpc_nrs_request *nrq, + const struct ptlrpc_nrs_resource *parent, + struct ptlrpc_nrs_resource **resp, + bool moving_req); /** * Called when releasing references taken for resources in the resource * hierarchy for the request; this operation is optional. @@ -663,8 +663,8 @@ struct ptlrpc_nrs_pol_ops { * \see ptlrpc_nrs_req_finalize() * \see ptlrpc_nrs_hpreq_add_nolock() */ - void (*op_res_put) (struct ptlrpc_nrs_policy *policy, - const struct ptlrpc_nrs_resource *res); + void (*op_res_put)(struct ptlrpc_nrs_policy *policy, + const struct ptlrpc_nrs_resource *res); /** * Obtains a request for handling from the policy, and optionally @@ -683,8 +683,8 @@ struct ptlrpc_nrs_pol_ops { * \see ptlrpc_nrs_req_get_nolock() */ struct ptlrpc_nrs_request * - (*op_req_get) (struct ptlrpc_nrs_policy *policy, bool peek, - bool force); + (*op_req_get)(struct ptlrpc_nrs_policy *policy, bool peek, + bool force); /** * Called when attempting to add a request to a policy for later * handling; this operation is mandatory. @@ -697,8 +697,8 @@ struct ptlrpc_nrs_pol_ops { * * \see ptlrpc_nrs_req_add_nolock() */ - int (*op_req_enqueue) (struct ptlrpc_nrs_policy *policy, - struct ptlrpc_nrs_request *nrq); + int (*op_req_enqueue)(struct ptlrpc_nrs_policy *policy, + struct ptlrpc_nrs_request *nrq); /** * Removes a request from the policy's set of pending requests. Normally * called after a request has been polled successfully from the policy @@ -707,8 +707,8 @@ struct ptlrpc_nrs_pol_ops { * \param[in,out] policy The policy the request \a nrq belongs to * \param[in,out] nrq The request to dequeue */ - void (*op_req_dequeue) (struct ptlrpc_nrs_policy *policy, - struct ptlrpc_nrs_request *nrq); + void (*op_req_dequeue)(struct ptlrpc_nrs_policy *policy, + struct ptlrpc_nrs_request *nrq); /** * Called after the request being carried out. Could be used for * job/resource control; this operation is optional. @@ -721,8 +721,8 @@ struct ptlrpc_nrs_pol_ops { * * \see ptlrpc_nrs_req_stop_nolock() */ - void (*op_req_stop) (struct ptlrpc_nrs_policy *policy, - struct ptlrpc_nrs_request *nrq); + void (*op_req_stop)(struct ptlrpc_nrs_policy *policy, + struct ptlrpc_nrs_request *nrq); /** * Registers the policy's lprocfs interface with a PTLRPC service. * @@ -731,7 +731,7 @@ struct ptlrpc_nrs_pol_ops { * \retval 0 success * \retval != 0 error */ - int (*op_lprocfs_init) (struct ptlrpc_service *svc); + int (*op_lprocfs_init)(struct ptlrpc_service *svc); /** * Unegisters the policy's lprocfs interface with a PTLRPC service. * @@ -743,7 +743,7 @@ struct ptlrpc_nrs_pol_ops { * * \param[in] svc The service */ - void (*op_lprocfs_fini) (struct ptlrpc_service *svc); + void (*op_lprocfs_fini)(struct ptlrpc_service *svc); }; /** -- cgit v0.10.2 From c276af40ef8d7cfbe257bd41a9d2501178de7e79 Mon Sep 17 00:00:00 2001 From: Baoyou Xie <baoyou.xie@linaro.org> Date: Sat, 17 Sep 2016 21:41:39 +0800 Subject: staging: lustre: clean function declaration in super25.c up We get 1 warning when building kernel with W=1: drivers/staging/lustre/lnet/selftest/conctl.c:804:1: warning: no previous prototype for 'lstcon_ioctl_entry' [-Wmissing-prototypes] In fact, this function is declared in drivers/staging/lustre/lustre/llite/super25.c, but should be moved into a header file, thus can be recognized in other file. So this patch moves the declaration into drivers/staging/lustre/lnet/selftest/console.h Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index 4c33621..a0fcbf3 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -1993,8 +1993,6 @@ static void lstcon_init_acceptor_service(void) lstcon_acceptor_service.sv_wi_total = SFW_FRWK_WI_MAX; } -extern int lstcon_ioctl_entry(unsigned int cmd, struct libcfs_ioctl_hdr *hdr); - static DECLARE_IOCTL_HANDLER(lstcon_ioctl_handler, lstcon_ioctl_entry); /* initialize console */ diff --git a/drivers/staging/lustre/lnet/selftest/console.h b/drivers/staging/lustre/lnet/selftest/console.h index 78b1477..78388a6 100644 --- a/drivers/staging/lustre/lnet/selftest/console.h +++ b/drivers/staging/lustre/lnet/selftest/console.h @@ -184,6 +184,7 @@ lstcon_id2hash(lnet_process_id_t id, struct list_head *hash) return &hash[idx]; } +int lstcon_ioctl_entry(unsigned int cmd, struct libcfs_ioctl_hdr *hdr); int lstcon_console_init(void); int lstcon_console_fini(void); int lstcon_session_match(lst_sid_t sid); -- cgit v0.10.2 From c2e1b91ed8b1b48b0aa5613c2cfd4cb3aac8d0af Mon Sep 17 00:00:00 2001 From: Baoyou Xie <baoyou.xie@linaro.org> Date: Sat, 17 Sep 2016 21:37:03 +0800 Subject: staging/lustre: clean function declaration in super25.c up We get 1 warning when building kernel with W=1: drivers/staging/lustre/lustre/obdclass/obd_config.c:719:6: warning: no previous prototype for 'lustre_register_client_process_config' [-Wmissing-prototypes] In fact, this function is declared in drivers/staging/lustre/lustre/llite/super25.c, but should be moved into a header file, thus can be recognized in other file. So this patch moves the declaration into drivers/staging/lustre/lustre/include/lprocfs_status.h. Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lprocfs_status.h b/drivers/staging/lustre/lustre/include/lprocfs_status.h index ff35e63..795d446 100644 --- a/drivers/staging/lustre/lustre/include/lprocfs_status.h +++ b/drivers/staging/lustre/lustre/include/lprocfs_status.h @@ -363,6 +363,9 @@ static inline void s2dhms(struct dhms *ts, time64_t secs64) #define JOBSTATS_PROCNAME_UID "procname_uid" #define JOBSTATS_NODELOCAL "nodelocal" +/* obd_config.c */ +void lustre_register_client_process_config(int (*cpc)(struct lustre_cfg *lcfg)); + int lprocfs_write_frac_helper(const char __user *buffer, unsigned long count, int *val, int mult); int lprocfs_read_frac_helper(char *buffer, unsigned long count, diff --git a/drivers/staging/lustre/lustre/llite/super25.c b/drivers/staging/lustre/lustre/llite/super25.c index 883084e..24c79c2 100644 --- a/drivers/staging/lustre/lustre/llite/super25.c +++ b/drivers/staging/lustre/lustre/llite/super25.c @@ -83,8 +83,6 @@ struct super_operations lustre_super_operations = { }; MODULE_ALIAS_FS("lustre"); -void lustre_register_client_process_config(int (*cpc)(struct lustre_cfg *lcfg)); - static int __init lustre_init(void) { lnet_process_id_t lnet_id; -- cgit v0.10.2 From af78e1e8f245c014e51347ad2e767fad5bbc1459 Mon Sep 17 00:00:00 2001 From: Baoyou Xie <baoyou.xie@linaro.org> Date: Sat, 17 Sep 2016 21:30:35 +0800 Subject: staging: lustre: obdclass: clean function declarations in obd_config.c and class_obd.c up We get 3 warnings when building kernel with W=1: drivers/staging/lustre/lustre/obdclass/obd_mount.c:705:5: warning: no previous prototype for 'lustre_check_exclusion' [-Wmissing-prototypes] drivers/staging/lustre/lustre/obdclass/obd_mount.c:1226:5: warning: no previous prototype for 'lustre_register_fs' [-Wmissing-prototypes] drivers/staging/lustre/lustre/obdclass/obd_mount.c:1231:5: warning: no previous prototype for 'lustre_unregister_fs' [-Wmissing-prototypes] In fact, the first function is declared in drivers/staging/lustre/lustre/obdclass/obd_config.c, and the other two functions are declared in drivers/staging/lustre/lustre/obdclass/class_obd.c, but all of these functions should be declared in a header file, thus can be recognized in other file. So this patch moves the declarations into drivers/staging/lustre/lustre/include/obd_class.h. Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index 324c70d..8e8df08 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -1696,6 +1696,9 @@ struct lwp_register_item { extern int (*ptlrpc_put_connection_superhack)(struct ptlrpc_connection *c); /* obd_mount.c */ +int lustre_unregister_fs(void); +int lustre_register_fs(void); +int lustre_check_exclusion(struct super_block *sb, char *svname); /* sysctl.c */ int obd_sysctl_init(void); diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c index 710039a..2293f6a 100644 --- a/drivers/staging/lustre/lustre/obdclass/class_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c @@ -450,8 +450,6 @@ static int __init obdclass_init(void) { int i, err; - int lustre_register_fs(void); - LCONSOLE_INFO("Lustre: Build Version: " LUSTRE_VERSION_STRING "\n"); spin_lock_init(&obd_types_lock); @@ -518,8 +516,6 @@ static int __init obdclass_init(void) static void obdclass_exit(void) { - int lustre_unregister_fs(void); - lustre_unregister_fs(); misc_deregister(&obd_psdev); diff --git a/drivers/staging/lustre/lustre/obdclass/obd_config.c b/drivers/staging/lustre/lustre/obdclass/obd_config.c index b7dcadb..036f396 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_config.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_config.c @@ -1047,8 +1047,6 @@ int class_process_proc_param(char *prefix, struct lprocfs_vars *lvars, } EXPORT_SYMBOL(class_process_proc_param); -extern int lustre_check_exclusion(struct super_block *sb, char *svname); - /** Parse a configuration llog, doing various manipulations on them * for various reasons, (modifications for compatibility, skip obsolete * records, change uuids, etc), then class_process_config() resulting -- cgit v0.10.2 From b3f863a6bce01196bf5298f1801a260595de75dd Mon Sep 17 00:00:00 2001 From: Baoyou Xie <baoyou.xie@linaro.org> Date: Sat, 17 Sep 2016 21:24:08 +0800 Subject: staging/lustre: clean function declaration in cl_io.c up We get 1 warning when building kernel with W=1: drivers/staging/lustre/lustre/obdclass/cl_page.c:488:6: warning: no previous prototype for 'cl_page_disown0' [-Wmissing-prototypes] In fact, this function is declared in drivers/staging/lustre/lustre/obdclass/cl_io.c, but should be removed in a header file. thus can be recognized in other file. So this patch moves the declaration into drivers/staging/lustre/lustre/include/cl_object.h. Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index 5e63a27..41e0801 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -2254,6 +2254,8 @@ void cl_page_unassume(const struct lu_env *env, struct cl_io *io, struct cl_page *pg); void cl_page_disown(const struct lu_env *env, struct cl_io *io, struct cl_page *page); +void cl_page_disown0(const struct lu_env *env, + struct cl_io *io, struct cl_page *pg); int cl_page_is_owned(const struct cl_page *pg, const struct cl_io *io); /** @} ownership */ diff --git a/drivers/staging/lustre/lustre/obdclass/cl_io.c b/drivers/staging/lustre/lustre/obdclass/cl_io.c index 4516fff..6643e78 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_io.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_io.c @@ -936,8 +936,6 @@ void cl_page_list_splice(struct cl_page_list *list, struct cl_page_list *head) } EXPORT_SYMBOL(cl_page_list_splice); -void cl_page_disown0(const struct lu_env *env, - struct cl_io *io, struct cl_page *pg); /** * Disowns pages in a queue. -- cgit v0.10.2 From 5adb3290ba8738f6f864488fce0ff19f56325eb8 Mon Sep 17 00:00:00 2001 From: Baoyou Xie <baoyou.xie@linaro.org> Date: Sat, 17 Sep 2016 20:04:36 +0800 Subject: staging: lustre: lmv: mark symbols static where possible We get a few warnings when building kernel with W=1: drivers/staging/lustre/lustre/lmv/lmv_obd.c:1640:1: warning: no previous prototype for 'lmv_locate_target_for_name' [-Wmissing-prototypes] drivers/staging/lustre/lustre/lmv/lmv_obd.c:2421:5: warning: no previous prototype for 'lmv_read_page' [-Wmissing-prototypes] .... In fact, these functions are only used in the file in which they are declared and don't need a declaration, but can be made static. so this patch marks these functions with 'static'. Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index dc752d5..5783359 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -1636,7 +1636,7 @@ static int lmv_close(struct obd_export *exp, struct md_op_data *op_data, * For striped-directory, it will locate MDT by name. And also * it will reset op_fid1 with the FID of the chosen stripe. **/ -struct lmv_tgt_desc * +static struct lmv_tgt_desc * lmv_locate_target_for_name(struct lmv_obd *lmv, struct lmv_stripe_md *lsm, const char *name, int namelen, struct lu_fid *fid, u32 *mds) @@ -2418,9 +2418,9 @@ out: return rc; } -int lmv_read_page(struct obd_export *exp, struct md_op_data *op_data, - struct md_callback *cb_op, __u64 offset, - struct page **ppage) +static int lmv_read_page(struct obd_export *exp, struct md_op_data *op_data, + struct md_callback *cb_op, __u64 offset, + struct page **ppage) { struct lmv_stripe_md *lsm = op_data->op_mea1; struct obd_device *obd = exp->exp_obd; @@ -2771,8 +2771,9 @@ static int lmv_pack_md_v1(const struct lmv_stripe_md *lsm, return 0; } -int lmv_pack_md(union lmv_mds_md **lmmp, const struct lmv_stripe_md *lsm, - int stripe_count) +static int +lmv_pack_md(union lmv_mds_md **lmmp, const struct lmv_stripe_md *lsm, + int stripe_count) { int lmm_size = 0, rc = 0; bool allocated = false; @@ -2966,15 +2967,15 @@ int lmv_unpack_md(struct obd_export *exp, struct lmv_stripe_md **lsmp, } EXPORT_SYMBOL(lmv_unpack_md); -int lmv_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, - struct lov_mds_md *lmm, int disk_len) +static int lmv_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, + struct lov_mds_md *lmm, int disk_len) { return lmv_unpack_md(exp, (struct lmv_stripe_md **)lsmp, (union lmv_mds_md *)lmm, disk_len); } -int lmv_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, - struct lov_stripe_md *lsm) +static int lmv_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, + struct lov_stripe_md *lsm) { const struct lmv_stripe_md *lmv = (struct lmv_stripe_md *)lsm; struct obd_device *obd = exp->exp_obd; @@ -3177,9 +3178,10 @@ static int lmv_revalidate_lock(struct obd_export *exp, struct lookup_intent *it, return rc; } -int lmv_get_fid_from_lsm(struct obd_export *exp, - const struct lmv_stripe_md *lsm, - const char *name, int namelen, struct lu_fid *fid) +static int +lmv_get_fid_from_lsm(struct obd_export *exp, + const struct lmv_stripe_md *lsm, + const char *name, int namelen, struct lu_fid *fid) { const struct lmv_oinfo *oinfo; @@ -3269,14 +3271,16 @@ static int lmv_quotacheck(struct obd_device *unused, struct obd_export *exp, return rc; } -int lmv_update_lsm_md(struct obd_export *exp, struct lmv_stripe_md *lsm, - struct mdt_body *body, ldlm_blocking_callback cb_blocking) +static int +lmv_update_lsm_md(struct obd_export *exp, struct lmv_stripe_md *lsm, + struct mdt_body *body, ldlm_blocking_callback cb_blocking) { return lmv_revalidate_slaves(exp, body, lsm, cb_blocking, 0); } -int lmv_merge_attr(struct obd_export *exp, const struct lmv_stripe_md *lsm, - struct cl_attr *attr) +static int +lmv_merge_attr(struct obd_export *exp, const struct lmv_stripe_md *lsm, + struct cl_attr *attr) { int i; -- cgit v0.10.2 From 2296f5215fd32c371f51a20155f9719b2366b7bf Mon Sep 17 00:00:00 2001 From: Namrata A Shettar <namrataashettar@gmail.com> Date: Sat, 17 Sep 2016 17:56:59 +0530 Subject: staging: rts5208: rtsx_chip: Add space around binary operators Add space around binary operators to resolve checkpatch issue. Signed-off-by: Namrata A Shettar <namrataashettar@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rts5208/rtsx_chip.c b/drivers/staging/rts5208/rtsx_chip.c index bcc4b66..c75493a 100644 --- a/drivers/staging/rts5208/rtsx_chip.c +++ b/drivers/staging/rts5208/rtsx_chip.c @@ -760,7 +760,7 @@ static inline int check_sd_current_prior(u32 sd_current_prior) int i; for (i = 0; i < 4; i++) { - u8 tmp = (u8)(sd_current_prior >> (i*8)); + u8 tmp = (u8)(sd_current_prior >> (i * 8)); if (tmp > 0x03) { fake_para = true; @@ -2288,7 +2288,7 @@ int rtsx_read_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len) ptr = buf; reg_addr = PPBUF_BASE2; - for (i = 0; i < buf_len/256; i++) { + for (i = 0; i < buf_len / 256; i++) { rtsx_init_cmd(chip); for (j = 0; j < 256; j++) @@ -2304,10 +2304,10 @@ int rtsx_read_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len) ptr += 256; } - if (buf_len%256) { + if (buf_len % 256) { rtsx_init_cmd(chip); - for (j = 0; j < buf_len%256; j++) + for (j = 0; j < buf_len % 256; j++) rtsx_add_cmd(chip, READ_REG_CMD, reg_addr++, 0, 0); retval = rtsx_send_cmd(chip, 0, 250); @@ -2317,7 +2317,7 @@ int rtsx_read_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len) } } - memcpy(ptr, rtsx_get_cmd_data(chip), buf_len%256); + memcpy(ptr, rtsx_get_cmd_data(chip), buf_len % 256); return STATUS_SUCCESS; } -- cgit v0.10.2 From 2751bc918e61a114704f2a6673d316a38878319d Mon Sep 17 00:00:00 2001 From: Bhumika Goyal <bhumirks@gmail.com> Date: Sat, 17 Sep 2016 13:09:13 +0530 Subject: Staging: ks7010: Remove extern keyword from function declaration Remove extern specifier from function declaration as they have it by default. Also move extern declaration from .c files to their respective header file 'ks_hostif.h'. Coccinelle was used to remove extern and other changes were done by hand. Script: @@ identifier func; type T; @@ - extern T func(...); Signed-off-by: Bhumika Goyal <bhumirks@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c index deb82ab..eb0192d 100644 --- a/drivers/staging/ks7010/ks_hostif.c +++ b/drivers/staging/ks7010/ks_hostif.c @@ -21,15 +21,6 @@ /* Include Wireless Extension definition and check version */ #include <net/iw_handler.h> /* New driver API */ -extern int ks_wlan_hw_tx(struct ks_wlan_private *priv, void *p, - unsigned long size, - void (*complete_handler) (void *arg1, void *arg2), - void *arg1, void *arg2); -extern void send_packet_complete(void *, void *); - -extern void ks_wlan_hw_wakeup_request(struct ks_wlan_private *priv); -extern int ks_wlan_hw_power_save(struct ks_wlan_private *priv); - /* macro */ #define inc_smeqhead(priv) \ ( priv->sme_i.qhead = (priv->sme_i.qhead + 1) % SME_EVENT_BUFF_SIZE ) diff --git a/drivers/staging/ks7010/ks_hostif.h b/drivers/staging/ks7010/ks_hostif.h index dc806b5b..ffd0174 100644 --- a/drivers/staging/ks7010/ks_hostif.h +++ b/drivers/staging/ks7010/ks_hostif.h @@ -616,13 +616,21 @@ enum { #include "ks_wlan.h" /* function prototype */ -extern int hostif_data_request(struct ks_wlan_private *priv, - struct sk_buff *packet); -extern void hostif_receive(struct ks_wlan_private *priv, unsigned char *p, - unsigned int size); -extern void hostif_sme_enqueue(struct ks_wlan_private *priv, uint16_t event); -extern int hostif_init(struct ks_wlan_private *priv); -extern void hostif_exit(struct ks_wlan_private *priv); +int hostif_data_request(struct ks_wlan_private *priv, + struct sk_buff *packet); +void hostif_receive(struct ks_wlan_private *priv, unsigned char *p, + unsigned int size); +void hostif_sme_enqueue(struct ks_wlan_private *priv, uint16_t event); +int hostif_init(struct ks_wlan_private *priv); +void hostif_exit(struct ks_wlan_private *priv); +int ks_wlan_hw_tx(struct ks_wlan_private *priv, void *p, + unsigned long size, + void (*complete_handler) (void *arg1, void *arg2), + void *arg1, void *arg2); +void send_packet_complete(void *, void *); + +void ks_wlan_hw_wakeup_request(struct ks_wlan_private *priv); +int ks_wlan_hw_power_save(struct ks_wlan_private *priv); static inline int hif_align_size(int size) diff --git a/drivers/staging/ks7010/ks_wlan.h b/drivers/staging/ks7010/ks_wlan.h index f05dc01..693e7d8 100644 --- a/drivers/staging/ks7010/ks_wlan.h +++ b/drivers/staging/ks7010/ks_wlan.h @@ -499,7 +499,7 @@ struct ks_wlan_private { uint wakeup_count; /* for detect wakeup loop */ }; -extern int ks_wlan_net_start(struct net_device *dev); -extern int ks_wlan_net_stop(struct net_device *dev); +int ks_wlan_net_start(struct net_device *dev); +int ks_wlan_net_stop(struct net_device *dev); #endif /* _KS_WLAN_H */ diff --git a/drivers/staging/ks7010/ks_wlan_ioctl.h b/drivers/staging/ks7010/ks_wlan_ioctl.h index 49369e4..84554b6 100644 --- a/drivers/staging/ks7010/ks_wlan_ioctl.h +++ b/drivers/staging/ks7010/ks_wlan_ioctl.h @@ -58,9 +58,9 @@ #include "ks_wlan.h" #include <linux/netdevice.h> -extern int ks_wlan_read_config_file(struct ks_wlan_private *priv); -extern int ks_wlan_setup_parameter(struct ks_wlan_private *priv, - unsigned int commit_flag); +int ks_wlan_read_config_file(struct ks_wlan_private *priv); +int ks_wlan_setup_parameter(struct ks_wlan_private *priv, + unsigned int commit_flag); #endif /* __KERNEL__ */ diff --git a/drivers/staging/ks7010/ks_wlan_net.c b/drivers/staging/ks7010/ks_wlan_net.c index 70cc9be..ee9c8f3 100644 --- a/drivers/staging/ks7010/ks_wlan_net.c +++ b/drivers/staging/ks7010/ks_wlan_net.c @@ -69,10 +69,6 @@ static const struct iw_handler_def ks_wlan_handler_def; /* * function prototypes */ -extern int ks_wlan_hw_tx(struct ks_wlan_private *priv, void *p, - unsigned long size, - void (*complete_handler) (void *arg1, void *arg2), - void *arg1, void *arg2); static int ks_wlan_open(struct net_device *dev); static void ks_wlan_tx_timeout(struct net_device *dev); static int ks_wlan_start_xmit(struct sk_buff *skb, struct net_device *dev); diff --git a/drivers/staging/ks7010/michael_mic.h b/drivers/staging/ks7010/michael_mic.h index c7e4eb2..89f17d5 100644 --- a/drivers/staging/ks7010/michael_mic.h +++ b/drivers/staging/ks7010/michael_mic.h @@ -20,7 +20,6 @@ struct michel_mic_t { uint8_t Result[8]; }; -extern void MichaelMICFunction(struct michel_mic_t *Mic, uint8_t * Key, uint8_t * Data, int Len, uint8_t priority, uint8_t * Result); -- cgit v0.10.2 From f9c7cb1cb5e1d81d24bf2d2c79229a3f25ab7e5d Mon Sep 17 00:00:00 2001 From: sayli karnik <karniksayli1995@gmail.com> Date: Sat, 17 Sep 2016 00:14:57 +0530 Subject: staging: media: davinci_vpfe: Use BIT macro instead of left shifting 1 This patch replaces left shifts on 1 with the BIT(x) macro, as suggested by checkpatch.pl. This was done using coccinelle script: @@ constant c; @@ - (1 << c) + BIT(c) Signed-off-by: sayli karnik <karniksayli1995@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h b/drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h index f4f35c9..d3f34f9 100644 --- a/drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h +++ b/drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h @@ -544,41 +544,41 @@ struct vpfe_isif_raw_config { /* IPIPE module configurations */ /* IPIPE input configuration */ -#define VPFE_IPIPE_INPUT_CONFIG (1 << 0) +#define VPFE_IPIPE_INPUT_CONFIG BIT(0) /* LUT based Defect Pixel Correction */ -#define VPFE_IPIPE_LUTDPC (1 << 1) +#define VPFE_IPIPE_LUTDPC BIT(1) /* On the fly (OTF) Defect Pixel Correction */ -#define VPFE_IPIPE_OTFDPC (1 << 2) +#define VPFE_IPIPE_OTFDPC BIT(2) /* Noise Filter - 1 */ -#define VPFE_IPIPE_NF1 (1 << 3) +#define VPFE_IPIPE_NF1 BIT(3) /* Noise Filter - 2 */ -#define VPFE_IPIPE_NF2 (1 << 4) +#define VPFE_IPIPE_NF2 BIT(4) /* White Balance. Also a control ID */ -#define VPFE_IPIPE_WB (1 << 5) +#define VPFE_IPIPE_WB BIT(5) /* 1st RGB to RBG Blend module */ -#define VPFE_IPIPE_RGB2RGB_1 (1 << 6) +#define VPFE_IPIPE_RGB2RGB_1 BIT(6) /* 2nd RGB to RBG Blend module */ -#define VPFE_IPIPE_RGB2RGB_2 (1 << 7) +#define VPFE_IPIPE_RGB2RGB_2 BIT(7) /* Gamma Correction */ -#define VPFE_IPIPE_GAMMA (1 << 8) +#define VPFE_IPIPE_GAMMA BIT(8) /* 3D LUT color conversion */ -#define VPFE_IPIPE_3D_LUT (1 << 9) +#define VPFE_IPIPE_3D_LUT BIT(9) /* RGB to YCbCr module */ -#define VPFE_IPIPE_RGB2YUV (1 << 10) +#define VPFE_IPIPE_RGB2YUV BIT(10) /* YUV 422 conversion module */ -#define VPFE_IPIPE_YUV422_CONV (1 << 11) +#define VPFE_IPIPE_YUV422_CONV BIT(11) /* Edge Enhancement */ -#define VPFE_IPIPE_YEE (1 << 12) +#define VPFE_IPIPE_YEE BIT(12) /* Green Imbalance Correction */ -#define VPFE_IPIPE_GIC (1 << 13) +#define VPFE_IPIPE_GIC BIT(13) /* CFA Interpolation */ -#define VPFE_IPIPE_CFA (1 << 14) +#define VPFE_IPIPE_CFA BIT(14) /* Chroma Artifact Reduction */ -#define VPFE_IPIPE_CAR (1 << 15) +#define VPFE_IPIPE_CAR BIT(15) /* Chroma Gain Suppression */ -#define VPFE_IPIPE_CGS (1 << 16) +#define VPFE_IPIPE_CGS BIT(16) /* Global brightness and contrast control */ -#define VPFE_IPIPE_GBCE (1 << 17) +#define VPFE_IPIPE_GBCE BIT(17) #define VPFE_IPIPE_MAX_MODULES 18 -- cgit v0.10.2 From a0db9c0a529d4407a1ed4bf697a09f50ae3e9744 Mon Sep 17 00:00:00 2001 From: sayli karnik <karniksayli1995@gmail.com> Date: Fri, 16 Sep 2016 23:29:30 +0530 Subject: staging: media: davinci_vpfe: Replace explicit NULL comparison with ! operator This patch replaces the explicit NULL comparisons with ! operator. It was found using Coccinelle: @disable is_null@ expression e; @@ - e == NULL + !e Signed-off-by: sayli karnik <karniksayli1995@gmail.com> Acked-by: Julia Lawall <julia.lawall@lip6.fr> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c index 3319fb8..8be9f85 100644 --- a/drivers/staging/media/davinci_vpfe/vpfe_video.c +++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c @@ -37,7 +37,7 @@ static struct media_entity *vpfe_get_input_entity struct media_pad *remote; remote = media_entity_remote_pad(&vpfe_dev->vpfe_isif.pads[0]); - if (remote == NULL) { + if (!remote) { pr_err("Invalid media connection to isif/ccdc\n"); return NULL; } @@ -54,7 +54,7 @@ static int vpfe_update_current_ext_subdev(struct vpfe_video_device *video) int i; remote = media_entity_remote_pad(&vpfe_dev->vpfe_isif.pads[0]); - if (remote == NULL) { + if (!remote) { pr_err("Invalid media connection to isif/ccdc\n"); return -EINVAL; } @@ -107,7 +107,7 @@ __vpfe_video_get_format(struct vpfe_video_device *video, int ret; subdev = vpfe_video_remote_subdev(video, &pad); - if (subdev == NULL) + if (!subdev) return -EINVAL; fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; @@ -236,7 +236,7 @@ static int vpfe_video_validate_pipeline(struct vpfe_pipeline *pipe) * format of the connected pad. */ subdev = vpfe_video_remote_subdev(pipe->outputs[0], NULL); - if (subdev == NULL) + if (!subdev) return -EPIPE; while (1) { @@ -413,7 +413,7 @@ static int vpfe_open(struct file *file) /* Allocate memory for the file handle object */ handle = kzalloc(sizeof(struct vpfe_fh), GFP_KERNEL); - if (handle == NULL) + if (!handle) return -ENOMEM; v4l2_fh_init(&handle->vfh, &video->video_dev); @@ -683,14 +683,14 @@ static int vpfe_enum_fmt(struct file *file, void *priv, } /* get the remote pad */ remote = media_entity_remote_pad(&video->pad); - if (remote == NULL) { + if (!remote) { v4l2_err(&vpfe_dev->v4l2_dev, "invalid remote pad for video node\n"); return -EINVAL; } /* get the remote subdev */ subdev = vpfe_video_remote_subdev(video, NULL); - if (subdev == NULL) { + if (!subdev) { v4l2_err(&vpfe_dev->v4l2_dev, "invalid remote subdev for video node\n"); return -EINVAL; -- cgit v0.10.2 From 069bb6a807950ee3eb2a7365248140bf186889ba Mon Sep 17 00:00:00 2001 From: sayli karnik <karniksayli1995@gmail.com> Date: Sat, 17 Sep 2016 02:03:45 +0530 Subject: staging: olpc_dcon: Replace u_int8_t with u8 This patch replaces type u_int8_t with u8 as suggested by checkpatch.pl. Signed-off-by: sayli karnik <karniksayli1995@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c b/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c index 6a4d379..1e23ef1 100644 --- a/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c +++ b/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c @@ -49,7 +49,7 @@ static void dcon_clear_irq(void) static int dcon_was_irq(void) { - u_int8_t tmp; + u8 tmp; /* irq status will appear in PMIO_Rx50[6] on gpio12 */ tmp = inb(VX855_GPI_STATUS_CHG); -- cgit v0.10.2 From fbafd397fb63c787f302f1ca6db281a87cdb0ca9 Mon Sep 17 00:00:00 2001 From: Andrew Kanner <andrew.kanner@gmail.com> Date: Sat, 17 Sep 2016 01:28:13 +0300 Subject: drivers: staging: vme: convert to octal notation for permission bits Ran checkpatch.pl -f vme_pio2_core.c Fixed: WARNING: Symbolic permissions are not preferred. Consider using octal permissions (0444) Signed-off-by: Andrew Kanner <andrew.kanner@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/vme/devices/vme_pio2_core.c b/drivers/staging/vme/devices/vme_pio2_core.c index 28a4568..8e66a52 100644 --- a/drivers/staging/vme/devices/vme_pio2_core.c +++ b/drivers/staging/vme/devices/vme_pio2_core.c @@ -466,23 +466,23 @@ static void __exit pio2_exit(void) /* These are required for each board */ MODULE_PARM_DESC(bus, "Enumeration of VMEbus to which the board is connected"); -module_param_array(bus, int, &bus_num, S_IRUGO); +module_param_array(bus, int, &bus_num, 0444); MODULE_PARM_DESC(base, "Base VME address for PIO2 Registers"); -module_param_array(base, long, &base_num, S_IRUGO); +module_param_array(base, long, &base_num, 0444); MODULE_PARM_DESC(vector, "VME IRQ Vector (Lower 4 bits masked)"); -module_param_array(vector, int, &vector_num, S_IRUGO); +module_param_array(vector, int, &vector_num, 0444); MODULE_PARM_DESC(level, "VME IRQ Level"); -module_param_array(level, int, &level_num, S_IRUGO); +module_param_array(level, int, &level_num, 0444); MODULE_PARM_DESC(variant, "Last 4 characters of PIO2 board variant"); -module_param_array(variant, charp, &variant_num, S_IRUGO); +module_param_array(variant, charp, &variant_num, 0444); /* This is for debugging */ MODULE_PARM_DESC(loopback, "Enable loopback mode on all cards"); -module_param(loopback, bool, S_IRUGO); +module_param(loopback, bool, 0444); MODULE_DESCRIPTION("GE PIO2 6U VME I/O Driver"); MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com"); -- cgit v0.10.2 From c60298c5869c9bcb14721e8450e6bf6e5e7989a8 Mon Sep 17 00:00:00 2001 From: sayli karnik <karniksayli1995@gmail.com> Date: Sat, 17 Sep 2016 22:05:19 +0530 Subject: staging: rtl8188eu: core: Replace memcpy() with ether_addr_copy() if ethernet addresses are __aligned(2) This patch fixes the checkpatch warning: Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2) Done using coccinelle: @@ expression exp1, exp2; @@ - memcpy(exp1, exp2, ETH_ALEN); + ether_addr_copy(exp1, exp2); The output of pahole shows that the addresses are aligned: struct ieee80211_hdr { __le16 frame_control; /* 0 2 */ __le16 duration_id; /* 2 2 */ u8 addr1[6]; /* 4 6 */ u8 addr2[6]; /* 10 6 */ u8 addr3[6]; /* 16 6 */ __le16 seq_ctrl; /* 22 2 */ u8 addr4[6]; /* 24 6 */ /* size: 30, cachelines: 1, members: 7 */ /* last cacheline: 30 bytes */ }; struct wlan_bssid_ex { u32 Length; /* 0 4 */ unsigned char MacAddress[6]; /* 4 6 */ u8 Reserved[2]; /* 10 2 */ struct ndis_802_11_ssid Ssid; /* 12 36 */ u32 Privacy; /* 48 4 */ long int Rssi; /* 52 8 */ enum NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; /* 60 4 */ /* --- cacheline 1 boundary (64 bytes) --- */ struct ndis_802_11_config Configuration; /* 64 32 */ enum ndis_802_11_network_infra InfrastructureMode; /* 96 4 */ unsigned char SupportedRates[16]; /* 100 16 */ struct wlan_phy_info PhyInfo; /* 116 4 */ u32 IELength; /* 120 4 */ u8 IEs[768]; /* 124 768 */ /* --- cacheline 13 boundary (832 bytes) was 60 bytes ago --- */ /* size: 892, cachelines: 14, members: 13 */ /* last cacheline: 60 bytes */ }; struct stadel_event { unsigned char macaddr[6]; /* 0 6 */ unsigned char rsvd[2]; /* 6 2 */ int mac_id; /* 8 4 */ /* size: 12, cachelines: 1, members: 3 */ /* last cacheline: 12 bytes */ }; Signed-off-by: sayli karnik <karniksayli1995@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 9544e55..fa8a5ca 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -353,9 +353,9 @@ static void issue_beacon(struct adapter *padapter, int timeout_ms) fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; - memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, cur_network->MacAddress, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, bc_addr); + 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++; */ @@ -495,9 +495,9 @@ static void issue_probersp(struct adapter *padapter, unsigned char *da) fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; - memcpy(pwlanhdr->addr1, da, ETH_ALEN); - memcpy(pwlanhdr->addr2, mac, ETH_ALEN); - memcpy(pwlanhdr->addr3, bssid, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, da); + ether_addr_copy(pwlanhdr->addr2, mac); + ether_addr_copy(pwlanhdr->addr3, bssid); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; @@ -642,15 +642,15 @@ static int issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pss if (da) { /* unicast probe request frame */ - memcpy(pwlanhdr->addr1, da, ETH_ALEN); - memcpy(pwlanhdr->addr3, da, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, da); + ether_addr_copy(pwlanhdr->addr3, da); } else { /* broadcast probe request frame */ - memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); - memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, bc_addr); + ether_addr_copy(pwlanhdr->addr3, bc_addr); } - memcpy(pwlanhdr->addr2, mac, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr2, mac); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; @@ -785,9 +785,11 @@ static void issue_auth(struct adapter *padapter, struct sta_info *psta, if (psta) {/* for AP mode */ #ifdef CONFIG_88EU_AP_MODE - memcpy(pwlanhdr->addr1, psta->hwaddr, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, psta->hwaddr); + ether_addr_copy(pwlanhdr->addr2, + myid(&(padapter->eeprompriv))); + ether_addr_copy(pwlanhdr->addr3, + myid(&(padapter->eeprompriv))); /* setting auth algo number */ @@ -825,9 +827,9 @@ static void issue_auth(struct adapter *padapter, struct sta_info *psta, } else { __le32 le_tmp32; __le16 le_tmp16; - memcpy(pwlanhdr->addr1, pnetwork->MacAddress, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN); - memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, pnetwork->MacAddress); + ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv)); + ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress); /* setting auth algo number */ val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) ? 1 : 0;/* 0:OPEN System, 1:Shared key */ @@ -921,9 +923,10 @@ static void issue_asocrsp(struct adapter *padapter, unsigned short status, fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; - memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr, ETH_ALEN); - memcpy((void *)GetAddr2Ptr(pwlanhdr), myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy((void *)GetAddr3Ptr(pwlanhdr), pnetwork->MacAddress, ETH_ALEN); + ether_addr_copy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr); + ether_addr_copy((void *)GetAddr2Ptr(pwlanhdr), + myid(&(padapter->eeprompriv))); + ether_addr_copy((void *)GetAddr3Ptr(pwlanhdr), pnetwork->MacAddress); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); @@ -1044,9 +1047,9 @@ static void issue_assocreq(struct adapter *padapter) fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; - memcpy(pwlanhdr->addr1, pnetwork->MacAddress, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, pnetwork->MacAddress); + ether_addr_copy(pwlanhdr->addr2, myid(&(padapter->eeprompriv))); + ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; @@ -1252,9 +1255,9 @@ static int _issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned if (power_mode) SetPwrMgt(fctrl); - memcpy(pwlanhdr->addr1, da, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, da); + ether_addr_copy(pwlanhdr->addr2, myid(&(padapter->eeprompriv))); + ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; @@ -1380,9 +1383,9 @@ static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 SetAckpolicy(qc, pattrib->ack_policy); - memcpy(pwlanhdr->addr1, da, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, da); + ether_addr_copy(pwlanhdr->addr2, myid(&(padapter->eeprompriv))); + ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; @@ -1483,9 +1486,9 @@ static int _issue_deauth(struct adapter *padapter, unsigned char *da, unsigned s fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; - memcpy(pwlanhdr->addr1, da, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, da); + ether_addr_copy(pwlanhdr->addr2, myid(&(padapter->eeprompriv))); + ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; @@ -1601,9 +1604,9 @@ static void issue_action_BA(struct adapter *padapter, unsigned char *raddr, fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; - memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, raddr); + ether_addr_copy(pwlanhdr->addr2, myid(&(padapter->eeprompriv))); + ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; @@ -1760,9 +1763,9 @@ static void issue_action_BSSCoexistPacket(struct adapter *padapter) fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; - memcpy(pwlanhdr->addr1, cur_network->MacAddress, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, cur_network->MacAddress, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, cur_network->MacAddress); + ether_addr_copy(pwlanhdr->addr2, myid(&(padapter->eeprompriv))); + ether_addr_copy(pwlanhdr->addr3, cur_network->MacAddress); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; @@ -2159,7 +2162,7 @@ static u8 collect_bss_info(struct adapter *padapter, if (subtype == WIFI_PROBEREQ) { /* FIXME */ bssid->InfrastructureMode = Ndis802_11Infrastructure; - memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN); + ether_addr_copy(bssid->MacAddress, GetAddr2Ptr(pframe)); bssid->Privacy = 1; return _SUCCESS; } @@ -2171,10 +2174,10 @@ static u8 collect_bss_info(struct adapter *padapter, if (val16 & BIT(0)) { bssid->InfrastructureMode = Ndis802_11Infrastructure; - memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN); + ether_addr_copy(bssid->MacAddress, GetAddr2Ptr(pframe)); } else { bssid->InfrastructureMode = Ndis802_11IBSS; - memcpy(bssid->MacAddress, GetAddr3Ptr(pframe), ETH_ALEN); + ether_addr_copy(bssid->MacAddress, GetAddr3Ptr(pframe)); } if (val16 & BIT(4)) @@ -4395,7 +4398,7 @@ void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsi pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); pdel_sta_evt = (struct stadel_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); - memcpy((unsigned char *)(&(pdel_sta_evt->macaddr)), MacAddr, ETH_ALEN); + ether_addr_copy((unsigned char *)(&(pdel_sta_evt->macaddr)), MacAddr); memcpy((unsigned char *)(pdel_sta_evt->rsvd), (unsigned char *)(&reason), 2); @@ -4448,7 +4451,7 @@ void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, int pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); padd_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); - memcpy((unsigned char *)(&(padd_sta_evt->macaddr)), MacAddr, ETH_ALEN); + ether_addr_copy((unsigned char *)(&(padd_sta_evt->macaddr)), MacAddr); padd_sta_evt->cam_id = cam_idx; DBG_88E("report_add_sta_event: add STA\n"); -- cgit v0.10.2 From 9fa1f943d6fae7a5b233427139ada65d0ce372cd Mon Sep 17 00:00:00 2001 From: Namrata A Shettar <namrataashettar@gmail.com> Date: Sat, 17 Sep 2016 02:35:21 +0530 Subject: staging: rtl8712: Rename misspelt macro Correct the word 'success' being misspelt in the macro: - LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA => LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA Signed-off-by: Namrata A Shettar <namrataashettar@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8712/rtl8712_led.c b/drivers/staging/rtl8712/rtl8712_led.c index 76d0535..a6cbfdc 100644 --- a/drivers/staging/rtl8712/rtl8712_led.c +++ b/drivers/staging/rtl8712/rtl8712_led.c @@ -43,7 +43,7 @@ #define LED_BLINK_LINK_INTERVAL_ALPHA 500 #define LED_BLINK_SCAN_INTERVAL_ALPHA 180 #define LED_BLINK_FASTER_INTERVAL_ALPHA 50 -#define LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA 5000 +#define LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA 5000 /*=========================================================================== * LED object. @@ -410,7 +410,7 @@ static void SwLedBlink1(struct LED_871x *pLed) if (pLed->BlinkingLedState == LED_ON) { pLed->BlinkingLedState = LED_OFF; mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA)); + msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA)); bStopBlinking = false; } else { bStopBlinking = true; @@ -574,7 +574,7 @@ static void SwLedBlink3(struct LED_871x *pLed) if (pLed->BlinkingLedState == LED_ON) { pLed->BlinkingLedState = LED_OFF; mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA)); + msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA)); bStopBlinking = false; } else { bStopBlinking = true; @@ -1052,7 +1052,7 @@ static void SwLedControlMode1(struct _adapter *padapter, if (pLed->bLedOn) { pLed->BlinkingLedState = LED_OFF; mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA)); + msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA)); } else { pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, @@ -1332,7 +1332,7 @@ static void SwLedControlMode3(struct _adapter *padapter, if (pLed->bLedOn) { pLed->BlinkingLedState = LED_OFF; mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA)); + msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA)); } else { pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, -- cgit v0.10.2 From 6841b2a0fccf930e80e0c7d7f1bd8d78d21cd0fa Mon Sep 17 00:00:00 2001 From: Cathal Mullaney <chuckleberryfinn@gmail.com> Date: Sat, 17 Sep 2016 20:01:08 +0100 Subject: Staging: dgnc: dgnc_tty: fixed a line too long style issue Fixed a coding style issue. Signed-off-by: Cathal Mullaney <chuckleberryfinn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index 31b18e6..fd46ef0 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -186,7 +186,8 @@ int dgnc_tty_register(struct dgnc_board *brd) if (IS_ERR(brd->serial_driver)) return PTR_ERR(brd->serial_driver); - snprintf(brd->serial_name, MAXTTYNAMELEN, "tty_dgnc_%d_", brd->boardnum); + snprintf(brd->serial_name, MAXTTYNAMELEN, "tty_dgnc_%d_", + brd->boardnum); brd->serial_driver->name = brd->serial_name; brd->serial_driver->name_base = 0; -- cgit v0.10.2 From ed88363e6aebb91df820e1a8898d2a07b18d2bc9 Mon Sep 17 00:00:00 2001 From: Anchal Jain <anchalj109@gmail.com> Date: Sun, 18 Sep 2016 12:16:40 +0530 Subject: staging: olpc_dcon: Replace a bit shift by a use of BIT. This patch replaces bit shifting on 1 with the BIT(x) macro as it's extensively used by other function in the file olpc_dcon.h . Signed-off-by: Anchal Jain <anchalj109@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/olpc_dcon/olpc_dcon.h b/drivers/staging/olpc_dcon/olpc_dcon.h index 215e7ec..23a48a1 100644 --- a/drivers/staging/olpc_dcon/olpc_dcon.h +++ b/drivers/staging/olpc_dcon/olpc_dcon.h @@ -9,18 +9,18 @@ #define DCON_REG_ID 0 #define DCON_REG_MODE 1 -#define MODE_PASSTHRU (1<<0) -#define MODE_SLEEP (1<<1) -#define MODE_SLEEP_AUTO (1<<2) -#define MODE_BL_ENABLE (1<<3) -#define MODE_BLANK (1<<4) -#define MODE_CSWIZZLE (1<<5) -#define MODE_COL_AA (1<<6) -#define MODE_MONO_LUMA (1<<7) -#define MODE_SCAN_INT (1<<8) -#define MODE_CLOCKDIV (1<<9) -#define MODE_DEBUG (1<<14) -#define MODE_SELFTEST (1<<15) +#define MODE_PASSTHRU bit(0) +#define MODE_SLEEP bit(1) +#define MODE_SLEEP_AUTO bit(2) +#define MODE_BL_ENABLE bit(3) +#define MODE_BLANK bit(4) +#define MODE_CSWIZZLE bit(5) +#define MODE_COL_AA bit(6) +#define MODE_MONO_LUMA bit(7) +#define MODE_SCAN_INT bit(8) +#define MODE_CLOCKDIV bit(9) +#define MODE_DEBUG bit(14) +#define MODE_SELFTEST bit(15) #define DCON_REG_HRES 0x2 #define DCON_REG_HTOTAL 0x3 @@ -35,11 +35,11 @@ #define DCON_REG_MEM_OPT_B 0x42 /* Load Delay Locked Loop (DLL) settings for clock delay */ -#define MEM_DLL_CLOCK_DELAY (1<<0) +#define MEM_DLL_CLOCK_DELAY bit(0) /* Memory controller power down function */ -#define MEM_POWER_DOWN (1<<8) +#define MEM_POWER_DOWN bit(8) /* Memory controller software reset */ -#define MEM_SOFT_RESET (1<<0) +#define MEM_SOFT_RESET bit(0) /* Status values */ -- cgit v0.10.2 From e63ecbc774d98062cfa6b5c2ef4ecc0d1d732242 Mon Sep 17 00:00:00 2001 From: Jon Eyolfson <jon@eyl.io> Date: Sat, 17 Sep 2016 19:49:55 -0400 Subject: staging: wlan-ng: if statement style cleanup Changed if statement bodies from 2 levels deeper than if statement to 1. Signed-off-by: Jon Eyolfson <jon@eyl.io> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index 884d0d5..28be314 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -476,11 +476,11 @@ static int prism2_connect(struct wiphy *wiphy, struct net_device *dev, /* Set the authorization */ if ((sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) || - ((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && !is_wep)) - msg_join.authtype.data = P80211ENUM_authalg_opensystem; + ((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && !is_wep)) + msg_join.authtype.data = P80211ENUM_authalg_opensystem; else if ((sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY) || - ((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && is_wep)) - msg_join.authtype.data = P80211ENUM_authalg_sharedkey; + ((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && is_wep)) + msg_join.authtype.data = P80211ENUM_authalg_sharedkey; else netdev_warn(dev, "Unhandled authorisation type for connect (%d)\n", -- cgit v0.10.2 From 364bcc5a5affea5a71db5a96f17b3e374cb659dc Mon Sep 17 00:00:00 2001 From: Cathal Mullaney <chuckleberryfinn@gmail.com> Date: Sun, 18 Sep 2016 00:04:42 +0100 Subject: Staging: octeon: ethernet-rx: fixed three redundant blank line style issues Fixed three minor coding style issues. Signed-off-by: Cathal Mullaney <chuckleberryfinn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c index ce1e2a3..f0900d1 100644 --- a/drivers/staging/octeon/ethernet-rx.c +++ b/drivers/staging/octeon/ethernet-rx.c @@ -450,12 +450,10 @@ void cvm_oct_poll_controller(struct net_device *dev) return; for (i = 0; i < ARRAY_SIZE(oct_rx_group); i++) { - if (!(pow_receive_groups & BIT(i))) continue; cvm_oct_poll(&oct_rx_group[i], 16); - } } #endif @@ -537,7 +535,6 @@ void cvm_oct_rx_shutdown(void) int i; for (i = 0; i < ARRAY_SIZE(oct_rx_group); i++) { - if (!(pow_receive_groups & BIT(i))) continue; -- cgit v0.10.2 From 9f9079720a4b802555ffc6f71ce3dd8adfd78f60 Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Thu, 1 Sep 2016 11:44:36 +0200 Subject: iio: accel: kxsd9: Split out transport mechanism Split off a transport mechanism struct that will deal with the SPI traffic in preparation for adding I2C support. Tested-by: Jonathan Cameron <jic23@kernel.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c index 9d72d4b..df8a31e 100644 --- a/drivers/iio/accel/kxsd9.c +++ b/drivers/iio/accel/kxsd9.c @@ -43,18 +43,36 @@ #define KXSD9_STATE_RX_SIZE 2 #define KXSD9_STATE_TX_SIZE 2 + +struct kxsd9_transport; + +/** + * struct kxsd9_transport - transport adapter for SPI or I2C + * @trdev: transport device such as SPI or I2C + * @write1(): function to write a byte to the device + * @write2(): function to write two consecutive bytes to the device + * @readval(): function to read a 16bit value from the device + * @rx: cache aligned read buffer + * @tx: cache aligned write buffer + */ +struct kxsd9_transport { + void *trdev; + int (*write1) (struct kxsd9_transport *tr, u8 byte); + int (*write2) (struct kxsd9_transport *tr, u8 b1, u8 b2); + int (*readval) (struct kxsd9_transport *tr, u8 address); + u8 rx[KXSD9_STATE_RX_SIZE] ____cacheline_aligned; + u8 tx[KXSD9_STATE_TX_SIZE]; +}; + /** * struct kxsd9_state - device related storage + * @transport: transport for the KXSD9 * @buf_lock: protect the rx and tx buffers. * @us: spi device - * @rx: single rx buffer storage - * @tx: single tx buffer storage **/ struct kxsd9_state { + struct kxsd9_transport *transport; struct mutex buf_lock; - struct spi_device *us; - u8 rx[KXSD9_STATE_RX_SIZE] ____cacheline_aligned; - u8 tx[KXSD9_STATE_TX_SIZE]; }; #define KXSD9_SCALE_2G "0.011978" @@ -80,13 +98,12 @@ static int kxsd9_write_scale(struct iio_dev *indio_dev, int micro) return -EINVAL; mutex_lock(&st->buf_lock); - ret = spi_w8r8(st->us, KXSD9_READ(KXSD9_REG_CTRL_C)); - if (ret < 0) + ret = st->transport->write1(st->transport, KXSD9_READ(KXSD9_REG_CTRL_C)); + if (ret) goto error_ret; - st->tx[0] = KXSD9_WRITE(KXSD9_REG_CTRL_C); - st->tx[1] = (ret & ~KXSD9_FS_MASK) | i; - - ret = spi_write(st->us, st->tx, 2); + ret = st->transport->write2(st->transport, + KXSD9_WRITE(KXSD9_REG_CTRL_C), + (ret & ~KXSD9_FS_MASK) | i); error_ret: mutex_unlock(&st->buf_lock); return ret; @@ -96,24 +113,9 @@ static int kxsd9_read(struct iio_dev *indio_dev, u8 address) { int ret; struct kxsd9_state *st = iio_priv(indio_dev); - struct spi_transfer xfers[] = { - { - .bits_per_word = 8, - .len = 1, - .delay_usecs = 200, - .tx_buf = st->tx, - }, { - .bits_per_word = 8, - .len = 2, - .rx_buf = st->rx, - }, - }; mutex_lock(&st->buf_lock); - st->tx[0] = KXSD9_READ(address); - ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); - if (!ret) - ret = (((u16)(st->rx[0])) << 8) | (st->rx[1] & 0xF0); + ret = st->transport->readval(st->transport, KXSD9_READ(address)); mutex_unlock(&st->buf_lock); return ret; } @@ -163,8 +165,8 @@ static int kxsd9_read_raw(struct iio_dev *indio_dev, ret = IIO_VAL_INT; break; case IIO_CHAN_INFO_SCALE: - ret = spi_w8r8(st->us, KXSD9_READ(KXSD9_REG_CTRL_C)); - if (ret < 0) + ret = st->transport->write1(st->transport, KXSD9_READ(KXSD9_REG_CTRL_C)); + if (ret) goto error_ret; *val = 0; *val2 = kxsd9_micro_scales[ret & KXSD9_FS_MASK]; @@ -203,15 +205,10 @@ static int kxsd9_power_up(struct kxsd9_state *st) { int ret; - st->tx[0] = 0x0d; - st->tx[1] = 0x40; - ret = spi_write(st->us, st->tx, 2); + ret = st->transport->write2(st->transport, 0x0d, 0x40); if (ret) return ret; - - st->tx[0] = 0x0c; - st->tx[1] = 0x9b; - return spi_write(st->us, st->tx, 2); + return st->transport->write2(st->transport, 0x0c, 0x9b); }; static const struct iio_info kxsd9_info = { @@ -221,56 +218,130 @@ static const struct iio_info kxsd9_info = { .driver_module = THIS_MODULE, }; -static int kxsd9_probe(struct spi_device *spi) +static int kxsd9_common_probe(struct device *parent, + struct kxsd9_transport *transport, + const char *name, + struct iio_dev **retdev) { struct iio_dev *indio_dev; struct kxsd9_state *st; + int ret; - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + indio_dev = devm_iio_device_alloc(parent, sizeof(*st)); if (!indio_dev) return -ENOMEM; st = iio_priv(indio_dev); - spi_set_drvdata(spi, indio_dev); + st->transport = transport; - st->us = spi; mutex_init(&st->buf_lock); indio_dev->channels = kxsd9_channels; indio_dev->num_channels = ARRAY_SIZE(kxsd9_channels); - indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->dev.parent = &spi->dev; + indio_dev->name = name; + indio_dev->dev.parent = parent; indio_dev->info = &kxsd9_info; indio_dev->modes = INDIO_DIRECT_MODE; + kxsd9_power_up(st); + + ret = iio_device_register(indio_dev); + if (ret) + return ret; + + *retdev = indio_dev; + return 0; +} + +static int kxsd9_spi_write1(struct kxsd9_transport *tr, u8 byte) +{ + struct spi_device *spi = tr->trdev; + + return spi_w8r8(spi, byte); +} + +static int kxsd9_spi_write2(struct kxsd9_transport *tr, u8 b1, u8 b2) +{ + struct spi_device *spi = tr->trdev; + + tr->tx[0] = b1; + tr->tx[1] = b2; + return spi_write(spi, tr->tx, 2); +} + +static int kxsd9_spi_readval(struct kxsd9_transport *tr, u8 address) +{ + struct spi_device *spi = tr->trdev; + struct spi_transfer xfers[] = { + { + .bits_per_word = 8, + .len = 1, + .delay_usecs = 200, + .tx_buf = tr->tx, + }, { + .bits_per_word = 8, + .len = 2, + .rx_buf = tr->rx, + }, + }; + int ret; + + tr->tx[0] = address; + ret = spi_sync_transfer(spi, xfers, ARRAY_SIZE(xfers)); + if (!ret) + ret = (((u16)(tr->rx[0])) << 8) | (tr->rx[1] & 0xF0); + return ret; +} + +static int kxsd9_spi_probe(struct spi_device *spi) +{ + struct kxsd9_transport *transport; + struct iio_dev *indio_dev; + int ret; + + transport = devm_kzalloc(&spi->dev, sizeof(*transport), GFP_KERNEL); + if (!transport) + return -ENOMEM; + + transport->trdev = spi; + transport->write1 = kxsd9_spi_write1; + transport->write2 = kxsd9_spi_write2; + transport->readval = kxsd9_spi_readval; spi->mode = SPI_MODE_0; spi_setup(spi); - kxsd9_power_up(st); - return iio_device_register(indio_dev); + ret = kxsd9_common_probe(&spi->dev, + transport, + spi_get_device_id(spi)->name, + &indio_dev); + if (ret) + return ret; + + spi_set_drvdata(spi, indio_dev); + return 0; } -static int kxsd9_remove(struct spi_device *spi) +static int kxsd9_spi_remove(struct spi_device *spi) { iio_device_unregister(spi_get_drvdata(spi)); return 0; } -static const struct spi_device_id kxsd9_id[] = { +static const struct spi_device_id kxsd9_spi_id[] = { {"kxsd9", 0}, { }, }; -MODULE_DEVICE_TABLE(spi, kxsd9_id); +MODULE_DEVICE_TABLE(spi, kxsd9_spi_id); -static struct spi_driver kxsd9_driver = { +static struct spi_driver kxsd9_spi_driver = { .driver = { .name = "kxsd9", }, - .probe = kxsd9_probe, - .remove = kxsd9_remove, - .id_table = kxsd9_id, + .probe = kxsd9_spi_probe, + .remove = kxsd9_spi_remove, + .id_table = kxsd9_spi_id, }; -module_spi_driver(kxsd9_driver); +module_spi_driver(kxsd9_spi_driver); MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>"); MODULE_DESCRIPTION("Kionix KXSD9 SPI driver"); -- cgit v0.10.2 From 154021a317564a600fb5b8e6eba9a76ca6888310 Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Thu, 1 Sep 2016 11:44:37 +0200 Subject: iio: accel: kxsd9: split out a common remove() function This makes it possible to later split the transport mechanism using a generic probe() and a generic remove(). Use dev_set_drvdata() and dev_get_drvdata() as a paired accessor to operate on the abstract struct device * regardless of the transport mechanism in use. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Tested-by: Jonathan Cameron <jic23@kernel.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c index df8a31e..1f9e9a8 100644 --- a/drivers/iio/accel/kxsd9.c +++ b/drivers/iio/accel/kxsd9.c @@ -220,8 +220,7 @@ static const struct iio_info kxsd9_info = { static int kxsd9_common_probe(struct device *parent, struct kxsd9_transport *transport, - const char *name, - struct iio_dev **retdev) + const char *name) { struct iio_dev *indio_dev; struct kxsd9_state *st; @@ -248,7 +247,17 @@ static int kxsd9_common_probe(struct device *parent, if (ret) return ret; - *retdev = indio_dev; + dev_set_drvdata(parent, indio_dev); + + return 0; +} + +static int kxsd9_common_remove(struct device *parent) +{ + struct iio_dev *indio_dev = dev_get_drvdata(parent); + + iio_device_unregister(indio_dev); + return 0; } @@ -295,7 +304,6 @@ static int kxsd9_spi_readval(struct kxsd9_transport *tr, u8 address) static int kxsd9_spi_probe(struct spi_device *spi) { struct kxsd9_transport *transport; - struct iio_dev *indio_dev; int ret; transport = devm_kzalloc(&spi->dev, sizeof(*transport), GFP_KERNEL); @@ -311,20 +319,16 @@ static int kxsd9_spi_probe(struct spi_device *spi) ret = kxsd9_common_probe(&spi->dev, transport, - spi_get_device_id(spi)->name, - &indio_dev); + spi_get_device_id(spi)->name); if (ret) return ret; - spi_set_drvdata(spi, indio_dev); return 0; } static int kxsd9_spi_remove(struct spi_device *spi) { - iio_device_unregister(spi_get_drvdata(spi)); - - return 0; + return kxsd9_common_remove(&spi->dev); } static const struct spi_device_id kxsd9_spi_id[] = { -- cgit v0.10.2 From bf96f6e80cef4b9a234e8ce81aa2e333ca7ce599 Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Thu, 1 Sep 2016 11:44:38 +0200 Subject: iio: accel: kxsd9: Split out SPI transport This moves the KXSD9 SPI transport out to its own file and Kconfig entry, so that we will be able to add another transport method. We export the common probe and add a local header file for the functionality shared between the main driver and the transport driver. We make the SPI transport the default for the driver if SPI is available and the KXSD9 driver was selected, so the oldconfig upgrade path will be clear. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Tested-by: Jonathan Cameron <jic23@kernel.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index 13b8a18..89bc5c5 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -119,7 +119,6 @@ config IIO_ST_ACCEL_SPI_3AXIS config KXSD9 tristate "Kionix KXSD9 Accelerometer Driver" - depends on SPI help Say yes here to build support for the Kionix KXSD9 accelerometer. Currently this only supports the device via an SPI interface. @@ -127,6 +126,15 @@ config KXSD9 To compile this driver as a module, choose M here: the module will be called kxsd9. +config KXSD9_SPI + tristate "Kionix KXSD9 SPI transport" + depends on KXSD9 + depends on SPI + default KXSD9 + help + Say yes here to enable the Kionix KXSD9 accelerometer + SPI transport channel. + config KXCJK1013 tristate "Kionix 3-Axis Accelerometer Driver" depends on I2C diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile index e974841..2fe41d7 100644 --- a/drivers/iio/accel/Makefile +++ b/drivers/iio/accel/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_DMARD09) += dmard09.o obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o obj-$(CONFIG_KXSD9) += kxsd9.o +obj-$(CONFIG_KXSD9_SPI) += kxsd9-spi.o obj-$(CONFIG_MMA7455) += mma7455_core.o obj-$(CONFIG_MMA7455_I2C) += mma7455_i2c.o diff --git a/drivers/iio/accel/kxsd9-spi.c b/drivers/iio/accel/kxsd9-spi.c new file mode 100644 index 0000000..ec9d00d --- /dev/null +++ b/drivers/iio/accel/kxsd9-spi.c @@ -0,0 +1,110 @@ +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/spi/spi.h> +#include <linux/module.h> +#include <linux/slab.h> + +#include "kxsd9.h" + +#define KXSD9_READ(a) (0x80 | (a)) +#define KXSD9_WRITE(a) (a) + +static int kxsd9_spi_readreg(struct kxsd9_transport *tr, u8 address) +{ + struct spi_device *spi = tr->trdev; + + return spi_w8r8(spi, KXSD9_READ(address)); +} + +static int kxsd9_spi_writereg(struct kxsd9_transport *tr, u8 address, u8 val) +{ + struct spi_device *spi = tr->trdev; + + tr->tx[0] = KXSD9_WRITE(address), + tr->tx[1] = val; + return spi_write(spi, tr->tx, 2); +} + +static int kxsd9_spi_write2(struct kxsd9_transport *tr, u8 b1, u8 b2) +{ + struct spi_device *spi = tr->trdev; + + tr->tx[0] = b1; + tr->tx[1] = b2; + return spi_write(spi, tr->tx, 2); +} + +static int kxsd9_spi_readval(struct kxsd9_transport *tr, u8 address) +{ + struct spi_device *spi = tr->trdev; + struct spi_transfer xfers[] = { + { + .bits_per_word = 8, + .len = 1, + .delay_usecs = 200, + .tx_buf = tr->tx, + }, { + .bits_per_word = 8, + .len = 2, + .rx_buf = tr->rx, + }, + }; + int ret; + + tr->tx[0] = KXSD9_READ(address); + ret = spi_sync_transfer(spi, xfers, ARRAY_SIZE(xfers)); + if (!ret) + ret = (((u16)(tr->rx[0])) << 8) | (tr->rx[1]); + return ret; +} + +static int kxsd9_spi_probe(struct spi_device *spi) +{ + struct kxsd9_transport *transport; + int ret; + + transport = devm_kzalloc(&spi->dev, sizeof(*transport), GFP_KERNEL); + if (!transport) + return -ENOMEM; + + transport->trdev = spi; + transport->readreg = kxsd9_spi_readreg; + transport->writereg = kxsd9_spi_writereg; + transport->write2 = kxsd9_spi_write2; + transport->readval = kxsd9_spi_readval; + spi->mode = SPI_MODE_0; + spi_setup(spi); + + ret = kxsd9_common_probe(&spi->dev, + transport, + spi_get_device_id(spi)->name); + if (ret) + return ret; + + return 0; +} + +static int kxsd9_spi_remove(struct spi_device *spi) +{ + return kxsd9_common_remove(&spi->dev); +} + +static const struct spi_device_id kxsd9_spi_id[] = { + {"kxsd9", 0}, + { }, +}; +MODULE_DEVICE_TABLE(spi, kxsd9_spi_id); + +static struct spi_driver kxsd9_spi_driver = { + .driver = { + .name = "kxsd9", + }, + .probe = kxsd9_spi_probe, + .remove = kxsd9_spi_remove, + .id_table = kxsd9_spi_id, +}; +module_spi_driver(kxsd9_spi_driver); + +MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>"); +MODULE_DESCRIPTION("Kionix KXSD9 SPI driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c index 1f9e9a8..e203337 100644 --- a/drivers/iio/accel/kxsd9.c +++ b/drivers/iio/accel/kxsd9.c @@ -18,7 +18,6 @@ #include <linux/device.h> #include <linux/kernel.h> -#include <linux/spi/spi.h> #include <linux/sysfs.h> #include <linux/slab.h> #include <linux/module.h> @@ -26,6 +25,8 @@ #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> +#include "kxsd9.h" + #define KXSD9_REG_X 0x00 #define KXSD9_REG_Y 0x02 #define KXSD9_REG_Z 0x04 @@ -38,32 +39,6 @@ #define KXSD9_REG_CTRL_B 0x0d #define KXSD9_REG_CTRL_A 0x0e -#define KXSD9_READ(a) (0x80 | (a)) -#define KXSD9_WRITE(a) (a) - -#define KXSD9_STATE_RX_SIZE 2 -#define KXSD9_STATE_TX_SIZE 2 - -struct kxsd9_transport; - -/** - * struct kxsd9_transport - transport adapter for SPI or I2C - * @trdev: transport device such as SPI or I2C - * @write1(): function to write a byte to the device - * @write2(): function to write two consecutive bytes to the device - * @readval(): function to read a 16bit value from the device - * @rx: cache aligned read buffer - * @tx: cache aligned write buffer - */ -struct kxsd9_transport { - void *trdev; - int (*write1) (struct kxsd9_transport *tr, u8 byte); - int (*write2) (struct kxsd9_transport *tr, u8 b1, u8 b2); - int (*readval) (struct kxsd9_transport *tr, u8 address); - u8 rx[KXSD9_STATE_RX_SIZE] ____cacheline_aligned; - u8 tx[KXSD9_STATE_TX_SIZE]; -}; - /** * struct kxsd9_state - device related storage * @transport: transport for the KXSD9 @@ -98,12 +73,13 @@ static int kxsd9_write_scale(struct iio_dev *indio_dev, int micro) return -EINVAL; mutex_lock(&st->buf_lock); - ret = st->transport->write1(st->transport, KXSD9_READ(KXSD9_REG_CTRL_C)); - if (ret) + ret = st->transport->readreg(st->transport, + KXSD9_REG_CTRL_C); + if (ret < 0) goto error_ret; - ret = st->transport->write2(st->transport, - KXSD9_WRITE(KXSD9_REG_CTRL_C), - (ret & ~KXSD9_FS_MASK) | i); + ret = st->transport->writereg(st->transport, + KXSD9_REG_CTRL_C, + (ret & ~KXSD9_FS_MASK) | i); error_ret: mutex_unlock(&st->buf_lock); return ret; @@ -115,7 +91,9 @@ static int kxsd9_read(struct iio_dev *indio_dev, u8 address) struct kxsd9_state *st = iio_priv(indio_dev); mutex_lock(&st->buf_lock); - ret = st->transport->readval(st->transport, KXSD9_READ(address)); + ret = st->transport->readval(st->transport, address); + /* Only 12 bits are valid */ + ret &= 0xfff0; mutex_unlock(&st->buf_lock); return ret; } @@ -165,8 +143,9 @@ static int kxsd9_read_raw(struct iio_dev *indio_dev, ret = IIO_VAL_INT; break; case IIO_CHAN_INFO_SCALE: - ret = st->transport->write1(st->transport, KXSD9_READ(KXSD9_REG_CTRL_C)); - if (ret) + ret = st->transport->readreg(st->transport, + KXSD9_REG_CTRL_C); + if (ret < 0) goto error_ret; *val = 0; *val2 = kxsd9_micro_scales[ret & KXSD9_FS_MASK]; @@ -218,9 +197,9 @@ static const struct iio_info kxsd9_info = { .driver_module = THIS_MODULE, }; -static int kxsd9_common_probe(struct device *parent, - struct kxsd9_transport *transport, - const char *name) +int kxsd9_common_probe(struct device *parent, + struct kxsd9_transport *transport, + const char *name) { struct iio_dev *indio_dev; struct kxsd9_state *st; @@ -251,8 +230,9 @@ static int kxsd9_common_probe(struct device *parent, return 0; } +EXPORT_SYMBOL(kxsd9_common_probe); -static int kxsd9_common_remove(struct device *parent) +int kxsd9_common_remove(struct device *parent) { struct iio_dev *indio_dev = dev_get_drvdata(parent); @@ -260,93 +240,8 @@ static int kxsd9_common_remove(struct device *parent) return 0; } - -static int kxsd9_spi_write1(struct kxsd9_transport *tr, u8 byte) -{ - struct spi_device *spi = tr->trdev; - - return spi_w8r8(spi, byte); -} - -static int kxsd9_spi_write2(struct kxsd9_transport *tr, u8 b1, u8 b2) -{ - struct spi_device *spi = tr->trdev; - - tr->tx[0] = b1; - tr->tx[1] = b2; - return spi_write(spi, tr->tx, 2); -} - -static int kxsd9_spi_readval(struct kxsd9_transport *tr, u8 address) -{ - struct spi_device *spi = tr->trdev; - struct spi_transfer xfers[] = { - { - .bits_per_word = 8, - .len = 1, - .delay_usecs = 200, - .tx_buf = tr->tx, - }, { - .bits_per_word = 8, - .len = 2, - .rx_buf = tr->rx, - }, - }; - int ret; - - tr->tx[0] = address; - ret = spi_sync_transfer(spi, xfers, ARRAY_SIZE(xfers)); - if (!ret) - ret = (((u16)(tr->rx[0])) << 8) | (tr->rx[1] & 0xF0); - return ret; -} - -static int kxsd9_spi_probe(struct spi_device *spi) -{ - struct kxsd9_transport *transport; - int ret; - - transport = devm_kzalloc(&spi->dev, sizeof(*transport), GFP_KERNEL); - if (!transport) - return -ENOMEM; - - transport->trdev = spi; - transport->write1 = kxsd9_spi_write1; - transport->write2 = kxsd9_spi_write2; - transport->readval = kxsd9_spi_readval; - spi->mode = SPI_MODE_0; - spi_setup(spi); - - ret = kxsd9_common_probe(&spi->dev, - transport, - spi_get_device_id(spi)->name); - if (ret) - return ret; - - return 0; -} - -static int kxsd9_spi_remove(struct spi_device *spi) -{ - return kxsd9_common_remove(&spi->dev); -} - -static const struct spi_device_id kxsd9_spi_id[] = { - {"kxsd9", 0}, - { }, -}; -MODULE_DEVICE_TABLE(spi, kxsd9_spi_id); - -static struct spi_driver kxsd9_spi_driver = { - .driver = { - .name = "kxsd9", - }, - .probe = kxsd9_spi_probe, - .remove = kxsd9_spi_remove, - .id_table = kxsd9_spi_id, -}; -module_spi_driver(kxsd9_spi_driver); +EXPORT_SYMBOL(kxsd9_common_remove); MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>"); -MODULE_DESCRIPTION("Kionix KXSD9 SPI driver"); +MODULE_DESCRIPTION("Kionix KXSD9 driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/accel/kxsd9.h b/drivers/iio/accel/kxsd9.h new file mode 100644 index 0000000..28845c3 --- /dev/null +++ b/drivers/iio/accel/kxsd9.h @@ -0,0 +1,32 @@ +#include <linux/device.h> +#include <linux/kernel.h> + +#define KXSD9_STATE_RX_SIZE 2 +#define KXSD9_STATE_TX_SIZE 2 + +struct kxsd9_transport; + +/** + * struct kxsd9_transport - transport adapter for SPI or I2C + * @trdev: transport device such as SPI or I2C + * @readreg(): function to read a byte from an address in the device + * @writereg(): function to write a byte to an address in the device + * @write2(): function to write two consecutive bytes to the device + * @readval(): function to read a 16bit value from the device + * @rx: cache aligned read buffer + * @tx: cache aligned write buffer + */ +struct kxsd9_transport { + void *trdev; + int (*readreg) (struct kxsd9_transport *tr, u8 address); + int (*writereg) (struct kxsd9_transport *tr, u8 address, u8 val); + int (*write2) (struct kxsd9_transport *tr, u8 b1, u8 b2); + int (*readval) (struct kxsd9_transport *tr, u8 address); + u8 rx[KXSD9_STATE_RX_SIZE] ____cacheline_aligned; + u8 tx[KXSD9_STATE_TX_SIZE]; +}; + +int kxsd9_common_probe(struct device *parent, + struct kxsd9_transport *transport, + const char *name); +int kxsd9_common_remove(struct device *parent); -- cgit v0.10.2 From ab04f734b08a404550ba5f8391307bad2145acff Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Thu, 1 Sep 2016 11:44:39 +0200 Subject: iio: accel: kxsd9: Do away with the write2 helper This is just a masquerading register write function, so use the register write function instead. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Tested-by: Jonathan Cameron <jic23@kernel.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/accel/kxsd9-spi.c b/drivers/iio/accel/kxsd9-spi.c index ec9d00d..a49c10c 100644 --- a/drivers/iio/accel/kxsd9-spi.c +++ b/drivers/iio/accel/kxsd9-spi.c @@ -25,15 +25,6 @@ static int kxsd9_spi_writereg(struct kxsd9_transport *tr, u8 address, u8 val) return spi_write(spi, tr->tx, 2); } -static int kxsd9_spi_write2(struct kxsd9_transport *tr, u8 b1, u8 b2) -{ - struct spi_device *spi = tr->trdev; - - tr->tx[0] = b1; - tr->tx[1] = b2; - return spi_write(spi, tr->tx, 2); -} - static int kxsd9_spi_readval(struct kxsd9_transport *tr, u8 address) { struct spi_device *spi = tr->trdev; @@ -70,7 +61,6 @@ static int kxsd9_spi_probe(struct spi_device *spi) transport->trdev = spi; transport->readreg = kxsd9_spi_readreg; transport->writereg = kxsd9_spi_writereg; - transport->write2 = kxsd9_spi_write2; transport->readval = kxsd9_spi_readval; spi->mode = SPI_MODE_0; spi_setup(spi); diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c index e203337..a787ec2 100644 --- a/drivers/iio/accel/kxsd9.c +++ b/drivers/iio/accel/kxsd9.c @@ -184,10 +184,10 @@ static int kxsd9_power_up(struct kxsd9_state *st) { int ret; - ret = st->transport->write2(st->transport, 0x0d, 0x40); + ret = st->transport->writereg(st->transport, KXSD9_REG_CTRL_B, 0x40); if (ret) return ret; - return st->transport->write2(st->transport, 0x0c, 0x9b); + return st->transport->writereg(st->transport, KXSD9_REG_CTRL_C, 0x9b); }; static const struct iio_info kxsd9_info = { diff --git a/drivers/iio/accel/kxsd9.h b/drivers/iio/accel/kxsd9.h index 28845c3..b6328e8 100644 --- a/drivers/iio/accel/kxsd9.h +++ b/drivers/iio/accel/kxsd9.h @@ -11,7 +11,6 @@ struct kxsd9_transport; * @trdev: transport device such as SPI or I2C * @readreg(): function to read a byte from an address in the device * @writereg(): function to write a byte to an address in the device - * @write2(): function to write two consecutive bytes to the device * @readval(): function to read a 16bit value from the device * @rx: cache aligned read buffer * @tx: cache aligned write buffer @@ -20,7 +19,6 @@ struct kxsd9_transport { void *trdev; int (*readreg) (struct kxsd9_transport *tr, u8 address); int (*writereg) (struct kxsd9_transport *tr, u8 address, u8 val); - int (*write2) (struct kxsd9_transport *tr, u8 b1, u8 b2); int (*readval) (struct kxsd9_transport *tr, u8 address); u8 rx[KXSD9_STATE_RX_SIZE] ____cacheline_aligned; u8 tx[KXSD9_STATE_TX_SIZE]; -- cgit v0.10.2 From 0d1fb2d52d8b4a1124cb2db7d22c4131ad5805cf Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Thu, 1 Sep 2016 11:44:40 +0200 Subject: iio: accel: kxsd9: Convert to use regmap for transport This converts the KXSD9 driver to drop the custom transport mechanism and just use regmap like everything else. Tested-by: Jonathan Cameron <jic23@kernel.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index 89bc5c5..eebc20d 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -131,6 +131,7 @@ config KXSD9_SPI depends on KXSD9 depends on SPI default KXSD9 + select REGMAP_SPI help Say yes here to enable the Kionix KXSD9 accelerometer SPI transport channel. diff --git a/drivers/iio/accel/kxsd9-spi.c b/drivers/iio/accel/kxsd9-spi.c index a49c10c..c5af51b 100644 --- a/drivers/iio/accel/kxsd9-spi.c +++ b/drivers/iio/accel/kxsd9-spi.c @@ -3,75 +3,30 @@ #include <linux/spi/spi.h> #include <linux/module.h> #include <linux/slab.h> +#include <linux/regmap.h> #include "kxsd9.h" -#define KXSD9_READ(a) (0x80 | (a)) -#define KXSD9_WRITE(a) (a) - -static int kxsd9_spi_readreg(struct kxsd9_transport *tr, u8 address) -{ - struct spi_device *spi = tr->trdev; - - return spi_w8r8(spi, KXSD9_READ(address)); -} - -static int kxsd9_spi_writereg(struct kxsd9_transport *tr, u8 address, u8 val) -{ - struct spi_device *spi = tr->trdev; - - tr->tx[0] = KXSD9_WRITE(address), - tr->tx[1] = val; - return spi_write(spi, tr->tx, 2); -} - -static int kxsd9_spi_readval(struct kxsd9_transport *tr, u8 address) -{ - struct spi_device *spi = tr->trdev; - struct spi_transfer xfers[] = { - { - .bits_per_word = 8, - .len = 1, - .delay_usecs = 200, - .tx_buf = tr->tx, - }, { - .bits_per_word = 8, - .len = 2, - .rx_buf = tr->rx, - }, - }; - int ret; - - tr->tx[0] = KXSD9_READ(address); - ret = spi_sync_transfer(spi, xfers, ARRAY_SIZE(xfers)); - if (!ret) - ret = (((u16)(tr->rx[0])) << 8) | (tr->rx[1]); - return ret; -} - static int kxsd9_spi_probe(struct spi_device *spi) { - struct kxsd9_transport *transport; - int ret; - - transport = devm_kzalloc(&spi->dev, sizeof(*transport), GFP_KERNEL); - if (!transport) - return -ENOMEM; + static const struct regmap_config config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0x0e, + }; + struct regmap *regmap; - transport->trdev = spi; - transport->readreg = kxsd9_spi_readreg; - transport->writereg = kxsd9_spi_writereg; - transport->readval = kxsd9_spi_readval; spi->mode = SPI_MODE_0; - spi_setup(spi); - - ret = kxsd9_common_probe(&spi->dev, - transport, - spi_get_device_id(spi)->name); - if (ret) - return ret; - - return 0; + regmap = devm_regmap_init_spi(spi, &config); + if (IS_ERR(regmap)) { + dev_err(&spi->dev, "%s: regmap allocation failed: %ld\n", + __func__, PTR_ERR(regmap)); + return PTR_ERR(regmap); + } + + return kxsd9_common_probe(&spi->dev, + regmap, + spi_get_device_id(spi)->name); } static int kxsd9_spi_remove(struct spi_device *spi) diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c index a787ec2..c065c6e 100644 --- a/drivers/iio/accel/kxsd9.c +++ b/drivers/iio/accel/kxsd9.c @@ -21,7 +21,7 @@ #include <linux/sysfs.h> #include <linux/slab.h> #include <linux/module.h> - +#include <linux/regmap.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> @@ -46,7 +46,7 @@ * @us: spi device **/ struct kxsd9_state { - struct kxsd9_transport *transport; + struct regmap *map; struct mutex buf_lock; }; @@ -63,6 +63,7 @@ static int kxsd9_write_scale(struct iio_dev *indio_dev, int micro) int ret, i; struct kxsd9_state *st = iio_priv(indio_dev); bool foundit = false; + unsigned int val; for (i = 0; i < 4; i++) if (micro == kxsd9_micro_scales[i]) { @@ -73,13 +74,14 @@ static int kxsd9_write_scale(struct iio_dev *indio_dev, int micro) return -EINVAL; mutex_lock(&st->buf_lock); - ret = st->transport->readreg(st->transport, - KXSD9_REG_CTRL_C); + ret = regmap_read(st->map, + KXSD9_REG_CTRL_C, + &val); if (ret < 0) goto error_ret; - ret = st->transport->writereg(st->transport, - KXSD9_REG_CTRL_C, - (ret & ~KXSD9_FS_MASK) | i); + ret = regmap_write(st->map, + KXSD9_REG_CTRL_C, + (val & ~KXSD9_FS_MASK) | i); error_ret: mutex_unlock(&st->buf_lock); return ret; @@ -89,11 +91,15 @@ static int kxsd9_read(struct iio_dev *indio_dev, u8 address) { int ret; struct kxsd9_state *st = iio_priv(indio_dev); + __be16 raw_val; mutex_lock(&st->buf_lock); - ret = st->transport->readval(st->transport, address); + ret = regmap_bulk_read(st->map, address, &raw_val, sizeof(raw_val)); + if (ret) + goto out_fail_read; /* Only 12 bits are valid */ - ret &= 0xfff0; + ret = be16_to_cpu(raw_val) & 0xfff0; +out_fail_read: mutex_unlock(&st->buf_lock); return ret; } @@ -133,6 +139,7 @@ static int kxsd9_read_raw(struct iio_dev *indio_dev, { int ret = -EINVAL; struct kxsd9_state *st = iio_priv(indio_dev); + unsigned int regval; switch (mask) { case IIO_CHAN_INFO_RAW: @@ -143,12 +150,13 @@ static int kxsd9_read_raw(struct iio_dev *indio_dev, ret = IIO_VAL_INT; break; case IIO_CHAN_INFO_SCALE: - ret = st->transport->readreg(st->transport, - KXSD9_REG_CTRL_C); + ret = regmap_read(st->map, + KXSD9_REG_CTRL_C, + ®val); if (ret < 0) goto error_ret; *val = 0; - *val2 = kxsd9_micro_scales[ret & KXSD9_FS_MASK]; + *val2 = kxsd9_micro_scales[regval & KXSD9_FS_MASK]; ret = IIO_VAL_INT_PLUS_MICRO; break; } @@ -184,10 +192,10 @@ static int kxsd9_power_up(struct kxsd9_state *st) { int ret; - ret = st->transport->writereg(st->transport, KXSD9_REG_CTRL_B, 0x40); + ret = regmap_write(st->map, KXSD9_REG_CTRL_B, 0x40); if (ret) return ret; - return st->transport->writereg(st->transport, KXSD9_REG_CTRL_C, 0x9b); + return regmap_write(st->map, KXSD9_REG_CTRL_C, 0x9b); }; static const struct iio_info kxsd9_info = { @@ -198,7 +206,7 @@ static const struct iio_info kxsd9_info = { }; int kxsd9_common_probe(struct device *parent, - struct kxsd9_transport *transport, + struct regmap *map, const char *name) { struct iio_dev *indio_dev; @@ -210,7 +218,7 @@ int kxsd9_common_probe(struct device *parent, return -ENOMEM; st = iio_priv(indio_dev); - st->transport = transport; + st->map = map; mutex_init(&st->buf_lock); indio_dev->channels = kxsd9_channels; diff --git a/drivers/iio/accel/kxsd9.h b/drivers/iio/accel/kxsd9.h index b6328e8..19131a7 100644 --- a/drivers/iio/accel/kxsd9.h +++ b/drivers/iio/accel/kxsd9.h @@ -4,27 +4,7 @@ #define KXSD9_STATE_RX_SIZE 2 #define KXSD9_STATE_TX_SIZE 2 -struct kxsd9_transport; - -/** - * struct kxsd9_transport - transport adapter for SPI or I2C - * @trdev: transport device such as SPI or I2C - * @readreg(): function to read a byte from an address in the device - * @writereg(): function to write a byte to an address in the device - * @readval(): function to read a 16bit value from the device - * @rx: cache aligned read buffer - * @tx: cache aligned write buffer - */ -struct kxsd9_transport { - void *trdev; - int (*readreg) (struct kxsd9_transport *tr, u8 address); - int (*writereg) (struct kxsd9_transport *tr, u8 address, u8 val); - int (*readval) (struct kxsd9_transport *tr, u8 address); - u8 rx[KXSD9_STATE_RX_SIZE] ____cacheline_aligned; - u8 tx[KXSD9_STATE_TX_SIZE]; -}; - int kxsd9_common_probe(struct device *parent, - struct kxsd9_transport *transport, + struct regmap *map, const char *name); int kxsd9_common_remove(struct device *parent); -- cgit v0.10.2 From a483ab796960c9080dc9f97f5905d11debad3df9 Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Thu, 1 Sep 2016 11:44:41 +0200 Subject: iio: accel: kxsd9: Add I2C transport This adds I2C regmap transport for the KXSD9 driver. Tested on the KXSD9 sensor on the APQ8060 Dragonboard. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index eebc20d..8824400 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -121,7 +121,7 @@ config KXSD9 tristate "Kionix KXSD9 Accelerometer Driver" help Say yes here to build support for the Kionix KXSD9 accelerometer. - Currently this only supports the device via an SPI interface. + It can be accessed using an (optional) SPI or I2C interface. To compile this driver as a module, choose M here: the module will be called kxsd9. @@ -136,6 +136,16 @@ config KXSD9_SPI Say yes here to enable the Kionix KXSD9 accelerometer SPI transport channel. +config KXSD9_I2C + tristate "Kionix KXSD9 I2C transport" + depends on KXSD9 + depends on I2C + default KXSD9 + select REGMAP_I2C + help + Say yes here to enable the Kionix KXSD9 accelerometer + I2C transport channel. + config KXCJK1013 tristate "Kionix 3-Axis Accelerometer Driver" depends on I2C diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile index 2fe41d7..b5c2a0b 100644 --- a/drivers/iio/accel/Makefile +++ b/drivers/iio/accel/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o obj-$(CONFIG_KXSD9) += kxsd9.o obj-$(CONFIG_KXSD9_SPI) += kxsd9-spi.o +obj-$(CONFIG_KXSD9_I2C) += kxsd9-i2c.o obj-$(CONFIG_MMA7455) += mma7455_core.o obj-$(CONFIG_MMA7455_I2C) += mma7455_i2c.o diff --git a/drivers/iio/accel/kxsd9-i2c.c b/drivers/iio/accel/kxsd9-i2c.c new file mode 100644 index 0000000..4aaa27d --- /dev/null +++ b/drivers/iio/accel/kxsd9-i2c.c @@ -0,0 +1,63 @@ +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/delay.h> +#include <linux/regmap.h> + +#include "kxsd9.h" + +static int kxsd9_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + static const struct regmap_config config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0x0e, + }; + struct regmap *regmap; + + regmap = devm_regmap_init_i2c(i2c, &config); + if (IS_ERR(regmap)) { + dev_err(&i2c->dev, "Failed to register i2c regmap %d\n", + (int)PTR_ERR(regmap)); + return PTR_ERR(regmap); + } + + return kxsd9_common_probe(&i2c->dev, + regmap, + i2c->name); +} + +static int kxsd9_i2c_remove(struct i2c_client *client) +{ + return kxsd9_common_remove(&client->dev); +} + +#ifdef CONFIG_OF +static const struct of_device_id kxsd9_of_match[] = { + { .compatible = "kionix,kxsd9", }, + { }, +}; +MODULE_DEVICE_TABLE(of, kxsd9_of_match); +#else +#define kxsd9_of_match NULL +#endif + +static const struct i2c_device_id kxsd9_i2c_id[] = { + {"kxsd9", 0}, + { }, +}; +MODULE_DEVICE_TABLE(i2c, kxsd9_i2c_id); + +static struct i2c_driver kxsd9_i2c_driver = { + .driver = { + .name = "kxsd9", + .of_match_table = of_match_ptr(kxsd9_of_match), + }, + .probe = kxsd9_i2c_probe, + .remove = kxsd9_i2c_remove, + .id_table = kxsd9_i2c_id, +}; +module_i2c_driver(kxsd9_i2c_driver); -- cgit v0.10.2 From dc6ac050c7d405cf99f847d5f7b485a7dfa00840 Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Thu, 1 Sep 2016 11:44:42 +0200 Subject: iio: accel: kxsd9: Drop the buffer lock The RX/TX buffers are gone so drop the lock (it should have been in the transport struct anyway). Tested-by: Jonathan Cameron <jic23@kernel.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c index c065c6e..dc0bea7 100644 --- a/drivers/iio/accel/kxsd9.c +++ b/drivers/iio/accel/kxsd9.c @@ -41,13 +41,10 @@ /** * struct kxsd9_state - device related storage - * @transport: transport for the KXSD9 - * @buf_lock: protect the rx and tx buffers. - * @us: spi device - **/ + * @map: regmap to the device + */ struct kxsd9_state { struct regmap *map; - struct mutex buf_lock; }; #define KXSD9_SCALE_2G "0.011978" @@ -73,7 +70,6 @@ static int kxsd9_write_scale(struct iio_dev *indio_dev, int micro) if (!foundit) return -EINVAL; - mutex_lock(&st->buf_lock); ret = regmap_read(st->map, KXSD9_REG_CTRL_C, &val); @@ -83,7 +79,6 @@ static int kxsd9_write_scale(struct iio_dev *indio_dev, int micro) KXSD9_REG_CTRL_C, (val & ~KXSD9_FS_MASK) | i); error_ret: - mutex_unlock(&st->buf_lock); return ret; } @@ -93,15 +88,11 @@ static int kxsd9_read(struct iio_dev *indio_dev, u8 address) struct kxsd9_state *st = iio_priv(indio_dev); __be16 raw_val; - mutex_lock(&st->buf_lock); ret = regmap_bulk_read(st->map, address, &raw_val, sizeof(raw_val)); if (ret) - goto out_fail_read; + return ret; /* Only 12 bits are valid */ - ret = be16_to_cpu(raw_val) & 0xfff0; -out_fail_read: - mutex_unlock(&st->buf_lock); - return ret; + return be16_to_cpu(raw_val) & 0xfff0; } static IIO_CONST_ATTR(accel_scale_available, @@ -220,7 +211,6 @@ int kxsd9_common_probe(struct device *parent, st = iio_priv(indio_dev); st->map = map; - mutex_init(&st->buf_lock); indio_dev->channels = kxsd9_channels; indio_dev->num_channels = ARRAY_SIZE(kxsd9_channels); indio_dev->name = name; -- cgit v0.10.2 From 84e2f6f9583f195b9851a8f6340bb526749ea609 Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Thu, 1 Sep 2016 11:44:43 +0200 Subject: iio: accel: kxsd9: Fix up offset and scaling This fixes several errors in the offset and scaling of the raw values from the KXSD9 sensor: - The code did not convert the big endian value from the sensor into the endianness of the host CPU. Fix this with be16_to_cpu() on the raw obtained value. - The code did not regard the fact that only the upper 12 bits of the accelerometer values are valid. Shift these down four bits to yield the real raw value. - Further the sensor provides 2048 at zero g. This means that an offset of 2048 must be subtracted from the raw value before scaling. This was not taken into account by the driver, yielding a weird value. Fix this by providing this offset in sysfs. To house the scaling code better, the value reading code was factored into the raw reading function. This proper scaling and offseting is necessary to get proper values out of triggered buffer by offsetting, shifting and scaling them. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Tested-by: Jonathan Cameron <jic23@kernel.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c index dc0bea7..6a1e677 100644 --- a/drivers/iio/accel/kxsd9.c +++ b/drivers/iio/accel/kxsd9.c @@ -55,6 +55,8 @@ struct kxsd9_state { /* reverse order */ static const int kxsd9_micro_scales[4] = { 47853, 35934, 23927, 11978 }; +#define KXSD9_ZERO_G_OFFSET -2048 + static int kxsd9_write_scale(struct iio_dev *indio_dev, int micro) { int ret, i; @@ -82,19 +84,6 @@ error_ret: return ret; } -static int kxsd9_read(struct iio_dev *indio_dev, u8 address) -{ - int ret; - struct kxsd9_state *st = iio_priv(indio_dev); - __be16 raw_val; - - ret = regmap_bulk_read(st->map, address, &raw_val, sizeof(raw_val)); - if (ret) - return ret; - /* Only 12 bits are valid */ - return be16_to_cpu(raw_val) & 0xfff0; -} - static IIO_CONST_ATTR(accel_scale_available, KXSD9_SCALE_2G " " KXSD9_SCALE_4G " " @@ -131,13 +120,24 @@ static int kxsd9_read_raw(struct iio_dev *indio_dev, int ret = -EINVAL; struct kxsd9_state *st = iio_priv(indio_dev); unsigned int regval; + __be16 raw_val; + u16 nval; switch (mask) { case IIO_CHAN_INFO_RAW: - ret = kxsd9_read(indio_dev, chan->address); - if (ret < 0) + ret = regmap_bulk_read(st->map, chan->address, &raw_val, + sizeof(raw_val)); + if (ret) goto error_ret; - *val = ret; + nval = be16_to_cpu(raw_val); + /* Only 12 bits are valid */ + nval >>= 4; + *val = nval; + ret = IIO_VAL_INT; + break; + case IIO_CHAN_INFO_OFFSET: + /* This has a bias of -2048 */ + *val = KXSD9_ZERO_G_OFFSET; ret = IIO_VAL_INT; break; case IIO_CHAN_INFO_SCALE: @@ -161,7 +161,8 @@ error_ret: .modified = 1, \ .channel2 = IIO_MOD_##axis, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_OFFSET), \ .address = KXSD9_REG_##axis, \ } -- cgit v0.10.2 From 0427a106a98adf94b53cc88607ceabc2ecebd2cc Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Thu, 1 Sep 2016 11:44:44 +0200 Subject: iio: accel: kxsd9: Add triggered buffer handling As is custom with all modern sensors, add a clever burst mode that will just stream out values from the sensor and provide it to userspace to do the proper offsetting and scaling. This is the result when tested with an HRTimer trigger: $ generic_buffer -a -c 10 -n kxsd9 -t foo /sys/bus/iio/devices/iio:device1 foo 0.371318 0.718680 9.869872 1795.000000 97545896129 -0.586922 0.179670 9.378775 2398.000000 97555864721 -0.299450 0.179670 10.348992 2672.000000 97565874055 0.371318 0.335384 11.103606 2816.000000 97575883240 0.179670 0.574944 10.540640 2847.000000 97585862351 0.335384 0.754614 9.953718 2840.000000 97595872425 0.179670 0.754614 10.732288 2879.000000 97605882351 0.000000 0.754614 10.348992 2872.000000 97615891832 -0.730658 0.574944 9.570422 2831.000000 97625871536 0.000000 1.137910 10.732288 2872.000000 97635881610 Columns shown are x, y, z acceleration, so a positive acceleration of ~9.81 (shaky due to bad calibration) along the z axis. The fourth column is the AUX IN which is floating on this system, it seems to float up to the 2.85V VDD voltage. To be able to cleanup the triggered buffer, we need to add .remove() callbacks to the I2C and SPI subdrivers and call back into an exported .remove() callback in the core. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Tested-by: Jonathan Cameron <jic23@kernel.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index 8824400..a8e9ed4 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -119,6 +119,8 @@ config IIO_ST_ACCEL_SPI_3AXIS config KXSD9 tristate "Kionix KXSD9 Accelerometer Driver" + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER help Say yes here to build support for the Kionix KXSD9 accelerometer. It can be accessed using an (optional) SPI or I2C interface. diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c index 6a1e677..d84413a 100644 --- a/drivers/iio/accel/kxsd9.c +++ b/drivers/iio/accel/kxsd9.c @@ -12,8 +12,6 @@ * I have a suitable wire made up. * * TODO: Support the motion detector - * Uses register address incrementing so could have a - * heavily optimized ring buffer access function. */ #include <linux/device.h> @@ -24,6 +22,9 @@ #include <linux/regmap.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> +#include <linux/iio/buffer.h> +#include <linux/iio/triggered_buffer.h> +#include <linux/iio/trigger_consumer.h> #include "kxsd9.h" @@ -41,9 +42,11 @@ /** * struct kxsd9_state - device related storage + * @dev: pointer to the parent device * @map: regmap to the device */ struct kxsd9_state { + struct device *dev; struct regmap *map; }; @@ -155,7 +158,35 @@ static int kxsd9_read_raw(struct iio_dev *indio_dev, error_ret: return ret; }; -#define KXSD9_ACCEL_CHAN(axis) \ + +static irqreturn_t kxsd9_trigger_handler(int irq, void *p) +{ + const struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct kxsd9_state *st = iio_priv(indio_dev); + int ret; + /* 4 * 16bit values AND timestamp */ + __be16 hw_values[8]; + + ret = regmap_bulk_read(st->map, + KXSD9_REG_X, + &hw_values, + 8); + if (ret) { + dev_err(st->dev, + "error reading data\n"); + return ret; + } + + iio_push_to_buffers_with_timestamp(indio_dev, + hw_values, + iio_get_time_ns(indio_dev)); + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +#define KXSD9_ACCEL_CHAN(axis, index) \ { \ .type = IIO_ACCEL, \ .modified = 1, \ @@ -164,16 +195,35 @@ error_ret: .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ BIT(IIO_CHAN_INFO_OFFSET), \ .address = KXSD9_REG_##axis, \ + .scan_index = index, \ + .scan_type = { \ + .sign = 'u', \ + .realbits = 12, \ + .storagebits = 16, \ + .shift = 4, \ + .endianness = IIO_BE, \ + }, \ } static const struct iio_chan_spec kxsd9_channels[] = { - KXSD9_ACCEL_CHAN(X), KXSD9_ACCEL_CHAN(Y), KXSD9_ACCEL_CHAN(Z), + KXSD9_ACCEL_CHAN(X, 0), + KXSD9_ACCEL_CHAN(Y, 1), + KXSD9_ACCEL_CHAN(Z, 2), { .type = IIO_VOLTAGE, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), .indexed = 1, .address = KXSD9_REG_AUX, - } + .scan_index = 3, + .scan_type = { + .sign = 'u', + .realbits = 12, + .storagebits = 16, + .shift = 4, + .endianness = IIO_BE, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(4), }; static const struct attribute_group kxsd9_attribute_group = { @@ -197,6 +247,9 @@ static const struct iio_info kxsd9_info = { .driver_module = THIS_MODULE, }; +/* Four channels apart from timestamp, scan mask = 0x0f */ +static const unsigned long kxsd9_scan_masks[] = { 0xf, 0 }; + int kxsd9_common_probe(struct device *parent, struct regmap *map, const char *name) @@ -210,6 +263,7 @@ int kxsd9_common_probe(struct device *parent, return -ENOMEM; st = iio_priv(indio_dev); + st->dev = parent; st->map = map; indio_dev->channels = kxsd9_channels; @@ -218,16 +272,31 @@ int kxsd9_common_probe(struct device *parent, indio_dev->dev.parent = parent; indio_dev->info = &kxsd9_info; indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->available_scan_masks = kxsd9_scan_masks; kxsd9_power_up(st); + ret = iio_triggered_buffer_setup(indio_dev, + iio_pollfunc_store_time, + kxsd9_trigger_handler, + NULL); + if (ret) { + dev_err(parent, "triggered buffer setup failed\n"); + return ret; + } + ret = iio_device_register(indio_dev); if (ret) - return ret; + goto err_cleanup_buffer; dev_set_drvdata(parent, indio_dev); return 0; + +err_cleanup_buffer: + iio_triggered_buffer_cleanup(indio_dev); + + return ret; } EXPORT_SYMBOL(kxsd9_common_probe); @@ -235,6 +304,7 @@ int kxsd9_common_remove(struct device *parent) { struct iio_dev *indio_dev = dev_get_drvdata(parent); + iio_triggered_buffer_cleanup(indio_dev); iio_device_unregister(indio_dev); return 0; -- cgit v0.10.2 From 11adc2b218028934540be4f235a486d575d74b54 Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Thu, 1 Sep 2016 11:44:45 +0200 Subject: iio: accel: kxsd9: Deploy proper register bit defines There are some hardcoded register values etc in the code, define proper bitfield definitions, and use them when getting and setting the scale. Optimize a read/modify/write to use regmap_update_bits() at the same time. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Tested-by: Jonathan Cameron <jic23@kernel.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c index d84413a..8c6a455 100644 --- a/drivers/iio/accel/kxsd9.c +++ b/drivers/iio/accel/kxsd9.c @@ -20,6 +20,7 @@ #include <linux/slab.h> #include <linux/module.h> #include <linux/regmap.h> +#include <linux/bitops.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> #include <linux/iio/buffer.h> @@ -35,9 +36,29 @@ #define KXSD9_REG_RESET 0x0a #define KXSD9_REG_CTRL_C 0x0c -#define KXSD9_FS_MASK 0x03 +#define KXSD9_CTRL_C_FS_MASK 0x03 +#define KXSD9_CTRL_C_FS_8G 0x00 +#define KXSD9_CTRL_C_FS_6G 0x01 +#define KXSD9_CTRL_C_FS_4G 0x02 +#define KXSD9_CTRL_C_FS_2G 0x03 +#define KXSD9_CTRL_C_MOT_LAT BIT(3) +#define KXSD9_CTRL_C_MOT_LEV BIT(4) +#define KXSD9_CTRL_C_LP_MASK 0xe0 +#define KXSD9_CTRL_C_LP_NONE 0x00 +#define KXSD9_CTRL_C_LP_2000HZC BIT(5) +#define KXSD9_CTRL_C_LP_2000HZB BIT(6) +#define KXSD9_CTRL_C_LP_2000HZA (BIT(5)|BIT(6)) +#define KXSD9_CTRL_C_LP_1000HZ BIT(7) +#define KXSD9_CTRL_C_LP_500HZ (BIT(7)|BIT(5)) +#define KXSD9_CTRL_C_LP_100HZ (BIT(7)|BIT(6)) +#define KXSD9_CTRL_C_LP_50HZ (BIT(7)|BIT(6)|BIT(5)) #define KXSD9_REG_CTRL_B 0x0d + +#define KXSD9_CTRL_B_CLK_HLD BIT(7) +#define KXSD9_CTRL_B_ENABLE BIT(6) +#define KXSD9_CTRL_B_ST BIT(5) /* Self-test */ + #define KXSD9_REG_CTRL_A 0x0e /** @@ -65,7 +86,6 @@ static int kxsd9_write_scale(struct iio_dev *indio_dev, int micro) int ret, i; struct kxsd9_state *st = iio_priv(indio_dev); bool foundit = false; - unsigned int val; for (i = 0; i < 4; i++) if (micro == kxsd9_micro_scales[i]) { @@ -75,14 +95,12 @@ static int kxsd9_write_scale(struct iio_dev *indio_dev, int micro) if (!foundit) return -EINVAL; - ret = regmap_read(st->map, - KXSD9_REG_CTRL_C, - &val); + ret = regmap_update_bits(st->map, + KXSD9_REG_CTRL_C, + KXSD9_CTRL_C_FS_MASK, + i); if (ret < 0) goto error_ret; - ret = regmap_write(st->map, - KXSD9_REG_CTRL_C, - (val & ~KXSD9_FS_MASK) | i); error_ret: return ret; } @@ -150,7 +168,7 @@ static int kxsd9_read_raw(struct iio_dev *indio_dev, if (ret < 0) goto error_ret; *val = 0; - *val2 = kxsd9_micro_scales[regval & KXSD9_FS_MASK]; + *val2 = kxsd9_micro_scales[regval & KXSD9_CTRL_C_FS_MASK]; ret = IIO_VAL_INT_PLUS_MICRO; break; } -- cgit v0.10.2 From 2bb4a02aad0257148be4f51e3b4c9c0077787e17 Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Thu, 1 Sep 2016 11:44:46 +0200 Subject: iio: accel: kxsd9: Fetch and handle regulators This adds supply regulator handling for the VDD and IOVDD inputs on the KXSD9 component, makes sure to bring the regulators online during probe and disable them on remove or the errorpath. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c index 8c6a455..dc53f70 100644 --- a/drivers/iio/accel/kxsd9.c +++ b/drivers/iio/accel/kxsd9.c @@ -21,6 +21,8 @@ #include <linux/module.h> #include <linux/regmap.h> #include <linux/bitops.h> +#include <linux/delay.h> +#include <linux/regulator/consumer.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> #include <linux/iio/buffer.h> @@ -65,10 +67,12 @@ * struct kxsd9_state - device related storage * @dev: pointer to the parent device * @map: regmap to the device + * @regs: regulators for this device, VDD and IOVDD */ struct kxsd9_state { struct device *dev; struct regmap *map; + struct regulator_bulk_data regs[2]; }; #define KXSD9_SCALE_2G "0.011978" @@ -81,6 +85,12 @@ static const int kxsd9_micro_scales[4] = { 47853, 35934, 23927, 11978 }; #define KXSD9_ZERO_G_OFFSET -2048 +/* + * Regulator names + */ +static const char kxsd9_reg_vdd[] = "vdd"; +static const char kxsd9_reg_iovdd[] = "iovdd"; + static int kxsd9_write_scale(struct iio_dev *indio_dev, int micro) { int ret, i; @@ -252,12 +262,69 @@ static int kxsd9_power_up(struct kxsd9_state *st) { int ret; - ret = regmap_write(st->map, KXSD9_REG_CTRL_B, 0x40); + /* Enable the regulators */ + ret = regulator_bulk_enable(ARRAY_SIZE(st->regs), st->regs); + if (ret) { + dev_err(st->dev, "Cannot enable regulators\n"); + return ret; + } + + /* Power up */ + ret = regmap_write(st->map, + KXSD9_REG_CTRL_B, + KXSD9_CTRL_B_ENABLE); if (ret) return ret; - return regmap_write(st->map, KXSD9_REG_CTRL_C, 0x9b); + + /* + * Set 1000Hz LPF, 2g fullscale, motion wakeup threshold 1g, + * latched wakeup + */ + ret = regmap_write(st->map, + KXSD9_REG_CTRL_C, + KXSD9_CTRL_C_LP_1000HZ | + KXSD9_CTRL_C_MOT_LEV | + KXSD9_CTRL_C_MOT_LAT | + KXSD9_CTRL_C_FS_2G); + if (ret) + return ret; + + /* + * Power-up time depends on the LPF setting, but typ 15.9 ms, let's + * set 20 ms to allow for some slack. + */ + msleep(20); + + return 0; }; +static int kxsd9_power_down(struct kxsd9_state *st) +{ + int ret; + + /* + * Set into low power mode - since there may be more users of the + * regulators this is the first step of the power saving: it will + * make sure we conserve power even if there are others users on the + * regulators. + */ + ret = regmap_update_bits(st->map, + KXSD9_REG_CTRL_B, + KXSD9_CTRL_B_ENABLE, + 0); + if (ret) + return ret; + + /* Disable the regulators */ + ret = regulator_bulk_disable(ARRAY_SIZE(st->regs), st->regs); + if (ret) { + dev_err(st->dev, "Cannot disable regulators\n"); + return ret; + } + + return 0; +} + static const struct iio_info kxsd9_info = { .read_raw = &kxsd9_read_raw, .write_raw = &kxsd9_write_raw, @@ -292,6 +359,17 @@ int kxsd9_common_probe(struct device *parent, indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->available_scan_masks = kxsd9_scan_masks; + /* Fetch and turn on regulators */ + st->regs[0].supply = kxsd9_reg_vdd; + st->regs[1].supply = kxsd9_reg_iovdd; + ret = devm_regulator_bulk_get(parent, + ARRAY_SIZE(st->regs), + st->regs); + if (ret) { + dev_err(parent, "Cannot get regulators\n"); + return ret; + } + kxsd9_power_up(st); ret = iio_triggered_buffer_setup(indio_dev, @@ -300,7 +378,7 @@ int kxsd9_common_probe(struct device *parent, NULL); if (ret) { dev_err(parent, "triggered buffer setup failed\n"); - return ret; + goto err_power_down; } ret = iio_device_register(indio_dev); @@ -313,6 +391,8 @@ int kxsd9_common_probe(struct device *parent, err_cleanup_buffer: iio_triggered_buffer_cleanup(indio_dev); +err_power_down: + kxsd9_power_down(st); return ret; } @@ -321,9 +401,11 @@ EXPORT_SYMBOL(kxsd9_common_probe); int kxsd9_common_remove(struct device *parent) { struct iio_dev *indio_dev = dev_get_drvdata(parent); + struct kxsd9_state *st = iio_priv(indio_dev); iio_triggered_buffer_cleanup(indio_dev); iio_device_unregister(indio_dev); + kxsd9_power_down(st); return 0; } -- cgit v0.10.2 From 79383aaec47a0ea0df49728ad0b8e72c4ac58fd0 Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Thu, 1 Sep 2016 11:44:47 +0200 Subject: iio: accel: kxsd9: Replace "parent" with "dev" What is passed to the .probe() and .remove() functions is technically the parent of the created IIO device but it becomes a big confusion for the head to have it named like this since it is usually clear from context the "dev" refers to the physical device, and when next adding PM callbacks a clean "struct device *dev" pointer is passed to these and that makes it even more confused. Rename "parent" to "dev" like in most other drivers. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c index dc53f70..f18cc94 100644 --- a/drivers/iio/accel/kxsd9.c +++ b/drivers/iio/accel/kxsd9.c @@ -335,7 +335,7 @@ static const struct iio_info kxsd9_info = { /* Four channels apart from timestamp, scan mask = 0x0f */ static const unsigned long kxsd9_scan_masks[] = { 0xf, 0 }; -int kxsd9_common_probe(struct device *parent, +int kxsd9_common_probe(struct device *dev, struct regmap *map, const char *name) { @@ -343,18 +343,18 @@ int kxsd9_common_probe(struct device *parent, struct kxsd9_state *st; int ret; - indio_dev = devm_iio_device_alloc(parent, sizeof(*st)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; st = iio_priv(indio_dev); - st->dev = parent; + st->dev = dev; st->map = map; indio_dev->channels = kxsd9_channels; indio_dev->num_channels = ARRAY_SIZE(kxsd9_channels); indio_dev->name = name; - indio_dev->dev.parent = parent; + indio_dev->dev.parent = dev; indio_dev->info = &kxsd9_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->available_scan_masks = kxsd9_scan_masks; @@ -362,11 +362,11 @@ int kxsd9_common_probe(struct device *parent, /* Fetch and turn on regulators */ st->regs[0].supply = kxsd9_reg_vdd; st->regs[1].supply = kxsd9_reg_iovdd; - ret = devm_regulator_bulk_get(parent, + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(st->regs), st->regs); if (ret) { - dev_err(parent, "Cannot get regulators\n"); + dev_err(dev, "Cannot get regulators\n"); return ret; } @@ -377,7 +377,7 @@ int kxsd9_common_probe(struct device *parent, kxsd9_trigger_handler, NULL); if (ret) { - dev_err(parent, "triggered buffer setup failed\n"); + dev_err(dev, "triggered buffer setup failed\n"); goto err_power_down; } @@ -385,7 +385,7 @@ int kxsd9_common_probe(struct device *parent, if (ret) goto err_cleanup_buffer; - dev_set_drvdata(parent, indio_dev); + dev_set_drvdata(dev, indio_dev); return 0; @@ -398,9 +398,9 @@ err_power_down: } EXPORT_SYMBOL(kxsd9_common_probe); -int kxsd9_common_remove(struct device *parent) +int kxsd9_common_remove(struct device *dev) { - struct iio_dev *indio_dev = dev_get_drvdata(parent); + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct kxsd9_state *st = iio_priv(indio_dev); iio_triggered_buffer_cleanup(indio_dev); diff --git a/drivers/iio/accel/kxsd9.h b/drivers/iio/accel/kxsd9.h index 19131a7..9c0861f 100644 --- a/drivers/iio/accel/kxsd9.h +++ b/drivers/iio/accel/kxsd9.h @@ -4,7 +4,7 @@ #define KXSD9_STATE_RX_SIZE 2 #define KXSD9_STATE_TX_SIZE 2 -int kxsd9_common_probe(struct device *parent, +int kxsd9_common_probe(struct device *dev, struct regmap *map, const char *name); -int kxsd9_common_remove(struct device *parent); +int kxsd9_common_remove(struct device *dev); -- cgit v0.10.2 From 9a9a369d6178dd4e263c49085ce1b37e1e8f63a0 Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Thu, 1 Sep 2016 11:44:48 +0200 Subject: iio: accel: kxsd9: Deploy system and runtime PM This deploys runtime and system PM in the KXSD9 driver: - Use the force_runtime_suspend/resume callbacks as system PM operations. - Add buffer prepare/unprepare callbacks to grab the runtime PM while we're using buffered reads and put get/put_autosuspend in these. - Insert get/put_autosuspend calls anywhere the IO is used from the raw read/write callbacks. - Move the fullscale setting to be cached in the state container so we can restore it properly when coming back from system/runtime suspend. - Set the autosuspend delay to two orders of magnitude that of the sensor start-up time (20ms) so we will autosuspend after 2s. - Register the callbacks in both the SPI and I2C subdrivers. Tested with the I2C KXSD9 on the Qualcomm APQ8060 Dragonboard. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/accel/kxsd9-i2c.c b/drivers/iio/accel/kxsd9-i2c.c index 4aaa27d..95e2085 100644 --- a/drivers/iio/accel/kxsd9-i2c.c +++ b/drivers/iio/accel/kxsd9-i2c.c @@ -55,6 +55,7 @@ static struct i2c_driver kxsd9_i2c_driver = { .driver = { .name = "kxsd9", .of_match_table = of_match_ptr(kxsd9_of_match), + .pm = &kxsd9_dev_pm_ops, }, .probe = kxsd9_i2c_probe, .remove = kxsd9_i2c_remove, diff --git a/drivers/iio/accel/kxsd9-spi.c b/drivers/iio/accel/kxsd9-spi.c index c5af51b..b7d0078 100644 --- a/drivers/iio/accel/kxsd9-spi.c +++ b/drivers/iio/accel/kxsd9-spi.c @@ -43,6 +43,7 @@ MODULE_DEVICE_TABLE(spi, kxsd9_spi_id); static struct spi_driver kxsd9_spi_driver = { .driver = { .name = "kxsd9", + .pm = &kxsd9_dev_pm_ops, }, .probe = kxsd9_spi_probe, .remove = kxsd9_spi_remove, diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c index f18cc94..a28163b7 100644 --- a/drivers/iio/accel/kxsd9.c +++ b/drivers/iio/accel/kxsd9.c @@ -23,6 +23,7 @@ #include <linux/bitops.h> #include <linux/delay.h> #include <linux/regulator/consumer.h> +#include <linux/pm_runtime.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> #include <linux/iio/buffer.h> @@ -68,11 +69,13 @@ * @dev: pointer to the parent device * @map: regmap to the device * @regs: regulators for this device, VDD and IOVDD + * @scale: the current scaling setting */ struct kxsd9_state { struct device *dev; struct regmap *map; struct regulator_bulk_data regs[2]; + u8 scale; }; #define KXSD9_SCALE_2G "0.011978" @@ -111,6 +114,10 @@ static int kxsd9_write_scale(struct iio_dev *indio_dev, int micro) i); if (ret < 0) goto error_ret; + + /* Cached scale when the sensor is powered down */ + st->scale = i; + error_ret: return ret; } @@ -133,6 +140,9 @@ static int kxsd9_write_raw(struct iio_dev *indio_dev, long mask) { int ret = -EINVAL; + struct kxsd9_state *st = iio_priv(indio_dev); + + pm_runtime_get_sync(st->dev); if (mask == IIO_CHAN_INFO_SCALE) { /* Check no integer component */ @@ -141,6 +151,9 @@ static int kxsd9_write_raw(struct iio_dev *indio_dev, ret = kxsd9_write_scale(indio_dev, val2); } + pm_runtime_mark_last_busy(st->dev); + pm_runtime_put_autosuspend(st->dev); + return ret; } @@ -154,6 +167,8 @@ static int kxsd9_read_raw(struct iio_dev *indio_dev, __be16 raw_val; u16 nval; + pm_runtime_get_sync(st->dev); + switch (mask) { case IIO_CHAN_INFO_RAW: ret = regmap_bulk_read(st->map, chan->address, &raw_val, @@ -184,6 +199,9 @@ static int kxsd9_read_raw(struct iio_dev *indio_dev, } error_ret: + pm_runtime_mark_last_busy(st->dev); + pm_runtime_put_autosuspend(st->dev); + return ret; }; @@ -214,6 +232,32 @@ static irqreturn_t kxsd9_trigger_handler(int irq, void *p) return IRQ_HANDLED; } +static int kxsd9_buffer_preenable(struct iio_dev *indio_dev) +{ + struct kxsd9_state *st = iio_priv(indio_dev); + + pm_runtime_get_sync(st->dev); + + return 0; +} + +static int kxsd9_buffer_postdisable(struct iio_dev *indio_dev) +{ + struct kxsd9_state *st = iio_priv(indio_dev); + + pm_runtime_mark_last_busy(st->dev); + pm_runtime_put_autosuspend(st->dev); + + return 0; +} + +static const struct iio_buffer_setup_ops kxsd9_buffer_setup_ops = { + .preenable = kxsd9_buffer_preenable, + .postenable = iio_triggered_buffer_postenable, + .predisable = iio_triggered_buffer_predisable, + .postdisable = kxsd9_buffer_postdisable, +}; + #define KXSD9_ACCEL_CHAN(axis, index) \ { \ .type = IIO_ACCEL, \ @@ -285,7 +329,7 @@ static int kxsd9_power_up(struct kxsd9_state *st) KXSD9_CTRL_C_LP_1000HZ | KXSD9_CTRL_C_MOT_LEV | KXSD9_CTRL_C_MOT_LAT | - KXSD9_CTRL_C_FS_2G); + st->scale); if (ret) return ret; @@ -369,13 +413,15 @@ int kxsd9_common_probe(struct device *dev, dev_err(dev, "Cannot get regulators\n"); return ret; } + /* Default scaling */ + st->scale = KXSD9_CTRL_C_FS_2G; kxsd9_power_up(st); ret = iio_triggered_buffer_setup(indio_dev, iio_pollfunc_store_time, kxsd9_trigger_handler, - NULL); + &kxsd9_buffer_setup_ops); if (ret) { dev_err(dev, "triggered buffer setup failed\n"); goto err_power_down; @@ -387,6 +433,19 @@ int kxsd9_common_probe(struct device *dev, dev_set_drvdata(dev, indio_dev); + /* Enable runtime PM */ + pm_runtime_get_noresume(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + /* + * Set autosuspend to two orders of magnitude larger than the + * start-up time. 20ms start-up time means 2000ms autosuspend, + * i.e. 2 seconds. + */ + pm_runtime_set_autosuspend_delay(dev, 2000); + pm_runtime_use_autosuspend(dev); + pm_runtime_put(dev); + return 0; err_cleanup_buffer: @@ -405,12 +464,41 @@ int kxsd9_common_remove(struct device *dev) iio_triggered_buffer_cleanup(indio_dev); iio_device_unregister(indio_dev); + pm_runtime_get_sync(dev); + pm_runtime_put_noidle(dev); + pm_runtime_disable(dev); kxsd9_power_down(st); return 0; } EXPORT_SYMBOL(kxsd9_common_remove); +#ifdef CONFIG_PM +static int kxsd9_runtime_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct kxsd9_state *st = iio_priv(indio_dev); + + return kxsd9_power_down(st); +} + +static int kxsd9_runtime_resume(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct kxsd9_state *st = iio_priv(indio_dev); + + return kxsd9_power_up(st); +} +#endif /* CONFIG_PM */ + +const struct dev_pm_ops kxsd9_dev_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) + SET_RUNTIME_PM_OPS(kxsd9_runtime_suspend, + kxsd9_runtime_resume, NULL) +}; +EXPORT_SYMBOL(kxsd9_dev_pm_ops); + MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>"); MODULE_DESCRIPTION("Kionix KXSD9 driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/accel/kxsd9.h b/drivers/iio/accel/kxsd9.h index 9c0861f..7e8a281 100644 --- a/drivers/iio/accel/kxsd9.h +++ b/drivers/iio/accel/kxsd9.h @@ -8,3 +8,5 @@ int kxsd9_common_probe(struct device *dev, struct regmap *map, const char *name); int kxsd9_common_remove(struct device *dev); + +extern const struct dev_pm_ops kxsd9_dev_pm_ops; -- cgit v0.10.2 From 041c4d754ae3901b0ac9295a110c4ad920d63201 Mon Sep 17 00:00:00 2001 From: sayli karnik <karniksayli1995@gmail.com> Date: Sun, 18 Sep 2016 12:51:03 +0530 Subject: staging: ks7010: Use #include <linux/atomic.h> instead of <asm/atomic.h> This patch replaces <asm/atomic.h> with <linux/atomic.h>, as suggested by checkpatch.pl. Signed-off-by: sayli karnik <karniksayli1995@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c index f9aec4f..394cb14 100644 --- a/drivers/staging/ks7010/ks7010_sdio.c +++ b/drivers/staging/ks7010/ks7010_sdio.c @@ -14,7 +14,7 @@ #include <linux/mmc/card.h> #include <linux/mmc/sdio_func.h> #include <linux/workqueue.h> -#include <asm/atomic.h> +#include <linux/atomic.h> #include "ks_wlan.h" #include "ks_wlan_ioctl.h" -- cgit v0.10.2 From 53638cef86bfa613bd635f9c8c9462524c8dc6d7 Mon Sep 17 00:00:00 2001 From: sayli karnik <karniksayli1995@gmail.com> Date: Sun, 18 Sep 2016 12:52:27 +0530 Subject: staging: ks7010: Remove braces following single statement blocks The patch removes braces {} for single statement blocks, as suggested by checkpatch.pl. Signed-off-by: sayli karnik <karniksayli1995@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c index 394cb14..42415b4 100644 --- a/drivers/staging/ks7010/ks7010_sdio.c +++ b/drivers/staging/ks7010/ks7010_sdio.c @@ -157,9 +157,9 @@ void ks_wlan_hw_wakeup_request(struct ks_wlan_private *priv) rw_data = WAKEUP_REQ; retval = ks7010_sdio_write(priv, WAKEUP, &rw_data, sizeof(rw_data)); - if (retval) { + if (retval) DPRINTK(1, " error : WAKEUP=%02X\n", rw_data); - } + DPRINTK(4, "wake up : WAKEUP=%02X\n", rw_data); priv->last_wakeup = jiffies; ++priv->wakeup_count; @@ -398,9 +398,8 @@ static void rx_event_task(unsigned long dev) hostif_receive(priv, rp->data, rp->size); inc_rxqhead(priv); - if (cnt_rxqbody(priv) > 0) { + if (cnt_rxqbody(priv) > 0) tasklet_schedule(&priv->ks_wlan_hw.rx_bh_task); - } } } @@ -426,9 +425,8 @@ static void ks_wlan_hw_rx(void *dev, uint16_t size) retval = ks7010_sdio_read(priv, DATA_WINDOW, &rx_buffer->data[0], hif_align_size(size)); - if (retval) { + if (retval) goto error_out; - } /* length check */ if (size > 2046 || size == 0) { @@ -443,9 +441,9 @@ static void ks_wlan_hw_rx(void *dev, uint16_t size) retval = ks7010_sdio_write(priv, READ_STATUS, &read_status, sizeof(read_status)); - if (retval) { + if (retval) DPRINTK(1, " error : READ_STATUS=%02X\n", read_status); - } + goto error_out; } @@ -459,9 +457,9 @@ static void ks_wlan_hw_rx(void *dev, uint16_t size) retval = ks7010_sdio_write(priv, READ_STATUS, &read_status, sizeof(read_status)); - if (retval) { + if (retval) DPRINTK(1, " error : READ_STATUS=%02X\n", read_status); - } + DPRINTK(4, "READ_STATUS=%02X\n", read_status); if (atomic_read(&priv->psstatus.confirm_wait)) { @@ -545,9 +543,9 @@ static void ks7010_rw_function(struct work_struct *work) ks_wlan_hw_rx((void *)priv, (uint16_t) (((rw_data & RSIZE_MASK) << 4))); } - if ((rw_data & WSTATUS_MASK)) { + if ((rw_data & WSTATUS_MASK)) tx_device_task((void *)priv); - } + _ks_wlan_hw_power_save(priv); err_out: @@ -884,9 +882,9 @@ static void ks7010_card_init(struct ks_wlan_private *priv) DPRINTK(1, "wait time out!! SME_START\n"); } - if (priv->mac_address_valid && priv->version_size) { + if (priv->mac_address_valid && priv->version_size) priv->dev_state = DEVICE_STATE_PREINIT; - } + hostif_sme_enqueue(priv, SME_GET_EEPROM_CKSUM); @@ -1029,9 +1027,9 @@ static int ks7010_sdio_probe(struct sdio_func *func, init_completion(&priv->ks_wlan_hw.ks7010_sdio_wait); priv->ks_wlan_hw.read_buf = NULL; priv->ks_wlan_hw.read_buf = kmalloc(RX_DATA_SIZE, GFP_KERNEL); - if (!priv->ks_wlan_hw.read_buf) { + if (!priv->ks_wlan_hw.read_buf) goto error_free_netdev; - } + priv->dev_state = DEVICE_STATE_PREBOOT; priv->net_dev = netdev; priv->firmware_version[0] = '\0'; @@ -1067,9 +1065,9 @@ static int ks7010_sdio_probe(struct sdio_func *func, sdio_claim_host(func); ret = ks7010_sdio_write(priv, INT_PENDING, &rw_data, sizeof(rw_data)); sdio_release_host(func); - if (ret) { + if (ret) DPRINTK(1, " error : INT_PENDING=%02X\n", rw_data); - } + DPRINTK(4, " clear Interrupt : INT_PENDING=%02X\n", rw_data); /* enable ks7010sdio interrupt (INT_GCR_B|INT_READ_STATUS|INT_WRITE_STATUS) */ @@ -1077,9 +1075,9 @@ static int ks7010_sdio_probe(struct sdio_func *func, sdio_claim_host(func); ret = ks7010_sdio_write(priv, INT_ENABLE, &rw_data, sizeof(rw_data)); sdio_release_host(func); - if (ret) { + if (ret) DPRINTK(1, " error : INT_ENABLE=%02X\n", rw_data); - } + DPRINTK(4, " enable Interrupt : INT_ENABLE=%02X\n", rw_data); priv->dev_state = DEVICE_STATE_BOOT; -- cgit v0.10.2 From 3d4a2cacc43fdae5c2c681455955c88d22561649 Mon Sep 17 00:00:00 2001 From: sayli karnik <karniksayli1995@gmail.com> Date: Sun, 18 Sep 2016 12:53:49 +0530 Subject: staging: ks7010: Remove space after '(' and before ')' The patch fixes the following errors detected by checkpatch.pl: ERROR: space prohibited before that close parenthesis ')' ERROR: space prohibited after that open parenthesis '(' Signed-off-by: sayli karnik <karniksayli1995@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c index 42415b4..54d055c 100644 --- a/drivers/staging/ks7010/ks7010_sdio.c +++ b/drivers/staging/ks7010/ks7010_sdio.c @@ -35,18 +35,18 @@ MODULE_DEVICE_TABLE(sdio, ks7010_sdio_ids); /* macro */ #define inc_txqhead(priv) \ - ( priv->tx_dev.qhead = (priv->tx_dev.qhead + 1) % TX_DEVICE_BUFF_SIZE ) + (priv->tx_dev.qhead = (priv->tx_dev.qhead + 1) % TX_DEVICE_BUFF_SIZE) #define inc_txqtail(priv) \ - ( priv->tx_dev.qtail = (priv->tx_dev.qtail + 1) % TX_DEVICE_BUFF_SIZE ) + (priv->tx_dev.qtail = (priv->tx_dev.qtail + 1) % TX_DEVICE_BUFF_SIZE) #define cnt_txqbody(priv) \ - (((priv->tx_dev.qtail + TX_DEVICE_BUFF_SIZE) - (priv->tx_dev.qhead)) % TX_DEVICE_BUFF_SIZE ) + (((priv->tx_dev.qtail + TX_DEVICE_BUFF_SIZE) - (priv->tx_dev.qhead)) % TX_DEVICE_BUFF_SIZE) #define inc_rxqhead(priv) \ - ( priv->rx_dev.qhead = (priv->rx_dev.qhead + 1) % RX_DEVICE_BUFF_SIZE ) + (priv->rx_dev.qhead = (priv->rx_dev.qhead + 1) % RX_DEVICE_BUFF_SIZE) #define inc_rxqtail(priv) \ - ( priv->rx_dev.qtail = (priv->rx_dev.qtail + 1) % RX_DEVICE_BUFF_SIZE ) + (priv->rx_dev.qtail = (priv->rx_dev.qtail + 1) % RX_DEVICE_BUFF_SIZE) #define cnt_rxqbody(priv) \ - (((priv->rx_dev.qtail + RX_DEVICE_BUFF_SIZE) - (priv->rx_dev.qhead)) % RX_DEVICE_BUFF_SIZE ) + (((priv->rx_dev.qtail + RX_DEVICE_BUFF_SIZE) - (priv->rx_dev.qhead)) % RX_DEVICE_BUFF_SIZE) static int ks7010_sdio_read(struct ks_wlan_private *priv, unsigned int address, unsigned char *buffer, int length) -- cgit v0.10.2 From 7333c6fd438d64b55c7f31909f5274b26eb62c03 Mon Sep 17 00:00:00 2001 From: sayli karnik <karniksayli1995@gmail.com> Date: Sun, 18 Sep 2016 12:54:43 +0530 Subject: staging: ks7010: Remove unnecessary blank lines and commented code The patch removes unnecessary blank lines as detected by checkpatch.pl. Also, it removes a commented line of unrequired code. Signed-off-by: sayli karnik <karniksayli1995@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c index 54d055c..d35cda8 100644 --- a/drivers/staging/ks7010/ks7010_sdio.c +++ b/drivers/staging/ks7010/ks7010_sdio.c @@ -180,8 +180,6 @@ int _ks_wlan_hw_power_save(struct ks_wlan_private *priv) if (priv->reg.operation_mode == MODE_INFRASTRUCTURE && (priv->connect_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) { - - //DPRINTK(1,"psstatus.status=%d\n",atomic_read(&priv->psstatus.status)); if (priv->dev_state == DEVICE_STATE_SLEEP) { switch (atomic_read(&priv->psstatus.status)) { case PS_SNOOZE: /* 4 */ @@ -244,7 +242,6 @@ int _ks_wlan_hw_power_save(struct ks_wlan_private *priv) break; } } - } return rc; @@ -343,7 +340,6 @@ static void tx_device_task(void *dev) &priv->ks_wlan_hw.rw_wq, 1); return; } - } kfree(sp->sendp); /* allocated memory free */ if (sp->complete_handler) /* TX Complete */ @@ -597,7 +593,6 @@ static void ks_sdio_interrupt(struct sdio_func *func) } complete(&priv->psstatus.wakeup_wait); } - } do { -- cgit v0.10.2 From ca4765152e9c7cc713a6f52073027648d70ff4c5 Mon Sep 17 00:00:00 2001 From: sayli karnik <karniksayli1995@gmail.com> Date: Sun, 18 Sep 2016 12:55:32 +0530 Subject: staging: ks7010: Remove the space after a type cast The patch removes an unnecessary space after a cast, as detected by checkpatch.pl. Signed-off-by: sayli karnik <karniksayli1995@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c index d35cda8..a9fac71 100644 --- a/drivers/staging/ks7010/ks7010_sdio.c +++ b/drivers/staging/ks7010/ks7010_sdio.c @@ -537,7 +537,7 @@ static void ks7010_rw_function(struct work_struct *work) if (rw_data & RSIZE_MASK) { /* Read schedule */ ks_wlan_hw_rx((void *)priv, - (uint16_t) (((rw_data & RSIZE_MASK) << 4))); + (uint16_t)(((rw_data & RSIZE_MASK) << 4))); } if ((rw_data & WSTATUS_MASK)) tx_device_task((void *)priv); @@ -609,7 +609,7 @@ static void ks_sdio_interrupt(struct sdio_func *func) rsize = rw_data & RSIZE_MASK; if (rsize) { /* Read schedule */ ks_wlan_hw_rx((void *)priv, - (uint16_t) (((rsize) << 4))); + (uint16_t)(((rsize) << 4))); } if (rw_data & WSTATUS_MASK) { #if 0 @@ -1150,7 +1150,7 @@ static void ks7010_sdio_remove(struct sdio_func *func) cpu_to_le16((uint16_t) (sizeof(*pp) - sizeof(pp->header.size))); - pp->header.event = cpu_to_le16((uint16_t) HIF_STOP_REQ); + pp->header.event = cpu_to_le16((uint16_t)HIF_STOP_REQ); sdio_claim_host(func); write_to_device(priv, (unsigned char *)pp, -- cgit v0.10.2 From 149ad082a2f4873daca28f57d59ec3deb47685ac Mon Sep 17 00:00:00 2001 From: sayli karnik <karniksayli1995@gmail.com> Date: Sun, 18 Sep 2016 12:56:25 +0530 Subject: staging: ks7010: Remove extra round braces around expressions/variables This patch removes excess round braces around expressions/variables. Signed-off-by: sayli karnik <karniksayli1995@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c index a9fac71..f7ed8db 100644 --- a/drivers/staging/ks7010/ks7010_sdio.c +++ b/drivers/staging/ks7010/ks7010_sdio.c @@ -537,7 +537,7 @@ static void ks7010_rw_function(struct work_struct *work) if (rw_data & RSIZE_MASK) { /* Read schedule */ ks_wlan_hw_rx((void *)priv, - (uint16_t)(((rw_data & RSIZE_MASK) << 4))); + (uint16_t)((rw_data & RSIZE_MASK) << 4)); } if ((rw_data & WSTATUS_MASK)) tx_device_task((void *)priv); @@ -609,7 +609,7 @@ static void ks_sdio_interrupt(struct sdio_func *func) rsize = rw_data & RSIZE_MASK; if (rsize) { /* Read schedule */ ks_wlan_hw_rx((void *)priv, - (uint16_t)(((rsize) << 4))); + (uint16_t)(rsize << 4)); } if (rw_data & WSTATUS_MASK) { #if 0 -- cgit v0.10.2 From 12884004f17f1c469d1f9a9a9db6147694db57d0 Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Thu, 1 Sep 2016 11:44:49 +0200 Subject: iio: accel: kxsd9: Support reading a mounting matrix This adds support for the mounting matrix to the KXSD9 driver. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c index a28163b7..9af60ac 100644 --- a/drivers/iio/accel/kxsd9.c +++ b/drivers/iio/accel/kxsd9.c @@ -68,12 +68,14 @@ * struct kxsd9_state - device related storage * @dev: pointer to the parent device * @map: regmap to the device + * @orientation: mounting matrix, flipped axis etc * @regs: regulators for this device, VDD and IOVDD * @scale: the current scaling setting */ struct kxsd9_state { struct device *dev; struct regmap *map; + struct iio_mount_matrix orientation; struct regulator_bulk_data regs[2]; u8 scale; }; @@ -258,6 +260,20 @@ static const struct iio_buffer_setup_ops kxsd9_buffer_setup_ops = { .postdisable = kxsd9_buffer_postdisable, }; +static const struct iio_mount_matrix * +kxsd9_get_mount_matrix(const struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct kxsd9_state *st = iio_priv(indio_dev); + + return &st->orientation; +} + +static const struct iio_chan_spec_ext_info kxsd9_ext_info[] = { + IIO_MOUNT_MATRIX(IIO_SHARED_BY_TYPE, kxsd9_get_mount_matrix), + { }, +}; + #define KXSD9_ACCEL_CHAN(axis, index) \ { \ .type = IIO_ACCEL, \ @@ -266,6 +282,7 @@ static const struct iio_buffer_setup_ops kxsd9_buffer_setup_ops = { .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ BIT(IIO_CHAN_INFO_OFFSET), \ + .ext_info = kxsd9_ext_info, \ .address = KXSD9_REG_##axis, \ .scan_index = index, \ .scan_type = { \ @@ -403,6 +420,13 @@ int kxsd9_common_probe(struct device *dev, indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->available_scan_masks = kxsd9_scan_masks; + /* Read the mounting matrix, if present */ + ret = of_iio_read_mount_matrix(dev, + "mount-matrix", + &st->orientation); + if (ret) + return ret; + /* Fetch and turn on regulators */ st->regs[0].supply = kxsd9_reg_vdd; st->regs[1].supply = kxsd9_reg_iovdd; -- cgit v0.10.2 From 70b9bb71fdf2da78341cdf70d3599c031d1e29fa Mon Sep 17 00:00:00 2001 From: Anchal Jain <anchalj109@gmail.com> Date: Sun, 18 Sep 2016 13:18:56 +0530 Subject: staging: rtl8188eu: core: Fix comparison to NULL Convert pointer comparisons to NULL to NULL pointer 'p' Signed-off-by: Anchal Jain <anchalj109@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c index bf722e7..6662855 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ap.c +++ b/drivers/staging/rtl8188eu/core/rtw_ap.c @@ -78,7 +78,7 @@ static void update_BCNTIM(struct adapter *padapter) /* update TIM IE */ p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, _TIM_IE_, &tim_ielen, pnetwork_mlmeext->IELength - _FIXED_IE_LENGTH_); - if (p != NULL && tim_ielen > 0) { + if (p && tim_ielen > 0) { tim_ielen += 2; premainder_ie = p+tim_ielen; tim_ie_offset = (int)(p - pie); @@ -98,7 +98,7 @@ static void update_BCNTIM(struct adapter *padapter) _SUPPORTEDRATES_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_)); - if (p != NULL) + if (p) offset += tmp_len+2; /* DS Parameter Set IE, len = 3 */ @@ -183,7 +183,7 @@ void rtw_add_bcn_ie(struct adapter *padapter, struct wlan_bssid_ex *pnetwork, i += (pIE->Length + 2); } - if (p != NULL && ielen > 0) { + if (p && ielen > 0) { ielen += 2; premainder_ie = p+ielen; @@ -232,7 +232,7 @@ void rtw_remove_bcn_ie(struct adapter *padapter, struct wlan_bssid_ex *pnetwork, p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, index, &ielen, pnetwork->IELength - _FIXED_IE_LENGTH_); - if (p != NULL && ielen > 0) { + if (p && ielen > 0) { ielen += 2; premainder_ie = p+ielen; @@ -934,14 +934,14 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) memset(supportRate, 0, NDIS_802_11_LENGTH_RATES_EX); /* get supported rates */ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_)); - if (p != NULL) { + if (p) { memcpy(supportRate, p+2, ie_len); supportRateNum = ie_len; } /* get ext_supported rates */ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, &ie_len, pbss_network->IELength - _BEACON_IE_OFFSET_); - if (p != NULL) { + if (p) { memcpy(supportRate+supportRateNum, p+2, ie_len); supportRateNum += ie_len; } -- cgit v0.10.2 From 58f0ff2a576d5389acebdfb21d54a921fd80ad10 Mon Sep 17 00:00:00 2001 From: Anchal Jain <anchalj109@gmail.com> Date: Sun, 18 Sep 2016 13:21:20 +0530 Subject: staging: rtl8188eu: core: Add spaces around operators Add spaces around operators {+, -, &, /, <<, &&} Signed-off-by: Anchal Jain <anchalj109@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c index 6662855..553e8d5 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ap.c +++ b/drivers/staging/rtl8188eu/core/rtw_ap.c @@ -80,7 +80,7 @@ static void update_BCNTIM(struct adapter *padapter) pnetwork_mlmeext->IELength - _FIXED_IE_LENGTH_); if (p && tim_ielen > 0) { tim_ielen += 2; - premainder_ie = p+tim_ielen; + premainder_ie = p + tim_ielen; tim_ie_offset = (int)(p - pie); remainder_ielen = pnetwork_mlmeext->IELength - tim_ie_offset - tim_ielen; @@ -186,7 +186,7 @@ void rtw_add_bcn_ie(struct adapter *padapter, struct wlan_bssid_ex *pnetwork, if (p && ielen > 0) { ielen += 2; - premainder_ie = p+ielen; + premainder_ie = p + ielen; ie_offset = (int)(p - pie); @@ -195,7 +195,7 @@ void rtw_add_bcn_ie(struct adapter *padapter, struct wlan_bssid_ex *pnetwork, if (bmatch) dst_ie = p; else - dst_ie = p+ielen; + dst_ie = p + ielen; } if (remainder_ielen > 0) { @@ -235,7 +235,7 @@ void rtw_remove_bcn_ie(struct adapter *padapter, struct wlan_bssid_ex *pnetwork, if (p && ielen > 0) { ielen += 2; - premainder_ie = p+ielen; + premainder_ie = p + ielen; ie_offset = (int)(p - pie); @@ -385,8 +385,8 @@ void expire_timeout_chk(struct adapter *padapter) 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)) { + 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, @@ -470,7 +470,7 @@ void add_RATid(struct adapter *padapter, struct sta_info *psta, u8 rssi_level) /* b/g mode ra_bitmap */ for (i = 0; i < sizeof(psta->bssrateset); i++) { if (psta->bssrateset[i]) - tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value(psta->bssrateset[i]&0x7f); + tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value(psta->bssrateset[i] & 0x7f); } /* n mode ra_bitmap */ if (psta_ht->ht_option) { @@ -482,7 +482,7 @@ void add_RATid(struct adapter *padapter, struct sta_info *psta, u8 rssi_level) for (i = 0; i < limit; i++) { if (psta_ht->ht_cap.mcs.rx_mask[i / 8] & BIT(i % 8)) - tx_ra_bitmap |= BIT(i+12); + tx_ra_bitmap |= BIT(i + 12); } /* max short GI rate */ @@ -507,19 +507,19 @@ void add_RATid(struct adapter *padapter, struct sta_info *psta, u8 rssi_level) psta->wireless_mode = sta_band; raid = networktype_to_raid(sta_band); - init_rate = get_highest_rate_idx(tx_ra_bitmap&0x0fffffff)&0x3f; + init_rate = get_highest_rate_idx(tx_ra_bitmap & 0x0fffffff) & 0x3f; if (psta->aid < NUM_STA) { u8 arg = 0; - arg = psta->mac_id&0x1f; + arg = psta->mac_id & 0x1f; arg |= BIT(7);/* support entry 2~31 */ if (shortGIrate) arg |= BIT(5); - tx_ra_bitmap |= ((raid<<28)&0xf0000000); + 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); @@ -573,7 +573,7 @@ static void update_bmc_sta(struct adapter *padapter) /* b/g mode ra_bitmap */ for (i = 0; i < supportRateNum; i++) { if (psta->bssrateset[i]) - tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value(psta->bssrateset[i]&0x7f); + tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value(psta->bssrateset[i] & 0x7f); } if (pcur_network->Configuration.DSConfig > 14) { @@ -587,7 +587,7 @@ static void update_bmc_sta(struct adapter *padapter) } raid = networktype_to_raid(network_type); - init_rate = get_highest_rate_idx(tx_ra_bitmap&0x0fffffff)&0x3f; + init_rate = get_highest_rate_idx(tx_ra_bitmap & 0x0fffffff) & 0x3f; /* ap mode */ rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, true); @@ -597,7 +597,7 @@ static void update_bmc_sta(struct adapter *padapter) arg = psta->mac_id&0x1f; arg |= BIT(7); - tx_ra_bitmap |= ((raid<<28)&0xf0000000); + tx_ra_bitmap |= ((raid << 28) & 0xf0000000); DBG_88E("update_bmc_sta, mask = 0x%x, arg = 0x%x\n", tx_ra_bitmap, arg); /* bitmap[0:27] = tx_rate_bitmap */ @@ -636,7 +636,7 @@ void update_sta_info_apmode(struct adapter *padapter, struct sta_info *psta) struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv; struct ht_priv *phtpriv_sta = &psta->htpriv; - psta->mac_id = psta->aid+1; + psta->mac_id = psta->aid + 1; DBG_88E("%s\n", __func__); /* ap mode */ @@ -750,7 +750,7 @@ static void start_bss_network(struct adapter *padapter, u8 *pbuf) /* check if there is wps ie, */ /* if there is wpsie in beacon, the hostapd will update beacon twice when stating hostapd, */ /* and at first time the security ie (RSN/WPA IE) will not include in beacon. */ - if (!rtw_get_wps_ie(pnetwork->IEs+_FIXED_IE_LENGTH_, pnetwork->IELength-_FIXED_IE_LENGTH_, NULL, NULL)) + if (!rtw_get_wps_ie(pnetwork->IEs + _FIXED_IE_LENGTH_, pnetwork->IELength - _FIXED_IE_LENGTH_, NULL, NULL)) pmlmeext->bstart_bss = true; /* todo: update wmm, ht cap */ @@ -803,7 +803,7 @@ static void start_bss_network(struct adapter *padapter, u8 *pbuf) /* set channel, bwmode */ p = rtw_get_ie((pnetwork->IEs + sizeof(struct ndis_802_11_fixed_ie)), _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength - sizeof(struct ndis_802_11_fixed_ie))); if (p && ie_len) { - pht_info = (struct HT_info_element *)(p+2); + pht_info = (struct HT_info_element *)(p + 2); if ((pregpriv->cbw40_enable) && (pht_info->infos[0] & BIT(2))) { /* switch to the 40M Hz mode */ @@ -935,14 +935,14 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) /* get supported rates */ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_)); if (p) { - memcpy(supportRate, p+2, ie_len); + memcpy(supportRate, p + 2, ie_len); supportRateNum = ie_len; } /* get ext_supported rates */ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, &ie_len, pbss_network->IELength - _BEACON_IE_OFFSET_); if (p) { - memcpy(supportRate+supportRateNum, p+2, ie_len); + memcpy(supportRate + supportRateNum, p + 2, ie_len); supportRateNum += ie_len; } @@ -970,7 +970,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_; p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _RSN_IE_2_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_)); if (p && ie_len > 0) { - if (rtw_parse_wpa2_ie(p, ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { + if (rtw_parse_wpa2_ie(p, ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; psecuritypriv->dot8021xalg = 1;/* psk, todo:802.1x */ @@ -989,8 +989,8 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) for (p = ie + _BEACON_IE_OFFSET_;; p += (ie_len + 2)) { p = rtw_get_ie(p, _SSN_IE_1_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2))); - if ((p) && (!memcmp(p+2, OUI1, 4))) { - if (rtw_parse_wpa_ie(p, ie_len+2, &group_cipher, + if ((p) && (!memcmp(p + 2, OUI1, 4))) { + if (rtw_parse_wpa_ie(p, ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; @@ -1014,10 +1014,10 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) for (p = ie + _BEACON_IE_OFFSET_;; p += (ie_len + 2)) { p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2))); - if ((p) && !memcmp(p+2, WMM_PARA_IE, 6)) { + if ((p) && !memcmp(p + 2, WMM_PARA_IE, 6)) { pmlmepriv->qospriv.qos_option = 1; - *(p+8) |= BIT(7);/* QoS Info, support U-APSD */ + *(p + 8) |= BIT(7);/* QoS Info, support U-APSD */ /* disable all ACM bits since the WMM admission control is not supported */ *(p + 10) &= ~BIT(4); /* BE */ @@ -1046,7 +1046,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) if ((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) || (psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP)) - pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&(0x07<<2)); + pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY & (0x07 << 2)); else pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&0x00); @@ -1147,7 +1147,7 @@ int rtw_acl_add_sta(struct adapter *padapter, u8 *addr) DBG_88E("%s(acl_num =%d) =%pM\n", __func__, pacl_list->num, (addr)); - if ((NUM_ACL-1) < pacl_list->num) + if ((NUM_ACL - 1) < pacl_list->num) return -1; spin_lock_bh(&(pacl_node_q->lock)); -- cgit v0.10.2 From 25670ba3f3719e6121a2b1a3c216833d1a9e1d89 Mon Sep 17 00:00:00 2001 From: Namrata A Shettar <namrataashettar@gmail.com> Date: Sun, 18 Sep 2016 13:46:01 +0530 Subject: staging: xgifb: Replace explicit NULL comparison Replace explicit NULL comparison with equivalent expression to resolve checkpatch issue. - x != NULL => x Signed-off-by: Namrata A Shettar <namrataashettar@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index d56ef14..23a3bd7 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -2085,7 +2085,7 @@ static int __init xgifb_init(void) { char *option = NULL; - if (forcecrt2type != NULL) + if (forcecrt2type) XGIfb_search_crt2type(forcecrt2type); if (fb_get_options("xgifb", &option)) return -ENODEV; -- cgit v0.10.2 From 56487aed9597569f5db716c86f9bc93aea1bd3b6 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal <bhumirks@gmail.com> Date: Sun, 18 Sep 2016 14:35:59 +0530 Subject: Staging: xgifb: Compress return logic This patch compresses the return logic into a single statement and removes the now unused return variable. Done using coccinelle: @@ type T; identifier r; @@ - T r; ... when !=r - r = + return ...; - return r; Signed-off-by: Bhumika Goyal <bhumirks@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index 23a3bd7..a58983f 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -62,7 +62,6 @@ static int XGIfb_mode_rate_to_dclock(struct vb_device_info *XGI_Pr, unsigned short ModeNo = modeno; unsigned short ModeIdIndex = 0, ClockIndex = 0; unsigned short RefreshRateTableIndex = 0; - int Clock; InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr); @@ -73,9 +72,7 @@ static int XGIfb_mode_rate_to_dclock(struct vb_device_info *XGI_Pr, ClockIndex = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK; - Clock = XGI_VCLKData[ClockIndex].CLOCK * 1000; - - return Clock; + return XGI_VCLKData[ClockIndex].CLOCK * 1000; } static int XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr, -- cgit v0.10.2 From 6869a11bff1df102dc73296129d63b9187a22f3a Mon Sep 17 00:00:00 2001 From: Sandhya Bankar <bankarsandhya512@gmail.com> Date: Sun, 18 Sep 2016 04:18:22 +0530 Subject: Staging: rtl8192e: Use !x instead of x == NULL Use !x instead of x == NULL. This patch was found by checkpatch. Signed-off-by: Sandhya Bankar <bankarsandhya512@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8192e/rtllib_module.c b/drivers/staging/rtl8192e/rtllib_module.c index f4f318a..9d5788e 100644 --- a/drivers/staging/rtl8192e/rtllib_module.c +++ b/drivers/staging/rtl8192e/rtllib_module.c @@ -138,7 +138,7 @@ struct net_device *alloc_rtllib(int sizeof_priv) rtllib_softmac_init(ieee); ieee->pHTInfo = kzalloc(sizeof(struct rt_hi_throughput), GFP_KERNEL); - if (ieee->pHTInfo == NULL) + if (!ieee->pHTInfo) return NULL; HTUpdateDefaultSetting(ieee); -- cgit v0.10.2 From a2576177cce7f1b5d04035a98bd1e27935fdb5fa Mon Sep 17 00:00:00 2001 From: Sandhya Bankar <bankarsandhya512@gmail.com> Date: Sun, 18 Sep 2016 04:29:54 +0530 Subject: Staging: lustre: lmv_obd: Remove redundant if-statement. Remove redundant if-statement. Signed-off-by: Sandhya Bankar <bankarsandhya512@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 5783359..0713e55 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -949,10 +949,8 @@ static int lmv_hsm_ct_register(struct lmv_obd *lmv, unsigned int cmd, int len, rc = libcfs_kkuc_group_add(filp, lk->lk_uid, lk->lk_group, &kcd, sizeof(kcd)); - if (rc) { - if (filp) - fput(filp); - } + if (rc && filp) + fput(filp); return rc; } -- cgit v0.10.2 From 604e383c5229a214e17695e3ec13d9aa4952e10c Mon Sep 17 00:00:00 2001 From: Sandhya Bankar <bankarsandhya512@gmail.com> Date: Sun, 18 Sep 2016 04:41:39 +0530 Subject: Staging: fbtft: Use !x instead of x == NULL. Use !x instead of x == NULL. This patch was found by checkpatch. Signed-off-by: Sandhya Bankar <bankarsandhya512@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fbtft/fbtft_device.c b/drivers/staging/fbtft/fbtft_device.c index 924abd3..e9f25dd 100644 --- a/drivers/staging/fbtft/fbtft_device.c +++ b/drivers/staging/fbtft/fbtft_device.c @@ -1401,7 +1401,7 @@ static int __init fbtft_device_init(void) long val; int ret = 0; - if (name == NULL) { + if (!name) { #ifdef MODULE pr_err("missing module parameter: 'name'\n"); return -EINVAL; -- cgit v0.10.2 From cbb351ccdfa1e2b3261a024fae7980597f56549f Mon Sep 17 00:00:00 2001 From: Sandhya Bankar <bankarsandhya512@gmail.com> Date: Sun, 18 Sep 2016 04:55:26 +0530 Subject: Staging: ks7010: Drop memory allocation cast. Drop cast on the result of kzalloc. The semantic patch that makes this change is as follows: @@ type T; @@ - (T *) (\(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\| kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\)(...)) Signed-off-by: Sandhya Bankar <bankarsandhya512@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c index f7ed8db..25ad43d 100644 --- a/drivers/staging/ks7010/ks7010_sdio.c +++ b/drivers/staging/ks7010/ks7010_sdio.c @@ -1140,8 +1140,7 @@ static void ks7010_sdio_remove(struct sdio_func *func) /* send stop request to MAC */ { struct hostif_stop_request_t *pp; - pp = (struct hostif_stop_request_t *) - kzalloc(hif_align_size(sizeof(*pp)), GFP_KERNEL); + pp = kzalloc(hif_align_size(sizeof(*pp)), GFP_KERNEL); if (!pp) { DPRINTK(3, "allocate memory failed..\n"); return; /* to do goto ni suru */ -- cgit v0.10.2 From c9573a8d1963ba82f163c4d113266da82c048c21 Mon Sep 17 00:00:00 2001 From: sayli karnik <karniksayli1995@gmail.com> Date: Sun, 18 Sep 2016 15:11:14 +0530 Subject: staging: wlan-ng: Remove the typedef to the 'wlandevice' structure This patch removes the typedef 'wlandevice_t' to the 'wlandevice' structure. Signed-off-by: sayli karnik <karniksayli1995@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index 28be314..8c592be 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -35,7 +35,7 @@ static const u32 prism2_cipher_suites[PRISM2_NUM_CIPHER_SUITES] = { /* prism2 device private data */ struct prism2_wiphy_private { - wlandevice_t *wlandev; + struct wlandevice *wlandev; struct ieee80211_supported_band band; struct ieee80211_channel channels[ARRAY_SIZE(prism2_channels)]; @@ -69,7 +69,7 @@ static int prism2_result2err(int prism2_result) return err; } -static int prism2_domibset_uint32(wlandevice_t *wlandev, u32 did, u32 data) +static int prism2_domibset_uint32(struct wlandevice *wlandev, u32 did, u32 data) { struct p80211msg_dot11req_mibset msg; p80211item_uint32_t *mibitem = @@ -82,7 +82,7 @@ static int prism2_domibset_uint32(wlandevice_t *wlandev, u32 did, u32 data) return p80211req_dorequest(wlandev, (u8 *)&msg); } -static int prism2_domibset_pstr32(wlandevice_t *wlandev, +static int prism2_domibset_pstr32(struct wlandevice *wlandev, u32 did, u8 len, const u8 *data) { struct p80211msg_dot11req_mibset msg; @@ -103,7 +103,7 @@ static int prism2_change_virtual_intf(struct wiphy *wiphy, enum nl80211_iftype type, u32 *flags, struct vif_params *params) { - wlandevice_t *wlandev = dev->ml_priv; + struct wlandevice *wlandev = dev->ml_priv; u32 data; int result; int err = 0; @@ -144,7 +144,7 @@ static int prism2_add_key(struct wiphy *wiphy, struct net_device *dev, u8 key_index, bool pairwise, const u8 *mac_addr, struct key_params *params) { - wlandevice_t *wlandev = dev->ml_priv; + struct wlandevice *wlandev = dev->ml_priv; u32 did; int err = 0; @@ -188,7 +188,7 @@ static int prism2_get_key(struct wiphy *wiphy, struct net_device *dev, const u8 *mac_addr, void *cookie, void (*callback)(void *cookie, struct key_params*)) { - wlandevice_t *wlandev = dev->ml_priv; + struct wlandevice *wlandev = dev->ml_priv; struct key_params params; int len; @@ -216,7 +216,7 @@ static int prism2_get_key(struct wiphy *wiphy, struct net_device *dev, static int prism2_del_key(struct wiphy *wiphy, struct net_device *dev, u8 key_index, bool pairwise, const u8 *mac_addr) { - wlandevice_t *wlandev = dev->ml_priv; + struct wlandevice *wlandev = dev->ml_priv; u32 did; int err = 0; int result = 0; @@ -241,7 +241,7 @@ static int prism2_del_key(struct wiphy *wiphy, struct net_device *dev, static int prism2_set_default_key(struct wiphy *wiphy, struct net_device *dev, u8 key_index, bool unicast, bool multicast) { - wlandevice_t *wlandev = dev->ml_priv; + struct wlandevice *wlandev = dev->ml_priv; int err = 0; int result = 0; @@ -259,7 +259,7 @@ static int prism2_set_default_key(struct wiphy *wiphy, struct net_device *dev, static int prism2_get_station(struct wiphy *wiphy, struct net_device *dev, const u8 *mac, struct station_info *sinfo) { - wlandevice_t *wlandev = dev->ml_priv; + struct wlandevice *wlandev = dev->ml_priv; struct p80211msg_lnxreq_commsquality quality; int result; @@ -294,7 +294,7 @@ static int prism2_scan(struct wiphy *wiphy, { struct net_device *dev; struct prism2_wiphy_private *priv = wiphy_priv(wiphy); - wlandevice_t *wlandev; + struct wlandevice *wlandev; struct p80211msg_dot11req_scan msg1; struct p80211msg_dot11req_scan_results msg2; struct cfg80211_bss *bss; @@ -411,7 +411,7 @@ exit: static int prism2_set_wiphy_params(struct wiphy *wiphy, u32 changed) { struct prism2_wiphy_private *priv = wiphy_priv(wiphy); - wlandevice_t *wlandev = priv->wlandev; + struct wlandevice *wlandev = priv->wlandev; u32 data; int result; int err = 0; @@ -453,7 +453,7 @@ exit: static int prism2_connect(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_connect_params *sme) { - wlandevice_t *wlandev = dev->ml_priv; + struct wlandevice *wlandev = dev->ml_priv; struct ieee80211_channel *channel = sme->channel; struct p80211msg_lnxreq_autojoin msg_join; u32 did; @@ -563,7 +563,7 @@ exit: static int prism2_disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_code) { - wlandevice_t *wlandev = dev->ml_priv; + struct wlandevice *wlandev = dev->ml_priv; struct p80211msg_lnxreq_autojoin msg_join; int result; int err = 0; @@ -597,7 +597,7 @@ static int prism2_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, enum nl80211_tx_power_setting type, int mbm) { struct prism2_wiphy_private *priv = wiphy_priv(wiphy); - wlandevice_t *wlandev = priv->wlandev; + struct wlandevice *wlandev = priv->wlandev; u32 data; int result; int err = 0; @@ -624,7 +624,7 @@ static int prism2_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, int *dbm) { struct prism2_wiphy_private *priv = wiphy_priv(wiphy); - wlandevice_t *wlandev = priv->wlandev; + struct wlandevice *wlandev = priv->wlandev; struct p80211msg_dot11req_mibget msg; p80211item_uint32_t *mibitem; int result; @@ -649,7 +649,7 @@ exit: } /* Interface callback functions, passing data back up to the cfg80211 layer */ -void prism2_connect_result(wlandevice_t *wlandev, u8 failed) +void prism2_connect_result(struct wlandevice *wlandev, u8 failed) { u16 status = failed ? WLAN_STATUS_UNSPECIFIED_FAILURE : WLAN_STATUS_SUCCESS; @@ -658,13 +658,13 @@ void prism2_connect_result(wlandevice_t *wlandev, u8 failed) NULL, 0, NULL, 0, status, GFP_KERNEL); } -void prism2_disconnected(wlandevice_t *wlandev) +void prism2_disconnected(struct wlandevice *wlandev) { cfg80211_disconnected(wlandev->netdev, 0, NULL, 0, false, GFP_KERNEL); } -void prism2_roamed(wlandevice_t *wlandev) +void prism2_roamed(struct wlandevice *wlandev) { cfg80211_roamed(wlandev->netdev, NULL, wlandev->bssid, NULL, 0, NULL, 0, GFP_KERNEL); @@ -689,7 +689,7 @@ static const struct cfg80211_ops prism2_usb_cfg_ops = { }; /* Functions to create/free wiphy interface */ -static struct wiphy *wlan_create_wiphy(struct device *dev, wlandevice_t *wlandev) +static struct wiphy *wlan_create_wiphy(struct device *dev, struct wlandevice *wlandev) { struct wiphy *wiphy; struct prism2_wiphy_private *priv; diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 616da07..87ceebe 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1273,7 +1273,7 @@ typedef struct hfa384x { int join_retries; /* number of join retries till we fail */ hfa384x_JoinRequest_data_t joinreq; /* join request saved data */ - wlandevice_t *wlandev; + struct wlandevice *wlandev; /* Timer to allow for the deferred processing of linkstatus messages */ struct work_struct link_bh; @@ -1410,7 +1410,7 @@ int hfa384x_drvr_txframe(hfa384x_t *hw, struct sk_buff *skb, union p80211_hdr *p80211_hdr, struct p80211_metawep *p80211_wep); -void hfa384x_tx_timeout(wlandevice_t *wlandev); +void hfa384x_tx_timeout(struct wlandevice *wlandev); int hfa384x_cmd_initialize(hfa384x_t *hw); int hfa384x_cmd_enable(hfa384x_t *hw, u16 macport); diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 3378107..9c29311 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -154,7 +154,7 @@ static void dbprint_urb(struct urb *urb); #endif static void -hfa384x_int_rxmonitor(wlandevice_t *wlandev, hfa384x_usb_rxfrm_t *rxfrm); +hfa384x_int_rxmonitor(struct wlandevice *wlandev, hfa384x_usb_rxfrm_t *rxfrm); static void hfa384x_usb_defer(struct work_struct *data); @@ -169,11 +169,11 @@ static void hfa384x_ctlxout_callback(struct urb *urb); static void hfa384x_usbin_callback(struct urb *urb); static void -hfa384x_usbin_txcompl(wlandevice_t *wlandev, hfa384x_usbin_t *usbin); +hfa384x_usbin_txcompl(struct wlandevice *wlandev, hfa384x_usbin_t *usbin); -static void hfa384x_usbin_rx(wlandevice_t *wlandev, struct sk_buff *skb); +static void hfa384x_usbin_rx(struct wlandevice *wlandev, struct sk_buff *skb); -static void hfa384x_usbin_info(wlandevice_t *wlandev, hfa384x_usbin_t *usbin); +static void hfa384x_usbin_info(struct wlandevice *wlandev, hfa384x_usbin_t *usbin); static void hfa384x_usbin_ctlx(hfa384x_t *hw, hfa384x_usbin_t *usbin, int urb_status); @@ -2656,7 +2656,7 @@ exit: return result; } -void hfa384x_tx_timeout(wlandevice_t *wlandev) +void hfa384x_tx_timeout(struct wlandevice *wlandev) { hfa384x_t *hw = wlandev->priv; unsigned long flags; @@ -2988,7 +2988,7 @@ unlock: ----------------------------------------------------------------*/ static void hfa384x_usbin_callback(struct urb *urb) { - wlandevice_t *wlandev = urb->context; + struct wlandevice *wlandev = urb->context; hfa384x_t *hw; hfa384x_usbin_t *usbin = (hfa384x_usbin_t *)urb->transfer_buffer; struct sk_buff *skb = NULL; @@ -3285,7 +3285,7 @@ unlock: * Call context: * interrupt ----------------------------------------------------------------*/ -static void hfa384x_usbin_txcompl(wlandevice_t *wlandev, +static void hfa384x_usbin_txcompl(struct wlandevice *wlandev, hfa384x_usbin_t *usbin) { u16 status; @@ -3316,7 +3316,7 @@ static void hfa384x_usbin_txcompl(wlandevice_t *wlandev, * Call context: * interrupt ----------------------------------------------------------------*/ -static void hfa384x_usbin_rx(wlandevice_t *wlandev, struct sk_buff *skb) +static void hfa384x_usbin_rx(struct wlandevice *wlandev, struct sk_buff *skb) { hfa384x_usbin_t *usbin = (hfa384x_usbin_t *)skb->data; hfa384x_t *hw = wlandev->priv; @@ -3416,7 +3416,7 @@ static void hfa384x_usbin_rx(wlandevice_t *wlandev, struct sk_buff *skb) * Call context: * interrupt ----------------------------------------------------------------*/ -static void hfa384x_int_rxmonitor(wlandevice_t *wlandev, +static void hfa384x_int_rxmonitor(struct wlandevice *wlandev, hfa384x_usb_rxfrm_t *rxfrm) { hfa384x_rx_frame_t *rxdesc = &(rxfrm->desc); @@ -3517,7 +3517,7 @@ static void hfa384x_int_rxmonitor(wlandevice_t *wlandev, * Call context: * interrupt ----------------------------------------------------------------*/ -static void hfa384x_usbin_info(wlandevice_t *wlandev, hfa384x_usbin_t *usbin) +static void hfa384x_usbin_info(struct wlandevice *wlandev, hfa384x_usbin_t *usbin) { usbin->infofrm.info.framelen = le16_to_cpu(usbin->infofrm.info.framelen); @@ -3542,7 +3542,7 @@ static void hfa384x_usbin_info(wlandevice_t *wlandev, hfa384x_usbin_t *usbin) ----------------------------------------------------------------*/ static void hfa384x_usbout_callback(struct urb *urb) { - wlandevice_t *wlandev = urb->context; + struct wlandevice *wlandev = urb->context; #ifdef DEBUG_USB dbprint_urb(urb); diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c index 6354036..efc52e9 100644 --- a/drivers/staging/wlan-ng/p80211conv.c +++ b/drivers/staging/wlan-ng/p80211conv.c @@ -104,7 +104,7 @@ static const u8 oui_8021h[] = { 0x00, 0x00, 0xf8 }; * May be called in interrupt or non-interrupt context *---------------------------------------------------------------- */ -int skb_ether_to_p80211(wlandevice_t *wlandev, u32 ethconv, +int skb_ether_to_p80211(struct wlandevice *wlandev, u32 ethconv, struct sk_buff *skb, union p80211_hdr *p80211_hdr, struct p80211_metawep *p80211_wep) { @@ -232,7 +232,7 @@ int skb_ether_to_p80211(wlandevice_t *wlandev, u32 ethconv, } /* jkriegl: from orinoco, modified */ -static void orinoco_spy_gather(wlandevice_t *wlandev, char *mac, +static void orinoco_spy_gather(struct wlandevice *wlandev, char *mac, struct p80211_rxmeta *rxmeta) { int i; @@ -274,7 +274,7 @@ static void orinoco_spy_gather(wlandevice_t *wlandev, char *mac, * May be called in interrupt or non-interrupt context *---------------------------------------------------------------- */ -int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, +int skb_p80211_to_ether(struct wlandevice *wlandev, u32 ethconv, struct sk_buff *skb) { netdevice_t *netdev = wlandev->netdev; diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c index 90cc8cd..fb97779 100644 --- a/drivers/staging/wlan-ng/p80211netdev.c +++ b/drivers/staging/wlan-ng/p80211netdev.c @@ -101,7 +101,7 @@ static int p80211knetdev_do_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd); static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr); static void p80211knetdev_tx_timeout(netdevice_t *netdev); -static int p80211_rx_typedrop(wlandevice_t *wlandev, u16 fc); +static int p80211_rx_typedrop(struct wlandevice *wlandev, u16 fc); int wlan_watchdog = 5000; module_param(wlan_watchdog, int, 0644); @@ -149,7 +149,7 @@ static int p80211knetdev_init(netdevice_t *netdev) static int p80211knetdev_open(netdevice_t *netdev) { int result = 0; /* success */ - wlandevice_t *wlandev = netdev->ml_priv; + struct wlandevice *wlandev = netdev->ml_priv; /* Check to make sure the MSD is running */ if (wlandev->msdstate != WLAN_MSD_RUNNING) @@ -184,7 +184,7 @@ static int p80211knetdev_open(netdevice_t *netdev) static int p80211knetdev_stop(netdevice_t *netdev) { int result = 0; - wlandevice_t *wlandev = netdev->ml_priv; + struct wlandevice *wlandev = netdev->ml_priv; if (wlandev->close) result = wlandev->close(wlandev); @@ -208,7 +208,7 @@ static int p80211knetdev_stop(netdevice_t *netdev) * Side effects: * ----------------------------------------------------------------*/ -void p80211netdev_rx(wlandevice_t *wlandev, struct sk_buff *skb) +void p80211netdev_rx(struct wlandevice *wlandev, struct sk_buff *skb) { /* Enqueue for post-irq processing */ skb_queue_tail(&wlandev->nsd_rxq, skb); @@ -227,7 +227,7 @@ void p80211netdev_rx(wlandevice_t *wlandev, struct sk_buff *skb) * CONV_TO_ETHER_FAILED if conversion failed * CONV_TO_ETHER_SKIPPED if frame is ignored */ -static int p80211_convert_to_ether(wlandevice_t *wlandev, struct sk_buff *skb) +static int p80211_convert_to_ether(struct wlandevice *wlandev, struct sk_buff *skb) { struct p80211_hdr_a3 *hdr; @@ -265,7 +265,7 @@ static int p80211_convert_to_ether(wlandevice_t *wlandev, struct sk_buff *skb) */ static void p80211netdev_rx_bh(unsigned long arg) { - wlandevice_t *wlandev = (wlandevice_t *) arg; + struct wlandevice *wlandev = (struct wlandevice *) arg; struct sk_buff *skb = NULL; netdevice_t *dev = wlandev->netdev; @@ -322,7 +322,7 @@ static int p80211knetdev_hard_start_xmit(struct sk_buff *skb, { int result = 0; int txresult = -1; - wlandevice_t *wlandev = netdev->ml_priv; + struct wlandevice *wlandev = netdev->ml_priv; union p80211_hdr p80211_hdr; struct p80211_metawep p80211_wep; @@ -448,7 +448,7 @@ failed: ----------------------------------------------------------------*/ static void p80211knetdev_set_multicast_list(netdevice_t *dev) { - wlandevice_t *wlandev = dev->ml_priv; + struct wlandevice *wlandev = dev->ml_priv; /* TODO: real multicast support as well */ @@ -459,7 +459,7 @@ static void p80211knetdev_set_multicast_list(netdevice_t *dev) #ifdef SIOCETHTOOL -static int p80211netdev_ethtool(wlandevice_t *wlandev, void __user *useraddr) +static int p80211netdev_ethtool(struct wlandevice *wlandev, void __user *useraddr) { u32 ethcmd; struct ethtool_drvinfo info; @@ -535,7 +535,7 @@ static int p80211knetdev_do_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd) { int result = 0; struct p80211ioctl_req *req = (struct p80211ioctl_req *) ifr; - wlandevice_t *wlandev = dev->ml_priv; + struct wlandevice *wlandev = dev->ml_priv; u8 *msgbuf; netdev_dbg(dev, "rx'd ioctl, cmd=%d, len=%d\n", cmd, req->len); @@ -633,7 +633,7 @@ static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr) dot11req.msgcode = DIDmsg_dot11req_mibset; dot11req.msglen = sizeof(struct p80211msg_dot11req_mibset); memcpy(dot11req.devname, - ((wlandevice_t *) dev->ml_priv)->name, WLAN_DEVNAMELEN_MAX - 1); + ((struct wlandevice *) dev->ml_priv)->name, WLAN_DEVNAMELEN_MAX - 1); /* Set up the mibattribute argument */ mibattr->did = DIDmsg_dot11req_mibset_mibattribute; @@ -717,7 +717,7 @@ static const struct net_device_ops p80211_netdev_ops = { * compiled drivers, this function will be called in the * context of the kernel startup code. ----------------------------------------------------------------*/ -int wlan_setup(wlandevice_t *wlandev, struct device *physdev) +int wlan_setup(struct wlandevice *wlandev, struct device *physdev) { int result = 0; netdevice_t *netdev; @@ -783,7 +783,7 @@ int wlan_setup(wlandevice_t *wlandev, struct device *physdev) * compiled drivers, this function will be called in the * context of the kernel startup code. ----------------------------------------------------------------*/ -void wlan_unsetup(wlandevice_t *wlandev) +void wlan_unsetup(struct wlandevice *wlandev) { struct wireless_dev *wdev; @@ -817,7 +817,7 @@ void wlan_unsetup(wlandevice_t *wlandev) * Call Context: * Can be either interrupt or not. ----------------------------------------------------------------*/ -int register_wlandev(wlandevice_t *wlandev) +int register_wlandev(struct wlandevice *wlandev) { return register_netdev(wlandev->netdev); } @@ -839,7 +839,7 @@ int register_wlandev(wlandevice_t *wlandev) * Call Context: * Can be either interrupt or not. ----------------------------------------------------------------*/ -int unregister_wlandev(wlandevice_t *wlandev) +int unregister_wlandev(struct wlandevice *wlandev) { struct sk_buff *skb; @@ -882,7 +882,7 @@ int unregister_wlandev(wlandevice_t *wlandev) * Call context: * Usually interrupt. ----------------------------------------------------------------*/ -void p80211netdev_hwremoved(wlandevice_t *wlandev) +void p80211netdev_hwremoved(struct wlandevice *wlandev) { wlandev->hwremoved = 1; if (wlandev->state == WLAN_DEVICE_OPEN) @@ -912,7 +912,7 @@ void p80211netdev_hwremoved(wlandevice_t *wlandev) * Call context: * interrupt ----------------------------------------------------------------*/ -static int p80211_rx_typedrop(wlandevice_t *wlandev, u16 fc) +static int p80211_rx_typedrop(struct wlandevice *wlandev, u16 fc) { u16 ftype; u16 fstype; @@ -1073,7 +1073,7 @@ static int p80211_rx_typedrop(wlandevice_t *wlandev, u16 fc) static void p80211knetdev_tx_timeout(netdevice_t *netdev) { - wlandevice_t *wlandev = netdev->ml_priv; + struct wlandevice *wlandev = netdev->ml_priv; if (wlandev->tx_timeout) { wlandev->tx_timeout(wlandev); diff --git a/drivers/staging/wlan-ng/p80211netdev.h b/drivers/staging/wlan-ng/p80211netdev.h index 820a0e2..138acdb 100644 --- a/drivers/staging/wlan-ng/p80211netdev.h +++ b/drivers/staging/wlan-ng/p80211netdev.h @@ -157,7 +157,7 @@ extern int wlan_watchdog; extern int wlan_wext_write; /* WLAN device type */ -typedef struct wlandevice { +struct wlandevice { void *priv; /* private data for MSD */ /* Subsystem State */ @@ -222,19 +222,19 @@ typedef struct wlandevice { u8 spy_number; char spy_address[IW_MAX_SPY][ETH_ALEN]; struct iw_quality spy_stat[IW_MAX_SPY]; -} wlandevice_t; +}; /* WEP stuff */ -int wep_change_key(wlandevice_t *wlandev, int keynum, u8 *key, int keylen); -int wep_decrypt(wlandevice_t *wlandev, u8 *buf, u32 len, int key_override, +int wep_change_key(struct wlandevice *wlandev, int keynum, u8 *key, int keylen); +int wep_decrypt(struct wlandevice *wlandev, u8 *buf, u32 len, int key_override, u8 *iv, u8 *icv); -int wep_encrypt(wlandevice_t *wlandev, u8 *buf, u8 *dst, u32 len, int keynum, +int wep_encrypt(struct wlandevice *wlandev, u8 *buf, u8 *dst, u32 len, int keynum, u8 *iv, u8 *icv); -int wlan_setup(wlandevice_t *wlandev, struct device *physdev); -void wlan_unsetup(wlandevice_t *wlandev); -int register_wlandev(wlandevice_t *wlandev); -int unregister_wlandev(wlandevice_t *wlandev); -void p80211netdev_rx(wlandevice_t *wlandev, struct sk_buff *skb); -void p80211netdev_hwremoved(wlandevice_t *wlandev); +int wlan_setup(struct wlandevice *wlandev, struct device *physdev); +void wlan_unsetup(struct wlandevice *wlandev); +int register_wlandev(struct wlandevice *wlandev); +int unregister_wlandev(struct wlandevice *wlandev); +void p80211netdev_rx(struct wlandevice *wlandev, struct sk_buff *skb); +void p80211netdev_hwremoved(struct wlandevice *wlandev); #endif diff --git a/drivers/staging/wlan-ng/p80211req.c b/drivers/staging/wlan-ng/p80211req.c index f755318..40627d5 100644 --- a/drivers/staging/wlan-ng/p80211req.c +++ b/drivers/staging/wlan-ng/p80211req.c @@ -72,8 +72,8 @@ #include "p80211metastruct.h" #include "p80211req.h" -static void p80211req_handlemsg(wlandevice_t *wlandev, struct p80211msg *msg); -static void p80211req_mibset_mibget(wlandevice_t *wlandev, +static void p80211req_handlemsg(struct wlandevice *wlandev, struct p80211msg *msg); +static void p80211req_mibset_mibget(struct wlandevice *wlandev, struct p80211msg_dot11req_mibget *mib_msg, int isget); @@ -108,7 +108,7 @@ static void p80211req_handle_action(struct wlandevice *wlandev, u32 *data, * Potentially blocks the caller, so it's a good idea to * not call this function from an interrupt context. ----------------------------------------------------------------*/ -int p80211req_dorequest(wlandevice_t *wlandev, u8 *msgbuf) +int p80211req_dorequest(struct wlandevice *wlandev, u8 *msgbuf) { struct p80211msg *msg = (struct p80211msg *) msgbuf; @@ -164,7 +164,7 @@ int p80211req_dorequest(wlandevice_t *wlandev, u8 *msgbuf) * Call context: * Process thread ----------------------------------------------------------------*/ -static void p80211req_handlemsg(wlandevice_t *wlandev, struct p80211msg *msg) +static void p80211req_handlemsg(struct wlandevice *wlandev, struct p80211msg *msg) { switch (msg->msgcode) { @@ -191,7 +191,7 @@ static void p80211req_handlemsg(wlandevice_t *wlandev, struct p80211msg *msg) } /* switch msg->msgcode */ } -static void p80211req_mibset_mibget(wlandevice_t *wlandev, +static void p80211req_mibset_mibget(struct wlandevice *wlandev, struct p80211msg_dot11req_mibget *mib_msg, int isget) { diff --git a/drivers/staging/wlan-ng/p80211req.h b/drivers/staging/wlan-ng/p80211req.h index a95a45a..8d3054c 100644 --- a/drivers/staging/wlan-ng/p80211req.h +++ b/drivers/staging/wlan-ng/p80211req.h @@ -48,6 +48,6 @@ #ifndef _LINUX_P80211REQ_H #define _LINUX_P80211REQ_H -int p80211req_dorequest(wlandevice_t *wlandev, u8 *msgbuf); +int p80211req_dorequest(struct wlandevice *wlandev, u8 *msgbuf); #endif diff --git a/drivers/staging/wlan-ng/p80211wep.c b/drivers/staging/wlan-ng/p80211wep.c index 22c7970..23b1837 100644 --- a/drivers/staging/wlan-ng/p80211wep.c +++ b/drivers/staging/wlan-ng/p80211wep.c @@ -119,7 +119,7 @@ static const u32 wep_crc32_table[256] = { /* keylen in bytes! */ -int wep_change_key(wlandevice_t *wlandev, int keynum, u8 *key, int keylen) +int wep_change_key(struct wlandevice *wlandev, int keynum, u8 *key, int keylen) { if (keylen < 0) return -1; @@ -143,7 +143,7 @@ int wep_change_key(wlandevice_t *wlandev, int keynum, u8 *key, int keylen) * 4-byte IV at start of buffer, 4-byte ICV at end of buffer. * if successful, buf start is payload begin, length -= 8; */ -int wep_decrypt(wlandevice_t *wlandev, u8 *buf, u32 len, int key_override, +int wep_decrypt(struct wlandevice *wlandev, u8 *buf, u32 len, int key_override, u8 *iv, u8 *icv) { u32 i, j, k, crc, keylen; @@ -217,7 +217,7 @@ int wep_decrypt(wlandevice_t *wlandev, u8 *buf, u32 len, int key_override, } /* encrypts in-place. */ -int wep_encrypt(wlandevice_t *wlandev, u8 *buf, u8 *dst, u32 len, int keynum, +int wep_encrypt(struct wlandevice *wlandev, u8 *buf, u8 *dst, u32 len, int keynum, u8 *iv, u8 *icv) { u32 i, j, k, crc, keylen; diff --git a/drivers/staging/wlan-ng/prism2fw.c b/drivers/staging/wlan-ng/prism2fw.c index 56bffd9..161637b 100644 --- a/drivers/staging/wlan-ng/prism2fw.c +++ b/drivers/staging/wlan-ng/prism2fw.c @@ -161,13 +161,13 @@ static hfa384x_caplevel_t priid; /* Local Function Declarations */ static int prism2_fwapply(const struct ihex_binrec *rfptr, -wlandevice_t *wlandev); +struct wlandevice *wlandev); static int read_fwfile(const struct ihex_binrec *rfptr); static int mkimage(struct imgchunk *clist, unsigned int *ccnt); -static int read_cardpda(struct pda *pda, wlandevice_t *wlandev); +static int read_cardpda(struct pda *pda, struct wlandevice *wlandev); static int mkpdrlist(struct pda *pda); @@ -177,7 +177,7 @@ static int plugimage(struct imgchunk *fchunk, unsigned int nfchunks, static int crcimage(struct imgchunk *fchunk, unsigned int nfchunks, struct s3crcrec *s3crc, unsigned int ns3crc); -static int writeimage(wlandevice_t *wlandev, struct imgchunk *fchunk, +static int writeimage(struct wlandevice *wlandev, struct imgchunk *fchunk, unsigned int nfchunks); static void free_chunks(struct imgchunk *fchunk, unsigned int *nfchunks); @@ -201,7 +201,7 @@ static int validate_identity(void); * 0 - success * ~0 - failure ----------------------------------------------------------------*/ -static int prism2_fwtry(struct usb_device *udev, wlandevice_t *wlandev) +static int prism2_fwtry(struct usb_device *udev, struct wlandevice *wlandev) { const struct firmware *fw_entry = NULL; @@ -239,7 +239,7 @@ static int prism2_fwtry(struct usb_device *udev, wlandevice_t *wlandev) * ~0 - failure ----------------------------------------------------------------*/ static int prism2_fwapply(const struct ihex_binrec *rfptr, - wlandevice_t *wlandev) + struct wlandevice *wlandev) { signed int result = 0; struct p80211msg_dot11req_mibget getmsg; @@ -766,7 +766,7 @@ static int plugimage(struct imgchunk *fchunk, unsigned int nfchunks, * 0 - success * ~0 - failure (probably an errno) ----------------------------------------------------------------*/ -static int read_cardpda(struct pda *pda, wlandevice_t *wlandev) +static int read_cardpda(struct pda *pda, struct wlandevice *wlandev) { int result = 0; struct p80211msg_p2req_readpda *msg; @@ -982,7 +982,7 @@ static int read_fwfile(const struct ihex_binrec *record) * 0 success * ~0 failure ----------------------------------------------------------------*/ -static int writeimage(wlandevice_t *wlandev, struct imgchunk *fchunk, +static int writeimage(struct wlandevice *wlandev, struct imgchunk *fchunk, unsigned int nfchunks) { int result = 0; diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c index d8ed9a0..73ea127 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.c +++ b/drivers/staging/wlan-ng/prism2mgmt.c @@ -113,7 +113,7 @@ * process thread (usually) * interrupt ----------------------------------------------------------------*/ -int prism2mgmt_scan(wlandevice_t *wlandev, void *msgp) +int prism2mgmt_scan(struct wlandevice *wlandev, void *msgp) { int result = 0; hfa384x_t *hw = wlandev->priv; @@ -366,7 +366,7 @@ exit: * process thread (usually) * interrupt ----------------------------------------------------------------*/ -int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp) +int prism2mgmt_scan_results(struct wlandevice *wlandev, void *msgp) { int result = 0; struct p80211msg_dot11req_scan_results *req; @@ -525,7 +525,7 @@ exit: * process thread (usually) * interrupt ----------------------------------------------------------------*/ -int prism2mgmt_start(wlandevice_t *wlandev, void *msgp) +int prism2mgmt_start(struct wlandevice *wlandev, void *msgp) { int result = 0; hfa384x_t *hw = wlandev->priv; @@ -708,7 +708,7 @@ done: * Call context: * process thread (usually) ----------------------------------------------------------------*/ -int prism2mgmt_readpda(wlandevice_t *wlandev, void *msgp) +int prism2mgmt_readpda(struct wlandevice *wlandev, void *msgp) { hfa384x_t *hw = wlandev->priv; struct p80211msg_p2req_readpda *msg = msgp; @@ -774,7 +774,7 @@ int prism2mgmt_readpda(wlandevice_t *wlandev, void *msgp) * Call context: * process thread (usually) ----------------------------------------------------------------*/ -int prism2mgmt_ramdl_state(wlandevice_t *wlandev, void *msgp) +int prism2mgmt_ramdl_state(struct wlandevice *wlandev, void *msgp) { hfa384x_t *hw = wlandev->priv; struct p80211msg_p2req_ramdl_state *msg = msgp; @@ -829,7 +829,7 @@ int prism2mgmt_ramdl_state(wlandevice_t *wlandev, void *msgp) * Call context: * process thread (usually) ----------------------------------------------------------------*/ -int prism2mgmt_ramdl_write(wlandevice_t *wlandev, void *msgp) +int prism2mgmt_ramdl_write(struct wlandevice *wlandev, void *msgp) { hfa384x_t *hw = wlandev->priv; struct p80211msg_p2req_ramdl_write *msg = msgp; @@ -890,7 +890,7 @@ int prism2mgmt_ramdl_write(wlandevice_t *wlandev, void *msgp) * Call context: * process thread (usually) ----------------------------------------------------------------*/ -int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp) +int prism2mgmt_flashdl_state(struct wlandevice *wlandev, void *msgp) { int result = 0; hfa384x_t *hw = wlandev->priv; @@ -961,7 +961,7 @@ int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp) * Call context: * process thread (usually) ----------------------------------------------------------------*/ -int prism2mgmt_flashdl_write(wlandevice_t *wlandev, void *msgp) +int prism2mgmt_flashdl_write(struct wlandevice *wlandev, void *msgp) { hfa384x_t *hw = wlandev->priv; struct p80211msg_p2req_flashdl_write *msg = msgp; @@ -1021,7 +1021,7 @@ int prism2mgmt_flashdl_write(wlandevice_t *wlandev, void *msgp) * process thread (usually) * interrupt ----------------------------------------------------------------*/ -int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp) +int prism2mgmt_autojoin(struct wlandevice *wlandev, void *msgp) { hfa384x_t *hw = wlandev->priv; int result = 0; @@ -1092,7 +1092,7 @@ int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp) * process thread (usually) * interrupt ----------------------------------------------------------------*/ -int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp) +int prism2mgmt_wlansniff(struct wlandevice *wlandev, void *msgp) { int result = 0; struct p80211msg_lnxreq_wlansniff *msg = msgp; diff --git a/drivers/staging/wlan-ng/prism2mgmt.h b/drivers/staging/wlan-ng/prism2mgmt.h index e647203..7ab19e9 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.h +++ b/drivers/staging/wlan-ng/prism2mgmt.h @@ -63,24 +63,24 @@ extern int prism2_reset_holdtime; extern int prism2_reset_settletime; -u32 prism2sta_ifstate(wlandevice_t *wlandev, u32 ifstate); +u32 prism2sta_ifstate(struct wlandevice *wlandev, u32 ifstate); -void prism2sta_ev_info(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); -void prism2sta_ev_txexc(wlandevice_t *wlandev, u16 status); -void prism2sta_ev_tx(wlandevice_t *wlandev, u16 status); -void prism2sta_ev_alloc(wlandevice_t *wlandev); +void prism2sta_ev_info(struct wlandevice *wlandev, hfa384x_InfFrame_t *inf); +void prism2sta_ev_txexc(struct wlandevice *wlandev, u16 status); +void prism2sta_ev_tx(struct wlandevice *wlandev, u16 status); +void prism2sta_ev_alloc(struct wlandevice *wlandev); -int prism2mgmt_mibset_mibget(wlandevice_t *wlandev, void *msgp); -int prism2mgmt_scan(wlandevice_t *wlandev, void *msgp); -int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp); -int prism2mgmt_start(wlandevice_t *wlandev, void *msgp); -int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp); -int prism2mgmt_readpda(wlandevice_t *wlandev, void *msgp); -int prism2mgmt_ramdl_state(wlandevice_t *wlandev, void *msgp); -int prism2mgmt_ramdl_write(wlandevice_t *wlandev, void *msgp); -int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp); -int prism2mgmt_flashdl_write(wlandevice_t *wlandev, void *msgp); -int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp); +int prism2mgmt_mibset_mibget(struct wlandevice *wlandev, void *msgp); +int prism2mgmt_scan(struct wlandevice *wlandev, void *msgp); +int prism2mgmt_scan_results(struct wlandevice *wlandev, void *msgp); +int prism2mgmt_start(struct wlandevice *wlandev, void *msgp); +int prism2mgmt_wlansniff(struct wlandevice *wlandev, void *msgp); +int prism2mgmt_readpda(struct wlandevice *wlandev, void *msgp); +int prism2mgmt_ramdl_state(struct wlandevice *wlandev, void *msgp); +int prism2mgmt_ramdl_write(struct wlandevice *wlandev, void *msgp); +int prism2mgmt_flashdl_state(struct wlandevice *wlandev, void *msgp); +int prism2mgmt_flashdl_write(struct wlandevice *wlandev, void *msgp); +int prism2mgmt_autojoin(struct wlandevice *wlandev, void *msgp); /*--------------------------------------------------------------- * conversion functions going between wlan message data types and @@ -108,8 +108,8 @@ void prism2sta_commsqual_defer(struct work_struct *data); void prism2sta_commsqual_timer(unsigned long data); /* Interface callback functions, passing data back up to the cfg80211 layer */ -void prism2_connect_result(wlandevice_t *wlandev, u8 failed); -void prism2_disconnected(wlandevice_t *wlandev); -void prism2_roamed(wlandevice_t *wlandev); +void prism2_connect_result(struct wlandevice *wlandev, u8 failed); +void prism2_disconnected(struct wlandevice *wlandev); +void prism2_roamed(struct wlandevice *wlandev); #endif diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c index 524271f..b02a3b1 100644 --- a/drivers/staging/wlan-ng/prism2mib.c +++ b/drivers/staging/wlan-ng/prism2mib.c @@ -87,61 +87,61 @@ struct mibrec { u16 parm3; int (*func)(struct mibrec *mib, int isget, - wlandevice_t *wlandev, + struct wlandevice *wlandev, hfa384x_t *hw, struct p80211msg_dot11req_mibset *msg, void *data); }; static int prism2mib_bytearea2pstr(struct mibrec *mib, int isget, - wlandevice_t *wlandev, + struct wlandevice *wlandev, hfa384x_t *hw, struct p80211msg_dot11req_mibset *msg, void *data); static int prism2mib_uint32(struct mibrec *mib, int isget, - wlandevice_t *wlandev, + struct wlandevice *wlandev, hfa384x_t *hw, struct p80211msg_dot11req_mibset *msg, void *data); static int prism2mib_flag(struct mibrec *mib, int isget, - wlandevice_t *wlandev, + struct wlandevice *wlandev, hfa384x_t *hw, struct p80211msg_dot11req_mibset *msg, void *data); static int prism2mib_wepdefaultkey(struct mibrec *mib, int isget, - wlandevice_t *wlandev, + struct wlandevice *wlandev, hfa384x_t *hw, struct p80211msg_dot11req_mibset *msg, void *data); static int prism2mib_privacyinvoked(struct mibrec *mib, int isget, - wlandevice_t *wlandev, + struct wlandevice *wlandev, hfa384x_t *hw, struct p80211msg_dot11req_mibset *msg, void *data); static int prism2mib_excludeunencrypted(struct mibrec *mib, int isget, - wlandevice_t *wlandev, + struct wlandevice *wlandev, hfa384x_t *hw, struct p80211msg_dot11req_mibset *msg, void *data); static int prism2mib_fragmentationthreshold(struct mibrec *mib, int isget, - wlandevice_t *wlandev, + struct wlandevice *wlandev, hfa384x_t *hw, struct p80211msg_dot11req_mibset *msg, void *data); static int prism2mib_priv(struct mibrec *mib, int isget, - wlandevice_t *wlandev, + struct wlandevice *wlandev, hfa384x_t *hw, struct p80211msg_dot11req_mibset *msg, void *data); @@ -257,7 +257,7 @@ static struct mibrec mibtab[] = { * interrupt */ -int prism2mgmt_mibset_mibget(wlandevice_t *wlandev, void *msgp) +int prism2mgmt_mibset_mibget(struct wlandevice *wlandev, void *msgp) { hfa384x_t *hw = wlandev->priv; int result, isget; @@ -373,7 +373,7 @@ done: static int prism2mib_bytearea2pstr(struct mibrec *mib, int isget, - wlandevice_t *wlandev, + struct wlandevice *wlandev, hfa384x_t *hw, struct p80211msg_dot11req_mibset *msg, void *data) @@ -423,7 +423,7 @@ static int prism2mib_bytearea2pstr(struct mibrec *mib, static int prism2mib_uint32(struct mibrec *mib, int isget, - wlandevice_t *wlandev, + struct wlandevice *wlandev, hfa384x_t *hw, struct p80211msg_dot11req_mibset *msg, void *data) { @@ -470,7 +470,7 @@ static int prism2mib_uint32(struct mibrec *mib, static int prism2mib_flag(struct mibrec *mib, int isget, - wlandevice_t *wlandev, + struct wlandevice *wlandev, hfa384x_t *hw, struct p80211msg_dot11req_mibset *msg, void *data) { @@ -527,7 +527,7 @@ static int prism2mib_flag(struct mibrec *mib, static int prism2mib_wepdefaultkey(struct mibrec *mib, int isget, - wlandevice_t *wlandev, + struct wlandevice *wlandev, hfa384x_t *hw, struct p80211msg_dot11req_mibset *msg, void *data) @@ -577,7 +577,7 @@ static int prism2mib_wepdefaultkey(struct mibrec *mib, static int prism2mib_privacyinvoked(struct mibrec *mib, int isget, - wlandevice_t *wlandev, + struct wlandevice *wlandev, hfa384x_t *hw, struct p80211msg_dot11req_mibset *msg, void *data) @@ -619,7 +619,7 @@ static int prism2mib_privacyinvoked(struct mibrec *mib, static int prism2mib_excludeunencrypted(struct mibrec *mib, int isget, - wlandevice_t *wlandev, + struct wlandevice *wlandev, hfa384x_t *hw, struct p80211msg_dot11req_mibset *msg, void *data) @@ -655,7 +655,7 @@ static int prism2mib_excludeunencrypted(struct mibrec *mib, static int prism2mib_fragmentationthreshold(struct mibrec *mib, int isget, - wlandevice_t *wlandev, + struct wlandevice *wlandev, hfa384x_t *hw, struct p80211msg_dot11req_mibset *msg, void *data) @@ -701,7 +701,7 @@ static int prism2mib_fragmentationthreshold(struct mibrec *mib, static int prism2mib_priv(struct mibrec *mib, int isget, - wlandevice_t *wlandev, + struct wlandevice *wlandev, hfa384x_t *hw, struct p80211msg_dot11req_mibset *msg, void *data) { diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index 64f9072..2deb263 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -81,7 +81,7 @@ #include "prism2mgmt.h" static char *dev_info = "prism2_usb"; -static wlandevice_t *create_wlan(void); +static struct wlandevice *create_wlan(void); int prism2_reset_holdtime = 30; /* Reset hold time in ms */ int prism2_reset_settletime = 100; /* Reset settle time in ms */ @@ -98,36 +98,36 @@ MODULE_PARM_DESC(prism2_reset_settletime, "reset settle time in ms"); MODULE_LICENSE("Dual MPL/GPL"); -static int prism2sta_open(wlandevice_t *wlandev); -static int prism2sta_close(wlandevice_t *wlandev); -static void prism2sta_reset(wlandevice_t *wlandev); -static int prism2sta_txframe(wlandevice_t *wlandev, struct sk_buff *skb, +static int prism2sta_open(struct wlandevice *wlandev); +static int prism2sta_close(struct wlandevice *wlandev); +static void prism2sta_reset(struct wlandevice *wlandev); +static int prism2sta_txframe(struct wlandevice *wlandev, struct sk_buff *skb, union p80211_hdr *p80211_hdr, struct p80211_metawep *p80211_wep); -static int prism2sta_mlmerequest(wlandevice_t *wlandev, struct p80211msg *msg); -static int prism2sta_getcardinfo(wlandevice_t *wlandev); -static int prism2sta_globalsetup(wlandevice_t *wlandev); -static int prism2sta_setmulticast(wlandevice_t *wlandev, netdevice_t *dev); +static int prism2sta_mlmerequest(struct wlandevice *wlandev, struct p80211msg *msg); +static int prism2sta_getcardinfo(struct wlandevice *wlandev); +static int prism2sta_globalsetup(struct wlandevice *wlandev); +static int prism2sta_setmulticast(struct wlandevice *wlandev, netdevice_t *dev); -static void prism2sta_inf_handover(wlandevice_t *wlandev, +static void prism2sta_inf_handover(struct wlandevice *wlandev, hfa384x_InfFrame_t *inf); -static void prism2sta_inf_tallies(wlandevice_t *wlandev, +static void prism2sta_inf_tallies(struct wlandevice *wlandev, hfa384x_InfFrame_t *inf); -static void prism2sta_inf_hostscanresults(wlandevice_t *wlandev, +static void prism2sta_inf_hostscanresults(struct wlandevice *wlandev, hfa384x_InfFrame_t *inf); -static void prism2sta_inf_scanresults(wlandevice_t *wlandev, +static void prism2sta_inf_scanresults(struct wlandevice *wlandev, hfa384x_InfFrame_t *inf); -static void prism2sta_inf_chinforesults(wlandevice_t *wlandev, +static void prism2sta_inf_chinforesults(struct wlandevice *wlandev, hfa384x_InfFrame_t *inf); -static void prism2sta_inf_linkstatus(wlandevice_t *wlandev, +static void prism2sta_inf_linkstatus(struct wlandevice *wlandev, hfa384x_InfFrame_t *inf); -static void prism2sta_inf_assocstatus(wlandevice_t *wlandev, +static void prism2sta_inf_assocstatus(struct wlandevice *wlandev, hfa384x_InfFrame_t *inf); -static void prism2sta_inf_authreq(wlandevice_t *wlandev, +static void prism2sta_inf_authreq(struct wlandevice *wlandev, hfa384x_InfFrame_t *inf); -static void prism2sta_inf_authreq_defer(wlandevice_t *wlandev, +static void prism2sta_inf_authreq_defer(struct wlandevice *wlandev, hfa384x_InfFrame_t *inf); -static void prism2sta_inf_psusercnt(wlandevice_t *wlandev, +static void prism2sta_inf_psusercnt(struct wlandevice *wlandev, hfa384x_InfFrame_t *inf); /* @@ -151,7 +151,7 @@ static void prism2sta_inf_psusercnt(wlandevice_t *wlandev, * Call context: * process thread */ -static int prism2sta_open(wlandevice_t *wlandev) +static int prism2sta_open(struct wlandevice *wlandev) { /* We don't currently have to do anything else. * The setup of the MAC should be subsequently completed via @@ -185,7 +185,7 @@ static int prism2sta_open(wlandevice_t *wlandev) * Call context: * process thread */ -static int prism2sta_close(wlandevice_t *wlandev) +static int prism2sta_close(struct wlandevice *wlandev) { /* We don't currently have to do anything else. * Higher layers know we're not ready from dev->start==0 and @@ -213,7 +213,7 @@ static int prism2sta_close(wlandevice_t *wlandev) * Call context: * process thread */ -static void prism2sta_reset(wlandevice_t *wlandev) +static void prism2sta_reset(struct wlandevice *wlandev) { } @@ -238,7 +238,7 @@ static void prism2sta_reset(wlandevice_t *wlandev) * Call context: * process thread */ -static int prism2sta_txframe(wlandevice_t *wlandev, struct sk_buff *skb, +static int prism2sta_txframe(struct wlandevice *wlandev, struct sk_buff *skb, union p80211_hdr *p80211_hdr, struct p80211_metawep *p80211_wep) { @@ -277,7 +277,7 @@ static int prism2sta_txframe(wlandevice_t *wlandev, struct sk_buff *skb, * Call context: * process thread */ -static int prism2sta_mlmerequest(wlandevice_t *wlandev, struct p80211msg *msg) +static int prism2sta_mlmerequest(struct wlandevice *wlandev, struct p80211msg *msg) { hfa384x_t *hw = wlandev->priv; @@ -407,7 +407,7 @@ static int prism2sta_mlmerequest(wlandevice_t *wlandev, struct p80211msg *msg) * process thread (usually) * interrupt */ -u32 prism2sta_ifstate(wlandevice_t *wlandev, u32 ifstate) +u32 prism2sta_ifstate(struct wlandevice *wlandev, u32 ifstate) { hfa384x_t *hw = wlandev->priv; u32 result; @@ -580,7 +580,7 @@ u32 prism2sta_ifstate(wlandevice_t *wlandev, u32 ifstate) * Call context: * Either. */ -static int prism2sta_getcardinfo(wlandevice_t *wlandev) +static int prism2sta_getcardinfo(struct wlandevice *wlandev) { int result = 0; hfa384x_t *hw = wlandev->priv; @@ -909,7 +909,7 @@ done: * Call context: * process thread */ -static int prism2sta_globalsetup(wlandevice_t *wlandev) +static int prism2sta_globalsetup(struct wlandevice *wlandev) { hfa384x_t *hw = wlandev->priv; @@ -918,7 +918,7 @@ static int prism2sta_globalsetup(wlandevice_t *wlandev) WLAN_DATA_MAXLEN); } -static int prism2sta_setmulticast(wlandevice_t *wlandev, netdevice_t *dev) +static int prism2sta_setmulticast(struct wlandevice *wlandev, netdevice_t *dev) { int result = 0; hfa384x_t *hw = wlandev->priv; @@ -959,7 +959,7 @@ exit: * Call context: * interrupt */ -static void prism2sta_inf_handover(wlandevice_t *wlandev, +static void prism2sta_inf_handover(struct wlandevice *wlandev, hfa384x_InfFrame_t *inf) { pr_debug("received infoframe:HANDOVER (unhandled)\n"); @@ -982,7 +982,7 @@ static void prism2sta_inf_handover(wlandevice_t *wlandev, * Call context: * interrupt */ -static void prism2sta_inf_tallies(wlandevice_t *wlandev, +static void prism2sta_inf_tallies(struct wlandevice *wlandev, hfa384x_InfFrame_t *inf) { hfa384x_t *hw = wlandev->priv; @@ -1028,7 +1028,7 @@ static void prism2sta_inf_tallies(wlandevice_t *wlandev, * Call context: * interrupt */ -static void prism2sta_inf_scanresults(wlandevice_t *wlandev, +static void prism2sta_inf_scanresults(struct wlandevice *wlandev, hfa384x_InfFrame_t *inf) { @@ -1084,7 +1084,7 @@ static void prism2sta_inf_scanresults(wlandevice_t *wlandev, * Call context: * interrupt */ -static void prism2sta_inf_hostscanresults(wlandevice_t *wlandev, +static void prism2sta_inf_hostscanresults(struct wlandevice *wlandev, hfa384x_InfFrame_t *inf) { hfa384x_t *hw = wlandev->priv; @@ -1125,7 +1125,7 @@ static void prism2sta_inf_hostscanresults(wlandevice_t *wlandev, * Call context: * interrupt */ -static void prism2sta_inf_chinforesults(wlandevice_t *wlandev, +static void prism2sta_inf_chinforesults(struct wlandevice *wlandev, hfa384x_InfFrame_t *inf) { hfa384x_t *hw = wlandev->priv; @@ -1171,7 +1171,7 @@ static void prism2sta_inf_chinforesults(wlandevice_t *wlandev, void prism2sta_processing_defer(struct work_struct *data) { hfa384x_t *hw = container_of(data, struct hfa384x, link_bh); - wlandevice_t *wlandev = hw->wlandev; + struct wlandevice *wlandev = hw->wlandev; hfa384x_bytestr32_t ssid; int result; @@ -1438,7 +1438,7 @@ void prism2sta_processing_defer(struct work_struct *data) * Call context: * interrupt */ -static void prism2sta_inf_linkstatus(wlandevice_t *wlandev, +static void prism2sta_inf_linkstatus(struct wlandevice *wlandev, hfa384x_InfFrame_t *inf) { hfa384x_t *hw = wlandev->priv; @@ -1466,7 +1466,7 @@ static void prism2sta_inf_linkstatus(wlandevice_t *wlandev, * Call context: * interrupt */ -static void prism2sta_inf_assocstatus(wlandevice_t *wlandev, +static void prism2sta_inf_assocstatus(struct wlandevice *wlandev, hfa384x_InfFrame_t *inf) { hfa384x_t *hw = wlandev->priv; @@ -1527,7 +1527,7 @@ static void prism2sta_inf_assocstatus(wlandevice_t *wlandev, * interrupt * */ -static void prism2sta_inf_authreq(wlandevice_t *wlandev, +static void prism2sta_inf_authreq(struct wlandevice *wlandev, hfa384x_InfFrame_t *inf) { hfa384x_t *hw = wlandev->priv; @@ -1542,7 +1542,7 @@ static void prism2sta_inf_authreq(wlandevice_t *wlandev, } } -static void prism2sta_inf_authreq_defer(wlandevice_t *wlandev, +static void prism2sta_inf_authreq_defer(struct wlandevice *wlandev, hfa384x_InfFrame_t *inf) { hfa384x_t *hw = wlandev->priv; @@ -1716,7 +1716,7 @@ static void prism2sta_inf_authreq_defer(wlandevice_t *wlandev, * Call context: * interrupt */ -static void prism2sta_inf_psusercnt(wlandevice_t *wlandev, +static void prism2sta_inf_psusercnt(struct wlandevice *wlandev, hfa384x_InfFrame_t *inf) { hfa384x_t *hw = wlandev->priv; @@ -1741,7 +1741,7 @@ static void prism2sta_inf_psusercnt(wlandevice_t *wlandev, * Call context: * interrupt */ -void prism2sta_ev_info(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf) +void prism2sta_ev_info(struct wlandevice *wlandev, hfa384x_InfFrame_t *inf) { inf->infotype = le16_to_cpu(inf->infotype); /* Dispatch */ @@ -1808,7 +1808,7 @@ void prism2sta_ev_info(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf) * Call context: * interrupt */ -void prism2sta_ev_txexc(wlandevice_t *wlandev, u16 status) +void prism2sta_ev_txexc(struct wlandevice *wlandev, u16 status) { pr_debug("TxExc status=0x%x.\n", status); } @@ -1829,7 +1829,7 @@ void prism2sta_ev_txexc(wlandevice_t *wlandev, u16 status) * Call context: * interrupt */ -void prism2sta_ev_tx(wlandevice_t *wlandev, u16 status) +void prism2sta_ev_tx(struct wlandevice *wlandev, u16 status) { pr_debug("Tx Complete, status=0x%04x\n", status); /* update linux network stats */ @@ -1852,7 +1852,7 @@ void prism2sta_ev_tx(wlandevice_t *wlandev, u16 status) * Call context: * interrupt */ -void prism2sta_ev_alloc(wlandevice_t *wlandev) +void prism2sta_ev_alloc(struct wlandevice *wlandev) { netif_wake_queue(wlandev->netdev); } @@ -1860,14 +1860,14 @@ void prism2sta_ev_alloc(wlandevice_t *wlandev) /* * create_wlan * -* Called at module init time. This creates the wlandevice_t structure +* Called at module init time. This creates the struct wlandevice structure * and initializes it with relevant bits. * * Arguments: * none * * Returns: -* the created wlandevice_t structure. +* the created struct wlandevice structure. * * Side effects: * also allocates the priv/hw structures. @@ -1876,13 +1876,13 @@ void prism2sta_ev_alloc(wlandevice_t *wlandev) * process thread * */ -static wlandevice_t *create_wlan(void) +static struct wlandevice *create_wlan(void) { - wlandevice_t *wlandev = NULL; + struct wlandevice *wlandev = NULL; hfa384x_t *hw = NULL; /* Alloc our structures */ - wlandev = kzalloc(sizeof(wlandevice_t), GFP_KERNEL); + wlandev = kzalloc(sizeof(struct wlandevice), GFP_KERNEL); hw = kzalloc(sizeof(hfa384x_t), GFP_KERNEL); if (!wlandev || !hw) { @@ -1914,7 +1914,7 @@ static wlandevice_t *create_wlan(void) void prism2sta_commsqual_defer(struct work_struct *data) { hfa384x_t *hw = container_of(data, struct hfa384x, commsqual_bh); - wlandevice_t *wlandev = hw->wlandev; + struct wlandevice *wlandev = hw->wlandev; hfa384x_bytestr32_t ssid; struct p80211msg_dot11req_mibget msg; p80211item_uint32_t *mibitem = (p80211item_uint32_t *) diff --git a/drivers/staging/wlan-ng/prism2usb.c b/drivers/staging/wlan-ng/prism2usb.c index 0463ec1..3561487 100644 --- a/drivers/staging/wlan-ng/prism2usb.c +++ b/drivers/staging/wlan-ng/prism2usb.c @@ -61,7 +61,7 @@ static int prism2sta_probe_usb(struct usb_interface *interface, { struct usb_device *dev; - wlandevice_t *wlandev = NULL; + struct wlandevice *wlandev = NULL; hfa384x_t *hw = NULL; int result = 0; @@ -134,9 +134,9 @@ done: static void prism2sta_disconnect_usb(struct usb_interface *interface) { - wlandevice_t *wlandev; + struct wlandevice *wlandev; - wlandev = (wlandevice_t *)usb_get_intfdata(interface); + wlandev = (struct wlandevice *)usb_get_intfdata(interface); if (wlandev) { LIST_HEAD(cleanlist); hfa384x_usbctlx_t *ctlx, *temp; @@ -219,9 +219,9 @@ static int prism2sta_suspend(struct usb_interface *interface, pm_message_t message) { hfa384x_t *hw = NULL; - wlandevice_t *wlandev; + struct wlandevice *wlandev; - wlandev = (wlandevice_t *)usb_get_intfdata(interface); + wlandev = (struct wlandevice *)usb_get_intfdata(interface); if (!wlandev) return -ENODEV; @@ -242,9 +242,9 @@ static int prism2sta_resume(struct usb_interface *interface) { int result = 0; hfa384x_t *hw = NULL; - wlandevice_t *wlandev; + struct wlandevice *wlandev; - wlandev = (wlandevice_t *)usb_get_intfdata(interface); + wlandev = (struct wlandevice *)usb_get_intfdata(interface); if (!wlandev) return -ENODEV; -- cgit v0.10.2 From 8f4166d888cb41b112ea38ceb037ba2f4f156c5b Mon Sep 17 00:00:00 2001 From: Namrata A Shettar <namrataashettar@gmail.com> Date: Sun, 18 Sep 2016 14:35:13 +0530 Subject: staging: vt6655: device_main: Replace explicit NULL comparison Replace NULL comparison to resolve checkpatch issue. - x == NULL => !x Signed-off-by: Namrata A Shettar <namrataashettar@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index ed12b5c..aea4179 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -735,7 +735,7 @@ static bool device_alloc_rx_buf(struct vnt_private *priv, struct vnt_rd_info *rd_info = rd->rd_info; rd_info->skb = dev_alloc_skb((int)priv->rx_buf_sz); - if (rd_info->skb == NULL) + if (!rd_info->skb) return false; rd_info->skb_dma = -- cgit v0.10.2 From 7cfae24953fa79c69f1bf4edbf44546648de55ba Mon Sep 17 00:00:00 2001 From: Namrata A Shettar <namrataashettar@gmail.com> Date: Sun, 18 Sep 2016 14:34:51 +0530 Subject: staging: vt6655: device_main: Replace NULL comparison with !x Replace NULL comparison to resolve checkpatch issue. - x == NULL => !x Signed-off-by: Namrata A Shettar <namrataashettar@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index aea4179..f109eea 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -477,7 +477,7 @@ static bool device_init_rings(struct vnt_private *priv) CB_MAX_BUF_SIZE, &priv->tx_bufs_dma0, GFP_ATOMIC); - if (priv->tx0_bufs == NULL) { + if (!priv->tx0_bufs) { dev_err(&priv->pcid->dev, "allocate buf dma memory failed\n"); dma_free_coherent(&priv->pcid->dev, -- cgit v0.10.2 From e0f3fc9b47e61bb5d79f2bb8684d80eee5aaac99 Mon Sep 17 00:00:00 2001 From: Ico Doornekamp <ico@pruts.nl> Date: Tue, 13 Sep 2016 21:14:14 +0200 Subject: iio: accel: sca3000_core: implemented IIO_CHAN_INFO_SAMP_FREQ Moved functionality from IIO_DEV_ATTR_SAMP_FREQ attribute into IIO_CHAN_INFO_SAMP_FREQ handlers. Added sca3000_write_raw() to allow writing the element as well. Signed-off-by: Ico Doornekamp <ico@pruts.nl> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/staging/iio/accel/sca3000.h b/drivers/staging/iio/accel/sca3000.h index 9c8a958..4dcc857 100644 --- a/drivers/staging/iio/accel/sca3000.h +++ b/drivers/staging/iio/accel/sca3000.h @@ -113,6 +113,7 @@ #define SCA3000_OUT_CTRL_BUF_X_EN 0x10 #define SCA3000_OUT_CTRL_BUF_Y_EN 0x08 #define SCA3000_OUT_CTRL_BUF_Z_EN 0x04 +#define SCA3000_OUT_CTRL_BUF_DIV_MASK 0x03 #define SCA3000_OUT_CTRL_BUF_DIV_4 0x02 #define SCA3000_OUT_CTRL_BUF_DIV_2 0x01 diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c index 61f3241..d626125 100644 --- a/drivers/staging/iio/accel/sca3000_core.c +++ b/drivers/staging/iio/accel/sca3000_core.c @@ -402,6 +402,7 @@ static const struct iio_event_spec sca3000_event = { .channel2 = mod, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\ .address = index, \ .scan_index = index, \ .scan_type = { \ @@ -443,6 +444,97 @@ static u8 sca3000_addresses[3][3] = { SCA3000_MD_CTRL_OR_Z}, }; +/** + * __sca3000_get_base_freq() obtain mode specific base frequency + * + * lock must be held + **/ +static inline int __sca3000_get_base_freq(struct sca3000_state *st, + const struct sca3000_chip_info *info, + int *base_freq) +{ + int ret; + + ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); + if (ret) + goto error_ret; + switch (0x03 & st->rx[0]) { + case SCA3000_MEAS_MODE_NORMAL: + *base_freq = info->measurement_mode_freq; + break; + case SCA3000_MEAS_MODE_OP_1: + *base_freq = info->option_mode_1_freq; + break; + case SCA3000_MEAS_MODE_OP_2: + *base_freq = info->option_mode_2_freq; + break; + } +error_ret: + return ret; +} + +/** + * read_raw handler for IIO_CHAN_INFO_SAMP_FREQ + * + * lock must be held + **/ +static int read_raw_samp_freq(struct sca3000_state *st, int *val) +{ + int ret; + + ret = __sca3000_get_base_freq(st, st->info, val); + if (ret) + return ret; + + ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL); + if (ret < 0) + return ret; + + if (*val > 0) { + ret &= SCA3000_OUT_CTRL_BUF_DIV_MASK; + switch (ret) { + case SCA3000_OUT_CTRL_BUF_DIV_2: + *val /= 2; + break; + case SCA3000_OUT_CTRL_BUF_DIV_4: + *val /= 4; + break; + } + } + + return 0; +} + +/** + * write_raw handler for IIO_CHAN_INFO_SAMP_FREQ + * + * lock must be held + **/ +static int write_raw_samp_freq(struct sca3000_state *st, int val) +{ + int ret, base_freq, ctrlval; + + ret = __sca3000_get_base_freq(st, st->info, &base_freq); + if (ret) + return ret; + + ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL); + if (ret < 0) + return ret; + + ctrlval = ret & ~SCA3000_OUT_CTRL_BUF_DIV_MASK; + + if (val == base_freq / 2) + ctrlval |= SCA3000_OUT_CTRL_BUF_DIV_2; + if (val == base_freq / 4) + ctrlval |= SCA3000_OUT_CTRL_BUF_DIV_4; + else if (val != base_freq) + return -EINVAL; + + return sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL, + ctrlval); +} + static int sca3000_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, @@ -495,11 +587,38 @@ static int sca3000_read_raw(struct iio_dev *indio_dev, *val = -214; *val2 = 600000; return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_SAMP_FREQ: + mutex_lock(&st->lock); + ret = read_raw_samp_freq(st, val); + mutex_unlock(&st->lock); + return ret ? ret : IIO_VAL_INT; default: return -EINVAL; } } +static int sca3000_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct sca3000_state *st = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + if (val2) + return -EINVAL; + mutex_lock(&st->lock); + ret = write_raw_samp_freq(st, val); + mutex_unlock(&st->lock); + return ret; + default: + return -EINVAL; + } + + return ret; +} + /** * sca3000_read_av_freq() sysfs function to get available frequencies * @@ -548,133 +667,12 @@ error_ret: return ret; } -/** - * __sca3000_get_base_freq() obtain mode specific base frequency - * - * lock must be held - **/ -static inline int __sca3000_get_base_freq(struct sca3000_state *st, - const struct sca3000_chip_info *info, - int *base_freq) -{ - int ret; - - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1); - if (ret) - goto error_ret; - switch (0x03 & st->rx[0]) { - case SCA3000_MEAS_MODE_NORMAL: - *base_freq = info->measurement_mode_freq; - break; - case SCA3000_MEAS_MODE_OP_1: - *base_freq = info->option_mode_1_freq; - break; - case SCA3000_MEAS_MODE_OP_2: - *base_freq = info->option_mode_2_freq; - break; - } -error_ret: - return ret; -} - -/** - * sca3000_read_frequency() sysfs interface to get the current frequency - **/ -static ssize_t sca3000_read_frequency(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct sca3000_state *st = iio_priv(indio_dev); - int ret, len = 0, base_freq = 0, val; - - mutex_lock(&st->lock); - ret = __sca3000_get_base_freq(st, st->info, &base_freq); - if (ret) - goto error_ret_mut; - ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL); - mutex_unlock(&st->lock); - if (ret < 0) - goto error_ret; - val = ret; - if (base_freq > 0) - switch (val & 0x03) { - case 0x00: - case 0x03: - len = sprintf(buf, "%d\n", base_freq); - break; - case 0x01: - len = sprintf(buf, "%d\n", base_freq / 2); - break; - case 0x02: - len = sprintf(buf, "%d\n", base_freq / 4); - break; - } - - return len; -error_ret_mut: - mutex_unlock(&st->lock); -error_ret: - return ret; -} - -/** - * sca3000_set_frequency() sysfs interface to set the current frequency - **/ -static ssize_t sca3000_set_frequency(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct sca3000_state *st = iio_priv(indio_dev); - int ret, base_freq = 0; - int ctrlval; - int val; - - ret = kstrtoint(buf, 10, &val); - if (ret) - return ret; - - mutex_lock(&st->lock); - /* What mode are we in? */ - ret = __sca3000_get_base_freq(st, st->info, &base_freq); - if (ret) - goto error_free_lock; - - ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL); - if (ret < 0) - goto error_free_lock; - ctrlval = ret; - /* clear the bits */ - ctrlval &= ~0x03; - - if (val == base_freq / 2) { - ctrlval |= SCA3000_OUT_CTRL_BUF_DIV_2; - } else if (val == base_freq / 4) { - ctrlval |= SCA3000_OUT_CTRL_BUF_DIV_4; - } else if (val != base_freq) { - ret = -EINVAL; - goto error_free_lock; - } - ret = sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL, - ctrlval); -error_free_lock: - mutex_unlock(&st->lock); - - return ret ? ret : len; -} - /* * Should only really be registered if ring buffer support is compiled in. * Does no harm however and doing it right would add a fair bit of complexity */ static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(sca3000_read_av_freq); -static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, - sca3000_read_frequency, - sca3000_set_frequency); - /** * sca3000_read_thresh() - query of a threshold **/ @@ -751,7 +749,6 @@ static struct attribute *sca3000_attributes[] = { &iio_dev_attr_measurement_mode_available.dev_attr.attr, &iio_dev_attr_measurement_mode.dev_attr.attr, &iio_dev_attr_sampling_frequency_available.dev_attr.attr, - &iio_dev_attr_sampling_frequency.dev_attr.attr, NULL, }; @@ -1086,6 +1083,7 @@ error_ret: static const struct iio_info sca3000_info = { .attrs = &sca3000_attribute_group, .read_raw = &sca3000_read_raw, + .write_raw = &sca3000_write_raw, .event_attrs = &sca3000_event_attribute_group, .read_event_value = &sca3000_read_thresh, .write_event_value = &sca3000_write_thresh, -- cgit v0.10.2 From 7504dfc9e935e3422d5187f8e813da5758976e6d Mon Sep 17 00:00:00 2001 From: Julia Lawall <Julia.Lawall@lip6.fr> Date: Fri, 16 Sep 2016 12:55:24 +0200 Subject: iio: common: ssp_sensors: accel: constify iio_info structures Check for iio_info structures that are only stored in the info field of a iio_dev structure. This field is declared const, so iio_info structures that have this property can be declared as const also. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // <smpl> @r disable optional_qualifier@ identifier i; position p; @@ static struct iio_info i@p = { ... }; @ok@ identifier r.i; struct iio_dev e; position p; @@ e.info = &i@p; @bad@ position p != {r.p,ok.p}; identifier r.i; struct iio_info e; @@ e@i@p @depends on !bad disable optional_qualifier@ identifier r.i; @@ static +const struct iio_info i = { ... }; // </smpl> The result of size on this file before the change is: text data bss dec hex filename 1265 344 0 1609 649 drivers/iio/accel/ssp_accel_sensor.o and after the change it is: text data bss dec hex filename 1425 192 0 1617 651 drivers/iio/accel/ssp_accel_sensor.o Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/accel/ssp_accel_sensor.c b/drivers/iio/accel/ssp_accel_sensor.c index 4ae05fc..31db009 100644 --- a/drivers/iio/accel/ssp_accel_sensor.c +++ b/drivers/iio/accel/ssp_accel_sensor.c @@ -74,7 +74,7 @@ static int ssp_accel_write_raw(struct iio_dev *indio_dev, return -EINVAL; } -static struct iio_info ssp_accel_iio_info = { +static const struct iio_info ssp_accel_iio_info = { .read_raw = &ssp_accel_read_raw, .write_raw = &ssp_accel_write_raw, }; -- cgit v0.10.2 From 52ceb7731e7c23101a26e91aad81ae30de87b10d Mon Sep 17 00:00:00 2001 From: Julia Lawall <Julia.Lawall@lip6.fr> Date: Fri, 16 Sep 2016 12:55:25 +0200 Subject: iio: adc: men_z188_adc: constify iio_info structures Check for iio_info structures that are only stored in the info field of a iio_dev structure. This field is declared const, so iio_info structures that have this property can be declared as const also. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // <smpl> @r disable optional_qualifier@ identifier i; position p; @@ static struct iio_info i@p = { ... }; @ok@ identifier r.i; struct iio_dev e; position p; @@ e.info = &i@p; @bad@ position p != {r.p,ok.p}; identifier r.i; struct iio_info e; @@ e@i@p @depends on !bad disable optional_qualifier@ identifier r.i; @@ static +const struct iio_info i = { ... }; // </smpl> The result of size on this file before the change is: text data bss dec hex filename 1529 312 0 1841 731 drivers/iio/adc/men_z188_adc.o and after the change it is: text data bss dec hex filename 1689 168 0 1857 741 drivers/iio/adc/men_z188_adc.o Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/adc/men_z188_adc.c b/drivers/iio/adc/men_z188_adc.c index d095efe..8f3606d 100644 --- a/drivers/iio/adc/men_z188_adc.c +++ b/drivers/iio/adc/men_z188_adc.c @@ -78,7 +78,7 @@ static int z188_iio_read_raw(struct iio_dev *iio_dev, return ret; } -static struct iio_info z188_adc_info = { +static const struct iio_info z188_adc_info = { .read_raw = &z188_iio_read_raw, .driver_module = THIS_MODULE, }; -- cgit v0.10.2 From becf05e748b3842b792373d812e41c5a407aef5f Mon Sep 17 00:00:00 2001 From: Julia Lawall <Julia.Lawall@lip6.fr> Date: Fri, 16 Sep 2016 12:55:26 +0200 Subject: iio: common: ssp_sensors: gyro: constify iio_info structures Check for iio_info structures that are only stored in the info field of a iio_dev structure. This field is declared const, so iio_info structures that have this property can be declared as const also. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // <smpl> @r disable optional_qualifier@ identifier i; position p; @@ static struct iio_info i@p = { ... }; @ok@ identifier r.i; struct iio_dev e; position p; @@ e.info = &i@p; @bad@ position p != {r.p,ok.p}; identifier r.i; struct iio_info e; @@ e@i@p @depends on !bad disable optional_qualifier@ identifier r.i; @@ static +const struct iio_info i = { ... }; // </smpl> The result of size on this file before the change is: text data bss dec hex filename 1245 344 0 1589 635 drivers/iio/gyro/ssp_gyro_sensor.o and after the change it is: text data bss dec hex filename 1397 192 0 1589 635 drivers/iio/gyro/ssp_gyro_sensor.o Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/gyro/ssp_gyro_sensor.c b/drivers/iio/gyro/ssp_gyro_sensor.c index 0a8afdd..1f25f40 100644 --- a/drivers/iio/gyro/ssp_gyro_sensor.c +++ b/drivers/iio/gyro/ssp_gyro_sensor.c @@ -74,7 +74,7 @@ static int ssp_gyro_write_raw(struct iio_dev *indio_dev, return -EINVAL; } -static struct iio_info ssp_gyro_iio_info = { +static const struct iio_info ssp_gyro_iio_info = { .read_raw = &ssp_gyro_read_raw, .write_raw = &ssp_gyro_write_raw, }; -- cgit v0.10.2 From b125a1b2b9d4692a0f17435101cf3cdaae1d5b25 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Date: Sun, 18 Sep 2016 13:09:50 +0200 Subject: Revert "staging: olpc_dcon: Replace a bit shift by a use of BIT." This reverts commit ed88363e6aebb91df820e1a8898d2a07b18d2bc9. It was incorrect :( Cc: Anchal Jain <anchalj109@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/olpc_dcon/olpc_dcon.h b/drivers/staging/olpc_dcon/olpc_dcon.h index 23a48a1..215e7ec 100644 --- a/drivers/staging/olpc_dcon/olpc_dcon.h +++ b/drivers/staging/olpc_dcon/olpc_dcon.h @@ -9,18 +9,18 @@ #define DCON_REG_ID 0 #define DCON_REG_MODE 1 -#define MODE_PASSTHRU bit(0) -#define MODE_SLEEP bit(1) -#define MODE_SLEEP_AUTO bit(2) -#define MODE_BL_ENABLE bit(3) -#define MODE_BLANK bit(4) -#define MODE_CSWIZZLE bit(5) -#define MODE_COL_AA bit(6) -#define MODE_MONO_LUMA bit(7) -#define MODE_SCAN_INT bit(8) -#define MODE_CLOCKDIV bit(9) -#define MODE_DEBUG bit(14) -#define MODE_SELFTEST bit(15) +#define MODE_PASSTHRU (1<<0) +#define MODE_SLEEP (1<<1) +#define MODE_SLEEP_AUTO (1<<2) +#define MODE_BL_ENABLE (1<<3) +#define MODE_BLANK (1<<4) +#define MODE_CSWIZZLE (1<<5) +#define MODE_COL_AA (1<<6) +#define MODE_MONO_LUMA (1<<7) +#define MODE_SCAN_INT (1<<8) +#define MODE_CLOCKDIV (1<<9) +#define MODE_DEBUG (1<<14) +#define MODE_SELFTEST (1<<15) #define DCON_REG_HRES 0x2 #define DCON_REG_HTOTAL 0x3 @@ -35,11 +35,11 @@ #define DCON_REG_MEM_OPT_B 0x42 /* Load Delay Locked Loop (DLL) settings for clock delay */ -#define MEM_DLL_CLOCK_DELAY bit(0) +#define MEM_DLL_CLOCK_DELAY (1<<0) /* Memory controller power down function */ -#define MEM_POWER_DOWN bit(8) +#define MEM_POWER_DOWN (1<<8) /* Memory controller software reset */ -#define MEM_SOFT_RESET bit(0) +#define MEM_SOFT_RESET (1<<0) /* Status values */ -- cgit v0.10.2 From a8886770dcf27082fe0fa64592e0054d02cea90d Mon Sep 17 00:00:00 2001 From: Katie Dunne <kdunne@mail.ccsf.edu> Date: Wed, 14 Sep 2016 10:18:28 -0700 Subject: staging: iio: ad5933: align arguments on new line with open parenthesis Issue found by checkpatch: "Alignment should match open parenthesis." Multiple lines are also reduced to a single line where possible. Signed-off-by: Katie Dunne <kdunne@mail.ccsf.edu> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index 24c348d..5eecf1c 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -156,8 +156,7 @@ static const struct iio_chan_spec ad5933_channels[] = { }, }; -static int ad5933_i2c_write(struct i2c_client *client, - u8 reg, u8 len, u8 *data) +static int ad5933_i2c_write(struct i2c_client *client, u8 reg, u8 len, u8 *data) { int ret; @@ -171,8 +170,7 @@ static int ad5933_i2c_write(struct i2c_client *client, return 0; } -static int ad5933_i2c_read(struct i2c_client *client, - u8 reg, u8 len, u8 *data) +static int ad5933_i2c_read(struct i2c_client *client, u8 reg, u8 len, u8 *data) { int ret; @@ -269,7 +267,8 @@ static int ad5933_setup(struct ad5933_state *st) dat = cpu_to_be16(st->settling_cycles); ret = ad5933_i2c_write(st->client, - AD5933_REG_SETTLING_CYCLES, 2, (u8 *)&dat); + AD5933_REG_SETTLING_CYCLES, + 2, (u8 *)&dat); if (ret < 0) return ret; @@ -294,8 +293,8 @@ static void ad5933_calc_out_ranges(struct ad5933_state *st) */ static ssize_t ad5933_show_frequency(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 ad5933_state *st = iio_priv(indio_dev); @@ -322,9 +321,9 @@ static ssize_t ad5933_show_frequency(struct device *dev, } static ssize_t ad5933_store_frequency(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) + struct device_attribute *attr, + const char *buf, + size_t len) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad5933_state *st = iio_priv(indio_dev); @@ -357,8 +356,8 @@ static IIO_DEVICE_ATTR(out_voltage0_freq_increment, S_IRUGO | S_IWUSR, AD5933_REG_FREQ_INC); static ssize_t ad5933_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 ad5933_state *st = iio_priv(indio_dev); @@ -399,9 +398,9 @@ static ssize_t ad5933_show(struct device *dev, } static ssize_t ad5933_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) + struct device_attribute *attr, + const char *buf, + size_t len) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad5933_state *st = iio_priv(indio_dev); @@ -451,7 +450,8 @@ static ssize_t ad5933_store(struct device *dev, dat = cpu_to_be16(val); ret = ad5933_i2c_write(st->client, - AD5933_REG_SETTLING_CYCLES, 2, (u8 *)&dat); + AD5933_REG_SETTLING_CYCLES, + 2, (u8 *)&dat); break; case AD5933_FREQ_POINTS: val = clamp(val, (u16)0, (u16)511); @@ -545,8 +545,8 @@ static int ad5933_read_raw(struct iio_dev *indio_dev, goto out; ret = ad5933_i2c_read(st->client, - AD5933_REG_TEMP_DATA, 2, - (u8 *)&dat); + AD5933_REG_TEMP_DATA, + 2, (u8 *)&dat); if (ret < 0) goto out; mutex_unlock(&indio_dev->mlock); @@ -705,7 +705,7 @@ static void ad5933_work(struct work_struct *work) } static int ad5933_probe(struct i2c_client *client, - const struct i2c_device_id *id) + const struct i2c_device_id *id) { int ret, voltage_uv = 0; struct ad5933_platform_data *pdata = dev_get_platdata(&client->dev); -- cgit v0.10.2 From 5620318828dce80748c0a8e5fa2775957cf28347 Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Sun, 11 Sep 2016 18:29:26 +0200 Subject: iio: accel: mma7660: fix missing MODULE_DEVICE_TABLE(i2c) Add missing MODULE_DEVICE_TABLE(i2c) this fixes autoloading on devicetree using systems. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/accel/mma7660.c b/drivers/iio/accel/mma7660.c index 0acdee5..03beadf 100644 --- a/drivers/iio/accel/mma7660.c +++ b/drivers/iio/accel/mma7660.c @@ -251,6 +251,7 @@ static const struct i2c_device_id mma7660_i2c_id[] = { {"mma7660", 0}, {} }; +MODULE_DEVICE_TABLE(i2c, mma7660_i2c_id); static const struct acpi_device_id mma7660_acpi_id[] = { {"MMA7660", 0}, -- cgit v0.10.2 From 063e3303a93fcd64554730145361f102236724cb Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Mon, 12 Sep 2016 09:43:50 +0200 Subject: iio: accel: Add driver for the mCube MC3230 3-axis accelerometer Add an IIO driver for the mCube MC3230 3-axis accelerometer. A datasheet for the mCube MC3230 can be found here: http://www.mcubemems.com/wp-content/uploads/2014/10/MC3230_2-Datasheet-APS-048-0007v1.6.pdf Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt index 310b1bb..1416c6a 100644 --- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt +++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt @@ -57,6 +57,7 @@ maxim,ds1050 5 Bit Programmable, Pulse-Width Modulator maxim,max1237 Low-Power, 4-/12-Channel, 2-Wire Serial, 12-Bit ADCs maxim,max6625 9-Bit/12-Bit Temperature Sensors with I²C-Compatible Serial Interface mc,rv3029c2 Real Time Clock Module with I2C-Bus +mcube,mc3230 mCube 3-axis 8-bit digital accelerometer microchip,mcp4531-502 Microchip 7-bit Single I2C Digital Potentiometer (5k) microchip,mcp4531-103 Microchip 7-bit Single I2C Digital Potentiometer (10k) microchip,mcp4531-503 Microchip 7-bit Single I2C Digital Potentiometer (50k) diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index a8e9ed4..2b791fe 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -161,6 +161,16 @@ config KXCJK1013 To compile this driver as a module, choose M here: the module will be called kxcjk-1013. +config MC3230 + tristate "mCube MC3230 Digital Accelerometer Driver" + depends on I2C + help + Say yes here to build support for the mCube MC3230 low-g tri-axial + digital accelerometer. + + To compile this driver as a module, choose M here: the + module will be called mc3230. + config MMA7455 tristate select IIO_BUFFER diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile index b5c2a0b..f5d3dde 100644 --- a/drivers/iio/accel/Makefile +++ b/drivers/iio/accel/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o obj-$(CONFIG_KXSD9) += kxsd9.o obj-$(CONFIG_KXSD9_SPI) += kxsd9-spi.o obj-$(CONFIG_KXSD9_I2C) += kxsd9-i2c.o +obj-$(CONFIG_MC3230) += mc3230.o obj-$(CONFIG_MMA7455) += mma7455_core.o obj-$(CONFIG_MMA7455_I2C) += mma7455_i2c.o diff --git a/drivers/iio/accel/mc3230.c b/drivers/iio/accel/mc3230.c new file mode 100644 index 0000000..4ea2ff6 --- /dev/null +++ b/drivers/iio/accel/mc3230.c @@ -0,0 +1,211 @@ +/** + * mCube MC3230 3-Axis Accelerometer + * + * Copyright (c) 2016 Hans de Goede <hdegoede@redhat.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * IIO driver for mCube MC3230; 7-bit I2C address: 0x4c. + */ + +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> + +#define MC3230_REG_XOUT 0x00 +#define MC3230_REG_YOUT 0x01 +#define MC3230_REG_ZOUT 0x02 + +#define MC3230_REG_MODE 0x07 +#define MC3230_MODE_OPCON_MASK 0x03 +#define MC3230_MODE_OPCON_WAKE 0x01 +#define MC3230_MODE_OPCON_STANDBY 0x03 + +#define MC3230_REG_CHIP_ID 0x18 +#define MC3230_CHIP_ID 0x01 + +#define MC3230_REG_PRODUCT_CODE 0x3b +#define MC3230_PRODUCT_CODE 0x19 + +/* + * The accelerometer has one measurement range: + * + * -1.5g - +1.5g (8-bit, signed) + * + * scale = (1.5 + 1.5) * 9.81 / (2^8 - 1) = 0.115411765 + */ + +static const int mc3230_nscale = 115411765; + +#define MC3230_CHANNEL(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), \ +} + +static const struct iio_chan_spec mc3230_channels[] = { + MC3230_CHANNEL(MC3230_REG_XOUT, X), + MC3230_CHANNEL(MC3230_REG_YOUT, Y), + MC3230_CHANNEL(MC3230_REG_ZOUT, Z), +}; + +struct mc3230_data { + struct i2c_client *client; +}; + +static int mc3230_set_opcon(struct mc3230_data *data, int opcon) +{ + int ret; + struct i2c_client *client = data->client; + + ret = i2c_smbus_read_byte_data(client, MC3230_REG_MODE); + if (ret < 0) { + dev_err(&client->dev, "failed to read mode reg: %d\n", ret); + return ret; + } + + ret &= ~MC3230_MODE_OPCON_MASK; + ret |= opcon; + + ret = i2c_smbus_write_byte_data(client, MC3230_REG_MODE, ret); + if (ret < 0) { + dev_err(&client->dev, "failed to write mode reg: %d\n", ret); + return ret; + } + + return 0; +} + +static int mc3230_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct mc3230_data *data = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = i2c_smbus_read_byte_data(data->client, chan->address); + if (ret < 0) + return ret; + *val = sign_extend32(ret, 7); + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 0; + *val2 = mc3230_nscale; + return IIO_VAL_INT_PLUS_NANO; + default: + return -EINVAL; + } +} + +static const struct iio_info mc3230_info = { + .driver_module = THIS_MODULE, + .read_raw = mc3230_read_raw, +}; + +static int mc3230_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret; + struct iio_dev *indio_dev; + struct mc3230_data *data; + + /* First check chip-id and product-id */ + ret = i2c_smbus_read_byte_data(client, MC3230_REG_CHIP_ID); + if (ret != MC3230_CHIP_ID) + return (ret < 0) ? ret : -ENODEV; + + ret = i2c_smbus_read_byte_data(client, MC3230_REG_PRODUCT_CODE); + if (ret != MC3230_PRODUCT_CODE) + return (ret < 0) ? ret : -ENODEV; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) { + dev_err(&client->dev, "iio allocation failed!\n"); + return -ENOMEM; + } + + data = iio_priv(indio_dev); + data->client = client; + i2c_set_clientdata(client, indio_dev); + + indio_dev->dev.parent = &client->dev; + indio_dev->info = &mc3230_info; + indio_dev->name = "mc3230"; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = mc3230_channels; + indio_dev->num_channels = ARRAY_SIZE(mc3230_channels); + + ret = mc3230_set_opcon(data, MC3230_MODE_OPCON_WAKE); + if (ret < 0) + return ret; + + ret = iio_device_register(indio_dev); + if (ret < 0) { + dev_err(&client->dev, "device_register failed\n"); + mc3230_set_opcon(data, MC3230_MODE_OPCON_STANDBY); + } + + return ret; +} + +static int mc3230_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + + iio_device_unregister(indio_dev); + + return mc3230_set_opcon(iio_priv(indio_dev), MC3230_MODE_OPCON_STANDBY); +} + +#ifdef CONFIG_PM_SLEEP +static int mc3230_suspend(struct device *dev) +{ + struct mc3230_data *data; + + data = iio_priv(i2c_get_clientdata(to_i2c_client(dev))); + + return mc3230_set_opcon(data, MC3230_MODE_OPCON_STANDBY); +} + +static int mc3230_resume(struct device *dev) +{ + struct mc3230_data *data; + + data = iio_priv(i2c_get_clientdata(to_i2c_client(dev))); + + return mc3230_set_opcon(data, MC3230_MODE_OPCON_WAKE); +} +#endif + +static SIMPLE_DEV_PM_OPS(mc3230_pm_ops, mc3230_suspend, mc3230_resume); + +static const struct i2c_device_id mc3230_i2c_id[] = { + {"mc3230", 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, mc3230_i2c_id); + +static struct i2c_driver mc3230_driver = { + .driver = { + .name = "mc3230", + .pm = &mc3230_pm_ops, + }, + .probe = mc3230_probe, + .remove = mc3230_remove, + .id_table = mc3230_i2c_id, +}; + +module_i2c_driver(mc3230_driver); + +MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); +MODULE_DESCRIPTION("mCube MC3230 3-Axis Accelerometer driver"); +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 03b262f2bbf43b82eaef82ffb3bc671d5b5c8da1 Mon Sep 17 00:00:00 2001 From: Gregor Boirie <gregor.boirie@parrot.com> Date: Tue, 13 Sep 2016 14:23:14 +0200 Subject: iio:pressure: initial zpa2326 barometer support Introduce driver for Murata ZPA2326 pressure and temperature sensor: http://www.murata.com/en-us/products/productdetail?partno=ZPA2326-0311A-R Signed-off-by: Gregor Boirie <gregor.boirie@parrot.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/Documentation/devicetree/bindings/iio/pressure/zpa2326.txt b/Documentation/devicetree/bindings/iio/pressure/zpa2326.txt new file mode 100644 index 0000000..fb85de6 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/pressure/zpa2326.txt @@ -0,0 +1,31 @@ +Murata ZPA2326 pressure sensor + +Pressure sensor from Murata with SPI and I2C bus interfaces. + +Required properties: +- compatible: "murata,zpa2326" +- reg: the I2C address or SPI chip select the device will respond to + +Recommended properties for SPI bus usage: +- spi-max-frequency: maximum SPI bus frequency as documented in + Documentation/devicetree/bindings/spi/spi-bus.txt + +Optional properties: +- vref-supply: an optional regulator that needs to be on to provide VREF + power to the sensor +- vdd-supply: an optional regulator that needs to be on to provide VDD + power to the sensor +- interrupt-parent: phandle to the parent interrupt controller as documented in + Documentation/devicetree/bindings/interrupt-controller/interrupts.txt +- interrupts: interrupt mapping for IRQ as documented in + Documentation/devicetree/bindings/interrupt-controller/interrupts.txt + +Example: + +zpa2326@5c { + compatible = "murata,zpa2326"; + reg = <0x5c>; + interrupt-parent = <&gpio>; + interrupts = <12>; + vdd-supply = <&ldo_1v8_gnss>; +}; diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig index d130cdc..cc090d8 100644 --- a/drivers/iio/pressure/Kconfig +++ b/drivers/iio/pressure/Kconfig @@ -187,4 +187,26 @@ config HP206C This driver can also be built as a module. If so, the module will be called hp206c. +config ZPA2326 + tristate "Murata ZPA2326 pressure sensor driver" + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + select REGMAP + select ZPA2326_I2C if I2C + select ZPA2326_SPI if SPI_MASTER + help + Say Y here to build support for the Murata ZPA2326 pressure and + temperature sensor. + + To compile this driver as a module, choose M here: the module will + be called zpa2326. + +config ZPA2326_I2C + tristate + select REGMAP_I2C + +config ZPA2326_SPI + tristate + select REGMAP_SPI + endmenu diff --git a/drivers/iio/pressure/Makefile b/drivers/iio/pressure/Makefile index 7f395be..fff7718 100644 --- a/drivers/iio/pressure/Makefile +++ b/drivers/iio/pressure/Makefile @@ -22,6 +22,9 @@ st_pressure-y := st_pressure_core.o st_pressure-$(CONFIG_IIO_BUFFER) += st_pressure_buffer.o obj-$(CONFIG_T5403) += t5403.o obj-$(CONFIG_HP206C) += hp206c.o +obj-$(CONFIG_ZPA2326) += zpa2326.o +obj-$(CONFIG_ZPA2326_I2C) += zpa2326_i2c.o +obj-$(CONFIG_ZPA2326_SPI) += zpa2326_spi.o obj-$(CONFIG_IIO_ST_PRESS_I2C) += st_pressure_i2c.o obj-$(CONFIG_IIO_ST_PRESS_SPI) += st_pressure_spi.o diff --git a/drivers/iio/pressure/zpa2326.c b/drivers/iio/pressure/zpa2326.c new file mode 100644 index 0000000..19d2eb4 --- /dev/null +++ b/drivers/iio/pressure/zpa2326.c @@ -0,0 +1,1735 @@ +/* + * Murata ZPA2326 pressure and temperature sensor IIO driver + * + * Copyright (c) 2016 Parrot S.A. + * + * Author: Gregor Boirie <gregor.boirie@parrot.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +/** + * DOC: ZPA2326 theory of operations + * + * This driver supports %INDIO_DIRECT_MODE and %INDIO_BUFFER_TRIGGERED IIO + * modes. + * A internal hardware trigger is also implemented to dispatch registered IIO + * trigger consumers upon "sample ready" interrupts. + * + * ZPA2326 hardware supports 2 sampling mode: one shot and continuous. + * + * A complete one shot sampling cycle gets device out of low power mode, + * performs pressure and temperature measurements, then automatically switches + * back to low power mode. It is meant for on demand sampling with optimal power + * saving at the cost of lower sampling rate and higher software overhead. + * This is a natural candidate for IIO read_raw hook implementation + * (%INDIO_DIRECT_MODE). It is also used for triggered buffering support to + * ensure explicit synchronization with external trigger events + * (%INDIO_BUFFER_TRIGGERED). + * + * The continuous mode works according to a periodic hardware measurement + * process continuously pushing samples into an internal hardware FIFO (for + * pressure samples only). Measurement cycle completion may be signaled by a + * "sample ready" interrupt. + * Typical software sequence of operations : + * - get device out of low power mode, + * - setup hardware sampling period, + * - at end of period, upon data ready interrupt: pop pressure samples out of + * hardware FIFO and fetch temperature sample + * - when no longer needed, stop sampling process by putting device into + * low power mode. + * This mode is used to implement %INDIO_BUFFER_TRIGGERED mode if device tree + * declares a valid interrupt line. In this case, the internal hardware trigger + * drives acquisition. + * + * Note that hardware sampling frequency is taken into account only when + * internal hardware trigger is attached as the highest sampling rate seems to + * be the most energy efficient. + * + * TODO: + * preset pressure threshold crossing / IIO events ; + * differential pressure sampling ; + * hardware samples averaging. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/regulator/consumer.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/buffer.h> +#include <linux/iio/trigger.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/iio/triggered_buffer.h> +#include "zpa2326.h" + +/* 200 ms should be enough for the longest conversion time in one-shot mode. */ +#define ZPA2326_CONVERSION_JIFFIES (HZ / 5) + +/* There should be a 1 ms delay (Tpup) after getting out of reset. */ +#define ZPA2326_TPUP_USEC_MIN (1000) +#define ZPA2326_TPUP_USEC_MAX (2000) + +/** + * struct zpa2326_frequency - Hardware sampling frequency descriptor + * @hz : Frequency in Hertz. + * @odr: Output Data Rate word as expected by %ZPA2326_CTRL_REG3_REG. + */ +struct zpa2326_frequency { + int hz; + u16 odr; +}; + +/* + * Keep these in strict ascending order: last array entry is expected to + * correspond to the highest sampling frequency. + */ +static const struct zpa2326_frequency zpa2326_sampling_frequencies[] = { + { .hz = 1, .odr = 1 << ZPA2326_CTRL_REG3_ODR_SHIFT }, + { .hz = 5, .odr = 5 << ZPA2326_CTRL_REG3_ODR_SHIFT }, + { .hz = 11, .odr = 6 << ZPA2326_CTRL_REG3_ODR_SHIFT }, + { .hz = 23, .odr = 7 << ZPA2326_CTRL_REG3_ODR_SHIFT }, +}; + +/* Return the highest hardware sampling frequency available. */ +static const struct zpa2326_frequency *zpa2326_highest_frequency(void) +{ + return &zpa2326_sampling_frequencies[ + ARRAY_SIZE(zpa2326_sampling_frequencies) - 1]; +} + +/** + * struct zpa_private - Per-device internal private state + * @timestamp: Buffered samples ready datum. + * @regmap: Underlying I2C / SPI bus adapter used to abstract slave register + * accesses. + * @result: Allows sampling logic to get completion status of operations + * that interrupt handlers perform asynchronously. + * @data_ready: Interrupt handler uses this to wake user context up at sampling + * operation completion. + * @trigger: Optional hardware / interrupt driven trigger used to notify + * external devices a new sample is ready. + * @waken: Flag indicating whether or not device has just been powered on. + * @irq: Optional interrupt line: negative or zero if not declared into + * DT, in which case sampling logic keeps polling status register + * to detect completion. + * @frequency: Current hardware sampling frequency. + * @vref: Power / voltage reference. + * @vdd: Power supply. + */ +struct zpa2326_private { + s64 timestamp; + struct regmap *regmap; + int result; + struct completion data_ready; + struct iio_trigger *trigger; + bool waken; + int irq; + const struct zpa2326_frequency *frequency; + struct regulator *vref; + struct regulator *vdd; +}; + +#define zpa2326_err(_idev, _format, _arg...) \ + dev_err(_idev->dev.parent, _format, ##_arg) + +#define zpa2326_warn(_idev, _format, _arg...) \ + dev_warn(_idev->dev.parent, _format, ##_arg) + +#ifdef DEBUG +#define zpa2326_dbg(_idev, _format, _arg...) \ + dev_dbg(_idev->dev.parent, _format, ##_arg) +#else +#define zpa2326_dbg(_idev, _format, _arg...) +#endif + +bool zpa2326_isreg_writeable(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ZPA2326_REF_P_XL_REG: + case ZPA2326_REF_P_L_REG: + case ZPA2326_REF_P_H_REG: + case ZPA2326_RES_CONF_REG: + case ZPA2326_CTRL_REG0_REG: + case ZPA2326_CTRL_REG1_REG: + case ZPA2326_CTRL_REG2_REG: + case ZPA2326_CTRL_REG3_REG: + case ZPA2326_THS_P_LOW_REG: + case ZPA2326_THS_P_HIGH_REG: + return true; + + default: + return false; + } +} +EXPORT_SYMBOL_GPL(zpa2326_isreg_writeable); + +bool zpa2326_isreg_readable(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ZPA2326_REF_P_XL_REG: + case ZPA2326_REF_P_L_REG: + case ZPA2326_REF_P_H_REG: + case ZPA2326_DEVICE_ID_REG: + case ZPA2326_RES_CONF_REG: + case ZPA2326_CTRL_REG0_REG: + case ZPA2326_CTRL_REG1_REG: + case ZPA2326_CTRL_REG2_REG: + case ZPA2326_CTRL_REG3_REG: + case ZPA2326_INT_SOURCE_REG: + case ZPA2326_THS_P_LOW_REG: + case ZPA2326_THS_P_HIGH_REG: + case ZPA2326_STATUS_REG: + case ZPA2326_PRESS_OUT_XL_REG: + case ZPA2326_PRESS_OUT_L_REG: + case ZPA2326_PRESS_OUT_H_REG: + case ZPA2326_TEMP_OUT_L_REG: + case ZPA2326_TEMP_OUT_H_REG: + return true; + + default: + return false; + } +} +EXPORT_SYMBOL_GPL(zpa2326_isreg_readable); + +bool zpa2326_isreg_precious(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ZPA2326_INT_SOURCE_REG: + case ZPA2326_PRESS_OUT_H_REG: + return true; + + default: + return false; + } +} +EXPORT_SYMBOL_GPL(zpa2326_isreg_precious); + +/** + * zpa2326_enable_device() - Enable device, i.e. get out of low power mode. + * @indio_dev: The IIO device associated with the hardware to enable. + * + * Required to access complete register space and to perform any sampling + * or control operations. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_enable_device(const struct iio_dev *indio_dev) +{ + int err; + + err = regmap_write(((struct zpa2326_private *) + iio_priv(indio_dev))->regmap, + ZPA2326_CTRL_REG0_REG, ZPA2326_CTRL_REG0_ENABLE); + if (err) { + zpa2326_err(indio_dev, "failed to enable device (%d)", err); + return err; + } + + zpa2326_dbg(indio_dev, "enabled"); + + return 0; +} + +/** + * zpa2326_sleep() - Disable device, i.e. switch to low power mode. + * @indio_dev: The IIO device associated with the hardware to disable. + * + * Only %ZPA2326_DEVICE_ID_REG and %ZPA2326_CTRL_REG0_REG registers may be + * accessed once device is in the disabled state. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_sleep(const struct iio_dev *indio_dev) +{ + int err; + + err = regmap_write(((struct zpa2326_private *) + iio_priv(indio_dev))->regmap, + ZPA2326_CTRL_REG0_REG, 0); + if (err) { + zpa2326_err(indio_dev, "failed to sleep (%d)", err); + return err; + } + + zpa2326_dbg(indio_dev, "sleeping"); + + return 0; +} + +/** + * zpa2326_reset_device() - Reset device to default hardware state. + * @indio_dev: The IIO device associated with the hardware to reset. + * + * Disable sampling and empty hardware FIFO. + * Device must be enabled before reset, i.e. not in low power mode. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_reset_device(const struct iio_dev *indio_dev) +{ + int err; + + err = regmap_write(((struct zpa2326_private *) + iio_priv(indio_dev))->regmap, + ZPA2326_CTRL_REG2_REG, ZPA2326_CTRL_REG2_SWRESET); + if (err) { + zpa2326_err(indio_dev, "failed to reset device (%d)", err); + return err; + } + + usleep_range(ZPA2326_TPUP_USEC_MIN, ZPA2326_TPUP_USEC_MAX); + + zpa2326_dbg(indio_dev, "reset"); + + return 0; +} + +/** + * zpa2326_start_oneshot() - Start a single sampling cycle, i.e. in one shot + * mode. + * @indio_dev: The IIO device associated with the sampling hardware. + * + * Device must have been previously enabled and configured for one shot mode. + * Device will be switched back to low power mode at end of cycle. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_start_oneshot(const struct iio_dev *indio_dev) +{ + int err; + + err = regmap_write(((struct zpa2326_private *) + iio_priv(indio_dev))->regmap, + ZPA2326_CTRL_REG0_REG, + ZPA2326_CTRL_REG0_ENABLE | + ZPA2326_CTRL_REG0_ONE_SHOT); + if (err) { + zpa2326_err(indio_dev, "failed to start one shot cycle (%d)", + err); + return err; + } + + zpa2326_dbg(indio_dev, "one shot cycle started"); + + return 0; +} + +/** + * zpa2326_power_on() - Power on device to allow subsequent configuration. + * @indio_dev: The IIO device associated with the sampling hardware. + * @private: Internal private state related to @indio_dev. + * + * Sampling will be disabled, preventing strange things from happening in our + * back. Hardware FIFO content will be cleared. + * When successful, device will be left in the enabled state to allow further + * configuration. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_power_on(const struct iio_dev *indio_dev, + const struct zpa2326_private *private) +{ + int err; + + err = regulator_enable(private->vref); + if (err) + return err; + + err = regulator_enable(private->vdd); + if (err) + goto vref; + + zpa2326_dbg(indio_dev, "powered on"); + + err = zpa2326_enable_device(indio_dev); + if (err) + goto vdd; + + err = zpa2326_reset_device(indio_dev); + if (err) + goto sleep; + + return 0; + +sleep: + zpa2326_sleep(indio_dev); +vdd: + regulator_disable(private->vdd); +vref: + regulator_disable(private->vref); + + zpa2326_dbg(indio_dev, "powered off"); + + return err; +} + +/** + * zpa2326_power_off() - Power off device, i.e. disable attached power + * regulators. + * @indio_dev: The IIO device associated with the sampling hardware. + * @private: Internal private state related to @indio_dev. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static void zpa2326_power_off(const struct iio_dev *indio_dev, + const struct zpa2326_private *private) +{ + regulator_disable(private->vdd); + regulator_disable(private->vref); + + zpa2326_dbg(indio_dev, "powered off"); +} + +/** + * zpa2326_config_oneshot() - Setup device for one shot / on demand mode. + * @indio_dev: The IIO device associated with the sampling hardware. + * @irq: Optional interrupt line the hardware uses to notify new data + * samples are ready. Negative or zero values indicate no interrupts + * are available, meaning polling is required. + * + * Output Data Rate is configured for the highest possible rate so that + * conversion time and power consumption are reduced to a minimum. + * Note that hardware internal averaging machinery (not implemented in this + * driver) is not applicable in this mode. + * + * Device must have been previously enabled before calling + * zpa2326_config_oneshot(). + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_config_oneshot(const struct iio_dev *indio_dev, + int irq) +{ + struct regmap *regs = ((struct zpa2326_private *) + iio_priv(indio_dev))->regmap; + const struct zpa2326_frequency *freq = zpa2326_highest_frequency(); + int err; + + /* Setup highest available Output Data Rate for one shot mode. */ + err = regmap_write(regs, ZPA2326_CTRL_REG3_REG, freq->odr); + if (err) + return err; + + if (irq > 0) { + /* Request interrupt when new sample is available. */ + err = regmap_write(regs, ZPA2326_CTRL_REG1_REG, + (u8)~ZPA2326_CTRL_REG1_MASK_DATA_READY); + + if (err) { + dev_err(indio_dev->dev.parent, + "failed to setup one shot mode (%d)", err); + return err; + } + } + + zpa2326_dbg(indio_dev, "one shot mode setup @%dHz", freq->hz); + + return 0; +} + +/** + * zpa2326_clear_fifo() - Clear remaining entries in hardware FIFO. + * @indio_dev: The IIO device associated with the sampling hardware. + * @min_count: Number of samples present within hardware FIFO. + * + * @min_count argument is a hint corresponding to the known minimum number of + * samples currently living in the FIFO. This allows to reduce the number of bus + * accesses by skipping status register read operation as long as we know for + * sure there are still entries left. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_clear_fifo(const struct iio_dev *indio_dev, + unsigned int min_count) +{ + struct regmap *regs = ((struct zpa2326_private *) + iio_priv(indio_dev))->regmap; + int err; + unsigned int val; + + if (!min_count) { + /* + * No hint: read status register to determine whether FIFO is + * empty or not. + */ + err = regmap_read(regs, ZPA2326_STATUS_REG, &val); + + if (err < 0) + goto err; + + if (val & ZPA2326_STATUS_FIFO_E) + /* Fifo is empty: nothing to trash. */ + return 0; + } + + /* Clear FIFO. */ + do { + /* + * A single fetch from pressure MSB register is enough to pop + * values out of FIFO. + */ + err = regmap_read(regs, ZPA2326_PRESS_OUT_H_REG, &val); + if (err < 0) + goto err; + + if (min_count) { + /* + * We know for sure there are at least min_count entries + * left in FIFO. Skip status register read. + */ + min_count--; + continue; + } + + err = regmap_read(regs, ZPA2326_STATUS_REG, &val); + if (err < 0) + goto err; + + } while (!(val & ZPA2326_STATUS_FIFO_E)); + + zpa2326_dbg(indio_dev, "FIFO cleared"); + + return 0; + +err: + zpa2326_err(indio_dev, "failed to clear FIFO (%d)", err); + + return err; +} + +/** + * zpa2326_dequeue_pressure() - Retrieve the most recent pressure sample from + * hardware FIFO. + * @indio_dev: The IIO device associated with the sampling hardware. + * @pressure: Sampled pressure output. + * + * Note that ZPA2326 hardware FIFO stores pressure samples only. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_dequeue_pressure(const struct iio_dev *indio_dev, + u32 *pressure) +{ + struct regmap *regs = ((struct zpa2326_private *) + iio_priv(indio_dev))->regmap; + unsigned int val; + int err; + int cleared = -1; + + err = regmap_read(regs, ZPA2326_STATUS_REG, &val); + if (err < 0) + return err; + + *pressure = 0; + + if (val & ZPA2326_STATUS_P_OR) { + /* + * Fifo overrun : first sample dequeued from FIFO is the + * newest. + */ + zpa2326_warn(indio_dev, "FIFO overflow"); + + err = regmap_bulk_read(regs, ZPA2326_PRESS_OUT_XL_REG, pressure, + 3); + if (err) + return err; + +#define ZPA2326_FIFO_DEPTH (16U) + /* Hardware FIFO may hold no more than 16 pressure samples. */ + return zpa2326_clear_fifo(indio_dev, ZPA2326_FIFO_DEPTH - 1); + } + + /* + * Fifo has not overflown : retrieve newest sample. We need to pop + * values out until FIFO is empty : last fetched pressure is the newest. + * In nominal cases, we should find a single queued sample only. + */ + do { + err = regmap_bulk_read(regs, ZPA2326_PRESS_OUT_XL_REG, pressure, + 3); + if (err) + return err; + + err = regmap_read(regs, ZPA2326_STATUS_REG, &val); + if (err < 0) + return err; + + cleared++; + } while (!(val & ZPA2326_STATUS_FIFO_E)); + + if (cleared) + /* + * Samples were pushed by hardware during previous rounds but we + * didn't consume them fast enough: inform user. + */ + zpa2326_dbg(indio_dev, "cleared %d FIFO entries", cleared); + + return 0; +} + +/** + * zpa2326_fill_sample_buffer() - Enqueue new channel samples to IIO buffer. + * @indio_dev: The IIO device associated with the sampling hardware. + * @private: Internal private state related to @indio_dev. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_fill_sample_buffer(struct iio_dev *indio_dev, + const struct zpa2326_private *private) +{ + struct { + u32 pressure; + u16 temperature; + u64 timestamp; + } sample; + int err; + + if (test_bit(0, indio_dev->active_scan_mask)) { + /* Get current pressure from hardware FIFO. */ + err = zpa2326_dequeue_pressure(indio_dev, &sample.pressure); + if (err) { + zpa2326_warn(indio_dev, "failed to fetch pressure (%d)", + err); + return err; + } + } + + if (test_bit(1, indio_dev->active_scan_mask)) { + /* Get current temperature. */ + err = regmap_bulk_read(private->regmap, ZPA2326_TEMP_OUT_L_REG, + &sample.temperature, 2); + if (err) { + zpa2326_warn(indio_dev, + "failed to fetch temperature (%d)", err); + return err; + } + } + + /* + * Now push samples using timestamp stored either : + * - by hardware interrupt handler if interrupt is available: see + * zpa2326_handle_irq(), + * - or oneshot completion polling machinery : see + * zpa2326_trigger_handler(). + */ + zpa2326_dbg(indio_dev, "filling raw samples buffer"); + + iio_push_to_buffers_with_timestamp(indio_dev, &sample, + private->timestamp); + + return 0; +} + +#ifdef CONFIG_PM +static int zpa2326_runtime_suspend(struct device *parent) +{ + const struct iio_dev *indio_dev = dev_get_drvdata(parent); + + if (pm_runtime_autosuspend_expiration(parent)) + /* Userspace changed autosuspend delay. */ + return -EAGAIN; + + zpa2326_power_off(indio_dev, iio_priv(indio_dev)); + + return 0; +} + +static int zpa2326_runtime_resume(struct device *parent) +{ + const struct iio_dev *indio_dev = dev_get_drvdata(parent); + + return zpa2326_power_on(indio_dev, iio_priv(indio_dev)); +} + +const struct dev_pm_ops zpa2326_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) + SET_RUNTIME_PM_OPS(zpa2326_runtime_suspend, zpa2326_runtime_resume, + NULL) +}; +EXPORT_SYMBOL_GPL(zpa2326_pm_ops); + +/** + * zpa2326_resume() - Request the PM layer to power supply the device. + * @indio_dev: The IIO device associated with the sampling hardware. + * + * Return: + * < 0 - a negative error code meaning failure ; + * 0 - success, device has just been powered up ; + * 1 - success, device was already powered. + */ +static int zpa2326_resume(const struct iio_dev *indio_dev) +{ + int err; + + err = pm_runtime_get_sync(indio_dev->dev.parent); + if (err < 0) + return err; + + if (err > 0) { + /* + * Device was already power supplied: get it out of low power + * mode and inform caller. + */ + zpa2326_enable_device(indio_dev); + return 1; + } + + /* Inform caller device has just been brought back to life. */ + return 0; +} + +/** + * zpa2326_suspend() - Schedule a power down using autosuspend feature of PM + * layer. + * @indio_dev: The IIO device associated with the sampling hardware. + * + * Device is switched to low power mode at first to save power even when + * attached regulator is a "dummy" one. + */ +static void zpa2326_suspend(struct iio_dev *indio_dev) +{ + struct device *parent = indio_dev->dev.parent; + + zpa2326_sleep(indio_dev); + + pm_runtime_mark_last_busy(parent); + pm_runtime_put_autosuspend(parent); +} + +static void zpa2326_init_runtime(struct device *parent) +{ + pm_runtime_get_noresume(parent); + pm_runtime_set_active(parent); + pm_runtime_enable(parent); + pm_runtime_set_autosuspend_delay(parent, 1000); + pm_runtime_use_autosuspend(parent); + pm_runtime_mark_last_busy(parent); + pm_runtime_put_autosuspend(parent); +} + +static void zpa2326_fini_runtime(struct device *parent) +{ + pm_runtime_disable(parent); + pm_runtime_set_suspended(parent); +} +#else /* !CONFIG_PM */ +static int zpa2326_resume(const struct iio_dev *indio_dev) +{ + zpa2326_enable_device(indio_dev); + + return 0; +} + +static void zpa2326_suspend(struct iio_dev *indio_dev) +{ + zpa2326_sleep(indio_dev); +} + +#define zpa2326_init_runtime(_parent) +#define zpa2326_fini_runtime(_parent) +#endif /* !CONFIG_PM */ + +/** + * zpa2326_handle_irq() - Process hardware interrupts. + * @irq: Interrupt line the hardware uses to notify new data has arrived. + * @data: The IIO device associated with the sampling hardware. + * + * Timestamp buffered samples as soon as possible then schedule threaded bottom + * half. + * + * Return: Always successful. + */ +static irqreturn_t zpa2326_handle_irq(int irq, void *data) +{ + struct iio_dev *indio_dev = (struct iio_dev *)data; + + if (iio_buffer_enabled(indio_dev)) { + /* Timestamping needed for buffered sampling only. */ + ((struct zpa2326_private *) + iio_priv(indio_dev))->timestamp = iio_get_time_ns(indio_dev); + } + + return IRQ_WAKE_THREAD; +} + +/** + * zpa2326_handle_threaded_irq() - Interrupt bottom-half handler. + * @irq: Interrupt line the hardware uses to notify new data has arrived. + * @data: The IIO device associated with the sampling hardware. + * + * Mainly ensures interrupt is caused by a real "new sample available" + * condition. This relies upon the ability to perform blocking / sleeping bus + * accesses to slave's registers. This is why zpa2326_handle_threaded_irq() is + * called from within a thread, i.e. not called from hard interrupt context. + * + * When device is using its own internal hardware trigger in continuous sampling + * mode, data are available into hardware FIFO once interrupt has occurred. All + * we have to do is to dispatch the trigger, which in turn will fetch data and + * fill IIO buffer. + * + * When not using its own internal hardware trigger, the device has been + * configured in one-shot mode either by an external trigger or the IIO read_raw + * hook. This means one of the latter is currently waiting for sampling + * completion, in which case we must simply wake it up. + * + * See zpa2326_trigger_handler(). + * + * Return: + * %IRQ_NONE - no consistent interrupt happened ; + * %IRQ_HANDLED - there was new samples available. + */ +static irqreturn_t zpa2326_handle_threaded_irq(int irq, void *data) +{ + struct iio_dev *indio_dev = (struct iio_dev *)data; + struct zpa2326_private *priv = iio_priv(indio_dev); + unsigned int val; + bool cont; + irqreturn_t ret = IRQ_NONE; + + /* + * Are we using our own internal trigger in triggered buffer mode, i.e., + * currently working in continuous sampling mode ? + */ + cont = (iio_buffer_enabled(indio_dev) && + iio_trigger_using_own(indio_dev)); + + /* + * Device works according to a level interrupt scheme: reading interrupt + * status de-asserts interrupt line. + */ + priv->result = regmap_read(priv->regmap, ZPA2326_INT_SOURCE_REG, &val); + if (priv->result < 0) { + if (cont) + return IRQ_NONE; + + goto complete; + } + + /* Data ready is the only interrupt source we requested. */ + if (!(val & ZPA2326_INT_SOURCE_DATA_READY)) { + /* + * Interrupt happened but no new sample available: likely caused + * by spurious interrupts, in which case, returning IRQ_NONE + * allows to benefit from the generic spurious interrupts + * handling. + */ + zpa2326_warn(indio_dev, "unexpected interrupt status %02x", + val); + + if (cont) + return IRQ_NONE; + + priv->result = -ENODATA; + goto complete; + } + + /* New sample available: dispatch internal trigger consumers. */ + iio_trigger_poll_chained(priv->trigger); + + if (cont) + /* + * Internal hardware trigger has been scheduled above : it will + * fetch data on its own. + */ + return IRQ_HANDLED; + + ret = IRQ_HANDLED; + +complete: + /* + * Wake up direct or externaly triggered buffer mode waiters: see + * zpa2326_sample_oneshot() and zpa2326_trigger_handler(). + */ + complete(&priv->data_ready); + + return ret; +} + +/** + * zpa2326_wait_oneshot_completion() - Wait for oneshot data ready interrupt. + * @indio_dev: The IIO device associated with the sampling hardware. + * @private: Internal private state related to @indio_dev. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_wait_oneshot_completion(const struct iio_dev *indio_dev, + struct zpa2326_private *private) +{ + int ret; + unsigned int val; + + zpa2326_dbg(indio_dev, "waiting for one shot completion interrupt"); + + ret = wait_for_completion_interruptible_timeout( + &private->data_ready, ZPA2326_CONVERSION_JIFFIES); + if (ret > 0) + /* + * Interrupt handler completed before timeout: return operation + * status. + */ + return private->result; + + /* Clear all interrupts just to be sure. */ + regmap_read(private->regmap, ZPA2326_INT_SOURCE_REG, &val); + + if (!ret) + /* Timed out. */ + ret = -ETIME; + + if (ret != -ERESTARTSYS) + zpa2326_warn(indio_dev, "no one shot interrupt occurred (%d)", + ret); + + return ret; +} + +static int zpa2326_init_managed_irq(struct device *parent, + struct iio_dev *indio_dev, + struct zpa2326_private *private, + int irq) +{ + int err; + + private->irq = irq; + + if (irq <= 0) { + /* + * Platform declared no interrupt line: device will be polled + * for data availability. + */ + dev_info(parent, "no interrupt found, running in polling mode"); + return 0; + } + + init_completion(&private->data_ready); + + /* Request handler to be scheduled into threaded interrupt context. */ + err = devm_request_threaded_irq(parent, irq, zpa2326_handle_irq, + zpa2326_handle_threaded_irq, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + dev_name(parent), indio_dev); + if (err) { + dev_err(parent, "failed to request interrupt %d (%d)", irq, + err); + return err; + } + + dev_info(parent, "using interrupt %d", irq); + + return 0; +} + +/** + * zpa2326_poll_oneshot_completion() - Actively poll for one shot data ready. + * @indio_dev: The IIO device associated with the sampling hardware. + * + * Loop over registers content to detect end of sampling cycle. Used when DT + * declared no valid interrupt lines. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_poll_oneshot_completion(const struct iio_dev *indio_dev) +{ + unsigned long tmout = jiffies + ZPA2326_CONVERSION_JIFFIES; + struct regmap *regs = ((struct zpa2326_private *) + iio_priv(indio_dev))->regmap; + unsigned int val; + int err; + + zpa2326_dbg(indio_dev, "polling for one shot completion"); + + /* + * At least, 100 ms is needed for the device to complete its one-shot + * cycle. + */ + if (msleep_interruptible(100)) + return -ERESTARTSYS; + + /* Poll for conversion completion in hardware. */ + while (true) { + err = regmap_read(regs, ZPA2326_CTRL_REG0_REG, &val); + if (err < 0) + goto err; + + if (!(val & ZPA2326_CTRL_REG0_ONE_SHOT)) + /* One-shot bit self clears at conversion end. */ + break; + + if (time_after(jiffies, tmout)) { + /* Prevent from waiting forever : let's time out. */ + err = -ETIME; + goto err; + } + + usleep_range(10000, 20000); + } + + /* + * In oneshot mode, pressure sample availability guarantees that + * temperature conversion has also completed : just check pressure + * status bit to keep things simple. + */ + err = regmap_read(regs, ZPA2326_STATUS_REG, &val); + if (err < 0) + goto err; + + if (!(val & ZPA2326_STATUS_P_DA)) { + /* No sample available. */ + err = -ENODATA; + goto err; + } + + return 0; + +err: + zpa2326_warn(indio_dev, "failed to poll one shot completion (%d)", err); + + return err; +} + +/** + * zpa2326_fetch_raw_sample() - Retrieve a raw sample and convert it to CPU + * endianness. + * @indio_dev: The IIO device associated with the sampling hardware. + * @type: Type of measurement / channel to fetch from. + * @value: Sample output. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_fetch_raw_sample(const struct iio_dev *indio_dev, + enum iio_chan_type type, + int *value) +{ + struct regmap *regs = ((struct zpa2326_private *) + iio_priv(indio_dev))->regmap; + int err; + + switch (type) { + case IIO_PRESSURE: + zpa2326_dbg(indio_dev, "fetching raw pressure sample"); + + err = regmap_bulk_read(regs, ZPA2326_PRESS_OUT_XL_REG, value, + 3); + if (err) { + zpa2326_warn(indio_dev, "failed to fetch pressure (%d)", + err); + return err; + } + + /* Pressure is a 24 bits wide little-endian unsigned int. */ + *value = (((u8 *)value)[2] << 16) | (((u8 *)value)[1] << 8) | + ((u8 *)value)[0]; + + return IIO_VAL_INT; + + case IIO_TEMP: + zpa2326_dbg(indio_dev, "fetching raw temperature sample"); + + err = regmap_bulk_read(regs, ZPA2326_TEMP_OUT_L_REG, value, 2); + if (err) { + zpa2326_warn(indio_dev, + "failed to fetch temperature (%d)", err); + return err; + } + + /* Temperature is a 16 bits wide little-endian signed int. */ + *value = (int)le16_to_cpup((__le16 *)value); + + return IIO_VAL_INT; + + default: + return -EINVAL; + } +} + +/** + * zpa2326_sample_oneshot() - Perform a complete one shot sampling cycle. + * @indio_dev: The IIO device associated with the sampling hardware. + * @type: Type of measurement / channel to fetch from. + * @value: Sample output. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_sample_oneshot(struct iio_dev *indio_dev, + enum iio_chan_type type, + int *value) +{ + int ret; + struct zpa2326_private *priv; + + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + + ret = zpa2326_resume(indio_dev); + if (ret < 0) + goto release; + + priv = iio_priv(indio_dev); + + if (ret > 0) { + /* + * We were already power supplied. Just clear hardware FIFO to + * get rid of samples acquired during previous rounds (if any). + * Sampling operation always generates both temperature and + * pressure samples. The latter are always enqueued into + * hardware FIFO. This may lead to situations were pressure + * samples still sit into FIFO when previous cycle(s) fetched + * temperature data only. + * Hence, we need to clear hardware FIFO content to prevent from + * getting outdated values at the end of current cycle. + */ + if (type == IIO_PRESSURE) { + ret = zpa2326_clear_fifo(indio_dev, 0); + if (ret) + goto suspend; + } + } else { + /* + * We have just been power supplied, i.e. device is in default + * "out of reset" state, meaning we need to reconfigure it + * entirely. + */ + ret = zpa2326_config_oneshot(indio_dev, priv->irq); + if (ret) + goto suspend; + } + + /* Start a sampling cycle in oneshot mode. */ + ret = zpa2326_start_oneshot(indio_dev); + if (ret) + goto suspend; + + /* Wait for sampling cycle to complete. */ + if (priv->irq > 0) + ret = zpa2326_wait_oneshot_completion(indio_dev, priv); + else + ret = zpa2326_poll_oneshot_completion(indio_dev); + + if (ret) + goto suspend; + + /* Retrieve raw sample value and convert it to CPU endianness. */ + ret = zpa2326_fetch_raw_sample(indio_dev, type, value); + +suspend: + zpa2326_suspend(indio_dev); +release: + iio_device_release_direct_mode(indio_dev); + + return ret; +} + +/** + * zpa2326_trigger_handler() - Perform an IIO buffered sampling round in one + * shot mode. + * @irq: The software interrupt assigned to @data + * @data: The IIO poll function dispatched by external trigger our device is + * attached to. + * + * Bottom-half handler called by the IIO trigger to which our device is + * currently attached. Allows us to synchronize this device buffered sampling + * either with external events (such as timer expiration, external device sample + * ready, etc...) or with its own interrupt (internal hardware trigger). + * + * When using an external trigger, basically run the same sequence of operations + * as for zpa2326_sample_oneshot() with the following hereafter. Hardware FIFO + * is not cleared since already done at buffering enable time and samples + * dequeueing always retrieves the most recent value. + * + * Otherwise, when internal hardware trigger has dispatched us, just fetch data + * from hardware FIFO. + * + * Fetched data will pushed unprocessed to IIO buffer since samples conversion + * is delegated to userspace in buffered mode (endianness, etc...). + * + * Return: + * %IRQ_NONE - no consistent interrupt happened ; + * %IRQ_HANDLED - there was new samples available. + */ +static irqreturn_t zpa2326_trigger_handler(int irq, void *data) +{ + struct iio_dev *indio_dev = ((struct iio_poll_func *) + data)->indio_dev; + struct zpa2326_private *priv = iio_priv(indio_dev); + bool cont; + + /* + * We have been dispatched, meaning we are in triggered buffer mode. + * Using our own internal trigger implies we are currently in continuous + * hardware sampling mode. + */ + cont = iio_trigger_using_own(indio_dev); + + if (!cont) { + /* On demand sampling : start a one shot cycle. */ + if (zpa2326_start_oneshot(indio_dev)) + goto out; + + /* Wait for sampling cycle to complete. */ + if (priv->irq <= 0) { + /* No interrupt available: poll for completion. */ + if (zpa2326_poll_oneshot_completion(indio_dev)) + goto out; + + /* Only timestamp sample once it is ready. */ + priv->timestamp = iio_get_time_ns(indio_dev); + } else { + /* Interrupt handlers will timestamp for us. */ + if (zpa2326_wait_oneshot_completion(indio_dev, priv)) + goto out; + } + } + + /* Enqueue to IIO buffer / userspace. */ + zpa2326_fill_sample_buffer(indio_dev, priv); + +out: + if (!cont) + /* Don't switch to low power if sampling continuously. */ + zpa2326_sleep(indio_dev); + + /* Inform attached trigger we are done. */ + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +/** + * zpa2326_preenable_buffer() - Prepare device for configuring triggered + * sampling + * modes. + * @indio_dev: The IIO device associated with the sampling hardware. + * + * Basically power up device. + * Called with IIO device's lock held. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_preenable_buffer(struct iio_dev *indio_dev) +{ + int ret = zpa2326_resume(indio_dev); + + if (ret < 0) + return ret; + + /* Tell zpa2326_postenable_buffer() if we have just been powered on. */ + ((struct zpa2326_private *) + iio_priv(indio_dev))->waken = iio_priv(indio_dev); + + return 0; +} + +/** + * zpa2326_postenable_buffer() - Configure device for triggered sampling. + * @indio_dev: The IIO device associated with the sampling hardware. + * + * Basically setup one-shot mode if plugging external trigger. + * Otherwise, let internal trigger configure continuous sampling : + * see zpa2326_set_trigger_state(). + * + * If an error is returned, IIO layer will call our postdisable hook for us, + * i.e. no need to explicitly power device off here. + * Called with IIO device's lock held. + * + * Called with IIO device's lock held. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_postenable_buffer(struct iio_dev *indio_dev) +{ + const struct zpa2326_private *priv = iio_priv(indio_dev); + int err; + + if (!priv->waken) { + /* + * We were already power supplied. Just clear hardware FIFO to + * get rid of samples acquired during previous rounds (if any). + */ + err = zpa2326_clear_fifo(indio_dev, 0); + if (err) + goto err; + } + + if (!iio_trigger_using_own(indio_dev) && priv->waken) { + /* + * We are using an external trigger and we have just been + * powered up: reconfigure one-shot mode. + */ + err = zpa2326_config_oneshot(indio_dev, priv->irq); + if (err) + goto err; + } + + /* Plug our own trigger event handler. */ + err = iio_triggered_buffer_postenable(indio_dev); + if (err) + goto err; + + return 0; + +err: + zpa2326_err(indio_dev, "failed to enable buffering (%d)", err); + + return err; +} + +static int zpa2326_postdisable_buffer(struct iio_dev *indio_dev) +{ + zpa2326_suspend(indio_dev); + + return 0; +} + +static const struct iio_buffer_setup_ops zpa2326_buffer_setup_ops = { + .preenable = zpa2326_preenable_buffer, + .postenable = zpa2326_postenable_buffer, + .predisable = iio_triggered_buffer_predisable, + .postdisable = zpa2326_postdisable_buffer +}; + +/** + * zpa2326_set_trigger_state() - Start / stop continuous sampling. + * @trig: The trigger being attached to IIO device associated with the sampling + * hardware. + * @state: Tell whether to start (true) or stop (false) + * + * Basically enable / disable hardware continuous sampling mode. + * + * Called with IIO device's lock held at postenable() or predisable() time. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_set_trigger_state(struct iio_trigger *trig, bool state) +{ + const struct iio_dev *indio_dev = dev_get_drvdata( + trig->dev.parent); + const struct zpa2326_private *priv = iio_priv(indio_dev); + int err; + + if (!state) { + /* + * Switch trigger off : in case of failure, interrupt is left + * disabled in order to prevent handler from accessing released + * resources. + */ + unsigned int val; + + /* + * As device is working in continuous mode, handlers may be + * accessing resources we are currently freeing... + * Prevent this by disabling interrupt handlers and ensure + * the device will generate no more interrupts unless explicitly + * required to, i.e. by restoring back to default one shot mode. + */ + disable_irq(priv->irq); + + /* + * Disable continuous sampling mode to restore settings for + * one shot / direct sampling operations. + */ + err = regmap_write(priv->regmap, ZPA2326_CTRL_REG3_REG, + zpa2326_highest_frequency()->odr); + if (err) + return err; + + /* + * Now that device won't generate interrupts on its own, + * acknowledge any currently active interrupts (may happen on + * rare occasions while stopping continuous mode). + */ + err = regmap_read(priv->regmap, ZPA2326_INT_SOURCE_REG, &val); + if (err < 0) + return err; + + /* + * Re-enable interrupts only if we can guarantee the device will + * generate no more interrupts to prevent handlers from + * accessing released resources. + */ + enable_irq(priv->irq); + + zpa2326_dbg(indio_dev, "continuous mode stopped"); + } else { + /* + * Switch trigger on : start continuous sampling at required + * frequency. + */ + + if (priv->waken) { + /* Enable interrupt if getting out of reset. */ + err = regmap_write(priv->regmap, ZPA2326_CTRL_REG1_REG, + (u8) + ~ZPA2326_CTRL_REG1_MASK_DATA_READY); + if (err) + return err; + } + + /* Enable continuous sampling at specified frequency. */ + err = regmap_write(priv->regmap, ZPA2326_CTRL_REG3_REG, + ZPA2326_CTRL_REG3_ENABLE_MEAS | + priv->frequency->odr); + if (err) + return err; + + zpa2326_dbg(indio_dev, "continuous mode setup @%dHz", + priv->frequency->hz); + } + + return 0; +} + +static const struct iio_trigger_ops zpa2326_trigger_ops = { + .owner = THIS_MODULE, + .set_trigger_state = zpa2326_set_trigger_state, +}; + +/** + * zpa2326_init_trigger() - Create an interrupt driven / hardware trigger + * allowing to notify external devices a new sample is + * ready. + * @parent: Hardware sampling device @indio_dev is a child of. + * @indio_dev: The IIO device associated with the sampling hardware. + * @private: Internal private state related to @indio_dev. + * @irq: Optional interrupt line the hardware uses to notify new data + * samples are ready. Negative or zero values indicate no interrupts + * are available, meaning polling is required. + * + * Only relevant when DT declares a valid interrupt line. + * + * Return: Zero when successful, a negative error code otherwise. + */ +static int zpa2326_init_managed_trigger(struct device *parent, + struct iio_dev *indio_dev, + struct zpa2326_private *private, + int irq) +{ + struct iio_trigger *trigger; + int ret; + + if (irq <= 0) + return 0; + + trigger = devm_iio_trigger_alloc(parent, "%s-dev%d", + indio_dev->name, indio_dev->id); + if (!trigger) + return -ENOMEM; + + /* Basic setup. */ + trigger->dev.parent = parent; + trigger->ops = &zpa2326_trigger_ops; + + private->trigger = trigger; + + /* Register to triggers space. */ + ret = devm_iio_trigger_register(parent, trigger); + if (ret) + dev_err(parent, "failed to register hardware trigger (%d)", + ret); + + return ret; +} + +static int zpa2326_get_frequency(const struct iio_dev *indio_dev) +{ + return ((struct zpa2326_private *)iio_priv(indio_dev))->frequency->hz; +} + +static int zpa2326_set_frequency(struct iio_dev *indio_dev, int hz) +{ + struct zpa2326_private *priv = iio_priv(indio_dev); + int freq; + int err; + + /* Check if requested frequency is supported. */ + for (freq = 0; freq < ARRAY_SIZE(zpa2326_sampling_frequencies); freq++) + if (zpa2326_sampling_frequencies[freq].hz == hz) + break; + if (freq == ARRAY_SIZE(zpa2326_sampling_frequencies)) + return -EINVAL; + + /* Don't allow changing frequency if buffered sampling is ongoing. */ + err = iio_device_claim_direct_mode(indio_dev); + if (err) + return err; + + priv->frequency = &zpa2326_sampling_frequencies[freq]; + + iio_device_release_direct_mode(indio_dev); + + return 0; +} + +/* Expose supported hardware sampling frequencies (Hz) through sysfs. */ +static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("1 5 11 23"); + +static struct attribute *zpa2326_attributes[] = { + &iio_const_attr_sampling_frequency_available.dev_attr.attr, + NULL +}; + +static const struct attribute_group zpa2326_attribute_group = { + .attrs = zpa2326_attributes, +}; + +static int zpa2326_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_RAW: + return zpa2326_sample_oneshot(indio_dev, chan->type, val); + + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_PRESSURE: + /* + * Pressure resolution is 1/64 Pascal. Scale to kPascal + * as required by IIO ABI. + */ + *val = 1; + *val2 = 64000; + return IIO_VAL_FRACTIONAL; + + case IIO_TEMP: + /* + * Temperature follows the equation: + * Temp[degC] = Tempcode * 0.00649 - 176.83 + * where: + * Tempcode is composed the raw sampled 16 bits. + * + * Hence, to produce a temperature in milli-degrees + * Celsius according to IIO ABI, we need to apply the + * following equation to raw samples: + * Temp[milli degC] = (Tempcode + Offset) * Scale + * where: + * Offset = -176.83 / 0.00649 + * Scale = 0.00649 * 1000 + */ + *val = 6; + *val2 = 490000; + return IIO_VAL_INT_PLUS_MICRO; + + default: + return -EINVAL; + } + + case IIO_CHAN_INFO_OFFSET: + switch (chan->type) { + case IIO_TEMP: + *val = -17683000; + *val2 = 649; + return IIO_VAL_FRACTIONAL; + + default: + return -EINVAL; + } + + case IIO_CHAN_INFO_SAMP_FREQ: + *val = zpa2326_get_frequency(indio_dev); + return IIO_VAL_INT; + + default: + return -EINVAL; + } +} + +static int zpa2326_write_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + int val, + int val2, + long mask) +{ + if ((mask != IIO_CHAN_INFO_SAMP_FREQ) || val2) + return -EINVAL; + + return zpa2326_set_frequency(indio_dev, val); +} + +static const struct iio_chan_spec zpa2326_channels[] = { + [0] = { + .type = IIO_PRESSURE, + .scan_index = 0, + .scan_type = { + .sign = 'u', + .realbits = 24, + .storagebits = 32, + .endianness = IIO_LE, + }, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), + }, + [1] = { + .type = IIO_TEMP, + .scan_index = 1, + .scan_type = { + .sign = 's', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_LE, + }, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_OFFSET), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), + }, + [2] = IIO_CHAN_SOFT_TIMESTAMP(2), +}; + +static const struct iio_info zpa2326_info = { + .driver_module = THIS_MODULE, + .attrs = &zpa2326_attribute_group, + .read_raw = zpa2326_read_raw, + .write_raw = zpa2326_write_raw, +}; + +static struct iio_dev *zpa2326_create_managed_iiodev(struct device *device, + const char *name, + struct regmap *regmap) +{ + struct iio_dev *indio_dev; + + /* Allocate space to hold IIO device internal state. */ + indio_dev = devm_iio_device_alloc(device, + sizeof(struct zpa2326_private)); + if (!indio_dev) + return NULL; + + /* Setup for userspace synchronous on demand sampling. */ + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->dev.parent = device; + indio_dev->channels = zpa2326_channels; + indio_dev->num_channels = ARRAY_SIZE(zpa2326_channels); + indio_dev->name = name; + indio_dev->info = &zpa2326_info; + + return indio_dev; +} + +int zpa2326_probe(struct device *parent, + const char *name, + int irq, + unsigned int hwid, + struct regmap *regmap) +{ + struct iio_dev *indio_dev; + struct zpa2326_private *priv; + int err; + unsigned int id; + + indio_dev = zpa2326_create_managed_iiodev(parent, name, regmap); + if (!indio_dev) + return -ENOMEM; + + priv = iio_priv(indio_dev); + + priv->vref = devm_regulator_get(parent, "vref"); + if (IS_ERR(priv->vref)) + return PTR_ERR(priv->vref); + + priv->vdd = devm_regulator_get(parent, "vdd"); + if (IS_ERR(priv->vdd)) + return PTR_ERR(priv->vdd); + + /* Set default hardware sampling frequency to highest rate supported. */ + priv->frequency = zpa2326_highest_frequency(); + + /* + * Plug device's underlying bus abstraction : this MUST be set before + * registering interrupt handlers since an interrupt might happen if + * power up sequence is not properly applied. + */ + priv->regmap = regmap; + + err = devm_iio_triggered_buffer_setup(parent, indio_dev, NULL, + zpa2326_trigger_handler, + &zpa2326_buffer_setup_ops); + if (err) + return err; + + err = zpa2326_init_managed_trigger(parent, indio_dev, priv, irq); + if (err) + return err; + + err = zpa2326_init_managed_irq(parent, indio_dev, priv, irq); + if (err) + return err; + + /* Power up to check device ID and perform initial hardware setup. */ + err = zpa2326_power_on(indio_dev, priv); + if (err) + return err; + + /* Read id register to check we are talking to the right slave. */ + err = regmap_read(regmap, ZPA2326_DEVICE_ID_REG, &id); + if (err) + goto sleep; + + if (id != hwid) { + dev_err(parent, "found device with unexpected id %02x", id); + err = -ENODEV; + goto sleep; + } + + err = zpa2326_config_oneshot(indio_dev, irq); + if (err) + goto sleep; + + /* Setup done : go sleeping. Device will be awaken upon user request. */ + err = zpa2326_sleep(indio_dev); + if (err) + goto poweroff; + + dev_set_drvdata(parent, indio_dev); + + zpa2326_init_runtime(parent); + + err = iio_device_register(indio_dev); + if (err) { + zpa2326_fini_runtime(parent); + goto poweroff; + } + + return 0; + +sleep: + /* Put to sleep just in case power regulators are "dummy" ones. */ + zpa2326_sleep(indio_dev); +poweroff: + zpa2326_power_off(indio_dev, priv); + + return err; +} +EXPORT_SYMBOL_GPL(zpa2326_probe); + +void zpa2326_remove(const struct device *parent) +{ + struct iio_dev *indio_dev = dev_get_drvdata(parent); + + iio_device_unregister(indio_dev); + zpa2326_fini_runtime(indio_dev->dev.parent); + zpa2326_sleep(indio_dev); + zpa2326_power_off(indio_dev, iio_priv(indio_dev)); +} +EXPORT_SYMBOL_GPL(zpa2326_remove); + +MODULE_AUTHOR("Gregor Boirie <gregor.boirie@parrot.com>"); +MODULE_DESCRIPTION("Core driver for Murata ZPA2326 pressure sensor"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/pressure/zpa2326.h b/drivers/iio/pressure/zpa2326.h new file mode 100644 index 0000000..05d3e1e --- /dev/null +++ b/drivers/iio/pressure/zpa2326.h @@ -0,0 +1,89 @@ +/* + * Murata ZPA2326 pressure and temperature sensor IIO driver + * + * Copyright (c) 2016 Parrot S.A. + * + * Author: Gregor Boirie <gregor.boirie@parrot.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef _ZPA2326_H +#define _ZPA2326_H + +/* Register map. */ +#define ZPA2326_REF_P_XL_REG (0x8) +#define ZPA2326_REF_P_L_REG (0x9) +#define ZPA2326_REF_P_H_REG (0xa) +#define ZPA2326_DEVICE_ID_REG (0xf) +#define ZPA2326_DEVICE_ID (0xb9) +#define ZPA2326_RES_CONF_REG (0x10) +#define ZPA2326_CTRL_REG0_REG (0x20) +#define ZPA2326_CTRL_REG0_ONE_SHOT BIT(0) +#define ZPA2326_CTRL_REG0_ENABLE BIT(1) +#define ZPA2326_CTRL_REG1_REG (0x21) +#define ZPA2326_CTRL_REG1_MASK_DATA_READY BIT(2) +#define ZPA2326_CTRL_REG2_REG (0x22) +#define ZPA2326_CTRL_REG2_SWRESET BIT(2) +#define ZPA2326_CTRL_REG3_REG (0x23) +#define ZPA2326_CTRL_REG3_ODR_SHIFT (4) +#define ZPA2326_CTRL_REG3_ENABLE_MEAS BIT(7) +#define ZPA2326_INT_SOURCE_REG (0x24) +#define ZPA2326_INT_SOURCE_DATA_READY BIT(2) +#define ZPA2326_THS_P_LOW_REG (0x25) +#define ZPA2326_THS_P_HIGH_REG (0x26) +#define ZPA2326_STATUS_REG (0x27) +#define ZPA2326_STATUS_P_DA BIT(1) +#define ZPA2326_STATUS_FIFO_E BIT(2) +#define ZPA2326_STATUS_P_OR BIT(5) +#define ZPA2326_PRESS_OUT_XL_REG (0x28) +#define ZPA2326_PRESS_OUT_L_REG (0x29) +#define ZPA2326_PRESS_OUT_H_REG (0x2a) +#define ZPA2326_TEMP_OUT_L_REG (0x2b) +#define ZPA2326_TEMP_OUT_H_REG (0x2c) + +struct device; +struct regmap; + +bool zpa2326_isreg_writeable(struct device *dev, unsigned int reg); +bool zpa2326_isreg_readable(struct device *dev, unsigned int reg); +bool zpa2326_isreg_precious(struct device *dev, unsigned int reg); + +/** + * zpa2326_probe() - Instantiate and register core ZPA2326 IIO device + * @parent: Hardware sampling device the created IIO device will be a child of. + * @name: Arbitrary name to identify the device. + * @irq: Interrupt line, negative if none. + * @hwid: Expected device hardware id. + * @regmap: Registers map used to abstract underlying bus accesses. + * + * Return: Zero when successful, a negative error code otherwise. + */ +int zpa2326_probe(struct device *parent, + const char *name, + int irq, + unsigned int hwid, + struct regmap *regmap); + +/** + * zpa2326_remove() - Unregister and destroy core ZPA2326 IIO device. + * @parent: Hardware sampling device the IIO device to remove is a child of. + */ +void zpa2326_remove(const struct device *parent); + +#ifdef CONFIG_PM +#include <linux/pm.h> +extern const struct dev_pm_ops zpa2326_pm_ops; +#define ZPA2326_PM_OPS (&zpa2326_pm_ops) +#else +#define ZPA2326_PM_OPS (NULL) +#endif + +#endif diff --git a/drivers/iio/pressure/zpa2326_i2c.c b/drivers/iio/pressure/zpa2326_i2c.c new file mode 100644 index 0000000..e4d27dd --- /dev/null +++ b/drivers/iio/pressure/zpa2326_i2c.c @@ -0,0 +1,99 @@ +/* + * Murata ZPA2326 I2C pressure and temperature sensor driver + * + * Copyright (c) 2016 Parrot S.A. + * + * Author: Gregor Boirie <gregor.boirie@parrot.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include <linux/module.h> +#include <linux/regmap.h> +#include <linux/i2c.h> +#include <linux/of_device.h> +#include "zpa2326.h" + +/* + * read_flag_mask: + * - address bit 7 must be set to request a register read operation + */ +static const struct regmap_config zpa2326_regmap_i2c_config = { + .reg_bits = 8, + .val_bits = 8, + .writeable_reg = zpa2326_isreg_writeable, + .readable_reg = zpa2326_isreg_readable, + .precious_reg = zpa2326_isreg_precious, + .max_register = ZPA2326_TEMP_OUT_H_REG, + .read_flag_mask = BIT(7), + .cache_type = REGCACHE_NONE, +}; + +static unsigned int zpa2326_i2c_hwid(const struct i2c_client *client) +{ +#define ZPA2326_SA0(_addr) (_addr & BIT(0)) +#define ZPA2326_DEVICE_ID_SA0_SHIFT (1) + + /* Identification register bit 1 mirrors device address bit 0. */ + return (ZPA2326_DEVICE_ID | + (ZPA2326_SA0(client->addr) << ZPA2326_DEVICE_ID_SA0_SHIFT)); +} + +static int zpa2326_probe_i2c(struct i2c_client *client, + const struct i2c_device_id *i2c_id) +{ + struct regmap *regmap; + + regmap = devm_regmap_init_i2c(client, &zpa2326_regmap_i2c_config); + if (IS_ERR(regmap)) { + dev_err(&client->dev, "failed to init registers map"); + return PTR_ERR(regmap); + } + + return zpa2326_probe(&client->dev, i2c_id->name, client->irq, + zpa2326_i2c_hwid(client), regmap); +} + +static int zpa2326_remove_i2c(struct i2c_client *client) +{ + zpa2326_remove(&client->dev); + + return 0; +} + +static const struct i2c_device_id zpa2326_i2c_ids[] = { + { "zpa2326", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, zpa2326_i2c_ids); + +#if defined(CONFIG_OF) +static const struct of_device_id zpa2326_i2c_matches[] = { + { .compatible = "murata,zpa2326" }, + { } +}; +MODULE_DEVICE_TABLE(of, zpa2326_i2c_matches); +#endif + +static struct i2c_driver zpa2326_i2c_driver = { + .driver = { + .name = "zpa2326-i2c", + .of_match_table = of_match_ptr(zpa2326_i2c_matches), + .pm = ZPA2326_PM_OPS, + }, + .probe = zpa2326_probe_i2c, + .remove = zpa2326_remove_i2c, + .id_table = zpa2326_i2c_ids, +}; +module_i2c_driver(zpa2326_i2c_driver); + +MODULE_AUTHOR("Gregor Boirie <gregor.boirie@parrot.com>"); +MODULE_DESCRIPTION("I2C driver for Murata ZPA2326 pressure sensor"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/pressure/zpa2326_spi.c b/drivers/iio/pressure/zpa2326_spi.c new file mode 100644 index 0000000..bd2c1c3 --- /dev/null +++ b/drivers/iio/pressure/zpa2326_spi.c @@ -0,0 +1,103 @@ +/* + * Murata ZPA2326 SPI pressure and temperature sensor driver + * + * Copyright (c) 2016 Parrot S.A. + * + * Author: Gregor Boirie <gregor.boirie@parrot.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include <linux/module.h> +#include <linux/regmap.h> +#include <linux/spi/spi.h> +#include <linux/of_device.h> +#include "zpa2326.h" + +/* + * read_flag_mask: + * - address bit 7 must be set to request a register read operation + * - address bit 6 must be set to request register address auto increment + */ +static const struct regmap_config zpa2326_regmap_spi_config = { + .reg_bits = 8, + .val_bits = 8, + .writeable_reg = zpa2326_isreg_writeable, + .readable_reg = zpa2326_isreg_readable, + .precious_reg = zpa2326_isreg_precious, + .max_register = ZPA2326_TEMP_OUT_H_REG, + .read_flag_mask = BIT(7) | BIT(6), + .cache_type = REGCACHE_NONE, +}; + +static int zpa2326_probe_spi(struct spi_device *spi) +{ + struct regmap *regmap; + int err; + + regmap = devm_regmap_init_spi(spi, &zpa2326_regmap_spi_config); + if (IS_ERR(regmap)) { + dev_err(&spi->dev, "failed to init registers map"); + return PTR_ERR(regmap); + } + + /* + * Enforce SPI slave settings to prevent from DT misconfiguration. + * + * Clock is idle high. Sampling happens on trailing edge, i.e., rising + * edge. Maximum bus frequency is 1 MHz. Registers are 8 bits wide. + */ + spi->mode = SPI_MODE_3; + spi->max_speed_hz = min(spi->max_speed_hz, 1000000U); + spi->bits_per_word = 8; + err = spi_setup(spi); + if (err < 0) + return err; + + return zpa2326_probe(&spi->dev, spi_get_device_id(spi)->name, + spi->irq, ZPA2326_DEVICE_ID, regmap); +} + +static int zpa2326_remove_spi(struct spi_device *spi) +{ + zpa2326_remove(&spi->dev); + + return 0; +} + +static const struct spi_device_id zpa2326_spi_ids[] = { + { "zpa2326", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(spi, zpa2326_spi_ids); + +#if defined(CONFIG_OF) +static const struct of_device_id zpa2326_spi_matches[] = { + { .compatible = "murata,zpa2326" }, + { } +}; +MODULE_DEVICE_TABLE(of, zpa2326_spi_matches); +#endif + +static struct spi_driver zpa2326_spi_driver = { + .driver = { + .name = "zpa2326-spi", + .of_match_table = of_match_ptr(zpa2326_spi_matches), + .pm = ZPA2326_PM_OPS, + }, + .probe = zpa2326_probe_spi, + .remove = zpa2326_remove_spi, + .id_table = zpa2326_spi_ids, +}; +module_spi_driver(zpa2326_spi_driver); + +MODULE_AUTHOR("Gregor Boirie <gregor.boirie@parrot.com>"); +MODULE_DESCRIPTION("SPI driver for Murata ZPA2326 pressure sensor"); +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From ac45e57f15903747ccd5a14cebfbd673ebcbdd6f Mon Sep 17 00:00:00 2001 From: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Date: Sun, 18 Sep 2016 16:41:30 +0200 Subject: iio: light: Add driver for Silabs si1132, si1141/2/3 and si1145/6/7 ambient light, uv index and proximity sensors The si114x supports x=1,2,3 IR LEDs for proximity sensing together with visible and IR ambient light sensing (ALS). Newer parts (si1132, si1145/6/7) can measure UV light and compute an UV index This was tested on si1143 and si1145 Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Signed-off-by: Crestez Dan Leonard <leonard.crestez@intel.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org> diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 0db0a0d..ba2e64d 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -267,6 +267,19 @@ config PA12203001 This driver can also be built as a module. If so, the module will be called pa12203001. +config SI1145 + tristate "SI1132 and SI1141/2/3/5/6/7 combined ALS, UV index and proximity sensor" + depends on I2C + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say Y here if you want to build a driver for the Silicon Labs SI1132 or + SI1141/2/3/5/6/7 combined ambient light, UV index and proximity sensor + chips. + + To compile this driver as a module, choose M here: the module will be + called si1145. + config STK3310 tristate "STK3310 ALS and proximity sensor" depends on I2C diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile index 6f2a3c6..c5768df 100644 --- a/drivers/iio/light/Makefile +++ b/drivers/iio/light/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_OPT3001) += opt3001.o obj-$(CONFIG_PA12203001) += pa12203001.o obj-$(CONFIG_RPR0521) += rpr0521.o obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o +obj-$(CONFIG_SI1145) += si1145.o obj-$(CONFIG_STK3310) += stk3310.o obj-$(CONFIG_TCS3414) += tcs3414.o obj-$(CONFIG_TCS3472) += tcs3472.o diff --git a/drivers/iio/light/si1145.c b/drivers/iio/light/si1145.c new file mode 100644 index 0000000..096034c --- /dev/null +++ b/drivers/iio/light/si1145.c @@ -0,0 +1,1404 @@ +/* + * si1145.c - Support for Silabs SI1132 and SI1141/2/3/5/6/7 combined ambient + * light, UV index and proximity sensors + * + * Copyright 2014-16 Peter Meerwald-Stadler <pmeerw@pmeerw.net> + * Copyright 2016 Crestez Dan Leonard <leonard.crestez@intel.com> + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + * + * SI1132 (7-bit I2C slave address 0x60) + * SI1141/2/3 (7-bit I2C slave address 0x5a) + * SI1145/6/6 (7-bit I2C slave address 0x60) + */ + +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/err.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/irq.h> +#include <linux/gpio.h> + +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/trigger.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/iio/triggered_buffer.h> +#include <linux/iio/buffer.h> +#include <linux/util_macros.h> + +#define SI1145_REG_PART_ID 0x00 +#define SI1145_REG_REV_ID 0x01 +#define SI1145_REG_SEQ_ID 0x02 +#define SI1145_REG_INT_CFG 0x03 +#define SI1145_REG_IRQ_ENABLE 0x04 +#define SI1145_REG_IRQ_MODE 0x05 +#define SI1145_REG_HW_KEY 0x07 +#define SI1145_REG_MEAS_RATE 0x08 +#define SI1145_REG_PS_LED21 0x0f +#define SI1145_REG_PS_LED3 0x10 +#define SI1145_REG_UCOEF1 0x13 +#define SI1145_REG_UCOEF2 0x14 +#define SI1145_REG_UCOEF3 0x15 +#define SI1145_REG_UCOEF4 0x16 +#define SI1145_REG_PARAM_WR 0x17 +#define SI1145_REG_COMMAND 0x18 +#define SI1145_REG_RESPONSE 0x20 +#define SI1145_REG_IRQ_STATUS 0x21 +#define SI1145_REG_ALSVIS_DATA 0x22 +#define SI1145_REG_ALSIR_DATA 0x24 +#define SI1145_REG_PS1_DATA 0x26 +#define SI1145_REG_PS2_DATA 0x28 +#define SI1145_REG_PS3_DATA 0x2a +#define SI1145_REG_AUX_DATA 0x2c +#define SI1145_REG_PARAM_RD 0x2e +#define SI1145_REG_CHIP_STAT 0x30 + +#define SI1145_UCOEF1_DEFAULT 0x7b +#define SI1145_UCOEF2_DEFAULT 0x6b +#define SI1145_UCOEF3_DEFAULT 0x01 +#define SI1145_UCOEF4_DEFAULT 0x00 + +/* Helper to figure out PS_LED register / shift per channel */ +#define SI1145_PS_LED_REG(ch) \ + (((ch) == 2) ? SI1145_REG_PS_LED3 : SI1145_REG_PS_LED21) +#define SI1145_PS_LED_SHIFT(ch) \ + (((ch) == 1) ? 4 : 0) + +/* Parameter offsets */ +#define SI1145_PARAM_CHLIST 0x01 +#define SI1145_PARAM_PSLED12_SELECT 0x02 +#define SI1145_PARAM_PSLED3_SELECT 0x03 +#define SI1145_PARAM_PS_ENCODING 0x05 +#define SI1145_PARAM_ALS_ENCODING 0x06 +#define SI1145_PARAM_PS1_ADC_MUX 0x07 +#define SI1145_PARAM_PS2_ADC_MUX 0x08 +#define SI1145_PARAM_PS3_ADC_MUX 0x09 +#define SI1145_PARAM_PS_ADC_COUNTER 0x0a +#define SI1145_PARAM_PS_ADC_GAIN 0x0b +#define SI1145_PARAM_PS_ADC_MISC 0x0c +#define SI1145_PARAM_ALS_ADC_MUX 0x0d +#define SI1145_PARAM_ALSIR_ADC_MUX 0x0e +#define SI1145_PARAM_AUX_ADC_MUX 0x0f +#define SI1145_PARAM_ALSVIS_ADC_COUNTER 0x10 +#define SI1145_PARAM_ALSVIS_ADC_GAIN 0x11 +#define SI1145_PARAM_ALSVIS_ADC_MISC 0x12 +#define SI1145_PARAM_LED_RECOVERY 0x1c +#define SI1145_PARAM_ALSIR_ADC_COUNTER 0x1d +#define SI1145_PARAM_ALSIR_ADC_GAIN 0x1e +#define SI1145_PARAM_ALSIR_ADC_MISC 0x1f +#define SI1145_PARAM_ADC_OFFSET 0x1a + +/* Channel enable masks for CHLIST parameter */ +#define SI1145_CHLIST_EN_PS1 BIT(0) +#define SI1145_CHLIST_EN_PS2 BIT(1) +#define SI1145_CHLIST_EN_PS3 BIT(2) +#define SI1145_CHLIST_EN_ALSVIS BIT(4) +#define SI1145_CHLIST_EN_ALSIR BIT(5) +#define SI1145_CHLIST_EN_AUX BIT(6) +#define SI1145_CHLIST_EN_UV BIT(7) + +/* Proximity measurement mode for ADC_MISC parameter */ +#define SI1145_PS_ADC_MODE_NORMAL BIT(2) +/* Signal range mask for ADC_MISC parameter */ +#define SI1145_ADC_MISC_RANGE BIT(5) + +/* Commands for REG_COMMAND */ +#define SI1145_CMD_NOP 0x00 +#define SI1145_CMD_RESET 0x01 +#define SI1145_CMD_PS_FORCE 0x05 +#define SI1145_CMD_ALS_FORCE 0x06 +#define SI1145_CMD_PSALS_FORCE 0x07 +#define SI1145_CMD_PS_PAUSE 0x09 +#define SI1145_CMD_ALS_PAUSE 0x0a +#define SI1145_CMD_PSALS_PAUSE 0x0b +#define SI1145_CMD_PS_AUTO 0x0d +#define SI1145_CMD_ALS_AUTO 0x0e +#define SI1145_CMD_PSALS_AUTO 0x0f +#define SI1145_CMD_PARAM_QUERY 0x80 +#define SI1145_CMD_PARAM_SET 0xa0 + +#define SI1145_RSP_INVALID_SETTING 0x80 +#define SI1145_RSP_COUNTER_MASK 0x0F + +/* Minimum sleep after each command to ensure it's received */ +#define SI1145_COMMAND_MINSLEEP_MS 5 +/* Return -ETIMEDOUT after this long */ +#define SI1145_COMMAND_TIMEOUT_MS 25 + +/* Interrupt configuration masks for INT_CFG register */ +#define SI1145_INT_CFG_OE BIT(0) /* enable interrupt */ +#define SI1145_INT_CFG_MODE BIT(1) /* auto reset interrupt pin */ + +/* Interrupt enable masks for IRQ_ENABLE register */ +#define SI1145_MASK_ALL_IE (BIT(4) | BIT(3) | BIT(2) | BIT(0)) + +#define SI1145_MUX_TEMP 0x65 +#define SI1145_MUX_VDD 0x75 + +/* Proximity LED current; see Table 2 in datasheet */ +#define SI1145_LED_CURRENT_45mA 0x04 + +enum { + SI1132, + SI1141, + SI1142, + SI1143, + SI1145, + SI1146, + SI1147, +}; + +struct si1145_part_info { + u8 part; + const struct iio_info *iio_info; + const struct iio_chan_spec *channels; + unsigned int num_channels; + unsigned int num_leds; + bool uncompressed_meas_rate; +}; + +/** + * struct si1145_data - si1145 chip state data + * @client: I2C client + * @lock: mutex to protect shared state. + * @cmdlock: Low-level mutex to protect command execution only + * @rsp_seq: Next expected response number or -1 if counter reset required + * @scan_mask: Saved scan mask to avoid duplicate set_chlist + * @autonomous: If automatic measurements are active (for buffer support) + * @part_info: Part information + * @trig: Pointer to iio trigger + * @meas_rate: Value of MEAS_RATE register. Only set in HW in auto mode + */ +struct si1145_data { + struct i2c_client *client; + struct mutex lock; + struct mutex cmdlock; + int rsp_seq; + const struct si1145_part_info *part_info; + unsigned long scan_mask; + bool autonomous; + struct iio_trigger *trig; + int meas_rate; +}; + +/** + * __si1145_command_reset() - Send CMD_NOP and wait for response 0 + * + * Does not modify data->rsp_seq + * + * Return: 0 on success and -errno on error. + */ +static int __si1145_command_reset(struct si1145_data *data) +{ + struct device *dev = &data->client->dev; + unsigned long stop_jiffies; + int ret; + + ret = i2c_smbus_write_byte_data(data->client, SI1145_REG_COMMAND, + SI1145_CMD_NOP); + if (ret < 0) + return ret; + msleep(SI1145_COMMAND_MINSLEEP_MS); + + stop_jiffies = jiffies + SI1145_COMMAND_TIMEOUT_MS * HZ / 1000; + while (true) { + ret = i2c_smbus_read_byte_data(data->client, + SI1145_REG_RESPONSE); + if (ret <= 0) + return ret; + if (time_after(jiffies, stop_jiffies)) { + dev_warn(dev, "timeout on reset\n"); + return -ETIMEDOUT; + } + msleep(SI1145_COMMAND_MINSLEEP_MS); + continue; + } +} + +/** + * si1145_command() - Execute a command and poll the response register + * + * All conversion overflows are reported as -EOVERFLOW + * INVALID_SETTING is reported as -EINVAL + * Timeouts are reported as -ETIMEDOUT + * + * Return: 0 on success or -errno on failure + */ +static int si1145_command(struct si1145_data *data, u8 cmd) +{ + struct device *dev = &data->client->dev; + unsigned long stop_jiffies; + int ret; + + mutex_lock(&data->cmdlock); + + if (data->rsp_seq < 0) { + ret = __si1145_command_reset(data); + if (ret < 0) { + dev_err(dev, "failed to reset command counter, ret=%d\n", + ret); + goto out; + } + data->rsp_seq = 0; + } + + ret = i2c_smbus_write_byte_data(data->client, SI1145_REG_COMMAND, cmd); + if (ret) { + dev_warn(dev, "failed to write command, ret=%d\n", ret); + goto out; + } + /* Sleep a little to ensure the command is received */ + msleep(SI1145_COMMAND_MINSLEEP_MS); + + stop_jiffies = jiffies + SI1145_COMMAND_TIMEOUT_MS * HZ / 1000; + while (true) { + ret = i2c_smbus_read_byte_data(data->client, + SI1145_REG_RESPONSE); + if (ret < 0) { + dev_warn(dev, "failed to read response, ret=%d\n", ret); + break; + } + + 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", + cmd); + ret = -ETIMEDOUT; + break; + } + msleep(SI1145_COMMAND_MINSLEEP_MS); + continue; + } + if (ret == ((data->rsp_seq + 1) & + SI1145_RSP_COUNTER_MASK)) { + data->rsp_seq = ret; + ret = 0; + break; + } + dev_warn(dev, "unexpected response counter %d instead of %d\n", + ret, (data->rsp_seq + 1) & + SI1145_RSP_COUNTER_MASK); + ret = -EIO; + } else { + if (ret == SI1145_RSP_INVALID_SETTING) { + dev_warn(dev, "INVALID_SETTING error on command %#02hhx\n", + cmd); + ret = -EINVAL; + } else { + /* All overflows are treated identically */ + dev_dbg(dev, "overflow, ret=%d, cmd=%#02hhx\n", + ret, cmd); + ret = -EOVERFLOW; + } + } + + /* Force a counter reset next time */ + data->rsp_seq = -1; + break; + } + +out: + mutex_unlock(&data->cmdlock); + + return ret; +} + +static int si1145_param_update(struct si1145_data *data, u8 op, u8 param, + u8 value) +{ + int ret; + + ret = i2c_smbus_write_byte_data(data->client, + SI1145_REG_PARAM_WR, value); + if (ret < 0) + return ret; + + return si1145_command(data, op | (param & 0x1F)); +} + +static int si1145_param_set(struct si1145_data *data, u8 param, u8 value) +{ + return si1145_param_update(data, SI1145_CMD_PARAM_SET, param, value); +} + +/* Set param. Returns negative errno or current value */ +static int si1145_param_query(struct si1145_data *data, u8 param) +{ + int ret; + + ret = si1145_command(data, SI1145_CMD_PARAM_QUERY | (param & 0x1F)); + if (ret < 0) + return ret; + + return i2c_smbus_read_byte_data(data->client, SI1145_REG_PARAM_RD); +} + +/* Expand 8 bit compressed value to 16 bit, see Silabs AN498 */ +static u16 si1145_uncompress(u8 x) +{ + u16 result = 0; + u8 exponent = 0; + + if (x < 8) + return 0; + + exponent = (x & 0xf0) >> 4; + result = 0x10 | (x & 0x0f); + + if (exponent >= 4) + return result << (exponent - 4); + return result >> (4 - exponent); +} + +/* Compress 16 bit value to 8 bit, see Silabs AN498 */ +static u8 si1145_compress(u16 x) +{ + u32 exponent = 0; + u32 significand = 0; + u32 tmp = x; + + if (x == 0x0000) + return 0x00; + if (x == 0x0001) + return 0x08; + + while (1) { + tmp >>= 1; + exponent += 1; + if (tmp == 1) + break; + } + + if (exponent < 5) { + significand = x << (4 - exponent); + return (exponent << 4) | (significand & 0xF); + } + + significand = x >> (exponent - 5); + if (significand & 1) { + significand += 2; + if (significand & 0x0040) { + exponent += 1; + significand >>= 1; + } + } + + return (exponent << 4) | ((significand >> 1) & 0xF); +} + +/* Write meas_rate in hardware */ +static int si1145_set_meas_rate(struct si1145_data *data, int interval) +{ + if (data->part_info->uncompressed_meas_rate) + return i2c_smbus_write_word_data(data->client, + SI1145_REG_MEAS_RATE, interval); + else + return i2c_smbus_write_byte_data(data->client, + SI1145_REG_MEAS_RATE, interval); +} + +static int si1145_read_samp_freq(struct si1145_data *data, int *val, int *val2) +{ + *val = 32000; + if (data->part_info->uncompressed_meas_rate) + *val2 = data->meas_rate; + else + *val2 = si1145_uncompress(data->meas_rate); + return IIO_VAL_FRACTIONAL; +} + +/* Set the samp freq in driver private data */ +static int si1145_store_samp_freq(struct si1145_data *data, int val) +{ + int ret = 0; + int meas_rate; + + if (val <= 0 || val > 32000) + return -ERANGE; + meas_rate = 32000 / val; + + mutex_lock(&data->lock); + if (data->autonomous) { + ret = si1145_set_meas_rate(data, meas_rate); + if (ret) + goto out; + } + if (data->part_info->uncompressed_meas_rate) + data->meas_rate = meas_rate; + else + data->meas_rate = si1145_compress(meas_rate); + +out: + mutex_unlock(&data->lock); + + return ret; +} + +static irqreturn_t si1145_trigger_handler(int irq, void *private) +{ + struct iio_poll_func *pf = private; + struct iio_dev *indio_dev = pf->indio_dev; + struct si1145_data *data = iio_priv(indio_dev); + /* + * Maximum buffer size: + * 6*2 bytes channels data + 4 bytes alignment + + * 8 bytes timestamp + */ + u8 buffer[24]; + int i, j = 0; + int ret; + u8 irq_status = 0; + + if (!data->autonomous) { + ret = si1145_command(data, SI1145_CMD_PSALS_FORCE); + if (ret < 0 && ret != -EOVERFLOW) + goto done; + } else { + irq_status = ret = i2c_smbus_read_byte_data(data->client, + SI1145_REG_IRQ_STATUS); + if (ret < 0) + goto done; + if (!(irq_status & SI1145_MASK_ALL_IE)) + goto done; + } + + for_each_set_bit(i, indio_dev->active_scan_mask, + indio_dev->masklength) { + int run = 1; + + while (i + run < indio_dev->masklength) { + if (!test_bit(i + run, indio_dev->active_scan_mask)) + break; + if (indio_dev->channels[i + run].address != + indio_dev->channels[i].address + 2 * run) + break; + run++; + } + + ret = i2c_smbus_read_i2c_block_data_or_emulated( + data->client, indio_dev->channels[i].address, + sizeof(u16) * run, &buffer[j]); + if (ret < 0) + goto done; + j += run * sizeof(u16); + i += run - 1; + } + + if (data->autonomous) { + ret = i2c_smbus_write_byte_data(data->client, + SI1145_REG_IRQ_STATUS, + irq_status & SI1145_MASK_ALL_IE); + if (ret < 0) + goto done; + } + + iio_push_to_buffers_with_timestamp(indio_dev, buffer, + iio_get_time_ns(indio_dev)); + +done: + iio_trigger_notify_done(indio_dev->trig); + return IRQ_HANDLED; +} + +static int si1145_set_chlist(struct iio_dev *indio_dev, unsigned long scan_mask) +{ + struct si1145_data *data = iio_priv(indio_dev); + u8 reg = 0, mux; + int ret; + int i; + + /* channel list already set, no need to reprogram */ + if (data->scan_mask == scan_mask) + return 0; + + for_each_set_bit(i, &scan_mask, indio_dev->masklength) { + switch (indio_dev->channels[i].address) { + case SI1145_REG_ALSVIS_DATA: + reg |= SI1145_CHLIST_EN_ALSVIS; + break; + case SI1145_REG_ALSIR_DATA: + reg |= SI1145_CHLIST_EN_ALSIR; + break; + case SI1145_REG_PS1_DATA: + reg |= SI1145_CHLIST_EN_PS1; + break; + case SI1145_REG_PS2_DATA: + reg |= SI1145_CHLIST_EN_PS2; + break; + case SI1145_REG_PS3_DATA: + reg |= SI1145_CHLIST_EN_PS3; + break; + case SI1145_REG_AUX_DATA: + switch (indio_dev->channels[i].type) { + case IIO_UVINDEX: + reg |= SI1145_CHLIST_EN_UV; + break; + default: + reg |= SI1145_CHLIST_EN_AUX; + if (indio_dev->channels[i].type == IIO_TEMP) + mux = SI1145_MUX_TEMP; + else + mux = SI1145_MUX_VDD; + ret = si1145_param_set(data, + SI1145_PARAM_AUX_ADC_MUX, mux); + if (ret < 0) + return ret; + + break; + } + } + } + + data->scan_mask = scan_mask; + ret = si1145_param_set(data, SI1145_PARAM_CHLIST, reg); + + return ret < 0 ? ret : 0; +} + +static int si1145_measure(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan) +{ + struct si1145_data *data = iio_priv(indio_dev); + u8 cmd; + int ret; + + ret = si1145_set_chlist(indio_dev, BIT(chan->scan_index)); + if (ret < 0) + return ret; + + cmd = (chan->type == IIO_PROXIMITY) ? SI1145_CMD_PS_FORCE : + SI1145_CMD_ALS_FORCE; + ret = si1145_command(data, cmd); + if (ret < 0 && ret != -EOVERFLOW) + return ret; + + return i2c_smbus_read_word_data(data->client, chan->address); +} + +/* + * Conversion between iio scale and ADC_GAIN values + * These could be further adjusted but proximity/intensity are dimensionless + */ +static const int si1145_proximity_scale_available[] = { + 128, 64, 32, 16, 8, 4}; +static const int si1145_intensity_scale_available[] = { + 128, 64, 32, 16, 8, 4, 2, 1}; +static IIO_CONST_ATTR(in_proximity_scale_available, + "128 64 32 16 8 4"); +static IIO_CONST_ATTR(in_intensity_scale_available, + "128 64 32 16 8 4 2 1"); +static IIO_CONST_ATTR(in_intensity_ir_scale_available, + "128 64 32 16 8 4 2 1"); + +static int si1145_scale_from_adcgain(int regval) +{ + return 128 >> regval; +} + +static int si1145_proximity_adcgain_from_scale(int val, int val2) +{ + val = find_closest_descending(val, si1145_proximity_scale_available, + ARRAY_SIZE(si1145_proximity_scale_available)); + if (val < 0 || val > 5 || val2 != 0) + return -EINVAL; + + return val; +} + +static int si1145_intensity_adcgain_from_scale(int val, int val2) +{ + val = find_closest_descending(val, si1145_intensity_scale_available, + ARRAY_SIZE(si1145_intensity_scale_available)); + if (val < 0 || val > 7 || val2 != 0) + return -EINVAL; + + return val; +} + +static int si1145_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct si1145_data *data = iio_priv(indio_dev); + int ret; + u8 reg; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + switch (chan->type) { + case IIO_INTENSITY: + case IIO_PROXIMITY: + case IIO_VOLTAGE: + case IIO_TEMP: + case IIO_UVINDEX: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + ret = si1145_measure(indio_dev, chan); + iio_device_release_direct_mode(indio_dev); + + if (ret < 0) + return ret; + + *val = ret; + + return IIO_VAL_INT; + case IIO_CURRENT: + ret = i2c_smbus_read_byte_data(data->client, + SI1145_PS_LED_REG(chan->channel)); + if (ret < 0) + return ret; + + *val = (ret >> SI1145_PS_LED_SHIFT(chan->channel)) + & 0x0f; + + return IIO_VAL_INT; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_PROXIMITY: + reg = SI1145_PARAM_PS_ADC_GAIN; + break; + case IIO_INTENSITY: + if (chan->channel2 == IIO_MOD_LIGHT_IR) + reg = SI1145_PARAM_ALSIR_ADC_GAIN; + else + reg = SI1145_PARAM_ALSVIS_ADC_GAIN; + break; + case IIO_TEMP: + *val = 28; + *val2 = 571429; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_UVINDEX: + *val = 0; + *val2 = 10000; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } + + ret = si1145_param_query(data, reg); + if (ret < 0) + return ret; + + *val = si1145_scale_from_adcgain(ret & 0x07); + + return IIO_VAL_INT; + case IIO_CHAN_INFO_OFFSET: + switch (chan->type) { + case IIO_TEMP: + /* + * -ADC offset - ADC counts @ 25°C - + * 35 * ADC counts / °C + */ + *val = -256 - 11136 + 25 * 35; + return IIO_VAL_INT; + default: + /* + * All ADC measurements have are by default offset + * by -256 + * See AN498 5.6.3 + */ + ret = si1145_param_query(data, SI1145_PARAM_ADC_OFFSET); + if (ret < 0) + return ret; + *val = -si1145_uncompress(ret); + return IIO_VAL_INT; + } + case IIO_CHAN_INFO_SAMP_FREQ: + return si1145_read_samp_freq(data, val, val2); + default: + return -EINVAL; + } +} + +static int si1145_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct si1145_data *data = iio_priv(indio_dev); + u8 reg1, reg2, shift; + int ret; + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_PROXIMITY: + val = si1145_proximity_adcgain_from_scale(val, val2); + if (val < 0) + return val; + reg1 = SI1145_PARAM_PS_ADC_GAIN; + reg2 = SI1145_PARAM_PS_ADC_COUNTER; + break; + case IIO_INTENSITY: + val = si1145_intensity_adcgain_from_scale(val, val2); + if (val < 0) + return val; + if (chan->channel2 == IIO_MOD_LIGHT_IR) { + reg1 = SI1145_PARAM_ALSIR_ADC_GAIN; + reg2 = SI1145_PARAM_ALSIR_ADC_COUNTER; + } else { + reg1 = SI1145_PARAM_ALSVIS_ADC_GAIN; + reg2 = SI1145_PARAM_ALSVIS_ADC_COUNTER; + } + break; + default: + return -EINVAL; + } + + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + + ret = si1145_param_set(data, reg1, val); + if (ret < 0) { + iio_device_release_direct_mode(indio_dev); + return ret; + } + /* Set recovery period to one's complement of gain */ + ret = si1145_param_set(data, reg2, (~val & 0x07) << 4); + iio_device_release_direct_mode(indio_dev); + return ret; + case IIO_CHAN_INFO_RAW: + if (chan->type != IIO_CURRENT) + return -EINVAL; + + if (val < 0 || val > 15 || val2 != 0) + return -EINVAL; + + reg1 = SI1145_PS_LED_REG(chan->channel); + shift = SI1145_PS_LED_SHIFT(chan->channel); + + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + + ret = i2c_smbus_read_byte_data(data->client, reg1); + if (ret < 0) { + iio_device_release_direct_mode(indio_dev); + return ret; + } + ret = i2c_smbus_write_byte_data(data->client, reg1, + (ret & ~(0x0f << shift)) | + ((val & 0x0f) << shift)); + iio_device_release_direct_mode(indio_dev); + return ret; + case IIO_CHAN_INFO_SAMP_FREQ: + return si1145_store_samp_freq(data, val); + default: + return -EINVAL; + } +} + +#define SI1145_ST { \ + .sign = 'u', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_LE, \ +} + +#define SI1145_INTENSITY_CHANNEL(_si) { \ + .type = IIO_INTENSITY, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_OFFSET) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_type = SI1145_ST, \ + .scan_index = _si, \ + .address = SI1145_REG_ALSVIS_DATA, \ +} + +#define SI1145_INTENSITY_IR_CHANNEL(_si) { \ + .type = IIO_INTENSITY, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_OFFSET) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .modified = 1, \ + .channel2 = IIO_MOD_LIGHT_IR, \ + .scan_type = SI1145_ST, \ + .scan_index = _si, \ + .address = SI1145_REG_ALSIR_DATA, \ +} + +#define SI1145_TEMP_CHANNEL(_si) { \ + .type = IIO_TEMP, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_OFFSET) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_type = SI1145_ST, \ + .scan_index = _si, \ + .address = SI1145_REG_AUX_DATA, \ +} + +#define SI1145_UV_CHANNEL(_si) { \ + .type = IIO_UVINDEX, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_type = SI1145_ST, \ + .scan_index = _si, \ + .address = SI1145_REG_AUX_DATA, \ +} + +#define SI1145_PROXIMITY_CHANNEL(_si, _ch) { \ + .type = IIO_PROXIMITY, \ + .indexed = 1, \ + .channel = _ch, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_OFFSET), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_type = SI1145_ST, \ + .scan_index = _si, \ + .address = SI1145_REG_PS1_DATA + _ch * 2, \ +} + +#define SI1145_VOLTAGE_CHANNEL(_si) { \ + .type = IIO_VOLTAGE, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_type = SI1145_ST, \ + .scan_index = _si, \ + .address = SI1145_REG_AUX_DATA, \ +} + +#define SI1145_CURRENT_CHANNEL(_ch) { \ + .type = IIO_CURRENT, \ + .indexed = 1, \ + .channel = _ch, \ + .output = 1, \ + .scan_index = -1, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ +} + +static const struct iio_chan_spec si1132_channels[] = { + SI1145_INTENSITY_CHANNEL(0), + SI1145_INTENSITY_IR_CHANNEL(1), + SI1145_TEMP_CHANNEL(2), + SI1145_VOLTAGE_CHANNEL(3), + SI1145_UV_CHANNEL(4), + IIO_CHAN_SOFT_TIMESTAMP(6), +}; + +static const struct iio_chan_spec si1141_channels[] = { + SI1145_INTENSITY_CHANNEL(0), + SI1145_INTENSITY_IR_CHANNEL(1), + SI1145_PROXIMITY_CHANNEL(2, 0), + SI1145_TEMP_CHANNEL(3), + SI1145_VOLTAGE_CHANNEL(4), + IIO_CHAN_SOFT_TIMESTAMP(5), + SI1145_CURRENT_CHANNEL(0), +}; + +static const struct iio_chan_spec si1142_channels[] = { + SI1145_INTENSITY_CHANNEL(0), + SI1145_INTENSITY_IR_CHANNEL(1), + SI1145_PROXIMITY_CHANNEL(2, 0), + SI1145_PROXIMITY_CHANNEL(3, 1), + SI1145_TEMP_CHANNEL(4), + SI1145_VOLTAGE_CHANNEL(5), + IIO_CHAN_SOFT_TIMESTAMP(6), + SI1145_CURRENT_CHANNEL(0), + SI1145_CURRENT_CHANNEL(1), +}; + +static const struct iio_chan_spec si1143_channels[] = { + SI1145_INTENSITY_CHANNEL(0), + SI1145_INTENSITY_IR_CHANNEL(1), + SI1145_PROXIMITY_CHANNEL(2, 0), + SI1145_PROXIMITY_CHANNEL(3, 1), + SI1145_PROXIMITY_CHANNEL(4, 2), + SI1145_TEMP_CHANNEL(5), + SI1145_VOLTAGE_CHANNEL(6), + IIO_CHAN_SOFT_TIMESTAMP(7), + SI1145_CURRENT_CHANNEL(0), + SI1145_CURRENT_CHANNEL(1), + SI1145_CURRENT_CHANNEL(2), +}; + +static const struct iio_chan_spec si1145_channels[] = { + SI1145_INTENSITY_CHANNEL(0), + SI1145_INTENSITY_IR_CHANNEL(1), + SI1145_PROXIMITY_CHANNEL(2, 0), + SI1145_TEMP_CHANNEL(3), + SI1145_VOLTAGE_CHANNEL(4), + SI1145_UV_CHANNEL(5), + IIO_CHAN_SOFT_TIMESTAMP(6), + SI1145_CURRENT_CHANNEL(0), +}; + +static const struct iio_chan_spec si1146_channels[] = { + SI1145_INTENSITY_CHANNEL(0), + SI1145_INTENSITY_IR_CHANNEL(1), + SI1145_TEMP_CHANNEL(2), + SI1145_VOLTAGE_CHANNEL(3), + SI1145_UV_CHANNEL(4), + SI1145_PROXIMITY_CHANNEL(5, 0), + SI1145_PROXIMITY_CHANNEL(6, 1), + IIO_CHAN_SOFT_TIMESTAMP(7), + SI1145_CURRENT_CHANNEL(0), + SI1145_CURRENT_CHANNEL(1), +}; + +static const struct iio_chan_spec si1147_channels[] = { + SI1145_INTENSITY_CHANNEL(0), + SI1145_INTENSITY_IR_CHANNEL(1), + SI1145_PROXIMITY_CHANNEL(2, 0), + SI1145_PROXIMITY_CHANNEL(3, 1), + SI1145_PROXIMITY_CHANNEL(4, 2), + SI1145_TEMP_CHANNEL(5), + SI1145_VOLTAGE_CHANNEL(6), + SI1145_UV_CHANNEL(7), + IIO_CHAN_SOFT_TIMESTAMP(8), + SI1145_CURRENT_CHANNEL(0), + SI1145_CURRENT_CHANNEL(1), + SI1145_CURRENT_CHANNEL(2), +}; + +static struct attribute *si1132_attributes[] = { + &iio_const_attr_in_intensity_scale_available.dev_attr.attr, + &iio_const_attr_in_intensity_ir_scale_available.dev_attr.attr, + NULL, +}; + +static struct attribute *si114x_attributes[] = { + &iio_const_attr_in_intensity_scale_available.dev_attr.attr, + &iio_const_attr_in_intensity_ir_scale_available.dev_attr.attr, + &iio_const_attr_in_proximity_scale_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group si1132_attribute_group = { + .attrs = si1132_attributes, +}; + +static const struct attribute_group si114x_attribute_group = { + .attrs = si114x_attributes, +}; + + +static const struct iio_info si1132_info = { + .read_raw = si1145_read_raw, + .write_raw = si1145_write_raw, + .driver_module = THIS_MODULE, + .attrs = &si1132_attribute_group, +}; + +static const struct iio_info si114x_info = { + .read_raw = si1145_read_raw, + .write_raw = si1145_write_raw, + .driver_module = THIS_MODULE, + .attrs = &si114x_attribute_group, +}; + +#define SI1145_PART(id, iio_info, chans, leds, uncompressed_meas_rate) \ + {id, iio_info, chans, ARRAY_SIZE(chans), leds, uncompressed_meas_rate} + +static const struct si1145_part_info si1145_part_info[] = { + [SI1132] = SI1145_PART(0x32, &si1132_info, si1132_channels, 0, true), + [SI1141] = SI1145_PART(0x41, &si114x_info, si1141_channels, 1, false), + [SI1142] = SI1145_PART(0x42, &si114x_info, si1142_channels, 2, false), + [SI1143] = SI1145_PART(0x43, &si114x_info, si1143_channels, 3, false), + [SI1145] = SI1145_PART(0x45, &si114x_info, si1145_channels, 1, true), + [SI1146] = SI1145_PART(0x46, &si114x_info, si1146_channels, 2, true), + [SI1147] = SI1145_PART(0x47, &si114x_info, si1147_channels, 3, true), +}; + +static int si1145_initialize(struct si1145_data *data) +{ + struct i2c_client *client = data->client; + int ret; + + ret = i2c_smbus_write_byte_data(client, SI1145_REG_COMMAND, + SI1145_CMD_RESET); + if (ret < 0) + return ret; + msleep(SI1145_COMMAND_TIMEOUT_MS); + + /* Hardware key, magic value */ + ret = i2c_smbus_write_byte_data(client, SI1145_REG_HW_KEY, 0x17); + if (ret < 0) + return ret; + msleep(SI1145_COMMAND_TIMEOUT_MS); + + /* Turn off autonomous mode */ + ret = si1145_set_meas_rate(data, 0); + if (ret < 0) + return ret; + + /* Initialize sampling freq to 10 Hz */ + ret = si1145_store_samp_freq(data, 10); + if (ret < 0) + return ret; + + /* Set LED currents to 45 mA; have 4 bits, see Table 2 in datasheet */ + switch (data->part_info->num_leds) { + case 3: + ret = i2c_smbus_write_byte_data(client, + SI1145_REG_PS_LED3, + SI1145_LED_CURRENT_45mA); + if (ret < 0) + return ret; + /* fallthrough */ + case 2: + ret = i2c_smbus_write_byte_data(client, + SI1145_REG_PS_LED21, + (SI1145_LED_CURRENT_45mA << 4) | + SI1145_LED_CURRENT_45mA); + break; + case 1: + ret = i2c_smbus_write_byte_data(client, + SI1145_REG_PS_LED21, + SI1145_LED_CURRENT_45mA); + break; + default: + ret = 0; + break; + } + if (ret < 0) + return ret; + + /* Set normal proximity measurement mode */ + ret = si1145_param_set(data, SI1145_PARAM_PS_ADC_MISC, + SI1145_PS_ADC_MODE_NORMAL); + if (ret < 0) + return ret; + + ret = si1145_param_set(data, SI1145_PARAM_PS_ADC_GAIN, 0x01); + if (ret < 0) + return ret; + + /* ADC_COUNTER should be one complement of ADC_GAIN */ + ret = si1145_param_set(data, SI1145_PARAM_PS_ADC_COUNTER, 0x06 << 4); + if (ret < 0) + return ret; + + /* Set ALS visible measurement mode */ + ret = si1145_param_set(data, SI1145_PARAM_ALSVIS_ADC_MISC, + SI1145_ADC_MISC_RANGE); + if (ret < 0) + return ret; + + ret = si1145_param_set(data, SI1145_PARAM_ALSVIS_ADC_GAIN, 0x03); + if (ret < 0) + return ret; + + ret = si1145_param_set(data, SI1145_PARAM_ALSVIS_ADC_COUNTER, + 0x04 << 4); + if (ret < 0) + return ret; + + /* Set ALS IR measurement mode */ + ret = si1145_param_set(data, SI1145_PARAM_ALSIR_ADC_MISC, + SI1145_ADC_MISC_RANGE); + if (ret < 0) + return ret; + + ret = si1145_param_set(data, SI1145_PARAM_ALSIR_ADC_GAIN, 0x01); + if (ret < 0) + return ret; + + ret = si1145_param_set(data, SI1145_PARAM_ALSIR_ADC_COUNTER, + 0x06 << 4); + if (ret < 0) + return ret; + + /* + * Initialize UCOEF to default values in datasheet + * These registers are normally zero on reset + */ + if (data->part_info == &si1145_part_info[SI1132] || + data->part_info == &si1145_part_info[SI1145] || + data->part_info == &si1145_part_info[SI1146] || + data->part_info == &si1145_part_info[SI1147]) { + ret = i2c_smbus_write_byte_data(data->client, + SI1145_REG_UCOEF1, + SI1145_UCOEF1_DEFAULT); + if (ret < 0) + return ret; + ret = i2c_smbus_write_byte_data(data->client, + SI1145_REG_UCOEF2, SI1145_UCOEF2_DEFAULT); + if (ret < 0) + return ret; + ret = i2c_smbus_write_byte_data(data->client, + SI1145_REG_UCOEF3, SI1145_UCOEF3_DEFAULT); + if (ret < 0) + return ret; + ret = i2c_smbus_write_byte_data(data->client, + SI1145_REG_UCOEF4, SI1145_UCOEF4_DEFAULT); + if (ret < 0) + return ret; + } + + return 0; +} + +/* + * Program the channels we want to measure with CMD_PSALS_AUTO. No need for + * _postdisable as we stop with CMD_PSALS_PAUSE; single measurement (direct) + * mode reprograms the channels list anyway... + */ +static int si1145_buffer_preenable(struct iio_dev *indio_dev) +{ + struct si1145_data *data = iio_priv(indio_dev); + int ret; + + mutex_lock(&data->lock); + ret = si1145_set_chlist(indio_dev, *indio_dev->active_scan_mask); + mutex_unlock(&data->lock); + + return ret; +} + +static bool si1145_validate_scan_mask(struct iio_dev *indio_dev, + const unsigned long *scan_mask) +{ + struct si1145_data *data = iio_priv(indio_dev); + unsigned int count = 0; + int i; + + /* Check that at most one AUX channel is enabled */ + for_each_set_bit(i, scan_mask, data->part_info->num_channels) { + if (indio_dev->channels[i].address == SI1145_REG_AUX_DATA) + count++; + } + + return count <= 1; +} + +static const struct iio_buffer_setup_ops si1145_buffer_setup_ops = { + .preenable = si1145_buffer_preenable, + .postenable = iio_triggered_buffer_postenable, + .predisable = iio_triggered_buffer_predisable, + .validate_scan_mask = si1145_validate_scan_mask, +}; + +/** + * si1145_trigger_set_state() - Set trigger state + * + * When not using triggers interrupts are disabled and measurement rate is + * set to zero in order to minimize power consumption. + */ +static int si1145_trigger_set_state(struct iio_trigger *trig, bool state) +{ + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); + struct si1145_data *data = iio_priv(indio_dev); + int err = 0, ret; + + mutex_lock(&data->lock); + + if (state) { + data->autonomous = true; + err = i2c_smbus_write_byte_data(data->client, + SI1145_REG_INT_CFG, SI1145_INT_CFG_OE); + if (err < 0) + goto disable; + err = i2c_smbus_write_byte_data(data->client, + SI1145_REG_IRQ_ENABLE, SI1145_MASK_ALL_IE); + if (err < 0) + goto disable; + err = si1145_set_meas_rate(data, data->meas_rate); + if (err < 0) + goto disable; + err = si1145_command(data, SI1145_CMD_PSALS_AUTO); + if (err < 0) + goto disable; + } else { +disable: + /* Disable as much as possible skipping errors */ + ret = si1145_command(data, SI1145_CMD_PSALS_PAUSE); + if (ret < 0 && !err) + err = ret; + ret = si1145_set_meas_rate(data, 0); + if (ret < 0 && !err) + err = ret; + ret = i2c_smbus_write_byte_data(data->client, + SI1145_REG_IRQ_ENABLE, 0); + if (ret < 0 && !err) + err = ret; + ret = i2c_smbus_write_byte_data(data->client, + SI1145_REG_INT_CFG, 0); + if (ret < 0 && !err) + err = ret; + data->autonomous = false; + } + + mutex_unlock(&data->lock); + return err; +} + +static const struct iio_trigger_ops si1145_trigger_ops = { + .owner = THIS_MODULE, + .set_trigger_state = si1145_trigger_set_state, +}; + +static int si1145_probe_trigger(struct iio_dev *indio_dev) +{ + struct si1145_data *data = iio_priv(indio_dev); + struct i2c_client *client = data->client; + struct iio_trigger *trig; + int ret; + + trig = devm_iio_trigger_alloc(&client->dev, + "%s-dev%d", indio_dev->name, indio_dev->id); + if (!trig) + return -ENOMEM; + + trig->dev.parent = &client->dev; + trig->ops = &si1145_trigger_ops; + iio_trigger_set_drvdata(trig, indio_dev); + + ret = devm_request_irq(&client->dev, client->irq, + iio_trigger_generic_data_rdy_poll, + IRQF_TRIGGER_FALLING, + "si1145_irq", + trig); + if (ret < 0) { + dev_err(&client->dev, "irq request failed\n"); + return ret; + } + + ret = iio_trigger_register(trig); + if (ret) + return ret; + + data->trig = trig; + indio_dev->trig = iio_trigger_get(data->trig); + + return 0; +} + +static void si1145_remove_trigger(struct iio_dev *indio_dev) +{ + struct si1145_data *data = iio_priv(indio_dev); + + if (data->trig) { + iio_trigger_unregister(data->trig); + data->trig = NULL; + } +} + +static int si1145_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct si1145_data *data; + struct iio_dev *indio_dev; + u8 part_id, rev_id, seq_id; + int ret; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + data->client = client; + data->part_info = &si1145_part_info[id->driver_data]; + + part_id = ret = i2c_smbus_read_byte_data(data->client, + SI1145_REG_PART_ID); + if (ret < 0) + return ret; + rev_id = ret = i2c_smbus_read_byte_data(data->client, + SI1145_REG_REV_ID); + if (ret < 0) + return ret; + seq_id = ret = i2c_smbus_read_byte_data(data->client, + SI1145_REG_SEQ_ID); + if (ret < 0) + return ret; + dev_info(&client->dev, "device ID part %#02hhx rev %#02hhx seq %#02hhx\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", + part_id, data->part_info->part); + return -ENODEV; + } + + indio_dev->dev.parent = &client->dev; + indio_dev->name = id->name; + indio_dev->channels = data->part_info->channels; + indio_dev->num_channels = data->part_info->num_channels; + indio_dev->info = data->part_info->iio_info; + indio_dev->modes = INDIO_DIRECT_MODE; + + mutex_init(&data->lock); + mutex_init(&data->cmdlock); + + ret = si1145_initialize(data); + if (ret < 0) + return ret; + + ret = iio_triggered_buffer_setup(indio_dev, NULL, + si1145_trigger_handler, &si1145_buffer_setup_ops); + if (ret < 0) + return ret; + + if (client->irq) { + ret = si1145_probe_trigger(indio_dev); + if (ret < 0) + goto error_free_buffer; + } else { + dev_info(&client->dev, "no irq, using polling\n"); + } + + ret = iio_device_register(indio_dev); + if (ret < 0) + goto error_free_trigger; + + return 0; + +error_free_trigger: + si1145_remove_trigger(indio_dev); +error_free_buffer: + iio_triggered_buffer_cleanup(indio_dev); + + return ret; +} + +static const struct i2c_device_id si1145_ids[] = { + { "si1132", SI1132 }, + { "si1141", SI1141 }, + { "si1142", SI1142 }, + { "si1143", SI1143 }, + { "si1145", SI1145 }, + { "si1146", SI1146 }, + { "si1147", SI1147 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, si1145_ids); + +static int si1145_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + + iio_device_unregister(indio_dev); + si1145_remove_trigger(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); + + return 0; +} + +static struct i2c_driver si1145_driver = { + .driver = { + .name = "si1145", + }, + .probe = si1145_probe, + .remove = si1145_remove, + .id_table = si1145_ids, +}; + +module_i2c_driver(si1145_driver); + +MODULE_AUTHOR("Peter Meerwald-Stadler <pmeerw@pmeerw.net>"); +MODULE_DESCRIPTION("Silabs SI1132 and SI1141/2/3/5/6/7 proximity, ambient light and UV index sensor driver"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From cfa4860592ba641077a439bf2848dcf57803f422 Mon Sep 17 00:00:00 2001 From: Li Xi <lixi@ddn.com> Date: Sun, 18 Sep 2016 16:37:00 -0400 Subject: staging: lustre: llite: fix ll_statahead_thread() problems on failure When ll_prep_md_op_data() fails, ll_statahead_thread() does not release reference of sai and parent dentry. It does not wake up parent thread either. This patch fixes these problems. Signed-off-by: Li Xi <lixi@ddn.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5274 Reviewed-on: http://review.whamcloud.com/10940 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Lai Siyao <lai.siyao@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c index 4ac0d6a..016463b 100644 --- a/drivers/staging/lustre/lustre/llite/statahead.c +++ b/drivers/staging/lustre/lustre/llite/statahead.c @@ -1050,8 +1050,10 @@ static int ll_statahead_thread(void *arg) op_data = ll_prep_md_op_data(NULL, dir, dir, NULL, 0, 0, LUSTRE_OPC_ANY, dir); - if (IS_ERR(op_data)) - return PTR_ERR(op_data); + if (IS_ERR(op_data)) { + rc = PTR_ERR(op_data); + goto out_put; + } op_data->op_max_pages = ll_i2sbi(dir)->ll_md_brw_pages; @@ -1239,7 +1241,9 @@ do_it: } } out: + ll_dir_chain_fini(&chain); ll_finish_md_op_data(op_data); +out_put: if (sai->sai_agl_valid) { spin_lock(&plli->lli_agl_lock); thread_set_flags(agl_thread, SVC_STOPPING); @@ -1255,7 +1259,6 @@ out: /* Set agl_thread flags anyway. */ thread_set_flags(&sai->sai_agl_thread, SVC_STOPPED); } - ll_dir_chain_fini(&chain); spin_lock(&plli->lli_sa_lock); if (!list_empty(&sai->sai_entries_received)) { thread_set_flags(thread, SVC_STOPPING); @@ -1272,9 +1275,9 @@ out: wake_up(&sai->sai_waitq); wake_up(&thread->t_ctl_waitq); ll_sai_put(sai); - dput(parent); CDEBUG(D_READA, "statahead thread stopped: sai %p, parent %pd\n", sai, parent); + dput(parent); return rc; } -- cgit v0.10.2 From 2e0ca344931997954443dbda26cfb409e7cd1f08 Mon Sep 17 00:00:00 2001 From: Li Xi <lixi@ddn.com> Date: Sun, 18 Sep 2016 16:37:01 -0400 Subject: staging: lustre: ptlrpc: enlarge OST_MAXREQSIZE for 4MB RPC This patch enlarges OST_MAXREQSIZE so as to make the request size large enough for 4MB RPC. Signed-off-by: Li Xi <lixi@ddn.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4755 Reviewed-on: http://review.whamcloud.com/9599 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre_net.h b/drivers/staging/lustre/lustre/include/lustre_net.h index 24ddccab..6d82998 100644 --- a/drivers/staging/lustre/lustre/include/lustre_net.h +++ b/drivers/staging/lustre/lustre/include/lustre_net.h @@ -261,7 +261,10 @@ #define MDS_MAXREQSIZE (5 * 1024) /* >= 4736 */ -#define OST_MAXREQSIZE (5 * 1024) +/** + * FIEMAP request can be 4K+ for now + */ +#define OST_MAXREQSIZE (16 * 1024) /* Macro to hide a typecast. */ #define ptlrpc_req_async_args(req) ((void *)&req->rq_async_args) -- cgit v0.10.2 From cde5f1097356568492257a550766e45264cfa923 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Sun, 18 Sep 2016 16:37:02 -0400 Subject: staging: lustre: ldlm: fix a use after free in ldlm_resource_get() If lvbo initialization has failed then save the return status (from lr_lvb_len) before putting the resource. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5305 Reviewed-on: http://review.whamcloud.com/11017 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Emoly Liu <emoly.liu@intel.com> Reviewed-by: Dmitry Eremin <dmitry.eremin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c index 62d9f6f..912cd68 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c @@ -1091,6 +1091,7 @@ ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent, struct cfs_hash_bd bd; __u64 version; int ns_refcount = 0; + int rc; LASSERT(!parent); LASSERT(ns->ns_rs_hash); @@ -1140,8 +1141,9 @@ lvbo_init: } if (unlikely(res->lr_lvb_len < 0)) { + rc = res->lr_lvb_len; ldlm_resource_putref(res); - res = ERR_PTR(res->lr_lvb_len); + res = ERR_PTR(rc); } return res; } @@ -1152,8 +1154,6 @@ lvbo_init: cfs_hash_bd_unlock(ns->ns_rs_hash, &bd, 1); if (ns->ns_lvbo && ns->ns_lvbo->lvbo_init) { - int rc; - OBD_FAIL_TIMEOUT(OBD_FAIL_LDLM_CREATE_RESOURCE, 2); rc = ns->ns_lvbo->lvbo_init(res); if (rc < 0) { -- cgit v0.10.2 From 1d62e09c2dd3c74e9244e550f2197f075999b0e1 Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Sun, 18 Sep 2016 16:37:03 -0400 Subject: staging: lustre: lmv: honor MDT index when creating volatile file LMV should honor MDT index embedded in the name of volatile file, then during hsm restore, the file under striped dir can be restored to the right MDT. Signed-off-by: wang di <di.wang@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4691 Reviewed-on: http://review.whamcloud.com/10866 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Henri Doreau <henri.doreau@cea.fr> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index 351fb4c..c69918b 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -244,6 +244,7 @@ struct ost_id { #define LL_IOC_HSM_IMPORT _IOWR('f', 245, struct hsm_user_import) #define LL_IOC_LMV_SET_DEFAULT_STRIPE _IOWR('f', 246, struct lmv_user_md) #define LL_IOC_MIGRATE _IOR('f', 247, int) +#define LL_IOC_FID2MDTIDX _IOWR('f', 248, struct lu_fid) #define LL_STATFS_LMV 1 #define LL_STATFS_LOV 2 diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 532047b..c97a4a0 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -1568,6 +1568,23 @@ out_quotactl: return rc; case OBD_IOC_FID2PATH: return ll_fid2path(inode, (void __user *)arg); + case LL_IOC_FID2MDTIDX: { + struct obd_export *exp = ll_i2mdexp(inode); + struct lu_fid fid; + __u32 index; + + if (copy_from_user(&fid, (const struct lu_fid __user *)arg, + sizeof(fid))) + return -EFAULT; + + /* Call mdc_iocontrol */ + rc = obd_iocontrol(LL_IOC_FID2MDTIDX, exp, sizeof(fid), &fid, + &index); + if (rc) + return rc; + + return index; + } case LL_IOC_HSM_REQUEST: { struct hsm_user_request *hur; ssize_t totalsize; diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 1ff788e..99aba6b 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -2373,9 +2373,10 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, op_data->op_bias = 0; op_data->op_cli_flags = 0; if ((opc == LUSTRE_OPC_CREATE) && name && - filename_is_volatile(name, namelen, NULL)) + filename_is_volatile(name, namelen, &op_data->op_mds)) op_data->op_bias |= MDS_CREATE_VOLATILE; - op_data->op_mds = 0; + else + op_data->op_mds = 0; op_data->op_data = data; /* When called by ll_setattr_raw, file is i1. */ diff --git a/drivers/staging/lustre/lustre/lmv/lmv_fld.c b/drivers/staging/lustre/lustre/lmv/lmv_fld.c index a3d170a..a5265f9 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_fld.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_fld.c @@ -47,18 +47,20 @@ #include "../include/lprocfs_status.h" #include "lmv_internal.h" -int lmv_fld_lookup(struct lmv_obd *lmv, - const struct lu_fid *fid, - u32 *mds) +int lmv_fld_lookup(struct lmv_obd *lmv, const struct lu_fid *fid, u32 *mds) { + struct obd_device *obd = lmv2obd_dev(lmv); int rc; - /* FIXME: Currently ZFS still use local seq for ROOT unfortunately, and + /* + * FIXME: Currently ZFS still use local seq for ROOT unfortunately, and * this fid_is_local check should be removed once LU-2240 is fixed */ - LASSERTF((fid_seq_in_fldb(fid_seq(fid)) || - fid_seq_is_local_file(fid_seq(fid))) && - fid_is_sane(fid), DFID" is insane!\n", PFID(fid)); + if (!fid_is_sane(fid) || !(fid_seq_in_fldb(fid_seq(fid)) || + fid_seq_is_local_file(fid_seq(fid)))) { + CERROR("%s: invalid FID " DFID "\n", obd->obd_name, PFID(fid)); + return -EINVAL; + } rc = fld_client_lookup(&lmv->lmv_fld, fid_seq(fid), mds, LU_SEQ_RANGE_MDT, NULL); diff --git a/drivers/staging/lustre/lustre/lmv/lmv_internal.h b/drivers/staging/lustre/lustre/lmv/lmv_internal.h index c4961d9..4a5e385 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_internal.h +++ b/drivers/staging/lustre/lustre/lmv/lmv_internal.h @@ -62,6 +62,11 @@ int lmv_revalidate_slaves(struct obd_export *exp, struct mdt_body *mbody, ldlm_blocking_callback cb_blocking, int extra_lock_flags); +static inline struct obd_device *lmv2obd_dev(struct lmv_obd *lmv) +{ + return container_of0(lmv, struct obd_device, u.lmv); +} + static inline struct lmv_tgt_desc * lmv_get_target(struct lmv_obd *lmv, u32 mdt_idx, int *index) { diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 0713e55..1d53c76 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -1073,6 +1073,21 @@ static int lmv_iocontrol(unsigned int cmd, struct obd_export *exp, rc = obd_iocontrol(cmd, tgt->ltd_exp, len, karg, uarg); break; } + case LL_IOC_FID2MDTIDX: { + struct lu_fid *fid = karg; + int mdt_index; + + rc = lmv_fld_lookup(lmv, fid, &mdt_index); + if (rc) + return rc; + + /* + * Note: this is from llite(see ll_dir_ioctl()), @uarg does not + * point to user space memory for FID2MDTIDX. + */ + *(__u32 *)uarg = mdt_index; + break; + } case OBD_IOC_FID2PATH: { rc = lmv_fid2path(exp, len, karg, uarg); break; @@ -1671,13 +1686,44 @@ lmv_locate_target_for_name(struct lmv_obd *lmv, struct lmv_stripe_md *lsm, * retval pointer to the lmv_tgt_desc if succeed. * ERR_PTR(errno) if failed. */ -struct lmv_tgt_desc -*lmv_locate_mds(struct lmv_obd *lmv, struct md_op_data *op_data, - struct lu_fid *fid) +struct lmv_tgt_desc* +lmv_locate_mds(struct lmv_obd *lmv, struct md_op_data *op_data, + struct lu_fid *fid) { struct lmv_stripe_md *lsm = op_data->op_mea1; struct lmv_tgt_desc *tgt; + /* + * During creating VOLATILE file, it should honor the mdt + * index if the file under striped dir is being restored, see + * ct_restore(). + */ + if (op_data->op_bias & MDS_CREATE_VOLATILE && + (int)op_data->op_mds != -1 && lsm) { + int i; + + tgt = lmv_get_target(lmv, op_data->op_mds, NULL); + if (IS_ERR(tgt)) + return tgt; + + /* refill the right parent fid */ + for (i = 0; i < lsm->lsm_md_stripe_count; i++) { + struct lmv_oinfo *oinfo; + + oinfo = &lsm->lsm_md_oinfo[i]; + if (oinfo->lmo_mds == op_data->op_mds) { + *fid = oinfo->lmo_fid; + break; + } + } + + /* Hmm, can not find the stripe by mdt_index(op_mds) */ + if (i == lsm->lsm_md_stripe_count) + tgt = ERR_PTR(-EINVAL); + + return tgt; + } + if (!lsm || !op_data->op_namelen) { tgt = lmv_find_target(lmv, fid); if (IS_ERR(tgt)) -- cgit v0.10.2 From 2e1ff4515adf956a47d98b2a711e2775f2406d44 Mon Sep 17 00:00:00 2001 From: Alexander Zarochentsev <alexander_zarochentsev@xyratex.com> Date: Sun, 18 Sep 2016 16:37:04 -0400 Subject: staging: lustre: obdclass: optimize busy loop wait two optimizations in the busy loop wait in class_cleanup(): (1) remove unnecessary spinlocks protecting obd_conn_inprogress access (2) replace cond_resched by more suitable yield to unconditionally yield the CPU if the condition check fails. Signed-off-by: Alexander Zarochentsev <alexander_zarochentsev@xyratex.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5397 Xyratex-bug-id: MRP-1991 Reviewed-on: http://review.whamcloud.com/11198 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Dmitry Eremin <dmitry.eremin@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/obdclass/obd_config.c b/drivers/staging/lustre/lustre/obdclass/obd_config.c index 036f396..fddfc9c 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_config.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_config.c @@ -414,17 +414,12 @@ static int class_cleanup(struct obd_device *obd, struct lustre_cfg *lcfg) } /* Leave this on forever */ obd->obd_stopping = 1; - - /* wait for already-arrived-connections to finish. */ - while (obd->obd_conn_inprogress > 0) { - spin_unlock(&obd->obd_dev_lock); - - cond_resched(); - - spin_lock(&obd->obd_dev_lock); - } spin_unlock(&obd->obd_dev_lock); + while (obd->obd_conn_inprogress > 0) + yield(); + smp_rmb(); + if (lcfg->lcfg_bufcount >= 2 && LUSTRE_CFG_BUFLEN(lcfg, 1) > 0) { for (flag = lustre_cfg_string(lcfg, 1); *flag != 0; flag++) switch (*flag) { -- cgit v0.10.2 From feefbe04ff2e72acbf9bff7b9b3e123a253d3869 Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Sun, 18 Sep 2016 16:37:05 -0400 Subject: staging: lustre: lmv: Do not ignore ENOENT in lmv_unlink Return correct value (rc) in lmv_unlink. In lmv_unlink, -ENOENT might be ingored for local directory unlink. Signed-off-by: wang di <di.wang@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5371 Reviewed-on: http://review.whamcloud.com/11170 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 1d53c76..fb5ddd7 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -2641,7 +2641,7 @@ try_next_stripe: /* Not cross-ref case, just get out of here. */ if (likely(!(body->mbo_valid & OBD_MD_MDS))) - return 0; + return rc; CDEBUG(D_INODE, "%s: try unlink to another MDT for "DFID"\n", exp->exp_obd->obd_name, PFID(&body->mbo_fid1)); -- cgit v0.10.2 From 485154db5e7711424f17fe5fd4d209f1571521c8 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Sun, 18 Sep 2016 16:37:06 -0400 Subject: staging: lustre: obd: add lnb_ prefix to members of struct niobuf_local Add the prefix lnb_ to the members of struct niobuf_local that do not already have it. Change the struct dentry *lnb_dentry member to void *lnb_data as it is not used to hold a pointer to struct dentry. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5061 Reviewed-on: http://review.whamcloud.com/10451 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Mike Pershin <mike.pershin@intel.com> Reviewed-by: Alex Zhuravlev <alexey.zhuravlev@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index f3d141b..f55e679 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -437,11 +437,11 @@ struct lmv_obd { struct niobuf_local { __u64 lnb_file_offset; __u32 lnb_page_offset; - __u32 len; - __u32 flags; - struct page *page; - struct dentry *dentry; - int rc; + __u32 lnb_len; + __u32 lnb_flags; + struct page *lnb_page; + void *lnb_data; + int lnb_rc; }; #define LUSTRE_FLD_NAME "fld" diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index 7527112..e7c492e 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -1452,14 +1452,14 @@ static int echo_client_prep_commit(const struct lu_env *env, LASSERT(lpages == npages); for (i = 0; i < lpages; i++) { - struct page *page = lnb[i].page; + struct page *page = lnb[i].lnb_page; /* read past eof? */ - if (!page && lnb[i].rc == 0) + if (!page && lnb[i].lnb_rc == 0) continue; if (async) - lnb[i].flags |= OBD_BRW_ASYNC; + lnb[i].lnb_flags |= OBD_BRW_ASYNC; if (ostid_id(&oa->o_oi) == ECHO_PERSISTENT_OBJID || (oa->o_valid & OBD_MD_FLFLAGS) == 0 || -- cgit v0.10.2 From 638814f6cdaaa20b9db362ae436ca11283dac98b Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Sun, 18 Sep 2016 16:37:07 -0400 Subject: staging: lustre: obd: add rnb_ prefix to struct niobuf_remote members Add the prefix rnb_ to the members of struct niobuf_remote. Delete the relevant compat macros from ofd_internal.h. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5061 Reviewed-on: http://review.whamcloud.com/10452 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Mike Pershin <mike.pershin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 3a0feac..6ff6615 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -1803,9 +1803,9 @@ void lustre_swab_obd_ioobj(struct obd_ioobj *ioo); /* multiple of 8 bytes => can array */ struct niobuf_remote { - __u64 offset; - __u32 len; - __u32 flags; + __u64 rnb_offset; + __u32 rnb_len; + __u32 rnb_flags; }; void lustre_swab_niobuf_remote(struct niobuf_remote *nbr); diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index e7c492e..6968953 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -1437,9 +1437,9 @@ static int echo_client_prep_commit(const struct lu_env *env, npages = tot_pages; for (i = 0; i < npages; i++, off += PAGE_SIZE) { - rnb[i].offset = off; - rnb[i].len = PAGE_SIZE; - rnb[i].flags = brw_flags; + rnb[i].rnb_offset = off; + rnb[i].rnb_len = PAGE_SIZE; + rnb[i].rnb_flags = brw_flags; } ioo.ioo_bufcnt = npages; @@ -1469,13 +1469,13 @@ static int echo_client_prep_commit(const struct lu_env *env, if (rw == OBD_BRW_WRITE) echo_client_page_debug_setup(page, rw, ostid_id(&oa->o_oi), - rnb[i].offset, - rnb[i].len); + rnb[i].rnb_offset, + rnb[i].rnb_len); else echo_client_page_debug_check(page, ostid_id(&oa->o_oi), - rnb[i].offset, - rnb[i].len); + rnb[i].rnb_offset, + rnb[i].rnb_len); } ret = obd_commitrw(env, rw, exp, oa, 1, &ioo, diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index bdb329d..e861973 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -1335,11 +1335,11 @@ static int osc_brw_prep_request(int cmd, struct client_obd *cli, if (i > 0 && can_merge_pages(pg_prev, pg)) { niobuf--; - niobuf->len += pg->count; + niobuf->rnb_len += pg->count; } else { - niobuf->offset = pg->off; - niobuf->len = pg->count; - niobuf->flags = pg->flag; + niobuf->rnb_offset = pg->off; + niobuf->rnb_len = pg->count; + niobuf->rnb_flags = pg->flag; } pg_prev = pg; } diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index 2cf3a51..102f0aa 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -1604,9 +1604,9 @@ EXPORT_SYMBOL(lustre_swab_obd_ioobj); void lustre_swab_niobuf_remote(struct niobuf_remote *nbr) { - __swab64s(&nbr->offset); - __swab32s(&nbr->len); - __swab32s(&nbr->flags); + __swab64s(&nbr->rnb_offset); + __swab32s(&nbr->rnb_len); + __swab32s(&nbr->rnb_flags); } EXPORT_SYMBOL(lustre_swab_niobuf_remote); @@ -2061,7 +2061,7 @@ EXPORT_SYMBOL(dump_ioo); void dump_rniobuf(struct niobuf_remote *nb) { CDEBUG(D_RPCTRACE, "niobuf_remote: offset=%llu, len=%d, flags=%x\n", - nb->offset, nb->len, nb->flags); + nb->rnb_offset, nb->rnb_len, nb->rnb_flags); } EXPORT_SYMBOL(dump_rniobuf); diff --git a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c index eb6d88e..2390255 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c +++ b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c @@ -1652,18 +1652,18 @@ void lustre_assert_wire_constants(void) /* Checks for struct niobuf_remote */ LASSERTF((int)sizeof(struct niobuf_remote) == 16, "found %lld\n", (long long)(int)sizeof(struct niobuf_remote)); - LASSERTF((int)offsetof(struct niobuf_remote, offset) == 0, "found %lld\n", - (long long)(int)offsetof(struct niobuf_remote, offset)); - LASSERTF((int)sizeof(((struct niobuf_remote *)0)->offset) == 8, "found %lld\n", - (long long)(int)sizeof(((struct niobuf_remote *)0)->offset)); - LASSERTF((int)offsetof(struct niobuf_remote, len) == 8, "found %lld\n", - (long long)(int)offsetof(struct niobuf_remote, len)); - LASSERTF((int)sizeof(((struct niobuf_remote *)0)->len) == 4, "found %lld\n", - (long long)(int)sizeof(((struct niobuf_remote *)0)->len)); - LASSERTF((int)offsetof(struct niobuf_remote, flags) == 12, "found %lld\n", - (long long)(int)offsetof(struct niobuf_remote, flags)); - LASSERTF((int)sizeof(((struct niobuf_remote *)0)->flags) == 4, "found %lld\n", - (long long)(int)sizeof(((struct niobuf_remote *)0)->flags)); + LASSERTF((int)offsetof(struct niobuf_remote, rnb_offset) == 0, "found %lld\n", + (long long)(int)offsetof(struct niobuf_remote, rnb_offset)); + LASSERTF((int)sizeof(((struct niobuf_remote *)0)->rnb_offset) == 8, "found %lld\n", + (long long)(int)sizeof(((struct niobuf_remote *)0)->rnb_offset)); + LASSERTF((int)offsetof(struct niobuf_remote, rnb_len) == 8, "found %lld\n", + (long long)(int)offsetof(struct niobuf_remote, rnb_len)); + LASSERTF((int)sizeof(((struct niobuf_remote *)0)->rnb_len) == 4, "found %lld\n", + (long long)(int)sizeof(((struct niobuf_remote *)0)->rnb_len)); + LASSERTF((int)offsetof(struct niobuf_remote, rnb_flags) == 12, "found %lld\n", + (long long)(int)offsetof(struct niobuf_remote, rnb_flags)); + LASSERTF((int)sizeof(((struct niobuf_remote *)0)->rnb_flags) == 4, "found %lld\n", + (long long)(int)sizeof(((struct niobuf_remote *)0)->rnb_flags)); LASSERTF(OBD_BRW_READ == 0x01, "found 0x%.8x\n", OBD_BRW_READ); LASSERTF(OBD_BRW_WRITE == 0x02, "found 0x%.8x\n", -- cgit v0.10.2 From 33ddd841eaf3ce7ba0b8daa041be4c851d2590a3 Mon Sep 17 00:00:00 2001 From: Niu Yawei <yawei.niu@intel.com> Date: Sun, 18 Sep 2016 16:37:08 -0400 Subject: staging: lustre: obdclass: serialize lu_site purge Umount process relies on lu_site_purge(-1) to purge all objects before umount, however, if there happen to have a cache shrinker which calls lu_site_purge(nr) in parallel, some objects may still being freed by cache shrinker even after the lu_site_purge(-1) called by umount done. This can be simply fixed by serializing purge threads, since it doesn't make any sense to have them in parallel. Signed-off-by: Niu Yawei <yawei.niu@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5331 Reviewed-on: http://review.whamcloud.com/11099 Reviewed-by: Lai Siyao <lai.siyao@intel.com> Reviewed-by: Mike Pershin <mike.pershin@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lu_object.h b/drivers/staging/lustre/lustre/include/lu_object.h index 502bc41..fe40b42 100644 --- a/drivers/staging/lustre/lustre/include/lu_object.h +++ b/drivers/staging/lustre/lustre/include/lu_object.h @@ -623,6 +623,11 @@ struct lu_site { spinlock_t ls_ld_lock; /** + * Lock to serialize site purge. + */ + struct mutex ls_purge_mutex; + + /** * lu_site stats */ struct lprocfs_stats *ls_stats; diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c index 9d1c96b..b6fd9af 100644 --- a/drivers/staging/lustre/lustre/obdclass/lu_object.c +++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c @@ -354,6 +354,11 @@ int lu_site_purge(const struct lu_env *env, struct lu_site *s, int nr) start = s->ls_purge_start; bnr = (nr == ~0) ? -1 : nr / CFS_HASH_NBKT(s->ls_obj_hash) + 1; again: + /* + * It doesn't make any sense to make purge threads parallel, that can + * only bring troubles to us. See LU-5331. + */ + mutex_lock(&s->ls_purge_mutex); did_sth = 0; cfs_hash_for_each_bucket(s->ls_obj_hash, &bd, i) { if (i < start) @@ -399,6 +404,7 @@ int lu_site_purge(const struct lu_env *env, struct lu_site *s, int nr) if (nr == 0) break; } + mutex_unlock(&s->ls_purge_mutex); if (nr != 0 && did_sth && start != 0) { start = 0; /* restart from the first bucket */ @@ -983,6 +989,7 @@ int lu_site_init(struct lu_site *s, struct lu_device *top) char name[16]; memset(s, 0, sizeof(*s)); + mutex_init(&s->ls_purge_mutex); snprintf(name, 16, "lu_site_%s", top->ld_type->ldt_name); for (bits = lu_htable_order(top); bits >= LU_SITE_BITS_MIN; bits--) { s->ls_obj_hash = cfs_hash_create(name, bits, bits, -- cgit v0.10.2 From 50dd90bab8745fe88e1e791dd6dfe2d5053c3981 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Sun, 18 Sep 2016 16:37:09 -0400 Subject: staging: lustre: llite: add LL_LEASE_{RD,WR,UN}LCK Define new constants LL_LEASE_{RD,WR,UN}LCK for use as the argument to and return value from the LL_IOC_{GET,SET}_LEASE ioctls. As arguments, these contants replace the use of F_{RD,WR,UN}LCK from fcntl.h. As return values they replace the use of FMODE_{READ,WRITE} which are internal to the Linux kernel source and not under the control of the Lustre ioctl interface. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5013 Reviewed-on: http://review.whamcloud.com/10233 Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Lai Siyao <lai.siyao@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index c69918b..5e907af 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -246,6 +246,13 @@ struct ost_id { #define LL_IOC_MIGRATE _IOR('f', 247, int) #define LL_IOC_FID2MDTIDX _IOWR('f', 248, struct lu_fid) +/* Lease types for use as arg and return of LL_IOC_{GET,SET}_LEASE ioctl. */ +enum ll_lease_type { + LL_LEASE_RDLCK = 0x1, + LL_LEASE_WRLCK = 0x2, + LL_LEASE_UNLCK = 0x4, +}; + #define LL_STATFS_LMV 1 #define LL_STATFS_LOV 2 #define LL_STATFS_NODELAY 4 diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index bfac6dd..e9791e3 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -2245,6 +2245,12 @@ free_hss: return rc; } +static inline long ll_lease_type_from_fmode(fmode_t fmode) +{ + return ((fmode & FMODE_READ) ? LL_LEASE_RDLCK : 0) | + ((fmode & FMODE_WRITE) ? LL_LEASE_WRLCK : 0); +} + static long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -2449,20 +2455,20 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) struct ll_inode_info *lli = ll_i2info(inode); struct obd_client_handle *och = NULL; bool lease_broken; - fmode_t mode = 0; + fmode_t fmode; switch (arg) { - case F_WRLCK: + case LL_LEASE_WRLCK: if (!(file->f_mode & FMODE_WRITE)) return -EPERM; - mode = FMODE_WRITE; + fmode = FMODE_WRITE; break; - case F_RDLCK: + case LL_LEASE_RDLCK: if (!(file->f_mode & FMODE_READ)) return -EPERM; - mode = FMODE_READ; + fmode = FMODE_READ; break; - case F_UNLCK: + case LL_LEASE_UNLCK: mutex_lock(&lli->lli_och_mutex); if (fd->fd_lease_och) { och = fd->fd_lease_och; @@ -2470,26 +2476,26 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } mutex_unlock(&lli->lli_och_mutex); - if (och) { - mode = och->och_flags & - (FMODE_READ | FMODE_WRITE); - rc = ll_lease_close(och, inode, &lease_broken); - if (rc == 0 && lease_broken) - mode = 0; - } else { - rc = -ENOLCK; - } + if (!och) + return -ENOLCK; - /* return the type of lease or error */ - return rc < 0 ? rc : (int)mode; + fmode = och->och_flags; + rc = ll_lease_close(och, inode, &lease_broken); + if (rc < 0) + return rc; + + if (lease_broken) + fmode = 0; + + return ll_lease_type_from_fmode(fmode); default: return -EINVAL; } - CDEBUG(D_INODE, "Set lease with mode %d\n", mode); + CDEBUG(D_INODE, "Set lease with mode %u\n", fmode); /* apply for lease */ - och = ll_lease_open(inode, file, mode, 0); + och = ll_lease_open(inode, file, fmode, 0); if (IS_ERR(och)) return PTR_ERR(och); @@ -2510,8 +2516,8 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case LL_IOC_GET_LEASE: { struct ll_inode_info *lli = ll_i2info(inode); struct ldlm_lock *lock = NULL; + fmode_t fmode = 0; - rc = 0; mutex_lock(&lli->lli_och_mutex); if (fd->fd_lease_och) { struct obd_client_handle *och = fd->fd_lease_och; @@ -2520,14 +2526,13 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (lock) { lock_res_and_lock(lock); if (!ldlm_is_cancel(lock)) - rc = och->och_flags & - (FMODE_READ | FMODE_WRITE); + fmode = och->och_flags; unlock_res_and_lock(lock); LDLM_LOCK_PUT(lock); } } mutex_unlock(&lli->lli_och_mutex); - return rc; + return ll_lease_type_from_fmode(fmode); } case LL_IOC_HSM_IMPORT: { struct hsm_user_import *hui; -- cgit v0.10.2 From 47137ad380a4d4c738f246bd792b76fd403219ce Mon Sep 17 00:00:00 2001 From: Bobi Jam <bobijam.xu@intel.com> Date: Sun, 18 Sep 2016 16:37:10 -0400 Subject: staging: lustre: llite: update ras stride offset When a read ahead does not reach the end of the region reserved from ras, we'd set ras::ras_next_readahead back to where we left off; For stride read ahead, it needs to make sure that the offset is no less than ras_stride_offset, so that the stride read ahead can work correctly. Signed-off-by: Bobi Jam <bobijam.xu@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5263 Reviewed-on: http://review.whamcloud.com/11181 Reviewed-by: Fan Yong <fan.yong@intel.com> Reviewed-by: wang di <di.wang@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index 25de3bf..de20b7d 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -413,7 +413,7 @@ static int ll_read_ahead_pages(const struct lu_env *env, * forward read-ahead, it will be fixed when backward * read-ahead is implemented */ - LASSERTF(page_idx > ria->ria_stoff, "Invalid page_idx %lu rs %lu re %lu ro %lu rl %lu rp %lu\n", + LASSERTF(page_idx >= ria->ria_stoff, "Invalid page_idx %lu rs %lu re %lu ro %lu rl %lu rp %lu\n", page_idx, ria->ria_start, ria->ria_end, ria->ria_stoff, ria->ria_length, ria->ria_pages); @@ -474,10 +474,22 @@ int ll_readahead(const struct lu_env *env, struct cl_io *io, } /* Reserve a part of the read-ahead window that we'll be issuing */ - if (ras->ras_window_len) { - start = ras->ras_next_readahead; + if (ras->ras_window_len > 0) { + /* + * Note: other thread might rollback the ras_next_readahead, + * if it can not get the full size of prepared pages, see the + * end of this function. For stride read ahead, it needs to + * make sure the offset is no less than ras_stride_offset, + * so that stride read ahead can work correctly. + */ + if (stride_io_mode(ras)) + start = max(ras->ras_next_readahead, + ras->ras_stride_offset); + else + start = ras->ras_next_readahead; end = ras->ras_window_start + ras->ras_window_len - 1; } + if (end != 0) { unsigned long rpc_boundary; /* -- cgit v0.10.2 From 212f6c7fcf06ecbe2d47d5e22f0068d035d5ee34 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Sun, 18 Sep 2016 16:37:11 -0400 Subject: staging: lustre: lmv: fix some byte order issues In the handler for LL_IOC_LMV_GETSTRIPE convert stripe FIDs from little to CPU endian when unpacking lmv_user_md. In lmv_unpack_md_v1() fix a double conversion of the stripe count. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5342 Reviewed-on: http://review.whamcloud.com/11106 Reviewed-by: Dmitry Eremin <dmitry.eremin@intel.com> Reviewed-by: Jian Yu <jian.yu@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index c97a4a0..97815cf 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -1252,16 +1252,16 @@ lmv_out_free: tmp->lum_stripe_count = 0; tmp->lum_stripe_offset = mdt_index; for (i = 0; i < stripe_count; i++) { - struct lu_fid *fid; + struct lu_fid fid; - fid = &lmm->lmv_md_v1.lmv_stripe_fids[i]; - mdt_index = ll_get_mdt_idx_by_fid(sbi, fid); + fid_le_to_cpu(&fid, &lmm->lmv_md_v1.lmv_stripe_fids[i]); + mdt_index = ll_get_mdt_idx_by_fid(sbi, &fid); if (mdt_index < 0) { rc = mdt_index; goto out_tmp; } tmp->lum_objects[i].lum_mds = mdt_index; - tmp->lum_objects[i].lum_fid = *fid; + tmp->lum_objects[i].lum_fid = fid; tmp->lum_stripe_count++; } diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index fb5ddd7..32d331e 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -2907,7 +2907,7 @@ static int lmv_unpack_md_v1(struct obd_export *exp, struct lmv_stripe_md *lsm, lsm->lsm_md_hash_type, lsm->lsm_md_layout_version); stripe_count = le32_to_cpu(lmm1->lmv_stripe_count); - for (i = 0; i < le32_to_cpu(stripe_count); i++) { + for (i = 0; i < stripe_count; i++) { fid_le_to_cpu(&lsm->lsm_md_oinfo[i].lmo_fid, &lmm1->lmv_stripe_fids[i]); rc = lmv_fld_lookup(lmv, &lsm->lsm_md_oinfo[i].lmo_fid, -- cgit v0.10.2 From 60deafeae486f8e6b1b4cc781214521e615c9459 Mon Sep 17 00:00:00 2001 From: Niu Yawei <yawei.niu@intel.com> Date: Sun, 18 Sep 2016 16:37:12 -0400 Subject: staging: lustre: osc: update kms in brw_interpret() properly In brw_interpret(), we forgot page offset when calculating write offset, that leads to wrong kms for sync write. Signed-off-by: Niu Yawei <yawei.niu@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5463 Reviewed-on: http://review.whamcloud.com/11374 Reviewed-by: Bobi Jam <bobijam@gmail.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Li Dongyang <dongyang.li@anu.edu.au> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index e861973..e44b4fa 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -1796,7 +1796,8 @@ static int brw_interpret(const struct lu_env *env, if (lustre_msg_get_opc(req->rq_reqmsg) == OST_WRITE) { struct lov_oinfo *loi = cl2osc(obj)->oo_oinfo; - loff_t last_off = last->oap_count + last->oap_obj_off; + loff_t last_off = last->oap_count + last->oap_obj_off + + last->oap_page_off; /* Change file size if this is an out of quota or * direct IO write and it extends the file size -- cgit v0.10.2 From 620f086d9ae2e4b47c67ac05b76153dfc30d0b1f Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Sun, 18 Sep 2016 16:37:13 -0400 Subject: staging: lustre: lmv: release locks if lmv_intent_lock() fails In lmv_intent_lock() if we will return an error then first release any locks referenced by the intent. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5431 Reviewed-on: http://review.whamcloud.com/11319 Reviewed-by: wang di <di.wang@intel.com> Reviewed-by: Lai Siyao <lai.siyao@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/lmv/lmv_intent.c b/drivers/staging/lustre/lustre/lmv/lmv_intent.c index 85cc5cb..fd3dc7c 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_intent.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_intent.c @@ -533,5 +533,27 @@ int lmv_intent_lock(struct obd_export *exp, struct md_op_data *op_data, extra_lock_flags); else LBUG(); + + if (rc < 0) { + struct lustre_handle lock_handle; + + if (it->it_lock_mode) { + lock_handle.cookie = it->it_lock_handle; + ldlm_lock_decref(&lock_handle, it->it_lock_mode); + } + + it->it_lock_handle = 0; + it->it_lock_mode = 0; + + if (it->it_remote_lock_mode) { + lock_handle.cookie = it->it_remote_lock_handle; + ldlm_lock_decref(&lock_handle, + it->it_remote_lock_mode); + } + + it->it_remote_lock_handle = 0; + it->it_remote_lock_mode = 0; + } + return rc; } -- cgit v0.10.2 From 058a6a4203fa31a4cfd7172e8d578310c6bafb95 Mon Sep 17 00:00:00 2001 From: Bobi Jam <bobijam.xu@intel.com> Date: Sun, 18 Sep 2016 16:37:14 -0400 Subject: staging: lustre: clio: lu_ref_del() mismatch ref add scope 'commit 77605e41a26f ("staging/lustre/clio: add pages into writeback cache in batches")' adds a page to a list aggregate issuing them to writeback cache; A page add is referenced in llite/vvp io scope, while writeback cache commit de-refers it under osc sub io scope, and enabling -lu_ref will detect this scope mismatch. Signed-off-by: Bobi Jam <bobijam.xu@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4503 Reviewed-on: http://review.whamcloud.com/8970 Reviewed-by: frank zago <fzago@cray.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index 94916dc..09ccd1f 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -821,7 +821,7 @@ static void write_commit_callback(const struct lu_env *env, struct cl_io *io, cl_page_disown(env, io, page); /* held in ll_cl_init() */ - lu_ref_del(&page->cp_reference, "cl_io", io); + lu_ref_del(&page->cp_reference, "cl_io", cl_io_top(io)); cl_page_put(env, page); } -- cgit v0.10.2 From 97cba1302d8994b9a573b6274133475e85ef7630 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin <dmitry.eremin@intel.com> Date: Sun, 18 Sep 2016 16:37:15 -0400 Subject: staging: lustre: fix comparison between signed and unsigned Cleanup in general headers. * use size_t in cfs_size_round*() * make unsigned index and len in lustre_cfg_*() * make iteration variable the same type as comparing value * make unsigned pages counters Signed-off-by: Dmitry Eremin <dmitry.eremin@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5417 Reviewed-on: http://review.whamcloud.com/11327 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Fan Yong <fan.yong@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h index d401ae1..e0e1a5d 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h @@ -310,13 +310,13 @@ do { \ #define MKSTR(ptr) ((ptr)) ? (ptr) : "" -static inline int cfs_size_round4(int val) +static inline size_t cfs_size_round4(int val) { return (val + 3) & (~0x3); } #ifndef HAVE_CFS_SIZE_ROUND -static inline int cfs_size_round(int val) +static inline size_t cfs_size_round(int val) { return (val + 7) & (~0x7); } @@ -324,17 +324,17 @@ static inline int cfs_size_round(int val) #define HAVE_CFS_SIZE_ROUND #endif -static inline int cfs_size_round16(int val) +static inline size_t cfs_size_round16(int val) { return (val + 0xf) & (~0xf); } -static inline int cfs_size_round32(int val) +static inline size_t cfs_size_round32(int val) { return (val + 0x1f) & (~0x1f); } -static inline int cfs_size_round0(int val) +static inline size_t cfs_size_round0(int val) { if (!val) return 0; @@ -343,7 +343,7 @@ static inline int cfs_size_round0(int val) static inline size_t cfs_round_strlen(char *fset) { - return (size_t)cfs_size_round((int)strlen(fset) + 1); + return cfs_size_round((int)strlen(fset) + 1); } #define LOGL(var, len, ptr) \ diff --git a/drivers/staging/lustre/lustre/include/lprocfs_status.h b/drivers/staging/lustre/lustre/include/lprocfs_status.h index 795d446..b1a8ca5 100644 --- a/drivers/staging/lustre/lustre/include/lprocfs_status.h +++ b/drivers/staging/lustre/lustre/include/lprocfs_status.h @@ -499,7 +499,7 @@ static inline __u64 lprocfs_stats_collector(struct lprocfs_stats *stats, int idx, enum lprocfs_fields_flags field) { - int i; + unsigned int i; unsigned int num_cpu; unsigned long flags = 0; __u64 ret = 0; diff --git a/drivers/staging/lustre/lustre/include/lustre_cfg.h b/drivers/staging/lustre/lustre/include/lustre_cfg.h index 95a0be1..8eb394e 100644 --- a/drivers/staging/lustre/lustre/include/lustre_cfg.h +++ b/drivers/staging/lustre/lustre/include/lustre_cfg.h @@ -151,13 +151,11 @@ static inline void lustre_cfg_bufs_reset(struct lustre_cfg_bufs *bufs, char *nam lustre_cfg_bufs_set_string(bufs, 0, name); } -static inline void *lustre_cfg_buf(struct lustre_cfg *lcfg, int index) +static inline void *lustre_cfg_buf(struct lustre_cfg *lcfg, __u32 index) { - int i; - int offset; - int bufcount; - - LASSERT(index >= 0); + __u32 i; + size_t offset; + __u32 bufcount; bufcount = lcfg->lcfg_bufcount; if (index >= bufcount) @@ -172,7 +170,7 @@ static inline void *lustre_cfg_buf(struct lustre_cfg *lcfg, int index) static inline void lustre_cfg_bufs_init(struct lustre_cfg_bufs *bufs, struct lustre_cfg *lcfg) { - int i; + __u32 i; bufs->lcfg_bufcount = lcfg->lcfg_bufcount; for (i = 0; i < bufs->lcfg_bufcount; i++) { @@ -181,7 +179,7 @@ static inline void lustre_cfg_bufs_init(struct lustre_cfg_bufs *bufs, } } -static inline char *lustre_cfg_string(struct lustre_cfg *lcfg, int index) +static inline char *lustre_cfg_string(struct lustre_cfg *lcfg, __u32 index) { char *s; @@ -197,8 +195,8 @@ static inline char *lustre_cfg_string(struct lustre_cfg *lcfg, int index) * of data. Try to use the padding first though. */ if (s[lcfg->lcfg_buflens[index] - 1] != '\0') { - int last = min((int)lcfg->lcfg_buflens[index], - cfs_size_round(lcfg->lcfg_buflens[index]) - 1); + size_t last = min((size_t)lcfg->lcfg_buflens[index], + cfs_size_round(lcfg->lcfg_buflens[index]) - 1); char lost = s[last]; s[last] = '\0'; @@ -210,10 +208,10 @@ static inline char *lustre_cfg_string(struct lustre_cfg *lcfg, int index) return s; } -static inline int lustre_cfg_len(__u32 bufcount, __u32 *buflens) +static inline __u32 lustre_cfg_len(__u32 bufcount, __u32 *buflens) { - int i; - int len; + __u32 i; + __u32 len; len = LCFG_HDR_SIZE(bufcount); for (i = 0; i < bufcount; i++) @@ -254,7 +252,7 @@ static inline void lustre_cfg_free(struct lustre_cfg *lcfg) return; } -static inline int lustre_cfg_sanity_check(void *buf, int len) +static inline int lustre_cfg_sanity_check(void *buf, size_t len) { struct lustre_cfg *lcfg = (struct lustre_cfg *)buf; diff --git a/drivers/staging/lustre/lustre/include/lustre_lmv.h b/drivers/staging/lustre/lustre/include/lustre_lmv.h index 085e596..5a2fc30 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lmv.h +++ b/drivers/staging/lustre/lustre/include/lustre_lmv.h @@ -55,7 +55,7 @@ struct lmv_stripe_md { static inline bool lsm_md_eq(const struct lmv_stripe_md *lsm1, const struct lmv_stripe_md *lsm2) { - int idx; + __u32 idx; if (lsm1->lsm_md_magic != lsm2->lsm_md_magic || lsm1->lsm_md_stripe_count != lsm2->lsm_md_stripe_count || @@ -92,7 +92,7 @@ static inline void lmv_free_memmd(struct lmv_stripe_md *lsm) static inline void lmv1_le_to_cpu(struct lmv_mds_md_v1 *lmv_dst, const struct lmv_mds_md_v1 *lmv_src) { - int i; + __u32 i; lmv_dst->lmv_magic = le32_to_cpu(lmv_src->lmv_magic); lmv_dst->lmv_stripe_count = le32_to_cpu(lmv_src->lmv_stripe_count); diff --git a/drivers/staging/lustre/lustre/include/lustre_net.h b/drivers/staging/lustre/lustre/include/lustre_net.h index 6d82998..531c628 100644 --- a/drivers/staging/lustre/lustre/include/lustre_net.h +++ b/drivers/staging/lustre/lustre/include/lustre_net.h @@ -1631,7 +1631,7 @@ static inline bool ptlrpc_nrs_req_can_move(struct ptlrpc_request *req) /** * Returns 1 if request buffer at offset \a index was already swabbed */ -static inline int lustre_req_swabbed(struct ptlrpc_request *req, int index) +static inline int lustre_req_swabbed(struct ptlrpc_request *req, size_t index) { LASSERT(index < sizeof(req->rq_req_swab_mask) * 8); return req->rq_req_swab_mask & (1 << index); @@ -1640,7 +1640,7 @@ static inline int lustre_req_swabbed(struct ptlrpc_request *req, int index) /** * Returns 1 if request reply buffer at offset \a index was already swabbed */ -static inline int lustre_rep_swabbed(struct ptlrpc_request *req, int index) +static inline int lustre_rep_swabbed(struct ptlrpc_request *req, size_t index) { LASSERT(index < sizeof(req->rq_rep_swab_mask) * 8); return req->rq_rep_swab_mask & (1 << index); @@ -1665,7 +1665,8 @@ static inline int ptlrpc_rep_need_swab(struct ptlrpc_request *req) /** * Mark request buffer at offset \a index that it was already swabbed */ -static inline void lustre_set_req_swabbed(struct ptlrpc_request *req, int index) +static inline void lustre_set_req_swabbed(struct ptlrpc_request *req, + size_t index) { LASSERT(index < sizeof(req->rq_req_swab_mask) * 8); LASSERT((req->rq_req_swab_mask & (1 << index)) == 0); @@ -1675,7 +1676,8 @@ static inline void lustre_set_req_swabbed(struct ptlrpc_request *req, int index) /** * Mark request reply buffer at offset \a index that it was already swabbed */ -static inline void lustre_set_rep_swabbed(struct ptlrpc_request *req, int index) +static inline void lustre_set_rep_swabbed(struct ptlrpc_request *req, + size_t index) { LASSERT(index < sizeof(req->rq_rep_swab_mask) * 8); LASSERT((req->rq_rep_swab_mask & (1 << index)) == 0); diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index f55e679..37a3acb 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -222,11 +222,11 @@ struct client_obd { struct sptlrpc_flavor cl_flvr_mgc; /* fixed flavor of mgc->mgs */ /* the grant values are protected by loi_list_lock below */ - long cl_dirty_pages; /* all _dirty_ in pahges */ - long cl_dirty_max_pages;/* allowed w/o rpc */ - long cl_dirty_transit; /* dirty synchronous */ - long cl_avail_grant; /* bytes of credit for ost */ - long cl_lost_grant; /* lost credits (trunc) */ + unsigned long cl_dirty_pages; /* all _dirty_ in pahges */ + unsigned long cl_dirty_max_pages; /* allowed w/o rpc */ + unsigned long cl_dirty_transit; /* dirty synchronous */ + unsigned long cl_avail_grant; /* bytes of credit for ost */ + unsigned long cl_lost_grant; /* lost credits (trunc) */ /* since we allocate grant by blocks, we don't know how many grant will * be used to add a page into cache. As a solution, we reserve maximum @@ -268,13 +268,13 @@ struct client_obd { struct list_head cl_loi_hp_ready_list; struct list_head cl_loi_write_list; struct list_head cl_loi_read_list; - int cl_r_in_flight; - int cl_w_in_flight; + __u32 cl_r_in_flight; + __u32 cl_w_in_flight; /* just a sum of the loi/lop pending numbers to be exported by sysfs */ atomic_t cl_pending_w_pages; atomic_t cl_pending_r_pages; __u32 cl_max_pages_per_rpc; - int cl_max_rpcs_in_flight; + __u32 cl_max_rpcs_in_flight; struct obd_histogram cl_read_rpc_hist; struct obd_histogram cl_write_rpc_hist; struct obd_histogram cl_read_page_hist; @@ -1183,8 +1183,8 @@ static inline void client_adjust_max_dirty(struct client_obd *cli) cli->cl_dirty_max_pages = (OSC_MAX_DIRTY_DEFAULT * 1024 * 1024) >> PAGE_SHIFT; else { - long dirty_max = cli->cl_max_rpcs_in_flight * - cli->cl_max_pages_per_rpc; + unsigned long dirty_max = cli->cl_max_rpcs_in_flight * + cli->cl_max_pages_per_rpc; if (dirty_max > cli->cl_dirty_max_pages) cli->cl_dirty_max_pages = dirty_max; diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index e44b4fa..5cca2b6 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -823,9 +823,10 @@ static void osc_announce_cached(struct client_obd *cli, struct obdo *oa, cli->cl_dirty_pages, cli->cl_dirty_max_pages); oa->o_undirty = 0; } else { - long max_in_flight = (cli->cl_max_pages_per_rpc << - PAGE_SHIFT) * - (cli->cl_max_rpcs_in_flight + 1); + unsigned long max_in_flight; + + max_in_flight = (cli->cl_max_pages_per_rpc << PAGE_SHIFT) * + (cli->cl_max_rpcs_in_flight + 1); oa->o_undirty = max(cli->cl_dirty_max_pages << PAGE_SHIFT, max_in_flight); } @@ -2048,7 +2049,7 @@ int osc_build_rpc(const struct lu_env *env, struct client_obd *cli, } spin_unlock(&cli->cl_loi_list_lock); - DEBUG_REQ(D_INODE, req, "%d pages, aa %p. now %dr/%dw in flight", + DEBUG_REQ(D_INODE, req, "%d pages, aa %p. now %ur/%dw in flight", page_count, aa, cli->cl_r_in_flight, cli->cl_w_in_flight); diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index 102f0aa..03fd5d7 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -1734,7 +1734,7 @@ EXPORT_SYMBOL(lustre_swab_mgs_target_info); void lustre_swab_mgs_nidtbl_entry(struct mgs_nidtbl_entry *entry) { - int i; + __u8 i; __swab64s(&entry->mne_version); __swab32s(&entry->mne_instance); @@ -1823,7 +1823,7 @@ static void lustre_swab_fiemap_extent(struct ll_fiemap_extent *fm_extent) void lustre_swab_fiemap(struct ll_user_fiemap *fiemap) { - int i; + __u32 i; __swab64s(&fiemap->fm_start); __swab64s(&fiemap->fm_length); -- cgit v0.10.2 From 3dd282c4bdf4bdac1b010c19088ea0c565b6d79f Mon Sep 17 00:00:00 2001 From: Jinshan Xiong <jinshan.xiong@intel.com> Date: Sun, 18 Sep 2016 16:37:16 -0400 Subject: staging: lustre: lov: adjust page bufsize after layout change Otherwise, the coh_page_bufsize keeps increasing when the file's layout keeps changing in lov_init_raid0(). Signed-off-by: Jinshan Xiong <jinshan.xiong@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5459 Reviewed-on: http://review.whamcloud.com/11394 Reviewed-by: frank zago <fzago@cray.com> Reviewed-by: Bobi Jam <bobijam@gmail.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/lov/lov_object.c b/drivers/staging/lustre/lustre/lov/lov_object.c index 2a52d0c5..4f766e0 100644 --- a/drivers/staging/lustre/lustre/lov/lov_object.c +++ b/drivers/staging/lustre/lustre/lov/lov_object.c @@ -195,6 +195,10 @@ static int lov_page_slice_fixup(struct lov_object *lov, struct cl_object_header *hdr = cl_object_header(&lov->lo_cl); struct cl_object *o; + if (!stripe) + return hdr->coh_page_bufsize - lov->lo_cl.co_slice_off - + cfs_size_round(sizeof(struct lov_page)); + cl_object_for_each(o, stripe) o->co_slice_off += hdr->coh_page_bufsize; @@ -720,6 +724,10 @@ static int lov_layout_change(const struct lu_env *unused, LASSERT(atomic_read(&lov->lo_active_ios) == 0); lov->lo_type = LLT_EMPTY; + /* page bufsize fixup */ + cl_object_header(&lov->lo_cl)->coh_page_bufsize -= + lov_page_slice_fixup(lov, NULL); + result = new_ops->llo_init(env, lu2lov_dev(lov->lo_cl.co_lu.lo_dev), lov, conf, state); -- cgit v0.10.2 From 691f8bfd1db0f9528cae76f52676722251720b7d Mon Sep 17 00:00:00 2001 From: Dmitry Eremin <dmitry.eremin@intel.com> Date: Sun, 18 Sep 2016 16:37:17 -0400 Subject: staging: lustre: obdclass: fix comparison between signed and unsigned Make lu_buf->lb_len unsigned. Signed-off-by: Dmitry Eremin <dmitry.eremin@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5417 Reviewed-on: http://review.whamcloud.com/11281 Reviewed-by: Fan Yong <fan.yong@intel.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lu_object.h b/drivers/staging/lustre/lustre/include/lu_object.h index fe40b42..66ab98a 100644 --- a/drivers/staging/lustre/lustre/include/lu_object.h +++ b/drivers/staging/lustre/lustre/include/lu_object.h @@ -1290,7 +1290,7 @@ static inline bool lu_name_is_valid_2(const char *name, size_t name_len) */ struct lu_buf { void *lb_buf; - ssize_t lb_len; + size_t lb_len; }; #define DLUBUF "(%p %zu)" diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c index b6fd9af..44a854c 100644 --- a/drivers/staging/lustre/lustre/obdclass/lu_object.c +++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c @@ -341,7 +341,7 @@ int lu_site_purge(const struct lu_env *env, struct lu_site *s, int nr) int start; int count; int bnr; - int i; + unsigned int i; if (OBD_FAIL_CHECK(OBD_FAIL_OBD_NO_LRU)) return 0; @@ -869,11 +869,11 @@ EXPORT_SYMBOL(lu_site_print); /** * Return desired hash table order. */ -static int lu_htable_order(struct lu_device *top) +static unsigned int lu_htable_order(struct lu_device *top) { unsigned long bits_max = LU_SITE_BITS_MAX; unsigned long cache_size; - int bits; + unsigned int bits; /* * Calculate hash table size, assuming that we want reasonable @@ -1325,7 +1325,7 @@ static unsigned key_set_version; int lu_context_key_register(struct lu_context_key *key) { int result; - int i; + unsigned int i; LASSERT(key->lct_init); LASSERT(key->lct_fini); @@ -1531,7 +1531,7 @@ EXPORT_SYMBOL(lu_context_key_revive); static void keys_fini(struct lu_context *ctx) { - int i; + unsigned int i; if (!ctx->lc_value) return; @@ -1545,7 +1545,7 @@ static void keys_fini(struct lu_context *ctx) static int keys_fill(struct lu_context *ctx) { - int i; + unsigned int i; LINVRNT(ctx->lc_value); for (i = 0; i < ARRAY_SIZE(lu_keys); ++i) { @@ -1658,7 +1658,7 @@ EXPORT_SYMBOL(lu_context_enter); */ void lu_context_exit(struct lu_context *ctx) { - int i; + unsigned int i; LINVRNT(ctx->lc_state == LCS_ENTERED); ctx->lc_state = LCS_LEFT; @@ -1740,7 +1740,7 @@ static void lu_site_stats_get(struct cfs_hash *hs, struct lu_site_stats *stats, int populated) { struct cfs_hash_bd bd; - int i; + unsigned int i; cfs_hash_for_each_bucket(hs, &bd, i) { struct lu_site_bkt_data *bkt = cfs_hash_bd_extra_get(hs, &bd); -- cgit v0.10.2 From 9e2c96eb8b84be1d4d783426aa0cf055c69896fe Mon Sep 17 00:00:00 2001 From: Wang Shilong <wshilong@ddn.com> Date: Sun, 18 Sep 2016 16:37:18 -0400 Subject: staging: lustre: ptlrpc: fix magic return value of ptlrpc_init_portals Previously, when running 'modprobe lustre', it hit the following error message which is becaue of network initialisation failure: modprobe: ERROR: could not insert 'lustre': Input/output error However, error code is there, just let it return to caller, after this patch, error message will be something like: modprobe: ERROR: could not insert 'lustre': Network is down Signed-off-by: Wang Shilong <wshilong@ddn.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5455 Reviewed-on: http://review.whamcloud.com/11337 Reviewed-by: Dmitry Eremin <dmitry.eremin@intel.com> Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/ptlrpc/events.c b/drivers/staging/lustre/lustre/ptlrpc/events.c index b1ce725..283dfb2 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/events.c +++ b/drivers/staging/lustre/lustre/ptlrpc/events.c @@ -543,7 +543,7 @@ static int ptlrpc_ni_init(void) rc = LNetNIInit(pid); if (rc < 0) { CDEBUG(D_NET, "Can't init network interface: %d\n", rc); - return -ENOENT; + return rc; } /* CAVEAT EMPTOR: how we process portals events is _radically_ @@ -561,7 +561,7 @@ static int ptlrpc_ni_init(void) CERROR("Failed to allocate event queue: %d\n", rc); LNetNIFini(); - return -ENOMEM; + return rc; } int ptlrpc_init_portals(void) @@ -570,7 +570,7 @@ int ptlrpc_init_portals(void) if (rc != 0) { CERROR("network initialisation failed\n"); - return -EIO; + return rc; } rc = ptlrpcd_addref(); if (rc == 0) -- cgit v0.10.2 From 426245a44d6dc03a7e32c8836eb334e32e6d12ee Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Sun, 18 Sep 2016 16:37:19 -0400 Subject: staging: lustre: lmv: release request in lmv_revalidate_slaves() In lmv_revalidate_slaves() ensure that the request returned by md_intent_lock() is properly released on all paths. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5452 Reviewed-on: http://review.whamcloud.com/11326 Reviewed-by: wang di <di.wang@intel.com> Reviewed-by: Lai Siyao <lai.siyao@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/lmv/lmv_intent.c b/drivers/staging/lustre/lustre/lmv/lmv_intent.c index fd3dc7c..f24848f 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_intent.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_intent.c @@ -155,6 +155,7 @@ int lmv_revalidate_slaves(struct obd_export *exp, struct mdt_body *mbody, { struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; + struct ptlrpc_request *req = NULL; struct mdt_body *body; struct md_op_data *op_data; unsigned long size = 0; @@ -178,7 +179,6 @@ int lmv_revalidate_slaves(struct obd_export *exp, struct mdt_body *mbody, */ for (i = 0; i < lsm->lsm_md_stripe_count; i++) { struct lookup_intent it = { .it_op = IT_GETATTR }; - struct ptlrpc_request *req = NULL; struct lustre_handle *lockh = NULL; struct lmv_tgt_desc *tgt = NULL; struct inode *inode; @@ -205,6 +205,11 @@ int lmv_revalidate_slaves(struct obd_export *exp, struct mdt_body *mbody, CDEBUG(D_INODE, "Revalidate slave "DFID" -> mds #%d\n", PFID(&fid), tgt->ltd_idx); + if (req) { + ptlrpc_req_finished(req); + req = NULL; + } + rc = md_intent_lock(tgt->ltd_exp, op_data, &it, &req, cb_blocking, extra_lock_flags); if (rc < 0) @@ -228,9 +233,6 @@ int lmv_revalidate_slaves(struct obd_export *exp, struct mdt_body *mbody, PFID(&lsm->lsm_md_oinfo[i].lmo_fid), PFID(&lsm->lsm_md_oinfo[0].lmo_fid)); - if (req) - ptlrpc_req_finished(req); - if (it.it_lock_mode && lockh) { ldlm_lock_decref(lockh, it.it_lock_mode); it.it_lock_mode = 0; @@ -245,9 +247,6 @@ int lmv_revalidate_slaves(struct obd_export *exp, struct mdt_body *mbody, LTIME_S(inode->i_atime) = body->mbo_atime; LTIME_S(inode->i_ctime) = body->mbo_ctime; LTIME_S(inode->i_mtime) = body->mbo_mtime; - - if (req) - ptlrpc_req_finished(req); } md_set_lock_data(tgt->ltd_exp, lockh, inode, NULL); @@ -288,6 +287,9 @@ int lmv_revalidate_slaves(struct obd_export *exp, struct mdt_body *mbody, mbody->mbo_mtime = mtime; } cleanup: + if (req) + ptlrpc_req_finished(req); + kfree(op_data); return rc; } -- cgit v0.10.2 From 743d6febbc68399a30a4f676b964c487cd435c72 Mon Sep 17 00:00:00 2001 From: Andreas Dilger <andreas.dilger@intel.com> Date: Sun, 18 Sep 2016 16:37:20 -0400 Subject: staging: lustre: build: bump build version warnings to x.y.53 Move the LUSTRE_VERSION_CODE checks to trigger on x.y.53 instead of x.y.50, so that it is into the development cycle that they are hit instead of right at the start. In many cases, the #warning has been removed (to prevent build errors) and instead the code is just disabled outright. The dead code can be seen easily and removed in the future with less interruption to the development process. Signed-off-by: Andreas Dilger <andreas.dilger@intel.com> Signed-off-by: Emoly Liu <emoly.liu@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4217 Reviewed-on: http://review.whamcloud.com/8630 Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Tested-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre_import.h b/drivers/staging/lustre/lustre/include/lustre_import.h index b7a7a74..5461ba3 100644 --- a/drivers/staging/lustre/lustre/include/lustre_import.h +++ b/drivers/staging/lustre/lustre/include/lustre_import.h @@ -285,8 +285,10 @@ struct obd_import { imp_resend_replay:1, /* disable normal recovery, for test only. */ imp_no_pinger_recover:1, +#if OBD_OCD_VERSION(3, 0, 53, 0) > LUSTRE_VERSION_CODE /* need IR MNE swab */ imp_need_mne_swab:1, +#endif /* import must be reconnected instead of * chosing new connection */ diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 37a3acb..838a428 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -317,7 +317,7 @@ struct client_obd { /* used by quotacheck when the servers are older than 2.4 */ int cl_qchk_stat; /* quotacheck stat of the peer */ #define CL_NOT_QUOTACHECKED 1 /* client->cl_qchk_stat init value */ -#if LUSTRE_VERSION_CODE >= OBD_OCD_VERSION(2, 7, 50, 0) +#if OBD_OCD_VERSION(2, 7, 53, 0) < LUSTRE_VERSION_CODE #warning "please consider removing quotacheck compatibility code" #endif diff --git a/drivers/staging/lustre/lustre/mgc/mgc_request.c b/drivers/staging/lustre/lustre/mgc/mgc_request.c index 9d0bd47..f3d4f7f 100644 --- a/drivers/staging/lustre/lustre/mgc/mgc_request.c +++ b/drivers/staging/lustre/lustre/mgc/mgc_request.c @@ -1428,14 +1428,12 @@ again: } mne_swab = !!ptlrpc_rep_need_swab(req); -#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 2, 50, 0) +#if OBD_OCD_VERSION(3, 0, 53, 0) > LUSTRE_VERSION_CODE /* This import flag means the server did an extra swab of IR MNE * records (fixed in LU-1252), reverse it here if needed. LU-1644 */ if (unlikely(req->rq_import->imp_need_mne_swab)) mne_swab = !mne_swab; -#else -#warning "LU-1644: Remove old OBD_CONNECT_MNE_SWAB fixup and imp_need_mne_swab" #endif for (i = 0; i < nrpages && ealen > 0; i++) { diff --git a/drivers/staging/lustre/lustre/obdclass/obd_mount.c b/drivers/staging/lustre/lustre/obdclass/obd_mount.c index 0273768..0df1aa6 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_mount.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_mount.c @@ -384,10 +384,8 @@ int lustre_start_mgc(struct super_block *sb) OBD_CONNECT_FULL20 | OBD_CONNECT_IMP_RECOV | OBD_CONNECT_LVB_TYPE; -#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 2, 50, 0) +#if OBD_OCD_VERSION(3, 0, 53, 0) > LUSTRE_VERSION_CODE data->ocd_connect_flags |= OBD_CONNECT_MNE_SWAB; -#else -#warning "LU-1644: Remove old OBD_CONNECT_MNE_SWAB fixup and imp_need_mne_swab" #endif if (lmd_is_client(lsi->lsi_lmd) && diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c index 93b1e78..013a957 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/import.c +++ b/drivers/staging/lustre/lustre/ptlrpc/import.c @@ -1042,7 +1042,7 @@ finish: warned = true; } -#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 2, 50, 0) +#if OBD_OCD_VERSION(3, 0, 53, 0) > LUSTRE_VERSION_CODE /* Check if server has LU-1252 fix applied to not always swab * the IR MNE entries. Do this only once per connection. This * fixup is version-limited, because we don't want to carry the @@ -1060,8 +1060,6 @@ finish: imp->imp_need_mne_swab = 1; else /* clear if server was upgraded since last connect */ imp->imp_need_mne_swab = 0; -#else -#warning "LU-1644: Remove old OBD_CONNECT_MNE_SWAB fixup and imp_need_mne_swab" #endif if (ocd->ocd_connect_flags & OBD_CONNECT_CKSUM) { -- cgit v0.10.2 From 460554c3587ae0e0ff82f175f926eecbb225ee41 Mon Sep 17 00:00:00 2001 From: Li Xi <lixi@ddn.com> Date: Sun, 18 Sep 2016 16:37:21 -0400 Subject: staging: lustre: llog: add newly opened llog at tail of handle list Add newly opened llog handle at the tail of handle list to increase lookup speed, especially for cancel operation, because the canceled log will be removed from the list, and lookup is from the beginning. Signed-off-by: Lai Siyao <lai.siyao@intel.com> Signed-off-by: Li Xi <lixi@ddn.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5405 Reviewed-on: http://review.whamcloud.com/11575 Reviewed-by: Ian Costello <costello.ian@gmail.com> Reviewed-by: Mike Pershin <mike.pershin@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/obdclass/llog_cat.c b/drivers/staging/lustre/lustre/obdclass/llog_cat.c index d28751a..b27f08f 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_cat.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_cat.c @@ -107,7 +107,7 @@ static int llog_cat_id2handle(const struct lu_env *env, } down_write(&cathandle->lgh_lock); - list_add(&loghandle->u.phd.phd_entry, &cathandle->u.chd.chd_head); + list_add_tail(&loghandle->u.phd.phd_entry, &cathandle->u.chd.chd_head); up_write(&cathandle->lgh_lock); loghandle->u.phd.phd_cat_handle = cathandle; -- cgit v0.10.2 From 83d36347ad4bc930e4deefeccdc63b9032b53e99 Mon Sep 17 00:00:00 2001 From: Henri Doreau <henri.doreau@cea.fr> Date: Sun, 18 Sep 2016 16:37:22 -0400 Subject: staging: lustre: mdc: Report D_CHANGELOG messages as D_HSM Removed the D_CHANGELOG pseudo-debug flag that wasn't actually defined as a usable one. Report the D_CHANGELOG messages as D_HSM ones instead since this is the primary user of these messages. Signed-off-by: Henri Doreau <henri.doreau@cea.fr> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5538 Reviewed-on: http://review.whamcloud.com/11558 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: James Nunez <james.a.nunez@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index cf94926..a77bc17 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -1857,8 +1857,6 @@ static struct kuc_hdr *changelog_kuc_hdr(char *buf, int len, int flags) return lh; } -#define D_CHANGELOG 0 - struct changelog_show { __u64 cs_startrec; __u32 cs_flags; @@ -1885,12 +1883,12 @@ static int changelog_kkuc_cb(const struct lu_env *env, struct llog_handle *llh, if (rec->cr.cr_index < cs->cs_startrec) { /* Skip entries earlier than what we are interested in */ - CDEBUG(D_CHANGELOG, "rec=%llu start=%llu\n", + CDEBUG(D_HSM, "rec=%llu start=%llu\n", rec->cr.cr_index, cs->cs_startrec); return 0; } - CDEBUG(D_CHANGELOG, "%llu %02d%-5s %llu 0x%x t="DFID" p="DFID + CDEBUG(D_HSM, "%llu %02d%-5s %llu 0x%x t=" DFID " p=" DFID " %.*s\n", rec->cr.cr_index, rec->cr.cr_type, changelog_type2str(rec->cr.cr_type), rec->cr.cr_time, rec->cr.cr_flags & CLF_FLAGMASK, @@ -1904,7 +1902,7 @@ static int changelog_kkuc_cb(const struct lu_env *env, struct llog_handle *llh, memcpy(lh + 1, &rec->cr, len - sizeof(*lh)); rc = libcfs_kkuc_msg_put(cs->cs_fp, lh); - CDEBUG(D_CHANGELOG, "kucmsg fp %p len %d rc %d\n", cs->cs_fp, len, rc); + CDEBUG(D_HSM, "kucmsg fp %p len %d rc %d\n", cs->cs_fp, len, rc); return rc; } @@ -1917,7 +1915,7 @@ static int mdc_changelog_send_thread(void *csdata) struct kuc_hdr *kuch; int rc; - CDEBUG(D_CHANGELOG, "changelog to fp=%p start %llu\n", + CDEBUG(D_HSM, "changelog to fp=%p start %llu\n", cs->cs_fp, cs->cs_startrec); cs->cs_buf = kzalloc(KUC_CHANGELOG_MSG_MAXSIZE, GFP_NOFS); @@ -1996,7 +1994,7 @@ static int mdc_ioc_changelog_send(struct obd_device *obd, kfree(cs); } else { rc = 0; - CDEBUG(D_CHANGELOG, "%s: started changelog thread\n", + CDEBUG(D_HSM, "%s: started changelog thread\n", obd->obd_name); } -- cgit v0.10.2 From bc3877b08b62adc9a218d67d6d8434195f789434 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Sun, 18 Sep 2016 16:37:23 -0400 Subject: staging: lustre: remove RCU2HANDLE macro Remove RCU2HANDLE macro from lustre_handles.h. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2675 Reviewed-on: http://review.whamcloud.com/11498 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Bob Glossman <bob.glossman@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre_handles.h b/drivers/staging/lustre/lustre/include/lustre_handles.h index bc1dd46..e071bac 100644 --- a/drivers/staging/lustre/lustre/include/lustre_handles.h +++ b/drivers/staging/lustre/lustre/include/lustre_handles.h @@ -76,8 +76,6 @@ struct portals_handle { unsigned int h_in:1; }; -#define RCU2HANDLE(rcu) container_of(rcu, struct portals_handle, h_rcu) - /* handles.c */ /* Add a handle to the hash table */ diff --git a/drivers/staging/lustre/lustre/obdclass/lustre_handles.c b/drivers/staging/lustre/lustre/obdclass/lustre_handles.c index 8faa318..c9445e5 100644 --- a/drivers/staging/lustre/lustre/obdclass/lustre_handles.c +++ b/drivers/staging/lustre/lustre/obdclass/lustre_handles.c @@ -164,8 +164,11 @@ EXPORT_SYMBOL(class_handle2object); void class_handle_free_cb(struct rcu_head *rcu) { - struct portals_handle *h = RCU2HANDLE(rcu); - void *ptr = (void *)(unsigned long)h->h_cookie; + struct portals_handle *h; + void *ptr; + + h = container_of(rcu, struct portals_handle, h_rcu); + ptr = (void *)(unsigned long)h->h_cookie; if (h->h_ops->hop_free) h->h_ops->hop_free(ptr, h->h_size); -- cgit v0.10.2 From d38a48e5b8cf0a186789c0b80a5e771672e141ea Mon Sep 17 00:00:00 2001 From: Dmitry Eremin <dmitry.eremin@intel.com> Date: Sun, 18 Sep 2016 16:37:24 -0400 Subject: staging: lustre: llite: Compare of unsigned value against 0 is always true Comparison of unsigned value against 0 is always true. Signed-off-by: Dmitry Eremin <dmitry.eremin@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5200 Reviewed-on: http://review.whamcloud.com/11217 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Fan Yong <fan.yong@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/lproc_llite.c b/drivers/staging/lustre/lustre/llite/lproc_llite.c index af233ea..fc2ba56 100644 --- a/drivers/staging/lustre/lustre/llite/lproc_llite.c +++ b/drivers/staging/lustre/lustre/llite/lproc_llite.c @@ -846,7 +846,7 @@ static ssize_t unstable_stats_store(struct kobject *kobj, if (!count) return 0; - if (count < 0 || count >= sizeof(kernbuf)) + if (count >= sizeof(kernbuf)) return -EINVAL; if (copy_from_user(kernbuf, buffer, count)) -- cgit v0.10.2 From e9792be1e4b12616e2097bcd7e74b121081051d4 Mon Sep 17 00:00:00 2001 From: Lai Siyao <lai.siyao@intel.com> Date: Sun, 18 Sep 2016 16:37:25 -0400 Subject: staging: lustre: statahead: statahead thread wait for RPCs to finish Statahead thread should wait for inflight stat RPCs to finish in case statahead RPC callback may access data allocated in statahead thread context. ll_sa_entry_fini() should keep old entry if stat RPC is not finished yet. Simplify sai refcounting: * newly allocated sai will hold one refcount, and it will put it after starting statahead thread. * statahead thread holds one refcount. * agl thread holds one refcount. * stat process calls do_statahead_enter() which will try to get sai, and if it's valid, it will revalidate from statahead cache, and put refcount after use. Signed-off-by: Lai Siyao <lai.siyao@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3270 Reviewed-on: http://review.whamcloud.com/9663 Reviewed-by: Fan Yong <fan.yong@intel.com> Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 838a428..89633f7 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -806,7 +806,6 @@ struct md_enqueue_info { int (*mi_cb)(struct ptlrpc_request *req, struct md_enqueue_info *minfo, int rc); __u64 mi_cbdata; - unsigned int mi_generation; }; struct obd_ops { diff --git a/drivers/staging/lustre/lustre/llite/dcache.c b/drivers/staging/lustre/lustre/llite/dcache.c index f4b6f38..8c00cc6 100644 --- a/drivers/staging/lustre/lustre/llite/dcache.c +++ b/drivers/staging/lustre/lustre/llite/dcache.c @@ -279,7 +279,7 @@ static int ll_revalidate_dentry(struct dentry *dentry, if (lookup_flags & (LOOKUP_PARENT | LOOKUP_OPEN | LOOKUP_CREATE)) return 1; - if (d_need_statahead(dir, dentry) <= 0) + if (!dentry_need_statahead(dir, dentry)) return 1; if (lookup_flags & LOOKUP_RCU) diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index e9791e3..273b563 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -351,13 +351,11 @@ int ll_file_release(struct inode *inode, struct file *file) fd = LUSTRE_FPRIVATE(file); LASSERT(fd); - /* The last ref on @file, maybe not be the owner pid of statahead. - * Different processes can open the same dir, "ll_opendir_key" means: - * it is me that should stop the statahead thread. + /* The last ref on @file, maybe not be the owner pid of statahead, + * because parent and child process can share the same file handle. */ - if (S_ISDIR(inode->i_mode) && lli->lli_opendir_key == fd && - lli->lli_opendir_pid != 0) - ll_stop_statahead(inode, lli->lli_opendir_key); + if (S_ISDIR(inode->i_mode) && lli->lli_opendir_key == fd) + ll_deauthorize_statahead(inode, fd); if (is_root_inode(inode)) { LUSTRE_FPRIVATE(file) = NULL; @@ -530,7 +528,7 @@ int ll_file_open(struct inode *inode, struct file *file) struct obd_client_handle **och_p = NULL; __u64 *och_usecount = NULL; struct ll_file_data *fd; - int rc = 0, opendir_set = 0; + int rc = 0; CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), flags %o\n", PFID(ll_inode2fid(inode)), inode, file->f_flags); @@ -545,16 +543,8 @@ int ll_file_open(struct inode *inode, struct file *file) } fd->fd_file = file; - if (S_ISDIR(inode->i_mode)) { - spin_lock(&lli->lli_sa_lock); - if (!lli->lli_opendir_key && !lli->lli_sai && - lli->lli_opendir_pid == 0) { - lli->lli_opendir_key = fd; - lli->lli_opendir_pid = current_pid(); - opendir_set = 1; - } - spin_unlock(&lli->lli_sa_lock); - } + if (S_ISDIR(inode->i_mode)) + ll_authorize_statahead(inode, fd); if (is_root_inode(inode)) { LUSTRE_FPRIVATE(file) = fd; @@ -713,9 +703,10 @@ out_och_free: mutex_unlock(&lli->lli_och_mutex); out_openerr: - if (opendir_set != 0) - ll_stop_statahead(inode, lli->lli_opendir_key); - ll_file_data_put(fd); + if (lli->lli_opendir_key == fd) + ll_deauthorize_statahead(inode, fd); + if (fd) + ll_file_data_put(fd); } else { ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_OPEN, 1); } diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index cbd5bc5..f903f2a 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -172,6 +172,13 @@ struct ll_inode_info { * -- I am the owner of dir statahead. */ pid_t d_opendir_pid; + /* stat will try to access statahead entries or start + * statahead if this flag is set, and this flag will be + * set upon dir open, and cleared when dir is closed, + * statahead hit ratio is too low, or start statahead + * thread failed. + */ + unsigned int d_sa_enabled:1; /* directory stripe information */ struct lmv_stripe_md *d_lsm_md; /* striped directory size */ @@ -184,6 +191,7 @@ struct ll_inode_info { #define lli_opendir_key u.d.d_opendir_key #define lli_sai u.d.d_sai #define lli_sa_lock u.d.d_sa_lock +#define lli_sa_enabled u.d.d_sa_enabled #define lli_opendir_pid u.d.d_opendir_pid #define lli_lsm_md u.d.d_lsm_md #define lli_stripe_dir_size u.d.d_stripe_size @@ -495,6 +503,9 @@ struct ll_sb_info { atomic_t ll_sa_wrong; /* statahead thread stopped for * low hit ratio */ + atomic_t ll_sa_running; /* running statahead thread + * count + */ atomic_t ll_agl_total; /* AGL thread started count */ dev_t ll_sdev_orig; /* save s_dev before assign for @@ -1040,7 +1051,8 @@ struct ll_statahead_info { int do_statahead_enter(struct inode *dir, struct dentry **dentry, int only_unplug); -void ll_stop_statahead(struct inode *dir, void *key); +void ll_authorize_statahead(struct inode *dir, void *key); +void ll_deauthorize_statahead(struct inode *dir, void *key); blkcnt_t dirty_cnt(struct inode *inode); @@ -1086,25 +1098,31 @@ ll_statahead_mark(struct inode *dir, struct dentry *dentry) ldd->lld_sa_generation = sai->sai_generation; } -static inline int -d_need_statahead(struct inode *dir, struct dentry *dentryp) +static inline bool +dentry_need_statahead(struct inode *dir, struct dentry *dentry) { struct ll_inode_info *lli; struct ll_dentry_data *ldd; if (ll_i2sbi(dir)->ll_sa_max == 0) - return -EAGAIN; + return false; lli = ll_i2info(dir); + + /* + * statahead is not allowed for this dir, there may be three causes: + * 1. dir is not opened. + * 2. statahead hit ratio is too low. + * 3. previous stat started statahead thread failed. + */ + if (!lli->lli_sa_enabled) + return false; + /* not the same process, don't statahead */ if (lli->lli_opendir_pid != current_pid()) - return -EAGAIN; - - /* statahead has been stopped */ - if (!lli->lli_opendir_key) - return -EAGAIN; + return false; - ldd = ll_d2d(dentryp); + ldd = ll_d2d(dentry); /* * When stats a dentry, the system trigger more than once "revalidate" * or "lookup", for "getattr", for "getxattr", and maybe for others. @@ -1122,19 +1140,16 @@ d_need_statahead(struct inode *dir, struct dentry *dentryp) */ if (ldd && lli->lli_sai && ldd->lld_sa_generation == lli->lli_sai->sai_generation) - return -EAGAIN; + return false; - return 1; + return true; } static inline int ll_statahead_enter(struct inode *dir, struct dentry **dentryp, int only_unplug) { - int ret; - - ret = d_need_statahead(dir, *dentryp); - if (ret <= 0) - return ret; + if (!dentry_need_statahead(dir, *dentryp)) + return -EAGAIN; return do_statahead_enter(dir, dentryp, only_unplug); } diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 99aba6b..93fd69b 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -116,6 +116,7 @@ static struct ll_sb_info *ll_init_sbi(struct super_block *sb) sbi->ll_sa_max = LL_SA_RPC_DEF; atomic_set(&sbi->ll_sa_total, 0); atomic_set(&sbi->ll_sa_wrong, 0); + atomic_set(&sbi->ll_sa_running, 0); atomic_set(&sbi->ll_agl_total, 0); sbi->ll_flags |= LL_SBI_AGL_ENABLED; @@ -630,6 +631,12 @@ void ll_kill_super(struct super_block *sb) if (sbi) { sb->s_dev = sbi->ll_sdev_orig; sbi->ll_umounting = 1; + + /* wait running statahead threads to quit */ + while (atomic_read(&sbi->ll_sa_running) > 0) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(msecs_to_jiffies(MSEC_PER_SEC >> 3)); + } } } @@ -795,6 +802,7 @@ void ll_lli_init(struct ll_inode_info *lli) lli->lli_sai = NULL; spin_lock_init(&lli->lli_sa_lock); lli->lli_opendir_pid = 0; + lli->lli_sa_enabled = 0; } else { mutex_init(&lli->lli_size_mutex); lli->lli_symlink_name = NULL; diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c index 016463b..6577a66 100644 --- a/drivers/staging/lustre/lustre/llite/statahead.c +++ b/drivers/staging/lustre/lustre/llite/statahead.c @@ -281,25 +281,6 @@ ll_sa_entry_get_byindex(struct ll_statahead_info *sai, __u64 index) return NULL; } -static void ll_sa_entry_cleanup(struct ll_statahead_info *sai, - struct ll_sa_entry *entry) -{ - struct md_enqueue_info *minfo = entry->se_minfo; - struct ptlrpc_request *req = entry->se_req; - - if (minfo) { - entry->se_minfo = NULL; - ll_intent_release(&minfo->mi_it); - iput(minfo->mi_dir); - kfree(minfo); - } - - if (req) { - entry->se_req = NULL; - ptlrpc_req_finished(req); - } -} - static void ll_sa_entry_put(struct ll_statahead_info *sai, struct ll_sa_entry *entry) { @@ -312,7 +293,6 @@ static void ll_sa_entry_put(struct ll_statahead_info *sai, LASSERT(list_empty(&entry->se_list)); LASSERT(list_empty(&entry->se_hash)); - ll_sa_entry_cleanup(sai, entry); iput(entry->se_inode); kfree(entry); @@ -355,7 +335,10 @@ ll_sa_entry_fini(struct ll_statahead_info *sai, struct ll_sa_entry *entry) list_for_each_entry_safe(pos, next, &sai->sai_entries, se_link) { if (!is_omitted_entry(sai, pos->se_index)) break; - do_sa_entry_fini(sai, pos); + /* keep those whose statahead RPC not finished */ + if (pos->se_stat == SA_ENTRY_SUCC || + pos->se_stat == SA_ENTRY_INVA) + do_sa_entry_fini(sai, pos); } } @@ -363,12 +346,14 @@ ll_sa_entry_fini(struct ll_statahead_info *sai, struct ll_sa_entry *entry) * Inside lli_sa_lock. */ static void -do_sa_entry_to_stated(struct ll_statahead_info *sai, - struct ll_sa_entry *entry, enum se_stat stat) +__sa_entry_post_stat(struct ll_statahead_info *sai, struct ll_sa_entry *entry, + enum se_stat stat) { struct ll_sa_entry *se; struct list_head *pos = &sai->sai_entries_stated; + LASSERT(entry->se_stat == SA_ENTRY_INIT); + if (!list_empty(&entry->se_list)) list_del_init(&entry->se_list); @@ -388,23 +373,30 @@ do_sa_entry_to_stated(struct ll_statahead_info *sai, * \retval 1 -- entry to be destroyed. * \retval 0 -- entry is inserted into stated list. */ -static int -ll_sa_entry_to_stated(struct ll_statahead_info *sai, - struct ll_sa_entry *entry, enum se_stat stat) +static void +sa_entry_post_stat(struct ll_statahead_info *sai, struct ll_sa_entry *entry, + enum se_stat stat) { struct ll_inode_info *lli = ll_i2info(sai->sai_inode); - int ret = 1; + struct md_enqueue_info *minfo = entry->se_minfo; + struct ptlrpc_request *req = entry->se_req; + + /* release resources used in RPC */ + if (minfo) { + entry->se_minfo = NULL; + ll_intent_release(&minfo->mi_it); + iput(minfo->mi_dir); + kfree(minfo); + } - ll_sa_entry_cleanup(sai, entry); + if (req) { + entry->se_req = NULL; + ptlrpc_req_finished(req); + } spin_lock(&lli->lli_sa_lock); - if (likely(entry->se_stat != SA_ENTRY_DEST)) { - do_sa_entry_to_stated(sai, entry, stat); - ret = 0; - } + __sa_entry_post_stat(sai, entry, stat); spin_unlock(&lli->lli_sa_lock); - - return ret; } /* @@ -475,56 +467,46 @@ static struct ll_statahead_info *ll_sai_alloc(void) return sai; } -static inline struct ll_statahead_info * -ll_sai_get(struct ll_statahead_info *sai) +static inline struct ll_statahead_info *ll_sai_get(struct inode *dir) { - atomic_inc(&sai->sai_refcount); + struct ll_inode_info *lli = ll_i2info(dir); + struct ll_statahead_info *sai = NULL; + + spin_lock(&lli->lli_sa_lock); + sai = lli->lli_sai; + if (sai) + atomic_inc(&sai->sai_refcount); + spin_unlock(&lli->lli_sa_lock); + return sai; } static void ll_sai_put(struct ll_statahead_info *sai) { - struct inode *inode = sai->sai_inode; - struct ll_inode_info *lli = ll_i2info(inode); + struct ll_inode_info *lli = ll_i2info(sai->sai_inode); if (atomic_dec_and_lock(&sai->sai_refcount, &lli->lli_sa_lock)) { + struct ll_sb_info *sbi = ll_i2sbi(sai->sai_inode); struct ll_sa_entry *entry, *next; - if (unlikely(atomic_read(&sai->sai_refcount) > 0)) { - /* It is race case, the interpret callback just hold - * a reference count - */ - spin_unlock(&lli->lli_sa_lock); - return; - } - - LASSERT(!lli->lli_opendir_key); - LASSERT(thread_is_stopped(&sai->sai_thread)); - LASSERT(thread_is_stopped(&sai->sai_agl_thread)); - lli->lli_sai = NULL; - lli->lli_opendir_pid = 0; spin_unlock(&lli->lli_sa_lock); - if (sai->sai_sent > sai->sai_replied) - CDEBUG(D_READA, "statahead for dir "DFID - " does not finish: [sent:%llu] [replied:%llu]\n", - PFID(&lli->lli_fid), - sai->sai_sent, sai->sai_replied); + LASSERT(thread_is_stopped(&sai->sai_thread)); + LASSERT(thread_is_stopped(&sai->sai_agl_thread)); + LASSERT(sai->sai_sent == sai->sai_replied); list_for_each_entry_safe(entry, next, &sai->sai_entries, se_link) do_sa_entry_fini(sai, entry); - LASSERT(list_empty(&sai->sai_entries)); - LASSERT(list_empty(&sai->sai_entries_received)); - LASSERT(list_empty(&sai->sai_entries_stated)); - LASSERT(atomic_read(&sai->sai_cache_count) == 0); LASSERT(list_empty(&sai->sai_entries_agl)); + LASSERT(atomic_read(&sai->sai_refcount) == 0); - iput(inode); + iput(sai->sai_inode); kfree(sai); + atomic_dec(&sbi->ll_sa_running); } } @@ -588,29 +570,18 @@ static void ll_agl_trigger(struct inode *inode, struct ll_statahead_info *sai) iput(inode); } -static void ll_post_statahead(struct ll_statahead_info *sai) +/* prepare inode for received statahead entry, and add it into agl list */ +static void sa_post_one(struct ll_statahead_info *sai, + struct ll_sa_entry *entry) { struct inode *dir = sai->sai_inode; struct inode *child; - struct ll_inode_info *lli = ll_i2info(dir); - struct ll_sa_entry *entry; struct md_enqueue_info *minfo; struct lookup_intent *it; struct ptlrpc_request *req; struct mdt_body *body; int rc = 0; - spin_lock(&lli->lli_sa_lock); - if (unlikely(list_empty(&sai->sai_entries_received))) { - spin_unlock(&lli->lli_sa_lock); - return; - } - entry = list_entry(sai->sai_entries_received.next, - struct ll_sa_entry, se_list); - atomic_inc(&entry->se_refcount); - list_del_init(&entry->se_list); - spin_unlock(&lli->lli_sa_lock); - LASSERT(entry->se_handle != 0); minfo = entry->se_minfo; @@ -670,18 +641,56 @@ static void ll_post_statahead(struct ll_statahead_info *sai) ll_agl_add(sai, child, entry->se_index); out: - /* The "ll_sa_entry_to_stated()" will drop related ldlm ibits lock + /* The "sa_entry_post_stat()" will drop related ldlm ibits lock * reference count by calling "ll_intent_drop_lock()" in spite of the * above operations failed or not. Do not worry about calling * "ll_intent_drop_lock()" more than once. */ - rc = ll_sa_entry_to_stated(sai, entry, - rc < 0 ? SA_ENTRY_INVA : SA_ENTRY_SUCC); - if (rc == 0 && entry->se_index == sai->sai_index_wait) + sa_entry_post_stat(sai, entry, rc < 0 ? SA_ENTRY_INVA : SA_ENTRY_SUCC); + if (entry->se_index == sai->sai_index_wait) wake_up(&sai->sai_waitq); ll_sa_entry_put(sai, entry); } +static void ll_post_statahead(struct ll_statahead_info *sai) +{ + struct ll_inode_info *lli; + + lli = ll_i2info(sai->sai_inode); + + while (!sa_received_empty(sai)) { + struct ll_sa_entry *entry; + + spin_lock(&lli->lli_sa_lock); + if (unlikely(sa_received_empty(sai))) { + spin_unlock(&lli->lli_sa_lock); + break; + } + entry = list_entry(sai->sai_entries_received.next, + struct ll_sa_entry, se_list); + atomic_inc(&entry->se_refcount); + list_del_init(&entry->se_list); + spin_unlock(&lli->lli_sa_lock); + + sa_post_one(sai, entry); + } + + spin_lock(&lli->lli_agl_lock); + while (!agl_list_empty(sai)) { + struct ll_inode_info *clli; + + clli = list_entry(sai->sai_entries_agl.next, + struct ll_inode_info, lli_agl_list); + list_del_init(&clli->lli_agl_list); + spin_unlock(&lli->lli_agl_lock); + + ll_agl_trigger(&clli->lli_vfs_inode, sai); + + spin_lock(&lli->lli_agl_lock); + } + spin_unlock(&lli->lli_agl_lock); +} + static int ll_statahead_interpret(struct ptlrpc_request *req, struct md_enqueue_info *minfo, int rc) { @@ -690,72 +699,43 @@ static int ll_statahead_interpret(struct ptlrpc_request *req, struct ll_inode_info *lli = ll_i2info(dir); struct ll_statahead_info *sai = NULL; struct ll_sa_entry *entry; - __u64 handle = 0; int wakeup; if (it_disposition(it, DISP_LOOKUP_NEG)) rc = -ENOENT; - if (rc == 0) { - /* release ibits lock ASAP to avoid deadlock when statahead - * thread enqueues lock on parent in readdir and another - * process enqueues lock on child with parent lock held, eg. - * unlink. - */ - handle = it->it_lock_handle; - ll_intent_drop_lock(it); - } + sai = ll_sai_get(dir); + LASSERT(sai); + LASSERT(!thread_is_stopped(&sai->sai_thread)); spin_lock(&lli->lli_sa_lock); - /* stale entry */ - if (unlikely(!lli->lli_sai || - lli->lli_sai->sai_generation != minfo->mi_generation)) { - spin_unlock(&lli->lli_sa_lock); - rc = -ESTALE; - goto out; + entry = ll_sa_entry_get_byindex(sai, minfo->mi_cbdata); + LASSERT(entry); + if (rc) { + __sa_entry_post_stat(sai, entry, SA_ENTRY_INVA); + wakeup = (entry->se_index == sai->sai_index_wait); } else { - sai = ll_sai_get(lli->lli_sai); - if (unlikely(!thread_is_running(&sai->sai_thread))) { - sai->sai_replied++; - spin_unlock(&lli->lli_sa_lock); - rc = -EBADFD; - goto out; - } - - entry = ll_sa_entry_get_byindex(sai, minfo->mi_cbdata); - if (!entry) { - sai->sai_replied++; - spin_unlock(&lli->lli_sa_lock); - rc = -EIDRM; - goto out; - } - - if (rc != 0) { - do_sa_entry_to_stated(sai, entry, SA_ENTRY_INVA); - wakeup = (entry->se_index == sai->sai_index_wait); - } else { - entry->se_minfo = minfo; - entry->se_req = ptlrpc_request_addref(req); - /* Release the async ibits lock ASAP to avoid deadlock - * when statahead thread tries to enqueue lock on parent - * for readpage and other tries to enqueue lock on child - * with parent's lock held, for example: unlink. - */ - entry->se_handle = handle; - wakeup = list_empty(&sai->sai_entries_received); - list_add_tail(&entry->se_list, - &sai->sai_entries_received); - } - sai->sai_replied++; - spin_unlock(&lli->lli_sa_lock); - - ll_sa_entry_put(sai, entry); - if (wakeup) - wake_up(&sai->sai_thread.t_ctl_waitq); + entry->se_minfo = minfo; + entry->se_req = ptlrpc_request_addref(req); + /* + * Release the async ibits lock ASAP to avoid deadlock + * when statahead thread tries to enqueue lock on parent + * for readpage and other tries to enqueue lock on child + * with parent's lock held, for example: unlink. + */ + entry->se_handle = it->it_lock_handle; + ll_intent_drop_lock(it); + wakeup = sa_received_empty(sai); + list_add_tail(&entry->se_list, &sai->sai_entries_received); } + sai->sai_replied++; + spin_unlock(&lli->lli_sa_lock); -out: - if (rc != 0) { + ll_sa_entry_put(sai, entry); + if (wakeup) + wake_up(&sai->sai_thread.t_ctl_waitq); + + if (rc) { ll_intent_release(it); iput(dir); kfree(minfo); @@ -782,7 +762,6 @@ static int sa_args_init(struct inode *dir, struct inode *child, struct ldlm_enqueue_info **pei) { const struct qstr *qstr = &entry->se_qstr; - struct ll_inode_info *lli = ll_i2info(dir); struct md_enqueue_info *minfo; struct ldlm_enqueue_info *einfo; struct md_op_data *op_data; @@ -808,7 +787,6 @@ static int sa_args_init(struct inode *dir, struct inode *child, minfo->mi_it.it_op = IT_GETATTR; minfo->mi_dir = igrab(dir); minfo->mi_cb = ll_statahead_interpret; - minfo->mi_generation = lli->lli_sai->sai_generation; minfo->mi_cbdata = entry->se_index; einfo->ei_type = LDLM_IBITS; @@ -889,8 +867,8 @@ static int do_sa_revalidate(struct inode *dir, struct ll_sa_entry *entry, return rc; } -static void ll_statahead_one(struct dentry *parent, const char *entry_name, - int entry_name_len) +static void ll_statahead_one(struct dentry *parent, const char *name, + const int name_len) { struct inode *dir = d_inode(parent); struct ll_inode_info *lli = ll_i2info(dir); @@ -898,10 +876,9 @@ static void ll_statahead_one(struct dentry *parent, const char *entry_name, struct dentry *dentry = NULL; struct ll_sa_entry *entry; int rc; - int rc1; - entry = ll_sa_entry_alloc(parent, sai, sai->sai_index, entry_name, - entry_name_len); + entry = ll_sa_entry_alloc(parent, sai, sai->sai_index, name, + name_len); if (IS_ERR(entry)) return; @@ -912,15 +889,15 @@ static void ll_statahead_one(struct dentry *parent, const char *entry_name, rc = do_sa_revalidate(dir, entry, dentry); if (rc == 1 && agl_should_run(sai, d_inode(dentry))) ll_agl_add(sai, d_inode(dentry), entry->se_index); + } + if (dentry) dput(dentry); - } if (rc) { - rc1 = ll_sa_entry_to_stated(sai, entry, - rc < 0 ? SA_ENTRY_INVA : - SA_ENTRY_SUCC); - if (rc1 == 0 && entry->se_index == sai->sai_index_wait) + sa_entry_post_stat(sai, entry, + rc < 0 ? SA_ENTRY_INVA : SA_ENTRY_SUCC); + if (entry->se_index == sai->sai_index_wait) wake_up(&sai->sai_waitq); } else { sai->sai_sent++; @@ -938,10 +915,12 @@ static int ll_agl_thread(void *arg) struct ll_inode_info *plli = ll_i2info(dir); struct ll_inode_info *clli; struct ll_sb_info *sbi = ll_i2sbi(dir); - struct ll_statahead_info *sai = ll_sai_get(plli->lli_sai); - struct ptlrpc_thread *thread = &sai->sai_agl_thread; + struct ll_statahead_info *sai; + struct ptlrpc_thread *thread; struct l_wait_info lwi = { 0 }; + sai = ll_sai_get(dir); + thread = &sai->sai_agl_thread; thread->t_pid = current_pid(); CDEBUG(D_READA, "agl thread started: sai %p, parent %pd\n", sai, parent); @@ -1030,12 +1009,11 @@ static int ll_statahead_thread(void *arg) { struct dentry *parent = arg; struct inode *dir = d_inode(parent); - struct ll_inode_info *plli = ll_i2info(dir); - struct ll_inode_info *clli; + struct ll_inode_info *lli = ll_i2info(dir); struct ll_sb_info *sbi = ll_i2sbi(dir); - struct ll_statahead_info *sai = ll_sai_get(plli->lli_sai); - struct ptlrpc_thread *thread = &sai->sai_thread; - struct ptlrpc_thread *agl_thread = &sai->sai_agl_thread; + struct ll_statahead_info *sai; + struct ptlrpc_thread *thread; + struct ptlrpc_thread *agl_thread; struct page *page = NULL; __u64 pos = 0; int first = 0; @@ -1044,6 +1022,9 @@ static int ll_statahead_thread(void *arg) struct ll_dir_chain chain; struct l_wait_info lwi = { 0 }; + sai = ll_sai_get(dir); + thread = &sai->sai_thread; + agl_thread = &sai->sai_agl_thread; thread->t_pid = current_pid(); CDEBUG(D_READA, "statahead thread starting: sai %p, parent %pd\n", sai, parent); @@ -1052,7 +1033,7 @@ static int ll_statahead_thread(void *arg) LUSTRE_OPC_ANY, dir); if (IS_ERR(op_data)) { rc = PTR_ERR(op_data); - goto out_put; + goto out; } op_data->op_max_pages = ll_i2sbi(dir)->ll_md_brw_pages; @@ -1061,33 +1042,35 @@ static int ll_statahead_thread(void *arg) ll_start_agl(parent, sai); atomic_inc(&sbi->ll_sa_total); - spin_lock(&plli->lli_sa_lock); + spin_lock(&lli->lli_sa_lock); if (thread_is_init(thread)) /* If someone else has changed the thread state * (e.g. already changed to SVC_STOPPING), we can't just * blindly overwrite that setting. */ thread_set_flags(thread, SVC_RUNNING); - spin_unlock(&plli->lli_sa_lock); + spin_unlock(&lli->lli_sa_lock); wake_up(&thread->t_ctl_waitq); ll_dir_chain_init(&chain); - page = ll_get_dir_page(dir, op_data, pos, &chain); - - while (1) { + while (pos != MDS_DIR_END_OFF && thread_is_running(thread)) { struct lu_dirpage *dp; struct lu_dirent *ent; + sai->sai_in_readpage = 1; + page = ll_get_dir_page(dir, op_data, pos, &chain); + sai->sai_in_readpage = 0; if (IS_ERR(page)) { rc = PTR_ERR(page); CDEBUG(D_READA, "error reading dir "DFID" at %llu/%llu: opendir_pid = %u: rc = %d\n", PFID(ll_inode2fid(dir)), pos, sai->sai_index, - plli->lli_opendir_pid, rc); - goto out; + lli->lli_opendir_pid, rc); + break; } dp = page_address(page); - for (ent = lu_dirent_start(dp); ent; + for (ent = lu_dirent_start(dp); + ent && thread_is_running(thread) && !sa_low_hit(sai); ent = lu_dirent_next(ent)) { __u64 hash; int namelen; @@ -1134,120 +1117,63 @@ static int ll_statahead_thread(void *arg) if (unlikely(++first == 1)) continue; -keep_it: - l_wait_event(thread->t_ctl_waitq, - !sa_sent_full(sai) || - !list_empty(&sai->sai_entries_received) || - !list_empty(&sai->sai_entries_agl) || - !thread_is_running(thread), - &lwi); - -interpret_it: - while (!list_empty(&sai->sai_entries_received)) + /* wait for spare statahead window */ + do { + l_wait_event(thread->t_ctl_waitq, + !sa_sent_full(sai) || + !list_empty(&sai->sai_entries_received) || + !list_empty(&sai->sai_entries_agl) || + !thread_is_running(thread), + &lwi); ll_post_statahead(sai); + } while (sa_sent_full(sai) && + thread_is_running(thread)); - if (unlikely(!thread_is_running(thread))) { - ll_release_page(dir, page, false); - rc = 0; - goto out; - } - - /* If no window for metadata statahead, but there are - * some AGL entries to be triggered, then try to help - * to process the AGL entries. - */ - if (sa_sent_full(sai)) { - spin_lock(&plli->lli_agl_lock); - while (!list_empty(&sai->sai_entries_agl)) { - clli = list_entry(sai->sai_entries_agl.next, - struct ll_inode_info, lli_agl_list); - list_del_init(&clli->lli_agl_list); - spin_unlock(&plli->lli_agl_lock); - ll_agl_trigger(&clli->lli_vfs_inode, - sai); - - if (!list_empty(&sai->sai_entries_received)) - goto interpret_it; - - if (unlikely(!thread_is_running(thread))) { - ll_release_page(dir, page, false); - rc = 0; - goto out; - } - - if (!sa_sent_full(sai)) - goto do_it; - - spin_lock(&plli->lli_agl_lock); - } - spin_unlock(&plli->lli_agl_lock); - - goto keep_it; - } -do_it: ll_statahead_one(parent, name, namelen); } pos = le64_to_cpu(dp->ldp_hash_end); - if (pos == MDS_DIR_END_OFF) { - /* - * End of directory reached. - */ - ll_release_page(dir, page, false); - while (1) { - l_wait_event(thread->t_ctl_waitq, - !list_empty(&sai->sai_entries_received) || - sai->sai_sent == sai->sai_replied || - !thread_is_running(thread), - &lwi); + ll_release_page(dir, page, + le32_to_cpu(dp->ldp_flags) & LDF_COLLIDE); - while (!list_empty(&sai->sai_entries_received)) - ll_post_statahead(sai); - - if (unlikely(!thread_is_running(thread))) { - rc = 0; - goto out; - } + if (sa_low_hit(sai)) { + rc = -EFAULT; + atomic_inc(&sbi->ll_sa_wrong); + CDEBUG(D_READA, "Statahead for dir "DFID" hit ratio too low: hit/miss %llu/%llu, sent/replied %llu/%llu, stopping statahead thread: pid %d\n", + PFID(&lli->lli_fid), sai->sai_hit, + sai->sai_miss, sai->sai_sent, + sai->sai_replied, current_pid()); + break; + } + } + ll_dir_chain_fini(&chain); + ll_finish_md_op_data(op_data); - if (sai->sai_sent == sai->sai_replied && - list_empty(&sai->sai_entries_received)) - break; - } + if (rc < 0) { + spin_lock(&lli->lli_sa_lock); + thread_set_flags(thread, SVC_STOPPING); + lli->lli_sa_enabled = 0; + spin_unlock(&lli->lli_sa_lock); + } - spin_lock(&plli->lli_agl_lock); - while (!list_empty(&sai->sai_entries_agl) && - thread_is_running(thread)) { - clli = list_entry(sai->sai_entries_agl.next, - struct ll_inode_info, lli_agl_list); - list_del_init(&clli->lli_agl_list); - spin_unlock(&plli->lli_agl_lock); - ll_agl_trigger(&clli->lli_vfs_inode, sai); - spin_lock(&plli->lli_agl_lock); - } - spin_unlock(&plli->lli_agl_lock); + /* + * statahead is finished, but statahead entries need to be cached, wait + * for file release to stop me. + */ + while (thread_is_running(thread)) { + l_wait_event(thread->t_ctl_waitq, + !sa_received_empty(sai) || + !agl_list_empty(sai) || + !thread_is_running(thread), + &lwi); - rc = 0; - goto out; - } else { - /* - * chain is exhausted. - * Normal case: continue to the next page. - */ - ll_release_page(dir, page, - le32_to_cpu(dp->ldp_flags) & LDF_COLLIDE); - sai->sai_in_readpage = 1; - page = ll_get_dir_page(dir, op_data, pos, &chain); - sai->sai_in_readpage = 0; - } + ll_post_statahead(sai); } out: - ll_dir_chain_fini(&chain); - ll_finish_md_op_data(op_data); -out_put: if (sai->sai_agl_valid) { - spin_lock(&plli->lli_agl_lock); + spin_lock(&lli->lli_agl_lock); thread_set_flags(agl_thread, SVC_STOPPING); - spin_unlock(&plli->lli_agl_lock); + spin_unlock(&lli->lli_agl_lock); wake_up(&agl_thread->t_ctl_waitq); CDEBUG(D_READA, "stop agl thread: sai %p pid %u\n", @@ -1257,21 +1183,27 @@ out_put: &lwi); } else { /* Set agl_thread flags anyway. */ - thread_set_flags(&sai->sai_agl_thread, SVC_STOPPED); + thread_set_flags(agl_thread, SVC_STOPPED); } - spin_lock(&plli->lli_sa_lock); - if (!list_empty(&sai->sai_entries_received)) { - thread_set_flags(thread, SVC_STOPPING); - spin_unlock(&plli->lli_sa_lock); - - /* To release the resources held by received entries. */ - while (!list_empty(&sai->sai_entries_received)) - ll_post_statahead(sai); - spin_lock(&plli->lli_sa_lock); + /* + * wait for inflight statahead RPCs to finish, and then we can free sai + * safely because statahead RPC will access sai data + */ + while (sai->sai_sent != sai->sai_replied) { + /* in case we're not woken up, timeout wait */ + lwi = LWI_TIMEOUT(HZ >> 3, NULL, NULL); + l_wait_event(thread->t_ctl_waitq, + sai->sai_sent == sai->sai_replied, &lwi); } + + /* release resources held by received entries. */ + ll_post_statahead(sai); + + spin_lock(&lli->lli_sa_lock); thread_set_flags(thread, SVC_STOPPED); - spin_unlock(&plli->lli_sa_lock); + spin_unlock(&lli->lli_sa_lock); + wake_up(&sai->sai_waitq); wake_up(&thread->t_ctl_waitq); ll_sai_put(sai); @@ -1281,52 +1213,54 @@ out_put: return rc; } -/** - * called in ll_file_release(). - */ -void ll_stop_statahead(struct inode *dir, void *key) +/* authorize opened dir handle @key to statahead later */ +void ll_authorize_statahead(struct inode *dir, void *key) { struct ll_inode_info *lli = ll_i2info(dir); - if (unlikely(!key)) - return; - spin_lock(&lli->lli_sa_lock); - if (lli->lli_opendir_key != key || lli->lli_opendir_pid == 0) { - spin_unlock(&lli->lli_sa_lock); - return; + if (!lli->lli_opendir_key && !lli->lli_sai) { + /* + * if lli_sai is not NULL, it means previous statahead is not + * finished yet, we'd better not start a new statahead for now. + */ + LASSERT(!lli->lli_opendir_pid); + lli->lli_opendir_key = key; + lli->lli_opendir_pid = current_pid(); + lli->lli_sa_enabled = 1; } + spin_unlock(&lli->lli_sa_lock); +} - lli->lli_opendir_key = NULL; +/* + * deauthorize opened dir handle @key to statahead, but statahead thread may + * still be running, notify it to quit. + */ +void ll_deauthorize_statahead(struct inode *dir, void *key) +{ + struct ll_inode_info *lli = ll_i2info(dir); + struct ll_statahead_info *sai; - if (lli->lli_sai) { - struct l_wait_info lwi = { 0 }; - struct ptlrpc_thread *thread = &lli->lli_sai->sai_thread; + LASSERT(lli->lli_opendir_key == key); + LASSERT(lli->lli_opendir_pid); - if (!thread_is_stopped(thread)) { - thread_set_flags(thread, SVC_STOPPING); - spin_unlock(&lli->lli_sa_lock); - wake_up(&thread->t_ctl_waitq); - - CDEBUG(D_READA, "stop statahead thread: sai %p pid %u\n", - lli->lli_sai, (unsigned int)thread->t_pid); - l_wait_event(thread->t_ctl_waitq, - thread_is_stopped(thread), - &lwi); - } else { - spin_unlock(&lli->lli_sa_lock); - } + CDEBUG(D_READA, "deauthorize statahead for "DFID"\n", + PFID(&lli->lli_fid)); + spin_lock(&lli->lli_sa_lock); + lli->lli_opendir_key = NULL; + lli->lli_opendir_pid = 0; + lli->lli_sa_enabled = 0; + sai = lli->lli_sai; + if (sai && thread_is_running(&sai->sai_thread)) { /* - * Put the ref which was held when first statahead_enter. - * It maybe not the last ref for some statahead requests - * maybe inflight. + * statahead thread may not quit yet because it needs to cache + * stated entries, now it's time to tell it to quit. */ - ll_sai_put(lli->lli_sai); - } else { - lli->lli_opendir_pid = 0; - spin_unlock(&lli->lli_sa_lock); + thread_set_flags(&sai->sai_thread, SVC_STOPPING); + wake_up(&sai->sai_thread.t_ctl_waitq); } + spin_unlock(&lli->lli_sa_lock); } enum { @@ -1465,175 +1399,137 @@ out: static void ll_sai_unplug(struct ll_statahead_info *sai, struct ll_sa_entry *entry) { - struct ptlrpc_thread *thread = &sai->sai_thread; - struct ll_sb_info *sbi = ll_i2sbi(sai->sai_inode); - int hit; + if (entry && entry->se_stat == SA_ENTRY_SUCC) { + struct ll_sb_info *sbi = ll_i2sbi(sai->sai_inode); - if (entry && entry->se_stat == SA_ENTRY_SUCC) - hit = 1; - else - hit = 0; - - ll_sa_entry_fini(sai, entry); - if (hit) { sai->sai_hit++; sai->sai_consecutive_miss = 0; sai->sai_max = min(2 * sai->sai_max, sbi->ll_sa_max); } else { - struct ll_inode_info *lli = ll_i2info(sai->sai_inode); - sai->sai_miss++; sai->sai_consecutive_miss++; - if (sa_low_hit(sai) && thread_is_running(thread)) { - atomic_inc(&sbi->ll_sa_wrong); - CDEBUG(D_READA, "Statahead for dir " DFID " hit ratio too low: hit/miss %llu/%llu, sent/replied %llu/%llu, stopping statahead thread\n", - PFID(&lli->lli_fid), sai->sai_hit, - sai->sai_miss, sai->sai_sent, - sai->sai_replied); - spin_lock(&lli->lli_sa_lock); - if (!thread_is_stopped(thread)) - thread_set_flags(thread, SVC_STOPPING); - spin_unlock(&lli->lli_sa_lock); - } } - - if (!thread_is_stopped(thread)) - wake_up(&thread->t_ctl_waitq); + ll_sa_entry_fini(sai, entry); + wake_up(&sai->sai_thread.t_ctl_waitq); } -/** - * Start statahead thread if this is the first dir entry. - * Otherwise if a thread is started already, wait it until it is ahead of me. - * \retval 1 -- find entry with lock in cache, the caller needs to do - * nothing. - * \retval 0 -- find entry in cache, but without lock, the caller needs - * refresh from MDS. - * \retval others -- the caller need to process as non-statahead. - */ -int do_statahead_enter(struct inode *dir, struct dentry **dentryp, - int only_unplug) +static int revalidate_statahead_dentry(struct inode *dir, + struct ll_statahead_info *sai, + struct dentry **dentryp, + int only_unplug) { - struct ll_inode_info *lli = ll_i2info(dir); - struct ll_statahead_info *sai = lli->lli_sai; - struct dentry *parent; - struct ll_sa_entry *entry; - struct ptlrpc_thread *thread; - struct l_wait_info lwi = { 0 }; - struct task_struct *task; - int rc = 0; - struct ll_inode_info *plli; - - LASSERT(lli->lli_opendir_pid == current_pid()); - - if (sai) { - thread = &sai->sai_thread; - if (unlikely(thread_is_stopped(thread) && - list_empty(&sai->sai_entries_stated))) { - /* to release resource */ - ll_stop_statahead(dir, lli->lli_opendir_key); - return -EAGAIN; - } + struct ll_sa_entry *entry = NULL; + struct l_wait_info lwi = { 0 }; + int rc = 0; - if ((*dentryp)->d_name.name[0] == '.') { - if (sai->sai_ls_all || - sai->sai_miss_hidden >= sai->sai_skip_hidden) { + if ((*dentryp)->d_name.name[0] == '.') { + if (sai->sai_ls_all || + sai->sai_miss_hidden >= sai->sai_skip_hidden) { + /* + * Hidden dentry is the first one, or statahead + * thread does not skip so many hidden dentries + * before "sai_ls_all" enabled as below. + */ + } else { + if (!sai->sai_ls_all) /* - * Hidden dentry is the first one, or statahead - * thread does not skip so many hidden dentries - * before "sai_ls_all" enabled as below. + * It maybe because hidden dentry is not + * the first one, "sai_ls_all" was not + * set, then "ls -al" missed. Enable + * "sai_ls_all" for such case. */ - } else { - if (!sai->sai_ls_all) - /* - * It maybe because hidden dentry is not - * the first one, "sai_ls_all" was not - * set, then "ls -al" missed. Enable - * "sai_ls_all" for such case. - */ - sai->sai_ls_all = 1; + sai->sai_ls_all = 1; - /* - * Such "getattr" has been skipped before - * "sai_ls_all" enabled as above. - */ - sai->sai_miss_hidden++; - return -EAGAIN; - } + /* + * Such "getattr" has been skipped before + * "sai_ls_all" enabled as above. + */ + sai->sai_miss_hidden++; + return -EAGAIN; } + } - entry = ll_sa_entry_get_byname(sai, &(*dentryp)->d_name); - if (!entry || only_unplug) { + entry = ll_sa_entry_get_byname(sai, &(*dentryp)->d_name); + if (!entry || only_unplug) { + ll_sai_unplug(sai, entry); + return entry ? 1 : -EAGAIN; + } + + /* if statahead is busy in readdir, help it do post-work */ + if (!ll_sa_entry_stated(entry) && sai->sai_in_readpage) + ll_post_statahead(sai); + + if (!ll_sa_entry_stated(entry)) { + sai->sai_index_wait = entry->se_index; + lwi = LWI_TIMEOUT_INTR(cfs_time_seconds(30), NULL, + LWI_ON_SIGNAL_NOOP, NULL); + rc = l_wait_event(sai->sai_waitq, + ll_sa_entry_stated(entry) || + thread_is_stopped(&sai->sai_thread), + &lwi); + if (rc < 0) { ll_sai_unplug(sai, entry); - return entry ? 1 : -EAGAIN; + return -EAGAIN; } + } - /* if statahead is busy in readdir, help it do post-work */ - while (!ll_sa_entry_stated(entry) && sai->sai_in_readpage && - !sa_received_empty(sai)) - ll_post_statahead(sai); - - if (!ll_sa_entry_stated(entry)) { - sai->sai_index_wait = entry->se_index; - lwi = LWI_TIMEOUT_INTR(cfs_time_seconds(30), NULL, - LWI_ON_SIGNAL_NOOP, NULL); - rc = l_wait_event(sai->sai_waitq, - ll_sa_entry_stated(entry) || - thread_is_stopped(thread), - &lwi); - if (rc < 0) { - ll_sai_unplug(sai, entry); - return -EAGAIN; - } - } + if (entry->se_stat == SA_ENTRY_SUCC && entry->se_inode) { + struct inode *inode = entry->se_inode; + struct lookup_intent it = { .it_op = IT_GETATTR, + .it_lock_handle = entry->se_handle }; + __u64 bits; + + rc = md_revalidate_lock(ll_i2mdexp(dir), &it, + ll_inode2fid(inode), &bits); + if (rc == 1) { + if (!(*dentryp)->d_inode) { + struct dentry *alias; - if (entry->se_stat == SA_ENTRY_SUCC && entry->se_inode) { - struct inode *inode = entry->se_inode; - struct lookup_intent it = { .it_op = IT_GETATTR, - .it_lock_handle = - entry->se_handle }; - __u64 bits; - - rc = md_revalidate_lock(ll_i2mdexp(dir), &it, - ll_inode2fid(inode), &bits); - if (rc == 1) { - if (!d_inode(*dentryp)) { - struct dentry *alias; - - alias = ll_splice_alias(inode, - *dentryp); - if (IS_ERR(alias)) { - ll_sai_unplug(sai, entry); - return PTR_ERR(alias); - } - *dentryp = alias; - } else if (d_inode(*dentryp) != inode) { - /* revalidate, but inode is recreated */ - CDEBUG(D_READA, "%s: stale dentry %pd inode "DFID", statahead inode "DFID"\n", - ll_get_fsname(d_inode(*dentryp)->i_sb, NULL, 0), - *dentryp, - PFID(ll_inode2fid(d_inode(*dentryp))), - PFID(ll_inode2fid(inode))); - ll_intent_release(&it); + alias = ll_splice_alias(inode, *dentryp); + if (IS_ERR(alias)) { ll_sai_unplug(sai, entry); - return -ESTALE; - } else { - iput(inode); + return PTR_ERR(alias); } - entry->se_inode = NULL; - - if ((bits & MDS_INODELOCK_LOOKUP) && - d_lustre_invalid(*dentryp)) - d_lustre_revalidate(*dentryp); - ll_intent_release(&it); + *dentryp = alias; + } else if ((*dentryp)->d_inode != inode) { + /* revalidate, but inode is recreated */ + CDEBUG(D_READA, + "%s: stale dentry %pd inode "DFID", statahead inode "DFID"\n", + ll_get_fsname((*dentryp)->d_inode->i_sb, + NULL, 0), + *dentryp, + PFID(ll_inode2fid((*dentryp)->d_inode)), + PFID(ll_inode2fid(inode))); + rc = -ESTALE; + goto out_unplug; + } else { + iput(inode); } - } + entry->se_inode = NULL; - ll_sai_unplug(sai, entry); - return rc; + if ((bits & MDS_INODELOCK_LOOKUP) && + d_lustre_invalid(*dentryp)) + d_lustre_revalidate(*dentryp); + ll_intent_release(&it); + } } +out_unplug: + ll_sai_unplug(sai, entry); + return rc; +} + +static int start_statahead_thread(struct inode *dir, struct dentry *dentry) +{ + struct ll_inode_info *lli = ll_i2info(dir); + struct ll_statahead_info *sai = NULL; + struct l_wait_info lwi = { 0 }; + struct ptlrpc_thread *thread; + struct task_struct *task; + struct dentry *parent; + int rc; /* I am the "lli_opendir_pid" owner, only me can set "lli_sai". */ - rc = is_first_dirent(dir, *dentryp); + rc = is_first_dirent(dir, dentry); if (rc == LS_NONE_FIRST_DE) { /* It is not "ls -{a}l" operation, no need statahead for it. */ rc = -EAGAIN; @@ -1656,13 +1552,12 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp, } /* get parent reference count here, and put it in ll_statahead_thread */ - parent = dget((*dentryp)->d_parent); + parent = dget(dentry->d_parent); if (unlikely(sai->sai_inode != d_inode(parent))) { struct ll_inode_info *nlli = ll_i2info(d_inode(parent)); CWARN("Race condition, someone changed %pd just now: old parent "DFID", new parent "DFID"\n", - *dentryp, - PFID(&lli->lli_fid), PFID(&nlli->lli_fid)); + dentry, PFID(&lli->lli_fid), PFID(&nlli->lli_fid)); dput(parent); iput(sai->sai_inode); rc = -EAGAIN; @@ -1672,30 +1567,18 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp, CDEBUG(D_READA, "start statahead thread: sai %p, parent %pd\n", sai, parent); - /* The sai buffer already has one reference taken at allocation time, - * but as soon as we expose the sai by attaching it to the lli that - * default reference can be dropped by another thread calling - * ll_stop_statahead. We need to take a local reference to protect - * the sai buffer while we intend to access it. - */ - ll_sai_get(sai); lli->lli_sai = sai; - plli = ll_i2info(d_inode(parent)); task = kthread_run(ll_statahead_thread, parent, "ll_sa_%u", - plli->lli_opendir_pid); + lli->lli_opendir_pid); thread = &sai->sai_thread; if (IS_ERR(task)) { rc = PTR_ERR(task); - CERROR("can't start ll_sa thread, rc: %d\n", rc); + CERROR("cannot start ll_sa thread: rc = %d\n", rc); dput(parent); lli->lli_opendir_key = NULL; thread_set_flags(thread, SVC_STOPPED); thread_set_flags(&sai->sai_agl_thread, SVC_STOPPED); - /* Drop both our own local reference and the default - * reference from allocation time. - */ - ll_sai_put(sai); ll_sai_put(sai); LASSERT(!lli->lli_sai); return -EAGAIN; @@ -1704,6 +1587,7 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp, l_wait_event(thread->t_ctl_waitq, thread_is_running(thread) || thread_is_stopped(thread), &lwi); + atomic_inc(&ll_i2sbi(d_inode(parent))->ll_sa_running); ll_sai_put(sai); /* @@ -1717,6 +1601,37 @@ out: spin_lock(&lli->lli_sa_lock); lli->lli_opendir_key = NULL; lli->lli_opendir_pid = 0; + lli->lli_sa_enabled = 0; spin_unlock(&lli->lli_sa_lock); + return rc; } + +/** + * Start statahead thread if this is the first dir entry. + * Otherwise if a thread is started already, wait it until it is ahead of me. + * \retval 1 -- find entry with lock in cache, the caller needs to do + * nothing. + * \retval 0 -- find entry in cache, but without lock, the caller needs + * refresh from MDS. + * \retval others -- the caller need to process as non-statahead. + */ +int do_statahead_enter(struct inode *dir, struct dentry **dentryp, + int only_unplug) +{ + struct ll_statahead_info *sai; + + sai = ll_sai_get(dir); + if (sai) { + int rc; + + rc = revalidate_statahead_dentry(dir, sai, dentryp, + only_unplug); + CDEBUG(D_READA, "revalidate statahead %pd: %d.\n", + *dentryp, rc); + ll_sai_put(sai); + return rc; + } + + return start_statahead_thread(dir, *dentryp); +} -- cgit v0.10.2 From f06d65a1587a7f16ec191dc81ab94dc3b9c19e6f Mon Sep 17 00:00:00 2001 From: Vitaly Fertman <vitaly_fertman@xyratex.com> Date: Sun, 18 Sep 2016 16:37:26 -0400 Subject: staging: lustre: ldlm: reconstruct proper flags on enqueue resend otherwise, waiting lock may get granted as no BLOCKED_GRANTED flag is returned Signed-off-by: Vitaly Fertman <vitaly_fertman@xyratex.com> Xyratex-bug-id: MRP-1944 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5496 Reviewed-on: http://review.whamcloud.com/11644 Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c index 78a8450..861f36f 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c @@ -470,8 +470,7 @@ ldlm_flock_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data) if (flags & LDLM_FL_FAILED) goto granted; - if (!(flags & (LDLM_FL_BLOCK_WAIT | LDLM_FL_BLOCK_GRANTED | - LDLM_FL_BLOCK_CONV))) { + if (!(flags & LDLM_FL_BLOCKED_MASK)) { if (!data) /* mds granted the lock in the reply */ goto granted; diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c index 55b7460..f516106 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c @@ -1549,8 +1549,7 @@ enum ldlm_error ldlm_lock_enqueue(struct ldlm_namespace *ns, * before we got a chance to actually enqueue it. We don't * need to do anything else. */ - *flags &= ~(LDLM_FL_BLOCK_GRANTED | - LDLM_FL_BLOCK_CONV | LDLM_FL_BLOCK_WAIT); + *flags &= ~LDLM_FL_BLOCKED_MASK; goto out; } diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index f4364f9..cc835cb 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -177,8 +177,7 @@ int ldlm_completion_ast_async(struct ldlm_lock *lock, __u64 flags, void *data) return 0; } - if (!(flags & (LDLM_FL_BLOCK_WAIT | LDLM_FL_BLOCK_GRANTED | - LDLM_FL_BLOCK_CONV))) { + if (!(flags & LDLM_FL_BLOCKED_MASK)) { wake_up(&lock->l_waitq); return ldlm_completion_tail(lock); } @@ -224,8 +223,7 @@ int ldlm_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data) goto noreproc; } - if (!(flags & (LDLM_FL_BLOCK_WAIT | LDLM_FL_BLOCK_GRANTED | - LDLM_FL_BLOCK_CONV))) { + if (!(flags & LDLM_FL_BLOCKED_MASK)) { wake_up(&lock->l_waitq); return 0; } -- cgit v0.10.2 From 9b00e00b7d851b51f3105eeb89e88ecd297ae5cf Mon Sep 17 00:00:00 2001 From: Vitaly Fertman <vitaly_fertman@xyratex.com> Date: Sun, 18 Sep 2016 16:37:27 -0400 Subject: staging: lustre: ldlm: resend AST callbacks While clients will resend client->server RPCs, servers would not resend server->client RPCs such as LDLM callbacks (blocking or completion callbacks/ASTs). This could result in clients being evicted from the server if blocking callbacks were dropped by the network (a failed router or lossy network) and the client did not cancel the requested lock in time. In order to fix this problem, this patch adds the ability to resend LDLM callbacks from the server and give the client a chance to respond within the timeout period before it is evicted: - resend BL AST within lock callback timeout period; - still do not resend CANCEL_ON_BLOCK; - regular resend for CP AST without BL AST embedded; - prolong lock callback timeout on resend; some fixes: - recovery-small test_10 to actually evict the client with dropped BL AST; - ETIMEDOUT to be returned if send limit is expired; Signed-off-by: Vitaly Fertman <vitaly_fertman@xyratex.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5520 Reviewed-by: Alexey Lyashkov <Alexey_Lyashkov@xyratex.com> Reviewed-by: Andriy Skulysh <Andriy_Skulysh@xyratex.com> Xyratex-bug-id: MRP-417 Reviewed-on: http://review.whamcloud.com/9335 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Johann Lombardi <johann.lombardi@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/mdc/mdc_reint.c b/drivers/staging/lustre/lustre/mdc/mdc_reint.c index c018e3b..af5c92c 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_reint.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_reint.c @@ -113,8 +113,7 @@ int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data, if (op_data->op_attr.ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) bits |= MDS_INODELOCK_LOOKUP; if ((op_data->op_flags & MF_MDC_CANCEL_FID1) && - (fid_is_sane(&op_data->op_fid1)) && - !OBD_FAIL_CHECK(OBD_FAIL_LDLM_BL_CALLBACK_NET)) + (fid_is_sane(&op_data->op_fid1))) count = mdc_resource_get_unused(exp, &op_data->op_fid1, &cancels, LCK_EX, bits); req = ptlrpc_request_alloc(class_exp2cliimp(exp), @@ -305,14 +304,12 @@ int mdc_unlink(struct obd_export *exp, struct md_op_data *op_data, LASSERT(!req); if ((op_data->op_flags & MF_MDC_CANCEL_FID1) && - (fid_is_sane(&op_data->op_fid1)) && - !OBD_FAIL_CHECK(OBD_FAIL_LDLM_BL_CALLBACK_NET)) + (fid_is_sane(&op_data->op_fid1))) count = mdc_resource_get_unused(exp, &op_data->op_fid1, &cancels, LCK_EX, MDS_INODELOCK_UPDATE); if ((op_data->op_flags & MF_MDC_CANCEL_FID3) && - (fid_is_sane(&op_data->op_fid3)) && - !OBD_FAIL_CHECK(OBD_FAIL_LDLM_BL_CALLBACK_NET)) + (fid_is_sane(&op_data->op_fid3))) count += mdc_resource_get_unused(exp, &op_data->op_fid3, &cancels, LCK_EX, MDS_INODELOCK_FULL); diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index bae91bd..bea1c16 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -1037,8 +1037,8 @@ static int ptlrpc_import_delay_req(struct obd_import *imp, *status = -EIO; } else if (ptlrpc_send_limit_expired(req)) { /* probably doesn't need to be a D_ERROR after initial testing */ - DEBUG_REQ(D_ERROR, req, "send limit expired "); - *status = -EIO; + DEBUG_REQ(D_HA, req, "send limit expired "); + *status = -ETIMEDOUT; } else if (req->rq_send_state == LUSTRE_IMP_CONNECTING && imp->imp_state == LUSTRE_IMP_CONNECTING) { /* allow CONNECT even if import is invalid */ -- cgit v0.10.2 From 7a742d08a46de9bfb7d89b31af1fd40e9e03134c Mon Sep 17 00:00:00 2001 From: James Simmons <jsimmons@infradead.org> Date: Sun, 18 Sep 2016 16:37:28 -0400 Subject: staging: lustre: ldlm: restore some of the interval functionality Earlier a bunch of interval handling got removed since it wasn't used by the upstream client. Now some of it is needed again for the client code so this patch restores what is needed. Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/interval_tree.h b/drivers/staging/lustre/lustre/include/interval_tree.h index 4a15228..5d387d3 100644 --- a/drivers/staging/lustre/lustre/include/interval_tree.h +++ b/drivers/staging/lustre/lustre/include/interval_tree.h @@ -63,6 +63,11 @@ static inline int interval_is_intree(struct interval_node *node) return node->in_intree == 1; } +static inline __u64 interval_low(struct interval_node *node) +{ + return node->in_extent.start; +} + static inline __u64 interval_high(struct interval_node *node) { return node->in_extent.end; @@ -77,8 +82,29 @@ static inline void interval_set(struct interval_node *node, node->in_max_high = end; } +/* + * Rules to write an interval callback. + * - the callback returns INTERVAL_ITER_STOP when it thinks the iteration + * should be stopped. It will then cause the iteration function to return + * immediately with return value INTERVAL_ITER_STOP. + * - callbacks for interval_iterate and interval_iterate_reverse: Every + * nodes in the tree will be set to @node before the callback being called + * - callback for interval_search: Only overlapped node will be set to @node + * before the callback being called. + */ +typedef enum interval_iter (*interval_callback_t)(struct interval_node *node, + void *args); + struct interval_node *interval_insert(struct interval_node *node, struct interval_node **root); void interval_erase(struct interval_node *node, struct interval_node **root); +/* + * Search the extents in the tree and call @func for each overlapped + * extents. + */ +enum interval_iter interval_search(struct interval_node *root, + struct interval_node_extent *ex, + interval_callback_t func, void *data); + #endif diff --git a/drivers/staging/lustre/lustre/ldlm/interval_tree.c b/drivers/staging/lustre/lustre/ldlm/interval_tree.c index f4a70eb..e134ecd 100644 --- a/drivers/staging/lustre/lustre/ldlm/interval_tree.c +++ b/drivers/staging/lustre/lustre/ldlm/interval_tree.c @@ -90,6 +90,17 @@ static inline int extent_equal(struct interval_node_extent *e1, return (e1->start == e2->start) && (e1->end == e2->end); } +static inline int extent_overlapped(struct interval_node_extent *e1, + struct interval_node_extent *e2) +{ + return (e1->start <= e2->end) && (e2->start <= e1->end); +} + +static inline int node_equal(struct interval_node *n1, struct interval_node *n2) +{ + return extent_equal(&n1->in_extent, &n2->in_extent); +} + static inline __u64 max_u64(__u64 x, __u64 y) { return x > y ? x : y; @@ -262,7 +273,7 @@ struct interval_node *interval_insert(struct interval_node *node, p = root; while (*p) { parent = *p; - if (extent_equal(&parent->in_extent, &node->in_extent)) + if (node_equal(parent, node)) return parent; /* max_high field must be updated after each iteration */ @@ -463,3 +474,90 @@ color: interval_erase_color(child, parent, root); } EXPORT_SYMBOL(interval_erase); + +static inline int interval_may_overlap(struct interval_node *node, + struct interval_node_extent *ext) +{ + return (ext->start <= node->in_max_high && + ext->end >= interval_low(node)); +} + +/* + * This function finds all intervals that overlap interval ext, + * and calls func to handle resulted intervals one by one. + * in lustre, this function will find all conflicting locks in + * the granted queue and add these locks to the ast work list. + * + * { + * if (!node) + * return 0; + * if (ext->end < interval_low(node)) { + * interval_search(node->in_left, ext, func, data); + * } else if (interval_may_overlap(node, ext)) { + * if (extent_overlapped(ext, &node->in_extent)) + * func(node, data); + * interval_search(node->in_left, ext, func, data); + * interval_search(node->in_right, ext, func, data); + * } + * return 0; + * } + * + */ +enum interval_iter interval_search(struct interval_node *node, + struct interval_node_extent *ext, + interval_callback_t func, + void *data) +{ + enum interval_iter rc = INTERVAL_ITER_CONT; + struct interval_node *parent; + + LASSERT(ext); + LASSERT(func); + + while (node) { + if (ext->end < interval_low(node)) { + if (node->in_left) { + node = node->in_left; + continue; + } + } else if (interval_may_overlap(node, ext)) { + if (extent_overlapped(ext, &node->in_extent)) { + rc = func(node, data); + if (rc == INTERVAL_ITER_STOP) + break; + } + + if (node->in_left) { + node = node->in_left; + continue; + } + if (node->in_right) { + node = node->in_right; + continue; + } + } + + parent = node->in_parent; + while (parent) { + if (node_is_left_child(node) && + parent->in_right) { + /* + * If we ever got the left, it means that the + * parent met ext->end<interval_low(parent), or + * may_overlap(parent). If the former is true, + * we needn't go back. So stop early and check + * may_overlap(parent) after this loop. + */ + node = parent->in_right; + break; + } + node = parent; + parent = parent->in_parent; + } + if (!parent || !interval_may_overlap(parent, ext)) + break; + } + + return rc; +} +EXPORT_SYMBOL(interval_search); -- cgit v0.10.2 From 5b8a39c53a16c992fe0d99cd21c141153ea3774b Mon Sep 17 00:00:00 2001 From: Prakash Surya <surya1@llnl.gov> Date: Sun, 18 Sep 2016 16:37:29 -0400 Subject: staging: lustre: llite: Replace write mutex with range lock Testing has shown the ll_inode_inode's lli_write_mutex to be a limiting factor with single shared file write performance, when using many writing threads on a single machine. Even if each thread is writing to a unique portion of the file, the lli_write_mutex will prevent no more than a single thread to ever write to the file simultaneously. This change attempts to remove this bottle neck, by replacing this mutex with a range lock. This should allow multiple threads to write to a single file simultaneously iff the threads are writing to unique regions of the file. Performance testing shows this change to garner a significant performance boost to write bandwidth. Using FIO on a single machine with 32 GB of RAM, write performance tests were run with and without this change applied; the results are below: +---------+-----------+---------+--------+--------+--------+ | fio v2.0.13 | Write Bandwidth (KB/s) | +---------+-----------+---------+--------+--------+--------+ | # Tasks | GB / Task | Test 1 | Test 2 | Test 3 | Test 4 | +---------+-----------+---------+--------+--------+--------+ | 1 | 64 | 452446 | 454623 | 457653 | 463737 | | 2 | 32 | 850318 | 565373 | 602498 | 733027 | | 4 | 16 | 1058900 | 463546 | 529107 | 976284 | | 8 | 8 | 1026300 | 468190 | 576451 | 963404 | | 16 | 4 | 1065500 | 503160 | 462902 | 830065 | | 32 | 2 | 1068600 | 462228 | 466963 | 749733 | | 64 | 1 | 991830 | 556618 | 557863 | 710912 | +---------+-----------+---------+--------+--------+--------+ * Test 1: Lustre client running 04ec54f. File per process write workload. This test was used as a baseline for what we _could_ achieve in the single shared file tests if the bottle necks were removed. * Test 2: Lustre client running 04ec54f. Single shared file workload, each task writing to a unique region. * Test 3: Lustre client running 04ec54f + I0023132b. Single shared file workload, each task writing to a unique region. * Test 4: Lustre client running 04ec54f + this patch. Single shared file workload, each task writing to a unique region. Direct IO does not use the page cache like normal IO, so concurrent direct IO reads of the same pages are not safe. As a result, direct IO reads must take the range lock in ll_file_io_generic, otherwise they will attempt to work on the same pages and hit assertions like: (osc_request.c:1219:osc_brw_prep_request()) ASSERTION( i == 0 || pg->off > pg_prev->off ) failed: i 3 p_c 10 pg ffffea00017a5208 [pri 0 ind 2771] off 16384 prev_pg ffffea00017a51d0 [pri 0 ind 2256] off 16384 Signed-off-by: Prakash Surya <surya1@llnl.gov> Signed-off-by: Patrick Farrell <paf@cray.com> Signed-off-by: Jinshan Xiong <jinshan.xiong@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-1669 Reviewed-on: http://review.whamcloud.com/6320 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6227 Reviewed-on: http://review.whamcloud.com/14385 Reviewed-by: Bobi Jam <bobijam@hotmail.com> Reviewed-by: Alexander Boyko <alexander.boyko@seagate.com> Reviewed-by: Hiroya Nozaki <nozaki.hiroya@jp.fujitsu.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/Makefile b/drivers/staging/lustre/lustre/llite/Makefile index 2cbb1b8..1ac0940 100644 --- a/drivers/staging/lustre/lustre/llite/Makefile +++ b/drivers/staging/lustre/lustre/llite/Makefile @@ -1,6 +1,6 @@ obj-$(CONFIG_LUSTRE_FS) += lustre.o lustre-y := dcache.o dir.o file.o llite_close.o llite_lib.o llite_nfs.o \ - rw.o namei.o symlink.o llite_mmap.o \ + rw.o namei.o symlink.o llite_mmap.o range_lock.o \ xattr.o xattr_cache.o rw26.o super25.o statahead.o \ glimpse.o lcommon_cl.o lcommon_misc.o \ vvp_dev.o vvp_page.o vvp_lock.o vvp_io.o vvp_object.o vvp_req.o \ diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 273b563..d9ee255 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -1126,6 +1126,7 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args, { struct ll_inode_info *lli = ll_i2info(file_inode(file)); struct ll_file_data *fd = LUSTRE_FPRIVATE(file); + struct range_lock range; struct cl_io *io; ssize_t result; @@ -1138,7 +1139,12 @@ restart: if (cl_io_rw_init(env, io, iot, *ppos, count) == 0) { struct vvp_io *vio = vvp_env_io(env); - int write_mutex_locked = 0; + bool range_locked = false; + + if (file->f_flags & O_APPEND) + range_lock_init(&range, 0, LUSTRE_EOF); + else + range_lock_init(&range, *ppos, *ppos + count - 1); vio->vui_fd = LUSTRE_FPRIVATE(file); vio->vui_io_subtype = args->via_io_subtype; @@ -1147,14 +1153,23 @@ restart: case IO_NORMAL: vio->vui_iter = args->u.normal.via_iter; vio->vui_iocb = args->u.normal.via_iocb; - if ((iot == CIT_WRITE) && + /* + * Direct IO reads must also take range lock, + * or multiple reads will try to work on the same pages + * See LU-6227 for details. + */ + if (((iot == CIT_WRITE) || + (iot == CIT_READ && (file->f_flags & O_DIRECT))) && !(vio->vui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) { - if (mutex_lock_interruptible(&lli-> - lli_write_mutex)) { - result = -ERESTARTSYS; + CDEBUG(D_VFSTRACE, "Range lock [%llu, %llu]\n", + range.rl_node.in_extent.start, + range.rl_node.in_extent.end); + result = range_lock(&lli->lli_write_tree, + &range); + if (result < 0) goto out; - } - write_mutex_locked = 1; + + range_locked = true; } down_read(&lli->lli_trunc_sem); break; @@ -1171,8 +1186,12 @@ restart: ll_cl_remove(file, env); if (args->via_io_subtype == IO_NORMAL) up_read(&lli->lli_trunc_sem); - if (write_mutex_locked) - mutex_unlock(&lli->lli_write_mutex); + if (range_locked) { + CDEBUG(D_VFSTRACE, "Range unlock [%llu, %llu]\n", + range.rl_node.in_extent.start, + range.rl_node.in_extent.end); + range_unlock(&lli->lli_write_tree, &range); + } } else { /* cl_io_rw_init() handled IO */ result = io->ci_result; diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index f903f2a..7f0a6c9 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -46,6 +46,7 @@ #include <linux/xattr.h> #include <linux/posix_acl_xattr.h> #include "vvp_internal.h" +#include "range_lock.h" #ifndef FMODE_EXEC #define FMODE_EXEC 0 @@ -210,7 +211,7 @@ struct ll_inode_info { * } */ struct rw_semaphore f_trunc_sem; - struct mutex f_write_mutex; + struct range_lock_tree f_write_tree; struct rw_semaphore f_glimpse_sem; unsigned long f_glimpse_time; @@ -235,7 +236,7 @@ struct ll_inode_info { #define lli_symlink_name u.f.f_symlink_name #define lli_maxbytes u.f.f_maxbytes #define lli_trunc_sem u.f.f_trunc_sem -#define lli_write_mutex u.f.f_write_mutex +#define lli_write_tree u.f.f_write_tree #define lli_glimpse_sem u.f.f_glimpse_sem #define lli_glimpse_time u.f.f_glimpse_time #define lli_agl_list u.f.f_agl_list diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 93fd69b..9112fa8 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -807,7 +807,7 @@ void ll_lli_init(struct ll_inode_info *lli) mutex_init(&lli->lli_size_mutex); lli->lli_symlink_name = NULL; init_rwsem(&lli->lli_trunc_sem); - mutex_init(&lli->lli_write_mutex); + range_lock_tree_init(&lli->lli_write_tree); init_rwsem(&lli->lli_glimpse_sem); lli->lli_glimpse_time = 0; INIT_LIST_HEAD(&lli->lli_agl_list); diff --git a/drivers/staging/lustre/lustre/llite/range_lock.c b/drivers/staging/lustre/lustre/llite/range_lock.c new file mode 100644 index 0000000..94c818f --- /dev/null +++ b/drivers/staging/lustre/lustre/llite/range_lock.c @@ -0,0 +1,233 @@ +/* + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.gnu.org/licenses/gpl-2.0.html + * + * GPL HEADER END + */ +/* + * Range lock is used to allow multiple threads writing a single shared + * file given each thread is writing to a non-overlapping portion of the + * file. + * + * Refer to the possible upstream kernel version of range lock by + * Jan Kara <jack@suse.cz>: https://lkml.org/lkml/2013/1/31/480 + * + * This file could later replaced by the upstream kernel version. + */ +/* + * Author: Prakash Surya <surya1@llnl.gov> + * Author: Bobi Jam <bobijam.xu@intel.com> + */ +#include "range_lock.h" +#include "../include/lustre/lustre_user.h" + +/** + * Initialize a range lock tree + * + * \param tree [in] an empty range lock tree + * + * Pre: Caller should have allocated the range lock tree. + * Post: The range lock tree is ready to function. + */ +void range_lock_tree_init(struct range_lock_tree *tree) +{ + tree->rlt_root = NULL; + tree->rlt_sequence = 0; + spin_lock_init(&tree->rlt_lock); +} + +/** + * Initialize a range lock node + * + * \param lock [in] an empty range lock node + * \param start [in] start of the covering region + * \param end [in] end of the covering region + * + * Pre: Caller should have allocated the range lock node. + * Post: The range lock node is meant to cover [start, end] region + */ +void range_lock_init(struct range_lock *lock, __u64 start, __u64 end) +{ + memset(&lock->rl_node, 0, sizeof(lock->rl_node)); + if (end != LUSTRE_EOF) + end >>= PAGE_SHIFT; + interval_set(&lock->rl_node, start >> PAGE_SHIFT, end); + INIT_LIST_HEAD(&lock->rl_next_lock); + lock->rl_task = NULL; + lock->rl_lock_count = 0; + lock->rl_blocking_ranges = 0; + lock->rl_sequence = 0; +} + +static inline struct range_lock *next_lock(struct range_lock *lock) +{ + return list_entry(lock->rl_next_lock.next, typeof(*lock), rl_next_lock); +} + +/** + * Helper function of range_unlock() + * + * \param node [in] a range lock found overlapped during interval node + * search + * \param arg [in] the range lock to be tested + * + * \retval INTERVAL_ITER_CONT indicate to continue the search for next + * overlapping range node + * \retval INTERVAL_ITER_STOP indicate to stop the search + */ +static enum interval_iter range_unlock_cb(struct interval_node *node, void *arg) +{ + struct range_lock *lock = arg; + struct range_lock *overlap = node2rangelock(node); + struct range_lock *iter; + + list_for_each_entry(iter, &overlap->rl_next_lock, rl_next_lock) { + if (iter->rl_sequence > lock->rl_sequence) { + --iter->rl_blocking_ranges; + LASSERT(iter->rl_blocking_ranges > 0); + } + } + if (overlap->rl_sequence > lock->rl_sequence) { + --overlap->rl_blocking_ranges; + if (overlap->rl_blocking_ranges == 0) + wake_up_process(overlap->rl_task); + } + return INTERVAL_ITER_CONT; +} + +/** + * Unlock a range lock, wake up locks blocked by this lock. + * + * \param tree [in] range lock tree + * \param lock [in] range lock to be deleted + * + * If this lock has been granted, relase it; if not, just delete it from + * the tree or the same region lock list. Wake up those locks only blocked + * by this lock through range_unlock_cb(). + */ +void range_unlock(struct range_lock_tree *tree, struct range_lock *lock) +{ + spin_lock(&tree->rlt_lock); + if (!list_empty(&lock->rl_next_lock)) { + struct range_lock *next; + + if (interval_is_intree(&lock->rl_node)) { /* first lock */ + /* Insert the next same range lock into the tree */ + next = next_lock(lock); + next->rl_lock_count = lock->rl_lock_count - 1; + interval_erase(&lock->rl_node, &tree->rlt_root); + interval_insert(&next->rl_node, &tree->rlt_root); + } else { + /* find the first lock in tree */ + list_for_each_entry(next, &lock->rl_next_lock, + rl_next_lock) { + if (!interval_is_intree(&next->rl_node)) + continue; + + LASSERT(next->rl_lock_count > 0); + next->rl_lock_count--; + break; + } + } + list_del_init(&lock->rl_next_lock); + } else { + LASSERT(interval_is_intree(&lock->rl_node)); + interval_erase(&lock->rl_node, &tree->rlt_root); + } + + interval_search(tree->rlt_root, &lock->rl_node.in_extent, + range_unlock_cb, lock); + spin_unlock(&tree->rlt_lock); +} + +/** + * Helper function of range_lock() + * + * \param node [in] a range lock found overlapped during interval node + * search + * \param arg [in] the range lock to be tested + * + * \retval INTERVAL_ITER_CONT indicate to continue the search for next + * overlapping range node + * \retval INTERVAL_ITER_STOP indicate to stop the search + */ +static enum interval_iter range_lock_cb(struct interval_node *node, void *arg) +{ + struct range_lock *lock = (struct range_lock *)arg; + struct range_lock *overlap = node2rangelock(node); + + lock->rl_blocking_ranges += overlap->rl_lock_count + 1; + return INTERVAL_ITER_CONT; +} + +/** + * Lock a region + * + * \param tree [in] range lock tree + * \param lock [in] range lock node containing the region span + * + * \retval 0 get the range lock + * \retval <0 error code while not getting the range lock + * + * If there exists overlapping range lock, the new lock will wait and + * retry, if later it find that it is not the chosen one to wake up, + * it wait again. + */ +int range_lock(struct range_lock_tree *tree, struct range_lock *lock) +{ + struct interval_node *node; + int rc = 0; + + spin_lock(&tree->rlt_lock); + /* + * We need to check for all conflicting intervals + * already in the tree. + */ + interval_search(tree->rlt_root, &lock->rl_node.in_extent, + range_lock_cb, lock); + /* + * Insert to the tree if I am unique, otherwise I've been linked to + * the rl_next_lock of another lock which has the same range as mine + * in range_lock_cb(). + */ + node = interval_insert(&lock->rl_node, &tree->rlt_root); + if (node) { + struct range_lock *tmp = node2rangelock(node); + + list_add_tail(&lock->rl_next_lock, &tmp->rl_next_lock); + tmp->rl_lock_count++; + } + lock->rl_sequence = ++tree->rlt_sequence; + + while (lock->rl_blocking_ranges > 0) { + lock->rl_task = current; + __set_current_state(TASK_INTERRUPTIBLE); + spin_unlock(&tree->rlt_lock); + schedule(); + + if (signal_pending(current)) { + range_unlock(tree, lock); + rc = -EINTR; + goto out; + } + spin_lock(&tree->rlt_lock); + } + spin_unlock(&tree->rlt_lock); +out: + return rc; +} diff --git a/drivers/staging/lustre/lustre/llite/range_lock.h b/drivers/staging/lustre/lustre/llite/range_lock.h new file mode 100644 index 0000000..c6d04a6 --- /dev/null +++ b/drivers/staging/lustre/lustre/llite/range_lock.h @@ -0,0 +1,82 @@ +/* + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.gnu.org/licenses/gpl-2.0.html + * + * GPL HEADER END + */ +/* + * Range lock is used to allow multiple threads writing a single shared + * file given each thread is writing to a non-overlapping portion of the + * file. + * + * Refer to the possible upstream kernel version of range lock by + * Jan Kara <jack@suse.cz>: https://lkml.org/lkml/2013/1/31/480 + * + * This file could later replaced by the upstream kernel version. + */ +/* + * Author: Prakash Surya <surya1@llnl.gov> + * Author: Bobi Jam <bobijam.xu@intel.com> + */ +#ifndef _RANGE_LOCK_H +#define _RANGE_LOCK_H + +#include "../../include/linux/libcfs/libcfs.h" +#include "../include/interval_tree.h" + +struct range_lock { + struct interval_node rl_node; + /** + * Process to enqueue this lock. + */ + struct task_struct *rl_task; + /** + * List of locks with the same range. + */ + struct list_head rl_next_lock; + /** + * Number of locks in the list rl_next_lock + */ + unsigned int rl_lock_count; + /** + * Number of ranges which are blocking acquisition of the lock + */ + unsigned int rl_blocking_ranges; + /** + * Sequence number of range lock. This number is used to get to know + * the order the locks are queued; this is required for range_cancel(). + */ + __u64 rl_sequence; +}; + +static inline struct range_lock *node2rangelock(const struct interval_node *n) +{ + return container_of(n, struct range_lock, rl_node); +} + +struct range_lock_tree { + struct interval_node *rlt_root; + spinlock_t rlt_lock; /* protect range lock tree */ + __u64 rlt_sequence; +}; + +void range_lock_tree_init(struct range_lock_tree *tree); +void range_lock_init(struct range_lock *lock, __u64 start, __u64 end); +int range_lock(struct range_lock_tree *tree, struct range_lock *lock); +void range_unlock(struct range_lock_tree *tree, struct range_lock *lock); +#endif -- cgit v0.10.2 From 5d770fe899bdff805fe174a9a0c946c3072b315e Mon Sep 17 00:00:00 2001 From: Prakash Surya <surya1@llnl.gov> Date: Sun, 18 Sep 2016 16:37:30 -0400 Subject: staging: lustre: vvp: Use lockless __generic_file_aio_write Testing multi-threaded single shard file write performance has shown the inode mutex to be a limiting factor when using the generic_file_write_iter function. To work around this bottle neck, this change replaces the locked version of that call with the lock less version, specifically, __generic_file_write_iter. In order to maintain posix consistency, Lustre must now employ it's own locking mechanism in the higher layers. Currently writes are protected using the lli_write_mutex in the ll_inode_info structure. To protect against simultaneous write and truncate operations, since we no longer take the inode mutex during writes, we must down the lli_trunc_sem semaphore. Unfortunately, this change by itself does not garner any performance benefits. Using FIO on a single machine with 32 GB of RAM, write performance tests were ran with and without this change applied; the results are below: +---------+-----------+---------+--------+--------+ | fio v2.0.13 | Write Bandwidth (KB/s) | +---------+-----------+---------+--------+--------+ | # Tasks | GB / Task | Test 1 | Test 2 | Test 3 | +---------+-----------+---------+--------+--------+ | 1 | 64 | 452446 | 454623 | 457653 | | 2 | 32 | 850318 | 565373 | 602498 | | 4 | 16 | 1058900 | 463546 | 529107 | | 8 | 8 | 1026300 | 468190 | 576451 | | 16 | 4 | 1065500 | 503160 | 462902 | | 32 | 2 | 1068600 | 462228 | 466963 | | 64 | 1 | 991830 | 556618 | 557863 | +---------+-----------+---------+--------+--------+ * Test 1: Lustre client running 04ec54f. File per process write workload. This test was used as a baseline for what we _could_ achieve in the single shared file tests if the bottle necks were removed. * Test 2: Lustre client running 04ec54f. Single shared file workload, each task writing to a unique region. * Test 3: Lustre client running 04ec54f + this patch. Single shared file workload, each task writing to a unique region. In order to garner any real performance benefits out of a single shared file workload, the lli_write_mutex needs to be broken up into a range lock. That would allow write operations to unique regions of a file to be executed concurrently. This work is left to be done in a follow up patch. Signed-off-by: Prakash Surya <surya1@llnl.gov> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-1669 Reviewed-on: http://review.whamcloud.com/6672 Reviewed-by: Lai Siyao <lai.siyao@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c index 2f8ef54..66dba04 100644 --- a/drivers/staging/lustre/lustre/llite/rw26.c +++ b/drivers/staging/lustre/lustre/llite/rw26.c @@ -375,13 +375,6 @@ static ssize_t ll_direct_IO_26(struct kiocb *iocb, struct iov_iter *iter) io = vvp_env_io(env)->vui_cl.cis_io; LASSERT(io); - /* 0. Need locking between buffered and direct access. and race with - * size changing by concurrent truncates and writes. - * 1. Need inode mutex to operate transient pages. - */ - if (iov_iter_rw(iter) == READ) - inode_lock(inode); - LASSERT(obj->vob_transient_pages == 0); while (iov_iter_count(iter)) { struct page **pages; @@ -431,8 +424,6 @@ static ssize_t ll_direct_IO_26(struct kiocb *iocb, struct iov_iter *iter) } out: LASSERT(obj->vob_transient_pages == 0); - if (iov_iter_rw(iter) == READ) - inode_unlock(inode); if (tot_bytes > 0) { struct vvp_io *vio = vvp_env_io(env); diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index 09ccd1f..f6dacee 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -959,10 +959,30 @@ static int vvp_io_write_start(const struct lu_env *env, CDEBUG(D_VFSTRACE, "write: [%lli, %lli)\n", pos, pos + (long long)cnt); - if (!vio->vui_iter) /* from a temp io in ll_cl_init(). */ + if (!vio->vui_iter) { + /* from a temp io in ll_cl_init(). */ result = 0; - else - result = generic_file_write_iter(vio->vui_iocb, vio->vui_iter); + } else { + /* + * When using the locked AIO function (generic_file_aio_write()) + * testing has shown the inode mutex to be a limiting factor + * with multi-threaded single shared file performance. To get + * around this, we now use the lockless version. To maintain + * consistency, proper locking to protect against writes, + * trucates, etc. is handled in the higher layers of lustre. + */ + bool lock_node = !IS_NOSEC(inode); + + if (lock_node) + inode_lock(inode); + result = __generic_file_write_iter(vio->vui_iocb, + vio->vui_iter); + if (lock_node) + inode_unlock(inode); + + if (result > 0 || result == -EIOCBQUEUED) + result = generic_write_sync(vio->vui_iocb, result); + } if (result > 0) { result = vvp_io_write_commit(env, io); diff --git a/drivers/staging/lustre/lustre/llite/vvp_page.c b/drivers/staging/lustre/lustre/llite/vvp_page.c index 2818a68..bbbb0f1 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_page.c +++ b/drivers/staging/lustre/lustre/llite/vvp_page.c @@ -444,18 +444,10 @@ static int vvp_transient_page_prep(const struct lu_env *env, return 0; } -static void vvp_transient_page_verify(const struct cl_page *page) -{ - struct inode *inode = vvp_object_inode(page->cp_obj); - - LASSERT(!inode_trylock(inode)); -} - static int vvp_transient_page_own(const struct lu_env *env, const struct cl_page_slice *slice, struct cl_io *unused, int nonblock) { - vvp_transient_page_verify(slice->cpl_page); return 0; } @@ -463,21 +455,18 @@ static void vvp_transient_page_assume(const struct lu_env *env, const struct cl_page_slice *slice, struct cl_io *unused) { - vvp_transient_page_verify(slice->cpl_page); } static void vvp_transient_page_unassume(const struct lu_env *env, const struct cl_page_slice *slice, struct cl_io *unused) { - vvp_transient_page_verify(slice->cpl_page); } static void vvp_transient_page_disown(const struct lu_env *env, const struct cl_page_slice *slice, struct cl_io *unused) { - vvp_transient_page_verify(slice->cpl_page); } static void vvp_transient_page_discard(const struct lu_env *env, @@ -486,8 +475,6 @@ static void vvp_transient_page_discard(const struct lu_env *env, { struct cl_page *page = slice->cpl_page; - vvp_transient_page_verify(slice->cpl_page); - /* * For transient pages, remove it from the radix tree. */ @@ -511,7 +498,6 @@ vvp_transient_page_completion(const struct lu_env *env, const struct cl_page_slice *slice, int ioret) { - vvp_transient_page_verify(slice->cpl_page); } static void vvp_transient_page_fini(const struct lu_env *env, @@ -522,7 +508,6 @@ static void vvp_transient_page_fini(const struct lu_env *env, struct vvp_object *clobj = cl2vvp(clp->cp_obj); vvp_page_fini_common(vpg); - LASSERT(!inode_trylock(clobj->vob_inode)); clobj->vob_transient_pages--; } @@ -570,7 +555,6 @@ int vvp_page_init(const struct lu_env *env, struct cl_object *obj, } else { struct vvp_object *clobj = cl2vvp(obj); - LASSERT(!inode_trylock(clobj->vob_inode)); cl_page_slice_add(page, &vpg->vpg_cl, obj, index, &vvp_transient_page_ops); clobj->vob_transient_pages++; diff --git a/drivers/staging/lustre/lustre/obdclass/cl_page.c b/drivers/staging/lustre/lustre/obdclass/cl_page.c index 80c6e0e..cae8d21 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_page.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_page.c @@ -228,11 +228,6 @@ EXPORT_SYMBOL(cl_page_find); static inline int cl_page_invariant(const struct cl_page *pg) { - /* - * Page invariant is protected by a VM lock. - */ - LINVRNT(cl_page_is_vmlocked(NULL, pg)); - return cl_page_in_use_noref(pg); } @@ -864,7 +859,6 @@ void cl_page_completion(const struct lu_env *env, (const struct lu_env *, const struct cl_page_slice *, int), ioret); if (anchor) { - LASSERT(cl_page_is_vmlocked(env, pg)); LASSERT(pg->cp_sync_io == anchor); pg->cp_sync_io = NULL; } -- cgit v0.10.2 From 9b496412f82352bfc78796e9d2a4b3a6a9104dc5 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Sun, 18 Sep 2016 16:37:31 -0400 Subject: staging: lustre: llite: remove lookup_flags from ll_lookup_it() Remove the effectively unused lookup_flags parameter from ll_lookup_it(). Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2675 Reviewed-on: http://review.whamcloud.com/10769 Reviewed-by: Yang Sheng <yang.sheng@intel.com> Reviewed-by: Lai Siyao <lai.siyao@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index b7d448f..2037c7c 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -502,7 +502,7 @@ out: } static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry, - struct lookup_intent *it, int lookup_flags) + struct lookup_intent *it) { struct lookup_intent lookup_it = { .it_op = IT_LOOKUP }; struct dentry *save = dentry, *retval; @@ -541,8 +541,7 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry, opc = LUSTRE_OPC_ANY; op_data = ll_prep_md_op_data(NULL, parent, NULL, dentry->d_name.name, - dentry->d_name.len, lookup_flags, opc, - NULL); + dentry->d_name.len, 0, opc, NULL); if (IS_ERR(op_data)) return (void *)op_data; @@ -606,7 +605,7 @@ static struct dentry *ll_lookup_nd(struct inode *parent, struct dentry *dentry, itp = NULL; else itp = ⁢ - de = ll_lookup_it(parent, dentry, itp, 0); + de = ll_lookup_it(parent, dentry, itp); if (itp) ll_intent_release(itp); @@ -624,7 +623,6 @@ static int ll_atomic_open(struct inode *dir, struct dentry *dentry, { struct lookup_intent *it; struct dentry *de; - long long lookup_flags = LOOKUP_OPEN; int rc = 0; CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir="DFID"(%p),file %p,open_flags %x,mode %x opened %d\n", @@ -654,16 +652,14 @@ static int ll_atomic_open(struct inode *dir, struct dentry *dentry, return -ENOMEM; it->it_op = IT_OPEN; - if (open_flags & O_CREAT) { + if (open_flags & O_CREAT) it->it_op |= IT_CREAT; - lookup_flags |= LOOKUP_CREATE; - } it->it_create_mode = (mode & S_IALLUGO) | S_IFREG; it->it_flags = (open_flags & ~O_ACCMODE) | OPEN_FMODE(open_flags); it->it_flags &= ~MDS_OPEN_FL_INTERNAL; /* Dentry added to dcache tree in ll_lookup_it */ - de = ll_lookup_it(dir, dentry, it, lookup_flags); + de = ll_lookup_it(dir, dentry, it); if (IS_ERR(de)) rc = PTR_ERR(de); else if (de) -- cgit v0.10.2 From 9c1c204fb3c7969f07cdbbed8e3bb2595e7a49c9 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Sun, 18 Sep 2016 16:37:32 -0400 Subject: staging: lustre: llite: remove mode from ll_create_it() Remove the unused mode parameter from ll_create_it(). Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2675 Reviewed-on: http://review.whamcloud.com/10769 Reviewed-by: Yang Sheng <yang.sheng@intel.com> Reviewed-by: Lai Siyao <lai.siyao@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index 2037c7c..8f92af4 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -47,8 +47,8 @@ #include "../include/lustre_ver.h" #include "llite_internal.h" -static int ll_create_it(struct inode *, struct dentry *, - int, struct lookup_intent *); +static int ll_create_it(struct inode *dir, struct dentry *dentry, + struct lookup_intent *it); /* called from iget5_locked->find_inode() under inode_hash_lock spinlock */ static int ll_test_inode(struct inode *inode, void *opaque) @@ -668,7 +668,7 @@ static int ll_atomic_open(struct inode *dir, struct dentry *dentry, if (!rc) { if (it_disposition(it, DISP_OPEN_CREATE)) { /* Dentry instantiated in ll_create_it. */ - rc = ll_create_it(dir, dentry, mode, it); + rc = ll_create_it(dir, dentry, it); if (rc) { /* We dget in ll_splice_alias. */ if (de) @@ -754,7 +754,7 @@ static struct inode *ll_create_node(struct inode *dir, struct lookup_intent *it) * If the create succeeds, we fill in the inode information * with d_instantiate(). */ -static int ll_create_it(struct inode *dir, struct dentry *dentry, int mode, +static int ll_create_it(struct inode *dir, struct dentry *dentry, struct lookup_intent *it) { struct inode *inode; -- cgit v0.10.2 From cad89e561320b6f5c8ca05a490729754e09a3597 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Sun, 18 Sep 2016 16:37:33 -0400 Subject: staging: lustre: llite: turn mode to umode_t for ll_new_inode() Change int mode to umode_t. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2675 Reviewed-on: http://review.whamcloud.com/10769 Reviewed-by: Yang Sheng <yang.sheng@intel.com> Reviewed-by: Lai Siyao <lai.siyao@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index 8f92af4..fadac44 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -794,7 +794,7 @@ void ll_update_times(struct ptlrpc_request *request, struct inode *inode) } static int ll_new_node(struct inode *dir, struct dentry *dentry, - const char *tgt, int mode, int rdev, + const char *tgt, umode_t mode, int rdev, __u32 opc) { struct ptlrpc_request *request = NULL; -- cgit v0.10.2 From 9329b697349f6b44b4936ac7499eaef02366554c Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Sun, 18 Sep 2016 16:37:34 -0400 Subject: staging: lustre: llite: style cleanup for ll_mkdir Style cleanup to make the code readable. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2675 Reviewed-on: http://review.whamcloud.com/10769 Reviewed-by: Yang Sheng <yang.sheng@intel.com> Reviewed-by: Lai Siyao <lai.siyao@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index fadac44..5e182fc 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -1015,8 +1015,8 @@ static int ll_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) if (!IS_POSIXACL(dir) || !exp_connect_umask(ll_i2mdexp(dir))) mode &= ~current_umask(); mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR; - err = ll_new_node(dir, dentry, NULL, mode, 0, LUSTRE_OPC_MKDIR); + err = ll_new_node(dir, dentry, NULL, mode, 0, LUSTRE_OPC_MKDIR); if (!err) ll_stats_ops_tally(ll_i2sbi(dir), LPROC_LL_MKDIR, 1); -- cgit v0.10.2 From 5d9d0cb76cdbec99af87dcbac80c66d1702d1fe6 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Sun, 18 Sep 2016 16:37:35 -0400 Subject: staging: lustre: llite: no need to check dentry is NULL We are already touching dentry in CDEBUG macros so it will crash long before these checks. Since this is the case no need to do an additional check. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2675 Reviewed-on: http://review.whamcloud.com/10769 Reviewed-by: Yang Sheng <yang.sheng@intel.com> Reviewed-by: Lai Siyao <lai.siyao@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index 5e182fc..7a82ae4 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -987,7 +987,7 @@ static int ll_unlink(struct inode *dir, struct dentry *dchild) if (IS_ERR(op_data)) return PTR_ERR(op_data); - if (dchild && dchild->d_inode) + if (dchild->d_inode) op_data->op_fid3 = *ll_inode2fid(dchild->d_inode); op_data->op_fid2 = op_data->op_fid3; @@ -1039,7 +1039,7 @@ static int ll_rmdir(struct inode *dir, struct dentry *dchild) if (IS_ERR(op_data)) return PTR_ERR(op_data); - if (dchild && dchild->d_inode) + if (dchild->d_inode) op_data->op_fid3 = *ll_inode2fid(dchild->d_inode); op_data->op_fid2 = op_data->op_fid3; @@ -1120,9 +1120,9 @@ static int ll_rename(struct inode *src, struct dentry *src_dchild, if (IS_ERR(op_data)) return PTR_ERR(op_data); - if (src_dchild && src_dchild->d_inode) + if (src_dchild->d_inode) op_data->op_fid3 = *ll_inode2fid(src_dchild->d_inode); - if (tgt_dchild && tgt_dchild->d_inode) + if (tgt_dchild->d_inode) op_data->op_fid4 = *ll_inode2fid(tgt_dchild->d_inode); err = md_rename(sbi->ll_md_exp, op_data, -- cgit v0.10.2 From 0a1200991234f7004a10a2ecb0e63075e306c2a3 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Sun, 18 Sep 2016 16:37:36 -0400 Subject: staging: lustre: cleanup lustre_lib.h Remove some unused declarations from lustre_lib.h and move some others to more natural headers. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2675 Reviewed-on: http://review.whamcloud.com/11500 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Bob Glossman <bob.glossman@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre_lib.h b/drivers/staging/lustre/lustre/include/lustre_lib.h index adb8c47..6b23191 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lib.h +++ b/drivers/staging/lustre/lustre/include/lustre_lib.h @@ -51,7 +51,6 @@ #include "lustre_cfg.h" /* target.c */ -struct kstatfs; struct ptlrpc_request; struct obd_export; struct lu_target; @@ -74,43 +73,8 @@ int do_set_info_async(struct obd_import *imp, u32 vallen, void *val, struct ptlrpc_request_set *set); -#define OBD_RECOVERY_MAX_TIME (obd_timeout * 18) /* b13079 */ - void target_send_reply(struct ptlrpc_request *req, int rc, int fail_id); -/* client.c */ - -int client_sanobd_setup(struct obd_device *obddev, struct lustre_cfg *lcfg); -struct client_obd *client_conn2cli(struct lustre_handle *conn); - -struct md_open_data; -struct obd_client_handle { - struct lustre_handle och_fh; - struct lu_fid och_fid; - struct md_open_data *och_mod; - struct lustre_handle och_lease_handle; /* open lock for lease */ - __u32 och_magic; - fmode_t och_flags; -}; - -#define OBD_CLIENT_HANDLE_MAGIC 0xd15ea5ed - -/* statfs_pack.c */ -void statfs_unpack(struct kstatfs *sfs, struct obd_statfs *osfs); - -/* Until such time as we get_info the per-stripe maximum from the OST, - * we define this to be 2T - 4k, which is the ext3 maxbytes. - */ -#define LUSTRE_STRIPE_MAXBYTES 0x1fffffff000ULL - -/* Special values for remove LOV EA from disk */ -#define LOVEA_DELETE_VALUES(size, count, offset) (size == 0 && count == 0 && \ - offset == (typeof(offset))(-1)) - -#define LMVEA_DELETE_VALUES(count, offset) ((count) == 0 && \ - (offset) == (typeof(offset))(-1)) -/* #define POISON_BULK 0 */ - /* * l_wait_event is a flexible sleeping function, permitting simple caller * configuration of interrupt and timeout sensitivity along with actions to diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 89633f7..0917aaa 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -41,6 +41,7 @@ #include "lustre_export.h" #include "lustre_fid.h" #include "lustre_fld.h" +#include "lustre_handles.h" #include "lustre_intent.h" #define MAX_OBD_DEVICES 8192 @@ -72,6 +73,11 @@ static inline void loi_init(struct lov_oinfo *loi) { } +/* Until such time as we get_info the per-stripe maximum from the OST, + * we define this to be 2T - 4k, which is the ext3 maxbytes. + */ +#define LUSTRE_STRIPE_MAXBYTES 0x1fffffff000ULL + struct lov_stripe_md { atomic_t lsm_refc; spinlock_t lsm_lock; @@ -949,6 +955,17 @@ struct md_open_data { bool mod_is_create; }; +struct obd_client_handle { + struct lustre_handle och_fh; + struct lu_fid och_fid; + struct md_open_data *och_mod; + struct lustre_handle och_lease_handle; /* open lock for lease */ + __u32 och_magic; + int och_flags; +}; + +#define OBD_CLIENT_HANDLE_MAGIC 0xd15ea5ed + struct lookup_intent; struct cl_attr; diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index 8e8df08..6fc54bd 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -1725,6 +1725,11 @@ int class_procfs_clean(void); /* prng.c */ #define ll_generate_random_uuid(uuid_out) cfs_get_random_bytes(uuid_out, sizeof(class_uuid_t)) +/* statfs_pack.c */ +struct kstatfs; +void statfs_pack(struct obd_statfs *osfs, struct kstatfs *sfs); +void statfs_unpack(struct kstatfs *sfs, struct obd_statfs *osfs); + /* root squash info */ struct rw_semaphore; struct root_squash_info { -- cgit v0.10.2 From 346dc1c8778f0715d023778a8e94397ac2328b74 Mon Sep 17 00:00:00 2001 From: Patrick Farrell <paf@cray.com> Date: Sun, 18 Sep 2016 16:37:37 -0400 Subject: staging: lustre: osc: debug to match extent to brw RPC Currently, it's difficult to match brw RPCs to objects and extents from client logs. This patch adds a D_RPCTRACE debug message giving the necessary information. Signed-off-by: Patrick Farrell <paf@cray.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5531 Reviewed-on: http://review.whamcloud.com/11548 Reviewed-by: Alexey Lyashkov <alexey.lyashkov@seagate.com> Reviewed-by: Ann Koehler <amk@cray.com> Reviewed-by: Ryan Haasken <haasken@cray.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 5cca2b6..0eb4e35 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -1419,6 +1419,11 @@ static int osc_brw_prep_request(int cmd, struct client_obd *cli, INIT_LIST_HEAD(&aa->aa_oaps); *reqp = req; + niobuf = req_capsule_client_get(pill, &RMF_NIOBUF_REMOTE); + CDEBUG(D_RPCTRACE, "brw rpc %p - object " DOSTID " offset %lld<>%lld\n", + req, POSTID(&oa->o_oi), niobuf[0].rnb_offset, + niobuf[niocount - 1].rnb_offset + niobuf[niocount - 1].rnb_len); + return 0; out: -- cgit v0.10.2 From f9acb591a1f502ae7c6b643c58a063b8fd233352 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Sun, 18 Sep 2016 16:37:38 -0400 Subject: staging: lustre: remove lustre_lite.h Move several definition only used in lustre/llite/ to lustre/llite/llite_internal.h. Remove lustre/include/{,linux/}lustre_lite.h and fixup the missing includes in other headers that this exposes. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2675 Reviewed-on: http://review.whamcloud.com/11501 Reviewed-by: Bob Glossman <bob.glossman@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_lite.h b/drivers/staging/lustre/lustre/include/linux/lustre_lite.h deleted file mode 100644 index d18e8a7..0000000 --- a/drivers/staging/lustre/lustre/include/linux/lustre_lite.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.gnu.org/licenses/gpl-2.0.html - * - * GPL HEADER END - */ -/* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - */ - -#ifndef _LINUX_LL_H -#define _LINUX_LL_H - -#ifndef _LL_H -#error Do not #include this file directly. #include <lustre_lite.h> instead -#endif - -#include <linux/statfs.h> - -#include <linux/fs.h> -#include <linux/dcache.h> - -#include "../obd_class.h" -#include "../lustre_net.h" -#include "../lustre_ha.h" - -#include <linux/rbtree.h> -#include "../../include/linux/lustre_compat25.h" -#include <linux/pagemap.h> - -/* lprocfs.c */ -enum { - LPROC_LL_DIRTY_HITS = 0, - LPROC_LL_DIRTY_MISSES, - LPROC_LL_READ_BYTES, - LPROC_LL_WRITE_BYTES, - LPROC_LL_BRW_READ, - LPROC_LL_BRW_WRITE, - LPROC_LL_OSC_READ, - LPROC_LL_OSC_WRITE, - LPROC_LL_IOCTL, - LPROC_LL_OPEN, - LPROC_LL_RELEASE, - LPROC_LL_MAP, - LPROC_LL_LLSEEK, - LPROC_LL_FSYNC, - LPROC_LL_READDIR, - LPROC_LL_SETATTR, - LPROC_LL_TRUNC, - LPROC_LL_FLOCK, - LPROC_LL_GETATTR, - LPROC_LL_CREATE, - LPROC_LL_LINK, - LPROC_LL_UNLINK, - LPROC_LL_SYMLINK, - LPROC_LL_MKDIR, - LPROC_LL_RMDIR, - LPROC_LL_MKNOD, - LPROC_LL_RENAME, - LPROC_LL_STAFS, - LPROC_LL_ALLOC_INODE, - LPROC_LL_SETXATTR, - LPROC_LL_GETXATTR, - LPROC_LL_GETXATTR_HITS, - LPROC_LL_LISTXATTR, - LPROC_LL_REMOVEXATTR, - LPROC_LL_INODE_PERM, - LPROC_LL_FILE_OPCODES -}; - -#endif diff --git a/drivers/staging/lustre/lustre/include/lustre_eacl.h b/drivers/staging/lustre/lustre/include/lustre_eacl.h index d1039e1..1e71a86 100644 --- a/drivers/staging/lustre/lustre/include/lustre_eacl.h +++ b/drivers/staging/lustre/lustre/include/lustre_eacl.h @@ -46,6 +46,7 @@ #ifdef CONFIG_FS_POSIX_ACL +#include <linux/fs.h> #include <linux/posix_acl_xattr.h> typedef struct { diff --git a/drivers/staging/lustre/lustre/include/lustre_lite.h b/drivers/staging/lustre/lustre/include/lustre_lite.h deleted file mode 100644 index 8333d76..0000000 --- a/drivers/staging/lustre/lustre/include/lustre_lite.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.gnu.org/licenses/gpl-2.0.html - * - * GPL HEADER END - */ -/* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 2011, 2012, Intel Corporation. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - */ - -#ifndef _LL_H -#define _LL_H - -/** \defgroup lite lite - * - * @{ - */ - -#include "linux/lustre_lite.h" - -#include "obd_class.h" -#include "lustre_net.h" -#include "lustre_ha.h" - -/* 4UL * 1024 * 1024 */ -#define LL_MAX_BLKSIZE_BITS (22) -#define LL_MAX_BLKSIZE (1UL << LL_MAX_BLKSIZE_BITS) - -/* - * This is embedded into llite super-blocks to keep track of - * connect flags (capabilities) supported by all imports given mount is - * connected to. - */ -struct lustre_client_ocd { - /* - * This is conjunction of connect_flags across all imports (LOVs) this - * mount is connected to. This field is updated by cl_ocd_update() - * under ->lco_lock. - */ - __u64 lco_flags; - struct mutex lco_lock; - struct obd_export *lco_md_exp; - struct obd_export *lco_dt_exp; -}; - -/* - * Chain of hash overflow pages. - */ -struct ll_dir_chain { - /* XXX something. Later */ -}; - -static inline void ll_dir_chain_init(struct ll_dir_chain *chain) -{ -} - -static inline void ll_dir_chain_fini(struct ll_dir_chain *chain) -{ -} - -/** @} lite */ - -#endif diff --git a/drivers/staging/lustre/lustre/include/lustre_param.h b/drivers/staging/lustre/lustre/include/lustre_param.h index 82aadd3..8061a04 100644 --- a/drivers/staging/lustre/lustre/include/lustre_param.h +++ b/drivers/staging/lustre/lustre/include/lustre_param.h @@ -39,6 +39,9 @@ #ifndef _LUSTRE_PARAM_H #define _LUSTRE_PARAM_H +#include "../../include/linux/libcfs/libcfs.h" +#include "../../include/linux/lnet/types.h" + /** \defgroup param param * * @{ diff --git a/drivers/staging/lustre/lustre/llite/dcache.c b/drivers/staging/lustre/lustre/llite/dcache.c index 8c00cc6..8500080 100644 --- a/drivers/staging/lustre/lustre/llite/dcache.c +++ b/drivers/staging/lustre/lustre/llite/dcache.c @@ -37,7 +37,6 @@ #define DEBUG_SUBSYSTEM S_LLITE #include "../include/obd_support.h" -#include "../include/lustre_lite.h" #include "../include/lustre/lustre_idl.h" #include "../include/lustre_dlm.h" diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 97815cf..234095e 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -48,7 +48,6 @@ #include "../include/obd_class.h" #include "../include/lustre/lustre_ioctl.h" #include "../include/lustre_lib.h" -#include "../include/lustre_lite.h" #include "../include/lustre_dlm.h" #include "../include/lustre_fid.h" #include "../include/lustre_kernelcomm.h" @@ -135,7 +134,7 @@ * */ struct page *ll_get_dir_page(struct inode *dir, struct md_op_data *op_data, - __u64 offset, struct ll_dir_chain *chain) + __u64 offset) { struct md_callback cb_op; struct page *page; @@ -202,13 +201,10 @@ int ll_dir_read(struct inode *inode, __u64 *ppos, struct md_op_data *op_data, int is_api32 = ll_need_32bit_api(sbi); int is_hash64 = sbi->ll_flags & LL_SBI_64BIT_HASH; struct page *page; - struct ll_dir_chain chain; bool done = false; int rc = 0; - ll_dir_chain_init(&chain); - - page = ll_get_dir_page(inode, op_data, pos, &chain); + page = ll_get_dir_page(inode, op_data, pos); while (rc == 0 && !done) { struct lu_dirpage *dp; @@ -286,13 +282,11 @@ int ll_dir_read(struct inode *inode, __u64 *ppos, struct md_op_data *op_data, le32_to_cpu(dp->ldp_flags) & LDF_COLLIDE); next = pos; - page = ll_get_dir_page(inode, op_data, pos, - &chain); + page = ll_get_dir_page(inode, op_data, pos); } } ctx->pos = pos; - ll_dir_chain_fini(&chain); return rc; } diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index d9ee255..127d0e0 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -38,7 +38,6 @@ #define DEBUG_SUBSYSTEM S_LLITE #include "../include/lustre_dlm.h" -#include "../include/lustre_lite.h" #include <linux/pagemap.h> #include <linux/file.h> #include <linux/sched.h> diff --git a/drivers/staging/lustre/lustre/llite/glimpse.c b/drivers/staging/lustre/lustre/llite/glimpse.c index 92004a0..22507b9 100644 --- a/drivers/staging/lustre/lustre/llite/glimpse.c +++ b/drivers/staging/lustre/lustre/llite/glimpse.c @@ -42,7 +42,6 @@ #include "../include/obd.h" #include "../include/lustre_dlm.h" -#include "../include/lustre_lite.h" #include "../include/lustre_mdc.h" #include <linux/pagemap.h> #include <linux/file.h> diff --git a/drivers/staging/lustre/lustre/llite/lcommon_cl.c b/drivers/staging/lustre/lustre/llite/lcommon_cl.c index eed464b..2ded6b5 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_cl.c @@ -49,7 +49,6 @@ #include "../include/obd.h" #include "../include/obd_support.h" #include "../include/lustre_fid.h" -#include "../include/lustre_lite.h" #include "../include/lustre_dlm.h" #include "../include/lustre_ver.h" #include "../include/lustre_mdc.h" diff --git a/drivers/staging/lustre/lustre/llite/lcommon_misc.c b/drivers/staging/lustre/lustre/llite/lcommon_misc.c index f6be105..fb346c1 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_misc.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_misc.c @@ -38,7 +38,6 @@ #include "../include/obd.h" #include "../include/cl_object.h" -#include "../include/lustre_lite.h" #include "llite_internal.h" /* Initialize the default and maximum LOV EA and cookie sizes. This allows diff --git a/drivers/staging/lustre/lustre/llite/llite_close.c b/drivers/staging/lustre/lustre/llite/llite_close.c index 2326b40..8644631 100644 --- a/drivers/staging/lustre/lustre/llite/llite_close.c +++ b/drivers/staging/lustre/lustre/llite/llite_close.c @@ -38,7 +38,6 @@ #define DEBUG_SUBSYSTEM S_LLITE -#include "../include/lustre_lite.h" #include "llite_internal.h" /** records that a write is in flight */ diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 7f0a6c9..f972ba3 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -60,6 +60,9 @@ #define LL_DIR_END_OFF 0x7fffffffffffffffULL #define LL_DIR_END_OFF_32BIT 0x7fffffffUL +/* 4UL * 1024 * 1024 */ +#define LL_MAX_BLKSIZE_BITS 22 + #define LL_IT2STR(it) ((it) ? ldlm_it2str((it)->it_op) : "0") #define LUSTRE_FPRIVATE(file) ((file)->private_data) @@ -445,6 +448,23 @@ enum stats_track_type { "norootsquash", \ } +/* + * This is embedded into llite super-blocks to keep track of connect + * flags (capabilities) supported by all imports given mount is + * connected to. + */ +struct lustre_client_ocd { + /* + * This is conjunction of connect_flags across all imports + * (LOVs) this mount is connected to. This field is updated by + * cl_ocd_update() under ->lco_lock. + */ + __u64 lco_flags; + struct mutex lco_lock; + struct obd_export *lco_md_exp; + struct obd_export *lco_dt_exp; +}; + struct ll_sb_info { /* this protects pglist and ra_info. It isn't safe to * grab from interrupt contexts @@ -669,6 +689,45 @@ void ll_rw_stats_tally(struct ll_sb_info *sbi, pid_t pid, struct ll_file_data *file, loff_t pos, size_t count, int rw); +enum { + LPROC_LL_DIRTY_HITS, + LPROC_LL_DIRTY_MISSES, + LPROC_LL_READ_BYTES, + LPROC_LL_WRITE_BYTES, + LPROC_LL_BRW_READ, + LPROC_LL_BRW_WRITE, + LPROC_LL_OSC_READ, + LPROC_LL_OSC_WRITE, + LPROC_LL_IOCTL, + LPROC_LL_OPEN, + LPROC_LL_RELEASE, + LPROC_LL_MAP, + LPROC_LL_LLSEEK, + LPROC_LL_FSYNC, + LPROC_LL_READDIR, + LPROC_LL_SETATTR, + LPROC_LL_TRUNC, + LPROC_LL_FLOCK, + LPROC_LL_GETATTR, + LPROC_LL_CREATE, + LPROC_LL_LINK, + LPROC_LL_UNLINK, + LPROC_LL_SYMLINK, + LPROC_LL_MKDIR, + LPROC_LL_RMDIR, + LPROC_LL_MKNOD, + LPROC_LL_RENAME, + LPROC_LL_STAFS, + LPROC_LL_ALLOC_INODE, + LPROC_LL_SETXATTR, + LPROC_LL_GETXATTR, + LPROC_LL_GETXATTR_HITS, + LPROC_LL_LISTXATTR, + LPROC_LL_REMOVEXATTR, + LPROC_LL_INODE_PERM, + LPROC_LL_FILE_OPCODES +}; + /* llite/dir.c */ extern const struct file_operations ll_dir_operations; extern const struct inode_operations ll_dir_inode_operations; @@ -677,7 +736,7 @@ int ll_dir_read(struct inode *inode, __u64 *ppos, struct md_op_data *op_data, int ll_get_mdt_idx(struct inode *inode); int ll_get_mdt_idx_by_fid(struct ll_sb_info *sbi, const struct lu_fid *fid); struct page *ll_get_dir_page(struct inode *dir, struct md_op_data *op_data, - __u64 offset, struct ll_dir_chain *chain); + __u64 offset); void ll_release_page(struct inode *inode, struct page *page, bool remove); /* llite/namei.c */ diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 9112fa8..19d18e8 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -42,7 +42,6 @@ #include <linux/mm.h> #include "../include/lustre/lustre_ioctl.h" -#include "../include/lustre_lite.h" #include "../include/lustre_ha.h" #include "../include/lustre_dlm.h" #include "../include/lprocfs_status.h" diff --git a/drivers/staging/lustre/lustre/llite/llite_mmap.c b/drivers/staging/lustre/lustre/llite/llite_mmap.c index 37f82ed..0cd25bf 100644 --- a/drivers/staging/lustre/lustre/llite/llite_mmap.c +++ b/drivers/staging/lustre/lustre/llite/llite_mmap.c @@ -43,7 +43,6 @@ #define DEBUG_SUBSYSTEM S_LLITE -#include "../include/lustre_lite.h" #include "llite_internal.h" #include "../include/linux/lustre_compat25.h" diff --git a/drivers/staging/lustre/lustre/llite/llite_nfs.c b/drivers/staging/lustre/lustre/llite/llite_nfs.c index 1e156dc..7092305 100644 --- a/drivers/staging/lustre/lustre/llite/llite_nfs.c +++ b/drivers/staging/lustre/lustre/llite/llite_nfs.c @@ -38,7 +38,6 @@ */ #define DEBUG_SUBSYSTEM S_LLITE -#include "../include/lustre_lite.h" #include "llite_internal.h" #include <linux/exportfs.h> diff --git a/drivers/staging/lustre/lustre/llite/lproc_llite.c b/drivers/staging/lustre/lustre/llite/lproc_llite.c index fc2ba56..6123435 100644 --- a/drivers/staging/lustre/lustre/llite/lproc_llite.c +++ b/drivers/staging/lustre/lustre/llite/lproc_llite.c @@ -31,7 +31,6 @@ */ #define DEBUG_SUBSYSTEM S_LLITE -#include "../include/lustre_lite.h" #include "../include/lprocfs_status.h" #include <linux/seq_file.h> #include "../include/obd_support.h" diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index 7a82ae4..e2dc920 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -42,7 +42,6 @@ #include "../include/obd_support.h" #include "../include/lustre_fid.h" -#include "../include/lustre_lite.h" #include "../include/lustre_dlm.h" #include "../include/lustre_ver.h" #include "llite_internal.h" diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index de20b7d..508cb46 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -50,7 +50,6 @@ #define DEBUG_SUBSYSTEM S_LLITE -#include "../include/lustre_lite.h" #include "../include/obd_cksum.h" #include "llite_internal.h" #include "../include/linux/lustre_compat25.h" diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c index 66dba04..6df89b0 100644 --- a/drivers/staging/lustre/lustre/llite/rw26.c +++ b/drivers/staging/lustre/lustre/llite/rw26.c @@ -51,7 +51,6 @@ #define DEBUG_SUBSYSTEM S_LLITE -#include "../include/lustre_lite.h" #include "llite_internal.h" #include "../include/linux/lustre_compat25.h" diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c index 6577a66..5760974 100644 --- a/drivers/staging/lustre/lustre/llite/statahead.c +++ b/drivers/staging/lustre/lustre/llite/statahead.c @@ -39,7 +39,6 @@ #define DEBUG_SUBSYSTEM S_LLITE #include "../include/obd_support.h" -#include "../include/lustre_lite.h" #include "../include/lustre_dlm.h" #include "llite_internal.h" @@ -1019,7 +1018,6 @@ static int ll_statahead_thread(void *arg) int first = 0; int rc = 0; struct md_op_data *op_data; - struct ll_dir_chain chain; struct l_wait_info lwi = { 0 }; sai = ll_sai_get(dir); @@ -1052,13 +1050,12 @@ static int ll_statahead_thread(void *arg) spin_unlock(&lli->lli_sa_lock); wake_up(&thread->t_ctl_waitq); - ll_dir_chain_init(&chain); while (pos != MDS_DIR_END_OFF && thread_is_running(thread)) { struct lu_dirpage *dp; struct lu_dirent *ent; sai->sai_in_readpage = 1; - page = ll_get_dir_page(dir, op_data, pos, &chain); + page = ll_get_dir_page(dir, op_data, pos); sai->sai_in_readpage = 0; if (IS_ERR(page)) { rc = PTR_ERR(page); @@ -1146,7 +1143,6 @@ static int ll_statahead_thread(void *arg) break; } } - ll_dir_chain_fini(&chain); ll_finish_md_op_data(op_data); if (rc < 0) { @@ -1280,7 +1276,6 @@ enum { static int is_first_dirent(struct inode *dir, struct dentry *dentry) { - struct ll_dir_chain chain; const struct qstr *target = &dentry->d_name; struct md_op_data *op_data; struct page *page; @@ -1297,8 +1292,7 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry) */ op_data->op_max_pages = ll_i2sbi(dir)->ll_md_brw_pages; - ll_dir_chain_init(&chain); - page = ll_get_dir_page(dir, op_data, pos, &chain); + page = ll_get_dir_page(dir, op_data, pos); while (1) { struct lu_dirpage *dp; @@ -1387,11 +1381,10 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry) ll_release_page(dir, page, le32_to_cpu(dp->ldp_flags) & LDF_COLLIDE); - page = ll_get_dir_page(dir, op_data, pos, &chain); + page = ll_get_dir_page(dir, op_data, pos); } } out: - ll_dir_chain_fini(&chain); ll_finish_md_op_data(op_data); return rc; } diff --git a/drivers/staging/lustre/lustre/llite/super25.c b/drivers/staging/lustre/lustre/llite/super25.c index 24c79c2..106cd00 100644 --- a/drivers/staging/lustre/lustre/llite/super25.c +++ b/drivers/staging/lustre/lustre/llite/super25.c @@ -34,7 +34,6 @@ #include <linux/module.h> #include <linux/types.h> -#include "../include/lustre_lite.h" #include "../include/lustre_ha.h" #include "../include/lustre_dlm.h" #include <linux/init.h> diff --git a/drivers/staging/lustre/lustre/llite/symlink.c b/drivers/staging/lustre/lustre/llite/symlink.c index 47fb799..f8bc7ed 100644 --- a/drivers/staging/lustre/lustre/llite/symlink.c +++ b/drivers/staging/lustre/lustre/llite/symlink.c @@ -35,7 +35,6 @@ #include <linux/stat.h> #define DEBUG_SUBSYSTEM S_LLITE -#include "../include/lustre_lite.h" #include "llite_internal.h" static int ll_readlink_internal(struct inode *inode, diff --git a/drivers/staging/lustre/lustre/llite/vvp_dev.c b/drivers/staging/lustre/lustre/llite/vvp_dev.c index 771c0bd..8aa8ecc 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_dev.c +++ b/drivers/staging/lustre/lustre/llite/vvp_dev.c @@ -38,7 +38,6 @@ #define DEBUG_SUBSYSTEM S_LLITE #include "../include/obd.h" -#include "../include/lustre_lite.h" #include "llite_internal.h" #include "vvp_internal.h" diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index f6dacee..27fc0b0 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -38,7 +38,6 @@ #define DEBUG_SUBSYSTEM S_LLITE #include "../include/obd.h" -#include "../include/lustre_lite.h" #include "llite_internal.h" #include "vvp_internal.h" diff --git a/drivers/staging/lustre/lustre/llite/vvp_lock.c b/drivers/staging/lustre/lustre/llite/vvp_lock.c index 64be0c9..07eb26c 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_lock.c +++ b/drivers/staging/lustre/lustre/llite/vvp_lock.c @@ -37,7 +37,6 @@ #define DEBUG_SUBSYSTEM S_LLITE #include "../include/obd_support.h" -#include "../include/lustre_lite.h" #include "vvp_internal.h" diff --git a/drivers/staging/lustre/lustre/llite/vvp_object.c b/drivers/staging/lustre/lustre/llite/vvp_object.c index e4080ba..01725fb 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_object.c +++ b/drivers/staging/lustre/lustre/llite/vvp_object.c @@ -39,7 +39,6 @@ #include "../../include/linux/libcfs/libcfs.h" #include "../include/obd.h" -#include "../include/lustre_lite.h" #include "llite_internal.h" #include "vvp_internal.h" diff --git a/drivers/staging/lustre/lustre/llite/vvp_page.c b/drivers/staging/lustre/lustre/llite/vvp_page.c index bbbb0f1..e763e7f 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_page.c +++ b/drivers/staging/lustre/lustre/llite/vvp_page.c @@ -44,8 +44,6 @@ #include <linux/page-flags.h> #include <linux/pagemap.h> -#include "../include/lustre_lite.h" - #include "llite_internal.h" #include "vvp_internal.h" diff --git a/drivers/staging/lustre/lustre/llite/vvp_req.c b/drivers/staging/lustre/lustre/llite/vvp_req.c index 0567a15..a6e2672 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_req.c +++ b/drivers/staging/lustre/lustre/llite/vvp_req.c @@ -32,7 +32,6 @@ #include "../include/cl_object.h" #include "../include/obd.h" #include "../include/obd_support.h" -#include "../include/lustre_lite.h" #include "llite_internal.h" #include "vvp_internal.h" diff --git a/drivers/staging/lustre/lustre/llite/xattr.c b/drivers/staging/lustre/lustre/llite/xattr.c index 7b8d469..17ad04f 100644 --- a/drivers/staging/lustre/lustre/llite/xattr.c +++ b/drivers/staging/lustre/lustre/llite/xattr.c @@ -38,7 +38,6 @@ #define DEBUG_SUBSYSTEM S_LLITE #include "../include/obd_support.h" -#include "../include/lustre_lite.h" #include "../include/lustre_dlm.h" #include "../include/lustre_ver.h" #include "../include/lustre_eacl.h" diff --git a/drivers/staging/lustre/lustre/llite/xattr_cache.c b/drivers/staging/lustre/lustre/llite/xattr_cache.c index 0330d1a..50a19a4 100644 --- a/drivers/staging/lustre/lustre/llite/xattr_cache.c +++ b/drivers/staging/lustre/lustre/llite/xattr_cache.c @@ -13,7 +13,6 @@ #include <linux/sched.h> #include <linux/mm.h> #include "../include/obd_support.h" -#include "../include/lustre_lite.h" #include "../include/lustre_dlm.h" #include "../include/lustre_ver.h" #include "llite_internal.h" diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 32d331e..9be479e 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -43,13 +43,11 @@ #include "../include/lustre/lustre_idl.h" #include "../include/obd_support.h" -#include "../include/lustre_lib.h" #include "../include/lustre_net.h" #include "../include/obd_class.h" #include "../include/lustre_lmv.h" #include "../include/lprocfs_status.h" #include "../include/cl_object.h" -#include "../include/lustre_lite.h" #include "../include/lustre_fid.h" #include "../include/lustre/lustre_ioctl.h" #include "../include/lustre_kernelcomm.h" -- cgit v0.10.2 From b9d4b143de6146a80e64b8a82dc9705498170059 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Sun, 18 Sep 2016 16:37:39 -0400 Subject: staging: lustre: obd: rename LUSTRE_STRIPE_MAXBYTES Rename LUSTRE_STRIPE_MAXBYTES to LUSTRE_EXT3_STRIPE_MAXBYTES and correct the comment describing its use. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2675 Reviewed-on: http://review.whamcloud.com/11800 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Bob Glossman <bob.glossman@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 0917aaa..19230a9 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -73,10 +73,12 @@ static inline void loi_init(struct lov_oinfo *loi) { } -/* Until such time as we get_info the per-stripe maximum from the OST, - * we define this to be 2T - 4k, which is the ext3 maxbytes. +/* + * If we are unable to get the maximum object size from the OST in + * ocd_maxbytes using OBD_CONNECT_MAXBYTES, then we fall back to using + * the old maximum object size from ext3. */ -#define LUSTRE_STRIPE_MAXBYTES 0x1fffffff000ULL +#define LUSTRE_EXT3_STRIPE_MAXBYTES 0x1fffffff000ULL struct lov_stripe_md { atomic_t lsm_refc; diff --git a/drivers/staging/lustre/lustre/lov/lov_ea.c b/drivers/staging/lustre/lustre/lov/lov_ea.c index d88b81d..9f0b5b7 100644 --- a/drivers/staging/lustre/lustre/lov/lov_ea.c +++ b/drivers/staging/lustre/lustre/lov/lov_ea.c @@ -154,14 +154,14 @@ static int lsm_destroy_plain(struct lov_stripe_md *lsm, struct obdo *oa, } /* Find minimum stripe maxbytes value. For inactive or - * reconnecting targets use LUSTRE_STRIPE_MAXBYTES. + * reconnecting targets use LUSTRE_EXT3_STRIPE_MAXBYTES. */ static void lov_tgt_maxbytes(struct lov_tgt_desc *tgt, __u64 *stripe_maxbytes) { struct obd_import *imp = tgt->ltd_obd->u.cli.cl_import; if (!imp || !tgt->ltd_active) { - *stripe_maxbytes = LUSTRE_STRIPE_MAXBYTES; + *stripe_maxbytes = LUSTRE_EXT3_STRIPE_MAXBYTES; return; } @@ -172,7 +172,7 @@ static void lov_tgt_maxbytes(struct lov_tgt_desc *tgt, __u64 *stripe_maxbytes) if (*stripe_maxbytes > imp->imp_connect_data.ocd_maxbytes) *stripe_maxbytes = imp->imp_connect_data.ocd_maxbytes; } else { - *stripe_maxbytes = LUSTRE_STRIPE_MAXBYTES; + *stripe_maxbytes = LUSTRE_EXT3_STRIPE_MAXBYTES; } spin_unlock(&imp->imp_lock); } diff --git a/drivers/staging/lustre/lustre/lov/lov_pack.c b/drivers/staging/lustre/lustre/lov/lov_pack.c index 869ef41..c654810 100644 --- a/drivers/staging/lustre/lustre/lov/lov_pack.c +++ b/drivers/staging/lustre/lustre/lov/lov_pack.c @@ -284,7 +284,7 @@ int lov_alloc_memmd(struct lov_stripe_md **lsmp, __u16 stripe_count, spin_lock_init(&(*lsmp)->lsm_lock); (*lsmp)->lsm_magic = magic; (*lsmp)->lsm_stripe_count = stripe_count; - (*lsmp)->lsm_maxbytes = LUSTRE_STRIPE_MAXBYTES * stripe_count; + (*lsmp)->lsm_maxbytes = LUSTRE_EXT3_STRIPE_MAXBYTES * stripe_count; (*lsmp)->lsm_pattern = pattern; (*lsmp)->lsm_pool_name[0] = '\0'; (*lsmp)->lsm_layout_gen = 0; diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index 6968953..cddc2d2 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -454,7 +454,7 @@ static int echo_alloc_memmd(struct echo_device *ed, } loi_init((*lsmp)->lsm_oinfo[0]); - (*lsmp)->lsm_maxbytes = LUSTRE_STRIPE_MAXBYTES; + (*lsmp)->lsm_maxbytes = LUSTRE_EXT3_STRIPE_MAXBYTES; ostid_set_seq_echo(&(*lsmp)->lsm_oi); return lsm_size; diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 0eb4e35..40a7ceb 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -190,7 +190,7 @@ static int osc_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, (imp->imp_connect_data.ocd_connect_flags & OBD_CONNECT_MAXBYTES)) (*lsmp)->lsm_maxbytes = imp->imp_connect_data.ocd_maxbytes; else - (*lsmp)->lsm_maxbytes = LUSTRE_STRIPE_MAXBYTES; + (*lsmp)->lsm_maxbytes = LUSTRE_EXT3_STRIPE_MAXBYTES; return lsm_size; } -- cgit v0.10.2 From 960a7e37f41e3f8bd3f974bef555991fe5cd3611 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Sun, 18 Sep 2016 16:37:40 -0400 Subject: staging: lustre: llite: don't call make_bad_inode() on an old inode In ll_iget() if ll_update_inode() fails then do not call make_bad_inode() on the inode since it may still be in use. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5468 Reviewed-on: http://review.whamcloud.com/11609 Reviewed-by: Lai Siyao <lai.siyao@intel.com> Reviewed-by: Fan Yong <fan.yong@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index e2dc920..85f8ce7 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -132,7 +132,6 @@ struct inode *ll_iget(struct super_block *sb, ino_t hash, CDEBUG(D_VFSTRACE, "got inode: "DFID"(%p): rc = %d\n", PFID(&md->body->mbo_fid1), inode, rc); if (rc) { - make_bad_inode(inode); iput(inode); inode = ERR_PTR(rc); } -- cgit v0.10.2 From d0d3d221f16bcdbff54087c4ea25e6e1dd954e76 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin <dmitry.eremin@intel.com> Date: Sun, 18 Sep 2016 16:37:41 -0400 Subject: staging: lustre: obd: change type of lmv_tgt_desc->ltd_idx to u32 ltd_idx is used as unsigned. Signed-off-by: Dmitry Eremin <dmitry.eremin@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5577 Reviewed-on: http://review.whamcloud.com/11879 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Fan Yong <fan.yong@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 19230a9..4b72fb9 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -406,7 +406,7 @@ struct lov_obd { struct lmv_tgt_desc { struct obd_uuid ltd_uuid; struct obd_export *ltd_exp; - int ltd_idx; + u32 ltd_idx; struct mutex ltd_fid_mutex; unsigned long ltd_active:1; /* target up for requests */ }; diff --git a/drivers/staging/lustre/lustre/lmv/lmv_intent.c b/drivers/staging/lustre/lustre/lmv/lmv_intent.c index f24848f..02bf3c3 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_intent.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_intent.c @@ -113,7 +113,7 @@ static int lmv_intent_remote(struct obd_export *exp, struct lookup_intent *it, } op_data->op_bias = MDS_CROSS_REF; - CDEBUG(D_INODE, "REMOTE_INTENT with fid="DFID" -> mds #%d\n", + CDEBUG(D_INODE, "REMOTE_INTENT with fid=" DFID " -> mds #%u\n", PFID(&body->mbo_fid1), tgt->ltd_idx); rc = md_intent_lock(tgt->ltd_exp, op_data, it, &req, cb_blocking, @@ -202,7 +202,7 @@ int lmv_revalidate_slaves(struct obd_export *exp, struct mdt_body *mbody, goto cleanup; } - CDEBUG(D_INODE, "Revalidate slave "DFID" -> mds #%d\n", + CDEBUG(D_INODE, "Revalidate slave " DFID " -> mds #%u\n", PFID(&fid), tgt->ltd_idx); if (req) { @@ -349,7 +349,7 @@ static int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data, return rc; } - CDEBUG(D_INODE, "OPEN_INTENT with fid1=" DFID ", fid2=" DFID ", name='%s' -> mds #%d\n", + CDEBUG(D_INODE, "OPEN_INTENT with fid1=" DFID ", fid2=" DFID ", name='%s' -> mds #%u\n", PFID(&op_data->op_fid1), PFID(&op_data->op_fid2), op_data->op_name, tgt->ltd_idx); @@ -427,7 +427,7 @@ static int lmv_intent_lookup(struct obd_export *exp, if (!fid_is_sane(&op_data->op_fid2)) fid_zero(&op_data->op_fid2); - CDEBUG(D_INODE, "LOOKUP_INTENT with fid1="DFID", fid2="DFID", name='%s' -> mds #%d lsm=%p lsm_magic=%x\n", + CDEBUG(D_INODE, "LOOKUP_INTENT with fid1=" DFID ", fid2=" DFID ", name='%s' -> mds #%u lsm=%p lsm_magic=%x\n", PFID(&op_data->op_fid1), PFID(&op_data->op_fid2), op_data->op_name ? op_data->op_name : "<NULL>", tgt->ltd_idx, lsm, !lsm ? -1 : lsm->lsm_md_magic); diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 9be479e..e1428cb 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -1834,7 +1834,7 @@ lmv_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo, if (IS_ERR(tgt)) return PTR_ERR(tgt); - CDEBUG(D_INODE, "ENQUEUE '%s' on "DFID" -> mds #%d\n", + CDEBUG(D_INODE, "ENQUEUE '%s' on " DFID " -> mds #%u\n", LL_IT2STR(it), PFID(&op_data->op_fid1), tgt->ltd_idx); rc = md_enqueue(tgt->ltd_exp, einfo, policy, it, op_data, lockh, @@ -1862,7 +1862,7 @@ lmv_getattr_name(struct obd_export *exp, struct md_op_data *op_data, if (IS_ERR(tgt)) return PTR_ERR(tgt); - CDEBUG(D_INODE, "GETATTR_NAME for %*s on "DFID" -> mds #%d\n", + CDEBUG(D_INODE, "GETATTR_NAME for %*s on " DFID " -> mds #%u\n", op_data->op_namelen, op_data->op_name, PFID(&op_data->op_fid1), tgt->ltd_idx); @@ -2607,7 +2607,7 @@ try_next_stripe: if (rc != 0) return rc; - CDEBUG(D_INODE, "unlink with fid="DFID"/"DFID" -> mds #%d\n", + CDEBUG(D_INODE, "unlink with fid=" DFID "/" DFID " -> mds #%u\n", PFID(&op_data->op_fid1), PFID(&op_data->op_fid2), tgt->ltd_idx); rc = md_unlink(tgt->ltd_exp, op_data, request); diff --git a/drivers/staging/lustre/lustre/lmv/lproc_lmv.c b/drivers/staging/lustre/lustre/lmv/lproc_lmv.c index d2316c0..20bbdfc 100644 --- a/drivers/staging/lustre/lustre/lmv/lproc_lmv.c +++ b/drivers/staging/lustre/lustre/lmv/lproc_lmv.c @@ -169,7 +169,7 @@ static int lmv_tgt_seq_show(struct seq_file *p, void *v) if (!tgt) return 0; - seq_printf(p, "%d: %s %sACTIVE\n", + seq_printf(p, "%u: %s %sACTIVE\n", tgt->ltd_idx, tgt->ltd_uuid.uuid, tgt->ltd_active ? "" : "IN"); return 0; -- cgit v0.10.2 From f32a692993dd6238b7261c2e1fe971ab3195b5b3 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin <dmitry.eremin@intel.com> Date: Sun, 18 Sep 2016 16:37:42 -0400 Subject: staging: lustre: lmv: change type of lmv_obd->tgts_size to u32 tgts_size is used as unsigned. Signed-off-by: Dmitry Eremin <dmitry.eremin@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5577 Reviewed-on: http://review.whamcloud.com/11881 Reviewed-by: Fan Yong <fan.yong@intel.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 4b72fb9..27fb4d7 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -435,7 +435,7 @@ struct lmv_obd { int max_def_cookiesize; int server_timeout; - int tgts_size; /* size of tgts array */ + u32 tgts_size; /* size of tgts array */ struct lmv_tgt_desc **tgts; struct obd_connect_data conn_data; diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index e1428cb..8d9e3b8 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -1353,10 +1353,10 @@ static int lmv_setup(struct obd_device *obd, struct lustre_cfg *lcfg) return -EINVAL; } - lmv->tgts = kcalloc(32, sizeof(*lmv->tgts), GFP_NOFS); + lmv->tgts_size = 32U; + lmv->tgts = kcalloc(lmv->tgts_size, sizeof(*lmv->tgts), GFP_NOFS); if (!lmv->tgts) return -ENOMEM; - lmv->tgts_size = 32; obd_str2uuid(&lmv->desc.ld_uuid, desc->ld_uuid.uuid); lmv->desc.ld_tgt_count = 0; -- cgit v0.10.2 From 29c877a5892e42a6b57812514d90ff4357511d90 Mon Sep 17 00:00:00 2001 From: Stephen Champion <schamp@sgi.com> Date: Sun, 18 Sep 2016 16:37:43 -0400 Subject: staging: lustre: misc: Reduce exposure to overflow on page counters. When the number of an object in use or circulation is tied to memory size of the system, very large memory systems can overflow 32 bit counters. This patch addresses overflow on page counters in the osc LRU and obd accounting. Signed-off-by: Stephen Champion <schamp@sgi.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4856 Reviewed-on: http://review.whamcloud.com/10537 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index 41e0801..5039643 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -2326,7 +2326,7 @@ struct cl_client_cache { /** * # of LRU entries available */ - atomic_t ccc_lru_left; + atomic_long_t ccc_lru_left; /** * List of entities(OSCs) for this LRU cache */ @@ -2346,7 +2346,7 @@ struct cl_client_cache { /** * # of unstable pages for this mount point */ - atomic_t ccc_unstable_nr; + atomic_long_t ccc_unstable_nr; /** * Waitq for awaiting unstable pages to reach zero. * Used at umounting time and signaled on BRW commit diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 27fb4d7..3fbb873 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -293,13 +293,13 @@ struct client_obd { /* lru for osc caching pages */ struct cl_client_cache *cl_cache; struct list_head cl_lru_osc; /* member of cl_cache->ccc_lru */ - atomic_t *cl_lru_left; - atomic_t cl_lru_busy; + atomic_long_t *cl_lru_left; + atomic_long_t cl_lru_busy; + atomic_long_t cl_lru_in_list; atomic_t cl_lru_shrinkers; - atomic_t cl_lru_in_list; struct list_head cl_lru_list; /* lru page list */ spinlock_t cl_lru_list_lock; /* page list protector */ - atomic_t cl_unstable_count; + atomic_long_t cl_unstable_count; /* number of in flight destroy rpcs is limited to max_rpcs_in_flight */ atomic_t cl_destroy_in_flight; diff --git a/drivers/staging/lustre/lustre/include/obd_support.h b/drivers/staging/lustre/lustre/include/obd_support.h index 4d7a5c8..d4c41d0 100644 --- a/drivers/staging/lustre/lustre/include/obd_support.h +++ b/drivers/staging/lustre/lustre/include/obd_support.h @@ -52,9 +52,9 @@ extern unsigned int at_max; extern unsigned int at_history; extern int at_early_margin; extern int at_extra; -extern unsigned int obd_max_dirty_pages; -extern atomic_t obd_dirty_pages; -extern atomic_t obd_dirty_transit_pages; +extern unsigned long obd_max_dirty_pages; +extern atomic_long_t obd_dirty_pages; +extern atomic_long_t obd_dirty_transit_pages; extern char obd_jobid_var[]; /* Some hash init argument constants */ diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c index 0d466e2..9a5f56a 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c @@ -328,11 +328,11 @@ int client_obd_setup(struct obd_device *obddev, struct lustre_cfg *lcfg) /* lru for osc. */ INIT_LIST_HEAD(&cli->cl_lru_osc); atomic_set(&cli->cl_lru_shrinkers, 0); - atomic_set(&cli->cl_lru_busy, 0); - atomic_set(&cli->cl_lru_in_list, 0); + atomic_long_set(&cli->cl_lru_busy, 0); + atomic_long_set(&cli->cl_lru_in_list, 0); INIT_LIST_HEAD(&cli->cl_lru_list); spin_lock_init(&cli->cl_lru_list_lock); - atomic_set(&cli->cl_unstable_count, 0); + atomic_long_set(&cli->cl_unstable_count, 0); init_waitqueue_head(&cli->cl_destroy_waitq); atomic_set(&cli->cl_destroy_in_flight, 0); diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 19d18e8..2aab396 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -926,7 +926,8 @@ void ll_put_super(struct super_block *sb) struct lustre_sb_info *lsi = s2lsi(sb); struct ll_sb_info *sbi = ll_s2sbi(sb); char *profilenm = get_profile_name(sb); - int ccc_count, next, force = 1, rc = 0; + int next, force = 1, rc = 0; + long ccc_count; CDEBUG(D_VFSTRACE, "VFS Op: sb %p - %s\n", sb, profilenm); @@ -947,13 +948,13 @@ void ll_put_super(struct super_block *sb) struct l_wait_info lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL); rc = l_wait_event(sbi->ll_cache->ccc_unstable_waitq, - !atomic_read(&sbi->ll_cache->ccc_unstable_nr), + !atomic_long_read(&sbi->ll_cache->ccc_unstable_nr), &lwi); } - ccc_count = atomic_read(&sbi->ll_cache->ccc_unstable_nr); + ccc_count = atomic_long_read(&sbi->ll_cache->ccc_unstable_nr); if (!force && rc != -EINTR) - LASSERTF(!ccc_count, "count: %i\n", ccc_count); + LASSERTF(!ccc_count, "count: %li\n", ccc_count); /* We need to set force before the lov_disconnect in * lustre_common_put_super, since l_d cleans up osc's as well. diff --git a/drivers/staging/lustre/lustre/llite/lproc_llite.c b/drivers/staging/lustre/lustre/llite/lproc_llite.c index 6123435..188fd37 100644 --- a/drivers/staging/lustre/lustre/llite/lproc_llite.c +++ b/drivers/staging/lustre/lustre/llite/lproc_llite.c @@ -357,16 +357,16 @@ static int ll_max_cached_mb_seq_show(struct seq_file *m, void *v) struct ll_sb_info *sbi = ll_s2sbi(sb); struct cl_client_cache *cache = sbi->ll_cache; int shift = 20 - PAGE_SHIFT; - int max_cached_mb; - int unused_mb; + long max_cached_mb; + long unused_mb; max_cached_mb = cache->ccc_lru_max >> shift; - unused_mb = atomic_read(&cache->ccc_lru_left) >> shift; + unused_mb = atomic_long_read(&cache->ccc_lru_left) >> shift; seq_printf(m, "users: %d\n" - "max_cached_mb: %d\n" - "used_mb: %d\n" - "unused_mb: %d\n" + "max_cached_mb: %ld\n" + "used_mb: %ld\n" + "unused_mb: %ld\n" "reclaim_count: %u\n", atomic_read(&cache->ccc_users), max_cached_mb, @@ -384,10 +384,13 @@ static ssize_t ll_max_cached_mb_seq_write(struct file *file, struct ll_sb_info *sbi = ll_s2sbi(sb); struct cl_client_cache *cache = sbi->ll_cache; struct lu_env *env; + long diff = 0; + long nrpages = 0; int refcheck; - int mult, rc, pages_number; - int diff = 0; - int nrpages = 0; + long pages_number; + int mult; + long rc; + u64 val; char kernbuf[128]; if (count >= sizeof(kernbuf)) @@ -400,10 +403,14 @@ static ssize_t ll_max_cached_mb_seq_write(struct file *file, mult = 1 << (20 - PAGE_SHIFT); buffer += lprocfs_find_named_value(kernbuf, "max_cached_mb:", &count) - kernbuf; - rc = lprocfs_write_frac_helper(buffer, count, &pages_number, mult); + rc = lprocfs_write_frac_u64_helper(buffer, count, &val, mult); if (rc) return rc; + if (val > LONG_MAX) + return -ERANGE; + pages_number = (long)val; + if (pages_number < 0 || pages_number > totalram_pages) { CERROR("%s: can't set max cache more than %lu MB\n", ll_get_fsname(sb, NULL, 0), @@ -417,7 +424,7 @@ static ssize_t ll_max_cached_mb_seq_write(struct file *file, /* easy - add more LRU slots. */ if (diff >= 0) { - atomic_add(diff, &cache->ccc_lru_left); + atomic_long_add(diff, &cache->ccc_lru_left); rc = 0; goto out; } @@ -428,18 +435,18 @@ static ssize_t ll_max_cached_mb_seq_write(struct file *file, diff = -diff; while (diff > 0) { - int tmp; + long tmp; /* reduce LRU budget from free slots. */ do { - int ov, nv; + long ov, nv; - ov = atomic_read(&cache->ccc_lru_left); + ov = atomic_long_read(&cache->ccc_lru_left); if (ov == 0) break; nv = ov > diff ? ov - diff : 0; - rc = atomic_cmpxchg(&cache->ccc_lru_left, ov, nv); + rc = atomic_long_cmpxchg(&cache->ccc_lru_left, ov, nv); if (likely(ov == rc)) { diff -= ov - nv; nrpages += ov - nv; @@ -473,7 +480,7 @@ out: spin_unlock(&sbi->ll_lock); rc = count; } else { - atomic_add(nrpages, &cache->ccc_lru_left); + atomic_long_add(nrpages, &cache->ccc_lru_left); } return rc; } @@ -822,14 +829,15 @@ static ssize_t unstable_stats_show(struct kobject *kobj, struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info, ll_kobj); struct cl_client_cache *cache = sbi->ll_cache; - int pages, mb; + long pages; + int mb; - pages = atomic_read(&cache->ccc_unstable_nr); + pages = atomic_long_read(&cache->ccc_unstable_nr); mb = (pages * PAGE_SIZE) >> 20; - return sprintf(buf, "unstable_check: %8d\n" - "unstable_pages: %8d\n" - "unstable_mb: %8d\n", + return sprintf(buf, "unstable_check: %8d\n" + "unstable_pages: %12ld\n" + "unstable_mb: %8d\n", cache->ccc_unstable_check, pages, mb); } diff --git a/drivers/staging/lustre/lustre/obdclass/cl_page.c b/drivers/staging/lustre/lustre/obdclass/cl_page.c index cae8d21..5c89dbd 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_page.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_page.c @@ -1073,11 +1073,11 @@ struct cl_client_cache *cl_cache_init(unsigned long lru_page_max) /* Initialize cache data */ atomic_set(&cache->ccc_users, 1); cache->ccc_lru_max = lru_page_max; - atomic_set(&cache->ccc_lru_left, lru_page_max); + atomic_long_set(&cache->ccc_lru_left, lru_page_max); spin_lock_init(&cache->ccc_lru_lock); INIT_LIST_HEAD(&cache->ccc_lru); - atomic_set(&cache->ccc_unstable_nr, 0); + atomic_long_set(&cache->ccc_unstable_nr, 0); init_waitqueue_head(&cache->ccc_unstable_waitq); return cache; diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c index 2293f6a..629d8b5 100644 --- a/drivers/staging/lustre/lustre/obdclass/class_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c @@ -55,9 +55,9 @@ unsigned int obd_dump_on_timeout; EXPORT_SYMBOL(obd_dump_on_timeout); unsigned int obd_dump_on_eviction; EXPORT_SYMBOL(obd_dump_on_eviction); -unsigned int obd_max_dirty_pages = 256; +unsigned long obd_max_dirty_pages; EXPORT_SYMBOL(obd_max_dirty_pages); -atomic_t obd_dirty_pages; +atomic_long_t obd_dirty_pages; EXPORT_SYMBOL(obd_dirty_pages); unsigned int obd_timeout = OBD_TIMEOUT_DEFAULT; /* seconds */ EXPORT_SYMBOL(obd_timeout); @@ -75,7 +75,7 @@ EXPORT_SYMBOL(at_early_margin); int at_extra = 30; EXPORT_SYMBOL(at_extra); -atomic_t obd_dirty_transit_pages; +atomic_long_t obd_dirty_transit_pages; EXPORT_SYMBOL(obd_dirty_transit_pages); char obd_jobid_var[JOBSTATS_JOBID_VAR_MAX_LEN + 1] = JOBSTATS_DISABLE; diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c index aea1abd..e6c785a 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c @@ -97,8 +97,7 @@ static ssize_t max_dirty_mb_show(struct kobject *kobj, struct attribute *attr, char *buf) { return sprintf(buf, "%lu\n", - (unsigned long)obd_max_dirty_pages / - (1 << (20 - PAGE_SHIFT))); + obd_max_dirty_pages / (1 << (20 - PAGE_SHIFT))); } static ssize_t max_dirty_mb_store(struct kobject *kobj, struct attribute *attr, diff --git a/drivers/staging/lustre/lustre/osc/lproc_osc.c b/drivers/staging/lustre/lustre/osc/lproc_osc.c index 9172b78..f0062d4 100644 --- a/drivers/staging/lustre/lustre/osc/lproc_osc.c +++ b/drivers/staging/lustre/lustre/osc/lproc_osc.c @@ -182,11 +182,11 @@ static int osc_cached_mb_seq_show(struct seq_file *m, void *v) int shift = 20 - PAGE_SHIFT; seq_printf(m, - "used_mb: %d\n" - "busy_cnt: %d\n", - (atomic_read(&cli->cl_lru_in_list) + - atomic_read(&cli->cl_lru_busy)) >> shift, - atomic_read(&cli->cl_lru_busy)); + "used_mb: %ld\n" + "busy_cnt: %ld\n", + (atomic_long_read(&cli->cl_lru_in_list) + + atomic_long_read(&cli->cl_lru_busy)) >> shift, + atomic_long_read(&cli->cl_lru_busy)); return 0; } @@ -198,8 +198,10 @@ static ssize_t osc_cached_mb_seq_write(struct file *file, { struct obd_device *dev = ((struct seq_file *)file->private_data)->private; struct client_obd *cli = &dev->u.cli; - int pages_number, mult, rc; + long pages_number, rc; char kernbuf[128]; + int mult; + u64 val; if (count >= sizeof(kernbuf)) return -EINVAL; @@ -211,14 +213,18 @@ static ssize_t osc_cached_mb_seq_write(struct file *file, mult = 1 << (20 - PAGE_SHIFT); buffer += lprocfs_find_named_value(kernbuf, "used_mb:", &count) - kernbuf; - rc = lprocfs_write_frac_helper(buffer, count, &pages_number, mult); + rc = lprocfs_write_frac_u64_helper(buffer, count, &val, mult); if (rc) return rc; + if (val > LONG_MAX) + return -ERANGE; + pages_number = (long)val; + if (pages_number < 0) return -ERANGE; - rc = atomic_read(&cli->cl_lru_in_list) - pages_number; + rc = atomic_long_read(&cli->cl_lru_in_list) - pages_number; if (rc > 0) { struct lu_env *env; int refcheck; @@ -598,13 +604,14 @@ static ssize_t unstable_stats_show(struct kobject *kobj, struct obd_device *dev = container_of(kobj, struct obd_device, obd_kobj); struct client_obd *cli = &dev->u.cli; - int pages, mb; + long pages; + int mb; - pages = atomic_read(&cli->cl_unstable_count); + pages = atomic_long_read(&cli->cl_unstable_count); mb = (pages * PAGE_SIZE) >> 20; - return sprintf(buf, "unstable_pages: %8d\n" - "unstable_mb: %8d\n", pages, mb); + return sprintf(buf, "unstable_pages: %20ld\n" + "unstable_mb: %10d\n", pages, mb); } LUSTRE_RO_ATTR(unstable_stats); diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index 97f936e..26ad360 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -1383,16 +1383,16 @@ static int osc_completion(const struct lu_env *env, struct osc_async_page *oap, #define OSC_DUMP_GRANT(lvl, cli, fmt, args...) do { \ struct client_obd *__tmp = (cli); \ - CDEBUG(lvl, "%s: grant { dirty: %ld/%ld dirty_pages: %d/%d " \ + CDEBUG(lvl, "%s: grant { dirty: %ld/%ld dirty_pages: %ld/%lu " \ "dropped: %ld avail: %ld, reserved: %ld, flight: %d }" \ - "lru {in list: %d, left: %d, waiters: %d }" fmt, \ + "lru {in list: %ld, left: %ld, waiters: %d }" fmt, \ __tmp->cl_import->imp_obd->obd_name, \ __tmp->cl_dirty_pages, __tmp->cl_dirty_max_pages, \ - atomic_read(&obd_dirty_pages), obd_max_dirty_pages, \ + atomic_long_read(&obd_dirty_pages), obd_max_dirty_pages, \ __tmp->cl_lost_grant, __tmp->cl_avail_grant, \ __tmp->cl_reserved_grant, __tmp->cl_w_in_flight, \ - atomic_read(&__tmp->cl_lru_in_list), \ - atomic_read(&__tmp->cl_lru_busy), \ + atomic_long_read(&__tmp->cl_lru_in_list), \ + atomic_long_read(&__tmp->cl_lru_busy), \ atomic_read(&__tmp->cl_lru_shrinkers), ##args); \ } while (0) @@ -1402,7 +1402,7 @@ static void osc_consume_write_grant(struct client_obd *cli, { assert_spin_locked(&cli->cl_loi_list_lock); LASSERT(!(pga->flag & OBD_BRW_FROM_GRANT)); - atomic_inc(&obd_dirty_pages); + atomic_long_inc(&obd_dirty_pages); cli->cl_dirty_pages++; pga->flag |= OBD_BRW_FROM_GRANT; CDEBUG(D_CACHE, "using %lu grant credits for brw %p page %p\n", @@ -1422,11 +1422,11 @@ static void osc_release_write_grant(struct client_obd *cli, } pga->flag &= ~OBD_BRW_FROM_GRANT; - atomic_dec(&obd_dirty_pages); + atomic_long_dec(&obd_dirty_pages); cli->cl_dirty_pages--; if (pga->flag & OBD_BRW_NOCACHE) { pga->flag &= ~OBD_BRW_NOCACHE; - atomic_dec(&obd_dirty_transit_pages); + atomic_long_dec(&obd_dirty_transit_pages); cli->cl_dirty_transit--; } } @@ -1495,7 +1495,7 @@ static void osc_free_grant(struct client_obd *cli, unsigned int nr_pages, int grant = (1 << cli->cl_chunkbits) + cli->cl_extent_tax; spin_lock(&cli->cl_loi_list_lock); - atomic_sub(nr_pages, &obd_dirty_pages); + atomic_long_sub(nr_pages, &obd_dirty_pages); cli->cl_dirty_pages -= nr_pages; cli->cl_lost_grant += lost_grant; if (cli->cl_avail_grant < grant && cli->cl_lost_grant >= grant) { @@ -1540,11 +1540,11 @@ static int osc_enter_cache_try(struct client_obd *cli, return 0; if (cli->cl_dirty_pages <= cli->cl_dirty_max_pages && - atomic_read(&obd_dirty_pages) + 1 <= obd_max_dirty_pages) { + atomic_long_read(&obd_dirty_pages) + 1 <= obd_max_dirty_pages) { osc_consume_write_grant(cli, &oap->oap_brw_page); if (transient) { cli->cl_dirty_transit++; - atomic_inc(&obd_dirty_transit_pages); + atomic_long_inc(&obd_dirty_transit_pages); oap->oap_brw_flags |= OBD_BRW_NOCACHE; } rc = 1; @@ -1668,8 +1668,9 @@ void osc_wake_cache_waiters(struct client_obd *cli) ocw->ocw_rc = -EDQUOT; /* we can't dirty more */ if ((cli->cl_dirty_pages > cli->cl_dirty_max_pages) || - (atomic_read(&obd_dirty_pages) + 1 > obd_max_dirty_pages)) { - CDEBUG(D_CACHE, "no dirty room: dirty: %ld osc max %ld, sys max %d\n", + (atomic_long_read(&obd_dirty_pages) + 1 > + obd_max_dirty_pages)) { + CDEBUG(D_CACHE, "no dirty room: dirty: %ld osc max %ld, sys max %ld\n", cli->cl_dirty_pages, cli->cl_dirty_max_pages, obd_max_dirty_pages); goto wakeup; diff --git a/drivers/staging/lustre/lustre/osc/osc_internal.h b/drivers/staging/lustre/lustre/osc/osc_internal.h index eca5fef..67fe0a2 100644 --- a/drivers/staging/lustre/lustre/osc/osc_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_internal.h @@ -133,9 +133,9 @@ int osc_sync_base(struct obd_export *exp, struct obd_info *oinfo, int osc_process_config_base(struct obd_device *obd, struct lustre_cfg *cfg); int osc_build_rpc(const struct lu_env *env, struct client_obd *cli, struct list_head *ext_list, int cmd); -int osc_lru_shrink(const struct lu_env *env, struct client_obd *cli, - int target, bool force); -int osc_lru_reclaim(struct client_obd *cli); +long osc_lru_shrink(const struct lu_env *env, struct client_obd *cli, + long target, bool force); +long osc_lru_reclaim(struct client_obd *cli); unsigned long osc_ldlm_weigh_ast(struct ldlm_lock *dlmlock); diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c index f6db60c..7698054 100644 --- a/drivers/staging/lustre/lustre/osc/osc_io.c +++ b/drivers/staging/lustre/lustre/osc/osc_io.c @@ -319,8 +319,8 @@ static int osc_io_rw_iter_init(const struct lu_env *env, struct osc_object *osc = cl2osc(ios->cis_obj); struct client_obd *cli = osc_cli(osc); unsigned long c; - unsigned int npages; - unsigned int max_pages; + unsigned long npages; + unsigned long max_pages; if (cl_io_is_append(io)) return 0; @@ -333,15 +333,15 @@ static int osc_io_rw_iter_init(const struct lu_env *env, if (npages > max_pages) npages = max_pages; - c = atomic_read(cli->cl_lru_left); + c = atomic_long_read(cli->cl_lru_left); if (c < npages && osc_lru_reclaim(cli) > 0) - c = atomic_read(cli->cl_lru_left); + c = atomic_long_read(cli->cl_lru_left); while (c >= npages) { - if (c == atomic_cmpxchg(cli->cl_lru_left, c, c - npages)) { + if (c == atomic_long_cmpxchg(cli->cl_lru_left, c, c - npages)) { oio->oi_lru_reserved = npages; break; } - c = atomic_read(cli->cl_lru_left); + c = atomic_long_read(cli->cl_lru_left); } return 0; @@ -355,7 +355,7 @@ static void osc_io_rw_iter_fini(const struct lu_env *env, struct client_obd *cli = osc_cli(osc); if (oio->oi_lru_reserved > 0) { - atomic_add(oio->oi_lru_reserved, cli->cl_lru_left); + atomic_long_add(oio->oi_lru_reserved, cli->cl_lru_left); oio->oi_lru_reserved = 0; } oio->oi_write_osclock = NULL; diff --git a/drivers/staging/lustre/lustre/osc/osc_page.c b/drivers/staging/lustre/lustre/osc/osc_page.c index c8889ea..2a7a70a 100644 --- a/drivers/staging/lustre/lustre/osc/osc_page.c +++ b/drivers/staging/lustre/lustre/osc/osc_page.c @@ -380,7 +380,7 @@ static const int lru_shrink_max = 8 << (20 - PAGE_SHIFT); /* 8M */ static int osc_cache_too_much(struct client_obd *cli) { struct cl_client_cache *cache = cli->cl_cache; - int pages = atomic_read(&cli->cl_lru_in_list); + long pages = atomic_long_read(&cli->cl_lru_in_list); unsigned long budget; budget = cache->ccc_lru_max / (atomic_read(&cache->ccc_users) - 2); @@ -388,7 +388,7 @@ static int osc_cache_too_much(struct client_obd *cli) /* if it's going to run out LRU slots, we should free some, but not * too much to maintain fairness among OSCs. */ - if (atomic_read(cli->cl_lru_left) < cache->ccc_lru_max >> 4) { + if (atomic_long_read(cli->cl_lru_left) < cache->ccc_lru_max >> 4) { if (pages >= budget) return lru_shrink_max; else if (pages >= budget / 2) @@ -415,7 +415,7 @@ void osc_lru_add_batch(struct client_obd *cli, struct list_head *plist) { LIST_HEAD(lru); struct osc_async_page *oap; - int npages = 0; + long npages = 0; list_for_each_entry(oap, plist, oap_pending_item) { struct osc_page *opg = oap2osc_page(oap); @@ -431,8 +431,8 @@ void osc_lru_add_batch(struct client_obd *cli, struct list_head *plist) if (npages > 0) { spin_lock(&cli->cl_lru_list_lock); list_splice_tail(&lru, &cli->cl_lru_list); - atomic_sub(npages, &cli->cl_lru_busy); - atomic_add(npages, &cli->cl_lru_in_list); + atomic_long_sub(npages, &cli->cl_lru_busy); + atomic_long_add(npages, &cli->cl_lru_in_list); spin_unlock(&cli->cl_lru_list_lock); /* XXX: May set force to be true for better performance */ @@ -443,9 +443,9 @@ void osc_lru_add_batch(struct client_obd *cli, struct list_head *plist) static void __osc_lru_del(struct client_obd *cli, struct osc_page *opg) { - LASSERT(atomic_read(&cli->cl_lru_in_list) > 0); + LASSERT(atomic_long_read(&cli->cl_lru_in_list) > 0); list_del_init(&opg->ops_lru); - atomic_dec(&cli->cl_lru_in_list); + atomic_long_dec(&cli->cl_lru_in_list); } /** @@ -459,12 +459,12 @@ static void osc_lru_del(struct client_obd *cli, struct osc_page *opg) if (!list_empty(&opg->ops_lru)) { __osc_lru_del(cli, opg); } else { - LASSERT(atomic_read(&cli->cl_lru_busy) > 0); - atomic_dec(&cli->cl_lru_busy); + LASSERT(atomic_long_read(&cli->cl_lru_busy) > 0); + atomic_long_dec(&cli->cl_lru_busy); } spin_unlock(&cli->cl_lru_list_lock); - atomic_inc(cli->cl_lru_left); + atomic_long_inc(cli->cl_lru_left); /* this is a great place to release more LRU pages if * this osc occupies too many LRU pages and kernel is * stealing one of them. @@ -489,7 +489,7 @@ static void osc_lru_use(struct client_obd *cli, struct osc_page *opg) spin_lock(&cli->cl_lru_list_lock); __osc_lru_del(cli, opg); spin_unlock(&cli->cl_lru_list_lock); - atomic_inc(&cli->cl_lru_busy); + atomic_long_inc(&cli->cl_lru_busy); } } @@ -535,8 +535,8 @@ static inline bool lru_page_busy(struct client_obd *cli, struct cl_page *page) /** * Drop @target of pages from LRU at most. */ -int osc_lru_shrink(const struct lu_env *env, struct client_obd *cli, - int target, bool force) +long osc_lru_shrink(const struct lu_env *env, struct client_obd *cli, + long target, bool force) { struct cl_io *io; struct cl_object *clobj = NULL; @@ -544,12 +544,12 @@ int osc_lru_shrink(const struct lu_env *env, struct client_obd *cli, struct osc_page *opg; struct osc_page *temp; int maxscan = 0; - int count = 0; + long count = 0; int index = 0; int rc = 0; - LASSERT(atomic_read(&cli->cl_lru_in_list) >= 0); - if (atomic_read(&cli->cl_lru_in_list) == 0 || target <= 0) + LASSERT(atomic_long_read(&cli->cl_lru_in_list) >= 0); + if (atomic_long_read(&cli->cl_lru_in_list) == 0 || target <= 0) return 0; if (!force) { @@ -568,7 +568,7 @@ int osc_lru_shrink(const struct lu_env *env, struct client_obd *cli, io = &osc_env_info(env)->oti_io; spin_lock(&cli->cl_lru_list_lock); - maxscan = min(target << 1, atomic_read(&cli->cl_lru_in_list)); + maxscan = min(target << 1, atomic_long_read(&cli->cl_lru_in_list)); list_for_each_entry_safe(opg, temp, &cli->cl_lru_list, ops_lru) { struct cl_page *page; bool will_free = false; @@ -656,24 +656,19 @@ int osc_lru_shrink(const struct lu_env *env, struct client_obd *cli, atomic_dec(&cli->cl_lru_shrinkers); if (count > 0) { - atomic_add(count, cli->cl_lru_left); + atomic_long_add(count, cli->cl_lru_left); wake_up_all(&osc_lru_waitq); } return count > 0 ? count : rc; } -static inline int max_to_shrink(struct client_obd *cli) -{ - return min(atomic_read(&cli->cl_lru_in_list) >> 1, lru_shrink_max); -} - -int osc_lru_reclaim(struct client_obd *cli) +long osc_lru_reclaim(struct client_obd *cli) { struct cl_env_nest nest; struct lu_env *env; struct cl_client_cache *cache = cli->cl_cache; int max_scans; - int rc = 0; + long rc = 0; LASSERT(cache); @@ -686,15 +681,15 @@ int osc_lru_reclaim(struct client_obd *cli) if (rc == -EBUSY) rc = 0; - CDEBUG(D_CACHE, "%s: Free %d pages from own LRU: %p.\n", + CDEBUG(D_CACHE, "%s: Free %ld pages from own LRU: %p.\n", cli->cl_import->imp_obd->obd_name, rc, cli); goto out; } - CDEBUG(D_CACHE, "%s: cli %p no free slots, pages: %d, busy: %d.\n", + CDEBUG(D_CACHE, "%s: cli %p no free slots, pages: %ld, busy: %ld.\n", cli->cl_import->imp_obd->obd_name, cli, - atomic_read(&cli->cl_lru_in_list), - atomic_read(&cli->cl_lru_busy)); + atomic_long_read(&cli->cl_lru_in_list), + atomic_long_read(&cli->cl_lru_busy)); /* Reclaim LRU slots from other client_obd as it can't free enough * from its own. This should rarely happen. @@ -710,10 +705,10 @@ int osc_lru_reclaim(struct client_obd *cli) cli = list_entry(cache->ccc_lru.next, struct client_obd, cl_lru_osc); - CDEBUG(D_CACHE, "%s: cli %p LRU pages: %d, busy: %d.\n", + CDEBUG(D_CACHE, "%s: cli %p LRU pages: %ld, busy: %ld.\n", cli->cl_import->imp_obd->obd_name, cli, - atomic_read(&cli->cl_lru_in_list), - atomic_read(&cli->cl_lru_busy)); + atomic_long_read(&cli->cl_lru_in_list), + atomic_long_read(&cli->cl_lru_busy)); list_move_tail(&cli->cl_lru_osc, &cache->ccc_lru); if (osc_cache_too_much(cli) > 0) { @@ -730,7 +725,7 @@ int osc_lru_reclaim(struct client_obd *cli) out: cl_env_nested_put(&nest, env); - CDEBUG(D_CACHE, "%s: cli %p freed %d pages.\n", + CDEBUG(D_CACHE, "%s: cli %p freed %ld pages.\n", cli->cl_import->imp_obd->obd_name, cli, rc); return rc; } @@ -758,8 +753,8 @@ static int osc_lru_reserve(const struct lu_env *env, struct osc_object *obj, goto out; } - LASSERT(atomic_read(cli->cl_lru_left) >= 0); - while (!atomic_add_unless(cli->cl_lru_left, -1, 0)) { + LASSERT(atomic_long_read(cli->cl_lru_left) >= 0); + while (!atomic_long_add_unless(cli->cl_lru_left, -1, 0)) { /* run out of LRU spaces, try to drop some by itself */ rc = osc_lru_reclaim(cli); if (rc < 0) @@ -770,7 +765,7 @@ static int osc_lru_reserve(const struct lu_env *env, struct osc_object *obj, cond_resched(); rc = l_wait_event(osc_lru_waitq, - atomic_read(cli->cl_lru_left) > 0, + atomic_long_read(cli->cl_lru_left) > 0, &lwi); if (rc < 0) @@ -779,7 +774,7 @@ static int osc_lru_reserve(const struct lu_env *env, struct osc_object *obj, out: if (rc >= 0) { - atomic_inc(&cli->cl_lru_busy); + atomic_long_inc(&cli->cl_lru_busy); opg->ops_in_lru = 1; rc = 0; } @@ -847,16 +842,17 @@ void osc_dec_unstable_pages(struct ptlrpc_request *req) struct client_obd *cli = &req->rq_import->imp_obd->u.cli; struct ptlrpc_bulk_desc *desc = req->rq_bulk; int page_count = desc->bd_iov_count; - int unstable_count; + long unstable_count; LASSERT(page_count >= 0); dec_unstable_page_accounting(desc); - unstable_count = atomic_sub_return(page_count, &cli->cl_unstable_count); + unstable_count = atomic_long_sub_return(page_count, + &cli->cl_unstable_count); LASSERT(unstable_count >= 0); - unstable_count = atomic_sub_return(page_count, - &cli->cl_cache->ccc_unstable_nr); + unstable_count = atomic_long_sub_return(page_count, + &cli->cl_cache->ccc_unstable_nr); LASSERT(unstable_count >= 0); if (!unstable_count) wake_up_all(&cli->cl_cache->ccc_unstable_waitq); @@ -872,15 +868,15 @@ void osc_inc_unstable_pages(struct ptlrpc_request *req) { struct client_obd *cli = &req->rq_import->imp_obd->u.cli; struct ptlrpc_bulk_desc *desc = req->rq_bulk; - int page_count = desc->bd_iov_count; + long page_count = desc->bd_iov_count; /* No unstable page tracking */ if (!cli->cl_cache || !cli->cl_cache->ccc_unstable_check) return; add_unstable_page_accounting(desc); - atomic_add(page_count, &cli->cl_unstable_count); - atomic_add(page_count, &cli->cl_cache->ccc_unstable_nr); + atomic_long_add(page_count, &cli->cl_unstable_count); + atomic_long_add(page_count, &cli->cl_cache->ccc_unstable_nr); /* * If the request has already been committed (i.e. brw_commit @@ -912,8 +908,8 @@ bool osc_over_unstable_soft_limit(struct client_obd *cli) if (!cli->cl_cache || !cli->cl_cache->ccc_unstable_check) return false; - osc_unstable_count = atomic_read(&cli->cl_unstable_count); - unstable_nr = atomic_read(&cli->cl_cache->ccc_unstable_nr); + osc_unstable_count = atomic_long_read(&cli->cl_unstable_count); + unstable_nr = atomic_long_read(&cli->cl_cache->ccc_unstable_nr); CDEBUG(D_CACHE, "%s: cli: %p unstable pages: %lu, osc unstable pages: %lu\n", diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 40a7ceb..e965faf 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -804,17 +804,17 @@ static void osc_announce_cached(struct client_obd *cli, struct obdo *oa, cli->cl_dirty_pages, cli->cl_dirty_transit, cli->cl_dirty_max_pages); oa->o_undirty = 0; - } else if (unlikely(atomic_read(&obd_dirty_pages) - - atomic_read(&obd_dirty_transit_pages) > - (long)(obd_max_dirty_pages + 1))) { + } else if (unlikely(atomic_long_read(&obd_dirty_pages) - + atomic_long_read(&obd_dirty_transit_pages) > + (obd_max_dirty_pages + 1))) { /* The atomic_read() allowing the atomic_inc() are * not covered by a lock thus they may safely race and trip * this CERROR() unless we add in a small fudge factor (+1). */ - CERROR("%s: dirty %d + %d > system dirty_max %d\n", + CERROR("%s: dirty %ld + %ld > system dirty_max %lu\n", cli->cl_import->imp_obd->obd_name, - atomic_read(&obd_dirty_pages), - atomic_read(&obd_dirty_transit_pages), + atomic_long_read(&obd_dirty_pages), + atomic_long_read(&obd_dirty_transit_pages), obd_max_dirty_pages); oa->o_undirty = 0; } else if (unlikely(cli->cl_dirty_max_pages - cli->cl_dirty_pages > @@ -2920,11 +2920,11 @@ static int osc_set_info_async(const struct lu_env *env, struct obd_export *exp, if (KEY_IS(KEY_CACHE_LRU_SHRINK)) { struct client_obd *cli = &obd->u.cli; - int nr = atomic_read(&cli->cl_lru_in_list) >> 1; - int target = *(int *)val; + long nr = atomic_long_read(&cli->cl_lru_in_list) >> 1; + long target = *(long *)val; nr = osc_lru_shrink(env, cli, min(nr, target), true); - *(int *)val -= nr; + *(long *)val -= nr; return 0; } -- cgit v0.10.2 From 4660dd9bbf39d355c8988081964ee346e53a43c9 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin <dmitry.eremin@intel.com> Date: Sun, 18 Sep 2016 16:37:44 -0400 Subject: staging: lustre: lmv: remove dead code The member lmv_obd->server_timeout and function lmv_set_timeouts() are not used. Signed-off-by: Dmitry Eremin <dmitry.eremin@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-991 Reviewed-on: http://review.whamcloud.com/11880 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 3fbb873..b84600a 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -433,7 +433,6 @@ struct lmv_obd { int max_def_easize; int max_cookiesize; int max_def_cookiesize; - int server_timeout; u32 tgts_size; /* size of tgts array */ struct lmv_tgt_desc **tgts; diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 8d9e3b8..4714853 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -302,30 +302,6 @@ static int lmv_connect(const struct lu_env *env, return rc; } -static void lmv_set_timeouts(struct obd_device *obd) -{ - struct lmv_obd *lmv; - u32 i; - - lmv = &obd->u.lmv; - if (lmv->server_timeout == 0) - return; - - if (lmv->connected == 0) - return; - - for (i = 0; i < lmv->desc.ld_tgt_count; i++) { - struct lmv_tgt_desc *tgt = lmv->tgts[i]; - - tgt = lmv->tgts[i]; - if (!tgt || !tgt->ltd_exp || !tgt->ltd_active) - continue; - - obd_set_info_async(NULL, tgt->ltd_exp, sizeof(KEY_INTERMDS), - KEY_INTERMDS, 0, NULL, NULL); - } -} - static int lmv_init_ea_size(struct obd_export *exp, int easize, int def_easize, int cookiesize, int def_cookiesize) { @@ -616,7 +592,6 @@ int lmv_check_connect(struct obd_device *obd) goto out_disc; } - lmv_set_timeouts(obd); class_export_put(lmv->exp); lmv->connected = 1; easize = lmv_mds_md_size(lmv->desc.ld_tgt_count, LMV_MAGIC); -- cgit v0.10.2 From b2e7bbb37a5c6314523e8034b9aca43f565de8e0 Mon Sep 17 00:00:00 2001 From: Stephen Champion <schamp@sgi.com> Date: Sun, 18 Sep 2016 16:37:45 -0400 Subject: staging: lustre: llite: handle concurrent use of cob_transient_pages With the lockless __generic_file_aio_write introduced in LU-1669, ll_direct_IO_26 is no longer protected by the inode i_isem. This renders obsoltete checks that all transient pages have been handled before and after entry, and requires atomic access to their counter. Signed-off-by: Stephen Champion <schamp@sgi.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5700 Reviewed-on: http://review.whamcloud.com/12179 Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Bobi Jam <bobijam@gmail.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c index 6df89b0..f35eb2e 100644 --- a/drivers/staging/lustre/lustre/llite/rw26.c +++ b/drivers/staging/lustre/lustre/llite/rw26.c @@ -345,7 +345,6 @@ static ssize_t ll_direct_IO_26(struct kiocb *iocb, struct iov_iter *iter) struct cl_io *io; struct file *file = iocb->ki_filp; struct inode *inode = file->f_mapping->host; - struct vvp_object *obj = cl_inode2vvp(inode); loff_t file_offset = iocb->ki_pos; ssize_t count = iov_iter_count(iter); ssize_t tot_bytes = 0, result = 0; @@ -374,7 +373,6 @@ static ssize_t ll_direct_IO_26(struct kiocb *iocb, struct iov_iter *iter) io = vvp_env_io(env)->vui_cl.cis_io; LASSERT(io); - LASSERT(obj->vob_transient_pages == 0); while (iov_iter_count(iter)) { struct page **pages; size_t offs; @@ -422,8 +420,6 @@ static ssize_t ll_direct_IO_26(struct kiocb *iocb, struct iov_iter *iter) file_offset += result; } out: - LASSERT(obj->vob_transient_pages == 0); - if (tot_bytes > 0) { struct vvp_io *vio = vvp_env_io(env); diff --git a/drivers/staging/lustre/lustre/llite/vvp_internal.h b/drivers/staging/lustre/lustre/llite/vvp_internal.h index 99437b8..5802da8 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_internal.h +++ b/drivers/staging/lustre/lustre/llite/vvp_internal.h @@ -217,11 +217,12 @@ struct vvp_object { struct list_head vob_pending_list; /** - * Access this counter is protected by inode->i_sem. Now that - * the lifetime of transient pages must be covered by inode sem, - * we don't need to hold any lock.. + * Number of transient pages. This is no longer protected by i_sem, + * and needs to be atomic. This is not actually used for anything, + * and can probably be removed. */ - int vob_transient_pages; + atomic_t vob_transient_pages; + /** * Number of outstanding mmaps on this file. * diff --git a/drivers/staging/lustre/lustre/llite/vvp_object.c b/drivers/staging/lustre/lustre/llite/vvp_object.c index 01725fb..6b6a63d 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_object.c +++ b/drivers/staging/lustre/lustre/llite/vvp_object.c @@ -67,8 +67,8 @@ static int vvp_object_print(const struct lu_env *env, void *cookie, (*p)(env, cookie, "(%s %d %d) inode: %p ", list_empty(&obj->vob_pending_list) ? "-" : "+", - obj->vob_transient_pages, atomic_read(&obj->vob_mmap_cnt), - inode); + atomic_read(&obj->vob_transient_pages), + atomic_read(&obj->vob_mmap_cnt), inode); if (inode) { lli = ll_i2info(inode); (*p)(env, cookie, "%lu/%u %o %u %d %p "DFID, @@ -220,7 +220,7 @@ static int vvp_object_init0(const struct lu_env *env, const struct cl_object_conf *conf) { vob->vob_inode = conf->coc_inode; - vob->vob_transient_pages = 0; + atomic_set(&vob->vob_transient_pages, 0); cl_object_page_init(&vob->vob_cl, sizeof(struct vvp_page)); return 0; } diff --git a/drivers/staging/lustre/lustre/llite/vvp_page.c b/drivers/staging/lustre/lustre/llite/vvp_page.c index e763e7f..5d79efc 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_page.c +++ b/drivers/staging/lustre/lustre/llite/vvp_page.c @@ -506,7 +506,7 @@ static void vvp_transient_page_fini(const struct lu_env *env, struct vvp_object *clobj = cl2vvp(clp->cp_obj); vvp_page_fini_common(vpg); - clobj->vob_transient_pages--; + atomic_dec(&clobj->vob_transient_pages); } static const struct cl_page_operations vvp_transient_page_ops = { @@ -555,7 +555,7 @@ int vvp_page_init(const struct lu_env *env, struct cl_object *obj, cl_page_slice_add(page, &vpg->vpg_cl, obj, index, &vvp_transient_page_ops); - clobj->vob_transient_pages++; + atomic_inc(&clobj->vob_transient_pages); } return 0; } -- cgit v0.10.2 From aaf06e29b300fc76c9ff42f4508801493e002ea4 Mon Sep 17 00:00:00 2001 From: Li Xi <lixi@ddn.com> Date: Sun, 18 Sep 2016 16:37:46 -0400 Subject: staging: lustre: llite: enforce pool name length limit The pool related codes have some inconsistency about the length of pool name. Creating and setting a pool name of length 16 to a directory will succeed. However, creating a file under that directory will fail. This patch disables any pool name which is longer or equal to 16. And it changes LOV_MAXPOOLNAME from 16 to 15 which might cause some invalid LLOG records of OST pools with 16 byte names. It is not a problem since invalid LLOG records are just ignored. And OST pools with 16 byte names won't work well anyway on the old versions. There will be problem of inconsistency if part of the servers have this patch and part of the servers don't. But it would be safe to assume that this is not a normal configuration. Signed-off-by: Li Xi <lixi@ddn.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5054 Reviewed-on: http://review.whamcloud.com/10306 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Fan Yong <fan.yong@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 6ff6615..56b5129 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -1620,7 +1620,7 @@ struct lov_mds_md_v3 { /* LOV EA mds/wire data (little-endian) */ /* lmm_stripe_count used to be __u32 */ __u16 lmm_stripe_count; /* num stripes in use for this object */ __u16 lmm_layout_gen; /* layout generation number */ - char lmm_pool_name[LOV_MAXPOOLNAME]; /* must be 32bit aligned */ + char lmm_pool_name[LOV_MAXPOOLNAME + 1]; /* must be 32bit aligned */ struct lov_ost_data_v1 lmm_objects[0]; /* per-stripe data */ }; @@ -2498,7 +2498,7 @@ struct lmv_mds_md_v1 { __u32 lmv_padding1; __u64 lmv_padding2; __u64 lmv_padding3; - char lmv_pool_name[LOV_MAXPOOLNAME]; /* pool name */ + char lmv_pool_name[LOV_MAXPOOLNAME + 1];/* pool name */ struct lu_fid lmv_stripe_fids[0]; /* FIDs for each stripe */ }; diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index 5e907af..79cd876 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -295,8 +295,8 @@ enum ll_lease_type { #define LOV_PATTERN_F_HOLE 0x40000000 /* there is hole in LOV EA */ #define LOV_PATTERN_F_RELEASED 0x80000000 /* HSM released file */ -#define LOV_MAXPOOLNAME 16 -#define LOV_POOLNAMEF "%.16s" +#define LOV_MAXPOOLNAME 15 +#define LOV_POOLNAMEF "%.15s" #define LOV_MIN_STRIPE_BITS 16 /* maximum PAGE_SIZE (ia64), power of 2 */ #define LOV_MIN_STRIPE_SIZE (1 << LOV_MIN_STRIPE_BITS) @@ -354,7 +354,7 @@ struct lov_user_md_v3 { /* LOV EA user data (host-endian) */ * used when reading */ }; - char lmm_pool_name[LOV_MAXPOOLNAME]; /* pool name */ + char lmm_pool_name[LOV_MAXPOOLNAME + 1]; /* pool name */ struct lov_user_ost_data_v1 lmm_objects[0]; /* per-stripe data */ } __packed; @@ -414,7 +414,7 @@ struct lmv_user_md_v1 { __u32 lum_padding1; __u32 lum_padding2; __u32 lum_padding3; - char lum_pool_name[LOV_MAXPOOLNAME]; + char lum_pool_name[LOV_MAXPOOLNAME + 1]; struct lmv_user_mds_data lum_objects[0]; } __packed; diff --git a/drivers/staging/lustre/lustre/include/lustre_lmv.h b/drivers/staging/lustre/lustre/include/lustre_lmv.h index 5a2fc30..388161e 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lmv.h +++ b/drivers/staging/lustre/lustre/include/lustre_lmv.h @@ -48,7 +48,7 @@ struct lmv_stripe_md { __u32 lsm_md_layout_version; __u32 lsm_md_default_count; __u32 lsm_md_default_index; - char lsm_md_pool_name[LOV_MAXPOOLNAME]; + char lsm_md_pool_name[LOV_MAXPOOLNAME + 1]; struct lmv_oinfo lsm_md_oinfo[0]; }; diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index b84600a..1c884c0 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -99,7 +99,7 @@ struct lov_stripe_md { __u32 lw_pattern; /* striping pattern (RAID0, RAID1) */ __u16 lw_stripe_count; /* number of objects being striped over */ __u16 lw_layout_gen; /* generation of the layout */ - char lw_pool_name[LOV_MAXPOOLNAME]; /* pool name */ + char lw_pool_name[LOV_MAXPOOLNAME + 1]; /* pool name */ } lsm_wire; struct lov_oinfo *lsm_oinfo[0]; diff --git a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c index 2390255..b33fd7b 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c +++ b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c @@ -1383,7 +1383,7 @@ void lustre_assert_wire_constants(void) (long long)(int)offsetof(struct lov_mds_md_v3, lmm_layout_gen)); LASSERTF((int)sizeof(((struct lov_mds_md_v3 *)0)->lmm_layout_gen) == 2, "found %lld\n", (long long)(int)sizeof(((struct lov_mds_md_v3 *)0)->lmm_layout_gen)); - CLASSERT(LOV_MAXPOOLNAME == 16); + CLASSERT(LOV_MAXPOOLNAME == 15); LASSERTF((int)offsetof(struct lov_mds_md_v3, lmm_pool_name[16]) == 48, "found %lld\n", (long long)(int)offsetof(struct lov_mds_md_v3, lmm_pool_name[16])); LASSERTF((int)sizeof(((struct lov_mds_md_v3 *)0)->lmm_pool_name[16]) == 1, "found %lld\n", -- cgit v0.10.2 From c9fe1f7f42934be528a22cb5e2dc3be55ab425c1 Mon Sep 17 00:00:00 2001 From: Henri Doreau <henri.doreau@cea.fr> Date: Sun, 18 Sep 2016 16:37:47 -0400 Subject: staging: lustre: Flexible changelog format. Added jobid fields to Changelog records (and extended records). The CLF_JOBID flags allows to check if the field is present or not (old format) when reading an entry. Jobids are expressed as 32 chars long, zero-terminated strings. Updated test_205 in sanity.sh. Signed-off-by: Henri Doreau <henri.doreau@cea.fr> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-1996 Reviewed-on: http://review.whamcloud.com/4060 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Aurelien Degremont <aurelien.degremont@cea.fr> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index 5039643..5af1153 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -1899,7 +1899,7 @@ struct cl_req_attr { /** Generic attributes for the server consumption. */ struct obdo *cra_oa; /** Jobid */ - char cra_jobid[JOBSTATS_JOBID_SIZE]; + char cra_jobid[LUSTRE_JOBID_SIZE]; }; /** diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 56b5129..2dc550a 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -1101,7 +1101,7 @@ struct lustre_msg_v2 { /* without gss, ptlrpc_body is put at the first buffer. */ #define PTLRPC_NUM_VERSIONS 4 -#define JOBSTATS_JOBID_SIZE 32 /* 32 bytes string */ + struct ptlrpc_body_v3 { struct lustre_handle pb_handle; __u32 pb_type; @@ -1123,7 +1123,7 @@ struct ptlrpc_body_v3 { __u64 pb_pre_versions[PTLRPC_NUM_VERSIONS]; /* padding for future needs */ __u64 pb_padding[4]; - char pb_jobid[JOBSTATS_JOBID_SIZE]; + char pb_jobid[LUSTRE_JOBID_SIZE]; }; #define ptlrpc_body ptlrpc_body_v3 @@ -3088,15 +3088,9 @@ struct changelog_setinfo { /** changelog record */ struct llog_changelog_rec { - struct llog_rec_hdr cr_hdr; - struct changelog_rec cr; - struct llog_rec_tail cr_tail; /**< for_sizezof_only */ -} __packed; - -struct llog_changelog_ext_rec { - struct llog_rec_hdr cr_hdr; - struct changelog_ext_rec cr; - struct llog_rec_tail cr_tail; /**< for_sizezof_only */ + struct llog_rec_hdr cr_hdr; + struct changelog_rec cr; /**< Variable length field */ + struct llog_rec_tail cr_do_not_use; /**< for_sizezof_only */ } __packed; struct llog_changelog_user_rec { @@ -3181,6 +3175,9 @@ enum llog_flag { LLOG_F_ZAP_WHEN_EMPTY = 0x1, LLOG_F_IS_CAT = 0x2, LLOG_F_IS_PLAIN = 0x4, + LLOG_F_EXT_JOBID = BIT(3), + + LLOG_F_EXT_MASK = LLOG_F_EXT_JOBID, }; struct llog_log_hdr { diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index 79cd876..cc0a786 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -673,11 +673,16 @@ static inline const char *changelog_type2str(int type) } /* per-record flags */ -#define CLF_VERSION 0x1000 -#define CLF_EXT_VERSION 0x2000 #define CLF_FLAGSHIFT 12 #define CLF_FLAGMASK ((1U << CLF_FLAGSHIFT) - 1) #define CLF_VERMASK (~CLF_FLAGMASK) +enum changelog_rec_flags { + CLF_VERSION = 0x1000, + CLF_RENAME = 0x2000, + CLF_JOBID = 0x4000, + CLF_SUPPORTED = CLF_VERSION | CLF_RENAME | CLF_JOBID +}; + /* Anything under the flagmask may be per-type (if desired) */ /* Flags for unlink */ #define CLF_UNLINK_LAST 0x0001 /* Unlink of last hardlink */ @@ -761,12 +766,35 @@ static inline void hsm_set_cl_error(int *flags, int error) *flags |= (error << CLF_HSM_ERR_L); } -#define CR_MAXSIZE cfs_size_round(2 * NAME_MAX + 1 + \ - sizeof(struct changelog_ext_rec)) +enum changelog_send_flag { + /* Not yet implemented */ + CHANGELOG_FLAG_FOLLOW = BIT(0), + /* + * Blocking IO makes sense in case of slow user parsing of the records, + * but it also prevents us from cleaning up if the records are not + * consumed. + */ + CHANGELOG_FLAG_BLOCK = BIT(1), + /* Pack jobid into the changelog records if available. */ + CHANGELOG_FLAG_JOBID = BIT(2), +}; + +#define CR_MAXSIZE cfs_size_round(2 * NAME_MAX + 2 + \ + changelog_rec_offset(CLF_SUPPORTED)) + +/* 31 usable bytes string + null terminator. */ +#define LUSTRE_JOBID_SIZE 32 +/* + * This is the minimal changelog record. It can contain extensions + * such as rename fields or process jobid. Its exact content is described + * by the cr_flags. + * + * Extensions are packed in the same order as their corresponding flags. + */ struct changelog_rec { __u16 cr_namelen; - __u16 cr_flags; /**< (flags&CLF_FLAGMASK)|CLF_VERSION */ + __u16 cr_flags; /**< \a changelog_rec_flags */ __u32 cr_type; /**< \a changelog_rec_type */ __u64 cr_index; /**< changelog record number */ __u64 cr_prev; /**< last index for this target fid */ @@ -776,55 +804,116 @@ struct changelog_rec { __u32 cr_markerflags; /**< CL_MARK flags */ }; struct lu_fid cr_pfid; /**< parent fid */ - char cr_name[0]; /**< last element */ } __packed; -/* changelog_ext_rec is 2*sizeof(lu_fid) bigger than changelog_rec, to save - * space, only rename uses changelog_ext_rec, while others use changelog_rec to - * store records. - */ -struct changelog_ext_rec { - __u16 cr_namelen; - __u16 cr_flags; /**< (flags & CLF_FLAGMASK) | - * CLF_EXT_VERSION - */ - __u32 cr_type; /**< \a changelog_rec_type */ - __u64 cr_index; /**< changelog record number */ - __u64 cr_prev; /**< last index for this target fid */ - __u64 cr_time; - union { - struct lu_fid cr_tfid; /**< target fid */ - __u32 cr_markerflags; /**< CL_MARK flags */ - }; - struct lu_fid cr_pfid; /**< target parent fid */ - struct lu_fid cr_sfid; /**< source fid, or zero */ - struct lu_fid cr_spfid; /**< source parent fid, or zero */ - char cr_name[0]; /**< last element */ -} __packed; +/* Changelog extension for RENAME. */ +struct changelog_ext_rename { + struct lu_fid cr_sfid; /**< source fid, or zero */ + struct lu_fid cr_spfid; /**< source parent fid, or zero */ +}; + +/* Changelog extension to include JOBID. */ +struct changelog_ext_jobid { + char cr_jobid[LUSTRE_JOBID_SIZE]; /**< zero-terminated string. */ +}; + +static inline unsigned int changelog_rec_offset(enum changelog_rec_flags crf) +{ + unsigned int size = sizeof(struct changelog_rec); + + if (crf & CLF_RENAME) + size += sizeof(struct changelog_ext_rename); + + if (crf & CLF_JOBID) + size += sizeof(struct changelog_ext_jobid); -#define CHANGELOG_REC_EXTENDED(rec) \ - (((rec)->cr_flags & CLF_VERMASK) == CLF_EXT_VERSION) + return size; +} static inline int changelog_rec_size(struct changelog_rec *rec) { - return CHANGELOG_REC_EXTENDED(rec) ? sizeof(struct changelog_ext_rec) : - sizeof(*rec); + return changelog_rec_offset(rec->cr_flags); +} + +static inline unsigned int changelog_rec_varsize(struct changelog_rec *rec) +{ + return changelog_rec_size(rec) - sizeof(*rec) + rec->cr_namelen; +} + +static inline +struct changelog_ext_rename *changelog_rec_rename(struct changelog_rec *rec) +{ + enum changelog_rec_flags crf = rec->cr_flags & CLF_VERSION; + + return (struct changelog_ext_rename *)((char *)rec + + changelog_rec_offset(crf)); +} + +/* The jobid follows the rename extension, if present */ +static inline +struct changelog_ext_jobid *changelog_rec_jobid(struct changelog_rec *rec) +{ + enum changelog_rec_flags crf = rec->cr_flags & + (CLF_VERSION | CLF_RENAME); + + return (struct changelog_ext_jobid *)((char *)rec + + changelog_rec_offset(crf)); } +/* The name follows the rename and jobid extensions, if present */ static inline char *changelog_rec_name(struct changelog_rec *rec) { - return CHANGELOG_REC_EXTENDED(rec) ? - ((struct changelog_ext_rec *)rec)->cr_name : rec->cr_name; + return (char *)rec + changelog_rec_offset(rec->cr_flags & + CLF_SUPPORTED); +} + +static inline int changelog_rec_snamelen(struct changelog_rec *rec) +{ + return rec->cr_namelen - strlen(changelog_rec_name(rec)) - 1; } -static inline int changelog_rec_snamelen(struct changelog_ext_rec *rec) +static inline char *changelog_rec_sname(struct changelog_rec *rec) { - return rec->cr_namelen - strlen(rec->cr_name) - 1; + char *cr_name = changelog_rec_name(rec); + + return cr_name + strlen(cr_name) + 1; } -static inline char *changelog_rec_sname(struct changelog_ext_rec *rec) +/* + * Remap a record to the desired format as specified by the crf flags. + * The record must be big enough to contain the final remapped version. + */ +static inline void changelog_remap_rec(struct changelog_rec *rec, + enum changelog_rec_flags crf) { - return rec->cr_name + strlen(rec->cr_name) + 1; + size_t var_size; + char *var_part; + + crf &= CLF_SUPPORTED; + + if ((rec->cr_flags & CLF_SUPPORTED) == crf) + return; + + if ((crf & CLF_JOBID) && rec->cr_flags & CLF_JOBID) { + var_part = (char *)changelog_rec_jobid(rec); + var_size = rec->cr_namelen + sizeof(struct changelog_ext_jobid); + } else { + var_part = changelog_rec_name(rec); + var_size = rec->cr_namelen; + } + + memmove((char *)rec + changelog_rec_offset(crf & ~CLF_JOBID), var_part, + var_size); + + if ((crf & CLF_RENAME) && !(rec->cr_flags & CLF_RENAME)) + memset(changelog_rec_rename(rec), 0, + sizeof(struct changelog_ext_rename)); + + if ((crf & CLF_JOBID) && !(rec->cr_flags & CLF_JOBID)) + memset(changelog_rec_jobid(rec), 0, + sizeof(struct changelog_ext_jobid)); + + rec->cr_flags = (rec->cr_flags & CLF_FLAGMASK) | crf; } struct ioc_changelog { diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index f972ba3..fc707c2 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -232,7 +232,7 @@ struct ll_inode_info { * so the read/write statistics for jobid will not be * accurate if the file is shared by different jobs. */ - char f_jobid[JOBSTATS_JOBID_SIZE]; + char f_jobid[LUSTRE_JOBID_SIZE]; } f; #define lli_size_mutex u.f.f_size_mutex diff --git a/drivers/staging/lustre/lustre/llite/vvp_req.c b/drivers/staging/lustre/lustre/llite/vvp_req.c index a6e2672..e3f4c79 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_req.c +++ b/drivers/staging/lustre/lustre/llite/vvp_req.c @@ -85,7 +85,7 @@ static void vvp_req_attr_set(const struct lu_env *env, if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_INVALID_PFID)) oa->o_parent_oid++; memcpy(attr->cra_jobid, ll_i2info(inode)->lli_jobid, - JOBSTATS_JOBID_SIZE); + LUSTRE_JOBID_SIZE); } static void vvp_req_completion(const struct lu_env *env, diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index a77bc17..157fdc0 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -1859,12 +1859,17 @@ static struct kuc_hdr *changelog_kuc_hdr(char *buf, int len, int flags) struct changelog_show { __u64 cs_startrec; - __u32 cs_flags; + enum changelog_send_flag cs_flags; struct file *cs_fp; char *cs_buf; struct obd_device *cs_obd; }; +static inline char *cs_obd_name(struct changelog_show *cs) +{ + return cs->cs_obd->obd_name; +} + static int changelog_kkuc_cb(const struct lu_env *env, struct llog_handle *llh, struct llog_rec_hdr *hdr, void *data) { @@ -1876,7 +1881,7 @@ static int changelog_kkuc_cb(const struct lu_env *env, struct llog_handle *llh, if (rec->cr_hdr.lrh_type != CHANGELOG_REC) { rc = -EINVAL; CERROR("%s: not a changelog rec %x/%d: rc = %d\n", - cs->cs_obd->obd_name, rec->cr_hdr.lrh_type, + cs_obd_name(cs), rec->cr_hdr.lrh_type, rec->cr.cr_type, rc); return rc; } @@ -1909,6 +1914,7 @@ static int changelog_kkuc_cb(const struct lu_env *env, struct llog_handle *llh, static int mdc_changelog_send_thread(void *csdata) { + enum llog_flag flags = LLOG_F_IS_CAT; struct changelog_show *cs = csdata; struct llog_ctxt *ctxt = NULL; struct llog_handle *llh = NULL; @@ -1934,10 +1940,14 @@ static int mdc_changelog_send_thread(void *csdata) LLOG_OPEN_EXISTS); if (rc) { CERROR("%s: fail to open changelog catalog: rc = %d\n", - cs->cs_obd->obd_name, rc); + cs_obd_name(cs), rc); goto out; } - rc = llog_init_handle(NULL, llh, LLOG_F_IS_CAT, NULL); + + if (cs->cs_flags & CHANGELOG_FLAG_JOBID) + flags |= LLOG_F_EXT_JOBID; + + rc = llog_init_handle(NULL, llh, flags, NULL); if (rc) { CERROR("llog_init_handle failed %d\n", rc); goto out; @@ -1990,12 +2000,12 @@ static int mdc_ioc_changelog_send(struct obd_device *obd, if (IS_ERR(task)) { rc = PTR_ERR(task); CERROR("%s: can't start changelog thread: rc = %d\n", - obd->obd_name, rc); + cs_obd_name(cs), rc); kfree(cs); } else { rc = 0; CDEBUG(D_HSM, "%s: started changelog thread\n", - obd->obd_name); + cs_obd_name(cs)); } CERROR("Failed to start changelog thread: %d\n", rc); diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c index 629d8b5..4c30d6bc 100644 --- a/drivers/staging/lustre/lustre/obdclass/class_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c @@ -81,7 +81,7 @@ EXPORT_SYMBOL(obd_dirty_transit_pages); char obd_jobid_var[JOBSTATS_JOBID_VAR_MAX_LEN + 1] = JOBSTATS_DISABLE; EXPORT_SYMBOL(obd_jobid_var); -char obd_jobid_node[JOBSTATS_JOBID_SIZE + 1]; +char obd_jobid_node[LUSTRE_JOBID_SIZE + 1]; /* Get jobid of current process from stored variable or calculate * it from pid and user_id. @@ -92,14 +92,14 @@ char obd_jobid_node[JOBSTATS_JOBID_SIZE + 1]; */ int lustre_get_jobid(char *jobid) { - memset(jobid, 0, JOBSTATS_JOBID_SIZE); + memset(jobid, 0, LUSTRE_JOBID_SIZE); /* Jobstats isn't enabled */ if (strcmp(obd_jobid_var, JOBSTATS_DISABLE) == 0) return 0; /* Use process name + fsuid as jobid */ if (strcmp(obd_jobid_var, JOBSTATS_PROCNAME_UID) == 0) { - snprintf(jobid, JOBSTATS_JOBID_SIZE, "%s.%u", + snprintf(jobid, LUSTRE_JOBID_SIZE, "%s.%u", current_comm(), from_kuid(&init_user_ns, current_fsuid())); return 0; diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c index 2b691d8..ae172c4 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c @@ -292,7 +292,7 @@ static ssize_t jobid_name_store(struct kobject *kobj, struct attribute *attr, const char *buffer, size_t count) { - if (!count || count > JOBSTATS_JOBID_SIZE) + if (!count || count > LUSTRE_JOBID_SIZE) return -EINVAL; memcpy(obd_jobid_node, buffer, count); diff --git a/drivers/staging/lustre/lustre/obdclass/llog.c b/drivers/staging/lustre/lustre/obdclass/llog.c index 8f06141..119372c 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog.c +++ b/drivers/staging/lustre/lustre/obdclass/llog.c @@ -137,6 +137,7 @@ static int llog_read_header(const struct lu_env *env, int llog_init_handle(const struct lu_env *env, struct llog_handle *handle, int flags, struct obd_uuid *uuid) { + enum llog_flag fmt = flags & LLOG_F_EXT_MASK; struct llog_log_hdr *llh; int rc; @@ -194,6 +195,7 @@ int llog_init_handle(const struct lu_env *env, struct llog_handle *handle, flags, LLOG_F_IS_CAT, LLOG_F_IS_PLAIN); rc = -EINVAL; } + llh->llh_flags |= fmt; out: if (rc) { kfree(llh); @@ -262,7 +264,7 @@ repeat: */ for (rec = (struct llog_rec_hdr *)buf; (char *)rec < buf + LLOG_CHUNK_SIZE; - rec = (struct llog_rec_hdr *)((char *)rec + rec->lrh_len)) { + rec = llog_rec_hdr_next(rec)) { CDEBUG(D_OTHER, "processing rec 0x%p type %#x\n", rec, rec->lrh_type); diff --git a/drivers/staging/lustre/lustre/obdclass/llog_cat.c b/drivers/staging/lustre/lustre/obdclass/llog_cat.c index b27f08f..ce8e2f6 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_cat.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_cat.c @@ -63,11 +63,13 @@ static int llog_cat_id2handle(const struct lu_env *env, struct llog_logid *logid) { struct llog_handle *loghandle; + enum llog_flag fmt; int rc = 0; if (!cathandle) return -EBADF; + fmt = cathandle->lgh_hdr->llh_flags & LLOG_F_EXT_MASK; down_write(&cathandle->lgh_lock); list_for_each_entry(loghandle, &cathandle->u.chd.chd_head, u.phd.phd_entry) { @@ -99,7 +101,7 @@ static int llog_cat_id2handle(const struct lu_env *env, return rc; } - rc = llog_init_handle(env, loghandle, LLOG_F_IS_PLAIN, NULL); + rc = llog_init_handle(env, loghandle, fmt | LLOG_F_IS_PLAIN, NULL); if (rc < 0) { llog_close(env, loghandle); loghandle = NULL; diff --git a/drivers/staging/lustre/lustre/obdclass/llog_internal.h b/drivers/staging/lustre/lustre/obdclass/llog_internal.h index f794952..21a93c7 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_internal.h +++ b/drivers/staging/lustre/lustre/obdclass/llog_internal.h @@ -70,4 +70,9 @@ int llog_process_or_fork(const struct lu_env *env, llog_cb_t cb, void *data, void *catdata, bool fork); int llog_cat_cleanup(const struct lu_env *env, struct llog_handle *cathandle, struct llog_handle *loghandle, int index); + +static inline struct llog_rec_hdr *llog_rec_hdr_next(struct llog_rec_hdr *rec) +{ + return (struct llog_rec_hdr *)((char *)rec + rec->lrh_len); +} #endif diff --git a/drivers/staging/lustre/lustre/obdclass/llog_swab.c b/drivers/staging/lustre/lustre/obdclass/llog_swab.c index 0ec6361..21ab90c 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_swab.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_swab.c @@ -172,20 +172,23 @@ void lustre_swab_llog_rec(struct llog_rec_hdr *rec) __swab64s(&cr->cr.cr_time); lustre_swab_lu_fid(&cr->cr.cr_tfid); lustre_swab_lu_fid(&cr->cr.cr_pfid); - if (CHANGELOG_REC_EXTENDED(&cr->cr)) { - struct llog_changelog_ext_rec *ext = - (struct llog_changelog_ext_rec *)rec; - - lustre_swab_lu_fid(&ext->cr.cr_sfid); - lustre_swab_lu_fid(&ext->cr.cr_spfid); - tail = &ext->cr_tail; - } else { - tail = &cr->cr_tail; + if (cr->cr.cr_flags & CLF_RENAME) { + struct changelog_ext_rename *rnm = + changelog_rec_rename(&cr->cr); + + lustre_swab_lu_fid(&rnm->cr_sfid); + lustre_swab_lu_fid(&rnm->cr_spfid); } - tail = (struct llog_rec_tail *)((char *)tail + + /* + * Because the tail follows a variable-length structure we need + * to compute its location at runtime + */ + tail = (struct llog_rec_tail *)((char *)&cr->cr + + changelog_rec_size(&cr->cr) + cr->cr.cr_namelen); break; } + case CHANGELOG_USER_REC: { struct llog_changelog_user_rec *cur = diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index 03fd5d7..e25596f 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -1378,7 +1378,7 @@ void lustre_msg_set_jobid(struct lustre_msg *msg, char *jobid) LASSERTF(pb, "invalid msg %p: no ptlrpc body!\n", msg); if (jobid) - memcpy(pb->pb_jobid, jobid, JOBSTATS_JOBID_SIZE); + memcpy(pb->pb_jobid, jobid, LUSTRE_JOBID_SIZE); else if (pb->pb_jobid[0] == '\0') lustre_get_jobid(pb->pb_jobid); return; diff --git a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c index b33fd7b..e5945e2 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c +++ b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c @@ -684,7 +684,7 @@ void lustre_assert_wire_constants(void) (long long)(int)offsetof(struct ptlrpc_body_v3, pb_padding)); LASSERTF((int)sizeof(((struct ptlrpc_body_v3 *)0)->pb_padding) == 32, "found %lld\n", (long long)(int)sizeof(((struct ptlrpc_body_v3 *)0)->pb_padding)); - CLASSERT(JOBSTATS_JOBID_SIZE == 32); + CLASSERT(LUSTRE_JOBID_SIZE == 32); LASSERTF((int)offsetof(struct ptlrpc_body_v3, pb_jobid) == 152, "found %lld\n", (long long)(int)offsetof(struct ptlrpc_body_v3, pb_jobid)); LASSERTF((int)sizeof(((struct ptlrpc_body_v3 *)0)->pb_jobid) == 32, "found %lld\n", @@ -3300,50 +3300,6 @@ void lustre_assert_wire_constants(void) LASSERTF((int)sizeof(((struct changelog_rec *)0)->cr_pfid) == 16, "found %lld\n", (long long)(int)sizeof(((struct changelog_rec *)0)->cr_pfid)); - /* Checks for struct changelog_ext_rec */ - LASSERTF((int)sizeof(struct changelog_ext_rec) == 96, "found %lld\n", - (long long)(int)sizeof(struct changelog_ext_rec)); - LASSERTF((int)offsetof(struct changelog_ext_rec, cr_namelen) == 0, "found %lld\n", - (long long)(int)offsetof(struct changelog_ext_rec, cr_namelen)); - LASSERTF((int)sizeof(((struct changelog_ext_rec *)0)->cr_namelen) == 2, "found %lld\n", - (long long)(int)sizeof(((struct changelog_ext_rec *)0)->cr_namelen)); - LASSERTF((int)offsetof(struct changelog_ext_rec, cr_flags) == 2, "found %lld\n", - (long long)(int)offsetof(struct changelog_ext_rec, cr_flags)); - LASSERTF((int)sizeof(((struct changelog_ext_rec *)0)->cr_flags) == 2, "found %lld\n", - (long long)(int)sizeof(((struct changelog_ext_rec *)0)->cr_flags)); - LASSERTF((int)offsetof(struct changelog_ext_rec, cr_type) == 4, "found %lld\n", - (long long)(int)offsetof(struct changelog_ext_rec, cr_type)); - LASSERTF((int)sizeof(((struct changelog_ext_rec *)0)->cr_type) == 4, "found %lld\n", - (long long)(int)sizeof(((struct changelog_ext_rec *)0)->cr_type)); - LASSERTF((int)offsetof(struct changelog_ext_rec, cr_index) == 8, "found %lld\n", - (long long)(int)offsetof(struct changelog_ext_rec, cr_index)); - LASSERTF((int)sizeof(((struct changelog_ext_rec *)0)->cr_index) == 8, "found %lld\n", - (long long)(int)sizeof(((struct changelog_ext_rec *)0)->cr_index)); - LASSERTF((int)offsetof(struct changelog_ext_rec, cr_prev) == 16, "found %lld\n", - (long long)(int)offsetof(struct changelog_ext_rec, cr_prev)); - LASSERTF((int)sizeof(((struct changelog_ext_rec *)0)->cr_prev) == 8, "found %lld\n", - (long long)(int)sizeof(((struct changelog_ext_rec *)0)->cr_prev)); - LASSERTF((int)offsetof(struct changelog_ext_rec, cr_time) == 24, "found %lld\n", - (long long)(int)offsetof(struct changelog_ext_rec, cr_time)); - LASSERTF((int)sizeof(((struct changelog_ext_rec *)0)->cr_time) == 8, "found %lld\n", - (long long)(int)sizeof(((struct changelog_ext_rec *)0)->cr_time)); - LASSERTF((int)offsetof(struct changelog_ext_rec, cr_tfid) == 32, "found %lld\n", - (long long)(int)offsetof(struct changelog_ext_rec, cr_tfid)); - LASSERTF((int)sizeof(((struct changelog_ext_rec *)0)->cr_tfid) == 16, "found %lld\n", - (long long)(int)sizeof(((struct changelog_ext_rec *)0)->cr_tfid)); - LASSERTF((int)offsetof(struct changelog_ext_rec, cr_pfid) == 48, "found %lld\n", - (long long)(int)offsetof(struct changelog_ext_rec, cr_pfid)); - LASSERTF((int)sizeof(((struct changelog_ext_rec *)0)->cr_pfid) == 16, "found %lld\n", - (long long)(int)sizeof(((struct changelog_ext_rec *)0)->cr_pfid)); - LASSERTF((int)offsetof(struct changelog_ext_rec, cr_sfid) == 64, "found %lld\n", - (long long)(int)offsetof(struct changelog_ext_rec, cr_sfid)); - LASSERTF((int)sizeof(((struct changelog_ext_rec *)0)->cr_sfid) == 16, "found %lld\n", - (long long)(int)sizeof(((struct changelog_ext_rec *)0)->cr_sfid)); - LASSERTF((int)offsetof(struct changelog_ext_rec, cr_spfid) == 80, "found %lld\n", - (long long)(int)offsetof(struct changelog_ext_rec, cr_spfid)); - LASSERTF((int)sizeof(((struct changelog_ext_rec *)0)->cr_spfid) == 16, "found %lld\n", - (long long)(int)sizeof(((struct changelog_ext_rec *)0)->cr_spfid)); - /* Checks for struct changelog_setinfo */ LASSERTF((int)sizeof(struct changelog_setinfo) == 12, "found %lld\n", (long long)(int)sizeof(struct changelog_setinfo)); @@ -3367,10 +3323,10 @@ void lustre_assert_wire_constants(void) (long long)(int)offsetof(struct llog_changelog_rec, cr)); LASSERTF((int)sizeof(((struct llog_changelog_rec *)0)->cr) == 64, "found %lld\n", (long long)(int)sizeof(((struct llog_changelog_rec *)0)->cr)); - LASSERTF((int)offsetof(struct llog_changelog_rec, cr_tail) == 80, "found %lld\n", - (long long)(int)offsetof(struct llog_changelog_rec, cr_tail)); - LASSERTF((int)sizeof(((struct llog_changelog_rec *)0)->cr_tail) == 8, "found %lld\n", - (long long)(int)sizeof(((struct llog_changelog_rec *)0)->cr_tail)); + LASSERTF((int)offsetof(struct llog_changelog_rec, cr_do_not_use) == 80, "found %lld\n", + (long long)(int)offsetof(struct llog_changelog_rec, cr_do_not_use)); + LASSERTF((int)sizeof(((struct llog_changelog_rec *)0)->cr_do_not_use) == 8, "found %lld\n", + (long long)(int)sizeof(((struct llog_changelog_rec *)0)->cr_do_not_use)); /* Checks for struct llog_changelog_user_rec */ LASSERTF((int)sizeof(struct llog_changelog_user_rec) == 40, "found %lld\n", -- cgit v0.10.2 From c5e0e23f906c8ff68ebf07542fb6d35e0f6bf33e Mon Sep 17 00:00:00 2001 From: Fan Yong <fan.yong@intel.com> Date: Sun, 18 Sep 2016 16:37:48 -0400 Subject: staging: lustre: lmv: move some inline functions to lustre_lmv.h Move some inline code out of lmv core into lustre_lmv.h. This is to prepare for use outside of the lmv layer in the future of these functions. Change from passing in struct lmv_stripe_md to just int for lmv_is_known_hash_type. Signed-off-by: Fan Yong <fan.yong@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5519 Reviewed-on: http://review.whamcloud.com/11845 Reviewed-by: Alex Zhuravlev <alexey.zhuravlev@intel.com> Reviewed-by: Lai Siyao <lai.siyao@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre_lmv.h b/drivers/staging/lustre/lustre/include/lustre_lmv.h index 388161e..d7f7afa 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lmv.h +++ b/drivers/staging/lustre/lustre/include/lustre_lmv.h @@ -118,4 +118,67 @@ static inline void lmv_le_to_cpu(union lmv_mds_md *lmv_dst, } } +/* This hash is only for testing purpose */ +static inline unsigned int +lmv_hash_all_chars(unsigned int count, const char *name, int namelen) +{ + const unsigned char *p = (const unsigned char *)name; + unsigned int c = 0; + + while (--namelen >= 0) + c += p[namelen]; + + c = c % count; + + return c; +} + +static inline unsigned int +lmv_hash_fnv1a(unsigned int count, const char *name, int namelen) +{ + __u64 hash; + + hash = lustre_hash_fnv_1a_64(name, namelen); + + return do_div(hash, count); +} + +static inline int lmv_name_to_stripe_index(__u32 lmv_hash_type, + unsigned int stripe_count, + const char *name, int namelen) +{ + __u32 hash_type = lmv_hash_type & LMV_HASH_TYPE_MASK; + int idx; + + LASSERT(namelen > 0); + if (stripe_count <= 1) + return 0; + + /* for migrating object, always start from 0 stripe */ + if (lmv_hash_type & LMV_HASH_FLAG_MIGRATION) + return 0; + + switch (hash_type) { + case LMV_HASH_TYPE_ALL_CHARS: + idx = lmv_hash_all_chars(stripe_count, name, namelen); + break; + case LMV_HASH_TYPE_FNV_1A_64: + idx = lmv_hash_fnv1a(stripe_count, name, namelen); + break; + default: + idx = -EBADFD; + break; + } + CDEBUG(D_INFO, "name %.*s hash_type %d idx %d\n", namelen, name, + hash_type, idx); + + return idx; +} + +static inline bool lmv_is_known_hash_type(__u32 type) +{ + return (type & LMV_HASH_TYPE_MASK) == LMV_HASH_TYPE_FNV_1A_64 || + (type & LMV_HASH_TYPE_MASK) == LMV_HASH_TYPE_ALL_CHARS; +} + #endif diff --git a/drivers/staging/lustre/lustre/lmv/lmv_intent.c b/drivers/staging/lustre/lustre/lmv/lmv_intent.c index 02bf3c3..6845a5e 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_intent.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_intent.c @@ -414,7 +414,7 @@ static int lmv_intent_lookup(struct obd_export *exp, * Both migrating dir and unknown hash dir need to try * all of sub-stripes */ - if (lsm && !lmv_is_known_hash_type(lsm)) { + if (lsm && !lmv_is_known_hash_type(lsm->lsm_md_hash_type)) { struct lmv_oinfo *oinfo = &lsm->lsm_md_oinfo[0]; op_data->op_fid1 = oinfo->lmo_fid; diff --git a/drivers/staging/lustre/lustre/lmv/lmv_internal.h b/drivers/staging/lustre/lustre/lmv/lmv_internal.h index 4a5e385..8f703ea 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_internal.h +++ b/drivers/staging/lustre/lustre/lmv/lmv_internal.h @@ -151,15 +151,9 @@ lsm_name_to_stripe_info(const struct lmv_stripe_md *lsm, const char *name, return &lsm->lsm_md_oinfo[stripe_index]; } -static inline bool lmv_is_known_hash_type(const struct lmv_stripe_md *lsm) -{ - return lsm->lsm_md_hash_type == LMV_HASH_TYPE_FNV_1A_64 || - lsm->lsm_md_hash_type == LMV_HASH_TYPE_ALL_CHARS; -} - static inline bool lmv_need_try_all_stripes(const struct lmv_stripe_md *lsm) { - return !lmv_is_known_hash_type(lsm) || + return !lmv_is_known_hash_type(lsm->lsm_md_hash_type) || lsm->lsm_md_hash_type & LMV_HASH_FLAG_MIGRATION; } diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 4714853..618af33 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -53,63 +53,6 @@ #include "../include/lustre_kernelcomm.h" #include "lmv_internal.h" -/* This hash is only for testing purpose */ -static inline unsigned int -lmv_hash_all_chars(unsigned int count, const char *name, int namelen) -{ - const unsigned char *p = (const unsigned char *)name; - unsigned int c = 0; - - while (--namelen >= 0) - c += p[namelen]; - - c = c % count; - - return c; -} - -static inline unsigned int -lmv_hash_fnv1a(unsigned int count, const char *name, int namelen) -{ - __u64 hash; - - hash = lustre_hash_fnv_1a_64(name, namelen); - - return do_div(hash, count); -} - -int lmv_name_to_stripe_index(__u32 lmv_hash_type, unsigned int stripe_count, - const char *name, int namelen) -{ - __u32 hash_type = lmv_hash_type & LMV_HASH_TYPE_MASK; - int idx; - - LASSERT(namelen > 0); - if (stripe_count <= 1) - return 0; - - /* for migrating object, always start from 0 stripe */ - if (lmv_hash_type & LMV_HASH_FLAG_MIGRATION) - return 0; - - switch (hash_type) { - case LMV_HASH_TYPE_ALL_CHARS: - idx = lmv_hash_all_chars(stripe_count, name, namelen); - break; - case LMV_HASH_TYPE_FNV_1A_64: - idx = lmv_hash_fnv1a(stripe_count, name, namelen); - break; - default: - idx = -EBADFD; - break; - } - - CDEBUG(D_INFO, "name %.*s hash_type %d idx %d\n", namelen, name, - hash_type, idx); - - return idx; -} - static void lmv_activate_target(struct lmv_obd *lmv, struct lmv_tgt_desc *tgt, int activate) @@ -2529,7 +2472,7 @@ retry_unlink: * inside lmv_locate_target_for_name(), so we only check * unknown hash type directory here */ - if (!lmv_is_known_hash_type(lsm)) { + if (!lmv_is_known_hash_type(lsm->lsm_md_hash_type)) { struct lmv_oinfo *oinfo; oinfo = &lsm->lsm_md_oinfo[stripe_index]; -- cgit v0.10.2 From 39ce28033e217f11a648027efdcc44a4f987f617 Mon Sep 17 00:00:00 2001 From: Vitaly Fertman <vitaly_fertman@xyratex.com> Date: Sun, 18 Sep 2016 16:37:49 -0400 Subject: staging: lustre: ldlm: per-export lock callback timeout The lock callback timeout is calculated as an average per namespace. This does not reflect individual client behavior. Instead, we should calculate it on a per-export basis. This is the client side changes for upstream client. Signed-off-by: Vitaly Fertman <vitaly_fertman@xyratex.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4942 Reviewed-by: Andriy Skulysh <Andriy_Skulysh@xyratex.com> Reviewed-by: Alexey Lyashkov <Alexey_Lyashkov@xyratex.com> Xyratex-bug-id: MRP-417 Reviewed-on: http://review.whamcloud.com/9336 Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Reviewed-by: James Simmons <uja.ornl@gmail.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h b/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h index dc0e4af..6536832 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h @@ -102,7 +102,7 @@ int ldlm_cancel_lru(struct ldlm_namespace *ns, int nr, int ldlm_cancel_lru_local(struct ldlm_namespace *ns, struct list_head *cancels, int count, int max, enum ldlm_cancel_flags cancel_flags, int flags); -extern int ldlm_enqueue_min; +extern unsigned int ldlm_enqueue_min; /* ldlm_resource.c */ int ldlm_resource_putref_locked(struct ldlm_resource *res); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c index f516106..3c48b4f 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c @@ -1541,8 +1541,6 @@ enum ldlm_error ldlm_lock_enqueue(struct ldlm_namespace *ns, struct ldlm_lock *lock = *lockp; struct ldlm_resource *res = lock->l_resource; - lock->l_last_activity = ktime_get_real_seconds(); - lock_res_and_lock(lock); if (lock->l_req_mode == lock->l_granted_mode) { /* The server returned a blocked lock, but it was granted diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index cc835cb..46842dd 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -63,8 +63,8 @@ #include "ldlm_internal.h" -int ldlm_enqueue_min = OBD_TIMEOUT_DEFAULT; -module_param(ldlm_enqueue_min, int, 0644); +unsigned int ldlm_enqueue_min = OBD_TIMEOUT_DEFAULT; +module_param(ldlm_enqueue_min, uint, 0644); MODULE_PARM_DESC(ldlm_enqueue_min, "lock enqueue timeout minimum"); /* in client side, whether the cached locks will be canceled before replay */ @@ -123,44 +123,56 @@ static int ldlm_expired_completion_wait(void *data) return 0; } +/** + * Calculate the Completion timeout (covering enqueue, BL AST, data flush, + * lock cancel, and their replies). Used for lock completion timeout on the + * client side. + * + * \param[in] lock lock which is waiting the completion callback + * + * \retval timeout in seconds to wait for the server reply + */ /* We use the same basis for both server side and client side functions * from a single node. */ -static int ldlm_get_enq_timeout(struct ldlm_lock *lock) +static unsigned int ldlm_cp_timeout(struct ldlm_lock *lock) { - int timeout = at_get(ldlm_lock_to_ns_at(lock)); + unsigned int timeout; if (AT_OFF) - return obd_timeout / 2; - /* Since these are non-updating timeouts, we should be conservative. - * It would be nice to have some kind of "early reply" mechanism for - * lock callbacks too... + return obd_timeout; + + /* + * Wait a long time for enqueue - server may have to callback a + * lock from another client. Server will evict the other client if it + * doesn't respond reasonably, and then give us the lock. */ - timeout = min_t(int, at_max, timeout + (timeout >> 1)); /* 150% */ - return max(timeout, ldlm_enqueue_min); + timeout = at_get(ldlm_lock_to_ns_at(lock)); + return max(3 * timeout, ldlm_enqueue_min); } /** * Helper function for ldlm_completion_ast(), updating timings when lock is * actually granted. */ -static int ldlm_completion_tail(struct ldlm_lock *lock) +static int ldlm_completion_tail(struct ldlm_lock *lock, void *data) { long delay; - int result; + int result = 0; if (ldlm_is_destroyed(lock) || ldlm_is_failed(lock)) { LDLM_DEBUG(lock, "client-side enqueue: destroyed"); result = -EIO; + } else if (!data) { + LDLM_DEBUG(lock, "client-side enqueue: granted"); } else { + /* Take into AT only CP RPC, not immediately granted locks */ delay = ktime_get_real_seconds() - lock->l_last_activity; LDLM_DEBUG(lock, "client-side enqueue: granted after %lds", delay); /* Update our time estimate */ - at_measured(ldlm_lock_to_ns_at(lock), - delay); - result = 0; + at_measured(ldlm_lock_to_ns_at(lock), delay); } return result; } @@ -179,7 +191,7 @@ int ldlm_completion_ast_async(struct ldlm_lock *lock, __u64 flags, void *data) if (!(flags & LDLM_FL_BLOCKED_MASK)) { wake_up(&lock->l_waitq); - return ldlm_completion_tail(lock); + return ldlm_completion_tail(lock, data); } LDLM_DEBUG(lock, "client-side enqueue returned a blocked lock, going forward"); @@ -238,13 +250,10 @@ noreproc: if (obd) imp = obd->u.cli.cl_import; - /* Wait a long time for enqueue - server may have to callback a - * lock from another client. Server will evict the other client if it - * doesn't respond reasonably, and then give us the lock. - */ - timeout = ldlm_get_enq_timeout(lock) * 2; + timeout = ldlm_cp_timeout(lock); lwd.lwd_lock = lock; + lock->l_last_activity = ktime_get_real_seconds(); if (ldlm_is_no_timeout(lock)) { LDLM_DEBUG(lock, "waiting indefinitely because of NO_TIMEOUT"); @@ -277,7 +286,7 @@ noreproc: return rc; } - return ldlm_completion_tail(lock); + return ldlm_completion_tail(lock, data); } EXPORT_SYMBOL(ldlm_completion_ast); @@ -715,6 +724,7 @@ int ldlm_cli_enqueue(struct obd_export *exp, struct ptlrpc_request **reqp, lock->l_export = NULL; lock->l_blocking_ast = einfo->ei_cb_bl; lock->l_flags |= (*flags & (LDLM_FL_NO_LRU | LDLM_FL_EXCL)); + lock->l_last_activity = ktime_get_real_seconds(); /* lock not sent to server yet */ -- cgit v0.10.2 From 7510c5ca70e3dc52a22f8ffd80c3bd5412c3704b Mon Sep 17 00:00:00 2001 From: Yang Sheng <yang.sheng@intel.com> Date: Sun, 18 Sep 2016 16:37:50 -0400 Subject: staging: lustre: llite: ensure all data flush out when umount Write out all extents when clear inode. Otherwise we may lose data while umount. Signed-off-by: Yang Sheng <yang.sheng@intel.com> Signed-off-by: Jinshan Xiong <jinshan.xiong@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5584 Reviewed-on: http://review.whamcloud.com/12103 Reviewed-by: Bobi Jam <bobijam@gmail.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 2aab396..f140d3e 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -1909,20 +1909,13 @@ void ll_delete_inode(struct inode *inode) * osc_extent implementation at LU-1030. */ cl_sync_file_range(inode, 0, OBD_OBJECT_EOF, - CL_FSYNC_DISCARD, 1); + CL_FSYNC_LOCAL, 1); truncate_inode_pages_final(&inode->i_data); - /* Workaround for LU-118 */ - if (inode->i_data.nrpages) { - spin_lock_irq(&inode->i_data.tree_lock); - spin_unlock_irq(&inode->i_data.tree_lock); - LASSERTF(inode->i_data.nrpages == 0, - "inode="DFID"(%p) nrpages=%lu, see http://jira.whamcloud.com/browse/LU-118\n", - PFID(ll_inode2fid(inode)), inode, - inode->i_data.nrpages); - } - /* Workaround end */ + LASSERTF(!inode->i_data.nrpages, + "inode=" DFID "(%p) nrpages=%lu, see http://jira.whamcloud.com/browse/LU-118\n", + PFID(ll_inode2fid(inode)), inode, inode->i_data.nrpages); ll_clear_inode(inode); clear_inode(inode); -- cgit v0.10.2 From 1ebfdcac07c223437383f52f7e9dbb8df440d62e Mon Sep 17 00:00:00 2001 From: Fan Yong <fan.yong@intel.com> Date: Sun, 18 Sep 2016 16:37:51 -0400 Subject: staging: lustre: lmv: add testing for bad name hash Enable testing of the lfsck recovery feature in the client code for the case when name hash for some entry becomes corrupt. Signed-off-by: Fan Yong <fan.yong@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5519 Reviewed-on: http://review.whamcloud.com/11846 Reviewed-by: Alex Zhuravlev <alexey.zhuravlev@intel.com> Reviewed-by: Lai Siyao <lai.siyao@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd_support.h b/drivers/staging/lustre/lustre/include/obd_support.h index d4c41d0..3144cca 100644 --- a/drivers/staging/lustre/lustre/include/obd_support.h +++ b/drivers/staging/lustre/lustre/include/obd_support.h @@ -479,6 +479,7 @@ extern char obd_jobid_var[]; #define OBD_FAIL_LFSCK_NO_AUTO 0x160b #define OBD_FAIL_LFSCK_NO_DOUBLESCAN 0x160c #define OBD_FAIL_LFSCK_INVALID_PFID 0x1619 +#define OBD_FAIL_LFSCK_BAD_NAME_HASH 0x1628 /* UPDATE */ #define OBD_FAIL_UPDATE_OBJ_NET 0x1700 diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 618af33..0ffb653 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -1573,9 +1573,13 @@ lmv_locate_target_for_name(struct lmv_obd *lmv, struct lmv_stripe_md *lsm, const struct lmv_oinfo *oinfo; struct lmv_tgt_desc *tgt; - oinfo = lsm_name_to_stripe_info(lsm, name, namelen); - if (IS_ERR(oinfo)) - return ERR_CAST(oinfo); + if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_BAD_NAME_HASH)) { + oinfo = &lsm->lsm_md_oinfo[cfs_fail_val]; + } else { + oinfo = lsm_name_to_stripe_info(lsm, name, namelen); + if (IS_ERR(oinfo)) + return ERR_CAST(oinfo); + } *fid = oinfo->lmo_fid; *mds = oinfo->lmo_mds; -- cgit v0.10.2 From eb1ddc6724f8b5e7f8d0fe1b2e29327802fe0503 Mon Sep 17 00:00:00 2001 From: James Simmons <jsimmons@infradead.org> Date: Sun, 18 Sep 2016 16:37:52 -0400 Subject: staging: lustre: obd: restore linkea support Original linkea was only used for the lustre server code so it was removed from the upstream client. Now it needs to be restored for client work that uses this infrastructure. Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lu_object.h b/drivers/staging/lustre/lustre/include/lu_object.h index 66ab98a..7b37cae 100644 --- a/drivers/staging/lustre/lustre/include/lu_object.h +++ b/drivers/staging/lustre/lustre/include/lu_object.h @@ -1319,5 +1319,12 @@ struct lu_kmem_descr { int lu_kmem_init(struct lu_kmem_descr *caches); void lu_kmem_fini(struct lu_kmem_descr *caches); +void lu_buf_free(struct lu_buf *buf); +void lu_buf_alloc(struct lu_buf *buf, size_t size); +void lu_buf_realloc(struct lu_buf *buf, size_t size); + +int lu_buf_check_and_grow(struct lu_buf *buf, size_t len); +struct lu_buf *lu_buf_check_and_alloc(struct lu_buf *buf, size_t len); + /** @} lu */ #endif /* __LUSTRE_LU_OBJECT_H */ diff --git a/drivers/staging/lustre/lustre/include/lustre_linkea.h b/drivers/staging/lustre/lustre/include/lustre_linkea.h new file mode 100644 index 0000000..249e8bf --- /dev/null +++ b/drivers/staging/lustre/lustre/include/lustre_linkea.h @@ -0,0 +1,79 @@ +/* + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.gnu.org/licenses/gpl-2.0.html + * + * GPL HEADER END + */ +/* + * Copyright (c) 2013, 2014, Intel Corporation. + * Use is subject to license terms. + * + * Author: di wang <di.wang@intel.com> + */ + +#define DEFAULT_LINKEA_SIZE 4096 + +struct linkea_data { + /** + * Buffer to keep link EA body. + */ + struct lu_buf *ld_buf; + /** + * The matched header, entry and its length in the EA + */ + struct link_ea_header *ld_leh; + struct link_ea_entry *ld_lee; + int ld_reclen; +}; + +int linkea_data_new(struct linkea_data *ldata, struct lu_buf *buf); +int linkea_init(struct linkea_data *ldata); +void linkea_entry_unpack(const struct link_ea_entry *lee, int *reclen, + struct lu_name *lname, struct lu_fid *pfid); +int linkea_entry_pack(struct link_ea_entry *lee, const struct lu_name *lname, + const struct lu_fid *pfid); +int linkea_add_buf(struct linkea_data *ldata, const struct lu_name *lname, + const struct lu_fid *pfid); +void linkea_del_buf(struct linkea_data *ldata, const struct lu_name *lname); +int linkea_links_find(struct linkea_data *ldata, const struct lu_name *lname, + const struct lu_fid *pfid); + +static inline void linkea_first_entry(struct linkea_data *ldata) +{ + LASSERT(ldata); + LASSERT(ldata->ld_leh); + + if (ldata->ld_leh->leh_reccount == 0) + ldata->ld_lee = NULL; + else + ldata->ld_lee = (struct link_ea_entry *)(ldata->ld_leh + 1); +} + +static inline void linkea_next_entry(struct linkea_data *ldata) +{ + LASSERT(ldata); + LASSERT(ldata->ld_leh); + + if (ldata->ld_lee) { + ldata->ld_lee = (struct link_ea_entry *)((char *)ldata->ld_lee + + ldata->ld_reclen); + if ((char *)ldata->ld_lee >= ((char *)ldata->ld_leh + + ldata->ld_leh->leh_len)) + ldata->ld_lee = NULL; + } +} diff --git a/drivers/staging/lustre/lustre/obdclass/Makefile b/drivers/staging/lustre/lustre/obdclass/Makefile index df7e47f..b42e109 100644 --- a/drivers/staging/lustre/lustre/obdclass/Makefile +++ b/drivers/staging/lustre/lustre/obdclass/Makefile @@ -3,6 +3,6 @@ obj-$(CONFIG_LUSTRE_FS) += obdclass.o obdclass-y := linux/linux-module.o linux/linux-obdo.o linux/linux-sysctl.o \ llog.o llog_cat.o llog_obd.o llog_swab.o class_obd.o debug.o \ genops.o uuid.o lprocfs_status.o lprocfs_counters.o \ - lustre_handles.o lustre_peer.o statfs_pack.o \ + lustre_handles.o lustre_peer.o statfs_pack.o linkea.o \ obdo.o obd_config.o obd_mount.o lu_object.o lu_ref.o \ cl_object.o cl_page.o cl_lock.o cl_io.o kernelcomm.o diff --git a/drivers/staging/lustre/lustre/obdclass/linkea.c b/drivers/staging/lustre/lustre/obdclass/linkea.c new file mode 100644 index 0000000..0b1d2f0 --- /dev/null +++ b/drivers/staging/lustre/lustre/obdclass/linkea.c @@ -0,0 +1,201 @@ +/* + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.gnu.org/licenses/gpl-2.0.html + * + * GPL HEADER END + */ +/* + * Copyright (c) 2013, 2014, Intel Corporation. + * Use is subject to license terms. + * + * Author: Di Wang <di.wang@intel.com> + */ + +#include "../include/lustre/lustre_idl.h" +#include "../include/obd.h" +#include "../include/lustre_linkea.h" + +int linkea_data_new(struct linkea_data *ldata, struct lu_buf *buf) +{ + ldata->ld_buf = lu_buf_check_and_alloc(buf, PAGE_SIZE); + if (!ldata->ld_buf->lb_buf) + return -ENOMEM; + ldata->ld_leh = ldata->ld_buf->lb_buf; + ldata->ld_leh->leh_magic = LINK_EA_MAGIC; + ldata->ld_leh->leh_len = sizeof(struct link_ea_header); + ldata->ld_leh->leh_reccount = 0; + return 0; +} +EXPORT_SYMBOL(linkea_data_new); + +int linkea_init(struct linkea_data *ldata) +{ + struct link_ea_header *leh; + + LASSERT(ldata->ld_buf); + leh = ldata->ld_buf->lb_buf; + if (leh->leh_magic == __swab32(LINK_EA_MAGIC)) { + leh->leh_magic = LINK_EA_MAGIC; + leh->leh_reccount = __swab32(leh->leh_reccount); + leh->leh_len = __swab64(leh->leh_len); + /* entries are swabbed by linkea_entry_unpack */ + } + if (leh->leh_magic != LINK_EA_MAGIC) + return -EINVAL; + if (leh->leh_reccount == 0) + return -ENODATA; + + ldata->ld_leh = leh; + return 0; +} +EXPORT_SYMBOL(linkea_init); + +/** + * Pack a link_ea_entry. + * All elements are stored as chars to avoid alignment issues. + * Numbers are always big-endian + * \retval record length + */ +int linkea_entry_pack(struct link_ea_entry *lee, const struct lu_name *lname, + const struct lu_fid *pfid) +{ + struct lu_fid tmpfid; + int reclen; + + tmpfid = *pfid; + if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_LINKEA_CRASH)) + tmpfid.f_ver = ~0; + fid_cpu_to_be(&tmpfid, &tmpfid); + memcpy(&lee->lee_parent_fid, &tmpfid, sizeof(tmpfid)); + memcpy(lee->lee_name, lname->ln_name, lname->ln_namelen); + reclen = sizeof(struct link_ea_entry) + lname->ln_namelen; + + lee->lee_reclen[0] = (reclen >> 8) & 0xff; + lee->lee_reclen[1] = reclen & 0xff; + return reclen; +} +EXPORT_SYMBOL(linkea_entry_pack); + +void linkea_entry_unpack(const struct link_ea_entry *lee, int *reclen, + struct lu_name *lname, struct lu_fid *pfid) +{ + *reclen = (lee->lee_reclen[0] << 8) | lee->lee_reclen[1]; + memcpy(pfid, &lee->lee_parent_fid, sizeof(*pfid)); + fid_be_to_cpu(pfid, pfid); + if (lname) { + lname->ln_name = lee->lee_name; + lname->ln_namelen = *reclen - sizeof(struct link_ea_entry); + } +} +EXPORT_SYMBOL(linkea_entry_unpack); + +/** + * Add a record to the end of link ea buf + **/ +int linkea_add_buf(struct linkea_data *ldata, const struct lu_name *lname, + const struct lu_fid *pfid) +{ + LASSERT(ldata->ld_leh); + + if (!lname || !pfid) + return -EINVAL; + + ldata->ld_reclen = lname->ln_namelen + sizeof(struct link_ea_entry); + if (ldata->ld_leh->leh_len + ldata->ld_reclen > + ldata->ld_buf->lb_len) { + if (lu_buf_check_and_grow(ldata->ld_buf, + ldata->ld_leh->leh_len + + ldata->ld_reclen) < 0) + return -ENOMEM; + } + + ldata->ld_leh = ldata->ld_buf->lb_buf; + ldata->ld_lee = ldata->ld_buf->lb_buf + ldata->ld_leh->leh_len; + ldata->ld_reclen = linkea_entry_pack(ldata->ld_lee, lname, pfid); + ldata->ld_leh->leh_len += ldata->ld_reclen; + ldata->ld_leh->leh_reccount++; + CDEBUG(D_INODE, "New link_ea name '" DFID ":%.*s' is added\n", + PFID(pfid), lname->ln_namelen, lname->ln_name); + return 0; +} +EXPORT_SYMBOL(linkea_add_buf); + +/** Del the current record from the link ea buf */ +void linkea_del_buf(struct linkea_data *ldata, const struct lu_name *lname) +{ + LASSERT(ldata->ld_leh && ldata->ld_lee); + + ldata->ld_leh->leh_reccount--; + ldata->ld_leh->leh_len -= ldata->ld_reclen; + memmove(ldata->ld_lee, (char *)ldata->ld_lee + ldata->ld_reclen, + (char *)ldata->ld_leh + ldata->ld_leh->leh_len - + (char *)ldata->ld_lee); + CDEBUG(D_INODE, "Old link_ea name '%.*s' is removed\n", + lname->ln_namelen, lname->ln_name); + + if ((char *)ldata->ld_lee >= ((char *)ldata->ld_leh + + ldata->ld_leh->leh_len)) + ldata->ld_lee = NULL; +} +EXPORT_SYMBOL(linkea_del_buf); + +/** + * Check if such a link exists in linkEA. + * + * \param ldata link data the search to be done on + * \param lname name in the parent's directory entry pointing to this object + * \param pfid parent fid the link to be found for + * + * \retval 0 success + * \retval -ENOENT link does not exist + * \retval -ve on error + */ +int linkea_links_find(struct linkea_data *ldata, const struct lu_name *lname, + const struct lu_fid *pfid) +{ + struct lu_name tmpname; + struct lu_fid tmpfid; + int count; + + LASSERT(ldata->ld_leh); + + /* link #0 */ + ldata->ld_lee = (struct link_ea_entry *)(ldata->ld_leh + 1); + + for (count = 0; count < ldata->ld_leh->leh_reccount; count++) { + linkea_entry_unpack(ldata->ld_lee, &ldata->ld_reclen, + &tmpname, &tmpfid); + if (tmpname.ln_namelen == lname->ln_namelen && + lu_fid_eq(&tmpfid, pfid) && + (strncmp(tmpname.ln_name, lname->ln_name, + tmpname.ln_namelen) == 0)) + break; + ldata->ld_lee = (struct link_ea_entry *)((char *)ldata->ld_lee + + ldata->ld_reclen); + } + + if (count == ldata->ld_leh->leh_reccount) { + CDEBUG(D_INODE, "Old link_ea name '%.*s' not found\n", + lname->ln_namelen, lname->ln_name); + ldata->ld_lee = NULL; + ldata->ld_reclen = 0; + return -ENOENT; + } + return 0; +} +EXPORT_SYMBOL(linkea_links_find); diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c index 44a854c..e284e5d 100644 --- a/drivers/staging/lustre/lustre/obdclass/lu_object.c +++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c @@ -1984,3 +1984,73 @@ void lu_kmem_fini(struct lu_kmem_descr *caches) } } EXPORT_SYMBOL(lu_kmem_fini); + +void lu_buf_free(struct lu_buf *buf) +{ + LASSERT(buf); + if (buf->lb_buf) { + LASSERT(buf->lb_len > 0); + kvfree(buf->lb_buf); + buf->lb_buf = NULL; + buf->lb_len = 0; + } +} +EXPORT_SYMBOL(lu_buf_free); + +void lu_buf_alloc(struct lu_buf *buf, size_t size) +{ + LASSERT(buf); + LASSERT(!buf->lb_buf); + LASSERT(!buf->lb_len); + buf->lb_buf = libcfs_kvzalloc(size, GFP_NOFS); + if (likely(buf->lb_buf)) + buf->lb_len = size; +} +EXPORT_SYMBOL(lu_buf_alloc); + +void lu_buf_realloc(struct lu_buf *buf, size_t size) +{ + lu_buf_free(buf); + lu_buf_alloc(buf, size); +} +EXPORT_SYMBOL(lu_buf_realloc); + +struct lu_buf *lu_buf_check_and_alloc(struct lu_buf *buf, size_t len) +{ + if (!buf->lb_buf && !buf->lb_len) + lu_buf_alloc(buf, len); + + if ((len > buf->lb_len) && buf->lb_buf) + lu_buf_realloc(buf, len); + + return buf; +} +EXPORT_SYMBOL(lu_buf_check_and_alloc); + +/** + * Increase the size of the \a buf. + * preserves old data in buffer + * old buffer remains unchanged on error + * \retval 0 or -ENOMEM + */ +int lu_buf_check_and_grow(struct lu_buf *buf, size_t len) +{ + char *ptr; + + if (len <= buf->lb_len) + return 0; + + ptr = libcfs_kvzalloc(len, GFP_NOFS); + if (!ptr) + return -ENOMEM; + + /* Free the old buf */ + if (buf->lb_buf) { + memcpy(ptr, buf->lb_buf, buf->lb_len); + kvfree(buf->lb_buf); + } + + buf->lb_buf = ptr; + buf->lb_len = len; + return 0; +} -- cgit v0.10.2 From a6d879fd08cd904c3595c338bb7995680b1ead13 Mon Sep 17 00:00:00 2001 From: Henri Doreau <henri.doreau@cea.fr> Date: Sun, 18 Sep 2016 16:37:53 -0400 Subject: staging: lustre: llite: Add ioctl to get parent fids from link EA. Added LL_IOC_GETPARENT to retrieve the <parent_fid>/name(s) of a given entry, based on its link EA. This saves multiple calls to path2fid/fid2path. Merged with second later patch that does various cleanups. Avoid unneeded allocation. Get read-only attributes from the user getparent structure and write the modified attributes only, instead of populating a whole structure in kernel and copying it back. Signed-off-by: Thomas Leibovici <thomas.leibovici@cea.fr> Signed-off-by: Henri Doreau <henri.doreau@cea.fr> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3613 Reviewed-on: http://review.whamcloud.com/7069 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5837 Reviewed-on: http://review.whamcloud.com/12527 Reviewed-by: Ned Bass <bass6@llnl.gov> Reviewed-by: frank zago <fzago@cray.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 2dc550a..0cc47bc 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -3468,6 +3468,14 @@ struct getinfo_fid2path { void lustre_swab_fid2path(struct getinfo_fid2path *gf); +/** path2parent request/reply structures */ +struct getparent { + struct lu_fid gp_fid; /**< parent FID */ + __u32 gp_linkno; /**< hardlink number */ + __u32 gp_name_size; /**< size of the name field */ + char gp_name[0]; /**< zero-terminated link name */ +} __packed; + enum { LAYOUT_INTENT_ACCESS = 0, LAYOUT_INTENT_READ = 1, diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index cc0a786..08ac6e4 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -245,6 +245,7 @@ struct ost_id { #define LL_IOC_LMV_SET_DEFAULT_STRIPE _IOWR('f', 246, struct lmv_user_md) #define LL_IOC_MIGRATE _IOR('f', 247, int) #define LL_IOC_FID2MDTIDX _IOWR('f', 248, struct lu_fid) +#define LL_IOC_GETPARENT _IOWR('f', 249, struct getparent) /* Lease types for use as arg and return of LL_IOC_{GET,SET}_LEASE ioctl. */ enum ll_lease_type { diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 234095e..705de1c 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -1562,6 +1562,8 @@ out_quotactl: return rc; case OBD_IOC_FID2PATH: return ll_fid2path(inode, (void __user *)arg); + case LL_IOC_GETPARENT: + return ll_getparent(file, (void __user *)arg); case LL_IOC_FID2MDTIDX: { struct obd_export *exp = ll_i2mdexp(inode); struct lu_fid fid; diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 127d0e0..45acc5d 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -2362,6 +2362,8 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return 0; } + case LL_IOC_GETPARENT: + return ll_getparent(file, (struct getparent __user *)arg); case OBD_IOC_FID2PATH: return ll_fid2path(inode, (void __user *)arg); case LL_IOC_DATA_VERSION: { diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index fc707c2..1cc427c 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -36,6 +36,7 @@ #include "../include/lustre_ver.h" #include "../include/lustre_disk.h" /* for s2sbi */ #include "../include/lustre_eacl.h" +#include "../include/lustre_linkea.h" /* for struct cl_lock_descr and struct cl_io */ #include "../include/cl_object.h" @@ -1038,7 +1039,17 @@ static inline __u64 ll_file_maxbytes(struct inode *inode) /* llite/xattr.c */ extern const struct xattr_handler *ll_xattr_handlers[]; +#define XATTR_USER_T 1 +#define XATTR_TRUSTED_T 2 +#define XATTR_SECURITY_T 3 +#define XATTR_ACL_ACCESS_T 4 +#define XATTR_ACL_DEFAULT_T 5 +#define XATTR_LUSTRE_T 6 +#define XATTR_OTHER_T 7 + ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size); +int ll_xattr_list(struct inode *inode, const char *name, int type, + void *buffer, size_t size, __u64 valid); /** * Common IO arguments for various VFS I/O interfaces. @@ -1399,6 +1410,8 @@ void ll_xattr_fini(void); int ll_page_sync_io(const struct lu_env *env, struct cl_io *io, struct cl_page *page, enum cl_req_type crt); +int ll_getparent(struct file *file, struct getparent __user *arg); + /* lcommon_cl.c */ int cl_setattr_ost(struct inode *inode, const struct iattr *attr); diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index f140d3e..91031b7 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -2545,3 +2545,128 @@ void ll_compute_rootsquash_state(struct ll_sb_info *sbi) } up_write(&squash->rsi_sem); } + +/** + * Parse linkea content to extract information about a given hardlink + * + * \param[in] ldata - Initialized linkea data + * \param[in] linkno - Link identifier + * \param[out] parent_fid - The entry's parent FID + * \param[in] size - Entry name destination buffer + * + * \retval 0 on success + * \retval Appropriate negative error code on failure + */ +static int ll_linkea_decode(struct linkea_data *ldata, unsigned int linkno, + struct lu_fid *parent_fid, struct lu_name *ln) +{ + unsigned int idx; + int rc; + + rc = linkea_init(ldata); + if (rc < 0) + return rc; + + if (linkno >= ldata->ld_leh->leh_reccount) + /* beyond last link */ + return -ENODATA; + + linkea_first_entry(ldata); + for (idx = 0; ldata->ld_lee; idx++) { + linkea_entry_unpack(ldata->ld_lee, &ldata->ld_reclen, ln, + parent_fid); + if (idx == linkno) + break; + + linkea_next_entry(ldata); + } + + if (idx < linkno) + return -ENODATA; + + return 0; +} + +/** + * Get parent FID and name of an identified link. Operation is performed for + * a given link number, letting the caller iterate over linkno to list one or + * all links of an entry. + * + * \param[in] file - File descriptor against which to perform the operation + * \param[in,out] arg - User-filled structure containing the linkno to operate + * on and the available size. It is eventually filled with + * the requested information or left untouched on error + * + * \retval - 0 on success + * \retval - Appropriate negative error code on failure + */ +int ll_getparent(struct file *file, struct getparent __user *arg) +{ + struct inode *inode = file_inode(file); + struct linkea_data *ldata; + struct lu_fid parent_fid; + struct lu_buf buf = { + .lb_buf = NULL, + .lb_len = 0 + }; + struct lu_name ln; + u32 name_size; + u32 linkno; + int rc; + + if (!capable(CFS_CAP_DAC_READ_SEARCH) && + !(ll_i2sbi(inode)->ll_flags & LL_SBI_USER_FID2PATH)) + return -EPERM; + + if (get_user(name_size, &arg->gp_name_size)) + return -EFAULT; + + if (get_user(linkno, &arg->gp_linkno)) + return -EFAULT; + + if (name_size > PATH_MAX) + return -EINVAL; + + ldata = kzalloc(sizeof(*ldata), GFP_NOFS); + if (!ldata) + return -ENOMEM; + + rc = linkea_data_new(ldata, &buf); + if (rc < 0) + goto ldata_free; + + rc = ll_xattr_list(inode, XATTR_NAME_LINK, XATTR_TRUSTED_T, buf.lb_buf, + buf.lb_len, OBD_MD_FLXATTR); + if (rc < 0) + goto lb_free; + + rc = ll_linkea_decode(ldata, linkno, &parent_fid, &ln); + if (rc < 0) + goto lb_free; + + if (ln.ln_namelen >= name_size) { + rc = -EOVERFLOW; + goto lb_free; + } + + if (copy_to_user(&arg->gp_fid, &parent_fid, sizeof(arg->gp_fid))) { + rc = -EFAULT; + goto lb_free; + } + + if (copy_to_user(&arg->gp_name, ln.ln_name, ln.ln_namelen)) { + rc = -EFAULT; + goto lb_free; + } + + if (put_user('\0', arg->gp_name + ln.ln_namelen)) { + rc = -EFAULT; + goto lb_free; + } + +lb_free: + lu_buf_free(&buf); +ldata_free: + kfree(ldata); + return rc; +} diff --git a/drivers/staging/lustre/lustre/llite/xattr.c b/drivers/staging/lustre/lustre/llite/xattr.c index 17ad04f..0e6a559 100644 --- a/drivers/staging/lustre/lustre/llite/xattr.c +++ b/drivers/staging/lustre/lustre/llite/xattr.c @@ -44,14 +44,6 @@ #include "llite_internal.h" -#define XATTR_USER_T (1) -#define XATTR_TRUSTED_T (2) -#define XATTR_SECURITY_T (3) -#define XATTR_ACL_ACCESS_T (4) -#define XATTR_ACL_DEFAULT_T (5) -#define XATTR_LUSTRE_T (6) -#define XATTR_OTHER_T (7) - static int get_xattr_type(const char *name) { @@ -219,7 +211,7 @@ static int ll_xattr_set(const struct xattr_handler *handler, flags); } -static int +int ll_xattr_list(struct inode *inode, const char *name, int type, void *buffer, size_t size, __u64 valid) { -- cgit v0.10.2 From dbf789ce9d45721f990a993c7b1e61b998470a90 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong <jinshan.xiong@intel.com> Date: Sun, 18 Sep 2016 16:37:54 -0400 Subject: staging: lustre: llite: allow setting stripes to specify OSTs Extend the llite layer to support specifying individual target OSTs. Support specifying OSTs for regular files only. Directory support will be implemented later in a separate project. With this a file could have for example a OST index layout of 2,4,5,9,11. In addition, duplicate indices will be eliminated automatically. Calculate the max easize by ld_active_tgt_count instead of ld_tgt_count. However this may introduce problems when the OSTs are in recovery because non sufficient buffer may be allocated to store EA. Signed-off-by: Jian Yu <jian.yu@intel.com> Signed-off-by: Jinshan Xiong <jinshan.xiong@intel.com> Signed-off-by: James Simmons <uja.ornl@gmail.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4665 Reviewed-on: http://review.whamcloud.com/9383 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 0cc47bc..a0ca571 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -1483,6 +1483,8 @@ enum obdo_flags { #define LOV_MAGIC_JOIN_V1 (0x0BD20000 | LOV_MAGIC_MAGIC) #define LOV_MAGIC_V3 (0x0BD30000 | LOV_MAGIC_MAGIC) #define LOV_MAGIC_MIGRATE (0x0BD40000 | LOV_MAGIC_MAGIC) +/* reserved for specifying OSTs */ +#define LOV_MAGIC_SPECIFIC (0x0BD50000 | LOV_MAGIC_MAGIC) #define LOV_MAGIC LOV_MAGIC_V1 /* diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index 08ac6e4..3ef5db0 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -280,10 +280,12 @@ enum ll_lease_type { #define LL_FILE_LOCKLESS_IO 0x00000010 /* server-side locks with cio */ #define LL_FILE_RMTACL 0x00000020 -#define LOV_USER_MAGIC_V1 0x0BD10BD0 -#define LOV_USER_MAGIC LOV_USER_MAGIC_V1 -#define LOV_USER_MAGIC_JOIN_V1 0x0BD20BD0 -#define LOV_USER_MAGIC_V3 0x0BD30BD0 +#define LOV_USER_MAGIC_V1 0x0BD10BD0 +#define LOV_USER_MAGIC LOV_USER_MAGIC_V1 +#define LOV_USER_MAGIC_JOIN_V1 0x0BD20BD0 +#define LOV_USER_MAGIC_V3 0x0BD30BD0 +/* 0x0BD40BD0 is occupied by LOV_MAGIC_MIGRATE */ +#define LOV_USER_MAGIC_SPECIFIC 0x0BD50BD0 /* for specific OSTs */ #define LMV_USER_MAGIC 0x0CD30CD0 /*default lmv magic*/ @@ -361,12 +363,11 @@ struct lov_user_md_v3 { /* LOV EA user data (host-endian) */ static inline __u32 lov_user_md_size(__u16 stripes, __u32 lmm_magic) { - if (lmm_magic == LOV_USER_MAGIC_V3) - return sizeof(struct lov_user_md_v3) + - stripes * sizeof(struct lov_user_ost_data_v1); - else + if (lmm_magic == LOV_USER_MAGIC_V1) return sizeof(struct lov_user_md_v1) + stripes * sizeof(struct lov_user_ost_data_v1); + return sizeof(struct lov_user_md_v3) + + stripes * sizeof(struct lov_user_ost_data_v1); } /* Compile with -D_LARGEFILE64_SOURCE or -D_GNU_SOURCE (or #define) to diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 45acc5d..fc81551 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -1540,39 +1540,33 @@ static int ll_lov_setea(struct inode *inode, struct file *file, static int ll_lov_setstripe(struct inode *inode, struct file *file, unsigned long arg) { - struct lov_user_md_v3 lumv3; - struct lov_user_md_v1 *lumv1 = (struct lov_user_md_v1 *)&lumv3; - struct lov_user_md_v1 __user *lumv1p = (void __user *)arg; - struct lov_user_md_v3 __user *lumv3p = (void __user *)arg; + struct lov_user_md __user *lum = (struct lov_user_md __user *)arg; + struct lov_user_md *klum; int lum_size, rc; __u64 flags = FMODE_WRITE; - /* first try with v1 which is smaller than v3 */ - lum_size = sizeof(struct lov_user_md_v1); - if (copy_from_user(lumv1, lumv1p, lum_size)) - return -EFAULT; - - if (lumv1->lmm_magic == LOV_USER_MAGIC_V3) { - lum_size = sizeof(struct lov_user_md_v3); - if (copy_from_user(&lumv3, lumv3p, lum_size)) - return -EFAULT; - } + rc = ll_copy_user_md(lum, &klum); + if (rc < 0) + return rc; - rc = ll_lov_setstripe_ea_info(inode, file->f_path.dentry, flags, lumv1, + lum_size = rc; + rc = ll_lov_setstripe_ea_info(inode, file->f_path.dentry, flags, klum, lum_size); cl_lov_delay_create_clear(&file->f_flags); if (rc == 0) { struct lov_stripe_md *lsm; __u32 gen; - put_user(0, &lumv1p->lmm_stripe_count); + put_user(0, &lum->lmm_stripe_count); ll_layout_refresh(inode, &gen); lsm = ccc_inode_lsm_get(inode); rc = obd_iocontrol(LL_IOC_LOV_GETSTRIPE, ll_i2dtexp(inode), - 0, lsm, (void __user *)arg); + 0, lsm, lum); ccc_inode_lsm_put(inode, lsm); } + + kfree(klum); return rc; } diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 1cc427c..9a9fefd 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -875,6 +875,26 @@ int ll_get_obd_name(struct inode *inode, unsigned int cmd, unsigned long arg); char *ll_get_fsname(struct super_block *sb, char *buf, int buflen); void ll_compute_rootsquash_state(struct ll_sb_info *sbi); void ll_open_cleanup(struct super_block *sb, struct ptlrpc_request *open_req); +ssize_t ll_copy_user_md(const struct lov_user_md __user *md, + struct lov_user_md **kbuf); + +/* Compute expected user md size when passing in a md from user space */ +static inline ssize_t ll_lov_user_md_size(const struct lov_user_md *lum) +{ + switch (lum->lmm_magic) { + case LOV_USER_MAGIC_V1: + return sizeof(struct lov_user_md_v1); + case LOV_USER_MAGIC_V3: + return sizeof(struct lov_user_md_v3); + case LOV_USER_MAGIC_SPECIFIC: + if (lum->lmm_stripe_count > LOV_MAX_STRIPE_COUNT) + return -EINVAL; + + return lov_user_md_size(lum->lmm_stripe_count, + LOV_USER_MAGIC_SPECIFIC); + } + return -EINVAL; +} /* llite/llite_nfs.c */ extern const struct export_operations lustre_export_operations; diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 91031b7..c498748 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -2507,6 +2507,36 @@ void ll_dirty_page_discard_warn(struct page *page, int ioret) free_page((unsigned long)buf); } +ssize_t ll_copy_user_md(const struct lov_user_md __user *md, + struct lov_user_md **kbuf) +{ + struct lov_user_md lum; + ssize_t lum_size; + + if (copy_from_user(&lum, md, sizeof(lum))) { + lum_size = -EFAULT; + goto no_kbuf; + } + + lum_size = ll_lov_user_md_size(&lum); + if (lum_size < 0) + goto no_kbuf; + + *kbuf = kzalloc(lum_size, GFP_NOFS); + if (!*kbuf) { + lum_size = -ENOMEM; + goto no_kbuf; + } + + if (copy_from_user(*kbuf, md, lum_size) != 0) { + kfree(*kbuf); + *kbuf = NULL; + lum_size = -EFAULT; + } +no_kbuf: + return lum_size; +} + /* * Compute llite root squash state after a change of root squash * configuration setting or add/remove of a lnet nid diff --git a/drivers/staging/lustre/lustre/llite/xattr.c b/drivers/staging/lustre/lustre/llite/xattr.c index 0e6a559..e070adb 100644 --- a/drivers/staging/lustre/lustre/llite/xattr.c +++ b/drivers/staging/lustre/lustre/llite/xattr.c @@ -189,12 +189,15 @@ static int ll_xattr_set(const struct xattr_handler *handler, if (lump && S_ISREG(inode->i_mode)) { __u64 it_flags = FMODE_WRITE; - int lum_size = (lump->lmm_magic == LOV_USER_MAGIC_V1) ? - sizeof(*lump) : sizeof(struct lov_user_md_v3); + int lum_size; + + lum_size = ll_lov_user_md_size(lump); + if (lum_size < 0 || size < lum_size) + return 0; /* b=10667: ignore error */ rc = ll_lov_setstripe_ea_info(inode, dentry, it_flags, lump, lum_size); - /* b10667: rc always be 0 here for now */ + /* b=10667: rc always be 0 here for now */ rc = 0; } else if (S_ISDIR(inode->i_mode)) { rc = ll_dir_setstripe(inode, lump, 0); diff --git a/drivers/staging/lustre/lustre/lov/lov_pack.c b/drivers/staging/lustre/lustre/lov/lov_pack.c index c654810..595cf16 100644 --- a/drivers/staging/lustre/lustre/lov/lov_pack.c +++ b/drivers/staging/lustre/lustre/lov/lov_pack.c @@ -148,16 +148,11 @@ int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, stripe_count = 0; } } else { - /* No need to allocate more than maximum supported stripes. - * Anyway, this is pretty inaccurate since ld_tgt_count now - * represents max index and we should rely on the actual number - * of OSTs instead + /* + * To calculate maximum easize by active targets at present, + * which is exactly the maximum easize to be seen by LOV */ - stripe_count = lov_mds_md_max_stripe_count( - lov->lov_ocd.ocd_max_easize, lmm_magic); - - if (stripe_count > lov->desc.ld_tgt_count) - stripe_count = lov->desc.ld_tgt_count; + stripe_count = lov->desc.ld_active_tgt_count; } /* XXX LOV STACKING call into osc for sizes */ @@ -403,8 +398,9 @@ int lov_getstripe(struct obd_export *exp, struct lov_stripe_md *lsm, rc = -EFAULT; goto out_set; } - if ((lum.lmm_magic != LOV_USER_MAGIC) && - (lum.lmm_magic != LOV_USER_MAGIC_V3)) { + if (lum.lmm_magic != LOV_USER_MAGIC_V1 && + lum.lmm_magic != LOV_USER_MAGIC_V3 && + lum.lmm_magic != LOV_USER_MAGIC_SPECIFIC) { rc = -EINVAL; goto out_set; } diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index e25596f..87027c5 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -1916,19 +1916,6 @@ void lustre_swab_lmv_user_md(struct lmv_user_md *lum) } EXPORT_SYMBOL(lustre_swab_lmv_user_md); -static void print_lum(struct lov_user_md *lum) -{ - CDEBUG(D_OTHER, "lov_user_md %p:\n", lum); - CDEBUG(D_OTHER, "\tlmm_magic: %#x\n", lum->lmm_magic); - CDEBUG(D_OTHER, "\tlmm_pattern: %#x\n", lum->lmm_pattern); - CDEBUG(D_OTHER, "\tlmm_object_id: %llu\n", lmm_oi_id(&lum->lmm_oi)); - CDEBUG(D_OTHER, "\tlmm_object_gr: %llu\n", lmm_oi_seq(&lum->lmm_oi)); - CDEBUG(D_OTHER, "\tlmm_stripe_size: %#x\n", lum->lmm_stripe_size); - CDEBUG(D_OTHER, "\tlmm_stripe_count: %#x\n", lum->lmm_stripe_count); - CDEBUG(D_OTHER, "\tlmm_stripe_offset/lmm_layout_gen: %#x\n", - lum->lmm_stripe_offset); -} - static void lustre_swab_lmm_oi(struct ost_id *oi) { __swab64s(&oi->oi.oi_id); @@ -1943,7 +1930,6 @@ static void lustre_swab_lov_user_md_common(struct lov_user_md_v1 *lum) __swab32s(&lum->lmm_stripe_size); __swab16s(&lum->lmm_stripe_count); __swab16s(&lum->lmm_stripe_offset); - print_lum(lum); } void lustre_swab_lov_user_md_v1(struct lov_user_md_v1 *lum) -- cgit v0.10.2 From e554fbfffcecc0558f891b66719fc933539ceb16 Mon Sep 17 00:00:00 2001 From: Lai Siyao <lai.siyao@intel.com> Date: Sun, 18 Sep 2016 16:37:55 -0400 Subject: staging: lustre: statahead: use dcache-like interface for sa entry Rename ll_sa_entry to sa_entry, and manage sa_entry cache with dcache-like interfaces. sa_entry is not needed to be refcounted, because only scanner can free it, so after it's put in stat list, statahead thread shouldn't access it any longer. ll_statahead_interpret() doesn't need to take sai refcount, because statahead thread will wait for all inflight RPC to finish. Signed-off-by: Lai Siyao <lai.siyao@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3270 Reviewed-on: http://review.whamcloud.com/9664 Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: Fan Yong <fan.yong@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 1c884c0..6758bf4 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -812,7 +812,7 @@ struct md_enqueue_info { struct inode *mi_dir; int (*mi_cb)(struct ptlrpc_request *req, struct md_enqueue_info *minfo, int rc); - __u64 mi_cbdata; + void *mi_cbdata; }; struct obd_ops { diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 9a9fefd..cd639f4 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -1131,10 +1131,12 @@ struct ll_statahead_info { wait_queue_head_t sai_waitq; /* stat-ahead wait queue */ struct ptlrpc_thread sai_thread; /* stat-ahead thread */ struct ptlrpc_thread sai_agl_thread; /* AGL thread */ - struct list_head sai_entries; /* entry list */ - struct list_head sai_entries_received; /* entries returned */ - struct list_head sai_entries_stated; /* entries stated */ - struct list_head sai_entries_agl; /* AGL entries to be sent */ + struct list_head sai_interim_entries; /* entries which got async + * stat reply, but not + * instantiated + */ + struct list_head sai_entries; /* completed entries */ + struct list_head sai_agls; /* AGLs to be sent */ struct list_head sai_cache[LL_SA_CACHE_SIZE]; spinlock_t sai_cache_lock[LL_SA_CACHE_SIZE]; atomic_t sai_cache_count; /* entry count in cache */ diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c index 5760974..0d87dc9 100644 --- a/drivers/staging/lustre/lustre/llite/statahead.c +++ b/drivers/staging/lustre/lustre/llite/statahead.c @@ -49,24 +49,26 @@ enum se_stat { SA_ENTRY_INIT = 0, /** init entry */ SA_ENTRY_SUCC = 1, /** stat succeed */ SA_ENTRY_INVA = 2, /** invalid entry */ - SA_ENTRY_DEST = 3, /** entry to be destroyed */ }; -struct ll_sa_entry { - /* link into sai->sai_entries */ - struct list_head se_link; - /* link into sai->sai_entries_{received,stated} */ +/* + * sa_entry is not refcounted: statahead thread allocates it and do async stat, + * and in async stat callback ll_statahead_interpret() will add it into + * sai_cb_entries, later statahead thread will call sa_handle_callback() to + * instantiate entry and move it into sai_entries, and then only scanner process + * can access and free it. + */ +struct sa_entry { + /* link into sai_cb_entries or sai_entries */ struct list_head se_list; /* link into sai hash table locally */ struct list_head se_hash; - /* entry reference count */ - atomic_t se_refcount; /* entry index in the sai */ __u64 se_index; /* low layer ldlm lock handle */ __u64 se_handle; /* entry status */ - enum se_stat se_stat; + enum se_stat se_state; /* entry size, contains name */ int se_size; /* pointer to async getattr enqueue info */ @@ -85,13 +87,13 @@ static DEFINE_SPINLOCK(sai_generation_lock); /* * The entry only can be released by the caller, it is necessary to hold lock. */ -static inline int ll_sa_entry_stated(struct ll_sa_entry *entry) +static inline int sa_ready(struct sa_entry *entry) { smp_rmb(); - return (entry->se_stat != SA_ENTRY_INIT); + return (entry->se_state != SA_ENTRY_INIT); } -static inline int ll_sa_entry_hash(int val) +static inline int sa_hash(int val) { return val & LL_SA_CACHE_MASK; } @@ -100,9 +102,9 @@ static inline int ll_sa_entry_hash(int val) * Insert entry to hash SA table. */ static inline void -ll_sa_entry_enhash(struct ll_statahead_info *sai, struct ll_sa_entry *entry) +sa_rehash(struct ll_statahead_info *sai, struct sa_entry *entry) { - int i = ll_sa_entry_hash(entry->se_qstr.hash); + int i = sa_hash(entry->se_qstr.hash); spin_lock(&sai->sai_cache_lock[i]); list_add_tail(&entry->se_hash, &sai->sai_cache[i]); @@ -113,9 +115,9 @@ ll_sa_entry_enhash(struct ll_statahead_info *sai, struct ll_sa_entry *entry) * Remove entry from SA table. */ static inline void -ll_sa_entry_unhash(struct ll_statahead_info *sai, struct ll_sa_entry *entry) +sa_unhash(struct ll_statahead_info *sai, struct sa_entry *entry) { - int i = ll_sa_entry_hash(entry->se_qstr.hash); + int i = sa_hash(entry->se_qstr.hash); spin_lock(&sai->sai_cache_lock[i]); list_del_init(&entry->se_hash); @@ -133,14 +135,14 @@ static inline int sa_sent_full(struct ll_statahead_info *sai) return atomic_read(&sai->sai_cache_count) >= sai->sai_max; } -static inline int sa_received_empty(struct ll_statahead_info *sai) +static inline int sa_has_callback(struct ll_statahead_info *sai) { - return list_empty(&sai->sai_entries_received); + return !list_empty(&sai->sai_interim_entries); } static inline int agl_list_empty(struct ll_statahead_info *sai) { - return list_empty(&sai->sai_entries_agl); + return list_empty(&sai->sai_agls); } /** @@ -168,17 +170,16 @@ static inline int is_omitted_entry(struct ll_statahead_info *sai, __u64 index) /* * Insert it into sai_entries tail when init. */ -static struct ll_sa_entry * -ll_sa_entry_alloc(struct dentry *parent, - struct ll_statahead_info *sai, __u64 index, - const char *name, int len) +static struct sa_entry * +sa_alloc(struct dentry *parent, struct ll_statahead_info *sai, __u64 index, + const char *name, int len) { struct ll_inode_info *lli; - struct ll_sa_entry *entry; + struct sa_entry *entry; int entry_size; char *dname; - entry_size = sizeof(struct ll_sa_entry) + (len & ~3) + 4; + entry_size = sizeof(struct sa_entry) + (len & ~3) + 4; entry = kzalloc(entry_size, GFP_NOFS); if (unlikely(!entry)) return ERR_PTR(-ENOMEM); @@ -187,34 +188,9 @@ ll_sa_entry_alloc(struct dentry *parent, len, name, entry, index); entry->se_index = index; - - /* - * Statahead entry reference rules: - * - * 1) When statahead entry is initialized, its reference is set as 2. - * One reference is used by the directory scanner. When the scanner - * searches the statahead cache for the given name, it can perform - * lockless hash lookup (only the scanner can remove entry from hash - * list), and once found, it needn't to call "atomic_inc()" for the - * entry reference. So the performance is improved. After using the - * statahead entry, the scanner will call "atomic_dec()" to drop the - * reference held when initialization. If it is the last reference, - * the statahead entry will be freed. - * - * 2) All other threads, including statahead thread and ptlrpcd thread, - * when they process the statahead entry, the reference for target - * should be held to guarantee the entry will not be released by the - * directory scanner. After processing the entry, these threads will - * drop the entry reference. If it is the last reference, the entry - * will be freed. - * - * The second reference when initializes the statahead entry is used - * by the statahead thread, following the rule 2). - */ - atomic_set(&entry->se_refcount, 2); - entry->se_stat = SA_ENTRY_INIT; + entry->se_state = SA_ENTRY_INIT; entry->se_size = entry_size; - dname = (char *)entry + sizeof(struct ll_sa_entry); + dname = (char *)entry + sizeof(struct sa_entry); memcpy(dname, name, len); dname[len] = 0; @@ -224,9 +200,8 @@ ll_sa_entry_alloc(struct dentry *parent, lli = ll_i2info(sai->sai_inode); spin_lock(&lli->lli_sa_lock); - list_add_tail(&entry->se_link, &sai->sai_entries); INIT_LIST_HEAD(&entry->se_list); - ll_sa_entry_enhash(sai, entry); + sa_rehash(sai, entry); spin_unlock(&lli->lli_sa_lock); atomic_inc(&sai->sai_cache_count); @@ -234,151 +209,130 @@ ll_sa_entry_alloc(struct dentry *parent, return entry; } -/* - * Used by the directory scanner to search entry with name. - * - * Only the caller can remove the entry from hash, so it is unnecessary to hold - * hash lock. It is caller's duty to release the init refcount on the entry, so - * it is also unnecessary to increase refcount on the entry. - */ -static struct ll_sa_entry * -ll_sa_entry_get_byname(struct ll_statahead_info *sai, const struct qstr *qstr) +/* free sa_entry, which should have been unhashed and not in any list */ +static void sa_free(struct ll_statahead_info *sai, struct sa_entry *entry) { - struct ll_sa_entry *entry; - int i = ll_sa_entry_hash(qstr->hash); + CDEBUG(D_READA, "free sa entry %.*s(%p) index %llu\n", + entry->se_qstr.len, entry->se_qstr.name, entry, + entry->se_index); - list_for_each_entry(entry, &sai->sai_cache[i], se_hash) { - if (entry->se_qstr.hash == qstr->hash && - entry->se_qstr.len == qstr->len && - memcmp(entry->se_qstr.name, qstr->name, qstr->len) == 0) - return entry; - } - return NULL; + LASSERT(list_empty(&entry->se_list)); + LASSERT(list_empty(&entry->se_hash)); + + kfree(entry); + atomic_dec(&sai->sai_cache_count); } /* - * Used by the async getattr request callback to find entry with index. - * - * Inside lli_sa_lock to prevent others to change the list during the search. - * It needs to increase entry refcount before returning to guarantee that the - * entry cannot be freed by others. + * find sa_entry by name, used by directory scanner, lock is not needed because + * only scanner can remove the entry from cache. */ -static struct ll_sa_entry * -ll_sa_entry_get_byindex(struct ll_statahead_info *sai, __u64 index) +static struct sa_entry * +sa_get(struct ll_statahead_info *sai, const struct qstr *qstr) { - struct ll_sa_entry *entry; + struct sa_entry *entry; + int i = sa_hash(qstr->hash); - list_for_each_entry(entry, &sai->sai_entries, se_link) { - if (entry->se_index == index) { - LASSERT(atomic_read(&entry->se_refcount) > 0); - atomic_inc(&entry->se_refcount); + list_for_each_entry(entry, &sai->sai_cache[i], se_hash) { + if (entry->se_qstr.hash == qstr->hash && + entry->se_qstr.len == qstr->len && + memcmp(entry->se_qstr.name, qstr->name, qstr->len) == 0) return entry; - } - if (entry->se_index > index) - break; } return NULL; } -static void ll_sa_entry_put(struct ll_statahead_info *sai, - struct ll_sa_entry *entry) -{ - if (atomic_dec_and_test(&entry->se_refcount)) { - CDEBUG(D_READA, "free sa entry %.*s(%p) index %llu\n", - entry->se_qstr.len, entry->se_qstr.name, entry, - entry->se_index); - - LASSERT(list_empty(&entry->se_link)); - LASSERT(list_empty(&entry->se_list)); - LASSERT(list_empty(&entry->se_hash)); - - iput(entry->se_inode); - - kfree(entry); - atomic_dec(&sai->sai_cache_count); - } -} - +/* unhash and unlink sa_entry, and then free it */ static inline void -do_sa_entry_fini(struct ll_statahead_info *sai, struct ll_sa_entry *entry) +sa_kill(struct ll_statahead_info *sai, struct sa_entry *entry) { struct ll_inode_info *lli = ll_i2info(sai->sai_inode); LASSERT(!list_empty(&entry->se_hash)); - LASSERT(!list_empty(&entry->se_link)); + LASSERT(!list_empty(&entry->se_list)); + LASSERT(sa_ready(entry)); - ll_sa_entry_unhash(sai, entry); + sa_unhash(sai, entry); spin_lock(&lli->lli_sa_lock); - entry->se_stat = SA_ENTRY_DEST; - list_del_init(&entry->se_link); - if (likely(!list_empty(&entry->se_list))) - list_del_init(&entry->se_list); + list_del_init(&entry->se_list); spin_unlock(&lli->lli_sa_lock); - ll_sa_entry_put(sai, entry); + if (entry->se_inode) + iput(entry->se_inode); + + sa_free(sai, entry); } -/* - * Delete it from sai_entries_stated list when fini. - */ +/* called by scanner after use, sa_entry will be killed */ static void -ll_sa_entry_fini(struct ll_statahead_info *sai, struct ll_sa_entry *entry) +sa_put(struct ll_statahead_info *sai, struct sa_entry *entry) { - struct ll_sa_entry *pos, *next; + struct sa_entry *tmp, *next; + + if (entry && entry->se_state == SA_ENTRY_SUCC) { + struct ll_sb_info *sbi = ll_i2sbi(sai->sai_inode); + + sai->sai_hit++; + sai->sai_consecutive_miss = 0; + sai->sai_max = min(2 * sai->sai_max, sbi->ll_sa_max); + } else { + sai->sai_miss++; + sai->sai_consecutive_miss++; + } if (entry) - do_sa_entry_fini(sai, entry); + sa_kill(sai, entry); - /* drop old entry, only 'scanner' process does this, no need to lock */ - list_for_each_entry_safe(pos, next, &sai->sai_entries, se_link) { - if (!is_omitted_entry(sai, pos->se_index)) + /* + * kill old completed entries, only scanner process does this, no need + * to lock + */ + list_for_each_entry_safe(tmp, next, &sai->sai_entries, se_list) { + if (!is_omitted_entry(sai, tmp->se_index)) break; - /* keep those whose statahead RPC not finished */ - if (pos->se_stat == SA_ENTRY_SUCC || - pos->se_stat == SA_ENTRY_INVA) - do_sa_entry_fini(sai, pos); + sa_kill(sai, tmp); } + wake_up(&sai->sai_thread.t_ctl_waitq); } /* - * Inside lli_sa_lock. + * update state and sort add entry to sai_entries by index, return true if + * scanner is waiting on this entry. */ -static void -__sa_entry_post_stat(struct ll_statahead_info *sai, struct ll_sa_entry *entry, - enum se_stat stat) +static bool +__sa_make_ready(struct ll_statahead_info *sai, struct sa_entry *entry, int ret) { - struct ll_sa_entry *se; - struct list_head *pos = &sai->sai_entries_stated; - - LASSERT(entry->se_stat == SA_ENTRY_INIT); + struct list_head *pos = &sai->sai_entries; + __u64 index = entry->se_index; + struct sa_entry *se; - if (!list_empty(&entry->se_list)) - list_del_init(&entry->se_list); + LASSERT(!sa_ready(entry)); + LASSERT(list_empty(&entry->se_list)); - list_for_each_entry_reverse(se, &sai->sai_entries_stated, se_list) { + list_for_each_entry_reverse(se, &sai->sai_entries, se_list) { if (se->se_index < entry->se_index) { pos = &se->se_list; break; } } - list_add(&entry->se_list, pos); - entry->se_stat = stat; + entry->se_state = ret < 0 ? SA_ENTRY_INVA : SA_ENTRY_SUCC; + + return (index == sai->sai_index_wait); } /* - * Move entry to sai_entries_stated and sort with the index. - * \retval 1 -- entry to be destroyed. - * \retval 0 -- entry is inserted into stated list. + * release resources used in async stat RPC, update entry state and wakeup if + * scanner process it waiting on this entry. */ static void -sa_entry_post_stat(struct ll_statahead_info *sai, struct ll_sa_entry *entry, - enum se_stat stat) +sa_make_ready(struct ll_statahead_info *sai, struct sa_entry *entry, int ret) { struct ll_inode_info *lli = ll_i2info(sai->sai_inode); struct md_enqueue_info *minfo = entry->se_minfo; struct ptlrpc_request *req = entry->se_req; + bool wakeup; /* release resources used in RPC */ if (minfo) { @@ -394,12 +348,15 @@ sa_entry_post_stat(struct ll_statahead_info *sai, struct ll_sa_entry *entry, } spin_lock(&lli->lli_sa_lock); - __sa_entry_post_stat(sai, entry, stat); + wakeup = __sa_make_ready(sai, entry, ret); spin_unlock(&lli->lli_sa_lock); + + if (wakeup) + wake_up(&sai->sai_waitq); } /* - * Insert inode into the list of sai_entries_agl. + * Insert inode into the list of sai_agls. */ static void ll_agl_add(struct ll_statahead_info *sai, struct inode *inode, int index) @@ -417,9 +374,9 @@ static void ll_agl_add(struct ll_statahead_info *sai, igrab(inode); spin_lock(&parent->lli_agl_lock); - if (list_empty(&sai->sai_entries_agl)) + if (list_empty(&sai->sai_agls)) added = 1; - list_add_tail(&child->lli_agl_list, &sai->sai_entries_agl); + list_add_tail(&child->lli_agl_list, &sai->sai_agls); spin_unlock(&parent->lli_agl_lock); } else { spin_unlock(&child->lli_agl_lock); @@ -429,6 +386,7 @@ static void ll_agl_add(struct ll_statahead_info *sai, wake_up(&sai->sai_agl_thread.t_ctl_waitq); } +/* allocate sai */ static struct ll_statahead_info *ll_sai_alloc(void) { struct ll_statahead_info *sai; @@ -452,10 +410,9 @@ static struct ll_statahead_info *ll_sai_alloc(void) init_waitqueue_head(&sai->sai_thread.t_ctl_waitq); init_waitqueue_head(&sai->sai_agl_thread.t_ctl_waitq); + INIT_LIST_HEAD(&sai->sai_interim_entries); INIT_LIST_HEAD(&sai->sai_entries); - INIT_LIST_HEAD(&sai->sai_entries_received); - INIT_LIST_HEAD(&sai->sai_entries_stated); - INIT_LIST_HEAD(&sai->sai_entries_agl); + INIT_LIST_HEAD(&sai->sai_agls); for (i = 0; i < LL_SA_CACHE_SIZE; i++) { INIT_LIST_HEAD(&sai->sai_cache[i]); @@ -486,7 +443,7 @@ static void ll_sai_put(struct ll_statahead_info *sai) if (atomic_dec_and_lock(&sai->sai_refcount, &lli->lli_sa_lock)) { struct ll_sb_info *sbi = ll_i2sbi(sai->sai_inode); - struct ll_sa_entry *entry, *next; + struct sa_entry *entry, *next; lli->lli_sai = NULL; spin_unlock(&lli->lli_sa_lock); @@ -494,14 +451,14 @@ static void ll_sai_put(struct ll_statahead_info *sai) LASSERT(thread_is_stopped(&sai->sai_thread)); LASSERT(thread_is_stopped(&sai->sai_agl_thread)); LASSERT(sai->sai_sent == sai->sai_replied); + LASSERT(!sa_has_callback(sai)); list_for_each_entry_safe(entry, next, &sai->sai_entries, - se_link) - do_sa_entry_fini(sai, entry); + se_list) + sa_kill(sai, entry); LASSERT(atomic_read(&sai->sai_cache_count) == 0); - LASSERT(list_empty(&sai->sai_entries_agl)); - LASSERT(atomic_read(&sai->sai_refcount) == 0); + LASSERT(list_empty(&sai->sai_agls)); iput(sai->sai_inode); kfree(sai); @@ -509,7 +466,7 @@ static void ll_sai_put(struct ll_statahead_info *sai) } } -/* Do NOT forget to drop inode refcount when into sai_entries_agl. */ +/* Do NOT forget to drop inode refcount when into sai_agls. */ static void ll_agl_trigger(struct inode *inode, struct ll_statahead_info *sai) { struct ll_inode_info *lli = ll_i2info(inode); @@ -569,9 +526,12 @@ static void ll_agl_trigger(struct inode *inode, struct ll_statahead_info *sai) iput(inode); } -/* prepare inode for received statahead entry, and add it into agl list */ -static void sa_post_one(struct ll_statahead_info *sai, - struct ll_sa_entry *entry) +/* + * prepare inode for sa entry, add it into agl list, now sa_entry is ready + * to be used by scanner process. + */ +static void sa_instantiate(struct ll_statahead_info *sai, + struct sa_entry *entry) { struct inode *dir = sai->sai_inode; struct inode *child; @@ -629,8 +589,9 @@ static void sa_post_one(struct ll_statahead_info *sai, if (rc) goto out; - CDEBUG(D_DLMTRACE, "%s: setting l_data to inode "DFID"%p\n", + CDEBUG(D_READA, "%s: setting %.*s" DFID " l_data to inode %p\n", ll_get_fsname(child->i_sb, NULL, 0), + entry->se_qstr.len, entry->se_qstr.name, PFID(ll_inode2fid(child)), child); ll_set_lock_data(ll_i2sbi(dir)->ll_md_exp, child, it, NULL); @@ -640,45 +601,42 @@ static void sa_post_one(struct ll_statahead_info *sai, ll_agl_add(sai, child, entry->se_index); out: - /* The "sa_entry_post_stat()" will drop related ldlm ibits lock - * reference count by calling "ll_intent_drop_lock()" in spite of the - * above operations failed or not. Do not worry about calling - * "ll_intent_drop_lock()" more than once. + /* + * sa_make_ready() will drop ldlm ibits lock refcount by calling + * ll_intent_drop_lock() in spite of failures. Do not worry about + * calling ll_intent_drop_lock() more than once. */ - sa_entry_post_stat(sai, entry, rc < 0 ? SA_ENTRY_INVA : SA_ENTRY_SUCC); - if (entry->se_index == sai->sai_index_wait) - wake_up(&sai->sai_waitq); - ll_sa_entry_put(sai, entry); + sa_make_ready(sai, entry, rc); } -static void ll_post_statahead(struct ll_statahead_info *sai) +/* once there are async stat replies, instantiate sa_entry */ +static void sa_handle_callback(struct ll_statahead_info *sai) { struct ll_inode_info *lli; lli = ll_i2info(sai->sai_inode); - while (!sa_received_empty(sai)) { - struct ll_sa_entry *entry; + while (sa_has_callback(sai)) { + struct sa_entry *entry; spin_lock(&lli->lli_sa_lock); - if (unlikely(sa_received_empty(sai))) { + if (unlikely(!sa_has_callback(sai))) { spin_unlock(&lli->lli_sa_lock); break; } - entry = list_entry(sai->sai_entries_received.next, - struct ll_sa_entry, se_list); - atomic_inc(&entry->se_refcount); + entry = list_entry(sai->sai_interim_entries.next, + struct sa_entry, se_list); list_del_init(&entry->se_list); spin_unlock(&lli->lli_sa_lock); - sa_post_one(sai, entry); + sa_instantiate(sai, entry); } spin_lock(&lli->lli_agl_lock); while (!agl_list_empty(sai)) { struct ll_inode_info *clli; - clli = list_entry(sai->sai_entries_agl.next, + clli = list_entry(sai->sai_agls.next, struct ll_inode_info, lli_agl_list); list_del_init(&clli->lli_agl_list); spin_unlock(&lli->lli_agl_lock); @@ -690,29 +648,38 @@ static void ll_post_statahead(struct ll_statahead_info *sai) spin_unlock(&lli->lli_agl_lock); } +/* + * callback for async stat, because this is called in ptlrpcd context, we only + * put sa_entry in sai_cb_entries list, and let sa_handle_callback() to really + * prepare inode and instantiate sa_entry later. + */ static int ll_statahead_interpret(struct ptlrpc_request *req, struct md_enqueue_info *minfo, int rc) { struct lookup_intent *it = &minfo->mi_it; struct inode *dir = minfo->mi_dir; struct ll_inode_info *lli = ll_i2info(dir); - struct ll_statahead_info *sai = NULL; - struct ll_sa_entry *entry; - int wakeup; + struct ll_statahead_info *sai = lli->lli_sai; + struct sa_entry *entry = (struct sa_entry *)minfo->mi_cbdata; + bool wakeup; if (it_disposition(it, DISP_LOOKUP_NEG)) rc = -ENOENT; - sai = ll_sai_get(dir); + /* + * because statahead thread will wait for all inflight RPC to finish, + * sai should be always valid, no need to refcount + */ LASSERT(sai); LASSERT(!thread_is_stopped(&sai->sai_thread)); + LASSERT(entry); + + CDEBUG(D_READA, "sa_entry %.*s rc %d\n", + entry->se_qstr.len, entry->se_qstr.name, rc); spin_lock(&lli->lli_sa_lock); - entry = ll_sa_entry_get_byindex(sai, minfo->mi_cbdata); - LASSERT(entry); if (rc) { - __sa_entry_post_stat(sai, entry, SA_ENTRY_INVA); - wakeup = (entry->se_index == sai->sai_index_wait); + wakeup = __sa_make_ready(sai, entry, rc); } else { entry->se_minfo = minfo; entry->se_req = ptlrpc_request_addref(req); @@ -724,27 +691,24 @@ static int ll_statahead_interpret(struct ptlrpc_request *req, */ entry->se_handle = it->it_lock_handle; ll_intent_drop_lock(it); - wakeup = sa_received_empty(sai); - list_add_tail(&entry->se_list, &sai->sai_entries_received); + wakeup = !sa_has_callback(sai); + list_add_tail(&entry->se_list, &sai->sai_interim_entries); } sai->sai_replied++; - spin_unlock(&lli->lli_sa_lock); - ll_sa_entry_put(sai, entry); if (wakeup) wake_up(&sai->sai_thread.t_ctl_waitq); + spin_unlock(&lli->lli_sa_lock); if (rc) { ll_intent_release(it); iput(dir); kfree(minfo); } - if (sai) - ll_sai_put(sai); return rc; } -static void sa_args_fini(struct md_enqueue_info *minfo, +static void sa_fini_data(struct md_enqueue_info *minfo, struct ldlm_enqueue_info *einfo) { LASSERT(minfo && einfo); @@ -756,8 +720,8 @@ static void sa_args_fini(struct md_enqueue_info *minfo, /** * prepare arguments for async stat RPC. */ -static int sa_args_init(struct inode *dir, struct inode *child, - struct ll_sa_entry *entry, struct md_enqueue_info **pmi, +static int sa_prep_data(struct inode *dir, struct inode *child, + struct sa_entry *entry, struct md_enqueue_info **pmi, struct ldlm_enqueue_info **pei) { const struct qstr *qstr = &entry->se_qstr; @@ -786,7 +750,7 @@ static int sa_args_init(struct inode *dir, struct inode *child, minfo->mi_it.it_op = IT_GETATTR; minfo->mi_dir = igrab(dir); minfo->mi_cb = ll_statahead_interpret; - minfo->mi_cbdata = entry->se_index; + minfo->mi_cbdata = entry; einfo->ei_type = LDLM_IBITS; einfo->ei_mode = it_to_lock_mode(&minfo->mi_it); @@ -801,19 +765,19 @@ static int sa_args_init(struct inode *dir, struct inode *child, return 0; } -static int do_sa_lookup(struct inode *dir, struct ll_sa_entry *entry) +static int sa_lookup(struct inode *dir, struct sa_entry *entry) { struct md_enqueue_info *minfo; struct ldlm_enqueue_info *einfo; int rc; - rc = sa_args_init(dir, NULL, entry, &minfo, &einfo); + rc = sa_prep_data(dir, NULL, entry, &minfo, &einfo); if (rc) return rc; rc = md_intent_getattr_async(ll_i2mdexp(dir), minfo, einfo); if (rc < 0) - sa_args_fini(minfo, einfo); + sa_fini_data(minfo, einfo); return rc; } @@ -824,8 +788,8 @@ static int do_sa_lookup(struct inode *dir, struct ll_sa_entry *entry) * \retval 0 -- will send stat-ahead request * \retval others -- prepare stat-ahead request failed */ -static int do_sa_revalidate(struct inode *dir, struct ll_sa_entry *entry, - struct dentry *dentry) +static int sa_revalidate(struct inode *dir, struct sa_entry *entry, + struct dentry *dentry) { struct inode *inode = d_inode(dentry); struct lookup_intent it = { .it_op = IT_GETATTR, @@ -849,7 +813,7 @@ static int do_sa_revalidate(struct inode *dir, struct ll_sa_entry *entry, return 1; } - rc = sa_args_init(dir, inode, entry, &minfo, &einfo); + rc = sa_prep_data(dir, inode, entry, &minfo, &einfo); if (rc) { entry->se_inode = NULL; iput(inode); @@ -860,32 +824,30 @@ static int do_sa_revalidate(struct inode *dir, struct ll_sa_entry *entry, if (rc < 0) { entry->se_inode = NULL; iput(inode); - sa_args_fini(minfo, einfo); + sa_fini_data(minfo, einfo); } return rc; } -static void ll_statahead_one(struct dentry *parent, const char *name, - const int name_len) +static void sa_statahead(struct dentry *parent, const char *name, int len) { struct inode *dir = d_inode(parent); struct ll_inode_info *lli = ll_i2info(dir); struct ll_statahead_info *sai = lli->lli_sai; struct dentry *dentry = NULL; - struct ll_sa_entry *entry; + struct sa_entry *entry; int rc; - entry = ll_sa_entry_alloc(parent, sai, sai->sai_index, name, - name_len); + entry = sa_alloc(parent, sai, sai->sai_index, name, len); if (IS_ERR(entry)) return; dentry = d_lookup(parent, &entry->se_qstr); if (!dentry) { - rc = do_sa_lookup(dir, entry); + rc = sa_lookup(dir, entry); } else { - rc = do_sa_revalidate(dir, entry, dentry); + rc = sa_revalidate(dir, entry, dentry); if (rc == 1 && agl_should_run(sai, d_inode(dentry))) ll_agl_add(sai, d_inode(dentry), entry->se_index); } @@ -893,18 +855,12 @@ static void ll_statahead_one(struct dentry *parent, const char *name, if (dentry) dput(dentry); - if (rc) { - sa_entry_post_stat(sai, entry, - rc < 0 ? SA_ENTRY_INVA : SA_ENTRY_SUCC); - if (entry->se_index == sai->sai_index_wait) - wake_up(&sai->sai_waitq); - } else { + if (rc) + sa_make_ready(sai, entry, rc); + else sai->sai_sent++; - } sai->sai_index++; - /* drop one refcount on entry by ll_sa_entry_alloc */ - ll_sa_entry_put(sai, entry); } static int ll_agl_thread(void *arg) @@ -938,7 +894,7 @@ static int ll_agl_thread(void *arg) while (1) { l_wait_event(thread->t_ctl_waitq, - !list_empty(&sai->sai_entries_agl) || + !list_empty(&sai->sai_agls) || !thread_is_running(thread), &lwi); @@ -949,8 +905,8 @@ static int ll_agl_thread(void *arg) /* The statahead thread maybe help to process AGL entries, * so check whether list empty again. */ - if (!list_empty(&sai->sai_entries_agl)) { - clli = list_entry(sai->sai_entries_agl.next, + if (!list_empty(&sai->sai_agls)) { + clli = list_entry(sai->sai_agls.next, struct ll_inode_info, lli_agl_list); list_del_init(&clli->lli_agl_list); spin_unlock(&plli->lli_agl_lock); @@ -962,8 +918,8 @@ static int ll_agl_thread(void *arg) spin_lock(&plli->lli_agl_lock); sai->sai_agl_valid = 0; - while (!list_empty(&sai->sai_entries_agl)) { - clli = list_entry(sai->sai_entries_agl.next, + while (!list_empty(&sai->sai_agls)) { + clli = list_entry(sai->sai_agls.next, struct ll_inode_info, lli_agl_list); list_del_init(&clli->lli_agl_list); spin_unlock(&plli->lli_agl_lock); @@ -1118,15 +1074,15 @@ static int ll_statahead_thread(void *arg) do { l_wait_event(thread->t_ctl_waitq, !sa_sent_full(sai) || - !list_empty(&sai->sai_entries_received) || - !list_empty(&sai->sai_entries_agl) || + sa_has_callback(sai) || + !list_empty(&sai->sai_agls) || !thread_is_running(thread), &lwi); - ll_post_statahead(sai); + sa_handle_callback(sai); } while (sa_sent_full(sai) && thread_is_running(thread)); - ll_statahead_one(parent, name, namelen); + sa_statahead(parent, name, namelen); } pos = le64_to_cpu(dp->ldp_hash_end); @@ -1158,12 +1114,12 @@ static int ll_statahead_thread(void *arg) */ while (thread_is_running(thread)) { l_wait_event(thread->t_ctl_waitq, - !sa_received_empty(sai) || + sa_has_callback(sai) || !agl_list_empty(sai) || !thread_is_running(thread), &lwi); - ll_post_statahead(sai); + sa_handle_callback(sai); } out: if (sai->sai_agl_valid) { @@ -1193,8 +1149,8 @@ out: sai->sai_sent == sai->sai_replied, &lwi); } - /* release resources held by received entries. */ - ll_post_statahead(sai); + /* release resources held by statahead RPCs */ + sa_handle_callback(sai); spin_lock(&lli->lli_sa_lock); thread_set_flags(thread, SVC_STOPPED); @@ -1251,7 +1207,7 @@ void ll_deauthorize_statahead(struct inode *dir, void *key) if (sai && thread_is_running(&sai->sai_thread)) { /* * statahead thread may not quit yet because it needs to cache - * stated entries, now it's time to tell it to quit. + * entries, now it's time to tell it to quit. */ thread_set_flags(&sai->sai_thread, SVC_STOPPING); wake_up(&sai->sai_thread.t_ctl_waitq); @@ -1389,29 +1345,12 @@ out: return rc; } -static void -ll_sai_unplug(struct ll_statahead_info *sai, struct ll_sa_entry *entry) -{ - if (entry && entry->se_stat == SA_ENTRY_SUCC) { - struct ll_sb_info *sbi = ll_i2sbi(sai->sai_inode); - - sai->sai_hit++; - sai->sai_consecutive_miss = 0; - sai->sai_max = min(2 * sai->sai_max, sbi->ll_sa_max); - } else { - sai->sai_miss++; - sai->sai_consecutive_miss++; - } - ll_sa_entry_fini(sai, entry); - wake_up(&sai->sai_thread.t_ctl_waitq); -} - static int revalidate_statahead_dentry(struct inode *dir, struct ll_statahead_info *sai, struct dentry **dentryp, int only_unplug) { - struct ll_sa_entry *entry = NULL; + struct sa_entry *entry = NULL; struct l_wait_info lwi = { 0 }; int rc = 0; @@ -1442,31 +1381,31 @@ static int revalidate_statahead_dentry(struct inode *dir, } } - entry = ll_sa_entry_get_byname(sai, &(*dentryp)->d_name); + entry = sa_get(sai, &(*dentryp)->d_name); if (!entry || only_unplug) { - ll_sai_unplug(sai, entry); + sa_put(sai, entry); return entry ? 1 : -EAGAIN; } /* if statahead is busy in readdir, help it do post-work */ - if (!ll_sa_entry_stated(entry) && sai->sai_in_readpage) - ll_post_statahead(sai); + if (!sa_ready(entry) && sai->sai_in_readpage) + sa_handle_callback(sai); - if (!ll_sa_entry_stated(entry)) { + if (!sa_ready(entry)) { sai->sai_index_wait = entry->se_index; lwi = LWI_TIMEOUT_INTR(cfs_time_seconds(30), NULL, LWI_ON_SIGNAL_NOOP, NULL); rc = l_wait_event(sai->sai_waitq, - ll_sa_entry_stated(entry) || + sa_ready(entry) || thread_is_stopped(&sai->sai_thread), &lwi); if (rc < 0) { - ll_sai_unplug(sai, entry); + sa_put(sai, entry); return -EAGAIN; } } - if (entry->se_stat == SA_ENTRY_SUCC && entry->se_inode) { + if (entry->se_state == SA_ENTRY_SUCC && entry->se_inode) { struct inode *inode = entry->se_inode; struct lookup_intent it = { .it_op = IT_GETATTR, .it_lock_handle = entry->se_handle }; @@ -1480,7 +1419,7 @@ static int revalidate_statahead_dentry(struct inode *dir, alias = ll_splice_alias(inode, *dentryp); if (IS_ERR(alias)) { - ll_sai_unplug(sai, entry); + sa_put(sai, entry); return PTR_ERR(alias); } *dentryp = alias; @@ -1507,7 +1446,7 @@ static int revalidate_statahead_dentry(struct inode *dir, } } out_unplug: - ll_sai_unplug(sai, entry); + sa_put(sai, entry); return rc; } -- cgit v0.10.2 From 6535a7d046a24d7d426a9dfedf918eac954ea00c Mon Sep 17 00:00:00 2001 From: Lai Siyao <lai.siyao@intel.com> Date: Sun, 18 Sep 2016 16:37:56 -0400 Subject: staging: lustre: statahead: ll_intent_drop_lock() called in spinlock ll_intent_drop_lock() may sleep, which should not be called inside spinlock. Signed-off-by: Lai Siyao <lai.siyao@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2272 Reviewed-on: http://review.whamcloud.com/9665 Reviewed-by: Fan Yong <fan.yong@intel.com> Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c index 0d87dc9..92972d0 100644 --- a/drivers/staging/lustre/lustre/llite/statahead.c +++ b/drivers/staging/lustre/lustre/llite/statahead.c @@ -661,6 +661,7 @@ static int ll_statahead_interpret(struct ptlrpc_request *req, struct ll_inode_info *lli = ll_i2info(dir); struct ll_statahead_info *sai = lli->lli_sai; struct sa_entry *entry = (struct sa_entry *)minfo->mi_cbdata; + __u64 handle = 0; bool wakeup; if (it_disposition(it, DISP_LOOKUP_NEG)) @@ -677,6 +678,21 @@ static int ll_statahead_interpret(struct ptlrpc_request *req, CDEBUG(D_READA, "sa_entry %.*s rc %d\n", entry->se_qstr.len, entry->se_qstr.name, rc); + if (rc) { + ll_intent_release(it); + iput(dir); + kfree(minfo); + } else { + /* + * release ibits lock ASAP to avoid deadlock when statahead + * thread enqueues lock on parent in readdir and another + * process enqueues lock on child with parent lock held, eg. + * unlink. + */ + handle = it->it_lock_handle; + ll_intent_drop_lock(it); + } + spin_lock(&lli->lli_sa_lock); if (rc) { wakeup = __sa_make_ready(sai, entry, rc); @@ -689,8 +705,7 @@ static int ll_statahead_interpret(struct ptlrpc_request *req, * for readpage and other tries to enqueue lock on child * with parent's lock held, for example: unlink. */ - entry->se_handle = it->it_lock_handle; - ll_intent_drop_lock(it); + entry->se_handle = handle; wakeup = !sa_has_callback(sai); list_add_tail(&entry->se_list, &sai->sai_interim_entries); } @@ -700,11 +715,6 @@ static int ll_statahead_interpret(struct ptlrpc_request *req, wake_up(&sai->sai_thread.t_ctl_waitq); spin_unlock(&lli->lli_sa_lock); - if (rc) { - ll_intent_release(it); - iput(dir); - kfree(minfo); - } return rc; } -- cgit v0.10.2 From 17be217056561b90134384d863abfd543d2321e4 Mon Sep 17 00:00:00 2001 From: Lai Siyao <lai.siyao@intel.com> Date: Sun, 18 Sep 2016 16:37:57 -0400 Subject: staging: lustre: statahead: race in start/stop statahead When starting statahead thread, it should check whether current lli_opendir_key was deauthorized in the mean time by another process. Signed-off-by: Lai Siyao <lai.siyao@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3270 Reviewed-on: http://review.whamcloud.com/9666 Reviewed-by: Fan Yong <fan.yong@intel.com> Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c index 92972d0..8cc0bfa 100644 --- a/drivers/staging/lustre/lustre/llite/statahead.c +++ b/drivers/staging/lustre/lustre/llite/statahead.c @@ -1509,7 +1509,24 @@ static int start_statahead_thread(struct inode *dir, struct dentry *dentry) CDEBUG(D_READA, "start statahead thread: sai %p, parent %pd\n", sai, parent); + /* + * if another process started statahead thread, or deauthorized current + * lli_opendir_key, don't start statahead. + */ + spin_lock(&lli->lli_sa_lock); + if (unlikely(lli->lli_sai || lli->lli_opendir_key || + lli->lli_opendir_pid != current->pid)) { + spin_unlock(&lli->lli_sa_lock); + + dput(parent); + iput(sai->sai_inode); + rc = -EAGAIN; + goto out; + } lli->lli_sai = sai; + spin_unlock(&lli->lli_sa_lock); + + atomic_inc(&ll_i2sbi(parent->d_inode)->ll_sa_running); task = kthread_run(ll_statahead_thread, parent, "ll_sa_%u", lli->lli_opendir_pid); @@ -1518,9 +1535,12 @@ static int start_statahead_thread(struct inode *dir, struct dentry *dentry) rc = PTR_ERR(task); CERROR("cannot start ll_sa thread: rc = %d\n", rc); dput(parent); - lli->lli_opendir_key = NULL; + + spin_lock(&lli->lli_sa_lock); thread_set_flags(thread, SVC_STOPPED); thread_set_flags(&sai->sai_agl_thread, SVC_STOPPED); + spin_unlock(&lli->lli_sa_lock); + ll_sai_put(sai); LASSERT(!lli->lli_sai); return -EAGAIN; @@ -1529,7 +1549,6 @@ static int start_statahead_thread(struct inode *dir, struct dentry *dentry) l_wait_event(thread->t_ctl_waitq, thread_is_running(thread) || thread_is_stopped(thread), &lwi); - atomic_inc(&ll_i2sbi(d_inode(parent))->ll_sa_running); ll_sai_put(sai); /* @@ -1540,9 +1559,11 @@ static int start_statahead_thread(struct inode *dir, struct dentry *dentry) out: kfree(sai); + /* + * once we start statahead thread failed, disable statahead so + * subsequent won't waste time to try it. + */ spin_lock(&lli->lli_sa_lock); - lli->lli_opendir_key = NULL; - lli->lli_opendir_pid = 0; lli->lli_sa_enabled = 0; spin_unlock(&lli->lli_sa_lock); -- cgit v0.10.2 From 60873bb8859ba73d395c6a23df9d71fba7f84685 Mon Sep 17 00:00:00 2001 From: Alexander Boyko <alexander_boyko@xyratex.com> Date: Sun, 18 Sep 2016 16:37:58 -0400 Subject: staging: lustre: at: net AT after connect Once connected, the previously gathered AT statistics is not valid anymore because may reflect other routing, etc. The connect by itself could take a long time due to different reasons (e.g. server was not ready) and net latency got very high (see import_select_connection()) what does not reflect the current situation. Take into account only the current (re-)CONNECT rpc latency. Signed-off-by: Vitaly Fertman <vitaly_fertman@xyratex.com> Signed-off-by: Alexander Boyko <alexander_boyko@xyratex.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5380 Xyratex-bug-id: MRP-1285 Reviewed-on: http://review.whamcloud.com/11155 Reviewed-by: Liang Zhen <liang.zhen@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Mike Pershin <mike.pershin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index bea1c16..27fe00d 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -283,8 +283,8 @@ int ptlrpc_at_get_net_latency(struct ptlrpc_request *req) } /* Adjust expected network latency */ -static void ptlrpc_at_adj_net_latency(struct ptlrpc_request *req, - unsigned int service_time) +void ptlrpc_at_adj_net_latency(struct ptlrpc_request *req, + unsigned int service_time) { unsigned int nl, oldnl; struct imp_at *at; diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c index 013a957..17f3fec 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/import.c +++ b/drivers/staging/lustre/lustre/ptlrpc/import.c @@ -846,6 +846,14 @@ static int ptlrpc_connect_interpret(const struct lu_env *env, imp->imp_obd->obd_self_export->exp_connect_data = *ocd; class_export_put(exp); + /* + * The net statistics after (re-)connect is not valid anymore, + * because may reflect other routing, etc. + */ + at_init(&imp->imp_at.iat_net_latency, 0, 0); + ptlrpc_at_adj_net_latency(request, + lustre_msg_get_service_time(request->rq_repmsg)); + obd_import_event(imp->imp_obd, imp, IMP_EVENT_OCD); if (aa->pcaa_initial_connect) { diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h index a9831fa..29cfac2 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h @@ -53,6 +53,8 @@ int ptlrpc_start_thread(struct ptlrpc_service_part *svcpt, int wait); int ptlrpcd_start(struct ptlrpcd_ctl *pc); /* client.c */ +void ptlrpc_at_adj_net_latency(struct ptlrpc_request *req, + unsigned int service_time); struct ptlrpc_bulk_desc *ptlrpc_new_bulk(unsigned npages, unsigned max_brw, unsigned type, unsigned portal); int ptlrpc_request_cache_init(void); -- cgit v0.10.2 From 930f60e659478b300d06e699cc45f31adb07ed25 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin <dmitry.eremin@intel.com> Date: Sun, 18 Sep 2016 16:37:59 -0400 Subject: staging: lustre: mdc: fix comparison between signed and unsigned Change type of client_obd->*_mds_*size from int to __u32 and argumanets of related create/rename/setattr functions. Change type of op_data->op_namelen to size_t. Change type of argument size for all mdc_*_pack() to size_t. Signed-off-by: Dmitry Eremin <dmitry.eremin@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5577 Reviewed-on: http://review.whamcloud.com/11379 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Fan Yong <fan.yong@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 6758bf4..8a7c803 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -220,10 +220,10 @@ struct client_obd { /* max_mds_easize is purely a performance thing so we don't have to * call obd_size_diskmd() all the time. */ - int cl_default_mds_easize; - int cl_max_mds_easize; - int cl_default_mds_cookiesize; - int cl_max_mds_cookiesize; + u32 cl_default_mds_easize; + u32 cl_max_mds_easize; + u32 cl_default_mds_cookiesize; + u32 cl_max_mds_cookiesize; enum lustre_sec_part cl_sp_me; enum lustre_sec_part cl_sp_to; @@ -745,7 +745,7 @@ struct md_op_data { struct lustre_handle op_handle; s64 op_mod_time; const char *op_name; - int op_namelen; + size_t op_namelen; __u32 op_mode; struct lmv_stripe_md *op_mea1; struct lmv_stripe_md *op_mea2; @@ -976,8 +976,8 @@ struct md_ops { int (*close)(struct obd_export *, struct md_op_data *, struct md_open_data *, struct ptlrpc_request **); int (*create)(struct obd_export *, struct md_op_data *, - const void *, int, int, __u32, __u32, cfs_cap_t, - __u64, struct ptlrpc_request **); + const void *, size_t, umode_t, uid_t, gid_t, + cfs_cap_t, __u64, struct ptlrpc_request **); int (*done_writing)(struct obd_export *, struct md_op_data *, struct md_open_data *); int (*enqueue)(struct obd_export *, struct ldlm_enqueue_info *, @@ -995,10 +995,10 @@ struct md_ops { int (*link)(struct obd_export *, struct md_op_data *, struct ptlrpc_request **); int (*rename)(struct obd_export *, struct md_op_data *, - const char *, int, const char *, int, + const char *, size_t, const char *, size_t, struct ptlrpc_request **); int (*setattr)(struct obd_export *, struct md_op_data *, void *, - int, void *, int, struct ptlrpc_request **, + size_t, void *, size_t, struct ptlrpc_request **, struct md_open_data **mod); int (*sync)(struct obd_export *, const struct lu_fid *, struct ptlrpc_request **); @@ -1016,7 +1016,7 @@ struct md_ops { u64, const char *, const char *, int, int, int, struct ptlrpc_request **); - int (*init_ea_size)(struct obd_export *, int, int, int, int); + int (*init_ea_size)(struct obd_export *, u32, u32, u32, u32); int (*get_lustre_md)(struct obd_export *, struct ptlrpc_request *, struct obd_export *, struct obd_export *, @@ -1139,7 +1139,8 @@ static inline const char *lu_dev_name(const struct lu_device *lu_dev) return lu_dev->ld_obd->obd_name; } -static inline bool filename_is_volatile(const char *name, int namelen, int *idx) +static inline bool filename_is_volatile(const char *name, size_t namelen, + int *idx) { const char *start; char *end; diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index 6fc54bd..3d081cf 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -1358,9 +1358,9 @@ static inline int md_close(struct obd_export *exp, struct md_op_data *op_data, } static inline int md_create(struct obd_export *exp, struct md_op_data *op_data, - const void *data, int datalen, int mode, __u32 uid, - __u32 gid, cfs_cap_t cap_effective, __u64 rdev, - struct ptlrpc_request **request) + const void *data, size_t datalen, umode_t mode, + uid_t uid, gid_t gid, cfs_cap_t cap_effective, + __u64 rdev, struct ptlrpc_request **request) { int rc; @@ -1440,8 +1440,8 @@ static inline int md_link(struct obd_export *exp, struct md_op_data *op_data, } static inline int md_rename(struct obd_export *exp, struct md_op_data *op_data, - const char *old, int oldlen, const char *new, - int newlen, struct ptlrpc_request **request) + const char *old, size_t oldlen, const char *new, + size_t newlen, struct ptlrpc_request **request) { int rc; @@ -1453,7 +1453,7 @@ static inline int md_rename(struct obd_export *exp, struct md_op_data *op_data, } static inline int md_setattr(struct obd_export *exp, struct md_op_data *op_data, - void *ea, int ealen, void *ea2, int ea2len, + void *ea, size_t ealen, void *ea2, size_t ea2len, struct ptlrpc_request **request, struct md_open_data **mod) { diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index cd639f4..a68bea1 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -868,8 +868,8 @@ enum { struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, struct inode *i1, struct inode *i2, - const char *name, int namelen, - int mode, __u32 opc, void *data); + const char *name, size_t namelen, + u32 mode, __u32 opc, void *data); void ll_finish_md_op_data(struct md_op_data *op_data); int ll_get_obd_name(struct inode *inode, unsigned int cmd, unsigned long arg); char *ll_get_fsname(struct super_block *sb, char *buf, int buflen); diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index c498748..e46214f 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -2324,8 +2324,8 @@ int ll_process_config(struct lustre_cfg *lcfg) /* this function prepares md_op_data hint for passing ot down to MD stack. */ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, struct inode *i1, struct inode *i2, - const char *name, int namelen, - int mode, __u32 opc, void *data) + const char *name, size_t namelen, + u32 mode, __u32 opc, void *data) { if (!name) { /* Do not reuse namelen for something else. */ diff --git a/drivers/staging/lustre/lustre/lmv/lmv_intent.c b/drivers/staging/lustre/lustre/lmv/lmv_intent.c index 6845a5e..a96b49d 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_intent.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_intent.c @@ -520,8 +520,9 @@ int lmv_intent_lock(struct obd_export *exp, struct md_op_data *op_data, LASSERT(fid_is_sane(&op_data->op_fid1)); CDEBUG(D_INODE, "INTENT LOCK '%s' for "DFID" '%*s' on "DFID"\n", - LL_IT2STR(it), PFID(&op_data->op_fid2), op_data->op_namelen, - op_data->op_name, PFID(&op_data->op_fid1)); + LL_IT2STR(it), PFID(&op_data->op_fid2), + (int)op_data->op_namelen, op_data->op_name, + PFID(&op_data->op_fid1)); rc = lmv_check_connect(obd); if (rc) diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 0ffb653..0337f05 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -245,8 +245,8 @@ static int lmv_connect(const struct lu_env *env, return rc; } -static int lmv_init_ea_size(struct obd_export *exp, int easize, - int def_easize, int cookiesize, int def_cookiesize) +static int lmv_init_ea_size(struct obd_export *exp, u32 easize, u32 def_easize, + u32 cookiesize, u32 def_cookiesize) { struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; @@ -1660,9 +1660,9 @@ lmv_locate_mds(struct lmv_obd *lmv, struct md_op_data *op_data, } static int lmv_create(struct obd_export *exp, struct md_op_data *op_data, - const void *data, int datalen, int mode, __u32 uid, - __u32 gid, cfs_cap_t cap_effective, __u64 rdev, - struct ptlrpc_request **request) + const void *data, size_t datalen, umode_t mode, + uid_t uid, gid_t gid, cfs_cap_t cap_effective, + __u64 rdev, struct ptlrpc_request **request) { struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; @@ -1681,8 +1681,8 @@ static int lmv_create(struct obd_export *exp, struct md_op_data *op_data, return PTR_ERR(tgt); CDEBUG(D_INODE, "CREATE name '%.*s' on "DFID" -> mds #%x\n", - op_data->op_namelen, op_data->op_name, PFID(&op_data->op_fid1), - op_data->op_mds); + (int)op_data->op_namelen, op_data->op_name, + PFID(&op_data->op_fid1), op_data->op_mds); rc = lmv_fid_alloc(NULL, exp, &op_data->op_fid2, op_data); if (rc) @@ -1785,8 +1785,8 @@ lmv_getattr_name(struct obd_export *exp, struct md_op_data *op_data, return PTR_ERR(tgt); CDEBUG(D_INODE, "GETATTR_NAME for %*s on " DFID " -> mds #%u\n", - op_data->op_namelen, op_data->op_name, PFID(&op_data->op_fid1), - tgt->ltd_idx); + (int)op_data->op_namelen, op_data->op_name, + PFID(&op_data->op_fid1), tgt->ltd_idx); rc = md_getattr_name(tgt->ltd_exp, op_data, preq); if (rc != 0) @@ -1879,7 +1879,7 @@ static int lmv_link(struct obd_export *exp, struct md_op_data *op_data, LASSERT(op_data->op_namelen != 0); CDEBUG(D_INODE, "LINK "DFID":%*s to "DFID"\n", - PFID(&op_data->op_fid2), op_data->op_namelen, + PFID(&op_data->op_fid2), (int)op_data->op_namelen, op_data->op_name, PFID(&op_data->op_fid1)); op_data->op_fsuid = from_kuid(&init_user_ns, current_fsuid()); @@ -1916,7 +1916,8 @@ static int lmv_link(struct obd_export *exp, struct md_op_data *op_data, } static int lmv_rename(struct obd_export *exp, struct md_op_data *op_data, - const char *old, int oldlen, const char *new, int newlen, + const char *old, size_t oldlen, + const char *new, size_t newlen, struct ptlrpc_request **request) { struct obd_device *obd = exp->exp_obd; @@ -1927,9 +1928,9 @@ static int lmv_rename(struct obd_export *exp, struct md_op_data *op_data, LASSERT(oldlen != 0); CDEBUG(D_INODE, "RENAME %.*s in "DFID":%d to %.*s in "DFID":%d\n", - oldlen, old, PFID(&op_data->op_fid1), + (int)oldlen, old, PFID(&op_data->op_fid1), op_data->op_mea1 ? op_data->op_mea1->lsm_md_stripe_count : 0, - newlen, new, PFID(&op_data->op_fid2), + (int)newlen, new, PFID(&op_data->op_fid2), op_data->op_mea2 ? op_data->op_mea2->lsm_md_stripe_count : 0); rc = lmv_check_connect(obd); @@ -2035,7 +2036,7 @@ static int lmv_rename(struct obd_export *exp, struct md_op_data *op_data, } static int lmv_setattr(struct obd_export *exp, struct md_op_data *op_data, - void *ea, int ealen, void *ea2, int ea2len, + void *ea, size_t ealen, void *ea2, size_t ea2len, struct ptlrpc_request **request, struct md_open_data **mod) { diff --git a/drivers/staging/lustre/lustre/mdc/mdc_internal.h b/drivers/staging/lustre/lustre/mdc/mdc_internal.h index c10441d..f446c1c 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_internal.h +++ b/drivers/staging/lustre/lustre/mdc/mdc_internal.h @@ -38,25 +38,26 @@ void lprocfs_mdc_init_vars(struct lprocfs_static_vars *lvars); void mdc_pack_body(struct ptlrpc_request *req, const struct lu_fid *fid, - __u64 valid, int ea_size, __u32 suppgid, int flags); + __u64 valid, size_t ea_size, __u32 suppgid, u32 flags); void mdc_swap_layouts_pack(struct ptlrpc_request *req, struct md_op_data *op_data); -void mdc_readdir_pack(struct ptlrpc_request *req, __u64 pgoff, __u32 size, +void mdc_readdir_pack(struct ptlrpc_request *req, __u64 pgoff, size_t size, const struct lu_fid *fid); -void mdc_getattr_pack(struct ptlrpc_request *req, __u64 valid, int flags, - struct md_op_data *data, int ea_size); +void mdc_getattr_pack(struct ptlrpc_request *req, __u64 valid, u32 flags, + struct md_op_data *data, size_t ea_size); void mdc_setattr_pack(struct ptlrpc_request *req, struct md_op_data *op_data, - void *ea, int ealen, void *ea2, int ea2len); + void *ea, size_t ealen, void *ea2, size_t ea2len); void mdc_create_pack(struct ptlrpc_request *req, struct md_op_data *op_data, - const void *data, int datalen, __u32 mode, __u32 uid, - __u32 gid, cfs_cap_t capability, __u64 rdev); + const void *data, size_t datalen, umode_t mode, uid_t uid, + gid_t gid, cfs_cap_t capability, __u64 rdev); void mdc_open_pack(struct ptlrpc_request *req, struct md_op_data *op_data, - __u32 mode, __u64 rdev, __u64 flags, const void *data, - int datalen); + umode_t mode, __u64 rdev, __u64 flags, const void *data, + size_t datalen); void mdc_unlink_pack(struct ptlrpc_request *req, struct md_op_data *op_data); void mdc_link_pack(struct ptlrpc_request *req, struct md_op_data *op_data); void mdc_rename_pack(struct ptlrpc_request *req, struct md_op_data *op_data, - const char *old, int oldlen, const char *new, int newlen); + const char *old, size_t oldlen, + const char *new, size_t newlen); void mdc_close_pack(struct ptlrpc_request *req, struct md_op_data *op_data); /* mdc/mdc_locks.c */ @@ -94,16 +95,17 @@ void mdc_commit_open(struct ptlrpc_request *req); void mdc_replay_open(struct ptlrpc_request *req); int mdc_create(struct obd_export *exp, struct md_op_data *op_data, - const void *data, int datalen, int mode, __u32 uid, __u32 gid, - cfs_cap_t capability, __u64 rdev, + const void *data, size_t datalen, umode_t mode, uid_t uid, + gid_t gid, cfs_cap_t capability, __u64 rdev, struct ptlrpc_request **request); int mdc_link(struct obd_export *exp, struct md_op_data *op_data, struct ptlrpc_request **request); int mdc_rename(struct obd_export *exp, struct md_op_data *op_data, - const char *old, int oldlen, const char *new, int newlen, + const char *old, size_t oldlen, + const char *new, size_t newlen, struct ptlrpc_request **request); int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data, - void *ea, int ealen, void *ea2, int ea2len, + void *ea, size_t ealen, void *ea2, size_t ea2len, struct ptlrpc_request **request, struct md_open_data **mod); int mdc_unlink(struct obd_export *exp, struct md_op_data *op_data, struct ptlrpc_request **request); diff --git a/drivers/staging/lustre/lustre/mdc/mdc_lib.c b/drivers/staging/lustre/lustre/mdc/mdc_lib.c index ecfe13e..82d1c4d 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_lib.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_lib.c @@ -58,7 +58,7 @@ void mdc_swap_layouts_pack(struct ptlrpc_request *req, } void mdc_pack_body(struct ptlrpc_request *req, const struct lu_fid *fid, - __u64 valid, int ea_size, __u32 suppgid, int flags) + __u64 valid, size_t ea_size, __u32 suppgid, u32 flags) { struct mdt_body *b = req_capsule_client_get(&req->rq_pill, &RMF_MDT_BODY); @@ -103,8 +103,8 @@ static void mdc_pack_name(struct ptlrpc_request *req, LASSERT(cpy_len == name_len && lu_name_is_valid_2(buf, cpy_len)); } -void mdc_readdir_pack(struct ptlrpc_request *req, __u64 pgoff, - __u32 size, const struct lu_fid *fid) +void mdc_readdir_pack(struct ptlrpc_request *req, __u64 pgoff, size_t size, + const struct lu_fid *fid) { struct mdt_body *b = req_capsule_client_get(&req->rq_pill, &RMF_MDT_BODY); @@ -118,8 +118,8 @@ void mdc_readdir_pack(struct ptlrpc_request *req, __u64 pgoff, /* packing of MDS records */ void mdc_create_pack(struct ptlrpc_request *req, struct md_op_data *op_data, - const void *data, int datalen, __u32 mode, - __u32 uid, __u32 gid, cfs_cap_t cap_effective, __u64 rdev) + const void *data, size_t datalen, umode_t mode, + uid_t uid, gid_t gid, cfs_cap_t cap_effective, __u64 rdev) { struct mdt_rec_create *rec; char *tmp; @@ -153,7 +153,7 @@ void mdc_create_pack(struct ptlrpc_request *req, struct md_op_data *op_data, } } -static __u64 mds_pack_open_flags(__u64 flags, __u32 mode) +static inline __u64 mds_pack_open_flags(__u64 flags) { __u64 cr_flags = (flags & (FMODE_READ | FMODE_WRITE | MDS_OPEN_FL_INTERNAL)); @@ -182,8 +182,8 @@ static __u64 mds_pack_open_flags(__u64 flags, __u32 mode) /* packing of MDS records */ void mdc_open_pack(struct ptlrpc_request *req, struct md_op_data *op_data, - __u32 mode, __u64 rdev, __u64 flags, const void *lmm, - int lmmlen) + umode_t mode, __u64 rdev, __u64 flags, const void *lmm, + size_t lmmlen) { struct mdt_rec_create *rec; char *tmp; @@ -201,7 +201,7 @@ void mdc_open_pack(struct ptlrpc_request *req, struct md_op_data *op_data, rec->cr_fid2 = op_data->op_fid2; rec->cr_mode = mode; - cr_flags = mds_pack_open_flags(flags, mode); + cr_flags = mds_pack_open_flags(flags); rec->cr_rdev = rdev; rec->cr_time = op_data->op_mod_time; rec->cr_suppgid1 = op_data->op_suppgids[0]; @@ -307,7 +307,7 @@ static void mdc_ioepoch_pack(struct mdt_ioepoch *epoch, } void mdc_setattr_pack(struct ptlrpc_request *req, struct md_op_data *op_data, - void *ea, int ealen, void *ea2, int ea2len) + void *ea, size_t ealen, void *ea2, size_t ea2len) { struct mdt_rec_setattr *rec; struct mdt_ioepoch *epoch; @@ -388,7 +388,8 @@ void mdc_link_pack(struct ptlrpc_request *req, struct md_op_data *op_data) } void mdc_rename_pack(struct ptlrpc_request *req, struct md_op_data *op_data, - const char *old, int oldlen, const char *new, int newlen) + const char *old, size_t oldlen, + const char *new, size_t newlen) { struct mdt_rec_rename *rec; @@ -416,8 +417,8 @@ void mdc_rename_pack(struct ptlrpc_request *req, struct md_op_data *op_data, mdc_pack_name(req, &RMF_SYMTGT, new, newlen); } -void mdc_getattr_pack(struct ptlrpc_request *req, __u64 valid, int flags, - struct md_op_data *op_data, int ea_size) +void mdc_getattr_pack(struct ptlrpc_request *req, __u64 valid, u32 flags, + struct md_op_data *op_data, size_t ea_size) { struct mdt_body *b = req_capsule_client_get(&req->rq_pill, &RMF_MDT_BODY); diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index 54de46b..f1f6c08 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -235,7 +235,7 @@ mdc_intent_open_pack(struct obd_export *exp, struct lookup_intent *it, struct obd_device *obddev = class_exp2obd(exp); struct ldlm_intent *lit; const void *lmm = op_data->op_data; - int lmmsize = op_data->op_data_size; + u32 lmmsize = op_data->op_data_size; LIST_HEAD(cancels); int count = 0; int mode; @@ -317,7 +317,8 @@ mdc_intent_getxattr_pack(struct obd_export *exp, { struct ptlrpc_request *req; struct ldlm_intent *lit; - int rc, count = 0, maxdata; + int rc, count = 0; + u32 maxdata; LIST_HEAD(cancels); req = ptlrpc_request_alloc(class_exp2cliimp(exp), @@ -402,7 +403,7 @@ static struct ptlrpc_request *mdc_intent_getattr_pack(struct obd_export *exp, OBD_MD_MEA | OBD_MD_FLACL; struct ldlm_intent *lit; int rc; - int easize; + u32 easize; req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_LDLM_INTENT_GETATTR); @@ -507,7 +508,7 @@ static int mdc_finish_enqueue(struct obd_export *exp, struct ldlm_reply *lockrep; struct ldlm_lock *lock; void *lvb_data = NULL; - int lvb_len = 0; + u32 lvb_len = 0; LASSERT(rc >= 0); /* Similarly, if we're going to replay this request, we don't want to @@ -952,8 +953,8 @@ static int mdc_finish_intent_lock(struct obd_export *exp, } CDEBUG(D_DENTRY, "D_IT dentry %.*s intent: %s status %d disp %x rc %d\n", - op_data->op_namelen, op_data->op_name, ldlm_it2str(it->it_op), - it->it_status, it->it_disposition, rc); + (int)op_data->op_namelen, op_data->op_name, + ldlm_it2str(it->it_op), it->it_status, it->it_disposition, rc); return rc; } @@ -1067,7 +1068,7 @@ int mdc_intent_lock(struct obd_export *exp, struct md_op_data *op_data, LASSERT(it); CDEBUG(D_DLMTRACE, "(name: %.*s,"DFID") in obj "DFID - ", intent: %s flags %#Lo\n", op_data->op_namelen, + ", intent: %s flags %#Lo\n", (int)op_data->op_namelen, op_data->op_name, PFID(&op_data->op_fid2), PFID(&op_data->op_fid1), ldlm_it2str(it->it_op), it->it_flags); @@ -1177,8 +1178,8 @@ int mdc_intent_getattr_async(struct obd_export *exp, CDEBUG(D_DLMTRACE, "name: %.*s in inode " DFID ", intent: %s flags %#Lo\n", - op_data->op_namelen, op_data->op_name, PFID(&op_data->op_fid1), - ldlm_it2str(it->it_op), it->it_flags); + (int)op_data->op_namelen, op_data->op_name, + PFID(&op_data->op_fid1), ldlm_it2str(it->it_op), it->it_flags); fid_build_reg_res_name(&op_data->op_fid1, &res_id); req = mdc_intent_getattr_pack(exp, it, op_data); diff --git a/drivers/staging/lustre/lustre/mdc/mdc_reint.c b/drivers/staging/lustre/lustre/mdc/mdc_reint.c index af5c92c..c921e47 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_reint.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_reint.c @@ -99,7 +99,7 @@ int mdc_resource_get_unused(struct obd_export *exp, const struct lu_fid *fid, } int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data, - void *ea, int ealen, void *ea2, int ea2len, + void *ea, size_t ealen, void *ea2, size_t ea2len, struct ptlrpc_request **request, struct md_open_data **mod) { LIST_HEAD(cancels); @@ -196,9 +196,9 @@ int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data, } int mdc_create(struct obd_export *exp, struct md_op_data *op_data, - const void *data, int datalen, int mode, __u32 uid, __u32 gid, - cfs_cap_t cap_effective, __u64 rdev, - struct ptlrpc_request **request) + const void *data, size_t datalen, umode_t mode, + uid_t uid, gid_t gid, cfs_cap_t cap_effective, + __u64 rdev, struct ptlrpc_request **request) { struct ptlrpc_request *req; int level, rc; @@ -389,7 +389,7 @@ int mdc_link(struct obd_export *exp, struct md_op_data *op_data, } int mdc_rename(struct obd_export *exp, struct md_op_data *op_data, - const char *old, int oldlen, const char *new, int newlen, + const char *old, size_t oldlen, const char *new, size_t newlen, struct ptlrpc_request **request) { LIST_HEAD(cancels); diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 157fdc0..e622b7a 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -447,7 +447,7 @@ static int mdc_get_lustre_md(struct obd_export *exp, if (rc < 0) goto out; - if (rc < sizeof(*md->lsm)) { + if (rc < (typeof(rc))sizeof(*md->lsm)) { CDEBUG(D_INFO, "lsm size too small: rc < sizeof (*md->lsm) (%d < %d)\n", rc, (int)sizeof(*md->lsm)); @@ -485,7 +485,7 @@ static int mdc_get_lustre_md(struct obd_export *exp, if (rc < 0) goto out; - if (rc < sizeof(*md->lmv)) { + if (rc < (typeof(rc))sizeof(*md->lmv)) { CDEBUG(D_INFO, "size too small: rc < sizeof(*md->lmv) (%d < %d)\n", rc, (int)sizeof(*md->lmv)); @@ -1843,7 +1843,7 @@ out: return rc; } -static struct kuc_hdr *changelog_kuc_hdr(char *buf, int len, int flags) +static struct kuc_hdr *changelog_kuc_hdr(char *buf, size_t len, u32 flags) { struct kuc_hdr *lh = (struct kuc_hdr *)buf; @@ -1876,7 +1876,8 @@ static int changelog_kkuc_cb(const struct lu_env *env, struct llog_handle *llh, struct changelog_show *cs = data; struct llog_changelog_rec *rec = (struct llog_changelog_rec *)hdr; struct kuc_hdr *lh; - int len, rc; + size_t len; + int rc; if (rec->cr_hdr.lrh_type != CHANGELOG_REC) { rc = -EINVAL; @@ -1907,7 +1908,7 @@ static int changelog_kkuc_cb(const struct lu_env *env, struct llog_handle *llh, memcpy(lh + 1, &rec->cr, len - sizeof(*lh)); rc = libcfs_kkuc_msg_put(cs->cs_fp, lh); - CDEBUG(D_HSM, "kucmsg fp %p len %d rc %d\n", cs->cs_fp, len, rc); + CDEBUG(D_HSM, "kucmsg fp %p len %zu rc %d\n", cs->cs_fp, len, rc); return rc; } @@ -2369,7 +2370,7 @@ static void lustre_swab_hai(struct hsm_action_item *h) static void lustre_swab_hal(struct hsm_action_list *h) { struct hsm_action_item *hai; - int i; + u32 i; __swab32s(&h->hal_version); __swab32s(&h->hal_count); @@ -2418,14 +2419,14 @@ static int mdc_ioc_hsm_ct_start(struct obd_export *exp, * @param val KUC message (kuc_hdr + hsm_action_list) * @param len total length of message */ -static int mdc_hsm_copytool_send(int len, void *val) +static int mdc_hsm_copytool_send(size_t len, void *val) { struct kuc_hdr *lh = (struct kuc_hdr *)val; struct hsm_action_list *hal = (struct hsm_action_list *)(lh + 1); if (len < sizeof(*lh) + sizeof(*hal)) { - CERROR("Short HSM message %d < %d\n", len, - (int)(sizeof(*lh) + sizeof(*hal))); + CERROR("Short HSM message %zu < %zu\n", len, + sizeof(*lh) + sizeof(*hal)); return -EPROTO; } if (lh->kuc_magic == __swab16(KUC_MAGIC)) { @@ -2528,18 +2529,18 @@ static int mdc_get_info(const struct lu_env *env, struct obd_export *exp, int rc = -EINVAL; if (KEY_IS(KEY_MAX_EASIZE)) { - int mdsize, *max_easize; + u32 mdsize, *max_easize; if (*vallen != sizeof(int)) return -EINVAL; - mdsize = *(int *)val; + mdsize = *(u32 *)val; if (mdsize > exp->exp_obd->u.cli.cl_max_mds_easize) exp->exp_obd->u.cli.cl_max_mds_easize = mdsize; max_easize = val; *max_easize = exp->exp_obd->u.cli.cl_max_mds_easize; return 0; } else if (KEY_IS(KEY_DEFAULT_EASIZE)) { - int *default_easize; + u32 *default_easize; if (*vallen != sizeof(int)) return -EINVAL; @@ -2556,7 +2557,7 @@ static int mdc_get_info(const struct lu_env *env, struct obd_export *exp, *data = imp->imp_connect_data; return 0; } else if (KEY_IS(KEY_TGT_COUNT)) { - *((int *)val) = 1; + *((u32 *)val) = 1; return 0; } @@ -2784,8 +2785,8 @@ err_rpc_lock: * a large number of stripes is possible. If a larger reply buffer is * required it will be reallocated in the ptlrpc layer due to overflow. */ -static int mdc_init_ea_size(struct obd_export *exp, int easize, - int def_easize, int cookiesize, int def_cookiesize) +static int mdc_init_ea_size(struct obd_export *exp, u32 easize, u32 def_easize, + u32 cookiesize, u32 def_cookiesize) { struct obd_device *obd = exp->exp_obd; struct client_obd *cli = &obd->u.cli; -- cgit v0.10.2 From 3cbbf5eddbf69dffae0e1eba63f2f3eb7fe9f1a1 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Sun, 18 Sep 2016 16:38:00 -0400 Subject: staging: lustre: obd: cleanup struct md_op_data and uses Make the following changes in or around struct md_op_data: * rename enum op_cli_flags to enum md_cli_flags. * Change to type of the op_flags member from __u32 to enum md_op_flags. * Remove the used but never set member op_npages. * Remove the set but never used member op_stripe_offset (an alias for op_ioepoch). * Remove the op_max_pages alias for op_valid and add a op_max_pages member. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2675 Reviewed-on: http://review.whamcloud.com/11734 Reviewed-by: Bob Glossman <bob.glossman@intel.com> Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: Dmitry Eremin <dmitry.eremin@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 8a7c803..2d25e40 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -736,6 +736,14 @@ static inline int it_to_lock_mode(struct lookup_intent *it) return -EINVAL; } +enum md_cli_flags { + CLI_SET_MEA = BIT(0), + CLI_RM_ENTRY = BIT(1), + CLI_HASH64 = BIT(2), + CLI_API32 = BIT(3), + CLI_MIGRATE = BIT(4), +}; + struct md_op_data { struct lu_fid op_fid1; /* operation fid1 (usually parent) */ struct lu_fid op_fid2; /* operation fid2 (usually child) */ @@ -773,35 +781,24 @@ struct md_op_data { __u64 op_offset; /* Used by readdir */ - __u32 op_npages; + __u32 op_max_pages; /* used to transfer info between the stacks of MD client * see enum op_cli_flags */ - __u32 op_cli_flags; + enum md_cli_flags op_cli_flags; /* File object data version for HSM release, on client */ __u64 op_data_version; struct lustre_handle op_lease_handle; }; -#define op_stripe_offset op_ioepoch -#define op_max_pages op_valid - struct md_callback { int (*md_blocking_ast)(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, void *data, int flag); }; -enum op_cli_flags { - CLI_SET_MEA = 1 << 0, - CLI_RM_ENTRY = 1 << 1, - CLI_HASH64 = BIT(2), - CLI_API32 = BIT(3), - CLI_MIGRATE = BIT(4), -}; - struct md_enqueue_info; /* metadata stat-ahead */ diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index e622b7a..1721925 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -1264,8 +1264,7 @@ static int mdc_read_page_remote(void *data, struct page *page0) lu_pgs >>= LU_PAGE_SHIFT; LASSERT(!(req->rq_bulk->bd_nob_transferred & ~LU_PAGE_MASK)); - CDEBUG(D_INODE, "read %d(%d)/%d pages\n", rd_pgs, lu_pgs, - op_data->op_npages); + CDEBUG(D_INODE, "read %d(%d) pages\n", rd_pgs, lu_pgs); mdc_adjust_dirpages(page_pool, rd_pgs, lu_pgs); -- cgit v0.10.2 From df3c30f6e9044fef7a7e508dad940c8e0f3346fa Mon Sep 17 00:00:00 2001 From: Jian Yu <jian.yu@intel.com> Date: Sun, 18 Sep 2016 16:38:01 -0400 Subject: staging: lustre: replace direct HZ access with kernel APIs On some customer's systems, kernel was compiled with HZ defined to 100, instead of 1000. This improves performance for HPC applications. However, to use these systems with Lustre, customers have to re-build Lustre for the kernel because Lustre directly uses the defined constant HZ. Since kernel 2.6.21, some non-HZ dependent timing APIs become non- inline functions, which can be used in Lustre codes to replace the direct HZ access. These kernel APIs include: jiffies_to_msecs() jiffies_to_usecs() jiffies_to_timespec() msecs_to_jiffies() usecs_to_jiffies() timespec_to_jiffies() And here are some samples of the replacement: HZ -> msecs_to_jiffies(MSEC_PER_SEC) n * HZ -> msecs_to_jiffies(n * MSEC_PER_SEC) HZ / n -> msecs_to_jiffies(MSEC_PER_SEC / n) n / HZ -> jiffies_to_msecs(n) / MSEC_PER_SEC n / HZ * 1000 -> jiffies_to_msecs(n) This patch replaces the direct HZ access in lustre modules. Signed-off-by: Jian Yu <jian.yu@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5443 Reviewed-on: http://review.whamcloud.com/12052 Reviewed-by: Bob Glossman <bob.glossman@intel.com> Reviewed-by: Dmitry Eremin <dmitry.eremin@intel.com> Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: Nathaniel Clark <nathaniel.l.clark@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c index 912cd68..a09c25a 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c @@ -880,7 +880,8 @@ static int __ldlm_namespace_free(struct ldlm_namespace *ns, int force) ldlm_ns_name(ns), atomic_read(&ns->ns_bref)); force_wait: if (force) - lwi = LWI_TIMEOUT(obd_timeout * HZ / 4, NULL, NULL); + lwi = LWI_TIMEOUT(msecs_to_jiffies(obd_timeout * + MSEC_PER_SEC) / 4, NULL, NULL); rc = l_wait_event(ns->ns_waitq, atomic_read(&ns->ns_bref) == 0, &lwi); diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c index 8cc0bfa..1867fd5 100644 --- a/drivers/staging/lustre/lustre/llite/statahead.c +++ b/drivers/staging/lustre/lustre/llite/statahead.c @@ -1154,7 +1154,8 @@ out: */ while (sai->sai_sent != sai->sai_replied) { /* in case we're not woken up, timeout wait */ - lwi = LWI_TIMEOUT(HZ >> 3, NULL, NULL); + lwi = LWI_TIMEOUT(msecs_to_jiffies(MSEC_PER_SEC >> 3), + NULL, NULL); l_wait_event(thread->t_ctl_waitq, sai->sai_sent == sai->sai_replied, &lwi); } diff --git a/drivers/staging/lustre/lustre/mgc/mgc_request.c b/drivers/staging/lustre/lustre/mgc/mgc_request.c index f3d4f7f..88d4d10 100644 --- a/drivers/staging/lustre/lustre/mgc/mgc_request.c +++ b/drivers/staging/lustre/lustre/mgc/mgc_request.c @@ -549,8 +549,9 @@ static int mgc_requeue_thread(void *data) * caused the lock revocation to finish its setup, plus some * random so everyone doesn't try to reconnect at once. */ - to = MGC_TIMEOUT_MIN_SECONDS * HZ; - to += rand * HZ / 100; /* rand is centi-seconds */ + to = msecs_to_jiffies(MGC_TIMEOUT_MIN_SECONDS * MSEC_PER_SEC); + /* rand is centi-seconds */ + to += msecs_to_jiffies(rand * MSEC_PER_SEC / 100); lwi = LWI_TIMEOUT(to, NULL, NULL); l_wait_event(rq_waitq, rq_state & (RQ_STOP | RQ_PRECLEANUP), &lwi); diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec.c b/drivers/staging/lustre/lustre/ptlrpc/sec.c index dbd819f..523579f 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec.c @@ -499,7 +499,7 @@ static int sptlrpc_req_replace_dead_ctx(struct ptlrpc_request *req) newctx, newctx->cc_flags); set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); + schedule_timeout(msecs_to_jiffies(MSEC_PER_SEC)); } else { /* * it's possible newctx == oldctx if we're switching @@ -718,8 +718,9 @@ again: req->rq_restart = 0; spin_unlock(&req->rq_lock); - lwi = LWI_TIMEOUT_INTR(timeout * HZ, ctx_refresh_timeout, - ctx_refresh_interrupt, req); + lwi = LWI_TIMEOUT_INTR(msecs_to_jiffies(timeout * MSEC_PER_SEC), + ctx_refresh_timeout, ctx_refresh_interrupt, + req); rc = l_wait_event(req->rq_reply_waitq, ctx_check_refresh(ctx), &lwi); /* diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c index fdb32d5..6adf274 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c @@ -139,7 +139,7 @@ int sptlrpc_proc_enc_pool_seq_show(struct seq_file *m, void *v) "cache missing: %lu\n" "low free mark: %lu\n" "max waitqueue depth: %u\n" - "max wait time: %ld/%u\n", + "max wait time: %ld/%lu\n", totalram_pages, PAGES_PER_POOL, page_pools.epp_max_pages, @@ -158,7 +158,7 @@ int sptlrpc_proc_enc_pool_seq_show(struct seq_file *m, void *v) page_pools.epp_st_lowfree, page_pools.epp_st_max_wqlen, page_pools.epp_st_max_wait, - HZ); + msecs_to_jiffies(MSEC_PER_SEC)); spin_unlock(&page_pools.epp_lock); @@ -432,12 +432,13 @@ void sptlrpc_enc_pool_fini(void) if (page_pools.epp_st_access > 0) { CDEBUG(D_SEC, - "max pages %lu, grows %u, grow fails %u, shrinks %u, access %lu, missing %lu, max qlen %u, max wait %ld/%d\n", + "max pages %lu, grows %u, grow fails %u, shrinks %u, access %lu, missing %lu, max qlen %u, max wait %ld/%ld\n", page_pools.epp_st_max_pages, page_pools.epp_st_grows, page_pools.epp_st_grow_fails, page_pools.epp_st_shrinks, page_pools.epp_st_access, page_pools.epp_st_missings, page_pools.epp_st_max_wqlen, - page_pools.epp_st_max_wait, HZ); + page_pools.epp_st_max_wait, + msecs_to_jiffies(MSEC_PER_SEC)); } } diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c b/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c index 9b9801e..f79a889 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c @@ -182,7 +182,8 @@ again: /* check ctx list again before sleep */ sec_process_ctx_list(); - lwi = LWI_TIMEOUT(SEC_GC_INTERVAL * HZ, NULL, NULL); + lwi = LWI_TIMEOUT(msecs_to_jiffies(SEC_GC_INTERVAL * MSEC_PER_SEC), + NULL, NULL); l_wait_event(thread->t_ctl_waitq, thread_is_stopping(thread) || thread_is_signal(thread), -- cgit v0.10.2 From 6f5083978b71b83849e8937e722ef41d0849a398 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin <dmitry.eremin@intel.com> Date: Sun, 18 Sep 2016 16:38:02 -0400 Subject: staging: lustre: ldlm: count of pools is unsigned long Function ldlm_pools_count() return unsigned long but counter is int. Use ldlm_pool_granted() everywhere. Signed-off-by: Dmitry Eremin <dmitry.eremin@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5577 Reviewed-on: http://review.whamcloud.com/12304 Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c index 2fc319e..1147b30 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c @@ -792,7 +792,8 @@ static struct completion ldlm_pools_comp; */ static unsigned long ldlm_pools_count(ldlm_side_t client, gfp_t gfp_mask) { - int total = 0, nr_ns; + unsigned long total = 0; + int nr_ns; struct ldlm_namespace *ns; struct ldlm_namespace *ns_old = NULL; /* loop detection */ void *cookie; -- cgit v0.10.2 From 8060c90186ec2d609b3ef3b2799e22f5a82ae55d Mon Sep 17 00:00:00 2001 From: Dmitry Eremin <dmitry.eremin@intel.com> Date: Sun, 18 Sep 2016 16:38:03 -0400 Subject: staging: lustre: lu_dirent_calc_size() return type to size_t Change the type accordant usage. Signed-off-by: Dmitry Eremin <dmitry.eremin@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5577 Reviewed-on: http://review.whamcloud.com/12383 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index a0ca571..445b813 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -1013,12 +1013,12 @@ static inline struct lu_dirent *lu_dirent_next(struct lu_dirent *ent) return next; } -static inline int lu_dirent_calc_size(int namelen, __u16 attr) +static inline size_t lu_dirent_calc_size(size_t namelen, __u16 attr) { - int size; + size_t size; if (attr & LUDA_TYPE) { - const unsigned align = sizeof(struct luda_type) - 1; + const size_t align = sizeof(struct luda_type) - 1; size = (sizeof(struct lu_dirent) + namelen + align) & ~align; size += sizeof(struct luda_type); @@ -1029,15 +1029,6 @@ static inline int lu_dirent_calc_size(int namelen, __u16 attr) return (size + 7) & ~7; } -static inline int lu_dirent_size(const struct lu_dirent *ent) -{ - if (le16_to_cpu(ent->lde_reclen) == 0) { - return lu_dirent_calc_size(le16_to_cpu(ent->lde_namelen), - le32_to_cpu(ent->lde_attrs)); - } - return le16_to_cpu(ent->lde_reclen); -} - #define MDS_DIR_END_OFF 0xfffffffffffffffeULL /** -- cgit v0.10.2 From 8e30ac1e43ca84006ec7d5a5f65bc87da858e3a1 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin <dmitry.eremin@intel.com> Date: Sun, 18 Sep 2016 16:38:04 -0400 Subject: staging: lustre: obdclass: change lu_site->ls_purge_start to unsigned Change the type accordant usage. Signed-off-by: Dmitry Eremin <dmitry.eremin@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5577 Reviewed-on: http://review.whamcloud.com/12384 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lu_object.h b/drivers/staging/lustre/lustre/include/lu_object.h index 7b37cae..260643e 100644 --- a/drivers/staging/lustre/lustre/include/lu_object.h +++ b/drivers/staging/lustre/lustre/include/lu_object.h @@ -602,7 +602,7 @@ struct lu_site { /** * index of bucket on hash table while purging */ - int ls_purge_start; + unsigned int ls_purge_start; /** * Top-level device for this stack. */ diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c index e284e5d..4395117 100644 --- a/drivers/staging/lustre/lustre/obdclass/lu_object.c +++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c @@ -338,7 +338,7 @@ int lu_site_purge(const struct lu_env *env, struct lu_site *s, int nr) struct cfs_hash_bd bd2; struct list_head dispose; int did_sth; - int start; + unsigned int start; int count; int bnr; unsigned int i; -- cgit v0.10.2 From ee5532436a7de5f77e8d0a5c9b52f915ed3a6187 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Sun, 18 Sep 2016 16:38:05 -0400 Subject: staging: lustre: lov: remove LL_IOC_RECREATE_{FID, OBJ} Remove the obsolete ioctls LL_IOC_RECREATE_FID and LL_IOC_RECREATE_OBJ along with their handlers in llite. Remove the then unused OBD method lov_create(). Remove OBD_FL_RECREATE_OBJS handling from osc_create(). Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5814 Reviewed-on: http://review.whamcloud.com/12442 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Bobi Jam <bobijam@gmail.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index 3ef5db0..de52339 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -202,8 +202,8 @@ struct ost_id { #define LL_IOC_LOV_SETSTRIPE _IOW('f', 154, long) #define LL_IOC_LOV_GETSTRIPE _IOW('f', 155, long) #define LL_IOC_LOV_SETEA _IOW('f', 156, long) -#define LL_IOC_RECREATE_OBJ _IOW('f', 157, long) -#define LL_IOC_RECREATE_FID _IOW('f', 157, struct lu_fid) +/* LL_IOC_RECREATE_OBJ 157 obsolete */ +/* LL_IOC_RECREATE_FID 158 obsolete */ #define LL_IOC_GROUP_LOCK _IOW('f', 158, long) #define LL_IOC_GROUP_UNLOCK _IOW('f', 159, long) /* #define LL_IOC_QUOTACHECK 160 OBD_IOC_QUOTACHECK */ diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index fc81551..4b10260 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -1302,88 +1302,6 @@ static ssize_t ll_file_splice_read(struct file *in_file, loff_t *ppos, return result; } -static int ll_lov_recreate(struct inode *inode, struct ost_id *oi, u32 ost_idx) -{ - struct obd_export *exp = ll_i2dtexp(inode); - struct obd_trans_info oti = { 0 }; - struct obdo *oa = NULL; - int lsm_size; - int rc = 0; - struct lov_stripe_md *lsm = NULL, *lsm2; - - oa = kmem_cache_zalloc(obdo_cachep, GFP_NOFS); - if (!oa) - return -ENOMEM; - - lsm = ccc_inode_lsm_get(inode); - if (!lsm_has_objects(lsm)) { - rc = -ENOENT; - goto out; - } - - lsm_size = sizeof(*lsm) + (sizeof(struct lov_oinfo) * - (lsm->lsm_stripe_count)); - - lsm2 = libcfs_kvzalloc(lsm_size, GFP_NOFS); - if (!lsm2) { - rc = -ENOMEM; - goto out; - } - - oa->o_oi = *oi; - oa->o_nlink = ost_idx; - oa->o_flags |= OBD_FL_RECREATE_OBJS; - oa->o_valid = OBD_MD_FLID | OBD_MD_FLFLAGS | OBD_MD_FLGROUP; - obdo_from_inode(oa, inode, OBD_MD_FLTYPE | OBD_MD_FLATIME | - OBD_MD_FLMTIME | OBD_MD_FLCTIME); - obdo_set_parent_fid(oa, &ll_i2info(inode)->lli_fid); - memcpy(lsm2, lsm, lsm_size); - ll_inode_size_lock(inode); - rc = obd_create(NULL, exp, oa, &lsm2, &oti); - ll_inode_size_unlock(inode); - - kvfree(lsm2); - goto out; -out: - ccc_inode_lsm_put(inode, lsm); - kmem_cache_free(obdo_cachep, oa); - return rc; -} - -static int ll_lov_recreate_obj(struct inode *inode, unsigned long arg) -{ - struct ll_recreate_obj ucreat; - struct ost_id oi; - - if (!capable(CFS_CAP_SYS_ADMIN)) - return -EPERM; - - if (copy_from_user(&ucreat, (struct ll_recreate_obj __user *)arg, - sizeof(ucreat))) - return -EFAULT; - - ostid_set_seq_mdt0(&oi); - ostid_set_id(&oi, ucreat.lrc_id); - return ll_lov_recreate(inode, &oi, ucreat.lrc_ost_idx); -} - -static int ll_lov_recreate_fid(struct inode *inode, unsigned long arg) -{ - struct lu_fid fid; - struct ost_id oi; - u32 ost_idx; - - if (!capable(CFS_CAP_SYS_ADMIN)) - return -EPERM; - - if (copy_from_user(&fid, (struct lu_fid __user *)arg, sizeof(fid))) - return -EFAULT; - - fid_to_ostid(&fid, &oi); - ost_idx = (fid_seq(&fid) >> 16) & 0xffff; - return ll_lov_recreate(inode, &oi, ost_idx); -} - int ll_lov_setstripe_ea_info(struct inode *inode, struct dentry *dentry, __u64 flags, struct lov_user_md *lum, int lum_size) @@ -2322,10 +2240,6 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } case LL_IOC_LOV_GETSTRIPE: return ll_lov_getstripe(inode, arg); - case LL_IOC_RECREATE_OBJ: - return ll_lov_recreate_obj(inode, arg); - case LL_IOC_RECREATE_FID: - return ll_lov_recreate_fid(inode, arg); case FSFILT_IOC_FIEMAP: return ll_ioctl_fiemap(inode, arg); case FSFILT_IOC_GETFLAGS: diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index 265be08..a54cd70 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -972,92 +972,6 @@ out: return rc; } -static int lov_recreate(struct obd_export *exp, struct obdo *src_oa, - struct lov_stripe_md **ea, struct obd_trans_info *oti) -{ - struct lov_stripe_md *obj_mdp, *lsm; - struct lov_obd *lov = &exp->exp_obd->u.lov; - unsigned ost_idx; - int rc, i; - - LASSERT(src_oa->o_valid & OBD_MD_FLFLAGS && - src_oa->o_flags & OBD_FL_RECREATE_OBJS); - - obj_mdp = kzalloc(sizeof(*obj_mdp), GFP_NOFS); - if (!obj_mdp) - return -ENOMEM; - - ost_idx = src_oa->o_nlink; - lsm = *ea; - if (!lsm) { - rc = -EINVAL; - goto out; - } - if (ost_idx >= lov->desc.ld_tgt_count || - !lov->lov_tgts[ost_idx]) { - rc = -EINVAL; - goto out; - } - - for (i = 0; i < lsm->lsm_stripe_count; i++) { - struct lov_oinfo *loi = lsm->lsm_oinfo[i]; - - if (lov_oinfo_is_dummy(loi)) - continue; - - if (loi->loi_ost_idx == ost_idx) { - if (ostid_id(&loi->loi_oi) != ostid_id(&src_oa->o_oi)) { - rc = -EINVAL; - goto out; - } - break; - } - } - if (i == lsm->lsm_stripe_count) { - rc = -EINVAL; - goto out; - } - - rc = obd_create(NULL, lov->lov_tgts[ost_idx]->ltd_exp, - src_oa, &obj_mdp, oti); -out: - kfree(obj_mdp); - return rc; -} - -/* the LOV expects oa->o_id to be set to the LOV object id */ -static int lov_create(const struct lu_env *env, struct obd_export *exp, - struct obdo *src_oa, struct lov_stripe_md **ea, - struct obd_trans_info *oti) -{ - struct lov_obd *lov; - int rc = 0; - - LASSERT(ea); - if (!exp) - return -EINVAL; - - if ((src_oa->o_valid & OBD_MD_FLFLAGS) && - src_oa->o_flags == OBD_FL_DELORPHAN) { - /* should be used with LOV anymore */ - LBUG(); - } - - lov = &exp->exp_obd->u.lov; - if (!lov->desc.ld_active_tgt_count) - return -EIO; - - obd_getref(exp->exp_obd); - /* Recreate a specific object id at the given OST index */ - if ((src_oa->o_valid & OBD_MD_FLFLAGS) && - (src_oa->o_flags & OBD_FL_RECREATE_OBJS)) { - rc = lov_recreate(exp, src_oa, ea, oti); - } - - obd_putref(exp->exp_obd); - return rc; -} - #define ASSERT_LSM_MAGIC(lsmp) \ do { \ LASSERT((lsmp)); \ @@ -2281,7 +2195,6 @@ static struct obd_ops lov_obd_ops = { .statfs_async = lov_statfs_async, .packmd = lov_packmd, .unpackmd = lov_unpackmd, - .create = lov_create, .destroy = lov_destroy, .getattr_async = lov_getattr_async, .setattr_async = lov_setattr_async, diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index e965faf..90d6eaa 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -696,11 +696,6 @@ static int osc_create(const struct lu_env *env, struct obd_export *exp, LASSERT(ea); LASSERT(oa->o_valid & OBD_MD_FLGROUP); - if ((oa->o_valid & OBD_MD_FLFLAGS) && - oa->o_flags == OBD_FL_RECREATE_OBJS) { - return osc_real_create(exp, oa, ea, oti); - } - if (!fid_seq_is_mdt(ostid_seq(&oa->o_oi))) return osc_real_create(exp, oa, ea, oti); -- cgit v0.10.2 From bb5c7f2630dec25282f1ef31c3eeb218ee8b323f Mon Sep 17 00:00:00 2001 From: Dmitry Eremin <dmitry.eremin@intel.com> Date: Sun, 18 Sep 2016 16:38:06 -0400 Subject: staging: lustre: changelog: fix comparison between signed and unsigned Change type of changelog_*{namelen,size}() to size_t. Fixed string specifier for unsigned types. Signed-off-by: Dmitry Eremin <dmitry.eremin@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5577 Reviewed-on: http://review.whamcloud.com/12474 Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: James Nunez <james.a.nunez@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index de52339..e8f81a5 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -819,9 +819,9 @@ struct changelog_ext_jobid { char cr_jobid[LUSTRE_JOBID_SIZE]; /**< zero-terminated string. */ }; -static inline unsigned int changelog_rec_offset(enum changelog_rec_flags crf) +static inline size_t changelog_rec_offset(enum changelog_rec_flags crf) { - unsigned int size = sizeof(struct changelog_rec); + size_t size = sizeof(struct changelog_rec); if (crf & CLF_RENAME) size += sizeof(struct changelog_ext_rename); @@ -832,12 +832,12 @@ static inline unsigned int changelog_rec_offset(enum changelog_rec_flags crf) return size; } -static inline int changelog_rec_size(struct changelog_rec *rec) +static inline size_t changelog_rec_size(struct changelog_rec *rec) { return changelog_rec_offset(rec->cr_flags); } -static inline unsigned int changelog_rec_varsize(struct changelog_rec *rec) +static inline size_t changelog_rec_varsize(struct changelog_rec *rec) { return changelog_rec_size(rec) - sizeof(*rec) + rec->cr_namelen; } @@ -869,7 +869,7 @@ static inline char *changelog_rec_name(struct changelog_rec *rec) CLF_SUPPORTED); } -static inline int changelog_rec_snamelen(struct changelog_rec *rec) +static inline size_t changelog_rec_snamelen(struct changelog_rec *rec) { return rec->cr_namelen - strlen(changelog_rec_name(rec)) - 1; } diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 4b10260..a562b11 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -1129,7 +1129,7 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args, struct cl_io *io; ssize_t result; - CDEBUG(D_VFSTRACE, "file: %s, type: %d ppos: %llu, count: %zd\n", + CDEBUG(D_VFSTRACE, "file: %s, type: %d ppos: %llu, count: %zu\n", file->f_path.dentry->d_name.name, iot, *ppos, count); restart: @@ -1207,7 +1207,7 @@ out: * short read/write instead of restart io. */ if ((result == 0 || result == -ENODATA) && io->ci_need_restart) { - CDEBUG(D_VFSTRACE, "Restart %s on %pD from %lld, count:%zd\n", + CDEBUG(D_VFSTRACE, "Restart %s on %pD from %lld, count:%zu\n", iot == CIT_READ ? "read" : "write", file, *ppos, count); LASSERTF(io->ci_nob == 0, "%zd\n", io->ci_nob); -- cgit v0.10.2 From 78e674e679b22f637c05d428891f565717dca504 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Sun, 18 Sep 2016 16:38:07 -0400 Subject: staging: lustre: lov: remove unused {get, set}_info handlers In LOV and OSC remove handlers for the obsolete get and set info keys: KEY_CAPA_KEY, KEY_CONNECT_FLAG, KEY_EVICT_BY_NID, KEY_LAST_ID, KEY_LOCK_TO_STRIPE, KEY_MDS_CONN, KEY_NEXT_ID. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5814 Reviewed-on: http://review.whamcloud.com/12445 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Bobi Jam <bobijam@gmail.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 2d25e40..6eac63e 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -681,20 +681,16 @@ enum obd_cleanup_stage { #define KEY_INTERMDS "inter_mds" #define KEY_LAST_ID "last_id" #define KEY_LAST_FID "last_fid" -#define KEY_LOCK_TO_STRIPE "lock_to_stripe" #define KEY_LOVDESC "lovdesc" #define KEY_MAX_EASIZE "max_easize" #define KEY_DEFAULT_EASIZE "default_easize" -#define KEY_MDS_CONN "mds_conn" #define KEY_MGSSEC "mgssec" -#define KEY_NEXT_ID "next_id" #define KEY_READ_ONLY "read-only" #define KEY_REGISTER_TARGET "register_target" #define KEY_SET_FS "set_fs" #define KEY_TGT_COUNT "tgt_count" /* KEY_SET_INFO in lustre_idl.h */ #define KEY_SPTLRPC_CONF "sptlrpc_conf" -#define KEY_CONNECT_FLAG "connect_flags" #define KEY_CACHE_SET "cache_set" #define KEY_CACHE_LRU_SHRINK "cache_lru_shrink" diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index a54cd70..2ee4b19 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -1862,73 +1862,14 @@ static int lov_get_info(const struct lu_env *env, struct obd_export *exp, { struct obd_device *obddev = class_exp2obd(exp); struct lov_obd *lov = &obddev->u.lov; - int i, rc; + int rc; if (!vallen || !val) return -EFAULT; obd_getref(obddev); - if (KEY_IS(KEY_LOCK_TO_STRIPE)) { - struct { - char name[16]; - struct ldlm_lock *lock; - } *data = key; - struct ldlm_res_id *res_id = &data->lock->l_resource->lr_name; - struct lov_oinfo *loi; - __u32 *stripe = val; - - if (*vallen < sizeof(*stripe)) { - rc = -EFAULT; - goto out; - } - *vallen = sizeof(*stripe); - - /* XXX This is another one of those bits that will need to - * change if we ever actually support nested LOVs. It uses - * the lock's export to find out which stripe it is. - */ - /* XXX - it's assumed all the locks for deleted OSTs have - * been cancelled. Also, the export for deleted OSTs will - * be NULL and won't match the lock's export. - */ - for (i = 0; i < lsm->lsm_stripe_count; i++) { - loi = lsm->lsm_oinfo[i]; - if (lov_oinfo_is_dummy(loi)) - continue; - - if (!lov->lov_tgts[loi->loi_ost_idx]) - continue; - if (lov->lov_tgts[loi->loi_ost_idx]->ltd_exp == - data->lock->l_conn_export && - ostid_res_name_eq(&loi->loi_oi, res_id)) { - *stripe = i; - rc = 0; - goto out; - } - } - LDLM_ERROR(data->lock, "lock on inode without such object"); - dump_lsm(D_ERROR, lsm); - rc = -ENXIO; - goto out; - } else if (KEY_IS(KEY_LAST_ID)) { - struct obd_id_info *info = val; - __u32 size = sizeof(u64); - struct lov_tgt_desc *tgt; - - LASSERT(*vallen == sizeof(struct obd_id_info)); - tgt = lov->lov_tgts[info->idx]; - - if (!tgt || !tgt->ltd_active) { - rc = -ESRCH; - goto out; - } - - rc = obd_get_info(env, tgt->ltd_exp, keylen, key, - &size, info->data, NULL); - rc = 0; - goto out; - } else if (KEY_IS(KEY_LOVDESC)) { + if (KEY_IS(KEY_LOVDESC)) { struct lov_desc *desc_ret = val; *desc_ret = lov->desc; @@ -1937,22 +1878,6 @@ static int lov_get_info(const struct lu_env *env, struct obd_export *exp, } else if (KEY_IS(KEY_FIEMAP)) { rc = lov_fiemap(lov, keylen, key, vallen, val, lsm); goto out; - } else if (KEY_IS(KEY_CONNECT_FLAG)) { - struct lov_tgt_desc *tgt; - __u64 ost_idx = *((__u64 *)val); - - LASSERT(*vallen == sizeof(__u64)); - LASSERT(ost_idx < lov->desc.ld_tgt_count); - tgt = lov->lov_tgts[ost_idx]; - - if (!tgt || !tgt->ltd_exp) { - rc = -ESRCH; - goto out; - } - - *((__u64 *)val) = exp_connect_flags(tgt->ltd_exp); - rc = 0; - goto out; } else if (KEY_IS(KEY_TGT_COUNT)) { *((int *)val) = lov->desc.ld_tgt_count; rc = 0; @@ -1975,8 +1900,7 @@ static int lov_set_info_async(const struct lu_env *env, struct obd_export *exp, u32 count; int i, rc = 0, err; struct lov_tgt_desc *tgt; - unsigned int incr = 0, check_uuid = 0, do_inactive = 0, no_set = 0; - unsigned int next_id = 0, mds_con = 0; + int do_inactive = 0, no_set = 0; if (!set) { no_set = 1; @@ -1988,18 +1912,8 @@ static int lov_set_info_async(const struct lu_env *env, struct obd_export *exp, obd_getref(obddev); count = lov->desc.ld_tgt_count; - if (KEY_IS(KEY_NEXT_ID)) { - count = vallen / sizeof(struct obd_id_info); - vallen = sizeof(u64); - incr = sizeof(struct obd_id_info); - do_inactive = 1; - next_id = 1; - } else if (KEY_IS(KEY_CHECKSUM)) { + if (KEY_IS(KEY_CHECKSUM)) { do_inactive = 1; - } else if (KEY_IS(KEY_EVICT_BY_NID)) { - /* use defaults: do_inactive = incr = 0; */ - } else if (KEY_IS(KEY_MDS_CONN)) { - mds_con = 1; } else if (KEY_IS(KEY_CACHE_SET)) { LASSERT(!lov->lov_cache); lov->lov_cache = val; @@ -2007,11 +1921,9 @@ static int lov_set_info_async(const struct lu_env *env, struct obd_export *exp, cl_cache_incref(lov->lov_cache); } - for (i = 0; i < count; i++, val = (char *)val + incr) { - if (next_id) - tgt = lov->lov_tgts[((struct obd_id_info *)val)->idx]; - else - tgt = lov->lov_tgts[i]; + for (i = 0; i < count; i++) { + tgt = lov->lov_tgts[i]; + /* OST was disconnected */ if (!tgt || !tgt->ltd_exp) continue; @@ -2020,34 +1932,8 @@ static int lov_set_info_async(const struct lu_env *env, struct obd_export *exp, if (!tgt->ltd_active && !do_inactive) continue; - if (mds_con) { - struct mds_group_info *mgi; - - LASSERT(vallen == sizeof(*mgi)); - mgi = (struct mds_group_info *)val; - - /* Only want a specific OSC */ - if (mgi->uuid && !obd_uuid_equals(mgi->uuid, - &tgt->ltd_uuid)) - continue; - - err = obd_set_info_async(env, tgt->ltd_exp, - keylen, key, sizeof(int), - &mgi->group, set); - } else if (next_id) { - err = obd_set_info_async(env, tgt->ltd_exp, - keylen, key, vallen, - ((struct obd_id_info *)val)->data, set); - } else { - /* Only want a specific OSC */ - if (check_uuid && - !obd_uuid_equals(val, &tgt->ltd_uuid)) - continue; - - err = obd_set_info_async(env, tgt->ltd_exp, - keylen, key, vallen, val, set); - } - + err = obd_set_info_async(env, tgt->ltd_exp, keylen, key, + vallen, val, set); if (!rc) rc = err; } diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 90d6eaa..df03884 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -2733,51 +2733,7 @@ static int osc_get_info(const struct lu_env *env, struct obd_export *exp, if (!vallen || !val) return -EFAULT; - if (KEY_IS(KEY_LOCK_TO_STRIPE)) { - __u32 *stripe = val; - *vallen = sizeof(*stripe); - *stripe = 0; - return 0; - } else if (KEY_IS(KEY_LAST_ID)) { - struct ptlrpc_request *req; - u64 *reply; - char *tmp; - int rc; - - req = ptlrpc_request_alloc(class_exp2cliimp(exp), - &RQF_OST_GET_INFO_LAST_ID); - if (!req) - return -ENOMEM; - - req_capsule_set_size(&req->rq_pill, &RMF_SETINFO_KEY, - RCL_CLIENT, keylen); - rc = ptlrpc_request_pack(req, LUSTRE_OST_VERSION, OST_GET_INFO); - if (rc) { - ptlrpc_request_free(req); - return rc; - } - - tmp = req_capsule_client_get(&req->rq_pill, &RMF_SETINFO_KEY); - memcpy(tmp, key, keylen); - - req->rq_no_delay = 1; - req->rq_no_resend = 1; - ptlrpc_request_set_replen(req); - rc = ptlrpc_queue_wait(req); - if (rc) - goto out; - - reply = req_capsule_server_get(&req->rq_pill, &RMF_OBD_ID); - if (!reply) { - rc = -EPROTO; - goto out; - } - - *((u64 *)val) = *reply; -out: - ptlrpc_req_finished(req); - return rc; - } else if (KEY_IS(KEY_FIEMAP)) { + if (KEY_IS(KEY_FIEMAP)) { struct ll_fiemap_info_key *fm_key = key; struct ldlm_res_id res_id; ldlm_policy_data_t policy; -- cgit v0.10.2 From 9ca6fb12f31dc9cbde07a27a9c1ea0c337e0fe08 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Sun, 18 Sep 2016 16:38:08 -0400 Subject: staging: lustre: fix messages with missing newlines Restore the trailing newline in the definition of OSC_DUMP_GRANT(). Remove an unnecessary CDEBUG() from ldlm_pool_recalc(). Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5551 Reviewed-on: http://review.whamcloud.com/11996 Reviewed-by: James Nunez <james.a.nunez@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c index 1147b30..44c3abf 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c @@ -385,10 +385,6 @@ static int ldlm_pool_recalc(struct ldlm_pool *pl) pl->pl_recalc_period; if (recalc_interval_sec <= 0) { /* Prevent too frequent recalculation. */ - CDEBUG(D_DLMTRACE, - "Negative interval(%d), too short period(%lld)", - recalc_interval_sec, - (s64)pl->pl_recalc_period); recalc_interval_sec = 1; } diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index 26ad360..5a0c1b2 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -1385,7 +1385,7 @@ static int osc_completion(const struct lu_env *env, struct osc_async_page *oap, struct client_obd *__tmp = (cli); \ CDEBUG(lvl, "%s: grant { dirty: %ld/%ld dirty_pages: %ld/%lu " \ "dropped: %ld avail: %ld, reserved: %ld, flight: %d }" \ - "lru {in list: %ld, left: %ld, waiters: %d }" fmt, \ + "lru {in list: %ld, left: %ld, waiters: %d }" fmt "\n", \ __tmp->cl_import->imp_obd->obd_name, \ __tmp->cl_dirty_pages, __tmp->cl_dirty_max_pages, \ atomic_long_read(&obd_dirty_pages), obd_max_dirty_pages, \ -- cgit v0.10.2 From 5231f7651c557996821940a576873c0e6e39425e Mon Sep 17 00:00:00 2001 From: Lai Siyao <lai.siyao@intel.com> Date: Sun, 18 Sep 2016 16:38:09 -0400 Subject: staging: lustre: statahead: small fixes and cleanup small fixes: * when 'unplug' is set for ll_statahead(), sa_put() shouldn't kill the entry found, because its inflight RPC may not finish yet. * remove 'sai_generation', add 'lli_sa_generation' because the former one is not safe to access without lock. * revalidate_statahead_dentry() may fail to wait for statahead entry to become ready, in this case it should not release this entry, because it may be used by inflight statahead RPC. cleanups: * rename ll_statahead_enter() to ll_statahead(). * move dentry 'lld_sa_generation' update to ll_statahead() to simplify code and logic. * other small cleanups. Signed-off-by: Lai Siyao <lai.siyao@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3270 Reviewed-on: http://review.whamcloud.com/9667 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6222 Reviewed-on: http://review.whamcloud.com/13708 Reviewed-by: Fan Yong <fan.yong@intel.com> Reviewed-by: Bobi Jam <bobijam@hotmail.com> Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/dcache.c b/drivers/staging/lustre/lustre/llite/dcache.c index 8500080..0e45d8f 100644 --- a/drivers/staging/lustre/lustre/llite/dcache.c +++ b/drivers/staging/lustre/lustre/llite/dcache.c @@ -278,14 +278,13 @@ static int ll_revalidate_dentry(struct dentry *dentry, if (lookup_flags & (LOOKUP_PARENT | LOOKUP_OPEN | LOOKUP_CREATE)) return 1; - if (!dentry_need_statahead(dir, dentry)) + if (!dentry_may_statahead(dir, dentry)) return 1; if (lookup_flags & LOOKUP_RCU) return -ECHILD; - do_statahead_enter(dir, &dentry, !d_inode(dentry)); - ll_statahead_mark(dir, dentry); + ll_statahead(dir, &dentry, !d_inode(dentry)); return 1; } diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index a68bea1..bdfdff5 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -161,7 +161,7 @@ struct ll_inode_info { /* for directory */ struct { /* serialize normal readdir and statahead-readdir. */ - struct mutex d_readdir_mutex; + struct mutex lli_readdir_mutex; /* metadata statahead */ /* since parent-child threads can share the same @file @@ -169,44 +169,35 @@ struct ll_inode_info { * case of parent exit before child -- it is me should * cleanup the dir readahead. */ - void *d_opendir_key; - struct ll_statahead_info *d_sai; + void *lli_opendir_key; + struct ll_statahead_info *lli_sai; /* protect statahead stuff. */ - spinlock_t d_sa_lock; + spinlock_t lli_sa_lock; /* "opendir_pid" is the token when lookup/revalidate * -- I am the owner of dir statahead. */ - pid_t d_opendir_pid; + pid_t lli_opendir_pid; /* stat will try to access statahead entries or start * statahead if this flag is set, and this flag will be * set upon dir open, and cleared when dir is closed, * statahead hit ratio is too low, or start statahead * thread failed. */ - unsigned int d_sa_enabled:1; + unsigned int lli_sa_enabled:1; + /* generation for statahead */ + unsigned int lli_sa_generation; /* directory stripe information */ - struct lmv_stripe_md *d_lsm_md; + struct lmv_stripe_md *lli_lsm_md; /* striped directory size */ - loff_t d_stripe_size; - /* striped directory nlink */ - __u64 d_stripe_nlink; - } d; - -#define lli_readdir_mutex u.d.d_readdir_mutex -#define lli_opendir_key u.d.d_opendir_key -#define lli_sai u.d.d_sai -#define lli_sa_lock u.d.d_sa_lock -#define lli_sa_enabled u.d.d_sa_enabled -#define lli_opendir_pid u.d.d_opendir_pid -#define lli_lsm_md u.d.d_lsm_md -#define lli_stripe_dir_size u.d.d_stripe_size -#define lli_stripe_dir_nlink u.d.d_stripe_nlink + loff_t lli_stripe_dir_size; + u64 lli_stripe_dir_nlink; + }; /* for non-directory */ struct { - struct mutex f_size_mutex; - char *f_symlink_name; - __u64 f_maxbytes; + struct mutex lli_size_mutex; + char *lli_symlink_name; + __u64 lli_maxbytes; /* * struct rw_semaphore { * signed long count; // align d.d_def_acl @@ -214,16 +205,16 @@ struct ll_inode_info { * struct list_head wait_list; * } */ - struct rw_semaphore f_trunc_sem; - struct range_lock_tree f_write_tree; + struct rw_semaphore lli_trunc_sem; + struct range_lock_tree lli_write_tree; - struct rw_semaphore f_glimpse_sem; - unsigned long f_glimpse_time; - struct list_head f_agl_list; - __u64 f_agl_index; + struct rw_semaphore lli_glimpse_sem; + unsigned long lli_glimpse_time; + struct list_head lli_agl_list; + __u64 lli_agl_index; /* for writepage() only to communicate to fsync */ - int f_async_rc; + int lli_async_rc; /* * whenever a process try to read/write the file, the @@ -233,22 +224,9 @@ struct ll_inode_info { * so the read/write statistics for jobid will not be * accurate if the file is shared by different jobs. */ - char f_jobid[LUSTRE_JOBID_SIZE]; - } f; - -#define lli_size_mutex u.f.f_size_mutex -#define lli_symlink_name u.f.f_symlink_name -#define lli_maxbytes u.f.f_maxbytes -#define lli_trunc_sem u.f.f_trunc_sem -#define lli_write_tree u.f.f_write_tree -#define lli_glimpse_sem u.f.f_glimpse_sem -#define lli_glimpse_time u.f.f_glimpse_time -#define lli_agl_list u.f.f_agl_list -#define lli_agl_index u.f.f_agl_index -#define lli_async_rc u.f.f_async_rc -#define lli_jobid u.f.f_jobid - - } u; + char lli_jobid[LUSTRE_JOBID_SIZE]; + }; + }; /* XXX: For following frequent used members, although they maybe special * used for non-directory object, it is some time-wasting to check @@ -1095,11 +1073,10 @@ void ll_ra_stats_inc(struct inode *inode, enum ra_stat which); /* per inode struct, for dir only */ struct ll_statahead_info { - struct inode *sai_inode; + struct dentry *sai_dentry; atomic_t sai_refcount; /* when access this struct, hold * refcount */ - unsigned int sai_generation; /* generation for statahead */ unsigned int sai_max; /* max ahead of lookup */ __u64 sai_sent; /* stat requests sent count */ __u64 sai_replied; /* stat requests which received @@ -1142,8 +1119,7 @@ struct ll_statahead_info { atomic_t sai_cache_count; /* entry count in cache */ }; -int do_statahead_enter(struct inode *dir, struct dentry **dentry, - int only_unplug); +int ll_statahead(struct inode *dir, struct dentry **dentry, bool unplug); void ll_authorize_statahead(struct inode *dir, void *key); void ll_deauthorize_statahead(struct inode *dir, void *key); @@ -1175,24 +1151,12 @@ static inline int ll_glimpse_size(struct inode *inode) return rc; } -static inline void -ll_statahead_mark(struct inode *dir, struct dentry *dentry) -{ - struct ll_inode_info *lli = ll_i2info(dir); - struct ll_statahead_info *sai = lli->lli_sai; - struct ll_dentry_data *ldd = ll_d2d(dentry); - - /* not the same process, don't mark */ - if (lli->lli_opendir_pid != current_pid()) - return; - - LASSERT(ldd); - if (sai) - ldd->lld_sa_generation = sai->sai_generation; -} - +/* + * dentry may statahead when statahead is enabled and current process has opened + * parent directory, and this dentry hasn't accessed statahead cache before + */ static inline bool -dentry_need_statahead(struct inode *dir, struct dentry *dentry) +dentry_may_statahead(struct inode *dir, struct dentry *dentry) { struct ll_inode_info *lli; struct ll_dentry_data *ldd; @@ -1215,38 +1179,27 @@ dentry_need_statahead(struct inode *dir, struct dentry *dentry) if (lli->lli_opendir_pid != current_pid()) return false; - ldd = ll_d2d(dentry); /* - * When stats a dentry, the system trigger more than once "revalidate" - * or "lookup", for "getattr", for "getxattr", and maybe for others. - * Under patchless client mode, the operation intent is not accurate, - * which maybe misguide the statahead thread. For example: - * The "revalidate" call for "getattr" and "getxattr" of a dentry maybe - * have the same operation intent -- "IT_GETATTR". - * In fact, one dentry should has only one chance to interact with the - * statahead thread, otherwise the statahead windows will be confused. + * When stating a dentry, kernel may trigger 'revalidate' or 'lookup' + * multiple times, eg. for 'getattr', 'getxattr' and etc. + * For patchless client, lookup intent is not accurate, which may + * misguide statahead. For example: + * The 'revalidate' call for 'getattr' and 'getxattr' of a dentry will + * have the same intent -- IT_GETATTR, while one dentry should access + * statahead cache once, otherwise statahead windows is messed up. * The solution is as following: - * Assign "lld_sa_generation" with "sai_generation" when a dentry - * "IT_GETATTR" for the first time, and the subsequent "IT_GETATTR" - * will bypass interacting with statahead thread for checking: - * "lld_sa_generation == lli_sai->sai_generation" + * Assign 'lld_sa_generation' with 'lli_sa_generation' when a dentry + * IT_GETATTR for the first time, and subsequent IT_GETATTR will + * bypass interacting with statahead cache by checking + * 'lld_sa_generation == lli->lli_sa_generation'. */ - if (ldd && lli->lli_sai && - ldd->lld_sa_generation == lli->lli_sai->sai_generation) + ldd = ll_d2d(dentry); + if (ldd && ldd->lld_sa_generation == lli->lli_sa_generation) return false; return true; } -static inline int -ll_statahead_enter(struct inode *dir, struct dentry **dentryp, int only_unplug) -{ - if (!dentry_need_statahead(dir, *dentryp)) - return -EAGAIN; - - return do_statahead_enter(dir, dentryp, only_unplug); -} - /* llite ioctl register support routine */ enum llioc_iter { LLIOC_CONT = 0, diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index 85f8ce7..494140a 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -522,8 +522,8 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry, if (!it || it->it_op == IT_GETXATTR) it = &lookup_it; - if (it->it_op == IT_GETATTR) { - rc = ll_statahead_enter(parent, &dentry, 0); + if (it->it_op == IT_GETATTR && dentry_may_statahead(parent, dentry)) { + rc = ll_statahead(parent, &dentry, 0); if (rc == 1) { if (dentry == save) retval = NULL; @@ -574,11 +574,8 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry, retval = NULL; else retval = dentry; - out: - if (req) - ptlrpc_req_finished(req); - if (it->it_op == IT_GETATTR && (!retval || retval == dentry)) - ll_statahead_mark(parent, dentry); +out: + ptlrpc_req_finished(req); return retval; } diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c index 1867fd5..0677513 100644 --- a/drivers/staging/lustre/lustre/llite/statahead.c +++ b/drivers/staging/lustre/lustre/llite/statahead.c @@ -54,12 +54,12 @@ enum se_stat { /* * sa_entry is not refcounted: statahead thread allocates it and do async stat, * and in async stat callback ll_statahead_interpret() will add it into - * sai_cb_entries, later statahead thread will call sa_handle_callback() to + * sai_interim_entries, later statahead thread will call sa_handle_callback() to * instantiate entry and move it into sai_entries, and then only scanner process * can access and free it. */ struct sa_entry { - /* link into sai_cb_entries or sai_entries */ + /* link into sai_interim_entries or sai_entries */ struct list_head se_list; /* link into sai hash table locally */ struct list_head se_hash; @@ -84,23 +84,20 @@ struct sa_entry { static unsigned int sai_generation; static DEFINE_SPINLOCK(sai_generation_lock); -/* - * The entry only can be released by the caller, it is necessary to hold lock. - */ +/* sa_entry is ready to use */ static inline int sa_ready(struct sa_entry *entry) { smp_rmb(); return (entry->se_state != SA_ENTRY_INIT); } +/* hash value to put in sai_cache */ static inline int sa_hash(int val) { return val & LL_SA_CACHE_MASK; } -/* - * Insert entry to hash SA table. - */ +/* hash entry into sai_cache */ static inline void sa_rehash(struct ll_statahead_info *sai, struct sa_entry *entry) { @@ -130,11 +127,13 @@ static inline int agl_should_run(struct ll_statahead_info *sai, return (inode && S_ISREG(inode->i_mode) && sai->sai_agl_valid); } +/* statahead window is full */ static inline int sa_sent_full(struct ll_statahead_info *sai) { return atomic_read(&sai->sai_cache_count) >= sai->sai_max; } +/* got async stat replies */ static inline int sa_has_callback(struct ll_statahead_info *sai) { return !list_empty(&sai->sai_interim_entries); @@ -158,7 +157,7 @@ static inline int sa_low_hit(struct ll_statahead_info *sai) } /* - * If the given index is behind of statahead window more than + * if the given index is behind of statahead window more than * SA_OMITTED_ENTRY_MAX, then it is old. */ static inline int is_omitted_entry(struct ll_statahead_info *sai, __u64 index) @@ -167,9 +166,7 @@ static inline int is_omitted_entry(struct ll_statahead_info *sai, __u64 index) sai->sai_index); } -/* - * Insert it into sai_entries tail when init. - */ +/* allocate sa_entry and hash it to allow scanner process to find it */ static struct sa_entry * sa_alloc(struct dentry *parent, struct ll_statahead_info *sai, __u64 index, const char *name, int len) @@ -198,7 +195,7 @@ sa_alloc(struct dentry *parent, struct ll_statahead_info *sai, __u64 index, entry->se_qstr.len = len; entry->se_qstr.name = dname; - lli = ll_i2info(sai->sai_inode); + lli = ll_i2info(sai->sai_dentry->d_inode); spin_lock(&lli->lli_sa_lock); INIT_LIST_HEAD(&entry->se_list); sa_rehash(sai, entry); @@ -246,7 +243,7 @@ sa_get(struct ll_statahead_info *sai, const struct qstr *qstr) static inline void sa_kill(struct ll_statahead_info *sai, struct sa_entry *entry) { - struct ll_inode_info *lli = ll_i2info(sai->sai_inode); + struct ll_inode_info *lli = ll_i2info(sai->sai_dentry->d_inode); LASSERT(!list_empty(&entry->se_hash)); LASSERT(!list_empty(&entry->se_list)); @@ -271,7 +268,7 @@ sa_put(struct ll_statahead_info *sai, struct sa_entry *entry) struct sa_entry *tmp, *next; if (entry && entry->se_state == SA_ENTRY_SUCC) { - struct ll_sb_info *sbi = ll_i2sbi(sai->sai_inode); + struct ll_sb_info *sbi = ll_i2sbi(sai->sai_dentry->d_inode); sai->sai_hit++; sai->sai_consecutive_miss = 0; @@ -293,6 +290,7 @@ sa_put(struct ll_statahead_info *sai, struct sa_entry *entry) break; sa_kill(sai, tmp); } + wake_up(&sai->sai_thread.t_ctl_waitq); } @@ -329,7 +327,7 @@ __sa_make_ready(struct ll_statahead_info *sai, struct sa_entry *entry, int ret) static void sa_make_ready(struct ll_statahead_info *sai, struct sa_entry *entry, int ret) { - struct ll_inode_info *lli = ll_i2info(sai->sai_inode); + struct ll_inode_info *lli = ll_i2info(sai->sai_dentry->d_inode); struct md_enqueue_info *minfo = entry->se_minfo; struct ptlrpc_request *req = entry->se_req; bool wakeup; @@ -355,14 +353,12 @@ sa_make_ready(struct ll_statahead_info *sai, struct sa_entry *entry, int ret) wake_up(&sai->sai_waitq); } -/* - * Insert inode into the list of sai_agls. - */ +/* Insert inode into the list of sai_agls. */ static void ll_agl_add(struct ll_statahead_info *sai, struct inode *inode, int index) { struct ll_inode_info *child = ll_i2info(inode); - struct ll_inode_info *parent = ll_i2info(sai->sai_inode); + struct ll_inode_info *parent = ll_i2info(sai->sai_dentry->d_inode); int added = 0; spin_lock(&child->lli_agl_lock); @@ -387,8 +383,9 @@ static void ll_agl_add(struct ll_statahead_info *sai, } /* allocate sai */ -static struct ll_statahead_info *ll_sai_alloc(void) +static struct ll_statahead_info *ll_sai_alloc(struct dentry *dentry) { + struct ll_inode_info *lli = ll_i2info(dentry->d_inode); struct ll_statahead_info *sai; int i; @@ -396,14 +393,9 @@ static struct ll_statahead_info *ll_sai_alloc(void) if (!sai) return NULL; + sai->sai_dentry = dget(dentry); atomic_set(&sai->sai_refcount, 1); - spin_lock(&sai_generation_lock); - sai->sai_generation = ++sai_generation; - if (unlikely(sai_generation == 0)) - sai->sai_generation = ++sai_generation; - spin_unlock(&sai_generation_lock); - sai->sai_max = LL_SA_RPC_MIN; sai->sai_index = 1; init_waitqueue_head(&sai->sai_waitq); @@ -420,9 +412,27 @@ static struct ll_statahead_info *ll_sai_alloc(void) } atomic_set(&sai->sai_cache_count, 0); + spin_lock(&sai_generation_lock); + lli->lli_sa_generation = ++sai_generation; + if (unlikely(!sai_generation)) + lli->lli_sa_generation = ++sai_generation; + spin_unlock(&sai_generation_lock); + return sai; } +/* free sai */ +static inline void ll_sai_free(struct ll_statahead_info *sai) +{ + LASSERT(sai->sai_dentry); + dput(sai->sai_dentry); + kfree(sai); +} + +/* + * take refcount of sai if sai for @dir exists, which means statahead is on for + * this directory. + */ static inline struct ll_statahead_info *ll_sai_get(struct inode *dir) { struct ll_inode_info *lli = ll_i2info(dir); @@ -437,12 +447,16 @@ static inline struct ll_statahead_info *ll_sai_get(struct inode *dir) return sai; } +/* + * put sai refcount after use, if refcount reaches zero, free sai and sa_entries + * attached to it. + */ static void ll_sai_put(struct ll_statahead_info *sai) { - struct ll_inode_info *lli = ll_i2info(sai->sai_inode); + struct ll_inode_info *lli = ll_i2info(sai->sai_dentry->d_inode); if (atomic_dec_and_lock(&sai->sai_refcount, &lli->lli_sa_lock)) { - struct ll_sb_info *sbi = ll_i2sbi(sai->sai_inode); + struct ll_sb_info *sbi = ll_i2sbi(sai->sai_dentry->d_inode); struct sa_entry *entry, *next; lli->lli_sai = NULL; @@ -460,8 +474,7 @@ static void ll_sai_put(struct ll_statahead_info *sai) LASSERT(atomic_read(&sai->sai_cache_count) == 0); LASSERT(list_empty(&sai->sai_agls)); - iput(sai->sai_inode); - kfree(sai); + ll_sai_free(sai); atomic_dec(&sbi->ll_sa_running); } } @@ -533,7 +546,7 @@ static void ll_agl_trigger(struct inode *inode, struct ll_statahead_info *sai) static void sa_instantiate(struct ll_statahead_info *sai, struct sa_entry *entry) { - struct inode *dir = sai->sai_inode; + struct inode *dir = sai->sai_dentry->d_inode; struct inode *child; struct md_enqueue_info *minfo; struct lookup_intent *it; @@ -609,12 +622,12 @@ out: sa_make_ready(sai, entry, rc); } -/* once there are async stat replies, instantiate sa_entry */ +/* once there are async stat replies, instantiate sa_entry from replies */ static void sa_handle_callback(struct ll_statahead_info *sai) { struct ll_inode_info *lli; - lli = ll_i2info(sai->sai_inode); + lli = ll_i2info(sai->sai_dentry->d_inode); while (sa_has_callback(sai)) { struct sa_entry *entry; @@ -631,21 +644,6 @@ static void sa_handle_callback(struct ll_statahead_info *sai) sa_instantiate(sai, entry); } - - spin_lock(&lli->lli_agl_lock); - while (!agl_list_empty(sai)) { - struct ll_inode_info *clli; - - clli = list_entry(sai->sai_agls.next, - struct ll_inode_info, lli_agl_list); - list_del_init(&clli->lli_agl_list); - spin_unlock(&lli->lli_agl_lock); - - ll_agl_trigger(&clli->lli_vfs_inode, sai); - - spin_lock(&lli->lli_agl_lock); - } - spin_unlock(&lli->lli_agl_lock); } /* @@ -718,6 +716,7 @@ static int ll_statahead_interpret(struct ptlrpc_request *req, return rc; } +/* finish async stat RPC arguments */ static void sa_fini_data(struct md_enqueue_info *minfo, struct ldlm_enqueue_info *einfo) { @@ -775,6 +774,7 @@ static int sa_prep_data(struct inode *dir, struct inode *child, return 0; } +/* async stat for file not found in dcache */ static int sa_lookup(struct inode *dir, struct sa_entry *entry) { struct md_enqueue_info *minfo; @@ -786,17 +786,18 @@ static int sa_lookup(struct inode *dir, struct sa_entry *entry) return rc; rc = md_intent_getattr_async(ll_i2mdexp(dir), minfo, einfo); - if (rc < 0) + if (rc) sa_fini_data(minfo, einfo); return rc; } /** - * similar to ll_revalidate_it(). - * \retval 1 -- dentry valid - * \retval 0 -- will send stat-ahead request - * \retval others -- prepare stat-ahead request failed + * async stat for file found in dcache, similar to .revalidate + * + * \retval 1 dentry valid, no RPC sent + * \retval 0 dentry invalid, will send async stat RPC + * \retval negative number upon error */ static int sa_revalidate(struct inode *dir, struct sa_entry *entry, struct dentry *dentry) @@ -831,7 +832,7 @@ static int sa_revalidate(struct inode *dir, struct sa_entry *entry, } rc = md_intent_getattr_async(ll_i2mdexp(dir), minfo, einfo); - if (rc < 0) { + if (rc) { entry->se_inode = NULL; iput(inode); sa_fini_data(minfo, einfo); @@ -840,6 +841,7 @@ static int sa_revalidate(struct inode *dir, struct sa_entry *entry, return rc; } +/* async stat for file with @name */ static void sa_statahead(struct dentry *parent, const char *name, int len) { struct inode *dir = d_inode(parent); @@ -873,6 +875,7 @@ static void sa_statahead(struct dentry *parent, const char *name, int len) sai->sai_index++; } +/* async glimpse (agl) thread main function */ static int ll_agl_thread(void *arg) { struct dentry *parent = arg; @@ -946,6 +949,7 @@ static int ll_agl_thread(void *arg) return 0; } +/* start agl thread */ static void ll_start_agl(struct dentry *parent, struct ll_statahead_info *sai) { struct ptlrpc_thread *thread = &sai->sai_agl_thread; @@ -970,6 +974,7 @@ static void ll_start_agl(struct dentry *parent, struct ll_statahead_info *sai) &lwi); } +/* statahead thread main function */ static int ll_statahead_thread(void *arg) { struct dentry *parent = arg; @@ -977,7 +982,7 @@ static int ll_statahead_thread(void *arg) struct ll_inode_info *lli = ll_i2info(dir); struct ll_sb_info *sbi = ll_i2sbi(dir); struct ll_statahead_info *sai; - struct ptlrpc_thread *thread; + struct ptlrpc_thread *sa_thread; struct ptlrpc_thread *agl_thread; struct page *page = NULL; __u64 pos = 0; @@ -987,9 +992,9 @@ static int ll_statahead_thread(void *arg) struct l_wait_info lwi = { 0 }; sai = ll_sai_get(dir); - thread = &sai->sai_thread; + sa_thread = &sai->sai_thread; agl_thread = &sai->sai_agl_thread; - thread->t_pid = current_pid(); + sa_thread->t_pid = current_pid(); CDEBUG(D_READA, "statahead thread starting: sai %p, parent %pd\n", sai, parent); @@ -1007,16 +1012,16 @@ static int ll_statahead_thread(void *arg) atomic_inc(&sbi->ll_sa_total); spin_lock(&lli->lli_sa_lock); - if (thread_is_init(thread)) + if (thread_is_init(sa_thread)) /* If someone else has changed the thread state * (e.g. already changed to SVC_STOPPING), we can't just * blindly overwrite that setting. */ - thread_set_flags(thread, SVC_RUNNING); + thread_set_flags(sa_thread, SVC_RUNNING); spin_unlock(&lli->lli_sa_lock); - wake_up(&thread->t_ctl_waitq); + wake_up(&sa_thread->t_ctl_waitq); - while (pos != MDS_DIR_END_OFF && thread_is_running(thread)) { + while (pos != MDS_DIR_END_OFF && thread_is_running(sa_thread)) { struct lu_dirpage *dp; struct lu_dirent *ent; @@ -1033,7 +1038,7 @@ static int ll_statahead_thread(void *arg) dp = page_address(page); for (ent = lu_dirent_start(dp); - ent && thread_is_running(thread) && !sa_low_hit(sai); + ent && thread_is_running(sa_thread) && !sa_low_hit(sai); ent = lu_dirent_next(ent)) { __u64 hash; int namelen; @@ -1082,15 +1087,32 @@ static int ll_statahead_thread(void *arg) /* wait for spare statahead window */ do { - l_wait_event(thread->t_ctl_waitq, + l_wait_event(sa_thread->t_ctl_waitq, !sa_sent_full(sai) || sa_has_callback(sai) || !list_empty(&sai->sai_agls) || - !thread_is_running(thread), + !thread_is_running(sa_thread), &lwi); sa_handle_callback(sai); + + spin_lock(&lli->lli_agl_lock); + while (sa_sent_full(sai) && + !agl_list_empty(sai)) { + struct ll_inode_info *clli; + + clli = list_entry(sai->sai_agls.next, + struct ll_inode_info, lli_agl_list); + list_del_init(&clli->lli_agl_list); + spin_unlock(&lli->lli_agl_lock); + + ll_agl_trigger(&clli->lli_vfs_inode, + sai); + + spin_lock(&lli->lli_agl_lock); + } + spin_unlock(&lli->lli_agl_lock); } while (sa_sent_full(sai) && - thread_is_running(thread)); + thread_is_running(sa_thread)); sa_statahead(parent, name, namelen); } @@ -1113,7 +1135,7 @@ static int ll_statahead_thread(void *arg) if (rc < 0) { spin_lock(&lli->lli_sa_lock); - thread_set_flags(thread, SVC_STOPPING); + thread_set_flags(sa_thread, SVC_STOPPING); lli->lli_sa_enabled = 0; spin_unlock(&lli->lli_sa_lock); } @@ -1122,11 +1144,11 @@ static int ll_statahead_thread(void *arg) * statahead is finished, but statahead entries need to be cached, wait * for file release to stop me. */ - while (thread_is_running(thread)) { - l_wait_event(thread->t_ctl_waitq, + while (thread_is_running(sa_thread)) { + l_wait_event(sa_thread->t_ctl_waitq, sa_has_callback(sai) || !agl_list_empty(sai) || - !thread_is_running(thread), + !thread_is_running(sa_thread), &lwi); sa_handle_callback(sai); @@ -1156,7 +1178,7 @@ out: /* in case we're not woken up, timeout wait */ lwi = LWI_TIMEOUT(msecs_to_jiffies(MSEC_PER_SEC >> 3), NULL, NULL); - l_wait_event(thread->t_ctl_waitq, + l_wait_event(sa_thread->t_ctl_waitq, sai->sai_sent == sai->sai_replied, &lwi); } @@ -1164,19 +1186,20 @@ out: sa_handle_callback(sai); spin_lock(&lli->lli_sa_lock); - thread_set_flags(thread, SVC_STOPPED); + thread_set_flags(sa_thread, SVC_STOPPED); spin_unlock(&lli->lli_sa_lock); - wake_up(&sai->sai_waitq); - wake_up(&thread->t_ctl_waitq); - ll_sai_put(sai); CDEBUG(D_READA, "statahead thread stopped: sai %p, parent %pd\n", sai, parent); - dput(parent); + + wake_up(&sai->sai_waitq); + wake_up(&sa_thread->t_ctl_waitq); + ll_sai_put(sai); + return rc; } -/* authorize opened dir handle @key to statahead later */ +/* authorize opened dir handle @key to statahead */ void ll_authorize_statahead(struct inode *dir, void *key) { struct ll_inode_info *lli = ll_i2info(dir); @@ -1230,7 +1253,7 @@ enum { /** * not first dirent, or is "." */ - LS_NONE_FIRST_DE = 0, + LS_NOT_FIRST_DE = 0, /** * the first non-hidden dirent */ @@ -1241,6 +1264,7 @@ enum { LS_FIRST_DOT_DE }; +/* file is first dirent under @dir */ static int is_first_dirent(struct inode *dir, struct dentry *dentry) { const struct qstr *target = &dentry->d_name; @@ -1248,7 +1272,7 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry) struct page *page; __u64 pos = 0; int dot_de; - int rc = LS_NONE_FIRST_DE; + int rc = LS_NOT_FIRST_DE; op_data = ll_prep_md_op_data(NULL, dir, dir, NULL, 0, 0, LUSTRE_OPC_ANY, dir); @@ -1324,7 +1348,7 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry) if (target->len != namelen || memcmp(target->name, name, namelen) != 0) - rc = LS_NONE_FIRST_DE; + rc = LS_NOT_FIRST_DE; else if (!dot_de) rc = LS_FIRST_DE; else @@ -1356,13 +1380,27 @@ out: return rc; } +/** + * revalidate @dentryp from statahead cache + * + * \param[in] dir parent directory + * \param[in] sai sai structure + * \param[out] dentryp pointer to dentry which will be revalidated + * \param[in] unplug unplug statahead window only (normally for negative + * dentry) + * \retval 1 on success, dentry is saved in @dentryp + * \retval 0 if revalidation failed (no proper lock on client) + * \retval negative number upon error + */ static int revalidate_statahead_dentry(struct inode *dir, struct ll_statahead_info *sai, struct dentry **dentryp, - int only_unplug) + bool unplug) { struct sa_entry *entry = NULL; struct l_wait_info lwi = { 0 }; + struct ll_dentry_data *ldd; + struct ll_inode_info *lli; int rc = 0; if ((*dentryp)->d_name.name[0] == '.') { @@ -1392,10 +1430,15 @@ static int revalidate_statahead_dentry(struct inode *dir, } } + if (unplug) { + rc = 1; + goto out_unplug; + } + entry = sa_get(sai, &(*dentryp)->d_name); - if (!entry || only_unplug) { - sa_put(sai, entry); - return entry ? 1 : -EAGAIN; + if (!entry) { + rc = -EAGAIN; + goto out_unplug; } /* if statahead is busy in readdir, help it do post-work */ @@ -1406,13 +1449,15 @@ static int revalidate_statahead_dentry(struct inode *dir, sai->sai_index_wait = entry->se_index; lwi = LWI_TIMEOUT_INTR(cfs_time_seconds(30), NULL, LWI_ON_SIGNAL_NOOP, NULL); - rc = l_wait_event(sai->sai_waitq, - sa_ready(entry) || - thread_is_stopped(&sai->sai_thread), - &lwi); + rc = l_wait_event(sai->sai_waitq, sa_ready(entry), &lwi); if (rc < 0) { - sa_put(sai, entry); - return -EAGAIN; + /* + * entry may not be ready, so it may be used by inflight + * statahead RPC, don't free it. + */ + entry = NULL; + rc = -EAGAIN; + goto out_unplug; } } @@ -1430,10 +1475,15 @@ static int revalidate_statahead_dentry(struct inode *dir, alias = ll_splice_alias(inode, *dentryp); if (IS_ERR(alias)) { - sa_put(sai, entry); - return PTR_ERR(alias); + rc = PTR_ERR(alias); + goto out_unplug; } *dentryp = alias; + /** + * statahead prepared this inode, transfer inode + * refcount from sa_entry to dentry + */ + entry->se_inode = NULL; } else if ((*dentryp)->d_inode != inode) { /* revalidate, but inode is recreated */ CDEBUG(D_READA, @@ -1445,10 +1495,7 @@ static int revalidate_statahead_dentry(struct inode *dir, PFID(ll_inode2fid(inode))); rc = -ESTALE; goto out_unplug; - } else { - iput(inode); } - entry->se_inode = NULL; if ((bits & MDS_INODELOCK_LOOKUP) && d_lustre_invalid(*dentryp)) @@ -1457,10 +1504,34 @@ static int revalidate_statahead_dentry(struct inode *dir, } } out_unplug: + /* + * statahead cached sa_entry can be used only once, and will be killed + * right after use, so if lookup/revalidate accessed statahead cache, + * set dentry ldd_sa_generation to parent lli_sa_generation, later if we + * stat this file again, we know we've done statahead before, see + * dentry_may_statahead(). + */ + ldd = ll_d2d(*dentryp); + lli = ll_i2info(dir); + /* ldd can be NULL if llite lookup failed. */ + if (ldd) + ldd->lld_sa_generation = lli->lli_sa_generation; sa_put(sai, entry); return rc; } +/** + * start statahead thread + * + * \param[in] dir parent directory + * \param[in] dentry dentry that triggers statahead, normally the first + * dirent under @dir + * \retval -EAGAIN on success, because when this function is + * called, it's already in lookup call, so client should + * do it itself instead of waiting for statahead thread + * to do it asynchronously. + * \retval negative number upon error + */ static int start_statahead_thread(struct inode *dir, struct dentry *dentry) { struct ll_inode_info *lli = ll_i2info(dir); @@ -1468,60 +1539,34 @@ static int start_statahead_thread(struct inode *dir, struct dentry *dentry) struct l_wait_info lwi = { 0 }; struct ptlrpc_thread *thread; struct task_struct *task; - struct dentry *parent; + struct dentry *parent = dentry->d_parent; int rc; /* I am the "lli_opendir_pid" owner, only me can set "lli_sai". */ rc = is_first_dirent(dir, dentry); - if (rc == LS_NONE_FIRST_DE) { + if (rc == LS_NOT_FIRST_DE) { /* It is not "ls -{a}l" operation, no need statahead for it. */ - rc = -EAGAIN; + rc = -EFAULT; goto out; } - sai = ll_sai_alloc(); + sai = ll_sai_alloc(parent); if (!sai) { rc = -ENOMEM; goto out; } sai->sai_ls_all = (rc == LS_FIRST_DOT_DE); - sai->sai_inode = igrab(dir); - if (unlikely(!sai->sai_inode)) { - CWARN("Do not start stat ahead on dying inode "DFID"\n", - PFID(&lli->lli_fid)); - rc = -ESTALE; - goto out; - } - - /* get parent reference count here, and put it in ll_statahead_thread */ - parent = dget(dentry->d_parent); - if (unlikely(sai->sai_inode != d_inode(parent))) { - struct ll_inode_info *nlli = ll_i2info(d_inode(parent)); - - CWARN("Race condition, someone changed %pd just now: old parent "DFID", new parent "DFID"\n", - dentry, PFID(&lli->lli_fid), PFID(&nlli->lli_fid)); - dput(parent); - iput(sai->sai_inode); - rc = -EAGAIN; - goto out; - } - - CDEBUG(D_READA, "start statahead thread: sai %p, parent %pd\n", - sai, parent); - /* - * if another process started statahead thread, or deauthorized current - * lli_opendir_key, don't start statahead. + * if current lli_opendir_key was deauthorized, or dir re-opened by + * another process, don't start statahead, otherwise the newly spawned + * statahead thread won't be notified to quit. */ spin_lock(&lli->lli_sa_lock); if (unlikely(lli->lli_sai || lli->lli_opendir_key || lli->lli_opendir_pid != current->pid)) { spin_unlock(&lli->lli_sa_lock); - - dput(parent); - iput(sai->sai_inode); - rc = -EAGAIN; + rc = -EPERM; goto out; } lli->lli_sai = sai; @@ -1529,22 +1574,16 @@ static int start_statahead_thread(struct inode *dir, struct dentry *dentry) atomic_inc(&ll_i2sbi(parent->d_inode)->ll_sa_running); + CDEBUG(D_READA, "start statahead thread: [pid %d] [parent %pd]\n", + current_pid(), parent); + task = kthread_run(ll_statahead_thread, parent, "ll_sa_%u", lli->lli_opendir_pid); thread = &sai->sai_thread; if (IS_ERR(task)) { rc = PTR_ERR(task); - CERROR("cannot start ll_sa thread: rc = %d\n", rc); - dput(parent); - - spin_lock(&lli->lli_sa_lock); - thread_set_flags(thread, SVC_STOPPED); - thread_set_flags(&sai->sai_agl_thread, SVC_STOPPED); - spin_unlock(&lli->lli_sa_lock); - - ll_sai_put(sai); - LASSERT(!lli->lli_sai); - return -EAGAIN; + CERROR("can't start ll_sa thread, rc : %d\n", rc); + goto out; } l_wait_event(thread->t_ctl_waitq, @@ -1559,29 +1598,35 @@ static int start_statahead_thread(struct inode *dir, struct dentry *dentry) return -EAGAIN; out: - kfree(sai); /* * once we start statahead thread failed, disable statahead so - * subsequent won't waste time to try it. + * that subsequent stat won't waste time to try it. */ spin_lock(&lli->lli_sa_lock); lli->lli_sa_enabled = 0; + lli->lli_sai = NULL; spin_unlock(&lli->lli_sa_lock); - + if (sai) + ll_sai_free(sai); return rc; } /** - * Start statahead thread if this is the first dir entry. - * Otherwise if a thread is started already, wait it until it is ahead of me. - * \retval 1 -- find entry with lock in cache, the caller needs to do - * nothing. - * \retval 0 -- find entry in cache, but without lock, the caller needs - * refresh from MDS. - * \retval others -- the caller need to process as non-statahead. + * statahead entry function, this is called when client getattr on a file, it + * will start statahead thread if this is the first dir entry, else revalidate + * dentry from statahead cache. + * + * \param[in] dir parent directory + * \param[out] dentryp dentry to getattr + * \param[in] unplug unplug statahead window only (normally for negative + * dentry) + * \retval 1 on success + * \retval 0 revalidation from statahead cache failed, caller needs + * to getattr from server directly + * \retval negative number on error, caller often ignores this and + * then getattr from server */ -int do_statahead_enter(struct inode *dir, struct dentry **dentryp, - int only_unplug) +int ll_statahead(struct inode *dir, struct dentry **dentryp, bool unplug) { struct ll_statahead_info *sai; @@ -1589,13 +1634,11 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp, if (sai) { int rc; - rc = revalidate_statahead_dentry(dir, sai, dentryp, - only_unplug); + rc = revalidate_statahead_dentry(dir, sai, dentryp, unplug); CDEBUG(D_READA, "revalidate statahead %pd: %d.\n", *dentryp, rc); ll_sai_put(sai); return rc; } - return start_statahead_thread(dir, *dentryp); } diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 1721925..9de2e43 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -1367,7 +1367,7 @@ static int mdc_read_page(struct obd_export *exp, struct md_op_data *op_data, page = mdc_page_locate(mapping, &rp_param.rp_off, &start, &end, rp_param.rp_hash64); if (IS_ERR(page)) { - CERROR("%s: dir page locate: "DFID" at %llu: rc %ld\n", + CDEBUG(D_INFO, "%s: dir page locate: " DFID " at %llu: rc %ld\n", exp->exp_obd->obd_name, PFID(&op_data->op_fid1), rp_param.rp_off, PTR_ERR(page)); rc = PTR_ERR(page); -- cgit v0.10.2 From 18c33b6b23ef0f7571f7d1d0960fabdd6d2b3b24 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Sun, 18 Sep 2016 16:38:10 -0400 Subject: staging: lustre: obd: remove unused obd methods Remove no longer used osc_packmd() and osc_getstripe(). Several ioctls cases that are no longer used are removed. Remove no longer used adjust_kms() infrastructure. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2785 Reviewed-on: http://review.whamcloud.com/8547 Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Lai Siyao <lai.siyao@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 6eac63e..04a9b97 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -866,7 +866,6 @@ struct obd_ops { int (*unpackmd)(struct obd_export *exp, struct lov_stripe_md **mem_tgt, struct lov_mds_md *disk_src, int disk_len); - int (*preallocate)(struct lustre_handle *, u32 *req, u64 *ids); int (*create)(const struct lu_env *env, struct obd_export *exp, struct obdo *oa, struct lov_stripe_md **ea, struct obd_trans_info *oti); @@ -882,8 +881,6 @@ struct obd_ops { struct obd_info *oinfo); int (*getattr_async)(struct obd_export *exp, struct obd_info *oinfo, struct ptlrpc_request_set *set); - int (*adjust_kms)(struct obd_export *exp, struct lov_stripe_md *lsm, - u64 size, int shrink); int (*preprw)(const struct lu_env *env, int cmd, struct obd_export *exp, struct obdo *oa, int objcount, struct obd_ioobj *obj, struct niobuf_remote *remote, diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index 3d081cf..3245952 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -1152,19 +1152,6 @@ static inline int obd_commitrw(const struct lu_env *env, int cmd, return rc; } -static inline int obd_adjust_kms(struct obd_export *exp, - struct lov_stripe_md *lsm, u64 size, - int shrink) -{ - int rc; - - EXP_CHECK_DT_OP(exp, adjust_kms); - EXP_COUNTER_INCREMENT(exp, adjust_kms); - - rc = OBP(exp->exp_obd, adjust_kms)(exp, lsm, size, shrink); - return rc; -} - static inline int obd_iocontrol(unsigned int cmd, struct obd_export *exp, int len, void *karg, void __user *uarg) { diff --git a/drivers/staging/lustre/lustre/lov/lov_internal.h b/drivers/staging/lustre/lustre/lov/lov_internal.h index 12bd511..5ddaeda 100644 --- a/drivers/staging/lustre/lustre/lov/lov_internal.h +++ b/drivers/staging/lustre/lustre/lov/lov_internal.h @@ -134,8 +134,6 @@ static inline void lov_put_reqset(struct lov_request_set *set) /* lov_merge.c */ void lov_merge_attrs(struct obdo *tgt, struct obdo *src, u64 valid, struct lov_stripe_md *lsm, int stripeno, int *set); -int lov_adjust_kms(struct obd_export *exp, struct lov_stripe_md *lsm, - u64 size, int shrink); int lov_merge_lvb_kms(struct lov_stripe_md *lsm, struct ost_lvb *lvb, __u64 *kms_place); diff --git a/drivers/staging/lustre/lustre/lov/lov_merge.c b/drivers/staging/lustre/lustre/lov/lov_merge.c index b9c9086..674af10 100644 --- a/drivers/staging/lustre/lustre/lov/lov_merge.c +++ b/drivers/staging/lustre/lustre/lov/lov_merge.c @@ -105,45 +105,6 @@ int lov_merge_lvb_kms(struct lov_stripe_md *lsm, return rc; } -/* Must be called under the lov_stripe_lock() */ -int lov_adjust_kms(struct obd_export *exp, struct lov_stripe_md *lsm, - u64 size, int shrink) -{ - struct lov_oinfo *loi; - int stripe = 0; - __u64 kms; - - assert_spin_locked(&lsm->lsm_lock); - LASSERT(lsm->lsm_lock_owner == current_pid()); - - if (shrink) { - for (; stripe < lsm->lsm_stripe_count; stripe++) { - struct lov_oinfo *loi = lsm->lsm_oinfo[stripe]; - - kms = lov_size_to_stripe(lsm, size, stripe); - CDEBUG(D_INODE, - "stripe %d KMS %sing %llu->%llu\n", - stripe, kms > loi->loi_kms ? "increase":"shrink", - loi->loi_kms, kms); - loi->loi_lvb.lvb_size = kms; - loi_kms_set(loi, loi->loi_lvb.lvb_size); - } - return 0; - } - - if (size > 0) - stripe = lov_stripe_number(lsm, size - 1); - kms = lov_size_to_stripe(lsm, size, stripe); - loi = lsm->lsm_oinfo[stripe]; - - CDEBUG(D_INODE, "stripe %d KMS %sincreasing %llu->%llu\n", - stripe, kms > loi->loi_kms ? "" : "not ", loi->loi_kms, kms); - if (kms > loi->loi_kms) - loi_kms_set(loi, kms); - - return 0; -} - void lov_merge_attrs(struct obdo *tgt, struct obdo *src, u64 valid, struct lov_stripe_md *lsm, int stripeno, int *set) { diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index 2ee4b19..f433515 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -2084,7 +2084,6 @@ static struct obd_ops lov_obd_ops = { .destroy = lov_destroy, .getattr_async = lov_getattr_async, .setattr_async = lov_setattr_async, - .adjust_kms = lov_adjust_kms, .iocontrol = lov_iocontrol, .get_info = lov_get_info, .set_info_async = lov_set_info_async, diff --git a/drivers/staging/lustre/lustre/mgc/mgc_request.c b/drivers/staging/lustre/lustre/mgc/mgc_request.c index 88d4d10..2191ca1 100644 --- a/drivers/staging/lustre/lustre/mgc/mgc_request.c +++ b/drivers/staging/lustre/lustre/mgc/mgc_request.c @@ -1739,8 +1739,6 @@ static struct obd_ops mgc_obd_ops = { .del_conn = client_import_del_conn, .connect = client_connect_import, .disconnect = client_disconnect_export, - /* .enqueue = mgc_enqueue, */ - /* .iocontrol = mgc_iocontrol, */ .set_info_async = mgc_set_info_async, .get_info = mgc_get_info, .import_event = mgc_import_event, diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index df03884..2b37c36 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -103,36 +103,6 @@ static void osc_release_ppga(struct brw_page **ppga, u32 count); static int brw_interpret(const struct lu_env *env, struct ptlrpc_request *req, void *data, int rc); -/* Pack OSC object metadata for disk storage (LE byte order). */ -static int osc_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, - struct lov_stripe_md *lsm) -{ - int lmm_size; - - lmm_size = sizeof(**lmmp); - if (!lmmp) - return lmm_size; - - if (*lmmp && !lsm) { - kfree(*lmmp); - *lmmp = NULL; - return 0; - } else if (unlikely(lsm && ostid_id(&lsm->lsm_oi) == 0)) { - return -EBADF; - } - - if (!*lmmp) { - *lmmp = kzalloc(lmm_size, GFP_NOFS); - if (!*lmmp) - return -ENOMEM; - } - - if (lsm) - ostid_cpu_to_le(&lsm->lsm_oi, &(*lmmp)->lmm_oi); - - return lmm_size; -} - /* Unpack OSC object metadata from disk storage (LE byte order). */ static int osc_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, struct lov_mds_md *lmm, int lmm_bytes) @@ -2570,71 +2540,6 @@ static int osc_statfs(const struct lu_env *env, struct obd_export *exp, return rc; } -/* Retrieve object striping information. - * - * @lmmu is a pointer to an in-core struct with lmm_ost_count indicating - * the maximum number of OST indices which will fit in the user buffer. - * lmm_magic must be LOV_MAGIC (we only use 1 slot here). - */ -static int osc_getstripe(struct lov_stripe_md *lsm, - struct lov_user_md __user *lump) -{ - /* we use lov_user_md_v3 because it is larger than lov_user_md_v1 */ - struct lov_user_md_v3 lum, *lumk; - struct lov_user_ost_data_v1 *lmm_objects; - int rc = 0, lum_size; - - if (!lsm) - return -ENODATA; - - /* we only need the header part from user space to get lmm_magic and - * lmm_stripe_count, (the header part is common to v1 and v3) - */ - lum_size = sizeof(struct lov_user_md_v1); - if (copy_from_user(&lum, lump, lum_size)) - return -EFAULT; - - if ((lum.lmm_magic != LOV_USER_MAGIC_V1) && - (lum.lmm_magic != LOV_USER_MAGIC_V3)) - return -EINVAL; - - /* lov_user_md_vX and lov_mds_md_vX must have the same size */ - LASSERT(sizeof(struct lov_user_md_v1) == sizeof(struct lov_mds_md_v1)); - LASSERT(sizeof(struct lov_user_md_v3) == sizeof(struct lov_mds_md_v3)); - LASSERT(sizeof(lum.lmm_objects[0]) == sizeof(lumk->lmm_objects[0])); - - /* we can use lov_mds_md_size() to compute lum_size - * because lov_user_md_vX and lov_mds_md_vX have the same size - */ - if (lum.lmm_stripe_count > 0) { - lum_size = lov_mds_md_size(lum.lmm_stripe_count, lum.lmm_magic); - lumk = kzalloc(lum_size, GFP_NOFS); - if (!lumk) - return -ENOMEM; - - if (lum.lmm_magic == LOV_USER_MAGIC_V1) - lmm_objects = - &(((struct lov_user_md_v1 *)lumk)->lmm_objects[0]); - else - lmm_objects = &lumk->lmm_objects[0]; - lmm_objects->l_ost_oi = lsm->lsm_oi; - } else { - lum_size = lov_mds_md_size(0, lum.lmm_magic); - lumk = &lum; - } - - lumk->lmm_oi = lsm->lsm_oi; - lumk->lmm_stripe_count = 1; - - if (copy_to_user(lump, lumk, lum_size)) - rc = -EFAULT; - - if (lumk != &lum) - kfree(lumk); - - return rc; -} - static int osc_iocontrol(unsigned int cmd, struct obd_export *exp, int len, void *karg, void __user *uarg) { @@ -2648,57 +2553,6 @@ static int osc_iocontrol(unsigned int cmd, struct obd_export *exp, int len, return -EINVAL; } switch (cmd) { - case OBD_IOC_LOV_GET_CONFIG: { - char *buf; - struct lov_desc *desc; - struct obd_uuid uuid; - - buf = NULL; - len = 0; - if (obd_ioctl_getdata(&buf, &len, uarg)) { - err = -EINVAL; - goto out; - } - - data = (struct obd_ioctl_data *)buf; - - if (sizeof(*desc) > data->ioc_inllen1) { - obd_ioctl_freedata(buf, len); - err = -EINVAL; - goto out; - } - - if (data->ioc_inllen2 < sizeof(uuid)) { - obd_ioctl_freedata(buf, len); - err = -EINVAL; - goto out; - } - - desc = (struct lov_desc *)data->ioc_inlbuf1; - desc->ld_tgt_count = 1; - desc->ld_active_tgt_count = 1; - desc->ld_default_stripe_count = 1; - desc->ld_default_stripe_size = 0; - desc->ld_default_stripe_offset = 0; - desc->ld_pattern = 0; - memcpy(&desc->ld_uuid, &obd->obd_uuid, sizeof(uuid)); - - memcpy(data->ioc_inlbuf2, &obd->obd_uuid, sizeof(uuid)); - - err = copy_to_user(uarg, buf, len); - if (err) - err = -EFAULT; - obd_ioctl_freedata(buf, len); - goto out; - } - case LL_IOC_LOV_SETSTRIPE: - err = obd_alloc_memmd(exp, karg); - if (err > 0) - err = 0; - goto out; - case LL_IOC_LOV_GETSTRIPE: - err = osc_getstripe(karg, uarg); - goto out; case OBD_IOC_CLIENT_RECOVER: err = ptlrpc_recover_import(obd->u.cli.cl_import, data->ioc_inlbuf1, 0); @@ -3287,7 +3141,6 @@ static struct obd_ops osc_obd_ops = { .disconnect = osc_disconnect, .statfs = osc_statfs, .statfs_async = osc_statfs_async, - .packmd = osc_packmd, .unpackmd = osc_unpackmd, .create = osc_create, .destroy = osc_destroy, -- cgit v0.10.2 From 972e54adcd435e87f15c972bb61836a1ee94a4cc Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Sun, 18 Sep 2016 16:38:11 -0400 Subject: staging: lustre: echo: replace lov_stripe_md with lov_oinfo In echo_client replace uses of struct lov_stripe_md with struct lov_oinfo (since the instances of the former really only contained a single instance of the latter). Remove the then unneccessary functions echo_alloc_memmd(), echo_free_memmd(), osc_unpackmd(), and obd_alloc_memmd(). Remove the struct lov_stripe_md * parameter from obd_create(). Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5418 Reviewed-on: http://review.whamcloud.com/12447 Reviewed-by: Bobi Jam <bobijam@gmail.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 04a9b97..ca63891 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -867,8 +867,7 @@ struct obd_ops { struct lov_stripe_md **mem_tgt, struct lov_mds_md *disk_src, int disk_len); int (*create)(const struct lu_env *env, struct obd_export *exp, - struct obdo *oa, struct lov_stripe_md **ea, - struct obd_trans_info *oti); + struct obdo *oa, struct obd_trans_info *oti); int (*destroy)(const struct lu_env *env, struct obd_export *exp, struct obdo *oa, struct lov_stripe_md *ea, struct obd_trans_info *oti, struct obd_export *md_exp); diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index 3245952..2bf2826 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -677,15 +677,6 @@ static inline int obd_unpackmd(struct obd_export *exp, return rc; } -/* helper functions */ -static inline int obd_alloc_memmd(struct obd_export *exp, - struct lov_stripe_md **mem_tgt) -{ - LASSERT(mem_tgt); - LASSERT(!*mem_tgt); - return obd_unpackmd(exp, mem_tgt, NULL, 0); -} - static inline int obd_free_memmd(struct obd_export *exp, struct lov_stripe_md **mem_tgt) { @@ -699,15 +690,14 @@ static inline int obd_free_memmd(struct obd_export *exp, } static inline int obd_create(const struct lu_env *env, struct obd_export *exp, - struct obdo *obdo, struct lov_stripe_md **ea, - struct obd_trans_info *oti) + struct obdo *obdo, struct obd_trans_info *oti) { int rc; EXP_CHECK_DT_OP(exp, create); EXP_COUNTER_INCREMENT(exp, create); - rc = OBP(exp->exp_obd, create)(env, exp, obdo, ea, oti); + rc = OBP(exp->exp_obd, create)(env, exp, obdo, oti); return rc; } diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index cddc2d2..3218ca1 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -65,14 +65,14 @@ struct echo_object { struct echo_device *eo_dev; struct list_head eo_obj_chain; - struct lov_stripe_md *eo_lsm; + struct lov_oinfo *eo_oinfo; atomic_t eo_npages; int eo_deleted; }; struct echo_object_conf { struct cl_object_conf eoc_cl; - struct lov_stripe_md **eoc_md; + struct lov_oinfo **eoc_oinfo; }; struct echo_page { @@ -153,9 +153,6 @@ struct echo_object_conf *cl2echo_conf(const struct cl_object_conf *c) } /** @} echo_helpers */ - -static struct echo_object *cl_echo_object_find(struct echo_device *d, - struct lov_stripe_md **lsm); static int cl_echo_object_put(struct echo_object *eco); static int cl_echo_object_brw(struct echo_object *eco, int rw, u64 offset, struct page **pages, int npages, int async); @@ -414,10 +411,13 @@ static int echo_object_init(const struct lu_env *env, struct lu_object *obj, cconf = lu2cl_conf(conf); econf = cl2echo_conf(cconf); - LASSERT(econf->eoc_md); - eco->eo_lsm = *econf->eoc_md; - /* clear the lsm pointer so that it won't get freed. */ - *econf->eoc_md = NULL; + LASSERT(econf->eoc_oinfo); + /* + * Transfer the oinfo pointer to eco that it won't be + * freed. + */ + eco->eo_oinfo = *econf->eoc_oinfo; + *econf->eoc_oinfo = NULL; eco->eo_dev = ed; atomic_set(&eco->eo_npages, 0); @@ -430,52 +430,6 @@ static int echo_object_init(const struct lu_env *env, struct lu_object *obj, return 0; } -/* taken from osc_unpackmd() */ -static int echo_alloc_memmd(struct echo_device *ed, - struct lov_stripe_md **lsmp) -{ - int lsm_size; - - /* If export is lov/osc then use their obd method */ - if (ed->ed_next) - return obd_alloc_memmd(ed->ed_ec->ec_exp, lsmp); - /* OFD has no unpackmd method, do everything here */ - lsm_size = lov_stripe_md_size(1); - - LASSERT(!*lsmp); - *lsmp = kzalloc(lsm_size, GFP_NOFS); - if (!*lsmp) - return -ENOMEM; - - (*lsmp)->lsm_oinfo[0] = kzalloc(sizeof(struct lov_oinfo), GFP_NOFS); - if (!(*lsmp)->lsm_oinfo[0]) { - kfree(*lsmp); - return -ENOMEM; - } - - loi_init((*lsmp)->lsm_oinfo[0]); - (*lsmp)->lsm_maxbytes = LUSTRE_EXT3_STRIPE_MAXBYTES; - ostid_set_seq_echo(&(*lsmp)->lsm_oi); - - return lsm_size; -} - -static int echo_free_memmd(struct echo_device *ed, struct lov_stripe_md **lsmp) -{ - int lsm_size; - - /* If export is lov/osc then use their obd method */ - if (ed->ed_next) - return obd_free_memmd(ed->ed_ec->ec_exp, lsmp); - /* OFD has no unpackmd method, do everything here */ - lsm_size = lov_stripe_md_size(1); - - kfree((*lsmp)->lsm_oinfo[0]); - kfree(*lsmp); - *lsmp = NULL; - return 0; -} - static void echo_object_free(const struct lu_env *env, struct lu_object *obj) { struct echo_object *eco = cl2echo_obj(lu2cl(obj)); @@ -490,8 +444,7 @@ static void echo_object_free(const struct lu_env *env, struct lu_object *obj) lu_object_fini(obj); lu_object_header_fini(obj->lo_header); - if (eco->eo_lsm) - echo_free_memmd(eco->eo_dev, &eco->eo_lsm); + kfree(eco->eo_oinfo); kmem_cache_free(echo_object_kmem, eco); } @@ -865,25 +818,21 @@ static struct lu_device_type echo_device_type = { */ /* Interfaces to echo client obd device */ -static struct echo_object *cl_echo_object_find(struct echo_device *d, - struct lov_stripe_md **lsmp) +static struct echo_object * +cl_echo_object_find(struct echo_device *d, const struct ost_id *oi) { struct lu_env *env; struct echo_thread_info *info; struct echo_object_conf *conf; - struct lov_stripe_md *lsm; + struct lov_oinfo *oinfo = NULL; struct echo_object *eco; struct cl_object *obj; struct lu_fid *fid; int refcheck; int rc; - LASSERT(lsmp); - lsm = *lsmp; - LASSERT(lsm); - LASSERTF(ostid_id(&lsm->lsm_oi) != 0, DOSTID"\n", POSTID(&lsm->lsm_oi)); - LASSERTF(ostid_seq(&lsm->lsm_oi) == FID_SEQ_ECHO, DOSTID"\n", - POSTID(&lsm->lsm_oi)); + LASSERTF(ostid_id(oi), DOSTID "\n", POSTID(oi)); + LASSERTF(ostid_seq(oi) == FID_SEQ_ECHO, DOSTID "\n", POSTID(oi)); /* Never return an object if the obd is to be freed. */ if (echo_dev2cl(d)->cd_lu_dev.ld_obd->obd_stopping) @@ -896,16 +845,24 @@ static struct echo_object *cl_echo_object_find(struct echo_device *d, info = echo_env_info(env); conf = &info->eti_conf; if (d->ed_next) { - struct lov_oinfo *oinfo = lsm->lsm_oinfo[0]; + oinfo = kzalloc(sizeof(*oinfo), GFP_NOFS); + if (!oinfo) { + eco = ERR_PTR(-ENOMEM); + goto out; + } - LASSERT(oinfo); - oinfo->loi_oi = lsm->lsm_oi; + oinfo->loi_oi = *oi; conf->eoc_cl.u.coc_oinfo = oinfo; } - conf->eoc_md = lsmp; + + /* + * If echo_object_init() is successful then ownership of oinfo + * is transferred to the object. + */ + conf->eoc_oinfo = &oinfo; fid = &info->eti_fid; - rc = ostid_to_fid(fid, &lsm->lsm_oi, 0); + rc = ostid_to_fid(fid, (struct ost_id *)oi, 0); if (rc != 0) { eco = ERR_PTR(rc); goto out; @@ -928,6 +885,7 @@ static struct echo_object *cl_echo_object_find(struct echo_device *d, } out: + kfree(oinfo); cl_env_put(env, &refcheck); return eco; } @@ -1146,7 +1104,6 @@ static int echo_create_object(const struct lu_env *env, struct echo_device *ed, { struct echo_object *eco; struct echo_client_obd *ec = ed->ed_ec; - struct lov_stripe_md *lsm = NULL; int rc; int created = 0; @@ -1157,30 +1114,19 @@ static int echo_create_object(const struct lu_env *env, struct echo_device *ed, return -EINVAL; } - rc = echo_alloc_memmd(ed, &lsm); - if (rc < 0) { - CERROR("Cannot allocate md: rc = %d\n", rc); - goto failed; - } - - /* setup object ID here */ - lsm->lsm_oi = oa->o_oi; + if (!ostid_id(&oa->o_oi)) + ostid_set_id(&oa->o_oi, ++last_object_id); - if (ostid_id(&lsm->lsm_oi) == 0) - ostid_set_id(&lsm->lsm_oi, ++last_object_id); - - rc = obd_create(env, ec->ec_exp, oa, &lsm, oti); + rc = obd_create(env, ec->ec_exp, oa, oti); if (rc != 0) { CERROR("Cannot create objects: rc = %d\n", rc); goto failed; } created = 1; - /* See what object ID we were given */ - oa->o_oi = lsm->lsm_oi; oa->o_valid |= OBD_MD_FLID; - eco = cl_echo_object_find(ed, &lsm); + eco = cl_echo_object_find(ed, &oa->o_oi); if (IS_ERR(eco)) { rc = PTR_ERR(eco); goto failed; @@ -1191,9 +1137,7 @@ static int echo_create_object(const struct lu_env *env, struct echo_device *ed, failed: if (created && rc) - obd_destroy(env, ec->ec_exp, oa, lsm, oti, NULL); - if (lsm) - echo_free_memmd(ed, &lsm); + obd_destroy(env, ec->ec_exp, oa, NULL, oti, NULL); if (rc) CERROR("create object failed with: rc = %d\n", rc); return rc; @@ -1202,32 +1146,21 @@ static int echo_create_object(const struct lu_env *env, struct echo_device *ed, static int echo_get_object(struct echo_object **ecop, struct echo_device *ed, struct obdo *oa) { - struct lov_stripe_md *lsm = NULL; struct echo_object *eco; int rc; - if ((oa->o_valid & OBD_MD_FLID) == 0 || ostid_id(&oa->o_oi) == 0) { - /* disallow use of object id 0 */ - CERROR("No valid oid\n"); + if (!(oa->o_valid & OBD_MD_FLID) || !(oa->o_valid & OBD_MD_FLGROUP) || + !ostid_id(&oa->o_oi)) { + CERROR("invalid oid " DOSTID "\n", POSTID(&oa->o_oi)); return -EINVAL; } - rc = echo_alloc_memmd(ed, &lsm); - if (rc < 0) - return rc; - - lsm->lsm_oi = oa->o_oi; - if (!(oa->o_valid & OBD_MD_FLGROUP)) - ostid_set_seq_echo(&lsm->lsm_oi); - rc = 0; - eco = cl_echo_object_find(ed, &lsm); + eco = cl_echo_object_find(ed, &oa->o_oi); if (!IS_ERR(eco)) *ecop = eco; else rc = PTR_ERR(eco); - if (lsm) - echo_free_memmd(ed, &lsm); return rc; } diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 2b37c36..7fa35e9 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -398,24 +398,16 @@ static int osc_setattr_async(struct obd_export *exp, struct obd_info *oinfo, oinfo->oi_cb_up, oinfo, rqset); } -static int osc_real_create(struct obd_export *exp, struct obdo *oa, - struct lov_stripe_md **ea, - struct obd_trans_info *oti) +static int osc_create(const struct lu_env *env, struct obd_export *exp, + struct obdo *oa, struct obd_trans_info *oti) { struct ptlrpc_request *req; struct ost_body *body; - struct lov_stripe_md *lsm; int rc; LASSERT(oa); - LASSERT(ea); - - lsm = *ea; - if (!lsm) { - rc = obd_alloc_memmd(exp, &lsm); - if (rc < 0) - return rc; - } + LASSERT(oa->o_valid & OBD_MD_FLGROUP); + LASSERT(fid_seq_is_echo(ostid_seq(&oa->o_oi))); req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_OST_CREATE); if (!req) { @@ -461,13 +453,6 @@ static int osc_real_create(struct obd_export *exp, struct obdo *oa, oa->o_blksize = cli_brw_size(exp->exp_obd); oa->o_valid |= OBD_MD_FLBLKSZ; - /* XXX LOV STACKING: the lsm that is passed to us from LOV does not - * have valid lsm_oinfo data structs, so don't go touching that. - * This needs to be fixed in a big way. - */ - lsm->lsm_oi = oa->o_oi; - *ea = lsm; - if (oti && oa->o_valid & OBD_MD_FLCOOKIE) { if (!oti->oti_logcookies) oti->oti_logcookies = &oti->oti_onecookie; @@ -479,8 +464,6 @@ static int osc_real_create(struct obd_export *exp, struct obdo *oa, out_req: ptlrpc_req_finished(req); out: - if (rc && !*ea) - obd_free_memmd(exp, &lsm); return rc; } @@ -656,25 +639,6 @@ static int osc_can_send_destroy(struct client_obd *cli) return 0; } -static int osc_create(const struct lu_env *env, struct obd_export *exp, - struct obdo *oa, struct lov_stripe_md **ea, - struct obd_trans_info *oti) -{ - int rc = 0; - - LASSERT(oa); - LASSERT(ea); - LASSERT(oa->o_valid & OBD_MD_FLGROUP); - - if (!fid_seq_is_mdt(ostid_seq(&oa->o_oi))) - return osc_real_create(exp, oa, ea, oti); - - /* we should not get here anymore */ - LBUG(); - - return rc; -} - /* Destroy requests can be async always on the client, and we don't even really * care about the return code since the client cannot do anything at all about * a destroy failure. -- cgit v0.10.2 From 3f062072a50f3a2dd4b11ca20e65ea7c3fd8c086 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Sun, 18 Sep 2016 16:38:12 -0400 Subject: staging: lustre: llite: remove ll_objects_destroy() Remove ll_objects_destroy(). This function is not needed for interoperability with servers of version 2.4 or higher. Remove the then unused function lov_destroy() and its supporting functions. Remove the lsm_destroy method of struct lsm_operations. Remove the unused struct lov_stripe_md, MD export, and capa parameters from obd_destroy() and its implementations. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5814 Reviewed-on: http://review.whamcloud.com/12618 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Lai Siyao <lai.siyao@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index ca63891..cd7f552 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -869,8 +869,7 @@ struct obd_ops { int (*create)(const struct lu_env *env, struct obd_export *exp, struct obdo *oa, struct obd_trans_info *oti); int (*destroy)(const struct lu_env *env, struct obd_export *exp, - struct obdo *oa, struct lov_stripe_md *ea, - struct obd_trans_info *oti, struct obd_export *md_exp); + struct obdo *oa, struct obd_trans_info *oti); int (*setattr)(const struct lu_env *, struct obd_export *exp, struct obd_info *oinfo, struct obd_trans_info *oti); int (*setattr_async)(struct obd_export *exp, struct obd_info *oinfo, @@ -1058,8 +1057,6 @@ struct md_ops { struct lsm_operations { void (*lsm_free)(struct lov_stripe_md *); - int (*lsm_destroy)(struct lov_stripe_md *, struct obdo *oa, - struct obd_export *md_exp); void (*lsm_stripe_by_index)(struct lov_stripe_md *, int *, u64 *, u64 *); void (*lsm_stripe_by_offset)(struct lov_stripe_md *, int *, u64 *, diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index 2bf2826..9836aed 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -702,16 +702,14 @@ static inline int obd_create(const struct lu_env *env, struct obd_export *exp, } static inline int obd_destroy(const struct lu_env *env, struct obd_export *exp, - struct obdo *obdo, struct lov_stripe_md *ea, - struct obd_trans_info *oti, - struct obd_export *md_exp) + struct obdo *obdo, struct obd_trans_info *oti) { int rc; EXP_CHECK_DT_OP(exp, destroy); EXP_COUNTER_INCREMENT(exp, destroy); - rc = OBP(exp->exp_obd, destroy)(env, exp, obdo, ea, oti, md_exp); + rc = OBP(exp->exp_obd, destroy)(env, exp, obdo, oti); return rc; } diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index a562b11..0b3b387 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -189,12 +189,6 @@ static int ll_close_inode_openhandle(struct obd_export *md_exp, spin_unlock(&lli->lli_lock); } - if (rc == 0) { - rc = ll_objects_destroy(req, inode); - if (rc) - CERROR("inode %lu ll_objects destroy: rc = %d\n", - inode->i_ino, rc); - } if (rc == 0 && op_data->op_bias & MDS_HSM_RELEASE) { struct mdt_body *body; diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index bdfdff5..0dc47f2 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -721,8 +721,6 @@ void ll_release_page(struct inode *inode, struct page *page, bool remove); /* llite/namei.c */ extern const struct inode_operations ll_special_inode_operations; -int ll_objects_destroy(struct ptlrpc_request *request, - struct inode *dir); struct inode *ll_iget(struct super_block *sb, ino_t hash, struct lustre_md *lic); int ll_test_inode_by_fid(struct inode *inode, void *opaque); diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index 494140a..1dd5df5 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -890,77 +890,6 @@ static int ll_create_nd(struct inode *dir, struct dentry *dentry, return rc; } -int ll_objects_destroy(struct ptlrpc_request *request, struct inode *dir) -{ - struct mdt_body *body; - struct lov_mds_md *eadata; - struct lov_stripe_md *lsm = NULL; - struct obd_trans_info oti = { 0 }; - struct obdo *oa; - int rc; - - /* req is swabbed so this is safe */ - body = req_capsule_server_get(&request->rq_pill, &RMF_MDT_BODY); - if (!(body->mbo_valid & OBD_MD_FLEASIZE)) - return 0; - - if (body->mbo_eadatasize == 0) { - CERROR("OBD_MD_FLEASIZE set but eadatasize zero\n"); - rc = -EPROTO; - goto out; - } - - /* The MDS sent back the EA because we unlinked the last reference - * to this file. Use this EA to unlink the objects on the OST. - * It's opaque so we don't swab here; we leave it to obd_unpackmd() to - * check it is complete and sensible. - */ - eadata = req_capsule_server_sized_get(&request->rq_pill, &RMF_MDT_MD, - body->mbo_eadatasize); - LASSERT(eadata); - - rc = obd_unpackmd(ll_i2dtexp(dir), &lsm, eadata, body->mbo_eadatasize); - if (rc < 0) { - CERROR("obd_unpackmd: %d\n", rc); - goto out; - } - LASSERT(rc >= sizeof(*lsm)); - - oa = kmem_cache_zalloc(obdo_cachep, GFP_NOFS); - if (!oa) { - rc = -ENOMEM; - goto out_free_memmd; - } - - oa->o_oi = lsm->lsm_oi; - oa->o_mode = body->mbo_mode & S_IFMT; - oa->o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLGROUP; - - if (body->mbo_valid & OBD_MD_FLCOOKIE) { - oa->o_valid |= OBD_MD_FLCOOKIE; - oti.oti_logcookies = - req_capsule_server_sized_get(&request->rq_pill, - &RMF_LOGCOOKIES, - sizeof(struct llog_cookie) * - lsm->lsm_stripe_count); - if (!oti.oti_logcookies) { - oa->o_valid &= ~OBD_MD_FLCOOKIE; - body->mbo_valid &= ~OBD_MD_FLCOOKIE; - } - } - - rc = obd_destroy(NULL, ll_i2dtexp(dir), oa, lsm, &oti, - ll_i2mdexp(dir)); - if (rc) - CERROR("obd destroy objid "DOSTID" error %d\n", - POSTID(&lsm->lsm_oi), rc); -out_free_memmd: - obd_free_memmd(ll_i2dtexp(dir), &lsm); - kmem_cache_free(obdo_cachep, oa); -out: - return rc; -} - /* ll_unlink() doesn't update the inode with the new link count. * Instead, ll_ddelete() and ll_d_iput() will update it based upon if there * is any lock existing. They will recycle dentries and inodes based upon locks @@ -994,7 +923,6 @@ static int ll_unlink(struct inode *dir, struct dentry *dchild) ll_update_times(request, dir); ll_stats_ops_tally(ll_i2sbi(dir), LPROC_LL_UNLINK, 1); - rc = ll_objects_destroy(request, dir); out: ptlrpc_req_finished(request); return rc; @@ -1130,7 +1058,6 @@ static int ll_rename(struct inode *src, struct dentry *src_dchild, ll_update_times(request, src); ll_update_times(request, tgt); ll_stats_ops_tally(sbi, LPROC_LL_RENAME, 1); - err = ll_objects_destroy(request, src); } ptlrpc_req_finished(request); diff --git a/drivers/staging/lustre/lustre/lov/lov_ea.c b/drivers/staging/lustre/lustre/lov/lov_ea.c index 9f0b5b7..214c561 100644 --- a/drivers/staging/lustre/lustre/lov/lov_ea.c +++ b/drivers/staging/lustre/lustre/lov/lov_ea.c @@ -147,12 +147,6 @@ lsm_stripe_by_offset_plain(struct lov_stripe_md *lsm, int *stripeno, *swidth = (u64)lsm->lsm_stripe_size * lsm->lsm_stripe_count; } -static int lsm_destroy_plain(struct lov_stripe_md *lsm, struct obdo *oa, - struct obd_export *md_exp) -{ - return 0; -} - /* Find minimum stripe maxbytes value. For inactive or * reconnecting targets use LUSTRE_EXT3_STRIPE_MAXBYTES. */ @@ -246,7 +240,6 @@ static int lsm_unpackmd_v1(struct lov_obd *lov, struct lov_stripe_md *lsm, const struct lsm_operations lsm_v1_ops = { .lsm_free = lsm_free_plain, - .lsm_destroy = lsm_destroy_plain, .lsm_stripe_by_index = lsm_stripe_by_index_plain, .lsm_stripe_by_offset = lsm_stripe_by_offset_plain, .lsm_lmm_verify = lsm_lmm_verify_v1, @@ -336,7 +329,6 @@ static int lsm_unpackmd_v3(struct lov_obd *lov, struct lov_stripe_md *lsm, const struct lsm_operations lsm_v3_ops = { .lsm_free = lsm_free_plain, - .lsm_destroy = lsm_destroy_plain, .lsm_stripe_by_index = lsm_stripe_by_index_plain, .lsm_stripe_by_offset = lsm_stripe_by_offset_plain, .lsm_lmm_verify = lsm_lmm_verify_v3, diff --git a/drivers/staging/lustre/lustre/lov/lov_internal.h b/drivers/staging/lustre/lustre/lov/lov_internal.h index 5ddaeda..0e5fc2e 100644 --- a/drivers/staging/lustre/lustre/lov/lov_internal.h +++ b/drivers/staging/lustre/lustre/lov/lov_internal.h @@ -155,11 +155,6 @@ int lov_update_common_set(struct lov_request_set *set, int lov_prep_getattr_set(struct obd_export *exp, struct obd_info *oinfo, struct lov_request_set **reqset); int lov_fini_getattr_set(struct lov_request_set *set); -int lov_prep_destroy_set(struct obd_export *exp, struct obd_info *oinfo, - struct obdo *src_oa, struct lov_stripe_md *lsm, - struct obd_trans_info *oti, - struct lov_request_set **reqset); -int lov_fini_destroy_set(struct lov_request_set *set); int lov_prep_setattr_set(struct obd_export *exp, struct obd_info *oinfo, struct obd_trans_info *oti, struct lov_request_set **reqset); diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index f433515..9b12159 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -980,59 +980,6 @@ do { \ "%p->lsm_magic=%x\n", (lsmp), (lsmp)->lsm_magic); \ } while (0) -static int lov_destroy(const struct lu_env *env, struct obd_export *exp, - struct obdo *oa, struct lov_stripe_md *lsm, - struct obd_trans_info *oti, struct obd_export *md_exp) -{ - struct lov_request_set *set; - struct obd_info oinfo; - struct lov_request *req; - struct lov_obd *lov; - int rc = 0, err = 0; - - ASSERT_LSM_MAGIC(lsm); - - if (!exp || !exp->exp_obd) - return -ENODEV; - - if (oa->o_valid & OBD_MD_FLCOOKIE) { - LASSERT(oti); - LASSERT(oti->oti_logcookies); - } - - lov = &exp->exp_obd->u.lov; - obd_getref(exp->exp_obd); - rc = lov_prep_destroy_set(exp, &oinfo, oa, lsm, oti, &set); - if (rc) - goto out; - - list_for_each_entry(req, &set->set_list, rq_link) { - if (oa->o_valid & OBD_MD_FLCOOKIE) - oti->oti_logcookies = set->set_cookies + req->rq_stripe; - - err = obd_destroy(env, lov->lov_tgts[req->rq_idx]->ltd_exp, - req->rq_oi.oi_oa, NULL, oti, NULL); - err = lov_update_common_set(set, req, err); - if (err) { - CERROR("%s: destroying objid "DOSTID" subobj " - DOSTID" on OST idx %d: rc = %d\n", - exp->exp_obd->obd_name, POSTID(&oa->o_oi), - POSTID(&req->rq_oi.oi_oa->o_oi), - req->rq_idx, err); - if (!rc) - rc = err; - } - } - - if (rc == 0) - rc = lsm_op_find(lsm->lsm_magic)->lsm_destroy(lsm, oa, md_exp); - - err = lov_fini_destroy_set(set); -out: - obd_putref(exp->exp_obd); - return rc ? rc : err; -} - static int lov_getattr_interpret(struct ptlrpc_request_set *rqset, void *data, int rc) { @@ -2081,7 +2028,6 @@ static struct obd_ops lov_obd_ops = { .statfs_async = lov_statfs_async, .packmd = lov_packmd, .unpackmd = lov_unpackmd, - .destroy = lov_destroy, .getattr_async = lov_getattr_async, .setattr_async = lov_setattr_async, .iocontrol = lov_iocontrol, diff --git a/drivers/staging/lustre/lustre/lov/lov_request.c b/drivers/staging/lustre/lustre/lov/lov_request.c index 4099b51..09dcaf4 100644 --- a/drivers/staging/lustre/lustre/lov/lov_request.c +++ b/drivers/staging/lustre/lustre/lov/lov_request.c @@ -325,84 +325,6 @@ out_set: return rc; } -int lov_fini_destroy_set(struct lov_request_set *set) -{ - if (!set) - return 0; - LASSERT(set->set_exp); - if (atomic_read(&set->set_completes)) { - /* FIXME update qos data here */ - } - - lov_put_reqset(set); - - return 0; -} - -int lov_prep_destroy_set(struct obd_export *exp, struct obd_info *oinfo, - struct obdo *src_oa, struct lov_stripe_md *lsm, - struct obd_trans_info *oti, - struct lov_request_set **reqset) -{ - struct lov_request_set *set; - struct lov_obd *lov = &exp->exp_obd->u.lov; - int rc = 0, i; - - set = kzalloc(sizeof(*set), GFP_NOFS); - if (!set) - return -ENOMEM; - lov_init_set(set); - - set->set_exp = exp; - set->set_oi = oinfo; - set->set_oi->oi_md = lsm; - set->set_oi->oi_oa = src_oa; - if (oti && src_oa->o_valid & OBD_MD_FLCOOKIE) - set->set_cookies = oti->oti_logcookies; - - for (i = 0; i < lsm->lsm_stripe_count; i++) { - struct lov_oinfo *loi; - struct lov_request *req; - - loi = lsm->lsm_oinfo[i]; - if (lov_oinfo_is_dummy(loi)) - continue; - - if (!lov_check_and_wait_active(lov, loi->loi_ost_idx)) { - CDEBUG(D_HA, "lov idx %d inactive\n", loi->loi_ost_idx); - continue; - } - - req = kzalloc(sizeof(*req), GFP_NOFS); - if (!req) { - rc = -ENOMEM; - goto out_set; - } - - req->rq_stripe = i; - req->rq_idx = loi->loi_ost_idx; - - req->rq_oi.oi_oa = kmem_cache_zalloc(obdo_cachep, GFP_NOFS); - if (!req->rq_oi.oi_oa) { - kfree(req); - rc = -ENOMEM; - goto out_set; - } - memcpy(req->rq_oi.oi_oa, src_oa, sizeof(*req->rq_oi.oi_oa)); - req->rq_oi.oi_oa->o_oi = loi->loi_oi; - lov_set_add_req(req, set); - } - if (!set->set_count) { - rc = -EIO; - goto out_set; - } - *reqset = set; - return rc; -out_set: - lov_fini_destroy_set(set); - return rc; -} - int lov_fini_setattr_set(struct lov_request_set *set) { int rc = 0; diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index 3218ca1..f3693d7 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -1137,7 +1137,7 @@ static int echo_create_object(const struct lu_env *env, struct echo_device *ed, failed: if (created && rc) - obd_destroy(env, ec->ec_exp, oa, NULL, oti, NULL); + obd_destroy(env, ec->ec_exp, oa, oti); if (rc) CERROR("create object failed with: rc = %d\n", rc); return rc; @@ -1546,8 +1546,7 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len, rc = echo_get_object(&eco, ed, oa); if (rc == 0) { - rc = obd_destroy(env, ec->ec_exp, oa, NULL, - &dummy_oti, NULL); + rc = obd_destroy(env, ec->ec_exp, oa, &dummy_oti); if (rc == 0) eco->eo_deleted = 1; echo_put_object(eco); diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 7fa35e9..67b72c8 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -651,8 +651,7 @@ static int osc_can_send_destroy(struct client_obd *cli) * cookies to the MDS after committing destroy transactions. */ static int osc_destroy(const struct lu_env *env, struct obd_export *exp, - struct obdo *oa, struct lov_stripe_md *ea, - struct obd_trans_info *oti, struct obd_export *md_export) + struct obdo *oa, struct obd_trans_info *oti) { struct client_obd *cli = &exp->exp_obd->u.cli; struct ptlrpc_request *req; -- cgit v0.10.2 From 347c7aed9e1b009a0d1bc7defdf93d3a760817a0 Mon Sep 17 00:00:00 2001 From: Henri Doreau <henri.doreau@cea.fr> Date: Sun, 18 Sep 2016 16:38:13 -0400 Subject: staging: lustre: changelog: Proper record remapping Fixed changelog_remap_rec() to correctly remap records emitted with jobid_var=disabled, i.e. delivered by new servers but with no jobid field. Signed-off-by: Henri Doreau <henri.doreau@cea.fr> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5862 Reviewed-on: http://review.whamcloud.com/12574 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Robert Read <robert.read@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index e8f81a5..ba679ad 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -881,41 +881,63 @@ static inline char *changelog_rec_sname(struct changelog_rec *rec) return cr_name + strlen(cr_name) + 1; } -/* +/** * Remap a record to the desired format as specified by the crf flags. * The record must be big enough to contain the final remapped version. + * Superfluous extension fields are removed and missing ones are added + * and zeroed. The flags of the record are updated accordingly. + * + * The jobid and rename extensions can be added to a record, to match the + * format an application expects, typically. In this case, the newly added + * fields will be zeroed. + * The Jobid field can be removed, to guarantee compatibility with older + * clients that don't expect this field in the records they process. + * + * The following assumptions are being made: + * - CLF_RENAME will not be removed + * - CLF_JOBID will not be added without CLF_RENAME being added too + * + * @param[in,out] rec The record to remap. + * @param[in] crf_wanted Flags describing the desired extensions. */ static inline void changelog_remap_rec(struct changelog_rec *rec, - enum changelog_rec_flags crf) + enum changelog_rec_flags crf_wanted) { - size_t var_size; - char *var_part; + char *jid_mov, *rnm_mov; - crf &= CLF_SUPPORTED; + crf_wanted &= CLF_SUPPORTED; - if ((rec->cr_flags & CLF_SUPPORTED) == crf) + if ((rec->cr_flags & CLF_SUPPORTED) == crf_wanted) return; - if ((crf & CLF_JOBID) && rec->cr_flags & CLF_JOBID) { - var_part = (char *)changelog_rec_jobid(rec); - var_size = rec->cr_namelen + sizeof(struct changelog_ext_jobid); - } else { - var_part = changelog_rec_name(rec); - var_size = rec->cr_namelen; - } + /* First move the variable-length name field */ + memmove((char *)rec + changelog_rec_offset(crf_wanted), + changelog_rec_name(rec), rec->cr_namelen); + + /* Locations of jobid and rename extensions in the remapped record */ + jid_mov = (char *)rec + + changelog_rec_offset(crf_wanted & ~CLF_JOBID); + rnm_mov = (char *)rec + + changelog_rec_offset(crf_wanted & ~(CLF_JOBID | CLF_RENAME)); + + /* Move the extension fields to the desired positions */ + if ((crf_wanted & CLF_JOBID) && (rec->cr_flags & CLF_JOBID)) + memmove(jid_mov, changelog_rec_jobid(rec), + sizeof(struct changelog_ext_jobid)); - memmove((char *)rec + changelog_rec_offset(crf & ~CLF_JOBID), var_part, - var_size); + if ((crf_wanted & CLF_RENAME) && (rec->cr_flags & CLF_RENAME)) + memmove(rnm_mov, changelog_rec_rename(rec), + sizeof(struct changelog_ext_rename)); - if ((crf & CLF_RENAME) && !(rec->cr_flags & CLF_RENAME)) - memset(changelog_rec_rename(rec), 0, - sizeof(struct changelog_ext_rename)); + /* Clear newly added fields */ + if ((crf_wanted & CLF_JOBID) && !(rec->cr_flags & CLF_JOBID)) + memset(jid_mov, 0, sizeof(struct changelog_ext_jobid)); - if ((crf & CLF_JOBID) && !(rec->cr_flags & CLF_JOBID)) - memset(changelog_rec_jobid(rec), 0, - sizeof(struct changelog_ext_jobid)); + if ((crf_wanted & CLF_RENAME) && !(rec->cr_flags & CLF_RENAME)) + memset(rnm_mov, 0, sizeof(struct changelog_ext_rename)); - rec->cr_flags = (rec->cr_flags & CLF_FLAGMASK) | crf; + /* Update the record's flags accordingly */ + rec->cr_flags = (rec->cr_flags & CLF_FLAGMASK) | crf_wanted; } struct ioc_changelog { -- cgit v0.10.2 From eda3565c3654fe98b2f7b61db0ad0307672fa25d Mon Sep 17 00:00:00 2001 From: Niu Yawei <yawei.niu@intel.com> Date: Sun, 18 Sep 2016 16:38:14 -0400 Subject: staging: lustre: recovery: don't replay closed open To avoid scanning the replay open list every time in the ptlrpc_free_committed(), the fix of LU-2613 (4322e0f9) changed the ptlrpc_free_committed() to skip the open list unless the import generation is changed. That introduced a race which could make a closed open being replayed: 1. Application calls ll_close_inode_openhandle()-> mdc_close(), to close file, rq_replay is cleared, but the open request is still on the imp_committed_list; 2. Before the md_clear_open_replay_data() is called for close, client start replay, and that closed open will be replayed mistakenly; 3. Open replay interpret callback (mdc_replay_open) could race with the mdc_clear_open_replay_data() at the end; This patch fix the ptlrpc_free_committed() to make sure the open list is scanned on recovery to prevent the closed open request from being replayed. Signed-off-by: Niu Yawei <yawei.niu@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5507 Reviewed-on: http://review.whamcloud.com/12667 Reviewed-by: Lai Siyao <lai.siyao@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index 27fe00d..a29ccaa 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -2455,7 +2455,8 @@ void ptlrpc_free_committed(struct obd_import *imp) imp->imp_obd->obd_name, imp->imp_peer_committed_transno, imp->imp_generation); - if (imp->imp_generation != imp->imp_last_generation_checked) + if (imp->imp_generation != imp->imp_last_generation_checked || + !imp->imp_last_transno_checked) skip_committed_list = false; imp->imp_last_transno_checked = imp->imp_peer_committed_transno; @@ -2503,6 +2504,9 @@ free_req: if (req->rq_import_generation < imp->imp_generation) { DEBUG_REQ(D_RPCTRACE, req, "free stale open request"); ptlrpc_free_request(req); + } else if (!req->rq_replay) { + DEBUG_REQ(D_RPCTRACE, req, "free closed open request"); + ptlrpc_free_request(req); } } } -- cgit v0.10.2 From 08fd034670b505c0ce1685404acaed0a4c073ef9 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong <jinshan.xiong@intel.com> Date: Sun, 18 Sep 2016 16:38:15 -0400 Subject: staging: lustre: ldlm: revert the changes for lock canceling policy The changes for LRU lock policy was introduced by commit bfae5a4e, where I was trying to revise the policy to pick locks for canceling. However, this caused two problems as mentioned in LU-5727. The first problem is that the lock can only be picked for canceling only if the number of LRU locks is over preset LRU number AND it's aged; the second problem is that mdc_cancel_weight() tends to not cancel OPEN locks, therefore open locks can be kept forever and finally exhausts memory on the MDT side. The commit 7b2d26b0 ("revert changes to ldlm_cancel_aged_policy") fixed the first problem. This patch will revert the rest of changes related to LRU policy revise. Signed-off-by: Jinshan Xiong <jinshan.xiong@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5727 Reviewed-on: http://review.whamcloud.com/12733 Reviewed-by: Niu Yawei <yawei.niu@intel.com> Reviewed-by: Bobi Jam <bobijam@gmail.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index 46842dd..582de52 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -1198,9 +1198,6 @@ static enum ldlm_policy_res ldlm_cancel_lrur_policy(struct ldlm_namespace *ns, if (slv == 0 || lv < slv) return LDLM_POLICY_KEEP_LOCK; - if (ns->ns_cancel && ns->ns_cancel(lock) == 0) - return LDLM_POLICY_KEEP_LOCK; - return LDLM_POLICY_CANCEL_LOCK; } @@ -1244,9 +1241,6 @@ static enum ldlm_policy_res ldlm_cancel_aged_policy(struct ldlm_namespace *ns, cfs_time_add(lock->l_last_used, ns->ns_max_age))) return LDLM_POLICY_KEEP_LOCK; - if (ns->ns_cancel && ns->ns_cancel(lock) == 0) - return LDLM_POLICY_KEEP_LOCK; - return LDLM_POLICY_CANCEL_LOCK; } -- cgit v0.10.2 From 50932a2280970723a3a4f58cff929c92f65fc60b Mon Sep 17 00:00:00 2001 From: Andreas Dilger <andreas.dilger@intel.com> Date: Sun, 18 Sep 2016 16:38:16 -0400 Subject: staging: lustre: ptlrpc: quiet errors on initial connection It may be that a client or MDS is trying to connect to a target (OST or peer MDT) before that target is finished setup. Rather than spamming the console logs during initial connection, only print a console error message if there are repeated failures trying to connect to the target, which may indicate an error on that node. Signed-off-by: Andreas Dilger <andreas.dilger@intel.com> Signed-off-by: Bobi Jam <bobijam.xu@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3456 Reviewed-on: http://review.whamcloud.com/10057 Reviewed-by: Bobi Jam <bobijam@gmail.com> Reviewed-by: Bob Glossman <bob.glossman@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index a29ccaa..f3914cc3 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -1075,36 +1075,42 @@ static int ptlrpc_import_delay_req(struct obd_import *imp, } /** - * Decide if the error message regarding provided request \a req - * should be printed to the console or not. - * Makes it's decision on request status and other properties. - * Returns 1 to print error on the system console or 0 if not. + * Decide if the error message should be printed to the console or not. + * Makes its decision based on request type, status, and failure frequency. + * + * \param[in] req request that failed and may need a console message + * + * \retval false if no message should be printed + * \retval true if console message should be printed */ -static int ptlrpc_console_allow(struct ptlrpc_request *req) +static bool ptlrpc_console_allow(struct ptlrpc_request *req) { __u32 opc; - int err; LASSERT(req->rq_reqmsg); opc = lustre_msg_get_opc(req->rq_reqmsg); - /* - * Suppress particular reconnect errors which are to be expected. No - * errors are suppressed for the initial connection on an import - */ - if ((lustre_handle_is_used(&req->rq_import->imp_remote_handle)) && - (opc == OST_CONNECT || opc == MDS_CONNECT || opc == MGS_CONNECT)) { + /* Suppress particular reconnect errors which are to be expected. */ + if (opc == OST_CONNECT || opc == MDS_CONNECT || opc == MGS_CONNECT) { + int err; + /* Suppress timed out reconnect requests */ - if (req->rq_timedout) - return 0; + if (lustre_handle_is_used(&req->rq_import->imp_remote_handle) || + req->rq_timedout) + return false; - /* Suppress unavailable/again reconnect requests */ + /* + * Suppress most unavailable/again reconnect requests, but + * print occasionally so it is clear client is trying to + * connect to a server where no target is running. + */ err = lustre_msg_get_status(req->rq_repmsg); - if (err == -ENODEV || err == -EAGAIN) - return 0; + if ((err == -ENODEV || err == -EAGAIN) && + req->rq_import->imp_conn_cnt % 30 != 20) + return false; } - return 1; + return true; } /** @@ -1118,14 +1124,14 @@ static int ptlrpc_check_status(struct ptlrpc_request *req) err = lustre_msg_get_status(req->rq_repmsg); if (lustre_msg_get_type(req->rq_repmsg) == PTL_RPC_MSG_ERR) { struct obd_import *imp = req->rq_import; + lnet_nid_t nid = imp->imp_connection->c_peer.nid; __u32 opc = lustre_msg_get_opc(req->rq_reqmsg); if (ptlrpc_console_allow(req)) - LCONSOLE_ERROR_MSG(0x011, "%s: Communicating with %s, operation %s failed with %d.\n", + LCONSOLE_ERROR_MSG(0x011, "%s: operation %s to node %s failed: rc = %d\n", imp->imp_obd->obd_name, - libcfs_nid2str( - imp->imp_connection->c_peer.nid), - ll_opcode2str(opc), err); + ll_opcode2str(opc), + libcfs_nid2str(nid), err); return err < 0 ? err : -EINVAL; } @@ -1282,7 +1288,7 @@ static int after_reply(struct ptlrpc_request *req) * some reason. Try to reconnect, and if that fails, punt to * the upcall. */ - if (ll_rpc_recoverable_error(rc)) { + if (ptlrpc_recoverable_error(rc)) { if (req->rq_send_state != LUSTRE_IMP_FULL || imp->imp_obd->obd_no_recov || imp->imp_dlm_fake) { return rc; diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h index 29cfac2..b420aa8 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h @@ -270,7 +270,7 @@ void sptlrpc_conf_fini(void); int sptlrpc_init(void); void sptlrpc_fini(void); -static inline int ll_rpc_recoverable_error(int rc) +static inline bool ptlrpc_recoverable_error(int rc) { return (rc == -ENOTCONN || rc == -ENODEV); } -- cgit v0.10.2 From 2ce3647e9aba981f968f42f75f6b0af79332fee3 Mon Sep 17 00:00:00 2001 From: frank zago <fzago@cray.com> Date: Sun, 18 Sep 2016 16:38:17 -0400 Subject: staging: lustre: llog: prevent out-of-bound index llog_process_thread() can be called from llog_cat_process_cb with an index already out of bound, leading to the following crash: LustreError: 3773:0:(llog.c:310:llog_process_thread()) ASSERTION(index <= last_index + 1 ) failed: LustreError: 3773:0:(llog.c:310:llog_process_thread()) LBUG #0 [ffff8801144bf900] machine_kexec at ffffffff81038f3b #1 [ffff8801144bf960] crash_kexec at ffffffff810c5d82 #2 [ffff8801144bfa30] panic at ffffffff8152798a #3 [ffff8801144bfab0] lbug_with_loc at ffffffffa02f8eeb [libcfs] #4 [ffff8801144bfad0] llog_process_thread at ffffffffa0413fff [obdclass] #5 [ffff8801144bfb80] llog_process_or_fork at ffffffffa041585f [obdclass] #6 [ffff8801144bfbd0] llog_cat_process_cb at ffffffffa0418612 [obdclass] #7 [ffff8801144bfc30] llog_process_thread at ffffffffa0413c22 [obdclass] #8 [ffff8801144bfce0] llog_process_or_fork at ffffffffa041585f [obdclass] #9 [ffff8801144bfd30] llog_cat_process_or_fork at ffffffffa0416b9d [obdclass] If index is too big, simply return success. Signed-off-by: frank zago <fzago@cray.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5635 Reviewed-on: http://review.whamcloud.com/12161 Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Patrick Farrell <paf@cray.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/obdclass/llog.c b/drivers/staging/lustre/lustre/obdclass/llog.c index 119372c..43797f1 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog.c +++ b/drivers/staging/lustre/lustre/obdclass/llog.c @@ -235,6 +235,10 @@ static int llog_process_thread(void *arg) else last_index = LLOG_BITMAP_BYTES * 8 - 1; + /* Record is not in this buffer. */ + if (index > last_index) + goto out; + while (rc == 0) { struct llog_rec_hdr *rec; -- cgit v0.10.2 From 816afc79f8370841c2f2b460cf93ba6ab74f99d7 Mon Sep 17 00:00:00 2001 From: Bob Glossman <bob.glossman@intel.com> Date: Sun, 18 Sep 2016 16:38:19 -0400 Subject: staging: lustre: llite: fix dup flags names The name 'xattr' is used for two different ll_flags bits. Change the names to be distinct and different, reflecting the names of the bits used in LL_SBI_xbitnamex #defines. Signed-off-by: Bob Glossman <bob.glossman@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5586 Reviewed-on: http://review.whamcloud.com/12892 Reviewed-by: Minh Diep <minh.diep@intel.com> Reviewed-by: Jian Yu <jian.yu@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 0dc47f2..05f2aa3 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -407,7 +407,7 @@ enum stats_track_type { "nolck", \ "checksum", \ "flock", \ - "xattr", \ + "user_xattr", \ "acl", \ "???", \ "???", \ @@ -423,7 +423,7 @@ enum stats_track_type { "verbose", \ "layout", \ "user_fid2path",\ - "xattr", \ + "xattr_cache", \ "norootsquash", \ } -- cgit v0.10.2 From ba40ae79f1f7c104b4bd2fcc5df2c949e379aa0d Mon Sep 17 00:00:00 2001 From: Dmitry Eremin <dmitry.eremin@intel.com> Date: Sun, 18 Sep 2016 16:38:20 -0400 Subject: staging: lustre: obdclass: lu_htable_order() return type to long Change the type accordant usage. Signed-off-by: Dmitry Eremin <dmitry.eremin@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5577 Reviewed-on: http://review.whamcloud.com/12385 Reviewed-by: Bob Glossman <bob.glossman@intel.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c index 4395117..7339c8b 100644 --- a/drivers/staging/lustre/lustre/obdclass/lu_object.c +++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c @@ -352,7 +352,7 @@ int lu_site_purge(const struct lu_env *env, struct lu_site *s, int nr) * the dispose list, removing them from LRU and hash table. */ start = s->ls_purge_start; - bnr = (nr == ~0) ? -1 : nr / CFS_HASH_NBKT(s->ls_obj_hash) + 1; + bnr = (nr == ~0) ? -1 : nr / (int)CFS_HASH_NBKT(s->ls_obj_hash) + 1; again: /* * It doesn't make any sense to make purge threads parallel, that can @@ -869,11 +869,11 @@ EXPORT_SYMBOL(lu_site_print); /** * Return desired hash table order. */ -static unsigned int lu_htable_order(struct lu_device *top) +static unsigned long lu_htable_order(struct lu_device *top) { unsigned long bits_max = LU_SITE_BITS_MAX; unsigned long cache_size; - unsigned int bits; + unsigned long bits; /* * Calculate hash table size, assuming that we want reasonable @@ -990,7 +990,7 @@ int lu_site_init(struct lu_site *s, struct lu_device *top) memset(s, 0, sizeof(*s)); mutex_init(&s->ls_purge_mutex); - snprintf(name, 16, "lu_site_%s", top->ld_type->ldt_name); + snprintf(name, sizeof(name), "lu_site_%s", top->ld_type->ldt_name); for (bits = lu_htable_order(top); bits >= LU_SITE_BITS_MIN; bits--) { s->ls_obj_hash = cfs_hash_create(name, bits, bits, bits - LU_SITE_BKT_BITS, -- cgit v0.10.2 From 8971ee5bc1ab24eb63ac379b7bd7e16619862834 Mon Sep 17 00:00:00 2001 From: Yoshifumi Uemura <kogexe@gmail.com> Date: Sun, 18 Sep 2016 16:38:21 -0400 Subject: staging: lustre: mdc: Proper accessing struct lov_user_md In mdc_setattr_pack() access the members of struct lov_user_md by little endian byte order. Signed-off-by: Yoshifumi Uemura <kogexe@gmail.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5889 Reviewed-on: http://review.whamcloud.com/12683 Reviewed-by: Dmitry Eremin <dmitry.eremin@intel.com> Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: Yang Sheng <yang.sheng@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/mdc/mdc_lib.c b/drivers/staging/lustre/lustre/mdc/mdc_lib.c index 82d1c4d..aac7e04 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_lib.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_lib.c @@ -328,7 +328,7 @@ void mdc_setattr_pack(struct ptlrpc_request *req, struct md_op_data *op_data, lum = req_capsule_client_get(&req->rq_pill, &RMF_EADATA); if (!ea) { /* Remove LOV EA */ - lum->lmm_magic = LOV_USER_MAGIC_V1; + lum->lmm_magic = cpu_to_le32(LOV_USER_MAGIC_V1); lum->lmm_stripe_size = 0; lum->lmm_stripe_count = 0; lum->lmm_stripe_offset = (typeof(lum->lmm_stripe_offset))(-1); -- cgit v0.10.2 From c86a6c1189a182c3b2670bbc91c3e66123c0cdba Mon Sep 17 00:00:00 2001 From: Alexey Lyashkov <alexey_lyashkov@xyratex.com> Date: Sun, 18 Sep 2016 16:38:22 -0400 Subject: staging: lustre: ldlm: evict clients returning errors on ASTs To test proper behavior of clients returning errors on ASTs we can induce a failure with setting OBD_FAIL_LDLM_BL_CALLBACK_NET. Handle the new additonal case of cfs_fail_err being set as well so that the cfs_fail_err can be sent back in a reply. Signed-off-by: Alexey Lyashkov <alexey_lyashkov@xyratex.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5581 Xyratex-bug-id: MRP-2041 Reviewed-on: http://review.whamcloud.com/11752 Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c index b91b26d..ff2c28e 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c @@ -559,8 +559,11 @@ static int ldlm_callback_handler(struct ptlrpc_request *req) switch (lustre_msg_get_opc(req->rq_reqmsg)) { case LDLM_BL_CALLBACK: - if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_BL_CALLBACK_NET)) + if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_BL_CALLBACK_NET)) { + if (cfs_fail_err) + ldlm_callback_reply(req, -(int)cfs_fail_err); return 0; + } break; case LDLM_CP_CALLBACK: if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_CP_CALLBACK_NET)) -- cgit v0.10.2 From 5e6bcb48b6b0c752132a393c98d19912564984b7 Mon Sep 17 00:00:00 2001 From: Bobi Jam <bobijam.xu@intel.com> Date: Sun, 18 Sep 2016 16:38:23 -0400 Subject: staging: lustre: fiemap: set FIEMAP_EXTENT_LAST correctly When we've collected enough extents as user requested, we'd check one further to decide whether we've reached the last extent of the file. Signed-off-by: Bobi Jam <bobijam.xu@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5933 Reviewed-on: http://review.whamcloud.com/12781 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index 9b12159..9ab3033 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -1548,6 +1548,8 @@ static int lov_fiemap(struct lov_obd *lov, __u32 keylen, void *key, u64 fm_start, fm_end, fm_length, fm_end_offset; u64 curr_loc; int current_extent = 0, rc = 0, i; + /* Whether have we collected enough extents */ + bool enough = false; int ost_eof = 0; /* EOF for object */ int ost_done = 0; /* done with required mapping for this OST? */ int last_stripe; @@ -1682,7 +1684,7 @@ static int lov_fiemap(struct lov_obd *lov, __u32 keylen, void *key, lun_start += len_mapped_single_call; fm_local->fm_length = req_fm_len - len_mapped_single_call; req_fm_len = fm_local->fm_length; - fm_local->fm_extent_count = count_local; + fm_local->fm_extent_count = enough ? 1 : count_local; fm_local->fm_mapped_extents = 0; fm_local->fm_flags = fiemap->fm_flags; @@ -1730,6 +1732,12 @@ inactive_tgt: goto finish; } break; + } else if (enough) { + /* + * We've collected enough extents and there are + * more extents after it. + */ + goto finish; } /* If we just need num of extents then go to next device */ @@ -1769,7 +1777,7 @@ inactive_tgt: /* Ran out of available extents? */ if (current_extent >= fiemap->fm_extent_count) - goto finish; + enough = true; } while (ost_done == 0 && ost_eof == 0); if (cur_stripe_wrap == last_stripe) -- cgit v0.10.2 From 0ae0d5eb33c04f9da9df520e53f4c7f1f56bdc80 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin <dmitry.eremin@intel.com> Date: Sun, 18 Sep 2016 16:38:24 -0400 Subject: staging: lustre: obdclass: change loop indexes to unsigned Cleanup warnings about comparison between signed and unsigned. Signed-off-by: Dmitry Eremin <dmitry.eremin@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5577 Reviewed-on: http://review.whamcloud.com/12387 Reviewed-by: Bob Glossman <bob.glossman@intel.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/obdclass/cl_io.c b/drivers/staging/lustre/lustre/obdclass/cl_io.c index 6643e78..7894cf9 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_io.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_io.c @@ -1211,7 +1211,7 @@ void cl_req_page_add(const struct lu_env *env, { struct cl_object *obj; struct cl_req_obj *rqo; - int i; + unsigned int i; LASSERT(list_empty(&page->cp_flight)); LASSERT(!page->cp_req); @@ -1258,7 +1258,7 @@ EXPORT_SYMBOL(cl_req_page_done); */ int cl_req_prep(const struct lu_env *env, struct cl_req *req) { - int i; + unsigned int i; int result; const struct cl_req_slice *slice; @@ -1291,7 +1291,7 @@ void cl_req_attr_set(const struct lu_env *env, struct cl_req *req, { const struct cl_req_slice *slice; struct cl_page *page; - int i; + unsigned int i; LASSERT(!list_empty(&req->crq_pages)); diff --git a/drivers/staging/lustre/lustre/obdclass/cl_object.c b/drivers/staging/lustre/lustre/obdclass/cl_object.c index 91a5806..bd85455 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_object.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_object.c @@ -377,7 +377,7 @@ static void cl_env_percpu_refill(void); */ int cl_site_init(struct cl_site *s, struct cl_device *d) { - int i; + size_t i; int result; result = lu_site_init(&s->cs_lu, &d->cd_lu_dev); @@ -411,7 +411,7 @@ static struct cache_stats cl_env_stats = { */ int cl_site_stats_print(const struct cl_site *site, struct seq_file *m) { - int i; + size_t i; static const char *pstate[] = { [CPS_CACHED] = "c", [CPS_OWNED] = "o", @@ -1126,7 +1126,7 @@ static void *cl_key_init(const struct lu_context *ctx, info = cl0_key_init(ctx, key); if (!IS_ERR(info)) { - int i; + size_t i; for (i = 0; i < ARRAY_SIZE(info->clt_counters); ++i) lu_ref_init(&info->clt_counters[i].ctc_locks_locked); @@ -1138,7 +1138,7 @@ static void cl_key_fini(const struct lu_context *ctx, struct lu_context_key *key, void *data) { struct cl_thread_info *info; - int i; + size_t i; info = data; for (i = 0; i < ARRAY_SIZE(info->clt_counters); ++i) @@ -1150,7 +1150,7 @@ static void cl_key_exit(const struct lu_context *ctx, struct lu_context_key *key, void *data) { struct cl_thread_info *info = data; - int i; + size_t i; for (i = 0; i < ARRAY_SIZE(info->clt_counters); ++i) { LASSERT(info->clt_counters[i].ctc_nr_held == 0); -- cgit v0.10.2 From a21e4b903d8ce19831dd504d8bfc4c99e85c2624 Mon Sep 17 00:00:00 2001 From: Bob Glossman <bob.glossman@intel.com> Date: Sun, 18 Sep 2016 16:38:25 -0400 Subject: staging: lustre: obdclass: eliminate NULL error return Always return an ERR_PTR() on errors, never return a NULL, in lu_object_find_slice(). Also clean up callers who no longer need special case handling of NULL returns. Signed-off-by: Bob Glossman <bob.glossman@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5858 Reviewed-on: http://review.whamcloud.com/12554 Reviewed-by: Dmitry Eremin <dmitry.eremin@intel.com> Reviewed-by: Fan Yong <fan.yong@intel.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c index 7339c8b..3f1fb28 100644 --- a/drivers/staging/lustre/lustre/obdclass/lu_object.c +++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c @@ -767,13 +767,15 @@ struct lu_object *lu_object_find_slice(const struct lu_env *env, struct lu_object *obj; top = lu_object_find(env, dev, f, conf); - if (!IS_ERR(top)) { - obj = lu_object_locate(top->lo_header, dev->ld_type); - if (!obj) - lu_object_put(env, top); - } else { - obj = top; + if (IS_ERR(top)) + return top; + + obj = lu_object_locate(top->lo_header, dev->ld_type); + if (unlikely(!obj)) { + lu_object_put(env, top); + obj = ERR_PTR(-ENOENT); } + return obj; } EXPORT_SYMBOL(lu_object_find_slice); -- cgit v0.10.2 From d333597a246b5d9fa8d1ff1dde45f74debc118d9 Mon Sep 17 00:00:00 2001 From: Amir Shehata <amir.shehata@intel.com> Date: Sun, 18 Sep 2016 16:38:26 -0400 Subject: staging: lustre: ptlrpc: Suppress error message when imp_sec is freed There is a race condition on client reconnect when the import is being destroyed. Some outstanding client bound requests are being processed when the imp_sec has alread been freed. Ensure to suppress the error message in import_sec_validate_get() in that case Signed-off-by: Amir Shehata <amir.shehata@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3353 Reviewed-on: http://review.whamcloud.com/10200 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec.c b/drivers/staging/lustre/lustre/ptlrpc/sec.c index 523579f..5d3995d 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec.c @@ -311,6 +311,19 @@ static int import_sec_check_expire(struct obd_import *imp) return sptlrpc_import_sec_adapt(imp, NULL, NULL); } +/** + * Get and validate the client side ptlrpc security facilities from + * \a imp. There is a race condition on client reconnect when the import is + * being destroyed while there are outstanding client bound requests. In + * this case do not output any error messages if import secuity is not + * found. + * + * \param[in] imp obd import associated with client + * \param[out] sec client side ptlrpc security + * + * \retval 0 if security retrieved successfully + * \retval -ve errno if there was a problem + */ static int import_sec_validate_get(struct obd_import *imp, struct ptlrpc_sec **sec) { @@ -323,9 +336,11 @@ static int import_sec_validate_get(struct obd_import *imp, } *sec = sptlrpc_import_sec_ref(imp); + /* Only output an error when the import is still active */ if (!*sec) { - CERROR("import %p (%s) with no sec\n", - imp, ptlrpc_import_state_name(imp->imp_state)); + if (list_empty(&imp->imp_zombie_chain)) + CERROR("import %p (%s) with no sec\n", + imp, ptlrpc_import_state_name(imp->imp_state)); return -EACCES; } -- cgit v0.10.2 From a5d604d76332dc020a1e010c8837f9bd349c177b Mon Sep 17 00:00:00 2001 From: Nathaniel Clark <nathaniel.l.clark@intel.com> Date: Sun, 18 Sep 2016 16:38:27 -0400 Subject: staging: lustre: ldlm: Recalculate interval in ldlm_pool_recalc() Instead of rechecking a static value, recalculate to see if pool stats need to be updated. Add newline so message will print instead of warning about missing newline. Signed-off-by: Nathaniel Clark <nathaniel.l.clark@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4536 Reviewed-on: http://review.whamcloud.com/12547 Reviewed-by: Lai Siyao <lai.siyao@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Jian Yu <jian.yu@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c index 44c3abf..9a1136e3 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c @@ -357,33 +357,39 @@ static int ldlm_pool_recalc(struct ldlm_pool *pl) int count; recalc_interval_sec = ktime_get_seconds() - pl->pl_recalc_time; - if (recalc_interval_sec <= 0) - goto recalc; - - spin_lock(&pl->pl_lock); if (recalc_interval_sec > 0) { - /* - * Update pool statistics every 1s. - */ - ldlm_pool_recalc_stats(pl); - - /* - * Zero out all rates and speed for the last period. - */ - atomic_set(&pl->pl_grant_rate, 0); - atomic_set(&pl->pl_cancel_rate, 0); + spin_lock(&pl->pl_lock); + recalc_interval_sec = ktime_get_seconds() - pl->pl_recalc_time; + + if (recalc_interval_sec > 0) { + /* + * Update pool statistics every 1s. + */ + ldlm_pool_recalc_stats(pl); + + /* + * Zero out all rates and speed for the last period. + */ + atomic_set(&pl->pl_grant_rate, 0); + atomic_set(&pl->pl_cancel_rate, 0); + } + spin_unlock(&pl->pl_lock); } - spin_unlock(&pl->pl_lock); - recalc: if (pl->pl_ops->po_recalc) { count = pl->pl_ops->po_recalc(pl); lprocfs_counter_add(pl->pl_stats, LDLM_POOL_RECALC_STAT, count); } + recalc_interval_sec = pl->pl_recalc_time - ktime_get_seconds() + pl->pl_recalc_period; if (recalc_interval_sec <= 0) { + /* DEBUG: should be re-removed after LU-4536 is fixed */ + CDEBUG(D_DLMTRACE, "%s: Negative interval(%ld), too short period(%ld)\n", + pl->pl_name, (long)recalc_interval_sec, + (long)pl->pl_recalc_period); + /* Prevent too frequent recalculation. */ recalc_interval_sec = 1; } -- cgit v0.10.2 From 855b5da50d2894fa2d8af5408203b307593b4dcd Mon Sep 17 00:00:00 2001 From: Dmitry Eremin <dmitry.eremin@intel.com> Date: Sun, 18 Sep 2016 16:38:28 -0400 Subject: staging: lustre: obd: change brw_page->count to unsigned Pages count is unsigned. So, change the type accordant usage. Signed-off-by: Dmitry Eremin <dmitry.eremin@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5577 Reviewed-on: http://review.whamcloud.com/12378 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index cd7f552..d1c4ccc 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -176,7 +176,7 @@ struct obd_type { struct brw_page { u64 off; struct page *pg; - int count; + unsigned int count; u32 flag; }; diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index 5a0c1b2..830a94b 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -1099,7 +1099,7 @@ static int osc_extent_make_ready(const struct lu_env *env, struct osc_async_page *oap; struct osc_async_page *last = NULL; struct osc_object *obj = ext->oe_obj; - int page_count = 0; + unsigned int page_count = 0; int rc; /* we're going to grab page lock, so object lock must not be taken. */ @@ -1140,9 +1140,11 @@ static int osc_extent_make_ready(const struct lu_env *env, * the size of file. */ if (!(last->oap_async_flags & ASYNC_COUNT_STABLE)) { - last->oap_count = osc_refresh_count(env, last, OBD_BRW_WRITE); - LASSERT(last->oap_count > 0); - LASSERT(last->oap_page_off + last->oap_count <= PAGE_SIZE); + int last_oap_count = osc_refresh_count(env, last, OBD_BRW_WRITE); + + LASSERT(last_oap_count > 0); + LASSERT(last->oap_page_off + last_oap_count <= PAGE_SIZE); + last->oap_count = last_oap_count; spin_lock(&last->oap_lock); last->oap_async_flags |= ASYNC_COUNT_STABLE; spin_unlock(&last->oap_lock); diff --git a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h index d41680b..3068113 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h @@ -64,7 +64,7 @@ struct osc_io { /** true if this io is lockless. */ unsigned int oi_lockless; /** how many LRU pages are reserved for this IO */ - int oi_lru_reserved; + unsigned long oi_lru_reserved; /** active extents, we know how many bytes is going to be written, * so having an active extent will prevent it from being fragmented -- cgit v0.10.2 From fdeb14fa6b4692abd093dd3365daf2ed7e7d5d06 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin <dmitry.eremin@intel.com> Date: Sun, 18 Sep 2016 16:38:29 -0400 Subject: staging: lustre: obdclass: change cl_fault_io->ft_nob to size_t Change the type accordant usage. Signed-off-by: Dmitry Eremin <dmitry.eremin@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5577 Reviewed-on: http://review.whamcloud.com/12380 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index 5af1153..f360ec9 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -1766,7 +1766,7 @@ struct cl_io { /** page index within file. */ pgoff_t ft_index; /** bytes valid byte on a faulted page. */ - int ft_nob; + size_t ft_nob; /** writable page? for nopage() only */ int ft_writable; /** page of an executable? */ @@ -2297,7 +2297,7 @@ int cl_page_is_under_lock(const struct lu_env *env, struct cl_io *io, struct cl_page *page, pgoff_t *max_index); loff_t cl_offset(const struct cl_object *obj, pgoff_t idx); pgoff_t cl_index(const struct cl_object *obj, loff_t offset); -int cl_page_size(const struct cl_object *obj); +size_t cl_page_size(const struct cl_object *obj); int cl_pages_prune(const struct lu_env *env, struct cl_object *obj); void cl_lock_print(const struct lu_env *env, void *cookie, diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c index f35eb2e..df0318e 100644 --- a/drivers/staging/lustre/lustre/llite/rw26.c +++ b/drivers/staging/lustre/lustre/llite/rw26.c @@ -213,10 +213,10 @@ ssize_t ll_direct_rw_pages(const struct lu_env *env, struct cl_io *io, int i; ssize_t rc = 0; loff_t file_offset = pv->ldp_start_offset; - long size = pv->ldp_size; + size_t size = pv->ldp_size; int page_count = pv->ldp_nr; struct page **pages = pv->ldp_pages; - long page_size = cl_page_size(obj); + size_t page_size = cl_page_size(obj); bool do_io; int io_pages = 0; diff --git a/drivers/staging/lustre/lustre/obdclass/cl_page.c b/drivers/staging/lustre/lustre/obdclass/cl_page.c index 5c89dbd..18784a8 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_page.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_page.c @@ -1032,9 +1032,9 @@ pgoff_t cl_index(const struct cl_object *obj, loff_t offset) } EXPORT_SYMBOL(cl_index); -int cl_page_size(const struct cl_object *obj) +size_t cl_page_size(const struct cl_object *obj) { - return 1 << PAGE_SHIFT; + return 1UL << PAGE_SHIFT; } EXPORT_SYMBOL(cl_page_size); diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index f3693d7..505582f 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -1010,7 +1010,7 @@ static int cl_echo_object_brw(struct echo_object *eco, int rw, u64 offset, struct cl_io *io; struct cl_page *clp; struct lustre_handle lh = { 0 }; - int page_size = cl_page_size(obj); + size_t page_size = cl_page_size(obj); int refcheck; int rc; int i; diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c index 7698054..96beba4 100644 --- a/drivers/staging/lustre/lustre/osc/osc_io.c +++ b/drivers/staging/lustre/lustre/osc/osc_io.c @@ -200,7 +200,7 @@ static int osc_io_submit(const struct lu_env *env, * Expand stripe KMS if necessary. */ static void osc_page_touch_at(const struct lu_env *env, - struct cl_object *obj, pgoff_t idx, unsigned to) + struct cl_object *obj, pgoff_t idx, size_t to) { struct lov_oinfo *loi = cl2osc(obj)->oo_oinfo; struct cl_attr *attr = &osc_env_info(env)->oti_attr; @@ -369,7 +369,7 @@ static int osc_io_fault_start(const struct lu_env *env, io = ios->cis_io; fio = &io->u.ci_fault; - CDEBUG(D_INFO, "%lu %d %d\n", + CDEBUG(D_INFO, "%lu %d %zu\n", fio->ft_index, fio->ft_writable, fio->ft_nob); /* * If mapping is writeable, adjust kms to cover this page, -- cgit v0.10.2 From a33fdc0d75dec2dfa454bcdd93d6d6cebfcb34f9 Mon Sep 17 00:00:00 2001 From: Bobi Jam <bobijam.xu@intel.com> Date: Sun, 18 Sep 2016 16:38:30 -0400 Subject: staging: lustre: clio: add coo_getstripe interface Use cl_object_operations::coo_getstripe() to handle LL_IOC_LOV_GETSTRIPE ops. Signed-off-by: Bobi Jam <bobijam.xu@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5823 Reviewed-on: http://review.whamcloud.com/12452 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index f360ec9..c1bcff8 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -395,6 +395,11 @@ struct cl_object_operations { * mainly pages and locks. */ int (*coo_prune)(const struct lu_env *env, struct cl_object *obj); + /** + * Object getstripe method. + */ + int (*coo_getstripe)(const struct lu_env *env, struct cl_object *obj, + struct lov_user_md __user *lum); }; /** @@ -2174,6 +2179,8 @@ int cl_conf_set(const struct lu_env *env, struct cl_object *obj, const struct cl_object_conf *conf); int cl_object_prune(const struct lu_env *env, struct cl_object *obj); void cl_object_kill(const struct lu_env *env, struct cl_object *obj); +int cl_object_getstripe(const struct lu_env *env, struct cl_object *obj, + struct lov_user_md __user *lum); /** * Returns true, iff \a o0 and \a o1 are slices of the same object. diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 0b3b387..2cb0b65 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -1449,6 +1449,22 @@ static int ll_lov_setea(struct inode *inode, struct file *file, return rc; } +static int ll_file_getstripe(struct inode *inode, + struct lov_user_md __user *lum) +{ + struct lu_env *env; + int refcheck; + int rc; + + env = cl_env_get(&refcheck); + if (IS_ERR(env)) + return PTR_ERR(env); + + rc = cl_object_getstripe(env, ll_i2info(inode)->lli_clob, lum); + cl_env_put(env, &refcheck); + return rc; +} + static int ll_lov_setstripe(struct inode *inode, struct file *file, unsigned long arg) { @@ -1466,35 +1482,18 @@ static int ll_lov_setstripe(struct inode *inode, struct file *file, lum_size); cl_lov_delay_create_clear(&file->f_flags); if (rc == 0) { - struct lov_stripe_md *lsm; __u32 gen; put_user(0, &lum->lmm_stripe_count); ll_layout_refresh(inode, &gen); - lsm = ccc_inode_lsm_get(inode); - rc = obd_iocontrol(LL_IOC_LOV_GETSTRIPE, ll_i2dtexp(inode), - 0, lsm, lum); - ccc_inode_lsm_put(inode, lsm); + rc = ll_file_getstripe(inode, (struct lov_user_md __user *)arg); } kfree(klum); return rc; } -static int ll_lov_getstripe(struct inode *inode, unsigned long arg) -{ - struct lov_stripe_md *lsm; - int rc = -ENODATA; - - lsm = ccc_inode_lsm_get(inode); - if (lsm) - rc = obd_iocontrol(LL_IOC_LOV_GETSTRIPE, ll_i2dtexp(inode), 0, - lsm, (void __user *)arg); - ccc_inode_lsm_put(inode, lsm); - return rc; -} - static int ll_get_grouplock(struct inode *inode, struct file *file, unsigned long arg) { @@ -2233,7 +2232,8 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return rc; } case LL_IOC_LOV_GETSTRIPE: - return ll_lov_getstripe(inode, arg); + return ll_file_getstripe(inode, + (struct lov_user_md __user *)arg); case FSFILT_IOC_FIEMAP: return ll_ioctl_fiemap(inode, arg); case FSFILT_IOC_GETFLAGS: diff --git a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h index 43d1a3f..ec40cf2 100644 --- a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h +++ b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h @@ -556,6 +556,8 @@ struct lov_lock_link *lov_lock_link_find(const struct lu_env *env, struct lovsub_lock *sub); struct lov_io_sub *lov_page_subio(const struct lu_env *env, struct lov_io *lio, const struct cl_page_slice *slice); + +struct lov_stripe_md *lov_lsm_addref(struct lov_object *lov); int lov_page_stripe(const struct cl_page *page); #define lov_foreach_target(lov, var) \ @@ -747,6 +749,10 @@ static inline struct lov_layout_raid0 *lov_r0(struct lov_object *lov) return &lov->u.raid0; } +/* lov_pack.c */ +int lov_getstripe(struct lov_object *obj, struct lov_stripe_md *lsm, + struct lov_user_md __user *lump); + /** @} lov */ #endif diff --git a/drivers/staging/lustre/lustre/lov/lov_internal.h b/drivers/staging/lustre/lustre/lov/lov_internal.h index 0e5fc2e..07e5ede 100644 --- a/drivers/staging/lustre/lustre/lov/lov_internal.h +++ b/drivers/staging/lustre/lustre/lov/lov_internal.h @@ -190,8 +190,6 @@ int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmm, struct lov_stripe_md *lsm); int lov_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, struct lov_mds_md *lmm, int lmm_bytes); -int lov_getstripe(struct obd_export *exp, - struct lov_stripe_md *lsm, struct lov_user_md __user *lump); int lov_alloc_memmd(struct lov_stripe_md **lsmp, __u16 stripe_count, int pattern, int magic); int lov_free_memmd(struct lov_stripe_md **lsmp); diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index 9ab3033..b23016f 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -1299,9 +1299,6 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len, obd_ioctl_freedata(buf, len); break; } - case LL_IOC_LOV_GETSTRIPE: - rc = lov_getstripe(exp, karg, uarg); - break; case OBD_IOC_QUOTACTL: { struct if_quotactl *qctl = karg; struct lov_tgt_desc *tgt = NULL; diff --git a/drivers/staging/lustre/lustre/lov/lov_object.c b/drivers/staging/lustre/lustre/lov/lov_object.c index 4f766e0..01f95a9 100644 --- a/drivers/staging/lustre/lustre/lov/lov_object.c +++ b/drivers/staging/lustre/lustre/lov/lov_object.c @@ -75,6 +75,13 @@ struct lov_layout_operations { static int lov_layout_wait(const struct lu_env *env, struct lov_object *lov); +void lov_lsm_put(struct cl_object *unused, struct lov_stripe_md *lsm) +{ + if (lsm) + lov_free_memmd(&lsm); +} +EXPORT_SYMBOL(lov_lsm_put); + /***************************************************************************** * * Lov object layout operations. @@ -904,13 +911,30 @@ int lov_lock_init(const struct lu_env *env, struct cl_object *obj, io); } +static int lov_object_getstripe(const struct lu_env *env, struct cl_object *obj, + struct lov_user_md __user *lum) +{ + struct lov_object *lov = cl2lov(obj); + struct lov_stripe_md *lsm; + int rc = 0; + + lsm = lov_lsm_addref(lov); + if (!lsm) + return -ENODATA; + + rc = lov_getstripe(cl2lov(obj), lsm, lum); + lov_lsm_put(obj, lsm); + return rc; +} + static const struct cl_object_operations lov_ops = { .coo_page_init = lov_page_init, .coo_lock_init = lov_lock_init, .coo_io_init = lov_io_init, .coo_attr_get = lov_attr_get, .coo_attr_set = lov_attr_set, - .coo_conf_set = lov_conf_set + .coo_conf_set = lov_conf_set, + .coo_getstripe = lov_object_getstripe }; static const struct lu_object_operations lov_lu_obj_ops = { @@ -947,7 +971,7 @@ struct lu_object *lov_object_alloc(const struct lu_env *env, return obj; } -static struct lov_stripe_md *lov_lsm_addref(struct lov_object *lov) +struct lov_stripe_md *lov_lsm_addref(struct lov_object *lov) { struct lov_stripe_md *lsm = NULL; @@ -978,13 +1002,6 @@ struct lov_stripe_md *lov_lsm_get(struct cl_object *clobj) } EXPORT_SYMBOL(lov_lsm_get); -void lov_lsm_put(struct cl_object *unused, struct lov_stripe_md *lsm) -{ - if (lsm) - lov_free_memmd(&lsm); -} -EXPORT_SYMBOL(lov_lsm_put); - int lov_read_and_clear_async_rc(struct cl_object *clob) { struct lu_object *luobj; diff --git a/drivers/staging/lustre/lustre/lov/lov_pack.c b/drivers/staging/lustre/lustre/lov/lov_pack.c index 595cf16..be6e985 100644 --- a/drivers/staging/lustre/lustre/lov/lov_pack.c +++ b/drivers/staging/lustre/lustre/lov/lov_pack.c @@ -45,6 +45,7 @@ #include "../include/lustre/lustre_user.h" #include "lov_internal.h" +#include "lov_cl_internal.h" void lov_dump_lmm_common(int level, void *lmmp) { @@ -104,11 +105,9 @@ void lov_dump_lmm_v3(int level, struct lov_mds_md_v3 *lmm) * LOVs properly. For now lov_mds_md_size() just assumes one u64 * per stripe. */ -int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, - struct lov_stripe_md *lsm) +int lov_obd_packmd(struct lov_obd *lov, struct lov_mds_md **lmmp, + struct lov_stripe_md *lsm) { - struct obd_device *obd = class_exp2obd(exp); - struct lov_obd *lov = &obd->u.lov; struct lov_mds_md_v1 *lmmv1; struct lov_mds_md_v3 *lmmv3; __u16 stripe_count; @@ -220,6 +219,15 @@ int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, return lmm_size; } +int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, + struct lov_stripe_md *lsm) +{ + struct obd_device *obd = class_exp2obd(exp); + struct lov_obd *lov = &obd->u.lov; + + return lov_obd_packmd(lov, lmmp, lsm); +} + /* Find the max stripecount we should use */ __u16 lov_get_stripecnt(struct lov_obd *lov, __u32 magic, __u16 stripe_count) { @@ -367,16 +375,17 @@ int lov_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, * the maximum number of OST indices which will fit in the user buffer. * lmm_magic must be LOV_USER_MAGIC. */ -int lov_getstripe(struct obd_export *exp, struct lov_stripe_md *lsm, +int lov_getstripe(struct lov_object *obj, struct lov_stripe_md *lsm, struct lov_user_md __user *lump) { /* * XXX huge struct allocated on stack. */ /* we use lov_user_md_v3 because it is larger than lov_user_md_v1 */ + struct lov_obd *lov; struct lov_user_md_v3 lum; struct lov_mds_md *lmmk = NULL; - int rc, lmm_size; + int rc, lmmk_size, lmm_size; int lum_size; mm_segment_t seg; @@ -396,13 +405,13 @@ int lov_getstripe(struct obd_export *exp, struct lov_stripe_md *lsm, lum_size = sizeof(struct lov_user_md_v1); if (copy_from_user(&lum, lump, lum_size)) { rc = -EFAULT; - goto out_set; + goto out; } if (lum.lmm_magic != LOV_USER_MAGIC_V1 && lum.lmm_magic != LOV_USER_MAGIC_V3 && lum.lmm_magic != LOV_USER_MAGIC_SPECIFIC) { rc = -EINVAL; - goto out_set; + goto out; } if (lum.lmm_stripe_count && @@ -411,11 +420,13 @@ int lov_getstripe(struct obd_export *exp, struct lov_stripe_md *lsm, lum.lmm_stripe_count = lsm->lsm_stripe_count; rc = copy_to_user(lump, &lum, lum_size); rc = -EOVERFLOW; - goto out_set; + goto out; } - rc = lov_packmd(exp, &lmmk, lsm); + lov = lu2lov_dev(obj->lo_cl.co_lu.lo_dev)->ld_lov; + rc = lov_obd_packmd(lov, &lmmk, lsm); if (rc < 0) - goto out_set; + goto out; + lmmk_size = rc; lmm_size = rc; rc = 0; @@ -451,7 +462,7 @@ int lov_getstripe(struct obd_export *exp, struct lov_stripe_md *lsm, lmm_size = lum_size; } else if (lum.lmm_stripe_count < lmmk->lmm_stripe_count) { rc = -EOVERFLOW; - goto out_set; + goto out_free; } /* * Have a difference between lov_mds_md & lov_user_md. @@ -464,8 +475,9 @@ int lov_getstripe(struct obd_export *exp, struct lov_stripe_md *lsm, if (copy_to_user(lump, lmmk, lmm_size)) rc = -EFAULT; - obd_free_diskmd(exp, &lmmk); -out_set: +out_free: + kfree(lmmk); +out: set_fs(seg); return rc; } diff --git a/drivers/staging/lustre/lustre/obdclass/cl_object.c b/drivers/staging/lustre/lustre/obdclass/cl_object.c index bd85455..ef5b1aa 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_object.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_object.c @@ -321,6 +321,27 @@ int cl_object_prune(const struct lu_env *env, struct cl_object *obj) EXPORT_SYMBOL(cl_object_prune); /** + * Get stripe information of this object. + */ +int cl_object_getstripe(const struct lu_env *env, struct cl_object *obj, + struct lov_user_md __user *uarg) +{ + struct lu_object_header *top; + int result = 0; + + top = obj->co_lu.lo_header; + list_for_each_entry(obj, &top->loh_layers, co_lu.lo_linkage) { + if (obj->co_ops->coo_getstripe) { + result = obj->co_ops->coo_getstripe(env, obj, uarg); + if (result) + break; + } + } + return result; +} +EXPORT_SYMBOL(cl_object_getstripe); + +/** * Helper function removing all object locks, and marking object for * deletion. All object pages must have been deleted at this point. * -- cgit v0.10.2 From 26ad0dc30eee1bd27c2f712f564bc2a217f9fff9 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin <dmitry.eremin@intel.com> Date: Sun, 18 Sep 2016 16:38:31 -0400 Subject: staging: lustre: ptlrpc: fix comparison between signed and unsigned Change return type and size argiments of lustre_msg_hdr_size(), lustre_msg_buf{len,count}() and req_capsule_*_size() to __u32. Change type of req_format->rf_idx and req_format->rf_fields.nr to size_t. Also return zero for incorrect message magic instead of -EINVAL. This will be more robust because of few of them after LASSERTF(0, "...") and will not be returned. In the rest places it return zero size instead of huge number after implicit unsigned conversion. Signed-off-by: Dmitry Eremin <dmitry.eremin@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5577 Reviewed-on: http://review.whamcloud.com/12475 Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: Fan Yong <fan.yong@intel.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre_net.h b/drivers/staging/lustre/lustre/include/lustre_net.h index 531c628..21e2267 100644 --- a/drivers/staging/lustre/lustre/include/lustre_net.h +++ b/drivers/staging/lustre/lustre/include/lustre_net.h @@ -2616,9 +2616,9 @@ int ptlrpc_reconnect_import(struct obd_import *imp); * @{ */ int ptlrpc_buf_need_swab(struct ptlrpc_request *req, const int inout, - int index); + u32 index); void ptlrpc_buf_set_swabbed(struct ptlrpc_request *req, const int inout, - int index); + u32 index); int ptlrpc_unpack_rep_msg(struct ptlrpc_request *req, int len); int ptlrpc_unpack_req_msg(struct ptlrpc_request *req, int len); @@ -2637,27 +2637,27 @@ int lustre_shrink_msg(struct lustre_msg *msg, int segment, unsigned int newlen, int move_data); void lustre_free_reply_state(struct ptlrpc_reply_state *rs); int __lustre_unpack_msg(struct lustre_msg *m, int len); -int lustre_msg_hdr_size(__u32 magic, int count); -int lustre_msg_size(__u32 magic, int count, __u32 *lengths); -int lustre_msg_size_v2(int count, __u32 *lengths); -int lustre_packed_msg_size(struct lustre_msg *msg); -int lustre_msg_early_size(void); -void *lustre_msg_buf_v2(struct lustre_msg_v2 *m, int n, int min_size); -void *lustre_msg_buf(struct lustre_msg *m, int n, int minlen); -int lustre_msg_buflen(struct lustre_msg *m, int n); -int lustre_msg_bufcount(struct lustre_msg *m); -char *lustre_msg_string(struct lustre_msg *m, int n, int max_len); +u32 lustre_msg_hdr_size(__u32 magic, u32 count); +u32 lustre_msg_size(__u32 magic, int count, __u32 *lengths); +u32 lustre_msg_size_v2(int count, __u32 *lengths); +u32 lustre_packed_msg_size(struct lustre_msg *msg); +u32 lustre_msg_early_size(void); +void *lustre_msg_buf_v2(struct lustre_msg_v2 *m, u32 n, u32 min_size); +void *lustre_msg_buf(struct lustre_msg *m, u32 n, u32 minlen); +u32 lustre_msg_buflen(struct lustre_msg *m, u32 n); +u32 lustre_msg_bufcount(struct lustre_msg *m); +char *lustre_msg_string(struct lustre_msg *m, u32 n, u32 max_len); __u32 lustre_msghdr_get_flags(struct lustre_msg *msg); void lustre_msghdr_set_flags(struct lustre_msg *msg, __u32 flags); __u32 lustre_msg_get_flags(struct lustre_msg *msg); -void lustre_msg_add_flags(struct lustre_msg *msg, int flags); -void lustre_msg_set_flags(struct lustre_msg *msg, int flags); -void lustre_msg_clear_flags(struct lustre_msg *msg, int flags); +void lustre_msg_add_flags(struct lustre_msg *msg, u32 flags); +void lustre_msg_set_flags(struct lustre_msg *msg, u32 flags); +void lustre_msg_clear_flags(struct lustre_msg *msg, u32 flags); __u32 lustre_msg_get_op_flags(struct lustre_msg *msg); -void lustre_msg_add_op_flags(struct lustre_msg *msg, int flags); +void lustre_msg_add_op_flags(struct lustre_msg *msg, u32 flags); struct lustre_handle *lustre_msg_get_handle(struct lustre_msg *msg); __u32 lustre_msg_get_type(struct lustre_msg *msg); -void lustre_msg_add_version(struct lustre_msg *msg, int version); +void lustre_msg_add_version(struct lustre_msg *msg, u32 version); __u32 lustre_msg_get_opc(struct lustre_msg *msg); __u64 lustre_msg_get_last_committed(struct lustre_msg *msg); __u64 *lustre_msg_get_versions(struct lustre_msg *msg); diff --git a/drivers/staging/lustre/lustre/include/lustre_req_layout.h b/drivers/staging/lustre/lustre/include/lustre_req_layout.h index ca0e683..a13558e 100644 --- a/drivers/staging/lustre/lustre/include/lustre_req_layout.h +++ b/drivers/staging/lustre/lustre/include/lustre_req_layout.h @@ -76,7 +76,8 @@ void req_capsule_init(struct req_capsule *pill, struct ptlrpc_request *req, void req_capsule_fini(struct req_capsule *pill); void req_capsule_set(struct req_capsule *pill, const struct req_format *fmt); -int req_capsule_filled_sizes(struct req_capsule *pill, enum req_location loc); +size_t req_capsule_filled_sizes(struct req_capsule *pill, + enum req_location loc); int req_capsule_server_pack(struct req_capsule *pill); void *req_capsule_client_get(struct req_capsule *pill, @@ -86,27 +87,27 @@ void *req_capsule_client_swab_get(struct req_capsule *pill, void *swabber); void *req_capsule_client_sized_get(struct req_capsule *pill, const struct req_msg_field *field, - int len); + u32 len); void *req_capsule_server_get(struct req_capsule *pill, const struct req_msg_field *field); void *req_capsule_server_sized_get(struct req_capsule *pill, const struct req_msg_field *field, - int len); + u32 len); void *req_capsule_server_swab_get(struct req_capsule *pill, const struct req_msg_field *field, void *swabber); void *req_capsule_server_sized_swab_get(struct req_capsule *pill, const struct req_msg_field *field, - int len, void *swabber); + u32 len, void *swabber); void req_capsule_set_size(struct req_capsule *pill, const struct req_msg_field *field, - enum req_location loc, int size); -int req_capsule_get_size(const struct req_capsule *pill, + enum req_location loc, u32 size); +u32 req_capsule_get_size(const struct req_capsule *pill, const struct req_msg_field *field, enum req_location loc); -int req_capsule_msg_size(struct req_capsule *pill, enum req_location loc); -int req_capsule_fmt_size(__u32 magic, const struct req_format *fmt, +u32 req_capsule_msg_size(struct req_capsule *pill, enum req_location loc); +u32 req_capsule_fmt_size(__u32 magic, const struct req_format *fmt, enum req_location loc); void req_capsule_extend(struct req_capsule *pill, const struct req_format *fmt); @@ -115,8 +116,7 @@ int req_capsule_has_field(const struct req_capsule *pill, enum req_location loc); void req_capsule_shrink(struct req_capsule *pill, const struct req_msg_field *field, - unsigned int newlen, - enum req_location loc); + u32 newlen, enum req_location loc); int req_layout_init(void); void req_layout_fini(void); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index 582de52..35ba6f1 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -561,7 +561,7 @@ static inline int ldlm_capsule_handles_avail(struct req_capsule *pill, enum req_location loc, int off) { - int size = req_capsule_msg_size(pill, loc); + u32 size = req_capsule_msg_size(pill, loc); return ldlm_req_handles_avail(size, off); } @@ -570,7 +570,7 @@ static inline int ldlm_format_handles_avail(struct obd_import *imp, const struct req_format *fmt, enum req_location loc, int off) { - int size = req_capsule_fmt_size(imp->imp_msg_magic, fmt, loc); + u32 size = req_capsule_fmt_size(imp->imp_msg_magic, fmt, loc); return ldlm_req_handles_avail(size, off); } diff --git a/drivers/staging/lustre/lustre/ptlrpc/layout.c b/drivers/staging/lustre/lustre/ptlrpc/layout.c index 101ac87..839ef3e 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/layout.c +++ b/drivers/staging/lustre/lustre/ptlrpc/layout.c @@ -1113,9 +1113,9 @@ EXPORT_SYMBOL(RMF_SWAP_LAYOUTS); struct req_format { const char *rf_name; - int rf_idx; + size_t rf_idx; struct { - int nr; + size_t nr; const struct req_msg_field **d; } rf_fields[RCL_NR]; }; @@ -1555,9 +1555,9 @@ EXPORT_SYMBOL(RQF_OST_GET_INFO_FIEMAP); */ int req_layout_init(void) { - int i; - int j; - int k; + size_t i; + size_t j; + size_t k; struct req_format *rf = NULL; for (i = 0; i < ARRAY_SIZE(req_formats); ++i) { @@ -1599,7 +1599,7 @@ EXPORT_SYMBOL(req_layout_fini); */ static void req_capsule_init_area(struct req_capsule *pill) { - int i; + size_t i; for (i = 0; i < ARRAY_SIZE(pill->rc_area[RCL_CLIENT]); i++) { pill->rc_area[RCL_CLIENT][i] = -1; @@ -1650,8 +1650,7 @@ EXPORT_SYMBOL(req_capsule_fini); static int __req_format_is_sane(const struct req_format *fmt) { - return - 0 <= fmt->rf_idx && fmt->rf_idx < ARRAY_SIZE(req_formats) && + return fmt->rf_idx < ARRAY_SIZE(req_formats) && req_formats[fmt->rf_idx] == fmt; } @@ -1685,11 +1684,11 @@ EXPORT_SYMBOL(req_capsule_set); * variable-sized fields. The field sizes come from the declared \a rmf_size * field of a \a pill's \a rc_fmt's RMF's. */ -int req_capsule_filled_sizes(struct req_capsule *pill, - enum req_location loc) +size_t req_capsule_filled_sizes(struct req_capsule *pill, + enum req_location loc) { const struct req_format *fmt = pill->rc_fmt; - int i; + size_t i; for (i = 0; i < fmt->rf_fields[loc].nr; ++i) { if (pill->rc_area[loc][i] == -1) { @@ -1744,11 +1743,11 @@ EXPORT_SYMBOL(req_capsule_server_pack); * Returns the PTLRPC request or reply (\a loc) buffer offset of a \a pill * corresponding to the given RMF (\a field). */ -static int __req_capsule_offset(const struct req_capsule *pill, +static u32 __req_capsule_offset(const struct req_capsule *pill, const struct req_msg_field *field, enum req_location loc) { - int offset; + u32 offset; offset = field->rmf_offset[pill->rc_fmt->rf_idx][loc]; LASSERTF(offset > 0, "%s:%s, off=%d, loc=%d\n", pill->rc_fmt->rf_name, @@ -1852,10 +1851,10 @@ static void *__req_capsule_get(struct req_capsule *pill, const struct req_format *fmt; struct lustre_msg *msg; void *value; - int len; - int offset; + u32 len; + u32 offset; - void *(*getter)(struct lustre_msg *m, int n, int minlen); + void *(*getter)(struct lustre_msg *m, u32 n, u32 minlen); static const char *rcl_names[RCL_NR] = { [RCL_CLIENT] = "client", @@ -1882,20 +1881,20 @@ static void *__req_capsule_get(struct req_capsule *pill, */ len = lustre_msg_buflen(msg, offset); if ((len % field->rmf_size) != 0) { - CERROR("%s: array field size mismatch %d modulo %d != 0 (%d)\n", + CERROR("%s: array field size mismatch %d modulo %u != 0 (%d)\n", field->rmf_name, len, field->rmf_size, loc); return NULL; } } else if (pill->rc_area[loc][offset] != -1) { len = pill->rc_area[loc][offset]; } else { - len = max(field->rmf_size, 0); + len = max_t(typeof(field->rmf_size), field->rmf_size, 0); } value = getter(msg, offset, len); if (!value) { DEBUG_REQ(D_ERROR, pill->rc_req, - "Wrong buffer for field `%s' (%d of %d) in format `%s': %d vs. %d (%s)\n", + "Wrong buffer for field `%s' (%u of %u) in format `%s': %u vs. %u (%s)\n", field->rmf_name, offset, lustre_msg_bufcount(msg), fmt->rf_name, lustre_msg_buflen(msg, offset), len, rcl_names[loc]); @@ -1941,7 +1940,7 @@ EXPORT_SYMBOL(req_capsule_client_swab_get); */ void *req_capsule_client_sized_get(struct req_capsule *pill, const struct req_msg_field *field, - int len) + u32 len) { req_capsule_set_size(pill, field, RCL_CLIENT, len); return __req_capsule_get(pill, field, RCL_CLIENT, NULL, 0); @@ -1982,7 +1981,7 @@ EXPORT_SYMBOL(req_capsule_server_swab_get); */ void *req_capsule_server_sized_get(struct req_capsule *pill, const struct req_msg_field *field, - int len) + u32 len) { req_capsule_set_size(pill, field, RCL_SERVER, len); return __req_capsule_get(pill, field, RCL_SERVER, NULL, 0); @@ -1991,7 +1990,7 @@ EXPORT_SYMBOL(req_capsule_server_sized_get); void *req_capsule_server_sized_swab_get(struct req_capsule *pill, const struct req_msg_field *field, - int len, void *swabber) + u32 len, void *swabber) { req_capsule_set_size(pill, field, RCL_SERVER, len); return __req_capsule_get(pill, field, RCL_SERVER, swabber, 0); @@ -2007,23 +2006,25 @@ EXPORT_SYMBOL(req_capsule_server_sized_swab_get); */ void req_capsule_set_size(struct req_capsule *pill, const struct req_msg_field *field, - enum req_location loc, int size) + enum req_location loc, u32 size) { LASSERT(loc == RCL_SERVER || loc == RCL_CLIENT); - if ((size != field->rmf_size) && + if ((size != (u32)field->rmf_size) && (field->rmf_size != -1) && !(field->rmf_flags & RMF_F_NO_SIZE_CHECK) && (size > 0)) { + u32 rmf_size = (u32)field->rmf_size; + if ((field->rmf_flags & RMF_F_STRUCT_ARRAY) && - (size % field->rmf_size != 0)) { - CERROR("%s: array field size mismatch %d %% %d != 0 (%d)\n", - field->rmf_name, size, field->rmf_size, loc); + (size % rmf_size != 0)) { + CERROR("%s: array field size mismatch %u %% %u != 0 (%d)\n", + field->rmf_name, size, rmf_size, loc); LBUG(); } else if (!(field->rmf_flags & RMF_F_STRUCT_ARRAY) && - size < field->rmf_size) { - CERROR("%s: field size mismatch %d != %d (%d)\n", - field->rmf_name, size, field->rmf_size, loc); + size < rmf_size) { + CERROR("%s: field size mismatch %u != %u (%d)\n", + field->rmf_name, size, rmf_size, loc); LBUG(); } } @@ -2040,7 +2041,7 @@ EXPORT_SYMBOL(req_capsule_set_size); * actually sets the size in pill.rc_area[loc][offset], but this function * returns the message buflen[offset], maybe we should use another name. */ -int req_capsule_get_size(const struct req_capsule *pill, +u32 req_capsule_get_size(const struct req_capsule *pill, const struct req_msg_field *field, enum req_location loc) { @@ -2058,7 +2059,7 @@ EXPORT_SYMBOL(req_capsule_get_size); * * See also req_capsule_set_size(). */ -int req_capsule_msg_size(struct req_capsule *pill, enum req_location loc) +u32 req_capsule_msg_size(struct req_capsule *pill, enum req_location loc) { return lustre_msg_size(pill->rc_req->rq_import->imp_msg_magic, pill->rc_fmt->rf_fields[loc].nr, @@ -2073,10 +2074,11 @@ int req_capsule_msg_size(struct req_capsule *pill, enum req_location loc) * This function should not be used for formats which contain variable size * fields. */ -int req_capsule_fmt_size(__u32 magic, const struct req_format *fmt, +u32 req_capsule_fmt_size(__u32 magic, const struct req_format *fmt, enum req_location loc) { - int size, i = 0; + size_t i = 0; + u32 size; /* * This function should probably LASSERT() that fmt has no fields with @@ -2086,7 +2088,7 @@ int req_capsule_fmt_size(__u32 magic, const struct req_format *fmt, * we do. */ size = lustre_msg_hdr_size(magic, fmt->rf_fields[loc].nr); - if (size < 0) + if (!size) return size; for (; i < fmt->rf_fields[loc].nr; ++i) @@ -2118,7 +2120,7 @@ int req_capsule_fmt_size(__u32 magic, const struct req_format *fmt, void req_capsule_extend(struct req_capsule *pill, const struct req_format *fmt) { int i; - int j; + size_t j; const struct req_format *old; @@ -2176,7 +2178,7 @@ static int req_capsule_field_present(const struct req_capsule *pill, const struct req_msg_field *field, enum req_location loc) { - int offset; + u32 offset; LASSERT(loc == RCL_SERVER || loc == RCL_CLIENT); LASSERT(req_capsule_has_field(pill, field, loc)); @@ -2193,12 +2195,11 @@ static int req_capsule_field_present(const struct req_capsule *pill, */ void req_capsule_shrink(struct req_capsule *pill, const struct req_msg_field *field, - unsigned int newlen, - enum req_location loc) + u32 newlen, enum req_location loc) { const struct req_format *fmt; struct lustre_msg *msg; - int len; + u32 len; int offset; fmt = pill->rc_fmt; @@ -2211,7 +2212,7 @@ void req_capsule_shrink(struct req_capsule *pill, msg = __req_msg(pill, loc); len = lustre_msg_buflen(msg, offset); - LASSERTF(newlen <= len, "%s:%s, oldlen=%d, newlen=%d\n", + LASSERTF(newlen <= len, "%s:%s, oldlen=%u, newlen=%u\n", fmt->rf_name, field->rmf_name, len, newlen); if (loc == RCL_CLIENT) diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index 87027c5..a1ea0c2 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -50,26 +50,26 @@ #include "ptlrpc_internal.h" -static inline int lustre_msg_hdr_size_v2(int count) +static inline u32 lustre_msg_hdr_size_v2(u32 count) { return cfs_size_round(offsetof(struct lustre_msg_v2, lm_buflens[count])); } -int lustre_msg_hdr_size(__u32 magic, int count) +u32 lustre_msg_hdr_size(__u32 magic, u32 count) { switch (magic) { case LUSTRE_MSG_MAGIC_V2: return lustre_msg_hdr_size_v2(count); default: LASSERTF(0, "incorrect message magic: %08x\n", magic); - return -EINVAL; + return 0; } } EXPORT_SYMBOL(lustre_msg_hdr_size); void ptlrpc_buf_set_swabbed(struct ptlrpc_request *req, const int inout, - int index) + u32 index) { if (inout) lustre_set_req_swabbed(req, index); @@ -79,7 +79,7 @@ void ptlrpc_buf_set_swabbed(struct ptlrpc_request *req, const int inout, EXPORT_SYMBOL(ptlrpc_buf_set_swabbed); int ptlrpc_buf_need_swab(struct ptlrpc_request *req, const int inout, - int index) + u32 index) { if (inout) return (ptlrpc_req_need_swab(req) && @@ -91,9 +91,9 @@ int ptlrpc_buf_need_swab(struct ptlrpc_request *req, const int inout, EXPORT_SYMBOL(ptlrpc_buf_need_swab); /* early reply size */ -int lustre_msg_early_size(void) +u32 lustre_msg_early_size(void) { - static int size; + static u32 size; if (!size) { /* Always reply old ptlrpc_body_v2 to keep interoperability @@ -111,9 +111,9 @@ int lustre_msg_early_size(void) } EXPORT_SYMBOL(lustre_msg_early_size); -int lustre_msg_size_v2(int count, __u32 *lengths) +u32 lustre_msg_size_v2(int count, __u32 *lengths) { - int size; + u32 size; int i; size = lustre_msg_hdr_size_v2(count); @@ -131,7 +131,7 @@ EXPORT_SYMBOL(lustre_msg_size_v2); * target then the first buffer will be stripped because the ptlrpc * data is part of the lustre_msg_v1 header. b=14043 */ -int lustre_msg_size(__u32 magic, int count, __u32 *lens) +u32 lustre_msg_size(__u32 magic, int count, __u32 *lens) { __u32 size[] = { sizeof(struct ptlrpc_body) }; @@ -148,7 +148,7 @@ int lustre_msg_size(__u32 magic, int count, __u32 *lens) return lustre_msg_size_v2(count, lens); default: LASSERTF(0, "incorrect message magic: %08x\n", magic); - return -EINVAL; + return 0; } } EXPORT_SYMBOL(lustre_msg_size); @@ -156,7 +156,7 @@ EXPORT_SYMBOL(lustre_msg_size); /* This is used to determine the size of a buffer that was already packed * and will correctly handle the different message formats. */ -int lustre_packed_msg_size(struct lustre_msg *msg) +u32 lustre_packed_msg_size(struct lustre_msg *msg) { switch (msg->lm_magic) { case LUSTRE_MSG_MAGIC_V2: @@ -378,11 +378,9 @@ int lustre_pack_reply(struct ptlrpc_request *req, int count, __u32 *lens, } EXPORT_SYMBOL(lustre_pack_reply); -void *lustre_msg_buf_v2(struct lustre_msg_v2 *m, int n, int min_size) +void *lustre_msg_buf_v2(struct lustre_msg_v2 *m, u32 n, u32 min_size) { - int i, offset, buflen, bufcount; - - LASSERT(n >= 0); + u32 i, offset, buflen, bufcount; bufcount = m->lm_bufcount; if (unlikely(n >= bufcount)) { @@ -406,7 +404,7 @@ void *lustre_msg_buf_v2(struct lustre_msg_v2 *m, int n, int min_size) return (char *)m + offset; } -void *lustre_msg_buf(struct lustre_msg *m, int n, int min_size) +void *lustre_msg_buf(struct lustre_msg *m, u32 n, u32 min_size) { switch (m->lm_magic) { case LUSTRE_MSG_MAGIC_V2: @@ -419,7 +417,7 @@ void *lustre_msg_buf(struct lustre_msg *m, int n, int min_size) } EXPORT_SYMBOL(lustre_msg_buf); -static int lustre_shrink_msg_v2(struct lustre_msg_v2 *msg, int segment, +static int lustre_shrink_msg_v2(struct lustre_msg_v2 *msg, u32 segment, unsigned int newlen, int move_data) { char *tail = NULL, *newpos; @@ -647,7 +645,7 @@ int lustre_unpack_rep_ptlrpc_body(struct ptlrpc_request *req, int offset) } } -static inline int lustre_msg_buflen_v2(struct lustre_msg_v2 *m, int n) +static inline u32 lustre_msg_buflen_v2(struct lustre_msg_v2 *m, u32 n) { if (n >= m->lm_bufcount) return 0; @@ -662,14 +660,14 @@ static inline int lustre_msg_buflen_v2(struct lustre_msg_v2 *m, int n) * * returns zero for non-existent message indices */ -int lustre_msg_buflen(struct lustre_msg *m, int n) +u32 lustre_msg_buflen(struct lustre_msg *m, u32 n) { switch (m->lm_magic) { case LUSTRE_MSG_MAGIC_V2: return lustre_msg_buflen_v2(m, n); default: CERROR("incorrect message magic: %08x\n", m->lm_magic); - return -EINVAL; + return 0; } } EXPORT_SYMBOL(lustre_msg_buflen); @@ -677,23 +675,23 @@ EXPORT_SYMBOL(lustre_msg_buflen); /* NB return the bufcount for lustre_msg_v2 format, so if message is packed * in V1 format, the result is one bigger. (add struct ptlrpc_body). */ -int lustre_msg_bufcount(struct lustre_msg *m) +u32 lustre_msg_bufcount(struct lustre_msg *m) { switch (m->lm_magic) { case LUSTRE_MSG_MAGIC_V2: return m->lm_bufcount; default: CERROR("incorrect message magic: %08x\n", m->lm_magic); - return -EINVAL; + return 0; } } EXPORT_SYMBOL(lustre_msg_bufcount); -char *lustre_msg_string(struct lustre_msg *m, int index, int max_len) +char *lustre_msg_string(struct lustre_msg *m, u32 index, u32 max_len) { /* max_len == 0 means the string should fill the buffer */ char *str; - int slen, blen; + u32 slen, blen; switch (m->lm_magic) { case LUSTRE_MSG_MAGIC_V2: @@ -734,8 +732,8 @@ char *lustre_msg_string(struct lustre_msg *m, int index, int max_len) EXPORT_SYMBOL(lustre_msg_string); /* Wrap up the normal fixed length cases */ -static inline void *__lustre_swab_buf(struct lustre_msg *msg, int index, - int min_size, void *swabber) +static inline void *__lustre_swab_buf(struct lustre_msg *msg, u32 index, + u32 min_size, void *swabber) { void *ptr = NULL; @@ -804,7 +802,7 @@ __u32 lustre_msg_get_flags(struct lustre_msg *msg) } EXPORT_SYMBOL(lustre_msg_get_flags); -void lustre_msg_add_flags(struct lustre_msg *msg, int flags) +void lustre_msg_add_flags(struct lustre_msg *msg, u32 flags) { switch (msg->lm_magic) { case LUSTRE_MSG_MAGIC_V2: { @@ -820,7 +818,7 @@ void lustre_msg_add_flags(struct lustre_msg *msg, int flags) } EXPORT_SYMBOL(lustre_msg_add_flags); -void lustre_msg_set_flags(struct lustre_msg *msg, int flags) +void lustre_msg_set_flags(struct lustre_msg *msg, u32 flags) { switch (msg->lm_magic) { case LUSTRE_MSG_MAGIC_V2: { @@ -836,7 +834,7 @@ void lustre_msg_set_flags(struct lustre_msg *msg, int flags) } EXPORT_SYMBOL(lustre_msg_set_flags); -void lustre_msg_clear_flags(struct lustre_msg *msg, int flags) +void lustre_msg_clear_flags(struct lustre_msg *msg, u32 flags) { switch (msg->lm_magic) { case LUSTRE_MSG_MAGIC_V2: { @@ -870,7 +868,7 @@ __u32 lustre_msg_get_op_flags(struct lustre_msg *msg) } EXPORT_SYMBOL(lustre_msg_get_op_flags); -void lustre_msg_add_op_flags(struct lustre_msg *msg, int flags) +void lustre_msg_add_op_flags(struct lustre_msg *msg, u32 flags) { switch (msg->lm_magic) { case LUSTRE_MSG_MAGIC_V2: { @@ -924,7 +922,7 @@ __u32 lustre_msg_get_type(struct lustre_msg *msg) } EXPORT_SYMBOL(lustre_msg_get_type); -void lustre_msg_add_version(struct lustre_msg *msg, int version) +void lustre_msg_add_version(struct lustre_msg *msg, u32 version) { switch (msg->lm_magic) { case LUSTRE_MSG_MAGIC_V2: { -- cgit v0.10.2 From 8b915c1ef5ba61127f364b5cff5f7315d9ded197 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong <jinshan.xiong@intel.com> Date: Sun, 18 Sep 2016 16:38:32 -0400 Subject: staging: lustre: ldlm: move LDLM_GID_ANY to lustre_dlm.h lustre_idl.h only includes wire data; lustre_dlm.h is the right place for LDLM_GID_ANY. Signed-off-by: Jinshan Xiong <jinshan.xiong@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6028 Reviewed-on: http://review.whamcloud.com/13074 Reviewed-by: Bobi Jam <bobijam@gmail.com> Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 445b813..acb2806 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -2716,8 +2716,6 @@ struct ldlm_extent { __u64 gid; }; -#define LDLM_GID_ANY ((__u64)-1) - static inline int ldlm_extent_overlap(const struct ldlm_extent *ex1, const struct ldlm_extent *ex2) { diff --git a/drivers/staging/lustre/lustre/include/lustre_dlm.h b/drivers/staging/lustre/lustre/include/lustre_dlm.h index 1ec4231..d035344 100644 --- a/drivers/staging/lustre/lustre/include/lustre_dlm.h +++ b/drivers/staging/lustre/lustre/include/lustre_dlm.h @@ -573,6 +573,11 @@ enum lvb_type { }; /** + * LDLM_GID_ANY is used to match any group id in ldlm_lock_match(). + */ +#define LDLM_GID_ANY ((__u64)-1) + +/** * LDLM lock structure * * Represents a single LDLM lock and its state in memory. Each lock is -- cgit v0.10.2 From 01cd98ffcf2ff56fc54781cc608f4043b813f54a Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Sun, 18 Sep 2016 16:38:33 -0400 Subject: staging: lustre: lov: flatten struct lov_stripe_md Flatten out the lsm_wire struct from the middle of struct lov_stripe_md and remove the member name macros. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5814 Reviewed-on: http://review.whamcloud.com/12581 Reviewed-by: Bobi Jam <bobijam@gmail.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index d1c4ccc..8e426b8 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -88,31 +88,17 @@ struct lov_stripe_md { /* maximum possible file size, might change as OSTs status changes, * e.g. disconnected, deactivated */ - __u64 lsm_maxbytes; - struct { - /* Public members. */ - struct ost_id lw_object_oi; /* lov object id/seq */ - - /* LOV-private members start here -- only for use in lov/. */ - __u32 lw_magic; - __u32 lw_stripe_size; /* size of the stripe */ - __u32 lw_pattern; /* striping pattern (RAID0, RAID1) */ - __u16 lw_stripe_count; /* number of objects being striped over */ - __u16 lw_layout_gen; /* generation of the layout */ - char lw_pool_name[LOV_MAXPOOLNAME + 1]; /* pool name */ - } lsm_wire; - + __u64 lsm_maxbytes; + struct ost_id lsm_oi; + __u32 lsm_magic; + __u32 lsm_stripe_size; + __u32 lsm_pattern; /* striping pattern (RAID0, RAID1) */ + __u16 lsm_stripe_count; + __u16 lsm_layout_gen; + char lsm_pool_name[LOV_MAXPOOLNAME + 1]; struct lov_oinfo *lsm_oinfo[0]; }; -#define lsm_oi lsm_wire.lw_object_oi -#define lsm_magic lsm_wire.lw_magic -#define lsm_layout_gen lsm_wire.lw_layout_gen -#define lsm_stripe_size lsm_wire.lw_stripe_size -#define lsm_pattern lsm_wire.lw_pattern -#define lsm_stripe_count lsm_wire.lw_stripe_count -#define lsm_pool_name lsm_wire.lw_pool_name - static inline bool lsm_is_released(struct lov_stripe_md *lsm) { return !!(lsm->lsm_pattern & LOV_PATTERN_F_RELEASED); diff --git a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h index ec40cf2..4d2b7d3 100644 --- a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h +++ b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h @@ -744,8 +744,8 @@ static inline struct lov_thread_info *lov_env_info(const struct lu_env *env) static inline struct lov_layout_raid0 *lov_r0(struct lov_object *lov) { LASSERT(lov->lo_type == LLT_RAID0); - LASSERT(lov->lo_lsm->lsm_wire.lw_magic == LOV_MAGIC || - lov->lo_lsm->lsm_wire.lw_magic == LOV_MAGIC_V3); + LASSERT(lov->lo_lsm->lsm_magic == LOV_MAGIC || + lov->lo_lsm->lsm_magic == LOV_MAGIC_V3); return &lov->u.raid0; } -- cgit v0.10.2 From d09cfb00612f2add6eb05ae7a17d2bf2a4d317ff Mon Sep 17 00:00:00 2001 From: Alexander Boyko <alexander_boyko@xyratex.com> Date: Sun, 18 Sep 2016 16:38:34 -0400 Subject: staging: lustre: ptlrpc: fix race between connect vs resend Buggy code at ptlrpc_connect_interpret() finish: rc = ptlrpc_import_recovery_state_machine(imp); ... Set import connection flags When import has FULL state ptlrpc_import_recovery_state_machine() wakeup all waiters on import and all delayed request, which was resented. And it could happened that request was send without updated flags and AT is disabled. If such request is in progress on the server, server drop the new instance, and could do early reply for it. But this early reply confuse client, cause it wait real reply(no AT for this request). Client try to touch buffer outside reply and got EPROTO error. The same bug existed for initital connect too. Import became FULL before import connection flags was set. Signed-off-by: Alexander Boyko <alexander_boyko@xyratex.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5528 Xyratex-bug-id: MRP-2034 Reviewed-on: http://review.whamcloud.com/11723 Reviewed-by: Li Wei <wei.g.li@intel.com> Reviewed-by: Alexander Boyko <alexander.boyko@seagate.com> Reviewed-by: Liang Zhen <liang.zhen@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c index 17f3fec..2e107e8 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/import.c +++ b/drivers/staging/lustre/lustre/ptlrpc/import.c @@ -752,6 +752,153 @@ static int ptlrpc_busy_reconnect(int rc) return (rc == -EBUSY) || (rc == -EAGAIN); } +static int ptlrpc_connect_set_flags(struct obd_import *imp, + struct obd_connect_data *ocd, + u64 old_connect_flags, + struct obd_export *exp, int init_connect) +{ + struct client_obd *cli = &imp->imp_obd->u.cli; + static bool warned; + + if ((imp->imp_connect_flags_orig & OBD_CONNECT_IBITS) && + !(ocd->ocd_connect_flags & OBD_CONNECT_IBITS)) { + LCONSOLE_WARN("%s: MDS %s does not support ibits lock, either very old or invalid: requested %#llx, replied %#llx\n", + imp->imp_obd->obd_name, + imp->imp_connection->c_remote_uuid.uuid, + imp->imp_connect_flags_orig, + ocd->ocd_connect_flags); + return -EPROTO; + } + + spin_lock(&imp->imp_lock); + list_del(&imp->imp_conn_current->oic_item); + list_add(&imp->imp_conn_current->oic_item, &imp->imp_conn_list); + imp->imp_last_success_conn = imp->imp_conn_current->oic_last_attempt; + + spin_unlock(&imp->imp_lock); + + if (!warned && (ocd->ocd_connect_flags & OBD_CONNECT_VERSION) && + (ocd->ocd_version > LUSTRE_VERSION_CODE + + LUSTRE_VERSION_OFFSET_WARN || + ocd->ocd_version < LUSTRE_VERSION_CODE - + LUSTRE_VERSION_OFFSET_WARN)) { + /* + * Sigh, some compilers do not like #ifdef in the middle + * of macro arguments + */ + const char *older = "older than client. Consider upgrading server"; + const char *newer = "newer than client. Consider recompiling application"; + + LCONSOLE_WARN("Server %s version (%d.%d.%d.%d) is much %s (%s)\n", + obd2cli_tgt(imp->imp_obd), + OBD_OCD_VERSION_MAJOR(ocd->ocd_version), + OBD_OCD_VERSION_MINOR(ocd->ocd_version), + OBD_OCD_VERSION_PATCH(ocd->ocd_version), + OBD_OCD_VERSION_FIX(ocd->ocd_version), + ocd->ocd_version > LUSTRE_VERSION_CODE ? + newer : older, LUSTRE_VERSION_STRING); + warned = true; + } + +#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 0, 53, 0) + /* + * Check if server has LU-1252 fix applied to not always swab + * the IR MNE entries. Do this only once per connection. This + * fixup is version-limited, because we don't want to carry the + * OBD_CONNECT_MNE_SWAB flag around forever, just so long as we + * need interop with unpatched 2.2 servers. For newer servers, + * the client will do MNE swabbing only as needed. LU-1644 + */ + if (unlikely((ocd->ocd_connect_flags & OBD_CONNECT_VERSION) && + !(ocd->ocd_connect_flags & OBD_CONNECT_MNE_SWAB) && + OBD_OCD_VERSION_MAJOR(ocd->ocd_version) == 2 && + OBD_OCD_VERSION_MINOR(ocd->ocd_version) == 2 && + OBD_OCD_VERSION_PATCH(ocd->ocd_version) < 55 && + !strcmp(imp->imp_obd->obd_type->typ_name, + LUSTRE_MGC_NAME))) + imp->imp_need_mne_swab = 1; + else /* clear if server was upgraded since last connect */ + imp->imp_need_mne_swab = 0; +#endif + + if (ocd->ocd_connect_flags & OBD_CONNECT_CKSUM) { + /* + * We sent to the server ocd_cksum_types with bits set + * for algorithms we understand. The server masked off + * the checksum types it doesn't support + */ + if (!(ocd->ocd_cksum_types & cksum_types_supported_client())) { + LCONSOLE_WARN("The negotiation of the checksum algorithm to use with server %s failed (%x/%x), disabling checksums\n", + obd2cli_tgt(imp->imp_obd), + ocd->ocd_cksum_types, + cksum_types_supported_client()); + cli->cl_checksum = 0; + cli->cl_supp_cksum_types = OBD_CKSUM_ADLER; + } else { + cli->cl_supp_cksum_types = ocd->ocd_cksum_types; + } + } else { + /* + * The server does not support OBD_CONNECT_CKSUM. + * Enforce ADLER for backward compatibility + */ + cli->cl_supp_cksum_types = OBD_CKSUM_ADLER; + } + cli->cl_cksum_type = cksum_type_select(cli->cl_supp_cksum_types); + + if (ocd->ocd_connect_flags & OBD_CONNECT_BRW_SIZE) + cli->cl_max_pages_per_rpc = + min(ocd->ocd_brw_size >> PAGE_SHIFT, + cli->cl_max_pages_per_rpc); + else if (imp->imp_connect_op == MDS_CONNECT || + imp->imp_connect_op == MGS_CONNECT) + cli->cl_max_pages_per_rpc = 1; + + LASSERT((cli->cl_max_pages_per_rpc <= PTLRPC_MAX_BRW_PAGES) && + (cli->cl_max_pages_per_rpc > 0)); + + client_adjust_max_dirty(cli); + + /* + * Reset ns_connect_flags only for initial connect. It might be + * changed in while using FS and if we reset it in reconnect + * this leads to losing user settings done before such as + * disable lru_resize, etc. + */ + if (old_connect_flags != exp_connect_flags(exp) || init_connect) { + CDEBUG(D_HA, "%s: Resetting ns_connect_flags to server flags: %#llx\n", + imp->imp_obd->obd_name, ocd->ocd_connect_flags); + imp->imp_obd->obd_namespace->ns_connect_flags = + ocd->ocd_connect_flags; + imp->imp_obd->obd_namespace->ns_orig_connect_flags = + ocd->ocd_connect_flags; + } + + if ((ocd->ocd_connect_flags & OBD_CONNECT_AT) && + (imp->imp_msg_magic == LUSTRE_MSG_MAGIC_V2)) + /* + * We need a per-message support flag, because + * a. we don't know if the incoming connect reply + * supports AT or not (in reply_in_callback) + * until we unpack it. + * b. failovered server means export and flags are gone + * (in ptlrpc_send_reply). + * Can only be set when we know AT is supported at + * both ends + */ + imp->imp_msghdr_flags |= MSGHDR_AT_SUPPORT; + else + imp->imp_msghdr_flags &= ~MSGHDR_AT_SUPPORT; + + if ((ocd->ocd_connect_flags & OBD_CONNECT_FULL20) && + (imp->imp_msg_magic == LUSTRE_MSG_MAGIC_V2)) + imp->imp_msghdr_flags |= MSGHDR_CKSUM_INCOMPAT18; + else + imp->imp_msghdr_flags &= ~MSGHDR_CKSUM_INCOMPAT18; + + return 0; +} + /** * interpret_reply callback for connect RPCs. * Looks into returned status of connect operation and decides @@ -764,7 +911,6 @@ static int ptlrpc_connect_interpret(const struct lu_env *env, { struct ptlrpc_connect_async_args *aa = data; struct obd_import *imp = request->rq_import; - struct client_obd *cli = &imp->imp_obd->u.cli; struct lustre_handle old_hdl; __u64 old_connect_flags; int msg_flags; @@ -844,7 +990,6 @@ static int ptlrpc_connect_interpret(const struct lu_env *env, old_connect_flags = exp_connect_flags(exp); exp->exp_connect_data = *ocd; imp->imp_obd->obd_self_export->exp_connect_data = *ocd; - class_export_put(exp); /* * The net statistics after (re-)connect is not valid anymore, @@ -854,6 +999,13 @@ static int ptlrpc_connect_interpret(const struct lu_env *env, ptlrpc_at_adj_net_latency(request, lustre_msg_get_service_time(request->rq_repmsg)); + /* Import flags should be updated before waking import at FULL state */ + rc = ptlrpc_connect_set_flags(imp, ocd, old_connect_flags, exp, + aa->pcaa_initial_connect); + class_export_put(exp); + if (rc) + goto out; + obd_import_event(imp->imp_obd, imp, IMP_EVENT_OCD); if (aa->pcaa_initial_connect) { @@ -997,150 +1149,13 @@ static int ptlrpc_connect_interpret(const struct lu_env *env, finish: rc = ptlrpc_import_recovery_state_machine(imp); - if (rc != 0) { - if (rc == -ENOTCONN) { - CDEBUG(D_HA, "evicted/aborted by %s@%s during recovery; invalidating and reconnecting\n", - obd2cli_tgt(imp->imp_obd), - imp->imp_connection->c_remote_uuid.uuid); - ptlrpc_connect_import(imp); - imp->imp_connect_tried = 1; - return 0; - } - } else { - static bool warned; - - spin_lock(&imp->imp_lock); - list_del(&imp->imp_conn_current->oic_item); - list_add(&imp->imp_conn_current->oic_item, &imp->imp_conn_list); - imp->imp_last_success_conn = - imp->imp_conn_current->oic_last_attempt; - - spin_unlock(&imp->imp_lock); - - if ((imp->imp_connect_flags_orig & OBD_CONNECT_IBITS) && - !(ocd->ocd_connect_flags & OBD_CONNECT_IBITS)) { - LCONSOLE_WARN("%s: MDS %s does not support ibits lock, either very old or invalid: requested %llx, replied %llx\n", - imp->imp_obd->obd_name, - imp->imp_connection->c_remote_uuid.uuid, - imp->imp_connect_flags_orig, - ocd->ocd_connect_flags); - rc = -EPROTO; - goto out; - } - - if (!warned && (ocd->ocd_connect_flags & OBD_CONNECT_VERSION) && - (ocd->ocd_version > LUSTRE_VERSION_CODE + - LUSTRE_VERSION_OFFSET_WARN || - ocd->ocd_version < LUSTRE_VERSION_CODE - - LUSTRE_VERSION_OFFSET_WARN)) { - /* Sigh, some compilers do not like #ifdef in the middle - * of macro arguments - */ - const char *older = "older than client. Consider upgrading server"; - const char *newer = "newer than client. Consider recompiling application"; - - LCONSOLE_WARN("Server %s version (%d.%d.%d.%d) is much %s (%s)\n", - obd2cli_tgt(imp->imp_obd), - OBD_OCD_VERSION_MAJOR(ocd->ocd_version), - OBD_OCD_VERSION_MINOR(ocd->ocd_version), - OBD_OCD_VERSION_PATCH(ocd->ocd_version), - OBD_OCD_VERSION_FIX(ocd->ocd_version), - ocd->ocd_version > LUSTRE_VERSION_CODE ? - newer : older, LUSTRE_VERSION_STRING); - warned = true; - } - -#if OBD_OCD_VERSION(3, 0, 53, 0) > LUSTRE_VERSION_CODE - /* Check if server has LU-1252 fix applied to not always swab - * the IR MNE entries. Do this only once per connection. This - * fixup is version-limited, because we don't want to carry the - * OBD_CONNECT_MNE_SWAB flag around forever, just so long as we - * need interop with unpatched 2.2 servers. For newer servers, - * the client will do MNE swabbing only as needed. LU-1644 - */ - if (unlikely((ocd->ocd_connect_flags & OBD_CONNECT_VERSION) && - !(ocd->ocd_connect_flags & OBD_CONNECT_MNE_SWAB) && - OBD_OCD_VERSION_MAJOR(ocd->ocd_version) == 2 && - OBD_OCD_VERSION_MINOR(ocd->ocd_version) == 2 && - OBD_OCD_VERSION_PATCH(ocd->ocd_version) < 55 && - strcmp(imp->imp_obd->obd_type->typ_name, - LUSTRE_MGC_NAME) == 0)) - imp->imp_need_mne_swab = 1; - else /* clear if server was upgraded since last connect */ - imp->imp_need_mne_swab = 0; -#endif - - if (ocd->ocd_connect_flags & OBD_CONNECT_CKSUM) { - /* We sent to the server ocd_cksum_types with bits set - * for algorithms we understand. The server masked off - * the checksum types it doesn't support - */ - if ((ocd->ocd_cksum_types & - cksum_types_supported_client()) == 0) { - LCONSOLE_WARN("The negotiation of the checksum algorithm to use with server %s failed (%x/%x), disabling checksums\n", - obd2cli_tgt(imp->imp_obd), - ocd->ocd_cksum_types, - cksum_types_supported_client()); - cli->cl_checksum = 0; - cli->cl_supp_cksum_types = OBD_CKSUM_ADLER; - } else { - cli->cl_supp_cksum_types = ocd->ocd_cksum_types; - } - } else { - /* The server does not support OBD_CONNECT_CKSUM. - * Enforce ADLER for backward compatibility - */ - cli->cl_supp_cksum_types = OBD_CKSUM_ADLER; - } - cli->cl_cksum_type = cksum_type_select(cli->cl_supp_cksum_types); - - if (ocd->ocd_connect_flags & OBD_CONNECT_BRW_SIZE) - cli->cl_max_pages_per_rpc = - min(ocd->ocd_brw_size >> PAGE_SHIFT, - cli->cl_max_pages_per_rpc); - else if (imp->imp_connect_op == MDS_CONNECT || - imp->imp_connect_op == MGS_CONNECT) - cli->cl_max_pages_per_rpc = 1; - - /* Reset ns_connect_flags only for initial connect. It might be - * changed in while using FS and if we reset it in reconnect - * this leads to losing user settings done before such as - * disable lru_resize, etc. - */ - if (old_connect_flags != exp_connect_flags(exp) || - aa->pcaa_initial_connect) { - CDEBUG(D_HA, "%s: Resetting ns_connect_flags to server flags: %#llx\n", - imp->imp_obd->obd_name, ocd->ocd_connect_flags); - imp->imp_obd->obd_namespace->ns_connect_flags = - ocd->ocd_connect_flags; - imp->imp_obd->obd_namespace->ns_orig_connect_flags = - ocd->ocd_connect_flags; - } - - if ((ocd->ocd_connect_flags & OBD_CONNECT_AT) && - (imp->imp_msg_magic == LUSTRE_MSG_MAGIC_V2)) - /* We need a per-message support flag, because - * a. we don't know if the incoming connect reply - * supports AT or not (in reply_in_callback) - * until we unpack it. - * b. failovered server means export and flags are gone - * (in ptlrpc_send_reply). - * Can only be set when we know AT is supported at - * both ends - */ - imp->imp_msghdr_flags |= MSGHDR_AT_SUPPORT; - else - imp->imp_msghdr_flags &= ~MSGHDR_AT_SUPPORT; - - if ((ocd->ocd_connect_flags & OBD_CONNECT_FULL20) && - (imp->imp_msg_magic == LUSTRE_MSG_MAGIC_V2)) - imp->imp_msghdr_flags |= MSGHDR_CKSUM_INCOMPAT18; - else - imp->imp_msghdr_flags &= ~MSGHDR_CKSUM_INCOMPAT18; - - LASSERT((cli->cl_max_pages_per_rpc <= PTLRPC_MAX_BRW_PAGES) && - (cli->cl_max_pages_per_rpc > 0)); - client_adjust_max_dirty(cli); + if (rc == -ENOTCONN) { + CDEBUG(D_HA, "evicted/aborted by %s@%s during recovery; invalidating and reconnecting\n", + obd2cli_tgt(imp->imp_obd), + imp->imp_connection->c_remote_uuid.uuid); + ptlrpc_connect_import(imp); + imp->imp_connect_tried = 1; + return 0; } out: diff --git a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c index 44f4eae..5bab2487 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c +++ b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c @@ -491,7 +491,8 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply) struct ptlrpc_connection *connection; lnet_handle_me_t reply_me_h; lnet_md_t reply_md; - struct obd_device *obd = request->rq_import->imp_obd; + struct obd_import *imp = request->rq_import; + struct obd_device *obd = imp->imp_obd; if (OBD_FAIL_CHECK(OBD_FAIL_PTLRPC_DROP_RPC)) return 0; @@ -504,7 +505,7 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply) */ LASSERT(!request->rq_receiving_reply); LASSERT(!((lustre_msg_get_flags(request->rq_reqmsg) & MSG_REPLAY) && - (request->rq_import->imp_state == LUSTRE_IMP_FULL))); + (imp->imp_state == LUSTRE_IMP_FULL))); if (unlikely(obd && obd->obd_fail)) { CDEBUG(D_HA, "muting rpc for failed imp obd %s\n", @@ -517,15 +518,22 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply) return -ENODEV; } - connection = request->rq_import->imp_connection; + connection = imp->imp_connection; lustre_msg_set_handle(request->rq_reqmsg, - &request->rq_import->imp_remote_handle); + &imp->imp_remote_handle); lustre_msg_set_type(request->rq_reqmsg, PTL_RPC_MSG_REQUEST); - lustre_msg_set_conn_cnt(request->rq_reqmsg, - request->rq_import->imp_conn_cnt); - lustre_msghdr_set_flags(request->rq_reqmsg, - request->rq_import->imp_msghdr_flags); + lustre_msg_set_conn_cnt(request->rq_reqmsg, imp->imp_conn_cnt); + lustre_msghdr_set_flags(request->rq_reqmsg, imp->imp_msghdr_flags); + + /** + * For enabled AT all request should have AT_SUPPORT in the + * FULL import state when OBD_CONNECT_AT is set + */ + LASSERT(AT_OFF || imp->imp_state != LUSTRE_IMP_FULL || + (imp->imp_msghdr_flags & MSGHDR_AT_SUPPORT) || + !(imp->imp_connect_data.ocd_connect_flags & + OBD_CONNECT_AT)); if (request->rq_resend) lustre_msg_add_flags(request->rq_reqmsg, MSG_RESENT); @@ -629,7 +637,7 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply) ptlrpc_request_addref(request); if (obd && obd->obd_svc_stats) lprocfs_counter_add(obd->obd_svc_stats, PTLRPC_REQACTIVE_CNTR, - atomic_read(&request->rq_import->imp_inflight)); + atomic_read(&imp->imp_inflight)); OBD_FAIL_TIMEOUT(OBD_FAIL_PTLRPC_DELAY_SEND, request->rq_timeout + 5); @@ -641,7 +649,7 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply) request->rq_deadline = request->rq_sent + request->rq_timeout + ptlrpc_at_get_net_latency(request); - ptlrpc_pinger_sending_on_import(request->rq_import); + ptlrpc_pinger_sending_on_import(imp); DEBUG_REQ(D_INFO, request, "send flg=%x", lustre_msg_get_flags(request->rq_reqmsg)); -- cgit v0.10.2 From bc875120b983bf7b297720ce384d6e20f0068ba8 Mon Sep 17 00:00:00 2001 From: Alexander Boyko <alexander.boyko@seagate.com> Date: Sun, 18 Sep 2016 16:38:18 -0400 Subject: staging: lustre: mgc: add nid iteration mgc_apply_recover_logs use only first nid from entry, this could be the problem for a cluster with several network address for a one node. Signed-off-by: Alexander Boyko <alexander.boyko@seagate.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5950 Xyratex-bug-id: MRP-2255 Reviewed-on: http://review.whamcloud.com/12829 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Mike Pershin <mike.pershin@intel.com> Reviewed-by: Ann Koehler <amk@cray.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/mgc/mgc_request.c b/drivers/staging/lustre/lustre/mgc/mgc_request.c index 2191ca1..23374ca 100644 --- a/drivers/staging/lustre/lustre/mgc/mgc_request.c +++ b/drivers/staging/lustre/lustre/mgc/mgc_request.c @@ -1159,7 +1159,7 @@ static int mgc_apply_recover_logs(struct obd_device *mgc, while (datalen > 0) { int entry_len = sizeof(*entry); - int is_ost; + int is_ost, i; struct obd_device *obd; char *obdname; char *cname; @@ -1265,11 +1265,17 @@ static int mgc_apply_recover_logs(struct obd_device *mgc, continue; } - /* TODO: iterate all nids to find one */ + /* iterate all nids to find one */ /* find uuid by nid */ - rc = client_import_find_conn(obd->u.cli.cl_import, - entry->u.nids[0], - (struct obd_uuid *)uuid); + rc = -ENOENT; + for (i = 0; i < entry->mne_nid_count; i++) { + rc = client_import_find_conn(obd->u.cli.cl_import, + entry->u.nids[0], + (struct obd_uuid *)uuid); + if (!rc) + break; + } + up_read(&obd->u.cli.cl_sem); if (rc < 0) { CERROR("mgc: cannot find uuid by nid %s\n", -- cgit v0.10.2 From 7715c63692efd92db4dd3bd7748a92edca902276 Mon Sep 17 00:00:00 2001 From: Bobi Jam <bobijam.xu@intel.com> Date: Sun, 18 Sep 2016 16:38:35 -0400 Subject: staging: lustre: osc: osc_object_ast_clear() LBUG An OSC object could be destroyed with AGL locks waiting for granted, so we'd get rid of the osc_object_ast_clear() assertion that its dlm locks all getting granted. Signed-off-by: Bobi Jam <bobijam.xu@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6042 Reviewed-on: http://review.whamcloud.com/13163 Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Niu Yawei <yawei.niu@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/osc/osc_object.c b/drivers/staging/lustre/lustre/osc/osc_object.c index d211d19..5fc5479 100644 --- a/drivers/staging/lustre/lustre/osc/osc_object.c +++ b/drivers/staging/lustre/lustre/osc/osc_object.c @@ -195,7 +195,6 @@ static int osc_object_glimpse(const struct lu_env *env, static int osc_object_ast_clear(struct ldlm_lock *lock, void *data) { - LASSERT(lock->l_granted_mode == lock->l_req_mode); if (lock->l_ast_data == data) lock->l_ast_data = NULL; return LDLM_ITER_CONTINUE; -- cgit v0.10.2 From 6ffc4b3b35acf1a860c703fc0c665b2719f5a44b Mon Sep 17 00:00:00 2001 From: Dmitry Eremin <dmitry.eremin@intel.com> Date: Sun, 18 Sep 2016 16:38:36 -0400 Subject: staging: lustre: osc: change cl_extent_tax and *grants to unsigned Change the type accordant usage and remove warnings. Signed-off-by: Dmitry Eremin <dmitry.eremin@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5577 Reviewed-on: http://review.whamcloud.com/12386 Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 8e426b8..5f0f1e3 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -237,7 +237,7 @@ struct client_obd { * the extent size. A chunk is max(PAGE_SIZE, OST block size) */ int cl_chunkbits; - int cl_extent_tax; /* extent overhead, by bytes */ + unsigned int cl_extent_tax; /* extent overhead, by bytes */ /* keep track of objects that have lois that contain pages which * have been queued for async brw. this lock also protects the diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index 830a94b..adc3b6d 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -44,7 +44,7 @@ static int extent_debug; /* set it to be true for more debug */ static void osc_update_pending(struct osc_object *obj, int cmd, int delta); static int osc_extent_wait(const struct lu_env *env, struct osc_extent *ext, - int state); + enum osc_extent_state state); static void osc_ap_completion(const struct lu_env *env, struct client_obd *cli, struct osc_async_page *oap, int sent, int rc); static int osc_make_ready(const struct lu_env *env, struct osc_async_page *oap, @@ -177,7 +177,7 @@ static int osc_extent_sanity_check0(struct osc_extent *ext, { struct osc_object *obj = ext->oe_obj; struct osc_async_page *oap; - int page_count; + size_t page_count; int rc = 0; if (!osc_object_is_locked(obj)) { @@ -632,7 +632,7 @@ static inline int overlapped(struct osc_extent *ex1, struct osc_extent *ex2) */ static struct osc_extent *osc_extent_find(const struct lu_env *env, struct osc_object *obj, pgoff_t index, - int *grants) + unsigned int *grants) { struct client_obd *cli = osc_cli(obj); struct osc_lock *olck; @@ -643,10 +643,10 @@ static struct osc_extent *osc_extent_find(const struct lu_env *env, struct osc_extent *found = NULL; pgoff_t chunk; pgoff_t max_end; - int max_pages; /* max_pages_per_rpc */ - int chunksize; + unsigned int max_pages; /* max_pages_per_rpc */ + unsigned int chunksize; int ppc_bits; /* pages per chunk bits */ - int chunk_mask; + pgoff_t chunk_mask; int rc; cur = osc_extent_alloc(obj); @@ -700,8 +700,8 @@ restart: if (!ext) ext = first_extent(obj); while (ext) { - loff_t ext_chk_start = ext->oe_start >> ppc_bits; - loff_t ext_chk_end = ext->oe_end >> ppc_bits; + pgoff_t ext_chk_start = ext->oe_start >> ppc_bits; + pgoff_t ext_chk_end = ext->oe_end >> ppc_bits; LASSERT(sanity_check_nolock(ext) == 0); if (chunk > ext_chk_end + 1) @@ -913,7 +913,7 @@ int osc_extent_finish(const struct lu_env *env, struct osc_extent *ext, return 0; } -static int extent_wait_cb(struct osc_extent *ext, int state) +static int extent_wait_cb(struct osc_extent *ext, enum osc_extent_state state) { int ret; @@ -928,7 +928,7 @@ static int extent_wait_cb(struct osc_extent *ext, int state) * Wait for the extent's state to become @state. */ static int osc_extent_wait(const struct lu_env *env, struct osc_extent *ext, - int state) + enum osc_extent_state state) { struct osc_object *obj = ext->oe_obj; struct l_wait_info lwi = LWI_TIMEOUT_INTR(cfs_time_seconds(600), NULL, @@ -958,7 +958,7 @@ static int osc_extent_wait(const struct lu_env *env, struct osc_extent *ext, rc = l_wait_event(ext->oe_waitq, extent_wait_cb(ext, state), &lwi); if (rc == -ETIMEDOUT) { OSC_EXTENT_DUMP(D_ERROR, ext, - "%s: wait ext to %d timedout, recovery in progress?\n", + "%s: wait ext to %u timedout, recovery in progress?\n", osc_export(obj)->exp_obd->obd_name, state); lwi = LWI_INTR(NULL, NULL); @@ -1176,7 +1176,8 @@ static int osc_extent_make_ready(const struct lu_env *env, * called to expand the extent for the same IO. To expand the extent, the * page index must be in the same or next chunk of ext->oe_end. */ -static int osc_extent_expand(struct osc_extent *ext, pgoff_t index, int *grants) +static int osc_extent_expand(struct osc_extent *ext, pgoff_t index, + unsigned int *grants) { struct osc_object *obj = ext->oe_obj; struct client_obd *cli = osc_cli(obj); @@ -1185,7 +1186,7 @@ static int osc_extent_expand(struct osc_extent *ext, pgoff_t index, int *grants) pgoff_t chunk = index >> ppc_bits; pgoff_t end_chunk; pgoff_t end_index; - int chunksize = 1 << cli->cl_chunkbits; + unsigned int chunksize = 1 << cli->cl_chunkbits; int rc = 0; LASSERT(ext->oe_max_end >= index && ext->oe_start <= index); @@ -1363,7 +1364,7 @@ static int osc_completion(const struct lu_env *env, struct osc_async_page *oap, if (rc == 0 && srvlock) { struct lu_device *ld = opg->ops_cl.cpl_obj->co_lu.lo_dev; struct osc_stats *stats = &lu2osc_dev(ld)->od_stats; - int bytes = oap->oap_count; + size_t bytes = oap->oap_count; if (crt == CRT_READ) stats->os_lockless_reads += bytes; @@ -1494,7 +1495,7 @@ static void osc_unreserve_grant(struct client_obd *cli, static void osc_free_grant(struct client_obd *cli, unsigned int nr_pages, unsigned int lost_grant) { - int grant = (1 << cli->cl_chunkbits) + cli->cl_extent_tax; + unsigned long grant = (1 << cli->cl_chunkbits) + cli->cl_extent_tax; spin_lock(&cli->cl_loi_list_lock); atomic_long_sub(nr_pages, &obd_dirty_pages); @@ -1884,7 +1885,7 @@ static void osc_ap_completion(const struct lu_env *env, struct client_obd *cli, */ static int try_to_add_extent_for_io(struct client_obd *cli, struct osc_extent *ext, struct list_head *rpclist, - int *pc, unsigned int *max_pages) + unsigned int *pc, unsigned int *max_pages) { struct osc_extent *tmp; struct osc_async_page *oap = list_first_entry(&ext->oe_pages, @@ -1937,12 +1938,13 @@ static int try_to_add_extent_for_io(struct client_obd *cli, * 5. Traverse the extent tree from the 1st extent; * 6. Above steps exit if there is no space in this RPC. */ -static int get_write_extents(struct osc_object *obj, struct list_head *rpclist) +static unsigned int get_write_extents(struct osc_object *obj, + struct list_head *rpclist) { struct client_obd *cli = osc_cli(obj); struct osc_extent *ext; struct osc_extent *temp; - int page_count = 0; + unsigned int page_count = 0; unsigned int max_pages = cli->cl_max_pages_per_rpc; LASSERT(osc_object_is_locked(obj)); @@ -2080,7 +2082,7 @@ osc_send_read_rpc(const struct lu_env *env, struct client_obd *cli, struct osc_extent *ext; struct osc_extent *next; LIST_HEAD(rpclist); - int page_count = 0; + unsigned int page_count = 0; unsigned int max_pages = cli->cl_max_pages_per_rpc; int rc = 0; @@ -2295,7 +2297,7 @@ int osc_queue_async_io(const struct lu_env *env, struct cl_io *io, struct client_obd *cli = oap->oap_cli; struct osc_object *osc = oap->oap_obj; pgoff_t index; - int grants = 0; + unsigned int grants = 0, tmp; int brw_flags = OBD_BRW_ASYNC; int cmd = OBD_BRW_WRITE; int need_release = 0; @@ -2378,7 +2380,7 @@ int osc_queue_async_io(const struct lu_env *env, struct cl_io *io, grants = 0; need_release = 1; } else if (ext->oe_end < index) { - int tmp = grants; + tmp = grants; /* try to expand this extent */ rc = osc_extent_expand(ext, index, &tmp); if (rc < 0) { @@ -2403,7 +2405,7 @@ int osc_queue_async_io(const struct lu_env *env, struct cl_io *io, } if (!ext) { - int tmp = (1 << cli->cl_chunkbits) + cli->cl_extent_tax; + tmp = (1 << cli->cl_chunkbits) + cli->cl_extent_tax; /* try to find new extent to cover this page */ LASSERT(!oio->oi_active); diff --git a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h index 3068113..9c8de15 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cl_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_cl_internal.h @@ -608,7 +608,7 @@ struct osc_extent { /** link list of osc_object's oo_{hp|urgent|locking}_exts. */ struct list_head oe_link; /** state of this extent */ - unsigned int oe_state; + enum osc_extent_state oe_state; /** flags for this extent. */ unsigned int oe_intree:1, /** 0 is write, 1 is read */ diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c index 96beba4..8bbb2a6 100644 --- a/drivers/staging/lustre/lustre/osc/osc_io.c +++ b/drivers/staging/lustre/lustre/osc/osc_io.c @@ -109,11 +109,11 @@ static int osc_io_submit(const struct lu_env *env, struct cl_page_list *qin = &queue->c2_qin; struct cl_page_list *qout = &queue->c2_qout; - int queued = 0; + unsigned int queued = 0; int result = 0; int cmd; int brw_flags; - int max_pages; + unsigned int max_pages; LASSERT(qin->pl_nr > 0); diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 67b72c8..a0f04e1 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -1110,7 +1110,7 @@ static u32 osc_checksum_bulk(int nob, u32 pg_count, } while (nob > 0 && pg_count > 0) { - int count = pga[i]->count > nob ? nob : pga[i]->count; + unsigned int count = pga[i]->count > nob ? nob : pga[i]->count; /* corrupt the data before we compute the checksum, to * simulate an OST->client data error @@ -1120,7 +1120,7 @@ static u32 osc_checksum_bulk(int nob, u32 pg_count, unsigned char *ptr = kmap(pga[i]->pg); int off = pga[i]->off & ~PAGE_MASK; - memcpy(ptr + off, "bad1", min(4, nob)); + memcpy(ptr + off, "bad1", min_t(typeof(nob), 4, nob)); kunmap(pga[i]->pg); } cfs_crypto_hash_update_page(hdesc, pga[i]->pg, -- cgit v0.10.2 From a466ca4ed0291956235a01ed8ca0b7a5761977b7 Mon Sep 17 00:00:00 2001 From: Andreas Dilger <andreas.dilger@intel.com> Date: Sun, 18 Sep 2016 16:38:37 -0400 Subject: staging: lustre: lprocfs: cleanup stats locking code Add comment blocks on lprocfs_stats_lock() and lprocfs_stats_unlock(). Move common NOPERCPU code out of the switch() statements to reduce code size and complexity, since it doesn't depend on the opc at all. Replace switch() in lprocfs_stats_unlock() with a simple if/else, since the lock opc was already checked in lprocfs_stats_lock(). Add an enum for the lprocfs_stats_lock() operations to make it clear what the valid values are and allow compiler checking. Signed-off-by: Andreas Dilger <andreas.dilger@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5946 Reviewed-on: http://review.whamcloud.com/12872 Reviewed-by: Bobi Jam <bobijam@hotmail.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lprocfs_status.h b/drivers/staging/lustre/lustre/include/lprocfs_status.h index b1a8ca5..cc0713e 100644 --- a/drivers/staging/lustre/lustre/include/lprocfs_status.h +++ b/drivers/staging/lustre/lustre/include/lprocfs_status.h @@ -165,8 +165,10 @@ struct lprocfs_percpu { struct lprocfs_counter lp_cntr[0]; }; -#define LPROCFS_GET_NUM_CPU 0x0001 -#define LPROCFS_GET_SMP_ID 0x0002 +enum lprocfs_stats_lock_ops { + LPROCFS_GET_NUM_CPU = 0x0001, /* number allocated per-CPU stats */ + LPROCFS_GET_SMP_ID = 0x0002, /* current stat to be updated */ +}; enum lprocfs_stats_flags { LPROCFS_STATS_FLAG_NONE = 0x0000, /* per cpu counter */ @@ -371,77 +373,91 @@ int lprocfs_write_frac_helper(const char __user *buffer, int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val, int mult); int lprocfs_stats_alloc_one(struct lprocfs_stats *stats, unsigned int cpuid); -/* - * \return value - * < 0 : on error (only possible for opc as LPROCFS_GET_SMP_ID) + +/** + * Lock statistics structure for access, possibly only on this CPU. + * + * The statistics struct may be allocated with per-CPU structures for + * efficient concurrent update (usually only on server-wide stats), or + * as a single global struct (e.g. for per-client or per-job statistics), + * so the required locking depends on the type of structure allocated. + * + * For per-CPU statistics, pin the thread to the current cpuid so that + * will only access the statistics for that CPU. If the stats structure + * for the current CPU has not been allocated (or previously freed), + * allocate it now. The per-CPU statistics do not need locking since + * the thread is pinned to the CPU during update. + * + * For global statistics, lock the stats structure to prevent concurrent update. + * + * \param[in] stats statistics structure to lock + * \param[in] opc type of operation: + * LPROCFS_GET_SMP_ID: "lock" and return current CPU index + * for incrementing statistics for that CPU + * LPROCFS_GET_NUM_CPU: "lock" and return number of used + * CPU indices to iterate over all indices + * \param[out] flags CPU interrupt saved state for IRQ-safe locking + * + * \retval cpuid of current thread or number of allocated structs + * \retval negative on error (only for opc LPROCFS_GET_SMP_ID + per-CPU stats) */ -static inline int lprocfs_stats_lock(struct lprocfs_stats *stats, int opc, +static inline int lprocfs_stats_lock(struct lprocfs_stats *stats, + enum lprocfs_stats_lock_ops opc, unsigned long *flags) { - int rc = 0; + if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) { + if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) + spin_lock_irqsave(&stats->ls_lock, *flags); + else + spin_lock(&stats->ls_lock); + return opc == LPROCFS_GET_NUM_CPU ? 1 : 0; + } switch (opc) { - default: - LBUG(); + case LPROCFS_GET_SMP_ID: { + unsigned int cpuid = get_cpu(); + + if (unlikely(!stats->ls_percpu[cpuid])) { + int rc = lprocfs_stats_alloc_one(stats, cpuid); - case LPROCFS_GET_SMP_ID: - if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) { - if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) - spin_lock_irqsave(&stats->ls_lock, *flags); - else - spin_lock(&stats->ls_lock); - return 0; - } else { - unsigned int cpuid = get_cpu(); - - if (unlikely(!stats->ls_percpu[cpuid])) { - rc = lprocfs_stats_alloc_one(stats, cpuid); - if (rc < 0) { - put_cpu(); - return rc; - } + if (rc < 0) { + put_cpu(); + return rc; } - return cpuid; } - + return cpuid; + } case LPROCFS_GET_NUM_CPU: - if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) { - if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) - spin_lock_irqsave(&stats->ls_lock, *flags); - else - spin_lock(&stats->ls_lock); - return 1; - } return stats->ls_biggest_alloc_num; + default: + LBUG(); } } -static inline void lprocfs_stats_unlock(struct lprocfs_stats *stats, int opc, +/** + * Unlock statistics structure after access. + * + * Unlock the lock acquired via lprocfs_stats_lock() for global statistics, + * or unpin this thread from the current cpuid for per-CPU statistics. + * + * This function must be called using the same arguments as used when calling + * lprocfs_stats_lock() so that the correct operation can be performed. + * + * \param[in] stats statistics structure to unlock + * \param[in] opc type of operation (current cpuid or number of structs) + * \param[in] flags CPU interrupt saved state for IRQ-safe locking + */ +static inline void lprocfs_stats_unlock(struct lprocfs_stats *stats, + enum lprocfs_stats_lock_ops opc, unsigned long *flags) { - switch (opc) { - default: - LBUG(); - - case LPROCFS_GET_SMP_ID: - if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) { - if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) - spin_unlock_irqrestore(&stats->ls_lock, *flags); - else - spin_unlock(&stats->ls_lock); - } else { - put_cpu(); - } - return; - - case LPROCFS_GET_NUM_CPU: - if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) { - if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) - spin_unlock_irqrestore(&stats->ls_lock, *flags); - else - spin_unlock(&stats->ls_lock); - } - return; + if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) { + if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) + spin_unlock_irqrestore(&stats->ls_lock, *flags); + else + spin_unlock(&stats->ls_lock); + } else if (opc == LPROCFS_GET_SMP_ID) { + put_cpu(); } } -- cgit v0.10.2 From 6d2f0127b2c6a4d518135fd014caa5be7c148eb1 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Sun, 18 Sep 2016 16:38:38 -0400 Subject: staging: lustre: llite: unlock inode size in ll_lov_setstripe_ea_info() In ll_lov_setstripe_ea_info() release the inode size lock on all appropriate exit paths. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6059 Reviewed-on: http://review.whamcloud.com/13167 Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Lai Siyao <lai.siyao@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 2cb0b65..ce96c9f 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -1301,7 +1301,10 @@ int ll_lov_setstripe_ea_info(struct inode *inode, struct dentry *dentry, int lum_size) { struct lov_stripe_md *lsm = NULL; - struct lookup_intent oit = {.it_op = IT_OPEN, .it_flags = flags}; + struct lookup_intent oit = { + .it_op = IT_OPEN, + .it_flags = flags | MDS_OPEN_BY_FID, + }; int rc = 0; lsm = ccc_inode_lsm_get(inode); @@ -1314,13 +1317,12 @@ int ll_lov_setstripe_ea_info(struct inode *inode, struct dentry *dentry, } ll_inode_size_lock(inode); - oit.it_flags |= MDS_OPEN_BY_FID; rc = ll_intent_file_open(dentry, lum, lum_size, &oit); - if (rc) + if (rc < 0) goto out_unlock; rc = oit.it_status; if (rc < 0) - goto out_req_free; + goto out_unlock; ll_release_openhandle(inode, &oit); @@ -1330,9 +1332,6 @@ out_unlock: ccc_inode_lsm_put(inode, lsm); out: return rc; -out_req_free: - ptlrpc_req_finished((struct ptlrpc_request *)oit.it_request); - goto out; } int ll_lov_getstripe_ea_info(struct inode *inode, const char *filename, -- cgit v0.10.2 From 6314ccb684857b8026f42a44a6dbc371548caae9 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin <dmitry.eremin@intel.com> Date: Sun, 18 Sep 2016 16:38:39 -0400 Subject: staging: lustre: obd: change type of cl_conn_count to size_t Change type of cl_conn_count to size_t. Signed-off-by: Dmitry Eremin <dmitry.eremin@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5577 Reviewed-on: http://review.whamcloud.com/13125 Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 5f0f1e3..986c6e9 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -202,7 +202,7 @@ struct client_obd { struct rw_semaphore cl_sem; struct obd_uuid cl_target_uuid; struct obd_import *cl_import; /* ptlrpc connection state */ - int cl_conn_count; + size_t cl_conn_count; /* max_mds_easize is purely a performance thing so we don't have to * call obd_size_diskmd() all the time. */ diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c index 9a5f56a..153e990 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c @@ -536,7 +536,7 @@ int client_disconnect_export(struct obd_export *exp) imp = cli->cl_import; down_write(&cli->cl_sem); - CDEBUG(D_INFO, "disconnect %s - %d\n", obd->obd_name, + CDEBUG(D_INFO, "disconnect %s - %zu\n", obd->obd_name, cli->cl_conn_count); if (!cli->cl_conn_count) { -- cgit v0.10.2 From c658b69656bb3081e1cd4ba93d2f2d8626903716 Mon Sep 17 00:00:00 2001 From: Liang Zhen <liang.zhen@intel.com> Date: Sun, 18 Sep 2016 16:38:40 -0400 Subject: staging: lustre: libcfs: check mask returned by cpumask_of_node cpumask_of_node can return NULL if NUMA node is unavailable, in this case cfs_node_to_cpumask will try to copy from NULL and cause kernel panic. Signed-off-by: Liang Zhen <liang.zhen@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5751 Reviewed-on: http://review.whamcloud.com/13207 Reviewed-by: Li Wei <wei.g.li@intel.com> Reviewed-by: Bobi Jam <bobijam@hotmail.com> Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-cpu.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-cpu.c index b52518c5..e8b1a61 100644 --- a/drivers/staging/lustre/lnet/libcfs/linux/linux-cpu.c +++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-cpu.c @@ -74,6 +74,17 @@ struct cfs_cpt_data { static struct cfs_cpt_data cpt_data; +static void +cfs_node_to_cpumask(int node, cpumask_t *mask) +{ + const cpumask_t *tmp = cpumask_of_node(node); + + if (tmp) + cpumask_copy(mask, tmp); + else + cpumask_clear(mask); +} + void cfs_cpt_table_free(struct cfs_cpt_table *cptab) { @@ -403,7 +414,7 @@ cfs_cpt_set_node(struct cfs_cpt_table *cptab, int cpt, int node) mutex_lock(&cpt_data.cpt_mutex); mask = cpt_data.cpt_cpumask; - cpumask_copy(mask, cpumask_of_node(node)); + cfs_node_to_cpumask(node, mask); rc = cfs_cpt_set_cpumask(cptab, cpt, mask); @@ -427,7 +438,7 @@ cfs_cpt_unset_node(struct cfs_cpt_table *cptab, int cpt, int node) mutex_lock(&cpt_data.cpt_mutex); mask = cpt_data.cpt_cpumask; - cpumask_copy(mask, cpumask_of_node(node)); + cfs_node_to_cpumask(node, mask); cfs_cpt_unset_cpumask(cptab, cpt, mask); @@ -749,7 +760,7 @@ cfs_cpt_table_create(int ncpt) } for_each_online_node(i) { - cpumask_copy(mask, cpumask_of_node(i)); + cfs_node_to_cpumask(i, mask); while (!cpumask_empty(mask)) { struct cfs_cpu_partition *part; -- cgit v0.10.2 From 23ec6607e98bf78a864c5d3393aa07f4ece3ff3a Mon Sep 17 00:00:00 2001 From: "John L. Hammond" <john.hammond@intel.com> Date: Sun, 18 Sep 2016 16:38:41 -0400 Subject: staging: lustre: remove lustre/include/linux/ Merge the contents of lustre/include/linux/lvfs.h into lustre/include/lvfs.h. Merge lustre/include/linux/lustre_user.h into lustre/include/lustre/lustre_user.h. Move lustre_compat25.h and lustre_patchless_compat.h from lustre/include/linux/ to lustre/include/ and rename lustre_compat25.h to lustre_compat.h. Signed-off-by: John L. Hammond <john.hammond@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2675 Reviewed-on: http://review.whamcloud.com/13271 Reviewed-by: Bob Glossman <bob.glossman@intel.com> Reviewed-by: Amir Shehata <amir.shehata@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index c1bcff8..409a324 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -93,8 +93,8 @@ * super-class definitions. */ #include "lu_object.h" +#include "lustre_compat.h" #include <linux/atomic.h> -#include "linux/lustre_compat25.h" #include <linux/mutex.h> #include <linux/radix-tree.h> #include <linux/spinlock.h> diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h deleted file mode 100644 index 1eb64ec..0000000 --- a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.gnu.org/licenses/gpl-2.0.html - * - * GPL HEADER END - */ -/* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 2011, 2012, Intel Corporation. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - */ - -#ifndef _LINUX_COMPAT25_H -#define _LINUX_COMPAT25_H - -#include <linux/fs_struct.h> -#include <linux/namei.h> - -#include "lustre_patchless_compat.h" - -/* - * set ATTR_BLOCKS to a high value to avoid any risk of collision with other - * ATTR_* attributes (see bug 13828) - */ -#define ATTR_BLOCKS (1 << 27) - -#define current_ngroups current_cred()->group_info->ngroups -#define current_groups current_cred()->group_info->small_block - -/* - * OBD need working random driver, thus all our - * initialization routines must be called after device - * driver initialization - */ -#ifndef MODULE -#undef module_init -#define module_init(a) late_initcall(a) -#endif - -#define LTIME_S(time) (time.tv_sec) - -#ifndef QUOTA_OK -# define QUOTA_OK 0 -#endif -#ifndef NO_QUOTA -# define NO_QUOTA (-EDQUOT) -#endif - -#if !defined(_ASM_GENERIC_BITOPS_EXT2_NON_ATOMIC_H_) && !defined(ext2_set_bit) -# define ext2_set_bit __test_and_set_bit_le -# define ext2_clear_bit __test_and_clear_bit_le -# define ext2_test_bit test_bit_le -# define ext2_find_first_zero_bit find_first_zero_bit_le -# define ext2_find_next_zero_bit find_next_zero_bit_le -#endif - -#endif /* _COMPAT25_H */ diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_patchless_compat.h b/drivers/staging/lustre/lustre/include/linux/lustre_patchless_compat.h deleted file mode 100644 index 5842cb1..0000000 --- a/drivers/staging/lustre/lustre/include/linux/lustre_patchless_compat.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.gnu.org/licenses/gpl-2.0.html - * - * GPL HEADER END - */ -/* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 2011, 2012, Intel Corporation. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - */ - -#ifndef LUSTRE_PATCHLESS_COMPAT_H -#define LUSTRE_PATCHLESS_COMPAT_H - -#include <linux/fs.h> - -#include <linux/list.h> -#include <linux/mm.h> -#include <linux/hash.h> - -#define ll_delete_from_page_cache(page) delete_from_page_cache(page) - -static inline void -truncate_complete_page(struct address_space *mapping, struct page *page) -{ - if (page->mapping != mapping) - return; - - if (PagePrivate(page)) - page->mapping->a_ops->invalidatepage(page, 0, PAGE_SIZE); - - cancel_dirty_page(page); - ClearPageMappedToDisk(page); - ll_delete_from_page_cache(page); -} - -#ifndef ATTR_CTIME_SET -/* - * set ATTR_CTIME_SET to a high value to avoid any risk of collision with other - * ATTR_* attributes (see bug 13828) - */ -#define ATTR_CTIME_SET (1 << 28) -#endif - -#endif /* LUSTRE_PATCHLESS_COMPAT_H */ diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_user.h b/drivers/staging/lustre/lustre/include/linux/lustre_user.h deleted file mode 100644 index e967950..0000000 --- a/drivers/staging/lustre/lustre/include/linux/lustre_user.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.gnu.org/licenses/gpl-2.0.html - * - * GPL HEADER END - */ -/* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 2012, Intel Corporation. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - * - * lustre/include/linux/lustre_user.h - * - * Lustre public user-space interface definitions. - */ - -#ifndef _LINUX_LUSTRE_USER_H -#define _LINUX_LUSTRE_USER_H - -# include <linux/quota.h> - -/* - * asm-x86_64/processor.h on some SLES 9 distros seems to use - * kernel-only typedefs. fortunately skipping it altogether is ok - * (for now). - */ -#define __ASM_X86_64_PROCESSOR_H - -#include <linux/string.h> - -/* - * We need to always use 64bit version because the structure - * is shared across entire cluster where 32bit and 64bit machines - * are co-existing. - */ -#if __BITS_PER_LONG != 64 || defined(__ARCH_WANT_STAT64) -typedef struct stat64 lstat_t; -#define lstat_f lstat64 -#else -typedef struct stat lstat_t; -#define lstat_f lstat -#endif - -#define HAVE_LOV_USER_MDS_DATA - -#endif /* _LUSTRE_USER_H */ diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index ba679ad..6fc9855 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -42,8 +42,33 @@ * @{ */ +#ifdef __KERNEL__ +# include <linux/quota.h> +# include <linux/string.h> /* snprintf() */ +# include <linux/version.h> +#else /* !__KERNEL__ */ +# define NEED_QUOTA_DEFS +# include <stdio.h> /* snprintf() */ +# include <string.h> +# include <sys/quota.h> +# include <sys/stat.h> +#endif /* __KERNEL__ */ #include "ll_fiemap.h" -#include "../linux/lustre_user.h" + +/* + * We need to always use 64bit version because the structure + * is shared across entire cluster where 32bit and 64bit machines + * are co-existing. + */ +#if __BITS_PER_LONG != 64 || defined(__ARCH_WANT_STAT64) +typedef struct stat64 lstat_t; +#define lstat_f lstat64 +#else +typedef struct stat lstat_t; +#define lstat_f lstat +#endif + +#define HAVE_LOV_USER_MDS_DATA #define LUSTRE_EOF 0xffffffffffffffffULL diff --git a/drivers/staging/lustre/lustre/include/lustre_compat.h b/drivers/staging/lustre/lustre/include/lustre_compat.h new file mode 100644 index 0000000..567c438 --- /dev/null +++ b/drivers/staging/lustre/lustre/include/lustre_compat.h @@ -0,0 +1,77 @@ +/* + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.gnu.org/licenses/gpl-2.0.html + * + * GPL HEADER END + */ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Use is subject to license terms. + * + * Copyright (c) 2011, 2012, Intel Corporation. + */ +/* + * This file is part of Lustre, http://www.lustre.org/ + * Lustre is a trademark of Sun Microsystems, Inc. + */ + +#ifndef _LUSTRE_COMPAT_H +#define _LUSTRE_COMPAT_H + +#include <linux/fs_struct.h> +#include <linux/namei.h> + +#include "lustre_patchless_compat.h" + +/* + * set ATTR_BLOCKS to a high value to avoid any risk of collision with other + * ATTR_* attributes (see bug 13828) + */ +#define ATTR_BLOCKS (1 << 27) + +#define current_ngroups current_cred()->group_info->ngroups +#define current_groups current_cred()->group_info->small_block + +/* + * OBD need working random driver, thus all our + * initialization routines must be called after device + * driver initialization + */ +#ifndef MODULE +#undef module_init +#define module_init(a) late_initcall(a) +#endif + +#define LTIME_S(time) (time.tv_sec) + +#ifndef QUOTA_OK +# define QUOTA_OK 0 +#endif +#ifndef NO_QUOTA +# define NO_QUOTA (-EDQUOT) +#endif + +#if !defined(_ASM_GENERIC_BITOPS_EXT2_NON_ATOMIC_H_) && !defined(ext2_set_bit) +# define ext2_set_bit __test_and_set_bit_le +# define ext2_clear_bit __test_and_clear_bit_le +# define ext2_test_bit test_bit_le +# define ext2_find_first_zero_bit find_first_zero_bit_le +# define ext2_find_next_zero_bit find_next_zero_bit_le +#endif + +#endif /* _LUSTRE_COMPAT_H */ diff --git a/drivers/staging/lustre/lustre/include/lustre_patchless_compat.h b/drivers/staging/lustre/lustre/include/lustre_patchless_compat.h new file mode 100644 index 0000000..5842cb1 --- /dev/null +++ b/drivers/staging/lustre/lustre/include/lustre_patchless_compat.h @@ -0,0 +1,66 @@ +/* + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.gnu.org/licenses/gpl-2.0.html + * + * GPL HEADER END + */ +/* + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Use is subject to license terms. + * + * Copyright (c) 2011, 2012, Intel Corporation. + */ +/* + * This file is part of Lustre, http://www.lustre.org/ + * Lustre is a trademark of Sun Microsystems, Inc. + */ + +#ifndef LUSTRE_PATCHLESS_COMPAT_H +#define LUSTRE_PATCHLESS_COMPAT_H + +#include <linux/fs.h> + +#include <linux/list.h> +#include <linux/mm.h> +#include <linux/hash.h> + +#define ll_delete_from_page_cache(page) delete_from_page_cache(page) + +static inline void +truncate_complete_page(struct address_space *mapping, struct page *page) +{ + if (page->mapping != mapping) + return; + + if (PagePrivate(page)) + page->mapping->a_ops->invalidatepage(page, 0, PAGE_SIZE); + + cancel_dirty_page(page); + ClearPageMappedToDisk(page); + ll_delete_from_page_cache(page); +} + +#ifndef ATTR_CTIME_SET +/* + * set ATTR_CTIME_SET to a high value to avoid any risk of collision with other + * ATTR_* attributes (see bug 13828) + */ +#define ATTR_CTIME_SET (1 << 28) +#endif + +#endif /* LUSTRE_PATCHLESS_COMPAT_H */ diff --git a/drivers/staging/lustre/lustre/include/obd_support.h b/drivers/staging/lustre/lustre/include/obd_support.h index 3144cca..b346a7f 100644 --- a/drivers/staging/lustre/lustre/include/obd_support.h +++ b/drivers/staging/lustre/lustre/include/obd_support.h @@ -35,7 +35,7 @@ #include <linux/slab.h> #include "../../include/linux/libcfs/libcfs.h" -#include "linux/lustre_compat25.h" +#include "lustre_compat.h" #include "lprocfs_status.h" /* global variables */ diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index ce96c9f..e8963fe 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -42,11 +42,11 @@ #include <linux/file.h> #include <linux/sched.h> #include <linux/mount.h> -#include "llite_internal.h" #include "../include/lustre/ll_fiemap.h" #include "../include/lustre/lustre_ioctl.h" #include "../include/cl_object.h" +#include "llite_internal.h" static int ll_put_grouplock(struct inode *inode, struct file *file, unsigned long arg); diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 05f2aa3..e5f1967 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -39,11 +39,14 @@ #include "../include/lustre_linkea.h" /* for struct cl_lock_descr and struct cl_io */ +#include "../include/lustre_patchless_compat.h" +#include "../include/lustre_compat.h" #include "../include/cl_object.h" #include "../include/lustre_lmv.h" #include "../include/lustre_mdc.h" #include "../include/lustre_intent.h" #include <linux/compat.h> +#include <linux/namei.h> #include <linux/xattr.h> #include <linux/posix_acl_xattr.h> #include "vvp_internal.h" diff --git a/drivers/staging/lustre/lustre/llite/llite_mmap.c b/drivers/staging/lustre/lustre/llite/llite_mmap.c index 0cd25bf..4366918 100644 --- a/drivers/staging/lustre/lustre/llite/llite_mmap.c +++ b/drivers/staging/lustre/lustre/llite/llite_mmap.c @@ -44,7 +44,6 @@ #define DEBUG_SUBSYSTEM S_LLITE #include "llite_internal.h" -#include "../include/linux/lustre_compat25.h" static const struct vm_operations_struct ll_file_vm_ops; diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index 508cb46..50c0152 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -52,7 +52,6 @@ #include "../include/obd_cksum.h" #include "llite_internal.h" -#include "../include/linux/lustre_compat25.h" static void ll_ra_stats_inc_sbi(struct ll_sb_info *sbi, enum ra_stat which); diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c index df0318e..26f3a37 100644 --- a/drivers/staging/lustre/lustre/llite/rw26.c +++ b/drivers/staging/lustre/lustre/llite/rw26.c @@ -52,7 +52,6 @@ #define DEBUG_SUBSYSTEM S_LLITE #include "llite_internal.h" -#include "../include/linux/lustre_compat25.h" /** * Implements Linux VM address_space::invalidatepage() method. This method is diff --git a/drivers/staging/lustre/lustre/obdclass/obd_mount.c b/drivers/staging/lustre/lustre/obdclass/obd_mount.c index 0df1aa6..0d3a3b0 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_mount.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_mount.c @@ -41,7 +41,7 @@ #define PRINT_CMD CDEBUG #include "../include/obd.h" -#include "../include/linux/lustre_compat25.h" +#include "../include/lustre_compat.h" #include "../include/obd_class.h" #include "../include/lustre/lustre_user.h" #include "../include/lustre_log.h" -- cgit v0.10.2 From 864d6a257e492e8c658a58841b35928d411151ab Mon Sep 17 00:00:00 2001 From: Fan Yong <fan.yong@intel.com> Date: Sun, 18 Sep 2016 16:38:42 -0400 Subject: staging: lustre: llite: pack suppgid to MDS correctly The ll_lookup_it() may trigger IT_OPEN RPC to open a file by name. But at that time, the client does not know the target file's GID, so it cannot pack the necessary supplementary group ID in the RPC. Because of missing the supplementary group ID, the RPC maybe fail for open permission check on the MDS. Under such case, MDS should return the target file's GID, if the current thread on the client in the right group (according to the file's GID), the client will try the IT_OPEN RPC again with the right supplementary group ID. This patch is also helpful if some other(s) changed the file's GID after current RPC sent to the MDS with the suppgid as the original GID by race. Signed-off-by: Fan Yong <fan.yong@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5423 Reviewed-on: http://review.whamcloud.com/12476 Reviewed-by: Lai Siyao <lai.siyao@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index acb2806..72eaee9 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -1987,6 +1987,7 @@ void lustre_swab_generic_32s(__u32 *val); #define DISP_OPEN_LOCK 0x02000000 #define DISP_OPEN_LEASE 0x04000000 #define DISP_OPEN_STRIPE 0x08000000 +#define DISP_OPEN_DENY 0x10000000 /* INODE LOCK PARTS */ #define MDS_INODELOCK_LOOKUP 0x000001 /* For namespace, dentry etc, and also diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index 1dd5df5..d55b14b 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -505,8 +505,8 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry, struct lookup_intent lookup_it = { .it_op = IT_LOOKUP }; struct dentry *save = dentry, *retval; struct ptlrpc_request *req = NULL; + struct md_op_data *op_data = NULL; struct inode *inode; - struct md_op_data *op_data; __u32 opc; int rc; @@ -549,7 +549,36 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry, rc = md_intent_lock(ll_i2mdexp(parent), op_data, it, &req, &ll_md_blocking_ast, 0); - ll_finish_md_op_data(op_data); + /* + * If the MDS allows the client to chgrp (CFS_SETGRP_PERM), but the + * client does not know which suppgid should be sent to the MDS, or + * some other(s) changed the target file's GID after this RPC sent + * to the MDS with the suppgid as the original GID, then we should + * try again with right suppgid. + */ + if (rc == -EACCES && it->it_op & IT_OPEN && + it_disposition(it, DISP_OPEN_DENY)) { + struct mdt_body *body; + + LASSERT(req); + + body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); + if (op_data->op_suppgids[0] == body->mbo_gid || + op_data->op_suppgids[1] == body->mbo_gid || + !in_group_p(make_kgid(&init_user_ns, body->mbo_gid))) { + retval = ERR_PTR(-EACCES); + goto out; + } + + fid_zero(&op_data->op_fid2); + op_data->op_suppgids[1] = body->mbo_gid; + ptlrpc_req_finished(req); + req = NULL; + ll_intent_release(it); + rc = md_intent_lock(ll_i2mdexp(parent), op_data, it, &req, + ll_md_blocking_ast, 0); + } + if (rc < 0) { retval = ERR_PTR(rc); goto out; @@ -575,6 +604,9 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry, else retval = dentry; out: + if (op_data && !IS_ERR(op_data)) + ll_finish_md_op_data(op_data); + ptlrpc_req_finished(req); return retval; } -- cgit v0.10.2 From 96234ec51269417ec5c43bf13daede17cf4078ba Mon Sep 17 00:00:00 2001 From: Bobi Jam <bobijam.xu@intel.com> Date: Sun, 18 Sep 2016 16:38:43 -0400 Subject: staging: lustre: clio: rename coo_attr_set to coo_attr_update coo_attr_set() is used to update object's attribute but its name makes confusion that people intuitively think that it is used to pass object's attribute down to server sides. Signed-off-by: Bobi Jam <bobijam.xu@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-1154 Reviewed-on: http://review.whamcloud.com/12888 Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index 409a324..9403c0c 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -369,8 +369,8 @@ struct cl_object_operations { * \return the same convention as for * cl_object_operations::coo_attr_get() is used. */ - int (*coo_attr_set)(const struct lu_env *env, struct cl_object *obj, - const struct cl_attr *attr, unsigned valid); + int (*coo_attr_update)(const struct lu_env *env, struct cl_object *obj, + const struct cl_attr *attr, unsigned int valid); /** * Update object configuration. Called top-to-bottom to modify object * configuration. @@ -2171,8 +2171,8 @@ void cl_object_attr_lock(struct cl_object *o); void cl_object_attr_unlock(struct cl_object *o); int cl_object_attr_get(const struct lu_env *env, struct cl_object *obj, struct cl_attr *attr); -int cl_object_attr_set(const struct lu_env *env, struct cl_object *obj, - const struct cl_attr *attr, unsigned valid); +int cl_object_attr_update(const struct lu_env *env, struct cl_object *obj, + const struct cl_attr *attr, unsigned int valid); int cl_object_glimpse(const struct lu_env *env, struct cl_object *obj, struct ost_lvb *lvb); int cl_conf_set(const struct lu_env *env, struct cl_object *obj, diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index 27fc0b0..2ab4503 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -627,7 +627,7 @@ static int vvp_io_setattr_time(const struct lu_env *env, attr->cat_mtime = io->u.ci_setattr.sa_attr.lvb_mtime; valid |= CAT_MTIME; } - result = cl_object_attr_set(env, obj, attr, valid); + result = cl_object_attr_update(env, obj, attr, valid); cl_object_attr_unlock(obj); return result; diff --git a/drivers/staging/lustre/lustre/llite/vvp_object.c b/drivers/staging/lustre/lustre/llite/vvp_object.c index 6b6a63d..b57195d 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_object.c +++ b/drivers/staging/lustre/lustre/llite/vvp_object.c @@ -101,8 +101,8 @@ static int vvp_attr_get(const struct lu_env *env, struct cl_object *obj, return 0; /* layers below have to fill in the rest */ } -static int vvp_attr_set(const struct lu_env *env, struct cl_object *obj, - const struct cl_attr *attr, unsigned valid) +static int vvp_attr_update(const struct lu_env *env, struct cl_object *obj, + const struct cl_attr *attr, unsigned int valid) { struct inode *inode = vvp_object_inode(obj); @@ -209,7 +209,7 @@ static const struct cl_object_operations vvp_ops = { .coo_lock_init = vvp_lock_init, .coo_io_init = vvp_io_init, .coo_attr_get = vvp_attr_get, - .coo_attr_set = vvp_attr_set, + .coo_attr_update = vvp_attr_update, .coo_conf_set = vvp_conf_set, .coo_prune = vvp_prune, .coo_glimpse = vvp_object_glimpse diff --git a/drivers/staging/lustre/lustre/lov/lov_object.c b/drivers/staging/lustre/lustre/lov/lov_object.c index 01f95a9..52f7363 100644 --- a/drivers/staging/lustre/lustre/lov/lov_object.c +++ b/drivers/staging/lustre/lustre/lov/lov_object.c @@ -894,8 +894,8 @@ static int lov_attr_get(const struct lu_env *env, struct cl_object *obj, return LOV_2DISPATCH_NOLOCK(cl2lov(obj), llo_getattr, env, obj, attr); } -static int lov_attr_set(const struct lu_env *env, struct cl_object *obj, - const struct cl_attr *attr, unsigned valid) +static int lov_attr_update(const struct lu_env *env, struct cl_object *obj, + const struct cl_attr *attr, unsigned int valid) { /* * No dispatch is required here, as no layout implements this. @@ -932,7 +932,7 @@ static const struct cl_object_operations lov_ops = { .coo_lock_init = lov_lock_init, .coo_io_init = lov_io_init, .coo_attr_get = lov_attr_get, - .coo_attr_set = lov_attr_set, + .coo_attr_update = lov_attr_update, .coo_conf_set = lov_conf_set, .coo_getstripe = lov_object_getstripe }; diff --git a/drivers/staging/lustre/lustre/lov/lovsub_object.c b/drivers/staging/lustre/lustre/lov/lovsub_object.c index fb2f266..a2bac7a 100644 --- a/drivers/staging/lustre/lustre/lov/lovsub_object.c +++ b/drivers/staging/lustre/lustre/lov/lovsub_object.c @@ -98,8 +98,8 @@ static int lovsub_object_print(const struct lu_env *env, void *cookie, return (*p)(env, cookie, "[%d]", los->lso_index); } -static int lovsub_attr_set(const struct lu_env *env, struct cl_object *obj, - const struct cl_attr *attr, unsigned valid) +static int lovsub_attr_update(const struct lu_env *env, struct cl_object *obj, + const struct cl_attr *attr, unsigned int valid) { struct lov_object *lov = cl2lovsub(obj)->lso_super; @@ -119,7 +119,7 @@ static int lovsub_object_glimpse(const struct lu_env *env, static const struct cl_object_operations lovsub_ops = { .coo_page_init = lovsub_page_init, .coo_lock_init = lovsub_lock_init, - .coo_attr_set = lovsub_attr_set, + .coo_attr_update = lovsub_attr_update, .coo_glimpse = lovsub_object_glimpse }; diff --git a/drivers/staging/lustre/lustre/obdclass/cl_object.c b/drivers/staging/lustre/lustre/obdclass/cl_object.c index ef5b1aa..e493c80 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_object.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_object.c @@ -163,7 +163,7 @@ static spinlock_t *cl_object_attr_guard(struct cl_object *o) * * Prevents data-attributes from changing, until lock is released by * cl_object_attr_unlock(). This has to be called before calls to - * cl_object_attr_get(), cl_object_attr_set(). + * cl_object_attr_get(), cl_object_attr_update(). */ void cl_object_attr_lock(struct cl_object *o) __acquires(cl_object_attr_guard(o)) @@ -217,11 +217,11 @@ EXPORT_SYMBOL(cl_object_attr_get); * Updates data-attributes of an object \a obj. * * Only attributes, mentioned in a validness bit-mask \a v are - * updated. Calls cl_object_operations::coo_attr_set() on every layer, bottom - * to top. + * updated. Calls cl_object_operations::coo_attr_update() on every layer, + * bottom to top. */ -int cl_object_attr_set(const struct lu_env *env, struct cl_object *obj, - const struct cl_attr *attr, unsigned v) +int cl_object_attr_update(const struct lu_env *env, struct cl_object *obj, + const struct cl_attr *attr, unsigned int v) { struct lu_object_header *top; int result; @@ -231,8 +231,9 @@ int cl_object_attr_set(const struct lu_env *env, struct cl_object *obj, top = obj->co_lu.lo_header; result = 0; list_for_each_entry_reverse(obj, &top->loh_layers, co_lu.lo_linkage) { - if (obj->co_ops->coo_attr_set) { - result = obj->co_ops->coo_attr_set(env, obj, attr, v); + if (obj->co_ops->coo_attr_update) { + result = obj->co_ops->coo_attr_update(env, obj, attr, + v); if (result != 0) { if (result > 0) result = 0; @@ -242,7 +243,7 @@ int cl_object_attr_set(const struct lu_env *env, struct cl_object *obj, } return result; } -EXPORT_SYMBOL(cl_object_attr_set); +EXPORT_SYMBOL(cl_object_attr_update); /** * Notifies layers (bottom-to-top) that glimpse AST was received. diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c index 8bbb2a6..42e9761a 100644 --- a/drivers/staging/lustre/lustre/osc/osc_io.c +++ b/drivers/staging/lustre/lustre/osc/osc_io.c @@ -233,7 +233,7 @@ static void osc_page_touch_at(const struct lu_env *env, attr->cat_size = kms; valid |= CAT_SIZE; } - cl_object_attr_set(env, obj, attr, valid); + cl_object_attr_update(env, obj, attr, valid); cl_object_attr_unlock(obj); } @@ -476,7 +476,8 @@ static int osc_io_setattr_start(const struct lu_env *env, attr->cat_ctime = lvb->lvb_ctime; cl_valid |= CAT_CTIME; } - result = cl_object_attr_set(env, obj, attr, cl_valid); + result = cl_object_attr_update(env, obj, attr, + cl_valid); } cl_object_attr_unlock(obj); } @@ -564,7 +565,7 @@ static int osc_io_read_start(const struct lu_env *env, if (!slice->cis_io->ci_noatime) { cl_object_attr_lock(obj); attr->cat_atime = ktime_get_real_seconds(); - rc = cl_object_attr_set(env, obj, attr, CAT_ATIME); + rc = cl_object_attr_update(env, obj, attr, CAT_ATIME); cl_object_attr_unlock(obj); } return rc; @@ -581,7 +582,7 @@ static int osc_io_write_start(const struct lu_env *env, cl_object_attr_lock(obj); attr->cat_ctime = ktime_get_real_seconds(); attr->cat_mtime = attr->cat_ctime; - rc = cl_object_attr_set(env, obj, attr, CAT_MTIME | CAT_CTIME); + rc = cl_object_attr_update(env, obj, attr, CAT_MTIME | CAT_CTIME); cl_object_attr_unlock(obj); return rc; diff --git a/drivers/staging/lustre/lustre/osc/osc_lock.c b/drivers/staging/lustre/lustre/osc/osc_lock.c index 717d3ff..39a8a58 100644 --- a/drivers/staging/lustre/lustre/osc/osc_lock.c +++ b/drivers/staging/lustre/lustre/osc/osc_lock.c @@ -222,7 +222,7 @@ static void osc_lock_lvb_update(const struct lu_env *env, ldlm_lock_allow_match_locked(dlmlock); } - cl_object_attr_set(env, obj, attr, valid); + cl_object_attr_update(env, obj, attr, valid); cl_object_attr_unlock(obj); } @@ -467,7 +467,7 @@ static int osc_dlm_blocking_ast0(const struct lu_env *env, */ attr->cat_kms = ldlm_extent_shift_kms(dlmlock, old_kms); - cl_object_attr_set(env, obj, attr, CAT_KMS); + cl_object_attr_update(env, obj, attr, CAT_KMS); cl_object_attr_unlock(obj); unlock_res_and_lock(dlmlock); diff --git a/drivers/staging/lustre/lustre/osc/osc_object.c b/drivers/staging/lustre/lustre/osc/osc_object.c index 5fc5479..aae3a2d 100644 --- a/drivers/staging/lustre/lustre/osc/osc_object.c +++ b/drivers/staging/lustre/lustre/osc/osc_object.c @@ -159,8 +159,8 @@ static int osc_attr_get(const struct lu_env *env, struct cl_object *obj, return 0; } -static int osc_attr_set(const struct lu_env *env, struct cl_object *obj, - const struct cl_attr *attr, unsigned valid) +static int osc_attr_update(const struct lu_env *env, struct cl_object *obj, + const struct cl_attr *attr, unsigned int valid) { struct lov_oinfo *oinfo = cl2osc(obj)->oo_oinfo; struct ost_lvb *lvb = &oinfo->loi_lvb; @@ -261,7 +261,7 @@ static const struct cl_object_operations osc_ops = { .coo_lock_init = osc_lock_init, .coo_io_init = osc_io_init, .coo_attr_get = osc_attr_get, - .coo_attr_set = osc_attr_set, + .coo_attr_update = osc_attr_update, .coo_glimpse = osc_object_glimpse, .coo_prune = osc_object_prune }; diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index a0f04e1..749781f 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -1749,7 +1749,7 @@ static int brw_interpret(const struct lu_env *env, } if (valid != 0) - cl_object_attr_set(env, obj, attr, valid); + cl_object_attr_update(env, obj, attr, valid); cl_object_attr_unlock(obj); } kmem_cache_free(obdo_cachep, aa->aa_oa); -- cgit v0.10.2 From 7ebb0ef382814c6c23188d7cf13951357fa75302 Mon Sep 17 00:00:00 2001 From: Bobi Jam <bobijam.xu@intel.com> Date: Sun, 18 Sep 2016 16:38:44 -0400 Subject: staging: lustre: clio: pass fid for OST setattr Store inode's fid in cl_setattr_ost() and OSC packs this info on the wire (via lustre_set_wire_obdo) so that OST can use. NOTE: currently lu_fid::f_ver and obdo::o_parent_ver are not used on OFD device, and we use obdo::o_stripe_idx as filter_fid::ff_parent::f_ver and save it to the device. Signed-off-by: Bobi Jam <bobijam.xu@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-1154 Reviewed-on: http://review.whamcloud.com/12902 Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index 9403c0c..89292c9 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -1766,6 +1766,8 @@ struct cl_io { struct cl_setattr_io { struct ost_lvb sa_attr; unsigned int sa_valid; + int sa_stripe_index; + struct lu_fid *sa_parent_fid; } ci_setattr; struct cl_fault_io { /** page index within file. */ diff --git a/drivers/staging/lustre/lustre/llite/lcommon_cl.c b/drivers/staging/lustre/lustre/llite/lcommon_cl.c index 2ded6b5..084330d 100644 --- a/drivers/staging/lustre/lustre/llite/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/llite/lcommon_cl.c @@ -99,6 +99,7 @@ int cl_setattr_ost(struct inode *inode, const struct iattr *attr) io->u.ci_setattr.sa_attr.lvb_ctime = LTIME_S(attr->ia_ctime); io->u.ci_setattr.sa_attr.lvb_size = attr->ia_size; io->u.ci_setattr.sa_valid = attr->ia_valid; + io->u.ci_setattr.sa_parent_fid = ll_inode2fid(inode); again: if (cl_io_init(env, io, CIT_SETATTR, io->ci_obj) == 0) { diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c index 5d47a5a..d101579 100644 --- a/drivers/staging/lustre/lustre/lov/lov_io.c +++ b/drivers/staging/lustre/lustre/lov/lov_io.c @@ -87,6 +87,9 @@ static void lov_io_sub_inherit(struct cl_io *io, struct lov_io *lio, case CIT_SETATTR: { io->u.ci_setattr.sa_attr = parent->u.ci_setattr.sa_attr; io->u.ci_setattr.sa_valid = parent->u.ci_setattr.sa_valid; + io->u.ci_setattr.sa_stripe_index = stripe; + io->u.ci_setattr.sa_parent_fid = + parent->u.ci_setattr.sa_parent_fid; if (cl_io_is_trunc(io)) { loff_t new_size = parent->u.ci_setattr.sa_attr.lvb_size; diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c index 42e9761a..8a559cb 100644 --- a/drivers/staging/lustre/lustre/osc/osc_io.c +++ b/drivers/staging/lustre/lustre/osc/osc_io.c @@ -484,11 +484,13 @@ static int osc_io_setattr_start(const struct lu_env *env, memset(oa, 0, sizeof(*oa)); if (result == 0) { oa->o_oi = loi->loi_oi; + obdo_set_parent_fid(oa, io->u.ci_setattr.sa_parent_fid); + oa->o_stripe_idx = io->u.ci_setattr.sa_stripe_index; oa->o_mtime = attr->cat_mtime; oa->o_atime = attr->cat_atime; oa->o_ctime = attr->cat_ctime; - oa->o_valid = OBD_MD_FLID | OBD_MD_FLGROUP | OBD_MD_FLATIME | - OBD_MD_FLCTIME | OBD_MD_FLMTIME; + oa->o_valid |= OBD_MD_FLID | OBD_MD_FLGROUP | OBD_MD_FLATIME | + OBD_MD_FLCTIME | OBD_MD_FLMTIME; if (ia_valid & ATTR_SIZE) { oa->o_size = size; oa->o_blocks = OBD_OBJECT_EOF; -- cgit v0.10.2 From 0022c6bcb4927c0ad94f9035fd38c123c48e0457 Mon Sep 17 00:00:00 2001 From: Artem Blagodarenko <artem_blagodarenko@xyratex.com> Date: Sun, 18 Sep 2016 16:38:45 -0400 Subject: staging: lustre: client: Fix mkdir -i 1 from DNE2 client to DNE1 server After DNE phase 2 has been added to client it sends create request to slave MDT. DNT1-only server doesn't expect request to slave MDT from client. It expects only cross-mdt request from master MDT. Thus if DNE2 client tries to "mkdir -i 1" on DNE1 server, then LBUG happened. This patch adds OBD_CONNECT_DIR_STRIPE connection flag check on client side. If striped directories are not supported by server, then create requrest is sent to master MDT. Signed-off-by: Artem Blagodarenko <artem_blagodarenko@xyratex.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6071 Xyratex-bug-id: MRP-2319 Reviewed-on: http://review.whamcloud.com/13189 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: wang di <di.wang@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 0337f05..9461cd3 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -1688,15 +1688,19 @@ static int lmv_create(struct obd_export *exp, struct md_op_data *op_data, if (rc) return rc; - /* - * Send the create request to the MDT where the object - * will be located - */ - tgt = lmv_find_target(lmv, &op_data->op_fid2); - if (IS_ERR(tgt)) - return PTR_ERR(tgt); + if (exp_connect_flags(exp) & OBD_CONNECT_DIR_STRIPE) { + /* + * Send the create request to the MDT where the object + * will be located + */ + tgt = lmv_find_target(lmv, &op_data->op_fid2); + if (IS_ERR(tgt)) + return PTR_ERR(tgt); - op_data->op_mds = tgt->ltd_idx; + op_data->op_mds = tgt->ltd_idx; + } else { + CDEBUG(D_CONFIG, "Server doesn't support striped dirs\n"); + } CDEBUG(D_INODE, "CREATE obj "DFID" -> mds #%x\n", PFID(&op_data->op_fid1), op_data->op_mds); -- cgit v0.10.2 From 15b241c539e9b45c17fd7354e8ab9c40f585c4ee Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Sun, 18 Sep 2016 16:38:46 -0400 Subject: staging: lustre: lmv: Do not revalidate stripes with master lock Do not revalidate slave stripes while holding master lock. Otherwise if the revalidating slaves are blocked, then the master lock can not be released in time. Remove some unnecesary merging in ll_revalidate_slave(), and the attributes will be stored in each stripe, only merging them if required. Signed-off-by: wang di <di.wang@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6088 Reviewed-on: http://review.whamcloud.com/13432 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Lai Siyao <lai.siyao@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 986c6e9..c6937b2 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -1000,10 +1000,7 @@ struct md_ops { int (*merge_attr)(struct obd_export *, const struct lmv_stripe_md *lsm, - struct cl_attr *attr); - - int (*update_lsm_md)(struct obd_export *, struct lmv_stripe_md *lsm, - struct mdt_body *, ldlm_blocking_callback); + struct cl_attr *attr, ldlm_blocking_callback); int (*set_open_replay_data)(struct obd_export *, struct obd_client_handle *, diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index 9836aed..16094db 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -1497,23 +1497,14 @@ static inline int md_free_lustre_md(struct obd_export *exp, return MDP(exp->exp_obd, free_lustre_md)(exp, md); } -static inline int md_update_lsm_md(struct obd_export *exp, - struct lmv_stripe_md *lsm, - struct mdt_body *body, - ldlm_blocking_callback cb) -{ - EXP_CHECK_MD_OP(exp, update_lsm_md); - EXP_MD_COUNTER_INCREMENT(exp, update_lsm_md); - return MDP(exp->exp_obd, update_lsm_md)(exp, lsm, body, cb); -} - static inline int md_merge_attr(struct obd_export *exp, const struct lmv_stripe_md *lsm, - struct cl_attr *attr) + struct cl_attr *attr, + ldlm_blocking_callback cb) { EXP_CHECK_MD_OP(exp, merge_attr); EXP_MD_COUNTER_INCREMENT(exp, merge_attr); - return MDP(exp->exp_obd, merge_attr)(exp, lsm, attr); + return MDP(exp->exp_obd, merge_attr)(exp, lsm, attr, cb); } static inline int md_setxattr(struct obd_export *exp, const struct lu_fid *fid, diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index e8963fe..d8761b8 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -3045,12 +3045,13 @@ static int ll_merge_md_attr(struct inode *inode) LASSERT(ll_i2info(inode)->lli_lsm_md); rc = md_merge_attr(ll_i2mdexp(inode), ll_i2info(inode)->lli_lsm_md, - &attr); + &attr, ll_md_blocking_ast); if (rc) return rc; - ll_i2info(inode)->lli_stripe_dir_size = attr.cat_size; - ll_i2info(inode)->lli_stripe_dir_nlink = attr.cat_nlink; + set_nlink(inode, attr.cat_nlink); + inode->i_blocks = attr.cat_blocks; + i_size_write(inode, attr.cat_size); ll_i2info(inode)->lli_atime = attr.cat_atime; ll_i2info(inode)->lli_mtime = attr.cat_mtime; @@ -3123,16 +3124,10 @@ int ll_getattr(struct vfsmount *mnt, struct dentry *de, struct kstat *stat) stat->mtime = inode->i_mtime; stat->ctime = inode->i_ctime; stat->blksize = 1 << inode->i_blkbits; - stat->blocks = inode->i_blocks; - if (S_ISDIR(inode->i_mode) && - ll_i2info(inode)->lli_lsm_md) { - stat->nlink = lli->lli_stripe_dir_nlink; - stat->size = lli->lli_stripe_dir_size; - } else { - stat->nlink = inode->i_nlink; - stat->size = i_size_read(inode); - } + stat->nlink = inode->i_nlink; + stat->size = i_size_read(inode); + stat->blocks = inode->i_blocks; return 0; } diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index e5f1967..51bf071 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -191,9 +191,6 @@ struct ll_inode_info { unsigned int lli_sa_generation; /* directory stripe information */ struct lmv_stripe_md *lli_lsm_md; - /* striped directory size */ - loff_t lli_stripe_dir_size; - u64 lli_stripe_dir_nlink; }; /* for non-directory */ diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index e46214f..15b487b 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -1117,12 +1117,7 @@ static int ll_init_lsm_md(struct inode *inode, struct lustre_md *md) } } - /* - * Here is where the lsm is being initialized(fill lmo_info) after - * client retrieve MD stripe information from MDT. - */ - return md_update_lsm_md(ll_i2mdexp(inode), lsm, md->body, - ll_md_blocking_ast); + return 0; } static inline int lli_lsm_md_eq(const struct lmv_stripe_md *lsm_md1, diff --git a/drivers/staging/lustre/lustre/lmv/lmv_intent.c b/drivers/staging/lustre/lustre/lmv/lmv_intent.c index a96b49d..9f4e826 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_intent.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_intent.c @@ -148,8 +148,8 @@ out: return rc; } -int lmv_revalidate_slaves(struct obd_export *exp, struct mdt_body *mbody, - struct lmv_stripe_md *lsm, +int lmv_revalidate_slaves(struct obd_export *exp, + const struct lmv_stripe_md *lsm, ldlm_blocking_callback cb_blocking, int extra_lock_flags) { @@ -158,11 +158,6 @@ int lmv_revalidate_slaves(struct obd_export *exp, struct mdt_body *mbody, struct ptlrpc_request *req = NULL; struct mdt_body *body; struct md_op_data *op_data; - unsigned long size = 0; - unsigned long nlink = 0; - __s64 atime = 0; - __s64 ctime = 0; - __s64 mtime = 0; int rc = 0, i; /** @@ -243,6 +238,7 @@ int lmv_revalidate_slaves(struct obd_export *exp, struct mdt_body *mbody, } i_size_write(inode, body->mbo_size); + inode->i_blocks = body->mbo_blocks; set_nlink(inode, body->mbo_nlink); LTIME_S(inode->i_atime) = body->mbo_atime; LTIME_S(inode->i_ctime) = body->mbo_ctime; @@ -251,41 +247,12 @@ int lmv_revalidate_slaves(struct obd_export *exp, struct mdt_body *mbody, md_set_lock_data(tgt->ltd_exp, lockh, inode, NULL); - if (i != 0) - nlink += inode->i_nlink - 2; - else - nlink += inode->i_nlink; - - atime = LTIME_S(inode->i_atime) > atime ? - LTIME_S(inode->i_atime) : atime; - ctime = LTIME_S(inode->i_ctime) > ctime ? - LTIME_S(inode->i_ctime) : ctime; - mtime = LTIME_S(inode->i_mtime) > mtime ? - LTIME_S(inode->i_mtime) : mtime; - if (it.it_lock_mode && lockh) { ldlm_lock_decref(lockh, it.it_lock_mode); it.it_lock_mode = 0; } - - CDEBUG(D_INODE, "i %d "DFID" size %llu, nlink %u, atime %lu, mtime %lu, ctime %lu.\n", - i, PFID(&fid), i_size_read(inode), inode->i_nlink, - LTIME_S(inode->i_atime), LTIME_S(inode->i_mtime), - LTIME_S(inode->i_ctime)); } - /* - * update attr of master request. - */ - CDEBUG(D_INODE, "Return refreshed attrs: size = %lu nlink %lu atime %llu ctime %llu mtime %llu for " DFID"\n", - size, nlink, atime, ctime, mtime, - PFID(&lsm->lsm_md_oinfo[0].lmo_fid)); - - if (mbody) { - mbody->mbo_atime = atime; - mbody->mbo_ctime = ctime; - mbody->mbo_mtime = mtime; - } cleanup: if (req) ptlrpc_req_finished(req); @@ -445,7 +412,7 @@ static int lmv_intent_lookup(struct obd_export *exp, * during update_inode process (see ll_update_lsm_md) */ if (op_data->op_mea2) { - rc = lmv_revalidate_slaves(exp, NULL, op_data->op_mea2, + rc = lmv_revalidate_slaves(exp, op_data->op_mea2, cb_blocking, extra_lock_flags); if (rc != 0) diff --git a/drivers/staging/lustre/lustre/lmv/lmv_internal.h b/drivers/staging/lustre/lustre/lmv/lmv_internal.h index 8f703ea..52b0374 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_internal.h +++ b/drivers/staging/lustre/lustre/lmv/lmv_internal.h @@ -57,8 +57,8 @@ int lmv_fid_alloc(const struct lu_env *env, struct obd_export *exp, int lmv_unpack_md(struct obd_export *exp, struct lmv_stripe_md **lsmp, const union lmv_mds_md *lmm, int stripe_count); -int lmv_revalidate_slaves(struct obd_export *exp, struct mdt_body *mbody, - struct lmv_stripe_md *lsm, +int lmv_revalidate_slaves(struct obd_export *exp, + const struct lmv_stripe_md *lsm, ldlm_blocking_callback cb_blocking, int extra_lock_flags); diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 9461cd3..9a53b0a 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -3240,27 +3240,25 @@ static int lmv_quotacheck(struct obd_device *unused, struct obd_export *exp, return rc; } -static int -lmv_update_lsm_md(struct obd_export *exp, struct lmv_stripe_md *lsm, - struct mdt_body *body, ldlm_blocking_callback cb_blocking) +static int lmv_merge_attr(struct obd_export *exp, + const struct lmv_stripe_md *lsm, + struct cl_attr *attr, + ldlm_blocking_callback cb_blocking) { - return lmv_revalidate_slaves(exp, body, lsm, cb_blocking, 0); -} + int rc, i; -static int -lmv_merge_attr(struct obd_export *exp, const struct lmv_stripe_md *lsm, - struct cl_attr *attr) -{ - int i; + rc = lmv_revalidate_slaves(exp, lsm, cb_blocking, 0); + if (rc < 0) + return rc; for (i = 0; i < lsm->lsm_md_stripe_count; i++) { struct inode *inode = lsm->lsm_md_oinfo[i].lmo_root; - CDEBUG(D_INFO, ""DFID" size %llu, nlink %u, atime %lu ctime %lu, mtime %lu.\n", + CDEBUG(D_INFO, ""DFID" size %llu, blocks %llu nlink %u, atime %lu ctime %lu, mtime %lu.\n", PFID(&lsm->lsm_md_oinfo[i].lmo_fid), - i_size_read(inode), inode->i_nlink, - LTIME_S(inode->i_atime), LTIME_S(inode->i_ctime), - LTIME_S(inode->i_mtime)); + i_size_read(inode), (unsigned long long)inode->i_blocks, + inode->i_nlink, LTIME_S(inode->i_atime), + LTIME_S(inode->i_ctime), LTIME_S(inode->i_mtime)); /* for slave stripe, it needs to subtract nlink for . and .. */ if (i) @@ -3269,6 +3267,7 @@ lmv_merge_attr(struct obd_export *exp, const struct lmv_stripe_md *lsm, attr->cat_nlink = inode->i_nlink; attr->cat_size += i_size_read(inode); + attr->cat_blocks += inode->i_blocks; if (attr->cat_atime < LTIME_S(inode->i_atime)) attr->cat_atime = LTIME_S(inode->i_atime); @@ -3326,7 +3325,6 @@ static struct md_ops lmv_md_ops = { .lock_match = lmv_lock_match, .get_lustre_md = lmv_get_lustre_md, .free_lustre_md = lmv_free_lustre_md, - .update_lsm_md = lmv_update_lsm_md, .merge_attr = lmv_merge_attr, .set_open_replay_data = lmv_set_open_replay_data, .clear_open_replay_data = lmv_clear_open_replay_data, -- cgit v0.10.2 From a09be8445c75f54fbbe11e1ce9b3af2d60f346f7 Mon Sep 17 00:00:00 2001 From: Johann Lombardi <johann.lombardi@intel.com> Date: Sun, 18 Sep 2016 16:38:47 -0400 Subject: staging: lustre: grant: quiet message on grant waiting timeout Use at_max in osc_enter_cache() to bound how long we wait for grant space before switching to synchronous I/Os. Do not print a message on the console when the timeout is hit since such long wait can be legitimate with flaky network (i.e. BRW is resent multiple times). Signed-off-by: Johann Lombardi <johann.lombardi@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5521 Reviewed-on: http://review.whamcloud.com/12146 Reviewed-by: Niu Yawei <yawei.niu@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index adc3b6d..4bbe219 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -1536,7 +1536,7 @@ static int osc_enter_cache_try(struct client_obd *cli, { int rc; - OSC_DUMP_GRANT(D_CACHE, cli, "need:%d.\n", bytes); + OSC_DUMP_GRANT(D_CACHE, cli, "need:%d\n", bytes); rc = osc_reserve_grant(cli, bytes); if (rc < 0) @@ -1581,11 +1581,13 @@ static int osc_enter_cache(const struct lu_env *env, struct client_obd *cli, struct osc_object *osc = oap->oap_obj; struct lov_oinfo *loi = osc->oo_oinfo; struct osc_cache_waiter ocw; - struct l_wait_info lwi = LWI_TIMEOUT_INTR(cfs_time_seconds(600), NULL, - LWI_ON_SIGNAL_NOOP, NULL); + struct l_wait_info lwi; int rc = -EDQUOT; - OSC_DUMP_GRANT(D_CACHE, cli, "need:%d.\n", bytes); + lwi = LWI_TIMEOUT_INTR(cfs_time_seconds(AT_OFF ? obd_timeout : at_max), + NULL, LWI_ON_SIGNAL_NOOP, NULL); + + OSC_DUMP_GRANT(D_CACHE, cli, "need:%d\n", bytes); spin_lock(&cli->cl_loi_list_lock); @@ -1595,12 +1597,14 @@ static int osc_enter_cache(const struct lu_env *env, struct client_obd *cli, if (OBD_FAIL_CHECK(OBD_FAIL_OSC_NO_GRANT) || !cli->cl_dirty_max_pages || cli->cl_ar.ar_force_sync || loi->loi_ar.ar_force_sync) { + OSC_DUMP_GRANT(D_CACHE, cli, "forced sync i/o\n"); rc = -EDQUOT; goto out; } /* Hopefully normal case - cache space and write credits available */ if (osc_enter_cache_try(cli, oap, bytes, 0)) { + OSC_DUMP_GRANT(D_CACHE, cli, "granted from cache\n"); rc = 0; goto out; } @@ -1629,32 +1633,49 @@ static int osc_enter_cache(const struct lu_env *env, struct client_obd *cli, spin_lock(&cli->cl_loi_list_lock); - /* l_wait_event is interrupted by signal, or timed out */ if (rc < 0) { - if (rc == -ETIMEDOUT) { - OSC_DUMP_GRANT(D_ERROR, cli, - "try to reserve %d.\n", bytes); - osc_extent_tree_dump(D_ERROR, osc); - rc = -EDQUOT; - } - + /* l_wait_event is interrupted by signal, or timed out */ list_del_init(&ocw.ocw_entry); - goto out; + break; } - LASSERT(list_empty(&ocw.ocw_entry)); rc = ocw.ocw_rc; if (rc != -EDQUOT) - goto out; + break; if (osc_enter_cache_try(cli, oap, bytes, 0)) { rc = 0; - goto out; + break; } } + + switch (rc) { + case 0: + OSC_DUMP_GRANT(D_CACHE, cli, "finally got grant space\n"); + break; + case -ETIMEDOUT: + OSC_DUMP_GRANT(D_CACHE, cli, + "timeout, fall back to sync i/o\n"); + osc_extent_tree_dump(D_CACHE, osc); + /* fall back to synchronous I/O */ + rc = -EDQUOT; + break; + case -EINTR: + /* Ensures restartability - LU-3581 */ + OSC_DUMP_GRANT(D_CACHE, cli, "interrupted\n"); + rc = -ERESTARTSYS; + break; + case -EDQUOT: + OSC_DUMP_GRANT(D_CACHE, cli, + "no grant space, fall back to sync i/o\n"); + break; + default: + CDEBUG(D_CACHE, "%s: event for cache space @ %p never arrived due to %d, fall back to sync i/o\n", + cli->cl_import->imp_obd->obd_name, &ocw, rc); + break; + } out: spin_unlock(&cli->cl_loi_list_lock); - OSC_DUMP_GRANT(D_CACHE, cli, "returned %d.\n", rc); return rc; } @@ -1679,10 +1700,8 @@ void osc_wake_cache_waiters(struct client_obd *cli) goto wakeup; } - ocw->ocw_rc = 0; - if (!osc_enter_cache_try(cli, ocw->ocw_oap, ocw->ocw_grant, 0)) - ocw->ocw_rc = -EDQUOT; - + if (osc_enter_cache_try(cli, ocw->ocw_oap, ocw->ocw_grant, 0)) + ocw->ocw_rc = 0; wakeup: CDEBUG(D_CACHE, "wake up %p for oap %p, avail grant %ld, %d\n", ocw, ocw->ocw_oap, cli->cl_avail_grant, ocw->ocw_rc); -- cgit v0.10.2 From b5d1b04e09d598a2f90d7b673b1caa2e174c6c8c Mon Sep 17 00:00:00 2001 From: frank zago <fzago@cray.com> Date: Sun, 18 Sep 2016 16:38:48 -0400 Subject: staging: lustre: misc: remove unnecessary EXPORT_SYMBOL A lot of symbols don't need to be exported at all because they are only used in the module they belong to. Signed-off-by: frank zago <fzago@cray.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5829 Reviewed-on: http://review.whamcloud.com/13321 Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: Dmitry Eremin <dmitry.eremin@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/fid/fid_lib.c b/drivers/staging/lustre/lustre/fid/fid_lib.c index 99ae7eb..4e49cb3 100644 --- a/drivers/staging/lustre/lustre/fid/fid_lib.c +++ b/drivers/staging/lustre/lustre/fid/fid_lib.c @@ -63,14 +63,12 @@ const struct lu_seq_range LUSTRE_SEQ_SPACE_RANGE = { FID_SEQ_NORMAL, (__u64)~0ULL }; -EXPORT_SYMBOL(LUSTRE_SEQ_SPACE_RANGE); /* Zero range, used for init and other purposes. */ const struct lu_seq_range LUSTRE_SEQ_ZERO_RANGE = { 0, 0 }; -EXPORT_SYMBOL(LUSTRE_SEQ_ZERO_RANGE); /* Lustre Big Fs Lock fid. */ const struct lu_fid LUSTRE_BFL_FID = { .f_seq = FID_SEQ_SPECIAL, diff --git a/drivers/staging/lustre/lustre/fld/fld_request.c b/drivers/staging/lustre/lustre/fld/fld_request.c index ed7962e..0de72b7 100644 --- a/drivers/staging/lustre/lustre/fld/fld_request.c +++ b/drivers/staging/lustre/lustre/fld/fld_request.c @@ -219,7 +219,6 @@ int fld_client_del_target(struct lu_client_fld *fld, __u64 idx) spin_unlock(&fld->lcf_lock); return -ENOENT; } -EXPORT_SYMBOL(fld_client_del_target); static struct dentry *fld_debugfs_dir; @@ -454,7 +453,6 @@ void fld_client_flush(struct lu_client_fld *fld) { fld_cache_flush(fld->lcf_cache); } -EXPORT_SYMBOL(fld_client_flush); static int __init fld_init(void) { diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 9a53b0a..7c24da3 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -2802,7 +2802,6 @@ lmv_pack_md(union lmv_mds_md **lmmp, const struct lmv_stripe_md *lsm, return lmm_size; } -EXPORT_SYMBOL(lmv_pack_md); static int lmv_unpack_md_v1(struct obd_export *exp, struct lmv_stripe_md *lsm, const struct lmv_mds_md_v1 *lmm1) diff --git a/drivers/staging/lustre/lustre/lov/lov_dev.c b/drivers/staging/lustre/lustre/lov/lov_dev.c index b1f260d..056ae2e 100644 --- a/drivers/staging/lustre/lustre/lov/lov_dev.c +++ b/drivers/staging/lustre/lustre/lov/lov_dev.c @@ -516,6 +516,5 @@ struct lu_device_type lov_device_type = { .ldt_ops = &lov_device_type_ops, .ldt_ctx_tags = LCT_CL_THREAD }; -EXPORT_SYMBOL(lov_device_type); /** @} lov */ -- cgit v0.10.2 From fee58df692924d3dbefe45c55dab9b03dde54074 Mon Sep 17 00:00:00 2001 From: frank zago <fzago@cray.com> Date: Sun, 18 Sep 2016 16:38:49 -0400 Subject: staging: lustre: obdclass: remove unnecessary EXPORT_SYMBOL A lot of symbols don't need to be exported at all because they are only used in the module they belong to. Signed-off-by: frank zago <fzago@cray.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5829 Reviewed-on: http://review.whamcloud.com/13323 Reviewed-by: Jian Yu <jian.yu@intel.com> Reviewed-by: Dmitry Eremin <dmitry.eremin@intel.com> Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/obdclass/cl_io.c b/drivers/staging/lustre/lustre/obdclass/cl_io.c index 7894cf9..bc4b7b6 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_io.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_io.c @@ -73,7 +73,6 @@ int cl_io_is_going(const struct lu_env *env) { return cl_env_info(env)->clt_current_io != NULL; } -EXPORT_SYMBOL(cl_io_is_going); /** * cl_io invariant that holds at all times when exported cl_io_*() functions diff --git a/drivers/staging/lustre/lustre/obdclass/cl_page.c b/drivers/staging/lustre/lustre/obdclass/cl_page.c index 18784a8..63973ba 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_page.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_page.c @@ -170,7 +170,6 @@ struct cl_page *cl_page_alloc(const struct lu_env *env, } return page; } -EXPORT_SYMBOL(cl_page_alloc); /** * Returns a cl_page with index \a idx at the object \a o, and associated with @@ -1006,7 +1005,6 @@ int cl_page_cancel(const struct lu_env *env, struct cl_page *page) (const struct lu_env *, const struct cl_page_slice *)); } -EXPORT_SYMBOL(cl_page_cancel); /** * Converts a byte offset within object \a obj into a page index. diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c index 4c30d6bc..76e1ee8 100644 --- a/drivers/staging/lustre/lustre/obdclass/class_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c @@ -44,7 +44,6 @@ #include "llog_internal.h" struct obd_device *obd_devs[MAX_OBD_DEVICES]; -EXPORT_SYMBOL(obd_devs); struct list_head obd_types; DEFINE_RWLOCK(obd_dev_lock); @@ -79,8 +78,6 @@ atomic_long_t obd_dirty_transit_pages; EXPORT_SYMBOL(obd_dirty_transit_pages); char obd_jobid_var[JOBSTATS_JOBID_VAR_MAX_LEN + 1] = JOBSTATS_DISABLE; -EXPORT_SYMBOL(obd_jobid_var); - char obd_jobid_node[LUSTRE_JOBID_SIZE + 1]; /* Get jobid of current process from stored variable or calculate diff --git a/drivers/staging/lustre/lustre/obdclass/genops.c b/drivers/staging/lustre/lustre/obdclass/genops.c index 0bc623e..cf8bb2a 100644 --- a/drivers/staging/lustre/lustre/obdclass/genops.c +++ b/drivers/staging/lustre/lustre/obdclass/genops.c @@ -133,7 +133,6 @@ void class_put_type(struct obd_type *type) module_put(type->typ_dt_ops->owner); spin_unlock(&type->obd_type_lock); } -EXPORT_SYMBOL(class_put_type); #define CLASS_MAX_NAME 1024 @@ -391,7 +390,6 @@ int class_name2dev(const char *name) return -1; } -EXPORT_SYMBOL(class_name2dev); struct obd_device *class_name2obd(const char *name) { @@ -421,7 +419,6 @@ int class_uuid2dev(struct obd_uuid *uuid) return -1; } -EXPORT_SYMBOL(class_uuid2dev); /** * Get obd device from ::obd_devs[] @@ -450,7 +447,6 @@ struct obd_device *class_num2obd(int num) return obd; } -EXPORT_SYMBOL(class_num2obd); /* Search for a client OBD connected to tgt_uuid. If grp_uuid is * specified, then only the client with that uuid is returned, @@ -817,7 +813,6 @@ void class_unlink_export(struct obd_export *exp) spin_unlock(&exp->exp_obd->obd_dev_lock); class_export_put(exp); } -EXPORT_SYMBOL(class_unlink_export); /* Import management functions */ static void class_import_destroy(struct obd_import *imp) @@ -973,7 +968,6 @@ void __class_export_add_lock_ref(struct obd_export *exp, struct ldlm_lock *lock) lock, exp, lock->l_exp_refs_nr); spin_unlock(&exp->exp_locks_list_guard); } -EXPORT_SYMBOL(__class_export_add_lock_ref); void __class_export_del_lock_ref(struct obd_export *exp, struct ldlm_lock *lock) { @@ -991,7 +985,6 @@ void __class_export_del_lock_ref(struct obd_export *exp, struct ldlm_lock *lock) lock, exp, lock->l_exp_refs_nr); spin_unlock(&exp->exp_locks_list_guard); } -EXPORT_SYMBOL(__class_export_del_lock_ref); #endif /* A connection defines an export context in which preallocation can @@ -1100,7 +1093,6 @@ EXPORT_SYMBOL(class_fail_export); #if LUSTRE_TRACKS_LOCK_EXP_REFS void (*class_export_dump_hook)(struct obd_export *) = NULL; -EXPORT_SYMBOL(class_export_dump_hook); #endif /* Total amount of zombies to be destroyed */ diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c index ae172c4..be09e04 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c @@ -158,7 +158,6 @@ int obd_ioctl_popdata(void __user *arg, void *data, int len) err = copy_to_user(arg, data, len) ? -EFAULT : 0; return err; } -EXPORT_SYMBOL(obd_ioctl_popdata); /* opening /dev/obd */ static int obd_class_open(struct inode *inode, struct file *file) diff --git a/drivers/staging/lustre/lustre/obdclass/llog_obd.c b/drivers/staging/lustre/lustre/obdclass/llog_obd.c index 6ace7e0..a4277d6 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_obd.c @@ -210,7 +210,6 @@ LU_KEY_INIT_FINI(llog, struct llog_thread_info); /* context key: llog_thread_key */ LU_CONTEXT_KEY_DEFINE(llog, LCT_MD_THREAD | LCT_MG_THREAD | LCT_LOCAL); LU_KEY_INIT_GENERIC(llog); -EXPORT_SYMBOL(llog_thread_key); int llog_info_init(void) { diff --git a/drivers/staging/lustre/lustre/obdclass/llog_swab.c b/drivers/staging/lustre/lustre/obdclass/llog_swab.c index 21ab90c..8c4c1b3 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_swab.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_swab.c @@ -347,7 +347,6 @@ void lustre_swab_lustre_cfg(struct lustre_cfg *lcfg) print_lustre_cfg(lcfg); } -EXPORT_SYMBOL(lustre_swab_lustre_cfg); /* used only for compatibility with old on-disk cfg_marker data */ struct cfg_marker32 { @@ -407,4 +406,3 @@ void lustre_swab_cfg_marker(struct cfg_marker *marker, int swab, int size) __swab64s(&marker->cm_canceltime); } } -EXPORT_SYMBOL(lustre_swab_cfg_marker); diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c index be6b6af..852a5ac 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c @@ -621,7 +621,6 @@ void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx, lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags); } -EXPORT_SYMBOL(lprocfs_stats_collect); /** * Append a space separated list of current set flags to str. @@ -1049,7 +1048,6 @@ int lprocfs_stats_alloc_one(struct lprocfs_stats *stats, unsigned int cpuid) } return rc; } -EXPORT_SYMBOL(lprocfs_stats_alloc_one); struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num, enum lprocfs_stats_flags flags) diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c index 3f1fb28..054e567 100644 --- a/drivers/staging/lustre/lustre/obdclass/lu_object.c +++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c @@ -1300,7 +1300,6 @@ void lu_stack_fini(const struct lu_env *env, struct lu_device *top) } } } -EXPORT_SYMBOL(lu_stack_fini); enum { /** @@ -1522,14 +1521,12 @@ void lu_context_key_quiesce(struct lu_context_key *key) ++key_set_version; } } -EXPORT_SYMBOL(lu_context_key_quiesce); void lu_context_key_revive(struct lu_context_key *key) { key->lct_tags &= ~LCT_QUIESCENT; ++key_set_version; } -EXPORT_SYMBOL(lu_context_key_revive); static void keys_fini(struct lu_context *ctx) { @@ -1688,7 +1685,6 @@ int lu_context_refill(struct lu_context *ctx) { return likely(ctx->lc_version == key_set_version) ? 0 : keys_fill(ctx); } -EXPORT_SYMBOL(lu_context_refill); /** * lu_ctx_tags/lu_ses_tags will be updated if there are new types of diff --git a/drivers/staging/lustre/lustre/obdclass/lustre_peer.c b/drivers/staging/lustre/lustre/obdclass/lustre_peer.c index 5974a9b..ffa740a 100644 --- a/drivers/staging/lustre/lustre/obdclass/lustre_peer.c +++ b/drivers/staging/lustre/lustre/obdclass/lustre_peer.c @@ -139,7 +139,6 @@ int class_add_uuid(const char *uuid, __u64 nid) } return 0; } -EXPORT_SYMBOL(class_add_uuid); /* Delete the nids for one uuid if specified, otherwise delete all */ int class_del_uuid(const char *uuid) -- cgit v0.10.2 From 8ef9dbe4b0ce3d9cae87251184096bfdaff75c9e Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Sun, 18 Sep 2016 16:38:50 -0400 Subject: staging: lustre: llite: lock the inode to be migrated Because the inode and its connected dentries will be cleared out of the cache after migration, the inode needs to be locked during the migration. Signed-off-by: wang di <di.wang@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4712 Reviewed-on: http://review.whamcloud.com/9689 Reviewed-by: Lai Siyao <lai.siyao@intel.com> Reviewed-by: Fan Yong <fan.yong@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index d8761b8..5d4d17f 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -2802,11 +2802,15 @@ int ll_migrate(struct inode *parent, struct file *file, int mdtidx, qstr.name = name; qstr.len = namelen; dchild = d_lookup(file_dentry(file), &qstr); - if (dchild && dchild->d_inode) { + if (dchild) { op_data->op_fid3 = *ll_inode2fid(dchild->d_inode); if (dchild->d_inode) { child_inode = igrab(dchild->d_inode); - ll_invalidate_aliases(child_inode); + if (child_inode) { + inode_lock(child_inode); + op_data->op_fid3 = *ll_inode2fid(child_inode); + ll_invalidate_aliases(child_inode); + } } dput(dchild); } else { @@ -2847,6 +2851,7 @@ int ll_migrate(struct inode *parent, struct file *file, int mdtidx, out_free: if (child_inode) { clear_nlink(child_inode); + inode_unlock(child_inode); iput(child_inode); } -- cgit v0.10.2 From e47fad9a7319d6e6a70f7ac4f9f870e65b962c87 Mon Sep 17 00:00:00 2001 From: frank zago <fzago@cray.com> Date: Sun, 18 Sep 2016 16:38:51 -0400 Subject: staging: lustre: ptlrpc: remove unnecessary EXPORT_SYMBOL A lot of symbols don't need to be exported at all because they are only used in the module they belong to. Signed-off-by: frank zago <fzago@cray.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5829 Reviewed-on: http://review.whamcloud.com/12510 Reviewed-by: Dmitry Eremin <dmitry.eremin@intel.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: James Simmons <uja.ornl@gmail.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre_net.h b/drivers/staging/lustre/lustre/include/lustre_net.h index 21e2267..e9aba99 100644 --- a/drivers/staging/lustre/lustre/include/lustre_net.h +++ b/drivers/staging/lustre/lustre/include/lustre_net.h @@ -2408,7 +2408,6 @@ int ptlrpc_send_reply(struct ptlrpc_request *req, int flags); int ptlrpc_reply(struct ptlrpc_request *req); int ptlrpc_send_error(struct ptlrpc_request *req, int difficult); int ptlrpc_error(struct ptlrpc_request *req); -void ptlrpc_resend_req(struct ptlrpc_request *request); int ptlrpc_at_get_net_latency(struct ptlrpc_request *req); int ptl_send_rpc(struct ptlrpc_request *request, int noreply); int ptlrpc_register_rqbd(struct ptlrpc_request_buffer_desc *rqbd); @@ -2428,23 +2427,17 @@ struct ptlrpc_connection *ptlrpc_uuid_to_connection(struct obd_uuid *uuid); int ptlrpc_queue_wait(struct ptlrpc_request *req); int ptlrpc_replay_req(struct ptlrpc_request *req); -int ptlrpc_unregister_reply(struct ptlrpc_request *req, int async); void ptlrpc_abort_inflight(struct obd_import *imp); void ptlrpc_abort_set(struct ptlrpc_request_set *set); struct ptlrpc_request_set *ptlrpc_prep_set(void); struct ptlrpc_request_set *ptlrpc_prep_fcset(int max, set_producer_func func, void *arg); -int ptlrpc_set_next_timeout(struct ptlrpc_request_set *); int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set); int ptlrpc_set_wait(struct ptlrpc_request_set *); -int ptlrpc_expired_set(void *data); -void ptlrpc_interrupted_set(void *data); void ptlrpc_mark_interrupted(struct ptlrpc_request *req); void ptlrpc_set_destroy(struct ptlrpc_request_set *); void ptlrpc_set_add_req(struct ptlrpc_request_set *, struct ptlrpc_request *); -void ptlrpc_set_add_new_req(struct ptlrpcd_ctl *pc, - struct ptlrpc_request *req); void ptlrpc_free_rq_pool(struct ptlrpc_request_pool *pool); int ptlrpc_add_rqs_to_pool(struct ptlrpc_request_pool *pool, int num_rq); diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index f3914cc3..18c7ff7 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -45,6 +45,7 @@ static int ptlrpc_send_new_req(struct ptlrpc_request *req); static int ptlrpcd_check_work(struct ptlrpc_request *req); +static int ptlrpc_unregister_reply(struct ptlrpc_request *request, int async); /** * Initialize passed in client structure \a cl. @@ -89,7 +90,6 @@ struct ptlrpc_connection *ptlrpc_uuid_to_connection(struct obd_uuid *uuid) return c; } -EXPORT_SYMBOL(ptlrpc_uuid_to_connection); /** * Allocate and initialize new bulk descriptor on the sender. @@ -886,7 +886,6 @@ struct ptlrpc_request_set *ptlrpc_prep_fcset(int max, set_producer_func func, return set; } -EXPORT_SYMBOL(ptlrpc_prep_fcset); /** * Wind down and free request set structure previously allocated with @@ -1006,7 +1005,6 @@ void ptlrpc_set_add_new_req(struct ptlrpcd_ctl *pc, wake_up(&pc->pc_partners[i]->pc_set->set_waitq); } } -EXPORT_SYMBOL(ptlrpc_set_add_new_req); /** * Based on the current state of the import, determine if the request @@ -2005,7 +2003,6 @@ int ptlrpc_expired_set(void *data) */ return 1; } -EXPORT_SYMBOL(ptlrpc_expired_set); /** * Sets rq_intr flag in \a req under spinlock. @@ -2022,7 +2019,7 @@ EXPORT_SYMBOL(ptlrpc_mark_interrupted); * Interrupts (sets interrupted flag) all uncompleted requests in * a set \a data. Callback for l_wait_event for interruptible waits. */ -void ptlrpc_interrupted_set(void *data) +static void ptlrpc_interrupted_set(void *data) { struct ptlrpc_request_set *set = data; struct list_head *tmp; @@ -2040,7 +2037,6 @@ void ptlrpc_interrupted_set(void *data) ptlrpc_mark_interrupted(req); } } -EXPORT_SYMBOL(ptlrpc_interrupted_set); /** * Get the smallest timeout in the set; this does NOT set a timeout. @@ -2084,7 +2080,6 @@ int ptlrpc_set_next_timeout(struct ptlrpc_request_set *set) } return timeout; } -EXPORT_SYMBOL(ptlrpc_set_next_timeout); /** * Send all unset request from the set and then wait until all @@ -2335,7 +2330,7 @@ EXPORT_SYMBOL(ptlrpc_req_xid); * The request owner (i.e. the thread doing the I/O) must call... * Returns 0 on success or 1 if unregistering cannot be made. */ -int ptlrpc_unregister_reply(struct ptlrpc_request *request, int async) +static int ptlrpc_unregister_reply(struct ptlrpc_request *request, int async) { int rc; wait_queue_head_t *wq; @@ -2400,7 +2395,6 @@ int ptlrpc_unregister_reply(struct ptlrpc_request *request, int async) } return 0; } -EXPORT_SYMBOL(ptlrpc_unregister_reply); static void ptlrpc_free_request(struct ptlrpc_request *req) { @@ -2555,7 +2549,6 @@ void ptlrpc_resend_req(struct ptlrpc_request *req) ptlrpc_client_wake_req(req); spin_unlock(&req->rq_lock); } -EXPORT_SYMBOL(ptlrpc_resend_req); /** * Grab additional reference on a request \a req @@ -2624,7 +2617,6 @@ void ptlrpc_retain_replayable_request(struct ptlrpc_request *req, list_add(&req->rq_replay_list, &imp->imp_replay_list); } -EXPORT_SYMBOL(ptlrpc_retain_replayable_request); /** * Send request and wait until it completes. @@ -2797,7 +2789,6 @@ int ptlrpc_replay_req(struct ptlrpc_request *req) ptlrpcd_add_req(req); return 0; } -EXPORT_SYMBOL(ptlrpc_replay_req); /** * Aborts all in-flight request on import \a imp sending and delayed lists @@ -2857,7 +2848,6 @@ void ptlrpc_abort_inflight(struct obd_import *imp) spin_unlock(&imp->imp_lock); } -EXPORT_SYMBOL(ptlrpc_abort_inflight); /** * Abort all uncompleted requests in request set \a set @@ -2943,7 +2933,6 @@ __u64 ptlrpc_next_xid(void) return next; } -EXPORT_SYMBOL(ptlrpc_next_xid); /** * Get a glimpse at what next xid value might have been. diff --git a/drivers/staging/lustre/lustre/ptlrpc/connection.c b/drivers/staging/lustre/lustre/ptlrpc/connection.c index 177a379..7b020d6 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/connection.c +++ b/drivers/staging/lustre/lustre/ptlrpc/connection.c @@ -82,7 +82,6 @@ out: libcfs_nid2str(conn->c_peer.nid)); return conn; } -EXPORT_SYMBOL(ptlrpc_connection_get); int ptlrpc_connection_put(struct ptlrpc_connection *conn) { @@ -118,7 +117,6 @@ int ptlrpc_connection_put(struct ptlrpc_connection *conn) return rc; } -EXPORT_SYMBOL(ptlrpc_connection_put); struct ptlrpc_connection * ptlrpc_connection_addref(struct ptlrpc_connection *conn) @@ -130,7 +128,6 @@ ptlrpc_connection_addref(struct ptlrpc_connection *conn) return conn; } -EXPORT_SYMBOL(ptlrpc_connection_addref); int ptlrpc_connection_init(void) { @@ -146,13 +143,11 @@ int ptlrpc_connection_init(void) return 0; } -EXPORT_SYMBOL(ptlrpc_connection_init); void ptlrpc_connection_fini(void) { cfs_hash_putref(conn_hash); } -EXPORT_SYMBOL(ptlrpc_connection_fini); /* * Hash operations for net_peer<->connection diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c index 2e107e8..a23d0a0 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/import.c +++ b/drivers/staging/lustre/lustre/ptlrpc/import.c @@ -425,7 +425,6 @@ void ptlrpc_fail_import(struct obd_import *imp, __u32 conn_cnt) ptlrpc_pinger_force(imp); } } -EXPORT_SYMBOL(ptlrpc_fail_import); int ptlrpc_reconnect_import(struct obd_import *imp) { diff --git a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c index 5bab2487..9c93739 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c +++ b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c @@ -295,7 +295,6 @@ int ptlrpc_unregister_bulk(struct ptlrpc_request *req, int async) } return 0; } -EXPORT_SYMBOL(ptlrpc_unregister_bulk); static void ptlrpc_at_set_reply(struct ptlrpc_request *req, int flags) { @@ -434,7 +433,6 @@ out: ptlrpc_connection_put(conn); return rc; } -EXPORT_SYMBOL(ptlrpc_send_reply); int ptlrpc_reply(struct ptlrpc_request *req) { @@ -442,7 +440,6 @@ int ptlrpc_reply(struct ptlrpc_request *req) return 0; return ptlrpc_send_reply(req, 0); } -EXPORT_SYMBOL(ptlrpc_reply); /** * For request \a req send an error reply back. Create empty @@ -469,13 +466,11 @@ int ptlrpc_send_error(struct ptlrpc_request *req, int may_be_difficult) rc = ptlrpc_send_reply(req, may_be_difficult); return rc; } -EXPORT_SYMBOL(ptlrpc_send_error); int ptlrpc_error(struct ptlrpc_request *req) { return ptlrpc_send_error(req, 0); } -EXPORT_SYMBOL(ptlrpc_error); /** * Send request \a request. diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index a1ea0c2..1349bf6 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -66,7 +66,6 @@ u32 lustre_msg_hdr_size(__u32 magic, u32 count) return 0; } } -EXPORT_SYMBOL(lustre_msg_hdr_size); void ptlrpc_buf_set_swabbed(struct ptlrpc_request *req, const int inout, u32 index) @@ -76,7 +75,6 @@ void ptlrpc_buf_set_swabbed(struct ptlrpc_request *req, const int inout, else lustre_set_rep_swabbed(req, index); } -EXPORT_SYMBOL(ptlrpc_buf_set_swabbed); int ptlrpc_buf_need_swab(struct ptlrpc_request *req, const int inout, u32 index) @@ -88,7 +86,6 @@ int ptlrpc_buf_need_swab(struct ptlrpc_request *req, const int inout, return (ptlrpc_rep_need_swab(req) && !lustre_rep_swabbed(req, index)); } -EXPORT_SYMBOL(ptlrpc_buf_need_swab); /* early reply size */ u32 lustre_msg_early_size(void) @@ -151,7 +148,6 @@ u32 lustre_msg_size(__u32 magic, int count, __u32 *lens) return 0; } } -EXPORT_SYMBOL(lustre_msg_size); /* This is used to determine the size of a buffer that was already packed * and will correctly handle the different message formats. @@ -166,7 +162,6 @@ u32 lustre_packed_msg_size(struct lustre_msg *msg) return 0; } } -EXPORT_SYMBOL(lustre_packed_msg_size); void lustre_init_msg_v2(struct lustre_msg_v2 *msg, int count, __u32 *lens, char **bufs) @@ -227,7 +222,6 @@ int lustre_pack_request(struct ptlrpc_request *req, __u32 magic, int count, /* only use new format, we don't need to be compatible with 1.4 */ return lustre_pack_request_v2(req, count, lens, bufs); } -EXPORT_SYMBOL(lustre_pack_request); #if RS_DEBUG LIST_HEAD(ptlrpc_rs_debug_lru); @@ -369,7 +363,6 @@ int lustre_pack_reply_flags(struct ptlrpc_request *req, int count, __u32 *lens, lustre_msg_size(req->rq_reqmsg->lm_magic, count, lens)); return rc; } -EXPORT_SYMBOL(lustre_pack_reply_flags); int lustre_pack_reply(struct ptlrpc_request *req, int count, __u32 *lens, char **bufs) @@ -491,7 +484,6 @@ void lustre_free_reply_state(struct ptlrpc_reply_state *rs) sptlrpc_svc_free_rs(rs); } -EXPORT_SYMBOL(lustre_free_reply_state); static int lustre_unpack_msg_v2(struct lustre_msg_v2 *m, int len) { @@ -579,7 +571,6 @@ int ptlrpc_unpack_req_msg(struct ptlrpc_request *req, int len) } return rc; } -EXPORT_SYMBOL(ptlrpc_unpack_req_msg); int ptlrpc_unpack_rep_msg(struct ptlrpc_request *req, int len) { @@ -592,7 +583,6 @@ int ptlrpc_unpack_rep_msg(struct ptlrpc_request *req, int len) } return rc; } -EXPORT_SYMBOL(ptlrpc_unpack_rep_msg); static inline int lustre_unpack_ptlrpc_body_v2(struct ptlrpc_request *req, const int inout, int offset) @@ -685,7 +675,6 @@ u32 lustre_msg_bufcount(struct lustre_msg *m) return 0; } } -EXPORT_SYMBOL(lustre_msg_bufcount); char *lustre_msg_string(struct lustre_msg *m, u32 index, u32 max_len) { @@ -729,7 +718,6 @@ char *lustre_msg_string(struct lustre_msg *m, u32 index, u32 max_len) return str; } -EXPORT_SYMBOL(lustre_msg_string); /* Wrap up the normal fixed length cases */ static inline void *__lustre_swab_buf(struct lustre_msg *msg, u32 index, @@ -832,7 +820,6 @@ void lustre_msg_set_flags(struct lustre_msg *msg, u32 flags) LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic); } } -EXPORT_SYMBOL(lustre_msg_set_flags); void lustre_msg_clear_flags(struct lustre_msg *msg, u32 flags) { @@ -866,7 +853,6 @@ __u32 lustre_msg_get_op_flags(struct lustre_msg *msg) return 0; } } -EXPORT_SYMBOL(lustre_msg_get_op_flags); void lustre_msg_add_op_flags(struct lustre_msg *msg, u32 flags) { @@ -901,7 +887,6 @@ struct lustre_handle *lustre_msg_get_handle(struct lustre_msg *msg) return NULL; } } -EXPORT_SYMBOL(lustre_msg_get_handle); __u32 lustre_msg_get_type(struct lustre_msg *msg) { @@ -936,7 +921,6 @@ void lustre_msg_add_version(struct lustre_msg *msg, u32 version) LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic); } } -EXPORT_SYMBOL(lustre_msg_add_version); __u32 lustre_msg_get_opc(struct lustre_msg *msg) { @@ -1053,7 +1037,6 @@ __u64 lustre_msg_get_slv(struct lustre_msg *msg) return -EINVAL; } } -EXPORT_SYMBOL(lustre_msg_get_slv); void lustre_msg_set_slv(struct lustre_msg *msg, __u64 slv) { @@ -1073,7 +1056,6 @@ void lustre_msg_set_slv(struct lustre_msg *msg, __u64 slv) return; } } -EXPORT_SYMBOL(lustre_msg_set_slv); __u32 lustre_msg_get_limit(struct lustre_msg *msg) { @@ -1092,7 +1074,6 @@ __u32 lustre_msg_get_limit(struct lustre_msg *msg) return -EINVAL; } } -EXPORT_SYMBOL(lustre_msg_get_limit); void lustre_msg_set_limit(struct lustre_msg *msg, __u64 limit) { @@ -1112,7 +1093,6 @@ void lustre_msg_set_limit(struct lustre_msg *msg, __u64 limit) return; } } -EXPORT_SYMBOL(lustre_msg_set_limit); __u32 lustre_msg_get_conn_cnt(struct lustre_msg *msg) { @@ -1143,7 +1123,6 @@ __u32 lustre_msg_get_magic(struct lustre_msg *msg) return 0; } } -EXPORT_SYMBOL(lustre_msg_get_magic); __u32 lustre_msg_get_timeout(struct lustre_msg *msg) { @@ -1226,7 +1205,6 @@ void lustre_msg_set_handle(struct lustre_msg *msg, struct lustre_handle *handle) LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic); } } -EXPORT_SYMBOL(lustre_msg_set_handle); void lustre_msg_set_type(struct lustre_msg *msg, __u32 type) { @@ -1242,7 +1220,6 @@ void lustre_msg_set_type(struct lustre_msg *msg, __u32 type) LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic); } } -EXPORT_SYMBOL(lustre_msg_set_type); void lustre_msg_set_opc(struct lustre_msg *msg, __u32 opc) { @@ -1258,7 +1235,6 @@ void lustre_msg_set_opc(struct lustre_msg *msg, __u32 opc) LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic); } } -EXPORT_SYMBOL(lustre_msg_set_opc); void lustre_msg_set_versions(struct lustre_msg *msg, __u64 *versions) { @@ -1325,7 +1301,6 @@ void lustre_msg_set_conn_cnt(struct lustre_msg *msg, __u32 conn_cnt) LASSERTF(0, "incorrect message magic: %08x\n", msg->lm_magic); } } -EXPORT_SYMBOL(lustre_msg_set_conn_cnt); void lustre_msg_set_timeout(struct lustre_msg *msg, __u32 timeout) { @@ -1490,7 +1465,6 @@ void lustre_swab_ptlrpc_body(struct ptlrpc_body *b) */ CLASSERT(offsetof(typeof(*b), pb_jobid) != 0); } -EXPORT_SYMBOL(lustre_swab_ptlrpc_body); void lustre_swab_connect(struct obd_connect_data *ocd) { @@ -1590,7 +1564,6 @@ void lustre_swab_obd_statfs(struct obd_statfs *os) CLASSERT(offsetof(typeof(*os), os_spare8) != 0); CLASSERT(offsetof(typeof(*os), os_spare9) != 0); } -EXPORT_SYMBOL(lustre_swab_obd_statfs); void lustre_swab_obd_ioobj(struct obd_ioobj *ioo) { @@ -1598,7 +1571,6 @@ void lustre_swab_obd_ioobj(struct obd_ioobj *ioo) __swab32s(&ioo->ioo_max_brw); __swab32s(&ioo->ioo_bufcnt); } -EXPORT_SYMBOL(lustre_swab_obd_ioobj); void lustre_swab_niobuf_remote(struct niobuf_remote *nbr) { @@ -1606,25 +1578,21 @@ void lustre_swab_niobuf_remote(struct niobuf_remote *nbr) __swab32s(&nbr->rnb_len); __swab32s(&nbr->rnb_flags); } -EXPORT_SYMBOL(lustre_swab_niobuf_remote); void lustre_swab_ost_body(struct ost_body *b) { lustre_swab_obdo(&b->oa); } -EXPORT_SYMBOL(lustre_swab_ost_body); void lustre_swab_ost_last_id(u64 *id) { __swab64s(id); } -EXPORT_SYMBOL(lustre_swab_ost_last_id); void lustre_swab_generic_32s(__u32 *val) { __swab32s(val); } -EXPORT_SYMBOL(lustre_swab_generic_32s); void lustre_swab_gl_desc(union ldlm_gl_desc *desc) { @@ -1703,7 +1671,6 @@ void lustre_swab_mdt_body(struct mdt_body *b) __swab32s(&b->mbo_gid_h); CLASSERT(offsetof(typeof(*b), mbo_padding_5) != 0); } -EXPORT_SYMBOL(lustre_swab_mdt_body); void lustre_swab_mdt_ioepoch(struct mdt_ioepoch *b) { @@ -1712,7 +1679,6 @@ void lustre_swab_mdt_ioepoch(struct mdt_ioepoch *b) __swab32s(&b->flags); CLASSERT(offsetof(typeof(*b), padding) != 0); } -EXPORT_SYMBOL(lustre_swab_mdt_ioepoch); void lustre_swab_mgs_target_info(struct mgs_target_info *mti) { @@ -1728,7 +1694,6 @@ void lustre_swab_mgs_target_info(struct mgs_target_info *mti) for (i = 0; i < MTI_NIDS_MAX; i++) __swab64s(&mti->mti_nids[i]); } -EXPORT_SYMBOL(lustre_swab_mgs_target_info); void lustre_swab_mgs_nidtbl_entry(struct mgs_nidtbl_entry *entry) { @@ -1759,14 +1724,12 @@ void lustre_swab_mgs_config_body(struct mgs_config_body *body) __swab32s(&body->mcb_units); __swab16s(&body->mcb_type); } -EXPORT_SYMBOL(lustre_swab_mgs_config_body); void lustre_swab_mgs_config_res(struct mgs_config_res *body) { __swab64s(&body->mcr_offset); __swab64s(&body->mcr_size); } -EXPORT_SYMBOL(lustre_swab_mgs_config_res); static void lustre_swab_obd_dqinfo(struct obd_dqinfo *i) { @@ -1799,7 +1762,6 @@ void lustre_swab_obd_quotactl(struct obd_quotactl *q) lustre_swab_obd_dqinfo(&q->qc_dqinfo); lustre_swab_obd_dqblk(&q->qc_dqblk); } -EXPORT_SYMBOL(lustre_swab_obd_quotactl); void lustre_swab_fid2path(struct getinfo_fid2path *gf) { @@ -1833,7 +1795,6 @@ void lustre_swab_fiemap(struct ll_user_fiemap *fiemap) for (i = 0; i < fiemap->fm_mapped_extents; i++) lustre_swab_fiemap_extent(&fiemap->fm_extents[i]); } -EXPORT_SYMBOL(lustre_swab_fiemap); void lustre_swab_mdt_rec_reint (struct mdt_rec_reint *rr) { @@ -1862,7 +1823,6 @@ void lustre_swab_mdt_rec_reint (struct mdt_rec_reint *rr) CLASSERT(offsetof(typeof(*rr), rr_padding_4) != 0); }; -EXPORT_SYMBOL(lustre_swab_mdt_rec_reint); void lustre_swab_lov_desc(struct lov_desc *ld) { @@ -1901,7 +1861,6 @@ void lustre_swab_lmv_mds_md(union lmv_mds_md *lmm) break; } } -EXPORT_SYMBOL(lustre_swab_lmv_mds_md); void lustre_swab_lmv_user_md(struct lmv_user_md *lum) { @@ -1955,7 +1914,6 @@ void lustre_swab_lov_mds_md(struct lov_mds_md *lmm) __swab16s(&lmm->lmm_stripe_count); __swab16s(&lmm->lmm_layout_gen); } -EXPORT_SYMBOL(lustre_swab_lov_mds_md); void lustre_swab_lov_user_md_objects(struct lov_user_ost_data *lod, int stripe_count) @@ -1995,7 +1953,6 @@ void lustre_swab_ldlm_intent(struct ldlm_intent *i) { __swab64s(&i->opc); } -EXPORT_SYMBOL(lustre_swab_ldlm_intent); static void lustre_swab_ldlm_resource_desc(struct ldlm_resource_desc *r) { @@ -2019,7 +1976,6 @@ void lustre_swab_ldlm_request(struct ldlm_request *rq) __swab32s(&rq->lock_count); /* lock_handle[] opaque */ } -EXPORT_SYMBOL(lustre_swab_ldlm_request); void lustre_swab_ldlm_reply(struct ldlm_reply *r) { @@ -2030,7 +1986,6 @@ void lustre_swab_ldlm_reply(struct ldlm_reply *r) __swab64s(&r->lock_policy_res1); __swab64s(&r->lock_policy_res2); } -EXPORT_SYMBOL(lustre_swab_ldlm_reply); /* Dump functions */ void dump_ioo(struct obd_ioobj *ioo) @@ -2040,14 +1995,12 @@ void dump_ioo(struct obd_ioobj *ioo) POSTID(&ioo->ioo_oid), ioo->ioo_max_brw, ioo->ioo_bufcnt); } -EXPORT_SYMBOL(dump_ioo); void dump_rniobuf(struct niobuf_remote *nb) { CDEBUG(D_RPCTRACE, "niobuf_remote: offset=%llu, len=%d, flags=%x\n", nb->rnb_offset, nb->rnb_len, nb->rnb_flags); } -EXPORT_SYMBOL(dump_rniobuf); static void dump_obdo(struct obdo *oa) { @@ -2115,13 +2068,11 @@ void dump_ost_body(struct ost_body *ob) { dump_obdo(&ob->oa); } -EXPORT_SYMBOL(dump_ost_body); void dump_rcs(__u32 *rc) { CDEBUG(D_RPCTRACE, "rmf_rcs: %d\n", *rc); } -EXPORT_SYMBOL(dump_rcs); static inline int req_ptlrpc_body_swabbed(struct ptlrpc_request *req) { @@ -2206,14 +2157,12 @@ void lustre_swab_lustre_capa(struct lustre_capa *c) __swab32s(&c->lc_timeout); __swab32s(&c->lc_expiry); } -EXPORT_SYMBOL(lustre_swab_lustre_capa); void lustre_swab_hsm_user_state(struct hsm_user_state *state) { __swab32s(&state->hus_states); __swab32s(&state->hus_archive_id); } -EXPORT_SYMBOL(lustre_swab_hsm_user_state); void lustre_swab_hsm_state_set(struct hsm_state_set *hss) { @@ -2236,14 +2185,12 @@ void lustre_swab_hsm_current_action(struct hsm_current_action *action) __swab32s(&action->hca_action); lustre_swab_hsm_extent(&action->hca_location); } -EXPORT_SYMBOL(lustre_swab_hsm_current_action); void lustre_swab_hsm_user_item(struct hsm_user_item *hui) { lustre_swab_lu_fid(&hui->hui_fid); lustre_swab_hsm_extent(&hui->hui_extent); } -EXPORT_SYMBOL(lustre_swab_hsm_user_item); void lustre_swab_layout_intent(struct layout_intent *li) { @@ -2252,7 +2199,6 @@ void lustre_swab_layout_intent(struct layout_intent *li) __swab64s(&li->li_start); __swab64s(&li->li_end); } -EXPORT_SYMBOL(lustre_swab_layout_intent); void lustre_swab_hsm_progress_kernel(struct hsm_progress_kernel *hpk) { @@ -2263,7 +2209,6 @@ void lustre_swab_hsm_progress_kernel(struct hsm_progress_kernel *hpk) __swab16s(&hpk->hpk_flags); __swab16s(&hpk->hpk_errval); } -EXPORT_SYMBOL(lustre_swab_hsm_progress_kernel); void lustre_swab_hsm_request(struct hsm_request *hr) { @@ -2273,7 +2218,6 @@ void lustre_swab_hsm_request(struct hsm_request *hr) __swab32s(&hr->hr_itemcount); __swab32s(&hr->hr_data_len); } -EXPORT_SYMBOL(lustre_swab_hsm_request); void lustre_swab_swap_layouts(struct mdc_swap_layouts *msl) { @@ -2286,4 +2230,3 @@ void lustre_swab_close_data(struct close_data *cd) lustre_swab_lu_fid(&cd->cd_fid); __swab64s(&cd->cd_data_version); } -EXPORT_SYMBOL(lustre_swab_close_data); diff --git a/drivers/staging/lustre/lustre/ptlrpc/pinger.c b/drivers/staging/lustre/lustre/ptlrpc/pinger.c index c0529d8..5504fc2 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pinger.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pinger.c @@ -340,7 +340,6 @@ void ptlrpc_pinger_sending_on_import(struct obd_import *imp) { ptlrpc_update_next_ping(imp, 0); } -EXPORT_SYMBOL(ptlrpc_pinger_sending_on_import); void ptlrpc_pinger_commit_expected(struct obd_import *imp) { diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h index b420aa8..f14d193 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h @@ -62,6 +62,11 @@ void ptlrpc_request_cache_fini(void); struct ptlrpc_request *ptlrpc_request_cache_alloc(gfp_t flags); void ptlrpc_request_cache_free(struct ptlrpc_request *req); void ptlrpc_init_xid(void); +void ptlrpc_set_add_new_req(struct ptlrpcd_ctl *pc, + struct ptlrpc_request *req); +int ptlrpc_expired_set(void *data); +int ptlrpc_set_next_timeout(struct ptlrpc_request_set *); +void ptlrpc_resend_req(struct ptlrpc_request *request); /* events.c */ int ptlrpc_init_portals(void); diff --git a/drivers/staging/lustre/lustre/ptlrpc/recover.c b/drivers/staging/lustre/lustre/ptlrpc/recover.c index 718b3a8..405faf0 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/recover.c +++ b/drivers/staging/lustre/lustre/ptlrpc/recover.c @@ -201,7 +201,6 @@ int ptlrpc_resend(struct obd_import *imp) return 0; } -EXPORT_SYMBOL(ptlrpc_resend); /** * Go through all requests in delayed list and wake their threads @@ -221,7 +220,6 @@ void ptlrpc_wake_delayed(struct obd_import *imp) } spin_unlock(&imp->imp_lock); } -EXPORT_SYMBOL(ptlrpc_wake_delayed); void ptlrpc_request_handle_notconn(struct ptlrpc_request *failed_req) { diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c index 6adf274..b2cc5ea 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c @@ -348,7 +348,6 @@ void sptlrpc_enc_pool_put_pages(struct ptlrpc_bulk_desc *desc) kfree(desc->bd_enc_iov); desc->bd_enc_iov = NULL; } -EXPORT_SYMBOL(sptlrpc_enc_pool_put_pages); static inline void enc_pools_alloc(void) { @@ -457,13 +456,11 @@ const char *sptlrpc_get_hash_name(__u8 hash_alg) { return cfs_crypto_hash_name(cfs_hash_alg_id[hash_alg]); } -EXPORT_SYMBOL(sptlrpc_get_hash_name); __u8 sptlrpc_get_hash_alg(const char *algname) { return cfs_crypto_hash_alg(algname); } -EXPORT_SYMBOL(sptlrpc_get_hash_alg); int bulk_sec_desc_unpack(struct lustre_msg *msg, int offset, int swabbed) { @@ -544,4 +541,3 @@ int sptlrpc_get_bulk_checksum(struct ptlrpc_bulk_desc *desc, __u8 alg, return err; } -EXPORT_SYMBOL(sptlrpc_get_bulk_checksum); diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_config.c b/drivers/staging/lustre/lustre/ptlrpc/sec_config.c index c140354..2181a85 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_config.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_config.c @@ -58,7 +58,6 @@ enum lustre_sec_part sptlrpc_target_sec_part(struct obd_device *obd) CERROR("unknown target %p(%s)\n", obd, type); return LUSTRE_SP_ANY; } -EXPORT_SYMBOL(sptlrpc_target_sec_part); /**************************************** * user supplied flavor string parsing * diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c b/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c index f79a889..8ffd000 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c @@ -71,7 +71,6 @@ void sptlrpc_gc_add_sec(struct ptlrpc_sec *sec) CDEBUG(D_SEC, "added sec %p(%s)\n", sec, sec->ps_policy->sp_name); } -EXPORT_SYMBOL(sptlrpc_gc_add_sec); void sptlrpc_gc_del_sec(struct ptlrpc_sec *sec) { @@ -95,7 +94,6 @@ void sptlrpc_gc_del_sec(struct ptlrpc_sec *sec) CDEBUG(D_SEC, "del sec %p(%s)\n", sec, sec->ps_policy->sp_name); } -EXPORT_SYMBOL(sptlrpc_gc_del_sec); static void sec_process_ctx_list(void) { diff --git a/drivers/staging/lustre/lustre/ptlrpc/service.c b/drivers/staging/lustre/lustre/ptlrpc/service.c index a2fce66..3edc9b1 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/service.c +++ b/drivers/staging/lustre/lustre/ptlrpc/service.c @@ -2407,7 +2407,6 @@ int ptlrpc_start_threads(struct ptlrpc_service *svc) ptlrpc_stop_all_threads(svc); return rc; } -EXPORT_SYMBOL(ptlrpc_start_threads); int ptlrpc_start_thread(struct ptlrpc_service_part *svcpt, int wait) { -- cgit v0.10.2 From bbc222b113fb5bed066a9bcc4ce7c1a92528a47e Mon Sep 17 00:00:00 2001 From: James Simmons <jsimmons@infradead.org> Date: Sun, 18 Sep 2016 16:38:52 -0400 Subject: staging: lustre: obd: use proper flags for call_usermodehelper When a parameter is permanently changed on the MGS the MGS send a changelog packet to the proper nodes that are affected by the change. Once the nodes receive the change they then call the userland utility lctl to change its local value. When calling a userland application from the kernel you specify a flag to control the interaction with the application. Originally by default the flag was set to 0 which is UMH_NO_WAIT which meant lctl was being called asynchronously. In older kernels this was fine since UHM_NO_WAIT and UHM_WAIT_PROC had nearly the same logic. This changed with newer kernels which broke updating our parameters. Plus doing a UHM_NO_WAIT doesn't report back a error if something goes wrong with lctl. The fix is to set the flag to UHM_WAIT_PROC so kernel space waits until lctl has finished and we get a proper error code if something does go wrong with lctl. Signed-off-by: James Simmons <uja.ornl@gmail.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6063 Reviewed-on: http://review.whamcloud.com/13677 Reviewed-by: Bob Glossman <bob.glossman@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/obdclass/obd_config.c b/drivers/staging/lustre/lustre/obdclass/obd_config.c index fddfc9c..bbed1b7 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_config.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_config.c @@ -738,7 +738,7 @@ static int process_param2_config(struct lustre_cfg *lcfg) } start = ktime_get(); - rc = call_usermodehelper(argv[0], argv, NULL, 1); + rc = call_usermodehelper(argv[0], argv, NULL, UMH_WAIT_PROC); end = ktime_get(); if (rc < 0) { -- cgit v0.10.2 From be2479818ff227fbb6800935909b65e06159735c Mon Sep 17 00:00:00 2001 From: Mikhail Pershin <mike.pershin@intel.com> Date: Sun, 18 Sep 2016 16:38:53 -0400 Subject: staging: lustre: ptlrpc: prevent request timeout grow due to recovery Patch fixes the issue seen on the client with growing request timeout which occurred after the server side patch landed for LU-5079. While commit itself is correct, it reveals another issue. If request is being processed for a long time on server then client adaptive timeouts will adapt to that after receiving reply and new requests will have bigger timeout. Another problem is that server AT history is corrupted by recovery request processing time which not pure service time but includes also waiting time for clients to recover. Patch prevents the AT stats update from early replies on client and from recovering requests processing time on server. The ptlrpc_at_recv_early_reply() still updates the current request timeout as asked by server, but don't include this into AT stats. The real reply will bring that data from server after all. Signed-off-by: Mikhail Pershin <mike.pershin@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6084 Reviewed-on: http://review.whamcloud.com/13520 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Jian Yu <jian.yu@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index 18c7ff7..8c51d51 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -364,23 +364,27 @@ static int ptlrpc_at_recv_early_reply(struct ptlrpc_request *req) } rc = unpack_reply(early_req); - if (rc == 0) { - /* Expecting to increase the service time estimate here */ - ptlrpc_at_adj_service(req, - lustre_msg_get_timeout(early_req->rq_repmsg)); - ptlrpc_at_adj_net_latency(req, - lustre_msg_get_service_time(early_req->rq_repmsg)); - } - - sptlrpc_cli_finish_early_reply(early_req); - - if (rc != 0) { + if (rc) { + sptlrpc_cli_finish_early_reply(early_req); spin_lock(&req->rq_lock); return rc; } - /* Adjust the local timeout for this req */ - ptlrpc_at_set_req_timeout(req); + /* + * Use new timeout value just to adjust the local value for this + * request, don't include it into at_history. It is unclear yet why + * service time increased and should it be counted or skipped, e.g. + * that can be recovery case or some error or server, the real reply + * will add all new data if it is worth to add. + */ + req->rq_timeout = lustre_msg_get_timeout(early_req->rq_repmsg); + lustre_msg_set_timeout(req->rq_reqmsg, req->rq_timeout); + + /* Network latency can be adjusted, it is pure network delays */ + ptlrpc_at_adj_net_latency(req, + lustre_msg_get_service_time(early_req->rq_repmsg)); + + sptlrpc_cli_finish_early_reply(early_req); spin_lock(&req->rq_lock); olddl = req->rq_deadline; diff --git a/drivers/staging/lustre/lustre/ptlrpc/service.c b/drivers/staging/lustre/lustre/ptlrpc/service.c index 3edc9b1..72f3930 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/service.c +++ b/drivers/staging/lustre/lustre/ptlrpc/service.c @@ -1015,6 +1015,7 @@ static int ptlrpc_at_send_early_reply(struct ptlrpc_request *req) struct ptlrpc_request *reqcopy; struct lustre_msg *reqmsg; long olddl = req->rq_deadline - ktime_get_real_seconds(); + time64_t newdl; int rc; /* deadline is when the client expects us to reply, margin is the @@ -1052,16 +1053,14 @@ static int ptlrpc_at_send_early_reply(struct ptlrpc_request *req) */ at_measured(&svcpt->scp_at_estimate, at_extra + ktime_get_real_seconds() - req->rq_arrival_time.tv_sec); + newdl = req->rq_arrival_time.tv_sec + at_get(&svcpt->scp_at_estimate); /* Check to see if we've actually increased the deadline - * we may be past adaptive_max */ - if (req->rq_deadline >= req->rq_arrival_time.tv_sec + - at_get(&svcpt->scp_at_estimate)) { + if (req->rq_deadline >= newdl) { DEBUG_REQ(D_WARNING, req, "Couldn't add any time (%ld/%lld), not sending early reply\n", - olddl, req->rq_arrival_time.tv_sec + - at_get(&svcpt->scp_at_estimate) - - ktime_get_real_seconds()); + olddl, newdl - ktime_get_real_seconds()); return -ETIMEDOUT; } @@ -1117,8 +1116,7 @@ static int ptlrpc_at_send_early_reply(struct ptlrpc_request *req) if (!rc) { /* Adjust our own deadline to what we told the client */ - req->rq_deadline = req->rq_arrival_time.tv_sec + - at_get(&svcpt->scp_at_estimate); + req->rq_deadline = newdl; req->rq_early_count++; /* number sent, server side */ } else { DEBUG_REQ(D_ERROR, req, "Early reply send failed %d", rc); -- cgit v0.10.2 From d81e90094ac77fa86288cad306ea25af82365b9f Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Sun, 18 Sep 2016 16:38:54 -0400 Subject: staging: lustre: mdt: add indexing option to default dir stripe Add indexing option to default dirstripe EA. If MDT find out the client send the create req to the wrong MDT because of default stripeEA, it will return -EREMOTE, then client will retrieve default stripeEA through xattr cache, and re-create the object. Also merged patch for LU-6341 to resolve the following problem. Use ll_dir_getstripe to get default stripeEA in ll_new_node(), Because ll_getxattr_common requires admin rights for retrieving default LMVEA (because of trusted- prefix), which might cause mkdir (from normal user) failure. If parent does not have default stripeEA, then child should always be in the same MDT for mkdir. Otherwise MDT should return -EREMOTE, then client will refresh the default stripe index, and recreate the object. Signed-off-by: wang di <di.wang@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5523 Reviewed-on: http://review.whamcloud.com/13360 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6341 Reviewed-on: http://review.whamcloud.com/13990 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Lai Siyao <lai.siyao@intel.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: James Simmons <uja.ornl@yahoo.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index c6937b2..ef11534 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -773,6 +773,9 @@ struct md_op_data { /* File object data version for HSM release, on client */ __u64 op_data_version; struct lustre_handle op_lease_handle; + + /* default stripe offset */ + __u32 op_default_stripe_offset; }; struct md_callback { diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 51bf071..70ca3e1 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -191,6 +191,13 @@ struct ll_inode_info { unsigned int lli_sa_generation; /* directory stripe information */ struct lmv_stripe_md *lli_lsm_md; + /* default directory stripe offset. This is extracted + * from the "dmv" xattr in order to decide which MDT to + * create a subdirectory on. The MDS itself fetches + * "dmv" and gets the rest of the default layout itself + * (count, hash, etc). + */ + __u32 lli_def_stripe_offset; }; /* for non-directory */ diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 15b487b..7e618c5 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -802,6 +802,7 @@ void ll_lli_init(struct ll_inode_info *lli) spin_lock_init(&lli->lli_sa_lock); lli->lli_opendir_pid = 0; lli->lli_sa_enabled = 0; + lli->lli_def_stripe_offset = -1; } else { mutex_init(&lli->lli_size_mutex); lli->lli_symlink_name = NULL; @@ -2342,8 +2343,12 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, ll_i2gids(op_data->op_suppgids, i1, i2); op_data->op_fid1 = *ll_inode2fid(i1); - if (S_ISDIR(i1->i_mode)) + op_data->op_default_stripe_offset = -1; + if (S_ISDIR(i1->i_mode)) { op_data->op_mea1 = ll_i2info(i1)->lli_lsm_md; + op_data->op_default_stripe_offset = + ll_i2info(i1)->lli_def_stripe_offset; + } if (i2) { op_data->op_fid2 = *ll_inode2fid(i2); diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index d55b14b..dfa36d3 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -204,6 +204,8 @@ int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, } if (bits & MDS_INODELOCK_XATTR) { + if (S_ISDIR(inode->i_mode)) + ll_i2info(inode)->lli_def_stripe_offset = -1; ll_xattr_cache_destroy(inode); bits &= ~MDS_INODELOCK_XATTR; } @@ -833,7 +835,7 @@ static int ll_new_node(struct inode *dir, struct dentry *dentry, if (unlikely(tgt)) tgt_len = strlen(tgt) + 1; - +again: op_data = ll_prep_md_op_data(NULL, dir, NULL, dentry->d_name.name, dentry->d_name.len, @@ -848,9 +850,45 @@ static int ll_new_node(struct inode *dir, struct dentry *dentry, from_kgid(&init_user_ns, current_fsgid()), cfs_curproc_cap_pack(), rdev, &request); ll_finish_md_op_data(op_data); - if (err) + if (err < 0 && err != -EREMOTE) goto err_exit; + /* + * If the client doesn't know where to create a subdirectory (or + * in case of a race that sends the RPC to the wrong MDS), the + * MDS will return -EREMOTE and the client will fetch the layout + * of the directory, then create the directory on the right MDT. + */ + if (unlikely(err == -EREMOTE)) { + struct ll_inode_info *lli = ll_i2info(dir); + struct lmv_user_md *lum; + int lumsize, err2; + + ptlrpc_req_finished(request); + request = NULL; + + err2 = ll_dir_getstripe(dir, (void **)&lum, &lumsize, &request, + OBD_MD_DEFAULT_MEA); + if (!err2) { + /* Update stripe_offset and retry */ + lli->lli_def_stripe_offset = lum->lum_stripe_offset; + } else if (err2 == -ENODATA && + lli->lli_def_stripe_offset != -1) { + /* + * If there are no default stripe EA on the MDT, but the + * client has default stripe, then it probably means + * default stripe EA has just been deleted. + */ + lli->lli_def_stripe_offset = -1; + } else { + goto err_exit; + } + + ptlrpc_req_finished(request); + request = NULL; + goto again; + } + ll_update_times(request, dir); err = ll_prep_inode(&inode, request, dir->i_sb, NULL); @@ -859,7 +897,8 @@ static int ll_new_node(struct inode *dir, struct dentry *dentry, d_instantiate(dentry, inode); err_exit: - ptlrpc_req_finished(request); + if (request) + ptlrpc_req_finished(request); return err; } diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 7c24da3..13d6f55 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -1162,6 +1162,11 @@ static int lmv_placement_policy(struct obd_device *obd, return 0; } + if (op_data->op_default_stripe_offset != -1) { + *mds = op_data->op_default_stripe_offset; + return 0; + } + /** * If stripe_offset is provided during setdirstripe * (setdirstripe -i xx), xx MDS will be chosen. -- cgit v0.10.2 From 60b65afb700626f0fe43589138c8ca9ac460d634 Mon Sep 17 00:00:00 2001 From: Ned Bass <bass6@llnl.gov> Date: Sun, 18 Sep 2016 16:38:55 -0400 Subject: staging: lustre: llite: make default_easize writeable in /sysfs Allow default_easize to be tuned via /sysfs. A system administrator might want this if a rare access to widely striped files drives up the value on a filesystem where narrowly striped files are the more common case. In practice, however, this is wanted primarily to facilitate a test case for LU-5549. - Plumb the necessary interfaces through the LMV and MDC layers to expose write access to this value by higher layers. - Add block comments to modified functions. Signed-off-by: Ned Bass <bass6@llnl.gov> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5549 Reviewed-on: http://review.whamcloud.com/13112 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Lai Siyao <lai.siyao@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 70ca3e1..3e98bd6 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -839,6 +839,7 @@ int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, int ll_obd_statfs(struct inode *inode, void __user *arg); int ll_get_max_mdsize(struct ll_sb_info *sbi, int *max_mdsize); int ll_get_default_mdsize(struct ll_sb_info *sbi, int *default_mdsize); +int ll_set_default_mdsize(struct ll_sb_info *sbi, int default_mdsize); int ll_process_config(struct lustre_cfg *lcfg); enum { diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 7e618c5..ab00409 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -582,6 +582,17 @@ int ll_get_max_mdsize(struct ll_sb_info *sbi, int *lmmsize) return rc; } +/** + * Get the value of the default_easize parameter. + * + * \see client_obd::cl_default_mds_easize + * + * \param[in] sbi superblock info for this filesystem + * \param[out] lmmsize pointer to storage location for value + * + * \retval 0 on success + * \retval negative negated errno on failure + */ int ll_get_default_mdsize(struct ll_sb_info *sbi, int *lmmsize) { int size, rc; @@ -595,6 +606,28 @@ int ll_get_default_mdsize(struct ll_sb_info *sbi, int *lmmsize) return rc; } +/** + * Set the default_easize parameter to the given value. + * + * \see client_obd::cl_default_mds_easize + * + * \param[in] sbi superblock info for this filesystem + * \param[in] lmmsize the size to set + * + * \retval 0 on success + * \retval negative negated errno on failure + */ +int ll_set_default_mdsize(struct ll_sb_info *sbi, int lmmsize) +{ + if (lmmsize < sizeof(struct lov_mds_md) || lmmsize > PAGE_SIZE) + return -EINVAL; + + return obd_set_info_async(NULL, sbi->ll_md_exp, + sizeof(KEY_DEFAULT_EASIZE), + KEY_DEFAULT_EASIZE, + sizeof(int), &lmmsize, NULL); +} + static void client_common_put_super(struct super_block *sb) { struct ll_sb_info *sbi = ll_s2sbi(sb); diff --git a/drivers/staging/lustre/lustre/llite/lproc_llite.c b/drivers/staging/lustre/lustre/llite/lproc_llite.c index 188fd37..6eae605 100644 --- a/drivers/staging/lustre/lustre/llite/lproc_llite.c +++ b/drivers/staging/lustre/lustre/llite/lproc_llite.c @@ -744,6 +744,18 @@ static ssize_t max_easize_show(struct kobject *kobj, } LUSTRE_RO_ATTR(max_easize); +/** + * Get default_easize. + * + * \see client_obd::cl_default_mds_easize + * + * \param[in] kobj kernel object for sysfs tree + * \param[in] attr attribute of this kernel object + * \param[in] buf buffer to write data into + * + * \retval positive \a count on success + * \retval negative negated errno on failure + */ static ssize_t default_easize_show(struct kobject *kobj, struct attribute *attr, char *buf) @@ -759,7 +771,44 @@ static ssize_t default_easize_show(struct kobject *kobj, return sprintf(buf, "%u\n", ealen); } -LUSTRE_RO_ATTR(default_easize); + +/** + * Set default_easize. + * + * Range checking on the passed value is handled by + * ll_set_default_mdsize(). + * + * \see client_obd::cl_default_mds_easize + * + * \param[in] kobj kernel object for sysfs tree + * \param[in] attr attribute of this kernel object + * \param[in] buffer string passed from user space + * \param[in] count \a buffer length + * + * \retval positive \a count on success + * \retval negative negated errno on failure + */ +static ssize_t default_easize_store(struct kobject *kobj, + struct attribute *attr, + const char *buffer, + size_t count) +{ + struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info, + ll_kobj); + unsigned long val; + int rc; + + rc = kstrtoul(buffer, 10, &val); + if (rc) + return rc; + + rc = ll_set_default_mdsize(sbi, val); + if (rc) + return rc; + + return count; +} +LUSTRE_RW_ATTR(default_easize); static int ll_sbi_flags_seq_show(struct seq_file *m, void *v) { diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 13d6f55..a0792d4 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -2623,6 +2623,22 @@ static int lmv_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage) return 0; } +/** + * Get by key a value associated with a LMV device. + * + * Dispatch request to lower-layer devices as needed. + * + * \param[in] env execution environment for this thread + * \param[in] exp export for the LMV device + * \param[in] keylen length of key identifier + * \param[in] key identifier of key to get value for + * \param[in] vallen size of \a val + * \param[out] val pointer to storage location for value + * \param[in] lsm optional striping metadata of object + * + * \retval 0 on success + * \retval negative negated errno on failure + */ static int lmv_get_info(const struct lu_env *env, struct obd_export *exp, __u32 keylen, void *key, __u32 *vallen, void *val, struct lov_stripe_md *lsm) @@ -2686,6 +2702,22 @@ static int lmv_get_info(const struct lu_env *env, struct obd_export *exp, return -EINVAL; } +/** + * Asynchronously set by key a value associated with a LMV device. + * + * Dispatch request to lower-layer devices as needed. + * + * \param[in] env execution environment for this thread + * \param[in] exp export for the LMV device + * \param[in] keylen length of key identifier + * \param[in] key identifier of key to store value for + * \param[in] vallen size of value to store + * \param[in] val pointer to data to be stored + * \param[in] set optional list of related ptlrpc requests + * + * \retval 0 on success + * \retval negative negated errno on failure + */ static int lmv_set_info_async(const struct lu_env *env, struct obd_export *exp, u32 keylen, void *key, u32 vallen, void *val, struct ptlrpc_request_set *set) @@ -2703,7 +2735,8 @@ static int lmv_set_info_async(const struct lu_env *env, struct obd_export *exp, } lmv = &obd->u.lmv; - if (KEY_IS(KEY_READ_ONLY) || KEY_IS(KEY_FLUSH_CTX)) { + if (KEY_IS(KEY_READ_ONLY) || KEY_IS(KEY_FLUSH_CTX) || + KEY_IS(KEY_DEFAULT_EASIZE)) { int i, err = 0; for (i = 0; i < lmv->desc.ld_tgt_count; i++) { diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 9de2e43..f56ea64 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -2516,6 +2516,12 @@ static int mdc_set_info_async(const struct lu_env *env, rc = mdc_hsm_copytool_send(vallen, val); return rc; } + if (KEY_IS(KEY_DEFAULT_EASIZE)) { + u32 *default_easize = val; + + exp->exp_obd->u.cli.cl_default_mds_easize = *default_easize; + return 0; + } CERROR("Unknown key %s\n", (char *)key); return -EINVAL; -- cgit v0.10.2 From 8ed62e91c4adf3f37c665d1d892aa17dc7150ab7 Mon Sep 17 00:00:00 2001 From: Ned Bass <bass6@llnl.gov> Date: Sun, 18 Sep 2016 16:38:56 -0400 Subject: staging: lustre: mdc: cl_default_mds_easize not refreshed The client_obd::cl_default_mds_easize field should track the largest observed EA size advertised by the MDT, subject to a reasonable upper bound. The MDC uses cl_default_mds_easize to calculate the initial size of request buffers. The default value should be small enough to avoid wasted memory and excessive use of vmalloc(), yet large enough to accommodate the common use case. In the current code, the default value is only updated if client_obd::cl_max_mds_easize is strictly less than mdt_body::mbo_max_mdsize. This condition is almost never met, because client_obd::cl_max_mds_easize is computed at client mount-time based on the number of OSTs in the filesystem, so the MDT won't ever observe and advertise an EA size larger than that. As a result, client_obd::cl_default_mds_easize indefinitely retains its initial value, which is computed at client mount-time based on the filesystem's default stripe width. Any getattr() requests for widely striped files will consequently allocate a request buffer that is too small, forcing reallocations on both the client and server side. To avoid this, update client_obd::cl_default_mds_easize independently of the value of client_obd::cl_max_mds_easize. In addition, this patch includes these changes: - Add comments to the client_obd structure to clarify what the cl_{default,max}_mds_{cookie,ea}size values mean. - Prevent mdc_get_info() from storing uninitialized data in client_obd::cl_max_mds_cookiesize. - Use 4096 as an upper bound for the default values. The former bound of PAGE_CACHE_SIZE is too large on 64k-page platforms (i.e. PPC), so it fails to prevent the vmalloc() spinlock contention described in LU-3338. The new value was chosen to be large enough to accommodate common use cases while staying well below the 16k threshold at which allocations start using vmalloc(). Signed-off-by: Ned Bass <bass6@llnl.gov> Signed-off-by: Kyle Blatter <kyleblatter@llnl.gov> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5549 Reviewed-on: http://review.whamcloud.com/11614 Reviewed-by: Lai Siyao <lai.siyao@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre_mdc.h b/drivers/staging/lustre/lustre/include/lustre_mdc.h index 9549fb4..8fc2d3f 100644 --- a/drivers/staging/lustre/lustre/include/lustre_mdc.h +++ b/drivers/staging/lustre/lustre/include/lustre_mdc.h @@ -156,26 +156,41 @@ static inline void mdc_put_rpc_lock(struct mdc_rpc_lock *lck, mutex_unlock(&lck->rpcl_mutex); } -/* Update the maximum observed easize and cookiesize. The default easize - * and cookiesize is initialized to the minimum value but allowed to grow - * up to a single page in size if required to handle the common case. +/** + * Update the maximum possible easize and cookiesize. + * + * The values are learned from ptlrpc replies sent by the MDT. The + * default easize and cookiesize is initialized to the minimum value but + * allowed to grow up to a single page in size if required to handle the + * common case. + * + * \see client_obd::cl_default_mds_easize and + * client_obd::cl_default_mds_cookiesize + * + * \param[in] exp export for MDC device + * \param[in] body body of ptlrpc reply from MDT + * */ static inline void mdc_update_max_ea_from_body(struct obd_export *exp, struct mdt_body *body) { if (body->mbo_valid & OBD_MD_FLMODEASIZE) { struct client_obd *cli = &exp->exp_obd->u.cli; + u32 def_cookiesize, def_easize; - if (cli->cl_max_mds_easize < body->mbo_max_mdsize) { + if (cli->cl_max_mds_easize < body->mbo_max_mdsize) cli->cl_max_mds_easize = body->mbo_max_mdsize; - cli->cl_default_mds_easize = - min_t(__u32, body->mbo_max_mdsize, PAGE_SIZE); - } - if (cli->cl_max_mds_cookiesize < body->mbo_max_cookiesize) { + + def_easize = min_t(__u32, body->mbo_max_mdsize, + OBD_MAX_DEFAULT_EA_SIZE); + cli->cl_default_mds_easize = def_easize; + + if (cli->cl_max_mds_cookiesize < body->mbo_max_cookiesize) cli->cl_max_mds_cookiesize = body->mbo_max_cookiesize; - cli->cl_default_mds_cookiesize = - min_t(__u32, body->mbo_max_cookiesize, PAGE_SIZE); - } + + def_cookiesize = min_t(__u32, body->mbo_max_cookiesize, + OBD_MAX_DEFAULT_COOKIE_SIZE); + cli->cl_default_mds_cookiesize = def_cookiesize; } } diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index ef11534..f6fc4dd 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -196,6 +196,16 @@ enum obd_cl_sem_lock_class { OBD_CLI_SEM_MDCOSC, }; +/* + * Limit reply buffer size for striping data to one x86_64 page. This + * value is chosen to fit the striping data for common use cases while + * staying well below the limit at which the buffer must be backed by + * vmalloc(). Excessive use of vmalloc() may cause spinlock contention + * on the MDS. + */ +#define OBD_MAX_DEFAULT_EA_SIZE 4096 +#define OBD_MAX_DEFAULT_COOKIE_SIZE 4096 + struct mdc_rpc_lock; struct obd_import; struct client_obd { @@ -203,12 +213,39 @@ struct client_obd { struct obd_uuid cl_target_uuid; struct obd_import *cl_import; /* ptlrpc connection state */ size_t cl_conn_count; - /* max_mds_easize is purely a performance thing so we don't have to - * call obd_size_diskmd() all the time. + /* + * Cache maximum and default values for easize and cookiesize. This is + * strictly a performance optimization to minimize calls to + * obd_size_diskmd(). The default values are used to calculate the + * initial size of a request buffer. The ptlrpc layer will resize the + * buffer as needed to accommodate a larger reply from the + * server. The default values should be small enough to avoid wasted + * memory and excessive use of vmalloc(), yet large enough to avoid + * reallocating the buffer in the common use case. + */ + /* + * Default EA size for striping attributes. It is initialized at + * mount-time based on the default stripe width of the filesystem, + * then it tracks the largest observed EA size advertised by + * the MDT, up to a maximum value of OBD_MAX_DEFAULT_EA_SIZE. */ u32 cl_default_mds_easize; + /* Maximum possible EA size computed at mount-time based on + * the number of OSTs in the filesystem. May be increased at + * run-time if a larger observed size is advertised by the MDT. + */ u32 cl_max_mds_easize; + /* Default cookie size for llog cookies (see struct llog_cookie). It is + * initialized to zero at mount-time, then it tracks the largest + * observed cookie size advertised by the MDT, up to a maximum value of + * OBD_MAX_DEFAULT_COOKIE_SIZE. Note that llog_cookies are not + * used by clients communicating with MDS versions 2.4.0 and later. + */ u32 cl_default_mds_cookiesize; + /* Maximum possible cookie size computed at mount-time based on + * the number of OSTs in the filesystem. May be increased at + * run-time if a larger observed size is advertised by the MDT. + */ u32 cl_max_mds_cookiesize; enum lustre_sec_part cl_sp_me; diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index ab00409..6bb41b0 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -619,7 +619,8 @@ int ll_get_default_mdsize(struct ll_sb_info *sbi, int *lmmsize) */ int ll_set_default_mdsize(struct ll_sb_info *sbi, int lmmsize) { - if (lmmsize < sizeof(struct lov_mds_md) || lmmsize > PAGE_SIZE) + if (lmmsize < sizeof(struct lov_mds_md) || + lmmsize > OBD_MAX_DEFAULT_EA_SIZE) return -EINVAL; return obd_set_info_async(NULL, sbi->ll_md_exp, -- cgit v0.10.2 From a1194ad691043fa5632f756c80a6bbafdb0f4dcd Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Sun, 18 Sep 2016 16:38:57 -0400 Subject: staging: lustre: lmv: fix parent FID for migration If the migrating directory is under striped directory, it needs to set right stripe FID for its parent. Signed-off-by: wang di <di.wang@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6263 Reviewed-on: http://review.whamcloud.com/13817 Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: Fan Yong <fan.yong@intel.com> Reviewed-by: Lai Siyao <lai.siyao@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index a0792d4..dad572eb 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -1579,6 +1579,8 @@ lmv_locate_target_for_name(struct lmv_obd *lmv, struct lmv_stripe_md *lsm, struct lmv_tgt_desc *tgt; if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_BAD_NAME_HASH)) { + if (cfs_fail_val >= lsm->lsm_md_stripe_count) + return ERR_PTR(-EBADF); oinfo = &lsm->lsm_md_oinfo[cfs_fail_val]; } else { oinfo = lsm_name_to_stripe_info(lsm, name, namelen); @@ -1586,11 +1588,15 @@ lmv_locate_target_for_name(struct lmv_obd *lmv, struct lmv_stripe_md *lsm, return ERR_CAST(oinfo); } - *fid = oinfo->lmo_fid; - *mds = oinfo->lmo_mds; - tgt = lmv_get_target(lmv, *mds, NULL); + if (fid) + *fid = oinfo->lmo_fid; + if (mds) + *mds = oinfo->lmo_mds; + + tgt = lmv_get_target(lmv, oinfo->lmo_mds, NULL); - CDEBUG(D_INFO, "locate on mds %u "DFID"\n", *mds, PFID(fid)); + CDEBUG(D_INFO, "locate on mds %u " DFID "\n", oinfo->lmo_mds, + PFID(&oinfo->lmo_fid)); return tgt; } @@ -1953,10 +1959,24 @@ static int lmv_rename(struct obd_export *exp, struct md_op_data *op_data, if (op_data->op_cli_flags & CLI_MIGRATE) { LASSERTF(fid_is_sane(&op_data->op_fid3), "invalid FID "DFID"\n", PFID(&op_data->op_fid3)); + + if (op_data->op_mea1) { + struct lmv_stripe_md *lsm = op_data->op_mea1; + struct lmv_tgt_desc *tmp; + + /* Fix the parent fid for striped dir */ + tmp = lmv_locate_target_for_name(lmv, lsm, old, + oldlen, + &op_data->op_fid1, + NULL); + if (IS_ERR(tmp)) + return PTR_ERR(tmp); + } + rc = lmv_fid_alloc(NULL, exp, &op_data->op_fid2, op_data); if (rc) return rc; - src_tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid3); + src_tgt = lmv_find_target(lmv, &op_data->op_fid3); } else { if (op_data->op_mea1) { struct lmv_stripe_md *lsm = op_data->op_mea1; -- cgit v0.10.2 From f2d928f933ce1b1803dac12f1bc8117b8f7563a9 Mon Sep 17 00:00:00 2001 From: Quentin Bouget <quentin.bouget.ocre@cea.fr> Date: Sun, 18 Sep 2016 16:38:58 -0400 Subject: staging: lustre: lnet: potential deadlock in lnet Fixes potential deadlock in LNetMDAttach Signed-off-by: Quentin Bouget <quentin.bouget.ocre@cea.fr> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-8249 Reviewed-on: http://review.whamcloud.com/20676 Reviewed-by: Doug Oucharek <doug.s.oucharek@intel.com> Reviewed-by: James Simmons <uja.ornl@yahoo.com> Reviewed-by: Henri Doreau <henri.doreau@cea.fr> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lnet/lnet/lib-md.c b/drivers/staging/lustre/lnet/lnet/lib-md.c index e0b2f16..eab53cd 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-md.c +++ b/drivers/staging/lustre/lnet/lnet/lib-md.c @@ -292,11 +292,12 @@ LNetMDAttach(lnet_handle_me_t meh, lnet_md_t umd, return -ENOMEM; rc = lnet_md_build(md, &umd, unlink); + if (rc) + goto out_free; + cpt = lnet_cpt_of_cookie(meh.cookie); lnet_res_lock(cpt); - if (rc) - goto failed; me = lnet_handle2me(&meh); if (!me) @@ -307,7 +308,7 @@ LNetMDAttach(lnet_handle_me_t meh, lnet_md_t umd, rc = lnet_md_link(md, umd.eq_handle, cpt); if (rc) - goto failed; + goto out_unlock; /* * attach this MD to portal of ME and check if it matches any @@ -324,10 +325,10 @@ LNetMDAttach(lnet_handle_me_t meh, lnet_md_t umd, return 0; - failed: - lnet_md_free(md); - +out_unlock: lnet_res_unlock(cpt); +out_free: + lnet_md_free(md); return rc; } EXPORT_SYMBOL(LNetMDAttach); @@ -370,24 +371,25 @@ LNetMDBind(lnet_md_t umd, lnet_unlink_t unlink, lnet_handle_md_t *handle) return -ENOMEM; rc = lnet_md_build(md, &umd, unlink); + if (rc) + goto out_free; cpt = lnet_res_lock_current(); - if (rc) - goto failed; rc = lnet_md_link(md, umd.eq_handle, cpt); if (rc) - goto failed; + goto out_unlock; lnet_md2handle(handle, md); lnet_res_unlock(cpt); return 0; - failed: +out_unlock: + lnet_res_unlock(cpt); +out_free: lnet_md_free(md); - lnet_res_unlock(cpt); return rc; } EXPORT_SYMBOL(LNetMDBind); -- cgit v0.10.2 From 4c6722fbc187e64288796d216e4685bb3b27c3f2 Mon Sep 17 00:00:00 2001 From: Sebastien Buisson <sbuisson@ddn.com> Date: Sun, 18 Sep 2016 16:38:59 -0400 Subject: staging: lustre: lnet: check if ni is in current net namespace Add new 'ni_net_ns' field to struct lnet_ni to hold a reference to original net namespace in which ni is created. In LNetDist(), check if ni was created in same net namespace as current's one. If not, assign order above 0xffff0000, to make this ni not a priority. Signed-off-by: Sebastien Buisson <sbuisson@ddn.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-7845 Reviewed-on: http://review.whamcloud.com/21884 Reviewed-by: Olaf Weber <olaf@sgi.com> Reviewed-by: Doug Oucharek <doug.s.oucharek@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/include/linux/lnet/lib-types.h b/drivers/staging/lustre/include/linux/lnet/lib-types.h index 640ff72..b84a5bb 100644 --- a/drivers/staging/lustre/include/linux/lnet/lib-types.h +++ b/drivers/staging/lustre/include/linux/lnet/lib-types.h @@ -275,6 +275,8 @@ typedef struct lnet_ni { struct lnet_ioctl_config_lnd_tunables *ni_lnd_tunables; /* equivalent interfaces to use */ char *ni_interfaces[LNET_MAX_INTERFACES]; + /* original net namespace */ + struct net *ni_net_ns; } lnet_ni_t; #define LNET_PROTO_PING_MATCHBITS 0x8000000000000000LL diff --git a/drivers/staging/lustre/lnet/lnet/config.c b/drivers/staging/lustre/lnet/lnet/config.c index a72afdf..9e2183f 100644 --- a/drivers/staging/lustre/lnet/lnet/config.c +++ b/drivers/staging/lustre/lnet/lnet/config.c @@ -31,6 +31,8 @@ */ #define DEBUG_SUBSYSTEM S_LNET +#include <linux/nsproxy.h> +#include <net/net_namespace.h> #include "../../include/linux/lnet/lib-lnet.h" struct lnet_text_buf { /* tmp struct for parsing routes */ @@ -110,6 +112,11 @@ lnet_ni_free(struct lnet_ni *ni) LIBCFS_FREE(ni->ni_interfaces[i], strlen(ni->ni_interfaces[i]) + 1); } + + /* release reference to net namespace */ + if (ni->ni_net_ns) + put_net(ni->ni_net_ns); + LIBCFS_FREE(ni, sizeof(*ni)); } @@ -171,6 +178,13 @@ lnet_ni_alloc(__u32 net, struct cfs_expr_list *el, struct list_head *nilist) /* LND will fill in the address part of the NID */ ni->ni_nid = LNET_MKNID(net, 0); + + /* Store net namespace in which current ni is being created */ + if (current->nsproxy->net_ns) + ni->ni_net_ns = get_net(current->nsproxy->net_ns); + else + ni->ni_net_ns = NULL; + ni->ni_last_alive = ktime_get_real_seconds(); list_add_tail(&ni->ni_list, nilist); return ni; diff --git a/drivers/staging/lustre/lnet/lnet/lib-move.c b/drivers/staging/lustre/lnet/lnet/lib-move.c index f89c9fe..48e6f8f 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-move.c +++ b/drivers/staging/lustre/lnet/lnet/lib-move.c @@ -37,6 +37,8 @@ #define DEBUG_SUBSYSTEM S_LNET #include "../../include/linux/lnet/lib-lnet.h" +#include <linux/nsproxy.h> +#include <net/net_namespace.h> static int local_nid_dist_zero = 1; module_param(local_nid_dist_zero, int, 0444); @@ -2320,6 +2322,15 @@ LNetDist(lnet_nid_t dstnid, lnet_nid_t *srcnidp, __u32 *orderp) } if (LNET_NIDNET(ni->ni_nid) == dstnet) { + /* + * Check if ni was originally created in + * current net namespace. + * If not, assign order above 0xffff0000, + * to make this ni not a priority. + */ + if (!net_eq(ni->ni_net_ns, current->nsproxy->net_ns)) + order += 0xffff0000; + if (srcnidp) *srcnidp = ni->ni_nid; if (orderp) -- cgit v0.10.2 From 9522bb7ac76f8290e65259a744ed5f286be39994 Mon Sep 17 00:00:00 2001 From: Doug Oucharek <doug.s.oucharek@intel.com> Date: Sun, 18 Sep 2016 16:39:00 -0400 Subject: staging: lustre: lnet: Ensure routing is turned on first time In lnet_rtrpools_enable(), a mistake was made and routing was not being turned on when the rtrpools are being allocated for the first time. This patch fixes that routine so we remember to turn on routing after allocating the rtrpools. Signed-off-by: Doug Oucharek <doug.s.oucharek@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-8501 Reviewed-on: http://review.whamcloud.com/21934 Reviewed-by: James Simmons <uja.ornl@yahoo.com> Reviewed-by: Amir Shehata <amir.shehata@intel.com> Reviewed-by: Dmitry Eremin <dmitry.eremin@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lnet/lnet/router.c b/drivers/staging/lustre/lnet/lnet/router.c index 69819c9..063ad55 100644 --- a/drivers/staging/lustre/lnet/lnet/router.c +++ b/drivers/staging/lustre/lnet/lnet/router.c @@ -1693,7 +1693,7 @@ lnet_rtrpools_adjust(int tiny, int small, int large) int lnet_rtrpools_enable(void) { - int rc; + int rc = 0; if (the_lnet.ln_routing) return 0; @@ -1706,9 +1706,9 @@ lnet_rtrpools_enable(void) * if we are just configuring this for the first * time. */ - return lnet_rtrpools_alloc(1); - - rc = lnet_rtrpools_adjust_helper(0, 0, 0); + rc = lnet_rtrpools_alloc(1); + else + rc = lnet_rtrpools_adjust_helper(0, 0, 0); if (rc) return rc; @@ -1718,7 +1718,7 @@ lnet_rtrpools_enable(void) the_lnet.ln_ping_info->pi_features &= ~LNET_PING_FEAT_RTE_DISABLED; lnet_net_unlock(LNET_LOCK_EX); - return 0; + return rc; } void -- cgit v0.10.2 From abe8a55fb0fbad1ab41d39c69212acf7f4364b49 Mon Sep 17 00:00:00 2001 From: Doug Oucharek <doug.s.oucharek@intel.com> Date: Sun, 18 Sep 2016 16:39:01 -0400 Subject: staging: lustre: lnet: Enable setting per NI peer_credits The code to allow peer_credits to be set per NI was originally "left inactive" because there were concerns about peer_credits interfering with the ability for IB nodes to connect to each other when peer_credits are not the same (peer_credits controls the queue depth for IB). With LU-3322, the values do not have to match so it is now safe to enable this code so peer_credits can be set per NI. This patch enables existing code for setting per NI peer_credits. Second this patch fixes a long standing bug in that the conf data was not being used to set variables in the lnet_ni structure until after lnd_startup() was called which meant LND drivers were ignoring struct lnet_ni tunable values being set. Now we change struct lnet_ni data fields based on conf data before calling lnd_startup(). Signed-off-by: Doug Oucharek <doug.s.oucharek@intel.com> Signed-off-by: James Simmons <uja.ornl@yahoo.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-8507 Reviewed-on: http://review.whamcloud.com/21948 Reviewed-by: Olaf Weber <olaf@sgi.com> Reviewed-by: Dmitry Eremin <dmitry.eremin@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lnet/lnet/api-ni.c b/drivers/staging/lustre/lnet/lnet/api-ni.c index 346db89..4daf828 100644 --- a/drivers/staging/lustre/lnet/lnet/api-ni.c +++ b/drivers/staging/lustre/lnet/lnet/api-ni.c @@ -1286,6 +1286,25 @@ lnet_startup_lndni(struct lnet_ni *ni, struct lnet_ioctl_config_data *conf) sizeof(*ni->ni_lnd_tunables)); } + /* + * If given some LND tunable parameters, parse those now to + * override the values in the NI structure. + */ + if (conf) { + if (conf->cfg_config_u.cfg_net.net_peer_rtr_credits >= 0) + ni->ni_peerrtrcredits = + conf->cfg_config_u.cfg_net.net_peer_rtr_credits; + if (conf->cfg_config_u.cfg_net.net_peer_timeout >= 0) + ni->ni_peertimeout = + conf->cfg_config_u.cfg_net.net_peer_timeout; + if (conf->cfg_config_u.cfg_net.net_peer_tx_credits != -1) + ni->ni_peertxcredits = + conf->cfg_config_u.cfg_net.net_peer_tx_credits; + if (conf->cfg_config_u.cfg_net.net_max_tx_credits >= 0) + ni->ni_maxtxcredits = + conf->cfg_config_u.cfg_net.net_max_tx_credits; + } + rc = lnd->lnd_startup(ni); mutex_unlock(&the_lnet.ln_lnd_mutex); @@ -1299,33 +1318,6 @@ lnet_startup_lndni(struct lnet_ni *ni, struct lnet_ioctl_config_data *conf) goto failed0; } - /* - * If given some LND tunable parameters, parse those now to - * override the values in the NI structure. - */ - if (conf && conf->cfg_config_u.cfg_net.net_peer_rtr_credits >= 0) { - ni->ni_peerrtrcredits = - conf->cfg_config_u.cfg_net.net_peer_rtr_credits; - } - if (conf && conf->cfg_config_u.cfg_net.net_peer_timeout >= 0) { - ni->ni_peertimeout = - conf->cfg_config_u.cfg_net.net_peer_timeout; - } - /* - * TODO - * Note: For now, don't allow the user to change - * peertxcredits as this number is used in the - * IB LND to control queue depth. - * - * if (conf && conf->cfg_config_u.cfg_net.net_peer_tx_credits != -1) - * ni->ni_peertxcredits = - * conf->cfg_config_u.cfg_net.net_peer_tx_credits; - */ - if (conf && conf->cfg_config_u.cfg_net.net_max_tx_credits >= 0) { - ni->ni_maxtxcredits = - conf->cfg_config_u.cfg_net.net_max_tx_credits; - } - LASSERT(ni->ni_peertimeout <= 0 || lnd->lnd_query); lnet_net_lock(LNET_LOCK_EX); -- cgit v0.10.2 From d566b9aec93e603f59430d32d7996b74a7b5f555 Mon Sep 17 00:00:00 2001 From: Doug Oucharek <doug.s.oucharek@intel.com> Date: Sun, 18 Sep 2016 16:39:02 -0400 Subject: staging: lustre: o2iblnd: Put back work queue check previously removed The previous patch, http://review.whamcloud.com/21304/, removed a check needed until LU-5718 is properly addressed. With the check, LU-5718 results in an error message and a lost RDMA operation. Without it, we have memory corruption and a crash (much harder to debug). Putting the check back in case LU-5718 is not fixed soon. Signed-off-by: Doug Oucharek <doug.s.oucharek@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-7650 Reviewed-on: http://review.whamcloud.com/22281 Reviewed-by: James Simmons <uja.ornl@yahoo.com> Reviewed-by: Olaf Weber <olaf@sgi.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index 3a86879..b27de88 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -1093,6 +1093,16 @@ kiblnd_init_rdma(struct kib_conn *conn, struct kib_tx *tx, int type, break; } + if (tx->tx_nwrq >= IBLND_MAX_RDMA_FRAGS) { + CERROR("RDMA has too many fragments for peer %s (%d), src idx/frags: %d/%d dst idx/frags: %d/%d\n", + libcfs_nid2str(conn->ibc_peer->ibp_nid), + IBLND_MAX_RDMA_FRAGS, + srcidx, srcrd->rd_nfrags, + dstidx, dstrd->rd_nfrags); + rc = -EMSGSIZE; + break; + } + wrknob = min(min(kiblnd_rd_frag_size(srcrd, srcidx), kiblnd_rd_frag_size(dstrd, dstidx)), (__u32)resid); -- cgit v0.10.2 From 26e9c85b48b4e3a2301c049213de3b5456c6b0a4 Mon Sep 17 00:00:00 2001 From: James Simmons <jsimmons@infradead.org> Date: Sun, 18 Sep 2016 16:39:03 -0400 Subject: staging: lustre: update version to 2.6.99 With all of the the missing patches from the lustre 2.7 version merged upstream its time to update the upstream clients version. Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/include/lustre_ver.h b/drivers/staging/lustre/lustre/include/lustre_ver.h index 414075f..19c9135 100644 --- a/drivers/staging/lustre/lustre/include/lustre_ver.h +++ b/drivers/staging/lustre/lustre/include/lustre_ver.h @@ -2,10 +2,10 @@ #define _LUSTRE_VER_H_ #define LUSTRE_MAJOR 2 -#define LUSTRE_MINOR 5 -#define LUSTRE_PATCH 60 +#define LUSTRE_MINOR 6 +#define LUSTRE_PATCH 99 #define LUSTRE_FIX 0 -#define LUSTRE_VERSION_STRING "2.5.99" +#define LUSTRE_VERSION_STRING "2.6.99" #define OBD_OCD_VERSION(major, minor, patch, fix) \ (((major) << 24) + ((minor) << 16) + ((patch) << 8) + (fix)) -- cgit v0.10.2 From dae09011115133666e47c35673c0564b0a702db7 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Thu, 8 Sep 2016 11:44:34 +0200 Subject: greybus: remove local checkpatch.pl copy When the greybus tree was external, it contained a copy of checkpatch.pl to keep everyone "in line". This is no longer needed and can now be removed. Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/scripts/checkpatch.pl b/drivers/staging/greybus/scripts/checkpatch.pl deleted file mode 100755 index 9930b73..0000000 --- a/drivers/staging/greybus/scripts/checkpatch.pl +++ /dev/null @@ -1,5993 +0,0 @@ -#!/usr/bin/perl -w -# (c) 2001, Dave Jones. (the file handling bit) -# (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit) -# (c) 2007,2008, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite) -# (c) 2008-2010 Andy Whitcroft <apw@canonical.com> -# Licensed under the terms of the GNU GPL License version 2 - -use strict; -use POSIX; -use File::Basename; -use Cwd 'abs_path'; -use Term::ANSIColor qw(:constants); - -my $P = $0; -my $D = dirname(abs_path($P)); - -my $V = '0.32'; - -use Getopt::Long qw(:config no_auto_abbrev); - -my $quiet = 0; -my $tree = 0; -my $chk_signoff = 1; -my $chk_patch = 1; -my $tst_only; -my $emacs = 0; -my $terse = 0; -my $showfile = 0; -my $file = 0; -my $check = 0; -my $check_orig = 0; -my $summary = 1; -my $mailback = 0; -my $summary_file = 0; -my $show_types = 0; -my $fix = 0; -my $fix_inplace = 0; -my $root; -my %debug; -my %camelcase = (); -my %use_type = (); -my @use = (); -my %ignore_type = (); -my @ignore = (); -my $help = 0; -my $configuration_file = ".checkpatch.conf"; -my $max_line_length = 80; -my $ignore_perl_version = 0; -my $minimum_perl_version = 5.10.0; -my $min_conf_desc_length = 4; -my $spelling_file = "$D/spelling.txt"; -my $codespell = 0; -my $codespellfile = "/usr/share/codespell/dictionary.txt"; -my $color = 1; - -sub help { - my ($exitcode) = @_; - - print << "EOM"; -Usage: $P [OPTION]... [FILE]... -Version: $V - -Options: - -q, --quiet quiet - --no-tree run without a kernel tree - --no-signoff do not check for 'Signed-off-by' line - --patch treat FILE as patchfile (default) - --emacs emacs compile window format - --terse one line per report - --showfile emit diffed file position, not input file position - -f, --file treat FILE as regular source file - --subjective, --strict enable more subjective tests - --types TYPE(,TYPE2...) show only these comma separated message types - --ignore TYPE(,TYPE2...) ignore various comma separated message types - --max-line-length=n set the maximum line length, if exceeded, warn - --min-conf-desc-length=n set the min description length, if shorter, warn - --show-types show the message "types" in the output - --root=PATH PATH to the kernel tree root - --no-summary suppress the per-file summary - --mailback only produce a report in case of warnings/errors - --summary-file include the filename in summary - --debug KEY=[0|1] turn on/off debugging of KEY, where KEY is one of - 'values', 'possible', 'type', and 'attr' (default - is all off) - --test-only=WORD report only warnings/errors containing WORD - literally - --fix EXPERIMENTAL - may create horrible results - If correctable single-line errors exist, create - "<inputfile>.EXPERIMENTAL-checkpatch-fixes" - with potential errors corrected to the preferred - checkpatch style - --fix-inplace EXPERIMENTAL - may create horrible results - Is the same as --fix, but overwrites the input - file. It's your fault if there's no backup or git - --ignore-perl-version override checking of perl version. expect - runtime errors. - --codespell Use the codespell dictionary for spelling/typos - (default:/usr/share/codespell/dictionary.txt) - --codespellfile Use this codespell dictionary - --color Use colors when output is STDOUT (default: on) - -h, --help, --version display this help and exit - -When FILE is - read standard input. -EOM - - exit($exitcode); -} - -my $conf = which_conf($configuration_file); -if (-f $conf) { - my @conf_args; - open(my $conffile, '<', "$conf") - or warn "$P: Can't find a readable $configuration_file file $!\n"; - - while (<$conffile>) { - my $line = $_; - - $line =~ s/\s*\n?$//g; - $line =~ s/^\s*//g; - $line =~ s/\s+/ /g; - - next if ($line =~ m/^\s*#/); - next if ($line =~ m/^\s*$/); - - my @words = split(" ", $line); - foreach my $word (@words) { - last if ($word =~ m/^#/); - push (@conf_args, $word); - } - } - close($conffile); - unshift(@ARGV, @conf_args) if @conf_args; -} - -GetOptions( - 'q|quiet+' => \$quiet, - 'tree!' => \$tree, - 'signoff!' => \$chk_signoff, - 'patch!' => \$chk_patch, - 'emacs!' => \$emacs, - 'terse!' => \$terse, - 'showfile!' => \$showfile, - 'f|file!' => \$file, - 'subjective!' => \$check, - 'strict!' => \$check, - 'ignore=s' => \@ignore, - 'types=s' => \@use, - 'show-types!' => \$show_types, - 'max-line-length=i' => \$max_line_length, - 'min-conf-desc-length=i' => \$min_conf_desc_length, - 'root=s' => \$root, - 'summary!' => \$summary, - 'mailback!' => \$mailback, - 'summary-file!' => \$summary_file, - 'fix!' => \$fix, - 'fix-inplace!' => \$fix_inplace, - 'ignore-perl-version!' => \$ignore_perl_version, - 'debug=s' => \%debug, - 'test-only=s' => \$tst_only, - 'codespell!' => \$codespell, - 'codespellfile=s' => \$codespellfile, - 'color!' => \$color, - 'h|help' => \$help, - 'version' => \$help -) or help(1); - -help(0) if ($help); - -$fix = 1 if ($fix_inplace); -$check_orig = $check; - -my $exit = 0; - -if ($^V && $^V lt $minimum_perl_version) { - printf "$P: requires at least perl version %vd\n", $minimum_perl_version; - if (!$ignore_perl_version) { - exit(1); - } -} - -if ($#ARGV < 0) { - print "$P: no input files\n"; - exit(1); -} - -sub hash_save_array_words { - my ($hashRef, $arrayRef) = @_; - - my @array = split(/,/, join(',', @$arrayRef)); - foreach my $word (@array) { - $word =~ s/\s*\n?$//g; - $word =~ s/^\s*//g; - $word =~ s/\s+/ /g; - $word =~ tr/[a-z]/[A-Z]/; - - next if ($word =~ m/^\s*#/); - next if ($word =~ m/^\s*$/); - - $hashRef->{$word}++; - } -} - -sub hash_show_words { - my ($hashRef, $prefix) = @_; - - if (keys %$hashRef) { - print "\nNOTE: $prefix message types:"; - foreach my $word (sort keys %$hashRef) { - print " $word"; - } - print "\n"; - } -} - -hash_save_array_words(\%ignore_type, \@ignore); -hash_save_array_words(\%use_type, \@use); - -my $dbg_values = 0; -my $dbg_possible = 0; -my $dbg_type = 0; -my $dbg_attr = 0; -for my $key (keys %debug) { - ## no critic - eval "\${dbg_$key} = '$debug{$key}';"; - die "$@" if ($@); -} - -my $rpt_cleaners = 0; - -if ($terse) { - $emacs = 1; - $quiet++; -} - -if ($tree) { - if (defined $root) { - if (!top_of_kernel_tree($root)) { - die "$P: $root: --root does not point at a valid tree\n"; - } - } else { - if (top_of_kernel_tree('.')) { - $root = '.'; - } elsif ($0 =~ m@(.*)/scripts/[^/]*$@ && - top_of_kernel_tree($1)) { - $root = $1; - } - } - - if (!defined $root) { - print "Must be run from the top-level dir. of a kernel tree\n"; - exit(2); - } -} - -my $emitted_corrupt = 0; - -our $Ident = qr{ - [A-Za-z_][A-Za-z\d_]* - (?:\s*\#\#\s*[A-Za-z_][A-Za-z\d_]*)* - }x; -our $Storage = qr{extern|static|asmlinkage}; -our $Sparse = qr{ - __user| - __kernel| - __force| - __iomem| - __pmem| - __must_check| - __init_refok| - __kprobes| - __ref| - __rcu| - __private - }x; -our $InitAttributePrefix = qr{__(?:mem|cpu|dev|net_|)}; -our $InitAttributeData = qr{$InitAttributePrefix(?:initdata\b)}; -our $InitAttributeConst = qr{$InitAttributePrefix(?:initconst\b)}; -our $InitAttributeInit = qr{$InitAttributePrefix(?:init\b)}; -our $InitAttribute = qr{$InitAttributeData|$InitAttributeConst|$InitAttributeInit}; - -# Notes to $Attribute: -# We need \b after 'init' otherwise 'initconst' will cause a false positive in a check -our $Attribute = qr{ - const| - __percpu| - __nocast| - __safe| - __bitwise__| - __packed__| - __packed2__| - __naked| - __maybe_unused| - __always_unused| - __noreturn| - __used| - __cold| - __pure| - __noclone| - __deprecated| - __read_mostly| - __kprobes| - $InitAttribute| - ____cacheline_aligned| - ____cacheline_aligned_in_smp| - ____cacheline_internodealigned_in_smp| - __weak - }x; -our $Modifier; -our $Inline = qr{inline|__always_inline|noinline|__inline|__inline__}; -our $Member = qr{->$Ident|\.$Ident|\[[^]]*\]}; -our $Lval = qr{$Ident(?:$Member)*}; - -our $Int_type = qr{(?i)llu|ull|ll|lu|ul|l|u}; -our $Binary = qr{(?i)0b[01]+$Int_type?}; -our $Hex = qr{(?i)0x[0-9a-f]+$Int_type?}; -our $Int = qr{[0-9]+$Int_type?}; -our $Octal = qr{0[0-7]+$Int_type?}; -our $String = qr{"[X\t]*"}; -our $Float_hex = qr{(?i)0x[0-9a-f]+p-?[0-9]+[fl]?}; -our $Float_dec = qr{(?i)(?:[0-9]+\.[0-9]*|[0-9]*\.[0-9]+)(?:e-?[0-9]+)?[fl]?}; -our $Float_int = qr{(?i)[0-9]+e-?[0-9]+[fl]?}; -our $Float = qr{$Float_hex|$Float_dec|$Float_int}; -our $Constant = qr{$Float|$Binary|$Octal|$Hex|$Int}; -our $Assignment = qr{\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=}; -our $Compare = qr{<=|>=|==|!=|<|(?<!-)>}; -our $Arithmetic = qr{\+|-|\*|\/|%}; -our $Operators = qr{ - <=|>=|==|!=| - =>|->|<<|>>|<|>|!|~| - &&|\|\||,|\^|\+\+|--|&|\||$Arithmetic - }x; - -our $c90_Keywords = qr{do|for|while|if|else|return|goto|continue|switch|default|case|break}x; - -our $BasicType; -our $NonptrType; -our $NonptrTypeMisordered; -our $NonptrTypeWithAttr; -our $Type; -our $TypeMisordered; -our $Declare; -our $DeclareMisordered; - -our $NON_ASCII_UTF8 = qr{ - [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte - | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs - | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte - | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates - | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 - | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 - | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 -}x; - -our $UTF8 = qr{ - [\x09\x0A\x0D\x20-\x7E] # ASCII - | $NON_ASCII_UTF8 -}x; - -our $typeC99Typedefs = qr{(?:__)?(?:[us]_?)?int_?(?:8|16|32|64)_t}; -our $typeOtherOSTypedefs = qr{(?x: - u_(?:char|short|int|long) | # bsd - u(?:nchar|short|int|long) # sysv -)}; -our $typeKernelTypedefs = qr{(?x: - (?:__)?(?:u|s|be|le)(?:8|16|32|64)| - atomic_t -)}; -our $typeTypedefs = qr{(?x: - $typeC99Typedefs\b| - $typeOtherOSTypedefs\b| - $typeKernelTypedefs\b -)}; - -our $zero_initializer = qr{(?:(?:0[xX])?0+$Int_type?|NULL|false)\b}; - -our $logFunctions = qr{(?x: - printk(?:_ratelimited|_once|)| - (?:[a-z0-9]+_){1,2}(?:printk|emerg|alert|crit|err|warning|warn|notice|info|debug|dbg|vdbg|devel|cont|WARN)(?:_ratelimited|_once|)| - WARN(?:_RATELIMIT|_ONCE|)| - panic| - MODULE_[A-Z_]+| - seq_vprintf|seq_printf|seq_puts -)}; - -our $signature_tags = qr{(?xi: - Signed-off-by:| - Acked-by:| - Tested-by:| - Reviewed-by:| - Reported-by:| - Suggested-by:| - To:| - Cc: -)}; - -our @typeListMisordered = ( - qr{char\s+(?:un)?signed}, - qr{int\s+(?:(?:un)?signed\s+)?short\s}, - qr{int\s+short(?:\s+(?:un)?signed)}, - qr{short\s+int(?:\s+(?:un)?signed)}, - qr{(?:un)?signed\s+int\s+short}, - qr{short\s+(?:un)?signed}, - qr{long\s+int\s+(?:un)?signed}, - qr{int\s+long\s+(?:un)?signed}, - qr{long\s+(?:un)?signed\s+int}, - qr{int\s+(?:un)?signed\s+long}, - qr{int\s+(?:un)?signed}, - qr{int\s+long\s+long\s+(?:un)?signed}, - qr{long\s+long\s+int\s+(?:un)?signed}, - qr{long\s+long\s+(?:un)?signed\s+int}, - qr{long\s+long\s+(?:un)?signed}, - qr{long\s+(?:un)?signed}, -); - -our @typeList = ( - qr{void}, - qr{(?:(?:un)?signed\s+)?char}, - qr{(?:(?:un)?signed\s+)?short\s+int}, - qr{(?:(?:un)?signed\s+)?short}, - qr{(?:(?:un)?signed\s+)?int}, - qr{(?:(?:un)?signed\s+)?long\s+int}, - qr{(?:(?:un)?signed\s+)?long\s+long\s+int}, - qr{(?:(?:un)?signed\s+)?long\s+long}, - qr{(?:(?:un)?signed\s+)?long}, - qr{(?:un)?signed}, - qr{float}, - qr{double}, - qr{bool}, - qr{struct\s+$Ident}, - qr{union\s+$Ident}, - qr{enum\s+$Ident}, - qr{${Ident}_t}, - qr{${Ident}_handler}, - qr{${Ident}_handler_fn}, - @typeListMisordered, -); - -our $C90_int_types = qr{(?x: - long\s+long\s+int\s+(?:un)?signed| - long\s+long\s+(?:un)?signed\s+int| - long\s+long\s+(?:un)?signed| - (?:(?:un)?signed\s+)?long\s+long\s+int| - (?:(?:un)?signed\s+)?long\s+long| - int\s+long\s+long\s+(?:un)?signed| - int\s+(?:(?:un)?signed\s+)?long\s+long| - - long\s+int\s+(?:un)?signed| - long\s+(?:un)?signed\s+int| - long\s+(?:un)?signed| - (?:(?:un)?signed\s+)?long\s+int| - (?:(?:un)?signed\s+)?long| - int\s+long\s+(?:un)?signed| - int\s+(?:(?:un)?signed\s+)?long| - - int\s+(?:un)?signed| - (?:(?:un)?signed\s+)?int -)}; - -our @typeListFile = (); -our @typeListWithAttr = ( - @typeList, - qr{struct\s+$InitAttribute\s+$Ident}, - qr{union\s+$InitAttribute\s+$Ident}, -); - -our @modifierList = ( - qr{fastcall}, -); -our @modifierListFile = (); - -our @mode_permission_funcs = ( - ["module_param", 3], - ["module_param_(?:array|named|string)", 4], - ["module_param_array_named", 5], - ["debugfs_create_(?:file|u8|u16|u32|u64|x8|x16|x32|x64|size_t|atomic_t|bool|blob|regset32|u32_array)", 2], - ["proc_create(?:_data|)", 2], - ["(?:CLASS|DEVICE|SENSOR)_ATTR", 2], -); - -#Create a search pattern for all these functions to speed up a loop below -our $mode_perms_search = ""; -foreach my $entry (@mode_permission_funcs) { - $mode_perms_search .= '|' if ($mode_perms_search ne ""); - $mode_perms_search .= $entry->[0]; -} - -our $mode_perms_world_writable = qr{ - S_IWUGO | - S_IWOTH | - S_IRWXUGO | - S_IALLUGO | - 0[0-7][0-7][2367] -}x; - -our $allowed_asm_includes = qr{(?x: - irq| - memory| - time| - reboot -)}; -# memory.h: ARM has a custom one - -# Load common spelling mistakes and build regular expression list. -my $misspellings; -my %spelling_fix; - -if (open(my $spelling, '<', $spelling_file)) { - while (<$spelling>) { - my $line = $_; - - $line =~ s/\s*\n?$//g; - $line =~ s/^\s*//g; - - next if ($line =~ m/^\s*#/); - next if ($line =~ m/^\s*$/); - - my ($suspect, $fix) = split(/\|\|/, $line); - - $spelling_fix{$suspect} = $fix; - } - close($spelling); -} else { - warn "No typos will be found - file '$spelling_file': $!\n"; -} - -if ($codespell) { - if (open(my $spelling, '<', $codespellfile)) { - while (<$spelling>) { - my $line = $_; - - $line =~ s/\s*\n?$//g; - $line =~ s/^\s*//g; - - next if ($line =~ m/^\s*#/); - next if ($line =~ m/^\s*$/); - next if ($line =~ m/, disabled/i); - - $line =~ s/,.*$//; - - my ($suspect, $fix) = split(/->/, $line); - - $spelling_fix{$suspect} = $fix; - } - close($spelling); - } else { - warn "No codespell typos will be found - file '$codespellfile': $!\n"; - } -} - -$misspellings = join("|", sort keys %spelling_fix) if keys %spelling_fix; - -sub build_types { - my $mods = "(?x: \n" . join("|\n ", (@modifierList, @modifierListFile)) . "\n)"; - my $all = "(?x: \n" . join("|\n ", (@typeList, @typeListFile)) . "\n)"; - my $Misordered = "(?x: \n" . join("|\n ", @typeListMisordered) . "\n)"; - my $allWithAttr = "(?x: \n" . join("|\n ", @typeListWithAttr) . "\n)"; - $Modifier = qr{(?:$Attribute|$Sparse|$mods)}; - $BasicType = qr{ - (?:$typeTypedefs\b)| - (?:${all}\b) - }x; - $NonptrType = qr{ - (?:$Modifier\s+|const\s+)* - (?: - (?:typeof|__typeof__)\s*\([^\)]*\)| - (?:$typeTypedefs\b)| - (?:${all}\b) - ) - (?:\s+$Modifier|\s+const)* - }x; - $NonptrTypeMisordered = qr{ - (?:$Modifier\s+|const\s+)* - (?: - (?:${Misordered}\b) - ) - (?:\s+$Modifier|\s+const)* - }x; - $NonptrTypeWithAttr = qr{ - (?:$Modifier\s+|const\s+)* - (?: - (?:typeof|__typeof__)\s*\([^\)]*\)| - (?:$typeTypedefs\b)| - (?:${allWithAttr}\b) - ) - (?:\s+$Modifier|\s+const)* - }x; - $Type = qr{ - $NonptrType - (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+)? - (?:\s+$Inline|\s+$Modifier)* - }x; - $TypeMisordered = qr{ - $NonptrTypeMisordered - (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+)? - (?:\s+$Inline|\s+$Modifier)* - }x; - $Declare = qr{(?:$Storage\s+(?:$Inline\s+)?)?$Type}; - $DeclareMisordered = qr{(?:$Storage\s+(?:$Inline\s+)?)?$TypeMisordered}; -} -build_types(); - -our $Typecast = qr{\s*(\(\s*$NonptrType\s*\)){0,1}\s*}; - -# Using $balanced_parens, $LvalOrFunc, or $FuncArg -# requires at least perl version v5.10.0 -# Any use must be runtime checked with $^V - -our $balanced_parens = qr/(\((?:[^\(\)]++|(?-1))*\))/; -our $LvalOrFunc = qr{((?:[\&\*]\s*)?$Lval)\s*($balanced_parens{0,1})\s*}; -our $FuncArg = qr{$Typecast{0,1}($LvalOrFunc|$Constant|$String)}; - -our $declaration_macros = qr{(?x: - (?:$Storage\s+)?(?:[A-Z_][A-Z0-9]*_){0,2}(?:DEFINE|DECLARE)(?:_[A-Z0-9]+){1,6}\s*\(| - (?:$Storage\s+)?LIST_HEAD\s*\(| - (?:$Storage\s+)?${Type}\s+uninitialized_var\s*\( -)}; - -sub deparenthesize { - my ($string) = @_; - return "" if (!defined($string)); - - while ($string =~ /^\s*\(.*\)\s*$/) { - $string =~ s@^\s*\(\s*@@; - $string =~ s@\s*\)\s*$@@; - } - - $string =~ s@\s+@ @g; - - return $string; -} - -sub seed_camelcase_file { - my ($file) = @_; - - return if (!(-f $file)); - - local $/; - - open(my $include_file, '<', "$file") - or warn "$P: Can't read '$file' $!\n"; - my $text = <$include_file>; - close($include_file); - - my @lines = split('\n', $text); - - foreach my $line (@lines) { - next if ($line !~ /(?:[A-Z][a-z]|[a-z][A-Z])/); - if ($line =~ /^[ \t]*(?:#[ \t]*define|typedef\s+$Type)\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)/) { - $camelcase{$1} = 1; - } elsif ($line =~ /^\s*$Declare\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)\s*[\(\[,;]/) { - $camelcase{$1} = 1; - } elsif ($line =~ /^\s*(?:union|struct|enum)\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)\s*[;\{]/) { - $camelcase{$1} = 1; - } - } -} - -my $camelcase_seeded = 0; -sub seed_camelcase_includes { - return if ($camelcase_seeded); - - my $files; - my $camelcase_cache = ""; - my @include_files = (); - - $camelcase_seeded = 1; - - if (-e ".git") { - my $git_last_include_commit = `git log --no-merges --pretty=format:"%h%n" -1 -- include`; - chomp $git_last_include_commit; - $camelcase_cache = ".checkpatch-camelcase.git.$git_last_include_commit"; - } else { - my $last_mod_date = 0; - $files = `find $root/include -name "*.h"`; - @include_files = split('\n', $files); - foreach my $file (@include_files) { - my $date = POSIX::strftime("%Y%m%d%H%M", - localtime((stat $file)[9])); - $last_mod_date = $date if ($last_mod_date < $date); - } - $camelcase_cache = ".checkpatch-camelcase.date.$last_mod_date"; - } - - if ($camelcase_cache ne "" && -f $camelcase_cache) { - open(my $camelcase_file, '<', "$camelcase_cache") - or warn "$P: Can't read '$camelcase_cache' $!\n"; - while (<$camelcase_file>) { - chomp; - $camelcase{$_} = 1; - } - close($camelcase_file); - - return; - } - - if (-e ".git") { - $files = `git ls-files "include/*.h"`; - @include_files = split('\n', $files); - } - - foreach my $file (@include_files) { - seed_camelcase_file($file); - } - - if ($camelcase_cache ne "") { - unlink glob ".checkpatch-camelcase.*"; - open(my $camelcase_file, '>', "$camelcase_cache") - or warn "$P: Can't write '$camelcase_cache' $!\n"; - foreach (sort { lc($a) cmp lc($b) } keys(%camelcase)) { - print $camelcase_file ("$_\n"); - } - close($camelcase_file); - } -} - -sub git_commit_info { - my ($commit, $id, $desc) = @_; - - return ($id, $desc) if ((which("git") eq "") || !(-e ".git")); - - my $output = `git log --no-color --format='%H %s' -1 $commit 2>&1`; - $output =~ s/^\s*//gm; - my @lines = split("\n", $output); - - return ($id, $desc) if ($#lines < 0); - - if ($lines[0] =~ /^error: short SHA1 $commit is ambiguous\./) { -# Maybe one day convert this block of bash into something that returns -# all matching commit ids, but it's very slow... -# -# echo "checking commits $1..." -# git rev-list --remotes | grep -i "^$1" | -# while read line ; do -# git log --format='%H %s' -1 $line | -# echo "commit $(cut -c 1-12,41-)" -# done - } elsif ($lines[0] =~ /^fatal: ambiguous argument '$commit': unknown revision or path not in the working tree\./) { - } else { - $id = substr($lines[0], 0, 12); - $desc = substr($lines[0], 41); - } - - return ($id, $desc); -} - -$chk_signoff = 0 if ($file); - -my @rawlines = (); -my @lines = (); -my @fixed = (); -my @fixed_inserted = (); -my @fixed_deleted = (); -my $fixlinenr = -1; - -my $vname; -for my $filename (@ARGV) { - my $FILE; - if ($file) { - open($FILE, '-|', "diff -u /dev/null $filename") || - die "$P: $filename: diff failed - $!\n"; - } elsif ($filename eq '-') { - open($FILE, '<&STDIN'); - } else { - open($FILE, '<', "$filename") || - die "$P: $filename: open failed - $!\n"; - } - if ($filename eq '-') { - $vname = 'Your patch'; - } else { - $vname = $filename; - } - while (<$FILE>) { - chomp; - push(@rawlines, $_); - } - close($FILE); - - if ($#ARGV > 0 && $quiet == 0) { - print '-' x length($vname) . "\n"; - print "$vname\n"; - print '-' x length($vname) . "\n"; - } - - if (!process($filename)) { - $exit = 1; - } - @rawlines = (); - @lines = (); - @fixed = (); - @fixed_inserted = (); - @fixed_deleted = (); - $fixlinenr = -1; - @modifierListFile = (); - @typeListFile = (); - build_types(); -} - -if (!$quiet) { - hash_show_words(\%use_type, "Used"); - hash_show_words(\%ignore_type, "Ignored"); - - if ($^V lt 5.10.0) { - print << "EOM" - -NOTE: perl $^V is not modern enough to detect all possible issues. - An upgrade to at least perl v5.10.0 is suggested. -EOM - } - if ($exit) { - print << "EOM" - -NOTE: If any of the errors are false positives, please report - them to the maintainer, see CHECKPATCH in MAINTAINERS. -EOM - } -} - -exit($exit); - -sub top_of_kernel_tree { - my ($root) = @_; - - my @tree_check = ( - "COPYING", "CREDITS", "Kbuild", "MAINTAINERS", "Makefile", - "README", "Documentation", "arch", "include", "drivers", - "fs", "init", "ipc", "kernel", "lib", "scripts", - ); - - foreach my $check (@tree_check) { - if (! -e $root . '/' . $check) { - return 0; - } - } - return 1; -} - -sub parse_email { - my ($formatted_email) = @_; - - my $name = ""; - my $address = ""; - my $comment = ""; - - if ($formatted_email =~ /^(.*)<(\S+\@\S+)>(.*)$/) { - $name = $1; - $address = $2; - $comment = $3 if defined $3; - } elsif ($formatted_email =~ /^\s*<(\S+\@\S+)>(.*)$/) { - $address = $1; - $comment = $2 if defined $2; - } elsif ($formatted_email =~ /(\S+\@\S+)(.*)$/) { - $address = $1; - $comment = $2 if defined $2; - $formatted_email =~ s/$address.*$//; - $name = $formatted_email; - $name = trim($name); - $name =~ s/^\"|\"$//g; - # If there's a name left after stripping spaces and - # leading quotes, and the address doesn't have both - # leading and trailing angle brackets, the address - # is invalid. ie: - # "joe smith joe@smith.com" bad - # "joe smith <joe@smith.com" bad - if ($name ne "" && $address !~ /^<[^>]+>$/) { - $name = ""; - $address = ""; - $comment = ""; - } - } - - $name = trim($name); - $name =~ s/^\"|\"$//g; - $address = trim($address); - $address =~ s/^\<|\>$//g; - - if ($name =~ /[^\w \-]/i) { ##has "must quote" chars - $name =~ s/(?<!\\)"/\\"/g; ##escape quotes - $name = "\"$name\""; - } - - return ($name, $address, $comment); -} - -sub format_email { - my ($name, $address) = @_; - - my $formatted_email; - - $name = trim($name); - $name =~ s/^\"|\"$//g; - $address = trim($address); - - if ($name =~ /[^\w \-]/i) { ##has "must quote" chars - $name =~ s/(?<!\\)"/\\"/g; ##escape quotes - $name = "\"$name\""; - } - - if ("$name" eq "") { - $formatted_email = "$address"; - } else { - $formatted_email = "$name <$address>"; - } - - return $formatted_email; -} - -sub which { - my ($bin) = @_; - - foreach my $path (split(/:/, $ENV{PATH})) { - if (-e "$path/$bin") { - return "$path/$bin"; - } - } - - return ""; -} - -sub which_conf { - my ($conf) = @_; - - foreach my $path (split(/:/, ".:$ENV{HOME}:.scripts")) { - if (-e "$path/$conf") { - return "$path/$conf"; - } - } - - return ""; -} - -sub expand_tabs { - my ($str) = @_; - - my $res = ''; - my $n = 0; - for my $c (split(//, $str)) { - if ($c eq "\t") { - $res .= ' '; - $n++; - for (; ($n % 8) != 0; $n++) { - $res .= ' '; - } - next; - } - $res .= $c; - $n++; - } - - return $res; -} -sub copy_spacing { - (my $res = shift) =~ tr/\t/ /c; - return $res; -} - -sub line_stats { - my ($line) = @_; - - # Drop the diff line leader and expand tabs - $line =~ s/^.//; - $line = expand_tabs($line); - - # Pick the indent from the front of the line. - my ($white) = ($line =~ /^(\s*)/); - - return (length($line), length($white)); -} - -my $sanitise_quote = ''; - -sub sanitise_line_reset { - my ($in_comment) = @_; - - if ($in_comment) { - $sanitise_quote = '*/'; - } else { - $sanitise_quote = ''; - } -} -sub sanitise_line { - my ($line) = @_; - - my $res = ''; - my $l = ''; - - my $qlen = 0; - my $off = 0; - my $c; - - # Always copy over the diff marker. - $res = substr($line, 0, 1); - - for ($off = 1; $off < length($line); $off++) { - $c = substr($line, $off, 1); - - # Comments we are wacking completly including the begin - # and end, all to $;. - if ($sanitise_quote eq '' && substr($line, $off, 2) eq '/*') { - $sanitise_quote = '*/'; - - substr($res, $off, 2, "$;$;"); - $off++; - next; - } - if ($sanitise_quote eq '*/' && substr($line, $off, 2) eq '*/') { - $sanitise_quote = ''; - substr($res, $off, 2, "$;$;"); - $off++; - next; - } - if ($sanitise_quote eq '' && substr($line, $off, 2) eq '//') { - $sanitise_quote = '//'; - - substr($res, $off, 2, $sanitise_quote); - $off++; - next; - } - - # A \ in a string means ignore the next character. - if (($sanitise_quote eq "'" || $sanitise_quote eq '"') && - $c eq "\\") { - substr($res, $off, 2, 'XX'); - $off++; - next; - } - # Regular quotes. - if ($c eq "'" || $c eq '"') { - if ($sanitise_quote eq '') { - $sanitise_quote = $c; - - substr($res, $off, 1, $c); - next; - } elsif ($sanitise_quote eq $c) { - $sanitise_quote = ''; - } - } - - #print "c<$c> SQ<$sanitise_quote>\n"; - if ($off != 0 && $sanitise_quote eq '*/' && $c ne "\t") { - substr($res, $off, 1, $;); - } elsif ($off != 0 && $sanitise_quote eq '//' && $c ne "\t") { - substr($res, $off, 1, $;); - } elsif ($off != 0 && $sanitise_quote && $c ne "\t") { - substr($res, $off, 1, 'X'); - } else { - substr($res, $off, 1, $c); - } - } - - if ($sanitise_quote eq '//') { - $sanitise_quote = ''; - } - - # The pathname on a #include may be surrounded by '<' and '>'. - if ($res =~ /^.\s*\#\s*include\s+\<(.*)\>/) { - my $clean = 'X' x length($1); - $res =~ s@\<.*\>@<$clean>@; - - # The whole of a #error is a string. - } elsif ($res =~ /^.\s*\#\s*(?:error|warning)\s+(.*)\b/) { - my $clean = 'X' x length($1); - $res =~ s@(\#\s*(?:error|warning)\s+).*@$1$clean@; - } - - return $res; -} - -sub get_quoted_string { - my ($line, $rawline) = @_; - - return "" if ($line !~ m/($String)/g); - return substr($rawline, $-[0], $+[0] - $-[0]); -} - -sub ctx_statement_block { - my ($linenr, $remain, $off) = @_; - my $line = $linenr - 1; - my $blk = ''; - my $soff = $off; - my $coff = $off - 1; - my $coff_set = 0; - - my $loff = 0; - - my $type = ''; - my $level = 0; - my @stack = (); - my $p; - my $c; - my $len = 0; - - my $remainder; - while (1) { - @stack = (['', 0]) if ($#stack == -1); - - #warn "CSB: blk<$blk> remain<$remain>\n"; - # If we are about to drop off the end, pull in more - # context. - if ($off >= $len) { - for (; $remain > 0; $line++) { - last if (!defined $lines[$line]); - next if ($lines[$line] =~ /^-/); - $remain--; - $loff = $len; - $blk .= $lines[$line] . "\n"; - $len = length($blk); - $line++; - last; - } - # Bail if there is no further context. - #warn "CSB: blk<$blk> off<$off> len<$len>\n"; - if ($off >= $len) { - last; - } - if ($level == 0 && substr($blk, $off) =~ /^.\s*#\s*define/) { - $level++; - $type = '#'; - } - } - $p = $c; - $c = substr($blk, $off, 1); - $remainder = substr($blk, $off); - - #warn "CSB: c<$c> type<$type> level<$level> remainder<$remainder> coff_set<$coff_set>\n"; - - # Handle nested #if/#else. - if ($remainder =~ /^#\s*(?:ifndef|ifdef|if)\s/) { - push(@stack, [ $type, $level ]); - } elsif ($remainder =~ /^#\s*(?:else|elif)\b/) { - ($type, $level) = @{$stack[$#stack - 1]}; - } elsif ($remainder =~ /^#\s*endif\b/) { - ($type, $level) = @{pop(@stack)}; - } - - # Statement ends at the ';' or a close '}' at the - # outermost level. - if ($level == 0 && $c eq ';') { - last; - } - - # An else is really a conditional as long as its not else if - if ($level == 0 && $coff_set == 0 && - (!defined($p) || $p =~ /(?:\s|\}|\+)/) && - $remainder =~ /^(else)(?:\s|{)/ && - $remainder !~ /^else\s+if\b/) { - $coff = $off + length($1) - 1; - $coff_set = 1; - #warn "CSB: mark coff<$coff> soff<$soff> 1<$1>\n"; - #warn "[" . substr($blk, $soff, $coff - $soff + 1) . "]\n"; - } - - if (($type eq '' || $type eq '(') && $c eq '(') { - $level++; - $type = '('; - } - if ($type eq '(' && $c eq ')') { - $level--; - $type = ($level != 0)? '(' : ''; - - if ($level == 0 && $coff < $soff) { - $coff = $off; - $coff_set = 1; - #warn "CSB: mark coff<$coff>\n"; - } - } - if (($type eq '' || $type eq '{') && $c eq '{') { - $level++; - $type = '{'; - } - if ($type eq '{' && $c eq '}') { - $level--; - $type = ($level != 0)? '{' : ''; - - if ($level == 0) { - if (substr($blk, $off + 1, 1) eq ';') { - $off++; - } - last; - } - } - # Preprocessor commands end at the newline unless escaped. - if ($type eq '#' && $c eq "\n" && $p ne "\\") { - $level--; - $type = ''; - $off++; - last; - } - $off++; - } - # We are truly at the end, so shuffle to the next line. - if ($off == $len) { - $loff = $len + 1; - $line++; - $remain--; - } - - my $statement = substr($blk, $soff, $off - $soff + 1); - my $condition = substr($blk, $soff, $coff - $soff + 1); - - #warn "STATEMENT<$statement>\n"; - #warn "CONDITION<$condition>\n"; - - #print "coff<$coff> soff<$off> loff<$loff>\n"; - - return ($statement, $condition, - $line, $remain + 1, $off - $loff + 1, $level); -} - -sub statement_lines { - my ($stmt) = @_; - - # Strip the diff line prefixes and rip blank lines at start and end. - $stmt =~ s/(^|\n)./$1/g; - $stmt =~ s/^\s*//; - $stmt =~ s/\s*$//; - - my @stmt_lines = ($stmt =~ /\n/g); - - return $#stmt_lines + 2; -} - -sub statement_rawlines { - my ($stmt) = @_; - - my @stmt_lines = ($stmt =~ /\n/g); - - return $#stmt_lines + 2; -} - -sub statement_block_size { - my ($stmt) = @_; - - $stmt =~ s/(^|\n)./$1/g; - $stmt =~ s/^\s*{//; - $stmt =~ s/}\s*$//; - $stmt =~ s/^\s*//; - $stmt =~ s/\s*$//; - - my @stmt_lines = ($stmt =~ /\n/g); - my @stmt_statements = ($stmt =~ /;/g); - - my $stmt_lines = $#stmt_lines + 2; - my $stmt_statements = $#stmt_statements + 1; - - if ($stmt_lines > $stmt_statements) { - return $stmt_lines; - } else { - return $stmt_statements; - } -} - -sub ctx_statement_full { - my ($linenr, $remain, $off) = @_; - my ($statement, $condition, $level); - - my (@chunks); - - # Grab the first conditional/block pair. - ($statement, $condition, $linenr, $remain, $off, $level) = - ctx_statement_block($linenr, $remain, $off); - #print "F: c<$condition> s<$statement> remain<$remain>\n"; - push(@chunks, [ $condition, $statement ]); - if (!($remain > 0 && $condition =~ /^\s*(?:\n[+-])?\s*(?:if|else|do)\b/s)) { - return ($level, $linenr, @chunks); - } - - # Pull in the following conditional/block pairs and see if they - # could continue the statement. - for (;;) { - ($statement, $condition, $linenr, $remain, $off, $level) = - ctx_statement_block($linenr, $remain, $off); - #print "C: c<$condition> s<$statement> remain<$remain>\n"; - last if (!($remain > 0 && $condition =~ /^(?:\s*\n[+-])*\s*(?:else|do)\b/s)); - #print "C: push\n"; - push(@chunks, [ $condition, $statement ]); - } - - return ($level, $linenr, @chunks); -} - -sub ctx_block_get { - my ($linenr, $remain, $outer, $open, $close, $off) = @_; - my $line; - my $start = $linenr - 1; - my $blk = ''; - my @o; - my @c; - my @res = (); - - my $level = 0; - my @stack = ($level); - for ($line = $start; $remain > 0; $line++) { - next if ($rawlines[$line] =~ /^-/); - $remain--; - - $blk .= $rawlines[$line]; - - # Handle nested #if/#else. - if ($lines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) { - push(@stack, $level); - } elsif ($lines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) { - $level = $stack[$#stack - 1]; - } elsif ($lines[$line] =~ /^.\s*#\s*endif\b/) { - $level = pop(@stack); - } - - foreach my $c (split(//, $lines[$line])) { - ##print "C<$c>L<$level><$open$close>O<$off>\n"; - if ($off > 0) { - $off--; - next; - } - - if ($c eq $close && $level > 0) { - $level--; - last if ($level == 0); - } elsif ($c eq $open) { - $level++; - } - } - - if (!$outer || $level <= 1) { - push(@res, $rawlines[$line]); - } - - last if ($level == 0); - } - - return ($level, @res); -} -sub ctx_block_outer { - my ($linenr, $remain) = @_; - - my ($level, @r) = ctx_block_get($linenr, $remain, 1, '{', '}', 0); - return @r; -} -sub ctx_block { - my ($linenr, $remain) = @_; - - my ($level, @r) = ctx_block_get($linenr, $remain, 0, '{', '}', 0); - return @r; -} -sub ctx_statement { - my ($linenr, $remain, $off) = @_; - - my ($level, @r) = ctx_block_get($linenr, $remain, 0, '(', ')', $off); - return @r; -} -sub ctx_block_level { - my ($linenr, $remain) = @_; - - return ctx_block_get($linenr, $remain, 0, '{', '}', 0); -} -sub ctx_statement_level { - my ($linenr, $remain, $off) = @_; - - return ctx_block_get($linenr, $remain, 0, '(', ')', $off); -} - -sub ctx_locate_comment { - my ($first_line, $end_line) = @_; - - # Catch a comment on the end of the line itself. - my ($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*(?:\\\s*)?$@); - return $current_comment if (defined $current_comment); - - # Look through the context and try and figure out if there is a - # comment. - my $in_comment = 0; - $current_comment = ''; - for (my $linenr = $first_line; $linenr < $end_line; $linenr++) { - my $line = $rawlines[$linenr - 1]; - #warn " $line\n"; - if ($linenr == $first_line and $line =~ m@^.\s*\*@) { - $in_comment = 1; - } - if ($line =~ m@/\*@) { - $in_comment = 1; - } - if (!$in_comment && $current_comment ne '') { - $current_comment = ''; - } - $current_comment .= $line . "\n" if ($in_comment); - if ($line =~ m@\*/@) { - $in_comment = 0; - } - } - - chomp($current_comment); - return($current_comment); -} -sub ctx_has_comment { - my ($first_line, $end_line) = @_; - my $cmt = ctx_locate_comment($first_line, $end_line); - - ##print "LINE: $rawlines[$end_line - 1 ]\n"; - ##print "CMMT: $cmt\n"; - - return ($cmt ne ''); -} - -sub raw_line { - my ($linenr, $cnt) = @_; - - my $offset = $linenr - 1; - $cnt++; - - my $line; - while ($cnt) { - $line = $rawlines[$offset++]; - next if (defined($line) && $line =~ /^-/); - $cnt--; - } - - return $line; -} - -sub cat_vet { - my ($vet) = @_; - my ($res, $coded); - - $res = ''; - while ($vet =~ /([^[:cntrl:]]*)([[:cntrl:]]|$)/g) { - $res .= $1; - if ($2 ne '') { - $coded = sprintf("^%c", unpack('C', $2) + 64); - $res .= $coded; - } - } - $res =~ s/$/\$/; - - return $res; -} - -my $av_preprocessor = 0; -my $av_pending; -my @av_paren_type; -my $av_pend_colon; - -sub annotate_reset { - $av_preprocessor = 0; - $av_pending = '_'; - @av_paren_type = ('E'); - $av_pend_colon = 'O'; -} - -sub annotate_values { - my ($stream, $type) = @_; - - my $res; - my $var = '_' x length($stream); - my $cur = $stream; - - print "$stream\n" if ($dbg_values > 1); - - while (length($cur)) { - @av_paren_type = ('E') if ($#av_paren_type < 0); - print " <" . join('', @av_paren_type) . - "> <$type> <$av_pending>" if ($dbg_values > 1); - if ($cur =~ /^(\s+)/o) { - print "WS($1)\n" if ($dbg_values > 1); - if ($1 =~ /\n/ && $av_preprocessor) { - $type = pop(@av_paren_type); - $av_preprocessor = 0; - } - - } elsif ($cur =~ /^(\(\s*$Type\s*)\)/ && $av_pending eq '_') { - print "CAST($1)\n" if ($dbg_values > 1); - push(@av_paren_type, $type); - $type = 'c'; - - } elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\(|\s*$)/) { - print "DECLARE($1)\n" if ($dbg_values > 1); - $type = 'T'; - - } elsif ($cur =~ /^($Modifier)\s*/) { - print "MODIFIER($1)\n" if ($dbg_values > 1); - $type = 'T'; - - } elsif ($cur =~ /^(\#\s*define\s*$Ident)(\(?)/o) { - print "DEFINE($1,$2)\n" if ($dbg_values > 1); - $av_preprocessor = 1; - push(@av_paren_type, $type); - if ($2 ne '') { - $av_pending = 'N'; - } - $type = 'E'; - - } elsif ($cur =~ /^(\#\s*(?:undef\s*$Ident|include\b))/o) { - print "UNDEF($1)\n" if ($dbg_values > 1); - $av_preprocessor = 1; - push(@av_paren_type, $type); - - } elsif ($cur =~ /^(\#\s*(?:ifdef|ifndef|if))/o) { - print "PRE_START($1)\n" if ($dbg_values > 1); - $av_preprocessor = 1; - - push(@av_paren_type, $type); - push(@av_paren_type, $type); - $type = 'E'; - - } elsif ($cur =~ /^(\#\s*(?:else|elif))/o) { - print "PRE_RESTART($1)\n" if ($dbg_values > 1); - $av_preprocessor = 1; - - push(@av_paren_type, $av_paren_type[$#av_paren_type]); - - $type = 'E'; - - } elsif ($cur =~ /^(\#\s*(?:endif))/o) { - print "PRE_END($1)\n" if ($dbg_values > 1); - - $av_preprocessor = 1; - - # Assume all arms of the conditional end as this - # one does, and continue as if the #endif was not here. - pop(@av_paren_type); - push(@av_paren_type, $type); - $type = 'E'; - - } elsif ($cur =~ /^(\\\n)/o) { - print "PRECONT($1)\n" if ($dbg_values > 1); - - } elsif ($cur =~ /^(__attribute__)\s*\(?/o) { - print "ATTR($1)\n" if ($dbg_values > 1); - $av_pending = $type; - $type = 'N'; - - } elsif ($cur =~ /^(sizeof)\s*(\()?/o) { - print "SIZEOF($1)\n" if ($dbg_values > 1); - if (defined $2) { - $av_pending = 'V'; - } - $type = 'N'; - - } elsif ($cur =~ /^(if|while|for)\b/o) { - print "COND($1)\n" if ($dbg_values > 1); - $av_pending = 'E'; - $type = 'N'; - - } elsif ($cur =~/^(case)/o) { - print "CASE($1)\n" if ($dbg_values > 1); - $av_pend_colon = 'C'; - $type = 'N'; - - } elsif ($cur =~/^(return|else|goto|typeof|__typeof__)\b/o) { - print "KEYWORD($1)\n" if ($dbg_values > 1); - $type = 'N'; - - } elsif ($cur =~ /^(\()/o) { - print "PAREN('$1')\n" if ($dbg_values > 1); - push(@av_paren_type, $av_pending); - $av_pending = '_'; - $type = 'N'; - - } elsif ($cur =~ /^(\))/o) { - my $new_type = pop(@av_paren_type); - if ($new_type ne '_') { - $type = $new_type; - print "PAREN('$1') -> $type\n" - if ($dbg_values > 1); - } else { - print "PAREN('$1')\n" if ($dbg_values > 1); - } - - } elsif ($cur =~ /^($Ident)\s*\(/o) { - print "FUNC($1)\n" if ($dbg_values > 1); - $type = 'V'; - $av_pending = 'V'; - - } elsif ($cur =~ /^($Ident\s*):(?:\s*\d+\s*(,|=|;))?/) { - if (defined $2 && $type eq 'C' || $type eq 'T') { - $av_pend_colon = 'B'; - } elsif ($type eq 'E') { - $av_pend_colon = 'L'; - } - print "IDENT_COLON($1,$type>$av_pend_colon)\n" if ($dbg_values > 1); - $type = 'V'; - - } elsif ($cur =~ /^($Ident|$Constant)/o) { - print "IDENT($1)\n" if ($dbg_values > 1); - $type = 'V'; - - } elsif ($cur =~ /^($Assignment)/o) { - print "ASSIGN($1)\n" if ($dbg_values > 1); - $type = 'N'; - - } elsif ($cur =~/^(;|{|})/) { - print "END($1)\n" if ($dbg_values > 1); - $type = 'E'; - $av_pend_colon = 'O'; - - } elsif ($cur =~/^(,)/) { - print "COMMA($1)\n" if ($dbg_values > 1); - $type = 'C'; - - } elsif ($cur =~ /^(\?)/o) { - print "QUESTION($1)\n" if ($dbg_values > 1); - $type = 'N'; - - } elsif ($cur =~ /^(:)/o) { - print "COLON($1,$av_pend_colon)\n" if ($dbg_values > 1); - - substr($var, length($res), 1, $av_pend_colon); - if ($av_pend_colon eq 'C' || $av_pend_colon eq 'L') { - $type = 'E'; - } else { - $type = 'N'; - } - $av_pend_colon = 'O'; - - } elsif ($cur =~ /^(\[)/o) { - print "CLOSE($1)\n" if ($dbg_values > 1); - $type = 'N'; - - } elsif ($cur =~ /^(-(?![->])|\+(?!\+)|\*|\&\&|\&)/o) { - my $variant; - - print "OPV($1)\n" if ($dbg_values > 1); - if ($type eq 'V') { - $variant = 'B'; - } else { - $variant = 'U'; - } - - substr($var, length($res), 1, $variant); - $type = 'N'; - - } elsif ($cur =~ /^($Operators)/o) { - print "OP($1)\n" if ($dbg_values > 1); - if ($1 ne '++' && $1 ne '--') { - $type = 'N'; - } - - } elsif ($cur =~ /(^.)/o) { - print "C($1)\n" if ($dbg_values > 1); - } - if (defined $1) { - $cur = substr($cur, length($1)); - $res .= $type x length($1); - } - } - - return ($res, $var); -} - -sub possible { - my ($possible, $line) = @_; - my $notPermitted = qr{(?: - ^(?: - $Modifier| - $Storage| - $Type| - DEFINE_\S+ - )$| - ^(?: - goto| - return| - case| - else| - asm|__asm__| - do| - \#| - \#\#| - )(?:\s|$)| - ^(?:typedef|struct|enum)\b - )}x; - warn "CHECK<$possible> ($line)\n" if ($dbg_possible > 2); - if ($possible !~ $notPermitted) { - # Check for modifiers. - $possible =~ s/\s*$Storage\s*//g; - $possible =~ s/\s*$Sparse\s*//g; - if ($possible =~ /^\s*$/) { - - } elsif ($possible =~ /\s/) { - $possible =~ s/\s*$Type\s*//g; - for my $modifier (split(' ', $possible)) { - if ($modifier !~ $notPermitted) { - warn "MODIFIER: $modifier ($possible) ($line)\n" if ($dbg_possible); - push(@modifierListFile, $modifier); - } - } - - } else { - warn "POSSIBLE: $possible ($line)\n" if ($dbg_possible); - push(@typeListFile, $possible); - } - build_types(); - } else { - warn "NOTPOSS: $possible ($line)\n" if ($dbg_possible > 1); - } -} - -my $prefix = ''; - -sub show_type { - my ($type) = @_; - - return defined $use_type{$type} if (scalar keys %use_type > 0); - - return !defined $ignore_type{$type}; -} - -sub report { - my ($level, $type, $msg) = @_; - - if (!show_type($type) || - (defined $tst_only && $msg !~ /\Q$tst_only\E/)) { - return 0; - } - my $output = ''; - if (-t STDOUT && $color) { - if ($level eq 'ERROR') { - $output .= RED; - } elsif ($level eq 'WARNING') { - $output .= YELLOW; - } else { - $output .= GREEN; - } - } - $output .= $prefix . $level . ':'; - if ($show_types) { - $output .= BLUE if (-t STDOUT && $color); - $output .= "$type:"; - } - $output .= RESET if (-t STDOUT && $color); - $output .= ' ' . $msg . "\n"; - - if ($showfile) { - my @lines = split("\n", $output, -1); - splice(@lines, 1, 1); - $output = join("\n", @lines); - } - $output = (split('\n', $output))[0] . "\n" if ($terse); - - push(our @report, $output); - - return 1; -} - -sub report_dump { - our @report; -} - -sub fixup_current_range { - my ($lineRef, $offset, $length) = @_; - - if ($$lineRef =~ /^\@\@ -\d+,\d+ \+(\d+),(\d+) \@\@/) { - my $o = $1; - my $l = $2; - my $no = $o + $offset; - my $nl = $l + $length; - $$lineRef =~ s/\+$o,$l \@\@/\+$no,$nl \@\@/; - } -} - -sub fix_inserted_deleted_lines { - my ($linesRef, $insertedRef, $deletedRef) = @_; - - my $range_last_linenr = 0; - my $delta_offset = 0; - - my $old_linenr = 0; - my $new_linenr = 0; - - my $next_insert = 0; - my $next_delete = 0; - - my @lines = (); - - my $inserted = @{$insertedRef}[$next_insert++]; - my $deleted = @{$deletedRef}[$next_delete++]; - - foreach my $old_line (@{$linesRef}) { - my $save_line = 1; - my $line = $old_line; #don't modify the array - if ($line =~ /^(?:\+\+\+|\-\-\-)\s+\S+/) { #new filename - $delta_offset = 0; - } elsif ($line =~ /^\@\@ -\d+,\d+ \+\d+,\d+ \@\@/) { #new hunk - $range_last_linenr = $new_linenr; - fixup_current_range(\$line, $delta_offset, 0); - } - - while (defined($deleted) && ${$deleted}{'LINENR'} == $old_linenr) { - $deleted = @{$deletedRef}[$next_delete++]; - $save_line = 0; - fixup_current_range(\$lines[$range_last_linenr], $delta_offset--, -1); - } - - while (defined($inserted) && ${$inserted}{'LINENR'} == $old_linenr) { - push(@lines, ${$inserted}{'LINE'}); - $inserted = @{$insertedRef}[$next_insert++]; - $new_linenr++; - fixup_current_range(\$lines[$range_last_linenr], $delta_offset++, 1); - } - - if ($save_line) { - push(@lines, $line); - $new_linenr++; - } - - $old_linenr++; - } - - return @lines; -} - -sub fix_insert_line { - my ($linenr, $line) = @_; - - my $inserted = { - LINENR => $linenr, - LINE => $line, - }; - push(@fixed_inserted, $inserted); -} - -sub fix_delete_line { - my ($linenr, $line) = @_; - - my $deleted = { - LINENR => $linenr, - LINE => $line, - }; - - push(@fixed_deleted, $deleted); -} - -sub ERROR { - my ($type, $msg) = @_; - - if (report("ERROR", $type, $msg)) { - our $clean = 0; - our $cnt_error++; - return 1; - } - return 0; -} -sub WARN { - my ($type, $msg) = @_; - - if (report("WARNING", $type, $msg)) { - our $clean = 0; - our $cnt_warn++; - return 1; - } - return 0; -} -sub CHK { - my ($type, $msg) = @_; - - if ($check && report("CHECK", $type, $msg)) { - our $clean = 0; - our $cnt_chk++; - return 1; - } - return 0; -} - -sub check_absolute_file { - my ($absolute, $herecurr) = @_; - my $file = $absolute; - - ##print "absolute<$absolute>\n"; - - # See if any suffix of this path is a path within the tree. - while ($file =~ s@^[^/]*/@@) { - if (-f "$root/$file") { - ##print "file<$file>\n"; - last; - } - } - if (! -f _) { - return 0; - } - - # It is, so see if the prefix is acceptable. - my $prefix = $absolute; - substr($prefix, -length($file)) = ''; - - ##print "prefix<$prefix>\n"; - if ($prefix ne ".../") { - WARN("USE_RELATIVE_PATH", - "use relative pathname instead of absolute in changelog text\n" . $herecurr); - } -} - -sub trim { - my ($string) = @_; - - $string =~ s/^\s+|\s+$//g; - - return $string; -} - -sub ltrim { - my ($string) = @_; - - $string =~ s/^\s+//; - - return $string; -} - -sub rtrim { - my ($string) = @_; - - $string =~ s/\s+$//; - - return $string; -} - -sub string_find_replace { - my ($string, $find, $replace) = @_; - - $string =~ s/$find/$replace/g; - - return $string; -} - -sub tabify { - my ($leading) = @_; - - my $source_indent = 8; - my $max_spaces_before_tab = $source_indent - 1; - my $spaces_to_tab = " " x $source_indent; - - #convert leading spaces to tabs - 1 while $leading =~ s@^([\t]*)$spaces_to_tab@$1\t@g; - #Remove spaces before a tab - 1 while $leading =~ s@^([\t]*)( {1,$max_spaces_before_tab})\t@$1\t@g; - - return "$leading"; -} - -sub pos_last_openparen { - my ($line) = @_; - - my $pos = 0; - - my $opens = $line =~ tr/\(/\(/; - my $closes = $line =~ tr/\)/\)/; - - my $last_openparen = 0; - - if (($opens == 0) || ($closes >= $opens)) { - return -1; - } - - my $len = length($line); - - for ($pos = 0; $pos < $len; $pos++) { - my $string = substr($line, $pos); - if ($string =~ /^($FuncArg|$balanced_parens)/) { - $pos += length($1) - 1; - } elsif (substr($line, $pos, 1) eq '(') { - $last_openparen = $pos; - } elsif (index($string, '(') == -1) { - last; - } - } - - return length(expand_tabs(substr($line, 0, $last_openparen))) + 1; -} - -sub process { - my $filename = shift; - - my $linenr=0; - my $prevline=""; - my $prevrawline=""; - my $stashline=""; - my $stashrawline=""; - - my $length; - my $indent; - my $previndent=0; - my $stashindent=0; - - our $clean = 1; - my $signoff = 0; - my $is_patch = 0; - my $in_header_lines = $file ? 0 : 1; - my $in_commit_log = 0; #Scanning lines before patch - my $commit_log_possible_stack_dump = 0; - my $commit_log_long_line = 0; - my $commit_log_has_diff = 0; - my $reported_maintainer_file = 0; - my $non_utf8_charset = 0; - - my $last_blank_line = 0; - my $last_coalesced_string_linenr = -1; - - our @report = (); - our $cnt_lines = 0; - our $cnt_error = 0; - our $cnt_warn = 0; - our $cnt_chk = 0; - - # Trace the real file/line as we go. - my $realfile = ''; - my $realline = 0; - my $realcnt = 0; - my $here = ''; - my $in_comment = 0; - my $comment_edge = 0; - my $first_line = 0; - my $p1_prefix = ''; - - my $prev_values = 'E'; - - # suppression flags - my %suppress_ifbraces; - my %suppress_whiletrailers; - my %suppress_export; - my $suppress_statement = 0; - - my %signatures = (); - - # Pre-scan the patch sanitizing the lines. - # Pre-scan the patch looking for any __setup documentation. - # - my @setup_docs = (); - my $setup_docs = 0; - - my $camelcase_file_seeded = 0; - - sanitise_line_reset(); - my $line; - foreach my $rawline (@rawlines) { - $linenr++; - $line = $rawline; - - push(@fixed, $rawline) if ($fix); - - if ($rawline=~/^\+\+\+\s+(\S+)/) { - $setup_docs = 0; - if ($1 =~ m@Documentation/kernel-parameters.txt$@) { - $setup_docs = 1; - } - #next; - } - if ($rawline=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) { - $realline=$1-1; - if (defined $2) { - $realcnt=$3+1; - } else { - $realcnt=1+1; - } - $in_comment = 0; - - # Guestimate if this is a continuing comment. Run - # the context looking for a comment "edge". If this - # edge is a close comment then we must be in a comment - # at context start. - my $edge; - my $cnt = $realcnt; - for (my $ln = $linenr + 1; $cnt > 0; $ln++) { - next if (defined $rawlines[$ln - 1] && - $rawlines[$ln - 1] =~ /^-/); - $cnt--; - #print "RAW<$rawlines[$ln - 1]>\n"; - last if (!defined $rawlines[$ln - 1]); - if ($rawlines[$ln - 1] =~ m@(/\*|\*/)@ && - $rawlines[$ln - 1] !~ m@"[^"]*(?:/\*|\*/)[^"]*"@) { - ($edge) = $1; - last; - } - } - if (defined $edge && $edge eq '*/') { - $in_comment = 1; - } - - # Guestimate if this is a continuing comment. If this - # is the start of a diff block and this line starts - # ' *' then it is very likely a comment. - if (!defined $edge && - $rawlines[$linenr] =~ m@^.\s*(?:\*\*+| \*)(?:\s|$)@) - { - $in_comment = 1; - } - - ##print "COMMENT:$in_comment edge<$edge> $rawline\n"; - sanitise_line_reset($in_comment); - - } elsif ($realcnt && $rawline =~ /^(?:\+| |$)/) { - # Standardise the strings and chars within the input to - # simplify matching -- only bother with positive lines. - $line = sanitise_line($rawline); - } - push(@lines, $line); - - if ($realcnt > 1) { - $realcnt-- if ($line =~ /^(?:\+| |$)/); - } else { - $realcnt = 0; - } - - #print "==>$rawline\n"; - #print "-->$line\n"; - - if ($setup_docs && $line =~ /^\+/) { - push(@setup_docs, $line); - } - } - - $prefix = ''; - - $realcnt = 0; - $linenr = 0; - $fixlinenr = -1; - foreach my $line (@lines) { - $linenr++; - $fixlinenr++; - my $sline = $line; #copy of $line - $sline =~ s/$;/ /g; #with comments as spaces - - my $rawline = $rawlines[$linenr - 1]; - -#extract the line range in the file after the patch is applied - if (!$in_commit_log && - $line =~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) { - $is_patch = 1; - $first_line = $linenr + 1; - $realline=$1-1; - if (defined $2) { - $realcnt=$3+1; - } else { - $realcnt=1+1; - } - annotate_reset(); - $prev_values = 'E'; - - %suppress_ifbraces = (); - %suppress_whiletrailers = (); - %suppress_export = (); - $suppress_statement = 0; - next; - -# track the line number as we move through the hunk, note that -# new versions of GNU diff omit the leading space on completely -# blank context lines so we need to count that too. - } elsif ($line =~ /^( |\+|$)/) { - $realline++; - $realcnt-- if ($realcnt != 0); - - # Measure the line length and indent. - ($length, $indent) = line_stats($rawline); - - # Track the previous line. - ($prevline, $stashline) = ($stashline, $line); - ($previndent, $stashindent) = ($stashindent, $indent); - ($prevrawline, $stashrawline) = ($stashrawline, $rawline); - - #warn "line<$line>\n"; - - } elsif ($realcnt == 1) { - $realcnt--; - } - - my $hunk_line = ($realcnt != 0); - - $here = "#$linenr: " if (!$file); - $here = "#$realline: " if ($file); - - my $found_file = 0; - # extract the filename as it passes - if ($line =~ /^diff --git.*?(\S+)$/) { - $realfile = $1; - $realfile =~ s@^([^/]*)/@@ if (!$file); - $in_commit_log = 0; - $found_file = 1; - } elsif ($line =~ /^\+\+\+\s+(\S+)/) { - $realfile = $1; - $realfile =~ s@^([^/]*)/@@ if (!$file); - $in_commit_log = 0; - - $p1_prefix = $1; - if (!$file && $tree && $p1_prefix ne '' && - -e "$root/$p1_prefix") { - WARN("PATCH_PREFIX", - "patch prefix '$p1_prefix' exists, appears to be a -p0 patch\n"); - } - - if ($realfile =~ m@^include/asm/@) { - ERROR("MODIFIED_INCLUDE_ASM", - "do not modify files in include/asm, change architecture specific files in include/asm-<architecture>\n" . "$here$rawline\n"); - } - $found_file = 1; - } - -#make up the handle for any error we report on this line - if ($showfile) { - $prefix = "$realfile:$realline: " - } elsif ($emacs) { - if ($file) { - $prefix = "$filename:$realline: "; - } else { - $prefix = "$filename:$linenr: "; - } - } - - if ($found_file) { - if ($realfile =~ m@^(?:drivers/net/|net/|drivers/staging/)@) { - $check = 1; - } else { - $check = $check_orig; - } - next; - } - - $here .= "FILE: $realfile:$realline:" if ($realcnt != 0); - - my $hereline = "$here\n$rawline\n"; - my $herecurr = "$here\n$rawline\n"; - my $hereprev = "$here\n$prevrawline\n$rawline\n"; - - $cnt_lines++ if ($realcnt != 0); - -# Check if the commit log has what seems like a diff which can confuse patch - if ($in_commit_log && !$commit_log_has_diff && - (($line =~ m@^\s+diff\b.*a/[\w/]+@ && - $line =~ m@^\s+diff\b.*a/([\w/]+)\s+b/$1\b@) || - $line =~ m@^\s*(?:\-\-\-\s+a/|\+\+\+\s+b/)@ || - $line =~ m/^\s*\@\@ \-\d+,\d+ \+\d+,\d+ \@\@/)) { - ERROR("DIFF_IN_COMMIT_MSG", - "Avoid using diff content in the commit message - patch(1) might not work\n" . $herecurr); - $commit_log_has_diff = 1; - } - -# Check for incorrect file permissions - if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) { - my $permhere = $here . "FILE: $realfile\n"; - if ($realfile !~ m@scripts/@ && - $realfile !~ /\.(py|pl|awk|sh)$/) { - ERROR("EXECUTE_PERMISSIONS", - "do not set execute permissions for source files\n" . $permhere); - } - } - -# Check the patch for a signoff: - if ($line =~ /^\s*signed-off-by:/i) { - $signoff++; - $in_commit_log = 0; - } - -# Check if MAINTAINERS is being updated. If so, there's probably no need to -# emit the "does MAINTAINERS need updating?" message on file add/move/delete - if ($line =~ /^\s*MAINTAINERS\s*\|/) { - $reported_maintainer_file = 1; - } - -# Check signature styles - if (!$in_header_lines && - $line =~ /^(\s*)([a-z0-9_-]+by:|$signature_tags)(\s*)(.*)/i) { - my $space_before = $1; - my $sign_off = $2; - my $space_after = $3; - my $email = $4; - my $ucfirst_sign_off = ucfirst(lc($sign_off)); - - if ($sign_off !~ /$signature_tags/) { - WARN("BAD_SIGN_OFF", - "Non-standard signature: $sign_off\n" . $herecurr); - } - if (defined $space_before && $space_before ne "") { - if (WARN("BAD_SIGN_OFF", - "Do not use whitespace before $ucfirst_sign_off\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] = - "$ucfirst_sign_off $email"; - } - } - if ($sign_off =~ /-by:$/i && $sign_off ne $ucfirst_sign_off) { - if (WARN("BAD_SIGN_OFF", - "'$ucfirst_sign_off' is the preferred signature form\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] = - "$ucfirst_sign_off $email"; - } - - } - if (!defined $space_after || $space_after ne " ") { - if (WARN("BAD_SIGN_OFF", - "Use a single space after $ucfirst_sign_off\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] = - "$ucfirst_sign_off $email"; - } - } - - my ($email_name, $email_address, $comment) = parse_email($email); - my $suggested_email = format_email(($email_name, $email_address)); - if ($suggested_email eq "") { - ERROR("BAD_SIGN_OFF", - "Unrecognized email address: '$email'\n" . $herecurr); - } else { - my $dequoted = $suggested_email; - $dequoted =~ s/^"//; - $dequoted =~ s/" </ </; - # Don't force email to have quotes - # Allow just an angle bracketed address - if ("$dequoted$comment" ne $email && - "<$email_address>$comment" ne $email && - "$suggested_email$comment" ne $email) { - WARN("BAD_SIGN_OFF", - "email address '$email' might be better as '$suggested_email$comment'\n" . $herecurr); - } - } - -# Check for duplicate signatures - my $sig_nospace = $line; - $sig_nospace =~ s/\s//g; - $sig_nospace = lc($sig_nospace); - if (defined $signatures{$sig_nospace}) { - WARN("BAD_SIGN_OFF", - "Duplicate signature\n" . $herecurr); - } else { - $signatures{$sig_nospace} = 1; - } - } - -# Check email subject for common tools that don't need to be mentioned - if ($in_header_lines && - $line =~ /^Subject:.*\b(?:checkpatch|sparse|smatch)\b[^:]/i) { - WARN("EMAIL_SUBJECT", - "A patch subject line should describe the change not the tool that found it\n" . $herecurr); - } - -# Check for old stable address - if ($line =~ /^\s*cc:\s*.*<?\bstable\@kernel\.org\b>?.*$/i) { - ERROR("STABLE_ADDRESS", - "The 'stable' address should be 'stable\@vger.kernel.org'\n" . $herecurr); - } - -# Check for unwanted Gerrit info - if ($in_commit_log && $line =~ /^\s*change-id:/i) { - ERROR("GERRIT_CHANGE_ID", - "Remove Gerrit Change-Id's before submitting upstream.\n" . $herecurr); - } - -# Check if the commit log is in a possible stack dump - if ($in_commit_log && !$commit_log_possible_stack_dump && - ($line =~ /^\s*(?:WARNING:|BUG:)/ || - $line =~ /^\s*\[\s*\d+\.\d{6,6}\s*\]/ || - # timestamp - $line =~ /^\s*\[\<[0-9a-fA-F]{8,}\>\]/)) { - # stack dump address - $commit_log_possible_stack_dump = 1; - } - -# Check for line lengths > 75 in commit log, warn once - if ($in_commit_log && !$commit_log_long_line && - length($line) > 75 && - !($line =~ /^\s*[a-zA-Z0-9_\/\.]+\s+\|\s+\d+/ || - # file delta changes - $line =~ /^\s*(?:[\w\.\-]+\/)++[\w\.\-]+:/ || - # filename then : - $line =~ /^\s*(?:Fixes:|Link:)/i || - # A Fixes: or Link: line - $commit_log_possible_stack_dump)) { - WARN("COMMIT_LOG_LONG_LINE", - "Possible unwrapped commit description (prefer a maximum 75 chars per line)\n" . $herecurr); - $commit_log_long_line = 1; - } - -# Reset possible stack dump if a blank line is found - if ($in_commit_log && $commit_log_possible_stack_dump && - $line =~ /^\s*$/) { - $commit_log_possible_stack_dump = 0; - } - -# Check for git id commit length and improperly formed commit descriptions - if ($in_commit_log && !$commit_log_possible_stack_dump && - ($line =~ /\bcommit\s+[0-9a-f]{5,}\b/i || - ($line =~ /\b[0-9a-f]{12,40}\b/i && - $line !~ /[\<\[][0-9a-f]{12,40}[\>\]]/i && - $line !~ /\bfixes:\s*[0-9a-f]{12,40}/i))) { - my $init_char = "c"; - my $orig_commit = ""; - my $short = 1; - my $long = 0; - my $case = 1; - my $space = 1; - my $hasdesc = 0; - my $hasparens = 0; - my $id = '0123456789ab'; - my $orig_desc = "commit description"; - my $description = ""; - - if ($line =~ /\b(c)ommit\s+([0-9a-f]{5,})\b/i) { - $init_char = $1; - $orig_commit = lc($2); - } elsif ($line =~ /\b([0-9a-f]{12,40})\b/i) { - $orig_commit = lc($1); - } - - $short = 0 if ($line =~ /\bcommit\s+[0-9a-f]{12,40}/i); - $long = 1 if ($line =~ /\bcommit\s+[0-9a-f]{41,}/i); - $space = 0 if ($line =~ /\bcommit [0-9a-f]/i); - $case = 0 if ($line =~ /\b[Cc]ommit\s+[0-9a-f]{5,40}[^A-F]/); - if ($line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("([^"]+)"\)/i) { - $orig_desc = $1; - $hasparens = 1; - } elsif ($line =~ /\bcommit\s+[0-9a-f]{5,}\s*$/i && - defined $rawlines[$linenr] && - $rawlines[$linenr] =~ /^\s*\("([^"]+)"\)/) { - $orig_desc = $1; - $hasparens = 1; - } elsif ($line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("[^"]+$/i && - defined $rawlines[$linenr] && - $rawlines[$linenr] =~ /^\s*[^"]+"\)/) { - $line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("([^"]+)$/i; - $orig_desc = $1; - $rawlines[$linenr] =~ /^\s*([^"]+)"\)/; - $orig_desc .= " " . $1; - $hasparens = 1; - } - - ($id, $description) = git_commit_info($orig_commit, - $id, $orig_desc); - - if ($short || $long || $space || $case || ($orig_desc ne $description) || !$hasparens) { - ERROR("GIT_COMMIT_ID", - "Please use git commit description style 'commit <12+ chars of sha1> (\"<title line>\")' - ie: '${init_char}ommit $id (\"$description\")'\n" . $herecurr); - } - } - -# Check for added, moved or deleted files - if (!$reported_maintainer_file && !$in_commit_log && - ($line =~ /^(?:new|deleted) file mode\s*\d+\s*$/ || - $line =~ /^rename (?:from|to) [\w\/\.\-]+\s*$/ || - ($line =~ /\{\s*([\w\/\.\-]*)\s*\=\>\s*([\w\/\.\-]*)\s*\}/ && - (defined($1) || defined($2))))) { - $reported_maintainer_file = 1; - WARN("FILE_PATH_CHANGES", - "added, moved or deleted file(s), does MAINTAINERS need updating?\n" . $herecurr); - } - -# Check for wrappage within a valid hunk of the file - if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) { - ERROR("CORRUPTED_PATCH", - "patch seems to be corrupt (line wrapped?)\n" . - $herecurr) if (!$emitted_corrupt++); - } - -# Check for absolute kernel paths. - if ($tree) { - while ($line =~ m{(?:^|\s)(/\S*)}g) { - my $file = $1; - - if ($file =~ m{^(.*?)(?::\d+)+:?$} && - check_absolute_file($1, $herecurr)) { - # - } else { - check_absolute_file($file, $herecurr); - } - } - } - -# UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php - if (($realfile =~ /^$/ || $line =~ /^\+/) && - $rawline !~ m/^$UTF8*$/) { - my ($utf8_prefix) = ($rawline =~ /^($UTF8*)/); - - my $blank = copy_spacing($rawline); - my $ptr = substr($blank, 0, length($utf8_prefix)) . "^"; - my $hereptr = "$hereline$ptr\n"; - - CHK("INVALID_UTF8", - "Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $hereptr); - } - -# Check if it's the start of a commit log -# (not a header line and we haven't seen the patch filename) - if ($in_header_lines && $realfile =~ /^$/ && - !($rawline =~ /^\s+\S/ || - $rawline =~ /^(commit\b|from\b|[\w-]+:).*$/i)) { - $in_header_lines = 0; - $in_commit_log = 1; - } - -# Check if there is UTF-8 in a commit log when a mail header has explicitly -# declined it, i.e defined some charset where it is missing. - if ($in_header_lines && - $rawline =~ /^Content-Type:.+charset="(.+)".*$/ && - $1 !~ /utf-8/i) { - $non_utf8_charset = 1; - } - - if ($in_commit_log && $non_utf8_charset && $realfile =~ /^$/ && - $rawline =~ /$NON_ASCII_UTF8/) { - WARN("UTF8_BEFORE_PATCH", - "8-bit UTF-8 used in possible commit log\n" . $herecurr); - } - -# Check for various typo / spelling mistakes - if (defined($misspellings) && - ($in_commit_log || $line =~ /^(?:\+|Subject:)/i)) { - while ($rawline =~ /(?:^|[^a-z@])($misspellings)(?:\b|$|[^a-z@])/gi) { - my $typo = $1; - my $typo_fix = $spelling_fix{lc($typo)}; - $typo_fix = ucfirst($typo_fix) if ($typo =~ /^[A-Z]/); - $typo_fix = uc($typo_fix) if ($typo =~ /^[A-Z]+$/); - my $msg_type = \&WARN; - $msg_type = \&CHK if ($file); - if (&{$msg_type}("TYPO_SPELLING", - "'$typo' may be misspelled - perhaps '$typo_fix'?\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/(^|[^A-Za-z@])($typo)($|[^A-Za-z@])/$1$typo_fix$3/; - } - } - } - -# ignore non-hunk lines and lines being removed - next if (!$hunk_line || $line =~ /^-/); - -#trailing whitespace - if ($line =~ /^\+.*\015/) { - my $herevet = "$here\n" . cat_vet($rawline) . "\n"; - if (ERROR("DOS_LINE_ENDINGS", - "DOS line endings\n" . $herevet) && - $fix) { - $fixed[$fixlinenr] =~ s/[\s\015]+$//; - } - } elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) { - my $herevet = "$here\n" . cat_vet($rawline) . "\n"; - if (ERROR("TRAILING_WHITESPACE", - "trailing whitespace\n" . $herevet) && - $fix) { - $fixed[$fixlinenr] =~ s/\s+$//; - } - - $rpt_cleaners = 1; - } - -# Check for FSF mailing addresses. - if ($rawline =~ /\bwrite to the Free/i || - $rawline =~ /\b59\s+Temple\s+Pl/i || - $rawline =~ /\b51\s+Franklin\s+St/i) { - my $herevet = "$here\n" . cat_vet($rawline) . "\n"; - my $msg_type = \&ERROR; - $msg_type = \&CHK if ($file); - &{$msg_type}("FSF_MAILING_ADDRESS", - "Do not include the paragraph about writing to the Free Software Foundation's mailing address from the sample GPL notice. The FSF has changed addresses in the past, and may do so again. Linux already includes a copy of the GPL.\n" . $herevet) - } - -# check for Kconfig help text having a real description -# Only applies when adding the entry originally, after that we do not have -# sufficient context to determine whether it is indeed long enough. - if ($realfile =~ /Kconfig/ && - $line =~ /^\+\s*config\s+/) { - my $length = 0; - my $cnt = $realcnt; - my $ln = $linenr + 1; - my $f; - my $is_start = 0; - my $is_end = 0; - for (; $cnt > 0 && defined $lines[$ln - 1]; $ln++) { - $f = $lines[$ln - 1]; - $cnt-- if ($lines[$ln - 1] !~ /^-/); - $is_end = $lines[$ln - 1] =~ /^\+/; - - next if ($f =~ /^-/); - last if (!$file && $f =~ /^\@\@/); - - if ($lines[$ln - 1] =~ /^\+\s*(?:bool|tristate)\s*\"/) { - $is_start = 1; - } elsif ($lines[$ln - 1] =~ /^\+\s*(?:---)?help(?:---)?$/) { - $length = -1; - } - - $f =~ s/^.//; - $f =~ s/#.*//; - $f =~ s/^\s+//; - next if ($f =~ /^$/); - if ($f =~ /^\s*config\s/) { - $is_end = 1; - last; - } - $length++; - } - if ($is_start && $is_end && $length < $min_conf_desc_length) { - WARN("CONFIG_DESCRIPTION", - "please write a paragraph that describes the config symbol fully\n" . $herecurr); - } - #print "is_start<$is_start> is_end<$is_end> length<$length>\n"; - } - -# discourage the addition of CONFIG_EXPERIMENTAL in Kconfig. - if ($realfile =~ /Kconfig/ && - $line =~ /.\s*depends on\s+.*\bEXPERIMENTAL\b/) { - WARN("CONFIG_EXPERIMENTAL", - "Use of CONFIG_EXPERIMENTAL is deprecated. For alternatives, see https://lkml.org/lkml/2012/10/23/580\n"); - } - -# discourage the use of boolean for type definition attributes of Kconfig options - if ($realfile =~ /Kconfig/ && - $line =~ /^\+\s*\bboolean\b/) { - WARN("CONFIG_TYPE_BOOLEAN", - "Use of boolean is deprecated, please use bool instead.\n" . $herecurr); - } - - if (($realfile =~ /Makefile.*/ || $realfile =~ /Kbuild.*/) && - ($line =~ /\+(EXTRA_[A-Z]+FLAGS).*/)) { - my $flag = $1; - my $replacement = { - 'EXTRA_AFLAGS' => 'asflags-y', - 'EXTRA_CFLAGS' => 'ccflags-y', - 'EXTRA_CPPFLAGS' => 'cppflags-y', - 'EXTRA_LDFLAGS' => 'ldflags-y', - }; - - WARN("DEPRECATED_VARIABLE", - "Use of $flag is deprecated, please use \`$replacement->{$flag} instead.\n" . $herecurr) if ($replacement->{$flag}); - } - -# check for DT compatible documentation - if (defined $root && - (($realfile =~ /\.dtsi?$/ && $line =~ /^\+\s*compatible\s*=\s*\"/) || - ($realfile =~ /\.[ch]$/ && $line =~ /^\+.*\.compatible\s*=\s*\"/))) { - - my @compats = $rawline =~ /\"([a-zA-Z0-9\-\,\.\+_]+)\"/g; - - my $dt_path = $root . "/Documentation/devicetree/bindings/"; - my $vp_file = $dt_path . "vendor-prefixes.txt"; - - foreach my $compat (@compats) { - my $compat2 = $compat; - $compat2 =~ s/\,[a-zA-Z0-9]*\-/\,<\.\*>\-/; - my $compat3 = $compat; - $compat3 =~ s/\,([a-z]*)[0-9]*\-/\,$1<\.\*>\-/; - `grep -Erq "$compat|$compat2|$compat3" $dt_path`; - if ( $? >> 8 ) { - WARN("UNDOCUMENTED_DT_STRING", - "DT compatible string \"$compat\" appears un-documented -- check $dt_path\n" . $herecurr); - } - - next if $compat !~ /^([a-zA-Z0-9\-]+)\,/; - my $vendor = $1; - `grep -Eq "^$vendor\\b" $vp_file`; - if ( $? >> 8 ) { - WARN("UNDOCUMENTED_DT_STRING", - "DT compatible string vendor \"$vendor\" appears un-documented -- check $vp_file\n" . $herecurr); - } - } - } - -# check we are in a valid source file if not then ignore this hunk - next if ($realfile !~ /\.(h|c|s|S|pl|sh|dtsi|dts)$/); - -# line length limit (with some exclusions) -# -# There are a few types of lines that may extend beyond $max_line_length: -# logging functions like pr_info that end in a string -# lines with a single string -# #defines that are a single string -# -# There are 3 different line length message types: -# LONG_LINE_COMMENT a comment starts before but extends beyond $max_linelength -# LONG_LINE_STRING a string starts before but extends beyond $max_line_length -# LONG_LINE all other lines longer than $max_line_length -# -# if LONG_LINE is ignored, the other 2 types are also ignored -# - - if ($line =~ /^\+/ && $length > $max_line_length) { - my $msg_type = "LONG_LINE"; - - # Check the allowed long line types first - - # logging functions that end in a string that starts - # before $max_line_length - if ($line =~ /^\+\s*$logFunctions\s*\(\s*(?:(?:KERN_\S+\s*|[^"]*))?($String\s*(?:|,|\)\s*;)\s*)$/ && - length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) { - $msg_type = ""; - - # lines with only strings (w/ possible termination) - # #defines with only strings - } elsif ($line =~ /^\+\s*$String\s*(?:\s*|,|\)\s*;)\s*$/ || - $line =~ /^\+\s*#\s*define\s+\w+\s+$String$/) { - $msg_type = ""; - - # Otherwise set the alternate message types - - # a comment starts before $max_line_length - } elsif ($line =~ /($;[\s$;]*)$/ && - length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) { - $msg_type = "LONG_LINE_COMMENT" - - # a quoted string starts before $max_line_length - } elsif ($sline =~ /\s*($String(?:\s*(?:\\|,\s*|\)\s*;\s*))?)$/ && - length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) { - $msg_type = "LONG_LINE_STRING" - } - - if ($msg_type ne "" && - (show_type("LONG_LINE") || show_type($msg_type))) { - WARN($msg_type, - "line over $max_line_length characters\n" . $herecurr); - } - } - -# check for adding lines without a newline. - if ($line =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ No newline at end of file/) { - WARN("MISSING_EOF_NEWLINE", - "adding a line without newline at end of file\n" . $herecurr); - } - -# Blackfin: use hi/lo macros - if ($realfile =~ m@arch/blackfin/.*\.S$@) { - if ($line =~ /\.[lL][[:space:]]*=.*&[[:space:]]*0x[fF][fF][fF][fF]/) { - my $herevet = "$here\n" . cat_vet($line) . "\n"; - ERROR("LO_MACRO", - "use the LO() macro, not (... & 0xFFFF)\n" . $herevet); - } - if ($line =~ /\.[hH][[:space:]]*=.*>>[[:space:]]*16/) { - my $herevet = "$here\n" . cat_vet($line) . "\n"; - ERROR("HI_MACRO", - "use the HI() macro, not (... >> 16)\n" . $herevet); - } - } - -# check we are in a valid source file C or perl if not then ignore this hunk - next if ($realfile !~ /\.(h|c|pl|dtsi|dts)$/); - -# at the beginning of a line any tabs must come first and anything -# more than 8 must use tabs. - if ($rawline =~ /^\+\s* \t\s*\S/ || - $rawline =~ /^\+\s* \s*/) { - my $herevet = "$here\n" . cat_vet($rawline) . "\n"; - $rpt_cleaners = 1; - if (ERROR("CODE_INDENT", - "code indent should use tabs where possible\n" . $herevet) && - $fix) { - $fixed[$fixlinenr] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e; - } - } - -# check for space before tabs. - if ($rawline =~ /^\+/ && $rawline =~ / \t/) { - my $herevet = "$here\n" . cat_vet($rawline) . "\n"; - if (WARN("SPACE_BEFORE_TAB", - "please, no space before tabs\n" . $herevet) && - $fix) { - while ($fixed[$fixlinenr] =~ - s/(^\+.*) {8,8}\t/$1\t\t/) {} - while ($fixed[$fixlinenr] =~ - s/(^\+.*) +\t/$1\t/) {} - } - } - -# check for && or || at the start of a line - if ($rawline =~ /^\+\s*(&&|\|\|)/) { - CHK("LOGICAL_CONTINUATIONS", - "Logical continuations should be on the previous line\n" . $hereprev); - } - -# check multi-line statement indentation matches previous line - if ($^V && $^V ge 5.10.0 && - $prevline =~ /^\+([ \t]*)((?:$c90_Keywords(?:\s+if)\s*)|(?:$Declare\s*)?(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*|$Ident\s*=\s*$Ident\s*)\(.*(\&\&|\|\||,)\s*$/) { - $prevline =~ /^\+(\t*)(.*)$/; - my $oldindent = $1; - my $rest = $2; - - my $pos = pos_last_openparen($rest); - if ($pos >= 0) { - $line =~ /^(\+| )([ \t]*)/; - my $newindent = $2; - - my $goodtabindent = $oldindent . - "\t" x ($pos / 8) . - " " x ($pos % 8); - my $goodspaceindent = $oldindent . " " x $pos; - - if ($newindent ne $goodtabindent && - $newindent ne $goodspaceindent) { - - if (CHK("PARENTHESIS_ALIGNMENT", - "Alignment should match open parenthesis\n" . $hereprev) && - $fix && $line =~ /^\+/) { - $fixed[$fixlinenr] =~ - s/^\+[ \t]*/\+$goodtabindent/; - } - } - } - } - -# check for space after cast like "(int) foo" or "(struct foo) bar" -# avoid checking a few false positives: -# "sizeof(<type>)" or "__alignof__(<type>)" -# function pointer declarations like "(*foo)(int) = bar;" -# structure definitions like "(struct foo) { 0 };" -# multiline macros that define functions -# known attributes or the __attribute__ keyword - if ($line =~ /^\+(.*)\(\s*$Type\s*\)([ \t]++)((?![={]|\\$|$Attribute|__attribute__))/ && - (!defined($1) || $1 !~ /\b(?:sizeof|__alignof__)\s*$/)) { - if (CHK("SPACING", - "No space is necessary after a cast\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/(\(\s*$Type\s*\))[ \t]+/$1/; - } - } - -# Block comment styles -# Networking with an initial /* - if ($realfile =~ m@^(drivers/net/|net/)@ && - $prevrawline =~ /^\+[ \t]*\/\*[ \t]*$/ && - $rawline =~ /^\+[ \t]*\*/ && - $realline > 2) { - WARN("NETWORKING_BLOCK_COMMENT_STYLE", - "networking block comments don't use an empty /* line, use /* Comment...\n" . $hereprev); - } - -# Block comments use * on subsequent lines - if ($prevline =~ /$;[ \t]*$/ && #ends in comment - $prevrawline =~ /^\+.*?\/\*/ && #starting /* - $prevrawline !~ /\*\/[ \t]*$/ && #no trailing */ - $rawline =~ /^\+/ && #line is new - $rawline !~ /^\+[ \t]*\*/) { #no leading * - WARN("BLOCK_COMMENT_STYLE", - "Block comments use * on subsequent lines\n" . $hereprev); - } - -# Block comments use */ on trailing lines - if ($rawline !~ m@^\+[ \t]*\*/[ \t]*$@ && #trailing */ - $rawline !~ m@^\+.*/\*.*\*/[ \t]*$@ && #inline /*...*/ - $rawline !~ m@^\+.*\*{2,}/[ \t]*$@ && #trailing **/ - $rawline =~ m@^\+[ \t]*.+\*\/[ \t]*$@) { #non blank */ - WARN("BLOCK_COMMENT_STYLE", - "Block comments use a trailing */ on a separate line\n" . $herecurr); - } - -# check for missing blank lines after struct/union declarations -# with exceptions for various attributes and macros - if ($prevline =~ /^[\+ ]};?\s*$/ && - $line =~ /^\+/ && - !($line =~ /^\+\s*$/ || - $line =~ /^\+\s*EXPORT_SYMBOL/ || - $line =~ /^\+\s*MODULE_/i || - $line =~ /^\+\s*\#\s*(?:end|elif|else)/ || - $line =~ /^\+[a-z_]*init/ || - $line =~ /^\+\s*(?:static\s+)?[A-Z_]*ATTR/ || - $line =~ /^\+\s*DECLARE/ || - $line =~ /^\+\s*__setup/)) { - if (CHK("LINE_SPACING", - "Please use a blank line after function/struct/union/enum declarations\n" . $hereprev) && - $fix) { - fix_insert_line($fixlinenr, "\+"); - } - } - -# check for multiple consecutive blank lines - if ($prevline =~ /^[\+ ]\s*$/ && - $line =~ /^\+\s*$/ && - $last_blank_line != ($linenr - 1)) { - if (CHK("LINE_SPACING", - "Please don't use multiple blank lines\n" . $hereprev) && - $fix) { - fix_delete_line($fixlinenr, $rawline); - } - - $last_blank_line = $linenr; - } - -# check for missing blank lines after declarations - if ($sline =~ /^\+\s+\S/ && #Not at char 1 - # actual declarations - ($prevline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ || - # function pointer declarations - $prevline =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ || - # foo bar; where foo is some local typedef or #define - $prevline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ || - # known declaration macros - $prevline =~ /^\+\s+$declaration_macros/) && - # for "else if" which can look like "$Ident $Ident" - !($prevline =~ /^\+\s+$c90_Keywords\b/ || - # other possible extensions of declaration lines - $prevline =~ /(?:$Compare|$Assignment|$Operators)\s*$/ || - # not starting a section or a macro "\" extended line - $prevline =~ /(?:\{\s*|\\)$/) && - # looks like a declaration - !($sline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ || - # function pointer declarations - $sline =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ || - # foo bar; where foo is some local typedef or #define - $sline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ || - # known declaration macros - $sline =~ /^\+\s+$declaration_macros/ || - # start of struct or union or enum - $sline =~ /^\+\s+(?:union|struct|enum|typedef)\b/ || - # start or end of block or continuation of declaration - $sline =~ /^\+\s+(?:$|[\{\}\.\#\"\?\:\(\[])/ || - # bitfield continuation - $sline =~ /^\+\s+$Ident\s*:\s*\d+\s*[,;]/ || - # other possible extensions of declaration lines - $sline =~ /^\+\s+\(?\s*(?:$Compare|$Assignment|$Operators)/) && - # indentation of previous and current line are the same - (($prevline =~ /\+(\s+)\S/) && $sline =~ /^\+$1\S/)) { - if (WARN("LINE_SPACING", - "Missing a blank line after declarations\n" . $hereprev) && - $fix) { - fix_insert_line($fixlinenr, "\+"); - } - } - -# check for spaces at the beginning of a line. -# Exceptions: -# 1) within comments -# 2) indented preprocessor commands -# 3) hanging labels - if ($rawline =~ /^\+ / && $line !~ /^\+ *(?:$;|#|$Ident:)/) { - my $herevet = "$here\n" . cat_vet($rawline) . "\n"; - if (WARN("LEADING_SPACE", - "please, no spaces at the start of a line\n" . $herevet) && - $fix) { - $fixed[$fixlinenr] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e; - } - } - -# check we are in a valid C source file if not then ignore this hunk - next if ($realfile !~ /\.(h|c)$/); - -# check indentation of any line with a bare else -# (but not if it is a multiple line "if (foo) return bar; else return baz;") -# if the previous line is a break or return and is indented 1 tab more... - if ($sline =~ /^\+([\t]+)(?:}[ \t]*)?else(?:[ \t]*{)?\s*$/) { - my $tabs = length($1) + 1; - if ($prevline =~ /^\+\t{$tabs,$tabs}break\b/ || - ($prevline =~ /^\+\t{$tabs,$tabs}return\b/ && - defined $lines[$linenr] && - $lines[$linenr] !~ /^[ \+]\t{$tabs,$tabs}return/)) { - WARN("UNNECESSARY_ELSE", - "else is not generally useful after a break or return\n" . $hereprev); - } - } - -# check indentation of a line with a break; -# if the previous line is a goto or return and is indented the same # of tabs - if ($sline =~ /^\+([\t]+)break\s*;\s*$/) { - my $tabs = $1; - if ($prevline =~ /^\+$tabs(?:goto|return)\b/) { - WARN("UNNECESSARY_BREAK", - "break is not useful after a goto or return\n" . $hereprev); - } - } - -# discourage the addition of CONFIG_EXPERIMENTAL in #if(def). - if ($line =~ /^\+\s*\#\s*if.*\bCONFIG_EXPERIMENTAL\b/) { - WARN("CONFIG_EXPERIMENTAL", - "Use of CONFIG_EXPERIMENTAL is deprecated. For alternatives, see https://lkml.org/lkml/2012/10/23/580\n"); - } - -# check for RCS/CVS revision markers - if ($rawline =~ /^\+.*\$(Revision|Log|Id)(?:\$|)/) { - WARN("CVS_KEYWORD", - "CVS style keyword markers, these will _not_ be updated\n". $herecurr); - } - -# Blackfin: don't use __builtin_bfin_[cs]sync - if ($line =~ /__builtin_bfin_csync/) { - my $herevet = "$here\n" . cat_vet($line) . "\n"; - ERROR("CSYNC", - "use the CSYNC() macro in asm/blackfin.h\n" . $herevet); - } - if ($line =~ /__builtin_bfin_ssync/) { - my $herevet = "$here\n" . cat_vet($line) . "\n"; - ERROR("SSYNC", - "use the SSYNC() macro in asm/blackfin.h\n" . $herevet); - } - -# check for old HOTPLUG __dev<foo> section markings - if ($line =~ /\b(__dev(init|exit)(data|const|))\b/) { - WARN("HOTPLUG_SECTION", - "Using $1 is unnecessary\n" . $herecurr); - } - -# Check for potential 'bare' types - my ($stat, $cond, $line_nr_next, $remain_next, $off_next, - $realline_next); -#print "LINE<$line>\n"; - if ($linenr >= $suppress_statement && - $realcnt && $sline =~ /.\s*\S/) { - ($stat, $cond, $line_nr_next, $remain_next, $off_next) = - ctx_statement_block($linenr, $realcnt, 0); - $stat =~ s/\n./\n /g; - $cond =~ s/\n./\n /g; - -#print "linenr<$linenr> <$stat>\n"; - # If this statement has no statement boundaries within - # it there is no point in retrying a statement scan - # until we hit end of it. - my $frag = $stat; $frag =~ s/;+\s*$//; - if ($frag !~ /(?:{|;)/) { -#print "skip<$line_nr_next>\n"; - $suppress_statement = $line_nr_next; - } - - # Find the real next line. - $realline_next = $line_nr_next; - if (defined $realline_next && - (!defined $lines[$realline_next - 1] || - substr($lines[$realline_next - 1], $off_next) =~ /^\s*$/)) { - $realline_next++; - } - - my $s = $stat; - $s =~ s/{.*$//s; - - # Ignore goto labels. - if ($s =~ /$Ident:\*$/s) { - - # Ignore functions being called - } elsif ($s =~ /^.\s*$Ident\s*\(/s) { - - } elsif ($s =~ /^.\s*else\b/s) { - - # declarations always start with types - } elsif ($prev_values eq 'E' && $s =~ /^.\s*(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?((?:\s*$Ident)+?)\b(?:\s+$Sparse)?\s*\**\s*(?:$Ident|\(\*[^\)]*\))(?:\s*$Modifier)?\s*(?:;|=|,|\()/s) { - my $type = $1; - $type =~ s/\s+/ /g; - possible($type, "A:" . $s); - - # definitions in global scope can only start with types - } elsif ($s =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b\s*(?!:)/s) { - possible($1, "B:" . $s); - } - - # any (foo ... *) is a pointer cast, and foo is a type - while ($s =~ /\(($Ident)(?:\s+$Sparse)*[\s\*]+\s*\)/sg) { - possible($1, "C:" . $s); - } - - # Check for any sort of function declaration. - # int foo(something bar, other baz); - # void (*store_gdt)(x86_descr_ptr *); - if ($prev_values eq 'E' && $s =~ /^(.(?:typedef\s*)?(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*(?:\b$Ident|\(\*\s*$Ident\))\s*)\(/s) { - my ($name_len) = length($1); - - my $ctx = $s; - substr($ctx, 0, $name_len + 1, ''); - $ctx =~ s/\)[^\)]*$//; - - for my $arg (split(/\s*,\s*/, $ctx)) { - if ($arg =~ /^(?:const\s+)?($Ident)(?:\s+$Sparse)*\s*\**\s*(:?\b$Ident)?$/s || $arg =~ /^($Ident)$/s) { - - possible($1, "D:" . $s); - } - } - } - - } - -# -# Checks which may be anchored in the context. -# - -# Check for switch () and associated case and default -# statements should be at the same indent. - if ($line=~/\bswitch\s*\(.*\)/) { - my $err = ''; - my $sep = ''; - my @ctx = ctx_block_outer($linenr, $realcnt); - shift(@ctx); - for my $ctx (@ctx) { - my ($clen, $cindent) = line_stats($ctx); - if ($ctx =~ /^\+\s*(case\s+|default:)/ && - $indent != $cindent) { - $err .= "$sep$ctx\n"; - $sep = ''; - } else { - $sep = "[...]\n"; - } - } - if ($err ne '') { - ERROR("SWITCH_CASE_INDENT_LEVEL", - "switch and case should be at the same indent\n$hereline$err"); - } - } - -# if/while/etc brace do not go on next line, unless defining a do while loop, -# or if that brace on the next line is for something else - if ($line =~ /(.*)\b((?:if|while|for|switch|(?:[a-z_]+|)for_each[a-z_]+)\s*\(|do\b|else\b)/ && $line !~ /^.\s*\#/) { - my $pre_ctx = "$1$2"; - - my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0); - - if ($line =~ /^\+\t{6,}/) { - WARN("DEEP_INDENTATION", - "Too many leading tabs - consider code refactoring\n" . $herecurr); - } - - my $ctx_cnt = $realcnt - $#ctx - 1; - my $ctx = join("\n", @ctx); - - my $ctx_ln = $linenr; - my $ctx_skip = $realcnt; - - while ($ctx_skip > $ctx_cnt || ($ctx_skip == $ctx_cnt && - defined $lines[$ctx_ln - 1] && - $lines[$ctx_ln - 1] =~ /^-/)) { - ##print "SKIP<$ctx_skip> CNT<$ctx_cnt>\n"; - $ctx_skip-- if (!defined $lines[$ctx_ln - 1] || $lines[$ctx_ln - 1] !~ /^-/); - $ctx_ln++; - } - - #print "realcnt<$realcnt> ctx_cnt<$ctx_cnt>\n"; - #print "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n"; - - if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln - 1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) { - ERROR("OPEN_BRACE", - "that open brace { should be on the previous line\n" . - "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n"); - } - if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ && - $ctx =~ /\)\s*\;\s*$/ && - defined $lines[$ctx_ln - 1]) - { - my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]); - if ($nindent > $indent) { - WARN("TRAILING_SEMICOLON", - "trailing semicolon indicates no statements, indent implies otherwise\n" . - "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n"); - } - } - } - -# Check relative indent for conditionals and blocks. - if ($line =~ /\b(?:(?:if|while|for|(?:[a-z_]+|)for_each[a-z_]+)\s*\(|do\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) { - ($stat, $cond, $line_nr_next, $remain_next, $off_next) = - ctx_statement_block($linenr, $realcnt, 0) - if (!defined $stat); - my ($s, $c) = ($stat, $cond); - - substr($s, 0, length($c), ''); - - # remove inline comments - $s =~ s/$;/ /g; - $c =~ s/$;/ /g; - - # Find out how long the conditional actually is. - my @newlines = ($c =~ /\n/gs); - my $cond_lines = 1 + $#newlines; - - # Make sure we remove the line prefixes as we have - # none on the first line, and are going to readd them - # where necessary. - $s =~ s/\n./\n/gs; - while ($s =~ /\n\s+\\\n/) { - $cond_lines += $s =~ s/\n\s+\\\n/\n/g; - } - - # We want to check the first line inside the block - # starting at the end of the conditional, so remove: - # 1) any blank line termination - # 2) any opening brace { on end of the line - # 3) any do (...) { - my $continuation = 0; - my $check = 0; - $s =~ s/^.*\bdo\b//; - $s =~ s/^\s*{//; - if ($s =~ s/^\s*\\//) { - $continuation = 1; - } - if ($s =~ s/^\s*?\n//) { - $check = 1; - $cond_lines++; - } - - # Also ignore a loop construct at the end of a - # preprocessor statement. - if (($prevline =~ /^.\s*#\s*define\s/ || - $prevline =~ /\\\s*$/) && $continuation == 0) { - $check = 0; - } - - my $cond_ptr = -1; - $continuation = 0; - while ($cond_ptr != $cond_lines) { - $cond_ptr = $cond_lines; - - # If we see an #else/#elif then the code - # is not linear. - if ($s =~ /^\s*\#\s*(?:else|elif)/) { - $check = 0; - } - - # Ignore: - # 1) blank lines, they should be at 0, - # 2) preprocessor lines, and - # 3) labels. - if ($continuation || - $s =~ /^\s*?\n/ || - $s =~ /^\s*#\s*?/ || - $s =~ /^\s*$Ident\s*:/) { - $continuation = ($s =~ /^.*?\\\n/) ? 1 : 0; - if ($s =~ s/^.*?\n//) { - $cond_lines++; - } - } - } - - my (undef, $sindent) = line_stats("+" . $s); - my $stat_real = raw_line($linenr, $cond_lines); - - # Check if either of these lines are modified, else - # this is not this patch's fault. - if (!defined($stat_real) || - $stat !~ /^\+/ && $stat_real !~ /^\+/) { - $check = 0; - } - if (defined($stat_real) && $cond_lines > 1) { - $stat_real = "[...]\n$stat_real"; - } - - #print "line<$line> prevline<$prevline> indent<$indent> sindent<$sindent> check<$check> continuation<$continuation> s<$s> cond_lines<$cond_lines> stat_real<$stat_real> stat<$stat>\n"; - - if ($check && $s ne '' && - (($sindent % 8) != 0 || - ($sindent < $indent) || - ($sindent > $indent + 8))) { - WARN("SUSPECT_CODE_INDENT", - "suspect code indent for conditional statements ($indent, $sindent)\n" . $herecurr . "$stat_real\n"); - } - } - - # Track the 'values' across context and added lines. - my $opline = $line; $opline =~ s/^./ /; - my ($curr_values, $curr_vars) = - annotate_values($opline . "\n", $prev_values); - $curr_values = $prev_values . $curr_values; - if ($dbg_values) { - my $outline = $opline; $outline =~ s/\t/ /g; - print "$linenr > .$outline\n"; - print "$linenr > $curr_values\n"; - print "$linenr > $curr_vars\n"; - } - $prev_values = substr($curr_values, -1); - -#ignore lines not being added - next if ($line =~ /^[^\+]/); - -# check for declarations of signed or unsigned without int - while ($line =~ m{($Declare)\s*(?!char\b|short\b|int\b|long\b)\s*($Ident)?\s*[=,;\[\)\(]}g) { - my $type = $1; - my $var = $2; - $var = "" if (!defined $var); - if ($type =~ /^(?:(?:$Storage|$Inline|$Attribute)\s+)*((?:un)?signed)((?:\s*\*)*)\s*$/) { - my $sign = $1; - my $pointer = $2; - - $pointer = "" if (!defined $pointer); - - if (WARN("UNSPECIFIED_INT", - "Prefer '" . trim($sign) . " int" . rtrim($pointer) . "' to bare use of '$sign" . rtrim($pointer) . "'\n" . $herecurr) && - $fix) { - my $decl = trim($sign) . " int "; - my $comp_pointer = $pointer; - $comp_pointer =~ s/\s//g; - $decl .= $comp_pointer; - $decl = rtrim($decl) if ($var eq ""); - $fixed[$fixlinenr] =~ s@\b$sign\s*\Q$pointer\E\s*$var\b@$decl$var@; - } - } - } - -# TEST: allow direct testing of the type matcher. - if ($dbg_type) { - if ($line =~ /^.\s*$Declare\s*$/) { - ERROR("TEST_TYPE", - "TEST: is type\n" . $herecurr); - } elsif ($dbg_type > 1 && $line =~ /^.+($Declare)/) { - ERROR("TEST_NOT_TYPE", - "TEST: is not type ($1 is)\n". $herecurr); - } - next; - } -# TEST: allow direct testing of the attribute matcher. - if ($dbg_attr) { - if ($line =~ /^.\s*$Modifier\s*$/) { - ERROR("TEST_ATTR", - "TEST: is attr\n" . $herecurr); - } elsif ($dbg_attr > 1 && $line =~ /^.+($Modifier)/) { - ERROR("TEST_NOT_ATTR", - "TEST: is not attr ($1 is)\n". $herecurr); - } - next; - } - -# check for initialisation to aggregates open brace on the next line - if ($line =~ /^.\s*{/ && - $prevline =~ /(?:^|[^=])=\s*$/) { - if (ERROR("OPEN_BRACE", - "that open brace { should be on the previous line\n" . $hereprev) && - $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { - fix_delete_line($fixlinenr - 1, $prevrawline); - fix_delete_line($fixlinenr, $rawline); - my $fixedline = $prevrawline; - $fixedline =~ s/\s*=\s*$/ = {/; - fix_insert_line($fixlinenr, $fixedline); - $fixedline = $line; - $fixedline =~ s/^(.\s*){\s*/$1/; - fix_insert_line($fixlinenr, $fixedline); - } - } - -# -# Checks which are anchored on the added line. -# - -# check for malformed paths in #include statements (uses RAW line) - if ($rawline =~ m{^.\s*\#\s*include\s+[<"](.*)[">]}) { - my $path = $1; - if ($path =~ m{//}) { - ERROR("MALFORMED_INCLUDE", - "malformed #include filename\n" . $herecurr); - } - if ($path =~ "^uapi/" && $realfile =~ m@\binclude/uapi/@) { - ERROR("UAPI_INCLUDE", - "No #include in ...include/uapi/... should use a uapi/ path prefix\n" . $herecurr); - } - } - -# no C99 // comments - if ($line =~ m{//}) { - if (ERROR("C99_COMMENTS", - "do not use C99 // comments\n" . $herecurr) && - $fix) { - my $line = $fixed[$fixlinenr]; - if ($line =~ /\/\/(.*)$/) { - my $comment = trim($1); - $fixed[$fixlinenr] =~ s@\/\/(.*)$@/\* $comment \*/@; - } - } - } - # Remove C99 comments. - $line =~ s@//.*@@; - $opline =~ s@//.*@@; - -# EXPORT_SYMBOL should immediately follow the thing it is exporting, consider -# the whole statement. -#print "APW <$lines[$realline_next - 1]>\n"; - if (defined $realline_next && - exists $lines[$realline_next - 1] && - !defined $suppress_export{$realline_next} && - ($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/ || - $lines[$realline_next - 1] =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) { - # Handle definitions which produce identifiers with - # a prefix: - # XXX(foo); - # EXPORT_SYMBOL(something_foo); - my $name = $1; - if ($stat =~ /^(?:.\s*}\s*\n)?.([A-Z_]+)\s*\(\s*($Ident)/ && - $name =~ /^${Ident}_$2/) { -#print "FOO C name<$name>\n"; - $suppress_export{$realline_next} = 1; - - } elsif ($stat !~ /(?: - \n.}\s*$| - ^.DEFINE_$Ident\(\Q$name\E\)| - ^.DECLARE_$Ident\(\Q$name\E\)| - ^.LIST_HEAD\(\Q$name\E\)| - ^.(?:$Storage\s+)?$Type\s*\(\s*\*\s*\Q$name\E\s*\)\s*\(| - \b\Q$name\E(?:\s+$Attribute)*\s*(?:;|=|\[|\() - )/x) { -#print "FOO A<$lines[$realline_next - 1]> stat<$stat> name<$name>\n"; - $suppress_export{$realline_next} = 2; - } else { - $suppress_export{$realline_next} = 1; - } - } - if (!defined $suppress_export{$linenr} && - $prevline =~ /^.\s*$/ && - ($line =~ /EXPORT_SYMBOL.*\((.*)\)/ || - $line =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) { -#print "FOO B <$lines[$linenr - 1]>\n"; - $suppress_export{$linenr} = 2; - } - if (defined $suppress_export{$linenr} && - $suppress_export{$linenr} == 2) { - WARN("EXPORT_SYMBOL", - "EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr); - } - -# check for global initialisers. - if ($line =~ /^\+$Type\s*$Ident(?:\s+$Modifier)*\s*=\s*($zero_initializer)\s*;/) { - if (ERROR("GLOBAL_INITIALISERS", - "do not initialise globals to $1\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/(^.$Type\s*$Ident(?:\s+$Modifier)*)\s*=\s*$zero_initializer\s*;/$1;/; - } - } -# check for static initialisers. - if ($line =~ /^\+.*\bstatic\s.*=\s*($zero_initializer)\s*;/) { - if (ERROR("INITIALISED_STATIC", - "do not initialise statics to $1\n" . - $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/(\bstatic\s.*?)\s*=\s*$zero_initializer\s*;/$1;/; - } - } - -# check for misordered declarations of char/short/int/long with signed/unsigned - while ($sline =~ m{(\b$TypeMisordered\b)}g) { - my $tmp = trim($1); - WARN("MISORDERED_TYPE", - "type '$tmp' should be specified in [[un]signed] [short|int|long|long long] order\n" . $herecurr); - } - -# check for static const char * arrays. - if ($line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/) { - WARN("STATIC_CONST_CHAR_ARRAY", - "static const char * array should probably be static const char * const\n" . - $herecurr); - } - -# check for static char foo[] = "bar" declarations. - if ($line =~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=\s*"/) { - WARN("STATIC_CONST_CHAR_ARRAY", - "static char array declaration should probably be static const char\n" . - $herecurr); - } - -# check for const <foo> const where <foo> is not a pointer or array type - if ($sline =~ /\bconst\s+($BasicType)\s+const\b/) { - my $found = $1; - if ($sline =~ /\bconst\s+\Q$found\E\s+const\b\s*\*/) { - WARN("CONST_CONST", - "'const $found const *' should probably be 'const $found * const'\n" . $herecurr); - } elsif ($sline !~ /\bconst\s+\Q$found\E\s+const\s+\w+\s*\[/) { - WARN("CONST_CONST", - "'const $found const' should probably be 'const $found'\n" . $herecurr); - } - } - -# check for non-global char *foo[] = {"bar", ...} declarations. - if ($line =~ /^.\s+(?:static\s+|const\s+)?char\s+\*\s*\w+\s*\[\s*\]\s*=\s*\{/) { - WARN("STATIC_CONST_CHAR_ARRAY", - "char * array declaration might be better as static const\n" . - $herecurr); - } - -# check for sizeof(foo)/sizeof(foo[0]) that could be ARRAY_SIZE(foo) - if ($line =~ m@\bsizeof\s*\(\s*($Lval)\s*\)@) { - my $array = $1; - if ($line =~ m@\b(sizeof\s*\(\s*\Q$array\E\s*\)\s*/\s*sizeof\s*\(\s*\Q$array\E\s*\[\s*0\s*\]\s*\))@) { - my $array_div = $1; - if (WARN("ARRAY_SIZE", - "Prefer ARRAY_SIZE($array)\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\Q$array_div\E/ARRAY_SIZE($array)/; - } - } - } - -# check for function declarations without arguments like "int foo()" - if ($line =~ /(\b$Type\s+$Ident)\s*\(\s*\)/) { - if (ERROR("FUNCTION_WITHOUT_ARGS", - "Bad function definition - $1() should probably be $1(void)\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/(\b($Type)\s+($Ident))\s*\(\s*\)/$2 $3(void)/; - } - } - -# check for uses of DEFINE_PCI_DEVICE_TABLE - if ($line =~ /\bDEFINE_PCI_DEVICE_TABLE\s*\(\s*(\w+)\s*\)\s*=/) { - if (WARN("DEFINE_PCI_DEVICE_TABLE", - "Prefer struct pci_device_id over deprecated DEFINE_PCI_DEVICE_TABLE\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b(?:static\s+|)DEFINE_PCI_DEVICE_TABLE\s*\(\s*(\w+)\s*\)\s*=\s*/static const struct pci_device_id $1\[\] = /; - } - } - -# check for new typedefs, only function parameters and sparse annotations -# make sense. - if ($line =~ /\btypedef\s/ && - $line !~ /\btypedef\s+$Type\s*\(\s*\*?$Ident\s*\)\s*\(/ && - $line !~ /\btypedef\s+$Type\s+$Ident\s*\(/ && - $line !~ /\b$typeTypedefs\b/ && - $line !~ /\b__bitwise(?:__|)\b/) { - WARN("NEW_TYPEDEFS", - "do not add new typedefs\n" . $herecurr); - } - -# * goes on variable not on type - # (char*[ const]) - while ($line =~ m{(\($NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)\))}g) { - #print "AA<$1>\n"; - my ($ident, $from, $to) = ($1, $2, $2); - - # Should start with a space. - $to =~ s/^(\S)/ $1/; - # Should not end with a space. - $to =~ s/\s+$//; - # '*'s should not have spaces between. - while ($to =~ s/\*\s+\*/\*\*/) { - } - -## print "1: from<$from> to<$to> ident<$ident>\n"; - if ($from ne $to) { - if (ERROR("POINTER_LOCATION", - "\"(foo$from)\" should be \"(foo$to)\"\n" . $herecurr) && - $fix) { - my $sub_from = $ident; - my $sub_to = $ident; - $sub_to =~ s/\Q$from\E/$to/; - $fixed[$fixlinenr] =~ - s@\Q$sub_from\E@$sub_to@; - } - } - } - while ($line =~ m{(\b$NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)($Ident))}g) { - #print "BB<$1>\n"; - my ($match, $from, $to, $ident) = ($1, $2, $2, $3); - - # Should start with a space. - $to =~ s/^(\S)/ $1/; - # Should not end with a space. - $to =~ s/\s+$//; - # '*'s should not have spaces between. - while ($to =~ s/\*\s+\*/\*\*/) { - } - # Modifiers should have spaces. - $to =~ s/(\b$Modifier$)/$1 /; - -## print "2: from<$from> to<$to> ident<$ident>\n"; - if ($from ne $to && $ident !~ /^$Modifier$/) { - if (ERROR("POINTER_LOCATION", - "\"foo${from}bar\" should be \"foo${to}bar\"\n" . $herecurr) && - $fix) { - - my $sub_from = $match; - my $sub_to = $match; - $sub_to =~ s/\Q$from\E/$to/; - $fixed[$fixlinenr] =~ - s@\Q$sub_from\E@$sub_to@; - } - } - } - -# avoid BUG() or BUG_ON() - if ($line =~ /\b(?:BUG|BUG_ON)\b/) { - my $msg_type = \&WARN; - $msg_type = \&CHK if ($file); - &{$msg_type}("AVOID_BUG", - "Avoid crashing the kernel - try using WARN_ON & recovery code rather than BUG() or BUG_ON()\n" . $herecurr); - } - -# avoid LINUX_VERSION_CODE - if ($line =~ /\bLINUX_VERSION_CODE\b/) { - WARN("LINUX_VERSION_CODE", - "LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged\n" . $herecurr); - } - -# check for uses of printk_ratelimit - if ($line =~ /\bprintk_ratelimit\s*\(/) { - WARN("PRINTK_RATELIMITED", - "Prefer printk_ratelimited or pr_<level>_ratelimited to printk_ratelimit\n" . $herecurr); - } - -# printk should use KERN_* levels. Note that follow on printk's on the -# same line do not need a level, so we use the current block context -# to try and find and validate the current printk. In summary the current -# printk includes all preceding printk's which have no newline on the end. -# we assume the first bad printk is the one to report. - if ($line =~ /\bprintk\((?!KERN_)\s*"/) { - my $ok = 0; - for (my $ln = $linenr - 1; $ln >= $first_line; $ln--) { - #print "CHECK<$lines[$ln - 1]\n"; - # we have a preceding printk if it ends - # with "\n" ignore it, else it is to blame - if ($lines[$ln - 1] =~ m{\bprintk\(}) { - if ($rawlines[$ln - 1] !~ m{\\n"}) { - $ok = 1; - } - last; - } - } - if ($ok == 0) { - WARN("PRINTK_WITHOUT_KERN_LEVEL", - "printk() should include KERN_ facility level\n" . $herecurr); - } - } - - if ($line =~ /\bprintk\s*\(\s*KERN_([A-Z]+)/) { - my $orig = $1; - my $level = lc($orig); - $level = "warn" if ($level eq "warning"); - my $level2 = $level; - $level2 = "dbg" if ($level eq "debug"); - WARN("PREFER_PR_LEVEL", - "Prefer [subsystem eg: netdev]_$level2([subsystem]dev, ... then dev_$level2(dev, ... then pr_$level(... to printk(KERN_$orig ...\n" . $herecurr); - } - - if ($line =~ /\bpr_warning\s*\(/) { - if (WARN("PREFER_PR_LEVEL", - "Prefer pr_warn(... to pr_warning(...\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/\bpr_warning\b/pr_warn/; - } - } - - if ($line =~ /\bdev_printk\s*\(\s*KERN_([A-Z]+)/) { - my $orig = $1; - my $level = lc($orig); - $level = "warn" if ($level eq "warning"); - $level = "dbg" if ($level eq "debug"); - WARN("PREFER_DEV_LEVEL", - "Prefer dev_$level(... to dev_printk(KERN_$orig, ...\n" . $herecurr); - } - -# ENOSYS means "bad syscall nr" and nothing else. This will have a small -# number of false positives, but assembly files are not checked, so at -# least the arch entry code will not trigger this warning. - if ($line =~ /\bENOSYS\b/) { - WARN("ENOSYS", - "ENOSYS means 'invalid syscall nr' and nothing else\n" . $herecurr); - } - -# function brace can't be on same line, except for #defines of do while, -# or if closed on same line - if (($line=~/$Type\s*$Ident\(.*\).*\s*{/) and - !($line=~/\#\s*define.*do\s\{/) and !($line=~/}/)) { - if (ERROR("OPEN_BRACE", - "open brace '{' following function declarations go on the next line\n" . $herecurr) && - $fix) { - fix_delete_line($fixlinenr, $rawline); - my $fixed_line = $rawline; - $fixed_line =~ /(^..*$Type\s*$Ident\(.*\)\s*){(.*)$/; - my $line1 = $1; - my $line2 = $2; - fix_insert_line($fixlinenr, ltrim($line1)); - fix_insert_line($fixlinenr, "\+{"); - if ($line2 !~ /^\s*$/) { - fix_insert_line($fixlinenr, "\+\t" . trim($line2)); - } - } - } - -# open braces for enum, union and struct go on the same line. - if ($line =~ /^.\s*{/ && - $prevline =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?\s*$/) { - if (ERROR("OPEN_BRACE", - "open brace '{' following $1 go on the same line\n" . $hereprev) && - $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { - fix_delete_line($fixlinenr - 1, $prevrawline); - fix_delete_line($fixlinenr, $rawline); - my $fixedline = rtrim($prevrawline) . " {"; - fix_insert_line($fixlinenr, $fixedline); - $fixedline = $rawline; - $fixedline =~ s/^(.\s*){\s*/$1\t/; - if ($fixedline !~ /^\+\s*$/) { - fix_insert_line($fixlinenr, $fixedline); - } - } - } - -# missing space after union, struct or enum definition - if ($line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident){1,2}[=\{]/) { - if (WARN("SPACING", - "missing space after $1 definition\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/^(.\s*(?:typedef\s+)?(?:enum|union|struct)(?:\s+$Ident){1,2})([=\{])/$1 $2/; - } - } - -# Function pointer declarations -# check spacing between type, funcptr, and args -# canonical declaration is "type (*funcptr)(args...)" - if ($line =~ /^.\s*($Declare)\((\s*)\*(\s*)($Ident)(\s*)\)(\s*)\(/) { - my $declare = $1; - my $pre_pointer_space = $2; - my $post_pointer_space = $3; - my $funcname = $4; - my $post_funcname_space = $5; - my $pre_args_space = $6; - -# the $Declare variable will capture all spaces after the type -# so check it for a missing trailing missing space but pointer return types -# don't need a space so don't warn for those. - my $post_declare_space = ""; - if ($declare =~ /(\s+)$/) { - $post_declare_space = $1; - $declare = rtrim($declare); - } - if ($declare !~ /\*$/ && $post_declare_space =~ /^$/) { - WARN("SPACING", - "missing space after return type\n" . $herecurr); - $post_declare_space = " "; - } - -# unnecessary space "type (*funcptr)(args...)" -# This test is not currently implemented because these declarations are -# equivalent to -# int foo(int bar, ...) -# and this is form shouldn't/doesn't generate a checkpatch warning. -# -# elsif ($declare =~ /\s{2,}$/) { -# WARN("SPACING", -# "Multiple spaces after return type\n" . $herecurr); -# } - -# unnecessary space "type ( *funcptr)(args...)" - if (defined $pre_pointer_space && - $pre_pointer_space =~ /^\s/) { - WARN("SPACING", - "Unnecessary space after function pointer open parenthesis\n" . $herecurr); - } - -# unnecessary space "type (* funcptr)(args...)" - if (defined $post_pointer_space && - $post_pointer_space =~ /^\s/) { - WARN("SPACING", - "Unnecessary space before function pointer name\n" . $herecurr); - } - -# unnecessary space "type (*funcptr )(args...)" - if (defined $post_funcname_space && - $post_funcname_space =~ /^\s/) { - WARN("SPACING", - "Unnecessary space after function pointer name\n" . $herecurr); - } - -# unnecessary space "type (*funcptr) (args...)" - if (defined $pre_args_space && - $pre_args_space =~ /^\s/) { - WARN("SPACING", - "Unnecessary space before function pointer arguments\n" . $herecurr); - } - - if (show_type("SPACING") && $fix) { - $fixed[$fixlinenr] =~ - s/^(.\s*)$Declare\s*\(\s*\*\s*$Ident\s*\)\s*\(/$1 . $declare . $post_declare_space . '(*' . $funcname . ')('/ex; - } - } - -# check for spacing round square brackets; allowed: -# 1. with a type on the left -- int [] a; -# 2. at the beginning of a line for slice initialisers -- [0...10] = 5, -# 3. inside a curly brace -- = { [0...10] = 5 } - while ($line =~ /(.*?\s)\[/g) { - my ($where, $prefix) = ($-[1], $1); - if ($prefix !~ /$Type\s+$/ && - ($where != 0 || $prefix !~ /^.\s+$/) && - $prefix !~ /[{,]\s+$/) { - if (ERROR("BRACKET_SPACE", - "space prohibited before open square bracket '['\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/^(\+.*?)\s+\[/$1\[/; - } - } - } - -# check for spaces between functions and their parentheses. - while ($line =~ /($Ident)\s+\(/g) { - my $name = $1; - my $ctx_before = substr($line, 0, $-[1]); - my $ctx = "$ctx_before$name"; - - # Ignore those directives where spaces _are_ permitted. - if ($name =~ /^(?: - if|for|while|switch|return|case| - volatile|__volatile__| - __attribute__|format|__extension__| - asm|__asm__)$/x) - { - # cpp #define statements have non-optional spaces, ie - # if there is a space between the name and the open - # parenthesis it is simply not a parameter group. - } elsif ($ctx_before =~ /^.\s*\#\s*define\s*$/) { - - # cpp #elif statement condition may start with a ( - } elsif ($ctx =~ /^.\s*\#\s*elif\s*$/) { - - # If this whole things ends with a type its most - # likely a typedef for a function. - } elsif ($ctx =~ /$Type$/) { - - } else { - if (WARN("SPACING", - "space prohibited between function name and open parenthesis '('\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/\b$name\s+\(/$name\(/; - } - } - } - -# Check operator spacing. - if (!($line=~/\#\s*include/)) { - my $fixed_line = ""; - my $line_fixed = 0; - - my $ops = qr{ - <<=|>>=|<=|>=|==|!=| - \+=|-=|\*=|\/=|%=|\^=|\|=|&=| - =>|->|<<|>>|<|>|=|!|~| - &&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%| - \?:|\?|: - }x; - my @elements = split(/($ops|;)/, $opline); - -## print("element count: <" . $#elements . ">\n"); -## foreach my $el (@elements) { -## print("el: <$el>\n"); -## } - - my @fix_elements = (); - my $off = 0; - - foreach my $el (@elements) { - push(@fix_elements, substr($rawline, $off, length($el))); - $off += length($el); - } - - $off = 0; - - my $blank = copy_spacing($opline); - my $last_after = -1; - - for (my $n = 0; $n < $#elements; $n += 2) { - - my $good = $fix_elements[$n] . $fix_elements[$n + 1]; - -## print("n: <$n> good: <$good>\n"); - - $off += length($elements[$n]); - - # Pick up the preceding and succeeding characters. - my $ca = substr($opline, 0, $off); - my $cc = ''; - if (length($opline) >= ($off + length($elements[$n + 1]))) { - $cc = substr($opline, $off + length($elements[$n + 1])); - } - my $cb = "$ca$;$cc"; - - my $a = ''; - $a = 'V' if ($elements[$n] ne ''); - $a = 'W' if ($elements[$n] =~ /\s$/); - $a = 'C' if ($elements[$n] =~ /$;$/); - $a = 'B' if ($elements[$n] =~ /(\[|\()$/); - $a = 'O' if ($elements[$n] eq ''); - $a = 'E' if ($ca =~ /^\s*$/); - - my $op = $elements[$n + 1]; - - my $c = ''; - if (defined $elements[$n + 2]) { - $c = 'V' if ($elements[$n + 2] ne ''); - $c = 'W' if ($elements[$n + 2] =~ /^\s/); - $c = 'C' if ($elements[$n + 2] =~ /^$;/); - $c = 'B' if ($elements[$n + 2] =~ /^(\)|\]|;)/); - $c = 'O' if ($elements[$n + 2] eq ''); - $c = 'E' if ($elements[$n + 2] =~ /^\s*\\$/); - } else { - $c = 'E'; - } - - my $ctx = "${a}x${c}"; - - my $at = "(ctx:$ctx)"; - - my $ptr = substr($blank, 0, $off) . "^"; - my $hereptr = "$hereline$ptr\n"; - - # Pull out the value of this operator. - my $op_type = substr($curr_values, $off + 1, 1); - - # Get the full operator variant. - my $opv = $op . substr($curr_vars, $off, 1); - - # Ignore operators passed as parameters. - if ($op_type ne 'V' && - $ca =~ /\s$/ && $cc =~ /^\s*[,\)]/) { - -# # Ignore comments -# } elsif ($op =~ /^$;+$/) { - - # ; should have either the end of line or a space or \ after it - } elsif ($op eq ';') { - if ($ctx !~ /.x[WEBC]/ && - $cc !~ /^\\/ && $cc !~ /^;/) { - if (ERROR("SPACING", - "space required after that '$op' $at\n" . $hereptr)) { - $good = $fix_elements[$n] . trim($fix_elements[$n + 1]) . " "; - $line_fixed = 1; - } - } - - # // is a comment - } elsif ($op eq '//') { - - # : when part of a bitfield - } elsif ($opv eq ':B') { - # skip the bitfield test for now - - # No spaces for: - # -> - } elsif ($op eq '->') { - if ($ctx =~ /Wx.|.xW/) { - if (ERROR("SPACING", - "spaces prohibited around that '$op' $at\n" . $hereptr)) { - $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); - if (defined $fix_elements[$n + 2]) { - $fix_elements[$n + 2] =~ s/^\s+//; - } - $line_fixed = 1; - } - } - - # , must not have a space before and must have a space on the right. - } elsif ($op eq ',') { - my $rtrim_before = 0; - my $space_after = 0; - if ($ctx =~ /Wx./) { - if (ERROR("SPACING", - "space prohibited before that '$op' $at\n" . $hereptr)) { - $line_fixed = 1; - $rtrim_before = 1; - } - } - if ($ctx !~ /.x[WEC]/ && $cc !~ /^}/) { - if (ERROR("SPACING", - "space required after that '$op' $at\n" . $hereptr)) { - $line_fixed = 1; - $last_after = $n; - $space_after = 1; - } - } - if ($rtrim_before || $space_after) { - if ($rtrim_before) { - $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); - } else { - $good = $fix_elements[$n] . trim($fix_elements[$n + 1]); - } - if ($space_after) { - $good .= " "; - } - } - - # '*' as part of a type definition -- reported already. - } elsif ($opv eq '*_') { - #warn "'*' is part of type\n"; - - # unary operators should have a space before and - # none after. May be left adjacent to another - # unary operator, or a cast - } elsif ($op eq '!' || $op eq '~' || - $opv eq '*U' || $opv eq '-U' || - $opv eq '&U' || $opv eq '&&U') { - if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) { - if (ERROR("SPACING", - "space required before that '$op' $at\n" . $hereptr)) { - if ($n != $last_after + 2) { - $good = $fix_elements[$n] . " " . ltrim($fix_elements[$n + 1]); - $line_fixed = 1; - } - } - } - if ($op eq '*' && $cc =~/\s*$Modifier\b/) { - # A unary '*' may be const - - } elsif ($ctx =~ /.xW/) { - if (ERROR("SPACING", - "space prohibited after that '$op' $at\n" . $hereptr)) { - $good = $fix_elements[$n] . rtrim($fix_elements[$n + 1]); - if (defined $fix_elements[$n + 2]) { - $fix_elements[$n + 2] =~ s/^\s+//; - } - $line_fixed = 1; - } - } - - # unary ++ and unary -- are allowed no space on one side. - } elsif ($op eq '++' or $op eq '--') { - if ($ctx !~ /[WEOBC]x[^W]/ && $ctx !~ /[^W]x[WOBEC]/) { - if (ERROR("SPACING", - "space required one side of that '$op' $at\n" . $hereptr)) { - $good = $fix_elements[$n] . trim($fix_elements[$n + 1]) . " "; - $line_fixed = 1; - } - } - if ($ctx =~ /Wx[BE]/ || - ($ctx =~ /Wx./ && $cc =~ /^;/)) { - if (ERROR("SPACING", - "space prohibited before that '$op' $at\n" . $hereptr)) { - $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); - $line_fixed = 1; - } - } - if ($ctx =~ /ExW/) { - if (ERROR("SPACING", - "space prohibited after that '$op' $at\n" . $hereptr)) { - $good = $fix_elements[$n] . trim($fix_elements[$n + 1]); - if (defined $fix_elements[$n + 2]) { - $fix_elements[$n + 2] =~ s/^\s+//; - } - $line_fixed = 1; - } - } - - # << and >> may either have or not have spaces both sides - } elsif ($op eq '<<' or $op eq '>>' or - $op eq '&' or $op eq '^' or $op eq '|' or - $op eq '+' or $op eq '-' or - $op eq '*' or $op eq '/' or - $op eq '%') - { - if ($check) { - if (defined $fix_elements[$n + 2] && $ctx !~ /[EW]x[EW]/) { - if (CHK("SPACING", - "spaces preferred around that '$op' $at\n" . $hereptr)) { - $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " "; - $fix_elements[$n + 2] =~ s/^\s+//; - $line_fixed = 1; - } - } elsif (!defined $fix_elements[$n + 2] && $ctx !~ /Wx[OE]/) { - if (CHK("SPACING", - "space preferred before that '$op' $at\n" . $hereptr)) { - $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]); - $line_fixed = 1; - } - } - } elsif ($ctx =~ /Wx[^WCE]|[^WCE]xW/) { - if (ERROR("SPACING", - "need consistent spacing around '$op' $at\n" . $hereptr)) { - $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " "; - if (defined $fix_elements[$n + 2]) { - $fix_elements[$n + 2] =~ s/^\s+//; - } - $line_fixed = 1; - } - } - - # A colon needs no spaces before when it is - # terminating a case value or a label. - } elsif ($opv eq ':C' || $opv eq ':L') { - if ($ctx =~ /Wx./) { - if (ERROR("SPACING", - "space prohibited before that '$op' $at\n" . $hereptr)) { - $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); - $line_fixed = 1; - } - } - - # All the others need spaces both sides. - } elsif ($ctx !~ /[EWC]x[CWE]/) { - my $ok = 0; - - # Ignore email addresses <foo@bar> - if (($op eq '<' && - $cc =~ /^\S+\@\S+>/) || - ($op eq '>' && - $ca =~ /<\S+\@\S+$/)) - { - $ok = 1; - } - - # for asm volatile statements - # ignore a colon with another - # colon immediately before or after - if (($op eq ':') && - ($ca =~ /:$/ || $cc =~ /^:/)) { - $ok = 1; - } - - # messages are ERROR, but ?: are CHK - if ($ok == 0) { - my $msg_type = \&ERROR; - $msg_type = \&CHK if (($op eq '?:' || $op eq '?' || $op eq ':') && $ctx =~ /VxV/); - - if (&{$msg_type}("SPACING", - "spaces required around that '$op' $at\n" . $hereptr)) { - $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " "; - if (defined $fix_elements[$n + 2]) { - $fix_elements[$n + 2] =~ s/^\s+//; - } - $line_fixed = 1; - } - } - } - $off += length($elements[$n + 1]); - -## print("n: <$n> GOOD: <$good>\n"); - - $fixed_line = $fixed_line . $good; - } - - if (($#elements % 2) == 0) { - $fixed_line = $fixed_line . $fix_elements[$#elements]; - } - - if ($fix && $line_fixed && $fixed_line ne $fixed[$fixlinenr]) { - $fixed[$fixlinenr] = $fixed_line; - } - - - } - -# check for whitespace before a non-naked semicolon - if ($line =~ /^\+.*\S\s+;\s*$/) { - if (WARN("SPACING", - "space prohibited before semicolon\n" . $herecurr) && - $fix) { - 1 while $fixed[$fixlinenr] =~ - s/^(\+.*\S)\s+;/$1;/; - } - } - -# check for multiple assignments - if ($line =~ /^.\s*$Lval\s*=\s*$Lval\s*=(?!=)/) { - CHK("MULTIPLE_ASSIGNMENTS", - "multiple assignments should be avoided\n" . $herecurr); - } - -## # check for multiple declarations, allowing for a function declaration -## # continuation. -## if ($line =~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Ident.*/ && -## $line !~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Type\s*$Ident.*/) { -## -## # Remove any bracketed sections to ensure we do not -## # falsly report the parameters of functions. -## my $ln = $line; -## while ($ln =~ s/\([^\(\)]*\)//g) { -## } -## if ($ln =~ /,/) { -## WARN("MULTIPLE_DECLARATION", -## "declaring multiple variables together should be avoided\n" . $herecurr); -## } -## } - -#need space before brace following if, while, etc - if (($line =~ /\(.*\)\{/ && $line !~ /\($Type\)\{/) || - $line =~ /do\{/) { - if (ERROR("SPACING", - "space required before the open brace '{'\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/^(\+.*(?:do|\))){/$1 {/; - } - } - -## # check for blank lines before declarations -## if ($line =~ /^.\t+$Type\s+$Ident(?:\s*=.*)?;/ && -## $prevrawline =~ /^.\s*$/) { -## WARN("SPACING", -## "No blank lines before declarations\n" . $hereprev); -## } -## - -# closing brace should have a space following it when it has anything -# on the line - if ($line =~ /}(?!(?:,|;|\)))\S/) { - if (ERROR("SPACING", - "space required after that close brace '}'\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/}((?!(?:,|;|\)))\S)/} $1/; - } - } - -# check spacing on square brackets - if ($line =~ /\[\s/ && $line !~ /\[\s*$/) { - if (ERROR("SPACING", - "space prohibited after that open square bracket '['\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/\[\s+/\[/; - } - } - if ($line =~ /\s\]/) { - if (ERROR("SPACING", - "space prohibited before that close square bracket ']'\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/\s+\]/\]/; - } - } - -# check spacing on parentheses - if ($line =~ /\(\s/ && $line !~ /\(\s*(?:\\)?$/ && - $line !~ /for\s*\(\s+;/) { - if (ERROR("SPACING", - "space prohibited after that open parenthesis '('\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/\(\s+/\(/; - } - } - if ($line =~ /(\s+)\)/ && $line !~ /^.\s*\)/ && - $line !~ /for\s*\(.*;\s+\)/ && - $line !~ /:\s+\)/) { - if (ERROR("SPACING", - "space prohibited before that close parenthesis ')'\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/\s+\)/\)/; - } - } - -# check unnecessary parentheses around addressof/dereference single $Lvals -# ie: &(foo->bar) should be &foo->bar and *(foo->bar) should be *foo->bar - - while ($line =~ /(?:[^&]&\s*|\*)\(\s*($Ident\s*(?:$Member\s*)+)\s*\)/g) { - my $var = $1; - if (CHK("UNNECESSARY_PARENTHESES", - "Unnecessary parentheses around $var\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\(\s*\Q$var\E\s*\)/$var/; - } - } - -# check for unnecessary parentheses around function pointer uses -# ie: (foo->bar)(); should be foo->bar(); -# but not "if (foo->bar) (" to avoid some false positives - if ($line =~ /(\bif\s*|)(\(\s*$Ident\s*(?:$Member\s*)+\))[ \t]*\(/ && $1 !~ /^if/) { - my $var = $2; - if (CHK("UNNECESSARY_PARENTHESES", - "Unnecessary parentheses around function pointer $var\n" . $herecurr) && - $fix) { - my $var2 = deparenthesize($var); - $var2 =~ s/\s//g; - $fixed[$fixlinenr] =~ s/\Q$var\E/$var2/; - } - } - -#goto labels aren't indented, allow a single space however - if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and - !($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) { - if (WARN("INDENTED_LABEL", - "labels should not be indented\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/^(.)\s+/$1/; - } - } - -# return is not a function - if (defined($stat) && $stat =~ /^.\s*return(\s*)\(/s) { - my $spacing = $1; - if ($^V && $^V ge 5.10.0 && - $stat =~ /^.\s*return\s*($balanced_parens)\s*;\s*$/) { - my $value = $1; - $value = deparenthesize($value); - if ($value =~ m/^\s*$FuncArg\s*(?:\?|$)/) { - ERROR("RETURN_PARENTHESES", - "return is not a function, parentheses are not required\n" . $herecurr); - } - } elsif ($spacing !~ /\s+/) { - ERROR("SPACING", - "space required before the open parenthesis '('\n" . $herecurr); - } - } - -# unnecessary return in a void function -# at end-of-function, with the previous line a single leading tab, then return; -# and the line before that not a goto label target like "out:" - if ($sline =~ /^[ \+]}\s*$/ && - $prevline =~ /^\+\treturn\s*;\s*$/ && - $linenr >= 3 && - $lines[$linenr - 3] =~ /^[ +]/ && - $lines[$linenr - 3] !~ /^[ +]\s*$Ident\s*:/) { - WARN("RETURN_VOID", - "void function return statements are not generally useful\n" . $hereprev); - } - -# if statements using unnecessary parentheses - ie: if ((foo == bar)) - if ($^V && $^V ge 5.10.0 && - $line =~ /\bif\s*((?:\(\s*){2,})/) { - my $openparens = $1; - my $count = $openparens =~ tr@\(@\(@; - my $msg = ""; - if ($line =~ /\bif\s*(?:\(\s*){$count,$count}$LvalOrFunc\s*($Compare)\s*$LvalOrFunc(?:\s*\)){$count,$count}/) { - my $comp = $4; #Not $1 because of $LvalOrFunc - $msg = " - maybe == should be = ?" if ($comp eq "=="); - WARN("UNNECESSARY_PARENTHESES", - "Unnecessary parentheses$msg\n" . $herecurr); - } - } - -# comparisons with a constant or upper case identifier on the left -# avoid cases like "foo + BAR < baz" -# only fix matches surrounded by parentheses to avoid incorrect -# conversions like "FOO < baz() + 5" being "misfixed" to "baz() > FOO + 5" - if ($^V && $^V ge 5.10.0 && - $line =~ /^\+(.*)\b($Constant|[A-Z_][A-Z0-9_]*)\s*($Compare)\s*($LvalOrFunc)/) { - my $lead = $1; - my $const = $2; - my $comp = $3; - my $to = $4; - my $newcomp = $comp; - if ($lead !~ /$Operators\s*$/ && - $to !~ /^(?:Constant|[A-Z_][A-Z0-9_]*)$/ && - WARN("CONSTANT_COMPARISON", - "Comparisons should place the constant on the right side of the test\n" . $herecurr) && - $fix) { - if ($comp eq "<") { - $newcomp = ">"; - } elsif ($comp eq "<=") { - $newcomp = ">="; - } elsif ($comp eq ">") { - $newcomp = "<"; - } elsif ($comp eq ">=") { - $newcomp = "<="; - } - $fixed[$fixlinenr] =~ s/\(\s*\Q$const\E\s*$Compare\s*\Q$to\E\s*\)/($to $newcomp $const)/; - } - } - -# Return of what appears to be an errno should normally be negative - if ($sline =~ /\breturn(?:\s*\(+\s*|\s+)(E[A-Z]+)(?:\s*\)+\s*|\s*)[;:,]/) { - my $name = $1; - if ($name ne 'EOF' && $name ne 'ERROR') { - WARN("USE_NEGATIVE_ERRNO", - "return of an errno should typically be negative (ie: return -$1)\n" . $herecurr); - } - } - -# Need a space before open parenthesis after if, while etc - if ($line =~ /\b(if|while|for|switch)\(/) { - if (ERROR("SPACING", - "space required before the open parenthesis '('\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/\b(if|while|for|switch)\(/$1 \(/; - } - } - -# Check for illegal assignment in if conditional -- and check for trailing -# statements after the conditional. - if ($line =~ /do\s*(?!{)/) { - ($stat, $cond, $line_nr_next, $remain_next, $off_next) = - ctx_statement_block($linenr, $realcnt, 0) - if (!defined $stat); - my ($stat_next) = ctx_statement_block($line_nr_next, - $remain_next, $off_next); - $stat_next =~ s/\n./\n /g; - ##print "stat<$stat> stat_next<$stat_next>\n"; - - if ($stat_next =~ /^\s*while\b/) { - # If the statement carries leading newlines, - # then count those as offsets. - my ($whitespace) = - ($stat_next =~ /^((?:\s*\n[+-])*\s*)/s); - my $offset = - statement_rawlines($whitespace) - 1; - - $suppress_whiletrailers{$line_nr_next + - $offset} = 1; - } - } - if (!defined $suppress_whiletrailers{$linenr} && - defined($stat) && defined($cond) && - $line =~ /\b(?:if|while|for)\s*\(/ && $line !~ /^.\s*#/) { - my ($s, $c) = ($stat, $cond); - - if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/s) { - ERROR("ASSIGN_IN_IF", - "do not use assignment in if condition\n" . $herecurr); - } - - # Find out what is on the end of the line after the - # conditional. - substr($s, 0, length($c), ''); - $s =~ s/\n.*//g; - $s =~ s/$;//g; # Remove any comments - if (length($c) && $s !~ /^\s*{?\s*\\*\s*$/ && - $c !~ /}\s*while\s*/) - { - # Find out how long the conditional actually is. - my @newlines = ($c =~ /\n/gs); - my $cond_lines = 1 + $#newlines; - my $stat_real = ''; - - $stat_real = raw_line($linenr, $cond_lines) - . "\n" if ($cond_lines); - if (defined($stat_real) && $cond_lines > 1) { - $stat_real = "[...]\n$stat_real"; - } - - ERROR("TRAILING_STATEMENTS", - "trailing statements should be on next line\n" . $herecurr . $stat_real); - } - } - -# Check for bitwise tests written as boolean - if ($line =~ / - (?: - (?:\[|\(|\&\&|\|\|) - \s*0[xX][0-9]+\s* - (?:\&\&|\|\|) - | - (?:\&\&|\|\|) - \s*0[xX][0-9]+\s* - (?:\&\&|\|\||\)|\]) - )/x) - { - WARN("HEXADECIMAL_BOOLEAN_TEST", - "boolean test with hexadecimal, perhaps just 1 \& or \|?\n" . $herecurr); - } - -# if and else should not have general statements after it - if ($line =~ /^.\s*(?:}\s*)?else\b(.*)/) { - my $s = $1; - $s =~ s/$;//g; # Remove any comments - if ($s !~ /^\s*(?:\sif|(?:{|)\s*\\?\s*$)/) { - ERROR("TRAILING_STATEMENTS", - "trailing statements should be on next line\n" . $herecurr); - } - } -# if should not continue a brace - if ($line =~ /}\s*if\b/) { - ERROR("TRAILING_STATEMENTS", - "trailing statements should be on next line (or did you mean 'else if'?)\n" . - $herecurr); - } -# case and default should not have general statements after them - if ($line =~ /^.\s*(?:case\s*.*|default\s*):/g && - $line !~ /\G(?: - (?:\s*$;*)(?:\s*{)?(?:\s*$;*)(?:\s*\\)?\s*$| - \s*return\s+ - )/xg) - { - ERROR("TRAILING_STATEMENTS", - "trailing statements should be on next line\n" . $herecurr); - } - - # Check for }<nl>else {, these must be at the same - # indent level to be relevant to each other. - if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ && - $previndent == $indent) { - if (ERROR("ELSE_AFTER_BRACE", - "else should follow close brace '}'\n" . $hereprev) && - $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { - fix_delete_line($fixlinenr - 1, $prevrawline); - fix_delete_line($fixlinenr, $rawline); - my $fixedline = $prevrawline; - $fixedline =~ s/}\s*$//; - if ($fixedline !~ /^\+\s*$/) { - fix_insert_line($fixlinenr, $fixedline); - } - $fixedline = $rawline; - $fixedline =~ s/^(.\s*)else/$1} else/; - fix_insert_line($fixlinenr, $fixedline); - } - } - - if ($prevline=~/}\s*$/ and $line=~/^.\s*while\s*/ && - $previndent == $indent) { - my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0); - - # Find out what is on the end of the line after the - # conditional. - substr($s, 0, length($c), ''); - $s =~ s/\n.*//g; - - if ($s =~ /^\s*;/) { - if (ERROR("WHILE_AFTER_BRACE", - "while should follow close brace '}'\n" . $hereprev) && - $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { - fix_delete_line($fixlinenr - 1, $prevrawline); - fix_delete_line($fixlinenr, $rawline); - my $fixedline = $prevrawline; - my $trailing = $rawline; - $trailing =~ s/^\+//; - $trailing = trim($trailing); - $fixedline =~ s/}\s*$/} $trailing/; - fix_insert_line($fixlinenr, $fixedline); - } - } - } - -#Specific variable tests - while ($line =~ m{($Constant|$Lval)}g) { - my $var = $1; - -#gcc binary extension - if ($var =~ /^$Binary$/) { - if (WARN("GCC_BINARY_CONSTANT", - "Avoid gcc v4.3+ binary constant extension: <$var>\n" . $herecurr) && - $fix) { - my $hexval = sprintf("0x%x", oct($var)); - $fixed[$fixlinenr] =~ - s/\b$var\b/$hexval/; - } - } - -#CamelCase - if ($var !~ /^$Constant$/ && - $var =~ /[A-Z][a-z]|[a-z][A-Z]/ && -#Ignore Page<foo> variants - $var !~ /^(?:Clear|Set|TestClear|TestSet|)Page[A-Z]/ && -#Ignore SI style variants like nS, mV and dB (ie: max_uV, regulator_min_uA_show) - $var !~ /^(?:[a-z_]*?)_?[a-z][A-Z](?:_[a-z_]+)?$/ && -#Ignore some three character SI units explicitly, like MiB and KHz - $var !~ /^(?:[a-z_]*?)_?(?:[KMGT]iB|[KMGT]?Hz)(?:_[a-z_]+)?$/) { - while ($var =~ m{($Ident)}g) { - my $word = $1; - next if ($word !~ /[A-Z][a-z]|[a-z][A-Z]/); - if ($check) { - seed_camelcase_includes(); - if (!$file && !$camelcase_file_seeded) { - seed_camelcase_file($realfile); - $camelcase_file_seeded = 1; - } - } - if (!defined $camelcase{$word}) { - $camelcase{$word} = 1; - CHK("CAMELCASE", - "Avoid CamelCase: <$word>\n" . $herecurr); - } - } - } - } - -#no spaces allowed after \ in define - if ($line =~ /\#\s*define.*\\\s+$/) { - if (WARN("WHITESPACE_AFTER_LINE_CONTINUATION", - "Whitespace after \\ makes next lines useless\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\s+$//; - } - } - -# warn if <asm/foo.h> is #included and <linux/foo.h> is available and includes -# itself <asm/foo.h> (uses RAW line) - if ($tree && $rawline =~ m{^.\s*\#\s*include\s*\<asm\/(.*)\.h\>}) { - my $file = "$1.h"; - my $checkfile = "include/linux/$file"; - if (-f "$root/$checkfile" && - $realfile ne $checkfile && - $1 !~ /$allowed_asm_includes/) - { - my $asminclude = `grep -Ec "#include\\s+<asm/$file>" $root/$checkfile`; - if ($asminclude > 0) { - if ($realfile =~ m{^arch/}) { - CHK("ARCH_INCLUDE_LINUX", - "Consider using #include <linux/$file> instead of <asm/$file>\n" . $herecurr); - } else { - WARN("INCLUDE_LINUX", - "Use #include <linux/$file> instead of <asm/$file>\n" . $herecurr); - } - } - } - } - -# multi-statement macros should be enclosed in a do while loop, grab the -# first statement and ensure its the whole macro if its not enclosed -# in a known good container - if ($realfile !~ m@/vmlinux.lds.h$@ && - $line =~ /^.\s*\#\s*define\s*$Ident(\()?/) { - my $ln = $linenr; - my $cnt = $realcnt; - my ($off, $dstat, $dcond, $rest); - my $ctx = ''; - my $has_flow_statement = 0; - my $has_arg_concat = 0; - ($dstat, $dcond, $ln, $cnt, $off) = - ctx_statement_block($linenr, $realcnt, 0); - $ctx = $dstat; - #print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n"; - #print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n"; - - $has_flow_statement = 1 if ($ctx =~ /\b(goto|return)\b/); - $has_arg_concat = 1 if ($ctx =~ /\#\#/ && $ctx !~ /\#\#\s*(?:__VA_ARGS__|args)\b/); - - $dstat =~ s/^.\s*\#\s*define\s+$Ident(?:\([^\)]*\))?\s*//; - $dstat =~ s/$;//g; - $dstat =~ s/\\\n.//g; - $dstat =~ s/^\s*//s; - $dstat =~ s/\s*$//s; - - # Flatten any parentheses and braces - while ($dstat =~ s/\([^\(\)]*\)/1/ || - $dstat =~ s/\{[^\{\}]*\}/1/ || - $dstat =~ s/.\[[^\[\]]*\]/1/) - { - } - - # Flatten any obvious string concatentation. - while ($dstat =~ s/($String)\s*$Ident/$1/ || - $dstat =~ s/$Ident\s*($String)/$1/) - { - } - - # Make asm volatile uses seem like a generic function - $dstat =~ s/\b_*asm_*\s+_*volatile_*\b/asm_volatile/g; - - my $exceptions = qr{ - $Declare| - module_param_named| - MODULE_PARM_DESC| - DECLARE_PER_CPU| - DEFINE_PER_CPU| - __typeof__\(| - union| - struct| - \.$Ident\s*=\s*| - ^\"|\"$| - ^\[ - }x; - #print "REST<$rest> dstat<$dstat> ctx<$ctx>\n"; - if ($dstat ne '' && - $dstat !~ /^(?:$Ident|-?$Constant),$/ && # 10, // foo(), - $dstat !~ /^(?:$Ident|-?$Constant);$/ && # foo(); - $dstat !~ /^[!~-]?(?:$Lval|$Constant)$/ && # 10 // foo() // !foo // ~foo // -foo // foo->bar // foo.bar->baz - $dstat !~ /^'X'$/ && $dstat !~ /^'XX'$/ && # character constants - $dstat !~ /$exceptions/ && - $dstat !~ /^\.$Ident\s*=/ && # .foo = - $dstat !~ /^(?:\#\s*$Ident|\#\s*$Constant)\s*$/ && # stringification #foo - $dstat !~ /^do\s*$Constant\s*while\s*$Constant;?$/ && # do {...} while (...); // do {...} while (...) - $dstat !~ /^for\s*$Constant$/ && # for (...) - $dstat !~ /^for\s*$Constant\s+(?:$Ident|-?$Constant)$/ && # for (...) bar() - $dstat !~ /^do\s*{/ && # do {... - $dstat !~ /^\(\{/ && # ({... - $ctx !~ /^.\s*#\s*define\s+TRACE_(?:SYSTEM|INCLUDE_FILE|INCLUDE_PATH)\b/) - { - $ctx =~ s/\n*$//; - my $herectx = $here . "\n"; - my $cnt = statement_rawlines($ctx); - - for (my $n = 0; $n < $cnt; $n++) { - $herectx .= raw_line($linenr, $n) . "\n"; - } - - if ($dstat =~ /;/) { - ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE", - "Macros with multiple statements should be enclosed in a do - while loop\n" . "$herectx"); - } else { - ERROR("COMPLEX_MACRO", - "Macros with complex values should be enclosed in parentheses\n" . "$herectx"); - } - } - -# check for macros with flow control, but without ## concatenation -# ## concatenation is commonly a macro that defines a function so ignore those - if ($has_flow_statement && !$has_arg_concat) { - my $herectx = $here . "\n"; - my $cnt = statement_rawlines($ctx); - - for (my $n = 0; $n < $cnt; $n++) { - $herectx .= raw_line($linenr, $n) . "\n"; - } - WARN("MACRO_WITH_FLOW_CONTROL", - "Macros with flow control statements should be avoided\n" . "$herectx"); - } - -# check for line continuations outside of #defines, preprocessor #, and asm - - } else { - if ($prevline !~ /^..*\\$/ && - $line !~ /^\+\s*\#.*\\$/ && # preprocessor - $line !~ /^\+.*\b(__asm__|asm)\b.*\\$/ && # asm - $line =~ /^\+.*\\$/) { - WARN("LINE_CONTINUATIONS", - "Avoid unnecessary line continuations\n" . $herecurr); - } - } - -# do {} while (0) macro tests: -# single-statement macros do not need to be enclosed in do while (0) loop, -# macro should not end with a semicolon - if ($^V && $^V ge 5.10.0 && - $realfile !~ m@/vmlinux.lds.h$@ && - $line =~ /^.\s*\#\s*define\s+$Ident(\()?/) { - my $ln = $linenr; - my $cnt = $realcnt; - my ($off, $dstat, $dcond, $rest); - my $ctx = ''; - ($dstat, $dcond, $ln, $cnt, $off) = - ctx_statement_block($linenr, $realcnt, 0); - $ctx = $dstat; - - $dstat =~ s/\\\n.//g; - $dstat =~ s/$;/ /g; - - if ($dstat =~ /^\+\s*#\s*define\s+$Ident\s*${balanced_parens}\s*do\s*{(.*)\s*}\s*while\s*\(\s*0\s*\)\s*([;\s]*)\s*$/) { - my $stmts = $2; - my $semis = $3; - - $ctx =~ s/\n*$//; - my $cnt = statement_rawlines($ctx); - my $herectx = $here . "\n"; - - for (my $n = 0; $n < $cnt; $n++) { - $herectx .= raw_line($linenr, $n) . "\n"; - } - - if (($stmts =~ tr/;/;/) == 1 && - $stmts !~ /^\s*(if|while|for|switch)\b/) { - WARN("SINGLE_STATEMENT_DO_WHILE_MACRO", - "Single statement macros should not use a do {} while (0) loop\n" . "$herectx"); - } - if (defined $semis && $semis ne "") { - WARN("DO_WHILE_MACRO_WITH_TRAILING_SEMICOLON", - "do {} while (0) macros should not be semicolon terminated\n" . "$herectx"); - } - } elsif ($dstat =~ /^\+\s*#\s*define\s+$Ident.*;\s*$/) { - $ctx =~ s/\n*$//; - my $cnt = statement_rawlines($ctx); - my $herectx = $here . "\n"; - - for (my $n = 0; $n < $cnt; $n++) { - $herectx .= raw_line($linenr, $n) . "\n"; - } - - WARN("TRAILING_SEMICOLON", - "macros should not use a trailing semicolon\n" . "$herectx"); - } - } - -# make sure symbols are always wrapped with VMLINUX_SYMBOL() ... -# all assignments may have only one of the following with an assignment: -# . -# ALIGN(...) -# VMLINUX_SYMBOL(...) - if ($realfile eq 'vmlinux.lds.h' && $line =~ /(?:(?:^|\s)$Ident\s*=|=\s*$Ident(?:\s|$))/) { - WARN("MISSING_VMLINUX_SYMBOL", - "vmlinux.lds.h needs VMLINUX_SYMBOL() around C-visible symbols\n" . $herecurr); - } - -# check for redundant bracing round if etc - if ($line =~ /(^.*)\bif\b/ && $1 !~ /else\s*$/) { - my ($level, $endln, @chunks) = - ctx_statement_full($linenr, $realcnt, 1); - #print "chunks<$#chunks> linenr<$linenr> endln<$endln> level<$level>\n"; - #print "APW: <<$chunks[1][0]>><<$chunks[1][1]>>\n"; - if ($#chunks > 0 && $level == 0) { - my @allowed = (); - my $allow = 0; - my $seen = 0; - my $herectx = $here . "\n"; - my $ln = $linenr - 1; - for my $chunk (@chunks) { - my ($cond, $block) = @{$chunk}; - - # If the condition carries leading newlines, then count those as offsets. - my ($whitespace) = ($cond =~ /^((?:\s*\n[+-])*\s*)/s); - my $offset = statement_rawlines($whitespace) - 1; - - $allowed[$allow] = 0; - #print "COND<$cond> whitespace<$whitespace> offset<$offset>\n"; - - # We have looked at and allowed this specific line. - $suppress_ifbraces{$ln + $offset} = 1; - - $herectx .= "$rawlines[$ln + $offset]\n[...]\n"; - $ln += statement_rawlines($block) - 1; - - substr($block, 0, length($cond), ''); - - $seen++ if ($block =~ /^\s*{/); - - #print "cond<$cond> block<$block> allowed<$allowed[$allow]>\n"; - if (statement_lines($cond) > 1) { - #print "APW: ALLOWED: cond<$cond>\n"; - $allowed[$allow] = 1; - } - if ($block =~/\b(?:if|for|while)\b/) { - #print "APW: ALLOWED: block<$block>\n"; - $allowed[$allow] = 1; - } - if (statement_block_size($block) > 1) { - #print "APW: ALLOWED: lines block<$block>\n"; - $allowed[$allow] = 1; - } - $allow++; - } - if ($seen) { - my $sum_allowed = 0; - foreach (@allowed) { - $sum_allowed += $_; - } - if ($sum_allowed == 0) { - WARN("BRACES", - "braces {} are not necessary for any arm of this statement\n" . $herectx); - } elsif ($sum_allowed != $allow && - $seen != $allow) { - CHK("BRACES", - "braces {} should be used on all arms of this statement\n" . $herectx); - } - } - } - } - if (!defined $suppress_ifbraces{$linenr - 1} && - $line =~ /\b(if|while|for|else)\b/) { - my $allowed = 0; - - # Check the pre-context. - if (substr($line, 0, $-[0]) =~ /(\}\s*)$/) { - #print "APW: ALLOWED: pre<$1>\n"; - $allowed = 1; - } - - my ($level, $endln, @chunks) = - ctx_statement_full($linenr, $realcnt, $-[0]); - - # Check the condition. - my ($cond, $block) = @{$chunks[0]}; - #print "CHECKING<$linenr> cond<$cond> block<$block>\n"; - if (defined $cond) { - substr($block, 0, length($cond), ''); - } - if (statement_lines($cond) > 1) { - #print "APW: ALLOWED: cond<$cond>\n"; - $allowed = 1; - } - if ($block =~/\b(?:if|for|while)\b/) { - #print "APW: ALLOWED: block<$block>\n"; - $allowed = 1; - } - if (statement_block_size($block) > 1) { - #print "APW: ALLOWED: lines block<$block>\n"; - $allowed = 1; - } - # Check the post-context. - if (defined $chunks[1]) { - my ($cond, $block) = @{$chunks[1]}; - if (defined $cond) { - substr($block, 0, length($cond), ''); - } - if ($block =~ /^\s*\{/) { - #print "APW: ALLOWED: chunk-1 block<$block>\n"; - $allowed = 1; - } - } - if ($level == 0 && $block =~ /^\s*\{/ && !$allowed) { - my $herectx = $here . "\n"; - my $cnt = statement_rawlines($block); - - for (my $n = 0; $n < $cnt; $n++) { - $herectx .= raw_line($linenr, $n) . "\n"; - } - - WARN("BRACES", - "braces {} are not necessary for single statement blocks\n" . $herectx); - } - } - -# check for unnecessary blank lines around braces - if (($line =~ /^.\s*}\s*$/ && $prevrawline =~ /^.\s*$/)) { - if (CHK("BRACES", - "Blank lines aren't necessary before a close brace '}'\n" . $hereprev) && - $fix && $prevrawline =~ /^\+/) { - fix_delete_line($fixlinenr - 1, $prevrawline); - } - } - if (($rawline =~ /^.\s*$/ && $prevline =~ /^..*{\s*$/)) { - if (CHK("BRACES", - "Blank lines aren't necessary after an open brace '{'\n" . $hereprev) && - $fix) { - fix_delete_line($fixlinenr, $rawline); - } - } - -# no volatiles please - my $asm_volatile = qr{\b(__asm__|asm)\s+(__volatile__|volatile)\b}; - if ($line =~ /\bvolatile\b/ && $line !~ /$asm_volatile/) { - WARN("VOLATILE", - "Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n" . $herecurr); - } - -# Check for user-visible strings broken across lines, which breaks the ability -# to grep for the string. Make exceptions when the previous string ends in a -# newline (multiple lines in one string constant) or '\t', '\r', ';', or '{' -# (common in inline assembly) or is a octal \123 or hexadecimal \xaf value - if ($line =~ /^\+\s*$String/ && - $prevline =~ /"\s*$/ && - $prevrawline !~ /(?:\\(?:[ntr]|[0-7]{1,3}|x[0-9a-fA-F]{1,2})|;\s*|\{\s*)"\s*$/) { - if (WARN("SPLIT_STRING", - "quoted string split across lines\n" . $hereprev) && - $fix && - $prevrawline =~ /^\+.*"\s*$/ && - $last_coalesced_string_linenr != $linenr - 1) { - my $extracted_string = get_quoted_string($line, $rawline); - my $comma_close = ""; - if ($rawline =~ /\Q$extracted_string\E(\s*\)\s*;\s*$|\s*,\s*)/) { - $comma_close = $1; - } - - fix_delete_line($fixlinenr - 1, $prevrawline); - fix_delete_line($fixlinenr, $rawline); - my $fixedline = $prevrawline; - $fixedline =~ s/"\s*$//; - $fixedline .= substr($extracted_string, 1) . trim($comma_close); - fix_insert_line($fixlinenr - 1, $fixedline); - $fixedline = $rawline; - $fixedline =~ s/\Q$extracted_string\E\Q$comma_close\E//; - if ($fixedline !~ /\+\s*$/) { - fix_insert_line($fixlinenr, $fixedline); - } - $last_coalesced_string_linenr = $linenr; - } - } - -# check for missing a space in a string concatenation - if ($prevrawline =~ /[^\\]\w"$/ && $rawline =~ /^\+[\t ]+"\w/) { - WARN('MISSING_SPACE', - "break quoted strings at a space character\n" . $hereprev); - } - -# check for spaces before a quoted newline - if ($rawline =~ /^.*\".*\s\\n/) { - if (WARN("QUOTED_WHITESPACE_BEFORE_NEWLINE", - "unnecessary whitespace before a quoted newline\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/^(\+.*\".*)\s+\\n/$1\\n/; - } - - } - -# concatenated string without spaces between elements - if ($line =~ /$String[A-Z_]/ || $line =~ /[A-Za-z0-9_]$String/) { - CHK("CONCATENATED_STRING", - "Concatenated strings should use spaces between elements\n" . $herecurr); - } - -# uncoalesced string fragments - if ($line =~ /$String\s*"/) { - WARN("STRING_FRAGMENTS", - "Consecutive strings are generally better as a single string\n" . $herecurr); - } - -# check for %L{u,d,i} and 0x%[udi] in strings - my $string; - while ($line =~ /(?:^|")([X\t]*)(?:"|$)/g) { - $string = substr($rawline, $-[1], $+[1] - $-[1]); - $string =~ s/%%/__/g; - if ($string =~ /(?<!%)%[\*\d\.\$]*L[udi]/) { - WARN("PRINTF_L", - "\%Ld/%Lu are not-standard C, use %lld/%llu\n" . $herecurr); - last; - } - if ($string =~ /0x%[\*\d\.\$\Llzth]*[udi]/) { - ERROR("PRINTF_0xDECIMAL", - "Prefixing 0x with decimal output is defective\n" . $herecurr); - } - } - -# check for line continuations in quoted strings with odd counts of " - if ($rawline =~ /\\$/ && $rawline =~ tr/"/"/ % 2) { - WARN("LINE_CONTINUATIONS", - "Avoid line continuations in quoted strings\n" . $herecurr); - } - -# warn about #if 0 - if ($line =~ /^.\s*\#\s*if\s+0\b/) { - CHK("REDUNDANT_CODE", - "if this code is redundant consider removing it\n" . - $herecurr); - } - -# check for needless "if (<foo>) fn(<foo>)" uses - if ($prevline =~ /\bif\s*\(\s*($Lval)\s*\)/) { - my $tested = quotemeta($1); - my $expr = '\s*\(\s*' . $tested . '\s*\)\s*;'; - if ($line =~ /\b(kfree|usb_free_urb|debugfs_remove(?:_recursive)?|(?:kmem_cache|mempool|dma_pool)_destroy)$expr/) { - my $func = $1; - if (WARN('NEEDLESS_IF', - "$func(NULL) is safe and this check is probably not required\n" . $hereprev) && - $fix) { - my $do_fix = 1; - my $leading_tabs = ""; - my $new_leading_tabs = ""; - if ($lines[$linenr - 2] =~ /^\+(\t*)if\s*\(\s*$tested\s*\)\s*$/) { - $leading_tabs = $1; - } else { - $do_fix = 0; - } - if ($lines[$linenr - 1] =~ /^\+(\t+)$func\s*\(\s*$tested\s*\)\s*;\s*$/) { - $new_leading_tabs = $1; - if (length($leading_tabs) + 1 ne length($new_leading_tabs)) { - $do_fix = 0; - } - } else { - $do_fix = 0; - } - if ($do_fix) { - fix_delete_line($fixlinenr - 1, $prevrawline); - $fixed[$fixlinenr] =~ s/^\+$new_leading_tabs/\+$leading_tabs/; - } - } - } - } - -# check for unnecessary "Out of Memory" messages - if ($line =~ /^\+.*\b$logFunctions\s*\(/ && - $prevline =~ /^[ \+]\s*if\s*\(\s*(\!\s*|NULL\s*==\s*)?($Lval)(\s*==\s*NULL\s*)?\s*\)/ && - (defined $1 || defined $3) && - $linenr > 3) { - my $testval = $2; - my $testline = $lines[$linenr - 3]; - - my ($s, $c) = ctx_statement_block($linenr - 3, $realcnt, 0); -# print("line: <$line>\nprevline: <$prevline>\ns: <$s>\nc: <$c>\n\n\n"); - - if ($c =~ /(?:^|\n)[ \+]\s*(?:$Type\s*)?\Q$testval\E\s*=\s*(?:\([^\)]*\)\s*)?\s*(?:devm_)?(?:[kv][czm]alloc(?:_node|_array)?\b|kstrdup|(?:dev_)?alloc_skb)/) { - WARN("OOM_MESSAGE", - "Possible unnecessary 'out of memory' message\n" . $hereprev); - } - } - -# check for logging functions with KERN_<LEVEL> - if ($line !~ /printk(?:_ratelimited|_once)?\s*\(/ && - $line =~ /\b$logFunctions\s*\(.*\b(KERN_[A-Z]+)\b/) { - my $level = $1; - if (WARN("UNNECESSARY_KERN_LEVEL", - "Possible unnecessary $level\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\s*$level\s*//; - } - } - -# check for mask then right shift without a parentheses - if ($^V && $^V ge 5.10.0 && - $line =~ /$LvalOrFunc\s*\&\s*($LvalOrFunc)\s*>>/ && - $4 !~ /^\&/) { # $LvalOrFunc may be &foo, ignore if so - WARN("MASK_THEN_SHIFT", - "Possible precedence defect with mask then right shift - may need parentheses\n" . $herecurr); - } - -# check for pointer comparisons to NULL - if ($^V && $^V ge 5.10.0) { - while ($line =~ /\b$LvalOrFunc\s*(==|\!=)\s*NULL\b/g) { - my $val = $1; - my $equal = "!"; - $equal = "" if ($4 eq "!="); - if (CHK("COMPARISON_TO_NULL", - "Comparison to NULL could be written \"${equal}${val}\"\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b\Q$val\E\s*(?:==|\!=)\s*NULL\b/$equal$val/; - } - } - } - -# check for bad placement of section $InitAttribute (e.g.: __initdata) - if ($line =~ /(\b$InitAttribute\b)/) { - my $attr = $1; - if ($line =~ /^\+\s*static\s+(?:const\s+)?(?:$attr\s+)?($NonptrTypeWithAttr)\s+(?:$attr\s+)?($Ident(?:\[[^]]*\])?)\s*[=;]/) { - my $ptr = $1; - my $var = $2; - if ((($ptr =~ /\b(union|struct)\s+$attr\b/ && - ERROR("MISPLACED_INIT", - "$attr should be placed after $var\n" . $herecurr)) || - ($ptr !~ /\b(union|struct)\s+$attr\b/ && - WARN("MISPLACED_INIT", - "$attr should be placed after $var\n" . $herecurr))) && - $fix) { - $fixed[$fixlinenr] =~ s/(\bstatic\s+(?:const\s+)?)(?:$attr\s+)?($NonptrTypeWithAttr)\s+(?:$attr\s+)?($Ident(?:\[[^]]*\])?)\s*([=;])\s*/"$1" . trim(string_find_replace($2, "\\s*$attr\\s*", " ")) . " " . trim(string_find_replace($3, "\\s*$attr\\s*", "")) . " $attr" . ("$4" eq ";" ? ";" : " = ")/e; - } - } - } - -# check for $InitAttributeData (ie: __initdata) with const - if ($line =~ /\bconst\b/ && $line =~ /($InitAttributeData)/) { - my $attr = $1; - $attr =~ /($InitAttributePrefix)(.*)/; - my $attr_prefix = $1; - my $attr_type = $2; - if (ERROR("INIT_ATTRIBUTE", - "Use of const init definition must use ${attr_prefix}initconst\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/$InitAttributeData/${attr_prefix}initconst/; - } - } - -# check for $InitAttributeConst (ie: __initconst) without const - if ($line !~ /\bconst\b/ && $line =~ /($InitAttributeConst)/) { - my $attr = $1; - if (ERROR("INIT_ATTRIBUTE", - "Use of $attr requires a separate use of const\n" . $herecurr) && - $fix) { - my $lead = $fixed[$fixlinenr] =~ - /(^\+\s*(?:static\s+))/; - $lead = rtrim($1); - $lead = "$lead " if ($lead !~ /^\+$/); - $lead = "${lead}const "; - $fixed[$fixlinenr] =~ s/(^\+\s*(?:static\s+))/$lead/; - } - } - -# check for __read_mostly with const non-pointer (should just be const) - if ($line =~ /\b__read_mostly\b/ && - $line =~ /($Type)\s*$Ident/ && $1 !~ /\*\s*$/ && $1 =~ /\bconst\b/) { - if (ERROR("CONST_READ_MOSTLY", - "Invalid use of __read_mostly with const type\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\s+__read_mostly\b//; - } - } - -# don't use __constant_<foo> functions outside of include/uapi/ - if ($realfile !~ m@^include/uapi/@ && - $line =~ /(__constant_(?:htons|ntohs|[bl]e(?:16|32|64)_to_cpu|cpu_to_[bl]e(?:16|32|64)))\s*\(/) { - my $constant_func = $1; - my $func = $constant_func; - $func =~ s/^__constant_//; - if (WARN("CONSTANT_CONVERSION", - "$constant_func should be $func\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b$constant_func\b/$func/g; - } - } - -# prefer usleep_range over udelay - if ($line =~ /\budelay\s*\(\s*(\d+)\s*\)/) { - my $delay = $1; - # ignore udelay's < 10, however - if (! ($delay < 10) ) { - CHK("USLEEP_RANGE", - "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt\n" . $herecurr); - } - if ($delay > 2000) { - WARN("LONG_UDELAY", - "long udelay - prefer mdelay; see arch/arm/include/asm/delay.h\n" . $herecurr); - } - } - -# warn about unexpectedly long msleep's - if ($line =~ /\bmsleep\s*\((\d+)\);/) { - if ($1 < 20) { - WARN("MSLEEP", - "msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt\n" . $herecurr); - } - } - -# check for comparisons of jiffies - if ($line =~ /\bjiffies\s*$Compare|$Compare\s*jiffies\b/) { - WARN("JIFFIES_COMPARISON", - "Comparing jiffies is almost always wrong; prefer time_after, time_before and friends\n" . $herecurr); - } - -# check for comparisons of get_jiffies_64() - if ($line =~ /\bget_jiffies_64\s*\(\s*\)\s*$Compare|$Compare\s*get_jiffies_64\s*\(\s*\)/) { - WARN("JIFFIES_COMPARISON", - "Comparing get_jiffies_64() is almost always wrong; prefer time_after64, time_before64 and friends\n" . $herecurr); - } - -# warn about #ifdefs in C files -# if ($line =~ /^.\s*\#\s*if(|n)def/ && ($realfile =~ /\.c$/)) { -# print "#ifdef in C files should be avoided\n"; -# print "$herecurr"; -# $clean = 0; -# } - -# warn about spacing in #ifdefs - if ($line =~ /^.\s*\#\s*(ifdef|ifndef|elif)\s\s+/) { - if (ERROR("SPACING", - "exactly one space required after that #$1\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/^(.\s*\#\s*(ifdef|ifndef|elif))\s{2,}/$1 /; - } - - } - -# check for spinlock_t definitions without a comment. - if ($line =~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/ || - $line =~ /^.\s*(DEFINE_MUTEX)\s*\(/) { - my $which = $1; - if (!ctx_has_comment($first_line, $linenr)) { - CHK("UNCOMMENTED_DEFINITION", - "$1 definition without comment\n" . $herecurr); - } - } -# check for memory barriers without a comment. - - my $barriers = qr{ - mb| - rmb| - wmb| - read_barrier_depends - }x; - my $barrier_stems = qr{ - mb__before_atomic| - mb__after_atomic| - store_release| - load_acquire| - store_mb| - (?:$barriers) - }x; - my $all_barriers = qr{ - (?:$barriers)| - smp_(?:$barrier_stems)| - virt_(?:$barrier_stems) - }x; - - if ($line =~ /\b(?:$all_barriers)\s*\(/) { - if (!ctx_has_comment($first_line, $linenr)) { - WARN("MEMORY_BARRIER", - "memory barrier without comment\n" . $herecurr); - } - } - - my $underscore_smp_barriers = qr{__smp_(?:$barrier_stems)}x; - - if ($realfile !~ m@^include/asm-generic/@ && - $realfile !~ m@/barrier\.h$@ && - $line =~ m/\b(?:$underscore_smp_barriers)\s*\(/ && - $line !~ m/^.\s*\#\s*define\s+(?:$underscore_smp_barriers)\s*\(/) { - WARN("MEMORY_BARRIER", - "__smp memory barriers shouldn't be used outside barrier.h and asm-generic\n" . $herecurr); - } - -# check for waitqueue_active without a comment. - if ($line =~ /\bwaitqueue_active\s*\(/) { - if (!ctx_has_comment($first_line, $linenr)) { - WARN("WAITQUEUE_ACTIVE", - "waitqueue_active without comment\n" . $herecurr); - } - } - -# Check for expedited grace periods that interrupt non-idle non-nohz -# online CPUs. These expedited can therefore degrade real-time response -# if used carelessly, and should be avoided where not absolutely -# needed. It is always OK to use synchronize_rcu_expedited() and -# synchronize_sched_expedited() at boot time (before real-time applications -# start) and in error situations where real-time response is compromised in -# any case. Note that synchronize_srcu_expedited() does -not- interrupt -# other CPUs, so don't warn on uses of synchronize_srcu_expedited(). -# Of course, nothing comes for free, and srcu_read_lock() and -# srcu_read_unlock() do contain full memory barriers in payment for -# synchronize_srcu_expedited() non-interruption properties. - if ($line =~ /\b(synchronize_rcu_expedited|synchronize_sched_expedited)\(/) { - WARN("EXPEDITED_RCU_GRACE_PERIOD", - "expedited RCU grace periods should be avoided where they can degrade real-time response\n" . $herecurr); - - } - -# check of hardware specific defines - if ($line =~ m@^.\s*\#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@ && $realfile !~ m@include/asm-@) { - CHK("ARCH_DEFINES", - "architecture specific defines should be avoided\n" . $herecurr); - } - -# Check that the storage class is at the beginning of a declaration - if ($line =~ /\b$Storage\b/ && $line !~ /^.\s*$Storage\b/) { - WARN("STORAGE_CLASS", - "storage class should be at the beginning of the declaration\n" . $herecurr) - } - -# check the location of the inline attribute, that it is between -# storage class and type. - if ($line =~ /\b$Type\s+$Inline\b/ || - $line =~ /\b$Inline\s+$Storage\b/) { - ERROR("INLINE_LOCATION", - "inline keyword should sit between storage class and type\n" . $herecurr); - } - -# Check for __inline__ and __inline, prefer inline - if ($realfile !~ m@\binclude/uapi/@ && - $line =~ /\b(__inline__|__inline)\b/) { - if (WARN("INLINE", - "plain inline is preferred over $1\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b(__inline__|__inline)\b/inline/; - - } - } - -# Check for __attribute__ packed, prefer __packed - if ($realfile !~ m@\binclude/uapi/@ && - $line =~ /\b__attribute__\s*\(\s*\(.*\bpacked\b/) { - WARN("PREFER_PACKED", - "__packed is preferred over __attribute__((packed))\n" . $herecurr); - } - -# Check for __attribute__ aligned, prefer __aligned - if ($realfile !~ m@\binclude/uapi/@ && - $line =~ /\b__attribute__\s*\(\s*\(.*aligned/) { - WARN("PREFER_ALIGNED", - "__aligned(size) is preferred over __attribute__((aligned(size)))\n" . $herecurr); - } - -# Check for __attribute__ format(printf, prefer __printf - if ($realfile !~ m@\binclude/uapi/@ && - $line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf/) { - if (WARN("PREFER_PRINTF", - "__printf(string-index, first-to-check) is preferred over __attribute__((format(printf, string-index, first-to-check)))\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf\s*,\s*(.*)\)\s*\)\s*\)/"__printf(" . trim($1) . ")"/ex; - - } - } - -# Check for __attribute__ format(scanf, prefer __scanf - if ($realfile !~ m@\binclude/uapi/@ && - $line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\b/) { - if (WARN("PREFER_SCANF", - "__scanf(string-index, first-to-check) is preferred over __attribute__((format(scanf, string-index, first-to-check)))\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\s*,\s*(.*)\)\s*\)\s*\)/"__scanf(" . trim($1) . ")"/ex; - } - } - -# Check for __attribute__ weak, or __weak declarations (may have link issues) - if ($^V && $^V ge 5.10.0 && - $line =~ /(?:$Declare|$DeclareMisordered)\s*$Ident\s*$balanced_parens\s*(?:$Attribute)?\s*;/ && - ($line =~ /\b__attribute__\s*\(\s*\(.*\bweak\b/ || - $line =~ /\b__weak\b/)) { - ERROR("WEAK_DECLARATION", - "Using weak declarations can have unintended link defects\n" . $herecurr); - } - -# check for c99 types like uint8_t used outside of uapi/ - if ($realfile !~ m@\binclude/uapi/@ && - $line =~ /\b($Declare)\s*$Ident\s*[=;,\[]/) { - my $type = $1; - if ($type =~ /\b($typeC99Typedefs)\b/) { - $type = $1; - my $kernel_type = 'u'; - $kernel_type = 's' if ($type =~ /^_*[si]/); - $type =~ /(\d+)/; - $kernel_type .= $1; - if (CHK("PREFER_KERNEL_TYPES", - "Prefer kernel type '$kernel_type' over '$type'\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b$type\b/$kernel_type/; - } - } - } - -# check for cast of C90 native int or longer types constants - if ($line =~ /(\(\s*$C90_int_types\s*\)\s*)($Constant)\b/) { - my $cast = $1; - my $const = $2; - if (WARN("TYPECAST_INT_CONSTANT", - "Unnecessary typecast of c90 int constant\n" . $herecurr) && - $fix) { - my $suffix = ""; - my $newconst = $const; - $newconst =~ s/${Int_type}$//; - $suffix .= 'U' if ($cast =~ /\bunsigned\b/); - if ($cast =~ /\blong\s+long\b/) { - $suffix .= 'LL'; - } elsif ($cast =~ /\blong\b/) { - $suffix .= 'L'; - } - $fixed[$fixlinenr] =~ s/\Q$cast\E$const\b/$newconst$suffix/; - } - } - -# check for sizeof(&) - if ($line =~ /\bsizeof\s*\(\s*\&/) { - WARN("SIZEOF_ADDRESS", - "sizeof(& should be avoided\n" . $herecurr); - } - -# check for sizeof without parenthesis - if ($line =~ /\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/) { - if (WARN("SIZEOF_PARENTHESIS", - "sizeof $1 should be sizeof($1)\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/"sizeof(" . trim($1) . ")"/ex; - } - } - -# check for struct spinlock declarations - if ($line =~ /^.\s*\bstruct\s+spinlock\s+\w+\s*;/) { - WARN("USE_SPINLOCK_T", - "struct spinlock should be spinlock_t\n" . $herecurr); - } - -# check for seq_printf uses that could be seq_puts - if ($sline =~ /\bseq_printf\s*\(.*"\s*\)\s*;\s*$/) { - my $fmt = get_quoted_string($line, $rawline); - $fmt =~ s/%%//g; - if ($fmt !~ /%/) { - if (WARN("PREFER_SEQ_PUTS", - "Prefer seq_puts to seq_printf\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\bseq_printf\b/seq_puts/; - } - } - } - -# Check for misused memsets - if ($^V && $^V ge 5.10.0 && - defined $stat && - $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*$FuncArg\s*\)/) { - - my $ms_addr = $2; - my $ms_val = $7; - my $ms_size = $12; - - if ($ms_size =~ /^(0x|)0$/i) { - ERROR("MEMSET", - "memset to 0's uses 0 as the 2nd argument, not the 3rd\n" . "$here\n$stat\n"); - } elsif ($ms_size =~ /^(0x|)1$/i) { - WARN("MEMSET", - "single byte memset is suspicious. Swapped 2nd/3rd argument?\n" . "$here\n$stat\n"); - } - } - -# Check for memcpy(foo, bar, ETH_ALEN) that could be ether_addr_copy(foo, bar) - if ($^V && $^V ge 5.10.0 && - defined $stat && - $stat =~ /^\+(?:.*?)\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) { - if (WARN("PREFER_ETHER_ADDR_COPY", - "Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2)\n" . "$here\n$stat\n") && - $fix) { - $fixed[$fixlinenr] =~ s/\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/ether_addr_copy($2, $7)/; - } - } - -# Check for memcmp(foo, bar, ETH_ALEN) that could be ether_addr_equal*(foo, bar) - if ($^V && $^V ge 5.10.0 && - defined $stat && - $stat =~ /^\+(?:.*?)\bmemcmp\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) { - WARN("PREFER_ETHER_ADDR_EQUAL", - "Prefer ether_addr_equal() or ether_addr_equal_unaligned() over memcmp()\n" . "$here\n$stat\n") - } - -# check for memset(foo, 0x0, ETH_ALEN) that could be eth_zero_addr -# check for memset(foo, 0xFF, ETH_ALEN) that could be eth_broadcast_addr - if ($^V && $^V ge 5.10.0 && - defined $stat && - $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) { - - my $ms_val = $7; - - if ($ms_val =~ /^(?:0x|)0+$/i) { - if (WARN("PREFER_ETH_ZERO_ADDR", - "Prefer eth_zero_addr over memset()\n" . "$here\n$stat\n") && - $fix) { - $fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_zero_addr($2)/; - } - } elsif ($ms_val =~ /^(?:0xff|255)$/i) { - if (WARN("PREFER_ETH_BROADCAST_ADDR", - "Prefer eth_broadcast_addr() over memset()\n" . "$here\n$stat\n") && - $fix) { - $fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_broadcast_addr($2)/; - } - } - } - -# typecasts on min/max could be min_t/max_t - if ($^V && $^V ge 5.10.0 && - defined $stat && - $stat =~ /^\+(?:.*?)\b(min|max)\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\)/) { - if (defined $2 || defined $7) { - my $call = $1; - my $cast1 = deparenthesize($2); - my $arg1 = $3; - my $cast2 = deparenthesize($7); - my $arg2 = $8; - my $cast; - - if ($cast1 ne "" && $cast2 ne "" && $cast1 ne $cast2) { - $cast = "$cast1 or $cast2"; - } elsif ($cast1 ne "") { - $cast = $cast1; - } else { - $cast = $cast2; - } - WARN("MINMAX", - "$call() should probably be ${call}_t($cast, $arg1, $arg2)\n" . "$here\n$stat\n"); - } - } - -# check usleep_range arguments - if ($^V && $^V ge 5.10.0 && - defined $stat && - $stat =~ /^\+(?:.*?)\busleep_range\s*\(\s*($FuncArg)\s*,\s*($FuncArg)\s*\)/) { - my $min = $1; - my $max = $7; - if ($min eq $max) { - WARN("USLEEP_RANGE", - "usleep_range should not use min == max args; see Documentation/timers/timers-howto.txt\n" . "$here\n$stat\n"); - } elsif ($min =~ /^\d+$/ && $max =~ /^\d+$/ && - $min > $max) { - WARN("USLEEP_RANGE", - "usleep_range args reversed, use min then max; see Documentation/timers/timers-howto.txt\n" . "$here\n$stat\n"); - } - } - -# check for naked sscanf - if ($^V && $^V ge 5.10.0 && - defined $stat && - $line =~ /\bsscanf\b/ && - ($stat !~ /$Ident\s*=\s*sscanf\s*$balanced_parens/ && - $stat !~ /\bsscanf\s*$balanced_parens\s*(?:$Compare)/ && - $stat !~ /(?:$Compare)\s*\bsscanf\s*$balanced_parens/)) { - my $lc = $stat =~ tr@\n@@; - $lc = $lc + $linenr; - my $stat_real = raw_line($linenr, 0); - for (my $count = $linenr + 1; $count <= $lc; $count++) { - $stat_real = $stat_real . "\n" . raw_line($count, 0); - } - WARN("NAKED_SSCANF", - "unchecked sscanf return value\n" . "$here\n$stat_real\n"); - } - -# check for simple sscanf that should be kstrto<foo> - if ($^V && $^V ge 5.10.0 && - defined $stat && - $line =~ /\bsscanf\b/) { - my $lc = $stat =~ tr@\n@@; - $lc = $lc + $linenr; - my $stat_real = raw_line($linenr, 0); - for (my $count = $linenr + 1; $count <= $lc; $count++) { - $stat_real = $stat_real . "\n" . raw_line($count, 0); - } - if ($stat_real =~ /\bsscanf\b\s*\(\s*$FuncArg\s*,\s*("[^"]+")/) { - my $format = $6; - my $count = $format =~ tr@%@%@; - if ($count == 1 && - $format =~ /^"\%(?i:ll[udxi]|[udxi]ll|ll|[hl]h?[udxi]|[udxi][hl]h?|[hl]h?|[udxi])"$/) { - WARN("SSCANF_TO_KSTRTO", - "Prefer kstrto<type> to single variable sscanf\n" . "$here\n$stat_real\n"); - } - } - } - -# check for new externs in .h files. - if ($realfile =~ /\.h$/ && - $line =~ /^\+\s*(extern\s+)$Type\s*$Ident\s*\(/s) { - if (CHK("AVOID_EXTERNS", - "extern prototypes should be avoided in .h files\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/(.*)\bextern\b\s*(.*)/$1$2/; - } - } - -# check for new externs in .c files. - if ($realfile =~ /\.c$/ && defined $stat && - $stat =~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s) - { - my $function_name = $1; - my $paren_space = $2; - - my $s = $stat; - if (defined $cond) { - substr($s, 0, length($cond), ''); - } - if ($s =~ /^\s*;/ && - $function_name ne 'uninitialized_var') - { - WARN("AVOID_EXTERNS", - "externs should be avoided in .c files\n" . $herecurr); - } - - if ($paren_space =~ /\n/) { - WARN("FUNCTION_ARGUMENTS", - "arguments for function declarations should follow identifier\n" . $herecurr); - } - - } elsif ($realfile =~ /\.c$/ && defined $stat && - $stat =~ /^.\s*extern\s+/) - { - WARN("AVOID_EXTERNS", - "externs should be avoided in .c files\n" . $herecurr); - } - -# checks for new __setup's - if ($rawline =~ /\b__setup\("([^"]*)"/) { - my $name = $1; - - if (!grep(/$name/, @setup_docs)) { - CHK("UNDOCUMENTED_SETUP", - "__setup appears un-documented -- check Documentation/kernel-parameters.txt\n" . $herecurr); - } - } - -# check for pointless casting of kmalloc return - if ($line =~ /\*\s*\)\s*[kv][czm]alloc(_node){0,1}\b/) { - WARN("UNNECESSARY_CASTS", - "unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $herecurr); - } - -# alloc style -# p = alloc(sizeof(struct foo), ...) should be p = alloc(sizeof(*p), ...) - if ($^V && $^V ge 5.10.0 && - $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*([kv][mz]alloc(?:_node)?)\s*\(\s*(sizeof\s*\(\s*struct\s+$Lval\s*\))/) { - CHK("ALLOC_SIZEOF_STRUCT", - "Prefer $3(sizeof(*$1)...) over $3($4...)\n" . $herecurr); - } - -# check for k[mz]alloc with multiplies that could be kmalloc_array/kcalloc - if ($^V && $^V ge 5.10.0 && - $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) { - my $oldfunc = $3; - my $a1 = $4; - my $a2 = $10; - my $newfunc = "kmalloc_array"; - $newfunc = "kcalloc" if ($oldfunc eq "kzalloc"); - my $r1 = $a1; - my $r2 = $a2; - if ($a1 =~ /^sizeof\s*\S/) { - $r1 = $a2; - $r2 = $a1; - } - if ($r1 !~ /^sizeof\b/ && $r2 =~ /^sizeof\s*\S/ && - !($r1 =~ /^$Constant$/ || $r1 =~ /^[A-Z_][A-Z0-9_]*$/)) { - if (WARN("ALLOC_WITH_MULTIPLY", - "Prefer $newfunc over $oldfunc with multiply\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . trim($r1) . ', ' . trim($r2)/e; - - } - } - } - -# check for krealloc arg reuse - if ($^V && $^V ge 5.10.0 && - $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*krealloc\s*\(\s*\1\s*,/) { - WARN("KREALLOC_ARG_REUSE", - "Reusing the krealloc arg is almost always a bug\n" . $herecurr); - } - -# check for alloc argument mismatch - if ($line =~ /\b(kcalloc|kmalloc_array)\s*\(\s*sizeof\b/) { - WARN("ALLOC_ARRAY_ARGS", - "$1 uses number as first arg, sizeof is generally wrong\n" . $herecurr); - } - -# check for multiple semicolons - if ($line =~ /;\s*;\s*$/) { - if (WARN("ONE_SEMICOLON", - "Statements terminations use 1 semicolon\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/(\s*;\s*){2,}$/;/g; - } - } - -# check for #defines like: 1 << <digit> that could be BIT(digit) - if ($line =~ /#\s*define\s+\w+\s+\(?\s*1\s*([ulUL]*)\s*\<\<\s*(?:\d+|$Ident)\s*\)?/) { - my $ull = ""; - $ull = "_ULL" if (defined($1) && $1 =~ /ll/i); - if (CHK("BIT_MACRO", - "Prefer using the BIT$ull macro\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\(?\s*1\s*[ulUL]*\s*<<\s*(\d+|$Ident)\s*\)?/BIT${ull}($1)/; - } - } - -# check for case / default statements not preceded by break/fallthrough/switch - if ($line =~ /^.\s*(?:case\s+(?:$Ident|$Constant)\s*|default):/) { - my $has_break = 0; - my $has_statement = 0; - my $count = 0; - my $prevline = $linenr; - while ($prevline > 1 && ($file || $count < 3) && !$has_break) { - $prevline--; - my $rline = $rawlines[$prevline - 1]; - my $fline = $lines[$prevline - 1]; - last if ($fline =~ /^\@\@/); - next if ($fline =~ /^\-/); - next if ($fline =~ /^.(?:\s*(?:case\s+(?:$Ident|$Constant)[\s$;]*|default):[\s$;]*)*$/); - $has_break = 1 if ($rline =~ /fall[\s_-]*(through|thru)/i); - next if ($fline =~ /^.[\s$;]*$/); - $has_statement = 1; - $count++; - $has_break = 1 if ($fline =~ /\bswitch\b|\b(?:break\s*;[\s$;]*$|return\b|goto\b|continue\b)/); - } - if (!$has_break && $has_statement) { - WARN("MISSING_BREAK", - "Possible switch case/default not preceeded by break or fallthrough comment\n" . $herecurr); - } - } - -# check for switch/default statements without a break; - if ($^V && $^V ge 5.10.0 && - defined $stat && - $stat =~ /^\+[$;\s]*(?:case[$;\s]+\w+[$;\s]*:[$;\s]*|)*[$;\s]*\bdefault[$;\s]*:[$;\s]*;/g) { - my $ctx = ''; - my $herectx = $here . "\n"; - my $cnt = statement_rawlines($stat); - for (my $n = 0; $n < $cnt; $n++) { - $herectx .= raw_line($linenr, $n) . "\n"; - } - WARN("DEFAULT_NO_BREAK", - "switch default: should use break\n" . $herectx); - } - -# check for gcc specific __FUNCTION__ - if ($line =~ /\b__FUNCTION__\b/) { - if (WARN("USE_FUNC", - "__func__ should be used instead of gcc specific __FUNCTION__\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b__FUNCTION__\b/__func__/g; - } - } - -# check for uses of __DATE__, __TIME__, __TIMESTAMP__ - while ($line =~ /\b(__(?:DATE|TIME|TIMESTAMP)__)\b/g) { - ERROR("DATE_TIME", - "Use of the '$1' macro makes the build non-deterministic\n" . $herecurr); - } - -# check for use of yield() - if ($line =~ /\byield\s*\(\s*\)/) { - WARN("YIELD", - "Using yield() is generally wrong. See yield() kernel-doc (sched/core.c)\n" . $herecurr); - } - -# check for comparisons against true and false - if ($line =~ /\+\s*(.*?)\b(true|false|$Lval)\s*(==|\!=)\s*(true|false|$Lval)\b(.*)$/i) { - my $lead = $1; - my $arg = $2; - my $test = $3; - my $otype = $4; - my $trail = $5; - my $op = "!"; - - ($arg, $otype) = ($otype, $arg) if ($arg =~ /^(?:true|false)$/i); - - my $type = lc($otype); - if ($type =~ /^(?:true|false)$/) { - if (("$test" eq "==" && "$type" eq "true") || - ("$test" eq "!=" && "$type" eq "false")) { - $op = ""; - } - - CHK("BOOL_COMPARISON", - "Using comparison to $otype is error prone\n" . $herecurr); - -## maybe suggesting a correct construct would better -## "Using comparison to $otype is error prone. Perhaps use '${lead}${op}${arg}${trail}'\n" . $herecurr); - - } - } - -# check for semaphores initialized locked - if ($line =~ /^.\s*sema_init.+,\W?0\W?\)/) { - WARN("CONSIDER_COMPLETION", - "consider using a completion\n" . $herecurr); - } - -# recommend kstrto* over simple_strto* and strict_strto* - if ($line =~ /\b((simple|strict)_(strto(l|ll|ul|ull)))\s*\(/) { - WARN("CONSIDER_KSTRTO", - "$1 is obsolete, use k$3 instead\n" . $herecurr); - } - -# check for __initcall(), use device_initcall() explicitly or more appropriate function please - if ($line =~ /^.\s*__initcall\s*\(/) { - WARN("USE_DEVICE_INITCALL", - "please use device_initcall() or more appropriate function instead of __initcall() (see include/linux/init.h)\n" . $herecurr); - } - -# check for various structs that are normally const (ops, kgdb, device_tree) - my $const_structs = qr{ - acpi_dock_ops| - address_space_operations| - backlight_ops| - block_device_operations| - dentry_operations| - dev_pm_ops| - dma_map_ops| - extent_io_ops| - file_lock_operations| - file_operations| - hv_ops| - ide_dma_ops| - intel_dvo_dev_ops| - item_operations| - iwl_ops| - kgdb_arch| - kgdb_io| - kset_uevent_ops| - lock_manager_operations| - microcode_ops| - mtrr_ops| - neigh_ops| - nlmsvc_binding| - of_device_id| - pci_raw_ops| - pipe_buf_operations| - platform_hibernation_ops| - platform_suspend_ops| - proto_ops| - rpc_pipe_ops| - seq_operations| - snd_ac97_build_ops| - soc_pcmcia_socket_ops| - stacktrace_ops| - sysfs_ops| - tty_operations| - uart_ops| - usb_mon_operations| - wd_ops}x; - if ($line !~ /\bconst\b/ && - $line =~ /\bstruct\s+($const_structs)\b/) { - WARN("CONST_STRUCT", - "struct $1 should normally be const\n" . - $herecurr); - } - -# use of NR_CPUS is usually wrong -# ignore definitions of NR_CPUS and usage to define arrays as likely right - if ($line =~ /\bNR_CPUS\b/ && - $line !~ /^.\s*\s*#\s*if\b.*\bNR_CPUS\b/ && - $line !~ /^.\s*\s*#\s*define\b.*\bNR_CPUS\b/ && - $line !~ /^.\s*$Declare\s.*\[[^\]]*NR_CPUS[^\]]*\]/ && - $line !~ /\[[^\]]*\.\.\.[^\]]*NR_CPUS[^\]]*\]/ && - $line !~ /\[[^\]]*NR_CPUS[^\]]*\.\.\.[^\]]*\]/) - { - WARN("NR_CPUS", - "usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc\n" . $herecurr); - } - -# Use of __ARCH_HAS_<FOO> or ARCH_HAVE_<BAR> is wrong. - if ($line =~ /\+\s*#\s*define\s+((?:__)?ARCH_(?:HAS|HAVE)\w*)\b/) { - ERROR("DEFINE_ARCH_HAS", - "#define of '$1' is wrong - use Kconfig variables or standard guards instead\n" . $herecurr); - } - -# likely/unlikely comparisons similar to "(likely(foo) > 0)" - if ($^V && $^V ge 5.10.0 && - $line =~ /\b((?:un)?likely)\s*\(\s*$FuncArg\s*\)\s*$Compare/) { - WARN("LIKELY_MISUSE", - "Using $1 should generally have parentheses around the comparison\n" . $herecurr); - } - -# whine mightly about in_atomic - if ($line =~ /\bin_atomic\s*\(/) { - if ($realfile =~ m@^drivers/@) { - ERROR("IN_ATOMIC", - "do not use in_atomic in drivers\n" . $herecurr); - } elsif ($realfile !~ m@^kernel/@) { - WARN("IN_ATOMIC", - "use of in_atomic() is incorrect outside core kernel code\n" . $herecurr); - } - } - -# check for lockdep_set_novalidate_class - if ($line =~ /^.\s*lockdep_set_novalidate_class\s*\(/ || - $line =~ /__lockdep_no_validate__\s*\)/ ) { - if ($realfile !~ m@^kernel/lockdep@ && - $realfile !~ m@^include/linux/lockdep@ && - $realfile !~ m@^drivers/base/core@) { - ERROR("LOCKDEP", - "lockdep_no_validate class is reserved for device->mutex.\n" . $herecurr); - } - } - - if ($line =~ /debugfs_create_\w+.*\b$mode_perms_world_writable\b/ || - $line =~ /DEVICE_ATTR.*\b$mode_perms_world_writable\b/) { - WARN("EXPORTED_WORLD_WRITABLE", - "Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr); - } - -# Mode permission misuses where it seems decimal should be octal -# This uses a shortcut match to avoid unnecessary uses of a slow foreach loop - if ($^V && $^V ge 5.10.0 && - $line =~ /$mode_perms_search/) { - foreach my $entry (@mode_permission_funcs) { - my $func = $entry->[0]; - my $arg_pos = $entry->[1]; - - my $skip_args = ""; - if ($arg_pos > 1) { - $arg_pos--; - $skip_args = "(?:\\s*$FuncArg\\s*,\\s*){$arg_pos,$arg_pos}"; - } - my $test = "\\b$func\\s*\\(${skip_args}([\\d]+)\\s*[,\\)]"; - if ($line =~ /$test/) { - my $val = $1; - $val = $6 if ($skip_args ne ""); - - if ($val !~ /^0$/ && - (($val =~ /^$Int$/ && $val !~ /^$Octal$/) || - length($val) ne 4)) { - ERROR("NON_OCTAL_PERMISSIONS", - "Use 4 digit octal (0777) not decimal permissions\n" . $herecurr); - } elsif ($val =~ /^$Octal$/ && (oct($val) & 02)) { - ERROR("EXPORTED_WORLD_WRITABLE", - "Exporting writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr); - } - } - } - } - -# validate content of MODULE_LICENSE against list from include/linux/module.h - if ($line =~ /\bMODULE_LICENSE\s*\(\s*($String)\s*\)/) { - my $extracted_string = get_quoted_string($line, $rawline); - my $valid_licenses = qr{ - GPL| - GPL\ v2| - GPL\ and\ additional\ rights| - Dual\ BSD/GPL| - Dual\ MIT/GPL| - Dual\ MPL/GPL| - Proprietary - }x; - if ($extracted_string !~ /^"(?:$valid_licenses)"$/x) { - WARN("MODULE_LICENSE", - "unknown module license " . $extracted_string . "\n" . $herecurr); - } - } - } - - # If we have no input at all, then there is nothing to report on - # so just keep quiet. - if ($#rawlines == -1) { - exit(0); - } - - # In mailback mode only produce a report in the negative, for - # things that appear to be patches. - if ($mailback && ($clean == 1 || !$is_patch)) { - exit(0); - } - - # This is not a patch, and we are are in 'no-patch' mode so - # just keep quiet. - if (!$chk_patch && !$is_patch) { - exit(0); - } - - if (!$is_patch && $file !~ /cover-letter\.patch$/) { - ERROR("NOT_UNIFIED_DIFF", - "Does not appear to be a unified-diff format patch\n"); - } - if ($is_patch && $filename ne '-' && $chk_signoff && $signoff == 0) { - ERROR("MISSING_SIGN_OFF", - "Missing Signed-off-by: line(s)\n"); - } - - print report_dump(); - if ($summary && !($clean == 1 && $quiet == 1)) { - print "$filename " if ($summary_file); - print "total: $cnt_error errors, $cnt_warn warnings, " . - (($check)? "$cnt_chk checks, " : "") . - "$cnt_lines lines checked\n"; - } - - if ($quiet == 0) { - # If there were whitespace errors which cleanpatch can fix - # then suggest that. - if ($rpt_cleaners) { - $rpt_cleaners = 0; - print << "EOM" - -NOTE: Whitespace errors detected. - You may wish to use scripts/cleanpatch or scripts/cleanfile -EOM - } - } - - if ($clean == 0 && $fix && - ("@rawlines" ne "@fixed" || - $#fixed_inserted >= 0 || $#fixed_deleted >= 0)) { - my $newfile = $filename; - $newfile .= ".EXPERIMENTAL-checkpatch-fixes" if (!$fix_inplace); - my $linecount = 0; - my $f; - - @fixed = fix_inserted_deleted_lines(\@fixed, \@fixed_inserted, \@fixed_deleted); - - open($f, '>', $newfile) - or die "$P: Can't open $newfile for write\n"; - foreach my $fixed_line (@fixed) { - $linecount++; - if ($file) { - if ($linecount > 3) { - $fixed_line =~ s/^\+//; - print $f $fixed_line . "\n"; - } - } else { - print $f $fixed_line . "\n"; - } - } - close($f); - - if (!$quiet) { - print << "EOM"; - -Wrote EXPERIMENTAL --fix correction(s) to '$newfile' - -Do _NOT_ trust the results written to this file. -Do _NOT_ submit these changes without inspecting them for correctness. - -This EXPERIMENTAL file is simply a convenience to help rewrite patches. -No warranties, expressed or implied... -EOM - } - } - - if ($quiet == 0) { - print "\n"; - if ($clean == 1) { - print "$vname has no obvious style problems and is ready for submission.\n"; - } else { - print "$vname has style problems, please review.\n"; - } - } - return $clean; -} diff --git a/drivers/staging/greybus/scripts/spelling.txt b/drivers/staging/greybus/scripts/spelling.txt deleted file mode 100644 index 946caf3..0000000 --- a/drivers/staging/greybus/scripts/spelling.txt +++ /dev/null @@ -1,1072 +0,0 @@ -# Originally from Debian's Lintian tool. Various false positives have been -# removed, and various additions have been made as they've been discovered -# in the kernel source. -# -# License: GPLv2 -# -# The format of each line is: -# mistake||correction -# -abandonning||abandoning -abigious||ambiguous -abitrate||arbitrate -abov||above -abreviated||abbreviated -absense||absence -absolut||absolute -absoulte||absolute -acccess||access -acceleratoin||acceleration -accelleration||acceleration -accesing||accessing -accesnt||accent -accessable||accessible -accesss||access -accidentaly||accidentally -accidentually||accidentally -accoding||according -accomodate||accommodate -accomodates||accommodates -accordign||according -accoring||according -accout||account -accquire||acquire -accquired||acquired -accross||across -acessable||accessible -acess||access -achitecture||architecture -acient||ancient -acitions||actions -acitve||active -acknowldegement||acknowldegement -acknowledgement||acknowledgment -ackowledge||acknowledge -ackowledged||acknowledged -acording||according -activete||activate -acumulating||accumulating -adapater||adapter -addional||additional -additionaly||additionally -addres||address -addreses||addresses -addresss||address -aditional||additional -aditionally||additionally -aditionaly||additionally -adminstrative||administrative -adress||address -adresses||addresses -adviced||advised -afecting||affecting -agaist||against -albumns||albums -alegorical||allegorical -algorith||algorithm -algorithmical||algorithmically -algoritm||algorithm -algoritms||algorithms -algorrithm||algorithm -algorritm||algorithm -allign||align -allocatrd||allocated -allocte||allocate -allpication||application -alocate||allocate -alogirhtms||algorithms -alogrithm||algorithm -alot||a lot -alow||allow -alows||allows -altough||although -alue||value -ambigious||ambiguous -amoung||among -amout||amount -analysator||analyzer -ang||and -anniversery||anniversary -annoucement||announcement -anomolies||anomalies -anomoly||anomaly -anway||anyway -aplication||application -appearence||appearance -applicaion||application -appliction||application -applictions||applications -appplications||applications -appropiate||appropriate -appropriatly||appropriately -approriate||appropriate -approriately||appropriately -apropriate||appropriate -aquainted||acquainted -aquired||acquired -aquisition||acquisition -arbitary||arbitrary -architechture||architecture -arguement||argument -arguements||arguments -aritmetic||arithmetic -arne't||aren't -arraival||arrival -artifical||artificial -artillary||artillery -asign||assign -assertation||assertion -assiged||assigned -assigment||assignment -assigments||assignments -assistent||assistant -assocation||association -associcated||associated -assotiated||associated -assum||assume -assumtpion||assumption -asuming||assuming -asycronous||asynchronous -asynchnous||asynchronous -atomatically||automatically -atomicly||atomically -attachement||attachment -attched||attached -attemps||attempts -attruibutes||attributes -authentification||authentication -automaticaly||automatically -automaticly||automatically -automatize||automate -automatized||automated -automatizes||automates -autonymous||autonomous -auxillary||auxiliary -auxilliary||auxiliary -avaiable||available -avaible||available -availabe||available -availabled||available -availablity||availability -availale||available -availavility||availability -availble||available -availiable||available -avalable||available -avaliable||available -aysnc||async -backgroud||background -backword||backward -backwords||backwards -bahavior||behavior -bakup||backup -baloon||balloon -baloons||balloons -bandwith||bandwidth -batery||battery -beacuse||because -becasue||because -becomming||becoming -becuase||because -beeing||being -befor||before -begining||beginning -beter||better -betweeen||between -bianries||binaries -bitmast||bitmask -boardcast||broadcast -borad||board -boundry||boundary -brievely||briefly -broadcat||broadcast -cacluated||calculated -caculation||calculation -calender||calendar -calle||called -calucate||calculate -calulate||calculate -cancelation||cancellation -capabilites||capabilities -capabitilies||capabilities -capatibilities||capabilities -carefuly||carefully -cariage||carriage -catagory||category -cehck||check -challange||challenge -challanges||challenges -chanell||channel -changable||changeable -channle||channel -channnel||channel -charachter||character -charachters||characters -charactor||character -charater||character -charaters||characters -charcter||character -chcek||check -chck||check -checksuming||checksumming -childern||children -childs||children -chiled||child -chked||checked -chnage||change -chnages||changes -chnnel||channel -choosen||chosen -chouse||chose -circumvernt||circumvent -claread||cleared -clared||cleared -closeing||closing -clustred||clustered -collapsable||collapsible -colorfull||colorful -comand||command -comit||commit -commerical||commercial -comming||coming -comminucation||communication -commited||committed -commiting||committing -committ||commit -commoditiy||commodity -compability||compatibility -compaibility||compatibility -compatability||compatibility -compatable||compatible -compatibiliy||compatibility -compatibilty||compatibility -compatiblity||compatibility -competion||completion -compilant||compliant -compleatly||completely -completly||completely -complient||compliant -componnents||components -compres||compress -compresion||compression -comression||compression -comunication||communication -conbination||combination -conditionaly||conditionally -conected||connected -configuratoin||configuration -configuraton||configuration -configuretion||configuration -conider||consider -conjuction||conjunction -connectinos||connections -connnection||connection -connnections||connections -consistancy||consistency -consistant||consistent -containes||contains -containts||contains -contaisn||contains -contant||contact -contence||contents -continous||continuous -continously||continuously -continueing||continuing -contraints||constraints -controled||controlled -controler||controller -controll||control -contruction||construction -contry||country -convertion||conversion -convertor||converter -convienient||convenient -convinient||convenient -corected||corrected -correponding||corresponding -correponds||corresponds -correspoding||corresponding -cotrol||control -couter||counter -coutner||counter -cryptocraphic||cryptographic -cunter||counter -curently||currently -dafault||default -deafult||default -deamon||daemon -decompres||decompress -decription||description -defailt||default -defferred||deferred -definate||definite -definately||definitely -defintion||definition -defintions||definitions -defualt||default -defult||default -deivce||device -delared||declared -delare||declare -delares||declares -delaring||declaring -delemiter||delimiter -dependancies||dependencies -dependancy||dependency -dependant||dependent -depreacted||deprecated -depreacte||deprecate -desactivate||deactivate -desciptors||descriptors -descripton||description -descrition||description -descritptor||descriptor -desctiptor||descriptor -desriptor||descriptor -desriptors||descriptors -destory||destroy -destoryed||destroyed -destorys||destroys -destroied||destroyed -detabase||database -develope||develop -developement||development -developped||developed -developpement||development -developper||developer -developpment||development -deveolpment||development -devided||divided -deviece||device -diable||disable -dictionnary||dictionary -didnt||didn't -diferent||different -differrence||difference -difinition||definition -diplay||display -direectly||directly -disapear||disappear -disapeared||disappeared -disappared||disappeared -disconnet||disconnect -discontinous||discontinuous -dispertion||dispersion -dissapears||disappears -distiction||distinction -docuentation||documentation -documantation||documentation -documentaion||documentation -documment||document -doesnt||doesn't -dorp||drop -dosen||doesn -downlad||download -downlads||downloads -druing||during -dynmaic||dynamic -easilly||easily -ecspecially||especially -edditable||editable -editting||editing -efficently||efficiently -ehther||ether -eigth||eight -eletronic||electronic -enabledi||enabled -enchanced||enhanced -encorporating||incorporating -encrupted||encrypted -encrypiton||encryption -endianess||endianness -enhaced||enhanced -enlightnment||enlightenment -enocded||encoded -enterily||entirely -enviroiment||environment -enviroment||environment -environement||environment -environent||environment -eqivalent||equivalent -equiped||equipped -equivelant||equivalent -equivilant||equivalent -eror||error -estbalishment||establishment -etsablishment||establishment -etsbalishment||establishment -excecutable||executable -exceded||exceeded -excellant||excellent -existance||existence -existant||existent -exixt||exist -exlcude||exclude -exlcusive||exclusive -exmaple||example -expecially||especially -explicite||explicit -explicitely||explicitly -explict||explicit -explictly||explicitly -expresion||expression -exprimental||experimental -extened||extended -extensability||extensibility -extention||extension -extracter||extractor -faild||failed -faill||fail -failue||failure -failuer||failure -faireness||fairness -faliure||failure -familar||familiar -fatser||faster -feauture||feature -feautures||features -fetaure||feature -fetaures||features -fileystem||filesystem -finanize||finalize -findn||find -finilizes||finalizes -finsih||finish -flusing||flushing -folloing||following -followign||following -follwing||following -forseeable||foreseeable -forse||force -fortan||fortran -forwardig||forwarding -framwork||framework -frequncy||frequency -frome||from -fucntion||function -fuction||function -fuctions||functions -funcion||function -functionallity||functionality -functionaly||functionally -functionnality||functionality -functonality||functionality -funtion||function -funtions||functions -furthur||further -futhermore||furthermore -futrue||future -gaurenteed||guaranteed -generiously||generously -genric||generic -globel||global -grabing||grabbing -grahical||graphical -grahpical||graphical -grapic||graphic -guage||gauge -guarenteed||guaranteed -guarentee||guarantee -halfs||halves -hander||handler -handfull||handful -hanled||handled -happend||happened -harware||hardware -heirarchically||hierarchically -helpfull||helpful -hierachy||hierarchy -hierarchie||hierarchy -howver||however -hsould||should -hypter||hyper -identidier||identifier -imblance||imbalance -immeadiately||immediately -immedaite||immediate -immediatelly||immediately -immediatly||immediately -immidiate||immediate -impelentation||implementation -impementated||implemented -implemantation||implementation -implemenation||implementation -implementaiton||implementation -implementated||implemented -implemention||implementation -implemetation||implementation -implemntation||implementation -implentation||implementation -implmentation||implementation -implmenting||implementing -incomming||incoming -incompatabilities||incompatibilities -incompatable||incompatible -inconsistant||inconsistent -increas||increase -incrment||increment -indendation||indentation -indended||intended -independant||independent -independantly||independently -independed||independent -indiate||indicate -inexpect||inexpected -infomation||information -informatiom||information -informations||information -informtion||information -infromation||information -ingore||ignore -inital||initial -initalised||initialized -initalise||initialize -initalize||initialize -initation||initiation -initators||initiators -initializiation||initialization -initialzed||initialized -initilization||initialization -initilize||initialize -inofficial||unofficial -insititute||institute -instal||install -inteface||interface -integreated||integrated -integrety||integrity -integrey||integrity -intendet||intended -intented||intended -interanl||internal -interchangable||interchangeable -interferring||interfering -interger||integer -intermittant||intermittent -internel||internal -interoprability||interoperability -interrface||interface -interrrupt||interrupt -interrup||interrupt -interrups||interrupts -interruptted||interrupted -interupted||interrupted -interupt||interrupt -intial||initial -intialized||initialized -intialize||initialize -intregral||integral -intrrupt||interrupt -intuative||intuitive -invaid||invalid -invalde||invald -invalide||invalid -invididual||individual -invokation||invocation -invokations||invocations -irrelevent||irrelevant -isnt||isn't -isssue||issue -itslef||itself -jave||java -jeffies||jiffies -juse||just -jus||just -kown||known -langage||language -langauage||language -langauge||language -langugage||language -lauch||launch -layed||laid -leightweight||lightweight -lengh||length -lenght||length -lenth||length -lesstiff||lesstif -libaries||libraries -libary||library -librairies||libraries -libraris||libraries -licenceing||licencing -loggging||logging -loggin||login -logile||logfile -loosing||losing -losted||lost -machinary||machinery -maintainance||maintenance -maintainence||maintenance -maintan||maintain -makeing||making -malplaced||misplaced -malplace||misplace -managable||manageable -managment||management -mangement||management -manoeuvering||maneuvering -mappping||mapping -mathimatical||mathematical -mathimatic||mathematic -mathimatics||mathematics -maxium||maximum -mechamism||mechanism -meetign||meeting -ment||meant -mergable||mergeable -mesage||message -messags||messages -messgaes||messages -messsage||message -messsages||messages -microprocesspr||microprocessor -milliseonds||milliseconds -minumum||minimum -miscelleneous||miscellaneous -misformed||malformed -mispelled||misspelled -mispelt||misspelt -miximum||maximum -mmnemonic||mnemonic -mnay||many -modeled||modelled -modulues||modules -monochorome||monochrome -monochromo||monochrome -monocrome||monochrome -mopdule||module -mroe||more -mulitplied||multiplied -multidimensionnal||multidimensional -multple||multiple -mumber||number -muticast||multicast -mutiple||multiple -mutli||multi -nams||names -navagating||navigating -nead||need -neccecary||necessary -neccesary||necessary -neccessary||necessary -necesary||necessary -negaive||negative -negoitation||negotiation -negotation||negotiation -nerver||never -nescessary||necessary -nessessary||necessary -noticable||noticeable -notications||notifications -notifed||notified -numebr||number -numner||number -obtaion||obtain -occassionally||occasionally -occationally||occasionally -occurance||occurrence -occurances||occurrences -occured||occurred -occurence||occurrence -occure||occurred -occuring||occurring -offet||offset -omitt||omit -ommiting||omitting -ommitted||omitted -onself||oneself -ony||only -operatione||operation -opertaions||operations -optionnal||optional -optmizations||optimizations -orientatied||orientated -orientied||oriented -otherise||otherwise -ouput||output -overaall||overall -overhread||overhead -overlaping||overlapping -overriden||overridden -overun||overrun -pacakge||package -pachage||package -packacge||package -packege||package -packge||package -packtes||packets -pakage||package -pallette||palette -paln||plan -paramameters||parameters -paramater||parameter -parametes||parameters -parametised||parametrised -paramter||parameter -paramters||parameters -particuarly||particularly -particularily||particularly -pased||passed -passin||passing -pathes||paths -pecularities||peculiarities -peformance||performance -peice||piece -pendantic||pedantic -peprocessor||preprocessor -perfoming||performing -permissons||permissions -peroid||period -persistance||persistence -persistant||persistent -platfrom||platform -plattform||platform -pleaes||please -ploting||plotting -plugable||pluggable -poinnter||pointer -poiter||pointer -posible||possible -positon||position -possibilites||possibilities -powerfull||powerful -preceeded||preceded -preceeding||preceding -preceed||precede -precendence||precedence -precission||precision -preemptable||preemptible -prefered||preferred -prefferably||preferably -premption||preemption -prepaired||prepared -pressre||pressure -primative||primitive -princliple||principle -priorty||priority -privilaged||privileged -privilage||privilege -priviledge||privilege -priviledges||privileges -probaly||probably -procceed||proceed -proccesors||processors -procesed||processed -proces||process -processessing||processing -processess||processes -processpr||processor -processsed||processed -processsing||processing -procteted||protected -prodecure||procedure -progams||programs -progess||progress -programers||programmers -programm||program -programms||programs -progresss||progress -promiscous||promiscuous -promps||prompts -pronnounced||pronounced -prononciation||pronunciation -pronouce||pronounce -pronunce||pronounce -propery||property -propigate||propagate -propigation||propagation -propogate||propagate -prosess||process -protable||portable -protcol||protocol -protecion||protection -protocoll||protocol -psudo||pseudo -psuedo||pseudo -psychadelic||psychedelic -pwoer||power -quering||querying -raoming||roaming -reasearcher||researcher -reasearchers||researchers -reasearch||research -recepient||recipient -receving||receiving -recieved||received -recieve||receive -reciever||receiver -recieves||receives -recogniced||recognised -recognizeable||recognizable -recommanded||recommended -recyle||recycle -redircet||redirect -redirectrion||redirection -refcounf||refcount -refence||reference -refered||referred -referenace||reference -refering||referring -refernces||references -refernnce||reference -refrence||reference -registerd||registered -registeresd||registered -registes||registers -registraration||registration -regster||register -regualar||regular -reguator||regulator -regulamentations||regulations -reigstration||registration -releated||related -relevent||relevant -remoote||remote -remore||remote -removeable||removable -repectively||respectively -replacable||replaceable -replacments||replacements -replys||replies -reponse||response -representaion||representation -reqeust||request -requiere||require -requirment||requirement -requred||required -requried||required -requst||request -reseting||resetting -resizeable||resizable -resouces||resources -resoures||resources -responce||response -ressizes||resizes -ressource||resource -ressources||resources -retransmited||retransmitted -retreived||retrieved -retreive||retrieve -retrive||retrieve -retuned||returned -reudce||reduce -reuest||request -reuqest||request -reutnred||returned -rmeoved||removed -rmeove||remove -rmeoves||removes -rountine||routine -routins||routines -rquest||request -runing||running -runned||ran -runnning||running -runtine||runtime -sacrifying||sacrificing -safly||safely -safty||safety -savable||saveable -scaned||scanned -scaning||scanning -scarch||search -seach||search -searchs||searches -secquence||sequence -secund||second -segement||segment -senarios||scenarios -sentivite||sensitive -separatly||separately -sepcify||specify -sepc||spec -seperated||separated -seperately||separately -seperate||separate -seperatly||separately -seperator||separator -sepperate||separate -sequece||sequence -sequencial||sequential -serveral||several -setts||sets -settting||setting -shotdown||shutdown -shoud||should -shouldnt||shouldn't -shoule||should -shrinked||shrunk -siginificantly||significantly -signabl||signal -similary||similarly -similiar||similar -simlar||similar -simliar||similar -simpified||simplified -singaled||signaled -singal||signal -singed||signed -sleeped||slept -softwares||software -speach||speech -specfic||specific -speciefied||specified -specifc||specific -specifed||specified -specificatin||specification -specificaton||specification -specifing||specifying -specifiying||specifying -speficied||specified -speicify||specify -speling||spelling -spinlcok||spinlock -spinock||spinlock -splitted||split -spreaded||spread -sructure||structure -stablilization||stabilization -staically||statically -staion||station -standardss||standards -standartization||standardization -standart||standard -staticly||statically -stoped||stopped -stoppped||stopped -straming||streaming -struc||struct -structres||structures -stuct||struct -stucture||structure -sturcture||structure -subdirectoires||subdirectories -suble||subtle -substract||subtract -succesfully||successfully -succesful||successful -successfull||successful -sucessfully||successfully -sucess||success -superflous||superfluous -superseeded||superseded -suplied||supplied -suported||supported -suport||support -suppored||supported -supportin||supporting -suppoted||supported -suppported||supported -suppport||support -supress||suppress -surpresses||suppresses -susbsystem||subsystem -suspicously||suspiciously -swaping||swapping -switchs||switches -symetric||symmetric -synax||syntax -synchonized||synchronized -syncronize||synchronize -syncronizing||synchronizing -syncronus||synchronous -syste||system -sytem||system -sythesis||synthesis -taht||that -targetted||targeted -targetting||targeting -teh||the -temorary||temporary -temproarily||temporarily -thier||their -threds||threads -threshhold||threshold -throught||through -thses||these -tiggered||triggered -tipically||typically -tmis||this -torerable||tolerable -tramsmitted||transmitted -tramsmit||transmit -tranfer||transfer -transciever||transceiver -transferd||transferrd -transfered||transferred -transfering||transferring -transision||transition -transmittd||transmitted -transormed||transformed -trasmission||transmission -treshold||threshold -trigerring||triggering -trun||turn -ture||true -tyep||type -udpate||update -uesd||used -unconditionaly||unconditionally -underun||underrun -unecessary||unnecessary -unexecpted||unexpected -unexpectd||unexpected -unexpeted||unexpected -unfortunatelly||unfortunately -unifiy||unify -unintialized||uninitialized -unknonw||unknown -unknow||unknown -unkown||unknown -unneedingly||unnecessarily -unresgister||unregister -unsinged||unsigned -unstabel||unstable -unsuccessfull||unsuccessful -unsuported||unsupported -untill||until -unuseful||useless -upate||update -usefule||useful -usefull||useful -usege||usage -usera||users -usualy||usually -utilites||utilities -utillities||utilities -utilties||utilities -utiltity||utility -utitity||utility -utitlty||utility -vaid||valid -vaild||valid -valide||valid -variantions||variations -varient||variant -vaule||value -verbse||verbose -verisons||versions -verison||version -verson||version -vicefersa||vice-versa -virtal||virtual -virtaul||virtual -virtiual||virtual -visiters||visitors -vitual||virtual -wating||waiting -wether||whether -whataver||whatever -whcih||which -whenver||whenever -wheter||whether -whe||when -wierd||weird -wiil||will -wirte||write -withing||within -wnat||want -workarould||workaround -writeing||writing -writting||writing -zombe||zombie -zomebie||zombie -- cgit v0.10.2 From bc5aa3a079437159ed4685e8bb062e027d6e54a3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Mon, 19 Sep 2016 12:35:16 +0200 Subject: staging: greybus: Documentation: remove sysfs tree We do not need an example of the sysfs tree in the kernel code itself, so remove these files, as they are now pointless. Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.1/bundle_class b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.1/bundle_class deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.1/bundle_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.1/bundle_id deleted file mode 100644 index d00491f..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.1/bundle_id +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.1/state b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.1/state deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.2/bundle_class b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.2/bundle_class deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.2/bundle_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.2/bundle_id deleted file mode 100644 index 0cfbf08..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.2/bundle_id +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.2/state b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.2/state deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.ctrl/product_string b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.ctrl/product_string deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.ctrl/vendor_string b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/1-2.2.ctrl/vendor_string deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/ddbl1_manufacturer_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/ddbl1_manufacturer_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/ddbl1_product_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/ddbl1_product_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/interface_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/interface_id deleted file mode 100644 index 0cfbf08..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/interface_id +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/product_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/product_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/serial_number b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/serial_number deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/vendor_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/1-2.2/vendor_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/eject b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/eject deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/module_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/module_id deleted file mode 100644 index 0cfbf08..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/module_id +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/num_interfaces b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/num_interfaces deleted file mode 100644 index d00491f..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-2/num_interfaces +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/bundle_class b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/bundle_class deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/bundle_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/bundle_id deleted file mode 100644 index 0cfbf08..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/bundle_id +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gbphy1/gpio/gpiochip490/.gitignore b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gbphy1/gpio/gpiochip490/.gitignore deleted file mode 100644 index f935021..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gbphy1/gpio/gpiochip490/.gitignore +++ /dev/null @@ -1 +0,0 @@ -!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gbphy1/i2c-4/.gitignore b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gbphy1/i2c-4/.gitignore deleted file mode 100644 index f935021..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/gbphy1/i2c-4/.gitignore +++ /dev/null @@ -1 +0,0 @@ -!.gitignore diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/state b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.2/state deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.ctrl/product_string b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.ctrl/product_string deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.ctrl/vendor_string b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/1-5.5.ctrl/vendor_string deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/ddbl1_manufacturer_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/ddbl1_manufacturer_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/ddbl1_product_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/ddbl1_product_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/interface_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/interface_id deleted file mode 100644 index 7ed6ff8..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/interface_id +++ /dev/null @@ -1 +0,0 @@ -5 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/product_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/product_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/serial_number b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/serial_number deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/vendor_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.5/vendor_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.6/interface_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.6/interface_id deleted file mode 100644 index 1e8b314..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/1-5.6/interface_id +++ /dev/null @@ -1 +0,0 @@ -6 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/eject b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/eject deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/module_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/module_id deleted file mode 100644 index 7ed6ff8..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/module_id +++ /dev/null @@ -1 +0,0 @@ -5 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/num_interfaces b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/num_interfaces deleted file mode 100644 index 0cfbf08..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-5/num_interfaces +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-svc/ap_intf_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-svc/ap_intf_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-svc/endo_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-svc/endo_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/1-svc/intf_eject b/drivers/staging/greybus/Documentation/sysfs/greybus1/1-svc/intf_eject deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus1/bus_id b/drivers/staging/greybus/Documentation/sysfs/greybus1/bus_id deleted file mode 100644 index d00491f..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus1/bus_id +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.1/bundle_class b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.1/bundle_class deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.1/bundle_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.1/bundle_id deleted file mode 100644 index d00491f..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.1/bundle_id +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.1/state b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.1/state deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.ctrl/product_string b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.ctrl/product_string deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.ctrl/vendor_string b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/2-3.3.ctrl/vendor_string deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/ddbl1_manufacturer_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/ddbl1_manufacturer_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/ddbl1_product_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/ddbl1_product_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/interface_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/interface_id deleted file mode 100644 index 00750ed..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/interface_id +++ /dev/null @@ -1 +0,0 @@ -3 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/product_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/product_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/serial_number b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/serial_number deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/vendor_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/2-3.3/vendor_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/eject b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/eject deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/module_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/module_id deleted file mode 100644 index 00750ed..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/module_id +++ /dev/null @@ -1 +0,0 @@ -3 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/num_interfaces b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/num_interfaces deleted file mode 100644 index d00491f..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-3/num_interfaces +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-svc/ap_intf_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-svc/ap_intf_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-svc/endo_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-svc/endo_id deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/2-svc/intf_eject b/drivers/staging/greybus/Documentation/sysfs/greybus2/2-svc/intf_eject deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/staging/greybus/Documentation/sysfs/greybus2/bus_id b/drivers/staging/greybus/Documentation/sysfs/greybus2/bus_id deleted file mode 100644 index 0cfbf08..0000000 --- a/drivers/staging/greybus/Documentation/sysfs/greybus2/bus_id +++ /dev/null @@ -1 +0,0 @@ -2 -- cgit v0.10.2 From 0be6dfc296624a6cc840d246de656d7ac800b70d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Thu, 8 Sep 2016 11:58:46 +0200 Subject: staging: greybus: remove README and LICENSE We don't need yet-another-copy of the GPLv2 in the tree, and the README is now pointless, so remove both of these files. Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/LICENSE b/drivers/staging/greybus/LICENSE deleted file mode 100644 index d7f1051..0000000 --- a/drivers/staging/greybus/LICENSE +++ /dev/null @@ -1,339 +0,0 @@ -GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/> - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - {description} - Copyright (C) {year} {fullname} - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - {signature of Ty Coon}, 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/drivers/staging/greybus/README b/drivers/staging/greybus/README deleted file mode 100644 index b0745d3..0000000 --- a/drivers/staging/greybus/README +++ /dev/null @@ -1,10 +0,0 @@ -Greybus kernel code - -To build against the running kernel (odds are you don't want this): - make - -To build against a specific kernel source tree (odds are you want this): - KERNELDIR=/home/some/random/place make - -Any questions / concerns about this code base, please email: - Greg Kroah-Hartman <greg@kroah.com> -- cgit v0.10.2 From ecfea541e66e313d743563c517b7072a79c13acc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Thu, 8 Sep 2016 15:01:23 +0200 Subject: staging: greybus: remove .gitignore file Only the tools subdirectory needs a .gitignore entry, so move it there and fix it up to only list the needed file. Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/.gitignore b/drivers/staging/greybus/.gitignore deleted file mode 100644 index faf45ee..0000000 --- a/drivers/staging/greybus/.gitignore +++ /dev/null @@ -1,15 +0,0 @@ -.* -*.cmd -*.ko -*.mod.c -modules.order -Module.symvers -*.o -*.o.* -*.swp -.tmp_versions -tags -cscope.* -ncscope.* -*.patch -tools/loopback_test diff --git a/drivers/staging/greybus/tools/.gitignore b/drivers/staging/greybus/tools/.gitignore new file mode 100644 index 0000000..023654c --- /dev/null +++ b/drivers/staging/greybus/tools/.gitignore @@ -0,0 +1 @@ +loopback_test -- cgit v0.10.2 From 526dec064223d7e21b1e3c91759bddff1f7d968a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Mon, 19 Sep 2016 12:40:33 +0200 Subject: staging: greybus: remove old es1 endpoint description The Toshiba ES1 chip is no longer around, so remove the USB descriptor documentation for it as no one cares anymore. Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Documentation/es1_ap_desc.c b/drivers/staging/greybus/Documentation/es1_ap_desc.c deleted file mode 100644 index 1502089..0000000 --- a/drivers/staging/greybus/Documentation/es1_ap_desc.c +++ /dev/null @@ -1,70 +0,0 @@ -/* ES1 AP Bridge Chip USB descriptor definitions */ - -static const u8 es1_dev_descriptor[] = { - 0x12, /* __u8 bLength */ - 0x01, /* __u8 bDescriptorType; Device */ - 0x00, 0x02 /* __le16 bcdUSB v2.0 */ - 0x00, /* __u8 bDeviceClass */ - 0x00, /* __u8 bDeviceClass */ - 0x00, /* __u8 bDeviceSubClass; */ - 0x00, /* __u8 bDeviceProtocol; */ - 0x40, /* __u8 bMaxPacketSize0; 2^64 = 512 Bytes */ - - 0xff, 0xff, /* __le16 idVendor; 0xffff made up for now */ - 0x01, 0x00, /* __le16 idProduct; 0x0001 made up for now */ - 0x01, 0x00, /* __le16 bcdDevice; ES1 */ - - 0x03, /* __u8 iManufacturer; */ - 0x02, /* __u8 iProduct; */ - 0x01, /* __u8 iSerialNumber; */ - 0x01 /* __u8 bNumConfigurations; */ -}; - -static const u8 es1_config_descriptor[] = { - /* one configuration */ - 0x09, /* __u8 bLength; */ - 0x02, /* __u8 bDescriptorType; Configuration */ - 0x19, 0x00, /* __le16 wTotalLength; */ - 0x01, /* __u8 bNumInterfaces; (1) */ - 0x01, /* __u8 bConfigurationValue; */ - 0x00, /* __u8 iConfiguration; */ - 0xc0, /* __u8 bmAttributes; - Bit 7: must be set, - 6: Self-powered, - 5: Remote wakeup, - 4..0: resvd */ - 0x00, /* __u8 MaxPower; */ - - /* one interface */ - 0x09, /* __u8 if_bLength; */ - 0x04, /* __u8 if_bDescriptorType; Interface */ - 0x00, /* __u8 if_bInterfaceNumber; */ - 0x00, /* __u8 if_bAlternateSetting; */ - 0x03, /* __u8 if_bNumEndpoints; */ - 0xff, /* __u8 if_bInterfaceClass; Vendor-specific */ - 0xff, /* __u8 if_bInterfaceSubClass; Vendor-specific */ - 0xff, /* __u8 if_bInterfaceProtocol; Vendor-specific */ - 0x00, /* __u8 if_iInterface; */ - - /* three endpoints */ - 0x07, /* __u8 ep_bLength; */ - 0x05, /* __u8 ep_bDescriptorType; Endpoint */ - 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ - 0x03, /* __u8 ep_bmAttributes; Interrupt */ - 0x00, 0x04, /* __le16 ep_wMaxPacketSize; 1024 */ - 0x40, /* __u8 ep_bInterval; 64ms */ - - 0x07, /* __u8 ep_bLength; */ - 0x05, /* __u8 ep_bDescriptorType; Endpoint */ - 0x82, /* __u8 ep_bEndpointAddress; IN Endpoint 2 */ - 0x02, /* __u8 ep_bmAttributes; Bulk */ - 0x00, 0x04, /* __le16 ep_wMaxPacketSize; 1024 */ - 0x40 /* __u8 ep_bInterval; */ - - 0x07, /* __u8 ep_bLength; */ - 0x05, /* __u8 ep_bDescriptorType; Endpoint */ - 0x02, /* __u8 ep_bEndpointAddress; Out Endpoint 2 */ - 0x02, /* __u8 ep_bmAttributes; Bulk */ - 0x00, 0x04, /* __le16 ep_wMaxPacketSize; 1024 */ - 0x40 /* __u8 ep_bInterval; */ -}; diff --git a/drivers/staging/greybus/devices b/drivers/staging/greybus/devices deleted file mode 100644 index 486bba8..0000000 --- a/drivers/staging/greybus/devices +++ /dev/null @@ -1,11 +0,0 @@ -T: Bus=01 Lev=03 Prnt=07 Port=02 Cnt=03 Dev#= 12 Spd=12 MxCh= 0 -D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 -P: Vendor=ffff ProdID=0001 Rev= 1.00 -S: Manufacturer=Greybus -S: Product=SVC Bridge -S: SerialNumber=12239 -C:* #Ifs= 1 Cfg#= 1 Atr=c0 MxPwr=100mA -I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=es1_ap_driver -E: Ad=81(I) Atr=03(Int.) MxPS= 64 Ivl=64ms -E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms -E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms -- cgit v0.10.2 From d4f56b47a8fac90b15adfae80a42a2735d6b3213 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Mon, 19 Sep 2016 15:46:40 +0200 Subject: staging: greybus: Add drivers/staging/greybus to the build This adds a proper Kconfig file for drivers/staging/greybus and fixes up the Makefile to work correctly within the kernel build system (modules depend on the .config options, etc.) Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index af94764..59829d8 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -104,4 +104,6 @@ source "drivers/staging/i4l/Kconfig" source "drivers/staging/ks7010/Kconfig" +source "drivers/staging/greybus/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 9f6009d..210fcea 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -41,3 +41,4 @@ obj-$(CONFIG_WILC1000) += wilc1000/ obj-$(CONFIG_MOST) += most/ obj-$(CONFIG_ISDN_I4L) += i4l/ obj-$(CONFIG_KS7010) += ks7010/ +obj-$(CONFIG_GREYBUS) += greybus/ diff --git a/drivers/staging/greybus/Kconfig b/drivers/staging/greybus/Kconfig new file mode 100644 index 0000000..c169bc3 --- /dev/null +++ b/drivers/staging/greybus/Kconfig @@ -0,0 +1,219 @@ +menuconfig GREYBUS + tristate "Greybus support" + depends on SYSFS + ---help--- + This option enables the Greybus driver core. Greybus is an + hardware protocol that was designed to provide Unipro with a + sane application layer. It was originally designed for the + ARA project, a module phone system, but has shown up in other + phones, and can be tunneled over other busses in order to + control hardware devices. + + Say Y here to enable support for these types of drivers. + + To compile this code as a module, chose M here: the module + will be called greybus.ko + +if GREYBUS + +config GREYBUS_ES2 + tristate "Greybus ES3 USB host controller" + depends on USB + ---help--- + Select this option if you have a Toshiba ES3 USB device that + acts as a Greybus "host controller". This device is a bridge + from a USB device to a Unipro network. + + To compile this code as a module, chose M here: the module + will be called gb-es2.ko + +config GREYBUS_AUDIO + tristate "Greybus Audio Class driver" + depends on SOUND + ---help--- + Select this option if you have a device that follows the + Greybus Audio Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-audio.ko + +config GREYBUS_BOOTROM + tristate "Greybus Bootrom Class driver" + ---help--- + Select this option if you have a device that follows the + Greybus Bootrom Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-bootrom.ko + +config GREYBUS_CAMERA + tristate "Greybus Camera Class driver" + depends on MEDIA && LEDS_CLASS_FLASH && BROKEN + ---help--- + Select this option if you have a device that follows the + Greybus Camera Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-camera.ko + +config GREYBUS_FIRMWARE + tristate "Greybus Firmware Download Class driver" + depends on SPI + ---help--- + Select this option if you have a device that follows the + Greybus Firmware Download Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-firmware.ko + +config GREYBUS_HID + tristate "Greybus HID Class driver" + depends on HID && INPUT + ---help--- + Select this option if you have a device that follows the + Greybus HID Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-hid.ko + +config GREYBUS_LIGHT + tristate "Greybus LED Class driver" + depends on LEDS_CLASS && BROKEN + ---help--- + Select this option if you have a device that follows the + Greybus LED Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-led.ko + +config GREYBUS_LOG + tristate "Greybus Debug Log Class driver" + ---help--- + Select this option if you have a device that follows the + Greybus Debug Log Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-log.ko + +config GREYBUS_LOOPBACK + tristate "Greybus Loopback Class driver" + ---help--- + Select this option if you have a device that follows the + Greybus Debug Log Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-log.ko + +config GREYBUS_POWER + tristate "Greybus Powersupply Class driver" + depends on POWER_SUPPLY + ---help--- + Select this option if you have a device that follows the + Greybus Powersupply Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-power-supply.ko + +config GREYBUS_RAW + tristate "Greybus Raw Class driver" + ---help--- + Select this option if you have a device that follows the + Greybus Raw Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-raw.ko + +config GREYBUS_VIBRATOR + tristate "Greybus Vibrator Motor Class driver" + ---help--- + Select this option if you have a device that follows the + Greybus Vibrator Motor Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-vibrator.ko + +menuconfig GREYBUS_BRIDGED_PHY + tristate "Greybus Bridged PHY Class drivers" + ---help--- + Select this option to pick from a variety of Greybus Bridged + PHY class drivers. These drivers emulate a number of + different "traditional" busses by tunneling them over Greybus. + Examples of this include serial, SPI, USB, and others. + + To compile this code as a module, chose M here: the module + will be called gb-phy.ko + +if GREYBUS_BRIDGED_PHY + +config GREYBUS_GPIO + tristate "Greybus GPIO Bridged PHY driver" + depends on GPIO + ---help--- + Select this option if you have a device that follows the + Greybus GPIO Bridged PHY Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-gpio.ko + +config GREYBUS_I2C + tristate "Greybus I2C Bridged PHY driver" + depends on I2C + ---help--- + Select this option if you have a device that follows the + Greybus I2C Bridged PHY Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-i2c.ko + +config GREYBUS_PWM + tristate "Greybus PWM Bridged PHY driver" + depends on PWM + ---help--- + Select this option if you have a device that follows the + Greybus PWM Bridged PHY Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-pwm.ko + +config GREYBUS_SDIO + tristate "Greybus SDIO Bridged PHY driver" + depends on MMC + ---help--- + Select this option if you have a device that follows the + Greybus SDIO Bridged PHY Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-sdio.ko + +config GREYBUS_SPI + tristate "Greybus SPI Bridged PHY driver" + depends on SPI + ---help--- + Select this option if you have a device that follows the + Greybus SPI Bridged PHY Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-spi.ko + +config GREYBUS_UART + tristate "Greybus UART Bridged PHY driver" + depends on TTY + ---help--- + Select this option if you have a device that follows the + Greybus UART Bridged PHY Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-uart.ko + +config GREYBUS_USB + tristate "Greybus USB Host Bridged PHY driver" + depends on USB + ---help--- + Select this option if you have a device that follows the + Greybus USB Host Bridged PHY Class specification. + + To compile this code as a module, chose M here: the module + will be called gb-usb.ko + +endif # GREYBUS_BRIDGED_PHY +endif # GREYBUS diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index fa5aaf3..0cc769e 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -1,3 +1,4 @@ +# Greybus core greybus-y := core.o \ debugfs.o \ hd.o \ @@ -13,135 +14,83 @@ greybus-y := core.o \ timesync.o \ timesync_platform.o -gb-gbphy-y := gbphy.o - -# Prefix all modules with gb- -gb-vibrator-y := vibrator.o -gb-power-supply-y := power_supply.o -gb-log-y := log.o -gb-loopback-y := loopback.o -gb-light-y := light.o -gb-raw-y := raw.o -gb-hid-y := hid.o -gb-es2-y := es2.o -gb-arche-y := arche-platform.o arche-apb-ctrl.o -gb-audio-module-y := audio_module.o audio_topology.o -gb-audio-codec-y := audio_codec.o -gb-audio-gb-y := audio_gb.o -gb-audio-apbridgea-y := audio_apbridgea.o -gb-audio-manager-y += audio_manager.o -gb-audio-manager-y += audio_manager_module.o -gb-bootrom-y := bootrom.o -gb-camera-y := camera.o -gb-firmware-y := fw-core.o fw-download.o fw-management.o authentication.o -gb-spilib-y := spilib.o -gb-sdio-y := sdio.o -gb-uart-y := uart.o -gb-pwm-y := pwm.o -gb-gpio-y := gpio.o -gb-i2c-y := i2c.o -gb-usb-y := usb.o -gb-spi-y := spi.o - -obj-m += greybus.o -obj-m += gb-gbphy.o -obj-m += gb-vibrator.o -obj-m += gb-power-supply.o -obj-m += gb-log.o -obj-m += gb-loopback.o -obj-m += gb-light.o -obj-m += gb-hid.o -obj-m += gb-raw.o -obj-m += gb-es2.o -ifeq ($(CONFIG_USB_HSIC_USB3613),y) - obj-m += gb-arche.o -endif -ifeq ($(CONFIG_ARCH_MSM8994),y) - obj-m += gb-audio-codec.o - obj-m += gb-audio-module.o - obj-m += gb-camera.o -endif -obj-m += gb-audio-gb.o -obj-m += gb-audio-apbridgea.o -obj-m += gb-audio-manager.o -obj-m += gb-bootrom.o -obj-m += gb-firmware.o -obj-m += gb-spilib.o -obj-m += gb-sdio.o -obj-m += gb-uart.o -obj-m += gb-pwm.o -obj-m += gb-gpio.o -obj-m += gb-i2c.o -obj-m += gb-usb.o -obj-m += gb-spi.o - -KERNELVER ?= $(shell uname -r) -KERNELDIR ?= /lib/modules/$(KERNELVER)/build -INSTALL_MOD_PATH ?= /.. -PWD := $(shell pwd) - -# kernel config option that shall be enable -CONFIG_OPTIONS_ENABLE := POWER_SUPPLY PWM SYSFS SPI USB SND_SOC MMC LEDS_CLASS INPUT - -# kernel config option that shall be disable -CONFIG_OPTIONS_DISABLE := - -# this only run in kbuild part of the makefile -ifneq ($(KERNELRELEASE),) -# This function returns the argument version if current kernel version is minor -# than the passed version, return 1 if equal or the current kernel version if it -# is greater than argument version. -kvers_cmp=$(shell [ "$(KERNELVERSION)" = "$(1)" ] && echo 1 || printf "$(1)\n$(KERNELVERSION)" | sort -V | tail -1) - -ifneq ($(call kvers_cmp,"3.19.0"),3.19.0) - CONFIG_OPTIONS_ENABLE += LEDS_CLASS_FLASH -endif - -ifneq ($(call kvers_cmp,"4.2.0"),4.2.0) - CONFIG_OPTIONS_ENABLE += V4L2_FLASH_LED_CLASS -endif - -$(foreach opt,$(CONFIG_OPTIONS_ENABLE),$(if $(CONFIG_$(opt)),, \ - $(error CONFIG_$(opt) is disabled in the kernel configuration and must be enable \ - to continue compilation))) -$(foreach opt,$(CONFIG_OPTIONS_DISABLE),$(if $(filter m y, $(CONFIG_$(opt))), \ - $(error CONFIG_$(opt) is enabled in the kernel configuration and must be disable \ - to continue compilation),)) -endif - -# add -Wall to try to catch everything we can. -ccflags-y := -Wall +obj-$(CONFIG_GREYBUS) += greybus.o # needed for trace events ccflags-y += -I$(src) -GB_AUDIO_MANAGER_SYSFS ?= true -ifeq ($(GB_AUDIO_MANAGER_SYSFS),true) -gb-audio-manager-y += audio_manager_sysfs.o -ccflags-y += -DGB_AUDIO_MANAGER_SYSFS -endif -all: module - -tools:: - $(MAKE) -C tools KERNELDIR=$(realpath $(KERNELDIR)) +# Greybus Host controller drivers +gb-es2-y := es2.o -module: - $(MAKE) -C $(KERNELDIR) M=$(PWD) +obj-$(CONFIG_GREYBUS_ES2) += gb-es2.o + +# Greybus class drivers +gb-bootrom-y := bootrom.o +gb-camera-y := camera.o +gb-firmware-y := fw-core.o fw-download.o fw-management.o authentication.o +gb-spilib-y := spilib.o +gb-hid-y := hid.o +gb-light-y := light.o +gb-log-y := log.o +gb-loopback-y := loopback.o +gb-power-supply-y := power_supply.o +gb-raw-y := raw.o +gb-vibrator-y := vibrator.o + +obj-$(CONFIG_GREYBUS_BOOTROM) += gb-bootrom.o +obj-$(CONFIG_GREYBUS_CAMERA) += gb-camera.o +obj-$(CONFIG_GREYBUS_FIRMWARE) += gb-firmware.o gb-spilib.o +obj-$(CONFIG_GREYBUS_HID) += gb-hid.o +obj-$(CONFIG_GREYBUS_LIGHT) += gb-light.o +obj-$(CONFIG_GREYBUS_LOG) += gb-log.o +obj-$(CONFIG_GREYBUS_LOOPBACK) += gb-loopback.o +obj-$(CONFIG_GREYBUS_POWER) += gb-power-supply.o +obj-$(CONFIG_GREYBUS_RAW) += gb-raw.o +obj-$(CONFIG_GREYBUS_VIBRATOR) += gb-vibrator.o + +# Greybus Audio is a bunch of modules +gb-audio-module-y := audio_module.o audio_topology.o +gb-audio-codec-y := audio_codec.o +gb-audio-gb-y := audio_gb.o +gb-audio-apbridgea-y := audio_apbridgea.o +gb-audio-manager-y := audio_manager.o audio_manager_module.o + +# Greybus Audio sysfs helpers can be useful when debugging +#GB_AUDIO_MANAGER_SYSFS ?= true +#ifeq ($(GB_AUDIO_MANAGER_SYSFS),true) +#gb-audio-manager-y += audio_manager_sysfs.o +#ccflags-y += -DGB_AUDIO_MANAGER_SYSFS +#endif + +obj-$(CONFIG_GREYBUS_AUDIO_MSM8994) += gb-audio-codec.o +obj-$(CONFIG_GREYBUS_AUDIO_MSM8994) += gb-audio-module.o +obj-$(CONFIG_GREYBUS_AUDIO) += gb-audio-gb.o +obj-$(CONFIG_GREYBUS_AUDIO) += gb-audio-apbridgea.o +obj-$(CONFIG_GREYBUS_AUDIO) += gb-audio-manager.o + + +# Greybus Bridged PHY drivers +gb-gbphy-y := gbphy.o +gb-gpio-y := gpio.o +gb-i2c-y := i2c.o +gb-pwm-y := pwm.o +gb-sdio-y := sdio.o +gb-spi-y := spi.o +gb-uart-y := uart.o +gb-usb-y := usb.o -check: - $(MAKE) -C $(KERNELDIR) M=$(PWD) C=2 CF="-D__CHECK_ENDIAN__" +obj-$(CONFIG_GREYBUS_BRIDGED_PHY) += gb-gbphy.o +obj-$(CONFIG_GREYBUS_GPIO) += gb-gpio.o +obj-$(CONFIG_GREYBUS_I2C) += gb-i2c.o +obj-$(CONFIG_GREYBUS_PWM) += gb-pwm.o +obj-$(CONFIG_GREYBUS_SDIO) += gb-sdio.o +obj-$(CONFIG_GREYBUS_SPI) += gb-spi.o +obj-$(CONFIG_GREYBUS_UART) += gb-uart.o +obj-$(CONFIG_GREYBUS_USB) += gb-usb.o -clean: - rm -f *.o *~ core .depend .*.cmd *.ko *.mod.c - rm -f Module.markers Module.symvers modules.order - rm -rf .tmp_versions Modules.symvers - $(MAKE) -C tools clean -coccicheck: - $(MAKE) -C $(KERNELDIR) M=$(PWD) coccicheck +# Greybus Platform driver +gb-arche-y := arche-platform.o arche-apb-ctrl.o -install: module - mkdir -p $(INSTALL_MOD_PATH)/lib/modules/$(KERNELVER)/kernel/drivers/greybus/ - cp -f *.ko $(INSTALL_MOD_PATH)/lib/modules/$(KERNELVER)/kernel/drivers/greybus/ - depmod -b $(INSTALL_MOD_PATH) -a $(KERNELVER) +obj-$(CONFIG_USB_HSIC_USB3613) += gb-arche.o -- cgit v0.10.2 From 887520884b9925312b78d23f323d9cf1f7e603af Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Thu, 8 Sep 2016 11:51:33 +0200 Subject: staging: greybus: kernel_ver.h: remove lots of stuff Now that we do not care about the kernel version we are building against, we can strip out lots of backward compatibilty that was added to kernel_ver.h in order to write semi-portable driver code. To start with, remove the functions and #defines that are now in the kernel tree, no need to have duplicate copies of them all. Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index 97e7ac9..eda9485 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -22,49 +22,6 @@ #define CORE_OWNS_PSY_STRUCT #endif -#ifndef __ATTR_WO -#define __ATTR_WO(_name) { \ - .attr = { .name = __stringify(_name), .mode = S_IWUSR }, \ - .store = _name##_store, \ -} -#endif - -#ifndef __ATTR_RW -#define __ATTR_RW(_name) __ATTR(_name, (S_IWUSR | S_IRUGO), \ - _name##_show, _name##_store) -#endif - -#ifndef DEVICE_ATTR_RO -#define DEVICE_ATTR_RO(_name) \ - struct device_attribute dev_attr_##_name = __ATTR_RO(_name) -#endif - -#ifndef DEVICE_ATTR_WO -#define DEVICE_ATTR_WO(_name) \ - struct device_attribute dev_attr_##_name = __ATTR_WO(_name) -#endif - -#ifndef DEVICE_ATTR_RW -#define DEVICE_ATTR_RW(_name) \ - struct device_attribute dev_attr_##_name = __ATTR_RW(_name) -#endif - -#ifndef U8_MAX -#define U8_MAX ((u8)~0U) -#endif /* ! U8_MAX */ - -#ifndef U16_MAX -#define U16_MAX ((u16)(~0U)) -#endif /* !U16_MAX */ - -#ifndef U32_MAX -#define U32_MAX ((u32)(~0U)) -#endif /* !U32_MAX */ - -#ifndef U64_MAX -#define U64_MAX ((u64)(~0U)) -#endif /* !U64_MAX */ - /* * The GPIO api sucks rocks in places, like removal, so work around their * explicit requirements of catching the return value for kernels older than @@ -87,54 +44,6 @@ static inline void gb_gpiochip_remove(struct gpio_chip *chip) } #endif -/* - * ATTRIBUTE_GROUPS showed up in 3.11-rc2, but we need to build on 3.10, so add - * it here. - */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) -#include <linux/sysfs.h> - -#define ATTRIBUTE_GROUPS(name) \ -static const struct attribute_group name##_group = { \ - .attrs = name##_attrs, \ -}; \ -static const struct attribute_group *name##_groups[] = { \ - &name##_group, \ - NULL, \ -} - -static inline int sysfs_create_groups(struct kobject *kobj, - const struct attribute_group **groups) -{ - int error = 0; - int i; - - if (!groups) - return 0; - - for (i = 0; groups[i]; i++) { - error = sysfs_create_group(kobj, groups[i]); - if (error) { - while (--i >= 0) - sysfs_remove_group(kobj, groups[i]); - break; - } - } - return error; -} - -static inline void sysfs_remove_groups(struct kobject *kobj, - const struct attribute_group **groups) -{ - int i; - - if (!groups) - return; - for (i = 0; groups[i]; i++) - sysfs_remove_group(kobj, groups[i]); -} -#endif - #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) #define MMC_HS400_SUPPORTED #define MMC_DDR52_DEFINED @@ -148,110 +57,6 @@ static inline void sysfs_remove_groups(struct kobject *kobj, #define MMC_POWER_UNDEFINED_SUPPORTED #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) -#include <linux/scatterlist.h> -static inline bool sg_miter_get_next_page(struct sg_mapping_iter *miter) -{ - if (!miter->__remaining) { - struct scatterlist *sg; - unsigned long pgoffset; - - if (!__sg_page_iter_next(&miter->piter)) - return false; - - sg = miter->piter.sg; - pgoffset = miter->piter.sg_pgoffset; - - miter->__offset = pgoffset ? 0 : sg->offset; - miter->__remaining = sg->offset + sg->length - - (pgoffset << PAGE_SHIFT) - miter->__offset; - miter->__remaining = min_t(unsigned long, miter->__remaining, - PAGE_SIZE - miter->__offset); - } - - return true; -} - -static inline bool sg_miter_skip(struct sg_mapping_iter *miter, off_t offset) -{ - sg_miter_stop(miter); - - while (offset) { - off_t consumed; - - if (!sg_miter_get_next_page(miter)) - return false; - - consumed = min_t(off_t, offset, miter->__remaining); - miter->__offset += consumed; - miter->__remaining -= consumed; - offset -= consumed; - } - - return true; -} - -static inline size_t _sg_copy_buffer(struct scatterlist *sgl, - unsigned int nents, void *buf, - size_t buflen, off_t skip, - bool to_buffer) -{ - unsigned int offset = 0; - struct sg_mapping_iter miter; - unsigned long flags; - unsigned int sg_flags = SG_MITER_ATOMIC; - - if (to_buffer) - sg_flags |= SG_MITER_FROM_SG; - else - sg_flags |= SG_MITER_TO_SG; - - sg_miter_start(&miter, sgl, nents, sg_flags); - - if (!sg_miter_skip(&miter, skip)) - return false; - - local_irq_save(flags); - - while (sg_miter_next(&miter) && offset < buflen) { - unsigned int len; - - len = min(miter.length, buflen - offset); - - if (to_buffer) - memcpy(buf + offset, miter.addr, len); - else - memcpy(miter.addr, buf + offset, len); - - offset += len; - } - - sg_miter_stop(&miter); - - local_irq_restore(flags); - return offset; -} - -static inline size_t sg_pcopy_to_buffer(struct scatterlist *sgl, - unsigned int nents, void *buf, - size_t buflen, off_t skip) -{ - return _sg_copy_buffer(sgl, nents, buf, buflen, skip, true); -} - -static inline size_t sg_pcopy_from_buffer(struct scatterlist *sgl, - unsigned int nents, void *buf, - size_t buflen, off_t skip) -{ - return _sg_copy_buffer(sgl, nents, buf, buflen, skip, false); -} -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) -#define list_last_entry(ptr, type, member) \ - list_entry((ptr)->prev, type, member) -#endif - #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) /* * At this time the internal API for the set brightness was changed to the async @@ -273,19 +78,6 @@ static inline size_t sg_pcopy_from_buffer(struct scatterlist *sgl, #define LED_HAVE_SET_BLOCKING #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) -/* - * From this version upper it was introduced the possibility to disable led - * sysfs entries to handle control of the led device to v4l2, which was - * implemented later. So, before that this should return false. - */ -#include <linux/leds.h> -static inline bool led_sysfs_is_disabled(struct led_classdev *led_cdev) -{ - return false; -} -#endif - #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) /* * New helper functions for registering/unregistering flash led devices as v4l2 @@ -329,82 +121,6 @@ static inline bool led_sysfs_is_disabled(struct led_classdev *led_cdev) #define SPI_CORE_SUPPORT_PM #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) -/** - * reinit_completion - reinitialize a completion structure - * @x: pointer to completion structure that is to be reinitialized - * - * This inline function should be used to reinitialize a completion structure - * so it can be reused. This is especially important after complete_all() is - * used. - */ -static inline void reinit_completion(struct completion *x) -{ - x->done = 0; -} -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0) -#include <linux/pwm.h> -/* - * pwm_is_enabled() was first defined in 4.3. - * PWMF_ENABLED was first defined in 3.5-rc2, but our code is - * always newer than that. -*/ -static inline bool pwm_is_enabled(const struct pwm_device *pwm) -{ - return test_bit(PWMF_ENABLED, &pwm->flags); -} -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) -/** - * kstrtobool - convert common user inputs into boolean values - * @s: input string - * @res: result - * - * This routine returns 0 iff the first character is one of 'Yy1Nn0', or - * [oO][NnFf] for "on" and "off". Otherwise it will return -EINVAL. Value - * pointed to by res is updated upon finding a match. - */ -static inline int kstrtobool(const char *s, bool *res) -{ - if (!s) - return -EINVAL; - - switch (s[0]) { - case 'y': - case 'Y': - case '1': - *res = true; - return 0; - case 'n': - case 'N': - case '0': - *res = false; - return 0; - case 'o': - case 'O': - switch (s[1]) { - case 'n': - case 'N': - *res = true; - return 0; - case 'f': - case 'F': - *res = false; - return 0; - default: - break; - } - default: - break; - } - - return -EINVAL; -} -#endif - #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) /* * After commit b2b49ccbdd54 (PM: Kconfig: Set PM_RUNTIME if PM_SLEEP is -- cgit v0.10.2 From be21106d67db9ad3c66e48c8efdcf1bc08be45a4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Thu, 8 Sep 2016 15:46:38 +0200 Subject: staging: greybus: hid: remove KERNEL_VERSION checks No need to support older kernel versions in the Greybus HID driver, so remove the checks as needed, we can now rely on all of the "new" apis being present. Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index b558c81..730d746 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -277,23 +277,6 @@ static int gb_hid_raw_request(struct hid_device *hid, unsigned char reportnum, } } -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0) -static int gb_hid_get_raw_report(struct hid_device *hid, - unsigned char reportnum, __u8 *buf, - size_t len, unsigned char rtype) -{ - return gb_hid_raw_request(hid, reportnum, buf, len, rtype, - HID_REQ_GET_REPORT); -} - -static int gb_hid_output_raw_report(struct hid_device *hid, __u8 *buf, - size_t len, unsigned char rtype) -{ - return gb_hid_raw_request(hid, buf[0], buf, len, rtype, - HID_REQ_SET_REPORT); -} -#endif - /* HID Callbacks */ static int gb_hid_parse(struct hid_device *hid) { @@ -422,9 +405,7 @@ static struct hid_ll_driver gb_hid_ll_driver = { .open = gb_hid_open, .close = gb_hid_close, .power = gb_hid_power, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0) .raw_request = gb_hid_raw_request, -#endif }; static int gb_hid_init(struct gb_hid *ghid) @@ -444,10 +425,6 @@ static int gb_hid_init(struct gb_hid *ghid) hid->driver_data = ghid; hid->ll_driver = &gb_hid_ll_driver; hid->dev.parent = &ghid->connection->bundle->dev; -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0) - hid->hid_get_raw_report = gb_hid_get_raw_report; - hid->hid_output_raw_report = gb_hid_output_raw_report; -#endif // hid->bus = BUS_GREYBUS; /* Need a bustype for GREYBUS in <linux/input.h> */ /* Set HID device's name */ -- cgit v0.10.2 From 06000c03174988b4e8167d03ad0a36c6792686cb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Thu, 8 Sep 2016 15:47:30 +0200 Subject: staging: greybus: vibrator: remove KERNEL_VERSION checks No need to support older kernel versions in the Greybus Vibrator driver, so remove the checks as needed, we can now rely on all of the correct driver core apis being present. Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/vibrator.c b/drivers/staging/greybus/vibrator.c index 7296a4d..4ba0e16 100644 --- a/drivers/staging/greybus/vibrator.c +++ b/drivers/staging/greybus/vibrator.c @@ -108,9 +108,7 @@ ATTRIBUTE_GROUPS(vibrator); static struct class vibrator_class = { .name = "vibrator", .owner = THIS_MODULE, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) .dev_groups = vibrator_groups, -#endif }; static DEFINE_IDA(minors); @@ -169,19 +167,6 @@ static int gb_vibrator_probe(struct gb_bundle *bundle, } vib->dev = dev; -#if LINUX_VERSION_CODE <= KERNEL_VERSION(3,11,0) - /* - * Newer kernels handle this in a race-free manner, by the dev_groups - * field in the struct class up above. But for older kernels, we need - * to "open code this :( - */ - retval = sysfs_create_group(&dev->kobj, vibrator_groups[0]); - if (retval) { - device_unregister(dev); - goto err_ida_remove; - } -#endif - INIT_DELAYED_WORK(&vib->delayed_work, gb_vibrator_worker); gb_pm_runtime_put_autosuspend(bundle); @@ -212,9 +197,6 @@ static void gb_vibrator_disconnect(struct gb_bundle *bundle) if (cancel_delayed_work_sync(&vib->delayed_work)) turn_off(vib); -#if LINUX_VERSION_CODE <= KERNEL_VERSION(3,11,0) - sysfs_remove_group(&vib->dev->kobj, vibrator_groups[0]); -#endif device_unregister(vib->dev); ida_simple_remove(&minors, vib->minor); gb_connection_disable(vib->connection); -- cgit v0.10.2 From b14bb976260077415047737a0032f89275622c96 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Thu, 8 Sep 2016 15:52:06 +0200 Subject: staging: greybus: gpio: remove KERNEL_VERSION checks No need to support older kernel versions in the Greybus GPIO driver, so remove the checks as needed, we can now rely on all of the correct GPIO core apis being present. Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 294e2f5..ea8234a 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -404,11 +404,7 @@ static int gb_gpio_request_handler(struct gb_operation *op) } local_irq_disable(); -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0) - generic_handle_irq_desc(irq, desc); -#else generic_handle_irq_desc(desc); -#endif local_irq_enable(); return 0; @@ -684,11 +680,7 @@ static int gb_gpio_probe(struct gbphy_device *gbphy_dev, gpio = &ggc->chip; gpio->label = "greybus_gpio"; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0) gpio->parent = &gbphy_dev->dev; -#else - gpio->dev = &gbphy_dev->dev; -#endif gpio->owner = THIS_MODULE; gpio->request = gb_gpio_request; @@ -750,7 +742,7 @@ static void gb_gpio_remove(struct gbphy_device *gbphy_dev) gbphy_runtime_get_noresume(gbphy_dev); gb_connection_disable_rx(connection); - gb_gpiochip_remove(&ggc->chip); + gpiochip_remove(&ggc->chip); gb_gpio_irqchip_remove(ggc); gb_connection_disable(connection); gb_connection_destroy(connection); diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index eda9485..0e129ff 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -22,28 +22,6 @@ #define CORE_OWNS_PSY_STRUCT #endif -/* - * The GPIO api sucks rocks in places, like removal, so work around their - * explicit requirements of catching the return value for kernels older than - * 3.17, which they explicitly changed in the 3.17 kernel. Consistency is - * overrated. - */ -#include <linux/gpio.h> - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0) -static inline void gb_gpiochip_remove(struct gpio_chip *chip) -{ - gpiochip_remove(chip); -} -#else -static inline void gb_gpiochip_remove(struct gpio_chip *chip) -{ - int ret; - - ret = gpiochip_remove(chip); -} -#endif - #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) #define MMC_HS400_SUPPORTED #define MMC_DDR52_DEFINED -- cgit v0.10.2 From 3e4b5b883780ed795843f68213c9db3f8d78391e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Mon, 19 Sep 2016 16:41:54 +0200 Subject: staging: greybus: gpio: it's CONFIG_GPIOLIB, not CONFIG_GPIO The GPIO dependancy is CONFIG_GPIOLIB, not CONFIG_GPIO, no wonder it wasn't building properly... Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Kconfig b/drivers/staging/greybus/Kconfig index c169bc3..ede9184 100644 --- a/drivers/staging/greybus/Kconfig +++ b/drivers/staging/greybus/Kconfig @@ -147,7 +147,7 @@ if GREYBUS_BRIDGED_PHY config GREYBUS_GPIO tristate "Greybus GPIO Bridged PHY driver" - depends on GPIO + depends on GPIOLIB ---help--- Select this option if you have a device that follows the Greybus GPIO Bridged PHY Class specification. -- cgit v0.10.2 From 148e0b8f48a83008596876befe1d9aed256c8ea1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Thu, 8 Sep 2016 16:06:27 +0200 Subject: staging: greybus: spi: remove KERNEL_VERSION checks No need to support older kernel versions in the Greybus SPI and spilib driver, so remove the checks as needed, we can now rely on all of the correct SPI core apis being present. Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/fw-core.c b/drivers/staging/greybus/fw-core.c index a7e4a8c..454a989 100644 --- a/drivers/staging/greybus/fw-core.c +++ b/drivers/staging/greybus/fw-core.c @@ -20,26 +20,7 @@ struct gb_fw_core { struct gb_connection *cap_connection; }; -#ifndef SPI_CORE_SUPPORT_PM -static int fw_spi_prepare_transfer_hardware(struct device *dev) -{ - return gb_pm_runtime_get_sync(to_gb_bundle(dev)); -} - -static void fw_spi_unprepare_transfer_hardware(struct device *dev) -{ - gb_pm_runtime_put_autosuspend(to_gb_bundle(dev)); -} - -static struct spilib_ops __spilib_ops = { - .prepare_transfer_hardware = fw_spi_prepare_transfer_hardware, - .unprepare_transfer_hardware = fw_spi_unprepare_transfer_hardware, -}; - -static struct spilib_ops *spilib_ops = &__spilib_ops; -#else -static struct spilib_ops *spilib_ops = NULL; -#endif +static struct spilib_ops *spilib_ops; struct gb_connection *to_fw_mgmt_connection(struct device *dev) { diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index 0e129ff..59d55be 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -86,19 +86,6 @@ #define POWER_SUPPLY_PROP_CALIBRATE -1 #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) -#define SPI_DEV_MODALIAS "spidev" -#define SPI_NOR_MODALIAS "spi-nor" -#else -#define SPI_DEV_MODALIAS "spidev" -#define SPI_NOR_MODALIAS "m25p80" -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0) -/* Starting from this version, the spi core handles runtime pm automatically */ -#define SPI_CORE_SUPPORT_PM -#endif - #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) /* * After commit b2b49ccbdd54 (PM: Kconfig: Set PM_RUNTIME if PM_SLEEP is diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index bb76b3c..c893552 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -13,26 +13,7 @@ #include "gbphy.h" #include "spilib.h" -#ifndef SPI_CORE_SUPPORT_PM -static int gbphy_spi_prepare_transfer_hardware(struct device *dev) -{ - return gbphy_runtime_get_sync(to_gbphy_dev(dev)); -} - -static void gbphy_spi_unprepare_transfer_hardware(struct device *dev) -{ - gbphy_runtime_put_autosuspend(to_gbphy_dev(dev)); -} - -static struct spilib_ops __spilib_ops = { - .prepare_transfer_hardware = gbphy_spi_prepare_transfer_hardware, - .unprepare_transfer_hardware = gbphy_spi_unprepare_transfer_hardware, -}; - -static struct spilib_ops *spilib_ops = &__spilib_ops; -#else -static struct spilib_ops *spilib_ops = NULL; -#endif +static struct spilib_ops *spilib_ops; static int gb_spi_probe(struct gbphy_device *gbphy_dev, const struct gbphy_device_id *id) diff --git a/drivers/staging/greybus/spilib.c b/drivers/staging/greybus/spilib.c index 9427c31..e97b191 100644 --- a/drivers/staging/greybus/spilib.c +++ b/drivers/staging/greybus/spilib.c @@ -456,10 +456,10 @@ static int gb_spi_setup_device(struct gb_spilib *spi, u8 cs) dev_type = response.device_type; if (dev_type == GB_SPI_SPI_DEV) - strlcpy(spi_board.modalias, SPI_DEV_MODALIAS, + strlcpy(spi_board.modalias, "spidev", sizeof(spi_board.modalias)); else if (dev_type == GB_SPI_SPI_NOR) - strlcpy(spi_board.modalias, SPI_NOR_MODALIAS, + strlcpy(spi_board.modalias, "spi-nor", sizeof(spi_board.modalias)); else if (dev_type == GB_SPI_SPI_MODALIAS) memcpy(spi_board.modalias, response.name, @@ -526,9 +526,7 @@ int gb_spilib_master_init(struct gb_connection *connection, struct device *dev, gb_spi_unprepare_transfer_hardware; } -#ifdef SPI_CORE_SUPPORT_PM master->auto_runtime_pm = true; -#endif ret = spi_register_master(master); if (ret < 0) -- cgit v0.10.2 From 7434564ca130552f3f873d0a7e87286a16890c32 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Thu, 8 Sep 2016 16:10:50 +0200 Subject: staging: greybus: sdio: fix min() type check The 0-day bot pointed out a type difference in one min() call, so fix it up by being explicit about the type being compared. Reported-by: kbuild test robot <fengguang.wu@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index a78d9e4..99b9979 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -136,7 +136,7 @@ static int gb_sdio_get_caps(struct gb_sdio_host *host) data_max = min(data_max - sizeof(struct gb_sdio_transfer_request), data_max - sizeof(struct gb_sdio_transfer_response)); - blksz = min(le16_to_cpu(response.max_blk_size), data_max); + blksz = min_t(u16, le16_to_cpu(response.max_blk_size), data_max); blksz = max_t(u32, 512, blksz); mmc->max_blk_size = rounddown_pow_of_two(blksz); -- cgit v0.10.2 From a7af2fe6d1baa45e73531fb994444fa0f59d8f62 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva <rui.silva@linaro.org> Date: Thu, 8 Sep 2016 17:17:48 +0100 Subject: staging: greybus: light: remove KERNEL_VERSION checks No need to support older kernel versions in the Greybus Light driver, so remove the checks as needed, we can now rely on all of the correct LED core apis being present. And compile only if flash and v4l2 flash is reachable. Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index 59d55be..980263f 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -35,36 +35,6 @@ #define MMC_POWER_UNDEFINED_SUPPORTED #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) -/* - * At this time the internal API for the set brightness was changed to the async - * version, and one sync API was added to handle cases that need immediate - * effect. Also, the led class flash and lock for sysfs access was introduced. - */ -#define LED_HAVE_SET_SYNC -#define LED_HAVE_FLASH -#define LED_HAVE_LOCK -#include <linux/led-class-flash.h> -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0) -/* - * New change in LED api, the set_sync operation was renamed to set_blocking and - * the workqueue is now handle by core. So, only one set operation is need. - */ -#undef LED_HAVE_SET_SYNC -#define LED_HAVE_SET_BLOCKING -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) -/* - * New helper functions for registering/unregistering flash led devices as v4l2 - * subdevices were added. - */ -#define V4L2_HAVE_FLASH -#include <media/v4l2-flash-led-class.h> -#endif - #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) /* * Power supply get by name need to drop reference after call diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index 71db077..b2847fe 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -9,9 +9,11 @@ #include <linux/kernel.h> #include <linux/leds.h> +#include <linux/led-class-flash.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/version.h> +#include <media/v4l2-flash-led-class.h> #include "greybus.h" #include "greybus_protocols.h" @@ -30,11 +32,8 @@ struct gb_channel { struct attribute **attrs; struct attribute_group *attr_group; const struct attribute_group **attr_groups; -#ifndef LED_HAVE_SET_BLOCKING - struct work_struct work_brightness_set; -#endif struct led_classdev *led; -#ifdef LED_HAVE_FLASH +#if IS_REACHABLE(CONFIG_LEDS_CLASS_FLASH) struct led_classdev_flash fled; struct led_flash_setting intensity_uA; struct led_flash_setting timeout_us; @@ -58,7 +57,7 @@ struct gb_light { struct gb_channel *channels; bool has_flash; bool ready; -#ifdef V4L2_HAVE_FLASH +#if IS_REACHABLE(CONFIG_V4L2_FLASH_LED_CLASS) struct v4l2_flash *v4l2_flash; #endif }; @@ -88,7 +87,7 @@ static bool is_channel_flash(struct gb_channel *channel) | GB_CHANNEL_MODE_INDICATOR)); } -#ifdef LED_HAVE_FLASH +#if IS_REACHABLE(CONFIG_LEDS_CLASS_FLASH) static struct gb_channel *get_channel_from_cdev(struct led_classdev *cdev) { struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(cdev); @@ -157,7 +156,7 @@ static int __gb_lights_flash_brightness_set(struct gb_channel *channel) return __gb_lights_flash_intensity_set(channel, intensity); } -#else /* LED_HAVE_FLASH */ +#else static struct gb_channel *get_channel_from_cdev(struct led_classdev *cdev) { return container_of(cdev, struct gb_channel, cled); @@ -172,12 +171,11 @@ static int __gb_lights_flash_brightness_set(struct gb_channel *channel) { return 0; } -#endif /* !LED_HAVE_FLASH */ +#endif static int gb_lights_color_set(struct gb_channel *channel, u32 color); static int gb_lights_fade_set(struct gb_channel *channel); -#ifdef LED_HAVE_LOCK static void led_lock(struct led_classdev *cdev) { mutex_lock(&cdev->led_access); @@ -187,15 +185,6 @@ static void led_unlock(struct led_classdev *cdev) { mutex_unlock(&cdev->led_access); } -#else -static void led_lock(struct led_classdev *cdev) -{ -} - -static void led_unlock(struct led_classdev *cdev) -{ -} -#endif /* !LED_HAVE_LOCK */ #define gb_lights_fade_attr(__dir) \ static ssize_t fade_##__dir##_show(struct device *dev, \ @@ -444,39 +433,6 @@ static int __gb_lights_brightness_set(struct gb_channel *channel) return ret; } -#ifndef LED_HAVE_SET_BLOCKING -static void gb_brightness_set_work(struct work_struct *work) -{ - struct gb_channel *channel = container_of(work, struct gb_channel, - work_brightness_set); - - __gb_lights_brightness_set(channel); -} - -#ifdef LED_HAVE_SET_SYNC -static int gb_brightness_set_sync(struct led_classdev *cdev, - enum led_brightness value) -{ - struct gb_channel *channel = get_channel_from_cdev(cdev); - - channel->led->brightness = value; - - return __gb_lights_brightness_set(channel); -} -#endif - -static void gb_brightness_set(struct led_classdev *cdev, - enum led_brightness value) -{ - struct gb_channel *channel = get_channel_from_cdev(cdev); - - if (channel->releasing) - return; - - cdev->brightness = value; - schedule_work(&channel->work_brightness_set); -} -#else /* LED_HAVE_SET_BLOCKING */ static int gb_brightness_set(struct led_classdev *cdev, enum led_brightness value) { @@ -486,7 +442,6 @@ static int gb_brightness_set(struct led_classdev *cdev, return __gb_lights_brightness_set(channel); } -#endif static enum led_brightness gb_brightness_get(struct led_classdev *cdev) @@ -554,22 +509,13 @@ static void gb_lights_led_operations_set(struct gb_channel *channel, struct led_classdev *cdev) { cdev->brightness_get = gb_brightness_get; -#ifdef LED_HAVE_SET_SYNC - cdev->brightness_set_sync = gb_brightness_set_sync; -#endif -#ifdef LED_HAVE_SET_BLOCKING cdev->brightness_set_blocking = gb_brightness_set; -#endif -#ifndef LED_HAVE_SET_BLOCKING - cdev->brightness_set = gb_brightness_set; - INIT_WORK(&channel->work_brightness_set, gb_brightness_set_work); -#endif if (channel->flags & GB_LIGHT_CHANNEL_BLINK) cdev->blink_set = gb_blink_set; } -#ifdef V4L2_HAVE_FLASH +#if IS_REACHABLE(CONFIG_V4L2_FLASH_LED_CLASS) /* V4L2 specific helpers */ static const struct v4l2_flash_ops v4l2_flash_ops; @@ -655,7 +601,7 @@ static void gb_lights_light_v4l2_unregister(struct gb_light *light) } #endif -#ifdef LED_HAVE_FLASH +#if IS_REACHABLE(CONFIG_LEDS_CLASS_FLASH) /* Flash specific operations */ static int gb_lights_flash_intensity_set(struct led_classdev_flash *fcdev, u32 brightness) @@ -936,7 +882,7 @@ static void __gb_lights_flash_led_unregister(struct gb_channel *channel) { } -#endif /* LED_HAVE_FLASH */ +#endif static int __gb_lights_led_register(struct gb_channel *channel) { @@ -1132,9 +1078,6 @@ static int gb_lights_light_register(struct gb_light *light) static void gb_lights_channel_free(struct gb_channel *channel) { -#ifndef LED_HAVE_SET_BLOCKING - flush_work(&channel->work_brightness_set); -#endif kfree(channel->attrs); kfree(channel->attr_group); kfree(channel->attr_groups); -- cgit v0.10.2 From 2064ae5741f49a3e8c178680390eb296592562c1 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva <rui.silva@linaro.org> Date: Thu, 8 Sep 2016 17:17:49 +0100 Subject: staging: greybus: sdio: remove KERNEL_VERSION checks No need to support older kernel versions in the Greybus SDIO driver, so remove the checks as needed, we can now rely on all of the correct SDIO core apis being present. Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index 980263f..1d93fb0 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -22,19 +22,6 @@ #define CORE_OWNS_PSY_STRUCT #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) -#define MMC_HS400_SUPPORTED -#define MMC_DDR52_DEFINED -#endif - -#ifndef MMC_CAP2_CORE_RUNTIME_PM -#define MMC_CAP2_CORE_RUNTIME_PM 0 -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0) -#define MMC_POWER_UNDEFINED_SUPPORTED -#endif - #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) /* * Power supply get by name need to drop reference after call diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index 99b9979..c7133b1 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -46,6 +46,10 @@ struct gb_sdio_host { /* kernel vdd starts at 0x80 and we need to translate to greybus ones 0x01 */ #define GB_SDIO_VDD_SHIFT 8 +#ifndef MMC_CAP2_CORE_RUNTIME_PM +#define MMC_CAP2_CORE_RUNTIME_PM 0 +#endif + static inline bool single_op(struct mmc_command *cmd) { uint32_t opcode = cmd->opcode; @@ -78,10 +82,8 @@ static void _gb_sdio_set_host_caps(struct gb_sdio_host *host, u32 r) ((r & GB_SDIO_CAP_DRIVER_TYPE_D) ? MMC_CAP_DRIVER_TYPE_D : 0); caps2 = ((r & GB_SDIO_CAP_HS200_1_2V) ? MMC_CAP2_HS200_1_2V_SDR : 0) | -#ifdef MMC_HS400_SUPPORTED ((r & GB_SDIO_CAP_HS400_1_2V) ? MMC_CAP2_HS400_1_2V : 0) | ((r & GB_SDIO_CAP_HS400_1_8V) ? MMC_CAP2_HS400_1_8V : 0) | -#endif ((r & GB_SDIO_CAP_HS200_1_8V) ? MMC_CAP2_HS200_1_8V_SDR : 0); host->mmc->caps = caps; @@ -617,11 +619,9 @@ static void gb_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) case MMC_POWER_ON: power_mode = GB_SDIO_POWER_ON; break; -#ifdef MMC_POWER_UNDEFINED_SUPPORTED case MMC_POWER_UNDEFINED: power_mode = GB_SDIO_POWER_UNDEFINED; break; -#endif } request.power_mode = power_mode; @@ -665,19 +665,15 @@ static void gb_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) case MMC_TIMING_UHS_DDR50: timing = GB_SDIO_TIMING_UHS_DDR50; break; -#ifdef MMC_DDR52_DEFINED case MMC_TIMING_MMC_DDR52: timing = GB_SDIO_TIMING_MMC_DDR52; break; -#endif case MMC_TIMING_MMC_HS200: timing = GB_SDIO_TIMING_MMC_HS200; break; -#ifdef MMC_HS400_SUPPORTED case MMC_TIMING_MMC_HS400: timing = GB_SDIO_TIMING_MMC_HS400; break; -#endif } request.timing = timing; -- cgit v0.10.2 From 722a133a6a6687bba21cfdf33bde5767109d0dea Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva <rui.silva@linaro.org> Date: Thu, 8 Sep 2016 17:17:50 +0100 Subject: staging: greybus: power_supply: remove KERNEL_VERSION checks No need to support older kernel versions in the Greybus Power Supply driver, so remove the checks as needed, we can now rely on all of the correct Power Supply core apis being present. Also move some properties definitions to the power supply greybus code. Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h index 1d93fb0..cfd7bc7 100644 --- a/drivers/staging/greybus/kernel_ver.h +++ b/drivers/staging/greybus/kernel_ver.h @@ -17,32 +17,6 @@ #include <linux/kernel.h> #include <linux/version.h> -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) -/* Commit: 297d716 power_supply: Change ownership from driver to core */ -#define CORE_OWNS_PSY_STRUCT -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) -/* - * Power supply get by name need to drop reference after call - */ -#define PSY_HAVE_PUT -#endif - -/* - * General power supply properties that could be absent from various reasons, - * like kernel versions or vendor specific versions - */ -#ifndef POWER_SUPPLY_PROP_VOLTAGE_BOOT - #define POWER_SUPPLY_PROP_VOLTAGE_BOOT -1 -#endif -#ifndef POWER_SUPPLY_PROP_CURRENT_BOOT - #define POWER_SUPPLY_PROP_CURRENT_BOOT -1 -#endif -#ifndef POWER_SUPPLY_PROP_CALIBRATE - #define POWER_SUPPLY_PROP_CALIBRATE -1 -#endif - #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) /* * After commit b2b49ccbdd54 (PM: Kconfig: Set PM_RUNTIME if PM_SLEEP is diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c index 68dd3d2..e85c988 100644 --- a/drivers/staging/greybus/power_supply.c +++ b/drivers/staging/greybus/power_supply.c @@ -27,14 +27,8 @@ struct gb_power_supply_prop { struct gb_power_supply { u8 id; bool registered; -#ifndef CORE_OWNS_PSY_STRUCT - struct power_supply psy; -#define to_gb_power_supply(x) container_of(x, struct gb_power_supply, psy) -#else struct power_supply *psy; struct power_supply_desc desc; -#define to_gb_power_supply(x) power_supply_get_drvdata(x) -#endif char name[64]; struct gb_power_supplies *supplies; struct delayed_work work; @@ -61,6 +55,22 @@ struct gb_power_supplies { struct mutex supplies_lock; }; +#define to_gb_power_supply(x) power_supply_get_drvdata(x) + +/* + * General power supply properties that could be absent from various reasons, + * like kernel versions or vendor specific versions + */ +#ifndef POWER_SUPPLY_PROP_VOLTAGE_BOOT + #define POWER_SUPPLY_PROP_VOLTAGE_BOOT -1 +#endif +#ifndef POWER_SUPPLY_PROP_CURRENT_BOOT + #define POWER_SUPPLY_PROP_CURRENT_BOOT -1 +#endif +#ifndef POWER_SUPPLY_PROP_CALIBRATE + #define POWER_SUPPLY_PROP_CALIBRATE -1 +#endif + /* cache time in milliseconds, if cache_time is set to 0 cache is disable */ static unsigned int cache_time = 1000; /* @@ -342,17 +352,10 @@ static void next_interval(struct gb_power_supply *gbpsy) gbpsy->update_interval = update_interval_max; } -#ifndef CORE_OWNS_PSY_STRUCT -static void __gb_power_supply_changed(struct gb_power_supply *gbpsy) -{ - power_supply_changed(&gbpsy->psy); -} -#else static void __gb_power_supply_changed(struct gb_power_supply *gbpsy) { power_supply_changed(gbpsy->psy); } -#endif static void gb_power_supply_state_change(struct gb_power_supply *gbpsy, struct gb_power_supply_prop *prop) @@ -451,9 +454,8 @@ static int __gb_power_supply_set_name(char *init_name, char *name, size_t len) strlcpy(name, init_name, len); while ((ret < len) && (psy = power_supply_get_by_name(name))) { -#ifdef PSY_HAVE_PUT power_supply_put(psy); -#endif + ret = snprintf(name, len, "%s_%u", init_name, ++i); } if (ret >= len) @@ -814,23 +816,6 @@ static int property_is_writeable(struct power_supply *b, return is_psy_prop_writeable(gbpsy, psp); } -#ifndef CORE_OWNS_PSY_STRUCT -static int gb_power_supply_register(struct gb_power_supply *gbpsy) -{ - struct gb_connection *connection = get_conn_from_psy(gbpsy); - - gbpsy->psy.name = gbpsy->name; - gbpsy->psy.type = gbpsy->type; - gbpsy->psy.properties = gbpsy->props_raw; - gbpsy->psy.num_properties = total_props(gbpsy); - gbpsy->psy.get_property = get_property; - gbpsy->psy.set_property = set_property; - gbpsy->psy.property_is_writeable = property_is_writeable; - - return power_supply_register(&connection->bundle->dev, - &gbpsy->psy); -} -#else static int gb_power_supply_register(struct gb_power_supply *gbpsy) { struct gb_connection *connection = get_conn_from_psy(gbpsy); @@ -850,7 +835,6 @@ static int gb_power_supply_register(struct gb_power_supply *gbpsy) &gbpsy->desc, &cfg); return PTR_ERR_OR_ZERO(gbpsy->psy); } -#endif static void _gb_power_supply_free(struct gb_power_supply *gbpsy) { @@ -866,13 +850,9 @@ static void _gb_power_supply_release(struct gb_power_supply *gbpsy) gbpsy->update_interval = 0; cancel_delayed_work_sync(&gbpsy->work); -#ifndef CORE_OWNS_PSY_STRUCT - if (gbpsy->registered) - power_supply_unregister(&gbpsy->psy); -#else + if (gbpsy->registered) power_supply_unregister(gbpsy->psy); -#endif _gb_power_supply_free(gbpsy); } -- cgit v0.10.2 From b04f56c6e7ccdc7d09ccd20f28bb4d34a1603ebb Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva <rui.silva@linaro.org> Date: Thu, 8 Sep 2016 17:17:51 +0100 Subject: staging: greybus: makefile: fix dependency of spi to spilib Greybus SPI driver depends on gb-spilib and we need to state that at makefile to make it link correctly. Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 0cc769e..f337b7b 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -85,7 +85,7 @@ obj-$(CONFIG_GREYBUS_GPIO) += gb-gpio.o obj-$(CONFIG_GREYBUS_I2C) += gb-i2c.o obj-$(CONFIG_GREYBUS_PWM) += gb-pwm.o obj-$(CONFIG_GREYBUS_SDIO) += gb-sdio.o -obj-$(CONFIG_GREYBUS_SPI) += gb-spi.o +obj-$(CONFIG_GREYBUS_SPI) += gb-spi.o gb-spilib.o obj-$(CONFIG_GREYBUS_UART) += gb-uart.o obj-$(CONFIG_GREYBUS_USB) += gb-usb.o -- cgit v0.10.2 From a0cf5951def318f40eec031c0898ad0140663824 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva <rui.silva@linaro.org> Date: Thu, 8 Sep 2016 17:17:52 +0100 Subject: staging: greybus: Kconfig: enable possibility to select light driver Remove BROKEN keyword to allow the light driver to be select now that we fixed the kernel version dependencies. Also fix the module name in the help section. Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/Kconfig b/drivers/staging/greybus/Kconfig index ede9184..89c4976 100644 --- a/drivers/staging/greybus/Kconfig +++ b/drivers/staging/greybus/Kconfig @@ -78,13 +78,13 @@ config GREYBUS_HID config GREYBUS_LIGHT tristate "Greybus LED Class driver" - depends on LEDS_CLASS && BROKEN + depends on LEDS_CLASS ---help--- Select this option if you have a device that follows the Greybus LED Class specification. To compile this code as a module, chose M here: the module - will be called gb-led.ko + will be called gb-light.ko config GREYBUS_LOG tristate "Greybus Debug Log Class driver" -- cgit v0.10.2 From 948c6227e76ef2443b327a409dc8eced92b32bda Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@google.com> Date: Fri, 9 Sep 2016 09:47:01 +0200 Subject: staging: greybus: remove CONFIG_PM_RUNTIME from kernel_ver.h The last thing remaining in kernel_ver.h was the setting of CONFIG_PM_RUNTIME, which isn't needed in a in-tree implementation. So remove the setting of this value, and the .h file entirely as that was the last thing left in it. Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> diff --git a/drivers/staging/greybus/audio_module.c b/drivers/staging/greybus/audio_module.c index 411735d..ae1c0fa 100644 --- a/drivers/staging/greybus/audio_module.c +++ b/drivers/staging/greybus/audio_module.c @@ -421,7 +421,7 @@ static const struct greybus_bundle_id gb_audio_id_table[] = { }; MODULE_DEVICE_TABLE(greybus, gb_audio_id_table); -#ifdef CONFIG_PM_RUNTIME +#ifdef CONFIG_PM static int gb_audio_suspend(struct device *dev) { struct gb_bundle *bundle = to_gb_bundle(dev); diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 5bd7731..d2ef57d 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -89,8 +89,7 @@ static void gb_bundle_release(struct device *dev) kfree(bundle); } -#ifdef CONFIG_PM_RUNTIME - +#ifdef CONFIG_PM static void gb_bundle_disable_all_connections(struct gb_bundle *bundle) { struct gb_connection *connection; diff --git a/drivers/staging/greybus/bundle.h b/drivers/staging/greybus/bundle.h index 349845e..0c3491d 100644 --- a/drivers/staging/greybus/bundle.h +++ b/drivers/staging/greybus/bundle.h @@ -41,7 +41,7 @@ int gb_bundle_add(struct gb_bundle *bundle); void gb_bundle_destroy(struct gb_bundle *bundle); /* Bundle Runtime PM wrappers */ -#ifdef CONFIG_PM_RUNTIME +#ifdef CONFIG_PM static inline int gb_pm_runtime_get_sync(struct gb_bundle *bundle) { int retval; diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index e1f3046..46d2e8a 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -1344,7 +1344,7 @@ static const struct greybus_bundle_id gb_camera_id_table[] = { { }, }; -#ifdef CONFIG_PM_RUNTIME +#ifdef CONFIG_PM static int gb_camera_suspend(struct device *dev) { struct gb_bundle *bundle = to_gb_bundle(dev); diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 6cb13fc..071bb1c 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -17,7 +17,6 @@ #include "arpc.h" #include "greybus.h" #include "greybus_trace.h" -#include "kernel_ver.h" #include "connection.h" diff --git a/drivers/staging/greybus/gbphy.c b/drivers/staging/greybus/gbphy.c index 478c162..bcde7c9 100644 --- a/drivers/staging/greybus/gbphy.c +++ b/drivers/staging/greybus/gbphy.c @@ -52,7 +52,7 @@ static void gbphy_dev_release(struct device *dev) kfree(gbphy_dev); } -#ifdef CONFIG_PM_RUNTIME +#ifdef CONFIG_PM static int gb_gbphy_idle(struct device *dev) { pm_runtime_mark_last_busy(dev); diff --git a/drivers/staging/greybus/gbphy.h b/drivers/staging/greybus/gbphy.h index e251186..8ee6805 100644 --- a/drivers/staging/greybus/gbphy.h +++ b/drivers/staging/greybus/gbphy.h @@ -66,7 +66,7 @@ void gb_gbphy_deregister_driver(struct gbphy_driver *driver); #define module_gbphy_driver(__gbphy_driver) \ module_driver(__gbphy_driver, gb_gbphy_register, gb_gbphy_deregister) -#ifdef CONFIG_PM_RUNTIME +#ifdef CONFIG_PM static inline int gbphy_runtime_get_sync(struct gbphy_device *gbphy_dev) { struct device *dev = &gbphy_dev->dev; diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 3e32028..1252688 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -21,7 +21,6 @@ #include <linux/pm_runtime.h> #include <linux/idr.h> -#include "kernel_ver.h" #include "greybus_id.h" #include "greybus_manifest.h" #include "greybus_protocols.h" diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index c3ed3d7..546b090 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -698,7 +698,7 @@ static void gb_interface_release(struct device *dev) kfree(intf); } -#ifdef CONFIG_PM_RUNTIME +#ifdef CONFIG_PM static int gb_interface_suspend(struct device *dev) { struct gb_interface *intf = to_gb_interface(dev); diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h deleted file mode 100644 index cfd7bc7..0000000 --- a/drivers/staging/greybus/kernel_ver.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Greybus kernel "version" glue logic. - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - * - * Released under the GPLv2 only. - * - * Backports of newer kernel apis to allow the code to build properly on older - * kernel versions. Remove this file when merging to upstream, it should not be - * needed at all - */ - -#ifndef __GREYBUS_KERNEL_VER_H -#define __GREYBUS_KERNEL_VER_H - -#include <linux/kernel.h> -#include <linux/version.h> - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) -/* - * After commit b2b49ccbdd54 (PM: Kconfig: Set PM_RUNTIME if PM_SLEEP is - * selected) PM_RUNTIME is always set if PM is set, so files that are build - * conditionally if CONFIG_PM_RUNTIME is set may now be build if CONFIG_PM is - * set. - */ - -#ifdef CONFIG_PM -#define CONFIG_PM_RUNTIME -#endif /* CONFIG_PM */ -#endif - -#endif /* __GREYBUS_KERNEL_VER_H */ -- cgit v0.10.2 From 629c1fb53717436ea0575daa1ae889e06bb13f71 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Date: Mon, 19 Sep 2016 18:23:19 +0200 Subject: staging: greybus: add some MAINTAINERS Johan and Alex and I are going to maintain the greybus code, so add it to MAINTAINERS so we get cc:ed on patches. Acked-by: Johan Hovold <johan@kernel.org> Acked-by: Alex Elder <elder@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/MAINTAINERS b/MAINTAINERS index 6781a3f..d369b0a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5283,6 +5283,13 @@ L: netdev@vger.kernel.org S: Maintained F: drivers/net/ethernet/aeroflex/ +GREYBUS SUBSYSTEM +M: Johan Hovold <johan@kernel.org> +M: Alex Elder <elder@kernel.org> +M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +S: Maintained +F: drivers/staging/greybus/ + GSPCA FINEPIX SUBDRIVER M: Frank Zago <frank@zago.net> L: linux-media@vger.kernel.org -- cgit v0.10.2 From 2bbadafbe4eacab57aa7bc8e50287c1366303807 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva <rmfrfs@gmail.com> Date: Mon, 19 Sep 2016 17:07:59 +0100 Subject: staging: greybus: MAINTAINERS: add greybus protocol drivers maintainers Add me to some Greybus protocol drivers maintainers, spi, sdio, power supply, light and gpio. Signed-off-by: Rui Miguel Silva <rmfrfs@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/MAINTAINERS b/MAINTAINERS index d369b0a..fb55334 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5290,6 +5290,16 @@ M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> S: Maintained F: drivers/staging/greybus/ +GREYBUS PROTOCOLS DRIVERS +M: Rui Miguel Silva <rmfrfs@gmail.com> +S: Maintained +F: drivers/staging/greybus/sdio.c +F: drivers/staging/greybus/light.c +F: drivers/staging/greybus/gpio.c +F: drivers/staging/greybus/power_supply.c +F: drivers/staging/greybus/spi.c +F: drivers/staging/greybus/spilib.c + GSPCA FINEPIX SUBDRIVER M: Frank Zago <frank@zago.net> L: linux-media@vger.kernel.org -- cgit v0.10.2 From 27e6245e35bc6c20c2933d7d8afa562623be1ef5 Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Mon, 19 Sep 2016 17:40:22 +0200 Subject: staging: most: hdm-usb: remove proprietary urb anchoring This patch removes the propietary tracking of URBs. Instead the structure usb_anchor of the USB subsystem is used. Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index 5b27e96..58f65a4 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -65,17 +65,6 @@ #define DRCI_WRITE_REQ 0xA1 /** - * struct buf_anchor - used to create a list of pending URBs - * @urb: pointer to USB request block - * @list: linked list - * @urb_completion: - */ -struct buf_anchor { - struct urb *urb; - struct list_head list; -}; - -/** * struct most_dci_obj - Direct Communication Interface * @kobj:position in sysfs * @usb_device: pointer to the usb device @@ -116,7 +105,7 @@ struct clear_hold_work { * @anchor_list_lock: locks list access * @padding_active: indicates channel uses padding * @is_channel_healthy: health status table of each channel - * @anchor_list: list of anchored items + * @busy_urbs: list of anchored items * @io_mutex: synchronize I/O with disconnect * @link_stat_timer: timer for link status reports * @poll_work_obj: work for polling link status @@ -137,7 +126,7 @@ struct most_dev { bool padding_active[MAX_NUM_ENDPOINTS]; bool is_channel_healthy[MAX_NUM_ENDPOINTS]; struct clear_hold_work clear_work[MAX_NUM_ENDPOINTS]; - struct list_head *anchor_list; + struct usb_anchor *busy_urbs; struct mutex io_mutex; struct timer_list link_stat_timer; struct work_struct poll_work_obj; @@ -207,29 +196,22 @@ static void free_anchored_buffers(struct most_dev *mdev, unsigned int channel, enum mbo_status_flags status) { struct mbo *mbo; - struct buf_anchor *anchor, *tmp; + struct urb *urb; spinlock_t *lock = mdev->anchor_list_lock + channel; /* temp. lock */ unsigned long flags; spin_lock_irqsave(lock, flags); - list_for_each_entry_safe(anchor, tmp, &mdev->anchor_list[channel], - list) { - struct urb *urb = anchor->urb; - + while ((urb = usb_get_from_anchor(&mdev->busy_urbs[channel]))) { spin_unlock_irqrestore(lock, flags); - if (likely(urb)) { - mbo = urb->context; - usb_kill_urb(urb); - if (mbo && mbo->complete) { - mbo->status = status; - mbo->processed_length = 0; - mbo->complete(mbo); - } - usb_free_urb(urb); + mbo = urb->context; + usb_kill_urb(urb); + if (mbo && mbo->complete) { + mbo->status = status; + mbo->processed_length = 0; + mbo->complete(mbo); } + usb_free_urb(urb); spin_lock_irqsave(lock, flags); - list_del(&anchor->list); - kfree(anchor); } spin_unlock_irqrestore(lock, flags); } @@ -394,7 +376,6 @@ static int hdm_remove_padding(struct most_dev *mdev, int channel, static void hdm_write_completion(struct urb *urb) { struct mbo *mbo = urb->context; - struct buf_anchor *anchor = mbo->priv; struct most_dev *mdev = to_mdev(mbo->ifp); unsigned int channel = mbo->hdm_channel_id; struct device *dev = &mdev->usb_device->dev; @@ -426,14 +407,13 @@ static void hdm_write_completion(struct urb *urb) mbo->status = MBO_E_INVAL; break; } + usb_unanchor_urb(urb); } else { mbo->status = MBO_SUCCESS; mbo->processed_length = urb->actual_length; } - list_del(&anchor->list); spin_unlock_irqrestore(lock, flags); - kfree(anchor); if (likely(mbo->complete)) mbo->complete(mbo); @@ -551,7 +531,6 @@ static void hdm_write_completion(struct urb *urb) static void hdm_read_completion(struct urb *urb) { struct mbo *mbo = urb->context; - struct buf_anchor *anchor = mbo->priv; struct most_dev *mdev = to_mdev(mbo->ifp); unsigned int channel = mbo->hdm_channel_id; struct device *dev = &mdev->usb_device->dev; @@ -585,6 +564,7 @@ static void hdm_read_completion(struct urb *urb) mbo->status = MBO_E_INVAL; break; } + usb_unanchor_urb(urb); } else { mbo->processed_length = urb->actual_length; mbo->status = MBO_SUCCESS; @@ -595,9 +575,7 @@ static void hdm_read_completion(struct urb *urb) } } - list_del(&anchor->list); spin_unlock_irqrestore(lock, flags); - kfree(anchor); if (likely(mbo->complete)) mbo->complete(mbo); @@ -623,7 +601,6 @@ static int hdm_enqueue(struct most_interface *iface, int channel, struct mbo *mbo) { struct most_dev *mdev; - struct buf_anchor *anchor; struct most_channel_config *conf; struct device *dev; int retval = 0; @@ -649,15 +626,6 @@ static int hdm_enqueue(struct most_interface *iface, int channel, if (!urb) return -ENOMEM; - anchor = kzalloc(sizeof(*anchor), GFP_ATOMIC); - if (!anchor) { - retval = -ENOMEM; - goto _error; - } - - anchor->urb = urb; - mbo->priv = anchor; - if ((conf->direction & MOST_CH_TX) && mdev->padding_active[channel] && hdm_add_padding(mdev, channel, mbo)) { retval = -EIO; @@ -691,7 +659,7 @@ static int hdm_enqueue(struct most_interface *iface, int channel, lock = mdev->anchor_list_lock + channel; spin_lock_irqsave(lock, flags); - list_add_tail(&anchor->list, &mdev->anchor_list[channel]); + usb_anchor_urb(urb, &mdev->busy_urbs[channel]); spin_unlock_irqrestore(lock, flags); retval = usb_submit_urb(urb, GFP_KERNEL); @@ -703,9 +671,8 @@ static int hdm_enqueue(struct most_interface *iface, int channel, _error_1: spin_lock_irqsave(lock, flags); - list_del(&anchor->list); + usb_unanchor_urb(urb); spin_unlock_irqrestore(lock, flags); - kfree(anchor); _error: usb_free_urb(urb); return retval; @@ -1281,9 +1248,9 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) if (!mdev->ep_address) goto exit_free2; - mdev->anchor_list = - kcalloc(num_endpoints, sizeof(*mdev->anchor_list), GFP_KERNEL); - if (!mdev->anchor_list) + mdev->busy_urbs = + kcalloc(num_endpoints, sizeof(*mdev->busy_urbs), GFP_KERNEL); + if (!mdev->busy_urbs) goto exit_free3; tmp_cap = mdev->cap; @@ -1308,7 +1275,7 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) else tmp_cap->direction = MOST_CH_TX; tmp_cap++; - INIT_LIST_HEAD(&mdev->anchor_list[i]); + init_usb_anchor(&mdev->busy_urbs[i]); spin_lock_init(&mdev->anchor_list_lock[i]); err = drci_wr_reg(usb_dev, DRCI_REG_BASE + DRCI_COMMAND + @@ -1358,7 +1325,7 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) return 0; exit_free4: - kfree(mdev->anchor_list); + kfree(mdev->busy_urbs); exit_free3: kfree(mdev->ep_address); exit_free2: @@ -1399,7 +1366,7 @@ static void hdm_disconnect(struct usb_interface *interface) destroy_most_dci_obj(mdev->dci); most_deregister_interface(&mdev->iface); - kfree(mdev->anchor_list); + kfree(mdev->busy_urbs); kfree(mdev->cap); kfree(mdev->conf); kfree(mdev->ep_address); -- cgit v0.10.2 From d223b37c9f44273c0cca5138118d6c75e5110bfa Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Mon, 19 Sep 2016 17:40:23 +0200 Subject: staging: most: hdm-usb: remove redundant spinlocks This patch removes the spinlocks when accessing the usb_anchor list, because the struct usb_anchor is using its own lock. Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index 58f65a4..f872ce9 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -197,12 +197,8 @@ static void free_anchored_buffers(struct most_dev *mdev, unsigned int channel, { struct mbo *mbo; struct urb *urb; - spinlock_t *lock = mdev->anchor_list_lock + channel; /* temp. lock */ - unsigned long flags; - spin_lock_irqsave(lock, flags); while ((urb = usb_get_from_anchor(&mdev->busy_urbs[channel]))) { - spin_unlock_irqrestore(lock, flags); mbo = urb->context; usb_kill_urb(urb); if (mbo && mbo->complete) { @@ -211,9 +207,7 @@ static void free_anchored_buffers(struct most_dev *mdev, unsigned int channel, mbo->complete(mbo); } usb_free_urb(urb); - spin_lock_irqsave(lock, flags); } - spin_unlock_irqrestore(lock, flags); } /** @@ -605,10 +599,8 @@ static int hdm_enqueue(struct most_interface *iface, int channel, struct device *dev; int retval = 0; struct urb *urb; - unsigned long flags; unsigned long length; void *virt_address; - spinlock_t *lock; /* temp. lock */ if (unlikely(!iface || !mbo)) return -EIO; @@ -657,10 +649,7 @@ static int hdm_enqueue(struct most_interface *iface, int channel, } urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - lock = mdev->anchor_list_lock + channel; - spin_lock_irqsave(lock, flags); usb_anchor_urb(urb, &mdev->busy_urbs[channel]); - spin_unlock_irqrestore(lock, flags); retval = usb_submit_urb(urb, GFP_KERNEL); if (retval) { @@ -670,9 +659,7 @@ static int hdm_enqueue(struct most_interface *iface, int channel, return 0; _error_1: - spin_lock_irqsave(lock, flags); usb_unanchor_urb(urb); - spin_unlock_irqrestore(lock, flags); _error: usb_free_urb(urb); return retval; -- cgit v0.10.2 From 3fbcb92b74581eaec224efe6972aab7359a5230b Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Mon, 19 Sep 2016 17:40:24 +0200 Subject: staging: most: hdm-usb: remove calls to usb_unachor_urb This patch removes the calls to usb_unanchor_urb() from the completion routines, since disassociation of the URBs is already handles by the USB subsystem. Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index f872ce9..9474b43 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -401,7 +401,6 @@ static void hdm_write_completion(struct urb *urb) mbo->status = MBO_E_INVAL; break; } - usb_unanchor_urb(urb); } else { mbo->status = MBO_SUCCESS; mbo->processed_length = urb->actual_length; @@ -558,7 +557,6 @@ static void hdm_read_completion(struct urb *urb) mbo->status = MBO_E_INVAL; break; } - usb_unanchor_urb(urb); } else { mbo->processed_length = urb->actual_length; mbo->status = MBO_SUCCESS; -- cgit v0.10.2 From 88d1878bcaa438297e3e5bb7376a6d8f5f5c38e5 Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Mon, 19 Sep 2016 17:40:25 +0200 Subject: staging: most: hdm-usb: rename channel related spinlock To increase comprehension this patch renames the channel related spinlock with a more fitting name. Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index 9474b43..9deb28c 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -102,7 +102,7 @@ struct clear_hold_work { * @link_stat: link status of hardware * @description: device description * @suffix: suffix for channel name - * @anchor_list_lock: locks list access + * @channel_lock: synchronize channel access * @padding_active: indicates channel uses padding * @is_channel_healthy: health status table of each channel * @busy_urbs: list of anchored items @@ -122,7 +122,7 @@ struct most_dev { u16 link_stat; char description[MAX_STRING_LEN]; char suffix[MAX_NUM_ENDPOINTS][MAX_SUFFIX_LEN]; - spinlock_t anchor_list_lock[MAX_NUM_ENDPOINTS]; + spinlock_t channel_lock[MAX_NUM_ENDPOINTS]; /* sync channel access */ bool padding_active[MAX_NUM_ENDPOINTS]; bool is_channel_healthy[MAX_NUM_ENDPOINTS]; struct clear_hold_work clear_work[MAX_NUM_ENDPOINTS]; @@ -270,7 +270,7 @@ static int hdm_poison_channel(struct most_interface *iface, int channel) return -ECHRNG; } - lock = mdev->anchor_list_lock + channel; + lock = mdev->channel_lock + channel; spin_lock_irqsave(lock, flags); mdev->is_channel_healthy[channel] = false; spin_unlock_irqrestore(lock, flags); @@ -373,7 +373,7 @@ static void hdm_write_completion(struct urb *urb) struct most_dev *mdev = to_mdev(mbo->ifp); unsigned int channel = mbo->hdm_channel_id; struct device *dev = &mdev->usb_device->dev; - spinlock_t *lock = mdev->anchor_list_lock + channel; /* temp. lock */ + spinlock_t *lock = mdev->channel_lock + channel; unsigned long flags; spin_lock_irqsave(lock, flags); @@ -527,7 +527,7 @@ static void hdm_read_completion(struct urb *urb) struct most_dev *mdev = to_mdev(mbo->ifp); unsigned int channel = mbo->hdm_channel_id; struct device *dev = &mdev->usb_device->dev; - spinlock_t *lock = mdev->anchor_list_lock + channel; /* temp. lock */ + spinlock_t *lock = mdev->channel_lock + channel; unsigned long flags; spin_lock_irqsave(lock, flags); @@ -1261,7 +1261,7 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) tmp_cap->direction = MOST_CH_TX; tmp_cap++; init_usb_anchor(&mdev->busy_urbs[i]); - spin_lock_init(&mdev->anchor_list_lock[i]); + spin_lock_init(&mdev->channel_lock[i]); err = drci_wr_reg(usb_dev, DRCI_REG_BASE + DRCI_COMMAND + ep_desc->bEndpointAddress * 16, -- cgit v0.10.2 From 7d7005180a7eab473bca4c1fe807f0589561791e Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <pure.logic@nexus-software.ie> Date: Mon, 19 Sep 2016 18:41:46 +0100 Subject: staging: greybus: MAINTAINERS: add greybus protocol drivers maintainers Add bod to some Greybus protocol drivers maintainers, loopback and timesync. Signed-off-by: Bryan O'Donoghue <pure.logic@nexus-software.ie> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/MAINTAINERS b/MAINTAINERS index 24b07f7..ddd382d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5307,6 +5307,13 @@ F: drivers/staging/greybus/power_supply.c F: drivers/staging/greybus/spi.c F: drivers/staging/greybus/spilib.c +GREYBUS PROTOCOLS DRIVERS +M: Bryan O'Donoghue <pure.logic@nexus-software.ie> +S: Maintained +F: drivers/staging/greybus/loopback.c +F: drivers/staging/greybus/timesync.c +F: drivers/staging/greybus/timesync_platform.c + GSPCA FINEPIX SUBDRIVER M: Frank Zago <frank@zago.net> L: linux-media@vger.kernel.org -- cgit v0.10.2 From 83a75e3f14667b334ecd53b6334407ace8679eed Mon Sep 17 00:00:00 2001 From: Sandhya Bankar <bankarsandhya512@gmail.com> Date: Sun, 18 Sep 2016 05:23:49 +0530 Subject: Staging: lustre: Convert array index from the loop bound to the loop index. Convert array index from the loop bound to the loop index. The structure cl_env_percpu[NR_CPUS] has been initializing for each possible cpu (i.e 0 to i). During initialization if any error will occurred, the error handling code should uninitialize cl_env_percpu upto i. But currently unitialization is repeatedly done for the same cl_env_percpu[i] element. This does not seems to be correct. Used below semantic patch to identify this issue: @@ expression e1,e2,ar; @@ for(e1 = 0; e1 < e2; e1++) { <... ar[ - e2 + e1 ] ...> } Signed-off-by: Sandhya Bankar <bankarsandhya512@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/obdclass/cl_object.c b/drivers/staging/lustre/lustre/obdclass/cl_object.c index e493c80..3199dd4 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_object.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_object.c @@ -1022,7 +1022,7 @@ static int cl_env_percpu_init(void) * thus we must uninitialize up to i, the rest are undefined. */ for (j = 0; j < i; j++) { - cle = &cl_env_percpu[i]; + cle = &cl_env_percpu[j]; lu_context_exit(&cle->ce_ses); lu_context_fini(&cle->ce_ses); lu_env_fini(&cle->ce_lu); -- cgit v0.10.2 From 024931694730a2ad31bc1e7c58a028abe441180b Mon Sep 17 00:00:00 2001 From: Sandhya Bankar <bankarsandhya512@gmail.com> Date: Mon, 19 Sep 2016 23:59:36 +0530 Subject: Staging: lustre: lmv_obd: Remove redundant test. filp != NULL is already checked, so no need to check it again. Signed-off-by: Sandhya Bankar <bankarsandhya512@gmail.com> Reviewed-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index dad572eb..7dbb2b9 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -865,7 +865,7 @@ static int lmv_hsm_ct_register(struct lmv_obd *lmv, unsigned int cmd, int len, rc = libcfs_kkuc_group_add(filp, lk->lk_uid, lk->lk_group, &kcd, sizeof(kcd)); - if (rc && filp) + if (rc) fput(filp); return rc; -- cgit v0.10.2 From a2921e2fc026718a6b2694c0f61cb0d58f7f4c77 Mon Sep 17 00:00:00 2001 From: Nayeemahmed Badebade <itachi.opsrc@gmail.com> Date: Mon, 19 Sep 2016 02:48:19 +0530 Subject: staging: lustre: lustre/ldlm: Fixed sparse warnings Added __acquires / __releases sparse locking annotations to lock_res_and_lock() and unlock_res_and_lock() functions in l_lock.c, to fix below sparse warnings: l_lock.c:47:22: warning: context imbalance in 'lock_res_and_lock' - wrong count at exit l_lock.c:61:6: warning: context imbalance in 'unlock_res_and_lock' - unexpected unlock Signed-off-by: Nayeemahmed Badebade <itachi.opsrc@gmail.com> Reviewed-by: James Simmons <jsimmons@infradead.org> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/ldlm/l_lock.c b/drivers/staging/lustre/lustre/ldlm/l_lock.c index ea8840c..3845f38 100644 --- a/drivers/staging/lustre/lustre/ldlm/l_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/l_lock.c @@ -45,6 +45,8 @@ * being an atomic operation. */ struct ldlm_resource *lock_res_and_lock(struct ldlm_lock *lock) + __acquires(&lock->l_lock) + __acquires(&lock->l_resource->lr_lock) { spin_lock(&lock->l_lock); @@ -59,6 +61,8 @@ EXPORT_SYMBOL(lock_res_and_lock); * Unlock a lock and its resource previously locked with lock_res_and_lock */ void unlock_res_and_lock(struct ldlm_lock *lock) + __releases(&lock->l_resource->lr_lock) + __releases(&lock->l_lock) { /* on server-side resource of lock doesn't change */ ldlm_clear_res_locked(lock); -- cgit v0.10.2 From 19c5a689cc3df512a817b7eb717bad24bb5bd7e8 Mon Sep 17 00:00:00 2001 From: Anchal Jain <anchalj109@gmail.com> Date: Sun, 18 Sep 2016 21:24:12 +0530 Subject: staging: lustre: lnet: klnds: socklnd: Remove unnecessary line continuations Fixes checkpatch warning: WARNING: Avoid unnecessary line continuations Signed-off-by: Anchal Jain <anchalj109@gmail.com> Acked-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c index 1bdf962..c1c6f60 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c @@ -35,8 +35,8 @@ ksocknal_alloc_tx(int type, int size) spin_lock(&ksocknal_data.ksnd_tx_lock); if (!list_empty(&ksocknal_data.ksnd_idle_noop_txs)) { - tx = list_entry(ksocknal_data.ksnd_idle_noop_txs. \ - next, struct ksock_tx, tx_list); + tx = list_entry(ksocknal_data.ksnd_idle_noop_txs.next, + struct ksock_tx, tx_list); LASSERT(tx->tx_desc_size == size); list_del(&tx->tx_list); } -- cgit v0.10.2 From 31959392c7db09c13af07dcdc409d306aaa03d4f Mon Sep 17 00:00:00 2001 From: Chaehyun Lim <chaehyun.lim@gmail.com> Date: Tue, 20 Sep 2016 09:47:29 +0900 Subject: staging: greybus: use preferred kernel type u8 As suggested by checkpatch.pl: CHECK: Prefer kernel type 'u8' over 'uint8_t' Signed-off-by: Chaehyun Lim <chaehyun.lim@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 2f70295..c9e1989 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -47,7 +47,7 @@ static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec, { int module_state, ret = 0; uint16_t data_cport, i2s_port, cportid; - uint8_t sig_bits, channels; + u8 sig_bits, channels; uint32_t format, rate; struct gbaudio_data_connection *data; struct gbaudio_stream_params *params; @@ -182,7 +182,7 @@ static int gbaudio_module_enable_rx(struct gbaudio_codec_info *codec, { int module_state, ret = 0; uint16_t data_cport, i2s_port, cportid; - uint8_t sig_bits, channels; + u8 sig_bits, channels; uint32_t format, rate; struct gbaudio_data_connection *data; struct gbaudio_stream_params *params; @@ -413,7 +413,7 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { int ret; - uint8_t sig_bits, channels; + u8 sig_bits, channels; uint32_t format, rate; struct gbaudio_module_info *module; struct gbaudio_data_connection *data; diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index 0a86459..fabaccc 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -98,7 +98,7 @@ enum gbaudio_codec_state { struct gbaudio_stream_params { int state; - uint8_t sig_bits, channels; + u8 sig_bits, channels; uint32_t format, rate; }; @@ -221,23 +221,23 @@ void gbaudio_unregister_module(struct gbaudio_module_info *module); extern int gb_audio_gb_get_topology(struct gb_connection *connection, struct gb_audio_topology **topology); extern int gb_audio_gb_get_control(struct gb_connection *connection, - uint8_t control_id, uint8_t index, + u8 control_id, u8 index, struct gb_audio_ctl_elem_value *value); extern int gb_audio_gb_set_control(struct gb_connection *connection, - uint8_t control_id, uint8_t index, + u8 control_id, u8 index, struct gb_audio_ctl_elem_value *value); extern int gb_audio_gb_enable_widget(struct gb_connection *connection, - uint8_t widget_id); + u8 widget_id); extern int gb_audio_gb_disable_widget(struct gb_connection *connection, - uint8_t widget_id); + u8 widget_id); extern int gb_audio_gb_get_pcm(struct gb_connection *connection, uint16_t data_cport, uint32_t *format, - uint32_t *rate, uint8_t *channels, - uint8_t *sig_bits); + uint32_t *rate, u8 *channels, + u8 *sig_bits); extern int gb_audio_gb_set_pcm(struct gb_connection *connection, uint16_t data_cport, uint32_t format, - uint32_t rate, uint8_t channels, - uint8_t sig_bits); + uint32_t rate, u8 channels, + u8 sig_bits); extern int gb_audio_gb_set_tx_data_size(struct gb_connection *connection, uint16_t data_cport, uint16_t size); extern int gb_audio_gb_activate_tx(struct gb_connection *connection, diff --git a/drivers/staging/greybus/audio_gb.c b/drivers/staging/greybus/audio_gb.c index a2f1c92..c386cd8 100644 --- a/drivers/staging/greybus/audio_gb.c +++ b/drivers/staging/greybus/audio_gb.c @@ -47,7 +47,7 @@ int gb_audio_gb_get_topology(struct gb_connection *connection, EXPORT_SYMBOL_GPL(gb_audio_gb_get_topology); int gb_audio_gb_get_control(struct gb_connection *connection, - uint8_t control_id, uint8_t index, + u8 control_id, u8 index, struct gb_audio_ctl_elem_value *value) { struct gb_audio_get_control_request req; @@ -69,7 +69,7 @@ int gb_audio_gb_get_control(struct gb_connection *connection, EXPORT_SYMBOL_GPL(gb_audio_gb_get_control); int gb_audio_gb_set_control(struct gb_connection *connection, - uint8_t control_id, uint8_t index, + u8 control_id, u8 index, struct gb_audio_ctl_elem_value *value) { struct gb_audio_set_control_request req; @@ -84,7 +84,7 @@ int gb_audio_gb_set_control(struct gb_connection *connection, EXPORT_SYMBOL_GPL(gb_audio_gb_set_control); int gb_audio_gb_enable_widget(struct gb_connection *connection, - uint8_t widget_id) + u8 widget_id) { struct gb_audio_enable_widget_request req; @@ -96,7 +96,7 @@ int gb_audio_gb_enable_widget(struct gb_connection *connection, EXPORT_SYMBOL_GPL(gb_audio_gb_enable_widget); int gb_audio_gb_disable_widget(struct gb_connection *connection, - uint8_t widget_id) + u8 widget_id) { struct gb_audio_disable_widget_request req; @@ -108,8 +108,8 @@ int gb_audio_gb_disable_widget(struct gb_connection *connection, EXPORT_SYMBOL_GPL(gb_audio_gb_disable_widget); int gb_audio_gb_get_pcm(struct gb_connection *connection, uint16_t data_cport, - uint32_t *format, uint32_t *rate, uint8_t *channels, - uint8_t *sig_bits) + uint32_t *format, uint32_t *rate, u8 *channels, + u8 *sig_bits) { struct gb_audio_get_pcm_request req; struct gb_audio_get_pcm_response resp; @@ -132,8 +132,8 @@ int gb_audio_gb_get_pcm(struct gb_connection *connection, uint16_t data_cport, EXPORT_SYMBOL_GPL(gb_audio_gb_get_pcm); int gb_audio_gb_set_pcm(struct gb_connection *connection, uint16_t data_cport, - uint32_t format, uint32_t rate, uint8_t channels, - uint8_t sig_bits) + uint32_t format, uint32_t rate, u8 channels, + u8 sig_bits) { struct gb_audio_set_pcm_request req; -- cgit v0.10.2 From 79cb2b26f54e8831342f3598393bb894e15c01f6 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim <chaehyun.lim@gmail.com> Date: Tue, 20 Sep 2016 09:47:30 +0900 Subject: staging: greybus: use preferred kernel type u16 As suggested by checkpatch.pl: CHECK: Prefer kernel type 'u16' over 'uint16_t' Signed-off-by: Chaehyun Lim <chaehyun.lim@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index c9e1989..5ce2542 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -46,7 +46,7 @@ static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec, struct gbaudio_module_info *module, int id) { int module_state, ret = 0; - uint16_t data_cport, i2s_port, cportid; + u16 data_cport, i2s_port, cportid; u8 sig_bits, channels; uint32_t format, rate; struct gbaudio_data_connection *data; @@ -131,7 +131,7 @@ static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec, static int gbaudio_module_disable_tx(struct gbaudio_module_info *module, int id) { int ret; - uint16_t data_cport, cportid, i2s_port; + u16 data_cport, cportid, i2s_port; int module_state; struct gbaudio_data_connection *data; @@ -181,7 +181,7 @@ static int gbaudio_module_enable_rx(struct gbaudio_codec_info *codec, struct gbaudio_module_info *module, int id) { int module_state, ret = 0; - uint16_t data_cport, i2s_port, cportid; + u16 data_cport, i2s_port, cportid; u8 sig_bits, channels; uint32_t format, rate; struct gbaudio_data_connection *data; @@ -266,7 +266,7 @@ static int gbaudio_module_enable_rx(struct gbaudio_codec_info *codec, static int gbaudio_module_disable_rx(struct gbaudio_module_info *module, int id) { int ret; - uint16_t data_cport, cportid, i2s_port; + u16 data_cport, cportid, i2s_port; int module_state; struct gbaudio_data_connection *data; @@ -855,7 +855,7 @@ EXPORT_SYMBOL(gbaudio_register_module); static void gbaudio_codec_clean_data_tx(struct gbaudio_data_connection *data) { - uint16_t i2s_port, cportid; + u16 i2s_port, cportid; int ret; if (list_is_singular(&gbcodec->module_list)) { @@ -877,7 +877,7 @@ static void gbaudio_codec_clean_data_tx(struct gbaudio_data_connection *data) static void gbaudio_codec_clean_data_rx(struct gbaudio_data_connection *data) { - uint16_t i2s_port, cportid; + u16 i2s_port, cportid; int ret; if (list_is_singular(&gbcodec->module_list)) { diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index fabaccc..ca027bd 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -231,25 +231,25 @@ extern int gb_audio_gb_enable_widget(struct gb_connection *connection, extern int gb_audio_gb_disable_widget(struct gb_connection *connection, u8 widget_id); extern int gb_audio_gb_get_pcm(struct gb_connection *connection, - uint16_t data_cport, uint32_t *format, + u16 data_cport, uint32_t *format, uint32_t *rate, u8 *channels, u8 *sig_bits); extern int gb_audio_gb_set_pcm(struct gb_connection *connection, - uint16_t data_cport, uint32_t format, + u16 data_cport, uint32_t format, uint32_t rate, u8 channels, u8 sig_bits); extern int gb_audio_gb_set_tx_data_size(struct gb_connection *connection, - uint16_t data_cport, uint16_t size); + u16 data_cport, u16 size); extern int gb_audio_gb_activate_tx(struct gb_connection *connection, - uint16_t data_cport); + u16 data_cport); extern int gb_audio_gb_deactivate_tx(struct gb_connection *connection, - uint16_t data_cport); + u16 data_cport); extern int gb_audio_gb_set_rx_data_size(struct gb_connection *connection, - uint16_t data_cport, uint16_t size); + u16 data_cport, u16 size); extern int gb_audio_gb_activate_rx(struct gb_connection *connection, - uint16_t data_cport); + u16 data_cport); extern int gb_audio_gb_deactivate_rx(struct gb_connection *connection, - uint16_t data_cport); + u16 data_cport); extern int gb_audio_apbridgea_set_config(struct gb_connection *connection, __u16 i2s_port, __u32 format, __u32 rate, __u32 mclk_freq); diff --git a/drivers/staging/greybus/audio_gb.c b/drivers/staging/greybus/audio_gb.c index c386cd8..42f287d 100644 --- a/drivers/staging/greybus/audio_gb.c +++ b/drivers/staging/greybus/audio_gb.c @@ -17,7 +17,7 @@ int gb_audio_gb_get_topology(struct gb_connection *connection, { struct gb_audio_get_topology_size_response size_resp; struct gb_audio_topology *topo; - uint16_t size; + u16 size; int ret; ret = gb_operation_sync(connection, GB_AUDIO_TYPE_GET_TOPOLOGY_SIZE, @@ -107,7 +107,7 @@ int gb_audio_gb_disable_widget(struct gb_connection *connection, } EXPORT_SYMBOL_GPL(gb_audio_gb_disable_widget); -int gb_audio_gb_get_pcm(struct gb_connection *connection, uint16_t data_cport, +int gb_audio_gb_get_pcm(struct gb_connection *connection, u16 data_cport, uint32_t *format, uint32_t *rate, u8 *channels, u8 *sig_bits) { @@ -131,7 +131,7 @@ int gb_audio_gb_get_pcm(struct gb_connection *connection, uint16_t data_cport, } EXPORT_SYMBOL_GPL(gb_audio_gb_get_pcm); -int gb_audio_gb_set_pcm(struct gb_connection *connection, uint16_t data_cport, +int gb_audio_gb_set_pcm(struct gb_connection *connection, u16 data_cport, uint32_t format, uint32_t rate, u8 channels, u8 sig_bits) { @@ -149,7 +149,7 @@ int gb_audio_gb_set_pcm(struct gb_connection *connection, uint16_t data_cport, EXPORT_SYMBOL_GPL(gb_audio_gb_set_pcm); int gb_audio_gb_set_tx_data_size(struct gb_connection *connection, - uint16_t data_cport, uint16_t size) + u16 data_cport, u16 size) { struct gb_audio_set_tx_data_size_request req; @@ -162,7 +162,7 @@ int gb_audio_gb_set_tx_data_size(struct gb_connection *connection, EXPORT_SYMBOL_GPL(gb_audio_gb_set_tx_data_size); int gb_audio_gb_activate_tx(struct gb_connection *connection, - uint16_t data_cport) + u16 data_cport) { struct gb_audio_activate_tx_request req; @@ -174,7 +174,7 @@ int gb_audio_gb_activate_tx(struct gb_connection *connection, EXPORT_SYMBOL_GPL(gb_audio_gb_activate_tx); int gb_audio_gb_deactivate_tx(struct gb_connection *connection, - uint16_t data_cport) + u16 data_cport) { struct gb_audio_deactivate_tx_request req; @@ -186,7 +186,7 @@ int gb_audio_gb_deactivate_tx(struct gb_connection *connection, EXPORT_SYMBOL_GPL(gb_audio_gb_deactivate_tx); int gb_audio_gb_set_rx_data_size(struct gb_connection *connection, - uint16_t data_cport, uint16_t size) + u16 data_cport, u16 size) { struct gb_audio_set_rx_data_size_request req; @@ -199,7 +199,7 @@ int gb_audio_gb_set_rx_data_size(struct gb_connection *connection, EXPORT_SYMBOL_GPL(gb_audio_gb_set_rx_data_size); int gb_audio_gb_activate_rx(struct gb_connection *connection, - uint16_t data_cport) + u16 data_cport) { struct gb_audio_activate_rx_request req; @@ -211,7 +211,7 @@ int gb_audio_gb_activate_rx(struct gb_connection *connection, EXPORT_SYMBOL_GPL(gb_audio_gb_activate_rx); int gb_audio_gb_deactivate_rx(struct gb_connection *connection, - uint16_t data_cport) + u16 data_cport) { struct gb_audio_deactivate_rx_request req; -- cgit v0.10.2 From 41ef5e5a4ad5044841296098b90b4f9da0d264f4 Mon Sep 17 00:00:00 2001 From: Jon Frisch <jon.frisch@unisys.com> Date: Mon, 19 Sep 2016 17:09:16 -0400 Subject: staging: unisys: visorbus remove unused module parameter This patch removes the unused module parameter visorchipset_visorbusregwait Signed-off-by: Jon Frisch <jon.frisch@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index ad8a407..656583e 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -50,7 +50,6 @@ * Module parameters */ static int visorchipset_major; -static int visorchipset_visorbusregwait = 1; /* default is on */ static unsigned long controlvm_payload_bytes_buffered; static u32 dump_vhba_bus; @@ -2311,9 +2310,6 @@ static void exit_unisys(void) module_param_named(major, visorchipset_major, int, S_IRUGO); MODULE_PARM_DESC(visorchipset_major, "major device number to use for the device node"); -module_param_named(visorbusregwait, visorchipset_visorbusregwait, int, S_IRUGO); -MODULE_PARM_DESC(visorchipset_visorbusregwait, - "1 to have the module wait for the visor bus to register"); module_init(init_unisys); module_exit(exit_unisys); -- cgit v0.10.2 From fbd5232109491118eba16773ea2db39b223edde3 Mon Sep 17 00:00:00 2001 From: Jon Frisch <jon.frisch@unisys.com> Date: Mon, 19 Sep 2016 17:09:17 -0400 Subject: staging: unisys: visorbus: remove unused long long bus_count This patch removes the unused long long bus_count. Signed-off-by: Jon Frisch <jon.frisch@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index fe5fc21..8ed60c0 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -111,9 +111,6 @@ struct bus_type visorbus_type = { .bus_groups = visorbus_bus_groups, }; -static long long bus_count; /* number of bus instances */ - /* ever-increasing */ - /* filled in with info about parent chipset driver when we register with it */ static struct ultra_vbus_deviceinfo chipset_driverinfo; /* filled in with info about this driver, wrt it servicing client busses */ @@ -1070,7 +1067,6 @@ create_bus_instance(struct visor_device *dev) } else { kfree(hdr_info); } - bus_count++; list_add_tail(&dev->list_all, &list_all_bus_instances); dev_set_drvdata(&dev->device, dev); return 0; @@ -1091,7 +1087,6 @@ remove_bus_instance(struct visor_device *dev) * successfully been able to trace thru the code to see where/how * release() gets called. But I know it does. */ - bus_count--; if (dev->visorchannel) { visorchannel_destroy(dev->visorchannel); dev->visorchannel = NULL; -- cgit v0.10.2 From 820b11b6bb4924598524750201cf9360013fe7b7 Mon Sep 17 00:00:00 2001 From: Jon Frisch <jon.frisch@unisys.com> Date: Mon, 19 Sep 2016 17:09:18 -0400 Subject: staging: unisys: visorbus: remove unused dump_vhba_bus This patch removes the unused u32 dump_vhba_bus. Signed-off-by: Jon Frisch <jon.frisch@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 656583e..84c2858 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -51,7 +51,6 @@ */ static int visorchipset_major; static unsigned long controlvm_payload_bytes_buffered; -static u32 dump_vhba_bus; static int visorchipset_open(struct inode *inode, struct file *file) @@ -1011,10 +1010,8 @@ bus_create(struct controlvm_message *inmsg) goto out_bus_epilog; } bus_info->visorchannel = visorchannel; - if (uuid_le_cmp(cmd->create_bus.bus_inst_uuid, spar_siovm_uuid) == 0) { - dump_vhba_bus = bus_no; + if (uuid_le_cmp(cmd->create_bus.bus_inst_uuid, spar_siovm_uuid) == 0) save_crash_message(inmsg, CRASH_BUS); - } POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, bus_no, POSTCODE_SEVERITY_INFO); -- cgit v0.10.2 From c071b6f541b62f4d143cc4316e4b1167dcaea8fe Mon Sep 17 00:00:00 2001 From: Jon Frisch <jon.frisch@unisys.com> Date: Mon, 19 Sep 2016 17:09:19 -0400 Subject: staging: unisys: visorbus: move controlvm_payload_bytes_buffered This patch moves the unsigned long controlvm_payload_bytes_buffered from the module parameters location to a more appropriate location below the controlvm_payload_info. Signed-off-by: Jon Frisch <jon.frisch@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 84c2858..de2e92f 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -50,7 +50,6 @@ * Module parameters */ static int visorchipset_major; -static unsigned long controlvm_payload_bytes_buffered; static int visorchipset_open(struct inode *inode, struct file *file) @@ -106,6 +105,7 @@ struct visor_controlvm_payload_info { }; static struct visor_controlvm_payload_info controlvm_payload_info; +static unsigned long controlvm_payload_bytes_buffered; /* * The following globals are used to handle the scenario where we are unable to -- cgit v0.10.2 From 3d8394c86f1b482ec2509e5a152484a27cc6cc74 Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Mon, 19 Sep 2016 17:09:20 -0400 Subject: staging: unisys: visorbus: reorder controlvm_periodic_work Move controlvm_periodic_work lower in the file to avoid having to create function prototypes. Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index de2e92f..7cb7c00 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -1752,73 +1752,6 @@ static u64 controlvm_get_channel_address(void) } static void -controlvm_periodic_work(struct work_struct *work) -{ - struct controlvm_message inmsg; - bool got_command = false; - bool handle_command_failed = false; - - while (visorchannel_signalremove(controlvm_channel, - CONTROLVM_QUEUE_RESPONSE, - &inmsg)) - ; - if (!got_command) { - if (controlvm_pending_msg_valid) { - /* - * we throttled processing of a prior - * msg, so try to process it again - * rather than reading a new one - */ - inmsg = controlvm_pending_msg; - controlvm_pending_msg_valid = false; - got_command = true; - } else { - got_command = read_controlvm_event(&inmsg); - } - } - - handle_command_failed = false; - while (got_command && (!handle_command_failed)) { - most_recent_message_jiffies = jiffies; - if (handle_command(inmsg, - visorchannel_get_physaddr - (controlvm_channel))) - got_command = read_controlvm_event(&inmsg); - else { - /* - * this is a scenario where throttling - * is required, but probably NOT an - * error...; we stash the current - * controlvm msg so we will attempt to - * reprocess it on our next loop - */ - handle_command_failed = true; - controlvm_pending_msg = inmsg; - controlvm_pending_msg_valid = true; - } - } - - /* parahotplug_worker */ - parahotplug_process_list(); - - if (time_after(jiffies, - most_recent_message_jiffies + (HZ * MIN_IDLE_SECONDS))) { - /* - * it's been longer than MIN_IDLE_SECONDS since we - * processed our last controlvm message; slow down the - * polling - */ - if (poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_SLOW) - poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW; - } else { - if (poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_FAST) - poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; - } - - schedule_delayed_work(&periodic_controlvm_work, poll_jiffies); -} - -static void setup_crash_devices_work_queue(struct work_struct *work) { struct controlvm_message local_crash_bus_msg; @@ -2158,6 +2091,73 @@ visorchipset_file_cleanup(dev_t major_dev) unregister_chrdev_region(major_dev, 1); } +static void +controlvm_periodic_work(struct work_struct *work) +{ + struct controlvm_message inmsg; + bool got_command = false; + bool handle_command_failed = false; + + while (visorchannel_signalremove(controlvm_channel, + CONTROLVM_QUEUE_RESPONSE, + &inmsg)) + ; + if (!got_command) { + if (controlvm_pending_msg_valid) { + /* + * we throttled processing of a prior + * msg, so try to process it again + * rather than reading a new one + */ + inmsg = controlvm_pending_msg; + controlvm_pending_msg_valid = false; + got_command = true; + } else { + got_command = read_controlvm_event(&inmsg); + } + } + + handle_command_failed = false; + while (got_command && (!handle_command_failed)) { + most_recent_message_jiffies = jiffies; + if (handle_command(inmsg, + visorchannel_get_physaddr + (controlvm_channel))) + got_command = read_controlvm_event(&inmsg); + else { + /* + * this is a scenario where throttling + * is required, but probably NOT an + * error...; we stash the current + * controlvm msg so we will attempt to + * reprocess it on our next loop + */ + handle_command_failed = true; + controlvm_pending_msg = inmsg; + controlvm_pending_msg_valid = true; + } + } + + /* parahotplug_worker */ + parahotplug_process_list(); + + if (time_after(jiffies, + most_recent_message_jiffies + (HZ * MIN_IDLE_SECONDS))) { + /* + * it's been longer than MIN_IDLE_SECONDS since we + * processed our last controlvm message; slow down the + * polling + */ + if (poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_SLOW) + poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW; + } else { + if (poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_FAST) + poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; + } + + schedule_delayed_work(&periodic_controlvm_work, poll_jiffies); +} + static int visorchipset_init(struct acpi_device *acpi_device) { -- cgit v0.10.2 From 511474a5077b088f92166a7875af5e6fa428e465 Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Mon, 19 Sep 2016 17:09:21 -0400 Subject: staging: unisys: visorbus: move handle_command Handle_command gets moved lower in the file to avoid the need for extraneous function prototypes. Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 7cb7c00..168d42f 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -1609,121 +1609,6 @@ parahotplug_process_message(struct controlvm_message *inmsg) } } -/** - * handle_command() - process a controlvm message - * @inmsg: the message to process - * @channel_addr: address of the controlvm channel - * - * Return: - * false - this function will return false only in the case where the - * controlvm message was NOT processed, but processing must be - * retried before reading the next controlvm message; a - * scenario where this can occur is when we need to throttle - * the allocation of memory in which to copy out controlvm - * payload data - * true - processing of the controlvm message completed, - * either successfully or with an error - */ -static bool -handle_command(struct controlvm_message inmsg, u64 channel_addr) -{ - struct controlvm_message_packet *cmd = &inmsg.cmd; - u64 parm_addr; - u32 parm_bytes; - struct parser_context *parser_ctx = NULL; - bool local_addr; - struct controlvm_message ackmsg; - - /* create parsing context if necessary */ - local_addr = (inmsg.hdr.flags.test_message == 1); - if (channel_addr == 0) - return true; - parm_addr = channel_addr + inmsg.hdr.payload_vm_offset; - parm_bytes = inmsg.hdr.payload_bytes; - - /* - * Parameter and channel addresses within test messages actually lie - * within our OS-controlled memory. We need to know that, because it - * makes a difference in how we compute the virtual address. - */ - if (parm_addr && parm_bytes) { - bool retry = false; - - parser_ctx = - parser_init_byte_stream(parm_addr, parm_bytes, - local_addr, &retry); - if (!parser_ctx && retry) - return false; - } - - if (!local_addr) { - controlvm_init_response(&ackmsg, &inmsg.hdr, - CONTROLVM_RESP_SUCCESS); - if (controlvm_channel) - visorchannel_signalinsert(controlvm_channel, - CONTROLVM_QUEUE_ACK, - &ackmsg); - } - switch (inmsg.hdr.id) { - case CONTROLVM_CHIPSET_INIT: - chipset_init(&inmsg); - break; - case CONTROLVM_BUS_CREATE: - bus_create(&inmsg); - break; - case CONTROLVM_BUS_DESTROY: - bus_destroy(&inmsg); - break; - case CONTROLVM_BUS_CONFIGURE: - bus_configure(&inmsg, parser_ctx); - break; - case CONTROLVM_DEVICE_CREATE: - my_device_create(&inmsg); - break; - case CONTROLVM_DEVICE_CHANGESTATE: - if (cmd->device_change_state.flags.phys_device) { - parahotplug_process_message(&inmsg); - } else { - /* - * save the hdr and cmd structures for later use - * when sending back the response to Command - */ - my_device_changestate(&inmsg); - break; - } - break; - case CONTROLVM_DEVICE_DESTROY: - my_device_destroy(&inmsg); - break; - case CONTROLVM_DEVICE_CONFIGURE: - /* no op for now, just send a respond that we passed */ - if (inmsg.hdr.flags.response_expected) - controlvm_respond(&inmsg.hdr, CONTROLVM_RESP_SUCCESS); - break; - case CONTROLVM_CHIPSET_READY: - chipset_ready(&inmsg.hdr); - break; - case CONTROLVM_CHIPSET_SELFTEST: - chipset_selftest(&inmsg.hdr); - break; - case CONTROLVM_CHIPSET_STOP: - chipset_notready(&inmsg.hdr); - break; - default: - if (inmsg.hdr.flags.response_expected) - controlvm_respond - (&inmsg.hdr, - -CONTROLVM_RESP_ERROR_MESSAGE_ID_UNKNOWN); - break; - } - - if (parser_ctx) { - parser_done(parser_ctx); - parser_ctx = NULL; - } - return true; -} - static inline unsigned int issue_vmcall_io_controlvm_addr(u64 *control_addr, u32 *control_bytes) { @@ -2091,6 +1976,121 @@ visorchipset_file_cleanup(dev_t major_dev) unregister_chrdev_region(major_dev, 1); } +/** + * handle_command() - process a controlvm message + * @inmsg: the message to process + * @channel_addr: address of the controlvm channel + * + * Return: + * false - this function will return false only in the case where the + * controlvm message was NOT processed, but processing must be + * retried before reading the next controlvm message; a + * scenario where this can occur is when we need to throttle + * the allocation of memory in which to copy out controlvm + * payload data + * true - processing of the controlvm message completed, + * either successfully or with an error + */ +static bool +handle_command(struct controlvm_message inmsg, u64 channel_addr) +{ + struct controlvm_message_packet *cmd = &inmsg.cmd; + u64 parm_addr; + u32 parm_bytes; + struct parser_context *parser_ctx = NULL; + bool local_addr; + struct controlvm_message ackmsg; + + /* create parsing context if necessary */ + local_addr = (inmsg.hdr.flags.test_message == 1); + if (channel_addr == 0) + return true; + parm_addr = channel_addr + inmsg.hdr.payload_vm_offset; + parm_bytes = inmsg.hdr.payload_bytes; + + /* + * Parameter and channel addresses within test messages actually lie + * within our OS-controlled memory. We need to know that, because it + * makes a difference in how we compute the virtual address. + */ + if (parm_addr && parm_bytes) { + bool retry = false; + + parser_ctx = + parser_init_byte_stream(parm_addr, parm_bytes, + local_addr, &retry); + if (!parser_ctx && retry) + return false; + } + + if (!local_addr) { + controlvm_init_response(&ackmsg, &inmsg.hdr, + CONTROLVM_RESP_SUCCESS); + if (controlvm_channel) + visorchannel_signalinsert(controlvm_channel, + CONTROLVM_QUEUE_ACK, + &ackmsg); + } + switch (inmsg.hdr.id) { + case CONTROLVM_CHIPSET_INIT: + chipset_init(&inmsg); + break; + case CONTROLVM_BUS_CREATE: + bus_create(&inmsg); + break; + case CONTROLVM_BUS_DESTROY: + bus_destroy(&inmsg); + break; + case CONTROLVM_BUS_CONFIGURE: + bus_configure(&inmsg, parser_ctx); + break; + case CONTROLVM_DEVICE_CREATE: + my_device_create(&inmsg); + break; + case CONTROLVM_DEVICE_CHANGESTATE: + if (cmd->device_change_state.flags.phys_device) { + parahotplug_process_message(&inmsg); + } else { + /* + * save the hdr and cmd structures for later use + * when sending back the response to Command + */ + my_device_changestate(&inmsg); + break; + } + break; + case CONTROLVM_DEVICE_DESTROY: + my_device_destroy(&inmsg); + break; + case CONTROLVM_DEVICE_CONFIGURE: + /* no op for now, just send a respond that we passed */ + if (inmsg.hdr.flags.response_expected) + controlvm_respond(&inmsg.hdr, CONTROLVM_RESP_SUCCESS); + break; + case CONTROLVM_CHIPSET_READY: + chipset_ready(&inmsg.hdr); + break; + case CONTROLVM_CHIPSET_SELFTEST: + chipset_selftest(&inmsg.hdr); + break; + case CONTROLVM_CHIPSET_STOP: + chipset_notready(&inmsg.hdr); + break; + default: + if (inmsg.hdr.flags.response_expected) + controlvm_respond + (&inmsg.hdr, + -CONTROLVM_RESP_ERROR_MESSAGE_ID_UNKNOWN); + break; + } + + if (parser_ctx) { + parser_done(parser_ctx); + parser_ctx = NULL; + } + return true; +} + static void controlvm_periodic_work(struct work_struct *work) { -- cgit v0.10.2 From 8a2853279b3316558d4a5a34b06b6890ebc65613 Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Mon, 19 Sep 2016 17:09:23 -0400 Subject: staging: unisys: visorbus: move read_controlvm_event The function read_controlvm_event needs to be moved lower in the file to avoid extraneous function prototypes. Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 168d42f..d8e5826 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -1357,27 +1357,6 @@ chipset_notready(struct controlvm_message_header *msg_hdr) controlvm_respond(msg_hdr, rc); } -/** - * read_controlvm_event() - retreives the next message from the - * CONTROLVM_QUEUE_EVENT queue in the controlvm - * channel - * @msg: pointer to the retrieved message - * - * Return: true if a valid message was retrieved or false otherwise - */ -static bool -read_controlvm_event(struct controlvm_message *msg) -{ - if (visorchannel_signalremove(controlvm_channel, - CONTROLVM_QUEUE_EVENT, msg)) { - /* got a message */ - if (msg->hdr.flags.test_message == 1) - return false; - return true; - } - return false; -} - /* * The general parahotplug flow works as follows. The visorchipset * driver receives a DEVICE_CHANGESTATE message from Command @@ -2091,6 +2070,27 @@ handle_command(struct controlvm_message inmsg, u64 channel_addr) return true; } +/** + * read_controlvm_event() - retreives the next message from the + * CONTROLVM_QUEUE_EVENT queue in the controlvm + * channel + * @msg: pointer to the retrieved message + * + * Return: true if a valid message was retrieved or false otherwise + */ +static bool +read_controlvm_event(struct controlvm_message *msg) +{ + if (visorchannel_signalremove(controlvm_channel, + CONTROLVM_QUEUE_EVENT, msg)) { + /* got a message */ + if (msg->hdr.flags.test_message == 1) + return false; + return true; + } + return false; +} + static void controlvm_periodic_work(struct work_struct *work) { -- cgit v0.10.2 From a9c73937436a412aed24c08595a31b7bf9e10dd6 Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Mon, 19 Sep 2016 17:09:24 -0400 Subject: staging: unisys: visorbus: move parahotplug_process_list The function parahotplug_process_list needs to be moved lower in the file to avoid extraneous function prototypes. Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index d8e5826..468286b 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -179,7 +179,6 @@ struct parahotplug_request { static LIST_HEAD(parahotplug_request_list); static DEFINE_SPINLOCK(parahotplug_request_list_lock); /* lock for above */ -static void parahotplug_process_list(void); /* info for /dev/visorchipset */ static dev_t major_dev = -1; /*< indicates major num for device */ @@ -1466,37 +1465,6 @@ parahotplug_request_kickoff(struct parahotplug_request *req) } /** - * parahotplug_process_list() - remove any request from the list that's been on - * there too long and respond with an error - */ -static void -parahotplug_process_list(void) -{ - struct list_head *pos; - struct list_head *tmp; - - spin_lock(¶hotplug_request_list_lock); - - list_for_each_safe(pos, tmp, ¶hotplug_request_list) { - struct parahotplug_request *req = - list_entry(pos, struct parahotplug_request, list); - - if (!time_after_eq(jiffies, req->expiration)) - continue; - - list_del(pos); - if (req->msg.hdr.flags.response_expected) - controlvm_respond_physdev_changestate( - &req->msg.hdr, - CONTROLVM_RESP_ERROR_DEVICE_UDEV_TIMEOUT, - req->msg.cmd.device_change_state.state); - parahotplug_request_destroy(req); - } - - spin_unlock(¶hotplug_request_list_lock); -} - -/** * parahotplug_request_complete() - mark request as complete * @id: the id of the request * @active: indicates whether the request is assigned to active partition @@ -2091,6 +2059,37 @@ read_controlvm_event(struct controlvm_message *msg) return false; } +/** + * parahotplug_process_list() - remove any request from the list that's been on + * there too long and respond with an error + */ +static void +parahotplug_process_list(void) +{ + struct list_head *pos; + struct list_head *tmp; + + spin_lock(¶hotplug_request_list_lock); + + list_for_each_safe(pos, tmp, ¶hotplug_request_list) { + struct parahotplug_request *req = + list_entry(pos, struct parahotplug_request, list); + + if (!time_after_eq(jiffies, req->expiration)) + continue; + + list_del(pos); + if (req->msg.hdr.flags.response_expected) + controlvm_respond_physdev_changestate( + &req->msg.hdr, + CONTROLVM_RESP_ERROR_DEVICE_UDEV_TIMEOUT, + req->msg.cmd.device_change_state.state); + parahotplug_request_destroy(req); + } + + spin_unlock(¶hotplug_request_list_lock); +} + static void controlvm_periodic_work(struct work_struct *work) { -- cgit v0.10.2 From 992228b2b0f2d7a1efc9cc21c21f1a3dea9c50f5 Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Mon, 19 Sep 2016 17:09:25 -0400 Subject: staging: unisys: visorbus: remove prototype controlvm_respond Remove the unneeded prototype for controlvm_respond. Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 468286b..6f530ea 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -271,8 +271,6 @@ static struct platform_device visorchipset_platform_device = { }; /* Function prototypes */ -static void controlvm_respond(struct controlvm_message_header *msg_hdr, - int response); static void controlvm_respond_chipset_init( struct controlvm_message_header *msg_hdr, int response, enum ultra_chipset_feature features); -- cgit v0.10.2 From 5f2513950f1f8b9acc740720b89389b2aa24ac72 Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Mon, 19 Sep 2016 17:09:26 -0400 Subject: staging: unisys: visorbus: remove controlvm_respond_chipset_init prototype Remove the unneeded controlvm_respond_chipset_init prototype by moving the functions controlvm_init_response and controlvm_respond_chipset_init up in the file. Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 6f530ea..7dcf0b3 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -271,9 +271,6 @@ static struct platform_device visorchipset_platform_device = { }; /* Function prototypes */ -static void controlvm_respond_chipset_init( - struct controlvm_message_header *msg_hdr, int response, - enum ultra_chipset_feature features); static void controlvm_respond_physdev_changestate( struct controlvm_message_header *msg_hdr, int response, struct spar_segment_state state); @@ -638,6 +635,36 @@ struct visor_device *visorbus_get_device_by_id(u32 bus_no, u32 dev_no, } static void +controlvm_init_response(struct controlvm_message *msg, + struct controlvm_message_header *msg_hdr, int response) +{ + memset(msg, 0, sizeof(struct controlvm_message)); + memcpy(&msg->hdr, msg_hdr, sizeof(struct controlvm_message_header)); + msg->hdr.payload_bytes = 0; + msg->hdr.payload_vm_offset = 0; + msg->hdr.payload_max_bytes = 0; + if (response < 0) { + msg->hdr.flags.failed = 1; + msg->hdr.completion_status = (u32)(-response); + } +} + +static void +controlvm_respond_chipset_init(struct controlvm_message_header *msg_hdr, + int response, + enum ultra_chipset_feature features) +{ + struct controlvm_message outmsg; + + controlvm_init_response(&outmsg, msg_hdr, response); + outmsg.cmd.init_chipset.features = features; + if (!visorchannel_signalinsert(controlvm_channel, + CONTROLVM_QUEUE_REQUEST, &outmsg)) { + return; + } +} + +static void chipset_init(struct controlvm_message *inmsg) { static int chipset_inited; @@ -672,21 +699,6 @@ out_respond: } static void -controlvm_init_response(struct controlvm_message *msg, - struct controlvm_message_header *msg_hdr, int response) -{ - memset(msg, 0, sizeof(struct controlvm_message)); - memcpy(&msg->hdr, msg_hdr, sizeof(struct controlvm_message_header)); - msg->hdr.payload_bytes = 0; - msg->hdr.payload_vm_offset = 0; - msg->hdr.payload_max_bytes = 0; - if (response < 0) { - msg->hdr.flags.failed = 1; - msg->hdr.completion_status = (u32)(-response); - } -} - -static void controlvm_respond(struct controlvm_message_header *msg_hdr, int response) { struct controlvm_message outmsg; @@ -701,21 +713,6 @@ controlvm_respond(struct controlvm_message_header *msg_hdr, int response) } } -static void -controlvm_respond_chipset_init(struct controlvm_message_header *msg_hdr, - int response, - enum ultra_chipset_feature features) -{ - struct controlvm_message outmsg; - - controlvm_init_response(&outmsg, msg_hdr, response); - outmsg.cmd.init_chipset.features = features; - if (!visorchannel_signalinsert(controlvm_channel, - CONTROLVM_QUEUE_REQUEST, &outmsg)) { - return; - } -} - static void controlvm_respond_physdev_changestate( struct controlvm_message_header *msg_hdr, int response, struct spar_segment_state state) -- cgit v0.10.2 From 84efd2077c1e935c4123e5688ba86062f608bb73 Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Mon, 19 Sep 2016 17:09:29 -0400 Subject: staging: unisys: visorbus: move toolaction functions to remove prototypes The toolchain functions show and store needed to be moved so the prototypes were no longer needed. Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 7dcf0b3..568ff9e 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -185,10 +185,37 @@ static dev_t major_dev = -1; /*< indicates major num for device */ /* prototypes for attributes */ static ssize_t toolaction_show(struct device *dev, - struct device_attribute *attr, char *buf); + struct device_attribute *attr, + char *buf) +{ + u8 tool_action = 0; + + visorchannel_read(controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + tool_action), &tool_action, sizeof(u8)); + return scnprintf(buf, PAGE_SIZE, "%u\n", tool_action); +} + static ssize_t toolaction_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count); + const char *buf, size_t count) +{ + u8 tool_action; + int ret; + + if (kstrtou8(buf, 10, &tool_action)) + return -EINVAL; + + ret = visorchannel_write + (controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + tool_action), + &tool_action, sizeof(u8)); + + if (ret) + return ret; + return count; +} static DEVICE_ATTR_RW(toolaction); static ssize_t boottotool_show(struct device *dev, @@ -431,39 +458,6 @@ parser_string_get(struct parser_context *ctx) return value; } -static ssize_t toolaction_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - u8 tool_action = 0; - - visorchannel_read(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - tool_action), &tool_action, sizeof(u8)); - return scnprintf(buf, PAGE_SIZE, "%u\n", tool_action); -} - -static ssize_t toolaction_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - u8 tool_action; - int ret; - - if (kstrtou8(buf, 10, &tool_action)) - return -EINVAL; - - ret = visorchannel_write - (controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - tool_action), - &tool_action, sizeof(u8)); - - if (ret) - return ret; - return count; -} - static ssize_t boottotool_show(struct device *dev, struct device_attribute *attr, char *buf) -- cgit v0.10.2 From 1b1d463d08be0785b48ad8b23446ac13f726a60b Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Mon, 19 Sep 2016 17:09:30 -0400 Subject: staging: unisys: visorbus: move boottotool Move the boottotool show and store functions so the function prototypes can be removed. Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 568ff9e..8081160 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -219,10 +219,40 @@ static ssize_t toolaction_store(struct device *dev, static DEVICE_ATTR_RW(toolaction); static ssize_t boottotool_show(struct device *dev, - struct device_attribute *attr, char *buf); + struct device_attribute *attr, + char *buf) +{ + struct efi_spar_indication efi_spar_indication; + + visorchannel_read(controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + efi_spar_ind), &efi_spar_indication, + sizeof(struct efi_spar_indication)); + return scnprintf(buf, PAGE_SIZE, "%u\n", + efi_spar_indication.boot_to_tool); +} + static ssize_t boottotool_store(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count); + struct device_attribute *attr, + const char *buf, size_t count) +{ + int val, ret; + struct efi_spar_indication efi_spar_indication; + + if (kstrtoint(buf, 10, &val)) + return -EINVAL; + + efi_spar_indication.boot_to_tool = val; + ret = visorchannel_write + (controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + efi_spar_ind), &(efi_spar_indication), + sizeof(struct efi_spar_indication)); + + if (ret) + return ret; + return count; +} static DEVICE_ATTR_RW(boottotool); static ssize_t error_show(struct device *dev, struct device_attribute *attr, @@ -458,42 +488,6 @@ parser_string_get(struct parser_context *ctx) return value; } -static ssize_t boottotool_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct efi_spar_indication efi_spar_indication; - - visorchannel_read(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - efi_spar_ind), &efi_spar_indication, - sizeof(struct efi_spar_indication)); - return scnprintf(buf, PAGE_SIZE, "%u\n", - efi_spar_indication.boot_to_tool); -} - -static ssize_t boottotool_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - int val, ret; - struct efi_spar_indication efi_spar_indication; - - if (kstrtoint(buf, 10, &val)) - return -EINVAL; - - efi_spar_indication.boot_to_tool = val; - ret = visorchannel_write - (controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - efi_spar_ind), &(efi_spar_indication), - sizeof(struct efi_spar_indication)); - - if (ret) - return ret; - return count; -} - static ssize_t error_show(struct device *dev, struct device_attribute *attr, char *buf) { -- cgit v0.10.2 From 612b81c9315c60f3ab921cf87e1740e087a103de Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Mon, 19 Sep 2016 17:09:22 -0400 Subject: staging: unisys: visorbus: move parser_init_byte_stream The function parser_init_byte_stream needs to be moved lower in the file to avoid extraneous function prototypes. Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 8081160..47504a6 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -334,64 +334,6 @@ static void controlvm_respond_physdev_changestate( static void parser_done(struct parser_context *ctx); -static struct parser_context * -parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry) -{ - int allocbytes = sizeof(struct parser_context) + bytes; - struct parser_context *ctx; - - if (retry) - *retry = false; - - /* - * alloc an 0 extra byte to ensure payload is - * '\0'-terminated - */ - allocbytes++; - if ((controlvm_payload_bytes_buffered + bytes) - > MAX_CONTROLVM_PAYLOAD_BYTES) { - if (retry) - *retry = true; - return NULL; - } - ctx = kzalloc(allocbytes, GFP_KERNEL | __GFP_NORETRY); - if (!ctx) { - if (retry) - *retry = true; - return NULL; - } - - ctx->allocbytes = allocbytes; - ctx->param_bytes = bytes; - ctx->curr = NULL; - ctx->bytes_remaining = 0; - ctx->byte_stream = false; - if (local) { - void *p; - - if (addr > virt_to_phys(high_memory - 1)) - goto err_finish_ctx; - p = __va((unsigned long)(addr)); - memcpy(ctx->data, p, bytes); - } else { - void *mapping = memremap(addr, bytes, MEMREMAP_WB); - - if (!mapping) - goto err_finish_ctx; - memcpy(ctx->data, mapping, bytes); - memunmap(mapping); - } - - ctx->byte_stream = true; - controlvm_payload_bytes_buffered += ctx->param_bytes; - - return ctx; - -err_finish_ctx: - parser_done(ctx); - return NULL; -} - static uuid_le parser_id_get(struct parser_context *ctx) { @@ -1906,6 +1848,64 @@ visorchipset_file_cleanup(dev_t major_dev) unregister_chrdev_region(major_dev, 1); } +static struct parser_context * +parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry) +{ + int allocbytes = sizeof(struct parser_context) + bytes; + struct parser_context *ctx; + + if (retry) + *retry = false; + + /* + * alloc an 0 extra byte to ensure payload is + * '\0'-terminated + */ + allocbytes++; + if ((controlvm_payload_bytes_buffered + bytes) + > MAX_CONTROLVM_PAYLOAD_BYTES) { + if (retry) + *retry = true; + return NULL; + } + ctx = kzalloc(allocbytes, GFP_KERNEL | __GFP_NORETRY); + if (!ctx) { + if (retry) + *retry = true; + return NULL; + } + + ctx->allocbytes = allocbytes; + ctx->param_bytes = bytes; + ctx->curr = NULL; + ctx->bytes_remaining = 0; + ctx->byte_stream = false; + if (local) { + void *p; + + if (addr > virt_to_phys(high_memory - 1)) + goto err_finish_ctx; + p = __va((unsigned long)(addr)); + memcpy(ctx->data, p, bytes); + } else { + void *mapping = memremap(addr, bytes, MEMREMAP_WB); + + if (!mapping) + goto err_finish_ctx; + memcpy(ctx->data, mapping, bytes); + memunmap(mapping); + } + + ctx->byte_stream = true; + controlvm_payload_bytes_buffered += ctx->param_bytes; + + return ctx; + +err_finish_ctx: + parser_done(ctx); + return NULL; +} + /** * handle_command() - process a controlvm message * @inmsg: the message to process -- cgit v0.10.2 From dd845d3632135c5e17aaadccddda56f849b03201 Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Mon, 19 Sep 2016 17:09:27 -0400 Subject: staging: unisys: visorbus: remove controlvm_respond_physdev_changestate Remove the unneeded prototype declaration for function controlvm_respond_physdev_changestate. Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 47504a6..c2833bd 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -328,10 +328,6 @@ static struct platform_device visorchipset_platform_device = { }; /* Function prototypes */ -static void controlvm_respond_physdev_changestate( - struct controlvm_message_header *msg_hdr, int response, - struct spar_segment_state state); - static void parser_done(struct parser_context *ctx); static uuid_le -- cgit v0.10.2 From 65cb1a8c5471ee2aed372dbf69a51457d15de056 Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Mon, 19 Sep 2016 17:09:28 -0400 Subject: staging: unisys: visorbus: remove parser_done prototype Remove the unneeded prototype parser_done. Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index c2833bd..d50e4cd 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -327,9 +327,6 @@ static struct platform_device visorchipset_platform_device = { .dev.release = visorchipset_dev_release, }; -/* Function prototypes */ -static void parser_done(struct parser_context *ctx); - static uuid_le parser_id_get(struct parser_context *ctx) { -- cgit v0.10.2 From 8a4a8a03d3a378694ba4170370a447d3e0df3ad9 Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Mon, 19 Sep 2016 17:09:31 -0400 Subject: staging: unisys: visorbus: move error store/show functions Move the show and store functions for the error DEV_ATTR_RW so that the function prototypes can be removed. Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index d50e4cd..951eaea 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -256,9 +256,35 @@ static ssize_t boottotool_store(struct device *dev, static DEVICE_ATTR_RW(boottotool); static ssize_t error_show(struct device *dev, struct device_attribute *attr, - char *buf); + char *buf) +{ + u32 error = 0; + + visorchannel_read(controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + installation_error), + &error, sizeof(u32)); + return scnprintf(buf, PAGE_SIZE, "%i\n", error); +} + static ssize_t error_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count); + const char *buf, size_t count) +{ + u32 error; + int ret; + + if (kstrtou32(buf, 10, &error)) + return -EINVAL; + + ret = visorchannel_write + (controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + installation_error), + &error, sizeof(u32)); + if (ret) + return ret; + return count; +} static DEVICE_ATTR_RW(error); static ssize_t textid_show(struct device *dev, struct device_attribute *attr, @@ -423,37 +449,6 @@ parser_string_get(struct parser_context *ctx) return value; } -static ssize_t error_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - u32 error = 0; - - visorchannel_read(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - installation_error), - &error, sizeof(u32)); - return scnprintf(buf, PAGE_SIZE, "%i\n", error); -} - -static ssize_t error_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - u32 error; - int ret; - - if (kstrtou32(buf, 10, &error)) - return -EINVAL; - - ret = visorchannel_write - (controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - installation_error), - &error, sizeof(u32)); - if (ret) - return ret; - return count; -} - static ssize_t textid_show(struct device *dev, struct device_attribute *attr, char *buf) { -- cgit v0.10.2 From 79730c7c8148f68144540181b8b53b1e9639f9b7 Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Mon, 19 Sep 2016 17:09:32 -0400 Subject: staging: unisys: visorbus: move textid store and show functions The textid store and show functions were moved to allow us to remove the function prototypes. Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 951eaea..5ba5f19 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -288,9 +288,36 @@ static ssize_t error_store(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR_RW(error); static ssize_t textid_show(struct device *dev, struct device_attribute *attr, - char *buf); + char *buf) +{ + u32 text_id = 0; + + visorchannel_read + (controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + installation_text_id), + &text_id, sizeof(u32)); + return scnprintf(buf, PAGE_SIZE, "%i\n", text_id); +} + static ssize_t textid_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count); + const char *buf, size_t count) +{ + u32 text_id; + int ret; + + if (kstrtou32(buf, 10, &text_id)) + return -EINVAL; + + ret = visorchannel_write + (controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + installation_text_id), + &text_id, sizeof(u32)); + if (ret) + return ret; + return count; +} static DEVICE_ATTR_RW(textid); static ssize_t remaining_steps_show(struct device *dev, @@ -449,38 +476,6 @@ parser_string_get(struct parser_context *ctx) return value; } -static ssize_t textid_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - u32 text_id = 0; - - visorchannel_read - (controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - installation_text_id), - &text_id, sizeof(u32)); - return scnprintf(buf, PAGE_SIZE, "%i\n", text_id); -} - -static ssize_t textid_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - u32 text_id; - int ret; - - if (kstrtou32(buf, 10, &text_id)) - return -EINVAL; - - ret = visorchannel_write - (controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - installation_text_id), - &text_id, sizeof(u32)); - if (ret) - return ret; - return count; -} - static ssize_t remaining_steps_show(struct device *dev, struct device_attribute *attr, char *buf) { -- cgit v0.10.2 From 97f792ee3cd6f62551f6247ca36492615e26cb5e Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Mon, 19 Sep 2016 17:09:33 -0400 Subject: staging: unisys: visorbus: move the remaining_steps_show/store functions Moving the remaining_steps functions allows us to get rid of an unneeded prototype. Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 5ba5f19..d3efe75 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -321,10 +321,36 @@ static ssize_t textid_store(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR_RW(textid); static ssize_t remaining_steps_show(struct device *dev, - struct device_attribute *attr, char *buf); + struct device_attribute *attr, char *buf) +{ + u16 remaining_steps = 0; + + visorchannel_read(controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + installation_remaining_steps), + &remaining_steps, sizeof(u16)); + return scnprintf(buf, PAGE_SIZE, "%hu\n", remaining_steps); +} + static ssize_t remaining_steps_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count); + const char *buf, size_t count) +{ + u16 remaining_steps; + int ret; + + if (kstrtou16(buf, 10, &remaining_steps)) + return -EINVAL; + + ret = visorchannel_write + (controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + installation_remaining_steps), + &remaining_steps, sizeof(u16)); + if (ret) + return ret; + return count; +} static DEVICE_ATTR_RW(remaining_steps); static ssize_t devicedisabled_store(struct device *dev, @@ -476,38 +502,6 @@ parser_string_get(struct parser_context *ctx) return value; } -static ssize_t remaining_steps_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - u16 remaining_steps = 0; - - visorchannel_read(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - installation_remaining_steps), - &remaining_steps, sizeof(u16)); - return scnprintf(buf, PAGE_SIZE, "%hu\n", remaining_steps); -} - -static ssize_t remaining_steps_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - u16 remaining_steps; - int ret; - - if (kstrtou16(buf, 10, &remaining_steps)) - return -EINVAL; - - ret = visorchannel_write - (controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - installation_remaining_steps), - &remaining_steps, sizeof(u16)); - if (ret) - return ret; - return count; -} - struct visor_busdev { u32 bus_no; u32 dev_no; -- cgit v0.10.2 From ebeff0558c0a311f4c5d432c69c32b9502219190 Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Mon, 19 Sep 2016 17:09:34 -0400 Subject: staging: unisys: visorbus: move deviceenabled/disabled store functions Move the deviceenabled/devicedisabled store functions so that function prototypes can be removed. This caused us to move several of the structures farther down in the file as well. Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index d3efe75..5603bb6 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -353,59 +353,6 @@ static ssize_t remaining_steps_store(struct device *dev, } static DEVICE_ATTR_RW(remaining_steps); -static ssize_t devicedisabled_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count); -static DEVICE_ATTR_WO(devicedisabled); - -static ssize_t deviceenabled_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count); -static DEVICE_ATTR_WO(deviceenabled); - -static struct attribute *visorchipset_install_attrs[] = { - &dev_attr_toolaction.attr, - &dev_attr_boottotool.attr, - &dev_attr_error.attr, - &dev_attr_textid.attr, - &dev_attr_remaining_steps.attr, - NULL -}; - -static struct attribute_group visorchipset_install_group = { - .name = "install", - .attrs = visorchipset_install_attrs -}; - -static struct attribute *visorchipset_parahotplug_attrs[] = { - &dev_attr_devicedisabled.attr, - &dev_attr_deviceenabled.attr, - NULL -}; - -static struct attribute_group visorchipset_parahotplug_group = { - .name = "parahotplug", - .attrs = visorchipset_parahotplug_attrs -}; - -static const struct attribute_group *visorchipset_dev_groups[] = { - &visorchipset_install_group, - &visorchipset_parahotplug_group, - NULL -}; - -static void visorchipset_dev_release(struct device *dev) -{ -} - -/* /sys/devices/platform/visorchipset */ -static struct platform_device visorchipset_platform_device = { - .name = "visorchipset", - .id = -1, - .dev.groups = visorchipset_dev_groups, - .dev.release = visorchipset_dev_release, -}; - static uuid_le parser_id_get(struct parser_context *ctx) { @@ -1185,79 +1132,6 @@ initialize_controlvm_payload(void) &controlvm_payload_info); } -/** - * visorchipset_chipset_ready() - sends chipset_ready action - * - * Send ACTION=online for DEVPATH=/sys/devices/platform/visorchipset. - * - * Return: CONTROLVM_RESP_SUCCESS - */ -static int -visorchipset_chipset_ready(void) -{ - kobject_uevent(&visorchipset_platform_device.dev.kobj, KOBJ_ONLINE); - return CONTROLVM_RESP_SUCCESS; -} - -static int -visorchipset_chipset_selftest(void) -{ - char env_selftest[20]; - char *envp[] = { env_selftest, NULL }; - - sprintf(env_selftest, "SPARSP_SELFTEST=%d", 1); - kobject_uevent_env(&visorchipset_platform_device.dev.kobj, KOBJ_CHANGE, - envp); - return CONTROLVM_RESP_SUCCESS; -} - -/** - * visorchipset_chipset_notready() - sends chipset_notready action - * - * Send ACTION=offline for DEVPATH=/sys/devices/platform/visorchipset. - * - * Return: CONTROLVM_RESP_SUCCESS - */ -static int -visorchipset_chipset_notready(void) -{ - kobject_uevent(&visorchipset_platform_device.dev.kobj, KOBJ_OFFLINE); - return CONTROLVM_RESP_SUCCESS; -} - -static void -chipset_ready(struct controlvm_message_header *msg_hdr) -{ - int rc = visorchipset_chipset_ready(); - - if (rc != CONTROLVM_RESP_SUCCESS) - rc = -rc; - if (msg_hdr->flags.response_expected) - controlvm_respond(msg_hdr, rc); -} - -static void -chipset_selftest(struct controlvm_message_header *msg_hdr) -{ - int rc = visorchipset_chipset_selftest(); - - if (rc != CONTROLVM_RESP_SUCCESS) - rc = -rc; - if (msg_hdr->flags.response_expected) - controlvm_respond(msg_hdr, rc); -} - -static void -chipset_notready(struct controlvm_message_header *msg_hdr) -{ - int rc = visorchipset_chipset_notready(); - - if (rc != CONTROLVM_RESP_SUCCESS) - rc = -rc; - if (msg_hdr->flags.response_expected) - controlvm_respond(msg_hdr, rc); -} - /* * The general parahotplug flow works as follows. The visorchipset * driver receives a DEVICE_CHANGESTATE message from Command @@ -1335,38 +1209,6 @@ parahotplug_request_destroy(struct parahotplug_request *req) } /** - * parahotplug_request_kickoff() - initiate parahotplug request - * @req: the request to initiate - * - * Cause uevent to run the user level script to do the disable/enable specified - * in the parahotplug_request. - */ -static void -parahotplug_request_kickoff(struct parahotplug_request *req) -{ - struct controlvm_message_packet *cmd = &req->msg.cmd; - char env_cmd[40], env_id[40], env_state[40], env_bus[40], env_dev[40], - env_func[40]; - char *envp[] = { - env_cmd, env_id, env_state, env_bus, env_dev, env_func, NULL - }; - - sprintf(env_cmd, "SPAR_PARAHOTPLUG=1"); - sprintf(env_id, "SPAR_PARAHOTPLUG_ID=%d", req->id); - sprintf(env_state, "SPAR_PARAHOTPLUG_STATE=%d", - cmd->device_change_state.state.active); - sprintf(env_bus, "SPAR_PARAHOTPLUG_BUS=%d", - cmd->device_change_state.bus_no); - sprintf(env_dev, "SPAR_PARAHOTPLUG_DEVICE=%d", - cmd->device_change_state.dev_no >> 3); - sprintf(env_func, "SPAR_PARAHOTPLUG_FUNCTION=%d", - cmd->device_change_state.dev_no & 0x7); - - kobject_uevent_env(&visorchipset_platform_device.dev.kobj, KOBJ_CHANGE, - envp); -} - -/** * parahotplug_request_complete() - mark request as complete * @id: the id of the request * @active: indicates whether the request is assigned to active partition @@ -1411,6 +1253,138 @@ parahotplug_request_complete(int id, u16 active) } /** + * devicedisabled_store() - disables the hotplug device + * @dev: sysfs interface variable not utilized in this function + * @attr: sysfs interface variable not utilized in this function + * @buf: buffer containing the device id + * @count: the size of the buffer + * + * The parahotplug/devicedisabled interface gets called by our support script + * when an SR-IOV device has been shut down. The ID is passed to the script + * and then passed back when the device has been removed. + * + * Return: the size of the buffer for success or negative for error + */ +static ssize_t devicedisabled_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned int id; + int err; + + if (kstrtouint(buf, 10, &id)) + return -EINVAL; + + err = parahotplug_request_complete(id, 0); + if (err < 0) + return err; + return count; +} +static DEVICE_ATTR_WO(devicedisabled); + +/** + * deviceenabled_store() - enables the hotplug device + * @dev: sysfs interface variable not utilized in this function + * @attr: sysfs interface variable not utilized in this function + * @buf: buffer containing the device id + * @count: the size of the buffer + * + * The parahotplug/deviceenabled interface gets called by our support script + * when an SR-IOV device has been recovered. The ID is passed to the script + * and then passed back when the device has been brought back up. + * + * Return: the size of the buffer for success or negative for error + */ +static ssize_t deviceenabled_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned int id; + + if (kstrtouint(buf, 10, &id)) + return -EINVAL; + + parahotplug_request_complete(id, 1); + return count; +} +static DEVICE_ATTR_WO(deviceenabled); + +static struct attribute *visorchipset_install_attrs[] = { + &dev_attr_toolaction.attr, + &dev_attr_boottotool.attr, + &dev_attr_error.attr, + &dev_attr_textid.attr, + &dev_attr_remaining_steps.attr, + NULL +}; + +static struct attribute_group visorchipset_install_group = { + .name = "install", + .attrs = visorchipset_install_attrs +}; + +static struct attribute *visorchipset_parahotplug_attrs[] = { + &dev_attr_devicedisabled.attr, + &dev_attr_deviceenabled.attr, + NULL +}; + +static struct attribute_group visorchipset_parahotplug_group = { + .name = "parahotplug", + .attrs = visorchipset_parahotplug_attrs +}; + +static const struct attribute_group *visorchipset_dev_groups[] = { + &visorchipset_install_group, + &visorchipset_parahotplug_group, + NULL +}; + +static void visorchipset_dev_release(struct device *dev) +{ +} + +/* /sys/devices/platform/visorchipset */ +static struct platform_device visorchipset_platform_device = { + .name = "visorchipset", + .id = -1, + .dev.groups = visorchipset_dev_groups, + .dev.release = visorchipset_dev_release, +}; + +/** + * parahotplug_request_kickoff() - initiate parahotplug request + * @req: the request to initiate + * + * Cause uevent to run the user level script to do the disable/enable specified + * in the parahotplug_request. + */ +static void +parahotplug_request_kickoff(struct parahotplug_request *req) +{ + struct controlvm_message_packet *cmd = &req->msg.cmd; + char env_cmd[40], env_id[40], env_state[40], env_bus[40], env_dev[40], + env_func[40]; + char *envp[] = { + env_cmd, env_id, env_state, env_bus, env_dev, env_func, NULL + }; + + sprintf(env_cmd, "SPAR_PARAHOTPLUG=1"); + sprintf(env_id, "SPAR_PARAHOTPLUG_ID=%d", req->id); + sprintf(env_state, "SPAR_PARAHOTPLUG_STATE=%d", + cmd->device_change_state.state.active); + sprintf(env_bus, "SPAR_PARAHOTPLUG_BUS=%d", + cmd->device_change_state.bus_no); + sprintf(env_dev, "SPAR_PARAHOTPLUG_DEVICE=%d", + cmd->device_change_state.dev_no >> 3); + sprintf(env_func, "SPAR_PARAHOTPLUG_FUNCTION=%d", + cmd->device_change_state.dev_no & 0x7); + + kobject_uevent_env(&visorchipset_platform_device.dev.kobj, KOBJ_CHANGE, + envp); +} + +/** * parahotplug_process_message() - enables or disables a PCI device by kicking * off a udev script * @inmsg: the message indicating whether to enable or disable @@ -1458,6 +1432,79 @@ parahotplug_process_message(struct controlvm_message *inmsg) } } +/** + * visorchipset_chipset_ready() - sends chipset_ready action + * + * Send ACTION=online for DEVPATH=/sys/devices/platform/visorchipset. + * + * Return: CONTROLVM_RESP_SUCCESS + */ +static int +visorchipset_chipset_ready(void) +{ + kobject_uevent(&visorchipset_platform_device.dev.kobj, KOBJ_ONLINE); + return CONTROLVM_RESP_SUCCESS; +} + +static int +visorchipset_chipset_selftest(void) +{ + char env_selftest[20]; + char *envp[] = { env_selftest, NULL }; + + sprintf(env_selftest, "SPARSP_SELFTEST=%d", 1); + kobject_uevent_env(&visorchipset_platform_device.dev.kobj, KOBJ_CHANGE, + envp); + return CONTROLVM_RESP_SUCCESS; +} + +/** + * visorchipset_chipset_notready() - sends chipset_notready action + * + * Send ACTION=offline for DEVPATH=/sys/devices/platform/visorchipset. + * + * Return: CONTROLVM_RESP_SUCCESS + */ +static int +visorchipset_chipset_notready(void) +{ + kobject_uevent(&visorchipset_platform_device.dev.kobj, KOBJ_OFFLINE); + return CONTROLVM_RESP_SUCCESS; +} + +static void +chipset_ready(struct controlvm_message_header *msg_hdr) +{ + int rc = visorchipset_chipset_ready(); + + if (rc != CONTROLVM_RESP_SUCCESS) + rc = -rc; + if (msg_hdr->flags.response_expected) + controlvm_respond(msg_hdr, rc); +} + +static void +chipset_selftest(struct controlvm_message_header *msg_hdr) +{ + int rc = visorchipset_chipset_selftest(); + + if (rc != CONTROLVM_RESP_SUCCESS) + rc = -rc; + if (msg_hdr->flags.response_expected) + controlvm_respond(msg_hdr, rc); +} + +static void +chipset_notready(struct controlvm_message_header *msg_hdr) +{ + int rc = visorchipset_chipset_notready(); + + if (rc != CONTROLVM_RESP_SUCCESS) + rc = -rc; + if (msg_hdr->flags.response_expected) + controlvm_respond(msg_hdr, rc); +} + static inline unsigned int issue_vmcall_io_controlvm_addr(u64 *control_addr, u32 *control_bytes) { @@ -1640,61 +1687,6 @@ device_resume_response(struct visor_device *dev_info, int response) dev_info->pending_msg_hdr = NULL; } -/** - * devicedisabled_store() - disables the hotplug device - * @dev: sysfs interface variable not utilized in this function - * @attr: sysfs interface variable not utilized in this function - * @buf: buffer containing the device id - * @count: the size of the buffer - * - * The parahotplug/devicedisabled interface gets called by our support script - * when an SR-IOV device has been shut down. The ID is passed to the script - * and then passed back when the device has been removed. - * - * Return: the size of the buffer for success or negative for error - */ -static ssize_t devicedisabled_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned int id; - int err; - - if (kstrtouint(buf, 10, &id)) - return -EINVAL; - - err = parahotplug_request_complete(id, 0); - if (err < 0) - return err; - return count; -} - -/** - * deviceenabled_store() - enables the hotplug device - * @dev: sysfs interface variable not utilized in this function - * @attr: sysfs interface variable not utilized in this function - * @buf: buffer containing the device id - * @count: the size of the buffer - * - * The parahotplug/deviceenabled interface gets called by our support script - * when an SR-IOV device has been recovered. The ID is passed to the script - * and then passed back when the device has been brought back up. - * - * Return: the size of the buffer for success or negative for error - */ -static ssize_t deviceenabled_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned int id; - - if (kstrtouint(buf, 10, &id)) - return -EINVAL; - - parahotplug_request_complete(id, 1); - return count; -} - static int visorchipset_mmap(struct file *file, struct vm_area_struct *vma) { -- cgit v0.10.2 From 7993b40cd772cae9890f81fb0ea809130a732c5e Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Mon, 19 Sep 2016 17:09:35 -0400 Subject: staging: unisys: visorbus move visorbus_type to remove prototypes Move the struct visorbus_type down in the file to get rid of the function prototypes visorbus_uevent and visorbus_match. Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 8ed60c0..d41e3d9 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -35,8 +35,6 @@ static int visorbus_forcenomatch; static int busreg_rc = -ENODEV; /* stores the result from bus registration */ -static int visorbus_uevent(struct device *xdev, struct kobj_uevent_env *env); -static int visorbus_match(struct device *xdev, struct device_driver *xdrv); static void fix_vbus_dev_info(struct visor_device *visordev); /* @@ -99,18 +97,6 @@ static const struct attribute_group *visorbus_dev_groups[] = { NULL, }; -/* - * This describes the TYPE of bus. - * (Don't confuse this with an INSTANCE of the bus.) - */ -struct bus_type visorbus_type = { - .name = "visorbus", - .match = visorbus_match, - .uevent = visorbus_uevent, - .dev_groups = visorbus_dev_groups, - .bus_groups = visorbus_bus_groups, -}; - /* filled in with info about parent chipset driver when we register with it */ static struct ultra_vbus_deviceinfo chipset_driverinfo; /* filled in with info about this driver, wrt it servicing client busses */ @@ -174,6 +160,18 @@ visorbus_match(struct device *xdev, struct device_driver *xdrv) return 0; } +/* + * This describes the TYPE of bus. + * (Don't confuse this with an INSTANCE of the bus.) + */ +struct bus_type visorbus_type = { + .name = "visorbus", + .match = visorbus_match, + .uevent = visorbus_uevent, + .dev_groups = visorbus_dev_groups, + .bus_groups = visorbus_bus_groups, +}; + /** * visorbus_releae_busdevice() - called when device_unregister() is called for * the bus device instance, after all other tasks -- cgit v0.10.2 From 7a0ee694889694c49d4ebe99dce30e699f832396 Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Mon, 19 Sep 2016 17:09:36 -0400 Subject: staging: unisys: visorbus: remove fix_vbus_dev_info prototype Move the visordriver_probe_device and visorbus_register_visor_driver functions lower in the file to get rid of the function prototype fix_vbus_dev_info. Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index d41e3d9..3918bb5 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -35,8 +35,6 @@ static int visorbus_forcenomatch; static int busreg_rc = -ENODEV; /* stores the result from bus registration */ -static void fix_vbus_dev_info(struct visor_device *visordev); - /* * BUS type attributes * @@ -531,48 +529,6 @@ dev_stop_periodic_work(struct visor_device *dev) } /** - * visordriver_probe_device() - handle new visor device coming online - * @xdev: struct device for the visor device being probed - * - * This is called automatically upon adding a visor_device (device_add), or - * adding a visor_driver (visorbus_register_visor_driver), but only after - * visorbus_match() has returned 1 to indicate a successful match between - * driver and device. - * - * If successful, a reference to the device will be held onto via get_device(). - * - * Return: 0 if successful, meaning the function driver's probe() function - * was successful with this device, otherwise a negative errno - * value indicating failure reason - */ -static int -visordriver_probe_device(struct device *xdev) -{ - int res; - struct visor_driver *drv; - struct visor_device *dev; - - drv = to_visor_driver(xdev->driver); - dev = to_visor_device(xdev); - - if (!drv->probe) - return -ENODEV; - - mutex_lock(&dev->visordriver_callback_lock); - dev->being_removed = false; - - res = drv->probe(dev); - if (res >= 0) { - /* success: reference kept via unmatched get_device() */ - get_device(&dev->device); - fix_vbus_dev_info(dev); - } - - mutex_unlock(&dev->visordriver_callback_lock); - return res; -} - -/** * visordriver_remove_device() - handle visor device going away * @xdev: struct device for the visor device being removed * @@ -602,91 +558,6 @@ visordriver_remove_device(struct device *xdev) } /** - * visorbus_register_visor_driver() - registers the provided visor driver - * for handling one or more visor device - * types (channel_types) - * @drv: the driver to register - * - * A visor function driver calls this function to register - * the driver. The caller MUST fill in the following fields within the - * #drv structure: - * name, version, owner, channel_types, probe, remove - * - * Here's how the whole Linux bus / driver / device model works. - * - * At system start-up, the visorbus kernel module is loaded, which registers - * visorbus_type as a bus type, using bus_register(). - * - * All kernel modules that support particular device types on a - * visorbus bus are loaded. Each of these kernel modules calls - * visorbus_register_visor_driver() in their init functions, passing a - * visor_driver struct. visorbus_register_visor_driver() in turn calls - * register_driver(&visor_driver.driver). This .driver member is - * initialized with generic methods (like probe), whose sole responsibility - * is to act as a broker for the real methods, which are within the - * visor_driver struct. (This is the way the subclass behavior is - * implemented, since visor_driver is essentially a subclass of the - * generic driver.) Whenever a driver_register() happens, core bus code in - * the kernel does (see device_attach() in drivers/base/dd.c): - * - * for each dev associated with the bus (the bus that driver is on) that - * does not yet have a driver - * if bus.match(dev,newdriver) == yes_matched ** .match specified - * ** during bus_register(). - * newdriver.probe(dev) ** for visor drivers, this will call - * ** the generic driver.probe implemented in visorbus.c, - * ** which in turn calls the probe specified within the - * ** struct visor_driver (which was specified by the - * ** actual device driver as part of - * ** visorbus_register_visor_driver()). - * - * The above dance also happens when a new device appears. - * So the question is, how are devices created within the system? - * Basically, just call device_add(dev). See pci_bus_add_devices(). - * pci_scan_device() shows an example of how to build a device struct. It - * returns the newly-created struct to pci_scan_single_device(), who adds it - * to the list of devices at PCIBUS.devices. That list of devices is what - * is traversed by pci_bus_add_devices(). - * - * Return: integer indicating success (zero) or failure (non-zero) - */ -int visorbus_register_visor_driver(struct visor_driver *drv) -{ - int rc = 0; - - if (busreg_rc < 0) - return -ENODEV; /*can't register on a nonexistent bus*/ - - drv->driver.name = drv->name; - drv->driver.bus = &visorbus_type; - drv->driver.probe = visordriver_probe_device; - drv->driver.remove = visordriver_remove_device; - drv->driver.owner = drv->owner; - - /* - * driver_register does this: - * bus_add_driver(drv) - * ->if (drv.bus) ** (bus_type) ** - * driver_attach(drv) - * for each dev with bus type of drv.bus - * if (!dev.drv) ** no driver assigned yet ** - * if (bus.match(dev,drv)) [visorbus_match] - * dev.drv = drv - * if (!drv.probe(dev)) [visordriver_probe_device] - * dev.drv = NULL - */ - - rc = driver_register(&drv->driver); - if (rc < 0) - return rc; - rc = register_driver_attributes(drv); - if (rc < 0) - driver_unregister(&drv->driver); - return rc; -} -EXPORT_SYMBOL_GPL(visorbus_register_visor_driver); - -/** * visorbus_unregister_visor_driver() - unregisters the provided driver * @drv: the driver to unregister * @@ -1026,6 +897,133 @@ fix_vbus_dev_info(struct visor_device *visordev) } /** + * visordriver_probe_device() - handle new visor device coming online + * @xdev: struct device for the visor device being probed + * + * This is called automatically upon adding a visor_device (device_add), or + * adding a visor_driver (visorbus_register_visor_driver), but only after + * visorbus_match() has returned 1 to indicate a successful match between + * driver and device. + * + * If successful, a reference to the device will be held onto via get_device(). + * + * Return: 0 if successful, meaning the function driver's probe() function + * was successful with this device, otherwise a negative errno + * value indicating failure reason + */ +static int +visordriver_probe_device(struct device *xdev) +{ + int res; + struct visor_driver *drv; + struct visor_device *dev; + + drv = to_visor_driver(xdev->driver); + dev = to_visor_device(xdev); + + if (!drv->probe) + return -ENODEV; + + mutex_lock(&dev->visordriver_callback_lock); + dev->being_removed = false; + + res = drv->probe(dev); + if (res >= 0) { + /* success: reference kept via unmatched get_device() */ + get_device(&dev->device); + fix_vbus_dev_info(dev); + } + + mutex_unlock(&dev->visordriver_callback_lock); + return res; +} + +/** + * visorbus_register_visor_driver() - registers the provided visor driver + * for handling one or more visor device + * types (channel_types) + * @drv: the driver to register + * + * A visor function driver calls this function to register + * the driver. The caller MUST fill in the following fields within the + * #drv structure: + * name, version, owner, channel_types, probe, remove + * + * Here's how the whole Linux bus / driver / device model works. + * + * At system start-up, the visorbus kernel module is loaded, which registers + * visorbus_type as a bus type, using bus_register(). + * + * All kernel modules that support particular device types on a + * visorbus bus are loaded. Each of these kernel modules calls + * visorbus_register_visor_driver() in their init functions, passing a + * visor_driver struct. visorbus_register_visor_driver() in turn calls + * register_driver(&visor_driver.driver). This .driver member is + * initialized with generic methods (like probe), whose sole responsibility + * is to act as a broker for the real methods, which are within the + * visor_driver struct. (This is the way the subclass behavior is + * implemented, since visor_driver is essentially a subclass of the + * generic driver.) Whenever a driver_register() happens, core bus code in + * the kernel does (see device_attach() in drivers/base/dd.c): + * + * for each dev associated with the bus (the bus that driver is on) that + * does not yet have a driver + * if bus.match(dev,newdriver) == yes_matched ** .match specified + * ** during bus_register(). + * newdriver.probe(dev) ** for visor drivers, this will call + * ** the generic driver.probe implemented in visorbus.c, + * ** which in turn calls the probe specified within the + * ** struct visor_driver (which was specified by the + * ** actual device driver as part of + * ** visorbus_register_visor_driver()). + * + * The above dance also happens when a new device appears. + * So the question is, how are devices created within the system? + * Basically, just call device_add(dev). See pci_bus_add_devices(). + * pci_scan_device() shows an example of how to build a device struct. It + * returns the newly-created struct to pci_scan_single_device(), who adds it + * to the list of devices at PCIBUS.devices. That list of devices is what + * is traversed by pci_bus_add_devices(). + * + * Return: integer indicating success (zero) or failure (non-zero) + */ +int visorbus_register_visor_driver(struct visor_driver *drv) +{ + int rc = 0; + + if (busreg_rc < 0) + return -ENODEV; /*can't register on a nonexistent bus*/ + + drv->driver.name = drv->name; + drv->driver.bus = &visorbus_type; + drv->driver.probe = visordriver_probe_device; + drv->driver.remove = visordriver_remove_device; + drv->driver.owner = drv->owner; + + /* + * driver_register does this: + * bus_add_driver(drv) + * ->if (drv.bus) ** (bus_type) ** + * driver_attach(drv) + * for each dev with bus type of drv.bus + * if (!dev.drv) ** no driver assigned yet ** + * if (bus.match(dev,drv)) [visorbus_match] + * dev.drv = drv + * if (!drv.probe(dev)) [visordriver_probe_device] + * dev.drv = NULL + */ + + rc = driver_register(&drv->driver); + if (rc < 0) + return rc; + rc = register_driver_attributes(drv); + if (rc < 0) + driver_unregister(&drv->driver); + return rc; +} +EXPORT_SYMBOL_GPL(visorbus_register_visor_driver); + +/** * create_bus_instance() - create a device instance for the visor bus itself * @dev: struct visor_device indicating the bus instance * -- cgit v0.10.2 From 51319662d6ac5729a1950579d70808d94e4fa8e6 Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Mon, 19 Sep 2016 17:09:37 -0400 Subject: staging: unisys: visorbus: move parahotplug_request_list and related lock parahotplug_request_list and parahotplug_request_list_lock should be defined closer to where we are actually using them. Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 5603bb6..39e8aca 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -177,9 +177,6 @@ struct parahotplug_request { struct controlvm_message msg; }; -static LIST_HEAD(parahotplug_request_list); -static DEFINE_SPINLOCK(parahotplug_request_list_lock); /* lock for above */ - /* info for /dev/visorchipset */ static dev_t major_dev = -1; /*< indicates major num for device */ @@ -1208,6 +1205,9 @@ parahotplug_request_destroy(struct parahotplug_request *req) kfree(req); } +static LIST_HEAD(parahotplug_request_list); +static DEFINE_SPINLOCK(parahotplug_request_list_lock); /* lock for above */ + /** * parahotplug_request_complete() - mark request as complete * @id: the id of the request -- cgit v0.10.2 From d37843d1a956bf87e219067a0f45bc82db260216 Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Tue, 20 Sep 2016 13:18:40 +0530 Subject: staging: wilc1000: Merge assignment with return Instead of storing the return value into a variable and then returning it, we can club the two into a single return statement. This change was made using the following semantic patch by Coccinelle: @@ local idexpression ret; expression e; @@ -ret = +return e; -return ret; Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index d0cb568..78f5613 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3279,7 +3279,6 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, int wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_attr *cfg_param) { - int result = 0; struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; @@ -3293,9 +3292,7 @@ int wilc_hif_set_cfg(struct wilc_vif *vif, msg.body.cfg_info = *cfg_param; msg.vif = vif; - result = wilc_enqueue_cmd(&msg); - - return result; + return wilc_enqueue_cmd(&msg); } static void GetPeriodicRSSI(unsigned long arg) diff --git a/drivers/staging/wilc1000/wilc_spi.c b/drivers/staging/wilc1000/wilc_spi.c index 0f8d625..f6c47ca 100644 --- a/drivers/staging/wilc1000/wilc_spi.c +++ b/drivers/staging/wilc1000/wilc_spi.c @@ -410,8 +410,7 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, if (len2 > ARRAY_SIZE(wb)) { dev_err(&spi->dev, "spi buffer size too small (%d) (%zu)\n", len2, ARRAY_SIZE(wb)); - result = N_FAIL; - return result; + return N_FAIL; } /* zero spi write buffers. */ for (wix = len; wix < len2; wix++) diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 19a5809..2b307ce 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1001,8 +1001,7 @@ int wilc_wlan_start(struct wilc *wilc) ret = wilc->hif_func->hif_write_reg(wilc, WILC_VMM_CORE_CFG, reg); if (!ret) { release_bus(wilc, RELEASE_ONLY); - ret = -EIO; - return ret; + return -EIO; } reg = 0; if (wilc->io_type == HIF_SDIO && wilc->dev_irq_num) -- cgit v0.10.2 From 43969aa7e8506765412087f5c1fc5ae4f0fe5d9a Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Mon, 19 Sep 2016 00:23:42 +0700 Subject: staging: r8188eu: change last argument type of the usb_write_port function usb_write_port writes only xmit_buf object data to device. In addition, an appropriate name for this argument is used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c index 3e6f5ca..5482f47 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c @@ -387,7 +387,7 @@ static s32 rtw_dump_xframe(struct adapter *adapt, struct xmit_frame *pxmitframe) } ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe); - inner_ret = usb_write_port(adapt, ff_hwaddr, w_sz, (unsigned char *)pxmitbuf); + inner_ret = usb_write_port(adapt, ff_hwaddr, w_sz, pxmitbuf); rtw_count_tx_stats(adapt, pxmitframe, sz); @@ -592,7 +592,7 @@ s32 rtl8188eu_xmitframe_complete(struct adapter *adapt, struct xmit_priv *pxmitp /* 3 4. write xmit buffer to USB FIFO */ ff_hwaddr = rtw_get_ff_hwaddr(pfirstframe); - usb_write_port(adapt, ff_hwaddr, pbuf_tail, (u8 *)pxmitbuf); + usb_write_port(adapt, ff_hwaddr, pbuf_tail, pxmitbuf); /* 3 5. update statisitc */ pbuf_tail -= (pfirstframe->agg_num * TXDESC_SIZE); diff --git a/drivers/staging/rtl8188eu/include/usb_ops_linux.h b/drivers/staging/rtl8188eu/include/usb_ops_linux.h index 2207333..fde7753 100644 --- a/drivers/staging/rtl8188eu/include/usb_ops_linux.h +++ b/drivers/staging/rtl8188eu/include/usb_ops_linux.h @@ -75,7 +75,7 @@ int usb_write8(struct adapter *adapter, u32 addr, u8 val); int usb_write16(struct adapter *adapter, u32 addr, u16 val); int usb_write32(struct adapter *adapter, u32 addr, u32 val); -u32 usb_write_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem); +u32 usb_write_port(struct adapter *adapter, u32 addr, u32 cnt, struct xmit_buf *pmem); void usb_write_port_cancel(struct adapter *adapter); #endif diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c index 9359cc7..52fa659 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c @@ -693,7 +693,7 @@ check_completion: tasklet_hi_schedule(&pxmitpriv->xmit_tasklet); } -u32 usb_write_port(struct adapter *padapter, u32 addr, u32 cnt, u8 *wmem) +u32 usb_write_port(struct adapter *padapter, u32 addr, u32 cnt, struct xmit_buf *xmitbuf) { unsigned long irqL; unsigned int pipe; @@ -702,8 +702,7 @@ u32 usb_write_port(struct adapter *padapter, u32 addr, u32 cnt, u8 *wmem) struct urb *purb = NULL; struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter); struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct xmit_buf *pxmitbuf = (struct xmit_buf *)wmem; - struct xmit_frame *pxmitframe = (struct xmit_frame *)pxmitbuf->priv_data; + struct xmit_frame *pxmitframe = (struct xmit_frame *)xmitbuf->priv_data; struct usb_device *pusbd = pdvobj->pusbdev; @@ -713,7 +712,7 @@ u32 usb_write_port(struct adapter *padapter, u32 addr, u32 cnt, u8 *wmem) (padapter->pwrctrlpriv.pnp_bstop_trx)) { RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_write_port:( padapter->bDriverStopped ||padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n")); - rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_TX_DENY); + rtw_sctx_done_err(&xmitbuf->sctx, RTW_SCTX_DONE_TX_DENY); goto exit; } @@ -722,44 +721,44 @@ u32 usb_write_port(struct adapter *padapter, u32 addr, u32 cnt, u8 *wmem) switch (addr) { case VO_QUEUE_INX: pxmitpriv->voq_cnt++; - pxmitbuf->flags = VO_QUEUE_INX; + xmitbuf->flags = VO_QUEUE_INX; break; case VI_QUEUE_INX: pxmitpriv->viq_cnt++; - pxmitbuf->flags = VI_QUEUE_INX; + xmitbuf->flags = VI_QUEUE_INX; break; case BE_QUEUE_INX: pxmitpriv->beq_cnt++; - pxmitbuf->flags = BE_QUEUE_INX; + xmitbuf->flags = BE_QUEUE_INX; break; case BK_QUEUE_INX: pxmitpriv->bkq_cnt++; - pxmitbuf->flags = BK_QUEUE_INX; + xmitbuf->flags = BK_QUEUE_INX; break; case HIGH_QUEUE_INX: - pxmitbuf->flags = HIGH_QUEUE_INX; + xmitbuf->flags = HIGH_QUEUE_INX; break; default: - pxmitbuf->flags = MGT_QUEUE_INX; + xmitbuf->flags = MGT_QUEUE_INX; break; } spin_unlock_irqrestore(&pxmitpriv->lock, irqL); - purb = pxmitbuf->pxmit_urb[0]; + purb = xmitbuf->pxmit_urb[0]; /* translate DMA FIFO addr to pipehandle */ pipe = ffaddr2pipehdl(pdvobj, addr); usb_fill_bulk_urb(purb, pusbd, pipe, - pxmitframe->buf_addr, /* pxmitbuf->pbuf */ + pxmitframe->buf_addr, /* xmitbuf->pbuf */ cnt, usb_write_port_complete, - pxmitbuf);/* context is pxmitbuf */ + xmitbuf);/* context is xmitbuf */ status = usb_submit_urb(purb, GFP_ATOMIC); if (status) { - rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR); + rtw_sctx_done_err(&xmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR); DBG_88E("usb_write_port, status =%d\n", status); RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_write_port(): usb_submit_urb, status =%x\n", status)); @@ -781,7 +780,7 @@ u32 usb_write_port(struct adapter *padapter, u32 addr, u32 cnt, u8 *wmem) exit: if (ret != _SUCCESS) - rtw_free_xmitbuf(pxmitpriv, pxmitbuf); + rtw_free_xmitbuf(pxmitpriv, xmitbuf); return ret; } -- cgit v0.10.2 From bc9886d32e631edf6db67feee195e6eed1a21786 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Mon, 19 Sep 2016 00:24:01 +0700 Subject: staging: r8188eu: remove xmitframe_direct function xmitframe_direct is a simple wrapper around rtw_xmitframe_coalesce and rtw_dump_xframe functions. Many wrappers complicates code reading. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c index 5482f47..169d6c8 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c @@ -605,18 +605,6 @@ s32 rtl8188eu_xmitframe_complete(struct adapter *adapt, struct xmit_priv *pxmitp return true; } -static s32 xmitframe_direct(struct adapter *adapt, struct xmit_frame *pxmitframe) -{ - s32 res; - - res = rtw_xmitframe_coalesce(adapt, pxmitframe->pkt, pxmitframe); - if (res == _SUCCESS) - rtw_dump_xframe(adapt, pxmitframe); - else - DBG_88E("==> %s xmitframe_coalsece failed\n", __func__); - return res; -} - /* * Return * true dump packet directly @@ -648,7 +636,12 @@ s32 rtw_hal_xmit(struct adapter *adapt, struct xmit_frame *pxmitframe) pxmitframe->buf_addr = pxmitbuf->pbuf; pxmitbuf->priv_data = pxmitframe; - if (xmitframe_direct(adapt, pxmitframe) != _SUCCESS) { + res = rtw_xmitframe_coalesce(adapt, pxmitframe->pkt, pxmitframe); + + if (res == _SUCCESS) { + rtw_dump_xframe(adapt, pxmitframe); + } else { + DBG_88E("==> %s xmitframe_coalsece failed\n", __func__); rtw_free_xmitbuf(pxmitpriv, pxmitbuf); rtw_free_xmitframe(pxmitpriv, pxmitframe); } -- cgit v0.10.2 From 111e4e5ac225a2b517994ae499fde729c7e4c551 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Mon, 19 Sep 2016 00:24:54 +0700 Subject: staging: r8188eu: remove pkt_hdrlen member of pkt_attrib structure pkt_hdrlen has a constant value. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c index be7fe74..e028ff4 100644 --- a/drivers/staging/rtl8188eu/core/rtw_xmit.c +++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c @@ -511,8 +511,6 @@ static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct p } pattrib->ack_policy = 0; - /* get ether_hdr_len */ - pattrib->pkt_hdrlen = ETH_HLEN;/* pattrib->ether_type == 0x8100) ? (14 + 4): 14; vlan tag */ pattrib->hdrlen = WLAN_HDR_A3_LEN; pattrib->subtype = WIFI_DATA_TYPE; @@ -995,7 +993,7 @@ s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, struct } _rtw_open_pktfile(pkt, &pktfile); - _rtw_pktfile_read(&pktfile, NULL, pattrib->pkt_hdrlen); + _rtw_pktfile_read(&pktfile, NULL, ETH_HLEN); frg_inx = 0; frg_len = pxmitpriv->frag_len - 4;/* 2346-4 = 2342 */ diff --git a/drivers/staging/rtl8188eu/include/rtw_xmit.h b/drivers/staging/rtl8188eu/include/rtw_xmit.h index cb49aca..dd6b7a9 100644 --- a/drivers/staging/rtl8188eu/include/rtw_xmit.h +++ b/drivers/staging/rtl8188eu/include/rtw_xmit.h @@ -113,7 +113,6 @@ struct pkt_attrib { u8 dhcp_pkt; u16 ether_type; u16 seqnum; - u16 pkt_hdrlen; /* the original 802.3 pkt header len */ u16 hdrlen; /* the WLAN Header Len */ u32 pktlen; /* the original 802.3 pkt raw_data len (not include * ether_hdr data) */ -- cgit v0.10.2 From 8fc01db37dfe00f748eb548d304640fc3148b2ab Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Mon, 19 Sep 2016 00:25:25 +0700 Subject: staging: r8188eu: delete rtw_usb_bulk_size_boundary function This function does not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/usb_ops_linux.h b/drivers/staging/rtl8188eu/include/usb_ops_linux.h index fde7753..78d9b6e 100644 --- a/drivers/staging/rtl8188eu/include/usb_ops_linux.h +++ b/drivers/staging/rtl8188eu/include/usb_ops_linux.h @@ -47,21 +47,6 @@ #define usb_read_interrupt_complete(purb, regs) \ usb_read_interrupt_complete(purb) -static inline u8 rtw_usb_bulk_size_boundary(struct adapter *padapter, - int buf_len) -{ - u8 rst = true; - struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); - - if (pdvobjpriv->ishighspeed) - rst = (0 == (buf_len) % USB_HIGH_SPEED_BULK_SIZE) ? - true : false; - else - rst = (0 == (buf_len) % USB_FULL_SPEED_BULK_SIZE) ? - true : false; - return rst; -} - unsigned int ffaddr2pipehdl(struct dvobj_priv *pdvobj, u32 addr); u8 usb_read8(struct adapter *adapter, u32 addr); -- cgit v0.10.2 From fb1134087568dad2b974669ebcee09718b7fdc80 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Mon, 19 Sep 2016 00:25:40 +0700 Subject: staging: r8188eu: replace N_BYTE_ALIGMENT macro with PTR_ALIGN PTR_ALIGN is a bit shorter than N_BYTE_ALIGMENT. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c index 1063617..b87cbbb 100644 --- a/drivers/staging/rtl8188eu/core/rtw_recv.c +++ b/drivers/staging/rtl8188eu/core/rtw_recv.c @@ -73,7 +73,7 @@ int _rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter) if (!precvpriv->pallocated_frame_buf) return _FAIL; - precvpriv->precv_frame_buf = (u8 *)N_BYTE_ALIGMENT((size_t)(precvpriv->pallocated_frame_buf), RXFRAME_ALIGN_SZ); + precvpriv->precv_frame_buf = PTR_ALIGN(precvpriv->pallocated_frame_buf, RXFRAME_ALIGN_SZ); precvframe = (struct recv_frame *)precvpriv->precv_frame_buf; diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c index e028ff4..56c6604 100644 --- a/drivers/staging/rtl8188eu/core/rtw_xmit.c +++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c @@ -86,7 +86,7 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) res = _FAIL; goto exit; } - pxmitpriv->pxmit_frame_buf = (u8 *)N_BYTE_ALIGMENT((size_t)(pxmitpriv->pallocated_frame_buf), 4); + pxmitpriv->pxmit_frame_buf = PTR_ALIGN(pxmitpriv->pallocated_frame_buf, 4); /* pxmitpriv->pxmit_frame_buf = pxmitpriv->pallocated_frame_buf + 4 - */ /* ((size_t) (pxmitpriv->pallocated_frame_buf) &3); */ @@ -124,7 +124,7 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) goto exit; } - pxmitpriv->pxmitbuf = (u8 *)N_BYTE_ALIGMENT((size_t)(pxmitpriv->pallocated_xmitbuf), 4); + pxmitpriv->pxmitbuf = PTR_ALIGN(pxmitpriv->pallocated_xmitbuf, 4); /* pxmitpriv->pxmitbuf = pxmitpriv->pallocated_xmitbuf + 4 - */ /* ((size_t) (pxmitpriv->pallocated_xmitbuf) &3); */ @@ -166,7 +166,7 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) goto exit; } - pxmitpriv->pxmit_extbuf = (u8 *)N_BYTE_ALIGMENT((size_t)(pxmitpriv->pallocated_xmit_extbuf), 4); + pxmitpriv->pxmit_extbuf = PTR_ALIGN(pxmitpriv->pallocated_xmit_extbuf, 4); pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf; diff --git a/drivers/staging/rtl8188eu/include/basic_types.h b/drivers/staging/rtl8188eu/include/basic_types.h index 2c1676d..69c4d49 100644 --- a/drivers/staging/rtl8188eu/include/basic_types.h +++ b/drivers/staging/rtl8188eu/include/basic_types.h @@ -137,8 +137,4 @@ value to host byte ordering.*/ ((((u8)__val) & BIT_LEN_MASK_8(__bitlen)) << (__bitoffset)) \ ) -/* Get the N-bytes aligment offset from the current length */ -#define N_BYTE_ALIGMENT(__value, __aligment) ((__aligment == 1) ? \ - (__value) : (((__value + __aligment - 1) / __aligment) * __aligment)) - #endif /* __BASIC_TYPES_H__ */ diff --git a/drivers/staging/rtl8188eu/os_dep/xmit_linux.c b/drivers/staging/rtl8188eu/os_dep/xmit_linux.c index 221e275..4b1b04e 100644 --- a/drivers/staging/rtl8188eu/os_dep/xmit_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/xmit_linux.c @@ -72,7 +72,7 @@ int rtw_os_xmit_resource_alloc(struct adapter *padapter, struct xmit_buf *pxmitb if (pxmitbuf->pallocated_buf == NULL) return _FAIL; - pxmitbuf->pbuf = (u8 *)N_BYTE_ALIGMENT((size_t)(pxmitbuf->pallocated_buf), XMITBUF_ALIGN_SZ); + pxmitbuf->pbuf = PTR_ALIGN(pxmitbuf->pallocated_buf, XMITBUF_ALIGN_SZ); pxmitbuf->dma_transfer_addr = 0; for (i = 0; i < 8; i++) { -- cgit v0.10.2 From 6955832f1375eb29b005128c51df0b73c209fcba Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Mon, 19 Sep 2016 00:26:16 +0700 Subject: staging: r8188eu: remove rtl8188eu_set_hal_ops function rtl8188eu_set_hal_ops only allocates HalData member of adapter structure. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index cc27d64..a3c4334 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -2040,10 +2040,3 @@ void rtw_hal_def_value_init(struct adapter *adapt) for (i = 0; i < HP_THERMAL_NUM; i++) haldata->odmpriv.RFCalibrateInfo.ThermalValue_HP[i] = 0; } - -void rtl8188eu_set_hal_ops(struct adapter *adapt) -{ - adapt->HalData = kzalloc(sizeof(struct hal_data_8188e), GFP_KERNEL); - if (!adapt->HalData) - DBG_88E("cant not alloc memory for HAL DATA\n"); -} diff --git a/drivers/staging/rtl8188eu/include/usb_hal.h b/drivers/staging/rtl8188eu/include/usb_hal.h index fd9921f..3bcf74f 100644 --- a/drivers/staging/rtl8188eu/include/usb_hal.h +++ b/drivers/staging/rtl8188eu/include/usb_hal.h @@ -15,6 +15,4 @@ #ifndef __USB_HAL_H__ #define __USB_HAL_H__ -void rtl8188eu_set_hal_ops(struct adapter *padapter); - #endif /* __USB_HAL_H__ */ diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c index cf33f65..3da2ab0 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c @@ -28,6 +28,8 @@ #include <usb_hal.h> #include <rtw_ioctl.h> +#include "rtl8188e_hal.h" + #define USB_VENDER_ID_REALTEK 0x0bda /* DID_USB_v916_20130116 */ @@ -361,8 +363,9 @@ static struct adapter *rtw_usb_if1_init(struct dvobj_priv *dvobj, padapter->pmondev = pmondev; } - /* step 2. hook HalFunc, allocate HalData */ - rtl8188eu_set_hal_ops(padapter); + padapter->HalData = kzalloc(sizeof(struct hal_data_8188e), GFP_KERNEL); + if (!padapter->HalData) + DBG_88E("cant not alloc memory for HAL DATA\n"); padapter->intf_start = &usb_intf_start; padapter->intf_stop = &usb_intf_stop; -- cgit v0.10.2 From 77c13d04925819bfb5cd5d35da75e62c1adc0c4c Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Mon, 19 Sep 2016 00:26:29 +0700 Subject: staging: r8188eu: remove usb_hal.h usb_hal.h is empty. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index 12fde45..a11c7b4 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -17,7 +17,6 @@ #include <osdep_service.h> #include <drv_types.h> #include <hal_intf.h> -#include <usb_hal.h> uint rtw_hal_init(struct adapter *adapt) { diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index a3c4334..c4a8f41 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -21,7 +21,6 @@ #include <rtl8188e_hal.h> #include <rtl8188e_led.h> #include <rtw_iol.h> -#include <usb_hal.h> #include <phy.h> #define HAL_BB_ENABLE 1 diff --git a/drivers/staging/rtl8188eu/include/usb_hal.h b/drivers/staging/rtl8188eu/include/usb_hal.h deleted file mode 100644 index 3bcf74f..0000000 --- a/drivers/staging/rtl8188eu/include/usb_hal.h +++ /dev/null @@ -1,18 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#ifndef __USB_HAL_H__ -#define __USB_HAL_H__ - -#endif /* __USB_HAL_H__ */ diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c index 79b1755..40691f1 100644 --- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c +++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c @@ -23,8 +23,6 @@ #include <rtw_ioctl.h> #include <rtl8188e_hal.h> -#include <usb_hal.h> - MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Realtek Wireless Lan Driver"); MODULE_AUTHOR("Realtek Semiconductor Corp."); diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c index 3da2ab0..b2bc09e 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c @@ -25,7 +25,6 @@ #include <osdep_intf.h> #include <usb_ops_linux.h> -#include <usb_hal.h> #include <rtw_ioctl.h> #include "rtl8188e_hal.h" -- cgit v0.10.2 From 693882a56d974ca4233f9beb5aac585d123af175 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Mon, 19 Sep 2016 00:27:16 +0700 Subject: staging: r8188eu: remove HW_VAR_DM_FLAG member of hw_variables enumeration rtw_hal_set_hwreg and rtw_hal_get_hwreg does not used with HW_VAR_DM_FLAG parameter. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index c4a8f41..897e469 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -1498,9 +1498,6 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) case HW_VAR_SEC_CFG: usb_write8(Adapter, REG_SECCFG, *((u8 *)val)); break; - case HW_VAR_DM_FLAG: - podmpriv->SupportAbility = *((u8 *)val); - break; case HW_VAR_DM_FUNC_OP: if (val[0]) podmpriv->BK_SupportAbility = podmpriv->SupportAbility; @@ -1769,7 +1766,6 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) void rtw_hal_get_hwreg(struct adapter *Adapter, u8 variable, u8 *val) { struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); - struct odm_dm_struct *podmpriv = &haldata->odmpriv; switch (variable) { case HW_VAR_BASIC_RATE: @@ -1781,9 +1777,6 @@ void rtw_hal_get_hwreg(struct adapter *Adapter, u8 variable, u8 *val) /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2 */ val[0] = (BIT(0) & usb_read8(Adapter, REG_TDECTRL+2)) ? true : false; break; - case HW_VAR_DM_FLAG: - val[0] = podmpriv->SupportAbility; - break; case HW_VAR_RF_TYPE: val[0] = haldata->rf_type; break; diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index 0c0fa35..fa032b0 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -58,7 +58,6 @@ enum hw_variables { HW_VAR_SEC_CFG, HW_VAR_BCN_VALID, HW_VAR_RF_TYPE, - HW_VAR_DM_FLAG, HW_VAR_DM_FUNC_OP, HW_VAR_DM_FUNC_SET, HW_VAR_DM_FUNC_CLR, -- cgit v0.10.2 From 47f7bd29b9bf60b909ca2879f4ba096acebbfe81 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Mon, 19 Sep 2016 00:27:32 +0700 Subject: staging: r8188eu: set correct type for HalData member of adapter structure To avoid unnecessary typecast. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/drv_types.h b/drivers/staging/rtl8188eu/include/drv_types.h index 7af690e..5c275fb 100644 --- a/drivers/staging/rtl8188eu/include/drv_types.h +++ b/drivers/staging/rtl8188eu/include/drv_types.h @@ -154,7 +154,7 @@ struct adapter { struct eeprom_priv eeprompriv; struct led_priv ledpriv; - void *HalData; + struct hal_data_8188e *HalData; s32 bDriverStopped; s32 bSurpriseRemoved; -- cgit v0.10.2 From bc15ada3dc74e2004749c3d49bcbc0debb6ec878 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Mon, 19 Sep 2016 00:27:43 +0700 Subject: staging: r8188eu: remove GET_RF_TYPE macro This macro does not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h index 418bdb9..5362218 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h @@ -353,7 +353,6 @@ struct hal_data_8188e { #define GET_HAL_DATA(__pAdapter) \ ((struct hal_data_8188e *)((__pAdapter)->HalData)) -#define GET_RF_TYPE(priv) (GET_HAL_DATA(priv)->rf_type) /* rtl8188e_hal_init.c */ void _8051Reset88E(struct adapter *padapter); -- cgit v0.10.2 From 177aa53a0d11b258a6615a042380fe7abf15d780 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Mon, 19 Sep 2016 00:28:06 +0700 Subject: staging: r8188eu: remove GET_HAL_DATA macro GET_HAL_DATA replaced by its definition. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_sreset.c b/drivers/staging/rtl8188eu/core/rtw_sreset.c index 5d631c5..a198c57 100644 --- a/drivers/staging/rtl8188eu/core/rtw_sreset.c +++ b/drivers/staging/rtl8188eu/core/rtw_sreset.c @@ -18,16 +18,14 @@ void rtw_hal_sreset_init(struct adapter *padapter) { - struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter); - struct sreset_priv *psrtpriv = &pHalData->srestpriv; + struct sreset_priv *psrtpriv = &padapter->HalData->srestpriv; psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS; } u8 sreset_get_wifi_status(struct adapter *padapter) { - struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter); - struct sreset_priv *psrtpriv = &pHalData->srestpriv; + struct sreset_priv *psrtpriv = &padapter->HalData->srestpriv; u8 status = WIFI_STATUS_SUCCESS; u32 val32 = 0; @@ -54,6 +52,5 @@ u8 sreset_get_wifi_status(struct adapter *padapter) void sreset_set_wifi_error_status(struct adapter *padapter, u32 status) { - struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter); - pHalData->srestpriv.Wifi_Error_Status = status; + padapter->HalData->srestpriv.Wifi_Error_Status = status; } diff --git a/drivers/staging/rtl8188eu/hal/bb_cfg.c b/drivers/staging/rtl8188eu/hal/bb_cfg.c index cce1ea2..c349923 100644 --- a/drivers/staging/rtl8188eu/hal/bb_cfg.c +++ b/drivers/staging/rtl8188eu/hal/bb_cfg.c @@ -498,7 +498,7 @@ static u32 array_phy_reg_pg_8188e[] = { static void store_pwrindex_offset(struct adapter *adapter, u32 regaddr, u32 bitmask, u32 data) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapter); + struct hal_data_8188e *hal_data = adapter->HalData; u32 * const power_level_offset = hal_data->MCSTxPowerLevelOriginalOffset[hal_data->pwrGroupCnt]; @@ -588,11 +588,10 @@ static bool config_bb_with_pgheader(struct adapter *adapt) static void rtl88e_phy_init_bb_rf_register_definition(struct adapter *adapter) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapter); struct bb_reg_def *reg[4]; - reg[RF_PATH_A] = &hal_data->PHYRegDef[RF_PATH_A]; - reg[RF_PATH_B] = &hal_data->PHYRegDef[RF_PATH_B]; + reg[RF_PATH_A] = &adapter->HalData->PHYRegDef[RF_PATH_A]; + reg[RF_PATH_B] = &adapter->HalData->PHYRegDef[RF_PATH_B]; reg[RF_PATH_A]->rfintfs = rFPGA0_XAB_RFInterfaceSW; reg[RF_PATH_B]->rfintfs = rFPGA0_XAB_RFInterfaceSW; @@ -652,13 +651,12 @@ static void rtl88e_phy_init_bb_rf_register_definition(struct adapter *adapter) static bool config_parafile(struct adapter *adapt) { struct eeprom_priv *eeprom = GET_EEPROM_EFUSE_PRIV(adapt); - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); set_baseband_phy_config(adapt); /* If EEPROM or EFUSE autoload OK, We must config by PHY_REG_PG.txt */ if (!eeprom->bautoload_fail_flag) { - hal_data->pwrGroupCnt = 0; + adapt->HalData->pwrGroupCnt = 0; config_bb_with_pgheader(adapt); } set_baseband_agc_config(adapt); @@ -668,7 +666,6 @@ static bool config_parafile(struct adapter *adapt) bool rtl88eu_phy_bb_config(struct adapter *adapt) { int rtstatus = true; - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); u32 regval; u8 crystal_cap; @@ -688,7 +685,7 @@ bool rtl88eu_phy_bb_config(struct adapter *adapt) rtstatus = config_parafile(adapt); /* write 0x24[16:11] = 0x24[22:17] = crystal_cap */ - crystal_cap = hal_data->CrystalCap & 0x3F; + crystal_cap = adapt->HalData->CrystalCap & 0x3F; phy_set_bb_reg(adapt, REG_AFE_XTAL_CTRL, 0x7ff800, (crystal_cap | (crystal_cap << 6))); diff --git a/drivers/staging/rtl8188eu/hal/odm.c b/drivers/staging/rtl8188eu/hal/odm.c index d1c9ef3..0677474 100644 --- a/drivers/staging/rtl8188eu/hal/odm.c +++ b/drivers/staging/rtl8188eu/hal/odm.c @@ -912,8 +912,7 @@ bool ODM_RAStateCheck(struct odm_dm_struct *pDM_Odm, s32 RSSI, bool bForceUpdate void odm_DynamicTxPowerInit(struct odm_dm_struct *pDM_Odm) { struct adapter *Adapter = pDM_Odm->Adapter; - struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; + struct dm_priv *pdmpriv = &Adapter->HalData->dmpriv; pdmpriv->bDynamicTxPowerEnable = false; pdmpriv->LastDTPLvl = TxHighPwrLevel_Normal; pdmpriv->DynamicTxHighPowerLvl = TxHighPwrLevel_Normal; @@ -938,8 +937,7 @@ void odm_RSSIMonitorCheck(struct odm_dm_struct *pDM_Odm) static void FindMinimumRSSI(struct adapter *pAdapter) { - struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; + struct dm_priv *pdmpriv = &pAdapter->HalData->dmpriv; /* 1 1.Unconditionally set RSSI */ pdmpriv->MinUndecoratedPWDBForDM = pdmpriv->EntryMinUndecoratedSmoothedPWDB; @@ -948,8 +946,7 @@ static void FindMinimumRSSI(struct adapter *pAdapter) void odm_RSSIMonitorCheckCE(struct odm_dm_struct *pDM_Odm) { struct adapter *Adapter = pDM_Odm->Adapter; - struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter); - struct dm_priv *pdmpriv = &pHalData->dmpriv; + struct dm_priv *pdmpriv = &Adapter->HalData->dmpriv; int i; int tmpEntryMaxPWDB = 0, tmpEntryMinPWDB = 0xff; u8 sta_cnt = 0; @@ -978,7 +975,7 @@ void odm_RSSIMonitorCheckCE(struct odm_dm_struct *pDM_Odm) for (i = 0; i < sta_cnt; i++) { if (PWDB_rssi[i] != 0) { - ODM_RA_SetRSSI_8188E(&pHalData->odmpriv, + ODM_RA_SetRSSI_8188E(&Adapter->HalData->odmpriv, PWDB_rssi[i] & 0xFF, (PWDB_rssi[i] >> 16) & 0xFF); } @@ -995,7 +992,7 @@ void odm_RSSIMonitorCheckCE(struct odm_dm_struct *pDM_Odm) pdmpriv->EntryMinUndecoratedSmoothedPWDB = 0; FindMinimumRSSI(Adapter); - pHalData->odmpriv.RSSI_Min = pdmpriv->MinUndecoratedPWDBForDM; + Adapter->HalData->odmpriv.RSSI_Min = pdmpriv->MinUndecoratedPWDBForDM; } /* 3============================================================ */ @@ -1105,7 +1102,6 @@ void odm_EdcaTurboCheckCE(struct odm_dm_struct *pDM_Odm) u64 cur_tx_bytes = 0; u64 cur_rx_bytes = 0; u8 bbtchange = false; - struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter); struct xmit_priv *pxmitpriv = &(Adapter->xmitpriv); struct recv_priv *precvpriv = &(Adapter->recvpriv); struct registry_priv *pregpriv = &Adapter->registrypriv; @@ -1159,7 +1155,8 @@ void odm_EdcaTurboCheckCE(struct odm_dm_struct *pDM_Odm) /* Turn Off EDCA turbo here. */ /* Restore original EDCA according to the declaration of AP. */ if (pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA) { - usb_write32(Adapter, REG_EDCA_BE_PARAM, pHalData->AcParam_BE); + usb_write32(Adapter, REG_EDCA_BE_PARAM, + Adapter->HalData->AcParam_BE); pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = false; } } diff --git a/drivers/staging/rtl8188eu/hal/phy.c b/drivers/staging/rtl8188eu/hal/phy.c index 776e5b8..4e3c2e6 100644 --- a/drivers/staging/rtl8188eu/hal/phy.c +++ b/drivers/staging/rtl8188eu/hal/phy.c @@ -65,8 +65,7 @@ static u32 rf_serial_read(struct adapter *adapt, enum rf_radio_path rfpath, u32 offset) { u32 ret = 0; - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); - struct bb_reg_def *phyreg = &hal_data->PHYRegDef[rfpath]; + struct bb_reg_def *phyreg = &adapt->HalData->PHYRegDef[rfpath]; u32 tmplong, tmplong2; u8 rfpi_enable = 0; @@ -110,8 +109,7 @@ static void rf_serial_write(struct adapter *adapt, u32 data) { u32 data_and_addr = 0; - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); - struct bb_reg_def *phyreg = &hal_data->PHYRegDef[rfpath]; + struct bb_reg_def *phyreg = &adapt->HalData->PHYRegDef[rfpath]; offset &= 0xff; data_and_addr = ((offset<<20) | (data&0x000fffff)) & 0x0fffffff; @@ -147,7 +145,7 @@ void phy_set_rf_reg(struct adapter *adapt, enum rf_radio_path rf_path, static void get_tx_power_index(struct adapter *adapt, u8 channel, u8 *cck_pwr, u8 *ofdm_pwr, u8 *bw20_pwr, u8 *bw40_pwr) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); + struct hal_data_8188e *hal_data = adapt->HalData; u8 index = (channel - 1); u8 TxCount = 0, path_nums; @@ -183,7 +181,7 @@ 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 = GET_HAL_DATA(adapt); + struct hal_data_8188e *hal_data = adapt->HalData; hal_data->CurrentCckTxPwrIdx = cck_pwr[0]; hal_data->CurrentOfdm24GTxPwrIdx = ofdm_pwr[0]; @@ -211,7 +209,7 @@ void phy_set_tx_power_level(struct adapter *adapt, u8 channel) static void phy_set_bw_mode_callback(struct adapter *adapt) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); + struct hal_data_8188e *hal_data = adapt->HalData; u8 reg_bw_opmode; u8 reg_prsr_rsc; @@ -277,7 +275,7 @@ static void phy_set_bw_mode_callback(struct adapter *adapt) void rtw_hal_set_bwmode(struct adapter *adapt, enum ht_channel_width bandwidth, unsigned char offset) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); + struct hal_data_8188e *hal_data = adapt->HalData; enum ht_channel_width tmp_bw = hal_data->CurrentChannelBW; hal_data->CurrentChannelBW = bandwidth; @@ -293,7 +291,7 @@ static void phy_sw_chnl_callback(struct adapter *adapt, u8 channel) { u8 rf_path; u32 param1, param2; - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); + struct hal_data_8188e *hal_data = adapt->HalData; phy_set_tx_power_level(adapt, channel); @@ -309,7 +307,7 @@ static void phy_sw_chnl_callback(struct adapter *adapt, u8 channel) void rtw_hal_set_chan(struct adapter *adapt, u8 channel) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); + struct hal_data_8188e *hal_data = adapt->HalData; u8 tmpchannel = hal_data->CurrentChannel; if (hal_data->rf_chip == RF_PSEUDO_11N) @@ -404,7 +402,7 @@ static void dm_txpwr_track_setpwr(struct odm_dm_struct *dm_odm) void rtl88eu_dm_txpower_tracking_callback_thermalmeter(struct adapter *adapt) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); + struct hal_data_8188e *hal_data = adapt->HalData; u8 thermal_val = 0, delta, delta_lck, delta_iqk, offset; u8 thermal_avg_count = 0; u32 thermal_avg = 0; @@ -629,8 +627,7 @@ 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 hal_data_8188e *hal_data = GET_HAL_DATA(adapt); - struct odm_dm_struct *dm_odm = &hal_data->odmpriv; + struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv; /* 1 Get TXIMR setting */ /* modify RXIQK mode table */ @@ -734,8 +731,7 @@ static u8 phy_path_b_iqk(struct adapter *adapt) { u32 regeac, regeb4, regebc, regec4, regecc; u8 result = 0x00; - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); - struct odm_dm_struct *dm_odm = &hal_data->odmpriv; + 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); @@ -951,8 +947,7 @@ static bool simularity_compare(struct adapter *adapt, s32 resulta[][8], u8 c1, u8 c2) { u32 i, j, diff, sim_bitmap = 0, bound; - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); - struct odm_dm_struct *dm_odm = &hal_data->odmpriv; + struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv; u8 final_candidate[2] = {0xFF, 0xFF}; /* for path A and path B */ bool result = true; s32 tmp1 = 0, tmp2 = 0; @@ -1030,8 +1025,7 @@ static bool simularity_compare(struct adapter *adapt, s32 resulta[][8], static void phy_iq_calibrate(struct adapter *adapt, s32 result[][8], u8 t, bool is2t) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); - struct odm_dm_struct *dm_odm = &hal_data->odmpriv; + struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv; u32 i; u8 path_a_ok, path_b_ok; u32 adda_reg[IQK_ADDA_REG_NUM] = { @@ -1276,8 +1270,7 @@ static void phy_lc_calibrate(struct adapter *adapt, bool is2t) void rtl88eu_phy_iq_calibrate(struct adapter *adapt, bool recovery) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); - struct odm_dm_struct *dm_odm = &hal_data->odmpriv; + struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv; s32 result[4][8]; u8 i, final, chn_index; bool pathaok, pathbok; @@ -1388,7 +1381,7 @@ void rtl88eu_phy_iq_calibrate(struct adapter *adapt, bool recovery) (reg_ec4 == 0)); } - chn_index = get_right_chnl_for_iqk(hal_data->CurrentChannel); + chn_index = get_right_chnl_for_iqk(adapt->HalData->CurrentChannel); if (final < 4) { for (i = 0; i < IQK_Matrix_REG_NUM; i++) @@ -1404,8 +1397,7 @@ void rtl88eu_phy_lc_calibrate(struct adapter *adapt) { bool singletone = false, carrier_sup = false; u32 timeout = 2000, timecount = 0; - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); - struct odm_dm_struct *dm_odm = &hal_data->odmpriv; + struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv; if (!(dm_odm->SupportAbility & ODM_RF_CALIBRATION)) return; diff --git a/drivers/staging/rtl8188eu/hal/rf.c b/drivers/staging/rtl8188eu/hal/rf.c index 1596274..2f3edf0 100644 --- a/drivers/staging/rtl8188eu/hal/rf.c +++ b/drivers/staging/rtl8188eu/hal/rf.c @@ -22,7 +22,7 @@ void rtl88eu_phy_rf6052_set_bandwidth(struct adapter *adapt, enum ht_channel_width bandwidth) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); + struct hal_data_8188e *hal_data = adapt->HalData; switch (bandwidth) { case HT_CHANNEL_WIDTH_20: @@ -44,7 +44,7 @@ void rtl88eu_phy_rf6052_set_bandwidth(struct adapter *adapt, void rtl88eu_phy_rf6052_set_cck_txpower(struct adapter *adapt, u8 *powerlevel) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); + struct hal_data_8188e *hal_data = adapt->HalData; struct dm_priv *pdmpriv = &hal_data->dmpriv; struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv; u32 tx_agc[2] = {0, 0}, tmpval = 0, pwrtrac_value; @@ -129,7 +129,6 @@ static void getpowerbase88e(struct adapter *adapt, u8 *pwr_level_ofdm, u8 *pwr_level_bw20, u8 *pwr_level_bw40, u8 channel, u32 *ofdmbase, u32 *mcs_base) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); u32 powerbase0, powerbase1; u8 i, powerlevel[2]; @@ -140,9 +139,9 @@ static void getpowerbase88e(struct adapter *adapt, u8 *pwr_level_ofdm, (powerbase0<<8) | powerbase0; *(ofdmbase+i) = powerbase0; } - for (i = 0; i < hal_data->NumTotalRFPath; i++) { + for (i = 0; i < adapt->HalData->NumTotalRFPath; i++) { /* Check HT20 to HT40 diff */ - if (hal_data->CurrentChannelBW == HT_CHANNEL_WIDTH_20) + if (adapt->HalData->CurrentChannelBW == HT_CHANNEL_WIDTH_20) powerlevel[i] = pwr_level_bw20[i]; else powerlevel[i] = pwr_level_bw40[i]; @@ -156,7 +155,7 @@ static void get_rx_power_val_by_reg(struct adapter *adapt, u8 channel, u8 index, u32 *powerbase0, u32 *powerbase1, u32 *out_val) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); + struct hal_data_8188e *hal_data = adapt->HalData; struct dm_priv *pdmpriv = &hal_data->dmpriv; u8 i, chnlGroup = 0, pwr_diff_limit[4], customer_pwr_limit; s8 pwr_diff = 0; @@ -286,7 +285,6 @@ void rtl88eu_phy_rf6052_set_ofdm_txpower(struct adapter *adapt, u8 *pwr_level_bw20, u8 *pwr_level_bw40, u8 channel) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); u32 write_val[2], powerbase0[2], powerbase1[2], pwrtrac_value; u8 direction; u8 index = 0; @@ -294,8 +292,8 @@ void rtl88eu_phy_rf6052_set_ofdm_txpower(struct adapter *adapt, getpowerbase88e(adapt, pwr_level_ofdm, pwr_level_bw20, pwr_level_bw40, channel, &powerbase0[0], &powerbase1[0]); - rtl88eu_dm_txpower_track_adjust(&hal_data->odmpriv, 0, &direction, - &pwrtrac_value); + rtl88eu_dm_txpower_track_adjust(&adapt->HalData->odmpriv, 0, + &direction, &pwrtrac_value); for (index = 0; index < 6; index++) { get_rx_power_val_by_reg(adapt, channel, index, diff --git a/drivers/staging/rtl8188eu/hal/rf_cfg.c b/drivers/staging/rtl8188eu/hal/rf_cfg.c index 453f9e7..dc26ad3 100644 --- a/drivers/staging/rtl8188eu/hal/rf_cfg.c +++ b/drivers/staging/rtl8188eu/hal/rf_cfg.c @@ -19,7 +19,7 @@ static bool check_condition(struct adapter *adapt, const u32 condition) { - struct odm_dm_struct *odm = &GET_HAL_DATA(adapt)->odmpriv; + struct odm_dm_struct *odm = &adapt->HalData->odmpriv; u32 _board = odm->BoardType; u32 _platform = odm->SupportPlatform; u32 _interface = odm->SupportInterface; @@ -228,7 +228,7 @@ static bool rtl88e_phy_config_rf_with_headerfile(struct adapter *adapt) static bool rf6052_conf_para(struct adapter *adapt) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); + struct hal_data_8188e *hal_data = adapt->HalData; u32 u4val = 0; u8 rfpath; bool rtstatus = true; @@ -299,7 +299,7 @@ static bool rf6052_conf_para(struct adapter *adapt) static bool rtl88e_phy_rf6052_config(struct adapter *adapt) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt); + struct hal_data_8188e *hal_data = adapt->HalData; if (hal_data->rf_type == RF_1T1R) hal_data->NumTotalRFPath = 1; diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c index 18f69b8..4e7cef3 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c @@ -60,7 +60,6 @@ static s32 FillH2CCmd_88E(struct adapter *adapt, u8 ElementID, u32 CmdLen, u8 *p u8 h2c_box_num; u32 msgbox_addr; u32 msgbox_ex_addr; - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); u8 cmd_idx, ext_cmd_len; u32 h2c_cmd = 0; u32 h2c_cmd_ex = 0; @@ -81,7 +80,7 @@ static s32 FillH2CCmd_88E(struct adapter *adapt, u8 ElementID, u32 CmdLen, u8 *p /* pay attention to if race condition happened in H2C cmd setting. */ do { - h2c_box_num = haldata->LastHMEBoxNum; + h2c_box_num = adapt->HalData->LastHMEBoxNum; if (!_is_fw_read_cmd_down(adapt, h2c_box_num)) { DBG_88E(" fw read cmd failed...\n"); @@ -110,7 +109,8 @@ static s32 FillH2CCmd_88E(struct adapter *adapt, u8 ElementID, u32 CmdLen, u8 *p } bcmd_down = true; - haldata->LastHMEBoxNum = (h2c_box_num+1) % RTL88E_MAX_H2C_BOX_NUMS; + adapt->HalData->LastHMEBoxNum = + (h2c_box_num+1) % RTL88E_MAX_H2C_BOX_NUMS; } while ((!bcmd_down) && (retry_cnts--)); @@ -128,7 +128,7 @@ exit: /* arg[5] = Short GI */ void rtw_hal_add_ra_tid(struct adapter *pAdapter, u32 bitmap, u8 arg, u8 rssi_level) { - struct hal_data_8188e *haldata = GET_HAL_DATA(pAdapter); + struct odm_dm_struct *odmpriv = &pAdapter->HalData->odmpriv; u8 macid, init_rate, raid, shortGIrate = false; @@ -138,7 +138,7 @@ void rtw_hal_add_ra_tid(struct adapter *pAdapter, u32 bitmap, u8 arg, u8 rssi_le bitmap &= 0x0fffffff; if (rssi_level != DM_RATR_STA_INIT) - bitmap = ODM_Get_Rate_Bitmap(&haldata->odmpriv, macid, bitmap, rssi_level); + bitmap = ODM_Get_Rate_Bitmap(odmpriv, macid, bitmap, rssi_level); bitmap |= ((raid<<28)&0xf0000000); @@ -156,7 +156,7 @@ void rtw_hal_add_ra_tid(struct adapter *pAdapter, u32 bitmap, u8 arg, u8 rssi_le 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(&(haldata->odmpriv), macid, raid, bitmap, shortGIrate); + ODM_RA_UpdateRateInfo_8188E(odmpriv, macid, raid, bitmap, shortGIrate); } void rtl8188e_set_FwPwrMode_cmd(struct adapter *adapt, u8 Mode) @@ -445,7 +445,6 @@ static void ConstructProbeRsp(struct adapter *adapt, u8 *pframe, u32 *pLength, u /* 2009.10.15 by tynli. */ static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished) { - struct hal_data_8188e *haldata; struct xmit_frame *pmgntframe; struct pkt_attrib *pattrib; struct xmit_priv *pxmitpriv; @@ -467,7 +466,6 @@ static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished) return; } - haldata = GET_HAL_DATA(adapt); pxmitpriv = &adapt->xmitpriv; pmlmeext = &adapt->mlmeextpriv; pmlmeinfo = &pmlmeext->mlmext_info; @@ -487,7 +485,7 @@ static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished) if (PageNeed == 1) PageNeed += 1; PageNum += PageNeed; - haldata->FwRsvdPageStartOffset = PageNum; + adapt->HalData->FwRsvdPageStartOffset = PageNum; BufIndex += PageNeed*128; @@ -554,7 +552,7 @@ exit: void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus) { - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); + struct hal_data_8188e *haldata = adapt->HalData; struct mlme_ext_priv *pmlmeext = &(adapt->mlmeextpriv); struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); bool bSendBeacon = false; diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c index 0c853fc..964b169 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c @@ -42,7 +42,7 @@ static void dm_InitGPIOSetting(struct adapter *Adapter) /* */ static void Init_ODM_ComInfo_88E(struct adapter *Adapter) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter); + struct hal_data_8188e *hal_data = Adapter->HalData; struct dm_priv *pdmpriv = &hal_data->dmpriv; struct odm_dm_struct *dm_odm = &(hal_data->odmpriv); @@ -83,7 +83,7 @@ static void Update_ODM_ComInfo_88E(struct adapter *Adapter) struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv; struct mlme_priv *pmlmepriv = &Adapter->mlmepriv; struct pwrctrl_priv *pwrctrlpriv = &Adapter->pwrctrlpriv; - struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter); + struct hal_data_8188e *hal_data = Adapter->HalData; struct odm_dm_struct *dm_odm = &(hal_data->odmpriv); struct dm_priv *pdmpriv = &hal_data->dmpriv; int i; @@ -133,9 +133,8 @@ static void Update_ODM_ComInfo_88E(struct adapter *Adapter) void rtl8188e_InitHalDm(struct adapter *Adapter) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter); - struct dm_priv *pdmpriv = &hal_data->dmpriv; - struct odm_dm_struct *dm_odm = &(hal_data->odmpriv); + struct dm_priv *pdmpriv = &Adapter->HalData->dmpriv; + struct odm_dm_struct *dm_odm = &(Adapter->HalData->odmpriv); dm_InitGPIOSetting(Adapter); pdmpriv->DM_Type = DM_Type_ByDriver; @@ -147,7 +146,6 @@ void rtl8188e_InitHalDm(struct adapter *Adapter) void rtw_hal_dm_watchdog(struct adapter *Adapter) { u8 hw_init_completed = false; - struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter); struct mlme_priv *pmlmepriv = NULL; u8 bLinked = false; @@ -169,8 +167,8 @@ void rtw_hal_dm_watchdog(struct adapter *Adapter) bLinked = true; } - hal_data->odmpriv.bLinked = bLinked; - ODM_DMWatchdog(&hal_data->odmpriv); + Adapter->HalData->odmpriv.bLinked = bLinked; + ODM_DMWatchdog(&Adapter->HalData->odmpriv); skip_dm: /* Check GPIO to determine current RF on/off and Pbc status. */ /* Check Hardware Radio ON/OFF or not */ @@ -179,9 +177,8 @@ skip_dm: void rtw_hal_dm_init(struct adapter *Adapter) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter); - struct dm_priv *pdmpriv = &hal_data->dmpriv; - struct odm_dm_struct *podmpriv = &hal_data->odmpriv; + 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); @@ -192,9 +189,7 @@ void rtw_hal_dm_init(struct adapter *Adapter) /* Compare RSSI for deciding antenna */ void rtw_hal_antdiv_rssi_compared(struct adapter *Adapter, struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter); - - if (0 != hal_data->AntDivCfg) { + if (0 != Adapter->HalData->AntDivCfg) { /* select optimum_antenna for before linked =>For antenna diversity */ if (dst->Rssi >= src->Rssi) {/* keep org parameter */ src->Rssi = dst->Rssi; @@ -206,13 +201,12 @@ void rtw_hal_antdiv_rssi_compared(struct adapter *Adapter, struct wlan_bssid_ex /* Add new function to reset the state of antenna diversity before link. */ u8 rtw_hal_antdiv_before_linked(struct adapter *Adapter) { - struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter); - struct odm_dm_struct *dm_odm = &hal_data->odmpriv; + struct odm_dm_struct *dm_odm = &Adapter->HalData->odmpriv; struct sw_ant_switch *dm_swat_tbl = &dm_odm->DM_SWAT_Table; struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv); /* Condition that does not need to use antenna diversity. */ - if (hal_data->AntDivCfg == 0) + if (Adapter->HalData->AntDivCfg == 0) return false; if (check_fwstate(pmlmepriv, _FW_LINKED)) diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c index a1812dd..a7b0375 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c @@ -108,13 +108,11 @@ void _8051Reset88E(struct adapter *padapter) void rtl8188e_InitializeFirmwareVars(struct adapter *padapter) { - struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter); - /* Init Fw LPS related. */ padapter->pwrctrlpriv.bFwCurrentInPSMode = false; /* Init H2C counter. by tynli. 2009.12.09. */ - pHalData->LastHMEBoxNum = 0; + padapter->HalData->LastHMEBoxNum = 0; } void rtw_hal_free_data(struct adapter *padapter) @@ -127,9 +125,7 @@ void rtw_hal_read_chip_version(struct adapter *padapter) { u32 value32; struct HAL_VERSION ChipVersion; - struct hal_data_8188e *pHalData; - - pHalData = GET_HAL_DATA(padapter); + struct hal_data_8188e *pHalData = padapter->HalData; value32 = usb_read32(padapter, REG_SYS_CFG); ChipVersion.ChipType = ((value32 & RTL_ID) ? TEST_CHIP : NORMAL_CHIP); @@ -147,8 +143,8 @@ void rtw_hal_read_chip_version(struct adapter *padapter) void rtw_hal_set_odm_var(struct adapter *Adapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet) { - struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter); - struct odm_dm_struct *podmpriv = &pHalData->odmpriv; + struct odm_dm_struct *podmpriv = &Adapter->HalData->odmpriv; + switch (eVariable) { case HAL_ODM_STA_INFO: { @@ -475,7 +471,7 @@ void Hal_ReadPowerSavingMode88E(struct adapter *padapter, u8 *hwinfo, bool AutoL void Hal_ReadTxPowerInfo88E(struct adapter *padapter, u8 *PROMContent, bool AutoLoadFail) { - struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter); + struct hal_data_8188e *pHalData = padapter->HalData; struct txpowerinfo24g pwrInfo24G; u8 rfPath, ch, group; u8 bIn24G, TxCount; @@ -527,7 +523,7 @@ void Hal_ReadTxPowerInfo88E(struct adapter *padapter, u8 *PROMContent, bool Auto void Hal_EfuseParseXtal_8188E(struct adapter *pAdapter, u8 *hwinfo, bool AutoLoadFail) { - struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter); + struct hal_data_8188e *pHalData = pAdapter->HalData; if (!AutoLoadFail) { pHalData->CrystalCap = hwinfo[EEPROM_XTAL_88E]; @@ -541,7 +537,7 @@ void Hal_EfuseParseXtal_8188E(struct adapter *pAdapter, u8 *hwinfo, bool AutoLoa void Hal_EfuseParseBoardType88E(struct adapter *pAdapter, u8 *hwinfo, bool AutoLoadFail) { - struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter); + struct hal_data_8188e *pHalData = pAdapter->HalData; if (!AutoLoadFail) pHalData->BoardType = (hwinfo[EEPROM_RF_BOARD_OPTION_88E] @@ -553,7 +549,7 @@ void Hal_EfuseParseBoardType88E(struct adapter *pAdapter, u8 *hwinfo, bool AutoL void Hal_EfuseParseEEPROMVer88E(struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail) { - struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter); + struct hal_data_8188e *pHalData = padapter->HalData; if (!AutoLoadFail) { pHalData->EEPROMVersion = hwinfo[EEPROM_VERSION_88E]; @@ -580,7 +576,7 @@ void rtl8188e_EfuseParseChnlPlan(struct adapter *padapter, u8 *hwinfo, bool Auto void Hal_EfuseParseCustomerID88E(struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail) { - struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter); + struct hal_data_8188e *pHalData = padapter->HalData; if (!AutoLoadFail) { pHalData->EEPROMCustomerID = hwinfo[EEPROM_CUSTOMERID_88E]; @@ -593,7 +589,7 @@ void Hal_EfuseParseCustomerID88E(struct adapter *padapter, u8 *hwinfo, bool Auto void Hal_ReadAntennaDiversity88E(struct adapter *pAdapter, u8 *PROMContent, bool AutoLoadFail) { - struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter); + struct hal_data_8188e *pHalData = pAdapter->HalData; struct registry_priv *registry_par = &pAdapter->registrypriv; if (!AutoLoadFail) { @@ -626,7 +622,7 @@ void Hal_ReadAntennaDiversity88E(struct adapter *pAdapter, u8 *PROMContent, bool void Hal_ReadThermalMeter_88E(struct adapter *Adapter, u8 *PROMContent, bool AutoloadFail) { - struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter); + struct hal_data_8188e *pHalData = Adapter->HalData; /* ThermalMeter from EEPROM */ if (!AutoloadFail) diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c b/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c index f110c96..8aea710 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c @@ -140,7 +140,6 @@ void update_recvframe_phyinfo_88e(struct recv_frame *precvframe, { struct adapter *padapter = precvframe->adapter; struct rx_pkt_attrib *pattrib = &precvframe->attrib; - struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter); struct odm_phy_status_info *pPHYInfo = (struct odm_phy_status_info *)(&pattrib->phy_info); u8 *wlanhdr; struct odm_per_pkt_info pkt_info; @@ -181,7 +180,8 @@ void update_recvframe_phyinfo_88e(struct recv_frame *precvframe, pkt_info.StationID = psta->mac_id; pkt_info.Rate = pattrib->mcs_rate; - ODM_PhyStatusQuery(&pHalData->odmpriv, pPHYInfo, (u8 *)pphy_status, &(pkt_info)); + ODM_PhyStatusQuery(&padapter->HalData->odmpriv, pPHYInfo, + (u8 *)pphy_status, &(pkt_info)); precvframe->psta = NULL; if (pkt_info.bPacketMatchBSSID && diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c index becf5b5..780666a 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c @@ -40,14 +40,13 @@ void SwLedOn(struct adapter *padapter, struct LED_871x *pLed) void SwLedOff(struct adapter *padapter, struct LED_871x *pLed) { u8 LedCfg; - struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter); if (padapter->bSurpriseRemoved || padapter->bDriverStopped) goto exit; LedCfg = usb_read8(padapter, REG_LEDCFG2);/* 0x4E */ - if (pHalData->bLedOpenDrain) { + if (padapter->HalData->bLedOpenDrain) { /* Open-drain arrangement for controlling the LED) */ LedCfg &= 0x90; /* Set to software control. */ usb_write8(padapter, REG_LEDCFG2, (LedCfg | BIT(3))); @@ -69,11 +68,10 @@ exit: void rtw_hal_sw_led_init(struct adapter *padapter) { struct led_priv *pledpriv = &(padapter->ledpriv); - struct hal_data_8188e *haldata = GET_HAL_DATA(padapter); pledpriv->bRegUseLed = true; pledpriv->LedControlHandler = LedControl8188eu; - haldata->bLedOpenDrain = true; + padapter->HalData->bLedOpenDrain = true; InitLed871x(padapter, &(pledpriv->SwLed0)); } diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c index 169d6c8..85650b2 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c @@ -33,11 +33,7 @@ s32 rtw_hal_init_xmit_priv(struct adapter *adapt) static u8 urb_zero_packet_chk(struct adapter *adapt, int sz) { - u8 set_tx_desc_offset; - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); - set_tx_desc_offset = (((sz + TXDESC_SIZE) % haldata->UsbBulkOutSize) == 0) ? 1 : 0; - - return set_tx_desc_offset; + return !((sz + TXDESC_SIZE) % adapt->HalData->UsbBulkOutSize); } static void rtl8188eu_cal_txdesc_chksum(struct tx_desc *ptxdesc) @@ -175,7 +171,7 @@ static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz, u8 bag u8 data_rate, pwr_status, offset; struct adapter *adapt = pxmitframe->padapter; struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); + struct odm_dm_struct *odmpriv = &adapt->HalData->odmpriv; struct tx_desc *ptxdesc = (struct tx_desc *)pmem; struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); @@ -259,12 +255,12 @@ static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz, u8 bag ptxdesc->txdw5 |= cpu_to_le32(0x0001ff00);/* DATA/RTS Rate FB LMT */ if (pattrib->ht_en) { - if (ODM_RA_GetShortGI_8188E(&haldata->odmpriv, pattrib->mac_id)) + if (ODM_RA_GetShortGI_8188E(odmpriv, pattrib->mac_id)) ptxdesc->txdw5 |= cpu_to_le32(SGI);/* SGI */ } - data_rate = ODM_RA_GetDecisionRate_8188E(&haldata->odmpriv, pattrib->mac_id); + data_rate = ODM_RA_GetDecisionRate_8188E(odmpriv, pattrib->mac_id); ptxdesc->txdw5 |= cpu_to_le32(data_rate & 0x3F); - pwr_status = ODM_RA_GetHwPwrStatus_8188E(&haldata->odmpriv, pattrib->mac_id); + pwr_status = ODM_RA_GetHwPwrStatus_8188E(odmpriv, pattrib->mac_id); ptxdesc->txdw4 |= cpu_to_le32((pwr_status & 0x7) << PWR_STATUS_SHT); } else { /* EAP data packet and ARP packet and DHCP. */ @@ -332,8 +328,7 @@ static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz, u8 bag ptxdesc->txdw4 |= cpu_to_le32(HW_SSN); /* Hw set sequence number */ } - rtl88eu_dm_set_tx_ant_by_tx_info(&haldata->odmpriv, pmem, - pattrib->mac_id); + 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); @@ -426,7 +421,6 @@ static u32 xmitframe_need_length(struct xmit_frame *pxmitframe) s32 rtl8188eu_xmitframe_complete(struct adapter *adapt, struct xmit_priv *pxmitpriv) { - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); struct xmit_frame *pxmitframe = NULL; struct xmit_frame *pfirstframe = NULL; struct xmit_buf *pxmitbuf; @@ -442,7 +436,7 @@ s32 rtl8188eu_xmitframe_complete(struct adapter *adapt, struct xmit_priv *pxmitp u32 pbuf_tail; /* last pkt tail */ u32 len; /* packet length, except TXDESC_SIZE and PKT_OFFSET */ - u32 bulksize = haldata->UsbBulkOutSize; + u32 bulksize = adapt->HalData->UsbBulkOutSize; u8 desc_cnt; u32 bulkptr; @@ -563,7 +557,7 @@ s32 rtl8188eu_xmitframe_complete(struct adapter *adapt, struct xmit_priv *pxmitp if (pbuf < bulkptr) { desc_cnt++; - if (desc_cnt == haldata->UsbTxAggDescNum) + if (desc_cnt == adapt->HalData->UsbTxAggDescNum) break; } else { desc_cnt = 0; diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 897e469..113bd0b 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -27,7 +27,7 @@ static void _ConfigNormalChipOutEP_8188E(struct adapter *adapt, u8 NumOutPipe) { - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); + struct hal_data_8188e *haldata = adapt->HalData; switch (NumOutPipe) { case 3: @@ -50,13 +50,12 @@ static void _ConfigNormalChipOutEP_8188E(struct adapter *adapt, u8 NumOutPipe) static bool HalUsbSetQueuePipeMapping8188EUsb(struct adapter *adapt, u8 NumInPipe, u8 NumOutPipe) { - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); bool result = false; _ConfigNormalChipOutEP_8188E(adapt, NumOutPipe); /* Normal chip with one IN and one OUT doesn't have interrupt IN EP. */ - if (haldata->OutEpNumber == 1) { + if (adapt->HalData->OutEpNumber == 1) { if (NumInPipe != 1) return result; } @@ -70,7 +69,7 @@ static bool HalUsbSetQueuePipeMapping8188EUsb(struct adapter *adapt, u8 NumInPip void rtw_hal_chip_configure(struct adapter *adapt) { - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); + struct hal_data_8188e *haldata = adapt->HalData; struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(adapt); if (pdvobjpriv->ishighspeed) @@ -97,8 +96,7 @@ u32 rtw_hal_power_on(struct adapter *adapt) { u16 value16; /* HW Power on sequence */ - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); - if (haldata->bMacPwrCtrlOn) + if (adapt->HalData->bMacPwrCtrlOn) return _SUCCESS; if (!rtl88eu_pwrseqcmdparsing(adapt, PWR_CUT_ALL_MSK, @@ -118,7 +116,7 @@ u32 rtw_hal_power_on(struct adapter *adapt) /* for SDIO - Set CR bit10 to enable 32k calibration. Suggested by SD1 Gimmy. Added by tynli. 2011.08.31. */ usb_write16(adapt, REG_CR, value16); - haldata->bMacPwrCtrlOn = true; + adapt->HalData->bMacPwrCtrlOn = true; return _SUCCESS; } @@ -128,18 +126,17 @@ static void _InitInterrupt(struct adapter *Adapter) { u32 imr, imr_ex; u8 usb_opt; - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); /* HISR write one to clear */ usb_write32(Adapter, REG_HISR_88E, 0xFFFFFFFF); /* HIMR - */ imr = IMR_PSTIMEOUT_88E | IMR_TBDER_88E | IMR_CPWM_88E | IMR_CPWM2_88E; usb_write32(Adapter, REG_HIMR_88E, imr); - haldata->IntrMask[0] = imr; + Adapter->HalData->IntrMask[0] = imr; imr_ex = IMR_TXERR_88E | IMR_RXERR_88E | IMR_TXFOVW_88E | IMR_RXFOVW_88E; usb_write32(Adapter, REG_HIMRE_88E, imr_ex); - haldata->IntrMask[1] = imr_ex; + Adapter->HalData->IntrMask[1] = imr_ex; /* REG_USB_SPECIAL_OPTION - BIT(4) */ /* 0; Use interrupt endpoint to upload interrupt pkt */ @@ -156,7 +153,6 @@ static void _InitInterrupt(struct adapter *Adapter) static void _InitQueueReservedPage(struct adapter *Adapter) { - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); struct registry_priv *pregistrypriv = &Adapter->registrypriv; u32 numHQ = 0; u32 numLQ = 0; @@ -167,14 +163,14 @@ static void _InitQueueReservedPage(struct adapter *Adapter) bool bWiFiConfig = pregistrypriv->wifi_spec; if (bWiFiConfig) { - if (haldata->OutEpQueueSel & TX_SELE_HQ) + if (Adapter->HalData->OutEpQueueSel & TX_SELE_HQ) numHQ = 0x29; - if (haldata->OutEpQueueSel & TX_SELE_LQ) + if (Adapter->HalData->OutEpQueueSel & TX_SELE_LQ) numLQ = 0x1C; /* NOTE: This step shall be proceed before writing REG_RQPN. */ - if (haldata->OutEpQueueSel & TX_SELE_NQ) + if (Adapter->HalData->OutEpQueueSel & TX_SELE_NQ) numNQ = 0x1C; value8 = (u8)_NPQ(numNQ); usb_write8(Adapter, REG_RQPN_NPQ, value8); @@ -224,10 +220,9 @@ static void _InitNormalChipRegPriority(struct adapter *Adapter, u16 beQ, static void _InitNormalChipOneOutEpPriority(struct adapter *Adapter) { - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); - u16 value = 0; - switch (haldata->OutEpQueueSel) { + + switch (Adapter->HalData->OutEpQueueSel) { case TX_SELE_HQ: value = QUEUE_HIGH; break; @@ -246,13 +241,12 @@ static void _InitNormalChipOneOutEpPriority(struct adapter *Adapter) static void _InitNormalChipTwoOutEpPriority(struct adapter *Adapter) { - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); struct registry_priv *pregistrypriv = &Adapter->registrypriv; u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ; u16 valueHi = 0; u16 valueLow = 0; - switch (haldata->OutEpQueueSel) { + switch (Adapter->HalData->OutEpQueueSel) { case (TX_SELE_HQ | TX_SELE_LQ): valueHi = QUEUE_HIGH; valueLow = QUEUE_LOW; @@ -312,9 +306,7 @@ static void _InitNormalChipThreeOutEpPriority(struct adapter *Adapter) static void _InitQueuePriority(struct adapter *Adapter) { - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); - - switch (haldata->OutEpNumber) { + switch (Adapter->HalData->OutEpNumber) { case 1: _InitNormalChipOneOutEpPriority(Adapter); break; @@ -356,7 +348,7 @@ static void _InitDriverInfoSize(struct adapter *Adapter, u8 drvInfoSize) static void _InitWMACSetting(struct adapter *Adapter) { - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); + struct hal_data_8188e *haldata = Adapter->HalData; haldata->ReceiveConfig = RCR_AAP | RCR_APM | RCR_AM | RCR_AB | RCR_CBSSID_DATA | RCR_CBSSID_BCN | @@ -455,7 +447,7 @@ static void _InitRetryFunction(struct adapter *Adapter) */ static void usb_AggSettingTxUpdate(struct adapter *Adapter) { - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); + struct hal_data_8188e *haldata = Adapter->HalData; u32 value32; if (Adapter->registrypriv.wifi_spec) @@ -491,7 +483,7 @@ usb_AggSettingRxUpdate( struct adapter *Adapter ) { - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); + struct hal_data_8188e *haldata = Adapter->HalData; u8 valueDMA; u8 valueUSB; @@ -565,8 +557,6 @@ usb_AggSettingRxUpdate( static void InitUsbAggregationSetting(struct adapter *Adapter) { - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); - /* Tx aggregation setting */ usb_AggSettingTxUpdate(Adapter); @@ -574,12 +564,12 @@ static void InitUsbAggregationSetting(struct adapter *Adapter) usb_AggSettingRxUpdate(Adapter); /* 201/12/10 MH Add for USB agg mode dynamic switch. */ - haldata->UsbRxHighSpeedMode = false; + Adapter->HalData->UsbRxHighSpeedMode = false; } static void _InitBeaconParameters(struct adapter *Adapter) { - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); + struct hal_data_8188e *haldata = Adapter->HalData; usb_write16(Adapter, REG_BCN_CTRL, 0x1010); @@ -621,7 +611,7 @@ enum { static void _InitAntenna_Selection(struct adapter *Adapter) { - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); + struct hal_data_8188e *haldata = Adapter->HalData; if (haldata->AntDivCfg == 0) return; @@ -677,7 +667,7 @@ u32 rtl8188eu_hal_init(struct adapter *Adapter) u16 value16; u8 txpktbuf_bndy; u32 status = _SUCCESS; - struct hal_data_8188e *haldata = GET_HAL_DATA(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; @@ -904,7 +894,6 @@ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_END); static void CardDisableRTL8188EU(struct adapter *Adapter) { u8 val8; - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("CardDisableRTL8188EU\n")); @@ -957,7 +946,7 @@ static void CardDisableRTL8188EU(struct adapter *Adapter) val8 = usb_read8(Adapter, REG_GPIO_IO_SEL+1); usb_write8(Adapter, REG_GPIO_IO_SEL+1, val8|0x0F);/* Reg0x43 */ usb_write32(Adapter, REG_BB_PAD_CTRL, 0x00080808);/* set LNA ,TRSW,EX_PA Pin to output mode */ - haldata->bMacPwrCtrlOn = false; + Adapter->HalData->bMacPwrCtrlOn = false; Adapter->bFWReady = false; } @@ -1035,7 +1024,7 @@ exit: /* */ static void Hal_EfuseParsePIDVID_8188EU(struct adapter *adapt, u8 *hwinfo, bool AutoLoadFail) { - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); + struct hal_data_8188e *haldata = adapt->HalData; if (!AutoLoadFail) { /* VID, PID */ @@ -1120,9 +1109,7 @@ static void _ReadPROMContent( static void _ReadRFType(struct adapter *Adapter) { - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); - - haldata->rf_chip = RF_6052; + Adapter->HalData->rf_chip = RF_6052; } void rtw_hal_read_chip_info(struct adapter *Adapter) @@ -1145,7 +1132,7 @@ static void rtl8192cu_trigger_gpio_0(struct adapter *adapt) static void ResumeTxBeacon(struct adapter *adapt) { - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); + struct hal_data_8188e *haldata = adapt->HalData; /* 2010.03.01. Marked by tynli. No need to call workitem beacause we record the value */ /* which should be read from register to a global variable. */ @@ -1159,7 +1146,7 @@ static void ResumeTxBeacon(struct adapter *adapt) static void StopTxBeacon(struct adapter *adapt) { - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); + struct hal_data_8188e *haldata = adapt->HalData; /* 2010.03.01. Marked by tynli. No need to call workitem beacause we record the value */ /* which should be read from register to a global variable. */ @@ -1266,7 +1253,7 @@ static void hw_var_set_bcn_func(struct adapter *Adapter, u8 variable, u8 *val) void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) { - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); + struct hal_data_8188e *haldata = Adapter->HalData; struct dm_priv *pdmpriv = &haldata->dmpriv; struct odm_dm_struct *podmpriv = &haldata->odmpriv; @@ -1765,11 +1752,9 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) void rtw_hal_get_hwreg(struct adapter *Adapter, u8 variable, u8 *val) { - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); - switch (variable) { case HW_VAR_BASIC_RATE: - *((u16 *)(val)) = haldata->BasicRateSet; + *((u16 *)(val)) = Adapter->HalData->BasicRateSet; case HW_VAR_TXPAUSE: val[0] = usb_read8(Adapter, REG_TXPAUSE); break; @@ -1778,7 +1763,7 @@ void rtw_hal_get_hwreg(struct adapter *Adapter, u8 variable, u8 *val) val[0] = (BIT(0) & usb_read8(Adapter, REG_TDECTRL+2)) ? true : false; break; case HW_VAR_RF_TYPE: - val[0] = haldata->rf_type; + val[0] = Adapter->HalData->rf_type; break; case HW_VAR_FWLPS_RF_ON: { @@ -1799,13 +1784,13 @@ void rtw_hal_get_hwreg(struct adapter *Adapter, u8 variable, u8 *val) } break; case HW_VAR_CURRENT_ANTENNA: - val[0] = haldata->CurAntenna; + val[0] = Adapter->HalData->CurAntenna; break; case HW_VAR_EFUSE_BYTES: /* To get EFUE total used bytes, added by Roger, 2008.12.22. */ - *((u16 *)(val)) = haldata->EfuseUsedBytes; + *((u16 *)(val)) = Adapter->HalData->EfuseUsedBytes; break; case HW_VAR_APFM_ON_MAC: - *val = haldata->bMacPwrCtrlOn; + *val = Adapter->HalData->bMacPwrCtrlOn; break; case HW_VAR_CHK_HI_QUEUE_EMPTY: *val = ((usb_read32(Adapter, REG_HGQ_INFORMATION)&0x0000ff00) == 0) ? true : false; @@ -1825,7 +1810,7 @@ u8 rtw_hal_get_def_var( void *pValue ) { - struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter); + struct hal_data_8188e *haldata = Adapter->HalData; u8 bResult = _SUCCESS; switch (eVariable) { @@ -1921,7 +1906,7 @@ void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level) u8 shortGIrate = false; int supportRateNum = 0; struct sta_info *psta; - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); + struct odm_dm_struct *odmpriv = &adapt->HalData->odmpriv; struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; @@ -1960,7 +1945,7 @@ void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level) break; } - rate_bitmap = ODM_Get_Rate_Bitmap(&haldata->odmpriv, mac_id, mask, 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); @@ -1968,8 +1953,7 @@ void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level) init_rate = get_highest_rate_idx(mask)&0x3f; - ODM_RA_UpdateRateInfo_8188E(&haldata->odmpriv, mac_id, - raid, mask, shortGIrate); + ODM_RA_UpdateRateInfo_8188E(odmpriv, mac_id, raid, mask, shortGIrate); /* set ra_id */ psta->raid = raid; @@ -2012,11 +1996,10 @@ void rtw_hal_bcn_related_reg_setting(struct adapter *adapt) void rtw_hal_def_value_init(struct adapter *adapt) { - struct hal_data_8188e *haldata; + struct hal_data_8188e *haldata = adapt->HalData; struct pwrctrl_priv *pwrctrlpriv; u8 i; - haldata = GET_HAL_DATA(adapt); pwrctrlpriv = &adapt->pwrctrlpriv; /* init default value */ diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h index 5362218..34268d9 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h @@ -351,9 +351,6 @@ struct hal_data_8188e { u8 UsbRxAggPageTimeout; }; -#define GET_HAL_DATA(__pAdapter) \ - ((struct hal_data_8188e *)((__pAdapter)->HalData)) - /* rtl8188e_hal_init.c */ void _8051Reset88E(struct adapter *padapter); void rtl8188e_InitializeFirmwareVars(struct adapter *padapter); diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c index 52fa659..d0d5915 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c @@ -20,7 +20,7 @@ static void interrupt_handler_8188eu(struct adapter *adapt, u16 pkt_len, u8 *pbuf) { - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); + 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); @@ -48,7 +48,7 @@ static int recvbuf2recvframe(struct adapter *adapt, struct sk_buff *pskb) struct sk_buff *pkt_copy = NULL; struct recv_frame *precvframe = NULL; struct rx_pkt_attrib *pattrib = NULL; - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); + struct hal_data_8188e *haldata = adapt->HalData; struct recv_priv *precvpriv = &adapt->recvpriv; struct __queue *pfree_recv_queue = &precvpriv->free_recv_queue; @@ -285,8 +285,7 @@ static int usbctrl_vendorreq(struct adapter *adapt, u8 request, u16 value, u16 i if (status == (-ESHUTDOWN) || status == -ENODEV) { adapt->bSurpriseRemoved = true; } else { - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); - haldata->srestpriv.Wifi_Error_Status = USB_VEN_REQ_CMD_FAIL; + adapt->HalData->srestpriv.Wifi_Error_Status = USB_VEN_REQ_CMD_FAIL; } } else { /* status != len && status >= 0 */ if (status > 0) { @@ -436,10 +435,7 @@ static void usb_read_port_complete(struct urb *purb, struct pt_regs *regs) break; case -EPROTO: case -EOVERFLOW: - { - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); - haldata->srestpriv.Wifi_Error_Status = USB_READ_PORT_FAIL; - } + adapt->HalData->srestpriv.Wifi_Error_Status = USB_READ_PORT_FAIL; precvbuf->reuse = true; usb_read_port(adapt, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf); break; -- cgit v0.10.2 From 182eec0eb75fc17455ff4d77f5e37ae4f0c5ea1c Mon Sep 17 00:00:00 2001 From: Xavier Roumegue <xroumegue@gmail.com> Date: Mon, 19 Sep 2016 14:49:24 +0200 Subject: staging: rtl8192u: r8192U_core: fix checkpatch permission warnings Fix the following warnings: Symbolic permissions are not preferred. Consider using octal permissions. Signed-off-by: Xavier Roumegue <xroumegue@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c index b86b28a..cdb64e3 100644 --- a/drivers/staging/rtl8192u/r8192U_core.c +++ b/drivers/staging/rtl8192u/r8192U_core.c @@ -114,9 +114,9 @@ static int channels = 0x3fff; -module_param(ifname, charp, S_IRUGO | S_IWUSR); -module_param(hwwep, int, S_IRUGO | S_IWUSR); -module_param(channels, int, S_IRUGO | S_IWUSR); +module_param(ifname, charp, 0644); +module_param(hwwep, int, 0644); +module_param(channels, int, 0644); MODULE_PARM_DESC(ifname, " Net interface name, wlan%d=default"); MODULE_PARM_DESC(hwwep, " Try to use hardware security support. "); -- cgit v0.10.2 From efdcb35a82fdd6e91b890efd3d5a5d4045e64c08 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal <bhumirks@gmail.com> Date: Sun, 18 Sep 2016 17:56:24 +0530 Subject: Staging: rtl8192u: Remove useless type conversion Some type conversions like casting a pointer to a pointer of same type, casting to the original type using addressof(&) operator etc. are not needed. Therefore, remove them. Done using coccinelle: @@ type t; t *p; t a; @@ ( - (t)(a) + a | - (t *)(p) + p | - (t *)(&a) + &a ) Signed-off-by: Bhumika Goyal <bhumirks@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c index 051c2be..89cbc07 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c @@ -1027,7 +1027,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, ieee, (PTS_COMMON_INFO *) &pRxTS, hdr->addr2, - (u8)Frame_QoSTID((u8 *)(skb->data)), + Frame_QoSTID((u8 *)(skb->data)), RX_DIR, true)) { diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c index 49db1b7..10a8040 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c @@ -806,7 +806,7 @@ static struct sk_buff *ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d *(tag++) = 2; put_unaligned_le16(ieee->current_network.atim_window, - (u8 *)tag); + tag); tag+=2; } diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c index 28737ec..98fbb6e 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c @@ -354,7 +354,7 @@ int ieee80211_rx_ADDBAReq(struct ieee80211_device *ieee, struct sk_buff *skb) req = (struct rtl_80211_hdr_3addr *) skb->data; tag = (u8 *)req; - dst = (u8 *)(&req->addr2[0]); + dst = &req->addr2[0]; tag += sizeof(struct rtl_80211_hdr_3addr); pDialogToken = tag + 2; //category+action pBaParamSet = (PBA_PARAM_SET)(tag + 3); //+DialogToken @@ -452,7 +452,7 @@ int ieee80211_rx_ADDBARsp(struct ieee80211_device *ieee, struct sk_buff *skb) } rsp = (struct rtl_80211_hdr_3addr *)skb->data; tag = (u8 *)rsp; - dst = (u8 *)(&rsp->addr2[0]); + dst = &rsp->addr2[0]; tag += sizeof(struct rtl_80211_hdr_3addr); pDialogToken = tag + 2; pStatusCode = (u16 *)(tag + 3); @@ -590,7 +590,7 @@ int ieee80211_rx_DELBA(struct ieee80211_device *ieee, struct sk_buff *skb) IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len); delba = (struct rtl_80211_hdr_3addr *)skb->data; - dst = (u8 *)(&delba->addr2[0]); + dst = &delba->addr2[0]; pDelBaParamSet = (PDELBA_PARAM_SET)&delba->payload[2]; if(pDelBaParamSet->field.Initiator == 1) diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c index cdb64e3..c66e7cf 100644 --- a/drivers/staging/rtl8192u/r8192U_core.c +++ b/drivers/staging/rtl8192u/r8192U_core.c @@ -4472,10 +4472,10 @@ static void rtl8192_query_rxphystatus(struct r8192_priv *priv, */ pstats->SignalQuality = precord_stats->SignalQuality = - (u8)(evm & 0xff); + evm & 0xff; pstats->RxMIMOSignalQuality[i] = precord_stats->RxMIMOSignalQuality[i] = - (u8)(evm & 0xff); + evm & 0xff; } @@ -5010,8 +5010,7 @@ static int rtl8192_usb_probe(struct usb_interface *intf, dev->netdev_ops = &rtl8192_netdev_ops; - dev->wireless_handlers = - (struct iw_handler_def *)&r8192_wx_handlers_def; + dev->wireless_handlers = &r8192_wx_handlers_def; dev->type = ARPHRD_ETHER; @@ -5219,7 +5218,8 @@ void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType, } else { /* Key Material */ if (KeyContent) { - write_nic_dword(dev, WCAMI, (u32)(*(KeyContent + i - 2))); + write_nic_dword(dev, WCAMI, + *(KeyContent + i - 2)); write_nic_dword(dev, RWCAM, TargetCommand); } } diff --git a/drivers/staging/rtl8192u/r8192U_dm.c b/drivers/staging/rtl8192u/r8192U_dm.c index 1e0e53c..9209aad 100644 --- a/drivers/staging/rtl8192u/r8192U_dm.c +++ b/drivers/staging/rtl8192u/r8192U_dm.c @@ -150,7 +150,7 @@ void deinit_hal_dm(struct net_device *dev) #ifdef USB_RX_AGGREGATION_SUPPORT void dm_CheckRxAggregation(struct net_device *dev) { - struct r8192_priv *priv = ieee80211_priv((struct net_device *)dev); + struct r8192_priv *priv = ieee80211_priv(dev); PRT_HIGH_THROUGHPUT pHTInfo = priv->ieee80211->pHTInfo; static unsigned long lastTxOkCnt; static unsigned long lastRxOkCnt; @@ -2346,7 +2346,7 @@ dm_CheckEdcaTurbo_EXIT: static void dm_init_ctstoself(struct net_device *dev) { - struct r8192_priv *priv = ieee80211_priv((struct net_device *)dev); + struct r8192_priv *priv = ieee80211_priv(dev); priv->ieee80211->bCTSToSelfEnable = true; priv->ieee80211->CTSToSelfTH = CTSToSelfTHVal; @@ -2354,7 +2354,7 @@ static void dm_init_ctstoself(struct net_device *dev) static void dm_ctstoself(struct net_device *dev) { - struct r8192_priv *priv = ieee80211_priv((struct net_device *)dev); + struct r8192_priv *priv = ieee80211_priv(dev); PRT_HIGH_THROUGHPUT pHTInfo = priv->ieee80211->pHTInfo; static unsigned long lastTxOkCnt; static unsigned long lastRxOkCnt; -- cgit v0.10.2 From b80fa1845d4bd20e99be116a049327fbe8281e42 Mon Sep 17 00:00:00 2001 From: Namrata A Shettar <namrataashettar@gmail.com> Date: Mon, 19 Sep 2016 20:27:26 +0530 Subject: staging: rtl8192e: Add space around '+' Add space around '+' to resolve checkpatch issue. Signed-off-by: Namrata A Shettar <namrataashettar@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8192e/dot11d.c b/drivers/staging/rtl8192e/dot11d.c index 4d8fb41..24fc615 100644 --- a/drivers/staging/rtl8192e/dot11d.c +++ b/drivers/staging/rtl8192e/dot11d.c @@ -51,7 +51,7 @@ void dot11d_init(struct rtllib_device *ieee) pDot11dInfo->State = DOT11D_STATE_NONE; pDot11dInfo->CountryIeLen = 0; memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); - memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); + memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER + 1); RESET_CIE_WATCHDOG(ieee); } @@ -105,8 +105,8 @@ void Dot11d_Reset(struct rtllib_device *ieee) struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(ieee); u32 i; - memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); - memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); + memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER + 1); + memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER + 1); for (i = 1; i <= 11; i++) (pDot11dInfo->channel_map)[i] = 1; for (i = 12; i <= 14; i++) @@ -123,8 +123,8 @@ void Dot11d_UpdateCountryIe(struct rtllib_device *dev, u8 *pTaddr, u8 i, j, NumTriples, MaxChnlNum; struct chnl_txpow_triple *pTriple; - memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); - memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); + memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER + 1); + memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER + 1); MaxChnlNum = 0; NumTriples = (CoutryIeLen - 3) / 3; pTriple = (struct chnl_txpow_triple *)(pCoutryIe + 3); -- cgit v0.10.2 From 1fa3a915b56ded00710d6f8bf8ed936bc0bb784c Mon Sep 17 00:00:00 2001 From: Namrata A Shettar <namrataashettar@gmail.com> Date: Mon, 19 Sep 2016 20:27:37 +0530 Subject: staging: rtl8192e: Remove unnecessary blank lines Remove unneccessary blank lines to resolve checkpatch issue. Signed-off-by: Namrata A Shettar <namrataashettar@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8192e/dot11d.c b/drivers/staging/rtl8192e/dot11d.c index 24fc615..25725b1 100644 --- a/drivers/staging/rtl8192e/dot11d.c +++ b/drivers/staging/rtl8192e/dot11d.c @@ -53,7 +53,6 @@ void dot11d_init(struct rtllib_device *ieee) memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER + 1); RESET_CIE_WATCHDOG(ieee); - } EXPORT_SYMBOL(dot11d_init); @@ -99,7 +98,6 @@ void Dot11d_Channelmap(u8 channel_plan, struct rtllib_device *ieee) } EXPORT_SYMBOL(Dot11d_Channelmap); - void Dot11d_Reset(struct rtllib_device *ieee) { struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(ieee); -- cgit v0.10.2 From 986fb011c4074650f1ff5e000abccf1f6162f0c1 Mon Sep 17 00:00:00 2001 From: Namrata A Shettar <namrataashettar@gmail.com> Date: Mon, 19 Sep 2016 20:27:46 +0530 Subject: staging: rtl8192e: Add space around binary operator '+' Add space around binary operator '+' to resolve checkpatch issue. Signed-off-by: Namrata A Shettar <namrataashettar@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8192e/dot11d.h b/drivers/staging/rtl8192e/dot11d.h index 735a199..bdb5392 100644 --- a/drivers/staging/rtl8192e/dot11d.h +++ b/drivers/staging/rtl8192e/dot11d.h @@ -47,8 +47,8 @@ struct rt_dot11d_info { u8 CountryIeSrcAddr[6]; u8 CountryIeWatchdog; - u8 channel_map[MAX_CHANNEL_NUMBER+1]; - u8 MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1]; + u8 channel_map[MAX_CHANNEL_NUMBER + 1]; + u8 MaxTxPwrDbmList[MAX_CHANNEL_NUMBER + 1]; enum dot11d_state State; }; -- cgit v0.10.2 From 8e9253b77735406d2bfe7685d3d5c8b8a12617da Mon Sep 17 00:00:00 2001 From: Namrata A Shettar <namrataashettar@gmail.com> Date: Mon, 19 Sep 2016 20:27:56 +0530 Subject: staging: rtl8192e: Insert blank line after function declaration Insert blank line after function declaration to resolve checkpatch issue. Signed-off-by: Namrata A Shettar <namrataashettar@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8192e/dot11d.h b/drivers/staging/rtl8192e/dot11d.h index bdb5392..aac395f 100644 --- a/drivers/staging/rtl8192e/dot11d.h +++ b/drivers/staging/rtl8192e/dot11d.h @@ -78,6 +78,7 @@ static inline void RESET_CIE_WATCHDOG(struct rtllib_device *__pIeeeDev) { GET_CIE_WATCHDOG(__pIeeeDev) = 0; } + #define UPDATE_CIE_WATCHDOG(__pIeeeDev) (++GET_CIE_WATCHDOG(__pIeeeDev)) void dot11d_init(struct rtllib_device *dev); -- cgit v0.10.2 From c43fcdd4434b7afef7f37bdad1c51b877cffc4ce Mon Sep 17 00:00:00 2001 From: Sandhya Bankar <bankarsandhya512@gmail.com> Date: Tue, 20 Sep 2016 14:31:50 +0530 Subject: Staging: rtl8712: rtl8712_efuse: Use !x instead of x == NULL. Use !x instead of x == NULL. This patch was found by checkpatch. Signed-off-by: Sandhya Bankar <bankarsandhya512@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8712/rtl8712_efuse.c b/drivers/staging/rtl8712/rtl8712_efuse.c index 76f60ba..205298e 100644 --- a/drivers/staging/rtl8712/rtl8712_efuse.c +++ b/drivers/staging/rtl8712/rtl8712_efuse.c @@ -248,7 +248,7 @@ u8 r8712_efuse_pg_packet_read(struct _adapter *padapter, u8 offset, u8 *data) u8 tmpdata[PGPKT_DATA_SIZE]; u8 ret = true; - if (data == NULL) + if (!data) return false; if (offset > 0x0f) return false; -- cgit v0.10.2 From a667dbce78d115396cf3b3d1c6d3c6001865ea29 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar <bankarsandhya512@gmail.com> Date: Tue, 20 Sep 2016 14:34:36 +0530 Subject: Staging: rtl8712: rtl8712_recv: Use !x instead of x == NULL Use !x instead of x == NULL. This patch was found by checkpatch. Signed-off-by: Sandhya Bankar <bankarsandhya512@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index 4027d1a..66f0e0a 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -60,7 +60,7 @@ int r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter) _init_queue(&precvpriv->free_recv_buf_queue); precvpriv->pallocated_recv_buf = kzalloc(NR_RECVBUFF * sizeof(struct recv_buf) + 4, GFP_ATOMIC); - if (precvpriv->pallocated_recv_buf == NULL) + if (!precvpriv->pallocated_recv_buf) return _FAIL; precvpriv->precv_buf = precvpriv->pallocated_recv_buf + 4 - ((addr_t) (precvpriv->pallocated_recv_buf) & 3); @@ -274,7 +274,7 @@ union recv_frame *r8712_recvframe_chk_defrag(struct _adapter *padapter, fragnum = pfhdr->attrib.frag_num; psta_addr = pfhdr->attrib.ta; psta = r8712_get_stainfo(pstapriv, psta_addr); - if (psta == NULL) + if (!psta) pdefrag_q = NULL; else pdefrag_q = &psta->sta_recvpriv.defrag_q; @@ -999,15 +999,15 @@ int recv_func(struct _adapter *padapter, void *pcontext) } process_phy_info(padapter, prframe); prframe = r8712_decryptor(padapter, prframe); - if (prframe == NULL) { + if (!prframe) { retval = _FAIL; goto _exit_recv_func; } prframe = r8712_recvframe_chk_defrag(padapter, prframe); - if (prframe == NULL) + if (!prframe) goto _exit_recv_func; prframe = r8712_portctrl(padapter, prframe); - if (prframe == NULL) { + if (!prframe) { retval = _FAIL; goto _exit_recv_func; } @@ -1065,7 +1065,7 @@ static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb) if ((le32_to_cpu(prxstat->rxdw0) >> 23) & 0x01) shift_sz = 2; precvframe = r8712_alloc_recvframe(pfree_recv_queue); - if (precvframe == NULL) + if (!precvframe) goto _exit_recvbuf2recvframe; INIT_LIST_HEAD(&precvframe->u.hdr.list); precvframe->u.hdr.precvbuf = NULL; /*can't access the precvbuf*/ -- cgit v0.10.2 From 78f70e6dfeb9d988a3211ac010dc62c22883c1ba Mon Sep 17 00:00:00 2001 From: Sandhya Bankar <bankarsandhya512@gmail.com> Date: Tue, 20 Sep 2016 14:36:17 +0530 Subject: Staging: rtl8712: rtl8712_xmit: Use !x instead of x == NULL Use !x instead of x == NULL. This patch was found by checkpatch. Signed-off-by: Sandhya Bankar <bankarsandhya512@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8712/rtl8712_xmit.c b/drivers/staging/rtl8712/rtl8712_xmit.c index 4bbf76f..c4f03a6 100644 --- a/drivers/staging/rtl8712/rtl8712_xmit.c +++ b/drivers/staging/rtl8712/rtl8712_xmit.c @@ -629,7 +629,7 @@ int r8712_xmitframe_complete(struct _adapter *padapter, phwxmits = pxmitpriv->hwxmits; hwentry = pxmitpriv->hwxmit_entry; - if (pxmitbuf == NULL) { + if (!pxmitbuf) { pxmitbuf = r8712_alloc_xmitbuf(pxmitpriv); if (!pxmitbuf) return false; -- cgit v0.10.2 From 11975c56b6d130970ef31dbcd3f307baec253c18 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar <bankarsandhya512@gmail.com> Date: Tue, 20 Sep 2016 14:37:43 +0530 Subject: Staging: rtl8712: rtl871x_cmd: Use !x instead of x == NULL. Use !x instead of x == NULL. This patch was found by checkpatch. Signed-off-by: Sandhya Bankar <bankarsandhya512@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8712/rtl871x_cmd.c b/drivers/staging/rtl8712/rtl871x_cmd.c index 51b6959..b7ee5e6 100644 --- a/drivers/staging/rtl8712/rtl871x_cmd.c +++ b/drivers/staging/rtl8712/rtl871x_cmd.c @@ -66,13 +66,13 @@ static sint _init_cmd_priv(struct cmd_priv *pcmdpriv) pcmdpriv->cmd_seq = 1; pcmdpriv->cmd_allocated_buf = kmalloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ, GFP_ATOMIC); - if (pcmdpriv->cmd_allocated_buf == NULL) + if (!pcmdpriv->cmd_allocated_buf) return _FAIL; pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf + CMDBUFF_ALIGN_SZ - ((addr_t)(pcmdpriv->cmd_allocated_buf) & (CMDBUFF_ALIGN_SZ - 1)); pcmdpriv->rsp_allocated_buf = kmalloc(MAX_RSPSZ + 4, GFP_ATOMIC); - if (pcmdpriv->rsp_allocated_buf == NULL) + if (!pcmdpriv->rsp_allocated_buf) return _FAIL; pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf + 4 - ((addr_t)(pcmdpriv->rsp_allocated_buf) & 3); @@ -88,7 +88,7 @@ static sint _init_evt_priv(struct evt_priv *pevtpriv) pevtpriv->event_seq = 0; pevtpriv->evt_allocated_buf = kmalloc(MAX_EVTSZ + 4, GFP_ATOMIC); - if (pevtpriv->evt_allocated_buf == NULL) + if (!pevtpriv->evt_allocated_buf) return _FAIL; pevtpriv->evt_buf = pevtpriv->evt_allocated_buf + 4 - ((addr_t)(pevtpriv->evt_allocated_buf) & 3); @@ -123,7 +123,7 @@ static sint _enqueue_cmd(struct __queue *queue, struct cmd_obj *obj) { unsigned long irqL; - if (obj == NULL) + if (!obj) return _SUCCESS; spin_lock_irqsave(&queue->lock, irqL); list_add_tail(&obj->list, &queue->queue); @@ -181,7 +181,7 @@ u32 r8712_enqueue_cmd_ex(struct cmd_priv *pcmdpriv, struct cmd_obj *obj) unsigned long irqL; struct __queue *queue; - if (obj == NULL) + if (!obj) return _SUCCESS; if (pcmdpriv->padapter->eeprompriv.bautoload_fail_flag) return _FAIL; @@ -477,7 +477,7 @@ u8 r8712_joinbss_cmd(struct _adapter *padapter, struct wlan_network *pnetwork) } } psecnetwork = &psecuritypriv->sec_bss; - if (psecnetwork == NULL) { + if (!psecnetwork) { kfree(pcmd); return _FAIL; } @@ -884,16 +884,16 @@ void r8712_createbss_cmd_callback(struct _adapter *padapter, if (!psta) { psta = r8712_alloc_stainfo(&padapter->stapriv, pnetwork->MacAddress); - if (psta == NULL) + if (!psta) goto createbss_cmd_fail; } r8712_indicate_connect(padapter); } else { pwlan = _r8712_alloc_network(pmlmepriv); - if (pwlan == NULL) { + if (!pwlan) { pwlan = r8712_get_oldest_wlan_network( &pmlmepriv->scanned_queue); - if (pwlan == NULL) + if (!pwlan) goto createbss_cmd_fail; pwlan->last_scanned = jiffies; } else @@ -925,7 +925,7 @@ void r8712_setstaKey_cmdrsp_callback(struct _adapter *padapter, struct sta_info *psta = r8712_get_stainfo(pstapriv, psetstakey_rsp->addr); - if (psta == NULL) + if (!psta) goto exit; psta->aid = psta->mac_id = psetstakey_rsp->keyid; /*CAM_ID(CAM_ENTRY)*/ exit: @@ -945,7 +945,7 @@ void r8712_setassocsta_cmdrsp_callback(struct _adapter *padapter, struct sta_info *psta = r8712_get_stainfo(pstapriv, passocsta_parm->addr); - if (psta == NULL) + if (!psta) return; psta->aid = psta->mac_id = passocsta_rsp->cam_id; spin_lock_irqsave(&pmlmepriv->lock, irqL); -- cgit v0.10.2 From dc0283c7bc85669a52963d38553411d30a19a2f2 Mon Sep 17 00:00:00 2001 From: Georgiana Rodica Chelu <georgiana.chelu93@gmail.com> Date: Tue, 20 Sep 2016 12:13:06 +0300 Subject: staging: rtl8188eu: core: rtw_xmit: Remove extra braces Remove the braces {} in the following cases: - when there is a single branch with a single statement. - when both branches have a single statement The modifications improve the coding style. Issues found by checkpatch.pl script. Signed-off-by: Georgiana Rodica Chelu <georgiana.chelu93@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c index 56c6604..1d2817b 100644 --- a/drivers/staging/rtl8188eu/core/rtw_xmit.c +++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c @@ -142,9 +142,8 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) if (res == _FAIL) { msleep(10); res = rtw_os_xmit_resource_alloc(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ)); - if (res == _FAIL) { + if (res == _FAIL) goto exit; - } } pxmitbuf->flags = XMIT_VO_QUEUE; @@ -248,9 +247,8 @@ void _rtw_free_xmit_priv(struct xmit_priv *pxmitpriv) pxmitbuf++; } - if (pxmitpriv->pallocated_xmit_extbuf) { + if (pxmitpriv->pallocated_xmit_extbuf) vfree(pxmitpriv->pallocated_xmit_extbuf); - } rtw_free_hwxmits(padapter); @@ -779,11 +777,10 @@ s32 rtw_make_wlanhdr(struct adapter *padapter, u8 *hdr, struct pkt_attrib *pattr if (pattrib->psta) { psta = pattrib->psta; } else { - if (bmcst) { + if (bmcst) psta = rtw_get_bcmc_stainfo(padapter); - } else { + else psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra); - } } memset(hdr, 0, WLANHDR_OFFSET); @@ -1048,9 +1045,8 @@ s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, struct mpdu_len -= llc_sz; } - if ((pattrib->icv_len > 0) && (pattrib->bswenc)) { + if ((pattrib->icv_len > 0) && (pattrib->bswenc)) mpdu_len -= pattrib->icv_len; - } if (bmcst) { /* don't do fragment to broadcat/multicast packets */ @@ -1554,11 +1550,10 @@ s32 rtw_xmit_classifier(struct adapter *padapter, struct xmit_frame *pxmitframe) int res = _SUCCESS; - if (pattrib->psta) { + if (pattrib->psta) psta = pattrib->psta; - } else { + else psta = rtw_get_stainfo(pstapriv, pattrib->ra); - } if (psta == NULL) { res = _FAIL; -- cgit v0.10.2 From 106d43f18819f69784ddf216b5f05a84a03c0d38 Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Tue, 20 Sep 2016 13:16:37 +0530 Subject: staging: dgnc: Merge assignment with return Instead of storing the return value of a function call into a variable and then returning it, we can club the two into a single return statement. This change was made using the following semantic patch by Coccinelle: @@ local idexpression ret; expression e; @@ -ret = +return e; -return ret; Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index fd46ef0..1c1ac84 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -2548,9 +2548,8 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, spin_unlock_irqrestore(&ch->ch_lock, flags); - rc = put_user(C_CLOCAL(tty) ? 1 : 0, - (unsigned long __user *)arg); - return rc; + return put_user(C_CLOCAL(tty) ? 1 : 0, + (unsigned long __user *)arg); case TIOCSSOFTCAR: @@ -2721,8 +2720,8 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, case DIGI_GETCUSTOMBAUD: spin_unlock_irqrestore(&ch->ch_lock, flags); - rc = put_user(ch->ch_custom_speed, (unsigned int __user *)arg); - return rc; + return put_user(ch->ch_custom_speed, + (unsigned int __user *)arg); case DIGI_SETCUSTOMBAUD: { @@ -2808,8 +2807,7 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, events |= (EV_IPU | EV_IPS); spin_unlock_irqrestore(&ch->ch_lock, flags); - rc = put_user(events, (unsigned int __user *)arg); - return rc; + return put_user(events, (unsigned int __user *)arg); } /* -- cgit v0.10.2 From 89237e06e2a57899424c8c51bada9b4046161e07 Mon Sep 17 00:00:00 2001 From: Georgiana Rodica Chelu <georgiana.chelu93@gmail.com> Date: Mon, 19 Sep 2016 18:41:56 +0300 Subject: staging: iio: meter: ade7758_ring: Match alignment with open parenthesis Organize the parameters on a single line to improve the readability of the code. Also, indent the line to match alignment with the open parenthesis. Ensure that the modifications do not break the rule of 80 characters per line. Issues found by checkpatch.pl script. Signed-off-by: Georgiana Rodica Chelu <georgiana.chelu93@gmail.com> Acked-by: Julia Lawall <julia.lawall@lip6.fr> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/iio/meter/ade7758_ring.c b/drivers/staging/iio/meter/ade7758_ring.c index a6b76d4..57c213d 100644 --- a/drivers/staging/iio/meter/ade7758_ring.c +++ b/drivers/staging/iio/meter/ade7758_ring.c @@ -38,18 +38,14 @@ static int ade7758_write_waveform_type(struct device *dev, unsigned int type) int ret; u8 reg; - ret = ade7758_spi_read_reg_8(dev, - ADE7758_WAVMODE, - ®); + ret = ade7758_spi_read_reg_8(dev, ADE7758_WAVMODE, ®); if (ret) goto out; reg &= ~0x1F; reg |= type & 0x1F; - ret = ade7758_spi_write_reg_8(dev, - ADE7758_WAVMODE, - reg); + ret = ade7758_spi_write_reg_8(dev, ADE7758_WAVMODE, reg); out: return ret; } @@ -94,7 +90,7 @@ static int ade7758_ring_preenable(struct iio_dev *indio_dev) indio_dev->masklength); ade7758_write_waveform_type(&indio_dev->dev, - indio_dev->channels[channel].address); + indio_dev->channels[channel].address); return 0; } -- cgit v0.10.2 From 748df3b1a429151ef05010792be254feeb83e201 Mon Sep 17 00:00:00 2001 From: Georgiana Rodica Chelu <georgiana.chelu93@gmail.com> Date: Mon, 19 Sep 2016 19:35:09 +0300 Subject: staging: iio: meter: ade7754: Match alignment with open parenthesis Reorganize the parameters to improve the readability of the code in two manners: - parameters of distinctive variable types on different lines - parameters of similar variable types on the same line Also, take advantage of the horizontal space available and place all the parameters on a single line. Issues found by checkpatch.pl script. Signed-off-by: Georgiana Rodica Chelu <georgiana.chelu93@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c index c46bef64..1730959 100644 --- a/drivers/staging/iio/meter/ade7754.c +++ b/drivers/staging/iio/meter/ade7754.c @@ -23,9 +23,7 @@ #include "meter.h" #include "ade7754.h" -static int ade7754_spi_write_reg_8(struct device *dev, - u8 reg_address, - u8 val) +static int ade7754_spi_write_reg_8(struct device *dev, u8 reg_address, u8 val) { int ret; struct iio_dev *indio_dev = dev_to_iio_dev(dev); @@ -42,8 +40,7 @@ static int ade7754_spi_write_reg_8(struct device *dev, } static int ade7754_spi_write_reg_16(struct device *dev, - u8 reg_address, - u16 value) + u8 reg_address, u16 value) { int ret; struct iio_dev *indio_dev = dev_to_iio_dev(dev); @@ -59,9 +56,7 @@ static int ade7754_spi_write_reg_16(struct device *dev, return ret; } -static int ade7754_spi_read_reg_8(struct device *dev, - u8 reg_address, - u8 *val) +static int ade7754_spi_read_reg_8(struct device *dev, u8 reg_address, u8 *val) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7754_state *st = iio_priv(indio_dev); @@ -70,7 +65,7 @@ static int ade7754_spi_read_reg_8(struct device *dev, ret = spi_w8r8(st->us, ADE7754_READ_REG(reg_address)); if (ret < 0) { dev_err(&st->us->dev, "problem when reading 8 bit register 0x%02X", - reg_address); + reg_address); return ret; } *val = ret; @@ -79,8 +74,7 @@ static int ade7754_spi_read_reg_8(struct device *dev, } static int ade7754_spi_read_reg_16(struct device *dev, - u8 reg_address, - u16 *val) + u8 reg_address, u16 *val) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7754_state *st = iio_priv(indio_dev); @@ -99,8 +93,7 @@ static int ade7754_spi_read_reg_16(struct device *dev, } static int ade7754_spi_read_reg_24(struct device *dev, - u8 reg_address, - u32 *val) + u8 reg_address, u32 *val) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7754_state *st = iio_priv(indio_dev); @@ -123,7 +116,7 @@ static int ade7754_spi_read_reg_24(struct device *dev, ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); if (ret) { dev_err(&st->us->dev, "problem when reading 24 bit register 0x%02X", - reg_address); + reg_address); goto error_ret; } *val = (st->rx[1] << 16) | (st->rx[2] << 8) | st->rx[3]; @@ -134,8 +127,8 @@ error_ret: } static ssize_t ade7754_read_8bit(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { int ret; u8 val = 0; @@ -149,8 +142,8 @@ static ssize_t ade7754_read_8bit(struct device *dev, } static ssize_t ade7754_read_16bit(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { int ret; u16 val = 0; @@ -164,8 +157,8 @@ static ssize_t ade7754_read_16bit(struct device *dev, } static ssize_t ade7754_read_24bit(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { int ret; u32 val = 0; @@ -179,9 +172,9 @@ static ssize_t ade7754_read_24bit(struct device *dev, } static ssize_t ade7754_write_8bit(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_attr *this_attr = to_iio_dev_attr(attr); int ret; @@ -197,9 +190,9 @@ error_ret: } static ssize_t ade7754_write_16bit(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_attr *this_attr = to_iio_dev_attr(attr); int ret; @@ -403,16 +396,14 @@ err_ret: } static ssize_t ade7754_read_frequency(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { int ret; u8 t; int sps; - ret = ade7754_spi_read_reg_8(dev, - ADE7754_WAVMODE, - &t); + ret = ade7754_spi_read_reg_8(dev, ADE7754_WAVMODE, &t); if (ret) return ret; @@ -423,9 +414,9 @@ static ssize_t ade7754_read_frequency(struct device *dev, } static ssize_t ade7754_write_frequency(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) + struct device_attribute *attr, + const char *buf, + size_t len) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7754_state *st = iio_priv(indio_dev); -- cgit v0.10.2 From d2a9334e7a12df52196f8e907cc71ec1dd917f61 Mon Sep 17 00:00:00 2001 From: Brian Masney <masneyb@onstation.org> Date: Tue, 20 Sep 2016 05:38:56 -0400 Subject: staging: iio: isl29018: remove the FSF's mailing address Address warning from checkpatch: CHECK: Do not include the paragraph about writing to the Free Software Foundation's mailing address from the sample GPL notice. The FSF has changed addresses in the past, and may do so again. Linux already includes a copy of the GPL. Signed-off-by: Brian Masney <masneyb@onstation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index f47a17d..a767a43 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -15,10 +15,6 @@ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include <linux/module.h> -- cgit v0.10.2 From 5ccde0dc6a9f699c470334632b72a064e16b61df Mon Sep 17 00:00:00 2001 From: Sandhya Bankar <bankarsandhya512@gmail.com> Date: Sun, 18 Sep 2016 05:16:44 +0530 Subject: Staging: i4l: Remove NULL comparison. This patch removes the explicit NULL comparison. This issue was found by checkpatch. Signed-off-by: Sandhya Bankar <bankarsandhya512@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/i4l/act2000/act2000_isa.c b/drivers/staging/i4l/act2000/act2000_isa.c index c800da8..808bb3b 100644 --- a/drivers/staging/i4l/act2000/act2000_isa.c +++ b/drivers/staging/i4l/act2000/act2000_isa.c @@ -166,7 +166,7 @@ act2000_isa_config_port(act2000_card *card, unsigned short portbase) release_region(card->port, ISA_REGION); card->flags &= ~ACT2000_FLAGS_PVALID; } - if (request_region(portbase, ACT2000_PORTLEN, card->regname) == NULL) + if (!request_region(portbase, ACT2000_PORTLEN, card->regname)) return -EBUSY; else { card->port = portbase; @@ -244,7 +244,7 @@ act2000_isa_receive(act2000_card *card) if (valid) { card->idat.isa.rcvlen = ((actcapi_msghdr *)&card->idat.isa.rcvhdr)->len; card->idat.isa.rcvskb = dev_alloc_skb(card->idat.isa.rcvlen); - if (card->idat.isa.rcvskb == NULL) { + if (!card->idat.isa.rcvskb) { card->idat.isa.rcvignore = 1; printk(KERN_WARNING "act2000_isa_receive: no memory\n"); -- cgit v0.10.2 From dfe996f275956b9039d49a6545684c739a39cab1 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar <bankarsandhya512@gmail.com> Date: Sun, 18 Sep 2016 05:29:03 +0530 Subject: Staging: i4l: Do not initialise statics to 0. Do not initialise statics to 0. Static variable by default initialise to 0, so no need to explicit initialisation. This issue was found by checkpatch. Signed-off-by: Sandhya Bankar <bankarsandhya512@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/i4l/act2000/module.c b/drivers/staging/i4l/act2000/module.c index 68073d0..39a8940 100644 --- a/drivers/staging/i4l/act2000/module.c +++ b/drivers/staging/i4l/act2000/module.c @@ -28,7 +28,7 @@ static unsigned short act2000_isa_ports[] = static act2000_card *cards = (act2000_card *) NULL; /* Parameters to be set by insmod */ -static int act_bus = 0; +static int act_bus; static int act_port = -1; /* -1 = Autoprobe */ static int act_irq = -1; static char *act_id = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; -- cgit v0.10.2 From 4b4a3e05c426b02b9728a0ab2bbfd20ad3294a71 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar <bankarsandhya512@gmail.com> Date: Sun, 18 Sep 2016 05:38:34 +0530 Subject: Staging: i4l: Use !x instead of x == NULL. Use !x instead of x == NULL. This issue was found by checkpatch. Signed-off-by: Sandhya Bankar <bankarsandhya512@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/i4l/act2000/capi.c b/drivers/staging/i4l/act2000/capi.c index bf04e6f..62f5629 100644 --- a/drivers/staging/i4l/act2000/capi.c +++ b/drivers/staging/i4l/act2000/capi.c @@ -618,7 +618,7 @@ handle_ack(act2000_card *card, act2000_chan *chan, __u8 blocknr) { spin_lock_irqsave(&card->lock, flags); tmp = skb_peek((struct sk_buff_head *)tmp); spin_unlock_irqrestore(&card->lock, flags); - if ((tmp == skb) || (tmp == NULL)) { + if ((tmp == skb) || !tmp) { /* reached end of queue */ printk(KERN_WARNING "act2000: handle_ack nothing found!\n"); return 0; -- cgit v0.10.2 From 1e5a82e0ddfa6c9a2cf42ea87db3e079a4a483e6 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar <bankarsandhya512@gmail.com> Date: Mon, 19 Sep 2016 00:31:12 +0530 Subject: Staging: i4l: Remove unused variable Remove unused variable. This change is made by below coccinelle script: @@ type T; identifier i; constant C; @@ ( extern T i; | - T i; <+... when != i - i = C; ...+> ) Signed-off-by: Sandhya Bankar <bankarsandhya512@gmail.com> Acked-by: Julia Lawall <julia.lawall@lip6.fr> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/i4l/act2000/act2000_isa.c b/drivers/staging/i4l/act2000/act2000_isa.c index 808bb3b..ad7a039 100644 --- a/drivers/staging/i4l/act2000/act2000_isa.c +++ b/drivers/staging/i4l/act2000/act2000_isa.c @@ -399,7 +399,6 @@ act2000_isa_download(act2000_card *card, act2000_ddef __user *cb) unsigned int length; int l; int c; - long timeout; u_char *b; u_char __user *p; u_char *buf; @@ -417,7 +416,6 @@ act2000_isa_download(act2000_card *card, act2000_ddef __user *cb) buf = kmalloc(1024, GFP_KERNEL); if (!buf) return -ENOMEM; - timeout = 0; while (length) { l = (length > 1024) ? 1024 : length; c = 0; -- cgit v0.10.2 From cd9ae9e4db8a62cfbdaec2d73f8c34eea66c48d5 Mon Sep 17 00:00:00 2001 From: sayli karnik <karniksayli1995@gmail.com> Date: Mon, 19 Sep 2016 20:02:40 +0530 Subject: staging: i4l: act2000: Move assignment out of if statement This patch places assignments which are inside the if condition, above it. Done using coccinelle: @@ statement s; expression e; identifier id; @@ - if ((id = e)) + id = e; + if (id) s Signed-off-by: sayli karnik <karniksayli1995@gmail.com> Acked-by: Julia Lawall <julia.lawall@lip6.fr> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/i4l/act2000/module.c b/drivers/staging/i4l/act2000/module.c index 39a8940..99c9c0a 100644 --- a/drivers/staging/i4l/act2000/module.c +++ b/drivers/staging/i4l/act2000/module.c @@ -289,7 +289,8 @@ act2000_command(act2000_card *card, isdn_ctrl *c) if (copy_from_user(tmp, arg, sizeof(tmp))) return -EFAULT; - if ((ret = act2000_set_msn(card, tmp))) + ret = act2000_set_msn(card, tmp); + if (ret) return ret; if (card->flags & ACT2000_FLAGS_RUNNING) return (actcapi_manufacturer_req_msn(card)); -- cgit v0.10.2 From 24586a35d3edfed3217fec3597861d52eb6d5814 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar <bankarsandhya512@gmail.com> Date: Sun, 18 Sep 2016 23:02:33 +0530 Subject: Staging: octeon: Add missing of_node_put after calling of_parse_phandle. of_node_put needs to be called when the device node which is got from of_parse_phandle is no longer used. This patch is found by below coccinelle script: @@ expression e,e1,e2; @@ *e = of_parse_phandle(...) ... when != of_node_put(e) when != true e == NULL when != e2 = e e = e1 Signed-off-by: Sandhya Bankar <bankarsandhya512@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c index 1fde9c8..691e4a5 100644 --- a/drivers/staging/octeon/ethernet-mdio.c +++ b/drivers/staging/octeon/ethernet-mdio.c @@ -168,6 +168,7 @@ int cvm_oct_phy_setup_device(struct net_device *dev) phydev = of_phy_connect(dev, phy_node, cvm_oct_adjust_link, 0, PHY_INTERFACE_MODE_GMII); + of_node_put(phy_node); if (!phydev) return -ENODEV; -- cgit v0.10.2 From 905a672a2f97755c3d7787a125cda100096c999d Mon Sep 17 00:00:00 2001 From: Sandhya Bankar <bankarsandhya512@gmail.com> Date: Sun, 18 Sep 2016 05:07:21 +0530 Subject: Staging: fsl-mc: Use !x instead of x == NULL. Use !x instead of x == NULL. This issue was found by checkpatch. Signed-off-by: Sandhya Bankar <bankarsandhya512@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-msi.c b/drivers/staging/fsl-mc/bus/fsl-mc-msi.c index cc19092..bc1ad1a 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-msi.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-msi.c @@ -50,7 +50,7 @@ static void fsl_mc_msi_update_dom_ops(struct msi_domain_info *info) /* * set_desc should not be set by the caller */ - if (ops->set_desc == NULL) + if (!ops->set_desc) ops->set_desc = fsl_mc_msi_set_desc; } @@ -140,7 +140,7 @@ static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info) /* * irq_write_msi_msg should not be set by the caller */ - if (chip->irq_write_msi_msg == NULL) + if (!chip->irq_write_msi_msg) chip->irq_write_msi_msg = fsl_mc_msi_write_msg; } -- cgit v0.10.2 From 197cc86e8e0de1f9f4d2a738e73b9acf34bdc347 Mon Sep 17 00:00:00 2001 From: Hariharan R <hariharanrangasamy@gmail.com> Date: Sun, 18 Sep 2016 20:16:03 -0400 Subject: staging: ks7010: fixes typo in ks_hostif.c Fixes typo, FAILUER -> FAILURE Recieve -> Receive Signed-off-by: Hariharan R <hariharanrangasamy@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c index eb0192d..f2bdd47 100644 --- a/drivers/staging/ks7010/ks_hostif.c +++ b/drivers/staging/ks7010/ks_hostif.c @@ -1226,7 +1226,7 @@ int hostif_data_request(struct ks_wlan_private *priv, struct sk_buff *packet) eth_hdr = (struct ether_hdr *)&pp->data[0]; eth_proto = ntohs(eth_hdr->h_proto); - /* for MIC FAILUER REPORT check */ + /* for MIC FAILURE REPORT check */ if (eth_proto == ETHER_PROTOCOL_TYPE_EAP && priv->wpa.mic_failure.failure > 0) { aa1x_hdr = (struct ieee802_1x_hdr *)(eth_hdr + 1); @@ -1279,7 +1279,7 @@ int hostif_data_request(struct ks_wlan_private *priv, struct sk_buff *packet) (void *)send_packet_complete, (void *)priv, (void *)packet); - /* MIC FAILUER REPORT check */ + /* MIC FAILURE REPORT check */ if (eth_proto == ETHER_PROTOCOL_TYPE_EAP && priv->wpa.mic_failure.failure > 0) { if (keyinfo & WPA_KEY_INFO_ERROR @@ -1848,7 +1848,7 @@ void hostif_mic_failure_request(struct ks_wlan_private *priv, ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp)), NULL, NULL, NULL); } -/* Device I/O Recieve indicate */ +/* Device I/O Receive indicate */ static void devio_rec_ind(struct ks_wlan_private *priv, unsigned char *p, unsigned int size) { -- cgit v0.10.2 From 0525a57b1879370fe0e330708bda3b1c25c937f1 Mon Sep 17 00:00:00 2001 From: sayli karnik <karniksayli1995@gmail.com> Date: Mon, 19 Sep 2016 01:46:34 +0530 Subject: staging: ks7010: Remove unnecessary variable used to store return value This patch removes an unnecessary variable used to store return values in order to reduce memory usage. Done using coccinelle: @@ type T; constant C; identifier ret; @@ - T ret = C; ... when != ret return - ret + C ; Signed-off-by: sayli karnik <karniksayli1995@gmail.com> Acked-by: Julia Lawall <julia.lawall@lip6.fr> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c index f2bdd47..e6f6445 100644 --- a/drivers/staging/ks7010/ks_hostif.c +++ b/drivers/staging/ks7010/ks_hostif.c @@ -92,8 +92,6 @@ static void ks_wlan_hw_wakeup_task(struct work_struct *work) static int ks_wlan_do_power_save(struct ks_wlan_private *priv) { - int rc = 0; - DPRINTK(4, "psstatus.status=%d\n", atomic_read(&priv->psstatus.status)); if ((priv->connect_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) { @@ -101,7 +99,7 @@ int ks_wlan_do_power_save(struct ks_wlan_private *priv) } else { priv->dev_state = DEVICE_STATE_READY; } - return rc; + return 0; } static @@ -213,7 +211,6 @@ int get_ap_information(struct ks_wlan_private *priv, struct ap_info_t *ap_info, { unsigned char *bp; int bsize, offset; - int rc = 0; DPRINTK(3, "\n"); memset(ap, 0, sizeof(struct local_ap_t)); @@ -311,7 +308,7 @@ int get_ap_information(struct ks_wlan_private *priv, struct ap_info_t *ap_info, bp += (*(bp + 1) + 2); /* pointer update */ } - return rc; + return 0; } static @@ -2681,7 +2678,6 @@ void hostif_sme_enqueue(struct ks_wlan_private *priv, unsigned short event) int hostif_init(struct ks_wlan_private *priv) { - int rc = 0; int i; DPRINTK(3, "\n"); @@ -2731,7 +2727,7 @@ int hostif_init(struct ks_wlan_private *priv) tasklet_init(&priv->sme_task, hostif_sme_task, (unsigned long)priv); - return rc; + return 0; } void hostif_exit(struct ks_wlan_private *priv) -- cgit v0.10.2 From 2d738bd28c813d35f80fa7f9931f6d16dba47dbb Mon Sep 17 00:00:00 2001 From: Sandhya Bankar <bankarsandhya512@gmail.com> Date: Tue, 20 Sep 2016 11:55:47 +0530 Subject: Staging: ks7010: Use sizeof structure *pointer over sizeof structure in kzalloc() This issue was found by checkpatch. Signed-off-by: Sandhya Bankar <bankarsandhya512@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c index 25ad43d..37a4ba3 100644 --- a/drivers/staging/ks7010/ks7010_sdio.c +++ b/drivers/staging/ks7010/ks7010_sdio.c @@ -955,7 +955,7 @@ static int ks7010_sdio_probe(struct sdio_func *func, netdev = NULL; /* initilize ks_sdio_card */ - card = kzalloc(sizeof(struct ks_sdio_card), GFP_KERNEL); + card = kzalloc(sizeof(*card), GFP_KERNEL); if (!card) return -ENOMEM; -- cgit v0.10.2 From 55d6aacd43f808746e9e929d6a0ff8a9b14d2374 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar <bankarsandhya512@gmail.com> Date: Tue, 20 Sep 2016 12:15:15 +0530 Subject: Staging: ks7010: Use "foo *bar" instead of "foo * bar" This patch was found by checkpatch. Signed-off-by: Sandhya Bankar <bankarsandhya512@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c index e6f6445..aad8048 100644 --- a/drivers/staging/ks7010/ks_hostif.c +++ b/drivers/staging/ks7010/ks_hostif.c @@ -1766,7 +1766,7 @@ void hostif_sleep_request(struct ks_wlan_private *priv, unsigned long mode) static void hostif_bss_scan_request(struct ks_wlan_private *priv, - unsigned long scan_type, uint8_t * scan_ssid, + unsigned long scan_type, uint8_t *scan_ssid, uint8_t scan_ssid_len) { struct hostif_bss_scan_request_t *pp; -- cgit v0.10.2 From d14d3557cb03903d7a477969f352ea9b57e0302d Mon Sep 17 00:00:00 2001 From: Sandhya Bankar <bankarsandhya512@gmail.com> Date: Tue, 20 Sep 2016 13:09:58 +0530 Subject: Staging: ks7010: Use "foo *bar" instead of "foo * bar". This issue was found by checkpatch. Signed-off-by: Sandhya Bankar <bankarsandhya512@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/michael_mic.h b/drivers/staging/ks7010/michael_mic.h index 89f17d5..efaa217 100644 --- a/drivers/staging/ks7010/michael_mic.h +++ b/drivers/staging/ks7010/michael_mic.h @@ -20,6 +20,6 @@ struct michel_mic_t { uint8_t Result[8]; }; -void MichaelMICFunction(struct michel_mic_t *Mic, uint8_t * Key, - uint8_t * Data, int Len, uint8_t priority, - uint8_t * Result); +void MichaelMICFunction(struct michel_mic_t *Mic, uint8_t *Key, + uint8_t *Data, int Len, uint8_t priority, + uint8_t *Result); -- cgit v0.10.2 From 7e935f181c00f779b3112ae57f423b3d3428e94a Mon Sep 17 00:00:00 2001 From: Sandhya Bankar <bankarsandhya512@gmail.com> Date: Tue, 20 Sep 2016 13:11:39 +0530 Subject: Staging: ks7010: michael_mic: Use "foo *bar" instead of "foo * bar". This issue was found by checkpatch. Signed-off-by: Sandhya Bankar <bankarsandhya512@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/michael_mic.c b/drivers/staging/ks7010/michael_mic.c index d332678..78ae2b8 100644 --- a/drivers/staging/ks7010/michael_mic.c +++ b/drivers/staging/ks7010/michael_mic.c @@ -37,7 +37,7 @@ do { \ } while (0) static -void MichaelInitializeFunction(struct michel_mic_t *Mic, uint8_t * key) +void MichaelInitializeFunction(struct michel_mic_t *Mic, uint8_t *key) { // Set the key Mic->K0 = getUInt32(key, 0); @@ -60,7 +60,7 @@ do{ \ }while(0) static -void MichaelAppend(struct michel_mic_t *Mic, uint8_t * src, int nBytes) +void MichaelAppend(struct michel_mic_t *Mic, uint8_t *src, int nBytes) { int addlen; if (Mic->nBytesInM) { @@ -94,7 +94,7 @@ void MichaelAppend(struct michel_mic_t *Mic, uint8_t * src, int nBytes) } static -void MichaelGetMIC(struct michel_mic_t *Mic, uint8_t * dst) +void MichaelGetMIC(struct michel_mic_t *Mic, uint8_t *dst) { uint8_t *data = Mic->M; switch (Mic->nBytesInM) { @@ -122,9 +122,9 @@ void MichaelGetMIC(struct michel_mic_t *Mic, uint8_t * dst) MichaelClear(Mic); } -void MichaelMICFunction(struct michel_mic_t *Mic, uint8_t * Key, - uint8_t * Data, int Len, uint8_t priority, - uint8_t * Result) +void MichaelMICFunction(struct michel_mic_t *Mic, uint8_t *Key, + uint8_t *Data, int Len, uint8_t priority, + uint8_t *Result) { uint8_t pad_data[4] = { priority, 0, 0, 0 }; // Compute the MIC value -- cgit v0.10.2 From e29cebe90120b4ceb5e707cee55ad65427420216 Mon Sep 17 00:00:00 2001 From: Cathal Mullaney <chuckleberryfinn@gmail.com> Date: Sun, 18 Sep 2016 20:08:45 +0100 Subject: Staging: rts5208: rtsx_card.c: Fixed brace style issues Fixed several minor brace coding style issues. Signed-off-by: Cathal Mullaney <chuckleberryfinn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rts5208/rtsx_card.c b/drivers/staging/rts5208/rtsx_card.c index 91e62c1..9771774 100644 --- a/drivers/staging/rts5208/rtsx_card.c +++ b/drivers/staging/rts5208/rtsx_card.c @@ -1027,26 +1027,26 @@ int card_share_mode(struct rtsx_chip *chip, int card) if (CHECK_PID(chip, 0x5208)) { mask = CARD_SHARE_MASK; - if (card == SD_CARD) + if (card == SD_CARD) { value = CARD_SHARE_48_SD; - else if (card == MS_CARD) + } else if (card == MS_CARD) { value = CARD_SHARE_48_MS; - else if (card == XD_CARD) + } else if (card == XD_CARD) { value = CARD_SHARE_48_XD; - else { + } else { rtsx_trace(chip); return STATUS_FAIL; } } else if (CHECK_PID(chip, 0x5288)) { mask = 0x03; - if (card == SD_CARD) + if (card == SD_CARD) { value = CARD_SHARE_BAROSSA_SD; - else if (card == MS_CARD) + } else if (card == MS_CARD) { value = CARD_SHARE_BAROSSA_MS; - else if (card == XD_CARD) + } else if (card == XD_CARD) { value = CARD_SHARE_BAROSSA_XD; - else { + } else { rtsx_trace(chip); return STATUS_FAIL; } @@ -1072,15 +1072,15 @@ int select_card(struct rtsx_chip *chip, int card) if (chip->cur_card != card) { u8 mod; - if (card == SD_CARD) + if (card == SD_CARD) { mod = SD_MOD_SEL; - else if (card == MS_CARD) + } else if (card == MS_CARD) { mod = MS_MOD_SEL; - else if (card == XD_CARD) + } else if (card == XD_CARD) { mod = XD_MOD_SEL; - else if (card == SPI_CARD) + } else if (card == SPI_CARD) { mod = SPI_MOD_SEL; - else { + } else { rtsx_trace(chip); return STATUS_FAIL; } -- cgit v0.10.2 From f432bc81415d7592e664485701c55dc5c6672a3b Mon Sep 17 00:00:00 2001 From: Sandhya Bankar <bankarsandhya512@gmail.com> Date: Mon, 19 Sep 2016 14:42:24 +0530 Subject: Staging: rts5208: ms: Use x instead of x != NULL. Use x instead of x != NULL. This patch was found by checkpatch. Signed-off-by: Sandhya Bankar <bankarsandhya512@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c index f927ba6..6afddea 100644 --- a/drivers/staging/rts5208/ms.c +++ b/drivers/staging/rts5208/ms.c @@ -4077,7 +4077,7 @@ void ms_free_l2p_tbl(struct rtsx_chip *chip) struct ms_info *ms_card = &chip->ms_card; int i = 0; - if (ms_card->segment != NULL) { + if (ms_card->segment) { for (i = 0; i < ms_card->segment_cnt; i++) { vfree(ms_card->segment[i].l2p_table); ms_card->segment[i].l2p_table = NULL; -- cgit v0.10.2 From 8bee668de51b7c5ed59be2696a199a335af3397a Mon Sep 17 00:00:00 2001 From: Sandhya Bankar <bankarsandhya512@gmail.com> Date: Mon, 19 Sep 2016 14:45:04 +0530 Subject: Staging: rts5208: rtsx: Use x instead of x != NULL. Use x instead of x != NULL. This patch was found by checkpatch. Signed-off-by: Sandhya Bankar <bankarsandhya512@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index d75fa8d..d7554f4 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -131,7 +131,7 @@ static int queuecommand_lck(struct scsi_cmnd *srb, struct rtsx_chip *chip = dev->chip; /* check for state-transition errors */ - if (chip->srb != NULL) { + if (chip->srb) { dev_err(&dev->pci->dev, "Error: chip->srb = %p\n", chip->srb); return SCSI_MLQUEUE_HOST_BUSY; -- cgit v0.10.2 From 5173abfc05095da983f16de4c5e2185c7eb1934a Mon Sep 17 00:00:00 2001 From: Sandhya Bankar <bankarsandhya512@gmail.com> Date: Mon, 19 Sep 2016 17:00:16 +0530 Subject: Staging: rts5208: Add space around operator. Add space around operator. This patch was found by checkpatch. Signed-off-by: Sandhya Bankar <bankarsandhya512@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rts5208/rtsx_chip.c b/drivers/staging/rts5208/rtsx_chip.c index c75493a..a10dd62 100644 --- a/drivers/staging/rts5208/rtsx_chip.c +++ b/drivers/staging/rts5208/rtsx_chip.c @@ -743,7 +743,7 @@ static inline int check_sd_speed_prior(u32 sd_speed_prior) int i; for (i = 0; i < 4; i++) { - u8 tmp = (u8)(sd_speed_prior >> (i*8)); + u8 tmp = (u8)(sd_speed_prior >> (i * 8)); if ((tmp < 0x01) || (tmp > 0x04)) { fake_para = true; @@ -2336,7 +2336,7 @@ int rtsx_write_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len) ptr = buf; reg_addr = PPBUF_BASE2; - for (i = 0; i < buf_len/256; i++) { + for (i = 0; i < buf_len / 256; i++) { rtsx_init_cmd(chip); for (j = 0; j < 256; j++) { @@ -2352,10 +2352,10 @@ int rtsx_write_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len) } } - if (buf_len%256) { + if (buf_len % 256) { rtsx_init_cmd(chip); - for (j = 0; j < buf_len%256; j++) { + for (j = 0; j < buf_len % 256; j++) { rtsx_add_cmd(chip, WRITE_REG_CMD, reg_addr++, 0xFF, *ptr); ptr++; -- cgit v0.10.2 From 4b72aa8af0eec14486442d0ad7afabdeb9abca91 Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Tue, 20 Sep 2016 13:30:47 +0530 Subject: staging: media: davinci_vpfe: Merge assignment with return Instead of storing the return value into a variable and then returning it, we can club the two into a single return statement. This change was made using the following semantic patch by Coccinelle: @@ local idexpression ret; expression e; @@ -ret = +return e; -return ret; Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif.c b/drivers/staging/media/davinci_vpfe/dm365_isif.c index ae9202d..569bcdc 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_isif.c +++ b/drivers/staging/media/davinci_vpfe/dm365_isif.c @@ -146,9 +146,8 @@ enum v4l2_field vpfe_isif_get_fid(struct vpfe_device *vpfe_dev) u32 field_status; field_status = isif_read(isif->isif_cfg.base_addr, MODESET); - field_status = (field_status >> DM365_ISIF_MDFS_OFFSET) & - DM365_ISIF_MDFS_MASK; - return field_status; + return (field_status >> DM365_ISIF_MDFS_OFFSET) & + DM365_ISIF_MDFS_MASK; } static int @@ -594,8 +593,7 @@ isif_validate_raw_params(struct vpfe_isif_raw_config *params) ret = isif_validate_dfc_params(¶ms->dfc); if (ret) return ret; - ret = isif_validate_bclamp_params(¶ms->bclamp); - return ret; + return isif_validate_bclamp_params(¶ms->bclamp); } static int isif_set_params(struct v4l2_subdev *sd, void *params) -- cgit v0.10.2 From 4b9fd698ac98fd578818461ccbd79f27139c8ee3 Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Tue, 20 Sep 2016 13:30:24 +0530 Subject: staging: media: bcm2048: Merge assignment with return Instead of storing the return value into a variable and then returning it, we can club the two into a single return statement. This change was made using the following semantic patch by Coccinelle: @@ local idexpression ret; expression e; @@ -ret = +return e; -return ret; Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/media/bcm2048/radio-bcm2048.c b/drivers/staging/media/bcm2048/radio-bcm2048.c index 8dade19..ea15cc6 100644 --- a/drivers/staging/media/bcm2048/radio-bcm2048.c +++ b/drivers/staging/media/bcm2048/radio-bcm2048.c @@ -483,10 +483,8 @@ static int bcm2048_set_rds_no_lock(struct bcm2048_device *bdev, u8 rds_on) memset(&bdev->rds_info, 0, sizeof(bdev->rds_info)); } - err = bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_SYSTEM, - bdev->cache_fm_rds_system); - - return err; + return bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_SYSTEM, + bdev->cache_fm_rds_system); } static int bcm2048_get_rds_no_lock(struct bcm2048_device *bdev) @@ -1834,9 +1832,7 @@ static int bcm2048_deinit(struct bcm2048_device *bdev) if (err < 0) return err; - err = bcm2048_set_power_state(bdev, BCM2048_POWER_OFF); - - return err; + return bcm2048_set_power_state(bdev, BCM2048_POWER_OFF); } /* @@ -1995,9 +1991,7 @@ static ssize_t bcm2048_##prop##_read(struct device *dev, \ \ value = bcm2048_get_##prop(bdev); \ \ - value = sprintf(buf, mask "\n", value); \ - \ - return value; \ + return sprintf(buf, mask "\n", value); \ } #define DEFINE_SYSFS_PROPERTY(prop, signal, size, mask, check) \ -- cgit v0.10.2 From 0ea5f7c6808b4ecfc5b045d9cab81803f27670fb Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya <eraretuya@gmail.com> Date: Tue, 20 Sep 2016 15:00:49 +0800 Subject: staging: media: cxd2099: replace printk with dev_info Use dev_info() instead of printk(). Majority of the conversion was done previously on this commit: 011b2aa [media] staging/media: Use dev_ printks in cxd2099/cxd2099.[ch] Signed-off-by: Eva Rachel Retuya <eraretuya@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/media/cxd2099/cxd2099.c b/drivers/staging/media/cxd2099/cxd2099.c index 692ba3e..fedeb3c 100644 --- a/drivers/staging/media/cxd2099/cxd2099.c +++ b/drivers/staging/media/cxd2099/cxd2099.c @@ -660,7 +660,7 @@ static int write_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount) struct cxd *ci = ca->data; mutex_lock(&ci->lock); - printk(kern_INFO "write_data %d\n", ecount); + dev_info(&ci->i2c->dev, "write_data %d\n", ecount); write_reg(ci, 0x0d, ecount>>8); write_reg(ci, 0x0e, ecount&0xff); write_block(ci, 0x11, ebuf, ecount); -- cgit v0.10.2 From 520a28443fb2f28a663053feb4431c0083268d75 Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya <eraretuya@gmail.com> Date: Tue, 20 Sep 2016 11:09:05 +0800 Subject: staging: most: hdm-usb: convert pr_warn() to dev_warn() Replace pr_warn() call with its respective dev_warn() counterpart. Semantic patch used to detect and apply the transformation: @a@ identifier dev; expression E; @@ struct device *dev = E; <+... when != dev == NULL - pr_warn( + dev_warn(dev, ...); ...+> Signed-off-by: Eva Rachel Retuya <eraretuya@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index 9deb28c..084bd00 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -1267,8 +1267,8 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) ep_desc->bEndpointAddress * 16, 1); if (err < 0) - pr_warn("DCI Sync for EP %02x failed", - ep_desc->bEndpointAddress); + dev_warn(dev, "DCI Sync for EP %02x failed", + ep_desc->bEndpointAddress); } dev_notice(dev, "claimed gadget: Vendor=%4.4x ProdID=%4.4x Bus=%02x Device=%02x\n", le16_to_cpu(usb_dev->descriptor.idVendor), -- cgit v0.10.2 From f4353ee3d3af22641beb99a146ef136f33952e80 Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Tue, 20 Sep 2016 01:05:54 +0530 Subject: staging: wlan-ng: Remove unnecessary variable usage Instead of storing the return value into a variable and then returning it, we can club the two into a single return statement. This change was made using the following semantic patch by Coccinelle: @@ local idexpression ret; expression e; @@ -ret = +return e; -return ret; Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c index 73ea127..b380c7d 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.c +++ b/drivers/staging/wlan-ng/prism2mgmt.c @@ -685,9 +685,7 @@ failed: msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters; done: - result = 0; - - return result; + return 0; } /*---------------------------------------------------------------- -- cgit v0.10.2 From f1f5b4303daab5c2e2dbb90d047763367cf556ca Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Mon, 19 Sep 2016 19:26:32 +0530 Subject: staging: sm750fb: Add spaces around '|' Adds spaces on either side of a '|'. Issue found by checkpatch. Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/sm750fb/ddk750_display.h b/drivers/staging/sm750fb/ddk750_display.h index ca35aa1..5fc9f6f 100644 --- a/drivers/staging/sm750fb/ddk750_display.h +++ b/drivers/staging/sm750fb/ddk750_display.h @@ -8,8 +8,8 @@ #define PNL_2_OFFSET 0 #define PNL_2_MASK (3 << PNL_2_OFFSET) #define PNL_2_USAGE (PNL_2_MASK << 16) -#define PNL_2_PRI ((0 << PNL_2_OFFSET)|PNL_2_USAGE) -#define PNL_2_SEC ((2 << PNL_2_OFFSET)|PNL_2_USAGE) +#define PNL_2_PRI ((0 << PNL_2_OFFSET) | PNL_2_USAGE) +#define PNL_2_SEC ((2 << PNL_2_OFFSET) | PNL_2_USAGE) /* primary timing & plane enable bit @@ -19,8 +19,8 @@ #define PRI_TP_OFFSET 4 #define PRI_TP_MASK BIT(PRI_TP_OFFSET) #define PRI_TP_USAGE (PRI_TP_MASK << 16) -#define PRI_TP_ON ((0x1 << PRI_TP_OFFSET)|PRI_TP_USAGE) -#define PRI_TP_OFF ((0x0 << PRI_TP_OFFSET)|PRI_TP_USAGE) +#define PRI_TP_ON ((0x1 << PRI_TP_OFFSET) | PRI_TP_USAGE) +#define PRI_TP_OFF ((0x0 << PRI_TP_OFFSET) | PRI_TP_USAGE) /* panel sequency status @@ -29,8 +29,8 @@ #define PNL_SEQ_OFFSET 6 #define PNL_SEQ_MASK BIT(PNL_SEQ_OFFSET) #define PNL_SEQ_USAGE (PNL_SEQ_MASK << 16) -#define PNL_SEQ_ON (BIT(PNL_SEQ_OFFSET)|PNL_SEQ_USAGE) -#define PNL_SEQ_OFF ((0 << PNL_SEQ_OFFSET)|PNL_SEQ_USAGE) +#define PNL_SEQ_ON (BIT(PNL_SEQ_OFFSET) | PNL_SEQ_USAGE) +#define PNL_SEQ_OFF ((0 << PNL_SEQ_OFFSET) | PNL_SEQ_USAGE) /* dual digital output 80000[19] @@ -38,8 +38,8 @@ #define DUAL_TFT_OFFSET 8 #define DUAL_TFT_MASK BIT(DUAL_TFT_OFFSET) #define DUAL_TFT_USAGE (DUAL_TFT_MASK << 16) -#define DUAL_TFT_ON (BIT(DUAL_TFT_OFFSET)|DUAL_TFT_USAGE) -#define DUAL_TFT_OFF ((0 << DUAL_TFT_OFFSET)|DUAL_TFT_USAGE) +#define DUAL_TFT_ON (BIT(DUAL_TFT_OFFSET) | DUAL_TFT_USAGE) +#define DUAL_TFT_OFF ((0 << DUAL_TFT_OFFSET) | DUAL_TFT_USAGE) /* secondary timing & plane enable bit 1:80200[8] & 80200[2] on @@ -48,8 +48,8 @@ #define SEC_TP_OFFSET 5 #define SEC_TP_MASK BIT(SEC_TP_OFFSET) #define SEC_TP_USAGE (SEC_TP_MASK << 16) -#define SEC_TP_ON ((0x1 << SEC_TP_OFFSET)|SEC_TP_USAGE) -#define SEC_TP_OFF ((0x0 << SEC_TP_OFFSET)|SEC_TP_USAGE) +#define SEC_TP_ON ((0x1 << SEC_TP_OFFSET) | SEC_TP_USAGE) +#define SEC_TP_OFF ((0x0 << SEC_TP_OFFSET) | SEC_TP_USAGE) /* crt path select 80200[19:18] @@ -57,8 +57,8 @@ #define CRT_2_OFFSET 2 #define CRT_2_MASK (3 << CRT_2_OFFSET) #define CRT_2_USAGE (CRT_2_MASK << 16) -#define CRT_2_PRI ((0x0 << CRT_2_OFFSET)|CRT_2_USAGE) -#define CRT_2_SEC ((0x2 << CRT_2_OFFSET)|CRT_2_USAGE) +#define CRT_2_PRI ((0x0 << CRT_2_OFFSET) | CRT_2_USAGE) +#define CRT_2_SEC ((0x2 << CRT_2_OFFSET) | CRT_2_USAGE) /* DAC affect both DVI and DSUB @@ -67,8 +67,8 @@ #define DAC_OFFSET 7 #define DAC_MASK BIT(DAC_OFFSET) #define DAC_USAGE (DAC_MASK << 16) -#define DAC_ON ((0x0 << DAC_OFFSET)|DAC_USAGE) -#define DAC_OFF ((0x1 << DAC_OFFSET)|DAC_USAGE) +#define DAC_ON ((0x0 << DAC_OFFSET) | DAC_USAGE) +#define DAC_OFF ((0x1 << DAC_OFFSET) | DAC_USAGE) /* DPMS only affect D-SUB head 0[31:30] @@ -76,8 +76,8 @@ #define DPMS_OFFSET 9 #define DPMS_MASK (3 << DPMS_OFFSET) #define DPMS_USAGE (DPMS_MASK << 16) -#define DPMS_OFF ((3 << DPMS_OFFSET)|DPMS_USAGE) -#define DPMS_ON ((0 << DPMS_OFFSET)|DPMS_USAGE) +#define DPMS_OFF ((3 << DPMS_OFFSET) | DPMS_USAGE) +#define DPMS_ON ((0 << DPMS_OFFSET) | DPMS_USAGE) @@ -86,16 +86,16 @@ CRT means crt path DSUB */ typedef enum _disp_output_t { - do_LCD1_PRI = PNL_2_PRI|PRI_TP_ON|PNL_SEQ_ON|DAC_ON, - do_LCD1_SEC = PNL_2_SEC|SEC_TP_ON|PNL_SEQ_ON|DAC_ON, - do_LCD2_PRI = CRT_2_PRI|PRI_TP_ON|DUAL_TFT_ON, - do_LCD2_SEC = CRT_2_SEC|SEC_TP_ON|DUAL_TFT_ON, + do_LCD1_PRI = PNL_2_PRI | PRI_TP_ON | PNL_SEQ_ON | DAC_ON, + do_LCD1_SEC = PNL_2_SEC | SEC_TP_ON | PNL_SEQ_ON | DAC_ON, + do_LCD2_PRI = CRT_2_PRI | PRI_TP_ON | DUAL_TFT_ON, + do_LCD2_SEC = CRT_2_SEC | SEC_TP_ON | DUAL_TFT_ON, /* do_DSUB_PRI = CRT_2_PRI|PRI_TP_ON|DPMS_ON|DAC_ON, do_DSUB_SEC = CRT_2_SEC|SEC_TP_ON|DPMS_ON|DAC_ON, */ - do_CRT_PRI = CRT_2_PRI|PRI_TP_ON|DPMS_ON|DAC_ON, - do_CRT_SEC = CRT_2_SEC|SEC_TP_ON|DPMS_ON|DAC_ON, + do_CRT_PRI = CRT_2_PRI | PRI_TP_ON | DPMS_ON | DAC_ON, + do_CRT_SEC = CRT_2_SEC | SEC_TP_ON | DPMS_ON | DAC_ON, } disp_output_t; -- cgit v0.10.2 From 58d44745254f30bdc8cd14baf9722e7934495a64 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar <bankarsandhya512@gmail.com> Date: Mon, 19 Sep 2016 17:47:21 +0530 Subject: Staging: vt6655: card: Remove unnecessary space after a cast No space is necessary after a cast. This issue was found by checkpatch. Signed-off-by: Sandhya Bankar <bankarsandhya512@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c index afb1e8b..dbcea44 100644 --- a/drivers/staging/vt6655/card.c +++ b/drivers/staging/vt6655/card.c @@ -619,7 +619,7 @@ CARDvSafeResetRx( static unsigned short CARDwGetCCKControlRate(struct vnt_private *priv, unsigned short wRateIdx) { - unsigned int ui = (unsigned int) wRateIdx; + unsigned int ui = (unsigned int)wRateIdx; while (ui > RATE_1M) { if (priv->basic_rates & ((u32)0x1 << ui)) @@ -645,7 +645,7 @@ static unsigned short CARDwGetCCKControlRate(struct vnt_private *priv, static unsigned short CARDwGetOFDMControlRate(struct vnt_private *priv, unsigned short wRateIdx) { - unsigned int ui = (unsigned int) wRateIdx; + unsigned int ui = (unsigned int)wRateIdx; pr_debug("BASIC RATE: %X\n", priv->basic_rates); -- cgit v0.10.2 From 33d877bb42df3db877677039746a71c93322add2 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar <bankarsandhya512@gmail.com> Date: Mon, 19 Sep 2016 17:44:43 +0530 Subject: Staging: vt6655: baseband: Remove unnecessary space after a cast No space is necessary after a cast. This issue was found by checkpatch. Signed-off-by: Sandhya Bankar <bankarsandhya512@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/vt6655/baseband.c b/drivers/staging/vt6655/baseband.c index 654d072..de503a3 100644 --- a/drivers/staging/vt6655/baseband.c +++ b/drivers/staging/vt6655/baseband.c @@ -1729,7 +1729,7 @@ BBuGetFrameTime( unsigned int uFrameTime; unsigned int uPreamble; unsigned int uTmp; - unsigned int uRateIdx = (unsigned int) wRate; + unsigned int uRateIdx = (unsigned int)wRate; unsigned int uRate = 0; if (uRateIdx > RATE_54M) -- cgit v0.10.2 From ec9d0754e0c64013278fda87d1bd6b8318747abe Mon Sep 17 00:00:00 2001 From: sayli karnik <karniksayli1995@gmail.com> Date: Tue, 20 Sep 2016 03:21:38 +0530 Subject: staging: comedi: Use vma_pages function on vma object instead of explicit computation This patch uses vma_pages function on vma object instead of explicit computation. Signed-off-by: sayli karnik <karniksayli1995@gmail.com> Reviewed-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index bf922ea..64b3966 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -2233,7 +2233,7 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma) goto done; } - n_pages = size >> PAGE_SHIFT; + n_pages = vma_pages(vma); /* get reference to current buf map (if any) */ bm = comedi_buf_map_from_subdev_get(s); -- cgit v0.10.2 From c86bdd474a0c7b644fff91e0db069040c6a39926 Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Tue, 20 Sep 2016 16:44:51 +0530 Subject: staging: rts5208: Remove unnecessary parentheses Removes unnecessary parentheses from an expression of the form &(x). Issue found by checkpatch. Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c index 6afddea..2f528ad 100644 --- a/drivers/staging/rts5208/ms.c +++ b/drivers/staging/rts5208/ms.c @@ -2465,7 +2465,7 @@ static u16 ms_get_l2p_tbl(struct rtsx_chip *chip, int seg_no, u16 log_off) if (!ms_card->segment) return 0xFFFF; - segment = &(ms_card->segment[seg_no]); + segment = &ms_card->segment[seg_no]; if (segment->l2p_table) return segment->l2p_table[log_off]; @@ -2482,7 +2482,7 @@ static void ms_set_l2p_tbl(struct rtsx_chip *chip, if (!ms_card->segment) return; - segment = &(ms_card->segment[seg_no]); + segment = &ms_card->segment[seg_no]; if (segment->l2p_table) segment->l2p_table[log_off] = phy_blk; } @@ -2494,7 +2494,7 @@ static void ms_set_unused_block(struct rtsx_chip *chip, u16 phy_blk) int seg_no; seg_no = (int)phy_blk >> 9; - segment = &(ms_card->segment[seg_no]); + segment = &ms_card->segment[seg_no]; segment->free_table[segment->set_index++] = phy_blk; if (segment->set_index >= MS_FREE_TABLE_CNT) @@ -2509,7 +2509,7 @@ static u16 ms_get_unused_block(struct rtsx_chip *chip, int seg_no) struct zone_entry *segment; u16 phy_blk; - segment = &(ms_card->segment[seg_no]); + segment = &ms_card->segment[seg_no]; if (segment->unused_blk_cnt <= 0) return 0xFFFF; @@ -2538,7 +2538,7 @@ static int ms_arbitrate_l2p(struct rtsx_chip *chip, u16 phy_blk, u16 tmp_blk; seg_no = (int)phy_blk >> 9; - segment = &(ms_card->segment[seg_no]); + segment = &ms_card->segment[seg_no]; tmp_blk = segment->l2p_table[log_off]; if (us1 != us2) { @@ -2602,7 +2602,7 @@ static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no) else table_size = 496; - segment = &(ms_card->segment[seg_no]); + segment = &ms_card->segment[seg_no]; if (!segment->l2p_table) { segment->l2p_table = vmalloc(table_size * 2); @@ -3760,7 +3760,7 @@ static int ms_prepare_write(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, int ms_delay_write(struct rtsx_chip *chip) { struct ms_info *ms_card = &chip->ms_card; - struct ms_delay_write_tag *delay_write = &(ms_card->delay_write); + struct ms_delay_write_tag *delay_write = &ms_card->delay_write; int retval; if (delay_write->delay_write_flag) { @@ -3806,7 +3806,7 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, u8 start_page, end_page = 0, page_cnt; u8 *ptr; #ifdef MS_DELAY_WRITE - struct ms_delay_write_tag *delay_write = &(ms_card->delay_write); + struct ms_delay_write_tag *delay_write = &ms_card->delay_write; #endif ms_set_err_code(chip, MS_NO_ERROR); @@ -4696,7 +4696,7 @@ SetICVFinish: void ms_cleanup_work(struct rtsx_chip *chip) { - struct ms_info *ms_card = &(chip->ms_card); + struct ms_info *ms_card = &chip->ms_card; if (CHK_MSPRO(ms_card)) { if (ms_card->seq_mode) { @@ -4761,7 +4761,7 @@ int ms_power_off_card3v3(struct rtsx_chip *chip) int release_ms_card(struct rtsx_chip *chip) { - struct ms_info *ms_card = &(chip->ms_card); + struct ms_info *ms_card = &chip->ms_card; int retval; #ifdef MS_DELAY_WRITE -- cgit v0.10.2 From 50024433d40f8a152027577a9bba1c45f02fe196 Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Tue, 20 Sep 2016 16:45:04 +0530 Subject: staging: rts5208: Add spaces around operators Adds spaces on either side of arithmetic and relational operators like '-', '<' and '*'. Issue found by checkpatch. Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c index 2f528ad..9fc64da 100644 --- a/drivers/staging/rts5208/ms.c +++ b/drivers/staging/rts5208/ms.c @@ -2711,7 +2711,7 @@ static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no) us2 = extra[0] & 0x10; (void)ms_arbitrate_l2p(chip, phy_blk, - log_blk-ms_start_idx[seg_no], us1, us2); + log_blk - ms_start_idx[seg_no], us1, us2); continue; } @@ -3986,7 +3986,7 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, for (seg_no = 0; seg_no < ARRAY_SIZE(ms_start_idx) - 1; seg_no++) { - if (log_blk < ms_start_idx[seg_no+1]) + if (log_blk < ms_start_idx[seg_no + 1]) break; } @@ -4648,8 +4648,8 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip) rtsx_send_cmd_no_wait(chip); - retval = rtsx_transfer_data(chip, MS_CARD, buf + 4 + i*512, - 512, 0, DMA_TO_DEVICE, 3000); + retval = rtsx_transfer_data(chip, MS_CARD, buf + 4 + i * 512, + 512, 0, DMA_TO_DEVICE, 3000); if ((retval < 0) || check_ms_err(chip)) { rtsx_clear_ms_error(chip); if (ms_card->mg_auth == 0) { -- cgit v0.10.2 From bd778ef093a7c0356524f99244a19c0d04241339 Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Tue, 20 Sep 2016 16:45:33 +0530 Subject: staging: rts5208: Fix indentation Fixes indentation by removing unnecessary TAB. Issue found by checkpatch. Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rts5208/rtsx.h b/drivers/staging/rts5208/rtsx.h index 2f902d5..c0f513c 100644 --- a/drivers/staging/rts5208/rtsx.h +++ b/drivers/staging/rts5208/rtsx.h @@ -70,10 +70,10 @@ #define rtsx_write_config_byte(chip, where, val) \ pci_write_config_byte((chip)->rtsx->pci, where, val) -#define wait_timeout_x(task_state, msecs) \ -do { \ - set_current_state((task_state)); \ - schedule_timeout((msecs) * HZ / 1000); \ +#define wait_timeout_x(task_state, msecs) \ +do { \ + set_current_state((task_state)); \ + schedule_timeout((msecs) * HZ / 1000); \ } while (0) #define wait_timeout(msecs) wait_timeout_x(TASK_INTERRUPTIBLE, (msecs)) -- cgit v0.10.2 From 03282179691330602ec5ab8223b741864452656c Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Tue, 20 Sep 2016 16:45:48 +0530 Subject: staging: rts5208: Put constant on right side of comparison Replaces position of constant from left to right side of a comparison. Additionally, modifies logical continuations to be on the previous line and fixes alignment to match open parenthesis. Issues found by checkpatch. Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rts5208/sd.c b/drivers/staging/rts5208/sd.c index 345313a..e72c432 100644 --- a/drivers/staging/rts5208/sd.c +++ b/drivers/staging/rts5208/sd.c @@ -1436,9 +1436,9 @@ static int sd_switch_function(struct rtsx_chip *chip, u8 bus_width) func_to_switch); #ifdef SUPPORT_SD_LOCK - if ((sd_card->sd_lock_status & SD_SDR_RST) - && (DDR50_SUPPORT == func_to_switch) - && (sd_card->func_group1_mask & SDR50_SUPPORT_MASK)) { + if ((sd_card->sd_lock_status & SD_SDR_RST) && + (func_to_switch == DDR50_SUPPORT) && + (sd_card->func_group1_mask & SDR50_SUPPORT_MASK)) { func_to_switch = SDR50_SUPPORT; dev_dbg(rtsx_dev(chip), "Using SDR50 instead of DDR50 for SD Lock\n"); } -- cgit v0.10.2 From eceef9a3f4459e84f214a83ac4c9905baca73832 Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Tue, 20 Sep 2016 16:46:05 +0530 Subject: staging: rts5208: Use BIT(x) macro Replaces left shift operation (1 << x) by BIT(x). Issue found by checkpatch. Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rts5208/rtsx_chip.h b/drivers/staging/rts5208/rtsx_chip.h index 79d1df6..132c2e6 100644 --- a/drivers/staging/rts5208/rtsx_chip.h +++ b/drivers/staging/rts5208/rtsx_chip.h @@ -266,22 +266,22 @@ struct sense_data_t { #define TRIG_DMA (0x01 << 31) /* Bus interrupt pending register */ -#define CMD_DONE_INT (1 << 31) -#define DATA_DONE_INT (1 << 30) -#define TRANS_OK_INT (1 << 29) -#define TRANS_FAIL_INT (1 << 28) -#define XD_INT (1 << 27) -#define MS_INT (1 << 26) -#define SD_INT (1 << 25) -#define GPIO0_INT (1 << 24) -#define OC_INT (1 << 23) -#define SD_WRITE_PROTECT (1 << 19) -#define XD_EXIST (1 << 18) -#define MS_EXIST (1 << 17) -#define SD_EXIST (1 << 16) +#define CMD_DONE_INT BIT(31) +#define DATA_DONE_INT BIT(30) +#define TRANS_OK_INT BIT(29) +#define TRANS_FAIL_INT BIT(28) +#define XD_INT BIT(27) +#define MS_INT BIT(26) +#define SD_INT BIT(25) +#define GPIO0_INT BIT(24) +#define OC_INT BIT(23) +#define SD_WRITE_PROTECT BIT(19) +#define XD_EXIST BIT(18) +#define MS_EXIST BIT(17) +#define SD_EXIST BIT(16) #define DELINK_INT GPIO0_INT -#define MS_OC_INT (1 << 23) -#define SD_OC_INT (1 << 22) +#define MS_OC_INT BIT(23) +#define SD_OC_INT BIT(22) #define CARD_INT (XD_INT | MS_INT | SD_INT) #define NEED_COMPLETE_INT (DATA_DONE_INT | TRANS_OK_INT | TRANS_FAIL_INT) -- cgit v0.10.2 From 7c7f23614586c4f48c4e8f4b10b62992fe38de3c Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Tue, 20 Sep 2016 16:46:24 +0530 Subject: staging: rts5208: Remove space after cast Removes unnecessary space after a cast. Issue found by checkpatch. Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rts5208/rtsx.h b/drivers/staging/rts5208/rtsx.h index c0f513c..7a21e46 100644 --- a/drivers/staging/rts5208/rtsx.h +++ b/drivers/staging/rts5208/rtsx.h @@ -135,12 +135,12 @@ typedef struct rtsx_dev rtsx_dev_t; /* Convert between rtsx_dev and the corresponding Scsi_Host */ static inline struct Scsi_Host *rtsx_to_host(struct rtsx_dev *dev) { - return container_of((void *) dev, struct Scsi_Host, hostdata); + return container_of((void *)dev, struct Scsi_Host, hostdata); } static inline struct rtsx_dev *host_to_rtsx(struct Scsi_Host *host) { - return (struct rtsx_dev *) host->hostdata; + return (struct rtsx_dev *)host->hostdata; } static inline void get_current_time(u8 *timeval_buf, int buf_len) diff --git a/drivers/staging/rts5208/xd.c b/drivers/staging/rts5208/xd.c index 126a2dc..ff423fa 100644 --- a/drivers/staging/rts5208/xd.c +++ b/drivers/staging/rts5208/xd.c @@ -937,7 +937,7 @@ static void xd_set_unused_block(struct rtsx_chip *chip, u32 phy_blk) dev_dbg(rtsx_dev(chip), "Set unused block to index %d\n", zone->set_index); - zone->free_table[zone->set_index++] = (u16) (phy_blk & 0x3ff); + zone->free_table[zone->set_index++] = (u16)(phy_blk & 0x3ff); if (zone->set_index >= XD_FREE_TABLE_CNT) zone->set_index = 0; zone->unused_blk_cnt++; -- cgit v0.10.2 From 5bd163509f61abadaff23ff8e1badd5c0c150605 Mon Sep 17 00:00:00 2001 From: Viresh Kumar <viresh.kumar@linaro.org> Date: Wed, 21 Sep 2016 12:10:16 +0530 Subject: staging: greybus: add Viresh as maintainer of few greybus protocol drivers Add Viresh Kumar as Maintainer of some of the Greybus protocol drivers. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/MAINTAINERS b/MAINTAINERS index ddd382d..e6e22e3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5314,6 +5314,23 @@ F: drivers/staging/greybus/loopback.c F: drivers/staging/greybus/timesync.c F: drivers/staging/greybus/timesync_platform.c +GREYBUS PROTOCOLS DRIVERS +M: Viresh Kumar <vireshk@kernel.org> +S: Maintained +F: drivers/staging/greybus/authentication.c +F: drivers/staging/greybus/bootrom.c +F: drivers/staging/greybus/firmware.h +F: drivers/staging/greybus/fw-core.c +F: drivers/staging/greybus/fw-download.c +F: drivers/staging/greybus/fw-managament.c +F: drivers/staging/greybus/greybus_authentication.h +F: drivers/staging/greybus/greybus_firmware.h +F: drivers/staging/greybus/hid.c +F: drivers/staging/greybus/i2c.c +F: drivers/staging/greybus/spi.c +F: drivers/staging/greybus/spilib.c +F: drivers/staging/greybus/spilib.h + GSPCA FINEPIX SUBDRIVER M: Frank Zago <frank@zago.net> L: linux-media@vger.kernel.org -- cgit v0.10.2 From 1fbf3e5f2db72c04a499f3923e6d2bba6f351344 Mon Sep 17 00:00:00 2001 From: James Simmons <jsimmons@infradead.org> Date: Tue, 20 Sep 2016 13:31:09 -0400 Subject: staging: lustre: ptlrpc: re-export lustre_swab_lov_mds_md Being over zealous in removing unused EXPORT_SYMBOLs the function lustre_swab_lov_mds_md exports were removed. They need to be exported so this patch restores those EXPORT_SYMBOLS. Same mistake was done when porting to the upstream client. Signed-off-by: James Simmons <uja.ornl@yahoo.com> Reviewed-on: http://review.whamcloud.com/14545 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6486 Reviewed-by: Dmitry Eremin <dmitry.eremin@intel.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index 1349bf6..e24d8e1 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -1914,6 +1914,7 @@ void lustre_swab_lov_mds_md(struct lov_mds_md *lmm) __swab16s(&lmm->lmm_stripe_count); __swab16s(&lmm->lmm_layout_gen); } +EXPORT_SYMBOL(lustre_swab_lov_mds_md); void lustre_swab_lov_user_md_objects(struct lov_user_ost_data *lod, int stripe_count) -- cgit v0.10.2 From 926706c59d4dbca4289b7aa20a8c47ee1006b1ce Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.sr@gmail.com> Date: Wed, 21 Sep 2016 14:17:05 +0530 Subject: staging: greybus: add maintainer for greybus audio protocol driver Add Vaibhav as maintainer of some Greybus Audio protocol drivers. Signed-off-by: Vaibhav Agarwal <vaibhav.sr@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/MAINTAINERS b/MAINTAINERS index e6e22e3..db6721b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5297,6 +5297,13 @@ M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> S: Maintained F: drivers/staging/greybus/ +GREYBUS AUDIO PROTOCOLS DRIVERS +M: Vaibhav Agarwal <vaibhav.sr@gmail.com> +S: Maintained +F: drivers/staging/greybus/audio_codec.c +F: drivers/staging/greybus/audio_module.c +F: drivers/staging/greybus/audio_topology.c + GREYBUS PROTOCOLS DRIVERS M: Rui Miguel Silva <rmfrfs@gmail.com> S: Maintained -- cgit v0.10.2 From 6083c7108193f32da8792fbbce18d80ee4ca75af Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Tue, 20 Sep 2016 11:42:03 -0400 Subject: staging: unisys: visornic: remove prototypes Remove unneeded prototypes from visornic_main.c Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index 49ee747..75d67f7 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -36,13 +36,6 @@ #define MAX_BUF 163840 #define NAPI_WEIGHT 64 -static int visornic_probe(struct visor_device *dev); -static void visornic_remove(struct visor_device *dev); -static int visornic_pause(struct visor_device *dev, - visorbus_state_complete_func complete_func); -static int visornic_resume(struct visor_device *dev, - visorbus_state_complete_func complete_func); - /* DEBUGFS declarations */ static ssize_t info_debugfs_read(struct file *file, char __user *buf, size_t len, loff_t *offset); @@ -75,23 +68,6 @@ MODULE_DEVICE_TABLE(visorbus, visornic_channel_types); */ MODULE_ALIAS("visorbus:" SPAR_VNIC_CHANNEL_PROTOCOL_UUID_STR); -/* This is used to tell the visor bus driver which types of visor devices - * we support, and what functions to call when a visor device that we support - * is attached or removed. - */ -static struct visor_driver visornic_driver = { - .name = "visornic", - .version = "1.0.0.0", - .vertag = NULL, - .owner = THIS_MODULE, - .channel_types = visornic_channel_types, - .probe = visornic_probe, - .remove = visornic_remove, - .pause = visornic_pause, - .resume = visornic_resume, - .channel_interrupt = NULL, -}; - struct chanstat { unsigned long got_rcv; unsigned long got_enbdisack; @@ -2059,6 +2035,23 @@ static int visornic_resume(struct visor_device *dev, return 0; } +/* This is used to tell the visor bus driver which types of visor devices + * we support, and what functions to call when a visor device that we support + * is attached or removed. + */ +static struct visor_driver visornic_driver = { + .name = "visornic", + .version = "1.0.0.0", + .vertag = NULL, + .owner = THIS_MODULE, + .channel_types = visornic_channel_types, + .probe = visornic_probe, + .remove = visornic_remove, + .pause = visornic_pause, + .resume = visornic_resume, + .channel_interrupt = NULL, +}; + /** * visornic_init - Init function * -- cgit v0.10.2 From 0543205b7e216288c7905cedf5ba804f3ee37599 Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Tue, 20 Sep 2016 11:42:04 -0400 Subject: staging: unisys: visornic: remove visornic debugfs protoyptes Remove visornic debugfs prototypes, they are not needed. Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index 75d67f7..beb1cf2 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -36,20 +36,6 @@ #define MAX_BUF 163840 #define NAPI_WEIGHT 64 -/* DEBUGFS declarations */ -static ssize_t info_debugfs_read(struct file *file, char __user *buf, - size_t len, loff_t *offset); -static ssize_t enable_ints_write(struct file *file, const char __user *buf, - size_t len, loff_t *ppos); -static struct dentry *visornic_debugfs_dir; -static const struct file_operations debugfs_info_fops = { - .read = info_debugfs_read, -}; - -static const struct file_operations debugfs_enable_ints_fops = { - .write = enable_ints_write, -}; - /* GUIDS for director channel type supported by this driver. */ static struct visor_channeltype_descriptor visornic_channel_types[] = { /* Note that the only channel type we expect to be reported by the @@ -263,6 +249,10 @@ static ssize_t enable_ints_write(struct file *file, return count; } +static const struct file_operations debugfs_enable_ints_fops = { + .write = enable_ints_write, +}; + /** * visornic_serverdown_complete - IOPART went down, pause device * @work: Work queue it was scheduled on @@ -1496,6 +1486,11 @@ static ssize_t info_debugfs_read(struct file *file, char __user *buf, return bytes_read; } +static struct dentry *visornic_debugfs_dir; +static const struct file_operations debugfs_info_fops = { + .read = info_debugfs_read, +}; + /** * send_rcv_posts_if_needed * @devdata: visornic device -- cgit v0.10.2 From 2e805a9738a0487db1f5b8b6cb41b6c4cd882b63 Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Tue, 20 Sep 2016 11:42:05 -0400 Subject: staging: unisys: visornic: remove visornic_poll prototype Remove visornic_poll prototype, because it is not needed. Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index beb1cf2..183d2ec 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -141,7 +141,6 @@ struct visornic_devdata { struct uiscmdrsp cmdrsp[SIZEOF_CMDRSP]; }; -static int visornic_poll(struct napi_struct *napi, int budget); static void poll_for_irq(unsigned long v); /** -- cgit v0.10.2 From e7b6d8a61e3244392f882a31d08eab338cdeb772 Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Tue, 20 Sep 2016 11:42:06 -0400 Subject: staging: unisys: visornic: remove poll_for_irq prototype Remove poll_for_irq prototype not needed. Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index 183d2ec..6b206be 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -141,8 +141,6 @@ struct visornic_devdata { struct uiscmdrsp cmdrsp[SIZEOF_CMDRSP]; }; -static void poll_for_irq(unsigned long v); - /** * visor_copy_fragsinfo_from_skb( * @skb_in: skbuff that we are pulling the frags from -- cgit v0.10.2 From d616700e38d91f9ec11d83ccf64d8e038935f26d Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Tue, 20 Sep 2016 13:14:05 -0400 Subject: staging: unisys: visorhba: remove prototypes for visorhba_main.c Remove not needed prototypes in visorhba. Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorhba/visorhba_main.c b/drivers/staging/unisys/visorhba/visorhba_main.c index 120ba20..5ab5c3f 100644 --- a/drivers/staging/unisys/visorhba/visorhba_main.c +++ b/drivers/staging/unisys/visorhba/visorhba_main.c @@ -36,21 +36,6 @@ #define MAX_PENDING_REQUESTS (MIN_NUMSIGNALS * 2) #define VISORHBA_ERROR_COUNT 30 -static int visorhba_queue_command_lck(struct scsi_cmnd *scsicmd, - void (*visorhba_cmnd_done) - (struct scsi_cmnd *)); -#ifdef DEF_SCSI_QCMD -static DEF_SCSI_QCMD(visorhba_queue_command) -#else -#define visorhba_queue_command visorhba_queue_command_lck -#endif -static int visorhba_probe(struct visor_device *dev); -static void visorhba_remove(struct visor_device *dev); -static int visorhba_pause(struct visor_device *dev, - visorbus_state_complete_func complete_func); -static int visorhba_resume(struct visor_device *dev, - visorbus_state_complete_func complete_func); - static struct dentry *visorhba_debugfs_dir; /* GUIDS for HBA channel type supported by this driver */ @@ -62,20 +47,6 @@ static struct visor_channeltype_descriptor visorhba_channel_types[] = { { NULL_UUID_LE, NULL } }; -/* This is used to tell the visor bus driver which types of visor devices - * we support, and what functions to call when a visor device that we support - * is attached or removed. - */ -static struct visor_driver visorhba_driver = { - .name = "visorhba", - .owner = THIS_MODULE, - .channel_types = visorhba_channel_types, - .probe = visorhba_probe, - .remove = visorhba_remove, - .pause = visorhba_pause, - .resume = visorhba_resume, - .channel_interrupt = NULL, -}; MODULE_DEVICE_TABLE(visorbus, visorhba_channel_types); MODULE_ALIAS("visorbus:" SPAR_VHBA_CHANNEL_PROTOCOL_UUID_STR); @@ -580,6 +551,12 @@ err_del_scsipending_ent: return SCSI_MLQUEUE_DEVICE_BUSY; } +#ifdef DEF_SCSI_QCMD +static DEF_SCSI_QCMD(visorhba_queue_command) +#else +#define visorhba_queue_command visorhba_queue_command_lck +#endif + /** * visorhba_slave_alloc - called when new disk is discovered * @scsidev: New disk @@ -1186,6 +1163,21 @@ static void visorhba_remove(struct visor_device *dev) debugfs_remove_recursive(devdata->debugfs_dir); } +/* This is used to tell the visor bus driver which types of visor devices + * we support, and what functions to call when a visor device that we support + * is attached or removed. + */ +static struct visor_driver visorhba_driver = { + .name = "visorhba", + .owner = THIS_MODULE, + .channel_types = visorhba_channel_types, + .probe = visorhba_probe, + .remove = visorhba_remove, + .pause = visorhba_pause, + .resume = visorhba_resume, + .channel_interrupt = NULL, +}; + /** * visorhba_init - driver init routine * -- cgit v0.10.2 From 3838925ce22063cb8e2b70311d3163b869bc6592 Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Tue, 20 Sep 2016 16:28:59 -0400 Subject: staging: unisys: include: remove unused function pathname_last_n_nodes The function pathname_last_n_nodes is not used, get rid of it. Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/include/channel.h b/drivers/staging/unisys/include/channel.h index ff86f7a..e42f46c 100644 --- a/drivers/staging/unisys/include/channel.h +++ b/drivers/staging/unisys/include/channel.h @@ -347,38 +347,6 @@ static inline int spar_check_channel_server(uuid_le typeuuid, char *name, return 1; } -/* Given a file pathname <s> (with '/' or '\' separating directory nodes), - * returns a pointer to the beginning of a node within that pathname such - * that the number of nodes from that pointer to the end of the string is - * NOT more than <n>. Note that if the pathname has less than <n> nodes - * in it, the return pointer will be to the beginning of the string. - */ -static inline u8 * -pathname_last_n_nodes(u8 *s, unsigned int n) -{ - u8 *p = s; - unsigned int node_count = 0; - - while (*p != '\0') { - if ((*p == '/') || (*p == '\\')) - node_count++; - p++; - } - if (node_count <= n) - return s; - while (n > 0) { - p--; - if (p == s) - break; /* should never happen, unless someone - * is changing the string while we are - * looking at it!! - */ - if ((*p == '/') || (*p == '\\')) - n--; - } - return p + 1; -} - static inline int spar_channel_client_acquire_os(void __iomem *ch, u8 *id) { -- cgit v0.10.2 From 207d14a1aa70fd5bafdc3900f431df40c733c8ab Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Tue, 20 Sep 2016 16:29:00 -0400 Subject: staging: unisys: include: remove unused spar_channel_client_acquire_os The function spar_channel_client_acquire_os is not being used so remove it. Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/include/channel.h b/drivers/staging/unisys/include/channel.h index e42f46c..7de9e2b 100644 --- a/drivers/staging/unisys/include/channel.h +++ b/drivers/staging/unisys/include/channel.h @@ -132,22 +132,6 @@ ULTRA_CHANNELCLI_STRING(u32 state) /* throttling invalid boot channel statetransition error due to busy channel */ #define ULTRA_CLIERRORBOOT_THROTTLEMSG_BUSY 0x04 -/* Values for ULTRA_CHANNEL_PROTOCOL.CliErrorOS: */ -/* throttling invalid guest OS channel statetransition error due to - * client disabled - */ -#define ULTRA_CLIERROROS_THROTTLEMSG_DISABLED 0x01 - -/* throttling invalid guest OS channel statetransition error due to - * client not attached - */ -#define ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED 0x02 - -/* throttling invalid guest OS channel statetransition error due to - * busy channel - */ -#define ULTRA_CLIERROROS_THROTTLEMSG_BUSY 0x04 - /* Values for ULTRA_CHANNEL_PROTOCOL.Features: This define exists so * that windows guest can look at the FeatureFlags in the io channel, * and configure the windows driver to use interrupts or not based on @@ -347,94 +331,6 @@ static inline int spar_check_channel_server(uuid_le typeuuid, char *name, return 1; } -static inline int -spar_channel_client_acquire_os(void __iomem *ch, u8 *id) -{ - struct channel_header __iomem *hdr = ch; - - if (readl(&hdr->cli_state_os) == CHANNELCLI_DISABLED) { - if ((readb(&hdr->cli_error_os) - & ULTRA_CLIERROROS_THROTTLEMSG_DISABLED) == 0) { - /* we are NOT throttling this message */ - writeb(readb(&hdr->cli_error_os) | - ULTRA_CLIERROROS_THROTTLEMSG_DISABLED, - &hdr->cli_error_os); - /* throttle until acquire successful */ - - pr_info("%s Channel StateTransition INVALID! - acquire failed because OS client DISABLED\n", - id); - } - return 0; - } - if ((readl(&hdr->cli_state_os) != CHANNELCLI_OWNED) && - (readl(&hdr->cli_state_boot) == CHANNELCLI_DISABLED)) { - /* Our competitor is DISABLED, so we can transition to OWNED */ - pr_info("%s Channel StateTransition (%s) %s(%d)-->%s(%d)\n", - id, "cli_state_os", - ULTRA_CHANNELCLI_STRING(readl(&hdr->cli_state_os)), - readl(&hdr->cli_state_os), - ULTRA_CHANNELCLI_STRING(CHANNELCLI_OWNED), - CHANNELCLI_OWNED); - writel(CHANNELCLI_OWNED, &hdr->cli_state_os); - mb(); /* required for channel synch */ - } - if (readl(&hdr->cli_state_os) == CHANNELCLI_OWNED) { - if (readb(&hdr->cli_error_os)) { - /* we are in an error msg throttling state; - * come out of it - */ - pr_info("%s Channel OS client acquire now successful\n", - id); - writeb(0, &hdr->cli_error_os); - } - return 1; - } - - /* We have to do it the "hard way". We transition to BUSY, - * and can use the channel iff our competitor has not also - * transitioned to BUSY. - */ - if (readl(&hdr->cli_state_os) != CHANNELCLI_ATTACHED) { - if ((readb(&hdr->cli_error_os) - & ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED) == 0) { - /* we are NOT throttling this message */ - writeb(readb(&hdr->cli_error_os) | - ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED, - &hdr->cli_error_os); - /* throttle until acquire successful */ - pr_info("%s Channel StateTransition INVALID! - acquire failed because OS client NOT ATTACHED (state=%s(%d))\n", - id, ULTRA_CHANNELCLI_STRING( - readl(&hdr->cli_state_os)), - readl(&hdr->cli_state_os)); - } - return 0; - } - writel(CHANNELCLI_BUSY, &hdr->cli_state_os); - mb(); /* required for channel synch */ - if (readl(&hdr->cli_state_boot) == CHANNELCLI_BUSY) { - if ((readb(&hdr->cli_error_os) - & ULTRA_CLIERROROS_THROTTLEMSG_BUSY) == 0) { - /* we are NOT throttling this message */ - writeb(readb(&hdr->cli_error_os) | - ULTRA_CLIERROROS_THROTTLEMSG_BUSY, - &hdr->cli_error_os); - /* throttle until acquire successful */ - pr_info("%s Channel StateTransition failed - host OS acquire failed because boot BUSY\n", - id); - } - /* reset busy */ - writel(CHANNELCLI_ATTACHED, &hdr->cli_state_os); - mb(); /* required for channel synch */ - return 0; - } - if (readb(&hdr->cli_error_os)) { - /* we are in an error msg throttling state; come out of it */ - pr_info("%s Channel OS client acquire now successful\n", id); - writeb(0, &hdr->cli_error_os); - } - return 1; -} - static inline void spar_channel_client_release_os(void __iomem *ch, u8 *id) { -- cgit v0.10.2 From 0082b016b59e67cbbb747166565074f61255da7d Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Tue, 20 Sep 2016 16:29:01 -0400 Subject: staging: unisys: include: remove unused spar_channel_client_release_os The function spar_channel_client_release_os is not being used so remove it. Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/include/channel.h b/drivers/staging/unisys/include/channel.h index 7de9e2b..ba8bfdc 100644 --- a/drivers/staging/unisys/include/channel.h +++ b/drivers/staging/unisys/include/channel.h @@ -331,28 +331,6 @@ static inline int spar_check_channel_server(uuid_le typeuuid, char *name, return 1; } -static inline void -spar_channel_client_release_os(void __iomem *ch, u8 *id) -{ - struct channel_header __iomem *hdr = ch; - - if (readb(&hdr->cli_error_os)) { - /* we are in an error msg throttling state; come out of it */ - pr_info("%s Channel OS client error state cleared\n", id); - writeb(0, &hdr->cli_error_os); - } - if (readl(&hdr->cli_state_os) == CHANNELCLI_OWNED) - return; - if (readl(&hdr->cli_state_os) != CHANNELCLI_BUSY) { - pr_info("%s Channel StateTransition INVALID! - release failed because OS client NOT BUSY (state=%s(%d))\n", - id, ULTRA_CHANNELCLI_STRING( - readl(&hdr->cli_state_os)), - readl(&hdr->cli_state_os)); - /* return; */ - } - writel(CHANNELCLI_ATTACHED, &hdr->cli_state_os); /* release busy */ -} - /* * Routine Description: * Tries to insert the prebuilt signal pointed to by pSignal into the nth -- cgit v0.10.2 From a43bb30b62cf6993f1351c3f0d25f048e96052cd Mon Sep 17 00:00:00 2001 From: David Kershner <david.kershner@unisys.com> Date: Tue, 20 Sep 2016 16:29:02 -0400 Subject: staging: unisys: include: remove unused ULTRA_CHANNELCLI_STRING The inline ULTRA_CHANNELCLI_STRING is not being used so remove it. Signed-off-by: David Kershner <david.kershner@unisys.com> Reviewed-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/include/channel.h b/drivers/staging/unisys/include/channel.h index ba8bfdc..259ef64 100644 --- a/drivers/staging/unisys/include/channel.h +++ b/drivers/staging/unisys/include/channel.h @@ -75,28 +75,6 @@ enum channel_clientstate { /* access channel anytime */ }; -static inline const u8 * -ULTRA_CHANNELCLI_STRING(u32 state) -{ - switch (state) { - case CHANNELCLI_DETACHED: - return (const u8 *)("DETACHED"); - case CHANNELCLI_DISABLED: - return (const u8 *)("DISABLED"); - case CHANNELCLI_ATTACHING: - return (const u8 *)("ATTACHING"); - case CHANNELCLI_ATTACHED: - return (const u8 *)("ATTACHED"); - case CHANNELCLI_BUSY: - return (const u8 *)("BUSY"); - case CHANNELCLI_OWNED: - return (const u8 *)("OWNED"); - default: - break; - } - return (const u8 *)("?"); -} - #define SPAR_CHANNEL_SERVER_READY(ch) \ (readl(&(ch)->srv_state) == CHANNELSRV_READY) -- cgit v0.10.2 From abf095b5c567e36800d56c0ea0066b046b2678e1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Date: Wed, 21 Sep 2016 12:35:13 +0200 Subject: staging: greybus: fix up camera Kconfig dependancies CONFIG_MEDIA is not a thing, but CONFIG_MEDIA_SUPPORT is, so use that. Reported-by: Valentin Rothberg <valentinrothberg@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/greybus/Kconfig b/drivers/staging/greybus/Kconfig index 89c4976..50de2d7 100644 --- a/drivers/staging/greybus/Kconfig +++ b/drivers/staging/greybus/Kconfig @@ -48,7 +48,7 @@ config GREYBUS_BOOTROM config GREYBUS_CAMERA tristate "Greybus Camera Class driver" - depends on MEDIA && LEDS_CLASS_FLASH && BROKEN + depends on MEDIA_SUPPORT && LEDS_CLASS_FLASH && BROKEN ---help--- Select this option if you have a device that follows the Greybus Camera Class specification. -- cgit v0.10.2 From 92b8bd96fc1ae9c804526cb79bf289c3f815f3ff Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath <hvaibhav.linux@gmail.com> Date: Wed, 21 Sep 2016 16:28:13 +0530 Subject: staging: greybus: add maintainer for greybus platform drivers Add Vaibhav Hiremath as a Maintainer of Greybus platform drivers. Signed-off-by: Vaibhav Hiremath <hvaibhav.linux@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/MAINTAINERS b/MAINTAINERS index db6721b..8d2a48c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5338,6 +5338,13 @@ F: drivers/staging/greybus/spi.c F: drivers/staging/greybus/spilib.c F: drivers/staging/greybus/spilib.h +GREYBUS PLATFORM DRIVERS +M: Vaibhav Hiremath <hvaibhav.linux@gmail.com> +S: Maintained +F: drivers/staging/greybus/arche-platform.c +F: drivers/staging/greybus/arche-apb-ctrl.c +F: drivers/staging/greybus/arche_platform.h + GSPCA FINEPIX SUBDRIVER M: Frank Zago <frank@zago.net> L: linux-media@vger.kernel.org -- cgit v0.10.2 From 5f0730fda824e4a708d5f307e806b0176f86dcd3 Mon Sep 17 00:00:00 2001 From: Juliana Rodrigues <juliana.orod@gmail.com> Date: Thu, 22 Sep 2016 03:01:28 -0300 Subject: staging: wlan-ng: fixed block comment trailing Moved trailing */ to a new line and added * to subsequent lines on a block comment. Signed-off-by: Juliana Rodrigues <juliana.orod@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 87ceebe..4e6ea76 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1297,7 +1297,8 @@ typedef struct hfa384x { int dbmadjust; /* Group Addresses - right now, there are up to a total - of MAX_GRP_ADDR group addresses */ + * of MAX_GRP_ADDR group addresses + */ u8 dot11_grp_addr[MAX_GRP_ADDR][ETH_ALEN]; unsigned int dot11_grpcnt; -- cgit v0.10.2 From 72d19e9899a9666c46fd0936dd694291bc5e78b9 Mon Sep 17 00:00:00 2001 From: Juliana Rodrigues <juliana.orod@gmail.com> Date: Thu, 22 Sep 2016 02:50:56 -0300 Subject: staging: wlan-ng: fixed parenthesis alignment This patch fixes a checkpatch warning by moving arguments to the right and aligning them to the open parenthesis above. Signed-off-by: Juliana Rodrigues <juliana.orod@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index 8c592be..19750f3 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -661,7 +661,7 @@ void prism2_connect_result(struct wlandevice *wlandev, u8 failed) void prism2_disconnected(struct wlandevice *wlandev) { cfg80211_disconnected(wlandev->netdev, 0, NULL, - 0, false, GFP_KERNEL); + 0, false, GFP_KERNEL); } void prism2_roamed(struct wlandevice *wlandev) -- cgit v0.10.2 From 98090a0ba794a96f0bc6703afe16b60b1baa396b Mon Sep 17 00:00:00 2001 From: Juliana Rodrigues <juliana.orod@gmail.com> Date: Thu, 22 Sep 2016 02:49:50 -0300 Subject: staging: wlan-ng: fixed alignment not matching This patch fixes a checkpatch warning by moving arguments to the right and aligning them to their open parenthesis. Signed-off-by: Juliana Rodrigues <juliana.orod@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index 19750f3..f1d93b7 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -334,7 +334,7 @@ static int prism2_scan(struct wiphy *wiphy, msg1.scantype.data = P80211ENUM_scantype_active; msg1.ssid.data.len = request->ssids->ssid_len; memcpy(msg1.ssid.data.data, - request->ssids->ssid, request->ssids->ssid_len); + request->ssids->ssid, request->ssids->ssid_len); } else { msg1.scantype.data = 0; } -- cgit v0.10.2 From 95842bc9fd03e51e4fa370c40542e2306d079699 Mon Sep 17 00:00:00 2001 From: Juliana Rodrigues <juliana.orod@gmail.com> Date: Thu, 22 Sep 2016 00:24:40 -0300 Subject: staging: wlan-ng: fixed block comment formatting This patch fixes a checkpatch warning in a block comment by adapting it to the community preferred coding style. Signed-off-by: Juliana Rodrigues <juliana.orod@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 4e6ea76..f8ee175 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -110,7 +110,8 @@ #define HFA384x_ADDR_FLAT_CMD_OFF_MASK (0x0000ffff) /* Mask bits for discarding unwanted pieces in AUX format - 16-bit address parts */ + * 16-bit address parts + */ #define HFA384x_ADDR_AUX_PAGE_MASK (0xffff) #define HFA384x_ADDR_AUX_OFF_MASK (0x007f) -- cgit v0.10.2 From a6f9d846cc0980ef85ba9a2c863cef2f6202ac83 Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Wed, 21 Sep 2016 14:49:05 +0200 Subject: staging: most: make function most_submit_mbo return void Function most_submit_mbo() causes an exception only if either the pointer mbo or mbo->context equals NULL. From the underlying architecture's point of view both cases must _not_ come true and would happen only, if something has tampered with the pointers. This would render runtime code unable to recover anyway. So, instead trying to hide that things are already critically out of control we're better off with a WARN_ON() assertion. This patch replaces the return type of the function most_submit_mbo() with 'void' and adds a WARN_ONCE() assertion. Additionally, code calling the function is adapted accordingly. Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index 1c20ae6..5458fb9 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -214,10 +214,7 @@ static ssize_t aim_write(struct file *filp, const char __user *buf, goto put_mbo; } - ret = most_submit_mbo(mbo); - if (ret) - goto put_mbo; - + most_submit_mbo(mbo); mutex_unlock(&c->io_mutex); return actual_len; put_mbo: diff --git a/drivers/staging/most/aim-sound/sound.c b/drivers/staging/most/aim-sound/sound.c index 9c64580..3dc625c 100644 --- a/drivers/staging/most/aim-sound/sound.c +++ b/drivers/staging/most/aim-sound/sound.c @@ -234,7 +234,6 @@ static int playback_thread(void *data) while (!kthread_should_stop()) { struct mbo *mbo = NULL; bool period_elapsed = false; - int ret; wait_event_interruptible( channel->playback_waitq, @@ -250,10 +249,7 @@ static int playback_thread(void *data) else memset(mbo->virt_address, 0, mbo->buffer_length); - ret = most_submit_mbo(mbo); - if (ret) - channel->is_stream_running = false; - + most_submit_mbo(mbo); if (period_elapsed) snd_pcm_period_elapsed(channel->substream); } diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index bd555ec..5f05a13 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -1323,17 +1323,14 @@ _exit: /** * most_submit_mbo - submits an MBO to fifo * @mbo: pointer to the MBO - * */ -int most_submit_mbo(struct mbo *mbo) +void most_submit_mbo(struct mbo *mbo) { - if (unlikely((!mbo) || (!mbo->context))) { - pr_err("Bad MBO or missing channel reference\n"); - return -EINVAL; - } + if (WARN_ONCE(!mbo || !mbo->context, + "bad mbo or missing channel reference\n")) + return; nq_hdm_mbo(mbo); - return 0; } EXPORT_SYMBOL_GPL(most_submit_mbo); diff --git a/drivers/staging/most/mostcore/mostcore.h b/drivers/staging/most/mostcore/mostcore.h index e768cb8..7644f44 100644 --- a/drivers/staging/most/mostcore/mostcore.h +++ b/drivers/staging/most/mostcore/mostcore.h @@ -287,7 +287,7 @@ struct kobject *most_register_interface(struct most_interface *iface); * @intf_instance Pointer to the interface instance description. */ void most_deregister_interface(struct most_interface *iface); -int most_submit_mbo(struct mbo *mbo); +void most_submit_mbo(struct mbo *mbo); /** * most_stop_enqueue - prevents core from enqueing MBOs -- cgit v0.10.2 From 22ff195b5a42a6935f624bcb995b6d051ee68872 Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov <andrey.shvetsov@k2l.de> Date: Wed, 21 Sep 2016 14:49:08 +0200 Subject: staging: most: core: remove trailing zero from text property This patch removes trailing zeros from the strings returned by the attributes available_datatypes and available_directions. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index 5f05a13..29e8a1c 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -265,7 +265,7 @@ static ssize_t show_available_directions(struct most_c_obj *c, if (c->iface->channel_vector[i].direction & MOST_CH_TX) strcat(buf, "dir_tx "); strcat(buf, "\n"); - return strlen(buf) + 1; + return strlen(buf); } static ssize_t show_available_datatypes(struct most_c_obj *c, @@ -284,7 +284,7 @@ static ssize_t show_available_datatypes(struct most_c_obj *c, if (c->iface->channel_vector[i].data_type & MOST_CH_ISOC_AVP) strcat(buf, "isoc_avp "); strcat(buf, "\n"); - return strlen(buf) + 1; + return strlen(buf); } static -- cgit v0.10.2 From 95f73013ed021ef30e787772ecf547c1355c4299 Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Wed, 21 Sep 2016 14:49:09 +0200 Subject: staging: most: clean up configuration strings This patch adds the strings 'rx', 'tx' and 'isoc' to the list of accepted identifiers when setting up a channel configuration. To keep consistency it removes the prefix "dir_" from strings returned by the attributes set_direction and available_directions and it removes the suffix "_avp" from the string "isoc_avp" returned by the attributes set_datatype and available_datatypes. Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/aim-v4l2/video.c b/drivers/staging/most/aim-v4l2/video.c index 150dc89..9173cd1 100644 --- a/drivers/staging/most/aim-v4l2/video.c +++ b/drivers/staging/most/aim-v4l2/video.c @@ -506,7 +506,7 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx, if (ccfg->data_type != MOST_CH_SYNC && ccfg->data_type != MOST_CH_ISOC_AVP) { - pr_err("wrong channel type, expect sync or isoc_avp\n"); + pr_err("wrong channel type, expect sync or isoc\n"); return -EINVAL; } diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index 29e8a1c..d7c3f46 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -83,10 +83,13 @@ struct most_inst_obj { static const struct { int most_ch_data_type; char *name; -} ch_data_type[] = { { MOST_CH_CONTROL, "control\n" }, +} ch_data_type[] = { + { MOST_CH_CONTROL, "control\n" }, { MOST_CH_ASYNC, "async\n" }, { MOST_CH_SYNC, "sync\n" }, - { MOST_CH_ISOC_AVP, "isoc_avp\n"} }; + { MOST_CH_ISOC_AVP, "isoc\n"}, + { MOST_CH_ISOC_AVP, "isoc_avp\n"}, +}; #define to_inst_obj(d) container_of(d, struct most_inst_obj, kobj) @@ -261,9 +264,9 @@ static ssize_t show_available_directions(struct most_c_obj *c, strcpy(buf, ""); if (c->iface->channel_vector[i].direction & MOST_CH_RX) - strcat(buf, "dir_rx "); + strcat(buf, "rx "); if (c->iface->channel_vector[i].direction & MOST_CH_TX) - strcat(buf, "dir_tx "); + strcat(buf, "tx "); strcat(buf, "\n"); return strlen(buf); } @@ -282,7 +285,7 @@ static ssize_t show_available_datatypes(struct most_c_obj *c, if (c->iface->channel_vector[i].data_type & MOST_CH_SYNC) strcat(buf, "sync "); if (c->iface->channel_vector[i].data_type & MOST_CH_ISOC_AVP) - strcat(buf, "isoc_avp "); + strcat(buf, "isoc "); strcat(buf, "\n"); return strlen(buf); } @@ -392,9 +395,9 @@ static ssize_t show_set_direction(struct most_c_obj *c, char *buf) { if (c->cfg.direction & MOST_CH_TX) - return snprintf(buf, PAGE_SIZE, "dir_tx\n"); + return snprintf(buf, PAGE_SIZE, "tx\n"); else if (c->cfg.direction & MOST_CH_RX) - return snprintf(buf, PAGE_SIZE, "dir_rx\n"); + return snprintf(buf, PAGE_SIZE, "rx\n"); return snprintf(buf, PAGE_SIZE, "unconfigured\n"); } @@ -405,8 +408,12 @@ static ssize_t store_set_direction(struct most_c_obj *c, { if (!strcmp(buf, "dir_rx\n")) { c->cfg.direction = MOST_CH_RX; + } else if (!strcmp(buf, "rx\n")) { + c->cfg.direction = MOST_CH_RX; } else if (!strcmp(buf, "dir_tx\n")) { c->cfg.direction = MOST_CH_TX; + } else if (!strcmp(buf, "tx\n")) { + c->cfg.direction = MOST_CH_TX; } else { pr_info("WARN: invalid attribute settings\n"); return -EINVAL; -- cgit v0.10.2 From 0540609fe217c3eed5804bcc095b0c41db5e63b0 Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov <andrey.shvetsov@k2l.de> Date: Wed, 21 Sep 2016 14:49:10 +0200 Subject: staging: most: replace MOST_CH_ISOC_AVP with MOST_CH_ISOC This patch replaces the enum value MOST_CH_ISOC_AVP with the more appropriate MOST_CH_ISOC. Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/aim-v4l2/video.c b/drivers/staging/most/aim-v4l2/video.c index 9173cd1..400f727 100644 --- a/drivers/staging/most/aim-v4l2/video.c +++ b/drivers/staging/most/aim-v4l2/video.c @@ -505,7 +505,7 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx, } if (ccfg->data_type != MOST_CH_SYNC && - ccfg->data_type != MOST_CH_ISOC_AVP) { + ccfg->data_type != MOST_CH_ISOC) { pr_err("wrong channel type, expect sync or isoc\n"); return -EINVAL; } diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c index 71f4ae7..78b2c3d 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hdm.c +++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c @@ -561,7 +561,7 @@ static int configure_channel(struct most_interface *most_iface, int ch_idx, hal_ret = dim_init_async(&hdm_ch->ch, is_tx, ch_addr, is_tx ? new_size * 2 : new_size); break; - case MOST_CH_ISOC_AVP: + case MOST_CH_ISOC: new_size = dim_norm_isoc_buffer_size(buf_size, sub_size); if (new_size == 0) { pr_err("%s: invalid sub-buffer size or too small buffer size\n", @@ -797,7 +797,7 @@ static int dim2_probe(struct platform_device *pdev) cap->name_suffix = hdm_ch->name; cap->direction = MOST_CH_RX | MOST_CH_TX; cap->data_type = MOST_CH_CONTROL | MOST_CH_ASYNC | - MOST_CH_ISOC_AVP | MOST_CH_SYNC; + MOST_CH_ISOC | MOST_CH_SYNC; cap->num_buffers_packet = MAX_BUFFERS_PACKET; cap->buffer_size_packet = MAX_BUF_SIZE_PACKET; cap->num_buffers_streaming = MAX_BUFFERS_STREAMING; diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index 084bd00..26c9adb 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -224,7 +224,7 @@ static unsigned int get_stream_frame_size(struct most_channel_config *cfg) return frame_size; } switch (cfg->data_type) { - case MOST_CH_ISOC_AVP: + case MOST_CH_ISOC: frame_size = AV_PACKETS_PER_XACT * sub_size; break; case MOST_CH_SYNC: @@ -634,7 +634,7 @@ static int hdm_enqueue(struct most_interface *iface, int channel, length, hdm_write_completion, mbo); - if (conf->data_type != MOST_CH_ISOC_AVP) + if (conf->data_type != MOST_CH_ISOC) urb->transfer_flags |= URB_ZERO_PACKET; } else { usb_fill_bulk_urb(urb, mdev->usb_device, @@ -698,7 +698,7 @@ static int hdm_configure_channel(struct most_interface *iface, int channel, } if (conf->data_type != MOST_CH_SYNC && - !(conf->data_type == MOST_CH_ISOC_AVP && + !(conf->data_type == MOST_CH_ISOC && conf->packets_per_xact != 0xFF)) { mdev->padding_active[channel] = false; goto exit; @@ -1254,7 +1254,7 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) tmp_cap->num_buffers_packet = BUF_CHAIN_SIZE; tmp_cap->num_buffers_streaming = BUF_CHAIN_SIZE; tmp_cap->data_type = MOST_CH_CONTROL | MOST_CH_ASYNC | - MOST_CH_ISOC_AVP | MOST_CH_SYNC; + MOST_CH_ISOC | MOST_CH_SYNC; if (usb_endpoint_dir_in(ep_desc)) tmp_cap->direction = MOST_CH_RX; else diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index d7c3f46..329109c 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -87,8 +87,8 @@ static const struct { { MOST_CH_CONTROL, "control\n" }, { MOST_CH_ASYNC, "async\n" }, { MOST_CH_SYNC, "sync\n" }, - { MOST_CH_ISOC_AVP, "isoc\n"}, - { MOST_CH_ISOC_AVP, "isoc_avp\n"}, + { MOST_CH_ISOC, "isoc\n"}, + { MOST_CH_ISOC, "isoc_avp\n"}, }; #define to_inst_obj(d) container_of(d, struct most_inst_obj, kobj) @@ -284,7 +284,7 @@ static ssize_t show_available_datatypes(struct most_c_obj *c, strcat(buf, "async "); if (c->iface->channel_vector[i].data_type & MOST_CH_SYNC) strcat(buf, "sync "); - if (c->iface->channel_vector[i].data_type & MOST_CH_ISOC_AVP) + if (c->iface->channel_vector[i].data_type & MOST_CH_ISOC) strcat(buf, "isoc "); strcat(buf, "\n"); return strlen(buf); diff --git a/drivers/staging/most/mostcore/mostcore.h b/drivers/staging/most/mostcore/mostcore.h index 7644f44..5f8339b 100644 --- a/drivers/staging/most/mostcore/mostcore.h +++ b/drivers/staging/most/mostcore/mostcore.h @@ -56,7 +56,7 @@ enum most_channel_direction { enum most_channel_data_type { MOST_CH_CONTROL = 1 << 0, MOST_CH_ASYNC = 1 << 1, - MOST_CH_ISOC_AVP = 1 << 2, + MOST_CH_ISOC = 1 << 2, MOST_CH_SYNC = 1 << 5, }; -- cgit v0.10.2 From ce35e9be62837d8242472264b511f9c27992adfa Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya <eraretuya@gmail.com> Date: Wed, 21 Sep 2016 12:59:29 +0800 Subject: staging: greybus: camera: simplify NULL test Replace direct comparisons to NULL i.e. 'x == NULL' with '!x' for consistency. Coccinelle semantic patch used: @@ identifier func; expression x; statement Z; @@ x = func(...); if ( ( + ! x - == NULL | + ! - NULL == x ) ) Z Signed-off-by: Eva Rachel Retuya <eraretuya@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 46d2e8a..491bdd7 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -1121,7 +1121,7 @@ static ssize_t gb_camera_debugfs_write(struct file *file, return -EINVAL; kbuf = kmalloc(len + 1, GFP_KERNEL); - if (kbuf == NULL) + if (!kbuf) return -ENOMEM; if (copy_from_user(kbuf, buf, len)) { -- cgit v0.10.2 From 4f1cbe2a7b4fa50e5ae09e0a564c9dc4101b02fd Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya <eraretuya@gmail.com> Date: Wed, 21 Sep 2016 13:03:24 +0800 Subject: staging: greybus: audio: delete unnecessary parentheses Eliminate unneeded parentheses around the right hand side of an assignment. Coccinelle semantic patch used: @@ expression e1, e2; identifier v; @@ ( v = (e1 == e2) | v = (e1 != e2) | v = (e1 <= e2) | v = (e1 >= e2) | v = - ( e1 - ) ) Signed-off-by: Eva Rachel Retuya <eraretuya@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index 5eef536..f9f3381 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -459,7 +459,7 @@ static int gbcodec_mixer_dapm_ctl_put(struct snd_kcontrol *kcontrol, max = info->value.integer.max; mask = (1 << fls(max)) - 1; - val = (ucontrol->value.integer.value[0] & mask); + val = ucontrol->value.integer.value[0] & mask; connect = !!val; /* update ucontrol */ -- cgit v0.10.2 From 5a420d15d15b0eb46672578baa268675c63962f7 Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya <eraretuya@gmail.com> Date: Wed, 21 Sep 2016 13:07:04 +0800 Subject: staging: greybus: arche-platform: compress return logic into one line Modify return statement to use the value being returned directly instead of assigning it first to 'ret' and returning this variable. Coccinelle semantic patch used: @@ expression e; local idexpression ret; @@ -ret = +return e; -return ret; Signed-off-by: Eva Rachel Retuya <eraretuya@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 9d9048e..d6b3609 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -634,8 +634,7 @@ static int arche_platform_probe(struct platform_device *pdev) arche_pdata->wake_detect_gpio = of_get_named_gpio(np, "svc,wake-detect-gpio", 0); if (arche_pdata->wake_detect_gpio < 0) { dev_err(dev, "failed to get wake detect gpio\n"); - ret = arche_pdata->wake_detect_gpio; - return ret; + return arche_pdata->wake_detect_gpio; } ret = devm_gpio_request(dev, arche_pdata->wake_detect_gpio, "wake detect"); -- cgit v0.10.2 From 0c8d9c73e6c99efdd5f76e5cbfb90e553130e729 Mon Sep 17 00:00:00 2001 From: Richard Groux <rgroux@sauron-mordor.net> Date: Wed, 21 Sep 2016 19:05:29 +0200 Subject: staging: greybus: audio_codec.c: space required before the open brace Minor error spotted by checkpatch.pl in greybus space required before the open brace '{' Signed-off-by: Richard Groux <rgroux@sauron-mordor.net> Reviewed-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 5ce2542..0e8e4e9 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -322,7 +322,7 @@ int gbaudio_module_update(struct gbaudio_codec_info *codec, dev_dbg(module->dev, "%s:Module update %s sequence\n", w->name, enable ? "Enable":"Disable"); - if ((w->id != snd_soc_dapm_aif_in) && (w->id != snd_soc_dapm_aif_out)){ + if ((w->id != snd_soc_dapm_aif_in) && (w->id != snd_soc_dapm_aif_out)) { dev_dbg(codec->dev, "No action required for %s\n", w->name); return 0; } -- cgit v0.10.2 From 33111574550b210f4841591a3938283ffdf91d01 Mon Sep 17 00:00:00 2001 From: Richard Groux <rgroux@sauron-mordor.net> Date: Wed, 21 Sep 2016 19:05:31 +0200 Subject: staging: greybus: audio_codec.c: code indent should use tabs where possible Minor error spotted by checkpatch.pl in greybus code indent should use tabs where possible Signed-off-by: Richard Groux <rgroux@sauron-mordor.net> Reviewed-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 0e8e4e9..8a0744b 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -1008,7 +1008,7 @@ static int gbcodec_probe(struct snd_soc_codec *codec) snd_soc_codec_set_drvdata(codec, info); gbcodec = info; - device_init_wakeup(codec->dev, 1); + device_init_wakeup(codec->dev, 1); return 0; } -- cgit v0.10.2 From 26746a360394158850c494dd89d9d4f2d276b032 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim <chaehyun.lim@gmail.com> Date: Thu, 22 Sep 2016 10:56:43 +0900 Subject: staging: greybus: uart.c: change 'unsigned' to 'unsigned int' Fixes checkpatch.pl warning: WARNING: Prefer 'unsigned int' to bare use of 'unsigned' Signed-off-by: Chaehyun Lim <chaehyun.lim@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 01aeed1..a3c753b 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -350,7 +350,7 @@ static int gb_uart_flush(struct gb_tty *gb_tty, u8 flags) &request, sizeof(request), NULL, 0); } -static struct gb_tty *get_gb_by_minor(unsigned minor) +static struct gb_tty *get_gb_by_minor(unsigned int minor) { struct gb_tty *gb_tty; -- cgit v0.10.2 From 319b78c3c4842a6f079bca8950248803fa67b38f Mon Sep 17 00:00:00 2001 From: Chaehyun Lim <chaehyun.lim@gmail.com> Date: Thu, 22 Sep 2016 10:56:44 +0900 Subject: staging: greybus: uart.c: fix alignment to match open parenthesis Fixes checkpatch.pl warning: CHECK: Alignment should match open parenthesis Signed-off-by: Chaehyun Lim <chaehyun.lim@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index a3c753b..5ee7954 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -93,8 +93,8 @@ static int gb_uart_receive_data_handler(struct gb_operation *op) if (request->payload_size < sizeof(*receive_data)) { dev_err(&gb_tty->gbphy_dev->dev, - "short receive-data request received (%zu < %zu)\n", - request->payload_size, sizeof(*receive_data)); + "short receive-data request received (%zu < %zu)\n", + request->payload_size, sizeof(*receive_data)); return -EINVAL; } @@ -103,9 +103,9 @@ static int gb_uart_receive_data_handler(struct gb_operation *op) if (recv_data_size != request->payload_size - sizeof(*receive_data)) { dev_err(&gb_tty->gbphy_dev->dev, - "malformed receive-data request received (%u != %zu)\n", - recv_data_size, - request->payload_size - sizeof(*receive_data)); + "malformed receive-data request received (%u != %zu)\n", + recv_data_size, + request->payload_size - sizeof(*receive_data)); return -EINVAL; } @@ -145,8 +145,8 @@ static int gb_uart_serial_state_handler(struct gb_operation *op) if (request->payload_size < sizeof(*serial_state)) { dev_err(&gb_tty->gbphy_dev->dev, - "short serial-state event received (%zu < %zu)\n", - request->payload_size, sizeof(*serial_state)); + "short serial-state event received (%zu < %zu)\n", + request->payload_size, sizeof(*serial_state)); return -EINVAL; } @@ -168,9 +168,9 @@ static int gb_uart_receive_credits_handler(struct gb_operation *op) if (request->payload_size < sizeof(*credit_request)) { dev_err(&gb_tty->gbphy_dev->dev, - "short receive_credits event received (%zu < %zu)\n", - request->payload_size, - sizeof(*credit_request)); + "short receive_credits event received (%zu < %zu)\n", + request->payload_size, + sizeof(*credit_request)); return -EINVAL; } @@ -253,8 +253,8 @@ static void gb_uart_tx_write_work(struct work_struct *work) send_size = gb_tty->credits; send_size = kfifo_out_peek(&gb_tty->write_fifo, - &request->data[0], - send_size); + &request->data[0], + send_size); if (!send_size) { spin_unlock_irqrestore(&gb_tty->write_lock, flags); break; @@ -446,7 +446,7 @@ static int gb_tty_write(struct tty_struct *tty, const unsigned char *buf, struct gb_tty *gb_tty = tty->driver_data; count = kfifo_in_spinlocked(&gb_tty->write_fifo, buf, count, - &gb_tty->write_lock); + &gb_tty->write_lock); if (count && !gb_tty->close_pending) schedule_work(&gb_tty->tx_work); @@ -878,7 +878,7 @@ static int gb_uart_probe(struct gbphy_device *gbphy_dev, INIT_WORK(&gb_tty->tx_work, gb_uart_tx_write_work); retval = kfifo_alloc(&gb_tty->write_fifo, GB_UART_WRITE_FIFO_SIZE, - GFP_KERNEL); + GFP_KERNEL); if (retval) goto exit_buf_free; -- cgit v0.10.2 From 8d904fe50e3c5bfd8204cf1b8d525baeb3738bba Mon Sep 17 00:00:00 2001 From: David Lin <dtwlin@gmail.com> Date: Wed, 21 Sep 2016 18:57:23 -0700 Subject: staging: greybus: add maintainer for uart and log protocol drivers Add myself as greybus uart and log protocol driver maintainer. Signed-off-by: David Lin <dtwlin@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/MAINTAINERS b/MAINTAINERS index 8d2a48c..e013c2b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5338,6 +5338,12 @@ F: drivers/staging/greybus/spi.c F: drivers/staging/greybus/spilib.c F: drivers/staging/greybus/spilib.h +GREYBUS PROTOCOLS DRIVERS +M: David Lin <dtwlin@gmail.com> +S: Maintained +F: drivers/staging/greybus/uart.c +F: drivers/staging/greybus/log.c + GREYBUS PLATFORM DRIVERS M: Vaibhav Hiremath <hvaibhav.linux@gmail.com> S: Maintained -- cgit v0.10.2 From 3adc4aae0e597a7cdcb9ed3f99d0933bf9a4aaa6 Mon Sep 17 00:00:00 2001 From: Katie Dunne <kdunne@mail.ccsf.edu> Date: Wed, 21 Sep 2016 15:13:20 -0700 Subject: staging: speakup: Remove unnecessary parentheses Issue found by checkpatch. Signed-off-by: Katie Dunne <kdunne@mail.ccsf.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/speakup/synth.c b/drivers/staging/speakup/synth.c index 810a214..54b2f39 100644 --- a/drivers/staging/speakup/synth.c +++ b/drivers/staging/speakup/synth.c @@ -407,7 +407,7 @@ static int do_synth_init(struct spk_synth *in_synth) if (!spk_quiet_boot) synth_printf("%s found\n", synth->long_name); if (synth->attributes.name - && sysfs_create_group(speakup_kobj, &(synth->attributes)) < 0) + && sysfs_create_group(speakup_kobj, &synth->attributes) < 0) return -ENOMEM; synth_flags = synth->flags; wake_up_interruptible_all(&speakup_event); @@ -429,7 +429,7 @@ void synth_release(void) del_timer(&thread_timer); spin_unlock_irqrestore(&speakup_info.spinlock, flags); if (synth->attributes.name) - sysfs_remove_group(speakup_kobj, &(synth->attributes)); + sysfs_remove_group(speakup_kobj, &synth->attributes); for (var = synth->vars; var->var_id != MAXVARS; var++) speakup_unregister_var(var->var_id); spk_stop_serial_interrupt(); -- cgit v0.10.2 From cf5d32736722a1abf00c432241a5477c09cd4db2 Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Tue, 20 Sep 2016 19:40:14 +0530 Subject: staging: xgifb: Remove unused variable and if statement Setting the variable 'refresh_rate = 60;' has no use to the rest of the function. Hence the if statement setting it and the variable itself can be removed. This was detected using the following Coccinelle semantic patch: @@ type T; identifier i; constant C; @@ ( extern T i; | - T i; <+... when != i - i = C; ...+> ) Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index a58983f..0c78491 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -1224,7 +1224,7 @@ static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) unsigned int vtotal = 0; unsigned int drate = 0, hrate = 0; int found_mode = 0; - int refresh_rate, search_idx; + int search_idx; if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) { vtotal = var->upper_margin + var->yres + var->lower_margin @@ -1260,10 +1260,6 @@ static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) xgifb_info->refresh_rate = 60; } - /* Calculation wrong for 1024x600 - force it to 60Hz */ - if ((var->xres == 1024) && (var->yres == 600)) - refresh_rate = 60; - search_idx = 0; while ((XGIbios_mode[search_idx].mode_no != 0) && (XGIbios_mode[search_idx].xres <= var->xres)) { -- cgit v0.10.2 From f3151e0043099bed805cecb7f363331e8c0a0449 Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Tue, 20 Sep 2016 17:36:29 +0530 Subject: staging: sm750fb: Use BIT(x) macro Replaces left shift operation (1 << d) by BIT(x) macro. Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index f557b6d..a887f32 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -349,7 +349,7 @@ unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll) fl_quo = (rem * 10000 / input); for (d = max_d; d >= 0; d--) { - X = (1 << d); + X = BIT(d); M = quo * X; M += fl_quo * X / 10000; /* round step */ -- cgit v0.10.2 From 837b65555359b8232f54211317a2da28303d9c5a Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Tue, 20 Sep 2016 18:41:18 +0530 Subject: staging: sm750fb: Remove unnecessary parentheses Remove unnecessary parentheses from right side of an assignment. Issue detected by the following Coccinelle semantic patch: @r@ identifier x; expression e1, e2; @@ - x = (e1 << e2); + x = e1 << e2; Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Acked-by: Julia Lawall <julia.lawall@lip6.fr> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index a376d17..bff7db5 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -322,8 +322,8 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc, reg |= (var->xoffset & PANEL_WINDOW_WIDTH_X_MASK); POKE32(PANEL_WINDOW_WIDTH, reg); - reg = ((var->yres_virtual - 1) << - PANEL_WINDOW_HEIGHT_HEIGHT_SHIFT); + reg = (var->yres_virtual - 1) << + PANEL_WINDOW_HEIGHT_HEIGHT_SHIFT; reg &= PANEL_WINDOW_HEIGHT_HEIGHT_MASK; reg |= (var->yoffset & PANEL_WINDOW_HEIGHT_Y_MASK); POKE32(PANEL_WINDOW_HEIGHT, reg); -- cgit v0.10.2 From 63e6464b62353988ef71fa28946fa9c5560d6469 Mon Sep 17 00:00:00 2001 From: Yannis Damigos <giannis.damigos@gmail.com> Date: Wed, 21 Sep 2016 20:24:54 +0300 Subject: Staging:rtl8188eu: Fix multiple blank lines This patch fixes multiple black lines issue found by checkpatch.pl Signed-off-by: Yannis Damigos <giannis.damigos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_rf.c b/drivers/staging/rtl8188eu/core/rtw_rf.c index 3fc1a8f..e47be87 100644 --- a/drivers/staging/rtl8188eu/core/rtw_rf.c +++ b/drivers/staging/rtl8188eu/core/rtw_rf.c @@ -19,7 +19,6 @@ #include <recv_osdep.h> #include <xmit_osdep.h> - struct ch_freq { u32 channel; u32 frequency; -- cgit v0.10.2 From efb35d12b352c0603fe21a2199ba54aa61d22a54 Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Wed, 21 Sep 2016 23:38:00 +0530 Subject: staging: octeon-usb: Remove unnecessary assignment Remove 'x=a;' from a consecutive double assignment of the form 'x=a; x=b;'. Issue detected by the semantic patch found here: https://github.com/coccinelle/coccinellery/blob/master/write2/write2.cocci Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c index 17442b3..9a7858a 100644 --- a/drivers/staging/octeon-usb/octeon-hcd.c +++ b/drivers/staging/octeon-usb/octeon-hcd.c @@ -3292,7 +3292,6 @@ static int octeon_usb_hub_status_data(struct usb_hcd *hcd, char *buf) spin_lock_irqsave(&usb->lock, flags); port_status = cvmx_usb_get_status(usb); spin_unlock_irqrestore(&usb->lock, flags); - buf[0] = 0; buf[0] = port_status.connect_change << 1; return buf[0] != 0; -- cgit v0.10.2 From 7d359a847cf65cafa3582ee0c52f68e629fe0547 Mon Sep 17 00:00:00 2001 From: sayli karnik <karniksayli1995@gmail.com> Date: Wed, 21 Sep 2016 23:47:55 +0530 Subject: staging: ks7010: Remove unnecessary variable used to store return value This patch removes an unnecessary variable used to store return values in order to reduce memory usage. Done using coccinelle: @@ type T; constant C; identifier ret; @@ - T ret = C; ... when != ret return - ret + C ; Signed-off-by: sayli karnik <karniksayli1995@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c index 37a4ba3..b27e9b0 100644 --- a/drivers/staging/ks7010/ks7010_sdio.c +++ b/drivers/staging/ks7010/ks7010_sdio.c @@ -171,12 +171,11 @@ void ks_wlan_hw_wakeup_request(struct ks_wlan_private *priv) int _ks_wlan_hw_power_save(struct ks_wlan_private *priv) { - int rc = 0; unsigned char rw_data; int retval; if (priv->reg.powermgt == POWMGT_ACTIVE_MODE) - return rc; + return 0; if (priv->reg.operation_mode == MODE_INFRASTRUCTURE && (priv->connect_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) { @@ -244,7 +243,7 @@ int _ks_wlan_hw_power_save(struct ks_wlan_private *priv) } } - return rc; + return 0; } int ks_wlan_hw_power_save(struct ks_wlan_private *priv) -- cgit v0.10.2 From 7725066f1b4dd7fe69d85bf2a276f01d048cb967 Mon Sep 17 00:00:00 2001 From: Rehas Sachdeva <aquannie@gmail.com> Date: Thu, 22 Sep 2016 00:06:51 +0530 Subject: staging: slicoss: Move NULL test closer to assignment Move the test to check if a variable is NULL, to right after it is being assigned, rather than some statements later. Signed-off-by: Rehas Sachdeva <aquannie@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index 714e6e1..062307a 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -2617,15 +2617,15 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter) sizeof(struct slic_eeprom), &phys_config); - phys_configl = SLIC_GET_ADDR_LOW(phys_config); - phys_configh = SLIC_GET_ADDR_HIGH(phys_config); - if (!peeprom) { dev_err(&adapter->pcidev->dev, "Failed to allocate DMA memory for EEPROM.\n"); return -ENOMEM; } + phys_configl = SLIC_GET_ADDR_LOW(phys_config); + phys_configh = SLIC_GET_ADDR_HIGH(phys_config); + memset(peeprom, 0, sizeof(struct slic_eeprom)); slic_write32(adapter, SLIC_REG_ICR, ICR_INT_OFF); -- cgit v0.10.2 From 114c9ec2fdcc492543c149fc1d0325ecbbf3d25e Mon Sep 17 00:00:00 2001 From: Sandhya Bankar <bankarsandhya512@gmail.com> Date: Thu, 22 Sep 2016 15:23:55 +0530 Subject: Staging: speakup: varhandlers: Add space around the operator. This patch was found by checkpatch. Signed-off-by: Sandhya Bankar <bankarsandhya512@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/speakup/varhandlers.c b/drivers/staging/speakup/varhandlers.c index e1393d2..21186e3 100644 --- a/drivers/staging/speakup/varhandlers.c +++ b/drivers/staging/speakup/varhandlers.c @@ -276,7 +276,7 @@ int spk_set_mask_bits(const char *input, const int which, const int how) u_char *cp; short mask = spk_punc_info[which].mask; - if (how&1) { + if (how & 1) { for (cp = (u_char *)spk_punc_info[3].value; *cp; cp++) spk_chartab[*cp] &= ~mask; } @@ -290,14 +290,14 @@ int spk_set_mask_bits(const char *input, const int which, const int how) if (mask < PUNC) { if (!(spk_chartab[*cp] & PUNC)) break; - } else if (spk_chartab[*cp]&B_NUM) + } else if (spk_chartab[*cp] & B_NUM) break; } if (*cp) return -EINVAL; cp = (u_char *)input; } - if (how&2) { + if (how & 2) { for (; *cp; cp++) if (*cp > SPACE) spk_chartab[*cp] |= mask; -- cgit v0.10.2 From a04c28d0797bb9b8743efe814672dea8e3b91c55 Mon Sep 17 00:00:00 2001 From: Sandhya Bankar <bankarsandhya512@gmail.com> Date: Thu, 22 Sep 2016 15:27:30 +0530 Subject: Staging: speakup: kobjects: Add space around the operator. This issue was found by checkpatch. Signed-off-by: Sandhya Bankar <bankarsandhya512@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/speakup/kobjects.c b/drivers/staging/speakup/kobjects.c index 7fedee3..4a78d37 100644 --- a/drivers/staging/speakup/kobjects.c +++ b/drivers/staging/speakup/kobjects.c @@ -251,7 +251,7 @@ static ssize_t keymap_show(struct kobject *kobj, struct kobj_attribute *attr, } cp += sprintf(cp, "0, %d\n", KEY_MAP_VER); spin_unlock_irqrestore(&speakup_info.spinlock, flags); - return (int)(cp-buf); + return (int)(cp - buf); } /* @@ -288,8 +288,8 @@ static ssize_t keymap_store(struct kobject *kobj, struct kobj_attribute *attr, cp = spk_s2uchar(cp, cp1); cp1++; } - i = (int)cp1[-2]+1; - i *= (int)cp1[-1]+1; + i = (int)cp1[-2] + 1; + i *= (int)cp1[-1] + 1; i += 2; /* 0 and last map ver */ if (cp1[-3] != KEY_MAP_VER || cp1[-1] > 10 || i+SHIFT_TBL_SIZE+4 >= sizeof(spk_key_buf)) { @@ -350,9 +350,9 @@ static ssize_t silent_store(struct kobject *kobj, struct kobj_attribute *attr, } else { shut = 0; } - if (ch&4) + if (ch & 4) shut |= 0x40; - if (ch&1) + if (ch & 1) spk_shut_up |= shut; else spk_shut_up &= ~shut; -- cgit v0.10.2 From cdcffc0cdf553500dca22d93e3a87e2e0848aa83 Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya <eraretuya@gmail.com> Date: Thu, 22 Sep 2016 23:33:34 +0800 Subject: staging: greybus: arche-platform: declare struct of_device_id as const Declare the arrays 'arche_platform_of_match' and 'arche_combined_id' as const. 'arche_platform_of_match' is only stored in the .of_match_table field of a device_driver structure, which is declared as const. 'arche_combined_id' is passed to MODULE_DEVICE_TABLE. This macro does not modify the array and therefore the array can be declared as const. Checkpatch pointed out both issues. WARNING: struct of_device_id should be normally const Signed-off-by: Eva Rachel Retuya <eraretuya@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index d6b3609..e36ee98 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -776,12 +776,12 @@ static SIMPLE_DEV_PM_OPS(arche_platform_pm_ops, arche_platform_suspend, arche_platform_resume); -static struct of_device_id arche_platform_of_match[] = { +static const struct of_device_id arche_platform_of_match[] = { { .compatible = "google,arche-platform", }, /* Use PID/VID of SVC device */ { }, }; -static struct of_device_id arche_combined_id[] = { +static const struct of_device_id arche_combined_id[] = { { .compatible = "google,arche-platform", }, /* Use PID/VID of SVC device */ { .compatible = "usbffff,2", }, { }, -- cgit v0.10.2 From 5c925fe2a496da4849f1f874b9fa54cad7f2386c Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya <eraretuya@gmail.com> Date: Thu, 22 Sep 2016 23:33:33 +0800 Subject: staging: greybus: arche-apb-ctrl: declare struct of_device_id as const Declare the 'arche_apb_ctrl_of_match' array as const. This array is only stored in the .of_match_table field of a device_driver structure, which is declared as const. This addresses the checkpatch warning: WARNING: struct of_device_id should be normally const Signed-off-by: Eva Rachel Retuya <eraretuya@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index 59d9d42..70323aa 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -495,7 +495,7 @@ static void arche_apb_ctrl_shutdown(struct platform_device *pdev) static SIMPLE_DEV_PM_OPS(arche_apb_ctrl_pm_ops, arche_apb_ctrl_suspend, arche_apb_ctrl_resume); -static struct of_device_id arche_apb_ctrl_of_match[] = { +static const struct of_device_id arche_apb_ctrl_of_match[] = { { .compatible = "usbffff,2", }, { }, }; -- cgit v0.10.2 From 57fd9569d35350a31ed2493baf9d9c010b9d22fa Mon Sep 17 00:00:00 2001 From: Juliana Rodrigues <juliana.orod@gmail.com> Date: Thu, 22 Sep 2016 18:09:28 -0300 Subject: staging: wlan-ng: removed blank lines Removed an unecessary blank line after open brace, fixing a checkpatch issue. Signed-off-by: Juliana Rodrigues <juliana.orod@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index 2deb263..e6c9bb0 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -1031,7 +1031,6 @@ static void prism2sta_inf_tallies(struct wlandevice *wlandev, static void prism2sta_inf_scanresults(struct wlandevice *wlandev, hfa384x_InfFrame_t *inf) { - hfa384x_t *hw = wlandev->priv; int nbss; hfa384x_ScanResult_t *sr = &(inf->info.scanresult); -- cgit v0.10.2 From 6f7fd0953cf9c2bb1cc7ef5a8810e0ddf5827dc5 Mon Sep 17 00:00:00 2001 From: Juliana Rodrigues <juliana.orod@gmail.com> Date: Fri, 23 Sep 2016 00:21:55 -0300 Subject: staging: lustre: llite: removed uneeded return variables Removed variables used only for return purposes and replaced them for the return value itself. Found using Coccinelle's semantic patch: @@ local idexpression ret; expression e; @@ -ret = +return e; -return ret; Signed-off-by: Juliana Rodrigues <juliana.orod@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 5d4d17f..6e3a188 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -889,7 +889,6 @@ static int ll_lease_close(struct obd_client_handle *och, struct inode *inode, { struct ldlm_lock *lock; bool cancelled = true; - int rc; lock = ldlm_handle2lock(&och->och_lease_handle); if (lock) { @@ -907,9 +906,8 @@ static int ll_lease_close(struct obd_client_handle *och, struct inode *inode, if (lease_broken) *lease_broken = cancelled; - rc = ll_close_inode_openhandle(ll_i2sbi(inode)->ll_md_exp, inode, och, - NULL); - return rc; + return ll_close_inode_openhandle(ll_i2sbi(inode)->ll_md_exp, + inode, och, NULL); } /* Fills the obdo with the attributes for the lsm */ @@ -2489,9 +2487,8 @@ static loff_t ll_file_seek(struct file *file, loff_t offset, int origin) eof = i_size_read(inode); } - retval = generic_file_llseek_size(file, offset, origin, - ll_file_maxbytes(inode), eof); - return retval; + return generic_file_llseek_size(file, offset, origin, + ll_file_maxbytes(inode), eof); } static int ll_flush(struct file *file, fl_owner_t id) @@ -2922,15 +2919,12 @@ enum ldlm_mode ll_take_md_lock(struct inode *inode, __u64 bits, { ldlm_policy_data_t policy = { .l_inodebits = {bits} }; struct lu_fid *fid; - enum ldlm_mode rc; fid = &ll_i2info(inode)->lli_fid; CDEBUG(D_INFO, "trying to match res "DFID"\n", PFID(fid)); - rc = md_lock_match(ll_i2mdexp(inode), flags | LDLM_FL_BLOCK_GRANTED, - fid, LDLM_IBITS, &policy, mode, lockh); - - return rc; + return md_lock_match(ll_i2mdexp(inode), flags | LDLM_FL_BLOCK_GRANTED, + fid, LDLM_IBITS, &policy, mode, lockh); } static int ll_inode_revalidate_fini(struct inode *inode, int rc) @@ -3031,10 +3025,8 @@ static int __ll_inode_revalidate(struct dentry *dentry, __u64 ibits) op_data->op_valid = valid; rc = md_getattr(sbi->ll_md_exp, op_data, &req); ll_finish_md_op_data(op_data); - if (rc) { - rc = ll_inode_revalidate_fini(inode, rc); - return rc; - } + if (rc) + return ll_inode_revalidate_fini(inode, rc); rc = ll_prep_inode(&inode, req, NULL, NULL); } -- cgit v0.10.2 From b95300e82f652209745bf65220c43f372666048e Mon Sep 17 00:00:00 2001 From: Georgiana Rodica Chelu <georgiana.chelu93@gmail.com> Date: Fri, 23 Sep 2016 09:14:27 +0300 Subject: staging: rtl8188eu: hal: rtl8188e_cmd: Use ether_addr_copy() instead of memcpy() The checkpatch.pl found the warning: WARNING: Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2) Checked if the the Ethernet addresses are __aligned(2) by using pahole tool. The type of pwlanhdr is struct ieee80211_hdr and pahole shows that addr1, addr2, and addr3 are aligned to u16. struct ieee80211_hdr { __le16 frame_control; /* 0 2 */ __le16 duration_id; /* 2 2 */ u8 addr1[6]; /* 4 6 */ u8 addr2[6]; /* 10 6 */ u8 addr3[6]; /* 16 6 */ __le16 seq_ctrl; /* 22 2 */ u8 addr4[6]; /* 24 6 */ /* size: 30, cachelines: 1, members: 7 */ /* last cacheline: 30 bytes */ }; Both eeprompriv from struct adapter and MacAddress from struct wlan_bssid_ex have the offset multiple of sizeof(u16). Also, the array bc_addr and the pointers: StaAddr, mac, and bssid, start from an even offset. Signed-off-by: Georgiana Rodica Chelu <georgiana.chelu93@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c index 4e7cef3..d0f59b7 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c @@ -232,9 +232,9 @@ static void ConstructBeacon(struct adapter *adapt, u8 *pframe, u32 *pLength) fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; - memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&(adapt->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, cur_network->MacAddress, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, bc_addr); + ether_addr_copy(pwlanhdr->addr2, myid(&(adapt->eeprompriv))); + ether_addr_copy(pwlanhdr->addr3, cur_network->MacAddress); SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/); SetFrameSubType(pframe, WIFI_BEACON); @@ -322,10 +322,10 @@ static void ConstructPSPoll(struct adapter *adapt, u8 *pframe, u32 *pLength) SetDuration(pframe, (pmlmeinfo->aid | 0xc000)); /* BSSID. */ - memcpy(pwlanhdr->addr1, pnetwork->MacAddress, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, pnetwork->MacAddress); /* TA. */ - memcpy(pwlanhdr->addr2, myid(&(adapt->eeprompriv)), ETH_ALEN); + ether_addr_copy(pwlanhdr->addr2, myid(&(adapt->eeprompriv))); *pLength = 16; } @@ -357,21 +357,21 @@ static void ConstructNullFunctionData(struct adapter *adapt, u8 *pframe, switch (cur_network->network.InfrastructureMode) { case Ndis802_11Infrastructure: SetToDs(fctrl); - memcpy(pwlanhdr->addr1, pnetwork->MacAddress, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&(adapt->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, StaAddr, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, pnetwork->MacAddress); + ether_addr_copy(pwlanhdr->addr2, myid(&(adapt->eeprompriv))); + ether_addr_copy(pwlanhdr->addr3, StaAddr); break; case Ndis802_11APMode: SetFrDs(fctrl); - memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN); - memcpy(pwlanhdr->addr2, pnetwork->MacAddress, ETH_ALEN); - memcpy(pwlanhdr->addr3, myid(&(adapt->eeprompriv)), ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, StaAddr); + ether_addr_copy(pwlanhdr->addr2, pnetwork->MacAddress); + ether_addr_copy(pwlanhdr->addr3, myid(&(adapt->eeprompriv))); break; case Ndis802_11IBSS: default: - memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&(adapt->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, StaAddr); + ether_addr_copy(pwlanhdr->addr2, myid(&(adapt->eeprompriv))); + ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress); break; } @@ -413,9 +413,9 @@ static void ConstructProbeRsp(struct adapter *adapt, u8 *pframe, u32 *pLength, u fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; - memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN); - memcpy(pwlanhdr->addr2, mac, ETH_ALEN); - memcpy(pwlanhdr->addr3, bssid, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, StaAddr); + ether_addr_copy(pwlanhdr->addr2, mac); + ether_addr_copy(pwlanhdr->addr3, bssid); SetSeqNum(pwlanhdr, 0); SetFrameSubType(fctrl, WIFI_PROBERSP); -- cgit v0.10.2 From 16eda427a320ba864e16236485efc33f8bc548cf Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Thu, 22 Sep 2016 21:58:43 +0700 Subject: staging: r8188eu: remove rf_type member of hal_data_8188e structure rf_type is always equal to RF_1T1R. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/bb_cfg.c b/drivers/staging/rtl8188eu/hal/bb_cfg.c index c349923..134fa6c 100644 --- a/drivers/staging/rtl8188eu/hal/bb_cfg.c +++ b/drivers/staging/rtl8188eu/hal/bb_cfg.c @@ -518,8 +518,7 @@ static void store_pwrindex_offset(struct adapter *adapter, power_level_offset[4] = data; if (regaddr == rTxAGC_A_Mcs15_Mcs12) { power_level_offset[5] = data; - if (hal_data->rf_type == RF_1T1R) - hal_data->pwrGroupCnt++; + hal_data->pwrGroupCnt++; } if (regaddr == rTxAGC_B_Rate18_06) power_level_offset[8] = data; @@ -537,8 +536,6 @@ static void store_pwrindex_offset(struct adapter *adapter, power_level_offset[12] = data; if (regaddr == rTxAGC_B_Mcs15_Mcs12) { power_level_offset[13] = data; - if (hal_data->rf_type != RF_1T1R) - hal_data->pwrGroupCnt++; } } diff --git a/drivers/staging/rtl8188eu/hal/phy.c b/drivers/staging/rtl8188eu/hal/phy.c index 4e3c2e6..aaf8c26 100644 --- a/drivers/staging/rtl8188eu/hal/phy.c +++ b/drivers/staging/rtl8188eu/hal/phy.c @@ -149,10 +149,7 @@ static void get_tx_power_index(struct adapter *adapt, u8 channel, u8 *cck_pwr, u8 index = (channel - 1); u8 TxCount = 0, path_nums; - if ((RF_1T2R == hal_data->rf_type) || (RF_1T1R == hal_data->rf_type)) - path_nums = 1; - else - path_nums = 2; + path_nums = 1; for (TxCount = 0; TxCount < path_nums; TxCount++) { if (TxCount == RF_PATH_A) { diff --git a/drivers/staging/rtl8188eu/hal/rf_cfg.c b/drivers/staging/rtl8188eu/hal/rf_cfg.c index dc26ad3..dde6441 100644 --- a/drivers/staging/rtl8188eu/hal/rf_cfg.c +++ b/drivers/staging/rtl8188eu/hal/rf_cfg.c @@ -301,10 +301,7 @@ static bool rtl88e_phy_rf6052_config(struct adapter *adapt) { struct hal_data_8188e *hal_data = adapt->HalData; - if (hal_data->rf_type == RF_1T1R) - hal_data->NumTotalRFPath = 1; - else - hal_data->NumTotalRFPath = 2; + hal_data->NumTotalRFPath = 1; return rf6052_conf_para(adapt); } diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c index 964b169..62c75cc 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c @@ -57,12 +57,7 @@ static void Init_ODM_ComInfo_88E(struct adapter *Adapter) dm_odm->PatchID = hal_data->CustomerID; dm_odm->bWIFITest = Adapter->registrypriv.wifi_spec; - if (hal_data->rf_type == RF_1T1R) - dm_odm->RFType = ODM_1T1R; - else if (hal_data->rf_type == RF_2T2R) - dm_odm->RFType = ODM_2T2R; - else if (hal_data->rf_type == RF_1T2R) - dm_odm->RFType = ODM_1T2R; + dm_odm->RFType = ODM_1T1R; dm_odm->AntDivType = hal_data->TRxAntDivType; diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c index a7b0375..385bc2f 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c @@ -135,10 +135,7 @@ void rtw_hal_read_chip_version(struct adapter *padapter) dump_chip_info(ChipVersion); pHalData->VersionID = ChipVersion; - pHalData->rf_type = RF_1T1R; pHalData->NumTotalRFPath = 1; - - MSG_88E("RF_Type is %x!!\n", pHalData->rf_type); } void rtw_hal_set_odm_var(struct adapter *Adapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet) diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 113bd0b..7692ca4 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -1763,7 +1763,7 @@ void rtw_hal_get_hwreg(struct adapter *Adapter, u8 variable, u8 *val) val[0] = (BIT(0) & usb_read8(Adapter, REG_TDECTRL+2)) ? true : false; break; case HW_VAR_RF_TYPE: - val[0] = Adapter->HalData->rf_type; + val[0] = RF_1T1R; break; case HW_VAR_FWLPS_RF_ON: { diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h index 34268d9..7c81e3f 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h @@ -202,7 +202,6 @@ struct hal_data_8188e { /* rf_ctrl */ u8 rf_chip; - u8 rf_type; u8 NumTotalRFPath; u8 BoardType; -- cgit v0.10.2 From 2e41434673774a23a1d72547aecacc8ccbcc9078 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Thu, 22 Sep 2016 21:59:22 +0700 Subject: staging: r8188eu: remove RFType member of odm_dm_struct structure rf_type is always equal to ODM_1T1R. So, only RF PATH A exists for r8188eu device... Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/odm.c b/drivers/staging/rtl8188eu/hal/odm.c index 0677474..d983a80 100644 --- a/drivers/staging/rtl8188eu/hal/odm.c +++ b/drivers/staging/rtl8188eu/hal/odm.c @@ -285,7 +285,6 @@ void odm_CmnInfoInit_Debug(struct odm_dm_struct *pDM_Odm) 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, ("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)); @@ -763,37 +762,21 @@ u32 ODM_Get_Rate_Bitmap(struct odm_dm_struct *pDM_Odm, u32 macid, u32 ra_mask, u break; case (ODM_WM_B|ODM_WM_G|ODM_WM_N24G): case (ODM_WM_A|ODM_WM_B|ODM_WM_G|ODM_WM_N24G): - if (pDM_Odm->RFType == ODM_1T2R || pDM_Odm->RFType == ODM_1T1R) { - if (rssi_level == DM_RATR_STA_HIGH) { - rate_bitmap = 0x000f0000; - } else if (rssi_level == DM_RATR_STA_MIDDLE) { - rate_bitmap = 0x000ff000; - } else { - if (*(pDM_Odm->pBandWidth) == ODM_BW40M) - rate_bitmap = 0x000ff015; - else - rate_bitmap = 0x000ff005; - } + if (rssi_level == DM_RATR_STA_HIGH) { + rate_bitmap = 0x000f0000; + } else if (rssi_level == DM_RATR_STA_MIDDLE) { + rate_bitmap = 0x000ff000; } else { - if (rssi_level == DM_RATR_STA_HIGH) { - rate_bitmap = 0x0f8f0000; - } else if (rssi_level == DM_RATR_STA_MIDDLE) { - rate_bitmap = 0x0f8ff000; - } else { - if (*(pDM_Odm->pBandWidth) == ODM_BW40M) - rate_bitmap = 0x0f8ff015; - else - rate_bitmap = 0x0f8ff005; - } + if (*(pDM_Odm->pBandWidth) == ODM_BW40M) + rate_bitmap = 0x000ff015; + else + rate_bitmap = 0x000ff005; } break; default: /* case WIRELESS_11_24N: */ /* case WIRELESS_11_5N: */ - if (pDM_Odm->RFType == RF_1T2R) - rate_bitmap = 0x000fffff; - else - rate_bitmap = 0x0fffffff; + rate_bitmap = 0x0fffffff; break; } diff --git a/drivers/staging/rtl8188eu/hal/phy.c b/drivers/staging/rtl8188eu/hal/phy.c index aaf8c26..5192ef7 100644 --- a/drivers/staging/rtl8188eu/hal/phy.c +++ b/drivers/staging/rtl8188eu/hal/phy.c @@ -944,16 +944,11 @@ static bool simularity_compare(struct adapter *adapt, s32 resulta[][8], u8 c1, u8 c2) { u32 i, j, diff, sim_bitmap = 0, bound; - struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv; u8 final_candidate[2] = {0xFF, 0xFF}; /* for path A and path B */ bool result = true; s32 tmp1 = 0, tmp2 = 0; - if ((dm_odm->RFType == ODM_2T2R) || (dm_odm->RFType == ODM_2T3R) || - (dm_odm->RFType == ODM_2T4R)) - bound = 8; - else - bound = 4; + bound = 4; for (i = 0; i < bound; i++) { if ((i == 1) || (i == 3) || (i == 5) || (i == 7)) { @@ -1282,7 +1277,7 @@ void rtl88eu_phy_iq_calibrate(struct adapter *adapt, bool recovery) rOFDM0_RxIQExtAnta}; bool is2t; - is2t = (dm_odm->RFType == ODM_2T2R) ? true : false; + is2t = false; if (!(dm_odm->SupportAbility & ODM_RF_CALIBRATION)) return; @@ -1408,12 +1403,7 @@ void rtl88eu_phy_lc_calibrate(struct adapter *adapt) dm_odm->RFCalibrateInfo.bLCKInProgress = true; - if (dm_odm->RFType == ODM_2T2R) { - phy_lc_calibrate(adapt, true); - } else { - /* For 88C 1T1R */ - phy_lc_calibrate(adapt, false); - } + phy_lc_calibrate(adapt, false); dm_odm->RFCalibrateInfo.bLCKInProgress = false; } diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c index 62c75cc..d04b7fb 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c @@ -57,8 +57,6 @@ static void Init_ODM_ComInfo_88E(struct adapter *Adapter) dm_odm->PatchID = hal_data->CustomerID; dm_odm->bWIFITest = Adapter->registrypriv.wifi_spec; - dm_odm->RFType = ODM_1T1R; - dm_odm->AntDivType = hal_data->TRxAntDivType; /* Tx power tracking BB swing table. */ diff --git a/drivers/staging/rtl8188eu/include/odm.h b/drivers/staging/rtl8188eu/include/odm.h index 21fb4225..805f52e 100644 --- a/drivers/staging/rtl8188eu/include/odm.h +++ b/drivers/staging/rtl8188eu/include/odm.h @@ -724,8 +724,6 @@ struct odm_dm_struct { u32 SupportICType; /* Cut Version TestChip/A-cut/B-cut... = 0/1/2/3/... */ u8 CutVersion; - /* RF Type 4T4R/3T3R/2T2R/1T2R/1T1R/... */ - u8 RFType; /* Board Type Normal/HighPower/MiniCard/SLIM/Combo/. = 0/1/2/3/4/. */ u8 BoardType; /* with external LNA NO/Yes = 0/1 */ -- cgit v0.10.2 From d30924a032722d72d19fc0ad13f24c7b5a6adf27 Mon Sep 17 00:00:00 2001 From: Johan Svensson <johan.svensson692@gmail.com> Date: Thu, 22 Sep 2016 20:11:21 +0200 Subject: staging: ks7010: add blank line after variable declarations Fixes warnings found by checkpatch Missing a blank line after declarations Signed-off-by: Johan Svensson <johan.svensson692@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c index aad8048..c57ca58 100644 --- a/drivers/staging/ks7010/ks_hostif.c +++ b/drivers/staging/ks7010/ks_hostif.c @@ -35,6 +35,7 @@ static inline u8 get_BYTE(struct ks_wlan_private *priv) { u8 data; + data = *(priv->rxp)++; /* length check in advance ! */ --(priv->rx_size); @@ -45,6 +46,7 @@ static inline u16 get_WORD(struct ks_wlan_private *priv) { u16 data; + data = (get_BYTE(priv) & 0xff); data |= ((get_BYTE(priv) << 8) & 0xff00); return data; @@ -54,6 +56,7 @@ static inline u32 get_DWORD(struct ks_wlan_private *priv) { u32 data; + data = (get_BYTE(priv) & 0xff); data |= ((get_BYTE(priv) << 8) & 0x0000ff00); data |= ((get_BYTE(priv) << 16) & 0x00ff0000); -- cgit v0.10.2 From 0e21fa4602078160e03ef210c983df0c257ccbe8 Mon Sep 17 00:00:00 2001 From: Jannik Becher <becher.jannik@gmail.com> Date: Fri, 23 Sep 2016 01:02:10 +0200 Subject: staging: wlan-ng: remove unnecessary spaces before casts Fixed a coding style issue by removing unnecessary spaces before casts. Signed-off-by: Jannik Becher <Becher.Jannik@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index f8ee175..4cf4796 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -256,7 +256,7 @@ Information RID Lengths: MAC Information include the len or code fields) --------------------------------------------------------------------*/ #define HFA384x_RID_DBMCOMMSQUALITY_LEN \ - ((u16) sizeof(hfa384x_dbmcommsquality_t)) + ((u16)sizeof(hfa384x_dbmcommsquality_t)) #define HFA384x_RID_JOINREQUEST_LEN \ ((u16)sizeof(hfa384x_JoinRequest_data_t)) @@ -1380,7 +1380,7 @@ static inline int hfa384x_drvr_getconfig16(hfa384x_t *hw, u16 rid, void *val) result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(u16)); if (result == 0) - *((u16 *) val) = le16_to_cpu(*((u16 *) val)); + *((u16 *)val) = le16_to_cpu(*((u16 *)val)); return result; } diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c index fb97779..38c936a 100644 --- a/drivers/staging/wlan-ng/p80211netdev.c +++ b/drivers/staging/wlan-ng/p80211netdev.c @@ -231,7 +231,7 @@ static int p80211_convert_to_ether(struct wlandevice *wlandev, struct sk_buff *s { struct p80211_hdr_a3 *hdr; - hdr = (struct p80211_hdr_a3 *) skb->data; + hdr = (struct p80211_hdr_a3 *)skb->data; if (p80211_rx_typedrop(wlandev, hdr->fc)) return CONV_TO_ETHER_SKIPPED; @@ -265,7 +265,7 @@ static int p80211_convert_to_ether(struct wlandevice *wlandev, struct sk_buff *s */ static void p80211netdev_rx_bh(unsigned long arg) { - struct wlandevice *wlandev = (struct wlandevice *) arg; + struct wlandevice *wlandev = (struct wlandevice *)arg; struct sk_buff *skb = NULL; netdevice_t *dev = wlandev->netdev; @@ -534,7 +534,7 @@ static int p80211netdev_ethtool(struct wlandevice *wlandev, void __user *useradd static int p80211knetdev_do_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd) { int result = 0; - struct p80211ioctl_req *req = (struct p80211ioctl_req *) ifr; + struct p80211ioctl_req *req = (struct p80211ioctl_req *)ifr; struct wlandevice *wlandev = dev->ml_priv; u8 *msgbuf; @@ -625,7 +625,7 @@ static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr) /* Set up some convenience pointers. */ mibattr = &dot11req.mibattribute; - macaddr = (p80211item_pstr6_t *) &mibattr->data; + macaddr = (p80211item_pstr6_t *)&mibattr->data; resultcode = &dot11req.resultcode; /* Set up a dot11req_mibset */ @@ -633,7 +633,7 @@ static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr) dot11req.msgcode = DIDmsg_dot11req_mibset; dot11req.msglen = sizeof(struct p80211msg_dot11req_mibset); memcpy(dot11req.devname, - ((struct wlandevice *) dev->ml_priv)->name, WLAN_DEVNAMELEN_MAX - 1); + ((struct wlandevice *)dev->ml_priv)->name, WLAN_DEVNAMELEN_MAX - 1); /* Set up the mibattribute argument */ mibattr->did = DIDmsg_dot11req_mibset_mibattribute; @@ -653,7 +653,7 @@ static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr) resultcode->data = 0; /* now fire the request */ - result = p80211req_dorequest(dev->ml_priv, (u8 *) &dot11req); + result = p80211req_dorequest(dev->ml_priv, (u8 *)&dot11req); /* If the request wasn't successful, report an error and don't * change the netdev address diff --git a/drivers/staging/wlan-ng/p80211req.c b/drivers/staging/wlan-ng/p80211req.c index 40627d5..010e5dc 100644 --- a/drivers/staging/wlan-ng/p80211req.c +++ b/drivers/staging/wlan-ng/p80211req.c @@ -110,7 +110,7 @@ static void p80211req_handle_action(struct wlandevice *wlandev, u32 *data, ----------------------------------------------------------------*/ int p80211req_dorequest(struct wlandevice *wlandev, u8 *msgbuf) { - struct p80211msg *msg = (struct p80211msg *) msgbuf; + struct p80211msg *msg = (struct p80211msg *)msgbuf; /* Check to make sure the MSD is running */ if (!((wlandev->msdstate == WLAN_MSD_HWPRESENT && @@ -170,7 +170,7 @@ static void p80211req_handlemsg(struct wlandevice *wlandev, struct p80211msg *ms case DIDmsg_lnxreq_hostwep:{ struct p80211msg_lnxreq_hostwep *req = - (struct p80211msg_lnxreq_hostwep *) msg; + (struct p80211msg_lnxreq_hostwep *)msg; wlandev->hostwep &= ~(HOSTWEP_DECRYPT | HOSTWEP_ENCRYPT); if (req->decrypt.data == P80211ENUM_truth_true) @@ -184,7 +184,7 @@ static void p80211req_handlemsg(struct wlandevice *wlandev, struct p80211msg *ms case DIDmsg_dot11req_mibset:{ int isget = (msg->msgcode == DIDmsg_dot11req_mibget); struct p80211msg_dot11req_mibget *mib_msg = - (struct p80211msg_dot11req_mibget *) msg; + (struct p80211msg_dot11req_mibget *)msg; p80211req_mibset_mibget(wlandev, mib_msg, isget); break; } @@ -195,8 +195,8 @@ static void p80211req_mibset_mibget(struct wlandevice *wlandev, struct p80211msg_dot11req_mibget *mib_msg, int isget) { - p80211itemd_t *mibitem = (p80211itemd_t *) mib_msg->mibattribute.data; - p80211pstrd_t *pstr = (p80211pstrd_t *) mibitem->data; + p80211itemd_t *mibitem = (p80211itemd_t *)mib_msg->mibattribute.data; + p80211pstrd_t *pstr = (p80211pstrd_t *)mibitem->data; u8 *key = mibitem->data + sizeof(p80211pstrd_t); switch (mibitem->did) { @@ -211,7 +211,7 @@ static void p80211req_mibset_mibget(struct wlandevice *wlandev, break; case DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID:{ - u32 *data = (u32 *) mibitem->data; + u32 *data = (u32 *)mibitem->data; if (isget) { *data = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK; @@ -222,14 +222,14 @@ static void p80211req_mibset_mibget(struct wlandevice *wlandev, break; } case DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked:{ - u32 *data = (u32 *) mibitem->data; + u32 *data = (u32 *)mibitem->data; p80211req_handle_action(wlandev, data, isget, HOSTWEP_PRIVACYINVOKED); break; } case DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted:{ - u32 *data = (u32 *) mibitem->data; + u32 *data = (u32 *)mibitem->data; p80211req_handle_action(wlandev, data, isget, HOSTWEP_EXCLUDEUNENCRYPTED); diff --git a/drivers/staging/wlan-ng/prism2fw.c b/drivers/staging/wlan-ng/prism2fw.c index 161637b..870bad9 100644 --- a/drivers/staging/wlan-ng/prism2fw.c +++ b/drivers/staging/wlan-ng/prism2fw.c @@ -266,7 +266,7 @@ static int prism2_fwapply(const struct ihex_binrec *rfptr, /* clear the pda and add an initial END record */ memset(&pda, 0, sizeof(pda)); - pda.rec[0] = (hfa384x_pdrec_t *) pda.buf; + pda.rec[0] = (hfa384x_pdrec_t *)pda.buf; pda.rec[0]->len = cpu_to_le16(2); /* len in words */ pda.rec[0]->code = cpu_to_le16(HFA384x_PDR_END_OF_PDA); pda.nrec = 1; @@ -293,11 +293,11 @@ static int prism2_fwapply(const struct ihex_binrec *rfptr, getmsg.resultcode.did = DIDmsg_dot11req_mibget_resultcode; getmsg.resultcode.status = P80211ENUM_msgitem_status_no_value; - item = (p80211itemd_t *) getmsg.mibattribute.data; + item = (p80211itemd_t *)getmsg.mibattribute.data; item->did = DIDmib_p2_p2NIC_p2PRISupRange; item->status = P80211ENUM_msgitem_status_no_value; - data = (u32 *) item->data; + data = (u32 *)item->data; /* DIDmsg_dot11req_mibget */ prism2mgmt_mibset_mibget(wlandev, &getmsg); @@ -592,14 +592,14 @@ static int mkimage(struct imgchunk *clist, unsigned int *ccnt) ----------------------------------------------------------------*/ static int mkpdrlist(struct pda *pda) { - u16 *pda16 = (u16 *) pda->buf; + u16 *pda16 = (u16 *)pda->buf; int curroff; /* in 'words' */ pda->nrec = 0; curroff = 0; while (curroff < (HFA384x_PDA_LEN_MAX / 2 - 1) && le16_to_cpu(pda16[curroff + 1]) != HFA384x_PDR_END_OF_PDA) { - pda->rec[pda->nrec] = (hfa384x_pdrec_t *) &(pda16[curroff]); + pda->rec[pda->nrec] = (hfa384x_pdrec_t *)&(pda16[curroff]); if (le16_to_cpu(pda->rec[pda->nrec]->code) == HFA384x_PDR_NICID) { @@ -638,7 +638,7 @@ static int mkpdrlist(struct pda *pda) curroff, pda->nrec); return 1; } - pda->rec[pda->nrec] = (hfa384x_pdrec_t *) &(pda16[curroff]); + pda->rec[pda->nrec] = (hfa384x_pdrec_t *)&(pda16[curroff]); (pda->nrec)++; return 0; } @@ -879,8 +879,8 @@ static int read_fwfile(const struct ihex_binrec *record) addr = be32_to_cpu(record->addr); /* Point into data for different word lengths */ - ptr32 = (u32 *) record->data; - ptr16 = (u16 *) record->data; + ptr32 = (u32 *)record->data; + ptr16 = (u16 *)record->data; /* parse what was an S3 srec and put it in the right array */ switch (addr) { @@ -954,7 +954,7 @@ static int read_fwfile(const struct ihex_binrec *record) default: /* Data record */ s3data[ns3data].addr = addr; s3data[ns3data].len = len; - s3data[ns3data].data = (uint8_t *) record->data; + s3data[ns3data].data = (uint8_t *)record->data; ns3data++; if (ns3data == S3DATA_MAX) { pr_err("S3 datarec limit reached - aborting\n"); diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c index b380c7d..f6f48d9 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.c +++ b/drivers/staging/wlan-ng/prism2mgmt.c @@ -533,7 +533,7 @@ int prism2mgmt_start(struct wlandevice *wlandev, void *msgp) p80211pstrd_t *pstr; u8 bytebuf[80]; - struct hfa384x_bytestr *p2bytestr = (struct hfa384x_bytestr *) bytebuf; + struct hfa384x_bytestr *p2bytestr = (struct hfa384x_bytestr *)bytebuf; u16 word; wlandev->macmode = WLAN_MACMODE_NONE; @@ -558,7 +558,7 @@ int prism2mgmt_start(struct wlandevice *wlandev, void *msgp) /*** STATION ***/ /* Set the REQUIRED config items */ /* SSID */ - pstr = (p80211pstrd_t *) &(msg->ssid.data); + pstr = (p80211pstrd_t *)&(msg->ssid.data); prism2mgmt_pstr2bytestr(p2bytestr, pstr); result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFOWNSSID, bytebuf, HFA384x_RID_CNFOWNSSID_LEN); @@ -1028,7 +1028,7 @@ int prism2mgmt_autojoin(struct wlandevice *wlandev, void *msgp) struct p80211msg_lnxreq_autojoin *msg = msgp; p80211pstrd_t *pstr; u8 bytebuf[256]; - struct hfa384x_bytestr *p2bytestr = (struct hfa384x_bytestr *) bytebuf; + struct hfa384x_bytestr *p2bytestr = (struct hfa384x_bytestr *)bytebuf; wlandev->macmode = WLAN_MACMODE_NONE; @@ -1052,7 +1052,7 @@ int prism2mgmt_autojoin(struct wlandevice *wlandev, void *msgp) /* Set the ssid */ memset(bytebuf, 0, 256); - pstr = (p80211pstrd_t *) &(msg->ssid.data); + pstr = (p80211pstrd_t *)&(msg->ssid.data); prism2mgmt_pstr2bytestr(p2bytestr, pstr); result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID, bytebuf, diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c index b02a3b1..ad1ae90 100644 --- a/drivers/staging/wlan-ng/prism2mib.c +++ b/drivers/staging/wlan-ng/prism2mib.c @@ -284,7 +284,7 @@ int prism2mgmt_mibset_mibget(struct wlandevice *wlandev, void *msgp) ** MIB table. */ - mibitem = (p80211itemd_t *) msg->mibattribute.data; + mibitem = (p80211itemd_t *)msg->mibattribute.data; for (mib = mibtab; mib->did != 0; mib++) if (mib->did == mibitem->did && (mib->flag & which)) @@ -430,7 +430,7 @@ static int prism2mib_uint32(struct mibrec *mib, int result; u32 *uint32 = data; u8 bytebuf[MIB_TMP_MAXLEN]; - u16 *wordbuf = (u16 *) bytebuf; + u16 *wordbuf = (u16 *)bytebuf; if (isget) { result = hfa384x_drvr_getconfig16(hw, mib->parm1, wordbuf); @@ -477,7 +477,7 @@ static int prism2mib_flag(struct mibrec *mib, int result; u32 *uint32 = data; u8 bytebuf[MIB_TMP_MAXLEN]; - u16 *wordbuf = (u16 *) bytebuf; + u16 *wordbuf = (u16 *)bytebuf; u32 flags; result = hfa384x_drvr_getconfig16(hw, mib->parm1, wordbuf); @@ -714,7 +714,7 @@ static int prism2mib_priv(struct mibrec *mib, if (isget) { hfa384x_drvr_getconfig(hw, HFA384x_RID_CNFWPADATA, - (u8 *) &wpa, + (u8 *)&wpa, sizeof(wpa)); pstr->len = le16_to_cpu(wpa.datalen); memcpy(pstr->data, wpa.data, pstr->len); @@ -724,7 +724,7 @@ static int prism2mib_priv(struct mibrec *mib, hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFWPADATA, - (u8 *) &wpa, + (u8 *)&wpa, sizeof(wpa)); } break; @@ -754,7 +754,7 @@ static int prism2mib_priv(struct mibrec *mib, void prism2mgmt_pstr2bytestr(struct hfa384x_bytestr *bytestr, p80211pstrd_t *pstr) { - bytestr->len = cpu_to_le16((u16) (pstr->len)); + bytestr->len = cpu_to_le16((u16)(pstr->len)); memcpy(bytestr->data, pstr->data, pstr->len); } @@ -776,7 +776,7 @@ void prism2mgmt_pstr2bytestr(struct hfa384x_bytestr *bytestr, void prism2mgmt_bytestr2pstr(struct hfa384x_bytestr *bytestr, p80211pstrd_t *pstr) { - pstr->len = (u8) (le16_to_cpu((u16) (bytestr->len))); + pstr->len = (u8)(le16_to_cpu((u16)(bytestr->len))); memcpy(pstr->data, bytestr->data, pstr->len); } @@ -797,6 +797,6 @@ void prism2mgmt_bytestr2pstr(struct hfa384x_bytestr *bytestr, void prism2mgmt_bytearea2pstr(u8 *bytearea, p80211pstrd_t *pstr, int len) { - pstr->len = (u8) len; + pstr->len = (u8)len; memcpy(pstr->data, bytearea, len); } diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index e6c9bb0..b8009ae 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -337,7 +337,7 @@ static int prism2sta_mlmerequest(struct wlandevice *wlandev, struct p80211msg *m struct p80211msg_lnxreq_ifstate *ifstatemsg; pr_debug("Received mlme ifstate request\n"); - ifstatemsg = (struct p80211msg_lnxreq_ifstate *) msg; + ifstatemsg = (struct p80211msg_lnxreq_ifstate *)msg; result = prism2sta_ifstate(wlandev, ifstatemsg->ifstate.data); @@ -360,7 +360,7 @@ static int prism2sta_mlmerequest(struct wlandevice *wlandev, struct p80211msg *m pr_debug("Received commsquality request\n"); - qualmsg = (struct p80211msg_lnxreq_commsquality *) msg; + qualmsg = (struct p80211msg_lnxreq_commsquality *)msg; qualmsg->link.status = P80211ENUM_msgitem_status_data_ok; @@ -651,7 +651,7 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev) /* strip out the 'special' variant bits */ hw->mm_mods = hw->ident_sta_fw.variant & (BIT(14) | BIT(15)); - hw->ident_sta_fw.variant &= ~((u16) (BIT(14) | BIT(15))); + hw->ident_sta_fw.variant &= ~((u16)(BIT(14) | BIT(15))); if (hw->ident_sta_fw.id == 0x1f) { netdev_info(wlandev->netdev, @@ -999,13 +999,13 @@ static void prism2sta_inf_tallies(struct wlandevice *wlandev, cnt = sizeof(hfa384x_CommTallies32_t) / sizeof(u32); if (inf->framelen > 22) { - dst = (u32 *) &hw->tallies; - src32 = (u32 *) &inf->info.commtallies32; + dst = (u32 *)&hw->tallies; + src32 = (u32 *)&inf->info.commtallies32; for (i = 0; i < cnt; i++, dst++, src32++) *dst += le32_to_cpu(*src32); } else { - dst = (u32 *) &hw->tallies; - src16 = (u16 *) &inf->info.commtallies16; + dst = (u32 *)&hw->tallies; + src16 = (u16 *)&inf->info.commtallies16; for (i = 0; i < cnt; i++, dst++, src16++) *dst += le16_to_cpu(*src16); } @@ -1180,7 +1180,7 @@ void prism2sta_processing_defer(struct work_struct *data) hfa384x_InfFrame_t *inf; while ((skb = skb_dequeue(&hw->authq))) { - inf = (hfa384x_InfFrame_t *) skb->data; + inf = (hfa384x_InfFrame_t *)skb->data; prism2sta_inf_authreq_defer(wlandev, inf); } @@ -1255,8 +1255,8 @@ void prism2sta_processing_defer(struct work_struct *data) return; } prism2mgmt_bytestr2pstr( - (struct hfa384x_bytestr *) &ssid, - (p80211pstrd_t *) &wlandev->ssid); + (struct hfa384x_bytestr *)&ssid, + (p80211pstrd_t *)&wlandev->ssid); /* Collect the port status */ result = hfa384x_drvr_getconfig16(hw, @@ -1336,8 +1336,8 @@ void prism2sta_processing_defer(struct work_struct *data) HFA384x_RID_CURRENTSSID, result); return; } - prism2mgmt_bytestr2pstr((struct hfa384x_bytestr *) &ssid, - (p80211pstrd_t *) &wlandev->ssid); + prism2mgmt_bytestr2pstr((struct hfa384x_bytestr *)&ssid, + (p80211pstrd_t *)&wlandev->ssid); hw->link_status = HFA384x_LINK_CONNECTED; netif_carrier_on(wlandev->netdev); @@ -1949,7 +1949,7 @@ void prism2sta_commsqual_defer(struct work_struct *data) /* Get the signal rate */ msg.msgcode = DIDmsg_dot11req_mibget; mibitem->did = DIDmib_p2_p2MAC_p2CurrentTxRate; - result = p80211req_dorequest(wlandev, (u8 *) &msg); + result = p80211req_dorequest(wlandev, (u8 *)&msg); if (result) { pr_debug("get signal rate failed, result = %d\n", @@ -1992,8 +1992,8 @@ void prism2sta_commsqual_defer(struct work_struct *data) HFA384x_RID_CURRENTSSID, result); return; } - prism2mgmt_bytestr2pstr((struct hfa384x_bytestr *) &ssid, - (p80211pstrd_t *) &wlandev->ssid); + prism2mgmt_bytestr2pstr((struct hfa384x_bytestr *)&ssid, + (p80211pstrd_t *)&wlandev->ssid); /* Reschedule timer */ mod_timer(&hw->commsqual_timer, jiffies + HZ); @@ -2001,7 +2001,7 @@ void prism2sta_commsqual_defer(struct work_struct *data) void prism2sta_commsqual_timer(unsigned long data) { - hfa384x_t *hw = (hfa384x_t *) data; + hfa384x_t *hw = (hfa384x_t *)data; schedule_work(&hw->commsqual_bh); } -- cgit v0.10.2 From 82af03f7b945634bfa93fef4e2f50db4459aabea Mon Sep 17 00:00:00 2001 From: sayli karnik <karniksayli1995@gmail.com> Date: Thu, 22 Sep 2016 22:09:06 +0530 Subject: staging: greybus: Use setup_timer function This patch uses setup_timer function instead of initializing timer with the function and data fields. Signed-off-by: sayli karnik <karniksayli1995@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 8b0d0dc..7882306 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -603,7 +603,6 @@ static int gb_loopback_async_operation(struct gb_loopback *gb, int type, return -ENOMEM; INIT_WORK(&op_async->work, gb_loopback_async_operation_work); - init_timer(&op_async->timer); kref_init(&op_async->kref); operation = gb_operation_create(gb->connection, type, request_size, @@ -634,9 +633,9 @@ static int gb_loopback_async_operation(struct gb_loopback *gb, int type, if (ret) goto error; - op_async->timer.function = gb_loopback_async_operation_timeout; + setup_timer(&op_async->timer, gb_loopback_async_operation_timeout, + (unsigned long)operation->id); op_async->timer.expires = jiffies + gb->jiffy_timeout; - op_async->timer.data = (unsigned long)operation->id; add_timer(&op_async->timer); goto done; -- cgit v0.10.2 From da2c08714c94780d81780dd8918c71d491f672f4 Mon Sep 17 00:00:00 2001 From: Christian Gromm <christian.gromm@microchip.com> Date: Fri, 23 Sep 2016 15:20:02 +0200 Subject: staging: most: aim-cdev: make syscall write accept buffers of arbitrary size This patch allows to call the write() function for synchronous and isochronous channels with buffers of any size. The AIM simply waits for data to fill up the MOST buffer object according to the network interface controller specification for streaming channels, before it submits the buffer to the HDM. The new behavior is backward compatible to the old applications, since all known applications needed to fill the buffer completely anyway. Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index 5458fb9..7f51024 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -57,7 +57,11 @@ static inline bool ch_has_mbo(struct aim_channel *c) static inline bool ch_get_mbo(struct aim_channel *c, struct mbo **mbo) { - *mbo = most_get_mbo(c->iface, c->channel_id, &cdev_aim); + if (!kfifo_peek(&c->fifo, mbo)) { + *mbo = most_get_mbo(c->iface, c->channel_id, &cdev_aim); + if (*mbo) + kfifo_in(&c->fifo, mbo, 1); + } return *mbo; } @@ -184,8 +188,7 @@ static ssize_t aim_write(struct file *filp, const char __user *buf, size_t count, loff_t *offset) { int ret; - size_t actual_len; - size_t max_len; + size_t to_copy, left; struct mbo *mbo = NULL; struct aim_channel *c = filp->private_data; @@ -205,20 +208,24 @@ static ssize_t aim_write(struct file *filp, const char __user *buf, goto unlock; } - max_len = c->cfg->buffer_size; - actual_len = min(count, max_len); - mbo->buffer_length = actual_len; - - if (copy_from_user(mbo->virt_address, buf, mbo->buffer_length)) { + to_copy = min(count, c->cfg->buffer_size - c->mbo_offs); + left = copy_from_user(mbo->virt_address + c->mbo_offs, buf, to_copy); + if (left == to_copy) { ret = -EFAULT; - goto put_mbo; + goto unlock; } - most_submit_mbo(mbo); - mutex_unlock(&c->io_mutex); - return actual_len; -put_mbo: - most_put_mbo(mbo); + c->mbo_offs += to_copy - left; + if (c->mbo_offs >= c->cfg->buffer_size || + c->cfg->data_type == MOST_CH_CONTROL || + c->cfg->data_type == MOST_CH_ASYNC) { + kfifo_skip(&c->fifo); + mbo->buffer_length = c->mbo_offs; + c->mbo_offs = 0; + most_submit_mbo(mbo); + } + + ret = to_copy - left; unlock: mutex_unlock(&c->io_mutex); return ret; @@ -287,7 +294,7 @@ static unsigned int aim_poll(struct file *filp, poll_table *wait) if (!kfifo_is_empty(&c->fifo)) mask |= POLLIN | POLLRDNORM; } else { - if (ch_has_mbo(c)) + if (!kfifo_is_empty(&c->fifo) || ch_has_mbo(c)) mask |= POLLOUT | POLLWRNORM; } return mask; -- cgit v0.10.2 From 252a2560903085c7d030eee070a1c15b13bac101 Mon Sep 17 00:00:00 2001 From: Baoyou Xie <baoyou.xie@linaro.org> Date: Fri, 23 Sep 2016 21:13:35 +0800 Subject: staging: android: ion: mark symbols static where possible We get 4 warnings when building kernel with W=1: drivers/staging/android/ion/ion_carveout_heap.c:36:17: warning: no previous prototype for 'ion_carveout_allocate' [-Wmissing-prototypes] drivers/staging/android/ion/ion_carveout_heap.c:50:6: warning: no previous prototype for 'ion_carveout_free' [-Wmissing-prototypes] drivers/staging/android/ion/ion_of.c:28:5: warning: no previous prototype for 'ion_parse_dt_heap_common' [-Wmissing-prototypes] drivers/staging/android/ion/ion_of.c:54:5: warning: no previous prototype for 'ion_setup_heap_common' [-Wmissing-prototypes] In fact, these functions are only used in the file in which they are declared and don't need a declaration, but can be made static. so this patch marks these functions with 'static'. Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index c4f0795..a8ea973 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -33,9 +33,9 @@ struct ion_carveout_heap { ion_phys_addr_t base; }; -ion_phys_addr_t ion_carveout_allocate(struct ion_heap *heap, - unsigned long size, - unsigned long align) +static ion_phys_addr_t ion_carveout_allocate(struct ion_heap *heap, + unsigned long size, + unsigned long align) { struct ion_carveout_heap *carveout_heap = container_of(heap, struct ion_carveout_heap, heap); @@ -47,8 +47,8 @@ ion_phys_addr_t ion_carveout_allocate(struct ion_heap *heap, return offset; } -void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr, - unsigned long size) +static void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr, + unsigned long size) { struct ion_carveout_heap *carveout_heap = container_of(heap, struct ion_carveout_heap, heap); diff --git a/drivers/staging/android/ion/ion_of.c b/drivers/staging/android/ion/ion_of.c index de0899a..3486909 100644 --- a/drivers/staging/android/ion/ion_of.c +++ b/drivers/staging/android/ion/ion_of.c @@ -25,9 +25,9 @@ #include "ion_priv.h" #include "ion_of.h" -int ion_parse_dt_heap_common(struct device_node *heap_node, - struct ion_platform_heap *heap, - struct ion_of_heap *compatible) +static int ion_parse_dt_heap_common(struct device_node *heap_node, + struct ion_platform_heap *heap, + struct ion_of_heap *compatible) { int i; @@ -51,9 +51,9 @@ int ion_parse_dt_heap_common(struct device_node *heap_node, return 0; } -int ion_setup_heap_common(struct platform_device *parent, - struct device_node *heap_node, - struct ion_platform_heap *heap) +static int ion_setup_heap_common(struct platform_device *parent, + struct device_node *heap_node, + struct ion_platform_heap *heap) { int ret = 0; -- cgit v0.10.2 From 3590e78a1d28f16aebbd723fc021cb752e42737b Mon Sep 17 00:00:00 2001 From: Baoyou Xie <baoyou.xie@linaro.org> Date: Fri, 23 Sep 2016 21:31:18 +0800 Subject: staging: rtl8192u: ieee80211: ieee80211_softmac: mark symbols static where possible We get 5 warnings when building kernel with W=1: drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c:287:13: warning: no previous declaration for 'softmac_ps_mgmt_xmit' [-Wmissing-declarations] drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c:323:24: warning: no previous declaration for 'ieee80211_probe_req' [-Wmissing-declarations] drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c:643:24: warning: no previous declaration for 'ieee80211_authentication_req' [-Wmissing-declarations] drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c:981:24: warning: no previous declaration for 'ieee80211_association_req' [-Wmissing-declarations] drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c:3094:24: warning: no previous declaration for 'ieee80211_disassociate_skb' [-Wmissing-declarations] In fact, these functions are only used in the file in which they are declared and don't need a declaration, but can be made static. so this patch marks these functions with 'static'. Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c index 10a8040..d7d85b3 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c @@ -284,7 +284,8 @@ inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee } } -inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee) +static inline void +softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee) { short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE; @@ -320,7 +321,7 @@ inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *i //dev_kfree_skb_any(skb);//edit by thomas } -inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee) +static inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee) { unsigned int len, rate_len; u8 *tag; @@ -640,8 +641,9 @@ void ieee80211_start_scan_syncro(struct ieee80211_device *ieee) } EXPORT_SYMBOL(ieee80211_start_scan_syncro); -inline struct sk_buff *ieee80211_authentication_req(struct ieee80211_network *beacon, - struct ieee80211_device *ieee, int challengelen) +static inline struct sk_buff * +ieee80211_authentication_req(struct ieee80211_network *beacon, + struct ieee80211_device *ieee, int challengelen) { struct sk_buff *skb; struct ieee80211_authentication *auth; @@ -978,7 +980,9 @@ static void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest) } -inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beacon,struct ieee80211_device *ieee) +static inline struct sk_buff * +ieee80211_association_req(struct ieee80211_network *beacon, + struct ieee80211_device *ieee) { struct sk_buff *skb; //unsigned long flags; @@ -3091,7 +3095,7 @@ static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee, return ret; } -inline struct sk_buff *ieee80211_disassociate_skb( +static inline struct sk_buff *ieee80211_disassociate_skb( struct ieee80211_network *beacon, struct ieee80211_device *ieee, u8 asRsn) -- cgit v0.10.2 From af8b19c4a8ed156904e14d97dd186f5d8858acd6 Mon Sep 17 00:00:00 2001 From: Baoyou Xie <baoyou.xie@linaro.org> Date: Fri, 23 Sep 2016 21:35:22 +0800 Subject: staging: rtl8192u: remove unused functions in r8192U_core.c We get 2 warnings when building kernel with W=1: drivers/staging/rtl8192u/r8192U_core.c:925:12: warning: no previous declaration for 'ieeerate2rtlrate' [-Wmissing-declarations] drivers/staging/rtl8192u/r8192U_core.c:958:12: warning: no previous declaration for 'rtl8192_rate2rate' [-Wmissing-declarations] drivers/staging/rtl8192u/r8192U_core.c:1322:11: warning: no previous declaration for 'rtl8192_IsWirelessBMode' [-Wmissing-declarations] In fact, these functions are unused in r8192U_core.c, but should be removed. So this patch removes the unused functions. Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c index c66e7cf..457eeb5 100644 --- a/drivers/staging/rtl8192u/r8192U_core.c +++ b/drivers/staging/rtl8192u/r8192U_core.c @@ -922,47 +922,6 @@ void rtl8192_rtx_disable(struct net_device *dev) skb_queue_purge(&priv->skb_queue); } -inline u16 ieeerate2rtlrate(int rate) -{ - switch (rate) { - case 10: - return 0; - case 20: - return 1; - case 55: - return 2; - case 110: - return 3; - case 60: - return 4; - case 90: - return 5; - case 120: - return 6; - case 180: - return 7; - case 240: - return 8; - case 360: - return 9; - case 480: - return 10; - case 540: - return 11; - default: - return 3; - } -} - -static u16 rtl_rate[] = {10, 20, 55, 110, 60, 90, 120, 180, 240, 360, 480, 540}; -inline u16 rtl8192_rate2rate(short rate) -{ - if (rate > 11) - return 0; - return rtl_rate[rate]; -} - - /* The prototype of rx_isr has changed since one version of Linux Kernel */ static void rtl8192_rx_isr(struct urb *urb) { @@ -1319,14 +1278,6 @@ void rtl819xusb_beacon_tx(struct net_device *dev, u16 tx_rate) } -inline u8 rtl8192_IsWirelessBMode(u16 rate) -{ - if (((rate <= 110) && (rate != 60) && (rate != 90)) || (rate == 220)) - return 1; - else - return 0; -} - short rtl819xU_tx_cmd(struct net_device *dev, struct sk_buff *skb) { struct r8192_priv *priv = ieee80211_priv(dev); -- cgit v0.10.2 From e4e8d968a319a311908b2dd8f241442b5c529b5f Mon Sep 17 00:00:00 2001 From: Baoyou Xie <baoyou.xie@linaro.org> Date: Fri, 23 Sep 2016 21:21:33 +0800 Subject: Staging: ks7010: remove unused function in ks_wlan_net.c We get 1 warning when building kernel with W=1: drivers/staging/ks7010/ks_wlan_net.c:3520:5: warning: no previous prototype for 'ks_wlan_reset' [-Wmissing-prototypes] In fact, these functions are unused in ks_wlan_net.c, but should be removed. So this patch removes the unused function. Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks_wlan_net.c b/drivers/staging/ks7010/ks_wlan_net.c index ee9c8f3..f1cd90e 100644 --- a/drivers/staging/ks7010/ks_wlan_net.c +++ b/drivers/staging/ks7010/ks_wlan_net.c @@ -3516,8 +3516,3 @@ int ks_wlan_net_stop(struct net_device *dev) return ret; } - -int ks_wlan_reset(struct net_device *dev) -{ - return 0; -} -- cgit v0.10.2 From 55adb7bf5a3e466b471eae8db8334f1196c3a2f8 Mon Sep 17 00:00:00 2001 From: Georgiana Rodica Chelu <georgiana.chelu93@gmail.com> Date: Fri, 23 Sep 2016 22:45:25 +0300 Subject: staging: ks7010: ks_wlan_net: Remove unnecessary variable used to store return value Remove unneeded code in order to make clear that the function returns 0(success) in all cases. Done using returnvar.cocci script. Signed-off-by: Georgiana Rodica Chelu <georgiana.chelu93@gmail.com> Acked-by: Julia Lawall <julia.lawall@lip6.fr> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks_wlan_net.c b/drivers/staging/ks7010/ks_wlan_net.c index f1cd90e..d13a06b 100644 --- a/drivers/staging/ks7010/ks_wlan_net.c +++ b/drivers/staging/ks7010/ks_wlan_net.c @@ -3507,12 +3507,11 @@ int ks_wlan_net_stop(struct net_device *dev) { struct ks_wlan_private *priv = netdev_priv(dev); - int ret = 0; priv->device_open_status = 0; del_timer_sync(&update_phyinfo_timer); if (netif_running(dev)) netif_stop_queue(dev); - return ret; + return 0; } -- cgit v0.10.2 From 7a4abee97f2a158e73746fd67b2c84454ac2194b Mon Sep 17 00:00:00 2001 From: Georgiana Rodica Chelu <georgiana.chelu93@gmail.com> Date: Sat, 24 Sep 2016 22:49:02 +0300 Subject: staging: ks7010: ks_wlan_net: Remove return statement from void function Remove the return statement from the end of a void function to clean up the code. Issue found by checkpatch.pl script. Signed-off-by: Georgiana Rodica Chelu <georgiana.chelu93@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks_wlan_net.c b/drivers/staging/ks7010/ks_wlan_net.c index d13a06b..9e2bdd6 100644 --- a/drivers/staging/ks7010/ks_wlan_net.c +++ b/drivers/staging/ks7010/ks_wlan_net.c @@ -3349,8 +3349,6 @@ void ks_wlan_tx_timeout(struct net_device *dev) } priv->nstats.tx_errors++; netif_wake_queue(dev); - - return; } static @@ -3416,8 +3414,6 @@ void ks_wlan_set_multicast_list(struct net_device *dev) return; /* not finished initialize */ } hostif_sme_enqueue(priv, SME_MULTICAST_REQUEST); - - return; } static -- cgit v0.10.2 From 23f389384b853323873fde406ebe2ea137b5b30d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antti=20Ker=C3=A4nen?= <detegr@gmail.com> Date: Fri, 23 Sep 2016 21:03:05 +0300 Subject: staging: ion: Fix a coding style issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes the alignment of an allocation flag block comment and moves the comments before each #define. Signed-off-by: Antti Keränen <detegr@gmail.com> Acked-by: Laura Abbott <labbott@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/uapi/ion.h b/drivers/staging/android/uapi/ion.h index 647f130..14cd873 100644 --- a/drivers/staging/android/uapi/ion.h +++ b/drivers/staging/android/uapi/ion.h @@ -52,18 +52,18 @@ enum ion_heap_type { * allocation flags - the lower 16 bits are used by core ion, the upper 16 * bits are reserved for use by the heaps themselves. */ -#define ION_FLAG_CACHED 1 /* - * mappings of this buffer should be - * cached, ion will do cache - * maintenance when the buffer is - * mapped for dma - */ -#define ION_FLAG_CACHED_NEEDS_SYNC 2 /* - * mappings of this buffer will created - * at mmap time, if this is set - * caches must be managed - * manually - */ + +/* + * mappings of this buffer should be cached, ion will do cache maintenance + * when the buffer is mapped for dma + */ +#define ION_FLAG_CACHED 1 + +/* + * mappings of this buffer will created at mmap time, if this is set + * caches must be managed manually + */ +#define ION_FLAG_CACHED_NEEDS_SYNC 2 /** * DOC: Ion Userspace API -- cgit v0.10.2 From ee928cb013f10c89b6779eebb80f514ad89feab2 Mon Sep 17 00:00:00 2001 From: Christopher Pezley <chris@pezley.net> Date: Sat, 24 Sep 2016 18:51:58 +0200 Subject: staging: ion: Align cases with switch The preferred indentation for cases and switches has the cases at the same level as the switch. Signed-off-by: Christopher H. Pezley <chris@pezley.net> Acked-by: Laura Abbott <labbott@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/ion_of.c b/drivers/staging/android/ion/ion_of.c index 3486909..826e756 100644 --- a/drivers/staging/android/ion/ion_of.c +++ b/drivers/staging/android/ion/ion_of.c @@ -58,15 +58,15 @@ static int ion_setup_heap_common(struct platform_device *parent, int ret = 0; switch (heap->type) { - case ION_HEAP_TYPE_CARVEOUT: - case ION_HEAP_TYPE_CHUNK: - if (heap->base && heap->size) - return 0; - - ret = of_reserved_mem_device_init(heap->priv); - break; - default: - break; + case ION_HEAP_TYPE_CARVEOUT: + case ION_HEAP_TYPE_CHUNK: + if (heap->base && heap->size) + return 0; + + ret = of_reserved_mem_device_init(heap->priv); + break; + default: + break; } return ret; -- cgit v0.10.2 From c491786447da1a0f3ee63fdc1d086f9e05df4540 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Fri, 23 Sep 2016 15:45:17 +0200 Subject: staging: wlan-ng: avoid new typedef: p80211enumpair_t This patch fixes the following checkpatch.pl warning in p80211types.h: WARNING: do not add new typedefs It applies for typedef p80211enumpair_t. Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h index 8cb4fc6..2fb06ff 100644 --- a/drivers/staging/wlan-ng/p80211types.h +++ b/drivers/staging/wlan-ng/p80211types.h @@ -200,14 +200,14 @@ /* The following structure types are used for the representation */ /* of ENUMint type metadata. */ -typedef struct p80211enumpair { +struct p80211enumpair { u32 val; char *name; -} p80211enumpair_t; +}; typedef struct p80211enum { int nitems; - p80211enumpair_t *list; + struct p80211enumpair *list; } p80211enum_t; /*----------------------------------------------------------------*/ -- cgit v0.10.2 From aa97dc1a76765ea6434f729f9ca4f47765c0db91 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Fri, 23 Sep 2016 15:45:19 +0200 Subject: staging: wlan-ng: avoid new typedef: p80211enum_t This patch fixes the following checkpatch.pl warning in p80211types.h: WARNING: do not add new typedefs It applies for typedef p80211enum_t. Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h index 2fb06ff..e98bc19 100644 --- a/drivers/staging/wlan-ng/p80211types.h +++ b/drivers/staging/wlan-ng/p80211types.h @@ -205,10 +205,10 @@ struct p80211enumpair { char *name; }; -typedef struct p80211enum { +struct p80211enum { int nitems; struct p80211enumpair *list; -} p80211enum_t; +}; /*----------------------------------------------------------------*/ /* The following structure types are used to store data items in */ @@ -351,25 +351,25 @@ typedef u32(*p80211_valid_t) (struct catlistitem *, u32 did, u8 *itembuf); /* The following are the external declarations */ /* for all enumerations */ -extern p80211enum_t MKENUMNAME(truth); -extern p80211enum_t MKENUMNAME(ifstate); -extern p80211enum_t MKENUMNAME(powermgmt); -extern p80211enum_t MKENUMNAME(bsstype); -extern p80211enum_t MKENUMNAME(authalg); -extern p80211enum_t MKENUMNAME(phytype); -extern p80211enum_t MKENUMNAME(temptype); -extern p80211enum_t MKENUMNAME(regdomain); -extern p80211enum_t MKENUMNAME(ccamode); -extern p80211enum_t MKENUMNAME(diversity); -extern p80211enum_t MKENUMNAME(scantype); -extern p80211enum_t MKENUMNAME(resultcode); -extern p80211enum_t MKENUMNAME(reason); -extern p80211enum_t MKENUMNAME(status); -extern p80211enum_t MKENUMNAME(msgcode); -extern p80211enum_t MKENUMNAME(msgitem_status); - -extern p80211enum_t MKENUMNAME(lnxroam_reason); - -extern p80211enum_t MKENUMNAME(p2preamble); +extern struct p80211enum MKENUMNAME(truth); +extern struct p80211enum MKENUMNAME(ifstate); +extern struct p80211enum MKENUMNAME(powermgmt); +extern struct p80211enum MKENUMNAME(bsstype); +extern struct p80211enum MKENUMNAME(authalg); +extern struct p80211enum MKENUMNAME(phytype); +extern struct p80211enum MKENUMNAME(temptype); +extern struct p80211enum MKENUMNAME(regdomain); +extern struct p80211enum MKENUMNAME(ccamode); +extern struct p80211enum MKENUMNAME(diversity); +extern struct p80211enum MKENUMNAME(scantype); +extern struct p80211enum MKENUMNAME(resultcode); +extern struct p80211enum MKENUMNAME(reason); +extern struct p80211enum MKENUMNAME(status); +extern struct p80211enum MKENUMNAME(msgcode); +extern struct p80211enum MKENUMNAME(msgitem_status); + +extern struct p80211enum MKENUMNAME(lnxroam_reason); + +extern struct p80211enum MKENUMNAME(p2preamble); #endif /* _P80211TYPES_H */ -- cgit v0.10.2 From c529e31ff67f52b86a68e13e5e07252918d14b05 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Fri, 23 Sep 2016 15:45:20 +0200 Subject: staging: wlan-ng: avoid new typedef: p80211pstr_t This patch fixes the following checkpatch.pl warning in p80211types.h: WARNING: do not add new typedefs It applies for typedef p80211pstr_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h index e98bc19..b002ee8 100644 --- a/drivers/staging/wlan-ng/p80211types.h +++ b/drivers/staging/wlan-ng/p80211types.h @@ -215,9 +215,9 @@ struct p80211enum { /* messages. */ /* Template pascal string */ -typedef struct p80211pstr { +struct p80211pstr { u8 len; -} __packed p80211pstr_t; +} __packed; typedef struct p80211pstrd { u8 len; -- cgit v0.10.2 From 8e7e0a96926ddaeb518e57b8a7e1042b7ce5e60a Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Fri, 23 Sep 2016 16:12:07 +0200 Subject: staging: rts5208: avoid new typedef in rtsx.h: rtsx_dev_t This patch fixes the following checkpatch.pl warning in rtsx.h: WARNING: do not add new typedefs It also remove DELAY_PARA_T because code is not using it. Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rts5208/rtsx.h b/drivers/staging/rts5208/rtsx.h index 7a21e46..2de4719 100644 --- a/drivers/staging/rts5208/rtsx.h +++ b/drivers/staging/rts5208/rtsx.h @@ -88,8 +88,6 @@ do { \ #define SCSI_LUN(srb) ((srb)->device->lun) -typedef unsigned long DELAY_PARA_T; - struct rtsx_chip; struct rtsx_dev { @@ -130,8 +128,6 @@ struct rtsx_dev { struct rtsx_chip *chip; }; -typedef struct rtsx_dev rtsx_dev_t; - /* Convert between rtsx_dev and the corresponding Scsi_Host */ static inline struct Scsi_Host *rtsx_to_host(struct rtsx_dev *dev) { diff --git a/drivers/staging/rts5208/rtsx_chip.h b/drivers/staging/rts5208/rtsx_chip.h index 132c2e6..6ef34fa 100644 --- a/drivers/staging/rts5208/rtsx_chip.h +++ b/drivers/staging/rts5208/rtsx_chip.h @@ -683,7 +683,7 @@ struct trace_msg_t { #define CLR_SDIO_IGNORED(chip) ((chip)->sdio_func_exist &= ~SDIO_IGNORED) struct rtsx_chip { - rtsx_dev_t *rtsx; + struct rtsx_dev *rtsx; u32 int_reg; /* Bus interrupt pending register */ char max_lun; -- cgit v0.10.2 From 20807e6ec4ce163c65acb6643e95842e091359a9 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Fri, 23 Sep 2016 16:12:08 +0200 Subject: staging: rts5208: avoid symbolic permissions in rtsx.c This patch fixes the following checkpatch.pl warning in rtsx.c: WARNING: Symbolic permissions are not preferred. Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index d7554f4..5d65a5c 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -34,27 +34,27 @@ MODULE_DESCRIPTION("Realtek PCI-Express card reader rts5208/rts5288 driver"); MODULE_LICENSE("GPL"); static unsigned int delay_use = 1; -module_param(delay_use, uint, S_IRUGO | S_IWUSR); +module_param(delay_use, uint, 0644); MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device"); static int ss_en; -module_param(ss_en, int, S_IRUGO | S_IWUSR); +module_param(ss_en, int, 0644); MODULE_PARM_DESC(ss_en, "enable selective suspend"); static int ss_interval = 50; -module_param(ss_interval, int, S_IRUGO | S_IWUSR); +module_param(ss_interval, int, 0644); MODULE_PARM_DESC(ss_interval, "Interval to enter ss state in seconds"); static int auto_delink_en; -module_param(auto_delink_en, int, S_IRUGO | S_IWUSR); +module_param(auto_delink_en, int, 0644); MODULE_PARM_DESC(auto_delink_en, "enable auto delink"); static unsigned char aspm_l0s_l1_en; -module_param(aspm_l0s_l1_en, byte, S_IRUGO | S_IWUSR); +module_param(aspm_l0s_l1_en, byte, 0644); MODULE_PARM_DESC(aspm_l0s_l1_en, "enable device aspm"); static int msi_en; -module_param(msi_en, int, S_IRUGO | S_IWUSR); +module_param(msi_en, int, 0644); MODULE_PARM_DESC(msi_en, "enable msi"); static irqreturn_t rtsx_interrupt(int irq, void *dev_id); -- cgit v0.10.2 From e89ac165a5ebd0a95650ed48d40b8b4e3a8991dc Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Fri, 23 Sep 2016 16:12:09 +0200 Subject: staging: rts5208: fix comment blocks style in rtsx_chip.h This patch fixes the following checkpatch.pl warning in rtsx_chip.h: WARNING: Block comments use a trailing */ on a separate line Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rts5208/rtsx_chip.h b/drivers/staging/rts5208/rtsx_chip.h index 6ef34fa..f366428 100644 --- a/drivers/staging/rts5208/rtsx_chip.h +++ b/drivers/staging/rts5208/rtsx_chip.h @@ -44,8 +44,10 @@ #define MG_SET_ICV_SLOW /* HW may miss ERR/CMDNK signal when sampling INT status. */ #define MS_SAMPLE_INT_ERR - /* HW DO NOT support Wait_INT function during READ_BYTES - * transfer mode */ + /* + * HW DO NOT support Wait_INT function + * during READ_BYTES transfer mode + */ #define READ_BYTES_WAIT_INT #endif @@ -101,17 +103,17 @@ #define TRANSPORT_NO_SENSE 2 /* Command failed, no auto-sense */ #define TRANSPORT_ERROR 3 /* Transport bad (i.e. device dead) */ -/*----------------------------------- - Start-Stop-Unit ------------------------------------*/ +/* + * Start-Stop-Unit + */ #define STOP_MEDIUM 0x00 /* access disable */ #define MAKE_MEDIUM_READY 0x01 /* access enable */ #define UNLOAD_MEDIUM 0x02 /* unload */ #define LOAD_MEDIUM 0x03 /* load */ -/*----------------------------------- - STANDARD_INQUIRY ------------------------------------*/ +/* + * STANDARD_INQUIRY + */ #define QULIFIRE 0x00 #define AENC_FNC 0x00 #define TRML_IOP 0x00 @@ -128,17 +130,15 @@ #define PRDCT_REV_LEN 4 /* Product LOT Length */ /* Dynamic flag definitions: used in set_bit() etc. */ -#define RTSX_FLIDX_TRANS_ACTIVE 18 /* 0x00040000 transfer is active */ -#define RTSX_FLIDX_ABORTING 20 /* 0x00100000 abort is in - * progress */ -#define RTSX_FLIDX_DISCONNECTING 21 /* 0x00200000 disconnect - * in progress */ +#define RTSX_FLIDX_TRANS_ACTIVE 18 /* 0x00040000 transfer is active */ +#define RTSX_FLIDX_ABORTING 20 /* 0x00100000 abort is in progress */ +#define RTSX_FLIDX_DISCONNECTING 21 /* 0x00200000 disconnect in progress */ + #define ABORTING_OR_DISCONNECTING ((1UL << US_FLIDX_ABORTING) | \ (1UL << US_FLIDX_DISCONNECTING)) -#define RTSX_FLIDX_RESETTING 22 /* 0x00400000 device reset - * in progress */ -#define RTSX_FLIDX_TIMED_OUT 23 /* 0x00800000 SCSI - * midlayer timed out */ + +#define RTSX_FLIDX_RESETTING 22 /* 0x00400000 device reset in progress */ +#define RTSX_FLIDX_TIMED_OUT 23 /* 0x00800000 SCSI midlayer timed out */ #define DRCT_ACCESS_DEV 0x00 /* Direct Access Device */ #define RMB_DISC 0x80 /* The Device is Removable */ @@ -173,9 +173,9 @@ #define FIRST_RESET 0x01 #define USED_EXIST 0x02 -/*----------------------------------- - SENSE_DATA ------------------------------------*/ +/* + * SENSE_DATA + */ /*---- valid ----*/ #define SENSE_VALID 0x80 /* Sense data is valid as SCSI2 */ #define SENSE_INVALID 0x00 /* Sense data is invalid as SCSI2 */ @@ -706,9 +706,9 @@ struct rtsx_chip { int cur_card; unsigned long need_release; /* need release bit map */ - unsigned long need_reset; /* need reset - * bit map */ - /* Flag to indicate that this card is just resumed from SS state, + unsigned long need_reset; /* need reset bit map */ + /* + * Flag to indicate that this card is just resumed from SS state, * and need released before being resetted */ unsigned long need_reinit; @@ -726,8 +726,10 @@ struct rtsx_chip { u8 card_ejected; /* card ejected bit map */ u8 card_wp; /* card write protected bit map */ - u8 lun_mc; /* flag to indicate whether to answer - * MediaChange */ + u8 lun_mc; /* + * flag to indicate whether to answer + * MediaChange + */ #ifndef LED_AUTO_BLINK int led_toggle_counter; -- cgit v0.10.2 From 55e94ccb43ec8b4c9db2c90303c75b87e23d7eed Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Fri, 23 Sep 2016 16:12:10 +0200 Subject: staging: rts5208: fix comment blocks style in rtsx.h This patch fixes the following checkpatch.pl warning in rtsx.h: WARNING: Block comments use a trailing */ on a separate line Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rts5208/rtsx.h b/drivers/staging/rts5208/rtsx.h index 2de4719..e725b10 100644 --- a/drivers/staging/rts5208/rtsx.h +++ b/drivers/staging/rts5208/rtsx.h @@ -161,8 +161,10 @@ static inline void get_current_time(u8 *timeval_buf, int buf_len) timeval_buf[7] = (u8)(tv_usec); } -/* The scsi_lock() and scsi_unlock() macros protect the sm_state and the - * single queue element srb for write access */ +/* + * The scsi_lock() and scsi_unlock() macros protect the sm_state and the + * single queue element srb for write access + */ #define scsi_unlock(host) spin_unlock_irq(host->host_lock) #define scsi_lock(host) spin_lock_irq(host->host_lock) -- cgit v0.10.2 From aeb92aef03d193b387be8a7b17d2afcadebbc21e Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Fri, 23 Sep 2016 16:12:11 +0200 Subject: staging: rts5208: remove not used typedef in rtsx_sys.h This patch fixes the following checkpatch.pl warning in rtsx_sys.h: WARNING: do not add new typedefs Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rts5208/rtsx_sys.h b/drivers/staging/rts5208/rtsx_sys.h index 0b6b4d4..f49bed9 100644 --- a/drivers/staging/rts5208/rtsx_sys.h +++ b/drivers/staging/rts5208/rtsx_sys.h @@ -28,8 +28,6 @@ #include "rtsx_chip.h" #include "rtsx_card.h" -typedef dma_addr_t ULONG_PTR; - static inline void rtsx_exclusive_enter_ss(struct rtsx_chip *chip) { struct rtsx_dev *dev = chip->rtsx; -- cgit v0.10.2 From 9afccdfe485a1df5e849dd4add91756f2ae2891d Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Fri, 23 Sep 2016 16:12:12 +0200 Subject: staging: rts5208: fix line style warnings in spi.c This patch fixes the following checkpatch.pl warning in spi.c: WARNING: line over 80 characters Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rts5208/spi.c b/drivers/staging/rts5208/spi.c index 26eb2a1..13c539c 100644 --- a/drivers/staging/rts5208/spi.c +++ b/drivers/staging/rts5208/spi.c @@ -39,7 +39,8 @@ static int spi_init(struct rtsx_chip *chip) int retval; retval = rtsx_write_register(chip, SPI_CONTROL, 0xFF, - CS_POLARITY_LOW | DTO_MSB_FIRST | SPI_MASTER | SPI_MODE0 | SPI_AUTO); + CS_POLARITY_LOW | DTO_MSB_FIRST + | SPI_MASTER | SPI_MODE0 | SPI_AUTO); if (retval) { rtsx_trace(chip); return retval; -- cgit v0.10.2 From e040b62683885caf9a376fd2582551cdbc213a3f Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Fri, 23 Sep 2016 16:12:13 +0200 Subject: staging: rts5208: fix style warnings in sd.c This patch fixes the following checkpatch.pl warning in sd.c: WARNING: else is not generally useful after a break or return It also makes code more uniform with the new changes Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rts5208/sd.c b/drivers/staging/rts5208/sd.c index e72c432..b0bbb36 100644 --- a/drivers/staging/rts5208/sd.c +++ b/drivers/staging/rts5208/sd.c @@ -2588,16 +2588,12 @@ Switch_Fail: #endif retval = sd_prepare_reset(chip); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; retval = sd_dummy_clock(chip); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip) && try_sdio) { int rty_cnt = 0; @@ -2605,8 +2601,7 @@ Switch_Fail: for (; rty_cnt < chip->sdio_retry_cnt; rty_cnt++) { if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { sd_set_err_code(chip, SD_NO_CARD); - rtsx_trace(chip); - return STATUS_FAIL; + goto Status_Fail; } retval = sd_send_cmd_get_rsp(chip, IO_SEND_OP_COND, 0, @@ -2618,8 +2613,7 @@ Switch_Fail: dev_dbg(rtsx_dev(chip), "SD_IO card (Function number: %d)!\n", func_num); chip->sd_io = 1; - rtsx_trace(chip); - return STATUS_FAIL; + goto Status_Fail; } break; @@ -2637,10 +2631,8 @@ Switch_Fail: RTY_SD_RST: retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0, NULL, 0); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; wait_timeout(20); @@ -2658,10 +2650,8 @@ RTY_SD_RST: retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0, NULL, 0); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; wait_timeout(20); } @@ -2672,39 +2662,32 @@ RTY_SD_RST: if (retval != STATUS_SUCCESS) { if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { sd_set_err_code(chip, SD_NO_CARD); - rtsx_trace(chip); - return STATUS_FAIL; + goto Status_Fail; } j++; - if (j < 3) { + if (j < 3) goto RTY_SD_RST; - } else { - rtsx_trace(chip); - return STATUS_FAIL; - } + else + goto Status_Fail; } retval = sd_send_cmd_get_rsp(chip, SD_APP_OP_COND, voltage, SD_RSP_TYPE_R3, rsp, 5); if (retval != STATUS_SUCCESS) { k++; - if (k < 3) { + if (k < 3) goto RTY_SD_RST; - } else { - rtsx_trace(chip); - return STATUS_FAIL; - } + else + goto Status_Fail; } i++; wait_timeout(20); } while (!(rsp[1] & 0x80) && (i < 255)); - if (i == 255) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (i == 255) + goto Status_Fail; if (hi_cap_flow) { if (rsp[1] & 0x40) @@ -2721,26 +2704,20 @@ RTY_SD_RST: if (support_1v8) { retval = sd_voltage_switch(chip); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; } retval = sd_send_cmd_get_rsp(chip, ALL_SEND_CID, 0, SD_RSP_TYPE_R2, NULL, 0); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; for (i = 0; i < 3; i++) { retval = sd_send_cmd_get_rsp(chip, SEND_RELATIVE_ADDR, 0, SD_RSP_TYPE_R6, rsp, 5); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; sd_card->sd_addr = (u32)rsp[1] << 24; sd_card->sd_addr += (u32)rsp[2] << 16; @@ -2750,24 +2727,18 @@ RTY_SD_RST: } retval = sd_check_csd(chip, 1); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; retval = sd_select_card(chip, 1); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; #ifdef SUPPORT_SD_LOCK SD_UNLOCK_ENTRY: retval = sd_update_lock_status(chip); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; if (sd_card->sd_lock_status & SD_LOCKED) { sd_card->sd_lock_status |= (SD_LOCK_1BIT_MODE | SD_PWD_EXIST); @@ -2779,32 +2750,24 @@ SD_UNLOCK_ENTRY: retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; retval = sd_send_cmd_get_rsp(chip, SET_CLR_CARD_DETECT, 0, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; if (support_1v8) { retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; retval = sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; switch_bus_width = SD_BUS_WIDTH_4; } else { @@ -2813,16 +2776,12 @@ SD_UNLOCK_ENTRY: retval = sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; if (!(sd_card->raw_csd[4] & 0x40)) sd_dont_switch = true; @@ -2861,17 +2820,13 @@ SD_UNLOCK_ENTRY: if (!support_1v8) { retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; retval = sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2, SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; } #ifdef SUPPORT_SD_LOCK @@ -2889,10 +2844,8 @@ SD_UNLOCK_ENTRY: } retval = sd_set_init_para(chip); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; if (CHK_SD_DDR50(sd_card)) retval = sd_ddr_tuning(chip); @@ -2901,14 +2854,11 @@ SD_UNLOCK_ENTRY: if (retval != STATUS_SUCCESS) { if (sd20_mode) { - rtsx_trace(chip); - return STATUS_FAIL; + goto Status_Fail; } else { retval = sd_init_power(chip); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; try_sdio = false; sd20_mode = true; @@ -2929,14 +2879,11 @@ SD_UNLOCK_ENTRY: retval = sd_read_lba0(chip); if (retval != STATUS_SUCCESS) { if (sd20_mode) { - rtsx_trace(chip); - return STATUS_FAIL; + goto Status_Fail; } else { retval = sd_init_power(chip); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; try_sdio = false; sd20_mode = true; @@ -2947,10 +2894,8 @@ SD_UNLOCK_ENTRY: } retval = sd_check_wp_state(chip); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; chip->card_bus_width[chip->card2lun[SD_CARD]] = 4; @@ -2972,6 +2917,10 @@ SD_UNLOCK_ENTRY: #endif return STATUS_SUCCESS; + +Status_Fail: + rtsx_trace(chip); + return STATUS_FAIL; } static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width) -- cgit v0.10.2 From e453eecbe696cfd73d1d6a04f0b4bf830877f5fa Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Fri, 23 Sep 2016 16:12:14 +0200 Subject: staging: rts5208: fix style warnings in xd.c This patch fixes the following checkpatch.pl warning in xd.c: WARNING: else is not generally useful after a break or return It also makes code more uniform with the new changes Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rts5208/xd.c b/drivers/staging/rts5208/xd.c index ff423fa..1de02bb 100644 --- a/drivers/staging/rts5208/xd.c +++ b/drivers/staging/rts5208/xd.c @@ -1622,10 +1622,8 @@ static int xd_read_multiple_pages(struct rtsx_chip *chip, u32 phy_blk, u8 reg_val, page_cnt; int zone_no, retval, i; - if (start_page > end_page) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (start_page > end_page) + goto Status_Fail; page_cnt = end_page - start_page; zone_no = (int)(log_blk / 1000); @@ -1641,8 +1639,7 @@ static int xd_read_multiple_pages(struct rtsx_chip *chip, u32 phy_blk, if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) { xd_set_err_code(chip, XD_NO_CARD); - rtsx_trace(chip); - return STATUS_FAIL; + goto Status_Fail; } } } @@ -1677,8 +1674,7 @@ static int xd_read_multiple_pages(struct rtsx_chip *chip, u32 phy_blk, if (retval == -ETIMEDOUT) { xd_set_err_code(chip, XD_TO_ERROR); - rtsx_trace(chip); - return STATUS_FAIL; + goto Status_Fail; } else { rtsx_trace(chip); goto Fail; @@ -1711,8 +1707,7 @@ Fail: if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) { xd_set_err_code(chip, XD_NO_CARD); - rtsx_trace(chip); - return STATUS_FAIL; + goto Status_Fail; } xd_set_err_code(chip, XD_ECC_ERROR); @@ -1720,8 +1715,7 @@ Fail: new_blk = xd_get_unused_block(chip, zone_no); if (new_blk == NO_NEW_BLK) { XD_CLR_BAD_OLDBLK(xd_card); - rtsx_trace(chip); - return STATUS_FAIL; + goto Status_Fail; } retval = xd_copy_page(chip, phy_blk, new_blk, 0, @@ -1735,8 +1729,7 @@ Fail: XD_CLR_BAD_NEWBLK(xd_card); } XD_CLR_BAD_OLDBLK(xd_card); - rtsx_trace(chip); - return STATUS_FAIL; + goto Status_Fail; } xd_set_l2p_tbl(chip, zone_no, log_off, (u16)(new_blk & 0x3FF)); xd_erase_block(chip, phy_blk); @@ -1744,6 +1737,7 @@ Fail: XD_CLR_BAD_OLDBLK(xd_card); } +Status_Fail: rtsx_trace(chip); return STATUS_FAIL; } @@ -1842,10 +1836,8 @@ static int xd_write_multiple_pages(struct rtsx_chip *chip, u32 old_blk, dev_dbg(rtsx_dev(chip), "%s, old_blk = 0x%x, new_blk = 0x%x, log_blk = 0x%x\n", __func__, old_blk, new_blk, log_blk); - if (start_page > end_page) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (start_page > end_page) + goto Status_Fail; page_cnt = end_page - start_page; zone_no = (int)(log_blk / 1000); @@ -1854,10 +1846,8 @@ static int xd_write_multiple_pages(struct rtsx_chip *chip, u32 old_blk, page_addr = (new_blk << xd_card->block_shift) + start_page; retval = xd_send_cmd(chip, READ1_1); - if (retval != STATUS_SUCCESS) { - rtsx_trace(chip); - return STATUS_FAIL; - } + if (retval != STATUS_SUCCESS) + goto Status_Fail; rtsx_init_cmd(chip); @@ -1892,8 +1882,7 @@ static int xd_write_multiple_pages(struct rtsx_chip *chip, u32 old_blk, if (retval == -ETIMEDOUT) { xd_set_err_code(chip, XD_TO_ERROR); - rtsx_trace(chip); - return STATUS_FAIL; + goto Status_Fail; } else { rtsx_trace(chip); goto Fail; @@ -1933,6 +1922,7 @@ Fail: xd_mark_bad_block(chip, new_blk); } +Status_Fail: rtsx_trace(chip); return STATUS_FAIL; } -- cgit v0.10.2 From a27e6e6d6512b96bfc4945a96d1bb730f1c5bea9 Mon Sep 17 00:00:00 2001 From: Georgiana Rodica Chelu <georgiana.chelu93@gmail.com> Date: Sat, 24 Sep 2016 23:35:20 +0300 Subject: staging: rtl8188eu: core: rtw_mlme: Remove return statement from void function Remove the return statement from the end of a void function to clean up the code. Issue found by checkpatch.pl script. Signed-off-by: Georgiana Rodica Chelu <georgiana.chelu93@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c index 249568c..ee2dcd0 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c @@ -259,7 +259,6 @@ void rtw_generate_random_ibss(u8 *pibss) pibss[3] = (u8)(curtime & 0xff);/* p[0]; */ pibss[4] = (u8)((curtime>>8) & 0xff);/* p[1]; */ pibss[5] = (u8)((curtime>>16) & 0xff);/* p[2]; */ - return; } u8 *rtw_get_capability_from_ie(u8 *ie) @@ -557,7 +556,6 @@ static int rtw_is_desired_network(struct adapter *adapter, struct wlan_network * void rtw_atimdone_event_callback(struct adapter *adapter, u8 *pbuf) { RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("receive atimdone_evet\n")); - return; } -- cgit v0.10.2 From b941f067ead3099eeeb3562d9de25664af3949f4 Mon Sep 17 00:00:00 2001 From: Georgiana Rodica Chelu <georgiana.chelu93@gmail.com> Date: Sat, 24 Sep 2016 23:35:53 +0300 Subject: staging: rtl8188eu: core: rtw_security: Remove return statement from void function Remove the return statement from the end of a void function to clean up the code. Issue found by checkpatch.pl script. Signed-off-by: Georgiana Rodica Chelu <georgiana.chelu93@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_security.c b/drivers/staging/rtl8188eu/core/rtw_security.c index 442a614..85bb441 100644 --- a/drivers/staging/rtl8188eu/core/rtw_security.c +++ b/drivers/staging/rtl8188eu/core/rtw_security.c @@ -233,7 +233,6 @@ void rtw_wep_decrypt(struct adapter *padapter, u8 *precvframe) &crc, &payload[length-4])); } } - return; } /* 3 ===== TKIP related ===== */ -- cgit v0.10.2 From c297d30756a427aa82b57f1fc0e6fb4343315ffd Mon Sep 17 00:00:00 2001 From: Imre Deak <imre.deak@gmail.com> Date: Sat, 24 Sep 2016 04:11:37 +0300 Subject: staging: lustre: ldlm: Fix extern variable declaration Move the extern declaration to a header file common to all users of the variable. This fixes the following sparse warning: symbol 'ldlm_cancel_unused_locks_before_replay' was not declared. Should it be static? Signed-off-by: Imre Deak <imre.deak@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h b/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h index 6536832..5e82cfc 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h @@ -103,6 +103,7 @@ int ldlm_cancel_lru_local(struct ldlm_namespace *ns, struct list_head *cancels, int count, int max, enum ldlm_cancel_flags cancel_flags, int flags); extern unsigned int ldlm_enqueue_min; +extern unsigned int ldlm_cancel_unused_locks_before_replay; /* ldlm_resource.c */ int ldlm_resource_putref_locked(struct ldlm_resource *res); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c index ff2c28e..fde697e 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c @@ -877,8 +877,6 @@ void ldlm_put_ref(void) } EXPORT_SYMBOL(ldlm_put_ref); -extern unsigned int ldlm_cancel_unused_locks_before_replay; - static ssize_t cancel_unused_locks_before_replay_show(struct kobject *kobj, struct attribute *attr, char *buf) -- cgit v0.10.2 From 8c52425a1303f0ad1f385a5e7335d0e75dd014fb Mon Sep 17 00:00:00 2001 From: Fernando Apesteguia <fernando.apesteguia@gmail.com> Date: Sun, 25 Sep 2016 19:20:31 +0200 Subject: staging: dgnc: Fix comment alignment As reported by checkpatch. Signed-off-by: Fernando Apesteguia <fernando.apesteguia@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_cls.c b/drivers/staging/dgnc/dgnc_cls.c index 4e1e0dc6..aedca66 100644 --- a/drivers/staging/dgnc/dgnc_cls.c +++ b/drivers/staging/dgnc/dgnc_cls.c @@ -345,7 +345,7 @@ static void cls_copy_data_from_uart_to_queue(struct channel_t *ch) /* * Discard character if we are ignoring the error mask. - */ + */ if (linestatus & error_mask) { linestatus = 0; readb(&ch->ch_cls_uart->txrx); -- cgit v0.10.2 From 3fd1e3fcb929e6b51598f76cfc0615259b8cfe54 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Sun, 25 Sep 2016 15:34:52 +0200 Subject: staging: wlan-ng: avoid new typedef: p80211pstrd_t This patch fixes the following checkpatch.pl warning in p80211types.h: WARNING: do not add new typedefs It applies for typedef p80211pstrd_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/p80211req.c b/drivers/staging/wlan-ng/p80211req.c index 010e5dc..61962d7 100644 --- a/drivers/staging/wlan-ng/p80211req.c +++ b/drivers/staging/wlan-ng/p80211req.c @@ -196,8 +196,8 @@ static void p80211req_mibset_mibget(struct wlandevice *wlandev, int isget) { p80211itemd_t *mibitem = (p80211itemd_t *)mib_msg->mibattribute.data; - p80211pstrd_t *pstr = (p80211pstrd_t *)mibitem->data; - u8 *key = mibitem->data + sizeof(p80211pstrd_t); + struct p80211pstrd *pstr = (struct p80211pstrd *)mibitem->data; + u8 *key = mibitem->data + sizeof(struct p80211pstrd); switch (mibitem->did) { case DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(1): diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h index b002ee8..0908510 100644 --- a/drivers/staging/wlan-ng/p80211types.h +++ b/drivers/staging/wlan-ng/p80211types.h @@ -219,10 +219,10 @@ struct p80211pstr { u8 len; } __packed; -typedef struct p80211pstrd { +struct p80211pstrd { u8 len; u8 data[0]; -} __packed p80211pstrd_t; +} __packed; /* Maximum pascal string */ typedef struct p80211pstr255 { diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c index f6f48d9..5e5d0ab 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.c +++ b/drivers/staging/wlan-ng/prism2mgmt.c @@ -531,7 +531,7 @@ int prism2mgmt_start(struct wlandevice *wlandev, void *msgp) hfa384x_t *hw = wlandev->priv; struct p80211msg_dot11req_start *msg = msgp; - p80211pstrd_t *pstr; + struct p80211pstrd *pstr; u8 bytebuf[80]; struct hfa384x_bytestr *p2bytestr = (struct hfa384x_bytestr *)bytebuf; u16 word; @@ -558,7 +558,7 @@ int prism2mgmt_start(struct wlandevice *wlandev, void *msgp) /*** STATION ***/ /* Set the REQUIRED config items */ /* SSID */ - pstr = (p80211pstrd_t *)&(msg->ssid.data); + pstr = (struct p80211pstrd *)&(msg->ssid.data); prism2mgmt_pstr2bytestr(p2bytestr, pstr); result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFOWNSSID, bytebuf, HFA384x_RID_CNFOWNSSID_LEN); @@ -1026,7 +1026,7 @@ int prism2mgmt_autojoin(struct wlandevice *wlandev, void *msgp) u16 reg; u16 port_type; struct p80211msg_lnxreq_autojoin *msg = msgp; - p80211pstrd_t *pstr; + struct p80211pstrd *pstr; u8 bytebuf[256]; struct hfa384x_bytestr *p2bytestr = (struct hfa384x_bytestr *)bytebuf; @@ -1052,7 +1052,7 @@ int prism2mgmt_autojoin(struct wlandevice *wlandev, void *msgp) /* Set the ssid */ memset(bytebuf, 0, 256); - pstr = (p80211pstrd_t *)&(msg->ssid.data); + pstr = (struct p80211pstrd *)&(msg->ssid.data); prism2mgmt_pstr2bytestr(p2bytestr, pstr); result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID, bytebuf, diff --git a/drivers/staging/wlan-ng/prism2mgmt.h b/drivers/staging/wlan-ng/prism2mgmt.h index 7ab19e9..5a4bc75 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.h +++ b/drivers/staging/wlan-ng/prism2mgmt.h @@ -87,18 +87,18 @@ int prism2mgmt_autojoin(struct wlandevice *wlandev, void *msgp); * Prism2 data types ---------------------------------------------------------------*/ /* byte area conversion functions*/ -void prism2mgmt_bytearea2pstr(u8 *bytearea, p80211pstrd_t *pstr, int len); +void prism2mgmt_bytearea2pstr(u8 *bytearea, struct p80211pstrd *pstr, int len); /* byte string conversion functions*/ void prism2mgmt_pstr2bytestr(struct hfa384x_bytestr *bytestr, - p80211pstrd_t *pstr); + struct p80211pstrd *pstr); void prism2mgmt_bytestr2pstr(struct hfa384x_bytestr *bytestr, - p80211pstrd_t *pstr); + struct p80211pstrd *pstr); /* functions to convert Group Addresses */ -void prism2mgmt_get_grpaddr(u32 did, p80211pstrd_t *pstr, hfa384x_t *priv); +void prism2mgmt_get_grpaddr(u32 did, struct p80211pstrd *pstr, hfa384x_t *priv); int prism2mgmt_set_grpaddr(u32 did, - u8 *prism2buf, p80211pstrd_t *pstr, + u8 *prism2buf, struct p80211pstrd *pstr, hfa384x_t *priv); int prism2mgmt_get_grpaddr_index(u32 did); diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c index ad1ae90..e022de4 100644 --- a/drivers/staging/wlan-ng/prism2mib.c +++ b/drivers/staging/wlan-ng/prism2mib.c @@ -379,7 +379,7 @@ static int prism2mib_bytearea2pstr(struct mibrec *mib, void *data) { int result; - p80211pstrd_t *pstr = data; + struct p80211pstrd *pstr = data; u8 bytebuf[MIB_TMP_MAXLEN]; if (isget) { @@ -533,7 +533,7 @@ static int prism2mib_wepdefaultkey(struct mibrec *mib, void *data) { int result; - p80211pstrd_t *pstr = data; + struct p80211pstrd *pstr = data; u8 bytebuf[MIB_TMP_MAXLEN]; u16 len; @@ -705,7 +705,7 @@ static int prism2mib_priv(struct mibrec *mib, hfa384x_t *hw, struct p80211msg_dot11req_mibset *msg, void *data) { - p80211pstrd_t *pstr = data; + struct p80211pstrd *pstr = data; switch (mib->did) { case DIDmib_lnx_lnxConfigTable_lnxRSNAIE:{ @@ -752,7 +752,7 @@ static int prism2mib_priv(struct mibrec *mib, */ void prism2mgmt_pstr2bytestr(struct hfa384x_bytestr *bytestr, - p80211pstrd_t *pstr) + struct p80211pstrd *pstr) { bytestr->len = cpu_to_le16((u16)(pstr->len)); memcpy(bytestr->data, pstr->data, pstr->len); @@ -774,7 +774,7 @@ void prism2mgmt_pstr2bytestr(struct hfa384x_bytestr *bytestr, */ void prism2mgmt_bytestr2pstr(struct hfa384x_bytestr *bytestr, - p80211pstrd_t *pstr) + struct p80211pstrd *pstr) { pstr->len = (u8)(le16_to_cpu((u16)(bytestr->len))); memcpy(pstr->data, bytestr->data, pstr->len); @@ -795,7 +795,7 @@ void prism2mgmt_bytestr2pstr(struct hfa384x_bytestr *bytestr, * */ -void prism2mgmt_bytearea2pstr(u8 *bytearea, p80211pstrd_t *pstr, int len) +void prism2mgmt_bytearea2pstr(u8 *bytearea, struct p80211pstrd *pstr, int len) { pstr->len = (u8)len; memcpy(pstr->data, bytearea, len); diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index b8009ae..1401df6 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -1256,7 +1256,7 @@ void prism2sta_processing_defer(struct work_struct *data) } prism2mgmt_bytestr2pstr( (struct hfa384x_bytestr *)&ssid, - (p80211pstrd_t *)&wlandev->ssid); + (struct p80211pstrd *)&wlandev->ssid); /* Collect the port status */ result = hfa384x_drvr_getconfig16(hw, @@ -1337,7 +1337,7 @@ void prism2sta_processing_defer(struct work_struct *data) return; } prism2mgmt_bytestr2pstr((struct hfa384x_bytestr *)&ssid, - (p80211pstrd_t *)&wlandev->ssid); + (struct p80211pstrd *)&wlandev->ssid); hw->link_status = HFA384x_LINK_CONNECTED; netif_carrier_on(wlandev->netdev); @@ -1993,7 +1993,7 @@ void prism2sta_commsqual_defer(struct work_struct *data) return; } prism2mgmt_bytestr2pstr((struct hfa384x_bytestr *)&ssid, - (p80211pstrd_t *)&wlandev->ssid); + (struct p80211pstrd *)&wlandev->ssid); /* Reschedule timer */ mod_timer(&hw->commsqual_timer, jiffies + HZ); -- cgit v0.10.2 From 94a29147beb0a777a62230cd4c5b1d3fb080ab29 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Sun, 25 Sep 2016 15:34:53 +0200 Subject: staging: wlan-ng: avoid new typedef: p80211pstr255_t This patch fixes the following checkpatch.pl warning in p80211types.h: WARNING: do not add new typedefs It applies for typedef p80211pstr255_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h index 0908510..edf44c3 100644 --- a/drivers/staging/wlan-ng/p80211types.h +++ b/drivers/staging/wlan-ng/p80211types.h @@ -225,10 +225,10 @@ struct p80211pstrd { } __packed; /* Maximum pascal string */ -typedef struct p80211pstr255 { +struct p80211pstr255 { u8 len; u8 data[MAXLEN_PSTR255]; -} __packed p80211pstr255_t; +} __packed; /* pascal string for macaddress and bssid */ typedef struct p80211pstr6 { @@ -306,7 +306,7 @@ typedef struct p80211item_pstr255 { u32 did; u16 status; u16 len; - p80211pstr255_t data; + struct p80211pstr255 data; } __packed p80211item_pstr255_t; /* message data item for UNK 392, namely mib items */ -- cgit v0.10.2 From 2816c008985fe2da20a40ca81d8d9232c9e7b035 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Sun, 25 Sep 2016 15:34:54 +0200 Subject: staging: wlan-ng: avoid new typedef: p80211pstr6_t This patch fixes the following checkpatch.pl warning in p80211types.h: WARNING: do not add new typedefs It applies for typedef p80211pstr6_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h index edf44c3..892e1b7 100644 --- a/drivers/staging/wlan-ng/p80211types.h +++ b/drivers/staging/wlan-ng/p80211types.h @@ -231,10 +231,10 @@ struct p80211pstr255 { } __packed; /* pascal string for macaddress and bssid */ -typedef struct p80211pstr6 { +struct p80211pstr6 { u8 len; u8 data[MAXLEN_PSTR6]; -} __packed p80211pstr6_t; +} __packed; /* pascal string for channel list */ typedef struct p80211pstr14 { @@ -282,7 +282,7 @@ typedef struct p80211item_pstr6 { u32 did; u16 status; u16 len; - p80211pstr6_t data; + struct p80211pstr6 data; } __packed p80211item_pstr6_t; /* message data item for OCTETSTR, DISPLAYSTR */ -- cgit v0.10.2 From 5d005584199bb481d052db946f6eb23d64222b25 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Sun, 25 Sep 2016 15:34:55 +0200 Subject: staging: wlan-ng: avoid new typedef: p80211pstr14_t This patch fixes the following checkpatch.pl warning in p80211types.h: WARNING: do not add new typedefs It applies for typedef p80211pstr14_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h index 892e1b7..b77f8f0 100644 --- a/drivers/staging/wlan-ng/p80211types.h +++ b/drivers/staging/wlan-ng/p80211types.h @@ -237,10 +237,10 @@ struct p80211pstr6 { } __packed; /* pascal string for channel list */ -typedef struct p80211pstr14 { +struct p80211pstr14 { u8 len; u8 data[MAXLEN_PSTR14]; -} __packed p80211pstr14_t; +} __packed; /* pascal string for ssid */ typedef struct p80211pstr32 { @@ -290,7 +290,7 @@ typedef struct p80211item_pstr14 { u32 did; u16 status; u16 len; - p80211pstr14_t data; + struct p80211pstr14 data; } __packed p80211item_pstr14_t; /* message data item for OCTETSTR, DISPLAYSTR */ -- cgit v0.10.2 From 758f140d473893bbfad9b9bbf6597ce93d55f415 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Sun, 25 Sep 2016 15:34:56 +0200 Subject: staging: wlan-ng: avoid new typedef: p80211pstr32_t This patch fixes the following checkpatch.pl warning in p80211types.h: WARNING: do not add new typedefs It applies for typedef p80211pstr32_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/p80211netdev.h b/drivers/staging/wlan-ng/p80211netdev.h index 138acdb..222f736 100644 --- a/drivers/staging/wlan-ng/p80211netdev.h +++ b/drivers/staging/wlan-ng/p80211netdev.h @@ -191,7 +191,7 @@ struct wlandevice { /* 802.11 State */ u8 bssid[WLAN_BSSID_LEN]; - p80211pstr32_t ssid; + struct p80211pstr32 ssid; u32 macmode; int linkstatus; diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h index b77f8f0..3d5e81b 100644 --- a/drivers/staging/wlan-ng/p80211types.h +++ b/drivers/staging/wlan-ng/p80211types.h @@ -243,10 +243,10 @@ struct p80211pstr14 { } __packed; /* pascal string for ssid */ -typedef struct p80211pstr32 { +struct p80211pstr32 { u8 len; u8 data[MAXLEN_PSTR32]; -} __packed p80211pstr32_t; +} __packed; /* MAC address array */ typedef struct p80211macarray { @@ -298,7 +298,7 @@ typedef struct p80211item_pstr32 { u32 did; u16 status; u16 len; - p80211pstr32_t data; + struct p80211pstr32 data; } __packed p80211item_pstr32_t; /* message data item for OCTETSTR, DISPLAYSTR */ -- cgit v0.10.2 From 46c226d77e9175daa85e7bb4a215724131069957 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Sun, 25 Sep 2016 15:34:57 +0200 Subject: staging: wlan-ng: avoid new typedef: p80211macarray_t This patch fixes the following checkpatch.pl warning in p80211types.h: WARNING: do not add new typedefs It applies for typedef p80211macarray_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h index 3d5e81b..b767049 100644 --- a/drivers/staging/wlan-ng/p80211types.h +++ b/drivers/staging/wlan-ng/p80211types.h @@ -249,10 +249,10 @@ struct p80211pstr32 { } __packed; /* MAC address array */ -typedef struct p80211macarray { +struct p80211macarray { u32 cnt; u8 data[1][MAXLEN_PSTR6]; -} __packed p80211macarray_t; +} __packed; /* prototype template */ typedef struct p80211item { -- cgit v0.10.2 From cf796937323dba7622409801a96fa09741523505 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Sun, 25 Sep 2016 15:34:58 +0200 Subject: staging: wlan-ng: avoid new typedef: p80211item_t This patch fixes the following checkpatch.pl warning in p80211types.h: WARNING: do not add new typedefs It applies for typedef p80211item_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h index b767049..6540044 100644 --- a/drivers/staging/wlan-ng/p80211types.h +++ b/drivers/staging/wlan-ng/p80211types.h @@ -255,11 +255,11 @@ struct p80211macarray { } __packed; /* prototype template */ -typedef struct p80211item { +struct p80211item { u32 did; u16 status; u16 len; -} __packed p80211item_t; +} __packed; /* prototype template w/ data item */ typedef struct p80211itemd { -- cgit v0.10.2 From ac033ec9f71a7107b64390fd9b52f799a22acedf Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Sun, 25 Sep 2016 15:34:59 +0200 Subject: staging: wlan-ng: avoid new typedef: p80211itemd_t This patch fixes the following checkpatch.pl warning in p80211types.h: WARNING: do not add new typedefs It applies for typedef p80211itemd_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/p80211req.c b/drivers/staging/wlan-ng/p80211req.c index 61962d7..d43e85b 100644 --- a/drivers/staging/wlan-ng/p80211req.c +++ b/drivers/staging/wlan-ng/p80211req.c @@ -195,7 +195,7 @@ static void p80211req_mibset_mibget(struct wlandevice *wlandev, struct p80211msg_dot11req_mibget *mib_msg, int isget) { - p80211itemd_t *mibitem = (p80211itemd_t *)mib_msg->mibattribute.data; + struct p80211itemd *mibitem = (struct p80211itemd *)mib_msg->mibattribute.data; struct p80211pstrd *pstr = (struct p80211pstrd *)mibitem->data; u8 *key = mibitem->data + sizeof(struct p80211pstrd); diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h index 6540044..57a65a8 100644 --- a/drivers/staging/wlan-ng/p80211types.h +++ b/drivers/staging/wlan-ng/p80211types.h @@ -262,12 +262,12 @@ struct p80211item { } __packed; /* prototype template w/ data item */ -typedef struct p80211itemd { +struct p80211itemd { u32 did; u16 status; u16 len; u8 data[0]; -} __packed p80211itemd_t; +} __packed; /* message data item for int, BOUNDEDINT, ENUMINT */ typedef struct p80211item_uint32 { diff --git a/drivers/staging/wlan-ng/prism2fw.c b/drivers/staging/wlan-ng/prism2fw.c index 870bad9..7c5d3e7 100644 --- a/drivers/staging/wlan-ng/prism2fw.c +++ b/drivers/staging/wlan-ng/prism2fw.c @@ -243,7 +243,7 @@ static int prism2_fwapply(const struct ihex_binrec *rfptr, { signed int result = 0; struct p80211msg_dot11req_mibget getmsg; - p80211itemd_t *item; + struct p80211itemd *item; u32 *data; /* Initialize the data structures */ @@ -293,7 +293,7 @@ static int prism2_fwapply(const struct ihex_binrec *rfptr, getmsg.resultcode.did = DIDmsg_dot11req_mibget_resultcode; getmsg.resultcode.status = P80211ENUM_msgitem_status_no_value; - item = (p80211itemd_t *)getmsg.mibattribute.data; + item = (struct p80211itemd *)getmsg.mibattribute.data; item->did = DIDmib_p2_p2NIC_p2PRISupRange; item->status = P80211ENUM_msgitem_status_no_value; diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c index e022de4..3442de3 100644 --- a/drivers/staging/wlan-ng/prism2mib.c +++ b/drivers/staging/wlan-ng/prism2mib.c @@ -266,7 +266,7 @@ int prism2mgmt_mibset_mibget(struct wlandevice *wlandev, void *msgp) u16 which; struct p80211msg_dot11req_mibset *msg = msgp; - p80211itemd_t *mibitem; + struct p80211itemd *mibitem; msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; msg->resultcode.data = P80211ENUM_resultcode_success; @@ -284,7 +284,7 @@ int prism2mgmt_mibset_mibget(struct wlandevice *wlandev, void *msgp) ** MIB table. */ - mibitem = (p80211itemd_t *)msg->mibattribute.data; + mibitem = (struct p80211itemd *)msg->mibattribute.data; for (mib = mibtab; mib->did != 0; mib++) if (mib->did == mibitem->did && (mib->flag & which)) -- cgit v0.10.2 From b26b232544601facdbf41e0e72f1a4ae1d2e8f00 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Sun, 25 Sep 2016 15:35:00 +0200 Subject: staging: wlan-ng: avoid new typedef: p80211item_uint32_t This patch fixes the following checkpatch.pl warning in p80211types.h: WARNING: do not add new typedefs It applies for typedef p80211item_uint32_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index f1d93b7..9f05c17 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -72,8 +72,8 @@ static int prism2_result2err(int prism2_result) static int prism2_domibset_uint32(struct wlandevice *wlandev, u32 did, u32 data) { struct p80211msg_dot11req_mibset msg; - p80211item_uint32_t *mibitem = - (p80211item_uint32_t *)&msg.mibattribute.data; + struct p80211item_uint32 *mibitem = + (struct p80211item_uint32 *)&msg.mibattribute.data; msg.msgcode = DIDmsg_dot11req_mibset; mibitem->did = did; @@ -626,11 +626,11 @@ static int prism2_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, struct prism2_wiphy_private *priv = wiphy_priv(wiphy); struct wlandevice *wlandev = priv->wlandev; struct p80211msg_dot11req_mibget msg; - p80211item_uint32_t *mibitem; + struct p80211item_uint32 *mibitem; int result; int err = 0; - mibitem = (p80211item_uint32_t *)&msg.mibattribute.data; + mibitem = (struct p80211item_uint32 *)&msg.mibattribute.data; msg.msgcode = DIDmsg_dot11req_mibget; mibitem->did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel; diff --git a/drivers/staging/wlan-ng/p80211metastruct.h b/drivers/staging/wlan-ng/p80211metastruct.h index c501162..c29988e 100644 --- a/drivers/staging/wlan-ng/p80211metastruct.h +++ b/drivers/staging/wlan-ng/p80211metastruct.h @@ -52,7 +52,7 @@ struct p80211msg_dot11req_mibget { u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; p80211item_unk392_t mibattribute; - p80211item_uint32_t resultcode; + struct p80211item_uint32 resultcode; } __packed; struct p80211msg_dot11req_mibset { @@ -60,76 +60,76 @@ struct p80211msg_dot11req_mibset { u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; p80211item_unk392_t mibattribute; - p80211item_uint32_t resultcode; + struct p80211item_uint32 resultcode; } __packed; struct p80211msg_dot11req_scan { u32 msgcode; u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_uint32_t bsstype; + struct p80211item_uint32 bsstype; p80211item_pstr6_t bssid; u8 pad_0C[1]; p80211item_pstr32_t ssid; u8 pad_1D[3]; - p80211item_uint32_t scantype; - p80211item_uint32_t probedelay; + struct p80211item_uint32 scantype; + struct p80211item_uint32 probedelay; p80211item_pstr14_t channellist; u8 pad_2C[1]; - p80211item_uint32_t minchanneltime; - p80211item_uint32_t maxchanneltime; - p80211item_uint32_t resultcode; - p80211item_uint32_t numbss; - p80211item_uint32_t append; + struct p80211item_uint32 minchanneltime; + struct p80211item_uint32 maxchanneltime; + struct p80211item_uint32 resultcode; + struct p80211item_uint32 numbss; + struct p80211item_uint32 append; } __packed; struct p80211msg_dot11req_scan_results { u32 msgcode; u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_uint32_t bssindex; - p80211item_uint32_t resultcode; - p80211item_uint32_t signal; - p80211item_uint32_t noise; + struct p80211item_uint32 bssindex; + struct p80211item_uint32 resultcode; + struct p80211item_uint32 signal; + struct p80211item_uint32 noise; p80211item_pstr6_t bssid; u8 pad_3C[1]; p80211item_pstr32_t ssid; u8 pad_4D[3]; - p80211item_uint32_t bsstype; - p80211item_uint32_t beaconperiod; - p80211item_uint32_t dtimperiod; - p80211item_uint32_t timestamp; - p80211item_uint32_t localtime; - p80211item_uint32_t fhdwelltime; - p80211item_uint32_t fhhopset; - p80211item_uint32_t fhhoppattern; - p80211item_uint32_t fhhopindex; - p80211item_uint32_t dschannel; - p80211item_uint32_t cfpcount; - p80211item_uint32_t cfpperiod; - p80211item_uint32_t cfpmaxduration; - p80211item_uint32_t cfpdurremaining; - p80211item_uint32_t ibssatimwindow; - p80211item_uint32_t cfpollable; - p80211item_uint32_t cfpollreq; - p80211item_uint32_t privacy; - p80211item_uint32_t capinfo; - p80211item_uint32_t basicrate1; - p80211item_uint32_t basicrate2; - p80211item_uint32_t basicrate3; - p80211item_uint32_t basicrate4; - p80211item_uint32_t basicrate5; - p80211item_uint32_t basicrate6; - p80211item_uint32_t basicrate7; - p80211item_uint32_t basicrate8; - p80211item_uint32_t supprate1; - p80211item_uint32_t supprate2; - p80211item_uint32_t supprate3; - p80211item_uint32_t supprate4; - p80211item_uint32_t supprate5; - p80211item_uint32_t supprate6; - p80211item_uint32_t supprate7; - p80211item_uint32_t supprate8; + struct p80211item_uint32 bsstype; + struct p80211item_uint32 beaconperiod; + struct p80211item_uint32 dtimperiod; + struct p80211item_uint32 timestamp; + struct p80211item_uint32 localtime; + struct p80211item_uint32 fhdwelltime; + struct p80211item_uint32 fhhopset; + struct p80211item_uint32 fhhoppattern; + struct p80211item_uint32 fhhopindex; + struct p80211item_uint32 dschannel; + struct p80211item_uint32 cfpcount; + struct p80211item_uint32 cfpperiod; + struct p80211item_uint32 cfpmaxduration; + struct p80211item_uint32 cfpdurremaining; + struct p80211item_uint32 ibssatimwindow; + struct p80211item_uint32 cfpollable; + struct p80211item_uint32 cfpollreq; + struct p80211item_uint32 privacy; + struct p80211item_uint32 capinfo; + struct p80211item_uint32 basicrate1; + struct p80211item_uint32 basicrate2; + struct p80211item_uint32 basicrate3; + struct p80211item_uint32 basicrate4; + struct p80211item_uint32 basicrate5; + struct p80211item_uint32 basicrate6; + struct p80211item_uint32 basicrate7; + struct p80211item_uint32 basicrate8; + struct p80211item_uint32 supprate1; + struct p80211item_uint32 supprate2; + struct p80211item_uint32 supprate3; + struct p80211item_uint32 supprate4; + struct p80211item_uint32 supprate5; + struct p80211item_uint32 supprate6; + struct p80211item_uint32 supprate7; + struct p80211item_uint32 supprate8; } __packed; struct p80211msg_dot11req_start { @@ -138,79 +138,79 @@ struct p80211msg_dot11req_start { u8 devname[WLAN_DEVNAMELEN_MAX]; p80211item_pstr32_t ssid; u8 pad_12D[3]; - p80211item_uint32_t bsstype; - p80211item_uint32_t beaconperiod; - p80211item_uint32_t dtimperiod; - p80211item_uint32_t cfpperiod; - p80211item_uint32_t cfpmaxduration; - p80211item_uint32_t fhdwelltime; - p80211item_uint32_t fhhopset; - p80211item_uint32_t fhhoppattern; - p80211item_uint32_t dschannel; - p80211item_uint32_t ibssatimwindow; - p80211item_uint32_t probedelay; - p80211item_uint32_t cfpollable; - p80211item_uint32_t cfpollreq; - p80211item_uint32_t basicrate1; - p80211item_uint32_t basicrate2; - p80211item_uint32_t basicrate3; - p80211item_uint32_t basicrate4; - p80211item_uint32_t basicrate5; - p80211item_uint32_t basicrate6; - p80211item_uint32_t basicrate7; - p80211item_uint32_t basicrate8; - p80211item_uint32_t operationalrate1; - p80211item_uint32_t operationalrate2; - p80211item_uint32_t operationalrate3; - p80211item_uint32_t operationalrate4; - p80211item_uint32_t operationalrate5; - p80211item_uint32_t operationalrate6; - p80211item_uint32_t operationalrate7; - p80211item_uint32_t operationalrate8; - p80211item_uint32_t resultcode; + struct p80211item_uint32 bsstype; + struct p80211item_uint32 beaconperiod; + struct p80211item_uint32 dtimperiod; + struct p80211item_uint32 cfpperiod; + struct p80211item_uint32 cfpmaxduration; + struct p80211item_uint32 fhdwelltime; + struct p80211item_uint32 fhhopset; + struct p80211item_uint32 fhhoppattern; + struct p80211item_uint32 dschannel; + struct p80211item_uint32 ibssatimwindow; + struct p80211item_uint32 probedelay; + struct p80211item_uint32 cfpollable; + struct p80211item_uint32 cfpollreq; + struct p80211item_uint32 basicrate1; + struct p80211item_uint32 basicrate2; + struct p80211item_uint32 basicrate3; + struct p80211item_uint32 basicrate4; + struct p80211item_uint32 basicrate5; + struct p80211item_uint32 basicrate6; + struct p80211item_uint32 basicrate7; + struct p80211item_uint32 basicrate8; + struct p80211item_uint32 operationalrate1; + struct p80211item_uint32 operationalrate2; + struct p80211item_uint32 operationalrate3; + struct p80211item_uint32 operationalrate4; + struct p80211item_uint32 operationalrate5; + struct p80211item_uint32 operationalrate6; + struct p80211item_uint32 operationalrate7; + struct p80211item_uint32 operationalrate8; + struct p80211item_uint32 resultcode; } __packed; struct p80211msg_lnxreq_ifstate { u32 msgcode; u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_uint32_t ifstate; - p80211item_uint32_t resultcode; + struct p80211item_uint32 ifstate; + struct p80211item_uint32 resultcode; } __packed; struct p80211msg_lnxreq_wlansniff { u32 msgcode; u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_uint32_t enable; - p80211item_uint32_t channel; - p80211item_uint32_t prismheader; - p80211item_uint32_t wlanheader; - p80211item_uint32_t keepwepflags; - p80211item_uint32_t stripfcs; - p80211item_uint32_t packet_trunc; - p80211item_uint32_t resultcode; + struct p80211item_uint32 enable; + struct p80211item_uint32 channel; + struct p80211item_uint32 prismheader; + struct p80211item_uint32 wlanheader; + struct p80211item_uint32 keepwepflags; + struct p80211item_uint32 stripfcs; + struct p80211item_uint32 packet_trunc; + struct p80211item_uint32 resultcode; } __packed; struct p80211msg_lnxreq_hostwep { u32 msgcode; u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_uint32_t resultcode; - p80211item_uint32_t decrypt; - p80211item_uint32_t encrypt; + struct p80211item_uint32 resultcode; + struct p80211item_uint32 decrypt; + struct p80211item_uint32 encrypt; } __packed; struct p80211msg_lnxreq_commsquality { u32 msgcode; u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_uint32_t resultcode; - p80211item_uint32_t dbm; - p80211item_uint32_t link; - p80211item_uint32_t level; - p80211item_uint32_t noise; - p80211item_uint32_t txrate; + struct p80211item_uint32 resultcode; + struct p80211item_uint32 dbm; + struct p80211item_uint32 link; + struct p80211item_uint32 level; + struct p80211item_uint32 noise; + struct p80211item_uint32 txrate; } __packed; struct p80211msg_lnxreq_autojoin { @@ -219,8 +219,8 @@ struct p80211msg_lnxreq_autojoin { u8 devname[WLAN_DEVNAMELEN_MAX]; p80211item_pstr32_t ssid; u8 pad_19D[3]; - p80211item_uint32_t authtype; - p80211item_uint32_t resultcode; + struct p80211item_uint32 authtype; + struct p80211item_uint32 resultcode; } __packed; struct p80211msg_p2req_readpda { @@ -228,44 +228,44 @@ struct p80211msg_p2req_readpda { u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; p80211item_unk1024_t pda; - p80211item_uint32_t resultcode; + struct p80211item_uint32 resultcode; } __packed; struct p80211msg_p2req_ramdl_state { u32 msgcode; u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_uint32_t enable; - p80211item_uint32_t exeaddr; - p80211item_uint32_t resultcode; + struct p80211item_uint32 enable; + struct p80211item_uint32 exeaddr; + struct p80211item_uint32 resultcode; } __packed; struct p80211msg_p2req_ramdl_write { u32 msgcode; u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_uint32_t addr; - p80211item_uint32_t len; + struct p80211item_uint32 addr; + struct p80211item_uint32 len; p80211item_unk4096_t data; - p80211item_uint32_t resultcode; + struct p80211item_uint32 resultcode; } __packed; struct p80211msg_p2req_flashdl_state { u32 msgcode; u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_uint32_t enable; - p80211item_uint32_t resultcode; + struct p80211item_uint32 enable; + struct p80211item_uint32 resultcode; } __packed; struct p80211msg_p2req_flashdl_write { u32 msgcode; u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_uint32_t addr; - p80211item_uint32_t len; + struct p80211item_uint32 addr; + struct p80211item_uint32 len; p80211item_unk4096_t data; - p80211item_uint32_t resultcode; + struct p80211item_uint32 resultcode; } __packed; #endif diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c index 38c936a..5244bd8 100644 --- a/drivers/staging/wlan-ng/p80211netdev.c +++ b/drivers/staging/wlan-ng/p80211netdev.c @@ -616,7 +616,7 @@ static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr) struct p80211msg_dot11req_mibset dot11req; p80211item_unk392_t *mibattr; p80211item_pstr6_t *macaddr; - p80211item_uint32_t *resultcode; + struct p80211item_uint32 *resultcode; int result; /* If we're running, we don't allow MAC address changes */ diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h index 57a65a8..13962ec 100644 --- a/drivers/staging/wlan-ng/p80211types.h +++ b/drivers/staging/wlan-ng/p80211types.h @@ -270,12 +270,12 @@ struct p80211itemd { } __packed; /* message data item for int, BOUNDEDINT, ENUMINT */ -typedef struct p80211item_uint32 { +struct p80211item_uint32 { u32 did; u16 status; u16 len; u32 data; -} __packed p80211item_uint32_t; +} __packed; /* message data item for OCTETSTR, DISPLAYSTR */ typedef struct p80211item_pstr6 { diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index 1401df6..a39b294 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -1916,7 +1916,7 @@ void prism2sta_commsqual_defer(struct work_struct *data) struct wlandevice *wlandev = hw->wlandev; hfa384x_bytestr32_t ssid; struct p80211msg_dot11req_mibget msg; - p80211item_uint32_t *mibitem = (p80211item_uint32_t *) + struct p80211item_uint32 *mibitem = (struct p80211item_uint32 *) &msg.mibattribute.data; int result = 0; -- cgit v0.10.2 From 34aae059939daf5f9298241d3981b9f421ff3dd1 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Sun, 25 Sep 2016 15:35:01 +0200 Subject: staging: wlan-ng: avoid new typedef: p80211item_pstr6_t This patch fixes the following checkpatch.pl warning in p80211types.h: WARNING: do not add new typedefs It applies for typedef p80211item_pstr6_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/p80211metastruct.h b/drivers/staging/wlan-ng/p80211metastruct.h index c29988e..97ef2ef 100644 --- a/drivers/staging/wlan-ng/p80211metastruct.h +++ b/drivers/staging/wlan-ng/p80211metastruct.h @@ -68,7 +68,7 @@ struct p80211msg_dot11req_scan { u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; struct p80211item_uint32 bsstype; - p80211item_pstr6_t bssid; + struct p80211item_pstr6 bssid; u8 pad_0C[1]; p80211item_pstr32_t ssid; u8 pad_1D[3]; @@ -91,7 +91,7 @@ struct p80211msg_dot11req_scan_results { struct p80211item_uint32 resultcode; struct p80211item_uint32 signal; struct p80211item_uint32 noise; - p80211item_pstr6_t bssid; + struct p80211item_pstr6 bssid; u8 pad_3C[1]; p80211item_pstr32_t ssid; u8 pad_4D[3]; diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c index 5244bd8..d71bd7e 100644 --- a/drivers/staging/wlan-ng/p80211netdev.c +++ b/drivers/staging/wlan-ng/p80211netdev.c @@ -615,7 +615,7 @@ static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr) struct sockaddr *new_addr = addr; struct p80211msg_dot11req_mibset dot11req; p80211item_unk392_t *mibattr; - p80211item_pstr6_t *macaddr; + struct p80211item_pstr6 *macaddr; struct p80211item_uint32 *resultcode; int result; @@ -625,7 +625,7 @@ static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr) /* Set up some convenience pointers. */ mibattr = &dot11req.mibattribute; - macaddr = (p80211item_pstr6_t *)&mibattr->data; + macaddr = (struct p80211item_pstr6 *)&mibattr->data; resultcode = &dot11req.resultcode; /* Set up a dot11req_mibset */ diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h index 13962ec..9a09cce 100644 --- a/drivers/staging/wlan-ng/p80211types.h +++ b/drivers/staging/wlan-ng/p80211types.h @@ -278,12 +278,12 @@ struct p80211item_uint32 { } __packed; /* message data item for OCTETSTR, DISPLAYSTR */ -typedef struct p80211item_pstr6 { +struct p80211item_pstr6 { u32 did; u16 status; u16 len; struct p80211pstr6 data; -} __packed p80211item_pstr6_t; +} __packed; /* message data item for OCTETSTR, DISPLAYSTR */ typedef struct p80211item_pstr14 { -- cgit v0.10.2 From f055b21142f613b363fa8bece91cdb6ca326677d Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Sun, 25 Sep 2016 15:35:02 +0200 Subject: staging: wlan-ng: avoid new typedef: p80211item_pstr14_t This patch fixes the following checkpatch.pl warning in p80211types.h: WARNING: do not add new typedefs It applies for typedef p80211item_pstr14_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/p80211metastruct.h b/drivers/staging/wlan-ng/p80211metastruct.h index 97ef2ef..c9d4bb5 100644 --- a/drivers/staging/wlan-ng/p80211metastruct.h +++ b/drivers/staging/wlan-ng/p80211metastruct.h @@ -74,7 +74,7 @@ struct p80211msg_dot11req_scan { u8 pad_1D[3]; struct p80211item_uint32 scantype; struct p80211item_uint32 probedelay; - p80211item_pstr14_t channellist; + struct p80211item_pstr14 channellist; u8 pad_2C[1]; struct p80211item_uint32 minchanneltime; struct p80211item_uint32 maxchanneltime; diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h index 9a09cce..4d70d84 100644 --- a/drivers/staging/wlan-ng/p80211types.h +++ b/drivers/staging/wlan-ng/p80211types.h @@ -286,12 +286,12 @@ struct p80211item_pstr6 { } __packed; /* message data item for OCTETSTR, DISPLAYSTR */ -typedef struct p80211item_pstr14 { +struct p80211item_pstr14 { u32 did; u16 status; u16 len; struct p80211pstr14 data; -} __packed p80211item_pstr14_t; +} __packed; /* message data item for OCTETSTR, DISPLAYSTR */ typedef struct p80211item_pstr32 { -- cgit v0.10.2 From 6a50b5afac396a708fa2cf18dd806603e90aad76 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Sun, 25 Sep 2016 15:35:03 +0200 Subject: staging: wlan-ng: avoid new typedef: p80211item_pstr32_t This patch fixes the following checkpatch.pl warning in p80211types.h: WARNING: do not add new typedefs It applies for typedef p80211item_pstr32_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index 9f05c17..182b2d5 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -86,8 +86,8 @@ static int prism2_domibset_pstr32(struct wlandevice *wlandev, u32 did, u8 len, const u8 *data) { struct p80211msg_dot11req_mibset msg; - p80211item_pstr32_t *mibitem = - (p80211item_pstr32_t *)&msg.mibattribute.data; + struct p80211item_pstr32 *mibitem = + (struct p80211item_pstr32 *)&msg.mibattribute.data; msg.msgcode = DIDmsg_dot11req_mibset; mibitem->did = did; diff --git a/drivers/staging/wlan-ng/p80211metastruct.h b/drivers/staging/wlan-ng/p80211metastruct.h index c9d4bb5..c66fc5a 100644 --- a/drivers/staging/wlan-ng/p80211metastruct.h +++ b/drivers/staging/wlan-ng/p80211metastruct.h @@ -70,7 +70,7 @@ struct p80211msg_dot11req_scan { struct p80211item_uint32 bsstype; struct p80211item_pstr6 bssid; u8 pad_0C[1]; - p80211item_pstr32_t ssid; + struct p80211item_pstr32 ssid; u8 pad_1D[3]; struct p80211item_uint32 scantype; struct p80211item_uint32 probedelay; @@ -93,7 +93,7 @@ struct p80211msg_dot11req_scan_results { struct p80211item_uint32 noise; struct p80211item_pstr6 bssid; u8 pad_3C[1]; - p80211item_pstr32_t ssid; + struct p80211item_pstr32 ssid; u8 pad_4D[3]; struct p80211item_uint32 bsstype; struct p80211item_uint32 beaconperiod; @@ -136,7 +136,7 @@ struct p80211msg_dot11req_start { u32 msgcode; u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_pstr32_t ssid; + struct p80211item_pstr32 ssid; u8 pad_12D[3]; struct p80211item_uint32 bsstype; struct p80211item_uint32 beaconperiod; @@ -217,7 +217,7 @@ struct p80211msg_lnxreq_autojoin { u32 msgcode; u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_pstr32_t ssid; + struct p80211item_pstr32 ssid; u8 pad_19D[3]; struct p80211item_uint32 authtype; struct p80211item_uint32 resultcode; diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h index 4d70d84..6c87729 100644 --- a/drivers/staging/wlan-ng/p80211types.h +++ b/drivers/staging/wlan-ng/p80211types.h @@ -294,12 +294,12 @@ struct p80211item_pstr14 { } __packed; /* message data item for OCTETSTR, DISPLAYSTR */ -typedef struct p80211item_pstr32 { +struct p80211item_pstr32 { u32 did; u16 status; u16 len; struct p80211pstr32 data; -} __packed p80211item_pstr32_t; +} __packed; /* message data item for OCTETSTR, DISPLAYSTR */ typedef struct p80211item_pstr255 { -- cgit v0.10.2 From 3636ab01fd8e846892844dcf6170244b1d6ace0b Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Sun, 25 Sep 2016 15:35:04 +0200 Subject: staging: wlan-ng: avoid new typedef: p80211item_pstr255_t This patch fixes the following checkpatch.pl warning in p80211types.h: WARNING: do not add new typedefs It applies for typedef p80211item_pstr255_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h index 6c87729..dd56815 100644 --- a/drivers/staging/wlan-ng/p80211types.h +++ b/drivers/staging/wlan-ng/p80211types.h @@ -302,12 +302,12 @@ struct p80211item_pstr32 { } __packed; /* message data item for OCTETSTR, DISPLAYSTR */ -typedef struct p80211item_pstr255 { +struct p80211item_pstr255 { u32 did; u16 status; u16 len; struct p80211pstr255 data; -} __packed p80211item_pstr255_t; +} __packed; /* message data item for UNK 392, namely mib items */ typedef struct p80211item_unk392 { -- cgit v0.10.2 From 37e48668cee8b32aea70a8a4e6c36725aaa52d5e Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Sun, 25 Sep 2016 15:35:05 +0200 Subject: staging: wlan-ng: avoid new typedef: p80211item_unk392_t This patch fixes the following checkpatch.pl warning in p80211types.h: WARNING: do not add new typedefs It applies for typedef p80211item_unk392_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/p80211metastruct.h b/drivers/staging/wlan-ng/p80211metastruct.h index c66fc5a..23fd385 100644 --- a/drivers/staging/wlan-ng/p80211metastruct.h +++ b/drivers/staging/wlan-ng/p80211metastruct.h @@ -51,7 +51,7 @@ struct p80211msg_dot11req_mibget { u32 msgcode; u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_unk392_t mibattribute; + struct p80211item_unk392 mibattribute; struct p80211item_uint32 resultcode; } __packed; @@ -59,7 +59,7 @@ struct p80211msg_dot11req_mibset { u32 msgcode; u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_unk392_t mibattribute; + struct p80211item_unk392 mibattribute; struct p80211item_uint32 resultcode; } __packed; diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c index d71bd7e..0a31467 100644 --- a/drivers/staging/wlan-ng/p80211netdev.c +++ b/drivers/staging/wlan-ng/p80211netdev.c @@ -614,7 +614,7 @@ static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr) { struct sockaddr *new_addr = addr; struct p80211msg_dot11req_mibset dot11req; - p80211item_unk392_t *mibattr; + struct p80211item_unk392 *mibattr; struct p80211item_pstr6 *macaddr; struct p80211item_uint32 *resultcode; int result; diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h index dd56815..8aefd0a 100644 --- a/drivers/staging/wlan-ng/p80211types.h +++ b/drivers/staging/wlan-ng/p80211types.h @@ -310,12 +310,12 @@ struct p80211item_pstr255 { } __packed; /* message data item for UNK 392, namely mib items */ -typedef struct p80211item_unk392 { +struct p80211item_unk392 { u32 did; u16 status; u16 len; u8 data[MAXLEN_MIBATTRIBUTE]; -} __packed p80211item_unk392_t; +} __packed; /* message data item for UNK 1025, namely p2 pdas */ typedef struct p80211item_unk1024 { -- cgit v0.10.2 From 1ad26f70e43518144ad760a97b7323cc85fe17fa Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Sun, 25 Sep 2016 15:35:06 +0200 Subject: staging: wlan-ng: avoid new typedef: p80211item_unk1024_t This patch fixes the following checkpatch.pl warning in p80211types.h: WARNING: do not add new typedefs It applies for typedef p80211item_unk1024_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/p80211metastruct.h b/drivers/staging/wlan-ng/p80211metastruct.h index 23fd385..0b18c19 100644 --- a/drivers/staging/wlan-ng/p80211metastruct.h +++ b/drivers/staging/wlan-ng/p80211metastruct.h @@ -227,7 +227,7 @@ struct p80211msg_p2req_readpda { u32 msgcode; u32 msglen; u8 devname[WLAN_DEVNAMELEN_MAX]; - p80211item_unk1024_t pda; + struct p80211item_unk1024 pda; struct p80211item_uint32 resultcode; } __packed; diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h index 8aefd0a..921b376 100644 --- a/drivers/staging/wlan-ng/p80211types.h +++ b/drivers/staging/wlan-ng/p80211types.h @@ -318,12 +318,12 @@ struct p80211item_unk392 { } __packed; /* message data item for UNK 1025, namely p2 pdas */ -typedef struct p80211item_unk1024 { +struct p80211item_unk1024 { u32 did; u16 status; u16 len; u8 data[1024]; -} __packed p80211item_unk1024_t; +} __packed; /* message data item for UNK 4096, namely p2 download chunks */ typedef struct p80211item_unk4096 { -- cgit v0.10.2 From f8b8f64f4140333f2f6766f2a88fa7f902d5ef9d Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Sun, 25 Sep 2016 15:35:07 +0200 Subject: staging: wlan-ng: avoid new typedef: p80211item_unk4096_t This patch fixes the following checkpatch.pl warning in p80211types.h: WARNING: do not add new typedefs It applies for typedef p80211item_unk4096_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/p80211metastruct.h b/drivers/staging/wlan-ng/p80211metastruct.h index 0b18c19..850d897 100644 --- a/drivers/staging/wlan-ng/p80211metastruct.h +++ b/drivers/staging/wlan-ng/p80211metastruct.h @@ -246,7 +246,7 @@ struct p80211msg_p2req_ramdl_write { u8 devname[WLAN_DEVNAMELEN_MAX]; struct p80211item_uint32 addr; struct p80211item_uint32 len; - p80211item_unk4096_t data; + struct p80211item_unk4096 data; struct p80211item_uint32 resultcode; } __packed; @@ -264,7 +264,7 @@ struct p80211msg_p2req_flashdl_write { u8 devname[WLAN_DEVNAMELEN_MAX]; struct p80211item_uint32 addr; struct p80211item_uint32 len; - p80211item_unk4096_t data; + struct p80211item_unk4096 data; struct p80211item_uint32 resultcode; } __packed; diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h index 921b376..8fc733f 100644 --- a/drivers/staging/wlan-ng/p80211types.h +++ b/drivers/staging/wlan-ng/p80211types.h @@ -326,12 +326,12 @@ struct p80211item_unk1024 { } __packed; /* message data item for UNK 4096, namely p2 download chunks */ -typedef struct p80211item_unk4096 { +struct p80211item_unk4096 { u32 did; u16 status; u16 len; u8 data[4096]; -} __packed p80211item_unk4096_t; +} __packed; struct catlistitem; -- cgit v0.10.2 From 0ae952e3bd1c761d4952c8ff1a259292e4f03e89 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Sun, 25 Sep 2016 15:35:08 +0200 Subject: staging: wlan-ng: fix block comments style errors This patch fixes the following checkpatch.pl warning in p80211types.h: WARNING: Block comments should align the * on each line Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h index 8fc733f..263ef2d 100644 --- a/drivers/staging/wlan-ng/p80211types.h +++ b/drivers/staging/wlan-ng/p80211types.h @@ -1,58 +1,59 @@ -/* p80211types.h -* -* Macros, constants, types, and funcs for p80211 data types -* -* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. -* -------------------------------------------------------------------- -* -* linux-wlan -* -* The contents of this file are subject to the Mozilla Public -* License Version 1.1 (the "License"); you may not use this file -* except in compliance with the License. You may obtain a copy of -* the License at http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS -* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -* implied. See the License for the specific language governing -* rights and limitations under the License. -* -* Alternatively, the contents of this file may be used under the -* terms of the GNU Public License version 2 (the "GPL"), in which -* case the provisions of the GPL are applicable instead of the -* above. If you wish to allow the use of your version of this file -* only under the terms of the GPL and not to allow others to use -* your version of this file under the MPL, indicate your decision -* by deleting the provisions above and replace them with the notice -* and other provisions required by the GPL. If you do not delete -* the provisions above, a recipient may use your version of this -* file under either the MPL or the GPL. -* -* -------------------------------------------------------------------- -* -* Inquiries regarding the linux-wlan Open Source project can be -* made directly to: -* -* AbsoluteValue Systems Inc. -* info@linux-wlan.com -* http://www.linux-wlan.com -* -* -------------------------------------------------------------------- -* -* Portions of the development of this software were funded by -* Intersil Corporation as part of PRISM(R) chipset product development. -* -* -------------------------------------------------------------------- -* -* This file declares some of the constants and types used in various -* parts of the linux-wlan system. -* -* Notes: -* - Constant values are always in HOST byte order. -* -* All functions and statics declared here are implemented in p80211types.c -* -------------------------------------------------------------------- -*/ +/* + * p80211types.h + * + * Macros, constants, types, and funcs for p80211 data types + * + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. + * -------------------------------------------------------------------- + * + * linux-wlan + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU Public License version 2 (the "GPL"), in which + * case the provisions of the GPL are applicable instead of the + * above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use + * your version of this file under the MPL, indicate your decision + * by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete + * the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * -------------------------------------------------------------------- + * + * Inquiries regarding the linux-wlan Open Source project can be + * made directly to: + * + * AbsoluteValue Systems Inc. + * info@linux-wlan.com + * http://www.linux-wlan.com + * + * -------------------------------------------------------------------- + * + * Portions of the development of this software were funded by + * Intersil Corporation as part of PRISM(R) chipset product development. + * + * -------------------------------------------------------------------- + * + * This file declares some of the constants and types used in various + * parts of the linux-wlan system. + * + * Notes: + * - Constant values are always in HOST byte order. + * + * All functions and statics declared here are implemented in p80211types.c + * -------------------------------------------------------------------- + */ #ifndef _P80211TYPES_H #define _P80211TYPES_H @@ -123,18 +124,18 @@ #define MKENUMNAME(name) p80211enum_ ## name /*---------------------------------------------------------------- -* The following constants and macros are used to construct and -* deconstruct the Data ID codes. The coding is as follows: -* -* ...rwtnnnnnnnniiiiiiggggggssssss s - Section -* g - Group -* i - Item -* n - Index -* t - Table flag -* w - Write flag -* r - Read flag -* . - Unused -*/ + * The following constants and macros are used to construct and + * deconstruct the Data ID codes. The coding is as follows: + * + * ...rwtnnnnnnnniiiiiiggggggssssss s - Section + * g - Group + * i - Item + * n - Index + * t - Table flag + * w - Write flag + * r - Read flag + * . - Unused + */ #define P80211DID_LSB_SECTION (0) #define P80211DID_LSB_GROUP (6) -- cgit v0.10.2 From 1140c8a61a3252f2ee6a461159102b964613f1a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Salazar?= <glbsalazar@gmail.com> Date: Mon, 26 Sep 2016 20:42:58 +0100 Subject: staging: rtl8172: usb_intf.c: Fixed block comment coding style MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed a block comment indentation in the rtl8712 usb_intf.c file. Signed-off-by: Gonçalo Salazar <glbsalazar@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c index 3fc65b2..897d462 100644 --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c @@ -369,7 +369,7 @@ static const struct device_type wlan_type = { * * notes: drv_init() is called when the bus driver has located a card for us * to support. We accept the new device by returning 0. -*/ + */ static int r871xu_drv_init(struct usb_interface *pusb_intf, const struct usb_device_id *pdid) { -- cgit v0.10.2 From dc258c15ea121414277156511c8cca944443201e Mon Sep 17 00:00:00 2001 From: "Darryl T. Agostinelli" <dagostinelli@gmail.com> Date: Mon, 26 Sep 2016 07:08:14 -0500 Subject: staging: rtl8192e: fixed block comments should align the * on each line shifted over comment block one space Signed-off-by: Darryl T. Agostinelli <dagostinelli@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_hwimg.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_hwimg.c index 29cefb5..d437a8e 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_hwimg.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_hwimg.c @@ -11,7 +11,7 @@ * * Contact Information: * wlanfae <wlanfae@realtek.com> -******************************************************************************/ + *****************************************************************************/ /*Created on 2008/11/18, 3: 7*/ #include "r8192E_hwimg.h" -- cgit v0.10.2 From 7224a2a50a29871b2ae04cac731ea199adedbe68 Mon Sep 17 00:00:00 2001 From: Vaibhav Agarwal <vaibhav.sr@gmail.com> Date: Sat, 24 Sep 2016 23:06:26 +0530 Subject: greybus: audio: fix uninitialized variable errors found by cppcheck Currently, if info is null, the dev_err message is dereferencing an uninitialized module pointer. Instead, it should use codec->dev pointer in dev_err call and better align with other err msg in this function. Also, ret variable might be used uninitialized in a specific case. Avoid using it this way. Found using static analysis with cppcheck: Checking drivers/staging/greybus/audio_topology.c... [drivers/staging/greybus/audio_topology.c:175]: (error) Uninitialized variable: module [drivers/staging/greybus/audio_topology.c:495]: (error) Uninitialized variable: ret Reported-by: Colin Ian King <colin.king@canonical.com> Signed-off-by: Vaibhav Agarwal <vaibhav.sr@gmail.com> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index f9f3381..b625169 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -172,7 +172,7 @@ static int gbcodec_mixer_ctl_info(struct snd_kcontrol *kcontrol, info = (struct gb_audio_ctl_elem_info *)data->info; if (!info) { - dev_err(module->dev, "NULL info for %s\n", uinfo->id.name); + dev_err(codec->dev, "NULL info for %s\n", uinfo->id.name); return -EINVAL; } @@ -489,10 +489,11 @@ static int gbcodec_mixer_dapm_ctl_put(struct snd_kcontrol *kcontrol, dev_err_ratelimited(codec->dev, "%d:Error in %s for %s\n", ret, __func__, kcontrol->id.name); + return ret; } } - return ret; + return 0; } #define SOC_DAPM_MIXER_GB(xname, kcount, data) \ -- cgit v0.10.2 From 3d7f3588553a9ee392aa1abb5a3e8fd4b1ba8f5e Mon Sep 17 00:00:00 2001 From: Chase Metzger <chasemetzger15@gmail.com> Date: Sun, 25 Sep 2016 13:35:47 -0700 Subject: drivers/staging/greybus: gpio.c - Fixed a checkpatch generated warning Removed braces for single line if statement. Signed-off-by: Chase Metzger <chasemetzger15@gmail.com> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index ea8234a..5e06e42 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -561,9 +561,8 @@ static void gb_gpio_irqchip_remove(struct gb_gpio_controller *ggc) irq_domain_remove(ggc->irqdomain); } - if (ggc->irqchip) { + if (ggc->irqchip) ggc->irqchip = NULL; - } } /** -- cgit v0.10.2 From 659849cdc065c3620e49f9a7dbc384669f4592ab Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue <pure.logic@nexus-software.ie> Date: Mon, 26 Sep 2016 18:01:23 +0100 Subject: staging: greybus/timesync: avoid divide by zero on X86 Qemu A system configured without CONFIG_CPUFREQ will return 0 for cpufreq_get(). greybus-timesync can subsequently then do a divide-by-zero as result. This patch fixes by checking for a zero return value from cpufreq_get() and setting to a default value of 19.2MHz. Reported-by: Rui Miguel Silva <rmfrfs@gmail.com> Signed-off-by: Bryan O'Donoghue <pure.logic@nexus-software.ie> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/greybus/timesync_platform.c b/drivers/staging/greybus/timesync_platform.c index 50e8883..113f3d6 100644 --- a/drivers/staging/greybus/timesync_platform.c +++ b/drivers/staging/greybus/timesync_platform.c @@ -20,6 +20,8 @@ #include "greybus.h" #include "arche_platform.h" +#define DEFAULT_FRAMETIME_CLOCK_HZ 19200000 + static u32 gb_timesync_clock_frequency; int (*arche_platform_change_state_cb)(enum arche_platform_state state, struct gb_timesync_svc *pdata); @@ -32,8 +34,11 @@ u64 gb_timesync_platform_get_counter(void) u32 gb_timesync_platform_get_clock_rate(void) { - if (unlikely(!gb_timesync_clock_frequency)) - return cpufreq_get(0); + if (unlikely(!gb_timesync_clock_frequency)) { + gb_timesync_clock_frequency = cpufreq_get(0); + if (!gb_timesync_clock_frequency) + gb_timesync_clock_frequency = DEFAULT_FRAMETIME_CLOCK_HZ; + } return gb_timesync_clock_frequency; } -- cgit v0.10.2 From 3dd22268d77c012aaad01d3d7d30b4bdd9c4488a Mon Sep 17 00:00:00 2001 From: Quentin Lambert <lambert.quentin@gmail.com> Date: Tue, 27 Sep 2016 11:42:08 +0200 Subject: greybus: manifest: style fix missing space before '(' Checkpatch printed a style ERROR concerning a missing space before '('. This patch fixes this issue. Signed-off-by: Quentin Lambert <lambert.quentin@gmail.com> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 3d1592f..7b90377 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -11,7 +11,7 @@ static const char *get_descriptor_type_string(u8 type) { - switch(type) { + switch (type) { case GREYBUS_TYPE_INVALID: return "invalid"; case GREYBUS_TYPE_STRING: -- cgit v0.10.2 From 4a7beb1850d23d8a396d8655195c0e211cdb2221 Mon Sep 17 00:00:00 2001 From: wang di <di.wang@intel.com> Date: Mon, 26 Sep 2016 10:50:50 -0400 Subject: staging: lustre: llite: add missing LMV_MAGIC_V1 case The port to upstream dropped handling the LMV_MAGIC_V1 case for ll_dir_getstripe. This adds it back. Signed-off-by: wang di <di.wang@intel.com> Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3531 Reviewed-on: http://review.whamcloud.com/7228 Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Reviewed-by: John L. Hammond <john.hammond@intel.com> Reviewed-by: Alex Zhuravlev <alexey.zhuravlev@intel.com> Reviewed-by: Oleg Drokin <oleg.drokin@intel.com> Signed-off-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 705de1c..7f32a53 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -620,6 +620,10 @@ int ll_dir_getstripe(struct inode *inode, void **plmm, int *plmm_size, if (cpu_to_le32(LOV_MAGIC) != LOV_MAGIC) lustre_swab_lov_user_md_v3((struct lov_user_md_v3 *)lmm); break; + case LMV_MAGIC_V1: + if (cpu_to_le32(LMV_MAGIC) != LMV_MAGIC) + lustre_swab_lmv_mds_md((union lmv_mds_md *)lmm); + break; case LMV_USER_MAGIC: if (cpu_to_le32(LMV_USER_MAGIC) != LMV_USER_MAGIC) lustre_swab_lmv_user_md((struct lmv_user_md *)lmm); diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index e24d8e1..8717685 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -1861,6 +1861,7 @@ void lustre_swab_lmv_mds_md(union lmv_mds_md *lmm) break; } } +EXPORT_SYMBOL(lustre_swab_lmv_mds_md); void lustre_swab_lmv_user_md(struct lmv_user_md *lum) { -- cgit v0.10.2 From 1c40429dfad97d4e8193603058915182b728c8e9 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal <bhumirks@gmail.com> Date: Mon, 26 Sep 2016 20:03:06 +0530 Subject: Staging: wilc1000: constify cfg80211_ops structures Check for cfg80211_ops structures that are only passed as the first argument to the function wiphy_new. As this argument is constant, so cfg80211_ops structures having this property can also be declared constant. Done using coccinelle: @r1 disable optional_qualifier @ identifier i; position p; @@ static struct cfg80211_ops i@p = {...}; @ok1@ identifier r1.i; position p; expression e1; @@ wiphy_new(&i@p,e1) @bad@ position p!={r1.p,ok1.p}; identifier r1.i; @@ i@p @depends on !bad disable optional_qualifier@ identifier r1.i; @@ static +const struct cfg80211_ops i={...}; @depends on !bad disable optional_qualifier@ identifier r1.i; @@ +const struct cfg80211_ops i; File size before: text data bss dec hex filename 17468 2417 14912 34797 87ed drivers/staging/wilc1000/wilc_wfi_cfgoperations.o File size after: text data bss dec hex filename 18204 1681 14912 34797 87ed drivers/staging/wilc1000/wilc_wfi_cfgoperations.o Signed-off-by: Bhumika Goyal <bhumirks@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 2c2e8ac..60d8b05 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -2200,7 +2200,7 @@ static int get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, return ret; } -static struct cfg80211_ops wilc_cfg80211_ops = { +static const struct cfg80211_ops wilc_cfg80211_ops = { .set_monitor_channel = set_channel, .scan = scan, .connect = connect, -- cgit v0.10.2 From 4ceffe65c3fd79e75f50d4613aaefc00d81e2171 Mon Sep 17 00:00:00 2001 From: Matias Mucciolo <mmucciolo@suteba.org.ar> Date: Mon, 26 Sep 2016 13:13:03 -0300 Subject: staging: wilc1000: fix sparse warning: symbol was not declared. Should it be static? - Fixed a sparse warning: wilc_debugfs.c:32:10: warning: symbol 'WILC_DEBUG_LEVEL' was not declared. Should it be static? Signed-off-by: Matias Mucciolo <mmucciolo@suteba.org.ar> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wilc1000/wilc_debugfs.c b/drivers/staging/wilc1000/wilc_debugfs.c index b052628..802bb1d 100644 --- a/drivers/staging/wilc1000/wilc_debugfs.c +++ b/drivers/staging/wilc1000/wilc_debugfs.c @@ -29,7 +29,7 @@ static struct dentry *wilc_dir; #define ERR BIT(3) #define DBG_LEVEL_ALL (DEBUG | INFO | WRN | ERR) -atomic_t WILC_DEBUG_LEVEL = ATOMIC_INIT(ERR); +static atomic_t WILC_DEBUG_LEVEL = ATOMIC_INIT(ERR); EXPORT_SYMBOL_GPL(WILC_DEBUG_LEVEL); /* -- cgit v0.10.2 From 1ed90ff342b6513f310d39c1c3e0cf341ec4698d Mon Sep 17 00:00:00 2001 From: Bhumika Goyal <bhumirks@gmail.com> Date: Mon, 26 Sep 2016 10:31:38 +0530 Subject: Staging: iio: adc: constify attribute_group structures Check for attribute_group structures that are only stored in the attrs filed of iio_info structure. As the attrs field of iio_info structures is constant, so these attribute_group structures can also be declared constant. Done using coccinelle: @r1 disable optional_qualifier @ identifier i; position p; @@ static struct attribute_group i@p = {...}; @ok1@ identifier r1.i; position p; struct iio_info x; @@ x.attrs=&i@p; @bad@ position p!={r1.p,ok1.p}; identifier r1.i; @@ i@p @depends on !bad disable optional_qualifier@ identifier r1.i; @@ static +const struct attribute_group i={...}; @depends on !bad disable optional_qualifier@ identifier r1.i; @@ +const struct attribute_group i; File size before: drivers/staging/iio/adc/ad7280a.o text data bss dec hex filename 6487 584 776 7847 1ea7 drivers/staging/iio/adc/ad7280a.o File size after: drivers/staging/iio/adc/ad7280a.o text data bss dec hex filename 6551 544 776 7871 1ebf drivers/staging/iio/adc/ad7280a.o Signed-off-by: Bhumika Goyal <bhumirks@gmail.com> Acked-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c index 2177f1d..b460dda 100644 --- a/drivers/staging/iio/adc/ad7280a.c +++ b/drivers/staging/iio/adc/ad7280a.c @@ -478,7 +478,7 @@ static ssize_t ad7280_store_balance_timer(struct device *dev, static struct attribute *ad7280_attributes[AD7280A_MAX_CHAIN * AD7280A_CELLS_PER_DEV * 2 + 1]; -static struct attribute_group ad7280_attrs_group = { +static const struct attribute_group ad7280_attrs_group = { .attrs = ad7280_attributes, }; -- cgit v0.10.2 From 58fce732f02a198dbf55708d8221efc292e948b7 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal <bhumirks@gmail.com> Date: Mon, 26 Sep 2016 10:31:39 +0530 Subject: Staging: iio: light: constify attribute_group structures Check for attribute_group structures that are only stored in the attrs filed of iio_info structure. As the attrs field of iio_info structures is constant, so these attribute_group structures can also be declared constant. Done using coccinelle @r1 disable optional_qualifier @ identifier i; position p; @@ static struct attribute_group i@p = {...}; @ok1@ identifier r1.i; position p; struct iio_info x; @@ x.attrs=&i@p; @bad@ position p!={r1.p,ok1.p}; identifier r1.i; @@ i@p @depends on !bad disable optional_qualifier@ identifier r1.i; @@ static +const struct attribute_group i={...}; @depends on !bad disable optional_qualifier@ identifier r1.i; @@ +const struct attribute_group i; File size before: drivers/staging/iio/light/tsl2583.o text data bss dec hex filename 6529 1052 0 7581 1d9d drivers/staging/iio/light/tsl2583.o File size after: drivers/staging/iio/light/tsl2583.o text data bss dec hex filename 6593 988 0 7581 1d9d drivers/staging/iio/light/tsl2583.o Signed-off-by: Bhumika Goyal <bhumirks@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c index 05b4ad4..08f1583 100644 --- a/drivers/staging/iio/light/tsl2583.c +++ b/drivers/staging/iio/light/tsl2583.c @@ -803,7 +803,7 @@ static struct attribute *sysfs_attrs_ctrl[] = { NULL }; -static struct attribute_group tsl2583_attribute_group = { +static const struct attribute_group tsl2583_attribute_group = { .attrs = sysfs_attrs_ctrl, }; -- cgit v0.10.2 From c8be6461054c8c1f536e3085b15b539c1a9c4c7e Mon Sep 17 00:00:00 2001 From: Georgiana Rodica Chelu <georgiana.chelu93@gmail.com> Date: Mon, 26 Sep 2016 11:15:56 +0300 Subject: staging: ks7010: ks_wlan_net: Use netdev_ instead of printk The checkpatch.pl script found the following warning: WARNING: printk() should include KERN_ facility level After adding the KERN_ facility level to printk(), the script showed another warning: WARNING: Prefer [subsystem eg: netdev]_info([subsystem]dev, ... then dev_info(dev, ... then pr_info(... to printk(KERN_INFO ... The warning is similar for KERN_ERR and KERN_DEBUG. In conclusion, use netdev_info(), netdev_err() or netdev_dbg() when there is a netdev device. Signed-off-by: Georgiana Rodica Chelu <georgiana.chelu93@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks_wlan_net.c b/drivers/staging/ks7010/ks_wlan_net.c index 9e2bdd6..4a14327 100644 --- a/drivers/staging/ks7010/ks_wlan_net.c +++ b/drivers/staging/ks7010/ks_wlan_net.c @@ -233,9 +233,9 @@ static int ks_wlan_set_freq(struct net_device *dev, /* We should do a better check than that, * based on the card capability !!! */ if ((channel < 1) || (channel > 14)) { - printk(KERN_DEBUG - "%s: New channel value of %d is invalid!\n", - dev->name, fwrq->m); + netdev_dbg(dev, + "%s: New channel value of %d is invalid!\n", + dev->name, fwrq->m); rc = -EINVAL; } else { /* Yes ! We can set it !!! */ @@ -2671,17 +2671,17 @@ static int ks_wlan_set_sleep_mode(struct net_device *dev, if (*uwrq == SLP_SLEEP) { priv->sleep_mode = *uwrq; - printk("SET_SLEEP_MODE %d\n", priv->sleep_mode); + netdev_info(dev, "SET_SLEEP_MODE %d\n", priv->sleep_mode); hostif_sme_enqueue(priv, SME_STOP_REQUEST); hostif_sme_enqueue(priv, SME_SLEEP_REQUEST); } else if (*uwrq == SLP_ACTIVE) { priv->sleep_mode = *uwrq; - printk("SET_SLEEP_MODE %d\n", priv->sleep_mode); + netdev_info(dev, "SET_SLEEP_MODE %d\n", priv->sleep_mode); hostif_sme_enqueue(priv, SME_SLEEP_REQUEST); } else { - printk("SET_SLEEP_MODE %d errror\n", *uwrq); + netdev_err(dev, "SET_SLEEP_MODE %d errror\n", *uwrq); return -EINVAL; } @@ -2783,7 +2783,7 @@ static int ks_wlan_get_wps_enable(struct net_device *dev, } /* for SLEEP MODE */ *uwrq = priv->wps.wps_enabled; - printk("return=%d\n", *uwrq); + netdev_info(dev, "return=%d\n", *uwrq); return 0; } @@ -3330,7 +3330,7 @@ int ks_wlan_set_mac_address(struct net_device *dev, void *addr) priv->mac_address_valid = 0; hostif_sme_enqueue(priv, SME_MACADDRESS_SET_REQUEST); - printk(KERN_INFO + netdev_info(dev, "ks_wlan: MAC ADDRESS = %02x:%02x:%02x:%02x:%02x:%02x\n", priv->eth_addr[0], priv->eth_addr[1], priv->eth_addr[2], priv->eth_addr[3], priv->eth_addr[4], priv->eth_addr[5]); @@ -3360,7 +3360,7 @@ int ks_wlan_start_xmit(struct sk_buff *skb, struct net_device *dev) DPRINTK(3, "in_interrupt()=%ld\n", in_interrupt()); if (!skb) { - printk(KERN_ERR "ks_wlan: skb == NULL!!!\n"); + netdev_err(dev, "ks_wlan: skb == NULL!!!\n"); return 0; } if (priv->dev_state < DEVICE_STATE_READY) { @@ -3424,7 +3424,7 @@ int ks_wlan_open(struct net_device *dev) priv->cur_rx = 0; if (!priv->mac_address_valid) { - printk(KERN_ERR "ks_wlan : %s Not READY !!\n", dev->name); + netdev_err(dev, "ks_wlan : %s Not READY !!\n", dev->name); return -EBUSY; } else netif_start_queue(dev); -- cgit v0.10.2 From 03806ab307c369b2598097a12c9ceed245f9ade0 Mon Sep 17 00:00:00 2001 From: Georgiana Rodica Chelu <georgiana.chelu93@gmail.com> Date: Mon, 26 Sep 2016 14:07:52 +0300 Subject: staging: ks7010: ks_wlan_net: Use netdev_info instead of printk Pass the net_device structure to print_hif_event function in order to use netdev_info instead of printk. Signed-off-by: Georgiana Rodica Chelu <georgiana.chelu93@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks_wlan_net.c b/drivers/staging/ks7010/ks_wlan_net.c index 4a14327..b2b4fa4 100644 --- a/drivers/staging/ks7010/ks_wlan_net.c +++ b/drivers/staging/ks7010/ks_wlan_net.c @@ -2973,117 +2973,117 @@ static int ks_wlan_get_eeprom_cksum(struct net_device *dev, return 0; } -static void print_hif_event(int event) +static void print_hif_event(struct net_device *dev, int event) { switch (event) { case HIF_DATA_REQ: - printk("HIF_DATA_REQ\n"); + netdev_info(dev, "HIF_DATA_REQ\n"); break; case HIF_DATA_IND: - printk("HIF_DATA_IND\n"); + netdev_info(dev, "HIF_DATA_IND\n"); break; case HIF_MIB_GET_REQ: - printk("HIF_MIB_GET_REQ\n"); + netdev_info(dev, "HIF_MIB_GET_REQ\n"); break; case HIF_MIB_GET_CONF: - printk("HIF_MIB_GET_CONF\n"); + netdev_info(dev, "HIF_MIB_GET_CONF\n"); break; case HIF_MIB_SET_REQ: - printk("HIF_MIB_SET_REQ\n"); + netdev_info(dev, "HIF_MIB_SET_REQ\n"); break; case HIF_MIB_SET_CONF: - printk("HIF_MIB_SET_CONF\n"); + netdev_info(dev, "HIF_MIB_SET_CONF\n"); break; case HIF_POWERMGT_REQ: - printk("HIF_POWERMGT_REQ\n"); + netdev_info(dev, "HIF_POWERMGT_REQ\n"); break; case HIF_POWERMGT_CONF: - printk("HIF_POWERMGT_CONF\n"); + netdev_info(dev, "HIF_POWERMGT_CONF\n"); break; case HIF_START_REQ: - printk("HIF_START_REQ\n"); + netdev_info(dev, "HIF_START_REQ\n"); break; case HIF_START_CONF: - printk("HIF_START_CONF\n"); + netdev_info(dev, "HIF_START_CONF\n"); break; case HIF_CONNECT_IND: - printk("HIF_CONNECT_IND\n"); + netdev_info(dev, "HIF_CONNECT_IND\n"); break; case HIF_STOP_REQ: - printk("HIF_STOP_REQ\n"); + netdev_info(dev, "HIF_STOP_REQ\n"); break; case HIF_STOP_CONF: - printk("HIF_STOP_CONF\n"); + netdev_info(dev, "HIF_STOP_CONF\n"); break; case HIF_PS_ADH_SET_REQ: - printk("HIF_PS_ADH_SET_REQ\n"); + netdev_info(dev, "HIF_PS_ADH_SET_REQ\n"); break; case HIF_PS_ADH_SET_CONF: - printk("HIF_PS_ADH_SET_CONF\n"); + netdev_info(dev, "HIF_PS_ADH_SET_CONF\n"); break; case HIF_INFRA_SET_REQ: - printk("HIF_INFRA_SET_REQ\n"); + netdev_info(dev, "HIF_INFRA_SET_REQ\n"); break; case HIF_INFRA_SET_CONF: - printk("HIF_INFRA_SET_CONF\n"); + netdev_info(dev, "HIF_INFRA_SET_CONF\n"); break; case HIF_ADH_SET_REQ: - printk("HIF_ADH_SET_REQ\n"); + netdev_info(dev, "HIF_ADH_SET_REQ\n"); break; case HIF_ADH_SET_CONF: - printk("HIF_ADH_SET_CONF\n"); + netdev_info(dev, "HIF_ADH_SET_CONF\n"); break; case HIF_AP_SET_REQ: - printk("HIF_AP_SET_REQ\n"); + netdev_info(dev, "HIF_AP_SET_REQ\n"); break; case HIF_AP_SET_CONF: - printk("HIF_AP_SET_CONF\n"); + netdev_info(dev, "HIF_AP_SET_CONF\n"); break; case HIF_ASSOC_INFO_IND: - printk("HIF_ASSOC_INFO_IND\n"); + netdev_info(dev, "HIF_ASSOC_INFO_IND\n"); break; case HIF_MIC_FAILURE_REQ: - printk("HIF_MIC_FAILURE_REQ\n"); + netdev_info(dev, "HIF_MIC_FAILURE_REQ\n"); break; case HIF_MIC_FAILURE_CONF: - printk("HIF_MIC_FAILURE_CONF\n"); + netdev_info(dev, "HIF_MIC_FAILURE_CONF\n"); break; case HIF_SCAN_REQ: - printk("HIF_SCAN_REQ\n"); + netdev_info(dev, "HIF_SCAN_REQ\n"); break; case HIF_SCAN_CONF: - printk("HIF_SCAN_CONF\n"); + netdev_info(dev, "HIF_SCAN_CONF\n"); break; case HIF_PHY_INFO_REQ: - printk("HIF_PHY_INFO_REQ\n"); + netdev_info(dev, "HIF_PHY_INFO_REQ\n"); break; case HIF_PHY_INFO_CONF: - printk("HIF_PHY_INFO_CONF\n"); + netdev_info(dev, "HIF_PHY_INFO_CONF\n"); break; case HIF_SLEEP_REQ: - printk("HIF_SLEEP_REQ\n"); + netdev_info(dev, "HIF_SLEEP_REQ\n"); break; case HIF_SLEEP_CONF: - printk("HIF_SLEEP_CONF\n"); + netdev_info(dev, "HIF_SLEEP_CONF\n"); break; case HIF_PHY_INFO_IND: - printk("HIF_PHY_INFO_IND\n"); + netdev_info(dev, "HIF_PHY_INFO_IND\n"); break; case HIF_SCAN_IND: - printk("HIF_SCAN_IND\n"); + netdev_info(dev, "HIF_SCAN_IND\n"); break; case HIF_INFRA_SET2_REQ: - printk("HIF_INFRA_SET2_REQ\n"); + netdev_info(dev, "HIF_INFRA_SET2_REQ\n"); break; case HIF_INFRA_SET2_CONF: - printk("HIF_INFRA_SET2_CONF\n"); + netdev_info(dev, "HIF_INFRA_SET2_CONF\n"); break; case HIF_ADH_SET2_REQ: - printk("HIF_ADH_SET2_REQ\n"); + netdev_info(dev, "HIF_ADH_SET2_REQ\n"); break; case HIF_ADH_SET2_CONF: - printk("HIF_ADH_SET2_CONF\n"); + netdev_info(dev, "HIF_ADH_SET2_CONF\n"); } } @@ -3100,7 +3100,7 @@ static int ks_wlan_hostt(struct net_device *dev, struct iw_request_info *info, event = priv->hostt.buff[(priv->hostt.qtail - 1 - i) % SME_EVENT_BUFF_SIZE]; - print_hif_event(event); + print_hif_event(dev, event); } return 0; } -- cgit v0.10.2 From 9887b5e51fafaf919601ccb8bdae1e0ad749032f Mon Sep 17 00:00:00 2001 From: Sabitha George <sabitha.george@gmail.com> Date: Mon, 26 Sep 2016 22:40:16 +0530 Subject: staging: ks7010: Fix warnings on printk() usage This patch fixes the following warnings on ks7010_sdio.c 1. printk() should include KERN_ facility level 2. Prefer [subsystem eg: netdev]_err([subsystem]dev, ... then dev_err(dev, ... then pr_err(... to printk(KERN_ERR ... Signed-off-by: Sabitha George <sabitha.george@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c index b27e9b0..28fb5a0 100644 --- a/drivers/staging/ks7010/ks7010_sdio.c +++ b/drivers/staging/ks7010/ks7010_sdio.c @@ -496,8 +496,10 @@ static void ks7010_rw_function(struct work_struct *work) DPRINTK(4, "wait after WAKEUP\n"); /* queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,&priv->ks_wlan_hw.rw_wq, (priv->last_wakeup + ((30*HZ)/1000) - jiffies));*/ - printk("wake: %lu %lu\n", priv->last_wakeup + (30 * HZ) / 1000, - jiffies); + dev_info(&priv->ks_wlan_hw.sdio_card->func->dev, + "wake: %lu %lu\n", + priv->last_wakeup + (30 * HZ) / 1000, + jiffies); msleep(30); } @@ -1003,11 +1005,12 @@ static int ks7010_sdio_probe(struct sdio_func *func, /* private memory allocate */ netdev = alloc_etherdev(sizeof(*priv)); if (!netdev) { - printk(KERN_ERR "ks7010 : Unable to alloc new net device\n"); + dev_err(&card->func->dev, "ks7010 : Unable to alloc new net device\n"); goto error_release_irq; } if (dev_alloc_name(netdev, "wlan%d") < 0) { - printk(KERN_ERR "ks7010 : Couldn't get name!\n"); + dev_err(&card->func->dev, + "ks7010 : Couldn't get name!\n"); goto error_free_netdev; } @@ -1047,9 +1050,9 @@ static int ks7010_sdio_probe(struct sdio_func *func, /* Upload firmware */ ret = ks7010_upload_firmware(priv, card); /* firmware load */ if (ret) { - printk(KERN_ERR - "ks7010: firmware load failed !! retern code = %d\n", - ret); + dev_err(&card->func->dev, + "ks7010: firmware load failed !! return code = %d\n", + ret); goto error_free_read_buf; } -- cgit v0.10.2 From 2460563fb490b8061d614f99b1ce1a470fde4913 Mon Sep 17 00:00:00 2001 From: Matt Kilgore <mattkilgore12@gmail.com> Date: Tue, 27 Sep 2016 02:05:44 -0400 Subject: staging: ks7010: Use __packed over __attribute__((packed)) This replaces uses of __attribute__((packed)) with __packed, which is recommended to be used over the direct __attribute__. This patch then includes <linux/compiler.h> as necessary to use __packed. Signed-off-by: Matthew Kilgore <mattkilgore12@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/eap_packet.h b/drivers/staging/ks7010/eap_packet.h index 16a392a..373c0fe 100644 --- a/drivers/staging/ks7010/eap_packet.h +++ b/drivers/staging/ks7010/eap_packet.h @@ -1,6 +1,8 @@ #ifndef EAP_PACKET_H #define EAP_PACKET_H +#include <linux/compiler.h> + #define WBIT(n) (1 << (n)) #ifndef ETH_ALEN @@ -19,14 +21,14 @@ struct ether_hdr { #define ETHER_PROTOCOL_TYPE_IP 0x0800 #define ETHER_PROTOCOL_TYPE_ARP 0x0806 /* followed by length octets of data */ -} __attribute__ ((packed)); +} __packed; struct ieee802_1x_hdr { unsigned char version; unsigned char type; unsigned short length; /* followed by length octets of data */ -} __attribute__ ((packed)); +} __packed; #define EAPOL_VERSION 2 @@ -69,7 +71,7 @@ struct ieee802_1x_eapol_key { * represents the number of least significant octets from * MS-MPPE-Send-Key attribute to be used as the keying material; * RC4 key used in encryption = Key-IV + MS-MPPE-Recv-Key */ -} __attribute__ ((packed)); +} __packed; #define WPA_NONCE_LEN 32 #define WPA_REPLAY_COUNTER_LEN 8 @@ -86,7 +88,7 @@ struct wpa_eapol_key { unsigned char key_mic[16]; unsigned short key_data_length; /* followed by key_data_length bytes of key_data */ -} __attribute__ ((packed)); +} __packed; #define WPA_KEY_INFO_TYPE_MASK (WBIT(0) | WBIT(1) | WBIT(2)) #define WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 WBIT(0) diff --git a/drivers/staging/ks7010/ks_hostif.h b/drivers/staging/ks7010/ks_hostif.h index ffd0174..743f31e 100644 --- a/drivers/staging/ks7010/ks_hostif.h +++ b/drivers/staging/ks7010/ks_hostif.h @@ -11,6 +11,9 @@ #ifndef _KS_HOSTIF_H_ #define _KS_HOSTIF_H_ + +#include <linux/compiler.h> + /* * HOST-MAC I/F events */ @@ -61,7 +64,7 @@ struct hostif_hdr { uint16_t size; uint16_t event; -} __attribute__ ((packed)); +} __packed; struct hostif_data_request_t { struct hostif_hdr header; @@ -70,7 +73,7 @@ struct hostif_data_request_t { #define TYPE_AUTH 0x0001 uint16_t reserved; uint8_t data[0]; -} __attribute__ ((packed)); +} __packed; struct hostif_data_indication_t { struct hostif_hdr header; @@ -81,14 +84,14 @@ struct hostif_data_indication_t { #define TYPE_GMK2 0x0003 uint16_t reserved; uint8_t data[0]; -} __attribute__ ((packed)); +} __packed; #define CHANNEL_LIST_MAX_SIZE 14 struct channel_list_t { uint8_t size; uint8_t body[CHANNEL_LIST_MAX_SIZE]; uint8_t pad; -} __attribute__ ((packed)); +} __packed; /* MIB Attribute */ #define DOT11_MAC_ADDRESS 0x21010100 /* MAC Address (R) */ @@ -141,7 +144,7 @@ struct channel_list_t { struct hostif_mib_get_request_t { struct hostif_hdr header; uint32_t mib_attribute; -} __attribute__ ((packed)); +} __packed; struct hostif_mib_value_t { uint16_t size; @@ -152,7 +155,7 @@ struct hostif_mib_value_t { #define MIB_VALUE_TYPE_COUNT32 3 #define MIB_VALUE_TYPE_OSTRING 4 uint8_t body[0]; -} __attribute__ ((packed)); +} __packed; struct hostif_mib_get_confirm_t { struct hostif_hdr header; @@ -163,19 +166,19 @@ struct hostif_mib_get_confirm_t { #define MIB_WRITE_ONLY 3 uint32_t mib_attribute; struct hostif_mib_value_t mib_value; -} __attribute__ ((packed)); +} __packed; struct hostif_mib_set_request_t { struct hostif_hdr header; uint32_t mib_attribute; struct hostif_mib_value_t mib_value; -} __attribute__ ((packed)); +} __packed; struct hostif_mib_set_confirm_t { struct hostif_hdr header; uint32_t mib_status; uint32_t mib_attribute; -} __attribute__ ((packed)); +} __packed; struct hostif_power_mngmt_request_t { struct hostif_hdr header; @@ -188,7 +191,7 @@ struct hostif_power_mngmt_request_t { uint32_t receiveDTIMs; #define DTIM_FALSE 0 #define DTIM_TRUE 1 -} __attribute__ ((packed)); +} __packed; /* power management mode */ enum { @@ -206,7 +209,7 @@ enum { struct hostif_power_mngmt_confirm_t { struct hostif_hdr header; uint16_t result_code; -} __attribute__ ((packed)); +} __packed; struct hostif_start_request_t { struct hostif_hdr header; @@ -215,64 +218,64 @@ struct hostif_start_request_t { #define MODE_INFRASTRUCTURE 1 #define MODE_AP 2 /* not used */ #define MODE_ADHOC 3 -} __attribute__ ((packed)); +} __packed; struct hostif_start_confirm_t { struct hostif_hdr header; uint16_t result_code; -} __attribute__ ((packed)); +} __packed; #define SSID_MAX_SIZE 32 struct ssid_t { uint8_t size; uint8_t body[SSID_MAX_SIZE]; uint8_t ssid_pad; -} __attribute__ ((packed)); +} __packed; #define RATE_SET_MAX_SIZE 16 struct rate_set8_t { uint8_t size; uint8_t body[8]; uint8_t rate_pad; -} __attribute__ ((packed)); +} __packed; struct FhParms_t { uint16_t dwellTime; uint8_t hopSet; uint8_t hopPattern; uint8_t hopIndex; -} __attribute__ ((packed)); +} __packed; struct DsParms_t { uint8_t channel; -} __attribute__ ((packed)); +} __packed; struct CfParms_t { uint8_t count; uint8_t period; uint16_t maxDuration; uint16_t durRemaining; -} __attribute__ ((packed)); +} __packed; struct IbssParms_t { uint16_t atimWindow; -} __attribute__ ((packed)); +} __packed; struct rsn_t { uint8_t size; #define RSN_BODY_SIZE 64 uint8_t body[RSN_BODY_SIZE]; -} __attribute__ ((packed)); +} __packed; struct ErpParams_t { uint8_t erp_info; -} __attribute__ ((packed)); +} __packed; struct rate_set16_t { uint8_t size; uint8_t body[16]; uint8_t rate_pad; -} __attribute__ ((packed)); +} __packed; struct ap_info_t { uint8_t bssid[6]; /* +00 */ @@ -299,7 +302,7 @@ struct ap_info_t { uint16_t body_size; /* +16 */ uint8_t body[1024]; /* +18 */ /* +1032 */ -} __attribute__ ((packed)); +} __packed; struct link_ap_info_t { uint8_t bssid[6]; /* +00 */ @@ -325,8 +328,8 @@ struct link_ap_info_t { struct { uint8_t size; /* +52 */ uint8_t body[128]; /* +53 */ - } __attribute__ ((packed)) rsn; -} __attribute__ ((packed)); + } __packed rsn; +} __packed; struct hostif_connect_indication_t { struct hostif_hdr header; @@ -334,16 +337,16 @@ struct hostif_connect_indication_t { #define RESULT_CONNECT 0 #define RESULT_DISCONNECT 1 struct link_ap_info_t link_ap_info; -} __attribute__ ((packed)); +} __packed; struct hostif_stop_request_t { struct hostif_hdr header; -} __attribute__ ((packed)); +} __packed; struct hostif_stop_confirm_t { struct hostif_hdr header; uint16_t result_code; -} __attribute__ ((packed)); +} __packed; struct hostif_ps_adhoc_set_request_t { struct hostif_hdr header; @@ -360,12 +363,12 @@ struct hostif_ps_adhoc_set_request_t { uint16_t capability; /* bit5:preamble bit6:pbcc pbcc not supported always 0 * bit10:ShortSlotTime bit13:DSSS-OFDM DSSS-OFDM not supported always 0 */ uint16_t scan_type; -} __attribute__ ((packed)); +} __packed; struct hostif_ps_adhoc_set_confirm_t { struct hostif_hdr header; uint16_t result_code; -} __attribute__ ((packed)); +} __packed; struct hostif_infrastructure_set_request_t { struct hostif_hdr header; @@ -381,7 +384,7 @@ struct hostif_infrastructure_set_request_t { #define AUTH_TYPE_SHARED_KEY 1 struct channel_list_t channel_list; uint16_t scan_type; -} __attribute__ ((packed)); +} __packed; struct hostif_infrastructure_set2_request_t { struct hostif_hdr header; @@ -398,12 +401,12 @@ struct hostif_infrastructure_set2_request_t { struct channel_list_t channel_list; uint16_t scan_type; uint8_t bssid[ETH_ALEN]; -} __attribute__ ((packed)); +} __packed; struct hostif_infrastructure_set_confirm_t { struct hostif_hdr header; uint16_t result_code; -} __attribute__ ((packed)); +} __packed; struct hostif_adhoc_set_request_t { struct hostif_hdr header; @@ -415,7 +418,7 @@ struct hostif_adhoc_set_request_t { uint16_t capability; /* bit5:preamble bit6:pbcc pbcc not supported always 0 * bit10:ShortSlotTime bit13:DSSS-OFDM DSSS-OFDM not supported always 0 */ uint16_t scan_type; -} __attribute__ ((packed)); +} __packed; struct hostif_adhoc_set2_request_t { struct hostif_hdr header; @@ -429,17 +432,17 @@ struct hostif_adhoc_set2_request_t { uint16_t scan_type; struct channel_list_t channel_list; uint8_t bssid[ETH_ALEN]; -} __attribute__ ((packed)); +} __packed; struct hostif_adhoc_set_confirm_t { struct hostif_hdr header; uint16_t result_code; -} __attribute__ ((packed)); +} __packed; struct last_associate_t { uint8_t type; uint8_t status; -} __attribute__ ((packed)); +} __packed; struct association_request_t { uint8_t type; @@ -450,7 +453,7 @@ struct association_request_t { uint16_t listen_interval; uint8_t ap_address[6]; uint16_t reqIEs_size; -} __attribute__ ((packed)); +} __packed; struct association_response_t { uint8_t type; @@ -461,7 +464,7 @@ struct association_response_t { uint16_t status; uint16_t association_id; uint16_t respIEs_size; -} __attribute__ ((packed)); +} __packed; struct hostif_associate_indication_t { struct hostif_hdr header; @@ -469,7 +472,7 @@ struct hostif_associate_indication_t { struct association_response_t assoc_resp; /* followed by (reqIEs_size + respIEs_size) octets of data */ /* reqIEs data *//* respIEs data */ -} __attribute__ ((packed)); +} __packed; struct hostif_bss_scan_request_t { struct hostif_hdr header; @@ -481,13 +484,13 @@ struct hostif_bss_scan_request_t { uint32_t ch_time_max; struct channel_list_t channel_list; struct ssid_t ssid; -} __attribute__ ((packed)); +} __packed; struct hostif_bss_scan_confirm_t { struct hostif_hdr header; uint16_t result_code; uint16_t reserved; -} __attribute__ ((packed)); +} __packed; struct hostif_phy_information_request_t { struct hostif_hdr header; @@ -495,7 +498,7 @@ struct hostif_phy_information_request_t { #define NORMAL_TYPE 0 #define TIME_TYPE 1 uint16_t time; /* unit 100ms */ -} __attribute__ ((packed)); +} __packed; struct hostif_phy_information_confirm_t { struct hostif_hdr header; @@ -507,30 +510,30 @@ struct hostif_phy_information_confirm_t { uint32_t rx_frame; uint32_t tx_error; uint32_t rx_error; -} __attribute__ ((packed)); +} __packed; /* sleep mode */ #define SLP_ACTIVE 0 #define SLP_SLEEP 1 struct hostif_sleep_request_t { struct hostif_hdr header; -} __attribute__ ((packed)); +} __packed; struct hostif_sleep_confirm_t { struct hostif_hdr header; uint16_t result_code; -} __attribute__ ((packed)); +} __packed; struct hostif_mic_failure_request_t { struct hostif_hdr header; uint16_t failure_count; uint16_t timer; -} __attribute__ ((packed)); +} __packed; struct hostif_mic_failure_confirm_t { struct hostif_hdr header; uint16_t result_code; -} __attribute__ ((packed)); +} __packed; #define BASIC_RATE 0x80 #define RATE_MASK 0x7F diff --git a/drivers/staging/ks7010/ks_wlan.h b/drivers/staging/ks7010/ks_wlan.h index 693e7d8..c2cc288 100644 --- a/drivers/staging/ks7010/ks_wlan.h +++ b/drivers/staging/ks7010/ks_wlan.h @@ -219,7 +219,7 @@ struct rsn_ie_t { uint8_t id; /* 0xdd = WPA or 0x30 = RSN */ uint8_t size; /* max ? 255 ? */ uint8_t body[RSN_IE_BODY_MAX]; -} __attribute__ ((packed)); +} __packed; #ifdef WPS #define WPS_IE_BODY_MAX 255 @@ -227,7 +227,7 @@ struct wps_ie_t { uint8_t id; /* 221 'dd <len> 00 50 F2 04' */ uint8_t size; /* max ? 255 ? */ uint8_t body[WPS_IE_BODY_MAX]; -} __attribute__ ((packed)); +} __packed; #endif /* WPS */ struct local_ap_t { -- cgit v0.10.2 From e82ed633eb814f25861d8942ed33881e4b36d5c4 Mon Sep 17 00:00:00 2001 From: Jon Frisch <jon.frisch@unisys.com> Date: Mon, 26 Sep 2016 11:03:41 -0400 Subject: staging: unisys: remove driver version from struct visor_driver This patch removes the all instances of the driver version from struct visor_driver. This includes removing version, vertag (a human readable version string of the driver version) and version_attr from struct visor_driver. This resulted in removing the bus attributes and driver attributes which only contained the driver version. The utsname function is used to replace the driver version with the kernel version in bus_device_info_init(). Signed-off-by: Jon Frisch <jon.frisch@unisys.com> Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: David Kershner <david.kershner@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/include/visorbus.h b/drivers/staging/unisys/include/visorbus.h index 993cf19..2e508c2 100644 --- a/drivers/staging/unisys/include/visorbus.h +++ b/drivers/staging/unisys/include/visorbus.h @@ -66,8 +66,6 @@ struct visor_channeltype_descriptor { * struct visor_driver - Information provided by each visor driver when it * registers with the visorbus driver. * @name: Name of the visor driver. - * @version: The numbered version of the driver (x.x.xxx). - * @vertag: A human readable version string. * @owner: The module owner. * @channel_types: Types of channels handled by this driver, ending with * a zero GUID. Our specialized BUS.match() method knows @@ -94,12 +92,9 @@ struct visor_channeltype_descriptor { * @resume: Behaves similar to pause. * @driver: Private reference to the device driver. For use by bus * driver only. - * @version_attr: Private version field. For use by bus driver only. */ struct visor_driver { const char *name; - const char *version; - const char *vertag; struct module *owner; struct visor_channeltype_descriptor *channel_types; int (*probe)(struct visor_device *dev); @@ -112,7 +107,6 @@ struct visor_driver { /* These fields are for private use by the bus driver only. */ struct device_driver driver; - struct driver_attribute version_attr; }; #define to_visor_driver(x) ((x) ? \ diff --git a/drivers/staging/unisys/visorbus/vbuschannel.h b/drivers/staging/unisys/visorbus/vbuschannel.h index 3f7830b..e979175 100644 --- a/drivers/staging/unisys/visorbus/vbuschannel.h +++ b/drivers/staging/unisys/visorbus/vbuschannel.h @@ -67,8 +67,7 @@ static const uuid_le spar_vbus_channel_protocol_uuid = struct ultra_vbus_deviceinfo { u8 devtype[16]; /* short string identifying the device type */ u8 drvname[16]; /* driver .sys file name */ - u8 infostrs[96]; /* sequence of tab-delimited id strings: */ - /* <DRIVER_REV> <DRIVER_VERTAG> <DRIVER_COMPILETIME> */ + u8 infostrs[96]; /* kernel version */ u8 reserved[128]; /* pad size to 256 bytes */ }; diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 3918bb5..1f3d2e0 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -18,7 +18,6 @@ #include "visorbus.h" #include "visorbus_private.h" -#include "version.h" #include "vmcallinterface.h" #define MYDRVNAME "visorbus" @@ -36,34 +35,6 @@ static int visorbus_forcenomatch; static int busreg_rc = -ENODEV; /* stores the result from bus registration */ /* - * BUS type attributes - * - * define & implement display of bus attributes under - * /sys/bus/visorbus. - */ - -static ssize_t version_show(struct bus_type *bus, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%s\n", VERSION); -} - -static BUS_ATTR_RO(version); - -static struct attribute *visorbus_bus_attrs[] = { - &bus_attr_version.attr, - NULL, -}; - -static const struct attribute_group visorbus_bus_group = { - .attrs = visorbus_bus_attrs, -}; - -static const struct attribute_group *visorbus_bus_groups[] = { - &visorbus_bus_group, - NULL, -}; - -/* * DEVICE type attributes * * The modalias file will contain the guid of the device. @@ -167,7 +138,6 @@ struct bus_type visorbus_type = { .match = visorbus_match, .uevent = visorbus_uevent, .dev_groups = visorbus_dev_groups, - .bus_groups = visorbus_bus_groups, }; /** @@ -465,36 +435,6 @@ static const struct attribute_group *visorbus_groups[] = { NULL }; -/* - * DRIVER attributes - * - * define & implement display of driver attributes under - * /sys/bus/visorbus/drivers/<drivername>. - */ - -static ssize_t -DRIVER_ATTR_version(struct device_driver *xdrv, char *buf) -{ - struct visor_driver *drv = to_visor_driver(xdrv); - - return snprintf(buf, PAGE_SIZE, "%s\n", drv->version); -} - -static int -register_driver_attributes(struct visor_driver *drv) -{ - struct driver_attribute version = - __ATTR(version, S_IRUGO, DRIVER_ATTR_version, NULL); - drv->version_attr = version; - return driver_create_file(&drv->driver, &drv->version_attr); -} - -static void -unregister_driver_attributes(struct visor_driver *drv) -{ - driver_remove_file(&drv->driver, &drv->version_attr); -} - static void dev_periodic_work(unsigned long __opaque) { @@ -567,7 +507,6 @@ visordriver_remove_device(struct device *xdev) void visorbus_unregister_visor_driver(struct visor_driver *drv) { - unregister_driver_attributes(drv); driver_unregister(&drv->driver); } EXPORT_SYMBOL_GPL(visorbus_unregister_visor_driver); @@ -882,9 +821,7 @@ fix_vbus_dev_info(struct visor_device *visordev) } } - bus_device_info_init(&dev_info, chan_type_name, - visordrv->name, visordrv->version, - visordrv->vertag); + bus_device_info_init(&dev_info, chan_type_name, visordrv->name); write_vbus_dev_info(bdev->visorchannel, hdr_info, &dev_info, dev_no); /* @@ -1015,9 +952,6 @@ int visorbus_register_visor_driver(struct visor_driver *drv) rc = driver_register(&drv->driver); if (rc < 0) - return rc; - rc = register_driver_attributes(drv); - if (rc < 0) driver_unregister(&drv->driver); return rc; } @@ -1343,9 +1277,7 @@ visorbus_init(void) int err; POSTCODE_LINUX_3(DRIVER_ENTRY_PC, 0, POSTCODE_SEVERITY_INFO); - bus_device_info_init(&clientbus_driverinfo, - "clientbus", "visorbus", - VERSION, NULL); + bus_device_info_init(&clientbus_driverinfo, "clientbus", "visorbus"); err = create_bus_type(); if (err < 0) { @@ -1353,9 +1285,7 @@ visorbus_init(void) goto error; } - bus_device_info_init(&chipset_driverinfo, - "chipset", "visorchipset", - VERSION, NULL); + bus_device_info_init(&chipset_driverinfo, "chipset", "visorchipset"); return 0; diff --git a/drivers/staging/unisys/visorbus/visorbus_private.h b/drivers/staging/unisys/visorbus/visorbus_private.h index 2f4e1e6..15403fb 100644 --- a/drivers/staging/unisys/visorbus/visorbus_private.h +++ b/drivers/staging/unisys/visorbus/visorbus_private.h @@ -18,6 +18,7 @@ #define __VISORBUS_PRIVATE_H__ #include <linux/uuid.h> +#include <linux/utsname.h> #include "controlvmchannel.h" #include "vbuschannel.h" @@ -26,12 +27,9 @@ * command line */ -#define TARGET_HOSTNAME "linuxguest" - static inline void bus_device_info_init( struct ultra_vbus_deviceinfo *bus_device_info_ptr, - const char *dev_type, const char *drv_name, - const char *ver, const char *ver_tag) + const char *dev_type, const char *drv_name) { memset(bus_device_info_ptr, 0, sizeof(struct ultra_vbus_deviceinfo)); snprintf(bus_device_info_ptr->devtype, @@ -41,10 +39,8 @@ static inline void bus_device_info_init( sizeof(bus_device_info_ptr->drvname), "%s", (drv_name) ? drv_name : "unknownDriver"); snprintf(bus_device_info_ptr->infostrs, - sizeof(bus_device_info_ptr->infostrs), "%s\t%s\t%s", - (ver) ? ver : "unknownVer", - (ver_tag) ? ver_tag : "unknownVerTag", - TARGET_HOSTNAME); + sizeof(bus_device_info_ptr->infostrs), "kernel ver. %s", + utsname()->release); } void chipset_bus_create(struct visor_device *bus_info); diff --git a/drivers/staging/unisys/visorinput/visorinput.c b/drivers/staging/unisys/visorinput/visorinput.c index 641cdab..4e0b26d2 100644 --- a/drivers/staging/unisys/visorinput/visorinput.c +++ b/drivers/staging/unisys/visorinput/visorinput.c @@ -735,7 +735,6 @@ static struct visor_channeltype_descriptor visorinput_channel_types[] = { static struct visor_driver visorinput_driver = { .name = "visorinput", - .vertag = NULL, .owner = THIS_MODULE, .channel_types = visorinput_channel_types, .probe = visorinput_probe, diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index 6b206be..7a58d2e 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -2033,8 +2033,6 @@ static int visornic_resume(struct visor_device *dev, */ static struct visor_driver visornic_driver = { .name = "visornic", - .version = "1.0.0.0", - .vertag = NULL, .owner = THIS_MODULE, .channel_types = visornic_channel_types, .probe = visornic_probe, -- cgit v0.10.2 From beedcc51b417126765cd0a8fc9b089b9bea58f08 Mon Sep 17 00:00:00 2001 From: Jon Frisch <jon.frisch@unisys.com> Date: Mon, 26 Sep 2016 11:03:42 -0400 Subject: staging: unisys: visorbus: remove driver version from visorchipset.c This patch removes the driver version and the version.h include from visorchipset.c Signed-off-by: Jon Frisch <jon.frisch@unisys.com> Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: David Kershner <david.kershner@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 39e8aca..fe3a773 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -25,7 +25,6 @@ #include <linux/uuid.h> #include <linux/crash_dump.h> -#include "version.h" #include "visorbus.h" #include "visorbus_private.h" #include "vmcallinterface.h" @@ -2264,6 +2263,4 @@ module_exit(exit_unisys); MODULE_AUTHOR("Unisys"); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Supervisor chipset driver for service partition: ver " - VERSION); -MODULE_VERSION(VERSION); +MODULE_DESCRIPTION("Supervisor chipset driver for service partition"); -- cgit v0.10.2 From 87932da6d3fe706be83033a421bd353f3606c7c7 Mon Sep 17 00:00:00 2001 From: Jon Frisch <jon.frisch@unisys.com> Date: Mon, 26 Sep 2016 11:03:43 -0400 Subject: staging: unisys: visorinput: remove driver version from visorinput.c This patch removes the driver version and the version.h include from visorinput.c Signed-off-by: Jon Frisch <jon.frisch@unisys.com> Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: David Kershner <david.kershner@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorinput/visorinput.c b/drivers/staging/unisys/visorinput/visorinput.c index 4e0b26d2..afdf2b5 100644 --- a/drivers/staging/unisys/visorinput/visorinput.c +++ b/drivers/staging/unisys/visorinput/visorinput.c @@ -29,7 +29,6 @@ #include <linux/kernel.h> #include <linux/uuid.h> -#include "version.h" #include "visorbus.h" #include "ultrainputreport.h" @@ -764,7 +763,6 @@ MODULE_DEVICE_TABLE(visorbus, visorinput_channel_types); MODULE_AUTHOR("Unisys"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("s-Par human input driver for guest Linux"); -MODULE_VERSION(VERSION); MODULE_ALIAS("visorbus:" SPAR_MOUSE_CHANNEL_PROTOCOL_UUID_STR); MODULE_ALIAS("visorbus:" SPAR_KEYBOARD_CHANNEL_PROTOCOL_UUID_STR); -- cgit v0.10.2 From deafd1855343a76dd1faf7f1b6bd469873063f71 Mon Sep 17 00:00:00 2001 From: Jon Frisch <jon.frisch@unisys.com> Date: Mon, 26 Sep 2016 11:03:44 -0400 Subject: staging: unisys: visornic: remove driver version from visornic_main.c This patch removes the driver version from visornic_main.c Signed-off-by: Jon Frisch <jon.frisch@unisys.com> Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: David Kershner <david.kershner@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index 7a58d2e..c001225 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -2096,5 +2096,4 @@ module_exit(visornic_cleanup); MODULE_AUTHOR("Unisys"); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("sPAR nic driver for sparlinux: ver 1.0.0.0"); -MODULE_VERSION("1.0.0.0"); +MODULE_DESCRIPTION("sPAR nic driver for sparlinux"); -- cgit v0.10.2 From 20cba4a6bbef122e17c52d687e9a674dcf6ff6b0 Mon Sep 17 00:00:00 2001 From: Jon Frisch <jon.frisch@unisys.com> Date: Mon, 26 Sep 2016 11:03:45 -0400 Subject: staging: unisys: remove version.h This patch removes version.h and the last version.h include in visorchannel.c. Signed-off-by: Jon Frisch <jon.frisch@unisys.com> Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: David Kershner <david.kershner@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/include/version.h b/drivers/staging/unisys/include/version.h deleted file mode 100644 index 83d1da7..0000000 --- a/drivers/staging/unisys/include/version.h +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -/* version.h */ - -/* Common version/release info needed by all components goes here. - * (This file must compile cleanly in all environments.) - * Ultimately, this will be combined with defines generated dynamically as - * part of the sysgen, and some of the defines below may in fact end up - * being replaced with dynamically generated ones. - */ -#ifndef __VERSION_H__ -#define __VERSION_H__ - -#define SPARVER1 "1" -#define SPARVER2 "0" -#define SPARVER3 "0" -#define SPARVER4 "0" - -#define VERSION SPARVER1 "." SPARVER2 "." SPARVER3 "." SPARVER4 - -/* Here are various version forms needed in Windows environments. - */ -#define VISOR_PRODUCTVERSION SPARVERCOMMA -#define VISOR_PRODUCTVERSION_STR SPARVER1 "." SPARVER2 "." SPARVER3 "." \ - SPARVER4 -#define VISOR_OBJECTVERSION_STR SPARVER1 "," SPARVER2 "," SPARVER3 "," \ - SPARVER4 - -#define COPYRIGHT "Unisys Corporation" -#define COPYRIGHTDATE "2010 - 2013" - -#endif diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c index b84c8d8..6cfd213 100644 --- a/drivers/staging/unisys/visorbus/visorchannel.c +++ b/drivers/staging/unisys/visorbus/visorchannel.c @@ -22,7 +22,6 @@ #include <linux/uuid.h> #include <linux/io.h> -#include "version.h" #include "visorbus.h" #include "controlvmchannel.h" -- cgit v0.10.2 From bff8c1a1604a73ce0e6d5182e441b97be563fcd4 Mon Sep 17 00:00:00 2001 From: Jon Frisch <jon.frisch@unisys.com> Date: Mon, 26 Sep 2016 11:03:46 -0400 Subject: staging: unisys: make MODULE_DESCRIPTIONs consistent This patch ensures that consistent verbiage is used in the MODULE_DESCRIPTION text (reported by 'modinfo') for all of the Unisys s-Par drivers. Signed-off-by: Jon Frisch <jon.frisch@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index fe3a773..e95d04d 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -2263,4 +2263,4 @@ module_exit(exit_unisys); MODULE_AUTHOR("Unisys"); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Supervisor chipset driver for service partition"); +MODULE_DESCRIPTION("s-Par visorbus driver for virtual device buses"); diff --git a/drivers/staging/unisys/visorhba/visorhba_main.c b/drivers/staging/unisys/visorhba/visorhba_main.c index 5ab5c3f..887be22 100644 --- a/drivers/staging/unisys/visorhba/visorhba_main.c +++ b/drivers/staging/unisys/visorhba/visorhba_main.c @@ -1220,4 +1220,4 @@ module_exit(visorhba_exit); MODULE_AUTHOR("Unisys"); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("s-Par hba driver"); +MODULE_DESCRIPTION("s-Par HBA driver for virtual SCSI host busses"); diff --git a/drivers/staging/unisys/visorinput/visorinput.c b/drivers/staging/unisys/visorinput/visorinput.c index afdf2b5..aa44414 100644 --- a/drivers/staging/unisys/visorinput/visorinput.c +++ b/drivers/staging/unisys/visorinput/visorinput.c @@ -762,7 +762,7 @@ MODULE_DEVICE_TABLE(visorbus, visorinput_channel_types); MODULE_AUTHOR("Unisys"); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("s-Par human input driver for guest Linux"); +MODULE_DESCRIPTION("s-Par human input driver for virtual keyboard/mouse"); MODULE_ALIAS("visorbus:" SPAR_MOUSE_CHANNEL_PROTOCOL_UUID_STR); MODULE_ALIAS("visorbus:" SPAR_KEYBOARD_CHANNEL_PROTOCOL_UUID_STR); diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index c001225..2b3ba49 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -2096,4 +2096,4 @@ module_exit(visornic_cleanup); MODULE_AUTHOR("Unisys"); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("sPAR nic driver for sparlinux"); +MODULE_DESCRIPTION("s-Par NIC driver for virtual network devices"); -- cgit v0.10.2 From 1306c429e2ce16d988a214456942b08f709a3e84 Mon Sep 17 00:00:00 2001 From: David Binder <david.binder@unisys.com> Date: Mon, 26 Sep 2016 11:03:47 -0400 Subject: staging: unisys: visorbus: Change support functions to integer return vals Per Documentation/CodingStyle, function names that convey an action or an imperative command should return an integer value. This commit changes several functions and a macro, internal to visorchannel.c, to follow this paradigm. These changes will be necessary later on to change other functions in this file, which are part of the visorbus API, to return integer values in lieu of a boolean. Signed-off-by: David Binder <david.binder@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c index 6cfd213..fe5a620 100644 --- a/drivers/staging/unisys/visorbus/visorchannel.c +++ b/drivers/staging/unisys/visorbus/visorchannel.c @@ -185,76 +185,66 @@ visorchannel_get_header(struct visorchannel *channel) * into host memory */ #define SIG_WRITE_FIELD(channel, queue, sig_hdr, FIELD) \ - (visorchannel_write(channel, \ - SIG_QUEUE_OFFSET(&channel->chan_hdr, queue) +\ - offsetof(struct signal_queue_header, FIELD), \ - &((sig_hdr)->FIELD), \ - sizeof((sig_hdr)->FIELD)) >= 0) + visorchannel_write(channel, \ + SIG_QUEUE_OFFSET(&channel->chan_hdr, queue) +\ + offsetof(struct signal_queue_header, FIELD), \ + &((sig_hdr)->FIELD), \ + sizeof((sig_hdr)->FIELD)) -static bool +static int sig_read_header(struct visorchannel *channel, u32 queue, struct signal_queue_header *sig_hdr) { - int err; - if (channel->chan_hdr.ch_space_offset < sizeof(struct channel_header)) - return false; + return -EINVAL; /* Read the appropriate SIGNAL_QUEUE_HEADER into local memory. */ - err = visorchannel_read(channel, - SIG_QUEUE_OFFSET(&channel->chan_hdr, queue), - sig_hdr, sizeof(struct signal_queue_header)); - if (err) - return false; - - return true; + return visorchannel_read(channel, + SIG_QUEUE_OFFSET(&channel->chan_hdr, queue), + sig_hdr, sizeof(struct signal_queue_header)); } -static inline bool +static inline int sig_read_data(struct visorchannel *channel, u32 queue, struct signal_queue_header *sig_hdr, u32 slot, void *data) { - int err; int signal_data_offset = SIG_DATA_OFFSET(&channel->chan_hdr, queue, sig_hdr, slot); - err = visorchannel_read(channel, signal_data_offset, - data, sig_hdr->signal_size); - if (err) - return false; - - return true; + return visorchannel_read(channel, signal_data_offset, + data, sig_hdr->signal_size); } -static inline bool +static inline int sig_write_data(struct visorchannel *channel, u32 queue, struct signal_queue_header *sig_hdr, u32 slot, void *data) { - int err; int signal_data_offset = SIG_DATA_OFFSET(&channel->chan_hdr, queue, sig_hdr, slot); - err = visorchannel_write(channel, signal_data_offset, - data, sig_hdr->signal_size); - if (err) - return false; - - return true; + return visorchannel_write(channel, signal_data_offset, + data, sig_hdr->signal_size); } -static bool +static int signalremove_inner(struct visorchannel *channel, u32 queue, void *msg) { struct signal_queue_header sig_hdr; + int error; + + error = sig_read_header(channel, queue, &sig_hdr); + if (error) + return error; - if (!sig_read_header(channel, queue, &sig_hdr)) - return false; if (sig_hdr.head == sig_hdr.tail) - return false; /* no signals to remove */ + return -EIO; /* no signals to remove */ sig_hdr.tail = (sig_hdr.tail + 1) % sig_hdr.max_slots; - if (!sig_read_data(channel, queue, &sig_hdr, sig_hdr.tail, msg)) - return false; + + error = sig_read_data(channel, queue, &sig_hdr, sig_hdr.tail, msg); + if (error) + return error; + sig_hdr.num_received++; /* @@ -262,11 +252,15 @@ signalremove_inner(struct visorchannel *channel, u32 queue, void *msg) * update host memory. */ mb(); /* required for channel synch */ - if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, tail)) - return false; - if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_received)) - return false; - return true; + + error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, tail); + if (error) + return error; + error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_received); + if (error) + return error; + + return 0; } /** @@ -292,7 +286,7 @@ visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg) rc = signalremove_inner(channel, queue, msg); } - return rc; + return !rc; } EXPORT_SYMBOL_GPL(visorchannel_signalremove); @@ -315,7 +309,7 @@ visorchannel_signalempty(struct visorchannel *channel, u32 queue) if (channel->needs_lock) spin_lock_irqsave(&channel->remove_lock, flags); - if (!sig_read_header(channel, queue, &sig_hdr)) + if (sig_read_header(channel, queue, &sig_hdr)) rc = true; if (sig_hdr.head == sig_hdr.tail) rc = true; @@ -326,13 +320,15 @@ visorchannel_signalempty(struct visorchannel *channel, u32 queue) } EXPORT_SYMBOL_GPL(visorchannel_signalempty); -static bool +static int signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg) { struct signal_queue_header sig_hdr; + int error; - if (!sig_read_header(channel, queue, &sig_hdr)) - return false; + error = sig_read_header(channel, queue, &sig_hdr); + if (error) + return error; sig_hdr.head = (sig_hdr.head + 1) % sig_hdr.max_slots; if (sig_hdr.head == sig_hdr.tail) { @@ -343,11 +339,12 @@ signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg) num_overflows), &sig_hdr.num_overflows, sizeof(sig_hdr.num_overflows)); - return false; + return -EIO; } - if (!sig_write_data(channel, queue, &sig_hdr, sig_hdr.head, msg)) - return false; + error = sig_write_data(channel, queue, &sig_hdr, sig_hdr.head, msg); + if (error) + return error; sig_hdr.num_sent++; @@ -356,12 +353,15 @@ signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg) * update host memory. */ mb(); /* required for channel synch */ - if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, head)) - return false; - if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_sent)) - return false; - return true; + error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, head); + if (error) + return error; + error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_sent); + if (error) + return error; + + return 0; } /** @@ -509,6 +509,6 @@ visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg) rc = signalinsert_inner(channel, queue, msg); } - return rc; + return !rc; } EXPORT_SYMBOL_GPL(visorchannel_signalinsert); -- cgit v0.10.2 From f621a96850c262b7de42bd06eae4edd5bfd099d8 Mon Sep 17 00:00:00 2001 From: David Binder <david.binder@unisys.com> Date: Mon, 26 Sep 2016 11:03:48 -0400 Subject: staging: unisys: visorbus: Convert visorchannel_signalremove() return val Per Documentation/CodingStyle, function names that convey an action or an imperative command should return an integer. This commit converts the visorbus API function, visorchannel_signalremove(), to returning integer values. All uses of this function are updated accordingly. Signed-off-by: David Binder <david.binder@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/include/visorbus.h b/drivers/staging/unisys/include/visorbus.h index 2e508c2..a4442c3 100644 --- a/drivers/staging/unisys/include/visorbus.h +++ b/drivers/staging/unisys/include/visorbus.h @@ -200,8 +200,8 @@ enum diag_severity { DIAG_SEVERITY_PRINT = 4, }; -bool visorchannel_signalremove(struct visorchannel *channel, u32 queue, - void *msg); +int visorchannel_signalremove(struct visorchannel *channel, u32 queue, + void *msg); bool visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg); bool visorchannel_signalempty(struct visorchannel *channel, u32 queue); diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c index fe5a620..70fcd1f 100644 --- a/drivers/staging/unisys/visorbus/visorchannel.c +++ b/drivers/staging/unisys/visorbus/visorchannel.c @@ -270,12 +270,12 @@ signalremove_inner(struct visorchannel *channel, u32 queue, void *msg) * @queue: the queue the message will be removed from * @msg: the message to remove * - * Return: boolean indicating whether the removal succeeded or failed + * Return: integer error code indicating the status of the removal */ -bool +int visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg) { - bool rc; + int rc; unsigned long flags; if (channel->needs_lock) { @@ -286,7 +286,7 @@ visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg) rc = signalremove_inner(channel, queue, msg); } - return !rc; + return rc; } EXPORT_SYMBOL_GPL(visorchannel_signalremove); diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index e95d04d..ed4eced 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -2000,8 +2000,8 @@ handle_command(struct controlvm_message inmsg, u64 channel_addr) static bool read_controlvm_event(struct controlvm_message *msg) { - if (visorchannel_signalremove(controlvm_channel, - CONTROLVM_QUEUE_EVENT, msg)) { + if (!visorchannel_signalremove(controlvm_channel, + CONTROLVM_QUEUE_EVENT, msg)) { /* got a message */ if (msg->hdr.flags.test_message == 1) return false; @@ -2048,9 +2048,9 @@ controlvm_periodic_work(struct work_struct *work) bool got_command = false; bool handle_command_failed = false; - while (visorchannel_signalremove(controlvm_channel, - CONTROLVM_QUEUE_RESPONSE, - &inmsg)) + while (!visorchannel_signalremove(controlvm_channel, + CONTROLVM_QUEUE_RESPONSE, + &inmsg)) ; if (!got_command) { if (controlvm_pending_msg_valid) { diff --git a/drivers/staging/unisys/visorhba/visorhba_main.c b/drivers/staging/unisys/visorhba/visorhba_main.c index 887be22..e968f33 100644 --- a/drivers/staging/unisys/visorhba/visorhba_main.c +++ b/drivers/staging/unisys/visorhba/visorhba_main.c @@ -927,9 +927,9 @@ drain_queue(struct uiscmdrsp *cmdrsp, struct visorhba_devdata *devdata) struct scsi_cmnd *scsicmd; while (1) { - if (!visorchannel_signalremove(devdata->dev->visorchannel, - IOCHAN_FROM_IOPART, - cmdrsp)) + if (visorchannel_signalremove(devdata->dev->visorchannel, + IOCHAN_FROM_IOPART, + cmdrsp)) break; /* queue empty */ if (cmdrsp->cmdtype == CMD_SCSI_TYPE) { diff --git a/drivers/staging/unisys/visorinput/visorinput.c b/drivers/staging/unisys/visorinput/visorinput.c index aa44414..6f94b64 100644 --- a/drivers/staging/unisys/visorinput/visorinput.c +++ b/drivers/staging/unisys/visorinput/visorinput.c @@ -581,7 +581,7 @@ visorinput_channel_interrupt(struct visor_device *dev) visorinput_dev = devdata->visorinput_dev; - while (visorchannel_signalremove(dev->visorchannel, 0, &r)) { + while (!visorchannel_signalremove(dev->visorchannel, 0, &r)) { scancode = r.activity.arg1; keycode = scancode_to_keycode(scancode); switch (r.activity.action) { diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index 2b3ba49..8e70b36 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -1539,9 +1539,9 @@ send_rcv_posts_if_needed(struct visornic_devdata *devdata) static void drain_resp_queue(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata) { - while (visorchannel_signalremove(devdata->dev->visorchannel, - IOCHAN_FROM_IOPART, - cmdrsp)) + while (!visorchannel_signalremove(devdata->dev->visorchannel, + IOCHAN_FROM_IOPART, + cmdrsp)) ; } @@ -1565,9 +1565,9 @@ service_resp_queue(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata, /* TODO: CLIENT ACQUIRE -- Don't really need this at the * moment */ - if (!visorchannel_signalremove(devdata->dev->visorchannel, - IOCHAN_FROM_IOPART, - cmdrsp)) + if (visorchannel_signalremove(devdata->dev->visorchannel, + IOCHAN_FROM_IOPART, + cmdrsp)) break; /* queue empty */ switch (cmdrsp->net.type) { -- cgit v0.10.2 From 264f7b8ac3ec3e7a38affd8140da30f8720b5946 Mon Sep 17 00:00:00 2001 From: David Binder <david.binder@unisys.com> Date: Mon, 26 Sep 2016 11:03:49 -0400 Subject: staging: unisys: visorbus: Convert visorchannel_signalinsert() return val Per Documentation/CodingStyle, function names that convey an action or an imperative command should return an integer. This commit converts the visorbus API function, visorchannel_signalinsert(), to returning integer values. All uses of this function are updated accordingly. Signed-off-by: David Binder <david.binder@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/include/visorbus.h b/drivers/staging/unisys/include/visorbus.h index a4442c3..677627c 100644 --- a/drivers/staging/unisys/include/visorbus.h +++ b/drivers/staging/unisys/include/visorbus.h @@ -202,8 +202,8 @@ enum diag_severity { int visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg); -bool visorchannel_signalinsert(struct visorchannel *channel, u32 queue, - void *msg); +int visorchannel_signalinsert(struct visorchannel *channel, u32 queue, + void *msg); bool visorchannel_signalempty(struct visorchannel *channel, u32 queue); uuid_le visorchannel_get_uuid(struct visorchannel *channel); diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c index 70fcd1f..300a65d 100644 --- a/drivers/staging/unisys/visorbus/visorchannel.c +++ b/drivers/staging/unisys/visorbus/visorchannel.c @@ -493,12 +493,12 @@ visorchannel_create_with_lock(u64 physaddr, unsigned long channel_bytes, * @queue: the queue the message will be added to * @msg: the message to insert * - * Return: boolean indicating whether the insertion succeeded or failed + * Return: integer error code indicating the status of the insertion */ -bool +int visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg) { - bool rc; + int rc; unsigned long flags; if (channel->needs_lock) { @@ -509,6 +509,6 @@ visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg) rc = signalinsert_inner(channel, queue, msg); } - return !rc; + return rc; } EXPORT_SYMBOL_GPL(visorchannel_signalinsert); diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index ed4eced..5987149 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -508,8 +508,8 @@ controlvm_respond_chipset_init(struct controlvm_message_header *msg_hdr, controlvm_init_response(&outmsg, msg_hdr, response); outmsg.cmd.init_chipset.features = features; - if (!visorchannel_signalinsert(controlvm_channel, - CONTROLVM_QUEUE_REQUEST, &outmsg)) { + if (visorchannel_signalinsert(controlvm_channel, + CONTROLVM_QUEUE_REQUEST, &outmsg)) { return; } } @@ -557,8 +557,8 @@ controlvm_respond(struct controlvm_message_header *msg_hdr, int response) if (outmsg.hdr.flags.test_message == 1) return; - if (!visorchannel_signalinsert(controlvm_channel, - CONTROLVM_QUEUE_REQUEST, &outmsg)) { + if (visorchannel_signalinsert(controlvm_channel, + CONTROLVM_QUEUE_REQUEST, &outmsg)) { return; } } @@ -572,8 +572,8 @@ static void controlvm_respond_physdev_changestate( controlvm_init_response(&outmsg, msg_hdr, response); outmsg.cmd.device_change_state.state = state; outmsg.cmd.device_change_state.flags.phys_device = 1; - if (!visorchannel_signalinsert(controlvm_channel, - CONTROLVM_QUEUE_REQUEST, &outmsg)) { + if (visorchannel_signalinsert(controlvm_channel, + CONTROLVM_QUEUE_REQUEST, &outmsg)) { return; } } @@ -670,8 +670,8 @@ device_changestate_responder(enum controlvm_id cmd_id, outmsg.cmd.device_change_state.dev_no = dev_no; outmsg.cmd.device_change_state.state = response_state; - if (!visorchannel_signalinsert(controlvm_channel, - CONTROLVM_QUEUE_REQUEST, &outmsg)) + if (visorchannel_signalinsert(controlvm_channel, + CONTROLVM_QUEUE_REQUEST, &outmsg)) return; } diff --git a/drivers/staging/unisys/visorhba/visorhba_main.c b/drivers/staging/unisys/visorhba/visorhba_main.c index e968f33..5a7a87e 100644 --- a/drivers/staging/unisys/visorhba/visorhba_main.c +++ b/drivers/staging/unisys/visorhba/visorhba_main.c @@ -335,9 +335,9 @@ static int forward_taskmgmt_command(enum task_mgmt_types tasktype, dev_dbg(&scsidev->sdev_gendev, "visorhba: initiating type=%d taskmgmt command\n", tasktype); - if (!visorchannel_signalinsert(devdata->dev->visorchannel, - IOCHAN_TO_IOPART, - cmdrsp)) + if (visorchannel_signalinsert(devdata->dev->visorchannel, + IOCHAN_TO_IOPART, + cmdrsp)) goto err_del_scsipending_ent; /* It can take the Service Partition up to 35 seconds to complete @@ -538,9 +538,9 @@ visorhba_queue_command_lck(struct scsi_cmnd *scsicmd, } cmdrsp->scsi.guest_phys_entries = scsi_sg_count(scsicmd); - if (!visorchannel_signalinsert(devdata->dev->visorchannel, - IOCHAN_TO_IOPART, - cmdrsp)) + if (visorchannel_signalinsert(devdata->dev->visorchannel, + IOCHAN_TO_IOPART, + cmdrsp)) /* queue must be full and we aren't going to wait */ goto err_del_scsipending_ent; diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index 8e70b36..1367007 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -386,9 +386,9 @@ post_skb(struct uiscmdrsp *cmdrsp, if ((cmdrsp->net.rcvpost.frag.pi_off + skb->len) <= PI_PAGE_SIZE) { cmdrsp->net.type = NET_RCV_POST; cmdrsp->cmdtype = CMD_NET_TYPE; - if (visorchannel_signalinsert(devdata->dev->visorchannel, - IOCHAN_TO_IOPART, - cmdrsp)) { + if (!visorchannel_signalinsert(devdata->dev->visorchannel, + IOCHAN_TO_IOPART, + cmdrsp)) { atomic_inc(&devdata->num_rcvbuf_in_iovm); devdata->chstat.sent_post++; } else { @@ -415,9 +415,9 @@ send_enbdis(struct net_device *netdev, int state, devdata->cmdrsp_rcv->net.enbdis.context = netdev; devdata->cmdrsp_rcv->net.type = NET_RCV_ENBDIS; devdata->cmdrsp_rcv->cmdtype = CMD_NET_TYPE; - if (visorchannel_signalinsert(devdata->dev->visorchannel, - IOCHAN_TO_IOPART, - devdata->cmdrsp_rcv)) + if (!visorchannel_signalinsert(devdata->dev->visorchannel, + IOCHAN_TO_IOPART, + devdata->cmdrsp_rcv)) devdata->chstat.sent_enbdis++; } @@ -881,8 +881,8 @@ visornic_xmit(struct sk_buff *skb, struct net_device *netdev) return NETDEV_TX_OK; } - if (!visorchannel_signalinsert(devdata->dev->visorchannel, - IOCHAN_TO_IOPART, cmdrsp)) { + if (visorchannel_signalinsert(devdata->dev->visorchannel, + IOCHAN_TO_IOPART, cmdrsp)) { netif_stop_queue(netdev); spin_unlock_irqrestore(&devdata->priv_lock, flags); devdata->busy_cnt++; -- cgit v0.10.2 From ca8b3fa7ea44738f02979dfdc72a1d75a27dcddb Mon Sep 17 00:00:00 2001 From: Wei Yongjun <weiyongjun1@huawei.com> Date: Sun, 25 Sep 2016 15:41:11 +0000 Subject: staging: most: fix error return code in audio_probe_channel() Fix to return a negative error code from the audio_set_hw_params() error handling case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com> Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de> Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/aim-sound/sound.c b/drivers/staging/most/aim-sound/sound.c index 3dc625c..00f01c9 100644 --- a/drivers/staging/most/aim-sound/sound.c +++ b/drivers/staging/most/aim-sound/sound.c @@ -607,7 +607,8 @@ static int audio_probe_channel(struct most_interface *iface, int channel_id, channel->id = channel_id; init_waitqueue_head(&channel->playback_waitq); - if (audio_set_hw_params(&channel->pcm_hardware, pcm_format, cfg)) + ret = audio_set_hw_params(&channel->pcm_hardware, pcm_format, cfg); + if (ret) goto err_free_card; snprintf(card->driver, sizeof(card->driver), "%s", DRIVER_NAME); -- cgit v0.10.2 From cfb459edaa91d624e42a959f0356d341a3347c76 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal <bhumirks@gmail.com> Date: Mon, 26 Sep 2016 23:09:03 +0530 Subject: Staging: most: aim-sound: constify snd_pcm_ops structures Check for snd_pcm_ops structures that are only passed as the third argument to the function snd_pcm_set_ops. As this argument is constant, so snd_pcm_ops structures having this property can also be made constant. Done using coccinelle: @r1 disable optional_qualifier @ identifier i; position p; @@ static struct snd_pcm_ops i@p = {...}; @ok1@ identifier r1.i; position p; expression e1,e2; @@ snd_pcm_set_ops(e1,e2,&i@p) @bad@ position p!={r1.p,ok1.p}; identifier r1.i; @@ i@p @depends on !bad disable optional_qualifier@ identifier r1.i; @@ static +const struct snd_pcm_ops i={...}; @depends on !bad disable optional_qualifier@ identifier r1.i; @@ +const struct snd_pcm_ops i; File size before: text data bss dec hex filename 4963 192 16 5171 1433 drivers/staging/most/aim-sound/sound.o File size after: text data bss dec hex filename 5075 64 16 5155 1423 drivers/staging/most/aim-sound/sound.o Signed-off-by: Bhumika Goyal <bhumirks@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/aim-sound/sound.c b/drivers/staging/most/aim-sound/sound.c index 00f01c9..e4198e5 100644 --- a/drivers/staging/most/aim-sound/sound.c +++ b/drivers/staging/most/aim-sound/sound.c @@ -453,7 +453,7 @@ static snd_pcm_uframes_t pcm_pointer(struct snd_pcm_substream *substream) /** * Initialization of struct snd_pcm_ops */ -static struct snd_pcm_ops pcm_ops = { +static const struct snd_pcm_ops pcm_ops = { .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, -- cgit v0.10.2 From af2708f5e8a82ddad80ff3f32102defd4ffd87d7 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal <bhumirks@gmail.com> Date: Tue, 27 Sep 2016 14:47:12 +0530 Subject: Staging: most: aim-v4l2: constify v4l2_file_operations structures Check for v4l2_file_operations structures that are only stored in the fops field of video_device structures. As this field is constant, so v4l2_file_operations structures having this property can also be declared constant. Done using coccinelle: @r1 disable optional_qualifier @ identifier i; position p; @@ static struct v4l2_file_operations i@p = {...}; @ok1@ identifier r1.i; position p; struct video_device x; @@ x.fops=&i@p; @bad@ position p!={r1.p,ok1.p}; identifier r1.i; @@ i@p @depends on !bad disable optional_qualifier@ identifier r1.i; @@ static +const struct v4l2_file_operations i={...}; @depends on !bad disable optional_qualifier@ identifier r1.i; @@ +const struct v4l2_file_operations i; File size before: text data bss dec hex filename 5608 160 4 5772 168c drivers/staging/most/aim-v4l2/video.o File size after: text data bss dec hex filename 5696 96 4 5796 16a4 drivers/staging/most/aim-v4l2/video.o Signed-off-by: Bhumika Goyal <bhumirks@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/aim-v4l2/video.c b/drivers/staging/most/aim-v4l2/video.c index 400f727..e074841 100644 --- a/drivers/staging/most/aim-v4l2/video.c +++ b/drivers/staging/most/aim-v4l2/video.c @@ -369,7 +369,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index) return 0; } -static struct v4l2_file_operations aim_fops = { +static const struct v4l2_file_operations aim_fops = { .owner = THIS_MODULE, .open = aim_vdev_open, .release = aim_vdev_close, -- cgit v0.10.2 From 896075a684a91ac8282c36bf5cc43c3feeec5623 Mon Sep 17 00:00:00 2001 From: Grygorii Maistrenko <grygoriimkd@gmail.com> Date: Mon, 26 Sep 2016 19:56:28 +0300 Subject: staging: slicoss: cleaning up codestyle warnings This removes checkpatch.pl warnings: WARNING: Block comments should align the * on each line Signed-off-by: Grygorii Maistrenko <grygoriimkd@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/slicoss/slic.h b/drivers/staging/slicoss/slic.h index 6d28539..420546d 100644 --- a/drivers/staging/slicoss/slic.h +++ b/drivers/staging/slicoss/slic.h @@ -224,8 +224,8 @@ struct mcast_address { struct slic_iface_stats { /* - * Stats - */ + * Stats + */ u64 xmt_bytes; u64 xmt_ucast; u64 xmt_mcast; @@ -469,8 +469,8 @@ struct adapter { struct slic_cmdqueue cmdq_all; struct slic_cmdqmem cmdqmem; /* - * SLIC Handles - */ + * SLIC Handles + */ /* Object handles*/ struct slic_handle slic_handles[SLIC_CMDQ_MAXCMDS + 1]; /* Free object handles*/ -- cgit v0.10.2 From 8abcae443af7b502831faa302b1bed7e765234e1 Mon Sep 17 00:00:00 2001 From: Eric Salem <ericsalem@gmail.com> Date: Sun, 25 Sep 2016 22:33:34 -0500 Subject: Staging: android: fixed permissions style issue Fixed a coding style issue. Changed symbolic permissions to octal. Signed-off-by: Eric Salem <ericsalem@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index 80d7adf..ec3b665 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -204,10 +204,9 @@ device_initcall(lowmem_init); * not really modular, but the easiest way to keep compat with existing * bootargs behaviour is to continue using module_param here. */ -module_param_named(cost, lowmem_shrinker.seeks, int, S_IRUGO | S_IWUSR); -module_param_array_named(adj, lowmem_adj, short, &lowmem_adj_size, - S_IRUGO | S_IWUSR); +module_param_named(cost, lowmem_shrinker.seeks, int, 0644); +module_param_array_named(adj, lowmem_adj, short, &lowmem_adj_size, 0644); module_param_array_named(minfree, lowmem_minfree, uint, &lowmem_minfree_size, - S_IRUGO | S_IWUSR); -module_param_named(debug_level, lowmem_debug_level, uint, S_IRUGO | S_IWUSR); + 0644); +module_param_named(debug_level, lowmem_debug_level, uint, 0644); -- cgit v0.10.2 From 3d44a78f0d8b7128221e19cf10d506010df20b59 Mon Sep 17 00:00:00 2001 From: Namrata A Shettar <namrataashettar@gmail.com> Date: Mon, 26 Sep 2016 00:05:49 +0530 Subject: staging: rtl8712: Remove unnecessary 'else' Remove unnecessary 'else' after 'return' to resolve checkpatch issue. Signed-off-by: Namrata A Shettar <namrataashettar@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index 66f0e0a..cf46592 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -508,8 +508,7 @@ static int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl, plist = plist->next; else if (SN_EQUAL(pnextattrib->seq_num, pattrib->seq_num)) return false; - else - break; + break; } list_del_init(&(prframe->u.hdr.list)); list_add_tail(&(prframe->u.hdr.list), plist); -- cgit v0.10.2 From 06a4f429bfa20d22c1385a35656206301ac2e672 Mon Sep 17 00:00:00 2001 From: Moshe Green <mgmoshes@gmail.com> Date: Sun, 25 Sep 2016 22:58:35 +0300 Subject: staging: sm750fb: rename getChipType to sm750_get_chip_type Rename CamelCased function getChipType to sm750_get_chip_type (prefex with sm750 in order to make the context of the function clear). This issue was found by checkpatch.pl Signed-off-by: Moshe Green <mgmoshes@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index a887f32..3a0afe1 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -10,7 +10,7 @@ #define roundedDiv(num, denom) ((2 * (num) + (denom)) / (2 * (denom))) #define MHz(x) ((x) * 1000000) -logical_chip_type_t getChipType(void) +logical_chip_type_t sm750_get_chip_type(void) { unsigned short physicalID; char physicalRev; @@ -37,7 +37,7 @@ static unsigned int get_mxclk_freq(void) unsigned int pll_reg; unsigned int M, N, OD, POD; - if (getChipType() == SM750LE) + if (sm750_get_chip_type() == SM750LE) return MHz(130); pll_reg = PEEK32(MXCLK_PLL_CTRL); @@ -60,7 +60,7 @@ static void setChipClock(unsigned int frequency) unsigned int ulActualMxClk; /* Cheok_0509: For SM750LE, the chip clock is fixed. Nothing to set. */ - if (getChipType() == SM750LE) + if (sm750_get_chip_type() == SM750LE) return; if (frequency) { @@ -90,7 +90,7 @@ static void setMemoryClock(unsigned int frequency) /* Cheok_0509: For SM750LE, the memory clock is fixed. * Nothing to set. */ - if (getChipType() == SM750LE) + if (sm750_get_chip_type() == SM750LE) return; if (frequency) { @@ -141,7 +141,7 @@ static void setMasterClock(unsigned int frequency) /* Cheok_0509: For SM750LE, the memory clock is fixed. * Nothing to set. */ - if (getChipType() == SM750LE) + if (sm750_get_chip_type() == SM750LE) return; if (frequency) { @@ -182,7 +182,7 @@ unsigned int ddk750_getVMSize(void) unsigned int data; /* sm750le only use 64 mb memory*/ - if (getChipType() == SM750LE) + if (sm750_get_chip_type() == SM750LE) return SZ_64M; /* for 750,always use power mode0*/ @@ -221,7 +221,7 @@ int ddk750_initHw(initchip_param_t *pInitParam) reg |= (CURRENT_GATE_DISPLAY | CURRENT_GATE_LOCALMEM); setCurrentGate(reg); - if (getChipType() != SM750LE) { + if (sm750_get_chip_type() != SM750LE) { /* set panel pll and graphic mode via mmio_88 */ reg = PEEK32(VGA_CONFIGURATION); reg |= (VGA_CONFIGURATION_PLL | VGA_CONFIGURATION_MODE); @@ -320,7 +320,7 @@ unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll) const int max_OD = 3; int max_d = 6; - if (getChipType() == SM750LE) { + if (sm750_get_chip_type() == SM750LE) { /* SM750LE don't have * programmable PLL and M/N values to work on. * Just return the requested clock. diff --git a/drivers/staging/sm750fb/ddk750_chip.h b/drivers/staging/sm750fb/ddk750_chip.h index 0891384..14357fd 100644 --- a/drivers/staging/sm750fb/ddk750_chip.h +++ b/drivers/staging/sm750fb/ddk750_chip.h @@ -69,7 +69,7 @@ typedef struct _initchip_param_t { } initchip_param_t; -logical_chip_type_t getChipType(void); +logical_chip_type_t sm750_get_chip_type(void); unsigned int calcPllValue(unsigned int request, pll_value_t *pll); unsigned int formatPllReg(pll_value_t *pPLL); void ddk750_set_mmio(void __iomem *, unsigned short, char); diff --git a/drivers/staging/sm750fb/ddk750_mode.c b/drivers/staging/sm750fb/ddk750_mode.c index e29d4bd..b767c7d 100644 --- a/drivers/staging/sm750fb/ddk750_mode.c +++ b/drivers/staging/sm750fb/ddk750_mode.c @@ -117,7 +117,7 @@ static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll) if (pModeParam->horizontal_sync_polarity) tmp |= DISPLAY_CTRL_HSYNC_PHASE; - if (getChipType() == SM750LE) { + if (sm750_get_chip_type() == SM750LE) { displayControlAdjust_SM750LE(pModeParam, tmp); } else { reg = PEEK32(CRT_DISPLAY_CTRL) & @@ -209,7 +209,7 @@ int ddk750_setModeTiming(mode_parameter_t *parm, clock_type_t clock) pll.clockType = clock; uiActualPixelClk = calcPllValue(parm->pixel_clock, &pll); - if (getChipType() == SM750LE) { + if (sm750_get_chip_type() == SM750LE) { /* set graphic mode via IO method */ outb_p(0x88, 0x3d4); outb_p(0x06, 0x3d5); diff --git a/drivers/staging/sm750fb/ddk750_power.c b/drivers/staging/sm750fb/ddk750_power.c index b3c3791..7cc6169 100644 --- a/drivers/staging/sm750fb/ddk750_power.c +++ b/drivers/staging/sm750fb/ddk750_power.c @@ -6,7 +6,7 @@ void ddk750_setDPMS(DPMS_t state) { unsigned int value; - if (getChipType() == SM750LE) { + if (sm750_get_chip_type() == SM750LE) { value = PEEK32(CRT_DISPLAY_CTRL) & ~CRT_DISPLAY_CTRL_DPMS_MASK; value |= (state << CRT_DISPLAY_CTRL_DPMS_SHIFT); POKE32(CRT_DISPLAY_CTRL, value); @@ -19,7 +19,7 @@ void ddk750_setDPMS(DPMS_t state) static unsigned int getPowerMode(void) { - if (getChipType() == SM750LE) + if (sm750_get_chip_type() == SM750LE) return 0; return PEEK32(POWER_MODE_CTRL) & POWER_MODE_CTRL_MODE_MASK; } @@ -35,7 +35,7 @@ void setPowerMode(unsigned int powerMode) control_value = PEEK32(POWER_MODE_CTRL) & ~POWER_MODE_CTRL_MODE_MASK; - if (getChipType() == SM750LE) + if (sm750_get_chip_type() == SM750LE) return; switch (powerMode) { diff --git a/drivers/staging/sm750fb/ddk750_swi2c.c b/drivers/staging/sm750fb/ddk750_swi2c.c index 8d644a7..6c1ffa1 100644 --- a/drivers/staging/sm750fb/ddk750_swi2c.c +++ b/drivers/staging/sm750fb/ddk750_swi2c.c @@ -403,7 +403,7 @@ long sm750_sw_i2c_init( if ((clk_gpio > 31) || (data_gpio > 31)) return -1; - if (getChipType() == SM750LE) + if (sm750_get_chip_type() == SM750LE) return sm750le_i2c_init(clk_gpio, data_gpio); /* Initialize the GPIO pin for the i2c Clock Register */ diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index bff7db5..7dd208c 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -91,7 +91,7 @@ int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev) parm = &sm750_dev->initParm; if (parm->chip_clk == 0) - parm->chip_clk = (getChipType() == SM750LE) ? + parm->chip_clk = (sm750_get_chip_type() == SM750LE) ? DEFAULT_SM750LE_CHIP_CLOCK : DEFAULT_SM750_CHIP_CLOCK; @@ -107,7 +107,7 @@ int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev) PEEK32(SYSTEM_CTRL) | SYSTEM_CTRL_PCI_BURST); } - if (getChipType() != SM750LE) { + if (sm750_get_chip_type() != SM750LE) { unsigned int val; /* does user need CRT? */ if (sm750_dev->nocrt) { @@ -183,7 +183,7 @@ int hw_sm750_output_setMode(struct lynxfb_output *output, dispSet = 0; channel = *output->channel; - if (getChipType() != SM750LE) { + if (sm750_get_chip_type() != SM750LE) { if (channel == sm750_primary) { pr_info("primary channel\n"); if (output->paths & sm750_panel) @@ -471,7 +471,7 @@ void hw_sm750_initAccel(struct sm750_dev *sm750_dev) enable2DEngine(1); - if (getChipType() == SM750LE) { + if (sm750_get_chip_type() == SM750LE) { reg = PEEK32(DE_STATE1); reg |= DE_STATE1_DE_ABORT; POKE32(DE_STATE1, reg); -- cgit v0.10.2 From e2ba2cb3278c5f15240ea4c05639a318e4f90128 Mon Sep 17 00:00:00 2001 From: Namrata A Shettar <namrataashettar@gmail.com> Date: Sat, 24 Sep 2016 21:30:04 +0530 Subject: staging: media: lirc: Remove multiple blank lines Remove multiple blank lines to resolve checkpatch issue. Signed-off-by: Namrata A Shettar <namrataashettar@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/media/lirc/lirc_bt829.c b/drivers/staging/media/lirc/lirc_bt829.c index f740115..06eac71 100644 --- a/drivers/staging/media/lirc/lirc_bt829.c +++ b/drivers/staging/media/lirc/lirc_bt829.c @@ -163,7 +163,6 @@ err_put_dev: return rc; } - void cleanup_module(void) { struct pci_dev *pdev = to_pci_dev(atir_driver.dev); @@ -174,7 +173,6 @@ void cleanup_module(void) pci_dev_put(pdev); } - static int atir_init_start(void) { pci_addr_lin = ioremap(pci_addr_phys + DATA_PCI_OFF, 0x400); @@ -190,7 +188,6 @@ static void cycle_delay(int cycle) udelay(WAIT_CYCLE*cycle); } - static int poll_main(void) { unsigned char status_high, status_low; -- cgit v0.10.2 From d85549a80b3d9d9dfa6922c80034ad78c7587ce2 Mon Sep 17 00:00:00 2001 From: Namrata A Shettar <namrataashettar@gmail.com> Date: Sat, 24 Sep 2016 21:30:20 +0530 Subject: staging: media: lirc: Add space around '*' Add space around '*' to resolve checkpatch issue. Signed-off-by: Namrata A Shettar <namrataashettar@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/media/lirc/lirc_bt829.c b/drivers/staging/media/lirc/lirc_bt829.c index 06eac71..04d881b 100644 --- a/drivers/staging/media/lirc/lirc_bt829.c +++ b/drivers/staging/media/lirc/lirc_bt829.c @@ -185,7 +185,7 @@ static int atir_init_start(void) static void cycle_delay(int cycle) { - udelay(WAIT_CYCLE*cycle); + udelay(WAIT_CYCLE * cycle); } static int poll_main(void) -- cgit v0.10.2 From 46c539054ecf5b1f4d1e3be07ddfdef5c88cd53c Mon Sep 17 00:00:00 2001 From: Namrata A Shettar <namrataashettar@gmail.com> Date: Sat, 24 Sep 2016 21:30:42 +0530 Subject: staging: media: lirc: Replace data type with pointer of same type Replace data type with pointer of same type in sizeof() to resolve checkpatch issue. Signed-off-by: Namrata A Shettar <namrataashettar@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/media/lirc/lirc_imon.c b/drivers/staging/media/lirc/lirc_imon.c index b1c28e5..198a805 100644 --- a/drivers/staging/media/lirc/lirc_imon.c +++ b/drivers/staging/media/lirc/lirc_imon.c @@ -702,7 +702,7 @@ static int imon_probe(struct usb_interface *interface, /* prevent races probing devices w/multiple interfaces */ mutex_lock(&driver_lock); - context = kzalloc(sizeof(struct imon_context), GFP_KERNEL); + context = kzalloc(sizeof(*context), GFP_KERNEL); if (!context) goto driver_unlock; @@ -782,11 +782,11 @@ static int imon_probe(struct usb_interface *interface, __func__, vfd_proto_6p); } - driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); + driver = kzalloc(sizeof(*driver), GFP_KERNEL); if (!driver) goto free_context; - rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); + rbuf = kmalloc(sizeof(*rbuf), GFP_KERNEL); if (!rbuf) goto free_driver; -- cgit v0.10.2 From a0ba7fcf6a98936afb43acd0a4070b4b0e95bb8e Mon Sep 17 00:00:00 2001 From: Namrata A Shettar <namrataashettar@gmail.com> Date: Sat, 24 Sep 2016 21:31:23 +0530 Subject: staging: media: lirc: Convert 'unsigned' to 'unsigned int' Mention data type along with the variable to resolve checkpatch issue. Signed-off-by: Namrata A Shettar <namrataashettar@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/media/lirc/lirc_sasem.c b/drivers/staging/media/lirc/lirc_sasem.c index b080fde..9eb1eec 100644 --- a/drivers/staging/media/lirc/lirc_sasem.c +++ b/drivers/staging/media/lirc/lirc_sasem.c @@ -73,7 +73,7 @@ static void usb_tx_callback(struct urb *urb); /* VFD file_operations function prototypes */ static int vfd_open(struct inode *inode, struct file *file); -static long vfd_ioctl(struct file *file, unsigned cmd, unsigned long arg); +static long vfd_ioctl(struct file *file, unsigned int cmd, unsigned long arg); static int vfd_close(struct inode *inode, struct file *file); static ssize_t vfd_write(struct file *file, const char __user *buf, size_t n_bytes, loff_t *pos); @@ -243,7 +243,7 @@ exit: * Called when the VFD device (e.g. /dev/usb/lcd) * is closed by the application. */ -static long vfd_ioctl(struct file *file, unsigned cmd, unsigned long arg) +static long vfd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct sasem_context *context; -- cgit v0.10.2 From e95557654167bbf8005a38957f4cf69550db5d35 Mon Sep 17 00:00:00 2001 From: Namrata A Shettar <namrataashettar@gmail.com> Date: Sun, 25 Sep 2016 17:17:57 +0530 Subject: staging: media: lirc: Remove unnecessary blank lines Remove unneccessary blank lines to resolve checkpatch issue. Signed-off-by: Namrata A Shettar <namrataashettar@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/media/lirc/lirc_sasem.c b/drivers/staging/media/lirc/lirc_sasem.c index 9eb1eec..65b7bd4 100644 --- a/drivers/staging/media/lirc/lirc_sasem.c +++ b/drivers/staging/media/lirc/lirc_sasem.c @@ -47,7 +47,6 @@ #include <media/lirc.h> #include <media/lirc_dev.h> - #define MOD_AUTHOR "Oliver Stabel <oliver.stabel@gmx.de>, " \ "Tim Davies <tim@opensystems.net.au>" #define MOD_DESC "USB Driver for Sasem Remote Controller V1.1" @@ -86,7 +85,6 @@ static void ir_close(void *data); #define SASEM_DATA_BUF_SZ 32 struct sasem_context { - struct usb_device *dev; int vfd_isopen; /* VFD port has been opened */ unsigned int vfd_contrast; /* VFD contrast */ @@ -156,7 +154,6 @@ static int debug; /*** M O D U L E C O D E ***/ - MODULE_AUTHOR(MOD_AUTHOR); MODULE_DESCRIPTION(MOD_DESC); MODULE_LICENSE("GPL"); @@ -186,7 +183,6 @@ static void deregister_from_lirc(struct sasem_context *context) else dev_info(&context->dev->dev, "Deregistered Sasem driver (minor:%d)\n", minor); - } /** @@ -297,7 +293,6 @@ static int vfd_close(struct inode *inode, struct file *file) context->vfd_isopen = 0; dev_info(&context->dev->dev, "VFD port closed\n"); if (!context->dev_present && !context->ir_isopen) { - /* Device disconnected before close and IR port is * not open. If IR port is open, context will be * deleted by ir_close. */ @@ -546,9 +541,7 @@ static void ir_close(void *data) * at disconnect time, so do it now. */ deregister_from_lirc(context); - if (!context->vfd_isopen) { - mutex_unlock(&context->ctx_lock); delete_context(context); return; @@ -633,7 +626,6 @@ static void usb_rx_callback(struct urb *urb) return; switch (urb->status) { - case -ENOENT: /* usbcore unlink successful! */ return; @@ -651,8 +643,6 @@ static void usb_rx_callback(struct urb *urb) usb_submit_urb(context->rx_urb, GFP_ATOMIC); } - - /** * Callback function for USB core API: Probe */ @@ -709,7 +699,6 @@ static int sasem_probe(struct usb_interface *interface, } else if (!vfd_ep_found && usb_endpoint_is_int_out(ep)) { - tx_endpoint = ep; vfd_ep_found = 1; if (debug) -- cgit v0.10.2 From cc1c1c141cc6747f0051cccd377e47cd2bda9b3e Mon Sep 17 00:00:00 2001 From: Daeseok Youn <daeseok.youn@gmail.com> Date: Mon, 26 Sep 2016 09:37:51 +0900 Subject: staging: dgnc: remove redundant initialization for channel array The channel array in board_t was initialized in dgnc_found_board() with NULL. But the channel is going to initialize in dgnc_tty_init(). So the channel array doesn't need to set NULL for initailization. Signed-off-by: Daeseok Youn <daeseok.youn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c index 01e948c..b598034 100644 --- a/drivers/staging/dgnc/dgnc_driver.c +++ b/drivers/staging/dgnc/dgnc_driver.c @@ -400,9 +400,6 @@ static int dgnc_found_board(struct pci_dev *pdev, int id) brd->state = BOARD_FOUND; - for (i = 0; i < MAXPORTS; i++) - brd->channels[i] = NULL; - /* store which card & revision we have */ pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &brd->subvendor); pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &brd->subdevice); -- cgit v0.10.2 From f530834ef4d99ed2c6d8cb435a739a2a8167574a Mon Sep 17 00:00:00 2001 From: Daeseok Youn <daeseok.youn@gmail.com> Date: Mon, 26 Sep 2016 09:38:48 +0900 Subject: staging: dgnc: remove useless message buffer There is a temporary message buffer for the boot message in dgnc_found_board() but the buffer was not used anywhere in dgnc driver. Signed-off-by: Daeseok Youn <daeseok.youn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c index b598034..c87b3de 100644 --- a/drivers/staging/dgnc/dgnc_driver.c +++ b/drivers/staging/dgnc/dgnc_driver.c @@ -324,17 +324,6 @@ static void dgnc_cleanup_board(struct dgnc_board *brd) brd->re_map_membase = NULL; } - if (brd->msgbuf_head) { - unsigned long flags; - - spin_lock_irqsave(&dgnc_global_lock, flags); - brd->msgbuf = NULL; - dev_dbg(&brd->pdev->dev, "%s\n", brd->msgbuf_head); - kfree(brd->msgbuf_head); - brd->msgbuf_head = NULL; - spin_unlock_irqrestore(&dgnc_global_lock, flags); - } - /* Free all allocated channels structs */ for (i = 0; i < MAXPORTS ; i++) { if (brd->channels[i]) { @@ -362,7 +351,6 @@ static int dgnc_found_board(struct pci_dev *pdev, int id) unsigned int pci_irq; int i = 0; int rc = 0; - unsigned long flags; /* get the board structure and prep it */ dgnc_board[dgnc_num_boards] = kzalloc(sizeof(*brd), GFP_KERNEL); @@ -371,15 +359,6 @@ static int dgnc_found_board(struct pci_dev *pdev, int id) if (!brd) return -ENOMEM; - /* make a temporary message buffer for the boot messages */ - brd->msgbuf_head = kcalloc(8192, sizeof(u8), GFP_KERNEL); - brd->msgbuf = brd->msgbuf_head; - - if (!brd->msgbuf) { - kfree(brd); - return -ENOMEM; - } - /* store the info for the board we've found */ brd->magic = DGNC_BOARD_MAGIC; brd->boardnum = dgnc_num_boards; @@ -553,13 +532,6 @@ static int dgnc_found_board(struct pci_dev *pdev, int id) brd->bd_ops->tasklet, (unsigned long)brd); - spin_lock_irqsave(&dgnc_global_lock, flags); - brd->msgbuf = NULL; - dev_dbg(&brd->pdev->dev, "%s\n", brd->msgbuf_head); - kfree(brd->msgbuf_head); - brd->msgbuf_head = NULL; - spin_unlock_irqrestore(&dgnc_global_lock, flags); - wake_up_interruptible(&brd->state_wait); return 0; diff --git a/drivers/staging/dgnc/dgnc_driver.h b/drivers/staging/dgnc/dgnc_driver.h index 88d2696..747a100 100644 --- a/drivers/staging/dgnc/dgnc_driver.h +++ b/drivers/staging/dgnc/dgnc_driver.h @@ -213,12 +213,6 @@ struct dgnc_board { * as defined by DPA */ - /* - * Mgmt data. - */ - char *msgbuf_head; - char *msgbuf; - uint bd_dividend; /* Board/UARTs specific dividend */ struct board_ops *bd_ops; -- cgit v0.10.2 From b09f0cd53f83f937a4e8b58298dbba981b72428b Mon Sep 17 00:00:00 2001 From: Daeseok Youn <daeseok.youn@gmail.com> Date: Mon, 26 Sep 2016 09:40:58 +0900 Subject: staging: dgnc: missing NULL check for ioremap in dgnc_do_remap() The ioremap() function can be failed, so it need to have error handling in dgnc_do_remap(). And also the return type of dgnc_do_remap() should be changed from "void" to "int" Signed-off-by: Daeseok Youn <daeseok.youn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c index c87b3de..58cebf4 100644 --- a/drivers/staging/dgnc/dgnc_driver.c +++ b/drivers/staging/dgnc/dgnc_driver.c @@ -43,7 +43,7 @@ static void dgnc_cleanup_board(struct dgnc_board *brd); static void dgnc_poll_handler(ulong dummy); static int dgnc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); -static void dgnc_do_remap(struct dgnc_board *brd); +static int dgnc_do_remap(struct dgnc_board *brd); /* * File operations permitted on Control/Management major. @@ -431,7 +431,10 @@ static int dgnc_found_board(struct pci_dev *pdev, int id) brd->bd_uart_offset = 0x8; brd->bd_dividend = 921600; - dgnc_do_remap(brd); + rc = dgnc_do_remap(brd); + + if (rc < 0) + goto failed; /* Get and store the board VPD, if it exists */ brd->bd_ops->vpd(brd); @@ -483,15 +486,17 @@ static int dgnc_found_board(struct pci_dev *pdev, int id) brd->bd_uart_offset = 0x200; brd->bd_dividend = 921600; - dgnc_do_remap(brd); + rc = dgnc_do_remap(brd); - if (brd->re_map_membase) { - /* Read and store the dvid after remapping */ - brd->dvid = readb(brd->re_map_membase + 0x8D); + if (rc < 0) + goto failed; + + /* Read and store the dvid after remapping */ + brd->dvid = readb(brd->re_map_membase + 0x8D); + + /* Get and store the board VPD, if it exists */ + brd->bd_ops->vpd(brd); - /* Get and store the board VPD, if it exists */ - brd->bd_ops->vpd(brd); - } break; default: @@ -566,9 +571,15 @@ static int dgnc_finalize_board_init(struct dgnc_board *brd) /* * Remap PCI memory. */ -static void dgnc_do_remap(struct dgnc_board *brd) +static int dgnc_do_remap(struct dgnc_board *brd) { + int rc = 0; + brd->re_map_membase = ioremap(brd->membase, 0x1000); + if (!brd->re_map_membase) + rc = -ENOMEM; + + return rc; } /* -- cgit v0.10.2 From 467132b029fedbffef2e252f2caff4f9dd9a59ff Mon Sep 17 00:00:00 2001 From: Daeseok Youn <daeseok.youn@gmail.com> Date: Mon, 26 Sep 2016 09:42:02 +0900 Subject: staging: dgnc: kfree for board structure in dgnc_found_board() The board structure should be freed when any function was failed in dgnc_found_board(). And the board strucure will be stored into dgnc_board array when the dgnc_found_board() function has no error. Signed-off-by: Daeseok Youn <daeseok.youn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c index 58cebf4..0114e78 100644 --- a/drivers/staging/dgnc/dgnc_driver.c +++ b/drivers/staging/dgnc/dgnc_driver.c @@ -353,9 +353,7 @@ static int dgnc_found_board(struct pci_dev *pdev, int id) int rc = 0; /* get the board structure and prep it */ - dgnc_board[dgnc_num_boards] = kzalloc(sizeof(*brd), GFP_KERNEL); - brd = dgnc_board[dgnc_num_boards]; - + brd = kzalloc(sizeof(*brd), GFP_KERNEL); if (!brd) return -ENOMEM; @@ -411,7 +409,8 @@ static int dgnc_found_board(struct pci_dev *pdev, int id) if (!brd->membase) { dev_err(&brd->pdev->dev, "Card has no PCI IO resources, failing.\n"); - return -ENODEV; + rc = -ENODEV; + goto failed; } brd->membase_end = pci_resource_end(pdev, 4); @@ -502,7 +501,8 @@ static int dgnc_found_board(struct pci_dev *pdev, int id) default: dev_err(&brd->pdev->dev, "Didn't find any compatible Neo/Classic PCI boards.\n"); - return -ENXIO; + rc = -ENXIO; + goto failed; } /* @@ -539,14 +539,15 @@ static int dgnc_found_board(struct pci_dev *pdev, int id) wake_up_interruptible(&brd->state_wait); + dgnc_board[dgnc_num_boards] = brd; + return 0; failed: dgnc_tty_uninit(brd); - brd->state = BOARD_FAILED; - brd->dpastatus = BD_NOFEP; + kfree(brd); - return -ENXIO; + return rc; } static int dgnc_finalize_board_init(struct dgnc_board *brd) -- cgit v0.10.2 From f20ae478ffcf5f191dc7b9aea0489b85e97c8e4e Mon Sep 17 00:00:00 2001 From: Daeseok Youn <daeseok.youn@gmail.com> Date: Mon, 26 Sep 2016 09:43:04 +0900 Subject: staging: dgnc: move functions unrelated with dgnc_found_board() The functions related with tty device initialization are needed to be moved from dgnc_found_board() to dgnc_init_one(). Signed-off-by: Daeseok Youn <daeseok.youn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c index 0114e78..a95d13c 100644 --- a/drivers/staging/dgnc/dgnc_driver.c +++ b/drivers/staging/dgnc/dgnc_driver.c @@ -38,7 +38,7 @@ MODULE_SUPPORTED_DEVICE("dgnc"); */ static int dgnc_start(void); static int dgnc_finalize_board_init(struct dgnc_board *brd); -static int dgnc_found_board(struct pci_dev *pdev, int id); +static struct dgnc_board *dgnc_found_board(struct pci_dev *pdev, int id); static void dgnc_cleanup_board(struct dgnc_board *brd); static void dgnc_poll_handler(ulong dummy); static int dgnc_init_one(struct pci_dev *pdev, @@ -274,6 +274,7 @@ failed_class: static int dgnc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { int rc; + struct dgnc_board *brd; /* wake up and enable device */ rc = pci_enable_device(pdev); @@ -281,9 +282,43 @@ static int dgnc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) return -EIO; - rc = dgnc_found_board(pdev, ent->driver_data); - if (rc == 0) - dgnc_num_boards++; + brd = dgnc_found_board(pdev, ent->driver_data); + if (IS_ERR(brd)) + return PTR_ERR(brd); + + /* + * Do tty device initialization. + */ + + rc = dgnc_tty_register(brd); + if (rc < 0) { + pr_err(DRVSTR ": Can't register tty devices (%d)\n", rc); + goto failed; + } + + rc = dgnc_finalize_board_init(brd); + if (rc < 0) { + pr_err(DRVSTR ": Can't finalize board init (%d)\n", rc); + goto failed; + } + + rc = dgnc_tty_init(brd); + if (rc < 0) { + pr_err(DRVSTR ": Can't init tty devices (%d)\n", rc); + goto failed; + } + + brd->state = BOARD_READY; + brd->dpastatus = BD_RUNNING; + + dgnc_create_ports_sysfiles(brd); + + dgnc_board[dgnc_num_boards++] = brd; + + return 0; + +failed: + kfree(brd); return rc; } @@ -345,7 +380,7 @@ static void dgnc_cleanup_board(struct dgnc_board *brd) * * A board has been found, init it. */ -static int dgnc_found_board(struct pci_dev *pdev, int id) +static struct dgnc_board *dgnc_found_board(struct pci_dev *pdev, int id) { struct dgnc_board *brd; unsigned int pci_irq; @@ -355,7 +390,7 @@ static int dgnc_found_board(struct pci_dev *pdev, int id) /* get the board structure and prep it */ brd = kzalloc(sizeof(*brd), GFP_KERNEL); if (!brd) - return -ENOMEM; + return ERR_PTR(-ENOMEM); /* store the info for the board we've found */ brd->magic = DGNC_BOARD_MAGIC; @@ -505,33 +540,6 @@ static int dgnc_found_board(struct pci_dev *pdev, int id) goto failed; } - /* - * Do tty device initialization. - */ - - rc = dgnc_tty_register(brd); - if (rc < 0) { - pr_err(DRVSTR ": Can't register tty devices (%d)\n", rc); - goto failed; - } - - rc = dgnc_finalize_board_init(brd); - if (rc < 0) { - pr_err(DRVSTR ": Can't finalize board init (%d)\n", rc); - goto failed; - } - - rc = dgnc_tty_init(brd); - if (rc < 0) { - pr_err(DRVSTR ": Can't init tty devices (%d)\n", rc); - goto failed; - } - - brd->state = BOARD_READY; - brd->dpastatus = BD_RUNNING; - - dgnc_create_ports_sysfiles(brd); - /* init our poll helper tasklet */ tasklet_init(&brd->helper_tasklet, brd->bd_ops->tasklet, @@ -539,15 +547,12 @@ static int dgnc_found_board(struct pci_dev *pdev, int id) wake_up_interruptible(&brd->state_wait); - dgnc_board[dgnc_num_boards] = brd; - - return 0; + return brd; failed: - dgnc_tty_uninit(brd); kfree(brd); - return rc; + return ERR_PTR(rc); } static int dgnc_finalize_board_init(struct dgnc_board *brd) -- cgit v0.10.2 From eea5fd116401ed89994e11a6cc1a2e0bee83d8c9 Mon Sep 17 00:00:00 2001 From: Daeseok Youn <daeseok.youn@gmail.com> Date: Mon, 26 Sep 2016 09:43:51 +0900 Subject: staging: dgnc: introduce the dgnc_tty_unregister() The dgnc_tty_unregister() will be called when the dgnc_tty_register() is failed. Signed-off-by: Daeseok Youn <daeseok.youn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c index a95d13c..ffe55a2 100644 --- a/drivers/staging/dgnc/dgnc_driver.c +++ b/drivers/staging/dgnc/dgnc_driver.c @@ -299,13 +299,13 @@ static int dgnc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) rc = dgnc_finalize_board_init(brd); if (rc < 0) { pr_err(DRVSTR ": Can't finalize board init (%d)\n", rc); - goto failed; + goto unregister_tty; } rc = dgnc_tty_init(brd); if (rc < 0) { pr_err(DRVSTR ": Can't init tty devices (%d)\n", rc); - goto failed; + goto unregister_tty; } brd->state = BOARD_READY; @@ -317,6 +317,9 @@ static int dgnc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) return 0; +unregister_tty: + dgnc_tty_unregister(brd); + failed: kfree(brd); diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index 1c1ac84..4f78195 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -273,6 +273,14 @@ free_serial_driver: return rc; } +void dgnc_tty_unregister(struct dgnc_board *brd) +{ + tty_unregister_driver(brd->print_driver); + tty_unregister_driver(brd->serial_driver); + put_tty_driver(brd->print_driver); + put_tty_driver(brd->serial_driver); +} + /* * dgnc_tty_init() * diff --git a/drivers/staging/dgnc/dgnc_tty.h b/drivers/staging/dgnc/dgnc_tty.h index 21d3369..f065c8f 100644 --- a/drivers/staging/dgnc/dgnc_tty.h +++ b/drivers/staging/dgnc/dgnc_tty.h @@ -19,6 +19,7 @@ #include "dgnc_driver.h" int dgnc_tty_register(struct dgnc_board *brd); +void dgnc_tty_unregister(struct dgnc_board *brd); int dgnc_tty_preinit(void); int dgnc_tty_init(struct dgnc_board *); -- cgit v0.10.2 From 0d79f59dbee57df234d982c6b4eab8037cc1cbb7 Mon Sep 17 00:00:00 2001 From: Daeseok Youn <daeseok.youn@gmail.com> Date: Mon, 26 Sep 2016 09:44:42 +0900 Subject: staging: dgnc: rename dgnc_finalize_board_init() to dgnc_request_irq() The dgnc_finalize_board_init() function has only job for requesting the IRQ. It should be renamed to dgnc_request_irq() Signed-off-by: Daeseok Youn <daeseok.youn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c index ffe55a2..70e68b5 100644 --- a/drivers/staging/dgnc/dgnc_driver.c +++ b/drivers/staging/dgnc/dgnc_driver.c @@ -37,7 +37,7 @@ MODULE_SUPPORTED_DEVICE("dgnc"); * */ static int dgnc_start(void); -static int dgnc_finalize_board_init(struct dgnc_board *brd); +static int dgnc_request_irq(struct dgnc_board *brd); static struct dgnc_board *dgnc_found_board(struct pci_dev *pdev, int id); static void dgnc_cleanup_board(struct dgnc_board *brd); static void dgnc_poll_handler(ulong dummy); @@ -296,7 +296,7 @@ static int dgnc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) goto failed; } - rc = dgnc_finalize_board_init(brd); + rc = dgnc_request_irq(brd); if (rc < 0) { pr_err(DRVSTR ": Can't finalize board init (%d)\n", rc); goto unregister_tty; @@ -558,7 +558,7 @@ failed: return ERR_PTR(rc); } -static int dgnc_finalize_board_init(struct dgnc_board *brd) +static int dgnc_request_irq(struct dgnc_board *brd) { int rc = 0; -- cgit v0.10.2 From 5897914f0abb276dddd8fea257782c489acb290b Mon Sep 17 00:00:00 2001 From: Daeseok Youn <daeseok.youn@gmail.com> Date: Mon, 26 Sep 2016 09:45:14 +0900 Subject: staging: dgnc: introduce the dgnc_free_irq() The dgnc_free_irq() will free the requested IRQ from the dgnc_request_irq(). Signed-off-by: Daeseok Youn <daeseok.youn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c index 70e68b5..81ce5c4 100644 --- a/drivers/staging/dgnc/dgnc_driver.c +++ b/drivers/staging/dgnc/dgnc_driver.c @@ -38,6 +38,7 @@ MODULE_SUPPORTED_DEVICE("dgnc"); */ static int dgnc_start(void); static int dgnc_request_irq(struct dgnc_board *brd); +static void dgnc_free_irq(struct dgnc_board *brd); static struct dgnc_board *dgnc_found_board(struct pci_dev *pdev, int id); static void dgnc_cleanup_board(struct dgnc_board *brd); static void dgnc_poll_handler(ulong dummy); @@ -305,7 +306,7 @@ static int dgnc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) rc = dgnc_tty_init(brd); if (rc < 0) { pr_err(DRVSTR ": Can't init tty devices (%d)\n", rc); - goto unregister_tty; + goto free_irq; } brd->state = BOARD_READY; @@ -317,6 +318,8 @@ static int dgnc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) return 0; +free_irq: + dgnc_free_irq(brd); unregister_tty: dgnc_tty_unregister(brd); @@ -577,6 +580,12 @@ static int dgnc_request_irq(struct dgnc_board *brd) return rc; } +static void dgnc_free_irq(struct dgnc_board *brd) +{ + if (brd->irq) + free_irq(brd->irq, brd); +} + /* * Remap PCI memory. */ -- cgit v0.10.2 From 33ccb442aa6b133c7c32aec02b633b11878e04e9 Mon Sep 17 00:00:00 2001 From: Daeseok Youn <daeseok.youn@gmail.com> Date: Mon, 26 Sep 2016 09:46:12 +0900 Subject: staging: dgnc: rename dgnc_tty_uninit() to dgnc_cleanup_tty() The dgnc_tty_uninit() doesn't match with dgnc_tty_init() at all. And also the dgnc_cleanup_tty() is only called for exiting the module. Signed-off-by: Daeseok Youn <daeseok.youn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c index 81ce5c4..fd372d3 100644 --- a/drivers/staging/dgnc/dgnc_driver.c +++ b/drivers/staging/dgnc/dgnc_driver.c @@ -147,7 +147,7 @@ static void cleanup(bool sysfiles) for (i = 0; i < dgnc_num_boards; ++i) { dgnc_remove_ports_sysfiles(dgnc_board[i]); - dgnc_tty_uninit(dgnc_board[i]); + dgnc_cleanup_tty(dgnc_board[i]); dgnc_cleanup_board(dgnc_board[i]); } diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index 4f78195..673c455 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -387,12 +387,12 @@ void dgnc_tty_post_uninit(void) } /* - * dgnc_tty_uninit() + * dgnc_cleanup_tty() * * Uninitialize the TTY portion of this driver. Free all memory and * resources. */ -void dgnc_tty_uninit(struct dgnc_board *brd) +void dgnc_cleanup_tty(struct dgnc_board *brd) { int i = 0; diff --git a/drivers/staging/dgnc/dgnc_tty.h b/drivers/staging/dgnc/dgnc_tty.h index f065c8f..24c9a41 100644 --- a/drivers/staging/dgnc/dgnc_tty.h +++ b/drivers/staging/dgnc/dgnc_tty.h @@ -25,7 +25,7 @@ int dgnc_tty_preinit(void); int dgnc_tty_init(struct dgnc_board *); void dgnc_tty_post_uninit(void); -void dgnc_tty_uninit(struct dgnc_board *); +void dgnc_cleanup_tty(struct dgnc_board *); void dgnc_input(struct channel_t *ch); void dgnc_carrier(struct channel_t *ch); -- cgit v0.10.2 From 1cd7c06213eaeb6c045983ebed8be866938c42b5 Mon Sep 17 00:00:00 2001 From: Daeseok Youn <daeseok.youn@gmail.com> Date: Mon, 26 Sep 2016 09:46:48 +0900 Subject: staging: dgnc: remove useless variables The dgnc_major_serial_registered and dgnc_major_serial_registered do not need to use to check whether the tty driver is registered or not. These variables are used only in dgnc_cleanup_tty() function, This function will be called normally with initialized board structure. It means the dgnc_cleanup_tty() cannot be called with unregistered tty. Signed-off-by: Daeseok Youn <daeseok.youn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_driver.h b/drivers/staging/dgnc/dgnc_driver.h index 747a100..8792026 100644 --- a/drivers/staging/dgnc/dgnc_driver.h +++ b/drivers/staging/dgnc/dgnc_driver.h @@ -203,9 +203,6 @@ struct dgnc_board { struct tty_driver *print_driver; char print_name[200]; - bool dgnc_major_serial_registered; - bool dgnc_major_transparent_print_registered; - u16 dpatype; /* The board "type", * as defined by DPA */ diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index 673c455..e93c0c8 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -204,15 +204,11 @@ int dgnc_tty_register(struct dgnc_board *brd) */ tty_set_operations(brd->serial_driver, &dgnc_tty_ops); - if (!brd->dgnc_major_serial_registered) { - /* Register tty devices */ - rc = tty_register_driver(brd->serial_driver); - if (rc < 0) { - dev_dbg(&brd->pdev->dev, - "Can't register tty device (%d)\n", rc); - goto free_serial_driver; - } - brd->dgnc_major_serial_registered = true; + rc = tty_register_driver(brd->serial_driver); + if (rc < 0) { + dev_dbg(&brd->pdev->dev, + "Can't register tty device (%d)\n", rc); + goto free_serial_driver; } /* @@ -247,16 +243,12 @@ int dgnc_tty_register(struct dgnc_board *brd) */ tty_set_operations(brd->print_driver, &dgnc_tty_ops); - if (!brd->dgnc_major_transparent_print_registered) { - /* Register Transparent Print devices */ - rc = tty_register_driver(brd->print_driver); - if (rc < 0) { - dev_dbg(&brd->pdev->dev, - "Can't register Transparent Print device(%d)\n", - rc); - goto free_print_driver; - } - brd->dgnc_major_transparent_print_registered = true; + rc = tty_register_driver(brd->print_driver); + if (rc < 0) { + dev_dbg(&brd->pdev->dev, + "Can't register Transparent Print device(%d)\n", + rc); + goto free_print_driver; } dgnc_BoardsByMajor[brd->serial_driver->major] = brd; @@ -396,29 +388,23 @@ void dgnc_cleanup_tty(struct dgnc_board *brd) { int i = 0; - if (brd->dgnc_major_serial_registered) { - dgnc_BoardsByMajor[brd->serial_driver->major] = NULL; - for (i = 0; i < brd->nasync; i++) { - if (brd->channels[i]) - dgnc_remove_tty_sysfs(brd->channels[i]-> - ch_tun.un_sysfs); - tty_unregister_device(brd->serial_driver, i); - } - tty_unregister_driver(brd->serial_driver); - brd->dgnc_major_serial_registered = false; + dgnc_BoardsByMajor[brd->serial_driver->major] = NULL; + for (i = 0; i < brd->nasync; i++) { + if (brd->channels[i]) + dgnc_remove_tty_sysfs(brd->channels[i]-> + ch_tun.un_sysfs); + tty_unregister_device(brd->serial_driver, i); } + tty_unregister_driver(brd->serial_driver); - if (brd->dgnc_major_transparent_print_registered) { - dgnc_BoardsByMajor[brd->print_driver->major] = NULL; - for (i = 0; i < brd->nasync; i++) { - if (brd->channels[i]) - dgnc_remove_tty_sysfs(brd->channels[i]-> - ch_pun.un_sysfs); - tty_unregister_device(brd->print_driver, i); - } - tty_unregister_driver(brd->print_driver); - brd->dgnc_major_transparent_print_registered = false; + dgnc_BoardsByMajor[brd->print_driver->major] = NULL; + for (i = 0; i < brd->nasync; i++) { + if (brd->channels[i]) + dgnc_remove_tty_sysfs(brd->channels[i]-> + ch_pun.un_sysfs); + tty_unregister_device(brd->print_driver, i); } + tty_unregister_driver(brd->print_driver); put_tty_driver(brd->serial_driver); put_tty_driver(brd->print_driver); -- cgit v0.10.2 From 9f7a104c2be97902752f7d7a15e955b2de402356 Mon Sep 17 00:00:00 2001 From: Daeseok Youn <daeseok.youn@gmail.com> Date: Mon, 26 Sep 2016 09:47:20 +0900 Subject: staging: dgnc: introduce find_board_by_major() It was used to get a board structure with dgnc_BoardsByMajor array. But this driver already has the array for managing initialized board as dgap_board[]. It can be used for searching the board structure by major number. Signed-off-by: Daeseok Youn <daeseok.youn@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index e93c0c8..953d931 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -45,7 +45,6 @@ /* * internal variables */ -static struct dgnc_board *dgnc_BoardsByMajor[256]; static unsigned char *dgnc_TmpWriteBuf; /* @@ -251,8 +250,6 @@ int dgnc_tty_register(struct dgnc_board *brd) goto free_print_driver; } - dgnc_BoardsByMajor[brd->serial_driver->major] = brd; - return 0; free_print_driver: @@ -388,7 +385,6 @@ void dgnc_cleanup_tty(struct dgnc_board *brd) { int i = 0; - dgnc_BoardsByMajor[brd->serial_driver->major] = NULL; for (i = 0; i < brd->nasync; i++) { if (brd->channels[i]) dgnc_remove_tty_sysfs(brd->channels[i]-> @@ -397,7 +393,6 @@ void dgnc_cleanup_tty(struct dgnc_board *brd) } tty_unregister_driver(brd->serial_driver); - dgnc_BoardsByMajor[brd->print_driver->major] = NULL; for (i = 0; i < brd->nasync; i++) { if (brd->channels[i]) dgnc_remove_tty_sysfs(brd->channels[i]-> @@ -935,6 +930,24 @@ void dgnc_wakeup_writes(struct channel_t *ch) spin_unlock_irqrestore(&ch->ch_lock, flags); } +struct dgnc_board *find_board_by_major(unsigned int major) +{ + int i; + + for (i = 0; i < MAXBOARDS; i++) { + struct dgnc_board *brd = dgnc_board[i]; + + if (!brd) + return NULL; + + if (major == brd->serial_driver->major || + major == brd->print_driver->major) + return brd; + } + + return NULL; +} + /************************************************************************ * * TTY Entry points and helper functions @@ -964,7 +977,7 @@ static int dgnc_tty_open(struct tty_struct *tty, struct file *file) return -ENXIO; /* Get board pointer from our array of majors we have allocated */ - brd = dgnc_BoardsByMajor[major]; + brd = find_board_by_major(major); if (!brd) return -ENXIO; -- cgit v0.10.2 From 66fa610095f758d1793a30d1cd57a0c1432258e2 Mon Sep 17 00:00:00 2001 From: Yannis Damigos <giannis.damigos@gmail.com> Date: Tue, 27 Sep 2016 10:38:23 +0300 Subject: staging:android:ion: Fix comparison with NULL This patch fixes the following comparison with NULL issues: CHECK: Comparison to NULL could be written "compatible[i].name" + for (i = 0; compatible[i].name != NULL; i++) { CHECK: Comparison to NULL could be written "!compatible[i].name" + if (compatible[i].name == NULL) Signed-off-by: Yannis Damigos <giannis.damigos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/ion_of.c b/drivers/staging/android/ion/ion_of.c index 826e756..a8050c6 100644 --- a/drivers/staging/android/ion/ion_of.c +++ b/drivers/staging/android/ion/ion_of.c @@ -31,12 +31,12 @@ static int ion_parse_dt_heap_common(struct device_node *heap_node, { int i; - for (i = 0; compatible[i].name != NULL; i++) { + for (i = 0; compatible[i].name; i++) { if (of_device_is_compatible(heap_node, compatible[i].compat)) break; } - if (compatible[i].name == NULL) + if (!compatible[i].name) return -ENODEV; heap->id = compatible[i].heap_id; -- cgit v0.10.2 From faa2f6f383c1a5e7200de0e2647442ff7ebf5108 Mon Sep 17 00:00:00 2001 From: Yannis Damigos <giannis.damigos@gmail.com> Date: Tue, 27 Sep 2016 10:38:24 +0300 Subject: staging:android:ion: Fix alignment issues This patch fixes the following whitespace issues: CHECK: Alignment should match open parenthesis + pr_info("%s: id %d type %d name %s align %lx\n", __func__, + heap->id, heap->type, heap->name, heap->align); CHECK: Alignment should match open parenthesis +struct ion_platform_data *ion_parse_dt(struct platform_device *pdev, + struct ion_of_heap *compatible) CHECK: Alignment should match open parenthesis + heaps = devm_kzalloc(&pdev->dev, + sizeof(struct ion_platform_heap)*num_heaps, CHECK: Alignment should match open parenthesis + data = devm_kzalloc(&pdev->dev, sizeof(struct ion_platform_data), + GFP_KERNEL); CHECK: Alignment should match open parenthesis + heap_pdev = of_platform_device_create(node, heaps[i].name, + &pdev->dev); CHECK: Alignment should match open parenthesis + pr_debug("%s: heap %s base %pa size %pa dev %p\n", __func__, + heap->name, &rmem->base, &rmem->size, dev); CHECK: Alignment should match open parenthesis +static void rmem_ion_device_release(struct reserved_mem *rmem, + struct device *dev) Signed-off-by: Yannis Damigos <giannis.damigos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/ion_of.c b/drivers/staging/android/ion/ion_of.c index a8050c6..d090c3a 100644 --- a/drivers/staging/android/ion/ion_of.c +++ b/drivers/staging/android/ion/ion_of.c @@ -47,7 +47,7 @@ static int ion_parse_dt_heap_common(struct device_node *heap_node, /* Some kind of callback function pointer? */ pr_info("%s: id %d type %d name %s align %lx\n", __func__, - heap->id, heap->type, heap->name, heap->align); + heap->id, heap->type, heap->name, heap->align); return 0; } @@ -73,7 +73,7 @@ static int ion_setup_heap_common(struct platform_device *parent, } struct ion_platform_data *ion_parse_dt(struct platform_device *pdev, - struct ion_of_heap *compatible) + struct ion_of_heap *compatible) { int num_heaps, ret; const struct device_node *dt_node = pdev->dev.of_node; @@ -88,13 +88,13 @@ struct ion_platform_data *ion_parse_dt(struct platform_device *pdev, return ERR_PTR(-EINVAL); heaps = devm_kzalloc(&pdev->dev, - sizeof(struct ion_platform_heap)*num_heaps, - GFP_KERNEL); + sizeof(struct ion_platform_heap)*num_heaps, + GFP_KERNEL); if (!heaps) return ERR_PTR(-ENOMEM); data = devm_kzalloc(&pdev->dev, sizeof(struct ion_platform_data), - GFP_KERNEL); + GFP_KERNEL); if (!data) return ERR_PTR(-ENOMEM); @@ -106,7 +106,7 @@ struct ion_platform_data *ion_parse_dt(struct platform_device *pdev, return ERR_PTR(ret); heap_pdev = of_platform_device_create(node, heaps[i].name, - &pdev->dev); + &pdev->dev); if (!pdev) return ERR_PTR(-ENOMEM); heap_pdev->dev.platform_data = &heaps[i]; @@ -155,12 +155,12 @@ static int rmem_ion_device_init(struct reserved_mem *rmem, struct device *dev) heap->base = rmem->base; heap->base = rmem->size; pr_debug("%s: heap %s base %pa size %pa dev %p\n", __func__, - heap->name, &rmem->base, &rmem->size, dev); + heap->name, &rmem->base, &rmem->size, dev); return 0; } static void rmem_ion_device_release(struct reserved_mem *rmem, - struct device *dev) + struct device *dev) { return; } -- cgit v0.10.2 From c595149c3e58cd4839354163a77a74cf6816d276 Mon Sep 17 00:00:00 2001 From: Yannis Damigos <giannis.damigos@gmail.com> Date: Tue, 27 Sep 2016 10:38:25 +0300 Subject: staging:android:ion: Fix blank line issues This patch fixes the following blank line issues: CHECK: Please don't use multiple blank lines CHECK: Please use a blank line after function/struct/union/enum declarations +} +RESERVEDMEM_OF_DECLARE(ion, "ion-region", rmem_ion_setup); Signed-off-by: Yannis Damigos <giannis.damigos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/ion_of.c b/drivers/staging/android/ion/ion_of.c index d090c3a..25f688c 100644 --- a/drivers/staging/android/ion/ion_of.c +++ b/drivers/staging/android/ion/ion_of.c @@ -119,7 +119,6 @@ struct ion_platform_data *ion_parse_dt(struct platform_device *pdev, i++; } - data->heaps = heaps; data->nr = num_heaps; return data; @@ -181,5 +180,6 @@ static int __init rmem_ion_setup(struct reserved_mem *rmem) rmem->ops = &rmem_dma_ops; return 0; } + RESERVEDMEM_OF_DECLARE(ion, "ion-region", rmem_ion_setup); #endif -- cgit v0.10.2 From 3dbab14b85a8537b4c447ca16d885a3cc1fa2f9e Mon Sep 17 00:00:00 2001 From: Yannis Damigos <giannis.damigos@gmail.com> Date: Tue, 27 Sep 2016 10:38:26 +0300 Subject: staging:android:ion: Fix whitespace issue This patch fixes the following whitespace issue: CHECK: spaces preferred around that '*' (ctx:VxV) FILE: drivers/staging/android/ion/ion_of.c:91: + sizeof(struct ion_platform_heap)*num_heaps, Signed-off-by: Yannis Damigos <giannis.damigos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/ion_of.c b/drivers/staging/android/ion/ion_of.c index 25f688c..15bac92 100644 --- a/drivers/staging/android/ion/ion_of.c +++ b/drivers/staging/android/ion/ion_of.c @@ -88,7 +88,7 @@ struct ion_platform_data *ion_parse_dt(struct platform_device *pdev, return ERR_PTR(-EINVAL); heaps = devm_kzalloc(&pdev->dev, - sizeof(struct ion_platform_heap)*num_heaps, + sizeof(struct ion_platform_heap) * num_heaps, GFP_KERNEL); if (!heaps) return ERR_PTR(-ENOMEM); -- cgit v0.10.2 From 2b21f96d6b8ac0ee91993abf9865e20fd0d215a8 Mon Sep 17 00:00:00 2001 From: Namrata A Shettar <namrataashettar@gmail.com> Date: Sat, 24 Sep 2016 21:30:57 +0530 Subject: staging: media: lirc: Add space around binary operators Add space around binary operators to resolve checkpatch issue. Signed-off-by: Namrata A Shettar <namrataashettar@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/media/lirc/lirc_parallel.c b/drivers/staging/media/lirc/lirc_parallel.c index 3906ac6..64d99ec 100644 --- a/drivers/staging/media/lirc/lirc_parallel.c +++ b/drivers/staging/media/lirc/lirc_parallel.c @@ -163,12 +163,12 @@ static unsigned int init_lirc_timer(void) if (count >= 1000 && timeelapsed > 0) { if (default_timer == 0) { /* autodetect timer */ - newtimer = (1000000*count)/timeelapsed; + newtimer = (1000000 * count) / timeelapsed; pr_info("%u Hz timer detected\n", newtimer); return newtimer; } - newtimer = (1000000*count)/timeelapsed; - if (abs(newtimer - default_timer) > default_timer/10) { + newtimer = (1000000 * count) / timeelapsed; + if (abs(newtimer - default_timer) > default_timer / 10) { /* bad timer */ pr_notice("bad timer: %u Hz\n", newtimer); pr_notice("using default timer: %u Hz\n", -- cgit v0.10.2 From 1d0a2c5f2c53dc116e4e5dc9ef4661baf2f597ec Mon Sep 17 00:00:00 2001 From: Namrata A Shettar <namrataashettar@gmail.com> Date: Sat, 24 Sep 2016 21:31:34 +0530 Subject: staging: media: lirc: Replace data type with pointer in sizeof() Replace data type with pointer of same type in sizeof() to resolve checkpatch issue. Signed-off-by: Namrata A Shettar <namrataashettar@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/media/lirc/lirc_sasem.c b/drivers/staging/media/lirc/lirc_sasem.c index 65b7bd4..4678ae1 100644 --- a/drivers/staging/media/lirc/lirc_sasem.c +++ b/drivers/staging/media/lirc/lirc_sasem.c @@ -724,17 +724,17 @@ static int sasem_probe(struct usb_interface *interface, /* Allocate memory */ alloc_status = 0; - context = kzalloc(sizeof(struct sasem_context), GFP_KERNEL); + context = kzalloc(sizeof(*context), GFP_KERNEL); if (!context) { alloc_status = 1; goto alloc_status_switch; } - driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); + driver = kzalloc(sizeof(*driver), GFP_KERNEL); if (!driver) { alloc_status = 2; goto alloc_status_switch; } - rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); + rbuf = kmalloc(sizeof(*rbuf), GFP_KERNEL); if (!rbuf) { alloc_status = 3; goto alloc_status_switch; -- cgit v0.10.2 From 8681a1d47b3332b4dbeb0321b347af1bb7cb0cd6 Mon Sep 17 00:00:00 2001 From: Matthew Kilgore <mattkilgore12@gmail.com> Date: Tue, 27 Sep 2016 23:07:54 -0400 Subject: Fixes: 3d44a78f0d8b ("staging: rtl8712: Remove unnecessary 'else'") An "unnecessary" 'else' was removed due to complains from checkpatch.pl as it is preceded by a 'return', however the 'else' branch is necessary as an earlier branch of the 'if' falls through. By removing the 'else', that route now hits the 'break' and the 'while' loop exits prematurely. This commit reverts that change and puts the original 'else' back in place. Signed-off-by: Matthew Kilgore <mattkilgore12@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index cf46592..66f0e0a 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -508,7 +508,8 @@ static int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl, plist = plist->next; else if (SN_EQUAL(pnextattrib->seq_num, pattrib->seq_num)) return false; - break; + else + break; } list_del_init(&(prframe->u.hdr.list)); list_add_tail(&(prframe->u.hdr.list), plist); -- cgit v0.10.2 From f7a34ff7c04527776a93683f4ac4bf92e9e778a5 Mon Sep 17 00:00:00 2001 From: Tim Sell <Timothy.Sell@unisys.com> Date: Tue, 27 Sep 2016 14:42:21 -0400 Subject: staging: unisys: visorbus: fix sloppy unsigned/signed int conversions Several implicit unsigned --> signed int conversions were corrected. No runtime effects were observed here, nevertheless implicit conversions between integral types can lead to unexpected behavior. Signed-off-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 1f3d2e0..ccdb5a1 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -762,7 +762,7 @@ write_vbus_bus_info(struct visorchannel *chan, static void write_vbus_dev_info(struct visorchannel *chan, struct spar_vbus_headerinfo *hdr_info, - struct ultra_vbus_deviceinfo *info, int devix) + struct ultra_vbus_deviceinfo *info, unsigned int devix) { int off = (sizeof(struct channel_header) + hdr_info->dev_info_offset) + @@ -787,8 +787,8 @@ fix_vbus_dev_info(struct visor_device *visordev) int i; struct visor_device *bdev; struct visor_driver *visordrv; - int bus_no = visordev->chipset_bus_no; - int dev_no = visordev->chipset_dev_no; + u32 bus_no = visordev->chipset_bus_no; + u32 dev_no = visordev->chipset_dev_no; struct ultra_vbus_deviceinfo dev_info; const char *chan_type_name = NULL; struct spar_vbus_headerinfo *hdr_info; -- cgit v0.10.2 From 5990b39e26db1126f475f94ea78fe07ea3782e28 Mon Sep 17 00:00:00 2001 From: Tim Sell <Timothy.Sell@unisys.com> Date: Tue, 27 Sep 2016 14:42:22 -0400 Subject: staging: unisys: visorbus: fix vbus info generated for s-Par livedumps Previously, the lines describing devices controlled by the visorinput, visornic, and visorhba drivers (keyboard, mouse, ultravnic, sparvhba) would be missing from the vbus channel header. This is important info that is collected as part of s-Par livedumps, and can be examined via /sys/bus/visorbus/devices/visorbus<n>/client_bus_info, e.g.: $ pwd /sys/bus/visorbus/devices $ cat visorbus1/client_bus_info Client device / client driver info for s-Par Console eartition (vbus #4294967295): chipset visorchipset kernel ver. 4.8.0-rc6-ARCH+ clientbus visorbus kernel ver. 4.8.0-rc6-ARCH+ -> [2]keyboard visorinput kernel ver. 4.8.0-rc6-ARCH+ -> [3]mouse visorinput kernel ver. 4.8.0-rc6-ARCH+ $ cat visorbus2/client_bus_info Client device / client driver info for s-Par IOVM eartition (vbus #4294967295): chipset visorchipset kernel ver. 4.8.0-rc6-ARCH+ clientbus visorbus kernel ver. 4.8.0-rc6-ARCH+ -> [0]ultravnic visornic kernel ver. 4.8.0-rc6-ARCH+ -> [1]ultravnic visornic kernel ver. 4.8.0-rc6-ARCH+ -> [2]sparvhba visorhba kernel ver. 4.8.0-rc6-ARCH+ Signed-off-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index ccdb5a1..2b4abda 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -796,14 +796,12 @@ fix_vbus_dev_info(struct visor_device *visordev) if (!visordev->device.driver) return; - hdr_info = (struct spar_vbus_headerinfo *)visordev->vbus_hdr_info; - if (!hdr_info) - return; - bdev = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL); if (!bdev) return; - + hdr_info = (struct spar_vbus_headerinfo *)bdev->vbus_hdr_info; + if (!hdr_info) + return; visordrv = to_visor_driver(visordev->device.driver); /* -- cgit v0.10.2 From bfc2cc0217140fce1b3ef130a1e5fd56899b5baa Mon Sep 17 00:00:00 2001 From: Tim Sell <Timothy.Sell@unisys.com> Date: Tue, 27 Sep 2016 14:42:23 -0400 Subject: staging: unisys: visorbus: fix typos with client_bus_info /sys entry Example corrected output: $ pwd /sys/bus/visorbus/devices/visorbus1 $ cat client_bus_info Client device / client driver info for s-Par Console partition (vbus #1): chipset visorchipset kernel ver. 4.8.0-rc6-ARCH+ clientbus visorbus kernel ver. 4.8.0-rc6-ARCH+ [2]keyboard visorinput kernel ver. 4.8.0-rc6-ARCH+ [3]mouse visorinput kernel ver. 4.8.0-rc6-ARCH+ $ cat ../visorbus2/client_bus_info Client device / client driver info for s-Par IOVM partition (vbus #2): chipset visorchipset kernel ver. 4.8.0-rc6-ARCH+ clientbus visorbus kernel ver. 4.8.0-rc6-ARCH+ [0]ultravnic visornic kernel ver. 4.8.0-rc6-ARCH+ [1]ultravnic visornic kernel ver. 4.8.0-rc6-ARCH+ [2]sparvhba visorhba kernel ver. 4.8.0-rc6-ARCH+ Signed-off-by: Tim Sell <Timothy.Sell@unisys.com> Signed-off-by: David Kershner <david.kershner@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 2b4abda..fec0a54 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -361,8 +361,8 @@ static ssize_t client_bus_info_show(struct device *dev, if (vdev->name) partition_name = vdev->name; shift = snprintf(pos, remain, - "Client device / client driver info for %s eartition (vbus #%u):\n", - partition_name, vdev->chipset_dev_no); + "Client device / client driver info for %s partition (vbus #%u):\n", + partition_name, vdev->chipset_bus_no); pos += shift; remain -= shift; shift = visorchannel_read(channel, -- cgit v0.10.2 From 19066982a7ae7ca9570d3271451ba3adc616019e Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Tue, 27 Sep 2016 19:33:51 +0200 Subject: staging: wlan-ng: avoid new typedef: netdevice_t This patch fixes the following checkpatch.pl warning in p80211netdev.h: WARNING: do not add new typedefs It applies for typedef netdevice_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c index efc52e9..0247cbc 100644 --- a/drivers/staging/wlan-ng/p80211conv.c +++ b/drivers/staging/wlan-ng/p80211conv.c @@ -277,7 +277,7 @@ static void orinoco_spy_gather(struct wlandevice *wlandev, char *mac, int skb_p80211_to_ether(struct wlandevice *wlandev, u32 ethconv, struct sk_buff *skb) { - netdevice_t *netdev = wlandev->netdev; + struct net_device *netdev = wlandev->netdev; u16 fc; unsigned int payload_length; unsigned int payload_offset; diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c index 0a31467..825a63a 100644 --- a/drivers/staging/wlan-ng/p80211netdev.c +++ b/drivers/staging/wlan-ng/p80211netdev.c @@ -91,16 +91,16 @@ #include "cfg80211.c" /* netdevice method functions */ -static int p80211knetdev_init(netdevice_t *netdev); -static int p80211knetdev_open(netdevice_t *netdev); -static int p80211knetdev_stop(netdevice_t *netdev); +static int p80211knetdev_init(struct net_device *netdev); +static int p80211knetdev_open(struct net_device *netdev); +static int p80211knetdev_stop(struct net_device *netdev); static int p80211knetdev_hard_start_xmit(struct sk_buff *skb, - netdevice_t *netdev); -static void p80211knetdev_set_multicast_list(netdevice_t *dev); -static int p80211knetdev_do_ioctl(netdevice_t *dev, struct ifreq *ifr, + struct net_device *netdev); +static void p80211knetdev_set_multicast_list(struct net_device *dev); +static int p80211knetdev_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); -static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr); -static void p80211knetdev_tx_timeout(netdevice_t *netdev); +static int p80211knetdev_set_mac_address(struct net_device *dev, void *addr); +static void p80211knetdev_tx_timeout(struct net_device *netdev); static int p80211_rx_typedrop(struct wlandevice *wlandev, u16 fc); int wlan_watchdog = 5000; @@ -123,7 +123,7 @@ MODULE_PARM_DESC(wlan_wext_write, "enable write wireless extensions"); * Returns: * nothing ----------------------------------------------------------------*/ -static int p80211knetdev_init(netdevice_t *netdev) +static int p80211knetdev_init(struct net_device *netdev) { /* Called in response to register_netdev */ /* This is usually the probe function, but the probe has */ @@ -146,7 +146,7 @@ static int p80211knetdev_init(netdevice_t *netdev) * Returns: * zero on success, non-zero otherwise ----------------------------------------------------------------*/ -static int p80211knetdev_open(netdevice_t *netdev) +static int p80211knetdev_open(struct net_device *netdev) { int result = 0; /* success */ struct wlandevice *wlandev = netdev->ml_priv; @@ -181,7 +181,7 @@ static int p80211knetdev_open(netdevice_t *netdev) * Returns: * zero on success, non-zero otherwise ----------------------------------------------------------------*/ -static int p80211knetdev_stop(netdevice_t *netdev) +static int p80211knetdev_stop(struct net_device *netdev) { int result = 0; struct wlandevice *wlandev = netdev->ml_priv; @@ -267,7 +267,7 @@ static void p80211netdev_rx_bh(unsigned long arg) { struct wlandevice *wlandev = (struct wlandevice *)arg; struct sk_buff *skb = NULL; - netdevice_t *dev = wlandev->netdev; + struct net_device *dev = wlandev->netdev; /* Let's empty our our queue */ while ((skb = skb_dequeue(&wlandev->nsd_rxq))) { @@ -318,7 +318,7 @@ static void p80211netdev_rx_bh(unsigned long arg) * zero on success, non-zero on failure. ----------------------------------------------------------------*/ static int p80211knetdev_hard_start_xmit(struct sk_buff *skb, - netdevice_t *netdev) + struct net_device *netdev) { int result = 0; int txresult = -1; @@ -446,7 +446,7 @@ failed: * Returns: * nothing ----------------------------------------------------------------*/ -static void p80211knetdev_set_multicast_list(netdevice_t *dev) +static void p80211knetdev_set_multicast_list(struct net_device *dev) { struct wlandevice *wlandev = dev->ml_priv; @@ -531,7 +531,7 @@ static int p80211netdev_ethtool(struct wlandevice *wlandev, void __user *useradd * Process thread (ioctl caller). TODO: SMP support may require * locks. ----------------------------------------------------------------*/ -static int p80211knetdev_do_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd) +static int p80211knetdev_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { int result = 0; struct p80211ioctl_req *req = (struct p80211ioctl_req *)ifr; @@ -610,7 +610,7 @@ bail: * * by: Collin R. Mulliner <collin@mulliner.org> ----------------------------------------------------------------*/ -static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr) +static int p80211knetdev_set_mac_address(struct net_device *dev, void *addr) { struct sockaddr *new_addr = addr; struct p80211msg_dot11req_mibset dot11req; @@ -669,7 +669,7 @@ static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr) return result; } -static int wlan_change_mtu(netdevice_t *dev, int new_mtu) +static int wlan_change_mtu(struct net_device *dev, int new_mtu) { /* 2312 is max 802.11 payload, 20 is overhead, (ether + llc +snap) and another 8 for wep. */ @@ -720,7 +720,7 @@ static const struct net_device_ops p80211_netdev_ops = { int wlan_setup(struct wlandevice *wlandev, struct device *physdev) { int result = 0; - netdevice_t *netdev; + struct net_device *netdev; struct wiphy *wiphy; struct wireless_dev *wdev; @@ -1071,7 +1071,7 @@ static int p80211_rx_typedrop(struct wlandevice *wlandev, u16 fc) return drop; } -static void p80211knetdev_tx_timeout(netdevice_t *netdev) +static void p80211knetdev_tx_timeout(struct net_device *netdev) { struct wlandevice *wlandev = netdev->ml_priv; diff --git a/drivers/staging/wlan-ng/p80211netdev.h b/drivers/staging/wlan-ng/p80211netdev.h index 222f736..5055837 100644 --- a/drivers/staging/wlan-ng/p80211netdev.h +++ b/drivers/staging/wlan-ng/p80211netdev.h @@ -57,9 +57,6 @@ #include <linux/wireless.h> #include <linux/netdevice.h> -#undef netdevice_t -typedef struct net_device netdevice_t; - #define WLAN_RELEASE "0.3.0-staging" #define WLAN_DEVICE_CLOSED 0 @@ -138,7 +135,7 @@ typedef struct p80211_frmrx_t { } p80211_frmrx_t; /* called by /proc/net/wireless */ -struct iw_statistics *p80211wext_get_wireless_stats(netdevice_t *dev); +struct iw_statistics *p80211wext_get_wireless_stats(struct net_device *dev); /* wireless extensions' ioctls */ extern struct iw_handler_def p80211wext_handler_def; @@ -186,7 +183,7 @@ struct wlandevice { struct p80211_metawep *p80211_wep); int (*mlmerequest)(struct wlandevice *wlandev, struct p80211msg *msg); int (*set_multicast_list)(struct wlandevice *wlandev, - netdevice_t *dev); + struct net_device *dev); void (*tx_timeout)(struct wlandevice *wlandev); /* 802.11 State */ @@ -206,7 +203,7 @@ struct wlandevice { /* netlink socket */ /* queue for indications waiting for cmd completion */ /* Linux netdevice and support */ - netdevice_t *netdev; /* ptr to linux netdevice */ + struct net_device *netdev; /* ptr to linux netdevice */ /* Rx bottom half */ struct tasklet_struct rx_bh; diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index a39b294..474e29f 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -107,7 +107,8 @@ static int prism2sta_txframe(struct wlandevice *wlandev, struct sk_buff *skb, static int prism2sta_mlmerequest(struct wlandevice *wlandev, struct p80211msg *msg); static int prism2sta_getcardinfo(struct wlandevice *wlandev); static int prism2sta_globalsetup(struct wlandevice *wlandev); -static int prism2sta_setmulticast(struct wlandevice *wlandev, netdevice_t *dev); +static int prism2sta_setmulticast(struct wlandevice *wlandev, + struct net_device *dev); static void prism2sta_inf_handover(struct wlandevice *wlandev, hfa384x_InfFrame_t *inf); @@ -918,7 +919,8 @@ static int prism2sta_globalsetup(struct wlandevice *wlandev) WLAN_DATA_MAXLEN); } -static int prism2sta_setmulticast(struct wlandevice *wlandev, netdevice_t *dev) +static int prism2sta_setmulticast(struct wlandevice *wlandev, + struct net_device *dev) { int result = 0; hfa384x_t *hw = wlandev->priv; -- cgit v0.10.2 From ae84ee13cbc7ff3826e6a4d185944fd9c7928fcf Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Tue, 27 Sep 2016 19:33:52 +0200 Subject: staging: wlan-ng: avoid new typedef: p80211_frmrx_t This patch fixes the following checkpatch.pl warning in p80211netdev.h: WARNING: do not add new typedefs It applies for typedef p80211_frmrx_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/p80211netdev.h b/drivers/staging/wlan-ng/p80211netdev.h index 5055837..e1a5689 100644 --- a/drivers/staging/wlan-ng/p80211netdev.h +++ b/drivers/staging/wlan-ng/p80211netdev.h @@ -98,7 +98,7 @@ #define P80211_NSDCAP_NOSCAN 0x200 /* nsd can scan */ /* Received frame statistics */ -typedef struct p80211_frmrx_t { +struct p80211_frmrx { u32 mgmt; u32 assocreq; u32 assocresp; @@ -132,7 +132,7 @@ typedef struct p80211_frmrx_t { u32 data_unknown; u32 decrypt; u32 decrypt_err; -} p80211_frmrx_t; +}; /* called by /proc/net/wireless */ struct iw_statistics *p80211wext_get_wireless_stats(struct net_device *dev); @@ -211,7 +211,7 @@ struct wlandevice { struct sk_buff_head nsd_rxq; /* 802.11 device statistics */ - struct p80211_frmrx_t rx; + struct p80211_frmrx rx; struct iw_statistics wstats; -- cgit v0.10.2 From a0cc6bf3eab70c9de1fbaf11cb10ae40619d5ee9 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Tue, 27 Sep 2016 19:33:53 +0200 Subject: staging: wlan-ng: fix line style warnings in p80211netdev.h This patch fixes the following checkpatch.pl warning in p80211netdev.h: WARNING: line over 80 characters Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/p80211netdev.h b/drivers/staging/wlan-ng/p80211netdev.h index e1a5689..1e6a774 100644 --- a/drivers/staging/wlan-ng/p80211netdev.h +++ b/drivers/staging/wlan-ng/p80211netdev.h @@ -225,8 +225,8 @@ struct wlandevice { int wep_change_key(struct wlandevice *wlandev, int keynum, u8 *key, int keylen); int wep_decrypt(struct wlandevice *wlandev, u8 *buf, u32 len, int key_override, u8 *iv, u8 *icv); -int wep_encrypt(struct wlandevice *wlandev, u8 *buf, u8 *dst, u32 len, int keynum, - u8 *iv, u8 *icv); +int wep_encrypt(struct wlandevice *wlandev, u8 *buf, u8 *dst, u32 len, + int keynum, u8 *iv, u8 *icv); int wlan_setup(struct wlandevice *wlandev, struct device *physdev); void wlan_unsetup(struct wlandevice *wlandev); -- cgit v0.10.2 From 4433459a49a186f8e253d7a2211b188040c8661d Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Tue, 27 Sep 2016 19:39:43 +0200 Subject: staging: ks7010: declare private functions static Private functions in ks7010_sdio.c can be declared static. Fixes sparse warnings 'was not declared. Should it be static?'. Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c index 28fb5a0..81c46f4 100644 --- a/drivers/staging/ks7010/ks7010_sdio.c +++ b/drivers/staging/ks7010/ks7010_sdio.c @@ -87,7 +87,7 @@ static int ks7010_sdio_write(struct ks_wlan_private *priv, unsigned int address, return rc; } -void ks_wlan_hw_sleep_doze_request(struct ks_wlan_private *priv) +static void ks_wlan_hw_sleep_doze_request(struct ks_wlan_private *priv) { unsigned char rw_data; int retval; @@ -117,7 +117,7 @@ void ks_wlan_hw_sleep_doze_request(struct ks_wlan_private *priv) priv->sleep_mode = atomic_read(&priv->sleepstatus.status); } -void ks_wlan_hw_sleep_wakeup_request(struct ks_wlan_private *priv) +static void ks_wlan_hw_sleep_wakeup_request(struct ks_wlan_private *priv) { unsigned char rw_data; int retval; @@ -169,7 +169,7 @@ void ks_wlan_hw_wakeup_request(struct ks_wlan_private *priv) } } -int _ks_wlan_hw_power_save(struct ks_wlan_private *priv) +static int _ks_wlan_hw_power_save(struct ks_wlan_private *priv) { unsigned char rw_data; int retval; -- cgit v0.10.2 From 30f9b3fe4da07cab7f1ea5759fd15c482ae65e78 Mon Sep 17 00:00:00 2001 From: Martin Alonso <martin.alonso@zoho.com> Date: Tue, 27 Sep 2016 14:52:48 -0300 Subject: staging: vt6656: Remove unused variable 'rx_sts' As suggested by Joe Perches, rx_sts is not used anywhere and could be removed. Signed-off-by: Martin Alonso <martin.alonso@zoho.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c index c352c70..655f000 100644 --- a/drivers/staging/vt6656/dpc.c +++ b/drivers/staging/vt6656/dpc.c @@ -46,7 +46,7 @@ int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb, __le64 *tsf_time; u32 frame_size; int ii, r; - u8 *rx_sts, *rx_rate, *sq, *sq_3; + u8 *rx_rate, *sq, *sq_3; u32 wbk_status; u8 *skb_data; u16 *pay_load_len; @@ -75,7 +75,6 @@ int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb, skb_data = (u8 *)skb->data; - rx_sts = skb_data + 4; rx_rate = skb_data + 5; /* real Frame Size = USBframe_size -4WbkStatus - 4RxStatus */ -- cgit v0.10.2 From 0c1d83c495d04658c25e5ccc90109dae452fa441 Mon Sep 17 00:00:00 2001 From: Zach Brown <zach.brown@ni.com> Date: Tue, 27 Sep 2016 16:51:49 -0500 Subject: staging: rtl8712: Change _LED_STATE enum in rtl871x driver to avoid conflicts with LED namespace Adding led support for phy causes namespace conflicts for some phy drivers. The rtl871 driver declared an enum for representing LED states. The enum contains constant LED_OFF which conflicted with declaration found in linux/leds.h. LED_OFF changed to LED_STATE_OFF In order to avoid a possible future collision LED_ON was changed to LED_STATE_ON as well. Signed-off-by: Zach Brown <zach.brown@ni.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8712/rtl8712_led.c b/drivers/staging/rtl8712/rtl8712_led.c index a6cbfdc..a8e237e 100644 --- a/drivers/staging/rtl8712/rtl8712_led.c +++ b/drivers/staging/rtl8712/rtl8712_led.c @@ -51,8 +51,8 @@ */ enum _LED_STATE_871x { LED_UNKNOWN = 0, - LED_ON = 1, - LED_OFF = 2, + LED_STATE_ON = 1, + LED_STATE_OFF = 2, LED_BLINK_NORMAL = 3, LED_BLINK_SLOWLY = 4, LED_POWER_ON_BLINK = 5, @@ -94,7 +94,7 @@ static void InitLed871x(struct _adapter *padapter, struct LED_871x *pLed, nic = padapter->pnetdev; pLed->padapter = padapter; pLed->LedPin = LedPin; - pLed->CurrLedState = LED_OFF; + pLed->CurrLedState = LED_STATE_OFF; pLed->bLedOn = false; pLed->bLedBlinkInProgress = false; pLed->BlinkTimes = 0; @@ -211,7 +211,7 @@ static void SwLedBlink(struct LED_871x *pLed) u8 bStopBlinking = false; /* Change LED according to BlinkingLedState specified. */ - if (pLed->BlinkingLedState == LED_ON) + if (pLed->BlinkingLedState == LED_STATE_ON) SwLedOn(padapter, pLed); else SwLedOff(padapter, pLed); @@ -251,10 +251,10 @@ static void SwLedBlink(struct LED_871x *pLed) pLed->bLedBlinkInProgress = false; } else { /* Assign LED state to toggle. */ - if (pLed->BlinkingLedState == LED_ON) - pLed->BlinkingLedState = LED_OFF; + if (pLed->BlinkingLedState == LED_STATE_ON) + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; /* Schedule a timer to toggle LED state. */ switch (pLed->CurrLedState) { @@ -291,7 +291,7 @@ static void SwLedBlink1(struct LED_871x *pLed) if (peeprompriv->CustomerID == RT_CID_819x_CAMEO) pLed = &(ledpriv->SwLed1); /* Change LED according to BlinkingLedState specified. */ - if (pLed->BlinkingLedState == LED_ON) + if (pLed->BlinkingLedState == LED_STATE_ON) SwLedOn(padapter, pLed); else SwLedOff(padapter, pLed); @@ -315,17 +315,17 @@ static void SwLedBlink1(struct LED_871x *pLed) switch (pLed->CurrLedState) { case LED_BLINK_SLOWLY: if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); break; case LED_BLINK_NORMAL: if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA)); break; @@ -338,27 +338,27 @@ static void SwLedBlink1(struct LED_871x *pLed) pLed->bLedLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_NORMAL; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA)); } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) { pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); } pLed->bLedScanBlinkInProgress = false; } else { if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } @@ -372,18 +372,18 @@ static void SwLedBlink1(struct LED_871x *pLed) pLed->bLedLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_NORMAL; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA)); } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) { pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); } @@ -391,24 +391,24 @@ static void SwLedBlink1(struct LED_871x *pLed) pLed->bLedBlinkInProgress = false; } else { if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } break; case LED_BLINK_WPS: if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); break; case LED_BLINK_WPS_STOP: /* WPS success */ - if (pLed->BlinkingLedState == LED_ON) { - pLed->BlinkingLedState = LED_OFF; + if (pLed->BlinkingLedState == LED_STATE_ON) { + pLed->BlinkingLedState = LED_STATE_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA)); bStopBlinking = false; @@ -419,9 +419,9 @@ static void SwLedBlink1(struct LED_871x *pLed) pLed->bLedLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_NORMAL; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA)); } @@ -439,7 +439,7 @@ static void SwLedBlink2(struct LED_871x *pLed) u8 bStopBlinking = false; /* Change LED according to BlinkingLedState specified. */ - if (pLed->BlinkingLedState == LED_ON) + if (pLed->BlinkingLedState == LED_STATE_ON) SwLedOn(padapter, pLed); else SwLedOff(padapter, pLed); @@ -450,20 +450,20 @@ static void SwLedBlink2(struct LED_871x *pLed) bStopBlinking = true; if (bStopBlinking) { if (check_fwstate(pmlmepriv, _FW_LINKED)) { - pLed->CurrLedState = LED_ON; - pLed->BlinkingLedState = LED_ON; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; SwLedOn(padapter, pLed); } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) { - pLed->CurrLedState = LED_OFF; - pLed->BlinkingLedState = LED_OFF; + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; SwLedOff(padapter, pLed); } pLed->bLedScanBlinkInProgress = false; } else { if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } @@ -474,20 +474,20 @@ static void SwLedBlink2(struct LED_871x *pLed) bStopBlinking = true; if (bStopBlinking) { if (check_fwstate(pmlmepriv, _FW_LINKED)) { - pLed->CurrLedState = LED_ON; - pLed->BlinkingLedState = LED_ON; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; SwLedOn(padapter, pLed); } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) { - pLed->CurrLedState = LED_OFF; - pLed->BlinkingLedState = LED_OFF; + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; SwLedOff(padapter, pLed); } pLed->bLedBlinkInProgress = false; } else { if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } @@ -504,7 +504,7 @@ static void SwLedBlink3(struct LED_871x *pLed) u8 bStopBlinking = false; /* Change LED according to BlinkingLedState specified. */ - if (pLed->BlinkingLedState == LED_ON) + if (pLed->BlinkingLedState == LED_STATE_ON) SwLedOn(padapter, pLed); else if (pLed->CurrLedState != LED_BLINK_WPS_STOP) @@ -516,22 +516,22 @@ static void SwLedBlink3(struct LED_871x *pLed) bStopBlinking = true; if (bStopBlinking) { if (check_fwstate(pmlmepriv, _FW_LINKED)) { - pLed->CurrLedState = LED_ON; - pLed->BlinkingLedState = LED_ON; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; if (!pLed->bLedOn) SwLedOn(padapter, pLed); } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) { - pLed->CurrLedState = LED_OFF; - pLed->BlinkingLedState = LED_OFF; + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; if (pLed->bLedOn) SwLedOff(padapter, pLed); } pLed->bLedScanBlinkInProgress = false; } else { if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } @@ -542,37 +542,37 @@ static void SwLedBlink3(struct LED_871x *pLed) bStopBlinking = true; if (bStopBlinking) { if (check_fwstate(pmlmepriv, _FW_LINKED)) { - pLed->CurrLedState = LED_ON; - pLed->BlinkingLedState = LED_ON; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; if (!pLed->bLedOn) SwLedOn(padapter, pLed); } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) { - pLed->CurrLedState = LED_OFF; - pLed->BlinkingLedState = LED_OFF; + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; if (pLed->bLedOn) SwLedOff(padapter, pLed); } pLed->bLedBlinkInProgress = false; } else { if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } break; case LED_BLINK_WPS: if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); break; case LED_BLINK_WPS_STOP: /*WPS success*/ - if (pLed->BlinkingLedState == LED_ON) { - pLed->BlinkingLedState = LED_OFF; + if (pLed->BlinkingLedState == LED_STATE_ON) { + pLed->BlinkingLedState = LED_STATE_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA)); bStopBlinking = false; @@ -580,8 +580,8 @@ static void SwLedBlink3(struct LED_871x *pLed) bStopBlinking = true; } if (bStopBlinking) { - pLed->CurrLedState = LED_ON; - pLed->BlinkingLedState = LED_ON; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; SwLedOn(padapter, pLed); pLed->bLedWPSBlinkInProgress = false; } @@ -599,32 +599,32 @@ static void SwLedBlink4(struct LED_871x *pLed) u8 bStopBlinking = false; /* Change LED according to BlinkingLedState specified. */ - if (pLed->BlinkingLedState == LED_ON) + if (pLed->BlinkingLedState == LED_STATE_ON) SwLedOn(padapter, pLed); else SwLedOff(padapter, pLed); if (!pLed1->bLedWPSBlinkInProgress && pLed1->BlinkingLedState == LED_UNKNOWN) { - pLed1->BlinkingLedState = LED_OFF; - pLed1->CurrLedState = LED_OFF; + pLed1->BlinkingLedState = LED_STATE_OFF; + pLed1->CurrLedState = LED_STATE_OFF; SwLedOff(padapter, pLed1); } switch (pLed->CurrLedState) { case LED_BLINK_SLOWLY: if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); break; case LED_BLINK_StartToBlink: if (pLed->bLedOn) { - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL)); } else { - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); } @@ -637,17 +637,17 @@ static void SwLedBlink4(struct LED_871x *pLed) pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); pLed->bLedScanBlinkInProgress = false; } else { if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } @@ -660,37 +660,37 @@ static void SwLedBlink4(struct LED_871x *pLed) pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); pLed->bLedBlinkInProgress = false; } else { if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } break; case LED_BLINK_WPS: if (pLed->bLedOn) { - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL)); } else { - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); } break; case LED_BLINK_WPS_STOP: /*WPS authentication fail*/ if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); break; @@ -704,14 +704,14 @@ static void SwLedBlink4(struct LED_871x *pLed) } if (bStopBlinking) { pLed->BlinkTimes = 10; - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA)); } else { if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); } @@ -727,7 +727,7 @@ static void SwLedBlink5(struct LED_871x *pLed) u8 bStopBlinking = false; /* Change LED according to BlinkingLedState specified. */ - if (pLed->BlinkingLedState == LED_ON) + if (pLed->BlinkingLedState == LED_STATE_ON) SwLedOn(padapter, pLed); else SwLedOff(padapter, pLed); @@ -737,17 +737,17 @@ static void SwLedBlink5(struct LED_871x *pLed) if (pLed->BlinkTimes == 0) bStopBlinking = true; if (bStopBlinking) { - pLed->CurrLedState = LED_ON; - pLed->BlinkingLedState = LED_ON; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; if (!pLed->bLedOn) mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); pLed->bLedScanBlinkInProgress = false; } else { if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } @@ -757,17 +757,17 @@ static void SwLedBlink5(struct LED_871x *pLed) if (pLed->BlinkTimes == 0) bStopBlinking = true; if (bStopBlinking) { - pLed->CurrLedState = LED_ON; - pLed->BlinkingLedState = LED_ON; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; if (!pLed->bLedOn) mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); pLed->bLedBlinkInProgress = false; } else { if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } @@ -783,7 +783,7 @@ static void SwLedBlink6(struct LED_871x *pLed) u8 bStopBlinking = false; /* Change LED according to BlinkingLedState specified. */ - if (pLed->BlinkingLedState == LED_ON) + if (pLed->BlinkingLedState == LED_STATE_ON) SwLedOn(padapter, pLed); else SwLedOff(padapter, pLed); @@ -793,25 +793,25 @@ static void SwLedBlink6(struct LED_871x *pLed) if (pLed->BlinkTimes == 0) bStopBlinking = true; if (bStopBlinking) { - pLed->CurrLedState = LED_ON; - pLed->BlinkingLedState = LED_ON; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; if (!pLed->bLedOn) SwLedOn(padapter, pLed); pLed->bLedBlinkInProgress = false; } else { if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } break; case LED_BLINK_WPS: if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); break; @@ -912,9 +912,9 @@ static void SwLedControlMode1(struct _adapter *padapter, pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); } @@ -935,9 +935,9 @@ static void SwLedControlMode1(struct _adapter *padapter, pLed->bLedLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_NORMAL; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA)); } @@ -965,9 +965,9 @@ static void SwLedControlMode1(struct _adapter *padapter, pLed->CurrLedState = LED_SCAN_BLINK; pLed->BlinkTimes = 24; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } @@ -990,9 +990,9 @@ static void SwLedControlMode1(struct _adapter *padapter, pLed->CurrLedState = LED_TXRX_BLINK; pLed->BlinkTimes = 2; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } @@ -1020,9 +1020,9 @@ static void SwLedControlMode1(struct _adapter *padapter, pLed->bLedWPSBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_WPS; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } @@ -1050,11 +1050,11 @@ static void SwLedControlMode1(struct _adapter *padapter, pLed->bLedWPSBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_WPS_STOP; if (pLed->bLedOn) { - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA)); } else { - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); } @@ -1067,15 +1067,15 @@ static void SwLedControlMode1(struct _adapter *padapter, pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); break; case LED_CTL_POWER_OFF: - pLed->CurrLedState = LED_OFF; - pLed->BlinkingLedState = LED_OFF; + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; if (pLed->bLedNoLinkBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedNoLinkBlinkInProgress = false; @@ -1127,9 +1127,9 @@ static void SwLedControlMode2(struct _adapter *padapter, pLed->CurrLedState = LED_SCAN_BLINK; pLed->BlinkTimes = 24; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } @@ -1146,17 +1146,17 @@ static void SwLedControlMode2(struct _adapter *padapter, pLed->CurrLedState = LED_TXRX_BLINK; pLed->BlinkTimes = 2; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } break; case LED_CTL_LINK: - pLed->CurrLedState = LED_ON; - pLed->BlinkingLedState = LED_ON; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; @@ -1182,8 +1182,8 @@ static void SwLedControlMode2(struct _adapter *padapter, pLed->bLedScanBlinkInProgress = false; } pLed->bLedWPSBlinkInProgress = true; - pLed->CurrLedState = LED_ON; - pLed->BlinkingLedState = LED_ON; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); } @@ -1191,16 +1191,16 @@ static void SwLedControlMode2(struct _adapter *padapter, case LED_CTL_STOP_WPS: pLed->bLedWPSBlinkInProgress = false; - pLed->CurrLedState = LED_ON; - pLed->BlinkingLedState = LED_ON; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); break; case LED_CTL_STOP_WPS_FAIL: pLed->bLedWPSBlinkInProgress = false; - pLed->CurrLedState = LED_OFF; - pLed->BlinkingLedState = LED_OFF; + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); break; @@ -1208,15 +1208,15 @@ static void SwLedControlMode2(struct _adapter *padapter, case LED_CTL_START_TO_LINK: case LED_CTL_NO_LINK: if (!IS_LED_BLINKING(pLed)) { - pLed->CurrLedState = LED_OFF; - pLed->BlinkingLedState = LED_OFF; + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); } break; case LED_CTL_POWER_OFF: - pLed->CurrLedState = LED_OFF; - pLed->BlinkingLedState = LED_OFF; + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; @@ -1259,9 +1259,9 @@ static void SwLedControlMode3(struct _adapter *padapter, pLed->CurrLedState = LED_SCAN_BLINK; pLed->BlinkTimes = 24; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } @@ -1277,9 +1277,9 @@ static void SwLedControlMode3(struct _adapter *padapter, pLed->CurrLedState = LED_TXRX_BLINK; pLed->BlinkTimes = 2; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } @@ -1287,8 +1287,8 @@ static void SwLedControlMode3(struct _adapter *padapter, case LED_CTL_LINK: if (IS_LED_WPS_BLINKING(pLed)) return; - pLed->CurrLedState = LED_ON; - pLed->BlinkingLedState = LED_ON; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; @@ -1314,9 +1314,9 @@ static void SwLedControlMode3(struct _adapter *padapter, pLed->bLedWPSBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_WPS; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } @@ -1330,11 +1330,11 @@ static void SwLedControlMode3(struct _adapter *padapter, } pLed->CurrLedState = LED_BLINK_WPS_STOP; if (pLed->bLedOn) { - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA)); } else { - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); } @@ -1344,23 +1344,23 @@ static void SwLedControlMode3(struct _adapter *padapter, del_timer(&pLed->BlinkTimer); pLed->bLedWPSBlinkInProgress = false; } - pLed->CurrLedState = LED_OFF; - pLed->BlinkingLedState = LED_OFF; + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); break; case LED_CTL_START_TO_LINK: case LED_CTL_NO_LINK: if (!IS_LED_BLINKING(pLed)) { - pLed->CurrLedState = LED_OFF; - pLed->BlinkingLedState = LED_OFF; + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); } break; case LED_CTL_POWER_OFF: - pLed->CurrLedState = LED_OFF; - pLed->BlinkingLedState = LED_OFF; + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; @@ -1394,8 +1394,8 @@ static void SwLedControlMode4(struct _adapter *padapter, if (pLed1->bLedWPSBlinkInProgress) { pLed1->bLedWPSBlinkInProgress = false; del_timer(&pLed1->BlinkTimer); - pLed1->BlinkingLedState = LED_OFF; - pLed1->CurrLedState = LED_OFF; + pLed1->BlinkingLedState = LED_STATE_OFF; + pLed1->CurrLedState = LED_STATE_OFF; if (pLed1->bLedOn) mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); @@ -1415,11 +1415,11 @@ static void SwLedControlMode4(struct _adapter *padapter, pLed->bLedStartToLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_StartToBlink; if (pLed->bLedOn) { - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL)); } else { - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); } @@ -1432,8 +1432,8 @@ static void SwLedControlMode4(struct _adapter *padapter, if (pLed1->bLedWPSBlinkInProgress) { pLed1->bLedWPSBlinkInProgress = false; del_timer(&pLed1->BlinkTimer); - pLed1->BlinkingLedState = LED_OFF; - pLed1->CurrLedState = LED_OFF; + pLed1->BlinkingLedState = LED_STATE_OFF; + pLed1->CurrLedState = LED_STATE_OFF; if (pLed1->bLedOn) mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); @@ -1450,9 +1450,9 @@ static void SwLedControlMode4(struct _adapter *padapter, pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); } @@ -1476,9 +1476,9 @@ static void SwLedControlMode4(struct _adapter *padapter, pLed->CurrLedState = LED_SCAN_BLINK; pLed->BlinkTimes = 24; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } @@ -1497,9 +1497,9 @@ static void SwLedControlMode4(struct _adapter *padapter, pLed->CurrLedState = LED_TXRX_BLINK; pLed->BlinkTimes = 2; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } @@ -1509,8 +1509,8 @@ static void SwLedControlMode4(struct _adapter *padapter, if (pLed1->bLedWPSBlinkInProgress) { pLed1->bLedWPSBlinkInProgress = false; del_timer(&pLed1->BlinkTimer); - pLed1->BlinkingLedState = LED_OFF; - pLed1->CurrLedState = LED_OFF; + pLed1->BlinkingLedState = LED_STATE_OFF; + pLed1->CurrLedState = LED_STATE_OFF; if (pLed1->bLedOn) mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); @@ -1531,11 +1531,11 @@ static void SwLedControlMode4(struct _adapter *padapter, pLed->bLedWPSBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_WPS; if (pLed->bLedOn) { - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL)); } else { - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); } @@ -1549,9 +1549,9 @@ static void SwLedControlMode4(struct _adapter *padapter, pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); break; @@ -1563,9 +1563,9 @@ static void SwLedControlMode4(struct _adapter *padapter, pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); /*LED1 settings*/ @@ -1575,9 +1575,9 @@ static void SwLedControlMode4(struct _adapter *padapter, pLed1->bLedWPSBlinkInProgress = true; pLed1->CurrLedState = LED_BLINK_WPS_STOP; if (pLed1->bLedOn) - pLed1->BlinkingLedState = LED_OFF; + pLed1->BlinkingLedState = LED_STATE_OFF; else - pLed1->BlinkingLedState = LED_ON; + pLed1->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); break; @@ -1589,9 +1589,9 @@ static void SwLedControlMode4(struct _adapter *padapter, pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); /*LED1 settings*/ @@ -1602,15 +1602,15 @@ static void SwLedControlMode4(struct _adapter *padapter, pLed1->CurrLedState = LED_BLINK_WPS_STOP_OVERLAP; pLed1->BlinkTimes = 10; if (pLed1->bLedOn) - pLed1->BlinkingLedState = LED_OFF; + pLed1->BlinkingLedState = LED_STATE_OFF; else - pLed1->BlinkingLedState = LED_ON; + pLed1->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); break; case LED_CTL_POWER_OFF: - pLed->CurrLedState = LED_OFF; - pLed->BlinkingLedState = LED_OFF; + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; if (pLed->bLedNoLinkBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedNoLinkBlinkInProgress = false; @@ -1664,8 +1664,8 @@ static void SwLedControlMode5(struct _adapter *padapter, case LED_CTL_LINK: /* solid blue */ if (pLed->CurrLedState == LED_SCAN_BLINK) return; - pLed->CurrLedState = LED_ON; - pLed->BlinkingLedState = LED_ON; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; pLed->bLedBlinkInProgress = false; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); @@ -1683,9 +1683,9 @@ static void SwLedControlMode5(struct _adapter *padapter, pLed->CurrLedState = LED_SCAN_BLINK; pLed->BlinkTimes = 24; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } @@ -1699,16 +1699,16 @@ static void SwLedControlMode5(struct _adapter *padapter, pLed->CurrLedState = LED_TXRX_BLINK; pLed->BlinkTimes = 2; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } break; case LED_CTL_POWER_OFF: - pLed->CurrLedState = LED_OFF; - pLed->BlinkingLedState = LED_OFF; + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; @@ -1735,8 +1735,8 @@ static void SwLedControlMode6(struct _adapter *padapter, case LED_CTL_SITE_SURVEY: if (IS_LED_WPS_BLINKING(pLed)) return; - pLed->CurrLedState = LED_ON; - pLed->BlinkingLedState = LED_ON; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; pLed->bLedBlinkInProgress = false; mod_timer(&(pLed->BlinkTimer), jiffies + msecs_to_jiffies(0)); break; @@ -1750,9 +1750,9 @@ static void SwLedControlMode6(struct _adapter *padapter, pLed->CurrLedState = LED_TXRX_BLINK; pLed->BlinkTimes = 2; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } @@ -1767,9 +1767,9 @@ static void SwLedControlMode6(struct _adapter *padapter, pLed->bLedWPSBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_WPS; if (pLed->bLedOn) - pLed->BlinkingLedState = LED_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; else - pLed->BlinkingLedState = LED_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } @@ -1780,14 +1780,14 @@ static void SwLedControlMode6(struct _adapter *padapter, del_timer(&pLed->BlinkTimer); pLed->bLedWPSBlinkInProgress = false; } - pLed->CurrLedState = LED_ON; - pLed->BlinkingLedState = LED_ON; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); break; case LED_CTL_POWER_OFF: - pLed->CurrLedState = LED_OFF; - pLed->BlinkingLedState = LED_OFF; + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; -- cgit v0.10.2 From eb9eb87d0a4281691f3259bd661c5946596c7e51 Mon Sep 17 00:00:00 2001 From: "Darryl T. Agostinelli" <dagostinelli@gmail.com> Date: Tue, 27 Sep 2016 20:51:23 -0500 Subject: staging: rtl8192e: fixed block comments use * on subsequent lines fixed block comments use * on subsequent lines Signed-off-by: Darryl T. Agostinelli <dagostinelli@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8192e/rtllib_tx.c b/drivers/staging/rtl8192e/rtllib_tx.c index 58fc70e..04fbc07 100644 --- a/drivers/staging/rtl8192e/rtllib_tx.c +++ b/drivers/staging/rtl8192e/rtllib_tx.c @@ -1,31 +1,31 @@ /****************************************************************************** - - Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - James P. Ketrenos <ipw2100-admin@linux.intel.com> - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -****************************************************************************** - - Few modifications for Realtek's Wi-Fi drivers by - Andrea Merello <andrea.merello@gmail.com> - - A special thanks goes to Realtek for their support ! - -******************************************************************************/ + * + * Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * James P. Ketrenos <ipw2100-admin@linux.intel.com> + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + ***************************************************************************** + * + * Few modifications for Realtek's Wi-Fi drivers by + * Andrea Merello <andrea.merello@gmail.com> + * + * A special thanks goes to Realtek for their support ! + * + *****************************************************************************/ #include <linux/compiler.h> #include <linux/errno.h> -- cgit v0.10.2 From ff2f3e0e05dfd0af15fec55c2502f1686a6389ce Mon Sep 17 00:00:00 2001 From: "Darryl T. Agostinelli" <dagostinelli@gmail.com> Date: Tue, 27 Sep 2016 20:51:24 -0500 Subject: staging: rtl8192e: fixed statements should start on a tabstop fixed statements should start on a tabstop Signed-off-by: Darryl T. Agostinelli <dagostinelli@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8192e/rtllib_tx.c b/drivers/staging/rtl8192e/rtllib_tx.c index 04fbc07..43ca90d 100644 --- a/drivers/staging/rtl8192e/rtllib_tx.c +++ b/drivers/staging/rtl8192e/rtllib_tx.c @@ -731,17 +731,19 @@ static int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev) if (qos_actived) { hdr_len = RTLLIB_3ADDR_LEN + 2; - /* in case we are a client verify acm is not set for this ac */ - while (unlikely(ieee->wmm_acm & (0x01 << skb->priority))) { - netdev_info(ieee->dev, "skb->priority = %x\n", - skb->priority); - if (wme_downgrade_ac(skb)) - break; - netdev_info(ieee->dev, "converted skb->priority = %x\n", - skb->priority); - } + /* in case we are a client verify acm is not set for this ac */ + while (unlikely(ieee->wmm_acm & (0x01 << skb->priority))) { + netdev_info(ieee->dev, "skb->priority = %x\n", + skb->priority); + if (wme_downgrade_ac(skb)) + break; + netdev_info(ieee->dev, "converted skb->priority = %x\n", + skb->priority); + } + qos_ctl |= skb->priority; header.qos_ctl = cpu_to_le16(qos_ctl & RTLLIB_QOS_TID); + } else { hdr_len = RTLLIB_3ADDR_LEN; } -- cgit v0.10.2 From 08e1416f9ce89e67bccae388ac85cfd51dcece38 Mon Sep 17 00:00:00 2001 From: "Darryl T. Agostinelli" <dagostinelli@gmail.com> Date: Tue, 27 Sep 2016 20:51:25 -0500 Subject: staging: rtl8192e: fixed use a blank line after function/struct/union/enum declarations fixed use a blank line after function/struct/union/enum declarations Signed-off-by: Darryl T. Agostinelli <dagostinelli@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8192e/rtllib_tx.c b/drivers/staging/rtl8192e/rtllib_tx.c index 43ca90d..78a3ad5 100644 --- a/drivers/staging/rtl8192e/rtllib_tx.c +++ b/drivers/staging/rtl8192e/rtllib_tx.c @@ -983,6 +983,7 @@ static int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev) return 1; } + int rtllib_xmit(struct sk_buff *skb, struct net_device *dev) { memset(skb->cb, 0, sizeof(skb->cb)); -- cgit v0.10.2 From 88638cf1a8c352bb47c23adbc36d35cfd6ace5a1 Mon Sep 17 00:00:00 2001 From: Mark Greer <mgreer@animalcreek.com> Date: Tue, 27 Sep 2016 16:34:13 -0700 Subject: staging: greybus: Add backup maintainer for Greybus audio Add Mark Greer as the backup maintainer for the Greybus Audio Protocol driver. Signed-off-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/MAINTAINERS b/MAINTAINERS index e013c2b..15c98ad 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5299,6 +5299,7 @@ F: drivers/staging/greybus/ GREYBUS AUDIO PROTOCOLS DRIVERS M: Vaibhav Agarwal <vaibhav.sr@gmail.com> +M: Mark Greer <mgreer@animalcreek.com> S: Maintained F: drivers/staging/greybus/audio_codec.c F: drivers/staging/greybus/audio_module.c -- cgit v0.10.2 From 71bad7f086419dc674244b91ca35a12bfa4cb597 Mon Sep 17 00:00:00 2001 From: popcornmix <popcornmix@gmail.com> Date: Tue, 2 Jul 2013 23:42:01 +0100 Subject: staging: add bcm2708 vchiq driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: popcornmix <popcornmix@gmail.com> vchiq: create_pagelist copes with vmalloc memory Signed-off-by: Daniel Stone <daniels@collabora.com> vchiq: fix the shim message release Signed-off-by: Daniel Stone <daniels@collabora.com> vchiq: export additional symbols Signed-off-by: Daniel Stone <daniels@collabora.com> VCHIQ: Make service closure fully synchronous (drv) This is one half of a two-part patch, the other half of which is to the vchiq_lib user library. With these patches, calls to vchiq_close_service and vchiq_remove_service won't return until any associated callbacks have been delivered to the callback thread. VCHIQ: Add per-service tracing The new service option VCHIQ_SERVICE_OPTION_TRACE is a boolean that toggles tracing for the specified service. This commit also introduces vchi_service_set_option and the associated option VCHI_SERVICE_OPTION_TRACE. vchiq: Make the synchronous-CLOSE logic more tolerant vchiq: Move logging control into debugfs vchiq: Take care of a corner case tickled by VCSM Closing a connection that isn't fully open requires care, since one side does not know the other side's port number. Code was present to handle the case where a CLOSE is sent immediately after an OPEN, i.e. before the OPENACK has been received, but this was incorrectly being used when an OPEN from a client using port 0 was rejected. (In the observed failure, the host was attempting to use the VCSM service, which isn't present in the 'cutdown' firmware. The failure was intermittent because sometimes the keepalive service would grab port 0.) This case can be distinguished because the client's remoteport will still be VCHIQ_PORT_FREE, and the srvstate will be OPENING. Either condition is sufficient to differentiate it from the special case described above. vchiq: Avoid high load when blocked and unkillable vchiq: Include SIGSTOP and SIGCONT in list of signals not-masked by vchiq to allow gdb to work vchiq_arm: Complete support for SYNCHRONOUS mode vchiq: Remove inline from suspend/resume vchiq: Allocation does not need to be atomic vchiq: Fix wrong condition check The log level is checked from within the log call. Remove the check in the call. Signed-off-by: Pranith Kumar <bobby.prani@gmail.com> BCM270x: Add vchiq device to platform file and Device Tree Prepare to turn the vchiq module into a driver. Signed-off-by: Noralf Trønnes <noralf@tronnes.org> bcm2708: vchiq: Add Device Tree support Turn vchiq into a driver and stop hardcoding resources. Use devm_* functions in probe path to simplify cleanup. A global variable is used to hold the register address. This is done to keep this patch as small as possible. Also make available on ARCH_BCM2835. Based on work by Lubomir Rintel. Signed-off-by: Noralf Trønnes <noralf@tronnes.org> vchiq: Change logging level for inbound data vchiq_arm: Two cacheing fixes 1) Make fragment size vary with cache line size Without this patch, non-cache-line-aligned transfers may corrupt (or be corrupted by) adjacent data structures. Both ARM and VC need to be updated to enable this feature. This is ensured by having the loader apply a new DT parameter - cache-line-size. The existence of this parameter guarantees that the kernel is capable, and the parameter will only be modified from the safe default if the loader is capable. 2) Flush/invalidate vmalloc'd memory, and invalidate after reads vchiq: fix NULL pointer dereference when closing driver The following code run as root will cause a null pointer dereference oops: int fd = open("/dev/vc-cma", O_RDONLY); if (fd < 0) err(1, "open failed"); (void)close(fd); [ 1704.877721] Unable to handle kernel NULL pointer dereference at virtual address 00000000 [ 1704.877725] pgd = b899c000 [ 1704.877736] [00000000] *pgd=37fab831, *pte=00000000, *ppte=00000000 [ 1704.877748] Internal error: Oops: 817 [#1] PREEMPT SMP ARM [ 1704.877765] Modules linked in: evdev i2c_bcm2708 uio_pdrv_genirq uio [ 1704.877774] CPU: 2 PID: 3656 Comm: stress-ng-fstat Not tainted 3.19.1-12-generic-bcm2709 #12-Ubuntu [ 1704.877777] Hardware name: BCM2709 [ 1704.877783] task: b8ab9b00 ti: b7e68000 task.ti: b7e68000 [ 1704.877798] PC is at __down_interruptible+0x50/0xec [ 1704.877806] LR is at down_interruptible+0x5c/0x68 [ 1704.877813] pc : [<80630ee8>] lr : [<800704b0>] psr: 60080093 sp : b7e69e50 ip : b7e69e88 fp : b7e69e84 [ 1704.877817] r10: b88123c8 r9 : 00000010 r8 : 00000001 [ 1704.877822] r7 : b8ab9b00 r6 : 7fffffff r5 : 80a1cc34 r4 : 80a1cc34 [ 1704.877826] r3 : b7e69e50 r2 : 00000000 r1 : 00000000 r0 : 80a1cc34 [ 1704.877833] Flags: nZCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user [ 1704.877838] Control: 10c5387d Table: 3899c06a DAC: 00000015 [ 1704.877843] Process do-oops (pid: 3656, stack limit = 0xb7e68238) [ 1704.877848] Stack: (0xb7e69e50 to 0xb7e6a000) [ 1704.877856] 9e40: 80a1cc3c 00000000 00000010 b88123c8 [ 1704.877865] 9e60: b7e69e84 80a1cc34 fff9fee9 ffffffff b7e68000 00000009 b7e69ea4 b7e69e88 [ 1704.877874] 9e80: 800704b0 80630ea4 fff9fee9 60080013 80a1cc28 fff9fee9 b7e69edc b7e69ea8 [ 1704.877884] 9ea0: 8040f558 80070460 fff9fee9 ffffffff 00000000 00000000 00000009 80a1cb7c [ 1704.877893] 9ec0: 00000000 80a1cb7c 00000000 00000010 b7e69ef4 b7e69ee0 803e1ba4 8040f514 [ 1704.877902] 9ee0: 00000e48 80a1cb7c b7e69f14 b7e69ef8 803e1c9c 803e1b74 b88123c0 b92acb18 [ 1704.877911] 9f00: b8812790 b8d815d8 b7e69f24 b7e69f18 803e2250 803e1bc8 b7e69f5c b7e69f28 [ 1704.877921] 9f20: 80167bac 803e222c 00000000 00000000 b7e69f54 b8ab9ffc 00000000 8098c794 [ 1704.877930] 9f40: b8ab9b00 8000efc4 b7e68000 00000000 b7e69f6c b7e69f60 80167d6c 80167b28 [ 1704.877939] 9f60: b7e69f8c b7e69f70 80047d38 80167d60 b7e68000 b7e68010 8000efc4 b7e69fb0 [ 1704.877949] 9f80: b7e69fac b7e69f90 80012820 80047c84 01155490 011549a8 00000001 00000006 [ 1704.877957] 9fa0: 00000000 b7e69fb0 8000ee5c 80012790 00000000 353d8c0f 7efc4308 00000000 [ 1704.877966] 9fc0: 01155490 011549a8 00000001 00000006 00000000 00000000 76cf3ba0 00000003 [ 1704.877975] 9fe0: 00000000 7efc42e4 0002272f 76e2ed66 60080030 00000003 00000000 00000000 [ 1704.877998] [<80630ee8>] (__down_interruptible) from [<800704b0>] (down_interruptible+0x5c/0x68) [ 1704.878015] [<800704b0>] (down_interruptible) from [<8040f558>] (vchiu_queue_push+0x50/0xd8) [ 1704.878032] [<8040f558>] (vchiu_queue_push) from [<803e1ba4>] (send_worker_msg+0x3c/0x54) [ 1704.878045] [<803e1ba4>] (send_worker_msg) from [<803e1c9c>] (vc_cma_set_reserve+0xe0/0x1c4) [ 1704.878057] [<803e1c9c>] (vc_cma_set_reserve) from [<803e2250>] (vc_cma_release+0x30/0x38) [ 1704.878069] [<803e2250>] (vc_cma_release) from [<80167bac>] (__fput+0x90/0x1e0) [ 1704.878082] [<80167bac>] (__fput) from [<80167d6c>] (____fput+0x18/0x1c) [ 1704.878094] [<80167d6c>] (____fput) from [<80047d38>] (task_work_run+0xc0/0xf8) [ 1704.878109] [<80047d38>] (task_work_run) from [<80012820>] (do_work_pending+0x9c/0xc4) [ 1704.878123] [<80012820>] (do_work_pending) from [<8000ee5c>] (work_pending+0xc/0x20) [ 1704.878133] Code: e50b1034 e3a01000 e50b2030 e580300c (e5823000) ..the fix is to ensure that we have actually initialized the queue before we attempt to push any items onto it. This occurs if we do an open() followed by a close() without any activity in between. Signed-off-by: Colin Ian King <colin.king@canonical.com> vchiq_arm: Sort out the vmalloc case See: https://github.com/raspberrypi/linux/issues/1055 vchiq: hack: Add include depecated dma include file [gregkh] added dependancy on CONFIG_BROKEN to make things sane for now. Cc: Eric Anholt <eric@anholt.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 9c0339c..58a7b35 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -104,4 +104,6 @@ source "drivers/staging/ks7010/Kconfig" source "drivers/staging/greybus/Kconfig" +source "drivers/staging/vc04_services/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 6952aaf..2fa9745 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -41,3 +41,4 @@ obj-$(CONFIG_MOST) += most/ obj-$(CONFIG_ISDN_I4L) += i4l/ obj-$(CONFIG_KS7010) += ks7010/ obj-$(CONFIG_GREYBUS) += greybus/ +obj-$(CONFIG_BCM2708_VCHIQ) += vc04_services/ diff --git a/drivers/staging/vc04_services/Kconfig b/drivers/staging/vc04_services/Kconfig new file mode 100644 index 0000000..9676fb2 --- /dev/null +++ b/drivers/staging/vc04_services/Kconfig @@ -0,0 +1,9 @@ +config BCM2708_VCHIQ + tristate "Videocore VCHIQ" + depends on RASPBERRYPI_FIRMWARE && BROKEN + default y + help + Kernel to VideoCore communication interface for the + BCM2708 family of products. + Defaults to Y when the Broadcom Videocore services + are included in the build, N otherwise. diff --git a/drivers/staging/vc04_services/Makefile b/drivers/staging/vc04_services/Makefile new file mode 100644 index 0000000..90ab478 --- /dev/null +++ b/drivers/staging/vc04_services/Makefile @@ -0,0 +1,14 @@ +obj-$(CONFIG_BCM2708_VCHIQ) += vchiq.o + +vchiq-objs := \ + interface/vchiq_arm/vchiq_core.o \ + interface/vchiq_arm/vchiq_arm.o \ + interface/vchiq_arm/vchiq_kern_lib.o \ + interface/vchiq_arm/vchiq_2835_arm.o \ + interface/vchiq_arm/vchiq_debugfs.o \ + interface/vchiq_arm/vchiq_shim.o \ + interface/vchiq_arm/vchiq_util.o \ + interface/vchiq_arm/vchiq_connected.o \ + +ccflags-y += -DVCOS_VERIFY_BKPTS=1 -Idrivers/staging/vc04_services -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 + diff --git a/drivers/staging/vc04_services/interface/vchi/connections/connection.h b/drivers/staging/vc04_services/interface/vchi/connections/connection.h new file mode 100644 index 0000000..fef6ac3 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchi/connections/connection.h @@ -0,0 +1,328 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CONNECTION_H_ +#define CONNECTION_H_ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/semaphore.h> + +#include "interface/vchi/vchi_cfg_internal.h" +#include "interface/vchi/vchi_common.h" +#include "interface/vchi/message_drivers/message.h" + +/****************************************************************************** + Global defs + *****************************************************************************/ + +// Opaque handle for a connection / service pair +typedef struct opaque_vchi_connection_connected_service_handle_t *VCHI_CONNECTION_SERVICE_HANDLE_T; + +// opaque handle to the connection state information +typedef struct opaque_vchi_connection_info_t VCHI_CONNECTION_STATE_T; + +typedef struct vchi_connection_t VCHI_CONNECTION_T; + + +/****************************************************************************** + API + *****************************************************************************/ + +// Routine to init a connection with a particular low level driver +typedef VCHI_CONNECTION_STATE_T * (*VCHI_CONNECTION_INIT_T)( struct vchi_connection_t * connection, + const VCHI_MESSAGE_DRIVER_T * driver ); + +// Routine to control CRC enabling at a connection level +typedef int32_t (*VCHI_CONNECTION_CRC_CONTROL_T)( VCHI_CONNECTION_STATE_T *state_handle, + VCHI_CRC_CONTROL_T control ); + +// Routine to create a service +typedef int32_t (*VCHI_CONNECTION_SERVICE_CONNECT_T)( VCHI_CONNECTION_STATE_T *state_handle, + int32_t service_id, + uint32_t rx_fifo_size, + uint32_t tx_fifo_size, + int server, + VCHI_CALLBACK_T callback, + void *callback_param, + int32_t want_crc, + int32_t want_unaligned_bulk_rx, + int32_t want_unaligned_bulk_tx, + VCHI_CONNECTION_SERVICE_HANDLE_T *service_handle ); + +// Routine to close a service +typedef int32_t (*VCHI_CONNECTION_SERVICE_DISCONNECT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle ); + +// Routine to queue a message +typedef int32_t (*VCHI_CONNECTION_SERVICE_QUEUE_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, + const void *data, + uint32_t data_size, + VCHI_FLAGS_T flags, + void *msg_handle ); + +// scatter-gather (vector) message queueing +typedef int32_t (*VCHI_CONNECTION_SERVICE_QUEUE_MESSAGEV_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, + VCHI_MSG_VECTOR_T *vector, + uint32_t count, + VCHI_FLAGS_T flags, + void *msg_handle ); + +// Routine to dequeue a message +typedef int32_t (*VCHI_CONNECTION_SERVICE_DEQUEUE_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, + void *data, + uint32_t max_data_size_to_read, + uint32_t *actual_msg_size, + VCHI_FLAGS_T flags ); + +// Routine to peek at a message +typedef int32_t (*VCHI_CONNECTION_SERVICE_PEEK_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, + void **data, + uint32_t *msg_size, + VCHI_FLAGS_T flags ); + +// Routine to hold a message +typedef int32_t (*VCHI_CONNECTION_SERVICE_HOLD_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, + void **data, + uint32_t *msg_size, + VCHI_FLAGS_T flags, + void **message_handle ); + +// Routine to initialise a received message iterator +typedef int32_t (*VCHI_CONNECTION_SERVICE_LOOKAHEAD_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, + VCHI_MSG_ITER_T *iter, + VCHI_FLAGS_T flags ); + +// Routine to release a held message +typedef int32_t (*VCHI_CONNECTION_HELD_MSG_RELEASE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, + void *message_handle ); + +// Routine to get info on a held message +typedef int32_t (*VCHI_CONNECTION_HELD_MSG_INFO_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, + void *message_handle, + void **data, + int32_t *msg_size, + uint32_t *tx_timestamp, + uint32_t *rx_timestamp ); + +// Routine to check whether the iterator has a next message +typedef int32_t (*VCHI_CONNECTION_MSG_ITER_HAS_NEXT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service, + const VCHI_MSG_ITER_T *iter ); + +// Routine to advance the iterator +typedef int32_t (*VCHI_CONNECTION_MSG_ITER_NEXT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service, + VCHI_MSG_ITER_T *iter, + void **data, + uint32_t *msg_size ); + +// Routine to remove the last message returned by the iterator +typedef int32_t (*VCHI_CONNECTION_MSG_ITER_REMOVE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service, + VCHI_MSG_ITER_T *iter ); + +// Routine to hold the last message returned by the iterator +typedef int32_t (*VCHI_CONNECTION_MSG_ITER_HOLD_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service, + VCHI_MSG_ITER_T *iter, + void **msg_handle ); + +// Routine to transmit bulk data +typedef int32_t (*VCHI_CONNECTION_BULK_QUEUE_TRANSMIT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, + const void *data_src, + uint32_t data_size, + VCHI_FLAGS_T flags, + void *bulk_handle ); + +// Routine to receive data +typedef int32_t (*VCHI_CONNECTION_BULK_QUEUE_RECEIVE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, + void *data_dst, + uint32_t data_size, + VCHI_FLAGS_T flags, + void *bulk_handle ); + +// Routine to report if a server is available +typedef int32_t (*VCHI_CONNECTION_SERVER_PRESENT)( VCHI_CONNECTION_STATE_T *state, int32_t service_id, int32_t peer_flags ); + +// Routine to report the number of RX slots available +typedef int (*VCHI_CONNECTION_RX_SLOTS_AVAILABLE)( const VCHI_CONNECTION_STATE_T *state ); + +// Routine to report the RX slot size +typedef uint32_t (*VCHI_CONNECTION_RX_SLOT_SIZE)( const VCHI_CONNECTION_STATE_T *state ); + +// Callback to indicate that the other side has added a buffer to the rx bulk DMA FIFO +typedef void (*VCHI_CONNECTION_RX_BULK_BUFFER_ADDED)(VCHI_CONNECTION_STATE_T *state, + int32_t service, + uint32_t length, + MESSAGE_TX_CHANNEL_T channel, + uint32_t channel_params, + uint32_t data_length, + uint32_t data_offset); + +// Callback to inform a service that a Xon or Xoff message has been received +typedef void (*VCHI_CONNECTION_FLOW_CONTROL)(VCHI_CONNECTION_STATE_T *state, int32_t service_id, int32_t xoff); + +// Callback to inform a service that a server available reply message has been received +typedef void (*VCHI_CONNECTION_SERVER_AVAILABLE_REPLY)(VCHI_CONNECTION_STATE_T *state, int32_t service_id, uint32_t flags); + +// Callback to indicate that bulk auxiliary messages have arrived +typedef void (*VCHI_CONNECTION_BULK_AUX_RECEIVED)(VCHI_CONNECTION_STATE_T *state); + +// Callback to indicate that bulk auxiliary messages have arrived +typedef void (*VCHI_CONNECTION_BULK_AUX_TRANSMITTED)(VCHI_CONNECTION_STATE_T *state, void *handle); + +// Callback with all the connection info you require +typedef void (*VCHI_CONNECTION_INFO)(VCHI_CONNECTION_STATE_T *state, uint32_t protocol_version, uint32_t slot_size, uint32_t num_slots, uint32_t min_bulk_size); + +// Callback to inform of a disconnect +typedef void (*VCHI_CONNECTION_DISCONNECT)(VCHI_CONNECTION_STATE_T *state, uint32_t flags); + +// Callback to inform of a power control request +typedef void (*VCHI_CONNECTION_POWER_CONTROL)(VCHI_CONNECTION_STATE_T *state, MESSAGE_TX_CHANNEL_T channel, int32_t enable); + +// allocate memory suitably aligned for this connection +typedef void * (*VCHI_BUFFER_ALLOCATE)(VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, uint32_t * length); + +// free memory allocated by buffer_allocate +typedef void (*VCHI_BUFFER_FREE)(VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, void * address); + + +/****************************************************************************** + System driver struct + *****************************************************************************/ + +struct opaque_vchi_connection_api_t +{ + // Routine to init the connection + VCHI_CONNECTION_INIT_T init; + + // Connection-level CRC control + VCHI_CONNECTION_CRC_CONTROL_T crc_control; + + // Routine to connect to or create service + VCHI_CONNECTION_SERVICE_CONNECT_T service_connect; + + // Routine to disconnect from a service + VCHI_CONNECTION_SERVICE_DISCONNECT_T service_disconnect; + + // Routine to queue a message + VCHI_CONNECTION_SERVICE_QUEUE_MESSAGE_T service_queue_msg; + + // scatter-gather (vector) message queue + VCHI_CONNECTION_SERVICE_QUEUE_MESSAGEV_T service_queue_msgv; + + // Routine to dequeue a message + VCHI_CONNECTION_SERVICE_DEQUEUE_MESSAGE_T service_dequeue_msg; + + // Routine to peek at a message + VCHI_CONNECTION_SERVICE_PEEK_MESSAGE_T service_peek_msg; + + // Routine to hold a message + VCHI_CONNECTION_SERVICE_HOLD_MESSAGE_T service_hold_msg; + + // Routine to initialise a received message iterator + VCHI_CONNECTION_SERVICE_LOOKAHEAD_MESSAGE_T service_look_ahead_msg; + + // Routine to release a message + VCHI_CONNECTION_HELD_MSG_RELEASE_T held_msg_release; + + // Routine to get information on a held message + VCHI_CONNECTION_HELD_MSG_INFO_T held_msg_info; + + // Routine to check for next message on iterator + VCHI_CONNECTION_MSG_ITER_HAS_NEXT_T msg_iter_has_next; + + // Routine to get next message on iterator + VCHI_CONNECTION_MSG_ITER_NEXT_T msg_iter_next; + + // Routine to remove the last message returned by iterator + VCHI_CONNECTION_MSG_ITER_REMOVE_T msg_iter_remove; + + // Routine to hold the last message returned by iterator + VCHI_CONNECTION_MSG_ITER_HOLD_T msg_iter_hold; + + // Routine to transmit bulk data + VCHI_CONNECTION_BULK_QUEUE_TRANSMIT_T bulk_queue_transmit; + + // Routine to receive data + VCHI_CONNECTION_BULK_QUEUE_RECEIVE_T bulk_queue_receive; + + // Routine to report the available servers + VCHI_CONNECTION_SERVER_PRESENT server_present; + + // Routine to report the number of RX slots available + VCHI_CONNECTION_RX_SLOTS_AVAILABLE connection_rx_slots_available; + + // Routine to report the RX slot size + VCHI_CONNECTION_RX_SLOT_SIZE connection_rx_slot_size; + + // Callback to indicate that the other side has added a buffer to the rx bulk DMA FIFO + VCHI_CONNECTION_RX_BULK_BUFFER_ADDED rx_bulk_buffer_added; + + // Callback to inform a service that a Xon or Xoff message has been received + VCHI_CONNECTION_FLOW_CONTROL flow_control; + + // Callback to inform a service that a server available reply message has been received + VCHI_CONNECTION_SERVER_AVAILABLE_REPLY server_available_reply; + + // Callback to indicate that bulk auxiliary messages have arrived + VCHI_CONNECTION_BULK_AUX_RECEIVED bulk_aux_received; + + // Callback to indicate that a bulk auxiliary message has been transmitted + VCHI_CONNECTION_BULK_AUX_TRANSMITTED bulk_aux_transmitted; + + // Callback to provide information about the connection + VCHI_CONNECTION_INFO connection_info; + + // Callback to notify that peer has requested disconnect + VCHI_CONNECTION_DISCONNECT disconnect; + + // Callback to notify that peer has requested power change + VCHI_CONNECTION_POWER_CONTROL power_control; + + // allocate memory suitably aligned for this connection + VCHI_BUFFER_ALLOCATE buffer_allocate; + + // free memory allocated by buffer_allocate + VCHI_BUFFER_FREE buffer_free; + +}; + +struct vchi_connection_t { + const VCHI_CONNECTION_API_T *api; + VCHI_CONNECTION_STATE_T *state; +#ifdef VCHI_COARSE_LOCKING + struct semaphore sem; +#endif +}; + + +#endif /* CONNECTION_H_ */ + +/****************************** End of file **********************************/ diff --git a/drivers/staging/vc04_services/interface/vchi/message_drivers/message.h b/drivers/staging/vc04_services/interface/vchi/message_drivers/message.h new file mode 100644 index 0000000..8b3f767 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchi/message_drivers/message.h @@ -0,0 +1,204 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _VCHI_MESSAGE_H_ +#define _VCHI_MESSAGE_H_ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/semaphore.h> + +#include "interface/vchi/vchi_cfg_internal.h" +#include "interface/vchi/vchi_common.h" + + +typedef enum message_event_type { + MESSAGE_EVENT_NONE, + MESSAGE_EVENT_NOP, + MESSAGE_EVENT_MESSAGE, + MESSAGE_EVENT_SLOT_COMPLETE, + MESSAGE_EVENT_RX_BULK_PAUSED, + MESSAGE_EVENT_RX_BULK_COMPLETE, + MESSAGE_EVENT_TX_COMPLETE, + MESSAGE_EVENT_MSG_DISCARDED +} MESSAGE_EVENT_TYPE_T; + +typedef enum vchi_msg_flags +{ + VCHI_MSG_FLAGS_NONE = 0x0, + VCHI_MSG_FLAGS_TERMINATE_DMA = 0x1 +} VCHI_MSG_FLAGS_T; + +typedef enum message_tx_channel +{ + MESSAGE_TX_CHANNEL_MESSAGE = 0, + MESSAGE_TX_CHANNEL_BULK = 1 // drivers may provide multiple bulk channels, from 1 upwards +} MESSAGE_TX_CHANNEL_T; + +// Macros used for cycling through bulk channels +#define MESSAGE_TX_CHANNEL_BULK_PREV(c) (MESSAGE_TX_CHANNEL_BULK+((c)-MESSAGE_TX_CHANNEL_BULK+VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION-1)%VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION) +#define MESSAGE_TX_CHANNEL_BULK_NEXT(c) (MESSAGE_TX_CHANNEL_BULK+((c)-MESSAGE_TX_CHANNEL_BULK+1)%VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION) + +typedef enum message_rx_channel +{ + MESSAGE_RX_CHANNEL_MESSAGE = 0, + MESSAGE_RX_CHANNEL_BULK = 1 // drivers may provide multiple bulk channels, from 1 upwards +} MESSAGE_RX_CHANNEL_T; + +// Message receive slot information +typedef struct rx_msg_slot_info { + + struct rx_msg_slot_info *next; + //struct slot_info *prev; +#if !defined VCHI_COARSE_LOCKING + struct semaphore sem; +#endif + + uint8_t *addr; // base address of slot + uint32_t len; // length of slot in bytes + + uint32_t write_ptr; // hardware causes this to advance + uint32_t read_ptr; // this module does the reading + int active; // is this slot in the hardware dma fifo? + uint32_t msgs_parsed; // count how many messages are in this slot + uint32_t msgs_released; // how many messages have been released + void *state; // connection state information + uint8_t ref_count[VCHI_MAX_SERVICES_PER_CONNECTION]; // reference count for slots held by services +} RX_MSG_SLOTINFO_T; + +// The message driver no longer needs to know about the fields of RX_BULK_SLOTINFO_T - sort this out. +// In particular, it mustn't use addr and len - they're the client buffer, but the message +// driver will be tasked with sending the aligned core section. +typedef struct rx_bulk_slotinfo_t { + struct rx_bulk_slotinfo_t *next; + + struct semaphore *blocking; + + // needed by DMA + void *addr; + uint32_t len; + + // needed for the callback + void *service; + void *handle; + VCHI_FLAGS_T flags; +} RX_BULK_SLOTINFO_T; + + +/* ---------------------------------------------------------------------- + * each connection driver will have a pool of the following struct. + * + * the pool will be managed by vchi_qman_* + * this means there will be multiple queues (single linked lists) + * a given struct message_info will be on exactly one of these queues + * at any one time + * -------------------------------------------------------------------- */ +typedef struct rx_message_info { + + struct message_info *next; + //struct message_info *prev; + + uint8_t *addr; + uint32_t len; + RX_MSG_SLOTINFO_T *slot; // points to whichever slot contains this message + uint32_t tx_timestamp; + uint32_t rx_timestamp; + +} RX_MESSAGE_INFO_T; + +typedef struct { + MESSAGE_EVENT_TYPE_T type; + + struct { + // for messages + void *addr; // address of message + uint16_t slot_delta; // whether this message indicated slot delta + uint32_t len; // length of message + RX_MSG_SLOTINFO_T *slot; // slot this message is in + int32_t service; // service id this message is destined for + uint32_t tx_timestamp; // timestamp from the header + uint32_t rx_timestamp; // timestamp when we parsed it + } message; + + // FIXME: cleanup slot reporting... + RX_MSG_SLOTINFO_T *rx_msg; + RX_BULK_SLOTINFO_T *rx_bulk; + void *tx_handle; + MESSAGE_TX_CHANNEL_T tx_channel; + +} MESSAGE_EVENT_T; + + +// callbacks +typedef void VCHI_MESSAGE_DRIVER_EVENT_CALLBACK_T( void *state ); + +typedef struct { + VCHI_MESSAGE_DRIVER_EVENT_CALLBACK_T *event_callback; +} VCHI_MESSAGE_DRIVER_OPEN_T; + + +// handle to this instance of message driver (as returned by ->open) +typedef struct opaque_mhandle_t *VCHI_MDRIVER_HANDLE_T; + +struct opaque_vchi_message_driver_t { + VCHI_MDRIVER_HANDLE_T *(*open)( VCHI_MESSAGE_DRIVER_OPEN_T *params, void *state ); + int32_t (*suspending)( VCHI_MDRIVER_HANDLE_T *handle ); + int32_t (*resumed)( VCHI_MDRIVER_HANDLE_T *handle ); + int32_t (*power_control)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T, int32_t enable ); + int32_t (*add_msg_rx_slot)( VCHI_MDRIVER_HANDLE_T *handle, RX_MSG_SLOTINFO_T *slot ); // rx message + int32_t (*add_bulk_rx)( VCHI_MDRIVER_HANDLE_T *handle, void *data, uint32_t len, RX_BULK_SLOTINFO_T *slot ); // rx data (bulk) + int32_t (*send)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel, const void *data, uint32_t len, VCHI_MSG_FLAGS_T flags, void *send_handle ); // tx (message & bulk) + void (*next_event)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_EVENT_T *event ); // get the next event from message_driver + int32_t (*enable)( VCHI_MDRIVER_HANDLE_T *handle ); + int32_t (*form_message)( VCHI_MDRIVER_HANDLE_T *handle, int32_t service_id, VCHI_MSG_VECTOR_T *vector, uint32_t count, void + *address, uint32_t length_avail, uint32_t max_total_length, int32_t pad_to_fill, int32_t allow_partial ); + + int32_t (*update_message)( VCHI_MDRIVER_HANDLE_T *handle, void *dest, int16_t *slot_count ); + int32_t (*buffer_aligned)( VCHI_MDRIVER_HANDLE_T *handle, int tx, int uncached, const void *address, const uint32_t length ); + void * (*allocate_buffer)( VCHI_MDRIVER_HANDLE_T *handle, uint32_t *length ); + void (*free_buffer)( VCHI_MDRIVER_HANDLE_T *handle, void *address ); + int (*rx_slot_size)( VCHI_MDRIVER_HANDLE_T *handle, int msg_size ); + int (*tx_slot_size)( VCHI_MDRIVER_HANDLE_T *handle, int msg_size ); + + int32_t (*tx_supports_terminate)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel ); + uint32_t (*tx_bulk_chunk_size)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel ); + int (*tx_alignment)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel ); + int (*rx_alignment)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_RX_CHANNEL_T channel ); + void (*form_bulk_aux)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel, const void *data, uint32_t len, uint32_t chunk_size, const void **aux_data, int32_t *aux_len ); + void (*debug)( VCHI_MDRIVER_HANDLE_T *handle ); +}; + + +#endif // _VCHI_MESSAGE_H_ + +/****************************** End of file ***********************************/ diff --git a/drivers/staging/vc04_services/interface/vchi/vchi.h b/drivers/staging/vc04_services/interface/vchi/vchi.h new file mode 100644 index 0000000..1b17e98 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchi/vchi.h @@ -0,0 +1,378 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHI_H_ +#define VCHI_H_ + +#include "interface/vchi/vchi_cfg.h" +#include "interface/vchi/vchi_common.h" +#include "interface/vchi/connections/connection.h" +#include "vchi_mh.h" + + +/****************************************************************************** + Global defs + *****************************************************************************/ + +#define VCHI_BULK_ROUND_UP(x) ((((unsigned long)(x))+VCHI_BULK_ALIGN-1) & ~(VCHI_BULK_ALIGN-1)) +#define VCHI_BULK_ROUND_DOWN(x) (((unsigned long)(x)) & ~(VCHI_BULK_ALIGN-1)) +#define VCHI_BULK_ALIGN_NBYTES(x) (VCHI_BULK_ALIGNED(x) ? 0 : (VCHI_BULK_ALIGN - ((unsigned long)(x) & (VCHI_BULK_ALIGN-1)))) + +#ifdef USE_VCHIQ_ARM +#define VCHI_BULK_ALIGNED(x) 1 +#else +#define VCHI_BULK_ALIGNED(x) (((unsigned long)(x) & (VCHI_BULK_ALIGN-1)) == 0) +#endif + +struct vchi_version { + uint32_t version; + uint32_t version_min; +}; +#define VCHI_VERSION(v_) { v_, v_ } +#define VCHI_VERSION_EX(v_, m_) { v_, m_ } + +typedef enum +{ + VCHI_VEC_POINTER, + VCHI_VEC_HANDLE, + VCHI_VEC_LIST +} VCHI_MSG_VECTOR_TYPE_T; + +typedef struct vchi_msg_vector_ex { + + VCHI_MSG_VECTOR_TYPE_T type; + union + { + // a memory handle + struct + { + VCHI_MEM_HANDLE_T handle; + uint32_t offset; + int32_t vec_len; + } handle; + + // an ordinary data pointer + struct + { + const void *vec_base; + int32_t vec_len; + } ptr; + + // a nested vector list + struct + { + struct vchi_msg_vector_ex *vec; + uint32_t vec_len; + } list; + } u; +} VCHI_MSG_VECTOR_EX_T; + + +// Construct an entry in a msg vector for a pointer (p) of length (l) +#define VCHI_VEC_POINTER(p,l) VCHI_VEC_POINTER, { { (VCHI_MEM_HANDLE_T)(p), (l) } } + +// Construct an entry in a msg vector for a message handle (h), starting at offset (o) of length (l) +#define VCHI_VEC_HANDLE(h,o,l) VCHI_VEC_HANDLE, { { (h), (o), (l) } } + +// Macros to manipulate 'FOURCC' values +#define MAKE_FOURCC(x) ((int32_t)( (x[0] << 24) | (x[1] << 16) | (x[2] << 8) | x[3] )) +#define FOURCC_TO_CHAR(x) (x >> 24) & 0xFF,(x >> 16) & 0xFF,(x >> 8) & 0xFF, x & 0xFF + + +// Opaque service information +struct opaque_vchi_service_t; + +// Descriptor for a held message. Allocated by client, initialised by vchi_msg_hold, +// vchi_msg_iter_hold or vchi_msg_iter_hold_next. Fields are for internal VCHI use only. +typedef struct +{ + struct opaque_vchi_service_t *service; + void *message; +} VCHI_HELD_MSG_T; + + + +// structure used to provide the information needed to open a server or a client +typedef struct { + struct vchi_version version; + int32_t service_id; + VCHI_CONNECTION_T *connection; + uint32_t rx_fifo_size; + uint32_t tx_fifo_size; + VCHI_CALLBACK_T callback; + void *callback_param; + /* client intends to receive bulk transfers of + odd lengths or into unaligned buffers */ + int32_t want_unaligned_bulk_rx; + /* client intends to transmit bulk transfers of + odd lengths or out of unaligned buffers */ + int32_t want_unaligned_bulk_tx; + /* client wants to check CRCs on (bulk) xfers. + Only needs to be set at 1 end - will do both directions. */ + int32_t want_crc; +} SERVICE_CREATION_T; + +// Opaque handle for a VCHI instance +typedef struct opaque_vchi_instance_handle_t *VCHI_INSTANCE_T; + +// Opaque handle for a server or client +typedef struct opaque_vchi_service_handle_t *VCHI_SERVICE_HANDLE_T; + +// Service registration & startup +typedef void (*VCHI_SERVICE_INIT)(VCHI_INSTANCE_T initialise_instance, VCHI_CONNECTION_T **connections, uint32_t num_connections); + +typedef struct service_info_tag { + const char * const vll_filename; /* VLL to load to start this service. This is an empty string if VLL is "static" */ + VCHI_SERVICE_INIT init; /* Service initialisation function */ + void *vll_handle; /* VLL handle; NULL when unloaded or a "static VLL" in build */ +} SERVICE_INFO_T; + +/****************************************************************************** + Global funcs - implementation is specific to which side you are on (local / remote) + *****************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +extern /*@observer@*/ VCHI_CONNECTION_T * vchi_create_connection( const VCHI_CONNECTION_API_T * function_table, + const VCHI_MESSAGE_DRIVER_T * low_level); + + +// Routine used to initialise the vchi on both local + remote connections +extern int32_t vchi_initialise( VCHI_INSTANCE_T *instance_handle ); + +extern int32_t vchi_exit( void ); + +extern int32_t vchi_connect( VCHI_CONNECTION_T **connections, + const uint32_t num_connections, + VCHI_INSTANCE_T instance_handle ); + +//When this is called, ensure that all services have no data pending. +//Bulk transfers can remain 'queued' +extern int32_t vchi_disconnect( VCHI_INSTANCE_T instance_handle ); + +// Global control over bulk CRC checking +extern int32_t vchi_crc_control( VCHI_CONNECTION_T *connection, + VCHI_CRC_CONTROL_T control ); + +// helper functions +extern void * vchi_allocate_buffer(VCHI_SERVICE_HANDLE_T handle, uint32_t *length); +extern void vchi_free_buffer(VCHI_SERVICE_HANDLE_T handle, void *address); +extern uint32_t vchi_current_time(VCHI_INSTANCE_T instance_handle); + + +/****************************************************************************** + Global service API + *****************************************************************************/ +// Routine to create a named service +extern int32_t vchi_service_create( VCHI_INSTANCE_T instance_handle, + SERVICE_CREATION_T *setup, + VCHI_SERVICE_HANDLE_T *handle ); + +// Routine to destory a service +extern int32_t vchi_service_destroy( const VCHI_SERVICE_HANDLE_T handle ); + +// Routine to open a named service +extern int32_t vchi_service_open( VCHI_INSTANCE_T instance_handle, + SERVICE_CREATION_T *setup, + VCHI_SERVICE_HANDLE_T *handle); + +extern int32_t vchi_get_peer_version( const VCHI_SERVICE_HANDLE_T handle, + short *peer_version ); + +// Routine to close a named service +extern int32_t vchi_service_close( const VCHI_SERVICE_HANDLE_T handle ); + +// Routine to increment ref count on a named service +extern int32_t vchi_service_use( const VCHI_SERVICE_HANDLE_T handle ); + +// Routine to decrement ref count on a named service +extern int32_t vchi_service_release( const VCHI_SERVICE_HANDLE_T handle ); + +// Routine to set a control option for a named service +extern int32_t vchi_service_set_option( const VCHI_SERVICE_HANDLE_T handle, + VCHI_SERVICE_OPTION_T option, + int value); + +// Routine to send a message across a service +extern int32_t vchi_msg_queue( VCHI_SERVICE_HANDLE_T handle, + const void *data, + uint32_t data_size, + VCHI_FLAGS_T flags, + void *msg_handle ); + +// scatter-gather (vector) and send message +int32_t vchi_msg_queuev_ex( VCHI_SERVICE_HANDLE_T handle, + VCHI_MSG_VECTOR_EX_T *vector, + uint32_t count, + VCHI_FLAGS_T flags, + void *msg_handle ); + +// legacy scatter-gather (vector) and send message, only handles pointers +int32_t vchi_msg_queuev( VCHI_SERVICE_HANDLE_T handle, + VCHI_MSG_VECTOR_T *vector, + uint32_t count, + VCHI_FLAGS_T flags, + void *msg_handle ); + +// Routine to receive a msg from a service +// Dequeue is equivalent to hold, copy into client buffer, release +extern int32_t vchi_msg_dequeue( VCHI_SERVICE_HANDLE_T handle, + void *data, + uint32_t max_data_size_to_read, + uint32_t *actual_msg_size, + VCHI_FLAGS_T flags ); + +// Routine to look at a message in place. +// The message is not dequeued, so a subsequent call to peek or dequeue +// will return the same message. +extern int32_t vchi_msg_peek( VCHI_SERVICE_HANDLE_T handle, + void **data, + uint32_t *msg_size, + VCHI_FLAGS_T flags ); + +// Routine to remove a message after it has been read in place with peek +// The first message on the queue is dequeued. +extern int32_t vchi_msg_remove( VCHI_SERVICE_HANDLE_T handle ); + +// Routine to look at a message in place. +// The message is dequeued, so the caller is left holding it; the descriptor is +// filled in and must be released when the user has finished with the message. +extern int32_t vchi_msg_hold( VCHI_SERVICE_HANDLE_T handle, + void **data, // } may be NULL, as info can be + uint32_t *msg_size, // } obtained from HELD_MSG_T + VCHI_FLAGS_T flags, + VCHI_HELD_MSG_T *message_descriptor ); + +// Initialise an iterator to look through messages in place +extern int32_t vchi_msg_look_ahead( VCHI_SERVICE_HANDLE_T handle, + VCHI_MSG_ITER_T *iter, + VCHI_FLAGS_T flags ); + +/****************************************************************************** + Global service support API - operations on held messages and message iterators + *****************************************************************************/ + +// Routine to get the address of a held message +extern void *vchi_held_msg_ptr( const VCHI_HELD_MSG_T *message ); + +// Routine to get the size of a held message +extern int32_t vchi_held_msg_size( const VCHI_HELD_MSG_T *message ); + +// Routine to get the transmit timestamp as written into the header by the peer +extern uint32_t vchi_held_msg_tx_timestamp( const VCHI_HELD_MSG_T *message ); + +// Routine to get the reception timestamp, written as we parsed the header +extern uint32_t vchi_held_msg_rx_timestamp( const VCHI_HELD_MSG_T *message ); + +// Routine to release a held message after it has been processed +extern int32_t vchi_held_msg_release( VCHI_HELD_MSG_T *message ); + +// Indicates whether the iterator has a next message. +extern int32_t vchi_msg_iter_has_next( const VCHI_MSG_ITER_T *iter ); + +// Return the pointer and length for the next message and advance the iterator. +extern int32_t vchi_msg_iter_next( VCHI_MSG_ITER_T *iter, + void **data, + uint32_t *msg_size ); + +// Remove the last message returned by vchi_msg_iter_next. +// Can only be called once after each call to vchi_msg_iter_next. +extern int32_t vchi_msg_iter_remove( VCHI_MSG_ITER_T *iter ); + +// Hold the last message returned by vchi_msg_iter_next. +// Can only be called once after each call to vchi_msg_iter_next. +extern int32_t vchi_msg_iter_hold( VCHI_MSG_ITER_T *iter, + VCHI_HELD_MSG_T *message ); + +// Return information for the next message, and hold it, advancing the iterator. +extern int32_t vchi_msg_iter_hold_next( VCHI_MSG_ITER_T *iter, + void **data, // } may be NULL + uint32_t *msg_size, // } + VCHI_HELD_MSG_T *message ); + + +/****************************************************************************** + Global bulk API + *****************************************************************************/ + +// Routine to prepare interface for a transfer from the other side +extern int32_t vchi_bulk_queue_receive( VCHI_SERVICE_HANDLE_T handle, + void *data_dst, + uint32_t data_size, + VCHI_FLAGS_T flags, + void *transfer_handle ); + + +// Prepare interface for a transfer from the other side into relocatable memory. +int32_t vchi_bulk_queue_receive_reloc( const VCHI_SERVICE_HANDLE_T handle, + VCHI_MEM_HANDLE_T h_dst, + uint32_t offset, + uint32_t data_size, + const VCHI_FLAGS_T flags, + void * const bulk_handle ); + +// Routine to queue up data ready for transfer to the other (once they have signalled they are ready) +extern int32_t vchi_bulk_queue_transmit( VCHI_SERVICE_HANDLE_T handle, + const void *data_src, + uint32_t data_size, + VCHI_FLAGS_T flags, + void *transfer_handle ); + + +/****************************************************************************** + Configuration plumbing + *****************************************************************************/ + +// function prototypes for the different mid layers (the state info gives the different physical connections) +extern const VCHI_CONNECTION_API_T *single_get_func_table( void ); +//extern const VCHI_CONNECTION_API_T *local_server_get_func_table( void ); +//extern const VCHI_CONNECTION_API_T *local_client_get_func_table( void ); + +// declare all message drivers here +const VCHI_MESSAGE_DRIVER_T *vchi_mphi_message_driver_func_table( void ); + +#ifdef __cplusplus +} +#endif + +extern int32_t vchi_bulk_queue_transmit_reloc( VCHI_SERVICE_HANDLE_T handle, + VCHI_MEM_HANDLE_T h_src, + uint32_t offset, + uint32_t data_size, + VCHI_FLAGS_T flags, + void *transfer_handle ); +#endif /* VCHI_H_ */ + +/****************************** End of file **********************************/ diff --git a/drivers/staging/vc04_services/interface/vchi/vchi_cfg.h b/drivers/staging/vc04_services/interface/vchi/vchi_cfg.h new file mode 100644 index 0000000..26bc2d3 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchi/vchi_cfg.h @@ -0,0 +1,224 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHI_CFG_H_ +#define VCHI_CFG_H_ + +/**************************************************************************************** + * Defines in this first section are part of the VCHI API and may be examined by VCHI + * services. + ***************************************************************************************/ + +/* Required alignment of base addresses for bulk transfer, if unaligned transfers are not enabled */ +/* Really determined by the message driver, and should be available from a run-time call. */ +#ifndef VCHI_BULK_ALIGN +# if __VCCOREVER__ >= 0x04000000 +# define VCHI_BULK_ALIGN 32 // Allows for the need to do cache cleans +# else +# define VCHI_BULK_ALIGN 16 +# endif +#endif + +/* Required length multiple for bulk transfers, if unaligned transfers are not enabled */ +/* May be less than or greater than VCHI_BULK_ALIGN */ +/* Really determined by the message driver, and should be available from a run-time call. */ +#ifndef VCHI_BULK_GRANULARITY +# if __VCCOREVER__ >= 0x04000000 +# define VCHI_BULK_GRANULARITY 32 // Allows for the need to do cache cleans +# else +# define VCHI_BULK_GRANULARITY 16 +# endif +#endif + +/* The largest possible message to be queued with vchi_msg_queue. */ +#ifndef VCHI_MAX_MSG_SIZE +# if defined VCHI_LOCAL_HOST_PORT +# define VCHI_MAX_MSG_SIZE 16384 // makes file transfers fast, but should they be using bulk? +# else +# define VCHI_MAX_MSG_SIZE 4096 // NOTE: THIS MUST BE LARGER THAN OR EQUAL TO THE SIZE OF THE KHRONOS MERGE BUFFER!! +# endif +#endif + +/****************************************************************************************** + * Defines below are system configuration options, and should not be used by VCHI services. + *****************************************************************************************/ + +/* How many connections can we support? A localhost implementation uses 2 connections, + * 1 for host-app, 1 for VMCS, and these are hooked together by a loopback MPHI VCFW + * driver. */ +#ifndef VCHI_MAX_NUM_CONNECTIONS +# define VCHI_MAX_NUM_CONNECTIONS 3 +#endif + +/* How many services can we open per connection? Extending this doesn't cost processing time, just a small + * amount of static memory. */ +#ifndef VCHI_MAX_SERVICES_PER_CONNECTION +# define VCHI_MAX_SERVICES_PER_CONNECTION 36 +#endif + +/* Adjust if using a message driver that supports more logical TX channels */ +#ifndef VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION +# define VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION 9 // 1 MPHI + 8 CCP2 logical channels +#endif + +/* Adjust if using a message driver that supports more logical RX channels */ +#ifndef VCHI_MAX_BULK_RX_CHANNELS_PER_CONNECTION +# define VCHI_MAX_BULK_RX_CHANNELS_PER_CONNECTION 1 // 1 MPHI +#endif + +/* How many receive slots do we use. This times VCHI_MAX_MSG_SIZE gives the effective + * receive queue space, less message headers. */ +#ifndef VCHI_NUM_READ_SLOTS +# if defined(VCHI_LOCAL_HOST_PORT) +# define VCHI_NUM_READ_SLOTS 4 +# else +# define VCHI_NUM_READ_SLOTS 48 +# endif +#endif + +/* Do we utilise overrun facility for receive message slots? Can aid peer transmit + * performance. Only define on VideoCore end, talking to host. + */ +//#define VCHI_MSG_RX_OVERRUN + +/* How many transmit slots do we use. Generally don't need many, as the hardware driver + * underneath VCHI will usually have its own buffering. */ +#ifndef VCHI_NUM_WRITE_SLOTS +# define VCHI_NUM_WRITE_SLOTS 4 +#endif + +/* If a service has held or queued received messages in VCHI_XOFF_THRESHOLD or more slots, + * then it's taking up too much buffer space, and the peer service will be told to stop + * transmitting with an XOFF message. For this to be effective, the VCHI_NUM_READ_SLOTS + * needs to be considerably bigger than VCHI_NUM_WRITE_SLOTS, or the transmit latency + * is too high. */ +#ifndef VCHI_XOFF_THRESHOLD +# define VCHI_XOFF_THRESHOLD (VCHI_NUM_READ_SLOTS / 2) +#endif + +/* After we've sent an XOFF, the peer will be told to resume transmission once the local + * service has dequeued/released enough messages that it's now occupying + * VCHI_XON_THRESHOLD slots or fewer. */ +#ifndef VCHI_XON_THRESHOLD +# define VCHI_XON_THRESHOLD (VCHI_NUM_READ_SLOTS / 4) +#endif + +/* A size below which a bulk transfer omits the handshake completely and always goes + * via the message channel, if bulk auxiliary is being sent on that service. (The user + * can guarantee this by enabling unaligned transmits). + * Not API. */ +#ifndef VCHI_MIN_BULK_SIZE +# define VCHI_MIN_BULK_SIZE ( VCHI_MAX_MSG_SIZE / 2 < 4096 ? VCHI_MAX_MSG_SIZE / 2 : 4096 ) +#endif + +/* Maximum size of bulk transmission chunks, for each interface type. A trade-off between + * speed and latency; the smaller the chunk size the better change of messages and other + * bulk transmissions getting in when big bulk transfers are happening. Set to 0 to not + * break transmissions into chunks. + */ +#ifndef VCHI_MAX_BULK_CHUNK_SIZE_MPHI +# define VCHI_MAX_BULK_CHUNK_SIZE_MPHI (16 * 1024) +#endif + +/* NB Chunked CCP2 transmissions violate the letter of the CCP2 spec by using "JPEG8" mode + * with multiple-line frames. Only use if the receiver can cope. */ +#ifndef VCHI_MAX_BULK_CHUNK_SIZE_CCP2 +# define VCHI_MAX_BULK_CHUNK_SIZE_CCP2 0 +#endif + +/* How many TX messages can we have pending in our transmit slots. Once exhausted, + * vchi_msg_queue will be blocked. */ +#ifndef VCHI_TX_MSG_QUEUE_SIZE +# define VCHI_TX_MSG_QUEUE_SIZE 256 +#endif + +/* How many RX messages can we have parsed in the receive slots. Once exhausted, parsing + * will be suspended until older messages are dequeued/released. */ +#ifndef VCHI_RX_MSG_QUEUE_SIZE +# define VCHI_RX_MSG_QUEUE_SIZE 256 +#endif + +/* Really should be able to cope if we run out of received message descriptors, by + * suspending parsing as the comment above says, but we don't. This sweeps the issue + * under the carpet. */ +#if VCHI_RX_MSG_QUEUE_SIZE < (VCHI_MAX_MSG_SIZE/16 + 1) * VCHI_NUM_READ_SLOTS +# undef VCHI_RX_MSG_QUEUE_SIZE +# define VCHI_RX_MSG_QUEUE_SIZE (VCHI_MAX_MSG_SIZE/16 + 1) * VCHI_NUM_READ_SLOTS +#endif + +/* How many bulk transmits can we have pending. Once exhausted, vchi_bulk_queue_transmit + * will be blocked. */ +#ifndef VCHI_TX_BULK_QUEUE_SIZE +# define VCHI_TX_BULK_QUEUE_SIZE 64 +#endif + +/* How many bulk receives can we have pending. Once exhausted, vchi_bulk_queue_receive + * will be blocked. */ +#ifndef VCHI_RX_BULK_QUEUE_SIZE +# define VCHI_RX_BULK_QUEUE_SIZE 64 +#endif + +/* A limit on how many outstanding bulk requests we expect the peer to give us. If + * the peer asks for more than this, VCHI will fail and assert. The number is determined + * by the peer's hardware - it's the number of outstanding requests that can be queued + * on all bulk channels. VC3's MPHI peripheral allows 16. */ +#ifndef VCHI_MAX_PEER_BULK_REQUESTS +# define VCHI_MAX_PEER_BULK_REQUESTS 32 +#endif + +/* Define VCHI_CCP2TX_MANUAL_POWER if the host tells us when to turn the CCP2 + * transmitter on and off. + */ +/*#define VCHI_CCP2TX_MANUAL_POWER*/ + +#ifndef VCHI_CCP2TX_MANUAL_POWER + +/* Timeout (in milliseconds) for putting the CCP2TX interface into IDLE state. Set + * negative for no IDLE. + */ +# ifndef VCHI_CCP2TX_IDLE_TIMEOUT +# define VCHI_CCP2TX_IDLE_TIMEOUT 5 +# endif + +/* Timeout (in milliseconds) for putting the CCP2TX interface into OFF state. Set + * negative for no OFF. + */ +# ifndef VCHI_CCP2TX_OFF_TIMEOUT +# define VCHI_CCP2TX_OFF_TIMEOUT 1000 +# endif + +#endif /* VCHI_CCP2TX_MANUAL_POWER */ + +#endif /* VCHI_CFG_H_ */ + +/****************************** End of file **********************************/ diff --git a/drivers/staging/vc04_services/interface/vchi/vchi_cfg_internal.h b/drivers/staging/vc04_services/interface/vchi/vchi_cfg_internal.h new file mode 100644 index 0000000..35dcba4 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchi/vchi_cfg_internal.h @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHI_CFG_INTERNAL_H_ +#define VCHI_CFG_INTERNAL_H_ + +/**************************************************************************************** + * Control optimisation attempts. + ***************************************************************************************/ + +// Don't use lots of short-term locks - use great long ones, reducing the overall locks-per-second +#define VCHI_COARSE_LOCKING + +// Avoid lock then unlock on exit from blocking queue operations (msg tx, bulk rx/tx) +// (only relevant if VCHI_COARSE_LOCKING) +#define VCHI_ELIDE_BLOCK_EXIT_LOCK + +// Avoid lock on non-blocking peek +// (only relevant if VCHI_COARSE_LOCKING) +#define VCHI_AVOID_PEEK_LOCK + +// Use one slot-handler thread per connection, rather than 1 thread dealing with all connections in rotation. +#define VCHI_MULTIPLE_HANDLER_THREADS + +// Put free descriptors onto the head of the free queue, rather than the tail, so that we don't thrash +// our way through the pool of descriptors. +#define VCHI_PUSH_FREE_DESCRIPTORS_ONTO_HEAD + +// Don't issue a MSG_AVAILABLE callback for every single message. Possibly only safe if VCHI_COARSE_LOCKING. +#define VCHI_FEWER_MSG_AVAILABLE_CALLBACKS + +// Don't use message descriptors for TX messages that don't need them +#define VCHI_MINIMISE_TX_MSG_DESCRIPTORS + +// Nano-locks for multiqueue +//#define VCHI_MQUEUE_NANOLOCKS + +// Lock-free(er) dequeuing +//#define VCHI_RX_NANOLOCKS + +#endif /*VCHI_CFG_INTERNAL_H_*/ diff --git a/drivers/staging/vc04_services/interface/vchi/vchi_common.h b/drivers/staging/vc04_services/interface/vchi/vchi_common.h new file mode 100644 index 0000000..d535a72 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchi/vchi_common.h @@ -0,0 +1,175 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHI_COMMON_H_ +#define VCHI_COMMON_H_ + + +//flags used when sending messages (must be bitmapped) +typedef enum +{ + VCHI_FLAGS_NONE = 0x0, + VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE = 0x1, // waits for message to be received, or sent (NB. not the same as being seen on other side) + VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE = 0x2, // run a callback when message sent + VCHI_FLAGS_BLOCK_UNTIL_QUEUED = 0x4, // return once the transfer is in a queue ready to go + VCHI_FLAGS_ALLOW_PARTIAL = 0x8, + VCHI_FLAGS_BLOCK_UNTIL_DATA_READ = 0x10, + VCHI_FLAGS_CALLBACK_WHEN_DATA_READ = 0x20, + + VCHI_FLAGS_ALIGN_SLOT = 0x000080, // internal use only + VCHI_FLAGS_BULK_AUX_QUEUED = 0x010000, // internal use only + VCHI_FLAGS_BULK_AUX_COMPLETE = 0x020000, // internal use only + VCHI_FLAGS_BULK_DATA_QUEUED = 0x040000, // internal use only + VCHI_FLAGS_BULK_DATA_COMPLETE = 0x080000, // internal use only + VCHI_FLAGS_INTERNAL = 0xFF0000 +} VCHI_FLAGS_T; + +// constants for vchi_crc_control() +typedef enum { + VCHI_CRC_NOTHING = -1, + VCHI_CRC_PER_SERVICE = 0, + VCHI_CRC_EVERYTHING = 1, +} VCHI_CRC_CONTROL_T; + +//callback reasons when an event occurs on a service +typedef enum +{ + VCHI_CALLBACK_REASON_MIN, + + //This indicates that there is data available + //handle is the msg id that was transmitted with the data + // When a message is received and there was no FULL message available previously, send callback + // Tasks get kicked by the callback, reset their event and try and read from the fifo until it fails + VCHI_CALLBACK_MSG_AVAILABLE, + VCHI_CALLBACK_MSG_SENT, + VCHI_CALLBACK_MSG_SPACE_AVAILABLE, // XXX not yet implemented + + // This indicates that a transfer from the other side has completed + VCHI_CALLBACK_BULK_RECEIVED, + //This indicates that data queued up to be sent has now gone + //handle is the msg id that was used when sending the data + VCHI_CALLBACK_BULK_SENT, + VCHI_CALLBACK_BULK_RX_SPACE_AVAILABLE, // XXX not yet implemented + VCHI_CALLBACK_BULK_TX_SPACE_AVAILABLE, // XXX not yet implemented + + VCHI_CALLBACK_SERVICE_CLOSED, + + // this side has sent XOFF to peer due to lack of data consumption by service + // (suggests the service may need to take some recovery action if it has + // been deliberately holding off consuming data) + VCHI_CALLBACK_SENT_XOFF, + VCHI_CALLBACK_SENT_XON, + + // indicates that a bulk transfer has finished reading the source buffer + VCHI_CALLBACK_BULK_DATA_READ, + + // power notification events (currently host side only) + VCHI_CALLBACK_PEER_OFF, + VCHI_CALLBACK_PEER_SUSPENDED, + VCHI_CALLBACK_PEER_ON, + VCHI_CALLBACK_PEER_RESUMED, + VCHI_CALLBACK_FORCED_POWER_OFF, + +#ifdef USE_VCHIQ_ARM + // some extra notifications provided by vchiq_arm + VCHI_CALLBACK_SERVICE_OPENED, + VCHI_CALLBACK_BULK_RECEIVE_ABORTED, + VCHI_CALLBACK_BULK_TRANSMIT_ABORTED, +#endif + + VCHI_CALLBACK_REASON_MAX +} VCHI_CALLBACK_REASON_T; + +// service control options +typedef enum +{ + VCHI_SERVICE_OPTION_MIN, + + VCHI_SERVICE_OPTION_TRACE, + VCHI_SERVICE_OPTION_SYNCHRONOUS, + + VCHI_SERVICE_OPTION_MAX +} VCHI_SERVICE_OPTION_T; + + +//Callback used by all services / bulk transfers +typedef void (*VCHI_CALLBACK_T)( void *callback_param, //my service local param + VCHI_CALLBACK_REASON_T reason, + void *handle ); //for transmitting msg's only + + + +/* + * Define vector struct for scatter-gather (vector) operations + * Vectors can be nested - if a vector element has negative length, then + * the data pointer is treated as pointing to another vector array, with + * '-vec_len' elements. Thus to append a header onto an existing vector, + * you can do this: + * + * void foo(const VCHI_MSG_VECTOR_T *v, int n) + * { + * VCHI_MSG_VECTOR_T nv[2]; + * nv[0].vec_base = my_header; + * nv[0].vec_len = sizeof my_header; + * nv[1].vec_base = v; + * nv[1].vec_len = -n; + * ... + * + */ +typedef struct vchi_msg_vector { + const void *vec_base; + int32_t vec_len; +} VCHI_MSG_VECTOR_T; + +// Opaque type for a connection API +typedef struct opaque_vchi_connection_api_t VCHI_CONNECTION_API_T; + +// Opaque type for a message driver +typedef struct opaque_vchi_message_driver_t VCHI_MESSAGE_DRIVER_T; + + +// Iterator structure for reading ahead through received message queue. Allocated by client, +// initialised by vchi_msg_look_ahead. Fields are for internal VCHI use only. +// Iterates over messages in queue at the instant of the call to vchi_msg_lookahead - +// will not proceed to messages received since. Behaviour is undefined if an iterator +// is used again after messages for that service are removed/dequeued by any +// means other than vchi_msg_iter_... calls on the iterator itself. +typedef struct { + struct opaque_vchi_service_t *service; + void *last; + void *next; + void *remove; +} VCHI_MSG_ITER_T; + + +#endif // VCHI_COMMON_H_ diff --git a/drivers/staging/vc04_services/interface/vchi/vchi_mh.h b/drivers/staging/vc04_services/interface/vchi/vchi_mh.h new file mode 100644 index 0000000..198bd07 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchi/vchi_mh.h @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHI_MH_H_ +#define VCHI_MH_H_ + +#include <linux/types.h> + +typedef int32_t VCHI_MEM_HANDLE_T; +#define VCHI_MEM_HANDLE_INVALID 0 + +#endif diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq.h new file mode 100644 index 0000000..ad398ba --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq.h @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHIQ_VCHIQ_H +#define VCHIQ_VCHIQ_H + +#include "vchiq_if.h" +#include "vchiq_util.h" + +#endif diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835.h new file mode 100644 index 0000000..7ea5c64 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835.h @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHIQ_2835_H +#define VCHIQ_2835_H + +#include "vchiq_pagelist.h" + +#define VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX 0 +#define VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX 1 + +#endif /* VCHIQ_2835_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 new file mode 100644 index 0000000..c29040f --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c @@ -0,0 +1,586 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/interrupt.h> +#include <linux/pagemap.h> +#include <linux/dma-mapping.h> +#include <linux/version.h> +#include <linux/io.h> +#include <linux/platform_device.h> +#include <linux/uaccess.h> +#include <linux/of.h> +#include <asm/pgtable.h> +#include <soc/bcm2835/raspberrypi-firmware.h> + +#define dmac_map_area __glue(_CACHE,_dma_map_area) +#define dmac_unmap_area __glue(_CACHE,_dma_unmap_area) + +extern void dmac_map_area(const void *, size_t, int); +extern void dmac_unmap_area(const void *, size_t, int); + +#define TOTAL_SLOTS (VCHIQ_SLOT_ZERO_SLOTS + 2 * 32) + +#define VCHIQ_ARM_ADDRESS(x) ((void *)((char *)x + g_virt_to_bus_offset)) + +#include "vchiq_arm.h" +#include "vchiq_2835.h" +#include "vchiq_connected.h" +#include "vchiq_killable.h" + +#define MAX_FRAGMENTS (VCHIQ_NUM_CURRENT_BULKS * 2) + +#define BELL0 0x00 +#define BELL2 0x08 + +typedef struct vchiq_2835_state_struct { + int inited; + VCHIQ_ARM_STATE_T arm_state; +} VCHIQ_2835_ARM_STATE_T; + +static void __iomem *g_regs; +static unsigned int g_cache_line_size = sizeof(CACHE_LINE_SIZE); +static unsigned int g_fragments_size; +static char *g_fragments_base; +static char *g_free_fragments; +static struct semaphore g_free_fragments_sema; +static unsigned long g_virt_to_bus_offset; + +extern int vchiq_arm_log_level; + +static DEFINE_SEMAPHORE(g_free_fragments_mutex); + +static irqreturn_t +vchiq_doorbell_irq(int irq, void *dev_id); + +static int +create_pagelist(char __user *buf, size_t count, unsigned short type, + struct task_struct *task, PAGELIST_T ** ppagelist); + +static void +free_pagelist(PAGELIST_T *pagelist, int actual); + +int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state) +{ + struct device *dev = &pdev->dev; + struct rpi_firmware *fw = platform_get_drvdata(pdev); + VCHIQ_SLOT_ZERO_T *vchiq_slot_zero; + struct resource *res; + void *slot_mem; + dma_addr_t slot_phys; + u32 channelbase; + int slot_mem_size, frag_mem_size; + int err, irq, i; + + g_virt_to_bus_offset = virt_to_dma(dev, (void *)0); + + (void)of_property_read_u32(dev->of_node, "cache-line-size", + &g_cache_line_size); + g_fragments_size = 2 * g_cache_line_size; + + /* Allocate space for the channels in coherent memory */ + slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE); + frag_mem_size = PAGE_ALIGN(g_fragments_size * MAX_FRAGMENTS); + + slot_mem = dmam_alloc_coherent(dev, slot_mem_size + frag_mem_size, + &slot_phys, GFP_KERNEL); + if (!slot_mem) { + dev_err(dev, "could not allocate DMA memory\n"); + return -ENOMEM; + } + + WARN_ON(((int)slot_mem & (PAGE_SIZE - 1)) != 0); + + vchiq_slot_zero = vchiq_init_slots(slot_mem, slot_mem_size); + if (!vchiq_slot_zero) + return -EINVAL; + + vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX] = + (int)slot_phys + slot_mem_size; + vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX] = + MAX_FRAGMENTS; + + g_fragments_base = (char *)slot_mem + slot_mem_size; + slot_mem_size += frag_mem_size; + + g_free_fragments = g_fragments_base; + for (i = 0; i < (MAX_FRAGMENTS - 1); i++) { + *(char **)&g_fragments_base[i*g_fragments_size] = + &g_fragments_base[(i + 1)*g_fragments_size]; + } + *(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, 0) != VCHIQ_SUCCESS) + return -EINVAL; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + g_regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(g_regs)) + return PTR_ERR(g_regs); + + irq = platform_get_irq(pdev, 0); + if (irq <= 0) { + dev_err(dev, "failed to get IRQ\n"); + return irq; + } + + err = devm_request_irq(dev, irq, vchiq_doorbell_irq, IRQF_IRQPOLL, + "VCHIQ doorbell", state); + if (err) { + dev_err(dev, "failed to register irq=%d\n", irq); + return err; + } + + /* Send the base address of the slots to VideoCore */ + channelbase = slot_phys; + err = rpi_firmware_property(fw, RPI_FIRMWARE_VCHIQ_INIT, + &channelbase, sizeof(channelbase)); + if (err || channelbase) { + dev_err(dev, "failed to set channelbase\n"); + return err ? : -ENXIO; + } + + vchiq_log_info(vchiq_arm_log_level, + "vchiq_init - done (slots %x, phys %pad)", + (unsigned int)vchiq_slot_zero, &slot_phys); + + vchiq_call_connected_callbacks(); + + return 0; +} + +VCHIQ_STATUS_T +vchiq_platform_init_state(VCHIQ_STATE_T *state) +{ + VCHIQ_STATUS_T status = VCHIQ_SUCCESS; + state->platform_state = kzalloc(sizeof(VCHIQ_2835_ARM_STATE_T), GFP_KERNEL); + ((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->inited = 1; + status = vchiq_arm_init_state(state, &((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->arm_state); + if(status != VCHIQ_SUCCESS) + { + ((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->inited = 0; + } + return status; +} + +VCHIQ_ARM_STATE_T* +vchiq_platform_get_arm_state(VCHIQ_STATE_T *state) +{ + if(!((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->inited) + { + BUG(); + } + return &((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->arm_state; +} + +void +remote_event_signal(REMOTE_EVENT_T *event) +{ + wmb(); + + event->fired = 1; + + dsb(); /* data barrier operation */ + + if (event->armed) + writel(0, g_regs + BELL2); /* trigger vc interrupt */ +} + +int +vchiq_copy_from_user(void *dst, const void *src, int size) +{ + if ((uint32_t)src < TASK_SIZE) { + return copy_from_user(dst, src, size); + } else { + memcpy(dst, src, size); + return 0; + } +} + +VCHIQ_STATUS_T +vchiq_prepare_bulk_data(VCHIQ_BULK_T *bulk, VCHI_MEM_HANDLE_T memhandle, + void *offset, int size, int dir) +{ + PAGELIST_T *pagelist; + int ret; + + WARN_ON(memhandle != VCHI_MEM_HANDLE_INVALID); + + ret = create_pagelist((char __user *)offset, size, + (dir == VCHIQ_BULK_RECEIVE) + ? PAGELIST_READ + : PAGELIST_WRITE, + current, + &pagelist); + if (ret != 0) + return VCHIQ_ERROR; + + bulk->handle = memhandle; + bulk->data = VCHIQ_ARM_ADDRESS(pagelist); + + /* Store the pagelist address in remote_data, which isn't used by the + slave. */ + bulk->remote_data = pagelist; + + return VCHIQ_SUCCESS; +} + +void +vchiq_complete_bulk(VCHIQ_BULK_T *bulk) +{ + if (bulk && bulk->remote_data && bulk->actual) + free_pagelist((PAGELIST_T *)bulk->remote_data, bulk->actual); +} + +void +vchiq_transfer_bulk(VCHIQ_BULK_T *bulk) +{ + /* + * This should only be called on the master (VideoCore) side, but + * provide an implementation to avoid the need for ifdefery. + */ + BUG(); +} + +void +vchiq_dump_platform_state(void *dump_context) +{ + char buf[80]; + int len; + len = snprintf(buf, sizeof(buf), + " Platform: 2835 (VC master)"); + vchiq_dump(dump_context, buf, len + 1); +} + +VCHIQ_STATUS_T +vchiq_platform_suspend(VCHIQ_STATE_T *state) +{ + return VCHIQ_ERROR; +} + +VCHIQ_STATUS_T +vchiq_platform_resume(VCHIQ_STATE_T *state) +{ + return VCHIQ_SUCCESS; +} + +void +vchiq_platform_paused(VCHIQ_STATE_T *state) +{ +} + +void +vchiq_platform_resumed(VCHIQ_STATE_T *state) +{ +} + +int +vchiq_platform_videocore_wanted(VCHIQ_STATE_T* state) +{ + return 1; // autosuspend not supported - videocore always wanted +} + +int +vchiq_platform_use_suspend_timer(void) +{ + return 0; +} +void +vchiq_dump_platform_use_state(VCHIQ_STATE_T *state) +{ + vchiq_log_info(vchiq_arm_log_level, "Suspend timer not in use"); +} +void +vchiq_platform_handle_timeout(VCHIQ_STATE_T *state) +{ + (void)state; +} +/* + * Local functions + */ + +static irqreturn_t +vchiq_doorbell_irq(int irq, void *dev_id) +{ + VCHIQ_STATE_T *state = dev_id; + irqreturn_t ret = IRQ_NONE; + unsigned int status; + + /* Read (and clear) the doorbell */ + status = readl(g_regs + BELL0); + + if (status & 0x4) { /* Was the doorbell rung? */ + remote_event_pollall(state); + ret = IRQ_HANDLED; + } + + return ret; +} + +/* There is a potential problem with partial cache lines (pages?) +** at the ends of the block when reading. If the CPU accessed anything in +** the same line (page?) then it may have pulled old data into the cache, +** obscuring the new data underneath. We can solve this by transferring the +** partial cache lines separately, and allowing the ARM to copy into the +** cached area. + +** N.B. This implementation plays slightly fast and loose with the Linux +** driver programming rules, e.g. its use of dmac_map_area instead of +** dma_map_single, but it isn't a multi-platform driver and it benefits +** from increased speed as a result. +*/ + +static int +create_pagelist(char __user *buf, size_t count, unsigned short type, + struct task_struct *task, PAGELIST_T ** ppagelist) +{ + PAGELIST_T *pagelist; + struct page **pages; + unsigned long *addrs; + unsigned int num_pages, offset, i; + char *addr, *base_addr, *next_addr; + int run, addridx, actual_pages; + unsigned long *need_release; + + offset = (unsigned int)buf & (PAGE_SIZE - 1); + num_pages = (count + offset + PAGE_SIZE - 1) / PAGE_SIZE; + + *ppagelist = NULL; + + /* Allocate enough storage to hold the page pointers and the page + ** list + */ + pagelist = kmalloc(sizeof(PAGELIST_T) + + (num_pages * sizeof(unsigned long)) + + sizeof(unsigned long) + + (num_pages * sizeof(pages[0])), + GFP_KERNEL); + + vchiq_log_trace(vchiq_arm_log_level, + "create_pagelist - %x", (unsigned int)pagelist); + if (!pagelist) + return -ENOMEM; + + addrs = pagelist->addrs; + need_release = (unsigned long *)(addrs + num_pages); + pages = (struct page **)(addrs + num_pages + 1); + + if (is_vmalloc_addr(buf)) { + int dir = (type == PAGELIST_WRITE) ? + DMA_TO_DEVICE : DMA_FROM_DEVICE; + unsigned long length = count; + unsigned int off = offset; + + for (actual_pages = 0; actual_pages < num_pages; + actual_pages++) { + struct page *pg = vmalloc_to_page(buf + (actual_pages * + PAGE_SIZE)); + size_t bytes = PAGE_SIZE - off; + + if (bytes > length) + bytes = length; + pages[actual_pages] = pg; + dmac_map_area(page_address(pg) + off, bytes, dir); + length -= bytes; + off = 0; + } + *need_release = 0; /* do not try and release vmalloc pages */ + } else { + down_read(&task->mm->mmap_sem); + actual_pages = get_user_pages(task, task->mm, + (unsigned long)buf & ~(PAGE_SIZE - 1), + num_pages, + (type == PAGELIST_READ) /*Write */ , + 0 /*Force */ , + pages, + NULL /*vmas */); + up_read(&task->mm->mmap_sem); + + if (actual_pages != num_pages) { + vchiq_log_info(vchiq_arm_log_level, + "create_pagelist - only %d/%d pages locked", + actual_pages, + num_pages); + + /* This is probably due to the process being killed */ + while (actual_pages > 0) + { + actual_pages--; + page_cache_release(pages[actual_pages]); + } + kfree(pagelist); + if (actual_pages == 0) + actual_pages = -ENOMEM; + return actual_pages; + } + *need_release = 1; /* release user pages */ + } + + pagelist->length = count; + pagelist->type = type; + pagelist->offset = offset; + + /* Group the pages into runs of contiguous pages */ + + base_addr = VCHIQ_ARM_ADDRESS(page_address(pages[0])); + next_addr = base_addr + PAGE_SIZE; + addridx = 0; + run = 0; + + for (i = 1; i < num_pages; i++) { + addr = VCHIQ_ARM_ADDRESS(page_address(pages[i])); + if ((addr == next_addr) && (run < (PAGE_SIZE - 1))) { + next_addr += PAGE_SIZE; + run++; + } else { + addrs[addridx] = (unsigned long)base_addr + run; + addridx++; + base_addr = addr; + next_addr = addr + PAGE_SIZE; + run = 0; + } + } + + addrs[addridx] = (unsigned long)base_addr + run; + addridx++; + + /* Partial cache lines (fragments) require special measures */ + if ((type == PAGELIST_READ) && + ((pagelist->offset & (g_cache_line_size - 1)) || + ((pagelist->offset + pagelist->length) & + (g_cache_line_size - 1)))) { + char *fragments; + + if (down_interruptible(&g_free_fragments_sema) != 0) { + kfree(pagelist); + return -EINTR; + } + + WARN_ON(g_free_fragments == NULL); + + down(&g_free_fragments_mutex); + fragments = g_free_fragments; + WARN_ON(fragments == NULL); + g_free_fragments = *(char **) g_free_fragments; + up(&g_free_fragments_mutex); + pagelist->type = PAGELIST_READ_WITH_FRAGMENTS + + (fragments - g_fragments_base) / g_fragments_size; + } + + dmac_flush_range(pagelist, addrs + num_pages); + + *ppagelist = pagelist; + + return 0; +} + +static void +free_pagelist(PAGELIST_T *pagelist, int actual) +{ + unsigned long *need_release; + struct page **pages; + unsigned int num_pages, i; + + vchiq_log_trace(vchiq_arm_log_level, + "free_pagelist - %x, %d", (unsigned int)pagelist, actual); + + num_pages = + (pagelist->length + pagelist->offset + PAGE_SIZE - 1) / + PAGE_SIZE; + + need_release = (unsigned long *)(pagelist->addrs + num_pages); + pages = (struct page **)(pagelist->addrs + num_pages + 1); + + /* Deal with any partial cache lines (fragments) */ + if (pagelist->type >= PAGELIST_READ_WITH_FRAGMENTS) { + char *fragments = g_fragments_base + + (pagelist->type - PAGELIST_READ_WITH_FRAGMENTS) * + g_fragments_size; + int head_bytes, tail_bytes; + head_bytes = (g_cache_line_size - pagelist->offset) & + (g_cache_line_size - 1); + tail_bytes = (pagelist->offset + actual) & + (g_cache_line_size - 1); + + if ((actual >= 0) && (head_bytes != 0)) { + if (head_bytes > actual) + head_bytes = actual; + + memcpy((char *)page_address(pages[0]) + + pagelist->offset, + fragments, + head_bytes); + } + if ((actual >= 0) && (head_bytes < actual) && + (tail_bytes != 0)) { + memcpy((char *)page_address(pages[num_pages - 1]) + + ((pagelist->offset + actual) & + (PAGE_SIZE - 1) & ~(g_cache_line_size - 1)), + fragments + g_cache_line_size, + tail_bytes); + } + + down(&g_free_fragments_mutex); + *(char **)fragments = g_free_fragments; + g_free_fragments = fragments; + up(&g_free_fragments_mutex); + up(&g_free_fragments_sema); + } + + if (*need_release) { + unsigned int length = pagelist->length; + unsigned int offset = pagelist->offset; + + for (i = 0; i < num_pages; i++) { + struct page *pg = pages[i]; + + if (pagelist->type != PAGELIST_WRITE) { + unsigned int bytes = PAGE_SIZE - offset; + + if (bytes > length) + bytes = length; + dmac_unmap_area(page_address(pg) + offset, + bytes, DMA_FROM_DEVICE); + length -= bytes; + offset = 0; + set_page_dirty(pg); + } + page_cache_release(pg); + } + } + + kfree(pagelist); +} diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c new file mode 100644 index 0000000..e11c0e0 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -0,0 +1,2903 @@ +/** + * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved. + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/cdev.h> +#include <linux/fs.h> +#include <linux/device.h> +#include <linux/mm.h> +#include <linux/highmem.h> +#include <linux/pagemap.h> +#include <linux/bug.h> +#include <linux/semaphore.h> +#include <linux/list.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <soc/bcm2835/raspberrypi-firmware.h> + +#include "vchiq_core.h" +#include "vchiq_ioctl.h" +#include "vchiq_arm.h" +#include "vchiq_debugfs.h" +#include "vchiq_killable.h" + +#define DEVICE_NAME "vchiq" + +/* Override the default prefix, which would be vchiq_arm (from the filename) */ +#undef MODULE_PARAM_PREFIX +#define MODULE_PARAM_PREFIX DEVICE_NAME "." + +#define VCHIQ_MINOR 0 + +/* Some per-instance constants */ +#define MAX_COMPLETIONS 16 +#define MAX_SERVICES 64 +#define MAX_ELEMENTS 8 +#define MSG_QUEUE_SIZE 64 + +#define KEEPALIVE_VER 1 +#define KEEPALIVE_VER_MIN KEEPALIVE_VER + +/* Run time control of log level, based on KERN_XXX level. */ +int vchiq_arm_log_level = VCHIQ_LOG_DEFAULT; +int vchiq_susp_log_level = VCHIQ_LOG_ERROR; + +#define SUSPEND_TIMER_TIMEOUT_MS 100 +#define SUSPEND_RETRY_TIMER_TIMEOUT_MS 1000 + +#define VC_SUSPEND_NUM_OFFSET 3 /* number of values before idle which are -ve */ +static const char *const suspend_state_names[] = { + "VC_SUSPEND_FORCE_CANCELED", + "VC_SUSPEND_REJECTED", + "VC_SUSPEND_FAILED", + "VC_SUSPEND_IDLE", + "VC_SUSPEND_REQUESTED", + "VC_SUSPEND_IN_PROGRESS", + "VC_SUSPEND_SUSPENDED" +}; +#define VC_RESUME_NUM_OFFSET 1 /* number of values before idle which are -ve */ +static const char *const resume_state_names[] = { + "VC_RESUME_FAILED", + "VC_RESUME_IDLE", + "VC_RESUME_REQUESTED", + "VC_RESUME_IN_PROGRESS", + "VC_RESUME_RESUMED" +}; +/* The number of times we allow force suspend to timeout before actually +** _forcing_ suspend. This is to cater for SW which fails to release vchiq +** correctly - we don't want to prevent ARM suspend indefinitely in this case. +*/ +#define FORCE_SUSPEND_FAIL_MAX 8 + +/* The time in ms allowed for videocore to go idle when force suspend has been + * requested */ +#define FORCE_SUSPEND_TIMEOUT_MS 200 + + +static void suspend_timer_callback(unsigned long context); + + +typedef struct user_service_struct { + VCHIQ_SERVICE_T *service; + void *userdata; + VCHIQ_INSTANCE_T instance; + char is_vchi; + char dequeue_pending; + char close_pending; + int message_available_pos; + int msg_insert; + int msg_remove; + struct semaphore insert_event; + struct semaphore remove_event; + struct semaphore close_event; + VCHIQ_HEADER_T * msg_queue[MSG_QUEUE_SIZE]; +} USER_SERVICE_T; + +struct bulk_waiter_node { + struct bulk_waiter bulk_waiter; + int pid; + struct list_head list; +}; + +struct vchiq_instance_struct { + VCHIQ_STATE_T *state; + VCHIQ_COMPLETION_DATA_T completions[MAX_COMPLETIONS]; + int completion_insert; + int completion_remove; + struct semaphore insert_event; + struct semaphore remove_event; + struct mutex completion_mutex; + + int connected; + int closing; + int pid; + int mark; + int use_close_delivered; + int trace; + + struct list_head bulk_waiter_list; + struct mutex bulk_waiter_list_mutex; + + VCHIQ_DEBUGFS_NODE_T debugfs_node; +}; + +typedef struct dump_context_struct { + char __user *buf; + size_t actual; + size_t space; + loff_t offset; +} DUMP_CONTEXT_T; + +static struct cdev vchiq_cdev; +static dev_t vchiq_devid; +static VCHIQ_STATE_T g_state; +static struct class *vchiq_class; +static struct device *vchiq_dev; +static DEFINE_SPINLOCK(msg_queue_spinlock); + +static const char *const ioctl_names[] = { + "CONNECT", + "SHUTDOWN", + "CREATE_SERVICE", + "REMOVE_SERVICE", + "QUEUE_MESSAGE", + "QUEUE_BULK_TRANSMIT", + "QUEUE_BULK_RECEIVE", + "AWAIT_COMPLETION", + "DEQUEUE_MESSAGE", + "GET_CLIENT_ID", + "GET_CONFIG", + "CLOSE_SERVICE", + "USE_SERVICE", + "RELEASE_SERVICE", + "SET_SERVICE_OPTION", + "DUMP_PHYS_MEM", + "LIB_VERSION", + "CLOSE_DELIVERED" +}; + +vchiq_static_assert((sizeof(ioctl_names)/sizeof(ioctl_names[0])) == + (VCHIQ_IOC_MAX + 1)); + +static void +dump_phys_mem(void *virt_addr, uint32_t num_bytes); + +/**************************************************************************** +* +* add_completion +* +***************************************************************************/ + +static VCHIQ_STATUS_T +add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, + VCHIQ_HEADER_T *header, USER_SERVICE_T *user_service, + void *bulk_userdata) +{ + VCHIQ_COMPLETION_DATA_T *completion; + DEBUG_INITIALISE(g_state.local) + + while (instance->completion_insert == + (instance->completion_remove + MAX_COMPLETIONS)) { + /* Out of space - wait for the client */ + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + vchiq_log_trace(vchiq_arm_log_level, + "add_completion - completion queue full"); + DEBUG_COUNT(COMPLETION_QUEUE_FULL_COUNT); + if (down_interruptible(&instance->remove_event) != 0) { + vchiq_log_info(vchiq_arm_log_level, + "service_callback interrupted"); + return VCHIQ_RETRY; + } else if (instance->closing) { + vchiq_log_info(vchiq_arm_log_level, + "service_callback closing"); + return VCHIQ_ERROR; + } + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + } + + completion = + &instance->completions[instance->completion_insert & + (MAX_COMPLETIONS - 1)]; + + completion->header = header; + completion->reason = reason; + /* N.B. service_userdata is updated while processing AWAIT_COMPLETION */ + completion->service_userdata = user_service->service; + completion->bulk_userdata = bulk_userdata; + + if (reason == VCHIQ_SERVICE_CLOSED) { + /* Take an extra reference, to be held until + this CLOSED notification is delivered. */ + lock_service(user_service->service); + if (instance->use_close_delivered) + user_service->close_pending = 1; + } + + /* A write barrier is needed here to ensure that the entire completion + record is written out before the insert point. */ + wmb(); + + if (reason == VCHIQ_MESSAGE_AVAILABLE) + user_service->message_available_pos = + instance->completion_insert; + instance->completion_insert++; + + up(&instance->insert_event); + + return VCHIQ_SUCCESS; +} + +/**************************************************************************** +* +* service_callback +* +***************************************************************************/ + +static VCHIQ_STATUS_T +service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header, + VCHIQ_SERVICE_HANDLE_T handle, void *bulk_userdata) +{ + /* How do we ensure the callback goes to the right client? + ** The service_user data points to a USER_SERVICE_T record containing + ** the original callback and the user state structure, which contains a + ** circular buffer for completion records. + */ + USER_SERVICE_T *user_service; + VCHIQ_SERVICE_T *service; + VCHIQ_INSTANCE_T instance; + DEBUG_INITIALISE(g_state.local) + + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + + service = handle_to_service(handle); + BUG_ON(!service); + user_service = (USER_SERVICE_T *)service->base.userdata; + instance = user_service->instance; + + if (!instance || instance->closing) + return VCHIQ_SUCCESS; + + vchiq_log_trace(vchiq_arm_log_level, + "service_callback - service %lx(%d,%p), reason %d, header %lx, " + "instance %lx, bulk_userdata %lx", + (unsigned long)user_service, + service->localport, user_service->userdata, + reason, (unsigned long)header, + (unsigned long)instance, (unsigned long)bulk_userdata); + + if (header && user_service->is_vchi) { + spin_lock(&msg_queue_spinlock); + while (user_service->msg_insert == + (user_service->msg_remove + MSG_QUEUE_SIZE)) { + spin_unlock(&msg_queue_spinlock); + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + DEBUG_COUNT(MSG_QUEUE_FULL_COUNT); + vchiq_log_trace(vchiq_arm_log_level, + "service_callback - msg queue full"); + /* If there is no MESSAGE_AVAILABLE in the completion + ** queue, add one + */ + if ((user_service->message_available_pos - + instance->completion_remove) < 0) { + VCHIQ_STATUS_T status; + vchiq_log_info(vchiq_arm_log_level, + "Inserting extra MESSAGE_AVAILABLE"); + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + status = add_completion(instance, reason, + NULL, user_service, bulk_userdata); + if (status != VCHIQ_SUCCESS) { + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + return status; + } + } + + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + if (down_interruptible(&user_service->remove_event) + != 0) { + vchiq_log_info(vchiq_arm_log_level, + "service_callback interrupted"); + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + return VCHIQ_RETRY; + } else if (instance->closing) { + vchiq_log_info(vchiq_arm_log_level, + "service_callback closing"); + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + return VCHIQ_ERROR; + } + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + spin_lock(&msg_queue_spinlock); + } + + user_service->msg_queue[user_service->msg_insert & + (MSG_QUEUE_SIZE - 1)] = header; + user_service->msg_insert++; + spin_unlock(&msg_queue_spinlock); + + up(&user_service->insert_event); + + /* If there is a thread waiting in DEQUEUE_MESSAGE, or if + ** there is a MESSAGE_AVAILABLE in the completion queue then + ** bypass the completion queue. + */ + if (((user_service->message_available_pos - + instance->completion_remove) >= 0) || + user_service->dequeue_pending) { + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + user_service->dequeue_pending = 0; + return VCHIQ_SUCCESS; + } + + header = NULL; + } + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + + return add_completion(instance, reason, header, user_service, + bulk_userdata); +} + +/**************************************************************************** +* +* user_service_free +* +***************************************************************************/ +static void +user_service_free(void *userdata) +{ + kfree(userdata); +} + +/**************************************************************************** +* +* close_delivered +* +***************************************************************************/ +static void close_delivered(USER_SERVICE_T *user_service) +{ + vchiq_log_info(vchiq_arm_log_level, + "close_delivered(handle=%x)", + user_service->service->handle); + + if (user_service->close_pending) { + /* Allow the underlying service to be culled */ + unlock_service(user_service->service); + + /* Wake the user-thread blocked in close_ or remove_service */ + up(&user_service->close_event); + + user_service->close_pending = 0; + } +} + +/**************************************************************************** +* +* vchiq_ioctl +* +***************************************************************************/ +static long +vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + VCHIQ_INSTANCE_T instance = file->private_data; + VCHIQ_STATUS_T status = VCHIQ_SUCCESS; + VCHIQ_SERVICE_T *service = NULL; + long ret = 0; + int i, rc; + DEBUG_INITIALISE(g_state.local) + + vchiq_log_trace(vchiq_arm_log_level, + "vchiq_ioctl - instance %x, cmd %s, arg %lx", + (unsigned int)instance, + ((_IOC_TYPE(cmd) == VCHIQ_IOC_MAGIC) && + (_IOC_NR(cmd) <= VCHIQ_IOC_MAX)) ? + ioctl_names[_IOC_NR(cmd)] : "<invalid>", arg); + + switch (cmd) { + case VCHIQ_IOC_SHUTDOWN: + if (!instance->connected) + break; + + /* Remove all services */ + i = 0; + while ((service = next_service_by_instance(instance->state, + instance, &i)) != NULL) { + status = vchiq_remove_service(service->handle); + unlock_service(service); + if (status != VCHIQ_SUCCESS) + break; + } + service = NULL; + + if (status == VCHIQ_SUCCESS) { + /* Wake the completion thread and ask it to exit */ + instance->closing = 1; + up(&instance->insert_event); + } + + break; + + case VCHIQ_IOC_CONNECT: + if (instance->connected) { + ret = -EINVAL; + break; + } + rc = mutex_lock_interruptible(&instance->state->mutex); + if (rc != 0) { + vchiq_log_error(vchiq_arm_log_level, + "vchiq: connect: could not lock mutex for " + "state %d: %d", + instance->state->id, rc); + ret = -EINTR; + break; + } + status = vchiq_connect_internal(instance->state, instance); + mutex_unlock(&instance->state->mutex); + + if (status == VCHIQ_SUCCESS) + instance->connected = 1; + else + vchiq_log_error(vchiq_arm_log_level, + "vchiq: could not connect: %d", status); + break; + + case VCHIQ_IOC_CREATE_SERVICE: { + VCHIQ_CREATE_SERVICE_T args; + USER_SERVICE_T *user_service = NULL; + void *userdata; + int srvstate; + + if (copy_from_user + (&args, (const void __user *)arg, + sizeof(args)) != 0) { + ret = -EFAULT; + break; + } + + user_service = kmalloc(sizeof(USER_SERVICE_T), GFP_KERNEL); + if (!user_service) { + ret = -ENOMEM; + break; + } + + if (args.is_open) { + if (!instance->connected) { + ret = -ENOTCONN; + kfree(user_service); + break; + } + srvstate = VCHIQ_SRVSTATE_OPENING; + } else { + srvstate = + instance->connected ? + VCHIQ_SRVSTATE_LISTENING : + VCHIQ_SRVSTATE_HIDDEN; + } + + userdata = args.params.userdata; + args.params.callback = service_callback; + args.params.userdata = user_service; + service = vchiq_add_service_internal( + instance->state, + &args.params, srvstate, + instance, user_service_free); + + if (service != NULL) { + user_service->service = service; + user_service->userdata = userdata; + user_service->instance = instance; + user_service->is_vchi = (args.is_vchi != 0); + user_service->dequeue_pending = 0; + user_service->close_pending = 0; + user_service->message_available_pos = + instance->completion_remove - 1; + user_service->msg_insert = 0; + user_service->msg_remove = 0; + sema_init(&user_service->insert_event, 0); + sema_init(&user_service->remove_event, 0); + sema_init(&user_service->close_event, 0); + + if (args.is_open) { + status = vchiq_open_service_internal + (service, instance->pid); + if (status != VCHIQ_SUCCESS) { + vchiq_remove_service(service->handle); + service = NULL; + ret = (status == VCHIQ_RETRY) ? + -EINTR : -EIO; + break; + } + } + + if (copy_to_user((void __user *) + &(((VCHIQ_CREATE_SERVICE_T __user *) + arg)->handle), + (const void *)&service->handle, + sizeof(service->handle)) != 0) { + ret = -EFAULT; + vchiq_remove_service(service->handle); + } + + service = NULL; + } else { + ret = -EEXIST; + kfree(user_service); + } + } break; + + case VCHIQ_IOC_CLOSE_SERVICE: { + VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg; + + service = find_service_for_instance(instance, handle); + if (service != NULL) { + USER_SERVICE_T *user_service = + (USER_SERVICE_T *)service->base.userdata; + /* close_pending is false on first entry, and when the + wait in vchiq_close_service has been interrupted. */ + if (!user_service->close_pending) { + status = vchiq_close_service(service->handle); + if (status != VCHIQ_SUCCESS) + break; + } + + /* close_pending is true once the underlying service + has been closed until the client library calls the + CLOSE_DELIVERED ioctl, signalling close_event. */ + if (user_service->close_pending && + down_interruptible(&user_service->close_event)) + status = VCHIQ_RETRY; + } + else + ret = -EINVAL; + } break; + + case VCHIQ_IOC_REMOVE_SERVICE: { + VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg; + + service = find_service_for_instance(instance, handle); + if (service != NULL) { + USER_SERVICE_T *user_service = + (USER_SERVICE_T *)service->base.userdata; + /* close_pending is false on first entry, and when the + wait in vchiq_close_service has been interrupted. */ + if (!user_service->close_pending) { + status = vchiq_remove_service(service->handle); + if (status != VCHIQ_SUCCESS) + break; + } + + /* close_pending is true once the underlying service + has been closed until the client library calls the + CLOSE_DELIVERED ioctl, signalling close_event. */ + if (user_service->close_pending && + down_interruptible(&user_service->close_event)) + status = VCHIQ_RETRY; + } + else + ret = -EINVAL; + } break; + + case VCHIQ_IOC_USE_SERVICE: + case VCHIQ_IOC_RELEASE_SERVICE: { + VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg; + + service = find_service_for_instance(instance, handle); + if (service != NULL) { + status = (cmd == VCHIQ_IOC_USE_SERVICE) ? + vchiq_use_service_internal(service) : + vchiq_release_service_internal(service); + if (status != VCHIQ_SUCCESS) { + vchiq_log_error(vchiq_susp_log_level, + "%s: cmd %s returned error %d for " + "service %c%c%c%c:%03d", + __func__, + (cmd == VCHIQ_IOC_USE_SERVICE) ? + "VCHIQ_IOC_USE_SERVICE" : + "VCHIQ_IOC_RELEASE_SERVICE", + status, + VCHIQ_FOURCC_AS_4CHARS( + service->base.fourcc), + service->client_id); + ret = -EINVAL; + } + } else + ret = -EINVAL; + } break; + + case VCHIQ_IOC_QUEUE_MESSAGE: { + VCHIQ_QUEUE_MESSAGE_T args; + if (copy_from_user + (&args, (const void __user *)arg, + sizeof(args)) != 0) { + ret = -EFAULT; + break; + } + + service = find_service_for_instance(instance, args.handle); + + if ((service != NULL) && (args.count <= MAX_ELEMENTS)) { + /* Copy elements into kernel space */ + VCHIQ_ELEMENT_T elements[MAX_ELEMENTS]; + if (copy_from_user(elements, args.elements, + args.count * sizeof(VCHIQ_ELEMENT_T)) == 0) + status = vchiq_queue_message + (args.handle, + elements, args.count); + else + ret = -EFAULT; + } else { + ret = -EINVAL; + } + } break; + + case VCHIQ_IOC_QUEUE_BULK_TRANSMIT: + case VCHIQ_IOC_QUEUE_BULK_RECEIVE: { + VCHIQ_QUEUE_BULK_TRANSFER_T args; + struct bulk_waiter_node *waiter = NULL; + VCHIQ_BULK_DIR_T dir = + (cmd == VCHIQ_IOC_QUEUE_BULK_TRANSMIT) ? + VCHIQ_BULK_TRANSMIT : VCHIQ_BULK_RECEIVE; + + if (copy_from_user + (&args, (const void __user *)arg, + sizeof(args)) != 0) { + ret = -EFAULT; + break; + } + + service = find_service_for_instance(instance, args.handle); + if (!service) { + ret = -EINVAL; + break; + } + + if (args.mode == VCHIQ_BULK_MODE_BLOCKING) { + waiter = kzalloc(sizeof(struct bulk_waiter_node), + GFP_KERNEL); + if (!waiter) { + ret = -ENOMEM; + break; + } + args.userdata = &waiter->bulk_waiter; + } else if (args.mode == VCHIQ_BULK_MODE_WAITING) { + struct list_head *pos; + mutex_lock(&instance->bulk_waiter_list_mutex); + list_for_each(pos, &instance->bulk_waiter_list) { + if (list_entry(pos, struct bulk_waiter_node, + list)->pid == current->pid) { + waiter = list_entry(pos, + struct bulk_waiter_node, + list); + list_del(pos); + break; + } + + } + mutex_unlock(&instance->bulk_waiter_list_mutex); + if (!waiter) { + vchiq_log_error(vchiq_arm_log_level, + "no bulk_waiter found for pid %d", + current->pid); + ret = -ESRCH; + break; + } + vchiq_log_info(vchiq_arm_log_level, + "found bulk_waiter %x for pid %d", + (unsigned int)waiter, current->pid); + args.userdata = &waiter->bulk_waiter; + } + status = vchiq_bulk_transfer + (args.handle, + VCHI_MEM_HANDLE_INVALID, + args.data, args.size, + args.userdata, args.mode, + dir); + if (!waiter) + break; + if ((status != VCHIQ_RETRY) || fatal_signal_pending(current) || + !waiter->bulk_waiter.bulk) { + if (waiter->bulk_waiter.bulk) { + /* Cancel the signal when the transfer + ** completes. */ + spin_lock(&bulk_waiter_spinlock); + waiter->bulk_waiter.bulk->userdata = NULL; + spin_unlock(&bulk_waiter_spinlock); + } + kfree(waiter); + } else { + const VCHIQ_BULK_MODE_T mode_waiting = + VCHIQ_BULK_MODE_WAITING; + waiter->pid = current->pid; + mutex_lock(&instance->bulk_waiter_list_mutex); + list_add(&waiter->list, &instance->bulk_waiter_list); + mutex_unlock(&instance->bulk_waiter_list_mutex); + vchiq_log_info(vchiq_arm_log_level, + "saved bulk_waiter %x for pid %d", + (unsigned int)waiter, current->pid); + + if (copy_to_user((void __user *) + &(((VCHIQ_QUEUE_BULK_TRANSFER_T __user *) + arg)->mode), + (const void *)&mode_waiting, + sizeof(mode_waiting)) != 0) + ret = -EFAULT; + } + } break; + + case VCHIQ_IOC_AWAIT_COMPLETION: { + VCHIQ_AWAIT_COMPLETION_T args; + + DEBUG_TRACE(AWAIT_COMPLETION_LINE); + if (!instance->connected) { + ret = -ENOTCONN; + break; + } + + if (copy_from_user(&args, (const void __user *)arg, + sizeof(args)) != 0) { + ret = -EFAULT; + break; + } + + mutex_lock(&instance->completion_mutex); + + DEBUG_TRACE(AWAIT_COMPLETION_LINE); + while ((instance->completion_remove == + instance->completion_insert) + && !instance->closing) { + int rc; + DEBUG_TRACE(AWAIT_COMPLETION_LINE); + mutex_unlock(&instance->completion_mutex); + rc = down_interruptible(&instance->insert_event); + mutex_lock(&instance->completion_mutex); + if (rc != 0) { + DEBUG_TRACE(AWAIT_COMPLETION_LINE); + vchiq_log_info(vchiq_arm_log_level, + "AWAIT_COMPLETION interrupted"); + ret = -EINTR; + break; + } + } + DEBUG_TRACE(AWAIT_COMPLETION_LINE); + + /* A read memory barrier is needed to stop prefetch of a stale + ** completion record + */ + rmb(); + + if (ret == 0) { + int msgbufcount = args.msgbufcount; + for (ret = 0; ret < args.count; ret++) { + VCHIQ_COMPLETION_DATA_T *completion; + VCHIQ_SERVICE_T *service; + USER_SERVICE_T *user_service; + VCHIQ_HEADER_T *header; + if (instance->completion_remove == + instance->completion_insert) + break; + completion = &instance->completions[ + instance->completion_remove & + (MAX_COMPLETIONS - 1)]; + + service = completion->service_userdata; + user_service = service->base.userdata; + completion->service_userdata = + user_service->userdata; + + header = completion->header; + if (header) { + void __user *msgbuf; + int msglen; + + msglen = header->size + + sizeof(VCHIQ_HEADER_T); + /* This must be a VCHIQ-style service */ + if (args.msgbufsize < msglen) { + vchiq_log_error( + vchiq_arm_log_level, + "header %x: msgbufsize" + " %x < msglen %x", + (unsigned int)header, + args.msgbufsize, + msglen); + WARN(1, "invalid message " + "size\n"); + if (ret == 0) + ret = -EMSGSIZE; + break; + } + if (msgbufcount <= 0) + /* Stall here for lack of a + ** buffer for the message. */ + break; + /* Get the pointer from user space */ + msgbufcount--; + if (copy_from_user(&msgbuf, + (const void __user *) + &args.msgbufs[msgbufcount], + sizeof(msgbuf)) != 0) { + if (ret == 0) + ret = -EFAULT; + break; + } + + /* Copy the message to user space */ + if (copy_to_user(msgbuf, header, + msglen) != 0) { + if (ret == 0) + ret = -EFAULT; + break; + } + + /* Now it has been copied, the message + ** can be released. */ + vchiq_release_message(service->handle, + header); + + /* The completion must point to the + ** msgbuf. */ + completion->header = msgbuf; + } + + if ((completion->reason == + VCHIQ_SERVICE_CLOSED) && + !instance->use_close_delivered) + unlock_service(service); + + if (copy_to_user((void __user *)( + (size_t)args.buf + + ret * sizeof(VCHIQ_COMPLETION_DATA_T)), + completion, + sizeof(VCHIQ_COMPLETION_DATA_T)) != 0) { + if (ret == 0) + ret = -EFAULT; + break; + } + + instance->completion_remove++; + } + + if (msgbufcount != args.msgbufcount) { + if (copy_to_user((void __user *) + &((VCHIQ_AWAIT_COMPLETION_T *)arg)-> + msgbufcount, + &msgbufcount, + sizeof(msgbufcount)) != 0) { + ret = -EFAULT; + } + } + } + + if (ret != 0) + up(&instance->remove_event); + mutex_unlock(&instance->completion_mutex); + DEBUG_TRACE(AWAIT_COMPLETION_LINE); + } break; + + case VCHIQ_IOC_DEQUEUE_MESSAGE: { + VCHIQ_DEQUEUE_MESSAGE_T args; + USER_SERVICE_T *user_service; + VCHIQ_HEADER_T *header; + + DEBUG_TRACE(DEQUEUE_MESSAGE_LINE); + if (copy_from_user + (&args, (const void __user *)arg, + sizeof(args)) != 0) { + ret = -EFAULT; + break; + } + service = find_service_for_instance(instance, args.handle); + if (!service) { + ret = -EINVAL; + break; + } + user_service = (USER_SERVICE_T *)service->base.userdata; + if (user_service->is_vchi == 0) { + ret = -EINVAL; + break; + } + + spin_lock(&msg_queue_spinlock); + if (user_service->msg_remove == user_service->msg_insert) { + if (!args.blocking) { + spin_unlock(&msg_queue_spinlock); + DEBUG_TRACE(DEQUEUE_MESSAGE_LINE); + ret = -EWOULDBLOCK; + break; + } + user_service->dequeue_pending = 1; + do { + spin_unlock(&msg_queue_spinlock); + DEBUG_TRACE(DEQUEUE_MESSAGE_LINE); + if (down_interruptible( + &user_service->insert_event) != 0) { + vchiq_log_info(vchiq_arm_log_level, + "DEQUEUE_MESSAGE interrupted"); + ret = -EINTR; + break; + } + spin_lock(&msg_queue_spinlock); + } while (user_service->msg_remove == + user_service->msg_insert); + + if (ret) + break; + } + + BUG_ON((int)(user_service->msg_insert - + user_service->msg_remove) < 0); + + header = user_service->msg_queue[user_service->msg_remove & + (MSG_QUEUE_SIZE - 1)]; + user_service->msg_remove++; + spin_unlock(&msg_queue_spinlock); + + up(&user_service->remove_event); + if (header == NULL) + ret = -ENOTCONN; + else if (header->size <= args.bufsize) { + /* Copy to user space if msgbuf is not NULL */ + if ((args.buf == NULL) || + (copy_to_user((void __user *)args.buf, + header->data, + header->size) == 0)) { + ret = header->size; + vchiq_release_message( + service->handle, + header); + } else + ret = -EFAULT; + } else { + vchiq_log_error(vchiq_arm_log_level, + "header %x: bufsize %x < size %x", + (unsigned int)header, args.bufsize, + header->size); + WARN(1, "invalid size\n"); + ret = -EMSGSIZE; + } + DEBUG_TRACE(DEQUEUE_MESSAGE_LINE); + } break; + + case VCHIQ_IOC_GET_CLIENT_ID: { + VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg; + + ret = vchiq_get_client_id(handle); + } break; + + case VCHIQ_IOC_GET_CONFIG: { + VCHIQ_GET_CONFIG_T args; + VCHIQ_CONFIG_T config; + + if (copy_from_user(&args, (const void __user *)arg, + sizeof(args)) != 0) { + ret = -EFAULT; + break; + } + if (args.config_size > sizeof(config)) { + ret = -EINVAL; + break; + } + status = vchiq_get_config(instance, args.config_size, &config); + if (status == VCHIQ_SUCCESS) { + if (copy_to_user((void __user *)args.pconfig, + &config, args.config_size) != 0) { + ret = -EFAULT; + break; + } + } + } break; + + case VCHIQ_IOC_SET_SERVICE_OPTION: { + VCHIQ_SET_SERVICE_OPTION_T args; + + if (copy_from_user( + &args, (const void __user *)arg, + sizeof(args)) != 0) { + ret = -EFAULT; + break; + } + + service = find_service_for_instance(instance, args.handle); + if (!service) { + ret = -EINVAL; + break; + } + + status = vchiq_set_service_option( + args.handle, args.option, args.value); + } break; + + case VCHIQ_IOC_DUMP_PHYS_MEM: { + VCHIQ_DUMP_MEM_T args; + + if (copy_from_user + (&args, (const void __user *)arg, + sizeof(args)) != 0) { + ret = -EFAULT; + break; + } + dump_phys_mem(args.virt_addr, args.num_bytes); + } break; + + case VCHIQ_IOC_LIB_VERSION: { + unsigned int lib_version = (unsigned int)arg; + + if (lib_version < VCHIQ_VERSION_MIN) + ret = -EINVAL; + else if (lib_version >= VCHIQ_VERSION_CLOSE_DELIVERED) + instance->use_close_delivered = 1; + } break; + + case VCHIQ_IOC_CLOSE_DELIVERED: { + VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg; + + service = find_closed_service_for_instance(instance, handle); + if (service != NULL) { + USER_SERVICE_T *user_service = + (USER_SERVICE_T *)service->base.userdata; + close_delivered(user_service); + } + else + ret = -EINVAL; + } break; + + default: + ret = -ENOTTY; + break; + } + + if (service) + unlock_service(service); + + if (ret == 0) { + if (status == VCHIQ_ERROR) + ret = -EIO; + else if (status == VCHIQ_RETRY) + ret = -EINTR; + } + + if ((status == VCHIQ_SUCCESS) && (ret < 0) && (ret != -EINTR) && + (ret != -EWOULDBLOCK)) + vchiq_log_info(vchiq_arm_log_level, + " ioctl instance %lx, cmd %s -> status %d, %ld", + (unsigned long)instance, + (_IOC_NR(cmd) <= VCHIQ_IOC_MAX) ? + ioctl_names[_IOC_NR(cmd)] : + "<invalid>", + status, ret); + else + vchiq_log_trace(vchiq_arm_log_level, + " ioctl instance %lx, cmd %s -> status %d, %ld", + (unsigned long)instance, + (_IOC_NR(cmd) <= VCHIQ_IOC_MAX) ? + ioctl_names[_IOC_NR(cmd)] : + "<invalid>", + status, ret); + + return ret; +} + +/**************************************************************************** +* +* vchiq_open +* +***************************************************************************/ + +static int +vchiq_open(struct inode *inode, struct file *file) +{ + int dev = iminor(inode) & 0x0f; + vchiq_log_info(vchiq_arm_log_level, "vchiq_open"); + switch (dev) { + case VCHIQ_MINOR: { + int ret; + VCHIQ_STATE_T *state = vchiq_get_state(); + VCHIQ_INSTANCE_T instance; + + if (!state) { + vchiq_log_error(vchiq_arm_log_level, + "vchiq has no connection to VideoCore"); + return -ENOTCONN; + } + + instance = kzalloc(sizeof(*instance), GFP_KERNEL); + if (!instance) + return -ENOMEM; + + instance->state = state; + instance->pid = current->tgid; + + ret = vchiq_debugfs_add_instance(instance); + if (ret != 0) { + kfree(instance); + return ret; + } + + sema_init(&instance->insert_event, 0); + sema_init(&instance->remove_event, 0); + mutex_init(&instance->completion_mutex); + mutex_init(&instance->bulk_waiter_list_mutex); + INIT_LIST_HEAD(&instance->bulk_waiter_list); + + file->private_data = instance; + } break; + + default: + vchiq_log_error(vchiq_arm_log_level, + "Unknown minor device: %d", dev); + return -ENXIO; + } + + return 0; +} + +/**************************************************************************** +* +* vchiq_release +* +***************************************************************************/ + +static int +vchiq_release(struct inode *inode, struct file *file) +{ + int dev = iminor(inode) & 0x0f; + int ret = 0; + switch (dev) { + case VCHIQ_MINOR: { + VCHIQ_INSTANCE_T instance = file->private_data; + VCHIQ_STATE_T *state = vchiq_get_state(); + VCHIQ_SERVICE_T *service; + int i; + + vchiq_log_info(vchiq_arm_log_level, + "vchiq_release: instance=%lx", + (unsigned long)instance); + + if (!state) { + ret = -EPERM; + goto out; + } + + /* Ensure videocore is awake to allow termination. */ + vchiq_use_internal(instance->state, NULL, + USE_TYPE_VCHIQ); + + mutex_lock(&instance->completion_mutex); + + /* Wake the completion thread and ask it to exit */ + instance->closing = 1; + up(&instance->insert_event); + + mutex_unlock(&instance->completion_mutex); + + /* Wake the slot handler if the completion queue is full. */ + up(&instance->remove_event); + + /* Mark all services for termination... */ + i = 0; + while ((service = next_service_by_instance(state, instance, + &i)) != NULL) { + USER_SERVICE_T *user_service = service->base.userdata; + + /* Wake the slot handler if the msg queue is full. */ + up(&user_service->remove_event); + + vchiq_terminate_service_internal(service); + unlock_service(service); + } + + /* ...and wait for them to die */ + i = 0; + while ((service = next_service_by_instance(state, instance, &i)) + != NULL) { + USER_SERVICE_T *user_service = service->base.userdata; + + down(&service->remove_event); + + BUG_ON(service->srvstate != VCHIQ_SRVSTATE_FREE); + + spin_lock(&msg_queue_spinlock); + + while (user_service->msg_remove != + user_service->msg_insert) { + VCHIQ_HEADER_T *header = user_service-> + msg_queue[user_service->msg_remove & + (MSG_QUEUE_SIZE - 1)]; + user_service->msg_remove++; + spin_unlock(&msg_queue_spinlock); + + if (header) + vchiq_release_message( + service->handle, + header); + spin_lock(&msg_queue_spinlock); + } + + spin_unlock(&msg_queue_spinlock); + + unlock_service(service); + } + + /* Release any closed services */ + while (instance->completion_remove != + instance->completion_insert) { + VCHIQ_COMPLETION_DATA_T *completion; + VCHIQ_SERVICE_T *service; + completion = &instance->completions[ + instance->completion_remove & + (MAX_COMPLETIONS - 1)]; + service = completion->service_userdata; + if (completion->reason == VCHIQ_SERVICE_CLOSED) + { + USER_SERVICE_T *user_service = + service->base.userdata; + + /* Wake any blocked user-thread */ + if (instance->use_close_delivered) + up(&user_service->close_event); + unlock_service(service); + } + instance->completion_remove++; + } + + /* Release the PEER service count. */ + vchiq_release_internal(instance->state, NULL); + + { + struct list_head *pos, *next; + list_for_each_safe(pos, next, + &instance->bulk_waiter_list) { + struct bulk_waiter_node *waiter; + waiter = list_entry(pos, + struct bulk_waiter_node, + list); + list_del(pos); + vchiq_log_info(vchiq_arm_log_level, + "bulk_waiter - cleaned up %x " + "for pid %d", + (unsigned int)waiter, waiter->pid); + kfree(waiter); + } + } + + vchiq_debugfs_remove_instance(instance); + + kfree(instance); + file->private_data = NULL; + } break; + + default: + vchiq_log_error(vchiq_arm_log_level, + "Unknown minor device: %d", dev); + ret = -ENXIO; + } + +out: + return ret; +} + +/**************************************************************************** +* +* vchiq_dump +* +***************************************************************************/ + +void +vchiq_dump(void *dump_context, const char *str, int len) +{ + DUMP_CONTEXT_T *context = (DUMP_CONTEXT_T *)dump_context; + + if (context->actual < context->space) { + int copy_bytes; + if (context->offset > 0) { + int skip_bytes = min(len, (int)context->offset); + str += skip_bytes; + len -= skip_bytes; + context->offset -= skip_bytes; + if (context->offset > 0) + return; + } + copy_bytes = min(len, (int)(context->space - context->actual)); + if (copy_bytes == 0) + return; + if (copy_to_user(context->buf + context->actual, str, + copy_bytes)) + context->actual = -EFAULT; + context->actual += copy_bytes; + len -= copy_bytes; + + /* If tne terminating NUL is included in the length, then it + ** marks the end of a line and should be replaced with a + ** carriage return. */ + if ((len == 0) && (str[copy_bytes - 1] == '\0')) { + char cr = '\n'; + if (copy_to_user(context->buf + context->actual - 1, + &cr, 1)) + context->actual = -EFAULT; + } + } +} + +/**************************************************************************** +* +* vchiq_dump_platform_instance_state +* +***************************************************************************/ + +void +vchiq_dump_platform_instances(void *dump_context) +{ + VCHIQ_STATE_T *state = vchiq_get_state(); + char buf[80]; + int len; + int i; + + /* There is no list of instances, so instead scan all services, + marking those that have been dumped. */ + + for (i = 0; i < state->unused_service; i++) { + VCHIQ_SERVICE_T *service = state->services[i]; + VCHIQ_INSTANCE_T instance; + + if (service && (service->base.callback == service_callback)) { + instance = service->instance; + if (instance) + instance->mark = 0; + } + } + + for (i = 0; i < state->unused_service; i++) { + VCHIQ_SERVICE_T *service = state->services[i]; + VCHIQ_INSTANCE_T instance; + + if (service && (service->base.callback == service_callback)) { + instance = service->instance; + if (instance && !instance->mark) { + len = snprintf(buf, sizeof(buf), + "Instance %x: pid %d,%s completions " + "%d/%d", + (unsigned int)instance, instance->pid, + instance->connected ? " connected, " : + "", + instance->completion_insert - + instance->completion_remove, + MAX_COMPLETIONS); + + vchiq_dump(dump_context, buf, len + 1); + + instance->mark = 1; + } + } + } +} + +/**************************************************************************** +* +* vchiq_dump_platform_service_state +* +***************************************************************************/ + +void +vchiq_dump_platform_service_state(void *dump_context, VCHIQ_SERVICE_T *service) +{ + USER_SERVICE_T *user_service = (USER_SERVICE_T *)service->base.userdata; + char buf[80]; + int len; + + len = snprintf(buf, sizeof(buf), " instance %x", + (unsigned int)service->instance); + + if ((service->base.callback == service_callback) && + user_service->is_vchi) { + len += snprintf(buf + len, sizeof(buf) - len, + ", %d/%d messages", + user_service->msg_insert - user_service->msg_remove, + MSG_QUEUE_SIZE); + + if (user_service->dequeue_pending) + len += snprintf(buf + len, sizeof(buf) - len, + " (dequeue pending)"); + } + + vchiq_dump(dump_context, buf, len + 1); +} + +/**************************************************************************** +* +* dump_user_mem +* +***************************************************************************/ + +static void +dump_phys_mem(void *virt_addr, uint32_t num_bytes) +{ + int rc; + uint8_t *end_virt_addr = virt_addr + num_bytes; + int num_pages; + int offset; + int end_offset; + int page_idx; + int prev_idx; + struct page *page; + struct page **pages; + uint8_t *kmapped_virt_ptr; + + /* Align virtAddr and endVirtAddr to 16 byte boundaries. */ + + virt_addr = (void *)((unsigned long)virt_addr & ~0x0fuL); + end_virt_addr = (void *)(((unsigned long)end_virt_addr + 15uL) & + ~0x0fuL); + + offset = (int)(long)virt_addr & (PAGE_SIZE - 1); + end_offset = (int)(long)end_virt_addr & (PAGE_SIZE - 1); + + num_pages = (offset + num_bytes + PAGE_SIZE - 1) / PAGE_SIZE; + + pages = kmalloc(sizeof(struct page *) * num_pages, GFP_KERNEL); + if (pages == NULL) { + vchiq_log_error(vchiq_arm_log_level, + "Unable to allocation memory for %d pages\n", + num_pages); + return; + } + + down_read(¤t->mm->mmap_sem); + rc = get_user_pages(current, /* task */ + current->mm, /* mm */ + (unsigned long)virt_addr, /* start */ + num_pages, /* len */ + 0, /* write */ + 0, /* force */ + pages, /* pages (array of page pointers) */ + NULL); /* vmas */ + up_read(¤t->mm->mmap_sem); + + prev_idx = -1; + page = NULL; + + while (offset < end_offset) { + + int page_offset = offset % PAGE_SIZE; + page_idx = offset / PAGE_SIZE; + + if (page_idx != prev_idx) { + + if (page != NULL) + kunmap(page); + page = pages[page_idx]; + kmapped_virt_ptr = kmap(page); + + prev_idx = page_idx; + } + + if (vchiq_arm_log_level >= VCHIQ_LOG_TRACE) + vchiq_log_dump_mem("ph", + (uint32_t)(unsigned long)&kmapped_virt_ptr[ + page_offset], + &kmapped_virt_ptr[page_offset], 16); + + offset += 16; + } + if (page != NULL) + kunmap(page); + + for (page_idx = 0; page_idx < num_pages; page_idx++) + page_cache_release(pages[page_idx]); + + kfree(pages); +} + +/**************************************************************************** +* +* vchiq_read +* +***************************************************************************/ + +static ssize_t +vchiq_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + DUMP_CONTEXT_T context; + context.buf = buf; + context.actual = 0; + context.space = count; + context.offset = *ppos; + + vchiq_dump_state(&context, &g_state); + + *ppos += context.actual; + + return context.actual; +} + +VCHIQ_STATE_T * +vchiq_get_state(void) +{ + + if (g_state.remote == NULL) + printk(KERN_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); + + return ((g_state.remote != NULL) && + (g_state.remote->initialised == 1)) ? &g_state : NULL; +} + +static const struct file_operations +vchiq_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = vchiq_ioctl, + .open = vchiq_open, + .release = vchiq_release, + .read = vchiq_read +}; + +/* + * Autosuspend related functionality + */ + +int +vchiq_videocore_wanted(VCHIQ_STATE_T *state) +{ + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + if (!arm_state) + /* autosuspend not supported - always return wanted */ + return 1; + else if (arm_state->blocked_count) + return 1; + else if (!arm_state->videocore_use_count) + /* usage count zero - check for override unless we're forcing */ + if (arm_state->resume_blocked) + return 0; + else + return vchiq_platform_videocore_wanted(state); + else + /* non-zero usage count - videocore still required */ + return 1; +} + +static VCHIQ_STATUS_T +vchiq_keepalive_vchiq_callback(VCHIQ_REASON_T reason, + VCHIQ_HEADER_T *header, + VCHIQ_SERVICE_HANDLE_T service_user, + void *bulk_user) +{ + vchiq_log_error(vchiq_susp_log_level, + "%s callback reason %d", __func__, reason); + return 0; +} + +static int +vchiq_keepalive_thread_func(void *v) +{ + VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v; + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + + VCHIQ_STATUS_T status; + VCHIQ_INSTANCE_T instance; + VCHIQ_SERVICE_HANDLE_T ka_handle; + + VCHIQ_SERVICE_PARAMS_T params = { + .fourcc = VCHIQ_MAKE_FOURCC('K', 'E', 'E', 'P'), + .callback = vchiq_keepalive_vchiq_callback, + .version = KEEPALIVE_VER, + .version_min = KEEPALIVE_VER_MIN + }; + + status = vchiq_initialise(&instance); + if (status != VCHIQ_SUCCESS) { + vchiq_log_error(vchiq_susp_log_level, + "%s vchiq_initialise failed %d", __func__, status); + goto exit; + } + + status = vchiq_connect(instance); + if (status != VCHIQ_SUCCESS) { + vchiq_log_error(vchiq_susp_log_level, + "%s vchiq_connect failed %d", __func__, status); + goto shutdown; + } + + status = vchiq_add_service(instance, ¶ms, &ka_handle); + if (status != VCHIQ_SUCCESS) { + vchiq_log_error(vchiq_susp_log_level, + "%s vchiq_open_service failed %d", __func__, status); + goto shutdown; + } + + while (1) { + long rc = 0, uc = 0; + if (wait_for_completion_interruptible(&arm_state->ka_evt) + != 0) { + vchiq_log_error(vchiq_susp_log_level, + "%s interrupted", __func__); + flush_signals(current); + continue; + } + + /* read and clear counters. Do release_count then use_count to + * prevent getting more releases than uses */ + rc = atomic_xchg(&arm_state->ka_release_count, 0); + uc = atomic_xchg(&arm_state->ka_use_count, 0); + + /* Call use/release service the requisite number of times. + * Process use before release so use counts don't go negative */ + while (uc--) { + atomic_inc(&arm_state->ka_use_ack_count); + status = vchiq_use_service(ka_handle); + if (status != VCHIQ_SUCCESS) { + vchiq_log_error(vchiq_susp_log_level, + "%s vchiq_use_service error %d", + __func__, status); + } + } + while (rc--) { + status = vchiq_release_service(ka_handle); + if (status != VCHIQ_SUCCESS) { + vchiq_log_error(vchiq_susp_log_level, + "%s vchiq_release_service error %d", + __func__, status); + } + } + } + +shutdown: + vchiq_shutdown(instance); +exit: + return 0; +} + + + +VCHIQ_STATUS_T +vchiq_arm_init_state(VCHIQ_STATE_T *state, VCHIQ_ARM_STATE_T *arm_state) +{ + VCHIQ_STATUS_T status = VCHIQ_SUCCESS; + + if (arm_state) { + rwlock_init(&arm_state->susp_res_lock); + + init_completion(&arm_state->ka_evt); + atomic_set(&arm_state->ka_use_count, 0); + atomic_set(&arm_state->ka_use_ack_count, 0); + atomic_set(&arm_state->ka_release_count, 0); + + init_completion(&arm_state->vc_suspend_complete); + + init_completion(&arm_state->vc_resume_complete); + /* Initialise to 'done' state. We only want to block on resume + * completion while videocore is suspended. */ + set_resume_state(arm_state, VC_RESUME_RESUMED); + + init_completion(&arm_state->resume_blocker); + /* Initialise to 'done' state. We only want to block on this + * completion while resume is blocked */ + complete_all(&arm_state->resume_blocker); + + init_completion(&arm_state->blocked_blocker); + /* Initialise to 'done' state. We only want to block on this + * completion while things are waiting on the resume blocker */ + complete_all(&arm_state->blocked_blocker); + + arm_state->suspend_timer_timeout = SUSPEND_TIMER_TIMEOUT_MS; + arm_state->suspend_timer_running = 0; + init_timer(&arm_state->suspend_timer); + arm_state->suspend_timer.data = (unsigned long)(state); + arm_state->suspend_timer.function = suspend_timer_callback; + + arm_state->first_connect = 0; + + } + return status; +} + +/* +** Functions to modify the state variables; +** set_suspend_state +** set_resume_state +** +** There are more state variables than we might like, so ensure they remain in +** step. Suspend and resume state are maintained separately, since most of +** these state machines can operate independently. However, there are a few +** states where state transitions in one state machine cause a reset to the +** other state machine. In addition, there are some completion events which +** need to occur on state machine reset and end-state(s), so these are also +** dealt with in these functions. +** +** In all states we set the state variable according to the input, but in some +** cases we perform additional steps outlined below; +** +** VC_SUSPEND_IDLE - Initialise the suspend completion at the same time. +** The suspend completion is completed after any suspend +** attempt. When we reset the state machine we also reset +** the completion. This reset occurs when videocore is +** resumed, and also if we initiate suspend after a suspend +** failure. +** +** VC_SUSPEND_IN_PROGRESS - This state is considered the point of no return for +** suspend - ie from this point on we must try to suspend +** before resuming can occur. We therefore also reset the +** resume state machine to VC_RESUME_IDLE in this state. +** +** VC_SUSPEND_SUSPENDED - Suspend has completed successfully. Also call +** complete_all on the suspend completion to notify +** anything waiting for suspend to happen. +** +** VC_SUSPEND_REJECTED - Videocore rejected suspend. Videocore will also +** initiate resume, so no need to alter resume state. +** We call complete_all on the suspend completion to notify +** of suspend rejection. +** +** VC_SUSPEND_FAILED - We failed to initiate videocore suspend. We notify the +** suspend completion and reset the resume state machine. +** +** VC_RESUME_IDLE - Initialise the resume completion at the same time. The +** resume completion is in it's 'done' state whenever +** videcore is running. Therfore, the VC_RESUME_IDLE state +** implies that videocore is suspended. +** Hence, any thread which needs to wait until videocore is +** running can wait on this completion - it will only block +** if videocore is suspended. +** +** VC_RESUME_RESUMED - Resume has completed successfully. Videocore is running. +** Call complete_all on the resume completion to unblock +** any threads waiting for resume. Also reset the suspend +** state machine to it's idle state. +** +** VC_RESUME_FAILED - Currently unused - no mechanism to fail resume exists. +*/ + +void +set_suspend_state(VCHIQ_ARM_STATE_T *arm_state, + enum vc_suspend_status new_state) +{ + /* set the state in all cases */ + arm_state->vc_suspend_state = new_state; + + /* state specific additional actions */ + switch (new_state) { + case VC_SUSPEND_FORCE_CANCELED: + complete_all(&arm_state->vc_suspend_complete); + break; + case VC_SUSPEND_REJECTED: + complete_all(&arm_state->vc_suspend_complete); + break; + case VC_SUSPEND_FAILED: + complete_all(&arm_state->vc_suspend_complete); + arm_state->vc_resume_state = VC_RESUME_RESUMED; + complete_all(&arm_state->vc_resume_complete); + break; + case VC_SUSPEND_IDLE: + reinit_completion(&arm_state->vc_suspend_complete); + break; + case VC_SUSPEND_REQUESTED: + break; + case VC_SUSPEND_IN_PROGRESS: + set_resume_state(arm_state, VC_RESUME_IDLE); + break; + case VC_SUSPEND_SUSPENDED: + complete_all(&arm_state->vc_suspend_complete); + break; + default: + BUG(); + break; + } +} + +void +set_resume_state(VCHIQ_ARM_STATE_T *arm_state, + enum vc_resume_status new_state) +{ + /* set the state in all cases */ + arm_state->vc_resume_state = new_state; + + /* state specific additional actions */ + switch (new_state) { + case VC_RESUME_FAILED: + break; + case VC_RESUME_IDLE: + reinit_completion(&arm_state->vc_resume_complete); + break; + case VC_RESUME_REQUESTED: + break; + case VC_RESUME_IN_PROGRESS: + break; + case VC_RESUME_RESUMED: + complete_all(&arm_state->vc_resume_complete); + set_suspend_state(arm_state, VC_SUSPEND_IDLE); + break; + default: + BUG(); + break; + } +} + + +/* should be called with the write lock held */ +inline void +start_suspend_timer(VCHIQ_ARM_STATE_T *arm_state) +{ + del_timer(&arm_state->suspend_timer); + arm_state->suspend_timer.expires = jiffies + + msecs_to_jiffies(arm_state-> + suspend_timer_timeout); + add_timer(&arm_state->suspend_timer); + arm_state->suspend_timer_running = 1; +} + +/* should be called with the write lock held */ +static inline void +stop_suspend_timer(VCHIQ_ARM_STATE_T *arm_state) +{ + if (arm_state->suspend_timer_running) { + del_timer(&arm_state->suspend_timer); + arm_state->suspend_timer_running = 0; + } +} + +static inline int +need_resume(VCHIQ_STATE_T *state) +{ + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + return (arm_state->vc_suspend_state > VC_SUSPEND_IDLE) && + (arm_state->vc_resume_state < VC_RESUME_REQUESTED) && + vchiq_videocore_wanted(state); +} + +static int +block_resume(VCHIQ_ARM_STATE_T *arm_state) +{ + int status = VCHIQ_SUCCESS; + const unsigned long timeout_val = + msecs_to_jiffies(FORCE_SUSPEND_TIMEOUT_MS); + int resume_count = 0; + + /* Allow any threads which were blocked by the last force suspend to + * complete if they haven't already. Only give this one shot; if + * blocked_count is incremented after blocked_blocker is completed + * (which only happens when blocked_count hits 0) then those threads + * will have to wait until next time around */ + if (arm_state->blocked_count) { + reinit_completion(&arm_state->blocked_blocker); + write_unlock_bh(&arm_state->susp_res_lock); + vchiq_log_info(vchiq_susp_log_level, "%s wait for previously " + "blocked clients", __func__); + if (wait_for_completion_interruptible_timeout( + &arm_state->blocked_blocker, timeout_val) + <= 0) { + vchiq_log_error(vchiq_susp_log_level, "%s wait for " + "previously blocked clients failed" , __func__); + status = VCHIQ_ERROR; + write_lock_bh(&arm_state->susp_res_lock); + goto out; + } + vchiq_log_info(vchiq_susp_log_level, "%s previously blocked " + "clients resumed", __func__); + write_lock_bh(&arm_state->susp_res_lock); + } + + /* We need to wait for resume to complete if it's in process */ + while (arm_state->vc_resume_state != VC_RESUME_RESUMED && + arm_state->vc_resume_state > VC_RESUME_IDLE) { + if (resume_count > 1) { + status = VCHIQ_ERROR; + vchiq_log_error(vchiq_susp_log_level, "%s waited too " + "many times for resume" , __func__); + goto out; + } + write_unlock_bh(&arm_state->susp_res_lock); + vchiq_log_info(vchiq_susp_log_level, "%s wait for resume", + __func__); + if (wait_for_completion_interruptible_timeout( + &arm_state->vc_resume_complete, timeout_val) + <= 0) { + vchiq_log_error(vchiq_susp_log_level, "%s wait for " + "resume failed (%s)", __func__, + resume_state_names[arm_state->vc_resume_state + + VC_RESUME_NUM_OFFSET]); + status = VCHIQ_ERROR; + write_lock_bh(&arm_state->susp_res_lock); + goto out; + } + vchiq_log_info(vchiq_susp_log_level, "%s resumed", __func__); + write_lock_bh(&arm_state->susp_res_lock); + resume_count++; + } + reinit_completion(&arm_state->resume_blocker); + arm_state->resume_blocked = 1; + +out: + return status; +} + +static inline void +unblock_resume(VCHIQ_ARM_STATE_T *arm_state) +{ + complete_all(&arm_state->resume_blocker); + arm_state->resume_blocked = 0; +} + +/* Initiate suspend via slot handler. Should be called with the write lock + * held */ +VCHIQ_STATUS_T +vchiq_arm_vcsuspend(VCHIQ_STATE_T *state) +{ + VCHIQ_STATUS_T status = VCHIQ_ERROR; + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + + if (!arm_state) + goto out; + + vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); + status = VCHIQ_SUCCESS; + + + switch (arm_state->vc_suspend_state) { + case VC_SUSPEND_REQUESTED: + vchiq_log_info(vchiq_susp_log_level, "%s: suspend already " + "requested", __func__); + break; + case VC_SUSPEND_IN_PROGRESS: + vchiq_log_info(vchiq_susp_log_level, "%s: suspend already in " + "progress", __func__); + break; + + default: + /* We don't expect to be in other states, so log but continue + * anyway */ + vchiq_log_error(vchiq_susp_log_level, + "%s unexpected suspend state %s", __func__, + suspend_state_names[arm_state->vc_suspend_state + + VC_SUSPEND_NUM_OFFSET]); + /* fall through */ + case VC_SUSPEND_REJECTED: + case VC_SUSPEND_FAILED: + /* Ensure any idle state actions have been run */ + set_suspend_state(arm_state, VC_SUSPEND_IDLE); + /* fall through */ + case VC_SUSPEND_IDLE: + vchiq_log_info(vchiq_susp_log_level, + "%s: suspending", __func__); + set_suspend_state(arm_state, VC_SUSPEND_REQUESTED); + /* kick the slot handler thread to initiate suspend */ + request_poll(state, NULL, 0); + break; + } + +out: + vchiq_log_trace(vchiq_susp_log_level, "%s exit %d", __func__, status); + return status; +} + +void +vchiq_platform_check_suspend(VCHIQ_STATE_T *state) +{ + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + int susp = 0; + + if (!arm_state) + goto out; + + vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); + + write_lock_bh(&arm_state->susp_res_lock); + if (arm_state->vc_suspend_state == VC_SUSPEND_REQUESTED && + arm_state->vc_resume_state == VC_RESUME_RESUMED) { + set_suspend_state(arm_state, VC_SUSPEND_IN_PROGRESS); + susp = 1; + } + write_unlock_bh(&arm_state->susp_res_lock); + + if (susp) + vchiq_platform_suspend(state); + +out: + vchiq_log_trace(vchiq_susp_log_level, "%s exit", __func__); + return; +} + + +static void +output_timeout_error(VCHIQ_STATE_T *state) +{ + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + char service_err[50] = ""; + int vc_use_count = arm_state->videocore_use_count; + int active_services = state->unused_service; + int i; + + if (!arm_state->videocore_use_count) { + snprintf(service_err, 50, " Videocore usecount is 0"); + goto output_msg; + } + for (i = 0; i < active_services; i++) { + VCHIQ_SERVICE_T *service_ptr = state->services[i]; + if (service_ptr && service_ptr->service_use_count && + (service_ptr->srvstate != VCHIQ_SRVSTATE_FREE)) { + snprintf(service_err, 50, " %c%c%c%c(%d) service has " + "use count %d%s", VCHIQ_FOURCC_AS_4CHARS( + service_ptr->base.fourcc), + service_ptr->client_id, + service_ptr->service_use_count, + service_ptr->service_use_count == + vc_use_count ? "" : " (+ more)"); + break; + } + } + +output_msg: + vchiq_log_error(vchiq_susp_log_level, + "timed out waiting for vc suspend (%d).%s", + arm_state->autosuspend_override, service_err); + +} + +/* Try to get videocore into suspended state, regardless of autosuspend state. +** We don't actually force suspend, since videocore may get into a bad state +** if we force suspend at a bad time. Instead, we wait for autosuspend to +** determine a good point to suspend. If this doesn't happen within 100ms we +** report failure. +** +** Returns VCHIQ_SUCCESS if videocore suspended successfully, VCHIQ_RETRY if +** videocore failed to suspend in time or VCHIQ_ERROR if interrupted. +*/ +VCHIQ_STATUS_T +vchiq_arm_force_suspend(VCHIQ_STATE_T *state) +{ + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + VCHIQ_STATUS_T status = VCHIQ_ERROR; + long rc = 0; + int repeat = -1; + + if (!arm_state) + goto out; + + vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); + + write_lock_bh(&arm_state->susp_res_lock); + + status = block_resume(arm_state); + if (status != VCHIQ_SUCCESS) + goto unlock; + if (arm_state->vc_suspend_state == VC_SUSPEND_SUSPENDED) { + /* Already suspended - just block resume and exit */ + vchiq_log_info(vchiq_susp_log_level, "%s already suspended", + __func__); + status = VCHIQ_SUCCESS; + goto unlock; + } else if (arm_state->vc_suspend_state <= VC_SUSPEND_IDLE) { + /* initiate suspend immediately in the case that we're waiting + * for the timeout */ + stop_suspend_timer(arm_state); + if (!vchiq_videocore_wanted(state)) { + vchiq_log_info(vchiq_susp_log_level, "%s videocore " + "idle, initiating suspend", __func__); + status = vchiq_arm_vcsuspend(state); + } else if (arm_state->autosuspend_override < + FORCE_SUSPEND_FAIL_MAX) { + vchiq_log_info(vchiq_susp_log_level, "%s letting " + "videocore go idle", __func__); + status = VCHIQ_SUCCESS; + } else { + vchiq_log_warning(vchiq_susp_log_level, "%s failed too " + "many times - attempting suspend", __func__); + status = vchiq_arm_vcsuspend(state); + } + } else { + vchiq_log_info(vchiq_susp_log_level, "%s videocore suspend " + "in progress - wait for completion", __func__); + status = VCHIQ_SUCCESS; + } + + /* Wait for suspend to happen due to system idle (not forced..) */ + if (status != VCHIQ_SUCCESS) + goto unblock_resume; + + do { + write_unlock_bh(&arm_state->susp_res_lock); + + rc = wait_for_completion_interruptible_timeout( + &arm_state->vc_suspend_complete, + msecs_to_jiffies(FORCE_SUSPEND_TIMEOUT_MS)); + + write_lock_bh(&arm_state->susp_res_lock); + if (rc < 0) { + vchiq_log_warning(vchiq_susp_log_level, "%s " + "interrupted waiting for suspend", __func__); + status = VCHIQ_ERROR; + goto unblock_resume; + } else if (rc == 0) { + if (arm_state->vc_suspend_state > VC_SUSPEND_IDLE) { + /* Repeat timeout once if in progress */ + if (repeat < 0) { + repeat = 1; + continue; + } + } + arm_state->autosuspend_override++; + output_timeout_error(state); + + status = VCHIQ_RETRY; + goto unblock_resume; + } + } while (0 < (repeat--)); + + /* Check and report state in case we need to abort ARM suspend */ + if (arm_state->vc_suspend_state != VC_SUSPEND_SUSPENDED) { + status = VCHIQ_RETRY; + vchiq_log_error(vchiq_susp_log_level, + "%s videocore suspend failed (state %s)", __func__, + suspend_state_names[arm_state->vc_suspend_state + + VC_SUSPEND_NUM_OFFSET]); + /* Reset the state only if it's still in an error state. + * Something could have already initiated another suspend. */ + if (arm_state->vc_suspend_state < VC_SUSPEND_IDLE) + set_suspend_state(arm_state, VC_SUSPEND_IDLE); + + goto unblock_resume; + } + + /* successfully suspended - unlock and exit */ + goto unlock; + +unblock_resume: + /* all error states need to unblock resume before exit */ + unblock_resume(arm_state); + +unlock: + write_unlock_bh(&arm_state->susp_res_lock); + +out: + vchiq_log_trace(vchiq_susp_log_level, "%s exit %d", __func__, status); + return status; +} + +void +vchiq_check_suspend(VCHIQ_STATE_T *state) +{ + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + + if (!arm_state) + goto out; + + vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); + + write_lock_bh(&arm_state->susp_res_lock); + if (arm_state->vc_suspend_state != VC_SUSPEND_SUSPENDED && + arm_state->first_connect && + !vchiq_videocore_wanted(state)) { + vchiq_arm_vcsuspend(state); + } + write_unlock_bh(&arm_state->susp_res_lock); + +out: + vchiq_log_trace(vchiq_susp_log_level, "%s exit", __func__); + return; +} + + +int +vchiq_arm_allow_resume(VCHIQ_STATE_T *state) +{ + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + int resume = 0; + int ret = -1; + + if (!arm_state) + goto out; + + vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); + + write_lock_bh(&arm_state->susp_res_lock); + unblock_resume(arm_state); + resume = vchiq_check_resume(state); + write_unlock_bh(&arm_state->susp_res_lock); + + if (resume) { + if (wait_for_completion_interruptible( + &arm_state->vc_resume_complete) < 0) { + vchiq_log_error(vchiq_susp_log_level, + "%s interrupted", __func__); + /* failed, cannot accurately derive suspend + * state, so exit early. */ + goto out; + } + } + + read_lock_bh(&arm_state->susp_res_lock); + if (arm_state->vc_suspend_state == VC_SUSPEND_SUSPENDED) { + vchiq_log_info(vchiq_susp_log_level, + "%s: Videocore remains suspended", __func__); + } else { + vchiq_log_info(vchiq_susp_log_level, + "%s: Videocore resumed", __func__); + ret = 0; + } + read_unlock_bh(&arm_state->susp_res_lock); +out: + vchiq_log_trace(vchiq_susp_log_level, "%s exit %d", __func__, ret); + return ret; +} + +/* This function should be called with the write lock held */ +int +vchiq_check_resume(VCHIQ_STATE_T *state) +{ + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + int resume = 0; + + if (!arm_state) + goto out; + + vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); + + if (need_resume(state)) { + set_resume_state(arm_state, VC_RESUME_REQUESTED); + request_poll(state, NULL, 0); + resume = 1; + } + +out: + vchiq_log_trace(vchiq_susp_log_level, "%s exit", __func__); + return resume; +} + +void +vchiq_platform_check_resume(VCHIQ_STATE_T *state) +{ + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + int res = 0; + + if (!arm_state) + goto out; + + vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); + + write_lock_bh(&arm_state->susp_res_lock); + if (arm_state->wake_address == 0) { + vchiq_log_info(vchiq_susp_log_level, + "%s: already awake", __func__); + goto unlock; + } + if (arm_state->vc_resume_state == VC_RESUME_IN_PROGRESS) { + vchiq_log_info(vchiq_susp_log_level, + "%s: already resuming", __func__); + goto unlock; + } + + if (arm_state->vc_resume_state == VC_RESUME_REQUESTED) { + set_resume_state(arm_state, VC_RESUME_IN_PROGRESS); + res = 1; + } else + vchiq_log_trace(vchiq_susp_log_level, + "%s: not resuming (resume state %s)", __func__, + resume_state_names[arm_state->vc_resume_state + + VC_RESUME_NUM_OFFSET]); + +unlock: + write_unlock_bh(&arm_state->susp_res_lock); + + if (res) + vchiq_platform_resume(state); + +out: + vchiq_log_trace(vchiq_susp_log_level, "%s exit", __func__); + return; + +} + + + +VCHIQ_STATUS_T +vchiq_use_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, + enum USE_TYPE_E use_type) +{ + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + VCHIQ_STATUS_T ret = VCHIQ_SUCCESS; + char entity[16]; + int *entity_uc; + int local_uc, local_entity_uc; + + if (!arm_state) + 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; + } else if (service) { + sprintf(entity, "%c%c%c%c:%03d", + VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc), + service->client_id); + entity_uc = &service->service_use_count; + } else { + vchiq_log_error(vchiq_susp_log_level, "%s null service " + "ptr", __func__); + ret = VCHIQ_ERROR; + goto out; + } + + write_lock_bh(&arm_state->susp_res_lock); + while (arm_state->resume_blocked) { + /* If we call 'use' while force suspend is waiting for suspend, + * then we're about to block the thread which the force is + * waiting to complete, so we're bound to just time out. In this + * case, set the suspend state such that the wait will be + * canceled, so we can complete as quickly as possible. */ + if (arm_state->resume_blocked && arm_state->vc_suspend_state == + VC_SUSPEND_IDLE) { + set_suspend_state(arm_state, VC_SUSPEND_FORCE_CANCELED); + break; + } + /* If suspend is already in progress then we need to block */ + if (!try_wait_for_completion(&arm_state->resume_blocker)) { + /* Indicate that there are threads waiting on the resume + * blocker. These need to be allowed to complete before + * a _second_ call to force suspend can complete, + * otherwise low priority threads might never actually + * continue */ + arm_state->blocked_count++; + write_unlock_bh(&arm_state->susp_res_lock); + vchiq_log_info(vchiq_susp_log_level, "%s %s resume " + "blocked - waiting...", __func__, entity); + if (wait_for_completion_killable( + &arm_state->resume_blocker) != 0) { + vchiq_log_error(vchiq_susp_log_level, "%s %s " + "wait for resume blocker interrupted", + __func__, entity); + ret = VCHIQ_ERROR; + write_lock_bh(&arm_state->susp_res_lock); + arm_state->blocked_count--; + write_unlock_bh(&arm_state->susp_res_lock); + goto out; + } + vchiq_log_info(vchiq_susp_log_level, "%s %s resume " + "unblocked", __func__, entity); + write_lock_bh(&arm_state->susp_res_lock); + if (--arm_state->blocked_count == 0) + complete_all(&arm_state->blocked_blocker); + } + } + + stop_suspend_timer(arm_state); + + local_uc = ++arm_state->videocore_use_count; + local_entity_uc = ++(*entity_uc); + + /* If there's a pending request which hasn't yet been serviced then + * just clear it. If we're past VC_SUSPEND_REQUESTED state then + * vc_resume_complete will block until we either resume or fail to + * suspend */ + if (arm_state->vc_suspend_state <= VC_SUSPEND_REQUESTED) + set_suspend_state(arm_state, VC_SUSPEND_IDLE); + + if ((use_type != USE_TYPE_SERVICE_NO_RESUME) && need_resume(state)) { + set_resume_state(arm_state, VC_RESUME_REQUESTED); + vchiq_log_info(vchiq_susp_log_level, + "%s %s count %d, state count %d", + __func__, entity, local_entity_uc, local_uc); + request_poll(state, NULL, 0); + } else + vchiq_log_trace(vchiq_susp_log_level, + "%s %s count %d, state count %d", + __func__, entity, *entity_uc, local_uc); + + + write_unlock_bh(&arm_state->susp_res_lock); + + /* Completion is in a done state when we're not suspended, so this won't + * block for the non-suspended case. */ + if (!try_wait_for_completion(&arm_state->vc_resume_complete)) { + vchiq_log_info(vchiq_susp_log_level, "%s %s wait for resume", + __func__, entity); + if (wait_for_completion_killable( + &arm_state->vc_resume_complete) != 0) { + vchiq_log_error(vchiq_susp_log_level, "%s %s wait for " + "resume interrupted", __func__, entity); + ret = VCHIQ_ERROR; + goto out; + } + vchiq_log_info(vchiq_susp_log_level, "%s %s resumed", __func__, + entity); + } + + if (ret == VCHIQ_SUCCESS) { + VCHIQ_STATUS_T status = VCHIQ_SUCCESS; + long ack_cnt = atomic_xchg(&arm_state->ka_use_ack_count, 0); + while (ack_cnt && (status == VCHIQ_SUCCESS)) { + /* Send the use notify to videocore */ + status = vchiq_send_remote_use_active(state); + if (status == VCHIQ_SUCCESS) + ack_cnt--; + else + atomic_add(ack_cnt, + &arm_state->ka_use_ack_count); + } + } + +out: + vchiq_log_trace(vchiq_susp_log_level, "%s exit %d", __func__, ret); + return ret; +} + +VCHIQ_STATUS_T +vchiq_release_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service) +{ + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + VCHIQ_STATUS_T ret = VCHIQ_SUCCESS; + char entity[16]; + int *entity_uc; + int local_uc, local_entity_uc; + + if (!arm_state) + 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), + service->client_id); + entity_uc = &service->service_use_count; + } else { + sprintf(entity, "PEER: "); + entity_uc = &arm_state->peer_use_count; + } + + write_lock_bh(&arm_state->susp_res_lock); + if (!arm_state->videocore_use_count || !(*entity_uc)) { + /* 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; + goto unlock; + } + local_uc = --arm_state->videocore_use_count; + local_entity_uc = --(*entity_uc); + + if (!vchiq_videocore_wanted(state)) { + if (vchiq_platform_use_suspend_timer() && + !arm_state->resume_blocked) { + /* Only use the timer if we're not trying to force + * suspend (=> resume_blocked) */ + start_suspend_timer(arm_state); + } else { + vchiq_log_info(vchiq_susp_log_level, + "%s %s count %d, state count %d - suspending", + __func__, entity, *entity_uc, + arm_state->videocore_use_count); + vchiq_arm_vcsuspend(state); + } + } else + vchiq_log_trace(vchiq_susp_log_level, + "%s %s count %d, state count %d", + __func__, entity, *entity_uc, + arm_state->videocore_use_count); + +unlock: + write_unlock_bh(&arm_state->susp_res_lock); + +out: + vchiq_log_trace(vchiq_susp_log_level, "%s exit %d", __func__, ret); + return ret; +} + +void +vchiq_on_remote_use(VCHIQ_STATE_T *state) +{ + VCHIQ_ARM_STATE_T *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); +} + +void +vchiq_on_remote_release(VCHIQ_STATE_T *state) +{ + VCHIQ_ARM_STATE_T *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); +} + +VCHIQ_STATUS_T +vchiq_use_service_internal(VCHIQ_SERVICE_T *service) +{ + return vchiq_use_internal(service->state, service, USE_TYPE_SERVICE); +} + +VCHIQ_STATUS_T +vchiq_release_service_internal(VCHIQ_SERVICE_T *service) +{ + return vchiq_release_internal(service->state, service); +} + +VCHIQ_DEBUGFS_NODE_T * +vchiq_instance_get_debugfs_node(VCHIQ_INSTANCE_T instance) +{ + return &instance->debugfs_node; +} + +int +vchiq_instance_get_use_count(VCHIQ_INSTANCE_T instance) +{ + VCHIQ_SERVICE_T *service; + int use_count = 0, i; + i = 0; + while ((service = next_service_by_instance(instance->state, + instance, &i)) != NULL) { + use_count += service->service_use_count; + unlock_service(service); + } + return use_count; +} + +int +vchiq_instance_get_pid(VCHIQ_INSTANCE_T instance) +{ + return instance->pid; +} + +int +vchiq_instance_get_trace(VCHIQ_INSTANCE_T instance) +{ + return instance->trace; +} + +void +vchiq_instance_set_trace(VCHIQ_INSTANCE_T instance, int trace) +{ + VCHIQ_SERVICE_T *service; + int i; + i = 0; + while ((service = next_service_by_instance(instance->state, + instance, &i)) != NULL) { + service->trace = trace; + unlock_service(service); + } + instance->trace = (trace != 0); +} + +static void suspend_timer_callback(unsigned long context) +{ + VCHIQ_STATE_T *state = (VCHIQ_STATE_T *)context; + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + if (!arm_state) + goto out; + vchiq_log_info(vchiq_susp_log_level, + "%s - suspend timer expired - check suspend", __func__); + vchiq_check_suspend(state); +out: + return; +} + +VCHIQ_STATUS_T +vchiq_use_service_no_resume(VCHIQ_SERVICE_HANDLE_T handle) +{ + VCHIQ_STATUS_T ret = VCHIQ_ERROR; + VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + if (service) { + ret = vchiq_use_internal(service->state, service, + USE_TYPE_SERVICE_NO_RESUME); + unlock_service(service); + } + return ret; +} + +VCHIQ_STATUS_T +vchiq_use_service(VCHIQ_SERVICE_HANDLE_T handle) +{ + VCHIQ_STATUS_T ret = VCHIQ_ERROR; + VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + if (service) { + ret = vchiq_use_internal(service->state, service, + USE_TYPE_SERVICE); + unlock_service(service); + } + return ret; +} + +VCHIQ_STATUS_T +vchiq_release_service(VCHIQ_SERVICE_HANDLE_T handle) +{ + VCHIQ_STATUS_T ret = VCHIQ_ERROR; + VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + if (service) { + ret = vchiq_release_internal(service->state, service); + unlock_service(service); + } + return ret; +} + +void +vchiq_dump_service_use_state(VCHIQ_STATE_T *state) +{ + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + int i, j = 0; + /* Only dump 64 services */ + static const int local_max_services = 64; + /* If there's more than 64 services, only dump ones with + * non-zero counts */ + int only_nonzero = 0; + static const char *nz = "<-- preventing suspend"; + + enum vc_suspend_status vc_suspend_state; + enum vc_resume_status vc_resume_state; + int peer_count; + int vc_use_count; + int active_services; + struct service_data_struct { + int fourcc; + int clientid; + int use_count; + } service_data[local_max_services]; + + if (!arm_state) + return; + + read_lock_bh(&arm_state->susp_res_lock); + vc_suspend_state = arm_state->vc_suspend_state; + vc_resume_state = arm_state->vc_resume_state; + peer_count = arm_state->peer_use_count; + vc_use_count = arm_state->videocore_use_count; + active_services = state->unused_service; + if (active_services > local_max_services) + only_nonzero = 1; + + for (i = 0; (i < active_services) && (j < local_max_services); i++) { + VCHIQ_SERVICE_T *service_ptr = state->services[i]; + if (!service_ptr) + continue; + + if (only_nonzero && !service_ptr->service_use_count) + continue; + + if (service_ptr->srvstate != VCHIQ_SRVSTATE_FREE) { + service_data[j].fourcc = service_ptr->base.fourcc; + service_data[j].clientid = service_ptr->client_id; + service_data[j++].use_count = service_ptr-> + service_use_count; + } + } + + read_unlock_bh(&arm_state->susp_res_lock); + + vchiq_log_warning(vchiq_susp_log_level, + "-- Videcore suspend state: %s --", + suspend_state_names[vc_suspend_state + VC_SUSPEND_NUM_OFFSET]); + vchiq_log_warning(vchiq_susp_log_level, + "-- Videcore resume state: %s --", + resume_state_names[vc_resume_state + VC_RESUME_NUM_OFFSET]); + + if (only_nonzero) + vchiq_log_warning(vchiq_susp_log_level, "Too many active " + "services (%d). Only dumping up to first %d services " + "with non-zero use-count", active_services, + local_max_services); + + for (i = 0; i < j; i++) { + vchiq_log_warning(vchiq_susp_log_level, + "----- %c%c%c%c:%d service count %d %s", + VCHIQ_FOURCC_AS_4CHARS(service_data[i].fourcc), + service_data[i].clientid, + service_data[i].use_count, + service_data[i].use_count ? nz : ""); + } + vchiq_log_warning(vchiq_susp_log_level, + "----- VCHIQ use count count %d", peer_count); + vchiq_log_warning(vchiq_susp_log_level, + "--- Overall vchiq instance use count %d", vc_use_count); + + vchiq_dump_platform_use_state(state); +} + +VCHIQ_STATUS_T +vchiq_check_service(VCHIQ_SERVICE_T *service) +{ + VCHIQ_ARM_STATE_T *arm_state; + VCHIQ_STATUS_T ret = VCHIQ_ERROR; + + 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); + if (service->service_use_count) + ret = VCHIQ_SUCCESS; + read_unlock_bh(&arm_state->susp_res_lock); + + if (ret == VCHIQ_ERROR) { + vchiq_log_error(vchiq_susp_log_level, + "%s ERROR - %c%c%c%c:%d service count %d, " + "state count %d, videocore suspend state %s", __func__, + VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc), + service->client_id, service->service_use_count, + arm_state->videocore_use_count, + suspend_state_names[arm_state->vc_suspend_state + + VC_SUSPEND_NUM_OFFSET]); + vchiq_dump_service_use_state(service->state); + } +out: + return ret; +} + +/* stub functions */ +void vchiq_on_remote_use_active(VCHIQ_STATE_T *state) +{ + (void)state; +} + +void vchiq_platform_conn_state_changed(VCHIQ_STATE_T *state, + VCHIQ_CONNSTATE_T oldstate, VCHIQ_CONNSTATE_T newstate) +{ + VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + vchiq_log_info(vchiq_susp_log_level, "%d: %s->%s", state->id, + get_conn_state_name(oldstate), get_conn_state_name(newstate)); + if (state->conn_state == VCHIQ_CONNSTATE_CONNECTED) { + write_lock_bh(&arm_state->susp_res_lock); + if (!arm_state->first_connect) { + char threadname[10]; + arm_state->first_connect = 1; + write_unlock_bh(&arm_state->susp_res_lock); + snprintf(threadname, sizeof(threadname), "VCHIQka-%d", + state->id); + arm_state->ka_thread = kthread_create( + &vchiq_keepalive_thread_func, + (void *)state, + threadname); + if (arm_state->ka_thread == NULL) { + vchiq_log_error(vchiq_susp_log_level, + "vchiq: FATAL: couldn't create thread %s", + threadname); + } else { + wake_up_process(arm_state->ka_thread); + } + } else + write_unlock_bh(&arm_state->susp_res_lock); + } +} + +static int vchiq_probe(struct platform_device *pdev) +{ + struct device_node *fw_node; + struct rpi_firmware *fw; + int err; + void *ptr_err; + + fw_node = of_parse_phandle(pdev->dev.of_node, "firmware", 0); +/* Remove comment when booting without Device Tree is no longer supported + if (!fw_node) { + dev_err(&pdev->dev, "Missing firmware node\n"); + return -ENOENT; + } +*/ + fw = rpi_firmware_get(fw_node); + if (!fw) + return -EPROBE_DEFER; + + platform_set_drvdata(pdev, fw); + + /* create debugfs entries */ + err = vchiq_debugfs_init(); + if (err != 0) + goto failed_debugfs_init; + + err = alloc_chrdev_region(&vchiq_devid, VCHIQ_MINOR, 1, DEVICE_NAME); + if (err != 0) { + vchiq_log_error(vchiq_arm_log_level, + "Unable to allocate device number"); + goto failed_alloc_chrdev; + } + cdev_init(&vchiq_cdev, &vchiq_fops); + vchiq_cdev.owner = THIS_MODULE; + err = cdev_add(&vchiq_cdev, vchiq_devid, 1); + if (err != 0) { + vchiq_log_error(vchiq_arm_log_level, + "Unable to register device"); + goto failed_cdev_add; + } + + /* create sysfs entries */ + vchiq_class = class_create(THIS_MODULE, DEVICE_NAME); + ptr_err = vchiq_class; + if (IS_ERR(ptr_err)) + goto failed_class_create; + + vchiq_dev = device_create(vchiq_class, NULL, + vchiq_devid, NULL, "vchiq"); + ptr_err = vchiq_dev; + if (IS_ERR(ptr_err)) + goto failed_device_create; + + err = vchiq_platform_init(pdev, &g_state); + if (err != 0) + goto failed_platform_init; + + vchiq_log_info(vchiq_arm_log_level, + "vchiq: initialised - version %d (min %d), device %d.%d", + VCHIQ_VERSION, VCHIQ_VERSION_MIN, + MAJOR(vchiq_devid), MINOR(vchiq_devid)); + + return 0; + +failed_platform_init: + device_destroy(vchiq_class, vchiq_devid); +failed_device_create: + class_destroy(vchiq_class); +failed_class_create: + cdev_del(&vchiq_cdev); + err = PTR_ERR(ptr_err); +failed_cdev_add: + unregister_chrdev_region(vchiq_devid, 1); +failed_alloc_chrdev: + vchiq_debugfs_deinit(); +failed_debugfs_init: + vchiq_log_warning(vchiq_arm_log_level, "could not load vchiq"); + return err; +} + +static int vchiq_remove(struct platform_device *pdev) +{ + device_destroy(vchiq_class, vchiq_devid); + class_destroy(vchiq_class); + cdev_del(&vchiq_cdev); + unregister_chrdev_region(vchiq_devid, 1); + + return 0; +} + +static const struct of_device_id vchiq_of_match[] = { + { .compatible = "brcm,bcm2835-vchiq", }, + {}, +}; +MODULE_DEVICE_TABLE(of, vchiq_of_match); + +static struct platform_driver vchiq_driver = { + .driver = { + .name = "bcm2835_vchiq", + .owner = THIS_MODULE, + .of_match_table = vchiq_of_match, + }, + .probe = vchiq_probe, + .remove = vchiq_remove, +}; +module_platform_driver(vchiq_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Broadcom Corporation"); diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h new file mode 100644 index 0000000..9740e1a --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h @@ -0,0 +1,220 @@ +/** + * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved. + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHIQ_ARM_H +#define VCHIQ_ARM_H + +#include <linux/mutex.h> +#include <linux/platform_device.h> +#include <linux/semaphore.h> +#include <linux/atomic.h> +#include "vchiq_core.h" +#include "vchiq_debugfs.h" + + +enum vc_suspend_status { + VC_SUSPEND_FORCE_CANCELED = -3, /* Force suspend canceled, too busy */ + VC_SUSPEND_REJECTED = -2, /* Videocore rejected suspend request */ + VC_SUSPEND_FAILED = -1, /* Videocore suspend failed */ + VC_SUSPEND_IDLE = 0, /* VC active, no suspend actions */ + VC_SUSPEND_REQUESTED, /* User has requested suspend */ + VC_SUSPEND_IN_PROGRESS, /* Slot handler has recvd suspend request */ + VC_SUSPEND_SUSPENDED /* Videocore suspend succeeded */ +}; + +enum vc_resume_status { + VC_RESUME_FAILED = -1, /* Videocore resume failed */ + VC_RESUME_IDLE = 0, /* VC suspended, no resume actions */ + VC_RESUME_REQUESTED, /* User has requested resume */ + VC_RESUME_IN_PROGRESS, /* Slot handler has received resume request */ + VC_RESUME_RESUMED /* Videocore resumed successfully (active) */ +}; + + +enum USE_TYPE_E { + USE_TYPE_SERVICE, + USE_TYPE_SERVICE_NO_RESUME, + USE_TYPE_VCHIQ +}; + + + +typedef struct vchiq_arm_state_struct { + /* Keepalive-related data */ + struct task_struct *ka_thread; + struct completion ka_evt; + atomic_t ka_use_count; + atomic_t ka_use_ack_count; + atomic_t ka_release_count; + + struct completion vc_suspend_complete; + struct completion vc_resume_complete; + + rwlock_t susp_res_lock; + enum vc_suspend_status vc_suspend_state; + enum vc_resume_status vc_resume_state; + + unsigned int wake_address; + + struct timer_list suspend_timer; + int suspend_timer_timeout; + int suspend_timer_running; + + /* Global use count for videocore. + ** This is equal to the sum of the use counts for all services. When + ** this hits zero the videocore suspend procedure will be initiated. + */ + int videocore_use_count; + + /* Use count to track requests from videocore peer. + ** This use count is not associated with a service, so needs to be + ** tracked separately with the state. + */ + int peer_use_count; + + /* Flag to indicate whether resume is blocked. This happens when the + ** ARM is suspending + */ + struct completion resume_blocker; + int resume_blocked; + struct completion blocked_blocker; + int blocked_count; + + int autosuspend_override; + + /* Flag to indicate that the first vchiq connect has made it through. + ** This means that both sides should be fully ready, and we should + ** be able to suspend after this point. + */ + int first_connect; + + unsigned long long suspend_start_time; + unsigned long long sleep_start_time; + unsigned long long resume_start_time; + unsigned long long last_wake_time; + +} VCHIQ_ARM_STATE_T; + +extern int vchiq_arm_log_level; +extern int vchiq_susp_log_level; + +int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state); + +extern VCHIQ_STATE_T * +vchiq_get_state(void); + +extern VCHIQ_STATUS_T +vchiq_arm_vcsuspend(VCHIQ_STATE_T *state); + +extern VCHIQ_STATUS_T +vchiq_arm_force_suspend(VCHIQ_STATE_T *state); + +extern int +vchiq_arm_allow_resume(VCHIQ_STATE_T *state); + +extern VCHIQ_STATUS_T +vchiq_arm_vcresume(VCHIQ_STATE_T *state); + +extern VCHIQ_STATUS_T +vchiq_arm_init_state(VCHIQ_STATE_T *state, VCHIQ_ARM_STATE_T *arm_state); + +extern int +vchiq_check_resume(VCHIQ_STATE_T *state); + +extern void +vchiq_check_suspend(VCHIQ_STATE_T *state); + VCHIQ_STATUS_T +vchiq_use_service(VCHIQ_SERVICE_HANDLE_T handle); + +extern VCHIQ_STATUS_T +vchiq_release_service(VCHIQ_SERVICE_HANDLE_T handle); + +extern VCHIQ_STATUS_T +vchiq_check_service(VCHIQ_SERVICE_T *service); + +extern VCHIQ_STATUS_T +vchiq_platform_suspend(VCHIQ_STATE_T *state); + +extern int +vchiq_platform_videocore_wanted(VCHIQ_STATE_T *state); + +extern int +vchiq_platform_use_suspend_timer(void); + +extern void +vchiq_dump_platform_use_state(VCHIQ_STATE_T *state); + +extern void +vchiq_dump_service_use_state(VCHIQ_STATE_T *state); + +extern VCHIQ_ARM_STATE_T* +vchiq_platform_get_arm_state(VCHIQ_STATE_T *state); + +extern int +vchiq_videocore_wanted(VCHIQ_STATE_T *state); + +extern VCHIQ_STATUS_T +vchiq_use_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, + enum USE_TYPE_E use_type); +extern VCHIQ_STATUS_T +vchiq_release_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service); + +extern VCHIQ_DEBUGFS_NODE_T * +vchiq_instance_get_debugfs_node(VCHIQ_INSTANCE_T instance); + +extern int +vchiq_instance_get_use_count(VCHIQ_INSTANCE_T instance); + +extern int +vchiq_instance_get_pid(VCHIQ_INSTANCE_T instance); + +extern int +vchiq_instance_get_trace(VCHIQ_INSTANCE_T instance); + +extern void +vchiq_instance_set_trace(VCHIQ_INSTANCE_T instance, int trace); + +extern void +set_suspend_state(VCHIQ_ARM_STATE_T *arm_state, + enum vc_suspend_status new_state); + +extern void +set_resume_state(VCHIQ_ARM_STATE_T *arm_state, + enum vc_resume_status new_state); + +extern void +start_suspend_timer(VCHIQ_ARM_STATE_T *arm_state); + + +#endif /* VCHIQ_ARM_H */ diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_build_info.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_build_info.h new file mode 100644 index 0000000..df64581 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_build_info.h @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + * + * 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. + */ + +const char *vchiq_get_build_hostname(void); +const char *vchiq_get_build_version(void); +const char *vchiq_get_build_time(void); +const char *vchiq_get_build_date(void); diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_cfg.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_cfg.h new file mode 100644 index 0000000..d2797db --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_cfg.h @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2010-2014 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHIQ_CFG_H +#define VCHIQ_CFG_H + +#define VCHIQ_MAGIC VCHIQ_MAKE_FOURCC('V', 'C', 'H', 'I') +/* The version of VCHIQ - change with any non-trivial change */ +#define VCHIQ_VERSION 8 +/* The minimum compatible version - update to match VCHIQ_VERSION with any +** incompatible change */ +#define VCHIQ_VERSION_MIN 3 + +/* The version that introduced the VCHIQ_IOC_LIB_VERSION ioctl */ +#define VCHIQ_VERSION_LIB_VERSION 7 + +/* The version that introduced the VCHIQ_IOC_CLOSE_DELIVERED ioctl */ +#define VCHIQ_VERSION_CLOSE_DELIVERED 7 + +/* The version that made it safe to use SYNCHRONOUS mode */ +#define VCHIQ_VERSION_SYNCHRONOUS_MODE 8 + +#define VCHIQ_MAX_STATES 1 +#define VCHIQ_MAX_SERVICES 4096 +#define VCHIQ_MAX_SLOTS 128 +#define VCHIQ_MAX_SLOTS_PER_SIDE 64 + +#define VCHIQ_NUM_CURRENT_BULKS 32 +#define VCHIQ_NUM_SERVICE_BULKS 4 + +#ifndef VCHIQ_ENABLE_DEBUG +#define VCHIQ_ENABLE_DEBUG 1 +#endif + +#ifndef VCHIQ_ENABLE_STATS +#define VCHIQ_ENABLE_STATS 1 +#endif + +#endif /* VCHIQ_CFG_H */ diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_connected.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_connected.c new file mode 100644 index 0000000..5efc62f --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_connected.c @@ -0,0 +1,120 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "vchiq_connected.h" +#include "vchiq_core.h" +#include "vchiq_killable.h" +#include <linux/module.h> +#include <linux/mutex.h> + +#define MAX_CALLBACKS 10 + +static int g_connected; +static int g_num_deferred_callbacks; +static VCHIQ_CONNECTED_CALLBACK_T g_deferred_callback[MAX_CALLBACKS]; +static int g_once_init; +static struct mutex g_connected_mutex; + +/**************************************************************************** +* +* Function to initialize our lock. +* +***************************************************************************/ + +static void connected_init(void) +{ + if (!g_once_init) { + mutex_init(&g_connected_mutex); + g_once_init = 1; + } +} + +/**************************************************************************** +* +* This function is used to defer initialization until the vchiq stack is +* initialized. If the stack is already initialized, then the callback will +* be made immediately, otherwise it will be deferred until +* vchiq_call_connected_callbacks is called. +* +***************************************************************************/ + +void vchiq_add_connected_callback(VCHIQ_CONNECTED_CALLBACK_T callback) +{ + connected_init(); + + if (mutex_lock_interruptible(&g_connected_mutex) != 0) + return; + + if (g_connected) + /* We're already connected. Call the callback immediately. */ + + callback(); + else { + if (g_num_deferred_callbacks >= MAX_CALLBACKS) + vchiq_log_error(vchiq_core_log_level, + "There already %d callback registered - " + "please increase MAX_CALLBACKS", + g_num_deferred_callbacks); + else { + g_deferred_callback[g_num_deferred_callbacks] = + callback; + g_num_deferred_callbacks++; + } + } + mutex_unlock(&g_connected_mutex); +} + +/**************************************************************************** +* +* This function is called by the vchiq stack once it has been connected to +* the videocore and clients can start to use the stack. +* +***************************************************************************/ + +void vchiq_call_connected_callbacks(void) +{ + int i; + + connected_init(); + + if (mutex_lock_interruptible(&g_connected_mutex) != 0) + return; + + for (i = 0; i < g_num_deferred_callbacks; i++) + g_deferred_callback[i](); + + g_num_deferred_callbacks = 0; + 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 new file mode 100644 index 0000000..863b3e3 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_connected.h @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef 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); + +#endif /* VCHIQ_CONNECTED_H */ diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c new file mode 100644 index 0000000..2c98da4 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c @@ -0,0 +1,3934 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "vchiq_core.h" +#include "vchiq_killable.h" + +#define VCHIQ_SLOT_HANDLER_STACK 8192 + +#define HANDLE_STATE_SHIFT 12 + +#define SLOT_INFO_FROM_INDEX(state, index) (state->slot_info + (index)) +#define SLOT_DATA_FROM_INDEX(state, index) (state->slot_data + (index)) +#define SLOT_INDEX_FROM_DATA(state, data) \ + (((unsigned int)((char *)data - (char *)state->slot_data)) / \ + VCHIQ_SLOT_SIZE) +#define SLOT_INDEX_FROM_INFO(state, info) \ + ((unsigned int)(info - state->slot_info)) +#define SLOT_QUEUE_INDEX_FROM_POS(pos) \ + ((int)((unsigned int)(pos) / VCHIQ_SLOT_SIZE)) + +#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))) + +struct vchiq_open_payload { + int fourcc; + int client_id; + short version; + short version_min; +}; + +struct vchiq_openack_payload { + short version; +}; + +enum +{ + QMFLAGS_IS_BLOCKING = (1 << 0), + QMFLAGS_NO_MUTEX_LOCK = (1 << 1), + QMFLAGS_NO_MUTEX_UNLOCK = (1 << 2) +}; + +/* we require this for consistency between endpoints */ +vchiq_static_assert(sizeof(VCHIQ_HEADER_T) == 8); +vchiq_static_assert(IS_POW2(sizeof(VCHIQ_HEADER_T))); +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); + +/* Run time control of log level, based on KERN_XXX level. */ +int vchiq_core_log_level = VCHIQ_LOG_DEFAULT; +int vchiq_core_msg_log_level = VCHIQ_LOG_DEFAULT; +int vchiq_sync_log_level = VCHIQ_LOG_DEFAULT; + +static atomic_t pause_bulks_count = ATOMIC_INIT(0); + +static DEFINE_SPINLOCK(service_spinlock); +DEFINE_SPINLOCK(bulk_waiter_spinlock); +DEFINE_SPINLOCK(quota_spinlock); + +VCHIQ_STATE_T *vchiq_states[VCHIQ_MAX_STATES]; +static unsigned int handle_seq; + +static const char *const srvstate_names[] = { + "FREE", + "HIDDEN", + "LISTENING", + "OPENING", + "OPEN", + "OPENSYNC", + "CLOSESENT", + "CLOSERECVD", + "CLOSEWAIT", + "CLOSED" +}; + +static const char *const reason_names[] = { + "SERVICE_OPENED", + "SERVICE_CLOSED", + "MESSAGE_AVAILABLE", + "BULK_TRANSMIT_DONE", + "BULK_RECEIVE_DONE", + "BULK_TRANSMIT_ABORTED", + "BULK_RECEIVE_ABORTED" +}; + +static const char *const conn_state_names[] = { + "DISCONNECTED", + "CONNECTING", + "CONNECTED", + "PAUSING", + "PAUSE_SENT", + "PAUSED", + "RESUMING", + "PAUSE_TIMEOUT", + "RESUME_TIMEOUT" +}; + + +static void +release_message_sync(VCHIQ_STATE_T *state, VCHIQ_HEADER_T *header); + +static const char *msg_type_str(unsigned int msg_type) +{ + switch (msg_type) { + case VCHIQ_MSG_PADDING: return "PADDING"; + case VCHIQ_MSG_CONNECT: return "CONNECT"; + case VCHIQ_MSG_OPEN: return "OPEN"; + case VCHIQ_MSG_OPENACK: return "OPENACK"; + case VCHIQ_MSG_CLOSE: return "CLOSE"; + case VCHIQ_MSG_DATA: return "DATA"; + case VCHIQ_MSG_BULK_RX: return "BULK_RX"; + case VCHIQ_MSG_BULK_TX: return "BULK_TX"; + case VCHIQ_MSG_BULK_RX_DONE: return "BULK_RX_DONE"; + case VCHIQ_MSG_BULK_TX_DONE: return "BULK_TX_DONE"; + case VCHIQ_MSG_PAUSE: return "PAUSE"; + case VCHIQ_MSG_RESUME: return "RESUME"; + case VCHIQ_MSG_REMOTE_USE: return "REMOTE_USE"; + case VCHIQ_MSG_REMOTE_RELEASE: return "REMOTE_RELEASE"; + case VCHIQ_MSG_REMOTE_USE_ACTIVE: return "REMOTE_USE_ACTIVE"; + } + return "???"; +} + +static inline void +vchiq_set_service_state(VCHIQ_SERVICE_T *service, int newstate) +{ + vchiq_log_info(vchiq_core_log_level, "%d: srv:%d %s->%s", + service->state->id, service->localport, + srvstate_names[service->srvstate], + srvstate_names[newstate]); + service->srvstate = newstate; +} + +VCHIQ_SERVICE_T * +find_service_by_handle(VCHIQ_SERVICE_HANDLE_T handle) +{ + VCHIQ_SERVICE_T *service; + + spin_lock(&service_spinlock); + service = handle_to_service(handle); + if (service && (service->srvstate != VCHIQ_SRVSTATE_FREE) && + (service->handle == handle)) { + BUG_ON(service->ref_count == 0); + service->ref_count++; + } else + service = NULL; + spin_unlock(&service_spinlock); + + if (!service) + vchiq_log_info(vchiq_core_log_level, + "Invalid service handle 0x%x", handle); + + return service; +} + +VCHIQ_SERVICE_T * +find_service_by_port(VCHIQ_STATE_T *state, int localport) +{ + VCHIQ_SERVICE_T *service = NULL; + if ((unsigned int)localport <= VCHIQ_PORT_MAX) { + spin_lock(&service_spinlock); + service = state->services[localport]; + if (service && (service->srvstate != VCHIQ_SRVSTATE_FREE)) { + BUG_ON(service->ref_count == 0); + service->ref_count++; + } else + service = NULL; + spin_unlock(&service_spinlock); + } + + if (!service) + vchiq_log_info(vchiq_core_log_level, + "Invalid port %d", localport); + + return service; +} + +VCHIQ_SERVICE_T * +find_service_for_instance(VCHIQ_INSTANCE_T instance, + VCHIQ_SERVICE_HANDLE_T handle) { + VCHIQ_SERVICE_T *service; + + spin_lock(&service_spinlock); + service = handle_to_service(handle); + if (service && (service->srvstate != VCHIQ_SRVSTATE_FREE) && + (service->handle == handle) && + (service->instance == instance)) { + BUG_ON(service->ref_count == 0); + service->ref_count++; + } else + service = NULL; + spin_unlock(&service_spinlock); + + if (!service) + vchiq_log_info(vchiq_core_log_level, + "Invalid service handle 0x%x", handle); + + return service; +} + +VCHIQ_SERVICE_T * +find_closed_service_for_instance(VCHIQ_INSTANCE_T instance, + VCHIQ_SERVICE_HANDLE_T handle) { + VCHIQ_SERVICE_T *service; + + spin_lock(&service_spinlock); + service = handle_to_service(handle); + if (service && + ((service->srvstate == VCHIQ_SRVSTATE_FREE) || + (service->srvstate == VCHIQ_SRVSTATE_CLOSED)) && + (service->handle == handle) && + (service->instance == instance)) { + BUG_ON(service->ref_count == 0); + service->ref_count++; + } else + service = NULL; + spin_unlock(&service_spinlock); + + if (!service) + vchiq_log_info(vchiq_core_log_level, + "Invalid service handle 0x%x", handle); + + return service; +} + +VCHIQ_SERVICE_T * +next_service_by_instance(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance, + int *pidx) +{ + VCHIQ_SERVICE_T *service = NULL; + int idx = *pidx; + + spin_lock(&service_spinlock); + while (idx < state->unused_service) { + VCHIQ_SERVICE_T *srv = state->services[idx++]; + if (srv && (srv->srvstate != VCHIQ_SRVSTATE_FREE) && + (srv->instance == instance)) { + service = srv; + BUG_ON(service->ref_count == 0); + service->ref_count++; + break; + } + } + spin_unlock(&service_spinlock); + + *pidx = idx; + + return service; +} + +void +lock_service(VCHIQ_SERVICE_T *service) +{ + spin_lock(&service_spinlock); + BUG_ON(!service || (service->ref_count == 0)); + if (service) + service->ref_count++; + spin_unlock(&service_spinlock); +} + +void +unlock_service(VCHIQ_SERVICE_T *service) +{ + VCHIQ_STATE_T *state = service->state; + spin_lock(&service_spinlock); + BUG_ON(!service || (service->ref_count == 0)); + if (service && service->ref_count) { + service->ref_count--; + if (!service->ref_count) { + BUG_ON(service->srvstate != VCHIQ_SRVSTATE_FREE); + state->services[service->localport] = NULL; + } else + service = NULL; + } + spin_unlock(&service_spinlock); + + if (service && service->userdata_term) + service->userdata_term(service->base.userdata); + + kfree(service); +} + +int +vchiq_get_client_id(VCHIQ_SERVICE_HANDLE_T handle) +{ + VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + int id; + + id = service ? service->client_id : 0; + if (service) + unlock_service(service); + + return id; +} + +void * +vchiq_get_service_userdata(VCHIQ_SERVICE_HANDLE_T handle) +{ + VCHIQ_SERVICE_T *service = handle_to_service(handle); + + return service ? service->base.userdata : NULL; +} + +int +vchiq_get_service_fourcc(VCHIQ_SERVICE_HANDLE_T handle) +{ + VCHIQ_SERVICE_T *service = handle_to_service(handle); + + return service ? service->base.fourcc : 0; +} + +static void +mark_service_closing_internal(VCHIQ_SERVICE_T *service, int sh_thread) +{ + VCHIQ_STATE_T *state = service->state; + VCHIQ_SERVICE_QUOTA_T *service_quota; + + service->closing = 1; + + /* Synchronise with other threads. */ + mutex_lock(&state->recycle_mutex); + mutex_unlock(&state->recycle_mutex); + if (!sh_thread || (state->conn_state != VCHIQ_CONNSTATE_PAUSE_SENT)) { + /* If we're pausing then the slot_mutex is held until resume + * by the slot handler. Therefore don't try to acquire this + * mutex if we're the slot handler and in the pause sent state. + * We don't need to in this case anyway. */ + mutex_lock(&state->slot_mutex); + mutex_unlock(&state->slot_mutex); + } + + /* Unblock any sending thread. */ + service_quota = &state->service_quotas[service->localport]; + up(&service_quota->quota_event); +} + +static void +mark_service_closing(VCHIQ_SERVICE_T *service) +{ + mark_service_closing_internal(service, 0); +} + +static inline VCHIQ_STATUS_T +make_service_callback(VCHIQ_SERVICE_T *service, VCHIQ_REASON_T reason, + VCHIQ_HEADER_T *header, void *bulk_userdata) +{ + VCHIQ_STATUS_T status; + vchiq_log_trace(vchiq_core_log_level, "%d: callback:%d (%s, %x, %x)", + service->state->id, service->localport, reason_names[reason], + (unsigned int)header, (unsigned int)bulk_userdata); + status = service->base.callback(reason, header, service->handle, + bulk_userdata); + if (status == VCHIQ_ERROR) { + vchiq_log_warning(vchiq_core_log_level, + "%d: ignoring ERROR from callback to service %x", + service->state->id, service->handle); + status = VCHIQ_SUCCESS; + } + return status; +} + +inline void +vchiq_set_conn_state(VCHIQ_STATE_T *state, VCHIQ_CONNSTATE_T newstate) +{ + VCHIQ_CONNSTATE_T oldstate = state->conn_state; + vchiq_log_info(vchiq_core_log_level, "%d: %s->%s", state->id, + conn_state_names[oldstate], + conn_state_names[newstate]); + state->conn_state = newstate; + vchiq_platform_conn_state_changed(state, oldstate, newstate); +} + +static inline void +remote_event_create(REMOTE_EVENT_T *event) +{ + event->armed = 0; + /* Don't clear the 'fired' flag because it may already have been set + ** by the other side. */ + sema_init(event->event, 0); +} + +static inline void +remote_event_destroy(REMOTE_EVENT_T *event) +{ + (void)event; +} + +static inline int +remote_event_wait(REMOTE_EVENT_T *event) +{ + if (!event->fired) { + event->armed = 1; + dsb(); + if (!event->fired) { + if (down_interruptible(event->event) != 0) { + event->armed = 0; + return 0; + } + } + event->armed = 0; + wmb(); + } + + event->fired = 0; + return 1; +} + +static inline void +remote_event_signal_local(REMOTE_EVENT_T *event) +{ + event->armed = 0; + up(event->event); +} + +static inline void +remote_event_poll(REMOTE_EVENT_T *event) +{ + if (event->fired && event->armed) + remote_event_signal_local(event); +} + +void +remote_event_pollall(VCHIQ_STATE_T *state) +{ + remote_event_poll(&state->local->sync_trigger); + remote_event_poll(&state->local->sync_release); + remote_event_poll(&state->local->trigger); + remote_event_poll(&state->local->recycle); +} + +/* Round up message sizes so that any space at the end of a slot is always big +** enough for a header. This relies on header size being a power of two, which +** has been verified earlier by a static assertion. */ + +static inline unsigned int +calc_stride(unsigned int size) +{ + /* Allow room for the header */ + size += sizeof(VCHIQ_HEADER_T); + + /* Round up */ + return (size + sizeof(VCHIQ_HEADER_T) - 1) & ~(sizeof(VCHIQ_HEADER_T) + - 1); +} + +/* Called by the slot handler thread */ +static VCHIQ_SERVICE_T * +get_listening_service(VCHIQ_STATE_T *state, int fourcc) +{ + int i; + + WARN_ON(fourcc == VCHIQ_FOURCC_INVALID); + + for (i = 0; i < state->unused_service; i++) { + VCHIQ_SERVICE_T *service = state->services[i]; + if (service && + (service->public_fourcc == fourcc) && + ((service->srvstate == VCHIQ_SRVSTATE_LISTENING) || + ((service->srvstate == VCHIQ_SRVSTATE_OPEN) && + (service->remoteport == VCHIQ_PORT_FREE)))) { + lock_service(service); + return service; + } + } + + return NULL; +} + +/* Called by the slot handler thread */ +static VCHIQ_SERVICE_T * +get_connected_service(VCHIQ_STATE_T *state, unsigned int port) +{ + int i; + for (i = 0; i < state->unused_service; i++) { + VCHIQ_SERVICE_T *service = state->services[i]; + if (service && (service->srvstate == VCHIQ_SRVSTATE_OPEN) + && (service->remoteport == port)) { + lock_service(service); + return service; + } + } + return NULL; +} + +inline void +request_poll(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, int poll_type) +{ + uint32_t value; + + if (service) { + do { + value = atomic_read(&service->poll_flags); + } while (atomic_cmpxchg(&service->poll_flags, value, + value | (1 << poll_type)) != value); + + do { + value = atomic_read(&state->poll_services[ + service->localport>>5]); + } while (atomic_cmpxchg( + &state->poll_services[service->localport>>5], + value, value | (1 << (service->localport & 0x1f))) + != value); + } + + state->poll_needed = 1; + wmb(); + + /* ... and ensure the slot handler runs. */ + remote_event_signal_local(&state->local->trigger); +} + +/* Called from queue_message, by the slot handler and application threads, +** with slot_mutex held */ +static VCHIQ_HEADER_T * +reserve_space(VCHIQ_STATE_T *state, int space, int is_blocking) +{ + VCHIQ_SHARED_STATE_T *local = state->local; + int tx_pos = state->local_tx_pos; + int slot_space = VCHIQ_SLOT_SIZE - (tx_pos & VCHIQ_SLOT_MASK); + + if (space > slot_space) { + VCHIQ_HEADER_T *header; + /* Fill the remaining space with padding */ + WARN_ON(state->tx_data == NULL); + header = (VCHIQ_HEADER_T *) + (state->tx_data + (tx_pos & VCHIQ_SLOT_MASK)); + header->msgid = VCHIQ_MSGID_PADDING; + header->size = slot_space - sizeof(VCHIQ_HEADER_T); + + tx_pos += slot_space; + } + + /* If necessary, get the next slot. */ + if ((tx_pos & VCHIQ_SLOT_MASK) == 0) { + int slot_index; + + /* If there is no free slot... */ + + if (down_trylock(&state->slot_available_event) != 0) { + /* ...wait for one. */ + + VCHIQ_STATS_INC(state, slot_stalls); + + /* But first, flush through the last slot. */ + state->local_tx_pos = tx_pos; + local->tx_pos = tx_pos; + remote_event_signal(&state->remote->trigger); + + if (!is_blocking || + (down_interruptible( + &state->slot_available_event) != 0)) + return NULL; /* No space available */ + } + + BUG_ON(tx_pos == + (state->slot_queue_available * VCHIQ_SLOT_SIZE)); + + slot_index = local->slot_queue[ + SLOT_QUEUE_INDEX_FROM_POS(tx_pos) & + VCHIQ_SLOT_QUEUE_MASK]; + state->tx_data = + (char *)SLOT_DATA_FROM_INDEX(state, slot_index); + } + + state->local_tx_pos = tx_pos + space; + + return (VCHIQ_HEADER_T *)(state->tx_data + (tx_pos & VCHIQ_SLOT_MASK)); +} + +/* Called by the recycle thread. */ +static void +process_free_queue(VCHIQ_STATE_T *state) +{ + VCHIQ_SHARED_STATE_T *local = state->local; + BITSET_T service_found[BITSET_SIZE(VCHIQ_MAX_SERVICES)]; + int slot_queue_available; + + /* Use a read memory barrier to ensure that any state that may have + ** been modified by another thread is not masked by stale prefetched + ** values. */ + rmb(); + + /* Find slots which have been freed by the other side, and return them + ** to the available queue. */ + slot_queue_available = state->slot_queue_available; + + while (slot_queue_available != local->slot_queue_recycle) { + unsigned int pos; + 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; + + vchiq_log_trace(vchiq_core_log_level, "%d: pfq %d=%x %x %x", + state->id, slot_index, (unsigned int)data, + local->slot_queue_recycle, slot_queue_available); + + /* Initialise the bitmask for services which have used this + ** slot */ + BITSET_ZERO(service_found); + + pos = 0; + + while (pos < VCHIQ_SLOT_SIZE) { + VCHIQ_HEADER_T *header = + (VCHIQ_HEADER_T *)(data + pos); + int msgid = header->msgid; + if (VCHIQ_MSG_TYPE(msgid) == VCHIQ_MSG_DATA) { + int port = VCHIQ_MSG_SRCPORT(msgid); + VCHIQ_SERVICE_QUOTA_T *service_quota = + &state->service_quotas[port]; + int count; + spin_lock("a_spinlock); + count = service_quota->message_use_count; + if (count > 0) + service_quota->message_use_count = + count - 1; + spin_unlock("a_spinlock); + + if (count == service_quota->message_quota) + /* Signal the service that it + ** has dropped below its quota + */ + up(&service_quota->quota_event); + else if (count == 0) { + vchiq_log_error(vchiq_core_log_level, + "service %d " + "message_use_count=%d " + "(header %x, msgid %x, " + "header->msgid %x, " + "header->size %x)", + port, + service_quota-> + message_use_count, + (unsigned int)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 = service_quota->slot_use_count; + if (count > 0) + service_quota->slot_use_count = + count - 1; + spin_unlock("a_spinlock); + + if (count > 0) { + /* Signal the service in case + ** it has dropped below its + ** quota */ + up(&service_quota->quota_event); + vchiq_log_trace( + vchiq_core_log_level, + "%d: pfq:%d %x@%x - " + "slot_use->%d", + state->id, port, + header->size, + (unsigned int)header, + count - 1); + } else { + vchiq_log_error( + vchiq_core_log_level, + "service %d " + "slot_use_count" + "=%d (header %x" + ", msgid %x, " + "header->msgid" + " %x, header->" + "size %x)", + port, count, + (unsigned int)header, + msgid, + header->msgid, + header->size); + WARN(1, "bad slot use count\n"); + } + } + + data_found = 1; + } + + pos += calc_stride(header->size); + if (pos > VCHIQ_SLOT_SIZE) { + vchiq_log_error(vchiq_core_log_level, + "pfq - pos %x: header %x, msgid %x, " + "header->msgid %x, header->size %x", + pos, (unsigned int)header, msgid, + header->msgid, header->size); + WARN(1, "invalid slot position\n"); + } + } + + if (data_found) { + int count; + spin_lock("a_spinlock); + count = state->data_use_count; + if (count > 0) + state->data_use_count = + count - 1; + spin_unlock("a_spinlock); + if (count == state->data_quota) + up(&state->data_quota_event); + } + + state->slot_queue_available = slot_queue_available; + up(&state->slot_available_event); + } +} + +/* Called by the slot handler and application threads */ +static VCHIQ_STATUS_T +queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, + int msgid, const VCHIQ_ELEMENT_T *elements, + int count, int size, int flags) +{ + VCHIQ_SHARED_STATE_T *local; + VCHIQ_SERVICE_QUOTA_T *service_quota = NULL; + VCHIQ_HEADER_T *header; + int type = VCHIQ_MSG_TYPE(msgid); + + unsigned int stride; + + local = state->local; + + stride = calc_stride(size); + + WARN_ON(!(stride <= VCHIQ_SLOT_SIZE)); + + if (!(flags & QMFLAGS_NO_MUTEX_LOCK) && + (mutex_lock_interruptible(&state->slot_mutex) != 0)) + return VCHIQ_RETRY; + + if (type == VCHIQ_MSG_DATA) { + int tx_end_index; + + BUG_ON(!service); + BUG_ON((flags & (QMFLAGS_NO_MUTEX_LOCK | + QMFLAGS_NO_MUTEX_UNLOCK)) != 0); + + if (service->closing) { + /* The service has been closed */ + mutex_unlock(&state->slot_mutex); + return VCHIQ_ERROR; + } + + service_quota = &state->service_quotas[service->localport]; + + spin_lock("a_spinlock); + + /* Ensure this service doesn't use more than its quota of + ** messages or slots */ + tx_end_index = SLOT_QUEUE_INDEX_FROM_POS( + state->local_tx_pos + stride - 1); + + /* Ensure data messages don't use more than their quota of + ** slots */ + while ((tx_end_index != state->previous_data_index) && + (state->data_use_count == state->data_quota)) { + VCHIQ_STATS_INC(state, data_stalls); + spin_unlock("a_spinlock); + mutex_unlock(&state->slot_mutex); + + if (down_interruptible(&state->data_quota_event) + != 0) + return VCHIQ_RETRY; + + mutex_lock(&state->slot_mutex); + spin_lock("a_spinlock); + tx_end_index = SLOT_QUEUE_INDEX_FROM_POS( + state->local_tx_pos + stride - 1); + if ((tx_end_index == state->previous_data_index) || + (state->data_use_count < state->data_quota)) { + /* Pass the signal on to other waiters */ + up(&state->data_quota_event); + break; + } + } + + while ((service_quota->message_use_count == + service_quota->message_quota) || + ((tx_end_index != service_quota->previous_tx_index) && + (service_quota->slot_use_count == + service_quota->slot_quota))) { + spin_unlock("a_spinlock); + vchiq_log_trace(vchiq_core_log_level, + "%d: qm:%d %s,%x - quota stall " + "(msg %d, slot %d)", + state->id, service->localport, + msg_type_str(type), size, + service_quota->message_use_count, + service_quota->slot_use_count); + VCHIQ_SERVICE_STATS_INC(service, quota_stalls); + mutex_unlock(&state->slot_mutex); + if (down_interruptible(&service_quota->quota_event) + != 0) + return VCHIQ_RETRY; + if (service->closing) + return VCHIQ_ERROR; + if (mutex_lock_interruptible(&state->slot_mutex) != 0) + return VCHIQ_RETRY; + if (service->srvstate != VCHIQ_SRVSTATE_OPEN) { + /* The service has been closed */ + mutex_unlock(&state->slot_mutex); + return VCHIQ_ERROR; + } + spin_lock("a_spinlock); + tx_end_index = SLOT_QUEUE_INDEX_FROM_POS( + state->local_tx_pos + stride - 1); + } + + spin_unlock("a_spinlock); + } + + header = reserve_space(state, stride, flags & QMFLAGS_IS_BLOCKING); + + if (!header) { + if (service) + VCHIQ_SERVICE_STATS_INC(service, slot_stalls); + /* In the event of a failure, return the mutex to the + state it was in */ + if (!(flags & QMFLAGS_NO_MUTEX_LOCK)) + mutex_unlock(&state->slot_mutex); + return VCHIQ_RETRY; + } + + if (type == VCHIQ_MSG_DATA) { + int i, pos; + int tx_end_index; + int slot_use_count; + + vchiq_log_info(vchiq_core_log_level, + "%d: qm %s@%x,%x (%d->%d)", + state->id, + msg_type_str(VCHIQ_MSG_TYPE(msgid)), + (unsigned int)header, size, + VCHIQ_MSG_SRCPORT(msgid), + VCHIQ_MSG_DSTPORT(msgid)); + + BUG_ON(!service); + BUG_ON((flags & (QMFLAGS_NO_MUTEX_LOCK | + QMFLAGS_NO_MUTEX_UNLOCK)) != 0); + + for (i = 0, pos = 0; i < (unsigned int)count; + pos += elements[i++].size) + if (elements[i].size) { + if (vchiq_copy_from_user + (header->data + pos, elements[i].data, + (size_t) elements[i].size) != + VCHIQ_SUCCESS) { + mutex_unlock(&state->slot_mutex); + VCHIQ_SERVICE_STATS_INC(service, + error_count); + return VCHIQ_ERROR; + } + if (i == 0) { + if (SRVTRACE_ENABLED(service, + VCHIQ_LOG_INFO)) + vchiq_log_dump_mem("Sent", 0, + header->data + pos, + min(64u, + elements[0].size)); + } + } + + spin_lock("a_spinlock); + service_quota->message_use_count++; + + tx_end_index = + SLOT_QUEUE_INDEX_FROM_POS(state->local_tx_pos - 1); + + /* If this transmission can't fit in the last slot used by any + ** service, the data_use_count must be increased. */ + if (tx_end_index != state->previous_data_index) { + state->previous_data_index = tx_end_index; + state->data_use_count++; + } + + /* If this isn't the same slot last used by this service, + ** the service's slot_use_count must be increased. */ + if (tx_end_index != service_quota->previous_tx_index) { + service_quota->previous_tx_index = tx_end_index; + slot_use_count = ++service_quota->slot_use_count; + } else { + slot_use_count = 0; + } + + spin_unlock("a_spinlock); + + if (slot_use_count) + vchiq_log_trace(vchiq_core_log_level, + "%d: qm:%d %s,%x - slot_use->%d (hdr %p)", + state->id, service->localport, + msg_type_str(VCHIQ_MSG_TYPE(msgid)), size, + slot_use_count, header); + + VCHIQ_SERVICE_STATS_INC(service, ctrl_tx_count); + VCHIQ_SERVICE_STATS_ADD(service, ctrl_tx_bytes, size); + } else { + vchiq_log_info(vchiq_core_log_level, + "%d: qm %s@%x,%x (%d->%d)", state->id, + msg_type_str(VCHIQ_MSG_TYPE(msgid)), + (unsigned int)header, size, + VCHIQ_MSG_SRCPORT(msgid), + VCHIQ_MSG_DSTPORT(msgid)); + if (size != 0) { + WARN_ON(!((count == 1) && (size == elements[0].size))); + memcpy(header->data, elements[0].data, + elements[0].size); + } + VCHIQ_STATS_INC(state, ctrl_tx_count); + } + + header->msgid = msgid; + header->size = size; + + { + int svc_fourcc; + + svc_fourcc = service + ? service->base.fourcc + : VCHIQ_MAKE_FOURCC('?', '?', '?', '?'); + + vchiq_log_info(SRVTRACE_LEVEL(service), + "Sent Msg %s(%u) to %c%c%c%c s:%u d:%d len:%d", + msg_type_str(VCHIQ_MSG_TYPE(msgid)), + VCHIQ_MSG_TYPE(msgid), + VCHIQ_FOURCC_AS_4CHARS(svc_fourcc), + VCHIQ_MSG_SRCPORT(msgid), + VCHIQ_MSG_DSTPORT(msgid), + size); + } + + /* Make sure the new header is visible to the peer. */ + wmb(); + + /* Make the new tx_pos visible to the peer. */ + local->tx_pos = state->local_tx_pos; + wmb(); + + if (service && (type == VCHIQ_MSG_CLOSE)) + vchiq_set_service_state(service, VCHIQ_SRVSTATE_CLOSESENT); + + if (!(flags & QMFLAGS_NO_MUTEX_UNLOCK)) + mutex_unlock(&state->slot_mutex); + + remote_event_signal(&state->remote->trigger); + + return VCHIQ_SUCCESS; +} + +/* Called by the slot handler and application threads */ +static VCHIQ_STATUS_T +queue_message_sync(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, + int msgid, const VCHIQ_ELEMENT_T *elements, + int count, int size, int is_blocking) +{ + VCHIQ_SHARED_STATE_T *local; + VCHIQ_HEADER_T *header; + + local = state->local; + + if ((VCHIQ_MSG_TYPE(msgid) != VCHIQ_MSG_RESUME) && + (mutex_lock_interruptible(&state->sync_mutex) != 0)) + return VCHIQ_RETRY; + + remote_event_wait(&local->sync_release); + + rmb(); + + header = (VCHIQ_HEADER_T *)SLOT_DATA_FROM_INDEX(state, + local->slot_sync); + + { + int oldmsgid = header->msgid; + if (oldmsgid != VCHIQ_MSGID_PADDING) + vchiq_log_error(vchiq_core_log_level, + "%d: qms - msgid %x, not PADDING", + state->id, oldmsgid); + } + + if (service) { + int i, pos; + + vchiq_log_info(vchiq_sync_log_level, + "%d: qms %s@%x,%x (%d->%d)", state->id, + msg_type_str(VCHIQ_MSG_TYPE(msgid)), + (unsigned int)header, size, + VCHIQ_MSG_SRCPORT(msgid), + VCHIQ_MSG_DSTPORT(msgid)); + + for (i = 0, pos = 0; i < (unsigned int)count; + pos += elements[i++].size) + if (elements[i].size) { + if (vchiq_copy_from_user + (header->data + pos, elements[i].data, + (size_t) elements[i].size) != + VCHIQ_SUCCESS) { + mutex_unlock(&state->sync_mutex); + VCHIQ_SERVICE_STATS_INC(service, + error_count); + return VCHIQ_ERROR; + } + if (i == 0) { + if (vchiq_sync_log_level >= + VCHIQ_LOG_TRACE) + vchiq_log_dump_mem("Sent Sync", + 0, header->data + pos, + min(64u, + elements[0].size)); + } + } + + VCHIQ_SERVICE_STATS_INC(service, ctrl_tx_count); + VCHIQ_SERVICE_STATS_ADD(service, ctrl_tx_bytes, size); + } else { + vchiq_log_info(vchiq_sync_log_level, + "%d: qms %s@%x,%x (%d->%d)", state->id, + msg_type_str(VCHIQ_MSG_TYPE(msgid)), + (unsigned int)header, size, + VCHIQ_MSG_SRCPORT(msgid), + VCHIQ_MSG_DSTPORT(msgid)); + if (size != 0) { + WARN_ON(!((count == 1) && (size == elements[0].size))); + memcpy(header->data, elements[0].data, + elements[0].size); + } + VCHIQ_STATS_INC(state, ctrl_tx_count); + } + + header->size = size; + header->msgid = msgid; + + if (vchiq_sync_log_level >= VCHIQ_LOG_TRACE) { + int svc_fourcc; + + svc_fourcc = service + ? service->base.fourcc + : VCHIQ_MAKE_FOURCC('?', '?', '?', '?'); + + vchiq_log_trace(vchiq_sync_log_level, + "Sent Sync Msg %s(%u) to %c%c%c%c s:%u d:%d len:%d", + msg_type_str(VCHIQ_MSG_TYPE(msgid)), + VCHIQ_MSG_TYPE(msgid), + VCHIQ_FOURCC_AS_4CHARS(svc_fourcc), + VCHIQ_MSG_SRCPORT(msgid), + VCHIQ_MSG_DSTPORT(msgid), + size); + } + + /* Make sure the new header is visible to the peer. */ + wmb(); + + remote_event_signal(&state->remote->sync_trigger); + + if (VCHIQ_MSG_TYPE(msgid) != VCHIQ_MSG_PAUSE) + mutex_unlock(&state->sync_mutex); + + return VCHIQ_SUCCESS; +} + +static inline void +claim_slot(VCHIQ_SLOT_INFO_T *slot) +{ + slot->use_count++; +} + +static void +release_slot(VCHIQ_STATE_T *state, VCHIQ_SLOT_INFO_T *slot_info, + VCHIQ_HEADER_T *header, VCHIQ_SERVICE_T *service) +{ + int release_count; + + mutex_lock(&state->recycle_mutex); + + if (header) { + int msgid = header->msgid; + if (((msgid & VCHIQ_MSGID_CLAIMED) == 0) || + (service && service->closing)) { + mutex_unlock(&state->recycle_mutex); + return; + } + + /* Rewrite the message header to prevent a double + ** release */ + header->msgid = msgid & ~VCHIQ_MSGID_CLAIMED; + } + + release_count = slot_info->release_count; + slot_info->release_count = ++release_count; + + if (release_count == slot_info->use_count) { + int slot_queue_recycle; + /* Add to the freed queue */ + + /* A read barrier is necessary here to prevent speculative + ** fetches of remote->slot_queue_recycle from overtaking the + ** mutex. */ + rmb(); + + slot_queue_recycle = state->remote->slot_queue_recycle; + state->remote->slot_queue[slot_queue_recycle & + VCHIQ_SLOT_QUEUE_MASK] = + SLOT_INDEX_FROM_INFO(state, slot_info); + state->remote->slot_queue_recycle = slot_queue_recycle + 1; + vchiq_log_info(vchiq_core_log_level, + "%d: release_slot %d - recycle->%x", + state->id, SLOT_INDEX_FROM_INFO(state, slot_info), + state->remote->slot_queue_recycle); + + /* A write barrier is necessary, but remote_event_signal + ** contains one. */ + remote_event_signal(&state->remote->recycle); + } + + mutex_unlock(&state->recycle_mutex); +} + +/* Called by the slot handler - don't hold the bulk mutex */ +static VCHIQ_STATUS_T +notify_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue, + int retry_poll) +{ + VCHIQ_STATUS_T status = VCHIQ_SUCCESS; + + vchiq_log_trace(vchiq_core_log_level, + "%d: nb:%d %cx - p=%x rn=%x r=%x", + service->state->id, service->localport, + (queue == &service->bulk_tx) ? 't' : 'r', + queue->process, queue->remote_notify, queue->remove); + + if (service->state->is_master) { + while (queue->remote_notify != queue->process) { + VCHIQ_BULK_T *bulk = + &queue->bulks[BULK_INDEX(queue->remote_notify)]; + int msgtype = (bulk->dir == VCHIQ_BULK_TRANSMIT) ? + VCHIQ_MSG_BULK_RX_DONE : VCHIQ_MSG_BULK_TX_DONE; + int msgid = VCHIQ_MAKE_MSG(msgtype, service->localport, + service->remoteport); + VCHIQ_ELEMENT_T element = { &bulk->actual, 4 }; + /* Only reply to non-dummy bulk requests */ + if (bulk->remote_data) { + status = queue_message(service->state, NULL, + msgid, &element, 1, 4, 0); + if (status != VCHIQ_SUCCESS) + break; + } + queue->remote_notify++; + } + } else { + queue->remote_notify = queue->process; + } + + if (status == VCHIQ_SUCCESS) { + while (queue->remove != queue->remote_notify) { + VCHIQ_BULK_T *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); + } + } 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; + up(&waiter->event); + } + spin_unlock(&bulk_waiter_spinlock); + } else if (bulk->mode == + VCHIQ_BULK_MODE_CALLBACK) { + VCHIQ_REASON_T 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; + } + } + + queue->remove++; + up(&service->bulk_remove_event); + } + if (!retry_poll) + status = VCHIQ_SUCCESS; + } + + if (status == VCHIQ_RETRY) + request_poll(service->state, service, + (queue == &service->bulk_tx) ? + VCHIQ_POLL_TXNOTIFY : VCHIQ_POLL_RXNOTIFY); + + return status; +} + +/* Called by the slot handler thread */ +static void +poll_services(VCHIQ_STATE_T *state) +{ + int group, i; + + for (group = 0; group < BITSET_SIZE(state->unused_service); group++) { + uint32_t flags; + flags = atomic_xchg(&state->poll_services[group], 0); + for (i = 0; flags; i++) { + if (flags & (1 << i)) { + VCHIQ_SERVICE_T *service = + find_service_by_port(state, + (group<<5) + i); + uint32_t service_flags; + flags &= ~(1 << i); + if (!service) + continue; + service_flags = + atomic_xchg(&service->poll_flags, 0); + if (service_flags & + (1 << 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 & + (1 << 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 & (1 << VCHIQ_POLL_TXNOTIFY)) + notify_bulks(service, + &service->bulk_tx, + 1/*retry_poll*/); + if (service_flags & (1 << VCHIQ_POLL_RXNOTIFY)) + notify_bulks(service, + &service->bulk_rx, + 1/*retry_poll*/); + unlock_service(service); + } + } + } +} + +/* Called by the slot handler or application threads, holding the bulk mutex. */ +static int +resolve_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue) +{ + VCHIQ_STATE_T *state = service->state; + int resolved = 0; + int rc; + + while ((queue->process != queue->local_insert) && + (queue->process != queue->remote_insert)) { + VCHIQ_BULK_T *bulk = &queue->bulks[BULK_INDEX(queue->process)]; + + vchiq_log_trace(vchiq_core_log_level, + "%d: rb:%d %cx - li=%x ri=%x p=%x", + state->id, service->localport, + (queue == &service->bulk_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)); + + rc = mutex_lock_interruptible(&state->bulk_transfer_mutex); + if (rc != 0) + break; + + vchiq_transfer_bulk(bulk); + mutex_unlock(&state->bulk_transfer_mutex); + + if (SRVTRACE_ENABLED(service, VCHIQ_LOG_INFO)) { + const char *header = (queue == &service->bulk_tx) ? + "Send Bulk to" : "Recv Bulk from"; + if (bulk->actual != VCHIQ_BULK_ACTUAL_ABORTED) + vchiq_log_info(SRVTRACE_LEVEL(service), + "%s %c%c%c%c d:%d len:%d %x<->%x", + header, + VCHIQ_FOURCC_AS_4CHARS( + service->base.fourcc), + service->remoteport, + bulk->size, + (unsigned int)bulk->data, + (unsigned int)bulk->remote_data); + else + vchiq_log_info(SRVTRACE_LEVEL(service), + "%s %c%c%c%c d:%d ABORTED - tx len:%d," + " rx len:%d %x<->%x", + header, + VCHIQ_FOURCC_AS_4CHARS( + service->base.fourcc), + service->remoteport, + bulk->size, + bulk->remote_size, + (unsigned int)bulk->data, + (unsigned int)bulk->remote_data); + } + + vchiq_complete_bulk(bulk); + queue->process++; + resolved++; + } + return resolved; +} + +/* Called with the bulk_mutex held */ +static void +abort_outstanding_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue) +{ + int is_tx = (queue == &service->bulk_tx); + vchiq_log_trace(vchiq_core_log_level, + "%d: aob:%d %cx - li=%x ri=%x p=%x", + 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)); + + while ((queue->process != queue->local_insert) || + (queue->process != queue->remote_insert)) { + VCHIQ_BULK_T *bulk = &queue->bulks[BULK_INDEX(queue->process)]; + + if (queue->process == queue->remote_insert) { + /* fabricate a matching dummy bulk */ + bulk->remote_data = NULL; + bulk->remote_size = 0; + queue->remote_insert++; + } + + if (queue->process != queue->local_insert) { + vchiq_complete_bulk(bulk); + + vchiq_log_info(SRVTRACE_LEVEL(service), + "%s %c%c%c%c d:%d ABORTED - tx len:%d, " + "rx len:%d", + is_tx ? "Send Bulk to" : "Recv Bulk from", + VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc), + service->remoteport, + bulk->size, + bulk->remote_size); + } else { + /* fabricate a matching dummy bulk */ + bulk->data = NULL; + bulk->size = 0; + bulk->actual = VCHIQ_BULK_ACTUAL_ABORTED; + bulk->dir = is_tx ? VCHIQ_BULK_TRANSMIT : + VCHIQ_BULK_RECEIVE; + queue->local_insert++; + } + + queue->process++; + } +} + +/* Called from the slot handler thread */ +static void +pause_bulks(VCHIQ_STATE_T *state) +{ + if (unlikely(atomic_inc_return(&pause_bulks_count) != 1)) { + WARN_ON_ONCE(1); + atomic_set(&pause_bulks_count, 1); + return; + } + + /* Block bulk transfers from all services */ + mutex_lock(&state->bulk_transfer_mutex); +} + +/* Called from the slot handler thread */ +static void +resume_bulks(VCHIQ_STATE_T *state) +{ + int i; + if (unlikely(atomic_dec_return(&pause_bulks_count) != 0)) { + WARN_ON_ONCE(1); + atomic_set(&pause_bulks_count, 0); + return; + } + + /* Allow bulk transfers from all services */ + mutex_unlock(&state->bulk_transfer_mutex); + + if (state->deferred_bulks == 0) + return; + + /* Deal with any bulks which had to be deferred due to being in + * paused state. Don't try to match up to number of deferred bulks + * in case we've had something come and close the service in the + * interim - just process all bulk queues for all services */ + vchiq_log_info(vchiq_core_log_level, "%s: processing %d deferred bulks", + __func__, state->deferred_bulks); + + for (i = 0; i < state->unused_service; i++) { + VCHIQ_SERVICE_T *service = state->services[i]; + int resolved_rx = 0; + int resolved_tx = 0; + if (!service || (service->srvstate != VCHIQ_SRVSTATE_OPEN)) + continue; + + mutex_lock(&service->bulk_mutex); + resolved_rx = resolve_bulks(service, &service->bulk_rx); + resolved_tx = resolve_bulks(service, &service->bulk_tx); + mutex_unlock(&service->bulk_mutex); + if (resolved_rx) + notify_bulks(service, &service->bulk_rx, 1); + if (resolved_tx) + notify_bulks(service, &service->bulk_tx, 1); + } + state->deferred_bulks = 0; +} + +static int +parse_open(VCHIQ_STATE_T *state, VCHIQ_HEADER_T *header) +{ + VCHIQ_SERVICE_T *service = NULL; + int msgid, size; + int type; + unsigned int localport, remoteport; + + msgid = header->msgid; + size = header->size; + type = VCHIQ_MSG_TYPE(msgid); + 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@%x (%d->'%c%c%c%c')", + state->id, (unsigned int)header, + localport, + VCHIQ_FOURCC_AS_4CHARS(fourcc)); + + service = get_listening_service(state, fourcc); + + 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; + + if (service->srvstate == VCHIQ_SRVSTATE_LISTENING) { + struct vchiq_openack_payload ack_payload = { + service->version + }; + VCHIQ_ELEMENT_T body = { + &ack_payload, + sizeof(ack_payload) + }; + + if (state->version_common < + VCHIQ_VERSION_SYNCHRONOUS_MODE) + service->sync = 0; + + /* Acknowledge the OPEN */ + if (service->sync && + (state->version_common >= + VCHIQ_VERSION_SYNCHRONOUS_MODE)) { + if (queue_message_sync(state, NULL, + VCHIQ_MAKE_MSG( + VCHIQ_MSG_OPENACK, + service->localport, + remoteport), + &body, 1, 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), + &body, 1, 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); + } + + service->remoteport = remoteport; + service->client_id = ((int *)header->data)[1]; + if (make_service_callback(service, VCHIQ_SERVICE_OPENED, + NULL, NULL) == VCHIQ_RETRY) { + /* Bail out if not ready */ + service->remoteport = VCHIQ_PORT_FREE; + goto bail_not_ready; + } + + /* Success - the message has been dealt with */ + unlock_service(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)), + NULL, 0, 0, 0) == VCHIQ_RETRY) + goto bail_not_ready; + + return 1; + +bail_not_ready: + if (service) + unlock_service(service); + + return 0; +} + +/* Called by the slot handler thread */ +static void +parse_rx_slots(VCHIQ_STATE_T *state) +{ + VCHIQ_SHARED_STATE_T *remote = state->remote; + VCHIQ_SERVICE_T *service = NULL; + int tx_pos; + DEBUG_INITIALISE(state->local) + + tx_pos = remote->tx_pos; + + while (state->rx_pos != tx_pos) { + VCHIQ_HEADER_T *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(state->rx_pos) & + VCHIQ_SLOT_QUEUE_MASK]; + 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 = (VCHIQ_HEADER_T *)(state->rx_data + + (state->rx_pos & VCHIQ_SLOT_MASK)); + DEBUG_VALUE(PARSE_HEADER, (int)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)) { + /* 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@%x (%d->%d) - " + "found connected service %d", + state->id, msg_type_str(type), + (unsigned int)header, + remoteport, localport, + service->localport); + } + + if (!service) { + vchiq_log_error(vchiq_core_log_level, + "%d: prs %s@%x (%d->%d) - " + "invalid/closed service %d", + state->id, msg_type_str(type), + (unsigned int)header, + remoteport, localport, localport); + goto skip_message; + } + break; + default: + break; + } + + if (SRVTRACE_ENABLED(service, VCHIQ_LOG_INFO)) { + int svc_fourcc; + + 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(64, size)); + } + + if (((unsigned int)header & VCHIQ_SLOT_MASK) + calc_stride(size) + > VCHIQ_SLOT_SIZE) { + vchiq_log_error(vchiq_core_log_level, + "header %x (msgid %x) - size %x too big for " + "slot", + (unsigned int)header, (unsigned int)msgid, + (unsigned int)size); + WARN(1, "oversized for slot\n"); + } + + 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@%x,%x (%d->%d) v:%d", + state->id, (unsigned int)header, size, + remoteport, localport, service->peer_version); + if (service->srvstate == + VCHIQ_SRVSTATE_OPENING) { + service->remoteport = remoteport; + vchiq_set_service_state(service, + VCHIQ_SRVSTATE_OPEN); + up(&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@%x (%d->%d)", + state->id, (unsigned int)header, + remoteport, localport); + + mark_service_closing_internal(service, 1); + + if (vchiq_close_service_internal(service, + 1/*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@%x,%x (%d->%d)", + state->id, (unsigned int)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); + 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); + } + break; + case VCHIQ_MSG_CONNECT: + vchiq_log_info(vchiq_core_log_level, + "%d: prs CONNECT@%x", + state->id, (unsigned int)header); + state->version_common = ((VCHIQ_SLOT_ZERO_T *) + state->slot_data)->version; + up(&state->connect); + break; + case VCHIQ_MSG_BULK_RX: + case VCHIQ_MSG_BULK_TX: { + VCHIQ_BULK_QUEUE_T *queue; + WARN_ON(!state->is_master); + queue = (type == VCHIQ_MSG_BULK_RX) ? + &service->bulk_tx : &service->bulk_rx; + if ((service->remoteport == remoteport) + && (service->srvstate == + VCHIQ_SRVSTATE_OPEN)) { + VCHIQ_BULK_T *bulk; + int resolved = 0; + + DEBUG_TRACE(PARSE_LINE); + if (mutex_lock_interruptible( + &service->bulk_mutex) != 0) { + DEBUG_TRACE(PARSE_LINE); + goto bail_not_ready; + } + + WARN_ON(!(queue->remote_insert < queue->remove + + VCHIQ_NUM_SERVICE_BULKS)); + bulk = &queue->bulks[ + BULK_INDEX(queue->remote_insert)]; + bulk->remote_data = + (void *)((int *)header->data)[0]; + bulk->remote_size = ((int *)header->data)[1]; + wmb(); + + vchiq_log_info(vchiq_core_log_level, + "%d: prs %s@%x (%d->%d) %x@%x", + state->id, msg_type_str(type), + (unsigned int)header, + remoteport, localport, + bulk->remote_size, + (unsigned int)bulk->remote_data); + + queue->remote_insert++; + + if (atomic_read(&pause_bulks_count)) { + state->deferred_bulks++; + vchiq_log_info(vchiq_core_log_level, + "%s: deferring bulk (%d)", + __func__, + state->deferred_bulks); + if (state->conn_state != + VCHIQ_CONNSTATE_PAUSE_SENT) + vchiq_log_error( + vchiq_core_log_level, + "%s: bulks paused in " + "unexpected state %s", + __func__, + conn_state_names[ + state->conn_state]); + } else if (state->conn_state == + VCHIQ_CONNSTATE_CONNECTED) { + DEBUG_TRACE(PARSE_LINE); + resolved = resolve_bulks(service, + queue); + } + + mutex_unlock(&service->bulk_mutex); + if (resolved) + notify_bulks(service, queue, + 1/*retry_poll*/); + } + } break; + case VCHIQ_MSG_BULK_RX_DONE: + case VCHIQ_MSG_BULK_TX_DONE: + WARN_ON(state->is_master); + if ((service->remoteport == remoteport) + && (service->srvstate != + VCHIQ_SRVSTATE_FREE)) { + VCHIQ_BULK_QUEUE_T *queue; + VCHIQ_BULK_T *bulk; + + queue = (type == VCHIQ_MSG_BULK_RX_DONE) ? + &service->bulk_rx : &service->bulk_tx; + + DEBUG_TRACE(PARSE_LINE); + if (mutex_lock_interruptible( + &service->bulk_mutex) != 0) { + 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@%x (%d->%d) " + "unexpected (ri=%d,li=%d)", + state->id, msg_type_str(type), + (unsigned int)header, + remoteport, localport, + queue->remote_insert, + queue->local_insert); + mutex_unlock(&service->bulk_mutex); + break; + } + + BUG_ON(queue->process == queue->local_insert); + BUG_ON(queue->process != queue->remote_insert); + + 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@%x (%d->%d) %x@%x", + state->id, msg_type_str(type), + (unsigned int)header, + remoteport, localport, + bulk->actual, (unsigned int)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, 1/*retry_poll*/); + DEBUG_TRACE(PARSE_LINE); + } + break; + case VCHIQ_MSG_PADDING: + vchiq_log_trace(vchiq_core_log_level, + "%d: prs PADDING@%x,%x", + state->id, (unsigned int)header, size); + break; + case VCHIQ_MSG_PAUSE: + /* If initiated, signal the application thread */ + vchiq_log_trace(vchiq_core_log_level, + "%d: prs PAUSE@%x,%x", + state->id, (unsigned int)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, 0, 0, QMFLAGS_NO_MUTEX_UNLOCK) + == VCHIQ_RETRY) + goto bail_not_ready; + if (state->is_master) + pause_bulks(state); + } + /* At this point slot_mutex is held */ + vchiq_set_conn_state(state, VCHIQ_CONNSTATE_PAUSED); + vchiq_platform_paused(state); + break; + case VCHIQ_MSG_RESUME: + vchiq_log_trace(vchiq_core_log_level, + "%d: prs RESUME@%x,%x", + state->id, (unsigned int)header, size); + /* Release the slot mutex */ + mutex_unlock(&state->slot_mutex); + if (state->is_master) + resume_bulks(state); + vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED); + vchiq_platform_resumed(state); + 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: + vchiq_on_remote_use_active(state); + break; + + default: + vchiq_log_error(vchiq_core_log_level, + "%d: prs invalid msgid %x@%x,%x", + state->id, msgid, (unsigned int)header, size); + WARN(1, "invalid message\n"); + break; + } + +skip_message: + if (service) { + unlock_service(service); + service = NULL; + } + + state->rx_pos += calc_stride(size); + + DEBUG_TRACE(PARSE_LINE); + /* Perform some housekeeping when the end of the slot is + ** reached. */ + if ((state->rx_pos & VCHIQ_SLOT_MASK) == 0) { + /* Remove the extra reference count. */ + release_slot(state, state->rx_info, NULL, NULL); + state->rx_data = NULL; + } + } + +bail_not_ready: + if (service) + unlock_service(service); +} + +/* Called by the slot handler thread */ +static int +slot_handler_func(void *v) +{ + VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v; + VCHIQ_SHARED_STATE_T *local = state->local; + DEBUG_INITIALISE(local) + + while (1) { + DEBUG_COUNT(SLOT_HANDLER_COUNT); + DEBUG_TRACE(SLOT_HANDLER_LINE); + remote_event_wait(&local->trigger); + + rmb(); + + DEBUG_TRACE(SLOT_HANDLER_LINE); + if (state->poll_needed) { + /* Check if we need to suspend - may change our + * conn_state */ + vchiq_platform_check_suspend(state); + + 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 (state->is_master) + pause_bulks(state); + if (queue_message(state, NULL, + VCHIQ_MAKE_MSG(VCHIQ_MSG_PAUSE, 0, 0), + NULL, 0, 0, + QMFLAGS_NO_MUTEX_UNLOCK) + != VCHIQ_RETRY) { + vchiq_set_conn_state(state, + VCHIQ_CONNSTATE_PAUSE_SENT); + } else { + if (state->is_master) + resume_bulks(state); + /* Retry later */ + state->poll_needed = 1; + } + break; + + case VCHIQ_CONNSTATE_PAUSED: + vchiq_platform_resume(state); + break; + + case VCHIQ_CONNSTATE_RESUMING: + if (queue_message(state, NULL, + VCHIQ_MAKE_MSG(VCHIQ_MSG_RESUME, 0, 0), + NULL, 0, 0, QMFLAGS_NO_MUTEX_LOCK) + != VCHIQ_RETRY) { + if (state->is_master) + resume_bulks(state); + vchiq_set_conn_state(state, + VCHIQ_CONNSTATE_CONNECTED); + vchiq_platform_resumed(state); + } 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"); + BUG(); + } + break; + + case VCHIQ_CONNSTATE_PAUSE_TIMEOUT: + case VCHIQ_CONNSTATE_RESUME_TIMEOUT: + vchiq_platform_handle_timeout(state); + break; + default: + break; + } + + + } + + DEBUG_TRACE(SLOT_HANDLER_LINE); + parse_rx_slots(state); + } + return 0; +} + + +/* Called by the recycle thread */ +static int +recycle_func(void *v) +{ + VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v; + VCHIQ_SHARED_STATE_T *local = state->local; + + while (1) { + remote_event_wait(&local->recycle); + + process_free_queue(state); + } + return 0; +} + + +/* Called by the sync thread */ +static int +sync_func(void *v) +{ + VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v; + VCHIQ_SHARED_STATE_T *local = state->local; + VCHIQ_HEADER_T *header = (VCHIQ_HEADER_T *)SLOT_DATA_FROM_INDEX(state, + state->remote->slot_sync); + + while (1) { + VCHIQ_SERVICE_T *service; + int msgid, size; + int type; + unsigned int localport, remoteport; + + remote_event_wait(&local->sync_trigger); + + rmb(); + + msgid = header->msgid; + size = header->size; + type = VCHIQ_MSG_TYPE(msgid); + localport = VCHIQ_MSG_DSTPORT(msgid); + remoteport = VCHIQ_MSG_SRCPORT(msgid); + + service = find_service_by_port(state, localport); + + if (!service) { + vchiq_log_error(vchiq_sync_log_level, + "%d: sf %s@%x (%d->%d) - " + "invalid/closed service %d", + state->id, msg_type_str(type), + (unsigned int)header, + remoteport, localport, localport); + release_message_sync(state, header); + continue; + } + + if (vchiq_sync_log_level >= VCHIQ_LOG_TRACE) { + int svc_fourcc; + + svc_fourcc = service + ? service->base.fourcc + : VCHIQ_MAKE_FOURCC('?', '?', '?', '?'); + vchiq_log_trace(vchiq_sync_log_level, + "Rcvd Msg %s from %c%c%c%c s:%d d:%d len:%d", + msg_type_str(type), + VCHIQ_FOURCC_AS_4CHARS(svc_fourcc), + remoteport, localport, size); + if (size > 0) + vchiq_log_dump_mem("Rcvd", 0, header->data, + min(64, size)); + } + + switch (type) { + 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_sync_log_level, + "%d: sf OPENACK@%x,%x (%d->%d) v:%d", + state->id, (unsigned int)header, size, + remoteport, localport, service->peer_version); + if (service->srvstate == VCHIQ_SRVSTATE_OPENING) { + service->remoteport = remoteport; + vchiq_set_service_state(service, + VCHIQ_SRVSTATE_OPENSYNC); + service->sync = 1; + up(&service->remove_event); + } + release_message_sync(state, header); + break; + + case VCHIQ_MSG_DATA: + vchiq_log_trace(vchiq_sync_log_level, + "%d: sf DATA@%x,%x (%d->%d)", + state->id, (unsigned int)header, size, + remoteport, localport); + + if ((service->remoteport == remoteport) && + (service->srvstate == + VCHIQ_SRVSTATE_OPENSYNC)) { + if (make_service_callback(service, + VCHIQ_MESSAGE_AVAILABLE, header, + NULL) == VCHIQ_RETRY) + vchiq_log_error(vchiq_sync_log_level, + "synchronous callback to " + "service %d returns " + "VCHIQ_RETRY", + localport); + } + break; + + default: + vchiq_log_error(vchiq_sync_log_level, + "%d: sf unexpected msgid %x@%x,%x", + state->id, msgid, (unsigned int)header, size); + release_message_sync(state, header); + break; + } + + unlock_service(service); + } + + return 0; +} + + +static void +init_bulk_queue(VCHIQ_BULK_QUEUE_T *queue) +{ + queue->local_insert = 0; + queue->remote_insert = 0; + queue->process = 0; + queue->remote_notify = 0; + queue->remove = 0; +} + + +inline const char * +get_conn_state_name(VCHIQ_CONNSTATE_T conn_state) +{ + return conn_state_names[conn_state]; +} + + +VCHIQ_SLOT_ZERO_T * +vchiq_init_slots(void *mem_base, int mem_size) +{ + int mem_align = (VCHIQ_SLOT_SIZE - (int)mem_base) & VCHIQ_SLOT_MASK; + VCHIQ_SLOT_ZERO_T *slot_zero = + (VCHIQ_SLOT_ZERO_T *)((char *)mem_base + mem_align); + int num_slots = (mem_size - mem_align)/VCHIQ_SLOT_SIZE; + int first_data_slot = VCHIQ_SLOT_ZERO_SLOTS; + + /* Ensure there is enough memory to run an absolutely minimum system */ + num_slots -= first_data_slot; + + if (num_slots < 4) { + vchiq_log_error(vchiq_core_log_level, + "vchiq_init_slots - insufficient memory %x bytes", + mem_size); + return NULL; + } + + memset(slot_zero, 0, sizeof(VCHIQ_SLOT_ZERO_T)); + + slot_zero->magic = VCHIQ_MAGIC; + slot_zero->version = VCHIQ_VERSION; + slot_zero->version_min = VCHIQ_VERSION_MIN; + slot_zero->slot_zero_size = sizeof(VCHIQ_SLOT_ZERO_T); + slot_zero->slot_size = VCHIQ_SLOT_SIZE; + slot_zero->max_slots = VCHIQ_MAX_SLOTS; + slot_zero->max_slots_per_side = VCHIQ_MAX_SLOTS_PER_SIDE; + + 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->slave.slot_last = first_data_slot + num_slots - 1; + + return slot_zero; +} + +VCHIQ_STATUS_T +vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero, + int is_master) +{ + VCHIQ_SHARED_STATE_T *local; + VCHIQ_SHARED_STATE_T *remote; + VCHIQ_STATUS_T status; + char threadname[10]; + static int id; + int i; + + vchiq_log_warning(vchiq_core_log_level, + "%s: slot_zero = 0x%08lx, is_master = %d", + __func__, (unsigned long)slot_zero, is_master); + + /* Check the input configuration */ + + if (slot_zero->magic != VCHIQ_MAGIC) { + vchiq_loud_error_header(); + vchiq_loud_error("Invalid VCHIQ magic value found."); + vchiq_loud_error("slot_zero=%x: magic=%x (expected %x)", + (unsigned int)slot_zero, slot_zero->magic, VCHIQ_MAGIC); + vchiq_loud_error_footer(); + return VCHIQ_ERROR; + } + + if (slot_zero->version < VCHIQ_VERSION_MIN) { + vchiq_loud_error_header(); + vchiq_loud_error("Incompatible VCHIQ versions found."); + vchiq_loud_error("slot_zero=%x: VideoCore version=%d " + "(minimum %d)", + (unsigned int)slot_zero, slot_zero->version, + VCHIQ_VERSION_MIN); + vchiq_loud_error("Restart with a newer VideoCore image."); + vchiq_loud_error_footer(); + return VCHIQ_ERROR; + } + + if (VCHIQ_VERSION < slot_zero->version_min) { + vchiq_loud_error_header(); + vchiq_loud_error("Incompatible VCHIQ versions found."); + vchiq_loud_error("slot_zero=%x: version=%d (VideoCore " + "minimum %d)", + (unsigned int)slot_zero, VCHIQ_VERSION, + slot_zero->version_min); + vchiq_loud_error("Restart with a newer kernel."); + vchiq_loud_error_footer(); + return VCHIQ_ERROR; + } + + if ((slot_zero->slot_zero_size != sizeof(VCHIQ_SLOT_ZERO_T)) || + (slot_zero->slot_size != VCHIQ_SLOT_SIZE) || + (slot_zero->max_slots != VCHIQ_MAX_SLOTS) || + (slot_zero->max_slots_per_side != VCHIQ_MAX_SLOTS_PER_SIDE)) { + vchiq_loud_error_header(); + if (slot_zero->slot_zero_size != sizeof(VCHIQ_SLOT_ZERO_T)) + vchiq_loud_error("slot_zero=%x: slot_zero_size=%x " + "(expected %x)", + (unsigned int)slot_zero, + slot_zero->slot_zero_size, + sizeof(VCHIQ_SLOT_ZERO_T)); + if (slot_zero->slot_size != VCHIQ_SLOT_SIZE) + vchiq_loud_error("slot_zero=%x: slot_size=%d " + "(expected %d", + (unsigned int)slot_zero, slot_zero->slot_size, + VCHIQ_SLOT_SIZE); + if (slot_zero->max_slots != VCHIQ_MAX_SLOTS) + vchiq_loud_error("slot_zero=%x: max_slots=%d " + "(expected %d)", + (unsigned int)slot_zero, slot_zero->max_slots, + VCHIQ_MAX_SLOTS); + if (slot_zero->max_slots_per_side != VCHIQ_MAX_SLOTS_PER_SIDE) + vchiq_loud_error("slot_zero=%x: max_slots_per_side=%d " + "(expected %d)", + (unsigned int)slot_zero, + slot_zero->max_slots_per_side, + VCHIQ_MAX_SLOTS_PER_SIDE); + vchiq_loud_error_footer(); + return VCHIQ_ERROR; + } + + if (VCHIQ_VERSION < slot_zero->version) + slot_zero->version = VCHIQ_VERSION; + + if (is_master) { + local = &slot_zero->master; + remote = &slot_zero->slave; + } else { + local = &slot_zero->slave; + remote = &slot_zero->master; + } + + if (local->initialised) { + vchiq_loud_error_header(); + if (remote->initialised) + vchiq_loud_error("local state has already been " + "initialised"); + else + vchiq_loud_error("master/slave mismatch - two %ss", + is_master ? "master" : "slave"); + vchiq_loud_error_footer(); + return VCHIQ_ERROR; + } + + memset(state, 0, sizeof(VCHIQ_STATE_T)); + + state->id = id++; + state->is_master = is_master; + + /* + initialize shared state pointers + */ + + state->local = local; + state->remote = remote; + state->slot_data = (VCHIQ_SLOT_T *)slot_zero; + + /* + initialize events and mutexes + */ + + sema_init(&state->connect, 0); + mutex_init(&state->mutex); + sema_init(&state->trigger_event, 0); + sema_init(&state->recycle_event, 0); + sema_init(&state->sync_trigger_event, 0); + sema_init(&state->sync_release_event, 0); + + mutex_init(&state->slot_mutex); + mutex_init(&state->recycle_mutex); + mutex_init(&state->sync_mutex); + mutex_init(&state->bulk_transfer_mutex); + + sema_init(&state->slot_available_event, 0); + sema_init(&state->slot_remove_event, 0); + sema_init(&state->data_quota_event, 0); + + state->slot_queue_available = 0; + + for (i = 0; i < VCHIQ_MAX_SERVICES; i++) { + VCHIQ_SERVICE_QUOTA_T *service_quota = + &state->service_quotas[i]; + sema_init(&service_quota->quota_event, 0); + } + + for (i = local->slot_first; i <= local->slot_last; i++) { + local->slot_queue[state->slot_queue_available++] = i; + up(&state->slot_available_event); + } + + state->default_slot_quota = state->slot_queue_available/2; + state->default_message_quota = + min((unsigned short)(state->default_slot_quota * 256), + (unsigned short)~0); + + state->previous_data_index = -1; + state->data_use_count = 0; + state->data_quota = state->slot_queue_available - 1; + + local->trigger.event = &state->trigger_event; + remote_event_create(&local->trigger); + local->tx_pos = 0; + + local->recycle.event = &state->recycle_event; + remote_event_create(&local->recycle); + local->slot_queue_recycle = state->slot_queue_available; + + local->sync_trigger.event = &state->sync_trigger_event; + remote_event_create(&local->sync_trigger); + + local->sync_release.event = &state->sync_release_event; + remote_event_create(&local->sync_release); + + /* At start-of-day, the slot is empty and available */ + ((VCHIQ_HEADER_T *)SLOT_DATA_FROM_INDEX(state, local->slot_sync))->msgid + = VCHIQ_MSGID_PADDING; + remote_event_signal_local(&local->sync_release); + + local->debug[DEBUG_ENTRIES] = DEBUG_MAX; + + status = vchiq_platform_init_state(state); + + /* + bring up slot handler thread + */ + snprintf(threadname, sizeof(threadname), "VCHIQ-%d", state->id); + state->slot_handler_thread = kthread_create(&slot_handler_func, + (void *)state, + threadname); + + if (state->slot_handler_thread == NULL) { + vchiq_loud_error_header(); + vchiq_loud_error("couldn't create thread %s", threadname); + vchiq_loud_error_footer(); + return VCHIQ_ERROR; + } + set_user_nice(state->slot_handler_thread, -19); + wake_up_process(state->slot_handler_thread); + + snprintf(threadname, sizeof(threadname), "VCHIQr-%d", state->id); + state->recycle_thread = kthread_create(&recycle_func, + (void *)state, + threadname); + if (state->recycle_thread == NULL) { + vchiq_loud_error_header(); + vchiq_loud_error("couldn't create thread %s", threadname); + vchiq_loud_error_footer(); + return VCHIQ_ERROR; + } + set_user_nice(state->recycle_thread, -19); + wake_up_process(state->recycle_thread); + + snprintf(threadname, sizeof(threadname), "VCHIQs-%d", state->id); + state->sync_thread = kthread_create(&sync_func, + (void *)state, + threadname); + if (state->sync_thread == NULL) { + vchiq_loud_error_header(); + vchiq_loud_error("couldn't create thread %s", threadname); + vchiq_loud_error_footer(); + return VCHIQ_ERROR; + } + set_user_nice(state->sync_thread, -20); + wake_up_process(state->sync_thread); + + BUG_ON(state->id >= VCHIQ_MAX_STATES); + vchiq_states[state->id] = state; + + /* Indicate readiness to the other side */ + local->initialised = 1; + + return status; +} + +/* Called from application thread when a client or server service is created. */ +VCHIQ_SERVICE_T * +vchiq_add_service_internal(VCHIQ_STATE_T *state, + const VCHIQ_SERVICE_PARAMS_T *params, int srvstate, + VCHIQ_INSTANCE_T instance, VCHIQ_USERDATA_TERM_T userdata_term) +{ + VCHIQ_SERVICE_T *service; + + service = kmalloc(sizeof(VCHIQ_SERVICE_T), GFP_KERNEL); + if (service) { + service->base.fourcc = params->fourcc; + service->base.callback = params->callback; + service->base.userdata = params->userdata; + service->handle = VCHIQ_SERVICE_HANDLE_INVALID; + service->ref_count = 1; + service->srvstate = VCHIQ_SRVSTATE_FREE; + service->userdata_term = userdata_term; + service->localport = VCHIQ_PORT_FREE; + service->remoteport = VCHIQ_PORT_FREE; + + service->public_fourcc = (srvstate == VCHIQ_SRVSTATE_OPENING) ? + VCHIQ_FOURCC_INVALID : params->fourcc; + service->client_id = 0; + service->auto_close = 1; + service->sync = 0; + service->closing = 0; + service->trace = 0; + atomic_set(&service->poll_flags, 0); + service->version = params->version; + service->version_min = params->version_min; + service->state = state; + service->instance = instance; + service->service_use_count = 0; + init_bulk_queue(&service->bulk_tx); + init_bulk_queue(&service->bulk_rx); + sema_init(&service->remove_event, 0); + sema_init(&service->bulk_remove_event, 0); + mutex_init(&service->bulk_mutex); + memset(&service->stats, 0, sizeof(service->stats)); + } else { + vchiq_log_error(vchiq_core_log_level, + "Out of memory"); + } + + if (service) { + VCHIQ_SERVICE_T **pservice = NULL; + int i; + + /* Although it is perfectly possible to use service_spinlock + ** to protect the creation of services, it is overkill as it + ** disables interrupts while the array is searched. + ** The only danger is of another thread trying to create a + ** service - service deletion is safe. + ** Therefore it is preferable to use state->mutex which, + ** although slower to claim, doesn't block interrupts while + ** it is held. + */ + + mutex_lock(&state->mutex); + + /* Prepare to use a previously unused service */ + if (state->unused_service < VCHIQ_MAX_SERVICES) + pservice = &state->services[state->unused_service]; + + if (srvstate == VCHIQ_SRVSTATE_OPENING) { + for (i = 0; i < state->unused_service; i++) { + VCHIQ_SERVICE_T *srv = state->services[i]; + if (!srv) { + pservice = &state->services[i]; + break; + } + } + } else { + for (i = (state->unused_service - 1); i >= 0; i--) { + VCHIQ_SERVICE_T *srv = state->services[i]; + if (!srv) + pservice = &state->services[i]; + 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. */ + pservice = NULL; + break; + } + } + } + + if (pservice) { + service->localport = (pservice - state->services); + if (!handle_seq) + handle_seq = VCHIQ_MAX_STATES * + VCHIQ_MAX_SERVICES; + service->handle = handle_seq | + (state->id * VCHIQ_MAX_SERVICES) | + service->localport; + handle_seq += VCHIQ_MAX_STATES * VCHIQ_MAX_SERVICES; + *pservice = service; + if (pservice == &state->services[state->unused_service]) + state->unused_service++; + } + + mutex_unlock(&state->mutex); + + if (!pservice) { + kfree(service); + service = NULL; + } + } + + if (service) { + VCHIQ_SERVICE_QUOTA_T *service_quota = + &state->service_quotas[service->localport]; + service_quota->slot_quota = state->default_slot_quota; + service_quota->message_quota = state->default_message_quota; + if (service_quota->slot_use_count == 0) + service_quota->previous_tx_index = + SLOT_QUEUE_INDEX_FROM_POS(state->local_tx_pos) + - 1; + + /* Bring this service online */ + vchiq_set_service_state(service, srvstate); + + vchiq_log_info(vchiq_core_msg_log_level, + "%s Service %c%c%c%c SrcPort:%d", + (srvstate == VCHIQ_SRVSTATE_OPENING) + ? "Open" : "Add", + VCHIQ_FOURCC_AS_4CHARS(params->fourcc), + service->localport); + } + + /* Don't unlock the service - leave it with a ref_count of 1. */ + + return service; +} + +VCHIQ_STATUS_T +vchiq_open_service_internal(VCHIQ_SERVICE_T *service, int client_id) +{ + struct vchiq_open_payload payload = { + service->base.fourcc, + client_id, + service->version, + service->version_min + }; + VCHIQ_ELEMENT_T body = { &payload, sizeof(payload) }; + VCHIQ_STATUS_T status = VCHIQ_SUCCESS; + + 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), + &body, 1, sizeof(payload), QMFLAGS_IS_BLOCKING); + if (status == VCHIQ_SUCCESS) { + /* Wait for the ACK/NAK */ + if (down_interruptible(&service->remove_event) != 0) { + status = VCHIQ_RETRY; + vchiq_release_service_internal(service); + } else if ((service->srvstate != VCHIQ_SRVSTATE_OPEN) && + (service->srvstate != VCHIQ_SRVSTATE_OPENSYNC)) { + if (service->srvstate != VCHIQ_SRVSTATE_CLOSEWAIT) + vchiq_log_error(vchiq_core_log_level, + "%d: osi - srvstate = %s (ref %d)", + service->state->id, + srvstate_names[service->srvstate], + service->ref_count); + status = VCHIQ_ERROR; + VCHIQ_SERVICE_STATS_INC(service, error_count); + vchiq_release_service_internal(service); + } + } + return status; +} + +static void +release_service_messages(VCHIQ_SERVICE_T *service) +{ + VCHIQ_STATE_T *state = service->state; + int slot_last = state->remote->slot_last; + int i; + + /* Release any claimed messages aimed at this service */ + + if (service->sync) { + VCHIQ_HEADER_T *header = + (VCHIQ_HEADER_T *)SLOT_DATA_FROM_INDEX(state, + state->remote->slot_sync); + if (VCHIQ_MSG_DSTPORT(header->msgid) == service->localport) + release_message_sync(state, header); + + return; + } + + for (i = state->remote->slot_first; i <= slot_last; i++) { + VCHIQ_SLOT_INFO_T *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; + + 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) { + VCHIQ_HEADER_T *header = + (VCHIQ_HEADER_T *)(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 %x", + (unsigned int)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 %x, " + "msgid %x, header->msgid %x, " + "header->size %x", + pos, (unsigned int)header, + msgid, header->msgid, + header->size); + WARN(1, "invalid slot position\n"); + } + } + } + } +} + +static int +do_abort_bulks(VCHIQ_SERVICE_T *service) +{ + VCHIQ_STATUS_T status; + + /* Abort any outstanding bulk transfers */ + if (mutex_lock_interruptible(&service->bulk_mutex) != 0) + return 0; + abort_outstanding_bulks(service, &service->bulk_tx); + 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*/); + return (status == VCHIQ_SUCCESS); +} + +static VCHIQ_STATUS_T +close_service_complete(VCHIQ_SERVICE_T *service, int failstate) +{ + VCHIQ_STATUS_T status; + int is_server = (service->public_fourcc != VCHIQ_FOURCC_INVALID); + int newstate; + + switch (service->srvstate) { + case VCHIQ_SRVSTATE_OPEN: + case VCHIQ_SRVSTATE_CLOSESENT: + case VCHIQ_SRVSTATE_CLOSERECVD: + if (is_server) { + if (service->auto_close) { + service->client_id = 0; + service->remoteport = VCHIQ_PORT_FREE; + newstate = VCHIQ_SRVSTATE_LISTENING; + } else + newstate = VCHIQ_SRVSTATE_CLOSEWAIT; + } else + newstate = VCHIQ_SRVSTATE_CLOSED; + vchiq_set_service_state(service, newstate); + break; + case VCHIQ_SRVSTATE_LISTENING: + break; + default: + vchiq_log_error(vchiq_core_log_level, + "close_service_complete(%x) called in state %s", + service->handle, srvstate_names[service->srvstate]); + WARN(1, "close_service_complete in unexpected state\n"); + return VCHIQ_ERROR; + } + + status = make_service_callback(service, + VCHIQ_SERVICE_CLOSED, NULL, NULL); + + if (status != VCHIQ_RETRY) { + int uc = service->service_use_count; + int i; + /* Complete the close process */ + for (i = 0; i < uc; i++) + /* cater for cases where close is forced and the + ** client may not close all it's handles */ + vchiq_release_service_internal(service); + + service->client_id = 0; + service->remoteport = VCHIQ_PORT_FREE; + + if (service->srvstate == VCHIQ_SRVSTATE_CLOSED) + vchiq_free_service_internal(service); + else if (service->srvstate != VCHIQ_SRVSTATE_CLOSEWAIT) { + if (is_server) + service->closing = 0; + + up(&service->remove_event); + } + } else + vchiq_set_service_state(service, failstate); + + return status; +} + +/* Called by the slot handler */ +VCHIQ_STATUS_T +vchiq_close_service_internal(VCHIQ_SERVICE_T *service, int close_recvd) +{ + VCHIQ_STATE_T *state = service->state; + VCHIQ_STATUS_T status = VCHIQ_SUCCESS; + int is_server = (service->public_fourcc != VCHIQ_FOURCC_INVALID); + + vchiq_log_info(vchiq_core_log_level, "%d: csi:%d,%d (%s)", + service->state->id, service->localport, close_recvd, + srvstate_names[service->srvstate]); + + switch (service->srvstate) { + case VCHIQ_SRVSTATE_CLOSED: + case VCHIQ_SRVSTATE_HIDDEN: + case VCHIQ_SRVSTATE_LISTENING: + case VCHIQ_SRVSTATE_CLOSEWAIT: + if (close_recvd) + vchiq_log_error(vchiq_core_log_level, + "vchiq_close_service_internal(1) called " + "in state %s", + srvstate_names[service->srvstate]); + else if (is_server) { + if (service->srvstate == VCHIQ_SRVSTATE_LISTENING) { + status = VCHIQ_ERROR; + } else { + service->client_id = 0; + service->remoteport = VCHIQ_PORT_FREE; + if (service->srvstate == + VCHIQ_SRVSTATE_CLOSEWAIT) + vchiq_set_service_state(service, + VCHIQ_SRVSTATE_LISTENING); + } + up(&service->remove_event); + } else + vchiq_free_service_internal(service); + break; + case VCHIQ_SRVSTATE_OPENING: + if (close_recvd) { + /* The open was rejected - tell the user */ + vchiq_set_service_state(service, + VCHIQ_SRVSTATE_CLOSEWAIT); + up(&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)), + NULL, 0, 0, 0); + } + break; + + case VCHIQ_SRVSTATE_OPENSYNC: + mutex_lock(&state->sync_mutex); + /* Drop through */ + + case VCHIQ_SRVSTATE_OPEN: + if (state->is_master || close_recvd) { + if (!do_abort_bulks(service)) + status = VCHIQ_RETRY; + } + + 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)), + NULL, 0, 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); + break; + } else + break; + + /* Change the state while the mutex is still held */ + vchiq_set_service_state(service, VCHIQ_SRVSTATE_CLOSERECVD); + mutex_unlock(&state->slot_mutex); + if (service->sync) + mutex_unlock(&state->sync_mutex); + + status = close_service_complete(service, + VCHIQ_SRVSTATE_CLOSERECVD); + break; + + case VCHIQ_SRVSTATE_CLOSESENT: + if (!close_recvd) + /* This happens when a process is killed mid-close */ + break; + + if (!state->is_master) { + if (!do_abort_bulks(service)) { + status = VCHIQ_RETRY; + break; + } + } + + if (status == VCHIQ_SUCCESS) + status = close_service_complete(service, + VCHIQ_SRVSTATE_CLOSERECVD); + break; + + case VCHIQ_SRVSTATE_CLOSERECVD: + if (!close_recvd && is_server) + /* Force into LISTENING mode */ + vchiq_set_service_state(service, + VCHIQ_SRVSTATE_LISTENING); + status = close_service_complete(service, + VCHIQ_SRVSTATE_CLOSERECVD); + break; + + default: + vchiq_log_error(vchiq_core_log_level, + "vchiq_close_service_internal(%d) called in state %s", + close_recvd, srvstate_names[service->srvstate]); + break; + } + + return status; +} + +/* Called from the application process upon process death */ +void +vchiq_terminate_service_internal(VCHIQ_SERVICE_T *service) +{ + VCHIQ_STATE_T *state = service->state; + + vchiq_log_info(vchiq_core_log_level, "%d: tsi - (%d<->%d)", + state->id, service->localport, service->remoteport); + + mark_service_closing(service); + + /* Mark the service for removal by the slot handler */ + request_poll(state, service, VCHIQ_POLL_REMOVE); +} + +/* Called from the slot handler */ +void +vchiq_free_service_internal(VCHIQ_SERVICE_T *service) +{ + VCHIQ_STATE_T *state = service->state; + + vchiq_log_info(vchiq_core_log_level, "%d: fsi - (%d)", + state->id, service->localport); + + switch (service->srvstate) { + case VCHIQ_SRVSTATE_OPENING: + case VCHIQ_SRVSTATE_CLOSED: + case VCHIQ_SRVSTATE_HIDDEN: + case VCHIQ_SRVSTATE_LISTENING: + case VCHIQ_SRVSTATE_CLOSEWAIT: + break; + default: + vchiq_log_error(vchiq_core_log_level, + "%d: fsi - (%d) in state %s", + state->id, service->localport, + srvstate_names[service->srvstate]); + return; + } + + vchiq_set_service_state(service, VCHIQ_SRVSTATE_FREE); + + up(&service->remove_event); + + /* Release the initial lock */ + unlock_service(service); +} + +VCHIQ_STATUS_T +vchiq_connect_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance) +{ + VCHIQ_SERVICE_T *service; + int i; + + /* Find all services registered to this client and enable them. */ + i = 0; + while ((service = next_service_by_instance(state, instance, + &i)) != NULL) { + if (service->srvstate == VCHIQ_SRVSTATE_HIDDEN) + vchiq_set_service_state(service, + VCHIQ_SRVSTATE_LISTENING); + unlock_service(service); + } + + if (state->conn_state == VCHIQ_CONNSTATE_DISCONNECTED) { + if (queue_message(state, NULL, + VCHIQ_MAKE_MSG(VCHIQ_MSG_CONNECT, 0, 0), NULL, 0, + 0, QMFLAGS_IS_BLOCKING) == VCHIQ_RETRY) + return VCHIQ_RETRY; + + vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTING); + } + + if (state->conn_state == VCHIQ_CONNSTATE_CONNECTING) { + if (down_interruptible(&state->connect) != 0) + return VCHIQ_RETRY; + + vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED); + up(&state->connect); + } + + return VCHIQ_SUCCESS; +} + +VCHIQ_STATUS_T +vchiq_shutdown_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance) +{ + VCHIQ_SERVICE_T *service; + int i; + + /* Find all services registered to this client and enable them. */ + i = 0; + while ((service = next_service_by_instance(state, instance, + &i)) != NULL) { + (void)vchiq_remove_service(service->handle); + unlock_service(service); + } + + return VCHIQ_SUCCESS; +} + +VCHIQ_STATUS_T +vchiq_pause_internal(VCHIQ_STATE_T *state) +{ + VCHIQ_STATUS_T status = VCHIQ_SUCCESS; + + switch (state->conn_state) { + case VCHIQ_CONNSTATE_CONNECTED: + /* Request a pause */ + vchiq_set_conn_state(state, VCHIQ_CONNSTATE_PAUSING); + request_poll(state, NULL, 0); + break; + default: + vchiq_log_error(vchiq_core_log_level, + "vchiq_pause_internal in state %s\n", + conn_state_names[state->conn_state]); + status = VCHIQ_ERROR; + VCHIQ_STATS_INC(state, error_count); + break; + } + + return status; +} + +VCHIQ_STATUS_T +vchiq_resume_internal(VCHIQ_STATE_T *state) +{ + VCHIQ_STATUS_T status = VCHIQ_SUCCESS; + + if (state->conn_state == VCHIQ_CONNSTATE_PAUSED) { + vchiq_set_conn_state(state, VCHIQ_CONNSTATE_RESUMING); + request_poll(state, NULL, 0); + } else { + status = VCHIQ_ERROR; + VCHIQ_STATS_INC(state, error_count); + } + + return status; +} + +VCHIQ_STATUS_T +vchiq_close_service(VCHIQ_SERVICE_HANDLE_T handle) +{ + /* Unregister the service */ + VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + VCHIQ_STATUS_T status = VCHIQ_SUCCESS; + + if (!service) + return VCHIQ_ERROR; + + vchiq_log_info(vchiq_core_log_level, + "%d: close_service:%d", + service->state->id, service->localport); + + if ((service->srvstate == VCHIQ_SRVSTATE_FREE) || + (service->srvstate == VCHIQ_SRVSTATE_LISTENING) || + (service->srvstate == VCHIQ_SRVSTATE_HIDDEN)) { + unlock_service(service); + return VCHIQ_ERROR; + } + + mark_service_closing(service); + + if (current == service->state->slot_handler_thread) { + status = vchiq_close_service_internal(service, + 0/*!close_recvd*/); + BUG_ON(status == VCHIQ_RETRY); + } else { + /* Mark the service for termination by the slot handler */ + request_poll(service->state, service, VCHIQ_POLL_TERMINATE); + } + + while (1) { + if (down_interruptible(&service->remove_event) != 0) { + status = VCHIQ_RETRY; + break; + } + + if ((service->srvstate == VCHIQ_SRVSTATE_FREE) || + (service->srvstate == VCHIQ_SRVSTATE_LISTENING) || + (service->srvstate == VCHIQ_SRVSTATE_OPEN)) + break; + + vchiq_log_warning(vchiq_core_log_level, + "%d: close_service:%d - waiting in state %s", + service->state->id, service->localport, + srvstate_names[service->srvstate]); + } + + if ((status == VCHIQ_SUCCESS) && + (service->srvstate != VCHIQ_SRVSTATE_FREE) && + (service->srvstate != VCHIQ_SRVSTATE_LISTENING)) + status = VCHIQ_ERROR; + + unlock_service(service); + + return status; +} + +VCHIQ_STATUS_T +vchiq_remove_service(VCHIQ_SERVICE_HANDLE_T handle) +{ + /* Unregister the service */ + VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + VCHIQ_STATUS_T status = VCHIQ_SUCCESS; + + if (!service) + return VCHIQ_ERROR; + + vchiq_log_info(vchiq_core_log_level, + "%d: remove_service:%d", + service->state->id, service->localport); + + if (service->srvstate == VCHIQ_SRVSTATE_FREE) { + unlock_service(service); + return VCHIQ_ERROR; + } + + mark_service_closing(service); + + if ((service->srvstate == VCHIQ_SRVSTATE_HIDDEN) || + (current == service->state->slot_handler_thread)) { + /* Make it look like a client, because it must be removed and + not left in the LISTENING state. */ + service->public_fourcc = VCHIQ_FOURCC_INVALID; + + status = vchiq_close_service_internal(service, + 0/*!close_recvd*/); + BUG_ON(status == VCHIQ_RETRY); + } else { + /* Mark the service for removal by the slot handler */ + request_poll(service->state, service, VCHIQ_POLL_REMOVE); + } + while (1) { + if (down_interruptible(&service->remove_event) != 0) { + status = VCHIQ_RETRY; + break; + } + + if ((service->srvstate == VCHIQ_SRVSTATE_FREE) || + (service->srvstate == VCHIQ_SRVSTATE_OPEN)) + break; + + vchiq_log_warning(vchiq_core_log_level, + "%d: remove_service:%d - waiting in state %s", + service->state->id, service->localport, + srvstate_names[service->srvstate]); + } + + if ((status == VCHIQ_SUCCESS) && + (service->srvstate != VCHIQ_SRVSTATE_FREE)) + status = VCHIQ_ERROR; + + unlock_service(service); + + return status; +} + + +/* This function may be called by kernel threads or user threads. + * User threads may receive VCHIQ_RETRY to indicate that a signal has been + * received and the call should be retried after being returned to user + * context. + * When called in blocking mode, the userdata field points to a bulk_waiter + * structure. + */ +VCHIQ_STATUS_T +vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, + VCHI_MEM_HANDLE_T memhandle, void *offset, int size, void *userdata, + VCHIQ_BULK_MODE_T mode, VCHIQ_BULK_DIR_T dir) +{ + VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + VCHIQ_BULK_QUEUE_T *queue; + VCHIQ_BULK_T *bulk; + VCHIQ_STATE_T *state; + struct bulk_waiter *bulk_waiter = NULL; + const char dir_char = (dir == VCHIQ_BULK_TRANSMIT) ? 't' : 'r'; + const int dir_msgtype = (dir == VCHIQ_BULK_TRANSMIT) ? + VCHIQ_MSG_BULK_TX : VCHIQ_MSG_BULK_RX; + VCHIQ_STATUS_T status = VCHIQ_ERROR; + + if (!service || + (service->srvstate != VCHIQ_SRVSTATE_OPEN) || + ((memhandle == VCHI_MEM_HANDLE_INVALID) && (offset == NULL)) || + (vchiq_check_service(service) != VCHIQ_SUCCESS)) + goto error_exit; + + switch (mode) { + case VCHIQ_BULK_MODE_NOCALLBACK: + case VCHIQ_BULK_MODE_CALLBACK: + break; + case VCHIQ_BULK_MODE_BLOCKING: + bulk_waiter = (struct bulk_waiter *)userdata; + sema_init(&bulk_waiter->event, 0); + bulk_waiter->actual = 0; + bulk_waiter->bulk = NULL; + break; + case VCHIQ_BULK_MODE_WAITING: + bulk_waiter = (struct bulk_waiter *)userdata; + bulk = bulk_waiter->bulk; + goto waiting; + default: + goto error_exit; + } + + state = service->state; + + queue = (dir == VCHIQ_BULK_TRANSMIT) ? + &service->bulk_tx : &service->bulk_rx; + + if (mutex_lock_interruptible(&service->bulk_mutex) != 0) { + status = VCHIQ_RETRY; + goto error_exit; + } + + if (queue->local_insert == queue->remove + VCHIQ_NUM_SERVICE_BULKS) { + VCHIQ_SERVICE_STATS_INC(service, bulk_stalls); + do { + mutex_unlock(&service->bulk_mutex); + if (down_interruptible(&service->bulk_remove_event) + != 0) { + status = VCHIQ_RETRY; + goto error_exit; + } + if (mutex_lock_interruptible(&service->bulk_mutex) + != 0) { + status = VCHIQ_RETRY; + goto error_exit; + } + } while (queue->local_insert == queue->remove + + VCHIQ_NUM_SERVICE_BULKS); + } + + bulk = &queue->bulks[BULK_INDEX(queue->local_insert)]; + + bulk->mode = mode; + bulk->dir = dir; + bulk->userdata = userdata; + bulk->size = size; + bulk->actual = VCHIQ_BULK_ACTUAL_ABORTED; + + if (vchiq_prepare_bulk_data(bulk, memhandle, offset, size, dir) != + VCHIQ_SUCCESS) + goto unlock_error_exit; + + wmb(); + + vchiq_log_info(vchiq_core_log_level, + "%d: bt (%d->%d) %cx %x@%x %x", + state->id, + service->localport, service->remoteport, dir_char, + size, (unsigned int)bulk->data, (unsigned int)userdata); + + /* The slot mutex must be held when the service is being closed, so + claim it here to ensure that isn't happening */ + if (mutex_lock_interruptible(&state->slot_mutex) != 0) { + status = VCHIQ_RETRY; + goto cancel_bulk_error_exit; + } + + if (service->srvstate != VCHIQ_SRVSTATE_OPEN) + goto unlock_both_error_exit; + + if (state->is_master) { + queue->local_insert++; + if (resolve_bulks(service, queue)) + request_poll(state, service, + (dir == VCHIQ_BULK_TRANSMIT) ? + VCHIQ_POLL_TXNOTIFY : VCHIQ_POLL_RXNOTIFY); + } else { + int payload[2] = { (int)bulk->data, bulk->size }; + VCHIQ_ELEMENT_T element = { payload, sizeof(payload) }; + + status = queue_message(state, NULL, + VCHIQ_MAKE_MSG(dir_msgtype, + service->localport, service->remoteport), + &element, 1, sizeof(payload), + QMFLAGS_IS_BLOCKING | + QMFLAGS_NO_MUTEX_LOCK | + QMFLAGS_NO_MUTEX_UNLOCK); + if (status != VCHIQ_SUCCESS) { + goto unlock_both_error_exit; + } + queue->local_insert++; + } + + mutex_unlock(&state->slot_mutex); + mutex_unlock(&service->bulk_mutex); + + vchiq_log_trace(vchiq_core_log_level, + "%d: bt:%d %cx li=%x ri=%x p=%x", + state->id, + service->localport, dir_char, + queue->local_insert, queue->remote_insert, queue->process); + +waiting: + unlock_service(service); + + status = VCHIQ_SUCCESS; + + if (bulk_waiter) { + bulk_waiter->bulk = bulk; + if (down_interruptible(&bulk_waiter->event) != 0) + status = VCHIQ_RETRY; + else if (bulk_waiter->actual == VCHIQ_BULK_ACTUAL_ABORTED) + status = VCHIQ_ERROR; + } + + return status; + +unlock_both_error_exit: + mutex_unlock(&state->slot_mutex); +cancel_bulk_error_exit: + vchiq_complete_bulk(bulk); +unlock_error_exit: + mutex_unlock(&service->bulk_mutex); + +error_exit: + if (service) + unlock_service(service); + return status; +} + +VCHIQ_STATUS_T +vchiq_queue_message(VCHIQ_SERVICE_HANDLE_T handle, + const VCHIQ_ELEMENT_T *elements, unsigned int count) +{ + VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + VCHIQ_STATUS_T status = VCHIQ_ERROR; + + unsigned int size = 0; + unsigned int i; + + if (!service || + (vchiq_check_service(service) != VCHIQ_SUCCESS)) + goto error_exit; + + for (i = 0; i < (unsigned int)count; i++) { + if (elements[i].size) { + if (elements[i].data == NULL) { + VCHIQ_SERVICE_STATS_INC(service, error_count); + goto error_exit; + } + size += elements[i].size; + } + } + + if (size > VCHIQ_MAX_MSG_SIZE) { + VCHIQ_SERVICE_STATS_INC(service, error_count); + goto error_exit; + } + + switch (service->srvstate) { + case VCHIQ_SRVSTATE_OPEN: + status = queue_message(service->state, service, + VCHIQ_MAKE_MSG(VCHIQ_MSG_DATA, + service->localport, + service->remoteport), + elements, count, size, 1); + break; + case VCHIQ_SRVSTATE_OPENSYNC: + status = queue_message_sync(service->state, service, + VCHIQ_MAKE_MSG(VCHIQ_MSG_DATA, + service->localport, + service->remoteport), + elements, count, size, 1); + break; + default: + status = VCHIQ_ERROR; + break; + } + +error_exit: + if (service) + unlock_service(service); + + return status; +} + +void +vchiq_release_message(VCHIQ_SERVICE_HANDLE_T handle, VCHIQ_HEADER_T *header) +{ + VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + VCHIQ_SHARED_STATE_T *remote; + VCHIQ_STATE_T *state; + int slot_index; + + if (!service) + return; + + state = service->state; + remote = state->remote; + + slot_index = SLOT_INDEX_FROM_DATA(state, (void *)header); + + if ((slot_index >= remote->slot_first) && + (slot_index <= remote->slot_last)) { + int msgid = header->msgid; + if (msgid & VCHIQ_MSGID_CLAIMED) { + VCHIQ_SLOT_INFO_T *slot_info = + SLOT_INFO_FROM_INDEX(state, slot_index); + + release_slot(state, slot_info, header, service); + } + } else if (slot_index == remote->slot_sync) + release_message_sync(state, header); + + unlock_service(service); +} + +static void +release_message_sync(VCHIQ_STATE_T *state, VCHIQ_HEADER_T *header) +{ + header->msgid = VCHIQ_MSGID_PADDING; + wmb(); + remote_event_signal(&state->remote->sync_release); +} + +VCHIQ_STATUS_T +vchiq_get_peer_version(VCHIQ_SERVICE_HANDLE_T handle, short *peer_version) +{ + VCHIQ_STATUS_T status = VCHIQ_ERROR; + VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + + if (!service || + (vchiq_check_service(service) != VCHIQ_SUCCESS) || + !peer_version) + goto exit; + *peer_version = service->peer_version; + status = VCHIQ_SUCCESS; + +exit: + if (service) + unlock_service(service); + return status; +} + +VCHIQ_STATUS_T +vchiq_get_config(VCHIQ_INSTANCE_T instance, + int config_size, VCHIQ_CONFIG_T *pconfig) +{ + VCHIQ_CONFIG_T config; + + (void)instance; + + config.max_msg_size = VCHIQ_MAX_MSG_SIZE; + config.bulk_threshold = VCHIQ_MAX_MSG_SIZE; + config.max_outstanding_bulks = VCHIQ_NUM_SERVICE_BULKS; + config.max_services = VCHIQ_MAX_SERVICES; + config.version = VCHIQ_VERSION; + config.version_min = VCHIQ_VERSION_MIN; + + if (config_size > sizeof(VCHIQ_CONFIG_T)) + return VCHIQ_ERROR; + + memcpy(pconfig, &config, + min(config_size, (int)(sizeof(VCHIQ_CONFIG_T)))); + + return VCHIQ_SUCCESS; +} + +VCHIQ_STATUS_T +vchiq_set_service_option(VCHIQ_SERVICE_HANDLE_T handle, + VCHIQ_SERVICE_OPTION_T option, int value) +{ + VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + VCHIQ_STATUS_T status = VCHIQ_ERROR; + + if (service) { + switch (option) { + case VCHIQ_SERVICE_OPTION_AUTOCLOSE: + service->auto_close = value; + status = VCHIQ_SUCCESS; + break; + + case VCHIQ_SERVICE_OPTION_SLOT_QUOTA: { + VCHIQ_SERVICE_QUOTA_T *service_quota = + &service->state->service_quotas[ + service->localport]; + if (value == 0) + value = service->state->default_slot_quota; + if ((value >= service_quota->slot_use_count) && + (value < (unsigned short)~0)) { + service_quota->slot_quota = value; + if ((value >= service_quota->slot_use_count) && + (service_quota->message_quota >= + service_quota->message_use_count)) { + /* Signal the service that it may have + ** dropped below its quota */ + up(&service_quota->quota_event); + } + status = VCHIQ_SUCCESS; + } + } break; + + case VCHIQ_SERVICE_OPTION_MESSAGE_QUOTA: { + VCHIQ_SERVICE_QUOTA_T *service_quota = + &service->state->service_quotas[ + service->localport]; + if (value == 0) + value = service->state->default_message_quota; + if ((value >= service_quota->message_use_count) && + (value < (unsigned short)~0)) { + service_quota->message_quota = value; + if ((value >= + service_quota->message_use_count) && + (service_quota->slot_quota >= + service_quota->slot_use_count)) + /* Signal the service that it may have + ** dropped below its quota */ + up(&service_quota->quota_event); + status = VCHIQ_SUCCESS; + } + } break; + + case VCHIQ_SERVICE_OPTION_SYNCHRONOUS: + if ((service->srvstate == VCHIQ_SRVSTATE_HIDDEN) || + (service->srvstate == + VCHIQ_SRVSTATE_LISTENING)) { + service->sync = value; + status = VCHIQ_SUCCESS; + } + break; + + case VCHIQ_SERVICE_OPTION_TRACE: + service->trace = value; + status = VCHIQ_SUCCESS; + break; + + default: + break; + } + unlock_service(service); + } + + return status; +} + +void +vchiq_dump_shared_state(void *dump_context, VCHIQ_STATE_T *state, + VCHIQ_SHARED_STATE_T *shared, const char *label) +{ + static const char *const debug_names[] = { + "<entries>", + "SLOT_HANDLER_COUNT", + "SLOT_HANDLER_LINE", + "PARSE_LINE", + "PARSE_HEADER", + "PARSE_MSGID", + "AWAIT_COMPLETION_LINE", + "DEQUEUE_MESSAGE_LINE", + "SERVICE_CALLBACK_LINE", + "MSG_QUEUE_FULL_COUNT", + "COMPLETION_QUEUE_FULL_COUNT" + }; + int i; + + char buf[80]; + int len; + len = snprintf(buf, sizeof(buf), + " %s: slots %d-%d tx_pos=%x recycle=%x", + label, shared->slot_first, shared->slot_last, + shared->tx_pos, shared->slot_queue_recycle); + vchiq_dump(dump_context, buf, len + 1); + + len = snprintf(buf, sizeof(buf), + " Slots claimed:"); + vchiq_dump(dump_context, buf, len + 1); + + for (i = shared->slot_first; i <= shared->slot_last; i++) { + VCHIQ_SLOT_INFO_T slot_info = *SLOT_INFO_FROM_INDEX(state, i); + if (slot_info.use_count != slot_info.release_count) { + len = snprintf(buf, sizeof(buf), + " %d: %d/%d", i, slot_info.use_count, + slot_info.release_count); + vchiq_dump(dump_context, buf, len + 1); + } + } + + for (i = 1; i < shared->debug[DEBUG_ENTRIES]; i++) { + len = snprintf(buf, sizeof(buf), " DEBUG: %s = %d(%x)", + debug_names[i], shared->debug[i], shared->debug[i]); + vchiq_dump(dump_context, buf, len + 1); + } +} + +void +vchiq_dump_state(void *dump_context, VCHIQ_STATE_T *state) +{ + char buf[80]; + int len; + int i; + + len = snprintf(buf, sizeof(buf), "State %d: %s", state->id, + conn_state_names[state->conn_state]); + vchiq_dump(dump_context, buf, len + 1); + + len = snprintf(buf, sizeof(buf), + " tx_pos=%x(@%x), rx_pos=%x(@%x)", + state->local->tx_pos, + (uint32_t)state->tx_data + + (state->local_tx_pos & VCHIQ_SLOT_MASK), + state->rx_pos, + (uint32_t)state->rx_data + + (state->rx_pos & VCHIQ_SLOT_MASK)); + vchiq_dump(dump_context, buf, len + 1); + + len = snprintf(buf, sizeof(buf), + " Version: %d (min %d)", + VCHIQ_VERSION, VCHIQ_VERSION_MIN); + vchiq_dump(dump_context, buf, len + 1); + + if (VCHIQ_ENABLE_STATS) { + len = snprintf(buf, sizeof(buf), + " Stats: ctrl_tx_count=%d, ctrl_rx_count=%d, " + "error_count=%d", + state->stats.ctrl_tx_count, state->stats.ctrl_rx_count, + state->stats.error_count); + vchiq_dump(dump_context, buf, len + 1); + } + + len = snprintf(buf, sizeof(buf), + " Slots: %d available (%d data), %d recyclable, %d stalls " + "(%d data)", + ((state->slot_queue_available * VCHIQ_SLOT_SIZE) - + state->local_tx_pos) / VCHIQ_SLOT_SIZE, + state->data_quota - state->data_use_count, + state->local->slot_queue_recycle - state->slot_queue_available, + state->stats.slot_stalls, state->stats.data_stalls); + vchiq_dump(dump_context, buf, len + 1); + + vchiq_dump_platform_state(dump_context); + + vchiq_dump_shared_state(dump_context, state, state->local, "Local"); + vchiq_dump_shared_state(dump_context, state, state->remote, "Remote"); + + vchiq_dump_platform_instances(dump_context); + + for (i = 0; i < state->unused_service; i++) { + VCHIQ_SERVICE_T *service = find_service_by_port(state, i); + + if (service) { + vchiq_dump_service_state(dump_context, service); + unlock_service(service); + } + } +} + +void +vchiq_dump_service_state(void *dump_context, VCHIQ_SERVICE_T *service) +{ + char buf[80]; + int len; + + len = snprintf(buf, sizeof(buf), "Service %d: %s (ref %u)", + service->localport, srvstate_names[service->srvstate], + service->ref_count - 1); /*Don't include the lock just taken*/ + + if (service->srvstate != VCHIQ_SRVSTATE_FREE) { + char remoteport[30]; + VCHIQ_SERVICE_QUOTA_T *service_quota = + &service->state->service_quotas[service->localport]; + int fourcc = service->base.fourcc; + int tx_pending, rx_pending; + if (service->remoteport != VCHIQ_PORT_FREE) { + int len2 = snprintf(remoteport, sizeof(remoteport), + "%d", service->remoteport); + if (service->public_fourcc != VCHIQ_FOURCC_INVALID) + snprintf(remoteport + len2, + sizeof(remoteport) - len2, + " (client %x)", service->client_id); + } else + strcpy(remoteport, "n/a"); + + len += snprintf(buf + len, sizeof(buf) - len, + " '%c%c%c%c' remote %s (msg use %d/%d, slot use %d/%d)", + VCHIQ_FOURCC_AS_4CHARS(fourcc), + remoteport, + service_quota->message_use_count, + service_quota->message_quota, + service_quota->slot_use_count, + service_quota->slot_quota); + + vchiq_dump(dump_context, buf, len + 1); + + tx_pending = service->bulk_tx.local_insert - + service->bulk_tx.remote_insert; + + rx_pending = service->bulk_rx.local_insert - + service->bulk_rx.remote_insert; + + len = snprintf(buf, sizeof(buf), + " Bulk: tx_pending=%d (size %d)," + " rx_pending=%d (size %d)", + tx_pending, + tx_pending ? service->bulk_tx.bulks[ + BULK_INDEX(service->bulk_tx.remove)].size : 0, + rx_pending, + rx_pending ? service->bulk_rx.bulks[ + BULK_INDEX(service->bulk_rx.remove)].size : 0); + + if (VCHIQ_ENABLE_STATS) { + vchiq_dump(dump_context, buf, len + 1); + + len = snprintf(buf, sizeof(buf), + " Ctrl: tx_count=%d, tx_bytes=%llu, " + "rx_count=%d, rx_bytes=%llu", + service->stats.ctrl_tx_count, + service->stats.ctrl_tx_bytes, + service->stats.ctrl_rx_count, + service->stats.ctrl_rx_bytes); + vchiq_dump(dump_context, buf, len + 1); + + len = snprintf(buf, sizeof(buf), + " Bulk: tx_count=%d, tx_bytes=%llu, " + "rx_count=%d, rx_bytes=%llu", + service->stats.bulk_tx_count, + service->stats.bulk_tx_bytes, + service->stats.bulk_rx_count, + service->stats.bulk_rx_bytes); + vchiq_dump(dump_context, buf, len + 1); + + len = snprintf(buf, sizeof(buf), + " %d quota stalls, %d slot stalls, " + "%d bulk stalls, %d aborted, %d errors", + service->stats.quota_stalls, + service->stats.slot_stalls, + service->stats.bulk_stalls, + service->stats.bulk_aborted_count, + service->stats.error_count); + } + } + + vchiq_dump(dump_context, buf, len + 1); + + if (service->srvstate != VCHIQ_SRVSTATE_FREE) + vchiq_dump_platform_service_state(dump_context, service); +} + + +void +vchiq_loud_error_header(void) +{ + vchiq_log_error(vchiq_core_log_level, + "============================================================" + "================"); + vchiq_log_error(vchiq_core_log_level, + "============================================================" + "================"); + vchiq_log_error(vchiq_core_log_level, "====="); +} + +void +vchiq_loud_error_footer(void) +{ + vchiq_log_error(vchiq_core_log_level, "====="); + vchiq_log_error(vchiq_core_log_level, + "============================================================" + "================"); + vchiq_log_error(vchiq_core_log_level, + "============================================================" + "================"); +} + + +VCHIQ_STATUS_T vchiq_send_remote_use(VCHIQ_STATE_T *state) +{ + VCHIQ_STATUS_T status = VCHIQ_RETRY; + if (state->conn_state != VCHIQ_CONNSTATE_DISCONNECTED) + status = queue_message(state, NULL, + VCHIQ_MAKE_MSG(VCHIQ_MSG_REMOTE_USE, 0, 0), + NULL, 0, 0, 0); + return status; +} + +VCHIQ_STATUS_T vchiq_send_remote_release(VCHIQ_STATE_T *state) +{ + VCHIQ_STATUS_T status = VCHIQ_RETRY; + if (state->conn_state != VCHIQ_CONNSTATE_DISCONNECTED) + status = queue_message(state, NULL, + VCHIQ_MAKE_MSG(VCHIQ_MSG_REMOTE_RELEASE, 0, 0), + NULL, 0, 0, 0); + return status; +} + +VCHIQ_STATUS_T vchiq_send_remote_use_active(VCHIQ_STATE_T *state) +{ + VCHIQ_STATUS_T status = VCHIQ_RETRY; + if (state->conn_state != VCHIQ_CONNSTATE_DISCONNECTED) + status = queue_message(state, NULL, + VCHIQ_MAKE_MSG(VCHIQ_MSG_REMOTE_USE_ACTIVE, 0, 0), + NULL, 0, 0, 0); + return status; +} + +void vchiq_log_dump_mem(const char *label, uint32_t addr, const void *voidMem, + size_t numBytes) +{ + const uint8_t *mem = (const uint8_t *)voidMem; + size_t offset; + char lineBuf[100]; + char *s; + + while (numBytes > 0) { + s = lineBuf; + + for (offset = 0; offset < 16; offset++) { + if (offset < numBytes) + s += snprintf(s, 4, "%02x ", mem[offset]); + else + s += snprintf(s, 4, " "); + } + + for (offset = 0; offset < 16; offset++) { + if (offset < numBytes) { + uint8_t ch = mem[offset]; + + if ((ch < ' ') || (ch > '~')) + ch = '.'; + *s++ = (char)ch; + } + } + *s++ = '\0'; + + if ((label != NULL) && (*label != '\0')) + vchiq_log_trace(VCHIQ_LOG_TRACE, + "%s: %08x: %s", label, addr, lineBuf); + else + vchiq_log_trace(VCHIQ_LOG_TRACE, + "%08x: %s", addr, lineBuf); + + addr += 16; + mem += 16; + if (numBytes > 16) + numBytes -= 16; + else + numBytes = 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 new file mode 100644 index 0000000..9be484c --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h @@ -0,0 +1,712 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHIQ_CORE_H +#define VCHIQ_CORE_H + +#include <linux/mutex.h> +#include <linux/semaphore.h> +#include <linux/kthread.h> + +#include "vchiq_cfg.h" + +#include "vchiq.h" + +/* Run time control of log level, based on KERN_XXX level. */ +#define VCHIQ_LOG_DEFAULT 4 +#define VCHIQ_LOG_ERROR 3 +#define VCHIQ_LOG_WARNING 4 +#define VCHIQ_LOG_INFO 6 +#define VCHIQ_LOG_TRACE 7 + +#define VCHIQ_LOG_PREFIX KERN_INFO "vchiq: " + +#ifndef vchiq_log_error +#define vchiq_log_error(cat, fmt, ...) \ + do { if (cat >= VCHIQ_LOG_ERROR) \ + printk(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0) +#endif +#ifndef vchiq_log_warning +#define vchiq_log_warning(cat, fmt, ...) \ + do { if (cat >= VCHIQ_LOG_WARNING) \ + printk(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0) +#endif +#ifndef vchiq_log_info +#define vchiq_log_info(cat, fmt, ...) \ + do { if (cat >= VCHIQ_LOG_INFO) \ + printk(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0) +#endif +#ifndef vchiq_log_trace +#define vchiq_log_trace(cat, fmt, ...) \ + do { if (cat >= VCHIQ_LOG_TRACE) \ + printk(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0) +#endif + +#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 ((sizeof(VCHIQ_SLOT_ZERO_T) + \ + VCHIQ_SLOT_SIZE - 1) / 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); + +#define BITSET_SIZE(b) ((b + 31) >> 5) +#define BITSET_WORD(b) (b >> 5) +#define BITSET_BIT(b) (1 << (b & 31)) +#define BITSET_ZERO(bs) memset(bs, 0, sizeof(bs)) +#define BITSET_IS_SET(bs, b) (bs[BITSET_WORD(b)] & BITSET_BIT(b)) +#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 + DEBUG_SLOT_HANDLER_COUNT, + DEBUG_SLOT_HANDLER_LINE, + DEBUG_PARSE_LINE, + DEBUG_PARSE_HEADER, + DEBUG_PARSE_MSGID, + DEBUG_AWAIT_COMPLETION_LINE, + DEBUG_DEQUEUE_MESSAGE_LINE, + DEBUG_SERVICE_CALLBACK_LINE, + DEBUG_MSG_QUEUE_FULL_COUNT, + DEBUG_COMPLETION_QUEUE_FULL_COUNT, +#endif + DEBUG_MAX +}; + +#if VCHIQ_ENABLE_DEBUG + +#define DEBUG_INITIALISE(local) int *debug_ptr = (local)->debug; +#define DEBUG_TRACE(d) \ + do { debug_ptr[DEBUG_ ## d] = __LINE__; dsb(); } while (0) +#define DEBUG_VALUE(d, v) \ + do { debug_ptr[DEBUG_ ## d] = (v); dsb(); } while (0) +#define DEBUG_COUNT(d) \ + do { debug_ptr[DEBUG_ ## d]++; dsb(); } while (0) + +#else /* VCHIQ_ENABLE_DEBUG */ + +#define DEBUG_INITIALISE(local) +#define DEBUG_TRACE(d) +#define DEBUG_VALUE(d, v) +#define DEBUG_COUNT(d) + +#endif /* VCHIQ_ENABLE_DEBUG */ + +typedef enum { + VCHIQ_CONNSTATE_DISCONNECTED, + VCHIQ_CONNSTATE_CONNECTING, + VCHIQ_CONNSTATE_CONNECTED, + VCHIQ_CONNSTATE_PAUSING, + VCHIQ_CONNSTATE_PAUSE_SENT, + VCHIQ_CONNSTATE_PAUSED, + VCHIQ_CONNSTATE_RESUMING, + VCHIQ_CONNSTATE_PAUSE_TIMEOUT, + VCHIQ_CONNSTATE_RESUME_TIMEOUT +} VCHIQ_CONNSTATE_T; + +enum { + VCHIQ_SRVSTATE_FREE, + VCHIQ_SRVSTATE_HIDDEN, + VCHIQ_SRVSTATE_LISTENING, + VCHIQ_SRVSTATE_OPENING, + VCHIQ_SRVSTATE_OPEN, + VCHIQ_SRVSTATE_OPENSYNC, + VCHIQ_SRVSTATE_CLOSESENT, + VCHIQ_SRVSTATE_CLOSERECVD, + VCHIQ_SRVSTATE_CLOSEWAIT, + VCHIQ_SRVSTATE_CLOSED +}; + +enum { + VCHIQ_POLL_TERMINATE, + VCHIQ_POLL_REMOVE, + VCHIQ_POLL_TXNOTIFY, + VCHIQ_POLL_RXNOTIFY, + VCHIQ_POLL_COUNT +}; + +typedef enum { + VCHIQ_BULK_TRANSMIT, + VCHIQ_BULK_RECEIVE +} VCHIQ_BULK_DIR_T; + +typedef void (*VCHIQ_USERDATA_TERM_T)(void *userdata); + +typedef struct vchiq_bulk_struct { + short mode; + short dir; + void *userdata; + VCHI_MEM_HANDLE_T handle; + void *data; + int size; + void *remote_data; + int remote_size; + int actual; +} VCHIQ_BULK_T; + +typedef struct vchiq_bulk_queue_struct { + int local_insert; /* Where to insert the next local bulk */ + int remote_insert; /* Where to insert the next remote bulk (master) */ + int process; /* Bulk to transfer next */ + int remote_notify; /* Bulk to notify the remote client of next (mstr) */ + int remove; /* Bulk to notify the local client of, and remove, + ** next */ + VCHIQ_BULK_T bulks[VCHIQ_NUM_SERVICE_BULKS]; +} VCHIQ_BULK_QUEUE_T; + +typedef struct remote_event_struct { + int armed; + int fired; + struct semaphore *event; +} REMOTE_EVENT_T; + +typedef struct opaque_platform_state_t *VCHIQ_PLATFORM_STATE_T; + +typedef struct vchiq_state_struct VCHIQ_STATE_T; + +typedef struct vchiq_slot_struct { + char data[VCHIQ_SLOT_SIZE]; +} VCHIQ_SLOT_T; + +typedef struct vchiq_slot_info_struct { + /* Use two counters rather than one to avoid the need for a mutex. */ + short use_count; + short release_count; +} VCHIQ_SLOT_INFO_T; + +typedef struct vchiq_service_struct { + VCHIQ_SERVICE_BASE_T base; + VCHIQ_SERVICE_HANDLE_T handle; + unsigned int ref_count; + int srvstate; + VCHIQ_USERDATA_TERM_T userdata_term; + unsigned int localport; + unsigned int remoteport; + int public_fourcc; + int client_id; + char auto_close; + char sync; + char closing; + char trace; + atomic_t poll_flags; + short version; + short version_min; + short peer_version; + + VCHIQ_STATE_T *state; + VCHIQ_INSTANCE_T instance; + + int service_use_count; + + VCHIQ_BULK_QUEUE_T bulk_tx; + VCHIQ_BULK_QUEUE_T bulk_rx; + + struct semaphore remove_event; + struct semaphore bulk_remove_event; + struct mutex bulk_mutex; + + struct service_stats_struct { + int quota_stalls; + int slot_stalls; + int bulk_stalls; + int error_count; + int ctrl_tx_count; + int ctrl_rx_count; + int bulk_tx_count; + int bulk_rx_count; + int bulk_aborted_count; + uint64_t ctrl_tx_bytes; + uint64_t ctrl_rx_bytes; + uint64_t bulk_tx_bytes; + uint64_t bulk_rx_bytes; + } stats; +} VCHIQ_SERVICE_T; + +/* The quota information is outside VCHIQ_SERVICE_T so that it can be + statically allocated, since for accounting reasons a service's slot + usage is carried over between users of the same port number. + */ +typedef struct vchiq_service_quota_struct { + unsigned short slot_quota; + unsigned short slot_use_count; + unsigned short message_quota; + unsigned short message_use_count; + struct semaphore quota_event; + int previous_tx_index; +} VCHIQ_SERVICE_QUOTA_T; + +typedef struct vchiq_shared_state_struct { + + /* A non-zero value here indicates that the content is valid. */ + int initialised; + + /* The first and last (inclusive) slots allocated to the owner. */ + int slot_first; + int slot_last; + + /* The slot allocated to synchronous messages from the owner. */ + int slot_sync; + + /* Signalling this event indicates that owner's slot handler thread + ** should run. */ + REMOTE_EVENT_T trigger; + + /* Indicates the byte position within the stream where the next message + ** will be written. The least significant bits are an index into the + ** slot. The next bits are the index of the slot in slot_queue. */ + int tx_pos; + + /* This event should be signalled when a slot is recycled. */ + REMOTE_EVENT_T recycle; + + /* The slot_queue index where the next recycled slot will be written. */ + int slot_queue_recycle; + + /* This event should be signalled when a synchronous message is sent. */ + REMOTE_EVENT_T sync_trigger; + + /* This event should be signalled when a synchronous message has been + ** released. */ + REMOTE_EVENT_T sync_release; + + /* A circular buffer of slot indexes. */ + int slot_queue[VCHIQ_MAX_SLOTS_PER_SIDE]; + + /* Debugging state */ + int debug[DEBUG_MAX]; +} VCHIQ_SHARED_STATE_T; + +typedef struct vchiq_slot_zero_struct { + int magic; + short version; + short version_min; + int slot_zero_size; + int slot_size; + int max_slots; + int max_slots_per_side; + int platform_data[2]; + VCHIQ_SHARED_STATE_T master; + VCHIQ_SHARED_STATE_T slave; + VCHIQ_SLOT_INFO_T slots[VCHIQ_MAX_SLOTS]; +} VCHIQ_SLOT_ZERO_T; + +struct vchiq_state_struct { + int id; + int initialised; + VCHIQ_CONNSTATE_T conn_state; + int is_master; + short version_common; + + VCHIQ_SHARED_STATE_T *local; + VCHIQ_SHARED_STATE_T *remote; + VCHIQ_SLOT_T *slot_data; + + unsigned short default_slot_quota; + unsigned short default_message_quota; + + /* Event indicating connect message received */ + struct semaphore connect; + + /* Mutex protecting services */ + struct mutex mutex; + VCHIQ_INSTANCE_T *instance; + + /* Processes incoming messages */ + struct task_struct *slot_handler_thread; + + /* Processes recycled slots */ + struct task_struct *recycle_thread; + + /* Processes synchronous messages */ + struct task_struct *sync_thread; + + /* Local implementation of the trigger remote event */ + struct semaphore trigger_event; + + /* Local implementation of the recycle remote event */ + struct semaphore recycle_event; + + /* Local implementation of the sync trigger remote event */ + struct semaphore sync_trigger_event; + + /* Local implementation of the sync release remote event */ + struct semaphore sync_release_event; + + char *tx_data; + char *rx_data; + VCHIQ_SLOT_INFO_T *rx_info; + + struct mutex slot_mutex; + + struct mutex recycle_mutex; + + struct mutex sync_mutex; + + struct mutex bulk_transfer_mutex; + + /* Indicates the byte position within the stream from where the next + ** message will be read. The least significant bits are an index into + ** the slot.The next bits are the index of the slot in + ** remote->slot_queue. */ + int rx_pos; + + /* A cached copy of local->tx_pos. Only write to local->tx_pos, and read + from remote->tx_pos. */ + int local_tx_pos; + + /* The slot_queue index of the slot to become available next. */ + int slot_queue_available; + + /* A flag to indicate if any poll has been requested */ + int poll_needed; + + /* Ths index of the previous slot used for data messages. */ + int previous_data_index; + + /* The number of slots occupied by data messages. */ + unsigned short data_use_count; + + /* The maximum number of slots to be occupied by data messages. */ + unsigned short data_quota; + + /* An array of bit sets indicating which services must be polled. */ + atomic_t poll_services[BITSET_SIZE(VCHIQ_MAX_SERVICES)]; + + /* The number of the first unused service */ + int unused_service; + + /* Signalled when a free slot becomes available. */ + struct semaphore slot_available_event; + + struct semaphore slot_remove_event; + + /* Signalled when a free data slot becomes available. */ + struct semaphore data_quota_event; + + /* Incremented when there are bulk transfers which cannot be processed + * whilst paused and must be processed on resume */ + int deferred_bulks; + + struct state_stats_struct { + int slot_stalls; + int data_stalls; + int ctrl_tx_count; + int ctrl_rx_count; + int error_count; + } stats; + + VCHIQ_SERVICE_T * services[VCHIQ_MAX_SERVICES]; + VCHIQ_SERVICE_QUOTA_T service_quotas[VCHIQ_MAX_SERVICES]; + VCHIQ_SLOT_INFO_T slot_info[VCHIQ_MAX_SLOTS]; + + VCHIQ_PLATFORM_STATE_T platform_state; +}; + +struct bulk_waiter { + VCHIQ_BULK_T *bulk; + struct semaphore event; + int actual; +}; + +extern spinlock_t bulk_waiter_spinlock; + +extern int vchiq_core_log_level; +extern int vchiq_core_msg_log_level; +extern int vchiq_sync_log_level; + +extern VCHIQ_STATE_T *vchiq_states[VCHIQ_MAX_STATES]; + +extern const char * +get_conn_state_name(VCHIQ_CONNSTATE_T conn_state); + +extern VCHIQ_SLOT_ZERO_T * +vchiq_init_slots(void *mem_base, int mem_size); + +extern VCHIQ_STATUS_T +vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero, + int is_master); + +extern VCHIQ_STATUS_T +vchiq_connect_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance); + +extern VCHIQ_SERVICE_T * +vchiq_add_service_internal(VCHIQ_STATE_T *state, + const VCHIQ_SERVICE_PARAMS_T *params, int srvstate, + VCHIQ_INSTANCE_T instance, VCHIQ_USERDATA_TERM_T userdata_term); + +extern VCHIQ_STATUS_T +vchiq_open_service_internal(VCHIQ_SERVICE_T *service, int client_id); + +extern VCHIQ_STATUS_T +vchiq_close_service_internal(VCHIQ_SERVICE_T *service, int close_recvd); + +extern void +vchiq_terminate_service_internal(VCHIQ_SERVICE_T *service); + +extern void +vchiq_free_service_internal(VCHIQ_SERVICE_T *service); + +extern VCHIQ_STATUS_T +vchiq_shutdown_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance); + +extern VCHIQ_STATUS_T +vchiq_pause_internal(VCHIQ_STATE_T *state); + +extern VCHIQ_STATUS_T +vchiq_resume_internal(VCHIQ_STATE_T *state); + +extern void +remote_event_pollall(VCHIQ_STATE_T *state); + +extern VCHIQ_STATUS_T +vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, + VCHI_MEM_HANDLE_T memhandle, void *offset, int size, void *userdata, + VCHIQ_BULK_MODE_T mode, VCHIQ_BULK_DIR_T dir); + +extern void +vchiq_dump_state(void *dump_context, VCHIQ_STATE_T *state); + +extern void +vchiq_dump_service_state(void *dump_context, VCHIQ_SERVICE_T *service); + +extern void +vchiq_loud_error_header(void); + +extern void +vchiq_loud_error_footer(void); + +extern void +request_poll(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, int poll_type); + +static inline VCHIQ_SERVICE_T * +handle_to_service(VCHIQ_SERVICE_HANDLE_T handle) +{ + VCHIQ_STATE_T *state = vchiq_states[(handle / VCHIQ_MAX_SERVICES) & + (VCHIQ_MAX_STATES - 1)]; + if (!state) + return NULL; + + return state->services[handle & (VCHIQ_MAX_SERVICES - 1)]; +} + +extern VCHIQ_SERVICE_T * +find_service_by_handle(VCHIQ_SERVICE_HANDLE_T handle); + +extern VCHIQ_SERVICE_T * +find_service_by_port(VCHIQ_STATE_T *state, int localport); + +extern VCHIQ_SERVICE_T * +find_service_for_instance(VCHIQ_INSTANCE_T instance, + VCHIQ_SERVICE_HANDLE_T handle); + +extern VCHIQ_SERVICE_T * +find_closed_service_for_instance(VCHIQ_INSTANCE_T instance, + VCHIQ_SERVICE_HANDLE_T handle); + +extern VCHIQ_SERVICE_T * +next_service_by_instance(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance, + int *pidx); + +extern void +lock_service(VCHIQ_SERVICE_T *service); + +extern void +unlock_service(VCHIQ_SERVICE_T *service); + +/* The following functions are called from vchiq_core, and external +** implementations must be provided. */ + +extern VCHIQ_STATUS_T +vchiq_prepare_bulk_data(VCHIQ_BULK_T *bulk, + VCHI_MEM_HANDLE_T memhandle, void *offset, int size, int dir); + +extern void +vchiq_transfer_bulk(VCHIQ_BULK_T *bulk); + +extern void +vchiq_complete_bulk(VCHIQ_BULK_T *bulk); + +extern VCHIQ_STATUS_T +vchiq_copy_from_user(void *dst, const void *src, int size); + +extern void +remote_event_signal(REMOTE_EVENT_T *event); + +void +vchiq_platform_check_suspend(VCHIQ_STATE_T *state); + +extern void +vchiq_platform_paused(VCHIQ_STATE_T *state); + +extern VCHIQ_STATUS_T +vchiq_platform_resume(VCHIQ_STATE_T *state); + +extern void +vchiq_platform_resumed(VCHIQ_STATE_T *state); + +extern void +vchiq_dump(void *dump_context, const char *str, int len); + +extern void +vchiq_dump_platform_state(void *dump_context); + +extern void +vchiq_dump_platform_instances(void *dump_context); + +extern void +vchiq_dump_platform_service_state(void *dump_context, + VCHIQ_SERVICE_T *service); + +extern VCHIQ_STATUS_T +vchiq_use_service_internal(VCHIQ_SERVICE_T *service); + +extern VCHIQ_STATUS_T +vchiq_release_service_internal(VCHIQ_SERVICE_T *service); + +extern void +vchiq_on_remote_use(VCHIQ_STATE_T *state); + +extern void +vchiq_on_remote_release(VCHIQ_STATE_T *state); + +extern VCHIQ_STATUS_T +vchiq_platform_init_state(VCHIQ_STATE_T *state); + +extern VCHIQ_STATUS_T +vchiq_check_service(VCHIQ_SERVICE_T *service); + +extern void +vchiq_on_remote_use_active(VCHIQ_STATE_T *state); + +extern VCHIQ_STATUS_T +vchiq_send_remote_use(VCHIQ_STATE_T *state); + +extern VCHIQ_STATUS_T +vchiq_send_remote_release(VCHIQ_STATE_T *state); + +extern VCHIQ_STATUS_T +vchiq_send_remote_use_active(VCHIQ_STATE_T *state); + +extern void +vchiq_platform_conn_state_changed(VCHIQ_STATE_T *state, + VCHIQ_CONNSTATE_T oldstate, VCHIQ_CONNSTATE_T newstate); + +extern void +vchiq_platform_handle_timeout(VCHIQ_STATE_T *state); + +extern void +vchiq_set_conn_state(VCHIQ_STATE_T *state, VCHIQ_CONNSTATE_T newstate); + + +extern void +vchiq_log_dump_mem(const char *label, uint32_t addr, const void *voidMem, + size_t numBytes); + +#endif diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c new file mode 100644 index 0000000..7e03213 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c @@ -0,0 +1,383 @@ +/** + * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved. + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include <linux/debugfs.h> +#include "vchiq_core.h" +#include "vchiq_arm.h" +#include "vchiq_debugfs.h" + +#ifdef CONFIG_DEBUG_FS + +/**************************************************************************** +* +* log category entries +* +***************************************************************************/ +#define DEBUGFS_WRITE_BUF_SIZE 256 + +#define VCHIQ_LOG_ERROR_STR "error" +#define VCHIQ_LOG_WARNING_STR "warning" +#define VCHIQ_LOG_INFO_STR "info" +#define VCHIQ_LOG_TRACE_STR "trace" + + +/* Top-level debug info */ +struct vchiq_debugfs_info { + /* Global 'vchiq' debugfs entry used by all instances */ + struct dentry *vchiq_cfg_dir; + + /* one entry per client process */ + struct dentry *clients; + + /* log categories */ + struct dentry *log_categories; +}; + +static struct vchiq_debugfs_info debugfs_info; + +/* Log category debugfs entries */ +struct vchiq_debugfs_log_entry { + const char *name; + int *plevel; + struct dentry *dir; +}; + +static struct vchiq_debugfs_log_entry vchiq_debugfs_log_entries[] = { + { "core", &vchiq_core_log_level }, + { "msg", &vchiq_core_msg_log_level }, + { "sync", &vchiq_sync_log_level }, + { "susp", &vchiq_susp_log_level }, + { "arm", &vchiq_arm_log_level }, +}; +static int n_log_entries = + sizeof(vchiq_debugfs_log_entries)/sizeof(vchiq_debugfs_log_entries[0]); + + +static struct dentry *vchiq_clients_top(void); +static struct dentry *vchiq_debugfs_top(void); + +static int debugfs_log_show(struct seq_file *f, void *offset) +{ + int *levp = f->private; + char *log_value = NULL; + + switch (*levp) { + case VCHIQ_LOG_ERROR: + log_value = VCHIQ_LOG_ERROR_STR; + break; + case VCHIQ_LOG_WARNING: + log_value = VCHIQ_LOG_WARNING_STR; + break; + case VCHIQ_LOG_INFO: + log_value = VCHIQ_LOG_INFO_STR; + break; + case VCHIQ_LOG_TRACE: + log_value = VCHIQ_LOG_TRACE_STR; + break; + default: + break; + } + + seq_printf(f, "%s\n", log_value ? log_value : "(null)"); + + return 0; +} + +static int debugfs_log_open(struct inode *inode, struct file *file) +{ + return single_open(file, debugfs_log_show, inode->i_private); +} + +static int debugfs_log_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *ppos) +{ + struct seq_file *f = (struct seq_file *)file->private_data; + int *levp = f->private; + char kbuf[DEBUGFS_WRITE_BUF_SIZE + 1]; + + memset(kbuf, 0, DEBUGFS_WRITE_BUF_SIZE + 1); + if (count >= DEBUGFS_WRITE_BUF_SIZE) + count = DEBUGFS_WRITE_BUF_SIZE; + + if (copy_from_user(kbuf, buffer, count) != 0) + return -EFAULT; + kbuf[count - 1] = 0; + + if (strncmp("error", kbuf, strlen("error")) == 0) + *levp = VCHIQ_LOG_ERROR; + else if (strncmp("warning", kbuf, strlen("warning")) == 0) + *levp = VCHIQ_LOG_WARNING; + else if (strncmp("info", kbuf, strlen("info")) == 0) + *levp = VCHIQ_LOG_INFO; + else if (strncmp("trace", kbuf, strlen("trace")) == 0) + *levp = VCHIQ_LOG_TRACE; + else + *levp = VCHIQ_LOG_DEFAULT; + + *ppos += count; + + return count; +} + +static const struct file_operations debugfs_log_fops = { + .owner = THIS_MODULE, + .open = debugfs_log_open, + .write = debugfs_log_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/* create an entry under <debugfs>/vchiq/log for each log category */ +static int vchiq_debugfs_create_log_entries(struct dentry *top) +{ + struct dentry *dir; + size_t i; + int ret = 0; + dir = debugfs_create_dir("log", vchiq_debugfs_top()); + if (!dir) + return -ENOMEM; + debugfs_info.log_categories = dir; + + for (i = 0; i < n_log_entries; i++) { + void *levp = (void *)vchiq_debugfs_log_entries[i].plevel; + dir = debugfs_create_file(vchiq_debugfs_log_entries[i].name, + 0644, + debugfs_info.log_categories, + levp, + &debugfs_log_fops); + if (!dir) { + ret = -ENOMEM; + break; + } + + vchiq_debugfs_log_entries[i].dir = dir; + } + return ret; +} + +static int debugfs_usecount_show(struct seq_file *f, void *offset) +{ + VCHIQ_INSTANCE_T instance = f->private; + int use_count; + + use_count = vchiq_instance_get_use_count(instance); + seq_printf(f, "%d\n", use_count); + + return 0; +} + +static int debugfs_usecount_open(struct inode *inode, struct file *file) +{ + return single_open(file, debugfs_usecount_show, inode->i_private); +} + +static const struct file_operations debugfs_usecount_fops = { + .owner = THIS_MODULE, + .open = debugfs_usecount_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int debugfs_trace_show(struct seq_file *f, void *offset) +{ + VCHIQ_INSTANCE_T instance = f->private; + int trace; + + trace = vchiq_instance_get_trace(instance); + seq_printf(f, "%s\n", trace ? "Y" : "N"); + + return 0; +} + +static int debugfs_trace_open(struct inode *inode, struct file *file) +{ + return single_open(file, debugfs_trace_show, inode->i_private); +} + +static int debugfs_trace_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *ppos) +{ + struct seq_file *f = (struct seq_file *)file->private_data; + VCHIQ_INSTANCE_T instance = f->private; + char firstchar; + + if (copy_from_user(&firstchar, buffer, 1) != 0) + return -EFAULT; + + switch (firstchar) { + case 'Y': + case 'y': + case '1': + vchiq_instance_set_trace(instance, 1); + break; + case 'N': + case 'n': + case '0': + vchiq_instance_set_trace(instance, 0); + break; + default: + break; + } + + *ppos += count; + + return count; +} + +static const struct file_operations debugfs_trace_fops = { + .owner = THIS_MODULE, + .open = debugfs_trace_open, + .write = debugfs_trace_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/* add an instance (process) to the debugfs entries */ +int vchiq_debugfs_add_instance(VCHIQ_INSTANCE_T instance) +{ + char pidstr[16]; + struct dentry *top, *use_count, *trace; + struct dentry *clients = vchiq_clients_top(); + + snprintf(pidstr, sizeof(pidstr), "%d", + vchiq_instance_get_pid(instance)); + + top = debugfs_create_dir(pidstr, clients); + if (!top) + goto fail_top; + + use_count = debugfs_create_file("use_count", + 0444, top, + instance, + &debugfs_usecount_fops); + if (!use_count) + goto fail_use_count; + + trace = debugfs_create_file("trace", + 0644, top, + instance, + &debugfs_trace_fops); + if (!trace) + goto fail_trace; + + vchiq_instance_get_debugfs_node(instance)->dentry = top; + + return 0; + +fail_trace: + debugfs_remove(use_count); +fail_use_count: + debugfs_remove(top); +fail_top: + return -ENOMEM; +} + +void vchiq_debugfs_remove_instance(VCHIQ_INSTANCE_T instance) +{ + VCHIQ_DEBUGFS_NODE_T *node = vchiq_instance_get_debugfs_node(instance); + debugfs_remove_recursive(node->dentry); +} + + +int vchiq_debugfs_init(void) +{ + BUG_ON(debugfs_info.vchiq_cfg_dir != NULL); + + debugfs_info.vchiq_cfg_dir = debugfs_create_dir("vchiq", NULL); + if (debugfs_info.vchiq_cfg_dir == NULL) + goto fail; + + debugfs_info.clients = debugfs_create_dir("clients", + vchiq_debugfs_top()); + if (!debugfs_info.clients) + goto fail; + + if (vchiq_debugfs_create_log_entries(vchiq_debugfs_top()) != 0) + goto fail; + + return 0; + +fail: + vchiq_debugfs_deinit(); + vchiq_log_error(vchiq_arm_log_level, + "%s: failed to create debugfs directory", + __func__); + + return -ENOMEM; +} + +/* remove all the debugfs entries */ +void vchiq_debugfs_deinit(void) +{ + debugfs_remove_recursive(vchiq_debugfs_top()); +} + +static struct dentry *vchiq_clients_top(void) +{ + return debugfs_info.clients; +} + +static struct dentry *vchiq_debugfs_top(void) +{ + BUG_ON(debugfs_info.vchiq_cfg_dir == NULL); + return debugfs_info.vchiq_cfg_dir; +} + +#else /* CONFIG_DEBUG_FS */ + +int vchiq_debugfs_init(void) +{ + return 0; +} + +void vchiq_debugfs_deinit(void) +{ +} + +int vchiq_debugfs_add_instance(VCHIQ_INSTANCE_T instance) +{ + return 0; +} + +void vchiq_debugfs_remove_instance(VCHIQ_INSTANCE_T instance) +{ +} + +#endif /* CONFIG_DEBUG_FS */ diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h new file mode 100644 index 0000000..4d6a378 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHIQ_DEBUGFS_H +#define VCHIQ_DEBUGFS_H + +#include "vchiq_core.h" + +typedef struct vchiq_debugfs_node_struct +{ + struct dentry *dentry; +} VCHIQ_DEBUGFS_NODE_T; + +int vchiq_debugfs_init(void); + +void vchiq_debugfs_deinit(void); + +int vchiq_debugfs_add_instance(VCHIQ_INSTANCE_T instance); + +void vchiq_debugfs_remove_instance(VCHIQ_INSTANCE_T instance); + +#endif /* VCHIQ_DEBUGFS_H */ diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_genversion b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_genversion new file mode 100644 index 0000000..9f5b634 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_genversion @@ -0,0 +1,87 @@ +#!/usr/bin/perl -w + +use strict; + +# +# Generate a version from available information +# + +my $prefix = shift @ARGV; +my $root = shift @ARGV; + + +if ( not defined $root ) { + die "usage: $0 prefix root-dir\n"; +} + +if ( ! -d $root ) { + die "root directory $root not found\n"; +} + +my $version = "unknown"; +my $tainted = ""; + +if ( -d "$root/.git" ) { + # attempt to work out git version. only do so + # on a linux build host, as cygwin builds are + # already slow enough + + if ( -f "/usr/bin/git" || -f "/usr/local/bin/git" ) { + if (not open(F, "git --git-dir $root/.git rev-parse --verify HEAD|")) { + $version = "no git version"; + } + else { + $version = <F>; + $version =~ s/[ \r\n]*$//; # chomp may not be enough (cygwin). + $version =~ s/^[ \r\n]*//; # chomp may not be enough (cygwin). + } + + if (open(G, "git --git-dir $root/.git status --porcelain|")) { + $tainted = <G>; + $tainted =~ s/[ \r\n]*$//; # chomp may not be enough (cygwin). + $tainted =~ s/^[ \r\n]*//; # chomp may not be enough (cygwin). + if (length $tainted) { + $version = join ' ', $version, "(tainted)"; + } + else { + $version = join ' ', $version, "(clean)"; + } + } + } +} + +my $hostname = `hostname`; +$hostname =~ s/[ \r\n]*$//; # chomp may not be enough (cygwin). +$hostname =~ s/^[ \r\n]*//; # chomp may not be enough (cygwin). + + +print STDERR "Version $version\n"; +print <<EOF; +#include "${prefix}_build_info.h" +#include <linux/broadcom/vc_debug_sym.h> + +VC_DEBUG_DECLARE_STRING_VAR( ${prefix}_build_hostname, "$hostname" ); +VC_DEBUG_DECLARE_STRING_VAR( ${prefix}_build_version, "$version" ); +VC_DEBUG_DECLARE_STRING_VAR( ${prefix}_build_time, __TIME__ ); +VC_DEBUG_DECLARE_STRING_VAR( ${prefix}_build_date, __DATE__ ); + +const char *vchiq_get_build_hostname( void ) +{ + return vchiq_build_hostname; +} + +const char *vchiq_get_build_version( void ) +{ + return vchiq_build_version; +} + +const char *vchiq_get_build_date( void ) +{ + return vchiq_build_date; +} + +const char *vchiq_get_build_time( void ) +{ + return vchiq_build_time; +} +EOF diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h new file mode 100644 index 0000000..8067bbe --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h @@ -0,0 +1,189 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHIQ_IF_H +#define VCHIQ_IF_H + +#include "interface/vchi/vchi_mh.h" + +#define VCHIQ_SERVICE_HANDLE_INVALID 0 + +#define VCHIQ_SLOT_SIZE 4096 +#define VCHIQ_MAX_MSG_SIZE (VCHIQ_SLOT_SIZE - sizeof(VCHIQ_HEADER_T)) +#define VCHIQ_CHANNEL_SIZE VCHIQ_MAX_MSG_SIZE /* For backwards compatibility */ + +#define VCHIQ_MAKE_FOURCC(x0, x1, x2, x3) \ + (((x0) << 24) | ((x1) << 16) | ((x2) << 8) | (x3)) +#define VCHIQ_GET_SERVICE_USERDATA(service) vchiq_get_service_userdata(service) +#define VCHIQ_GET_SERVICE_FOURCC(service) vchiq_get_service_fourcc(service) + +typedef enum { + VCHIQ_SERVICE_OPENED, /* service, -, - */ + VCHIQ_SERVICE_CLOSED, /* service, -, - */ + VCHIQ_MESSAGE_AVAILABLE, /* service, header, - */ + VCHIQ_BULK_TRANSMIT_DONE, /* service, -, bulk_userdata */ + VCHIQ_BULK_RECEIVE_DONE, /* service, -, bulk_userdata */ + VCHIQ_BULK_TRANSMIT_ABORTED, /* service, -, bulk_userdata */ + VCHIQ_BULK_RECEIVE_ABORTED /* service, -, bulk_userdata */ +} VCHIQ_REASON_T; + +typedef enum { + VCHIQ_ERROR = -1, + VCHIQ_SUCCESS = 0, + VCHIQ_RETRY = 1 +} VCHIQ_STATUS_T; + +typedef enum { + VCHIQ_BULK_MODE_CALLBACK, + VCHIQ_BULK_MODE_BLOCKING, + VCHIQ_BULK_MODE_NOCALLBACK, + VCHIQ_BULK_MODE_WAITING /* Reserved for internal use */ +} VCHIQ_BULK_MODE_T; + +typedef enum { + VCHIQ_SERVICE_OPTION_AUTOCLOSE, + VCHIQ_SERVICE_OPTION_SLOT_QUOTA, + VCHIQ_SERVICE_OPTION_MESSAGE_QUOTA, + VCHIQ_SERVICE_OPTION_SYNCHRONOUS, + VCHIQ_SERVICE_OPTION_TRACE +} VCHIQ_SERVICE_OPTION_T; + +typedef struct vchiq_header_struct { + /* The message identifier - opaque to applications. */ + int msgid; + + /* Size of message data. */ + unsigned int size; + + char data[0]; /* message */ +} VCHIQ_HEADER_T; + +typedef struct { + const void *data; + unsigned int size; +} VCHIQ_ELEMENT_T; + +typedef unsigned int VCHIQ_SERVICE_HANDLE_T; + +typedef VCHIQ_STATUS_T (*VCHIQ_CALLBACK_T)(VCHIQ_REASON_T, VCHIQ_HEADER_T *, + VCHIQ_SERVICE_HANDLE_T, void *); + +typedef struct vchiq_service_base_struct { + int fourcc; + VCHIQ_CALLBACK_T callback; + void *userdata; +} VCHIQ_SERVICE_BASE_T; + +typedef struct vchiq_service_params_struct { + int fourcc; + VCHIQ_CALLBACK_T callback; + void *userdata; + short version; /* Increment for non-trivial changes */ + short version_min; /* Update for incompatible changes */ +} VCHIQ_SERVICE_PARAMS_T; + +typedef struct vchiq_config_struct { + unsigned int max_msg_size; + unsigned int bulk_threshold; /* The message size above which it + is better to use a bulk transfer + (<= max_msg_size) */ + unsigned int max_outstanding_bulks; + unsigned int max_services; + short version; /* The version of VCHIQ */ + short version_min; /* The minimum compatible version of VCHIQ */ +} VCHIQ_CONFIG_T; + +typedef struct vchiq_instance_struct *VCHIQ_INSTANCE_T; +typedef void (*VCHIQ_REMOTE_USE_CALLBACK_T)(void *cb_arg); + +extern VCHIQ_STATUS_T vchiq_initialise(VCHIQ_INSTANCE_T *pinstance); +extern VCHIQ_STATUS_T vchiq_shutdown(VCHIQ_INSTANCE_T instance); +extern VCHIQ_STATUS_T vchiq_connect(VCHIQ_INSTANCE_T instance); +extern VCHIQ_STATUS_T vchiq_add_service(VCHIQ_INSTANCE_T instance, + const VCHIQ_SERVICE_PARAMS_T *params, + VCHIQ_SERVICE_HANDLE_T *pservice); +extern VCHIQ_STATUS_T vchiq_open_service(VCHIQ_INSTANCE_T instance, + const VCHIQ_SERVICE_PARAMS_T *params, + VCHIQ_SERVICE_HANDLE_T *pservice); +extern VCHIQ_STATUS_T vchiq_close_service(VCHIQ_SERVICE_HANDLE_T service); +extern VCHIQ_STATUS_T vchiq_remove_service(VCHIQ_SERVICE_HANDLE_T service); +extern VCHIQ_STATUS_T vchiq_use_service(VCHIQ_SERVICE_HANDLE_T service); +extern VCHIQ_STATUS_T vchiq_use_service_no_resume( + VCHIQ_SERVICE_HANDLE_T service); +extern VCHIQ_STATUS_T vchiq_release_service(VCHIQ_SERVICE_HANDLE_T service); + +extern VCHIQ_STATUS_T vchiq_queue_message(VCHIQ_SERVICE_HANDLE_T service, + const VCHIQ_ELEMENT_T *elements, unsigned int count); +extern void vchiq_release_message(VCHIQ_SERVICE_HANDLE_T service, + VCHIQ_HEADER_T *header); +extern VCHIQ_STATUS_T vchiq_queue_bulk_transmit(VCHIQ_SERVICE_HANDLE_T service, + const void *data, unsigned int size, void *userdata); +extern VCHIQ_STATUS_T vchiq_queue_bulk_receive(VCHIQ_SERVICE_HANDLE_T service, + void *data, unsigned int size, void *userdata); +extern VCHIQ_STATUS_T vchiq_queue_bulk_transmit_handle( + VCHIQ_SERVICE_HANDLE_T service, VCHI_MEM_HANDLE_T handle, + const void *offset, unsigned int size, void *userdata); +extern VCHIQ_STATUS_T vchiq_queue_bulk_receive_handle( + VCHIQ_SERVICE_HANDLE_T service, VCHI_MEM_HANDLE_T handle, + void *offset, unsigned int size, void *userdata); +extern VCHIQ_STATUS_T vchiq_bulk_transmit(VCHIQ_SERVICE_HANDLE_T service, + const void *data, unsigned int size, void *userdata, + VCHIQ_BULK_MODE_T mode); +extern VCHIQ_STATUS_T vchiq_bulk_receive(VCHIQ_SERVICE_HANDLE_T service, + void *data, unsigned int size, void *userdata, + VCHIQ_BULK_MODE_T mode); +extern VCHIQ_STATUS_T vchiq_bulk_transmit_handle(VCHIQ_SERVICE_HANDLE_T service, + VCHI_MEM_HANDLE_T handle, const void *offset, unsigned int size, + void *userdata, VCHIQ_BULK_MODE_T mode); +extern VCHIQ_STATUS_T vchiq_bulk_receive_handle(VCHIQ_SERVICE_HANDLE_T service, + VCHI_MEM_HANDLE_T handle, void *offset, unsigned int size, + void *userdata, VCHIQ_BULK_MODE_T mode); +extern int vchiq_get_client_id(VCHIQ_SERVICE_HANDLE_T service); +extern void *vchiq_get_service_userdata(VCHIQ_SERVICE_HANDLE_T service); +extern int vchiq_get_service_fourcc(VCHIQ_SERVICE_HANDLE_T service); +extern VCHIQ_STATUS_T vchiq_get_config(VCHIQ_INSTANCE_T instance, + int config_size, VCHIQ_CONFIG_T *pconfig); +extern VCHIQ_STATUS_T vchiq_set_service_option(VCHIQ_SERVICE_HANDLE_T service, + VCHIQ_SERVICE_OPTION_T option, int value); + +extern VCHIQ_STATUS_T vchiq_remote_use(VCHIQ_INSTANCE_T instance, + VCHIQ_REMOTE_USE_CALLBACK_T callback, void *cb_arg); +extern VCHIQ_STATUS_T vchiq_remote_release(VCHIQ_INSTANCE_T instance); + +extern VCHIQ_STATUS_T vchiq_dump_phys_mem(VCHIQ_SERVICE_HANDLE_T service, + void *ptr, size_t num_bytes); + +extern VCHIQ_STATUS_T vchiq_get_peer_version(VCHIQ_SERVICE_HANDLE_T handle, + short *peer_version); + +#endif /* VCHIQ_IF_H */ diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h new file mode 100644 index 0000000..6137ae9 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h @@ -0,0 +1,131 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHIQ_IOCTLS_H +#define VCHIQ_IOCTLS_H + +#include <linux/ioctl.h> +#include "vchiq_if.h" + +#define VCHIQ_IOC_MAGIC 0xc4 +#define VCHIQ_INVALID_HANDLE (~0) + +typedef struct { + VCHIQ_SERVICE_PARAMS_T params; + int is_open; + int is_vchi; + unsigned int handle; /* OUT */ +} VCHIQ_CREATE_SERVICE_T; + +typedef struct { + unsigned int handle; + unsigned int count; + const VCHIQ_ELEMENT_T *elements; +} VCHIQ_QUEUE_MESSAGE_T; + +typedef struct { + unsigned int handle; + void *data; + unsigned int size; + void *userdata; + VCHIQ_BULK_MODE_T mode; +} VCHIQ_QUEUE_BULK_TRANSFER_T; + +typedef struct { + VCHIQ_REASON_T reason; + VCHIQ_HEADER_T *header; + void *service_userdata; + void *bulk_userdata; +} VCHIQ_COMPLETION_DATA_T; + +typedef struct { + unsigned int count; + VCHIQ_COMPLETION_DATA_T *buf; + unsigned int msgbufsize; + unsigned int msgbufcount; /* IN/OUT */ + void **msgbufs; +} VCHIQ_AWAIT_COMPLETION_T; + +typedef struct { + unsigned int handle; + int blocking; + unsigned int bufsize; + void *buf; +} VCHIQ_DEQUEUE_MESSAGE_T; + +typedef struct { + unsigned int config_size; + VCHIQ_CONFIG_T *pconfig; +} VCHIQ_GET_CONFIG_T; + +typedef struct { + unsigned int handle; + VCHIQ_SERVICE_OPTION_T option; + int value; +} VCHIQ_SET_SERVICE_OPTION_T; + +typedef struct { + void *virt_addr; + size_t num_bytes; +} VCHIQ_DUMP_MEM_T; + +#define VCHIQ_IOC_CONNECT _IO(VCHIQ_IOC_MAGIC, 0) +#define VCHIQ_IOC_SHUTDOWN _IO(VCHIQ_IOC_MAGIC, 1) +#define VCHIQ_IOC_CREATE_SERVICE \ + _IOWR(VCHIQ_IOC_MAGIC, 2, VCHIQ_CREATE_SERVICE_T) +#define VCHIQ_IOC_REMOVE_SERVICE _IO(VCHIQ_IOC_MAGIC, 3) +#define VCHIQ_IOC_QUEUE_MESSAGE \ + _IOW(VCHIQ_IOC_MAGIC, 4, VCHIQ_QUEUE_MESSAGE_T) +#define VCHIQ_IOC_QUEUE_BULK_TRANSMIT \ + _IOWR(VCHIQ_IOC_MAGIC, 5, VCHIQ_QUEUE_BULK_TRANSFER_T) +#define VCHIQ_IOC_QUEUE_BULK_RECEIVE \ + _IOWR(VCHIQ_IOC_MAGIC, 6, VCHIQ_QUEUE_BULK_TRANSFER_T) +#define VCHIQ_IOC_AWAIT_COMPLETION \ + _IOWR(VCHIQ_IOC_MAGIC, 7, VCHIQ_AWAIT_COMPLETION_T) +#define VCHIQ_IOC_DEQUEUE_MESSAGE \ + _IOWR(VCHIQ_IOC_MAGIC, 8, VCHIQ_DEQUEUE_MESSAGE_T) +#define VCHIQ_IOC_GET_CLIENT_ID _IO(VCHIQ_IOC_MAGIC, 9) +#define VCHIQ_IOC_GET_CONFIG \ + _IOWR(VCHIQ_IOC_MAGIC, 10, VCHIQ_GET_CONFIG_T) +#define VCHIQ_IOC_CLOSE_SERVICE _IO(VCHIQ_IOC_MAGIC, 11) +#define VCHIQ_IOC_USE_SERVICE _IO(VCHIQ_IOC_MAGIC, 12) +#define VCHIQ_IOC_RELEASE_SERVICE _IO(VCHIQ_IOC_MAGIC, 13) +#define VCHIQ_IOC_SET_SERVICE_OPTION \ + _IOW(VCHIQ_IOC_MAGIC, 14, VCHIQ_SET_SERVICE_OPTION_T) +#define VCHIQ_IOC_DUMP_PHYS_MEM \ + _IOW(VCHIQ_IOC_MAGIC, 15, VCHIQ_DUMP_MEM_T) +#define VCHIQ_IOC_LIB_VERSION _IO(VCHIQ_IOC_MAGIC, 16) +#define VCHIQ_IOC_CLOSE_DELIVERED _IO(VCHIQ_IOC_MAGIC, 17) +#define VCHIQ_IOC_MAX 17 + +#endif diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c new file mode 100644 index 0000000..25e7011 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c @@ -0,0 +1,458 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* ---- Include Files ---------------------------------------------------- */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mutex.h> + +#include "vchiq_core.h" +#include "vchiq_arm.h" +#include "vchiq_killable.h" + +/* ---- Public Variables ------------------------------------------------- */ + +/* ---- Private Constants and Types -------------------------------------- */ + +struct bulk_waiter_node { + struct bulk_waiter bulk_waiter; + int pid; + struct list_head list; +}; + +struct vchiq_instance_struct { + VCHIQ_STATE_T *state; + + int connected; + + struct list_head bulk_waiter_list; + struct mutex bulk_waiter_list_mutex; +}; + +static VCHIQ_STATUS_T +vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data, + unsigned int size, VCHIQ_BULK_DIR_T dir); + +/**************************************************************************** +* +* vchiq_initialise +* +***************************************************************************/ +#define VCHIQ_INIT_RETRIES 10 +VCHIQ_STATUS_T vchiq_initialise(VCHIQ_INSTANCE_T *instanceOut) +{ + VCHIQ_STATUS_T status = VCHIQ_ERROR; + VCHIQ_STATE_T *state; + VCHIQ_INSTANCE_T instance = NULL; + int i; + + vchiq_log_trace(vchiq_core_log_level, "%s called", __func__); + + /* VideoCore may not be ready due to boot up timing. + It may never be ready if kernel and firmware are mismatched, so don't block forever. */ + for (i=0; i<VCHIQ_INIT_RETRIES; i++) { + state = vchiq_get_state(); + if (state) + break; + udelay(500); + } + if (i==VCHIQ_INIT_RETRIES) { + vchiq_log_error(vchiq_core_log_level, + "%s: videocore not initialized\n", __func__); + goto failed; + } else if (i>0) { + vchiq_log_warning(vchiq_core_log_level, + "%s: videocore initialized after %d retries\n", __func__, i); + } + + instance = kzalloc(sizeof(*instance), GFP_KERNEL); + if (!instance) { + vchiq_log_error(vchiq_core_log_level, + "%s: error allocating vchiq instance\n", __func__); + goto failed; + } + + instance->connected = 0; + instance->state = state; + mutex_init(&instance->bulk_waiter_list_mutex); + INIT_LIST_HEAD(&instance->bulk_waiter_list); + + *instanceOut = instance; + + status = VCHIQ_SUCCESS; + +failed: + vchiq_log_trace(vchiq_core_log_level, + "%s(%p): returning %d", __func__, instance, status); + + return status; +} +EXPORT_SYMBOL(vchiq_initialise); + +/**************************************************************************** +* +* vchiq_shutdown +* +***************************************************************************/ + +VCHIQ_STATUS_T vchiq_shutdown(VCHIQ_INSTANCE_T instance) +{ + VCHIQ_STATUS_T status; + VCHIQ_STATE_T *state = instance->state; + + vchiq_log_trace(vchiq_core_log_level, + "%s(%p) called", __func__, instance); + + if (mutex_lock_interruptible(&state->mutex) != 0) + return VCHIQ_RETRY; + + /* Remove all services */ + status = 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 list_head *pos, *next; + list_for_each_safe(pos, next, + &instance->bulk_waiter_list) { + struct bulk_waiter_node *waiter; + waiter = list_entry(pos, + struct bulk_waiter_node, + list); + list_del(pos); + vchiq_log_info(vchiq_arm_log_level, + "bulk_waiter - cleaned up %x " + "for pid %d", + (unsigned int)waiter, waiter->pid); + kfree(waiter); + } + kfree(instance); + } + + return status; +} +EXPORT_SYMBOL(vchiq_shutdown); + +/**************************************************************************** +* +* vchiq_is_connected +* +***************************************************************************/ + +int vchiq_is_connected(VCHIQ_INSTANCE_T instance) +{ + return instance->connected; +} + +/**************************************************************************** +* +* vchiq_connect +* +***************************************************************************/ + +VCHIQ_STATUS_T vchiq_connect(VCHIQ_INSTANCE_T instance) +{ + VCHIQ_STATUS_T status; + VCHIQ_STATE_T *state = instance->state; + + vchiq_log_trace(vchiq_core_log_level, + "%s(%p) called", __func__, instance); + + if (mutex_lock_interruptible(&state->mutex) != 0) { + vchiq_log_trace(vchiq_core_log_level, + "%s: call to mutex_lock failed", __func__); + status = VCHIQ_RETRY; + goto failed; + } + status = vchiq_connect_internal(state, instance); + + if (status == VCHIQ_SUCCESS) + instance->connected = 1; + + mutex_unlock(&state->mutex); + +failed: + vchiq_log_trace(vchiq_core_log_level, + "%s(%p): returning %d", __func__, instance, status); + + return status; +} +EXPORT_SYMBOL(vchiq_connect); + +/**************************************************************************** +* +* vchiq_add_service +* +***************************************************************************/ + +VCHIQ_STATUS_T vchiq_add_service( + VCHIQ_INSTANCE_T instance, + const VCHIQ_SERVICE_PARAMS_T *params, + VCHIQ_SERVICE_HANDLE_T *phandle) +{ + VCHIQ_STATUS_T status; + VCHIQ_STATE_T *state = instance->state; + VCHIQ_SERVICE_T *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) + ? VCHIQ_SRVSTATE_LISTENING + : VCHIQ_SRVSTATE_HIDDEN; + + service = vchiq_add_service_internal( + state, + params, + srvstate, + instance, + NULL); + + if (service) { + *phandle = service->handle; + status = VCHIQ_SUCCESS; + } else + status = VCHIQ_ERROR; + + vchiq_log_trace(vchiq_core_log_level, + "%s(%p): returning %d", __func__, instance, status); + + return status; +} +EXPORT_SYMBOL(vchiq_add_service); + +/**************************************************************************** +* +* vchiq_open_service +* +***************************************************************************/ + +VCHIQ_STATUS_T vchiq_open_service( + VCHIQ_INSTANCE_T instance, + const VCHIQ_SERVICE_PARAMS_T *params, + VCHIQ_SERVICE_HANDLE_T *phandle) +{ + VCHIQ_STATUS_T status = VCHIQ_ERROR; + VCHIQ_STATE_T *state = instance->state; + VCHIQ_SERVICE_T *service = NULL; + + vchiq_log_trace(vchiq_core_log_level, + "%s(%p) called", __func__, instance); + + *phandle = VCHIQ_SERVICE_HANDLE_INVALID; + + if (!vchiq_is_connected(instance)) + goto failed; + + service = vchiq_add_service_internal(state, + params, + VCHIQ_SRVSTATE_OPENING, + instance, + NULL); + + if (service) { + *phandle = service->handle; + status = vchiq_open_service_internal(service, current->pid); + if (status != VCHIQ_SUCCESS) { + vchiq_remove_service(service->handle); + *phandle = VCHIQ_SERVICE_HANDLE_INVALID; + } + } + +failed: + vchiq_log_trace(vchiq_core_log_level, + "%s(%p): returning %d", __func__, instance, status); + + return status; +} +EXPORT_SYMBOL(vchiq_open_service); + +VCHIQ_STATUS_T +vchiq_queue_bulk_transmit(VCHIQ_SERVICE_HANDLE_T handle, + const void *data, unsigned int size, void *userdata) +{ + return vchiq_bulk_transfer(handle, + VCHI_MEM_HANDLE_INVALID, (void *)data, size, userdata, + VCHIQ_BULK_MODE_CALLBACK, VCHIQ_BULK_TRANSMIT); +} +EXPORT_SYMBOL(vchiq_queue_bulk_transmit); + +VCHIQ_STATUS_T +vchiq_queue_bulk_receive(VCHIQ_SERVICE_HANDLE_T handle, void *data, + unsigned int size, void *userdata) +{ + return vchiq_bulk_transfer(handle, + VCHI_MEM_HANDLE_INVALID, data, size, userdata, + VCHIQ_BULK_MODE_CALLBACK, VCHIQ_BULK_RECEIVE); +} +EXPORT_SYMBOL(vchiq_queue_bulk_receive); + +VCHIQ_STATUS_T +vchiq_bulk_transmit(VCHIQ_SERVICE_HANDLE_T handle, const void *data, + unsigned int size, void *userdata, VCHIQ_BULK_MODE_T mode) +{ + VCHIQ_STATUS_T status; + + switch (mode) { + case VCHIQ_BULK_MODE_NOCALLBACK: + case VCHIQ_BULK_MODE_CALLBACK: + status = vchiq_bulk_transfer(handle, + VCHI_MEM_HANDLE_INVALID, (void *)data, size, userdata, + mode, VCHIQ_BULK_TRANSMIT); + break; + case VCHIQ_BULK_MODE_BLOCKING: + status = vchiq_blocking_bulk_transfer(handle, + (void *)data, size, VCHIQ_BULK_TRANSMIT); + break; + default: + return VCHIQ_ERROR; + } + + return status; +} +EXPORT_SYMBOL(vchiq_bulk_transmit); + +VCHIQ_STATUS_T +vchiq_bulk_receive(VCHIQ_SERVICE_HANDLE_T handle, void *data, + unsigned int size, void *userdata, VCHIQ_BULK_MODE_T mode) +{ + VCHIQ_STATUS_T status; + + switch (mode) { + case VCHIQ_BULK_MODE_NOCALLBACK: + case VCHIQ_BULK_MODE_CALLBACK: + status = vchiq_bulk_transfer(handle, + VCHI_MEM_HANDLE_INVALID, data, size, userdata, + mode, VCHIQ_BULK_RECEIVE); + break; + case VCHIQ_BULK_MODE_BLOCKING: + status = vchiq_blocking_bulk_transfer(handle, + (void *)data, size, VCHIQ_BULK_RECEIVE); + break; + default: + return VCHIQ_ERROR; + } + + return status; +} +EXPORT_SYMBOL(vchiq_bulk_receive); + +static VCHIQ_STATUS_T +vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data, + unsigned int size, VCHIQ_BULK_DIR_T dir) +{ + VCHIQ_INSTANCE_T instance; + VCHIQ_SERVICE_T *service; + VCHIQ_STATUS_T status; + struct bulk_waiter_node *waiter = NULL; + struct list_head *pos; + + service = find_service_by_handle(handle); + if (!service) + return VCHIQ_ERROR; + + instance = service->instance; + + unlock_service(service); + + mutex_lock(&instance->bulk_waiter_list_mutex); + list_for_each(pos, &instance->bulk_waiter_list) { + if (list_entry(pos, struct bulk_waiter_node, + list)->pid == current->pid) { + waiter = list_entry(pos, + struct bulk_waiter_node, + list); + list_del(pos); + break; + } + } + mutex_unlock(&instance->bulk_waiter_list_mutex); + + if (waiter) { + VCHIQ_BULK_T *bulk = waiter->bulk_waiter.bulk; + if (bulk) { + /* This thread has an outstanding bulk transfer. */ + if ((bulk->data != data) || + (bulk->size != size)) { + /* This is not a retry of the previous one. + ** Cancel the signal when the transfer + ** completes. */ + spin_lock(&bulk_waiter_spinlock); + bulk->userdata = NULL; + spin_unlock(&bulk_waiter_spinlock); + } + } + } + + if (!waiter) { + waiter = kzalloc(sizeof(struct bulk_waiter_node), GFP_KERNEL); + if (!waiter) { + vchiq_log_error(vchiq_core_log_level, + "%s - out of memory", __func__); + return VCHIQ_ERROR; + } + } + + status = vchiq_bulk_transfer(handle, VCHI_MEM_HANDLE_INVALID, + data, size, &waiter->bulk_waiter, VCHIQ_BULK_MODE_BLOCKING, + dir); + if ((status != VCHIQ_RETRY) || fatal_signal_pending(current) || + !waiter->bulk_waiter.bulk) { + VCHIQ_BULK_T *bulk = waiter->bulk_waiter.bulk; + if (bulk) { + /* Cancel the signal when the transfer + ** completes. */ + spin_lock(&bulk_waiter_spinlock); + bulk->userdata = NULL; + spin_unlock(&bulk_waiter_spinlock); + } + kfree(waiter); + } else { + waiter->pid = current->pid; + mutex_lock(&instance->bulk_waiter_list_mutex); + list_add(&waiter->list, &instance->bulk_waiter_list); + mutex_unlock(&instance->bulk_waiter_list_mutex); + vchiq_log_info(vchiq_arm_log_level, + "saved bulk_waiter %x for pid %d", + (unsigned int)waiter, current->pid); + } + + return status; +} diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_killable.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_killable.h new file mode 100644 index 0000000..335446e --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_killable.h @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHIQ_KILLABLE_H +#define VCHIQ_KILLABLE_H + +#include <linux/mutex.h> +#include <linux/semaphore.h> + +#define SHUTDOWN_SIGS (sigmask(SIGKILL) | sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGTRAP) | sigmask(SIGSTOP) | sigmask(SIGCONT)) + +static inline int __must_check down_interruptible_killable(struct semaphore *sem) +{ + /* Allow interception of killable signals only. We don't want to be interrupted by harmless signals like SIGALRM */ + int ret; + sigset_t blocked, oldset; + siginitsetinv(&blocked, SHUTDOWN_SIGS); + sigprocmask(SIG_SETMASK, &blocked, &oldset); + ret = down_interruptible(sem); + sigprocmask(SIG_SETMASK, &oldset, NULL); + return ret; +} +#define down_interruptible down_interruptible_killable + + +static inline int __must_check mutex_lock_interruptible_killable(struct mutex *lock) +{ + /* Allow interception of killable signals only. We don't want to be interrupted by harmless signals like SIGALRM */ + int ret; + sigset_t blocked, oldset; + siginitsetinv(&blocked, SHUTDOWN_SIGS); + sigprocmask(SIG_SETMASK, &blocked, &oldset); + ret = mutex_lock_interruptible(lock); + sigprocmask(SIG_SETMASK, &oldset, NULL); + return ret; +} +#define mutex_lock_interruptible mutex_lock_interruptible_killable + +#endif diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_memdrv.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_memdrv.h new file mode 100644 index 0000000..d02e776 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_memdrv.h @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHIQ_MEMDRV_H +#define VCHIQ_MEMDRV_H + +/* ---- Include Files ----------------------------------------------------- */ + +#include <linux/kernel.h> +#include "vchiq_if.h" + +/* ---- Constants and Types ---------------------------------------------- */ + +typedef struct { + void *armSharedMemVirt; + dma_addr_t armSharedMemPhys; + size_t armSharedMemSize; + + void *vcSharedMemVirt; + dma_addr_t vcSharedMemPhys; + size_t vcSharedMemSize; +} VCHIQ_SHARED_MEM_INFO_T; + +/* ---- Variable Externs ------------------------------------------------- */ + +/* ---- Function Prototypes ---------------------------------------------- */ + +void vchiq_get_shared_mem_info(VCHIQ_SHARED_MEM_INFO_T *info); + +VCHIQ_STATUS_T vchiq_memdrv_initialise(void); + +VCHIQ_STATUS_T vchiq_userdrv_create_instance( + const VCHIQ_PLATFORM_DATA_T * platform_data); + +VCHIQ_STATUS_T vchiq_userdrv_suspend( + const VCHIQ_PLATFORM_DATA_T * platform_data); + +VCHIQ_STATUS_T vchiq_userdrv_resume( + const VCHIQ_PLATFORM_DATA_T * platform_data); + +#endif diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_pagelist.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_pagelist.h new file mode 100644 index 0000000..54a3ece --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_pagelist.h @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHIQ_PAGELIST_H +#define VCHIQ_PAGELIST_H + +#ifndef PAGE_SIZE +#define PAGE_SIZE 4096 +#endif +#define CACHE_LINE_SIZE 32 +#define PAGELIST_WRITE 0 +#define PAGELIST_READ 1 +#define PAGELIST_READ_WITH_FRAGMENTS 2 + +typedef struct pagelist_struct { + unsigned long length; + unsigned short type; + unsigned short offset; + unsigned long addrs[1]; /* N.B. 12 LSBs hold the number of following + pages at consecutive addresses. */ +} PAGELIST_T; + +typedef struct fragments_struct { + char headbuf[CACHE_LINE_SIZE]; + char tailbuf[CACHE_LINE_SIZE]; +} FRAGMENTS_T; + +#endif /* VCHIQ_PAGELIST_H */ diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c new file mode 100644 index 0000000..8072ff6 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c @@ -0,0 +1,860 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include <linux/module.h> +#include <linux/types.h> + +#include "interface/vchi/vchi.h" +#include "vchiq.h" +#include "vchiq_core.h" + +#include "vchiq_util.h" + +#include <stddef.h> + +#define vchiq_status_to_vchi(status) ((int32_t)status) + +typedef struct { + VCHIQ_SERVICE_HANDLE_T handle; + + VCHIU_QUEUE_T queue; + + VCHI_CALLBACK_T callback; + void *callback_param; +} SHIM_SERVICE_T; + +/* ---------------------------------------------------------------------- + * return pointer to the mphi message driver function table + * -------------------------------------------------------------------- */ +const VCHI_MESSAGE_DRIVER_T * +vchi_mphi_message_driver_func_table(void) +{ + return NULL; +} + +/* ---------------------------------------------------------------------- + * return a pointer to the 'single' connection driver fops + * -------------------------------------------------------------------- */ +const VCHI_CONNECTION_API_T * +single_get_func_table(void) +{ + return NULL; +} + +VCHI_CONNECTION_T *vchi_create_connection( + const VCHI_CONNECTION_API_T *function_table, + const VCHI_MESSAGE_DRIVER_T *low_level) +{ + (void)function_table; + (void)low_level; + return NULL; +} + +/*********************************************************** + * Name: vchi_msg_peek + * + * Arguments: const VCHI_SERVICE_HANDLE_T handle, + * void **data, + * uint32_t *msg_size, + + + * VCHI_FLAGS_T flags + * + * Description: Routine to return a pointer to the current message (to allow in + * place processing). The message can be removed using + * vchi_msg_remove when you're finished + * + * Returns: int32_t - success == 0 + * + ***********************************************************/ +int32_t vchi_msg_peek(VCHI_SERVICE_HANDLE_T handle, + void **data, + uint32_t *msg_size, + VCHI_FLAGS_T flags) +{ + SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; + VCHIQ_HEADER_T *header; + + WARN_ON((flags != VCHI_FLAGS_NONE) && + (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE)); + + if (flags == VCHI_FLAGS_NONE) + if (vchiu_queue_is_empty(&service->queue)) + return -1; + + header = vchiu_queue_peek(&service->queue); + + *data = header->data; + *msg_size = header->size; + + return 0; +} +EXPORT_SYMBOL(vchi_msg_peek); + +/*********************************************************** + * Name: vchi_msg_remove + * + * Arguments: const VCHI_SERVICE_HANDLE_T handle, + * + * Description: Routine to remove a message (after it has been read with + * vchi_msg_peek) + * + * Returns: int32_t - success == 0 + * + ***********************************************************/ +int32_t vchi_msg_remove(VCHI_SERVICE_HANDLE_T handle) +{ + SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; + VCHIQ_HEADER_T *header; + + header = vchiu_queue_pop(&service->queue); + + vchiq_release_message(service->handle, header); + + return 0; +} +EXPORT_SYMBOL(vchi_msg_remove); + +/*********************************************************** + * Name: vchi_msg_queue + * + * Arguments: VCHI_SERVICE_HANDLE_T handle, + * const void *data, + * uint32_t data_size, + * VCHI_FLAGS_T flags, + * void *msg_handle, + * + * Description: Thin wrapper to queue a message onto a connection + * + * Returns: int32_t - success == 0 + * + ***********************************************************/ +int32_t vchi_msg_queue(VCHI_SERVICE_HANDLE_T handle, + const void *data, + uint32_t data_size, + VCHI_FLAGS_T flags, + void *msg_handle) +{ + SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; + VCHIQ_ELEMENT_T element = {data, data_size}; + VCHIQ_STATUS_T status; + + (void)msg_handle; + + WARN_ON(flags != VCHI_FLAGS_BLOCK_UNTIL_QUEUED); + + status = vchiq_queue_message(service->handle, &element, 1); + + /* vchiq_queue_message() may return VCHIQ_RETRY, so we need to + ** implement a retry mechanism since this function is supposed + ** to block until queued + */ + while (status == VCHIQ_RETRY) { + msleep(1); + status = vchiq_queue_message(service->handle, &element, 1); + } + + return vchiq_status_to_vchi(status); +} +EXPORT_SYMBOL(vchi_msg_queue); + +/*********************************************************** + * Name: vchi_bulk_queue_receive + * + * Arguments: VCHI_BULK_HANDLE_T handle, + * void *data_dst, + * const uint32_t data_size, + * VCHI_FLAGS_T flags + * void *bulk_handle + * + * Description: Routine to setup a rcv buffer + * + * Returns: int32_t - success == 0 + * + ***********************************************************/ +int32_t vchi_bulk_queue_receive(VCHI_SERVICE_HANDLE_T handle, + void *data_dst, + uint32_t data_size, + VCHI_FLAGS_T flags, + void *bulk_handle) +{ + SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; + VCHIQ_BULK_MODE_T mode; + VCHIQ_STATUS_T status; + + switch ((int)flags) { + case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE + | VCHI_FLAGS_BLOCK_UNTIL_QUEUED: + WARN_ON(!service->callback); + mode = VCHIQ_BULK_MODE_CALLBACK; + break; + case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE: + mode = VCHIQ_BULK_MODE_BLOCKING; + break; + case VCHI_FLAGS_BLOCK_UNTIL_QUEUED: + case VCHI_FLAGS_NONE: + mode = VCHIQ_BULK_MODE_NOCALLBACK; + break; + default: + WARN(1, "unsupported message\n"); + return vchiq_status_to_vchi(VCHIQ_ERROR); + } + + status = vchiq_bulk_receive(service->handle, data_dst, data_size, + bulk_handle, mode); + + /* vchiq_bulk_receive() may return VCHIQ_RETRY, so we need to + ** implement a retry mechanism since this function is supposed + ** to block until queued + */ + while (status == VCHIQ_RETRY) { + msleep(1); + status = vchiq_bulk_receive(service->handle, data_dst, + data_size, bulk_handle, mode); + } + + return vchiq_status_to_vchi(status); +} +EXPORT_SYMBOL(vchi_bulk_queue_receive); + +/*********************************************************** + * Name: vchi_bulk_queue_transmit + * + * Arguments: VCHI_BULK_HANDLE_T handle, + * const void *data_src, + * uint32_t data_size, + * VCHI_FLAGS_T flags, + * void *bulk_handle + * + * Description: Routine to transmit some data + * + * Returns: int32_t - success == 0 + * + ***********************************************************/ +int32_t vchi_bulk_queue_transmit(VCHI_SERVICE_HANDLE_T handle, + const void *data_src, + uint32_t data_size, + VCHI_FLAGS_T flags, + void *bulk_handle) +{ + SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; + VCHIQ_BULK_MODE_T mode; + VCHIQ_STATUS_T status; + + switch ((int)flags) { + case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE + | VCHI_FLAGS_BLOCK_UNTIL_QUEUED: + WARN_ON(!service->callback); + mode = VCHIQ_BULK_MODE_CALLBACK; + break; + case VCHI_FLAGS_BLOCK_UNTIL_DATA_READ: + case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE: + mode = VCHIQ_BULK_MODE_BLOCKING; + break; + case VCHI_FLAGS_BLOCK_UNTIL_QUEUED: + case VCHI_FLAGS_NONE: + mode = VCHIQ_BULK_MODE_NOCALLBACK; + break; + default: + WARN(1, "unsupported message\n"); + return vchiq_status_to_vchi(VCHIQ_ERROR); + } + + status = vchiq_bulk_transmit(service->handle, data_src, data_size, + bulk_handle, mode); + + /* vchiq_bulk_transmit() may return VCHIQ_RETRY, so we need to + ** implement a retry mechanism since this function is supposed + ** to block until queued + */ + while (status == VCHIQ_RETRY) { + msleep(1); + status = vchiq_bulk_transmit(service->handle, data_src, + data_size, bulk_handle, mode); + } + + return vchiq_status_to_vchi(status); +} +EXPORT_SYMBOL(vchi_bulk_queue_transmit); + +/*********************************************************** + * Name: vchi_msg_dequeue + * + * Arguments: VCHI_SERVICE_HANDLE_T handle, + * void *data, + * uint32_t max_data_size_to_read, + * uint32_t *actual_msg_size + * VCHI_FLAGS_T flags + * + * Description: Routine to dequeue a message into the supplied buffer + * + * Returns: int32_t - success == 0 + * + ***********************************************************/ +int32_t vchi_msg_dequeue(VCHI_SERVICE_HANDLE_T handle, + void *data, + uint32_t max_data_size_to_read, + uint32_t *actual_msg_size, + VCHI_FLAGS_T flags) +{ + SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; + VCHIQ_HEADER_T *header; + + WARN_ON((flags != VCHI_FLAGS_NONE) && + (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE)); + + if (flags == VCHI_FLAGS_NONE) + if (vchiu_queue_is_empty(&service->queue)) + return -1; + + header = vchiu_queue_pop(&service->queue); + + memcpy(data, header->data, header->size < max_data_size_to_read ? + header->size : max_data_size_to_read); + + *actual_msg_size = header->size; + + vchiq_release_message(service->handle, header); + + return 0; +} +EXPORT_SYMBOL(vchi_msg_dequeue); + +/*********************************************************** + * Name: vchi_msg_queuev + * + * Arguments: VCHI_SERVICE_HANDLE_T handle, + * VCHI_MSG_VECTOR_T *vector, + * uint32_t count, + * VCHI_FLAGS_T flags, + * void *msg_handle + * + * Description: Thin wrapper to queue a message onto a connection + * + * Returns: int32_t - success == 0 + * + ***********************************************************/ + +vchiq_static_assert(sizeof(VCHI_MSG_VECTOR_T) == sizeof(VCHIQ_ELEMENT_T)); +vchiq_static_assert(offsetof(VCHI_MSG_VECTOR_T, vec_base) == + offsetof(VCHIQ_ELEMENT_T, data)); +vchiq_static_assert(offsetof(VCHI_MSG_VECTOR_T, vec_len) == + offsetof(VCHIQ_ELEMENT_T, size)); + +int32_t vchi_msg_queuev(VCHI_SERVICE_HANDLE_T handle, + VCHI_MSG_VECTOR_T *vector, + uint32_t count, + VCHI_FLAGS_T flags, + void *msg_handle) +{ + SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; + + (void)msg_handle; + + WARN_ON(flags != VCHI_FLAGS_BLOCK_UNTIL_QUEUED); + + return vchiq_status_to_vchi(vchiq_queue_message(service->handle, + (const VCHIQ_ELEMENT_T *)vector, count)); +} +EXPORT_SYMBOL(vchi_msg_queuev); + +/*********************************************************** + * Name: vchi_held_msg_release + * + * Arguments: VCHI_HELD_MSG_T *message + * + * Description: Routine to release a held message (after it has been read with + * vchi_msg_hold) + * + * Returns: int32_t - success == 0 + * + ***********************************************************/ +int32_t vchi_held_msg_release(VCHI_HELD_MSG_T *message) +{ + vchiq_release_message((VCHIQ_SERVICE_HANDLE_T)message->service, + (VCHIQ_HEADER_T *)message->message); + + return 0; +} +EXPORT_SYMBOL(vchi_held_msg_release); + +/*********************************************************** + * Name: vchi_msg_hold + * + * Arguments: VCHI_SERVICE_HANDLE_T handle, + * void **data, + * uint32_t *msg_size, + * VCHI_FLAGS_T flags, + * VCHI_HELD_MSG_T *message_handle + * + * Description: Routine to return a pointer to the current message (to allow + * in place processing). The message is dequeued - don't forget + * to release the message using vchi_held_msg_release when you're + * finished. + * + * Returns: int32_t - success == 0 + * + ***********************************************************/ +int32_t vchi_msg_hold(VCHI_SERVICE_HANDLE_T handle, + void **data, + uint32_t *msg_size, + VCHI_FLAGS_T flags, + VCHI_HELD_MSG_T *message_handle) +{ + SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; + VCHIQ_HEADER_T *header; + + WARN_ON((flags != VCHI_FLAGS_NONE) && + (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE)); + + if (flags == VCHI_FLAGS_NONE) + if (vchiu_queue_is_empty(&service->queue)) + return -1; + + header = vchiu_queue_pop(&service->queue); + + *data = header->data; + *msg_size = header->size; + + message_handle->service = + (struct opaque_vchi_service_t *)service->handle; + message_handle->message = header; + + return 0; +} +EXPORT_SYMBOL(vchi_msg_hold); + +/*********************************************************** + * Name: vchi_initialise + * + * Arguments: VCHI_INSTANCE_T *instance_handle + * + * Description: Initialises the hardware but does not transmit anything + * When run as a Host App this will be called twice hence the need + * to malloc the state information + * + * Returns: 0 if successful, failure otherwise + * + ***********************************************************/ + +int32_t vchi_initialise(VCHI_INSTANCE_T *instance_handle) +{ + VCHIQ_INSTANCE_T instance; + VCHIQ_STATUS_T status; + + status = vchiq_initialise(&instance); + + *instance_handle = (VCHI_INSTANCE_T)instance; + + return vchiq_status_to_vchi(status); +} +EXPORT_SYMBOL(vchi_initialise); + +/*********************************************************** + * Name: vchi_connect + * + * Arguments: VCHI_CONNECTION_T **connections + * const uint32_t num_connections + * VCHI_INSTANCE_T instance_handle) + * + * Description: Starts the command service on each connection, + * causing INIT messages to be pinged back and forth + * + * Returns: 0 if successful, failure otherwise + * + ***********************************************************/ +int32_t vchi_connect(VCHI_CONNECTION_T **connections, + const uint32_t num_connections, + VCHI_INSTANCE_T instance_handle) +{ + VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; + + (void)connections; + (void)num_connections; + + return vchiq_connect(instance); +} +EXPORT_SYMBOL(vchi_connect); + + +/*********************************************************** + * Name: vchi_disconnect + * + * Arguments: VCHI_INSTANCE_T instance_handle + * + * Description: Stops the command service on each connection, + * causing DE-INIT messages to be pinged back and forth + * + * Returns: 0 if successful, failure otherwise + * + ***********************************************************/ +int32_t vchi_disconnect(VCHI_INSTANCE_T instance_handle) +{ + VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; + return vchiq_status_to_vchi(vchiq_shutdown(instance)); +} +EXPORT_SYMBOL(vchi_disconnect); + + +/*********************************************************** + * Name: vchi_service_open + * Name: vchi_service_create + * + * Arguments: VCHI_INSTANCE_T *instance_handle + * SERVICE_CREATION_T *setup, + * VCHI_SERVICE_HANDLE_T *handle + * + * Description: Routine to open a service + * + * Returns: int32_t - success == 0 + * + ***********************************************************/ + +static VCHIQ_STATUS_T shim_callback(VCHIQ_REASON_T reason, + VCHIQ_HEADER_T *header, VCHIQ_SERVICE_HANDLE_T handle, void *bulk_user) +{ + SHIM_SERVICE_T *service = + (SHIM_SERVICE_T *)VCHIQ_GET_SERVICE_USERDATA(handle); + + if (!service->callback) + goto release; + + switch (reason) { + case VCHIQ_MESSAGE_AVAILABLE: + vchiu_queue_push(&service->queue, header); + + service->callback(service->callback_param, + VCHI_CALLBACK_MSG_AVAILABLE, NULL); + + goto done; + break; + + case VCHIQ_BULK_TRANSMIT_DONE: + service->callback(service->callback_param, + VCHI_CALLBACK_BULK_SENT, bulk_user); + break; + + case VCHIQ_BULK_RECEIVE_DONE: + service->callback(service->callback_param, + VCHI_CALLBACK_BULK_RECEIVED, bulk_user); + break; + + case VCHIQ_SERVICE_CLOSED: + service->callback(service->callback_param, + VCHI_CALLBACK_SERVICE_CLOSED, NULL); + break; + + case VCHIQ_SERVICE_OPENED: + /* No equivalent VCHI reason */ + break; + + case VCHIQ_BULK_TRANSMIT_ABORTED: + service->callback(service->callback_param, + VCHI_CALLBACK_BULK_TRANSMIT_ABORTED, + bulk_user); + break; + + case VCHIQ_BULK_RECEIVE_ABORTED: + service->callback(service->callback_param, + VCHI_CALLBACK_BULK_RECEIVE_ABORTED, + bulk_user); + break; + + default: + WARN(1, "not supported\n"); + break; + } + +release: + vchiq_release_message(service->handle, header); +done: + return VCHIQ_SUCCESS; +} + +static SHIM_SERVICE_T *service_alloc(VCHIQ_INSTANCE_T instance, + SERVICE_CREATION_T *setup) +{ + SHIM_SERVICE_T *service = kzalloc(sizeof(SHIM_SERVICE_T), GFP_KERNEL); + + (void)instance; + + if (service) { + if (vchiu_queue_init(&service->queue, 64)) { + service->callback = setup->callback; + service->callback_param = setup->callback_param; + } else { + kfree(service); + service = NULL; + } + } + + return service; +} + +static void service_free(SHIM_SERVICE_T *service) +{ + if (service) { + vchiu_queue_delete(&service->queue); + kfree(service); + } +} + +int32_t vchi_service_open(VCHI_INSTANCE_T instance_handle, + SERVICE_CREATION_T *setup, + VCHI_SERVICE_HANDLE_T *handle) +{ + VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; + SHIM_SERVICE_T *service = service_alloc(instance, setup); + + *handle = (VCHI_SERVICE_HANDLE_T)service; + + if (service) { + VCHIQ_SERVICE_PARAMS_T params; + VCHIQ_STATUS_T status; + + memset(¶ms, 0, sizeof(params)); + params.fourcc = setup->service_id; + params.callback = shim_callback; + params.userdata = service; + params.version = setup->version.version; + params.version_min = setup->version.version_min; + + status = vchiq_open_service(instance, ¶ms, + &service->handle); + if (status != VCHIQ_SUCCESS) { + service_free(service); + service = NULL; + *handle = NULL; + } + } + + return (service != NULL) ? 0 : -1; +} +EXPORT_SYMBOL(vchi_service_open); + +int32_t vchi_service_create(VCHI_INSTANCE_T instance_handle, + SERVICE_CREATION_T *setup, + VCHI_SERVICE_HANDLE_T *handle) +{ + VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; + SHIM_SERVICE_T *service = service_alloc(instance, setup); + + *handle = (VCHI_SERVICE_HANDLE_T)service; + + if (service) { + VCHIQ_SERVICE_PARAMS_T params; + VCHIQ_STATUS_T status; + + memset(¶ms, 0, sizeof(params)); + params.fourcc = setup->service_id; + params.callback = shim_callback; + params.userdata = service; + params.version = setup->version.version; + params.version_min = setup->version.version_min; + status = vchiq_add_service(instance, ¶ms, &service->handle); + + if (status != VCHIQ_SUCCESS) { + service_free(service); + service = NULL; + *handle = NULL; + } + } + + return (service != NULL) ? 0 : -1; +} +EXPORT_SYMBOL(vchi_service_create); + +int32_t vchi_service_close(const VCHI_SERVICE_HANDLE_T handle) +{ + int32_t ret = -1; + SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; + if (service) { + VCHIQ_STATUS_T status = vchiq_close_service(service->handle); + if (status == VCHIQ_SUCCESS) { + service_free(service); + service = NULL; + } + + ret = vchiq_status_to_vchi(status); + } + return ret; +} +EXPORT_SYMBOL(vchi_service_close); + +int32_t vchi_service_destroy(const VCHI_SERVICE_HANDLE_T handle) +{ + int32_t ret = -1; + SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; + if (service) { + VCHIQ_STATUS_T status = vchiq_remove_service(service->handle); + if (status == VCHIQ_SUCCESS) { + service_free(service); + service = NULL; + } + + ret = vchiq_status_to_vchi(status); + } + return ret; +} +EXPORT_SYMBOL(vchi_service_destroy); + +int32_t vchi_service_set_option(const VCHI_SERVICE_HANDLE_T handle, + VCHI_SERVICE_OPTION_T option, + int value) +{ + int32_t ret = -1; + SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; + VCHIQ_SERVICE_OPTION_T vchiq_option; + switch (option) { + case VCHI_SERVICE_OPTION_TRACE: + vchiq_option = VCHIQ_SERVICE_OPTION_TRACE; + break; + case VCHI_SERVICE_OPTION_SYNCHRONOUS: + vchiq_option = VCHIQ_SERVICE_OPTION_SYNCHRONOUS; + break; + default: + service = NULL; + break; + } + if (service) { + VCHIQ_STATUS_T status = + vchiq_set_service_option(service->handle, + vchiq_option, + value); + + ret = vchiq_status_to_vchi(status); + } + return ret; +} +EXPORT_SYMBOL(vchi_service_set_option); + +int32_t vchi_get_peer_version( const VCHI_SERVICE_HANDLE_T handle, short *peer_version ) +{ + int32_t ret = -1; + SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; + if(service) + { + VCHIQ_STATUS_T status = vchiq_get_peer_version(service->handle, peer_version); + ret = vchiq_status_to_vchi( status ); + } + return ret; +} +EXPORT_SYMBOL(vchi_get_peer_version); + +/* ---------------------------------------------------------------------- + * read a uint32_t from buffer. + * network format is defined to be little endian + * -------------------------------------------------------------------- */ +uint32_t +vchi_readbuf_uint32(const void *_ptr) +{ + const unsigned char *ptr = _ptr; + return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24); +} + +/* ---------------------------------------------------------------------- + * write a uint32_t to buffer. + * network format is defined to be little endian + * -------------------------------------------------------------------- */ +void +vchi_writebuf_uint32(void *_ptr, uint32_t value) +{ + unsigned char *ptr = _ptr; + ptr[0] = (unsigned char)((value >> 0) & 0xFF); + ptr[1] = (unsigned char)((value >> 8) & 0xFF); + ptr[2] = (unsigned char)((value >> 16) & 0xFF); + ptr[3] = (unsigned char)((value >> 24) & 0xFF); +} + +/* ---------------------------------------------------------------------- + * read a uint16_t from buffer. + * network format is defined to be little endian + * -------------------------------------------------------------------- */ +uint16_t +vchi_readbuf_uint16(const void *_ptr) +{ + const unsigned char *ptr = _ptr; + return ptr[0] | (ptr[1] << 8); +} + +/* ---------------------------------------------------------------------- + * write a uint16_t into the buffer. + * network format is defined to be little endian + * -------------------------------------------------------------------- */ +void +vchi_writebuf_uint16(void *_ptr, uint16_t value) +{ + unsigned char *ptr = _ptr; + ptr[0] = (value >> 0) & 0xFF; + ptr[1] = (value >> 8) & 0xFF; +} + +/*********************************************************** + * Name: vchi_service_use + * + * Arguments: const VCHI_SERVICE_HANDLE_T handle + * + * Description: Routine to increment refcount on a service + * + * Returns: void + * + ***********************************************************/ +int32_t vchi_service_use(const VCHI_SERVICE_HANDLE_T handle) +{ + int32_t ret = -1; + SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; + if (service) + ret = vchiq_status_to_vchi(vchiq_use_service(service->handle)); + return ret; +} +EXPORT_SYMBOL(vchi_service_use); + +/*********************************************************** + * Name: vchi_service_release + * + * Arguments: const VCHI_SERVICE_HANDLE_T handle + * + * Description: Routine to decrement refcount on a service + * + * Returns: void + * + ***********************************************************/ +int32_t vchi_service_release(const VCHI_SERVICE_HANDLE_T handle) +{ + int32_t ret = -1; + SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; + if (service) + ret = vchiq_status_to_vchi( + vchiq_release_service(service->handle)); + return ret; +} +EXPORT_SYMBOL(vchi_service_release); diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c new file mode 100644 index 0000000..384acb8 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c @@ -0,0 +1,156 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "vchiq_util.h" +#include "vchiq_killable.h" + +static inline int is_pow2(int i) +{ + return i && !(i & (i - 1)); +} + +int vchiu_queue_init(VCHIU_QUEUE_T *queue, int size) +{ + WARN_ON(!is_pow2(size)); + + queue->size = size; + queue->read = 0; + queue->write = 0; + queue->initialized = 1; + + sema_init(&queue->pop, 0); + sema_init(&queue->push, 0); + + queue->storage = kzalloc(size * sizeof(VCHIQ_HEADER_T *), GFP_KERNEL); + if (queue->storage == NULL) { + vchiu_queue_delete(queue); + return 0; + } + return 1; +} + +void vchiu_queue_delete(VCHIU_QUEUE_T *queue) +{ + if (queue->storage != NULL) + kfree(queue->storage); +} + +int vchiu_queue_is_empty(VCHIU_QUEUE_T *queue) +{ + return queue->read == queue->write; +} + +int vchiu_queue_is_full(VCHIU_QUEUE_T *queue) +{ + return queue->write == queue->read + queue->size; +} + +void vchiu_queue_push(VCHIU_QUEUE_T *queue, VCHIQ_HEADER_T *header) +{ + if (!queue->initialized) + return; + + while (queue->write == queue->read + queue->size) { + if (down_interruptible(&queue->pop) != 0) { + flush_signals(current); + } + } + + /* + * Write to queue->storage must be visible after read from + * queue->read + */ + smp_mb(); + + queue->storage[queue->write & (queue->size - 1)] = header; + + /* + * Write to queue->storage must be visible before write to + * queue->write + */ + smp_wmb(); + + queue->write++; + + up(&queue->push); +} + +VCHIQ_HEADER_T *vchiu_queue_peek(VCHIU_QUEUE_T *queue) +{ + while (queue->write == queue->read) { + if (down_interruptible(&queue->push) != 0) { + flush_signals(current); + } + } + + up(&queue->push); // We haven't removed anything from the queue. + + /* + * Read from queue->storage must be visible after read from + * queue->write + */ + smp_rmb(); + + return queue->storage[queue->read & (queue->size - 1)]; +} + +VCHIQ_HEADER_T *vchiu_queue_pop(VCHIU_QUEUE_T *queue) +{ + VCHIQ_HEADER_T *header; + + while (queue->write == queue->read) { + if (down_interruptible(&queue->push) != 0) { + flush_signals(current); + } + } + + /* + * Read from queue->storage must be visible after read from + * queue->write + */ + smp_rmb(); + + header = queue->storage[queue->read & (queue->size - 1)]; + + /* + * Read from queue->storage must be visible before write to + * queue->read + */ + smp_mb(); + + queue->read++; + + up(&queue->pop); + + return header; +} diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.h new file mode 100644 index 0000000..4055d4b --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.h @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VCHIQ_UTIL_H +#define VCHIQ_UTIL_H + +#include <linux/types.h> +#include <linux/semaphore.h> +#include <linux/mutex.h> +#include <linux/bitops.h> +#include <linux/kthread.h> +#include <linux/wait.h> +#include <linux/vmalloc.h> +#include <linux/jiffies.h> +#include <linux/delay.h> +#include <linux/string.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/random.h> +#include <linux/sched.h> +#include <linux/ctype.h> +#include <linux/uaccess.h> +#include <linux/time.h> /* for time_t */ +#include <linux/slab.h> +#include <linux/vmalloc.h> + +#include "vchiq_if.h" + +typedef struct { + int size; + int read; + int write; + int initialized; + + struct semaphore pop; + struct semaphore push; + + VCHIQ_HEADER_T **storage; +} VCHIU_QUEUE_T; + +extern int vchiu_queue_init(VCHIU_QUEUE_T *queue, int size); +extern void vchiu_queue_delete(VCHIU_QUEUE_T *queue); + +extern int vchiu_queue_is_empty(VCHIU_QUEUE_T *queue); +extern int vchiu_queue_is_full(VCHIU_QUEUE_T *queue); + +extern void vchiu_queue_push(VCHIU_QUEUE_T *queue, VCHIQ_HEADER_T *header); + +extern VCHIQ_HEADER_T *vchiu_queue_peek(VCHIU_QUEUE_T *queue); +extern VCHIQ_HEADER_T *vchiu_queue_pop(VCHIU_QUEUE_T *queue); + +#endif diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_version.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_version.c new file mode 100644 index 0000000..b6bfa21 --- /dev/null +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_version.c @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "vchiq_build_info.h" +#include <linux/broadcom/vc_debug_sym.h> + +VC_DEBUG_DECLARE_STRING_VAR( vchiq_build_hostname, "dc4-arm-01" ); +VC_DEBUG_DECLARE_STRING_VAR( vchiq_build_version, "9245b4c35b99b3870e1f7dc598c5692b3c66a6f0 (tainted)" ); +VC_DEBUG_DECLARE_STRING_VAR( vchiq_build_time, __TIME__ ); +VC_DEBUG_DECLARE_STRING_VAR( vchiq_build_date, __DATE__ ); + +const char *vchiq_get_build_hostname( void ) +{ + return vchiq_build_hostname; +} + +const char *vchiq_get_build_version( void ) +{ + return vchiq_build_version; +} + +const char *vchiq_get_build_date( void ) +{ + return vchiq_build_date; +} + +const char *vchiq_get_build_time( void ) +{ + return vchiq_build_time; +} -- cgit v0.10.2 From 85a42dc8676c2ea15fb44715eef85a7a419254a0 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva <rmfrfs@gmail.com> Date: Fri, 30 Sep 2016 19:24:31 +0100 Subject: staging: greybus: sdio: fix cmd_flags check for none response When checking for command flags field if response is not available we really need to compare it with the right define and not bitwise AND it. smatch warn: drivers/staging/greybus/sdio.c:481 gb_sdio_command() warn: bitwise AND condition is false here Reported-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Rui Miguel Silva <rmfrfs@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index c7133b1..5649ef1 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -478,7 +478,7 @@ static int gb_sdio_command(struct gb_sdio_host *host, struct mmc_command *cmd) goto out; /* no response expected */ - if (cmd_flags & GB_SDIO_RSP_NONE) + if (cmd_flags == GB_SDIO_RSP_NONE) goto out; /* long response expected */ -- cgit v0.10.2 From 3855eeec1a47cace93acd5ff89fb3c9bd593d307 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva <rmfrfs@gmail.com> Date: Fri, 30 Sep 2016 19:24:32 +0100 Subject: staging: greybus: light: fix attributes allocation Fix allocation of attributes with the correct size, this also fix smatch warning: drivers/staging/greybus/light.c:293 channel_attr_groups_set() warn: double check that we're allocating correct size: 8 vs 16 Signed-off-by: Rui Miguel Silva <rmfrfs@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index b2847fe..f3cd485 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -290,8 +290,7 @@ static int channel_attr_groups_set(struct gb_channel *channel, return 0; /* Set attributes based in the channel flags */ - channel->attrs = kcalloc(size + 1, sizeof(**channel->attrs), - GFP_KERNEL); + channel->attrs = kcalloc(size + 1, sizeof(*channel->attrs), GFP_KERNEL); if (!channel->attrs) return -ENOMEM; channel->attr_group = kcalloc(1, sizeof(*channel->attr_group), -- cgit v0.10.2 From dc875c77900dba5d177f9219492fd60c046feec8 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva <rmfrfs@gmail.com> Date: Fri, 30 Sep 2016 19:24:33 +0100 Subject: staging: greybus: light: check delay_{on|off} before use Even though we trust leds core that the pointers should be valid, we are safer to check delay_{on|off} before use. Also, this avoid a smatch warning: drivers/staging/greybus/light.c:484 gb_blink_set() warn: variable dereferenced before check 'delay_on' (see line 476) Signed-off-by: Rui Miguel Silva <rmfrfs@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index f3cd485..80dc4a9 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -463,6 +463,9 @@ static int gb_blink_set(struct led_classdev *cdev, unsigned long *delay_on, if (channel->releasing) return -ESHUTDOWN; + if (!delay_on || !delay_off) + return -EINVAL; + mutex_lock(&channel->lock); ret = gb_pm_runtime_get_sync(bundle); if (ret < 0) -- cgit v0.10.2 From 544a69443bf069fa52b1b3b5e25b682b710210f5 Mon Sep 17 00:00:00 2001 From: Mark Greer <mgreer@animalcreek.com> Date: Wed, 28 Sep 2016 09:34:49 -0700 Subject: staging: greybus: Add remaining audio files to maintained list Some Greybus Audio Device Class Protocol driver files are missing in the MAINTAINERS file even though they are maintained so add them. CC: Vaibhav Agarwal <vaibhav.sr@gmail.com> Signed-off-by: Mark Greer <mgreer@animalcreek.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/MAINTAINERS b/MAINTAINERS index 15c98ad..d408b16 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5301,7 +5301,16 @@ GREYBUS AUDIO PROTOCOLS DRIVERS M: Vaibhav Agarwal <vaibhav.sr@gmail.com> M: Mark Greer <mgreer@animalcreek.com> S: Maintained +F: drivers/staging/greybus/audio_apbridgea.c +F: drivers/staging/greybus/audio_apbridgea.h F: drivers/staging/greybus/audio_codec.c +F: drivers/staging/greybus/audio_codec.h +F: drivers/staging/greybus/audio_gb.c +F: drivers/staging/greybus/audio_manager.c +F: drivers/staging/greybus/audio_manager.h +F: drivers/staging/greybus/audio_manager_module.c +F: drivers/staging/greybus/audio_manager_private.h +F: drivers/staging/greybus/audio_manager_sysfs.c F: drivers/staging/greybus/audio_module.c F: drivers/staging/greybus/audio_topology.c -- cgit v0.10.2 From 5cf62679153ed7014d6952bb6a5094b3ee31428d Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva <rmfrfs@gmail.com> Date: Fri, 30 Sep 2016 18:26:55 +0100 Subject: staging: greybus: light: check the correct value of delay_on When checking the value of delay_on to set the channel as active, it was checked the pointer and not the value, as it should be. Fixes: cc43368a3c ("greybus: lights: Control runtime pm suspend/resume on AP side") Signed-off-by: Rui Miguel Silva <rmfrfs@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index 80dc4a9..8dffd8a 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -483,7 +483,7 @@ static int gb_blink_set(struct led_classdev *cdev, unsigned long *delay_on, if (ret < 0) goto out_pm_put; - if (delay_on) + if (*delay_on) channel->active = true; else channel->active = false; -- cgit v0.10.2 From 35e4d8ca05e87d38fb160cb35ba7c3282192a77b Mon Sep 17 00:00:00 2001 From: Elizabeth Ferdman <gnudevliz@gmail.com> Date: Wed, 28 Sep 2016 14:33:51 -0700 Subject: staging: sm750fb: conform to block comment style Fix 2 checkpatch errors: -Block comments use * on subsequent lines, -Block comments use a trailing */ on a separate line to conform to block commenting style. Signed-off-by: Elizabeth Ferdman <gnudevliz@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/sm750fb/ddk750_display.h b/drivers/staging/sm750fb/ddk750_display.h index 5fc9f6f..e3fde42 100644 --- a/drivers/staging/sm750fb/ddk750_display.h +++ b/drivers/staging/sm750fb/ddk750_display.h @@ -2,8 +2,8 @@ #define DDK750_DISPLAY_H__ /* panel path select - 80000[29:28] -*/ + * 80000[29:28] + */ #define PNL_2_OFFSET 0 #define PNL_2_MASK (3 << PNL_2_OFFSET) @@ -13,9 +13,9 @@ /* primary timing & plane enable bit - 1: 80000[8] & 80000[2] on - 0: both off -*/ + * 1: 80000[8] & 80000[2] on + * 0: both off + */ #define PRI_TP_OFFSET 4 #define PRI_TP_MASK BIT(PRI_TP_OFFSET) #define PRI_TP_USAGE (PRI_TP_MASK << 16) @@ -24,8 +24,8 @@ /* panel sequency status - 80000[27:24] -*/ + * 80000[27:24] + */ #define PNL_SEQ_OFFSET 6 #define PNL_SEQ_MASK BIT(PNL_SEQ_OFFSET) #define PNL_SEQ_USAGE (PNL_SEQ_MASK << 16) @@ -33,8 +33,8 @@ #define PNL_SEQ_OFF ((0 << PNL_SEQ_OFFSET) | PNL_SEQ_USAGE) /* dual digital output - 80000[19] -*/ + * 80000[19] + */ #define DUAL_TFT_OFFSET 8 #define DUAL_TFT_MASK BIT(DUAL_TFT_OFFSET) #define DUAL_TFT_USAGE (DUAL_TFT_MASK << 16) @@ -42,9 +42,9 @@ #define DUAL_TFT_OFF ((0 << DUAL_TFT_OFFSET) | DUAL_TFT_USAGE) /* secondary timing & plane enable bit - 1:80200[8] & 80200[2] on - 0: both off -*/ + * 1:80200[8] & 80200[2] on + * 0: both off + */ #define SEC_TP_OFFSET 5 #define SEC_TP_MASK BIT(SEC_TP_OFFSET) #define SEC_TP_USAGE (SEC_TP_MASK << 16) @@ -52,8 +52,8 @@ #define SEC_TP_OFF ((0x0 << SEC_TP_OFFSET) | SEC_TP_USAGE) /* crt path select - 80200[19:18] -*/ + * 80200[19:18] + */ #define CRT_2_OFFSET 2 #define CRT_2_MASK (3 << CRT_2_OFFSET) #define CRT_2_USAGE (CRT_2_MASK << 16) @@ -62,8 +62,8 @@ /* DAC affect both DVI and DSUB - 4[20] -*/ + * 4[20] + */ #define DAC_OFFSET 7 #define DAC_MASK BIT(DAC_OFFSET) #define DAC_USAGE (DAC_MASK << 16) @@ -71,8 +71,8 @@ #define DAC_OFF ((0x1 << DAC_OFFSET) | DAC_USAGE) /* DPMS only affect D-SUB head - 0[31:30] -*/ + * 0[31:30] + */ #define DPMS_OFFSET 9 #define DPMS_MASK (3 << DPMS_OFFSET) #define DPMS_USAGE (DPMS_MASK << 16) @@ -81,19 +81,17 @@ -/* - LCD1 means panel path TFT1 & panel path DVI (so enable DAC) - CRT means crt path DSUB -*/ +/* LCD1 means panel path TFT1 & panel path DVI (so enable DAC) + * CRT means crt path DSUB + */ typedef enum _disp_output_t { do_LCD1_PRI = PNL_2_PRI | PRI_TP_ON | PNL_SEQ_ON | DAC_ON, do_LCD1_SEC = PNL_2_SEC | SEC_TP_ON | PNL_SEQ_ON | DAC_ON, do_LCD2_PRI = CRT_2_PRI | PRI_TP_ON | DUAL_TFT_ON, do_LCD2_SEC = CRT_2_SEC | SEC_TP_ON | DUAL_TFT_ON, - /* - do_DSUB_PRI = CRT_2_PRI|PRI_TP_ON|DPMS_ON|DAC_ON, - do_DSUB_SEC = CRT_2_SEC|SEC_TP_ON|DPMS_ON|DAC_ON, - */ + /* do_DSUB_PRI = CRT_2_PRI | PRI_TP_ON | DPMS_ON|DAC_ON, + * do_DSUB_SEC = CRT_2_SEC | SEC_TP_ON | DPMS_ON|DAC_ON, + */ do_CRT_PRI = CRT_2_PRI | PRI_TP_ON | DPMS_ON | DAC_ON, do_CRT_SEC = CRT_2_SEC | SEC_TP_ON | DPMS_ON | DAC_ON, } diff --git a/drivers/staging/sm750fb/ddk750_hwi2c.c b/drivers/staging/sm750fb/ddk750_hwi2c.c index 39c3e1c..d391c12 100644 --- a/drivers/staging/sm750fb/ddk750_hwi2c.c +++ b/drivers/staging/sm750fb/ddk750_hwi2c.c @@ -21,7 +21,7 @@ unsigned char bus_speed_mode POKE32(GPIO_MUX, value); /* Enable Hardware I2C power. - TODO: Check if we need to enable GPIO power? + * TODO: Check if we need to enable GPIO power? */ enableI2C(1); diff --git a/drivers/staging/sm750fb/ddk750_mode.c b/drivers/staging/sm750fb/ddk750_mode.c index b767c7d..05b8364 100644 --- a/drivers/staging/sm750fb/ddk750_mode.c +++ b/drivers/staging/sm750fb/ddk750_mode.c @@ -4,15 +4,14 @@ #include "ddk750_mode.h" #include "ddk750_chip.h" -/* - SM750LE only: - This function takes care extra registers and bit fields required to set - up a mode in SM750LE - - Explanation about Display Control register: - HW only supports 7 predefined pixel clocks, and clock select is - in bit 29:27 of Display Control register. -*/ +/* SM750LE only: + * This function takes care extra registers and bit fields required to set + * up a mode in SM750LE + * + * Explanation about Display Control register: + * HW only supports 7 predefined pixel clocks, and clock select is + * in bit 29:27 of Display Control register. + */ static unsigned long displayControlAdjust_SM750LE(mode_parameter_t *pModeParam, unsigned long dispControl) { unsigned long x, y; @@ -21,9 +20,9 @@ static unsigned long displayControlAdjust_SM750LE(mode_parameter_t *pModeParam, y = pModeParam->vertical_display_end; /* SM750LE has to set up the top-left and bottom-right - registers as well. - Note that normal SM750/SM718 only use those two register for - auto-centering mode. + * registers as well. + * Note that normal SM750/SM718 only use those two register for + * auto-centering mode. */ POKE32(CRT_AUTO_CENTERING_TL, 0); @@ -33,8 +32,8 @@ static unsigned long displayControlAdjust_SM750LE(mode_parameter_t *pModeParam, ((x - 1) & CRT_AUTO_CENTERING_BR_RIGHT_MASK)); /* Assume common fields in dispControl have been properly set before - calling this function. - This function only sets the extra fields in dispControl. + * calling this function. + * This function only sets the extra fields in dispControl. */ /* Clear bit 29:27 of display control register */ diff --git a/drivers/staging/sm750fb/ddk750_sii164.c b/drivers/staging/sm750fb/ddk750_sii164.c index 67f36e7..99a8683 100644 --- a/drivers/staging/sm750fb/ddk750_sii164.c +++ b/drivers/staging/sm750fb/ddk750_sii164.c @@ -174,8 +174,8 @@ long sii164InitChip( i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config); /* De-skew enabled with default 111b value. - This will fix some artifacts problem in some mode on board 2.2. - Somehow this fix does not affect board 2.1. + * This fixes some artifacts problem in some mode on board 2.2. + * Somehow this fix does not affect board 2.1. */ if (deskewEnable == 0) config = SII164_DESKEW_DISABLE; @@ -344,7 +344,8 @@ void sii164EnableHotPlugDetection( detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT); /* Depending on each DVI controller, need to enable the hot plug based on each - individual chip design. */ + * individual chip design. + */ if (enableHotPlug != 0) sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_USE_MDI); else diff --git a/drivers/staging/sm750fb/ddk750_swi2c.c b/drivers/staging/sm750fb/ddk750_swi2c.c index 6c1ffa1..72a4233 100644 --- a/drivers/staging/sm750fb/ddk750_swi2c.c +++ b/drivers/staging/sm750fb/ddk750_swi2c.c @@ -89,12 +89,12 @@ static void sw_i2c_wait(void) * always be non-zero,which makes the while loop * never finish. * use non-ultimate for loop below is safe - * */ + */ /* Change wait algorithm to use PCI bus clock, - it's more reliable than counter loop .. - write 0x61 to 0x3ce and read from 0x3cf - */ + * it's more reliable than counter loop .. + * write 0x61 to 0x3ce and read from 0x3cf + */ int i, tmp; for (i = 0; i < 600; i++) { @@ -501,8 +501,8 @@ long sm750_sw_i2c_write_reg( sw_i2c_start(); /* Send the device address and read the data. All should return success - in order for the writing processed to be successful - */ + * in order for the writing processed to be successful + */ if ((sw_i2c_write_byte(addr) != 0) || (sw_i2c_write_byte(reg) != 0) || (sw_i2c_write_byte(data) != 0)) { diff --git a/drivers/staging/sm750fb/sm750.h b/drivers/staging/sm750fb/sm750.h index 8e70ce0..ff31c5c 100644 --- a/drivers/staging/sm750fb/sm750.h +++ b/drivers/staging/sm750fb/sm750.h @@ -147,17 +147,17 @@ struct lynxfb_output { int dpms; int paths; /* which paths(s) this output stands for,for sm750: - paths=1:means output for panel paths - paths=2:means output for crt paths - paths=3:means output for both panel and crt paths - */ + * paths=1:means output for panel paths + * paths=2:means output for crt paths + * paths=3:means output for both panel and crt paths + */ int *channel; /* which channel these outputs linked with,for sm750: - *channel=0 means primary channel - *channel=1 means secondary channel - output->channel ==> &crtc->channel - */ + * *channel=0 means primary channel + * *channel=1 means secondary channel + * output->channel ==> &crtc->channel + */ void *priv; int (*proc_setBLANK)(struct lynxfb_output*, int); diff --git a/drivers/staging/sm750fb/sm750_accel.c b/drivers/staging/sm750fb/sm750_accel.c index 9aa4066..38adae6 100644 --- a/drivers/staging/sm750fb/sm750_accel.c +++ b/drivers/staging/sm750fb/sm750_accel.c @@ -67,7 +67,8 @@ void hw_de_init(struct lynx_accel *accel) /* set2dformat only be called from setmode functions * but if you need dual framebuffer driver,need call set2dformat - * every time you use 2d function */ + * every time you use 2d function + */ void hw_set2dformat(struct lynx_accel *accel, int fmt) { @@ -90,7 +91,8 @@ int hw_fillrect(struct lynx_accel *accel, if (accel->de_wait() != 0) { /* int time wait and always busy,seems hardware - * got something error */ + * got something error + */ pr_debug("De engine always busy\n"); return -1; } @@ -152,24 +154,26 @@ unsigned int rop2) /* ROP value */ /* Determine direction of operation */ if (sy < dy) { /* +----------+ - |S | - | +----------+ - | | | | - | | | | - +---|------+ | - | D| - +----------+ */ + * |S | + * | +----------+ + * | | | | + * | | | | + * +---|------+ | + * | D| + * +----------+ + */ nDirection = BOTTOM_TO_TOP; } else if (sy > dy) { /* +----------+ - |D | - | +----------+ - | | | | - | | | | - +---|------+ | - | S| - +----------+ */ + * |D | + * | +----------+ + * | | | | + * | | | | + * +---|------+ | + * | S| + * +----------+ + */ nDirection = TOP_TO_BOTTOM; } else { @@ -177,22 +181,24 @@ unsigned int rop2) /* ROP value */ if (sx <= dx) { /* +------+---+------+ - |S | | D| - | | | | - | | | | - | | | | - +------+---+------+ */ + * |S | | D| + * | | | | + * | | | | + * | | | | + * +------+---+------+ + */ nDirection = RIGHT_TO_LEFT; } else { /* sx > dx */ /* +------+---+------+ - |D | | S| - | | | | - | | | | - | | | | - +------+---+------+ */ + * |D | | S| + * | | | | + * | | | | + * | | | | + * +------+---+------+ + */ nDirection = LEFT_TO_RIGHT; } @@ -208,32 +214,36 @@ unsigned int rop2) /* ROP value */ } /* Note: - DE_FOREGROUND are DE_BACKGROUND are don't care. - DE_COLOR_COMPARE and DE_COLOR_COMPARE_MAKS are set by set deSetTransparency(). + * DE_FOREGROUND are DE_BACKGROUND are don't care. + * DE_COLOR_COMPARE and DE_COLOR_COMPARE_MAKS + * are set by set deSetTransparency(). */ /* 2D Source Base. - It is an address offset (128 bit aligned) from the beginning of frame buffer. + * It is an address offset (128 bit aligned) + * from the beginning of frame buffer. */ write_dpr(accel, DE_WINDOW_SOURCE_BASE, sBase); /* dpr40 */ /* 2D Destination Base. - It is an address offset (128 bit aligned) from the beginning of frame buffer. + * It is an address offset (128 bit aligned) + * from the beginning of frame buffer. */ write_dpr(accel, DE_WINDOW_DESTINATION_BASE, dBase); /* dpr44 */ /* Program pitch (distance between the 1st points of two adjacent lines). - Note that input pitch is BYTE value, but the 2D Pitch register uses - pixel values. Need Byte to pixel conversion. - */ + * Note that input pitch is BYTE value, but the 2D Pitch register uses + * pixel values. Need Byte to pixel conversion. + */ write_dpr(accel, DE_PITCH, ((dPitch / Bpp << DE_PITCH_DESTINATION_SHIFT) & DE_PITCH_DESTINATION_MASK) | (sPitch / Bpp & DE_PITCH_SOURCE_MASK)); /* dpr10 */ /* Screen Window width in Pixels. - 2D engine uses this value to calculate the linear address in frame buffer for a given point. - */ + * 2D engine uses this value to calculate the linear address in frame buffer + * for a given point. + */ write_dpr(accel, DE_WINDOW_WIDTH, ((dPitch / Bpp << DE_WINDOW_WIDTH_DST_SHIFT) & DE_WINDOW_WIDTH_DST_MASK) | @@ -307,33 +317,37 @@ int hw_imageblit(struct lynx_accel *accel, return -1; /* 2D Source Base. - Use 0 for HOST Blt. + * Use 0 for HOST Blt. */ write_dpr(accel, DE_WINDOW_SOURCE_BASE, 0); /* 2D Destination Base. - It is an address offset (128 bit aligned) from the beginning of frame buffer. + * It is an address offset (128 bit aligned) + * from the beginning of frame buffer. */ write_dpr(accel, DE_WINDOW_DESTINATION_BASE, dBase); /* Program pitch (distance between the 1st points of two adjacent lines). - Note that input pitch is BYTE value, but the 2D Pitch register uses - pixel values. Need Byte to pixel conversion. - */ + * Note that input pitch is BYTE value, but the 2D Pitch register uses + * pixel values. Need Byte to pixel conversion. + */ write_dpr(accel, DE_PITCH, ((dPitch / bytePerPixel << DE_PITCH_DESTINATION_SHIFT) & DE_PITCH_DESTINATION_MASK) | (dPitch / bytePerPixel & DE_PITCH_SOURCE_MASK)); /* dpr10 */ /* Screen Window width in Pixels. - 2D engine uses this value to calculate the linear address in frame buffer for a given point. + * 2D engine uses this value to calculate the linear address + * in frame buffer for a given point. */ write_dpr(accel, DE_WINDOW_WIDTH, ((dPitch / bytePerPixel << DE_WINDOW_WIDTH_DST_SHIFT) & DE_WINDOW_WIDTH_DST_MASK) | (dPitch / bytePerPixel & DE_WINDOW_WIDTH_SRC_MASK)); - /* Note: For 2D Source in Host Write, only X_K1_MONO field is needed, and Y_K2 field is not used. - For mono bitmap, use startBit for X_K1. */ + /* Note: For 2D Source in Host Write, only X_K1_MONO field is needed, + * and Y_K2 field is not used. + * For mono bitmap, use startBit for X_K1. + */ write_dpr(accel, DE_SOURCE, (startBit << DE_SOURCE_X_K1_SHIFT) & DE_SOURCE_X_K1_MONO_MASK); /* dpr00 */ -- cgit v0.10.2 From 42f8f2184bdc980a03cbc61abf53f9a97597d1e9 Mon Sep 17 00:00:00 2001 From: Moshe Green <mgmoshes@gmail.com> Date: Sun, 2 Oct 2016 14:04:46 +0300 Subject: staging: sm750fb: replace roundedDiv with DIV_ROUND_CLOSEST Replace local implementation of rounded division (roundedDiv macro) with the in-kernel implementation (DIV_ROUND_CLOSEST macro) in ddk750_chip.c Signed-off-by: Moshe Green <mgmoshes@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index 3a0afe1..839d673 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -6,8 +6,6 @@ #include "ddk750_chip.h" #include "ddk750_power.h" -/* n / d + 1 / 2 = (2n + d) / 2d */ -#define roundedDiv(num, denom) ((2 * (num) + (denom)) / (2 * (denom))) #define MHz(x) ((x) * 1000000) logical_chip_type_t sm750_get_chip_type(void) @@ -102,7 +100,7 @@ static void setMemoryClock(unsigned int frequency) frequency = MHz(336); /* Calculate the divisor */ - divisor = roundedDiv(get_mxclk_freq(), frequency); + divisor = DIV_ROUND_CLOSEST(get_mxclk_freq(), frequency); /* Set the corresponding divisor in the register. */ reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_M2XCLK_MASK; @@ -152,7 +150,7 @@ static void setMasterClock(unsigned int frequency) frequency = MHz(190); /* Calculate the divisor */ - divisor = roundedDiv(get_mxclk_freq(), frequency); + divisor = DIV_ROUND_CLOSEST(get_mxclk_freq(), frequency); /* Set the corresponding divisor in the register. */ reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_MCLK_MASK; -- cgit v0.10.2 From b19ca1e5f1c35ce7c6da52d45975f025ece1be88 Mon Sep 17 00:00:00 2001 From: Elizabeth Ferdman <gnudevliz@gmail.com> Date: Thu, 29 Sep 2016 15:45:55 -0700 Subject: staging: media: replace unsigned with unsigned int Fix checkpatch error "Prefer 'unsigned int' to bare use of 'unsigned'" for readability. Signed-off-by: Elizabeth Ferdman <gnudevliz@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/media/davinci_vpfe/dm365_resizer.c b/drivers/staging/media/davinci_vpfe/dm365_resizer.c index 3cd56cc..1286626 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_resizer.c +++ b/drivers/staging/media/davinci_vpfe/dm365_resizer.c @@ -128,7 +128,7 @@ resizer_configure_passthru(struct vpfe_resizer_device *resizer, int bypass) static void configure_resizer_out_params(struct vpfe_resizer_device *resizer, int index, void *output_spec, unsigned char partial, - unsigned flag) + unsigned int flag) { struct resizer_params *param = &resizer->config; struct v4l2_mbus_framefmt *outformat; -- cgit v0.10.2 From b4e26d6c06eb70b0d3892bbd40ce43d4ea345c45 Mon Sep 17 00:00:00 2001 From: Wayne Porter <wporter82@gmail.com> Date: Fri, 30 Sep 2016 23:12:55 +0000 Subject: staging: android: ion: fix warning found by checkpatch.pl Fix checkpatch.pl warning: WARNING: braces {} are not necessary for single statement blocks Signed-off-by: Wayne Porter <wporter82@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/hisilicon/hi6220_ion.c b/drivers/staging/android/ion/hisilicon/hi6220_ion.c index 659aa71..bd45151 100644 --- a/drivers/staging/android/ion/hisilicon/hi6220_ion.c +++ b/drivers/staging/android/ion/hisilicon/hi6220_ion.c @@ -82,9 +82,9 @@ static int hi6220_ion_remove(struct platform_device *pdev) ipdev = platform_get_drvdata(pdev); - for (i = 0; i < ipdev->data->nr; i++) { + for (i = 0; i < ipdev->data->nr; i++) ion_heap_destroy(ipdev->heaps[i]); - } + ion_destroy_platform_data(ipdev->data); ion_device_destroy(ipdev->idev); -- cgit v0.10.2 From b1e42d9f7057d074e6ada45abe003c4d8578bd20 Mon Sep 17 00:00:00 2001 From: Wayne Porter <wporter82@gmail.com> Date: Fri, 30 Sep 2016 22:58:44 +0000 Subject: staging: android: ion: fix checks found by checkpatch.pl Alignment fixes Signed-off-by: Wayne Porter <wporter82@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/android/ion/hisilicon/hi6220_ion.c b/drivers/staging/android/ion/hisilicon/hi6220_ion.c index bd45151..0de7897 100644 --- a/drivers/staging/android/ion/hisilicon/hi6220_ion.c +++ b/drivers/staging/android/ion/hisilicon/hi6220_ion.c @@ -29,11 +29,11 @@ struct hisi_ion_dev { static struct ion_of_heap hisi_heaps[] = { PLATFORM_HEAP("hisilicon,sys_user", 0, - ION_HEAP_TYPE_SYSTEM, "sys_user"), + ION_HEAP_TYPE_SYSTEM, "sys_user"), PLATFORM_HEAP("hisilicon,sys_contig", 1, - ION_HEAP_TYPE_SYSTEM_CONTIG, "sys_contig"), + ION_HEAP_TYPE_SYSTEM_CONTIG, "sys_contig"), PLATFORM_HEAP("hisilicon,cma", ION_HEAP_TYPE_DMA, ION_HEAP_TYPE_DMA, - "cma"), + "cma"), {} }; @@ -57,7 +57,7 @@ static int hi6220_ion_probe(struct platform_device *pdev) return PTR_ERR(ipdev->data); ipdev->heaps = devm_kzalloc(&pdev->dev, - sizeof(struct ion_heap)*ipdev->data->nr, + sizeof(struct ion_heap) * ipdev->data->nr, GFP_KERNEL); if (!ipdev->heaps) { ion_destroy_platform_data(ipdev->data); -- cgit v0.10.2 From 03c2975b664297f4954ecedf7c212418a31f083e Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:18:54 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_bytestr32_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_bytestr32_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 4cf4796..5df4e1f 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -356,10 +356,10 @@ struct hfa384x_bytestr { u8 data[0]; } __packed; -typedef struct hfa384x_bytestr32 { +struct hfa384x_bytestr32 { u16 len; u8 data[32]; -} __packed hfa384x_bytestr32_t; +} __packed; /*-------------------------------------------------------------------- Configuration Record Structures: @@ -398,7 +398,7 @@ Configuration Record Structures: typedef struct hfa384x_HostScanRequest_data { u16 channelList; u16 txRate; - hfa384x_bytestr32_t ssid; + struct hfa384x_bytestr32 ssid; } __packed hfa384x_HostScanRequest_data_t; /*-- Configuration Record: JoinRequest (data portion only) --*/ @@ -643,7 +643,7 @@ typedef struct hfa384x_ScanResultSub { u8 bssid[WLAN_BSSID_LEN]; u16 bcnint; u16 capinfo; - hfa384x_bytestr32_t ssid; + struct hfa384x_bytestr32 ssid; u8 supprates[10]; /* 802.11 info element */ u16 proberesp_rate; } __packed hfa384x_ScanResultSub_t; @@ -678,7 +678,7 @@ typedef struct hfa384x_HScanResultSub { u8 bssid[WLAN_BSSID_LEN]; u16 bcnint; u16 capinfo; - hfa384x_bytestr32_t ssid; + struct hfa384x_bytestr32 ssid; u8 supprates[10]; /* 802.11 info element */ u16 proberesp_rate; u16 atim; diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index 474e29f..098cb57 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -1173,7 +1173,7 @@ void prism2sta_processing_defer(struct work_struct *data) { hfa384x_t *hw = container_of(data, struct hfa384x, link_bh); struct wlandevice *wlandev = hw->wlandev; - hfa384x_bytestr32_t ssid; + struct hfa384x_bytestr32 ssid; int result; /* First let's process the auth frames */ @@ -1916,7 +1916,7 @@ void prism2sta_commsqual_defer(struct work_struct *data) { hfa384x_t *hw = container_of(data, struct hfa384x, commsqual_bh); struct wlandevice *wlandev = hw->wlandev; - hfa384x_bytestr32_t ssid; + struct hfa384x_bytestr32 ssid; struct p80211msg_dot11req_mibget msg; struct p80211item_uint32 *mibitem = (struct p80211item_uint32 *) &msg.mibattribute.data; -- cgit v0.10.2 From 5f04645672c3dabf263939ab0454590e4e18fdff Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:18:55 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_compident_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_compident_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 5df4e1f..d462c78 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -367,12 +367,12 @@ Configuration Record Structures: --------------------------------------------------------------------*/ /*-- Hardware/Firmware Component Information ----------*/ -typedef struct hfa384x_compident { +struct hfa384x_compident { u16 id; u16 variant; u16 major; u16 minor; -} __packed hfa384x_compident_t; +} __packed; typedef struct hfa384x_caplevel { u16 role; @@ -1304,10 +1304,10 @@ typedef struct hfa384x { unsigned int dot11_grpcnt; /* Component Identities */ - hfa384x_compident_t ident_nic; - hfa384x_compident_t ident_pri_fw; - hfa384x_compident_t ident_sta_fw; - hfa384x_compident_t ident_ap_fw; + struct hfa384x_compident ident_nic; + struct hfa384x_compident ident_pri_fw; + struct hfa384x_compident ident_sta_fw; + struct hfa384x_compident ident_ap_fw; u16 mm_mods; /* Supplier compatibility ranges */ diff --git a/drivers/staging/wlan-ng/prism2fw.c b/drivers/staging/wlan-ng/prism2fw.c index 7c5d3e7..35b0ff99 100644 --- a/drivers/staging/wlan-ng/prism2fw.c +++ b/drivers/staging/wlan-ng/prism2fw.c @@ -96,10 +96,10 @@ struct s3inforec { u16 len; u16 type; union { - hfa384x_compident_t version; + struct hfa384x_compident version; hfa384x_caplevel_t compat; u16 buildseq; - hfa384x_compident_t platform; + struct hfa384x_compident platform; } info; }; @@ -152,7 +152,7 @@ static struct imgchunk fchunk[CHUNKS_MAX]; /* PDA, built from [card|newfile]+[addfile1+addfile2...] */ static struct pda pda; -static hfa384x_compident_t nicid; +static struct hfa384x_compident nicid; static hfa384x_caplevel_t rfid; static hfa384x_caplevel_t macid; static hfa384x_caplevel_t priid; diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index 098cb57..0dbdba8 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -593,7 +593,7 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev) /* NIC identity */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_NICIDENTITY, &hw->ident_nic, - sizeof(hfa384x_compident_t)); + sizeof(struct hfa384x_compident)); if (result) { netdev_err(wlandev->netdev, "Failed to retrieve NICIDENTITY\n"); goto failed; @@ -612,7 +612,7 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev) /* Primary f/w identity */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRIIDENTITY, &hw->ident_pri_fw, - sizeof(hfa384x_compident_t)); + sizeof(struct hfa384x_compident)); if (result) { netdev_err(wlandev->netdev, "Failed to retrieve PRIIDENTITY\n"); goto failed; @@ -631,7 +631,7 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev) /* Station (Secondary?) f/w identity */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STAIDENTITY, &hw->ident_sta_fw, - sizeof(hfa384x_compident_t)); + sizeof(struct hfa384x_compident)); if (result) { netdev_err(wlandev->netdev, "Failed to retrieve STAIDENTITY\n"); goto failed; -- cgit v0.10.2 From 3e27dfa2ce240fb67b722f7e1e9b1c2485a79d60 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:18:56 +0200 Subject: staging: wlang-ng: Fix block comments style warnings in hfa384x.h This patch fixes the following checkpatch.pl warnings in hfa384x.h: WARNING: Block comments use * on subsequent lines WARNING: Block comments use a trailing */ on a separate line Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index d462c78..5ca2a94 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -174,11 +174,12 @@ #define HFA384x_CMD_ERR ((u16)(0x7F)) /*--- Programming Modes -------------------------- - MODE 0: Disable programming - MODE 1: Enable volatile memory programming - MODE 2: Enable non-volatile memory programming - MODE 3: Program non-volatile memory section ---------------------------------------------------*/ + * MODE 0: Disable programming + * MODE 1: Enable volatile memory programming + * MODE 2: Enable non-volatile memory programming + * MODE 3: Program non-volatile memory section + *------------------------------------------------- + */ #define HFA384x_PROGMODE_DISABLE ((u16)0x00) #define HFA384x_PROGMODE_RAM ((u16)0x01) #define HFA384x_PROGMODE_NV ((u16)0x02) @@ -186,8 +187,9 @@ /*--- Record ID Constants --------------------------*/ /*-------------------------------------------------------------------- -Configuration RIDs: Network Parameters, Static Configuration Entities ---------------------------------------------------------------------*/ + * Configuration RIDs: Network Parameters, Static Configuration Entities + *-------------------------------------------------------------------- + */ #define HFA384x_RID_CNFPORTTYPE ((u16)0xFC00) #define HFA384x_RID_CNFOWNMACADDR ((u16)0xFC01) #define HFA384x_RID_CNFDESIREDSSID ((u16)0xFC02) @@ -196,17 +198,19 @@ Configuration RIDs: Network Parameters, Static Configuration Entities #define HFA384x_RID_CNFMAXDATALEN ((u16)0xFC07) /*-------------------------------------------------------------------- -Configuration RID lengths: Network Params, Static Config Entities - This is the length of JUST the DATA part of the RID (does not - include the len or code fields) ---------------------------------------------------------------------*/ + * Configuration RID lengths: Network Params, Static Config Entities + * This is the length of JUST the DATA part of the RID (does not + * include the len or code fields) + *-------------------------------------------------------------------- + */ #define HFA384x_RID_CNFOWNMACADDR_LEN ((u16)6) #define HFA384x_RID_CNFDESIREDSSID_LEN ((u16)34) #define HFA384x_RID_CNFOWNSSID_LEN ((u16)34) /*-------------------------------------------------------------------- -Configuration RIDs: Network Parameters, Dynamic Configuration Entities ---------------------------------------------------------------------*/ + * Configuration RIDs: Network Parameters, Dynamic Configuration Entities + *-------------------------------------------------------------------- + */ #define HFA384x_RID_CREATEIBSS ((u16)0xFC81) #define HFA384x_RID_FRAGTHRESH ((u16)0xFC82) #define HFA384x_RID_RTSTHRESH ((u16)0xFC83) @@ -214,8 +218,9 @@ Configuration RIDs: Network Parameters, Dynamic Configuration Entities #define HFA384x_RID_PROMISCMODE ((u16)0xFC85) /*---------------------------------------------------------------------- -Information RIDs: NIC Information ---------------------------------------------------------------------*/ + * Information RIDs: NIC Information + *---------------------------------------------------------------------- + */ #define HFA384x_RID_MAXLOADTIME ((u16)0xFD00) #define HFA384x_RID_DOWNLOADBUFFER ((u16)0xFD01) #define HFA384x_RID_PRIIDENTITY ((u16)0xFD02) @@ -231,15 +236,17 @@ Information RIDs: NIC Information #define HFA384x_RID_STA_CFIACTRANGES ((u16)0xFD23) /*---------------------------------------------------------------------- -Information RID Lengths: NIC Information - This is the length of JUST the DATA part of the RID (does not - include the len or code fields) ---------------------------------------------------------------------*/ + * Information RID Lengths: NIC Information + * This is the length of JUST the DATA part of the RID (does not + * include the len or code fields) + *--------------------------------------------------------------------- + */ #define HFA384x_RID_NICSERIALNUMBER_LEN ((u16)12) /*-------------------------------------------------------------------- -Information RIDs: MAC Information ---------------------------------------------------------------------*/ + * Information RIDs: MAC Information + *-------------------------------------------------------------------- + */ #define HFA384x_RID_PORTSTATUS ((u16)0xFD40) #define HFA384x_RID_CURRENTSSID ((u16)0xFD41) #define HFA384x_RID_CURRENTBSSID ((u16)0xFD42) @@ -251,23 +258,26 @@ Information RIDs: MAC Information #define HFA384x_RID_DBMCOMMSQUALITY ((u16)0xFD51) /*-------------------------------------------------------------------- -Information RID Lengths: MAC Information - This is the length of JUST the DATA part of the RID (does not - include the len or code fields) ---------------------------------------------------------------------*/ + * Information RID Lengths: MAC Information + * This is the length of JUST the DATA part of the RID (does not + * include the len or code fields) + *-------------------------------------------------------------------- + */ #define HFA384x_RID_DBMCOMMSQUALITY_LEN \ ((u16)sizeof(hfa384x_dbmcommsquality_t)) #define HFA384x_RID_JOINREQUEST_LEN \ ((u16)sizeof(hfa384x_JoinRequest_data_t)) /*-------------------------------------------------------------------- -Information RIDs: Modem Information ---------------------------------------------------------------------*/ + * Information RIDs: Modem Information + *-------------------------------------------------------------------- + */ #define HFA384x_RID_CURRENTCHANNEL ((u16)0xFDC1) /*-------------------------------------------------------------------- -API ENHANCEMENTS (NOT ALREADY IMPLEMENTED) ---------------------------------------------------------------------*/ + * API ENHANCEMENTS (NOT ALREADY IMPLEMENTED) + *-------------------------------------------------------------------- + */ #define HFA384x_RID_CNFWEPDEFAULTKEYID ((u16)0xFC23) #define HFA384x_RID_CNFWEPDEFAULTKEY0 ((u16)0xFC24) #define HFA384x_RID_CNFWEPDEFAULTKEY1 ((u16)0xFC25) @@ -291,8 +301,9 @@ API ENHANCEMENTS (NOT ALREADY IMPLEMENTED) #define HFA384x_RID_CNFWEP128DEFAULTKEY_LEN ((u16)14) /*-------------------------------------------------------------------- -PD Record codes ---------------------------------------------------------------------*/ + * PD Record codes + *-------------------------------------------------------------------- + */ #define HFA384x_PDR_PCB_PARTNUM ((u16)0x0001) #define HFA384x_PDR_PDAVER ((u16)0x0002) #define HFA384x_PDR_NIC_SERIAL ((u16)0x0003) @@ -362,9 +373,10 @@ struct hfa384x_bytestr32 { } __packed; /*-------------------------------------------------------------------- -Configuration Record Structures: - Network Parameters, Static Configuration Entities ---------------------------------------------------------------------*/ + * Configuration Record Structures: + * Network Parameters, Static Configuration Entities + *-------------------------------------------------------------------- + */ /*-- Hardware/Firmware Component Information ----------*/ struct hfa384x_compident { @@ -388,9 +400,10 @@ typedef struct hfa384x_caplevel { #define HFA384x_CNFAUTHENTICATION_LEAP 0x0004 /*-------------------------------------------------------------------- -Configuration Record Structures: - Network Parameters, Dynamic Configuration Entities ---------------------------------------------------------------------*/ + * Configuration Record Structures: + * Network Parameters, Dynamic Configuration Entities + *-------------------------------------------------------------------- + */ #define HFA384x_CREATEIBSS_JOINCREATEIBSS 0 @@ -421,8 +434,9 @@ typedef struct hfa384x_WPAData { } __packed hfa384x_WPAData_t; /*-------------------------------------------------------------------- -Information Record Structures: NIC Information ---------------------------------------------------------------------*/ + * Information Record Structures: NIC Information + *-------------------------------------------------------------------- + */ /*-- Information Record: DownLoadBuffer --*/ /* NOTE: The page and offset are in AUX format */ @@ -433,8 +447,9 @@ typedef struct hfa384x_downloadbuffer { } __packed hfa384x_downloadbuffer_t; /*-------------------------------------------------------------------- -Information Record Structures: NIC Information ---------------------------------------------------------------------*/ + * Information Record Structures: NIC Information + *-------------------------------------------------------------------- + */ #define HFA384x_PSTATUS_CONN_IBSS ((u16)3) @@ -453,10 +468,11 @@ typedef struct hfa384x_dbmcommsquality { } __packed hfa384x_dbmcommsquality_t; /*-------------------------------------------------------------------- -FRAME STRUCTURES: Communication Frames ----------------------------------------------------------------------- -Communication Frames: Transmit Frames ---------------------------------------------------------------------*/ + * FRAME STRUCTURES: Communication Frames + *-------------------------------------------------------------------- + * Communication Frames: Transmit Frames + *-------------------------------------------------------------------- + */ /*-- Communication Frame: Transmit Frame Structure --*/ typedef struct hfa384x_tx_frame { u16 status; @@ -485,8 +501,9 @@ typedef struct hfa384x_tx_frame { u16 data_length; /* big endian format */ } __packed hfa384x_tx_frame_t; /*-------------------------------------------------------------------- -Communication Frames: Field Masks for Transmit Frames ---------------------------------------------------------------------*/ + * Communication Frames: Field Masks for Transmit Frames + *-------------------------------------------------------------------- + */ /*-- Status Field --*/ #define HFA384x_TXSTATUS_ACKERR ((u16)BIT(5)) #define HFA384x_TXSTATUS_FORMERR ((u16)BIT(3)) @@ -500,8 +517,9 @@ Communication Frames: Field Masks for Transmit Frames #define HFA384x_TX_TXEX ((u16)BIT(2)) #define HFA384x_TX_TXOK ((u16)BIT(1)) /*-------------------------------------------------------------------- -Communication Frames: Test/Get/Set Field Values for Transmit Frames ---------------------------------------------------------------------*/ + * Communication Frames: Test/Get/Set Field Values for Transmit Frames + *-------------------------------------------------------------------- + */ /*-- Status Field --*/ #define HFA384x_TXSTATUS_ISERROR(v) \ (((u16)(v)) & \ @@ -517,8 +535,9 @@ Communication Frames: Test/Get/Set Field Values for Transmit Frames #define HFA384x_TX_TXEX_SET(v) HFA384x_TX_SET(v, HFA384x_TX_TXEX, 2) #define HFA384x_TX_TXOK_SET(v) HFA384x_TX_SET(v, HFA384x_TX_TXOK, 1) /*-------------------------------------------------------------------- -Communication Frames: Receive Frames ---------------------------------------------------------------------*/ + * Communication Frames: Receive Frames + *-------------------------------------------------------------------- + */ /*-- Communication Frame: Receive Frame Structure --*/ typedef struct hfa384x_rx_frame { /*-- MAC rx descriptor (hfa384x byte order) --*/ @@ -547,8 +566,9 @@ typedef struct hfa384x_rx_frame { u16 data_length; /* IEEE? (big endian) format */ } __packed hfa384x_rx_frame_t; /*-------------------------------------------------------------------- -Communication Frames: Field Masks for Receive Frames ---------------------------------------------------------------------*/ + * Communication Frames: Field Masks for Receive Frames + *-------------------------------------------------------------------- + */ /*-- Status Fields --*/ #define HFA384x_RXSTATUS_MACPORT ((u16)(BIT(10) | \ @@ -556,17 +576,19 @@ Communication Frames: Field Masks for Receive Frames BIT(8))) #define HFA384x_RXSTATUS_FCSERR ((u16)BIT(0)) /*-------------------------------------------------------------------- -Communication Frames: Test/Get/Set Field Values for Receive Frames ---------------------------------------------------------------------*/ + * Communication Frames: Test/Get/Set Field Values for Receive Frames + *-------------------------------------------------------------------- + */ #define HFA384x_RXSTATUS_MACPORT_GET(value) ((u16)((((u16)(value)) \ & HFA384x_RXSTATUS_MACPORT) >> 8)) #define HFA384x_RXSTATUS_ISFCSERR(value) ((u16)(((u16)(value)) \ & HFA384x_RXSTATUS_FCSERR)) /*-------------------------------------------------------------------- - FRAME STRUCTURES: Information Types and Information Frame Structures ----------------------------------------------------------------------- -Information Types ---------------------------------------------------------------------*/ + * FRAME STRUCTURES: Information Types and Information Frame Structures + *-------------------------------------------------------------------- + * Information Types + *-------------------------------------------------------------------- + */ #define HFA384x_IT_HANDOVERADDR ((u16)0xF000UL) #define HFA384x_IT_COMMTALLIES ((u16)0xF100UL) #define HFA384x_IT_SCANRESULTS ((u16)0xF101UL) @@ -581,10 +603,11 @@ Information Types #define HFA384x_IT_MICFAILURE ((u16)0xF206UL) /*-------------------------------------------------------------------- -Information Frames Structures ----------------------------------------------------------------------- -Information Frames: Notification Frame Structures ---------------------------------------------------------------------*/ + * Information Frames Structures + *-------------------------------------------------------------------- + * Information Frames: Notification Frame Structures + *-------------------------------------------------------------------- + */ /*-- Inquiry Frame, Diagnose: Communication Tallies --*/ typedef struct hfa384x_CommTallies16 { @@ -758,8 +781,9 @@ typedef struct hfa384x_InfFrame { } __packed hfa384x_InfFrame_t; /*-------------------------------------------------------------------- -USB Packet structures and constants. ---------------------------------------------------------------------*/ + * USB Packet structures and constants. + *-------------------------------------------------------------------- + */ /* Should be sent to the bulkout endpoint */ #define HFA384x_USB_TXFRM 0 @@ -905,8 +929,9 @@ typedef union hfa384x_usbin { } __packed hfa384x_usbin_t; /*-------------------------------------------------------------------- -PD record structures. ---------------------------------------------------------------------*/ + * PD record structures. + *-------------------------------------------------------------------- + */ typedef struct hfa384x_pdr_pcb_partnum { u8 num[8]; @@ -1113,9 +1138,10 @@ typedef struct hfa384x_pdrec { #ifdef __KERNEL__ /*-------------------------------------------------------------------- ---- MAC state structure, argument to all functions -- ---- Also, a collection of support types -- ---------------------------------------------------------------------*/ + * --- MAC state structure, argument to all functions -- + * --- Also, a collection of support types -- + *-------------------------------------------------------------------- + */ typedef struct hfa384x_statusresult { u16 status; u16 resp0; -- cgit v0.10.2 From 65f170c661d9419db74c6710baaa9df72c1f95b3 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:18:57 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_caplevel_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_caplevel_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 5ca2a94..e02f894 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -386,13 +386,13 @@ struct hfa384x_compident { u16 minor; } __packed; -typedef struct hfa384x_caplevel { +struct hfa384x_caplevel { u16 role; u16 id; u16 variant; u16 bottom; u16 top; -} __packed hfa384x_caplevel_t; +} __packed; /*-- Configuration Record: cnfAuthentication --*/ #define HFA384x_CNFAUTHENTICATION_OPENSYSTEM 0x0001 @@ -1337,31 +1337,31 @@ typedef struct hfa384x { u16 mm_mods; /* Supplier compatibility ranges */ - hfa384x_caplevel_t cap_sup_mfi; - hfa384x_caplevel_t cap_sup_cfi; - hfa384x_caplevel_t cap_sup_pri; - hfa384x_caplevel_t cap_sup_sta; - hfa384x_caplevel_t cap_sup_ap; + struct hfa384x_caplevel cap_sup_mfi; + struct hfa384x_caplevel cap_sup_cfi; + struct hfa384x_caplevel cap_sup_pri; + struct hfa384x_caplevel cap_sup_sta; + struct hfa384x_caplevel cap_sup_ap; /* Actor compatibility ranges */ - hfa384x_caplevel_t cap_act_pri_cfi; /* + struct hfa384x_caplevel cap_act_pri_cfi; /* * pri f/w to controller * interface */ - hfa384x_caplevel_t cap_act_sta_cfi; /* + struct hfa384x_caplevel cap_act_sta_cfi; /* * sta f/w to controller * interface */ - hfa384x_caplevel_t cap_act_sta_mfi; /* sta f/w to modem interface */ + struct hfa384x_caplevel cap_act_sta_mfi; /* sta f/w to modem interface */ - hfa384x_caplevel_t cap_act_ap_cfi; /* + struct hfa384x_caplevel cap_act_ap_cfi; /* * ap f/w to controller * interface */ - hfa384x_caplevel_t cap_act_ap_mfi; /* ap f/w to modem interface */ + struct hfa384x_caplevel cap_act_ap_mfi; /* ap f/w to modem interface */ u32 psusercount; /* Power save user count. */ hfa384x_CommTallies32_t tallies; /* Communication tallies. */ diff --git a/drivers/staging/wlan-ng/prism2fw.c b/drivers/staging/wlan-ng/prism2fw.c index 35b0ff99..ca322fa 100644 --- a/drivers/staging/wlan-ng/prism2fw.c +++ b/drivers/staging/wlan-ng/prism2fw.c @@ -97,7 +97,7 @@ struct s3inforec { u16 type; union { struct hfa384x_compident version; - hfa384x_caplevel_t compat; + struct hfa384x_caplevel compat; u16 buildseq; struct hfa384x_compident platform; } info; @@ -153,9 +153,9 @@ static struct imgchunk fchunk[CHUNKS_MAX]; static struct pda pda; static struct hfa384x_compident nicid; -static hfa384x_caplevel_t rfid; -static hfa384x_caplevel_t macid; -static hfa384x_caplevel_t priid; +static struct hfa384x_caplevel rfid; +static struct hfa384x_caplevel macid; +static struct hfa384x_caplevel priid; /*================================================================*/ /* Local Function Declarations */ diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index 0dbdba8..850cbbc 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -671,7 +671,7 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev) /* Compatibility range, Modem supplier */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_MFISUPRANGE, &hw->cap_sup_mfi, - sizeof(hfa384x_caplevel_t)); + sizeof(struct hfa384x_caplevel)); if (result) { netdev_err(wlandev->netdev, "Failed to retrieve MFISUPRANGE\n"); goto failed; @@ -695,7 +695,7 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev) /* Compatibility range, Controller supplier */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CFISUPRANGE, &hw->cap_sup_cfi, - sizeof(hfa384x_caplevel_t)); + sizeof(struct hfa384x_caplevel)); if (result) { netdev_err(wlandev->netdev, "Failed to retrieve CFISUPRANGE\n"); goto failed; @@ -719,7 +719,7 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev) /* Compatibility range, Primary f/w supplier */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRISUPRANGE, &hw->cap_sup_pri, - sizeof(hfa384x_caplevel_t)); + sizeof(struct hfa384x_caplevel)); if (result) { netdev_err(wlandev->netdev, "Failed to retrieve PRISUPRANGE\n"); goto failed; @@ -743,7 +743,7 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev) /* Compatibility range, Station f/w supplier */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STASUPRANGE, &hw->cap_sup_sta, - sizeof(hfa384x_caplevel_t)); + sizeof(struct hfa384x_caplevel)); if (result) { netdev_err(wlandev->netdev, "Failed to retrieve STASUPRANGE\n"); goto failed; @@ -775,7 +775,7 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev) /* Compatibility range, primary f/w actor, CFI supplier */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRI_CFIACTRANGES, &hw->cap_act_pri_cfi, - sizeof(hfa384x_caplevel_t)); + sizeof(struct hfa384x_caplevel)); if (result) { netdev_err(wlandev->netdev, "Failed to retrieve PRI_CFIACTRANGES\n"); goto failed; @@ -799,7 +799,7 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev) /* Compatibility range, sta f/w actor, CFI supplier */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STA_CFIACTRANGES, &hw->cap_act_sta_cfi, - sizeof(hfa384x_caplevel_t)); + sizeof(struct hfa384x_caplevel)); if (result) { netdev_err(wlandev->netdev, "Failed to retrieve STA_CFIACTRANGES\n"); goto failed; @@ -823,7 +823,7 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev) /* Compatibility range, sta f/w actor, MFI supplier */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STA_MFIACTRANGES, &hw->cap_act_sta_mfi, - sizeof(hfa384x_caplevel_t)); + sizeof(struct hfa384x_caplevel)); if (result) { netdev_err(wlandev->netdev, "Failed to retrieve STA_MFIACTRANGES\n"); goto failed; -- cgit v0.10.2 From 935cbfb2bd16404c908c0902fa493939d6190de2 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:18:58 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_HostScanRequest_data_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_HostScanRequest_data_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index e02f894..2ac10a0 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -408,11 +408,11 @@ struct hfa384x_caplevel { #define HFA384x_CREATEIBSS_JOINCREATEIBSS 0 /*-- Configuration Record: HostScanRequest (data portion only) --*/ -typedef struct hfa384x_HostScanRequest_data { +struct hfa384x_HostScanRequest_data { u16 channelList; u16 txRate; struct hfa384x_bytestr32 ssid; -} __packed hfa384x_HostScanRequest_data_t; +} __packed; /*-- Configuration Record: JoinRequest (data portion only) --*/ typedef struct hfa384x_JoinRequest_data { diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c index 5e5d0ab..1a98d69 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.c +++ b/drivers/staging/wlan-ng/prism2mgmt.c @@ -122,7 +122,7 @@ int prism2mgmt_scan(struct wlandevice *wlandev, void *msgp) int i, timeout; int istmpenable = 0; - hfa384x_HostScanRequest_data_t scanreq; + struct hfa384x_HostScanRequest_data scanreq; /* gatekeeper check */ if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major, @@ -292,7 +292,7 @@ int prism2mgmt_scan(struct wlandevice *wlandev, void *msgp) result = hfa384x_drvr_setconfig(hw, HFA384x_RID_HOSTSCAN, &scanreq, - sizeof(hfa384x_HostScanRequest_data_t)); + sizeof(struct hfa384x_HostScanRequest_data)); if (result) { netdev_err(wlandev->netdev, "setconfig(SCANREQUEST) failed. result=%d\n", -- cgit v0.10.2 From f0ffa0e2a01904764700afa681ba30f7db051e03 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:18:59 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_JoinRequest_data_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_JoinRequest_data_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 2ac10a0..46487da 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -266,7 +266,7 @@ #define HFA384x_RID_DBMCOMMSQUALITY_LEN \ ((u16)sizeof(hfa384x_dbmcommsquality_t)) #define HFA384x_RID_JOINREQUEST_LEN \ - ((u16)sizeof(hfa384x_JoinRequest_data_t)) + ((u16)sizeof(struct hfa384x_JoinRequest_data)) /*-------------------------------------------------------------------- * Information RIDs: Modem Information @@ -415,10 +415,10 @@ struct hfa384x_HostScanRequest_data { } __packed; /*-- Configuration Record: JoinRequest (data portion only) --*/ -typedef struct hfa384x_JoinRequest_data { +struct hfa384x_JoinRequest_data { u8 bssid[WLAN_BSSID_LEN]; u16 channel; -} __packed hfa384x_JoinRequest_data_t; +} __packed; /*-- Configuration Record: authenticateStation (data portion only) --*/ typedef struct hfa384x_authenticateStation_data { @@ -1298,7 +1298,7 @@ typedef struct hfa384x { int scanflag; /* to signal scan complete */ int join_ap; /* are we joined to a specific ap */ int join_retries; /* number of join retries till we fail */ - hfa384x_JoinRequest_data_t joinreq; /* join request saved data */ + struct hfa384x_JoinRequest_data joinreq; /* join request saved data */ struct wlandevice *wlandev; /* Timer to allow for the deferred processing of linkstatus messages */ diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index 850cbbc..461eedf 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -1037,7 +1037,7 @@ static void prism2sta_inf_scanresults(struct wlandevice *wlandev, int nbss; hfa384x_ScanResult_t *sr = &(inf->info.scanresult); int i; - hfa384x_JoinRequest_data_t joinreq; + struct hfa384x_JoinRequest_data joinreq; int result; /* Get the number of results, first in bytes, then in results */ @@ -1391,7 +1391,7 @@ void prism2sta_processing_defer(struct work_struct *data) * Disable Transmits, Ignore receives of data frames */ if (hw->join_ap && --hw->join_retries > 0) { - hfa384x_JoinRequest_data_t joinreq; + struct hfa384x_JoinRequest_data joinreq; joinreq = hw->joinreq; /* Send the join request */ -- cgit v0.10.2 From 17fb19f022ec36007567ad40bcef42d812cf24e0 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:00 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_authenticateStation_data_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_authenticateStation_data_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 46487da..385a332 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -421,11 +421,11 @@ struct hfa384x_JoinRequest_data { } __packed; /*-- Configuration Record: authenticateStation (data portion only) --*/ -typedef struct hfa384x_authenticateStation_data { +struct hfa384x_authenticateStation_data { u8 address[ETH_ALEN]; u16 status; u16 algorithm; -} __packed hfa384x_authenticateStation_data_t; +} __packed; /*-- Configuration Record: WPAData (data portion only) --*/ typedef struct hfa384x_WPAData { diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index 461eedf..0b09c05 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -1547,7 +1547,7 @@ static void prism2sta_inf_authreq_defer(struct wlandevice *wlandev, hfa384x_InfFrame_t *inf) { hfa384x_t *hw = wlandev->priv; - hfa384x_authenticateStation_data_t rec; + struct hfa384x_authenticateStation_data rec; int i, added, result, cnt; u8 *addr; -- cgit v0.10.2 From a2a4480370d22d1a4d24a86a5f9f2c984305bb04 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:01 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_WPAData_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_WPAData_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 385a332..f7dadfb 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -428,10 +428,10 @@ struct hfa384x_authenticateStation_data { } __packed; /*-- Configuration Record: WPAData (data portion only) --*/ -typedef struct hfa384x_WPAData { +struct hfa384x_WPAData { u16 datalen; u8 data[0]; /* max 80 */ -} __packed hfa384x_WPAData_t; +} __packed; /*-------------------------------------------------------------------- * Information Record Structures: NIC Information diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c index 3442de3..95bab45 100644 --- a/drivers/staging/wlan-ng/prism2mib.c +++ b/drivers/staging/wlan-ng/prism2mib.c @@ -709,7 +709,7 @@ static int prism2mib_priv(struct mibrec *mib, switch (mib->did) { case DIDmib_lnx_lnxConfigTable_lnxRSNAIE:{ - hfa384x_WPAData_t wpa; + struct hfa384x_WPAData wpa; if (isget) { hfa384x_drvr_getconfig(hw, -- cgit v0.10.2 From b71db7404d576f6edde5282b638c905f0f21aedc Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:02 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_downloadbuffer_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_downloadbuffer_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index f7dadfb..761d2c2 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -440,11 +440,11 @@ struct hfa384x_WPAData { /*-- Information Record: DownLoadBuffer --*/ /* NOTE: The page and offset are in AUX format */ -typedef struct hfa384x_downloadbuffer { +struct hfa384x_downloadbuffer { u16 page; u16 offset; u16 len; -} __packed hfa384x_downloadbuffer_t; +} __packed; /*-------------------------------------------------------------------- * Information Record Structures: NIC Information @@ -1292,7 +1292,7 @@ typedef struct hfa384x { /* Download support */ unsigned int dlstate; - hfa384x_downloadbuffer_t bufinfo; + struct hfa384x_downloadbuffer bufinfo; u16 dltimeout; int scanflag; /* to signal scan complete */ -- cgit v0.10.2 From a1e950452be0d90c8e2c7593a825e35666073378 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:03 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_commsquality_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_commsquality_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 761d2c2..41d8a87 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -454,11 +454,11 @@ struct hfa384x_downloadbuffer { #define HFA384x_PSTATUS_CONN_IBSS ((u16)3) /*-- Information Record: commsquality --*/ -typedef struct hfa384x_commsquality { +struct hfa384x_commsquality { u16 CQ_currBSS; u16 ASL_currBSS; u16 ANL_currFC; -} __packed hfa384x_commsquality_t; +} __packed; /*-- Information Record: dmbcommsquality --*/ typedef struct hfa384x_dbmcommsquality { @@ -1305,7 +1305,7 @@ typedef struct hfa384x { struct work_struct link_bh; struct work_struct commsqual_bh; - hfa384x_commsquality_t qual; + struct hfa384x_commsquality qual; struct timer_list commsqual_timer; u16 link_status; -- cgit v0.10.2 From 62e493c4540a775becfeca1fb7b8c613adc14abe Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:04 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_dbmcommsquality_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_dbmcommsquality_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 41d8a87..1390236 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -264,7 +264,7 @@ *-------------------------------------------------------------------- */ #define HFA384x_RID_DBMCOMMSQUALITY_LEN \ - ((u16)sizeof(hfa384x_dbmcommsquality_t)) + ((u16)sizeof(struct hfa384x_dbmcommsquality)) #define HFA384x_RID_JOINREQUEST_LEN \ ((u16)sizeof(struct hfa384x_JoinRequest_data)) @@ -461,11 +461,11 @@ struct hfa384x_commsquality { } __packed; /*-- Information Record: dmbcommsquality --*/ -typedef struct hfa384x_dbmcommsquality { +struct hfa384x_dbmcommsquality { u16 CQdbm_currBSS; u16 ASLdbm_currBSS; u16 ANLdbm_currFC; -} __packed hfa384x_dbmcommsquality_t; +} __packed; /*-------------------------------------------------------------------- * FRAME STRUCTURES: Communication Frames -- cgit v0.10.2 From eb76afc917fd7acc8b33061f39d3f1b566b7c77c Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:05 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_tx_frame_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_tx_frame_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 1390236..cb416ce 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -474,7 +474,7 @@ struct hfa384x_dbmcommsquality { *-------------------------------------------------------------------- */ /*-- Communication Frame: Transmit Frame Structure --*/ -typedef struct hfa384x_tx_frame { +struct hfa384x_tx_frame { u16 status; u16 reserved1; u16 reserved2; @@ -499,7 +499,7 @@ typedef struct hfa384x_tx_frame { u8 dest_addr[6]; u8 src_addr[6]; u16 data_length; /* big endian format */ -} __packed hfa384x_tx_frame_t; +} __packed; /*-------------------------------------------------------------------- * Communication Frames: Field Masks for Transmit Frames *-------------------------------------------------------------------- @@ -809,7 +809,7 @@ typedef struct hfa384x_InfFrame { /* Request (bulk OUT) packet contents */ typedef struct hfa384x_usb_txfrm { - hfa384x_tx_frame_t desc; + struct hfa384x_tx_frame desc; u8 data[WLAN_DATA_MAXLEN]; } __packed hfa384x_usb_txfrm_t; diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 9c29311..044ca4d 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -2566,7 +2566,7 @@ int hfa384x_drvr_txframe(hfa384x_t *hw, struct sk_buff *skb, union p80211_hdr *p80211_hdr, struct p80211_metawep *p80211_wep) { - int usbpktlen = sizeof(hfa384x_tx_frame_t); + int usbpktlen = sizeof(struct hfa384x_tx_frame); int result; int ret; char *ptr; -- cgit v0.10.2 From 70adf50956a47a2aeb7fa99015ea96f2632c7193 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:06 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_rx_frame_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_rx_frame_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index cb416ce..d663faf 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -539,7 +539,7 @@ struct hfa384x_tx_frame { *-------------------------------------------------------------------- */ /*-- Communication Frame: Receive Frame Structure --*/ -typedef struct hfa384x_rx_frame { +struct hfa384x_rx_frame { /*-- MAC rx descriptor (hfa384x byte order) --*/ u16 status; u32 time; @@ -564,7 +564,7 @@ typedef struct hfa384x_rx_frame { u8 dest_addr[6]; u8 src_addr[6]; u16 data_length; /* IEEE? (big endian) format */ -} __packed hfa384x_rx_frame_t; +} __packed; /*-------------------------------------------------------------------- * Communication Frames: Field Masks for Receive Frames *-------------------------------------------------------------------- @@ -856,7 +856,7 @@ typedef struct hfa384x_usb_rmemreq { /* Response (bulk IN) packet contents */ typedef struct hfa384x_usb_rxfrm { - hfa384x_rx_frame_t desc; + struct hfa384x_rx_frame desc; u8 data[WLAN_DATA_MAXLEN]; } __packed hfa384x_usb_rxfrm_t; diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 044ca4d..f1809af 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -3346,7 +3346,7 @@ static void hfa384x_usbin_rx(struct wlandevice *wlandev, struct sk_buff *skb) hdrlen = p80211_headerlen(fc); /* Pull off the descriptor */ - skb_pull(skb, sizeof(hfa384x_rx_frame_t)); + skb_pull(skb, sizeof(struct hfa384x_rx_frame)); /* Now shunt the header block up against the data block * with an "overlapping" copy @@ -3419,7 +3419,7 @@ static void hfa384x_usbin_rx(struct wlandevice *wlandev, struct sk_buff *skb) static void hfa384x_int_rxmonitor(struct wlandevice *wlandev, hfa384x_usb_rxfrm_t *rxfrm) { - hfa384x_rx_frame_t *rxdesc = &(rxfrm->desc); + struct hfa384x_rx_frame *rxdesc = &(rxfrm->desc); unsigned int hdrlen = 0; unsigned int datalen = 0; unsigned int skblen = 0; -- cgit v0.10.2 From 07e23b67c53193cfcc8b58184dba017a113cf407 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:07 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_CommTallies16_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_CommTallies16_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index d663faf..1ff46fe 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -610,7 +610,7 @@ struct hfa384x_rx_frame { */ /*-- Inquiry Frame, Diagnose: Communication Tallies --*/ -typedef struct hfa384x_CommTallies16 { +struct hfa384x_CommTallies16 { u16 txunicastframes; u16 txmulticastframes; u16 txfragments; @@ -632,7 +632,7 @@ typedef struct hfa384x_CommTallies16 { u16 rxdiscardswepundecr; u16 rxmsginmsgfrag; u16 rxmsginbadmsgfrag; -} __packed hfa384x_CommTallies16_t; +} __packed; typedef struct hfa384x_CommTallies32 { u32 txunicastframes; @@ -762,7 +762,7 @@ typedef struct hfa384x_KeyIDChanged { /*-- Collection of all Inf frames ---------------*/ typedef union hfa384x_infodata { - hfa384x_CommTallies16_t commtallies16; + struct hfa384x_CommTallies16 commtallies16; hfa384x_CommTallies32_t commtallies32; hfa384x_ScanResult_t scanresult; hfa384x_ChInfoResult_t chinforesult; -- cgit v0.10.2 From cfc6cb1fea8c7414e73f4d3cbeb10e0d6e28ed65 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:08 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_CommTallies32_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_CommTallies32_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 1ff46fe..40cbe64 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -634,7 +634,7 @@ struct hfa384x_CommTallies16 { u16 rxmsginbadmsgfrag; } __packed; -typedef struct hfa384x_CommTallies32 { +struct hfa384x_CommTallies32 { u32 txunicastframes; u32 txmulticastframes; u32 txfragments; @@ -656,7 +656,7 @@ typedef struct hfa384x_CommTallies32 { u32 rxdiscardswepundecr; u32 rxmsginmsgfrag; u32 rxmsginbadmsgfrag; -} __packed hfa384x_CommTallies32_t; +} __packed; /*-- Inquiry Frame, Diagnose: Scan Results & Subfields--*/ typedef struct hfa384x_ScanResultSub { @@ -763,7 +763,7 @@ typedef struct hfa384x_KeyIDChanged { /*-- Collection of all Inf frames ---------------*/ typedef union hfa384x_infodata { struct hfa384x_CommTallies16 commtallies16; - hfa384x_CommTallies32_t commtallies32; + struct hfa384x_CommTallies32 commtallies32; hfa384x_ScanResult_t scanresult; hfa384x_ChInfoResult_t chinforesult; hfa384x_HScanResult_t hscanresult; @@ -1364,7 +1364,7 @@ typedef struct hfa384x { struct hfa384x_caplevel cap_act_ap_mfi; /* ap f/w to modem interface */ u32 psusercount; /* Power save user count. */ - hfa384x_CommTallies32_t tallies; /* Communication tallies. */ + struct hfa384x_CommTallies32 tallies; /* Communication tallies. */ u8 comment[WLAN_COMMENT_MAX + 1]; /* User comment */ /* Channel Info request results (AP only) */ diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index 0b09c05..9b95d6f 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -999,7 +999,7 @@ static void prism2sta_inf_tallies(struct wlandevice *wlandev, * record length of the info record. */ - cnt = sizeof(hfa384x_CommTallies32_t) / sizeof(u32); + cnt = sizeof(struct hfa384x_CommTallies32) / sizeof(u32); if (inf->framelen > 22) { dst = (u32 *)&hw->tallies; src32 = (u32 *)&inf->info.commtallies32; -- cgit v0.10.2 From 4400334b568dbfb3eb0cabe8fadfd5c43e59ca02 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:09 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_ScanResultSub_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_ScanResultSub_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 40cbe64..97a796e 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -659,7 +659,7 @@ struct hfa384x_CommTallies32 { } __packed; /*-- Inquiry Frame, Diagnose: Scan Results & Subfields--*/ -typedef struct hfa384x_ScanResultSub { +struct hfa384x_ScanResultSub { u16 chid; u16 anl; u16 sl; @@ -669,12 +669,12 @@ typedef struct hfa384x_ScanResultSub { struct hfa384x_bytestr32 ssid; u8 supprates[10]; /* 802.11 info element */ u16 proberesp_rate; -} __packed hfa384x_ScanResultSub_t; +} __packed; typedef struct hfa384x_ScanResult { u16 rsvd; u16 scanreason; - hfa384x_ScanResultSub_t result[HFA384x_SCANRESULT_MAX]; + struct hfa384x_ScanResultSub result[HFA384x_SCANRESULT_MAX]; } __packed hfa384x_ScanResult_t; /*-- Inquiry Frame, Diagnose: ChInfo Results & Subfields--*/ diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index 9b95d6f..8cf81c6 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -1043,7 +1043,7 @@ static void prism2sta_inf_scanresults(struct wlandevice *wlandev, /* Get the number of results, first in bytes, then in results */ nbss = (inf->framelen * sizeof(u16)) - sizeof(inf->infotype) - sizeof(inf->info.scanresult.scanreason); - nbss /= sizeof(hfa384x_ScanResultSub_t); + nbss /= sizeof(struct hfa384x_ScanResultSub); /* Print em */ pr_debug("rx scanresults, reason=%d, nbss=%d:\n", -- cgit v0.10.2 From dc0bb002b3f2029e55c58a9a26fb49b4dd06e652 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:10 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_ScanResult_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_ScanResult_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 97a796e..1da5a67 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -671,11 +671,11 @@ struct hfa384x_ScanResultSub { u16 proberesp_rate; } __packed; -typedef struct hfa384x_ScanResult { +struct hfa384x_ScanResult { u16 rsvd; u16 scanreason; struct hfa384x_ScanResultSub result[HFA384x_SCANRESULT_MAX]; -} __packed hfa384x_ScanResult_t; +} __packed; /*-- Inquiry Frame, Diagnose: ChInfo Results & Subfields--*/ typedef struct hfa384x_ChInfoResultSub { @@ -764,7 +764,7 @@ typedef struct hfa384x_KeyIDChanged { typedef union hfa384x_infodata { struct hfa384x_CommTallies16 commtallies16; struct hfa384x_CommTallies32 commtallies32; - hfa384x_ScanResult_t scanresult; + struct hfa384x_ScanResult scanresult; hfa384x_ChInfoResult_t chinforesult; hfa384x_HScanResult_t hscanresult; hfa384x_LinkStatus_t linkstatus; diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index 8cf81c6..dfb7a73 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -1035,7 +1035,7 @@ static void prism2sta_inf_scanresults(struct wlandevice *wlandev, { hfa384x_t *hw = wlandev->priv; int nbss; - hfa384x_ScanResult_t *sr = &(inf->info.scanresult); + struct hfa384x_ScanResult *sr = &(inf->info.scanresult); int i; struct hfa384x_JoinRequest_data joinreq; int result; -- cgit v0.10.2 From 1bc4292aaa07347f0870b6690814b4e0a3a0c281 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:11 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_ChInfoResultSub_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_ChInfoResultSub_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 1da5a67..beb97d9 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -678,19 +678,19 @@ struct hfa384x_ScanResult { } __packed; /*-- Inquiry Frame, Diagnose: ChInfo Results & Subfields--*/ -typedef struct hfa384x_ChInfoResultSub { +struct hfa384x_ChInfoResultSub { u16 chid; u16 anl; u16 pnl; u16 active; -} __packed hfa384x_ChInfoResultSub_t; +} __packed; #define HFA384x_CHINFORESULT_BSSACTIVE BIT(0) #define HFA384x_CHINFORESULT_PCFACTIVE BIT(1) typedef struct hfa384x_ChInfoResult { u16 scanchannels; - hfa384x_ChInfoResultSub_t result[HFA384x_CHINFORESULT_MAX]; + struct hfa384x_ChInfoResultSub result[HFA384x_CHINFORESULT_MAX]; } __packed hfa384x_ChInfoResult_t; /*-- Inquiry Frame, Diagnose: Host Scan Results & Subfields--*/ diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index dfb7a73..7e1c338 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -1136,8 +1136,8 @@ static void prism2sta_inf_chinforesults(struct wlandevice *wlandev, le16_to_cpu(inf->info.chinforesult.scanchannels); for (i = 0, n = 0; i < HFA384x_CHINFORESULT_MAX; i++) { - hfa384x_ChInfoResultSub_t *result; - hfa384x_ChInfoResultSub_t *chinforesult; + struct hfa384x_ChInfoResultSub *result; + struct hfa384x_ChInfoResultSub *chinforesult; int chan; if (!(hw->channel_info.results.scanchannels & (1 << i))) -- cgit v0.10.2 From 0fddae8ef86305135d3509953d1311199c5d2137 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:12 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_ChInfoResult_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_ChInfoResult_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index beb97d9..8fee24b 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -688,10 +688,10 @@ struct hfa384x_ChInfoResultSub { #define HFA384x_CHINFORESULT_BSSACTIVE BIT(0) #define HFA384x_CHINFORESULT_PCFACTIVE BIT(1) -typedef struct hfa384x_ChInfoResult { +struct hfa384x_ChInfoResult { u16 scanchannels; struct hfa384x_ChInfoResultSub result[HFA384x_CHINFORESULT_MAX]; -} __packed hfa384x_ChInfoResult_t; +} __packed; /*-- Inquiry Frame, Diagnose: Host Scan Results & Subfields--*/ typedef struct hfa384x_HScanResultSub { @@ -765,7 +765,7 @@ typedef union hfa384x_infodata { struct hfa384x_CommTallies16 commtallies16; struct hfa384x_CommTallies32 commtallies32; struct hfa384x_ScanResult scanresult; - hfa384x_ChInfoResult_t chinforesult; + struct hfa384x_ChInfoResult chinforesult; hfa384x_HScanResult_t hscanresult; hfa384x_LinkStatus_t linkstatus; hfa384x_AssocStatus_t assocstatus; @@ -1371,7 +1371,7 @@ typedef struct hfa384x { struct { atomic_t done; u8 count; - hfa384x_ChInfoResult_t results; + struct hfa384x_ChInfoResult results; } channel_info; hfa384x_InfFrame_t *scanresults; -- cgit v0.10.2 From b353d11af9a07fbdfe4f98a466bb26405d5aacbb Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:13 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_HScanResultSub_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_HScanResultSub_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 8fee24b..343debb 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -694,7 +694,7 @@ struct hfa384x_ChInfoResult { } __packed; /*-- Inquiry Frame, Diagnose: Host Scan Results & Subfields--*/ -typedef struct hfa384x_HScanResultSub { +struct hfa384x_HScanResultSub { u16 chid; u16 anl; u16 sl; @@ -705,12 +705,12 @@ typedef struct hfa384x_HScanResultSub { u8 supprates[10]; /* 802.11 info element */ u16 proberesp_rate; u16 atim; -} __packed hfa384x_HScanResultSub_t; +} __packed; typedef struct hfa384x_HScanResult { u16 nresult; u16 rsvd; - hfa384x_HScanResultSub_t result[HFA384x_HSCANRESULT_MAX]; + struct hfa384x_HScanResultSub result[HFA384x_HSCANRESULT_MAX]; } __packed hfa384x_HScanResult_t; /*-- Unsolicited Frame, MAC Mgmt: LinkStatus --*/ diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c index 1a98d69..1780875 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.c +++ b/drivers/staging/wlan-ng/prism2mgmt.c @@ -371,7 +371,7 @@ int prism2mgmt_scan_results(struct wlandevice *wlandev, void *msgp) int result = 0; struct p80211msg_dot11req_scan_results *req; hfa384x_t *hw = wlandev->priv; - hfa384x_HScanResultSub_t *item = NULL; + struct hfa384x_HScanResultSub *item = NULL; int count; -- cgit v0.10.2 From f8f2821e36903fefc58ec50b8066dd129373b26f Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:14 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_HScanResult_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_HScanResult_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 343debb..123987f 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -707,11 +707,11 @@ struct hfa384x_HScanResultSub { u16 atim; } __packed; -typedef struct hfa384x_HScanResult { +struct hfa384x_HScanResult { u16 nresult; u16 rsvd; struct hfa384x_HScanResultSub result[HFA384x_HSCANRESULT_MAX]; -} __packed hfa384x_HScanResult_t; +} __packed; /*-- Unsolicited Frame, MAC Mgmt: LinkStatus --*/ @@ -766,7 +766,7 @@ typedef union hfa384x_infodata { struct hfa384x_CommTallies32 commtallies32; struct hfa384x_ScanResult scanresult; struct hfa384x_ChInfoResult chinforesult; - hfa384x_HScanResult_t hscanresult; + struct hfa384x_HScanResult hscanresult; hfa384x_LinkStatus_t linkstatus; hfa384x_AssocStatus_t assocstatus; hfa384x_AuthReq_t authreq; -- cgit v0.10.2 From a8eb513929afb38d8ec9f4ed2ab8fa82c7b76c35 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:15 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_LinkStatus_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_LinkStatus_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 123987f..8f8c64d 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -723,9 +723,9 @@ struct hfa384x_HScanResult { #define HFA384x_LINK_AP_INRANGE ((u16)5) #define HFA384x_LINK_ASSOCFAIL ((u16)6) -typedef struct hfa384x_LinkStatus { +struct hfa384x_LinkStatus { u16 linkstatus; -} __packed hfa384x_LinkStatus_t; +} __packed; /*-- Unsolicited Frame, MAC Mgmt: AssociationStatus (--*/ @@ -767,7 +767,7 @@ typedef union hfa384x_infodata { struct hfa384x_ScanResult scanresult; struct hfa384x_ChInfoResult chinforesult; struct hfa384x_HScanResult hscanresult; - hfa384x_LinkStatus_t linkstatus; + struct hfa384x_LinkStatus linkstatus; hfa384x_AssocStatus_t assocstatus; hfa384x_AuthReq_t authreq; hfa384x_PSUserCount_t psusercnt; -- cgit v0.10.2 From 5383f13eb1fc77a081a7cf81e437e3141c591d36 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:16 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_AssocStatus_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_AssocStatus_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 8f8c64d..c8f5493 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -733,14 +733,14 @@ struct hfa384x_LinkStatus { #define HFA384x_ASSOCSTATUS_REASSOC ((u16)2) #define HFA384x_ASSOCSTATUS_AUTHFAIL ((u16)5) -typedef struct hfa384x_AssocStatus { +struct hfa384x_AssocStatus { u16 assocstatus; u8 sta_addr[ETH_ALEN]; /* old_ap_addr is only valid if assocstatus == 2 */ u8 old_ap_addr[ETH_ALEN]; u16 reason; u16 reserved; -} __packed hfa384x_AssocStatus_t; +} __packed; /*-- Unsolicited Frame, MAC Mgmt: AuthRequest (AP Only) --*/ @@ -768,7 +768,7 @@ typedef union hfa384x_infodata { struct hfa384x_ChInfoResult chinforesult; struct hfa384x_HScanResult hscanresult; struct hfa384x_LinkStatus linkstatus; - hfa384x_AssocStatus_t assocstatus; + struct hfa384x_AssocStatus assocstatus; hfa384x_AuthReq_t authreq; hfa384x_PSUserCount_t psusercnt; hfa384x_KeyIDChanged_t keyidchanged; diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index 7e1c338..bc3941c2 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -1471,7 +1471,7 @@ static void prism2sta_inf_assocstatus(struct wlandevice *wlandev, hfa384x_InfFrame_t *inf) { hfa384x_t *hw = wlandev->priv; - hfa384x_AssocStatus_t rec; + struct hfa384x_AssocStatus rec; int i; memcpy(&rec, &inf->info.assocstatus, sizeof(rec)); -- cgit v0.10.2 From b9820e0c4fb736cab991ebd4346fcfc525c5ff3d Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:17 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_AuthReq_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_AuthReq_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index c8f5493..10d13d4 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -744,10 +744,10 @@ struct hfa384x_AssocStatus { /*-- Unsolicited Frame, MAC Mgmt: AuthRequest (AP Only) --*/ -typedef struct hfa384x_AuthRequest { +struct hfa384x_AuthRequest { u8 sta_addr[ETH_ALEN]; u16 algorithm; -} __packed hfa384x_AuthReq_t; +} __packed; /*-- Unsolicited Frame, MAC Mgmt: PSUserCount (AP Only) --*/ @@ -769,7 +769,7 @@ typedef union hfa384x_infodata { struct hfa384x_HScanResult hscanresult; struct hfa384x_LinkStatus linkstatus; struct hfa384x_AssocStatus assocstatus; - hfa384x_AuthReq_t authreq; + struct hfa384x_AuthRequest authreq; hfa384x_PSUserCount_t psusercnt; hfa384x_KeyIDChanged_t keyidchanged; } __packed hfa384x_infodata_t; -- cgit v0.10.2 From 013e69ebd682fba2891d24f2e022089aa9b5677c Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:18 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_PSUserCount_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_PSUserCount_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 10d13d4..4d078e2 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -751,9 +751,9 @@ struct hfa384x_AuthRequest { /*-- Unsolicited Frame, MAC Mgmt: PSUserCount (AP Only) --*/ -typedef struct hfa384x_PSUserCount { +struct hfa384x_PSUserCount { u16 usercnt; -} __packed hfa384x_PSUserCount_t; +} __packed; typedef struct hfa384x_KeyIDChanged { u8 sta_addr[ETH_ALEN]; @@ -770,7 +770,7 @@ typedef union hfa384x_infodata { struct hfa384x_LinkStatus linkstatus; struct hfa384x_AssocStatus assocstatus; struct hfa384x_AuthRequest authreq; - hfa384x_PSUserCount_t psusercnt; + struct hfa384x_PSUserCount psusercnt; hfa384x_KeyIDChanged_t keyidchanged; } __packed hfa384x_infodata_t; -- cgit v0.10.2 From 44049d81b5ba531418a9a4360e7e6a9599f49527 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:19 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_KeyIDChanged_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_KeyIDChanged_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 4d078e2..532b1a7 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -755,10 +755,10 @@ struct hfa384x_PSUserCount { u16 usercnt; } __packed; -typedef struct hfa384x_KeyIDChanged { +struct hfa384x_KeyIDChanged { u8 sta_addr[ETH_ALEN]; u16 keyid; -} __packed hfa384x_KeyIDChanged_t; +} __packed; /*-- Collection of all Inf frames ---------------*/ typedef union hfa384x_infodata { @@ -771,7 +771,7 @@ typedef union hfa384x_infodata { struct hfa384x_AssocStatus assocstatus; struct hfa384x_AuthRequest authreq; struct hfa384x_PSUserCount psusercnt; - hfa384x_KeyIDChanged_t keyidchanged; + struct hfa384x_KeyIDChanged keyidchanged; } __packed hfa384x_infodata_t; typedef struct hfa384x_InfFrame { -- cgit v0.10.2 From f745ea612a91cd19189ab18940c7e8d370d92f0b Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:20 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_infodata_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_infodata_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 532b1a7..7accea2 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -761,7 +761,7 @@ struct hfa384x_KeyIDChanged { } __packed; /*-- Collection of all Inf frames ---------------*/ -typedef union hfa384x_infodata { +union hfa384x_infodata { struct hfa384x_CommTallies16 commtallies16; struct hfa384x_CommTallies32 commtallies32; struct hfa384x_ScanResult scanresult; @@ -772,12 +772,12 @@ typedef union hfa384x_infodata { struct hfa384x_AuthRequest authreq; struct hfa384x_PSUserCount psusercnt; struct hfa384x_KeyIDChanged keyidchanged; -} __packed hfa384x_infodata_t; +} __packed; typedef struct hfa384x_InfFrame { u16 framelen; u16 infotype; - hfa384x_infodata_t info; + union hfa384x_infodata info; } __packed hfa384x_InfFrame_t; /*-------------------------------------------------------------------- -- cgit v0.10.2 From f69de9e3fc07571f0c05041dafb839274949fe77 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:21 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_InfFrame_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_InfFrame_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 7accea2..29d9bc5 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -774,11 +774,11 @@ union hfa384x_infodata { struct hfa384x_KeyIDChanged keyidchanged; } __packed; -typedef struct hfa384x_InfFrame { +struct hfa384x_InfFrame { u16 framelen; u16 infotype; union hfa384x_infodata info; -} __packed hfa384x_InfFrame_t; +} __packed; /*-------------------------------------------------------------------- * USB Packet structures and constants. @@ -862,7 +862,7 @@ typedef struct hfa384x_usb_rxfrm { typedef struct hfa384x_usb_infofrm { u16 type; - hfa384x_InfFrame_t info; + struct hfa384x_InfFrame info; } __packed hfa384x_usb_infofrm_t; typedef struct hfa384x_usb_statusresp { @@ -1374,7 +1374,7 @@ typedef struct hfa384x { struct hfa384x_ChInfoResult results; } channel_info; - hfa384x_InfFrame_t *scanresults; + struct hfa384x_InfFrame *scanresults; struct prism2sta_authlist authlist; /* Authenticated station list. */ unsigned int accessmode; /* Access mode. */ diff --git a/drivers/staging/wlan-ng/prism2mgmt.h b/drivers/staging/wlan-ng/prism2mgmt.h index 5a4bc75..a275e97 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.h +++ b/drivers/staging/wlan-ng/prism2mgmt.h @@ -65,7 +65,7 @@ extern int prism2_reset_settletime; u32 prism2sta_ifstate(struct wlandevice *wlandev, u32 ifstate); -void prism2sta_ev_info(struct wlandevice *wlandev, hfa384x_InfFrame_t *inf); +void prism2sta_ev_info(struct wlandevice *wlandev, struct hfa384x_InfFrame *inf); void prism2sta_ev_txexc(struct wlandevice *wlandev, u16 status); void prism2sta_ev_tx(struct wlandevice *wlandev, u16 status); void prism2sta_ev_alloc(struct wlandevice *wlandev); diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index bc3941c2..59f4619 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -111,25 +111,25 @@ static int prism2sta_setmulticast(struct wlandevice *wlandev, struct net_device *dev); static void prism2sta_inf_handover(struct wlandevice *wlandev, - hfa384x_InfFrame_t *inf); + struct hfa384x_InfFrame *inf); static void prism2sta_inf_tallies(struct wlandevice *wlandev, - hfa384x_InfFrame_t *inf); + struct hfa384x_InfFrame *inf); static void prism2sta_inf_hostscanresults(struct wlandevice *wlandev, - hfa384x_InfFrame_t *inf); + struct hfa384x_InfFrame *inf); static void prism2sta_inf_scanresults(struct wlandevice *wlandev, - hfa384x_InfFrame_t *inf); + struct hfa384x_InfFrame *inf); static void prism2sta_inf_chinforesults(struct wlandevice *wlandev, - hfa384x_InfFrame_t *inf); + struct hfa384x_InfFrame *inf); static void prism2sta_inf_linkstatus(struct wlandevice *wlandev, - hfa384x_InfFrame_t *inf); + struct hfa384x_InfFrame *inf); static void prism2sta_inf_assocstatus(struct wlandevice *wlandev, - hfa384x_InfFrame_t *inf); + struct hfa384x_InfFrame *inf); static void prism2sta_inf_authreq(struct wlandevice *wlandev, - hfa384x_InfFrame_t *inf); + struct hfa384x_InfFrame *inf); static void prism2sta_inf_authreq_defer(struct wlandevice *wlandev, - hfa384x_InfFrame_t *inf); + struct hfa384x_InfFrame *inf); static void prism2sta_inf_psusercnt(struct wlandevice *wlandev, - hfa384x_InfFrame_t *inf); + struct hfa384x_InfFrame *inf); /* * prism2sta_open @@ -962,7 +962,7 @@ exit: * interrupt */ static void prism2sta_inf_handover(struct wlandevice *wlandev, - hfa384x_InfFrame_t *inf) + struct hfa384x_InfFrame *inf) { pr_debug("received infoframe:HANDOVER (unhandled)\n"); } @@ -985,7 +985,7 @@ static void prism2sta_inf_handover(struct wlandevice *wlandev, * interrupt */ static void prism2sta_inf_tallies(struct wlandevice *wlandev, - hfa384x_InfFrame_t *inf) + struct hfa384x_InfFrame *inf) { hfa384x_t *hw = wlandev->priv; u16 *src16; @@ -1031,7 +1031,7 @@ static void prism2sta_inf_tallies(struct wlandevice *wlandev, * interrupt */ static void prism2sta_inf_scanresults(struct wlandevice *wlandev, - hfa384x_InfFrame_t *inf) + struct hfa384x_InfFrame *inf) { hfa384x_t *hw = wlandev->priv; int nbss; @@ -1086,7 +1086,7 @@ static void prism2sta_inf_scanresults(struct wlandevice *wlandev, * interrupt */ static void prism2sta_inf_hostscanresults(struct wlandevice *wlandev, - hfa384x_InfFrame_t *inf) + struct hfa384x_InfFrame *inf) { hfa384x_t *hw = wlandev->priv; int nbss; @@ -1099,7 +1099,7 @@ static void prism2sta_inf_hostscanresults(struct wlandevice *wlandev, kfree(hw->scanresults); - hw->scanresults = kmemdup(inf, sizeof(hfa384x_InfFrame_t), GFP_ATOMIC); + hw->scanresults = kmemdup(inf, sizeof(struct hfa384x_InfFrame), GFP_ATOMIC); if (nbss == 0) nbss = -1; @@ -1127,7 +1127,7 @@ static void prism2sta_inf_hostscanresults(struct wlandevice *wlandev, * interrupt */ static void prism2sta_inf_chinforesults(struct wlandevice *wlandev, - hfa384x_InfFrame_t *inf) + struct hfa384x_InfFrame *inf) { hfa384x_t *hw = wlandev->priv; unsigned int i, n; @@ -1179,10 +1179,10 @@ void prism2sta_processing_defer(struct work_struct *data) /* First let's process the auth frames */ { struct sk_buff *skb; - hfa384x_InfFrame_t *inf; + struct hfa384x_InfFrame *inf; while ((skb = skb_dequeue(&hw->authq))) { - inf = (hfa384x_InfFrame_t *)skb->data; + inf = (struct hfa384x_InfFrame *)skb->data; prism2sta_inf_authreq_defer(wlandev, inf); } @@ -1440,7 +1440,7 @@ void prism2sta_processing_defer(struct work_struct *data) * interrupt */ static void prism2sta_inf_linkstatus(struct wlandevice *wlandev, - hfa384x_InfFrame_t *inf) + struct hfa384x_InfFrame *inf) { hfa384x_t *hw = wlandev->priv; @@ -1468,7 +1468,7 @@ static void prism2sta_inf_linkstatus(struct wlandevice *wlandev, * interrupt */ static void prism2sta_inf_assocstatus(struct wlandevice *wlandev, - hfa384x_InfFrame_t *inf) + struct hfa384x_InfFrame *inf) { hfa384x_t *hw = wlandev->priv; struct hfa384x_AssocStatus rec; @@ -1529,7 +1529,7 @@ static void prism2sta_inf_assocstatus(struct wlandevice *wlandev, * */ static void prism2sta_inf_authreq(struct wlandevice *wlandev, - hfa384x_InfFrame_t *inf) + struct hfa384x_InfFrame *inf) { hfa384x_t *hw = wlandev->priv; struct sk_buff *skb; @@ -1544,7 +1544,7 @@ static void prism2sta_inf_authreq(struct wlandevice *wlandev, } static void prism2sta_inf_authreq_defer(struct wlandevice *wlandev, - hfa384x_InfFrame_t *inf) + struct hfa384x_InfFrame *inf) { hfa384x_t *hw = wlandev->priv; struct hfa384x_authenticateStation_data rec; @@ -1718,7 +1718,7 @@ static void prism2sta_inf_authreq_defer(struct wlandevice *wlandev, * interrupt */ static void prism2sta_inf_psusercnt(struct wlandevice *wlandev, - hfa384x_InfFrame_t *inf) + struct hfa384x_InfFrame *inf) { hfa384x_t *hw = wlandev->priv; @@ -1742,7 +1742,7 @@ static void prism2sta_inf_psusercnt(struct wlandevice *wlandev, * Call context: * interrupt */ -void prism2sta_ev_info(struct wlandevice *wlandev, hfa384x_InfFrame_t *inf) +void prism2sta_ev_info(struct wlandevice *wlandev, struct hfa384x_InfFrame *inf) { inf->infotype = le16_to_cpu(inf->infotype); /* Dispatch */ -- cgit v0.10.2 From 2f1014f7ce7121bb8508a153c47a4a2906d93ac3 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:22 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_usb_txfrm_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_usb_txfrm_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 29d9bc5..2d6f6a9 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -808,10 +808,10 @@ struct hfa384x_InfFrame { /*------------------------------------*/ /* Request (bulk OUT) packet contents */ -typedef struct hfa384x_usb_txfrm { +struct hfa384x_usb_txfrm { struct hfa384x_tx_frame desc; u8 data[WLAN_DATA_MAXLEN]; -} __packed hfa384x_usb_txfrm_t; +} __packed; typedef struct hfa384x_usb_cmdreq { u16 type; @@ -905,7 +905,7 @@ typedef struct hfa384x_usb_error { typedef union hfa384x_usbout { __le16 type; - hfa384x_usb_txfrm_t txfrm; + struct hfa384x_usb_txfrm txfrm; hfa384x_usb_cmdreq_t cmdreq; hfa384x_usb_wridreq_t wridreq; hfa384x_usb_rridreq_t rridreq; @@ -916,7 +916,7 @@ typedef union hfa384x_usbout { typedef union hfa384x_usbin { __le16 type; hfa384x_usb_rxfrm_t rxfrm; - hfa384x_usb_txfrm_t txfrm; + struct hfa384x_usb_txfrm txfrm; hfa384x_usb_infofrm_t infofrm; hfa384x_usb_cmdresp_t cmdresp; hfa384x_usb_wridresp_t wridresp; -- cgit v0.10.2 From a6dcbdfe04c039293970b144c5cb6e7ed4168de5 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:23 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_usb_cmdreq_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_usb_cmdreq_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 2d6f6a9..affdeef 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -813,14 +813,14 @@ struct hfa384x_usb_txfrm { u8 data[WLAN_DATA_MAXLEN]; } __packed; -typedef struct hfa384x_usb_cmdreq { +struct hfa384x_usb_cmdreq { u16 type; u16 cmd; u16 parm0; u16 parm1; u16 parm2; u8 pad[54]; -} __packed hfa384x_usb_cmdreq_t; +} __packed; typedef struct hfa384x_usb_wridreq { u16 type; @@ -906,7 +906,7 @@ typedef struct hfa384x_usb_error { typedef union hfa384x_usbout { __le16 type; struct hfa384x_usb_txfrm txfrm; - hfa384x_usb_cmdreq_t cmdreq; + struct hfa384x_usb_cmdreq cmdreq; hfa384x_usb_wridreq_t wridreq; hfa384x_usb_rridreq_t rridreq; hfa384x_usb_wmemreq_t wmemreq; -- cgit v0.10.2 From 3bc070f6537b35945f9d822a34de42d4146222bc Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:24 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_usb_wridreq_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_usb_wridreq_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index affdeef..e0cfe79 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -822,12 +822,12 @@ struct hfa384x_usb_cmdreq { u8 pad[54]; } __packed; -typedef struct hfa384x_usb_wridreq { +struct hfa384x_usb_wridreq { u16 type; u16 frmlen; u16 rid; u8 data[HFA384x_RIDDATA_MAXLEN]; -} __packed hfa384x_usb_wridreq_t; +} __packed; typedef struct hfa384x_usb_rridreq { u16 type; @@ -907,7 +907,7 @@ typedef union hfa384x_usbout { __le16 type; struct hfa384x_usb_txfrm txfrm; struct hfa384x_usb_cmdreq cmdreq; - hfa384x_usb_wridreq_t wridreq; + struct hfa384x_usb_wridreq wridreq; hfa384x_usb_rridreq_t rridreq; hfa384x_usb_wmemreq_t wmemreq; hfa384x_usb_rmemreq_t rmemreq; -- cgit v0.10.2 From 5b9f240e482ea96ea1ebe3387b6f5678d195d2b1 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:25 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_usb_rridreq_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_usb_rridreq_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index e0cfe79..1300472 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -829,12 +829,12 @@ struct hfa384x_usb_wridreq { u8 data[HFA384x_RIDDATA_MAXLEN]; } __packed; -typedef struct hfa384x_usb_rridreq { +struct hfa384x_usb_rridreq { u16 type; u16 frmlen; u16 rid; u8 pad[58]; -} __packed hfa384x_usb_rridreq_t; +} __packed; typedef struct hfa384x_usb_wmemreq { u16 type; @@ -908,7 +908,7 @@ typedef union hfa384x_usbout { struct hfa384x_usb_txfrm txfrm; struct hfa384x_usb_cmdreq cmdreq; struct hfa384x_usb_wridreq wridreq; - hfa384x_usb_rridreq_t rridreq; + struct hfa384x_usb_rridreq rridreq; hfa384x_usb_wmemreq_t wmemreq; hfa384x_usb_rmemreq_t rmemreq; } __packed hfa384x_usbout_t; -- cgit v0.10.2 From f0e15d40bb1a6963cb05023d8e64e4237a30d89d Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:26 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_usb_wmemreq_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_usb_wmemreq_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 1300472..da73cb1 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -836,13 +836,13 @@ struct hfa384x_usb_rridreq { u8 pad[58]; } __packed; -typedef struct hfa384x_usb_wmemreq { +struct hfa384x_usb_wmemreq { u16 type; u16 frmlen; u16 offset; u16 page; u8 data[HFA384x_USB_RWMEM_MAXLEN]; -} __packed hfa384x_usb_wmemreq_t; +} __packed; typedef struct hfa384x_usb_rmemreq { u16 type; @@ -909,7 +909,7 @@ typedef union hfa384x_usbout { struct hfa384x_usb_cmdreq cmdreq; struct hfa384x_usb_wridreq wridreq; struct hfa384x_usb_rridreq rridreq; - hfa384x_usb_wmemreq_t wmemreq; + struct hfa384x_usb_wmemreq wmemreq; hfa384x_usb_rmemreq_t rmemreq; } __packed hfa384x_usbout_t; -- cgit v0.10.2 From 94ec5464c7285e3bf01097e158ef5a247d3a41a4 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:27 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_usb_rmemreq_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_usb_rmemreq_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index da73cb1..28928c8 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -844,13 +844,13 @@ struct hfa384x_usb_wmemreq { u8 data[HFA384x_USB_RWMEM_MAXLEN]; } __packed; -typedef struct hfa384x_usb_rmemreq { +struct hfa384x_usb_rmemreq { u16 type; u16 frmlen; u16 offset; u16 page; u8 pad[56]; -} __packed hfa384x_usb_rmemreq_t; +} __packed; /*------------------------------------*/ /* Response (bulk IN) packet contents */ @@ -910,7 +910,7 @@ typedef union hfa384x_usbout { struct hfa384x_usb_wridreq wridreq; struct hfa384x_usb_rridreq rridreq; struct hfa384x_usb_wmemreq wmemreq; - hfa384x_usb_rmemreq_t rmemreq; + struct hfa384x_usb_rmemreq rmemreq; } __packed hfa384x_usbout_t; typedef union hfa384x_usbin { -- cgit v0.10.2 From 684b2e087fa6ce45f8cfd6e672cf1ee4f24abffa Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:28 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_usb_rxfrm_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_usb_rxfrm_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 28928c8..b0de7cb 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -855,10 +855,10 @@ struct hfa384x_usb_rmemreq { /*------------------------------------*/ /* Response (bulk IN) packet contents */ -typedef struct hfa384x_usb_rxfrm { +struct hfa384x_usb_rxfrm { struct hfa384x_rx_frame desc; u8 data[WLAN_DATA_MAXLEN]; -} __packed hfa384x_usb_rxfrm_t; +} __packed; typedef struct hfa384x_usb_infofrm { u16 type; @@ -915,7 +915,7 @@ typedef union hfa384x_usbout { typedef union hfa384x_usbin { __le16 type; - hfa384x_usb_rxfrm_t rxfrm; + struct hfa384x_usb_rxfrm rxfrm; struct hfa384x_usb_txfrm txfrm; hfa384x_usb_infofrm_t infofrm; hfa384x_usb_cmdresp_t cmdresp; diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index f1809af..76d1223 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -154,7 +154,7 @@ static void dbprint_urb(struct urb *urb); #endif static void -hfa384x_int_rxmonitor(struct wlandevice *wlandev, hfa384x_usb_rxfrm_t *rxfrm); +hfa384x_int_rxmonitor(struct wlandevice *wlandev, struct hfa384x_usb_rxfrm *rxfrm); static void hfa384x_usb_defer(struct work_struct *data); @@ -3417,7 +3417,7 @@ static void hfa384x_usbin_rx(struct wlandevice *wlandev, struct sk_buff *skb) * interrupt ----------------------------------------------------------------*/ static void hfa384x_int_rxmonitor(struct wlandevice *wlandev, - hfa384x_usb_rxfrm_t *rxfrm) + struct hfa384x_usb_rxfrm *rxfrm) { struct hfa384x_rx_frame *rxdesc = &(rxfrm->desc); unsigned int hdrlen = 0; -- cgit v0.10.2 From e20a7ca18cdccd339e96453522e64b670e9818f8 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:29 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_usb_infofrm_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_usb_infofrm_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index b0de7cb..1113676 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -860,10 +860,10 @@ struct hfa384x_usb_rxfrm { u8 data[WLAN_DATA_MAXLEN]; } __packed; -typedef struct hfa384x_usb_infofrm { +struct hfa384x_usb_infofrm { u16 type; struct hfa384x_InfFrame info; -} __packed hfa384x_usb_infofrm_t; +} __packed; typedef struct hfa384x_usb_statusresp { u16 type; @@ -917,7 +917,7 @@ typedef union hfa384x_usbin { __le16 type; struct hfa384x_usb_rxfrm rxfrm; struct hfa384x_usb_txfrm txfrm; - hfa384x_usb_infofrm_t infofrm; + struct hfa384x_usb_infofrm infofrm; hfa384x_usb_cmdresp_t cmdresp; hfa384x_usb_wridresp_t wridresp; hfa384x_usb_rridresp_t rridresp; -- cgit v0.10.2 From 385a79df4b8863ba0e30ec364656a4bc7ceceb0d Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:30 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_usb_cmdresp_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_usb_cmdresp_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 1113676..24e8ac4 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -865,15 +865,15 @@ struct hfa384x_usb_infofrm { struct hfa384x_InfFrame info; } __packed; -typedef struct hfa384x_usb_statusresp { +struct hfa384x_usb_statusresp { u16 type; u16 status; u16 resp0; u16 resp1; u16 resp2; -} __packed hfa384x_usb_cmdresp_t; +} __packed; -typedef hfa384x_usb_cmdresp_t hfa384x_usb_wridresp_t; +typedef struct hfa384x_usb_statusresp hfa384x_usb_wridresp_t; typedef struct hfa384x_usb_rridresp { u16 type; @@ -882,7 +882,7 @@ typedef struct hfa384x_usb_rridresp { u8 data[HFA384x_RIDDATA_MAXLEN]; } __packed hfa384x_usb_rridresp_t; -typedef hfa384x_usb_cmdresp_t hfa384x_usb_wmemresp_t; +typedef struct hfa384x_usb_statusresp hfa384x_usb_wmemresp_t; typedef struct hfa384x_usb_rmemresp { u16 type; @@ -918,7 +918,7 @@ typedef union hfa384x_usbin { struct hfa384x_usb_rxfrm rxfrm; struct hfa384x_usb_txfrm txfrm; struct hfa384x_usb_infofrm infofrm; - hfa384x_usb_cmdresp_t cmdresp; + struct hfa384x_usb_statusresp cmdresp; hfa384x_usb_wridresp_t wridresp; hfa384x_usb_rridresp_t rridresp; hfa384x_usb_wmemresp_t wmemresp; diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 76d1223..7d09f25 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -212,7 +212,7 @@ unlocked_usbctlx_cancel_async(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx); static void hfa384x_cb_status(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx); static int -usbctlx_get_status(const hfa384x_usb_cmdresp_t *cmdresp, +usbctlx_get_status(const struct hfa384x_usb_statusresp *cmdresp, hfa384x_cmdresult_t *result); static void @@ -621,7 +621,7 @@ static hfa384x_usbctlx_t *usbctlx_alloc(void) } static int -usbctlx_get_status(const hfa384x_usb_cmdresp_t *cmdresp, +usbctlx_get_status(const struct hfa384x_usb_statusresp *cmdresp, hfa384x_cmdresult_t *result) { result->status = le16_to_cpu(cmdresp->status); @@ -652,7 +652,7 @@ usbctlx_get_rridresult(const hfa384x_usb_rridresp_t *rridresp, struct usbctlx_cmd_completor { struct usbctlx_completor head; - const hfa384x_usb_cmdresp_t *cmdresp; + const struct hfa384x_usb_statusresp *cmdresp; hfa384x_cmdresult_t *result; }; @@ -667,7 +667,7 @@ static inline int usbctlx_cmd_completor_fn(struct usbctlx_completor *head) static inline struct usbctlx_completor *init_cmd_completor( struct usbctlx_cmd_completor *completor, - const hfa384x_usb_cmdresp_t + const struct hfa384x_usb_statusresp *cmdresp, hfa384x_cmdresult_t *result) { -- cgit v0.10.2 From 2c8079dedc1cefc7098f5071f7e4b96a2bddac80 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:31 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_usb_wridresp_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_usb_wridresp_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 24e8ac4..18588d6 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -873,8 +873,6 @@ struct hfa384x_usb_statusresp { u16 resp2; } __packed; -typedef struct hfa384x_usb_statusresp hfa384x_usb_wridresp_t; - typedef struct hfa384x_usb_rridresp { u16 type; u16 frmlen; @@ -919,7 +917,7 @@ typedef union hfa384x_usbin { struct hfa384x_usb_txfrm txfrm; struct hfa384x_usb_infofrm infofrm; struct hfa384x_usb_statusresp cmdresp; - hfa384x_usb_wridresp_t wridresp; + struct hfa384x_usb_statusresp wridresp; hfa384x_usb_rridresp_t rridresp; hfa384x_usb_wmemresp_t wmemresp; hfa384x_usb_rmemresp_t rmemresp; -- cgit v0.10.2 From a988c9f3ea35e3a6b532ebe30d2724c55b427c9d Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:32 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_usb_rridresp_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_usb_rridresp_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 18588d6..0ba5517 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -873,12 +873,12 @@ struct hfa384x_usb_statusresp { u16 resp2; } __packed; -typedef struct hfa384x_usb_rridresp { +struct hfa384x_usb_rridresp { u16 type; u16 frmlen; u16 rid; u8 data[HFA384x_RIDDATA_MAXLEN]; -} __packed hfa384x_usb_rridresp_t; +} __packed; typedef struct hfa384x_usb_statusresp hfa384x_usb_wmemresp_t; @@ -918,7 +918,7 @@ typedef union hfa384x_usbin { struct hfa384x_usb_infofrm infofrm; struct hfa384x_usb_statusresp cmdresp; struct hfa384x_usb_statusresp wridresp; - hfa384x_usb_rridresp_t rridresp; + struct hfa384x_usb_rridresp rridresp; hfa384x_usb_wmemresp_t wmemresp; hfa384x_usb_rmemresp_t rmemresp; hfa384x_usb_bufavail_t bufavail; diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 7d09f25..c21c591 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -216,7 +216,7 @@ usbctlx_get_status(const struct hfa384x_usb_statusresp *cmdresp, hfa384x_cmdresult_t *result); static void -usbctlx_get_rridresult(const hfa384x_usb_rridresp_t *rridresp, +usbctlx_get_rridresult(const struct hfa384x_usb_rridresp *rridresp, hfa384x_rridresult_t *result); /*---------------------------------------------------*/ @@ -636,7 +636,7 @@ usbctlx_get_status(const struct hfa384x_usb_statusresp *cmdresp, } static void -usbctlx_get_rridresult(const hfa384x_usb_rridresp_t *rridresp, +usbctlx_get_rridresult(const struct hfa384x_usb_rridresp *rridresp, hfa384x_rridresult_t *result) { result->rid = le16_to_cpu(rridresp->rid); @@ -685,7 +685,7 @@ static inline struct usbctlx_completor *init_cmd_completor( struct usbctlx_rrid_completor { struct usbctlx_completor head; - const hfa384x_usb_rridresp_t *rridresp; + const struct hfa384x_usb_rridresp *rridresp; void *riddata; unsigned int riddatalen; }; @@ -713,7 +713,7 @@ static int usbctlx_rrid_completor_fn(struct usbctlx_completor *head) static inline struct usbctlx_completor *init_rrid_completor( struct usbctlx_rrid_completor *completor, - const hfa384x_usb_rridresp_t + const struct hfa384x_usb_rridresp *rridresp, void *riddata, unsigned int riddatalen) -- cgit v0.10.2 From 499c1cc937bf8203914025db71c72e1117943d21 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:33 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_usb_wmemresp_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_usb_wmemresp_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 0ba5517..28c008c 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -880,8 +880,6 @@ struct hfa384x_usb_rridresp { u8 data[HFA384x_RIDDATA_MAXLEN]; } __packed; -typedef struct hfa384x_usb_statusresp hfa384x_usb_wmemresp_t; - typedef struct hfa384x_usb_rmemresp { u16 type; u16 frmlen; @@ -919,7 +917,7 @@ typedef union hfa384x_usbin { struct hfa384x_usb_statusresp cmdresp; struct hfa384x_usb_statusresp wridresp; struct hfa384x_usb_rridresp rridresp; - hfa384x_usb_wmemresp_t wmemresp; + struct hfa384x_usb_statusresp wmemresp; hfa384x_usb_rmemresp_t rmemresp; hfa384x_usb_bufavail_t bufavail; hfa384x_usb_error_t usberror; -- cgit v0.10.2 From 1ed548063b66242f655c8fb759f3dc32dd511e5e Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:34 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_usb_rmemresp_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_usb_rmemresp_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 28c008c..955f22d 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -880,11 +880,11 @@ struct hfa384x_usb_rridresp { u8 data[HFA384x_RIDDATA_MAXLEN]; } __packed; -typedef struct hfa384x_usb_rmemresp { +struct hfa384x_usb_rmemresp { u16 type; u16 frmlen; u8 data[HFA384x_USB_RWMEM_MAXLEN]; -} __packed hfa384x_usb_rmemresp_t; +} __packed; typedef struct hfa384x_usb_bufavail { u16 type; @@ -918,7 +918,7 @@ typedef union hfa384x_usbin { struct hfa384x_usb_statusresp wridresp; struct hfa384x_usb_rridresp rridresp; struct hfa384x_usb_statusresp wmemresp; - hfa384x_usb_rmemresp_t rmemresp; + struct hfa384x_usb_rmemresp rmemresp; hfa384x_usb_bufavail_t bufavail; hfa384x_usb_error_t usberror; u8 boguspad[3000]; diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index c21c591..d76ec2a 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -744,7 +744,7 @@ static inline struct usbctlx_completor *init_rrid_completor( struct usbctlx_rmem_completor { struct usbctlx_completor head; - const hfa384x_usb_rmemresp_t *rmemresp; + const struct hfa384x_usb_rmemresp *rmemresp; void *data; unsigned int len; }; @@ -762,7 +762,7 @@ static int usbctlx_rmem_completor_fn(struct usbctlx_completor *head) static inline struct usbctlx_completor *init_rmem_completor( struct usbctlx_rmem_completor *completor, - hfa384x_usb_rmemresp_t + struct hfa384x_usb_rmemresp *rmemresp, void *data, unsigned int len) -- cgit v0.10.2 From c4d8a0a85d89ecda970bd8949544a2f911700b60 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:35 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_usb_bufavail_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_usb_bufavail_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 955f22d..09f7ce5 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -886,10 +886,10 @@ struct hfa384x_usb_rmemresp { u8 data[HFA384x_USB_RWMEM_MAXLEN]; } __packed; -typedef struct hfa384x_usb_bufavail { +struct hfa384x_usb_bufavail { u16 type; u16 frmlen; -} __packed hfa384x_usb_bufavail_t; +} __packed; typedef struct hfa384x_usb_error { u16 type; @@ -919,7 +919,7 @@ typedef union hfa384x_usbin { struct hfa384x_usb_rridresp rridresp; struct hfa384x_usb_statusresp wmemresp; struct hfa384x_usb_rmemresp rmemresp; - hfa384x_usb_bufavail_t bufavail; + struct hfa384x_usb_bufavail bufavail; hfa384x_usb_error_t usberror; u8 boguspad[3000]; } __packed hfa384x_usbin_t; -- cgit v0.10.2 From d4734c301c165c03ff7fb04483b456f51a405c0c Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:36 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_usb_error_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_usb_error_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 09f7ce5..58b1ac5 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -891,10 +891,10 @@ struct hfa384x_usb_bufavail { u16 frmlen; } __packed; -typedef struct hfa384x_usb_error { +struct hfa384x_usb_error { u16 type; u16 errortype; -} __packed hfa384x_usb_error_t; +} __packed; /*----------------------------------------------------------*/ /* Unions for packaging all the known packet types together */ @@ -920,7 +920,7 @@ typedef union hfa384x_usbin { struct hfa384x_usb_statusresp wmemresp; struct hfa384x_usb_rmemresp rmemresp; struct hfa384x_usb_bufavail bufavail; - hfa384x_usb_error_t usberror; + struct hfa384x_usb_error usberror; u8 boguspad[3000]; } __packed hfa384x_usbin_t; -- cgit v0.10.2 From 4012684a5129f750b38726370a855a4a794cc88d Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:37 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_usbout_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_usbout_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 58b1ac5..2365edc 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -899,7 +899,7 @@ struct hfa384x_usb_error { /*----------------------------------------------------------*/ /* Unions for packaging all the known packet types together */ -typedef union hfa384x_usbout { +union hfa384x_usbout { __le16 type; struct hfa384x_usb_txfrm txfrm; struct hfa384x_usb_cmdreq cmdreq; @@ -907,7 +907,7 @@ typedef union hfa384x_usbout { struct hfa384x_usb_rridreq rridreq; struct hfa384x_usb_wmemreq wmemreq; struct hfa384x_usb_rmemreq rmemreq; -} __packed hfa384x_usbout_t; +} __packed; typedef union hfa384x_usbin { __le16 type; @@ -1183,7 +1183,7 @@ typedef struct hfa384x_usbctlx { struct list_head list; size_t outbufsize; - hfa384x_usbout_t outbuf; /* pkt buf for OUT */ + union hfa384x_usbout outbuf; /* pkt buf for OUT */ hfa384x_usbin_t inbuf; /* pkt buf for IN(a copy) */ CTLX_STATE state; /* Tracks running state */ @@ -1248,7 +1248,7 @@ typedef struct hfa384x { struct sk_buff *rx_urb_skb; struct urb tx_urb; struct urb ctlx_urb; - hfa384x_usbout_t txbuff; + union hfa384x_usbout txbuff; hfa384x_usbctlxq_t ctlxq; struct timer_list reqtimer; struct timer_list resptimer; -- cgit v0.10.2 From 3e4180c3e8fe17518ce1a3b7ecd49b318217541f Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:38 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_usbin_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_usbin_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 2365edc..f715f5f 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -909,7 +909,7 @@ union hfa384x_usbout { struct hfa384x_usb_rmemreq rmemreq; } __packed; -typedef union hfa384x_usbin { +union hfa384x_usbin { __le16 type; struct hfa384x_usb_rxfrm rxfrm; struct hfa384x_usb_txfrm txfrm; @@ -922,7 +922,7 @@ typedef union hfa384x_usbin { struct hfa384x_usb_bufavail bufavail; struct hfa384x_usb_error usberror; u8 boguspad[3000]; -} __packed hfa384x_usbin_t; +} __packed; /*-------------------------------------------------------------------- * PD record structures. @@ -1184,7 +1184,7 @@ typedef struct hfa384x_usbctlx { size_t outbufsize; union hfa384x_usbout outbuf; /* pkt buf for OUT */ - hfa384x_usbin_t inbuf; /* pkt buf for IN(a copy) */ + union hfa384x_usbin inbuf; /* pkt buf for IN(a copy) */ CTLX_STATE state; /* Tracks running state */ diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index d76ec2a..9203880 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -169,13 +169,13 @@ static void hfa384x_ctlxout_callback(struct urb *urb); static void hfa384x_usbin_callback(struct urb *urb); static void -hfa384x_usbin_txcompl(struct wlandevice *wlandev, hfa384x_usbin_t *usbin); +hfa384x_usbin_txcompl(struct wlandevice *wlandev, union hfa384x_usbin *usbin); static void hfa384x_usbin_rx(struct wlandevice *wlandev, struct sk_buff *skb); -static void hfa384x_usbin_info(struct wlandevice *wlandev, hfa384x_usbin_t *usbin); +static void hfa384x_usbin_info(struct wlandevice *wlandev, union hfa384x_usbin *usbin); -static void hfa384x_usbin_ctlx(hfa384x_t *hw, hfa384x_usbin_t *usbin, +static void hfa384x_usbin_ctlx(hfa384x_t *hw, union hfa384x_usbin *usbin, int urb_status); /*---------------------------------------------------*/ @@ -327,7 +327,7 @@ static int submit_rx_urb(hfa384x_t *hw, gfp_t memflags) struct sk_buff *skb; int result; - skb = dev_alloc_skb(sizeof(hfa384x_usbin_t)); + skb = dev_alloc_skb(sizeof(union hfa384x_usbin)); if (!skb) { result = -ENOMEM; goto done; @@ -336,7 +336,7 @@ static int submit_rx_urb(hfa384x_t *hw, gfp_t memflags) /* Post the IN urb */ usb_fill_bulk_urb(&hw->rx_urb, hw->usb, hw->endp_in, - skb->data, sizeof(hfa384x_usbin_t), + skb->data, sizeof(union hfa384x_usbin), hfa384x_usbin_callback, hw->wlandev); hw->rx_urb_skb = skb; @@ -2990,7 +2990,7 @@ static void hfa384x_usbin_callback(struct urb *urb) { struct wlandevice *wlandev = urb->context; hfa384x_t *hw; - hfa384x_usbin_t *usbin = (hfa384x_usbin_t *)urb->transfer_buffer; + union hfa384x_usbin *usbin = (union hfa384x_usbin *)urb->transfer_buffer; struct sk_buff *skb = NULL; int result; int urb_status; @@ -3166,7 +3166,7 @@ exit: * Call context: * interrupt ----------------------------------------------------------------*/ -static void hfa384x_usbin_ctlx(hfa384x_t *hw, hfa384x_usbin_t *usbin, +static void hfa384x_usbin_ctlx(hfa384x_t *hw, union hfa384x_usbin *usbin, int urb_status) { hfa384x_usbctlx_t *ctlx; @@ -3286,7 +3286,7 @@ unlock: * interrupt ----------------------------------------------------------------*/ static void hfa384x_usbin_txcompl(struct wlandevice *wlandev, - hfa384x_usbin_t *usbin) + union hfa384x_usbin *usbin) { u16 status; @@ -3318,7 +3318,7 @@ static void hfa384x_usbin_txcompl(struct wlandevice *wlandev, ----------------------------------------------------------------*/ static void hfa384x_usbin_rx(struct wlandevice *wlandev, struct sk_buff *skb) { - hfa384x_usbin_t *usbin = (hfa384x_usbin_t *)skb->data; + union hfa384x_usbin *usbin = (union hfa384x_usbin *)skb->data; hfa384x_t *hw = wlandev->priv; int hdrlen; struct p80211_rxmeta *rxmeta; @@ -3517,7 +3517,8 @@ static void hfa384x_int_rxmonitor(struct wlandevice *wlandev, * Call context: * interrupt ----------------------------------------------------------------*/ -static void hfa384x_usbin_info(struct wlandevice *wlandev, hfa384x_usbin_t *usbin) +static void hfa384x_usbin_info(struct wlandevice *wlandev, + union hfa384x_usbin *usbin) { usbin->infofrm.info.framelen = le16_to_cpu(usbin->infofrm.info.framelen); -- cgit v0.10.2 From e0696aa81b47f094ba33809b63f36432cc6acf70 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:39 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_pcb_partnum_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_pcb_partnum_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index f715f5f..7ecbf2f 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -929,9 +929,9 @@ union hfa384x_usbin { *-------------------------------------------------------------------- */ -typedef struct hfa384x_pdr_pcb_partnum { +struct hfa384x_pdr_pcb_partnum { u8 num[8]; -} __packed hfa384x_pdr_pcb_partnum_t; +} __packed; typedef struct hfa384x_pdr_pcb_tracenum { u8 num[8]; @@ -1094,7 +1094,7 @@ typedef struct hfa384x_pdrec { u16 len; /* in words */ u16 code; union pdr { - hfa384x_pdr_pcb_partnum_t pcb_partnum; + struct hfa384x_pdr_pcb_partnum pcb_partnum; hfa384x_pdr_pcb_tracenum_t pcb_tracenum; hfa384x_pdr_nic_serial_t nic_serial; hfa384x_pdr_mkk_measurements_t mkk_measurements; -- cgit v0.10.2 From caeabb804a2c716e1596b55810c6489514de2124 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:40 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_pcb_tracenum_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_pcb_tracenum_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 7ecbf2f..a989198 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -933,9 +933,9 @@ struct hfa384x_pdr_pcb_partnum { u8 num[8]; } __packed; -typedef struct hfa384x_pdr_pcb_tracenum { +struct hfa384x_pdr_pcb_tracenum { u8 num[8]; -} __packed hfa384x_pdr_pcb_tracenum_t; +} __packed; typedef struct hfa384x_pdr_nic_serial { u8 num[12]; @@ -1095,7 +1095,7 @@ typedef struct hfa384x_pdrec { u16 code; union pdr { struct hfa384x_pdr_pcb_partnum pcb_partnum; - hfa384x_pdr_pcb_tracenum_t pcb_tracenum; + struct hfa384x_pdr_pcb_tracenum pcb_tracenum; hfa384x_pdr_nic_serial_t nic_serial; hfa384x_pdr_mkk_measurements_t mkk_measurements; hfa384x_pdr_nic_ramsize_t nic_ramsize; -- cgit v0.10.2 From 66e7bdb61233be2b0c7f1b27b4678777ddc90edf Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:41 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_nic_serial_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_nic_serial_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index a989198..dcb181e 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -937,9 +937,9 @@ struct hfa384x_pdr_pcb_tracenum { u8 num[8]; } __packed; -typedef struct hfa384x_pdr_nic_serial { +struct hfa384x_pdr_nic_serial { u8 num[12]; -} __packed hfa384x_pdr_nic_serial_t; +} __packed; typedef struct hfa384x_pdr_mkk_measurements { double carrier_freq; @@ -1096,7 +1096,7 @@ typedef struct hfa384x_pdrec { union pdr { struct hfa384x_pdr_pcb_partnum pcb_partnum; struct hfa384x_pdr_pcb_tracenum pcb_tracenum; - hfa384x_pdr_nic_serial_t nic_serial; + struct hfa384x_pdr_nic_serial nic_serial; hfa384x_pdr_mkk_measurements_t mkk_measurements; hfa384x_pdr_nic_ramsize_t nic_ramsize; hfa384x_pdr_mfisuprange_t mfisuprange; -- cgit v0.10.2 From ee9f7626e024007f6bf7e40ee50012d5b7e52685 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:42 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_mkk_measurements_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_mkk_measurements_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index dcb181e..79f3761 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -941,7 +941,7 @@ struct hfa384x_pdr_nic_serial { u8 num[12]; } __packed; -typedef struct hfa384x_pdr_mkk_measurements { +struct hfa384x_pdr_mkk_measurements { double carrier_freq; double occupied_band; double power_density; @@ -957,7 +957,7 @@ typedef struct hfa384x_pdr_mkk_measurements { double rx_spur_f2; double rx_spur_l1; double rx_spur_l2; -} __packed hfa384x_pdr_mkk_measurements_t; +} __packed; typedef struct hfa384x_pdr_nic_ramsize { u8 size[12]; /* units of KB */ @@ -1097,7 +1097,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_pcb_partnum pcb_partnum; struct hfa384x_pdr_pcb_tracenum pcb_tracenum; struct hfa384x_pdr_nic_serial nic_serial; - hfa384x_pdr_mkk_measurements_t mkk_measurements; + struct hfa384x_pdr_mkk_measurements mkk_measurements; hfa384x_pdr_nic_ramsize_t nic_ramsize; hfa384x_pdr_mfisuprange_t mfisuprange; hfa384x_pdr_cfisuprange_t cfisuprange; -- cgit v0.10.2 From 02eebae415bc3dc3e469de0c7f2b45f1d42cc0a4 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:43 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_nic_ramsize_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_nic_ramsize_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 79f3761..2986d17 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -959,9 +959,9 @@ struct hfa384x_pdr_mkk_measurements { double rx_spur_l2; } __packed; -typedef struct hfa384x_pdr_nic_ramsize { +struct hfa384x_pdr_nic_ramsize { u8 size[12]; /* units of KB */ -} __packed hfa384x_pdr_nic_ramsize_t; +} __packed; typedef struct hfa384x_pdr_mfisuprange { u16 id; @@ -1098,7 +1098,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_pcb_tracenum pcb_tracenum; struct hfa384x_pdr_nic_serial nic_serial; struct hfa384x_pdr_mkk_measurements mkk_measurements; - hfa384x_pdr_nic_ramsize_t nic_ramsize; + struct hfa384x_pdr_nic_ramsize nic_ramsize; hfa384x_pdr_mfisuprange_t mfisuprange; hfa384x_pdr_cfisuprange_t cfisuprange; hfa384x_pdr_nicid_t nicid; -- cgit v0.10.2 From 9127692f0e56fafed906be3b6ab5f2360439ecc4 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:44 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_mfisuprange_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_mfisuprange_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 2986d17..d558a1f 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -963,12 +963,12 @@ struct hfa384x_pdr_nic_ramsize { u8 size[12]; /* units of KB */ } __packed; -typedef struct hfa384x_pdr_mfisuprange { +struct hfa384x_pdr_mfisuprange { u16 id; u16 variant; u16 bottom; u16 top; -} __packed hfa384x_pdr_mfisuprange_t; +} __packed; typedef struct hfa384x_pdr_cfisuprange { u16 id; @@ -1099,7 +1099,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_nic_serial nic_serial; struct hfa384x_pdr_mkk_measurements mkk_measurements; struct hfa384x_pdr_nic_ramsize nic_ramsize; - hfa384x_pdr_mfisuprange_t mfisuprange; + struct hfa384x_pdr_mfisuprange mfisuprange; hfa384x_pdr_cfisuprange_t cfisuprange; hfa384x_pdr_nicid_t nicid; hfa384x_pdr_refdac_measurements_t refdac_measurements; -- cgit v0.10.2 From 4ae2996f497966831491c131a8c07c5f9a258d67 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:45 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_cfisuprange_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_cfisuprange_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index d558a1f..26d72a3 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -970,12 +970,12 @@ struct hfa384x_pdr_mfisuprange { u16 top; } __packed; -typedef struct hfa384x_pdr_cfisuprange { +struct hfa384x_pdr_cfisuprange { u16 id; u16 variant; u16 bottom; u16 top; -} __packed hfa384x_pdr_cfisuprange_t; +} __packed; typedef struct hfa384x_pdr_nicid { u16 id; @@ -1100,7 +1100,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_mkk_measurements mkk_measurements; struct hfa384x_pdr_nic_ramsize nic_ramsize; struct hfa384x_pdr_mfisuprange mfisuprange; - hfa384x_pdr_cfisuprange_t cfisuprange; + struct hfa384x_pdr_cfisuprange cfisuprange; hfa384x_pdr_nicid_t nicid; hfa384x_pdr_refdac_measurements_t refdac_measurements; hfa384x_pdr_vgdac_measurements_t vgdac_measurements; -- cgit v0.10.2 From e9ee92c79997ae51fd76048346bc02cea966c45e Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:46 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_nicid_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_nicid_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 26d72a3..68267b5 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -977,12 +977,12 @@ struct hfa384x_pdr_cfisuprange { u16 top; } __packed; -typedef struct hfa384x_pdr_nicid { +struct hfa384x_pdr_nicid { u16 id; u16 variant; u16 major; u16 minor; -} __packed hfa384x_pdr_nicid_t; +} __packed; typedef struct hfa384x_pdr_refdac_measurements { u16 value[0]; @@ -1101,7 +1101,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_nic_ramsize nic_ramsize; struct hfa384x_pdr_mfisuprange mfisuprange; struct hfa384x_pdr_cfisuprange cfisuprange; - hfa384x_pdr_nicid_t nicid; + struct hfa384x_pdr_nicid nicid; hfa384x_pdr_refdac_measurements_t refdac_measurements; hfa384x_pdr_vgdac_measurements_t vgdac_measurements; hfa384x_pdr_level_compc_measurements_t level_compc_measurements; -- cgit v0.10.2 From 1c0c8ebae1627d8c7cbbc41e6a850b5310ce0363 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:47 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_refdac_measurements_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_refdac_measurements_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 68267b5..47aa64a 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -984,9 +984,9 @@ struct hfa384x_pdr_nicid { u16 minor; } __packed; -typedef struct hfa384x_pdr_refdac_measurements { +struct hfa384x_pdr_refdac_measurements { u16 value[0]; -} __packed hfa384x_pdr_refdac_measurements_t; +} __packed; typedef struct hfa384x_pdr_vgdac_measurements { u16 value[0]; @@ -1102,7 +1102,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_mfisuprange mfisuprange; struct hfa384x_pdr_cfisuprange cfisuprange; struct hfa384x_pdr_nicid nicid; - hfa384x_pdr_refdac_measurements_t refdac_measurements; + struct hfa384x_pdr_refdac_measurements refdac_measurements; hfa384x_pdr_vgdac_measurements_t vgdac_measurements; hfa384x_pdr_level_compc_measurements_t level_compc_measurements; hfa384x_pdr_mac_address_t mac_address; -- cgit v0.10.2 From de95929c550ba936220048e9935e028f6e035a0d Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:48 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_vgdac_measurements_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_vgdac_measurements_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 47aa64a..b0a4b24 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -988,9 +988,9 @@ struct hfa384x_pdr_refdac_measurements { u16 value[0]; } __packed; -typedef struct hfa384x_pdr_vgdac_measurements { +struct hfa384x_pdr_vgdac_measurements { u16 value[0]; -} __packed hfa384x_pdr_vgdac_measurements_t; +} __packed; typedef struct hfa384x_pdr_level_comp_measurements { u16 value[0]; @@ -1103,7 +1103,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_cfisuprange cfisuprange; struct hfa384x_pdr_nicid nicid; struct hfa384x_pdr_refdac_measurements refdac_measurements; - hfa384x_pdr_vgdac_measurements_t vgdac_measurements; + struct hfa384x_pdr_vgdac_measurements vgdac_measurements; hfa384x_pdr_level_compc_measurements_t level_compc_measurements; hfa384x_pdr_mac_address_t mac_address; hfa384x_pdr_mkk_callname_t mkk_callname; -- cgit v0.10.2 From dac1445de191d60f7cdc35e38a134c2674a62ad4 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:49 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_level_compc_measurements_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_level_compc_measurements_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index b0a4b24..4fa91f0 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -992,9 +992,9 @@ struct hfa384x_pdr_vgdac_measurements { u16 value[0]; } __packed; -typedef struct hfa384x_pdr_level_comp_measurements { +struct hfa384x_pdr_level_comp_measurements { u16 value[0]; -} __packed hfa384x_pdr_level_compc_measurements_t; +} __packed; typedef struct hfa384x_pdr_mac_address { u8 addr[6]; @@ -1104,7 +1104,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_nicid nicid; struct hfa384x_pdr_refdac_measurements refdac_measurements; struct hfa384x_pdr_vgdac_measurements vgdac_measurements; - hfa384x_pdr_level_compc_measurements_t level_compc_measurements; + struct hfa384x_pdr_level_comp_measurements level_compc_measurements; hfa384x_pdr_mac_address_t mac_address; hfa384x_pdr_mkk_callname_t mkk_callname; hfa384x_pdr_regdomain_t regdomain; -- cgit v0.10.2 From 29f1e44ed1edc7047ec1f9740b3d39f4ed8b3421 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:50 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_mac_address_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_mac_address_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 4fa91f0..644f097 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -996,9 +996,9 @@ struct hfa384x_pdr_level_comp_measurements { u16 value[0]; } __packed; -typedef struct hfa384x_pdr_mac_address { +struct hfa384x_pdr_mac_address { u8 addr[6]; -} __packed hfa384x_pdr_mac_address_t; +} __packed; typedef struct hfa384x_pdr_mkk_callname { u8 callname[8]; @@ -1105,7 +1105,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_refdac_measurements refdac_measurements; struct hfa384x_pdr_vgdac_measurements vgdac_measurements; struct hfa384x_pdr_level_comp_measurements level_compc_measurements; - hfa384x_pdr_mac_address_t mac_address; + struct hfa384x_pdr_mac_address mac_address; hfa384x_pdr_mkk_callname_t mkk_callname; hfa384x_pdr_regdomain_t regdomain; hfa384x_pdr_allowed_channel_t allowed_channel; -- cgit v0.10.2 From f969955355d32ac3f359bd64ede0164569f3e514 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:51 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_mkk_callname_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_mkk_callname_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 644f097..da7937d 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1000,9 +1000,9 @@ struct hfa384x_pdr_mac_address { u8 addr[6]; } __packed; -typedef struct hfa384x_pdr_mkk_callname { +struct hfa384x_pdr_mkk_callname { u8 callname[8]; -} __packed hfa384x_pdr_mkk_callname_t; +} __packed; typedef struct hfa384x_pdr_regdomain { u16 numdomains; @@ -1106,7 +1106,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_vgdac_measurements vgdac_measurements; struct hfa384x_pdr_level_comp_measurements level_compc_measurements; struct hfa384x_pdr_mac_address mac_address; - hfa384x_pdr_mkk_callname_t mkk_callname; + struct hfa384x_pdr_mkk_callname mkk_callname; hfa384x_pdr_regdomain_t regdomain; hfa384x_pdr_allowed_channel_t allowed_channel; hfa384x_pdr_default_channel_t default_channel; -- cgit v0.10.2 From 0970a33d516628c238507173558e8cfd5d44a1b8 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:52 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_regdomain_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_regdomain_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index da7937d..acd7e1d 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1004,10 +1004,10 @@ struct hfa384x_pdr_mkk_callname { u8 callname[8]; } __packed; -typedef struct hfa384x_pdr_regdomain { +struct hfa384x_pdr_regdomain { u16 numdomains; u16 domain[5]; -} __packed hfa384x_pdr_regdomain_t; +} __packed; typedef struct hfa384x_pdr_allowed_channel { u16 ch_bitmap; @@ -1107,7 +1107,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_level_comp_measurements level_compc_measurements; struct hfa384x_pdr_mac_address mac_address; struct hfa384x_pdr_mkk_callname mkk_callname; - hfa384x_pdr_regdomain_t regdomain; + struct hfa384x_pdr_regdomain regdomain; hfa384x_pdr_allowed_channel_t allowed_channel; hfa384x_pdr_default_channel_t default_channel; hfa384x_pdr_privacy_option_t privacy_option; -- cgit v0.10.2 From e0322d1bb04b5602471a359955fb51bdddbd89af Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:53 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_allowed_channel_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_allowed_channel_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index acd7e1d..00dbe8a 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1009,9 +1009,9 @@ struct hfa384x_pdr_regdomain { u16 domain[5]; } __packed; -typedef struct hfa384x_pdr_allowed_channel { +struct hfa384x_pdr_allowed_channel { u16 ch_bitmap; -} __packed hfa384x_pdr_allowed_channel_t; +} __packed; typedef struct hfa384x_pdr_default_channel { u16 channel; @@ -1108,7 +1108,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_mac_address mac_address; struct hfa384x_pdr_mkk_callname mkk_callname; struct hfa384x_pdr_regdomain regdomain; - hfa384x_pdr_allowed_channel_t allowed_channel; + struct hfa384x_pdr_allowed_channel allowed_channel; hfa384x_pdr_default_channel_t default_channel; hfa384x_pdr_privacy_option_t privacy_option; hfa384x_pdr_temptype_t temptype; -- cgit v0.10.2 From 892b51ec854a91bc4635ecfc97210eafbcb49179 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:54 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_default_channel_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_default_channel_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 00dbe8a..a0ab29d 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1013,9 +1013,9 @@ struct hfa384x_pdr_allowed_channel { u16 ch_bitmap; } __packed; -typedef struct hfa384x_pdr_default_channel { +struct hfa384x_pdr_default_channel { u16 channel; -} __packed hfa384x_pdr_default_channel_t; +} __packed; typedef struct hfa384x_pdr_privacy_option { u16 available; @@ -1109,7 +1109,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_mkk_callname mkk_callname; struct hfa384x_pdr_regdomain regdomain; struct hfa384x_pdr_allowed_channel allowed_channel; - hfa384x_pdr_default_channel_t default_channel; + struct hfa384x_pdr_default_channel default_channel; hfa384x_pdr_privacy_option_t privacy_option; hfa384x_pdr_temptype_t temptype; hfa384x_pdr_refdac_setup_t refdac_setup; -- cgit v0.10.2 From 2c1759be42e5e2072a17a0e72b62f425288a2bab Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:55 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_privacy_option_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_privacy_option_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index a0ab29d..d84a25e 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1017,9 +1017,9 @@ struct hfa384x_pdr_default_channel { u16 channel; } __packed; -typedef struct hfa384x_pdr_privacy_option { +struct hfa384x_pdr_privacy_option { u16 available; -} __packed hfa384x_pdr_privacy_option_t; +} __packed; typedef struct hfa384x_pdr_temptype { u16 type; @@ -1110,7 +1110,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_regdomain regdomain; struct hfa384x_pdr_allowed_channel allowed_channel; struct hfa384x_pdr_default_channel default_channel; - hfa384x_pdr_privacy_option_t privacy_option; + struct hfa384x_pdr_privacy_option privacy_option; hfa384x_pdr_temptype_t temptype; hfa384x_pdr_refdac_setup_t refdac_setup; hfa384x_pdr_vgdac_setup_t vgdac_setup; -- cgit v0.10.2 From 0c350461e2aecd806479cf2517b0494ead0ef72f Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:56 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_temptype_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_temptype_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index d84a25e..c1e5709 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1021,9 +1021,9 @@ struct hfa384x_pdr_privacy_option { u16 available; } __packed; -typedef struct hfa384x_pdr_temptype { +struct hfa384x_pdr_temptype { u16 type; -} __packed hfa384x_pdr_temptype_t; +} __packed; typedef struct hfa384x_pdr_refdac_setup { u16 ch_value[14]; @@ -1111,7 +1111,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_allowed_channel allowed_channel; struct hfa384x_pdr_default_channel default_channel; struct hfa384x_pdr_privacy_option privacy_option; - hfa384x_pdr_temptype_t temptype; + struct hfa384x_pdr_temptype temptype; hfa384x_pdr_refdac_setup_t refdac_setup; hfa384x_pdr_vgdac_setup_t vgdac_setup; hfa384x_pdr_level_comp_setup_t level_comp_setup; -- cgit v0.10.2 From 3c92d65d2e7b9d895dfe5d42f4eb5a62f595427a Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:57 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_refdac_setup_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_refdac_setup_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index c1e5709..cebc52e 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1025,9 +1025,9 @@ struct hfa384x_pdr_temptype { u16 type; } __packed; -typedef struct hfa384x_pdr_refdac_setup { +struct hfa384x_pdr_refdac_setup { u16 ch_value[14]; -} __packed hfa384x_pdr_refdac_setup_t; +} __packed; typedef struct hfa384x_pdr_vgdac_setup { u16 ch_value[14]; @@ -1112,7 +1112,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_default_channel default_channel; struct hfa384x_pdr_privacy_option privacy_option; struct hfa384x_pdr_temptype temptype; - hfa384x_pdr_refdac_setup_t refdac_setup; + struct hfa384x_pdr_refdac_setup refdac_setup; hfa384x_pdr_vgdac_setup_t vgdac_setup; hfa384x_pdr_level_comp_setup_t level_comp_setup; hfa384x_pdr_trimdac_setup_t trimdac_setup; -- cgit v0.10.2 From dce6c28300211bba65b5152e171942b29d8c5fad Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:58 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_vgdac_setup_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_vgdac_setup_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index cebc52e..bab8665 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1029,9 +1029,9 @@ struct hfa384x_pdr_refdac_setup { u16 ch_value[14]; } __packed; -typedef struct hfa384x_pdr_vgdac_setup { +struct hfa384x_pdr_vgdac_setup { u16 ch_value[14]; -} __packed hfa384x_pdr_vgdac_setup_t; +} __packed; typedef struct hfa384x_pdr_level_comp_setup { u16 ch_value[14]; @@ -1113,7 +1113,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_privacy_option privacy_option; struct hfa384x_pdr_temptype temptype; struct hfa384x_pdr_refdac_setup refdac_setup; - hfa384x_pdr_vgdac_setup_t vgdac_setup; + struct hfa384x_pdr_vgdac_setup vgdac_setup; hfa384x_pdr_level_comp_setup_t level_comp_setup; hfa384x_pdr_trimdac_setup_t trimdac_setup; hfa384x_pdr_ifr_setting_t ifr_setting; -- cgit v0.10.2 From 29aef6bb89a46522ccd48210c4f9e224199d3fd9 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:19:59 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_level_comp_setup_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_level_comp_setup_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index bab8665..4fc0760 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1033,9 +1033,9 @@ struct hfa384x_pdr_vgdac_setup { u16 ch_value[14]; } __packed; -typedef struct hfa384x_pdr_level_comp_setup { +struct hfa384x_pdr_level_comp_setup { u16 ch_value[14]; -} __packed hfa384x_pdr_level_comp_setup_t; +} __packed; typedef struct hfa384x_pdr_trimdac_setup { u16 trimidac; @@ -1114,7 +1114,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_temptype temptype; struct hfa384x_pdr_refdac_setup refdac_setup; struct hfa384x_pdr_vgdac_setup vgdac_setup; - hfa384x_pdr_level_comp_setup_t level_comp_setup; + struct hfa384x_pdr_level_comp_setup level_comp_setup; hfa384x_pdr_trimdac_setup_t trimdac_setup; hfa384x_pdr_ifr_setting_t ifr_setting; hfa384x_pdr_rfr_setting_t rfr_setting; -- cgit v0.10.2 From a98f8609ad9fec571ef9b7c1bce444c2f1b98710 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:20:00 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_trimdac_setup_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_trimdac_setup_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 4fc0760..ff4ebd6 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1037,10 +1037,10 @@ struct hfa384x_pdr_level_comp_setup { u16 ch_value[14]; } __packed; -typedef struct hfa384x_pdr_trimdac_setup { +struct hfa384x_pdr_trimdac_setup { u16 trimidac; u16 trimqdac; -} __packed hfa384x_pdr_trimdac_setup_t; +} __packed; typedef struct hfa384x_pdr_ifr_setting { u16 value[3]; @@ -1115,7 +1115,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_refdac_setup refdac_setup; struct hfa384x_pdr_vgdac_setup vgdac_setup; struct hfa384x_pdr_level_comp_setup level_comp_setup; - hfa384x_pdr_trimdac_setup_t trimdac_setup; + struct hfa384x_pdr_trimdac_setup trimdac_setup; hfa384x_pdr_ifr_setting_t ifr_setting; hfa384x_pdr_rfr_setting_t rfr_setting; hfa384x_pdr_hfa3861_baseline_t hfa3861_baseline; -- cgit v0.10.2 From 3d2358857ab02cf3aaa6553d252ebe0e21116a52 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:20:01 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_ifr_setting_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_ifr_setting_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index ff4ebd6..1400cb2 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1042,9 +1042,9 @@ struct hfa384x_pdr_trimdac_setup { u16 trimqdac; } __packed; -typedef struct hfa384x_pdr_ifr_setting { +struct hfa384x_pdr_ifr_setting { u16 value[3]; -} __packed hfa384x_pdr_ifr_setting_t; +} __packed; typedef struct hfa384x_pdr_rfr_setting { u16 value[3]; @@ -1116,7 +1116,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_vgdac_setup vgdac_setup; struct hfa384x_pdr_level_comp_setup level_comp_setup; struct hfa384x_pdr_trimdac_setup trimdac_setup; - hfa384x_pdr_ifr_setting_t ifr_setting; + struct hfa384x_pdr_ifr_setting ifr_setting; hfa384x_pdr_rfr_setting_t rfr_setting; hfa384x_pdr_hfa3861_baseline_t hfa3861_baseline; hfa384x_pdr_hfa3861_shadow_t hfa3861_shadow; -- cgit v0.10.2 From da79fe4aeca494969a2d023f3fbe427247fd90e9 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:20:02 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_rfr_setting_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_rfr_setting_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 1400cb2..b51b568 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1046,9 +1046,9 @@ struct hfa384x_pdr_ifr_setting { u16 value[3]; } __packed; -typedef struct hfa384x_pdr_rfr_setting { +struct hfa384x_pdr_rfr_setting { u16 value[3]; -} __packed hfa384x_pdr_rfr_setting_t; +} __packed; typedef struct hfa384x_pdr_hfa3861_baseline { u16 value[50]; @@ -1117,7 +1117,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_level_comp_setup level_comp_setup; struct hfa384x_pdr_trimdac_setup trimdac_setup; struct hfa384x_pdr_ifr_setting ifr_setting; - hfa384x_pdr_rfr_setting_t rfr_setting; + struct hfa384x_pdr_rfr_setting rfr_setting; hfa384x_pdr_hfa3861_baseline_t hfa3861_baseline; hfa384x_pdr_hfa3861_shadow_t hfa3861_shadow; hfa384x_pdr_hfa3861_ifrf_t hfa3861_ifrf; -- cgit v0.10.2 From b4547dc56846afc9f527c304c211eb1166a9625a Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:20:03 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_hfa3861_baseline_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_hfa3861_baseline_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index b51b568..306f3bb 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1050,9 +1050,9 @@ struct hfa384x_pdr_rfr_setting { u16 value[3]; } __packed; -typedef struct hfa384x_pdr_hfa3861_baseline { +struct hfa384x_pdr_hfa3861_baseline { u16 value[50]; -} __packed hfa384x_pdr_hfa3861_baseline_t; +} __packed; typedef struct hfa384x_pdr_hfa3861_shadow { u32 value[32]; @@ -1118,7 +1118,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_trimdac_setup trimdac_setup; struct hfa384x_pdr_ifr_setting ifr_setting; struct hfa384x_pdr_rfr_setting rfr_setting; - hfa384x_pdr_hfa3861_baseline_t hfa3861_baseline; + struct hfa384x_pdr_hfa3861_baseline hfa3861_baseline; hfa384x_pdr_hfa3861_shadow_t hfa3861_shadow; hfa384x_pdr_hfa3861_ifrf_t hfa3861_ifrf; hfa384x_pdr_hfa3861_chcalsp_t hfa3861_chcalsp; -- cgit v0.10.2 From 0dbc2e46ac1890a5f2a41561e8ef00c147b2202a Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:20:04 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_hfa3861_shadow_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_hfa3861_shadow_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 306f3bb..ebe434f 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1054,9 +1054,9 @@ struct hfa384x_pdr_hfa3861_baseline { u16 value[50]; } __packed; -typedef struct hfa384x_pdr_hfa3861_shadow { +struct hfa384x_pdr_hfa3861_shadow { u32 value[32]; -} __packed hfa384x_pdr_hfa3861_shadow_t; +} __packed; typedef struct hfa384x_pdr_hfa3861_ifrf { u32 value[20]; @@ -1119,7 +1119,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_ifr_setting ifr_setting; struct hfa384x_pdr_rfr_setting rfr_setting; struct hfa384x_pdr_hfa3861_baseline hfa3861_baseline; - hfa384x_pdr_hfa3861_shadow_t hfa3861_shadow; + struct hfa384x_pdr_hfa3861_shadow hfa3861_shadow; hfa384x_pdr_hfa3861_ifrf_t hfa3861_ifrf; hfa384x_pdr_hfa3861_chcalsp_t hfa3861_chcalsp; hfa384x_pdr_hfa3861_chcali_t hfa3861_chcali; -- cgit v0.10.2 From 1755c01bf6d106c7ab5308bdac5251213f9e9600 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:20:05 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_hfa3861_ifrf_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_hfa3861_ifrf_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index ebe434f..25f89ad9 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1058,9 +1058,9 @@ struct hfa384x_pdr_hfa3861_shadow { u32 value[32]; } __packed; -typedef struct hfa384x_pdr_hfa3861_ifrf { +struct hfa384x_pdr_hfa3861_ifrf { u32 value[20]; -} __packed hfa384x_pdr_hfa3861_ifrf_t; +} __packed; typedef struct hfa384x_pdr_hfa3861_chcalsp { u16 value[14]; @@ -1120,7 +1120,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_rfr_setting rfr_setting; struct hfa384x_pdr_hfa3861_baseline hfa3861_baseline; struct hfa384x_pdr_hfa3861_shadow hfa3861_shadow; - hfa384x_pdr_hfa3861_ifrf_t hfa3861_ifrf; + struct hfa384x_pdr_hfa3861_ifrf hfa3861_ifrf; hfa384x_pdr_hfa3861_chcalsp_t hfa3861_chcalsp; hfa384x_pdr_hfa3861_chcali_t hfa3861_chcali; hfa384x_pdr_nic_config_t nic_config; -- cgit v0.10.2 From 788c973247d25e71cd9ed09bf7011f6e1fbea256 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:20:06 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_hfa3861_chcalsp_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_hfa3861_chcalsp_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 25f89ad9..7d63dd8 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1062,9 +1062,9 @@ struct hfa384x_pdr_hfa3861_ifrf { u32 value[20]; } __packed; -typedef struct hfa384x_pdr_hfa3861_chcalsp { +struct hfa384x_pdr_hfa3861_chcalsp { u16 value[14]; -} __packed hfa384x_pdr_hfa3861_chcalsp_t; +} __packed; typedef struct hfa384x_pdr_hfa3861_chcali { u16 value[17]; @@ -1121,7 +1121,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_hfa3861_baseline hfa3861_baseline; struct hfa384x_pdr_hfa3861_shadow hfa3861_shadow; struct hfa384x_pdr_hfa3861_ifrf hfa3861_ifrf; - hfa384x_pdr_hfa3861_chcalsp_t hfa3861_chcalsp; + struct hfa384x_pdr_hfa3861_chcalsp hfa3861_chcalsp; hfa384x_pdr_hfa3861_chcali_t hfa3861_chcali; hfa384x_pdr_nic_config_t nic_config; hfa384x_hfo_delay_t hfo_delay; -- cgit v0.10.2 From b94425ff7081ee9ea1644e93f7458cfa11a356c8 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:20:07 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_hfa3861_chcali_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_hfa3861_chcali_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 7d63dd8..9232855 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1066,9 +1066,9 @@ struct hfa384x_pdr_hfa3861_chcalsp { u16 value[14]; } __packed; -typedef struct hfa384x_pdr_hfa3861_chcali { +struct hfa384x_pdr_hfa3861_chcali { u16 value[17]; -} __packed hfa384x_pdr_hfa3861_chcali_t; +} __packed; typedef struct hfa384x_pdr_hfa3861_nic_config { u16 config_bitmap; @@ -1122,7 +1122,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_hfa3861_shadow hfa3861_shadow; struct hfa384x_pdr_hfa3861_ifrf hfa3861_ifrf; struct hfa384x_pdr_hfa3861_chcalsp hfa3861_chcalsp; - hfa384x_pdr_hfa3861_chcali_t hfa3861_chcali; + struct hfa384x_pdr_hfa3861_chcali hfa3861_chcali; hfa384x_pdr_nic_config_t nic_config; hfa384x_hfo_delay_t hfo_delay; hfa384x_pdr_hfa3861_manf_testsp_t hfa3861_manf_testsp; -- cgit v0.10.2 From bd84b588775a729c8e9d46bcfa2c501ff2836953 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:20:08 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_nic_config_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_nic_config_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 9232855..ce85adf 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1070,9 +1070,9 @@ struct hfa384x_pdr_hfa3861_chcali { u16 value[17]; } __packed; -typedef struct hfa384x_pdr_hfa3861_nic_config { +struct hfa384x_pdr_hfa3861_nic_config { u16 config_bitmap; -} __packed hfa384x_pdr_nic_config_t; +} __packed; typedef struct hfa384x_pdr_hfo_delay { u8 hfo_delay; @@ -1123,7 +1123,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_hfa3861_ifrf hfa3861_ifrf; struct hfa384x_pdr_hfa3861_chcalsp hfa3861_chcalsp; struct hfa384x_pdr_hfa3861_chcali hfa3861_chcali; - hfa384x_pdr_nic_config_t nic_config; + struct hfa384x_pdr_hfa3861_nic_config nic_config; hfa384x_hfo_delay_t hfo_delay; hfa384x_pdr_hfa3861_manf_testsp_t hfa3861_manf_testsp; hfa384x_pdr_hfa3861_manf_testi_t hfa3861_manf_testi; -- cgit v0.10.2 From 9408a44c7e19d9c95cd8eb9e589f3f5bedc44128 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:20:09 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_hfo_delay_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_hfo_delay_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index ce85adf..4817b01 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1074,9 +1074,9 @@ struct hfa384x_pdr_hfa3861_nic_config { u16 config_bitmap; } __packed; -typedef struct hfa384x_pdr_hfo_delay { +struct hfa384x_pdr_hfo_delay { u8 hfo_delay; -} __packed hfa384x_hfo_delay_t; +} __packed; typedef struct hfa384x_pdr_hfa3861_manf_testsp { u16 value[30]; @@ -1124,7 +1124,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_hfa3861_chcalsp hfa3861_chcalsp; struct hfa384x_pdr_hfa3861_chcali hfa3861_chcali; struct hfa384x_pdr_hfa3861_nic_config nic_config; - hfa384x_hfo_delay_t hfo_delay; + struct hfa384x_pdr_hfo_delay hfo_delay; hfa384x_pdr_hfa3861_manf_testsp_t hfa3861_manf_testsp; hfa384x_pdr_hfa3861_manf_testi_t hfa3861_manf_testi; hfa384x_pdr_end_of_pda_t end_of_pda; -- cgit v0.10.2 From 0960d2e1e4e4a8fea5ae8d87ed0ad0899310c2b8 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:20:10 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_hfa3861_manf_testsp_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_hfa3861_manf_testsp_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 4817b01..42e29f0 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1078,9 +1078,9 @@ struct hfa384x_pdr_hfo_delay { u8 hfo_delay; } __packed; -typedef struct hfa384x_pdr_hfa3861_manf_testsp { +struct hfa384x_pdr_hfa3861_manf_testsp { u16 value[30]; -} __packed hfa384x_pdr_hfa3861_manf_testsp_t; +} __packed; typedef struct hfa384x_pdr_hfa3861_manf_testi { u16 value[30]; @@ -1125,7 +1125,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_hfa3861_chcali hfa3861_chcali; struct hfa384x_pdr_hfa3861_nic_config nic_config; struct hfa384x_pdr_hfo_delay hfo_delay; - hfa384x_pdr_hfa3861_manf_testsp_t hfa3861_manf_testsp; + struct hfa384x_pdr_hfa3861_manf_testsp hfa3861_manf_testsp; hfa384x_pdr_hfa3861_manf_testi_t hfa3861_manf_testi; hfa384x_pdr_end_of_pda_t end_of_pda; -- cgit v0.10.2 From 5a4a58236a5ccc781f48200f3eddc4a590bf1264 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:20:11 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_hfa3861_manf_testi_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_hfa3861_manf_testi_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 42e29f0..1d86ccf 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1082,9 +1082,9 @@ struct hfa384x_pdr_hfa3861_manf_testsp { u16 value[30]; } __packed; -typedef struct hfa384x_pdr_hfa3861_manf_testi { +struct hfa384x_pdr_hfa3861_manf_testi { u16 value[30]; -} __packed hfa384x_pdr_hfa3861_manf_testi_t; +} __packed; typedef struct hfa384x_end_of_pda { u16 crc; @@ -1126,7 +1126,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_hfa3861_nic_config nic_config; struct hfa384x_pdr_hfo_delay hfo_delay; struct hfa384x_pdr_hfa3861_manf_testsp hfa3861_manf_testsp; - hfa384x_pdr_hfa3861_manf_testi_t hfa3861_manf_testi; + struct hfa384x_pdr_hfa3861_manf_testi hfa3861_manf_testi; hfa384x_pdr_end_of_pda_t end_of_pda; } data; -- cgit v0.10.2 From b26ce5f6864a5bf524d0513b5b7b00886bbcb644 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:20:12 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdr_end_of_pda_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdr_end_of_pda_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 1d86ccf..45bc4a8 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1086,9 +1086,9 @@ struct hfa384x_pdr_hfa3861_manf_testi { u16 value[30]; } __packed; -typedef struct hfa384x_end_of_pda { +struct hfa384x_pdr_end_of_pda { u16 crc; -} __packed hfa384x_pdr_end_of_pda_t; +} __packed; typedef struct hfa384x_pdrec { u16 len; /* in words */ @@ -1127,7 +1127,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_hfo_delay hfo_delay; struct hfa384x_pdr_hfa3861_manf_testsp hfa3861_manf_testsp; struct hfa384x_pdr_hfa3861_manf_testi hfa3861_manf_testi; - hfa384x_pdr_end_of_pda_t end_of_pda; + struct hfa384x_pdr_end_of_pda end_of_pda; } data; } __packed hfa384x_pdrec_t; -- cgit v0.10.2 From 4f026e894da368a3dbb7454ac696b25e8f4dcbf7 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:20:13 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_pdrec_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_pdrec_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 45bc4a8..57c394d 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1090,7 +1090,7 @@ struct hfa384x_pdr_end_of_pda { u16 crc; } __packed; -typedef struct hfa384x_pdrec { +struct hfa384x_pdrec { u16 len; /* in words */ u16 code; union pdr { @@ -1130,7 +1130,7 @@ typedef struct hfa384x_pdrec { struct hfa384x_pdr_end_of_pda end_of_pda; } data; -} __packed hfa384x_pdrec_t; +} __packed; #ifdef __KERNEL__ /*-------------------------------------------------------------------- diff --git a/drivers/staging/wlan-ng/prism2fw.c b/drivers/staging/wlan-ng/prism2fw.c index ca322fa..96aa211 100644 --- a/drivers/staging/wlan-ng/prism2fw.c +++ b/drivers/staging/wlan-ng/prism2fw.c @@ -105,7 +105,7 @@ struct s3inforec { struct pda { u8 buf[HFA384x_PDA_LEN_MAX]; - hfa384x_pdrec_t *rec[HFA384x_PDA_RECS_MAX]; + struct hfa384x_pdrec *rec[HFA384x_PDA_RECS_MAX]; unsigned int nrec; }; @@ -266,7 +266,7 @@ static int prism2_fwapply(const struct ihex_binrec *rfptr, /* clear the pda and add an initial END record */ memset(&pda, 0, sizeof(pda)); - pda.rec[0] = (hfa384x_pdrec_t *)pda.buf; + pda.rec[0] = (struct hfa384x_pdrec *)pda.buf; pda.rec[0]->len = cpu_to_le16(2); /* len in words */ pda.rec[0]->code = cpu_to_le16(HFA384x_PDR_END_OF_PDA); pda.nrec = 1; @@ -599,7 +599,7 @@ static int mkpdrlist(struct pda *pda) curroff = 0; while (curroff < (HFA384x_PDA_LEN_MAX / 2 - 1) && le16_to_cpu(pda16[curroff + 1]) != HFA384x_PDR_END_OF_PDA) { - pda->rec[pda->nrec] = (hfa384x_pdrec_t *)&(pda16[curroff]); + pda->rec[pda->nrec] = (struct hfa384x_pdrec *)&(pda16[curroff]); if (le16_to_cpu(pda->rec[pda->nrec]->code) == HFA384x_PDR_NICID) { @@ -638,7 +638,7 @@ static int mkpdrlist(struct pda *pda) curroff, pda->nrec); return 1; } - pda->rec[pda->nrec] = (hfa384x_pdrec_t *)&(pda16[curroff]); + pda->rec[pda->nrec] = (struct hfa384x_pdrec *)&(pda16[curroff]); (pda->nrec)++; return 0; } -- cgit v0.10.2 From 501f5f96b3bd70348c5e9f71f3c17ddbab73522d Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:20:14 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_cmdresult_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_cmdresult_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 57c394d..a1a347c 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1138,12 +1138,12 @@ struct hfa384x_pdrec { * --- Also, a collection of support types -- *-------------------------------------------------------------------- */ -typedef struct hfa384x_statusresult { +struct hfa384x_cmdresult { u16 status; u16 resp0; u16 resp1; u16 resp2; -} hfa384x_cmdresult_t; +}; /* USB Control Exchange (CTLX): * A queue of the structure below is maintained for all of the @@ -1213,7 +1213,7 @@ typedef struct hfa484x_metacmd { u16 parm1; u16 parm2; - hfa384x_cmdresult_t result; + struct hfa384x_cmdresult result; } hfa384x_metacmd_t; #define MAX_GRP_ADDR 32 diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 9203880..1e5f74c 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -213,7 +213,7 @@ static void hfa384x_cb_status(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx); static int usbctlx_get_status(const struct hfa384x_usb_statusresp *cmdresp, - hfa384x_cmdresult_t *result); + struct hfa384x_cmdresult *result); static void usbctlx_get_rridresult(const struct hfa384x_usb_rridresp *rridresp, @@ -622,7 +622,7 @@ static hfa384x_usbctlx_t *usbctlx_alloc(void) static int usbctlx_get_status(const struct hfa384x_usb_statusresp *cmdresp, - hfa384x_cmdresult_t *result) + struct hfa384x_cmdresult *result) { result->status = le16_to_cpu(cmdresp->status); result->resp0 = le16_to_cpu(cmdresp->resp0); @@ -647,13 +647,13 @@ usbctlx_get_rridresult(const struct hfa384x_usb_rridresp *rridresp, /*---------------------------------------------------------------- * Completor object: * This completor must be passed to hfa384x_usbctlx_complete_sync() -* when processing a CTLX that returns a hfa384x_cmdresult_t structure. +* when processing a CTLX that returns a struct hfa384x_cmdresult structure. ----------------------------------------------------------------*/ struct usbctlx_cmd_completor { struct usbctlx_completor head; const struct hfa384x_usb_statusresp *cmdresp; - hfa384x_cmdresult_t *result; + struct hfa384x_cmdresult *result; }; static inline int usbctlx_cmd_completor_fn(struct usbctlx_completor *head) @@ -669,7 +669,7 @@ static inline struct usbctlx_completor *init_cmd_completor( *completor, const struct hfa384x_usb_statusresp *cmdresp, - hfa384x_cmdresult_t *result) + struct hfa384x_cmdresult *result) { completor->head.complete = usbctlx_cmd_completor_fn; completor->cmdresp = cmdresp; @@ -798,7 +798,7 @@ static inline struct usbctlx_completor *init_rmem_completor( static void hfa384x_cb_status(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx) { if (ctlx->usercb) { - hfa384x_cmdresult_t cmdresult; + struct hfa384x_cmdresult cmdresult; if (ctlx->state != CTLX_COMPLETE) { memset(&cmdresult, 0, sizeof(cmdresult)); @@ -1497,7 +1497,7 @@ hfa384x_dowrid(hfa384x_t *hw, kfree(ctlx); } else if (mode == DOWAIT) { struct usbctlx_cmd_completor completor; - hfa384x_cmdresult_t wridresult; + struct hfa384x_cmdresult wridresult; result = hfa384x_usbctlx_complete_sync(hw, ctlx, @@ -1679,7 +1679,7 @@ hfa384x_dowmem(hfa384x_t *hw, kfree(ctlx); } else if (mode == DOWAIT) { struct usbctlx_cmd_completor completor; - hfa384x_cmdresult_t wmemresult; + struct hfa384x_cmdresult wmemresult; result = hfa384x_usbctlx_complete_sync(hw, ctlx, -- cgit v0.10.2 From b3fd890e1b4fc2fb0ff72c3663ccff18ba47046b Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:20:15 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_rridresult_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_rridresult_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index a1a347c..9390fdd 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1152,11 +1152,11 @@ struct hfa384x_cmdresult { /* The following hfa384x_* structures are arguments to * the usercb() for the different CTLX types. */ -typedef struct hfa384x_rridresult { +struct hfa384x_rridresult { u16 rid; const void *riddata; unsigned int riddata_len; -} hfa384x_rridresult_t; +}; enum ctlx_state { CTLX_START = 0, /* Start state, not queued */ diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 1e5f74c..17a90c5 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -217,7 +217,7 @@ usbctlx_get_status(const struct hfa384x_usb_statusresp *cmdresp, static void usbctlx_get_rridresult(const struct hfa384x_usb_rridresp *rridresp, - hfa384x_rridresult_t *result); + struct hfa384x_rridresult *result); /*---------------------------------------------------*/ /* Low level req/resp CTLX formatters and submitters */ @@ -637,7 +637,7 @@ usbctlx_get_status(const struct hfa384x_usb_statusresp *cmdresp, static void usbctlx_get_rridresult(const struct hfa384x_usb_rridresp *rridresp, - hfa384x_rridresult_t *result) + struct hfa384x_rridresult *result) { result->rid = le16_to_cpu(rridresp->rid); result->riddata = rridresp->data; @@ -693,7 +693,7 @@ struct usbctlx_rrid_completor { static int usbctlx_rrid_completor_fn(struct usbctlx_completor *head) { struct usbctlx_rrid_completor *complete; - hfa384x_rridresult_t rridresult; + struct hfa384x_rridresult rridresult; complete = (struct usbctlx_rrid_completor *)head; usbctlx_get_rridresult(complete->rridresp, &rridresult); -- cgit v0.10.2 From a10d36b08355d44acd9f0c391f0f01bd631d2d9d Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:20:16 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_usbctlx_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_usbctlx_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 9390fdd..f38b195 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1179,7 +1179,7 @@ typedef void (*ctlx_cmdcb_t) (struct hfa384x *, const struct hfa384x_usbctlx *); typedef void (*ctlx_usercb_t) (struct hfa384x *hw, void *ctlxresult, void *usercb_data); -typedef struct hfa384x_usbctlx { +struct hfa384x_usbctlx { struct list_head list; size_t outbufsize; @@ -1196,7 +1196,7 @@ typedef struct hfa384x_usbctlx { void *usercb_data; /* at CTLX completion */ int variant; /* Identifies cmd variant */ -} hfa384x_usbctlx_t; +}; typedef struct hfa384x_usbctlxq { spinlock_t lock; diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 17a90c5..1f0c428 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -193,9 +193,9 @@ static void hfa384x_usbctlx_completion_task(unsigned long data); static void hfa384x_usbctlx_reaper_task(unsigned long data); -static int hfa384x_usbctlx_submit(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx); +static int hfa384x_usbctlx_submit(hfa384x_t *hw, struct hfa384x_usbctlx *ctlx); -static void unlocked_usbctlx_complete(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx); +static void unlocked_usbctlx_complete(hfa384x_t *hw, struct hfa384x_usbctlx *ctlx); struct usbctlx_completor { int (*complete)(struct usbctlx_completor *); @@ -203,13 +203,13 @@ struct usbctlx_completor { static int hfa384x_usbctlx_complete_sync(hfa384x_t *hw, - hfa384x_usbctlx_t *ctlx, + struct hfa384x_usbctlx *ctlx, struct usbctlx_completor *completor); static int -unlocked_usbctlx_cancel_async(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx); +unlocked_usbctlx_cancel_async(hfa384x_t *hw, struct hfa384x_usbctlx *ctlx); -static void hfa384x_cb_status(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx); +static void hfa384x_cb_status(hfa384x_t *hw, const struct hfa384x_usbctlx *ctlx); static int usbctlx_get_status(const struct hfa384x_usb_statusresp *cmdresp, @@ -278,9 +278,9 @@ static inline const char *ctlxstr(CTLX_STATE s) return ctlx_str[s]; }; -static inline hfa384x_usbctlx_t *get_active_ctlx(hfa384x_t *hw) +static inline struct hfa384x_usbctlx *get_active_ctlx(hfa384x_t *hw) { - return list_entry(hw->ctlxq.active.next, hfa384x_usbctlx_t, list); + return list_entry(hw->ctlxq.active.next, struct hfa384x_usbctlx, list); } #ifdef DEBUG_USB @@ -608,9 +608,9 @@ void hfa384x_destroy(hfa384x_t *hw) dev_kfree_skb(skb); } -static hfa384x_usbctlx_t *usbctlx_alloc(void) +static struct hfa384x_usbctlx *usbctlx_alloc(void) { - hfa384x_usbctlx_t *ctlx; + struct hfa384x_usbctlx *ctlx; ctlx = kzalloc(sizeof(*ctlx), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); @@ -795,7 +795,7 @@ static inline struct usbctlx_completor *init_rmem_completor( * Call context: * interrupt ----------------------------------------------------------------*/ -static void hfa384x_cb_status(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx) +static void hfa384x_cb_status(hfa384x_t *hw, const struct hfa384x_usbctlx *ctlx) { if (ctlx->usercb) { struct hfa384x_cmdresult cmdresult; @@ -1174,7 +1174,7 @@ int hfa384x_corereset(hfa384x_t *hw, int holdtime, int settletime, int genesis) * process ----------------------------------------------------------------*/ static int hfa384x_usbctlx_complete_sync(hfa384x_t *hw, - hfa384x_usbctlx_t *ctlx, + struct hfa384x_usbctlx *ctlx, struct usbctlx_completor *completor) { unsigned long flags; @@ -1295,7 +1295,7 @@ hfa384x_docmd(hfa384x_t *hw, ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) { int result; - hfa384x_usbctlx_t *ctlx; + struct hfa384x_usbctlx *ctlx; ctlx = usbctlx_alloc(); if (!ctlx) { @@ -1385,7 +1385,7 @@ hfa384x_dorrid(hfa384x_t *hw, ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) { int result; - hfa384x_usbctlx_t *ctlx; + struct hfa384x_usbctlx *ctlx; ctlx = usbctlx_alloc(); if (!ctlx) { @@ -1466,7 +1466,7 @@ hfa384x_dowrid(hfa384x_t *hw, ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) { int result; - hfa384x_usbctlx_t *ctlx; + struct hfa384x_usbctlx *ctlx; ctlx = usbctlx_alloc(); if (!ctlx) { @@ -1554,7 +1554,7 @@ hfa384x_dormem(hfa384x_t *hw, ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) { int result; - hfa384x_usbctlx_t *ctlx; + struct hfa384x_usbctlx *ctlx; ctlx = usbctlx_alloc(); if (!ctlx) { @@ -1645,7 +1645,7 @@ hfa384x_dowmem(hfa384x_t *hw, ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) { int result; - hfa384x_usbctlx_t *ctlx; + struct hfa384x_usbctlx *ctlx; pr_debug("page=0x%04x offset=0x%04x len=%d\n", page, offset, len); @@ -2691,7 +2691,7 @@ void hfa384x_tx_timeout(struct wlandevice *wlandev) static void hfa384x_usbctlx_reaper_task(unsigned long data) { hfa384x_t *hw = (hfa384x_t *)data; - hfa384x_usbctlx_t *ctlx, *temp; + struct hfa384x_usbctlx *ctlx, *temp; unsigned long flags; spin_lock_irqsave(&hw->ctlxq.lock, flags); @@ -2724,7 +2724,7 @@ static void hfa384x_usbctlx_reaper_task(unsigned long data) static void hfa384x_usbctlx_completion_task(unsigned long data) { hfa384x_t *hw = (hfa384x_t *)data; - hfa384x_usbctlx_t *ctlx, *temp; + struct hfa384x_usbctlx *ctlx, *temp; unsigned long flags; int reap = 0; @@ -2798,7 +2798,7 @@ static void hfa384x_usbctlx_completion_task(unsigned long data) * Either process or interrupt, but presumably interrupt ----------------------------------------------------------------*/ static int unlocked_usbctlx_cancel_async(hfa384x_t *hw, - hfa384x_usbctlx_t *ctlx) + struct hfa384x_usbctlx *ctlx) { int ret; @@ -2847,7 +2847,7 @@ static int unlocked_usbctlx_cancel_async(hfa384x_t *hw, * Call context: * Either, assume interrupt ----------------------------------------------------------------*/ -static void unlocked_usbctlx_complete(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx) +static void unlocked_usbctlx_complete(hfa384x_t *hw, struct hfa384x_usbctlx *ctlx) { /* Timers have been stopped, and ctlx should be in * a terminal state. Retire it from the "active" @@ -2905,12 +2905,12 @@ static void hfa384x_usbctlxq_run(hfa384x_t *hw) goto unlock; while (!list_empty(&hw->ctlxq.pending)) { - hfa384x_usbctlx_t *head; + struct hfa384x_usbctlx *head; int result; /* This is the first pending command */ head = list_entry(hw->ctlxq.pending.next, - hfa384x_usbctlx_t, list); + struct hfa384x_usbctlx, list); /* We need to split this off to avoid a race condition */ list_move_tail(&head->list, &hw->ctlxq.active); @@ -3169,7 +3169,7 @@ exit: static void hfa384x_usbin_ctlx(hfa384x_t *hw, union hfa384x_usbin *usbin, int urb_status) { - hfa384x_usbctlx_t *ctlx; + struct hfa384x_usbctlx *ctlx; int run_queue = 0; unsigned long flags; @@ -3622,7 +3622,7 @@ static void hfa384x_ctlxout_callback(struct urb *urb) int delete_resptimer = 0; int timer_ok = 1; int run_queue = 0; - hfa384x_usbctlx_t *ctlx; + struct hfa384x_usbctlx *ctlx; unsigned long flags; pr_debug("urb->status=%d\n", urb->status); @@ -3766,7 +3766,7 @@ static void hfa384x_usbctlx_reqtimerfn(unsigned long data) */ hw->ctlx_urb.transfer_flags |= URB_ASYNC_UNLINK; if (usb_unlink_urb(&hw->ctlx_urb) == -EINPROGRESS) { - hfa384x_usbctlx_t *ctlx = get_active_ctlx(hw); + struct hfa384x_usbctlx *ctlx = get_active_ctlx(hw); ctlx->state = CTLX_REQ_FAILED; @@ -3818,7 +3818,7 @@ static void hfa384x_usbctlx_resptimerfn(unsigned long data) * adapter has been unplugged ... */ if (!list_empty(&hw->ctlxq.active)) { - hfa384x_usbctlx_t *ctlx = get_active_ctlx(hw); + struct hfa384x_usbctlx *ctlx = get_active_ctlx(hw); if (unlocked_usbctlx_cancel_async(hw, ctlx) == 0) { spin_unlock_irqrestore(&hw->ctlxq.lock, flags); @@ -3886,7 +3886,7 @@ static void hfa384x_usb_throttlefn(unsigned long data) * Call context: * process or interrupt ----------------------------------------------------------------*/ -static int hfa384x_usbctlx_submit(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx) +static int hfa384x_usbctlx_submit(hfa384x_t *hw, struct hfa384x_usbctlx *ctlx) { unsigned long flags; diff --git a/drivers/staging/wlan-ng/prism2usb.c b/drivers/staging/wlan-ng/prism2usb.c index 3561487..81831d3 100644 --- a/drivers/staging/wlan-ng/prism2usb.c +++ b/drivers/staging/wlan-ng/prism2usb.c @@ -139,7 +139,7 @@ static void prism2sta_disconnect_usb(struct usb_interface *interface) wlandev = (struct wlandevice *)usb_get_intfdata(interface); if (wlandev) { LIST_HEAD(cleanlist); - hfa384x_usbctlx_t *ctlx, *temp; + struct hfa384x_usbctlx *ctlx, *temp; unsigned long flags; hfa384x_t *hw = wlandev->priv; -- cgit v0.10.2 From 3df38936a79589af342060b33ec3139bb09f95cc Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:20:17 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_usbctlxq_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_usbctlxq_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index f38b195..736ac31 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1198,13 +1198,13 @@ struct hfa384x_usbctlx { int variant; /* Identifies cmd variant */ }; -typedef struct hfa384x_usbctlxq { +struct hfa384x_usbctlxq { spinlock_t lock; struct list_head pending; struct list_head active; struct list_head completing; struct list_head reapable; -} hfa384x_usbctlxq_t; +}; typedef struct hfa484x_metacmd { u16 cmd; @@ -1249,7 +1249,7 @@ typedef struct hfa384x { struct urb tx_urb; struct urb ctlx_urb; union hfa384x_usbout txbuff; - hfa384x_usbctlxq_t ctlxq; + struct hfa384x_usbctlxq ctlxq; struct timer_list reqtimer; struct timer_list resptimer; -- cgit v0.10.2 From e2f503c40dcc4d2a772612dc9e4e4c6373bc1f73 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:20:18 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_metacmd_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_metacmd_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 736ac31..b97099d 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1206,7 +1206,7 @@ struct hfa384x_usbctlxq { struct list_head reapable; }; -typedef struct hfa484x_metacmd { +struct hfa384x_metacmd { u16 cmd; u16 parm0; @@ -1214,7 +1214,7 @@ typedef struct hfa484x_metacmd { u16 parm2; struct hfa384x_cmdresult result; -} hfa384x_metacmd_t; +}; #define MAX_GRP_ADDR 32 #define WLAN_COMMENT_MAX 80 /* Max. length of user comment string. */ diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 1f0c428..7b0aae5 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -224,7 +224,7 @@ usbctlx_get_rridresult(const struct hfa384x_usb_rridresp *rridresp, static int hfa384x_docmd(hfa384x_t *hw, enum cmd_mode mode, - hfa384x_metacmd_t *cmd, + struct hfa384x_metacmd *cmd, ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data); static int @@ -812,14 +812,14 @@ static void hfa384x_cb_status(hfa384x_t *hw, const struct hfa384x_usbctlx *ctlx) } } -static inline int hfa384x_docmd_wait(hfa384x_t *hw, hfa384x_metacmd_t *cmd) +static inline int hfa384x_docmd_wait(hfa384x_t *hw, struct hfa384x_metacmd *cmd) { return hfa384x_docmd(hw, DOWAIT, cmd, NULL, NULL, NULL); } static inline int hfa384x_docmd_async(hfa384x_t *hw, - hfa384x_metacmd_t *cmd, + struct hfa384x_metacmd *cmd, ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) { return hfa384x_docmd(hw, DOASYNC, cmd, cmdcb, usercb, usercb_data); @@ -927,7 +927,7 @@ int hfa384x_cmd_initialize(hfa384x_t *hw) { int result = 0; int i; - hfa384x_metacmd_t cmd; + struct hfa384x_metacmd cmd; cmd.cmd = HFA384x_CMDCODE_INIT; cmd.parm0 = 0; @@ -971,7 +971,7 @@ int hfa384x_cmd_initialize(hfa384x_t *hw) ----------------------------------------------------------------*/ int hfa384x_cmd_disable(hfa384x_t *hw, u16 macport) { - hfa384x_metacmd_t cmd; + struct hfa384x_metacmd cmd; cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_DISABLE) | HFA384x_CMD_MACPORT_SET(macport); @@ -1004,7 +1004,7 @@ int hfa384x_cmd_disable(hfa384x_t *hw, u16 macport) ----------------------------------------------------------------*/ int hfa384x_cmd_enable(hfa384x_t *hw, u16 macport) { - hfa384x_metacmd_t cmd; + struct hfa384x_metacmd cmd; cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ENABLE) | HFA384x_CMD_MACPORT_SET(macport); @@ -1046,7 +1046,7 @@ int hfa384x_cmd_enable(hfa384x_t *hw, u16 macport) ----------------------------------------------------------------*/ int hfa384x_cmd_monitor(hfa384x_t *hw, u16 enable) { - hfa384x_metacmd_t cmd; + struct hfa384x_metacmd cmd; cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_MONITOR) | HFA384x_CMD_AINFO_SET(enable); @@ -1098,7 +1098,7 @@ int hfa384x_cmd_monitor(hfa384x_t *hw, u16 enable) int hfa384x_cmd_download(hfa384x_t *hw, u16 mode, u16 lowaddr, u16 highaddr, u16 codelen) { - hfa384x_metacmd_t cmd; + struct hfa384x_metacmd cmd; pr_debug("mode=%d, lowaddr=0x%04x, highaddr=0x%04x, codelen=%d\n", mode, lowaddr, highaddr, codelen); @@ -1291,7 +1291,7 @@ cleanup: static int hfa384x_docmd(hfa384x_t *hw, enum cmd_mode mode, - hfa384x_metacmd_t *cmd, + struct hfa384x_metacmd *cmd, ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) { int result; -- cgit v0.10.2 From 5a2214e2e02fd24874b68ac7f5b07ad4d7ad1813 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:20:19 +0200 Subject: staging: wlang-ng: avoid new typedef: hfa384x_t This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: do not add new typedefs It applies for typedef hfa384x_t Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index b97099d..06a5778 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1241,7 +1241,7 @@ struct prism2sta_accesslist { u8 addr1[WLAN_ACCESS_MAX][ETH_ALEN]; }; -typedef struct hfa384x { +struct hfa384x { /* USB support data */ struct usb_device *usb; struct urb rx_urb; @@ -1377,26 +1377,26 @@ typedef struct hfa384x { struct prism2sta_accesslist allow; /* Allowed station list. */ struct prism2sta_accesslist deny; /* Denied station list. */ -} hfa384x_t; +}; -void hfa384x_create(hfa384x_t *hw, struct usb_device *usb); -void hfa384x_destroy(hfa384x_t *hw); +void hfa384x_create(struct hfa384x *hw, struct usb_device *usb); +void hfa384x_destroy(struct hfa384x *hw); int -hfa384x_corereset(hfa384x_t *hw, int holdtime, int settletime, int genesis); -int hfa384x_drvr_disable(hfa384x_t *hw, u16 macport); -int hfa384x_drvr_enable(hfa384x_t *hw, u16 macport); -int hfa384x_drvr_flashdl_enable(hfa384x_t *hw); -int hfa384x_drvr_flashdl_disable(hfa384x_t *hw); -int hfa384x_drvr_flashdl_write(hfa384x_t *hw, u32 daddr, void *buf, u32 len); -int hfa384x_drvr_getconfig(hfa384x_t *hw, u16 rid, void *buf, u16 len); -int hfa384x_drvr_ramdl_enable(hfa384x_t *hw, u32 exeaddr); -int hfa384x_drvr_ramdl_disable(hfa384x_t *hw); -int hfa384x_drvr_ramdl_write(hfa384x_t *hw, u32 daddr, void *buf, u32 len); -int hfa384x_drvr_readpda(hfa384x_t *hw, void *buf, unsigned int len); -int hfa384x_drvr_setconfig(hfa384x_t *hw, u16 rid, void *buf, u16 len); - -static inline int hfa384x_drvr_getconfig16(hfa384x_t *hw, u16 rid, void *val) +hfa384x_corereset(struct hfa384x *hw, int holdtime, int settletime, int genesis); +int hfa384x_drvr_disable(struct hfa384x *hw, u16 macport); +int hfa384x_drvr_enable(struct hfa384x *hw, u16 macport); +int hfa384x_drvr_flashdl_enable(struct hfa384x *hw); +int hfa384x_drvr_flashdl_disable(struct hfa384x *hw); +int hfa384x_drvr_flashdl_write(struct hfa384x *hw, u32 daddr, void *buf, u32 len); +int hfa384x_drvr_getconfig(struct hfa384x *hw, u16 rid, void *buf, u16 len); +int hfa384x_drvr_ramdl_enable(struct hfa384x *hw, u32 exeaddr); +int hfa384x_drvr_ramdl_disable(struct hfa384x *hw); +int hfa384x_drvr_ramdl_write(struct hfa384x *hw, u32 daddr, void *buf, u32 len); +int hfa384x_drvr_readpda(struct hfa384x *hw, void *buf, unsigned int len); +int hfa384x_drvr_setconfig(struct hfa384x *hw, u16 rid, void *buf, u16 len); + +static inline int hfa384x_drvr_getconfig16(struct hfa384x *hw, u16 rid, void *val) { int result = 0; @@ -1406,7 +1406,7 @@ static inline int hfa384x_drvr_getconfig16(hfa384x_t *hw, u16 rid, void *val) return result; } -static inline int hfa384x_drvr_setconfig16(hfa384x_t *hw, u16 rid, u16 val) +static inline int hfa384x_drvr_setconfig16(struct hfa384x *hw, u16 rid, u16 val) { u16 value = cpu_to_le16(val); @@ -1414,13 +1414,13 @@ static inline int hfa384x_drvr_setconfig16(hfa384x_t *hw, u16 rid, u16 val) } int -hfa384x_drvr_setconfig_async(hfa384x_t *hw, +hfa384x_drvr_setconfig_async(struct hfa384x *hw, u16 rid, void *buf, u16 len, ctlx_usercb_t usercb, void *usercb_data); static inline int -hfa384x_drvr_setconfig16_async(hfa384x_t *hw, u16 rid, u16 val) +hfa384x_drvr_setconfig16_async(struct hfa384x *hw, u16 rid, u16 val) { u16 value = cpu_to_le16(val); @@ -1428,21 +1428,21 @@ hfa384x_drvr_setconfig16_async(hfa384x_t *hw, u16 rid, u16 val) NULL, NULL); } -int hfa384x_drvr_start(hfa384x_t *hw); -int hfa384x_drvr_stop(hfa384x_t *hw); +int hfa384x_drvr_start(struct hfa384x *hw); +int hfa384x_drvr_stop(struct hfa384x *hw); int -hfa384x_drvr_txframe(hfa384x_t *hw, struct sk_buff *skb, +hfa384x_drvr_txframe(struct hfa384x *hw, struct sk_buff *skb, union p80211_hdr *p80211_hdr, struct p80211_metawep *p80211_wep); void hfa384x_tx_timeout(struct wlandevice *wlandev); -int hfa384x_cmd_initialize(hfa384x_t *hw); -int hfa384x_cmd_enable(hfa384x_t *hw, u16 macport); -int hfa384x_cmd_disable(hfa384x_t *hw, u16 macport); -int hfa384x_cmd_allocate(hfa384x_t *hw, u16 len); -int hfa384x_cmd_monitor(hfa384x_t *hw, u16 enable); +int hfa384x_cmd_initialize(struct hfa384x *hw); +int hfa384x_cmd_enable(struct hfa384x *hw, u16 macport); +int hfa384x_cmd_disable(struct hfa384x *hw, u16 macport); +int hfa384x_cmd_allocate(struct hfa384x *hw, u16 len); +int hfa384x_cmd_monitor(struct hfa384x *hw, u16 enable); int -hfa384x_cmd_download(hfa384x_t *hw, +hfa384x_cmd_download(struct hfa384x *hw, u16 mode, u16 lowaddr, u16 highaddr, u16 codelen); #endif /*__KERNEL__ */ diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 7b0aae5..6a107f8 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -158,9 +158,9 @@ hfa384x_int_rxmonitor(struct wlandevice *wlandev, struct hfa384x_usb_rxfrm *rxfr static void hfa384x_usb_defer(struct work_struct *data); -static int submit_rx_urb(hfa384x_t *hw, gfp_t flags); +static int submit_rx_urb(struct hfa384x *hw, gfp_t flags); -static int submit_tx_urb(hfa384x_t *hw, struct urb *tx_urb, gfp_t flags); +static int submit_tx_urb(struct hfa384x *hw, struct urb *tx_urb, gfp_t flags); /*---------------------------------------------------*/ /* Callbacks */ @@ -175,13 +175,13 @@ static void hfa384x_usbin_rx(struct wlandevice *wlandev, struct sk_buff *skb); static void hfa384x_usbin_info(struct wlandevice *wlandev, union hfa384x_usbin *usbin); -static void hfa384x_usbin_ctlx(hfa384x_t *hw, union hfa384x_usbin *usbin, +static void hfa384x_usbin_ctlx(struct hfa384x *hw, union hfa384x_usbin *usbin, int urb_status); /*---------------------------------------------------*/ /* Functions to support the prism2 usb command queue */ -static void hfa384x_usbctlxq_run(hfa384x_t *hw); +static void hfa384x_usbctlxq_run(struct hfa384x *hw); static void hfa384x_usbctlx_reqtimerfn(unsigned long data); @@ -193,23 +193,23 @@ static void hfa384x_usbctlx_completion_task(unsigned long data); static void hfa384x_usbctlx_reaper_task(unsigned long data); -static int hfa384x_usbctlx_submit(hfa384x_t *hw, struct hfa384x_usbctlx *ctlx); +static int hfa384x_usbctlx_submit(struct hfa384x *hw, struct hfa384x_usbctlx *ctlx); -static void unlocked_usbctlx_complete(hfa384x_t *hw, struct hfa384x_usbctlx *ctlx); +static void unlocked_usbctlx_complete(struct hfa384x *hw, struct hfa384x_usbctlx *ctlx); struct usbctlx_completor { int (*complete)(struct usbctlx_completor *); }; static int -hfa384x_usbctlx_complete_sync(hfa384x_t *hw, +hfa384x_usbctlx_complete_sync(struct hfa384x *hw, struct hfa384x_usbctlx *ctlx, struct usbctlx_completor *completor); static int -unlocked_usbctlx_cancel_async(hfa384x_t *hw, struct hfa384x_usbctlx *ctlx); +unlocked_usbctlx_cancel_async(struct hfa384x *hw, struct hfa384x_usbctlx *ctlx); -static void hfa384x_cb_status(hfa384x_t *hw, const struct hfa384x_usbctlx *ctlx); +static void hfa384x_cb_status(struct hfa384x *hw, const struct hfa384x_usbctlx *ctlx); static int usbctlx_get_status(const struct hfa384x_usb_statusresp *cmdresp, @@ -222,13 +222,13 @@ usbctlx_get_rridresult(const struct hfa384x_usb_rridresp *rridresp, /*---------------------------------------------------*/ /* Low level req/resp CTLX formatters and submitters */ static int -hfa384x_docmd(hfa384x_t *hw, +hfa384x_docmd(struct hfa384x *hw, enum cmd_mode mode, struct hfa384x_metacmd *cmd, ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data); static int -hfa384x_dorrid(hfa384x_t *hw, +hfa384x_dorrid(struct hfa384x *hw, enum cmd_mode mode, u16 rid, void *riddata, @@ -236,7 +236,7 @@ hfa384x_dorrid(hfa384x_t *hw, ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data); static int -hfa384x_dowrid(hfa384x_t *hw, +hfa384x_dowrid(struct hfa384x *hw, enum cmd_mode mode, u16 rid, void *riddata, @@ -244,7 +244,7 @@ hfa384x_dowrid(hfa384x_t *hw, ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data); static int -hfa384x_dormem(hfa384x_t *hw, +hfa384x_dormem(struct hfa384x *hw, enum cmd_mode mode, u16 page, u16 offset, @@ -253,7 +253,7 @@ hfa384x_dormem(hfa384x_t *hw, ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data); static int -hfa384x_dowmem(hfa384x_t *hw, +hfa384x_dowmem(struct hfa384x *hw, enum cmd_mode mode, u16 page, u16 offset, @@ -278,7 +278,7 @@ static inline const char *ctlxstr(CTLX_STATE s) return ctlx_str[s]; }; -static inline struct hfa384x_usbctlx *get_active_ctlx(hfa384x_t *hw) +static inline struct hfa384x_usbctlx *get_active_ctlx(struct hfa384x *hw) { return list_entry(hw->ctlxq.active.next, struct hfa384x_usbctlx, list); } @@ -322,7 +322,7 @@ void dbprint_urb(struct urb *urb) * Call context: * Any ----------------------------------------------------------------*/ -static int submit_rx_urb(hfa384x_t *hw, gfp_t memflags) +static int submit_rx_urb(struct hfa384x *hw, gfp_t memflags) { struct sk_buff *skb; int result; @@ -384,7 +384,7 @@ done: * Call context: * Any ----------------------------------------------------------------*/ -static int submit_tx_urb(hfa384x_t *hw, struct urb *tx_urb, gfp_t memflags) +static int submit_tx_urb(struct hfa384x *hw, struct urb *tx_urb, gfp_t memflags) { struct net_device *netdev = hw->wlandev->netdev; int result; @@ -429,7 +429,7 @@ static int submit_tx_urb(hfa384x_t *hw, struct urb *tx_urb, gfp_t memflags) ----------------------------------------------------------------*/ static void hfa384x_usb_defer(struct work_struct *data) { - hfa384x_t *hw = container_of(data, struct hfa384x, usb_work); + struct hfa384x *hw = container_of(data, struct hfa384x, usb_work); struct net_device *netdev = hw->wlandev->netdev; /* Don't bother trying to reset anything if the plug @@ -503,7 +503,7 @@ static void hfa384x_usb_defer(struct work_struct *data) /*---------------------------------------------------------------- * hfa384x_create * -* Sets up the hfa384x_t data structure for use. Note this +* Sets up the struct hfa384x data structure for use. Note this * does _not_ initialize the actual hardware, just the data structures * we use to keep track of its state. * @@ -521,9 +521,9 @@ static void hfa384x_usb_defer(struct work_struct *data) * Call context: * process ----------------------------------------------------------------*/ -void hfa384x_create(hfa384x_t *hw, struct usb_device *usb) +void hfa384x_create(struct hfa384x *hw, struct usb_device *usb) { - memset(hw, 0, sizeof(hfa384x_t)); + memset(hw, 0, sizeof(struct hfa384x)); hw->usb = usb; /* set up the endpoints */ @@ -592,7 +592,7 @@ void hfa384x_create(hfa384x_t *hw, struct usb_device *usb) * Call context: * process ----------------------------------------------------------------*/ -void hfa384x_destroy(hfa384x_t *hw) +void hfa384x_destroy(struct hfa384x *hw) { struct sk_buff *skb; @@ -795,7 +795,7 @@ static inline struct usbctlx_completor *init_rmem_completor( * Call context: * interrupt ----------------------------------------------------------------*/ -static void hfa384x_cb_status(hfa384x_t *hw, const struct hfa384x_usbctlx *ctlx) +static void hfa384x_cb_status(struct hfa384x *hw, const struct hfa384x_usbctlx *ctlx) { if (ctlx->usercb) { struct hfa384x_cmdresult cmdresult; @@ -812,13 +812,13 @@ static void hfa384x_cb_status(hfa384x_t *hw, const struct hfa384x_usbctlx *ctlx) } } -static inline int hfa384x_docmd_wait(hfa384x_t *hw, struct hfa384x_metacmd *cmd) +static inline int hfa384x_docmd_wait(struct hfa384x *hw, struct hfa384x_metacmd *cmd) { return hfa384x_docmd(hw, DOWAIT, cmd, NULL, NULL, NULL); } static inline int -hfa384x_docmd_async(hfa384x_t *hw, +hfa384x_docmd_async(struct hfa384x *hw, struct hfa384x_metacmd *cmd, ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) { @@ -826,7 +826,7 @@ hfa384x_docmd_async(hfa384x_t *hw, } static inline int -hfa384x_dorrid_wait(hfa384x_t *hw, u16 rid, void *riddata, +hfa384x_dorrid_wait(struct hfa384x *hw, u16 rid, void *riddata, unsigned int riddatalen) { return hfa384x_dorrid(hw, DOWAIT, @@ -834,7 +834,7 @@ hfa384x_dorrid_wait(hfa384x_t *hw, u16 rid, void *riddata, } static inline int -hfa384x_dorrid_async(hfa384x_t *hw, +hfa384x_dorrid_async(struct hfa384x *hw, u16 rid, void *riddata, unsigned int riddatalen, ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) @@ -845,7 +845,7 @@ hfa384x_dorrid_async(hfa384x_t *hw, } static inline int -hfa384x_dowrid_wait(hfa384x_t *hw, u16 rid, void *riddata, +hfa384x_dowrid_wait(struct hfa384x *hw, u16 rid, void *riddata, unsigned int riddatalen) { return hfa384x_dowrid(hw, DOWAIT, @@ -853,7 +853,7 @@ hfa384x_dowrid_wait(hfa384x_t *hw, u16 rid, void *riddata, } static inline int -hfa384x_dowrid_async(hfa384x_t *hw, +hfa384x_dowrid_async(struct hfa384x *hw, u16 rid, void *riddata, unsigned int riddatalen, ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) @@ -864,7 +864,7 @@ hfa384x_dowrid_async(hfa384x_t *hw, } static inline int -hfa384x_dormem_wait(hfa384x_t *hw, +hfa384x_dormem_wait(struct hfa384x *hw, u16 page, u16 offset, void *data, unsigned int len) { return hfa384x_dormem(hw, DOWAIT, @@ -872,7 +872,7 @@ hfa384x_dormem_wait(hfa384x_t *hw, } static inline int -hfa384x_dormem_async(hfa384x_t *hw, +hfa384x_dormem_async(struct hfa384x *hw, u16 page, u16 offset, void *data, unsigned int len, ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) @@ -883,7 +883,7 @@ hfa384x_dormem_async(hfa384x_t *hw, } static inline int -hfa384x_dowmem_wait(hfa384x_t *hw, +hfa384x_dowmem_wait(struct hfa384x *hw, u16 page, u16 offset, void *data, unsigned int len) { return hfa384x_dowmem(hw, DOWAIT, @@ -891,7 +891,7 @@ hfa384x_dowmem_wait(hfa384x_t *hw, } static inline int -hfa384x_dowmem_async(hfa384x_t *hw, +hfa384x_dowmem_async(struct hfa384x *hw, u16 page, u16 offset, void *data, @@ -923,7 +923,7 @@ hfa384x_dowmem_async(hfa384x_t *hw, * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_cmd_initialize(hfa384x_t *hw) +int hfa384x_cmd_initialize(struct hfa384x *hw) { int result = 0; int i; @@ -969,7 +969,7 @@ int hfa384x_cmd_initialize(hfa384x_t *hw) * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_cmd_disable(hfa384x_t *hw, u16 macport) +int hfa384x_cmd_disable(struct hfa384x *hw, u16 macport) { struct hfa384x_metacmd cmd; @@ -1002,7 +1002,7 @@ int hfa384x_cmd_disable(hfa384x_t *hw, u16 macport) * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_cmd_enable(hfa384x_t *hw, u16 macport) +int hfa384x_cmd_enable(struct hfa384x *hw, u16 macport) { struct hfa384x_metacmd cmd; @@ -1044,7 +1044,7 @@ int hfa384x_cmd_enable(hfa384x_t *hw, u16 macport) * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_cmd_monitor(hfa384x_t *hw, u16 enable) +int hfa384x_cmd_monitor(struct hfa384x *hw, u16 enable) { struct hfa384x_metacmd cmd; @@ -1095,7 +1095,7 @@ int hfa384x_cmd_monitor(hfa384x_t *hw, u16 enable) * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_cmd_download(hfa384x_t *hw, u16 mode, u16 lowaddr, +int hfa384x_cmd_download(struct hfa384x *hw, u16 mode, u16 lowaddr, u16 highaddr, u16 codelen) { struct hfa384x_metacmd cmd; @@ -1136,7 +1136,7 @@ int hfa384x_cmd_download(hfa384x_t *hw, u16 mode, u16 lowaddr, * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_corereset(hfa384x_t *hw, int holdtime, int settletime, int genesis) +int hfa384x_corereset(struct hfa384x *hw, int holdtime, int settletime, int genesis) { int result; @@ -1173,7 +1173,7 @@ int hfa384x_corereset(hfa384x_t *hw, int holdtime, int settletime, int genesis) * Call context: * process ----------------------------------------------------------------*/ -static int hfa384x_usbctlx_complete_sync(hfa384x_t *hw, +static int hfa384x_usbctlx_complete_sync(struct hfa384x *hw, struct hfa384x_usbctlx *ctlx, struct usbctlx_completor *completor) { @@ -1289,7 +1289,7 @@ cleanup: * process ----------------------------------------------------------------*/ static int -hfa384x_docmd(hfa384x_t *hw, +hfa384x_docmd(struct hfa384x *hw, enum cmd_mode mode, struct hfa384x_metacmd *cmd, ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) @@ -1377,7 +1377,7 @@ done: * process (DOWAIT or DOASYNC) ----------------------------------------------------------------*/ static int -hfa384x_dorrid(hfa384x_t *hw, +hfa384x_dorrid(struct hfa384x *hw, enum cmd_mode mode, u16 rid, void *riddata, @@ -1458,7 +1458,7 @@ done: * process (DOWAIT or DOASYNC) ----------------------------------------------------------------*/ static int -hfa384x_dowrid(hfa384x_t *hw, +hfa384x_dowrid(struct hfa384x *hw, enum cmd_mode mode, u16 rid, void *riddata, @@ -1545,7 +1545,7 @@ done: * process (DOWAIT or DOASYNC) ----------------------------------------------------------------*/ static int -hfa384x_dormem(hfa384x_t *hw, +hfa384x_dormem(struct hfa384x *hw, enum cmd_mode mode, u16 page, u16 offset, @@ -1636,7 +1636,7 @@ done: * process (DOWAIT or DOASYNC) ----------------------------------------------------------------*/ static int -hfa384x_dowmem(hfa384x_t *hw, +hfa384x_dowmem(struct hfa384x *hw, enum cmd_mode mode, u16 page, u16 offset, @@ -1715,7 +1715,7 @@ done: * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_drvr_disable(hfa384x_t *hw, u16 macport) +int hfa384x_drvr_disable(struct hfa384x *hw, u16 macport) { int result = 0; @@ -1753,7 +1753,7 @@ int hfa384x_drvr_disable(hfa384x_t *hw, u16 macport) * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_drvr_enable(hfa384x_t *hw, u16 macport) +int hfa384x_drvr_enable(struct hfa384x *hw, u16 macport) { int result = 0; @@ -1790,7 +1790,7 @@ int hfa384x_drvr_enable(hfa384x_t *hw, u16 macport) * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_drvr_flashdl_enable(hfa384x_t *hw) +int hfa384x_drvr_flashdl_enable(struct hfa384x *hw) { int result = 0; int i; @@ -1849,7 +1849,7 @@ int hfa384x_drvr_flashdl_enable(hfa384x_t *hw) * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_drvr_flashdl_disable(hfa384x_t *hw) +int hfa384x_drvr_flashdl_disable(struct hfa384x *hw) { /* Check that we're already in the download state */ if (hw->dlstate != HFA384x_DLSTATE_FLASHENABLED) @@ -1894,7 +1894,7 @@ int hfa384x_drvr_flashdl_disable(hfa384x_t *hw) * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_drvr_flashdl_write(hfa384x_t *hw, u32 daddr, void *buf, u32 len) +int hfa384x_drvr_flashdl_write(struct hfa384x *hw, u32 daddr, void *buf, u32 len) { int result = 0; u32 dlbufaddr; @@ -2032,7 +2032,7 @@ exit_proc: * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_drvr_getconfig(hfa384x_t *hw, u16 rid, void *buf, u16 len) +int hfa384x_drvr_getconfig(struct hfa384x *hw, u16 rid, void *buf, u16 len) { return hfa384x_dorrid_wait(hw, rid, buf, len); } @@ -2061,7 +2061,7 @@ int hfa384x_drvr_getconfig(hfa384x_t *hw, u16 rid, void *buf, u16 len) * process ----------------------------------------------------------------*/ int -hfa384x_drvr_setconfig_async(hfa384x_t *hw, +hfa384x_drvr_setconfig_async(struct hfa384x *hw, u16 rid, void *buf, u16 len, ctlx_usercb_t usercb, void *usercb_data) @@ -2088,7 +2088,7 @@ hfa384x_drvr_setconfig_async(hfa384x_t *hw, * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_drvr_ramdl_disable(hfa384x_t *hw) +int hfa384x_drvr_ramdl_disable(struct hfa384x *hw) { /* Check that we're already in the download state */ if (hw->dlstate != HFA384x_DLSTATE_RAMENABLED) @@ -2128,7 +2128,7 @@ int hfa384x_drvr_ramdl_disable(hfa384x_t *hw) * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_drvr_ramdl_enable(hfa384x_t *hw, u32 exeaddr) +int hfa384x_drvr_ramdl_enable(struct hfa384x *hw, u32 exeaddr) { int result = 0; u16 lowaddr; @@ -2196,7 +2196,7 @@ int hfa384x_drvr_ramdl_enable(hfa384x_t *hw, u32 exeaddr) * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_drvr_ramdl_write(hfa384x_t *hw, u32 daddr, void *buf, u32 len) +int hfa384x_drvr_ramdl_write(struct hfa384x *hw, u32 daddr, void *buf, u32 len) { int result = 0; int nwrites; @@ -2276,7 +2276,7 @@ int hfa384x_drvr_ramdl_write(hfa384x_t *hw, u32 daddr, void *buf, u32 len) * Call context: * process or non-card interrupt. ----------------------------------------------------------------*/ -int hfa384x_drvr_readpda(hfa384x_t *hw, void *buf, unsigned int len) +int hfa384x_drvr_readpda(struct hfa384x *hw, void *buf, unsigned int len) { int result = 0; u16 *pda = buf; @@ -2386,7 +2386,7 @@ int hfa384x_drvr_readpda(hfa384x_t *hw, void *buf, unsigned int len) * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_drvr_setconfig(hfa384x_t *hw, u16 rid, void *buf, u16 len) +int hfa384x_drvr_setconfig(struct hfa384x *hw, u16 rid, void *buf, u16 len) { return hfa384x_dowrid_wait(hw, rid, buf, len); } @@ -2411,7 +2411,7 @@ int hfa384x_drvr_setconfig(hfa384x_t *hw, u16 rid, void *buf, u16 len) * process ----------------------------------------------------------------*/ -int hfa384x_drvr_start(hfa384x_t *hw) +int hfa384x_drvr_start(struct hfa384x *hw) { int result, result1, result2; u16 status; @@ -2512,7 +2512,7 @@ done: * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_drvr_stop(hfa384x_t *hw) +int hfa384x_drvr_stop(struct hfa384x *hw) { int i; @@ -2562,7 +2562,7 @@ int hfa384x_drvr_stop(hfa384x_t *hw) * Call context: * interrupt ----------------------------------------------------------------*/ -int hfa384x_drvr_txframe(hfa384x_t *hw, struct sk_buff *skb, +int hfa384x_drvr_txframe(struct hfa384x *hw, struct sk_buff *skb, union p80211_hdr *p80211_hdr, struct p80211_metawep *p80211_wep) { @@ -2658,7 +2658,7 @@ exit: void hfa384x_tx_timeout(struct wlandevice *wlandev) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; unsigned long flags; spin_lock_irqsave(&hw->ctlxq.lock, flags); @@ -2681,7 +2681,7 @@ void hfa384x_tx_timeout(struct wlandevice *wlandev) * Tasklet to delete dead CTLX objects * * Arguments: -* data ptr to a hfa384x_t +* data ptr to a struct hfa384x * * Returns: * @@ -2690,7 +2690,7 @@ void hfa384x_tx_timeout(struct wlandevice *wlandev) ----------------------------------------------------------------*/ static void hfa384x_usbctlx_reaper_task(unsigned long data) { - hfa384x_t *hw = (hfa384x_t *)data; + struct hfa384x *hw = (struct hfa384x *)data; struct hfa384x_usbctlx *ctlx, *temp; unsigned long flags; @@ -2713,7 +2713,7 @@ static void hfa384x_usbctlx_reaper_task(unsigned long data) * Tasklet to call completion handlers for returned CTLXs * * Arguments: -* data ptr to hfa384x_t +* data ptr to struct hfa384x * * Returns: * Nothing @@ -2723,7 +2723,7 @@ static void hfa384x_usbctlx_reaper_task(unsigned long data) ----------------------------------------------------------------*/ static void hfa384x_usbctlx_completion_task(unsigned long data) { - hfa384x_t *hw = (hfa384x_t *)data; + struct hfa384x *hw = (struct hfa384x *)data; struct hfa384x_usbctlx *ctlx, *temp; unsigned long flags; @@ -2787,7 +2787,7 @@ static void hfa384x_usbctlx_completion_task(unsigned long data) * next command on the queue is run afterwards. * * Arguments: -* hw ptr to the hfa384x_t structure +* hw ptr to the struct hfa384x structure * ctlx ptr to a CTLX structure * * Returns: @@ -2797,7 +2797,7 @@ static void hfa384x_usbctlx_completion_task(unsigned long data) * Call context: * Either process or interrupt, but presumably interrupt ----------------------------------------------------------------*/ -static int unlocked_usbctlx_cancel_async(hfa384x_t *hw, +static int unlocked_usbctlx_cancel_async(struct hfa384x *hw, struct hfa384x_usbctlx *ctlx) { int ret; @@ -2836,7 +2836,7 @@ static int unlocked_usbctlx_cancel_async(hfa384x_t *hw, * tasklet is scheduled. * * Arguments: -* hw ptr to a hfa384x_t structure +* hw ptr to a struct hfa384x structure * ctlx ptr to a ctlx structure * * Returns: @@ -2847,7 +2847,7 @@ static int unlocked_usbctlx_cancel_async(hfa384x_t *hw, * Call context: * Either, assume interrupt ----------------------------------------------------------------*/ -static void unlocked_usbctlx_complete(hfa384x_t *hw, struct hfa384x_usbctlx *ctlx) +static void unlocked_usbctlx_complete(struct hfa384x *hw, struct hfa384x_usbctlx *ctlx) { /* Timers have been stopped, and ctlx should be in * a terminal state. Retire it from the "active" @@ -2876,7 +2876,7 @@ static void unlocked_usbctlx_complete(hfa384x_t *hw, struct hfa384x_usbctlx *ctl * Checks to see if the head item is running. If not, starts it. * * Arguments: -* hw ptr to hfa384x_t +* hw ptr to struct hfa384x * * Returns: * nothing @@ -2886,7 +2886,7 @@ static void unlocked_usbctlx_complete(hfa384x_t *hw, struct hfa384x_usbctlx *ctl * Call context: * any ----------------------------------------------------------------*/ -static void hfa384x_usbctlxq_run(hfa384x_t *hw) +static void hfa384x_usbctlxq_run(struct hfa384x *hw) { unsigned long flags; @@ -2989,7 +2989,7 @@ unlock: static void hfa384x_usbin_callback(struct urb *urb) { struct wlandevice *wlandev = urb->context; - hfa384x_t *hw; + struct hfa384x *hw; union hfa384x_usbin *usbin = (union hfa384x_usbin *)urb->transfer_buffer; struct sk_buff *skb = NULL; int result; @@ -3154,7 +3154,7 @@ exit: * queue and our state updated accordingly. * * Arguments: -* hw ptr to hfa384x_t +* hw ptr to struct hfa384x * usbin ptr to USB IN packet * urb_status status of this Bulk-In URB * @@ -3166,7 +3166,7 @@ exit: * Call context: * interrupt ----------------------------------------------------------------*/ -static void hfa384x_usbin_ctlx(hfa384x_t *hw, union hfa384x_usbin *usbin, +static void hfa384x_usbin_ctlx(struct hfa384x *hw, union hfa384x_usbin *usbin, int urb_status) { struct hfa384x_usbctlx *ctlx; @@ -3319,7 +3319,7 @@ static void hfa384x_usbin_txcompl(struct wlandevice *wlandev, static void hfa384x_usbin_rx(struct wlandevice *wlandev, struct sk_buff *skb) { union hfa384x_usbin *usbin = (union hfa384x_usbin *)skb->data; - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; int hdrlen; struct p80211_rxmeta *rxmeta; u16 data_len; @@ -3426,7 +3426,7 @@ static void hfa384x_int_rxmonitor(struct wlandevice *wlandev, u8 *datap; u16 fc; struct sk_buff *skb; - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; /* Remember the status, time, and data_len fields are in host order */ /* Figure out how big the frame is */ @@ -3557,7 +3557,7 @@ static void hfa384x_usbout_callback(struct urb *urb) case -EPIPE: { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; netdev_warn(hw->wlandev->netdev, "%s tx pipe stalled: requesting reset\n", @@ -3573,7 +3573,7 @@ static void hfa384x_usbout_callback(struct urb *urb) case -ETIMEDOUT: case -EILSEQ: { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; if (!test_and_set_bit (THROTTLE_TX, &hw->usb_flags) && @@ -3618,7 +3618,7 @@ static void hfa384x_usbout_callback(struct urb *urb) ----------------------------------------------------------------*/ static void hfa384x_ctlxout_callback(struct urb *urb) { - hfa384x_t *hw = urb->context; + struct hfa384x *hw = urb->context; int delete_resptimer = 0; int timer_ok = 1; int run_queue = 0; @@ -3737,7 +3737,7 @@ delresp: * URB containing a Prism2.x XXX_Request was never called. * * Arguments: -* data a ptr to the hfa384x_t +* data a ptr to the struct hfa384x * * Returns: * nothing @@ -3749,7 +3749,7 @@ delresp: ----------------------------------------------------------------*/ static void hfa384x_usbctlx_reqtimerfn(unsigned long data) { - hfa384x_t *hw = (hfa384x_t *)data; + struct hfa384x *hw = (struct hfa384x *)data; unsigned long flags; spin_lock_irqsave(&hw->ctlxq.lock, flags); @@ -3795,7 +3795,7 @@ static void hfa384x_usbctlx_reqtimerfn(unsigned long data) * URB containing a Prism2.x XXX_Response was never called. * * Arguments: -* data a ptr to the hfa384x_t +* data a ptr to the struct hfa384x * * Returns: * nothing @@ -3807,7 +3807,7 @@ static void hfa384x_usbctlx_reqtimerfn(unsigned long data) ----------------------------------------------------------------*/ static void hfa384x_usbctlx_resptimerfn(unsigned long data) { - hfa384x_t *hw = (hfa384x_t *)data; + struct hfa384x *hw = (struct hfa384x *)data; unsigned long flags; spin_lock_irqsave(&hw->ctlxq.lock, flags); @@ -3846,7 +3846,7 @@ static void hfa384x_usbctlx_resptimerfn(unsigned long data) ----------------------------------------------------------------*/ static void hfa384x_usb_throttlefn(unsigned long data) { - hfa384x_t *hw = (hfa384x_t *)data; + struct hfa384x *hw = (struct hfa384x *)data; unsigned long flags; spin_lock_irqsave(&hw->ctlxq.lock, flags); @@ -3886,7 +3886,7 @@ static void hfa384x_usb_throttlefn(unsigned long data) * Call context: * process or interrupt ----------------------------------------------------------------*/ -static int hfa384x_usbctlx_submit(hfa384x_t *hw, struct hfa384x_usbctlx *ctlx) +static int hfa384x_usbctlx_submit(struct hfa384x *hw, struct hfa384x_usbctlx *ctlx) { unsigned long flags; diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c index 1780875..170de1c 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.c +++ b/drivers/staging/wlan-ng/prism2mgmt.c @@ -116,7 +116,7 @@ int prism2mgmt_scan(struct wlandevice *wlandev, void *msgp) { int result = 0; - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; struct p80211msg_dot11req_scan *msg = msgp; u16 roamingmode, word; int i, timeout; @@ -370,7 +370,7 @@ int prism2mgmt_scan_results(struct wlandevice *wlandev, void *msgp) { int result = 0; struct p80211msg_dot11req_scan_results *req; - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; struct hfa384x_HScanResultSub *item = NULL; int count; @@ -528,7 +528,7 @@ exit: int prism2mgmt_start(struct wlandevice *wlandev, void *msgp) { int result = 0; - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; struct p80211msg_dot11req_start *msg = msgp; struct p80211pstrd *pstr; @@ -708,7 +708,7 @@ done: ----------------------------------------------------------------*/ int prism2mgmt_readpda(struct wlandevice *wlandev, void *msgp) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; struct p80211msg_p2req_readpda *msg = msgp; int result; @@ -774,7 +774,7 @@ int prism2mgmt_readpda(struct wlandevice *wlandev, void *msgp) ----------------------------------------------------------------*/ int prism2mgmt_ramdl_state(struct wlandevice *wlandev, void *msgp) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; struct p80211msg_p2req_ramdl_state *msg = msgp; if (wlandev->msdstate != WLAN_MSD_FWLOAD) { @@ -829,7 +829,7 @@ int prism2mgmt_ramdl_state(struct wlandevice *wlandev, void *msgp) ----------------------------------------------------------------*/ int prism2mgmt_ramdl_write(struct wlandevice *wlandev, void *msgp) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; struct p80211msg_p2req_ramdl_write *msg = msgp; u32 addr; u32 len; @@ -891,7 +891,7 @@ int prism2mgmt_ramdl_write(struct wlandevice *wlandev, void *msgp) int prism2mgmt_flashdl_state(struct wlandevice *wlandev, void *msgp) { int result = 0; - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; struct p80211msg_p2req_flashdl_state *msg = msgp; if (wlandev->msdstate != WLAN_MSD_FWLOAD) { @@ -961,7 +961,7 @@ int prism2mgmt_flashdl_state(struct wlandevice *wlandev, void *msgp) ----------------------------------------------------------------*/ int prism2mgmt_flashdl_write(struct wlandevice *wlandev, void *msgp) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; struct p80211msg_p2req_flashdl_write *msg = msgp; u32 addr; u32 len; @@ -1021,7 +1021,7 @@ int prism2mgmt_flashdl_write(struct wlandevice *wlandev, void *msgp) ----------------------------------------------------------------*/ int prism2mgmt_autojoin(struct wlandevice *wlandev, void *msgp) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; int result = 0; u16 reg; u16 port_type; @@ -1095,7 +1095,7 @@ int prism2mgmt_wlansniff(struct wlandevice *wlandev, void *msgp) int result = 0; struct p80211msg_lnxreq_wlansniff *msg = msgp; - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; u16 word; msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; diff --git a/drivers/staging/wlan-ng/prism2mgmt.h b/drivers/staging/wlan-ng/prism2mgmt.h index a275e97..cc1ac7a 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.h +++ b/drivers/staging/wlan-ng/prism2mgmt.h @@ -96,10 +96,11 @@ void prism2mgmt_bytestr2pstr(struct hfa384x_bytestr *bytestr, struct p80211pstrd *pstr); /* functions to convert Group Addresses */ -void prism2mgmt_get_grpaddr(u32 did, struct p80211pstrd *pstr, hfa384x_t *priv); +void prism2mgmt_get_grpaddr(u32 did, struct p80211pstrd *pstr, + struct hfa384x *priv); int prism2mgmt_set_grpaddr(u32 did, u8 *prism2buf, struct p80211pstrd *pstr, - hfa384x_t *priv); + struct hfa384x *priv); int prism2mgmt_get_grpaddr_index(u32 did); void prism2sta_processing_defer(struct work_struct *data); diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c index 95bab45..63ab6bc8 100644 --- a/drivers/staging/wlan-ng/prism2mib.c +++ b/drivers/staging/wlan-ng/prism2mib.c @@ -88,61 +88,61 @@ struct mibrec { int (*func)(struct mibrec *mib, int isget, struct wlandevice *wlandev, - hfa384x_t *hw, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data); }; static int prism2mib_bytearea2pstr(struct mibrec *mib, int isget, struct wlandevice *wlandev, - hfa384x_t *hw, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data); static int prism2mib_uint32(struct mibrec *mib, int isget, struct wlandevice *wlandev, - hfa384x_t *hw, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data); static int prism2mib_flag(struct mibrec *mib, int isget, struct wlandevice *wlandev, - hfa384x_t *hw, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data); static int prism2mib_wepdefaultkey(struct mibrec *mib, int isget, struct wlandevice *wlandev, - hfa384x_t *hw, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data); static int prism2mib_privacyinvoked(struct mibrec *mib, int isget, struct wlandevice *wlandev, - hfa384x_t *hw, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data); static int prism2mib_excludeunencrypted(struct mibrec *mib, int isget, struct wlandevice *wlandev, - hfa384x_t *hw, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data); static int prism2mib_fragmentationthreshold(struct mibrec *mib, int isget, struct wlandevice *wlandev, - hfa384x_t *hw, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data); static int prism2mib_priv(struct mibrec *mib, int isget, struct wlandevice *wlandev, - hfa384x_t *hw, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data); static struct mibrec mibtab[] = { @@ -259,7 +259,7 @@ static struct mibrec mibtab[] = { int prism2mgmt_mibset_mibget(struct wlandevice *wlandev, void *msgp) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; int result, isget; struct mibrec *mib; @@ -374,7 +374,7 @@ done: static int prism2mib_bytearea2pstr(struct mibrec *mib, int isget, struct wlandevice *wlandev, - hfa384x_t *hw, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data) { @@ -424,7 +424,7 @@ static int prism2mib_bytearea2pstr(struct mibrec *mib, static int prism2mib_uint32(struct mibrec *mib, int isget, struct wlandevice *wlandev, - hfa384x_t *hw, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data) { int result; @@ -471,7 +471,7 @@ static int prism2mib_uint32(struct mibrec *mib, static int prism2mib_flag(struct mibrec *mib, int isget, struct wlandevice *wlandev, - hfa384x_t *hw, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data) { int result; @@ -528,7 +528,7 @@ static int prism2mib_flag(struct mibrec *mib, static int prism2mib_wepdefaultkey(struct mibrec *mib, int isget, struct wlandevice *wlandev, - hfa384x_t *hw, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data) { @@ -578,7 +578,7 @@ static int prism2mib_wepdefaultkey(struct mibrec *mib, static int prism2mib_privacyinvoked(struct mibrec *mib, int isget, struct wlandevice *wlandev, - hfa384x_t *hw, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data) { @@ -620,7 +620,7 @@ static int prism2mib_privacyinvoked(struct mibrec *mib, static int prism2mib_excludeunencrypted(struct mibrec *mib, int isget, struct wlandevice *wlandev, - hfa384x_t *hw, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data) { @@ -656,7 +656,7 @@ static int prism2mib_excludeunencrypted(struct mibrec *mib, static int prism2mib_fragmentationthreshold(struct mibrec *mib, int isget, struct wlandevice *wlandev, - hfa384x_t *hw, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data) { @@ -702,7 +702,7 @@ static int prism2mib_fragmentationthreshold(struct mibrec *mib, static int prism2mib_priv(struct mibrec *mib, int isget, struct wlandevice *wlandev, - hfa384x_t *hw, + struct hfa384x *hw, struct p80211msg_dot11req_mibset *msg, void *data) { struct p80211pstrd *pstr = data; diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index 59f4619..e1b4a94 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -243,7 +243,7 @@ static int prism2sta_txframe(struct wlandevice *wlandev, struct sk_buff *skb, union p80211_hdr *p80211_hdr, struct p80211_metawep *p80211_wep) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; /* If necessary, set the 802.11 WEP bit */ if ((wlandev->hostwep & (HOSTWEP_PRIVACYINVOKED | HOSTWEP_ENCRYPT)) == @@ -280,7 +280,7 @@ static int prism2sta_txframe(struct wlandevice *wlandev, struct sk_buff *skb, */ static int prism2sta_mlmerequest(struct wlandevice *wlandev, struct p80211msg *msg) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; int result = 0; @@ -410,7 +410,7 @@ static int prism2sta_mlmerequest(struct wlandevice *wlandev, struct p80211msg *m */ u32 prism2sta_ifstate(struct wlandevice *wlandev, u32 ifstate) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; u32 result; result = P80211ENUM_resultcode_implementation_failure; @@ -584,7 +584,7 @@ u32 prism2sta_ifstate(struct wlandevice *wlandev, u32 ifstate) static int prism2sta_getcardinfo(struct wlandevice *wlandev) { int result = 0; - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; u16 temp; u8 snum[HFA384x_RID_NICSERIALNUMBER_LEN]; @@ -912,7 +912,7 @@ done: */ static int prism2sta_globalsetup(struct wlandevice *wlandev) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; /* Set the maximum frame size */ return hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, @@ -923,7 +923,7 @@ static int prism2sta_setmulticast(struct wlandevice *wlandev, struct net_device *dev) { int result = 0; - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; u16 promisc; @@ -987,7 +987,7 @@ static void prism2sta_inf_handover(struct wlandevice *wlandev, static void prism2sta_inf_tallies(struct wlandevice *wlandev, struct hfa384x_InfFrame *inf) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; u16 *src16; u32 *dst; u32 *src32; @@ -1033,7 +1033,7 @@ static void prism2sta_inf_tallies(struct wlandevice *wlandev, static void prism2sta_inf_scanresults(struct wlandevice *wlandev, struct hfa384x_InfFrame *inf) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; int nbss; struct hfa384x_ScanResult *sr = &(inf->info.scanresult); int i; @@ -1088,7 +1088,7 @@ static void prism2sta_inf_scanresults(struct wlandevice *wlandev, static void prism2sta_inf_hostscanresults(struct wlandevice *wlandev, struct hfa384x_InfFrame *inf) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; int nbss; nbss = (inf->framelen - 3) / 32; @@ -1129,7 +1129,7 @@ static void prism2sta_inf_hostscanresults(struct wlandevice *wlandev, static void prism2sta_inf_chinforesults(struct wlandevice *wlandev, struct hfa384x_InfFrame *inf) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; unsigned int i, n; hw->channel_info.results.scanchannels = @@ -1171,7 +1171,7 @@ static void prism2sta_inf_chinforesults(struct wlandevice *wlandev, void prism2sta_processing_defer(struct work_struct *data) { - hfa384x_t *hw = container_of(data, struct hfa384x, link_bh); + struct hfa384x *hw = container_of(data, struct hfa384x, link_bh); struct wlandevice *wlandev = hw->wlandev; struct hfa384x_bytestr32 ssid; int result; @@ -1442,7 +1442,7 @@ void prism2sta_processing_defer(struct work_struct *data) static void prism2sta_inf_linkstatus(struct wlandevice *wlandev, struct hfa384x_InfFrame *inf) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; hw->link_status_new = le16_to_cpu(inf->info.linkstatus.linkstatus); @@ -1470,7 +1470,7 @@ static void prism2sta_inf_linkstatus(struct wlandevice *wlandev, static void prism2sta_inf_assocstatus(struct wlandevice *wlandev, struct hfa384x_InfFrame *inf) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; struct hfa384x_AssocStatus rec; int i; @@ -1531,7 +1531,7 @@ static void prism2sta_inf_assocstatus(struct wlandevice *wlandev, static void prism2sta_inf_authreq(struct wlandevice *wlandev, struct hfa384x_InfFrame *inf) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; struct sk_buff *skb; skb = dev_alloc_skb(sizeof(*inf)); @@ -1546,7 +1546,7 @@ static void prism2sta_inf_authreq(struct wlandevice *wlandev, static void prism2sta_inf_authreq_defer(struct wlandevice *wlandev, struct hfa384x_InfFrame *inf) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; struct hfa384x_authenticateStation_data rec; int i, added, result, cnt; @@ -1720,7 +1720,7 @@ static void prism2sta_inf_authreq_defer(struct wlandevice *wlandev, static void prism2sta_inf_psusercnt(struct wlandevice *wlandev, struct hfa384x_InfFrame *inf) { - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; hw->psusercount = le16_to_cpu(inf->info.psusercnt.usercnt); } @@ -1880,11 +1880,11 @@ void prism2sta_ev_alloc(struct wlandevice *wlandev) static struct wlandevice *create_wlan(void) { struct wlandevice *wlandev = NULL; - hfa384x_t *hw = NULL; + struct hfa384x *hw = NULL; /* Alloc our structures */ wlandev = kzalloc(sizeof(struct wlandevice), GFP_KERNEL); - hw = kzalloc(sizeof(hfa384x_t), GFP_KERNEL); + hw = kzalloc(sizeof(struct hfa384x), GFP_KERNEL); if (!wlandev || !hw) { kfree(wlandev); @@ -1914,7 +1914,7 @@ static struct wlandevice *create_wlan(void) void prism2sta_commsqual_defer(struct work_struct *data) { - hfa384x_t *hw = container_of(data, struct hfa384x, commsqual_bh); + struct hfa384x *hw = container_of(data, struct hfa384x, commsqual_bh); struct wlandevice *wlandev = hw->wlandev; struct hfa384x_bytestr32 ssid; struct p80211msg_dot11req_mibget msg; @@ -2003,7 +2003,7 @@ void prism2sta_commsqual_defer(struct work_struct *data) void prism2sta_commsqual_timer(unsigned long data) { - hfa384x_t *hw = (hfa384x_t *)data; + struct hfa384x *hw = (struct hfa384x *)data; schedule_work(&hw->commsqual_bh); } diff --git a/drivers/staging/wlan-ng/prism2usb.c b/drivers/staging/wlan-ng/prism2usb.c index 81831d3..bfb6b0a 100644 --- a/drivers/staging/wlan-ng/prism2usb.c +++ b/drivers/staging/wlan-ng/prism2usb.c @@ -62,7 +62,7 @@ static int prism2sta_probe_usb(struct usb_interface *interface, struct usb_device *dev; struct wlandevice *wlandev = NULL; - hfa384x_t *hw = NULL; + struct hfa384x *hw = NULL; int result = 0; dev = interface_to_usbdev(interface); @@ -142,7 +142,7 @@ static void prism2sta_disconnect_usb(struct usb_interface *interface) struct hfa384x_usbctlx *ctlx, *temp; unsigned long flags; - hfa384x_t *hw = wlandev->priv; + struct hfa384x *hw = wlandev->priv; if (!hw) goto exit; @@ -218,7 +218,7 @@ exit: static int prism2sta_suspend(struct usb_interface *interface, pm_message_t message) { - hfa384x_t *hw = NULL; + struct hfa384x *hw = NULL; struct wlandevice *wlandev; wlandev = (struct wlandevice *)usb_get_intfdata(interface); @@ -241,7 +241,7 @@ static int prism2sta_suspend(struct usb_interface *interface, static int prism2sta_resume(struct usb_interface *interface) { int result = 0; - hfa384x_t *hw = NULL; + struct hfa384x *hw = NULL; struct wlandevice *wlandev; wlandev = (struct wlandevice *)usb_get_intfdata(interface); -- cgit v0.10.2 From 5f7688dd41e3d98b18792a961662387857dcd68e Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos <sergio.paracuellos@gmail.com> Date: Wed, 28 Sep 2016 20:20:20 +0200 Subject: staging: wlang-ng: Fix block comments style warnings in hfa384x.h This patch fixes the following checkpatch.pl warning in hfa384x.h: WARNING: Block comments use * on subsequent lines No more warnings block comments warnings for this file. Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 06a5778..43c299c 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1,57 +1,57 @@ /* hfa384x.h -* -* Defines the constants and data structures for the hfa384x -* -* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. -* -------------------------------------------------------------------- -* -* linux-wlan -* -* The contents of this file are subject to the Mozilla Public -* License Version 1.1 (the "License"); you may not use this file -* except in compliance with the License. You may obtain a copy of -* the License at http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS -* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -* implied. See the License for the specific language governing -* rights and limitations under the License. -* -* Alternatively, the contents of this file may be used under the -* terms of the GNU Public License version 2 (the "GPL"), in which -* case the provisions of the GPL are applicable instead of the -* above. If you wish to allow the use of your version of this file -* only under the terms of the GPL and not to allow others to use -* your version of this file under the MPL, indicate your decision -* by deleting the provisions above and replace them with the notice -* and other provisions required by the GPL. If you do not delete -* the provisions above, a recipient may use your version of this -* file under either the MPL or the GPL. -* -* -------------------------------------------------------------------- -* -* Inquiries regarding the linux-wlan Open Source project can be -* made directly to: -* -* AbsoluteValue Systems Inc. -* info@linux-wlan.com -* http://www.linux-wlan.com -* -* -------------------------------------------------------------------- -* -* Portions of the development of this software were funded by -* Intersil Corporation as part of PRISM(R) chipset product development. -* -* -------------------------------------------------------------------- -* -* [Implementation and usage notes] -* -* [References] -* CW10 Programmer's Manual v1.5 -* IEEE 802.11 D10.0 -* -* -------------------------------------------------------------------- -*/ + * + * Defines the constants and data structures for the hfa384x + * + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. + * -------------------------------------------------------------------- + * + * linux-wlan + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU Public License version 2 (the "GPL"), in which + * case the provisions of the GPL are applicable instead of the + * above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use + * your version of this file under the MPL, indicate your decision + * by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete + * the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * -------------------------------------------------------------------- + * + * Inquiries regarding the linux-wlan Open Source project can be + * made directly to: + * + * AbsoluteValue Systems Inc. + * info@linux-wlan.com + * http://www.linux-wlan.com + * + * -------------------------------------------------------------------- + * + * Portions of the development of this software were funded by + * Intersil Corporation as part of PRISM(R) chipset product development. + * + * -------------------------------------------------------------------- + * + * [Implementation and usage notes] + * + * [References] + * CW10 Programmer's Manual v1.5 + * IEEE 802.11 D10.0 + * + * -------------------------------------------------------------------- + */ #ifndef _HFA384x_H #define _HFA384x_H @@ -1340,17 +1340,17 @@ struct hfa384x { struct hfa384x_caplevel cap_sup_ap; /* Actor compatibility ranges */ - struct hfa384x_caplevel cap_act_pri_cfi; /* - * pri f/w to controller - * interface - */ + struct hfa384x_caplevel cap_act_pri_cfi; /* + * pri f/w to controller + * interface + */ - struct hfa384x_caplevel cap_act_sta_cfi; /* - * sta f/w to controller - * interface - */ + struct hfa384x_caplevel cap_act_sta_cfi; /* + * sta f/w to controller + * interface + */ - struct hfa384x_caplevel cap_act_sta_mfi; /* sta f/w to modem interface */ + struct hfa384x_caplevel cap_act_sta_mfi; /* sta f/w to modem interface */ struct hfa384x_caplevel cap_act_ap_cfi; /* * ap f/w to controller -- cgit v0.10.2 From c4610f6e1db2dd04119bcef80ab9dc12bff62117 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal <bhumirks@gmail.com> Date: Thu, 29 Sep 2016 20:52:00 +0530 Subject: Staging: speakup: constify attribute_group structures Check for attribute_group structures that are only passed as a second argument to the functions sysfs_remove_group and sysfs_create_group. As these arguments are constant so, attribute_group structures having this property can also be made constant. Done using coccinelle: @r1 disable optional_qualifier @ identifier i; position p; @@ static struct attribute_group i@p = {...}; @ok1@ identifier r1.i; position p; expression e1; @@ ( sysfs_remove_group(e1,&i@p) | sysfs_create_group(e1,&i@p) ) @bad@ position p!={r1.p,ok1.p}; identifier r1.i; @@ i@p @depends on !bad disable optional_qualifier@ identifier r1.i; @@ static +const struct attribute_group i={...}; @depends on !bad disable optional_qualifier@ identifier r1.i; @@ +const struct attribute_group i; File size before: text data bss dec hex filename 7551 1440 16 9007 232f drivers/staging/speakup/kobjects.o File size after: text data bss dec hex filename 7671 1312 16 8999 2327 drivers/staging/speakup/kobjects.o Signed-off-by: Bhumika Goyal <bhumirks@gmail.com> Acked-by: Samuel Thibault <samuel.thibault@ens-lyon.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/speakup/kobjects.c b/drivers/staging/speakup/kobjects.c index 4a78d37..e744aa9 100644 --- a/drivers/staging/speakup/kobjects.c +++ b/drivers/staging/speakup/kobjects.c @@ -976,11 +976,11 @@ static struct attribute *i18n_attrs[] = { * created for the attributes with the directory being the name of the * attribute group. */ -static struct attribute_group main_attr_group = { +static const struct attribute_group main_attr_group = { .attrs = main_attrs, }; -static struct attribute_group i18n_attr_group = { +static const struct attribute_group i18n_attr_group = { .attrs = i18n_attrs, .name = "i18n", }; -- cgit v0.10.2 From 6d81bf25506a70f4e66826d5cb35f1ca07147499 Mon Sep 17 00:00:00 2001 From: Namrata A Shettar <namrataashettar@gmail.com> Date: Thu, 29 Sep 2016 22:05:31 +0530 Subject: staging: rts5208: Add space around binary operators Add space around binary operators to resolve checkpatch issue. Signed-off-by: Namrata A Shettar <namrataashettar@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rts5208/rtsx_scsi.c b/drivers/staging/rts5208/rtsx_scsi.c index def53d9..d11b173 100644 --- a/drivers/staging/rts5208/rtsx_scsi.c +++ b/drivers/staging/rts5208/rtsx_scsi.c @@ -484,14 +484,14 @@ static int inquiry(struct scsi_cmnd *srb, struct rtsx_chip *chip) u8 card = get_lun_card(chip, lun); bool pro_formatter_flag = false; unsigned char inquiry_buf[] = { - QULIFIRE|DRCT_ACCESS_DEV, - RMB_DISC|0x0D, + QULIFIRE | DRCT_ACCESS_DEV, + RMB_DISC | 0x0D, 0x00, 0x01, 0x1f, 0x02, 0, - REL_ADR|WBUS_32|WBUS_16|SYNC|LINKED|CMD_QUE|SFT_RE, + REL_ADR | WBUS_32 | WBUS_16 | SYNC | LINKED | CMD_QUE | SFT_RE, }; if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) { @@ -1986,8 +1986,8 @@ static int read_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip) return TRANSPORT_FAILED; } - buf[2*i] = (u8)(val >> 8); - buf[2*i+1] = (u8)val; + buf[2 * i] = (u8)(val >> 8); + buf[2 * i + 1] = (u8)val; } len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), @@ -2045,7 +2045,7 @@ static int write_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip) } for (i = 0; i < len / 2; i++) { - val = ((u16)buf[2*i] << 8) | buf[2*i+1]; + val = ((u16)buf[2 * i] << 8) | buf[2 * i + 1]; retval = rtsx_write_phy_register(chip, addr + i, val); if (retval != STATUS_SUCCESS) { vfree(buf); @@ -3067,18 +3067,18 @@ static int get_ms_information(struct scsi_cmnd *srb, struct rtsx_chip *chip) buf[i++] = 0x80; if ((dev_info_id == 0x10) || (dev_info_id == 0x13)) { /* System Information */ - memcpy(buf+i, ms_card->raw_sys_info, 96); + memcpy(buf + i, ms_card->raw_sys_info, 96); } else { /* Model Name */ - memcpy(buf+i, ms_card->raw_model_name, 48); + memcpy(buf + i, ms_card->raw_model_name, 48); } rtsx_stor_set_xfer_buf(buf, buf_len, srb); if (dev_info_id == 0x15) - scsi_set_resid(srb, scsi_bufflen(srb)-0x3C); + scsi_set_resid(srb, scsi_bufflen(srb) - 0x3C); else - scsi_set_resid(srb, scsi_bufflen(srb)-0x6C); + scsi_set_resid(srb, scsi_bufflen(srb) - 0x6C); kfree(buf); return STATUS_SUCCESS; -- cgit v0.10.2 From 6c5d28f523665a38672b27f603bef43bf21560ea Mon Sep 17 00:00:00 2001 From: Namrata A Shettar <namrataashettar@gmail.com> Date: Thu, 29 Sep 2016 22:07:39 +0530 Subject: staging: rts5208: Replace explicit NULL comparison Replace explicit NULL comparison to resolve checkpatch issues. Signed-off-by: Namrata A Shettar <namrataashettar@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rts5208/rtsx_scsi.c b/drivers/staging/rts5208/rtsx_scsi.c index d11b173..becb4bb 100644 --- a/drivers/staging/rts5208/rtsx_scsi.c +++ b/drivers/staging/rts5208/rtsx_scsi.c @@ -1397,7 +1397,7 @@ static int trace_msg_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip) buf_len = 4 + ((2 + MSG_FUNC_LEN + MSG_FILE_LEN + TIME_VAL_LEN) * TRACE_ITEM_CNT); - if ((scsi_bufflen(srb) < buf_len) || (scsi_sglist(srb) == NULL)) { + if ((scsi_bufflen(srb) < buf_len) || !scsi_sglist(srb)) { set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); rtsx_trace(chip); -- cgit v0.10.2 From 259334ed303b40630c4248944a04145918fc0ac3 Mon Sep 17 00:00:00 2001 From: Wayne Porter <wporter82@gmail.com> Date: Fri, 30 Sep 2016 19:06:37 +0000 Subject: Staging: rts5208: Fix indentation warnings Fix code indentation warnings detected by checkpatch.pl Signed-off-by: Wayne Porter <wporter82@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c index 9fc64da..f27df0b 100644 --- a/drivers/staging/rts5208/ms.c +++ b/drivers/staging/rts5208/ms.c @@ -63,12 +63,12 @@ static int ms_transfer_tpc(struct rtsx_chip *chip, u8 trans_mode, rtsx_add_cmd(chip, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt); rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, - 0x01, PINGPONG_BUFFER); + 0x01, PINGPONG_BUFFER); rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, - 0xFF, MS_TRANSFER_START | trans_mode); + 0xFF, MS_TRANSFER_START | trans_mode); rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, - MS_TRANSFER_END, MS_TRANSFER_END); + MS_TRANSFER_END, MS_TRANSFER_END); rtsx_add_cmd(chip, READ_REG_CMD, MS_TRANS_CFG, 0, 0); @@ -109,8 +109,8 @@ static int ms_transfer_tpc(struct rtsx_chip *chip, u8 trans_mode, } static int ms_transfer_data(struct rtsx_chip *chip, u8 trans_mode, - u8 tpc, u16 sec_cnt, u8 cfg, bool mode_2k, - int use_sg, void *buf, int buf_len) + u8 tpc, u16 sec_cnt, u8 cfg, bool mode_2k, + int use_sg, void *buf, int buf_len) { int retval; u8 val, err_code = 0; @@ -206,7 +206,7 @@ static int ms_write_bytes(struct rtsx_chip *chip, rtsx_add_cmd(chip, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt); rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, - 0x01, PINGPONG_BUFFER); + 0x01, PINGPONG_BUFFER); rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, MS_TRANSFER_START | MS_TM_WRITE_BYTES); @@ -253,7 +253,7 @@ static int ms_write_bytes(struct rtsx_chip *chip, } static int ms_read_bytes(struct rtsx_chip *chip, - u8 tpc, u8 cnt, u8 cfg, u8 *data, int data_len) + u8 tpc, u8 cnt, u8 cfg, u8 *data, int data_len) { struct ms_info *ms_card = &chip->ms_card; int retval, i; @@ -270,12 +270,12 @@ static int ms_read_bytes(struct rtsx_chip *chip, rtsx_add_cmd(chip, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt); rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg); rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, - 0x01, PINGPONG_BUFFER); + 0x01, PINGPONG_BUFFER); rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, - MS_TRANSFER_START | MS_TM_READ_BYTES); + MS_TRANSFER_START | MS_TM_READ_BYTES); rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, - MS_TRANSFER_END, MS_TRANSFER_END); + MS_TRANSFER_END, MS_TRANSFER_END); for (i = 0; i < data_len - 1; i++) rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + i, 0, 0); @@ -284,7 +284,7 @@ static int ms_read_bytes(struct rtsx_chip *chip, rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + data_len, 0, 0); else rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + data_len - 1, - 0, 0); + 0, 0); retval = rtsx_send_cmd(chip, MS_CARD, 5000); if (retval < 0) { @@ -334,8 +334,8 @@ static int ms_read_bytes(struct rtsx_chip *chip, return STATUS_SUCCESS; } -static int ms_set_rw_reg_addr(struct rtsx_chip *chip, - u8 read_start, u8 read_cnt, u8 write_start, u8 write_cnt) +static int ms_set_rw_reg_addr(struct rtsx_chip *chip, u8 read_start, + u8 read_cnt, u8 write_start, u8 write_cnt) { int retval, i; u8 data[4]; -- cgit v0.10.2 From 52b4f6e081ba20adac694f5e445be2dcb469d3a1 Mon Sep 17 00:00:00 2001 From: Carlos Palminha <CARLOS.PALMINHA@synopsys.com> Date: Thu, 29 Sep 2016 13:03:30 +0100 Subject: staging: fbtft: fix NULL comparison checkpatch warning Fixed the following checkpatch warnings (task #10 of eudyptula challenge): - NULL comparison rewritten to use '!' operator Signed-off-by: Carlos Palminha <palminha@synopsys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fbtft/fbtft_device.c b/drivers/staging/fbtft/fbtft_device.c index e9f25dd..e921183 100644 --- a/drivers/staging/fbtft/fbtft_device.c +++ b/drivers/staging/fbtft/fbtft_device.c @@ -1418,14 +1418,14 @@ static int __init fbtft_device_init(void) /* parse module parameter: gpios */ while ((p_gpio = strsep(&gpios, ","))) { - if (strchr(p_gpio, ':') == NULL) { + if (!strchr(p_gpio, ':')) { pr_err("error: missing ':' in gpios parameter: %s\n", p_gpio); return -EINVAL; } p_num = p_gpio; p_name = strsep(&p_num, ":"); - if (p_name == NULL || p_num == NULL) { + if (!p_name || !p_num) { pr_err("something bad happened parsing gpios parameter: %s\n", p_gpio); return -EINVAL; -- cgit v0.10.2 From 0ca8df12e78f3085224faac9058a2d278992dd82 Mon Sep 17 00:00:00 2001 From: Namrata A Shettar <namrataashettar@gmail.com> Date: Fri, 30 Sep 2016 19:14:36 +0530 Subject: staging: wilc1000: wilc_wlan: Compress return logic Compress return logic. Done using Coccinelle : @@ local idexpression ret; expression e; @@ -ret= +return e; -return ret; Signed-off-by: Namrata A Shettar <namrataashettar@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 2b307ce..58843f7 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1033,8 +1033,7 @@ int wilc_wlan_start(struct wilc *wilc) ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_1, reg); if (!ret) { release_bus(wilc, RELEASE_ONLY); - ret = -EIO; - return ret; + return -EIO; } wilc->hif_func->hif_sync_ext(wilc, NUM_INT_EXT); @@ -1042,8 +1041,7 @@ int wilc_wlan_start(struct wilc *wilc) ret = wilc->hif_func->hif_read_reg(wilc, 0x1000, &chipid); if (!ret) { release_bus(wilc, RELEASE_ONLY); - ret = -EIO; - return ret; + return -EIO; } wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, ®); -- cgit v0.10.2 From 8244d269098348f9bcfbcfed5c443857b4c8ffc7 Mon Sep 17 00:00:00 2001 From: Namrata A Shettar <namrataashettar@gmail.com> Date: Fri, 30 Sep 2016 19:14:54 +0530 Subject: staging: wilc1000: wilc_spi: Compress return logic Compress return logic. Done using Coccinelle : @@ local idexpression ret; expression e; @@ -ret= +return e; -return ret; Signed-off-by: Namrata A Shettar <namrataashettar@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wilc1000/wilc_spi.c b/drivers/staging/wilc1000/wilc_spi.c index f6c47ca..d865fb1 100644 --- a/drivers/staging/wilc1000/wilc_spi.c +++ b/drivers/staging/wilc1000/wilc_spi.c @@ -419,8 +419,7 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, if (wilc_spi_tx_rx(wilc, wb, rb, len2)) { dev_err(&spi->dev, "Failed cmd write, bus error...\n"); - result = N_FAIL; - return result; + return N_FAIL; } /** @@ -441,8 +440,7 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, dev_err(&spi->dev, "Failed cmd response, cmd (%02x), resp (%02x)\n", cmd, rsp); - result = N_FAIL; - return result; + return N_FAIL; } /** @@ -452,8 +450,7 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, if (rsp != 0x00) { dev_err(&spi->dev, "Failed cmd state response state (%02x)\n", rsp); - result = N_FAIL; - return result; + return N_FAIL; } if ((cmd == CMD_INTERNAL_READ) || (cmd == CMD_SINGLE_READ) @@ -480,8 +477,7 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, if (retry <= 0) { dev_err(&spi->dev, "Error, data read response (%02x)\n", rsp); - result = N_RESET; - return result; + return N_RESET; } if ((cmd == CMD_INTERNAL_READ) || (cmd == CMD_SINGLE_READ)) { @@ -496,8 +492,7 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, } else { dev_err(&spi->dev, "buffer overrun when reading data.\n"); - result = N_FAIL; - return result; + return N_FAIL; } if (!g_spi.crc_off) { @@ -509,8 +504,7 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, crc[1] = rb[rix++]; } else { dev_err(&spi->dev, "buffer overrun when reading crc.\n"); - result = N_FAIL; - return result; + return N_FAIL; } } } else if ((cmd == CMD_DMA_READ) || (cmd == CMD_DMA_EXT_READ)) { -- cgit v0.10.2 From 8d3496c39357bc4b16e6ede0b71126bf1f2a34bc Mon Sep 17 00:00:00 2001 From: Namrata A Shettar <namrataashettar@gmail.com> Date: Fri, 30 Sep 2016 19:15:05 +0530 Subject: staging: wilc1000: wilc_spi: Remove unnecessary blank lines Remove unnecessary blank lines to resolve checkpatch issue. Signed-off-by: Namrata A Shettar <namrataashettar@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wilc1000/wilc_spi.c b/drivers/staging/wilc1000/wilc_spi.c index d865fb1..f08cf6d 100644 --- a/drivers/staging/wilc1000/wilc_spi.c +++ b/drivers/staging/wilc1000/wilc_spi.c @@ -544,7 +544,6 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, } } - ix += nbytes; sz -= nbytes; } @@ -580,7 +579,6 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, if (result == N_FAIL) break; - /** * Read bytes **/ @@ -680,7 +678,6 @@ static int spi_data_write(struct wilc *wilc, u8 *b, u32 sz) sz -= nbytes; } while (sz); - return result; } @@ -843,7 +840,6 @@ static int wilc_spi_init(struct wilc *wilc, bool resume) static int isinit; if (isinit) { - if (!wilc_spi_read_reg(wilc, 0x1000, &chipid)) { dev_err(&spi->dev, "Fail cmd read chip id...\n"); return 0; @@ -883,7 +879,6 @@ static int wilc_spi_init(struct wilc *wilc, bool resume) g_spi.crc_off = 1; } - /** * make sure can read back chip id correctly **/ @@ -924,14 +919,10 @@ static int wilc_spi_read_size(struct wilc *wilc, u32 *size) *size = tmp; } - - _fail_: return ret; } - - static int wilc_spi_read_int(struct wilc *wilc, u32 *int_status) { struct spi_device *spi = to_spi_device(wilc->dev); @@ -986,7 +977,6 @@ static int wilc_spi_read_int(struct wilc *wilc, u32 *int_status) } *int_status = tmp; - } _fail_: -- cgit v0.10.2 From 4ee4b9da2b01421521f6ee434e7d6098aecedbdf Mon Sep 17 00:00:00 2001 From: Elizabeth Ferdman <gnudevliz@gmail.com> Date: Fri, 30 Sep 2016 12:15:09 -0700 Subject: staging: wilc1000: remove unnecessary braces Fix checkpatch warning "braces {} are not necessary for single statement blocks" to conform to linux kernel coding style. Signed-off-by: Elizabeth Ferdman <gnudevliz@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 58843f7..bc5ad20 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -621,9 +621,9 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) if (!ret) break; - if ((reg & 0x1) == 0) { + if ((reg & 0x1) == 0) break; - } + counter++; if (counter > 200) { counter = 0; -- cgit v0.10.2 From d983c597757883496a9e4956e308395f8ac53bf0 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal <bhumirks@gmail.com> Date: Thu, 29 Sep 2016 20:28:31 +0530 Subject: Staging: most: hdm-dim2: constify attribute_group structures Check for attribute_group structures that are only passed as a second argument to the functions sysfs_remove_group and sysfs_create_group. As these arguments are constant so, attribute_group structures having this property can also be made constant. Done using coccinelle: @r1 disable optional_qualifier @ identifier i; position p; @@ static struct attribute_group i@p = {...}; @ok1@ identifier r1.i; position p; expression e1,e2; @@ ( sysfs_remove_group(e1,&i@p) | sysfs_create_group(e1,&i@p) ) @bad@ position p!={r1.p,ok1.p}; identifier r1.i; @@ i@p @depends on !bad disable optional_qualifier@ identifier r1.i; @@ static +const struct attribute_group i={...}; @depends on !bad disable optional_qualifier@ identifier r1.i; @@ +const struct attribute_group i; File size before: text data bss dec hex filename 509 160 0 669 29d drivers/staging/most/hdm-dim2/dim2_sysfs.o File size after: text data bss dec hex filename 565 96 0 661 295 drivers/staging/most/hdm-dim2/dim2_sysfs.o Signed-off-by: Bhumika Goyal <bhumirks@gmail.com> Acked-by: Julia Lawall <julia.lawall@lip6.fr> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/most/hdm-dim2/dim2_sysfs.c b/drivers/staging/most/hdm-dim2/dim2_sysfs.c index 2b28e4a..d8b22f9 100644 --- a/drivers/staging/most/hdm-dim2/dim2_sysfs.c +++ b/drivers/staging/most/hdm-dim2/dim2_sysfs.c @@ -39,7 +39,7 @@ static struct attribute *bus_default_attrs[] = { NULL, }; -static struct attribute_group bus_attr_group = { +static const struct attribute_group bus_attr_group = { .attrs = bus_default_attrs, }; -- cgit v0.10.2 From 7b346dac731361d45ef173f66df3a6509fd3b865 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal <bhumirks@gmail.com> Date: Thu, 29 Sep 2016 20:18:54 +0530 Subject: Staging: dgnc: constify attribute_group structures Check for attribute_group structures that are only passed as a second argument to the functions sysfs_remove_group and sysfs_create_group. As these arguments are constant so, attribute_group structures having this property can also be made constant. Done using coccinelle: @r1 disable optional_qualifier @ identifier i; position p; @@ static struct attribute_group i@p = {...}; @ok1@ identifier r1.i; position p; expression e1; @@ ( sysfs_remove_group(e1,&i@p) | sysfs_create_group(e1,&i@p) ) @bad@ position p!={r1.p,ok1.p}; identifier r1.i; @@ i@p @depends on !bad disable optional_qualifier@ identifier r1.i; @@ static +const struct attribute_group i={...}; @depends on !bad disable optional_qualifier@ identifier r1.i; @@ +const struct attribute_group i; File size before: text data bss dec hex filename 6248 1024 0 7272 1c68 drivers/staging/dgnc/dgnc_sysfs.o File size after: text data bss dec hex filename 6288 960 0 7248 1c50 drivers/staging/dgnc/dgnc_sysfs.o Signed-off-by: Bhumika Goyal <bhumirks@gmail.com> Acked-by: Julia Lawall <julia.lawall@lip6.fr> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_sysfs.c b/drivers/staging/dgnc/dgnc_sysfs.c index a83e0e4..290bf6e 100644 --- a/drivers/staging/dgnc/dgnc_sysfs.c +++ b/drivers/staging/dgnc/dgnc_sysfs.c @@ -677,7 +677,7 @@ static struct attribute *dgnc_sysfs_tty_entries[] = { NULL }; -static struct attribute_group dgnc_tty_attribute_group = { +static const struct attribute_group dgnc_tty_attribute_group = { .name = NULL, .attrs = dgnc_sysfs_tty_entries, }; -- cgit v0.10.2 From 777c5e94c163e07ad8676ac37cc8e20301f63f80 Mon Sep 17 00:00:00 2001 From: Fernando Apesteguia <fernando.apesteguia@gmail.com> Date: Wed, 28 Sep 2016 19:20:39 +0200 Subject: staging: dgnc: Fix lines longer than 80 characters All the chunks of the patch apply to comments save the first one. Signed-off-by: Fernando Apesteguia <fernando.apesteguia@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/dgnc/dgnc_neo.c b/drivers/staging/dgnc/dgnc_neo.c index e794056..5becb37 100644 --- a/drivers/staging/dgnc/dgnc_neo.c +++ b/drivers/staging/dgnc/dgnc_neo.c @@ -449,7 +449,8 @@ static inline void neo_parse_isr(struct dgnc_board *brd, uint port) flags); } } else if (cause == UART_17158_XOFF_DETECT) { - if (!(brd->channels[port]->ch_flags & CH_STOP)) { + if (!(brd->channels[port]->ch_flags & + CH_STOP)) { spin_lock_irqsave(&ch->ch_lock, flags); ch->ch_flags |= CH_STOP; @@ -554,7 +555,8 @@ static inline void neo_parse_lsr(struct dgnc_board *brd, uint port) * Rx Oruns. Exar says that an orun will NOT corrupt * the FIFO. It will just replace the holding register * with this new data byte. So basically just ignore this. - * Probably we should eventually have an orun stat in our driver... + * Probably we should eventually have an orun stat in our + * driver... */ ch->ch_err_overrun++; } @@ -949,14 +951,18 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) /* * If 0, no interrupts pending. - * This can happen if the IRQ is shared among a couple Neo/Classic boards. + * This can happen if the IRQ is shared among a couple Neo/Classic + * boards. */ if (!uart_poll) { spin_unlock_irqrestore(&brd->bd_intr_lock, flags); return IRQ_NONE; } - /* At this point, we have at least SOMETHING to service, dig further... */ + /* + * At this point, we have at least SOMETHING to service, dig + * further... + */ /* Loop on each port */ while ((uart_poll & 0xff) != 0) { @@ -980,7 +986,10 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) ch = brd->channels[port]; neo_copy_data_from_uart_to_queue(ch); - /* Call our tty layer to enforce queue flow control if needed. */ + /* + * Call our tty layer to enforce queue flow control if + * needed. + */ spin_lock_irqsave(&ch->ch_lock, flags2); dgnc_check_queue_flow_control(ch); spin_unlock_irqrestore(&ch->ch_lock, flags2); @@ -996,16 +1005,18 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) case UART_17158_TXRDY: /* - * TXRDY interrupt clears after reading ISR register for the UART channel. + * TXRDY interrupt clears after reading ISR register + * for the UART channel. */ /* * Yes, this is odd... * Why would I check EVERY possibility of type of * interrupt, when we know its TXRDY??? - * Becuz for some reason, even tho we got triggered for TXRDY, - * it seems to be occasionally wrong. Instead of TX, which - * it should be, I was getting things like RXDY too. Weird. + * Becuz for some reason, even tho we got triggered for + * TXRDY, it seems to be occasionally wrong. Instead of + * TX, which it should be, I was getting things like + * RXDY too. Weird. */ neo_parse_isr(brd, port); break; @@ -1020,8 +1031,8 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) default: /* * The UART triggered us with a bogus interrupt type. - * It appears the Exar chip, when REALLY bogged down, will throw - * these once and awhile. + * It appears the Exar chip, when REALLY bogged down, + * will throw these once and awhile. * Its harmless, just ignore it and move on. */ break; @@ -1239,7 +1250,8 @@ static void neo_copy_data_from_uart_to_queue(struct channel_t *ch) } /* - * If our queue is full, we have no choice but to drop some data. + * If our queue is full, we have no choice but to drop some + * data. * The assumption is that HWFLOW or SWFLOW should have stopped * things way way before we got to this point. * @@ -1332,7 +1344,10 @@ static void neo_flush_uart_write(struct channel_t *ch) neo_pci_posting_flush(ch->ch_bd); for (i = 0; i < 10; i++) { - /* Check to see if the UART feels it completely flushed the FIFO. */ + /* + * Check to see if the UART feels it completely flushed the + * FIFO. + */ tmp = readb(&ch->ch_neo_uart->isr_fcr); if (tmp & 4) udelay(10); @@ -1361,7 +1376,10 @@ static void neo_flush_uart_read(struct channel_t *ch) neo_pci_posting_flush(ch->ch_bd); for (i = 0; i < 10; i++) { - /* Check to see if the UART feels it completely flushed the FIFO. */ + /* + * Check to see if the UART feels it completely flushed the + * FIFO. + */ tmp = readb(&ch->ch_neo_uart->isr_fcr); if (tmp & 2) udelay(10); @@ -1406,8 +1424,9 @@ static void neo_copy_data_from_queue_to_uart(struct channel_t *ch) ch->ch_cached_lsr &= ~(UART_LSR_THRE); /* - * If RTS Toggle mode is on, turn on RTS now if not already set, - * and make sure we get an event when the data transfer has completed. + * If RTS Toggle mode is on, turn on RTS now if not + * already set, and make sure we get an event when the + * data transfer has completed. */ if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) { if (!(ch->ch_mostat & UART_MCR_RTS)) { @@ -1417,8 +1436,9 @@ static void neo_copy_data_from_queue_to_uart(struct channel_t *ch) ch->ch_tun.un_flags |= (UN_EMPTY); } /* - * If DTR Toggle mode is on, turn on DTR now if not already set, - * and make sure we get an event when the data transfer has completed. + * If DTR Toggle mode is on, turn on DTR now if not + * already set, and make sure we get an event when the + * data transfer has completed. */ if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) { if (!(ch->ch_mostat & UART_MCR_DTR)) { @@ -1474,7 +1494,8 @@ static void neo_copy_data_from_queue_to_uart(struct channel_t *ch) /* * If RTS Toggle mode is on, turn on RTS now if not already set, - * and make sure we get an event when the data transfer has completed. + * and make sure we get an event when the data transfer has + * completed. */ if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) { if (!(ch->ch_mostat & UART_MCR_RTS)) { @@ -1486,7 +1507,8 @@ static void neo_copy_data_from_queue_to_uart(struct channel_t *ch) /* * If DTR Toggle mode is on, turn on DTR now if not already set, - * and make sure we get an event when the data transfer has completed. + * and make sure we get an event when the data transfer has + * completed. */ if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) { if (!(ch->ch_mostat & UART_MCR_DTR)) { @@ -1550,7 +1572,10 @@ static void neo_parse_modem(struct channel_t *ch, unsigned char signals) } } - /* Scrub off lower bits. They signify delta's, which I don't care about */ + /* + * Scrub off lower bits. They signify delta's, which I don't care + * about + */ msignals &= 0xf0; if (msignals & UART_MSR_DCD) -- cgit v0.10.2 From 7d7be350073e5a27ff5ed73b3dc31e1d2cb7d573 Mon Sep 17 00:00:00 2001 From: Georgiana Rodica Chelu <georgiana.chelu93@gmail.com> Date: Wed, 28 Sep 2016 23:33:02 +0300 Subject: staging: rtl8188eu: core: rtw_xmit: Move constant of the right side Constants should be on the right side of comparisons. Issue found by checkpatch.pl script. Signed-off-by: Georgiana Rodica Chelu <georgiana.chelu93@gmail.com> Acked-by: Julia Lawall <julia.lawall@lip6.fr> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c index 1d2817b..1392899 100644 --- a/drivers/staging/rtl8188eu/core/rtw_xmit.c +++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c @@ -451,14 +451,14 @@ 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 */ u8 tmp[24]; _rtw_pktfile_read(&pktfile, &tmp[0], 24); 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 */ @@ -469,7 +469,7 @@ static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct p } } } - } else if (0x888e == pattrib->ether_type) { + } else if (pattrib->ether_type == 0x888e) { DBG_88E_LEVEL(_drv_info_, "send eapol packet\n"); } -- cgit v0.10.2 From 7b170bacbb13089ccb1d14ca18ad4fb5dcb8b72e Mon Sep 17 00:00:00 2001 From: Georgiana Rodica Chelu <georgiana.chelu93@gmail.com> Date: Thu, 29 Sep 2016 00:07:15 +0300 Subject: staging: rtl8188eu: core: rtw_xmit: Use macros instead of constants Replace the 0x888e with ETH_P_PAE and 0x0806 with ETH_P_ARP. These macros can be found in drivers/staging/rtl8192e/rtllib.h Hexadecimal numbers are not case sensitive, therefore 0x888e is equal with 0x888E. The modifications improve the readability of the code. Signed-off-by: Georgiana Rodica Chelu <georgiana.chelu93@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c index 1392899..0f8b8e0 100644 --- a/drivers/staging/rtl8188eu/core/rtw_xmit.c +++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c @@ -402,7 +402,7 @@ static void set_qos(struct pkt_file *ppktfile, struct pkt_attrib *pattrib) _rtw_pktfile_read(ppktfile, (u8 *)&ip_hdr, sizeof(ip_hdr)); /* user_prio = (ntohs(ip_hdr.tos) >> 5) & 0x3; */ user_prio = ip_hdr.tos >> 5; - } else if (pattrib->ether_type == 0x888e) { + } else if (pattrib->ether_type == ETH_P_PAE) { /* "When priority processing of data frames is supported, */ /* a STA's SME should send EAPOL-Key frames at the highest priority." */ user_prio = 7; @@ -469,15 +469,15 @@ static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct p } } } - } else if (pattrib->ether_type == 0x888e) { + } else if (pattrib->ether_type == ETH_P_PAE) { DBG_88E_LEVEL(_drv_info_, "send eapol packet\n"); } - if ((pattrib->ether_type == 0x888e) || (pattrib->dhcp_pkt == 1)) + if ((pattrib->ether_type == ETH_P_PAE) || (pattrib->dhcp_pkt == 1)) rtw_set_scan_deny(padapter, 3000); /* If EAPOL , ARP , OR DHCP packet, driver must be in active mode. */ - if ((pattrib->ether_type == 0x0806) || (pattrib->ether_type == 0x888e) || (pattrib->dhcp_pkt == 1)) + if ((pattrib->ether_type == ETH_P_ARP) || (pattrib->ether_type == ETH_P_PAE) || (pattrib->dhcp_pkt == 1)) rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SPECIAL_PACKET, 1); bmcast = IS_MCAST(pattrib->ra); @@ -531,8 +531,8 @@ static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct p pattrib->encrypt = 0; - if ((pattrib->ether_type != 0x888e) && !check_fwstate(pmlmepriv, WIFI_MP_STATE)) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("\npsta->ieee8021x_blocked == true, pattrib->ether_type(%.4x) != 0x888e\n", pattrib->ether_type)); + if ((pattrib->ether_type != ETH_P_PAE) && !check_fwstate(pmlmepriv, WIFI_MP_STATE)) { + 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; } diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h index 38247fa..b895a53 100644 --- a/drivers/staging/rtl8192e/rtllib.h +++ b/drivers/staging/rtl8192e/rtllib.h @@ -521,7 +521,7 @@ enum wireless_mode { }; #ifndef ETH_P_PAE -#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ +#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ #define ETH_P_IP 0x0800 /* Internet Protocol packet */ #define ETH_P_ARP 0x0806 /* Address Resolution packet */ #endif /* ETH_P_PAE */ -- cgit v0.10.2 From 4d932504b534584e116b400dd6e7b8ce7deb455c Mon Sep 17 00:00:00 2001 From: shyam saini <mayhs11saini@gmail.com> Date: Thu, 29 Sep 2016 04:22:20 +0530 Subject: Staging: vt6655: Remove explicit NULL comparison using Coccinelle Remove the explicit NULL comparison and rewrite in a compact form. Signed-off-by: shyam saini <mayhs11saini@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c index 890d108..7e69bc9 100644 --- a/drivers/staging/vt6655/rxtx.c +++ b/drivers/staging/vt6655/rxtx.c @@ -504,7 +504,7 @@ s_uFillDataHead( ) { - if (pTxDataHead == NULL) + if (!pTxDataHead) return 0; @@ -648,7 +648,7 @@ s_vFillRTSHead( { unsigned int uRTSFrameLen = 20; - if (pvRTS == NULL) + if (!pvRTS) return; if (bDisCRC) { @@ -843,7 +843,7 @@ s_vFillCTSHead( { unsigned int uCTSFrameLen = 14; - if (pvCTS == NULL) + if (!pvCTS) return; if (bDisCRC) { @@ -1009,7 +1009,7 @@ s_vGenerateTxParameter( /* Fill RTS */ s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption); - } else if (pvRTS == NULL) {/* RTS_needless, non PCF mode */ + } else if (!pvRTS) {/* RTS_needless, non PCF mode */ struct vnt_rrv_time_ab *buf = pvRrvTime; buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11A, cbFrameSize, wCurrentRate, bNeedACK); -- cgit v0.10.2 From 6315bbdb59bca30b16409aaca8031ce5c41325aa Mon Sep 17 00:00:00 2001 From: Muraru Mihaela <mihaela.muraru21@gmail.com> Date: Thu, 29 Sep 2016 13:09:56 +0300 Subject: Staging : ks7010 : Fix block comments warninig Move final */ to a new line, to conform to the kernel coding style for block comments. Issue found by checkpatch. Signed-off-by: Muraru Mihaela <mihaela.muraru21@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/ks7010/eap_packet.h b/drivers/staging/ks7010/eap_packet.h index 373c0fe..df7f760 100644 --- a/drivers/staging/ks7010/eap_packet.h +++ b/drivers/staging/ks7010/eap_packet.h @@ -53,24 +53,32 @@ enum { EAPOL_KEY_TYPE_RC4 = 1, EAPOL_KEY_TYPE_RSN = 2, struct ieee802_1x_eapol_key { unsigned char type; unsigned short key_length; - /* does not repeat within the life of the keying material used to - * encrypt the Key field; 64-bit NTP timestamp MAY be used here */ + /* + * does not repeat within the life of the keying material used to + * encrypt the Key field; 64-bit NTP timestamp MAY be used here + */ unsigned char replay_counter[IEEE8021X_REPLAY_COUNTER_LEN]; unsigned char key_iv[IEEE8021X_KEY_IV_LEN]; /* cryptographically random number */ - unsigned char key_index; /* key flag in the most significant bit: + unsigned char key_index; /* + * key flag in the most significant bit: * 0 = broadcast (default key), * 1 = unicast (key mapping key); key index is in the - * 7 least significant bits */ - /* HMAC-MD5 message integrity check computed with MS-MPPE-Send-Key as - * the key */ + * 7 least significant bits + */ + /* + * HMAC-MD5 message integrity check computed with MS-MPPE-Send-Key as + * the key + */ unsigned char key_signature[IEEE8021X_KEY_SIGN_LEN]; - /* followed by key: if packet body length = 44 + key length, then the + /* + * followed by key: if packet body length = 44 + key length, then the * key field (of key_length bytes) contains the key in encrypted form; * if packet body length = 44, key field is absent and key_length * represents the number of least significant octets from * MS-MPPE-Send-Key attribute to be used as the keying material; - * RC4 key used in encryption = Key-IV + MS-MPPE-Recv-Key */ + * RC4 key used in encryption = Key-IV + MS-MPPE-Recv-Key + */ } __packed; #define WPA_NONCE_LEN 32 -- cgit v0.10.2 From 37a7029b755b0b82c22a69880106d95ca66af0ba Mon Sep 17 00:00:00 2001 From: Ramiro Oliveira <Ramiro.Oliveira@synopsys.com> Date: Fri, 30 Sep 2016 11:32:05 +0100 Subject: Staging: comedi: Align the * in block comments Align the * on each line of block comments as reported by checkpatch Signed-off-by: Ramiro Oliveira <roliveir@synopsys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 44511d7..a5bf2cc 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -15,7 +15,7 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -*/ + */ #include <linux/device.h> #include <linux/module.h> -- cgit v0.10.2 From f86a180868a92ae57da8a716ec72d5303ba8faaa Mon Sep 17 00:00:00 2001 From: Ramiro Oliveira <Ramiro.Oliveira@synopsys.com> Date: Fri, 30 Sep 2016 15:01:21 +0100 Subject: Staging: fsl-mc: Fix unaligned * in block comments Align the * in some block comments as reported by checkpatch. Signed-off-by: Ramiro Oliveira <roliveir@synopsys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fsl-mc/bus/dpbp.c b/drivers/staging/fsl-mc/bus/dpbp.c index fe271fb..5d4cd81 100644 --- a/drivers/staging/fsl-mc/bus/dpbp.c +++ b/drivers/staging/fsl-mc/bus/dpbp.c @@ -1,34 +1,34 @@ /* Copyright 2013-2016 Freescale Semiconductor Inc. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the above-listed copyright holders nor the -* names of any contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* -* ALTERNATIVELY, this software may be distributed under the terms of the -* GNU General Public License ("GPL") as published by the Free Software -* Foundation, either version 2 of that License or (at your option) any -* later version. -* -* 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 HOLDERS 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. -*/ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the above-listed copyright holders nor the + * names of any contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * 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 HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ #include "../include/mc-sys.h" #include "../include/mc-cmd.h" #include "../include/dpbp.h" diff --git a/drivers/staging/fsl-mc/bus/dpmng.c b/drivers/staging/fsl-mc/bus/dpmng.c index 669f604..96b1d67 100644 --- a/drivers/staging/fsl-mc/bus/dpmng.c +++ b/drivers/staging/fsl-mc/bus/dpmng.c @@ -1,34 +1,34 @@ /* Copyright 2013-2016 Freescale Semiconductor Inc. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the above-listed copyright holders nor the -* names of any contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* -* ALTERNATIVELY, this software may be distributed under the terms of the -* GNU General Public License ("GPL") as published by the Free Software -* Foundation, either version 2 of that License or (at your option) any -* later version. -* -* 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 HOLDERS 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. -*/ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the above-listed copyright holders nor the + * names of any contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * 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 HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ #include "../include/mc-sys.h" #include "../include/mc-cmd.h" #include "../include/dpmng.h" diff --git a/drivers/staging/fsl-mc/bus/dprc.c b/drivers/staging/fsl-mc/bus/dprc.c index ac4ed35..9fea3de 100644 --- a/drivers/staging/fsl-mc/bus/dprc.c +++ b/drivers/staging/fsl-mc/bus/dprc.c @@ -1,34 +1,34 @@ /* Copyright 2013-2016 Freescale Semiconductor Inc. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the above-listed copyright holders nor the -* names of any contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* -* ALTERNATIVELY, this software may be distributed under the terms of the -* GNU General Public License ("GPL") as published by the Free Software -* Foundation, either version 2 of that License or (at your option) any -* later version. -* -* 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 HOLDERS 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. -*/ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the above-listed copyright holders nor the + * names of any contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * 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 HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ #include "../include/mc-sys.h" #include "../include/mc-cmd.h" #include "../include/dprc.h" @@ -1335,20 +1335,20 @@ int dprc_disconnect(struct fsl_mc_io *mc_io, } /** -* dprc_get_connection() - Get connected endpoint and link status if connection -* exists. -* @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 -* @endpoint1: Endpoint 1 configuration parameters -* @endpoint2: Returned endpoint 2 configuration parameters -* @state: Returned link state: -* 1 - link is up; -* 0 - link is down; -* -1 - no connection (endpoint2 information is irrelevant) -* -* Return: '0' on Success; -ENAVAIL if connection does not exist. -*/ + * dprc_get_connection() - Get connected endpoint and link status if connection + * exists. + * @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 + * @endpoint1: Endpoint 1 configuration parameters + * @endpoint2: Returned endpoint 2 configuration parameters + * @state: Returned link state: + * 1 - link is up; + * 0 - link is down; + * -1 - no connection (endpoint2 information is irrelevant) + * + * Return: '0' on Success; -ENAVAIL if connection does not exist. + */ int dprc_get_connection(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c index 3d687b5..4ebc72f 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c @@ -259,8 +259,8 @@ bool fsl_mc_bus_exists(void) EXPORT_SYMBOL_GPL(fsl_mc_bus_exists); /** -* fsl_mc_get_root_dprc - function to traverse to the root dprc -*/ + * fsl_mc_get_root_dprc - function to traverse to the root dprc + */ void fsl_mc_get_root_dprc(struct device *dev, struct device **root_dprc_dev) { diff --git a/drivers/staging/fsl-mc/include/dpbp-cmd.h b/drivers/staging/fsl-mc/include/dpbp-cmd.h index 4828ccd..2860411 100644 --- a/drivers/staging/fsl-mc/include/dpbp-cmd.h +++ b/drivers/staging/fsl-mc/include/dpbp-cmd.h @@ -1,34 +1,34 @@ /* Copyright 2013-2016 Freescale Semiconductor Inc. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the above-listed copyright holders nor the -* names of any contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* -* ALTERNATIVELY, this software may be distributed under the terms of the -* GNU General Public License ("GPL") as published by the Free Software -* Foundation, either version 2 of that License or (at your option) any -* later version. -* -* 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 HOLDERS 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. -*/ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the above-listed copyright holders nor the + * names of any contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * 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 HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ #ifndef _FSL_DPBP_CMD_H #define _FSL_DPBP_CMD_H -- cgit v0.10.2 From cb0b65556eb43b1465672d340be6de07baf85ecf Mon Sep 17 00:00:00 2001 From: Ramiro Oliveira <Ramiro.Oliveira@synopsys.com> Date: Fri, 30 Sep 2016 15:01:22 +0100 Subject: Staging: fsl-mc: Remove blank lines Remove multiple blank lines as reported by checkpatch Signed-off-by: Ramiro Oliveira <roliveir@synopsys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fsl-mc/bus/dpmcp.c b/drivers/staging/fsl-mc/bus/dpmcp.c index bd63baa..55766f7 100644 --- a/drivers/staging/fsl-mc/bus/dpmcp.c +++ b/drivers/staging/fsl-mc/bus/dpmcp.c @@ -369,7 +369,6 @@ int dpmcp_set_irq_mask(struct fsl_mc_io *mc_io, struct mc_command cmd = { 0 }; struct dpmcp_cmd_set_irq_mask *cmd_params; - /* prepare command */ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_SET_IRQ_MASK, cmd_flags, token); diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c index 4ebc72f..44f64b6 100644 --- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c +++ b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c @@ -139,7 +139,6 @@ static struct attribute *fsl_mc_dev_attrs[] = { ATTRIBUTE_GROUPS(fsl_mc_dev); - struct bus_type fsl_mc_bus_type = { .name = "fsl-mc", .match = fsl_mc_bus_match, -- cgit v0.10.2 From 0699715183ad3a7708a72d74e2e09995d6822f1f Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Fri, 30 Sep 2016 21:36:14 +0700 Subject: staging:r8188eu: change rtl8188e_process_phy_info function argument type prframe is (void *), but function used only with (struct recv_frame *). Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c b/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c index 8aea710..fa2cfd5 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c @@ -57,10 +57,9 @@ static void process_link_qual(struct adapter *padapter, signal_stat->avg_val = signal_stat->total_val / signal_stat->total_num; } -void rtl8188e_process_phy_info(struct adapter *padapter, void *prframe) +void rtl8188e_process_phy_info(struct adapter *padapter, + struct recv_frame *precvframe) { - struct recv_frame *precvframe = prframe; - /* Check RSSI */ process_rssi(padapter, precvframe); /* Check EVM */ diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_recv.h b/drivers/staging/rtl8188eu/include/rtl8188e_recv.h index 516c6d7..80832a5 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_recv.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_recv.h @@ -54,7 +54,8 @@ enum rx_packet_type { void rtl8188eu_recv_hdl(struct adapter *padapter, struct recv_buf *precvbuf); void rtl8188eu_recv_tasklet(void *priv); void rtl8188e_query_rx_phy_status(struct recv_frame *fr, struct phy_stat *phy); -void rtl8188e_process_phy_info(struct adapter *padapter, void *prframe); +void rtl8188e_process_phy_info(struct adapter *padapter, + struct recv_frame *prframe); void update_recvframe_phyinfo_88e(struct recv_frame *fra, struct phy_stat *phy); void update_recvframe_attrib_88e(struct recv_frame *fra, struct recv_stat *stat); -- cgit v0.10.2 From 64164d66a36dc6f95aa07c8d56c9a002c3a13f1e Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Fri, 30 Sep 2016 21:36:15 +0700 Subject: staging:r8188eu: remove (RGTRY|BSSID)_(OFT|SZ) macros These macros does not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/drv_types.h b/drivers/staging/rtl8188eu/include/drv_types.h index 5c275fb..c966c8e 100644 --- a/drivers/staging/rtl8188eu/include/drv_types.h +++ b/drivers/staging/rtl8188eu/include/drv_types.h @@ -104,12 +104,6 @@ struct registry_priv { bool monitor_enable; }; -/* For registry parameters */ -#define RGTRY_OFT(field) ((u32)offsetof(struct registry_priv, field)) -#define RGTRY_SZ(field) sizeof(((struct registry_priv *)0)->field) -#define BSSID_OFT(field) ((u32)offsetofT(struct wlan_bssid_ex, field)) -#define BSSID_SZ(field) sizeof(((struct wlan_bssid_ex *)0)->field) - #define MAX_CONTINUAL_URB_ERR 4 struct dvobj_priv { -- cgit v0.10.2 From f34395c83325480cda7f8abfc03f6f52912ea314 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Fri, 30 Sep 2016 21:36:16 +0700 Subject: staging:r8188eu: remove rtw_handle_dualmac declaration It is a declaration of the non-existent function. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/drv_types.h b/drivers/staging/rtl8188eu/include/drv_types.h index c966c8e..32326fd 100644 --- a/drivers/staging/rtl8188eu/include/drv_types.h +++ b/drivers/staging/rtl8188eu/include/drv_types.h @@ -177,8 +177,6 @@ struct adapter { #define adapter_to_dvobj(adapter) (adapter->dvobj) -int rtw_handle_dualmac(struct adapter *adapter, bool init); - static inline u8 *myid(struct eeprom_priv *peepriv) { return peepriv->mac_addr; -- cgit v0.10.2 From 2e2f78d078ca8908a79155b80c16311d06f027be Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Fri, 30 Sep 2016 21:36:17 +0700 Subject: staging:r8188eu: remove pkt_newalloc member of the recv_buf structure This member does not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/rtw_recv.h b/drivers/staging/rtl8188eu/include/rtw_recv.h index 758cd16..49d9738 100644 --- a/drivers/staging/rtl8188eu/include/rtw_recv.h +++ b/drivers/staging/rtl8188eu/include/rtw_recv.h @@ -239,7 +239,6 @@ struct recv_buf { struct recv_frame { struct list_head list; struct sk_buff *pkt; - struct sk_buff *pkt_newalloc; struct adapter *adapter; struct rx_pkt_attrib attrib; uint len; diff --git a/drivers/staging/rtl8188eu/os_dep/recv_linux.c b/drivers/staging/rtl8188eu/os_dep/recv_linux.c index 0c44914..103cdb4 100644 --- a/drivers/staging/rtl8188eu/os_dep/recv_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/recv_linux.c @@ -24,7 +24,6 @@ /* alloc os related resource in struct recv_frame */ void rtw_os_recv_resource_alloc(struct recv_frame *precvframe) { - precvframe->pkt_newalloc = NULL; precvframe->pkt = NULL; } -- cgit v0.10.2 From ae7f7aa0c02bdedd4ff383d3b3fd3bc07cfef2a8 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Fri, 30 Sep 2016 21:36:18 +0700 Subject: staging:r8188eu: remove GEN_CMD_CODE macro GEN_CMD_CODE is redundant macro. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_cmd.c b/drivers/staging/rtl8188eu/core/rtw_cmd.c index e87ab11..f1f4788 100644 --- a/drivers/staging/rtl8188eu/core/rtw_cmd.c +++ b/drivers/staging/rtl8188eu/core/rtw_cmd.c @@ -85,7 +85,7 @@ static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) /* To decide allow or not */ if ((pcmdpriv->padapter->pwrctrlpriv.bHWPwrPindetect) && (!pcmdpriv->padapter->registrypriv.usbss_enable)) { - if (cmd_obj->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) { + if (cmd_obj->cmdcode == _Set_Drv_Extra_CMD_) { struct drvextra_cmd_parm *pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)cmd_obj->parmbuf; if (pdrvextra_cmd_parm->ec_id == POWER_SAVING_CTRL_WK_CID) @@ -93,7 +93,7 @@ static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) } } - if (cmd_obj->cmdcode == GEN_CMD_CODE(_SetChannelPlan)) + if (cmd_obj->cmdcode == _SetChannelPlan_CMD_) bAllow = true; if ((!pcmdpriv->padapter->hw_init_completed && !bAllow) || @@ -271,7 +271,7 @@ u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid, RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("%s: flush network queue\n", __func__)); - init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey)); + init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, _SiteSurvey_CMD_); /* psurveyPara->bsslimit = 48; */ psurveyPara->scan_mode = pmlmepriv->scan_mode; @@ -489,7 +489,7 @@ u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork) pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork);/* get cmdsz before endian conversion */ INIT_LIST_HEAD(&pcmd->list); - pcmd->cmdcode = _JoinBss_CMD_;/* GEN_CMD_CODE(_JoinBss) */ + pcmd->cmdcode = _JoinBss_CMD_; pcmd->parmbuf = (unsigned char *)psecnetwork; pcmd->rsp = NULL; pcmd->rspsz = 0; @@ -684,7 +684,7 @@ u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr) paddbareq_parm->tid = tid; memcpy(paddbareq_parm->addr, addr, ETH_ALEN); - init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, GEN_CMD_CODE(_AddBAReq)); + init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, _AddBAReq_CMD_); /* DBG_88E("rtw_addbareq_cmd, tid =%d\n", tid); */ @@ -722,7 +722,7 @@ u8 rtw_dynamic_chk_wk_cmd(struct adapter *padapter) pdrvextra_cmd_parm->type_size = 0; pdrvextra_cmd_parm->pbuf = (u8 *)padapter; - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); + init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_); /* rtw_enqueue_cmd(pcmdpriv, ph2c); */ @@ -765,7 +765,7 @@ u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue) goto exit; } - init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelPlan_param, GEN_CMD_CODE(_SetChannelPlan)); + init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelPlan_param, _SetChannelPlan_CMD_); res = rtw_enqueue_cmd(pcmdpriv, pcmdobj); } else { /* no need to enqueue, do the cmd hdl directly and free cmd parameter */ @@ -934,7 +934,7 @@ u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue) pdrvextra_cmd_parm->type_size = lps_ctrl_type; pdrvextra_cmd_parm->pbuf = NULL; - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); + init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_); res = rtw_enqueue_cmd(pcmdpriv, ph2c); } else { @@ -976,7 +976,7 @@ u8 rtw_rpt_timer_cfg_cmd(struct adapter *padapter, u16 min_time) pdrvextra_cmd_parm->ec_id = RTP_TIMER_CFG_WK_CID; pdrvextra_cmd_parm->type_size = min_time; pdrvextra_cmd_parm->pbuf = NULL; - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); + init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_); res = rtw_enqueue_cmd(pcmdpriv, ph2c); exit: @@ -1018,7 +1018,7 @@ u8 rtw_antenna_select_cmd(struct adapter *padapter, u8 antenna, u8 enqueue) pdrvextra_cmd_parm->ec_id = ANT_SELECT_WK_CID; pdrvextra_cmd_parm->type_size = antenna; pdrvextra_cmd_parm->pbuf = NULL; - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); + init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_); res = rtw_enqueue_cmd(pcmdpriv, ph2c); } else { @@ -1046,7 +1046,7 @@ u8 rtw_ps_cmd(struct adapter *padapter) pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID; pdrvextra_cmd_parm->pbuf = NULL; - init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); + init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_); return rtw_enqueue_cmd(pcmdpriv, ppscmd); } @@ -1117,7 +1117,7 @@ u8 rtw_chk_hi_queue_cmd(struct adapter *padapter) pdrvextra_cmd_parm->type_size = 0; pdrvextra_cmd_parm->pbuf = NULL; - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); + init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_); res = rtw_enqueue_cmd(pcmdpriv, ph2c); exit: diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index fa8a5ca..baf8606 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -4240,7 +4240,7 @@ void report_survey_event(struct adapter *padapter, INIT_LIST_HEAD(&pcmd_obj->list); - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); + pcmd_obj->cmdcode = _Set_MLME_EVT_CMD_; pcmd_obj->cmdsz = cmdsz; pcmd_obj->parmbuf = pevtcmd; @@ -4290,7 +4290,7 @@ void report_surveydone_event(struct adapter *padapter) INIT_LIST_HEAD(&pcmd_obj->list); - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); + pcmd_obj->cmdcode = _Set_MLME_EVT_CMD_; pcmd_obj->cmdsz = cmdsz; pcmd_obj->parmbuf = pevtcmd; @@ -4334,7 +4334,7 @@ void report_join_res(struct adapter *padapter, int res) INIT_LIST_HEAD(&pcmd_obj->list); - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); + pcmd_obj->cmdcode = _Set_MLME_EVT_CMD_; pcmd_obj->cmdsz = cmdsz; pcmd_obj->parmbuf = pevtcmd; @@ -4385,7 +4385,7 @@ void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsi INIT_LIST_HEAD(&pcmd_obj->list); - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); + pcmd_obj->cmdcode = _Set_MLME_EVT_CMD_; pcmd_obj->cmdsz = cmdsz; pcmd_obj->parmbuf = pevtcmd; @@ -4438,7 +4438,7 @@ void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, int INIT_LIST_HEAD(&pcmd_obj->list); - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); + pcmd_obj->cmdcode = _Set_MLME_EVT_CMD_; pcmd_obj->cmdsz = cmdsz; pcmd_obj->parmbuf = pevtcmd; @@ -4849,7 +4849,7 @@ void survey_timer_hdl(unsigned long data) goto exit_survey_timer_hdl; } - init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey)); + init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, _SiteSurvey_CMD_); rtw_enqueue_cmd(pcmdpriv, ph2c); } @@ -5425,7 +5425,7 @@ u8 set_tx_beacon_cmd(struct adapter *padapter) pmlmeinfo->hidden_ssid_mode); ptxBeacon_parm->IELength += len_diff; - init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon)); + init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, _TX_Beacon_CMD_); res = rtw_enqueue_cmd(pcmdpriv, ph2c); diff --git a/drivers/staging/rtl8188eu/include/rtw_cmd.h b/drivers/staging/rtl8188eu/include/rtw_cmd.h index e8e75f3..18a6530 100644 --- a/drivers/staging/rtl8188eu/include/rtw_cmd.h +++ b/drivers/staging/rtl8188eu/include/rtw_cmd.h @@ -284,8 +284,6 @@ struct SetChannelPlan_param { u8 channel_plan; }; -#define GEN_CMD_CODE(cmd) cmd ## _CMD_ - /* Result: @@ -348,42 +346,42 @@ struct _cmd_callback { }; enum rtw_h2c_cmd { - GEN_CMD_CODE(_JoinBss), - GEN_CMD_CODE(_DisConnect), - GEN_CMD_CODE(_CreateBss), - GEN_CMD_CODE(_SetOpMode), - GEN_CMD_CODE(_SiteSurvey), - GEN_CMD_CODE(_SetAuth), - GEN_CMD_CODE(_SetKey), - GEN_CMD_CODE(_SetStaKey), - GEN_CMD_CODE(_SetAssocSta), - GEN_CMD_CODE(_AddBAReq), - GEN_CMD_CODE(_SetChannel), - GEN_CMD_CODE(_TX_Beacon), - GEN_CMD_CODE(_Set_MLME_EVT), - GEN_CMD_CODE(_Set_Drv_Extra), - GEN_CMD_CODE(_SetChannelPlan), + _JoinBss_CMD_, + _DisConnect_CMD_, + _CreateBss_CMD_, + _SetOpMode_CMD_, + _SiteSurvey_CMD_, + _SetAuth_CMD_, + _SetKey_CMD_, + _SetStaKey_CMD_, + _SetAssocSta_CMD_, + _AddBAReq_CMD_, + _SetChannel_CMD_, + _TX_Beacon_CMD_, + _Set_MLME_EVT_CMD_, + _Set_Drv_Extra_CMD_, + _SetChannelPlan_CMD_, MAX_H2CCMD }; #ifdef _RTW_CMD_C_ static struct _cmd_callback rtw_cmd_callback[] = { - {GEN_CMD_CODE(_JoinBss), &rtw_joinbss_cmd_callback}, - {GEN_CMD_CODE(_DisConnect), &rtw_disassoc_cmd_callback}, - {GEN_CMD_CODE(_CreateBss), &rtw_createbss_cmd_callback}, - {GEN_CMD_CODE(_SetOpMode), NULL}, - {GEN_CMD_CODE(_SiteSurvey), &rtw_survey_cmd_callback}, - {GEN_CMD_CODE(_SetAuth), NULL}, - {GEN_CMD_CODE(_SetKey), NULL}, - {GEN_CMD_CODE(_SetStaKey), &rtw_setstaKey_cmdrsp_callback}, - {GEN_CMD_CODE(_SetAssocSta), &rtw_setassocsta_cmdrsp_callback}, - {GEN_CMD_CODE(_AddBAReq), NULL}, - {GEN_CMD_CODE(_SetChannel), NULL}, - {GEN_CMD_CODE(_TX_Beacon), NULL}, - {GEN_CMD_CODE(_Set_MLME_EVT), NULL}, - {GEN_CMD_CODE(_Set_Drv_Extra), NULL}, - {GEN_CMD_CODE(_SetChannelPlan), NULL}, + {_JoinBss_CMD_, &rtw_joinbss_cmd_callback}, + {_DisConnect_CMD_, &rtw_disassoc_cmd_callback}, + {_CreateBss_CMD_, &rtw_createbss_cmd_callback}, + {_SetOpMode_CMD_, NULL}, + {_SiteSurvey_CMD_, &rtw_survey_cmd_callback}, + {_SetAuth_CMD_, NULL}, + {_SetKey_CMD_, NULL}, + {_SetStaKey_CMD_, &rtw_setstaKey_cmdrsp_callback}, + {_SetAssocSta_CMD_, &rtw_setassocsta_cmdrsp_callback}, + {_AddBAReq_CMD_, NULL}, + {_SetChannel_CMD_, NULL}, + {_TX_Beacon_CMD_, NULL}, + {_Set_MLME_EVT_CMD_, NULL}, + {_Set_Drv_Extra_CMD_, NULL}, + {_SetChannelPlan_CMD_, NULL}, }; #endif -- cgit v0.10.2 From c1300df211b181e0ab9897c4def6b9ec320e8046 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Fri, 30 Sep 2016 21:36:19 +0700 Subject: staging:r8188eu: remove GEN_EVT_CODE macro GEN_EVT_CODE is redundant macro. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index baf8606..fb13df5 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -4249,7 +4249,7 @@ void report_survey_event(struct adapter *padapter, pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); pc2h_evt_hdr->len = sizeof(struct survey_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey); + pc2h_evt_hdr->ID = _Survey_EVT_; pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); psurvey_evt = (struct survey_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); @@ -4299,7 +4299,7 @@ void report_surveydone_event(struct adapter *padapter) pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); pc2h_evt_hdr->len = sizeof(struct surveydone_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone); + pc2h_evt_hdr->ID = _SurveyDone_EVT_; pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); psurveydone_evt = (struct surveydone_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); @@ -4343,7 +4343,7 @@ void report_join_res(struct adapter *padapter, int res) pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); pc2h_evt_hdr->len = sizeof(struct joinbss_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss); + pc2h_evt_hdr->ID = _JoinBss_EVT_; pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); pjoinbss_evt = (struct joinbss_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); @@ -4394,7 +4394,7 @@ void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsi pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); pc2h_evt_hdr->len = sizeof(struct stadel_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA); + pc2h_evt_hdr->ID = _DelSTA_EVT_; pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); pdel_sta_evt = (struct stadel_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); @@ -4447,7 +4447,7 @@ void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, int pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); pc2h_evt_hdr->len = sizeof(struct stassoc_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA); + pc2h_evt_hdr->ID = _AddSTA_EVT_; pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); padd_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); diff --git a/drivers/staging/rtl8188eu/include/rtw_event.h b/drivers/staging/rtl8188eu/include/rtw_event.h index df68948..1c5ebde 100644 --- a/drivers/staging/rtl8188eu/include/rtw_event.h +++ b/drivers/staging/rtl8188eu/include/rtw_event.h @@ -71,8 +71,6 @@ struct stadel_event { int mac_id; }; -#define GEN_EVT_CODE(event) event ## _EVT_ - struct fwevent { u32 parmsize; void (*event_callback)(struct adapter *dev, u8 *pbuf); diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h index 5ee6366..80758e1 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h @@ -667,32 +667,32 @@ void rtw_dummy_event_callback(struct adapter *adapter, u8 *pbuf); void rtw_fwdbg_event_callback(struct adapter *adapter, u8 *pbuf); enum rtw_c2h_event { - GEN_EVT_CODE(_Read_MACREG) = 0, /*0*/ - GEN_EVT_CODE(_Read_BBREG), - GEN_EVT_CODE(_Read_RFREG), - GEN_EVT_CODE(_Read_EEPROM), - GEN_EVT_CODE(_Read_EFUSE), - GEN_EVT_CODE(_Read_CAM), /*5*/ - GEN_EVT_CODE(_Get_BasicRate), - GEN_EVT_CODE(_Get_DataRate), - GEN_EVT_CODE(_Survey), /*8*/ - GEN_EVT_CODE(_SurveyDone), /*9*/ - - GEN_EVT_CODE(_JoinBss), /*10*/ - GEN_EVT_CODE(_AddSTA), - GEN_EVT_CODE(_DelSTA), - GEN_EVT_CODE(_AtimDone), - GEN_EVT_CODE(_TX_Report), - GEN_EVT_CODE(_CCX_Report), /*15*/ - GEN_EVT_CODE(_DTM_Report), - GEN_EVT_CODE(_TX_Rate_Statistics), - GEN_EVT_CODE(_C2HLBK), - GEN_EVT_CODE(_FWDBG), - GEN_EVT_CODE(_C2HFEEDBACK), /*20*/ - GEN_EVT_CODE(_ADDBA), - GEN_EVT_CODE(_C2HBCN), - GEN_EVT_CODE(_ReportPwrState), /* filen: only for PCIE, USB */ - GEN_EVT_CODE(_CloseRF), /* filen: only for PCIE, + _Read_MACREG_EVT_ = 0, /*0*/ + _Read_BBREG_EVT_, + _Read_RFREG_EVT_, + _Read_EEPROM_EVT_, + _Read_EFUSE_EVT_, + _Read_CAM_EVT_, /*5*/ + _Get_BasicRate_EVT_, + _Get_DataRate_EVT_, + _Survey_EVT_, /*8*/ + _SurveyDone_EVT_, /*9*/ + + _JoinBss_EVT_, /*10*/ + _AddSTA_EVT_, + _DelSTA_EVT_, + _AtimDone_EVT_, + _TX_Report_EVT_, + _CCX_Report_EVT_, /*15*/ + _DTM_Report_EVT_, + _TX_Rate_Statistics_EVT_, + _C2HLBK_EVT_, + _FWDBG_EVT_, + _C2HFEEDBACK_EVT_, /*20*/ + _ADDBA_EVT_, + _C2HBCN_EVT_, + _ReportPwrState_EVT_, /* filen: only for PCIE, USB */ + _CloseRF_EVT_, /* filen: only for PCIE, * work around ASPM */ MAX_C2HEVT }; -- cgit v0.10.2 From d88dd94e24cf45d519f93b4ad07922441ebb5cb3 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Fri, 30 Sep 2016 21:36:20 +0700 Subject: staging:r8188eu: remove GEN_DRV_CMD_HANDLER macro This macro does not used. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h index 80758e1..872a531 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h @@ -625,7 +625,6 @@ u8 led_blink_hdl(struct adapter *padapter, unsigned char *pbuf); u8 set_csa_hdl(struct adapter *padapter, unsigned char *pbuf); u8 tdls_hdl(struct adapter *padapter, unsigned char *pbuf); -#define GEN_DRV_CMD_HANDLER(size, cmd) {size, &cmd ## _hdl}, #define GEN_MLME_EXT_HANDLER(size, cmd) {size, cmd}, #ifdef _RTW_CMD_C_ -- cgit v0.10.2 From 612e1c94bfe9736cef0a9b86db792fd863be7733 Mon Sep 17 00:00:00 2001 From: Ivan Safonov <insafonov@gmail.com> Date: Fri, 30 Sep 2016 21:36:21 +0700 Subject: staging:r8188eu: remove GEN_MLME_EXT_HANDLER macro GEN_MLME_EXT_HANDLER is redundant macro. Signed-off-by: Ivan Safonov <insafonov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h index 872a531..1b1caaf 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h @@ -625,26 +625,24 @@ u8 led_blink_hdl(struct adapter *padapter, unsigned char *pbuf); u8 set_csa_hdl(struct adapter *padapter, unsigned char *pbuf); u8 tdls_hdl(struct adapter *padapter, unsigned char *pbuf); -#define GEN_MLME_EXT_HANDLER(size, cmd) {size, cmd}, - #ifdef _RTW_CMD_C_ static struct cmd_hdl wlancmds[] = { - GEN_MLME_EXT_HANDLER(sizeof(struct wlan_bssid_ex), join_cmd_hdl) - GEN_MLME_EXT_HANDLER(sizeof(struct disconnect_parm), disconnect_hdl) - GEN_MLME_EXT_HANDLER(sizeof(struct wlan_bssid_ex), createbss_hdl) - GEN_MLME_EXT_HANDLER(sizeof(struct setopmode_parm), setopmode_hdl) - GEN_MLME_EXT_HANDLER(sizeof(struct sitesurvey_parm), sitesurvey_cmd_hdl) - GEN_MLME_EXT_HANDLER(sizeof(struct setauth_parm), setauth_hdl) - GEN_MLME_EXT_HANDLER(sizeof(struct setkey_parm), setkey_hdl) - GEN_MLME_EXT_HANDLER(sizeof(struct set_stakey_parm), set_stakey_hdl) - GEN_MLME_EXT_HANDLER(sizeof(struct set_assocsta_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct addBaReq_parm), add_ba_hdl) - GEN_MLME_EXT_HANDLER(sizeof(struct set_ch_parm), set_ch_hdl) - GEN_MLME_EXT_HANDLER(sizeof(struct wlan_bssid_ex), tx_beacon_hdl) - GEN_MLME_EXT_HANDLER(0, mlme_evt_hdl) - GEN_MLME_EXT_HANDLER(0, rtw_drvextra_cmd_hdl) - GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelPlan_param), set_chplan_hdl) + {sizeof(struct wlan_bssid_ex), join_cmd_hdl}, + {sizeof(struct disconnect_parm), disconnect_hdl}, + {sizeof(struct wlan_bssid_ex), createbss_hdl}, + {sizeof(struct setopmode_parm), setopmode_hdl}, + {sizeof(struct sitesurvey_parm), sitesurvey_cmd_hdl}, + {sizeof(struct setauth_parm), setauth_hdl}, + {sizeof(struct setkey_parm), setkey_hdl}, + {sizeof(struct set_stakey_parm), set_stakey_hdl}, + {sizeof(struct set_assocsta_parm), NULL}, + {sizeof(struct addBaReq_parm), add_ba_hdl}, + {sizeof(struct set_ch_parm), set_ch_hdl}, + {sizeof(struct wlan_bssid_ex), tx_beacon_hdl}, + {0, mlme_evt_hdl}, + {0, rtw_drvextra_cmd_hdl}, + {sizeof(struct SetChannelPlan_param), set_chplan_hdl} }; #endif -- cgit v0.10.2 From 23bf40424a0f641ca7ff4225add4aa592086bdd5 Mon Sep 17 00:00:00 2001 From: Wei Yongjun <weiyj.lk@gmail.com> Date: Sat, 1 Oct 2016 00:38:08 +0800 Subject: staging: rtl8188eu: fix double unlock error in rtw_resume_process() Fix following static checker warning: drivers/staging/rtl8188eu/os_dep/usb_intf.c:311 rtw_resume_process() error: double unlock 'mutex:&pwrpriv->mutex_lock' Fixes: eaf47b713b60 ("staging: rtl8188eu: fix missing unlock on error in rtw_resume_process()") Reported-By: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Wei Yongjun <weiyj.lk@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c index b2bc09e..68e1e6b 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c @@ -294,8 +294,10 @@ static int rtw_resume_process(struct adapter *padapter) pwrpriv->bkeepfwalive = false; pr_debug("bkeepfwalive(%x)\n", pwrpriv->bkeepfwalive); - if (pm_netdev_open(pnetdev, true) != 0) + if (pm_netdev_open(pnetdev, true) != 0) { + mutex_unlock(&pwrpriv->mutex_lock); goto exit; + } netif_device_attach(pnetdev); netif_carrier_on(pnetdev); @@ -306,10 +308,8 @@ static int rtw_resume_process(struct adapter *padapter) ret = 0; exit: - if (pwrpriv) { + if (pwrpriv) pwrpriv->bInSuspend = false; - mutex_unlock(&pwrpriv->mutex_lock); - } pr_debug("<=== %s return %d.............. in %dms\n", __func__, ret, jiffies_to_msecs(jiffies - start_time)); -- cgit v0.10.2 From fc1e2c8ea85e109acf09e74789e9b852f6eed251 Mon Sep 17 00:00:00 2001 From: Ksenija Stanojevic <ksenija.stanojevic@gmail.com> Date: Sun, 2 Oct 2016 17:42:35 +0200 Subject: Staging: fbtft: Fix bug in fbtft-core Commit 367e8560e8d7a62d96e9b1d644028a3816e04206 introduced a bug in fbtft-core where fps is always 0, this is because variable update_time is not assigned correctly. Signed-off-by: Ksenija Stanojevic <ksenija.stanojevic@gmail.com> Fixes: 367e8560e8d7 ("Staging: fbtbt: Replace timespec with ktime_t") Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c index d9046162..587f68a 100644 --- a/drivers/staging/fbtft/fbtft-core.c +++ b/drivers/staging/fbtft/fbtft-core.c @@ -391,11 +391,11 @@ static void fbtft_update_display(struct fbtft_par *par, unsigned int start_line, if (unlikely(timeit)) { ts_end = ktime_get(); - if (ktime_to_ns(par->update_time)) + if (!ktime_to_ns(par->update_time)) par->update_time = ts_start; - par->update_time = ts_start; fps = ktime_us_delta(ts_start, par->update_time); + par->update_time = ts_start; fps = fps ? 1000000 / fps : 0; throughput = ktime_us_delta(ts_end, ts_start); -- cgit v0.10.2